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:
authorCampbell Barton <ideasman42@gmail.com>2019-04-17 07:17:24 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-04-17 07:21:24 +0300
commite12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch)
tree8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/editors
parentb3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff)
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/CMakeLists.txt88
-rw-r--r--source/blender/editors/animation/CMakeLists.txt68
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c6705
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c5042
-rw-r--r--source/blender/editors/animation/anim_deps.c623
-rw-r--r--source/blender/editors/animation/anim_draw.c986
-rw-r--r--source/blender/editors/animation/anim_filter.c5702
-rw-r--r--source/blender/editors/animation/anim_intern.h3
-rw-r--r--source/blender/editors/animation/anim_ipo_utils.c322
-rw-r--r--source/blender/editors/animation/anim_markers.c2156
-rw-r--r--source/blender/editors/animation/anim_motion_paths.c483
-rw-r--r--source/blender/editors/animation/anim_ops.c683
-rw-r--r--source/blender/editors/animation/drivers.c1788
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c1495
-rw-r--r--source/blender/editors/animation/keyframes_draw.c1681
-rw-r--r--source/blender/editors/animation/keyframes_edit.c1808
-rw-r--r--source/blender/editors/animation/keyframes_general.c1678
-rw-r--r--source/blender/editors/animation/keyframing.c4648
-rw-r--r--source/blender/editors/animation/keyingsets.c1522
-rw-r--r--source/blender/editors/armature/CMakeLists.txt72
-rw-r--r--source/blender/editors/armature/armature_add.c1919
-rw-r--r--source/blender/editors/armature/armature_edit.c2864
-rw-r--r--source/blender/editors/armature/armature_intern.h109
-rw-r--r--source/blender/editors/armature/armature_naming.c871
-rw-r--r--source/blender/editors/armature/armature_ops.c295
-rw-r--r--source/blender/editors/armature/armature_relations.c1498
-rw-r--r--source/blender/editors/armature/armature_select.c3046
-rw-r--r--source/blender/editors/armature/armature_skinning.c789
-rw-r--r--source/blender/editors/armature/armature_utils.c1187
-rw-r--r--source/blender/editors/armature/editarmature_undo.c241
-rw-r--r--source/blender/editors/armature/meshlaplacian.c2581
-rw-r--r--source/blender/editors/armature/meshlaplacian.h16
-rw-r--r--source/blender/editors/armature/pose_edit.c1558
-rw-r--r--source/blender/editors/armature/pose_group.c693
-rw-r--r--source/blender/editors/armature/pose_lib.c2881
-rw-r--r--source/blender/editors/armature/pose_select.c1802
-rw-r--r--source/blender/editors/armature/pose_slide.c2827
-rw-r--r--source/blender/editors/armature/pose_transform.c1591
-rw-r--r--source/blender/editors/armature/pose_utils.c498
-rw-r--r--source/blender/editors/curve/CMakeLists.txt56
-rw-r--r--source/blender/editors/curve/curve_intern.h57
-rw-r--r--source/blender/editors/curve/curve_ops.c230
-rw-r--r--source/blender/editors/curve/editcurve.c12123
-rw-r--r--source/blender/editors/curve/editcurve_add.c1260
-rw-r--r--source/blender/editors/curve/editcurve_paint.c1981
-rw-r--r--source/blender/editors/curve/editcurve_select.c3271
-rw-r--r--source/blender/editors/curve/editcurve_undo.c380
-rw-r--r--source/blender/editors/curve/editfont.c3180
-rw-r--r--source/blender/editors/curve/editfont_undo.c394
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt1582
-rw-r--r--source/blender/editors/gizmo_library/CMakeLists.txt66
-rw-r--r--source/blender/editors/gizmo_library/geometry/geom_arrow_gizmo.c138
-rw-r--r--source/blender/editors/gizmo_library/geometry/geom_cube_gizmo.c56
-rw-r--r--source/blender/editors/gizmo_library/geometry/geom_dial_gizmo.c1031
-rw-r--r--source/blender/editors/gizmo_library/gizmo_draw_utils.c78
-rw-r--r--source/blender/editors/gizmo_library/gizmo_geometry.h13
-rw-r--r--source/blender/editors/gizmo_library/gizmo_group_types/value2d_gizmo_group.c153
-rw-r--r--source/blender/editors/gizmo_library/gizmo_library_intern.h97
-rw-r--r--source/blender/editors/gizmo_library/gizmo_library_presets.c120
-rw-r--r--source/blender/editors/gizmo_library/gizmo_library_utils.c329
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/arrow2d_gizmo.c229
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c641
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c34
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c401
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c1925
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c1011
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c955
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c648
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/primitive3d_gizmo.c165
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/value2d_gizmo.c188
-rw-r--r--source/blender/editors/gpencil/CMakeLists.txt78
-rw-r--r--source/blender/editors/gpencil/annotate_draw.c1924
-rw-r--r--source/blender/editors/gpencil/annotate_paint.c4191
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c1850
-rw-r--r--source/blender/editors/gpencil/editaction_gpencil.c852
-rw-r--r--source/blender/editors/gpencil/gpencil_add_monkey.c2099
-rw-r--r--source/blender/editors/gpencil/gpencil_add_stroke.c321
-rw-r--r--source/blender/editors/gpencil/gpencil_armature.c1113
-rw-r--r--source/blender/editors/gpencil/gpencil_brush.c3502
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c2816
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c4192
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c7454
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c2485
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h551
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c1931
-rw-r--r--source/blender/editors/gpencil/gpencil_merge.c909
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c450
-rw-r--r--source/blender/editors/gpencil/gpencil_ops_versioning.c267
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c6758
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c3081
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c2296
-rw-r--r--source/blender/editors/gpencil/gpencil_undo.c207
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c3928
-rw-r--r--source/blender/editors/include/BIF_gl.h12
-rw-r--r--source/blender/editors/include/BIF_glutil.h118
-rw-r--r--source/blender/editors/include/ED_anim_api.h766
-rw-r--r--source/blender/editors/include/ED_armature.h275
-rw-r--r--source/blender/editors/include/ED_clip.h23
-rw-r--r--source/blender/editors/include/ED_curve.h45
-rw-r--r--source/blender/editors/include/ED_fileselect.h90
-rw-r--r--source/blender/editors/include/ED_gizmo_library.h233
-rw-r--r--source/blender/editors/include/ED_gizmo_utils.h18
-rw-r--r--source/blender/editors/include/ED_gpencil.h180
-rw-r--r--source/blender/editors/include/ED_image.h62
-rw-r--r--source/blender/editors/include/ED_info.h4
-rw-r--r--source/blender/editors/include/ED_keyframes_draw.h241
-rw-r--r--source/blender/editors/include/ED_keyframes_edit.h254
-rw-r--r--source/blender/editors/include/ED_keyframing.h280
-rw-r--r--source/blender/editors/include/ED_lattice.h5
-rw-r--r--source/blender/editors/include/ED_markers.h9
-rw-r--r--source/blender/editors/include/ED_mask.h55
-rw-r--r--source/blender/editors/include/ED_mball.h17
-rw-r--r--source/blender/editors/include/ED_mesh.h381
-rw-r--r--source/blender/editors/include/ED_node.h25
-rw-r--r--source/blender/editors/include/ED_numinput.h73
-rw-r--r--source/blender/editors/include/ED_object.h364
-rw-r--r--source/blender/editors/include/ED_paint.h3
-rw-r--r--source/blender/editors/include/ED_particle.h19
-rw-r--r--source/blender/editors/include/ED_physics.h12
-rw-r--r--source/blender/editors/include/ED_render.h31
-rw-r--r--source/blender/editors/include/ED_scene.h20
-rw-r--r--source/blender/editors/include/ED_screen.h427
-rw-r--r--source/blender/editors/include/ED_screen_types.h116
-rw-r--r--source/blender/editors/include/ED_sculpt.h5
-rw-r--r--source/blender/editors/include/ED_select_utils.h35
-rw-r--r--source/blender/editors/include/ED_sequencer.h8
-rw-r--r--source/blender/editors/include/ED_space_api.h9
-rw-r--r--source/blender/editors/include/ED_text.h5
-rw-r--r--source/blender/editors/include/ED_transform.h240
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h164
-rw-r--r--source/blender/editors/include/ED_transverts.h40
-rw-r--r--source/blender/editors/include/ED_types.h6
-rw-r--r--source/blender/editors/include/ED_undo.h47
-rw-r--r--source/blender/editors/include/ED_userpref.h2
-rw-r--r--source/blender/editors/include/ED_util.h15
-rw-r--r--source/blender/editors/include/ED_uvedit.h199
-rw-r--r--source/blender/editors/include/ED_view3d.h789
-rw-r--r--source/blender/editors/include/UI_icons.h70
-rw-r--r--source/blender/editors/include/UI_interface.h2340
-rw-r--r--source/blender/editors/include/UI_interface_icons.h34
-rw-r--r--source/blender/editors/include/UI_resources.h604
-rw-r--r--source/blender/editors/include/UI_view2d.h210
-rw-r--r--source/blender/editors/interface/CMakeLists.txt128
-rw-r--r--source/blender/editors/interface/interface.c9467
-rw-r--r--source/blender/editors/interface/interface_align.c1152
-rw-r--r--source/blender/editors/interface/interface_anim.c538
-rw-r--r--source/blender/editors/interface/interface_context_menu.c1703
-rw-r--r--source/blender/editors/interface/interface_draw.c4246
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c147
-rw-r--r--source/blender/editors/interface/interface_eyedropper_color.c450
-rw-r--r--source/blender/editors/interface/interface_eyedropper_colorband.c477
-rw-r--r--source/blender/editors/interface/interface_eyedropper_datablock.c409
-rw-r--r--source/blender/editors/interface/interface_eyedropper_depth.c510
-rw-r--r--source/blender/editors/interface/interface_eyedropper_driver.c284
-rw-r--r--source/blender/editors/interface/interface_eyedropper_intern.h24
-rw-r--r--source/blender/editors/interface/interface_handlers.c17190
-rw-r--r--source/blender/editors/interface/interface_icons.c3160
-rw-r--r--source/blender/editors/interface/interface_icons_event.c382
-rw-r--r--source/blender/editors/interface/interface_intern.h1005
-rw-r--r--source/blender/editors/interface/interface_layout.c8034
-rw-r--r--source/blender/editors/interface/interface_ops.c2363
-rw-r--r--source/blender/editors/interface/interface_panel.c4248
-rw-r--r--source/blender/editors/interface/interface_query.c595
-rw-r--r--source/blender/editors/interface/interface_region_color_picker.c1239
-rw-r--r--source/blender/editors/interface/interface_region_hud.c473
-rw-r--r--source/blender/editors/interface/interface_region_menu_pie.c496
-rw-r--r--source/blender/editors/interface/interface_region_menu_popup.c921
-rw-r--r--source/blender/editors/interface/interface_region_popover.c538
-rw-r--r--source/blender/editors/interface/interface_region_popup.c1328
-rw-r--r--source/blender/editors/interface/interface_region_search.c1275
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c2257
-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.c878
-rw-r--r--source/blender/editors/interface/interface_templates.c10223
-rw-r--r--source/blender/editors/interface/interface_utils.c1056
-rw-r--r--source/blender/editors/interface/interface_widgets.c8403
-rw-r--r--source/blender/editors/interface/resources.c2170
-rw-r--r--source/blender/editors/interface/view2d.c4461
-rw-r--r--source/blender/editors/interface/view2d_ops.c3333
-rw-r--r--source/blender/editors/io/CMakeLists.txt68
-rw-r--r--source/blender/editors/io/io_alembic.c1013
-rw-r--r--source/blender/editors/io/io_cache.c156
-rw-r--r--source/blender/editors/io/io_collada.c1306
-rw-r--r--source/blender/editors/io/io_ops.c16
-rw-r--r--source/blender/editors/lattice/CMakeLists.txt30
-rw-r--r--source/blender/editors/lattice/editlattice_select.c963
-rw-r--r--source/blender/editors/lattice/editlattice_tools.c531
-rw-r--r--source/blender/editors/lattice/editlattice_undo.c225
-rw-r--r--source/blender/editors/lattice/lattice_intern.h3
-rw-r--r--source/blender/editors/lattice/lattice_ops.c20
-rw-r--r--source/blender/editors/mask/CMakeLists.txt40
-rw-r--r--source/blender/editors/mask/mask_add.c1448
-rw-r--r--source/blender/editors/mask/mask_draw.c1311
-rw-r--r--source/blender/editors/mask/mask_edit.c849
-rw-r--r--source/blender/editors/mask/mask_editaction.c353
-rw-r--r--source/blender/editors/mask/mask_intern.h30
-rw-r--r--source/blender/editors/mask/mask_ops.c3814
-rw-r--r--source/blender/editors/mask/mask_relationships.c251
-rw-r--r--source/blender/editors/mask/mask_select.c1324
-rw-r--r--source/blender/editors/mask/mask_shapekey.c663
-rw-r--r--source/blender/editors/mesh/CMakeLists.txt104
-rw-r--r--source/blender/editors/mesh/editface.c1060
-rw-r--r--source/blender/editors/mesh/editmesh_add.c1009
-rw-r--r--source/blender/editors/mesh/editmesh_add_gizmo.c491
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c1575
-rw-r--r--source/blender/editors/mesh/editmesh_bisect.c1139
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c1262
-rw-r--r--source/blender/editors/mesh/editmesh_extrude_screw.c308
-rw-r--r--source/blender/editors/mesh/editmesh_extrude_spin.c291
-rw-r--r--source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c1640
-rw-r--r--source/blender/editors/mesh/editmesh_inset.c999
-rw-r--r--source/blender/editors/mesh/editmesh_intersect.c1538
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c4918
-rw-r--r--source/blender/editors/mesh/editmesh_knife_project.c219
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c1130
-rw-r--r--source/blender/editors/mesh/editmesh_path.c1282
-rw-r--r--source/blender/editors/mesh/editmesh_polybuild.c680
-rw-r--r--source/blender/editors/mesh/editmesh_preselect_edgering.c465
-rw-r--r--source/blender/editors/mesh/editmesh_preselect_elem.c224
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c1811
-rw-r--r--source/blender/editors/mesh/editmesh_rip_edge.c348
-rw-r--r--source/blender/editors/mesh/editmesh_select.c7811
-rw-r--r--source/blender/editors/mesh/editmesh_select_similar.c2301
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c13785
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c1095
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c2256
-rw-r--r--source/blender/editors/mesh/mesh_data.c1651
-rw-r--r--source/blender/editors/mesh/mesh_intern.h39
-rw-r--r--source/blender/editors/mesh/mesh_mirror.c593
-rw-r--r--source/blender/editors/mesh/mesh_ops.c539
-rw-r--r--source/blender/editors/mesh/meshtools.c2250
-rw-r--r--source/blender/editors/metaball/CMakeLists.txt28
-rw-r--r--source/blender/editors/metaball/editmball_undo.c259
-rw-r--r--source/blender/editors/metaball/mball_edit.c1289
-rw-r--r--source/blender/editors/metaball/mball_intern.h1
-rw-r--r--source/blender/editors/metaball/mball_ops.c35
-rw-r--r--source/blender/editors/object/CMakeLists.txt96
-rw-r--r--source/blender/editors/object/object_add.c3846
-rw-r--r--source/blender/editors/object/object_bake.c870
-rw-r--r--source/blender/editors/object/object_bake_api.c2807
-rw-r--r--source/blender/editors/object/object_collection.c857
-rw-r--r--source/blender/editors/object/object_constraint.c3109
-rw-r--r--source/blender/editors/object/object_data_transfer.c1340
-rw-r--r--source/blender/editors/object/object_edit.c2541
-rw-r--r--source/blender/editors/object/object_facemap_ops.c645
-rw-r--r--source/blender/editors/object/object_gpencil_modifier.c754
-rw-r--r--source/blender/editors/object/object_hook.c1475
-rw-r--r--source/blender/editors/object/object_intern.h10
-rw-r--r--source/blender/editors/object/object_modes.c363
-rw-r--r--source/blender/editors/object/object_modifier.c3329
-rw-r--r--source/blender/editors/object/object_ops.c482
-rw-r--r--source/blender/editors/object/object_random.c218
-rw-r--r--source/blender/editors/object/object_relations.c4314
-rw-r--r--source/blender/editors/object/object_select.c2060
-rw-r--r--source/blender/editors/object/object_shader_fx.c505
-rw-r--r--source/blender/editors/object/object_shapekey.c652
-rw-r--r--source/blender/editors/object/object_transform.c2947
-rw-r--r--source/blender/editors/object/object_utils.c181
-rw-r--r--source/blender/editors/object/object_vgroup.c6626
-rw-r--r--source/blender/editors/object/object_warp.c441
-rw-r--r--source/blender/editors/physics/CMakeLists.txt84
-rw-r--r--source/blender/editors/physics/dynamicpaint_ops.c746
-rw-r--r--source/blender/editors/physics/particle_boids.c422
-rw-r--r--source/blender/editors/physics/particle_edit.c8199
-rw-r--r--source/blender/editors/physics/particle_edit_undo.c364
-rw-r--r--source/blender/editors/physics/particle_edit_utildefines.h48
-rw-r--r--source/blender/editors/physics/particle_object.c1916
-rw-r--r--source/blender/editors/physics/physics_fluid.c1832
-rw-r--r--source/blender/editors/physics/physics_intern.h13
-rw-r--r--source/blender/editors/physics/physics_ops.c186
-rw-r--r--source/blender/editors/physics/physics_pointcache.c487
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c220
-rw-r--r--source/blender/editors/physics/rigidbody_object.c818
-rw-r--r--source/blender/editors/physics/rigidbody_world.c182
-rw-r--r--source/blender/editors/render/CMakeLists.txt62
-rw-r--r--source/blender/editors/render/render_intern.h2
-rw-r--r--source/blender/editors/render/render_internal.c1792
-rw-r--r--source/blender/editors/render/render_opengl.c1879
-rw-r--r--source/blender/editors/render/render_ops.c92
-rw-r--r--source/blender/editors/render/render_preview.c2221
-rw-r--r--source/blender/editors/render/render_shading.c2551
-rw-r--r--source/blender/editors/render/render_update.c387
-rw-r--r--source/blender/editors/render/render_view.c521
-rw-r--r--source/blender/editors/scene/CMakeLists.txt24
-rw-r--r--source/blender/editors/scene/scene_edit.c288
-rw-r--r--source/blender/editors/screen/CMakeLists.txt64
-rw-r--r--source/blender/editors/screen/area.c5138
-rw-r--r--source/blender/editors/screen/area_utils.c58
-rw-r--r--source/blender/editors/screen/glutil.c1017
-rw-r--r--source/blender/editors/screen/screen_context.c1302
-rw-r--r--source/blender/editors/screen/screen_draw.c829
-rw-r--r--source/blender/editors/screen/screen_edit.c2422
-rw-r--r--source/blender/editors/screen/screen_geometry.c678
-rw-r--r--source/blender/editors/screen/screen_intern.h83
-rw-r--r--source/blender/editors/screen/screen_ops.c6827
-rw-r--r--source/blender/editors/screen/screen_user_menu.c351
-rw-r--r--source/blender/editors/screen/screendump.c343
-rw-r--r--source/blender/editors/screen/workspace_edit.c714
-rw-r--r--source/blender/editors/screen/workspace_layout_edit.c225
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt84
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c1934
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve.c1125
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve_undo.c122
-rw-r--r--source/blender/editors/sculpt_paint/paint_hide.c700
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c1787
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c3129
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c10715
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_undo.c806
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h259
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c795
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c1609
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c2126
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c1093
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c5580
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_color_ops.c743
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_color_utils.c921
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_proj.c260
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c1326
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c363
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c9838
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h459
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c1792
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c1512
-rw-r--r--source/blender/editors/sound/CMakeLists.txt40
-rw-r--r--source/blender/editors/sound/sound_intern.h2
-rw-r--r--source/blender/editors/sound/sound_ops.c1201
-rw-r--r--source/blender/editors/space_action/CMakeLists.txt42
-rw-r--r--source/blender/editors/space_action/action_buttons.c82
-rw-r--r--source/blender/editors/space_action/action_data.c1427
-rw-r--r--source/blender/editors/space_action/action_draw.c939
-rw-r--r--source/blender/editors/space_action/action_edit.c2556
-rw-r--r--source/blender/editors/space_action/action_intern.h30
-rw-r--r--source/blender/editors/space_action/action_ops.c138
-rw-r--r--source/blender/editors/space_action/action_select.c2605
-rw-r--r--source/blender/editors/space_action/space_action.c1445
-rw-r--r--source/blender/editors/space_api/CMakeLists.txt58
-rw-r--r--source/blender/editors/space_api/spacetypes.c377
-rw-r--r--source/blender/editors/space_buttons/CMakeLists.txt36
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c2001
-rw-r--r--source/blender/editors/space_buttons/buttons_intern.h40
-rw-r--r--source/blender/editors/space_buttons/buttons_ops.c408
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c867
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c1175
-rw-r--r--source/blender/editors/space_clip/CMakeLists.txt78
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c1182
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_draw.c695
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_ops.c242
-rw-r--r--source/blender/editors/space_clip/clip_draw.c3076
-rw-r--r--source/blender/editors/space_clip/clip_editor.c1566
-rw-r--r--source/blender/editors/space_clip/clip_graph_draw.c487
-rw-r--r--source/blender/editors/space_clip/clip_graph_ops.c1002
-rw-r--r--source/blender/editors/space_clip/clip_intern.h74
-rw-r--r--source/blender/editors/space_clip/clip_ops.c1978
-rw-r--r--source/blender/editors/space_clip/clip_toolbar.c130
-rw-r--r--source/blender/editors/space_clip/clip_utils.c398
-rw-r--r--source/blender/editors/space_clip/space_clip.c2030
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c3333
-rw-r--r--source/blender/editors/space_clip/tracking_ops_detect.c203
-rw-r--r--source/blender/editors/space_clip/tracking_ops_intern.h3
-rw-r--r--source/blender/editors/space_clip/tracking_ops_orient.c1374
-rw-r--r--source/blender/editors/space_clip/tracking_ops_plane.c584
-rw-r--r--source/blender/editors/space_clip/tracking_ops_solve.c460
-rw-r--r--source/blender/editors/space_clip/tracking_ops_stabilize.c421
-rw-r--r--source/blender/editors/space_clip/tracking_ops_track.c707
-rw-r--r--source/blender/editors/space_clip/tracking_ops_utils.c46
-rw-r--r--source/blender/editors/space_clip/tracking_select.c1440
-rw-r--r--source/blender/editors/space_console/CMakeLists.txt36
-rw-r--r--source/blender/editors/space_console/console_draw.c272
-rw-r--r--source/blender/editors/space_console/console_intern.h10
-rw-r--r--source/blender/editors/space_console/console_ops.c1688
-rw-r--r--source/blender/editors/space_console/space_console.c361
-rw-r--r--source/blender/editors/space_file/CMakeLists.txt76
-rw-r--r--source/blender/editors/space_file/file_draw.c1400
-rw-r--r--source/blender/editors/space_file/file_intern.h15
-rw-r--r--source/blender/editors/space_file/file_ops.c3601
-rw-r--r--source/blender/editors/space_file/file_panels.c83
-rw-r--r--source/blender/editors/space_file/file_utils.c16
-rw-r--r--source/blender/editors/space_file/filelist.c4156
-rw-r--r--source/blender/editors/space_file/filelist.h154
-rw-r--r--source/blender/editors/space_file/filesel.c1214
-rw-r--r--source/blender/editors/space_file/fsmenu.c1156
-rw-r--r--source/blender/editors/space_file/fsmenu.h27
-rw-r--r--source/blender/editors/space_file/space_file.c1024
-rw-r--r--source/blender/editors/space_graph/CMakeLists.txt60
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c2121
-rw-r--r--source/blender/editors/space_graph/graph_draw.c2040
-rw-r--r--source/blender/editors/space_graph/graph_edit.c4155
-rw-r--r--source/blender/editors/space_graph/graph_intern.h52
-rw-r--r--source/blender/editors/space_graph/graph_ops.c712
-rw-r--r--source/blender/editors/space_graph/graph_select.c2395
-rw-r--r--source/blender/editors/space_graph/graph_utils.c402
-rw-r--r--source/blender/editors/space_graph/space_graph.c1424
-rw-r--r--source/blender/editors/space_image/CMakeLists.txt62
-rw-r--r--source/blender/editors/space_image/image_buttons.c2287
-rw-r--r--source/blender/editors/space_image/image_draw.c1501
-rw-r--r--source/blender/editors/space_image/image_edit.c555
-rw-r--r--source/blender/editors/space_image/image_intern.h1
-rw-r--r--source/blender/editors/space_image/image_ops.c5789
-rw-r--r--source/blender/editors/space_image/space_image.c1559
-rw-r--r--source/blender/editors/space_info/CMakeLists.txt52
-rw-r--r--source/blender/editors/space_info/info_draw.c314
-rw-r--r--source/blender/editors/space_info/info_intern.h6
-rw-r--r--source/blender/editors/space_info/info_ops.c722
-rw-r--r--source/blender/editors/space_info/info_report.c481
-rw-r--r--source/blender/editors/space_info/info_stats.c862
-rw-r--r--source/blender/editors/space_info/space_info.c358
-rw-r--r--source/blender/editors/space_info/textview.c606
-rw-r--r--source/blender/editors/space_info/textview.h63
-rw-r--r--source/blender/editors/space_nla/CMakeLists.txt48
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c855
-rw-r--r--source/blender/editors/space_nla/nla_channels.c1343
-rw-r--r--source/blender/editors/space_nla/nla_draw.c1494
-rw-r--r--source/blender/editors/space_nla/nla_edit.c3996
-rw-r--r--source/blender/editors/space_nla/nla_intern.h22
-rw-r--r--source/blender/editors/space_nla/nla_ops.c189
-rw-r--r--source/blender/editors/space_nla/nla_select.c984
-rw-r--r--source/blender/editors/space_nla/space_nla.c985
-rw-r--r--source/blender/editors/space_node/CMakeLists.txt74
-rw-r--r--source/blender/editors/space_node/drawnode.c5731
-rw-r--r--source/blender/editors/space_node/node_add.c806
-rw-r--r--source/blender/editors/space_node/node_buttons.c290
-rw-r--r--source/blender/editors/space_node/node_draw.c2757
-rw-r--r--source/blender/editors/space_node/node_edit.c3954
-rw-r--r--source/blender/editors/space_node/node_gizmo.c769
-rw-r--r--source/blender/editors/space_node/node_group.c1720
-rw-r--r--source/blender/editors/space_node/node_intern.h127
-rw-r--r--source/blender/editors/space_node/node_ops.c279
-rw-r--r--source/blender/editors/space_node/node_relationships.c3145
-rw-r--r--source/blender/editors/space_node/node_select.c1670
-rw-r--r--source/blender/editors/space_node/node_templates.c1327
-rw-r--r--source/blender/editors/space_node/node_toolbar.c33
-rw-r--r--source/blender/editors/space_node/node_view.c894
-rw-r--r--source/blender/editors/space_node/space_node.c1558
-rw-r--r--source/blender/editors/space_outliner/CMakeLists.txt56
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c1829
-rw-r--r--source/blender/editors/space_outliner/outliner_dragdrop.c1653
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c4573
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c2931
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h317
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c146
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c2215
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c3519
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c3698
-rw-r--r--source/blender/editors/space_outliner/outliner_utils.c323
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c598
-rw-r--r--source/blender/editors/space_script/CMakeLists.txt36
-rw-r--r--source/blender/editors/space_script/script_edit.c125
-rw-r--r--source/blender/editors/space_script/script_ops.c9
-rw-r--r--source/blender/editors/space_script/space_script.c195
-rw-r--r--source/blender/editors/space_sequencer/CMakeLists.txt64
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c1693
-rw-r--r--source/blender/editors/space_sequencer/sequencer_buttons.c127
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c3201
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c6053
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h62
-rw-r--r--source/blender/editors/space_sequencer/sequencer_modifier.c360
-rw-r--r--source/blender/editors/space_sequencer/sequencer_ops.c183
-rw-r--r--source/blender/editors/space_sequencer/sequencer_preview.c203
-rw-r--r--source/blender/editors/space_sequencer/sequencer_scopes.c1168
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c2075
-rw-r--r--source/blender/editors/space_sequencer/sequencer_view.c298
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c1301
-rw-r--r--source/blender/editors/space_statusbar/CMakeLists.txt30
-rw-r--r--source/blender/editors/space_statusbar/space_statusbar.c189
-rw-r--r--source/blender/editors/space_text/CMakeLists.txt66
-rw-r--r--source/blender/editors/space_text/space_text.c617
-rw-r--r--source/blender/editors/space_text/text_autocomplete.c995
-rw-r--r--source/blender/editors/space_text/text_draw.c2824
-rw-r--r--source/blender/editors/space_text/text_format.c240
-rw-r--r--source/blender/editors/space_text/text_format.h110
-rw-r--r--source/blender/editors/space_text/text_format_lua.c514
-rw-r--r--source/blender/editors/space_text/text_format_osl.c566
-rw-r--r--source/blender/editors/space_text/text_format_pov.c1693
-rw-r--r--source/blender/editors/space_text/text_format_pov_ini.c894
-rw-r--r--source/blender/editors/space_text/text_format_py.c528
-rw-r--r--source/blender/editors/space_text/text_header.c224
-rw-r--r--source/blender/editors/space_text/text_intern.h57
-rw-r--r--source/blender/editors/space_text/text_ops.c4689
-rw-r--r--source/blender/editors/space_text/text_undo.c213
-rw-r--r--source/blender/editors/space_topbar/CMakeLists.txt26
-rw-r--r--source/blender/editors/space_topbar/space_topbar.c352
-rw-r--r--source/blender/editors/space_userpref/CMakeLists.txt20
-rw-r--r--source/blender/editors/space_userpref/space_userpref.c267
-rw-r--r--source/blender/editors/space_userpref/userpref_ops.c26
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt108
-rw-r--r--source/blender/editors/space_view3d/drawobject.c766
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c2395
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c2573
-rw-r--r--source/blender/editors/space_view3d/view3d_camera_control.c428
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c2961
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c1573
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c7785
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c1782
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_armature.c268
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_camera.c778
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_empty.c247
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_forcefield.c121
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_light.c377
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_navigate.c488
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c747
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_preselect.c64
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c678
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c1681
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c241
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h154
-rw-r--r--source/blender/editors/space_view3d/view3d_iterators.c696
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c264
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c923
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c6208
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c1363
-rw-r--r--source/blender/editors/space_view3d/view3d_toolbar.c28
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c2004
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c2316
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c2067
-rw-r--r--source/blender/editors/transform/CMakeLists.txt72
-rw-r--r--source/blender/editors/transform/transform.c15383
-rw-r--r--source/blender/editors/transform/transform.h1398
-rw-r--r--source/blender/editors/transform/transform_constraints.c1768
-rw-r--r--source/blender/editors/transform/transform_conversions.c16167
-rw-r--r--source/blender/editors/transform/transform_generics.c4171
-rw-r--r--source/blender/editors/transform/transform_gizmo_2d.c525
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c3969
-rw-r--r--source/blender/editors/transform/transform_gizmo_extrude_3d.c761
-rw-r--r--source/blender/editors/transform/transform_input.c651
-rw-r--r--source/blender/editors/transform/transform_ops.c1774
-rw-r--r--source/blender/editors/transform/transform_orientations.c1930
-rw-r--r--source/blender/editors/transform/transform_snap.c2441
-rw-r--r--source/blender/editors/transform/transform_snap_object.c4654
-rw-r--r--source/blender/editors/undo/CMakeLists.txt44
-rw-r--r--source/blender/editors/undo/ed_undo.c910
-rw-r--r--source/blender/editors/undo/memfile_undo.c153
-rw-r--r--source/blender/editors/undo/undo_system_types.c35
-rw-r--r--source/blender/editors/util/CMakeLists.txt158
-rw-r--r--source/blender/editors/util/ed_transverts.c876
-rw-r--r--source/blender/editors/util/ed_util.c620
-rw-r--r--source/blender/editors/util/gizmo_utils.c44
-rw-r--r--source/blender/editors/util/numinput.c919
-rw-r--r--source/blender/editors/util/select_utils.c157
-rw-r--r--source/blender/editors/uvedit/CMakeLists.txt48
-rw-r--r--source/blender/editors/uvedit/uvedit_buttons.c315
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c759
-rw-r--r--source/blender/editors/uvedit/uvedit_intern.h93
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c7665
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c6861
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.h14
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c4920
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c3645
548 files changed, 388302 insertions, 368944 deletions
diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt
index 3b06e1784e6..7910cf47a33 100644
--- a/source/blender/editors/CMakeLists.txt
+++ b/source/blender/editors/CMakeLists.txt
@@ -16,51 +16,51 @@
# ***** END GPL LICENSE BLOCK *****
if(WITH_BLENDER)
- if(WITH_INPUT_NDOF)
- add_definitions(-DWITH_INPUT_NDOF)
- endif()
+ if(WITH_INPUT_NDOF)
+ add_definitions(-DWITH_INPUT_NDOF)
+ endif()
- add_subdirectory(animation)
- add_subdirectory(armature)
- add_subdirectory(curve)
- add_subdirectory(gpencil)
- add_subdirectory(interface)
- add_subdirectory(io)
- add_subdirectory(lattice)
- add_subdirectory(gizmo_library)
- add_subdirectory(mask)
- add_subdirectory(mesh)
- add_subdirectory(metaball)
- add_subdirectory(object)
- add_subdirectory(physics)
- add_subdirectory(render)
- add_subdirectory(scene)
- add_subdirectory(sculpt_paint)
- add_subdirectory(sound)
- add_subdirectory(space_action)
- add_subdirectory(space_api)
- add_subdirectory(space_buttons)
- add_subdirectory(space_clip)
- add_subdirectory(space_console)
- add_subdirectory(space_file)
- add_subdirectory(space_graph)
- add_subdirectory(space_image)
- add_subdirectory(space_info)
- add_subdirectory(space_nla)
- add_subdirectory(space_node)
- add_subdirectory(space_outliner)
- add_subdirectory(space_script)
- add_subdirectory(space_sequencer)
- add_subdirectory(space_statusbar)
- add_subdirectory(space_text)
- add_subdirectory(space_topbar)
- add_subdirectory(space_userpref)
- add_subdirectory(space_view3d)
- add_subdirectory(transform)
- add_subdirectory(undo)
- add_subdirectory(util)
- add_subdirectory(uvedit)
- add_subdirectory(screen)
+ add_subdirectory(animation)
+ add_subdirectory(armature)
+ add_subdirectory(curve)
+ add_subdirectory(gpencil)
+ add_subdirectory(interface)
+ add_subdirectory(io)
+ add_subdirectory(lattice)
+ add_subdirectory(gizmo_library)
+ add_subdirectory(mask)
+ add_subdirectory(mesh)
+ add_subdirectory(metaball)
+ add_subdirectory(object)
+ add_subdirectory(physics)
+ add_subdirectory(render)
+ add_subdirectory(scene)
+ add_subdirectory(sculpt_paint)
+ add_subdirectory(sound)
+ add_subdirectory(space_action)
+ add_subdirectory(space_api)
+ add_subdirectory(space_buttons)
+ add_subdirectory(space_clip)
+ add_subdirectory(space_console)
+ add_subdirectory(space_file)
+ add_subdirectory(space_graph)
+ add_subdirectory(space_image)
+ add_subdirectory(space_info)
+ add_subdirectory(space_nla)
+ add_subdirectory(space_node)
+ add_subdirectory(space_outliner)
+ add_subdirectory(space_script)
+ add_subdirectory(space_sequencer)
+ add_subdirectory(space_statusbar)
+ add_subdirectory(space_text)
+ add_subdirectory(space_topbar)
+ add_subdirectory(space_userpref)
+ add_subdirectory(space_view3d)
+ add_subdirectory(transform)
+ add_subdirectory(undo)
+ add_subdirectory(util)
+ add_subdirectory(uvedit)
+ add_subdirectory(screen)
endif()
add_subdirectory(datafiles)
diff --git a/source/blender/editors/animation/CMakeLists.txt b/source/blender/editors/animation/CMakeLists.txt
index ea37aab69ea..b67298a6df6 100644
--- a/source/blender/editors/animation/CMakeLists.txt
+++ b/source/blender/editors/animation/CMakeLists.txt
@@ -16,56 +16,56 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../depsgraph
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/clog
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../depsgraph
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/clog
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- anim_channels_defines.c
- anim_channels_edit.c
- anim_deps.c
- anim_draw.c
- anim_filter.c
- anim_ipo_utils.c
- anim_markers.c
- anim_motion_paths.c
- anim_ops.c
- drivers.c
- fmodifier_ui.c
- keyframes_draw.c
- keyframes_edit.c
- keyframes_general.c
- keyframing.c
- keyingsets.c
+ anim_channels_defines.c
+ anim_channels_edit.c
+ anim_deps.c
+ anim_draw.c
+ anim_filter.c
+ anim_ipo_utils.c
+ anim_markers.c
+ anim_motion_paths.c
+ anim_ops.c
+ drivers.c
+ fmodifier_ui.c
+ keyframes_draw.c
+ keyframes_edit.c
+ keyframes_general.c
+ keyframing.c
+ keyingsets.c
- anim_intern.h
+ anim_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
+ bf_blenkernel
+ bf_blenlib
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
if(WITH_PYTHON)
- add_definitions(-DWITH_PYTHON)
+ add_definitions(-DWITH_PYTHON)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index daa2cda2e1b..78c17ac7015 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -21,7 +21,6 @@
* \ingroup edanimation
*/
-
#include <stdio.h>
#include "MEM_guardedalloc.h"
@@ -83,10 +82,10 @@
// XXX constant defines to be moved elsewhere?
/* extra padding for lengths (to go under scrollers) */
-#define EXTRA_SCROLL_PAD 100.0f
+#define EXTRA_SCROLL_PAD 100.0f
/* size of indent steps */
-#define INDENT_STEP_SIZE (0.35f * U.widget_unit)
+#define INDENT_STEP_SIZE (0.35f * U.widget_unit)
/* size of string buffers used for animation channel displayed names */
#define ANIM_CHAN_NAME_SIZE 256
@@ -100,163 +99,175 @@
/* Draw Backdrop ---------------------------------- */
/* get backdrop color for top-level widgets (Scene and Object only) */
-static void acf_generic_root_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
+static void acf_generic_root_color(bAnimContext *UNUSED(ac),
+ bAnimListElem *UNUSED(ale),
+ float r_color[3])
{
- /* darker blue for top-level widgets */
- UI_GetThemeColor3fv(TH_DOPESHEET_CHANNELOB, r_color);
+ /* darker blue for top-level widgets */
+ UI_GetThemeColor3fv(TH_DOPESHEET_CHANNELOB, r_color);
}
/* backdrop for top-level widgets (Scene and Object only) */
-static void acf_generic_root_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
+static void acf_generic_root_backdrop(bAnimContext *ac,
+ bAnimListElem *ale,
+ float yminc,
+ float ymaxc)
{
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- View2D *v2d = &ac->ar->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];
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ View2D *v2d = &ac->ar->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];
- /* set backdrop drawing color */
- acf->get_backdrop_color(ac, ale, color);
+ /* set backdrop drawing color */
+ acf->get_backdrop_color(ac, ale, color);
- /* 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(true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
+ /* 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(
+ true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
}
-
/* get backdrop color for data expanders under top-level Scene/Object */
-static void acf_generic_dataexpand_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
+static void acf_generic_dataexpand_color(bAnimContext *UNUSED(ac),
+ bAnimListElem *UNUSED(ale),
+ float r_color[3])
{
- /* lighter color than top-level widget */
- UI_GetThemeColor3fv(TH_DOPESHEET_CHANNELSUBOB, r_color);
+ /* lighter color than top-level widget */
+ UI_GetThemeColor3fv(TH_DOPESHEET_CHANNELSUBOB, r_color);
}
/* backdrop for data expanders under top-level Scene/Object */
-static void acf_generic_dataexpand_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
+static void acf_generic_dataexpand_backdrop(bAnimContext *ac,
+ bAnimListElem *ale,
+ float yminc,
+ float ymaxc)
{
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- View2D *v2d = &ac->ar->v2d;
- short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
- float color[3];
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ View2D *v2d = &ac->ar->v2d;
+ short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
+ float color[3];
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- /* set backdrop drawing color */
- acf->get_backdrop_color(ac, ale, color);
+ /* set backdrop drawing color */
+ acf->get_backdrop_color(ac, ale, color);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3fv(color);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
- /* no rounded corner - just rectangular box */
- immRectf(pos, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
+ /* no rounded corner - just rectangular box */
+ immRectf(pos, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
- immUnbindProgram();
+ immUnbindProgram();
}
/* helper method to test if group colors should be drawn */
static bool acf_show_channel_colors(bAnimContext *ac)
{
- bool showGroupColors = false;
+ bool showGroupColors = false;
- if (ac->sl) {
- switch (ac->spacetype) {
- case SPACE_ACTION:
- {
- SpaceAction *saction = (SpaceAction *)ac->sl;
- showGroupColors = !(saction->flag & SACTION_NODRAWGCOLORS);
+ if (ac->sl) {
+ switch (ac->spacetype) {
+ case SPACE_ACTION: {
+ SpaceAction *saction = (SpaceAction *)ac->sl;
+ showGroupColors = !(saction->flag & SACTION_NODRAWGCOLORS);
- break;
- }
- case SPACE_GRAPH:
- {
- SpaceGraph *sipo = (SpaceGraph *)ac->sl;
- showGroupColors = !(sipo->flag & SIPO_NODRAWGCOLORS);
+ break;
+ }
+ case SPACE_GRAPH: {
+ SpaceGraph *sipo = (SpaceGraph *)ac->sl;
+ showGroupColors = !(sipo->flag & SIPO_NODRAWGCOLORS);
- break;
- }
- }
- }
+ break;
+ }
+ }
+ }
- return showGroupColors;
+ return showGroupColors;
}
/* get backdrop color for generic channels */
static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, float r_color[3])
{
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- bActionGroup *grp = NULL;
- short indent = (acf->get_indent_level) ? acf->get_indent_level(ac, ale) : 0;
- bool showGroupColors = acf_show_channel_colors(ac);
-
- if (ale->type == ANIMTYPE_FCURVE) {
- FCurve *fcu = (FCurve *)ale->data;
- grp = fcu->grp;
- }
-
- /* set color for normal channels
- * - use 3 shades of color group/standard color for 3 indention level
- * - only use group colors if allowed to, and if actually feasible
- */
- if (showGroupColors && (grp) && (grp->customCol)) {
- unsigned char cp[3];
-
- if (indent == 2) {
- copy_v3_v3_char((char *)cp, grp->cs.solid);
- }
- else if (indent == 1) {
- copy_v3_v3_char((char *)cp, grp->cs.select);
- }
- else {
- copy_v3_v3_char((char *)cp, grp->cs.active);
- }
-
- /* copy the colors over, transforming from bytes to floats */
- rgb_uchar_to_float(r_color, cp);
- }
- else {
- // FIXME: what happens when the indention is 1 greater than what it should be (due to grouping)?
- int colOfs = 10 - 10 * indent;
- UI_GetThemeColorShade3fv(TH_SHADE2, colOfs, r_color);
- }
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ bActionGroup *grp = NULL;
+ short indent = (acf->get_indent_level) ? acf->get_indent_level(ac, ale) : 0;
+ bool showGroupColors = acf_show_channel_colors(ac);
+
+ if (ale->type == ANIMTYPE_FCURVE) {
+ FCurve *fcu = (FCurve *)ale->data;
+ grp = fcu->grp;
+ }
+
+ /* set color for normal channels
+ * - use 3 shades of color group/standard color for 3 indention level
+ * - only use group colors if allowed to, and if actually feasible
+ */
+ if (showGroupColors && (grp) && (grp->customCol)) {
+ unsigned char cp[3];
+
+ if (indent == 2) {
+ copy_v3_v3_char((char *)cp, grp->cs.solid);
+ }
+ else if (indent == 1) {
+ copy_v3_v3_char((char *)cp, grp->cs.select);
+ }
+ else {
+ copy_v3_v3_char((char *)cp, grp->cs.active);
+ }
+
+ /* copy the colors over, transforming from bytes to floats */
+ rgb_uchar_to_float(r_color, cp);
+ }
+ else {
+ // FIXME: what happens when the indention is 1 greater than what it should be (due to grouping)?
+ int colOfs = 10 - 10 * indent;
+ UI_GetThemeColorShade3fv(TH_SHADE2, colOfs, r_color);
+ }
}
/* get backdrop color for grease pencil channels */
static void acf_gpencil_channel_color(bAnimContext *ac, bAnimListElem *ale, float r_color[3])
{
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- short indent = (acf->get_indent_level) ? acf->get_indent_level(ac, ale) : 0;
- bool showGroupColors = acf_show_channel_colors(ac);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ short indent = (acf->get_indent_level) ? acf->get_indent_level(ac, ale) : 0;
+ bool showGroupColors = acf_show_channel_colors(ac);
- if ((showGroupColors) && (ale->type == ANIMTYPE_GPLAYER)) {
- bGPDlayer *gpl = (bGPDlayer *)ale->data;
- copy_v3_v3(r_color, gpl->color);
- }
- else {
- int colOfs = 10 - 10 * indent;
- UI_GetThemeColorShade3fv(TH_SHADE2, colOfs, r_color);
- }
+ if ((showGroupColors) && (ale->type == ANIMTYPE_GPLAYER)) {
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+ copy_v3_v3(r_color, gpl->color);
+ }
+ else {
+ int colOfs = 10 - 10 * indent;
+ UI_GetThemeColorShade3fv(TH_SHADE2, colOfs, r_color);
+ }
}
/* backdrop for generic channels */
-static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
+static void acf_generic_channel_backdrop(bAnimContext *ac,
+ bAnimListElem *ale,
+ float yminc,
+ float ymaxc)
{
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- View2D *v2d = &ac->ar->v2d;
- short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
- float color[3];
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ View2D *v2d = &ac->ar->v2d;
+ short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
+ float color[3];
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- /* set backdrop drawing color */
- acf->get_backdrop_color(ac, ale, color);
+ /* set backdrop drawing color */
+ acf->get_backdrop_color(ac, ale, color);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3fv(color);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
- /* no rounded corners - just rectangular box */
- immRectf(pos, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
+ /* no rounded corners - just rectangular box */
+ immRectf(pos, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
- immUnbindProgram();
+ immUnbindProgram();
}
/* Indention + Offset ------------------------------------------- */
@@ -264,99 +275,99 @@ static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, f
/* indention level is always the value in the name */
static short acf_generic_indention_0(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
{
- return 0;
+ return 0;
}
static short acf_generic_indention_1(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
{
- return 1;
+ return 1;
}
-#if 0 // XXX not used
+#if 0 // XXX not used
static short acf_generic_indention_2(bAnimContext *ac, bAnimListElem *ale)
{
- return 2;
+ return 2;
}
#endif
/* indention which varies with the grouping status */
static short acf_generic_indention_flexible(bAnimContext *UNUSED(ac), bAnimListElem *ale)
{
- short indent = 0;
+ short indent = 0;
- /* grouped F-Curves need extra level of indention */
- if (ale->type == ANIMTYPE_FCURVE) {
- FCurve *fcu = (FCurve *)ale->data;
+ /* grouped F-Curves need extra level of indention */
+ if (ale->type == ANIMTYPE_FCURVE) {
+ FCurve *fcu = (FCurve *)ale->data;
- // TODO: we need some way of specifying that the indention color should be one less...
- if (fcu->grp)
- indent++;
- }
+ // TODO: we need some way of specifying that the indention color should be one less...
+ if (fcu->grp)
+ indent++;
+ }
- /* no indention */
- return indent;
+ /* no indention */
+ return indent;
}
/* basic offset for channels derived from indention */
static short acf_generic_basic_offset(bAnimContext *ac, bAnimListElem *ale)
{
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- if (acf && acf->get_indent_level)
- return acf->get_indent_level(ac, ale) * INDENT_STEP_SIZE;
- else
- return 0;
+ if (acf && acf->get_indent_level)
+ return acf->get_indent_level(ac, ale) * INDENT_STEP_SIZE;
+ else
+ return 0;
}
/* offset based on nodetree type */
static short acf_nodetree_rootType_offset(bNodeTree *ntree)
{
- if (ntree) {
- switch (ntree->type) {
- case NTREE_SHADER:
- /* 1 additional level (i.e. is indented one level in from material,
- * so shift all right by one step)
- */
- return INDENT_STEP_SIZE;
+ if (ntree) {
+ switch (ntree->type) {
+ case NTREE_SHADER:
+ /* 1 additional level (i.e. is indented one level in from material,
+ * so shift all right by one step)
+ */
+ return INDENT_STEP_SIZE;
- case NTREE_COMPOSIT:
- /* no additional levels needed */
- return 0;
+ case NTREE_COMPOSIT:
+ /* no additional levels needed */
+ return 0;
- case NTREE_TEXTURE:
- /* 2 additional levels */
- return INDENT_STEP_SIZE * 2;
- }
- }
+ case NTREE_TEXTURE:
+ /* 2 additional levels */
+ return INDENT_STEP_SIZE * 2;
+ }
+ }
- /* unknown */
- return 0;
+ /* unknown */
+ return 0;
}
/* offset for groups + grouped entities */
static short acf_generic_group_offset(bAnimContext *ac, bAnimListElem *ale)
{
- short offset = acf_generic_basic_offset(ac, ale);
+ short offset = acf_generic_basic_offset(ac, ale);
- if (ale->id) {
- /* texture animdata */
- if (GS(ale->id->name) == ID_TE) {
- offset += U.widget_unit;
- }
- /* materials and particles animdata */
- else if (ELEM(GS(ale->id->name), ID_MA, ID_PA))
- offset += (short)(0.7f * U.widget_unit);
+ if (ale->id) {
+ /* texture animdata */
+ if (GS(ale->id->name) == ID_TE) {
+ offset += U.widget_unit;
+ }
+ /* materials and particles animdata */
+ else if (ELEM(GS(ale->id->name), ID_MA, ID_PA))
+ offset += (short)(0.7f * U.widget_unit);
- /* if not in Action Editor mode, action-groups (and their children) must carry some offset too... */
- else if (ac->datatype != ANIMCONT_ACTION)
- offset += (short)(0.7f * U.widget_unit);
+ /* if not in Action Editor mode, action-groups (and their children) must carry some offset too... */
+ else if (ac->datatype != ANIMCONT_ACTION)
+ offset += (short)(0.7f * U.widget_unit);
- /* nodetree animdata */
- if (GS(ale->id->name) == ID_NT) {
- offset += acf_nodetree_rootType_offset((bNodeTree *)ale->id);
- }
- }
+ /* nodetree animdata */
+ if (GS(ale->id->name) == ID_NT) {
+ offset += acf_nodetree_rootType_offset((bNodeTree *)ale->id);
+ }
+ }
- /* offset is just the normal type - i.e. based on indention */
- return offset;
+ /* offset is just the normal type - i.e. based on indention */
+ return offset;
}
/* Name ------------------------------------------- */
@@ -364,31 +375,30 @@ static short acf_generic_group_offset(bAnimContext *ac, bAnimListElem *ale)
/* name for ID block entries */
static void acf_generic_idblock_name(bAnimListElem *ale, char *name)
{
- ID *id = (ID *)ale->data; /* data pointed to should be an ID block */
+ ID *id = (ID *)ale->data; /* data pointed to should be an ID block */
- /* just copy the name... */
- if (id && name)
- BLI_strncpy(name, id->name + 2, ANIM_CHAN_NAME_SIZE);
+ /* just copy the name... */
+ if (id && name)
+ BLI_strncpy(name, id->name + 2, ANIM_CHAN_NAME_SIZE);
}
/* name property for ID block entries */
static bool acf_generic_idblock_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
- RNA_id_pointer_create(ale->data, ptr);
- *prop = RNA_struct_name_property(ptr->type);
+ RNA_id_pointer_create(ale->data, ptr);
+ *prop = RNA_struct_name_property(ptr->type);
- return (*prop != NULL);
+ return (*prop != NULL);
}
-
/* name property for ID block entries which are just subheading "fillers" */
static bool acf_generic_idfill_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
- /* actual ID we're representing is stored in ale->data not ale->id, as id gives the owner */
- RNA_id_pointer_create(ale->data, ptr);
- *prop = RNA_struct_name_property(ptr->type);
+ /* actual ID we're representing is stored in ale->data not ale->id, as id gives the owner */
+ RNA_id_pointer_create(ale->data, ptr);
+ *prop = RNA_struct_name_property(ptr->type);
- return (*prop != NULL);
+ return (*prop != NULL);
}
/* Settings ------------------------------------------- */
@@ -397,33 +407,35 @@ static bool acf_generic_idfill_name_prop(bAnimListElem *ale, PointerRNA *ptr, Pr
/* channel type has no settings */
static bool acf_generic_none_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
{
- return false;
+ return false;
}
#endif
/* check if some setting exists for this object-based data-expander (datablock only) */
-static bool acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
+static bool acf_generic_dataexpand_setting_valid(bAnimContext *ac,
+ bAnimListElem *UNUSED(ale),
+ eAnimChannel_Settings setting)
{
- switch (setting) {
- /* expand is always supported */
- case ACHANNEL_SETTING_EXPAND:
- return true;
+ switch (setting) {
+ /* expand is always supported */
+ case ACHANNEL_SETTING_EXPAND:
+ return true;
- /* mute is only supported for NLA */
- case ACHANNEL_SETTING_MUTE:
- return ((ac) && (ac->spacetype == SPACE_NLA));
+ /* mute is only supported for NLA */
+ case ACHANNEL_SETTING_MUTE:
+ return ((ac) && (ac->spacetype == SPACE_NLA));
- /* select is ok for most "ds*" channels (e.g. dsmat) */
- case ACHANNEL_SETTING_SELECT:
- return true;
+ /* select is ok for most "ds*" channels (e.g. dsmat) */
+ case ACHANNEL_SETTING_SELECT:
+ return true;
- case ACHANNEL_SETTING_ALWAYS_VISIBLE:
- return true;
+ case ACHANNEL_SETTING_ALWAYS_VISIBLE:
+ return true;
- /* other flags are never supported */
- default:
- return false;
- }
+ /* other flags are never supported */
+ default:
+ return false;
+ }
}
/* *********************************************** */
@@ -432,105 +444,113 @@ static bool acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListElem
/* Animation Summary ----------------------------------- */
/* get backdrop color for summary widget */
-static void acf_summary_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
+static void acf_summary_color(bAnimContext *UNUSED(ac),
+ bAnimListElem *UNUSED(ale),
+ float r_color[3])
{
- /* reddish color - same as the 'action' line in NLA */
- UI_GetThemeColor3fv(TH_ANIM_ACTIVE, r_color);
+ /* reddish color - same as the 'action' line in NLA */
+ UI_GetThemeColor3fv(TH_ANIM_ACTIVE, r_color);
}
/* backdrop for summary widget */
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;
- float color[3];
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ View2D *v2d = &ac->ar->v2d;
+ float color[3];
- /* set backdrop drawing color */
- acf->get_backdrop_color(ac, ale, color);
+ /* set backdrop drawing color */
+ acf->get_backdrop_color(ac, ale, color);
- /* rounded corners on LHS only
- * - top and bottom
- * - 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(true, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
+ /* rounded corners on LHS only
+ * - top and bottom
+ * - 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(
+ true, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
}
/* name for summary entries */
static void acf_summary_name(bAnimListElem *UNUSED(ale), char *name)
{
- if (name)
- BLI_strncpy(name, IFACE_("Dope Sheet Summary"), ANIM_CHAN_NAME_SIZE);
+ if (name)
+ BLI_strncpy(name, IFACE_("Dope Sheet Summary"), ANIM_CHAN_NAME_SIZE);
}
// FIXME: this is really a temp icon I think
static int acf_summary_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_BORDERMOVE;
+ return ICON_BORDERMOVE;
}
/* check if some setting exists for this channel */
-static bool acf_summary_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
+static bool acf_summary_setting_valid(bAnimContext *UNUSED(ac),
+ bAnimListElem *UNUSED(ale),
+ eAnimChannel_Settings setting)
{
- /* only expanded is supported, as it is used for hiding all stuff which the summary covers */
- return (setting == ACHANNEL_SETTING_EXPAND);
+ /* only expanded is supported, as it is used for hiding all stuff which the summary covers */
+ return (setting == ACHANNEL_SETTING_EXPAND);
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_summary_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
-{
- if (setting == ACHANNEL_SETTING_EXPAND) {
- /* expanded */
- *neg = true;
- return ADS_FLAG_SUMMARY_COLLAPSED;
- }
- else {
- /* unsupported */
- *neg = false;
- return 0;
- }
+static int acf_summary_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
+{
+ if (setting == ACHANNEL_SETTING_EXPAND) {
+ /* expanded */
+ *neg = true;
+ return ADS_FLAG_SUMMARY_COLLAPSED;
+ }
+ else {
+ /* unsupported */
+ *neg = false;
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_summary_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
+static void *acf_summary_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings setting,
+ short *type)
{
- bAnimContext *ac = (bAnimContext *)ale->data;
+ bAnimContext *ac = (bAnimContext *)ale->data;
- /* if data is valid, return pointer to active dopesheet's relevant flag
- * - this is restricted to DopeSheet/Action Editor only
- */
- if ((ac->sl) && (ac->spacetype == SPACE_ACTION) && (setting == ACHANNEL_SETTING_EXPAND)) {
- SpaceAction *saction = (SpaceAction *)ac->sl;
- bDopeSheet *ads = &saction->ads;
+ /* if data is valid, return pointer to active dopesheet's relevant flag
+ * - this is restricted to DopeSheet/Action Editor only
+ */
+ if ((ac->sl) && (ac->spacetype == SPACE_ACTION) && (setting == ACHANNEL_SETTING_EXPAND)) {
+ SpaceAction *saction = (SpaceAction *)ac->sl;
+ bDopeSheet *ads = &saction->ads;
- /* return pointer to DopeSheet's flag */
- return GET_ACF_FLAG_PTR(ads->flag, type);
- }
- else {
- /* can't return anything useful - unsupported */
- *type = 0;
- return NULL;
- }
+ /* return pointer to DopeSheet's flag */
+ return GET_ACF_FLAG_PTR(ads->flag, type);
+ }
+ else {
+ /* can't return anything useful - unsupported */
+ *type = 0;
+ return NULL;
+ }
}
/* all animation summary (DopeSheet only) type define */
-static bAnimChannelType ACF_SUMMARY =
-{
- "Summary", /* type name */
- ACHANNEL_ROLE_EXPANDER, /* role */
-
- acf_summary_color, /* backdrop color */
- acf_summary_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
- NULL, /* offset */
-
- acf_summary_name, /* name */
- NULL, /* name prop */
- acf_summary_icon, /* icon */
-
- acf_summary_setting_valid, /* has setting */
- acf_summary_setting_flag, /* flag for setting */
- acf_summary_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_SUMMARY = {
+ "Summary", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_summary_color, /* backdrop color */
+ acf_summary_backdrop, /* backdrop */
+ acf_generic_indention_0, /* indent level */
+ NULL, /* offset */
+
+ acf_summary_name, /* name */
+ NULL, /* name prop */
+ acf_summary_icon, /* icon */
+
+ acf_summary_setting_valid, /* has setting */
+ acf_summary_setting_flag, /* flag for setting */
+ acf_summary_setting_ptr, /* pointer for setting */
};
/* Scene ------------------------------------------- */
@@ -538,269 +558,275 @@ static bAnimChannelType ACF_SUMMARY =
// TODO: just get this from RNA?
static int acf_scene_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_SCENE_DATA;
+ return ICON_SCENE_DATA;
}
/* check if some setting exists for this channel */
-static bool acf_scene_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
+static bool acf_scene_setting_valid(bAnimContext *ac,
+ bAnimListElem *UNUSED(ale),
+ eAnimChannel_Settings setting)
{
- switch (setting) {
- /* muted only in NLA */
- case ACHANNEL_SETTING_MUTE:
- return ((ac) && (ac->spacetype == SPACE_NLA));
+ switch (setting) {
+ /* muted only in NLA */
+ case ACHANNEL_SETTING_MUTE:
+ return ((ac) && (ac->spacetype == SPACE_NLA));
- /* visible only in Graph Editor */
- case ACHANNEL_SETTING_VISIBLE:
- return ((ac) && (ac->spacetype == SPACE_GRAPH));
+ /* visible only in Graph Editor */
+ case ACHANNEL_SETTING_VISIBLE:
+ return ((ac) && (ac->spacetype == SPACE_GRAPH));
- /* only select and expand supported otherwise */
- case ACHANNEL_SETTING_SELECT:
- case ACHANNEL_SETTING_EXPAND:
- return true;
+ /* only select and expand supported otherwise */
+ case ACHANNEL_SETTING_SELECT:
+ case ACHANNEL_SETTING_EXPAND:
+ return true;
- case ACHANNEL_SETTING_ALWAYS_VISIBLE:
- return false;
+ case ACHANNEL_SETTING_ALWAYS_VISIBLE:
+ return false;
- default:
- return false;
- }
+ default:
+ return false;
+ }
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_scene_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_scene_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_SELECT: /* selected */
- return SCE_DS_SELECTED;
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return SCE_DS_SELECTED;
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- *neg = true;
- return SCE_DS_COLLAPSED;
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ *neg = true;
+ return SCE_DS_COLLAPSED;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
static void *acf_scene_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
- Scene *scene = (Scene *)ale->data;
+ Scene *scene = (Scene *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_SELECT: /* selected */
- return GET_ACF_FLAG_PTR(scene->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return GET_ACF_FLAG_PTR(scene->flag, type);
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(scene->flag, type);
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(scene->flag, type);
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
- if (scene->adt)
- return GET_ACF_FLAG_PTR(scene->adt->flag, type);
- return NULL;
+ case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (scene->adt)
+ return GET_ACF_FLAG_PTR(scene->adt->flag, type);
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* scene type define */
-static bAnimChannelType ACF_SCENE =
-{
- "Scene", /* type name */
- ACHANNEL_ROLE_EXPANDER, /* role */
-
- acf_generic_root_color, /* backdrop color */
- acf_generic_root_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
- NULL, /* offset */
-
- acf_generic_idblock_name, /* name */
- acf_generic_idblock_name_prop, /* name prop */
- acf_scene_icon, /* icon */
-
- acf_scene_setting_valid, /* has setting */
- acf_scene_setting_flag, /* flag for setting */
- acf_scene_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_SCENE = {
+ "Scene", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_generic_root_color, /* backdrop color */
+ acf_generic_root_backdrop, /* backdrop */
+ acf_generic_indention_0, /* indent level */
+ NULL, /* offset */
+
+ acf_generic_idblock_name, /* name */
+ acf_generic_idblock_name_prop, /* name prop */
+ acf_scene_icon, /* icon */
+
+ acf_scene_setting_valid, /* has setting */
+ acf_scene_setting_flag, /* flag for setting */
+ acf_scene_setting_ptr, /* pointer for setting */
};
/* Object ------------------------------------------- */
static int acf_object_icon(bAnimListElem *ale)
{
- Base *base = (Base *)ale->data;
- Object *ob = base->object;
-
- /* icon depends on object-type */
- switch (ob->type) {
- case OB_LAMP:
- return ICON_OUTLINER_OB_LIGHT;
- case OB_MESH:
- return ICON_OUTLINER_OB_MESH;
- case OB_CAMERA:
- return ICON_OUTLINER_OB_CAMERA;
- case OB_CURVE:
- return ICON_OUTLINER_OB_CURVE;
- case OB_MBALL:
- return ICON_OUTLINER_OB_META;
- case OB_LATTICE:
- return ICON_OUTLINER_OB_LATTICE;
- case OB_SPEAKER:
- return ICON_OUTLINER_OB_SPEAKER;
- case OB_LIGHTPROBE:
- return ICON_OUTLINER_OB_LIGHTPROBE;
- case OB_ARMATURE:
- return ICON_OUTLINER_OB_ARMATURE;
- case OB_FONT:
- return ICON_OUTLINER_OB_FONT;
- case OB_SURF:
- return ICON_OUTLINER_OB_SURFACE;
- case OB_EMPTY:
- return ICON_OUTLINER_OB_EMPTY;
- case OB_GPENCIL:
- return ICON_OUTLINER_OB_GREASEPENCIL;
- default:
- return ICON_OBJECT_DATA;
- }
+ Base *base = (Base *)ale->data;
+ Object *ob = base->object;
+
+ /* icon depends on object-type */
+ switch (ob->type) {
+ case OB_LAMP:
+ return ICON_OUTLINER_OB_LIGHT;
+ case OB_MESH:
+ return ICON_OUTLINER_OB_MESH;
+ case OB_CAMERA:
+ return ICON_OUTLINER_OB_CAMERA;
+ case OB_CURVE:
+ return ICON_OUTLINER_OB_CURVE;
+ case OB_MBALL:
+ return ICON_OUTLINER_OB_META;
+ case OB_LATTICE:
+ return ICON_OUTLINER_OB_LATTICE;
+ case OB_SPEAKER:
+ return ICON_OUTLINER_OB_SPEAKER;
+ case OB_LIGHTPROBE:
+ return ICON_OUTLINER_OB_LIGHTPROBE;
+ case OB_ARMATURE:
+ return ICON_OUTLINER_OB_ARMATURE;
+ case OB_FONT:
+ return ICON_OUTLINER_OB_FONT;
+ case OB_SURF:
+ return ICON_OUTLINER_OB_SURFACE;
+ case OB_EMPTY:
+ return ICON_OUTLINER_OB_EMPTY;
+ case OB_GPENCIL:
+ return ICON_OUTLINER_OB_GREASEPENCIL;
+ default:
+ return ICON_OBJECT_DATA;
+ }
}
/* name for object */
static void acf_object_name(bAnimListElem *ale, char *name)
{
- Base *base = (Base *)ale->data;
- Object *ob = base->object;
+ Base *base = (Base *)ale->data;
+ Object *ob = base->object;
- /* just copy the name... */
- if (ob && name)
- BLI_strncpy(name, ob->id.name + 2, ANIM_CHAN_NAME_SIZE);
+ /* just copy the name... */
+ if (ob && name)
+ BLI_strncpy(name, ob->id.name + 2, ANIM_CHAN_NAME_SIZE);
}
/* name property for object */
static bool acf_object_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
- RNA_id_pointer_create(ale->id, ptr);
- *prop = RNA_struct_name_property(ptr->type);
+ RNA_id_pointer_create(ale->id, ptr);
+ *prop = RNA_struct_name_property(ptr->type);
- return (*prop != NULL);
+ return (*prop != NULL);
}
/* check if some setting exists for this channel */
-static bool acf_object_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
+static bool acf_object_setting_valid(bAnimContext *ac,
+ bAnimListElem *ale,
+ eAnimChannel_Settings setting)
{
- Base *base = (Base *)ale->data;
- Object *ob = base->object;
+ Base *base = (Base *)ale->data;
+ Object *ob = base->object;
- switch (setting) {
- /* muted only in NLA */
- case ACHANNEL_SETTING_MUTE:
- return ((ac) && (ac->spacetype == SPACE_NLA));
+ switch (setting) {
+ /* muted only in NLA */
+ case ACHANNEL_SETTING_MUTE:
+ return ((ac) && (ac->spacetype == SPACE_NLA));
- /* visible only in Graph Editor */
- case ACHANNEL_SETTING_VISIBLE:
- return ((ac) && (ac->spacetype == SPACE_GRAPH) && (ob->adt));
+ /* visible only in Graph Editor */
+ case ACHANNEL_SETTING_VISIBLE:
+ return ((ac) && (ac->spacetype == SPACE_GRAPH) && (ob->adt));
- /* only select and expand supported otherwise */
- case ACHANNEL_SETTING_SELECT:
- case ACHANNEL_SETTING_EXPAND:
- return true;
+ /* only select and expand supported otherwise */
+ case ACHANNEL_SETTING_SELECT:
+ case ACHANNEL_SETTING_EXPAND:
+ return true;
- case ACHANNEL_SETTING_ALWAYS_VISIBLE:
- return ((ac) && (ac->spacetype == SPACE_GRAPH) && (ob->adt));
+ case ACHANNEL_SETTING_ALWAYS_VISIBLE:
+ return ((ac) && (ac->spacetype == SPACE_GRAPH) && (ob->adt));
- default:
- return false;
- }
+ default:
+ return false;
+ }
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_object_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_object_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_SELECT: /* selected */
- return BASE_SELECTED;
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return BASE_SELECTED;
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- *neg = 1;
- return OB_ADS_COLLAPSED;
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ *neg = 1;
+ return OB_ADS_COLLAPSED;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_ALWAYS_VISIBLE:
- return ADT_CURVES_ALWAYS_VISIBLE;
+ case ACHANNEL_SETTING_ALWAYS_VISIBLE:
+ return ADT_CURVES_ALWAYS_VISIBLE;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
static void *acf_object_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
- Base *base = (Base *)ale->data;
- Object *ob = base->object;
+ Base *base = (Base *)ale->data;
+ Object *ob = base->object;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_SELECT: /* selected */
- return GET_ACF_FLAG_PTR(base->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return GET_ACF_FLAG_PTR(base->flag, type);
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(ob->nlaflag, type); // xxx
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(ob->nlaflag, type); // xxx
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
- case ACHANNEL_SETTING_ALWAYS_VISIBLE:
- if (ob->adt)
- return GET_ACF_FLAG_PTR(ob->adt->flag, type);
- return NULL;
+ case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ case ACHANNEL_SETTING_ALWAYS_VISIBLE:
+ if (ob->adt)
+ return GET_ACF_FLAG_PTR(ob->adt->flag, type);
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* object type define */
-static bAnimChannelType ACF_OBJECT =
-{
- "Object", /* type name */
- ACHANNEL_ROLE_EXPANDER, /* role */
-
- acf_generic_root_color, /* backdrop color */
- acf_generic_root_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
- NULL, /* offset */
-
- acf_object_name, /* name */
- acf_object_name_prop, /* name prop */
- acf_object_icon, /* icon */
-
- acf_object_setting_valid, /* has setting */
- acf_object_setting_flag, /* flag for setting */
- acf_object_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_OBJECT = {
+ "Object", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_generic_root_color, /* backdrop color */
+ acf_generic_root_backdrop, /* backdrop */
+ acf_generic_indention_0, /* indent level */
+ NULL, /* offset */
+
+ acf_object_name, /* name */
+ acf_object_name_prop, /* name prop */
+ acf_object_icon, /* icon */
+
+ acf_object_setting_valid, /* has setting */
+ acf_object_setting_flag, /* flag for setting */
+ acf_object_setting_ptr, /* pointer for setting */
};
/* Group ------------------------------------------- */
@@ -808,158 +834,161 @@ static bAnimChannelType ACF_OBJECT =
/* get backdrop color for group widget */
static void acf_group_color(bAnimContext *ac, bAnimListElem *ale, float r_color[3])
{
- bActionGroup *agrp = (bActionGroup *)ale->data;
- bool showGroupColors = acf_show_channel_colors(ac);
+ bActionGroup *agrp = (bActionGroup *)ale->data;
+ bool showGroupColors = acf_show_channel_colors(ac);
- if (showGroupColors && agrp->customCol) {
- unsigned char cp[3];
+ if (showGroupColors && agrp->customCol) {
+ unsigned char cp[3];
- /* highlight only for active */
- if (ale->flag & AGRP_ACTIVE)
- copy_v3_v3_char((char *)cp, agrp->cs.select);
- else
- copy_v3_v3_char((char *)cp, agrp->cs.solid);
+ /* highlight only for active */
+ if (ale->flag & AGRP_ACTIVE)
+ copy_v3_v3_char((char *)cp, agrp->cs.select);
+ else
+ copy_v3_v3_char((char *)cp, agrp->cs.solid);
- /* copy the colors over, transforming from bytes to floats */
- rgb_uchar_to_float(r_color, cp);
- }
- else {
- /* highlight only for active */
- if (ale->flag & AGRP_ACTIVE)
- UI_GetThemeColor3fv(TH_GROUP_ACTIVE, r_color);
- else
- UI_GetThemeColor3fv(TH_GROUP, r_color);
- }
+ /* copy the colors over, transforming from bytes to floats */
+ rgb_uchar_to_float(r_color, cp);
+ }
+ else {
+ /* highlight only for active */
+ if (ale->flag & AGRP_ACTIVE)
+ UI_GetThemeColor3fv(TH_GROUP_ACTIVE, r_color);
+ else
+ UI_GetThemeColor3fv(TH_GROUP, r_color);
+ }
}
/* backdrop for group widget */
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;
- 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];
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ View2D *v2d = &ac->ar->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];
- /* set backdrop drawing color */
- acf->get_backdrop_color(ac, ale, color);
+ /* set backdrop drawing color */
+ acf->get_backdrop_color(ac, ale, color);
- /* 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(true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
+ /* 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(
+ true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
}
/* name for group entries */
static void acf_group_name(bAnimListElem *ale, char *name)
{
- bActionGroup *agrp = (bActionGroup *)ale->data;
+ bActionGroup *agrp = (bActionGroup *)ale->data;
- /* just copy the name... */
- if (agrp && name)
- BLI_strncpy(name, agrp->name, ANIM_CHAN_NAME_SIZE);
+ /* just copy the name... */
+ if (agrp && name)
+ BLI_strncpy(name, agrp->name, ANIM_CHAN_NAME_SIZE);
}
/* name property for group entries */
static bool acf_group_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
- RNA_pointer_create(ale->id, &RNA_ActionGroup, ale->data, ptr);
- *prop = RNA_struct_name_property(ptr->type);
+ RNA_pointer_create(ale->id, &RNA_ActionGroup, ale->data, ptr);
+ *prop = RNA_struct_name_property(ptr->type);
- return (*prop != NULL);
+ return (*prop != NULL);
}
/* check if some setting exists for this channel */
-static bool acf_group_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
+static bool acf_group_setting_valid(bAnimContext *ac,
+ bAnimListElem *UNUSED(ale),
+ eAnimChannel_Settings setting)
{
- /* 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 */
- return false;
+ /* 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 */
+ return false;
- /* conditionally supported */
- case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
- return (ac->spacetype == SPACE_GRAPH);
+ /* conditionally supported */
+ case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
+ return (ac->spacetype == SPACE_GRAPH);
- case ACHANNEL_SETTING_ALWAYS_VISIBLE:
- return (ac->spacetype == SPACE_GRAPH);
+ case ACHANNEL_SETTING_ALWAYS_VISIBLE:
+ return (ac->spacetype == SPACE_GRAPH);
- default: /* always supported */
- return true;
- }
+ default: /* always supported */
+ return true;
+ }
}
/* get the appropriate flag(s) for the setting when it is valid */
static int acf_group_setting_flag(bAnimContext *ac, eAnimChannel_Settings setting, bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_SELECT: /* selected */
- return AGRP_SELECTED;
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return AGRP_SELECTED;
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- {
- /* NOTE: Graph Editor uses a different flag to everywhere else for this,
- * allowing different collapsing of groups there, since sharing the flag
- * proved to be a hazard for workflows...
- */
- return (ac->spacetype == SPACE_GRAPH) ?
- AGRP_EXPANDED_G : /* Graph Editor case */
- AGRP_EXPANDED; /* DopeSheet and elsewhere */
- }
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ {
+ /* NOTE: Graph Editor uses a different flag to everywhere else for this,
+ * allowing different collapsing of groups there, since sharing the flag
+ * proved to be a hazard for workflows...
+ */
+ return (ac->spacetype == SPACE_GRAPH) ? AGRP_EXPANDED_G : /* Graph Editor case */
+ AGRP_EXPANDED; /* DopeSheet and elsewhere */
+ }
- case ACHANNEL_SETTING_MUTE: /* muted */
- return AGRP_MUTED;
+ case ACHANNEL_SETTING_MUTE: /* muted */
+ return AGRP_MUTED;
- case ACHANNEL_SETTING_MOD_OFF: /* muted */
- *neg = 1;
- return AGRP_MODIFIERS_OFF;
+ case ACHANNEL_SETTING_MOD_OFF: /* muted */
+ *neg = 1;
+ return AGRP_MODIFIERS_OFF;
- case ACHANNEL_SETTING_PROTECT: /* protected */
- return AGRP_PROTECTED;
+ case ACHANNEL_SETTING_PROTECT: /* protected */
+ return AGRP_PROTECTED;
- case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
- *neg = 1;
- return AGRP_NOTVISIBLE;
+ case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
+ *neg = 1;
+ return AGRP_NOTVISIBLE;
- case ACHANNEL_SETTING_ALWAYS_VISIBLE:
- return ADT_CURVES_ALWAYS_VISIBLE;
+ case ACHANNEL_SETTING_ALWAYS_VISIBLE:
+ return ADT_CURVES_ALWAYS_VISIBLE;
- default:
- /* this shouldn't happen */
- return 0;
- }
+ default:
+ /* this shouldn't happen */
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_group_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
+static void *acf_group_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings UNUSED(setting),
+ short *type)
{
- bActionGroup *agrp = (bActionGroup *)ale->data;
+ bActionGroup *agrp = (bActionGroup *)ale->data;
- /* all flags are just in agrp->flag for now... */
- return GET_ACF_FLAG_PTR(agrp->flag, type);
+ /* all flags are just in agrp->flag for now... */
+ return GET_ACF_FLAG_PTR(agrp->flag, type);
}
/* group type define */
-static bAnimChannelType ACF_GROUP =
-{
- "Group", /* type name */
- ACHANNEL_ROLE_CHANNEL, /* role */
-
- acf_group_color, /* backdrop color */
- acf_group_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
- acf_generic_group_offset, /* offset */
-
- acf_group_name, /* name */
- acf_group_name_prop, /* name prop */
- NULL, /* icon */
-
- acf_group_setting_valid, /* has setting */
- acf_group_setting_flag, /* flag for setting */
- acf_group_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_GROUP = {
+ "Group", /* type name */
+ ACHANNEL_ROLE_CHANNEL, /* role */
+
+ acf_group_color, /* backdrop color */
+ acf_group_backdrop, /* backdrop */
+ acf_generic_indention_0, /* indent level */
+ acf_generic_group_offset, /* offset */
+
+ acf_group_name, /* name */
+ acf_group_name_prop, /* name prop */
+ NULL, /* icon */
+
+ acf_group_setting_valid, /* has setting */
+ acf_group_setting_flag, /* flag for setting */
+ acf_group_setting_ptr, /* pointer for setting */
};
/* F-Curve ------------------------------------------- */
@@ -967,258 +996,272 @@ static bAnimChannelType ACF_GROUP =
/* name for fcurve entries */
static void acf_fcurve_name(bAnimListElem *ale, char *name)
{
- getname_anim_fcurve(name, ale->id, ale->data);
+ getname_anim_fcurve(name, ale->id, ale->data);
}
/* "name" property for fcurve entries */
static bool acf_fcurve_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
- FCurve *fcu = (FCurve *)ale->data;
+ FCurve *fcu = (FCurve *)ale->data;
- /* Ctrl-Click Usability Convenience Hack:
- * For disabled F-Curves, allow access to the RNA Path
- * as our "name" so that user can perform quick fixes
- */
- if (fcu->flag & FCURVE_DISABLED) {
- RNA_pointer_create(ale->id, &RNA_FCurve, ale->data, ptr);
- *prop = RNA_struct_find_property(ptr, "data_path");
- }
- else {
- /* for "normal" F-Curves - no editable name, but *prop may not be set properly yet... */
- *prop = NULL;
- }
+ /* Ctrl-Click Usability Convenience Hack:
+ * For disabled F-Curves, allow access to the RNA Path
+ * as our "name" so that user can perform quick fixes
+ */
+ if (fcu->flag & FCURVE_DISABLED) {
+ RNA_pointer_create(ale->id, &RNA_FCurve, ale->data, ptr);
+ *prop = RNA_struct_find_property(ptr, "data_path");
+ }
+ else {
+ /* for "normal" F-Curves - no editable name, but *prop may not be set properly yet... */
+ *prop = NULL;
+ }
- return (*prop != NULL);
+ return (*prop != NULL);
}
/* check if some setting exists for this channel */
-static bool acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
+static bool acf_fcurve_setting_valid(bAnimContext *ac,
+ bAnimListElem *ale,
+ eAnimChannel_Settings setting)
{
- FCurve *fcu = (FCurve *)ale->data;
+ FCurve *fcu = (FCurve *)ale->data;
- switch (setting) {
- /* unsupported */
- case ACHANNEL_SETTING_SOLO: /* Solo Flag is only for NLA */
- case ACHANNEL_SETTING_EXPAND: /* F-Curves are not containers */
- case ACHANNEL_SETTING_PINNED: /* This is only for NLA Actions */
- return false;
+ switch (setting) {
+ /* unsupported */
+ case ACHANNEL_SETTING_SOLO: /* Solo Flag is only for NLA */
+ case ACHANNEL_SETTING_EXPAND: /* F-Curves are not containers */
+ case ACHANNEL_SETTING_PINNED: /* This is only for NLA Actions */
+ return false;
- /* conditionally available */
- case ACHANNEL_SETTING_PROTECT: /* Protection is only valid when there's keyframes */
- if (fcu->bezt)
- return true;
- else
- return false; // NOTE: in this special case, we need to draw ICON_ZOOMOUT
+ /* conditionally available */
+ case ACHANNEL_SETTING_PROTECT: /* Protection is only valid when there's keyframes */
+ if (fcu->bezt)
+ return true;
+ else
+ return false; // NOTE: in this special case, we need to draw ICON_ZOOMOUT
- case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
- return (ac->spacetype == SPACE_GRAPH);
+ case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
+ return (ac->spacetype == SPACE_GRAPH);
- case ACHANNEL_SETTING_ALWAYS_VISIBLE:
- return false;
+ case ACHANNEL_SETTING_ALWAYS_VISIBLE:
+ return false;
- /* always available */
- default:
- return true;
- }
+ /* always available */
+ default:
+ return true;
+ }
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_SELECT: /* selected */
- return FCURVE_SELECTED;
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return FCURVE_SELECTED;
- case ACHANNEL_SETTING_MUTE: /* muted */
- return FCURVE_MUTED;
+ case ACHANNEL_SETTING_MUTE: /* muted */
+ return FCURVE_MUTED;
- case ACHANNEL_SETTING_PROTECT: /* protected */
- return FCURVE_PROTECTED;
+ case ACHANNEL_SETTING_PROTECT: /* protected */
+ return FCURVE_PROTECTED;
- case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
- return FCURVE_VISIBLE;
+ case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
+ return FCURVE_VISIBLE;
- case ACHANNEL_SETTING_MOD_OFF:
- *neg = 1;
- return FCURVE_MOD_OFF;
+ case ACHANNEL_SETTING_MOD_OFF:
+ *neg = 1;
+ return FCURVE_MOD_OFF;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_fcurve_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
+static void *acf_fcurve_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings UNUSED(setting),
+ short *type)
{
- FCurve *fcu = (FCurve *)ale->data;
+ FCurve *fcu = (FCurve *)ale->data;
- /* all flags are just in agrp->flag for now... */
- return GET_ACF_FLAG_PTR(fcu->flag, type);
+ /* all flags are just in agrp->flag for now... */
+ return GET_ACF_FLAG_PTR(fcu->flag, type);
}
/* fcurve type define */
-static bAnimChannelType ACF_FCURVE =
-{
- "F-Curve", /* type name */
- ACHANNEL_ROLE_CHANNEL, /* role */
-
- acf_generic_channel_color, /* backdrop color */
- acf_generic_channel_backdrop, /* backdrop */
- acf_generic_indention_flexible, /* indent level */ // xxx rename this to f-curves only?
- acf_generic_group_offset, /* offset */
-
- acf_fcurve_name, /* name */
- acf_fcurve_name_prop, /* name prop */
- NULL, /* icon */
-
- acf_fcurve_setting_valid, /* has setting */
- acf_fcurve_setting_flag, /* flag for setting */
- acf_fcurve_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_FCURVE = {
+ "F-Curve", /* type name */
+ ACHANNEL_ROLE_CHANNEL, /* role */
+
+ acf_generic_channel_color, /* backdrop color */
+ acf_generic_channel_backdrop, /* backdrop */
+ acf_generic_indention_flexible,
+ /* indent level */ // xxx rename this to f-curves only?
+ acf_generic_group_offset, /* offset */
+
+ acf_fcurve_name, /* name */
+ acf_fcurve_name_prop, /* name prop */
+ NULL, /* icon */
+
+ acf_fcurve_setting_valid, /* has setting */
+ acf_fcurve_setting_flag, /* flag for setting */
+ acf_fcurve_setting_ptr, /* pointer for setting */
};
/* NLA Control FCurves Expander ----------------------- */
/* get backdrop color for nla controls widget */
-static void acf_nla_controls_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
+static void acf_nla_controls_color(bAnimContext *UNUSED(ac),
+ bAnimListElem *UNUSED(ale),
+ float r_color[3])
{
- // TODO: give this its own theme setting?
- UI_GetThemeColorShade3fv(TH_GROUP, 55, r_color);
+ // TODO: give this its own theme setting?
+ UI_GetThemeColorShade3fv(TH_GROUP, 55, r_color);
}
/* backdrop for nla controls expander widget */
-static void acf_nla_controls_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
+static void acf_nla_controls_backdrop(bAnimContext *ac,
+ bAnimListElem *ale,
+ float yminc,
+ float ymaxc)
{
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- View2D *v2d = &ac->ar->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];
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ View2D *v2d = &ac->ar->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];
- /* set backdrop drawing color */
- acf->get_backdrop_color(ac, ale, color);
+ /* set backdrop drawing color */
+ acf->get_backdrop_color(ac, ale, color);
- /* 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(true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5, color, 1.0f);
+ /* 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(
+ true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5, color, 1.0f);
}
/* name for nla controls expander entries */
static void acf_nla_controls_name(bAnimListElem *UNUSED(ale), char *name)
{
- BLI_strncpy(name, IFACE_("NLA Strip Controls"), ANIM_CHAN_NAME_SIZE);
+ BLI_strncpy(name, IFACE_("NLA Strip Controls"), ANIM_CHAN_NAME_SIZE);
}
/* check if some setting exists for this channel */
-static bool acf_nla_controls_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
+static bool acf_nla_controls_setting_valid(bAnimContext *UNUSED(ac),
+ bAnimListElem *UNUSED(ale),
+ eAnimChannel_Settings setting)
{
- /* for now, all settings are supported, though some are only conditionally */
- switch (setting) {
- /* supported */
- case ACHANNEL_SETTING_EXPAND:
- return true;
+ /* for now, all settings are supported, though some are only conditionally */
+ switch (setting) {
+ /* supported */
+ case ACHANNEL_SETTING_EXPAND:
+ return true;
- // TODO: selected?
+ // TODO: selected?
- default: /* unsupported */
- return false;
- }
+ default: /* unsupported */
+ return false;
+ }
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_nla_controls_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_nla_controls_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- *neg = true;
- return ADT_NLA_SKEYS_COLLAPSED;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ *neg = true;
+ return ADT_NLA_SKEYS_COLLAPSED;
- default:
- /* this shouldn't happen */
- return 0;
- }
+ default:
+ /* this shouldn't happen */
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_nla_controls_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
+static void *acf_nla_controls_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings UNUSED(setting),
+ short *type)
{
- AnimData *adt = (AnimData *)ale->data;
+ AnimData *adt = (AnimData *)ale->data;
- /* all flags are just in adt->flag for now... */
- return GET_ACF_FLAG_PTR(adt->flag, type);
+ /* all flags are just in adt->flag for now... */
+ return GET_ACF_FLAG_PTR(adt->flag, type);
}
static int acf_nla_controls_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_NLA;
+ return ICON_NLA;
}
/* NLA Control FCurves Expander type define */
-static bAnimChannelType ACF_NLACONTROLS =
-{
- "NLA Controls Expander", /* type name */
- ACHANNEL_ROLE_EXPANDER, /* role */
-
- acf_nla_controls_color, /* backdrop color */
- acf_nla_controls_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
- acf_generic_group_offset, /* offset */
-
- acf_nla_controls_name, /* name */
- NULL, /* name prop */
- acf_nla_controls_icon, /* icon */
-
- acf_nla_controls_setting_valid, /* has setting */
- acf_nla_controls_setting_flag, /* flag for setting */
- acf_nla_controls_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_NLACONTROLS = {
+ "NLA Controls Expander", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_nla_controls_color, /* backdrop color */
+ acf_nla_controls_backdrop, /* backdrop */
+ acf_generic_indention_0, /* indent level */
+ acf_generic_group_offset, /* offset */
+
+ acf_nla_controls_name, /* name */
+ NULL, /* name prop */
+ acf_nla_controls_icon, /* icon */
+
+ acf_nla_controls_setting_valid, /* has setting */
+ acf_nla_controls_setting_flag, /* flag for setting */
+ acf_nla_controls_setting_ptr, /* pointer for setting */
};
-
/* NLA Control F-Curve -------------------------------- */
/* name for nla control fcurve entries */
static void acf_nla_curve_name(bAnimListElem *ale, char *name)
{
- NlaStrip *strip = ale->owner;
- FCurve *fcu = ale->data;
- PropertyRNA *prop;
+ NlaStrip *strip = ale->owner;
+ FCurve *fcu = ale->data;
+ PropertyRNA *prop;
- /* try to get RNA property that this shortened path (relative to the strip) refers to */
- prop = RNA_struct_type_find_property(&RNA_NlaStrip, fcu->rna_path);
- if (prop) {
- /* "name" of this strip displays the UI identifier + the name of the NlaStrip */
- BLI_snprintf(name, 256, "%s (%s)", RNA_property_ui_name(prop), strip->name);
- }
- else {
- /* unknown property... */
- BLI_snprintf(name, 256, "%s[%d]", fcu->rna_path, fcu->array_index);
- }
+ /* try to get RNA property that this shortened path (relative to the strip) refers to */
+ prop = RNA_struct_type_find_property(&RNA_NlaStrip, fcu->rna_path);
+ if (prop) {
+ /* "name" of this strip displays the UI identifier + the name of the NlaStrip */
+ BLI_snprintf(name, 256, "%s (%s)", RNA_property_ui_name(prop), strip->name);
+ }
+ else {
+ /* unknown property... */
+ BLI_snprintf(name, 256, "%s[%d]", fcu->rna_path, fcu->array_index);
+ }
}
-
/* NLA Control F-Curve type define */
-static bAnimChannelType ACF_NLACURVE =
-{
- "NLA Control F-Curve", /* type name */
- ACHANNEL_ROLE_CHANNEL, /* role */
-
- acf_generic_channel_color, /* backdrop color */
- acf_generic_channel_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
- acf_generic_group_offset, /* offset */
-
- acf_nla_curve_name, /* name */
- acf_fcurve_name_prop, /* name prop */
- NULL, /* icon */
-
- acf_fcurve_setting_valid, /* has setting */
- acf_fcurve_setting_flag, /* flag for setting */
- acf_fcurve_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_NLACURVE = {
+ "NLA Control F-Curve", /* type name */
+ ACHANNEL_ROLE_CHANNEL, /* role */
+
+ acf_generic_channel_color, /* backdrop color */
+ acf_generic_channel_backdrop, /* backdrop */
+ acf_generic_indention_1, /* indent level */
+ acf_generic_group_offset, /* offset */
+
+ acf_nla_curve_name, /* name */
+ acf_fcurve_name_prop, /* name prop */
+ NULL, /* icon */
+
+ acf_fcurve_setting_valid, /* has setting */
+ acf_fcurve_setting_flag, /* flag for setting */
+ acf_fcurve_setting_ptr, /* pointer for setting */
};
/* Object Action Expander ------------------------------------------- */
@@ -1226,84 +1269,89 @@ static bAnimChannelType ACF_NLACURVE =
// TODO: just get this from RNA?
static int acf_fillactd_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_ACTION;
+ return ICON_ACTION;
}
/* check if some setting exists for this channel */
-static bool acf_fillactd_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
+static bool acf_fillactd_setting_valid(bAnimContext *UNUSED(ac),
+ bAnimListElem *UNUSED(ale),
+ eAnimChannel_Settings setting)
{
- switch (setting) {
- /* only select and expand supported */
- case ACHANNEL_SETTING_SELECT:
- case ACHANNEL_SETTING_EXPAND:
- return true;
+ switch (setting) {
+ /* only select and expand supported */
+ case ACHANNEL_SETTING_SELECT:
+ case ACHANNEL_SETTING_EXPAND:
+ return true;
- default:
- return false;
- }
+ default:
+ return false;
+ }
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_fillactd_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_fillactd_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- *neg = true;
- return ACT_COLLAPSED;
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ *neg = true;
+ return ACT_COLLAPSED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_fillactd_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
+static void *acf_fillactd_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings setting,
+ short *type)
{
- bAction *act = (bAction *)ale->data;
- AnimData *adt = ale->adt;
+ bAction *act = (bAction *)ale->data;
+ AnimData *adt = ale->adt;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_SELECT: /* selected */
- if (adt) {
- return GET_ACF_FLAG_PTR(adt->flag, type);
- }
- return NULL;
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ if (adt) {
+ return GET_ACF_FLAG_PTR(adt->flag, type);
+ }
+ return NULL;
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(act->flag, type);
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(act->flag, type);
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* object action expander type define */
-static bAnimChannelType ACF_FILLACTD =
-{
- "Ob-Action Filler", /* 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_idfill_name_prop, /* name prop */
- acf_fillactd_icon, /* icon */
-
- acf_fillactd_setting_valid, /* has setting */
- acf_fillactd_setting_flag, /* flag for setting */
- acf_fillactd_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_FILLACTD = {
+ "Ob-Action Filler", /* 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_idfill_name_prop, /* name prop */
+ acf_fillactd_icon, /* icon */
+
+ acf_fillactd_setting_valid, /* has setting */
+ acf_fillactd_setting_flag, /* flag for setting */
+ acf_fillactd_setting_ptr, /* pointer for setting */
};
/* Drivers Expander ------------------------------------------- */
@@ -1311,157 +1359,162 @@ static bAnimChannelType ACF_FILLACTD =
// TODO: just get this from RNA?
static int acf_filldrivers_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_DRIVER;
+ return ICON_DRIVER;
}
static void acf_filldrivers_name(bAnimListElem *UNUSED(ale), char *name)
{
- BLI_strncpy(name, IFACE_("Drivers"), ANIM_CHAN_NAME_SIZE);
+ BLI_strncpy(name, IFACE_("Drivers"), ANIM_CHAN_NAME_SIZE);
}
/* check if some setting exists for this channel */
// TODO: this could be made more generic
-static bool acf_filldrivers_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
+static bool acf_filldrivers_setting_valid(bAnimContext *UNUSED(ac),
+ bAnimListElem *UNUSED(ale),
+ eAnimChannel_Settings setting)
{
- switch (setting) {
- /* only expand supported */
- case ACHANNEL_SETTING_EXPAND:
- return true;
+ switch (setting) {
+ /* only expand supported */
+ case ACHANNEL_SETTING_EXPAND:
+ return true;
- default:
- return false;
- }
+ default:
+ return false;
+ }
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_filldrivers_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_filldrivers_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- *neg = true;
- return ADT_DRIVERS_COLLAPSED;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ *neg = true;
+ return ADT_DRIVERS_COLLAPSED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_filldrivers_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
+static void *acf_filldrivers_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings setting,
+ short *type)
{
- AnimData *adt = (AnimData *)ale->data;
+ AnimData *adt = (AnimData *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(adt->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(adt->flag, type);
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* drivers expander type define */
-static bAnimChannelType ACF_FILLDRIVERS =
-{
- "Drivers Filler", /* 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_filldrivers_name, /* name */
- NULL, /* name prop */
- acf_filldrivers_icon, /* icon */
-
- acf_filldrivers_setting_valid, /* has setting */
- acf_filldrivers_setting_flag, /* flag for setting */
- acf_filldrivers_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_FILLDRIVERS = {
+ "Drivers Filler", /* 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_filldrivers_name, /* name */
+ NULL, /* name prop */
+ acf_filldrivers_icon, /* icon */
+
+ acf_filldrivers_setting_valid, /* has setting */
+ acf_filldrivers_setting_flag, /* flag for setting */
+ acf_filldrivers_setting_ptr, /* pointer for setting */
};
-
/* Material Expander ------------------------------------------- */
// TODO: just get this from RNA?
static int acf_dsmat_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_MATERIAL_DATA;
+ return ICON_MATERIAL_DATA;
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dsmat_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_dsmat_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return MA_DS_EXPAND;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return MA_DS_EXPAND;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
static void *acf_dsmat_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
- Material *ma = (Material *)ale->data;
+ Material *ma = (Material *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(ma->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(ma->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 (ma->adt)
- return GET_ACF_FLAG_PTR(ma->adt->flag, type);
- return NULL;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (ma->adt)
+ return GET_ACF_FLAG_PTR(ma->adt->flag, type);
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* material expander type define */
-static bAnimChannelType ACF_DSMAT =
-{
- "Material Data 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_dsmat_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dsmat_setting_flag, /* flag for setting */
- acf_dsmat_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_DSMAT = {
+ "Material Data 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_dsmat_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dsmat_setting_flag, /* flag for setting */
+ acf_dsmat_setting_ptr, /* pointer for setting */
};
/* Light Expander ------------------------------------------- */
@@ -1469,76 +1522,79 @@ static bAnimChannelType ACF_DSMAT =
// TODO: just get this from RNA?
static int acf_dslight_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_LIGHT_DATA;
+ return ICON_LIGHT_DATA;
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dslight_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_dslight_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return LA_DS_EXPAND;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return LA_DS_EXPAND;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_dslight_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
+static void *acf_dslight_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings setting,
+ short *type)
{
- Light *la = (Light *)ale->data;
+ Light *la = (Light *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(la->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(la->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 (la->adt)
- return GET_ACF_FLAG_PTR(la->adt->flag, type);
- return NULL;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (la->adt)
+ return GET_ACF_FLAG_PTR(la->adt->flag, type);
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* light expander type define */
-static bAnimChannelType ACF_DSLIGHT =
-{
- "Light 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_dslight_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dslight_setting_flag, /* flag for setting */
- acf_dslight_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_DSLIGHT = {
+ "Light 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_dslight_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dslight_setting_flag, /* flag for setting */
+ acf_dslight_setting_ptr, /* pointer for setting */
};
/* Texture Expander ------------------------------------------- */
@@ -1546,83 +1602,84 @@ static bAnimChannelType ACF_DSLIGHT =
// TODO: just get this from RNA?
static int acf_dstex_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_TEXTURE_DATA;
+ return ICON_TEXTURE_DATA;
}
/* offset for texture expanders */
// FIXME: soon to be obsolete?
static short acf_dstex_offset(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
{
- return 14; // XXX: simply include this in indention instead?
+ return 14; // XXX: simply include this in indention instead?
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dstex_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_dstex_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return TEX_DS_EXPAND;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return TEX_DS_EXPAND;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
static void *acf_dstex_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
- Tex *tex = (Tex *)ale->data;
+ Tex *tex = (Tex *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(tex->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(tex->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 (tex->adt)
- return GET_ACF_FLAG_PTR(tex->adt->flag, type);
- return NULL;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (tex->adt)
+ return GET_ACF_FLAG_PTR(tex->adt->flag, type);
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* texture expander type define */
-static bAnimChannelType ACF_DSTEX =
-{
- "Texture Data 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_dstex_offset, /* offset */
-
- acf_generic_idblock_name, /* name */
- acf_generic_idfill_name_prop, /* name prop */
- acf_dstex_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dstex_setting_flag, /* flag for setting */
- acf_dstex_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_DSTEX = {
+ "Texture Data 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_dstex_offset, /* offset */
+
+ acf_generic_idblock_name, /* name */
+ acf_generic_idfill_name_prop, /* name prop */
+ acf_dstex_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dstex_setting_flag, /* flag for setting */
+ acf_dstex_setting_ptr, /* pointer for setting */
};
/* Camera Expander ------------------------------------------- */
@@ -1630,81 +1687,82 @@ static bAnimChannelType ACF_DSTEX =
// TODO: just get this from RNA?
static int acf_dscachefile_icon(bAnimListElem *ale)
{
- UNUSED_VARS(ale);
- return ICON_FILE;
+ UNUSED_VARS(ale);
+ return ICON_FILE;
}
/* get the appropriate flag(s) for the setting when it is valid */
static int acf_dscachefile_setting_flag(bAnimContext *ac, eAnimChannel_Settings setting, bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return CACHEFILE_DS_EXPAND;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return CACHEFILE_DS_EXPAND;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
- UNUSED_VARS(ac);
+ UNUSED_VARS(ac);
}
/* get pointer to the setting */
-static void *acf_dscachefile_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
+static void *acf_dscachefile_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings setting,
+ short *type)
{
- CacheFile *cache_file = (CacheFile *)ale->data;
+ CacheFile *cache_file = (CacheFile *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(cache_file->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(cache_file->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 (cache_file->adt) {
- return GET_ACF_FLAG_PTR(cache_file->adt->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 (cache_file->adt) {
+ return GET_ACF_FLAG_PTR(cache_file->adt->flag, type);
+ }
- return NULL;
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* CacheFile expander type define. */
-static bAnimChannelType ACF_DSCACHEFILE =
-{
- "Cache File 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_idfill_name_prop, /* name prop */
- acf_dscachefile_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dscachefile_setting_flag, /* flag for setting */
- acf_dscachefile_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_DSCACHEFILE = {
+ "Cache File 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_idfill_name_prop, /* name prop */
+ acf_dscachefile_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dscachefile_setting_flag, /* flag for setting */
+ acf_dscachefile_setting_ptr, /* pointer for setting */
};
/* Camera Expander ------------------------------------------- */
@@ -1712,80 +1770,81 @@ static bAnimChannelType ACF_DSCACHEFILE =
// TODO: just get this from RNA?
static int acf_dscam_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_CAMERA_DATA;
+ return ICON_CAMERA_DATA;
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dscam_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_dscam_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return CAM_DS_EXPAND;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return CAM_DS_EXPAND;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- case ACHANNEL_SETTING_ALWAYS_VISIBLE:
- return ADT_CURVES_ALWAYS_VISIBLE;
+ case ACHANNEL_SETTING_ALWAYS_VISIBLE:
+ return ADT_CURVES_ALWAYS_VISIBLE;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
static void *acf_dscam_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
- Camera *ca = (Camera *)ale->data;
+ Camera *ca = (Camera *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(ca->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(ca->flag, type);
- case ACHANNEL_SETTING_SELECT: /* selected */
- case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
- case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
- case ACHANNEL_SETTING_ALWAYS_VISIBLE:
- if (ca->adt)
- return GET_ACF_FLAG_PTR(ca->adt->flag, type);
- return NULL;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ case ACHANNEL_SETTING_ALWAYS_VISIBLE:
+ if (ca->adt)
+ return GET_ACF_FLAG_PTR(ca->adt->flag, type);
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* camera expander type define */
-static bAnimChannelType ACF_DSCAM =
-{
- "Camera 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_idfill_name_prop, /* name prop */
- acf_dscam_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dscam_setting_flag, /* flag for setting */
- acf_dscam_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_DSCAM = {
+ "Camera 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_idfill_name_prop, /* name prop */
+ acf_dscam_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dscam_setting_flag, /* flag for setting */
+ acf_dscam_setting_ptr, /* pointer for setting */
};
/* Curve Expander ------------------------------------------- */
@@ -1793,86 +1852,87 @@ static bAnimChannelType ACF_DSCAM =
// TODO: just get this from RNA?
static int acf_dscur_icon(bAnimListElem *ale)
{
- Curve *cu = (Curve *)ale->data;
- short obtype = BKE_curve_type_get(cu);
+ Curve *cu = (Curve *)ale->data;
+ short obtype = BKE_curve_type_get(cu);
- switch (obtype) {
- case OB_FONT:
- return ICON_FONT_DATA;
- case OB_SURF:
- return ICON_SURFACE_DATA;
- default:
- return ICON_CURVE_DATA;
- }
+ switch (obtype) {
+ case OB_FONT:
+ return ICON_FONT_DATA;
+ case OB_SURF:
+ return ICON_SURFACE_DATA;
+ default:
+ return ICON_CURVE_DATA;
+ }
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dscur_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_dscur_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return CU_DS_EXPAND;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return CU_DS_EXPAND;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
static void *acf_dscur_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
- Curve *cu = (Curve *)ale->data;
+ Curve *cu = (Curve *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(cu->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(cu->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 (cu->adt)
- return GET_ACF_FLAG_PTR(cu->adt->flag, type);
- return NULL;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (cu->adt)
+ return GET_ACF_FLAG_PTR(cu->adt->flag, type);
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* curve expander type define */
-static bAnimChannelType ACF_DSCUR =
-{
- "Curve 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_dscur_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dscur_setting_flag, /* flag for setting */
- acf_dscur_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_DSCUR = {
+ "Curve 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_dscur_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dscur_setting_flag, /* flag for setting */
+ acf_dscur_setting_ptr, /* pointer for setting */
};
/* Shape Key Expander ------------------------------------------- */
@@ -1880,76 +1940,77 @@ static bAnimChannelType ACF_DSCUR =
// TODO: just get this from RNA?
static int acf_dsskey_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_SHAPEKEY_DATA;
+ return ICON_SHAPEKEY_DATA;
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dsskey_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_dsskey_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return KEY_DS_EXPAND;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return KEY_DS_EXPAND;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
static void *acf_dsskey_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
- Key *key = (Key *)ale->data;
+ Key *key = (Key *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(key->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(key->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 (key->adt)
- return GET_ACF_FLAG_PTR(key->adt->flag, type);
- return NULL;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (key->adt)
+ return GET_ACF_FLAG_PTR(key->adt->flag, type);
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* shapekey expander type define */
-static bAnimChannelType ACF_DSSKEY =
-{
- "Shape Key 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_dsskey_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dsskey_setting_flag, /* flag for setting */
- acf_dsskey_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_DSSKEY = {
+ "Shape Key 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_dsskey_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dsskey_setting_flag, /* flag for setting */
+ acf_dsskey_setting_ptr, /* pointer for setting */
};
/* World Expander ------------------------------------------- */
@@ -1957,76 +2018,77 @@ static bAnimChannelType ACF_DSSKEY =
// TODO: just get this from RNA?
static int acf_dswor_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_WORLD_DATA;
+ return ICON_WORLD_DATA;
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dswor_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_dswor_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return WO_DS_EXPAND;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return WO_DS_EXPAND;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
static void *acf_dswor_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
- World *wo = (World *)ale->data;
+ World *wo = (World *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(wo->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(wo->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 (wo->adt)
- return GET_ACF_FLAG_PTR(wo->adt->flag, type);
- return NULL;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (wo->adt)
+ return GET_ACF_FLAG_PTR(wo->adt->flag, type);
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* world expander type define */
-static bAnimChannelType ACF_DSWOR =
-{
- "World 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_idfill_name_prop, /* name prop */
- acf_dswor_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dswor_setting_flag, /* flag for setting */
- acf_dswor_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_DSWOR = {
+ "World 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_idfill_name_prop, /* name prop */
+ acf_dswor_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dswor_setting_flag, /* flag for setting */
+ acf_dswor_setting_ptr, /* pointer for setting */
};
/* Particle Expander ------------------------------------------- */
@@ -2034,76 +2096,77 @@ static bAnimChannelType ACF_DSWOR =
// TODO: just get this from RNA?
static int acf_dspart_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_PARTICLE_DATA;
+ return ICON_PARTICLE_DATA;
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return PART_DS_EXPAND;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return PART_DS_EXPAND;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
static void *acf_dspart_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
- ParticleSettings *part = (ParticleSettings *)ale->data;
+ ParticleSettings *part = (ParticleSettings *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(part->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(part->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 (part->adt)
- return GET_ACF_FLAG_PTR(part->adt->flag, type);
- return NULL;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (part->adt)
+ return GET_ACF_FLAG_PTR(part->adt->flag, type);
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* particle expander type define */
-static bAnimChannelType ACF_DSPART =
-{
- "Particle Data 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_dspart_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dspart_setting_flag, /* flag for setting */
- acf_dspart_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_DSPART = {
+ "Particle Data 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_dspart_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dspart_setting_flag, /* flag for setting */
+ acf_dspart_setting_ptr, /* pointer for setting */
};
/* MetaBall Expander ------------------------------------------- */
@@ -2111,76 +2174,79 @@ static bAnimChannelType ACF_DSPART =
// TODO: just get this from RNA?
static int acf_dsmball_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_META_DATA;
+ return ICON_META_DATA;
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dsmball_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_dsmball_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return MB_DS_EXPAND;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return MB_DS_EXPAND;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_dsmball_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
+static void *acf_dsmball_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings setting,
+ short *type)
{
- MetaBall *mb = (MetaBall *)ale->data;
+ MetaBall *mb = (MetaBall *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(mb->flag2, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(mb->flag2, type);
- case ACHANNEL_SETTING_SELECT: /* selected */
- case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
- case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
- if (mb->adt)
- return GET_ACF_FLAG_PTR(mb->adt->flag, type);
- return NULL;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (mb->adt)
+ return GET_ACF_FLAG_PTR(mb->adt->flag, type);
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* metaball expander type define */
-static bAnimChannelType ACF_DSMBALL =
-{
- "Metaball 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_dsmball_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dsmball_setting_flag, /* flag for setting */
- acf_dsmball_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_DSMBALL = {
+ "Metaball 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_dsmball_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dsmball_setting_flag, /* flag for setting */
+ acf_dsmball_setting_ptr, /* pointer for setting */
};
/* Armature Expander ------------------------------------------- */
@@ -2188,76 +2254,77 @@ static bAnimChannelType ACF_DSMBALL =
// TODO: just get this from RNA?
static int acf_dsarm_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_ARMATURE_DATA;
+ return ICON_ARMATURE_DATA;
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dsarm_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_dsarm_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return ARM_DS_EXPAND;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return ARM_DS_EXPAND;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
static void *acf_dsarm_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
- bArmature *arm = (bArmature *)ale->data;
+ bArmature *arm = (bArmature *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(arm->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(arm->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 (arm->adt)
- return GET_ACF_FLAG_PTR(arm->adt->flag, type);
- return NULL;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (arm->adt)
+ return GET_ACF_FLAG_PTR(arm->adt->flag, type);
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* metaball expander type define */
-static bAnimChannelType ACF_DSARM =
-{
- "Armature 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_dsarm_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dsarm_setting_flag, /* flag for setting */
- acf_dsarm_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_DSARM = {
+ "Armature 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_dsarm_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dsarm_setting_flag, /* flag for setting */
+ acf_dsarm_setting_ptr, /* pointer for setting */
};
/* NodeTree Expander ------------------------------------------- */
@@ -2265,87 +2332,90 @@ static bAnimChannelType ACF_DSARM =
// TODO: just get this from RNA?
static int acf_dsntree_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_NODETREE;
+ return ICON_NODETREE;
}
/* offset for nodetree expanders */
static short acf_dsntree_offset(bAnimContext *ac, bAnimListElem *ale)
{
- bNodeTree *ntree = (bNodeTree *)ale->data;
- short offset = acf_generic_basic_offset(ac, ale);
+ bNodeTree *ntree = (bNodeTree *)ale->data;
+ short offset = acf_generic_basic_offset(ac, ale);
- offset += acf_nodetree_rootType_offset(ntree);
+ offset += acf_nodetree_rootType_offset(ntree);
- return offset;
+ return offset;
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dsntree_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_dsntree_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return NTREE_DS_EXPAND;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return NTREE_DS_EXPAND;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_dsntree_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
+static void *acf_dsntree_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings setting,
+ short *type)
{
- bNodeTree *ntree = (bNodeTree *)ale->data;
+ bNodeTree *ntree = (bNodeTree *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(ntree->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(ntree->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 (ntree->adt)
- return GET_ACF_FLAG_PTR(ntree->adt->flag, type);
- return NULL;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (ntree->adt)
+ return GET_ACF_FLAG_PTR(ntree->adt->flag, type);
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* node tree expander type define */
-static bAnimChannelType ACF_DSNTREE =
-{
- "Node Tree 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_dsntree_offset, /* offset */
-
- acf_generic_idblock_name, /* name */
- acf_generic_idblock_name_prop, /* name prop */
- acf_dsntree_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dsntree_setting_flag, /* flag for setting */
- acf_dsntree_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_DSNTREE = {
+ "Node Tree 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_dsntree_offset, /* offset */
+
+ acf_generic_idblock_name, /* name */
+ acf_generic_idblock_name_prop, /* name prop */
+ acf_dsntree_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dsntree_setting_flag, /* flag for setting */
+ acf_dsntree_setting_ptr, /* pointer for setting */
};
/* LineStyle Expander ------------------------------------------- */
@@ -2353,76 +2423,79 @@ static bAnimChannelType ACF_DSNTREE =
/* TODO: just get this from RNA? */
static int acf_dslinestyle_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_LINE_DATA;
+ return ICON_LINE_DATA;
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dslinestyle_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_dslinestyle_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return LS_DS_EXPAND;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return LS_DS_EXPAND;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_dslinestyle_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
+static void *acf_dslinestyle_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings setting,
+ short *type)
{
- FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ale->data;
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(linestyle->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(linestyle->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 (linestyle->adt)
- return GET_ACF_FLAG_PTR(linestyle->adt->flag, type);
- return NULL;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (linestyle->adt)
+ return GET_ACF_FLAG_PTR(linestyle->adt->flag, type);
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* node tree expander type define */
-static bAnimChannelType ACF_DSLINESTYLE =
-{
- "Line Style 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_dslinestyle_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dslinestyle_setting_flag, /* flag for setting */
- acf_dslinestyle_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_DSLINESTYLE = {
+ "Line Style 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_dslinestyle_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dslinestyle_setting_flag, /* flag for setting */
+ acf_dslinestyle_setting_ptr, /* pointer for setting */
};
/* Mesh Expander ------------------------------------------- */
@@ -2430,76 +2503,78 @@ static bAnimChannelType ACF_DSLINESTYLE =
// TODO: just get this from RNA?
static int acf_dsmesh_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_MESH_DATA;
+ return ICON_MESH_DATA;
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dsmesh_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_dsmesh_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return ME_DS_EXPAND;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return ME_DS_EXPAND;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
static void *acf_dsmesh_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
- Mesh *me = (Mesh *)ale->data;
+ Mesh *me = (Mesh *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(me->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(me->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 (me->adt)
- return GET_ACF_FLAG_PTR(me->adt->flag, type);
- return NULL;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (me->adt)
+ return GET_ACF_FLAG_PTR(me->adt->flag, type);
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* node tree expander type define */
-static bAnimChannelType ACF_DSMESH =
-{
- "Mesh Expander", /* type name */
- ACHANNEL_ROLE_EXPANDER, /* role */
-
- acf_generic_dataexpand_color, /* backdrop color */
- acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */ // XXX this only works for compositing
- acf_generic_basic_offset, /* offset */
-
- acf_generic_idblock_name, /* name */
- acf_generic_idblock_name_prop, /* name prop */
- acf_dsmesh_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dsmesh_setting_flag, /* flag for setting */
- acf_dsmesh_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_DSMESH = {
+ "Mesh Expander", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_generic_dataexpand_color, /* backdrop color */
+ acf_generic_dataexpand_backdrop, /* backdrop */
+ acf_generic_indention_1,
+ /* indent level */ // XXX this only works for compositing
+ acf_generic_basic_offset, /* offset */
+
+ acf_generic_idblock_name, /* name */
+ acf_generic_idblock_name_prop, /* name prop */
+ acf_dsmesh_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dsmesh_setting_flag, /* flag for setting */
+ acf_dsmesh_setting_ptr, /* pointer for setting */
};
/* Lattice Expander ------------------------------------------- */
@@ -2507,76 +2582,78 @@ static bAnimChannelType ACF_DSMESH =
// TODO: just get this from RNA?
static int acf_dslat_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_LATTICE_DATA;
+ return ICON_LATTICE_DATA;
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dslat_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_dslat_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return LT_DS_EXPAND;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return LT_DS_EXPAND;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
static void *acf_dslat_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
- Lattice *lt = (Lattice *)ale->data;
+ Lattice *lt = (Lattice *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(lt->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(lt->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 (lt->adt)
- return GET_ACF_FLAG_PTR(lt->adt->flag, type);
- return NULL;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (lt->adt)
+ return GET_ACF_FLAG_PTR(lt->adt->flag, type);
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* node tree expander type define */
-static bAnimChannelType ACF_DSLAT =
-{
- "Lattice Expander", /* type name */
- ACHANNEL_ROLE_EXPANDER, /* role */
-
- acf_generic_dataexpand_color, /* backdrop color */
- acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */ // XXX this only works for compositing
- acf_generic_basic_offset, /* offset */
-
- acf_generic_idblock_name, /* name */
- acf_generic_idblock_name_prop, /* name prop */
- acf_dslat_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dslat_setting_flag, /* flag for setting */
- acf_dslat_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_DSLAT = {
+ "Lattice Expander", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_generic_dataexpand_color, /* backdrop color */
+ acf_generic_dataexpand_backdrop, /* backdrop */
+ acf_generic_indention_1,
+ /* indent level */ // XXX this only works for compositing
+ acf_generic_basic_offset, /* offset */
+
+ acf_generic_idblock_name, /* name */
+ acf_generic_idblock_name_prop, /* name prop */
+ acf_dslat_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dslat_setting_flag, /* flag for setting */
+ acf_dslat_setting_ptr, /* pointer for setting */
};
/* Speaker Expander ------------------------------------------- */
@@ -2584,76 +2661,77 @@ static bAnimChannelType ACF_DSLAT =
// TODO: just get this from RNA?
static int acf_dsspk_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_SPEAKER;
+ return ICON_SPEAKER;
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dsspk_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_dsspk_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return SPK_DS_EXPAND;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return SPK_DS_EXPAND;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
static void *acf_dsspk_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
- Speaker *spk = (Speaker *)ale->data;
+ Speaker *spk = (Speaker *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(spk->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(spk->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 (spk->adt)
- return GET_ACF_FLAG_PTR(spk->adt->flag, type);
- return NULL;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (spk->adt)
+ return GET_ACF_FLAG_PTR(spk->adt->flag, type);
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* speaker expander type define */
-static bAnimChannelType ACF_DSSPK =
-{
- "Speaker 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_dsspk_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dsspk_setting_flag, /* flag for setting */
- acf_dsspk_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_DSSPK = {
+ "Speaker 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_dsspk_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dsspk_setting_flag, /* flag for setting */
+ acf_dsspk_setting_ptr, /* pointer for setting */
};
/* GPencil Expander ------------------------------------------- */
@@ -2661,76 +2739,79 @@ static bAnimChannelType ACF_DSSPK =
// TODO: just get this from RNA?
static int acf_dsgpencil_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_GREASEPENCIL;
+ return ICON_GREASEPENCIL;
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dsgpencil_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_dsgpencil_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GP_DATA_EXPAND;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GP_DATA_EXPAND;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_dsgpencil_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
+static void *acf_dsgpencil_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings setting,
+ short *type)
{
- bGPdata *gpd = (bGPdata *)ale->data;
+ bGPdata *gpd = (bGPdata *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(gpd->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(gpd->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 (gpd->adt)
- return GET_ACF_FLAG_PTR(gpd->adt->flag, type);
- return NULL;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (gpd->adt)
+ return GET_ACF_FLAG_PTR(gpd->adt->flag, type);
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* grease pencil expander type define */
-static bAnimChannelType ACF_DSGPENCIL =
-{
- "GPencil DS 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_dsgpencil_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dsgpencil_setting_flag, /* flag for setting */
- acf_dsgpencil_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_DSGPENCIL = {
+ "GPencil DS 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_dsgpencil_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dsgpencil_setting_flag, /* flag for setting */
+ acf_dsgpencil_setting_ptr, /* pointer for setting */
};
/* World Expander ------------------------------------------- */
@@ -2738,77 +2819,80 @@ static bAnimChannelType ACF_DSGPENCIL =
// TODO: just get this from RNA?
static int acf_dsmclip_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_SEQUENCE;
+ return ICON_SEQUENCE;
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dsmclip_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_dsmclip_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return MCLIP_DATA_EXPAND;
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return MCLIP_DATA_EXPAND;
- case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
- return ADT_NLA_EVAL_OFF;
+ 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_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return ADT_UI_SELECTED;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_dsmclip_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
+static void *acf_dsmclip_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings setting,
+ short *type)
{
- MovieClip *clip = (MovieClip *)ale->data;
+ MovieClip *clip = (MovieClip *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(clip->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(clip->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 (clip->adt != NULL) {
- return GET_ACF_FLAG_PTR(clip->adt->flag, type);
- }
- return NULL;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (clip->adt != NULL) {
+ return GET_ACF_FLAG_PTR(clip->adt->flag, type);
+ }
+ return NULL;
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* world expander type define */
-static bAnimChannelType ACF_DSMCLIP =
-{
- "Movieclip 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_idfill_name_prop, /* name prop */
- acf_dsmclip_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dsmclip_setting_flag, /* flag for setting */
- acf_dsmclip_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_DSMCLIP = {
+ "Movieclip 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_idfill_name_prop, /* name prop */
+ acf_dsmclip_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dsmclip_setting_flag, /* flag for setting */
+ acf_dsmclip_setting_ptr, /* pointer for setting */
};
/* ShapeKey Entry ------------------------------------------- */
@@ -2816,107 +2900,112 @@ static bAnimChannelType ACF_DSMCLIP =
/* name for ShapeKey */
static void acf_shapekey_name(bAnimListElem *ale, char *name)
{
- KeyBlock *kb = (KeyBlock *)ale->data;
+ KeyBlock *kb = (KeyBlock *)ale->data;
- /* just copy the name... */
- if (kb && name) {
- /* if the KeyBlock had a name, use it, otherwise use the index */
- if (kb->name[0])
- BLI_strncpy(name, kb->name, ANIM_CHAN_NAME_SIZE);
- else
- BLI_snprintf(name, ANIM_CHAN_NAME_SIZE, IFACE_("Key %d"), ale->index);
- }
+ /* just copy the name... */
+ if (kb && name) {
+ /* if the KeyBlock had a name, use it, otherwise use the index */
+ if (kb->name[0])
+ BLI_strncpy(name, kb->name, ANIM_CHAN_NAME_SIZE);
+ else
+ BLI_snprintf(name, ANIM_CHAN_NAME_SIZE, IFACE_("Key %d"), ale->index);
+ }
}
/* name property for ShapeKey entries */
static bool acf_shapekey_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
- KeyBlock *kb = (KeyBlock *)ale->data;
+ KeyBlock *kb = (KeyBlock *)ale->data;
- /* if the KeyBlock had a name, use it, otherwise use the index */
- if (kb && kb->name[0]) {
- RNA_pointer_create(ale->id, &RNA_ShapeKey, kb, ptr);
- *prop = RNA_struct_name_property(ptr->type);
+ /* if the KeyBlock had a name, use it, otherwise use the index */
+ if (kb && kb->name[0]) {
+ RNA_pointer_create(ale->id, &RNA_ShapeKey, kb, ptr);
+ *prop = RNA_struct_name_property(ptr->type);
- return (*prop != NULL);
- }
+ return (*prop != NULL);
+ }
- return false;
+ return false;
}
/* check if some setting exists for this channel */
-static bool acf_shapekey_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
+static bool acf_shapekey_setting_valid(bAnimContext *UNUSED(ac),
+ bAnimListElem *UNUSED(ale),
+ eAnimChannel_Settings setting)
{
- switch (setting) {
- case ACHANNEL_SETTING_SELECT: /* selected */
- case ACHANNEL_SETTING_MUTE: /* muted */
- case ACHANNEL_SETTING_PROTECT: /* protected */
- return true;
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted */
+ case ACHANNEL_SETTING_PROTECT: /* protected */
+ return true;
- /* nothing else is supported */
- default:
- return false;
- }
+ /* nothing else is supported */
+ default:
+ return false;
+ }
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_shapekey_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_shapekey_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_MUTE: /* mute */
- return KEYBLOCK_MUTE;
+ switch (setting) {
+ case ACHANNEL_SETTING_MUTE: /* mute */
+ return KEYBLOCK_MUTE;
- case ACHANNEL_SETTING_SELECT: /* selected */
- return KEYBLOCK_SEL;
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return KEYBLOCK_SEL;
- case ACHANNEL_SETTING_PROTECT: /* locked */
- return KEYBLOCK_LOCKED;
+ case ACHANNEL_SETTING_PROTECT: /* locked */
+ return KEYBLOCK_LOCKED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_shapekey_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
+static void *acf_shapekey_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings setting,
+ short *type)
{
- KeyBlock *kb = (KeyBlock *)ale->data;
+ KeyBlock *kb = (KeyBlock *)ale->data;
- /* clear extra return data first */
- *type = 0;
+ /* clear extra return data first */
+ *type = 0;
- switch (setting) {
- case ACHANNEL_SETTING_SELECT: /* selected */
- case ACHANNEL_SETTING_MUTE: /* muted */
- case ACHANNEL_SETTING_PROTECT: /* protected */
- return GET_ACF_FLAG_PTR(kb->flag, type);
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted */
+ case ACHANNEL_SETTING_PROTECT: /* protected */
+ return GET_ACF_FLAG_PTR(kb->flag, type);
- default: /* unsupported */
- return NULL;
- }
+ default: /* unsupported */
+ return NULL;
+ }
}
/* shapekey expander type define */
-static bAnimChannelType ACF_SHAPEKEY =
-{
- "Shape Key", /* type name */
- ACHANNEL_ROLE_CHANNEL, /* role */
-
- acf_generic_channel_color, /* backdrop color */
- acf_generic_channel_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
- acf_generic_basic_offset, /* offset */
-
- acf_shapekey_name, /* name */
- acf_shapekey_name_prop, /* name prop */
- NULL, /* icon */
-
- acf_shapekey_setting_valid, /* has setting */
- acf_shapekey_setting_flag, /* flag for setting */
- acf_shapekey_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_SHAPEKEY = {
+ "Shape Key", /* type name */
+ ACHANNEL_ROLE_CHANNEL, /* role */
+
+ acf_generic_channel_color, /* backdrop color */
+ acf_generic_channel_backdrop, /* backdrop */
+ acf_generic_indention_0, /* indent level */
+ acf_generic_basic_offset, /* offset */
+
+ acf_shapekey_name, /* name */
+ acf_shapekey_name_prop, /* name prop */
+ NULL, /* icon */
+
+ acf_shapekey_setting_valid, /* has setting */
+ acf_shapekey_setting_flag, /* flag for setting */
+ acf_shapekey_setting_ptr, /* pointer for setting */
};
/* GPencil Datablock ------------------------------------------- */
@@ -2924,76 +3013,79 @@ static bAnimChannelType ACF_SHAPEKEY =
/* get backdrop color for gpencil datablock widget */
static void acf_gpd_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
{
- /* these are ID-blocks, but not exactly standalone... */
- UI_GetThemeColorShade3fv(TH_DOPESHEET_CHANNELSUBOB, 20, r_color);
+ /* these are ID-blocks, but not exactly standalone... */
+ UI_GetThemeColorShade3fv(TH_DOPESHEET_CHANNELSUBOB, 20, r_color);
}
// TODO: just get this from RNA?
static int acf_gpd_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_GREASEPENCIL;
+ return ICON_GREASEPENCIL;
}
/* check if some setting exists for this channel */
-static bool acf_gpd_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
+static bool acf_gpd_setting_valid(bAnimContext *UNUSED(ac),
+ bAnimListElem *UNUSED(ale),
+ eAnimChannel_Settings setting)
{
- switch (setting) {
- /* only select and expand supported */
- case ACHANNEL_SETTING_SELECT:
- case ACHANNEL_SETTING_EXPAND:
- return true;
+ switch (setting) {
+ /* only select and expand supported */
+ case ACHANNEL_SETTING_SELECT:
+ case ACHANNEL_SETTING_EXPAND:
+ return true;
- default:
- return false;
- }
+ default:
+ return false;
+ }
}
/* get the appropriate flag(s) for the setting when it is valid */
static int acf_gpd_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_SELECT: /* selected */
- return AGRP_SELECTED;
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return AGRP_SELECTED;
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GP_DATA_EXPAND;
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GP_DATA_EXPAND;
- default:
- /* these shouldn't happen */
- return 0;
- }
+ default:
+ /* these shouldn't happen */
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_gpd_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
+static void *acf_gpd_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings UNUSED(setting),
+ short *type)
{
- bGPdata *gpd = (bGPdata *)ale->data;
+ bGPdata *gpd = (bGPdata *)ale->data;
- /* all flags are just in gpd->flag for now... */
- return GET_ACF_FLAG_PTR(gpd->flag, type);
+ /* all flags are just in gpd->flag for now... */
+ return GET_ACF_FLAG_PTR(gpd->flag, type);
}
/* gpencil datablock type define */
-static bAnimChannelType ACF_GPD =
-{
- "GPencil Datablock", /* type name */
- ACHANNEL_ROLE_EXPANDER, /* role */
-
- acf_gpd_color, /* backdrop color */
- acf_group_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
- acf_generic_group_offset, /* offset */
-
- acf_generic_idblock_name, /* name */
- acf_generic_idfill_name_prop, /* name prop */
- acf_gpd_icon, /* icon */
-
- acf_gpd_setting_valid, /* has setting */
- acf_gpd_setting_flag, /* flag for setting */
- acf_gpd_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_GPD = {
+ "GPencil Datablock", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_gpd_color, /* backdrop color */
+ acf_group_backdrop, /* backdrop */
+ acf_generic_indention_0, /* indent level */
+ acf_generic_group_offset, /* offset */
+
+ acf_generic_idblock_name, /* name */
+ acf_generic_idfill_name_prop, /* name prop */
+ acf_gpd_icon, /* icon */
+
+ acf_gpd_setting_valid, /* has setting */
+ acf_gpd_setting_flag, /* flag for setting */
+ acf_gpd_setting_ptr, /* pointer for setting */
};
/* GPencil Layer ------------------------------------------- */
@@ -3001,170 +3093,177 @@ static bAnimChannelType ACF_GPD =
/* name for grease pencil layer entries */
static void acf_gpl_name(bAnimListElem *ale, char *name)
{
- bGPDlayer *gpl = (bGPDlayer *)ale->data;
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
- if (gpl && name)
- BLI_strncpy(name, gpl->info, ANIM_CHAN_NAME_SIZE);
+ if (gpl && name)
+ BLI_strncpy(name, gpl->info, ANIM_CHAN_NAME_SIZE);
}
/* name property for grease pencil layer entries */
static bool acf_gpl_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
- if (ale->data) {
- RNA_pointer_create(ale->id, &RNA_GPencilLayer, ale->data, ptr);
- *prop = RNA_struct_name_property(ptr->type);
+ if (ale->data) {
+ RNA_pointer_create(ale->id, &RNA_GPencilLayer, ale->data, ptr);
+ *prop = RNA_struct_name_property(ptr->type);
- return (*prop != NULL);
- }
+ return (*prop != NULL);
+ }
- return false;
+ return false;
}
/* check if some setting exists for this channel */
-static bool acf_gpl_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
+static bool acf_gpl_setting_valid(bAnimContext *UNUSED(ac),
+ bAnimListElem *UNUSED(ale),
+ eAnimChannel_Settings setting)
{
- switch (setting) {
- /* unsupported */
- case ACHANNEL_SETTING_EXPAND: /* gpencil layers are more like F-Curves than groups */
- case ACHANNEL_SETTING_SOLO: /* nla editor only */
- return false;
+ switch (setting) {
+ /* unsupported */
+ case ACHANNEL_SETTING_EXPAND: /* gpencil layers are more like F-Curves than groups */
+ case ACHANNEL_SETTING_SOLO: /* nla editor only */
+ return false;
- /* always available */
- default:
- return true;
- }
+ /* always available */
+ default:
+ return true;
+ }
}
/* get the appropriate flag(s) for the setting when it is valid */
static int acf_gpl_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_SELECT: /* selected */
- return GP_LAYER_SELECT;
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return GP_LAYER_SELECT;
- case ACHANNEL_SETTING_MUTE: /* animation muting - similar to frame lock... */
- return GP_LAYER_FRAMELOCK;
+ case ACHANNEL_SETTING_MUTE: /* animation muting - similar to frame lock... */
+ return GP_LAYER_FRAMELOCK;
- case ACHANNEL_SETTING_VISIBLE: /* visibility of the layers (NOT muting) */
- *neg = true;
- return GP_LAYER_HIDE;
+ case ACHANNEL_SETTING_VISIBLE: /* visibility of the layers (NOT muting) */
+ *neg = true;
+ return GP_LAYER_HIDE;
- case ACHANNEL_SETTING_PROTECT: /* protected */
- return GP_LAYER_LOCKED;
+ case ACHANNEL_SETTING_PROTECT: /* protected */
+ return GP_LAYER_LOCKED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_gpl_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
+static void *acf_gpl_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings UNUSED(setting),
+ short *type)
{
- bGPDlayer *gpl = (bGPDlayer *)ale->data;
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
- /* all flags are just in gpl->flag for now... */
- return GET_ACF_FLAG_PTR(gpl->flag, type);
+ /* all flags are just in gpl->flag for now... */
+ return GET_ACF_FLAG_PTR(gpl->flag, type);
}
/* grease pencil layer type define */
-static bAnimChannelType ACF_GPL =
-{
- "GPencil Layer", /* type name */
- ACHANNEL_ROLE_CHANNEL, /* role */
-
- acf_gpencil_channel_color, /* backdrop color */
- acf_generic_channel_backdrop, /* backdrop */
- acf_generic_indention_flexible, /* indent level */
- acf_generic_group_offset, /* offset */
-
- acf_gpl_name, /* name */
- acf_gpl_name_prop, /* name prop */
- NULL, /* icon */
-
- acf_gpl_setting_valid, /* has setting */
- acf_gpl_setting_flag, /* flag for setting */
- acf_gpl_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_GPL = {
+ "GPencil Layer", /* type name */
+ ACHANNEL_ROLE_CHANNEL, /* role */
+
+ acf_gpencil_channel_color, /* backdrop color */
+ acf_generic_channel_backdrop, /* backdrop */
+ acf_generic_indention_flexible, /* indent level */
+ acf_generic_group_offset, /* offset */
+
+ acf_gpl_name, /* name */
+ acf_gpl_name_prop, /* name prop */
+ NULL, /* icon */
+
+ acf_gpl_setting_valid, /* has setting */
+ acf_gpl_setting_flag, /* flag for setting */
+ acf_gpl_setting_ptr, /* pointer for setting */
};
-
/* Mask Datablock ------------------------------------------- */
/* get backdrop color for mask datablock widget */
static void acf_mask_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
{
- /* these are ID-blocks, but not exactly standalone... */
- UI_GetThemeColorShade3fv(TH_DOPESHEET_CHANNELSUBOB, 20, r_color);
+ /* these are ID-blocks, but not exactly standalone... */
+ UI_GetThemeColorShade3fv(TH_DOPESHEET_CHANNELSUBOB, 20, r_color);
}
// TODO: just get this from RNA?
static int acf_mask_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_MOD_MASK;
+ return ICON_MOD_MASK;
}
/* check if some setting exists for this channel */
-static bool acf_mask_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
+static bool acf_mask_setting_valid(bAnimContext *UNUSED(ac),
+ bAnimListElem *UNUSED(ale),
+ eAnimChannel_Settings setting)
{
- switch (setting) {
- /* only select and expand supported */
- case ACHANNEL_SETTING_SELECT:
- case ACHANNEL_SETTING_EXPAND:
- return true;
+ switch (setting) {
+ /* only select and expand supported */
+ case ACHANNEL_SETTING_SELECT:
+ case ACHANNEL_SETTING_EXPAND:
+ return true;
- default:
- return false;
- }
+ default:
+ return false;
+ }
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_mask_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_mask_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_SELECT: /* selected */
- return AGRP_SELECTED;
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return AGRP_SELECTED;
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return MASK_ANIMF_EXPAND;
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return MASK_ANIMF_EXPAND;
- default:
- /* this shouldn't happen */
- return 0;
- }
+ default:
+ /* this shouldn't happen */
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_mask_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
+static void *acf_mask_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings UNUSED(setting),
+ short *type)
{
- Mask *mask = (Mask *)ale->data;
+ Mask *mask = (Mask *)ale->data;
- /* all flags are just in mask->flag for now... */
- return GET_ACF_FLAG_PTR(mask->flag, type);
+ /* all flags are just in mask->flag for now... */
+ return GET_ACF_FLAG_PTR(mask->flag, type);
}
/* mask datablock type define */
-static bAnimChannelType ACF_MASKDATA =
-{
- "Mask Datablock", /* type name */
- ACHANNEL_ROLE_EXPANDER, /* role */
-
- acf_mask_color, /* backdrop color */
- acf_group_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
- acf_generic_group_offset, /* offset */
-
- acf_generic_idblock_name, /* name */
- acf_generic_idfill_name_prop, /* name prop */
- acf_mask_icon, /* icon */
-
- acf_mask_setting_valid, /* has setting */
- acf_mask_setting_flag, /* flag for setting */
- acf_mask_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_MASKDATA = {
+ "Mask Datablock", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_mask_color, /* backdrop color */
+ acf_group_backdrop, /* backdrop */
+ acf_generic_indention_0, /* indent level */
+ acf_generic_group_offset, /* offset */
+
+ acf_generic_idblock_name, /* name */
+ acf_generic_idfill_name_prop, /* name prop */
+ acf_mask_icon, /* icon */
+
+ acf_mask_setting_valid, /* has setting */
+ acf_mask_setting_flag, /* flag for setting */
+ acf_mask_setting_ptr, /* pointer for setting */
};
/* Mask Layer ------------------------------------------- */
@@ -3172,86 +3271,91 @@ static bAnimChannelType ACF_MASKDATA =
/* name for grease pencil layer entries */
static void acf_masklay_name(bAnimListElem *ale, char *name)
{
- MaskLayer *masklay = (MaskLayer *)ale->data;
+ MaskLayer *masklay = (MaskLayer *)ale->data;
- if (masklay && name)
- BLI_strncpy(name, masklay->name, ANIM_CHAN_NAME_SIZE);
+ if (masklay && name)
+ BLI_strncpy(name, masklay->name, ANIM_CHAN_NAME_SIZE);
}
/* name property for grease pencil layer entries */
static bool acf_masklay_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
- if (ale->data) {
- RNA_pointer_create(ale->id, &RNA_MaskLayer, ale->data, ptr);
- *prop = RNA_struct_name_property(ptr->type);
+ if (ale->data) {
+ RNA_pointer_create(ale->id, &RNA_MaskLayer, ale->data, ptr);
+ *prop = RNA_struct_name_property(ptr->type);
- return (*prop != NULL);
- }
+ return (*prop != NULL);
+ }
- return false;
+ return false;
}
/* check if some setting exists for this channel */
-static bool acf_masklay_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
+static bool acf_masklay_setting_valid(bAnimContext *UNUSED(ac),
+ bAnimListElem *UNUSED(ale),
+ eAnimChannel_Settings setting)
{
- switch (setting) {
- /* unsupported */
- 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 */
- return false;
+ switch (setting) {
+ /* unsupported */
+ 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 */
+ return false;
- /* always available */
- default:
- return true;
- }
+ /* always available */
+ default:
+ return true;
+ }
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_masklay_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_masklay_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_SELECT: /* selected */
- return MASK_LAYERFLAG_SELECT;
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return MASK_LAYERFLAG_SELECT;
- case ACHANNEL_SETTING_PROTECT: /* protected */
- return MASK_LAYERFLAG_LOCKED;
+ case ACHANNEL_SETTING_PROTECT: /* protected */
+ return MASK_LAYERFLAG_LOCKED;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_masklay_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
+static void *acf_masklay_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings UNUSED(setting),
+ short *type)
{
- MaskLayer *masklay = (MaskLayer *)ale->data;
+ MaskLayer *masklay = (MaskLayer *)ale->data;
- /* all flags are just in masklay->flag for now... */
- return GET_ACF_FLAG_PTR(masklay->flag, type);
+ /* all flags are just in masklay->flag for now... */
+ return GET_ACF_FLAG_PTR(masklay->flag, type);
}
/* grease pencil layer type define */
-static bAnimChannelType ACF_MASKLAYER =
-{
- "Mask Layer", /* type name */
- ACHANNEL_ROLE_CHANNEL, /* role */
-
- acf_generic_channel_color, /* backdrop color */
- acf_generic_channel_backdrop, /* backdrop */
- acf_generic_indention_flexible, /* indent level */
- acf_generic_group_offset, /* offset */
-
- acf_masklay_name, /* name */
- acf_masklay_name_prop, /* name prop */
- NULL, /* icon */
-
- acf_masklay_setting_valid, /* has setting */
- acf_masklay_setting_flag, /* flag for setting */
- acf_masklay_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_MASKLAYER = {
+ "Mask Layer", /* type name */
+ ACHANNEL_ROLE_CHANNEL, /* role */
+
+ acf_generic_channel_color, /* backdrop color */
+ acf_generic_channel_backdrop, /* backdrop */
+ acf_generic_indention_flexible, /* indent level */
+ acf_generic_group_offset, /* offset */
+
+ acf_masklay_name, /* name */
+ acf_masklay_name_prop, /* name prop */
+ NULL, /* icon */
+
+ acf_masklay_setting_valid, /* has setting */
+ acf_masklay_setting_flag, /* flag for setting */
+ acf_masklay_setting_ptr, /* pointer for setting */
};
/* NLA Track ----------------------------------------------- */
@@ -3259,138 +3363,143 @@ static bAnimChannelType ACF_MASKLAYER =
/* get backdrop color for nla track channels */
static void acf_nlatrack_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, float r_color[3])
{
- NlaTrack *nlt = (NlaTrack *)ale->data;
- AnimData *adt = ale->adt;
- bool nonSolo = false;
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ AnimData *adt = ale->adt;
+ bool nonSolo = false;
- /* is track enabled for solo drawing? */
- if ((adt) && (adt->flag & ADT_NLA_SOLO_TRACK)) {
- if ((nlt->flag & NLATRACK_SOLO) == 0) {
- /* tag for special non-solo handling */
- nonSolo = true;
- }
- }
+ /* is track enabled for solo drawing? */
+ if ((adt) && (adt->flag & ADT_NLA_SOLO_TRACK)) {
+ if ((nlt->flag & NLATRACK_SOLO) == 0) {
+ /* tag for special non-solo handling */
+ nonSolo = true;
+ }
+ }
- /* set color for nla track */
- UI_GetThemeColorShade3fv(TH_HEADER, ((nonSolo == false) ? 20 : -20), r_color);
+ /* set color for nla track */
+ UI_GetThemeColorShade3fv(TH_HEADER, ((nonSolo == false) ? 20 : -20), r_color);
}
/* name for nla track entries */
static void acf_nlatrack_name(bAnimListElem *ale, char *name)
{
- NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaTrack *nlt = (NlaTrack *)ale->data;
- if (nlt && name)
- BLI_strncpy(name, nlt->name, ANIM_CHAN_NAME_SIZE);
+ if (nlt && name)
+ BLI_strncpy(name, nlt->name, ANIM_CHAN_NAME_SIZE);
}
/* name property for nla track entries */
static bool acf_nlatrack_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
- if (ale->data) {
- RNA_pointer_create(ale->id, &RNA_NlaTrack, ale->data, ptr);
- *prop = RNA_struct_name_property(ptr->type);
+ if (ale->data) {
+ RNA_pointer_create(ale->id, &RNA_NlaTrack, ale->data, ptr);
+ *prop = RNA_struct_name_property(ptr->type);
- return (*prop != NULL);
- }
+ return (*prop != NULL);
+ }
- return false;
+ return false;
}
/* check if some setting exists for this channel */
-static bool acf_nlatrack_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *ale, eAnimChannel_Settings setting)
-{
- NlaTrack *nlt = (NlaTrack *)ale->data;
- AnimData *adt = ale->adt;
-
- /* visibility of settings depends on various states... */
- switch (setting) {
- /* always supported */
- case ACHANNEL_SETTING_SELECT:
- case ACHANNEL_SETTING_SOLO:
- return true;
-
- /* conditionally supported... */
- case ACHANNEL_SETTING_PROTECT:
- case ACHANNEL_SETTING_MUTE:
- /* if this track is active and we're tweaking it, don't draw these toggles */
- if (((nlt->flag & NLATRACK_ACTIVE) && (nlt->flag & NLATRACK_DISABLED)) == 0) {
- /* is track enabled for solo drawing? */
- if ((adt) && (adt->flag & ADT_NLA_SOLO_TRACK)) {
- if (nlt->flag & NLATRACK_SOLO) {
- /* ok - we've got a solo track, and this is it */
- return true;
- }
- else {
- /* not ok - we've got a solo track, but this isn't it, so make it more obvious */
- return false;
- }
- }
-
-
- /* ok - no tracks are solo'd, and this isn't being tweaked */
- return true;
- }
- else {
- /* unsupported - this track is being tweaked */
- return false;
- }
-
- /* unsupported */
- default:
- return false;
- }
+static bool acf_nlatrack_setting_valid(bAnimContext *UNUSED(ac),
+ bAnimListElem *ale,
+ eAnimChannel_Settings setting)
+{
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ AnimData *adt = ale->adt;
+
+ /* visibility of settings depends on various states... */
+ switch (setting) {
+ /* always supported */
+ case ACHANNEL_SETTING_SELECT:
+ case ACHANNEL_SETTING_SOLO:
+ return true;
+
+ /* conditionally supported... */
+ case ACHANNEL_SETTING_PROTECT:
+ case ACHANNEL_SETTING_MUTE:
+ /* if this track is active and we're tweaking it, don't draw these toggles */
+ if (((nlt->flag & NLATRACK_ACTIVE) && (nlt->flag & NLATRACK_DISABLED)) == 0) {
+ /* is track enabled for solo drawing? */
+ if ((adt) && (adt->flag & ADT_NLA_SOLO_TRACK)) {
+ if (nlt->flag & NLATRACK_SOLO) {
+ /* ok - we've got a solo track, and this is it */
+ return true;
+ }
+ else {
+ /* not ok - we've got a solo track, but this isn't it, so make it more obvious */
+ return false;
+ }
+ }
+
+ /* ok - no tracks are solo'd, and this isn't being tweaked */
+ return true;
+ }
+ else {
+ /* unsupported - this track is being tweaked */
+ return false;
+ }
+
+ /* unsupported */
+ default:
+ return false;
+ }
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_nlatrack_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_nlatrack_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_SELECT: /* selected */
- return NLATRACK_SELECTED;
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return NLATRACK_SELECTED;
- case ACHANNEL_SETTING_MUTE: /* muted */
- return NLATRACK_MUTED;
+ case ACHANNEL_SETTING_MUTE: /* muted */
+ return NLATRACK_MUTED;
- case ACHANNEL_SETTING_PROTECT: /* protected */
- return NLATRACK_PROTECTED;
+ case ACHANNEL_SETTING_PROTECT: /* protected */
+ return NLATRACK_PROTECTED;
- case ACHANNEL_SETTING_SOLO: /* solo */
- return NLATRACK_SOLO;
+ case ACHANNEL_SETTING_SOLO: /* solo */
+ return NLATRACK_SOLO;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_nlatrack_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
+static void *acf_nlatrack_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings UNUSED(setting),
+ short *type)
{
- NlaTrack *nlt = (NlaTrack *)ale->data;
- return GET_ACF_FLAG_PTR(nlt->flag, type);
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ return GET_ACF_FLAG_PTR(nlt->flag, type);
}
/* nla track type define */
-static bAnimChannelType ACF_NLATRACK =
-{
- "NLA Track", /* type name */
- ACHANNEL_ROLE_CHANNEL, /* role */
-
- acf_nlatrack_color, /* backdrop color */
- acf_generic_channel_backdrop, /* backdrop */
- acf_generic_indention_flexible, /* indent level */
- acf_generic_group_offset, /* offset */ // XXX?
-
- acf_nlatrack_name, /* name */
- acf_nlatrack_name_prop, /* name prop */
- NULL, /* icon */
-
- acf_nlatrack_setting_valid, /* has setting */
- acf_nlatrack_setting_flag, /* flag for setting */
- acf_nlatrack_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_NLATRACK = {
+ "NLA Track", /* type name */
+ ACHANNEL_ROLE_CHANNEL, /* role */
+
+ acf_nlatrack_color, /* backdrop color */
+ acf_generic_channel_backdrop, /* backdrop */
+ acf_generic_indention_flexible, /* indent level */
+ acf_generic_group_offset,
+ /* offset */ // XXX?
+
+ acf_nlatrack_name, /* name */
+ acf_nlatrack_name_prop, /* name prop */
+ NULL, /* icon */
+
+ acf_nlatrack_setting_valid, /* has setting */
+ acf_nlatrack_setting_flag, /* flag for setting */
+ acf_nlatrack_setting_ptr, /* pointer for setting */
};
/* NLA Action ----------------------------------------------- */
@@ -3398,15 +3507,15 @@ static bAnimChannelType ACF_NLATRACK =
/* icon for action depends on whether it's in tweaking mode */
static int acf_nlaaction_icon(bAnimListElem *ale)
{
- AnimData *adt = ale->adt;
+ AnimData *adt = ale->adt;
- /* indicate tweaking-action state by changing the icon... */
- if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
- return ICON_ACTION_TWEAK;
- }
- else {
- return ICON_ACTION;
- }
+ /* indicate tweaking-action state by changing the icon... */
+ if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
+ return ICON_ACTION_TWEAK;
+ }
+ else {
+ return ICON_ACTION;
+ }
}
/* Backdrop color for nla action channel
@@ -3415,151 +3524,162 @@ static int acf_nlaaction_icon(bAnimListElem *ale)
*/
static void acf_nlaaction_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, float r_color[3])
{
- float color[4];
+ float color[4];
- /* Action Line
- * The alpha values action_get_color returns are only useful for drawing
- * strips backgrounds but here we're doing channel list backgrounds instead
- * so we ignore that and use our own when needed
- */
- nla_action_get_color(ale->adt, (bAction *)ale->data, color);
+ /* Action Line
+ * The alpha values action_get_color returns are only useful for drawing
+ * strips backgrounds but here we're doing channel list backgrounds instead
+ * so we ignore that and use our own when needed
+ */
+ nla_action_get_color(ale->adt, (bAction *)ale->data, color);
- /* NOTE: since the return types only allow rgb, we cannot do the alpha-blending we'd
- * like for the solo-drawing case. Hence, this method isn't actually used for drawing
- * most of the channel...
- */
- copy_v3_v3(r_color, color);
+ /* NOTE: since the return types only allow rgb, we cannot do the alpha-blending we'd
+ * like for the solo-drawing case. Hence, this method isn't actually used for drawing
+ * most of the channel...
+ */
+ copy_v3_v3(r_color, color);
}
/* backdrop for nla action channel */
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;
- AnimData *adt = ale->adt;
- short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
- float color[4];
-
- /* Action Line
- * The alpha values action_get_color returns are only useful for drawing
- * strips backgrounds but here we're doing channel list backgrounds instead
- * so we ignore that and use our own when needed
- */
- nla_action_get_color(adt, (bAction *)ale->data, color);
-
- if (adt && (adt->flag & ADT_NLA_EDIT_ON))
- color[3] = 1.0f;
- else
- color[3] = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3f : 1.0f;
-
- /* only on top left corner, to show that this channel sits on top of the preceding ones
- * while still linking into the action line strip to the right
- */
- UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT);
-
- /* draw slightly shifted up vertically to look like it has more separation from other channels,
- * but we then need to slightly shorten it so that it doesn't look like it overlaps
- */
- UI_draw_roundbox_4fv(true, offset, yminc + NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc + NLACHANNEL_SKIP - 1, 8, color);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ View2D *v2d = &ac->ar->v2d;
+ AnimData *adt = ale->adt;
+ short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
+ float color[4];
+
+ /* Action Line
+ * The alpha values action_get_color returns are only useful for drawing
+ * strips backgrounds but here we're doing channel list backgrounds instead
+ * so we ignore that and use our own when needed
+ */
+ nla_action_get_color(adt, (bAction *)ale->data, color);
+
+ if (adt && (adt->flag & ADT_NLA_EDIT_ON))
+ color[3] = 1.0f;
+ else
+ color[3] = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3f : 1.0f;
+
+ /* only on top left corner, to show that this channel sits on top of the preceding ones
+ * while still linking into the action line strip to the right
+ */
+ UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT);
+
+ /* draw slightly shifted up vertically to look like it has more separation from other channels,
+ * but we then need to slightly shorten it so that it doesn't look like it overlaps
+ */
+ UI_draw_roundbox_4fv(true,
+ offset,
+ yminc + NLACHANNEL_SKIP,
+ (float)v2d->cur.xmax,
+ ymaxc + NLACHANNEL_SKIP - 1,
+ 8,
+ color);
}
/* name for nla action entries */
static void acf_nlaaction_name(bAnimListElem *ale, char *name)
{
- bAction *act = (bAction *)ale->data;
+ bAction *act = (bAction *)ale->data;
- if (name) {
- if (act) {
- // TODO: add special decoration when doing this in tweaking mode?
- BLI_strncpy(name, act->id.name + 2, ANIM_CHAN_NAME_SIZE);
- }
- else {
- BLI_strncpy(name, "<No Action>", ANIM_CHAN_NAME_SIZE);
- }
- }
+ if (name) {
+ if (act) {
+ // TODO: add special decoration when doing this in tweaking mode?
+ BLI_strncpy(name, act->id.name + 2, ANIM_CHAN_NAME_SIZE);
+ }
+ else {
+ BLI_strncpy(name, "<No Action>", ANIM_CHAN_NAME_SIZE);
+ }
+ }
}
/* name property for nla action entries */
static bool acf_nlaaction_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
- if (ale->data) {
- RNA_pointer_create(ale->id, &RNA_Action, ale->data, ptr);
- *prop = RNA_struct_name_property(ptr->type);
+ if (ale->data) {
+ RNA_pointer_create(ale->id, &RNA_Action, ale->data, ptr);
+ *prop = RNA_struct_name_property(ptr->type);
- return (*prop != NULL);
- }
+ return (*prop != NULL);
+ }
- return false;
+ return false;
}
/* check if some setting exists for this channel */
-static bool acf_nlaaction_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *ale, eAnimChannel_Settings setting)
-{
- AnimData *adt = ale->adt;
-
- /* visibility of settings depends on various states... */
- switch (setting) {
- /* conditionally supported */
- case ACHANNEL_SETTING_PINNED: /* pinned - map/unmap */
- if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
- /* this should only appear in tweakmode */
- return true;
- }
- else {
- return false;
- }
-
- /* unsupported */
- default:
- return false;
- }
+static bool acf_nlaaction_setting_valid(bAnimContext *UNUSED(ac),
+ bAnimListElem *ale,
+ eAnimChannel_Settings setting)
+{
+ AnimData *adt = ale->adt;
+
+ /* visibility of settings depends on various states... */
+ switch (setting) {
+ /* conditionally supported */
+ case ACHANNEL_SETTING_PINNED: /* pinned - map/unmap */
+ if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
+ /* this should only appear in tweakmode */
+ return true;
+ }
+ else {
+ return false;
+ }
+
+ /* unsupported */
+ default:
+ return false;
+ }
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_nlaaction_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+static int acf_nlaaction_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
{
- /* clear extra return data first */
- *neg = false;
+ /* clear extra return data first */
+ *neg = false;
- switch (setting) {
- case ACHANNEL_SETTING_PINNED: /* pinned - map/unmap */
- *neg = true; // XXX
- return ADT_NLA_EDIT_NOMAP;
+ switch (setting) {
+ case ACHANNEL_SETTING_PINNED: /* pinned - map/unmap */
+ *neg = true; // XXX
+ return ADT_NLA_EDIT_NOMAP;
- default: /* unsupported */
- return 0;
- }
+ default: /* unsupported */
+ return 0;
+ }
}
/* get pointer to the setting */
-static void *acf_nlaaction_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
+static void *acf_nlaaction_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings UNUSED(setting),
+ short *type)
{
- AnimData *adt = ale->adt;
- return GET_ACF_FLAG_PTR(adt->flag, type);
+ AnimData *adt = ale->adt;
+ return GET_ACF_FLAG_PTR(adt->flag, type);
}
/* nla action type define */
-static bAnimChannelType ACF_NLAACTION =
-{
- "NLA Active Action", /* type name */
- ACHANNEL_ROLE_CHANNEL, /* role */
-
- acf_nlaaction_color, /* backdrop color (NOTE: the backdrop handles this too,
- * since it needs special hacks) */
- acf_nlaaction_backdrop, /* backdrop */
- acf_generic_indention_flexible, /* indent level */
- acf_generic_group_offset, /* offset */ // XXX?
-
- acf_nlaaction_name, /* name */
- acf_nlaaction_name_prop, /* name prop */
- acf_nlaaction_icon, /* icon */
-
- acf_nlaaction_setting_valid, /* has setting */
- acf_nlaaction_setting_flag, /* flag for setting */
- acf_nlaaction_setting_ptr, /* pointer for setting */
+static bAnimChannelType ACF_NLAACTION = {
+ "NLA Active Action", /* type name */
+ ACHANNEL_ROLE_CHANNEL, /* role */
+
+ acf_nlaaction_color, /* backdrop color (NOTE: the backdrop handles this too,
+ * since it needs special hacks) */
+ acf_nlaaction_backdrop, /* backdrop */
+ acf_generic_indention_flexible, /* indent level */
+ acf_generic_group_offset,
+ /* offset */ // XXX?
+
+ acf_nlaaction_name, /* name */
+ acf_nlaaction_name_prop, /* name prop */
+ acf_nlaaction_icon, /* icon */
+
+ acf_nlaaction_setting_valid, /* has setting */
+ acf_nlaaction_setting_flag, /* flag for setting */
+ acf_nlaaction_setting_ptr, /* pointer for setting */
};
-
/* *********************************************** */
/* Type Registration and General Access */
@@ -3570,79 +3690,79 @@ static short ACF_INIT = 1; /* when non-zero, the list needs to be updated */
/* Initialize type info definitions */
static void ANIM_init_channel_typeinfo_data(void)
{
- int type = 0;
+ int type = 0;
- /* start initializing if necessary... */
- if (ACF_INIT) {
- ACF_INIT = 0;
+ /* start initializing if necessary... */
+ if (ACF_INIT) {
+ ACF_INIT = 0;
- /* NOTE: need to keep the order of these synchronized with the definition of
- * channel types (eAnim_ChannelType) in ED_anim_api.h
- */
- animchannelTypeInfo[type++] = NULL; /* None */
- animchannelTypeInfo[type++] = NULL; /* AnimData */
- animchannelTypeInfo[type++] = NULL; /* Special */
+ /* NOTE: need to keep the order of these synchronized with the definition of
+ * channel types (eAnim_ChannelType) in ED_anim_api.h
+ */
+ animchannelTypeInfo[type++] = NULL; /* None */
+ animchannelTypeInfo[type++] = NULL; /* AnimData */
+ animchannelTypeInfo[type++] = NULL; /* Special */
- animchannelTypeInfo[type++] = &ACF_SUMMARY; /* Motion Summary */
+ animchannelTypeInfo[type++] = &ACF_SUMMARY; /* Motion Summary */
- animchannelTypeInfo[type++] = &ACF_SCENE; /* Scene */
- animchannelTypeInfo[type++] = &ACF_OBJECT; /* Object */
- animchannelTypeInfo[type++] = &ACF_GROUP; /* Group */
- animchannelTypeInfo[type++] = &ACF_FCURVE; /* F-Curve */
+ animchannelTypeInfo[type++] = &ACF_SCENE; /* Scene */
+ animchannelTypeInfo[type++] = &ACF_OBJECT; /* Object */
+ animchannelTypeInfo[type++] = &ACF_GROUP; /* Group */
+ animchannelTypeInfo[type++] = &ACF_FCURVE; /* F-Curve */
- animchannelTypeInfo[type++] = &ACF_NLACONTROLS; /* NLA Control FCurve Expander */
- animchannelTypeInfo[type++] = &ACF_NLACURVE; /* NLA Control FCurve Channel */
+ animchannelTypeInfo[type++] = &ACF_NLACONTROLS; /* NLA Control FCurve Expander */
+ animchannelTypeInfo[type++] = &ACF_NLACURVE; /* NLA Control FCurve Channel */
- animchannelTypeInfo[type++] = &ACF_FILLACTD; /* Object Action Expander */
- animchannelTypeInfo[type++] = &ACF_FILLDRIVERS; /* Drivers Expander */
+ 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_SHAPEKEY; /* ShapeKey */
+ animchannelTypeInfo[type++] = &ACF_SHAPEKEY; /* ShapeKey */
- animchannelTypeInfo[type++] = &ACF_GPD; /* Grease Pencil Datablock */
- animchannelTypeInfo[type++] = &ACF_GPL; /* Grease Pencil Layer */
+ animchannelTypeInfo[type++] = &ACF_GPD; /* Grease Pencil Datablock */
+ animchannelTypeInfo[type++] = &ACF_GPL; /* Grease Pencil Layer */
- animchannelTypeInfo[type++] = &ACF_MASKDATA; /* Mask Datablock */
- animchannelTypeInfo[type++] = &ACF_MASKLAYER; /* Mask Layer */
+ animchannelTypeInfo[type++] = &ACF_MASKDATA; /* Mask Datablock */
+ animchannelTypeInfo[type++] = &ACF_MASKLAYER; /* Mask Layer */
- animchannelTypeInfo[type++] = &ACF_NLATRACK; /* NLA Track */
- animchannelTypeInfo[type++] = &ACF_NLAACTION; /* NLA Action */
- }
+ animchannelTypeInfo[type++] = &ACF_NLATRACK; /* NLA Track */
+ animchannelTypeInfo[type++] = &ACF_NLAACTION; /* NLA Action */
+ }
}
/* Get type info from given channel type */
const bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale)
{
- /* santiy checks */
- if (ale == NULL)
- return NULL;
+ /* santiy checks */
+ if (ale == NULL)
+ return NULL;
- /* init the typeinfo if not available yet... */
- ANIM_init_channel_typeinfo_data();
+ /* init the typeinfo if not available yet... */
+ ANIM_init_channel_typeinfo_data();
- /* check if type is in bounds... */
- if ((ale->type >= 0) && (ale->type < ANIMTYPE_NUM_TYPES))
- return animchannelTypeInfo[ale->type];
- else
- return NULL;
+ /* check if type is in bounds... */
+ if ((ale->type >= 0) && (ale->type < ANIMTYPE_NUM_TYPES))
+ return animchannelTypeInfo[ale->type];
+ else
+ return NULL;
}
/* --------------------------- */
@@ -3650,29 +3770,29 @@ const bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale)
/* Print debug info string for the given channel */
void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level)
{
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- /* print indents */
- for (; indent_level > 0; indent_level--)
- printf(" ");
+ /* print indents */
+ for (; indent_level > 0; indent_level--)
+ printf(" ");
- /* print info */
- if (acf) {
- char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */
+ /* print info */
+ if (acf) {
+ char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */
- /* get UI name */
- if (acf->name)
- acf->name(ale, name);
- else
- BLI_strncpy(name, "<No name>", sizeof(name));
+ /* get UI name */
+ if (acf->name)
+ acf->name(ale, name);
+ else
+ BLI_strncpy(name, "<No name>", sizeof(name));
- /* print type name + ui name */
- printf("ChanType: <%s> Name: \"%s\"\n", acf->channel_type_name, name);
- }
- else if (ale)
- printf("ChanType: <Unknown - %d>\n", ale->type);
- else
- printf("<Invalid channel - NULL>\n");
+ /* print type name + ui name */
+ printf("ChanType: <%s> Name: \"%s\"\n", acf->channel_type_name, name);
+ }
+ else if (ale)
+ printf("ChanType: <Unknown - %d>\n", ale->type);
+ else
+ printf("<Invalid channel - NULL>\n");
}
/* --------------------------- */
@@ -3682,361 +3802,374 @@ void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level)
*/
short ANIM_channel_setting_get(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
{
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
-
- /* 1) check that the setting exists for the current context */
- if ((acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting))) {
- /* 2) get pointer to check for flag in, and the flag to check for */
- short ptrsize;
- bool negflag;
- int flag;
- void *ptr;
-
- flag = acf->setting_flag(ac, setting, &negflag);
- ptr = acf->setting_ptr(ale, setting, &ptrsize);
-
- /* check if flag is enabled */
- if (ptr && flag) {
- switch (ptrsize) {
- case sizeof(int): /* integer pointer for setting */
- {
- const int *val = (int *)ptr;
-
- if (negflag)
- return ((*val) & flag) == 0;
- else
- return ((*val) & flag) != 0;
- }
- case sizeof(short): /* short pointer for setting */
- {
- const short *val = (short *)ptr;
-
- if (negflag)
- return ((*val) & flag) == 0;
- else
- return ((*val) & flag) != 0;
- }
- case sizeof(char): /* char pointer for setting */
- {
- const char *val = (char *)ptr;
-
- if (negflag)
- return ((*val) & flag) == 0;
- else
- return ((*val) & flag) != 0;
- }
- }
- }
- }
-
- /* not found... */
- return -1;
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+
+ /* 1) check that the setting exists for the current context */
+ if ((acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting))) {
+ /* 2) get pointer to check for flag in, and the flag to check for */
+ short ptrsize;
+ bool negflag;
+ int flag;
+ void *ptr;
+
+ flag = acf->setting_flag(ac, setting, &negflag);
+ ptr = acf->setting_ptr(ale, setting, &ptrsize);
+
+ /* check if flag is enabled */
+ if (ptr && flag) {
+ switch (ptrsize) {
+ case sizeof(int): /* integer pointer for setting */
+ {
+ const int *val = (int *)ptr;
+
+ if (negflag)
+ return ((*val) & flag) == 0;
+ else
+ return ((*val) & flag) != 0;
+ }
+ case sizeof(short): /* short pointer for setting */
+ {
+ const short *val = (short *)ptr;
+
+ if (negflag)
+ return ((*val) & flag) == 0;
+ else
+ return ((*val) & flag) != 0;
+ }
+ case sizeof(char): /* char pointer for setting */
+ {
+ const char *val = (char *)ptr;
+
+ if (negflag)
+ return ((*val) & flag) == 0;
+ else
+ return ((*val) & flag) != 0;
+ }
+ }
+ }
+ }
+
+ /* not found... */
+ return -1;
}
-
/* quick macro for use in ANIM_channel_setting_set - set flag for setting according the mode given */
#define ACF_SETTING_SET(sval, sflag, smode) \
- { \
- if (negflag) { \
- if (smode == ACHANNEL_SETFLAG_INVERT) (sval) ^= (sflag); \
- else if (smode == ACHANNEL_SETFLAG_ADD) (sval) &= ~(sflag); \
- else (sval) |= (sflag); \
- } \
- else { \
- if (smode == ACHANNEL_SETFLAG_INVERT) (sval) ^= (sflag); \
- else if (smode == ACHANNEL_SETFLAG_ADD) (sval) |= (sflag); \
- else (sval) &= ~(sflag); \
- } \
- } (void)0
+ { \
+ if (negflag) { \
+ if (smode == ACHANNEL_SETFLAG_INVERT) \
+ (sval) ^= (sflag); \
+ else if (smode == ACHANNEL_SETFLAG_ADD) \
+ (sval) &= ~(sflag); \
+ else \
+ (sval) |= (sflag); \
+ } \
+ else { \
+ if (smode == ACHANNEL_SETFLAG_INVERT) \
+ (sval) ^= (sflag); \
+ else if (smode == ACHANNEL_SETFLAG_ADD) \
+ (sval) |= (sflag); \
+ else \
+ (sval) &= ~(sflag); \
+ } \
+ } \
+ (void)0
/* Change value of some setting for a channel
* - setting: eAnimChannel_Settings
* - mode: eAnimChannels_SetFlag
*/
-void ANIM_channel_setting_set(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting, eAnimChannels_SetFlag mode)
-{
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
-
- /* 1) check that the setting exists for the current context */
- if ((acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting))) {
- /* 2) get pointer to check for flag in, and the flag to check for */
- short ptrsize;
- bool negflag;
- int flag;
- void *ptr;
-
- flag = acf->setting_flag(ac, setting, &negflag);
- ptr = acf->setting_ptr(ale, setting, &ptrsize);
-
- /* check if flag is enabled */
- if (ptr && flag) {
- switch (ptrsize) {
- case sizeof(int): /* integer pointer for setting */
- {
- int *val = (int *)ptr;
- ACF_SETTING_SET(*val, flag, mode);
- break;
- }
- case sizeof(short): /* short pointer for setting */
- {
- short *val = (short *)ptr;
- ACF_SETTING_SET(*val, flag, mode);
- break;
- }
- case sizeof(char): /* char pointer for setting */
- {
- char *val = (char *)ptr;
- ACF_SETTING_SET(*val, flag, mode);
- break;
- }
- }
- }
- }
+void ANIM_channel_setting_set(bAnimContext *ac,
+ bAnimListElem *ale,
+ eAnimChannel_Settings setting,
+ eAnimChannels_SetFlag mode)
+{
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+
+ /* 1) check that the setting exists for the current context */
+ if ((acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting))) {
+ /* 2) get pointer to check for flag in, and the flag to check for */
+ short ptrsize;
+ bool negflag;
+ int flag;
+ void *ptr;
+
+ flag = acf->setting_flag(ac, setting, &negflag);
+ ptr = acf->setting_ptr(ale, setting, &ptrsize);
+
+ /* check if flag is enabled */
+ if (ptr && flag) {
+ switch (ptrsize) {
+ case sizeof(int): /* integer pointer for setting */
+ {
+ int *val = (int *)ptr;
+ ACF_SETTING_SET(*val, flag, mode);
+ break;
+ }
+ case sizeof(short): /* short pointer for setting */
+ {
+ short *val = (short *)ptr;
+ ACF_SETTING_SET(*val, flag, mode);
+ break;
+ }
+ case sizeof(char): /* char pointer for setting */
+ {
+ char *val = (char *)ptr;
+ ACF_SETTING_SET(*val, flag, mode);
+ break;
+ }
+ }
+ }
+ }
}
/* --------------------------- */
// size of icons
-#define ICON_WIDTH (0.85f * U.widget_unit)
+#define ICON_WIDTH (0.85f * U.widget_unit)
// width of sliders
-#define SLIDER_WIDTH (4 * U.widget_unit)
+#define SLIDER_WIDTH (4 * U.widget_unit)
// min-width of rename textboxes
#define RENAME_TEXT_MIN_WIDTH (U.widget_unit)
-
/* Helper - Check if a channel needs renaming */
-static bool achannel_is_being_renamed(const bAnimContext *ac, const bAnimChannelType *acf, size_t channel_index)
+static bool achannel_is_being_renamed(const bAnimContext *ac,
+ const bAnimChannelType *acf,
+ size_t channel_index)
{
- if (acf->name_prop && ac->ads) {
- /* if rename index matches, this channel is being renamed */
- if (ac->ads->renameIndex == channel_index + 1) {
- return true;
- }
- }
+ if (acf->name_prop && ac->ads) {
+ /* if rename index matches, this channel is being renamed */
+ if (ac->ads->renameIndex == channel_index + 1) {
+ return true;
+ }
+ }
- /* not being renamed */
- return false;
+ /* not being renamed */
+ return false;
}
-
/* Draw the given channel */
-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;
- short selected, offset;
- float y, ymid, ytext;
-
- /* sanity checks - don't draw anything */
- if (ELEM(NULL, acf, ale))
- return;
-
- /* get initial offset */
- if (acf->get_offset)
- offset = acf->get_offset(ac, ale);
- else
- offset = 0;
-
- /* calculate appropriate y-coordinates for icon buttons */
- y = (ymaxc - yminc) / 2 + yminc;
- ymid = y - 0.5f * ICON_WIDTH;
- /* y-coordinates for text is only 4 down from middle */
- ytext = y - 0.2f * U.widget_unit;
-
- /* check if channel is selected */
- if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT))
- selected = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
- else
- selected = 0;
-
- /* set blending again, as may not be set in previous step */
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
-
- /* step 1) draw backdrop ........................................... */
- if (acf->draw_backdrop)
- acf->draw_backdrop(ac, ale, yminc, ymaxc);
-
- /* step 2) draw expand widget ....................................... */
- if (acf->has_setting(ac, ale, ACHANNEL_SETTING_EXPAND)) {
- /* just skip - drawn as widget now */
- offset += ICON_WIDTH;
- }
-
- /* step 3) draw icon ............................................... */
- if (acf->icon) {
- UI_icon_draw(offset, ymid, acf->icon(ale));
- 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...
- * - in Grease Pencil mode, color swatches for layer color
- */
- if (ac->sl) {
- 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 */
- if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
- FCurve *fcu = (FCurve *)ale->data;
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* 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);
-
- immUnbindProgram();
- }
- /* icon is drawn as widget now... */
- if (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
- offset += ICON_WIDTH;
- }
- if (acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE)) {
- offset += ICON_WIDTH;
- }
- }
- else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
- /* 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 ............................................... */
- /* Don't draw this if renaming... */
- 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];
-
- /* set text color */
- /* XXX: if active, highlight differently? */
-
- if (selected)
- UI_GetThemeColor4ubv(TH_TEXT_HI, col);
- else
- UI_GetThemeColor4ubv(TH_TEXT, col);
-
- /* get name */
- acf->name(ale, name);
-
- offset += 3;
- UI_fontstyle_draw_simple(fstyle, offset, ytext, name, col);
-
- /* draw red underline if channel is disabled */
- if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE) && (ale->flag & FCURVE_DISABLED)) {
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* FIXME: replace hardcoded color here, and check on extents! */
- immUniformColor3f(1.0f, 0.0f, 0.0f);
-
- GPU_line_width(2.0f);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, (float)offset, yminc);
- immVertex2f(pos, (float)v2d->cur.xmax, yminc);
- immEnd();
-
- immUnbindProgram();
- }
- }
-
- /* step 6) draw backdrops behind mute+protection toggles + (sliders) ....................... */
- /* reset offset - now goes from RHS of panel */
- offset = 0;
-
- /* TODO: when drawing sliders, make those draw instead of these toggles if not enough space */
-
- if (v2d) {
- short draw_sliders = 0;
- float ymin_ofs = 0.0f;
- float color[3];
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* get and set backdrop color */
- acf->get_backdrop_color(ac, ale, color);
- immUniformColor3fv(color);
-
- /* check if we need to show the sliders */
- if ((ac->sl) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_GRAPH)) {
- switch (ac->spacetype) {
- case SPACE_ACTION:
- {
- SpaceAction *saction = (SpaceAction *)ac->sl;
- draw_sliders = (saction->flag & SACTION_SLIDERS);
- break;
- }
- case SPACE_GRAPH:
- {
- SpaceGraph *sipo = (SpaceGraph *)ac->sl;
- draw_sliders = (sipo->flag & SIPO_SLIDERS);
- break;
- }
- }
- }
-
- /* check if there's enough space for the toggles if the sliders are drawn too */
- if (!(draw_sliders) || (BLI_rcti_size_x(&v2d->mask) > ACHANNEL_BUTTON_WIDTH / 2) ) {
- /* protect... */
- if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT))
- offset += ICON_WIDTH;
-
- /* mute... */
- if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MUTE))
- offset += ICON_WIDTH;
- if (ale->type == ANIMTYPE_GPLAYER)
- offset += ICON_WIDTH;
-
- /* pinned... */
- if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PINNED))
- offset += ICON_WIDTH;
-
- /* NOTE: technically, NLA Action "pushdown" should be here too, but there are no sliders there */
-
- /* NLA action channels have slightly different spacing requirements... */
- if (ale->type == ANIMTYPE_NLAACTION)
- ymin_ofs = NLACHANNEL_SKIP;
- }
-
- /* draw slider
- * - even if we can draw sliders for this view, we must also check that the channel-type supports them
- * (only only F-Curves really can support them for now)
- * - slider should start before the toggles (if they're visible) to keep a clean line down the side
- */
- if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE, ANIMTYPE_SHAPEKEY)) {
- /* adjust offset */
- offset += SLIDER_WIDTH;
- }
-
-
- /* finally draw a backdrop rect behind these
- * - starts from the point where the first toggle/slider starts,
- * - ends past the space that might be reserved for a scroller
- */
- immRectf(pos, v2d->cur.xmax - (float)offset, yminc + ymin_ofs, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
-
- immUnbindProgram();
- }
+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;
+ short selected, offset;
+ float y, ymid, ytext;
+
+ /* sanity checks - don't draw anything */
+ if (ELEM(NULL, acf, ale))
+ return;
+
+ /* get initial offset */
+ if (acf->get_offset)
+ offset = acf->get_offset(ac, ale);
+ else
+ offset = 0;
+
+ /* calculate appropriate y-coordinates for icon buttons */
+ y = (ymaxc - yminc) / 2 + yminc;
+ ymid = y - 0.5f * ICON_WIDTH;
+ /* y-coordinates for text is only 4 down from middle */
+ ytext = y - 0.2f * U.widget_unit;
+
+ /* check if channel is selected */
+ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT))
+ selected = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
+ else
+ selected = 0;
+
+ /* set blending again, as may not be set in previous step */
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
+
+ /* step 1) draw backdrop ........................................... */
+ if (acf->draw_backdrop)
+ acf->draw_backdrop(ac, ale, yminc, ymaxc);
+
+ /* step 2) draw expand widget ....................................... */
+ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_EXPAND)) {
+ /* just skip - drawn as widget now */
+ offset += ICON_WIDTH;
+ }
+
+ /* step 3) draw icon ............................................... */
+ if (acf->icon) {
+ UI_icon_draw(offset, ymid, acf->icon(ale));
+ 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...
+ * - in Grease Pencil mode, color swatches for layer color
+ */
+ if (ac->sl) {
+ 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 */
+ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
+ FCurve *fcu = (FCurve *)ale->data;
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* 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);
+
+ immUnbindProgram();
+ }
+ /* icon is drawn as widget now... */
+ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
+ offset += ICON_WIDTH;
+ }
+ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE)) {
+ offset += ICON_WIDTH;
+ }
+ }
+ else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
+ /* 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 ............................................... */
+ /* Don't draw this if renaming... */
+ 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];
+
+ /* set text color */
+ /* XXX: if active, highlight differently? */
+
+ if (selected)
+ UI_GetThemeColor4ubv(TH_TEXT_HI, col);
+ else
+ UI_GetThemeColor4ubv(TH_TEXT, col);
+
+ /* get name */
+ acf->name(ale, name);
+
+ offset += 3;
+ UI_fontstyle_draw_simple(fstyle, offset, ytext, name, col);
+
+ /* draw red underline if channel is disabled */
+ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE) && (ale->flag & FCURVE_DISABLED)) {
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* FIXME: replace hardcoded color here, and check on extents! */
+ immUniformColor3f(1.0f, 0.0f, 0.0f);
+
+ GPU_line_width(2.0f);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, (float)offset, yminc);
+ immVertex2f(pos, (float)v2d->cur.xmax, yminc);
+ immEnd();
+
+ immUnbindProgram();
+ }
+ }
+
+ /* step 6) draw backdrops behind mute+protection toggles + (sliders) ....................... */
+ /* reset offset - now goes from RHS of panel */
+ offset = 0;
+
+ /* TODO: when drawing sliders, make those draw instead of these toggles if not enough space */
+
+ if (v2d) {
+ short draw_sliders = 0;
+ float ymin_ofs = 0.0f;
+ float color[3];
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* get and set backdrop color */
+ acf->get_backdrop_color(ac, ale, color);
+ immUniformColor3fv(color);
+
+ /* check if we need to show the sliders */
+ if ((ac->sl) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_GRAPH)) {
+ switch (ac->spacetype) {
+ case SPACE_ACTION: {
+ SpaceAction *saction = (SpaceAction *)ac->sl;
+ draw_sliders = (saction->flag & SACTION_SLIDERS);
+ break;
+ }
+ case SPACE_GRAPH: {
+ SpaceGraph *sipo = (SpaceGraph *)ac->sl;
+ draw_sliders = (sipo->flag & SIPO_SLIDERS);
+ break;
+ }
+ }
+ }
+
+ /* check if there's enough space for the toggles if the sliders are drawn too */
+ if (!(draw_sliders) || (BLI_rcti_size_x(&v2d->mask) > ACHANNEL_BUTTON_WIDTH / 2)) {
+ /* protect... */
+ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT))
+ offset += ICON_WIDTH;
+
+ /* mute... */
+ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MUTE))
+ offset += ICON_WIDTH;
+ if (ale->type == ANIMTYPE_GPLAYER)
+ offset += ICON_WIDTH;
+
+ /* pinned... */
+ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PINNED))
+ offset += ICON_WIDTH;
+
+ /* NOTE: technically, NLA Action "pushdown" should be here too, but there are no sliders there */
+
+ /* NLA action channels have slightly different spacing requirements... */
+ if (ale->type == ANIMTYPE_NLAACTION)
+ ymin_ofs = NLACHANNEL_SKIP;
+ }
+
+ /* draw slider
+ * - even if we can draw sliders for this view, we must also check that the channel-type supports them
+ * (only only F-Curves really can support them for now)
+ * - slider should start before the toggles (if they're visible) to keep a clean line down the side
+ */
+ if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE, ANIMTYPE_SHAPEKEY)) {
+ /* adjust offset */
+ offset += SLIDER_WIDTH;
+ }
+
+ /* finally draw a backdrop rect behind these
+ * - starts from the point where the first toggle/slider starts,
+ * - ends past the space that might be reserved for a scroller
+ */
+ immRectf(pos,
+ v2d->cur.xmax - (float)offset,
+ yminc + ymin_ofs,
+ v2d->cur.xmax + EXTRA_SCROLL_PAD,
+ ymaxc);
+
+ immUnbindProgram();
+ }
}
/* ------------------ */
@@ -4044,711 +4177,803 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
/* callback for (normal) widget settings - send notifiers */
static void achannel_setting_widget_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
{
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
}
/* callback for widget settings that need flushing */
static void achannel_setting_flush_widget_cb(bContext *C, void *ale_npoin, void *setting_wrap)
{
- bAnimListElem *ale_setting = (bAnimListElem *)ale_npoin;
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- int filter;
- int setting = POINTER_AS_INT(setting_wrap);
- short on = 0;
+ bAnimListElem *ale_setting = (bAnimListElem *)ale_npoin;
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ int filter;
+ int setting = POINTER_AS_INT(setting_wrap);
+ short on = 0;
- /* send notifiers before doing anything else... */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ /* send notifiers before doing anything else... */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
- /* verify that we have a channel to operate on. */
- if (!ale_setting) {
- return;
- }
+ /* verify that we have a channel to operate on. */
+ if (!ale_setting) {
+ return;
+ }
- if (ale_setting->type == ANIMTYPE_GPLAYER) {
- /* draw cache updates for settings that affect the visible strokes */
- if (setting == ACHANNEL_SETTING_VISIBLE) {
- bGPdata *gpd = (bGPdata *)ale_setting->id;
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- }
+ if (ale_setting->type == ANIMTYPE_GPLAYER) {
+ /* draw cache updates for settings that affect the visible strokes */
+ if (setting == ACHANNEL_SETTING_VISIBLE) {
+ bGPdata *gpd = (bGPdata *)ale_setting->id;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ }
- /* UI updates */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
- }
+ /* UI updates */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
+ }
- /* Tag for full animation update, so that the settings will have an effect. */
- if (ale_setting->id) {
- DEG_id_tag_update(ale_setting->id, ID_RECALC_ANIMATION);
- }
- if (ale_setting->adt && ale_setting->adt->action) {
- /* Action is it's own datablock, so has to be tagged specifically. */
- DEG_id_tag_update(&ale_setting->adt->action->id, ID_RECALC_ANIMATION);
- }
+ /* Tag for full animation update, so that the settings will have an effect. */
+ if (ale_setting->id) {
+ DEG_id_tag_update(ale_setting->id, ID_RECALC_ANIMATION);
+ }
+ if (ale_setting->adt && ale_setting->adt->action) {
+ /* Action is it's own datablock, so has to be tagged specifically. */
+ DEG_id_tag_update(&ale_setting->adt->action->id, ID_RECALC_ANIMATION);
+ }
- /* verify animation context */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return;
+ /* verify animation context */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return;
- /* check if the setting is on... */
- on = ANIM_channel_setting_get(&ac, ale_setting, setting);
+ /* check if the setting is on... */
+ on = ANIM_channel_setting_get(&ac, ale_setting, setting);
- /* on == -1 means setting not found... */
- if (on == -1) {
- return;
- }
+ /* on == -1 means setting not found... */
+ if (on == -1) {
+ return;
+ }
- /* get all channels that can possibly be chosen - but ignore hierarchy */
- filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS;
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* get all channels that can possibly be chosen - but ignore hierarchy */
+ filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS;
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* call API method to flush the setting */
- ANIM_flush_setting_anim_channels(&ac, &anim_data, ale_setting, setting, on);
+ /* call API method to flush the setting */
+ ANIM_flush_setting_anim_channels(&ac, &anim_data, ale_setting, setting, on);
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
}
/* callback for wrapping NLA Track "solo" toggle logic */
static void achannel_nlatrack_solo_widget_cb(bContext *C, void *ale_poin, void *UNUSED(arg2))
{
- bAnimListElem *ale = ale_poin;
- AnimData *adt = ale->adt;
- NlaTrack *nlt = ale->data;
+ bAnimListElem *ale = ale_poin;
+ AnimData *adt = ale->adt;
+ NlaTrack *nlt = ale->data;
- /* Toggle 'solo' mode. There are several complications here which need explaining:
- * - The method call is needed to perform a few additional validation operations
- * to ensure that the mode is applied properly
- * - BUT, since the button already toggles the value, we need to un-toggle it
- * before the API call gets to it, otherwise it will end up clearing the result
- * again!
- */
- nlt->flag ^= NLATRACK_SOLO;
- BKE_nlatrack_solo_toggle(adt, nlt);
+ /* Toggle 'solo' mode. There are several complications here which need explaining:
+ * - The method call is needed to perform a few additional validation operations
+ * to ensure that the mode is applied properly
+ * - BUT, since the button already toggles the value, we need to un-toggle it
+ * before the API call gets to it, otherwise it will end up clearing the result
+ * again!
+ */
+ nlt->flag ^= NLATRACK_SOLO;
+ BKE_nlatrack_solo_toggle(adt, nlt);
- /* send notifiers */
- DEG_id_tag_update(ale->id, ID_RECALC_ANIMATION);
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+ /* send notifiers */
+ DEG_id_tag_update(ale->id, ID_RECALC_ANIMATION);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
}
/* callback for widget sliders - insert keyframes */
static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poin)
{
- ID *id = (ID *)id_poin;
- AnimData *adt = BKE_animdata_from_id(id);
- FCurve *fcu = (FCurve *)fcu_poin;
+ ID *id = (ID *)id_poin;
+ AnimData *adt = BKE_animdata_from_id(id);
+ FCurve *fcu = (FCurve *)fcu_poin;
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ReportList *reports = CTX_wm_reports(C);
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = scene->toolsettings;
- ListBase nla_cache = {NULL, NULL};
- PointerRNA id_ptr, ptr;
- PropertyRNA *prop;
- short flag = 0;
- bool done = false;
- float cfra;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ReportList *reports = CTX_wm_reports(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
+ ListBase nla_cache = {NULL, NULL};
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ short flag = 0;
+ bool done = false;
+ float cfra;
- /* Get RNA pointer */
- RNA_id_pointer_create(id, &id_ptr);
+ /* Get RNA pointer */
+ RNA_id_pointer_create(id, &id_ptr);
- /* Get NLA context for value remapping */
- NlaKeyframingContext *nla_context = BKE_animsys_get_nla_keyframing_context(&nla_cache, depsgraph, &id_ptr, adt, (float)CFRA);
+ /* Get NLA context for value remapping */
+ NlaKeyframingContext *nla_context = BKE_animsys_get_nla_keyframing_context(
+ &nla_cache, depsgraph, &id_ptr, adt, (float)CFRA);
- /* get current frame and apply NLA-mapping to it (if applicable) */
- cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+ /* 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, 1);
- /* try to resolve the path stored in the F-Curve */
- if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
- /* set the special 'replace' flag if on a keyframe */
- if (fcurve_frame_has_keyframe(fcu, cfra, 0))
- flag |= INSERTKEY_REPLACE;
+ /* try to resolve the path stored in the F-Curve */
+ if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
+ /* set the special 'replace' flag if on a keyframe */
+ if (fcurve_frame_has_keyframe(fcu, cfra, 0))
+ flag |= INSERTKEY_REPLACE;
- /* insert a keyframe for this F-Curve */
- done = insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, ts->keyframe_type, nla_context, flag);
+ /* insert a keyframe for this F-Curve */
+ done = insert_keyframe_direct(
+ depsgraph, reports, ptr, prop, fcu, cfra, ts->keyframe_type, nla_context, flag);
- if (done) {
- if (adt->action != NULL) {
- DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
- }
- DEG_id_tag_update(id, ID_RECALC_ANIMATION_NO_FLUSH);
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
- }
- }
+ if (done) {
+ if (adt->action != NULL) {
+ DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
+ }
+ DEG_id_tag_update(id, ID_RECALC_ANIMATION_NO_FLUSH);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ }
+ }
- BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
+ BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
}
/* callback for shapekey widget sliders - insert keyframes */
static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, void *kb_poin)
{
- Main *bmain = CTX_data_main(C);
- Key *key = (Key *)key_poin;
- KeyBlock *kb = (KeyBlock *)kb_poin;
- char *rna_path = BKE_keyblock_curval_rnapath_get(key, kb);
+ Main *bmain = CTX_data_main(C);
+ Key *key = (Key *)key_poin;
+ KeyBlock *kb = (KeyBlock *)kb_poin;
+ char *rna_path = BKE_keyblock_curval_rnapath_get(key, kb);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ReportList *reports = CTX_wm_reports(C);
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = scene->toolsettings;
- ListBase nla_cache = {NULL, NULL};
- PointerRNA id_ptr, ptr;
- PropertyRNA *prop;
- short flag = 0;
- bool done = false;
- float cfra;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ReportList *reports = CTX_wm_reports(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
+ ListBase nla_cache = {NULL, NULL};
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ short flag = 0;
+ bool done = false;
+ float cfra;
- /* Get RNA pointer */
- RNA_id_pointer_create((ID *)key, &id_ptr);
+ /* Get RNA pointer */
+ RNA_id_pointer_create((ID *)key, &id_ptr);
- /* Get NLA context for value remapping */
- NlaKeyframingContext *nla_context = BKE_animsys_get_nla_keyframing_context(&nla_cache, depsgraph, &id_ptr, key->adt, (float)CFRA);
+ /* Get NLA context for value remapping */
+ NlaKeyframingContext *nla_context = BKE_animsys_get_nla_keyframing_context(
+ &nla_cache, depsgraph, &id_ptr, key->adt, (float)CFRA);
- /* get current frame and apply NLA-mapping to it (if applicable) */
- cfra = BKE_nla_tweakedit_remap(key->adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+ /* get current frame and apply NLA-mapping to it (if applicable) */
+ cfra = BKE_nla_tweakedit_remap(key->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, 1);
- /* 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);
+ /* 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);
- /* set the special 'replace' flag if on a keyframe */
- if (fcurve_frame_has_keyframe(fcu, cfra, 0))
- flag |= INSERTKEY_REPLACE;
+ /* set the special 'replace' flag if on a keyframe */
+ if (fcurve_frame_has_keyframe(fcu, cfra, 0))
+ flag |= INSERTKEY_REPLACE;
- /* insert a keyframe for this F-Curve */
- done = insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, ts->keyframe_type, nla_context, flag);
+ /* insert a keyframe for this F-Curve */
+ done = insert_keyframe_direct(
+ depsgraph, reports, ptr, prop, fcu, cfra, ts->keyframe_type, nla_context, flag);
- if (done)
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
- }
+ if (done)
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ }
- /* free the path */
- if (rna_path)
- MEM_freeN(rna_path);
+ /* free the path */
+ if (rna_path)
+ MEM_freeN(rna_path);
- BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
+ BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
}
/* callback for NLA Control Curve widget sliders - insert keyframes */
-static void achannel_setting_slider_nla_curve_cb(bContext *C, void *UNUSED(id_poin), void *fcu_poin)
+static void achannel_setting_slider_nla_curve_cb(bContext *C,
+ void *UNUSED(id_poin),
+ void *fcu_poin)
{
- /* ID *id = (ID *)id_poin; */
- FCurve *fcu = (FCurve *)fcu_poin;
+ /* ID *id = (ID *)id_poin; */
+ FCurve *fcu = (FCurve *)fcu_poin;
- PointerRNA ptr;
- PropertyRNA *prop;
- int index;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ReportList *reports = CTX_wm_reports(C);
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = scene->toolsettings;
- short flag = 0;
- bool done = false;
- float cfra;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ReportList *reports = CTX_wm_reports(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
+ short flag = 0;
+ bool done = false;
+ float cfra;
- /* get current frame - *no* NLA mapping should be done */
- cfra = (float)CFRA;
+ /* get current frame - *no* NLA mapping should be done */
+ cfra = (float)CFRA;
- /* get flags for keyframing */
- flag = ANIM_get_keyframing_flags(scene, 1);
+ /* get flags for keyframing */
+ flag = ANIM_get_keyframing_flags(scene, 1);
- /* get pointer and property from the slider - this should all match up with the NlaStrip required... */
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+ /* get pointer and property from the slider - this should all match up with the NlaStrip required... */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- if (fcu && prop) {
- /* set the special 'replace' flag if on a keyframe */
- if (fcurve_frame_has_keyframe(fcu, cfra, 0))
- flag |= INSERTKEY_REPLACE;
+ if (fcu && prop) {
+ /* set the special 'replace' flag if on a keyframe */
+ if (fcurve_frame_has_keyframe(fcu, cfra, 0))
+ flag |= INSERTKEY_REPLACE;
- /* insert a keyframe for this F-Curve */
- done = insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, ts->keyframe_type, NULL, flag);
+ /* insert a keyframe for this F-Curve */
+ done = insert_keyframe_direct(
+ depsgraph, reports, ptr, prop, fcu, cfra, ts->keyframe_type, NULL, flag);
- if (done)
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
- }
+ if (done)
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ }
}
/* Draw a widget for some setting */
-static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, const bAnimChannelType *acf,
- uiBlock *block, int xpos, int ypos, int setting)
-{
- short ptrsize, butType;
- bool negflag;
- bool usetoggle = true;
- int flag, icon;
- void *ptr;
- const char *tooltip;
- uiBut *but = NULL;
- bool enabled;
-
- /* get the flag and the pointer to that flag */
- flag = acf->setting_flag(ac, setting, &negflag);
- ptr = acf->setting_ptr(ale, setting, &ptrsize);
- enabled = ANIM_channel_setting_get(ac, ale, setting);
-
- /* get the base icon for the setting */
- switch (setting) {
- case ACHANNEL_SETTING_VISIBLE: /* visibility eyes */
- //icon = ((enabled) ? ICON_VISIBLE_IPO_ON : ICON_VISIBLE_IPO_OFF);
- icon = ICON_VISIBLE_IPO_OFF;
-
- if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE))
- tooltip = TIP_("F-Curve is visible in Graph Editor for editing");
- else if (ale->type == ANIMTYPE_GPLAYER)
- tooltip = TIP_("Grease Pencil layer is visible in the viewport");
- else
- tooltip = TIP_("Channels are visible in Graph Editor for editing");
- break;
-
- case ACHANNEL_SETTING_ALWAYS_VISIBLE:
- icon = ICON_UNPINNED;
- tooltip = TIP_("Channels are visible in Graph Editor for editing");
- break;
-
- case ACHANNEL_SETTING_MOD_OFF: /* modifiers disabled */
- icon = ICON_MODIFIER_OFF;
- tooltip = TIP_("F-Curve modifiers are disabled");
- break;
-
- case ACHANNEL_SETTING_EXPAND: /* expanded triangle */
- //icon = ((enabled) ? ICON_TRIA_DOWN : ICON_TRIA_RIGHT);
- icon = ICON_TRIA_RIGHT;
- tooltip = TIP_("Make channels grouped under this channel visible");
- break;
-
- case ACHANNEL_SETTING_SOLO: /* NLA Tracks only */
- //icon = ((enabled) ? ICON_SOLO_OFF : ICON_SOLO_ON);
- icon = ICON_SOLO_OFF;
- tooltip = TIP_("NLA Track is the only one evaluated in this animation data-block, with all others muted");
- break;
-
- /* --- */
-
- case ACHANNEL_SETTING_PROTECT: /* protected lock */
- // TODO: what about when there's no protect needed?
- //icon = ((enabled) ? ICON_LOCKED : ICON_UNLOCKED);
- icon = ICON_UNLOCKED;
-
- if (ale->datatype != ALE_NLASTRIP)
- tooltip = TIP_("Editability of keyframes for this channel");
- else
- tooltip = TIP_("Editability of NLA Strips in this track");
- break;
-
- case ACHANNEL_SETTING_MUTE: /* muted speaker */
- icon = ((enabled) ? ICON_CHECKBOX_DEHLT : ICON_CHECKBOX_HLT);
- usetoggle = false;
-
- if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
- tooltip = TIP_("Does F-Curve contribute to result");
- }
- else if ((ac) && (ac->spacetype == SPACE_NLA) && (ale->type != ANIMTYPE_NLATRACK)) {
- tooltip = TIP_("Temporarily disable NLA stack evaluation (i.e. only the active action is evaluated)");
- }
- else if (ale->type == ANIMTYPE_GPLAYER) {
- tooltip = TIP_("Lock current frame displayed by layer (i.e. disable animation playback)");
- }
- else {
- tooltip = TIP_("Do channels contribute to result (toggle channel muting)");
- }
- break;
-
- case ACHANNEL_SETTING_PINNED: /* pin icon */
- //icon = ((enabled) ? ICON_PINNED : ICON_UNPINNED);
- icon = ICON_UNPINNED;
-
- if (ale->type == ANIMTYPE_NLAACTION) {
- tooltip = TIP_("Display action without any time remapping (when unpinned)");
- }
- else {
- /* TODO: there are no other tools which require the 'pinning' concept yet */
- tooltip = NULL;
- }
- break;
-
- default:
- tooltip = NULL;
- icon = 0;
- break;
- }
-
- /* type of button */
- if (usetoggle) {
- if (negflag)
- butType = UI_BTYPE_ICON_TOGGLE_N;
- else
- butType = UI_BTYPE_ICON_TOGGLE;
- }
- else {
- if (negflag)
- butType = UI_BTYPE_TOGGLE_N;
- else
- butType = UI_BTYPE_TOGGLE;
- }
- /* draw button for setting */
- if (ptr && flag) {
- switch (ptrsize) {
- case sizeof(int): /* integer pointer for setting */
- but = uiDefIconButBitI(block, butType, flag, 0, icon,
- xpos, ypos, ICON_WIDTH, ICON_WIDTH, ptr, 0, 0, 0, 0, tooltip);
- break;
-
- case sizeof(short): /* short pointer for setting */
- but = uiDefIconButBitS(block, butType, flag, 0, icon,
- xpos, ypos, ICON_WIDTH, ICON_WIDTH, ptr, 0, 0, 0, 0, tooltip);
- break;
-
- case sizeof(char): /* char pointer for setting */
- but = uiDefIconButBitC(block, butType, flag, 0, icon,
- xpos, ypos, ICON_WIDTH, ICON_WIDTH, ptr, 0, 0, 0, 0, tooltip);
- break;
- }
-
- /* set call to send relevant notifiers and/or perform type-specific updates */
- if (but) {
- switch (setting) {
- /* settings needing flushing up/down hierarchy */
- case ACHANNEL_SETTING_VISIBLE: /* Graph Editor - 'visibility' toggles */
- case ACHANNEL_SETTING_PROTECT: /* General - protection flags */
- case ACHANNEL_SETTING_MUTE: /* General - muting flags */
- case ACHANNEL_SETTING_PINNED: /* NLA Actions - 'map/nomap' */
- case ACHANNEL_SETTING_MOD_OFF:
- case ACHANNEL_SETTING_ALWAYS_VISIBLE:
- UI_but_funcN_set(but, achannel_setting_flush_widget_cb, MEM_dupallocN(ale), POINTER_FROM_INT(setting));
- break;
-
- /* settings needing special attention */
- case ACHANNEL_SETTING_SOLO: /* NLA Tracks - Solo toggle */
- UI_but_funcN_set(but, achannel_nlatrack_solo_widget_cb, MEM_dupallocN(ale), NULL);
- break;
-
- /* no flushing */
- case ACHANNEL_SETTING_EXPAND: /* expanding - cannot flush,
- * otherwise all would open/close at once */
- default:
- UI_but_func_set(but, achannel_setting_widget_cb, NULL, NULL);
- break;
- }
- }
- }
-
- if ((ale->fcurve_owner_id != NULL && ID_IS_LINKED(ale->fcurve_owner_id)) ||
- (ale->id != NULL && ID_IS_LINKED(ale->id)))
- {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
+static void draw_setting_widget(bAnimContext *ac,
+ bAnimListElem *ale,
+ const bAnimChannelType *acf,
+ uiBlock *block,
+ int xpos,
+ int ypos,
+ int setting)
+{
+ short ptrsize, butType;
+ bool negflag;
+ bool usetoggle = true;
+ int flag, icon;
+ void *ptr;
+ const char *tooltip;
+ uiBut *but = NULL;
+ bool enabled;
+
+ /* get the flag and the pointer to that flag */
+ flag = acf->setting_flag(ac, setting, &negflag);
+ ptr = acf->setting_ptr(ale, setting, &ptrsize);
+ enabled = ANIM_channel_setting_get(ac, ale, setting);
+
+ /* get the base icon for the setting */
+ switch (setting) {
+ case ACHANNEL_SETTING_VISIBLE: /* visibility eyes */
+ //icon = ((enabled) ? ICON_VISIBLE_IPO_ON : ICON_VISIBLE_IPO_OFF);
+ icon = ICON_VISIBLE_IPO_OFF;
+
+ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE))
+ tooltip = TIP_("F-Curve is visible in Graph Editor for editing");
+ else if (ale->type == ANIMTYPE_GPLAYER)
+ tooltip = TIP_("Grease Pencil layer is visible in the viewport");
+ else
+ tooltip = TIP_("Channels are visible in Graph Editor for editing");
+ break;
+
+ case ACHANNEL_SETTING_ALWAYS_VISIBLE:
+ icon = ICON_UNPINNED;
+ tooltip = TIP_("Channels are visible in Graph Editor for editing");
+ break;
+
+ case ACHANNEL_SETTING_MOD_OFF: /* modifiers disabled */
+ icon = ICON_MODIFIER_OFF;
+ tooltip = TIP_("F-Curve modifiers are disabled");
+ break;
+
+ case ACHANNEL_SETTING_EXPAND: /* expanded triangle */
+ //icon = ((enabled) ? ICON_TRIA_DOWN : ICON_TRIA_RIGHT);
+ icon = ICON_TRIA_RIGHT;
+ tooltip = TIP_("Make channels grouped under this channel visible");
+ break;
+
+ case ACHANNEL_SETTING_SOLO: /* NLA Tracks only */
+ //icon = ((enabled) ? ICON_SOLO_OFF : ICON_SOLO_ON);
+ icon = ICON_SOLO_OFF;
+ tooltip = TIP_(
+ "NLA Track is the only one evaluated in this animation data-block, with all others "
+ "muted");
+ break;
+
+ /* --- */
+
+ case ACHANNEL_SETTING_PROTECT: /* protected lock */
+ // TODO: what about when there's no protect needed?
+ //icon = ((enabled) ? ICON_LOCKED : ICON_UNLOCKED);
+ icon = ICON_UNLOCKED;
+
+ if (ale->datatype != ALE_NLASTRIP)
+ tooltip = TIP_("Editability of keyframes for this channel");
+ else
+ tooltip = TIP_("Editability of NLA Strips in this track");
+ break;
+
+ case ACHANNEL_SETTING_MUTE: /* muted speaker */
+ icon = ((enabled) ? ICON_CHECKBOX_DEHLT : ICON_CHECKBOX_HLT);
+ usetoggle = false;
+
+ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
+ tooltip = TIP_("Does F-Curve contribute to result");
+ }
+ else if ((ac) && (ac->spacetype == SPACE_NLA) && (ale->type != ANIMTYPE_NLATRACK)) {
+ tooltip = TIP_(
+ "Temporarily disable NLA stack evaluation (i.e. only the active action is evaluated)");
+ }
+ else if (ale->type == ANIMTYPE_GPLAYER) {
+ tooltip = TIP_("Lock current frame displayed by layer (i.e. disable animation playback)");
+ }
+ else {
+ tooltip = TIP_("Do channels contribute to result (toggle channel muting)");
+ }
+ break;
+
+ case ACHANNEL_SETTING_PINNED: /* pin icon */
+ //icon = ((enabled) ? ICON_PINNED : ICON_UNPINNED);
+ icon = ICON_UNPINNED;
+
+ if (ale->type == ANIMTYPE_NLAACTION) {
+ tooltip = TIP_("Display action without any time remapping (when unpinned)");
+ }
+ else {
+ /* TODO: there are no other tools which require the 'pinning' concept yet */
+ tooltip = NULL;
+ }
+ break;
+
+ default:
+ tooltip = NULL;
+ icon = 0;
+ break;
+ }
+
+ /* type of button */
+ if (usetoggle) {
+ if (negflag)
+ butType = UI_BTYPE_ICON_TOGGLE_N;
+ else
+ butType = UI_BTYPE_ICON_TOGGLE;
+ }
+ else {
+ if (negflag)
+ butType = UI_BTYPE_TOGGLE_N;
+ else
+ butType = UI_BTYPE_TOGGLE;
+ }
+ /* draw button for setting */
+ if (ptr && flag) {
+ switch (ptrsize) {
+ case sizeof(int): /* integer pointer for setting */
+ but = uiDefIconButBitI(block,
+ butType,
+ flag,
+ 0,
+ icon,
+ xpos,
+ ypos,
+ ICON_WIDTH,
+ ICON_WIDTH,
+ ptr,
+ 0,
+ 0,
+ 0,
+ 0,
+ tooltip);
+ break;
+
+ case sizeof(short): /* short pointer for setting */
+ but = uiDefIconButBitS(block,
+ butType,
+ flag,
+ 0,
+ icon,
+ xpos,
+ ypos,
+ ICON_WIDTH,
+ ICON_WIDTH,
+ ptr,
+ 0,
+ 0,
+ 0,
+ 0,
+ tooltip);
+ break;
+
+ case sizeof(char): /* char pointer for setting */
+ but = uiDefIconButBitC(block,
+ butType,
+ flag,
+ 0,
+ icon,
+ xpos,
+ ypos,
+ ICON_WIDTH,
+ ICON_WIDTH,
+ ptr,
+ 0,
+ 0,
+ 0,
+ 0,
+ tooltip);
+ break;
+ }
+
+ /* set call to send relevant notifiers and/or perform type-specific updates */
+ if (but) {
+ switch (setting) {
+ /* settings needing flushing up/down hierarchy */
+ case ACHANNEL_SETTING_VISIBLE: /* Graph Editor - 'visibility' toggles */
+ case ACHANNEL_SETTING_PROTECT: /* General - protection flags */
+ case ACHANNEL_SETTING_MUTE: /* General - muting flags */
+ case ACHANNEL_SETTING_PINNED: /* NLA Actions - 'map/nomap' */
+ case ACHANNEL_SETTING_MOD_OFF:
+ case ACHANNEL_SETTING_ALWAYS_VISIBLE:
+ UI_but_funcN_set(but,
+ achannel_setting_flush_widget_cb,
+ MEM_dupallocN(ale),
+ POINTER_FROM_INT(setting));
+ break;
+
+ /* settings needing special attention */
+ case ACHANNEL_SETTING_SOLO: /* NLA Tracks - Solo toggle */
+ UI_but_funcN_set(but, achannel_nlatrack_solo_widget_cb, MEM_dupallocN(ale), NULL);
+ break;
+
+ /* no flushing */
+ case ACHANNEL_SETTING_EXPAND: /* expanding - cannot flush,
+ * otherwise all would open/close at once */
+ default:
+ UI_but_func_set(but, achannel_setting_widget_cb, NULL, NULL);
+ break;
+ }
+ }
+ }
+
+ if ((ale->fcurve_owner_id != NULL && ID_IS_LINKED(ale->fcurve_owner_id)) ||
+ (ale->id != NULL && ID_IS_LINKED(ale->id))) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
}
/* Draw UI widgets the given channel */
-void ANIM_channel_draw_widgets(
- const bContext *C,
- bAnimContext *ac,
- bAnimListElem *ale,
- uiBlock *block,
- rctf *rect,
- size_t channel_index)
-{
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- View2D *v2d = &ac->ar->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);
-
- /* sanity checks - don't draw anything */
- if (ELEM(NULL, acf, ale, block))
- return;
-
- /* get initial offset */
- short offset = rect->xmin;
- if (acf->get_offset) {
- offset += acf->get_offset(ac, ale);
- }
-
- /* calculate appropriate y-coordinates for icon buttons */
- ymid = BLI_rctf_cent_y(rect) - 0.5f * ICON_WIDTH;
-
- /* no button backdrop behind icons */
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
- /* step 1) draw expand widget ....................................... */
- if (acf->has_setting(ac, ale, ACHANNEL_SETTING_EXPAND)) {
- draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_EXPAND);
- offset += ICON_WIDTH;
- }
-
- /* step 2) draw icon ............................................... */
- if (acf->icon) {
- /* icon is not drawn here (not a widget) */
- offset += ICON_WIDTH;
- }
-
- /* step 3) draw special toggles .................................
- * - in Graph Editor, checkboxes for visibility in curves area
- * - in NLA Editor, glowing dots for solo/not solo...
- * - in Grease Pencil mode, color swatches for layer color
- */
- if (ac->sl) {
- if ((ac->spacetype == SPACE_GRAPH) &&
- (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE) ||
- acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE)))
- {
- /* pin toggle */
- if (acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE)) {
- draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_ALWAYS_VISIBLE);
- offset += ICON_WIDTH;
- }
- /* visibility toggle */
- if (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
- draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_VISIBLE);
- offset += ICON_WIDTH;
- }
- }
- else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
- /* 'solo' setting for NLA Tracks */
- draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_SOLO);
- offset += ICON_WIDTH;
- }
- else if (ale->type == ANIMTYPE_GPLAYER) {
+void ANIM_channel_draw_widgets(const bContext *C,
+ bAnimContext *ac,
+ bAnimListElem *ale,
+ uiBlock *block,
+ rctf *rect,
+ size_t channel_index)
+{
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ View2D *v2d = &ac->ar->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);
+
+ /* sanity checks - don't draw anything */
+ if (ELEM(NULL, acf, ale, block))
+ return;
+
+ /* get initial offset */
+ short offset = rect->xmin;
+ if (acf->get_offset) {
+ offset += acf->get_offset(ac, ale);
+ }
+
+ /* calculate appropriate y-coordinates for icon buttons */
+ ymid = BLI_rctf_cent_y(rect) - 0.5f * ICON_WIDTH;
+
+ /* no button backdrop behind icons */
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+
+ /* step 1) draw expand widget ....................................... */
+ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_EXPAND)) {
+ draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_EXPAND);
+ offset += ICON_WIDTH;
+ }
+
+ /* step 2) draw icon ............................................... */
+ if (acf->icon) {
+ /* icon is not drawn here (not a widget) */
+ offset += ICON_WIDTH;
+ }
+
+ /* step 3) draw special toggles .................................
+ * - in Graph Editor, checkboxes for visibility in curves area
+ * - in NLA Editor, glowing dots for solo/not solo...
+ * - in Grease Pencil mode, color swatches for layer color
+ */
+ if (ac->sl) {
+ if ((ac->spacetype == SPACE_GRAPH) &&
+ (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE) ||
+ acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE))) {
+ /* pin toggle */
+ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE)) {
+ draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_ALWAYS_VISIBLE);
+ offset += ICON_WIDTH;
+ }
+ /* visibility toggle */
+ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
+ draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_VISIBLE);
+ offset += ICON_WIDTH;
+ }
+ }
+ else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
+ /* 'solo' setting for NLA Tracks */
+ 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;
+ /* 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... */
- if (is_being_renamed) {
- PointerRNA ptr = {{NULL}};
- PropertyRNA *prop = NULL;
-
- /* draw renaming widget if we can get RNA pointer for it
- * NOTE: property may only be available in some cases, even if we have
- * a callback available (e.g. broken F-Curve rename)
- */
- 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);
- uiBut *but;
-
- UI_block_emboss_set(block, UI_EMBOSS);
-
- but = uiDefButR(block, UI_BTYPE_TEXT, 1, "", offset + margin_x, rect->ymin,
- MAX2(width, RENAME_TEXT_MIN_WIDTH), channel_height,
- &ptr, RNA_property_identifier(prop), -1, 0, 0, -1, -1, NULL);
-
- /* copy what outliner does here, see outliner_buttons */
- if (UI_but_active_only(C, ac->ar, block, but) == false) {
- ac->ads->renameIndex = 0;
-
- /* send notifiers */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_RENAME, NULL);
- }
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- }
- else {
- /* Cannot get property/cannot or rename for some reason, so clear rename index
- * so that this doesn't hang around, and the name can be drawn normally - T47492
- */
- ac->ads->renameIndex = 0;
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, NULL);
- }
- }
-
- /* step 5) draw mute+protection toggles + (sliders) ....................... */
- /* reset offset - now goes from RHS of panel */
- offset = (int)rect->xmax;
-
- // TODO: when drawing sliders, make those draw instead of these toggles if not enough space
- if (v2d && !is_being_renamed) {
- short draw_sliders = 0;
-
- /* check if we need to show the sliders */
- if ((ac->sl) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_GRAPH)) {
- switch (ac->spacetype) {
- case SPACE_ACTION:
- {
- SpaceAction *saction = (SpaceAction *)ac->sl;
- draw_sliders = (saction->flag & SACTION_SLIDERS);
- break;
- }
- case SPACE_GRAPH:
- {
- SpaceGraph *sipo = (SpaceGraph *)ac->sl;
- draw_sliders = (sipo->flag & SIPO_SLIDERS);
- break;
- }
- }
- }
-
- /* check if there's enough space for the toggles if the sliders are drawn too */
- if (!(draw_sliders) || (BLI_rcti_size_x(&v2d->mask) > ACHANNEL_BUTTON_WIDTH / 2) ) {
- /* protect... */
- if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT)) {
- offset -= ICON_WIDTH;
- draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_PROTECT);
- }
- /* mute... */
- if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MUTE)) {
- offset -= ICON_WIDTH;
- draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_MUTE);
- }
- if (ale->type == ANIMTYPE_GPLAYER) {
- /* Not technically "mute" (in terms of anim channels, but this sets layer visibility instead) */
- offset -= ICON_WIDTH;
- draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_VISIBLE);
- }
-
- /* 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;
- draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_MOD_OFF);
- }
-
- /* ----------- */
-
- /* pinned... */
- if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PINNED)) {
- offset -= ICON_WIDTH;
- draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_PINNED);
- }
-
- /* NLA Action "pushdown" */
- if ((ale->type == ANIMTYPE_NLAACTION) && (ale->adt && ale->adt->action) && !(ale->adt->flag & ADT_NLA_EDIT_ON)) {
- uiBut *but;
- PointerRNA *opptr_b;
-
- UI_block_emboss_set(block, UI_EMBOSS);
-
- offset -= UI_UNIT_X;
- but = uiDefIconButO(block, UI_BTYPE_BUT, "NLA_OT_action_pushdown", WM_OP_INVOKE_DEFAULT, ICON_NLA_PUSHDOWN,
- offset, ymid, UI_UNIT_X, UI_UNIT_X, NULL);
-
- opptr_b = UI_but_operator_ptr_get(but);
- RNA_int_set(opptr_b, "channel_index", channel_index);
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- }
- }
-
- /* draw slider
- * - even if we can draw sliders for this view, we must also check that the channel-type supports them
- * (only only F-Curves really can support them for now)
- * - to make things easier, we use RNA-autobuts for this so that changes are reflected immediately,
- * wherever they occurred. BUT, we don't use the layout engine, otherwise we'd get wrong alignment,
- * and wouldn't be able to auto-keyframe...
- * - slider should start before the toggles (if they're visible) to keep a clean line down the side
- */
- if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE, ANIMTYPE_SHAPEKEY)) {
- /* adjust offset */
- // TODO: make slider width dynamic, so that they can be easier to use when the view is wide enough
- offset -= SLIDER_WIDTH;
-
- /* need backdrop behind sliders... */
- UI_block_emboss_set(block, UI_EMBOSS);
-
- if (ale->owner) { /* Slider using custom RNA Access ---------- */
- if (ale->type == ANIMTYPE_NLACURVE) {
- NlaStrip *strip = (NlaStrip *)ale->owner;
- FCurve *fcu = (FCurve *)ale->data;
- PointerRNA ptr;
- PropertyRNA *prop;
-
- /* create RNA pointers */
- RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, &ptr);
- prop = RNA_struct_find_property(&ptr, fcu->rna_path);
-
- /* create property slider */
- if (prop) {
- uiBut *but;
-
- /* create the slider button, and assign relevant callback to ensure keyframes are inserted... */
- but = uiDefAutoButR(block, &ptr, prop, fcu->array_index, "", ICON_NONE, offset, ymid, SLIDER_WIDTH, channel_height);
- UI_but_func_set(but, achannel_setting_slider_nla_curve_cb, ale->id, ale->data);
- }
- }
- }
- else if (ale->id) { /* Slider using RNA Access --------------- */
- PointerRNA id_ptr, ptr;
- PropertyRNA *prop;
- char *rna_path = NULL;
- int array_index = 0;
- short free_path = 0;
-
- /* get destination info */
- if (ale->type == ANIMTYPE_FCURVE) {
- FCurve *fcu = (FCurve *)ale->data;
-
- rna_path = fcu->rna_path;
- array_index = fcu->array_index;
- }
- else if (ale->type == ANIMTYPE_SHAPEKEY) {
- KeyBlock *kb = (KeyBlock *)ale->data;
- Key *key = (Key *)ale->id;
-
- rna_path = BKE_keyblock_curval_rnapath_get(key, kb);
- free_path = 1;
- }
-
- /* only if RNA-Path found */
- if (rna_path) {
- /* get RNA pointer, and resolve the path */
- RNA_id_pointer_create(ale->id, &id_ptr);
-
- /* try to resolve the path */
- if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop)) {
- uiBut *but;
-
- /* create the slider button, and assign relevant callback to ensure keyframes are inserted... */
- but = uiDefAutoButR(block, &ptr, prop, array_index, "", ICON_NONE, offset, ymid, SLIDER_WIDTH, channel_height);
-
- /* assign keyframing function according to slider type */
- if (ale->type == ANIMTYPE_SHAPEKEY)
- UI_but_func_set(but, achannel_setting_slider_shapekey_cb, ale->id, ale->data);
- else
- UI_but_func_set(but, achannel_setting_slider_cb, ale->id, ale->data);
- }
-
- /* free the path if necessary */
- if (free_path)
- MEM_freeN(rna_path);
- }
- }
- else { /* Special Slider for stuff without RNA Access ---------- */
- // TODO: only implement this case when we really need it...
- }
- }
- }
+ }
+ }
+
+ /* step 4) draw text - check if renaming widget is in use... */
+ if (is_being_renamed) {
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop = NULL;
+
+ /* draw renaming widget if we can get RNA pointer for it
+ * NOTE: property may only be available in some cases, even if we have
+ * a callback available (e.g. broken F-Curve rename)
+ */
+ 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);
+ uiBut *but;
+
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ but = uiDefButR(block,
+ UI_BTYPE_TEXT,
+ 1,
+ "",
+ offset + margin_x,
+ rect->ymin,
+ MAX2(width, RENAME_TEXT_MIN_WIDTH),
+ channel_height,
+ &ptr,
+ RNA_property_identifier(prop),
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+
+ /* copy what outliner does here, see outliner_buttons */
+ if (UI_but_active_only(C, ac->ar, block, but) == false) {
+ ac->ads->renameIndex = 0;
+
+ /* send notifiers */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_RENAME, NULL);
+ }
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ }
+ else {
+ /* Cannot get property/cannot or rename for some reason, so clear rename index
+ * so that this doesn't hang around, and the name can be drawn normally - T47492
+ */
+ ac->ads->renameIndex = 0;
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, NULL);
+ }
+ }
+
+ /* step 5) draw mute+protection toggles + (sliders) ....................... */
+ /* reset offset - now goes from RHS of panel */
+ offset = (int)rect->xmax;
+
+ // TODO: when drawing sliders, make those draw instead of these toggles if not enough space
+ if (v2d && !is_being_renamed) {
+ short draw_sliders = 0;
+
+ /* check if we need to show the sliders */
+ if ((ac->sl) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_GRAPH)) {
+ switch (ac->spacetype) {
+ case SPACE_ACTION: {
+ SpaceAction *saction = (SpaceAction *)ac->sl;
+ draw_sliders = (saction->flag & SACTION_SLIDERS);
+ break;
+ }
+ case SPACE_GRAPH: {
+ SpaceGraph *sipo = (SpaceGraph *)ac->sl;
+ draw_sliders = (sipo->flag & SIPO_SLIDERS);
+ break;
+ }
+ }
+ }
+
+ /* check if there's enough space for the toggles if the sliders are drawn too */
+ if (!(draw_sliders) || (BLI_rcti_size_x(&v2d->mask) > ACHANNEL_BUTTON_WIDTH / 2)) {
+ /* protect... */
+ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT)) {
+ offset -= ICON_WIDTH;
+ draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_PROTECT);
+ }
+ /* mute... */
+ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MUTE)) {
+ offset -= ICON_WIDTH;
+ draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_MUTE);
+ }
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ /* Not technically "mute" (in terms of anim channels, but this sets layer visibility instead) */
+ offset -= ICON_WIDTH;
+ draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_VISIBLE);
+ }
+
+ /* 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;
+ draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_MOD_OFF);
+ }
+
+ /* ----------- */
+
+ /* pinned... */
+ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PINNED)) {
+ offset -= ICON_WIDTH;
+ draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_PINNED);
+ }
+
+ /* NLA Action "pushdown" */
+ if ((ale->type == ANIMTYPE_NLAACTION) && (ale->adt && ale->adt->action) &&
+ !(ale->adt->flag & ADT_NLA_EDIT_ON)) {
+ uiBut *but;
+ PointerRNA *opptr_b;
+
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ offset -= UI_UNIT_X;
+ but = uiDefIconButO(block,
+ UI_BTYPE_BUT,
+ "NLA_OT_action_pushdown",
+ WM_OP_INVOKE_DEFAULT,
+ ICON_NLA_PUSHDOWN,
+ offset,
+ ymid,
+ UI_UNIT_X,
+ UI_UNIT_X,
+ NULL);
+
+ opptr_b = UI_but_operator_ptr_get(but);
+ RNA_int_set(opptr_b, "channel_index", channel_index);
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ }
+ }
+
+ /* draw slider
+ * - even if we can draw sliders for this view, we must also check that the channel-type supports them
+ * (only only F-Curves really can support them for now)
+ * - to make things easier, we use RNA-autobuts for this so that changes are reflected immediately,
+ * wherever they occurred. BUT, we don't use the layout engine, otherwise we'd get wrong alignment,
+ * and wouldn't be able to auto-keyframe...
+ * - slider should start before the toggles (if they're visible) to keep a clean line down the side
+ */
+ if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE, ANIMTYPE_SHAPEKEY)) {
+ /* adjust offset */
+ // TODO: make slider width dynamic, so that they can be easier to use when the view is wide enough
+ offset -= SLIDER_WIDTH;
+
+ /* need backdrop behind sliders... */
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ if (ale->owner) { /* Slider using custom RNA Access ---------- */
+ if (ale->type == ANIMTYPE_NLACURVE) {
+ NlaStrip *strip = (NlaStrip *)ale->owner;
+ FCurve *fcu = (FCurve *)ale->data;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ /* create RNA pointers */
+ RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, &ptr);
+ prop = RNA_struct_find_property(&ptr, fcu->rna_path);
+
+ /* create property slider */
+ if (prop) {
+ uiBut *but;
+
+ /* create the slider button, and assign relevant callback to ensure keyframes are inserted... */
+ but = uiDefAutoButR(block,
+ &ptr,
+ prop,
+ fcu->array_index,
+ "",
+ ICON_NONE,
+ offset,
+ ymid,
+ SLIDER_WIDTH,
+ channel_height);
+ UI_but_func_set(but, achannel_setting_slider_nla_curve_cb, ale->id, ale->data);
+ }
+ }
+ }
+ else if (ale->id) { /* Slider using RNA Access --------------- */
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ char *rna_path = NULL;
+ int array_index = 0;
+ short free_path = 0;
+
+ /* get destination info */
+ if (ale->type == ANIMTYPE_FCURVE) {
+ FCurve *fcu = (FCurve *)ale->data;
+
+ rna_path = fcu->rna_path;
+ array_index = fcu->array_index;
+ }
+ else if (ale->type == ANIMTYPE_SHAPEKEY) {
+ KeyBlock *kb = (KeyBlock *)ale->data;
+ Key *key = (Key *)ale->id;
+
+ rna_path = BKE_keyblock_curval_rnapath_get(key, kb);
+ free_path = 1;
+ }
+
+ /* only if RNA-Path found */
+ if (rna_path) {
+ /* get RNA pointer, and resolve the path */
+ RNA_id_pointer_create(ale->id, &id_ptr);
+
+ /* try to resolve the path */
+ if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop)) {
+ uiBut *but;
+
+ /* create the slider button, and assign relevant callback to ensure keyframes are inserted... */
+ but = uiDefAutoButR(block,
+ &ptr,
+ prop,
+ array_index,
+ "",
+ ICON_NONE,
+ offset,
+ ymid,
+ SLIDER_WIDTH,
+ channel_height);
+
+ /* assign keyframing function according to slider type */
+ if (ale->type == ANIMTYPE_SHAPEKEY)
+ UI_but_func_set(but, achannel_setting_slider_shapekey_cb, ale->id, ale->data);
+ else
+ UI_but_func_set(but, achannel_setting_slider_cb, ale->id, ale->data);
+ }
+
+ /* free the path if necessary */
+ if (free_path)
+ MEM_freeN(rna_path);
+ }
+ }
+ else { /* Special Slider for stuff without RNA Access ---------- */
+ // TODO: only implement this case when we really need it...
+ }
+ }
+ }
}
/* *********************************************** */
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 558c5d5bfc1..c2878a64e97 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -21,7 +21,6 @@
* \ingroup edanimation
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -59,7 +58,7 @@
#include "ED_anim_api.h"
#include "ED_armature.h"
-#include "ED_keyframes_edit.h" // XXX move the select modes out of there!
+#include "ED_keyframes_edit.h" // XXX move the select modes out of there!
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
@@ -74,178 +73,173 @@
/* Set the given animation-channel as the active one for the active context */
// TODO: extend for animdata types...
-void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datatype, eAnimFilter_Flags filter, void *channel_data, eAnim_ChannelType channel_type)
-{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
-
- /* try to build list of filtered items */
- ANIM_animdata_filter(ac, &anim_data, filter, data, datatype);
- if (BLI_listbase_is_empty(&anim_data))
- return;
-
- /* only clear the 'active' flag for the channels of the same type */
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* skip if types don't match */
- if (channel_type != ale->type)
- continue;
-
- /* flag to set depends on type */
- switch (ale->type) {
- case ANIMTYPE_GROUP:
- {
- bActionGroup *agrp = (bActionGroup *)ale->data;
-
- ACHANNEL_SET_FLAG(agrp, ACHANNEL_SETFLAG_CLEAR, AGRP_ACTIVE);
- break;
- }
- case ANIMTYPE_FCURVE:
- case ANIMTYPE_NLACURVE:
- {
- FCurve *fcu = (FCurve *)ale->data;
-
- ACHANNEL_SET_FLAG(fcu, ACHANNEL_SETFLAG_CLEAR, FCURVE_ACTIVE);
- break;
- }
- case ANIMTYPE_NLATRACK:
- {
- NlaTrack *nlt = (NlaTrack *)ale->data;
-
- ACHANNEL_SET_FLAG(nlt, ACHANNEL_SETFLAG_CLEAR, NLATRACK_ACTIVE);
- break;
- }
- case ANIMTYPE_FILLACTD: /* Action Expander */
- case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
- case ANIMTYPE_DSLAM:
- case ANIMTYPE_DSCAM:
- case ANIMTYPE_DSCACHEFILE:
- case ANIMTYPE_DSCUR:
- case ANIMTYPE_DSSKEY:
- case ANIMTYPE_DSWOR:
- case ANIMTYPE_DSPART:
- case ANIMTYPE_DSMBALL:
- case ANIMTYPE_DSARM:
- case ANIMTYPE_DSMESH:
- case ANIMTYPE_DSTEX:
- case ANIMTYPE_DSLAT:
- case ANIMTYPE_DSLINESTYLE:
- case ANIMTYPE_DSSPK:
- case ANIMTYPE_DSGPENCIL:
- case ANIMTYPE_DSMCLIP:
- {
- /* need to verify that this data is valid for now */
- if (ale->adt) {
- ACHANNEL_SET_FLAG(ale->adt, ACHANNEL_SETFLAG_CLEAR, ADT_UI_ACTIVE);
- }
- break;
- }
- case ANIMTYPE_GPLAYER:
- {
- bGPDlayer *gpl = (bGPDlayer *)ale->data;
-
- ACHANNEL_SET_FLAG(gpl, ACHANNEL_SETFLAG_CLEAR, GP_LAYER_ACTIVE);
- break;
- }
- }
- }
-
- /* set active flag */
- if (channel_data) {
- switch (channel_type) {
- case ANIMTYPE_GROUP:
- {
- bActionGroup *agrp = (bActionGroup *)channel_data;
- agrp->flag |= AGRP_ACTIVE;
- break;
- }
- case ANIMTYPE_FCURVE:
- case ANIMTYPE_NLACURVE:
- {
- FCurve *fcu = (FCurve *)channel_data;
- fcu->flag |= FCURVE_ACTIVE;
- break;
- }
- case ANIMTYPE_NLATRACK:
- {
- NlaTrack *nlt = (NlaTrack *)channel_data;
- nlt->flag |= NLATRACK_ACTIVE;
- break;
- }
- case ANIMTYPE_FILLACTD: /* Action Expander */
- case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
- case ANIMTYPE_DSLAM:
- case ANIMTYPE_DSCAM:
- case ANIMTYPE_DSCACHEFILE:
- case ANIMTYPE_DSCUR:
- case ANIMTYPE_DSSKEY:
- case ANIMTYPE_DSWOR:
- case ANIMTYPE_DSPART:
- case ANIMTYPE_DSMBALL:
- case ANIMTYPE_DSARM:
- case ANIMTYPE_DSMESH:
- case ANIMTYPE_DSLAT:
- case ANIMTYPE_DSLINESTYLE:
- case ANIMTYPE_DSSPK:
- case ANIMTYPE_DSNTREE:
- case ANIMTYPE_DSTEX:
- case ANIMTYPE_DSGPENCIL:
- case ANIMTYPE_DSMCLIP:
- {
- /* need to verify that this data is valid for now */
- if (ale && ale->adt) {
- ale->adt->flag |= ADT_UI_ACTIVE;
- }
- break;
- }
-
- case ANIMTYPE_GPLAYER:
- {
- bGPDlayer *gpl = (bGPDlayer *)channel_data;
- gpl->flag |= GP_LAYER_ACTIVE;
- break;
- }
-
- /* unhandled currently, but may be interesting */
- case ANIMTYPE_MASKLAYER:
- case ANIMTYPE_SHAPEKEY:
- case ANIMTYPE_NLAACTION:
- break;
-
- /* other types */
- default:
- break;
- }
- }
-
- /* clean up */
- ANIM_animdata_freelist(&anim_data);
+void ANIM_set_active_channel(bAnimContext *ac,
+ void *data,
+ eAnimCont_Types datatype,
+ eAnimFilter_Flags filter,
+ void *channel_data,
+ eAnim_ChannelType channel_type)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+
+ /* try to build list of filtered items */
+ ANIM_animdata_filter(ac, &anim_data, filter, data, datatype);
+ if (BLI_listbase_is_empty(&anim_data))
+ return;
+
+ /* only clear the 'active' flag for the channels of the same type */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* skip if types don't match */
+ if (channel_type != ale->type)
+ continue;
+
+ /* flag to set depends on type */
+ switch (ale->type) {
+ case ANIMTYPE_GROUP: {
+ bActionGroup *agrp = (bActionGroup *)ale->data;
+
+ ACHANNEL_SET_FLAG(agrp, ACHANNEL_SETFLAG_CLEAR, AGRP_ACTIVE);
+ break;
+ }
+ case ANIMTYPE_FCURVE:
+ case ANIMTYPE_NLACURVE: {
+ FCurve *fcu = (FCurve *)ale->data;
+
+ ACHANNEL_SET_FLAG(fcu, ACHANNEL_SETFLAG_CLEAR, FCURVE_ACTIVE);
+ break;
+ }
+ case ANIMTYPE_NLATRACK: {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+
+ ACHANNEL_SET_FLAG(nlt, ACHANNEL_SETFLAG_CLEAR, NLATRACK_ACTIVE);
+ break;
+ }
+ case ANIMTYPE_FILLACTD: /* Action Expander */
+ case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
+ case ANIMTYPE_DSLAM:
+ case ANIMTYPE_DSCAM:
+ case ANIMTYPE_DSCACHEFILE:
+ case ANIMTYPE_DSCUR:
+ case ANIMTYPE_DSSKEY:
+ case ANIMTYPE_DSWOR:
+ case ANIMTYPE_DSPART:
+ case ANIMTYPE_DSMBALL:
+ case ANIMTYPE_DSARM:
+ case ANIMTYPE_DSMESH:
+ case ANIMTYPE_DSTEX:
+ case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
+ case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSGPENCIL:
+ case ANIMTYPE_DSMCLIP: {
+ /* need to verify that this data is valid for now */
+ if (ale->adt) {
+ ACHANNEL_SET_FLAG(ale->adt, ACHANNEL_SETFLAG_CLEAR, ADT_UI_ACTIVE);
+ }
+ break;
+ }
+ case ANIMTYPE_GPLAYER: {
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+
+ ACHANNEL_SET_FLAG(gpl, ACHANNEL_SETFLAG_CLEAR, GP_LAYER_ACTIVE);
+ break;
+ }
+ }
+ }
+
+ /* set active flag */
+ if (channel_data) {
+ switch (channel_type) {
+ case ANIMTYPE_GROUP: {
+ bActionGroup *agrp = (bActionGroup *)channel_data;
+ agrp->flag |= AGRP_ACTIVE;
+ break;
+ }
+ case ANIMTYPE_FCURVE:
+ case ANIMTYPE_NLACURVE: {
+ FCurve *fcu = (FCurve *)channel_data;
+ fcu->flag |= FCURVE_ACTIVE;
+ break;
+ }
+ case ANIMTYPE_NLATRACK: {
+ NlaTrack *nlt = (NlaTrack *)channel_data;
+ nlt->flag |= NLATRACK_ACTIVE;
+ break;
+ }
+ case ANIMTYPE_FILLACTD: /* Action Expander */
+ case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
+ case ANIMTYPE_DSLAM:
+ case ANIMTYPE_DSCAM:
+ case ANIMTYPE_DSCACHEFILE:
+ case ANIMTYPE_DSCUR:
+ case ANIMTYPE_DSSKEY:
+ case ANIMTYPE_DSWOR:
+ case ANIMTYPE_DSPART:
+ case ANIMTYPE_DSMBALL:
+ case ANIMTYPE_DSARM:
+ case ANIMTYPE_DSMESH:
+ case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
+ case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSNTREE:
+ case ANIMTYPE_DSTEX:
+ case ANIMTYPE_DSGPENCIL:
+ case ANIMTYPE_DSMCLIP: {
+ /* need to verify that this data is valid for now */
+ if (ale && ale->adt) {
+ ale->adt->flag |= ADT_UI_ACTIVE;
+ }
+ break;
+ }
+
+ case ANIMTYPE_GPLAYER: {
+ bGPDlayer *gpl = (bGPDlayer *)channel_data;
+ gpl->flag |= GP_LAYER_ACTIVE;
+ break;
+ }
+
+ /* unhandled currently, but may be interesting */
+ case ANIMTYPE_MASKLAYER:
+ case ANIMTYPE_SHAPEKEY:
+ case ANIMTYPE_NLAACTION:
+ break;
+
+ /* other types */
+ default:
+ break;
+ }
+ }
+
+ /* clean up */
+ ANIM_animdata_freelist(&anim_data);
}
static void select_pchan_for_action_group(bAnimContext *ac, bActionGroup *agrp, bAnimListElem *ale)
{
- /* Armatures-Specific Feature:
- * See mouse_anim_channels() -> ANIMTYPE_GROUP case for more details (T38737)
- */
- if ((ac->ads->filterflag & ADS_FILTER_ONLYSEL) == 0) {
- if ((ale->id) && (GS(ale->id->name) == ID_OB)) {
- Object *ob = (Object *)ale->id;
- if (ob->type == OB_ARMATURE) {
- /* Assume for now that any group with corresponding name is what we want
- * (i.e. for an armature whose location is animated, things would break
- * if the user were to add a bone named "Location").
- *
- * TODO: check the first F-Curve or so to be sure...
- */
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, agrp->name);
- if (agrp->flag & AGRP_SELECTED) {
- ED_pose_bone_select(ob, pchan, true);
- }
- else {
- ED_pose_bone_select(ob, pchan, false);
- }
- }
- }
- }
+ /* Armatures-Specific Feature:
+ * See mouse_anim_channels() -> ANIMTYPE_GROUP case for more details (T38737)
+ */
+ if ((ac->ads->filterflag & ADS_FILTER_ONLYSEL) == 0) {
+ if ((ale->id) && (GS(ale->id->name) == ID_OB)) {
+ Object *ob = (Object *)ale->id;
+ if (ob->type == OB_ARMATURE) {
+ /* Assume for now that any group with corresponding name is what we want
+ * (i.e. for an armature whose location is animated, things would break
+ * if the user were to add a bone named "Location").
+ *
+ * TODO: check the first F-Curve or so to be sure...
+ */
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, agrp->name);
+ if (agrp->flag & AGRP_SELECTED) {
+ ED_pose_bone_select(ob, pchan, true);
+ }
+ else {
+ ED_pose_bone_select(ob, pchan, false);
+ }
+ }
+ }
+ }
}
/* Deselect all animation channels
@@ -254,195 +248,186 @@ static void select_pchan_for_action_group(bAnimContext *ac, bActionGroup *agrp,
* - test: check if deselecting instead of selecting
* - sel: eAnimChannels_SetFlag;
*/
-void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types datatype, bool test, eAnimChannels_SetFlag sel)
-{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* filter data */
- /* NOTE: no list visible, otherwise, we get dangling */
- filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS;
- ANIM_animdata_filter(ac, &anim_data, filter, data, datatype);
-
- /* See if we should be selecting or deselecting */
- if (test) {
- for (ale = anim_data.first; ale; ale = ale->next) {
- if (sel == 0)
- break;
-
- switch (ale->type) {
- case ANIMTYPE_SCENE:
- if (ale->flag & SCE_DS_SELECTED)
- sel = ACHANNEL_SETFLAG_CLEAR;
- break;
- case ANIMTYPE_OBJECT:
-#if 0 /* for now, do not take object selection into account, since it gets too annoying */
- if (ale->flag & SELECT)
- sel = ACHANNEL_SETFLAG_CLEAR;
+void ANIM_deselect_anim_channels(
+ bAnimContext *ac, void *data, eAnimCont_Types datatype, bool test, eAnimChannels_SetFlag sel)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ /* NOTE: no list visible, otherwise, we get dangling */
+ filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS;
+ ANIM_animdata_filter(ac, &anim_data, filter, data, datatype);
+
+ /* See if we should be selecting or deselecting */
+ if (test) {
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (sel == 0)
+ break;
+
+ switch (ale->type) {
+ case ANIMTYPE_SCENE:
+ if (ale->flag & SCE_DS_SELECTED)
+ sel = ACHANNEL_SETFLAG_CLEAR;
+ break;
+ case ANIMTYPE_OBJECT:
+#if 0 /* for now, do not take object selection into account, since it gets too annoying */
+ if (ale->flag & SELECT)
+ sel = ACHANNEL_SETFLAG_CLEAR;
#endif
- break;
- case ANIMTYPE_GROUP:
- if (ale->flag & AGRP_SELECTED)
- sel = ACHANNEL_SETFLAG_CLEAR;
- break;
- case ANIMTYPE_FCURVE:
- case ANIMTYPE_NLACURVE:
- if (ale->flag & FCURVE_SELECTED)
- sel = ACHANNEL_SETFLAG_CLEAR;
- break;
- case ANIMTYPE_SHAPEKEY:
- if (ale->flag & KEYBLOCK_SEL)
- sel = ACHANNEL_SETFLAG_CLEAR;
- break;
- case ANIMTYPE_NLATRACK:
- if (ale->flag & NLATRACK_SELECTED)
- sel = ACHANNEL_SETFLAG_CLEAR;
- break;
-
- case ANIMTYPE_FILLACTD: /* Action Expander */
- case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
- case ANIMTYPE_DSLAM:
- case ANIMTYPE_DSCAM:
- case ANIMTYPE_DSCACHEFILE:
- case ANIMTYPE_DSCUR:
- case ANIMTYPE_DSSKEY:
- case ANIMTYPE_DSWOR:
- case ANIMTYPE_DSPART:
- case ANIMTYPE_DSMBALL:
- case ANIMTYPE_DSARM:
- case ANIMTYPE_DSMESH:
- case ANIMTYPE_DSNTREE:
- case ANIMTYPE_DSTEX:
- case ANIMTYPE_DSLAT:
- case ANIMTYPE_DSLINESTYLE:
- case ANIMTYPE_DSSPK:
- case ANIMTYPE_DSGPENCIL:
- case ANIMTYPE_DSMCLIP:
- {
- if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED))
- sel = ACHANNEL_SETFLAG_CLEAR;
- break;
- }
- case ANIMTYPE_GPLAYER:
- if (ale->flag & GP_LAYER_SELECT)
- sel = ACHANNEL_SETFLAG_CLEAR;
- break;
- case ANIMTYPE_MASKLAYER:
- if (ale->flag & MASK_LAYERFLAG_SELECT)
- sel = ACHANNEL_SETFLAG_CLEAR;
- break;
- }
- }
- }
-
- /* Now set the flags */
- for (ale = anim_data.first; ale; ale = ale->next) {
- switch (ale->type) {
- case ANIMTYPE_SCENE:
- {
- Scene *scene = (Scene *)ale->data;
-
- ACHANNEL_SET_FLAG(scene, sel, SCE_DS_SELECTED);
-
- if (scene->adt) {
- ACHANNEL_SET_FLAG(scene, sel, ADT_UI_SELECTED);
- }
- break;
- }
- case ANIMTYPE_OBJECT:
- {
-#if 0 /* for now, do not take object selection into account, since it gets too annoying */
- Base *base = (Base *)ale->data;
- Object *ob = base->object;
-
- ACHANNEL_SET_FLAG(base, sel, SELECT);
- ACHANNEL_SET_FLAG(ob, sel, SELECT);
-
- if (ob->adt) {
- ACHANNEL_SET_FLAG(ob, sel, ADT_UI_SELECTED);
- }
+ break;
+ case ANIMTYPE_GROUP:
+ if (ale->flag & AGRP_SELECTED)
+ sel = ACHANNEL_SETFLAG_CLEAR;
+ break;
+ case ANIMTYPE_FCURVE:
+ case ANIMTYPE_NLACURVE:
+ if (ale->flag & FCURVE_SELECTED)
+ sel = ACHANNEL_SETFLAG_CLEAR;
+ break;
+ case ANIMTYPE_SHAPEKEY:
+ if (ale->flag & KEYBLOCK_SEL)
+ sel = ACHANNEL_SETFLAG_CLEAR;
+ break;
+ case ANIMTYPE_NLATRACK:
+ if (ale->flag & NLATRACK_SELECTED)
+ sel = ACHANNEL_SETFLAG_CLEAR;
+ break;
+
+ case ANIMTYPE_FILLACTD: /* Action Expander */
+ case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
+ case ANIMTYPE_DSLAM:
+ case ANIMTYPE_DSCAM:
+ case ANIMTYPE_DSCACHEFILE:
+ case ANIMTYPE_DSCUR:
+ case ANIMTYPE_DSSKEY:
+ case ANIMTYPE_DSWOR:
+ case ANIMTYPE_DSPART:
+ case ANIMTYPE_DSMBALL:
+ case ANIMTYPE_DSARM:
+ case ANIMTYPE_DSMESH:
+ case ANIMTYPE_DSNTREE:
+ case ANIMTYPE_DSTEX:
+ case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
+ case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSGPENCIL:
+ case ANIMTYPE_DSMCLIP: {
+ if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED))
+ sel = ACHANNEL_SETFLAG_CLEAR;
+ break;
+ }
+ case ANIMTYPE_GPLAYER:
+ if (ale->flag & GP_LAYER_SELECT)
+ sel = ACHANNEL_SETFLAG_CLEAR;
+ break;
+ case ANIMTYPE_MASKLAYER:
+ if (ale->flag & MASK_LAYERFLAG_SELECT)
+ sel = ACHANNEL_SETFLAG_CLEAR;
+ break;
+ }
+ }
+ }
+
+ /* Now set the flags */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ switch (ale->type) {
+ case ANIMTYPE_SCENE: {
+ Scene *scene = (Scene *)ale->data;
+
+ ACHANNEL_SET_FLAG(scene, sel, SCE_DS_SELECTED);
+
+ if (scene->adt) {
+ ACHANNEL_SET_FLAG(scene, sel, ADT_UI_SELECTED);
+ }
+ break;
+ }
+ case ANIMTYPE_OBJECT: {
+#if 0 /* for now, do not take object selection into account, since it gets too annoying */
+ Base *base = (Base *)ale->data;
+ Object *ob = base->object;
+
+ ACHANNEL_SET_FLAG(base, sel, SELECT);
+ ACHANNEL_SET_FLAG(ob, sel, SELECT);
+
+ if (ob->adt) {
+ ACHANNEL_SET_FLAG(ob, sel, ADT_UI_SELECTED);
+ }
#endif
- break;
- }
- case ANIMTYPE_GROUP:
- {
- bActionGroup *agrp = (bActionGroup *)ale->data;
- ACHANNEL_SET_FLAG(agrp, sel, AGRP_SELECTED);
- select_pchan_for_action_group(ac, agrp, ale);
- agrp->flag &= ~AGRP_ACTIVE;
- break;
- }
- case ANIMTYPE_FCURVE:
- case ANIMTYPE_NLACURVE:
- {
- FCurve *fcu = (FCurve *)ale->data;
-
- ACHANNEL_SET_FLAG(fcu, sel, FCURVE_SELECTED);
- fcu->flag &= ~FCURVE_ACTIVE;
- break;
- }
- case ANIMTYPE_SHAPEKEY:
- {
- KeyBlock *kb = (KeyBlock *)ale->data;
-
- ACHANNEL_SET_FLAG(kb, sel, KEYBLOCK_SEL);
- break;
- }
- case ANIMTYPE_NLATRACK:
- {
- NlaTrack *nlt = (NlaTrack *)ale->data;
-
- ACHANNEL_SET_FLAG(nlt, sel, NLATRACK_SELECTED);
- nlt->flag &= ~NLATRACK_ACTIVE;
- break;
- }
- case ANIMTYPE_FILLACTD: /* Action Expander */
- case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
- case ANIMTYPE_DSLAM:
- case ANIMTYPE_DSCAM:
- case ANIMTYPE_DSCACHEFILE:
- case ANIMTYPE_DSCUR:
- case ANIMTYPE_DSSKEY:
- case ANIMTYPE_DSWOR:
- case ANIMTYPE_DSPART:
- case ANIMTYPE_DSMBALL:
- case ANIMTYPE_DSARM:
- case ANIMTYPE_DSMESH:
- case ANIMTYPE_DSNTREE:
- case ANIMTYPE_DSTEX:
- case ANIMTYPE_DSLAT:
- case ANIMTYPE_DSLINESTYLE:
- case ANIMTYPE_DSSPK:
- case ANIMTYPE_DSGPENCIL:
- case ANIMTYPE_DSMCLIP:
- {
- /* need to verify that this data is valid for now */
- if (ale->adt) {
- ACHANNEL_SET_FLAG(ale->adt, sel, ADT_UI_SELECTED);
- ale->adt->flag &= ~ADT_UI_ACTIVE;
- }
- break;
- }
- case ANIMTYPE_GPLAYER:
- {
- bGPDlayer *gpl = (bGPDlayer *)ale->data;
-
- ACHANNEL_SET_FLAG(gpl, sel, GP_LAYER_SELECT);
- break;
- }
- case ANIMTYPE_MASKLAYER:
- {
- MaskLayer *masklay = (MaskLayer *)ale->data;
-
- ACHANNEL_SET_FLAG(masklay, sel, MASK_LAYERFLAG_SELECT);
- break;
- }
- }
- }
-
- /* Cleanup */
- ANIM_animdata_freelist(&anim_data);
+ break;
+ }
+ case ANIMTYPE_GROUP: {
+ bActionGroup *agrp = (bActionGroup *)ale->data;
+ ACHANNEL_SET_FLAG(agrp, sel, AGRP_SELECTED);
+ select_pchan_for_action_group(ac, agrp, ale);
+ agrp->flag &= ~AGRP_ACTIVE;
+ break;
+ }
+ case ANIMTYPE_FCURVE:
+ case ANIMTYPE_NLACURVE: {
+ FCurve *fcu = (FCurve *)ale->data;
+
+ ACHANNEL_SET_FLAG(fcu, sel, FCURVE_SELECTED);
+ fcu->flag &= ~FCURVE_ACTIVE;
+ break;
+ }
+ case ANIMTYPE_SHAPEKEY: {
+ KeyBlock *kb = (KeyBlock *)ale->data;
+
+ ACHANNEL_SET_FLAG(kb, sel, KEYBLOCK_SEL);
+ break;
+ }
+ case ANIMTYPE_NLATRACK: {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+
+ ACHANNEL_SET_FLAG(nlt, sel, NLATRACK_SELECTED);
+ nlt->flag &= ~NLATRACK_ACTIVE;
+ break;
+ }
+ case ANIMTYPE_FILLACTD: /* Action Expander */
+ case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
+ case ANIMTYPE_DSLAM:
+ case ANIMTYPE_DSCAM:
+ case ANIMTYPE_DSCACHEFILE:
+ case ANIMTYPE_DSCUR:
+ case ANIMTYPE_DSSKEY:
+ case ANIMTYPE_DSWOR:
+ case ANIMTYPE_DSPART:
+ case ANIMTYPE_DSMBALL:
+ case ANIMTYPE_DSARM:
+ case ANIMTYPE_DSMESH:
+ case ANIMTYPE_DSNTREE:
+ case ANIMTYPE_DSTEX:
+ case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
+ case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSGPENCIL:
+ case ANIMTYPE_DSMCLIP: {
+ /* need to verify that this data is valid for now */
+ if (ale->adt) {
+ ACHANNEL_SET_FLAG(ale->adt, sel, ADT_UI_SELECTED);
+ ale->adt->flag &= ~ADT_UI_ACTIVE;
+ }
+ break;
+ }
+ case ANIMTYPE_GPLAYER: {
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+
+ ACHANNEL_SET_FLAG(gpl, sel, GP_LAYER_SELECT);
+ break;
+ }
+ case ANIMTYPE_MASKLAYER: {
+ MaskLayer *masklay = (MaskLayer *)ale->data;
+
+ ACHANNEL_SET_FLAG(masklay, sel, MASK_LAYERFLAG_SELECT);
+ break;
+ }
+ }
+ }
+
+ /* Cleanup */
+ ANIM_animdata_freelist(&anim_data);
}
/* ---------------------------- Graph Editor ------------------------------------- */
@@ -456,137 +441,140 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
* - setting: type of setting to set
* - on: whether the visibility setting has been enabled or disabled
*/
-void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAnimListElem *ale_setting, eAnimChannel_Settings setting, eAnimChannels_SetFlag mode)
-{
- bAnimListElem *ale, *match = NULL;
- int prevLevel = 0, matchLevel = 0;
-
- /* sanity check */
- if (ELEM(NULL, anim_data, anim_data->first))
- return;
-
- if (setting == ACHANNEL_SETTING_ALWAYS_VISIBLE) {
- return;
- }
-
- /* find the channel that got changed */
- for (ale = anim_data->first; ale; ale = ale->next) {
- /* compare data, and type as main way of identifying the channel */
- if ((ale->data == ale_setting->data) && (ale->type == ale_setting->type)) {
- /* we also have to check the ID, this is assigned to, since a block may have multiple users */
- /* TODO: is the owner-data more revealing? */
- if (ale->id == ale_setting->id) {
- match = ale;
- break;
- }
- }
- }
- if (match == NULL) {
- printf("ERROR: no channel matching the one changed was found\n");
- return;
- }
- else {
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale_setting);
-
- if (acf == NULL) {
- printf("ERROR: no channel info for the changed channel\n");
- return;
- }
-
- /* get the level of the channel that was affected
- * - we define the level as simply being the offset for the start of the channel
- */
- matchLevel = (acf->get_offset) ? acf->get_offset(ac, ale_setting) : 0;
- prevLevel = matchLevel;
- }
-
- /* flush up?
- *
- * For Visibility:
- * - only flush up if the current state is now enabled (positive 'on' state is default)
- * (otherwise, it's too much work to force the parents to be inactive too)
- *
- * For everything else:
- * - only flush up if the current state is now disabled (negative 'off' state is default)
- * (otherwise, it's too much work to force the parents to be active too)
- */
- if ( ((setting == ACHANNEL_SETTING_VISIBLE) && (mode != ACHANNEL_SETFLAG_CLEAR)) ||
- ((setting != ACHANNEL_SETTING_VISIBLE) && (mode == ACHANNEL_SETFLAG_CLEAR)))
- {
- /* go backwards in the list, until the highest-ranking element (by indention has been covered) */
- for (ale = match->prev; ale; ale = ale->prev) {
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- int level;
-
- /* if no channel info was found, skip, since this type might not have any useful info */
- if (acf == NULL)
- continue;
-
- /* get the level of the current channel traversed
- * - we define the level as simply being the offset for the start of the channel
- */
- level = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
-
- /* if the level is 'less than' (i.e. more important) the level we're matching
- * but also 'less than' the level just tried (i.e. only the 1st group above grouped F-Curves,
- * when toggling visibility of F-Curves, gets flushed, which should happen if we don't let prevLevel
- * get updated below once the first 1st group is found)...
- */
- if (level < prevLevel) {
- /* flush the new status... */
- ANIM_channel_setting_set(ac, ale, setting, mode);
-
- /* store this level as the 'old' level now */
- prevLevel = level;
- }
- /* if the level is 'greater than' (i.e. less important) than the previous level... */
- else if (level > prevLevel) {
- /* if previous level was a base-level (i.e. 0 offset / root of one hierarchy),
- * stop here
- */
- if (prevLevel == 0)
- break;
- /* otherwise, this level weaves into another sibling hierarchy to the previous one just
- * finished, so skip until we get to the parent of this level
- */
- else
- continue;
- }
- }
- }
-
- /* flush down (always) */
- {
- /* go forwards in the list, until the lowest-ranking element (by indention has been covered) */
- for (ale = match->next; ale; ale = ale->next) {
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- int level;
-
- /* if no channel info was found, skip, since this type might not have any useful info */
- if (acf == NULL)
- continue;
-
- /* get the level of the current channel traversed
- * - we define the level as simply being the offset for the start of the channel
- */
- level = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
-
- /* if the level is 'greater than' (i.e. less important) the channel that was changed,
- * flush the new status...
- */
- if (level > matchLevel)
- ANIM_channel_setting_set(ac, ale, setting, mode);
- /* however, if the level is 'less than or equal to' the channel that was changed,
- * (i.e. the current channel is as important if not more important than the changed channel)
- * then we should stop, since we've found the last one of the children we should flush
- */
- else
- break;
-
- /* store this level as the 'old' level now */
- // prevLevel = level; // XXX: prevLevel is unused
- }
- }
+void ANIM_flush_setting_anim_channels(bAnimContext *ac,
+ ListBase *anim_data,
+ bAnimListElem *ale_setting,
+ eAnimChannel_Settings setting,
+ eAnimChannels_SetFlag mode)
+{
+ bAnimListElem *ale, *match = NULL;
+ int prevLevel = 0, matchLevel = 0;
+
+ /* sanity check */
+ if (ELEM(NULL, anim_data, anim_data->first))
+ return;
+
+ if (setting == ACHANNEL_SETTING_ALWAYS_VISIBLE) {
+ return;
+ }
+
+ /* find the channel that got changed */
+ for (ale = anim_data->first; ale; ale = ale->next) {
+ /* compare data, and type as main way of identifying the channel */
+ if ((ale->data == ale_setting->data) && (ale->type == ale_setting->type)) {
+ /* we also have to check the ID, this is assigned to, since a block may have multiple users */
+ /* TODO: is the owner-data more revealing? */
+ if (ale->id == ale_setting->id) {
+ match = ale;
+ break;
+ }
+ }
+ }
+ if (match == NULL) {
+ printf("ERROR: no channel matching the one changed was found\n");
+ return;
+ }
+ else {
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale_setting);
+
+ if (acf == NULL) {
+ printf("ERROR: no channel info for the changed channel\n");
+ return;
+ }
+
+ /* get the level of the channel that was affected
+ * - we define the level as simply being the offset for the start of the channel
+ */
+ matchLevel = (acf->get_offset) ? acf->get_offset(ac, ale_setting) : 0;
+ prevLevel = matchLevel;
+ }
+
+ /* flush up?
+ *
+ * For Visibility:
+ * - only flush up if the current state is now enabled (positive 'on' state is default)
+ * (otherwise, it's too much work to force the parents to be inactive too)
+ *
+ * For everything else:
+ * - only flush up if the current state is now disabled (negative 'off' state is default)
+ * (otherwise, it's too much work to force the parents to be active too)
+ */
+ if (((setting == ACHANNEL_SETTING_VISIBLE) && (mode != ACHANNEL_SETFLAG_CLEAR)) ||
+ ((setting != ACHANNEL_SETTING_VISIBLE) && (mode == ACHANNEL_SETFLAG_CLEAR))) {
+ /* go backwards in the list, until the highest-ranking element (by indention has been covered) */
+ for (ale = match->prev; ale; ale = ale->prev) {
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ int level;
+
+ /* if no channel info was found, skip, since this type might not have any useful info */
+ if (acf == NULL)
+ continue;
+
+ /* get the level of the current channel traversed
+ * - we define the level as simply being the offset for the start of the channel
+ */
+ level = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
+
+ /* if the level is 'less than' (i.e. more important) the level we're matching
+ * but also 'less than' the level just tried (i.e. only the 1st group above grouped F-Curves,
+ * when toggling visibility of F-Curves, gets flushed, which should happen if we don't let prevLevel
+ * get updated below once the first 1st group is found)...
+ */
+ if (level < prevLevel) {
+ /* flush the new status... */
+ ANIM_channel_setting_set(ac, ale, setting, mode);
+
+ /* store this level as the 'old' level now */
+ prevLevel = level;
+ }
+ /* if the level is 'greater than' (i.e. less important) than the previous level... */
+ else if (level > prevLevel) {
+ /* if previous level was a base-level (i.e. 0 offset / root of one hierarchy),
+ * stop here
+ */
+ if (prevLevel == 0)
+ break;
+ /* otherwise, this level weaves into another sibling hierarchy to the previous one just
+ * finished, so skip until we get to the parent of this level
+ */
+ else
+ continue;
+ }
+ }
+ }
+
+ /* flush down (always) */
+ {
+ /* go forwards in the list, until the lowest-ranking element (by indention has been covered) */
+ for (ale = match->next; ale; ale = ale->next) {
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ int level;
+
+ /* if no channel info was found, skip, since this type might not have any useful info */
+ if (acf == NULL)
+ continue;
+
+ /* get the level of the current channel traversed
+ * - we define the level as simply being the offset for the start of the channel
+ */
+ level = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
+
+ /* if the level is 'greater than' (i.e. less important) the channel that was changed,
+ * flush the new status...
+ */
+ if (level > matchLevel)
+ ANIM_channel_setting_set(ac, ale, setting, mode);
+ /* however, if the level is 'less than or equal to' the channel that was changed,
+ * (i.e. the current channel is as important if not more important than the changed channel)
+ * then we should stop, since we've found the last one of the children we should flush
+ */
+ else
+ break;
+
+ /* store this level as the 'old' level now */
+ // prevLevel = level; // XXX: prevLevel is unused
+ }
+ }
}
/* -------------------------- F-Curves ------------------------------------- */
@@ -594,59 +582,59 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn
/* Delete the given F-Curve from its AnimData block */
void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *fcu)
{
- /* - if no AnimData, we've got nowhere to remove the F-Curve from
- * (this doesn't guarantee that the F-Curve is in there, but at least we tried
- * - if no F-Curve, there is nothing to remove
- */
- if (ELEM(NULL, adt, fcu))
- return;
-
- /* remove from whatever list it came from
- * - Action Group
- * - Action
- * - Drivers
- * - TODO... some others?
- */
- if ((ac) && (ac->datatype == ANIMCONT_DRIVERS)) {
- /* driver F-Curve */
- BLI_remlink(&adt->drivers, fcu);
- }
- else if (adt->action) {
- bAction *act = adt->action;
-
- /* remove from group or action, whichever one "owns" the F-Curve */
- if (fcu->grp) {
- bActionGroup *agrp = fcu->grp;
-
- /* remove F-Curve from group+action */
- action_groups_remove_channel(act, fcu);
-
- /* if group has no more channels, remove it too,
- * otherwise can have many dangling groups [#33541]
- */
- if (BLI_listbase_is_empty(&agrp->channels)) {
- BLI_freelinkN(&act->groups, agrp);
- }
- }
- else {
- BLI_remlink(&act->curves, fcu);
- }
-
- /* if action has no more F-Curves as a result of this, unlink it from
- * AnimData if it did not come from a NLA Strip being tweaked.
- *
- * This is done so that we don't have dangling Object+Action entries in
- * channel list that are empty, and linger around long after the data they
- * are for has disappeared (and probably won't come back).
- */
- if (BLI_listbase_is_empty(&act->curves) && (adt->flag & ADT_NLA_EDIT_ON) == 0) {
- id_us_min(&act->id);
- adt->action = NULL;
- }
- }
-
- /* free the F-Curve itself */
- free_fcurve(fcu);
+ /* - if no AnimData, we've got nowhere to remove the F-Curve from
+ * (this doesn't guarantee that the F-Curve is in there, but at least we tried
+ * - if no F-Curve, there is nothing to remove
+ */
+ if (ELEM(NULL, adt, fcu))
+ return;
+
+ /* remove from whatever list it came from
+ * - Action Group
+ * - Action
+ * - Drivers
+ * - TODO... some others?
+ */
+ if ((ac) && (ac->datatype == ANIMCONT_DRIVERS)) {
+ /* driver F-Curve */
+ BLI_remlink(&adt->drivers, fcu);
+ }
+ else if (adt->action) {
+ bAction *act = adt->action;
+
+ /* remove from group or action, whichever one "owns" the F-Curve */
+ if (fcu->grp) {
+ bActionGroup *agrp = fcu->grp;
+
+ /* remove F-Curve from group+action */
+ action_groups_remove_channel(act, fcu);
+
+ /* if group has no more channels, remove it too,
+ * otherwise can have many dangling groups [#33541]
+ */
+ if (BLI_listbase_is_empty(&agrp->channels)) {
+ BLI_freelinkN(&act->groups, agrp);
+ }
+ }
+ else {
+ BLI_remlink(&act->curves, fcu);
+ }
+
+ /* if action has no more F-Curves as a result of this, unlink it from
+ * AnimData if it did not come from a NLA Strip being tweaked.
+ *
+ * This is done so that we don't have dangling Object+Action entries in
+ * channel list that are empty, and linger around long after the data they
+ * are for has disappeared (and probably won't come back).
+ */
+ if (BLI_listbase_is_empty(&act->curves) && (adt->flag & ADT_NLA_EDIT_ON) == 0) {
+ id_us_min(&act->id);
+ adt->action = NULL;
+ }
+ }
+
+ /* free the F-Curve itself */
+ free_fcurve(fcu);
}
/* ************************************************************************** */
@@ -657,40 +645,40 @@ void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *f
/* 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 *sa = CTX_wm_area(C);
- /* channels region test */
- /* TODO: could enhance with actually testing if channels region? */
- if (ELEM(NULL, sa, CTX_wm_region(C)))
- return 0;
- /* animation editor test */
- if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA) == 0)
- return 0;
+ /* channels region test */
+ /* TODO: could enhance with actually testing if channels region? */
+ if (ELEM(NULL, sa, CTX_wm_region(C)))
+ return 0;
+ /* animation editor test */
+ if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA) == 0)
+ return 0;
- return 1;
+ return 1;
}
/* 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);
- Scene *scene = CTX_data_scene(C);
+ ScrArea *sa = 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)))
- return 0;
- /* animation editor test */
- if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA) == 0)
- return 0;
+ /* channels region test */
+ /* TODO: could enhance with actually testing if channels region? */
+ if (ELEM(NULL, sa, CTX_wm_region(C)))
+ return 0;
+ /* animation editor test */
+ if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA) == 0)
+ return 0;
- /* NLA TweakMode test */
- if (sa->spacetype == SPACE_NLA) {
- if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON))
- return 0;
- }
+ /* NLA TweakMode test */
+ if (sa->spacetype == SPACE_NLA) {
+ if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON))
+ return 0;
+ }
- return 1;
+ return 1;
}
/* ****************** Rearrange Channels Operator ******************* */
@@ -698,146 +686,144 @@ static bool animedit_poll_channels_nla_tweakmode_off(bContext *C)
/* constants for channel rearranging */
/* WARNING: don't change existing ones without modifying rearrange func accordingly */
typedef enum eRearrangeAnimChan_Mode {
- REARRANGE_ANIMCHAN_TOP = -2,
- REARRANGE_ANIMCHAN_UP = -1,
- REARRANGE_ANIMCHAN_DOWN = 1,
- REARRANGE_ANIMCHAN_BOTTOM = 2,
+ REARRANGE_ANIMCHAN_TOP = -2,
+ REARRANGE_ANIMCHAN_UP = -1,
+ REARRANGE_ANIMCHAN_DOWN = 1,
+ REARRANGE_ANIMCHAN_BOTTOM = 2,
} eRearrangeAnimChan_Mode;
/* defines for rearranging channels */
static const EnumPropertyItem prop_animchannel_rearrange_types[] = {
- {REARRANGE_ANIMCHAN_TOP, "TOP", 0, "To Top", ""},
- {REARRANGE_ANIMCHAN_UP, "UP", 0, "Up", ""},
- {REARRANGE_ANIMCHAN_DOWN, "DOWN", 0, "Down", ""},
- {REARRANGE_ANIMCHAN_BOTTOM, "BOTTOM", 0, "To Bottom", ""},
- {0, NULL, 0, NULL, NULL},
+ {REARRANGE_ANIMCHAN_TOP, "TOP", 0, "To Top", ""},
+ {REARRANGE_ANIMCHAN_UP, "UP", 0, "Up", ""},
+ {REARRANGE_ANIMCHAN_DOWN, "DOWN", 0, "Down", ""},
+ {REARRANGE_ANIMCHAN_BOTTOM, "BOTTOM", 0, "To Bottom", ""},
+ {0, NULL, 0, NULL, NULL},
};
/* Reordering "Islands" Defines ----------------------------------- */
/* Island definition - just a listbase container */
typedef struct tReorderChannelIsland {
- struct tReorderChannelIsland *next, *prev;
+ struct tReorderChannelIsland *next, *prev;
- ListBase channels; /* channels within this region with the same state */
- int flag; /* eReorderIslandFlag */
+ ListBase channels; /* channels within this region with the same state */
+ int flag; /* eReorderIslandFlag */
} tReorderChannelIsland;
/* flags for channel reordering islands */
typedef enum eReorderIslandFlag {
- REORDER_ISLAND_SELECTED = (1 << 0), /* island is selected */
- REORDER_ISLAND_UNTOUCHABLE = (1 << 1), /* island should be ignored */
- REORDER_ISLAND_MOVED = (1 << 2), /* island has already been moved */
- REORDER_ISLAND_HIDDEN = (1 << 3), /* island is not visible */
+ REORDER_ISLAND_SELECTED = (1 << 0), /* island is selected */
+ REORDER_ISLAND_UNTOUCHABLE = (1 << 1), /* island should be ignored */
+ REORDER_ISLAND_MOVED = (1 << 2), /* island has already been moved */
+ REORDER_ISLAND_HIDDEN = (1 << 3), /* island is not visible */
} eReorderIslandFlag;
-
/* Rearrange Methods --------------------------------------------- */
static bool rearrange_island_ok(tReorderChannelIsland *island)
{
- /* island must not be untouchable */
- if (island->flag & REORDER_ISLAND_UNTOUCHABLE)
- return 0;
+ /* island must not be untouchable */
+ if (island->flag & REORDER_ISLAND_UNTOUCHABLE)
+ return 0;
- /* island should be selected to be moved */
- return (island->flag & REORDER_ISLAND_SELECTED) && !(island->flag & REORDER_ISLAND_MOVED);
+ /* island should be selected to be moved */
+ return (island->flag & REORDER_ISLAND_SELECTED) && !(island->flag & REORDER_ISLAND_MOVED);
}
/* ............................. */
static bool rearrange_island_top(ListBase *list, tReorderChannelIsland *island)
{
- if (rearrange_island_ok(island)) {
- /* remove from current position */
- BLI_remlink(list, island);
+ if (rearrange_island_ok(island)) {
+ /* remove from current position */
+ BLI_remlink(list, island);
- /* make it first element */
- BLI_insertlinkbefore(list, list->first, island);
+ /* make it first element */
+ BLI_insertlinkbefore(list, list->first, island);
- return 1;
- }
+ return 1;
+ }
- return 0;
+ return 0;
}
static bool rearrange_island_up(ListBase *list, tReorderChannelIsland *island)
{
- if (rearrange_island_ok(island)) {
- /* moving up = moving before the previous island, otherwise we're in the same place */
- tReorderChannelIsland *prev = island->prev;
+ if (rearrange_island_ok(island)) {
+ /* moving up = moving before the previous island, otherwise we're in the same place */
+ tReorderChannelIsland *prev = island->prev;
- /* Skip hidden islands! */
- while (prev && prev->flag & REORDER_ISLAND_HIDDEN) {
- prev = prev->prev;
- }
+ /* Skip hidden islands! */
+ while (prev && prev->flag & REORDER_ISLAND_HIDDEN) {
+ prev = prev->prev;
+ }
- if (prev) {
- /* remove from current position */
- BLI_remlink(list, island);
+ if (prev) {
+ /* remove from current position */
+ BLI_remlink(list, island);
- /* push it up */
- BLI_insertlinkbefore(list, prev, island);
+ /* push it up */
+ BLI_insertlinkbefore(list, prev, island);
- return 1;
- }
- }
+ return 1;
+ }
+ }
- return 0;
+ return 0;
}
static bool rearrange_island_down(ListBase *list, tReorderChannelIsland *island)
{
- if (rearrange_island_ok(island)) {
- /* moving down = moving after the next island, otherwise we're in the same place */
- tReorderChannelIsland *next = island->next;
+ if (rearrange_island_ok(island)) {
+ /* moving down = moving after the next island, otherwise we're in the same place */
+ tReorderChannelIsland *next = island->next;
- /* Skip hidden islands! */
- while (next && next->flag & REORDER_ISLAND_HIDDEN) {
- next = next->next;
- }
+ /* Skip hidden islands! */
+ while (next && next->flag & REORDER_ISLAND_HIDDEN) {
+ next = next->next;
+ }
- if (next) {
- /* can only move past if next is not untouchable (i.e. nothing can go after it) */
- if ((next->flag & REORDER_ISLAND_UNTOUCHABLE) == 0) {
- /* remove from current position */
- BLI_remlink(list, island);
+ if (next) {
+ /* can only move past if next is not untouchable (i.e. nothing can go after it) */
+ if ((next->flag & REORDER_ISLAND_UNTOUCHABLE) == 0) {
+ /* remove from current position */
+ BLI_remlink(list, island);
- /* push it down */
- BLI_insertlinkafter(list, next, island);
+ /* push it down */
+ BLI_insertlinkafter(list, next, island);
- return true;
- }
- }
- /* else: no next channel, so we're at the bottom already, so can't move */
- }
+ return true;
+ }
+ }
+ /* else: no next channel, so we're at the bottom already, so can't move */
+ }
- return false;
+ return false;
}
static bool rearrange_island_bottom(ListBase *list, tReorderChannelIsland *island)
{
- if (rearrange_island_ok(island)) {
- tReorderChannelIsland *last = list->last;
-
- /* remove island from current position */
- BLI_remlink(list, island);
+ if (rearrange_island_ok(island)) {
+ tReorderChannelIsland *last = list->last;
- /* add before or after the last channel? */
- if ((last->flag & REORDER_ISLAND_UNTOUCHABLE) == 0) {
- /* can add after it */
- BLI_addtail(list, island);
- }
- else {
- /* can at most go just before it, since last cannot be moved */
- BLI_insertlinkbefore(list, last, island);
+ /* remove island from current position */
+ BLI_remlink(list, island);
- }
+ /* add before or after the last channel? */
+ if ((last->flag & REORDER_ISLAND_UNTOUCHABLE) == 0) {
+ /* can add after it */
+ BLI_addtail(list, island);
+ }
+ else {
+ /* can at most go just before it, since last cannot be moved */
+ BLI_insertlinkbefore(list, last, island);
+ }
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
/* ............................. */
@@ -854,184 +840,187 @@ typedef bool (*AnimChanRearrangeFp)(ListBase *list, tReorderChannelIsland *islan
/* get rearranging function, given 'rearrange' mode */
static AnimChanRearrangeFp rearrange_get_mode_func(eRearrangeAnimChan_Mode mode)
{
- switch (mode) {
- case REARRANGE_ANIMCHAN_TOP:
- return rearrange_island_top;
- case REARRANGE_ANIMCHAN_UP:
- return rearrange_island_up;
- case REARRANGE_ANIMCHAN_DOWN:
- return rearrange_island_down;
- case REARRANGE_ANIMCHAN_BOTTOM:
- return rearrange_island_bottom;
- default:
- return NULL;
- }
+ switch (mode) {
+ case REARRANGE_ANIMCHAN_TOP:
+ return rearrange_island_top;
+ case REARRANGE_ANIMCHAN_UP:
+ return rearrange_island_up;
+ case REARRANGE_ANIMCHAN_DOWN:
+ return rearrange_island_down;
+ case REARRANGE_ANIMCHAN_BOTTOM:
+ return rearrange_island_bottom;
+ default:
+ return NULL;
+ }
}
/* Rearrange Islands Generics ------------------------------------- */
/* add channel into list of islands */
-static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *srcList,
- Link *channel, eAnim_ChannelType type,
+static void rearrange_animchannel_add_to_islands(ListBase *islands,
+ ListBase *srcList,
+ Link *channel,
+ eAnim_ChannelType type,
const bool is_hidden)
{
- /* always try to add to last island if possible */
- tReorderChannelIsland *island = islands->last;
- bool is_sel = false, is_untouchable = false;
-
- /* get flags - selected and untouchable from the channel */
- switch (type) {
- case ANIMTYPE_GROUP:
- {
- bActionGroup *agrp = (bActionGroup *)channel;
-
- is_sel = SEL_AGRP(agrp);
- is_untouchable = (agrp->flag & AGRP_TEMP) != 0;
- break;
- }
- case ANIMTYPE_FCURVE:
- case ANIMTYPE_NLACURVE:
- {
- FCurve *fcu = (FCurve *)channel;
-
- is_sel = SEL_FCU(fcu);
- break;
- }
- case ANIMTYPE_NLATRACK:
- {
- NlaTrack *nlt = (NlaTrack *)channel;
-
- is_sel = SEL_NLT(nlt);
- break;
- }
- case ANIMTYPE_GPLAYER:
- {
- bGPDlayer *gpl = (bGPDlayer *)channel;
-
- is_sel = SEL_GPL(gpl);
- break;
- }
- default:
- printf("rearrange_animchannel_add_to_islands(): don't know how to handle channels of type %u\n", type);
- return;
- }
-
- /* do we need to add to a new island? */
- if (/* 1) no islands yet */
- (island == NULL) ||
- /* 2) unselected islands have single channels only - to allow up/down movement */
- ((island->flag & REORDER_ISLAND_SELECTED) == 0) ||
- /* 3) if channel is unselected, stop existing island (it was either wrong sel status, or full already) */
- (is_sel == 0) ||
- /* 4) hidden status changes */
- ((island->flag & REORDER_ISLAND_HIDDEN) != is_hidden)
- )
- {
- /* create a new island now */
- island = MEM_callocN(sizeof(tReorderChannelIsland), "tReorderChannelIsland");
- BLI_addtail(islands, island);
-
- if (is_sel)
- island->flag |= REORDER_ISLAND_SELECTED;
- if (is_untouchable)
- island->flag |= REORDER_ISLAND_UNTOUCHABLE;
- if (is_hidden)
- island->flag |= REORDER_ISLAND_HIDDEN;
- }
-
- /* add channel to island - need to remove it from its existing list first though */
- BLI_remlink(srcList, channel);
- BLI_addtail(&island->channels, channel);
+ /* always try to add to last island if possible */
+ tReorderChannelIsland *island = islands->last;
+ bool is_sel = false, is_untouchable = false;
+
+ /* get flags - selected and untouchable from the channel */
+ switch (type) {
+ case ANIMTYPE_GROUP: {
+ bActionGroup *agrp = (bActionGroup *)channel;
+
+ is_sel = SEL_AGRP(agrp);
+ is_untouchable = (agrp->flag & AGRP_TEMP) != 0;
+ break;
+ }
+ case ANIMTYPE_FCURVE:
+ case ANIMTYPE_NLACURVE: {
+ FCurve *fcu = (FCurve *)channel;
+
+ is_sel = SEL_FCU(fcu);
+ break;
+ }
+ case ANIMTYPE_NLATRACK: {
+ NlaTrack *nlt = (NlaTrack *)channel;
+
+ is_sel = SEL_NLT(nlt);
+ break;
+ }
+ case ANIMTYPE_GPLAYER: {
+ bGPDlayer *gpl = (bGPDlayer *)channel;
+
+ is_sel = SEL_GPL(gpl);
+ break;
+ }
+ default:
+ printf(
+ "rearrange_animchannel_add_to_islands(): don't know how to handle channels of type %u\n",
+ type);
+ return;
+ }
+
+ /* do we need to add to a new island? */
+ if (/* 1) no islands yet */
+ (island == NULL) ||
+ /* 2) unselected islands have single channels only - to allow up/down movement */
+ ((island->flag & REORDER_ISLAND_SELECTED) == 0) ||
+ /* 3) if channel is unselected, stop existing island (it was either wrong sel status, or full already) */
+ (is_sel == 0) ||
+ /* 4) hidden status changes */
+ ((island->flag & REORDER_ISLAND_HIDDEN) != is_hidden)) {
+ /* create a new island now */
+ island = MEM_callocN(sizeof(tReorderChannelIsland), "tReorderChannelIsland");
+ BLI_addtail(islands, island);
+
+ if (is_sel)
+ island->flag |= REORDER_ISLAND_SELECTED;
+ if (is_untouchable)
+ island->flag |= REORDER_ISLAND_UNTOUCHABLE;
+ if (is_hidden)
+ island->flag |= REORDER_ISLAND_HIDDEN;
+ }
+
+ /* add channel to island - need to remove it from its existing list first though */
+ BLI_remlink(srcList, channel);
+ BLI_addtail(&island->channels, channel);
}
/* flatten islands out into a single list again */
static void rearrange_animchannel_flatten_islands(ListBase *islands, ListBase *srcList)
{
- tReorderChannelIsland *island, *isn = NULL;
+ tReorderChannelIsland *island, *isn = NULL;
- /* make sure srcList is empty now */
- BLI_assert(BLI_listbase_is_empty(srcList));
+ /* make sure srcList is empty now */
+ BLI_assert(BLI_listbase_is_empty(srcList));
- /* go through merging islands */
- for (island = islands->first; island; island = isn) {
- isn = island->next;
+ /* go through merging islands */
+ for (island = islands->first; island; island = isn) {
+ isn = island->next;
- /* merge island channels back to main list, then delete the island */
- BLI_movelisttolist(srcList, &island->channels);
- BLI_freelinkN(islands, island);
- }
+ /* merge island channels back to main list, then delete the island */
+ BLI_movelisttolist(srcList, &island->channels);
+ BLI_freelinkN(islands, island);
+ }
}
/* ............................. */
/* get a list of all bAnimListElem's of a certain type which are currently visible */
-static void rearrange_animchannels_filter_visible(ListBase *anim_data_visible, bAnimContext *ac, eAnim_ChannelType type)
+static void rearrange_animchannels_filter_visible(ListBase *anim_data_visible,
+ bAnimContext *ac,
+ eAnim_ChannelType type)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale, *ale_next;
- int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale, *ale_next;
+ int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- /* get all visible channels */
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ /* get all visible channels */
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* now, only keep the ones that are of the types we are interested in */
- for (ale = anim_data.first; ale; ale = ale_next) {
- ale_next = ale->next;
+ /* now, only keep the ones that are of the types we are interested in */
+ for (ale = anim_data.first; ale; ale = ale_next) {
+ ale_next = ale->next;
- if (ale->type != type) {
- BLI_freelinkN(&anim_data, ale);
- }
- }
+ if (ale->type != type) {
+ BLI_freelinkN(&anim_data, ale);
+ }
+ }
- /* return cleaned up list */
- *anim_data_visible = anim_data;
+ /* return cleaned up list */
+ *anim_data_visible = anim_data;
}
/* performing rearranging of channels using islands */
-static bool rearrange_animchannel_islands(ListBase *list, AnimChanRearrangeFp rearrange_func,
- eRearrangeAnimChan_Mode mode, eAnim_ChannelType type,
+static bool rearrange_animchannel_islands(ListBase *list,
+ AnimChanRearrangeFp rearrange_func,
+ eRearrangeAnimChan_Mode mode,
+ eAnim_ChannelType type,
ListBase *anim_data_visible)
{
- ListBase islands = {NULL, NULL};
- Link *channel, *chanNext = NULL;
- bool done = false;
-
- /* don't waste effort on an empty list */
- if (BLI_listbase_is_empty(list))
- return 0;
-
- /* group channels into islands */
- for (channel = list->first; channel; channel = chanNext) {
- /* find out whether this channel is present in anim_data_visible or not! */
- const bool is_hidden = (BLI_findptr(anim_data_visible, channel, offsetof(bAnimListElem, data)) == NULL);
- chanNext = channel->next;
- rearrange_animchannel_add_to_islands(&islands, list, channel, type, is_hidden);
- }
-
- /* perform moving of selected islands now, but only if there is more than one of 'em so that something will happen
- * - scanning of the list is performed in the opposite direction to the direction we're moving things, so that we
- * shouldn't need to encounter items we've moved already
- */
- if (islands.first != islands.last) {
- tReorderChannelIsland *first = (mode > 0) ? islands.last : islands.first;
- tReorderChannelIsland *island, *isn = NULL;
-
- for (island = first; island; island = isn) {
- isn = (mode > 0) ? island->prev : island->next;
-
- /* perform rearranging */
- if (rearrange_func(&islands, island)) {
- island->flag |= REORDER_ISLAND_MOVED;
- done = true;
- }
- }
- }
-
- /* ungroup islands */
- rearrange_animchannel_flatten_islands(&islands, list);
-
- /* did we do anything? */
- return done;
+ ListBase islands = {NULL, NULL};
+ Link *channel, *chanNext = NULL;
+ bool done = false;
+
+ /* don't waste effort on an empty list */
+ if (BLI_listbase_is_empty(list))
+ return 0;
+
+ /* group channels into islands */
+ for (channel = list->first; channel; channel = chanNext) {
+ /* find out whether this channel is present in anim_data_visible or not! */
+ const bool is_hidden =
+ (BLI_findptr(anim_data_visible, channel, offsetof(bAnimListElem, data)) == NULL);
+ chanNext = channel->next;
+ rearrange_animchannel_add_to_islands(&islands, list, channel, type, is_hidden);
+ }
+
+ /* perform moving of selected islands now, but only if there is more than one of 'em so that something will happen
+ * - scanning of the list is performed in the opposite direction to the direction we're moving things, so that we
+ * shouldn't need to encounter items we've moved already
+ */
+ if (islands.first != islands.last) {
+ tReorderChannelIsland *first = (mode > 0) ? islands.last : islands.first;
+ tReorderChannelIsland *island, *isn = NULL;
+
+ for (island = first; island; island = isn) {
+ isn = (mode > 0) ? island->prev : island->next;
+
+ /* perform rearranging */
+ if (rearrange_func(&islands, island)) {
+ island->flag |= REORDER_ISLAND_MOVED;
+ done = true;
+ }
+ }
+ }
+
+ /* ungroup islands */
+ rearrange_animchannel_flatten_islands(&islands, list);
+
+ /* did we do anything? */
+ return done;
}
/* NLA Specific Stuff ----------------------------------------------------- */
@@ -1042,25 +1031,26 @@ static bool rearrange_animchannel_islands(ListBase *list, AnimChanRearrangeFp re
*/
static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, eRearrangeAnimChan_Mode mode)
{
- AnimChanRearrangeFp rearrange_func;
- ListBase anim_data_visible = {NULL, NULL};
+ AnimChanRearrangeFp rearrange_func;
+ ListBase anim_data_visible = {NULL, NULL};
- /* hack: invert mode so that functions will work in right order */
- mode *= -1;
+ /* hack: invert mode so that functions will work in right order */
+ mode *= -1;
- /* get rearranging function */
- rearrange_func = rearrange_get_mode_func(mode);
- if (rearrange_func == NULL)
- return;
+ /* get rearranging function */
+ rearrange_func = rearrange_get_mode_func(mode);
+ if (rearrange_func == NULL)
+ return;
- /* Filter visible data. */
- rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_NLATRACK);
+ /* Filter visible data. */
+ rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_NLATRACK);
- /* perform rearranging on tracks list */
- rearrange_animchannel_islands(&adt->nla_tracks, rearrange_func, mode, ANIMTYPE_NLATRACK, &anim_data_visible);
+ /* perform rearranging on tracks list */
+ rearrange_animchannel_islands(
+ &adt->nla_tracks, rearrange_func, mode, ANIMTYPE_NLATRACK, &anim_data_visible);
- /* free temp data */
- BLI_freelistN(&anim_data_visible);
+ /* free temp data */
+ BLI_freelistN(&anim_data_visible);
}
/* Drivers Specific Stuff ------------------------------------------------- */
@@ -1068,27 +1058,30 @@ static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, eRearrangeAn
/* Change the order drivers within AnimData block
* mode: REARRANGE_ANIMCHAN_*
*/
-static void rearrange_driver_channels(bAnimContext *ac, AnimData *adt, eRearrangeAnimChan_Mode mode)
+static void rearrange_driver_channels(bAnimContext *ac,
+ AnimData *adt,
+ eRearrangeAnimChan_Mode mode)
{
- /* get rearranging function */
- AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
- ListBase anim_data_visible = {NULL, NULL};
+ /* get rearranging function */
+ AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
+ ListBase anim_data_visible = {NULL, NULL};
- if (rearrange_func == NULL)
- return;
+ if (rearrange_func == NULL)
+ return;
- /* only consider drivers if they're accessible */
- if (EXPANDED_DRVD(adt) == 0)
- return;
+ /* only consider drivers if they're accessible */
+ if (EXPANDED_DRVD(adt) == 0)
+ return;
- /* Filter visible data. */
- rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_FCURVE);
+ /* Filter visible data. */
+ rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_FCURVE);
- /* perform rearranging on drivers list (drivers are really just F-Curves) */
- rearrange_animchannel_islands(&adt->drivers, rearrange_func, mode, ANIMTYPE_FCURVE, &anim_data_visible);
+ /* perform rearranging on drivers list (drivers are really just F-Curves) */
+ rearrange_animchannel_islands(
+ &adt->drivers, rearrange_func, mode, ANIMTYPE_FCURVE, &anim_data_visible);
- /* free temp data */
- BLI_freelistN(&anim_data_visible);
+ /* free temp data */
+ BLI_freelistN(&anim_data_visible);
}
/* Action Specific Stuff ------------------------------------------------- */
@@ -1096,88 +1089,88 @@ static void rearrange_driver_channels(bAnimContext *ac, AnimData *adt, eRearrang
/* make sure all action-channels belong to a group (and clear action's list) */
static void split_groups_action_temp(bAction *act, bActionGroup *tgrp)
{
- bActionGroup *agrp;
- FCurve *fcu;
-
- if (act == NULL)
- return;
-
- /* Separate F-Curves into lists per group */
- for (agrp = act->groups.first; agrp; agrp = agrp->next) {
- if (agrp->channels.first) {
- fcu = agrp->channels.last;
- act->curves.first = fcu->next;
-
- fcu = agrp->channels.first;
- fcu->prev = NULL;
-
- fcu = agrp->channels.last;
- fcu->next = NULL;
- }
- }
-
- /* Initialize memory for temp-group */
- memset(tgrp, 0, sizeof(bActionGroup));
- tgrp->flag |= (AGRP_EXPANDED | AGRP_TEMP);
- BLI_strncpy(tgrp->name, "#TempGroup", sizeof(tgrp->name));
-
- /* Move any action-channels not already moved, to the temp group */
- if (act->curves.first) {
- /* start of list */
- fcu = act->curves.first;
- fcu->prev = NULL;
- tgrp->channels.first = fcu;
- act->curves.first = NULL;
-
- /* end of list */
- fcu = act->curves.last;
- fcu->next = NULL;
- tgrp->channels.last = fcu;
- act->curves.last = NULL;
-
- /* ensure that all of these get their group set to this temp group
- * (so that visibility filtering works)
- */
- for (fcu = tgrp->channels.first; fcu; fcu = fcu->next) {
- fcu->grp = tgrp;
- }
- }
-
- /* Add temp-group to list */
- BLI_addtail(&act->groups, tgrp);
+ bActionGroup *agrp;
+ FCurve *fcu;
+
+ if (act == NULL)
+ return;
+
+ /* Separate F-Curves into lists per group */
+ for (agrp = act->groups.first; agrp; agrp = agrp->next) {
+ if (agrp->channels.first) {
+ fcu = agrp->channels.last;
+ act->curves.first = fcu->next;
+
+ fcu = agrp->channels.first;
+ fcu->prev = NULL;
+
+ fcu = agrp->channels.last;
+ fcu->next = NULL;
+ }
+ }
+
+ /* Initialize memory for temp-group */
+ memset(tgrp, 0, sizeof(bActionGroup));
+ tgrp->flag |= (AGRP_EXPANDED | AGRP_TEMP);
+ BLI_strncpy(tgrp->name, "#TempGroup", sizeof(tgrp->name));
+
+ /* Move any action-channels not already moved, to the temp group */
+ if (act->curves.first) {
+ /* start of list */
+ fcu = act->curves.first;
+ fcu->prev = NULL;
+ tgrp->channels.first = fcu;
+ act->curves.first = NULL;
+
+ /* end of list */
+ fcu = act->curves.last;
+ fcu->next = NULL;
+ tgrp->channels.last = fcu;
+ act->curves.last = NULL;
+
+ /* ensure that all of these get their group set to this temp group
+ * (so that visibility filtering works)
+ */
+ for (fcu = tgrp->channels.first; fcu; fcu = fcu->next) {
+ fcu->grp = tgrp;
+ }
+ }
+
+ /* Add temp-group to list */
+ BLI_addtail(&act->groups, tgrp);
}
/* link lists of channels that groups have */
static void join_groups_action_temp(bAction *act)
{
- bActionGroup *agrp;
+ bActionGroup *agrp;
- for (agrp = act->groups.first; agrp; agrp = agrp->next) {
- ListBase tempGroup;
+ for (agrp = act->groups.first; agrp; agrp = agrp->next) {
+ ListBase tempGroup;
- /* add list of channels to action's channels */
- tempGroup = agrp->channels;
- BLI_movelisttolist(&act->curves, &agrp->channels);
- agrp->channels = tempGroup;
+ /* add list of channels to action's channels */
+ tempGroup = agrp->channels;
+ BLI_movelisttolist(&act->curves, &agrp->channels);
+ agrp->channels = tempGroup;
- /* clear moved flag */
- agrp->flag &= ~AGRP_MOVED;
+ /* clear moved flag */
+ agrp->flag &= ~AGRP_MOVED;
- /* if group was temporary one:
- * - unassign all FCurves which were temporarily added to it
- * - remove from list (but don't free as it's on the stack!)
- */
- if (agrp->flag & AGRP_TEMP) {
- FCurve *fcu;
+ /* if group was temporary one:
+ * - unassign all FCurves which were temporarily added to it
+ * - remove from list (but don't free as it's on the stack!)
+ */
+ if (agrp->flag & AGRP_TEMP) {
+ FCurve *fcu;
- for (fcu = agrp->channels.first; fcu; fcu = fcu->next) {
- fcu->grp = NULL;
- }
+ for (fcu = agrp->channels.first; fcu; fcu = fcu->next) {
+ fcu->grp = NULL;
+ }
- BLI_remlink(&act->groups, agrp);
- break;
- }
- }
+ BLI_remlink(&act->groups, agrp);
+ break;
+ }
+ }
}
/* Change the order of anim-channels within action
@@ -1185,635 +1178,644 @@ static void join_groups_action_temp(bAction *act)
*/
static void rearrange_action_channels(bAnimContext *ac, bAction *act, eRearrangeAnimChan_Mode mode)
{
- bActionGroup tgrp;
- ListBase anim_data_visible = {NULL, NULL};
- bool do_channels;
+ bActionGroup tgrp;
+ ListBase anim_data_visible = {NULL, NULL};
+ bool do_channels;
- /* get rearranging function */
- AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
+ /* get rearranging function */
+ AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
- if (rearrange_func == NULL)
- return;
+ if (rearrange_func == NULL)
+ return;
- /* make sure we're only operating with groups (vs a mixture of groups+curves) */
- split_groups_action_temp(act, &tgrp);
+ /* make sure we're only operating with groups (vs a mixture of groups+curves) */
+ split_groups_action_temp(act, &tgrp);
- /* Filter visible data. */
- rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_GROUP);
+ /* Filter visible data. */
+ rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_GROUP);
- /* rearrange groups first
- * - the group's channels will only get considered if nothing happened when rearranging the groups
- * i.e. the rearrange function returned 0
- */
- do_channels = (rearrange_animchannel_islands(&act->groups, rearrange_func, mode, ANIMTYPE_GROUP,
- &anim_data_visible) == 0);
+ /* rearrange groups first
+ * - the group's channels will only get considered if nothing happened when rearranging the groups
+ * i.e. the rearrange function returned 0
+ */
+ do_channels = (rearrange_animchannel_islands(
+ &act->groups, rearrange_func, mode, ANIMTYPE_GROUP, &anim_data_visible) == 0);
- /* free temp data */
- BLI_freelistN(&anim_data_visible);
+ /* free temp data */
+ BLI_freelistN(&anim_data_visible);
- if (do_channels) {
- bActionGroup *agrp;
+ if (do_channels) {
+ bActionGroup *agrp;
- /* Filter visible data. */
- rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_FCURVE);
+ /* Filter visible data. */
+ rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_FCURVE);
- for (agrp = act->groups.first; agrp; agrp = agrp->next) {
- /* only consider F-Curves if they're visible (group expanded) */
- if (EXPANDED_AGRP(ac, agrp)) {
- rearrange_animchannel_islands(&agrp->channels, rearrange_func, mode, ANIMTYPE_FCURVE,
- &anim_data_visible);
- }
- }
+ for (agrp = act->groups.first; agrp; agrp = agrp->next) {
+ /* only consider F-Curves if they're visible (group expanded) */
+ if (EXPANDED_AGRP(ac, agrp)) {
+ rearrange_animchannel_islands(
+ &agrp->channels, rearrange_func, mode, ANIMTYPE_FCURVE, &anim_data_visible);
+ }
+ }
- /* free temp data */
- BLI_freelistN(&anim_data_visible);
- }
+ /* free temp data */
+ BLI_freelistN(&anim_data_visible);
+ }
- /* assemble lists into one list (and clear moved tags) */
- join_groups_action_temp(act);
+ /* assemble lists into one list (and clear moved tags) */
+ join_groups_action_temp(act);
}
/* ------------------- */
-static void rearrange_nla_control_channels(bAnimContext *ac, AnimData *adt, eRearrangeAnimChan_Mode mode)
+static void rearrange_nla_control_channels(bAnimContext *ac,
+ AnimData *adt,
+ eRearrangeAnimChan_Mode mode)
{
- ListBase anim_data_visible = {NULL, NULL};
+ ListBase anim_data_visible = {NULL, NULL};
- NlaTrack *nlt;
- NlaStrip *strip;
+ NlaTrack *nlt;
+ NlaStrip *strip;
- /* get rearranging function */
- AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
+ /* get rearranging function */
+ AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
- if (rearrange_func == NULL)
- return;
+ if (rearrange_func == NULL)
+ return;
- /* skip if these curves aren't being shown */
- if (adt->flag & ADT_NLA_SKEYS_COLLAPSED)
- return;
+ /* skip if these curves aren't being shown */
+ if (adt->flag & ADT_NLA_SKEYS_COLLAPSED)
+ return;
- /* Filter visible data. */
- rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_NLACURVE);
+ /* Filter visible data. */
+ rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_NLACURVE);
- /* we cannot rearrange between strips, but within each strip, we can rearrange those curves */
- for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- rearrange_animchannel_islands(
- &strip->fcurves, rearrange_func, mode, ANIMTYPE_NLACURVE,
- &anim_data_visible);
- }
- }
+ /* we cannot rearrange between strips, but within each strip, we can rearrange those curves */
+ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ rearrange_animchannel_islands(
+ &strip->fcurves, rearrange_func, mode, ANIMTYPE_NLACURVE, &anim_data_visible);
+ }
+ }
- /* free temp data */
- BLI_freelistN(&anim_data_visible);
+ /* free temp data */
+ BLI_freelistN(&anim_data_visible);
}
/* ------------------- */
static void rearrange_gpencil_channels(bAnimContext *ac, eRearrangeAnimChan_Mode mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- /* get rearranging function */
- AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
+ /* get rearranging function */
+ AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
- if (rearrange_func == NULL)
- return;
+ if (rearrange_func == NULL)
+ return;
- /* get Grease Pencil datablocks */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ /* get Grease Pencil datablocks */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- for (ale = anim_data.first; ale; ale = ale->next) {
- ListBase anim_data_visible = {NULL, NULL};
- bGPdata *gpd = ale->data;
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ ListBase anim_data_visible = {NULL, NULL};
+ bGPdata *gpd = ale->data;
- /* only consider layers if this datablock is open */
- BLI_assert(ale->type == ANIMTYPE_GPDATABLOCK);
- if ((gpd->flag & GP_DATA_EXPAND) == 0)
- continue;
+ /* only consider layers if this datablock is open */
+ BLI_assert(ale->type == ANIMTYPE_GPDATABLOCK);
+ if ((gpd->flag & GP_DATA_EXPAND) == 0)
+ continue;
- /* Filter visible data. */
- rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_GPLAYER);
+ /* Filter visible data. */
+ rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_GPLAYER);
- /* rearrange datablock's layers */
- rearrange_animchannel_islands(&gpd->layers, rearrange_func, mode, ANIMTYPE_GPLAYER, &anim_data_visible);
+ /* rearrange datablock's layers */
+ rearrange_animchannel_islands(
+ &gpd->layers, rearrange_func, mode, ANIMTYPE_GPLAYER, &anim_data_visible);
- /* free visible layers data */
- BLI_freelistN(&anim_data_visible);
- }
+ /* free visible layers data */
+ BLI_freelistN(&anim_data_visible);
+ }
- /* free GPD channel data */
- ANIM_animdata_freelist(&anim_data);
+ /* free GPD channel data */
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- eRearrangeAnimChan_Mode mode;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get mode */
- mode = RNA_enum_get(op->ptr, "direction");
-
- /* method to move channels depends on the editor */
- if (ac.datatype == ANIMCONT_GPENCIL) {
- /* Grease Pencil channels */
- rearrange_gpencil_channels(&ac, mode);
- }
- else if (ac.datatype == ANIMCONT_MASK) {
- /* Grease Pencil channels */
- printf("Mask does not supported for moving yet\n");
- }
- else if (ac.datatype == ANIMCONT_ACTION) {
- /* Directly rearrange action's channels */
- rearrange_action_channels(&ac, ac.data, mode);
- }
- else {
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* get animdata blocks */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ale->data;
-
- switch (ac.datatype) {
- case ANIMCONT_NLA: /* NLA-tracks only */
- rearrange_nla_channels(&ac, adt, mode);
- DEG_id_tag_update(ale->id, ID_RECALC_ANIMATION);
- break;
-
- case ANIMCONT_DRIVERS: /* Drivers list only */
- rearrange_driver_channels(&ac, adt, mode);
- break;
-
- case ANIMCONT_ACTION: /* Single Action only... */
- case ANIMCONT_SHAPEKEY: // DOUBLE CHECK ME...
- {
- if (adt->action)
- rearrange_action_channels(&ac, adt->action, mode);
- else if (G.debug & G_DEBUG)
- printf("Animdata has no action\n");
- break;
- }
-
- default: /* DopeSheet/Graph Editor - Some Actions + NLA Control Curves */
- {
- /* NLA Control Curves */
- if (adt->nla_tracks.first)
- rearrange_nla_control_channels(&ac, adt, mode);
-
- /* Action */
- if (adt->action)
- rearrange_action_channels(&ac, adt->action, mode);
- else if (G.debug & G_DEBUG)
- printf("Animdata has no action\n");
- break;
- }
- }
- }
-
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
- }
-
- /* send notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ eRearrangeAnimChan_Mode mode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get mode */
+ mode = RNA_enum_get(op->ptr, "direction");
+
+ /* method to move channels depends on the editor */
+ if (ac.datatype == ANIMCONT_GPENCIL) {
+ /* Grease Pencil channels */
+ rearrange_gpencil_channels(&ac, mode);
+ }
+ else if (ac.datatype == ANIMCONT_MASK) {
+ /* Grease Pencil channels */
+ printf("Mask does not supported for moving yet\n");
+ }
+ else if (ac.datatype == ANIMCONT_ACTION) {
+ /* Directly rearrange action's channels */
+ rearrange_action_channels(&ac, ac.data, mode);
+ }
+ else {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get animdata blocks */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ale->data;
+
+ switch (ac.datatype) {
+ case ANIMCONT_NLA: /* NLA-tracks only */
+ rearrange_nla_channels(&ac, adt, mode);
+ DEG_id_tag_update(ale->id, ID_RECALC_ANIMATION);
+ break;
+
+ case ANIMCONT_DRIVERS: /* Drivers list only */
+ rearrange_driver_channels(&ac, adt, mode);
+ break;
+
+ case ANIMCONT_ACTION: /* Single Action only... */
+ case ANIMCONT_SHAPEKEY: // DOUBLE CHECK ME...
+ {
+ if (adt->action)
+ rearrange_action_channels(&ac, adt->action, mode);
+ else if (G.debug & G_DEBUG)
+ printf("Animdata has no action\n");
+ break;
+ }
+
+ default: /* DopeSheet/Graph Editor - Some Actions + NLA Control Curves */
+ {
+ /* NLA Control Curves */
+ if (adt->nla_tracks.first)
+ rearrange_nla_control_channels(&ac, adt, mode);
+
+ /* Action */
+ if (adt->action)
+ rearrange_action_channels(&ac, adt->action, mode);
+ else if (G.debug & G_DEBUG)
+ printf("Animdata has no action\n");
+ break;
+ }
+ }
+ }
+
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
+ }
+
+ /* send notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
}
static void ANIM_OT_channels_move(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move Channels";
- ot->idname = "ANIM_OT_channels_move";
- ot->description = "Rearrange selected animation channels";
+ /* identifiers */
+ ot->name = "Move Channels";
+ ot->idname = "ANIM_OT_channels_move";
+ ot->description = "Rearrange selected animation channels";
- /* api callbacks */
- ot->exec = animchannels_rearrange_exec;
- ot->poll = animedit_poll_channels_nla_tweakmode_off;
+ /* api callbacks */
+ ot->exec = animchannels_rearrange_exec;
+ ot->poll = animedit_poll_channels_nla_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- ot->prop = RNA_def_enum(ot->srna, "direction", prop_animchannel_rearrange_types, REARRANGE_ANIMCHAN_DOWN, "Direction", "");
+ /* props */
+ ot->prop = RNA_def_enum(ot->srna,
+ "direction",
+ prop_animchannel_rearrange_types,
+ REARRANGE_ANIMCHAN_DOWN,
+ "Direction",
+ "");
}
/* ******************** Group Channel Operator ************************ */
static bool animchannels_grouping_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- SpaceLink *sl;
+ ScrArea *sa = 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)))
- return 0;
+ /* channels region test */
+ /* TODO: could enhance with actually testing if channels region? */
+ if (ELEM(NULL, sa, CTX_wm_region(C)))
+ return 0;
- /* animation editor test - must be suitable modes only */
- sl = CTX_wm_space_data(C);
+ /* animation editor test - must be suitable modes only */
+ sl = CTX_wm_space_data(C);
- switch (sa->spacetype) {
- /* supported... */
- case SPACE_ACTION:
- {
- SpaceAction *saction = (SpaceAction *)sl;
+ switch (sa->spacetype) {
+ /* supported... */
+ case SPACE_ACTION: {
+ SpaceAction *saction = (SpaceAction *)sl;
- /* dopesheet and action only - all others are for other datatypes or have no groups */
- if (ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_DOPESHEET) == 0)
- return 0;
+ /* dopesheet and action only - all others are for other datatypes or have no groups */
+ if (ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_DOPESHEET) == 0)
+ return 0;
- break;
- }
- case SPACE_GRAPH:
- {
- SpaceGraph *sipo = (SpaceGraph *)sl;
+ break;
+ }
+ case SPACE_GRAPH: {
+ SpaceGraph *sipo = (SpaceGraph *)sl;
- /* drivers can't have groups... */
- if (sipo->mode != SIPO_MODE_ANIMATION)
- return 0;
+ /* drivers can't have groups... */
+ if (sipo->mode != SIPO_MODE_ANIMATION)
+ return 0;
- break;
- }
- /* unsupported... */
- default:
- return 0;
- }
+ break;
+ }
+ /* unsupported... */
+ default:
+ return 0;
+ }
- return 1;
+ return 1;
}
/* ----------------------------------------------------------- */
-static void animchannels_group_channels(bAnimContext *ac, bAnimListElem *adt_ref, const char name[])
+static void animchannels_group_channels(bAnimContext *ac,
+ bAnimListElem *adt_ref,
+ const char name[])
{
- AnimData *adt = adt_ref->adt;
- bAction *act = adt->action;
+ AnimData *adt = adt_ref->adt;
+ bAction *act = adt->action;
- if (act) {
- ListBase anim_data = {NULL, NULL};
- int filter;
+ if (act) {
+ ListBase anim_data = {NULL, NULL};
+ int filter;
- /* find selected F-Curves to re-group */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL);
- ANIM_animdata_filter(ac, &anim_data, filter, adt_ref, ANIMCONT_CHANNEL);
+ /* find selected F-Curves to re-group */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL);
+ ANIM_animdata_filter(ac, &anim_data, filter, adt_ref, ANIMCONT_CHANNEL);
- if (anim_data.first) {
- bActionGroup *agrp;
- bAnimListElem *ale;
+ if (anim_data.first) {
+ bActionGroup *agrp;
+ bAnimListElem *ale;
- /* create new group, which should now be part of the action */
- agrp = action_groups_add_new(act, name);
- BLI_assert(agrp != NULL);
+ /* create new group, which should now be part of the action */
+ agrp = action_groups_add_new(act, name);
+ BLI_assert(agrp != NULL);
- /* transfer selected F-Curves across to new group */
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->data;
- bActionGroup *grp = fcu->grp;
+ /* transfer selected F-Curves across to new group */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->data;
+ bActionGroup *grp = fcu->grp;
- /* remove F-Curve from group, then group too if it is now empty */
- action_groups_remove_channel(act, fcu);
+ /* remove F-Curve from group, then group too if it is now empty */
+ action_groups_remove_channel(act, fcu);
- if ((grp) && BLI_listbase_is_empty(&grp->channels)) {
- BLI_freelinkN(&act->groups, grp);
- }
+ if ((grp) && BLI_listbase_is_empty(&grp->channels)) {
+ BLI_freelinkN(&act->groups, grp);
+ }
- /* add F-Curve to group */
- action_groups_add_channel(act, agrp, fcu);
- }
- }
+ /* add F-Curve to group */
+ action_groups_add_channel(act, agrp, fcu);
+ }
+ }
- /* cleanup */
- ANIM_animdata_freelist(&anim_data);
- }
+ /* cleanup */
+ ANIM_animdata_freelist(&anim_data);
+ }
}
static int animchannels_group_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- char name[MAX_NAME];
+ bAnimContext ac;
+ char name[MAX_NAME];
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* get name for new group */
- RNA_string_get(op->ptr, "name", name);
+ /* get name for new group */
+ RNA_string_get(op->ptr, "name", name);
- /* XXX: name for group should never be empty... */
- if (name[0]) {
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ /* XXX: name for group should never be empty... */
+ if (name[0]) {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- /* handle each animdata block separately, so that the regrouping doesn't flow into blocks */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* handle each animdata block separately, so that the regrouping doesn't flow into blocks */
+ 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) {
- animchannels_group_channels(&ac, ale, name);
- }
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ animchannels_group_channels(&ac, ale, name);
+ }
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
- /* updatss */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
- }
+ /* updatss */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void ANIM_OT_channels_group(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Group Channels";
- ot->idname = "ANIM_OT_channels_group";
- ot->description = "Add selected F-Curves to a new group";
+ /* identifiers */
+ ot->name = "Group Channels";
+ ot->idname = "ANIM_OT_channels_group";
+ ot->description = "Add selected F-Curves to a new group";
- /* callbacks */
- ot->invoke = WM_operator_props_popup;
- ot->exec = animchannels_group_exec;
- ot->poll = animchannels_grouping_poll;
+ /* callbacks */
+ ot->invoke = WM_operator_props_popup;
+ ot->exec = animchannels_group_exec;
+ ot->poll = animchannels_grouping_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- ot->prop = RNA_def_string(ot->srna, "name", "New Group",
- sizeof(((bActionGroup *)NULL)->name),
- "Name", "Name of newly created group");
- /* XXX: still not too sure about this - keeping same text is confusing... */
- // RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+ /* props */
+ ot->prop = RNA_def_string(ot->srna,
+ "name",
+ "New Group",
+ sizeof(((bActionGroup *)NULL)->name),
+ "Name",
+ "Name of newly created group");
+ /* XXX: still not too sure about this - keeping same text is confusing... */
+ // RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
}
/* ----------------------------------------------------------- */
static int animchannels_ungroup_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
+ bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* just selected F-Curves... */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* just selected F-Curves... */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* find action for this F-Curve... */
- if (ale->adt && ale->adt->action) {
- FCurve *fcu = (FCurve *)ale->data;
- bAction *act = ale->adt->action;
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* find action for this F-Curve... */
+ if (ale->adt && ale->adt->action) {
+ FCurve *fcu = (FCurve *)ale->data;
+ bAction *act = ale->adt->action;
- /* only proceed to remove if F-Curve is in a group... */
- if (fcu->grp) {
- bActionGroup *agrp = fcu->grp;
+ /* only proceed to remove if F-Curve is in a group... */
+ if (fcu->grp) {
+ bActionGroup *agrp = fcu->grp;
- /* remove F-Curve from group and add at tail (ungrouped) */
- action_groups_remove_channel(act, fcu);
- BLI_addtail(&act->curves, fcu);
+ /* remove F-Curve from group and add at tail (ungrouped) */
+ action_groups_remove_channel(act, fcu);
+ BLI_addtail(&act->curves, fcu);
- /* delete group if it is now empty */
- if (BLI_listbase_is_empty(&agrp->channels)) {
- BLI_freelinkN(&act->groups, agrp);
- }
- }
- }
- }
+ /* delete group if it is now empty */
+ if (BLI_listbase_is_empty(&agrp->channels)) {
+ BLI_freelinkN(&act->groups, agrp);
+ }
+ }
+ }
+ }
- /* cleanup */
- ANIM_animdata_freelist(&anim_data);
+ /* cleanup */
+ ANIM_animdata_freelist(&anim_data);
- /* updates */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ /* updates */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void ANIM_OT_channels_ungroup(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Ungroup Channels";
- ot->idname = "ANIM_OT_channels_ungroup";
- ot->description = "Remove selected F-Curves from their current groups";
+ /* identifiers */
+ ot->name = "Ungroup Channels";
+ ot->idname = "ANIM_OT_channels_ungroup";
+ ot->description = "Remove selected F-Curves from their current groups";
- /* callbacks */
- ot->exec = animchannels_ungroup_exec;
- ot->poll = animchannels_grouping_poll;
+ /* callbacks */
+ ot->exec = animchannels_ungroup_exec;
+ ot->poll = animchannels_grouping_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Delete Channel Operator *********************** */
static void update_dependencies_on_delete(bAnimListElem *ale)
{
- ID *id = ale->id;
- AnimData *adt = BKE_animdata_from_id(id);
- /* TODO(sergey): Technically, if the animation element is being deleted
- * from a driver we don't have to tag action. This is something we can check
- * for in the future. For now just do most reliable tag whic hwas always
- * happening. */
- if (adt != NULL) {
- DEG_id_tag_update(id, ID_RECALC_ANIMATION);
- if (adt->action != NULL) {
- DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION);
- }
- }
- /* Deals with NLA and drivers.
- * Doesn't cause overhead for action updates, since object will receive
- * animation update after dependency graph flushes update from action to
- * all its users. */
- DEG_id_tag_update(id, ID_RECALC_ANIMATION);
+ ID *id = ale->id;
+ AnimData *adt = BKE_animdata_from_id(id);
+ /* TODO(sergey): Technically, if the animation element is being deleted
+ * from a driver we don't have to tag action. This is something we can check
+ * for in the future. For now just do most reliable tag whic hwas always
+ * happening. */
+ if (adt != NULL) {
+ DEG_id_tag_update(id, ID_RECALC_ANIMATION);
+ if (adt->action != NULL) {
+ DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION);
+ }
+ }
+ /* Deals with NLA and drivers.
+ * Doesn't cause overhead for action updates, since object will receive
+ * animation update after dependency graph flushes update from action to
+ * all its users. */
+ DEG_id_tag_update(id, ID_RECALC_ANIMATION);
}
static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* cannot delete in shapekey */
- if (ac.datatype == ANIMCONT_SHAPEKEY)
- return OPERATOR_CANCELLED;
-
-
- /* do groups only first (unless in Drivers mode, where there are none) */
- if (ac.datatype != ANIMCONT_DRIVERS) {
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* delete selected groups and their associated channels */
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* only groups - don't check other types yet, since they may no-longer exist */
- if (ale->type == ANIMTYPE_GROUP) {
- bActionGroup *agrp = (bActionGroup *)ale->data;
- AnimData *adt = ale->adt;
- FCurve *fcu, *fcn;
-
- /* skip this group if no AnimData available, as we can't safely remove the F-Curves */
- if (adt == NULL)
- continue;
-
- /* delete all of the Group's F-Curves, but no others */
- for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcn) {
- fcn = fcu->next;
-
- /* remove from group and action, then free */
- action_groups_remove_channel(adt->action, fcu);
- free_fcurve(fcu);
- }
-
- /* free the group itself */
- if (adt->action) {
- BLI_freelinkN(&adt->action->groups, agrp);
- DEG_id_tag_update_ex(CTX_data_main(C), &adt->action->id, ID_RECALC_ANIMATION);
- }
- else
- MEM_freeN(agrp);
- }
- }
-
- /* cleanup */
- ANIM_animdata_freelist(&anim_data);
- }
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* delete selected data channels */
- for (ale = anim_data.first; ale; ale = ale->next) {
- switch (ale->type) {
- case ANIMTYPE_FCURVE:
- {
- /* F-Curves if we can identify its parent */
- AnimData *adt = ale->adt;
- FCurve *fcu = (FCurve *)ale->data;
-
- /* try to free F-Curve */
- ANIM_fcurve_delete_from_animdata(&ac, adt, fcu);
- update_dependencies_on_delete(ale);
- break;
- }
- case ANIMTYPE_NLACURVE:
- {
- /* NLA Control Curve - Deleting it should disable the corresponding setting... */
- NlaStrip *strip = (NlaStrip *)ale->owner;
- FCurve *fcu = (FCurve *)ale->data;
-
- if (STREQ(fcu->rna_path, "strip_time")) {
- strip->flag &= ~NLASTRIP_FLAG_USR_TIME;
- }
- else if (STREQ(fcu->rna_path, "influence")) {
- strip->flag &= ~NLASTRIP_FLAG_USR_INFLUENCE;
- }
- else {
- printf("ERROR: Trying to delete NLA Control Curve for unknown property '%s'\n", fcu->rna_path);
- }
-
- /* unlink and free the F-Curve */
- BLI_remlink(&strip->fcurves, fcu);
- free_fcurve(fcu);
- update_dependencies_on_delete(ale);
- break;
- }
- case ANIMTYPE_GPLAYER:
- {
- /* Grease Pencil layer */
- bGPdata *gpd = (bGPdata *)ale->id;
- bGPDlayer *gpl = (bGPDlayer *)ale->data;
-
- /* try to delete the layer's data and the layer itself */
- BKE_gpencil_layer_delete(gpd, gpl);
- ale->update = ANIM_UPDATE_DEPS;
- break;
- }
- case ANIMTYPE_MASKLAYER:
- {
- /* Mask layer */
- Mask *mask = (Mask *)ale->id;
- MaskLayer *masklay = (MaskLayer *)ale->data;
-
- /* try to delete the layer's data and the layer itself */
- BKE_mask_layer_remove(mask, masklay);
- break;
- }
- }
- }
-
- /* cleanup */
- ANIM_animdata_freelist(&anim_data);
-
- /* send notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
- DEG_relations_tag_update(CTX_data_main(C));
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* cannot delete in shapekey */
+ if (ac.datatype == ANIMCONT_SHAPEKEY)
+ return OPERATOR_CANCELLED;
+
+ /* do groups only first (unless in Drivers mode, where there are none) */
+ if (ac.datatype != ANIMCONT_DRIVERS) {
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL |
+ ANIMFILTER_LIST_CHANNELS | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* delete selected groups and their associated channels */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* only groups - don't check other types yet, since they may no-longer exist */
+ if (ale->type == ANIMTYPE_GROUP) {
+ bActionGroup *agrp = (bActionGroup *)ale->data;
+ AnimData *adt = ale->adt;
+ FCurve *fcu, *fcn;
+
+ /* skip this group if no AnimData available, as we can't safely remove the F-Curves */
+ if (adt == NULL)
+ continue;
+
+ /* delete all of the Group's F-Curves, but no others */
+ for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcn) {
+ fcn = fcu->next;
+
+ /* remove from group and action, then free */
+ action_groups_remove_channel(adt->action, fcu);
+ free_fcurve(fcu);
+ }
+
+ /* free the group itself */
+ if (adt->action) {
+ BLI_freelinkN(&adt->action->groups, agrp);
+ DEG_id_tag_update_ex(CTX_data_main(C), &adt->action->id, ID_RECALC_ANIMATION);
+ }
+ else
+ MEM_freeN(agrp);
+ }
+ }
+
+ /* cleanup */
+ ANIM_animdata_freelist(&anim_data);
+ }
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL |
+ ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* delete selected data channels */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ switch (ale->type) {
+ case ANIMTYPE_FCURVE: {
+ /* F-Curves if we can identify its parent */
+ AnimData *adt = ale->adt;
+ FCurve *fcu = (FCurve *)ale->data;
+
+ /* try to free F-Curve */
+ ANIM_fcurve_delete_from_animdata(&ac, adt, fcu);
+ update_dependencies_on_delete(ale);
+ break;
+ }
+ case ANIMTYPE_NLACURVE: {
+ /* NLA Control Curve - Deleting it should disable the corresponding setting... */
+ NlaStrip *strip = (NlaStrip *)ale->owner;
+ FCurve *fcu = (FCurve *)ale->data;
+
+ if (STREQ(fcu->rna_path, "strip_time")) {
+ strip->flag &= ~NLASTRIP_FLAG_USR_TIME;
+ }
+ else if (STREQ(fcu->rna_path, "influence")) {
+ strip->flag &= ~NLASTRIP_FLAG_USR_INFLUENCE;
+ }
+ else {
+ printf("ERROR: Trying to delete NLA Control Curve for unknown property '%s'\n",
+ fcu->rna_path);
+ }
+
+ /* unlink and free the F-Curve */
+ BLI_remlink(&strip->fcurves, fcu);
+ free_fcurve(fcu);
+ update_dependencies_on_delete(ale);
+ break;
+ }
+ case ANIMTYPE_GPLAYER: {
+ /* Grease Pencil layer */
+ bGPdata *gpd = (bGPdata *)ale->id;
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+
+ /* try to delete the layer's data and the layer itself */
+ BKE_gpencil_layer_delete(gpd, gpl);
+ ale->update = ANIM_UPDATE_DEPS;
+ break;
+ }
+ case ANIMTYPE_MASKLAYER: {
+ /* Mask layer */
+ Mask *mask = (Mask *)ale->id;
+ MaskLayer *masklay = (MaskLayer *)ale->data;
+
+ /* try to delete the layer's data and the layer itself */
+ BKE_mask_layer_remove(mask, masklay);
+ break;
+ }
+ }
+ }
+
+ /* cleanup */
+ ANIM_animdata_freelist(&anim_data);
+
+ /* send notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ DEG_relations_tag_update(CTX_data_main(C));
+
+ return OPERATOR_FINISHED;
}
static void ANIM_OT_channels_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Channels";
- ot->idname = "ANIM_OT_channels_delete";
- ot->description = "Delete all selected animation channels";
+ /* identifiers */
+ ot->name = "Delete Channels";
+ ot->idname = "ANIM_OT_channels_delete";
+ ot->description = "Delete all selected animation channels";
- /* api callbacks */
- ot->exec = animchannels_delete_exec;
- ot->poll = animedit_poll_channels_active;
+ /* api callbacks */
+ ot->exec = animchannels_delete_exec;
+ ot->poll = animedit_poll_channels_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************** Set Flags Operator *********************** */
/* defines for setting animation-channel flags */
static const EnumPropertyItem prop_animchannel_setflag_types[] = {
- {ACHANNEL_SETFLAG_TOGGLE, "TOGGLE", 0, "Toggle", ""},
- {ACHANNEL_SETFLAG_CLEAR, "DISABLE", 0, "Disable", ""},
- {ACHANNEL_SETFLAG_ADD, "ENABLE", 0, "Enable", ""},
- {ACHANNEL_SETFLAG_INVERT, "INVERT", 0, "Invert", ""},
- {0, NULL, 0, NULL, NULL},
+ {ACHANNEL_SETFLAG_TOGGLE, "TOGGLE", 0, "Toggle", ""},
+ {ACHANNEL_SETFLAG_CLEAR, "DISABLE", 0, "Disable", ""},
+ {ACHANNEL_SETFLAG_ADD, "ENABLE", 0, "Enable", ""},
+ {ACHANNEL_SETFLAG_INVERT, "INVERT", 0, "Invert", ""},
+ {0, NULL, 0, NULL, NULL},
};
/* defines for set animation-channel settings */
// TODO: could add some more types, but those are really quite dependent on the mode...
static const EnumPropertyItem prop_animchannel_settings_types[] = {
- {ACHANNEL_SETTING_PROTECT, "PROTECT", 0, "Protect", ""},
- {ACHANNEL_SETTING_MUTE, "MUTE", 0, "Mute", ""},
- {0, NULL, 0, NULL, NULL},
+ {ACHANNEL_SETTING_PROTECT, "PROTECT", 0, "Protect", ""},
+ {ACHANNEL_SETTING_MUTE, "MUTE", 0, "Mute", ""},
+ {0, NULL, 0, NULL, NULL},
};
-
/* ------------------- */
/* Set/clear a particular flag (setting) for all selected + visible channels
@@ -1822,288 +1824,302 @@ static const EnumPropertyItem prop_animchannel_settings_types[] = {
* onlysel: only selected channels get the flag set
*/
// TODO: enable a setting which turns flushing on/off?
-static void setflag_anim_channels(bAnimContext *ac, eAnimChannel_Settings setting, eAnimChannels_SetFlag mode, bool onlysel, bool flush)
-{
- ListBase anim_data = {NULL, NULL};
- ListBase all_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* filter data that we need if flush is on */
- if (flush) {
- /* get list of all channels that selection may need to be flushed to
- * - hierarchy visibility needs to be ignored so that settings can get flushed
- * "down" inside closed containers
- */
- filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS;
- ANIM_animdata_filter(ac, &all_data, filter, ac->data, ac->datatype);
- }
-
- /* filter data that we're working on
- * - hierarchy matters if we're doing this from the channels region
- * since we only want to apply this to channels we can "see",
- * and have these affect their relatives
- * - but for Graph Editor, this gets used also from main region
- * where hierarchy doesn't apply [#21276]
- */
- if ((ac->spacetype == SPACE_GRAPH) && (ac->regiontype != RGN_TYPE_CHANNELS)) {
- /* graph editor (case 2) */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- }
- else {
- /* standard case */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
- }
- if (onlysel) filter |= ANIMFILTER_SEL;
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* if toggling, check if disable or enable */
- if (mode == ACHANNEL_SETFLAG_TOGGLE) {
- /* default to turn all on, unless we encounter one that's on... */
- mode = ACHANNEL_SETFLAG_ADD;
-
- /* see if we should turn off instead... */
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* set the setting in the appropriate way (if available) */
- if (ANIM_channel_setting_get(ac, ale, setting) > 0) {
- mode = ACHANNEL_SETFLAG_CLEAR;
- break;
- }
- }
- }
-
- /* apply the setting */
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* skip channel if setting is not available */
- if (ANIM_channel_setting_get(ac, ale, setting) == -1)
- continue;
-
- /* set the setting in the appropriate way */
- ANIM_channel_setting_set(ac, ale, setting, mode);
-
- /* if flush status... */
- if (flush)
- ANIM_flush_setting_anim_channels(ac, &all_data, ale, setting, mode);
- }
-
- ANIM_animdata_freelist(&anim_data);
- BLI_freelistN(&all_data);
+static void setflag_anim_channels(bAnimContext *ac,
+ eAnimChannel_Settings setting,
+ eAnimChannels_SetFlag mode,
+ bool onlysel,
+ bool flush)
+{
+ ListBase anim_data = {NULL, NULL};
+ ListBase all_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data that we need if flush is on */
+ if (flush) {
+ /* get list of all channels that selection may need to be flushed to
+ * - hierarchy visibility needs to be ignored so that settings can get flushed
+ * "down" inside closed containers
+ */
+ filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS;
+ ANIM_animdata_filter(ac, &all_data, filter, ac->data, ac->datatype);
+ }
+
+ /* filter data that we're working on
+ * - hierarchy matters if we're doing this from the channels region
+ * since we only want to apply this to channels we can "see",
+ * and have these affect their relatives
+ * - but for Graph Editor, this gets used also from main region
+ * where hierarchy doesn't apply [#21276]
+ */
+ if ((ac->spacetype == SPACE_GRAPH) && (ac->regiontype != RGN_TYPE_CHANNELS)) {
+ /* graph editor (case 2) */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_CURVE_VISIBLE |
+ ANIMFILTER_NODUPLIS);
+ }
+ else {
+ /* standard case */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS |
+ ANIMFILTER_NODUPLIS);
+ }
+ if (onlysel)
+ filter |= ANIMFILTER_SEL;
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* if toggling, check if disable or enable */
+ if (mode == ACHANNEL_SETFLAG_TOGGLE) {
+ /* default to turn all on, unless we encounter one that's on... */
+ mode = ACHANNEL_SETFLAG_ADD;
+
+ /* see if we should turn off instead... */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* set the setting in the appropriate way (if available) */
+ if (ANIM_channel_setting_get(ac, ale, setting) > 0) {
+ mode = ACHANNEL_SETFLAG_CLEAR;
+ break;
+ }
+ }
+ }
+
+ /* apply the setting */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* skip channel if setting is not available */
+ if (ANIM_channel_setting_get(ac, ale, setting) == -1)
+ continue;
+
+ /* set the setting in the appropriate way */
+ ANIM_channel_setting_set(ac, ale, setting, mode);
+
+ /* if flush status... */
+ if (flush)
+ ANIM_flush_setting_anim_channels(ac, &all_data, ale, setting, mode);
+ }
+
+ ANIM_animdata_freelist(&anim_data);
+ BLI_freelistN(&all_data);
}
/* ------------------- */
static int animchannels_setflag_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- eAnimChannel_Settings setting;
- eAnimChannels_SetFlag mode;
- bool flush = true;
+ bAnimContext ac;
+ eAnimChannel_Settings setting;
+ eAnimChannels_SetFlag mode;
+ bool flush = true;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* mode (eAnimChannels_SetFlag), setting (eAnimChannel_Settings) */
- mode = RNA_enum_get(op->ptr, "mode");
- setting = RNA_enum_get(op->ptr, "type");
+ /* mode (eAnimChannels_SetFlag), setting (eAnimChannel_Settings) */
+ mode = RNA_enum_get(op->ptr, "mode");
+ setting = RNA_enum_get(op->ptr, "type");
- /* check if setting is flushable */
- if (setting == ACHANNEL_SETTING_EXPAND)
- flush = false;
+ /* check if setting is flushable */
+ if (setting == ACHANNEL_SETTING_EXPAND)
+ flush = false;
- /* modify setting
- * - only selected channels are affected
- */
- setflag_anim_channels(&ac, setting, mode, true, flush);
+ /* modify setting
+ * - only selected channels are affected
+ */
+ setflag_anim_channels(&ac, setting, mode, true, flush);
- /* send notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ /* send notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* duplicate of 'ANIM_OT_channels_setting_toggle' for menu title only, weak! */
static void ANIM_OT_channels_setting_enable(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Enable Channel Setting";
- ot->idname = "ANIM_OT_channels_setting_enable";
- ot->description = "Enable specified setting on all selected animation channels";
+ /* identifiers */
+ ot->name = "Enable Channel Setting";
+ ot->idname = "ANIM_OT_channels_setting_enable";
+ ot->description = "Enable specified setting on all selected animation channels";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = animchannels_setflag_exec;
- ot->poll = animedit_poll_channels_active;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = animchannels_setflag_exec;
+ ot->poll = animedit_poll_channels_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- /* flag-setting mode */
- prop = RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_ADD, "Mode", "");
- RNA_def_property_flag(prop, PROP_HIDDEN);
- /* setting to set */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
+ /* props */
+ /* flag-setting mode */
+ prop = RNA_def_enum(
+ ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_ADD, "Mode", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ /* setting to set */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
}
/* duplicate of 'ANIM_OT_channels_setting_toggle' for menu title only, weak! */
static void ANIM_OT_channels_setting_disable(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Disable Channel Setting";
- ot->idname = "ANIM_OT_channels_setting_disable";
- ot->description = "Disable specified setting on all selected animation channels";
+ /* identifiers */
+ ot->name = "Disable Channel Setting";
+ ot->idname = "ANIM_OT_channels_setting_disable";
+ ot->description = "Disable specified setting on all selected animation channels";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = animchannels_setflag_exec;
- ot->poll = animedit_poll_channels_active;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = animchannels_setflag_exec;
+ ot->poll = animedit_poll_channels_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- /* flag-setting mode */
- prop = RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_CLEAR, "Mode", "");
- RNA_def_property_flag(prop, PROP_HIDDEN); /* internal hack - don't expose */
- /* setting to set */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
+ /* props */
+ /* flag-setting mode */
+ prop = RNA_def_enum(
+ ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_CLEAR, "Mode", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN); /* internal hack - don't expose */
+ /* setting to set */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
}
static void ANIM_OT_channels_setting_toggle(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Toggle Channel Setting";
- ot->idname = "ANIM_OT_channels_setting_toggle";
- ot->description = "Toggle specified setting on all selected animation channels";
+ /* identifiers */
+ ot->name = "Toggle Channel Setting";
+ ot->idname = "ANIM_OT_channels_setting_toggle";
+ ot->description = "Toggle specified setting on all selected animation channels";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = animchannels_setflag_exec;
- ot->poll = animedit_poll_channels_active;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = animchannels_setflag_exec;
+ ot->poll = animedit_poll_channels_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- /* flag-setting mode */
- prop = RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", "");
- RNA_def_property_flag(prop, PROP_HIDDEN); /* internal hack - don't expose */
- /* setting to set */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
+ /* props */
+ /* flag-setting mode */
+ prop = RNA_def_enum(
+ ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN); /* internal hack - don't expose */
+ /* setting to set */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
}
static void ANIM_OT_channels_editable_toggle(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Toggle Channel Editability";
- ot->idname = "ANIM_OT_channels_editable_toggle";
- ot->description = "Toggle editability of selected channels";
+ /* identifiers */
+ ot->name = "Toggle Channel Editability";
+ ot->idname = "ANIM_OT_channels_editable_toggle";
+ ot->description = "Toggle editability of selected channels";
- /* api callbacks */
- ot->exec = animchannels_setflag_exec;
- ot->poll = animedit_poll_channels_active;
+ /* api callbacks */
+ ot->exec = animchannels_setflag_exec;
+ ot->poll = animedit_poll_channels_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- /* flag-setting mode */
- RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", "");
- /* setting to set */
- prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, ACHANNEL_SETTING_PROTECT, "Type", "");
- RNA_def_property_flag(prop, PROP_HIDDEN); /* internal hack - don't expose */
+ /* props */
+ /* flag-setting mode */
+ RNA_def_enum(
+ ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", "");
+ /* setting to set */
+ prop = RNA_def_enum(
+ ot->srna, "type", prop_animchannel_settings_types, ACHANNEL_SETTING_PROTECT, "Type", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN); /* internal hack - don't expose */
}
/* ********************** Expand Channels Operator *********************** */
static int animchannels_expand_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- bool onlysel = true;
+ bAnimContext ac;
+ bool onlysel = true;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* only affect selected channels? */
- if (RNA_boolean_get(op->ptr, "all"))
- onlysel = false;
+ /* only affect selected channels? */
+ if (RNA_boolean_get(op->ptr, "all"))
+ onlysel = false;
- /* modify setting */
- setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_ADD, onlysel, false);
+ /* modify setting */
+ setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_ADD, onlysel, false);
- /* send notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ /* send notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void ANIM_OT_channels_expand(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Expand Channels";
- ot->idname = "ANIM_OT_channels_expand";
- ot->description = "Expand (i.e. open) all selected expandable animation channels";
+ /* identifiers */
+ ot->name = "Expand Channels";
+ ot->idname = "ANIM_OT_channels_expand";
+ ot->description = "Expand (i.e. open) all selected expandable animation channels";
- /* api callbacks */
- ot->exec = animchannels_expand_exec;
- ot->poll = animedit_poll_channels_active;
+ /* api callbacks */
+ ot->exec = animchannels_expand_exec;
+ ot->poll = animedit_poll_channels_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- ot->prop = RNA_def_boolean(ot->srna, "all", 1, "All", "Expand all channels (not just selected ones)");
+ /* props */
+ ot->prop = RNA_def_boolean(
+ ot->srna, "all", 1, "All", "Expand all channels (not just selected ones)");
}
/* ********************** Collapse Channels Operator *********************** */
static int animchannels_collapse_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- bool onlysel = true;
+ bAnimContext ac;
+ bool onlysel = true;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* only affect selected channels? */
- if (RNA_boolean_get(op->ptr, "all"))
- onlysel = false;
+ /* only affect selected channels? */
+ if (RNA_boolean_get(op->ptr, "all"))
+ onlysel = false;
- /* modify setting */
- setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_CLEAR, onlysel, false);
+ /* modify setting */
+ setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_CLEAR, onlysel, false);
- /* send notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ /* send notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void ANIM_OT_channels_collapse(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Collapse Channels";
- ot->idname = "ANIM_OT_channels_collapse";
- ot->description = "Collapse (i.e. close) all selected expandable animation channels";
+ /* identifiers */
+ ot->name = "Collapse Channels";
+ ot->idname = "ANIM_OT_channels_collapse";
+ ot->description = "Collapse (i.e. close) all selected expandable animation channels";
- /* api callbacks */
- ot->exec = animchannels_collapse_exec;
- ot->poll = animedit_poll_channels_active;
+ /* api callbacks */
+ ot->exec = animchannels_collapse_exec;
+ ot->poll = animedit_poll_channels_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- ot->prop = RNA_def_boolean(ot->srna, "all", true, "All", "Collapse all channels (not just selected ones)");
+ /* props */
+ ot->prop = RNA_def_boolean(
+ ot->srna, "all", true, "All", "Collapse all channels (not just selected ones)");
}
/* ************ Remove All "Empty" AnimData Blocks Operator ********* */
@@ -2120,170 +2136,169 @@ static void ANIM_OT_channels_collapse(wmOperatorType *ot)
static int animchannels_clean_empty_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get animdata blocks */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- ID *id = ale->id;
- AnimData *adt = ale->data;
-
- bool action_empty = false;
- bool nla_empty = false;
- bool drivers_empty = false;
-
- /* sanity checks */
- BLI_assert((id != NULL) && (adt != NULL));
-
- /* check if this is "empty" and can be deleted */
- /* (For now, there are only these 3 criteria) */
-
- /* 1) Active Action is missing or empty */
- if (ELEM(NULL, adt->action, adt->action->curves.first)) {
- action_empty = true;
- }
- else {
- /* TODO: check for keyframe + fmodifier data on these too */
- }
-
- /* 2) No NLA Tracks and/or NLA Strips */
- if (adt->nla_tracks.first == NULL) {
- nla_empty = true;
- }
- else {
- NlaTrack *nlt;
-
- /* empty tracks? */
- for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
- if (nlt->strips.first) {
- /* stop searching, as we found one that actually had stuff we don't want lost
- * NOTE: nla_empty gets reset to false, as a previous track may have been empty
- */
- nla_empty = false;
- break;
- }
- else if (nlt->strips.first == NULL) {
- /* this track is empty, but another one may still have stuff in it, so can't break yet */
- nla_empty = true;
- }
- }
- }
-
- /* 3) Drivers */
- drivers_empty = (adt->drivers.first == NULL);
-
-
- /* remove AnimData? */
- if (action_empty && nla_empty && drivers_empty) {
- BKE_animdata_free(id, true);
- }
- }
-
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
-
- /* send notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get animdata blocks */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ ID *id = ale->id;
+ AnimData *adt = ale->data;
+
+ bool action_empty = false;
+ bool nla_empty = false;
+ bool drivers_empty = false;
+
+ /* sanity checks */
+ BLI_assert((id != NULL) && (adt != NULL));
+
+ /* check if this is "empty" and can be deleted */
+ /* (For now, there are only these 3 criteria) */
+
+ /* 1) Active Action is missing or empty */
+ if (ELEM(NULL, adt->action, adt->action->curves.first)) {
+ action_empty = true;
+ }
+ else {
+ /* TODO: check for keyframe + fmodifier data on these too */
+ }
+
+ /* 2) No NLA Tracks and/or NLA Strips */
+ if (adt->nla_tracks.first == NULL) {
+ nla_empty = true;
+ }
+ else {
+ NlaTrack *nlt;
+
+ /* empty tracks? */
+ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+ if (nlt->strips.first) {
+ /* stop searching, as we found one that actually had stuff we don't want lost
+ * NOTE: nla_empty gets reset to false, as a previous track may have been empty
+ */
+ nla_empty = false;
+ break;
+ }
+ else if (nlt->strips.first == NULL) {
+ /* this track is empty, but another one may still have stuff in it, so can't break yet */
+ nla_empty = true;
+ }
+ }
+ }
+
+ /* 3) Drivers */
+ drivers_empty = (adt->drivers.first == NULL);
+
+ /* remove AnimData? */
+ if (action_empty && nla_empty && drivers_empty) {
+ BKE_animdata_free(id, true);
+ }
+ }
+
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
+
+ /* send notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
}
static void ANIM_OT_channels_clean_empty(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Empty Animation Data";
- ot->idname = "ANIM_OT_channels_clean_empty";
- ot->description = "Delete all empty animation data containers from visible data-blocks";
+ /* identifiers */
+ ot->name = "Remove Empty Animation Data";
+ ot->idname = "ANIM_OT_channels_clean_empty";
+ ot->description = "Delete all empty animation data containers from visible data-blocks";
- /* api callbacks */
- ot->exec = animchannels_clean_empty_exec;
- ot->poll = animedit_poll_channels_nla_tweakmode_off;
+ /* api callbacks */
+ ot->exec = animchannels_clean_empty_exec;
+ ot->poll = animedit_poll_channels_nla_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************* Reenable Disabled Operator ******************* */
static bool animchannels_enable_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *sa = CTX_wm_area(C);
- /* channels region test */
- /* TODO: could enhance with actually testing if channels region? */
- if (ELEM(NULL, sa, CTX_wm_region(C)))
- return 0;
+ /* channels region test */
+ /* TODO: could enhance with actually testing if channels region? */
+ if (ELEM(NULL, sa, CTX_wm_region(C)))
+ return 0;
- /* animation editor test - Action/Dopesheet/etc. and Graph only */
- if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH) == 0)
- return 0;
+ /* animation editor test - Action/Dopesheet/etc. and Graph only */
+ if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH) == 0)
+ return 0;
- return 1;
+ return 1;
}
static int animchannels_enable_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
+ bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* loop through filtered data and clean curves */
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->data;
+ /* loop through filtered data and clean curves */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->data;
- /* remove disabled flags from F-Curves */
- fcu->flag &= ~FCURVE_DISABLED;
+ /* remove disabled flags from F-Curves */
+ fcu->flag &= ~FCURVE_DISABLED;
- /* for drivers, let's do the same too */
- if (fcu->driver)
- fcu->driver->flag &= ~DRIVER_FLAG_INVALID;
+ /* for drivers, let's do the same too */
+ if (fcu->driver)
+ fcu->driver->flag &= ~DRIVER_FLAG_INVALID;
- /* tag everything for updates - in particular, this is needed to get drivers working again */
- ale->update |= ANIM_UPDATE_DEPS;
- }
+ /* tag everything for updates - in particular, this is needed to get drivers working again */
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
- ANIM_animdata_update(&ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ANIM_animdata_update(&ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
- /* send notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ /* send notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void ANIM_OT_channels_fcurves_enable(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Revive Disabled F-Curves";
- ot->idname = "ANIM_OT_channels_fcurves_enable";
- ot->description = "Clears 'disabled' tag from all F-Curves to get broken F-Curves working again";
+ /* identifiers */
+ ot->name = "Revive Disabled F-Curves";
+ ot->idname = "ANIM_OT_channels_fcurves_enable";
+ ot->description = "Clears 'disabled' tag from all F-Curves to get broken F-Curves working again";
- /* api callbacks */
- ot->exec = animchannels_enable_exec;
- ot->poll = animchannels_enable_poll;
+ /* api callbacks */
+ ot->exec = animchannels_enable_exec;
+ ot->poll = animchannels_enable_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** Find / Set Filter Operator ******************** */
@@ -2291,253 +2306,256 @@ 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 *sa = CTX_wm_area(C);
- if (sa == NULL)
- return 0;
+ if (sa == NULL)
+ return 0;
- /* animation editor with dopesheet */
- return ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA);
+ /* animation editor with dopesheet */
+ return ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA);
}
/* find_invoke() - Get initial channels */
static int animchannels_find_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
{
- bAnimContext ac;
+ bAnimContext ac;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* set initial filter text, and enable filter */
- RNA_string_set(op->ptr, "query", ac.ads->searchstr);
+ /* set initial filter text, and enable filter */
+ RNA_string_set(op->ptr, "query", ac.ads->searchstr);
- /* defer to popup */
- return WM_operator_props_popup(C, op, evt);
+ /* defer to popup */
+ return WM_operator_props_popup(C, op, evt);
}
/* find_exec() - Called to set the value */
static int animchannels_find_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
+ bAnimContext ac;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* update filter text */
- RNA_string_get(op->ptr, "query", ac.ads->searchstr);
+ /* update filter text */
+ RNA_string_get(op->ptr, "query", ac.ads->searchstr);
- /* redraw */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ /* redraw */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void ANIM_OT_channels_find(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Find Channels";
- ot->idname = "ANIM_OT_channels_find";
- ot->description = "Filter the set of channels shown to only include those with matching names";
+ /* identifiers */
+ ot->name = "Find Channels";
+ ot->idname = "ANIM_OT_channels_find";
+ ot->description = "Filter the set of channels shown to only include those with matching names";
- /* callbacks */
- ot->invoke = animchannels_find_invoke;
- ot->exec = animchannels_find_exec;
- ot->poll = animchannels_find_poll;
+ /* callbacks */
+ ot->invoke = animchannels_find_invoke;
+ ot->exec = animchannels_find_exec;
+ ot->poll = animchannels_find_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_string(ot->srna, "query", "Query", sizeof(((bDopeSheet *)NULL)->searchstr), "", "Text to search for in channel names");
+ /* properties */
+ ot->prop = RNA_def_string(ot->srna,
+ "query",
+ "Query",
+ sizeof(((bDopeSheet *)NULL)->searchstr),
+ "",
+ "Text to search for in channel names");
}
/* ********************** Select All Operator *********************** */
static int animchannels_deselectall_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* 'standard' behavior - check if selected, then apply relevant selection */
- const int action = RNA_enum_get(op->ptr, "action");
- switch (action) {
- case SEL_TOGGLE:
- ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, true, ACHANNEL_SETFLAG_ADD);
- break;
- case SEL_SELECT:
- ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, false, ACHANNEL_SETFLAG_ADD);
- break;
- case SEL_DESELECT:
- ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, false, ACHANNEL_SETFLAG_CLEAR);
- break;
- case SEL_INVERT:
- ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, false, ACHANNEL_SETFLAG_INVERT);
- break;
- default:
- BLI_assert(0);
- break;
- }
-
- /* send notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* 'standard' behavior - check if selected, then apply relevant selection */
+ const int action = RNA_enum_get(op->ptr, "action");
+ switch (action) {
+ case SEL_TOGGLE:
+ ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, true, ACHANNEL_SETFLAG_ADD);
+ break;
+ case SEL_SELECT:
+ ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, false, ACHANNEL_SETFLAG_ADD);
+ break;
+ case SEL_DESELECT:
+ ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, false, ACHANNEL_SETFLAG_CLEAR);
+ break;
+ case SEL_INVERT:
+ ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, false, ACHANNEL_SETFLAG_INVERT);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ /* send notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
+
+ return OPERATOR_FINISHED;
}
static void ANIM_OT_channels_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select All";
- ot->idname = "ANIM_OT_channels_select_all";
- ot->description = "Toggle selection of all animation channels";
+ /* identifiers */
+ ot->name = "Select All";
+ ot->idname = "ANIM_OT_channels_select_all";
+ ot->description = "Toggle selection of all animation channels";
- /* api callbacks */
- ot->exec = animchannels_deselectall_exec;
- ot->poll = animedit_poll_channels_nla_tweakmode_off;
+ /* api callbacks */
+ ot->exec = animchannels_deselectall_exec;
+ ot->poll = animedit_poll_channels_nla_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_select_all(ot);
+ /* properties */
+ WM_operator_properties_select_all(ot);
}
/* ******************** Box Select Operator *********************** */
static void box_select_anim_channels(bAnimContext *ac, rcti *rect, short selectmode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- SpaceNla *snla = (SpaceNla *)ac->sl;
- View2D *v2d = &ac->ar->v2d;
- rctf rectf;
- float ymin, ymax;
-
- /* set initial y extents */
- if (ac->datatype == ANIMCONT_NLA) {
- ymin = (float)(-NLACHANNEL_HEIGHT(snla));
- ymax = 0.0f;
- }
- else {
- ymin = 0.0f;
- ymax = (float)(-ACHANNEL_HEIGHT(ac));
- }
-
- /* convert border-region to view coordinates */
- UI_view2d_region_to_view(v2d, rect->xmin, rect->ymin + 2, &rectf.xmin, &rectf.ymin);
- UI_view2d_region_to_view(v2d, rect->xmax, rect->ymax - 2, &rectf.xmax, &rectf.ymax);
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* loop over data, doing box select */
- for (ale = anim_data.first; ale; ale = ale->next) {
- if (ac->datatype == ANIMCONT_NLA)
- ymin = ymax - NLACHANNEL_STEP(snla);
- else
- ymin = ymax - ACHANNEL_STEP(ac);
-
- /* if channel is within border-select region, alter it */
- if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
- /* set selection flags only */
- ANIM_channel_setting_set(ac, ale, ACHANNEL_SETTING_SELECT, selectmode);
-
- /* type specific actions */
- switch (ale->type) {
- case ANIMTYPE_GROUP:
- {
- bActionGroup *agrp = (bActionGroup *)ale->data;
- select_pchan_for_action_group(ac, agrp, ale);
- /* always clear active flag after doing this */
- agrp->flag &= ~AGRP_ACTIVE;
- break;
- }
- case ANIMTYPE_NLATRACK:
- {
- NlaTrack *nlt = (NlaTrack *)ale->data;
-
- /* for now, it's easier just to do this here manually, as defining a new type
- * currently adds complications when doing other stuff
- */
- ACHANNEL_SET_FLAG(nlt, selectmode, NLATRACK_SELECTED);
- break;
- }
- }
- }
-
- /* set minimum extent to be the maximum of the next channel */
- ymax = ymin;
- }
-
- /* cleanup */
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ SpaceNla *snla = (SpaceNla *)ac->sl;
+ View2D *v2d = &ac->ar->v2d;
+ rctf rectf;
+ float ymin, ymax;
+
+ /* set initial y extents */
+ if (ac->datatype == ANIMCONT_NLA) {
+ ymin = (float)(-NLACHANNEL_HEIGHT(snla));
+ ymax = 0.0f;
+ }
+ else {
+ ymin = 0.0f;
+ ymax = (float)(-ACHANNEL_HEIGHT(ac));
+ }
+
+ /* convert border-region to view coordinates */
+ UI_view2d_region_to_view(v2d, rect->xmin, rect->ymin + 2, &rectf.xmin, &rectf.ymin);
+ UI_view2d_region_to_view(v2d, rect->xmax, rect->ymax - 2, &rectf.xmax, &rectf.ymax);
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop over data, doing box select */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (ac->datatype == ANIMCONT_NLA)
+ ymin = ymax - NLACHANNEL_STEP(snla);
+ else
+ ymin = ymax - ACHANNEL_STEP(ac);
+
+ /* if channel is within border-select region, alter it */
+ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
+ /* set selection flags only */
+ ANIM_channel_setting_set(ac, ale, ACHANNEL_SETTING_SELECT, selectmode);
+
+ /* type specific actions */
+ switch (ale->type) {
+ case ANIMTYPE_GROUP: {
+ bActionGroup *agrp = (bActionGroup *)ale->data;
+ select_pchan_for_action_group(ac, agrp, ale);
+ /* always clear active flag after doing this */
+ agrp->flag &= ~AGRP_ACTIVE;
+ break;
+ }
+ case ANIMTYPE_NLATRACK: {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+
+ /* for now, it's easier just to do this here manually, as defining a new type
+ * currently adds complications when doing other stuff
+ */
+ ACHANNEL_SET_FLAG(nlt, selectmode, NLATRACK_SELECTED);
+ break;
+ }
+ }
+ }
+
+ /* set minimum extent to be the maximum of the next channel */
+ ymax = ymin;
+ }
+
+ /* cleanup */
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int animchannels_box_select_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- rcti rect;
- short selectmode = 0;
- const bool select = !RNA_boolean_get(op->ptr, "deselect");
- const bool extend = RNA_boolean_get(op->ptr, "extend");
+ bAnimContext ac;
+ rcti rect;
+ short selectmode = 0;
+ const bool select = !RNA_boolean_get(op->ptr, "deselect");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* get settings from operator */
- WM_operator_properties_border_to_rcti(op, &rect);
+ /* get settings from operator */
+ WM_operator_properties_border_to_rcti(op, &rect);
- if (!extend) {
- ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, true, ACHANNEL_SETFLAG_CLEAR);
- }
+ if (!extend) {
+ ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, true, ACHANNEL_SETFLAG_CLEAR);
+ }
- if (select) {
- selectmode = ACHANNEL_SETFLAG_ADD;
- }
- else {
- selectmode = ACHANNEL_SETFLAG_CLEAR;
- }
+ if (select) {
+ selectmode = ACHANNEL_SETFLAG_ADD;
+ }
+ else {
+ selectmode = ACHANNEL_SETFLAG_CLEAR;
+ }
- /* apply box_select animation channels */
- box_select_anim_channels(&ac, &rect, selectmode);
+ /* apply box_select animation channels */
+ box_select_anim_channels(&ac, &rect, selectmode);
- /* send notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
+ /* send notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void ANIM_OT_channels_select_box(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Box Select";
- ot->idname = "ANIM_OT_channels_select_box";
- ot->description = "Select all animation channels within the specified region";
+ /* identifiers */
+ ot->name = "Box Select";
+ ot->idname = "ANIM_OT_channels_select_box";
+ ot->description = "Select all animation channels within the specified region";
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = animchannels_box_select_exec;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = animchannels_box_select_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
- ot->poll = animedit_poll_channels_nla_tweakmode_off;
+ ot->poll = animedit_poll_channels_nla_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* rna */
- WM_operator_properties_gesture_box_select(ot);
+ /* rna */
+ WM_operator_properties_gesture_box_select(ot);
}
/* ******************* Rename Operator ***************************** */
@@ -2545,114 +2563,131 @@ static void ANIM_OT_channels_select_box(wmOperatorType *ot)
static bool rename_anim_channels(bAnimContext *ac, int channel_index)
{
- ListBase anim_data = {NULL, NULL};
- const bAnimChannelType *acf;
- bAnimListElem *ale;
- int filter;
- bool success = false;
-
- /* get the channel that was clicked on */
- /* filter channels */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* get channel from index */
- ale = BLI_findlink(&anim_data, channel_index);
- if (ale == NULL) {
- /* channel not found */
- if (G.debug & G_DEBUG)
- printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n", channel_index);
-
- ANIM_animdata_freelist(&anim_data);
- return false;
- }
-
- /* check that channel can be renamed */
- acf = ANIM_channel_get_typeinfo(ale);
- if (acf && acf->name_prop) {
- PointerRNA ptr;
- PropertyRNA *prop;
-
- /* ok if we can get name property to edit from this channel */
- if (acf->name_prop(ale, &ptr, &prop)) {
- /* actually showing the rename textfield is done on redraw,
- * so here we just store the index of this channel in the
- * dopesheet data, which will get utilized when drawing the
- * channel...
- *
- * +1 factor is for backwards compat issues
- */
- if (ac->ads) {
- ac->ads->renameIndex = channel_index + 1;
- success = true;
- }
- }
- }
-
- /* free temp data and tag for refresh */
- ANIM_animdata_freelist(&anim_data);
- ED_region_tag_redraw(ac->ar);
- return success;
+ ListBase anim_data = {NULL, NULL};
+ const bAnimChannelType *acf;
+ bAnimListElem *ale;
+ int filter;
+ bool success = false;
+
+ /* get the channel that was clicked on */
+ /* filter channels */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* get channel from index */
+ ale = BLI_findlink(&anim_data, channel_index);
+ if (ale == NULL) {
+ /* channel not found */
+ if (G.debug & G_DEBUG)
+ printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n",
+ channel_index);
+
+ ANIM_animdata_freelist(&anim_data);
+ return false;
+ }
+
+ /* check that channel can be renamed */
+ acf = ANIM_channel_get_typeinfo(ale);
+ if (acf && acf->name_prop) {
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ /* ok if we can get name property to edit from this channel */
+ if (acf->name_prop(ale, &ptr, &prop)) {
+ /* actually showing the rename textfield is done on redraw,
+ * so here we just store the index of this channel in the
+ * dopesheet data, which will get utilized when drawing the
+ * channel...
+ *
+ * +1 factor is for backwards compat issues
+ */
+ if (ac->ads) {
+ ac->ads->renameIndex = channel_index + 1;
+ success = true;
+ }
+ }
+ }
+
+ /* free temp data and tag for refresh */
+ ANIM_animdata_freelist(&anim_data);
+ ED_region_tag_redraw(ac->ar);
+ return success;
}
static int animchannels_channel_get(bAnimContext *ac, const int mval[2])
{
- ARegion *ar;
- View2D *v2d;
- int channel_index;
- float x, y;
-
- /* get useful pointers from animation context data */
- ar = ac->ar;
- v2d = &ar->v2d;
-
- /* figure out which channel user clicked in
- * Note: although channels technically start at (y = ACHANNEL_FIRST), we need to adjust by half a channel's height
- * so that the tops of channels get caught ok. Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use
- * ACHANNEL_HEIGHT_HALF.
- */
- UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
-
- if (ac->datatype == ANIMCONT_NLA) {
- SpaceNla *snla = (SpaceNla *)ac->sl;
- UI_view2d_listview_view_to_cell(v2d, NLACHANNEL_NAMEWIDTH, NLACHANNEL_STEP(snla), 0, (float)NLACHANNEL_HEIGHT_HALF(snla), x, y, NULL, &channel_index);
- }
- else {
- UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP(ac), 0, (float)ACHANNEL_HEIGHT_HALF(ac), x, y, NULL, &channel_index);
- }
-
- return channel_index;
+ ARegion *ar;
+ View2D *v2d;
+ int channel_index;
+ float x, y;
+
+ /* get useful pointers from animation context data */
+ ar = ac->ar;
+ v2d = &ar->v2d;
+
+ /* figure out which channel user clicked in
+ * Note: although channels technically start at (y = ACHANNEL_FIRST), we need to adjust by half a channel's height
+ * so that the tops of channels get caught ok. Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use
+ * ACHANNEL_HEIGHT_HALF.
+ */
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
+
+ if (ac->datatype == ANIMCONT_NLA) {
+ SpaceNla *snla = (SpaceNla *)ac->sl;
+ UI_view2d_listview_view_to_cell(v2d,
+ NLACHANNEL_NAMEWIDTH,
+ NLACHANNEL_STEP(snla),
+ 0,
+ (float)NLACHANNEL_HEIGHT_HALF(snla),
+ x,
+ y,
+ NULL,
+ &channel_index);
+ }
+ else {
+ UI_view2d_listview_view_to_cell(v2d,
+ ACHANNEL_NAMEWIDTH,
+ ACHANNEL_STEP(ac),
+ 0,
+ (float)ACHANNEL_HEIGHT_HALF(ac),
+ x,
+ y,
+ NULL,
+ &channel_index);
+ }
+
+ return channel_index;
}
static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- bAnimContext ac;
- int channel_index;
+ bAnimContext ac;
+ int channel_index;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- channel_index = animchannels_channel_get(&ac, event->mval);
+ channel_index = animchannels_channel_get(&ac, event->mval);
- /* handle click */
- if (rename_anim_channels(&ac, channel_index))
- return OPERATOR_FINISHED;
- else
- /* allow event to be handled by selectall operator */
- return OPERATOR_PASS_THROUGH;
+ /* handle click */
+ if (rename_anim_channels(&ac, channel_index))
+ return OPERATOR_FINISHED;
+ else
+ /* allow event to be handled by selectall operator */
+ return OPERATOR_PASS_THROUGH;
}
static void ANIM_OT_channels_rename(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Rename Channels";
- ot->idname = "ANIM_OT_channels_rename";
- ot->description = "Rename animation channel under mouse";
+ /* identifiers */
+ ot->name = "Rename Channels";
+ ot->idname = "ANIM_OT_channels_rename";
+ ot->description = "Rename animation channel under mouse";
- /* api callbacks */
- ot->invoke = animchannels_rename_invoke;
- ot->poll = animedit_poll_channels_active;
+ /* api callbacks */
+ ot->invoke = animchannels_rename_invoke;
+ ot->poll = animedit_poll_channels_active;
}
/* ******************** Mouse-Click Operator *********************** */
@@ -2660,357 +2695,355 @@ static void ANIM_OT_channels_rename(wmOperatorType *ot)
static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, short selectmode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- int notifierFlags = 0;
-
- /* get the channel that was clicked on */
- /* filter channels */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* get channel from index */
- ale = BLI_findlink(&anim_data, channel_index);
- if (ale == NULL) {
- /* channel not found */
- if (G.debug & G_DEBUG)
- printf("Error: animation channel (index = %d) not found in mouse_anim_channels()\n", channel_index);
-
- ANIM_animdata_freelist(&anim_data);
- return 0;
- }
-
- /* selectmode -1 is a special case for ActionGroups only, which selects all of the channels underneath it only... */
- /* TODO: should this feature be extended to work with other channel types too? */
- if ((selectmode == -1) && (ale->type != ANIMTYPE_GROUP)) {
- /* normal channels should not behave normally in this case */
- ANIM_animdata_freelist(&anim_data);
- return 0;
- }
-
- /* action to take depends on what channel we've got */
- /* WARNING: must keep this in sync with the equivalent function in nla_channels.c */
- switch (ale->type) {
- case ANIMTYPE_SCENE:
- {
- Scene *sce = (Scene *)ale->data;
- AnimData *adt = sce->adt;
-
- /* set selection status */
- if (selectmode == SELECT_INVERT) {
- /* swap select */
- sce->flag ^= SCE_DS_SELECTED;
- if (adt) adt->flag ^= ADT_UI_SELECTED;
- }
- else {
- sce->flag |= SCE_DS_SELECTED;
- if (adt) adt->flag |= ADT_UI_SELECTED;
- }
-
- notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
- break;
- }
- case ANIMTYPE_OBJECT:
- {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ int notifierFlags = 0;
+
+ /* get the channel that was clicked on */
+ /* filter channels */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* get channel from index */
+ ale = BLI_findlink(&anim_data, channel_index);
+ if (ale == NULL) {
+ /* channel not found */
+ if (G.debug & G_DEBUG)
+ printf("Error: animation channel (index = %d) not found in mouse_anim_channels()\n",
+ channel_index);
+
+ ANIM_animdata_freelist(&anim_data);
+ return 0;
+ }
+
+ /* selectmode -1 is a special case for ActionGroups only, which selects all of the channels underneath it only... */
+ /* TODO: should this feature be extended to work with other channel types too? */
+ if ((selectmode == -1) && (ale->type != ANIMTYPE_GROUP)) {
+ /* normal channels should not behave normally in this case */
+ ANIM_animdata_freelist(&anim_data);
+ return 0;
+ }
+
+ /* action to take depends on what channel we've got */
+ /* WARNING: must keep this in sync with the equivalent function in nla_channels.c */
+ switch (ale->type) {
+ case ANIMTYPE_SCENE: {
+ Scene *sce = (Scene *)ale->data;
+ AnimData *adt = sce->adt;
+
+ /* set selection status */
+ if (selectmode == SELECT_INVERT) {
+ /* swap select */
+ sce->flag ^= SCE_DS_SELECTED;
+ if (adt)
+ adt->flag ^= ADT_UI_SELECTED;
+ }
+ else {
+ sce->flag |= SCE_DS_SELECTED;
+ if (adt)
+ adt->flag |= ADT_UI_SELECTED;
+ }
+
+ notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
+ break;
+ }
+ case ANIMTYPE_OBJECT: {
#if 0
- bDopeSheet *ads = (bDopeSheet *)ac->data;
- Scene *sce = (Scene *)ads->source;
+ bDopeSheet *ads = (bDopeSheet *)ac->data;
+ Scene *sce = (Scene *)ads->source;
#endif
- ViewLayer *view_layer = ac->view_layer;
- Base *base = (Base *)ale->data;
- Object *ob = base->object;
- AnimData *adt = ob->adt;
-
- /* set selection status */
- if (base->flag & BASE_SELECTABLE) {
- if (selectmode == SELECT_INVERT) {
- /* swap select */
- ED_object_base_select(base, BA_INVERT);
- BKE_scene_object_base_flag_sync_from_base(base);
-
- if (adt) adt->flag ^= ADT_UI_SELECTED;
- }
- else {
- Base *b;
-
- /* deselect all */
- /* TODO: should this deselect all other types of channels too? */
- for (b = view_layer->object_bases.first; b; b = b->next) {
- ED_object_base_select(b, BA_DESELECT);
- BKE_scene_object_base_flag_sync_from_base(b);
- if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE);
- }
-
- /* select object now */
- ED_object_base_select(base, BA_SELECT);
- BKE_scene_object_base_flag_sync_from_base(base);
- if (adt) adt->flag |= ADT_UI_SELECTED;
- }
-
- /* change active object - regardless of whether it is now selected [T37883] */
- ED_object_base_activate(C, base); /* adds notifier */
-
- if ((adt) && (adt->flag & ADT_UI_SELECTED))
- adt->flag |= ADT_UI_ACTIVE;
-
- /* ensure we exit editmode on whatever object was active before to avoid getting stuck there - T48747 */
- if (ob != CTX_data_edit_object(C)) {
- ED_object_editmode_exit(C, EM_FREEDATA);
- }
-
- notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
- }
- break;
- }
- case ANIMTYPE_FILLACTD: /* Action Expander */
- case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
- case ANIMTYPE_DSLAM:
- case ANIMTYPE_DSCAM:
- case ANIMTYPE_DSCACHEFILE:
- case ANIMTYPE_DSCUR:
- case ANIMTYPE_DSSKEY:
- case ANIMTYPE_DSWOR:
- case ANIMTYPE_DSPART:
- case ANIMTYPE_DSMBALL:
- case ANIMTYPE_DSARM:
- case ANIMTYPE_DSMESH:
- case ANIMTYPE_DSNTREE:
- case ANIMTYPE_DSTEX:
- case ANIMTYPE_DSLAT:
- case ANIMTYPE_DSLINESTYLE:
- case ANIMTYPE_DSSPK:
- case ANIMTYPE_DSGPENCIL:
- case ANIMTYPE_DSMCLIP:
- {
- /* sanity checking... */
- if (ale->adt) {
- /* select/deselect */
- if (selectmode == SELECT_INVERT) {
- /* inverse selection status of this AnimData block only */
- ale->adt->flag ^= ADT_UI_SELECTED;
- }
- else {
- /* select AnimData block by itself */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
- ale->adt->flag |= ADT_UI_SELECTED;
- }
-
- /* set active? */
- if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED))
- ale->adt->flag |= ADT_UI_ACTIVE;
- }
-
- notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
- break;
- }
- case ANIMTYPE_GROUP:
- {
- bActionGroup *agrp = (bActionGroup *)ale->data;
-
- Object *ob = NULL;
- bPoseChannel *pchan = NULL;
-
-
- /* Armatures-Specific Feature:
- * Since groups are used to collect F-Curves of the same Bone by default
- * (via Keying Sets) so that they can be managed better, we try to make
- * things here easier for animators by mapping group selection to bone
- * selection.
- *
- * Only do this if "Only Selected" dopesheet filter is not active, or else it
- * becomes too unpredictable/tricky to manage
- */
- if ((ac->ads->filterflag & ADS_FILTER_ONLYSEL) == 0) {
- if ((ale->id) && (GS(ale->id->name) == ID_OB)) {
- ob = (Object *)ale->id;
-
- if (ob->type == OB_ARMATURE) {
- /* Assume for now that any group with corresponding name is what we want
- * (i.e. for an armature whose location is animated, things would break
- * if the user were to add a bone named "Location").
- *
- * TODO: check the first F-Curve or so to be sure...
- */
- pchan = BKE_pose_channel_find_name(ob->pose, agrp->name);
- }
- }
- }
-
- /* select/deselect group */
- if (selectmode == SELECT_INVERT) {
- /* inverse selection status of this group only */
- agrp->flag ^= AGRP_SELECTED;
- }
- else if (selectmode == -1) {
- /* select all in group (and deselect everything else) */
- FCurve *fcu;
-
- /* deselect all other channels */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
- if (pchan) ED_pose_deselect_all(ob, SEL_DESELECT, false);
-
- /* only select channels in group and group itself */
- for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next)
- fcu->flag |= FCURVE_SELECTED;
- agrp->flag |= AGRP_SELECTED;
- }
- else {
- /* select group by itself */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
- if (pchan) ED_pose_deselect_all(ob, SEL_DESELECT, false);
-
- agrp->flag |= AGRP_SELECTED;
- }
-
- /* if group is selected now, make group the 'active' one in the visible list */
- if (agrp->flag & AGRP_SELECTED) {
- ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
- if (pchan) ED_pose_bone_select(ob, pchan, true);
- }
- else {
- ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, NULL, ANIMTYPE_GROUP);
- if (pchan) ED_pose_bone_select(ob, pchan, false);
- }
-
- notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
- break;
- }
- case ANIMTYPE_FCURVE:
- case ANIMTYPE_NLACURVE:
- {
- FCurve *fcu = (FCurve *)ale->data;
-
- /* select/deselect */
- if (selectmode == SELECT_INVERT) {
- /* inverse selection status of this F-Curve only */
- fcu->flag ^= FCURVE_SELECTED;
- }
- else {
- /* select F-Curve by itself */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
- fcu->flag |= FCURVE_SELECTED;
- }
-
- /* if F-Curve is selected now, make F-Curve the 'active' one in the visible list */
- if (fcu->flag & FCURVE_SELECTED)
- ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type);
-
- notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
- break;
- }
- case ANIMTYPE_SHAPEKEY:
- {
- KeyBlock *kb = (KeyBlock *)ale->data;
-
- /* select/deselect */
- if (selectmode == SELECT_INVERT) {
- /* inverse selection status of this ShapeKey only */
- kb->flag ^= KEYBLOCK_SEL;
- }
- else {
- /* select ShapeKey by itself */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
- kb->flag |= KEYBLOCK_SEL;
- }
-
- notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
- break;
- }
- case ANIMTYPE_NLACONTROLS:
- {
- AnimData *adt = (AnimData *)ale->data;
-
- /* toggle expand
- * - Although the triangle widget already allows this, since there's nothing else that can be done here now,
- * let's just use it for easier expand/collapse for now
- */
- adt->flag ^= ADT_NLA_SKEYS_COLLAPSED;
-
- notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
- break;
- }
- case ANIMTYPE_GPDATABLOCK:
- {
- bGPdata *gpd = (bGPdata *)ale->data;
-
- /* toggle expand
- * - although the triangle widget already allows this, the whole channel can also be used for this purpose
- */
- gpd->flag ^= GP_DATA_EXPAND;
-
- notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
- break;
- }
- case ANIMTYPE_GPLAYER:
- {
- bGPdata *gpd = (bGPdata *)ale->id;
- bGPDlayer *gpl = (bGPDlayer *)ale->data;
-
- /* select/deselect */
- if (selectmode == SELECT_INVERT) {
- /* invert selection status of this layer only */
- gpl->flag ^= GP_LAYER_SELECT;
- }
- else {
- /* select layer by itself */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
- gpl->flag |= GP_LAYER_SELECT;
- }
-
- /* change active layer, if this is selected (since we must always have an active layer) */
- 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);
- }
-
- /* Grease Pencil updates */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
- notifierFlags |= (ND_ANIMCHAN | NA_EDITED); /* Animation Editors updates */
- break;
- }
- case ANIMTYPE_MASKDATABLOCK:
- {
- Mask *mask = (Mask *)ale->data;
-
- /* toggle expand
- * - although the triangle widget already allows this, the whole channel can also be used for this purpose
- */
- mask->flag ^= MASK_ANIMF_EXPAND;
-
- notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
- break;
- }
- case ANIMTYPE_MASKLAYER:
- {
- MaskLayer *masklay = (MaskLayer *)ale->data;
-
- /* select/deselect */
- if (selectmode == SELECT_INVERT) {
- /* invert selection status of this layer only */
- masklay->flag ^= MASK_LAYERFLAG_SELECT;
- }
- else {
- /* select layer by itself */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
- masklay->flag |= MASK_LAYERFLAG_SELECT;
- }
-
- notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
- break;
- }
- default:
- if (G.debug & G_DEBUG)
- printf("Error: Invalid channel type in mouse_anim_channels()\n");
- break;
- }
-
- /* free channels */
- ANIM_animdata_freelist(&anim_data);
-
- /* return notifier flags */
- return notifierFlags;
+ ViewLayer *view_layer = ac->view_layer;
+ Base *base = (Base *)ale->data;
+ Object *ob = base->object;
+ AnimData *adt = ob->adt;
+
+ /* set selection status */
+ if (base->flag & BASE_SELECTABLE) {
+ if (selectmode == SELECT_INVERT) {
+ /* swap select */
+ ED_object_base_select(base, BA_INVERT);
+ BKE_scene_object_base_flag_sync_from_base(base);
+
+ if (adt)
+ adt->flag ^= ADT_UI_SELECTED;
+ }
+ else {
+ Base *b;
+
+ /* deselect all */
+ /* TODO: should this deselect all other types of channels too? */
+ for (b = view_layer->object_bases.first; b; b = b->next) {
+ ED_object_base_select(b, BA_DESELECT);
+ BKE_scene_object_base_flag_sync_from_base(b);
+ if (b->object->adt)
+ b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE);
+ }
+
+ /* select object now */
+ ED_object_base_select(base, BA_SELECT);
+ BKE_scene_object_base_flag_sync_from_base(base);
+ if (adt)
+ adt->flag |= ADT_UI_SELECTED;
+ }
+
+ /* change active object - regardless of whether it is now selected [T37883] */
+ ED_object_base_activate(C, base); /* adds notifier */
+
+ if ((adt) && (adt->flag & ADT_UI_SELECTED))
+ adt->flag |= ADT_UI_ACTIVE;
+
+ /* ensure we exit editmode on whatever object was active before to avoid getting stuck there - T48747 */
+ if (ob != CTX_data_edit_object(C)) {
+ ED_object_editmode_exit(C, EM_FREEDATA);
+ }
+
+ notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
+ }
+ break;
+ }
+ case ANIMTYPE_FILLACTD: /* Action Expander */
+ case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
+ case ANIMTYPE_DSLAM:
+ case ANIMTYPE_DSCAM:
+ case ANIMTYPE_DSCACHEFILE:
+ case ANIMTYPE_DSCUR:
+ case ANIMTYPE_DSSKEY:
+ case ANIMTYPE_DSWOR:
+ case ANIMTYPE_DSPART:
+ case ANIMTYPE_DSMBALL:
+ case ANIMTYPE_DSARM:
+ case ANIMTYPE_DSMESH:
+ case ANIMTYPE_DSNTREE:
+ case ANIMTYPE_DSTEX:
+ case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
+ case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSGPENCIL:
+ case ANIMTYPE_DSMCLIP: {
+ /* sanity checking... */
+ if (ale->adt) {
+ /* select/deselect */
+ if (selectmode == SELECT_INVERT) {
+ /* inverse selection status of this AnimData block only */
+ ale->adt->flag ^= ADT_UI_SELECTED;
+ }
+ else {
+ /* select AnimData block by itself */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
+ ale->adt->flag |= ADT_UI_SELECTED;
+ }
+
+ /* set active? */
+ if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED))
+ ale->adt->flag |= ADT_UI_ACTIVE;
+ }
+
+ notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
+ break;
+ }
+ case ANIMTYPE_GROUP: {
+ bActionGroup *agrp = (bActionGroup *)ale->data;
+
+ Object *ob = NULL;
+ bPoseChannel *pchan = NULL;
+
+ /* Armatures-Specific Feature:
+ * Since groups are used to collect F-Curves of the same Bone by default
+ * (via Keying Sets) so that they can be managed better, we try to make
+ * things here easier for animators by mapping group selection to bone
+ * selection.
+ *
+ * Only do this if "Only Selected" dopesheet filter is not active, or else it
+ * becomes too unpredictable/tricky to manage
+ */
+ if ((ac->ads->filterflag & ADS_FILTER_ONLYSEL) == 0) {
+ if ((ale->id) && (GS(ale->id->name) == ID_OB)) {
+ ob = (Object *)ale->id;
+
+ if (ob->type == OB_ARMATURE) {
+ /* Assume for now that any group with corresponding name is what we want
+ * (i.e. for an armature whose location is animated, things would break
+ * if the user were to add a bone named "Location").
+ *
+ * TODO: check the first F-Curve or so to be sure...
+ */
+ pchan = BKE_pose_channel_find_name(ob->pose, agrp->name);
+ }
+ }
+ }
+
+ /* select/deselect group */
+ if (selectmode == SELECT_INVERT) {
+ /* inverse selection status of this group only */
+ agrp->flag ^= AGRP_SELECTED;
+ }
+ else if (selectmode == -1) {
+ /* select all in group (and deselect everything else) */
+ FCurve *fcu;
+
+ /* deselect all other channels */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
+ if (pchan)
+ ED_pose_deselect_all(ob, SEL_DESELECT, false);
+
+ /* only select channels in group and group itself */
+ for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next)
+ fcu->flag |= FCURVE_SELECTED;
+ agrp->flag |= AGRP_SELECTED;
+ }
+ else {
+ /* select group by itself */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
+ if (pchan)
+ ED_pose_deselect_all(ob, SEL_DESELECT, false);
+
+ agrp->flag |= AGRP_SELECTED;
+ }
+
+ /* if group is selected now, make group the 'active' one in the visible list */
+ if (agrp->flag & AGRP_SELECTED) {
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
+ if (pchan)
+ ED_pose_bone_select(ob, pchan, true);
+ }
+ else {
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, NULL, ANIMTYPE_GROUP);
+ if (pchan)
+ ED_pose_bone_select(ob, pchan, false);
+ }
+
+ notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
+ break;
+ }
+ case ANIMTYPE_FCURVE:
+ case ANIMTYPE_NLACURVE: {
+ FCurve *fcu = (FCurve *)ale->data;
+
+ /* select/deselect */
+ if (selectmode == SELECT_INVERT) {
+ /* inverse selection status of this F-Curve only */
+ fcu->flag ^= FCURVE_SELECTED;
+ }
+ else {
+ /* select F-Curve by itself */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
+ fcu->flag |= FCURVE_SELECTED;
+ }
+
+ /* if F-Curve is selected now, make F-Curve the 'active' one in the visible list */
+ if (fcu->flag & FCURVE_SELECTED)
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type);
+
+ notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
+ break;
+ }
+ case ANIMTYPE_SHAPEKEY: {
+ KeyBlock *kb = (KeyBlock *)ale->data;
+
+ /* select/deselect */
+ if (selectmode == SELECT_INVERT) {
+ /* inverse selection status of this ShapeKey only */
+ kb->flag ^= KEYBLOCK_SEL;
+ }
+ else {
+ /* select ShapeKey by itself */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
+ kb->flag |= KEYBLOCK_SEL;
+ }
+
+ notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
+ break;
+ }
+ case ANIMTYPE_NLACONTROLS: {
+ AnimData *adt = (AnimData *)ale->data;
+
+ /* toggle expand
+ * - Although the triangle widget already allows this, since there's nothing else that can be done here now,
+ * let's just use it for easier expand/collapse for now
+ */
+ adt->flag ^= ADT_NLA_SKEYS_COLLAPSED;
+
+ notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
+ break;
+ }
+ case ANIMTYPE_GPDATABLOCK: {
+ bGPdata *gpd = (bGPdata *)ale->data;
+
+ /* toggle expand
+ * - although the triangle widget already allows this, the whole channel can also be used for this purpose
+ */
+ gpd->flag ^= GP_DATA_EXPAND;
+
+ notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
+ break;
+ }
+ case ANIMTYPE_GPLAYER: {
+ bGPdata *gpd = (bGPdata *)ale->id;
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+
+ /* select/deselect */
+ if (selectmode == SELECT_INVERT) {
+ /* invert selection status of this layer only */
+ gpl->flag ^= GP_LAYER_SELECT;
+ }
+ else {
+ /* select layer by itself */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
+ gpl->flag |= GP_LAYER_SELECT;
+ }
+
+ /* change active layer, if this is selected (since we must always have an active layer) */
+ 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);
+ }
+
+ /* Grease Pencil updates */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
+ notifierFlags |= (ND_ANIMCHAN | NA_EDITED); /* Animation Editors updates */
+ break;
+ }
+ case ANIMTYPE_MASKDATABLOCK: {
+ Mask *mask = (Mask *)ale->data;
+
+ /* toggle expand
+ * - although the triangle widget already allows this, the whole channel can also be used for this purpose
+ */
+ mask->flag ^= MASK_ANIMF_EXPAND;
+
+ notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
+ break;
+ }
+ case ANIMTYPE_MASKLAYER: {
+ MaskLayer *masklay = (MaskLayer *)ale->data;
+
+ /* select/deselect */
+ if (selectmode == SELECT_INVERT) {
+ /* invert selection status of this layer only */
+ masklay->flag ^= MASK_LAYERFLAG_SELECT;
+ }
+ else {
+ /* select layer by itself */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
+ masklay->flag |= MASK_LAYERFLAG_SELECT;
+ }
+
+ notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
+ break;
+ }
+ default:
+ if (G.debug & G_DEBUG)
+ printf("Error: Invalid channel type in mouse_anim_channels()\n");
+ break;
+ }
+
+ /* free channels */
+ ANIM_animdata_freelist(&anim_data);
+
+ /* return notifier flags */
+ return notifierFlags;
}
/* ------------------- */
@@ -3018,177 +3051,188 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
/* handle clicking */
static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bAnimContext ac;
- ARegion *ar;
- View2D *v2d;
- int channel_index;
- int notifierFlags = 0;
- short selectmode;
- float x, y;
-
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get useful pointers from animation context data */
- ar = ac.ar;
- v2d = &ar->v2d;
-
- /* select mode is either replace (deselect all, then add) or add/extend */
- if (RNA_boolean_get(op->ptr, "extend")) {
- selectmode = SELECT_INVERT;
- }
- else if (RNA_boolean_get(op->ptr, "children_only")) {
- /* this is a bit of a special case for ActionGroups only...
- * should it be removed or extended to all instead? */
- selectmode = -1;
- }
- else {
- selectmode = SELECT_REPLACE;
- }
-
- /* figure out which channel user clicked in
- *
- * Note:
- * although channels technically start at (y = ACHANNEL_FIRST),
- * we need to adjust by half a channel's height so that the tops of channels get caught ok.
- * Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use ACHANNEL_HEIGHT_HALF.
- */
- UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y);
- UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP(&ac), 0, (float)ACHANNEL_HEIGHT_HALF(&ac), x, y, NULL, &channel_index);
-
- /* handle mouse-click in the relevant channel then */
- notifierFlags = mouse_anim_channels(C, &ac, channel_index, selectmode);
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | notifierFlags, NULL);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ ARegion *ar;
+ View2D *v2d;
+ int channel_index;
+ int notifierFlags = 0;
+ short selectmode;
+ float x, y;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get useful pointers from animation context data */
+ ar = ac.ar;
+ v2d = &ar->v2d;
+
+ /* select mode is either replace (deselect all, then add) or add/extend */
+ if (RNA_boolean_get(op->ptr, "extend")) {
+ selectmode = SELECT_INVERT;
+ }
+ else if (RNA_boolean_get(op->ptr, "children_only")) {
+ /* this is a bit of a special case for ActionGroups only...
+ * should it be removed or extended to all instead? */
+ selectmode = -1;
+ }
+ else {
+ selectmode = SELECT_REPLACE;
+ }
+
+ /* figure out which channel user clicked in
+ *
+ * Note:
+ * although channels technically start at (y = ACHANNEL_FIRST),
+ * we need to adjust by half a channel's height so that the tops of channels get caught ok.
+ * Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use ACHANNEL_HEIGHT_HALF.
+ */
+ UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y);
+ UI_view2d_listview_view_to_cell(v2d,
+ ACHANNEL_NAMEWIDTH,
+ ACHANNEL_STEP(&ac),
+ 0,
+ (float)ACHANNEL_HEIGHT_HALF(&ac),
+ x,
+ y,
+ NULL,
+ &channel_index);
+
+ /* handle mouse-click in the relevant channel then */
+ notifierFlags = mouse_anim_channels(C, &ac, channel_index, selectmode);
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | notifierFlags, NULL);
+
+ return OPERATOR_FINISHED;
}
static void ANIM_OT_channels_click(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Mouse Click on Channels";
- ot->idname = "ANIM_OT_channels_click";
- ot->description = "Handle mouse-clicks over animation channels";
+ /* identifiers */
+ ot->name = "Mouse Click on Channels";
+ ot->idname = "ANIM_OT_channels_click";
+ ot->description = "Handle mouse-clicks over animation channels";
- /* api callbacks */
- ot->invoke = animchannels_mouseclick_invoke;
- ot->poll = animedit_poll_channels_active;
+ /* api callbacks */
+ ot->invoke = animchannels_mouseclick_invoke;
+ ot->poll = animedit_poll_channels_active;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- /* properties */
- /* NOTE: don't save settings, otherwise, can end up with some weird behavior (sticky extend) */
- prop = RNA_def_boolean(ot->srna, "extend", false, "Extend Select", ""); // SHIFTKEY
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ /* NOTE: don't save settings, otherwise, can end up with some weird behavior (sticky extend) */
+ prop = RNA_def_boolean(ot->srna, "extend", false, "Extend Select", ""); // SHIFTKEY
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "children_only", false, "Select Children Only", ""); // CTRLKEY|SHIFTKEY
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(
+ ot->srna, "children_only", false, "Select Children Only", ""); // CTRLKEY|SHIFTKEY
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static bool select_anim_channel_keys(bAnimContext *ac, int channel_index, bool extend)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- bool success = false;
- FCurve *fcu;
- int i;
-
- /* get the channel that was clicked on */
- /* filter channels */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* get channel from index */
- ale = BLI_findlink(&anim_data, channel_index);
- if (ale == NULL) {
- /* channel not found */
- if (G.debug & G_DEBUG)
- printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n", channel_index);
-
- ANIM_animdata_freelist(&anim_data);
- return false;
- }
-
- fcu = (FCurve *)ale->key_data;
- success = (fcu != NULL);
-
- ANIM_animdata_freelist(&anim_data);
-
- /* F-Curve may not have any keyframes */
- if (fcu && fcu->bezt) {
- BezTriple *bezt;
-
- if (!extend) {
- filter = (ANIMFILTER_DATA_VISIBLE);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu_inner = (FCurve *)ale->key_data;
-
- if (fcu_inner != NULL && fcu_inner->bezt != NULL) {
- for (i = 0, bezt = fcu_inner->bezt; i < fcu_inner->totvert; i++, bezt++) {
- bezt->f2 = bezt->f1 = bezt->f3 = 0;
- }
- }
- }
-
- ANIM_animdata_freelist(&anim_data);
- }
-
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- bezt->f2 = bezt->f1 = bezt->f3 = SELECT;
- }
- }
-
- /* free temp data and tag for refresh */
- ED_region_tag_redraw(ac->ar);
- return success;
-}
-
-static int animchannels_channel_select_keys_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- bAnimContext ac;
- int channel_index;
- bool extend = RNA_boolean_get(op->ptr, "extend");
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- channel_index = animchannels_channel_get(&ac, event->mval);
-
- /* handle click */
- if (select_anim_channel_keys(&ac, channel_index, extend)) {
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
- }
- else
- /* allow event to be handled by selectall operator */
- return OPERATOR_PASS_THROUGH;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ bool success = false;
+ FCurve *fcu;
+ int i;
+
+ /* get the channel that was clicked on */
+ /* filter channels */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* get channel from index */
+ ale = BLI_findlink(&anim_data, channel_index);
+ if (ale == NULL) {
+ /* channel not found */
+ if (G.debug & G_DEBUG)
+ printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n",
+ channel_index);
+
+ ANIM_animdata_freelist(&anim_data);
+ return false;
+ }
+
+ fcu = (FCurve *)ale->key_data;
+ success = (fcu != NULL);
+
+ ANIM_animdata_freelist(&anim_data);
+
+ /* F-Curve may not have any keyframes */
+ if (fcu && fcu->bezt) {
+ BezTriple *bezt;
+
+ if (!extend) {
+ filter = (ANIMFILTER_DATA_VISIBLE);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu_inner = (FCurve *)ale->key_data;
+
+ if (fcu_inner != NULL && fcu_inner->bezt != NULL) {
+ for (i = 0, bezt = fcu_inner->bezt; i < fcu_inner->totvert; i++, bezt++) {
+ bezt->f2 = bezt->f1 = bezt->f3 = 0;
+ }
+ }
+ }
+
+ ANIM_animdata_freelist(&anim_data);
+ }
+
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ bezt->f2 = bezt->f1 = bezt->f3 = SELECT;
+ }
+ }
+
+ /* free temp data and tag for refresh */
+ ED_region_tag_redraw(ac->ar);
+ return success;
+}
+
+static int animchannels_channel_select_keys_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *event)
+{
+ bAnimContext ac;
+ int channel_index;
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ channel_index = animchannels_channel_get(&ac, event->mval);
+
+ /* handle click */
+ if (select_anim_channel_keys(&ac, channel_index, extend)) {
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ return OPERATOR_FINISHED;
+ }
+ else
+ /* allow event to be handled by selectall operator */
+ return OPERATOR_PASS_THROUGH;
}
static void ANIM_OT_channel_select_keys(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Select Channel keyframes";
- ot->idname = "ANIM_OT_channel_select_keys";
- ot->description = "Select all keyframes of channel under mouse";
+ /* identifiers */
+ ot->name = "Select Channel keyframes";
+ ot->idname = "ANIM_OT_channel_select_keys";
+ ot->description = "Select all keyframes of channel under mouse";
- /* api callbacks */
- ot->invoke = animchannels_channel_select_keys_invoke;
- ot->poll = animedit_poll_channels_active;
+ /* api callbacks */
+ ot->invoke = animchannels_channel_select_keys_invoke;
+ ot->poll = animedit_poll_channels_active;
- prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ************************************************************************** */
@@ -3196,41 +3240,41 @@ static void ANIM_OT_channel_select_keys(wmOperatorType *ot)
void ED_operatortypes_animchannels(void)
{
- WM_operatortype_append(ANIM_OT_channels_select_all);
- WM_operatortype_append(ANIM_OT_channels_select_box);
+ WM_operatortype_append(ANIM_OT_channels_select_all);
+ WM_operatortype_append(ANIM_OT_channels_select_box);
- WM_operatortype_append(ANIM_OT_channels_click);
- WM_operatortype_append(ANIM_OT_channel_select_keys);
- WM_operatortype_append(ANIM_OT_channels_rename);
+ WM_operatortype_append(ANIM_OT_channels_click);
+ WM_operatortype_append(ANIM_OT_channel_select_keys);
+ WM_operatortype_append(ANIM_OT_channels_rename);
- WM_operatortype_append(ANIM_OT_channels_find);
+ WM_operatortype_append(ANIM_OT_channels_find);
- WM_operatortype_append(ANIM_OT_channels_setting_enable);
- WM_operatortype_append(ANIM_OT_channels_setting_disable);
- WM_operatortype_append(ANIM_OT_channels_setting_toggle);
+ WM_operatortype_append(ANIM_OT_channels_setting_enable);
+ WM_operatortype_append(ANIM_OT_channels_setting_disable);
+ WM_operatortype_append(ANIM_OT_channels_setting_toggle);
- WM_operatortype_append(ANIM_OT_channels_delete);
+ WM_operatortype_append(ANIM_OT_channels_delete);
- /* XXX does this need to be a separate operator? */
- WM_operatortype_append(ANIM_OT_channels_editable_toggle);
+ /* XXX does this need to be a separate operator? */
+ WM_operatortype_append(ANIM_OT_channels_editable_toggle);
- WM_operatortype_append(ANIM_OT_channels_move);
+ WM_operatortype_append(ANIM_OT_channels_move);
- WM_operatortype_append(ANIM_OT_channels_expand);
- WM_operatortype_append(ANIM_OT_channels_collapse);
+ WM_operatortype_append(ANIM_OT_channels_expand);
+ WM_operatortype_append(ANIM_OT_channels_collapse);
- WM_operatortype_append(ANIM_OT_channels_fcurves_enable);
+ WM_operatortype_append(ANIM_OT_channels_fcurves_enable);
- WM_operatortype_append(ANIM_OT_channels_clean_empty);
+ WM_operatortype_append(ANIM_OT_channels_clean_empty);
- WM_operatortype_append(ANIM_OT_channels_group);
- WM_operatortype_append(ANIM_OT_channels_ungroup);
+ WM_operatortype_append(ANIM_OT_channels_group);
+ WM_operatortype_append(ANIM_OT_channels_ungroup);
}
// TODO: check on a poll callback for this, to get hotkeys into menus
void ED_keymap_animchannels(wmKeyConfig *keyconf)
{
- WM_keymap_ensure(keyconf, "Animation Channels", 0, 0);
+ WM_keymap_ensure(keyconf, "Animation Channels", 0, 0);
}
/* ************************************************************************** */
diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c
index dfb1a456364..53fec2e1ef7 100644
--- a/source/blender/editors/animation/anim_deps.c
+++ b/source/blender/editors/animation/anim_deps.c
@@ -21,7 +21,6 @@
* \ingroup edanimation
*/
-
#include <string.h>
#include "MEM_guardedalloc.h"
@@ -59,58 +58,68 @@
*/
void ANIM_list_elem_update(Main *bmain, Scene *scene, bAnimListElem *ale)
{
- ID *id;
- FCurve *fcu;
- AnimData *adt;
-
- id = ale->id;
- if (!id)
- return;
-
- /* tag AnimData for refresh so that other views will update in realtime with these changes */
- adt = BKE_animdata_from_id(id);
- if (adt) {
- DEG_id_tag_update(id, ID_RECALC_ANIMATION);
- if (adt->action != NULL) {
- DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION);
- }
- }
-
- /* Tag copy on the main object if updating anything directly inside AnimData */
- if (ELEM(ale->type, ANIMTYPE_ANIMDATA, ANIMTYPE_NLAACTION, ANIMTYPE_NLATRACK, ANIMTYPE_NLACURVE)) {
- DEG_id_tag_update(id, ID_RECALC_ANIMATION);
- return;
- }
-
- /* update data */
- fcu = (ale->datatype == ALE_FCURVE) ? ale->key_data : NULL;
-
- if (fcu && fcu->rna_path) {
- /* if we have an fcurve, call the update for the property we
- * are editing, this is then expected to do the proper redraws
- * and depsgraph updates */
- PointerRNA id_ptr, ptr;
- PropertyRNA *prop;
-
- RNA_id_pointer_create(id, &id_ptr);
-
- if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop))
- RNA_property_update_main(bmain, scene, &ptr, prop);
- }
- else {
- /* in other case we do standard depsgraph update, ideally
- * we'd be calling property update functions here too ... */
- DEG_id_tag_update(id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); // XXX or do we want something more restrictive?
- }
+ ID *id;
+ FCurve *fcu;
+ AnimData *adt;
+
+ id = ale->id;
+ if (!id)
+ return;
+
+ /* tag AnimData for refresh so that other views will update in realtime with these changes */
+ adt = BKE_animdata_from_id(id);
+ if (adt) {
+ DEG_id_tag_update(id, ID_RECALC_ANIMATION);
+ if (adt->action != NULL) {
+ DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION);
+ }
+ }
+
+ /* Tag copy on the main object if updating anything directly inside AnimData */
+ if (ELEM(ale->type,
+ ANIMTYPE_ANIMDATA,
+ ANIMTYPE_NLAACTION,
+ ANIMTYPE_NLATRACK,
+ ANIMTYPE_NLACURVE)) {
+ DEG_id_tag_update(id, ID_RECALC_ANIMATION);
+ return;
+ }
+
+ /* update data */
+ fcu = (ale->datatype == ALE_FCURVE) ? ale->key_data : NULL;
+
+ if (fcu && fcu->rna_path) {
+ /* if we have an fcurve, call the update for the property we
+ * are editing, this is then expected to do the proper redraws
+ * and depsgraph updates */
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+
+ RNA_id_pointer_create(id, &id_ptr);
+
+ if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop))
+ RNA_property_update_main(bmain, scene, &ptr, prop);
+ }
+ else {
+ /* in other case we do standard depsgraph update, ideally
+ * we'd be calling property update functions here too ... */
+ DEG_id_tag_update(id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY |
+ ID_RECALC_ANIMATION); // XXX or do we want something more restrictive?
+ }
}
/* tags the given ID block for refreshes (if applicable) due to
* Animation Editor editing */
void ANIM_id_update(Main *bmain, ID *id)
{
- if (id) {
- DEG_id_tag_update_ex(bmain, id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); // XXX or do we want something more restrictive?
- }
+ if (id) {
+ DEG_id_tag_update_ex(
+ bmain,
+ id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY |
+ ID_RECALC_ANIMATION); // XXX or do we want something more restrictive?
+ }
}
/* **************************** animation data <-> data syncing ******************************** */
@@ -126,161 +135,165 @@ void ANIM_id_update(Main *bmain, ID *id)
/* perform syncing updates for Action Groups */
static void animchan_sync_group(bAnimContext *ac, bAnimListElem *ale, bActionGroup **active_agrp)
{
- bActionGroup *agrp = (bActionGroup *)ale->data;
- ID *owner_id = ale->id;
-
- /* major priority is selection status
- * so we need both a group and an owner
- */
- if (ELEM(NULL, agrp, owner_id))
- return;
-
- /* for standard Objects, check if group is the name of some bone */
- if (GS(owner_id->name) == ID_OB) {
- Object *ob = (Object *)owner_id;
-
- /* check if there are bones, and whether the name matches any
- * NOTE: this feature will only really work if groups by default contain the F-Curves for a single bone
- */
- if (ob->pose) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, agrp->name);
- bArmature *arm = ob->data;
-
- if (pchan) {
- bActionGroup *bgrp;
-
- /* if one matches, sync the selection status */
- if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))
- agrp->flag |= AGRP_SELECTED;
- else
- agrp->flag &= ~AGRP_SELECTED;
-
- /* also sync active group status */
- if ((ob == ac->obact) && (pchan->bone == arm->act_bone)) {
- /* if no previous F-Curve has active flag, then we're the first and only one to get it */
- if (*active_agrp == NULL) {
- agrp->flag |= AGRP_ACTIVE;
- *active_agrp = agrp;
- }
- else {
- /* someone else has already taken it - set as not active */
- agrp->flag &= ~AGRP_ACTIVE;
- }
- }
- else {
- /* this can't possibly be active now */
- agrp->flag &= ~AGRP_ACTIVE;
- }
-
- /* sync group colors */
- bgrp = (bActionGroup *)BLI_findlink(&ob->pose->agroups, (pchan->agrp_index - 1));
- if (bgrp) {
- agrp->customCol = bgrp->customCol;
- action_group_colors_sync(agrp, bgrp);
- }
- }
- }
- }
+ bActionGroup *agrp = (bActionGroup *)ale->data;
+ ID *owner_id = ale->id;
+
+ /* major priority is selection status
+ * so we need both a group and an owner
+ */
+ if (ELEM(NULL, agrp, owner_id))
+ return;
+
+ /* for standard Objects, check if group is the name of some bone */
+ if (GS(owner_id->name) == ID_OB) {
+ Object *ob = (Object *)owner_id;
+
+ /* check if there are bones, and whether the name matches any
+ * NOTE: this feature will only really work if groups by default contain the F-Curves for a single bone
+ */
+ if (ob->pose) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, agrp->name);
+ bArmature *arm = ob->data;
+
+ if (pchan) {
+ bActionGroup *bgrp;
+
+ /* if one matches, sync the selection status */
+ if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))
+ agrp->flag |= AGRP_SELECTED;
+ else
+ agrp->flag &= ~AGRP_SELECTED;
+
+ /* also sync active group status */
+ if ((ob == ac->obact) && (pchan->bone == arm->act_bone)) {
+ /* if no previous F-Curve has active flag, then we're the first and only one to get it */
+ if (*active_agrp == NULL) {
+ agrp->flag |= AGRP_ACTIVE;
+ *active_agrp = agrp;
+ }
+ else {
+ /* someone else has already taken it - set as not active */
+ agrp->flag &= ~AGRP_ACTIVE;
+ }
+ }
+ else {
+ /* this can't possibly be active now */
+ agrp->flag &= ~AGRP_ACTIVE;
+ }
+
+ /* sync group colors */
+ bgrp = (bActionGroup *)BLI_findlink(&ob->pose->agroups, (pchan->agrp_index - 1));
+ if (bgrp) {
+ agrp->customCol = bgrp->customCol;
+ action_group_colors_sync(agrp, bgrp);
+ }
+ }
+ }
+ }
}
/* perform syncing updates for F-Curves */
-static void animchan_sync_fcurve(bAnimContext *UNUSED(ac), bAnimListElem *ale, FCurve **active_fcurve)
+static void animchan_sync_fcurve(bAnimContext *UNUSED(ac),
+ bAnimListElem *ale,
+ FCurve **active_fcurve)
{
- FCurve *fcu = (FCurve *)ale->data;
- ID *owner_id = ale->id;
-
- /* major priority is selection status, so refer to the checks done in anim_filter.c
- * skip_fcurve_selected_data() for reference about what's going on here...
- */
- if (ELEM(NULL, fcu, fcu->rna_path, owner_id))
- return;
-
- if (GS(owner_id->name) == ID_SCE) {
- Scene *scene = (Scene *)owner_id;
-
- /* only affect if F-Curve involves sequence_editor.sequences */
- if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) {
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq;
- char *seq_name;
-
- /* get strip name, and check if this strip is selected */
- seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all[");
- seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, false);
- if (seq_name) MEM_freeN(seq_name);
-
- /* update selection status */
- if (seq) {
- if (seq->flag & SELECT)
- fcu->flag |= FCURVE_SELECTED;
- else
- fcu->flag &= ~FCURVE_SELECTED;
- }
- }
- }
- else if (GS(owner_id->name) == ID_NT) {
- bNodeTree *ntree = (bNodeTree *)owner_id;
-
- /* check for selected nodes */
- if ((fcu->rna_path) && strstr(fcu->rna_path, "nodes")) {
- bNode *node;
- char *node_name;
-
- /* get strip name, and check if this strip is selected */
- node_name = BLI_str_quoted_substrN(fcu->rna_path, "nodes[");
- node = nodeFindNodebyName(ntree, node_name);
- if (node_name) MEM_freeN(node_name);
-
- /* update selection/active status */
- if (node) {
- /* update selection status */
- if (node->flag & NODE_SELECT)
- fcu->flag |= FCURVE_SELECTED;
- else
- fcu->flag &= ~FCURVE_SELECTED;
-
- /* update active status */
- /* XXX: this may interfere with setting bones as active if both exist at once;
- * then again, if that's the case, production setups aren't likely to be animating
- * nodes while working with bones?
- */
- if (node->flag & NODE_ACTIVE) {
- if (*active_fcurve == NULL) {
- fcu->flag |= FCURVE_ACTIVE;
- *active_fcurve = fcu;
- }
- else {
- fcu->flag &= ~FCURVE_ACTIVE;
- }
- }
- else {
- fcu->flag &= ~FCURVE_ACTIVE;
- }
- }
- }
- }
+ FCurve *fcu = (FCurve *)ale->data;
+ ID *owner_id = ale->id;
+
+ /* major priority is selection status, so refer to the checks done in anim_filter.c
+ * skip_fcurve_selected_data() for reference about what's going on here...
+ */
+ if (ELEM(NULL, fcu, fcu->rna_path, owner_id))
+ return;
+
+ if (GS(owner_id->name) == ID_SCE) {
+ Scene *scene = (Scene *)owner_id;
+
+ /* only affect if F-Curve involves sequence_editor.sequences */
+ if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) {
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+ char *seq_name;
+
+ /* get strip name, and check if this strip is selected */
+ seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all[");
+ seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, false);
+ if (seq_name)
+ MEM_freeN(seq_name);
+
+ /* update selection status */
+ if (seq) {
+ if (seq->flag & SELECT)
+ fcu->flag |= FCURVE_SELECTED;
+ else
+ fcu->flag &= ~FCURVE_SELECTED;
+ }
+ }
+ }
+ else if (GS(owner_id->name) == ID_NT) {
+ bNodeTree *ntree = (bNodeTree *)owner_id;
+
+ /* check for selected nodes */
+ if ((fcu->rna_path) && strstr(fcu->rna_path, "nodes")) {
+ bNode *node;
+ char *node_name;
+
+ /* get strip name, and check if this strip is selected */
+ node_name = BLI_str_quoted_substrN(fcu->rna_path, "nodes[");
+ node = nodeFindNodebyName(ntree, node_name);
+ if (node_name)
+ MEM_freeN(node_name);
+
+ /* update selection/active status */
+ if (node) {
+ /* update selection status */
+ if (node->flag & NODE_SELECT)
+ fcu->flag |= FCURVE_SELECTED;
+ else
+ fcu->flag &= ~FCURVE_SELECTED;
+
+ /* update active status */
+ /* XXX: this may interfere with setting bones as active if both exist at once;
+ * then again, if that's the case, production setups aren't likely to be animating
+ * nodes while working with bones?
+ */
+ if (node->flag & NODE_ACTIVE) {
+ if (*active_fcurve == NULL) {
+ fcu->flag |= FCURVE_ACTIVE;
+ *active_fcurve = fcu;
+ }
+ else {
+ fcu->flag &= ~FCURVE_ACTIVE;
+ }
+ }
+ else {
+ fcu->flag &= ~FCURVE_ACTIVE;
+ }
+ }
+ }
+ }
}
/* perform syncing updates for GPencil Layers */
static void animchan_sync_gplayer(bAnimContext *UNUSED(ac), bAnimListElem *ale)
{
- bGPDlayer *gpl = (bGPDlayer *)ale->data;
-
- /* Make sure the selection flags agree with the "active" flag.
- * The selection flags are used in the Dopesheet only, whereas
- * the active flag is used everywhere else. Hence, we try to
- * sync these here so that it all seems to be have as the user
- * expects - T50184
- *
- * Assume that we only really do this when the active status changes.
- * (NOTE: This may prove annoying if it means selection is always lost)
- */
- if (gpl->flag & GP_LAYER_ACTIVE) {
- gpl->flag |= GP_LAYER_SELECT;
- }
- else {
- gpl->flag &= ~GP_LAYER_SELECT;
- }
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+
+ /* Make sure the selection flags agree with the "active" flag.
+ * The selection flags are used in the Dopesheet only, whereas
+ * the active flag is used everywhere else. Hence, we try to
+ * sync these here so that it all seems to be have as the user
+ * expects - T50184
+ *
+ * Assume that we only really do this when the active status changes.
+ * (NOTE: This may prove annoying if it means selection is always lost)
+ */
+ if (gpl->flag & GP_LAYER_ACTIVE) {
+ gpl->flag |= GP_LAYER_SELECT;
+ }
+ else {
+ gpl->flag &= ~GP_LAYER_SELECT;
+ }
}
/* ---------------- */
@@ -288,131 +301,135 @@ static void animchan_sync_gplayer(bAnimContext *UNUSED(ac), bAnimListElem *ale)
/* Main call to be exported to animation editors */
void ANIM_sync_animchannels_to_data(const bContext *C)
{
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- bActionGroup *active_agrp = NULL;
- FCurve *active_fcurve = NULL;
-
- /* get animation context info for filtering the channels */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return;
-
- /* filter data */
- /* NOTE: we want all channels, since we want to be able to set selection status on some of them even when collapsed
- * However, don't include duplicates so that selection statuses don't override each other
- */
- filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS;
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* flush settings as appropriate depending on the types of the channels */
- for (ale = anim_data.first; ale; ale = ale->next) {
- switch (ale->type) {
- case ANIMTYPE_GROUP:
- animchan_sync_group(&ac, ale, &active_agrp);
- break;
-
- case ANIMTYPE_FCURVE:
- animchan_sync_fcurve(&ac, ale, &active_fcurve);
- break;
-
- case ANIMTYPE_GPLAYER:
- animchan_sync_gplayer(&ac, ale);
- break;
- }
- }
-
- ANIM_animdata_freelist(&anim_data);
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ bActionGroup *active_agrp = NULL;
+ FCurve *active_fcurve = NULL;
+
+ /* get animation context info for filtering the channels */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return;
+
+ /* filter data */
+ /* NOTE: we want all channels, since we want to be able to set selection status on some of them even when collapsed
+ * However, don't include duplicates so that selection statuses don't override each other
+ */
+ filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS;
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* flush settings as appropriate depending on the types of the channels */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ switch (ale->type) {
+ case ANIMTYPE_GROUP:
+ animchan_sync_group(&ac, ale, &active_agrp);
+ break;
+
+ case ANIMTYPE_FCURVE:
+ animchan_sync_fcurve(&ac, ale, &active_fcurve);
+ break;
+
+ case ANIMTYPE_GPLAYER:
+ animchan_sync_gplayer(&ac, ale);
+ break;
+ }
+ }
+
+ ANIM_animdata_freelist(&anim_data);
}
void ANIM_animdata_update(bAnimContext *ac, ListBase *anim_data)
{
- bAnimListElem *ale;
+ bAnimListElem *ale;
- if (ELEM(ac->datatype, ANIMCONT_MASK)) {
+ if (ELEM(ac->datatype, ANIMCONT_MASK)) {
#ifdef DEBUG
- /* quiet assert */
- for (ale = anim_data->first; ale; ale = ale->next) {
- ale->update = 0;
- }
+ /* 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;
-
- if (ale->update & ANIM_UPDATE_ORDER) {
- ale->update &= ~ANIM_UPDATE_ORDER;
- if (gpl) {
- //gpencil_sort_frames(gpl);
- }
- }
-
- if (ale->update & ANIM_UPDATE_DEPS) {
- ale->update &= ~ANIM_UPDATE_DEPS;
- ANIM_list_elem_update(ac->bmain, ac->scene, ale);
- }
- /* disable handles to avoid crash */
- if (ale->update & ANIM_UPDATE_HANDLES) {
- ale->update &= ~ANIM_UPDATE_HANDLES;
- }
- }
- else if (ale->datatype == ALE_FCURVE) {
- FCurve *fcu = ale->key_data;
-
- if (ale->update & ANIM_UPDATE_ORDER) {
- ale->update &= ~ANIM_UPDATE_ORDER;
- if (fcu)
- sort_time_fcurve(fcu);
- }
-
- if (ale->update & ANIM_UPDATE_HANDLES) {
- ale->update &= ~ANIM_UPDATE_HANDLES;
- if (fcu)
- calchandles_fcurve(fcu);
- }
-
- if (ale->update & ANIM_UPDATE_DEPS) {
- ale->update &= ~ANIM_UPDATE_DEPS;
- ANIM_list_elem_update(ac->bmain, ac->scene, ale);
- }
- }
- else if (ELEM(ale->type, ANIMTYPE_ANIMDATA, ANIMTYPE_NLAACTION, ANIMTYPE_NLATRACK, ANIMTYPE_NLACURVE)) {
- if (ale->update & ANIM_UPDATE_DEPS) {
- ale->update &= ~ANIM_UPDATE_DEPS;
- ANIM_list_elem_update(ac->bmain, ac->scene, ale);
- }
- }
- else if (ale->update) {
+ return;
+ }
+
+ for (ale = anim_data->first; ale; ale = ale->next) {
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ bGPDlayer *gpl = ale->data;
+
+ if (ale->update & ANIM_UPDATE_ORDER) {
+ ale->update &= ~ANIM_UPDATE_ORDER;
+ if (gpl) {
+ //gpencil_sort_frames(gpl);
+ }
+ }
+
+ if (ale->update & ANIM_UPDATE_DEPS) {
+ ale->update &= ~ANIM_UPDATE_DEPS;
+ ANIM_list_elem_update(ac->bmain, ac->scene, ale);
+ }
+ /* disable handles to avoid crash */
+ if (ale->update & ANIM_UPDATE_HANDLES) {
+ ale->update &= ~ANIM_UPDATE_HANDLES;
+ }
+ }
+ else if (ale->datatype == ALE_FCURVE) {
+ FCurve *fcu = ale->key_data;
+
+ if (ale->update & ANIM_UPDATE_ORDER) {
+ ale->update &= ~ANIM_UPDATE_ORDER;
+ if (fcu)
+ sort_time_fcurve(fcu);
+ }
+
+ if (ale->update & ANIM_UPDATE_HANDLES) {
+ ale->update &= ~ANIM_UPDATE_HANDLES;
+ if (fcu)
+ calchandles_fcurve(fcu);
+ }
+
+ if (ale->update & ANIM_UPDATE_DEPS) {
+ ale->update &= ~ANIM_UPDATE_DEPS;
+ ANIM_list_elem_update(ac->bmain, ac->scene, ale);
+ }
+ }
+ else if (ELEM(ale->type,
+ ANIMTYPE_ANIMDATA,
+ ANIMTYPE_NLAACTION,
+ ANIMTYPE_NLATRACK,
+ ANIMTYPE_NLACURVE)) {
+ if (ale->update & ANIM_UPDATE_DEPS) {
+ ale->update &= ~ANIM_UPDATE_DEPS;
+ ANIM_list_elem_update(ac->bmain, ac->scene, ale);
+ }
+ }
+ else if (ale->update) {
#if 0
- if (G.debug & G_DEBUG) {
- printf("%s: Unhandled animchannel updates (%d) for type=%d (%p)\n",
- __func__, ale->update, ale->type, ale->data);
- }
+ if (G.debug & G_DEBUG) {
+ printf("%s: Unhandled animchannel updates (%d) for type=%d (%p)\n",
+ __func__, ale->update, ale->type, ale->data);
+ }
#endif
- /* Prevent crashes in cases where it can't be handled */
- ale->update = 0;
- }
+ /* Prevent crashes in cases where it can't be handled */
+ ale->update = 0;
+ }
- BLI_assert(ale->update == 0);
- }
+ BLI_assert(ale->update == 0);
+ }
}
void ANIM_animdata_freelist(ListBase *anim_data)
{
#ifndef NDEBUG
- bAnimListElem *ale, *ale_next;
- for (ale = anim_data->first; ale; ale = ale_next) {
- ale_next = ale->next;
- BLI_assert(ale->update == 0);
- MEM_freeN(ale);
- }
- BLI_listbase_clear(anim_data);
+ bAnimListElem *ale, *ale_next;
+ for (ale = anim_data->first; ale; ale = ale_next) {
+ ale_next = ale->next;
+ BLI_assert(ale->update == 0);
+ MEM_freeN(ale);
+ }
+ BLI_listbase_clear(anim_data);
#else
- BLI_freelistN(anim_data);
+ BLI_freelistN(anim_data);
#endif
}
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 2b168aa9463..11c768a8efd 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -65,88 +65,87 @@
/* Draw current frame number in a little green box beside the current frame indicator */
void ANIM_draw_cfra_number(const bContext *C, View2D *v2d, short flag)
{
- Scene *scene = CTX_data_scene(C);
- const float time = scene->r.cfra + scene->r.subframe;
- const float cfra = (float)(time * scene->r.framelen);
- const bool show_time = (flag & DRAWCFRA_UNIT_SECONDS) != 0;
-
- const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- unsigned char col[4];
- float color[4];
- float xscale, x, y;
- char numstr[32] = " t "; /* t is the character to start replacing from */
- float hlen;
- int slen;
-
- /* because the frame number text is subject to the same scaling as the contents of the view */
- UI_view2d_scale_get(v2d, &xscale, NULL);
- GPU_matrix_push();
- GPU_matrix_scale_2f(1.0f / xscale, 1.0f);
-
- /* get timecode string
- * - padding on str-buf passed so that it doesn't sit on the frame indicator
- */
- if (show_time) {
- BLI_timecode_string_from_time(&numstr[2], sizeof(numstr) - 2, 0, FRA2TIME(cfra), FPS, U.timecode_style);
- }
- else {
- BLI_timecode_string_from_time_seconds(&numstr[2], sizeof(numstr) - 2, 1, cfra);
- }
-
- slen = UI_fontstyle_string_width(fstyle, numstr) - 1;
- hlen = slen * 0.5f;
-
- /* get starting coordinates for drawing */
- x = cfra * xscale;
- y = -0.1f * U.widget_unit;
-
- /* draw green box around/behind text */
- UI_GetThemeColor4fv(TH_CFRAME, color);
- color[3] = 3.0f;
-
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_aa(true,
- x - hlen - 0.1f * U.widget_unit,
- y + 3.0f,
- x + hlen + 0.1f * U.widget_unit,
- y -3.0f + U.widget_unit,
- 0.1f * U.widget_unit,
- color);
-
- /* draw current frame number */
- UI_GetThemeColor4ubv(TH_TEXT_HI, col);
- UI_fontstyle_draw_simple(fstyle,
- x - hlen - 0.15f * U.widget_unit,
- y + 0.28f * U.widget_unit,
- numstr, col);
-
- /* restore view transform */
- GPU_matrix_pop();
+ Scene *scene = CTX_data_scene(C);
+ const float time = scene->r.cfra + scene->r.subframe;
+ const float cfra = (float)(time * scene->r.framelen);
+ const bool show_time = (flag & DRAWCFRA_UNIT_SECONDS) != 0;
+
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ unsigned char col[4];
+ float color[4];
+ float xscale, x, y;
+ char numstr[32] = " t "; /* t is the character to start replacing from */
+ float hlen;
+ int slen;
+
+ /* because the frame number text is subject to the same scaling as the contents of the view */
+ UI_view2d_scale_get(v2d, &xscale, NULL);
+ GPU_matrix_push();
+ GPU_matrix_scale_2f(1.0f / xscale, 1.0f);
+
+ /* get timecode string
+ * - padding on str-buf passed so that it doesn't sit on the frame indicator
+ */
+ if (show_time) {
+ BLI_timecode_string_from_time(
+ &numstr[2], sizeof(numstr) - 2, 0, FRA2TIME(cfra), FPS, U.timecode_style);
+ }
+ else {
+ BLI_timecode_string_from_time_seconds(&numstr[2], sizeof(numstr) - 2, 1, cfra);
+ }
+
+ slen = UI_fontstyle_string_width(fstyle, numstr) - 1;
+ hlen = slen * 0.5f;
+
+ /* get starting coordinates for drawing */
+ x = cfra * xscale;
+ y = -0.1f * U.widget_unit;
+
+ /* draw green box around/behind text */
+ UI_GetThemeColor4fv(TH_CFRAME, color);
+ color[3] = 3.0f;
+
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_aa(true,
+ x - hlen - 0.1f * U.widget_unit,
+ y + 3.0f,
+ x + hlen + 0.1f * U.widget_unit,
+ y - 3.0f + U.widget_unit,
+ 0.1f * U.widget_unit,
+ color);
+
+ /* draw current frame number */
+ UI_GetThemeColor4ubv(TH_TEXT_HI, col);
+ UI_fontstyle_draw_simple(
+ fstyle, x - hlen - 0.15f * U.widget_unit, y + 0.28f * U.widget_unit, numstr, col);
+
+ /* restore view transform */
+ GPU_matrix_pop();
}
/* General call for drawing current frame indicator in animation editor */
void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag)
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- const float time = scene->r.cfra + scene->r.subframe;
- const float x = (float)(time * scene->r.framelen);
+ const float time = scene->r.cfra + scene->r.subframe;
+ const float x = (float)(time * scene->r.framelen);
- GPU_line_width((flag & DRAWCFRA_WIDE) ? 3.0 : 2.0);
+ GPU_line_width((flag & DRAWCFRA_WIDE) ? 3.0 : 2.0);
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- /* Draw a light green line to indicate current frame */
- immUniformThemeColor(TH_CFRAME);
+ /* Draw a light green line to indicate current frame */
+ immUniformThemeColor(TH_CFRAME);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, x, v2d->cur.ymin - 500.0f); /* XXX arbitrary... want it go to bottom */
- immVertex2f(pos, x, v2d->cur.ymax);
- immEnd();
- immUnbindProgram();
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, x, v2d->cur.ymin - 500.0f); /* XXX arbitrary... want it go to bottom */
+ immVertex2f(pos, x, v2d->cur.ymax);
+ immEnd();
+ immUnbindProgram();
}
/* *************************************************** */
@@ -156,34 +155,35 @@ void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag)
/* Draw preview range 'curtains' for highlighting where the animation data is */
void ANIM_draw_previewrange(const bContext *C, View2D *v2d, int end_frame_width)
{
- Scene *scene = CTX_data_scene(C);
-
- /* only draw this if preview range is set */
- if (PRVRANGEON) {
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColorShadeAlpha(TH_ANIM_PREVIEW_RANGE, -25, -30);
- /* XXX: Fix this hardcoded color (anim_active) */
- //immUniformColor4f(0.8f, 0.44f, 0.1f, 0.2f);
-
- /* only draw two separate 'curtains' if there's no overlap between them */
- if (PSFRA < PEFRA + end_frame_width) {
- immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
- immRectf(pos, (float)(PEFRA + end_frame_width), v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
- }
- else {
- immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
- }
-
- immUnbindProgram();
-
- GPU_blend(false);
- }
+ Scene *scene = CTX_data_scene(C);
+
+ /* only draw this if preview range is set */
+ if (PRVRANGEON) {
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShadeAlpha(TH_ANIM_PREVIEW_RANGE, -25, -30);
+ /* XXX: Fix this hardcoded color (anim_active) */
+ //immUniformColor4f(0.8f, 0.44f, 0.1f, 0.2f);
+
+ /* only draw two separate 'curtains' if there's no overlap between them */
+ if (PSFRA < PEFRA + end_frame_width) {
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
+ immRectf(pos, (float)(PEFRA + end_frame_width), v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ }
+ else {
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ }
+
+ immUnbindProgram();
+
+ GPU_blend(false);
+ }
}
/* *************************************************** */
@@ -193,39 +193,40 @@ void ANIM_draw_previewrange(const bContext *C, View2D *v2d, int end_frame_width)
// TODO: Should we still show these when preview range is enabled?
void ANIM_draw_framerange(Scene *scene, View2D *v2d)
{
- /* draw darkened area outside of active timeline frame range */
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
+ /* draw darkened area outside of active timeline frame range */
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColorShadeAlpha(TH_BACK, -25, -100);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShadeAlpha(TH_BACK, -25, -100);
- if (SFRA < EFRA) {
- immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)SFRA, v2d->cur.ymax);
- immRectf(pos, (float)EFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
- }
- else {
- immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
- }
+ if (SFRA < EFRA) {
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)SFRA, v2d->cur.ymax);
+ immRectf(pos, (float)EFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ }
+ else {
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ }
- GPU_blend(false);
+ GPU_blend(false);
- /* thin lines where the actual frames are */
- immUniformThemeColorShade(TH_BACK, -60);
+ /* thin lines where the actual frames are */
+ immUniformThemeColorShade(TH_BACK, -60);
- immBegin(GPU_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, (float)SFRA, v2d->cur.ymin);
- immVertex2f(pos, (float)SFRA, v2d->cur.ymax);
+ immVertex2f(pos, (float)SFRA, v2d->cur.ymin);
+ immVertex2f(pos, (float)SFRA, v2d->cur.ymax);
- immVertex2f(pos, (float)EFRA, v2d->cur.ymin);
- immVertex2f(pos, (float)EFRA, v2d->cur.ymax);
+ immVertex2f(pos, (float)EFRA, v2d->cur.ymin);
+ immVertex2f(pos, (float)EFRA, v2d->cur.ymax);
- immEnd();
- immUnbindProgram();
+ immEnd();
+ immUnbindProgram();
}
/* *************************************************** */
@@ -235,28 +236,33 @@ void ANIM_draw_framerange(Scene *scene, View2D *v2d)
// TODO: do not supply return this if the animdata tells us that there is no mapping to perform
AnimData *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
{
- /* sanity checks */
- if (ac == NULL)
- return NULL;
-
- /* abort if rendering - we may get some race condition issues... */
- if (G.is_rendering) return NULL;
-
- /* apart from strictly keyframe-related contexts, this shouldn't even happen */
- // XXX: nla and channel here may not be necessary...
- if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_SHAPEKEY, ANIMCONT_DOPESHEET,
- ANIMCONT_FCURVES, ANIMCONT_NLA, ANIMCONT_CHANNEL))
- {
- /* handling depends on the type of animation-context we've got */
- if (ale) {
- /* NLA Control Curves occur on NLA strips, and shouldn't be subjected to this kind of mapping */
- if (ale->type != ANIMTYPE_NLACURVE)
- return ale->adt;
- }
- }
-
- /* cannot handle... */
- return NULL;
+ /* sanity checks */
+ if (ac == NULL)
+ return NULL;
+
+ /* abort if rendering - we may get some race condition issues... */
+ if (G.is_rendering)
+ return NULL;
+
+ /* apart from strictly keyframe-related contexts, this shouldn't even happen */
+ // XXX: nla and channel here may not be necessary...
+ if (ELEM(ac->datatype,
+ ANIMCONT_ACTION,
+ ANIMCONT_SHAPEKEY,
+ ANIMCONT_DOPESHEET,
+ ANIMCONT_FCURVES,
+ ANIMCONT_NLA,
+ ANIMCONT_CHANNEL)) {
+ /* handling depends on the type of animation-context we've got */
+ if (ale) {
+ /* NLA Control Curves occur on NLA strips, and shouldn't be subjected to this kind of mapping */
+ if (ale->type != ANIMTYPE_NLACURVE)
+ return ale->adt;
+ }
+ }
+
+ /* cannot handle... */
+ return NULL;
}
/* ------------------- */
@@ -264,65 +270,64 @@ AnimData *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
/* helper function for ANIM_nla_mapping_apply_fcurve() -> "restore", i.e. mapping points back to action-time */
static short bezt_nlamapping_restore(KeyframeEditData *ked, BezTriple *bezt)
{
- /* AnimData block providing scaling is stored in 'data', only_keys option is stored in i1 */
- AnimData *adt = (AnimData *)ked->data;
- short only_keys = (short)ked->i1;
+ /* AnimData block providing scaling is stored in 'data', only_keys option is stored in i1 */
+ AnimData *adt = (AnimData *)ked->data;
+ short only_keys = (short)ked->i1;
- /* adjust BezTriple handles only if allowed to */
- if (only_keys == 0) {
- bezt->vec[0][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], NLATIME_CONVERT_UNMAP);
- bezt->vec[2][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], NLATIME_CONVERT_UNMAP);
- }
+ /* adjust BezTriple handles only if allowed to */
+ if (only_keys == 0) {
+ bezt->vec[0][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], NLATIME_CONVERT_UNMAP);
+ bezt->vec[2][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], NLATIME_CONVERT_UNMAP);
+ }
- bezt->vec[1][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], NLATIME_CONVERT_UNMAP);
+ bezt->vec[1][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], NLATIME_CONVERT_UNMAP);
- return 0;
+ return 0;
}
/* helper function for ANIM_nla_mapping_apply_fcurve() -> "apply",
* i.e. mapping points to NLA-mapped global time */
static short bezt_nlamapping_apply(KeyframeEditData *ked, BezTriple *bezt)
{
- /* AnimData block providing scaling is stored in 'data', only_keys option is stored in i1 */
- AnimData *adt = (AnimData *)ked->data;
- short only_keys = (short)ked->i1;
+ /* AnimData block providing scaling is stored in 'data', only_keys option is stored in i1 */
+ AnimData *adt = (AnimData *)ked->data;
+ short only_keys = (short)ked->i1;
- /* adjust BezTriple handles only if allowed to */
- if (only_keys == 0) {
- bezt->vec[0][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], NLATIME_CONVERT_MAP);
- bezt->vec[2][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], NLATIME_CONVERT_MAP);
- }
+ /* adjust BezTriple handles only if allowed to */
+ if (only_keys == 0) {
+ bezt->vec[0][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], NLATIME_CONVERT_MAP);
+ bezt->vec[2][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], NLATIME_CONVERT_MAP);
+ }
- bezt->vec[1][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], NLATIME_CONVERT_MAP);
+ bezt->vec[1][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], NLATIME_CONVERT_MAP);
- return 0;
+ return 0;
}
-
/* Apply/Unapply NLA mapping to all keyframes in the nominated F-Curve
* - restore = whether to map points back to non-mapped time
* - only_keys = whether to only adjust the location of the center point of beztriples
*/
void ANIM_nla_mapping_apply_fcurve(AnimData *adt, FCurve *fcu, bool restore, bool only_keys)
{
- KeyframeEditData ked = {{NULL}};
- KeyframeEditFunc map_cb;
-
- /* init edit data
- * - AnimData is stored in 'data'
- * - only_keys is stored in 'i1'
- */
- ked.data = (void *)adt;
- ked.i1 = (int)only_keys;
-
- /* get editing callback */
- if (restore)
- map_cb = bezt_nlamapping_restore;
- else
- map_cb = bezt_nlamapping_apply;
-
- /* apply to F-Curve */
- ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, map_cb, NULL);
+ KeyframeEditData ked = {{NULL}};
+ KeyframeEditFunc map_cb;
+
+ /* init edit data
+ * - AnimData is stored in 'data'
+ * - only_keys is stored in 'i1'
+ */
+ ked.data = (void *)adt;
+ ked.i1 = (int)only_keys;
+
+ /* get editing callback */
+ if (restore)
+ map_cb = bezt_nlamapping_restore;
+ else
+ map_cb = bezt_nlamapping_apply;
+
+ /* apply to F-Curve */
+ ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, map_cb, NULL);
}
/* *************************************************** */
@@ -331,329 +336,328 @@ void ANIM_nla_mapping_apply_fcurve(AnimData *adt, FCurve *fcu, bool restore, boo
/* Get flags used for normalization in ANIM_unit_mapping_get_factor. */
short ANIM_get_normalization_flags(bAnimContext *ac)
{
- if (ac->sl->spacetype == SPACE_GRAPH) {
- SpaceGraph *sipo = (SpaceGraph *) ac->sl;
- bool use_normalization = (sipo->flag & SIPO_NORMALIZE) != 0;
- bool freeze_normalization = (sipo->flag & SIPO_NORMALIZE_FREEZE) != 0;
- return use_normalization
- ? (ANIM_UNITCONV_NORMALIZE | (freeze_normalization ? ANIM_UNITCONV_NORMALIZE_FREEZE : 0))
- : 0;
- }
-
- return 0;
+ if (ac->sl->spacetype == SPACE_GRAPH) {
+ SpaceGraph *sipo = (SpaceGraph *)ac->sl;
+ bool use_normalization = (sipo->flag & SIPO_NORMALIZE) != 0;
+ bool freeze_normalization = (sipo->flag & SIPO_NORMALIZE_FREEZE) != 0;
+ return use_normalization ? (ANIM_UNITCONV_NORMALIZE |
+ (freeze_normalization ? ANIM_UNITCONV_NORMALIZE_FREEZE : 0)) :
+ 0;
+ }
+
+ return 0;
}
static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, float *r_offset)
{
- float factor = 1.0f, offset = 0.0f;
-
- if (flag & ANIM_UNITCONV_RESTORE) {
- if (r_offset)
- *r_offset = fcu->prev_offset;
-
- return 1.0f / fcu->prev_norm_factor;
- }
-
- if (flag & ANIM_UNITCONV_NORMALIZE_FREEZE) {
- if (r_offset)
- *r_offset = fcu->prev_offset;
- if (fcu->prev_norm_factor == 0.0f) {
- /* Happens when Auto Normalize was disabled before
- * any curves were displayed.
- */
- return 1.0f;
- }
- return fcu->prev_norm_factor;
- }
-
- if (G.moving & G_TRANSFORM_FCURVES) {
- if (r_offset)
- *r_offset = fcu->prev_offset;
- if (fcu->prev_norm_factor == 0.0f) {
- /* Same as above. */
- return 1.0f;
- }
- return fcu->prev_norm_factor;
- }
-
- fcu->prev_norm_factor = 1.0f;
- if (fcu->bezt) {
- const bool use_preview_only = PRVRANGEON;
- const BezTriple *bezt;
- int i;
- float max_coord = -FLT_MAX;
- float min_coord = FLT_MAX;
- float range;
-
- if (fcu->totvert < 1) {
- return 1.0f;
- }
-
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- if (use_preview_only && !IN_RANGE_INCL(bezt->vec[1][0],
- scene->r.psfra,
- scene->r.pefra))
- {
- continue;
- }
-
- if (i == 0) {
- /* We ignore extrapolation flags and handle here, and use the
- * control point position only. so we normalize "interesting"
- * part of the curve.
- *
- * Here we handle left extrapolation.
- */
- max_coord = max_ff(max_coord, bezt->vec[1][1]);
-
- min_coord = min_ff(min_coord, bezt->vec[1][1]);
- }
- else {
- const BezTriple *prev_bezt = bezt - 1;
- if (prev_bezt->ipo == BEZT_IPO_CONST) {
- /* Constant interpolation: previous CV value is used up
- * to the current keyframe.
- */
- max_coord = max_ff(max_coord, bezt->vec[1][1]);
- min_coord = min_ff(min_coord, bezt->vec[1][1]);
- }
- else if (prev_bezt->ipo == BEZT_IPO_LIN) {
- /* Linear interpolation: min/max using both previous and
- * and current CV.
- */
- max_coord = max_ff(max_coord, bezt->vec[1][1]);
- min_coord = min_ff(min_coord, bezt->vec[1][1]);
- max_coord = max_ff(max_coord, prev_bezt->vec[1][1]);
- min_coord = min_ff(min_coord, prev_bezt->vec[1][1]);
- }
- else if (prev_bezt->ipo == BEZT_IPO_BEZ) {
- const int resol = fcu->driver
- ? 32
- : min_ii((int)(5.0f * len_v2v2(bezt->vec[1], prev_bezt->vec[1])), 32);
- if (resol < 2) {
- max_coord = max_ff(max_coord, prev_bezt->vec[1][1]);
- min_coord = min_ff(min_coord, prev_bezt->vec[1][1]);
- }
- else {
- 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]);
- }
- }
- }
- }
- }
-
- if (max_coord > min_coord) {
- range = max_coord - min_coord;
- if (range > FLT_EPSILON) {
- factor = 2.0f / range;
- }
- offset = -min_coord - range / 2.0f;
- }
- else if (max_coord == min_coord) {
- factor = 1.0f;
- offset = -min_coord;
- }
- }
- BLI_assert(factor != 0.0f);
- if (r_offset) {
- *r_offset = offset;
- }
-
- fcu->prev_norm_factor = factor;
- fcu->prev_offset = offset;
- return factor;
+ float factor = 1.0f, offset = 0.0f;
+
+ if (flag & ANIM_UNITCONV_RESTORE) {
+ if (r_offset)
+ *r_offset = fcu->prev_offset;
+
+ return 1.0f / fcu->prev_norm_factor;
+ }
+
+ if (flag & ANIM_UNITCONV_NORMALIZE_FREEZE) {
+ if (r_offset)
+ *r_offset = fcu->prev_offset;
+ if (fcu->prev_norm_factor == 0.0f) {
+ /* Happens when Auto Normalize was disabled before
+ * any curves were displayed.
+ */
+ return 1.0f;
+ }
+ return fcu->prev_norm_factor;
+ }
+
+ if (G.moving & G_TRANSFORM_FCURVES) {
+ if (r_offset)
+ *r_offset = fcu->prev_offset;
+ if (fcu->prev_norm_factor == 0.0f) {
+ /* Same as above. */
+ return 1.0f;
+ }
+ return fcu->prev_norm_factor;
+ }
+
+ fcu->prev_norm_factor = 1.0f;
+ if (fcu->bezt) {
+ const bool use_preview_only = PRVRANGEON;
+ const BezTriple *bezt;
+ int i;
+ float max_coord = -FLT_MAX;
+ float min_coord = FLT_MAX;
+ float range;
+
+ if (fcu->totvert < 1) {
+ return 1.0f;
+ }
+
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (use_preview_only && !IN_RANGE_INCL(bezt->vec[1][0], scene->r.psfra, scene->r.pefra)) {
+ continue;
+ }
+
+ if (i == 0) {
+ /* We ignore extrapolation flags and handle here, and use the
+ * control point position only. so we normalize "interesting"
+ * part of the curve.
+ *
+ * Here we handle left extrapolation.
+ */
+ max_coord = max_ff(max_coord, bezt->vec[1][1]);
+
+ min_coord = min_ff(min_coord, bezt->vec[1][1]);
+ }
+ else {
+ const BezTriple *prev_bezt = bezt - 1;
+ if (prev_bezt->ipo == BEZT_IPO_CONST) {
+ /* Constant interpolation: previous CV value is used up
+ * to the current keyframe.
+ */
+ max_coord = max_ff(max_coord, bezt->vec[1][1]);
+ min_coord = min_ff(min_coord, bezt->vec[1][1]);
+ }
+ else if (prev_bezt->ipo == BEZT_IPO_LIN) {
+ /* Linear interpolation: min/max using both previous and
+ * and current CV.
+ */
+ max_coord = max_ff(max_coord, bezt->vec[1][1]);
+ min_coord = min_ff(min_coord, bezt->vec[1][1]);
+ max_coord = max_ff(max_coord, prev_bezt->vec[1][1]);
+ min_coord = min_ff(min_coord, prev_bezt->vec[1][1]);
+ }
+ else if (prev_bezt->ipo == BEZT_IPO_BEZ) {
+ const int resol = fcu->driver ?
+ 32 :
+ min_ii((int)(5.0f * len_v2v2(bezt->vec[1], prev_bezt->vec[1])),
+ 32);
+ if (resol < 2) {
+ max_coord = max_ff(max_coord, prev_bezt->vec[1][1]);
+ min_coord = min_ff(min_coord, prev_bezt->vec[1][1]);
+ }
+ else {
+ 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]);
+ }
+ }
+ }
+ }
+ }
+
+ if (max_coord > min_coord) {
+ range = max_coord - min_coord;
+ if (range > FLT_EPSILON) {
+ factor = 2.0f / range;
+ }
+ offset = -min_coord - range / 2.0f;
+ }
+ else if (max_coord == min_coord) {
+ factor = 1.0f;
+ offset = -min_coord;
+ }
+ }
+ BLI_assert(factor != 0.0f);
+ if (r_offset) {
+ *r_offset = offset;
+ }
+
+ fcu->prev_norm_factor = factor;
+ fcu->prev_offset = offset;
+ return factor;
}
/* Get unit conversion factor for given ID + F-Curve */
float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag, float *r_offset)
{
- if (flag & ANIM_UNITCONV_NORMALIZE) {
- return normalization_factor_get(scene, fcu, flag, r_offset);
- }
-
- if (r_offset)
- *r_offset = 0.0f;
-
- /* sanity checks */
- if (id && fcu && fcu->rna_path) {
- PointerRNA ptr, id_ptr;
- PropertyRNA *prop;
-
- /* get RNA property that F-Curve affects */
- RNA_id_pointer_create(id, &id_ptr);
- if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
- /* rotations: radians <-> degrees? */
- if (RNA_SUBTYPE_UNIT(RNA_property_subtype(prop)) == PROP_UNIT_ROTATION) {
- /* if the radians flag is not set, default to using degrees which need conversions */
- if ((scene) && (scene->unit.system_rotation == USER_UNIT_ROT_RADIANS) == 0) {
- if (flag & ANIM_UNITCONV_RESTORE)
- return DEG2RADF(1.0f); /* degrees to radians */
- else
- return RAD2DEGF(1.0f); /* radians to degrees */
- }
- }
-
- /* TODO: other rotation types here as necessary */
- }
- }
-
- /* no mapping needs to occur... */
- return 1.0f;
+ if (flag & ANIM_UNITCONV_NORMALIZE) {
+ return normalization_factor_get(scene, fcu, flag, r_offset);
+ }
+
+ if (r_offset)
+ *r_offset = 0.0f;
+
+ /* sanity checks */
+ if (id && fcu && fcu->rna_path) {
+ PointerRNA ptr, id_ptr;
+ PropertyRNA *prop;
+
+ /* get RNA property that F-Curve affects */
+ RNA_id_pointer_create(id, &id_ptr);
+ if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
+ /* rotations: radians <-> degrees? */
+ if (RNA_SUBTYPE_UNIT(RNA_property_subtype(prop)) == PROP_UNIT_ROTATION) {
+ /* if the radians flag is not set, default to using degrees which need conversions */
+ if ((scene) && (scene->unit.system_rotation == USER_UNIT_ROT_RADIANS) == 0) {
+ if (flag & ANIM_UNITCONV_RESTORE)
+ return DEG2RADF(1.0f); /* degrees to radians */
+ else
+ return RAD2DEGF(1.0f); /* radians to degrees */
+ }
+ }
+
+ /* TODO: other rotation types here as necessary */
+ }
+ }
+
+ /* no mapping needs to occur... */
+ return 1.0f;
}
static bool find_prev_next_keyframes(struct bContext *C, int *nextfra, int *prevfra)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- Mask *mask = CTX_data_edit_mask(C);
- bDopeSheet ads = {NULL};
- DLRBT_Tree keys;
- ActKeyColumn *aknext, *akprev;
- float cfranext, cfraprev;
- bool donenext = false, doneprev = false;
- int nextcount = 0, prevcount = 0;
-
- cfranext = cfraprev = (float)(CFRA);
-
- /* init binarytree-list for getting keyframes */
- BLI_dlrbTree_init(&keys);
-
- /* seed up dummy dopesheet context with flags to perform necessary filtering */
- if ((scene->flag & SCE_KEYS_NO_SELONLY) == 0) {
- /* only selected channels are included */
- ads.filterflag |= ADS_FILTER_ONLYSEL;
- }
-
- /* populate tree with keyframe nodes */
- scene_to_keylist(&ads, scene, &keys, 0);
- gpencil_to_keylist(&ads, scene->gpd, &keys, false);
-
- if (ob) {
- ob_to_keylist(&ads, ob, &keys, 0);
- gpencil_to_keylist(&ads, ob->data, &keys, false);
- }
-
- if (mask) {
- MaskLayer *masklay = BKE_mask_layer_active(mask);
- mask_to_keylist(&ads, masklay, &keys);
- }
-
- /* find matching keyframe in the right direction */
- do {
- aknext = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfranext);
-
- if (aknext) {
- if (CFRA == (int)aknext->cfra) {
- /* make this the new starting point for the search and ignore */
- cfranext = aknext->cfra;
- }
- else {
- /* this changes the frame, so set the frame and we're done */
- if (++nextcount == U.view_frame_keyframes)
- donenext = true;
- }
- cfranext = aknext->cfra;
- }
- } while ((aknext != NULL) && (donenext == false));
-
- do {
- akprev = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfraprev);
-
- if (akprev) {
- if (CFRA == (int)akprev->cfra) {
- /* make this the new starting point for the search */
- }
- else {
- /* this changes the frame, so set the frame and we're done */
- if (++prevcount == U.view_frame_keyframes)
- doneprev = true;
- }
- cfraprev = akprev->cfra;
- }
- } while ((akprev != NULL) && (doneprev == false));
-
- /* free temp stuff */
- BLI_dlrbTree_free(&keys);
-
- /* any success? */
- if (doneprev || donenext) {
- if (doneprev)
- *prevfra = cfraprev;
- else
- *prevfra = CFRA - (cfranext - CFRA);
-
- if (donenext)
- *nextfra = cfranext;
- else
- *nextfra = CFRA + (CFRA - cfraprev);
-
- return true;
- }
-
- return false;
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ Mask *mask = CTX_data_edit_mask(C);
+ bDopeSheet ads = {NULL};
+ DLRBT_Tree keys;
+ ActKeyColumn *aknext, *akprev;
+ float cfranext, cfraprev;
+ bool donenext = false, doneprev = false;
+ int nextcount = 0, prevcount = 0;
+
+ cfranext = cfraprev = (float)(CFRA);
+
+ /* init binarytree-list for getting keyframes */
+ BLI_dlrbTree_init(&keys);
+
+ /* seed up dummy dopesheet context with flags to perform necessary filtering */
+ if ((scene->flag & SCE_KEYS_NO_SELONLY) == 0) {
+ /* only selected channels are included */
+ ads.filterflag |= ADS_FILTER_ONLYSEL;
+ }
+
+ /* populate tree with keyframe nodes */
+ scene_to_keylist(&ads, scene, &keys, 0);
+ gpencil_to_keylist(&ads, scene->gpd, &keys, false);
+
+ if (ob) {
+ ob_to_keylist(&ads, ob, &keys, 0);
+ gpencil_to_keylist(&ads, ob->data, &keys, false);
+ }
+
+ if (mask) {
+ MaskLayer *masklay = BKE_mask_layer_active(mask);
+ mask_to_keylist(&ads, masklay, &keys);
+ }
+
+ /* find matching keyframe in the right direction */
+ do {
+ aknext = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfranext);
+
+ if (aknext) {
+ if (CFRA == (int)aknext->cfra) {
+ /* make this the new starting point for the search and ignore */
+ cfranext = aknext->cfra;
+ }
+ else {
+ /* this changes the frame, so set the frame and we're done */
+ if (++nextcount == U.view_frame_keyframes)
+ donenext = true;
+ }
+ cfranext = aknext->cfra;
+ }
+ } while ((aknext != NULL) && (donenext == false));
+
+ do {
+ akprev = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfraprev);
+
+ if (akprev) {
+ if (CFRA == (int)akprev->cfra) {
+ /* make this the new starting point for the search */
+ }
+ else {
+ /* this changes the frame, so set the frame and we're done */
+ if (++prevcount == U.view_frame_keyframes)
+ doneprev = true;
+ }
+ cfraprev = akprev->cfra;
+ }
+ } while ((akprev != NULL) && (doneprev == false));
+
+ /* free temp stuff */
+ BLI_dlrbTree_free(&keys);
+
+ /* any success? */
+ if (doneprev || donenext) {
+ if (doneprev)
+ *prevfra = cfraprev;
+ else
+ *prevfra = CFRA - (cfranext - CFRA);
+
+ if (donenext)
+ *nextfra = cfranext;
+ else
+ *nextfra = CFRA + (CFRA - cfraprev);
+
+ return true;
+ }
+
+ return false;
}
void ANIM_center_frame(struct bContext *C, int smooth_viewtx)
{
- ARegion *ar = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
- float w = BLI_rctf_size_x(&ar->v2d.cur);
- rctf newrct;
- int nextfra, prevfra;
-
- switch (U.view_frame_type) {
- case ZOOM_FRAME_MODE_SECONDS:
- {
- 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;
- break;
- }
-
- /* hardest case of all, look for all keyframes around frame and display those */
- case ZOOM_FRAME_MODE_KEYFRAMES:
- 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;
- break;
- }
- /* else drop through, keep range instead */
- ATTR_FALLTHROUGH;
-
- case ZOOM_FRAME_MODE_KEEP_RANGE:
- 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;
- break;
- }
-
- UI_view2d_smooth_view(C, ar, &newrct, smooth_viewtx);
+ ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+ float w = BLI_rctf_size_x(&ar->v2d.cur);
+ rctf newrct;
+ int nextfra, prevfra;
+
+ switch (U.view_frame_type) {
+ case ZOOM_FRAME_MODE_SECONDS: {
+ 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;
+ break;
+ }
+
+ /* hardest case of all, look for all keyframes around frame and display those */
+ case ZOOM_FRAME_MODE_KEYFRAMES:
+ 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;
+ break;
+ }
+ /* else drop through, keep range instead */
+ ATTR_FALLTHROUGH;
+
+ case ZOOM_FRAME_MODE_KEEP_RANGE:
+ 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;
+ break;
+ }
+
+ UI_view2d_smooth_view(C, ar, &newrct, smooth_viewtx);
}
/* *************************************************** */
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index dad0727a82d..57ea5ad81f5 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -21,7 +21,6 @@
* \ingroup edanimation
*/
-
/* This file contains a system used to provide a layer of abstraction between sources
* of animation data and tools in Animation Editors. The method used here involves
* generating a list of edit structures which enable tools to naively perform the actions
@@ -96,7 +95,7 @@
#include "ED_anim_api.h"
#include "ED_markers.h"
-#include "UI_resources.h" /* for TH_KEYFRAME_SCALE lookup */
+#include "UI_resources.h" /* for TH_KEYFRAME_SCALE lookup */
/* ************************************************************ */
/* Blender Context <-> Animation Context mapping */
@@ -106,18 +105,18 @@
/* Get vertical scaling factor (i.e. typically used for keyframe size) */
static void animedit_get_yscale_factor(bAnimContext *ac)
{
- bTheme *btheme = UI_GetTheme();
-
- /* grab scale factor directly from action editor setting
- * NOTE: This theme setting doesn't have an ID, as it cannot be accessed normally
- * since it is a float, and the theme settings methods can only handle chars.
- */
- ac->yscale_fac = btheme->space_action.keyframe_scale_fac;
-
- /* clamp to avoid problems with uninitialised values... */
- if (ac->yscale_fac < 0.1f)
- ac->yscale_fac = 1.0f;
- //printf("yscale_fac = %f\n", ac->yscale_fac);
+ bTheme *btheme = UI_GetTheme();
+
+ /* grab scale factor directly from action editor setting
+ * NOTE: This theme setting doesn't have an ID, as it cannot be accessed normally
+ * since it is a float, and the theme settings methods can only handle chars.
+ */
+ ac->yscale_fac = btheme->space_action.keyframe_scale_fac;
+
+ /* clamp to avoid problems with uninitialised values... */
+ if (ac->yscale_fac < 0.1f)
+ ac->yscale_fac = 1.0f;
+ //printf("yscale_fac = %f\n", ac->yscale_fac);
}
/* ----------- Private Stuff - Action Editor ------------- */
@@ -126,144 +125,144 @@ static void animedit_get_yscale_factor(bAnimContext *ac)
/* Note: there's a similar function in key.c (BKE_key_from_object) */
static Key *actedit_get_shapekeys(bAnimContext *ac)
{
- ViewLayer *view_layer = ac->view_layer;
- Object *ob;
- Key *key;
+ ViewLayer *view_layer = ac->view_layer;
+ Object *ob;
+ Key *key;
- ob = OBACT(view_layer);
- if (ob == NULL)
- return NULL;
+ ob = OBACT(view_layer);
+ if (ob == NULL)
+ return NULL;
- /* XXX pinning is not available in 'ShapeKey' mode... */
- //if (saction->pin) return NULL;
+ /* XXX pinning is not available in 'ShapeKey' mode... */
+ //if (saction->pin) return NULL;
- /* shapekey data is stored with geometry data */
- key = BKE_key_from_object(ob);
+ /* shapekey data is stored with geometry data */
+ key = BKE_key_from_object(ob);
- if (key) {
- if (key->type == KEY_RELATIVE)
- return key;
- }
+ if (key) {
+ if (key->type == KEY_RELATIVE)
+ return key;
+ }
- return NULL;
+ return NULL;
}
/* Get data being edited in Action Editor (depending on current 'mode') */
static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction)
{
- /* get dopesheet */
- ac->ads = &saction->ads;
-
- /* sync settings with current view status, then return appropriate data */
- switch (saction->mode) {
- case SACTCONT_ACTION: /* 'Action Editor' */
- /* if not pinned, sync with active object */
- if (/*saction->pin == 0*/ true) {
- if (ac->obact && ac->obact->adt)
- saction->action = ac->obact->adt->action;
- else
- saction->action = NULL;
- }
-
- ac->datatype = ANIMCONT_ACTION;
- ac->data = saction->action;
-
- ac->mode = saction->mode;
- return true;
-
- case SACTCONT_SHAPEKEY: /* 'ShapeKey Editor' */
- ac->datatype = ANIMCONT_SHAPEKEY;
- ac->data = actedit_get_shapekeys(ac);
-
- /* if not pinned, sync with active object */
- if (/*saction->pin == 0*/ true) {
- Key *key = (Key *)ac->data;
-
- if (key && key->adt)
- saction->action = key->adt->action;
- else
- saction->action = NULL;
- }
-
- ac->mode = saction->mode;
- return true;
-
- case SACTCONT_GPENCIL: /* Grease Pencil */ /* XXX review how this mode is handled... */
- /* update scene-pointer (no need to check for pinning yet, as not implemented) */
- saction->ads.source = (ID *)ac->scene;
-
- ac->datatype = ANIMCONT_GPENCIL;
- ac->data = &saction->ads;
-
- ac->mode = saction->mode;
- return true;
-
- case SACTCONT_CACHEFILE: /* Cache File */ /* XXX review how this mode is handled... */
- /* update scene-pointer (no need to check for pinning yet, as not implemented) */
- saction->ads.source = (ID *)ac->scene;
-
- ac->datatype = ANIMCONT_CHANNEL;
- ac->data = &saction->ads;
-
- ac->mode = saction->mode;
- return true;
-
- case SACTCONT_MASK: /* Mask */ /* XXX review how this mode is handled... */
- {
- /* TODO, other methods to get the mask */
- // Sequence *seq = BKE_sequencer_active_get(ac->scene);
- //MovieClip *clip = ac->scene->clip;
-// struct Mask *mask = seq ? seq->mask : NULL;
-
- /* update scene-pointer (no need to check for pinning yet, as not implemented) */
- saction->ads.source = (ID *)ac->scene;
-
- ac->datatype = ANIMCONT_MASK;
- ac->data = &saction->ads;
-
- ac->mode = saction->mode;
- return true;
- }
-
- case SACTCONT_DOPESHEET: /* DopeSheet */
- /* update scene-pointer (no need to check for pinning yet, as not implemented) */
- saction->ads.source = (ID *)ac->scene;
-
- ac->datatype = ANIMCONT_DOPESHEET;
- ac->data = &saction->ads;
-
- ac->mode = saction->mode;
- return true;
-
- case SACTCONT_TIMELINE: /* Timeline */
- /* update scene-pointer (no need to check for pinning yet, as not implemented) */
- saction->ads.source = (ID *)ac->scene;
-
- /* sync scene's "selected keys only" flag with our "only selected" flag
- * XXX: This is a workaround for T55525. We shouldn't really be syncing the flags like this,
- * but it's a simpler fix for now than also figuring out how the next/prev keyframe tools
- * should work in the 3D View if we allowed full access to the timeline's dopesheet filters
- * (i.e. we'd have to figure out where to host those settings, to be on a scene level like
- * this flag currently is, along with several other unknowns)
- */
- if (ac->scene->flag & SCE_KEYS_NO_SELONLY)
- saction->ads.filterflag &= ~ADS_FILTER_ONLYSEL;
- else
- saction->ads.filterflag |= ADS_FILTER_ONLYSEL;
-
- ac->datatype = ANIMCONT_TIMELINE;
- ac->data = &saction->ads;
-
- ac->mode = saction->mode;
- return true;
-
- default: /* unhandled yet */
- ac->datatype = ANIMCONT_NONE;
- ac->data = NULL;
-
- ac->mode = -1;
- return false;
- }
+ /* get dopesheet */
+ ac->ads = &saction->ads;
+
+ /* sync settings with current view status, then return appropriate data */
+ switch (saction->mode) {
+ case SACTCONT_ACTION: /* 'Action Editor' */
+ /* if not pinned, sync with active object */
+ if (/*saction->pin == 0*/ true) {
+ if (ac->obact && ac->obact->adt)
+ saction->action = ac->obact->adt->action;
+ else
+ saction->action = NULL;
+ }
+
+ ac->datatype = ANIMCONT_ACTION;
+ ac->data = saction->action;
+
+ ac->mode = saction->mode;
+ return true;
+
+ case SACTCONT_SHAPEKEY: /* 'ShapeKey Editor' */
+ ac->datatype = ANIMCONT_SHAPEKEY;
+ ac->data = actedit_get_shapekeys(ac);
+
+ /* if not pinned, sync with active object */
+ if (/*saction->pin == 0*/ true) {
+ Key *key = (Key *)ac->data;
+
+ if (key && key->adt)
+ saction->action = key->adt->action;
+ else
+ saction->action = NULL;
+ }
+
+ ac->mode = saction->mode;
+ return true;
+
+ case SACTCONT_GPENCIL: /* Grease Pencil */ /* XXX review how this mode is handled... */
+ /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+ saction->ads.source = (ID *)ac->scene;
+
+ ac->datatype = ANIMCONT_GPENCIL;
+ ac->data = &saction->ads;
+
+ ac->mode = saction->mode;
+ return true;
+
+ case SACTCONT_CACHEFILE: /* Cache File */ /* XXX review how this mode is handled... */
+ /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+ saction->ads.source = (ID *)ac->scene;
+
+ ac->datatype = ANIMCONT_CHANNEL;
+ ac->data = &saction->ads;
+
+ ac->mode = saction->mode;
+ return true;
+
+ case SACTCONT_MASK: /* Mask */ /* XXX review how this mode is handled... */
+ {
+ /* TODO, other methods to get the mask */
+ // Sequence *seq = BKE_sequencer_active_get(ac->scene);
+ //MovieClip *clip = ac->scene->clip;
+ // struct Mask *mask = seq ? seq->mask : NULL;
+
+ /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+ saction->ads.source = (ID *)ac->scene;
+
+ ac->datatype = ANIMCONT_MASK;
+ ac->data = &saction->ads;
+
+ ac->mode = saction->mode;
+ return true;
+ }
+
+ case SACTCONT_DOPESHEET: /* DopeSheet */
+ /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+ saction->ads.source = (ID *)ac->scene;
+
+ ac->datatype = ANIMCONT_DOPESHEET;
+ ac->data = &saction->ads;
+
+ ac->mode = saction->mode;
+ return true;
+
+ case SACTCONT_TIMELINE: /* Timeline */
+ /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+ saction->ads.source = (ID *)ac->scene;
+
+ /* sync scene's "selected keys only" flag with our "only selected" flag
+ * XXX: This is a workaround for T55525. We shouldn't really be syncing the flags like this,
+ * but it's a simpler fix for now than also figuring out how the next/prev keyframe tools
+ * should work in the 3D View if we allowed full access to the timeline's dopesheet filters
+ * (i.e. we'd have to figure out where to host those settings, to be on a scene level like
+ * this flag currently is, along with several other unknowns)
+ */
+ if (ac->scene->flag & SCE_KEYS_NO_SELONLY)
+ saction->ads.filterflag &= ~ADS_FILTER_ONLYSEL;
+ else
+ saction->ads.filterflag |= ADS_FILTER_ONLYSEL;
+
+ ac->datatype = ANIMCONT_TIMELINE;
+ ac->data = &saction->ads;
+
+ ac->mode = saction->mode;
+ return true;
+
+ default: /* unhandled yet */
+ ac->datatype = ANIMCONT_NONE;
+ ac->data = NULL;
+
+ ac->mode = -1;
+ return false;
+ }
}
/* ----------- Private Stuff - Graph Editor ------------- */
@@ -271,50 +270,50 @@ static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction)
/* Get data being edited in Graph Editor (depending on current 'mode') */
static bool graphedit_get_context(bAnimContext *ac, SpaceGraph *sipo)
{
- /* init dopesheet data if non-existent (i.e. for old files) */
- if (sipo->ads == NULL) {
- sipo->ads = MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
- sipo->ads->source = (ID *)ac->scene;
- }
- ac->ads = sipo->ads;
-
- /* set settings for Graph Editor - "Selected = Editable" */
- if (sipo->flag & SIPO_SELCUVERTSONLY)
- sipo->ads->filterflag |= ADS_FILTER_SELEDIT;
- else
- sipo->ads->filterflag &= ~ADS_FILTER_SELEDIT;
-
- /* sync settings with current view status, then return appropriate data */
- switch (sipo->mode) {
- case SIPO_MODE_ANIMATION: /* Animation F-Curve Editor */
- /* update scene-pointer (no need to check for pinning yet, as not implemented) */
- sipo->ads->source = (ID *)ac->scene;
- sipo->ads->filterflag &= ~ADS_FILTER_ONLYDRIVERS;
-
- ac->datatype = ANIMCONT_FCURVES;
- ac->data = sipo->ads;
-
- ac->mode = sipo->mode;
- return true;
-
- case SIPO_MODE_DRIVERS: /* Driver F-Curve Editor */
- /* update scene-pointer (no need to check for pinning yet, as not implemented) */
- sipo->ads->source = (ID *)ac->scene;
- sipo->ads->filterflag |= ADS_FILTER_ONLYDRIVERS;
-
- ac->datatype = ANIMCONT_DRIVERS;
- ac->data = sipo->ads;
-
- ac->mode = sipo->mode;
- return true;
-
- default: /* unhandled yet */
- ac->datatype = ANIMCONT_NONE;
- ac->data = NULL;
-
- ac->mode = -1;
- return false;
- }
+ /* init dopesheet data if non-existent (i.e. for old files) */
+ if (sipo->ads == NULL) {
+ sipo->ads = MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
+ sipo->ads->source = (ID *)ac->scene;
+ }
+ ac->ads = sipo->ads;
+
+ /* set settings for Graph Editor - "Selected = Editable" */
+ if (sipo->flag & SIPO_SELCUVERTSONLY)
+ sipo->ads->filterflag |= ADS_FILTER_SELEDIT;
+ else
+ sipo->ads->filterflag &= ~ADS_FILTER_SELEDIT;
+
+ /* sync settings with current view status, then return appropriate data */
+ switch (sipo->mode) {
+ case SIPO_MODE_ANIMATION: /* Animation F-Curve Editor */
+ /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+ sipo->ads->source = (ID *)ac->scene;
+ sipo->ads->filterflag &= ~ADS_FILTER_ONLYDRIVERS;
+
+ ac->datatype = ANIMCONT_FCURVES;
+ ac->data = sipo->ads;
+
+ ac->mode = sipo->mode;
+ return true;
+
+ case SIPO_MODE_DRIVERS: /* Driver F-Curve Editor */
+ /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+ sipo->ads->source = (ID *)ac->scene;
+ sipo->ads->filterflag |= ADS_FILTER_ONLYDRIVERS;
+
+ ac->datatype = ANIMCONT_DRIVERS;
+ ac->data = sipo->ads;
+
+ ac->mode = sipo->mode;
+ return true;
+
+ default: /* unhandled yet */
+ ac->datatype = ANIMCONT_NONE;
+ ac->data = NULL;
+
+ ac->mode = -1;
+ return false;
+ }
}
/* ----------- Private Stuff - NLA Editor ------------- */
@@ -322,20 +321,20 @@ static bool graphedit_get_context(bAnimContext *ac, SpaceGraph *sipo)
/* Get data being edited in Graph Editor (depending on current 'mode') */
static bool nlaedit_get_context(bAnimContext *ac, SpaceNla *snla)
{
- /* init dopesheet data if non-existent (i.e. for old files) */
- if (snla->ads == NULL)
- snla->ads = MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
- ac->ads = snla->ads;
+ /* init dopesheet data if non-existent (i.e. for old files) */
+ if (snla->ads == NULL)
+ snla->ads = MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
+ ac->ads = snla->ads;
- /* sync settings with current view status, then return appropriate data */
- /* update scene-pointer (no need to check for pinning yet, as not implemented) */
- snla->ads->source = (ID *)ac->scene;
- snla->ads->filterflag |= ADS_FILTER_ONLYNLA;
+ /* sync settings with current view status, then return appropriate data */
+ /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+ snla->ads->source = (ID *)ac->scene;
+ snla->ads->filterflag |= ADS_FILTER_ONLYNLA;
- ac->datatype = ANIMCONT_NLA;
- ac->data = snla->ads;
+ ac->datatype = ANIMCONT_NLA;
+ ac->data = snla->ads;
- return true;
+ return true;
}
/* ----------- Public API --------------- */
@@ -346,35 +345,32 @@ static bool nlaedit_get_context(bAnimContext *ac, SpaceNla *snla)
*/
bool ANIM_animdata_context_getdata(bAnimContext *ac)
{
- SpaceLink *sl = ac->sl;
- bool ok = false;
-
- /* context depends on editor we are currently in */
- if (sl) {
- switch (ac->spacetype) {
- case SPACE_ACTION:
- {
- SpaceAction *saction = (SpaceAction *)sl;
- ok = actedit_get_context(ac, saction);
- break;
- }
- case SPACE_GRAPH:
- {
- SpaceGraph *sipo = (SpaceGraph *)sl;
- ok = graphedit_get_context(ac, sipo);
- break;
- }
- case SPACE_NLA:
- {
- SpaceNla *snla = (SpaceNla *)sl;
- ok = nlaedit_get_context(ac, snla);
- break;
- }
- }
- }
-
- /* check if there's any valid data */
- return (ok && ac->data);
+ SpaceLink *sl = ac->sl;
+ bool ok = false;
+
+ /* context depends on editor we are currently in */
+ if (sl) {
+ switch (ac->spacetype) {
+ case SPACE_ACTION: {
+ SpaceAction *saction = (SpaceAction *)sl;
+ ok = actedit_get_context(ac, saction);
+ break;
+ }
+ case SPACE_GRAPH: {
+ SpaceGraph *sipo = (SpaceGraph *)sl;
+ ok = graphedit_get_context(ac, sipo);
+ break;
+ }
+ case SPACE_NLA: {
+ SpaceNla *snla = (SpaceNla *)sl;
+ ok = nlaedit_get_context(ac, snla);
+ break;
+ }
+ }
+ }
+
+ /* check if there's any valid data */
+ return (ok && ac->data);
}
/* Obtain current anim-data context from Blender Context info
@@ -384,37 +380,38 @@ 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);
- SpaceLink *sl = CTX_wm_space_data(C);
- Scene *scene = CTX_data_scene(C);
-
- /* clear old context info */
- if (ac == NULL) return false;
- memset(ac, 0, sizeof(bAnimContext));
-
- /* get useful default context settings from context */
- ac->bmain = bmain;
- ac->scene = scene;
- if (scene) {
- ac->markers = ED_context_get_markers(C);
- }
- ac->depsgraph = CTX_data_depsgraph(C);
- 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->sl = sl;
- ac->spacetype = (sa) ? sa->spacetype : 0;
- ac->regiontype = (ar) ? ar->regiontype : 0;
-
- /* initialise default y-scale factor */
- animedit_get_yscale_factor(ac);
-
- /* get data context info */
- // XXX: if the below fails, try to grab this info from context instead... (to allow for scripting)
- return ANIM_animdata_context_getdata(ac);
+ Main *bmain = CTX_data_main(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ SpaceLink *sl = CTX_wm_space_data(C);
+ Scene *scene = CTX_data_scene(C);
+
+ /* clear old context info */
+ if (ac == NULL)
+ return false;
+ memset(ac, 0, sizeof(bAnimContext));
+
+ /* get useful default context settings from context */
+ ac->bmain = bmain;
+ ac->scene = scene;
+ if (scene) {
+ ac->markers = ED_context_get_markers(C);
+ }
+ ac->depsgraph = CTX_data_depsgraph(C);
+ 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->sl = sl;
+ ac->spacetype = (sa) ? sa->spacetype : 0;
+ ac->regiontype = (ar) ? ar->regiontype : 0;
+
+ /* initialise default y-scale factor */
+ animedit_get_yscale_factor(ac);
+
+ /* get data context info */
+ // XXX: if the below fails, try to grab this info from context instead... (to allow for scripting)
+ return ANIM_animdata_context_getdata(ac);
}
/* ************************************************************ */
@@ -439,24 +436,25 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
* one case below.
*/
#define BEGIN_ANIMFILTER_SUBCHANNELS(expanded_check) \
- { \
- int _filter = filter_mode; \
- short _doSubChannels = 0; \
- if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || (expanded_check)) \
- _doSubChannels = 1; \
- else if (!(filter_mode & ANIMFILTER_LIST_CHANNELS)) \
- _doSubChannels = 2; \
- else { \
- filter_mode |= ANIMFILTER_TMP_PEEK; \
- } \
- \
- { \
- (void) _doSubChannels; \
- }
+ { \
+ int _filter = filter_mode; \
+ short _doSubChannels = 0; \
+ if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || (expanded_check)) \
+ _doSubChannels = 1; \
+ else if (!(filter_mode & ANIMFILTER_LIST_CHANNELS)) \
+ _doSubChannels = 2; \
+ else { \
+ filter_mode |= ANIMFILTER_TMP_PEEK; \
+ } \
+\
+ { \
+ (void)_doSubChannels; \
+ }
/* ... standard sub-channel filtering can go on here now ... */
#define END_ANIMFILTER_SUBCHANNELS \
- filter_mode = _filter; \
- } (void)0
+ filter_mode = _filter; \
+ } \
+ (void)0
/* ............................... */
@@ -500,36 +498,38 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
* 4B) normal keyframes: only when there is an active action
*/
#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, nlaKeysOk, keysOk) \
- { \
- if ((id)->adt) { \
- if (!(filter_mode & ANIMFILTER_CURVE_VISIBLE) || !((id)->adt->flag & ADT_CURVES_NOT_VISIBLE)) { \
- if (filter_mode & ANIMFILTER_ANIMDATA) { \
- adtOk \
- } \
- else if (ads->filterflag & ADS_FILTER_ONLYNLA) { \
- if (ANIMDATA_HAS_NLA(id)) { \
- nlaOk \
- } \
- else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) || ANIMDATA_HAS_KEYS(id)) { \
- nlaOk \
- } \
- } \
- else if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) { \
- if (ANIMDATA_HAS_DRIVERS(id)) { \
- driversOk \
- } \
- } \
- else { \
- if (ANIMDATA_HAS_NLA(id)) { \
- nlaKeysOk \
- } \
- if (ANIMDATA_HAS_KEYS(id)) { \
- keysOk \
- } \
- } \
- } \
- } \
- } (void)0
+ { \
+ if ((id)->adt) { \
+ if (!(filter_mode & ANIMFILTER_CURVE_VISIBLE) || \
+ !((id)->adt->flag & ADT_CURVES_NOT_VISIBLE)) { \
+ if (filter_mode & ANIMFILTER_ANIMDATA) { \
+ adtOk \
+ } \
+ else if (ads->filterflag & ADS_FILTER_ONLYNLA) { \
+ if (ANIMDATA_HAS_NLA(id)) { \
+ nlaOk \
+ } \
+ else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) || ANIMDATA_HAS_KEYS(id)) { \
+ nlaOk \
+ } \
+ } \
+ else if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) { \
+ if (ANIMDATA_HAS_DRIVERS(id)) { \
+ driversOk \
+ } \
+ } \
+ else { \
+ if (ANIMDATA_HAS_NLA(id)) { \
+ nlaKeysOk \
+ } \
+ if (ANIMDATA_HAS_KEYS(id)) { \
+ keysOk \
+ } \
+ } \
+ } \
+ } \
+ } \
+ (void)0
/* ............................... */
@@ -539,32 +539,35 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
* ! This causes the calling function to return early if we're only "peeking" for channels
*/
// XXX: ale_statement stuff is really a hack for one special case. It shouldn't really be needed...
-#define ANIMCHANNEL_NEW_CHANNEL_FULL(channel_data, channel_type, owner_id, fcurve_owner_id, ale_statement) \
- if (filter_mode & ANIMFILTER_TMP_PEEK) \
- return 1; \
- else { \
- bAnimListElem *ale = make_new_animlistelem(channel_data, channel_type, (ID *)owner_id, fcurve_owner_id); \
- if (ale) { \
- BLI_addtail(anim_data, ale); \
- items ++; \
- ale_statement \
- } \
- } (void)0
+#define ANIMCHANNEL_NEW_CHANNEL_FULL( \
+ channel_data, channel_type, owner_id, fcurve_owner_id, ale_statement) \
+ if (filter_mode & ANIMFILTER_TMP_PEEK) \
+ return 1; \
+ else { \
+ bAnimListElem *ale = make_new_animlistelem( \
+ channel_data, channel_type, (ID *)owner_id, fcurve_owner_id); \
+ if (ale) { \
+ BLI_addtail(anim_data, ale); \
+ items++; \
+ ale_statement \
+ } \
+ } \
+ (void)0
#define ANIMCHANNEL_NEW_CHANNEL(channel_data, channel_type, owner_id, fcurve_owner_id) \
- ANIMCHANNEL_NEW_CHANNEL_FULL(channel_data, channel_type, owner_id, fcurve_owner_id, {})
+ ANIMCHANNEL_NEW_CHANNEL_FULL(channel_data, channel_type, owner_id, fcurve_owner_id, {})
/* ............................... */
/* quick macro to test if an anim-channel representing an AnimData block is suitably active */
#define ANIMCHANNEL_ACTIVEOK(ale) \
- (!(filter_mode & ANIMFILTER_ACTIVE) || !(ale->adt) || (ale->adt->flag & ADT_UI_ACTIVE) )
+ (!(filter_mode & ANIMFILTER_ACTIVE) || !(ale->adt) || (ale->adt->flag & ADT_UI_ACTIVE))
/* quick macro to test if an anim-channel (F-Curve, Group, etc.) is selected in an acceptable way */
#define ANIMCHANNEL_SELOK(test_func) \
- (!(filter_mode & (ANIMFILTER_SEL | ANIMFILTER_UNSEL)) || \
- ((filter_mode & ANIMFILTER_SEL) && test_func) || \
- ((filter_mode & ANIMFILTER_UNSEL) && test_func == 0) )
+ (!(filter_mode & (ANIMFILTER_SEL | ANIMFILTER_UNSEL)) || \
+ ((filter_mode & ANIMFILTER_SEL) && test_func) || \
+ ((filter_mode & ANIMFILTER_UNSEL) && test_func == 0))
/* quick macro to test if an anim-channel (F-Curve) is selected ok for editing purposes
* - _SELEDIT means that only selected curves will have visible+editable keyframes
@@ -575,414 +578,386 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
* 3) test_func (i.e. selection test) - only if selected, this test will pass
*/
#define ANIMCHANNEL_SELEDITOK(test_func) \
- (!(filter_mode & ANIMFILTER_SELEDIT) || \
- !(filter_mode & ANIMFILTER_FOREDIT) || \
- (test_func) )
+ (!(filter_mode & ANIMFILTER_SELEDIT) || !(filter_mode & ANIMFILTER_FOREDIT) || (test_func))
/* ----------- 'Private' Stuff --------------- */
/* this function allocates memory for a new bAnimListElem struct for the
* provided animation channel-data.
*/
-static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owner_id, ID *fcurve_owner_id)
+static bAnimListElem *make_new_animlistelem(void *data,
+ short datatype,
+ ID *owner_id,
+ ID *fcurve_owner_id)
{
- bAnimListElem *ale = NULL;
-
- /* only allocate memory if there is data to convert */
- if (data) {
- /* allocate and set generic data */
- ale = MEM_callocN(sizeof(bAnimListElem), "bAnimListElem");
-
- ale->data = data;
- ale->type = datatype;
-
- ale->id = owner_id;
- ale->adt = BKE_animdata_from_id(owner_id);
- ale->fcurve_owner_id = fcurve_owner_id;
-
- /* do specifics */
- switch (datatype) {
- case ANIMTYPE_SUMMARY:
- {
- /* nothing to include for now... this is just a dummy wrappy around all the other channels
- * in the DopeSheet, and gets included at the start of the list
- */
- ale->key_data = NULL;
- ale->datatype = ALE_ALL;
- break;
- }
- case ANIMTYPE_SCENE:
- {
- Scene *sce = (Scene *)data;
-
- ale->flag = sce->flag;
-
- ale->key_data = sce;
- ale->datatype = ALE_SCE;
-
- ale->adt = BKE_animdata_from_id(data);
- break;
- }
- case ANIMTYPE_OBJECT:
- {
- Base *base = (Base *)data;
- Object *ob = base->object;
-
- ale->flag = ob->flag;
-
- ale->key_data = ob;
- ale->datatype = ALE_OB;
-
- ale->adt = BKE_animdata_from_id(&ob->id);
- break;
- }
- case ANIMTYPE_FILLACTD:
- {
- bAction *act = (bAction *)data;
-
- ale->flag = act->flag;
-
- ale->key_data = act;
- ale->datatype = ALE_ACT;
- break;
- }
- case ANIMTYPE_FILLDRIVERS:
- {
- AnimData *adt = (AnimData *)data;
-
- ale->flag = adt->flag;
-
- // XXX... drivers don't show summary for now
- ale->key_data = NULL;
- ale->datatype = ALE_NONE;
- break;
- }
- case ANIMTYPE_DSMAT:
- {
- Material *ma = (Material *)data;
- AnimData *adt = ma->adt;
-
- ale->flag = FILTER_MAT_OBJD(ma);
-
- ale->key_data = (adt) ? adt->action : NULL;
- ale->datatype = ALE_ACT;
-
- ale->adt = BKE_animdata_from_id(data);
- break;
- }
- case ANIMTYPE_DSLAM:
- {
- Light *la = (Light *)data;
- AnimData *adt = la->adt;
-
- ale->flag = FILTER_LAM_OBJD(la);
-
- ale->key_data = (adt) ? adt->action : NULL;
- ale->datatype = ALE_ACT;
-
- ale->adt = BKE_animdata_from_id(data);
- break;
- }
- case ANIMTYPE_DSCAM:
- {
- Camera *ca = (Camera *)data;
- AnimData *adt = ca->adt;
-
- ale->flag = FILTER_CAM_OBJD(ca);
-
- ale->key_data = (adt) ? adt->action : NULL;
- ale->datatype = ALE_ACT;
-
- ale->adt = BKE_animdata_from_id(data);
- break;
- }
- case ANIMTYPE_DSCACHEFILE:
- {
- CacheFile *cache_file = (CacheFile *)data;
- AnimData *adt = cache_file->adt;
-
- ale->flag = FILTER_CACHEFILE_OBJD(cache_file);
-
- ale->key_data = (adt) ? adt->action : NULL;
- ale->datatype = ALE_ACT;
-
- ale->adt = BKE_animdata_from_id(data);
- break;
- }
- case ANIMTYPE_DSCUR:
- {
- Curve *cu = (Curve *)data;
- AnimData *adt = cu->adt;
-
- ale->flag = FILTER_CUR_OBJD(cu);
-
- ale->key_data = (adt) ? adt->action : NULL;
- ale->datatype = ALE_ACT;
-
- ale->adt = BKE_animdata_from_id(data);
- break;
- }
- case ANIMTYPE_DSARM:
- {
- bArmature *arm = (bArmature *)data;
- AnimData *adt = arm->adt;
-
- ale->flag = FILTER_ARM_OBJD(arm);
-
- ale->key_data = (adt) ? adt->action : NULL;
- ale->datatype = ALE_ACT;
-
- ale->adt = BKE_animdata_from_id(data);
- break;
- }
- case ANIMTYPE_DSMESH:
- {
- Mesh *me = (Mesh *)data;
- AnimData *adt = me->adt;
-
- ale->flag = FILTER_MESH_OBJD(me);
-
- ale->key_data = (adt) ? adt->action : NULL;
- ale->datatype = ALE_ACT;
-
- ale->adt = BKE_animdata_from_id(data);
- break;
- }
- case ANIMTYPE_DSLAT:
- {
- Lattice *lt = (Lattice *)data;
- AnimData *adt = lt->adt;
-
- ale->flag = FILTER_LATTICE_OBJD(lt);
-
- ale->key_data = (adt) ? adt->action : NULL;
- ale->datatype = ALE_ACT;
-
- ale->adt = BKE_animdata_from_id(data);
- break;
- }
- case ANIMTYPE_DSSPK:
- {
- Speaker *spk = (Speaker *)data;
- AnimData *adt = spk->adt;
-
- ale->flag = FILTER_SPK_OBJD(spk);
-
- 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;
-
- ale->flag = FILTER_SKE_OBJD(key);
-
- ale->key_data = (adt) ? adt->action : NULL;
- ale->datatype = ALE_ACT;
-
- ale->adt = BKE_animdata_from_id(data);
- break;
- }
- case ANIMTYPE_DSWOR:
- {
- World *wo = (World *)data;
- AnimData *adt = wo->adt;
-
- ale->flag = FILTER_WOR_SCED(wo);
-
- ale->key_data = (adt) ? adt->action : NULL;
- ale->datatype = ALE_ACT;
-
- ale->adt = BKE_animdata_from_id(data);
- break;
- }
- case ANIMTYPE_DSNTREE:
- {
- bNodeTree *ntree = (bNodeTree *)data;
- AnimData *adt = ntree->adt;
-
- ale->flag = FILTER_NTREE_DATA(ntree);
-
- ale->key_data = (adt) ? adt->action : NULL;
- ale->datatype = ALE_ACT;
-
- ale->adt = BKE_animdata_from_id(data);
- break;
- }
- case ANIMTYPE_DSLINESTYLE:
- {
- FreestyleLineStyle *linestyle = (FreestyleLineStyle *)data;
- AnimData *adt = linestyle->adt;
-
- ale->flag = FILTER_LS_SCED(linestyle);
-
- ale->key_data = (adt) ? adt->action : NULL;
- ale->datatype = ALE_ACT;
-
- ale->adt = BKE_animdata_from_id(data);
- break;
- }
- case ANIMTYPE_DSPART:
- {
- ParticleSettings *part = (ParticleSettings *)ale->data;
- AnimData *adt = part->adt;
-
- ale->flag = FILTER_PART_OBJD(part);
-
- ale->key_data = (adt) ? adt->action : NULL;
- ale->datatype = ALE_ACT;
-
- ale->adt = BKE_animdata_from_id(data);
- break;
- }
- case ANIMTYPE_DSTEX:
- {
- Tex *tex = (Tex *)data;
- AnimData *adt = tex->adt;
-
- ale->flag = FILTER_TEX_DATA(tex);
-
- ale->key_data = (adt) ? adt->action : NULL;
- ale->datatype = ALE_ACT;
-
- ale->adt = BKE_animdata_from_id(data);
- break;
- }
- case ANIMTYPE_DSGPENCIL:
- {
- bGPdata *gpd = (bGPdata *)data;
- AnimData *adt = gpd->adt;
-
- /* NOTE: we just reuse the same expand filter for this case */
- ale->flag = EXPANDED_GPD(gpd);
-
- // XXX: currently, this is only used for access to its animation data
- ale->key_data = (adt) ? adt->action : NULL;
- ale->datatype = ALE_ACT;
-
- ale->adt = BKE_animdata_from_id(data);
- break;
- }
- case ANIMTYPE_DSMCLIP:
- {
- MovieClip *clip = (MovieClip *)data;
- AnimData *adt = clip->adt;
-
- ale->flag = EXPANDED_MCLIP(clip);
-
- ale->key_data = (adt) ? adt->action : NULL;
- ale->datatype = ALE_ACT;
-
- ale->adt = BKE_animdata_from_id(data);
- break;
- }
- case ANIMTYPE_NLACONTROLS:
- {
- AnimData *adt = (AnimData *)data;
-
- ale->flag = adt->flag;
-
- ale->key_data = NULL;
- ale->datatype = ALE_NONE;
- break;
- }
- case ANIMTYPE_GROUP:
- {
- bActionGroup *agrp = (bActionGroup *)data;
-
- ale->flag = agrp->flag;
-
- ale->key_data = NULL;
- ale->datatype = ALE_GROUP;
- break;
- }
- case ANIMTYPE_FCURVE:
- case ANIMTYPE_NLACURVE: /* practically the same as ANIMTYPE_FCURVE.
- * Differences are applied post-creation */
- {
- FCurve *fcu = (FCurve *)data;
-
- ale->flag = fcu->flag;
-
- ale->key_data = fcu;
- ale->datatype = ALE_FCURVE;
- break;
- }
- case ANIMTYPE_SHAPEKEY:
- {
- KeyBlock *kb = (KeyBlock *)data;
- Key *key = (Key *)ale->id;
-
- ale->flag = kb->flag;
-
- /* whether we have keyframes depends on whether there is a Key block to find it from */
- if (key) {
- /* index of shapekey is defined by place in key's list */
- ale->index = BLI_findindex(&key->block, kb);
-
- /* the corresponding keyframes are from the animdata */
- if (ale->adt && ale->adt->action) {
- bAction *act = ale->adt->action;
- char *rna_path = BKE_keyblock_curval_rnapath_get(key, kb);
-
- /* try to find the F-Curve which corresponds to this exactly,
- * then free the MEM_alloc'd string
- */
- if (rna_path) {
- ale->key_data = (void *)list_find_fcurve(&act->curves, rna_path, 0);
- MEM_freeN(rna_path);
- }
- }
- ale->datatype = (ale->key_data) ? ALE_FCURVE : ALE_NONE;
- }
- break;
- }
- case ANIMTYPE_GPLAYER:
- {
- bGPDlayer *gpl = (bGPDlayer *)data;
-
- ale->flag = gpl->flag;
-
- ale->key_data = NULL;
- ale->datatype = ALE_GPFRAME;
- break;
- }
- case ANIMTYPE_MASKLAYER:
- {
- MaskLayer *masklay = (MaskLayer *)data;
-
- ale->flag = masklay->flag;
-
- ale->key_data = NULL;
- ale->datatype = ALE_MASKLAY;
- break;
- }
- case ANIMTYPE_NLATRACK:
- {
- NlaTrack *nlt = (NlaTrack *)data;
-
- ale->flag = nlt->flag;
-
- ale->key_data = &nlt->strips;
- ale->datatype = ALE_NLASTRIP;
- break;
- }
- case ANIMTYPE_NLAACTION:
- {
- /* nothing to include for now... nothing editable from NLA-perspective here */
- ale->key_data = NULL;
- ale->datatype = ALE_NONE;
- break;
- }
- }
- }
-
- /* return created datatype */
- return ale;
+ bAnimListElem *ale = NULL;
+
+ /* only allocate memory if there is data to convert */
+ if (data) {
+ /* allocate and set generic data */
+ ale = MEM_callocN(sizeof(bAnimListElem), "bAnimListElem");
+
+ ale->data = data;
+ ale->type = datatype;
+
+ ale->id = owner_id;
+ ale->adt = BKE_animdata_from_id(owner_id);
+ ale->fcurve_owner_id = fcurve_owner_id;
+
+ /* do specifics */
+ switch (datatype) {
+ case ANIMTYPE_SUMMARY: {
+ /* nothing to include for now... this is just a dummy wrappy around all the other channels
+ * in the DopeSheet, and gets included at the start of the list
+ */
+ ale->key_data = NULL;
+ ale->datatype = ALE_ALL;
+ break;
+ }
+ case ANIMTYPE_SCENE: {
+ Scene *sce = (Scene *)data;
+
+ ale->flag = sce->flag;
+
+ ale->key_data = sce;
+ ale->datatype = ALE_SCE;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_OBJECT: {
+ Base *base = (Base *)data;
+ Object *ob = base->object;
+
+ ale->flag = ob->flag;
+
+ ale->key_data = ob;
+ ale->datatype = ALE_OB;
+
+ ale->adt = BKE_animdata_from_id(&ob->id);
+ break;
+ }
+ case ANIMTYPE_FILLACTD: {
+ bAction *act = (bAction *)data;
+
+ ale->flag = act->flag;
+
+ ale->key_data = act;
+ ale->datatype = ALE_ACT;
+ break;
+ }
+ case ANIMTYPE_FILLDRIVERS: {
+ AnimData *adt = (AnimData *)data;
+
+ ale->flag = adt->flag;
+
+ // XXX... drivers don't show summary for now
+ ale->key_data = NULL;
+ ale->datatype = ALE_NONE;
+ break;
+ }
+ case ANIMTYPE_DSMAT: {
+ Material *ma = (Material *)data;
+ AnimData *adt = ma->adt;
+
+ ale->flag = FILTER_MAT_OBJD(ma);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_DSLAM: {
+ Light *la = (Light *)data;
+ AnimData *adt = la->adt;
+
+ ale->flag = FILTER_LAM_OBJD(la);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_DSCAM: {
+ Camera *ca = (Camera *)data;
+ AnimData *adt = ca->adt;
+
+ ale->flag = FILTER_CAM_OBJD(ca);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_DSCACHEFILE: {
+ CacheFile *cache_file = (CacheFile *)data;
+ AnimData *adt = cache_file->adt;
+
+ ale->flag = FILTER_CACHEFILE_OBJD(cache_file);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_DSCUR: {
+ Curve *cu = (Curve *)data;
+ AnimData *adt = cu->adt;
+
+ ale->flag = FILTER_CUR_OBJD(cu);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_DSARM: {
+ bArmature *arm = (bArmature *)data;
+ AnimData *adt = arm->adt;
+
+ ale->flag = FILTER_ARM_OBJD(arm);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_DSMESH: {
+ Mesh *me = (Mesh *)data;
+ AnimData *adt = me->adt;
+
+ ale->flag = FILTER_MESH_OBJD(me);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_DSLAT: {
+ Lattice *lt = (Lattice *)data;
+ AnimData *adt = lt->adt;
+
+ ale->flag = FILTER_LATTICE_OBJD(lt);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_DSSPK: {
+ Speaker *spk = (Speaker *)data;
+ AnimData *adt = spk->adt;
+
+ ale->flag = FILTER_SPK_OBJD(spk);
+
+ 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;
+
+ ale->flag = FILTER_SKE_OBJD(key);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_DSWOR: {
+ World *wo = (World *)data;
+ AnimData *adt = wo->adt;
+
+ ale->flag = FILTER_WOR_SCED(wo);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_DSNTREE: {
+ bNodeTree *ntree = (bNodeTree *)data;
+ AnimData *adt = ntree->adt;
+
+ ale->flag = FILTER_NTREE_DATA(ntree);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_DSLINESTYLE: {
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)data;
+ AnimData *adt = linestyle->adt;
+
+ ale->flag = FILTER_LS_SCED(linestyle);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_DSPART: {
+ ParticleSettings *part = (ParticleSettings *)ale->data;
+ AnimData *adt = part->adt;
+
+ ale->flag = FILTER_PART_OBJD(part);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_DSTEX: {
+ Tex *tex = (Tex *)data;
+ AnimData *adt = tex->adt;
+
+ ale->flag = FILTER_TEX_DATA(tex);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_DSGPENCIL: {
+ bGPdata *gpd = (bGPdata *)data;
+ AnimData *adt = gpd->adt;
+
+ /* NOTE: we just reuse the same expand filter for this case */
+ ale->flag = EXPANDED_GPD(gpd);
+
+ // XXX: currently, this is only used for access to its animation data
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_DSMCLIP: {
+ MovieClip *clip = (MovieClip *)data;
+ AnimData *adt = clip->adt;
+
+ ale->flag = EXPANDED_MCLIP(clip);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_NLACONTROLS: {
+ AnimData *adt = (AnimData *)data;
+
+ ale->flag = adt->flag;
+
+ ale->key_data = NULL;
+ ale->datatype = ALE_NONE;
+ break;
+ }
+ case ANIMTYPE_GROUP: {
+ bActionGroup *agrp = (bActionGroup *)data;
+
+ ale->flag = agrp->flag;
+
+ ale->key_data = NULL;
+ ale->datatype = ALE_GROUP;
+ break;
+ }
+ case ANIMTYPE_FCURVE:
+ case ANIMTYPE_NLACURVE: /* practically the same as ANIMTYPE_FCURVE.
+ * Differences are applied post-creation */
+ {
+ FCurve *fcu = (FCurve *)data;
+
+ ale->flag = fcu->flag;
+
+ ale->key_data = fcu;
+ ale->datatype = ALE_FCURVE;
+ break;
+ }
+ case ANIMTYPE_SHAPEKEY: {
+ KeyBlock *kb = (KeyBlock *)data;
+ Key *key = (Key *)ale->id;
+
+ ale->flag = kb->flag;
+
+ /* whether we have keyframes depends on whether there is a Key block to find it from */
+ if (key) {
+ /* index of shapekey is defined by place in key's list */
+ ale->index = BLI_findindex(&key->block, kb);
+
+ /* the corresponding keyframes are from the animdata */
+ if (ale->adt && ale->adt->action) {
+ bAction *act = ale->adt->action;
+ char *rna_path = BKE_keyblock_curval_rnapath_get(key, kb);
+
+ /* try to find the F-Curve which corresponds to this exactly,
+ * then free the MEM_alloc'd string
+ */
+ if (rna_path) {
+ ale->key_data = (void *)list_find_fcurve(&act->curves, rna_path, 0);
+ MEM_freeN(rna_path);
+ }
+ }
+ ale->datatype = (ale->key_data) ? ALE_FCURVE : ALE_NONE;
+ }
+ break;
+ }
+ case ANIMTYPE_GPLAYER: {
+ bGPDlayer *gpl = (bGPDlayer *)data;
+
+ ale->flag = gpl->flag;
+
+ ale->key_data = NULL;
+ ale->datatype = ALE_GPFRAME;
+ break;
+ }
+ case ANIMTYPE_MASKLAYER: {
+ MaskLayer *masklay = (MaskLayer *)data;
+
+ ale->flag = masklay->flag;
+
+ ale->key_data = NULL;
+ ale->datatype = ALE_MASKLAY;
+ break;
+ }
+ case ANIMTYPE_NLATRACK: {
+ NlaTrack *nlt = (NlaTrack *)data;
+
+ ale->flag = nlt->flag;
+
+ ale->key_data = &nlt->strips;
+ ale->datatype = ALE_NLASTRIP;
+ break;
+ }
+ case ANIMTYPE_NLAACTION: {
+ /* nothing to include for now... nothing editable from NLA-perspective here */
+ ale->key_data = NULL;
+ ale->datatype = ALE_NONE;
+ break;
+ }
+ }
+ }
+
+ /* return created datatype */
+ return ale;
}
/* ----------------------------------------- */
@@ -992,154 +967,160 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
*/
static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id, int filter_mode)
{
- if (fcu->grp != NULL && fcu->grp->flag & ADT_CURVES_ALWAYS_VISIBLE) {
- return false;
- }
- /* hidden items should be skipped if we only care about visible data,
- * but we aren't interested in hidden stuff */
- const bool skip_hidden = (filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN);
-
- if (GS(owner_id->name) == ID_OB) {
- Object *ob = (Object *)owner_id;
-
- /* only consider if F-Curve involves pose.bones */
- if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones")) {
- bPoseChannel *pchan;
- char *bone_name;
-
- /* get bone-name, and check if this bone is selected */
- bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
- pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
- if (bone_name) MEM_freeN(bone_name);
-
- /* check whether to continue or skip */
- if ((pchan) && (pchan->bone)) {
- /* if only visible channels, skip if bone not visible unless user wants channels from hidden data too */
- if (skip_hidden) {
- bArmature *arm = (bArmature *)ob->data;
-
- /* skipping - not visible on currently visible layers */
- if ((arm->layer & pchan->bone->layer) == 0)
- return true;
- /* skipping - is currently hidden */
- if (pchan->bone->flag & BONE_HIDDEN_P)
- return true;
- }
-
- /* can only add this F-Curve if it is selected */
- if (ads->filterflag & ADS_FILTER_ONLYSEL) {
- if ((pchan->bone->flag & BONE_SELECTED) == 0)
- return true;
- }
- }
- }
- }
- else if (GS(owner_id->name) == ID_SCE) {
- Scene *scene = (Scene *)owner_id;
-
- /* only consider if F-Curve involves sequence_editor.sequences */
- if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) {
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq = NULL;
- char *seq_name;
-
- if (ed) {
- /* get strip name, and check if this strip is selected */
- seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all[");
- seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, false);
- if (seq_name) MEM_freeN(seq_name);
- }
-
- /* can only add this F-Curve if it is selected */
- if (ads->filterflag & ADS_FILTER_ONLYSEL) {
- if ((seq == NULL) || (seq->flag & SELECT) == 0)
- return true;
- }
- }
- }
- else if (GS(owner_id->name) == ID_NT) {
- bNodeTree *ntree = (bNodeTree *)owner_id;
-
- /* check for selected nodes */
- if ((fcu->rna_path) && strstr(fcu->rna_path, "nodes")) {
- bNode *node;
- char *node_name;
-
- /* get strip name, and check if this strip is selected */
- node_name = BLI_str_quoted_substrN(fcu->rna_path, "nodes[");
- node = nodeFindNodebyName(ntree, node_name);
- if (node_name) MEM_freeN(node_name);
-
- /* can only add this F-Curve if it is selected */
- if (ads->filterflag & ADS_FILTER_ONLYSEL) {
- if ((node) && (node->flag & NODE_SELECT) == 0)
- return true;
- }
- }
- }
-
- return false;
+ if (fcu->grp != NULL && fcu->grp->flag & ADT_CURVES_ALWAYS_VISIBLE) {
+ return false;
+ }
+ /* hidden items should be skipped if we only care about visible data,
+ * but we aren't interested in hidden stuff */
+ const bool skip_hidden = (filter_mode & ANIMFILTER_DATA_VISIBLE) &&
+ !(ads->filterflag & ADS_FILTER_INCL_HIDDEN);
+
+ if (GS(owner_id->name) == ID_OB) {
+ Object *ob = (Object *)owner_id;
+
+ /* only consider if F-Curve involves pose.bones */
+ if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones")) {
+ bPoseChannel *pchan;
+ char *bone_name;
+
+ /* get bone-name, and check if this bone is selected */
+ bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
+ pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
+ if (bone_name)
+ MEM_freeN(bone_name);
+
+ /* check whether to continue or skip */
+ if ((pchan) && (pchan->bone)) {
+ /* if only visible channels, skip if bone not visible unless user wants channels from hidden data too */
+ if (skip_hidden) {
+ bArmature *arm = (bArmature *)ob->data;
+
+ /* skipping - not visible on currently visible layers */
+ if ((arm->layer & pchan->bone->layer) == 0)
+ return true;
+ /* skipping - is currently hidden */
+ if (pchan->bone->flag & BONE_HIDDEN_P)
+ return true;
+ }
+
+ /* can only add this F-Curve if it is selected */
+ if (ads->filterflag & ADS_FILTER_ONLYSEL) {
+ if ((pchan->bone->flag & BONE_SELECTED) == 0)
+ return true;
+ }
+ }
+ }
+ }
+ else if (GS(owner_id->name) == ID_SCE) {
+ Scene *scene = (Scene *)owner_id;
+
+ /* only consider if F-Curve involves sequence_editor.sequences */
+ if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) {
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq = NULL;
+ char *seq_name;
+
+ if (ed) {
+ /* get strip name, and check if this strip is selected */
+ seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all[");
+ seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, false);
+ if (seq_name)
+ MEM_freeN(seq_name);
+ }
+
+ /* can only add this F-Curve if it is selected */
+ if (ads->filterflag & ADS_FILTER_ONLYSEL) {
+ if ((seq == NULL) || (seq->flag & SELECT) == 0)
+ return true;
+ }
+ }
+ }
+ else if (GS(owner_id->name) == ID_NT) {
+ bNodeTree *ntree = (bNodeTree *)owner_id;
+
+ /* check for selected nodes */
+ if ((fcu->rna_path) && strstr(fcu->rna_path, "nodes")) {
+ bNode *node;
+ char *node_name;
+
+ /* get strip name, and check if this strip is selected */
+ node_name = BLI_str_quoted_substrN(fcu->rna_path, "nodes[");
+ node = nodeFindNodebyName(ntree, node_name);
+ if (node_name)
+ MEM_freeN(node_name);
+
+ /* can only add this F-Curve if it is selected */
+ if (ads->filterflag & ADS_FILTER_ONLYSEL) {
+ if ((node) && (node->flag & NODE_SELECT) == 0)
+ return true;
+ }
+ }
+ }
+
+ return false;
}
/* Helper for name-based filtering - Perform "partial/fuzzy matches" (as in 80a7efd) */
static bool name_matches_dopesheet_filter(bDopeSheet *ads, char *name)
{
- if (ads->flag & ADS_FLAG_FUZZY_NAMES) {
- /* full fuzzy, multi-word, case insensitive matches */
- const size_t str_len = strlen(ads->searchstr);
- 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(ads->searchstr, str_len, ' ', words, words_max);
- bool found = false;
-
- /* match name against all search words */
- for (int index = 0; index < words_len; index++) {
- if (BLI_strncasestr(name, ads->searchstr + words[index][0], words[index][1])) {
- found = true;
- break;
- }
- }
-
- /* if we have a match somewhere, this returns true */
- return found;
- }
- else {
- /* fallback/default - just case insensitive, but starts from start of word */
- return BLI_strcasestr(name, ads->searchstr) != NULL;
- }
+ if (ads->flag & ADS_FLAG_FUZZY_NAMES) {
+ /* full fuzzy, multi-word, case insensitive matches */
+ const size_t str_len = strlen(ads->searchstr);
+ 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(
+ ads->searchstr, str_len, ' ', words, words_max);
+ bool found = false;
+
+ /* match name against all search words */
+ for (int index = 0; index < words_len; index++) {
+ if (BLI_strncasestr(name, ads->searchstr + words[index][0], words[index][1])) {
+ found = true;
+ break;
+ }
+ }
+
+ /* if we have a match somewhere, this returns true */
+ return found;
+ }
+ else {
+ /* fallback/default - just case insensitive, but starts from start of word */
+ return BLI_strcasestr(name, ads->searchstr) != NULL;
+ }
}
/* (Display-)Name-based F-Curve filtering
* NOTE: when this function returns true, the F-Curve is to be skipped
*/
-static bool skip_fcurve_with_name(bDopeSheet *ads, FCurve *fcu, eAnim_ChannelType channel_type, void *owner, ID *owner_id)
+static bool skip_fcurve_with_name(
+ bDopeSheet *ads, FCurve *fcu, eAnim_ChannelType channel_type, void *owner, ID *owner_id)
{
- bAnimListElem ale_dummy = {NULL};
- const bAnimChannelType *acf;
-
- /* create a dummy wrapper for the F-Curve, so we can get typeinfo for it */
- ale_dummy.type = channel_type;
- ale_dummy.owner = owner;
- ale_dummy.id = owner_id;
- ale_dummy.data = fcu;
-
- /* get type info for channel */
- acf = ANIM_channel_get_typeinfo(&ale_dummy);
- if (acf && acf->name) {
- char name[256]; /* hopefully this will be enough! */
-
- /* get name */
- acf->name(&ale_dummy, name);
-
- /* check for partial match with the match string, assuming case insensitive filtering
- * if match, this channel shouldn't be ignored!
- */
- return !name_matches_dopesheet_filter(ads, name);
- }
-
- /* just let this go... */
- return true;
+ bAnimListElem ale_dummy = {NULL};
+ const bAnimChannelType *acf;
+
+ /* create a dummy wrapper for the F-Curve, so we can get typeinfo for it */
+ ale_dummy.type = channel_type;
+ ale_dummy.owner = owner;
+ ale_dummy.id = owner_id;
+ ale_dummy.data = fcu;
+
+ /* get type info for channel */
+ acf = ANIM_channel_get_typeinfo(&ale_dummy);
+ if (acf && acf->name) {
+ char name[256]; /* hopefully this will be enough! */
+
+ /* get name */
+ acf->name(&ale_dummy, name);
+
+ /* check for partial match with the match string, assuming case insensitive filtering
+ * if match, this channel shouldn't be ignored!
+ */
+ return !name_matches_dopesheet_filter(ads, name);
+ }
+
+ /* just let this go... */
+ return true;
}
/**
@@ -1149,247 +1130,271 @@ static bool skip_fcurve_with_name(bDopeSheet *ads, FCurve *fcu, eAnim_ChannelTyp
*/
static bool fcurve_has_errors(FCurve *fcu)
{
- /* F-Curve disabled - path eval error */
- if (fcu->flag & FCURVE_DISABLED) {
- return true;
- }
-
- /* driver? */
- if (fcu->driver) {
- ChannelDriver *driver = fcu->driver;
- DriverVar *dvar;
-
- /* error flag on driver usually means that there is an error
- * BUT this may not hold with PyDrivers as this flag gets cleared
- * if no critical errors prevent the driver from working...
- */
- if (driver->flag & DRIVER_FLAG_INVALID)
- return true;
-
- /* check variables for other things that need linting... */
- // TODO: maybe it would be more efficient just to have a quick flag for this?
- for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
- DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar)
- {
- if (dtar->flag & DTAR_FLAG_INVALID)
- return true;
- }
- DRIVER_TARGETS_LOOPER_END;
- }
- }
-
- /* no errors found */
- return false;
+ /* F-Curve disabled - path eval error */
+ if (fcu->flag & FCURVE_DISABLED) {
+ return true;
+ }
+
+ /* driver? */
+ if (fcu->driver) {
+ ChannelDriver *driver = fcu->driver;
+ DriverVar *dvar;
+
+ /* error flag on driver usually means that there is an error
+ * BUT this may not hold with PyDrivers as this flag gets cleared
+ * if no critical errors prevent the driver from working...
+ */
+ if (driver->flag & DRIVER_FLAG_INVALID)
+ return true;
+
+ /* check variables for other things that need linting... */
+ // TODO: maybe it would be more efficient just to have a quick flag for this?
+ for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
+ DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
+ if (dtar->flag & DTAR_FLAG_INVALID)
+ return true;
+ }
+ DRIVER_TARGETS_LOOPER_END;
+ }
+ }
+
+ /* no errors found */
+ return false;
}
/* find the next F-Curve that is usable for inclusion */
-static FCurve *animfilter_fcurve_next(bDopeSheet *ads, FCurve *first, eAnim_ChannelType channel_type, int filter_mode, void *owner, ID *owner_id)
+static FCurve *animfilter_fcurve_next(bDopeSheet *ads,
+ FCurve *first,
+ eAnim_ChannelType channel_type,
+ int filter_mode,
+ void *owner,
+ ID *owner_id)
{
- bActionGroup *grp = (channel_type == ANIMTYPE_FCURVE) ? owner : NULL;
- FCurve *fcu = NULL;
-
- /* loop over F-Curves - assume that the caller of this has already checked that these should be included
- * NOTE: we need to check if the F-Curves belong to the same group, as this gets called for groups too...
- */
- for (fcu = first; ((fcu) && (fcu->grp == grp)); fcu = fcu->next) {
- /* special exception for Pose-Channel/Sequence-Strip/Node Based F-Curves:
- * - the 'Only Selected' and 'Include Hidden' data filters should be applied to sub-ID data which
- * can be independently selected/hidden, such as Pose-Channels, Sequence Strips, and Nodes.
- * Since these checks were traditionally done as first check for objects, we do the same here
- * - we currently use an 'approximate' method for getting these F-Curves that doesn't require
- * carefully checking the entire path
- * - this will also affect things like Drivers, and also works for Bone Constraints
- */
- if (ads && owner_id) {
- if ((filter_mode & ANIMFILTER_TMP_IGNORE_ONLYSEL) == 0) {
- if ((ads->filterflag & ADS_FILTER_ONLYSEL) || (ads->filterflag & ADS_FILTER_INCL_HIDDEN) == 0) {
- if (skip_fcurve_selected_data(ads, fcu, owner_id, filter_mode))
- continue;
- }
- }
- }
-
- /* only include if visible (Graph Editor check, not channels check) */
- if (!(filter_mode & ANIMFILTER_CURVE_VISIBLE) || (fcu->flag & FCURVE_VISIBLE)) {
- /* only work with this channel and its subchannels if it is editable */
- if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_FCU(fcu)) {
- /* only include this curve if selected in a way consistent with the filtering requirements */
- if (ANIMCHANNEL_SELOK(SEL_FCU(fcu)) && ANIMCHANNEL_SELEDITOK(SEL_FCU(fcu))) {
- /* only include if this curve is active */
- if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) {
- /* name based filtering... */
- if ( ((ads) && (ads->searchstr[0] != '\0')) && (owner_id) ) {
- if (skip_fcurve_with_name(ads, fcu, channel_type, owner, owner_id))
- continue;
- }
-
- /* error-based filtering... */
- if ((ads) && (ads->filterflag & ADS_FILTER_ONLY_ERRORS)) {
- /* skip if no errors... */
- if (fcurve_has_errors(fcu) == false)
- continue;
- }
-
- /* this F-Curve can be used, so return it */
- return fcu;
- }
- }
- }
- }
- }
-
- /* no (more) F-Curves from the list are suitable... */
- return NULL;
+ bActionGroup *grp = (channel_type == ANIMTYPE_FCURVE) ? owner : NULL;
+ FCurve *fcu = NULL;
+
+ /* loop over F-Curves - assume that the caller of this has already checked that these should be included
+ * NOTE: we need to check if the F-Curves belong to the same group, as this gets called for groups too...
+ */
+ for (fcu = first; ((fcu) && (fcu->grp == grp)); fcu = fcu->next) {
+ /* special exception for Pose-Channel/Sequence-Strip/Node Based F-Curves:
+ * - the 'Only Selected' and 'Include Hidden' data filters should be applied to sub-ID data which
+ * can be independently selected/hidden, such as Pose-Channels, Sequence Strips, and Nodes.
+ * Since these checks were traditionally done as first check for objects, we do the same here
+ * - we currently use an 'approximate' method for getting these F-Curves that doesn't require
+ * carefully checking the entire path
+ * - this will also affect things like Drivers, and also works for Bone Constraints
+ */
+ if (ads && owner_id) {
+ if ((filter_mode & ANIMFILTER_TMP_IGNORE_ONLYSEL) == 0) {
+ if ((ads->filterflag & ADS_FILTER_ONLYSEL) ||
+ (ads->filterflag & ADS_FILTER_INCL_HIDDEN) == 0) {
+ if (skip_fcurve_selected_data(ads, fcu, owner_id, filter_mode))
+ continue;
+ }
+ }
+ }
+
+ /* only include if visible (Graph Editor check, not channels check) */
+ if (!(filter_mode & ANIMFILTER_CURVE_VISIBLE) || (fcu->flag & FCURVE_VISIBLE)) {
+ /* only work with this channel and its subchannels if it is editable */
+ if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_FCU(fcu)) {
+ /* only include this curve if selected in a way consistent with the filtering requirements */
+ if (ANIMCHANNEL_SELOK(SEL_FCU(fcu)) && ANIMCHANNEL_SELEDITOK(SEL_FCU(fcu))) {
+ /* only include if this curve is active */
+ if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) {
+ /* name based filtering... */
+ if (((ads) && (ads->searchstr[0] != '\0')) && (owner_id)) {
+ if (skip_fcurve_with_name(ads, fcu, channel_type, owner, owner_id))
+ continue;
+ }
+
+ /* error-based filtering... */
+ if ((ads) && (ads->filterflag & ADS_FILTER_ONLY_ERRORS)) {
+ /* skip if no errors... */
+ if (fcurve_has_errors(fcu) == false)
+ continue;
+ }
+
+ /* this F-Curve can be used, so return it */
+ return fcu;
+ }
+ }
+ }
+ }
+ }
+
+ /* no (more) F-Curves from the list are suitable... */
+ return NULL;
}
-static size_t animfilter_fcurves(ListBase *anim_data, bDopeSheet *ads,
- FCurve *first, eAnim_ChannelType fcurve_type,
+static size_t animfilter_fcurves(ListBase *anim_data,
+ bDopeSheet *ads,
+ FCurve *first,
+ eAnim_ChannelType fcurve_type,
int filter_mode,
- void *owner, ID *owner_id, ID *fcurve_owner_id)
+ void *owner,
+ ID *owner_id,
+ ID *fcurve_owner_id)
{
- FCurve *fcu;
- size_t items = 0;
-
- /* loop over every F-Curve able to be included
- * - this for-loop works like this:
- * 1) the starting F-Curve is assigned to the fcu pointer so that we have a starting point to search from
- * 2) the first valid F-Curve to start from (which may include the one given as 'first') in the remaining
- * list of F-Curves is found, and verified to be non-null
- * 3) the F-Curve referenced by fcu pointer is added to the list
- * 4) the fcu pointer is set to the F-Curve after the one we just added, so that we can keep going through
- * the rest of the F-Curve list without an eternal loop. Back to step 2 :)
- */
- for (fcu = first; ( (fcu = animfilter_fcurve_next(ads, fcu, fcurve_type, filter_mode, owner, owner_id)) ); fcu = fcu->next) {
- if (UNLIKELY(fcurve_type == ANIMTYPE_NLACURVE)) {
- /* NLA Control Curve - Basically the same as normal F-Curves,
- * except we need to set some stuff differently */
- ANIMCHANNEL_NEW_CHANNEL_FULL(fcu, ANIMTYPE_NLACURVE, owner_id, fcurve_owner_id, {
- ale->owner = owner; /* strip */
- ale->adt = NULL; /* to prevent time mapping from causing problems */
- });
- }
- else {
- /* Normal FCurve */
- ANIMCHANNEL_NEW_CHANNEL(fcu, ANIMTYPE_FCURVE, owner_id, fcurve_owner_id);
- }
- }
-
- /* return the number of items added to the list */
- return items;
+ FCurve *fcu;
+ size_t items = 0;
+
+ /* loop over every F-Curve able to be included
+ * - this for-loop works like this:
+ * 1) the starting F-Curve is assigned to the fcu pointer so that we have a starting point to search from
+ * 2) the first valid F-Curve to start from (which may include the one given as 'first') in the remaining
+ * list of F-Curves is found, and verified to be non-null
+ * 3) the F-Curve referenced by fcu pointer is added to the list
+ * 4) the fcu pointer is set to the F-Curve after the one we just added, so that we can keep going through
+ * the rest of the F-Curve list without an eternal loop. Back to step 2 :)
+ */
+ for (fcu = first;
+ ((fcu = animfilter_fcurve_next(ads, fcu, fcurve_type, filter_mode, owner, owner_id)));
+ fcu = fcu->next) {
+ if (UNLIKELY(fcurve_type == ANIMTYPE_NLACURVE)) {
+ /* NLA Control Curve - Basically the same as normal F-Curves,
+ * except we need to set some stuff differently */
+ ANIMCHANNEL_NEW_CHANNEL_FULL(fcu, ANIMTYPE_NLACURVE, owner_id, fcurve_owner_id, {
+ ale->owner = owner; /* strip */
+ ale->adt = NULL; /* to prevent time mapping from causing problems */
+ });
+ }
+ else {
+ /* Normal FCurve */
+ ANIMCHANNEL_NEW_CHANNEL(fcu, ANIMTYPE_FCURVE, owner_id, fcurve_owner_id);
+ }
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
-static size_t animfilter_act_group(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bAction *act, bActionGroup *agrp, int filter_mode, ID *owner_id)
+static size_t animfilter_act_group(bAnimContext *ac,
+ ListBase *anim_data,
+ bDopeSheet *ads,
+ bAction *act,
+ bActionGroup *agrp,
+ int filter_mode,
+ ID *owner_id)
{
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
- size_t items = 0;
- //int ofilter = filter_mode;
-
- /* if we care about the selection status of the channels,
- * but the group isn't expanded (1)...
- * (1) this only matters if we actually care about the hierarchy though.
- * - Hierarchy matters: this hack should be applied
- * - Hierarchy ignored: cases like [#21276] won't work properly, unless we skip this hack
- */
- if (
- /* care about hierarchy but group isn't expanded */
- ((filter_mode & ANIMFILTER_LIST_VISIBLE) && EXPANDED_AGRP(ac, agrp) == 0) &&
- /* care about selection status */
- (filter_mode & (ANIMFILTER_SEL | ANIMFILTER_UNSEL)) )
- {
- /* if the group itself isn't selected appropriately, we shouldn't consider it's children either */
- if (ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) == 0)
- return 0;
-
- /* if we're still here, then the selection status of the curves within this group should not matter,
- * since this creates too much overhead for animators (i.e. making a slow workflow)
- *
- * Tools affected by this at time of coding (2010 Feb 09):
- * - inserting keyframes on selected channels only
- * - pasting keyframes
- * - creating ghost curves in Graph Editor
- */
- filter_mode &= ~(ANIMFILTER_SEL | ANIMFILTER_UNSEL | ANIMFILTER_LIST_VISIBLE);
- }
-
- /* add grouped F-Curves */
- BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_AGRP(ac, agrp))
- {
- /* special filter so that we can get just the F-Curves within the active group */
- if (!(filter_mode & ANIMFILTER_ACTGROUPED) || (agrp->flag & AGRP_ACTIVE)) {
- /* for the Graph Editor, curves may be set to not be visible in the view to lessen
- * clutter, but to do this, we need to check that the group doesn't have it's
- * not-visible flag set preventing all its sub-curves to be shown
- */
- if (!(filter_mode & ANIMFILTER_CURVE_VISIBLE) || !(agrp->flag & AGRP_NOTVISIBLE)) {
- /* group must be editable for its children to be editable (if we care about this) */
- if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
- /* get first F-Curve which can be used here */
- FCurve *first_fcu = animfilter_fcurve_next(ads, agrp->channels.first, ANIMTYPE_FCURVE, filter_mode, agrp, owner_id);
-
- /* filter list, starting from this F-Curve */
- tmp_items += animfilter_fcurves(&tmp_data, ads, first_fcu, ANIMTYPE_FCURVE, filter_mode, agrp, owner_id, &act->id);
- }
- }
- }
- }
- END_ANIMFILTER_SUBCHANNELS;
-
- /* did we find anything? */
- if (tmp_items) {
- /* add this group as a channel first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* restore original filter mode so that this next step works ok... */
- //filter_mode = ofilter;
-
- /* filter selection of channel specially here again,
- * since may be open and not subject to previous test */
- if (ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) ) {
- ANIMCHANNEL_NEW_CHANNEL(agrp, ANIMTYPE_GROUP, owner_id, NULL);
- }
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
-
- /* return the number of items added to the list */
- return items;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+ //int ofilter = filter_mode;
+
+ /* if we care about the selection status of the channels,
+ * but the group isn't expanded (1)...
+ * (1) this only matters if we actually care about the hierarchy though.
+ * - Hierarchy matters: this hack should be applied
+ * - Hierarchy ignored: cases like [#21276] won't work properly, unless we skip this hack
+ */
+ if (
+ /* care about hierarchy but group isn't expanded */
+ ((filter_mode & ANIMFILTER_LIST_VISIBLE) && EXPANDED_AGRP(ac, agrp) == 0) &&
+ /* care about selection status */
+ (filter_mode & (ANIMFILTER_SEL | ANIMFILTER_UNSEL))) {
+ /* if the group itself isn't selected appropriately, we shouldn't consider it's children either */
+ if (ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) == 0)
+ return 0;
+
+ /* if we're still here, then the selection status of the curves within this group should not matter,
+ * since this creates too much overhead for animators (i.e. making a slow workflow)
+ *
+ * Tools affected by this at time of coding (2010 Feb 09):
+ * - inserting keyframes on selected channels only
+ * - pasting keyframes
+ * - creating ghost curves in Graph Editor
+ */
+ filter_mode &= ~(ANIMFILTER_SEL | ANIMFILTER_UNSEL | ANIMFILTER_LIST_VISIBLE);
+ }
+
+ /* add grouped F-Curves */
+ BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_AGRP(ac, agrp))
+ {
+ /* special filter so that we can get just the F-Curves within the active group */
+ if (!(filter_mode & ANIMFILTER_ACTGROUPED) || (agrp->flag & AGRP_ACTIVE)) {
+ /* for the Graph Editor, curves may be set to not be visible in the view to lessen
+ * clutter, but to do this, we need to check that the group doesn't have it's
+ * not-visible flag set preventing all its sub-curves to be shown
+ */
+ if (!(filter_mode & ANIMFILTER_CURVE_VISIBLE) || !(agrp->flag & AGRP_NOTVISIBLE)) {
+ /* group must be editable for its children to be editable (if we care about this) */
+ if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
+ /* get first F-Curve which can be used here */
+ FCurve *first_fcu = animfilter_fcurve_next(
+ ads, agrp->channels.first, ANIMTYPE_FCURVE, filter_mode, agrp, owner_id);
+
+ /* filter list, starting from this F-Curve */
+ tmp_items += animfilter_fcurves(
+ &tmp_data, ads, first_fcu, ANIMTYPE_FCURVE, filter_mode, agrp, owner_id, &act->id);
+ }
+ }
+ }
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* add this group as a channel first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* restore original filter mode so that this next step works ok... */
+ //filter_mode = ofilter;
+
+ /* filter selection of channel specially here again,
+ * since may be open and not subject to previous test */
+ if (ANIMCHANNEL_SELOK(SEL_AGRP(agrp))) {
+ ANIMCHANNEL_NEW_CHANNEL(agrp, ANIMTYPE_GROUP, owner_id, NULL);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
-static size_t animfilter_action(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bAction *act, int filter_mode, ID *owner_id)
+static size_t animfilter_action(bAnimContext *ac,
+ ListBase *anim_data,
+ bDopeSheet *ads,
+ bAction *act,
+ int filter_mode,
+ ID *owner_id)
{
- bActionGroup *agrp;
- FCurve *lastchan = NULL;
- size_t items = 0;
-
- /* don't include anything from this action if it is linked in from another file,
- * and we're getting stuff for editing...
- */
- if ((filter_mode & ANIMFILTER_FOREDIT) && ID_IS_LINKED(act))
- return 0;
-
- /* do groups */
- // TODO: do nested groups?
- for (agrp = act->groups.first; agrp; agrp = agrp->next) {
- /* store reference to last channel of group */
- if (agrp->channels.last)
- lastchan = agrp->channels.last;
-
- /* action group's channels */
- items += animfilter_act_group(ac, anim_data, ads, act, agrp, filter_mode, owner_id);
- }
-
- /* un-grouped F-Curves (only if we're not only considering those channels in the active group) */
- if (!(filter_mode & ANIMFILTER_ACTGROUPED)) {
- FCurve *firstfcu = (lastchan) ? (lastchan->next) : (act->curves.first);
- items += animfilter_fcurves(anim_data, ads, firstfcu, ANIMTYPE_FCURVE, filter_mode, NULL, owner_id, &act->id);
- }
-
- /* return the number of items added to the list */
- return items;
+ bActionGroup *agrp;
+ FCurve *lastchan = NULL;
+ size_t items = 0;
+
+ /* don't include anything from this action if it is linked in from another file,
+ * and we're getting stuff for editing...
+ */
+ if ((filter_mode & ANIMFILTER_FOREDIT) && ID_IS_LINKED(act))
+ return 0;
+
+ /* do groups */
+ // TODO: do nested groups?
+ for (agrp = act->groups.first; agrp; agrp = agrp->next) {
+ /* store reference to last channel of group */
+ if (agrp->channels.last)
+ lastchan = agrp->channels.last;
+
+ /* action group's channels */
+ items += animfilter_act_group(ac, anim_data, ads, act, agrp, filter_mode, owner_id);
+ }
+
+ /* un-grouped F-Curves (only if we're not only considering those channels in the active group) */
+ if (!(filter_mode & ANIMFILTER_ACTGROUPED)) {
+ FCurve *firstfcu = (lastchan) ? (lastchan->next) : (act->curves.first);
+ items += animfilter_fcurves(
+ anim_data, ads, firstfcu, ANIMTYPE_FCURVE, filter_mode, NULL, owner_id, &act->id);
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
/* Include NLA-Data for NLA-Editor:
@@ -1400,863 +1405,916 @@ static size_t animfilter_action(bAnimContext *ac, ListBase *anim_data, bDopeShee
* - for normal filtering (i.e. for editing), we only need the NLA-tracks but they can be in 'normal' evaluation
* order, i.e. first to last. Otherwise, some tools may get screwed up.
*/
-static size_t animfilter_nla(bAnimContext *UNUSED(ac), ListBase *anim_data, bDopeSheet *ads, AnimData *adt, int filter_mode, ID *owner_id)
+static size_t animfilter_nla(bAnimContext *UNUSED(ac),
+ ListBase *anim_data,
+ bDopeSheet *ads,
+ AnimData *adt,
+ int filter_mode,
+ ID *owner_id)
{
- NlaTrack *nlt;
- NlaTrack *first = NULL, *next = NULL;
- size_t items = 0;
-
- /* if showing channels, include active action */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* if NLA action-line filtering is off, don't show unless there are keyframes,
- * in order to keep things more compact for doing transforms
- */
- if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) || (adt->action)) {
- /* there isn't really anything editable here, so skip if need editable */
- if ((filter_mode & ANIMFILTER_FOREDIT) == 0) {
- /* just add the action track now (this MUST appear for drawing)
- * - as AnimData may not have an action, we pass a dummy pointer just to get the list elem created, then
- * overwrite this with the real value - REVIEW THIS...
- */
- ANIMCHANNEL_NEW_CHANNEL_FULL(
- (void *)(&adt->action), ANIMTYPE_NLAACTION, owner_id, NULL,
- {
- ale->data = adt->action ? adt->action : NULL;
- });
- }
- }
-
- /* first track to include will be the last one if we're filtering by channels */
- first = adt->nla_tracks.last;
- }
- else {
- /* first track to include will the first one (as per normal) */
- first = adt->nla_tracks.first;
- }
-
- /* loop over NLA Tracks - assume that the caller of this has already checked that these should be included */
- for (nlt = first; nlt; nlt = next) {
- /* 'next' NLA-Track to use depends on whether we're filtering for drawing or not */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS)
- next = nlt->prev;
- else
- next = nlt->next;
-
- /* if we're in NLA-tweakmode, don't show this track if it was disabled (due to tweaking) for now
- * - active track should still get shown though (even though it has disabled flag set)
- */
- // FIXME: the channels after should still get drawn, just 'differently', and after an active-action channel
- if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED) && (adt->act_track != nlt))
- continue;
-
- /* only work with this channel and its subchannels if it is editable */
- if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_NLT(nlt)) {
- /* only include this track if selected in a way consistent with the filtering requirements */
- if (ANIMCHANNEL_SELOK(SEL_NLT(nlt))) {
- /* only include if this track is active */
- if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) {
- /* name based filtering... */
- if (((ads) && (ads->searchstr[0] != '\0')) && (owner_id)) {
- bool track_ok = false, strip_ok = false;
-
- /* check if the name of the track, or the strips it has are ok... */
- track_ok = name_matches_dopesheet_filter(ads, nlt->name);
-
- if (track_ok == false) {
- NlaStrip *strip;
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- if (name_matches_dopesheet_filter(ads, strip->name)) {
- strip_ok = true;
- break;
- }
- }
- }
-
- /* skip if both fail this test... */
- if (!track_ok && !strip_ok) {
- continue;
- }
- }
-
- /* add the track now that it has passed all our tests */
- ANIMCHANNEL_NEW_CHANNEL(nlt, ANIMTYPE_NLATRACK, owner_id, NULL);
- }
- }
- }
- }
-
- /* return the number of items added to the list */
- return items;
+ NlaTrack *nlt;
+ NlaTrack *first = NULL, *next = NULL;
+ size_t items = 0;
+
+ /* if showing channels, include active action */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* if NLA action-line filtering is off, don't show unless there are keyframes,
+ * in order to keep things more compact for doing transforms
+ */
+ if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) || (adt->action)) {
+ /* there isn't really anything editable here, so skip if need editable */
+ if ((filter_mode & ANIMFILTER_FOREDIT) == 0) {
+ /* just add the action track now (this MUST appear for drawing)
+ * - as AnimData may not have an action, we pass a dummy pointer just to get the list elem created, then
+ * overwrite this with the real value - REVIEW THIS...
+ */
+ ANIMCHANNEL_NEW_CHANNEL_FULL((void *)(&adt->action), ANIMTYPE_NLAACTION, owner_id, NULL, {
+ ale->data = adt->action ? adt->action : NULL;
+ });
+ }
+ }
+
+ /* first track to include will be the last one if we're filtering by channels */
+ first = adt->nla_tracks.last;
+ }
+ else {
+ /* first track to include will the first one (as per normal) */
+ first = adt->nla_tracks.first;
+ }
+
+ /* loop over NLA Tracks - assume that the caller of this has already checked that these should be included */
+ for (nlt = first; nlt; nlt = next) {
+ /* 'next' NLA-Track to use depends on whether we're filtering for drawing or not */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS)
+ next = nlt->prev;
+ else
+ next = nlt->next;
+
+ /* if we're in NLA-tweakmode, don't show this track if it was disabled (due to tweaking) for now
+ * - active track should still get shown though (even though it has disabled flag set)
+ */
+ // FIXME: the channels after should still get drawn, just 'differently', and after an active-action channel
+ if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED) &&
+ (adt->act_track != nlt))
+ continue;
+
+ /* only work with this channel and its subchannels if it is editable */
+ if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_NLT(nlt)) {
+ /* only include this track if selected in a way consistent with the filtering requirements */
+ if (ANIMCHANNEL_SELOK(SEL_NLT(nlt))) {
+ /* only include if this track is active */
+ if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) {
+ /* name based filtering... */
+ if (((ads) && (ads->searchstr[0] != '\0')) && (owner_id)) {
+ bool track_ok = false, strip_ok = false;
+
+ /* check if the name of the track, or the strips it has are ok... */
+ track_ok = name_matches_dopesheet_filter(ads, nlt->name);
+
+ if (track_ok == false) {
+ NlaStrip *strip;
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ if (name_matches_dopesheet_filter(ads, strip->name)) {
+ strip_ok = true;
+ break;
+ }
+ }
+ }
+
+ /* skip if both fail this test... */
+ if (!track_ok && !strip_ok) {
+ continue;
+ }
+ }
+
+ /* add the track now that it has passed all our tests */
+ ANIMCHANNEL_NEW_CHANNEL(nlt, ANIMTYPE_NLATRACK, owner_id, NULL);
+ }
+ }
+ }
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
/* Include the control FCurves per NLA Strip in the channel list
* NOTE: This is includes the expander too...
*/
-static size_t animfilter_nla_controls(ListBase *anim_data, bDopeSheet *ads, AnimData *adt, int filter_mode, ID *owner_id)
+static size_t animfilter_nla_controls(
+ ListBase *anim_data, bDopeSheet *ads, AnimData *adt, int filter_mode, ID *owner_id)
{
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
- size_t items = 0;
-
- /* add control curves from each NLA strip... */
- /* NOTE: ANIMTYPE_FCURVES are created here, to avoid duplicating the code needed */
- BEGIN_ANIMFILTER_SUBCHANNELS(((adt->flag & ADT_NLA_SKEYS_COLLAPSED) == 0))
- {
- NlaTrack *nlt;
- NlaStrip *strip;
-
- /* for now, we only go one level deep - so controls on grouped FCurves are not handled */
- for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- /* pass strip as the "owner", so that the name lookups (used while filtering) will resolve */
- /* NLA tracks are coming from AnimData, so owner of f-curves
- * is the same as owner of animation data. */
- tmp_items += animfilter_fcurves(&tmp_data, ads, strip->fcurves.first, ANIMTYPE_NLACURVE,
- filter_mode, strip, owner_id, owner_id);
- }
- }
- }
- END_ANIMFILTER_SUBCHANNELS;
-
- /* did we find anything? */
- if (tmp_items) {
- /* add the expander as a channel first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* currently these channels cannot be selected, so they should be skipped */
- if ((filter_mode & (ANIMFILTER_SEL | ANIMFILTER_UNSEL)) == 0) {
- ANIMCHANNEL_NEW_CHANNEL(adt, ANIMTYPE_NLACONTROLS, owner_id, NULL);
- }
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
-
- /* return the number of items added to the list */
- return items;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* add control curves from each NLA strip... */
+ /* NOTE: ANIMTYPE_FCURVES are created here, to avoid duplicating the code needed */
+ BEGIN_ANIMFILTER_SUBCHANNELS(((adt->flag & ADT_NLA_SKEYS_COLLAPSED) == 0))
+ {
+ NlaTrack *nlt;
+ NlaStrip *strip;
+
+ /* for now, we only go one level deep - so controls on grouped FCurves are not handled */
+ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ /* pass strip as the "owner", so that the name lookups (used while filtering) will resolve */
+ /* NLA tracks are coming from AnimData, so owner of f-curves
+ * is the same as owner of animation data. */
+ tmp_items += animfilter_fcurves(&tmp_data,
+ ads,
+ strip->fcurves.first,
+ ANIMTYPE_NLACURVE,
+ filter_mode,
+ strip,
+ owner_id,
+ owner_id);
+ }
+ }
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* add the expander as a channel first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* currently these channels cannot be selected, so they should be skipped */
+ if ((filter_mode & (ANIMFILTER_SEL | ANIMFILTER_UNSEL)) == 0) {
+ ANIMCHANNEL_NEW_CHANNEL(adt, ANIMTYPE_NLACONTROLS, owner_id, NULL);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
/* determine what animation data from AnimData block should get displayed */
-static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *id, int filter_mode)
+static size_t animfilter_block_data(
+ bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *id, int filter_mode)
{
- AnimData *adt = BKE_animdata_from_id(id);
- size_t items = 0;
-
- /* image object datablocks have no anim-data so check for NULL */
- if (adt) {
- IdAdtTemplate *iat = (IdAdtTemplate *)id;
-
- /* NOTE: this macro is used instead of inlining the logic here, since this sort of filtering is still needed
- * in a few places in the rest of the code still - notably for the few cases where special mode-based
- * different types of data expanders are required.
- */
- ANIMDATA_FILTER_CASES(
- iat,
- { /* AnimData */
- /* specifically filter animdata block */
- if (ANIMCHANNEL_SELOK(SEL_ANIMDATA(adt)) ) {
- ANIMCHANNEL_NEW_CHANNEL(adt, ANIMTYPE_ANIMDATA, id, NULL);
- }
- },
- { /* NLA */
- items += animfilter_nla(ac, anim_data, ads, adt, filter_mode, id);
- },
- { /* Drivers */
- items += animfilter_fcurves(anim_data, ads, adt->drivers.first, ANIMTYPE_FCURVE,
- filter_mode, NULL, id, id);
- },
- { /* NLA Control Keyframes */
- items += animfilter_nla_controls(anim_data, ads, adt, filter_mode, id);
- },
- { /* Keyframes */
- items += animfilter_action(ac, anim_data, ads, adt->action, filter_mode, id);
- }
- );
- }
-
- return items;
+ AnimData *adt = BKE_animdata_from_id(id);
+ size_t items = 0;
+
+ /* image object datablocks have no anim-data so check for NULL */
+ if (adt) {
+ IdAdtTemplate *iat = (IdAdtTemplate *)id;
+
+ /* NOTE: this macro is used instead of inlining the logic here, since this sort of filtering is still needed
+ * in a few places in the rest of the code still - notably for the few cases where special mode-based
+ * different types of data expanders are required.
+ */
+ ANIMDATA_FILTER_CASES(
+ iat,
+ { /* AnimData */
+ /* specifically filter animdata block */
+ if (ANIMCHANNEL_SELOK(SEL_ANIMDATA(adt))) {
+ ANIMCHANNEL_NEW_CHANNEL(adt, ANIMTYPE_ANIMDATA, id, NULL);
+ }
+ },
+ { /* NLA */
+ items += animfilter_nla(ac, anim_data, ads, adt, filter_mode, id);
+ },
+ { /* Drivers */
+ items += animfilter_fcurves(
+ anim_data, ads, adt->drivers.first, ANIMTYPE_FCURVE, filter_mode, NULL, id, id);
+ },
+ { /* NLA Control Keyframes */
+ items += animfilter_nla_controls(anim_data, ads, adt, filter_mode, id);
+ },
+ { /* Keyframes */
+ items += animfilter_action(ac, anim_data, ads, adt->action, filter_mode, id);
+ });
+ }
+
+ return items;
}
-
-
/* Include ShapeKey Data for ShapeKey Editor */
-static size_t animdata_filter_shapekey(bAnimContext *ac, ListBase *anim_data, Key *key, int filter_mode)
+static size_t animdata_filter_shapekey(bAnimContext *ac,
+ ListBase *anim_data,
+ Key *key,
+ int filter_mode)
{
- size_t items = 0;
-
- /* check if channels or only F-Curves */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- KeyBlock *kb;
-
- /* loop through the channels adding ShapeKeys as appropriate */
- for (kb = key->block.first; kb; kb = kb->next) {
- /* skip the first one, since that's the non-animatable basis */
- if (kb == key->block.first) continue;
-
- /* only work with this channel and its subchannels if it is editable */
- if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_SHAPEKEY(kb)) {
- /* only include this track if selected in a way consistent with the filtering requirements */
- if (ANIMCHANNEL_SELOK(SEL_SHAPEKEY(kb)) ) {
- // TODO: consider 'active' too?
-
- /* owner-id here must be key so that the F-Curve can be resolved... */
- ANIMCHANNEL_NEW_CHANNEL(kb, ANIMTYPE_SHAPEKEY, key, NULL);
- }
- }
- }
- }
- else {
- /* just use the action associated with the shapekey */
- // TODO: somehow manage to pass dopesheet info down here too?
- if (key->adt) {
- if (filter_mode & ANIMFILTER_ANIMDATA) {
- if (ANIMCHANNEL_SELOK(SEL_ANIMDATA(key->adt)) ) {
- ANIMCHANNEL_NEW_CHANNEL(key->adt, ANIMTYPE_ANIMDATA, key, NULL);
- }
- }
- else if (key->adt->action) {
- items = animfilter_action(ac, anim_data, NULL, key->adt->action, filter_mode, (ID *)key);
- }
- }
- }
-
- /* return the number of items added to the list */
- return items;
+ size_t items = 0;
+
+ /* check if channels or only F-Curves */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ KeyBlock *kb;
+
+ /* loop through the channels adding ShapeKeys as appropriate */
+ for (kb = key->block.first; kb; kb = kb->next) {
+ /* skip the first one, since that's the non-animatable basis */
+ if (kb == key->block.first)
+ continue;
+
+ /* only work with this channel and its subchannels if it is editable */
+ if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_SHAPEKEY(kb)) {
+ /* only include this track if selected in a way consistent with the filtering requirements */
+ if (ANIMCHANNEL_SELOK(SEL_SHAPEKEY(kb))) {
+ // TODO: consider 'active' too?
+
+ /* owner-id here must be key so that the F-Curve can be resolved... */
+ ANIMCHANNEL_NEW_CHANNEL(kb, ANIMTYPE_SHAPEKEY, key, NULL);
+ }
+ }
+ }
+ }
+ else {
+ /* just use the action associated with the shapekey */
+ // TODO: somehow manage to pass dopesheet info down here too?
+ if (key->adt) {
+ if (filter_mode & ANIMFILTER_ANIMDATA) {
+ if (ANIMCHANNEL_SELOK(SEL_ANIMDATA(key->adt))) {
+ ANIMCHANNEL_NEW_CHANNEL(key->adt, ANIMTYPE_ANIMDATA, key, NULL);
+ }
+ }
+ else if (key->adt->action) {
+ items = animfilter_action(ac, anim_data, NULL, key->adt->action, filter_mode, (ID *)key);
+ }
+ }
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
/* Helper for Grease Pencil - layers within a datablock */
-static size_t animdata_filter_gpencil_layers_data(ListBase *anim_data, bDopeSheet *ads, bGPdata *gpd, int filter_mode)
+static size_t animdata_filter_gpencil_layers_data(ListBase *anim_data,
+ bDopeSheet *ads,
+ bGPdata *gpd,
+ int filter_mode)
{
- bGPDlayer *gpl;
- size_t items = 0;
-
- /* 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);
- }
- }
- }
- }
-
- return items;
+ bGPDlayer *gpl;
+ size_t items = 0;
+
+ /* 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);
+ }
+ }
+ }
+ }
+
+ return items;
}
/* Helper for Grease Pencil - Grease Pencil datablock - GP Frames */
-static size_t animdata_filter_gpencil_data(ListBase *anim_data, bDopeSheet *ads, bGPdata *gpd, int filter_mode)
+static size_t animdata_filter_gpencil_data(ListBase *anim_data,
+ bDopeSheet *ads,
+ bGPdata *gpd,
+ int filter_mode)
{
- size_t items = 0;
-
- /* When asked from "AnimData" blocks (i.e. the top-level containers for normal animation),
- * for convenience, this will return GP Datablocks instead. This may cause issues down
- * the track, but for now, this will do...
- */
- if (filter_mode & ANIMFILTER_ANIMDATA) {
- /* just add GPD as a channel - this will add everything needed */
- ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_GPDATABLOCK, gpd, NULL);
- }
- else {
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
-
- /* add gpencil animation channels */
- BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_GPD(gpd))
- {
- tmp_items += animdata_filter_gpencil_layers_data(&tmp_data, ads, gpd, filter_mode);
- }
- END_ANIMFILTER_SUBCHANNELS;
-
- /* did we find anything? */
- if (tmp_items) {
- /* include data-expand widget first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* add gpd as channel too (if for drawing, and it has layers) */
- ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_GPDATABLOCK, NULL, NULL);
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
- }
-
- return items;
+ size_t items = 0;
+
+ /* When asked from "AnimData" blocks (i.e. the top-level containers for normal animation),
+ * for convenience, this will return GP Datablocks instead. This may cause issues down
+ * the track, but for now, this will do...
+ */
+ if (filter_mode & ANIMFILTER_ANIMDATA) {
+ /* just add GPD as a channel - this will add everything needed */
+ ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_GPDATABLOCK, gpd, NULL);
+ }
+ else {
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+
+ /* add gpencil animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_GPD(gpd))
+ {
+ tmp_items += animdata_filter_gpencil_layers_data(&tmp_data, ads, gpd, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include data-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* add gpd as channel too (if for drawing, and it has layers) */
+ ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_GPDATABLOCK, NULL, NULL);
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+ }
+
+ return items;
}
/* Grab all Grease Pencil datablocks in file */
// TODO: should this be amalgamated with the dopesheet filtering code?
-static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, void *UNUSED(data), int filter_mode)
+static size_t animdata_filter_gpencil(bAnimContext *ac,
+ ListBase *anim_data,
+ void *UNUSED(data),
+ int filter_mode)
{
- 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) == 0) continue;
-
- /* outliner restrict-flag */
- if (ob->restrictflag & OB_RESTRICT_VIEW) continue;
- }
-
- /* check selection and object type filters */
- if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & BASE_SELECTED) /*|| (base == scene->basact)*/) ) {
- /* 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;
- }
-
- /* finally, include this object's grease pencil datablock */
- /* 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 datablocks 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)
- continue;
-
- /* add GP frames from this datablock */
- items += animdata_filter_gpencil_data(anim_data, ads, gpd, filter_mode);
- }
- }
-
- /* return the number of items added to the list */
- return items;
+ 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) == 0)
+ continue;
+
+ /* outliner restrict-flag */
+ if (ob->restrictflag & OB_RESTRICT_VIEW)
+ continue;
+ }
+
+ /* check selection and object type filters */
+ if ((ads->filterflag & ADS_FILTER_ONLYSEL) &&
+ !((base->flag & BASE_SELECTED) /*|| (base == scene->basact)*/)) {
+ /* 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;
+ }
+
+ /* finally, include this object's grease pencil datablock */
+ /* 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 datablocks 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)
+ continue;
+
+ /* add GP frames from this datablock */
+ items += animdata_filter_gpencil_data(anim_data, ads, gpd, filter_mode);
+ }
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
/* Helper for Grease Pencil data integrated with main DopeSheet */
-static size_t animdata_filter_ds_gpencil(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bGPdata *gpd, int filter_mode)
+static size_t animdata_filter_ds_gpencil(
+ bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bGPdata *gpd, int filter_mode)
{
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
- size_t items = 0;
-
- /* add relevant animation channels for Grease Pencil */
- BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_GPD(gpd))
- {
- /* add animation channels */
- tmp_items += animfilter_block_data(ac, &tmp_data, ads, &gpd->id, filter_mode);
-
- /* add Grease Pencil layers */
- // TODO: do these need a separate expander?
- // XXX: what order should these go in?
- }
- END_ANIMFILTER_SUBCHANNELS;
-
- /* did we find anything? */
- if (tmp_items) {
- /* include data-expand widget first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* check if filtering by active status */
- // XXX: active check here needs checking
- if (ANIMCHANNEL_ACTIVEOK(gpd)) {
- ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_DSGPENCIL, gpd, NULL);
- }
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
-
- /* return the number of items added to the list */
- return items;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* add relevant animation channels for Grease Pencil */
+ BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_GPD(gpd))
+ {
+ /* add animation channels */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, &gpd->id, filter_mode);
+
+ /* add Grease Pencil layers */
+ // TODO: do these need a separate expander?
+ // XXX: what order should these go in?
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include data-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by active status */
+ // XXX: active check here needs checking
+ if (ANIMCHANNEL_ACTIVEOK(gpd)) {
+ ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_DSGPENCIL, gpd, NULL);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
/* Helper for Cache File data integrated with main DopeSheet */
-static size_t animdata_filter_ds_cachefile(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, CacheFile *cache_file, int filter_mode)
+static size_t animdata_filter_ds_cachefile(
+ bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, CacheFile *cache_file, int filter_mode)
{
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
- size_t items = 0;
-
- /* add relevant animation channels for Cache File */
- BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_CACHEFILE_OBJD(cache_file))
- {
- /* add animation channels */
- tmp_items += animfilter_block_data(ac, &tmp_data, ads, &cache_file->id, filter_mode);
- }
- END_ANIMFILTER_SUBCHANNELS;
-
- /* did we find anything? */
- if (tmp_items) {
- /* include data-expand widget first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* check if filtering by active status */
- // XXX: active check here needs checking
- if (ANIMCHANNEL_ACTIVEOK(cache_file)) {
- ANIMCHANNEL_NEW_CHANNEL(cache_file, ANIMTYPE_DSCACHEFILE, cache_file, NULL);
- }
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
-
- /* return the number of items added to the list */
- return items;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* add relevant animation channels for Cache File */
+ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_CACHEFILE_OBJD(cache_file))
+ {
+ /* add animation channels */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, &cache_file->id, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include data-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by active status */
+ // XXX: active check here needs checking
+ if (ANIMCHANNEL_ACTIVEOK(cache_file)) {
+ ANIMCHANNEL_NEW_CHANNEL(cache_file, ANIMTYPE_DSCACHEFILE, cache_file, NULL);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
/* Helper for Mask Editing - mask layers */
static size_t animdata_filter_mask_data(ListBase *anim_data, Mask *mask, const int filter_mode)
{
- MaskLayer *masklay_act = BKE_mask_layer_active(mask);
- MaskLayer *masklay;
- size_t items = 0;
-
- /* loop over layers as the conditions are acceptable */
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- /* only if selected */
- if (ANIMCHANNEL_SELOK(SEL_MASKLAY(masklay)) ) {
- /* only if editable */
- if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_MASK(masklay)) {
- /* active... */
- if (!(filter_mode & ANIMFILTER_ACTIVE) || (masklay_act == masklay)) {
- /* add to list */
- ANIMCHANNEL_NEW_CHANNEL(masklay, ANIMTYPE_MASKLAYER, mask, NULL);
- }
- }
- }
- }
-
- return items;
+ MaskLayer *masklay_act = BKE_mask_layer_active(mask);
+ MaskLayer *masklay;
+ size_t items = 0;
+
+ /* loop over layers as the conditions are acceptable */
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ /* only if selected */
+ if (ANIMCHANNEL_SELOK(SEL_MASKLAY(masklay))) {
+ /* only if editable */
+ if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_MASK(masklay)) {
+ /* active... */
+ if (!(filter_mode & ANIMFILTER_ACTIVE) || (masklay_act == masklay)) {
+ /* add to list */
+ ANIMCHANNEL_NEW_CHANNEL(masklay, ANIMTYPE_MASKLAYER, mask, NULL);
+ }
+ }
+ }
+ }
+
+ return items;
}
/* Grab all mask data */
-static size_t animdata_filter_mask(Main *bmain, ListBase *anim_data, void *UNUSED(data), int filter_mode)
+static size_t animdata_filter_mask(Main *bmain,
+ ListBase *anim_data,
+ void *UNUSED(data),
+ int filter_mode)
{
- Mask *mask;
- size_t items = 0;
-
- /* for now, grab mask datablocks directly from main */
- // XXX: this is not good...
- for (mask = bmain->masks.first; mask; mask = mask->id.next) {
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
-
- /* only show if mask is used by something... */
- if (ID_REAL_USERS(mask) < 1)
- continue;
-
- /* add mask animation channels */
- BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_MASK(mask))
- {
- tmp_items += animdata_filter_mask_data(&tmp_data, mask, filter_mode);
- }
- END_ANIMFILTER_SUBCHANNELS;
-
- /* did we find anything? */
- if (tmp_items) {
- /* include data-expand widget first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* add mask datablock as channel too (if for drawing, and it has layers) */
- ANIMCHANNEL_NEW_CHANNEL(mask, ANIMTYPE_MASKDATABLOCK, NULL, NULL);
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
- }
-
- /* return the number of items added to the list */
- return items;
+ Mask *mask;
+ size_t items = 0;
+
+ /* for now, grab mask datablocks directly from main */
+ // XXX: this is not good...
+ for (mask = bmain->masks.first; mask; mask = mask->id.next) {
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+
+ /* only show if mask is used by something... */
+ if (ID_REAL_USERS(mask) < 1)
+ continue;
+
+ /* add mask animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_MASK(mask))
+ {
+ tmp_items += animdata_filter_mask_data(&tmp_data, mask, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include data-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* add mask datablock as channel too (if for drawing, and it has layers) */
+ ANIMCHANNEL_NEW_CHANNEL(mask, ANIMTYPE_MASKDATABLOCK, NULL, NULL);
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
/* NOTE: owner_id is scene, material, or texture block, which is the direct owner of the node tree in question */
-static size_t animdata_filter_ds_nodetree_group(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, bNodeTree *ntree, int filter_mode)
+static size_t animdata_filter_ds_nodetree_group(bAnimContext *ac,
+ ListBase *anim_data,
+ bDopeSheet *ads,
+ ID *owner_id,
+ bNodeTree *ntree,
+ int filter_mode)
{
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
- size_t items = 0;
-
- /* add nodetree animation channels */
- BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_NTREE_DATA(ntree))
- {
- /* animation data filtering */
- tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)ntree, filter_mode);
- }
- END_ANIMFILTER_SUBCHANNELS;
-
- /* did we find anything? */
- if (tmp_items) {
- /* include data-expand widget first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* check if filtering by active status */
- if (ANIMCHANNEL_ACTIVEOK(ntree)) {
- ANIMCHANNEL_NEW_CHANNEL(ntree, ANIMTYPE_DSNTREE, owner_id, NULL);
- }
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
-
- /* return the number of items added to the list */
- return items;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* add nodetree animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_NTREE_DATA(ntree))
+ {
+ /* animation data filtering */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)ntree, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include data-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by active status */
+ if (ANIMCHANNEL_ACTIVEOK(ntree)) {
+ ANIMCHANNEL_NEW_CHANNEL(ntree, ANIMTYPE_DSNTREE, owner_id, NULL);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
-static size_t animdata_filter_ds_nodetree(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, bNodeTree *ntree, int filter_mode)
+static size_t animdata_filter_ds_nodetree(bAnimContext *ac,
+ ListBase *anim_data,
+ bDopeSheet *ads,
+ ID *owner_id,
+ bNodeTree *ntree,
+ int filter_mode)
{
- bNode *node;
- size_t items = 0;
-
- items += animdata_filter_ds_nodetree_group(ac, anim_data, ads, owner_id, ntree, filter_mode);
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == NODE_GROUP) {
- if (node->id) {
- if ((ads->filterflag & ADS_FILTER_ONLYSEL) && (node->flag & NODE_SELECT) == 0) {
- continue;
- }
- /* Recurse into the node group */
- items += animdata_filter_ds_nodetree(ac, anim_data, ads, owner_id, (bNodeTree *) node->id,
- filter_mode | ANIMFILTER_TMP_IGNORE_ONLYSEL);
- }
- }
- }
-
- return items;
+ bNode *node;
+ size_t items = 0;
+
+ items += animdata_filter_ds_nodetree_group(ac, anim_data, ads, owner_id, ntree, filter_mode);
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP) {
+ if (node->id) {
+ if ((ads->filterflag & ADS_FILTER_ONLYSEL) && (node->flag & NODE_SELECT) == 0) {
+ continue;
+ }
+ /* Recurse into the node group */
+ items += animdata_filter_ds_nodetree(ac,
+ anim_data,
+ ads,
+ owner_id,
+ (bNodeTree *)node->id,
+ filter_mode | ANIMFILTER_TMP_IGNORE_ONLYSEL);
+ }
+ }
+ }
+
+ return items;
}
-static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
+static size_t animdata_filter_ds_linestyle(
+ bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
{
- ViewLayer *view_layer;
- FreestyleLineSet *lineset;
- size_t items = 0;
-
- for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
- for (lineset = view_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
- if (lineset->linestyle) {
- lineset->linestyle->id.tag |= LIB_TAG_DOIT;
- }
- }
- }
-
- for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
- /* skip render layers without Freestyle enabled */
- if ((view_layer->flag & VIEW_LAYER_FREESTYLE) == 0) {
- continue;
- }
-
- /* loop over linesets defined in the render layer */
- for (lineset = view_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
- FreestyleLineStyle *linestyle = lineset->linestyle;
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
-
- if ((linestyle == NULL) ||
- !(linestyle->id.tag & LIB_TAG_DOIT))
- {
- continue;
- }
- linestyle->id.tag &= ~LIB_TAG_DOIT;
-
- /* add scene-level animation channels */
- BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_LS_SCED(linestyle))
- {
- /* animation data filtering */
- tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)linestyle, filter_mode);
- }
- END_ANIMFILTER_SUBCHANNELS;
-
- /* did we find anything? */
- if (tmp_items) {
- /* include anim-expand widget first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* check if filtering by active status */
- if (ANIMCHANNEL_ACTIVEOK(linestyle)) {
- ANIMCHANNEL_NEW_CHANNEL(linestyle, ANIMTYPE_DSLINESTYLE, sce, NULL);
- }
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
- }
- }
-
- /* return the number of items added to the list */
- return items;
+ ViewLayer *view_layer;
+ FreestyleLineSet *lineset;
+ size_t items = 0;
+
+ for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (lineset = view_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
+ if (lineset->linestyle) {
+ lineset->linestyle->id.tag |= LIB_TAG_DOIT;
+ }
+ }
+ }
+
+ for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
+ /* skip render layers without Freestyle enabled */
+ if ((view_layer->flag & VIEW_LAYER_FREESTYLE) == 0) {
+ continue;
+ }
+
+ /* loop over linesets defined in the render layer */
+ for (lineset = view_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
+ FreestyleLineStyle *linestyle = lineset->linestyle;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+
+ if ((linestyle == NULL) || !(linestyle->id.tag & LIB_TAG_DOIT)) {
+ continue;
+ }
+ linestyle->id.tag &= ~LIB_TAG_DOIT;
+
+ /* add scene-level animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_LS_SCED(linestyle))
+ {
+ /* animation data filtering */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)linestyle, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include anim-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by active status */
+ if (ANIMCHANNEL_ACTIVEOK(linestyle)) {
+ ANIMCHANNEL_NEW_CHANNEL(linestyle, ANIMTYPE_DSLINESTYLE, sce, NULL);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+ }
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
-static size_t animdata_filter_ds_texture(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads,
- Tex *tex, ID *owner_id, int filter_mode)
+static size_t animdata_filter_ds_texture(bAnimContext *ac,
+ ListBase *anim_data,
+ bDopeSheet *ads,
+ Tex *tex,
+ ID *owner_id,
+ int filter_mode)
{
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
- size_t items = 0;
-
- /* add texture's animation data to temp collection */
- BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_TEX_DATA(tex))
- {
- /* texture animdata */
- tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)tex, filter_mode);
-
- /* nodes */
- if ((tex->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
- /* owner_id as id instead of texture, since it'll otherwise be impossible to track the depth */
- // FIXME: perhaps as a result, textures should NOT be included under materials, but under their own section instead
- // so that free-floating textures can also be animated
- tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, (ID *)tex, tex->nodetree, filter_mode);
- }
- }
- END_ANIMFILTER_SUBCHANNELS;
-
- /* did we find anything? */
- if (tmp_items) {
- /* include texture-expand widget? */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* check if filtering by active status */
- if (ANIMCHANNEL_ACTIVEOK(tex)) {
- ANIMCHANNEL_NEW_CHANNEL(tex, ANIMTYPE_DSTEX, owner_id, NULL);
- }
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
-
- /* return the number of items added to the list */
- return items;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* add texture's animation data to temp collection */
+ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_TEX_DATA(tex))
+ {
+ /* texture animdata */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)tex, filter_mode);
+
+ /* nodes */
+ if ((tex->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
+ /* owner_id as id instead of texture, since it'll otherwise be impossible to track the depth */
+ // FIXME: perhaps as a result, textures should NOT be included under materials, but under their own section instead
+ // so that free-floating textures can also be animated
+ tmp_items += animdata_filter_ds_nodetree(
+ ac, &tmp_data, ads, (ID *)tex, tex->nodetree, filter_mode);
+ }
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include texture-expand widget? */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by active status */
+ if (ANIMCHANNEL_ACTIVEOK(tex)) {
+ ANIMCHANNEL_NEW_CHANNEL(tex, ANIMTYPE_DSTEX, owner_id, NULL);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
/* NOTE: owner_id is the direct owner of the texture stack in question
* It used to be Material/Light/World before the Blender Internal removal for 2.8
*/
-static size_t animdata_filter_ds_textures(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, int filter_mode)
+static size_t animdata_filter_ds_textures(
+ bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, int filter_mode)
{
- MTex **mtex = NULL;
- size_t items = 0;
- int a = 0;
-
- /* get datatype specific data first */
- if (owner_id == NULL)
- return 0;
-
- switch (GS(owner_id->name)) {
- case ID_PA:
- {
- ParticleSettings *part = (ParticleSettings *)owner_id;
- mtex = (MTex **)(&part->mtex);
- break;
- }
- default:
- {
- /* invalid/unsupported option */
- if (G.debug & G_DEBUG)
- printf("ERROR: Unsupported owner_id (i.e. texture stack) for filter textures - %s\n", owner_id->name);
- return 0;
- }
- }
-
- /* firstly check that we actuallly have some textures, by gathering all textures in a temp list */
- for (a = 0; a < MAX_MTEX; a++) {
- Tex *tex = (mtex[a]) ? mtex[a]->tex : NULL;
-
- /* for now, if no texture returned, skip (this shouldn't confuse the user I hope) */
- if (tex == NULL)
- continue;
-
- /* add texture's anim channels */
- items += animdata_filter_ds_texture(ac, anim_data, ads, tex, owner_id, filter_mode);
- }
-
- /* return the number of items added to the list */
- return items;
+ MTex **mtex = NULL;
+ size_t items = 0;
+ int a = 0;
+
+ /* get datatype specific data first */
+ if (owner_id == NULL)
+ return 0;
+
+ switch (GS(owner_id->name)) {
+ case ID_PA: {
+ ParticleSettings *part = (ParticleSettings *)owner_id;
+ mtex = (MTex **)(&part->mtex);
+ break;
+ }
+ default: {
+ /* invalid/unsupported option */
+ if (G.debug & G_DEBUG)
+ printf("ERROR: Unsupported owner_id (i.e. texture stack) for filter textures - %s\n",
+ owner_id->name);
+ return 0;
+ }
+ }
+
+ /* firstly check that we actuallly have some textures, by gathering all textures in a temp list */
+ for (a = 0; a < MAX_MTEX; a++) {
+ Tex *tex = (mtex[a]) ? mtex[a]->tex : NULL;
+
+ /* for now, if no texture returned, skip (this shouldn't confuse the user I hope) */
+ if (tex == NULL)
+ continue;
+
+ /* add texture's anim channels */
+ items += animdata_filter_ds_texture(ac, anim_data, ads, tex, owner_id, filter_mode);
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
-
-static size_t animdata_filter_ds_material(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Material *ma, int filter_mode)
+static size_t animdata_filter_ds_material(
+ bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Material *ma, int filter_mode)
{
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
- size_t items = 0;
-
- /* add material's animation data to temp collection */
- BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_MAT_OBJD(ma))
- {
- /* material's animation data */
- tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)ma, filter_mode);
-
- /* nodes */
- if ((ma->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE))
- tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, (ID *)ma, ma->nodetree, filter_mode);
- }
- END_ANIMFILTER_SUBCHANNELS;
-
- /* did we find anything? */
- if (tmp_items) {
- /* include material-expand widget first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* check if filtering by active status */
- if (ANIMCHANNEL_ACTIVEOK(ma)) {
- ANIMCHANNEL_NEW_CHANNEL(ma, ANIMTYPE_DSMAT, ma, NULL);
- }
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
-
- return items;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* add material's animation data to temp collection */
+ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_MAT_OBJD(ma))
+ {
+ /* material's animation data */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)ma, filter_mode);
+
+ /* nodes */
+ if ((ma->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE))
+ tmp_items += animdata_filter_ds_nodetree(
+ ac, &tmp_data, ads, (ID *)ma, ma->nodetree, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include material-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by active status */
+ if (ANIMCHANNEL_ACTIVEOK(ma)) {
+ ANIMCHANNEL_NEW_CHANNEL(ma, ANIMTYPE_DSMAT, ma, NULL);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+
+ return items;
}
-static size_t animdata_filter_ds_materials(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
+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);
-
- /* 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);
- }
- }
- }
-
- /* return the number of items added to the list */
- return items;
+ 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);
+
+ /* 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);
+ }
+ }
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
-
/* ............ */
/* Temporary context for modifier linked-data channel extraction */
typedef struct tAnimFilterModifiersContext {
- bAnimContext *ac; /* anim editor context */
- bDopeSheet *ads; /* dopesheet filtering settings */
+ bAnimContext *ac; /* anim editor context */
+ bDopeSheet *ads; /* dopesheet filtering settings */
- ListBase tmp_data; /* list of channels created (but not yet added to the main list) */
- size_t items; /* number of channels created */
+ ListBase tmp_data; /* list of channels created (but not yet added to the main list) */
+ size_t items; /* number of channels created */
- int filter_mode; /* flags for stuff we want to filter */
+ int filter_mode; /* flags for stuff we want to filter */
} tAnimFilterModifiersContext;
-
/* dependency walker callback for modifier dependencies */
-static void animfilter_modifier_idpoin_cb(void *afm_ptr, Object *ob, ID **idpoin, int UNUSED(cb_flag))
+static void animfilter_modifier_idpoin_cb(void *afm_ptr,
+ Object *ob,
+ ID **idpoin,
+ int UNUSED(cb_flag))
{
- tAnimFilterModifiersContext *afm = (tAnimFilterModifiersContext *)afm_ptr;
- ID *owner_id = &ob->id;
- ID *id = *idpoin;
-
- /* NOTE: the walker only guarantees to give us all the ID-ptr *slots*,
- * not just the ones which are actually used, so be careful!
- */
- if (id == NULL)
- return;
-
- /* check if this is something we're interested in... */
- switch (GS(id->name)) {
- case ID_TE: /* Textures */
- {
- Tex *tex = (Tex *)id;
- if (!(afm->ads->filterflag & ADS_FILTER_NOTEX)) {
- afm->items += animdata_filter_ds_texture(afm->ac, &afm->tmp_data, afm->ads, tex, owner_id, afm->filter_mode);
- }
- break;
- }
-
- /* TODO: images? */
- default:
- break;
- }
+ tAnimFilterModifiersContext *afm = (tAnimFilterModifiersContext *)afm_ptr;
+ ID *owner_id = &ob->id;
+ ID *id = *idpoin;
+
+ /* NOTE: the walker only guarantees to give us all the ID-ptr *slots*,
+ * not just the ones which are actually used, so be careful!
+ */
+ if (id == NULL)
+ return;
+
+ /* check if this is something we're interested in... */
+ switch (GS(id->name)) {
+ case ID_TE: /* Textures */
+ {
+ Tex *tex = (Tex *)id;
+ if (!(afm->ads->filterflag & ADS_FILTER_NOTEX)) {
+ afm->items += animdata_filter_ds_texture(
+ afm->ac, &afm->tmp_data, afm->ads, tex, owner_id, afm->filter_mode);
+ }
+ break;
+ }
+
+ /* TODO: images? */
+ default:
+ break;
+ }
}
/* animation linked to data used by modifiers
@@ -2266,861 +2324,886 @@ static void animfilter_modifier_idpoin_cb(void *afm_ptr, Object *ob, ID **idpoin
* attached to any other objects/materials/etc. in the scene
*/
// TODO: do we want an expander for this?
-static size_t animdata_filter_ds_modifiers(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
+static size_t animdata_filter_ds_modifiers(
+ bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
{
- tAnimFilterModifiersContext afm = {NULL};
- size_t items = 0;
-
- /* 1) create a temporary "context" containing all the info we have here to pass to the callback
- * use to walk through the dependencies of the modifiers
- *
- * ! Assumes that all other unspecified values (i.e. accumulation buffers) are zero'd out properly
- */
- afm.ac = ac;
- afm.ads = ads;
- afm.filter_mode = filter_mode;
-
- /* 2) walk over dependencies */
- modifiers_foreachIDLink(ob, animfilter_modifier_idpoin_cb, &afm);
-
- /* 3) extract data from the context, merging it back into the standard list */
- if (afm.items) {
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &afm.tmp_data);
- BLI_assert(BLI_listbase_is_empty(&afm.tmp_data));
- items += afm.items;
- }
-
- return items;
+ tAnimFilterModifiersContext afm = {NULL};
+ size_t items = 0;
+
+ /* 1) create a temporary "context" containing all the info we have here to pass to the callback
+ * use to walk through the dependencies of the modifiers
+ *
+ * ! Assumes that all other unspecified values (i.e. accumulation buffers) are zero'd out properly
+ */
+ afm.ac = ac;
+ afm.ads = ads;
+ afm.filter_mode = filter_mode;
+
+ /* 2) walk over dependencies */
+ modifiers_foreachIDLink(ob, animfilter_modifier_idpoin_cb, &afm);
+
+ /* 3) extract data from the context, merging it back into the standard list */
+ if (afm.items) {
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &afm.tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&afm.tmp_data));
+ items += afm.items;
+ }
+
+ return items;
}
/* ............ */
-
-static size_t animdata_filter_ds_particles(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
+static size_t animdata_filter_ds_particles(
+ bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
{
- ParticleSystem *psys;
- size_t items = 0;
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
-
- /* if no material returned, skip - so that we don't get weird blank entries... */
- if (ELEM(NULL, psys->part, psys->part->adt))
- continue;
-
- /* add particle-system's animation data to temp collection */
- BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_PART_OBJD(psys->part))
- {
- /* particle system's animation data */
- tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)psys->part, filter_mode);
-
- /* textures */
- if (!(ads->filterflag & ADS_FILTER_NOTEX))
- tmp_items += animdata_filter_ds_textures(ac, &tmp_data, ads, (ID *)psys->part, filter_mode);
- }
- END_ANIMFILTER_SUBCHANNELS;
-
- /* did we find anything? */
- if (tmp_items) {
- /* include particle-expand widget first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* check if filtering by active status */
- if (ANIMCHANNEL_ACTIVEOK(psys->part)) {
- ANIMCHANNEL_NEW_CHANNEL(psys->part, ANIMTYPE_DSPART, psys->part, NULL);
- }
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
- }
-
- /* return the number of items added to the list */
- return items;
+ ParticleSystem *psys;
+ size_t items = 0;
+
+ for (psys = ob->particlesystem.first; psys; psys = psys->next) {
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+
+ /* if no material returned, skip - so that we don't get weird blank entries... */
+ if (ELEM(NULL, psys->part, psys->part->adt))
+ continue;
+
+ /* add particle-system's animation data to temp collection */
+ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_PART_OBJD(psys->part))
+ {
+ /* particle system's animation data */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)psys->part, filter_mode);
+
+ /* textures */
+ if (!(ads->filterflag & ADS_FILTER_NOTEX))
+ tmp_items += animdata_filter_ds_textures(
+ ac, &tmp_data, ads, (ID *)psys->part, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include particle-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by active status */
+ if (ANIMCHANNEL_ACTIVEOK(psys->part)) {
+ ANIMCHANNEL_NEW_CHANNEL(psys->part, ANIMTYPE_DSPART, psys->part, NULL);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
-
-static size_t animdata_filter_ds_obdata(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
+static size_t animdata_filter_ds_obdata(
+ bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
{
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
- size_t items = 0;
-
- IdAdtTemplate *iat = ob->data;
- short type = 0, expanded = 0;
-
- /* get settings based on data type */
- switch (ob->type) {
- case OB_CAMERA: /* ------- Camera ------------ */
- {
- Camera *ca = (Camera *)ob->data;
-
- if (ads->filterflag & ADS_FILTER_NOCAM)
- return 0;
-
- type = ANIMTYPE_DSCAM;
- expanded = FILTER_CAM_OBJD(ca);
- break;
- }
- case OB_LAMP: /* ---------- Light ----------- */
- {
- Light *la = (Light *)ob->data;
-
- if (ads->filterflag & ADS_FILTER_NOLAM)
- return 0;
-
- type = ANIMTYPE_DSLAM;
- expanded = FILTER_LAM_OBJD(la);
- break;
- }
- case OB_CURVE: /* ------- Curve ---------- */
- case OB_SURF: /* ------- Nurbs Surface ---------- */
- case OB_FONT: /* ------- Text Curve ---------- */
- {
- Curve *cu = (Curve *)ob->data;
-
- if (ads->filterflag & ADS_FILTER_NOCUR)
- return 0;
-
- type = ANIMTYPE_DSCUR;
- expanded = FILTER_CUR_OBJD(cu);
- break;
- }
- case OB_MBALL: /* ------- MetaBall ---------- */
- {
- MetaBall *mb = (MetaBall *)ob->data;
-
- if (ads->filterflag & ADS_FILTER_NOMBA)
- return 0;
-
- type = ANIMTYPE_DSMBALL;
- expanded = FILTER_MBALL_OBJD(mb);
- break;
- }
- case OB_ARMATURE: /* ------- Armature ---------- */
- {
- bArmature *arm = (bArmature *)ob->data;
-
- if (ads->filterflag & ADS_FILTER_NOARM)
- return 0;
-
- type = ANIMTYPE_DSARM;
- expanded = FILTER_ARM_OBJD(arm);
- break;
- }
- case OB_MESH: /* ------- Mesh ---------- */
- {
- Mesh *me = (Mesh *)ob->data;
-
- if (ads->filterflag & ADS_FILTER_NOMESH)
- return 0;
-
- type = ANIMTYPE_DSMESH;
- expanded = FILTER_MESH_OBJD(me);
- break;
- }
- case OB_LATTICE: /* ---- Lattice ---- */
- {
- Lattice *lt = (Lattice *)ob->data;
-
- if (ads->filterflag & ADS_FILTER_NOLAT)
- return 0;
-
- type = ANIMTYPE_DSLAT;
- expanded = FILTER_LATTICE_OBJD(lt);
- break;
- }
- case OB_SPEAKER: /* ---------- Speaker ----------- */
- {
- Speaker *spk = (Speaker *)ob->data;
-
- type = ANIMTYPE_DSSPK;
- expanded = FILTER_SPK_OBJD(spk);
- break;
- }
- }
-
- /* add object data animation channels */
- BEGIN_ANIMFILTER_SUBCHANNELS(expanded)
- {
- /* animation data filtering */
- tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)iat, filter_mode);
-
- /* sub-data filtering... */
- switch (ob->type) {
- case OB_LAMP: /* light - textures + nodetree */
- {
- Light *la = ob->data;
- bNodeTree *ntree = la->nodetree;
-
- /* nodetree */
- if ((ntree) && !(ads->filterflag & ADS_FILTER_NONTREE))
- tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, &la->id, ntree, filter_mode);
- break;
- }
- }
- }
- END_ANIMFILTER_SUBCHANNELS;
-
- /* did we find anything? */
- if (tmp_items) {
- /* include data-expand widget first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* check if filtering by active status */
- if (ANIMCHANNEL_ACTIVEOK(iat)) {
- ANIMCHANNEL_NEW_CHANNEL(iat, type, iat, NULL);
- }
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
-
- /* return the number of items added to the list */
- return items;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ IdAdtTemplate *iat = ob->data;
+ short type = 0, expanded = 0;
+
+ /* get settings based on data type */
+ switch (ob->type) {
+ case OB_CAMERA: /* ------- Camera ------------ */
+ {
+ Camera *ca = (Camera *)ob->data;
+
+ if (ads->filterflag & ADS_FILTER_NOCAM)
+ return 0;
+
+ type = ANIMTYPE_DSCAM;
+ expanded = FILTER_CAM_OBJD(ca);
+ break;
+ }
+ case OB_LAMP: /* ---------- Light ----------- */
+ {
+ Light *la = (Light *)ob->data;
+
+ if (ads->filterflag & ADS_FILTER_NOLAM)
+ return 0;
+
+ type = ANIMTYPE_DSLAM;
+ expanded = FILTER_LAM_OBJD(la);
+ break;
+ }
+ case OB_CURVE: /* ------- Curve ---------- */
+ case OB_SURF: /* ------- Nurbs Surface ---------- */
+ case OB_FONT: /* ------- Text Curve ---------- */
+ {
+ Curve *cu = (Curve *)ob->data;
+
+ if (ads->filterflag & ADS_FILTER_NOCUR)
+ return 0;
+
+ type = ANIMTYPE_DSCUR;
+ expanded = FILTER_CUR_OBJD(cu);
+ break;
+ }
+ case OB_MBALL: /* ------- MetaBall ---------- */
+ {
+ MetaBall *mb = (MetaBall *)ob->data;
+
+ if (ads->filterflag & ADS_FILTER_NOMBA)
+ return 0;
+
+ type = ANIMTYPE_DSMBALL;
+ expanded = FILTER_MBALL_OBJD(mb);
+ break;
+ }
+ case OB_ARMATURE: /* ------- Armature ---------- */
+ {
+ bArmature *arm = (bArmature *)ob->data;
+
+ if (ads->filterflag & ADS_FILTER_NOARM)
+ return 0;
+
+ type = ANIMTYPE_DSARM;
+ expanded = FILTER_ARM_OBJD(arm);
+ break;
+ }
+ case OB_MESH: /* ------- Mesh ---------- */
+ {
+ Mesh *me = (Mesh *)ob->data;
+
+ if (ads->filterflag & ADS_FILTER_NOMESH)
+ return 0;
+
+ type = ANIMTYPE_DSMESH;
+ expanded = FILTER_MESH_OBJD(me);
+ break;
+ }
+ case OB_LATTICE: /* ---- Lattice ---- */
+ {
+ Lattice *lt = (Lattice *)ob->data;
+
+ if (ads->filterflag & ADS_FILTER_NOLAT)
+ return 0;
+
+ type = ANIMTYPE_DSLAT;
+ expanded = FILTER_LATTICE_OBJD(lt);
+ break;
+ }
+ case OB_SPEAKER: /* ---------- Speaker ----------- */
+ {
+ Speaker *spk = (Speaker *)ob->data;
+
+ type = ANIMTYPE_DSSPK;
+ expanded = FILTER_SPK_OBJD(spk);
+ break;
+ }
+ }
+
+ /* add object data animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(expanded)
+ {
+ /* animation data filtering */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)iat, filter_mode);
+
+ /* sub-data filtering... */
+ switch (ob->type) {
+ case OB_LAMP: /* light - textures + nodetree */
+ {
+ Light *la = ob->data;
+ bNodeTree *ntree = la->nodetree;
+
+ /* nodetree */
+ if ((ntree) && !(ads->filterflag & ADS_FILTER_NONTREE))
+ tmp_items += animdata_filter_ds_nodetree(
+ ac, &tmp_data, ads, &la->id, ntree, filter_mode);
+ break;
+ }
+ }
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include data-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by active status */
+ if (ANIMCHANNEL_ACTIVEOK(iat)) {
+ ANIMCHANNEL_NEW_CHANNEL(iat, type, iat, NULL);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
/* shapekey-level animation */
-static size_t animdata_filter_ds_keyanim(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, Key *key, int filter_mode)
+static size_t animdata_filter_ds_keyanim(
+ bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, Key *key, int filter_mode)
{
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
- size_t items = 0;
-
- /* add shapekey-level animation channels */
- BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_SKE_OBJD(key))
- {
- /* animation data filtering */
- tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)key, filter_mode);
- }
- END_ANIMFILTER_SUBCHANNELS;
-
- /* did we find anything? */
- if (tmp_items) {
- /* include key-expand widget first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- if (ANIMCHANNEL_ACTIVEOK(key)) {
- ANIMCHANNEL_NEW_CHANNEL(key, ANIMTYPE_DSSKEY, ob, NULL);
- }
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
-
- /* return the number of items added to the list */
- return items;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* add shapekey-level animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_SKE_OBJD(key))
+ {
+ /* animation data filtering */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)key, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include key-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ if (ANIMCHANNEL_ACTIVEOK(key)) {
+ ANIMCHANNEL_NEW_CHANNEL(key, ANIMTYPE_DSSKEY, ob, NULL);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
-
/* object-level animation */
-static size_t animdata_filter_ds_obanim(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
+static size_t animdata_filter_ds_obanim(
+ bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
{
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
- size_t items = 0;
-
- AnimData *adt = ob->adt;
- short type = 0, expanded = 1;
- void *cdata = NULL;
-
- /* determine the type of expander channels to use */
- /* this is the best way to do this for now... */
- ANIMDATA_FILTER_CASES(
- ob,
- { /* AnimData - no channel, but consider data */ },
- { /* NLA - no channel, but consider data */ },
- { /* Drivers */
- type = ANIMTYPE_FILLDRIVERS;
- cdata = adt;
- expanded = EXPANDED_DRVD(adt);
- },
- { /* NLA Strip Controls - no dedicated channel for now (XXX) */ },
- { /* Keyframes */
- type = ANIMTYPE_FILLACTD;
- cdata = adt->action;
- expanded = EXPANDED_ACTC(adt->action);
- });
-
- /* add object-level animation channels */
- BEGIN_ANIMFILTER_SUBCHANNELS(expanded)
- {
- /* animation data filtering */
- tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)ob, filter_mode);
- }
- END_ANIMFILTER_SUBCHANNELS;
-
- /* did we find anything? */
- if (tmp_items) {
- /* include anim-expand widget first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- if (type != ANIMTYPE_NONE) {
- /* NOTE: active-status (and the associated checks) don't apply here... */
- ANIMCHANNEL_NEW_CHANNEL(cdata, type, ob, NULL);
- }
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
-
- /* return the number of items added to the list */
- return items;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ AnimData *adt = ob->adt;
+ short type = 0, expanded = 1;
+ void *cdata = NULL;
+
+ /* determine the type of expander channels to use */
+ /* this is the best way to do this for now... */
+ ANIMDATA_FILTER_CASES(
+ ob,
+ {/* AnimData - no channel, but consider data */},
+ {/* NLA - no channel, but consider data */},
+ { /* Drivers */
+ type = ANIMTYPE_FILLDRIVERS;
+ cdata = adt;
+ expanded = EXPANDED_DRVD(adt);
+ },
+ {/* NLA Strip Controls - no dedicated channel for now (XXX) */},
+ { /* Keyframes */
+ type = ANIMTYPE_FILLACTD;
+ cdata = adt->action;
+ expanded = EXPANDED_ACTC(adt->action);
+ });
+
+ /* add object-level animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(expanded)
+ {
+ /* animation data filtering */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)ob, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include anim-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ if (type != ANIMTYPE_NONE) {
+ /* NOTE: active-status (and the associated checks) don't apply here... */
+ ANIMCHANNEL_NEW_CHANNEL(cdata, type, ob, NULL);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
/* get animation channels from object2 */
-static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+static size_t animdata_filter_dopesheet_ob(
+ bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
{
- ListBase tmp_data = {NULL, NULL};
- Object *ob = base->object;
- size_t tmp_items = 0;
- size_t items = 0;
-
- /* filter data contained under object first */
- BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_OBJC(ob))
- {
- Key *key = BKE_key_from_object(ob);
-
- /* object-level animation */
- if ((ob->adt) && !(ads->filterflag & ADS_FILTER_NOOBJ)) {
- tmp_items += animdata_filter_ds_obanim(ac, &tmp_data, ads, ob, filter_mode);
- }
-
- /* shape-key */
- if ((key && key->adt) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
- tmp_items += animdata_filter_ds_keyanim(ac, &tmp_data, ads, ob, key, filter_mode);
- }
-
- /* modifiers */
- if ((ob->modifiers.first) && !(ads->filterflag & ADS_FILTER_NOMODIFIERS)) {
- tmp_items += animdata_filter_ds_modifiers(ac, &tmp_data, ads, ob, filter_mode);
- }
-
- /* materials */
- if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT)) {
- tmp_items += animdata_filter_ds_materials(ac, &tmp_data, ads, ob, filter_mode);
- }
-
- /* object data */
- if (ob->data) {
- tmp_items += animdata_filter_ds_obdata(ac, &tmp_data, ads, ob, filter_mode);
- }
-
- /* particles */
- if ((ob->particlesystem.first) && !(ads->filterflag & ADS_FILTER_NOPART)) {
- tmp_items += animdata_filter_ds_particles(ac, &tmp_data, ads, ob, filter_mode);
- }
-
- /* grease pencil */
- if ((ob->type == OB_GPENCIL) &&
- (ob->data) && !(ads->filterflag & ADS_FILTER_NOGPENCIL))
- {
- tmp_items += animdata_filter_ds_gpencil(ac, &tmp_data, ads, ob->data, filter_mode);
- }
- }
- END_ANIMFILTER_SUBCHANNELS;
-
-
- /* if we collected some channels, add these to the new list... */
- if (tmp_items) {
- /* firstly add object expander if required */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* check if filtering by selection */
- // XXX: double-check on this - most of the time, a lot of tools need to filter out these channels!
- if (ANIMCHANNEL_SELOK((base->flag & BASE_SELECTED))) {
- /* check if filtering by active status */
- if (ANIMCHANNEL_ACTIVEOK(ob)) {
- ANIMCHANNEL_NEW_CHANNEL(base, ANIMTYPE_OBJECT, ob, NULL);
- }
- }
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
-
- /* return the number of items added */
- return items;
+ ListBase tmp_data = {NULL, NULL};
+ Object *ob = base->object;
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* filter data contained under object first */
+ BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_OBJC(ob))
+ {
+ Key *key = BKE_key_from_object(ob);
+
+ /* object-level animation */
+ if ((ob->adt) && !(ads->filterflag & ADS_FILTER_NOOBJ)) {
+ tmp_items += animdata_filter_ds_obanim(ac, &tmp_data, ads, ob, filter_mode);
+ }
+
+ /* shape-key */
+ if ((key && key->adt) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
+ tmp_items += animdata_filter_ds_keyanim(ac, &tmp_data, ads, ob, key, filter_mode);
+ }
+
+ /* modifiers */
+ if ((ob->modifiers.first) && !(ads->filterflag & ADS_FILTER_NOMODIFIERS)) {
+ tmp_items += animdata_filter_ds_modifiers(ac, &tmp_data, ads, ob, filter_mode);
+ }
+
+ /* materials */
+ if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT)) {
+ tmp_items += animdata_filter_ds_materials(ac, &tmp_data, ads, ob, filter_mode);
+ }
+
+ /* object data */
+ if (ob->data) {
+ tmp_items += animdata_filter_ds_obdata(ac, &tmp_data, ads, ob, filter_mode);
+ }
+
+ /* particles */
+ if ((ob->particlesystem.first) && !(ads->filterflag & ADS_FILTER_NOPART)) {
+ tmp_items += animdata_filter_ds_particles(ac, &tmp_data, ads, ob, filter_mode);
+ }
+
+ /* grease pencil */
+ if ((ob->type == OB_GPENCIL) && (ob->data) && !(ads->filterflag & ADS_FILTER_NOGPENCIL)) {
+ tmp_items += animdata_filter_ds_gpencil(ac, &tmp_data, ads, ob->data, filter_mode);
+ }
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* if we collected some channels, add these to the new list... */
+ if (tmp_items) {
+ /* firstly add object expander if required */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by selection */
+ // XXX: double-check on this - most of the time, a lot of tools need to filter out these channels!
+ if (ANIMCHANNEL_SELOK((base->flag & BASE_SELECTED))) {
+ /* check if filtering by active status */
+ if (ANIMCHANNEL_ACTIVEOK(ob)) {
+ ANIMCHANNEL_NEW_CHANNEL(base, ANIMTYPE_OBJECT, ob, NULL);
+ }
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+
+ /* return the number of items added */
+ return items;
}
-static size_t animdata_filter_ds_world(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, World *wo, int filter_mode)
+static size_t animdata_filter_ds_world(
+ bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, World *wo, int filter_mode)
{
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
- size_t items = 0;
-
- /* add world animation channels */
- BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_WOR_SCED(wo))
- {
- /* animation data filtering */
- tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)wo, filter_mode);
-
- /* nodes */
- if ((wo->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE))
- tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, (ID *)wo, wo->nodetree, filter_mode);
- }
- END_ANIMFILTER_SUBCHANNELS;
-
- /* did we find anything? */
- if (tmp_items) {
- /* include data-expand widget first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* check if filtering by active status */
- if (ANIMCHANNEL_ACTIVEOK(wo)) {
- ANIMCHANNEL_NEW_CHANNEL(wo, ANIMTYPE_DSWOR, sce, NULL);
- }
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
-
- /* return the number of items added to the list */
- return items;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* add world animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_WOR_SCED(wo))
+ {
+ /* animation data filtering */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)wo, filter_mode);
+
+ /* nodes */
+ if ((wo->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE))
+ tmp_items += animdata_filter_ds_nodetree(
+ ac, &tmp_data, ads, (ID *)wo, wo->nodetree, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include data-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by active status */
+ if (ANIMCHANNEL_ACTIVEOK(wo)) {
+ ANIMCHANNEL_NEW_CHANNEL(wo, ANIMTYPE_DSWOR, sce, NULL);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
-static size_t animdata_filter_ds_scene(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
+static size_t animdata_filter_ds_scene(
+ bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
{
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
- size_t items = 0;
-
- AnimData *adt = sce->adt;
- short type = 0, expanded = 1;
- void *cdata = NULL;
-
- /* determine the type of expander channels to use */
- // this is the best way to do this for now...
- ANIMDATA_FILTER_CASES(
- sce,
- { /* AnimData - no channel, but consider data */},
- { /* NLA - no channel, but consider data */},
- { /* Drivers */
- type = ANIMTYPE_FILLDRIVERS;
- cdata = adt;
- expanded = EXPANDED_DRVD(adt);
- },
- { /* NLA Strip Controls - no dedicated channel for now (XXX) */ },
- { /* Keyframes */
- type = ANIMTYPE_FILLACTD;
- cdata = adt->action;
- expanded = EXPANDED_ACTC(adt->action);
- });
-
- /* add scene-level animation channels */
- BEGIN_ANIMFILTER_SUBCHANNELS(expanded)
- {
- /* animation data filtering */
- tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)sce, filter_mode);
- }
- END_ANIMFILTER_SUBCHANNELS;
-
- /* did we find anything? */
- if (tmp_items) {
- /* include anim-expand widget first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- if (type != ANIMTYPE_NONE) {
- /* NOTE: active-status (and the associated checks) don't apply here... */
- ANIMCHANNEL_NEW_CHANNEL(cdata, type, sce, NULL);
- }
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
-
- /* return the number of items added to the list */
- return items;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ AnimData *adt = sce->adt;
+ short type = 0, expanded = 1;
+ void *cdata = NULL;
+
+ /* determine the type of expander channels to use */
+ // this is the best way to do this for now...
+ ANIMDATA_FILTER_CASES(
+ sce,
+ {/* AnimData - no channel, but consider data */},
+ {/* NLA - no channel, but consider data */},
+ { /* Drivers */
+ type = ANIMTYPE_FILLDRIVERS;
+ cdata = adt;
+ expanded = EXPANDED_DRVD(adt);
+ },
+ {/* NLA Strip Controls - no dedicated channel for now (XXX) */},
+ { /* Keyframes */
+ type = ANIMTYPE_FILLACTD;
+ cdata = adt->action;
+ expanded = EXPANDED_ACTC(adt->action);
+ });
+
+ /* add scene-level animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(expanded)
+ {
+ /* animation data filtering */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)sce, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include anim-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ if (type != ANIMTYPE_NONE) {
+ /* NOTE: active-status (and the associated checks) don't apply here... */
+ ANIMCHANNEL_NEW_CHANNEL(cdata, type, sce, NULL);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+
+ /* return the number of items added to the list */
+ return items;
}
-static size_t animdata_filter_dopesheet_scene(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
+static size_t animdata_filter_dopesheet_scene(
+ bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
{
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
- size_t items = 0;
-
- /* filter data contained under object first */
- BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_SCEC(sce))
- {
- bNodeTree *ntree = sce->nodetree;
- bGPdata *gpd = sce->gpd;
- World *wo = sce->world;
-
- /* Action, Drivers, or NLA for Scene */
- if ((ads->filterflag & ADS_FILTER_NOSCE) == 0) {
- tmp_items += animdata_filter_ds_scene(ac, &tmp_data, ads, sce, filter_mode);
- }
-
- /* world */
- if ((wo) && !(ads->filterflag & ADS_FILTER_NOWOR)) {
- tmp_items += animdata_filter_ds_world(ac, &tmp_data, ads, sce, wo, filter_mode);
- }
-
- /* nodetree */
- if ((ntree) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
- tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, (ID *)sce, ntree, filter_mode);
- }
-
- /* line styles */
- if ((ads->filterflag & ADS_FILTER_NOLINESTYLE) == 0) {
- tmp_items += animdata_filter_ds_linestyle(ac, &tmp_data, ads, sce, filter_mode);
- }
-
- /* grease pencil */
- if ((gpd) && !(ads->filterflag & ADS_FILTER_NOGPENCIL)) {
- tmp_items += animdata_filter_ds_gpencil(ac, &tmp_data, ads, gpd, filter_mode);
- }
-
- /* TODO: one day, when sequencer becomes its own datatype, perhaps it should be included here */
- }
- END_ANIMFILTER_SUBCHANNELS;
-
- /* if we collected some channels, add these to the new list... */
- if (tmp_items) {
- /* firstly add object expander if required */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* check if filtering by selection */
- if (ANIMCHANNEL_SELOK((sce->flag & SCE_DS_SELECTED))) {
- /* NOTE: active-status doesn't matter for this! */
- ANIMCHANNEL_NEW_CHANNEL(sce, ANIMTYPE_SCENE, sce, NULL);
- }
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
-
- /* return the number of items added */
- return items;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* filter data contained under object first */
+ BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_SCEC(sce))
+ {
+ bNodeTree *ntree = sce->nodetree;
+ bGPdata *gpd = sce->gpd;
+ World *wo = sce->world;
+
+ /* Action, Drivers, or NLA for Scene */
+ if ((ads->filterflag & ADS_FILTER_NOSCE) == 0) {
+ tmp_items += animdata_filter_ds_scene(ac, &tmp_data, ads, sce, filter_mode);
+ }
+
+ /* world */
+ if ((wo) && !(ads->filterflag & ADS_FILTER_NOWOR)) {
+ tmp_items += animdata_filter_ds_world(ac, &tmp_data, ads, sce, wo, filter_mode);
+ }
+
+ /* nodetree */
+ if ((ntree) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
+ tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, (ID *)sce, ntree, filter_mode);
+ }
+
+ /* line styles */
+ if ((ads->filterflag & ADS_FILTER_NOLINESTYLE) == 0) {
+ tmp_items += animdata_filter_ds_linestyle(ac, &tmp_data, ads, sce, filter_mode);
+ }
+
+ /* grease pencil */
+ if ((gpd) && !(ads->filterflag & ADS_FILTER_NOGPENCIL)) {
+ tmp_items += animdata_filter_ds_gpencil(ac, &tmp_data, ads, gpd, filter_mode);
+ }
+
+ /* TODO: one day, when sequencer becomes its own datatype, perhaps it should be included here */
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* if we collected some channels, add these to the new list... */
+ if (tmp_items) {
+ /* firstly add object expander if required */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by selection */
+ if (ANIMCHANNEL_SELOK((sce->flag & SCE_DS_SELECTED))) {
+ /* NOTE: active-status doesn't matter for this! */
+ ANIMCHANNEL_NEW_CHANNEL(sce, ANIMTYPE_SCENE, sce, NULL);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+
+ /* return the number of items added */
+ return items;
}
-static size_t animdata_filter_ds_movieclip(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, MovieClip *clip, int filter_mode)
+static size_t animdata_filter_ds_movieclip(
+ bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, MovieClip *clip, int filter_mode)
{
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
- size_t items = 0;
- /* add world animation channels */
- BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_MCLIP(clip))
- {
- /* animation data filtering */
- tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)clip, filter_mode);
- }
- END_ANIMFILTER_SUBCHANNELS;
- /* did we find anything? */
- if (tmp_items) {
- /* include data-expand widget first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* check if filtering by active status */
- if (ANIMCHANNEL_ACTIVEOK(clip)) {
- ANIMCHANNEL_NEW_CHANNEL(clip, ANIMTYPE_DSMCLIP, clip, NULL);
- }
- }
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
- /* return the number of items added to the list */
- return items;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+ /* add world animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_MCLIP(clip))
+ {
+ /* animation data filtering */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)clip, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include data-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by active status */
+ if (ANIMCHANNEL_ACTIVEOK(clip)) {
+ ANIMCHANNEL_NEW_CHANNEL(clip, ANIMTYPE_DSMCLIP, clip, NULL);
+ }
+ }
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+ /* return the number of items added to the list */
+ return items;
}
-static size_t animdata_filter_dopesheet_movieclips(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, int filter_mode)
+static size_t animdata_filter_dopesheet_movieclips(bAnimContext *ac,
+ ListBase *anim_data,
+ bDopeSheet *ads,
+ int filter_mode)
{
- size_t items = 0;
- MovieClip *clip;
- for (clip = ac->bmain->movieclips.first; clip != NULL; clip = clip->id.next) {
- /* only show if gpd is used by something... */
- if (ID_REAL_USERS(clip) < 1) {
- continue;
- }
- items += animdata_filter_ds_movieclip(ac, anim_data, ads, clip, filter_mode);
- }
- /* return the number of items added to the list */
- return items;
+ size_t items = 0;
+ MovieClip *clip;
+ for (clip = ac->bmain->movieclips.first; clip != NULL; clip = clip->id.next) {
+ /* only show if gpd is used by something... */
+ if (ID_REAL_USERS(clip) < 1) {
+ continue;
+ }
+ items += animdata_filter_ds_movieclip(ac, anim_data, ads, clip, filter_mode);
+ }
+ /* return the number of items added to the list */
+ return items;
}
/* Helper for animdata_filter_dopesheet() - For checking if an object should be included or not */
static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_mode)
{
- Object *ob = base->object;
-
- if (base->object == NULL)
- return false;
-
- /* 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) == 0)
- return false;
-
- /* outliner restrict-flag */
- if (ob->restrictflag & OB_RESTRICT_VIEW)
- return false;
- }
-
- /* if only F-Curves with visible flags set can be shown, check that
- * datablock hasn't been set to invisible
- */
- if (filter_mode & ANIMFILTER_CURVE_VISIBLE) {
- if ((ob->adt) && (ob->adt->flag & ADT_CURVES_NOT_VISIBLE))
- return false;
- }
-
- /* Pinned curves are visible regardless of selection flags. */
- if ((ob->adt) && (ob->adt->flag & ADT_CURVES_ALWAYS_VISIBLE)) {
- return true;
- }
-
- /* Special case.
- * We don't do recursive checks for pin, but we need to deal with tricky
- * setup like animated camera lens without animated camera location.
- * Without such special handle here we wouldn't be able to bin such
- * camera data only animation to the editor.
- */
- if (ob->adt == NULL && ob->data != NULL) {
- AnimData *data_adt = BKE_animdata_from_id(ob->data);
- if (data_adt != NULL && (data_adt->flag & ADT_CURVES_ALWAYS_VISIBLE)) {
- return true;
- }
- }
-
- /* check selection and object type filters */
- if ((ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & BASE_SELECTED) /*|| (base == sce->basact)*/)) {
- /* only selected should be shown */
- return false;
- }
-
- /* 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)
- return false;
- }
-
- /* no reason to exclude this object... */
- return true;
+ Object *ob = base->object;
+
+ if (base->object == NULL)
+ return false;
+
+ /* 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) == 0)
+ return false;
+
+ /* outliner restrict-flag */
+ if (ob->restrictflag & OB_RESTRICT_VIEW)
+ return false;
+ }
+
+ /* if only F-Curves with visible flags set can be shown, check that
+ * datablock hasn't been set to invisible
+ */
+ if (filter_mode & ANIMFILTER_CURVE_VISIBLE) {
+ if ((ob->adt) && (ob->adt->flag & ADT_CURVES_NOT_VISIBLE))
+ return false;
+ }
+
+ /* Pinned curves are visible regardless of selection flags. */
+ if ((ob->adt) && (ob->adt->flag & ADT_CURVES_ALWAYS_VISIBLE)) {
+ return true;
+ }
+
+ /* Special case.
+ * We don't do recursive checks for pin, but we need to deal with tricky
+ * setup like animated camera lens without animated camera location.
+ * Without such special handle here we wouldn't be able to bin such
+ * camera data only animation to the editor.
+ */
+ if (ob->adt == NULL && ob->data != NULL) {
+ AnimData *data_adt = BKE_animdata_from_id(ob->data);
+ if (data_adt != NULL && (data_adt->flag & ADT_CURVES_ALWAYS_VISIBLE)) {
+ return true;
+ }
+ }
+
+ /* check selection and object type filters */
+ if ((ads->filterflag & ADS_FILTER_ONLYSEL) &&
+ !((base->flag & BASE_SELECTED) /*|| (base == sce->basact)*/)) {
+ /* only selected should be shown */
+ return false;
+ }
+
+ /* 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)
+ return false;
+ }
+
+ /* no reason to exclude this object... */
+ return true;
}
/* Helper for animdata_filter_ds_sorted_bases() - Comparison callback for two Base pointers... */
static int ds_base_sorting_cmp(const void *base1_ptr, const void *base2_ptr)
{
- const Base *b1 = *((const Base **)base1_ptr);
- const Base *b2 = *((const Base **)base2_ptr);
+ const Base *b1 = *((const Base **)base1_ptr);
+ const Base *b2 = *((const Base **)base2_ptr);
- return strcmp(b1->object->id.name + 2, b2->object->id.name + 2);
+ return strcmp(b1->object->id.name + 2, b2->object->id.name + 2);
}
/* Get a sorted list of all the bases - for inclusion in dopesheet (when drawing channels) */
-static Base **animdata_filter_ds_sorted_bases(bDopeSheet *ads, ViewLayer *view_layer, int filter_mode, size_t *r_usable_bases)
+static Base **animdata_filter_ds_sorted_bases(bDopeSheet *ads,
+ ViewLayer *view_layer,
+ int filter_mode,
+ size_t *r_usable_bases)
{
- /* Create an array with space for all the bases, but only containing the usable ones */
- size_t tot_bases = BLI_listbase_count(&view_layer->object_bases);
- 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) {
- if (animdata_filter_base_is_ok(ads, base, filter_mode)) {
- sorted_bases[num_bases++] = base;
- }
- }
-
- /* Sort this list of pointers (based on the names) */
- qsort(sorted_bases, num_bases, sizeof(Base *), ds_base_sorting_cmp);
-
- /* Return list of sorted bases */
- *r_usable_bases = num_bases;
- return sorted_bases;
+ /* Create an array with space for all the bases, but only containing the usable ones */
+ size_t tot_bases = BLI_listbase_count(&view_layer->object_bases);
+ 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) {
+ if (animdata_filter_base_is_ok(ads, base, filter_mode)) {
+ sorted_bases[num_bases++] = base;
+ }
+ }
+
+ /* Sort this list of pointers (based on the names) */
+ qsort(sorted_bases, num_bases, sizeof(Base *), ds_base_sorting_cmp);
+
+ /* Return list of sorted bases */
+ *r_usable_bases = num_bases;
+ return sorted_bases;
}
-
// TODO: implement pinning... (if and when pinning is done, what we need to do is to provide freeing mechanisms - to protect against data that was deleted)
-static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, int filter_mode)
+static size_t animdata_filter_dopesheet(bAnimContext *ac,
+ ListBase *anim_data,
+ bDopeSheet *ads,
+ int filter_mode)
{
- Scene *scene = (Scene *)ads->source;
- ViewLayer *view_layer = (ViewLayer *)ac->view_layer;
- size_t items = 0;
-
- /* check that we do indeed have a scene */
- if ((ads->source == NULL) || (GS(ads->source->name) != ID_SCE)) {
- printf("Dope Sheet Error: No scene!\n");
- if (G.debug & G_DEBUG)
- printf("\tPointer = %p, Name = '%s'\n", (void *)ads->source, (ads->source) ? ads->source->name : NULL);
- return 0;
- }
-
- /* augment the filter-flags with settings based on the dopesheet filterflags
- * so that some temp settings can get added automagically...
- */
- if (ads->filterflag & ADS_FILTER_SELEDIT) {
- /* only selected F-Curves should get their keyframes considered for editability */
- filter_mode |= ANIMFILTER_SELEDIT;
- }
-
- /* Cache files level animations (frame duration and such). */
- if (!(ads->filterflag2 & ADS_FILTER_NOCACHEFILES) && !(ads->filterflag & ADS_FILTER_ONLYSEL)) {
- CacheFile *cache_file = ac->bmain->cachefiles.first;
- for (; cache_file; cache_file = cache_file->id.next) {
- items += animdata_filter_ds_cachefile(ac, anim_data, ads, cache_file, filter_mode);
- }
- }
-
- /* movie clip's animation */
- items += animdata_filter_dopesheet_movieclips(ac, anim_data, ads, filter_mode);
-
- /* scene-linked animation - e.g. world, compositing nodes, scene anim (including sequencer currently) */
- items += animdata_filter_dopesheet_scene(ac, anim_data, ads, scene, filter_mode);
-
- /* If filtering for channel drawing, we want the objects in alphabetical order,
- * to make it easier to predict where items are in the hierarchy
- * - This order only really matters if we need to show all channels in the list (e.g. for drawing)
- * (XXX: What about lingering "active" flags? The order may now become unpredictable)
- * - Don't do this if this behavior has been turned off (i.e. due to it being too slow)
- * - Don't do this if there's just a single object
- */
- if ((filter_mode & ANIMFILTER_LIST_CHANNELS) && !(ads->flag & ADS_FLAG_NO_DB_SORT) &&
- (view_layer->object_bases.first != view_layer->object_bases.last))
- {
- /* Filter list of bases (i.e. objects), sort them, then add their contents normally... */
- // TODO: Cache the old sorted order - if the set of bases hasn't changed, don't re-sort...
- Base **sorted_bases;
- size_t num_bases;
-
- sorted_bases = animdata_filter_ds_sorted_bases(ads, view_layer, filter_mode, &num_bases);
- if (sorted_bases) {
- /* Add the necessary channels for these bases... */
- for (size_t i = 0; i < num_bases; i++) {
- items += animdata_filter_dopesheet_ob(ac, anim_data, ads, sorted_bases[i], filter_mode);
- }
-
- // TODO: store something to validate whether any changes are needed?
-
- /* free temporary data */
- MEM_freeN(sorted_bases);
- }
- }
- else {
- /* 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) {
- 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);
- }
- }
- }
-
- /* return the number of items in the list */
- return items;
+ Scene *scene = (Scene *)ads->source;
+ ViewLayer *view_layer = (ViewLayer *)ac->view_layer;
+ size_t items = 0;
+
+ /* check that we do indeed have a scene */
+ if ((ads->source == NULL) || (GS(ads->source->name) != ID_SCE)) {
+ printf("Dope Sheet Error: No scene!\n");
+ if (G.debug & G_DEBUG)
+ printf("\tPointer = %p, Name = '%s'\n",
+ (void *)ads->source,
+ (ads->source) ? ads->source->name : NULL);
+ return 0;
+ }
+
+ /* augment the filter-flags with settings based on the dopesheet filterflags
+ * so that some temp settings can get added automagically...
+ */
+ if (ads->filterflag & ADS_FILTER_SELEDIT) {
+ /* only selected F-Curves should get their keyframes considered for editability */
+ filter_mode |= ANIMFILTER_SELEDIT;
+ }
+
+ /* Cache files level animations (frame duration and such). */
+ if (!(ads->filterflag2 & ADS_FILTER_NOCACHEFILES) && !(ads->filterflag & ADS_FILTER_ONLYSEL)) {
+ CacheFile *cache_file = ac->bmain->cachefiles.first;
+ for (; cache_file; cache_file = cache_file->id.next) {
+ items += animdata_filter_ds_cachefile(ac, anim_data, ads, cache_file, filter_mode);
+ }
+ }
+
+ /* movie clip's animation */
+ items += animdata_filter_dopesheet_movieclips(ac, anim_data, ads, filter_mode);
+
+ /* scene-linked animation - e.g. world, compositing nodes, scene anim (including sequencer currently) */
+ items += animdata_filter_dopesheet_scene(ac, anim_data, ads, scene, filter_mode);
+
+ /* If filtering for channel drawing, we want the objects in alphabetical order,
+ * to make it easier to predict where items are in the hierarchy
+ * - This order only really matters if we need to show all channels in the list (e.g. for drawing)
+ * (XXX: What about lingering "active" flags? The order may now become unpredictable)
+ * - Don't do this if this behavior has been turned off (i.e. due to it being too slow)
+ * - Don't do this if there's just a single object
+ */
+ if ((filter_mode & ANIMFILTER_LIST_CHANNELS) && !(ads->flag & ADS_FLAG_NO_DB_SORT) &&
+ (view_layer->object_bases.first != view_layer->object_bases.last)) {
+ /* Filter list of bases (i.e. objects), sort them, then add their contents normally... */
+ // TODO: Cache the old sorted order - if the set of bases hasn't changed, don't re-sort...
+ Base **sorted_bases;
+ size_t num_bases;
+
+ sorted_bases = animdata_filter_ds_sorted_bases(ads, view_layer, filter_mode, &num_bases);
+ if (sorted_bases) {
+ /* Add the necessary channels for these bases... */
+ for (size_t i = 0; i < num_bases; i++) {
+ items += animdata_filter_dopesheet_ob(ac, anim_data, ads, sorted_bases[i], filter_mode);
+ }
+
+ // TODO: store something to validate whether any changes are needed?
+
+ /* free temporary data */
+ MEM_freeN(sorted_bases);
+ }
+ }
+ else {
+ /* 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) {
+ 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);
+ }
+ }
+ }
+
+ /* return the number of items in the list */
+ return items;
}
/* Summary track for DopeSheet/Action Editor
* - return code is whether the summary lets the other channels get drawn
*/
-static short animdata_filter_dopesheet_summary(bAnimContext *ac, ListBase *anim_data, int filter_mode, size_t *items)
+static short animdata_filter_dopesheet_summary(bAnimContext *ac,
+ ListBase *anim_data,
+ int filter_mode,
+ size_t *items)
{
- bDopeSheet *ads = NULL;
-
- /* get the DopeSheet information to use
- * - we should only need to deal with the DopeSheet/Action Editor,
- * since all the other Animation Editors won't have this concept
- * being applicable.
- */
- if ((ac && ac->sl) && (ac->spacetype == SPACE_ACTION)) {
- SpaceAction *saction = (SpaceAction *)ac->sl;
- ads = &saction->ads;
- }
- else {
- /* invalid space type - skip this summary channels */
- return 1;
- }
-
- /* dopesheet summary
- * - only for drawing and/or selecting keyframes in channels, but not for real editing
- * - only useful for DopeSheet/Action/etc. editors where it is actually useful
- */
- if ((filter_mode & ANIMFILTER_LIST_CHANNELS) && (ads->filterflag & ADS_FILTER_SUMMARY)) {
- bAnimListElem *ale = make_new_animlistelem(ac, ANIMTYPE_SUMMARY, NULL, NULL);
- if (ale) {
- BLI_addtail(anim_data, ale);
- (*items)++;
- }
-
- /* if summary is collapsed, don't show other channels beneath this
- * - this check is put inside the summary check so that it doesn't interfere with normal operation
- */
- if (ads->flag & ADS_FLAG_SUMMARY_COLLAPSED)
- return 0;
- }
-
- /* the other channels beneath this can be shown */
- return 1;
+ bDopeSheet *ads = NULL;
+
+ /* get the DopeSheet information to use
+ * - we should only need to deal with the DopeSheet/Action Editor,
+ * since all the other Animation Editors won't have this concept
+ * being applicable.
+ */
+ if ((ac && ac->sl) && (ac->spacetype == SPACE_ACTION)) {
+ SpaceAction *saction = (SpaceAction *)ac->sl;
+ ads = &saction->ads;
+ }
+ else {
+ /* invalid space type - skip this summary channels */
+ return 1;
+ }
+
+ /* dopesheet summary
+ * - only for drawing and/or selecting keyframes in channels, but not for real editing
+ * - only useful for DopeSheet/Action/etc. editors where it is actually useful
+ */
+ if ((filter_mode & ANIMFILTER_LIST_CHANNELS) && (ads->filterflag & ADS_FILTER_SUMMARY)) {
+ bAnimListElem *ale = make_new_animlistelem(ac, ANIMTYPE_SUMMARY, NULL, NULL);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ (*items)++;
+ }
+
+ /* if summary is collapsed, don't show other channels beneath this
+ * - this check is put inside the summary check so that it doesn't interfere with normal operation
+ */
+ if (ads->flag & ADS_FLAG_SUMMARY_COLLAPSED)
+ return 0;
+ }
+
+ /* the other channels beneath this can be shown */
+ return 1;
}
/* ......................... */
/* filter data associated with a channel - usually for handling summary-channels in DopeSheet */
-static size_t animdata_filter_animchan(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bAnimListElem *channel, int filter_mode)
+static size_t animdata_filter_animchan(bAnimContext *ac,
+ ListBase *anim_data,
+ bDopeSheet *ads,
+ bAnimListElem *channel,
+ int filter_mode)
{
- size_t items = 0;
-
- /* data to filter depends on channel type */
- /* NOTE: only common channel-types have been handled for now. More can be added as necessary */
- switch (channel->type) {
- case ANIMTYPE_SUMMARY:
- items += animdata_filter_dopesheet(ac, anim_data, ads, filter_mode);
- break;
-
- case ANIMTYPE_SCENE:
- items += animdata_filter_dopesheet_scene(ac, anim_data, ads, channel->data, filter_mode);
- break;
-
- case ANIMTYPE_OBJECT:
- items += animdata_filter_dopesheet_ob(ac, anim_data, ads, channel->data, filter_mode);
- break;
-
- case ANIMTYPE_DSCACHEFILE:
- items += animdata_filter_ds_cachefile(ac, anim_data, ads, channel->data, filter_mode);
- break;
-
- case ANIMTYPE_ANIMDATA:
- items += animfilter_block_data(ac, anim_data, ads, channel->id, filter_mode);
- break;
-
- default:
- printf("ERROR: Unsupported channel type (%d) in animdata_filter_animchan()\n", channel->type);
- break;
- }
-
- return items;
+ size_t items = 0;
+
+ /* data to filter depends on channel type */
+ /* NOTE: only common channel-types have been handled for now. More can be added as necessary */
+ switch (channel->type) {
+ case ANIMTYPE_SUMMARY:
+ items += animdata_filter_dopesheet(ac, anim_data, ads, filter_mode);
+ break;
+
+ case ANIMTYPE_SCENE:
+ items += animdata_filter_dopesheet_scene(ac, anim_data, ads, channel->data, filter_mode);
+ break;
+
+ case ANIMTYPE_OBJECT:
+ items += animdata_filter_dopesheet_ob(ac, anim_data, ads, channel->data, filter_mode);
+ break;
+
+ case ANIMTYPE_DSCACHEFILE:
+ items += animdata_filter_ds_cachefile(ac, anim_data, ads, channel->data, filter_mode);
+ break;
+
+ case ANIMTYPE_ANIMDATA:
+ items += animfilter_block_data(ac, anim_data, ads, channel->id, filter_mode);
+ break;
+
+ default:
+ printf("ERROR: Unsupported channel type (%d) in animdata_filter_animchan()\n",
+ channel->type);
+ break;
+ }
+
+ return items;
}
/* ----------- Cleanup API --------------- */
@@ -3128,57 +3211,57 @@ static size_t animdata_filter_animchan(bAnimContext *ac, ListBase *anim_data, bD
/* Remove entries with invalid types in animation channel list */
static size_t animdata_filter_remove_invalid(ListBase *anim_data)
{
- bAnimListElem *ale, *next;
- size_t items = 0;
+ bAnimListElem *ale, *next;
+ size_t items = 0;
- /* only keep entries with valid types */
- for (ale = anim_data->first; ale; ale = next) {
- next = ale->next;
+ /* only keep entries with valid types */
+ for (ale = anim_data->first; ale; ale = next) {
+ next = ale->next;
- if (ale->type == ANIMTYPE_NONE)
- BLI_freelinkN(anim_data, ale);
- else
- items++;
- }
+ if (ale->type == ANIMTYPE_NONE)
+ BLI_freelinkN(anim_data, ale);
+ else
+ items++;
+ }
- return items;
+ return items;
}
/* Remove duplicate entries in animation channel list */
static size_t animdata_filter_remove_duplis(ListBase *anim_data)
{
- bAnimListElem *ale, *next;
- GSet *gs;
- size_t items = 0;
-
- /* build new hashtable to efficiently store and retrieve which entries have been
- * encountered already while searching
- */
- gs = BLI_gset_ptr_new(__func__);
-
- /* loop through items, removing them from the list if a similar item occurs already */
- for (ale = anim_data->first; ale; ale = next) {
- next = ale->next;
-
- /* check if hash has any record of an entry like this
- * - just use ale->data for now, though it would be nicer to involve
- * ale->type in combination too to capture corner cases (where same data performs differently)
- */
- if (BLI_gset_add(gs, ale->data)) {
- /* this entry is 'unique' and can be kept */
- items++;
- }
- else {
- /* this entry isn't needed anymore */
- BLI_freelinkN(anim_data, ale);
- }
- }
-
- /* free the hash... */
- BLI_gset_free(gs, NULL);
-
- /* return the number of items still in the list */
- return items;
+ bAnimListElem *ale, *next;
+ GSet *gs;
+ size_t items = 0;
+
+ /* build new hashtable to efficiently store and retrieve which entries have been
+ * encountered already while searching
+ */
+ gs = BLI_gset_ptr_new(__func__);
+
+ /* loop through items, removing them from the list if a similar item occurs already */
+ for (ale = anim_data->first; ale; ale = next) {
+ next = ale->next;
+
+ /* check if hash has any record of an entry like this
+ * - just use ale->data for now, though it would be nicer to involve
+ * ale->type in combination too to capture corner cases (where same data performs differently)
+ */
+ if (BLI_gset_add(gs, ale->data)) {
+ /* this entry is 'unique' and can be kept */
+ items++;
+ }
+ else {
+ /* this entry isn't needed anymore */
+ BLI_freelinkN(anim_data, ale);
+ }
+ }
+
+ /* free the hash... */
+ BLI_gset_free(gs, NULL);
+
+ /* return the number of items still in the list */
+ return items;
}
/* ----------- Public API --------------- */
@@ -3190,128 +3273,125 @@ static size_t animdata_filter_remove_duplis(ListBase *anim_data)
* will be placed for use.
* filter_mode: how should the data be filtered - bitmapping accessed flags
*/
-size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_Flags filter_mode, void *data, eAnimCont_Types datatype)
+size_t ANIM_animdata_filter(bAnimContext *ac,
+ ListBase *anim_data,
+ eAnimFilter_Flags filter_mode,
+ void *data,
+ eAnimCont_Types datatype)
{
- size_t items = 0;
-
- /* only filter data if there's somewhere to put it */
- if (data && anim_data) {
- /* firstly filter the data */
- switch (datatype) {
- /* Action-Editing Modes */
- case ANIMCONT_ACTION: /* 'Action Editor' */
- {
- Object *obact = ac->obact;
- SpaceAction *saction = (SpaceAction *)ac->sl;
- bDopeSheet *ads = (saction) ? &saction->ads : NULL;
-
- /* specially check for AnimData filter... [#36687] */
- if (UNLIKELY(filter_mode & ANIMFILTER_ANIMDATA)) {
- /* all channels here are within the same AnimData block, hence this special case */
- if (LIKELY(obact->adt)) {
- ANIMCHANNEL_NEW_CHANNEL(obact->adt, ANIMTYPE_ANIMDATA, (ID *)obact, NULL);
- }
- }
- else {
- /* the check for the DopeSheet summary is included here since the summary works here too */
- if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
- items += animfilter_action(ac, anim_data, ads, data, filter_mode, (ID *)obact);
- }
-
- break;
- }
- case ANIMCONT_SHAPEKEY: /* 'ShapeKey Editor' */
- {
- Key *key = (Key *)data;
-
- /* specially check for AnimData filter... [#36687] */
- if (UNLIKELY(filter_mode & ANIMFILTER_ANIMDATA)) {
- /* all channels here are within the same AnimData block, hence this special case */
- if (LIKELY(key->adt)) {
- ANIMCHANNEL_NEW_CHANNEL(key->adt, ANIMTYPE_ANIMDATA, (ID *)key, NULL);
- }
- }
- else {
- /* the check for the DopeSheet summary is included here since the summary works here too */
- if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
- items = animdata_filter_shapekey(ac, anim_data, key, filter_mode);
- }
-
- break;
- }
-
-
- /* Modes for Specialty Data Types (i.e. not keyframes) */
- case ANIMCONT_GPENCIL:
- {
- if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
- items = animdata_filter_gpencil(ac, anim_data, data, filter_mode);
- break;
- }
- case ANIMCONT_MASK:
- {
- if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
- items = animdata_filter_mask(ac->bmain, anim_data, data, filter_mode);
- break;
- }
-
-
- /* DopeSheet Based Modes */
- case ANIMCONT_DOPESHEET: /* 'DopeSheet Editor' */
- {
- /* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */
- if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
- items += animdata_filter_dopesheet(ac, anim_data, data, filter_mode);
- break;
- }
- case ANIMCONT_FCURVES: /* Graph Editor -> F-Curves/Animation Editing */
- case ANIMCONT_DRIVERS: /* Graph Editor -> Drivers Editing */
- case ANIMCONT_NLA: /* NLA Editor */
- {
- /* all of these editors use the basic DopeSheet data for filtering options,
- * but don't have all the same features */
- items = animdata_filter_dopesheet(ac, anim_data, data, filter_mode);
- break;
- }
-
-
- /* Timeline Mode - Basically the same as dopesheet, except we only have the summary for now */
- case ANIMCONT_TIMELINE:
- {
- /* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */
- if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
- items += animdata_filter_dopesheet(ac, anim_data, data, filter_mode);
- break;
- }
-
- /* Special/Internal Use */
- case ANIMCONT_CHANNEL: /* animation channel */
- {
- bDopeSheet *ads = ac->ads;
-
- /* based on the channel type, filter relevant data for this */
- items = animdata_filter_animchan(ac, anim_data, ads, data, filter_mode);
- break;
- }
-
- /* unhandled */
- default:
- {
- printf("ANIM_animdata_filter() - Invalid datatype argument %u\n", datatype);
- break;
- }
- }
-
- /* remove any 'weedy' entries */
- items = animdata_filter_remove_invalid(anim_data);
-
- /* remove duplicates (if required) */
- if (filter_mode & ANIMFILTER_NODUPLIS)
- items = animdata_filter_remove_duplis(anim_data);
- }
-
- /* return the number of items in the list */
- return items;
+ size_t items = 0;
+
+ /* only filter data if there's somewhere to put it */
+ if (data && anim_data) {
+ /* firstly filter the data */
+ switch (datatype) {
+ /* Action-Editing Modes */
+ case ANIMCONT_ACTION: /* 'Action Editor' */
+ {
+ Object *obact = ac->obact;
+ SpaceAction *saction = (SpaceAction *)ac->sl;
+ bDopeSheet *ads = (saction) ? &saction->ads : NULL;
+
+ /* specially check for AnimData filter... [#36687] */
+ if (UNLIKELY(filter_mode & ANIMFILTER_ANIMDATA)) {
+ /* all channels here are within the same AnimData block, hence this special case */
+ if (LIKELY(obact->adt)) {
+ ANIMCHANNEL_NEW_CHANNEL(obact->adt, ANIMTYPE_ANIMDATA, (ID *)obact, NULL);
+ }
+ }
+ else {
+ /* the check for the DopeSheet summary is included here since the summary works here too */
+ if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
+ items += animfilter_action(ac, anim_data, ads, data, filter_mode, (ID *)obact);
+ }
+
+ break;
+ }
+ case ANIMCONT_SHAPEKEY: /* 'ShapeKey Editor' */
+ {
+ Key *key = (Key *)data;
+
+ /* specially check for AnimData filter... [#36687] */
+ if (UNLIKELY(filter_mode & ANIMFILTER_ANIMDATA)) {
+ /* all channels here are within the same AnimData block, hence this special case */
+ if (LIKELY(key->adt)) {
+ ANIMCHANNEL_NEW_CHANNEL(key->adt, ANIMTYPE_ANIMDATA, (ID *)key, NULL);
+ }
+ }
+ else {
+ /* the check for the DopeSheet summary is included here since the summary works here too */
+ if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
+ items = animdata_filter_shapekey(ac, anim_data, key, filter_mode);
+ }
+
+ break;
+ }
+
+ /* Modes for Specialty Data Types (i.e. not keyframes) */
+ case ANIMCONT_GPENCIL: {
+ if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
+ items = animdata_filter_gpencil(ac, anim_data, data, filter_mode);
+ break;
+ }
+ case ANIMCONT_MASK: {
+ if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
+ items = animdata_filter_mask(ac->bmain, anim_data, data, filter_mode);
+ break;
+ }
+
+ /* DopeSheet Based Modes */
+ case ANIMCONT_DOPESHEET: /* 'DopeSheet Editor' */
+ {
+ /* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */
+ if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
+ items += animdata_filter_dopesheet(ac, anim_data, data, filter_mode);
+ break;
+ }
+ case ANIMCONT_FCURVES: /* Graph Editor -> F-Curves/Animation Editing */
+ case ANIMCONT_DRIVERS: /* Graph Editor -> Drivers Editing */
+ case ANIMCONT_NLA: /* NLA Editor */
+ {
+ /* all of these editors use the basic DopeSheet data for filtering options,
+ * but don't have all the same features */
+ items = animdata_filter_dopesheet(ac, anim_data, data, filter_mode);
+ break;
+ }
+
+ /* Timeline Mode - Basically the same as dopesheet, except we only have the summary for now */
+ case ANIMCONT_TIMELINE: {
+ /* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */
+ if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
+ items += animdata_filter_dopesheet(ac, anim_data, data, filter_mode);
+ break;
+ }
+
+ /* Special/Internal Use */
+ case ANIMCONT_CHANNEL: /* animation channel */
+ {
+ bDopeSheet *ads = ac->ads;
+
+ /* based on the channel type, filter relevant data for this */
+ items = animdata_filter_animchan(ac, anim_data, ads, data, filter_mode);
+ break;
+ }
+
+ /* unhandled */
+ default: {
+ printf("ANIM_animdata_filter() - Invalid datatype argument %u\n", datatype);
+ break;
+ }
+ }
+
+ /* remove any 'weedy' entries */
+ items = animdata_filter_remove_invalid(anim_data);
+
+ /* remove duplicates (if required) */
+ if (filter_mode & ANIMFILTER_NODUPLIS)
+ items = animdata_filter_remove_duplis(anim_data);
+ }
+
+ /* return the number of items in the list */
+ return items;
}
/* ************************************************************ */
diff --git a/source/blender/editors/animation/anim_intern.h b/source/blender/editors/animation/anim_intern.h
index 4661d19378a..7fb5540fdf7 100644
--- a/source/blender/editors/animation/anim_intern.h
+++ b/source/blender/editors/animation/anim_intern.h
@@ -21,7 +21,6 @@
* \ingroup edanimation
*/
-
#ifndef __ANIM_INTERN_H__
#define __ANIM_INTERN_H__
@@ -79,4 +78,4 @@ void ANIM_OT_driver_button_edit(struct wmOperatorType *ot);
void ANIM_OT_copy_driver_button(struct wmOperatorType *ot);
void ANIM_OT_paste_driver_button(struct wmOperatorType *ot);
-#endif /* __ANIM_INTERN_H__ */
+#endif /* __ANIM_INTERN_H__ */
diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c
index 03cc4855a4b..fd22fa16fe8 100644
--- a/source/blender/editors/animation/anim_ipo_utils.c
+++ b/source/blender/editors/animation/anim_ipo_utils.c
@@ -21,14 +21,12 @@
* \ingroup edanimation
*/
-
/* This file contains code for presenting F-Curves and other animation data
* in the UI (especially for use in the Animation Editors).
*
* -- Joshua Leung, Dec 2008
*/
-
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
@@ -51,172 +49,176 @@
*/
int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
{
- int icon = 0;
-
- /* sanity checks */
- if (name == NULL)
- return icon;
- else if (ELEM(NULL, id, fcu, fcu->rna_path)) {
- if (fcu == NULL)
- strcpy(name, IFACE_("<invalid>"));
- else if (fcu->rna_path == NULL)
- strcpy(name, IFACE_("<no path>"));
- else /* id == NULL */
- BLI_snprintf(name, 256, "%s[%d]", fcu->rna_path, fcu->array_index);
- }
- else {
- PointerRNA id_ptr, ptr;
- PropertyRNA *prop;
-
- /* get RNA pointer, and resolve the path */
- RNA_id_pointer_create(id, &id_ptr);
-
- /* try to resolve the path */
- if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
- const char *structname = NULL, *propname = NULL;
- char arrayindbuf[16];
- const char *arrayname = NULL;
- short free_structname = 0;
-
- /* For now, name will consist of 3 parts: struct-name, property name, array index
- * There are several options possible:
- * 1) <struct-name>.<property-name>.<array-index>
- * i.e. Bone1.Location.X, or Object.Location.X
- * 2) <array-index> <property-name> (<struct name>)
- * i.e. X Location (Bone1), or X Location (Object)
- *
- * Currently, option 2 is in use, to try and make it easier to quickly identify F-Curves (it does have
- * problems with looking rather odd though). Option 1 is better in terms of revealing a consistent sense of
- * hierarchy though, which isn't so clear with option 2.
- */
-
- /* for structname
- * - as base, we use a custom name from the structs if one is available
- * - however, if we're showing subdata of bones (probably there will be other exceptions later)
- * need to include that info too since it gets confusing otherwise
- * - if a pointer just refers to the ID-block, then don't repeat this info
- * since this just introduces clutter
- */
- if (strstr(fcu->rna_path, "bones") && strstr(fcu->rna_path, "constraints")) {
- /* perform string 'chopping' to get "Bone Name : Constraint Name" */
- char *pchanName = BLI_str_quoted_substrN(fcu->rna_path, "bones[");
- char *constName = BLI_str_quoted_substrN(fcu->rna_path, "constraints[");
-
- /* assemble the string to display in the UI... */
- structname = BLI_sprintfN("%s : %s", pchanName, constName);
- free_structname = 1;
-
- /* free the temp names */
- if (pchanName) MEM_freeN(pchanName);
- if (constName) MEM_freeN(constName);
- }
- else if (ptr.data != ptr.id.data) {
- PropertyRNA *nameprop = RNA_struct_name_property(ptr.type);
- if (nameprop) {
- /* this gets a string which will need to be freed */
- structname = RNA_property_string_get_alloc(&ptr, nameprop, NULL, 0, NULL);
- free_structname = 1;
- }
- else
- structname = RNA_struct_ui_name(ptr.type);
- }
-
- /* Property Name is straightforward */
- propname = RNA_property_ui_name(prop);
-
- /* Array Index - only if applicable */
- if (RNA_property_array_check(prop)) {
- char c = RNA_property_array_item_char(prop, fcu->array_index);
-
- /* we need to write the index to a temp buffer (in py syntax) */
- if (c) BLI_snprintf(arrayindbuf, sizeof(arrayindbuf), "%c ", c);
- else BLI_snprintf(arrayindbuf, sizeof(arrayindbuf), "[%d]", fcu->array_index);
-
- arrayname = &arrayindbuf[0];
- }
- else {
- /* no array index */
- arrayname = "";
- }
-
- /* putting this all together into the buffer */
- /* XXX we need to check for invalid names...
- * XXX the name length limit needs to be passed in or as some define */
- if (structname)
- BLI_snprintf(name, 256, "%s%s (%s)", arrayname, propname, structname);
- else
- BLI_snprintf(name, 256, "%s%s", arrayname, propname);
-
- /* free temp name if nameprop is set */
- if (free_structname)
- MEM_freeN((void *)structname);
-
-
- /* Icon for this property's owner:
- * use the struct's icon if it is set
- */
- 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]
- */
- fcu->flag &= ~FCURVE_DISABLED;
- }
- else {
- /* invalid path */
- BLI_snprintf(name, 256, "\"%s[%d]\"", fcu->rna_path, fcu->array_index);
-
- /* icon for this should be the icon for the base ID */
- /* TODO: or should we just use the error icon? */
- icon = RNA_struct_ui_icon(id_ptr.type);
-
- /* tag F-Curve as disabled - as not usable path */
- fcu->flag |= FCURVE_DISABLED;
- }
- }
-
- /* return the icon that the active data had */
- return icon;
+ int icon = 0;
+
+ /* sanity checks */
+ if (name == NULL)
+ return icon;
+ else if (ELEM(NULL, id, fcu, fcu->rna_path)) {
+ if (fcu == NULL)
+ strcpy(name, IFACE_("<invalid>"));
+ else if (fcu->rna_path == NULL)
+ strcpy(name, IFACE_("<no path>"));
+ else /* id == NULL */
+ BLI_snprintf(name, 256, "%s[%d]", fcu->rna_path, fcu->array_index);
+ }
+ else {
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+
+ /* get RNA pointer, and resolve the path */
+ RNA_id_pointer_create(id, &id_ptr);
+
+ /* try to resolve the path */
+ if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
+ const char *structname = NULL, *propname = NULL;
+ char arrayindbuf[16];
+ const char *arrayname = NULL;
+ short free_structname = 0;
+
+ /* For now, name will consist of 3 parts: struct-name, property name, array index
+ * There are several options possible:
+ * 1) <struct-name>.<property-name>.<array-index>
+ * i.e. Bone1.Location.X, or Object.Location.X
+ * 2) <array-index> <property-name> (<struct name>)
+ * i.e. X Location (Bone1), or X Location (Object)
+ *
+ * Currently, option 2 is in use, to try and make it easier to quickly identify F-Curves (it does have
+ * problems with looking rather odd though). Option 1 is better in terms of revealing a consistent sense of
+ * hierarchy though, which isn't so clear with option 2.
+ */
+
+ /* for structname
+ * - as base, we use a custom name from the structs if one is available
+ * - however, if we're showing subdata of bones (probably there will be other exceptions later)
+ * need to include that info too since it gets confusing otherwise
+ * - if a pointer just refers to the ID-block, then don't repeat this info
+ * since this just introduces clutter
+ */
+ if (strstr(fcu->rna_path, "bones") && strstr(fcu->rna_path, "constraints")) {
+ /* perform string 'chopping' to get "Bone Name : Constraint Name" */
+ char *pchanName = BLI_str_quoted_substrN(fcu->rna_path, "bones[");
+ char *constName = BLI_str_quoted_substrN(fcu->rna_path, "constraints[");
+
+ /* assemble the string to display in the UI... */
+ structname = BLI_sprintfN("%s : %s", pchanName, constName);
+ free_structname = 1;
+
+ /* free the temp names */
+ if (pchanName)
+ MEM_freeN(pchanName);
+ if (constName)
+ MEM_freeN(constName);
+ }
+ else if (ptr.data != ptr.id.data) {
+ PropertyRNA *nameprop = RNA_struct_name_property(ptr.type);
+ if (nameprop) {
+ /* this gets a string which will need to be freed */
+ structname = RNA_property_string_get_alloc(&ptr, nameprop, NULL, 0, NULL);
+ free_structname = 1;
+ }
+ else
+ structname = RNA_struct_ui_name(ptr.type);
+ }
+
+ /* Property Name is straightforward */
+ propname = RNA_property_ui_name(prop);
+
+ /* Array Index - only if applicable */
+ if (RNA_property_array_check(prop)) {
+ char c = RNA_property_array_item_char(prop, fcu->array_index);
+
+ /* we need to write the index to a temp buffer (in py syntax) */
+ if (c)
+ BLI_snprintf(arrayindbuf, sizeof(arrayindbuf), "%c ", c);
+ else
+ BLI_snprintf(arrayindbuf, sizeof(arrayindbuf), "[%d]", fcu->array_index);
+
+ arrayname = &arrayindbuf[0];
+ }
+ else {
+ /* no array index */
+ arrayname = "";
+ }
+
+ /* putting this all together into the buffer */
+ /* XXX we need to check for invalid names...
+ * XXX the name length limit needs to be passed in or as some define */
+ if (structname)
+ BLI_snprintf(name, 256, "%s%s (%s)", arrayname, propname, structname);
+ else
+ BLI_snprintf(name, 256, "%s%s", arrayname, propname);
+
+ /* free temp name if nameprop is set */
+ if (free_structname)
+ MEM_freeN((void *)structname);
+
+ /* Icon for this property's owner:
+ * use the struct's icon if it is set
+ */
+ 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]
+ */
+ fcu->flag &= ~FCURVE_DISABLED;
+ }
+ else {
+ /* invalid path */
+ BLI_snprintf(name, 256, "\"%s[%d]\"", fcu->rna_path, fcu->array_index);
+
+ /* icon for this should be the icon for the base ID */
+ /* TODO: or should we just use the error icon? */
+ icon = RNA_struct_ui_icon(id_ptr.type);
+
+ /* tag F-Curve as disabled - as not usable path */
+ fcu->flag |= FCURVE_DISABLED;
+ }
+ }
+
+ /* return the icon that the active data had */
+ return icon;
}
/* ------------------------------- Color Codes for F-Curve Channels ---------------------------- */
/* step between the major distinguishable color bands of the primary colors */
-#define HSV_BANDWIDTH 0.3f
+#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 getcolor_fcurve_rainbow(int cur, int tot, float out[3])
{
- float hsv[3], fac;
- int grouping;
-
- /* we try to divide the color into groupings of n colors,
- * where n is:
- * 3 - for 'odd' numbers of curves - there should be a majority of triplets of curves
- * 4 - for 'even' numbers of curves - there should be a majority of quartets of curves
- * so the base color is simply one of the three primary colors
- */
- grouping = (4 - (tot % 2));
- hsv[0] = HSV_BANDWIDTH * (float)(cur % grouping);
-
- /* 'Value' (i.e. darkness) needs to vary so that larger sets of three will be
- * 'darker' (i.e. smaller value), so that they don't look that similar to previous ones.
- * However, only a range of 0.3 to 1.0 is really usable to avoid clashing
- * with some other stuff
- */
- fac = ((float)cur / (float)tot) * 0.7f;
-
- /* the base color can get offset a bit so that the colors aren't so identical */
- hsv[0] += fac * HSV_BANDWIDTH;
- if (hsv[0] > 1.0f) hsv[0] = fmod(hsv[0], 1.0f);
-
- /* saturation adjustments for more visible range */
- hsv[1] = ((hsv[0] > 0.5f) && (hsv[0] < 0.8f)) ? 0.5f : 0.6f;
-
- /* value is fixed at 1.0f, otherwise we cannot clearly see the curves... */
- hsv[2] = 1.0f;
-
- /* finally, conver this to RGB colors */
- hsv_to_rgb_v(hsv, out);
+ float hsv[3], fac;
+ int grouping;
+
+ /* we try to divide the color into groupings of n colors,
+ * where n is:
+ * 3 - for 'odd' numbers of curves - there should be a majority of triplets of curves
+ * 4 - for 'even' numbers of curves - there should be a majority of quartets of curves
+ * so the base color is simply one of the three primary colors
+ */
+ grouping = (4 - (tot % 2));
+ hsv[0] = HSV_BANDWIDTH * (float)(cur % grouping);
+
+ /* 'Value' (i.e. darkness) needs to vary so that larger sets of three will be
+ * 'darker' (i.e. smaller value), so that they don't look that similar to previous ones.
+ * However, only a range of 0.3 to 1.0 is really usable to avoid clashing
+ * with some other stuff
+ */
+ fac = ((float)cur / (float)tot) * 0.7f;
+
+ /* the base color can get offset a bit so that the colors aren't so identical */
+ hsv[0] += fac * HSV_BANDWIDTH;
+ if (hsv[0] > 1.0f)
+ hsv[0] = fmod(hsv[0], 1.0f);
+
+ /* saturation adjustments for more visible range */
+ hsv[1] = ((hsv[0] > 0.5f) && (hsv[0] < 0.8f)) ? 0.5f : 0.6f;
+
+ /* value is fixed at 1.0f, otherwise we cannot clearly see the curves... */
+ hsv[2] = 1.0f;
+
+ /* finally, conver this to RGB colors */
+ hsv_to_rgb_v(hsv, out);
}
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 7a9bb1df477..beffa47b2c5 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -76,24 +76,24 @@
/* helper function for getting the list of markers to work on */
static ListBase *context_get_markers(Scene *scene, ScrArea *sa)
{
- /* local marker sets... */
- if (sa) {
- if (sa->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)sa->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?
- */
- if (ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY) && (saction->action)) {
- if (saction->flag & SACTION_POSEMARKERS_SHOW) {
- return &saction->action->markers;
- }
- }
- }
- }
-
- /* default to using the scene's markers */
- return &scene->markers;
+ /* local marker sets... */
+ if (sa) {
+ if (sa->spacetype == SPACE_ACTION) {
+ SpaceAction *saction = (SpaceAction *)sa->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?
+ */
+ if (ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY) && (saction->action)) {
+ if (saction->flag & SACTION_POSEMARKERS_SHOW) {
+ return &saction->action->markers;
+ }
+ }
+ }
+ }
+
+ /* default to using the scene's markers */
+ return &scene->markers;
}
/* ............. */
@@ -101,16 +101,16 @@ static ListBase *context_get_markers(Scene *scene, ScrArea *sa)
/* public API for getting markers from context */
ListBase *ED_context_get_markers(const bContext *C)
{
- return context_get_markers(CTX_data_scene(C), CTX_wm_area(C));
+ return context_get_markers(CTX_data_scene(C), CTX_wm_area(C));
}
/* public API for getting markers from "animation" context */
ListBase *ED_animcontext_get_markers(const bAnimContext *ac)
{
- if (ac)
- return context_get_markers(ac->scene, ac->sa);
- else
- return NULL;
+ if (ac)
+ return context_get_markers(ac->scene, ac->sa);
+ else
+ return NULL;
}
/* --------------------------------- */
@@ -125,48 +125,43 @@ ListBase *ED_animcontext_get_markers(const bAnimContext *ac)
* (which is delta transform for grab/extend, and scale factor for scale)
* \param side: (B/L/R) for 'extend' functionality, which side of current frame to use
*/
-int ED_markers_post_apply_transform(ListBase *markers, Scene *scene, int mode, float value, char side)
+int ED_markers_post_apply_transform(
+ ListBase *markers, Scene *scene, int mode, float value, char side)
{
- TimeMarker *marker;
- float cfra = (float)CFRA;
- int changed_tot = 0;
-
- /* sanity check - no markers, or locked markers */
- if ((scene->toolsettings->lock_markers) ||
- (markers == NULL))
- {
- return changed_tot;
- }
-
- /* affect selected markers - it's unlikely that we will want to affect all in this way? */
- for (marker = markers->first; marker; marker = marker->next) {
- if (marker->flag & SELECT) {
- switch (mode) {
- case TFM_TIME_TRANSLATE:
- case TFM_TIME_EXTEND:
- {
- /* apply delta if marker is on the right side of the current frame */
- if ((side == 'B') ||
- (side == 'L' && marker->frame < cfra) ||
- (side == 'R' && marker->frame >= cfra))
- {
- marker->frame += round_fl_to_int(value);
- changed_tot++;
- }
- break;
- }
- case TFM_TIME_SCALE:
- {
- /* rescale the distance between the marker and the current frame */
- marker->frame = cfra + round_fl_to_int((float)(marker->frame - cfra) * value);
- changed_tot++;
- break;
- }
- }
- }
- }
-
- return changed_tot;
+ TimeMarker *marker;
+ float cfra = (float)CFRA;
+ int changed_tot = 0;
+
+ /* sanity check - no markers, or locked markers */
+ if ((scene->toolsettings->lock_markers) || (markers == NULL)) {
+ return changed_tot;
+ }
+
+ /* affect selected markers - it's unlikely that we will want to affect all in this way? */
+ for (marker = markers->first; marker; marker = marker->next) {
+ if (marker->flag & SELECT) {
+ switch (mode) {
+ case TFM_TIME_TRANSLATE:
+ case TFM_TIME_EXTEND: {
+ /* apply delta if marker is on the right side of the current frame */
+ if ((side == 'B') || (side == 'L' && marker->frame < cfra) ||
+ (side == 'R' && marker->frame >= cfra)) {
+ marker->frame += round_fl_to_int(value);
+ changed_tot++;
+ }
+ break;
+ }
+ case TFM_TIME_SCALE: {
+ /* rescale the distance between the marker and the current frame */
+ marker->frame = cfra + round_fl_to_int((float)(marker->frame - cfra) * value);
+ changed_tot++;
+ break;
+ }
+ }
+ }
+ }
+
+ return changed_tot;
}
/* --------------------------------- */
@@ -175,58 +170,57 @@ int ED_markers_post_apply_transform(ListBase *markers, Scene *scene, int mode, f
/* XXX for select, the min_dist should be small */
TimeMarker *ED_markers_find_nearest_marker(ListBase *markers, float x)
{
- TimeMarker *marker, *nearest = NULL;
- float dist, min_dist = 1000000;
+ TimeMarker *marker, *nearest = NULL;
+ float dist, min_dist = 1000000;
- if (markers) {
- for (marker = markers->first; marker; marker = marker->next) {
- dist = fabsf((float)marker->frame - x);
+ if (markers) {
+ for (marker = markers->first; marker; marker = marker->next) {
+ dist = fabsf((float)marker->frame - x);
- if (dist < min_dist) {
- min_dist = dist;
- nearest = marker;
- }
- }
- }
+ if (dist < min_dist) {
+ min_dist = dist;
+ nearest = marker;
+ }
+ }
+ }
- return nearest;
+ return nearest;
}
/* Return the time of the marker that occurs on a frame closest to the given time */
int ED_markers_find_nearest_marker_time(ListBase *markers, float x)
{
- TimeMarker *nearest = ED_markers_find_nearest_marker(markers, x);
- return (nearest) ? (nearest->frame) : round_fl_to_int(x);
+ TimeMarker *nearest = ED_markers_find_nearest_marker(markers, x);
+ return (nearest) ? (nearest->frame) : round_fl_to_int(x);
}
-
void ED_markers_get_minmax(ListBase *markers, short sel, float *first, float *last)
{
- TimeMarker *marker;
- float min, max;
-
- /* 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;
- return;
- }
-
- min = FLT_MAX;
- max = -FLT_MAX;
- for (marker = markers->first; marker; marker = marker->next) {
- if (!sel || (marker->flag & SELECT)) {
- if (marker->frame < min)
- min = (float)marker->frame;
- if (marker->frame > max)
- max = (float)marker->frame;
- }
- }
-
- /* set the min/max values */
- *first = min;
- *last = max;
+ TimeMarker *marker;
+ float min, max;
+
+ /* 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;
+ return;
+ }
+
+ min = FLT_MAX;
+ max = -FLT_MAX;
+ for (marker = markers->first; marker; marker = marker->next) {
+ if (!sel || (marker->flag & SELECT)) {
+ if (marker->frame < min)
+ min = (float)marker->frame;
+ if (marker->frame > max)
+ max = (float)marker->frame;
+ }
+ }
+
+ /* set the min/max values */
+ *first = min;
+ *last = max;
}
/* --------------------------------- */
@@ -234,31 +228,33 @@ void ED_markers_get_minmax(ListBase *markers, short sel, float *first, float *la
/* Adds a marker to list of cfra elems */
static void add_marker_to_cfra_elem(ListBase *lb, TimeMarker *marker, short only_sel)
{
- CfraElem *ce, *cen;
-
- /* should this one only be considered if it is selected? */
- if ((only_sel) && ((marker->flag & SELECT) == 0))
- return;
-
- /* insertion sort - try to find a previous cfra elem */
- for (ce = lb->first; ce; ce = ce->next) {
- if (ce->cfra == marker->frame) {
- /* do because of double keys */
- if (marker->flag & SELECT)
- ce->sel = marker->flag;
- return;
- }
- else if (ce->cfra > marker->frame) {
- break;
- }
- }
-
- cen = MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem");
- if (ce) BLI_insertlinkbefore(lb, ce, cen);
- else BLI_addtail(lb, cen);
-
- cen->cfra = marker->frame;
- cen->sel = marker->flag;
+ CfraElem *ce, *cen;
+
+ /* should this one only be considered if it is selected? */
+ if ((only_sel) && ((marker->flag & SELECT) == 0))
+ return;
+
+ /* insertion sort - try to find a previous cfra elem */
+ for (ce = lb->first; ce; ce = ce->next) {
+ if (ce->cfra == marker->frame) {
+ /* do because of double keys */
+ if (marker->flag & SELECT)
+ ce->sel = marker->flag;
+ return;
+ }
+ else if (ce->cfra > marker->frame) {
+ break;
+ }
+ }
+
+ cen = MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem");
+ if (ce)
+ BLI_insertlinkbefore(lb, ce, cen);
+ else
+ BLI_addtail(lb, cen);
+
+ cen->cfra = marker->frame;
+ cen->sel = marker->flag;
}
/* This function makes a list of all the markers. The only_sel
@@ -267,47 +263,47 @@ static void add_marker_to_cfra_elem(ListBase *lb, TimeMarker *marker, short only
*/
void ED_markers_make_cfra_list(ListBase *markers, ListBase *lb, short only_sel)
{
- TimeMarker *marker;
-
- if (lb) {
- /* Clear the list first, since callers have no way of knowing
- * whether this terminated early otherwise. This may lead
- * to crashes if the user didn't clear the memory first.
- */
- lb->first = lb->last = NULL;
- }
- else {
- return;
- }
-
- if (markers == NULL) {
- return;
- }
-
- for (marker = markers->first; marker; marker = marker->next)
- add_marker_to_cfra_elem(lb, marker, only_sel);
+ TimeMarker *marker;
+
+ if (lb) {
+ /* Clear the list first, since callers have no way of knowing
+ * whether this terminated early otherwise. This may lead
+ * to crashes if the user didn't clear the memory first.
+ */
+ lb->first = lb->last = NULL;
+ }
+ else {
+ return;
+ }
+
+ if (markers == NULL) {
+ return;
+ }
+
+ for (marker = markers->first; marker; marker = marker->next)
+ add_marker_to_cfra_elem(lb, marker, only_sel);
}
void ED_markers_deselect_all(ListBase *markers, int action)
{
- if (action == SEL_TOGGLE) {
- action = ED_markers_get_first_selected(markers) ? SEL_DESELECT : SEL_SELECT;
- }
-
- for (TimeMarker *marker = markers->first; marker; marker = marker->next) {
- if (action == SEL_SELECT) {
- marker->flag |= SELECT;
- }
- else if (action == SEL_DESELECT) {
- marker->flag &= ~SELECT;
- }
- else if (action == SEL_INVERT) {
- marker->flag ^= SELECT;
- }
- else {
- BLI_assert(0);
- }
- }
+ if (action == SEL_TOGGLE) {
+ action = ED_markers_get_first_selected(markers) ? SEL_DESELECT : SEL_SELECT;
+ }
+
+ for (TimeMarker *marker = markers->first; marker; marker = marker->next) {
+ if (action == SEL_SELECT) {
+ marker->flag |= SELECT;
+ }
+ else if (action == SEL_DESELECT) {
+ marker->flag &= ~SELECT;
+ }
+ else if (action == SEL_INVERT) {
+ marker->flag ^= SELECT;
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
}
/* --------------------------------- */
@@ -315,16 +311,16 @@ void ED_markers_deselect_all(ListBase *markers, int action)
/* Get the first selected marker */
TimeMarker *ED_markers_get_first_selected(ListBase *markers)
{
- TimeMarker *marker;
+ TimeMarker *marker;
- if (markers) {
- for (marker = markers->first; marker; marker = marker->next) {
- if (marker->flag & SELECT)
- return marker;
- }
- }
+ if (markers) {
+ for (marker = markers->first; marker; marker = marker->next) {
+ if (marker->flag & SELECT)
+ return marker;
+ }
+ }
- return NULL;
+ return NULL;
}
/* --------------------------------- */
@@ -334,226 +330,229 @@ TimeMarker *ED_markers_get_first_selected(ListBase *markers)
*/
void debug_markers_print_list(ListBase *markers)
{
- TimeMarker *marker;
+ TimeMarker *marker;
- if (markers == NULL) {
- printf("No markers list to print debug for\n");
- return;
- }
+ if (markers == NULL) {
+ printf("No markers list to print debug for\n");
+ return;
+ }
- printf("List of markers follows: -----\n");
+ printf("List of markers follows: -----\n");
- for (marker = markers->first; marker; marker = marker->next) {
- printf("\t'%s' on %d at %p with %u\n", marker->name, marker->frame, (void *)marker, marker->flag);
- }
+ for (marker = markers->first; marker; marker = marker->next) {
+ printf(
+ "\t'%s' on %d at %p with %u\n", marker->name, marker->frame, (void *)marker, marker->flag);
+ }
- printf("End of list ------------------\n");
+ printf("End of list ------------------\n");
}
/* ************* Marker Drawing ************ */
-static void draw_marker_name(
- const uiFontStyle *fstyle, TimeMarker *marker, const char *name,
- int cfra, const float xpos, const float ypixels)
+static void draw_marker_name(const uiFontStyle *fstyle,
+ TimeMarker *marker,
+ const char *name,
+ int cfra,
+ const float xpos,
+ const float ypixels)
{
- unsigned char text_col[4];
- float x, y;
-
- /* minimal y coordinate which wouldn't be occluded by scroll */
- int min_y = 17.0f * UI_DPI_FAC;
-
- if (marker->flag & SELECT) {
- UI_GetThemeColor4ubv(TH_TEXT_HI, text_col);
- x = xpos + 4.0f * UI_DPI_FAC;
- y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC;
- y = max_ii(y, min_y);
- }
- else {
- UI_GetThemeColor4ubv(TH_TEXT, text_col);
- if ((marker->frame <= cfra) && (marker->frame + 5 > cfra)) {
- x = xpos + 8.0f * UI_DPI_FAC;
- y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC;
- y = max_ii(y, min_y);
- }
- else {
- x = xpos + 8.0f * UI_DPI_FAC;
- y = 17.0f * UI_DPI_FAC;
- }
- }
+ unsigned char text_col[4];
+ float x, y;
+
+ /* minimal y coordinate which wouldn't be occluded by scroll */
+ int min_y = 17.0f * UI_DPI_FAC;
+
+ if (marker->flag & SELECT) {
+ UI_GetThemeColor4ubv(TH_TEXT_HI, text_col);
+ x = xpos + 4.0f * UI_DPI_FAC;
+ y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC;
+ y = max_ii(y, min_y);
+ }
+ else {
+ UI_GetThemeColor4ubv(TH_TEXT, text_col);
+ if ((marker->frame <= cfra) && (marker->frame + 5 > cfra)) {
+ x = xpos + 8.0f * UI_DPI_FAC;
+ y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC;
+ y = max_ii(y, min_y);
+ }
+ else {
+ x = xpos + 8.0f * UI_DPI_FAC;
+ y = 17.0f * UI_DPI_FAC;
+ }
+ }
#ifdef DURIAN_CAMERA_SWITCH
- if (marker->camera && (marker->camera->restrictflag & OB_RESTRICT_RENDER)) {
- text_col[3] = 100;
- }
+ if (marker->camera && (marker->camera->restrictflag & OB_RESTRICT_RENDER)) {
+ text_col[3] = 100;
+ }
#endif
- UI_fontstyle_draw_simple(fstyle, x, y, name, text_col);
+ UI_fontstyle_draw_simple(fstyle, x, y, name, text_col);
}
static void draw_marker_line(const float color[4], float x, float ymin, float ymax)
{
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
- immUniformColor4fv(color);
- immUniform1i("colors_len", 0); /* "simple" mode */
- immUniform1f("dash_width", 6.0f);
- immUniform1f("dash_factor", 0.5f);
+ immUniformColor4fv(color);
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, x, ymin);
- immVertex2f(pos, x, ymax);
- immEnd();
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, x, ymin);
+ immVertex2f(pos, x, ymax);
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
}
/* function to draw markers */
-static void draw_marker(
- const uiFontStyle *fstyle, TimeMarker *marker, int cfra, int flag,
- /* avoid re-calculating each time */
- const float ypixels, const float xscale, int height)
+static void draw_marker(const uiFontStyle *fstyle,
+ TimeMarker *marker,
+ int cfra,
+ int flag,
+ /* avoid re-calculating each time */
+ const float ypixels,
+ const float xscale,
+ int height)
{
- const float xpos = marker->frame * xscale;
+ const float xpos = marker->frame * xscale;
#ifdef DURIAN_CAMERA_SWITCH
- const float yoffs = (marker->camera) ? 0.2f * UI_DPI_ICON_SIZE : 0.0f;
+ const float yoffs = (marker->camera) ? 0.2f * UI_DPI_ICON_SIZE : 0.0f;
#else
- const float yoffs = 0.0f;
+ const float yoffs = 0.0f;
#endif
- int icon_id;
+ int icon_id;
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- /* vertical line - dotted */
+ /* vertical line - dotted */
#ifdef DURIAN_CAMERA_SWITCH
- if ((marker->camera) || (flag & DRAW_MARKERS_LINES))
+ if ((marker->camera) || (flag & DRAW_MARKERS_LINES))
#else
- if (flag & DRAW_MARKERS_LINES)
+ if (flag & DRAW_MARKERS_LINES)
#endif
- {
- 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, yoffs + 1.5f * UI_DPI_ICON_SIZE, height);
- }
-
- /* 5 px to offset icon to align properly, space / pixels corrects for zoom */
- if (flag & DRAW_MARKERS_LOCAL) {
- icon_id = (marker->flag & ACTIVE) ? ICON_PMARKER_ACT :
- (marker->flag & SELECT) ? ICON_PMARKER_SEL :
- ICON_PMARKER;
- }
+ {
+ 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, yoffs + 1.5f * UI_DPI_ICON_SIZE, height);
+ }
+
+ /* 5 px to offset icon to align properly, space / pixels corrects for zoom */
+ if (flag & DRAW_MARKERS_LOCAL) {
+ icon_id = (marker->flag & ACTIVE) ? ICON_PMARKER_ACT :
+ (marker->flag & SELECT) ? ICON_PMARKER_SEL : ICON_PMARKER;
+ }
#ifdef DURIAN_CAMERA_SWITCH
- else if (marker->camera) {
- icon_id = (marker->flag & SELECT) ? ICON_OUTLINER_OB_CAMERA :
- ICON_CAMERA_DATA;
- }
+ else if (marker->camera) {
+ icon_id = (marker->flag & SELECT) ? ICON_OUTLINER_OB_CAMERA : ICON_CAMERA_DATA;
+ }
#endif
- else {
- icon_id = (marker->flag & SELECT) ? ICON_MARKER_HLT :
- ICON_MARKER;
- }
+ else {
+ icon_id = (marker->flag & SELECT) ? ICON_MARKER_HLT : ICON_MARKER;
+ }
- UI_icon_draw(xpos - 0.55f * UI_DPI_ICON_SIZE, yoffs + UI_DPI_ICON_SIZE, icon_id);
+ UI_icon_draw(xpos - 0.55f * UI_DPI_ICON_SIZE, yoffs + UI_DPI_ICON_SIZE, icon_id);
- GPU_blend(false);
+ GPU_blend(false);
- /* and the marker name too, shifted slightly to the top-right */
+ /* and the marker name too, shifted slightly to the top-right */
#ifdef DURIAN_CAMERA_SWITCH
- if (marker->camera) {
- draw_marker_name(fstyle, marker, marker->camera->id.name + 2, cfra, xpos, ypixels);
- }
- else if (marker->name[0]) {
- draw_marker_name(fstyle, marker, marker->name, cfra, xpos, ypixels);
- }
+ if (marker->camera) {
+ draw_marker_name(fstyle, marker, marker->camera->id.name + 2, cfra, xpos, ypixels);
+ }
+ else if (marker->name[0]) {
+ draw_marker_name(fstyle, marker, marker->name, cfra, xpos, ypixels);
+ }
#else
- if (marker->name[0]) {
- draw_marker_name(fstyle, marker, marker->name, cfra, xpos, ypixels);
-
- }
+ if (marker->name[0]) {
+ draw_marker_name(fstyle, marker, marker->name, cfra, xpos, ypixels);
+ }
#endif
}
/* Draw Scene-Markers in time window */
void ED_markers_draw(const bContext *C, int flag)
{
- const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- ListBase *markers = ED_context_get_markers(C);
- View2D *v2d;
- TimeMarker *marker;
- Scene *scene;
- int select_pass;
- int v2d_clip_range_x[2];
- float font_width_max;
-
- /* cache values */
- float ypixels, xscale, yscale;
-
- if (markers == NULL || BLI_listbase_is_empty(markers)) {
- return;
- }
-
- scene = CTX_data_scene(C);
- v2d = UI_view2d_fromcontext(C);
- int height = v2d->mask.ymax - v2d->mask.ymin;
-
- if (flag & DRAW_MARKERS_MARGIN) {
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- const unsigned char shade[4] = {0, 0, 0, 16};
- immUniformColor4ubv(shade);
-
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- immRectf(pos, v2d->cur.xmin, 0, v2d->cur.xmax, UI_MARKER_MARGIN_Y);
-
- GPU_blend(false);
-
- immUnbindProgram();
- }
-
- /* no time correction for framelen! space is drawn with old values */
- ypixels = BLI_rcti_size_y(&v2d->mask);
- UI_view2d_scale_get(v2d, &xscale, &yscale);
- GPU_matrix_push();
- GPU_matrix_scale_2f(1.0f / xscale, 1.0f);
-
- /* x-bounds with offset for text (adjust for long string, avoid checking string width) */
- font_width_max = (10 * UI_DPI_FAC) / xscale;
- v2d_clip_range_x[0] = v2d->cur.xmin - (sizeof(marker->name) * font_width_max);
- v2d_clip_range_x[1] = v2d->cur.xmax + font_width_max;
-
- /* loop [unselected, selected] */
- for (select_pass = 0; select_pass <= SELECT; select_pass += SELECT) {
- /* unselected markers are drawn at the first time */
- for (marker = markers->first; marker; marker = marker->next) {
- if ((marker->flag & SELECT) == select_pass) {
- /* bounds check */
- if ((marker->frame >= v2d_clip_range_x[0]) &&
- (marker->frame <= v2d_clip_range_x[1]))
- {
- draw_marker(fstyle, marker, scene->r.cfra, flag,
- ypixels, xscale, height);
- }
- }
- }
- }
-
- GPU_matrix_pop();
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ ListBase *markers = ED_context_get_markers(C);
+ View2D *v2d;
+ TimeMarker *marker;
+ Scene *scene;
+ int select_pass;
+ int v2d_clip_range_x[2];
+ float font_width_max;
+
+ /* cache values */
+ float ypixels, xscale, yscale;
+
+ if (markers == NULL || BLI_listbase_is_empty(markers)) {
+ return;
+ }
+
+ scene = CTX_data_scene(C);
+ v2d = UI_view2d_fromcontext(C);
+ int height = v2d->mask.ymax - v2d->mask.ymin;
+
+ if (flag & DRAW_MARKERS_MARGIN) {
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ const unsigned char shade[4] = {0, 0, 0, 16};
+ immUniformColor4ubv(shade);
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ immRectf(pos, v2d->cur.xmin, 0, v2d->cur.xmax, UI_MARKER_MARGIN_Y);
+
+ GPU_blend(false);
+
+ immUnbindProgram();
+ }
+
+ /* no time correction for framelen! space is drawn with old values */
+ ypixels = BLI_rcti_size_y(&v2d->mask);
+ UI_view2d_scale_get(v2d, &xscale, &yscale);
+ GPU_matrix_push();
+ GPU_matrix_scale_2f(1.0f / xscale, 1.0f);
+
+ /* x-bounds with offset for text (adjust for long string, avoid checking string width) */
+ font_width_max = (10 * UI_DPI_FAC) / xscale;
+ v2d_clip_range_x[0] = v2d->cur.xmin - (sizeof(marker->name) * font_width_max);
+ v2d_clip_range_x[1] = v2d->cur.xmax + font_width_max;
+
+ /* loop [unselected, selected] */
+ for (select_pass = 0; select_pass <= SELECT; select_pass += SELECT) {
+ /* unselected markers are drawn at the first time */
+ for (marker = markers->first; marker; marker = marker->next) {
+ if ((marker->flag & SELECT) == select_pass) {
+ /* bounds check */
+ if ((marker->frame >= v2d_clip_range_x[0]) && (marker->frame <= v2d_clip_range_x[1])) {
+ draw_marker(fstyle, marker, scene->r.cfra, flag, ypixels, xscale, height);
+ }
+ }
+ }
+ }
+
+ GPU_matrix_pop();
}
/* ************************ Marker Wrappers API ********************* */
@@ -567,48 +566,47 @@ void ED_markers_draw(const bContext *C, int flag)
/* special poll() which checks if there are selected markers first */
static bool ed_markers_poll_selected_markers(bContext *C)
{
- ListBase *markers = ED_context_get_markers(C);
+ ListBase *markers = ED_context_get_markers(C);
- /* first things first: markers can only exist in timeline views */
- if (ED_operator_animview_active(C) == 0)
- return 0;
+ /* first things first: markers can only exist in timeline views */
+ if (ED_operator_animview_active(C) == 0)
+ return 0;
- /* check if some marker is selected */
- return ED_markers_get_first_selected(markers) != NULL;
+ /* check if some marker is selected */
+ return ED_markers_get_first_selected(markers) != NULL;
}
static bool ed_markers_poll_selected_no_locked_markers(bContext *C)
{
- ListBase *markers = ED_context_get_markers(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
+ ListBase *markers = ED_context_get_markers(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
- if (ts->lock_markers)
- return 0;
+ if (ts->lock_markers)
+ return 0;
- /* first things first: markers can only exist in timeline views */
- if (ED_operator_animview_active(C) == 0)
- return 0;
+ /* first things first: markers can only exist in timeline views */
+ if (ED_operator_animview_active(C) == 0)
+ return 0;
- /* check if some marker is selected */
- return ED_markers_get_first_selected(markers) != NULL;
+ /* check if some marker is selected */
+ return ED_markers_get_first_selected(markers) != NULL;
}
-
/* special poll() which checks if there are any markers at all first */
static bool ed_markers_poll_markers_exist(bContext *C)
{
- ListBase *markers = ED_context_get_markers(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
+ ListBase *markers = ED_context_get_markers(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
- if (ts->lock_markers)
- return 0;
+ if (ts->lock_markers)
+ return 0;
- /* first things first: markers can only exist in timeline views */
- if (ED_operator_animview_active(C) == 0)
- return 0;
+ /* first things first: markers can only exist in timeline views */
+ if (ED_operator_animview_active(C) == 0)
+ return 0;
- /* list of markers must exist, as well as some markers in it! */
- return (markers && markers->first);
+ /* list of markers must exist, as well as some markers in it! */
+ return (markers && markers->first);
}
/* ------------------------ */
@@ -622,29 +620,34 @@ static bool ed_markers_poll_markers_exist(bContext *C)
* If NULL, the operator's standard exec()
* callback will be called instead in the appropriate places.
*/
-static int ed_markers_opwrap_invoke_custom(bContext *C, wmOperator *op, const wmEvent *event,
- int (*invoke_func)(bContext *, wmOperator *, const wmEvent *))
+static int ed_markers_opwrap_invoke_custom(bContext *C,
+ wmOperator *op,
+ const wmEvent *event,
+ int (*invoke_func)(bContext *,
+ wmOperator *,
+ const wmEvent *))
{
- int retval = OPERATOR_PASS_THROUGH;
-
- /* removed check for Y coord of event, keymap has bounbox now */
-
- /* allow operator to run now */
- if (invoke_func)
- retval = invoke_func(C, op, event);
- else if (op->type->exec)
- retval = op->type->exec(C, op);
- else
- BKE_report(op->reports, RPT_ERROR, "Programming error: operator does not actually have code to do anything!");
-
-
- /* unless successful, must add "pass-through"
- * to let normal operator's have a chance at tackling this event */
- if ((retval & (OPERATOR_FINISHED | OPERATOR_INTERFACE)) == 0) {
- retval |= OPERATOR_PASS_THROUGH;
- }
-
- return retval;
+ int retval = OPERATOR_PASS_THROUGH;
+
+ /* removed check for Y coord of event, keymap has bounbox now */
+
+ /* allow operator to run now */
+ if (invoke_func)
+ retval = invoke_func(C, op, event);
+ else if (op->type->exec)
+ retval = op->type->exec(C, op);
+ else
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Programming error: operator does not actually have code to do anything!");
+
+ /* unless successful, must add "pass-through"
+ * to let normal operator's have a chance at tackling this event */
+ if ((retval & (OPERATOR_FINISHED | OPERATOR_INTERFACE)) == 0) {
+ retval |= OPERATOR_PASS_THROUGH;
+ }
+
+ return retval;
}
/* standard wrapper - first-tier invoke() callback to be directly assigned to operator typedata
@@ -654,7 +657,7 @@ static int ed_markers_opwrap_invoke_custom(bContext *C, wmOperator *op, const wm
*/
static int ed_markers_opwrap_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- return ed_markers_opwrap_invoke_custom(C, op, event, NULL);
+ return ed_markers_opwrap_invoke_custom(C, op, event, NULL);
}
/* ************************** add markers *************************** */
@@ -662,50 +665,50 @@ static int ed_markers_opwrap_invoke(bContext *C, wmOperator *op, const wmEvent *
/* add TimeMarker at current frame */
static int ed_marker_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- ListBase *markers = ED_context_get_markers(C);
- TimeMarker *marker;
- int frame = CTX_data_scene(C)->r.cfra;
-
- if (markers == NULL)
- return OPERATOR_CANCELLED;
-
- /* prefer not having 2 markers at the same place,
- * though the user can move them to overlap once added */
- for (marker = markers->first; marker; marker = marker->next) {
- if (marker->frame == frame)
- return OPERATOR_CANCELLED;
- }
-
- /* deselect all */
- for (marker = markers->first; marker; marker = marker->next)
- marker->flag &= ~SELECT;
-
- marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
- marker->flag = SELECT;
- marker->frame = frame;
- BLI_snprintf(marker->name, sizeof(marker->name), "F_%02d", frame); // XXX - temp code only
- BLI_addtail(markers, marker);
-
- WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
-
- return OPERATOR_FINISHED;
+ ListBase *markers = ED_context_get_markers(C);
+ TimeMarker *marker;
+ int frame = CTX_data_scene(C)->r.cfra;
+
+ if (markers == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* prefer not having 2 markers at the same place,
+ * though the user can move them to overlap once added */
+ for (marker = markers->first; marker; marker = marker->next) {
+ if (marker->frame == frame)
+ return OPERATOR_CANCELLED;
+ }
+
+ /* deselect all */
+ for (marker = markers->first; marker; marker = marker->next)
+ marker->flag &= ~SELECT;
+
+ marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
+ marker->flag = SELECT;
+ marker->frame = frame;
+ BLI_snprintf(marker->name, sizeof(marker->name), "F_%02d", frame); // XXX - temp code only
+ BLI_addtail(markers, marker);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
+
+ return OPERATOR_FINISHED;
}
static void MARKER_OT_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Time Marker";
- ot->description = "Add a new time marker";
- ot->idname = "MARKER_OT_add";
-
- /* api callbacks */
- ot->exec = ed_marker_add_exec;
- ot->invoke = ed_markers_opwrap_invoke;
- ot->poll = ED_operator_animview_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Add Time Marker";
+ ot->description = "Add a new time marker";
+ ot->idname = "MARKER_OT_add";
+
+ /* api callbacks */
+ ot->exec = ed_marker_add_exec;
+ ot->invoke = ed_markers_opwrap_invoke;
+ ot->poll = ED_operator_animview_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ************************** transform markers *************************** */
@@ -733,315 +736,323 @@ static void MARKER_OT_add(wmOperatorType *ot)
*/
typedef struct MarkerMove {
- SpaceLink *slink;
- ListBase *markers;
- int event_type; /* store invoke-event, to verify */
- int *oldframe, evtx, firstx;
- NumInput num;
+ SpaceLink *slink;
+ ListBase *markers;
+ int event_type; /* store invoke-event, to verify */
+ int *oldframe, evtx, firstx;
+ NumInput num;
} MarkerMove;
static bool ed_marker_move_use_time(MarkerMove *mm)
{
- if (((mm->slink->spacetype == SPACE_SEQ) && !(((SpaceSeq *)mm->slink)->flag & SEQ_DRAWFRAMES)) ||
- ((mm->slink->spacetype == SPACE_ACTION) && (((SpaceAction *)mm->slink)->flag & SACTION_DRAWTIME)) ||
- ((mm->slink->spacetype == SPACE_GRAPH) && !(((SpaceGraph *)mm->slink)->flag & SIPO_DRAWTIME)) ||
- ((mm->slink->spacetype == SPACE_NLA) && !(((SpaceNla *)mm->slink)->flag & SNLA_DRAWTIME)))
- {
- return true;
- }
-
- return false;
+ if (((mm->slink->spacetype == SPACE_SEQ) && !(((SpaceSeq *)mm->slink)->flag & SEQ_DRAWFRAMES)) ||
+ ((mm->slink->spacetype == SPACE_ACTION) &&
+ (((SpaceAction *)mm->slink)->flag & SACTION_DRAWTIME)) ||
+ ((mm->slink->spacetype == SPACE_GRAPH) &&
+ !(((SpaceGraph *)mm->slink)->flag & SIPO_DRAWTIME)) ||
+ ((mm->slink->spacetype == SPACE_NLA) && !(((SpaceNla *)mm->slink)->flag & SNLA_DRAWTIME))) {
+ return true;
+ }
+
+ return false;
}
static void ed_marker_move_update_header(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- MarkerMove *mm = op->customdata;
- TimeMarker *marker, *selmarker = NULL;
- const int offs = RNA_int_get(op->ptr, "frames");
- char str[UI_MAX_DRAW_STR];
- char str_offs[NUM_STR_REP_LEN];
- int totmark;
- const bool use_time = ed_marker_move_use_time(mm);
-
- for (totmark = 0, marker = mm->markers->first; marker; marker = marker->next) {
- if (marker->flag & SELECT) {
- selmarker = marker;
- totmark++;
- }
- }
-
- if (hasNumInput(&mm->num)) {
- outputNumInput(&mm->num, str_offs, &scene->unit);
- }
- else if (use_time) {
- BLI_snprintf(str_offs, sizeof(str_offs), "%.2f", FRA2TIME(offs));
- }
- else {
- BLI_snprintf(str_offs, sizeof(str_offs), "%d", offs);
- }
-
- if (totmark == 1 && selmarker) {
- /* we print current marker value */
- if (use_time) {
- BLI_snprintf(str, sizeof(str), IFACE_("Marker %.2f offset %s"), FRA2TIME(selmarker->frame), str_offs);
- }
- else {
- BLI_snprintf(str, sizeof(str), IFACE_("Marker %d offset %s"), selmarker->frame, str_offs);
- }
- }
- else {
- BLI_snprintf(str, sizeof(str), IFACE_("Marker offset %s"), str_offs);
- }
-
- ED_area_status_text(CTX_wm_area(C), str);
+ Scene *scene = CTX_data_scene(C);
+ MarkerMove *mm = op->customdata;
+ TimeMarker *marker, *selmarker = NULL;
+ const int offs = RNA_int_get(op->ptr, "frames");
+ char str[UI_MAX_DRAW_STR];
+ char str_offs[NUM_STR_REP_LEN];
+ int totmark;
+ const bool use_time = ed_marker_move_use_time(mm);
+
+ for (totmark = 0, marker = mm->markers->first; marker; marker = marker->next) {
+ if (marker->flag & SELECT) {
+ selmarker = marker;
+ totmark++;
+ }
+ }
+
+ if (hasNumInput(&mm->num)) {
+ outputNumInput(&mm->num, str_offs, &scene->unit);
+ }
+ else if (use_time) {
+ BLI_snprintf(str_offs, sizeof(str_offs), "%.2f", FRA2TIME(offs));
+ }
+ else {
+ BLI_snprintf(str_offs, sizeof(str_offs), "%d", offs);
+ }
+
+ if (totmark == 1 && selmarker) {
+ /* we print current marker value */
+ if (use_time) {
+ BLI_snprintf(
+ str, sizeof(str), IFACE_("Marker %.2f offset %s"), FRA2TIME(selmarker->frame), str_offs);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("Marker %d offset %s"), selmarker->frame, str_offs);
+ }
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("Marker offset %s"), str_offs);
+ }
+
+ ED_area_status_text(CTX_wm_area(C), str);
}
/* copy selection to temp buffer */
/* return 0 if not OK */
static bool ed_marker_move_init(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ListBase *markers = ED_context_get_markers(C);
- MarkerMove *mm;
- TimeMarker *marker;
- int a, totmark;
-
- if (markers == NULL) {
- return false;
- }
-
- for (totmark = 0, marker = markers->first; marker; marker = marker->next) {
- if (marker->flag & SELECT) {
- totmark++;
- }
- }
-
- if (totmark == 0) {
- return false;
- }
-
- op->customdata = mm = MEM_callocN(sizeof(MarkerMove), "Markermove");
- mm->slink = CTX_wm_space_data(C);
- mm->markers = markers;
- mm->oldframe = MEM_callocN(totmark * sizeof(int), "MarkerMove oldframe");
-
- initNumInput(&mm->num);
- mm->num.idx_max = 0; /* one axis */
- mm->num.val_flag[0] |= NUM_NO_FRACTION;
- mm->num.unit_sys = scene->unit.system;
- /* No time unit supporting frames currently... */
- mm->num.unit_type[0] = ed_marker_move_use_time(mm) ? B_UNIT_TIME : B_UNIT_NONE;
-
- for (a = 0, marker = markers->first; marker; marker = marker->next) {
- if (marker->flag & SELECT) {
- mm->oldframe[a] = marker->frame;
- a++;
- }
- }
-
- return true;
+ Scene *scene = CTX_data_scene(C);
+ ListBase *markers = ED_context_get_markers(C);
+ MarkerMove *mm;
+ TimeMarker *marker;
+ int a, totmark;
+
+ if (markers == NULL) {
+ return false;
+ }
+
+ for (totmark = 0, marker = markers->first; marker; marker = marker->next) {
+ if (marker->flag & SELECT) {
+ totmark++;
+ }
+ }
+
+ if (totmark == 0) {
+ return false;
+ }
+
+ op->customdata = mm = MEM_callocN(sizeof(MarkerMove), "Markermove");
+ mm->slink = CTX_wm_space_data(C);
+ mm->markers = markers;
+ mm->oldframe = MEM_callocN(totmark * sizeof(int), "MarkerMove oldframe");
+
+ initNumInput(&mm->num);
+ mm->num.idx_max = 0; /* one axis */
+ mm->num.val_flag[0] |= NUM_NO_FRACTION;
+ mm->num.unit_sys = scene->unit.system;
+ /* No time unit supporting frames currently... */
+ mm->num.unit_type[0] = ed_marker_move_use_time(mm) ? B_UNIT_TIME : B_UNIT_NONE;
+
+ for (a = 0, marker = markers->first; marker; marker = marker->next) {
+ if (marker->flag & SELECT) {
+ mm->oldframe[a] = marker->frame;
+ a++;
+ }
+ }
+
+ return true;
}
/* free stuff */
static void ed_marker_move_exit(bContext *C, wmOperator *op)
{
- MarkerMove *mm = op->customdata;
+ MarkerMove *mm = op->customdata;
- /* free data */
- MEM_freeN(mm->oldframe);
- MEM_freeN(op->customdata);
- op->customdata = NULL;
+ /* free data */
+ MEM_freeN(mm->oldframe);
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
- /* clear custom header prints */
- ED_area_status_text(CTX_wm_area(C), NULL);
+ /* clear custom header prints */
+ ED_area_status_text(CTX_wm_area(C), NULL);
}
static int ed_marker_move_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (ed_marker_move_init(C, op)) {
- MarkerMove *mm = op->customdata;
+ if (ed_marker_move_init(C, op)) {
+ MarkerMove *mm = op->customdata;
- mm->evtx = event->x;
- mm->firstx = event->x;
- mm->event_type = event->type;
+ mm->evtx = event->x;
+ mm->firstx = event->x;
+ mm->event_type = event->type;
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
- /* reset frs delta */
- RNA_int_set(op->ptr, "frames", 0);
+ /* reset frs delta */
+ RNA_int_set(op->ptr, "frames", 0);
- ed_marker_move_update_header(C, op);
+ ed_marker_move_update_header(C, op);
- return OPERATOR_RUNNING_MODAL;
- }
+ return OPERATOR_RUNNING_MODAL;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
static int ed_marker_move_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event)
{
- return ed_markers_opwrap_invoke_custom(C, op, event, ed_marker_move_invoke);
+ return ed_markers_opwrap_invoke_custom(C, op, event, ed_marker_move_invoke);
}
/* note, init has to be called successfully */
static void ed_marker_move_apply(bContext *C, wmOperator *op)
{
#ifdef DURIAN_CAMERA_SWITCH
- bScreen *sc = CTX_wm_screen(C);
- Scene *scene = CTX_data_scene(C);
- Object *camera = scene->camera;
+ bScreen *sc = CTX_wm_screen(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *camera = scene->camera;
#endif
- MarkerMove *mm = op->customdata;
- TimeMarker *marker;
- int a, offs;
+ MarkerMove *mm = op->customdata;
+ TimeMarker *marker;
+ int a, offs;
- offs = RNA_int_get(op->ptr, "frames");
- for (a = 0, marker = mm->markers->first; marker; marker = marker->next) {
- if (marker->flag & SELECT) {
- marker->frame = mm->oldframe[a] + offs;
- a++;
- }
- }
+ offs = RNA_int_get(op->ptr, "frames");
+ for (a = 0, marker = mm->markers->first; marker; marker = marker->next) {
+ if (marker->flag & SELECT) {
+ marker->frame = mm->oldframe[a] + offs;
+ a++;
+ }
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
#ifdef DURIAN_CAMERA_SWITCH
- /* so we get view3d redraws */
- BKE_scene_camera_switch_update(scene);
+ /* so we get view3d redraws */
+ BKE_scene_camera_switch_update(scene);
- if (camera != scene->camera) {
- BKE_screen_view3d_scene_sync(sc, scene);
- WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
- }
+ if (camera != scene->camera) {
+ BKE_screen_view3d_scene_sync(sc, scene);
+ WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
+ }
#endif
}
/* only for modal */
static void ed_marker_move_cancel(bContext *C, wmOperator *op)
{
- RNA_int_set(op->ptr, "frames", 0);
- ed_marker_move_apply(C, op);
- ed_marker_move_exit(C, op);
+ RNA_int_set(op->ptr, "frames", 0);
+ ed_marker_move_apply(C, op);
+ ed_marker_move_exit(C, op);
}
static int ed_marker_move_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- Scene *scene = CTX_data_scene(C);
- MarkerMove *mm = op->customdata;
- View2D *v2d = UI_view2d_fromcontext(C);
- const bool has_numinput = hasNumInput(&mm->num);
- const bool use_time = ed_marker_move_use_time(mm);
-
- /* Modal numinput active, try to handle numeric inputs first... */
- if (event->val == KM_PRESS && has_numinput && handleNumInput(C, &mm->num, event)) {
- float value = (float)RNA_int_get(op->ptr, "frames");
-
- applyNumInput(&mm->num, &value);
- if (use_time) {
- value = TIME2FRA(value);
- }
-
- RNA_int_set(op->ptr, "frames", (int)value);
- ed_marker_move_apply(C, op);
- ed_marker_move_update_header(C, op);
- }
- else {
- bool handled = false;
- switch (event->type) {
- case ESCKEY:
- ed_marker_move_cancel(C, op);
- return OPERATOR_CANCELLED;
- case RIGHTMOUSE:
- /* press = user manually demands transform to be canceled */
- if (event->val == KM_PRESS) {
- ed_marker_move_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- /* else continue; <--- see if release event should be caught for tweak-end */
- ATTR_FALLTHROUGH;
-
- case RETKEY:
- case PADENTER:
- case LEFTMOUSE:
- case MIDDLEMOUSE:
- if (WM_event_is_modal_tweak_exit(event, mm->event_type)) {
- ed_marker_move_exit(C, op);
- WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
- return OPERATOR_FINISHED;
- }
- break;
- case MOUSEMOVE:
- if (!has_numinput) {
- float dx;
-
- dx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
-
- if (event->x != mm->evtx) { /* XXX maybe init for first time */
- float fac;
-
- mm->evtx = event->x;
- fac = ((float)(event->x - mm->firstx) * dx);
-
- apply_keyb_grid(event->shift, event->ctrl, &fac, 0.0, 1.0, 0.1, 0 /*was: U.flag & USER_AUTOGRABGRID*/);
-
- RNA_int_set(op->ptr, "frames", (int)fac);
- ed_marker_move_apply(C, op);
- ed_marker_move_update_header(C, op);
- }
- }
- break;
- }
-
- if (!handled && event->val == KM_PRESS && handleNumInput(C, &mm->num, event)) {
- float value = (float)RNA_int_get(op->ptr, "frames");
-
- applyNumInput(&mm->num, &value);
- if (use_time) {
- value = TIME2FRA(value);
- }
-
- RNA_int_set(op->ptr, "frames", (int)value);
- ed_marker_move_apply(C, op);
- ed_marker_move_update_header(C, op);
- }
- }
-
- return OPERATOR_RUNNING_MODAL;
+ Scene *scene = CTX_data_scene(C);
+ MarkerMove *mm = op->customdata;
+ View2D *v2d = UI_view2d_fromcontext(C);
+ const bool has_numinput = hasNumInput(&mm->num);
+ const bool use_time = ed_marker_move_use_time(mm);
+
+ /* Modal numinput active, try to handle numeric inputs first... */
+ if (event->val == KM_PRESS && has_numinput && handleNumInput(C, &mm->num, event)) {
+ float value = (float)RNA_int_get(op->ptr, "frames");
+
+ applyNumInput(&mm->num, &value);
+ if (use_time) {
+ value = TIME2FRA(value);
+ }
+
+ RNA_int_set(op->ptr, "frames", (int)value);
+ ed_marker_move_apply(C, op);
+ ed_marker_move_update_header(C, op);
+ }
+ else {
+ bool handled = false;
+ switch (event->type) {
+ case ESCKEY:
+ ed_marker_move_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ case RIGHTMOUSE:
+ /* press = user manually demands transform to be canceled */
+ if (event->val == KM_PRESS) {
+ ed_marker_move_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ /* else continue; <--- see if release event should be caught for tweak-end */
+ ATTR_FALLTHROUGH;
+
+ case RETKEY:
+ case PADENTER:
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ if (WM_event_is_modal_tweak_exit(event, mm->event_type)) {
+ ed_marker_move_exit(C, op);
+ WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
+ return OPERATOR_FINISHED;
+ }
+ break;
+ case MOUSEMOVE:
+ if (!has_numinput) {
+ float dx;
+
+ dx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
+
+ if (event->x != mm->evtx) { /* XXX maybe init for first time */
+ float fac;
+
+ mm->evtx = event->x;
+ fac = ((float)(event->x - mm->firstx) * dx);
+
+ apply_keyb_grid(event->shift,
+ event->ctrl,
+ &fac,
+ 0.0,
+ 1.0,
+ 0.1,
+ 0 /*was: U.flag & USER_AUTOGRABGRID*/);
+
+ RNA_int_set(op->ptr, "frames", (int)fac);
+ ed_marker_move_apply(C, op);
+ ed_marker_move_update_header(C, op);
+ }
+ }
+ break;
+ }
+
+ if (!handled && event->val == KM_PRESS && handleNumInput(C, &mm->num, event)) {
+ float value = (float)RNA_int_get(op->ptr, "frames");
+
+ applyNumInput(&mm->num, &value);
+ if (use_time) {
+ value = TIME2FRA(value);
+ }
+
+ RNA_int_set(op->ptr, "frames", (int)value);
+ ed_marker_move_apply(C, op);
+ ed_marker_move_update_header(C, op);
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
static int ed_marker_move_exec(bContext *C, wmOperator *op)
{
- if (ed_marker_move_init(C, op)) {
- ed_marker_move_apply(C, op);
- ed_marker_move_exit(C, op);
- return OPERATOR_FINISHED;
- }
- return OPERATOR_PASS_THROUGH;
+ if (ed_marker_move_init(C, op)) {
+ ed_marker_move_apply(C, op);
+ ed_marker_move_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_PASS_THROUGH;
}
static void MARKER_OT_move(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move Time Marker";
- ot->description = "Move selected time marker(s)";
- ot->idname = "MARKER_OT_move";
-
- /* api callbacks */
- ot->exec = ed_marker_move_exec;
- ot->invoke = ed_marker_move_invoke_wrapper;
- ot->modal = ed_marker_move_modal;
- ot->poll = ed_markers_poll_selected_no_locked_markers;
- ot->cancel = ed_marker_move_cancel;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
-
- /* rna storage */
- RNA_def_int(ot->srna, "frames", 0, INT_MIN, INT_MAX, "Frames", "", INT_MIN, INT_MAX);
+ /* identifiers */
+ ot->name = "Move Time Marker";
+ ot->description = "Move selected time marker(s)";
+ ot->idname = "MARKER_OT_move";
+
+ /* api callbacks */
+ ot->exec = ed_marker_move_exec;
+ ot->invoke = ed_marker_move_invoke_wrapper;
+ ot->modal = ed_marker_move_modal;
+ ot->poll = ed_markers_poll_selected_no_locked_markers;
+ ot->cancel = ed_marker_move_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
+
+ /* rna storage */
+ RNA_def_int(ot->srna, "frames", 0, INT_MIN, INT_MAX, "Frames", "", INT_MIN, INT_MAX);
}
/* ************************** duplicate markers *************************** */
@@ -1065,76 +1076,75 @@ static void MARKER_OT_move(wmOperatorType *ot)
/* duplicate selected TimeMarkers */
static void ed_marker_duplicate_apply(bContext *C)
{
- ListBase *markers = ED_context_get_markers(C);
- TimeMarker *marker, *newmarker;
-
- if (markers == NULL)
- return;
-
- /* go through the list of markers, duplicate selected markers and add duplicated copies
- * to the beginning of the list (unselect original markers)
- */
- for (marker = markers->first; marker; marker = marker->next) {
- if (marker->flag & SELECT) {
- /* unselect selected marker */
- marker->flag &= ~SELECT;
-
- /* create and set up new marker */
- newmarker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
- newmarker->flag = SELECT;
- newmarker->frame = marker->frame;
- BLI_strncpy(newmarker->name, marker->name, sizeof(marker->name));
+ ListBase *markers = ED_context_get_markers(C);
+ TimeMarker *marker, *newmarker;
+
+ if (markers == NULL)
+ return;
+
+ /* go through the list of markers, duplicate selected markers and add duplicated copies
+ * to the beginning of the list (unselect original markers)
+ */
+ for (marker = markers->first; marker; marker = marker->next) {
+ if (marker->flag & SELECT) {
+ /* unselect selected marker */
+ marker->flag &= ~SELECT;
+
+ /* create and set up new marker */
+ newmarker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
+ newmarker->flag = SELECT;
+ newmarker->frame = marker->frame;
+ BLI_strncpy(newmarker->name, marker->name, sizeof(marker->name));
#ifdef DURIAN_CAMERA_SWITCH
- newmarker->camera = marker->camera;
+ newmarker->camera = marker->camera;
#endif
- /* new marker is added to the beginning of list */
- // FIXME: bad ordering!
- BLI_addhead(markers, newmarker);
- }
- }
+ /* new marker is added to the beginning of list */
+ // FIXME: bad ordering!
+ BLI_addhead(markers, newmarker);
+ }
+ }
}
static int ed_marker_duplicate_exec(bContext *C, wmOperator *op)
{
- ed_marker_duplicate_apply(C);
- ed_marker_move_exec(C, op); /* assumes frs delta set */
-
- return OPERATOR_FINISHED;
+ ed_marker_duplicate_apply(C);
+ ed_marker_move_exec(C, op); /* assumes frs delta set */
+ return OPERATOR_FINISHED;
}
static int ed_marker_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ed_marker_duplicate_apply(C);
- return ed_marker_move_invoke(C, op, event);
+ ed_marker_duplicate_apply(C);
+ return ed_marker_move_invoke(C, op, event);
}
static int ed_marker_duplicate_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event)
{
- return ed_markers_opwrap_invoke_custom(C, op, event, ed_marker_duplicate_invoke);
+ return ed_markers_opwrap_invoke_custom(C, op, event, ed_marker_duplicate_invoke);
}
static void MARKER_OT_duplicate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Duplicate Time Marker";
- ot->description = "Duplicate selected time marker(s)";
- ot->idname = "MARKER_OT_duplicate";
-
- /* api callbacks */
- ot->exec = ed_marker_duplicate_exec;
- ot->invoke = ed_marker_duplicate_invoke_wrapper;
- ot->modal = ed_marker_move_modal;
- ot->poll = ed_markers_poll_selected_no_locked_markers;
- ot->cancel = ed_marker_move_cancel;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* rna storage */
- RNA_def_int(ot->srna, "frames", 0, INT_MIN, INT_MAX, "Frames", "", INT_MIN, INT_MAX);
+ /* identifiers */
+ ot->name = "Duplicate Time Marker";
+ ot->description = "Duplicate selected time marker(s)";
+ ot->idname = "MARKER_OT_duplicate";
+
+ /* api callbacks */
+ ot->exec = ed_marker_duplicate_exec;
+ ot->invoke = ed_marker_duplicate_invoke_wrapper;
+ ot->modal = ed_marker_move_modal;
+ ot->poll = ed_markers_poll_selected_no_locked_markers;
+ ot->cancel = ed_marker_move_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* rna storage */
+ RNA_def_int(ot->srna, "frames", 0, INT_MIN, INT_MAX, "Frames", "", INT_MIN, INT_MAX);
}
/* ************************** selection ************************************/
@@ -1142,137 +1152,136 @@ static void MARKER_OT_duplicate(wmOperatorType *ot)
/* select/deselect TimeMarker at current frame */
static void select_timeline_marker_frame(ListBase *markers, int frame, bool extend)
{
- TimeMarker *marker, *marker_first = NULL;
-
- /* support for selection cycling */
- for (marker = markers->first; marker; marker = marker->next) {
- if (marker->frame == frame) {
- if (marker->flag & SELECT) {
- marker_first = marker->next;
- break;
- }
- }
- }
-
- /* if extend is not set, then deselect markers */
- if (extend == false) {
- for (marker = markers->first; marker; marker = marker->next) {
- marker->flag &= ~SELECT;
- }
- }
-
- LISTBASE_CIRCULAR_FORWARD_BEGIN(markers, marker, marker_first)
- {
- /* this way a not-extend select will always give 1 selected marker */
- if (marker->frame == frame) {
- marker->flag ^= SELECT;
- break;
- }
- }
- LISTBASE_CIRCULAR_FORWARD_END(markers, marker, marker_first);
+ TimeMarker *marker, *marker_first = NULL;
+
+ /* support for selection cycling */
+ for (marker = markers->first; marker; marker = marker->next) {
+ if (marker->frame == frame) {
+ if (marker->flag & SELECT) {
+ marker_first = marker->next;
+ break;
+ }
+ }
+ }
+
+ /* if extend is not set, then deselect markers */
+ if (extend == false) {
+ for (marker = markers->first; marker; marker = marker->next) {
+ marker->flag &= ~SELECT;
+ }
+ }
+
+ LISTBASE_CIRCULAR_FORWARD_BEGIN (markers, marker, marker_first) {
+ /* this way a not-extend select will always give 1 selected marker */
+ if (marker->frame == frame) {
+ marker->flag ^= SELECT;
+ break;
+ }
+ }
+ LISTBASE_CIRCULAR_FORWARD_END(markers, marker, marker_first);
}
static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool camera)
{
- ListBase *markers = ED_context_get_markers(C);
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = UI_view2d_fromcontext(C);
- float viewx;
- int x, cfra;
+ ListBase *markers = ED_context_get_markers(C);
+ ARegion *ar = CTX_wm_region(C);
+ View2D *v2d = UI_view2d_fromcontext(C);
+ float viewx;
+ int x, cfra;
- if (markers == NULL)
- return OPERATOR_PASS_THROUGH;
+ if (markers == NULL)
+ return OPERATOR_PASS_THROUGH;
- x = event->x - ar->winrct.xmin;
+ x = event->x - ar->winrct.xmin;
- viewx = UI_view2d_region_to_view_x(v2d, x);
+ viewx = UI_view2d_region_to_view_x(v2d, x);
- cfra = ED_markers_find_nearest_marker_time(markers, viewx);
+ cfra = ED_markers_find_nearest_marker_time(markers, viewx);
- select_timeline_marker_frame(markers, cfra, extend);
+ select_timeline_marker_frame(markers, cfra, extend);
#ifdef DURIAN_CAMERA_SWITCH
- if (camera) {
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base;
- TimeMarker *marker;
- int sel = 0;
-
- if (!extend)
- BKE_view_layer_base_deselect_all(view_layer);
-
- for (marker = markers->first; marker; marker = marker->next) {
- if (marker->frame == cfra) {
- sel = (marker->flag & SELECT);
- break;
- }
- }
-
- for (marker = markers->first; marker; marker = marker->next) {
- if (marker->camera) {
- if (marker->frame == cfra) {
- base = BKE_view_layer_base_find(view_layer, marker->camera);
- if (base) {
- ED_object_base_select(base, sel);
- if (sel)
- ED_object_base_activate(C, base);
- }
- }
- }
- }
-
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
+ if (camera) {
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base;
+ TimeMarker *marker;
+ int sel = 0;
+
+ if (!extend)
+ BKE_view_layer_base_deselect_all(view_layer);
+
+ for (marker = markers->first; marker; marker = marker->next) {
+ if (marker->frame == cfra) {
+ sel = (marker->flag & SELECT);
+ break;
+ }
+ }
+
+ for (marker = markers->first; marker; marker = marker->next) {
+ if (marker->camera) {
+ if (marker->frame == cfra) {
+ base = BKE_view_layer_base_find(view_layer, marker->camera);
+ if (base) {
+ ED_object_base_select(base, sel);
+ if (sel)
+ ED_object_base_activate(C, base);
+ }
+ }
+ }
+ }
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ }
#else
- (void)camera;
+ (void)camera;
#endif
- WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
- /* allowing tweaks, but needs OPERATOR_FINISHED, otherwise renaming fails... [#25987] */
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ /* allowing tweaks, but needs OPERATOR_FINISHED, otherwise renaming fails... [#25987] */
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
}
static int ed_marker_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- const bool extend = RNA_boolean_get(op->ptr, "extend");
- bool camera = false;
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ bool camera = false;
#ifdef DURIAN_CAMERA_SWITCH
- camera = RNA_boolean_get(op->ptr, "camera");
+ camera = RNA_boolean_get(op->ptr, "camera");
#endif
- return ed_marker_select(C, event, extend, camera);
+ return ed_marker_select(C, event, extend, camera);
}
static int ed_marker_select_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event)
{
- return ed_markers_opwrap_invoke_custom(C, op, event, ed_marker_select_invoke);
+ return ed_markers_opwrap_invoke_custom(C, op, event, ed_marker_select_invoke);
}
static void MARKER_OT_select(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Select Time Marker";
- ot->description = "Select time marker(s)";
- ot->idname = "MARKER_OT_select";
+ /* identifiers */
+ ot->name = "Select Time Marker";
+ ot->description = "Select time marker(s)";
+ ot->idname = "MARKER_OT_select";
- /* api callbacks */
- ot->invoke = ed_marker_select_invoke_wrapper;
- ot->poll = ed_markers_poll_markers_exist;
+ /* api callbacks */
+ ot->invoke = ed_marker_select_invoke_wrapper;
+ ot->poll = ed_markers_poll_markers_exist;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
#ifdef DURIAN_CAMERA_SWITCH
- prop = RNA_def_boolean(ot->srna, "camera", 0, "Camera", "Select the camera");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "camera", 0, "Camera", "Select the camera");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
#endif
}
@@ -1286,110 +1295,110 @@ static void MARKER_OT_select(wmOperatorType *ot)
*
* callbacks:
*
- * exec() has to be filled in by user
+ * exec() has to be filled in by user
*
* invoke() default WM function
* adds modal handler
*
- * modal() default WM function
+ * modal() default WM function
* accept modal events while doing it, calls exec(), handles ESC and border drawing
*
- * poll() has to be filled in by user for context
+ * poll() has to be filled in by user for context
*/
static int ed_marker_box_select_exec(bContext *C, wmOperator *op)
{
- View2D *v2d = UI_view2d_fromcontext(C);
- ListBase *markers = ED_context_get_markers(C);
- rctf rect;
+ View2D *v2d = UI_view2d_fromcontext(C);
+ ListBase *markers = ED_context_get_markers(C);
+ rctf rect;
- WM_operator_properties_border_to_rctf(op, &rect);
- UI_view2d_region_to_view_rctf(v2d, &rect, &rect);
+ WM_operator_properties_border_to_rctf(op, &rect);
+ UI_view2d_region_to_view_rctf(v2d, &rect, &rect);
- if (markers == NULL)
- return 0;
+ if (markers == NULL)
+ return 0;
- 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)) {
- ED_markers_deselect_all(markers, SEL_DESELECT);
- }
+ 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)) {
+ ED_markers_deselect_all(markers, SEL_DESELECT);
+ }
- for (TimeMarker *marker = markers->first; marker; marker = marker->next) {
- if (BLI_rctf_isect_x(&rect, marker->frame)) {
- SET_FLAG_FROM_TEST(marker->flag, select, SELECT);
- }
- }
+ for (TimeMarker *marker = markers->first; marker; marker = marker->next) {
+ if (BLI_rctf_isect_x(&rect, marker->frame)) {
+ SET_FLAG_FROM_TEST(marker->flag, select, SELECT);
+ }
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
- return 1;
+ return 1;
}
static int ed_marker_select_box_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event)
{
- return ed_markers_opwrap_invoke_custom(C, op, event, WM_gesture_box_invoke);
+ return ed_markers_opwrap_invoke_custom(C, op, event, WM_gesture_box_invoke);
}
static void MARKER_OT_select_box(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Marker Box Select";
- ot->description = "Select all time markers using box selection";
- ot->idname = "MARKER_OT_select_box";
+ /* identifiers */
+ ot->name = "Marker Box Select";
+ ot->description = "Select all time markers using box selection";
+ ot->idname = "MARKER_OT_select_box";
- /* api callbacks */
- ot->exec = ed_marker_box_select_exec;
- ot->invoke = ed_marker_select_box_invoke_wrapper;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
+ /* api callbacks */
+ ot->exec = ed_marker_box_select_exec;
+ ot->invoke = ed_marker_select_box_invoke_wrapper;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
- ot->poll = ed_markers_poll_markers_exist;
+ ot->poll = ed_markers_poll_markers_exist;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_gesture_box(ot);
- WM_operator_properties_select_operation_simple(ot);
+ /* properties */
+ WM_operator_properties_gesture_box(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
/* *********************** (de)select all ***************** */
static int ed_marker_select_all_exec(bContext *C, wmOperator *op)
{
- ListBase *markers = ED_context_get_markers(C);
- if (markers == NULL) {
- return OPERATOR_CANCELLED;
- }
+ ListBase *markers = ED_context_get_markers(C);
+ if (markers == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- int action = RNA_enum_get(op->ptr, "action");
- ED_markers_deselect_all(markers, action);
+ int action = RNA_enum_get(op->ptr, "action");
+ ED_markers_deselect_all(markers, action);
- WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void MARKER_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select all Markers";
- ot->description = "Change selection of all time markers";
- ot->idname = "MARKER_OT_select_all";
+ /* identifiers */
+ ot->name = "(De)select all Markers";
+ ot->description = "Change selection of all time markers";
+ ot->idname = "MARKER_OT_select_all";
- /* api callbacks */
- ot->exec = ed_marker_select_all_exec;
- ot->invoke = ed_markers_opwrap_invoke;
- ot->poll = ed_markers_poll_markers_exist;
+ /* api callbacks */
+ ot->exec = ed_marker_select_all_exec;
+ ot->invoke = ed_markers_opwrap_invoke;
+ ot->poll = ed_markers_poll_markers_exist;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* rna */
- WM_operator_properties_select_all(ot);
+ /* rna */
+ WM_operator_properties_select_all(ot);
}
/* ***************** remove marker *********************** */
@@ -1397,167 +1406,172 @@ static void MARKER_OT_select_all(wmOperatorType *ot)
/* remove selected TimeMarkers */
static int ed_marker_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- ListBase *markers = ED_context_get_markers(C);
- TimeMarker *marker, *nmarker;
- bool changed = false;
-
- if (markers == NULL)
- return OPERATOR_CANCELLED;
-
- for (marker = markers->first; marker; marker = nmarker) {
- nmarker = marker->next;
- if (marker->flag & SELECT) {
- BLI_freelinkN(markers, marker);
- changed = true;
- }
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
- }
-
- return OPERATOR_FINISHED;
+ ListBase *markers = ED_context_get_markers(C);
+ TimeMarker *marker, *nmarker;
+ bool changed = false;
+
+ if (markers == NULL)
+ return OPERATOR_CANCELLED;
+
+ for (marker = markers->first; marker; marker = nmarker) {
+ nmarker = marker->next;
+ if (marker->flag & SELECT) {
+ BLI_freelinkN(markers, marker);
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
+ }
+
+ return OPERATOR_FINISHED;
}
static int ed_marker_delete_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event)
{
- // XXX: must we keep these confirmations?
- return ed_markers_opwrap_invoke_custom(C, op, event, WM_operator_confirm);
+ // XXX: must we keep these confirmations?
+ return ed_markers_opwrap_invoke_custom(C, op, event, WM_operator_confirm);
}
static void MARKER_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Markers";
- ot->description = "Delete selected time marker(s)";
- ot->idname = "MARKER_OT_delete";
-
- /* api callbacks */
- ot->invoke = ed_marker_delete_invoke_wrapper;
- ot->exec = ed_marker_delete_exec;
- ot->poll = ed_markers_poll_selected_no_locked_markers;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Delete Markers";
+ ot->description = "Delete selected time marker(s)";
+ ot->idname = "MARKER_OT_delete";
+
+ /* api callbacks */
+ ot->invoke = ed_marker_delete_invoke_wrapper;
+ ot->exec = ed_marker_delete_exec;
+ ot->poll = ed_markers_poll_selected_no_locked_markers;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/* **************** rename marker ***************** */
/* rename first selected TimeMarker */
static int ed_marker_rename_exec(bContext *C, wmOperator *op)
{
- TimeMarker *marker = ED_markers_get_first_selected(ED_context_get_markers(C));
+ TimeMarker *marker = ED_markers_get_first_selected(ED_context_get_markers(C));
- if (marker) {
- RNA_string_get(op->ptr, "name", marker->name);
+ if (marker) {
+ RNA_string_get(op->ptr, "name", marker->name);
- WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static int ed_marker_rename_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event)
{
- /* must initialize the marker name first if there is a marker selected */
- TimeMarker *marker = ED_markers_get_first_selected(ED_context_get_markers(C));
- if (marker)
- RNA_string_set(op->ptr, "name", marker->name);
+ /* must initialize the marker name first if there is a marker selected */
+ TimeMarker *marker = ED_markers_get_first_selected(ED_context_get_markers(C));
+ if (marker)
+ RNA_string_set(op->ptr, "name", marker->name);
- /* now see if the operator is usable */
- return ed_markers_opwrap_invoke_custom(C, op, event, WM_operator_props_popup_confirm);
+ /* now see if the operator is usable */
+ return ed_markers_opwrap_invoke_custom(C, op, event, WM_operator_props_popup_confirm);
}
static void MARKER_OT_rename(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Rename Marker";
- ot->description = "Rename first selected time marker";
- ot->idname = "MARKER_OT_rename";
-
- /* api callbacks */
- ot->invoke = ed_marker_rename_invoke_wrapper;
- ot->exec = ed_marker_rename_exec;
- ot->poll = ed_markers_poll_selected_no_locked_markers;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_string(ot->srna, "name", "RenamedMarker", sizeof(((TimeMarker *)NULL)->name), "Name", "New name for marker");
- //RNA_def_boolean(ot->srna, "ensure_unique", 0, "Ensure Unique", "Ensure that new name is unique within collection of markers");
+ /* identifiers */
+ ot->name = "Rename Marker";
+ ot->description = "Rename first selected time marker";
+ ot->idname = "MARKER_OT_rename";
+
+ /* api callbacks */
+ ot->invoke = ed_marker_rename_invoke_wrapper;
+ ot->exec = ed_marker_rename_exec;
+ ot->poll = ed_markers_poll_selected_no_locked_markers;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_string(ot->srna,
+ "name",
+ "RenamedMarker",
+ sizeof(((TimeMarker *)NULL)->name),
+ "Name",
+ "New name for marker");
+ //RNA_def_boolean(ot->srna, "ensure_unique", 0, "Ensure Unique", "Ensure that new name is unique within collection of markers");
}
/* **************** make links to scene ***************** */
static int ed_marker_make_links_scene_exec(bContext *C, wmOperator *op)
{
- ListBase *markers = ED_context_get_markers(C);
- Scene *scene_to = BLI_findlink(&CTX_data_main(C)->scenes, RNA_enum_get(op->ptr, "scene"));
- TimeMarker *marker, *marker_new;
-
- if (scene_to == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Scene not found");
- return OPERATOR_CANCELLED;
- }
-
- if (scene_to == CTX_data_scene(C)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot re-link markers into the same scene");
- return OPERATOR_CANCELLED;
- }
-
- if (scene_to->toolsettings->lock_markers) {
- BKE_report(op->reports, RPT_ERROR, "Target scene has locked markers");
- return OPERATOR_CANCELLED;
- }
-
- /* copy markers */
- for (marker = markers->first; marker; marker = marker->next) {
- if (marker->flag & SELECT) {
- marker_new = MEM_dupallocN(marker);
- marker_new->prev = marker_new->next = NULL;
-
- BLI_addtail(&scene_to->markers, marker_new);
- }
- }
-
- return OPERATOR_FINISHED;
+ ListBase *markers = ED_context_get_markers(C);
+ Scene *scene_to = BLI_findlink(&CTX_data_main(C)->scenes, RNA_enum_get(op->ptr, "scene"));
+ TimeMarker *marker, *marker_new;
+
+ if (scene_to == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Scene not found");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (scene_to == CTX_data_scene(C)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot re-link markers into the same scene");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (scene_to->toolsettings->lock_markers) {
+ BKE_report(op->reports, RPT_ERROR, "Target scene has locked markers");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* copy markers */
+ for (marker = markers->first; marker; marker = marker->next) {
+ if (marker->flag & SELECT) {
+ marker_new = MEM_dupallocN(marker);
+ marker_new->prev = marker_new->next = NULL;
+
+ BLI_addtail(&scene_to->markers, marker_new);
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
-static int ed_marker_make_links_scene_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event)
+static int ed_marker_make_links_scene_invoke_wrapper(bContext *C,
+ wmOperator *op,
+ const wmEvent *event)
{
- return ed_markers_opwrap_invoke_custom(C, op, event, WM_menu_invoke);
+ return ed_markers_opwrap_invoke_custom(C, op, event, WM_menu_invoke);
}
static void MARKER_OT_make_links_scene(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Make Links to Scene";
- ot->description = "Copy selected markers to another scene";
- ot->idname = "MARKER_OT_make_links_scene";
-
- /* api callbacks */
- ot->exec = ed_marker_make_links_scene_exec;
- ot->invoke = ed_marker_make_links_scene_invoke_wrapper;
- ot->poll = ed_markers_poll_selected_markers;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "scene", DummyRNA_NULL_items, 0, "Scene", "");
- RNA_def_enum_funcs(prop, RNA_scene_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
-
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Make Links to Scene";
+ ot->description = "Copy selected markers to another scene";
+ ot->idname = "MARKER_OT_make_links_scene";
+
+ /* api callbacks */
+ ot->exec = ed_marker_make_links_scene_exec;
+ ot->invoke = ed_marker_make_links_scene_invoke_wrapper;
+ ot->poll = ed_markers_poll_selected_markers;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna, "scene", DummyRNA_NULL_items, 0, "Scene", "");
+ RNA_def_enum_funcs(prop, RNA_scene_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
#ifdef DURIAN_CAMERA_SWITCH
@@ -1565,65 +1579,65 @@ 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);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- ListBase *markers = ED_context_get_markers(C);
- TimeMarker *marker;
-
- /* Don't do anything if we don't have a camera selected */
- if (ob == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Select a camera to bind to a marker on this frame");
- return OPERATOR_CANCELLED;
- }
-
- /* add new marker, unless we already have one on this frame, in which case, replace it */
- if (markers == NULL)
- return OPERATOR_CANCELLED;
-
- marker = ED_markers_find_nearest_marker(markers, CFRA);
- if ((marker == NULL) || (marker->frame != CFRA)) {
- marker = MEM_callocN(sizeof(TimeMarker), "Camera TimeMarker");
- marker->flag = SELECT;
- marker->frame = CFRA;
- 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) {
- if (m != marker) {
- m->flag &= ~SELECT;
- }
- }
- }
-
- /* bind to the nominated camera (as set in operator props) */
- marker->camera = ob;
-
- /* camera may have changes */
- BKE_scene_camera_switch_update(scene);
- BKE_screen_view3d_scene_sync(sc, scene);
-
- WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
- WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene); /* so we get view3d redraws */
-
- return OPERATOR_FINISHED;
+ bScreen *sc = CTX_wm_screen(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ ListBase *markers = ED_context_get_markers(C);
+ TimeMarker *marker;
+
+ /* Don't do anything if we don't have a camera selected */
+ if (ob == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Select a camera to bind to a marker on this frame");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* add new marker, unless we already have one on this frame, in which case, replace it */
+ if (markers == NULL)
+ return OPERATOR_CANCELLED;
+
+ marker = ED_markers_find_nearest_marker(markers, CFRA);
+ if ((marker == NULL) || (marker->frame != CFRA)) {
+ marker = MEM_callocN(sizeof(TimeMarker), "Camera TimeMarker");
+ marker->flag = SELECT;
+ marker->frame = CFRA;
+ 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) {
+ if (m != marker) {
+ m->flag &= ~SELECT;
+ }
+ }
+ }
+
+ /* bind to the nominated camera (as set in operator props) */
+ marker->camera = ob;
+
+ /* camera may have changes */
+ BKE_scene_camera_switch_update(scene);
+ BKE_screen_view3d_scene_sync(sc, scene);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
+ WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene); /* so we get view3d redraws */
+
+ return OPERATOR_FINISHED;
}
static void MARKER_OT_camera_bind(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Bind Camera to Markers";
- ot->description = "Bind the selected camera to a marker on the current frame";
- ot->idname = "MARKER_OT_camera_bind";
-
- /* api callbacks */
- ot->exec = ed_marker_camera_bind_exec;
- ot->invoke = ed_markers_opwrap_invoke;
- ot->poll = ED_operator_animview_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Bind Camera to Markers";
+ ot->description = "Bind the selected camera to a marker on the current frame";
+ ot->idname = "MARKER_OT_camera_bind";
+
+ /* api callbacks */
+ ot->exec = ed_marker_camera_bind_exec;
+ ot->invoke = ed_markers_opwrap_invoke;
+ ot->poll = ED_operator_animview_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
#endif
@@ -1632,22 +1646,22 @@ static void MARKER_OT_camera_bind(wmOperatorType *ot)
/* called in screen_ops.c:ED_operatortypes_screen() */
void ED_operatortypes_marker(void)
{
- WM_operatortype_append(MARKER_OT_add);
- WM_operatortype_append(MARKER_OT_move);
- WM_operatortype_append(MARKER_OT_duplicate);
- WM_operatortype_append(MARKER_OT_select);
- WM_operatortype_append(MARKER_OT_select_box);
- WM_operatortype_append(MARKER_OT_select_all);
- WM_operatortype_append(MARKER_OT_delete);
- WM_operatortype_append(MARKER_OT_rename);
- WM_operatortype_append(MARKER_OT_make_links_scene);
+ WM_operatortype_append(MARKER_OT_add);
+ WM_operatortype_append(MARKER_OT_move);
+ WM_operatortype_append(MARKER_OT_duplicate);
+ WM_operatortype_append(MARKER_OT_select);
+ WM_operatortype_append(MARKER_OT_select_box);
+ WM_operatortype_append(MARKER_OT_select_all);
+ WM_operatortype_append(MARKER_OT_delete);
+ WM_operatortype_append(MARKER_OT_rename);
+ WM_operatortype_append(MARKER_OT_make_links_scene);
#ifdef DURIAN_CAMERA_SWITCH
- WM_operatortype_append(MARKER_OT_camera_bind);
+ WM_operatortype_append(MARKER_OT_camera_bind);
#endif
}
/* called in screen_ops.c:ED_keymap_screen() */
void ED_keymap_marker(wmKeyConfig *keyconf)
{
- WM_keymap_ensure(keyconf, "Markers", 0, 0);
+ WM_keymap_ensure(keyconf, "Markers", 0, 0);
}
diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c
index 7023a138c96..b1183167945 100644
--- a/source/blender/editors/animation/anim_motion_paths.c
+++ b/source/blender/editors/animation/anim_motion_paths.c
@@ -48,23 +48,22 @@
static CLG_LogRef LOG = {"ed.anim.motion_paths"};
-
/* Motion path needing to be baked (mpt) */
typedef struct MPathTarget {
- struct MPathTarget *next, *prev;
+ struct MPathTarget *next, *prev;
- bMotionPath *mpath; /* motion path in question */
+ bMotionPath *mpath; /* motion path in question */
- DLRBT_Tree keys; /* temp, to know where the keyframes are */
+ DLRBT_Tree keys; /* temp, to know where the keyframes are */
- /* Original (Source Objects) */
- Object *ob; /* source object */
- bPoseChannel *pchan; /* source posechannel (if applicable) */
+ /* Original (Source Objects) */
+ Object *ob; /* source object */
+ bPoseChannel *pchan; /* source posechannel (if applicable) */
- /* "Evaluated" Copies (these come from the background COW copie
- * that provide all the coordinates we want to save off)
- */
- Object *ob_eval; /* evaluated object */
+ /* "Evaluated" Copies (these come from the background COW copie
+ * that provide all the coordinates we want to save off)
+ */
+ Object *ob_eval; /* evaluated object */
} MPathTarget;
/* ........ */
@@ -75,54 +74,53 @@ typedef struct MPathTarget {
/* TODO: it would be nice in future to be able to update objects dependent on these bones too? */
void animviz_get_object_motionpaths(Object *ob, ListBase *targets)
{
- MPathTarget *mpt;
-
- /* object itself first */
- if ((ob->avs.recalc & ANIMVIZ_RECALC_PATHS) && (ob->mpath)) {
- /* new target for object */
- mpt = MEM_callocN(sizeof(MPathTarget), "MPathTarget Ob");
- BLI_addtail(targets, mpt);
-
- mpt->mpath = ob->mpath;
- mpt->ob = ob;
- }
-
- /* bones */
- if ((ob->pose) && (ob->pose->avs.recalc & ANIMVIZ_RECALC_PATHS)) {
- bArmature *arm = ob->data;
- bPoseChannel *pchan;
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if ((pchan->bone) && (arm->layer & pchan->bone->layer) && (pchan->mpath)) {
- /* new target for bone */
- mpt = MEM_callocN(sizeof(MPathTarget), "MPathTarget PoseBone");
- BLI_addtail(targets, mpt);
-
- mpt->mpath = pchan->mpath;
- mpt->ob = ob;
- mpt->pchan = pchan;
- }
- }
- }
+ MPathTarget *mpt;
+
+ /* object itself first */
+ if ((ob->avs.recalc & ANIMVIZ_RECALC_PATHS) && (ob->mpath)) {
+ /* new target for object */
+ mpt = MEM_callocN(sizeof(MPathTarget), "MPathTarget Ob");
+ BLI_addtail(targets, mpt);
+
+ mpt->mpath = ob->mpath;
+ mpt->ob = ob;
+ }
+
+ /* bones */
+ if ((ob->pose) && (ob->pose->avs.recalc & ANIMVIZ_RECALC_PATHS)) {
+ bArmature *arm = ob->data;
+ bPoseChannel *pchan;
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if ((pchan->bone) && (arm->layer & pchan->bone->layer) && (pchan->mpath)) {
+ /* new target for bone */
+ mpt = MEM_callocN(sizeof(MPathTarget), "MPathTarget PoseBone");
+ BLI_addtail(targets, mpt);
+
+ mpt->mpath = pchan->mpath;
+ mpt->ob = ob;
+ mpt->pchan = pchan;
+ }
+ }
+ }
}
/* ........ */
/* update scene for current frame */
-static void motionpaths_calc_update_scene(Main *bmain,
- struct Depsgraph *depsgraph)
+static void motionpaths_calc_update_scene(Main *bmain, struct Depsgraph *depsgraph)
{
- /* Do all updates
- * - if this is too slow, resort to using a more efficient way
- * that doesn't force complete update, but for now, this is the
- * most accurate way!
- *
- * TODO(segey): Bring back partial updates, which became impossible
- * with the new depsgraph due to unsorted nature of bases.
- *
- * TODO(sergey): Use evaluation context dedicated to motion paths.
- */
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+ /* Do all updates
+ * - if this is too slow, resort to using a more efficient way
+ * that doesn't force complete update, but for now, this is the
+ * most accurate way!
+ *
+ * TODO(segey): Bring back partial updates, which became impossible
+ * with the new depsgraph due to unsorted nature of bases.
+ *
+ * TODO(sergey): Use evaluation context dedicated to motion paths.
+ */
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
}
/* ........ */
@@ -130,78 +128,78 @@ static void motionpaths_calc_update_scene(Main *bmain,
/* perform baking for the targets on the current frame */
static void motionpaths_calc_bake_targets(ListBase *targets, int cframe)
{
- MPathTarget *mpt;
-
- /* for each target, check if it can be baked on the current frame */
- for (mpt = targets->first; mpt; mpt = mpt->next) {
- bMotionPath *mpath = mpt->mpath;
-
- /* current frame must be within the range the cache works for
- * - is inclusive of the first frame, but not the last otherwise we get buffer overruns
- */
- if ((cframe < mpath->start_frame) || (cframe >= mpath->end_frame)) {
- continue;
- }
-
- /* get the relevant cache vert to write to */
- bMotionPathVert *mpv = mpath->points + (cframe - mpath->start_frame);
-
- Object *ob_eval = mpt->ob_eval;
-
- /* Lookup evaluated pose channel, here because the depsgraph
- * evaluation can change them so they are not cached in mpt. */
- bPoseChannel *pchan_eval = NULL;
- if (mpt->pchan) {
- pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, mpt->pchan->name);
- }
-
- /* pose-channel or object path baking? */
- if (pchan_eval) {
- /* heads or tails */
- if (mpath->flag & MOTIONPATH_FLAG_BHEAD) {
- copy_v3_v3(mpv->co, pchan_eval->pose_head);
- }
- else {
- copy_v3_v3(mpv->co, pchan_eval->pose_tail);
- }
-
- /* result must be in worldspace */
- mul_m4_v3(ob_eval->obmat, mpv->co);
- }
- else {
- /* worldspace object location */
- copy_v3_v3(mpv->co, ob_eval->obmat[3]);
- }
-
- float mframe = (float)(cframe);
-
- /* Tag if it's a keyframe */
- if (BLI_dlrbTree_search_exact(&mpt->keys, compare_ak_cfraPtr, &mframe)) {
- mpv->flag |= MOTIONPATH_VERT_KEY;
- }
- else {
- mpv->flag &= ~MOTIONPATH_VERT_KEY;
- }
-
- /* Incremental update on evaluated object if possible, for fast updating
- * while dragging in transform. */
- bMotionPath *mpath_eval = NULL;
- if (mpt->pchan) {
- mpath_eval = (pchan_eval) ? pchan_eval->mpath : NULL;
- }
- else {
- mpath_eval = ob_eval->mpath;
- }
-
- if (mpath_eval && mpath_eval->length == mpath->length) {
- bMotionPathVert *mpv_eval = mpath_eval->points + (cframe - mpath_eval->start_frame);
- *mpv_eval = *mpv;
-
- GPU_VERTBUF_DISCARD_SAFE(mpath_eval->points_vbo);
- GPU_BATCH_DISCARD_SAFE(mpath_eval->batch_line);
- GPU_BATCH_DISCARD_SAFE(mpath_eval->batch_points);
- }
- }
+ MPathTarget *mpt;
+
+ /* for each target, check if it can be baked on the current frame */
+ for (mpt = targets->first; mpt; mpt = mpt->next) {
+ bMotionPath *mpath = mpt->mpath;
+
+ /* current frame must be within the range the cache works for
+ * - is inclusive of the first frame, but not the last otherwise we get buffer overruns
+ */
+ if ((cframe < mpath->start_frame) || (cframe >= mpath->end_frame)) {
+ continue;
+ }
+
+ /* get the relevant cache vert to write to */
+ bMotionPathVert *mpv = mpath->points + (cframe - mpath->start_frame);
+
+ Object *ob_eval = mpt->ob_eval;
+
+ /* Lookup evaluated pose channel, here because the depsgraph
+ * evaluation can change them so they are not cached in mpt. */
+ bPoseChannel *pchan_eval = NULL;
+ if (mpt->pchan) {
+ pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, mpt->pchan->name);
+ }
+
+ /* pose-channel or object path baking? */
+ if (pchan_eval) {
+ /* heads or tails */
+ if (mpath->flag & MOTIONPATH_FLAG_BHEAD) {
+ copy_v3_v3(mpv->co, pchan_eval->pose_head);
+ }
+ else {
+ copy_v3_v3(mpv->co, pchan_eval->pose_tail);
+ }
+
+ /* result must be in worldspace */
+ mul_m4_v3(ob_eval->obmat, mpv->co);
+ }
+ else {
+ /* worldspace object location */
+ copy_v3_v3(mpv->co, ob_eval->obmat[3]);
+ }
+
+ float mframe = (float)(cframe);
+
+ /* Tag if it's a keyframe */
+ if (BLI_dlrbTree_search_exact(&mpt->keys, compare_ak_cfraPtr, &mframe)) {
+ mpv->flag |= MOTIONPATH_VERT_KEY;
+ }
+ else {
+ mpv->flag &= ~MOTIONPATH_VERT_KEY;
+ }
+
+ /* Incremental update on evaluated object if possible, for fast updating
+ * while dragging in transform. */
+ bMotionPath *mpath_eval = NULL;
+ if (mpt->pchan) {
+ mpath_eval = (pchan_eval) ? pchan_eval->mpath : NULL;
+ }
+ else {
+ mpath_eval = ob_eval->mpath;
+ }
+
+ if (mpath_eval && mpath_eval->length == mpath->length) {
+ bMotionPathVert *mpv_eval = mpath_eval->points + (cframe - mpath_eval->start_frame);
+ *mpv_eval = *mpv;
+
+ GPU_VERTBUF_DISCARD_SAFE(mpath_eval->points_vbo);
+ GPU_BATCH_DISCARD_SAFE(mpath_eval->batch_line);
+ GPU_BATCH_DISCARD_SAFE(mpath_eval->batch_points);
+ }
+ }
}
/* Perform baking of the given object's and/or its bones' transforms to motion paths
@@ -217,119 +215,124 @@ void animviz_calc_motionpaths(Depsgraph *depsgraph,
bool restore,
bool current_frame_only)
{
- /* sanity check */
- if (ELEM(NULL, targets, targets->first))
- return;
-
- /* Compute frame range to bake within.
- * TODO: this method could be improved...
- * 1) max range for standard baking
- * 2) minimum range for recalc baking (i.e. between keyframes, but how?) */
- int sfra = INT_MAX;
- int efra = INT_MIN;
-
- for (MPathTarget *mpt = targets->first; mpt; mpt = mpt->next) {
- /* try to increase area to do (only as much as needed) */
- sfra = MIN2(sfra, mpt->mpath->start_frame);
- efra = MAX2(efra, mpt->mpath->end_frame);
- }
-
- if (efra <= sfra) {
- return;
- }
-
- /* Limit frame range if we are updating just the current frame. */
- /* set frame values */
- int cfra = CFRA;
- if (current_frame_only) {
- if (cfra < sfra || cfra > efra) {
- return;
- }
- sfra = efra = cfra;
- }
-
- /* get copies of objects/bones to get the calculated results from
- * (for copy-on-write evaluation), so that we actually get some results
- */
- // TODO: Create a copy of background depsgraph that only contain these entities, and only evaluates them..
- for (MPathTarget *mpt = targets->first; mpt; mpt = mpt->next) {
- mpt->ob_eval = DEG_get_evaluated_object(depsgraph, mpt->ob);
-
- AnimData *adt = BKE_animdata_from_id(&mpt->ob_eval->id);
-
- /* build list of all keyframes in active action for object or pchan */
- BLI_dlrbTree_init(&mpt->keys);
-
- if (adt) {
- bAnimVizSettings *avs;
-
- /* get pointer to animviz settings for each target */
- if (mpt->pchan)
- avs = &mpt->ob->pose->avs;
- else
- avs = &mpt->ob->avs;
-
- /* it is assumed that keyframes for bones are all grouped in a single group
- * unless an option is set to always use the whole action
- */
- if ((mpt->pchan) && (avs->path_viewflag & MOTIONPATH_VIEW_KFACT) == 0) {
- bActionGroup *agrp = BKE_action_group_find_name(adt->action, mpt->pchan->name);
-
- if (agrp) {
- agroup_to_keylist(adt, agrp, &mpt->keys, 0);
- }
- }
- else {
- action_to_keylist(adt, adt->action, &mpt->keys, 0);
- }
- }
- }
-
- /* calculate path over requested range */
- CLOG_INFO(&LOG, 1, "Calculating MotionPaths between frames %d - %d (%d frames)", sfra, efra, efra - sfra + 1);
- for (CFRA = sfra; CFRA <= efra; CFRA++) {
- if (current_frame_only) {
- /* For current frame, only update tagged. */
- BKE_scene_graph_update_tagged(depsgraph, bmain);
- }
- else {
- /* Update relevant data for new frame. */
- motionpaths_calc_update_scene(bmain, depsgraph);
- }
-
- /* perform baking for targets */
- motionpaths_calc_bake_targets(targets, CFRA);
- }
-
- /* reset original environment */
- /* NOTE: We don't always need to reevaluate the main scene, as the depsgraph
- * may be a temporary one that works on a subset of the data. We always have
- * to resoture the current frame though. */
- CFRA = cfra;
- if (!current_frame_only && restore) {
- motionpaths_calc_update_scene(bmain, depsgraph);
- }
-
- /* clear recalc flags from targets */
- for (MPathTarget *mpt = targets->first; mpt; mpt = mpt->next) {
- bAnimVizSettings *avs;
- bMotionPath *mpath = mpt->mpath;
-
- /* get pointer to animviz settings for each target */
- if (mpt->pchan)
- avs = &mpt->ob->pose->avs;
- else
- avs = &mpt->ob->avs;
-
- /* clear the flag requesting recalculation of targets */
- avs->recalc &= ~ANIMVIZ_RECALC_PATHS;
-
- /* Clean temp data */
- BLI_dlrbTree_free(&mpt->keys);
-
- /* Free previous batches to force update. */
- GPU_VERTBUF_DISCARD_SAFE(mpath->points_vbo);
- GPU_BATCH_DISCARD_SAFE(mpath->batch_line);
- GPU_BATCH_DISCARD_SAFE(mpath->batch_points);
- }
+ /* sanity check */
+ if (ELEM(NULL, targets, targets->first))
+ return;
+
+ /* Compute frame range to bake within.
+ * TODO: this method could be improved...
+ * 1) max range for standard baking
+ * 2) minimum range for recalc baking (i.e. between keyframes, but how?) */
+ int sfra = INT_MAX;
+ int efra = INT_MIN;
+
+ for (MPathTarget *mpt = targets->first; mpt; mpt = mpt->next) {
+ /* try to increase area to do (only as much as needed) */
+ sfra = MIN2(sfra, mpt->mpath->start_frame);
+ efra = MAX2(efra, mpt->mpath->end_frame);
+ }
+
+ if (efra <= sfra) {
+ return;
+ }
+
+ /* Limit frame range if we are updating just the current frame. */
+ /* set frame values */
+ int cfra = CFRA;
+ if (current_frame_only) {
+ if (cfra < sfra || cfra > efra) {
+ return;
+ }
+ sfra = efra = cfra;
+ }
+
+ /* get copies of objects/bones to get the calculated results from
+ * (for copy-on-write evaluation), so that we actually get some results
+ */
+ // TODO: Create a copy of background depsgraph that only contain these entities, and only evaluates them..
+ for (MPathTarget *mpt = targets->first; mpt; mpt = mpt->next) {
+ mpt->ob_eval = DEG_get_evaluated_object(depsgraph, mpt->ob);
+
+ AnimData *adt = BKE_animdata_from_id(&mpt->ob_eval->id);
+
+ /* build list of all keyframes in active action for object or pchan */
+ BLI_dlrbTree_init(&mpt->keys);
+
+ if (adt) {
+ bAnimVizSettings *avs;
+
+ /* get pointer to animviz settings for each target */
+ if (mpt->pchan)
+ avs = &mpt->ob->pose->avs;
+ else
+ avs = &mpt->ob->avs;
+
+ /* it is assumed that keyframes for bones are all grouped in a single group
+ * unless an option is set to always use the whole action
+ */
+ if ((mpt->pchan) && (avs->path_viewflag & MOTIONPATH_VIEW_KFACT) == 0) {
+ bActionGroup *agrp = BKE_action_group_find_name(adt->action, mpt->pchan->name);
+
+ if (agrp) {
+ agroup_to_keylist(adt, agrp, &mpt->keys, 0);
+ }
+ }
+ else {
+ action_to_keylist(adt, adt->action, &mpt->keys, 0);
+ }
+ }
+ }
+
+ /* calculate path over requested range */
+ CLOG_INFO(&LOG,
+ 1,
+ "Calculating MotionPaths between frames %d - %d (%d frames)",
+ sfra,
+ efra,
+ efra - sfra + 1);
+ for (CFRA = sfra; CFRA <= efra; CFRA++) {
+ if (current_frame_only) {
+ /* For current frame, only update tagged. */
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
+ }
+ else {
+ /* Update relevant data for new frame. */
+ motionpaths_calc_update_scene(bmain, depsgraph);
+ }
+
+ /* perform baking for targets */
+ motionpaths_calc_bake_targets(targets, CFRA);
+ }
+
+ /* reset original environment */
+ /* NOTE: We don't always need to reevaluate the main scene, as the depsgraph
+ * may be a temporary one that works on a subset of the data. We always have
+ * to resoture the current frame though. */
+ CFRA = cfra;
+ if (!current_frame_only && restore) {
+ motionpaths_calc_update_scene(bmain, depsgraph);
+ }
+
+ /* clear recalc flags from targets */
+ for (MPathTarget *mpt = targets->first; mpt; mpt = mpt->next) {
+ bAnimVizSettings *avs;
+ bMotionPath *mpath = mpt->mpath;
+
+ /* get pointer to animviz settings for each target */
+ if (mpt->pchan)
+ avs = &mpt->ob->pose->avs;
+ else
+ avs = &mpt->ob->avs;
+
+ /* clear the flag requesting recalculation of targets */
+ avs->recalc &= ~ANIMVIZ_RECALC_PATHS;
+
+ /* Clean temp data */
+ BLI_dlrbTree_free(&mpt->keys);
+
+ /* Free previous batches to force update. */
+ GPU_VERTBUF_DISCARD_SAFE(mpath->points_vbo);
+ GPU_BATCH_DISCARD_SAFE(mpath->batch_line);
+ GPU_BATCH_DISCARD_SAFE(mpath->batch_points);
+ }
}
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index 2287f2e0347..91cbc2ff3e0 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -21,7 +21,6 @@
* \ingroup edanimation
*/
-
#include <stdlib.h>
#include <math.h>
@@ -60,61 +59,62 @@
/* Check if the operator can be run from the current context */
static bool change_frame_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
-
- /* XXX temp? prevent changes during render */
- if (G.is_rendering) return false;
-
- /* 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)) {
- 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");
- return false;
+ ScrArea *sa = CTX_wm_area(C);
+
+ /* XXX temp? prevent changes during render */
+ if (G.is_rendering)
+ return false;
+
+ /* 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)) {
+ 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");
+ return false;
}
/* Set the new frame number */
static void change_frame_apply(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- float frame = RNA_float_get(op->ptr, "frame");
- bool do_snap = RNA_boolean_get(op->ptr, "snap");
-
- if (do_snap) {
- if (CTX_wm_space_seq(C)) {
- frame = BKE_sequencer_find_next_prev_edit(scene, frame, SEQ_SIDE_BOTH, true, false, false);
- }
- else {
- frame = BKE_scene_frame_snap_by_seconds(scene, 1.0, frame);
- }
- }
-
- /* set the new frame number */
- if (scene->r.flag & SCER_SHOW_SUBFRAME) {
- CFRA = (int)frame;
- SUBFRA = frame - (int)frame;
- }
- else {
- CFRA = round_fl_to_int(frame);
- SUBFRA = 0.0f;
- }
- FRAMENUMBER_MIN_CLAMP(CFRA);
-
- /* do updates */
- BKE_sound_seek_scene(bmain, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ float frame = RNA_float_get(op->ptr, "frame");
+ bool do_snap = RNA_boolean_get(op->ptr, "snap");
+
+ if (do_snap) {
+ if (CTX_wm_space_seq(C)) {
+ frame = BKE_sequencer_find_next_prev_edit(scene, frame, SEQ_SIDE_BOTH, true, false, false);
+ }
+ else {
+ frame = BKE_scene_frame_snap_by_seconds(scene, 1.0, frame);
+ }
+ }
+
+ /* set the new frame number */
+ if (scene->r.flag & SCER_SHOW_SUBFRAME) {
+ CFRA = (int)frame;
+ SUBFRA = frame - (int)frame;
+ }
+ else {
+ CFRA = round_fl_to_int(frame);
+ SUBFRA = 0.0f;
+ }
+ FRAMENUMBER_MIN_CLAMP(CFRA);
+
+ /* do updates */
+ BKE_sound_seek_scene(bmain, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
/* ---- */
@@ -122,9 +122,9 @@ static void change_frame_apply(bContext *C, wmOperator *op)
/* Non-modal callback for running operator without user input */
static int change_frame_exec(bContext *C, wmOperator *op)
{
- change_frame_apply(C, op);
+ change_frame_apply(C, op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* ---- */
@@ -132,402 +132,401 @@ static int change_frame_exec(bContext *C, wmOperator *op)
/* Get frame from mouse coordinates */
static float frame_from_event(bContext *C, const wmEvent *event)
{
- ARegion *region = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
- float frame;
+ ARegion *region = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+ float frame;
- /* convert from region coordinates to View2D 'tot' space */
- frame = UI_view2d_region_to_view_x(&region->v2d, event->mval[0]);
+ /* convert from region coordinates to View2D 'tot' space */
+ frame = UI_view2d_region_to_view_x(&region->v2d, event->mval[0]);
- /* respect preview range restrictions (if only allowed to move around within that range) */
- if (scene->r.flag & SCER_LOCK_FRAME_SELECTION) {
- CLAMP(frame, PSFRA, PEFRA);
- }
+ /* respect preview range restrictions (if only allowed to move around within that range) */
+ if (scene->r.flag & SCER_LOCK_FRAME_SELECTION) {
+ CLAMP(frame, PSFRA, PEFRA);
+ }
- return frame;
+ return frame;
}
static void change_frame_seq_preview_begin(bContext *C, const wmEvent *event)
{
- ScrArea *sa = 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)) {
- ED_sequencer_special_preview_set(C, event->mval);
- }
- }
- if (screen)
- screen->scrubbing = true;
+ ScrArea *sa = 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)) {
+ ED_sequencer_special_preview_set(C, event->mval);
+ }
+ }
+ if (screen)
+ screen->scrubbing = true;
}
static void change_frame_seq_preview_end(bContext *C)
{
- bScreen *screen = CTX_wm_screen(C);
- bool notify = false;
-
- if (screen->scrubbing) {
- screen->scrubbing = false;
- notify = true;
- }
-
- if (ED_sequencer_special_preview_get() != NULL) {
- ED_sequencer_special_preview_clear();
- notify = true;
- }
-
- if (notify) {
- Scene *scene = CTX_data_scene(C);
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
- }
+ bScreen *screen = CTX_wm_screen(C);
+ bool notify = false;
+
+ if (screen->scrubbing) {
+ screen->scrubbing = false;
+ notify = true;
+ }
+
+ if (ED_sequencer_special_preview_get() != NULL) {
+ ED_sequencer_special_preview_clear();
+ notify = true;
+ }
+
+ if (notify) {
+ Scene *scene = CTX_data_scene(C);
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ }
}
/* Modal Operator init */
static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- /* Change to frame that mouse is over before adding modal handler,
- * as user could click on a single frame (jump to frame) as well as
- * click-dragging over a range (modal scrubbing).
- */
- RNA_float_set(op->ptr, "frame", frame_from_event(C, event));
+ /* Change to frame that mouse is over before adding modal handler,
+ * as user could click on a single frame (jump to frame) as well as
+ * click-dragging over a range (modal scrubbing).
+ */
+ RNA_float_set(op->ptr, "frame", frame_from_event(C, event));
- change_frame_seq_preview_begin(C, event);
+ change_frame_seq_preview_begin(C, event);
- change_frame_apply(C, op);
+ change_frame_apply(C, op);
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static void change_frame_cancel(bContext *C, wmOperator *UNUSED(op))
{
- change_frame_seq_preview_end(C);
+ change_frame_seq_preview_end(C);
}
/* Modal event handling of frame changing */
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:
- ret = OPERATOR_FINISHED;
- break;
-
- case MOUSEMOVE:
- RNA_float_set(op->ptr, "frame", frame_from_event(C, event));
- change_frame_apply(C, op);
- break;
-
- case LEFTMOUSE:
- case RIGHTMOUSE:
- case MIDDLEMOUSE:
- /* We check for either mouse-button to end, to work with all user keymaps. */
- if (event->val == KM_RELEASE)
- ret = OPERATOR_FINISHED;
- break;
-
- case LEFTCTRLKEY:
- case RIGHTCTRLKEY:
- if (event->val == KM_RELEASE) {
- RNA_boolean_set(op->ptr, "snap", false);
- }
- else if (event->val == KM_PRESS) {
- RNA_boolean_set(op->ptr, "snap", true);
- }
- break;
- }
-
- if (ret != OPERATOR_RUNNING_MODAL) {
- change_frame_seq_preview_end(C);
- }
-
- return ret;
+ int ret = OPERATOR_RUNNING_MODAL;
+ /* execute the events */
+ switch (event->type) {
+ case ESCKEY:
+ ret = OPERATOR_FINISHED;
+ break;
+
+ case MOUSEMOVE:
+ RNA_float_set(op->ptr, "frame", frame_from_event(C, event));
+ change_frame_apply(C, op);
+ break;
+
+ case LEFTMOUSE:
+ case RIGHTMOUSE:
+ case MIDDLEMOUSE:
+ /* We check for either mouse-button to end, to work with all user keymaps. */
+ if (event->val == KM_RELEASE)
+ ret = OPERATOR_FINISHED;
+ break;
+
+ case LEFTCTRLKEY:
+ case RIGHTCTRLKEY:
+ if (event->val == KM_RELEASE) {
+ RNA_boolean_set(op->ptr, "snap", false);
+ }
+ else if (event->val == KM_PRESS) {
+ RNA_boolean_set(op->ptr, "snap", true);
+ }
+ break;
+ }
+
+ if (ret != OPERATOR_RUNNING_MODAL) {
+ change_frame_seq_preview_end(C);
+ }
+
+ return ret;
}
static void ANIM_OT_change_frame(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Change Frame";
- ot->idname = "ANIM_OT_change_frame";
- ot->description = "Interactively change the current frame number";
-
- /* api callbacks */
- ot->exec = change_frame_exec;
- ot->invoke = change_frame_invoke;
- ot->cancel = change_frame_cancel;
- ot->modal = change_frame_modal;
- ot->poll = change_frame_poll;
-
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_UNDO_GROUPED;
- ot->undo_group = "Frame Change";
-
- /* rna */
- ot->prop = RNA_def_float(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
- prop = RNA_def_boolean(ot->srna, "snap", false, "Snap", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Change Frame";
+ ot->idname = "ANIM_OT_change_frame";
+ ot->description = "Interactively change the current frame number";
+
+ /* api callbacks */
+ ot->exec = change_frame_exec;
+ ot->invoke = change_frame_invoke;
+ ot->cancel = change_frame_cancel;
+ ot->modal = change_frame_modal;
+ ot->poll = change_frame_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_UNDO_GROUPED;
+ ot->undo_group = "Frame Change";
+
+ /* rna */
+ ot->prop = RNA_def_float(
+ ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
+ prop = RNA_def_boolean(ot->srna, "snap", false, "Snap", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-
/* ****************** Start/End Frame Operators *******************************/
static bool anim_set_end_frames_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
-
- /* XXX temp? prevent changes during render */
- if (G.is_rendering) return false;
-
- /* 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)) {
- return true;
- }
- }
-
- CTX_wm_operator_poll_msg_set(C, "Expected an animation area to be active");
- return false;
+ ScrArea *sa = CTX_wm_area(C);
+
+ /* XXX temp? prevent changes during render */
+ if (G.is_rendering)
+ return false;
+
+ /* 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)) {
+ return true;
+ }
+ }
+
+ CTX_wm_operator_poll_msg_set(C, "Expected an animation area to be active");
+ return false;
}
static int anim_set_sfra_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- int frame;
+ Scene *scene = CTX_data_scene(C);
+ int frame;
- if (scene == NULL)
- return OPERATOR_CANCELLED;
+ if (scene == NULL)
+ return OPERATOR_CANCELLED;
- frame = CFRA;
+ frame = CFRA;
- /* if Preview Range is defined, set the 'start' frame for that */
- if (PRVRANGEON)
- scene->r.psfra = frame;
- else
- scene->r.sfra = frame;
+ /* if Preview Range is defined, set the 'start' frame for that */
+ if (PRVRANGEON)
+ scene->r.psfra = frame;
+ else
+ scene->r.sfra = frame;
- if (PEFRA < frame) {
- if (PRVRANGEON)
- scene->r.pefra = frame;
- else
- scene->r.efra = frame;
- }
+ if (PEFRA < frame) {
+ if (PRVRANGEON)
+ scene->r.pefra = frame;
+ else
+ scene->r.efra = frame;
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void ANIM_OT_start_frame_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Start Frame";
- ot->idname = "ANIM_OT_start_frame_set";
- ot->description = "Set the current frame as the preview or scene start frame";
+ /* identifiers */
+ ot->name = "Set Start Frame";
+ ot->idname = "ANIM_OT_start_frame_set";
+ ot->description = "Set the current frame as the preview or scene start frame";
- /* api callbacks */
- ot->exec = anim_set_sfra_exec;
- ot->poll = anim_set_end_frames_poll;
+ /* api callbacks */
+ ot->exec = anim_set_sfra_exec;
+ ot->poll = anim_set_end_frames_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
static int anim_set_efra_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- int frame;
+ Scene *scene = CTX_data_scene(C);
+ int frame;
- if (scene == NULL)
- return OPERATOR_CANCELLED;
+ if (scene == NULL)
+ return OPERATOR_CANCELLED;
- frame = CFRA;
+ frame = CFRA;
- /* if Preview Range is defined, set the 'end' frame for that */
- if (PRVRANGEON)
- scene->r.pefra = frame;
- else
- scene->r.efra = frame;
+ /* if Preview Range is defined, set the 'end' frame for that */
+ if (PRVRANGEON)
+ scene->r.pefra = frame;
+ else
+ scene->r.efra = frame;
- if (PSFRA > frame) {
- if (PRVRANGEON)
- scene->r.psfra = frame;
- else
- scene->r.sfra = frame;
- }
+ if (PSFRA > frame) {
+ if (PRVRANGEON)
+ scene->r.psfra = frame;
+ else
+ scene->r.sfra = frame;
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void ANIM_OT_end_frame_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set End Frame";
- ot->idname = "ANIM_OT_end_frame_set";
- ot->description = "Set the current frame as the preview or scene end frame";
+ /* identifiers */
+ ot->name = "Set End Frame";
+ ot->idname = "ANIM_OT_end_frame_set";
+ ot->description = "Set the current frame as the preview or scene end frame";
- /* api callbacks */
- ot->exec = anim_set_efra_exec;
- ot->poll = anim_set_end_frames_poll;
+ /* api callbacks */
+ ot->exec = anim_set_efra_exec;
+ ot->poll = anim_set_end_frames_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** set preview range operator ****************************/
static int previewrange_define_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
- float sfra, efra;
- rcti rect;
-
- /* get min/max values from box select rect (already in region coordinates, not screen) */
- 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);
-
- /* set start/end frames for preview-range
- * - must clamp within allowable limits
- * - end must not be before start (though this won't occur most of the time)
- */
- FRAMENUMBER_MIN_CLAMP(sfra);
- FRAMENUMBER_MIN_CLAMP(efra);
- if (efra < sfra) efra = sfra;
-
- scene->r.flag |= SCER_PRV_RANGE;
- scene->r.psfra = round_fl_to_int(sfra);
- scene->r.pefra = round_fl_to_int(efra);
-
- /* send notifiers */
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ ARegion *ar = CTX_wm_region(C);
+ float sfra, efra;
+ rcti rect;
+
+ /* get min/max values from box select rect (already in region coordinates, not screen) */
+ 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);
+
+ /* set start/end frames for preview-range
+ * - must clamp within allowable limits
+ * - end must not be before start (though this won't occur most of the time)
+ */
+ FRAMENUMBER_MIN_CLAMP(sfra);
+ FRAMENUMBER_MIN_CLAMP(efra);
+ if (efra < sfra)
+ efra = sfra;
+
+ scene->r.flag |= SCER_PRV_RANGE;
+ scene->r.psfra = round_fl_to_int(sfra);
+ scene->r.pefra = round_fl_to_int(efra);
+
+ /* send notifiers */
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+
+ return OPERATOR_FINISHED;
}
static void ANIM_OT_previewrange_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Preview Range";
- ot->idname = "ANIM_OT_previewrange_set";
- ot->description = "Interactively define frame range used for playback";
-
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = previewrange_define_exec;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
-
- ot->poll = ED_operator_animview_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* rna */
- /* used to define frame range.
- *
- * note: border Y values are not used,
- * but are needed by box_select gesture operator stuff */
- WM_operator_properties_border(ot);
+ /* identifiers */
+ ot->name = "Set Preview Range";
+ ot->idname = "ANIM_OT_previewrange_set";
+ ot->description = "Interactively define frame range used for playback";
+
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = previewrange_define_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
+
+ ot->poll = ED_operator_animview_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* rna */
+ /* used to define frame range.
+ *
+ * note: border Y values are not used,
+ * but are needed by box_select gesture operator stuff */
+ WM_operator_properties_border(ot);
}
/* ****************** clear preview range operator ****************************/
static int previewrange_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- ScrArea *curarea = CTX_wm_area(C);
+ Scene *scene = CTX_data_scene(C);
+ ScrArea *curarea = CTX_wm_area(C);
- /* sanity checks */
- if (ELEM(NULL, scene, curarea))
- return OPERATOR_CANCELLED;
+ /* sanity checks */
+ if (ELEM(NULL, scene, curarea))
+ return OPERATOR_CANCELLED;
- /* simply clear values */
- scene->r.flag &= ~SCER_PRV_RANGE;
- scene->r.psfra = 0;
- scene->r.pefra = 0;
+ /* simply clear values */
+ scene->r.flag &= ~SCER_PRV_RANGE;
+ scene->r.psfra = 0;
+ scene->r.pefra = 0;
- ED_area_tag_redraw(curarea);
+ ED_area_tag_redraw(curarea);
- /* send notifiers */
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ /* send notifiers */
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void ANIM_OT_previewrange_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Preview Range";
- ot->idname = "ANIM_OT_previewrange_clear";
- ot->description = "Clear Preview Range";
+ /* identifiers */
+ ot->name = "Clear Preview Range";
+ ot->idname = "ANIM_OT_previewrange_clear";
+ ot->description = "Clear Preview Range";
- /* api callbacks */
- ot->exec = previewrange_clear_exec;
+ /* api callbacks */
+ ot->exec = previewrange_clear_exec;
- ot->poll = ED_operator_animview_active;
+ ot->poll = ED_operator_animview_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ************************** registration **********************************/
void ED_operatortypes_anim(void)
{
- /* Animation Editors only -------------------------- */
- WM_operatortype_append(ANIM_OT_change_frame);
-
- WM_operatortype_append(ANIM_OT_start_frame_set);
- WM_operatortype_append(ANIM_OT_end_frame_set);
-
- WM_operatortype_append(ANIM_OT_previewrange_set);
- WM_operatortype_append(ANIM_OT_previewrange_clear);
-
- /* Entire UI --------------------------------------- */
- WM_operatortype_append(ANIM_OT_keyframe_insert);
- WM_operatortype_append(ANIM_OT_keyframe_delete);
- WM_operatortype_append(ANIM_OT_keyframe_insert_menu);
- WM_operatortype_append(ANIM_OT_keyframe_delete_v3d);
- WM_operatortype_append(ANIM_OT_keyframe_clear_v3d);
- WM_operatortype_append(ANIM_OT_keyframe_insert_button);
- WM_operatortype_append(ANIM_OT_keyframe_delete_button);
- WM_operatortype_append(ANIM_OT_keyframe_clear_button);
- WM_operatortype_append(ANIM_OT_keyframe_insert_by_name);
- WM_operatortype_append(ANIM_OT_keyframe_delete_by_name);
-
-
- WM_operatortype_append(ANIM_OT_driver_button_add);
- WM_operatortype_append(ANIM_OT_driver_button_remove);
- WM_operatortype_append(ANIM_OT_driver_button_edit);
- WM_operatortype_append(ANIM_OT_copy_driver_button);
- WM_operatortype_append(ANIM_OT_paste_driver_button);
-
-
- WM_operatortype_append(ANIM_OT_keyingset_button_add);
- WM_operatortype_append(ANIM_OT_keyingset_button_remove);
-
- WM_operatortype_append(ANIM_OT_keying_set_add);
- WM_operatortype_append(ANIM_OT_keying_set_remove);
- WM_operatortype_append(ANIM_OT_keying_set_path_add);
- WM_operatortype_append(ANIM_OT_keying_set_path_remove);
-
- WM_operatortype_append(ANIM_OT_keying_set_active_set);
+ /* Animation Editors only -------------------------- */
+ WM_operatortype_append(ANIM_OT_change_frame);
+
+ WM_operatortype_append(ANIM_OT_start_frame_set);
+ WM_operatortype_append(ANIM_OT_end_frame_set);
+
+ WM_operatortype_append(ANIM_OT_previewrange_set);
+ WM_operatortype_append(ANIM_OT_previewrange_clear);
+
+ /* Entire UI --------------------------------------- */
+ WM_operatortype_append(ANIM_OT_keyframe_insert);
+ WM_operatortype_append(ANIM_OT_keyframe_delete);
+ WM_operatortype_append(ANIM_OT_keyframe_insert_menu);
+ WM_operatortype_append(ANIM_OT_keyframe_delete_v3d);
+ WM_operatortype_append(ANIM_OT_keyframe_clear_v3d);
+ WM_operatortype_append(ANIM_OT_keyframe_insert_button);
+ WM_operatortype_append(ANIM_OT_keyframe_delete_button);
+ WM_operatortype_append(ANIM_OT_keyframe_clear_button);
+ WM_operatortype_append(ANIM_OT_keyframe_insert_by_name);
+ WM_operatortype_append(ANIM_OT_keyframe_delete_by_name);
+
+ WM_operatortype_append(ANIM_OT_driver_button_add);
+ WM_operatortype_append(ANIM_OT_driver_button_remove);
+ WM_operatortype_append(ANIM_OT_driver_button_edit);
+ WM_operatortype_append(ANIM_OT_copy_driver_button);
+ WM_operatortype_append(ANIM_OT_paste_driver_button);
+
+ WM_operatortype_append(ANIM_OT_keyingset_button_add);
+ WM_operatortype_append(ANIM_OT_keyingset_button_remove);
+
+ WM_operatortype_append(ANIM_OT_keying_set_add);
+ WM_operatortype_append(ANIM_OT_keying_set_remove);
+ WM_operatortype_append(ANIM_OT_keying_set_path_add);
+ WM_operatortype_append(ANIM_OT_keying_set_path_remove);
+
+ WM_operatortype_append(ANIM_OT_keying_set_active_set);
}
void ED_keymap_anim(wmKeyConfig *keyconf)
{
- WM_keymap_ensure(keyconf, "Animation", 0, 0);
+ WM_keymap_ensure(keyconf, "Animation", 0, 0);
}
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index d726c25816b..d6564be9574 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -21,7 +21,6 @@
* \ingroup edanimation
*/
-
#include <stdio.h>
#include <string.h>
@@ -70,212 +69,216 @@
*/
FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_index, short add)
{
- AnimData *adt;
- FCurve *fcu;
-
- /* sanity checks */
- if (ELEM(NULL, id, rna_path))
- return NULL;
-
- /* init animdata if none available yet */
- adt = BKE_animdata_from_id(id);
- if ((adt == NULL) && (add))
- adt = BKE_animdata_add_id(id);
- if (adt == NULL) {
- /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
- return NULL;
- }
-
- /* try to find f-curve matching for this setting
- * - add if not found and allowed to add one
- * TODO: add auto-grouping support? how this works will need to be resolved
- */
- fcu = list_find_fcurve(&adt->drivers, rna_path, array_index);
-
- if ((fcu == NULL) && (add)) {
- /* use default settings to make a F-Curve */
- fcu = MEM_callocN(sizeof(FCurve), "FCurve");
-
- fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
- fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
-
- /* store path - make copy, and store that */
- fcu->rna_path = BLI_strdup(rna_path);
- fcu->array_index = array_index;
-
- /* if add is negative, don't init this data yet, since it will be filled in by the pasted driver */
- if (add > 0) {
- BezTriple *bezt;
- size_t i;
-
- /* add some new driver data */
- fcu->driver = MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
-
- /* F-Modifier or Keyframes? */
- // FIXME: replace these magic numbers with defines
- if (add == 2) {
- /* Python API Backwards compatibility hack:
- * Create FModifier so that old scripts won't break
- * for now before 2.7 series -- (September 4, 2013)
- */
- add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu);
- }
- else {
- /* add 2 keyframes so that user has something to work with
- * - These are configured to 0,0 and 1,1 to give a 1-1 mapping
- * which can be easily tweaked from there.
- */
- insert_vert_fcurve(fcu, 0.0f, 0.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
- insert_vert_fcurve(fcu, 1.0f, 1.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
-
- /* configure this curve to extrapolate */
- for (i = 0, bezt = fcu->bezt; (i < fcu->totvert) && bezt; i++, bezt++) {
- bezt->h1 = bezt->h2 = HD_VECT;
- }
-
- fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
- calchandles_fcurve(fcu);
- }
- }
-
- /* just add F-Curve to end of driver list */
- BLI_addtail(&adt->drivers, fcu);
- }
-
- /* return the F-Curve */
- return fcu;
+ AnimData *adt;
+ FCurve *fcu;
+
+ /* sanity checks */
+ if (ELEM(NULL, id, rna_path))
+ return NULL;
+
+ /* init animdata if none available yet */
+ adt = BKE_animdata_from_id(id);
+ if ((adt == NULL) && (add))
+ adt = BKE_animdata_add_id(id);
+ if (adt == NULL) {
+ /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
+ return NULL;
+ }
+
+ /* try to find f-curve matching for this setting
+ * - add if not found and allowed to add one
+ * TODO: add auto-grouping support? how this works will need to be resolved
+ */
+ fcu = list_find_fcurve(&adt->drivers, rna_path, array_index);
+
+ if ((fcu == NULL) && (add)) {
+ /* use default settings to make a F-Curve */
+ fcu = MEM_callocN(sizeof(FCurve), "FCurve");
+
+ fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
+ fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
+
+ /* store path - make copy, and store that */
+ fcu->rna_path = BLI_strdup(rna_path);
+ fcu->array_index = array_index;
+
+ /* if add is negative, don't init this data yet, since it will be filled in by the pasted driver */
+ if (add > 0) {
+ BezTriple *bezt;
+ size_t i;
+
+ /* add some new driver data */
+ fcu->driver = MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
+
+ /* F-Modifier or Keyframes? */
+ // FIXME: replace these magic numbers with defines
+ if (add == 2) {
+ /* Python API Backwards compatibility hack:
+ * Create FModifier so that old scripts won't break
+ * for now before 2.7 series -- (September 4, 2013)
+ */
+ add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu);
+ }
+ else {
+ /* add 2 keyframes so that user has something to work with
+ * - These are configured to 0,0 and 1,1 to give a 1-1 mapping
+ * which can be easily tweaked from there.
+ */
+ insert_vert_fcurve(fcu, 0.0f, 0.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
+ insert_vert_fcurve(fcu, 1.0f, 1.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
+
+ /* configure this curve to extrapolate */
+ for (i = 0, bezt = fcu->bezt; (i < fcu->totvert) && bezt; i++, bezt++) {
+ bezt->h1 = bezt->h2 = HD_VECT;
+ }
+
+ fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
+ calchandles_fcurve(fcu);
+ }
+ }
+
+ /* just add F-Curve to end of driver list */
+ BLI_addtail(&adt->drivers, fcu);
+ }
+
+ /* return the F-Curve */
+ return fcu;
}
/* ************************************************** */
/* Driver Management API */
/* Helper for ANIM_add_driver_with_target - Adds the actual driver */
-static int add_driver_with_target(
- ReportList *UNUSED(reports),
- ID *dst_id, const char dst_path[], int dst_index,
- ID *src_id, const char src_path[], int src_index,
- PointerRNA *dst_ptr, PropertyRNA *dst_prop,
- PointerRNA *src_ptr, PropertyRNA *src_prop,
- short flag, int driver_type)
+static int add_driver_with_target(ReportList *UNUSED(reports),
+ ID *dst_id,
+ const char dst_path[],
+ int dst_index,
+ ID *src_id,
+ const char src_path[],
+ int src_index,
+ PointerRNA *dst_ptr,
+ PropertyRNA *dst_prop,
+ PointerRNA *src_ptr,
+ PropertyRNA *src_prop,
+ short flag,
+ int driver_type)
{
- FCurve *fcu;
- short add_mode = (flag & CREATEDRIVER_WITH_FMODIFIER) ? 2 : 1;
- const char *prop_name = RNA_property_identifier(src_prop);
-
- /* Create F-Curve with Driver */
- fcu = verify_driver_fcurve(dst_id, dst_path, dst_index, add_mode);
-
- if (fcu && fcu->driver) {
- ChannelDriver *driver = fcu->driver;
- DriverVar *dvar;
-
- /* Set the type of the driver */
- driver->type = driver_type;
-
- /* Set driver expression, so that the driver works out of the box
- *
- * The following checks define a bit of "autodetection magic" we use
- * to ensure that the drivers will behave as expected out of the box
- * when faced with properties with different units.
- */
- /* XXX: if we have N-1 mapping, should we include all those in the expression? */
- if ((RNA_property_unit(dst_prop) == PROP_UNIT_ROTATION) &&
- (RNA_property_unit(src_prop) != PROP_UNIT_ROTATION))
- {
- /* Rotation Destination: normal -> radians, so convert src to radians
- * (However, if both input and output is a rotation, don't apply such corrections)
- */
- BLI_strncpy(driver->expression, "radians(var)", sizeof(driver->expression));
- }
- else if ((RNA_property_unit(src_prop) == PROP_UNIT_ROTATION) &&
- (RNA_property_unit(dst_prop) != PROP_UNIT_ROTATION))
- {
- /* Rotation Source: radians -> normal, so convert src to degrees
- * (However, if both input and output is a rotation, don't apply such corrections)
- */
- BLI_strncpy(driver->expression, "degrees(var)", sizeof(driver->expression));
- }
- else {
- /* Just a normal property without any unit problems */
- BLI_strncpy(driver->expression, "var", sizeof(driver->expression));
- }
-
- /* Create a driver variable for the target
- * - For transform properties, we want to automatically use "transform channel" instead
- * (The only issue is with quat rotations vs euler channels...)
- * - To avoid problems with transform properties depending on the final transform that they
- * control (thus creating pseudo-cycles - see T48734), we don't use transform channels
- * when both the source and destinations are in same places.
- */
- dvar = driver_add_new_variable(driver);
-
- if (ELEM(src_ptr->type, &RNA_Object, &RNA_PoseBone) &&
- (STREQ(prop_name, "location") || STREQ(prop_name, "scale") || STRPREFIX(prop_name, "rotation_")) &&
- (src_ptr->data != dst_ptr->data))
- {
- /* Transform Channel */
- DriverTarget *dtar;
-
- driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN);
- dtar = &dvar->targets[0];
-
- /* Bone or Object target? */
- dtar->id = src_id;
- dtar->idtype = GS(src_id->name);
-
- if (src_ptr->type == &RNA_PoseBone) {
- RNA_string_get(src_ptr, "name", dtar->pchan_name);
- }
-
- /* Transform channel depends on type */
- if (STREQ(prop_name, "location")) {
- if (src_index == 2)
- dtar->transChan = DTAR_TRANSCHAN_LOCZ;
- else if (src_index == 1)
- dtar->transChan = DTAR_TRANSCHAN_LOCY;
- else
- dtar->transChan = DTAR_TRANSCHAN_LOCX;
- }
- else if (STREQ(prop_name, "scale")) {
- if (src_index == 2)
- dtar->transChan = DTAR_TRANSCHAN_SCALEZ;
- else if (src_index == 1)
- dtar->transChan = DTAR_TRANSCHAN_SCALEY;
- else
- dtar->transChan = DTAR_TRANSCHAN_SCALEX;
- }
- else {
- /* XXX: With quaternions and axis-angle, this mapping might not be correct...
- * But since those have 4 elements instead, there's not much we can do
- */
- if (src_index == 2)
- dtar->transChan = DTAR_TRANSCHAN_ROTZ;
- else if (src_index == 1)
- dtar->transChan = DTAR_TRANSCHAN_ROTY;
- else
- dtar->transChan = DTAR_TRANSCHAN_ROTX;
- }
- }
- else {
- /* Single RNA Property */
- DriverTarget *dtar = &dvar->targets[0];
-
- /* ID is as-is */
- dtar->id = src_id;
- dtar->idtype = GS(src_id->name);
-
- /* Need to make a copy of the path (or build one with array index built in) */
- if (RNA_property_array_check(src_prop)) {
- dtar->rna_path = BLI_sprintfN("%s[%d]", src_path, src_index);
- }
- else {
- dtar->rna_path = BLI_strdup(src_path);
- }
- }
- }
-
- /* set the done status */
- return (fcu != NULL);
+ FCurve *fcu;
+ short add_mode = (flag & CREATEDRIVER_WITH_FMODIFIER) ? 2 : 1;
+ const char *prop_name = RNA_property_identifier(src_prop);
+
+ /* Create F-Curve with Driver */
+ fcu = verify_driver_fcurve(dst_id, dst_path, dst_index, add_mode);
+
+ if (fcu && fcu->driver) {
+ ChannelDriver *driver = fcu->driver;
+ DriverVar *dvar;
+
+ /* Set the type of the driver */
+ driver->type = driver_type;
+
+ /* Set driver expression, so that the driver works out of the box
+ *
+ * The following checks define a bit of "autodetection magic" we use
+ * to ensure that the drivers will behave as expected out of the box
+ * when faced with properties with different units.
+ */
+ /* XXX: if we have N-1 mapping, should we include all those in the expression? */
+ if ((RNA_property_unit(dst_prop) == PROP_UNIT_ROTATION) &&
+ (RNA_property_unit(src_prop) != PROP_UNIT_ROTATION)) {
+ /* Rotation Destination: normal -> radians, so convert src to radians
+ * (However, if both input and output is a rotation, don't apply such corrections)
+ */
+ BLI_strncpy(driver->expression, "radians(var)", sizeof(driver->expression));
+ }
+ else if ((RNA_property_unit(src_prop) == PROP_UNIT_ROTATION) &&
+ (RNA_property_unit(dst_prop) != PROP_UNIT_ROTATION)) {
+ /* Rotation Source: radians -> normal, so convert src to degrees
+ * (However, if both input and output is a rotation, don't apply such corrections)
+ */
+ BLI_strncpy(driver->expression, "degrees(var)", sizeof(driver->expression));
+ }
+ else {
+ /* Just a normal property without any unit problems */
+ BLI_strncpy(driver->expression, "var", sizeof(driver->expression));
+ }
+
+ /* Create a driver variable for the target
+ * - For transform properties, we want to automatically use "transform channel" instead
+ * (The only issue is with quat rotations vs euler channels...)
+ * - To avoid problems with transform properties depending on the final transform that they
+ * control (thus creating pseudo-cycles - see T48734), we don't use transform channels
+ * when both the source and destinations are in same places.
+ */
+ dvar = driver_add_new_variable(driver);
+
+ if (ELEM(src_ptr->type, &RNA_Object, &RNA_PoseBone) &&
+ (STREQ(prop_name, "location") || STREQ(prop_name, "scale") ||
+ STRPREFIX(prop_name, "rotation_")) &&
+ (src_ptr->data != dst_ptr->data)) {
+ /* Transform Channel */
+ DriverTarget *dtar;
+
+ driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN);
+ dtar = &dvar->targets[0];
+
+ /* Bone or Object target? */
+ dtar->id = src_id;
+ dtar->idtype = GS(src_id->name);
+
+ if (src_ptr->type == &RNA_PoseBone) {
+ RNA_string_get(src_ptr, "name", dtar->pchan_name);
+ }
+
+ /* Transform channel depends on type */
+ if (STREQ(prop_name, "location")) {
+ if (src_index == 2)
+ dtar->transChan = DTAR_TRANSCHAN_LOCZ;
+ else if (src_index == 1)
+ dtar->transChan = DTAR_TRANSCHAN_LOCY;
+ else
+ dtar->transChan = DTAR_TRANSCHAN_LOCX;
+ }
+ else if (STREQ(prop_name, "scale")) {
+ if (src_index == 2)
+ dtar->transChan = DTAR_TRANSCHAN_SCALEZ;
+ else if (src_index == 1)
+ dtar->transChan = DTAR_TRANSCHAN_SCALEY;
+ else
+ dtar->transChan = DTAR_TRANSCHAN_SCALEX;
+ }
+ else {
+ /* XXX: With quaternions and axis-angle, this mapping might not be correct...
+ * But since those have 4 elements instead, there's not much we can do
+ */
+ if (src_index == 2)
+ dtar->transChan = DTAR_TRANSCHAN_ROTZ;
+ else if (src_index == 1)
+ dtar->transChan = DTAR_TRANSCHAN_ROTY;
+ else
+ dtar->transChan = DTAR_TRANSCHAN_ROTX;
+ }
+ }
+ else {
+ /* Single RNA Property */
+ DriverTarget *dtar = &dvar->targets[0];
+
+ /* ID is as-is */
+ dtar->id = src_id;
+ dtar->idtype = GS(src_id->name);
+
+ /* Need to make a copy of the path (or build one with array index built in) */
+ if (RNA_property_array_check(src_prop)) {
+ dtar->rna_path = BLI_sprintfN("%s[%d]", src_path, src_index);
+ }
+ else {
+ dtar->rna_path = BLI_strdup(src_path);
+ }
+ }
+ }
+
+ /* set the done status */
+ return (fcu != NULL);
}
/* Main Driver Management API calls:
@@ -289,75 +292,118 @@ static int add_driver_with_target(
* - driver_type: eDriver_Types
* - mapping_type: eCreateDriver_MappingTypes
*/
-int ANIM_add_driver_with_target(
- ReportList *reports,
- ID *dst_id, const char dst_path[], int dst_index,
- ID *src_id, const char src_path[], int src_index,
- short flag, int driver_type, short mapping_type)
+int ANIM_add_driver_with_target(ReportList *reports,
+ ID *dst_id,
+ const char dst_path[],
+ int dst_index,
+ ID *src_id,
+ const char src_path[],
+ int src_index,
+ short flag,
+ int driver_type,
+ short mapping_type)
{
- PointerRNA id_ptr, ptr;
- PropertyRNA *prop;
-
- PointerRNA id_ptr2, ptr2;
- PropertyRNA *prop2;
- int done_tot = 0;
-
- /* validate pointers first - exit if failure */
- RNA_id_pointer_create(dst_id, &id_ptr);
- if (RNA_path_resolve_property(&id_ptr, dst_path, &ptr, &prop) == false) {
- BKE_reportf(reports, RPT_ERROR,
- "Could not add driver, as RNA path is invalid for the given ID (ID = %s, path = %s)",
- dst_id->name, dst_path);
- return 0;
- }
-
- RNA_id_pointer_create(src_id, &id_ptr2);
- if ((RNA_path_resolve_property(&id_ptr2, src_path, &ptr2, &prop2) == false) ||
- (mapping_type == CREATEDRIVER_MAPPING_NONE))
- {
- /* No target - So, fall back to default method for adding a "simple" driver normally */
- return ANIM_add_driver(reports, dst_id, dst_path, dst_index, flag | CREATEDRIVER_WITH_DEFAULT_DVAR, driver_type);
- }
-
- /* handle curve-property mappings based on mapping_type */
- switch (mapping_type) {
- case CREATEDRIVER_MAPPING_N_N: /* N-N - Try to match as much as possible,
- * then use the first one */
- {
- /* Use the shorter of the two (to avoid out of bounds access) */
- int dst_len = (RNA_property_array_check(prop)) ? RNA_property_array_length(&ptr, prop) : 1;
- int src_len = (RNA_property_array_check(prop)) ? RNA_property_array_length(&ptr2, prop2) : 1;
-
- int len = MIN2(dst_len, src_len);
- int i;
-
- for (i = 0; i < len; i++) {
- done_tot += add_driver_with_target(reports, dst_id, dst_path, i, src_id, src_path, i, &ptr, prop, &ptr2, prop2, flag, driver_type);
- }
- break;
- }
-
- case CREATEDRIVER_MAPPING_1_N: /* 1-N - Specified target index for all */
- default:
- {
- int len = (RNA_property_array_check(prop)) ? RNA_property_array_length(&ptr, prop) : 1;
- int i;
-
- for (i = 0; i < len; i++) {
- done_tot += add_driver_with_target(reports, dst_id, dst_path, i, src_id, src_path, src_index, &ptr, prop, &ptr2, prop2, flag, driver_type);
- }
- break;
- }
-
- case CREATEDRIVER_MAPPING_1_1: /* 1-1 - Use the specified index (unless -1) */
- {
- done_tot = add_driver_with_target(reports, dst_id, dst_path, dst_index, src_id, src_path, src_index, &ptr, prop, &ptr2, prop2, flag, driver_type);
- break;
- }
- }
-
- /* done */
- return done_tot;
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+
+ PointerRNA id_ptr2, ptr2;
+ PropertyRNA *prop2;
+ int done_tot = 0;
+
+ /* validate pointers first - exit if failure */
+ RNA_id_pointer_create(dst_id, &id_ptr);
+ if (RNA_path_resolve_property(&id_ptr, dst_path, &ptr, &prop) == false) {
+ BKE_reportf(
+ reports,
+ RPT_ERROR,
+ "Could not add driver, as RNA path is invalid for the given ID (ID = %s, path = %s)",
+ dst_id->name,
+ dst_path);
+ return 0;
+ }
+
+ RNA_id_pointer_create(src_id, &id_ptr2);
+ if ((RNA_path_resolve_property(&id_ptr2, src_path, &ptr2, &prop2) == false) ||
+ (mapping_type == CREATEDRIVER_MAPPING_NONE)) {
+ /* No target - So, fall back to default method for adding a "simple" driver normally */
+ return ANIM_add_driver(
+ reports, dst_id, dst_path, dst_index, flag | CREATEDRIVER_WITH_DEFAULT_DVAR, driver_type);
+ }
+
+ /* handle curve-property mappings based on mapping_type */
+ switch (mapping_type) {
+ case CREATEDRIVER_MAPPING_N_N: /* N-N - Try to match as much as possible,
+ * then use the first one */
+ {
+ /* Use the shorter of the two (to avoid out of bounds access) */
+ int dst_len = (RNA_property_array_check(prop)) ? RNA_property_array_length(&ptr, prop) : 1;
+ int src_len = (RNA_property_array_check(prop)) ? RNA_property_array_length(&ptr2, prop2) : 1;
+
+ int len = MIN2(dst_len, src_len);
+ int i;
+
+ for (i = 0; i < len; i++) {
+ done_tot += add_driver_with_target(reports,
+ dst_id,
+ dst_path,
+ i,
+ src_id,
+ src_path,
+ i,
+ &ptr,
+ prop,
+ &ptr2,
+ prop2,
+ flag,
+ driver_type);
+ }
+ break;
+ }
+
+ case CREATEDRIVER_MAPPING_1_N: /* 1-N - Specified target index for all */
+ default: {
+ int len = (RNA_property_array_check(prop)) ? RNA_property_array_length(&ptr, prop) : 1;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ done_tot += add_driver_with_target(reports,
+ dst_id,
+ dst_path,
+ i,
+ src_id,
+ src_path,
+ src_index,
+ &ptr,
+ prop,
+ &ptr2,
+ prop2,
+ flag,
+ driver_type);
+ }
+ break;
+ }
+
+ case CREATEDRIVER_MAPPING_1_1: /* 1-1 - Use the specified index (unless -1) */
+ {
+ done_tot = add_driver_with_target(reports,
+ dst_id,
+ dst_path,
+ dst_index,
+ src_id,
+ src_path,
+ src_index,
+ &ptr,
+ prop,
+ &ptr2,
+ prop2,
+ flag,
+ driver_type);
+ break;
+ }
+ }
+
+ /* done */
+ return done_tot;
}
/* --------------------------------- */
@@ -365,155 +411,169 @@ int ANIM_add_driver_with_target(
/* Main Driver Management API calls:
* Add a new driver for the specified property on the given ID block
*/
-int ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short flag, int type)
+int ANIM_add_driver(
+ ReportList *reports, ID *id, const char rna_path[], int array_index, short flag, int type)
{
- PointerRNA id_ptr, ptr;
- PropertyRNA *prop;
- FCurve *fcu;
- int array_index_max;
- int done_tot = 0;
-
- /* validate pointer first - exit if failure */
- RNA_id_pointer_create(id, &id_ptr);
- if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
- BKE_reportf(reports, RPT_ERROR,
- "Could not add driver, as RNA path is invalid for the given ID (ID = %s, path = %s)",
- id->name, rna_path);
- return 0;
- }
-
- /* key entire array convenience method */
- if (array_index == -1) {
- array_index_max = RNA_property_array_length(&ptr, prop);
- array_index = 0;
- }
- else
- array_index_max = array_index;
-
- /* maximum index should be greater than the start index */
- if (array_index == array_index_max)
- array_index_max += 1;
-
- /* will only loop once unless the array index was -1 */
- for (; array_index < array_index_max; array_index++) {
- short add_mode = (flag & CREATEDRIVER_WITH_FMODIFIER) ? 2 : 1;
-
- /* create F-Curve with Driver */
- fcu = verify_driver_fcurve(id, rna_path, array_index, add_mode);
-
- if (fcu && fcu->driver) {
- ChannelDriver *driver = fcu->driver;
-
- /* set the type of the driver */
- driver->type = type;
-
- /* Creating drivers for buttons will create the driver(s) with type
- * "scripted expression" so that their values won't be lost immediately,
- * so here we copy those values over to the driver's expression
- *
- * If the "default dvar" option (for easier UI setup of drivers) is provided,
- * include "var" in the expressions too, so that the user doesn't have to edit
- * it to get something to happen. It should be fine to just add it to the default
- * value, so that we get both in the expression, even if it's a bit more confusing
- * that way...
- */
- if (type == DRIVER_TYPE_PYTHON) {
- PropertyType proptype = RNA_property_type(prop);
- int array = RNA_property_array_length(&ptr, prop);
- const char *dvar_prefix = (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) ? "var + " : "";
- char *expression = driver->expression;
- int val, maxlen = sizeof(driver->expression);
- float fval;
-
- if (proptype == PROP_BOOLEAN) {
- if (!array) val = RNA_property_boolean_get(&ptr, prop);
- else val = RNA_property_boolean_get_index(&ptr, prop, array_index);
-
- BLI_snprintf(expression, maxlen, "%s%s", dvar_prefix, (val) ? "True" : "False");
- }
- else if (proptype == PROP_INT) {
- if (!array) val = RNA_property_int_get(&ptr, prop);
- else val = RNA_property_int_get_index(&ptr, prop, array_index);
-
- BLI_snprintf(expression, maxlen, "%s%d", dvar_prefix, val);
- }
- else if (proptype == PROP_FLOAT) {
- if (!array) fval = RNA_property_float_get(&ptr, prop);
- else fval = RNA_property_float_get_index(&ptr, prop, array_index);
-
- BLI_snprintf(expression, maxlen, "%s%.3f", dvar_prefix, fval);
- BLI_str_rstrip_float_zero(expression, '\0');
- }
- else if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) {
- BLI_strncpy(expression, "var", maxlen);
- }
- }
-
- /* for easier setup of drivers from UI, a driver variable should be
- * added if flag is set (UI calls only)
- */
- if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) {
- /* assume that users will mostly want this to be of type "Transform Channel" too,
- * since this allows the easiest setting up of common rig components
- */
- DriverVar *dvar = driver_add_new_variable(driver);
- driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN);
- }
- }
-
- /* set the done status */
- done_tot += (fcu != NULL);
- }
-
- /* done */
- return done_tot;
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ FCurve *fcu;
+ int array_index_max;
+ int done_tot = 0;
+
+ /* validate pointer first - exit if failure */
+ RNA_id_pointer_create(id, &id_ptr);
+ if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
+ BKE_reportf(
+ reports,
+ RPT_ERROR,
+ "Could not add driver, as RNA path is invalid for the given ID (ID = %s, path = %s)",
+ id->name,
+ rna_path);
+ return 0;
+ }
+
+ /* key entire array convenience method */
+ if (array_index == -1) {
+ array_index_max = RNA_property_array_length(&ptr, prop);
+ array_index = 0;
+ }
+ else
+ array_index_max = array_index;
+
+ /* maximum index should be greater than the start index */
+ if (array_index == array_index_max)
+ array_index_max += 1;
+
+ /* will only loop once unless the array index was -1 */
+ for (; array_index < array_index_max; array_index++) {
+ short add_mode = (flag & CREATEDRIVER_WITH_FMODIFIER) ? 2 : 1;
+
+ /* create F-Curve with Driver */
+ fcu = verify_driver_fcurve(id, rna_path, array_index, add_mode);
+
+ if (fcu && fcu->driver) {
+ ChannelDriver *driver = fcu->driver;
+
+ /* set the type of the driver */
+ driver->type = type;
+
+ /* Creating drivers for buttons will create the driver(s) with type
+ * "scripted expression" so that their values won't be lost immediately,
+ * so here we copy those values over to the driver's expression
+ *
+ * If the "default dvar" option (for easier UI setup of drivers) is provided,
+ * include "var" in the expressions too, so that the user doesn't have to edit
+ * it to get something to happen. It should be fine to just add it to the default
+ * value, so that we get both in the expression, even if it's a bit more confusing
+ * that way...
+ */
+ if (type == DRIVER_TYPE_PYTHON) {
+ PropertyType proptype = RNA_property_type(prop);
+ int array = RNA_property_array_length(&ptr, prop);
+ const char *dvar_prefix = (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) ? "var + " : "";
+ char *expression = driver->expression;
+ int val, maxlen = sizeof(driver->expression);
+ float fval;
+
+ if (proptype == PROP_BOOLEAN) {
+ if (!array)
+ val = RNA_property_boolean_get(&ptr, prop);
+ else
+ val = RNA_property_boolean_get_index(&ptr, prop, array_index);
+
+ BLI_snprintf(expression, maxlen, "%s%s", dvar_prefix, (val) ? "True" : "False");
+ }
+ else if (proptype == PROP_INT) {
+ if (!array)
+ val = RNA_property_int_get(&ptr, prop);
+ else
+ val = RNA_property_int_get_index(&ptr, prop, array_index);
+
+ BLI_snprintf(expression, maxlen, "%s%d", dvar_prefix, val);
+ }
+ else if (proptype == PROP_FLOAT) {
+ if (!array)
+ fval = RNA_property_float_get(&ptr, prop);
+ else
+ fval = RNA_property_float_get_index(&ptr, prop, array_index);
+
+ BLI_snprintf(expression, maxlen, "%s%.3f", dvar_prefix, fval);
+ BLI_str_rstrip_float_zero(expression, '\0');
+ }
+ else if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) {
+ BLI_strncpy(expression, "var", maxlen);
+ }
+ }
+
+ /* for easier setup of drivers from UI, a driver variable should be
+ * added if flag is set (UI calls only)
+ */
+ if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) {
+ /* assume that users will mostly want this to be of type "Transform Channel" too,
+ * since this allows the easiest setting up of common rig components
+ */
+ DriverVar *dvar = driver_add_new_variable(driver);
+ driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN);
+ }
+ }
+
+ /* set the done status */
+ done_tot += (fcu != NULL);
+ }
+
+ /* done */
+ return done_tot;
}
/* Main Driver Management API calls:
* Remove the driver for the specified property on the given ID block (if available)
*/
-bool ANIM_remove_driver(ReportList *UNUSED(reports), ID *id, const char rna_path[], int array_index, short UNUSED(flag))
+bool ANIM_remove_driver(ReportList *UNUSED(reports),
+ ID *id,
+ const char rna_path[],
+ int array_index,
+ short UNUSED(flag))
{
- AnimData *adt;
- FCurve *fcu;
- bool success = false;
-
- /* we don't check the validity of the path here yet, but it should be ok... */
- adt = BKE_animdata_from_id(id);
-
- if (adt) {
- if (array_index == -1) {
- /* step through all drivers, removing all of those with the same base path */
- FCurve *fcu_iter = adt->drivers.first;
-
- while ((fcu = iter_step_fcurve(fcu_iter, rna_path)) != NULL) {
- /* store the next fcurve for looping */
- fcu_iter = fcu->next;
-
- /* remove F-Curve from driver stack, then free it */
- BLI_remlink(&adt->drivers, fcu);
- free_fcurve(fcu);
-
- /* done successfully */
- success = true;
- }
- }
- else {
- /* find the matching driver and remove it only
- * Note: here is one of the places where we don't want new F-Curve + Driver added!
- * so 'add' var must be 0
- */
- fcu = verify_driver_fcurve(id, rna_path, array_index, 0);
- if (fcu) {
- BLI_remlink(&adt->drivers, fcu);
- free_fcurve(fcu);
-
- success = true;
- }
- }
- }
-
- return success;
+ AnimData *adt;
+ FCurve *fcu;
+ bool success = false;
+
+ /* we don't check the validity of the path here yet, but it should be ok... */
+ adt = BKE_animdata_from_id(id);
+
+ if (adt) {
+ if (array_index == -1) {
+ /* step through all drivers, removing all of those with the same base path */
+ FCurve *fcu_iter = adt->drivers.first;
+
+ while ((fcu = iter_step_fcurve(fcu_iter, rna_path)) != NULL) {
+ /* store the next fcurve for looping */
+ fcu_iter = fcu->next;
+
+ /* remove F-Curve from driver stack, then free it */
+ BLI_remlink(&adt->drivers, fcu);
+ free_fcurve(fcu);
+
+ /* done successfully */
+ success = true;
+ }
+ }
+ else {
+ /* find the matching driver and remove it only
+ * Note: here is one of the places where we don't want new F-Curve + Driver added!
+ * so 'add' var must be 0
+ */
+ fcu = verify_driver_fcurve(id, rna_path, array_index, 0);
+ if (fcu) {
+ BLI_remlink(&adt->drivers, fcu);
+ free_fcurve(fcu);
+
+ success = true;
+ }
+ }
+ }
+
+ return success;
}
/* ************************************************** */
@@ -525,16 +585,16 @@ static FCurve *channeldriver_copypaste_buf = NULL;
/* This function frees any MEM_calloc'ed copy/paste buffer data */
void ANIM_drivers_copybuf_free(void)
{
- /* free the buffer F-Curve if it exists, as if it were just another F-Curve */
- if (channeldriver_copypaste_buf)
- free_fcurve(channeldriver_copypaste_buf);
- channeldriver_copypaste_buf = NULL;
+ /* free the buffer F-Curve if it exists, as if it were just another F-Curve */
+ if (channeldriver_copypaste_buf)
+ free_fcurve(channeldriver_copypaste_buf);
+ channeldriver_copypaste_buf = NULL;
}
/* Checks if there is a driver in the copy/paste buffer */
bool ANIM_driver_can_paste(void)
{
- return (channeldriver_copypaste_buf != NULL);
+ return (channeldriver_copypaste_buf != NULL);
}
/* ------------------- */
@@ -542,98 +602,106 @@ bool ANIM_driver_can_paste(void)
/* Main Driver Management API calls:
* Make a copy of the driver for the specified property on the given ID block
*/
-bool ANIM_copy_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag))
+bool ANIM_copy_driver(
+ ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag))
{
- PointerRNA id_ptr, ptr;
- PropertyRNA *prop;
- FCurve *fcu;
-
- /* validate pointer first - exit if failure */
- RNA_id_pointer_create(id, &id_ptr);
- if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
- BKE_reportf(reports, RPT_ERROR,
- "Could not find driver to copy, as RNA path is invalid for the given ID (ID = %s, path = %s)",
- id->name, rna_path);
- return 0;
- }
-
- /* try to get F-Curve with Driver */
- fcu = verify_driver_fcurve(id, rna_path, array_index, 0);
-
- /* clear copy/paste buffer first (for consistency with other copy/paste buffers) */
- ANIM_drivers_copybuf_free();
-
- /* copy this to the copy/paste buf if it exists */
- if (fcu && fcu->driver) {
- /* make copies of some info such as the rna_path, then clear this info from the F-Curve temporarily
- * so that we don't end up wasting memory storing the path which won't get used ever...
- */
- char *tmp_path = fcu->rna_path;
- fcu->rna_path = NULL;
-
- /* make a copy of the F-Curve with */
- channeldriver_copypaste_buf = copy_fcurve(fcu);
-
- /* restore the path */
- fcu->rna_path = tmp_path;
-
- /* copied... */
- return 1;
- }
-
- /* done */
- return 0;
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ FCurve *fcu;
+
+ /* validate pointer first - exit if failure */
+ RNA_id_pointer_create(id, &id_ptr);
+ if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Could not find driver to copy, as RNA path is invalid for the given ID (ID = %s, "
+ "path = %s)",
+ id->name,
+ rna_path);
+ return 0;
+ }
+
+ /* try to get F-Curve with Driver */
+ fcu = verify_driver_fcurve(id, rna_path, array_index, 0);
+
+ /* clear copy/paste buffer first (for consistency with other copy/paste buffers) */
+ ANIM_drivers_copybuf_free();
+
+ /* copy this to the copy/paste buf if it exists */
+ if (fcu && fcu->driver) {
+ /* make copies of some info such as the rna_path, then clear this info from the F-Curve temporarily
+ * so that we don't end up wasting memory storing the path which won't get used ever...
+ */
+ char *tmp_path = fcu->rna_path;
+ fcu->rna_path = NULL;
+
+ /* make a copy of the F-Curve with */
+ channeldriver_copypaste_buf = copy_fcurve(fcu);
+
+ /* restore the path */
+ fcu->rna_path = tmp_path;
+
+ /* copied... */
+ return 1;
+ }
+
+ /* done */
+ return 0;
}
/* Main Driver Management API calls:
* Add a new driver for the specified property on the given ID block or replace an existing one
* with the driver + driver-curve data from the buffer
*/
-bool ANIM_paste_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag))
+bool ANIM_paste_driver(
+ ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag))
{
- PointerRNA id_ptr, ptr;
- PropertyRNA *prop;
- FCurve *fcu;
-
- /* validate pointer first - exit if failure */
- RNA_id_pointer_create(id, &id_ptr);
- if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
- BKE_reportf(reports, RPT_ERROR,
- "Could not paste driver, as RNA path is invalid for the given ID (ID = %s, path = %s)",
- id->name, rna_path);
- return 0;
- }
-
- /* if the buffer is empty, cannot paste... */
- if (channeldriver_copypaste_buf == NULL) {
- BKE_report(reports, RPT_ERROR, "Paste driver: no driver to paste");
- return 0;
- }
-
- /* create Driver F-Curve, but without data which will be copied across... */
- fcu = verify_driver_fcurve(id, rna_path, array_index, -1);
-
- if (fcu) {
- /* copy across the curve data from the buffer curve
- * NOTE: this step needs care to not miss new settings
- */
- /* keyframes/samples */
- fcu->bezt = MEM_dupallocN(channeldriver_copypaste_buf->bezt);
- fcu->fpt = MEM_dupallocN(channeldriver_copypaste_buf->fpt);
- fcu->totvert = channeldriver_copypaste_buf->totvert;
-
- /* modifiers */
- copy_fmodifiers(&fcu->modifiers, &channeldriver_copypaste_buf->modifiers);
-
- /* extrapolation mode */
- fcu->extend = channeldriver_copypaste_buf->extend;
-
- /* the 'juicy' stuff - the driver */
- fcu->driver = fcurve_copy_driver(channeldriver_copypaste_buf->driver);
- }
-
- /* done */
- return (fcu != NULL);
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ FCurve *fcu;
+
+ /* validate pointer first - exit if failure */
+ RNA_id_pointer_create(id, &id_ptr);
+ if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
+ BKE_reportf(
+ reports,
+ RPT_ERROR,
+ "Could not paste driver, as RNA path is invalid for the given ID (ID = %s, path = %s)",
+ id->name,
+ rna_path);
+ return 0;
+ }
+
+ /* if the buffer is empty, cannot paste... */
+ if (channeldriver_copypaste_buf == NULL) {
+ BKE_report(reports, RPT_ERROR, "Paste driver: no driver to paste");
+ return 0;
+ }
+
+ /* create Driver F-Curve, but without data which will be copied across... */
+ fcu = verify_driver_fcurve(id, rna_path, array_index, -1);
+
+ if (fcu) {
+ /* copy across the curve data from the buffer curve
+ * NOTE: this step needs care to not miss new settings
+ */
+ /* keyframes/samples */
+ fcu->bezt = MEM_dupallocN(channeldriver_copypaste_buf->bezt);
+ fcu->fpt = MEM_dupallocN(channeldriver_copypaste_buf->fpt);
+ fcu->totvert = channeldriver_copypaste_buf->totvert;
+
+ /* modifiers */
+ copy_fmodifiers(&fcu->modifiers, &channeldriver_copypaste_buf->modifiers);
+
+ /* extrapolation mode */
+ fcu->extend = channeldriver_copypaste_buf->extend;
+
+ /* the 'juicy' stuff - the driver */
+ fcu->driver = fcurve_copy_driver(channeldriver_copypaste_buf->driver);
+ }
+
+ /* done */
+ return (fcu != NULL);
}
/* ************************************************** */
@@ -645,24 +713,24 @@ static ListBase driver_vars_copybuf = {NULL, NULL};
/* This function frees any MEM_calloc'ed copy/paste buffer data */
void ANIM_driver_vars_copybuf_free(void)
{
- /* Free the driver variables kept in the buffer */
- if (driver_vars_copybuf.first) {
- DriverVar *dvar, *dvarn;
-
- /* Free variables (and any data they use) */
- for (dvar = driver_vars_copybuf.first; dvar; dvar = dvarn) {
- dvarn = dvar->next;
- driver_free_variable(&driver_vars_copybuf, dvar);
- }
- }
-
- BLI_listbase_clear(&driver_vars_copybuf);
+ /* Free the driver variables kept in the buffer */
+ if (driver_vars_copybuf.first) {
+ DriverVar *dvar, *dvarn;
+
+ /* Free variables (and any data they use) */
+ for (dvar = driver_vars_copybuf.first; dvar; dvar = dvarn) {
+ dvarn = dvar->next;
+ driver_free_variable(&driver_vars_copybuf, dvar);
+ }
+ }
+
+ BLI_listbase_clear(&driver_vars_copybuf);
}
/* Checks if there are driver variables in the copy/paste buffer */
bool ANIM_driver_vars_can_paste(void)
{
- return (BLI_listbase_is_empty(&driver_vars_copybuf) == false);
+ return (BLI_listbase_is_empty(&driver_vars_copybuf) == false);
}
/* -------------------------------------------------- */
@@ -670,78 +738,78 @@ bool ANIM_driver_vars_can_paste(void)
/* Copy the given driver's variables to the buffer */
bool ANIM_driver_vars_copy(ReportList *reports, FCurve *fcu)
{
- /* sanity checks */
- if (ELEM(NULL, fcu, fcu->driver)) {
- BKE_report(reports, RPT_ERROR, "No driver to copy variables from");
- return false;
- }
+ /* sanity checks */
+ if (ELEM(NULL, fcu, fcu->driver)) {
+ BKE_report(reports, RPT_ERROR, "No driver to copy variables from");
+ return false;
+ }
- if (BLI_listbase_is_empty(&fcu->driver->variables)) {
- BKE_report(reports, RPT_ERROR, "Driver has no variables to copy");
- return false;
- }
+ if (BLI_listbase_is_empty(&fcu->driver->variables)) {
+ BKE_report(reports, RPT_ERROR, "Driver has no variables to copy");
+ return false;
+ }
- /* clear buffer */
- ANIM_driver_vars_copybuf_free();
+ /* clear buffer */
+ ANIM_driver_vars_copybuf_free();
- /* copy over the variables */
- driver_variables_copy(&driver_vars_copybuf, &fcu->driver->variables);
+ /* copy over the variables */
+ driver_variables_copy(&driver_vars_copybuf, &fcu->driver->variables);
- return (BLI_listbase_is_empty(&driver_vars_copybuf) == false);
+ return (BLI_listbase_is_empty(&driver_vars_copybuf) == false);
}
/* Paste the variables in the buffer to the given FCurve */
bool ANIM_driver_vars_paste(ReportList *reports, FCurve *fcu, bool replace)
{
- ChannelDriver *driver = (fcu) ? fcu->driver : NULL;
- ListBase tmp_list = {NULL, NULL};
-
- /* sanity checks */
- if (BLI_listbase_is_empty(&driver_vars_copybuf)) {
- BKE_report(reports, RPT_ERROR, "No driver variables in clipboard to paste");
- return false;
- }
-
- if (ELEM(NULL, fcu, fcu->driver)) {
- BKE_report(reports, RPT_ERROR, "Cannot paste driver variables without a driver");
- return false;
- }
-
- /* 1) Make a new copy of the variables in the buffer - these will get pasted later... */
- driver_variables_copy(&tmp_list, &driver_vars_copybuf);
-
- /* 2) Prepare destination array */
- if (replace) {
- DriverVar *dvar, *dvarn;
-
- /* Free all existing vars first - We aren't retaining anything */
- for (dvar = driver->variables.first; dvar; dvar = dvarn) {
- dvarn = dvar->next;
- driver_free_variable_ex(driver, dvar);
- }
-
- BLI_listbase_clear(&driver->variables);
- }
-
- /* 3) Add new vars */
- if (driver->variables.last) {
- DriverVar *last = driver->variables.last;
- DriverVar *first = tmp_list.first;
-
- last->next = first;
- first->prev = last;
-
- driver->variables.last = tmp_list.last;
- }
- else {
- driver->variables.first = tmp_list.first;
- driver->variables.last = tmp_list.last;
- }
-
- /* since driver variables are cached, the expression needs re-compiling too */
- BKE_driver_invalidate_expression(driver, false, true);
-
- return true;
+ ChannelDriver *driver = (fcu) ? fcu->driver : NULL;
+ ListBase tmp_list = {NULL, NULL};
+
+ /* sanity checks */
+ if (BLI_listbase_is_empty(&driver_vars_copybuf)) {
+ BKE_report(reports, RPT_ERROR, "No driver variables in clipboard to paste");
+ return false;
+ }
+
+ if (ELEM(NULL, fcu, fcu->driver)) {
+ BKE_report(reports, RPT_ERROR, "Cannot paste driver variables without a driver");
+ return false;
+ }
+
+ /* 1) Make a new copy of the variables in the buffer - these will get pasted later... */
+ driver_variables_copy(&tmp_list, &driver_vars_copybuf);
+
+ /* 2) Prepare destination array */
+ if (replace) {
+ DriverVar *dvar, *dvarn;
+
+ /* Free all existing vars first - We aren't retaining anything */
+ for (dvar = driver->variables.first; dvar; dvar = dvarn) {
+ dvarn = dvar->next;
+ driver_free_variable_ex(driver, dvar);
+ }
+
+ BLI_listbase_clear(&driver->variables);
+ }
+
+ /* 3) Add new vars */
+ if (driver->variables.last) {
+ DriverVar *last = driver->variables.last;
+ DriverVar *first = tmp_list.first;
+
+ last->next = first;
+ first->prev = last;
+
+ driver->variables.last = tmp_list.last;
+ }
+ else {
+ driver->variables.first = tmp_list.first;
+ driver->variables.last = tmp_list.last;
+ }
+
+ /* since driver variables are cached, the expression needs re-compiling too */
+ BKE_driver_invalidate_expression(driver, false, true);
+
+ return true;
}
/* ************************************************** */
@@ -753,397 +821,421 @@ bool ANIM_driver_vars_paste(ReportList *reports, FCurve *fcu, bool replace)
/* NOTE: Used by ANIM_OT_driver_button_add and UI_OT_eyedropper_driver */
// XXX: These names need reviewing
EnumPropertyItem prop_driver_create_mapping_types[] = {
- {CREATEDRIVER_MAPPING_1_N, "SINGLE_MANY", 0, "All from Target",
- "Drive all components of this property using the target picked"},
- {CREATEDRIVER_MAPPING_1_1, "DIRECT", 0, "Single from Target",
- "Drive this component of this property using the target picked"},
-
- {CREATEDRIVER_MAPPING_N_N, "MATCH", ICON_COLOR, "Match Indices",
- "Create drivers for each pair of corresponding elements"},
-
- {CREATEDRIVER_MAPPING_NONE_ALL, "NONE_ALL", ICON_HAND, "Manually Create Later",
- "Create drivers for all properties without assigning any targets yet"},
- {CREATEDRIVER_MAPPING_NONE, "NONE_SINGLE", 0, "Manually Create Later (Single)",
- "Create driver for this property only and without assigning any targets yet"},
- {0, NULL, 0, NULL, NULL},
+ {CREATEDRIVER_MAPPING_1_N,
+ "SINGLE_MANY",
+ 0,
+ "All from Target",
+ "Drive all components of this property using the target picked"},
+ {CREATEDRIVER_MAPPING_1_1,
+ "DIRECT",
+ 0,
+ "Single from Target",
+ "Drive this component of this property using the target picked"},
+
+ {CREATEDRIVER_MAPPING_N_N,
+ "MATCH",
+ ICON_COLOR,
+ "Match Indices",
+ "Create drivers for each pair of corresponding elements"},
+
+ {CREATEDRIVER_MAPPING_NONE_ALL,
+ "NONE_ALL",
+ ICON_HAND,
+ "Manually Create Later",
+ "Create drivers for all properties without assigning any targets yet"},
+ {CREATEDRIVER_MAPPING_NONE,
+ "NONE_SINGLE",
+ 0,
+ "Manually Create Later (Single)",
+ "Create driver for this property only and without assigning any targets yet"},
+ {0, NULL, 0, NULL, NULL},
};
/* Filtering callback for driver mapping types enum */
-static const EnumPropertyItem *driver_mapping_type_itemsf(bContext *C, PointerRNA *UNUSED(owner_ptr), PropertyRNA *UNUSED(owner_prop), bool *r_free)
+static const EnumPropertyItem *driver_mapping_type_itemsf(bContext *C,
+ PointerRNA *UNUSED(owner_ptr),
+ PropertyRNA *UNUSED(owner_prop),
+ bool *r_free)
{
- EnumPropertyItem *input = prop_driver_create_mapping_types;
- EnumPropertyItem *item = NULL;
+ EnumPropertyItem *input = prop_driver_create_mapping_types;
+ EnumPropertyItem *item = NULL;
- PointerRNA ptr = {{NULL}};
- PropertyRNA *prop = NULL;
- int index;
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop = NULL;
+ int index;
- int totitem = 0;
+ int totitem = 0;
- if (!C) /* needed for docs */
- return prop_driver_create_mapping_types;
+ if (!C) /* needed for docs */
+ return prop_driver_create_mapping_types;
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
- const bool is_array = RNA_property_array_check(prop);
+ if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
+ const bool is_array = RNA_property_array_check(prop);
- while (input->identifier) {
- if (ELEM(input->value, CREATEDRIVER_MAPPING_1_1, CREATEDRIVER_MAPPING_NONE) || (is_array)) {
- RNA_enum_item_add(&item, &totitem, input);
- }
- input++;
- }
- }
- else {
- /* We need at least this one! */
- RNA_enum_items_add_value(&item, &totitem, input, CREATEDRIVER_MAPPING_NONE);
- }
+ while (input->identifier) {
+ if (ELEM(input->value, CREATEDRIVER_MAPPING_1_1, CREATEDRIVER_MAPPING_NONE) || (is_array)) {
+ RNA_enum_item_add(&item, &totitem, input);
+ }
+ input++;
+ }
+ }
+ else {
+ /* We need at least this one! */
+ RNA_enum_items_add_value(&item, &totitem, input, CREATEDRIVER_MAPPING_NONE);
+ }
- RNA_enum_item_end(&item, &totitem);
+ RNA_enum_item_end(&item, &totitem);
- *r_free = true;
- return item;
+ *r_free = true;
+ return item;
}
-
/* Add Driver (With Menu) Button Operator ------------------------ */
static bool add_driver_button_poll(bContext *C)
{
- PointerRNA ptr = {{NULL}};
- PropertyRNA *prop = NULL;
- int index;
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop = NULL;
+ int index;
- /* this operator can only run if there's a property button active, and it can be animated */
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- return (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop));
+ /* this operator can only run if there's a property button active, and it can be animated */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+ return (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop));
}
/* Wrapper for creating a driver without knowing what the targets will be yet (i.e. "manual/add later") */
static int add_driver_button_none(bContext *C, wmOperator *op, short mapping_type)
{
- PointerRNA ptr = {{NULL}};
- PropertyRNA *prop = NULL;
- int index;
- int success = 0;
-
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
-
- if (mapping_type == CREATEDRIVER_MAPPING_NONE_ALL)
- index = -1;
-
- if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
- char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
- short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
-
- if (path) {
- success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON);
- MEM_freeN(path);
- }
- }
-
- if (success) {
- /* 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 OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop = NULL;
+ int index;
+ int success = 0;
+
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ if (mapping_type == CREATEDRIVER_MAPPING_NONE_ALL)
+ index = -1;
+
+ if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
+ char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
+ short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
+
+ if (path) {
+ success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON);
+ MEM_freeN(path);
+ }
+ }
+
+ if (success) {
+ /* 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 OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static int add_driver_button_menu_exec(bContext *C, wmOperator *op)
{
- short mapping_type = RNA_enum_get(op->ptr, "mapping_type");
- if (ELEM(mapping_type, CREATEDRIVER_MAPPING_NONE, CREATEDRIVER_MAPPING_NONE_ALL)) {
- /* Just create driver with no targets */
- return add_driver_button_none(C, op, mapping_type);
- }
- else {
- /* Create Driver using Eyedropper */
- wmOperatorType *ot = WM_operatortype_find("UI_OT_eyedropper_driver", true);
-
- /* XXX: We assume that it's fine to use the same set of properties, since they're actually the same... */
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, op->ptr);
-
- return OPERATOR_FINISHED;
- }
+ short mapping_type = RNA_enum_get(op->ptr, "mapping_type");
+ if (ELEM(mapping_type, CREATEDRIVER_MAPPING_NONE, CREATEDRIVER_MAPPING_NONE_ALL)) {
+ /* Just create driver with no targets */
+ return add_driver_button_none(C, op, mapping_type);
+ }
+ else {
+ /* Create Driver using Eyedropper */
+ wmOperatorType *ot = WM_operatortype_find("UI_OT_eyedropper_driver", true);
+
+ /* XXX: We assume that it's fine to use the same set of properties, since they're actually the same... */
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, op->ptr);
+
+ return OPERATOR_FINISHED;
+ }
}
/* Show menu or create drivers */
static int add_driver_button_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- PropertyRNA *prop;
-
- if ((prop = RNA_struct_find_property(op->ptr, "mapping_type")) && RNA_property_is_set(op->ptr, prop)) {
- /* Mapping Type is Set - Directly go into creating drivers */
- return add_driver_button_menu_exec(C, op);
- }
- else {
- /* Show menu */
- // TODO: This should get filtered by the enum filter
- /* important to execute in the region we're currently in */
- return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_DEFAULT);
- }
+ PropertyRNA *prop;
+
+ if ((prop = RNA_struct_find_property(op->ptr, "mapping_type")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ /* Mapping Type is Set - Directly go into creating drivers */
+ return add_driver_button_menu_exec(C, op);
+ }
+ else {
+ /* Show menu */
+ // TODO: This should get filtered by the enum filter
+ /* important to execute in the region we're currently in */
+ return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_DEFAULT);
+ }
}
static void UNUSED_FUNCTION(ANIM_OT_driver_button_add_menu)(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Driver Menu";
- ot->idname = "ANIM_OT_driver_button_add_menu";
- ot->description = "Add driver(s) for the property(s) represented by the highlighted button";
-
- /* callbacks */
- ot->invoke = add_driver_button_menu_invoke;
- ot->exec = add_driver_button_menu_exec;
- ot->poll = add_driver_button_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "mapping_type", prop_driver_create_mapping_types, 0,
- "Mapping Type", "Method used to match target and driven properties");
- RNA_def_enum_funcs(ot->prop, driver_mapping_type_itemsf);
+ /* identifiers */
+ ot->name = "Add Driver Menu";
+ ot->idname = "ANIM_OT_driver_button_add_menu";
+ ot->description = "Add driver(s) for the property(s) represented by the highlighted button";
+
+ /* callbacks */
+ ot->invoke = add_driver_button_menu_invoke;
+ ot->exec = add_driver_button_menu_exec;
+ ot->poll = add_driver_button_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna,
+ "mapping_type",
+ prop_driver_create_mapping_types,
+ 0,
+ "Mapping Type",
+ "Method used to match target and driven properties");
+ RNA_def_enum_funcs(ot->prop, driver_mapping_type_itemsf);
}
/* Add Driver Button Operator ------------------------ */
static int add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- PointerRNA ptr = {{NULL}};
- PropertyRNA *prop = NULL;
- int index;
-
- /* try to find driver using property retrieved from UI */
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
-
- if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
- /* 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;
-
- if (path) {
- success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON);
- MEM_freeN(path);
- }
-
- if (success) {
- /* send updates */
- UI_context_update_anim_flag(C);
- DEG_id_tag_update(ptr.id.data, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(CTX_data_main(C));
- WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL);
- }
-
- /* 2) Show editing panel for setting up this driver */
- /* TODO: Use a different one from the editing popever, so we can have the single/all toggle? */
- UI_popover_panel_invoke(C, "GRAPH_PT_drivers_popover", true, op->reports);
- }
-
- return OPERATOR_INTERFACE;
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop = NULL;
+ int index;
+
+ /* try to find driver using property retrieved from UI */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
+ /* 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;
+
+ if (path) {
+ success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON);
+ MEM_freeN(path);
+ }
+
+ if (success) {
+ /* send updates */
+ UI_context_update_anim_flag(C);
+ DEG_id_tag_update(ptr.id.data, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(CTX_data_main(C));
+ WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL);
+ }
+
+ /* 2) Show editing panel for setting up this driver */
+ /* TODO: Use a different one from the editing popever, so we can have the single/all toggle? */
+ UI_popover_panel_invoke(C, "GRAPH_PT_drivers_popover", true, op->reports);
+ }
+
+ return OPERATOR_INTERFACE;
}
void ANIM_OT_driver_button_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Driver";
- ot->idname = "ANIM_OT_driver_button_add";
- ot->description = "Add driver for the property under the cursor";
-
- /* callbacks */
- /* NOTE: No exec, as we need all these to use the current context info */
- ot->invoke = add_driver_button_invoke;
- ot->poll = add_driver_button_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* identifiers */
+ ot->name = "Add Driver";
+ ot->idname = "ANIM_OT_driver_button_add";
+ ot->description = "Add driver for the property under the cursor";
+
+ /* callbacks */
+ /* NOTE: No exec, as we need all these to use the current context info */
+ ot->invoke = add_driver_button_invoke;
+ ot->poll = add_driver_button_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
}
/* Remove Driver Button Operator ------------------------ */
static int remove_driver_button_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr = {{NULL}};
- PropertyRNA *prop = NULL;
- short success = 0;
- int index;
- const bool all = RNA_boolean_get(op->ptr, "all");
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop = NULL;
+ short success = 0;
+ int index;
+ const bool all = RNA_boolean_get(op->ptr, "all");
- /* try to find driver using property retrieved from UI */
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+ /* try to find driver using property retrieved from UI */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- if (all)
- index = -1;
+ if (all)
+ index = -1;
- if (ptr.id.data && ptr.data && prop) {
- char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
+ if (ptr.id.data && ptr.data && prop) {
+ char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
- if (path) {
- success = ANIM_remove_driver(op->reports, ptr.id.data, path, index, 0);
+ if (path) {
+ success = ANIM_remove_driver(op->reports, ptr.id.data, path, index, 0);
- MEM_freeN(path);
- }
- }
+ MEM_freeN(path);
+ }
+ }
- if (success) {
- /* 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
- }
+ if (success) {
+ /* 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 (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void ANIM_OT_driver_button_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Driver";
- ot->idname = "ANIM_OT_driver_button_remove";
- ot->description = "Remove the driver(s) for the property(s) connected represented by the highlighted button";
+ /* identifiers */
+ ot->name = "Remove Driver";
+ ot->idname = "ANIM_OT_driver_button_remove";
+ ot->description =
+ "Remove the driver(s) for the property(s) connected represented by the highlighted button";
- /* callbacks */
- ot->exec = remove_driver_button_exec;
- //op->poll = ??? // TODO: need to have some driver to be able to do this...
+ /* callbacks */
+ ot->exec = remove_driver_button_exec;
+ //op->poll = ??? // TODO: need to have some driver to be able to do this...
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
- /* properties */
- RNA_def_boolean(ot->srna, "all", 1, "All", "Delete drivers for all elements of the array");
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Delete drivers for all elements of the array");
}
/* Edit Driver Button Operator ------------------------ */
static int edit_driver_button_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr = {{NULL}};
- PropertyRNA *prop = NULL;
- int index;
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop = NULL;
+ int index;
- /* try to find driver using property retrieved from UI */
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+ /* try to find driver using property retrieved from UI */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- if (ptr.id.data && ptr.data && prop) {
- UI_popover_panel_invoke(C, "GRAPH_PT_drivers_popover", true, op->reports);
- }
+ if (ptr.id.data && ptr.data && prop) {
+ UI_popover_panel_invoke(C, "GRAPH_PT_drivers_popover", true, op->reports);
+ }
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
void ANIM_OT_driver_button_edit(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Edit Driver";
- ot->idname = "ANIM_OT_driver_button_edit";
- ot->description = "Edit the drivers for the property connected represented by the highlighted button";
-
- /* callbacks */
- ot->exec = edit_driver_button_exec;
- //op->poll = ??? // TODO: need to have some driver to be able to do this...
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* identifiers */
+ ot->name = "Edit Driver";
+ ot->idname = "ANIM_OT_driver_button_edit";
+ ot->description =
+ "Edit the drivers for the property connected represented by the highlighted button";
+
+ /* callbacks */
+ ot->exec = edit_driver_button_exec;
+ //op->poll = ??? // TODO: need to have some driver to be able to do this...
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
}
/* Copy Driver Button Operator ------------------------ */
static int copy_driver_button_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr = {{NULL}};
- PropertyRNA *prop = NULL;
- short success = 0;
- int index;
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop = NULL;
+ short success = 0;
+ int index;
- /* try to create driver using property retrieved from UI */
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+ /* try to create driver using property retrieved from UI */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
- char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
+ if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
+ char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
- if (path) {
- /* only copy the driver for the button that this was involved for */
- success = ANIM_copy_driver(op->reports, ptr.id.data, path, index, 0);
+ if (path) {
+ /* only copy the driver for the button that this was involved for */
+ success = ANIM_copy_driver(op->reports, ptr.id.data, path, index, 0);
- UI_context_update_anim_flag(C);
+ UI_context_update_anim_flag(C);
- MEM_freeN(path);
- }
- }
+ MEM_freeN(path);
+ }
+ }
- /* since we're just copying, we don't really need to do anything else...*/
- return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ /* since we're just copying, we don't really need to do anything else...*/
+ return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void ANIM_OT_copy_driver_button(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Driver";
- ot->idname = "ANIM_OT_copy_driver_button";
- ot->description = "Copy the driver for the highlighted button";
+ /* identifiers */
+ ot->name = "Copy Driver";
+ ot->idname = "ANIM_OT_copy_driver_button";
+ ot->description = "Copy the driver for the highlighted button";
- /* callbacks */
- ot->exec = copy_driver_button_exec;
- //op->poll = ??? // TODO: need to have some driver to be able to do this...
+ /* callbacks */
+ ot->exec = copy_driver_button_exec;
+ //op->poll = ??? // TODO: need to have some driver to be able to do this...
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
}
/* Paste Driver Button Operator ------------------------ */
static int paste_driver_button_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr = {{NULL}};
- PropertyRNA *prop = NULL;
- short success = 0;
- int index;
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop = NULL;
+ short success = 0;
+ int index;
- /* try to create driver using property retrieved from UI */
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+ /* try to create driver using property retrieved from UI */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
- char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
+ if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
+ char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
- if (path) {
- /* only copy the driver for the button that this was involved for */
- success = ANIM_paste_driver(op->reports, ptr.id.data, path, index, 0);
+ if (path) {
+ /* only copy the driver for the button that this was involved for */
+ success = ANIM_paste_driver(op->reports, ptr.id.data, path, index, 0);
- UI_context_update_anim_flag(C);
+ UI_context_update_anim_flag(C);
- DEG_relations_tag_update(CTX_data_main(C));
- DEG_id_tag_update(ptr.id.data, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(CTX_data_main(C));
+ DEG_id_tag_update(ptr.id.data, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); // XXX
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); // XXX
- MEM_freeN(path);
- }
- }
+ MEM_freeN(path);
+ }
+ }
- /* since we're just copying, we don't really need to do anything else...*/
- return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ /* since we're just copying, we don't really need to do anything else...*/
+ return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void ANIM_OT_paste_driver_button(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Paste Driver";
- ot->idname = "ANIM_OT_paste_driver_button";
- ot->description = "Paste the driver in the copy/paste buffer for the highlighted button";
+ /* identifiers */
+ ot->name = "Paste Driver";
+ ot->idname = "ANIM_OT_paste_driver_button";
+ ot->description = "Paste the driver in the copy/paste buffer for the highlighted button";
- /* callbacks */
- ot->exec = paste_driver_button_exec;
- //op->poll = ??? // TODO: need to have some driver to be able to do this...
+ /* callbacks */
+ ot->exec = paste_driver_button_exec;
+ //op->poll = ??? // TODO: need to have some driver to be able to do this...
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
}
/* ************************************************** */
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
index 8edad506a33..919090cdee9 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -21,7 +21,6 @@
* \ingroup edanimation
*/
-
/* User-Interface Stuff for F-Modifiers:
* This file defines the (C-Coded) templates + editing callbacks needed
* by the interface stuff or F-Modifiers, as used by F-Curves in the Graph Editor,
@@ -65,635 +64,939 @@
// XXX! --------------------------------
/* temporary definition for limits of float number buttons (FLT_MAX tends to infinity with old system) */
-#define UI_FLT_MAX 10000.0f
+#define UI_FLT_MAX 10000.0f
-#define B_REDR 1
-#define B_FMODIFIER_REDRAW 20
+#define B_REDR 1
+#define B_FMODIFIER_REDRAW 20
/* callback to verify modifier data */
static void validate_fmodifier_cb(bContext *UNUSED(C), void *fcm_v, void *UNUSED(arg))
{
- FModifier *fcm = (FModifier *)fcm_v;
- const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
+ FModifier *fcm = (FModifier *)fcm_v;
+ const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
- /* call the verify callback on the modifier if applicable */
- if (fmi && fmi->verify_data)
- fmi->verify_data(fcm);
+ /* call the verify callback on the modifier if applicable */
+ if (fmi && fmi->verify_data)
+ fmi->verify_data(fcm);
}
/* callback to remove the given modifier */
typedef struct FModifierDeleteContext {
- ID *fcurve_owner_id;
- ListBase *modifiers;
+ ID *fcurve_owner_id;
+ ListBase *modifiers;
} FModifierDeleteContext;
static void delete_fmodifier_cb(bContext *C, void *ctx_v, void *fcm_v)
{
- FModifierDeleteContext *ctx = (FModifierDeleteContext *)ctx_v;
- ListBase *modifiers = ctx->modifiers;
- FModifier *fcm = (FModifier *)fcm_v;
+ FModifierDeleteContext *ctx = (FModifierDeleteContext *)ctx_v;
+ ListBase *modifiers = ctx->modifiers;
+ FModifier *fcm = (FModifier *)fcm_v;
- /* remove the given F-Modifier from the active modifier-stack */
- remove_fmodifier(modifiers, fcm);
+ /* remove the given F-Modifier from the active modifier-stack */
+ remove_fmodifier(modifiers, fcm);
- ED_undo_push(C, "Delete F-Curve Modifier");
+ ED_undo_push(C, "Delete F-Curve Modifier");
- /* send notifiers */
- // XXX for now, this is the only way to get updates in all the right places... but would be nice to have a special one in this case
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- DEG_id_tag_update(ctx->fcurve_owner_id, ID_RECALC_ANIMATION);
+ /* send notifiers */
+ // XXX for now, this is the only way to get updates in all the right places... but would be nice to have a special one in this case
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ DEG_id_tag_update(ctx->fcurve_owner_id, ID_RECALC_ANIMATION);
}
/* --------------- */
/* draw settings for generator modifier */
-static void draw_modifier__generator(uiLayout *layout, ID *fcurve_owner_id, FModifier *fcm, short width)
+static void draw_modifier__generator(uiLayout *layout,
+ ID *fcurve_owner_id,
+ FModifier *fcm,
+ short width)
{
- FMod_Generator *data = (FMod_Generator *)fcm->data;
- uiLayout /* *col, */ /* UNUSED */ *row;
- uiBlock *block;
- uiBut *but;
- PointerRNA ptr;
- short bwidth = width - 1.5 * UI_UNIT_X; /* max button width */
-
- /* init the RNA-pointer */
- RNA_pointer_create(fcurve_owner_id, &RNA_FModifierFunctionGenerator, fcm, &ptr);
-
- /* basic settings (backdrop + mode selector + some padding) */
- /* col = uiLayoutColumn(layout, true); */ /* UNUSED */
- block = uiLayoutGetBlock(layout);
- UI_block_align_begin(block);
- but = uiDefButR(block, UI_BTYPE_MENU, B_FMODIFIER_REDRAW, NULL, 0, 0, bwidth, UI_UNIT_Y, &ptr, "mode", -1, 0, 0, -1, -1, NULL);
- UI_but_func_set(but, validate_fmodifier_cb, fcm, NULL);
-
- uiDefButR(block, UI_BTYPE_TOGGLE, B_FMODIFIER_REDRAW, NULL, 0, 0, bwidth, UI_UNIT_Y, &ptr, "use_additive", -1, 0, 0, -1, -1, NULL);
- UI_block_align_end(block);
-
- /* now add settings for individual modes */
- switch (data->mode) {
- case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */
- {
- const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- float *cp = NULL;
- char xval[32];
- unsigned int i;
- int maxXWidth;
-
- /* draw polynomial order selector */
- row = uiLayoutRow(layout, false);
- block = uiLayoutGetBlock(row);
- but = uiDefButI(block, UI_BTYPE_NUM, B_FMODIFIER_REDRAW, IFACE_("Poly Order:"), 0.5f * UI_UNIT_X, 0, bwidth, UI_UNIT_Y,
- &data->poly_order, 1, 100, 0, 0,
- TIP_("'Order' of the Polynomial (for a polynomial with n terms, 'order' is n-1)"));
- UI_but_func_set(but, validate_fmodifier_cb, fcm, NULL);
-
-
- /* calculate maximum width of label for "x^n" labels */
- if (data->arraysize > 2) {
- BLI_snprintf(xval, sizeof(xval), "x^%u", data->arraysize);
- /* XXX: UI_fontstyle_string_width is not accurate */
- maxXWidth = UI_fontstyle_string_width(fstyle, xval) + 0.5 * UI_UNIT_X;
- }
- else {
- /* basic size (just "x") */
- maxXWidth = UI_fontstyle_string_width(fstyle, "x") + 0.5 * UI_UNIT_X;
- }
-
- /* draw controls for each coefficient and a + sign at end of row */
- row = uiLayoutRow(layout, true);
- block = uiLayoutGetBlock(row);
-
- cp = data->coefficients;
- for (i = 0; (i < data->arraysize) && (cp); i++, cp++) {
- /* To align with first line... */
- if (i)
- uiDefBut(block, UI_BTYPE_LABEL, 1, " ", 0, 0, 2 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- else
- uiDefBut(block, UI_BTYPE_LABEL, 1, "y =", 0, 0, 2 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
-
- /* coefficient */
- uiDefButF(block, UI_BTYPE_NUM, B_FMODIFIER_REDRAW, "", 0, 0, bwidth / 2, UI_UNIT_Y, cp, -UI_FLT_MAX, UI_FLT_MAX,
- 10, 3, TIP_("Coefficient for polynomial"));
-
- /* 'x' param (and '+' if necessary) */
- if (i == 0)
- BLI_strncpy(xval, "", sizeof(xval));
- else if (i == 1)
- BLI_strncpy(xval, "x", sizeof(xval));
- else
- BLI_snprintf(xval, sizeof(xval), "x^%u", i);
- uiDefBut(block, UI_BTYPE_LABEL, 1, xval, 0, 0, maxXWidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, TIP_("Power of x"));
-
- if ( (i != (data->arraysize - 1)) || ((i == 0) && data->arraysize == 2) ) {
- uiDefBut(block, UI_BTYPE_LABEL, 1, "+", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
-
- /* next coefficient on a new row */
- row = uiLayoutRow(layout, true);
- block = uiLayoutGetBlock(row);
- }
- else {
- /* For alignment in UI! */
- uiDefBut(block, UI_BTYPE_LABEL, 1, " ", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- }
- }
- break;
- }
-
- case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* Factorized polynomial expression */
- {
- float *cp = NULL;
- unsigned int i;
-
- /* draw polynomial order selector */
- row = uiLayoutRow(layout, false);
- block = uiLayoutGetBlock(row);
- but = uiDefButI(block, UI_BTYPE_NUM, B_FMODIFIER_REDRAW, IFACE_("Poly Order:"), 0, 0, width - 1.5 * UI_UNIT_X, UI_UNIT_Y,
- &data->poly_order, 1, 100, 0, 0,
- TIP_("'Order' of the Polynomial (for a polynomial with n terms, 'order' is n-1)"));
- UI_but_func_set(but, validate_fmodifier_cb, fcm, NULL);
-
-
- /* draw controls for each pair of coefficients */
- row = uiLayoutRow(layout, true);
- block = uiLayoutGetBlock(row);
-
- cp = data->coefficients;
- for (i = 0; (i < data->poly_order) && (cp); i++, cp += 2) {
- /* To align with first line */
- if (i)
- uiDefBut(block, UI_BTYPE_LABEL, 1, " ", 0, 0, 2.5 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- else
- uiDefBut(block, UI_BTYPE_LABEL, 1, "y =", 0, 0, 2.5 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- /* opening bracket */
- uiDefBut(block, UI_BTYPE_LABEL, 1, "(", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
-
- /* coefficients */
- uiDefButF(block, UI_BTYPE_NUM, B_FMODIFIER_REDRAW, "", 0, 0, 5 * UI_UNIT_X, UI_UNIT_Y, cp, -UI_FLT_MAX, UI_FLT_MAX,
- 10, 3, TIP_("Coefficient of x"));
-
- uiDefBut(block, UI_BTYPE_LABEL, 1, "x +", 0, 0, 2 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
-
- uiDefButF(block, UI_BTYPE_NUM, B_FMODIFIER_REDRAW, "", 0, 0, 5 * UI_UNIT_X, UI_UNIT_Y, cp + 1, -UI_FLT_MAX, UI_FLT_MAX,
- 10, 3, TIP_("Second coefficient"));
-
- /* closing bracket and multiplication sign */
- if ( (i != (data->poly_order - 1)) || ((i == 0) && data->poly_order == 2) ) {
- uiDefBut(block, UI_BTYPE_LABEL, 1, ") \xc3\x97", 0, 0, 2 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
-
- /* set up new row for the next pair of coefficients */
- row = uiLayoutRow(layout, true);
- block = uiLayoutGetBlock(row);
- }
- else
- uiDefBut(block, UI_BTYPE_LABEL, 1, ") ", 0, 0, 2 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- }
- break;
- }
- }
+ FMod_Generator *data = (FMod_Generator *)fcm->data;
+ uiLayout /* *col, */ /* UNUSED */ *row;
+ uiBlock *block;
+ uiBut *but;
+ PointerRNA ptr;
+ short bwidth = width - 1.5 * UI_UNIT_X; /* max button width */
+
+ /* init the RNA-pointer */
+ RNA_pointer_create(fcurve_owner_id, &RNA_FModifierFunctionGenerator, fcm, &ptr);
+
+ /* basic settings (backdrop + mode selector + some padding) */
+ /* col = uiLayoutColumn(layout, true); */ /* UNUSED */
+ block = uiLayoutGetBlock(layout);
+ UI_block_align_begin(block);
+ but = uiDefButR(block,
+ UI_BTYPE_MENU,
+ B_FMODIFIER_REDRAW,
+ NULL,
+ 0,
+ 0,
+ bwidth,
+ UI_UNIT_Y,
+ &ptr,
+ "mode",
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ UI_but_func_set(but, validate_fmodifier_cb, fcm, NULL);
+
+ uiDefButR(block,
+ UI_BTYPE_TOGGLE,
+ B_FMODIFIER_REDRAW,
+ NULL,
+ 0,
+ 0,
+ bwidth,
+ UI_UNIT_Y,
+ &ptr,
+ "use_additive",
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ UI_block_align_end(block);
+
+ /* now add settings for individual modes */
+ switch (data->mode) {
+ case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */
+ {
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ float *cp = NULL;
+ char xval[32];
+ unsigned int i;
+ int maxXWidth;
+
+ /* draw polynomial order selector */
+ row = uiLayoutRow(layout, false);
+ block = uiLayoutGetBlock(row);
+ but = uiDefButI(
+ block,
+ UI_BTYPE_NUM,
+ B_FMODIFIER_REDRAW,
+ IFACE_("Poly Order:"),
+ 0.5f * UI_UNIT_X,
+ 0,
+ bwidth,
+ UI_UNIT_Y,
+ &data->poly_order,
+ 1,
+ 100,
+ 0,
+ 0,
+ TIP_("'Order' of the Polynomial (for a polynomial with n terms, 'order' is n-1)"));
+ UI_but_func_set(but, validate_fmodifier_cb, fcm, NULL);
+
+ /* calculate maximum width of label for "x^n" labels */
+ if (data->arraysize > 2) {
+ BLI_snprintf(xval, sizeof(xval), "x^%u", data->arraysize);
+ /* XXX: UI_fontstyle_string_width is not accurate */
+ maxXWidth = UI_fontstyle_string_width(fstyle, xval) + 0.5 * UI_UNIT_X;
+ }
+ else {
+ /* basic size (just "x") */
+ maxXWidth = UI_fontstyle_string_width(fstyle, "x") + 0.5 * UI_UNIT_X;
+ }
+
+ /* draw controls for each coefficient and a + sign at end of row */
+ row = uiLayoutRow(layout, true);
+ block = uiLayoutGetBlock(row);
+
+ cp = data->coefficients;
+ for (i = 0; (i < data->arraysize) && (cp); i++, cp++) {
+ /* To align with first line... */
+ if (i)
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 1,
+ " ",
+ 0,
+ 0,
+ 2 * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ else
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 1,
+ "y =",
+ 0,
+ 0,
+ 2 * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+
+ /* coefficient */
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_FMODIFIER_REDRAW,
+ "",
+ 0,
+ 0,
+ bwidth / 2,
+ UI_UNIT_Y,
+ cp,
+ -UI_FLT_MAX,
+ UI_FLT_MAX,
+ 10,
+ 3,
+ TIP_("Coefficient for polynomial"));
+
+ /* 'x' param (and '+' if necessary) */
+ if (i == 0)
+ BLI_strncpy(xval, "", sizeof(xval));
+ else if (i == 1)
+ BLI_strncpy(xval, "x", sizeof(xval));
+ else
+ BLI_snprintf(xval, sizeof(xval), "x^%u", i);
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 1,
+ xval,
+ 0,
+ 0,
+ maxXWidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ TIP_("Power of x"));
+
+ if ((i != (data->arraysize - 1)) || ((i == 0) && data->arraysize == 2)) {
+ uiDefBut(
+ block, UI_BTYPE_LABEL, 1, "+", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+
+ /* next coefficient on a new row */
+ row = uiLayoutRow(layout, true);
+ block = uiLayoutGetBlock(row);
+ }
+ else {
+ /* For alignment in UI! */
+ uiDefBut(
+ block, UI_BTYPE_LABEL, 1, " ", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ }
+ }
+ break;
+ }
+
+ case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* Factorized polynomial expression */
+ {
+ float *cp = NULL;
+ unsigned int i;
+
+ /* draw polynomial order selector */
+ row = uiLayoutRow(layout, false);
+ block = uiLayoutGetBlock(row);
+ but = uiDefButI(
+ block,
+ UI_BTYPE_NUM,
+ B_FMODIFIER_REDRAW,
+ IFACE_("Poly Order:"),
+ 0,
+ 0,
+ width - 1.5 * UI_UNIT_X,
+ UI_UNIT_Y,
+ &data->poly_order,
+ 1,
+ 100,
+ 0,
+ 0,
+ TIP_("'Order' of the Polynomial (for a polynomial with n terms, 'order' is n-1)"));
+ UI_but_func_set(but, validate_fmodifier_cb, fcm, NULL);
+
+ /* draw controls for each pair of coefficients */
+ row = uiLayoutRow(layout, true);
+ block = uiLayoutGetBlock(row);
+
+ cp = data->coefficients;
+ for (i = 0; (i < data->poly_order) && (cp); i++, cp += 2) {
+ /* To align with first line */
+ if (i)
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 1,
+ " ",
+ 0,
+ 0,
+ 2.5 * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ else
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 1,
+ "y =",
+ 0,
+ 0,
+ 2.5 * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ /* opening bracket */
+ uiDefBut(
+ block, UI_BTYPE_LABEL, 1, "(", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+
+ /* coefficients */
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_FMODIFIER_REDRAW,
+ "",
+ 0,
+ 0,
+ 5 * UI_UNIT_X,
+ UI_UNIT_Y,
+ cp,
+ -UI_FLT_MAX,
+ UI_FLT_MAX,
+ 10,
+ 3,
+ TIP_("Coefficient of x"));
+
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 1,
+ "x +",
+ 0,
+ 0,
+ 2 * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_FMODIFIER_REDRAW,
+ "",
+ 0,
+ 0,
+ 5 * UI_UNIT_X,
+ UI_UNIT_Y,
+ cp + 1,
+ -UI_FLT_MAX,
+ UI_FLT_MAX,
+ 10,
+ 3,
+ TIP_("Second coefficient"));
+
+ /* closing bracket and multiplication sign */
+ if ((i != (data->poly_order - 1)) || ((i == 0) && data->poly_order == 2)) {
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 1,
+ ") \xc3\x97",
+ 0,
+ 0,
+ 2 * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+
+ /* set up new row for the next pair of coefficients */
+ row = uiLayoutRow(layout, true);
+ block = uiLayoutGetBlock(row);
+ }
+ else
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 1,
+ ") ",
+ 0,
+ 0,
+ 2 * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ }
+ break;
+ }
+ }
}
/* --------------- */
/* draw settings for generator modifier */
-static void draw_modifier__fn_generator(uiLayout *layout, ID *fcurve_owner_id, FModifier *fcm, short UNUSED(width))
+static void draw_modifier__fn_generator(uiLayout *layout,
+ ID *fcurve_owner_id,
+ FModifier *fcm,
+ short UNUSED(width))
{
- uiLayout *col;
- PointerRNA ptr;
-
- /* init the RNA-pointer */
- RNA_pointer_create(fcurve_owner_id, &RNA_FModifierFunctionGenerator, fcm, &ptr);
-
- /* add the settings */
- col = uiLayoutColumn(layout, true);
- uiItemR(col, &ptr, "function_type", 0, "", ICON_NONE);
- uiItemR(col, &ptr, "use_additive", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
-
- col = uiLayoutColumn(layout, false); // no grouping for now
- uiItemR(col, &ptr, "amplitude", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "phase_multiplier", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "phase_offset", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "value_offset", 0, NULL, ICON_NONE);
+ uiLayout *col;
+ PointerRNA ptr;
+
+ /* init the RNA-pointer */
+ RNA_pointer_create(fcurve_owner_id, &RNA_FModifierFunctionGenerator, fcm, &ptr);
+
+ /* add the settings */
+ col = uiLayoutColumn(layout, true);
+ uiItemR(col, &ptr, "function_type", 0, "", ICON_NONE);
+ uiItemR(col, &ptr, "use_additive", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
+
+ col = uiLayoutColumn(layout, false); // no grouping for now
+ uiItemR(col, &ptr, "amplitude", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "phase_multiplier", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "phase_offset", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "value_offset", 0, NULL, ICON_NONE);
}
/* --------------- */
/* draw settings for cycles modifier */
-static void draw_modifier__cycles(uiLayout *layout, ID *fcurve_owner_id, FModifier *fcm, short UNUSED(width))
+static void draw_modifier__cycles(uiLayout *layout,
+ ID *fcurve_owner_id,
+ FModifier *fcm,
+ short UNUSED(width))
{
- uiLayout *split, *col;
- PointerRNA ptr;
-
- /* init the RNA-pointer */
- RNA_pointer_create(fcurve_owner_id, &RNA_FModifierCycles, fcm, &ptr);
-
- /* split into 2 columns
- * NOTE: the mode comboboxes shouldn't get labels, otherwise there isn't enough room
- */
- split = uiLayoutSplit(layout, 0.5f, false);
-
- /* before range */
- col = uiLayoutColumn(split, true);
- uiItemL(col, IFACE_("Before:"), ICON_NONE);
- uiItemR(col, &ptr, "mode_before", 0, "", ICON_NONE);
- uiItemR(col, &ptr, "cycles_before", 0, NULL, ICON_NONE);
-
- /* after range */
- col = uiLayoutColumn(split, true);
- uiItemL(col, IFACE_("After:"), ICON_NONE);
- uiItemR(col, &ptr, "mode_after", 0, "", ICON_NONE);
- uiItemR(col, &ptr, "cycles_after", 0, NULL, ICON_NONE);
+ uiLayout *split, *col;
+ PointerRNA ptr;
+
+ /* init the RNA-pointer */
+ RNA_pointer_create(fcurve_owner_id, &RNA_FModifierCycles, fcm, &ptr);
+
+ /* split into 2 columns
+ * NOTE: the mode comboboxes shouldn't get labels, otherwise there isn't enough room
+ */
+ split = uiLayoutSplit(layout, 0.5f, false);
+
+ /* before range */
+ col = uiLayoutColumn(split, true);
+ uiItemL(col, IFACE_("Before:"), ICON_NONE);
+ uiItemR(col, &ptr, "mode_before", 0, "", ICON_NONE);
+ uiItemR(col, &ptr, "cycles_before", 0, NULL, ICON_NONE);
+
+ /* after range */
+ col = uiLayoutColumn(split, true);
+ uiItemL(col, IFACE_("After:"), ICON_NONE);
+ uiItemR(col, &ptr, "mode_after", 0, "", ICON_NONE);
+ uiItemR(col, &ptr, "cycles_after", 0, NULL, ICON_NONE);
}
/* --------------- */
/* draw settings for noise modifier */
-static void draw_modifier__noise(uiLayout *layout, ID *fcurve_owner_id, FModifier *fcm, short UNUSED(width))
+static void draw_modifier__noise(uiLayout *layout,
+ ID *fcurve_owner_id,
+ FModifier *fcm,
+ short UNUSED(width))
{
- uiLayout *split, *col;
- PointerRNA ptr;
+ uiLayout *split, *col;
+ PointerRNA ptr;
- /* init the RNA-pointer */
- RNA_pointer_create(fcurve_owner_id, &RNA_FModifierNoise, fcm, &ptr);
+ /* init the RNA-pointer */
+ RNA_pointer_create(fcurve_owner_id, &RNA_FModifierNoise, fcm, &ptr);
- /* blending mode */
- uiItemR(layout, &ptr, "blend_type", 0, NULL, ICON_NONE);
+ /* blending mode */
+ uiItemR(layout, &ptr, "blend_type", 0, NULL, ICON_NONE);
- /* split into 2 columns */
- split = uiLayoutSplit(layout, 0.5f, false);
+ /* split into 2 columns */
+ split = uiLayoutSplit(layout, 0.5f, false);
- /* col 1 */
- col = uiLayoutColumn(split, false);
- uiItemR(col, &ptr, "scale", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "strength", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "offset", 0, NULL, ICON_NONE);
+ /* col 1 */
+ col = uiLayoutColumn(split, false);
+ uiItemR(col, &ptr, "scale", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "strength", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "offset", 0, NULL, ICON_NONE);
- /* col 2 */
- col = uiLayoutColumn(split, false);
- uiItemR(col, &ptr, "phase", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "depth", 0, NULL, ICON_NONE);
+ /* col 2 */
+ col = uiLayoutColumn(split, false);
+ uiItemR(col, &ptr, "phase", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "depth", 0, NULL, ICON_NONE);
}
/* callback to add new envelope data point */
static void fmod_envelope_addpoint_cb(bContext *C, void *fcm_dv, void *UNUSED(arg))
{
- Scene *scene = CTX_data_scene(C);
- FMod_Envelope *env = (FMod_Envelope *)fcm_dv;
- FCM_EnvelopeData *fedn;
- FCM_EnvelopeData fed;
-
- /* init template data */
- fed.min = -1.0f;
- fed.max = 1.0f;
- fed.time = (float)scene->r.cfra; // XXX make this int for ease of use?
- fed.f1 = fed.f2 = 0;
-
- /* check that no data exists for the current frame... */
- if (env->data) {
- bool exists;
- int i = BKE_fcm_envelope_find_index(env->data, (float)(scene->r.cfra), env->totvert, &exists);
-
- /* binarysearch_...() will set exists by default to 0,
- * so if it is non-zero, that means that the point exists already */
- if (exists) {
- return;
- }
-
- /* add new */
- fedn = MEM_callocN((env->totvert + 1) * sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
-
- /* add the points that should occur before the point to be pasted */
- if (i > 0)
- memcpy(fedn, env->data, i * sizeof(FCM_EnvelopeData));
-
- /* add point to paste at index i */
- *(fedn + i) = fed;
-
- /* add the points that occur after the point to be pasted */
- if (i < env->totvert)
- memcpy(fedn + i + 1, env->data + i, (env->totvert - i) * sizeof(FCM_EnvelopeData));
-
- /* replace (+ free) old with new */
- MEM_freeN(env->data);
- env->data = fedn;
-
- env->totvert++;
- }
- else {
- env->data = MEM_callocN(sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
- *(env->data) = fed;
-
- env->totvert = 1;
- }
+ Scene *scene = CTX_data_scene(C);
+ FMod_Envelope *env = (FMod_Envelope *)fcm_dv;
+ FCM_EnvelopeData *fedn;
+ FCM_EnvelopeData fed;
+
+ /* init template data */
+ fed.min = -1.0f;
+ fed.max = 1.0f;
+ fed.time = (float)scene->r.cfra; // XXX make this int for ease of use?
+ fed.f1 = fed.f2 = 0;
+
+ /* check that no data exists for the current frame... */
+ if (env->data) {
+ bool exists;
+ int i = BKE_fcm_envelope_find_index(env->data, (float)(scene->r.cfra), env->totvert, &exists);
+
+ /* binarysearch_...() will set exists by default to 0,
+ * so if it is non-zero, that means that the point exists already */
+ if (exists) {
+ return;
+ }
+
+ /* add new */
+ fedn = MEM_callocN((env->totvert + 1) * sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
+
+ /* add the points that should occur before the point to be pasted */
+ if (i > 0)
+ memcpy(fedn, env->data, i * sizeof(FCM_EnvelopeData));
+
+ /* add point to paste at index i */
+ *(fedn + i) = fed;
+
+ /* add the points that occur after the point to be pasted */
+ if (i < env->totvert)
+ memcpy(fedn + i + 1, env->data + i, (env->totvert - i) * sizeof(FCM_EnvelopeData));
+
+ /* replace (+ free) old with new */
+ MEM_freeN(env->data);
+ env->data = fedn;
+
+ env->totvert++;
+ }
+ else {
+ env->data = MEM_callocN(sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
+ *(env->data) = fed;
+
+ env->totvert = 1;
+ }
}
/* callback to remove envelope data point */
// TODO: should we have a separate file for things like this?
static void fmod_envelope_deletepoint_cb(bContext *UNUSED(C), void *fcm_dv, void *ind_v)
{
- FMod_Envelope *env = (FMod_Envelope *)fcm_dv;
- FCM_EnvelopeData *fedn;
- int index = POINTER_AS_INT(ind_v);
-
- /* check that no data exists for the current frame... */
- if (env->totvert > 1) {
- /* allocate a new smaller array */
- fedn = MEM_callocN(sizeof(FCM_EnvelopeData) * (env->totvert - 1), "FCM_EnvelopeData");
-
- memcpy(fedn, env->data, sizeof(FCM_EnvelopeData) * (index));
- memcpy(fedn + index, env->data + (index + 1), sizeof(FCM_EnvelopeData) * ((env->totvert - index) - 1));
-
- /* free old array, and set the new */
- MEM_freeN(env->data);
- env->data = fedn;
- env->totvert--;
- }
- else {
- /* just free array, since the only vert was deleted */
- if (env->data) {
- MEM_freeN(env->data);
- env->data = NULL;
- }
- env->totvert = 0;
- }
+ FMod_Envelope *env = (FMod_Envelope *)fcm_dv;
+ FCM_EnvelopeData *fedn;
+ int index = POINTER_AS_INT(ind_v);
+
+ /* check that no data exists for the current frame... */
+ if (env->totvert > 1) {
+ /* allocate a new smaller array */
+ fedn = MEM_callocN(sizeof(FCM_EnvelopeData) * (env->totvert - 1), "FCM_EnvelopeData");
+
+ memcpy(fedn, env->data, sizeof(FCM_EnvelopeData) * (index));
+ memcpy(fedn + index,
+ env->data + (index + 1),
+ sizeof(FCM_EnvelopeData) * ((env->totvert - index) - 1));
+
+ /* free old array, and set the new */
+ MEM_freeN(env->data);
+ env->data = fedn;
+ env->totvert--;
+ }
+ else {
+ /* just free array, since the only vert was deleted */
+ if (env->data) {
+ MEM_freeN(env->data);
+ env->data = NULL;
+ }
+ env->totvert = 0;
+ }
}
/* draw settings for envelope modifier */
-static void draw_modifier__envelope(uiLayout *layout, ID *fcurve_owner_id, FModifier *fcm, short UNUSED(width))
+static void draw_modifier__envelope(uiLayout *layout,
+ ID *fcurve_owner_id,
+ FModifier *fcm,
+ short UNUSED(width))
{
- FMod_Envelope *env = (FMod_Envelope *)fcm->data;
- FCM_EnvelopeData *fed;
- uiLayout *col, *row;
- uiBlock *block;
- uiBut *but;
- PointerRNA ptr;
- int i;
-
- /* init the RNA-pointer */
- RNA_pointer_create(fcurve_owner_id, &RNA_FModifierEnvelope, fcm, &ptr);
-
- /* general settings */
- col = uiLayoutColumn(layout, true);
- uiItemL(col, IFACE_("Envelope:"), ICON_NONE);
- uiItemR(col, &ptr, "reference_value", 0, NULL, ICON_NONE);
-
- row = uiLayoutRow(col, true);
- uiItemR(row, &ptr, "default_min", 0, IFACE_("Min"), ICON_NONE);
- uiItemR(row, &ptr, "default_max", 0, IFACE_("Max"), ICON_NONE);
-
- /* control points header */
- /* TODO: move this control-point control stuff to using the new special widgets for lists
- * the current way is far too cramped */
- row = uiLayoutRow(layout, false);
- block = uiLayoutGetBlock(row);
-
- uiDefBut(block, UI_BTYPE_LABEL, 1, IFACE_("Control Points:"), 0, 0, 7.5 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
-
- but = uiDefBut(block, UI_BTYPE_BUT, B_FMODIFIER_REDRAW, IFACE_("Add Point"), 0, 0, 7.5 * UI_UNIT_X, UI_UNIT_Y,
- NULL, 0, 0, 0, 0, TIP_("Add a new control-point to the envelope on the current frame"));
- UI_but_func_set(but, fmod_envelope_addpoint_cb, env, NULL);
-
- /* control points list */
- for (i = 0, fed = env->data; i < env->totvert; i++, fed++) {
- /* 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, UI_BTYPE_NUM, B_FMODIFIER_REDRAW, IFACE_("Min:"), 0, 0, 5 * UI_UNIT_X, UI_UNIT_Y,
- &fed->min, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, TIP_("Minimum bound of envelope at this point"));
- uiDefButF(block, UI_BTYPE_NUM, B_FMODIFIER_REDRAW, IFACE_("Max:"), 0, 0, 5 * UI_UNIT_X, UI_UNIT_Y,
- &fed->max, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, TIP_("Maximum bound of envelope at this point"));
-
- but = uiDefIconBut(block, UI_BTYPE_BUT, B_FMODIFIER_REDRAW, ICON_X, 0, 0, 0.9 * UI_UNIT_X, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Delete envelope control point"));
- UI_but_func_set(but, fmod_envelope_deletepoint_cb, env, POINTER_FROM_INT(i));
- UI_block_align_begin(block);
- }
+ FMod_Envelope *env = (FMod_Envelope *)fcm->data;
+ FCM_EnvelopeData *fed;
+ uiLayout *col, *row;
+ uiBlock *block;
+ uiBut *but;
+ PointerRNA ptr;
+ int i;
+
+ /* init the RNA-pointer */
+ RNA_pointer_create(fcurve_owner_id, &RNA_FModifierEnvelope, fcm, &ptr);
+
+ /* general settings */
+ col = uiLayoutColumn(layout, true);
+ uiItemL(col, IFACE_("Envelope:"), ICON_NONE);
+ uiItemR(col, &ptr, "reference_value", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(col, true);
+ uiItemR(row, &ptr, "default_min", 0, IFACE_("Min"), ICON_NONE);
+ uiItemR(row, &ptr, "default_max", 0, IFACE_("Max"), ICON_NONE);
+
+ /* control points header */
+ /* TODO: move this control-point control stuff to using the new special widgets for lists
+ * the current way is far too cramped */
+ row = uiLayoutRow(layout, false);
+ block = uiLayoutGetBlock(row);
+
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 1,
+ IFACE_("Control Points:"),
+ 0,
+ 0,
+ 7.5 * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+
+ but = uiDefBut(block,
+ UI_BTYPE_BUT,
+ B_FMODIFIER_REDRAW,
+ IFACE_("Add Point"),
+ 0,
+ 0,
+ 7.5 * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Add a new control-point to the envelope on the current frame"));
+ UI_but_func_set(but, fmod_envelope_addpoint_cb, env, NULL);
+
+ /* control points list */
+ for (i = 0, fed = env->data; i < env->totvert; i++, fed++) {
+ /* 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,
+ UI_BTYPE_NUM,
+ B_FMODIFIER_REDRAW,
+ IFACE_("Min:"),
+ 0,
+ 0,
+ 5 * UI_UNIT_X,
+ UI_UNIT_Y,
+ &fed->min,
+ -UI_FLT_MAX,
+ UI_FLT_MAX,
+ 10,
+ 2,
+ TIP_("Minimum bound of envelope at this point"));
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_FMODIFIER_REDRAW,
+ IFACE_("Max:"),
+ 0,
+ 0,
+ 5 * UI_UNIT_X,
+ UI_UNIT_Y,
+ &fed->max,
+ -UI_FLT_MAX,
+ UI_FLT_MAX,
+ 10,
+ 2,
+ TIP_("Maximum bound of envelope at this point"));
+
+ but = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ B_FMODIFIER_REDRAW,
+ ICON_X,
+ 0,
+ 0,
+ 0.9 * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Delete envelope control point"));
+ UI_but_func_set(but, fmod_envelope_deletepoint_cb, env, POINTER_FROM_INT(i));
+ UI_block_align_begin(block);
+ }
}
/* --------------- */
/* draw settings for limits modifier */
-static void draw_modifier__limits(uiLayout *layout, ID *fcurve_owner_id, FModifier *fcm, short UNUSED(width))
+static void draw_modifier__limits(uiLayout *layout,
+ ID *fcurve_owner_id,
+ FModifier *fcm,
+ short UNUSED(width))
{
- uiLayout *split, *col /* , *row */ /* UNUSED */;
- PointerRNA ptr;
-
- /* init the RNA-pointer */
- RNA_pointer_create(fcurve_owner_id, &RNA_FModifierLimits, fcm, &ptr);
-
- /* row 1: minimum */
- {
- /* row = uiLayoutRow(layout, false); */ /* UNUSED */
-
- /* split into 2 columns */
- split = uiLayoutSplit(layout, 0.5f, false);
-
- /* x-minimum */
- col = uiLayoutColumn(split, true);
- uiItemR(col, &ptr, "use_min_x", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "min_x", 0, NULL, ICON_NONE);
-
- /* y-minimum*/
- col = uiLayoutColumn(split, true);
- uiItemR(col, &ptr, "use_min_y", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "min_y", 0, NULL, ICON_NONE);
- }
-
- /* row 2: maximum */
- {
- /* row = uiLayoutRow(layout, false); */ /* UNUSED */
-
- /* split into 2 columns */
- split = uiLayoutSplit(layout, 0.5f, false);
-
- /* x-minimum */
- col = uiLayoutColumn(split, true);
- uiItemR(col, &ptr, "use_max_x", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "max_x", 0, NULL, ICON_NONE);
-
- /* y-minimum*/
- col = uiLayoutColumn(split, true);
- uiItemR(col, &ptr, "use_max_y", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "max_y", 0, NULL, ICON_NONE);
- }
+ uiLayout *split, *col /* , *row */ /* UNUSED */;
+ PointerRNA ptr;
+
+ /* init the RNA-pointer */
+ RNA_pointer_create(fcurve_owner_id, &RNA_FModifierLimits, fcm, &ptr);
+
+ /* row 1: minimum */
+ {
+ /* row = uiLayoutRow(layout, false); */ /* UNUSED */
+
+ /* split into 2 columns */
+ split = uiLayoutSplit(layout, 0.5f, false);
+
+ /* x-minimum */
+ col = uiLayoutColumn(split, true);
+ uiItemR(col, &ptr, "use_min_x", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "min_x", 0, NULL, ICON_NONE);
+
+ /* y-minimum*/
+ col = uiLayoutColumn(split, true);
+ uiItemR(col, &ptr, "use_min_y", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "min_y", 0, NULL, ICON_NONE);
+ }
+
+ /* row 2: maximum */
+ {
+ /* row = uiLayoutRow(layout, false); */ /* UNUSED */
+
+ /* split into 2 columns */
+ split = uiLayoutSplit(layout, 0.5f, false);
+
+ /* x-minimum */
+ col = uiLayoutColumn(split, true);
+ uiItemR(col, &ptr, "use_max_x", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "max_x", 0, NULL, ICON_NONE);
+
+ /* y-minimum*/
+ col = uiLayoutColumn(split, true);
+ uiItemR(col, &ptr, "use_max_y", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "max_y", 0, NULL, ICON_NONE);
+ }
}
/* --------------- */
/* draw settings for stepped interpolation modifier */
-static void draw_modifier__stepped(uiLayout *layout, ID *fcurve_owner_id, FModifier *fcm, short UNUSED(width))
+static void draw_modifier__stepped(uiLayout *layout,
+ ID *fcurve_owner_id,
+ FModifier *fcm,
+ short UNUSED(width))
{
- uiLayout *col, *sub;
- PointerRNA ptr;
+ uiLayout *col, *sub;
+ PointerRNA ptr;
- /* init the RNA-pointer */
- RNA_pointer_create(fcurve_owner_id, &RNA_FModifierStepped, fcm, &ptr);
+ /* init the RNA-pointer */
+ RNA_pointer_create(fcurve_owner_id, &RNA_FModifierStepped, fcm, &ptr);
- /* block 1: "stepping" settings */
- col = uiLayoutColumn(layout, false);
- uiItemR(col, &ptr, "frame_step", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "frame_offset", 0, NULL, ICON_NONE);
+ /* block 1: "stepping" settings */
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, &ptr, "frame_step", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "frame_offset", 0, NULL, ICON_NONE);
- /* block 2: start range settings */
- col = uiLayoutColumn(layout, true);
- uiItemR(col, &ptr, "use_frame_start", 0, NULL, ICON_NONE);
+ /* block 2: start range settings */
+ col = uiLayoutColumn(layout, true);
+ uiItemR(col, &ptr, "use_frame_start", 0, NULL, ICON_NONE);
- sub = uiLayoutColumn(col, true);
- uiLayoutSetActive(sub, RNA_boolean_get(&ptr, "use_frame_start"));
- uiItemR(sub, &ptr, "frame_start", 0, NULL, ICON_NONE);
+ sub = uiLayoutColumn(col, true);
+ uiLayoutSetActive(sub, RNA_boolean_get(&ptr, "use_frame_start"));
+ uiItemR(sub, &ptr, "frame_start", 0, NULL, ICON_NONE);
- /* block 3: end range settings */
- col = uiLayoutColumn(layout, true);
- uiItemR(col, &ptr, "use_frame_end", 0, NULL, ICON_NONE);
+ /* block 3: end range settings */
+ col = uiLayoutColumn(layout, true);
+ uiItemR(col, &ptr, "use_frame_end", 0, NULL, ICON_NONE);
- sub = uiLayoutColumn(col, true);
- uiLayoutSetActive(sub, RNA_boolean_get(&ptr, "use_frame_end"));
- uiItemR(sub, &ptr, "frame_end", 0, NULL, ICON_NONE);
+ sub = uiLayoutColumn(col, true);
+ uiLayoutSetActive(sub, RNA_boolean_get(&ptr, "use_frame_end"));
+ uiItemR(sub, &ptr, "frame_end", 0, NULL, ICON_NONE);
}
/* --------------- */
-void ANIM_uiTemplate_fmodifier_draw(uiLayout *layout, ID *fcurve_owner_id,
- ListBase *modifiers, FModifier *fcm)
+void ANIM_uiTemplate_fmodifier_draw(uiLayout *layout,
+ ID *fcurve_owner_id,
+ ListBase *modifiers,
+ FModifier *fcm)
{
- const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
- uiLayout *box, *row, *sub, *col;
- uiBlock *block;
- uiBut *but;
- short width = 314;
- PointerRNA ptr;
-
- /* init the RNA-pointer */
- RNA_pointer_create(fcurve_owner_id, &RNA_FModifier, fcm, &ptr);
-
- /* draw header */
- {
- /* get layout-row + UI-block for this */
- box = uiLayoutBox(layout);
-
- row = uiLayoutRow(box, false);
- block = uiLayoutGetBlock(row); // err...
-
- /* left-align -------------------------------------------- */
- sub = uiLayoutRow(row, true);
- uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
- /* expand */
- uiItemR(sub, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
-
- /* checkbox for 'active' status (for now) */
- uiItemR(sub, &ptr, "active", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
-
- /* name */
- if (fmi)
- uiItemL(sub, IFACE_(fmi->name), ICON_NONE);
- else
- uiItemL(sub, IFACE_("<Unknown Modifier>"), ICON_NONE);
-
- /* right-align ------------------------------------------- */
- sub = uiLayoutRow(row, true);
- uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_RIGHT);
-
-
- /* 'mute' button */
- uiItemR(sub, &ptr, "mute", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
- /* delete button */
- but = uiDefIconBut(block, UI_BTYPE_BUT, B_REDR, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Delete F-Curve Modifier"));
- FModifierDeleteContext *ctx = MEM_mallocN(sizeof(FModifierDeleteContext), "fmodifier ctx");
- ctx->fcurve_owner_id = fcurve_owner_id;
- ctx->modifiers = modifiers;
- UI_but_funcN_set(but, delete_fmodifier_cb, ctx, fcm);
-
- UI_block_emboss_set(block, UI_EMBOSS);
- }
-
- /* when modifier is expanded, draw settings */
- if (fcm->flag & FMODIFIER_FLAG_EXPANDED) {
- /* set up the flexible-box layout which acts as the backdrop for the modifier settings */
- box = uiLayoutBox(layout);
-
- /* draw settings for individual modifiers */
- switch (fcm->type) {
- case FMODIFIER_TYPE_GENERATOR: /* Generator */
- draw_modifier__generator(box, fcurve_owner_id, fcm, width);
- break;
-
- case FMODIFIER_TYPE_FN_GENERATOR: /* Built-In Function Generator */
- draw_modifier__fn_generator(box, fcurve_owner_id, fcm, width);
- break;
-
- case FMODIFIER_TYPE_CYCLES: /* Cycles */
- draw_modifier__cycles(box, fcurve_owner_id, fcm, width);
- break;
-
- case FMODIFIER_TYPE_ENVELOPE: /* Envelope */
- draw_modifier__envelope(box, fcurve_owner_id, fcm, width);
- break;
-
- case FMODIFIER_TYPE_LIMITS: /* Limits */
- draw_modifier__limits(box, fcurve_owner_id, fcm, width);
- break;
-
- case FMODIFIER_TYPE_NOISE: /* Noise */
- draw_modifier__noise(box, fcurve_owner_id, fcm, width);
- break;
-
- case FMODIFIER_TYPE_STEPPED: /* Stepped */
- draw_modifier__stepped(box, fcurve_owner_id, fcm, width);
- break;
-
- default: /* unknown type */
- break;
- }
-
- /* one last panel below this: FModifier range */
- // TODO: experiment with placement of this
- {
- box = uiLayoutBox(layout);
-
- /* restricted range ----------------------------------------------------- */
- col = uiLayoutColumn(box, true);
-
- /* top row: use restricted range */
- row = uiLayoutRow(col, true);
- uiItemR(row, &ptr, "use_restricted_range", 0, NULL, ICON_NONE);
-
- if (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) {
- /* second row: settings */
- row = uiLayoutRow(col, true);
-
- uiItemR(row, &ptr, "frame_start", 0, IFACE_("Start"), ICON_NONE);
- uiItemR(row, &ptr, "frame_end", 0, IFACE_("End"), ICON_NONE);
-
- /* third row: blending influence */
- row = uiLayoutRow(col, true);
-
- uiItemR(row, &ptr, "blend_in", 0, IFACE_("In"), ICON_NONE);
- uiItemR(row, &ptr, "blend_out", 0, IFACE_("Out"), ICON_NONE);
- }
-
- /* influence -------------------------------------------------------------- */
- col = uiLayoutColumn(box, true);
-
- /* top row: use influence */
- uiItemR(col, &ptr, "use_influence", 0, NULL, ICON_NONE);
-
- if (fcm->flag & FMODIFIER_FLAG_USEINFLUENCE) {
- /* second row: influence value */
- uiItemR(col, &ptr, "influence", 0, NULL, ICON_NONE);
- }
- }
- }
+ const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
+ uiLayout *box, *row, *sub, *col;
+ uiBlock *block;
+ uiBut *but;
+ short width = 314;
+ PointerRNA ptr;
+
+ /* init the RNA-pointer */
+ RNA_pointer_create(fcurve_owner_id, &RNA_FModifier, fcm, &ptr);
+
+ /* draw header */
+ {
+ /* get layout-row + UI-block for this */
+ box = uiLayoutBox(layout);
+
+ row = uiLayoutRow(box, false);
+ block = uiLayoutGetBlock(row); // err...
+
+ /* left-align -------------------------------------------- */
+ sub = uiLayoutRow(row, true);
+ uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+
+ /* expand */
+ uiItemR(sub, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+
+ /* checkbox for 'active' status (for now) */
+ uiItemR(sub, &ptr, "active", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+
+ /* name */
+ if (fmi)
+ uiItemL(sub, IFACE_(fmi->name), ICON_NONE);
+ else
+ uiItemL(sub, IFACE_("<Unknown Modifier>"), ICON_NONE);
+
+ /* right-align ------------------------------------------- */
+ sub = uiLayoutRow(row, true);
+ uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_RIGHT);
+
+ /* 'mute' button */
+ uiItemR(sub, &ptr, "mute", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+
+ /* delete button */
+ but = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ B_REDR,
+ ICON_X,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Delete F-Curve Modifier"));
+ FModifierDeleteContext *ctx = MEM_mallocN(sizeof(FModifierDeleteContext), "fmodifier ctx");
+ ctx->fcurve_owner_id = fcurve_owner_id;
+ ctx->modifiers = modifiers;
+ UI_but_funcN_set(but, delete_fmodifier_cb, ctx, fcm);
+
+ UI_block_emboss_set(block, UI_EMBOSS);
+ }
+
+ /* when modifier is expanded, draw settings */
+ if (fcm->flag & FMODIFIER_FLAG_EXPANDED) {
+ /* set up the flexible-box layout which acts as the backdrop for the modifier settings */
+ box = uiLayoutBox(layout);
+
+ /* draw settings for individual modifiers */
+ switch (fcm->type) {
+ case FMODIFIER_TYPE_GENERATOR: /* Generator */
+ draw_modifier__generator(box, fcurve_owner_id, fcm, width);
+ break;
+
+ case FMODIFIER_TYPE_FN_GENERATOR: /* Built-In Function Generator */
+ draw_modifier__fn_generator(box, fcurve_owner_id, fcm, width);
+ break;
+
+ case FMODIFIER_TYPE_CYCLES: /* Cycles */
+ draw_modifier__cycles(box, fcurve_owner_id, fcm, width);
+ break;
+
+ case FMODIFIER_TYPE_ENVELOPE: /* Envelope */
+ draw_modifier__envelope(box, fcurve_owner_id, fcm, width);
+ break;
+
+ case FMODIFIER_TYPE_LIMITS: /* Limits */
+ draw_modifier__limits(box, fcurve_owner_id, fcm, width);
+ break;
+
+ case FMODIFIER_TYPE_NOISE: /* Noise */
+ draw_modifier__noise(box, fcurve_owner_id, fcm, width);
+ break;
+
+ case FMODIFIER_TYPE_STEPPED: /* Stepped */
+ draw_modifier__stepped(box, fcurve_owner_id, fcm, width);
+ break;
+
+ default: /* unknown type */
+ break;
+ }
+
+ /* one last panel below this: FModifier range */
+ // TODO: experiment with placement of this
+ {
+ box = uiLayoutBox(layout);
+
+ /* restricted range ----------------------------------------------------- */
+ col = uiLayoutColumn(box, true);
+
+ /* top row: use restricted range */
+ row = uiLayoutRow(col, true);
+ uiItemR(row, &ptr, "use_restricted_range", 0, NULL, ICON_NONE);
+
+ if (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) {
+ /* second row: settings */
+ row = uiLayoutRow(col, true);
+
+ uiItemR(row, &ptr, "frame_start", 0, IFACE_("Start"), ICON_NONE);
+ uiItemR(row, &ptr, "frame_end", 0, IFACE_("End"), ICON_NONE);
+
+ /* third row: blending influence */
+ row = uiLayoutRow(col, true);
+
+ uiItemR(row, &ptr, "blend_in", 0, IFACE_("In"), ICON_NONE);
+ uiItemR(row, &ptr, "blend_out", 0, IFACE_("Out"), ICON_NONE);
+ }
+
+ /* influence -------------------------------------------------------------- */
+ col = uiLayoutColumn(box, true);
+
+ /* top row: use influence */
+ uiItemR(col, &ptr, "use_influence", 0, NULL, ICON_NONE);
+
+ if (fcm->flag & FMODIFIER_FLAG_USEINFLUENCE) {
+ /* second row: influence value */
+ uiItemR(col, &ptr, "influence", 0, NULL, ICON_NONE);
+ }
+ }
+ }
}
/* ********************************************** */
@@ -707,8 +1010,8 @@ static ListBase fmodifier_copypaste_buf = {NULL, NULL};
/* free the copy/paste buffer */
void ANIM_fmodifiers_copybuf_free(void)
{
- /* just free the whole buffer */
- free_fmodifiers(&fmodifier_copypaste_buf);
+ /* just free the whole buffer */
+ free_fmodifiers(&fmodifier_copypaste_buf);
}
/* copy the given F-Modifiers to the buffer, returning whether anything was copied or not
@@ -717,28 +1020,28 @@ void ANIM_fmodifiers_copybuf_free(void)
*/
bool ANIM_fmodifiers_copy_to_buf(ListBase *modifiers, bool active)
{
- bool ok = true;
-
- /* sanity checks */
- if (ELEM(NULL, modifiers, modifiers->first))
- return 0;
-
- /* copy the whole list, or just the active one? */
- if (active) {
- FModifier *fcm = find_active_fmodifier(modifiers);
-
- if (fcm) {
- FModifier *fcmN = copy_fmodifier(fcm);
- BLI_addtail(&fmodifier_copypaste_buf, fcmN);
- }
- else
- ok = 0;
- }
- else
- copy_fmodifiers(&fmodifier_copypaste_buf, modifiers);
-
- /* did we succeed? */
- return ok;
+ bool ok = true;
+
+ /* sanity checks */
+ if (ELEM(NULL, modifiers, modifiers->first))
+ return 0;
+
+ /* copy the whole list, or just the active one? */
+ if (active) {
+ FModifier *fcm = find_active_fmodifier(modifiers);
+
+ if (fcm) {
+ FModifier *fcmN = copy_fmodifier(fcm);
+ BLI_addtail(&fmodifier_copypaste_buf, fcmN);
+ }
+ else
+ ok = 0;
+ }
+ else
+ copy_fmodifiers(&fmodifier_copypaste_buf, modifiers);
+
+ /* did we succeed? */
+ return ok;
}
/* 'Paste' the F-Modifier(s) from the buffer to the specified list
@@ -746,40 +1049,40 @@ bool ANIM_fmodifiers_copy_to_buf(ListBase *modifiers, bool active)
*/
bool ANIM_fmodifiers_paste_from_buf(ListBase *modifiers, bool replace, FCurve *curve)
{
- FModifier *fcm;
- bool ok = false;
+ FModifier *fcm;
+ bool ok = false;
- /* sanity checks */
- if (modifiers == NULL)
- return 0;
+ /* sanity checks */
+ if (modifiers == NULL)
+ return 0;
- bool was_cyclic = curve && BKE_fcurve_is_cyclic(curve);
+ bool was_cyclic = curve && BKE_fcurve_is_cyclic(curve);
- /* if replacing the list, free the existing modifiers */
- if (replace)
- free_fmodifiers(modifiers);
+ /* if replacing the list, free the existing modifiers */
+ if (replace)
+ free_fmodifiers(modifiers);
- /* now copy over all the modifiers in the buffer to the end of the list */
- for (fcm = fmodifier_copypaste_buf.first; fcm; fcm = fcm->next) {
- /* make a copy of it */
- FModifier *fcmN = copy_fmodifier(fcm);
+ /* now copy over all the modifiers in the buffer to the end of the list */
+ for (fcm = fmodifier_copypaste_buf.first; fcm; fcm = fcm->next) {
+ /* make a copy of it */
+ FModifier *fcmN = copy_fmodifier(fcm);
- fcmN->curve = curve;
+ fcmN->curve = curve;
- /* make sure the new one isn't active, otherwise the list may get several actives */
- fcmN->flag &= ~FMODIFIER_FLAG_ACTIVE;
+ /* make sure the new one isn't active, otherwise the list may get several actives */
+ fcmN->flag &= ~FMODIFIER_FLAG_ACTIVE;
- /* now add it to the end of the list */
- BLI_addtail(modifiers, fcmN);
- ok = 1;
- }
+ /* now add it to the end of the list */
+ BLI_addtail(modifiers, fcmN);
+ ok = 1;
+ }
- /* adding or removing the Cycles modifier requires an update to handles */
- if (curve && BKE_fcurve_is_cyclic(curve) != was_cyclic)
- calchandles_fcurve(curve);
+ /* adding or removing the Cycles modifier requires an update to handles */
+ if (curve && BKE_fcurve_is_cyclic(curve) != was_cyclic)
+ calchandles_fcurve(curve);
- /* did we succeed? */
- return ok;
+ /* did we succeed? */
+ return ok;
}
/* ********************************************** */
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index 19ac0ea18a0..e8c17e10b17 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -21,7 +21,6 @@
* \ingroup edanimation
*/
-
/* System includes ----------------------------------------------------- */
#include <math.h>
@@ -62,60 +61,60 @@
BLI_INLINE bool is_cfra_eq(float a, float b)
{
- return IS_EQT(a, b, BEZT_BINARYSEARCH_THRESH);
+ return IS_EQT(a, b, BEZT_BINARYSEARCH_THRESH);
}
BLI_INLINE bool is_cfra_lt(float a, float b)
{
- return (b - a) > BEZT_BINARYSEARCH_THRESH;
+ return (b - a) > BEZT_BINARYSEARCH_THRESH;
}
/* Comparator callback used for ActKeyColumns and cframe float-value pointer */
/* NOTE: this is exported to other modules that use the ActKeyColumns for finding keyframes */
short compare_ak_cfraPtr(void *node, void *data)
{
- ActKeyColumn *ak = (ActKeyColumn *)node;
- const float *cframe = data;
- float val = *cframe;
+ ActKeyColumn *ak = (ActKeyColumn *)node;
+ const float *cframe = data;
+ float val = *cframe;
- if (is_cfra_eq(val, ak->cfra))
- return 0;
+ if (is_cfra_eq(val, ak->cfra))
+ return 0;
- if (val < ak->cfra)
- return -1;
- else
- return 1;
+ if (val < ak->cfra)
+ return -1;
+ else
+ return 1;
}
/* --------------- */
/* Set of references to three logically adjacent keys. */
typedef struct BezTripleChain {
- /* Current keyframe. */
- BezTriple *cur;
+ /* Current keyframe. */
+ BezTriple *cur;
- /* Logical neighbors. May be NULL. */
- BezTriple *prev, *next;
+ /* Logical neighbors. May be NULL. */
+ BezTriple *prev, *next;
} BezTripleChain;
/* Categorize the interpolation & handle type of the keyframe. */
static eKeyframeHandleDrawOpts bezt_handle_type(BezTriple *bezt)
{
- if (bezt->h1 == HD_AUTO_ANIM && bezt->h2 == HD_AUTO_ANIM) {
- return KEYFRAME_HANDLE_AUTO_CLAMP;
- }
- else if (ELEM(bezt->h1, HD_AUTO_ANIM, HD_AUTO) && ELEM(bezt->h2, HD_AUTO_ANIM, HD_AUTO)) {
- return KEYFRAME_HANDLE_AUTO;
- }
- else if (bezt->h1 == HD_VECT && bezt->h2 == HD_VECT) {
- return KEYFRAME_HANDLE_VECTOR;
- }
- else if (ELEM(HD_FREE, bezt->h1, bezt->h2)) {
- return KEYFRAME_HANDLE_FREE;
- }
- else {
- return KEYFRAME_HANDLE_ALIGNED;
- }
+ if (bezt->h1 == HD_AUTO_ANIM && bezt->h2 == HD_AUTO_ANIM) {
+ return KEYFRAME_HANDLE_AUTO_CLAMP;
+ }
+ else if (ELEM(bezt->h1, HD_AUTO_ANIM, HD_AUTO) && ELEM(bezt->h2, HD_AUTO_ANIM, HD_AUTO)) {
+ return KEYFRAME_HANDLE_AUTO;
+ }
+ else if (bezt->h1 == HD_VECT && bezt->h2 == HD_VECT) {
+ return KEYFRAME_HANDLE_VECTOR;
+ }
+ else if (ELEM(HD_FREE, bezt->h1, bezt->h2)) {
+ return KEYFRAME_HANDLE_FREE;
+ }
+ else {
+ return KEYFRAME_HANDLE_ALIGNED;
+ }
}
/* Determine if the keyframe is an extreme by comparing with neighbors.
@@ -123,113 +122,114 @@ static eKeyframeHandleDrawOpts bezt_handle_type(BezTriple *bezt)
*/
static eKeyframeExtremeDrawOpts bezt_extreme_type(BezTripleChain *chain)
{
- if (chain->prev == NULL && chain->next == NULL) {
- return KEYFRAME_EXTREME_NONE;
- }
-
- /* Keyframe values for the current one and neighbors. */
- float cur_y = chain->cur->vec[1][1];
- float prev_y = cur_y, next_y = cur_y;
-
- if (chain->prev && !IS_EQF(cur_y, chain->prev->vec[1][1])) {
- prev_y = chain->prev->vec[1][1];
- }
- if (chain->next && !IS_EQF(cur_y, chain->next->vec[1][1])) {
- next_y = chain->next->vec[1][1];
- }
-
- /* Static hold. */
- if (prev_y == cur_y && next_y == cur_y) {
- return KEYFRAME_EXTREME_FLAT;
- }
-
- /* Middle of an incline. */
- if ((prev_y < cur_y && next_y > cur_y) || (prev_y > cur_y && next_y < cur_y)) {
- return KEYFRAME_EXTREME_NONE;
- }
-
- /* Bezier handle values for the overshoot check. */
- bool l_bezier = chain->prev && chain->prev->ipo == BEZT_IPO_BEZ;
- bool r_bezier = chain->next && chain->cur->ipo == BEZT_IPO_BEZ;
- float handle_l = l_bezier ? chain->cur->vec[0][1] : cur_y;
- float handle_r = r_bezier ? chain->cur->vec[2][1] : cur_y;
-
- /* Detect extremes. One of the neighbors is allowed to be equal to current. */
- if (prev_y < cur_y || next_y < cur_y) {
- bool is_overshoot = (handle_l > cur_y || handle_r > cur_y);
-
- return KEYFRAME_EXTREME_MAX | (is_overshoot ? KEYFRAME_EXTREME_MIXED : 0);
- }
-
- if (prev_y > cur_y || next_y > cur_y) {
- bool is_overshoot = (handle_l < cur_y || handle_r < cur_y);
-
- return KEYFRAME_EXTREME_MIN | (is_overshoot ? KEYFRAME_EXTREME_MIXED : 0);
- }
-
- return KEYFRAME_EXTREME_NONE;
+ if (chain->prev == NULL && chain->next == NULL) {
+ return KEYFRAME_EXTREME_NONE;
+ }
+
+ /* Keyframe values for the current one and neighbors. */
+ float cur_y = chain->cur->vec[1][1];
+ float prev_y = cur_y, next_y = cur_y;
+
+ if (chain->prev && !IS_EQF(cur_y, chain->prev->vec[1][1])) {
+ prev_y = chain->prev->vec[1][1];
+ }
+ if (chain->next && !IS_EQF(cur_y, chain->next->vec[1][1])) {
+ next_y = chain->next->vec[1][1];
+ }
+
+ /* Static hold. */
+ if (prev_y == cur_y && next_y == cur_y) {
+ return KEYFRAME_EXTREME_FLAT;
+ }
+
+ /* Middle of an incline. */
+ if ((prev_y < cur_y && next_y > cur_y) || (prev_y > cur_y && next_y < cur_y)) {
+ return KEYFRAME_EXTREME_NONE;
+ }
+
+ /* Bezier handle values for the overshoot check. */
+ bool l_bezier = chain->prev && chain->prev->ipo == BEZT_IPO_BEZ;
+ bool r_bezier = chain->next && chain->cur->ipo == BEZT_IPO_BEZ;
+ float handle_l = l_bezier ? chain->cur->vec[0][1] : cur_y;
+ float handle_r = r_bezier ? chain->cur->vec[2][1] : cur_y;
+
+ /* Detect extremes. One of the neighbors is allowed to be equal to current. */
+ if (prev_y < cur_y || next_y < cur_y) {
+ bool is_overshoot = (handle_l > cur_y || handle_r > cur_y);
+
+ return KEYFRAME_EXTREME_MAX | (is_overshoot ? KEYFRAME_EXTREME_MIXED : 0);
+ }
+
+ if (prev_y > cur_y || next_y > cur_y) {
+ bool is_overshoot = (handle_l < cur_y || handle_r < cur_y);
+
+ return KEYFRAME_EXTREME_MIN | (is_overshoot ? KEYFRAME_EXTREME_MIXED : 0);
+ }
+
+ return KEYFRAME_EXTREME_NONE;
}
/* Comparator callback used for ActKeyColumns and BezTripleChain */
static short compare_ak_bezt(void *node, void *data)
{
- BezTripleChain *chain = data;
+ BezTripleChain *chain = data;
- return compare_ak_cfraPtr(node, &chain->cur->vec[1][0]);
+ return compare_ak_cfraPtr(node, &chain->cur->vec[1][0]);
}
/* New node callback used for building ActKeyColumns from BezTripleChain */
static DLRBT_Node *nalloc_ak_bezt(void *data)
{
- ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
- BezTripleChain *chain = data;
- BezTriple *bezt = chain->cur;
+ ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
+ BezTripleChain *chain = data;
+ BezTriple *bezt = chain->cur;
- /* store settings based on state of BezTriple */
- ak->cfra = bezt->vec[1][0];
- ak->sel = BEZT_ISSEL_ANY(bezt) ? SELECT : 0;
- ak->key_type = BEZKEYTYPE(bezt);
- ak->handle_type = bezt_handle_type(bezt);
- ak->extreme_type = bezt_extreme_type(chain);
+ /* store settings based on state of BezTriple */
+ ak->cfra = bezt->vec[1][0];
+ ak->sel = BEZT_ISSEL_ANY(bezt) ? SELECT : 0;
+ ak->key_type = BEZKEYTYPE(bezt);
+ ak->handle_type = bezt_handle_type(bezt);
+ ak->extreme_type = bezt_extreme_type(chain);
- /* count keyframes in this column */
- ak->totkey = 1;
+ /* count keyframes in this column */
+ ak->totkey = 1;
- return (DLRBT_Node *)ak;
+ return (DLRBT_Node *)ak;
}
/* Node updater callback used for building ActKeyColumns from BezTripleChain */
static void nupdate_ak_bezt(void *node, void *data)
{
- ActKeyColumn *ak = node;
- BezTripleChain *chain = data;
- BezTriple *bezt = chain->cur;
-
- /* set selection status and 'touched' status */
- if (BEZT_ISSEL_ANY(bezt)) ak->sel = SELECT;
-
- /* count keyframes in this column */
- ak->totkey++;
-
- /* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
- if (BEZKEYTYPE(bezt) == BEZT_KEYTYPE_KEYFRAME)
- ak->key_type = BEZT_KEYTYPE_KEYFRAME;
-
- /* For interpolation type, select the highest value (enum is sorted). */
- ak->handle_type = MAX2(ak->handle_type, bezt_handle_type(bezt));
-
- /* For extremes, detect when combining different states. */
- char new_extreme = bezt_extreme_type(chain);
-
- if (new_extreme != ak->extreme_type) {
- /* Replace the flat status without adding mixed. */
- if (ak->extreme_type == KEYFRAME_EXTREME_FLAT) {
- ak->extreme_type = new_extreme;
- }
- else if (new_extreme != KEYFRAME_EXTREME_FLAT) {
- ak->extreme_type |= (new_extreme | KEYFRAME_EXTREME_MIXED);
- }
- }
+ ActKeyColumn *ak = node;
+ BezTripleChain *chain = data;
+ BezTriple *bezt = chain->cur;
+
+ /* set selection status and 'touched' status */
+ if (BEZT_ISSEL_ANY(bezt))
+ ak->sel = SELECT;
+
+ /* count keyframes in this column */
+ ak->totkey++;
+
+ /* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
+ if (BEZKEYTYPE(bezt) == BEZT_KEYTYPE_KEYFRAME)
+ ak->key_type = BEZT_KEYTYPE_KEYFRAME;
+
+ /* For interpolation type, select the highest value (enum is sorted). */
+ ak->handle_type = MAX2(ak->handle_type, bezt_handle_type(bezt));
+
+ /* For extremes, detect when combining different states. */
+ char new_extreme = bezt_extreme_type(chain);
+
+ if (new_extreme != ak->extreme_type) {
+ /* Replace the flat status without adding mixed. */
+ if (ak->extreme_type == KEYFRAME_EXTREME_FLAT) {
+ ak->extreme_type = new_extreme;
+ }
+ else if (new_extreme != KEYFRAME_EXTREME_FLAT) {
+ ak->extreme_type |= (new_extreme | KEYFRAME_EXTREME_MIXED);
+ }
+ }
}
/* ......... */
@@ -237,44 +237,45 @@ static void nupdate_ak_bezt(void *node, void *data)
/* Comparator callback used for ActKeyColumns and GPencil frame */
static short compare_ak_gpframe(void *node, void *data)
{
- bGPDframe *gpf = (bGPDframe *)data;
+ bGPDframe *gpf = (bGPDframe *)data;
- float frame = gpf->framenum;
- return compare_ak_cfraPtr(node, &frame);
+ float frame = gpf->framenum;
+ return compare_ak_cfraPtr(node, &frame);
}
/* New node callback used for building ActKeyColumns from GPencil frames */
static DLRBT_Node *nalloc_ak_gpframe(void *data)
{
- ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF");
- bGPDframe *gpf = (bGPDframe *)data;
+ ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF");
+ bGPDframe *gpf = (bGPDframe *)data;
- /* store settings based on state of BezTriple */
- ak->cfra = gpf->framenum;
- ak->sel = (gpf->flag & GP_FRAME_SELECT) ? SELECT : 0;
- ak->key_type = gpf->key_type;
+ /* store settings based on state of BezTriple */
+ ak->cfra = gpf->framenum;
+ ak->sel = (gpf->flag & GP_FRAME_SELECT) ? SELECT : 0;
+ ak->key_type = gpf->key_type;
- /* count keyframes in this column */
- ak->totkey = 1;
+ /* count keyframes in this column */
+ ak->totkey = 1;
- return (DLRBT_Node *)ak;
+ return (DLRBT_Node *)ak;
}
/* Node updater callback used for building ActKeyColumns from GPencil frames */
static void nupdate_ak_gpframe(void *node, void *data)
{
- ActKeyColumn *ak = (ActKeyColumn *)node;
- bGPDframe *gpf = (bGPDframe *)data;
+ ActKeyColumn *ak = (ActKeyColumn *)node;
+ bGPDframe *gpf = (bGPDframe *)data;
- /* set selection status and 'touched' status */
- if (gpf->flag & GP_FRAME_SELECT) ak->sel = SELECT;
+ /* set selection status and 'touched' status */
+ if (gpf->flag & GP_FRAME_SELECT)
+ ak->sel = SELECT;
- /* count keyframes in this column */
- ak->totkey++;
+ /* count keyframes in this column */
+ ak->totkey++;
- /* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
- if (gpf->key_type == BEZT_KEYTYPE_KEYFRAME)
- ak->key_type = BEZT_KEYTYPE_KEYFRAME;
+ /* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
+ if (gpf->key_type == BEZT_KEYTYPE_KEYFRAME)
+ ak->key_type = BEZT_KEYTYPE_KEYFRAME;
}
/* ......... */
@@ -282,193 +283,198 @@ static void nupdate_ak_gpframe(void *node, void *data)
/* Comparator callback used for ActKeyColumns and GPencil frame */
static short compare_ak_masklayshape(void *node, void *data)
{
- MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
+ MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
- float frame = masklay_shape->frame;
- return compare_ak_cfraPtr(node, &frame);
+ float frame = masklay_shape->frame;
+ return compare_ak_cfraPtr(node, &frame);
}
/* New node callback used for building ActKeyColumns from GPencil frames */
static DLRBT_Node *nalloc_ak_masklayshape(void *data)
{
- ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF");
- MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
+ ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF");
+ MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
- /* store settings based on state of BezTriple */
- ak->cfra = masklay_shape->frame;
- ak->sel = (masklay_shape->flag & MASK_SHAPE_SELECT) ? SELECT : 0;
+ /* store settings based on state of BezTriple */
+ ak->cfra = masklay_shape->frame;
+ ak->sel = (masklay_shape->flag & MASK_SHAPE_SELECT) ? SELECT : 0;
- /* count keyframes in this column */
- ak->totkey = 1;
+ /* count keyframes in this column */
+ ak->totkey = 1;
- return (DLRBT_Node *)ak;
+ return (DLRBT_Node *)ak;
}
/* Node updater callback used for building ActKeyColumns from GPencil frames */
static void nupdate_ak_masklayshape(void *node, void *data)
{
- ActKeyColumn *ak = (ActKeyColumn *)node;
- MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
+ ActKeyColumn *ak = (ActKeyColumn *)node;
+ MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
- /* set selection status and 'touched' status */
- if (masklay_shape->flag & MASK_SHAPE_SELECT) ak->sel = SELECT;
+ /* set selection status and 'touched' status */
+ if (masklay_shape->flag & MASK_SHAPE_SELECT)
+ ak->sel = SELECT;
- /* count keyframes in this column */
- ak->totkey++;
+ /* count keyframes in this column */
+ ak->totkey++;
}
-
/* --------------- */
/* Add the given BezTriple to the given 'list' of Keyframes */
static void add_bezt_to_keycolumns_list(DLRBT_Tree *keys, BezTripleChain *bezt)
{
- if (ELEM(NULL, keys, bezt))
- return;
- else
- BLI_dlrbTree_add(keys, compare_ak_bezt, nalloc_ak_bezt, nupdate_ak_bezt, bezt);
+ if (ELEM(NULL, keys, bezt))
+ return;
+ else
+ BLI_dlrbTree_add(keys, compare_ak_bezt, nalloc_ak_bezt, nupdate_ak_bezt, bezt);
}
/* Add the given GPencil Frame to the given 'list' of Keyframes */
static void add_gpframe_to_keycolumns_list(DLRBT_Tree *keys, bGPDframe *gpf)
{
- if (ELEM(NULL, keys, gpf))
- return;
- else
- BLI_dlrbTree_add(keys, compare_ak_gpframe, nalloc_ak_gpframe, nupdate_ak_gpframe, gpf);
+ if (ELEM(NULL, keys, gpf))
+ return;
+ else
+ BLI_dlrbTree_add(keys, compare_ak_gpframe, nalloc_ak_gpframe, nupdate_ak_gpframe, gpf);
}
/* Add the given MaskLayerShape Frame to the given 'list' of Keyframes */
static void add_masklay_to_keycolumns_list(DLRBT_Tree *keys, MaskLayerShape *masklay_shape)
{
- if (ELEM(NULL, keys, masklay_shape))
- return;
- else
- BLI_dlrbTree_add(keys, compare_ak_masklayshape, nalloc_ak_masklayshape, nupdate_ak_masklayshape, masklay_shape);
+ if (ELEM(NULL, keys, masklay_shape))
+ return;
+ else
+ BLI_dlrbTree_add(keys,
+ compare_ak_masklayshape,
+ nalloc_ak_masklayshape,
+ nupdate_ak_masklayshape,
+ masklay_shape);
}
/* ActKeyBlocks (Long Keyframes) ------------------------------------------ */
-static const ActKeyBlockInfo dummy_keyblock = { 0 };
+static const ActKeyBlockInfo dummy_keyblock = {0};
static void compute_keyblock_data(ActKeyBlockInfo *info, BezTriple *prev, BezTriple *beztn)
{
- memset(info, 0, sizeof(ActKeyBlockInfo));
-
- if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD) {
- /* Animator tagged a "moving hold"
- * - Previous key must also be tagged as a moving hold, otherwise
- * we're just dealing with the first of a pair, and we don't
- * want to be creating any phantom holds...
- */
- if (BEZKEYTYPE(prev) == BEZT_KEYTYPE_MOVEHOLD) {
- info->flag |= ACTKEYBLOCK_FLAG_MOVING_HOLD | ACTKEYBLOCK_FLAG_ANY_HOLD;
- }
- }
-
- /* Check for same values...
- * - Handles must have same central value as each other
- * - Handles which control that section of the curve must be constant
- */
- if (IS_EQF(beztn->vec[1][1], prev->vec[1][1])) {
- bool hold;
-
- /* Only check handles in case of actual bezier interpolation. */
- if (prev->ipo == BEZT_IPO_BEZ) {
- hold = IS_EQF(beztn->vec[1][1], beztn->vec[0][1]) && IS_EQF(prev->vec[1][1], prev->vec[2][1]);
- }
- /* This interpolation type induces movement even between identical keys. */
- else {
- hold = !ELEM(prev->ipo, BEZT_IPO_ELASTIC);
- }
-
- if (hold) {
- info->flag |= ACTKEYBLOCK_FLAG_STATIC_HOLD | ACTKEYBLOCK_FLAG_ANY_HOLD;
- }
- }
-
- /* Remember non-bezier interpolation info. */
- if (prev->ipo != BEZT_IPO_BEZ) {
- info->flag |= ACTKEYBLOCK_FLAG_NON_BEZIER;
- }
-
- info->sel = BEZT_ISSEL_ANY(prev) || BEZT_ISSEL_ANY(beztn);
+ memset(info, 0, sizeof(ActKeyBlockInfo));
+
+ if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD) {
+ /* Animator tagged a "moving hold"
+ * - Previous key must also be tagged as a moving hold, otherwise
+ * we're just dealing with the first of a pair, and we don't
+ * want to be creating any phantom holds...
+ */
+ if (BEZKEYTYPE(prev) == BEZT_KEYTYPE_MOVEHOLD) {
+ info->flag |= ACTKEYBLOCK_FLAG_MOVING_HOLD | ACTKEYBLOCK_FLAG_ANY_HOLD;
+ }
+ }
+
+ /* Check for same values...
+ * - Handles must have same central value as each other
+ * - Handles which control that section of the curve must be constant
+ */
+ if (IS_EQF(beztn->vec[1][1], prev->vec[1][1])) {
+ bool hold;
+
+ /* Only check handles in case of actual bezier interpolation. */
+ if (prev->ipo == BEZT_IPO_BEZ) {
+ hold = IS_EQF(beztn->vec[1][1], beztn->vec[0][1]) &&
+ IS_EQF(prev->vec[1][1], prev->vec[2][1]);
+ }
+ /* This interpolation type induces movement even between identical keys. */
+ else {
+ hold = !ELEM(prev->ipo, BEZT_IPO_ELASTIC);
+ }
+
+ if (hold) {
+ info->flag |= ACTKEYBLOCK_FLAG_STATIC_HOLD | ACTKEYBLOCK_FLAG_ANY_HOLD;
+ }
+ }
+
+ /* Remember non-bezier interpolation info. */
+ if (prev->ipo != BEZT_IPO_BEZ) {
+ info->flag |= ACTKEYBLOCK_FLAG_NON_BEZIER;
+ }
+
+ info->sel = BEZT_ISSEL_ANY(prev) || BEZT_ISSEL_ANY(beztn);
}
static void add_keyblock_info(ActKeyColumn *col, const ActKeyBlockInfo *block)
{
- /* New curve and block. */
- if (col->totcurve <= 1 && col->totblock == 0) {
- memcpy(&col->block, block, sizeof(ActKeyBlockInfo));
- }
- /* Existing curve. */
- else {
- col->block.conflict |= (col->block.flag ^ block->flag);
- col->block.flag |= block->flag;
- col->block.sel |= block->sel;
- }
-
- if (block->flag) {
- col->totblock++;
- }
+ /* New curve and block. */
+ if (col->totcurve <= 1 && col->totblock == 0) {
+ memcpy(&col->block, block, sizeof(ActKeyBlockInfo));
+ }
+ /* Existing curve. */
+ else {
+ col->block.conflict |= (col->block.flag ^ block->flag);
+ col->block.flag |= block->flag;
+ col->block.sel |= block->sel;
+ }
+
+ if (block->flag) {
+ col->totblock++;
+ }
}
static void add_bezt_to_keyblocks_list(DLRBT_Tree *keys, BezTriple *bezt, int bezt_len)
{
- ActKeyColumn *col = keys->first;
-
- if (bezt && bezt_len >= 2) {
- ActKeyBlockInfo block;
-
- /* Find the first key column while inserting dummy blocks. */
- for (; col != NULL && is_cfra_lt(col->cfra, bezt[0].vec[1][0]); col = col->next) {
- add_keyblock_info(col, &dummy_keyblock);
- }
-
- BLI_assert(col != NULL);
-
- /* Insert real blocks. */
- for (int v = 1; col != NULL && v < bezt_len; v++, bezt++) {
- /* Wrong order of bezier keys: resync position. */
- if (is_cfra_lt(bezt[1].vec[1][0], bezt[0].vec[1][0])) {
- /* Backtrack to find the right location. */
- if (is_cfra_lt(bezt[1].vec[1][0], col->cfra)) {
- ActKeyColumn *newcol = (ActKeyColumn *)BLI_dlrbTree_search_exact(
- keys, compare_ak_cfraPtr, &bezt[1].vec[1][0]);
-
- if (newcol != NULL) {
- col = newcol;
-
- /* The previous keyblock is garbage too. */
- if (col->prev != NULL) {
- add_keyblock_info(col->prev, &dummy_keyblock);
- }
- }
- else {
- BLI_assert(false);
- }
- }
-
- continue;
- }
-
- /* Normal sequence */
- BLI_assert(is_cfra_eq(col->cfra, bezt[0].vec[1][0]));
-
- compute_keyblock_data(&block, bezt, bezt + 1);
-
- for (; col != NULL && is_cfra_lt(col->cfra, bezt[1].vec[1][0]); col = col->next) {
- add_keyblock_info(col, &block);
- }
-
- BLI_assert(col != NULL);
- }
- }
-
- /* Insert dummy blocks at the end. */
- for (; col != NULL; col = col->next) {
- add_keyblock_info(col, &dummy_keyblock);
- }
+ ActKeyColumn *col = keys->first;
+
+ if (bezt && bezt_len >= 2) {
+ ActKeyBlockInfo block;
+
+ /* Find the first key column while inserting dummy blocks. */
+ for (; col != NULL && is_cfra_lt(col->cfra, bezt[0].vec[1][0]); col = col->next) {
+ add_keyblock_info(col, &dummy_keyblock);
+ }
+
+ BLI_assert(col != NULL);
+
+ /* Insert real blocks. */
+ for (int v = 1; col != NULL && v < bezt_len; v++, bezt++) {
+ /* Wrong order of bezier keys: resync position. */
+ if (is_cfra_lt(bezt[1].vec[1][0], bezt[0].vec[1][0])) {
+ /* Backtrack to find the right location. */
+ if (is_cfra_lt(bezt[1].vec[1][0], col->cfra)) {
+ ActKeyColumn *newcol = (ActKeyColumn *)BLI_dlrbTree_search_exact(
+ keys, compare_ak_cfraPtr, &bezt[1].vec[1][0]);
+
+ if (newcol != NULL) {
+ col = newcol;
+
+ /* The previous keyblock is garbage too. */
+ if (col->prev != NULL) {
+ add_keyblock_info(col->prev, &dummy_keyblock);
+ }
+ }
+ else {
+ BLI_assert(false);
+ }
+ }
+
+ continue;
+ }
+
+ /* Normal sequence */
+ BLI_assert(is_cfra_eq(col->cfra, bezt[0].vec[1][0]));
+
+ compute_keyblock_data(&block, bezt, bezt + 1);
+
+ for (; col != NULL && is_cfra_lt(col->cfra, bezt[1].vec[1][0]); col = col->next) {
+ add_keyblock_info(col, &block);
+ }
+
+ BLI_assert(col != NULL);
+ }
+ }
+
+ /* Insert dummy blocks at the end. */
+ for (; col != NULL; col = col->next) {
+ add_keyblock_info(col, &dummy_keyblock);
+ }
}
/* Walk through columns and propagate blocks and totcurve.
@@ -478,689 +484,756 @@ static void add_bezt_to_keyblocks_list(DLRBT_Tree *keys, BezTriple *bezt, int be
*/
static void update_keyblocks(DLRBT_Tree *keys, BezTriple *bezt, int bezt_len)
{
- /* Recompute the prev/next linked list. */
- BLI_dlrbTree_linkedlist_sync(keys);
-
- /* Find the curve count */
- int max_curve = 0;
-
- for (ActKeyColumn *col = keys->first; col; col = col->next) {
- 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) {
- /* Pre-existing column. */
- if (col->totcurve > 0) {
- prev_ready = col;
- }
- /* Newly inserted column, so copy block data from previous. */
- else if (prev_ready != NULL) {
- col->totblock = prev_ready->totblock;
- memcpy(&col->block, &prev_ready->block, sizeof(ActKeyBlockInfo));
- }
-
- col->totcurve = max_curve + 1;
- }
-
- /* Add blocks on top */
- add_bezt_to_keyblocks_list(keys, bezt, bezt_len);
+ /* Recompute the prev/next linked list. */
+ BLI_dlrbTree_linkedlist_sync(keys);
+
+ /* Find the curve count */
+ int max_curve = 0;
+
+ for (ActKeyColumn *col = keys->first; col; col = col->next) {
+ 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) {
+ /* Pre-existing column. */
+ if (col->totcurve > 0) {
+ prev_ready = col;
+ }
+ /* Newly inserted column, so copy block data from previous. */
+ else if (prev_ready != NULL) {
+ col->totblock = prev_ready->totblock;
+ memcpy(&col->block, &prev_ready->block, sizeof(ActKeyBlockInfo));
+ }
+
+ col->totcurve = max_curve + 1;
+ }
+
+ /* Add blocks on top */
+ add_bezt_to_keyblocks_list(keys, bezt, bezt_len);
}
/* --------- */
bool actkeyblock_is_valid(ActKeyColumn *ac)
{
- return ac != NULL && ac->next != NULL && ac->totblock > 0;
+ return ac != NULL && ac->next != NULL && ac->totblock > 0;
}
/* Checks if ActKeyBlock should exist... */
int actkeyblock_get_valid_hold(ActKeyColumn *ac)
{
- /* check that block is valid */
- if (!actkeyblock_is_valid(ac))
- return 0;
+ /* check that block is valid */
+ if (!actkeyblock_is_valid(ac))
+ return 0;
- const int hold_mask = (ACTKEYBLOCK_FLAG_ANY_HOLD | ACTKEYBLOCK_FLAG_STATIC_HOLD | ACTKEYBLOCK_FLAG_ANY_HOLD);
- return (ac->block.flag & ~ac->block.conflict) & hold_mask;
+ const int hold_mask = (ACTKEYBLOCK_FLAG_ANY_HOLD | ACTKEYBLOCK_FLAG_STATIC_HOLD |
+ ACTKEYBLOCK_FLAG_ANY_HOLD);
+ return (ac->block.flag & ~ac->block.conflict) & hold_mask;
}
/* *************************** Keyframe Drawing *************************** */
-void draw_keyframe_shape(float x, float y, float size, bool sel, 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, short handle_type, short extreme_type)
+void draw_keyframe_shape(float x,
+ float y,
+ float size,
+ bool sel,
+ 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,
+ short handle_type,
+ short extreme_type)
{
- bool draw_fill = ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH);
- bool draw_outline = ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH);
-
- BLI_assert(draw_fill || draw_outline);
-
- /* tweak size of keyframe shape according to type of keyframe
- * - 'proper' keyframes have key_type = 0, so get drawn at full size
- */
- switch (key_type) {
- case BEZT_KEYTYPE_KEYFRAME: /* must be full size */
- break;
-
- case BEZT_KEYTYPE_BREAKDOWN: /* slightly smaller than normal keyframe */
- size *= 0.85f;
- break;
-
- case BEZT_KEYTYPE_MOVEHOLD: /* slightly smaller than normal keyframes
- * (but by less than for breakdowns) */
- size *= 0.925f;
- break;
-
- case BEZT_KEYTYPE_EXTREME: /* slightly larger */
- size *= 1.2f;
- break;
-
- default:
- size -= 0.8f * key_type;
- }
-
- unsigned char fill_col[4];
- unsigned char outline_col[4];
- unsigned int flags = 0;
-
- /* draw! */
- if (draw_fill) {
- /* get interior colors from theme (for selected and unselected only) */
- switch (key_type) {
- case BEZT_KEYTYPE_BREAKDOWN: /* bluish frames (default theme) */
- UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_BREAKDOWN_SELECT : TH_KEYTYPE_BREAKDOWN, fill_col);
- break;
- case BEZT_KEYTYPE_EXTREME: /* reddish frames (default theme) */
- UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_EXTREME_SELECT : TH_KEYTYPE_EXTREME, fill_col);
- break;
- case BEZT_KEYTYPE_JITTER: /* greenish frames (default theme) */
- UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_JITTER_SELECT : TH_KEYTYPE_JITTER, fill_col);
- break;
- case BEZT_KEYTYPE_MOVEHOLD: /* similar to traditional keyframes, but different... */
- UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_MOVEHOLD_SELECT : TH_KEYTYPE_MOVEHOLD, fill_col);
- break;
- case BEZT_KEYTYPE_KEYFRAME: /* traditional yellowish frames (default theme) */
- default:
- UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_KEYFRAME_SELECT : TH_KEYTYPE_KEYFRAME, fill_col);
- }
-
- /* NOTE: we don't use the straight alpha from the theme, or else effects such as
- * graying out protected/muted channels doesn't work correctly!
- */
- fill_col[3] *= alpha;
-
- if (!draw_outline) {
- /* force outline color to match */
- outline_col[0] = fill_col[0];
- outline_col[1] = fill_col[1];
- outline_col[2] = fill_col[2];
- outline_col[3] = fill_col[3];
- }
- }
-
- if (draw_outline) {
- /* exterior - black frame */
- UI_GetThemeColor4ubv(sel ? TH_KEYBORDER_SELECT : TH_KEYBORDER, outline_col);
- outline_col[3] *= alpha;
-
- if (!draw_fill) {
- /* fill color needs to be (outline.rgb, 0) */
- fill_col[0] = outline_col[0];
- fill_col[1] = outline_col[1];
- fill_col[2] = outline_col[2];
- fill_col[3] = 0;
- }
-
- /* Handle type to outline shape. */
- switch (handle_type) {
- case KEYFRAME_HANDLE_AUTO_CLAMP: flags = 0x2; break; /* circle */
- case KEYFRAME_HANDLE_AUTO: flags = 0x12; break; /* circle with dot */
- case KEYFRAME_HANDLE_VECTOR: flags = 0xC; break; /* square */
- case KEYFRAME_HANDLE_ALIGNED: flags = 0x5; break; /* clipped diamond */
-
- case KEYFRAME_HANDLE_FREE:
- default:
- flags = 1; /* diamond */
- }
-
- /* Extreme type to arrow-like shading. */
- if (extreme_type & KEYFRAME_EXTREME_MAX) {
- flags |= 0x100;
- }
- if (extreme_type & KEYFRAME_EXTREME_MIN) {
- flags |= 0x200;
- }
- if (extreme_type & KEYFRAME_EXTREME_MIXED) {
- flags |= 0x400;
- }
- }
-
- immAttr1f(size_id, size);
- immAttr4ubv(color_id, fill_col);
- immAttr4ubv(outline_color_id, outline_col);
- immAttr1u(flags_id, flags);
- immVertex2f(pos_id, x, y);
+ bool draw_fill = ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH);
+ bool draw_outline = ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH);
+
+ BLI_assert(draw_fill || draw_outline);
+
+ /* tweak size of keyframe shape according to type of keyframe
+ * - 'proper' keyframes have key_type = 0, so get drawn at full size
+ */
+ switch (key_type) {
+ case BEZT_KEYTYPE_KEYFRAME: /* must be full size */
+ break;
+
+ case BEZT_KEYTYPE_BREAKDOWN: /* slightly smaller than normal keyframe */
+ size *= 0.85f;
+ break;
+
+ case BEZT_KEYTYPE_MOVEHOLD: /* slightly smaller than normal keyframes
+ * (but by less than for breakdowns) */
+ size *= 0.925f;
+ break;
+
+ case BEZT_KEYTYPE_EXTREME: /* slightly larger */
+ size *= 1.2f;
+ break;
+
+ default:
+ size -= 0.8f * key_type;
+ }
+
+ unsigned char fill_col[4];
+ unsigned char outline_col[4];
+ unsigned int flags = 0;
+
+ /* draw! */
+ if (draw_fill) {
+ /* get interior colors from theme (for selected and unselected only) */
+ switch (key_type) {
+ case BEZT_KEYTYPE_BREAKDOWN: /* bluish frames (default theme) */
+ UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_BREAKDOWN_SELECT : TH_KEYTYPE_BREAKDOWN, fill_col);
+ break;
+ case BEZT_KEYTYPE_EXTREME: /* reddish frames (default theme) */
+ UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_EXTREME_SELECT : TH_KEYTYPE_EXTREME, fill_col);
+ break;
+ case BEZT_KEYTYPE_JITTER: /* greenish frames (default theme) */
+ UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_JITTER_SELECT : TH_KEYTYPE_JITTER, fill_col);
+ break;
+ case BEZT_KEYTYPE_MOVEHOLD: /* similar to traditional keyframes, but different... */
+ UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_MOVEHOLD_SELECT : TH_KEYTYPE_MOVEHOLD, fill_col);
+ break;
+ case BEZT_KEYTYPE_KEYFRAME: /* traditional yellowish frames (default theme) */
+ default:
+ UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_KEYFRAME_SELECT : TH_KEYTYPE_KEYFRAME, fill_col);
+ }
+
+ /* NOTE: we don't use the straight alpha from the theme, or else effects such as
+ * graying out protected/muted channels doesn't work correctly!
+ */
+ fill_col[3] *= alpha;
+
+ if (!draw_outline) {
+ /* force outline color to match */
+ outline_col[0] = fill_col[0];
+ outline_col[1] = fill_col[1];
+ outline_col[2] = fill_col[2];
+ outline_col[3] = fill_col[3];
+ }
+ }
+
+ if (draw_outline) {
+ /* exterior - black frame */
+ UI_GetThemeColor4ubv(sel ? TH_KEYBORDER_SELECT : TH_KEYBORDER, outline_col);
+ outline_col[3] *= alpha;
+
+ if (!draw_fill) {
+ /* fill color needs to be (outline.rgb, 0) */
+ fill_col[0] = outline_col[0];
+ fill_col[1] = outline_col[1];
+ fill_col[2] = outline_col[2];
+ fill_col[3] = 0;
+ }
+
+ /* Handle type to outline shape. */
+ switch (handle_type) {
+ case KEYFRAME_HANDLE_AUTO_CLAMP:
+ flags = 0x2;
+ break; /* circle */
+ case KEYFRAME_HANDLE_AUTO:
+ flags = 0x12;
+ break; /* circle with dot */
+ case KEYFRAME_HANDLE_VECTOR:
+ flags = 0xC;
+ break; /* square */
+ case KEYFRAME_HANDLE_ALIGNED:
+ flags = 0x5;
+ break; /* clipped diamond */
+
+ case KEYFRAME_HANDLE_FREE:
+ default:
+ flags = 1; /* diamond */
+ }
+
+ /* Extreme type to arrow-like shading. */
+ if (extreme_type & KEYFRAME_EXTREME_MAX) {
+ flags |= 0x100;
+ }
+ if (extreme_type & KEYFRAME_EXTREME_MIN) {
+ flags |= 0x200;
+ }
+ if (extreme_type & KEYFRAME_EXTREME_MIXED) {
+ flags |= 0x400;
+ }
+ }
+
+ immAttr1f(size_id, size);
+ immAttr4ubv(color_id, fill_col);
+ immAttr4ubv(outline_color_id, outline_col);
+ immAttr1u(flags_id, flags);
+ immVertex2f(pos_id, x, y);
}
-static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, float ypos, float yscale_fac, bool channelLocked, int saction_flag)
+static void draw_keylist(View2D *v2d,
+ DLRBT_Tree *keys,
+ float ypos,
+ float yscale_fac,
+ bool channelLocked,
+ int saction_flag)
{
- const float icon_sz = U.widget_unit * 0.5f * yscale_fac;
- const float half_icon_sz = 0.5f * icon_sz;
- const float smaller_sz = 0.35f * icon_sz;
- const float ipo_sz = 0.1f * icon_sz;
-
- GPU_blend(true);
-
- /* locked channels are less strongly shown, as feedback for locked channels in DopeSheet */
- /* TODO: allow this opacity factor to be themed? */
- float alpha = channelLocked ? 0.25f : 1.0f;
-
- /* Show interpolation and handle type? */
- bool show_ipo = (saction_flag & SACTION_SHOW_INTERPOLATION) != 0;
-
- /* draw keyblocks */
- if (keys) {
- float sel_color[4], unsel_color[4];
- float sel_mhcol[4], unsel_mhcol[4];
- float ipo_color[4], ipo_color_mix[4];
-
- /* cache colours first */
- UI_GetThemeColor4fv(TH_STRIP_SELECT, sel_color);
- UI_GetThemeColor4fv(TH_STRIP, unsel_color);
- UI_GetThemeColor4fv(TH_DOPESHEET_IPOLINE, ipo_color);
-
- sel_color[3] *= alpha;
- unsel_color[3] *= alpha;
- ipo_color[3] *= alpha;
-
- copy_v4_v4(sel_mhcol, sel_color);
- sel_mhcol[3] *= 0.8f;
- copy_v4_v4(unsel_mhcol, unsel_color);
- unsel_mhcol[3] *= 0.8f;
- copy_v4_v4(ipo_color_mix, ipo_color);
- ipo_color_mix[3] *= 0.5f;
-
- uint block_len = 0;
- for (ActKeyColumn *ab = keys->first; ab; ab = ab->next) {
- if (actkeyblock_get_valid_hold(ab)) {
- block_len++;
- }
- if (show_ipo && actkeyblock_is_valid(ab) && (ab->block.flag & ACTKEYBLOCK_FLAG_NON_BEZIER)) {
- block_len++;
- }
- }
-
- if (block_len > 0) {
- GPUVertFormat *format = immVertexFormat();
- uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
-
- immBegin(GPU_PRIM_TRIS, 6 * block_len);
- for (ActKeyColumn *ab = keys->first; ab; ab = ab->next) {
- int valid_hold = actkeyblock_get_valid_hold(ab);
- if (valid_hold != 0) {
- if ((valid_hold & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) {
- /* draw "moving hold" long-keyframe block - slightly smaller */
- immRectf_fast_with_color(pos_id, color_id,
- ab->cfra, ypos - smaller_sz, ab->next->cfra, ypos + smaller_sz,
- (ab->block.sel) ? sel_mhcol : unsel_mhcol);
- }
- else {
- /* draw standard long-keyframe block */
- immRectf_fast_with_color(pos_id, color_id,
- ab->cfra, ypos - half_icon_sz, ab->next->cfra, ypos + half_icon_sz,
- (ab->block.sel) ? sel_color : unsel_color);
- }
- }
- if (show_ipo && actkeyblock_is_valid(ab) && (ab->block.flag & ACTKEYBLOCK_FLAG_NON_BEZIER)) {
- /* draw an interpolation line */
- immRectf_fast_with_color(pos_id, color_id,
- ab->cfra, ypos - ipo_sz, ab->next->cfra, ypos + ipo_sz,
- (ab->block.conflict & ACTKEYBLOCK_FLAG_NON_BEZIER) ? ipo_color_mix : ipo_color);
- }
- }
- immEnd();
- immUnbindProgram();
- }
- }
-
- if (keys) {
- /* count keys */
- uint key_len = 0;
- for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) {
- /* optimization: if keyframe doesn't appear within 5 units (screenspace) in visible area, don't draw
- * - this might give some improvements, since we current have to flip between view/region matrices
- */
- if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax))
- key_len++;
- }
-
- if (key_len > 0) {
- /* draw keys */
- GPUVertFormat *format = immVertexFormat();
- uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- uint outline_color_id = GPU_vertformat_attr_add(format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
- immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
- GPU_enable_program_point_size();
- immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
- immBegin(GPU_PRIM_POINTS, key_len);
-
- short handle_type = KEYFRAME_HANDLE_NONE, extreme_type = KEYFRAME_EXTREME_NONE;
-
- for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) {
- if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax)) {
- if (show_ipo) {
- handle_type = ak->handle_type;
- }
- if (saction_flag & SACTION_SHOW_EXTREMES) {
- extreme_type = ak->extreme_type;
- }
-
- draw_keyframe_shape(ak->cfra, ypos, icon_sz, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, alpha,
- pos_id, size_id, color_id, outline_color_id, flags_id, handle_type, extreme_type);
- }
- }
-
- immEnd();
- GPU_disable_program_point_size();
- immUnbindProgram();
- }
- }
-
- GPU_blend(false);
+ const float icon_sz = U.widget_unit * 0.5f * yscale_fac;
+ const float half_icon_sz = 0.5f * icon_sz;
+ const float smaller_sz = 0.35f * icon_sz;
+ const float ipo_sz = 0.1f * icon_sz;
+
+ GPU_blend(true);
+
+ /* locked channels are less strongly shown, as feedback for locked channels in DopeSheet */
+ /* TODO: allow this opacity factor to be themed? */
+ float alpha = channelLocked ? 0.25f : 1.0f;
+
+ /* Show interpolation and handle type? */
+ bool show_ipo = (saction_flag & SACTION_SHOW_INTERPOLATION) != 0;
+
+ /* draw keyblocks */
+ if (keys) {
+ float sel_color[4], unsel_color[4];
+ float sel_mhcol[4], unsel_mhcol[4];
+ float ipo_color[4], ipo_color_mix[4];
+
+ /* cache colours first */
+ UI_GetThemeColor4fv(TH_STRIP_SELECT, sel_color);
+ UI_GetThemeColor4fv(TH_STRIP, unsel_color);
+ UI_GetThemeColor4fv(TH_DOPESHEET_IPOLINE, ipo_color);
+
+ sel_color[3] *= alpha;
+ unsel_color[3] *= alpha;
+ ipo_color[3] *= alpha;
+
+ copy_v4_v4(sel_mhcol, sel_color);
+ sel_mhcol[3] *= 0.8f;
+ copy_v4_v4(unsel_mhcol, unsel_color);
+ unsel_mhcol[3] *= 0.8f;
+ copy_v4_v4(ipo_color_mix, ipo_color);
+ ipo_color_mix[3] *= 0.5f;
+
+ uint block_len = 0;
+ for (ActKeyColumn *ab = keys->first; ab; ab = ab->next) {
+ if (actkeyblock_get_valid_hold(ab)) {
+ block_len++;
+ }
+ if (show_ipo && actkeyblock_is_valid(ab) && (ab->block.flag & ACTKEYBLOCK_FLAG_NON_BEZIER)) {
+ block_len++;
+ }
+ }
+
+ if (block_len > 0) {
+ GPUVertFormat *format = immVertexFormat();
+ uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
+ immBegin(GPU_PRIM_TRIS, 6 * block_len);
+ for (ActKeyColumn *ab = keys->first; ab; ab = ab->next) {
+ int valid_hold = actkeyblock_get_valid_hold(ab);
+ if (valid_hold != 0) {
+ if ((valid_hold & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) {
+ /* draw "moving hold" long-keyframe block - slightly smaller */
+ immRectf_fast_with_color(pos_id,
+ color_id,
+ ab->cfra,
+ ypos - smaller_sz,
+ ab->next->cfra,
+ ypos + smaller_sz,
+ (ab->block.sel) ? sel_mhcol : unsel_mhcol);
+ }
+ else {
+ /* draw standard long-keyframe block */
+ immRectf_fast_with_color(pos_id,
+ color_id,
+ ab->cfra,
+ ypos - half_icon_sz,
+ ab->next->cfra,
+ ypos + half_icon_sz,
+ (ab->block.sel) ? sel_color : unsel_color);
+ }
+ }
+ if (show_ipo && actkeyblock_is_valid(ab) &&
+ (ab->block.flag & ACTKEYBLOCK_FLAG_NON_BEZIER)) {
+ /* draw an interpolation line */
+ immRectf_fast_with_color(
+ pos_id,
+ color_id,
+ ab->cfra,
+ ypos - ipo_sz,
+ ab->next->cfra,
+ ypos + ipo_sz,
+ (ab->block.conflict & ACTKEYBLOCK_FLAG_NON_BEZIER) ? ipo_color_mix : ipo_color);
+ }
+ }
+ immEnd();
+ immUnbindProgram();
+ }
+ }
+
+ if (keys) {
+ /* count keys */
+ uint key_len = 0;
+ for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) {
+ /* optimization: if keyframe doesn't appear within 5 units (screenspace) in visible area, don't draw
+ * - this might give some improvements, since we current have to flip between view/region matrices
+ */
+ if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax))
+ key_len++;
+ }
+
+ if (key_len > 0) {
+ /* draw keys */
+ GPUVertFormat *format = immVertexFormat();
+ uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uint color_id = GPU_vertformat_attr_add(
+ format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ uint outline_color_id = GPU_vertformat_attr_add(
+ format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ GPU_enable_program_point_size();
+ immUniform2f(
+ "ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
+ immBegin(GPU_PRIM_POINTS, key_len);
+
+ short handle_type = KEYFRAME_HANDLE_NONE, extreme_type = KEYFRAME_EXTREME_NONE;
+
+ for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) {
+ if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax)) {
+ if (show_ipo) {
+ handle_type = ak->handle_type;
+ }
+ if (saction_flag & SACTION_SHOW_EXTREMES) {
+ extreme_type = ak->extreme_type;
+ }
+
+ draw_keyframe_shape(ak->cfra,
+ ypos,
+ icon_sz,
+ (ak->sel & SELECT),
+ ak->key_type,
+ KEYFRAME_SHAPE_BOTH,
+ alpha,
+ pos_id,
+ size_id,
+ color_id,
+ outline_color_id,
+ flags_id,
+ handle_type,
+ extreme_type);
+ }
+ }
+
+ immEnd();
+ GPU_disable_program_point_size();
+ immUnbindProgram();
+ }
+ }
+
+ GPU_blend(false);
}
/* *************************** Channel Drawing Funcs *************************** */
-void draw_summary_channel(View2D *v2d, bAnimContext *ac, float ypos, float yscale_fac, int saction_flag)
+void draw_summary_channel(
+ View2D *v2d, bAnimContext *ac, float ypos, float yscale_fac, int saction_flag)
{
- DLRBT_Tree keys;
+ DLRBT_Tree keys;
- saction_flag &= ~SACTION_SHOW_EXTREMES;
+ saction_flag &= ~SACTION_SHOW_EXTREMES;
- BLI_dlrbTree_init(&keys);
+ BLI_dlrbTree_init(&keys);
- summary_to_keylist(ac, &keys, saction_flag);
+ summary_to_keylist(ac, &keys, saction_flag);
- draw_keylist(v2d, &keys, ypos, yscale_fac, false, saction_flag);
+ draw_keylist(v2d, &keys, ypos, yscale_fac, false, saction_flag);
- BLI_dlrbTree_free(&keys);
+ BLI_dlrbTree_free(&keys);
}
-void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos, float yscale_fac, int saction_flag)
+void draw_scene_channel(
+ View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos, float yscale_fac, int saction_flag)
{
- DLRBT_Tree keys;
+ DLRBT_Tree keys;
- saction_flag &= ~SACTION_SHOW_EXTREMES;
+ saction_flag &= ~SACTION_SHOW_EXTREMES;
- BLI_dlrbTree_init(&keys);
+ BLI_dlrbTree_init(&keys);
- scene_to_keylist(ads, sce, &keys, saction_flag);
+ scene_to_keylist(ads, sce, &keys, saction_flag);
- draw_keylist(v2d, &keys, ypos, yscale_fac, false, saction_flag);
+ draw_keylist(v2d, &keys, ypos, yscale_fac, false, saction_flag);
- BLI_dlrbTree_free(&keys);
+ BLI_dlrbTree_free(&keys);
}
-void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos, float yscale_fac, int saction_flag)
+void draw_object_channel(
+ View2D *v2d, bDopeSheet *ads, Object *ob, float ypos, float yscale_fac, int saction_flag)
{
- DLRBT_Tree keys;
+ DLRBT_Tree keys;
- saction_flag &= ~SACTION_SHOW_EXTREMES;
+ saction_flag &= ~SACTION_SHOW_EXTREMES;
- BLI_dlrbTree_init(&keys);
+ BLI_dlrbTree_init(&keys);
- ob_to_keylist(ads, ob, &keys, saction_flag);
+ ob_to_keylist(ads, ob, &keys, saction_flag);
- draw_keylist(v2d, &keys, ypos, yscale_fac, false, saction_flag);
+ draw_keylist(v2d, &keys, ypos, yscale_fac, false, saction_flag);
- BLI_dlrbTree_free(&keys);
+ BLI_dlrbTree_free(&keys);
}
-void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos, float yscale_fac, int saction_flag)
+void draw_fcurve_channel(
+ View2D *v2d, AnimData *adt, FCurve *fcu, float ypos, float yscale_fac, int saction_flag)
{
- DLRBT_Tree keys;
+ DLRBT_Tree keys;
- bool locked = (fcu->flag & FCURVE_PROTECTED) ||
- ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
- ((adt && adt->action) && ID_IS_LINKED(adt->action));
+ bool locked = (fcu->flag & FCURVE_PROTECTED) ||
+ ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
+ ((adt && adt->action) && ID_IS_LINKED(adt->action));
- BLI_dlrbTree_init(&keys);
+ BLI_dlrbTree_init(&keys);
- fcurve_to_keylist(adt, fcu, &keys, saction_flag);
+ fcurve_to_keylist(adt, fcu, &keys, saction_flag);
- draw_keylist(v2d, &keys, ypos, yscale_fac, locked, saction_flag);
+ draw_keylist(v2d, &keys, ypos, yscale_fac, locked, saction_flag);
- BLI_dlrbTree_free(&keys);
+ BLI_dlrbTree_free(&keys);
}
-void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos, float yscale_fac, int saction_flag)
+void draw_agroup_channel(
+ View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos, float yscale_fac, int saction_flag)
{
- DLRBT_Tree keys;
+ DLRBT_Tree keys;
- bool locked = (agrp->flag & AGRP_PROTECTED) ||
- ((adt && adt->action) && ID_IS_LINKED(adt->action));
+ bool locked = (agrp->flag & AGRP_PROTECTED) ||
+ ((adt && adt->action) && ID_IS_LINKED(adt->action));
- BLI_dlrbTree_init(&keys);
+ BLI_dlrbTree_init(&keys);
- agroup_to_keylist(adt, agrp, &keys, saction_flag);
+ agroup_to_keylist(adt, agrp, &keys, saction_flag);
- draw_keylist(v2d, &keys, ypos, yscale_fac, locked, saction_flag);
+ draw_keylist(v2d, &keys, ypos, yscale_fac, locked, saction_flag);
- BLI_dlrbTree_free(&keys);
+ BLI_dlrbTree_free(&keys);
}
-void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos, float yscale_fac, int saction_flag)
+void draw_action_channel(
+ View2D *v2d, AnimData *adt, bAction *act, float ypos, float yscale_fac, int saction_flag)
{
- DLRBT_Tree keys;
+ DLRBT_Tree keys;
- bool locked = (act && ID_IS_LINKED(act));
+ bool locked = (act && ID_IS_LINKED(act));
- saction_flag &= ~SACTION_SHOW_EXTREMES;
+ saction_flag &= ~SACTION_SHOW_EXTREMES;
- BLI_dlrbTree_init(&keys);
+ BLI_dlrbTree_init(&keys);
- action_to_keylist(adt, act, &keys, saction_flag);
+ action_to_keylist(adt, act, &keys, saction_flag);
- draw_keylist(v2d, &keys, ypos, yscale_fac, locked, saction_flag);
+ draw_keylist(v2d, &keys, ypos, yscale_fac, locked, saction_flag);
- BLI_dlrbTree_free(&keys);
+ BLI_dlrbTree_free(&keys);
}
-void draw_gpencil_channel(View2D *v2d, bDopeSheet *ads, bGPdata *gpd, float ypos, float yscale_fac, int saction_flag)
+void draw_gpencil_channel(
+ View2D *v2d, bDopeSheet *ads, bGPdata *gpd, float ypos, float yscale_fac, int saction_flag)
{
- DLRBT_Tree keys;
+ DLRBT_Tree keys;
- saction_flag &= ~SACTION_SHOW_EXTREMES;
+ saction_flag &= ~SACTION_SHOW_EXTREMES;
- BLI_dlrbTree_init(&keys);
+ BLI_dlrbTree_init(&keys);
- gpencil_to_keylist(ads, gpd, &keys, false);
+ gpencil_to_keylist(ads, gpd, &keys, false);
- draw_keylist(v2d, &keys, ypos, yscale_fac, false, saction_flag);
+ draw_keylist(v2d, &keys, ypos, yscale_fac, false, saction_flag);
- BLI_dlrbTree_free(&keys);
+ BLI_dlrbTree_free(&keys);
}
-void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos, float yscale_fac, int saction_flag)
+void draw_gpl_channel(
+ View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos, float yscale_fac, int saction_flag)
{
- DLRBT_Tree keys;
+ DLRBT_Tree keys;
- bool locked = (gpl->flag & GP_LAYER_LOCKED) != 0;
+ bool locked = (gpl->flag & GP_LAYER_LOCKED) != 0;
- BLI_dlrbTree_init(&keys);
+ BLI_dlrbTree_init(&keys);
- gpl_to_keylist(ads, gpl, &keys);
+ gpl_to_keylist(ads, gpl, &keys);
- draw_keylist(v2d, &keys, ypos, yscale_fac, locked, saction_flag);
+ draw_keylist(v2d, &keys, ypos, yscale_fac, locked, saction_flag);
- BLI_dlrbTree_free(&keys);
+ BLI_dlrbTree_free(&keys);
}
-void draw_masklay_channel(View2D *v2d, bDopeSheet *ads, MaskLayer *masklay, float ypos, float yscale_fac, int saction_flag)
+void draw_masklay_channel(View2D *v2d,
+ bDopeSheet *ads,
+ MaskLayer *masklay,
+ float ypos,
+ float yscale_fac,
+ int saction_flag)
{
- DLRBT_Tree keys;
+ DLRBT_Tree keys;
- bool locked = (masklay->flag & MASK_LAYERFLAG_LOCKED) != 0;
+ bool locked = (masklay->flag & MASK_LAYERFLAG_LOCKED) != 0;
- BLI_dlrbTree_init(&keys);
+ BLI_dlrbTree_init(&keys);
- mask_to_keylist(ads, masklay, &keys);
+ mask_to_keylist(ads, masklay, &keys);
- draw_keylist(v2d, &keys, ypos, yscale_fac, locked, saction_flag);
+ draw_keylist(v2d, &keys, ypos, yscale_fac, locked, saction_flag);
- BLI_dlrbTree_free(&keys);
+ BLI_dlrbTree_free(&keys);
}
/* *************************** Keyframe List Conversions *************************** */
void summary_to_keylist(bAnimContext *ac, DLRBT_Tree *keys, int saction_flag)
{
- if (ac) {
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* get F-Curves to take keyframes from */
- filter = ANIMFILTER_DATA_VISIBLE;
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* loop through each F-Curve, grabbing the keyframes */
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* Why not use all #eAnim_KeyType here?
- * All of the other key types are actually "summaries" themselves,
- * and will just end up duplicating stuff that comes up through
- * standard filtering of just F-Curves. Given the way that these work,
- * there isn't really any benefit at all from including them. - Aligorith */
-
- switch (ale->datatype) {
- case ALE_FCURVE:
- fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag);
- break;
- case ALE_MASKLAY:
- mask_to_keylist(ac->ads, ale->data, keys);
- break;
- case ALE_GPFRAME:
- gpl_to_keylist(ac->ads, ale->data, keys);
- break;
- default:
- // printf("%s: datatype %d unhandled\n", __func__, ale->datatype);
- break;
- }
- }
-
- ANIM_animdata_freelist(&anim_data);
- }
+ if (ac) {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get F-Curves to take keyframes from */
+ filter = ANIMFILTER_DATA_VISIBLE;
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through each F-Curve, grabbing the keyframes */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* Why not use all #eAnim_KeyType here?
+ * All of the other key types are actually "summaries" themselves,
+ * and will just end up duplicating stuff that comes up through
+ * standard filtering of just F-Curves. Given the way that these work,
+ * there isn't really any benefit at all from including them. - Aligorith */
+
+ switch (ale->datatype) {
+ case ALE_FCURVE:
+ fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag);
+ break;
+ case ALE_MASKLAY:
+ mask_to_keylist(ac->ads, ale->data, keys);
+ break;
+ case ALE_GPFRAME:
+ gpl_to_keylist(ac->ads, ale->data, keys);
+ break;
+ default:
+ // printf("%s: datatype %d unhandled\n", __func__, ale->datatype);
+ break;
+ }
+ }
+
+ ANIM_animdata_freelist(&anim_data);
+ }
}
void scene_to_keylist(bDopeSheet *ads, Scene *sce, DLRBT_Tree *keys, int saction_flag)
{
- bAnimContext ac = {NULL};
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ bAnimContext ac = {NULL};
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- bAnimListElem dummychan = {NULL};
+ bAnimListElem dummychan = {NULL};
- if (sce == NULL)
- return;
+ if (sce == NULL)
+ return;
- /* create a dummy wrapper data to work with */
- dummychan.type = ANIMTYPE_SCENE;
- dummychan.data = sce;
- dummychan.id = &sce->id;
- dummychan.adt = sce->adt;
+ /* create a dummy wrapper data to work with */
+ dummychan.type = ANIMTYPE_SCENE;
+ dummychan.data = sce;
+ dummychan.id = &sce->id;
+ dummychan.adt = sce->adt;
- ac.ads = ads;
- ac.data = &dummychan;
- ac.datatype = ANIMCONT_CHANNEL;
+ ac.ads = ads;
+ ac.data = &dummychan;
+ ac.datatype = ANIMCONT_CHANNEL;
- /* get F-Curves to take keyframes from */
- filter = ANIMFILTER_DATA_VISIBLE; // curves only
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* get F-Curves to take keyframes from */
+ filter = ANIMFILTER_DATA_VISIBLE; // curves only
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* loop through each F-Curve, grabbing the keyframes */
- for (ale = anim_data.first; ale; ale = ale->next)
- fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag);
+ /* loop through each F-Curve, grabbing the keyframes */
+ for (ale = anim_data.first; ale; ale = ale->next)
+ fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag);
- ANIM_animdata_freelist(&anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, int saction_flag)
{
- bAnimContext ac = {NULL};
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ bAnimContext ac = {NULL};
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- bAnimListElem dummychan = {NULL};
- Base dummybase = {NULL};
+ bAnimListElem dummychan = {NULL};
+ Base dummybase = {NULL};
- if (ob == NULL)
- return;
+ if (ob == NULL)
+ return;
- /* create a dummy wrapper data to work with */
- dummybase.object = ob;
+ /* create a dummy wrapper data to work with */
+ dummybase.object = ob;
- dummychan.type = ANIMTYPE_OBJECT;
- dummychan.data = &dummybase;
- dummychan.id = &ob->id;
- dummychan.adt = ob->adt;
+ dummychan.type = ANIMTYPE_OBJECT;
+ dummychan.data = &dummybase;
+ dummychan.id = &ob->id;
+ dummychan.adt = ob->adt;
- ac.ads = ads;
- ac.data = &dummychan;
- ac.datatype = ANIMCONT_CHANNEL;
+ ac.ads = ads;
+ ac.data = &dummychan;
+ ac.datatype = ANIMCONT_CHANNEL;
- /* get F-Curves to take keyframes from */
- filter = ANIMFILTER_DATA_VISIBLE; // curves only
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* get F-Curves to take keyframes from */
+ filter = ANIMFILTER_DATA_VISIBLE; // curves only
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* loop through each F-Curve, grabbing the keyframes */
- for (ale = anim_data.first; ale; ale = ale->next)
- fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag);
+ /* loop through each F-Curve, grabbing the keyframes */
+ for (ale = anim_data.first; ale; ale = ale->next)
+ fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag);
- ANIM_animdata_freelist(&anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
-void cachefile_to_keylist(bDopeSheet *ads, CacheFile *cache_file, DLRBT_Tree *keys, int saction_flag)
+void cachefile_to_keylist(bDopeSheet *ads,
+ CacheFile *cache_file,
+ DLRBT_Tree *keys,
+ int saction_flag)
{
- if (cache_file == NULL) {
- return;
- }
-
- /* create a dummy wrapper data to work with */
- bAnimListElem dummychan = {NULL};
- dummychan.type = ANIMTYPE_DSCACHEFILE;
- dummychan.data = cache_file;
- dummychan.id = &cache_file->id;
- dummychan.adt = cache_file->adt;
-
- bAnimContext ac = {NULL};
- ac.ads = ads;
- ac.data = &dummychan;
- ac.datatype = ANIMCONT_CHANNEL;
-
- /* get F-Curves to take keyframes from */
- ListBase anim_data = { NULL, NULL };
- int filter = ANIMFILTER_DATA_VISIBLE; // curves only
- 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) {
- fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag);
- }
-
- ANIM_animdata_freelist(&anim_data);
+ if (cache_file == NULL) {
+ return;
+ }
+
+ /* create a dummy wrapper data to work with */
+ bAnimListElem dummychan = {NULL};
+ dummychan.type = ANIMTYPE_DSCACHEFILE;
+ dummychan.data = cache_file;
+ dummychan.id = &cache_file->id;
+ dummychan.adt = cache_file->adt;
+
+ bAnimContext ac = {NULL};
+ ac.ads = ads;
+ ac.data = &dummychan;
+ ac.datatype = ANIMCONT_CHANNEL;
+
+ /* get F-Curves to take keyframes from */
+ ListBase anim_data = {NULL, NULL};
+ int filter = ANIMFILTER_DATA_VISIBLE; // curves only
+ 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) {
+ fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag);
+ }
+
+ ANIM_animdata_freelist(&anim_data);
}
void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, int saction_flag)
{
- if (fcu && fcu->totvert && fcu->bezt) {
- /* apply NLA-mapping (if applicable) */
- if (adt)
- ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
+ if (fcu && fcu->totvert && fcu->bezt) {
+ /* apply NLA-mapping (if applicable) */
+ if (adt)
+ ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
- /* Check if the curve is cyclic. */
- bool is_cyclic = BKE_fcurve_is_cyclic(fcu) && (fcu->totvert >= 2);
- bool do_extremes = (saction_flag & SACTION_SHOW_EXTREMES) != 0;
+ /* Check if the curve is cyclic. */
+ bool is_cyclic = BKE_fcurve_is_cyclic(fcu) && (fcu->totvert >= 2);
+ bool do_extremes = (saction_flag & SACTION_SHOW_EXTREMES) != 0;
- /* loop through beztriples, making ActKeysColumns */
- BezTripleChain chain = { 0 };
+ /* loop through beztriples, making ActKeysColumns */
+ BezTripleChain chain = {0};
- for (int v = 0; v < fcu->totvert; v++) {
- chain.cur = &fcu->bezt[v];
+ for (int v = 0; v < fcu->totvert; v++) {
+ chain.cur = &fcu->bezt[v];
- /* Neighbor keys, accounting for being cyclic. */
- if (do_extremes) {
- chain.prev = (v > 0) ? &fcu->bezt[v - 1] : is_cyclic ? &fcu->bezt[fcu->totvert - 2] : NULL;
- chain.next = (v + 1 < fcu->totvert) ? &fcu->bezt[v + 1] : is_cyclic ? &fcu->bezt[1] : NULL;
- }
+ /* Neighbor keys, accounting for being cyclic. */
+ if (do_extremes) {
+ chain.prev = (v > 0) ? &fcu->bezt[v - 1] : is_cyclic ? &fcu->bezt[fcu->totvert - 2] : NULL;
+ chain.next = (v + 1 < fcu->totvert) ? &fcu->bezt[v + 1] : is_cyclic ? &fcu->bezt[1] : NULL;
+ }
- add_bezt_to_keycolumns_list(keys, &chain);
- }
+ add_bezt_to_keycolumns_list(keys, &chain);
+ }
- /* Update keyblocks. */
- update_keyblocks(keys, fcu->bezt, fcu->totvert);
+ /* Update keyblocks. */
+ update_keyblocks(keys, fcu->bezt, fcu->totvert);
- /* unapply NLA-mapping if applicable */
- if (adt)
- ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
- }
+ /* unapply NLA-mapping if applicable */
+ if (adt)
+ ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
+ }
}
void agroup_to_keylist(AnimData *adt, bActionGroup *agrp, DLRBT_Tree *keys, int saction_flag)
{
- FCurve *fcu;
-
- if (agrp) {
- /* loop through F-Curves */
- for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next) {
- fcurve_to_keylist(adt, fcu, keys, saction_flag);
- }
- }
+ FCurve *fcu;
+
+ if (agrp) {
+ /* loop through F-Curves */
+ for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next) {
+ fcurve_to_keylist(adt, fcu, keys, saction_flag);
+ }
+ }
}
void action_to_keylist(AnimData *adt, bAction *act, DLRBT_Tree *keys, int saction_flag)
{
- FCurve *fcu;
-
- if (act) {
- /* loop through F-Curves */
- for (fcu = act->curves.first; fcu; fcu = fcu->next) {
- fcurve_to_keylist(adt, fcu, keys, saction_flag);
- }
- }
+ FCurve *fcu;
+
+ if (act) {
+ /* loop through F-Curves */
+ for (fcu = act->curves.first; fcu; fcu = fcu->next) {
+ fcurve_to_keylist(adt, fcu, keys, saction_flag);
+ }
+ }
}
-
void gpencil_to_keylist(bDopeSheet *ads, bGPdata *gpd, DLRBT_Tree *keys, const bool active)
{
- bGPDlayer *gpl;
-
- if (gpd && keys) {
- /* for now, just aggregate out all the frames, but only for visible layers */
- for (gpl = gpd->layers.last; gpl; gpl = gpl->prev) {
- if ((gpl->flag & GP_LAYER_HIDE) == 0) {
- if ((!active) || ((active) && (gpl->flag & GP_LAYER_SELECT))) {
- gpl_to_keylist(ads, gpl, keys);
- }
- }
- }
- }
+ bGPDlayer *gpl;
+
+ if (gpd && keys) {
+ /* for now, just aggregate out all the frames, but only for visible layers */
+ for (gpl = gpd->layers.last; gpl; gpl = gpl->prev) {
+ if ((gpl->flag & GP_LAYER_HIDE) == 0) {
+ if ((!active) || ((active) && (gpl->flag & GP_LAYER_SELECT))) {
+ gpl_to_keylist(ads, gpl, keys);
+ }
+ }
+ }
+ }
}
void gpl_to_keylist(bDopeSheet *UNUSED(ads), bGPDlayer *gpl, DLRBT_Tree *keys)
{
- bGPDframe *gpf;
+ bGPDframe *gpf;
- if (gpl && keys) {
- /* although the frames should already be in an ordered list, they are not suitable for displaying yet */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next)
- add_gpframe_to_keycolumns_list(keys, gpf);
+ if (gpl && keys) {
+ /* although the frames should already be in an ordered list, they are not suitable for displaying yet */
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next)
+ add_gpframe_to_keycolumns_list(keys, gpf);
- update_keyblocks(keys, NULL, 0);
- }
+ update_keyblocks(keys, NULL, 0);
+ }
}
void mask_to_keylist(bDopeSheet *UNUSED(ads), MaskLayer *masklay, DLRBT_Tree *keys)
{
- MaskLayerShape *masklay_shape;
-
- if (masklay && keys) {
- for (masklay_shape = masklay->splines_shapes.first;
- masklay_shape;
- masklay_shape = masklay_shape->next)
- {
- add_masklay_to_keycolumns_list(keys, masklay_shape);
- }
-
- update_keyblocks(keys, NULL, 0);
- }
+ MaskLayerShape *masklay_shape;
+
+ if (masklay && keys) {
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape->next) {
+ add_masklay_to_keycolumns_list(keys, masklay_shape);
+ }
+
+ update_keyblocks(keys, NULL, 0);
+ }
}
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index 837a25946da..bb0ab112af4 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -20,7 +20,6 @@
* \ingroup edanimation
*/
-
#include <stdlib.h>
#include <string.h>
#include <math.h>
@@ -71,329 +70,369 @@
* operation on them, and optionally applies an F-Curve validation function afterwards.
*/
// TODO: make this function work on samples too...
-short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked, FCurve *fcu, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
-{
- BezTriple *bezt;
- short ok = 0;
- unsigned int i;
-
- /* sanity check */
- if (ELEM(NULL, fcu, fcu->bezt))
- return 0;
-
- /* set the F-Curve into the editdata so that it can be accessed */
- if (ked) {
- ked->fcu = fcu;
- ked->curIndex = 0;
- ked->curflags = ok;
- }
-
- /* if function to apply to bezier curves is set, then loop through executing it on beztriples */
- if (key_cb) {
- /* if there's a validation func, include that check in the loop
- * (this is should be more efficient than checking for it in every loop)
- */
- if (key_ok) {
- for (bezt = fcu->bezt, i = 0; i < fcu->totvert; bezt++, i++) {
- if (ked) {
- /* advance the index, and reset the ok flags (to not influence the result) */
- ked->curIndex = i;
- ked->curflags = 0;
- }
-
- /* Only operate on this BezTriple if it fulfills the criteria of the validation func */
- if ((ok = key_ok(ked, bezt))) {
- if (ked) ked->curflags = ok;
-
- /* Exit with return-code '1' if function returns positive
- * This is useful if finding if some BezTriple satisfies a condition.
- */
- if (key_cb(ked, bezt)) return 1;
- }
- }
- }
- else {
- for (bezt = fcu->bezt, i = 0; i < fcu->totvert; bezt++, i++) {
- if (ked) ked->curIndex = i;
-
- /* Exit with return-code '1' if function returns positive
- * This is useful if finding if some BezTriple satisfies a condition.
- */
- if (key_cb(ked, bezt)) return 1;
- }
- }
- }
-
- /* unset the F-Curve from the editdata now that it's done */
- if (ked) {
- ked->fcu = NULL;
- ked->curIndex = 0;
- ked->curflags = 0;
- }
-
- /* if fcu_cb (F-Curve post-editing callback) has been specified then execute it */
- if (fcu_cb)
- fcu_cb(fcu);
-
- /* done */
- return 0;
+short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked,
+ FCurve *fcu,
+ KeyframeEditFunc key_ok,
+ KeyframeEditFunc key_cb,
+ FcuEditFunc fcu_cb)
+{
+ BezTriple *bezt;
+ short ok = 0;
+ unsigned int i;
+
+ /* sanity check */
+ if (ELEM(NULL, fcu, fcu->bezt))
+ return 0;
+
+ /* set the F-Curve into the editdata so that it can be accessed */
+ if (ked) {
+ ked->fcu = fcu;
+ ked->curIndex = 0;
+ ked->curflags = ok;
+ }
+
+ /* if function to apply to bezier curves is set, then loop through executing it on beztriples */
+ if (key_cb) {
+ /* if there's a validation func, include that check in the loop
+ * (this is should be more efficient than checking for it in every loop)
+ */
+ if (key_ok) {
+ for (bezt = fcu->bezt, i = 0; i < fcu->totvert; bezt++, i++) {
+ if (ked) {
+ /* advance the index, and reset the ok flags (to not influence the result) */
+ ked->curIndex = i;
+ ked->curflags = 0;
+ }
+
+ /* Only operate on this BezTriple if it fulfills the criteria of the validation func */
+ if ((ok = key_ok(ked, bezt))) {
+ if (ked)
+ ked->curflags = ok;
+
+ /* Exit with return-code '1' if function returns positive
+ * This is useful if finding if some BezTriple satisfies a condition.
+ */
+ if (key_cb(ked, bezt))
+ return 1;
+ }
+ }
+ }
+ else {
+ for (bezt = fcu->bezt, i = 0; i < fcu->totvert; bezt++, i++) {
+ if (ked)
+ ked->curIndex = i;
+
+ /* Exit with return-code '1' if function returns positive
+ * This is useful if finding if some BezTriple satisfies a condition.
+ */
+ if (key_cb(ked, bezt))
+ return 1;
+ }
+ }
+ }
+
+ /* unset the F-Curve from the editdata now that it's done */
+ if (ked) {
+ ked->fcu = NULL;
+ ked->curIndex = 0;
+ ked->curflags = 0;
+ }
+
+ /* if fcu_cb (F-Curve post-editing callback) has been specified then execute it */
+ if (fcu_cb)
+ fcu_cb(fcu);
+
+ /* done */
+ return 0;
}
/* -------------------------------- Further Abstracted (Not Exposed Directly) ----------------------------- */
/* This function is used to loop over the keyframe data in an Action Group */
-static short agrp_keyframes_loop(KeyframeEditData *ked, bActionGroup *agrp, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
+static short agrp_keyframes_loop(KeyframeEditData *ked,
+ bActionGroup *agrp,
+ KeyframeEditFunc key_ok,
+ KeyframeEditFunc key_cb,
+ FcuEditFunc fcu_cb)
{
- FCurve *fcu;
+ FCurve *fcu;
- /* sanity check */
- if (agrp == NULL)
- return 0;
+ /* sanity check */
+ if (agrp == NULL)
+ return 0;
- /* only iterate over the F-Curves that are in this group */
- for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next) {
- if (ANIM_fcurve_keyframes_loop(ked, fcu, key_ok, key_cb, fcu_cb))
- return 1;
- }
+ /* only iterate over the F-Curves that are in this group */
+ for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next) {
+ if (ANIM_fcurve_keyframes_loop(ked, fcu, key_ok, key_cb, fcu_cb))
+ return 1;
+ }
- return 0;
+ return 0;
}
/* This function is used to loop over the keyframe data in an Action */
-static short act_keyframes_loop(KeyframeEditData *ked, bAction *act, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
+static short act_keyframes_loop(KeyframeEditData *ked,
+ bAction *act,
+ KeyframeEditFunc key_ok,
+ KeyframeEditFunc key_cb,
+ FcuEditFunc fcu_cb)
{
- FCurve *fcu;
+ FCurve *fcu;
- /* sanity check */
- if (act == NULL)
- return 0;
+ /* sanity check */
+ if (act == NULL)
+ return 0;
- /* just loop through all F-Curves */
- for (fcu = act->curves.first; fcu; fcu = fcu->next) {
- if (ANIM_fcurve_keyframes_loop(ked, fcu, key_ok, key_cb, fcu_cb))
- return 1;
- }
+ /* just loop through all F-Curves */
+ for (fcu = act->curves.first; fcu; fcu = fcu->next) {
+ if (ANIM_fcurve_keyframes_loop(ked, fcu, key_ok, key_cb, fcu_cb))
+ return 1;
+ }
- return 0;
+ return 0;
}
/* This function is used to loop over the keyframe data in an Object */
-static short ob_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, Object *ob, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
+static short ob_keyframes_loop(KeyframeEditData *ked,
+ bDopeSheet *ads,
+ Object *ob,
+ KeyframeEditFunc key_ok,
+ KeyframeEditFunc key_cb,
+ FcuEditFunc fcu_cb)
{
- bAnimContext ac = {NULL};
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- int ret = 0;
+ bAnimContext ac = {NULL};
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ int ret = 0;
- bAnimListElem dummychan = {NULL};
- Base dummybase = {NULL};
+ bAnimListElem dummychan = {NULL};
+ Base dummybase = {NULL};
- if (ob == NULL)
- return 0;
+ if (ob == NULL)
+ return 0;
- /* create a dummy wrapper data to work with */
- dummybase.object = ob;
+ /* create a dummy wrapper data to work with */
+ dummybase.object = ob;
- dummychan.type = ANIMTYPE_OBJECT;
- dummychan.data = &dummybase;
- dummychan.id = &ob->id;
- dummychan.adt = ob->adt;
+ dummychan.type = ANIMTYPE_OBJECT;
+ dummychan.data = &dummybase;
+ dummychan.id = &ob->id;
+ dummychan.adt = ob->adt;
- ac.ads = ads;
- ac.data = &dummychan;
- ac.datatype = ANIMCONT_CHANNEL;
+ ac.ads = ads;
+ ac.data = &dummychan;
+ ac.datatype = ANIMCONT_CHANNEL;
- /* get F-Curves to take keyframes from */
- filter = ANIMFILTER_DATA_VISIBLE; // curves only
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* get F-Curves to take keyframes from */
+ filter = ANIMFILTER_DATA_VISIBLE; // curves only
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* loop through each F-Curve, applying the operation as required, but stopping on the first one */
- for (ale = anim_data.first; ale; ale = ale->next) {
- if (ANIM_fcurve_keyframes_loop(ked, (FCurve *)ale->data, key_ok, key_cb, fcu_cb)) {
- ret = 1;
- break;
- }
- }
+ /* loop through each F-Curve, applying the operation as required, but stopping on the first one */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (ANIM_fcurve_keyframes_loop(ked, (FCurve *)ale->data, key_ok, key_cb, fcu_cb)) {
+ ret = 1;
+ break;
+ }
+ }
- ANIM_animdata_freelist(&anim_data);
+ ANIM_animdata_freelist(&anim_data);
- /* return return code - defaults to zero if nothing happened */
- return ret;
+ /* return return code - defaults to zero if nothing happened */
+ return ret;
}
/* This function is used to loop over the keyframe data in a Scene */
-static short scene_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, Scene *sce, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
+static short scene_keyframes_loop(KeyframeEditData *ked,
+ bDopeSheet *ads,
+ Scene *sce,
+ KeyframeEditFunc key_ok,
+ KeyframeEditFunc key_cb,
+ FcuEditFunc fcu_cb)
{
- bAnimContext ac = {NULL};
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- int ret = 0;
+ bAnimContext ac = {NULL};
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ int ret = 0;
- bAnimListElem dummychan = {NULL};
+ bAnimListElem dummychan = {NULL};
- if (sce == NULL)
- return 0;
+ if (sce == NULL)
+ return 0;
- /* create a dummy wrapper data to work with */
- dummychan.type = ANIMTYPE_SCENE;
- dummychan.data = sce;
- dummychan.id = &sce->id;
- dummychan.adt = sce->adt;
+ /* create a dummy wrapper data to work with */
+ dummychan.type = ANIMTYPE_SCENE;
+ dummychan.data = sce;
+ dummychan.id = &sce->id;
+ dummychan.adt = sce->adt;
- ac.ads = ads;
- ac.data = &dummychan;
- ac.datatype = ANIMCONT_CHANNEL;
+ ac.ads = ads;
+ ac.data = &dummychan;
+ ac.datatype = ANIMCONT_CHANNEL;
- /* get F-Curves to take keyframes from */
- filter = ANIMFILTER_DATA_VISIBLE; // curves only
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* get F-Curves to take keyframes from */
+ filter = ANIMFILTER_DATA_VISIBLE; // curves only
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* loop through each F-Curve, applying the operation as required, but stopping on the first one */
- for (ale = anim_data.first; ale; ale = ale->next) {
- if (ANIM_fcurve_keyframes_loop(ked, (FCurve *)ale->data, key_ok, key_cb, fcu_cb)) {
- ret = 1;
- break;
- }
- }
+ /* loop through each F-Curve, applying the operation as required, but stopping on the first one */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (ANIM_fcurve_keyframes_loop(ked, (FCurve *)ale->data, key_ok, key_cb, fcu_cb)) {
+ ret = 1;
+ break;
+ }
+ }
- ANIM_animdata_freelist(&anim_data);
+ ANIM_animdata_freelist(&anim_data);
- /* return return code - defaults to zero if nothing happened */
- return ret;
+ /* return return code - defaults to zero if nothing happened */
+ return ret;
}
/* This function is used to loop over the keyframe data in a DopeSheet summary */
-static short summary_keyframes_loop(KeyframeEditData *ked, bAnimContext *ac, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
-{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter, ret_code = 0;
-
- /* sanity check */
- if (ac == NULL)
- return 0;
-
- /* get F-Curves to take keyframes from */
- filter = ANIMFILTER_DATA_VISIBLE;
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* loop through each F-Curve, working on the keyframes until the first curve aborts */
- for (ale = anim_data.first; ale; ale = ale->next) {
- switch (ale->datatype) {
- case ALE_MASKLAY:
- case ALE_GPFRAME:
- break;
-
- case ALE_FCURVE:
- default:
- {
- if (ked && ked->iterflags) {
- /* make backups of the current values, so that a localised fix
- * (e.g. NLA time remapping) can be applied to these values
- */
- float f1 = ked->f1;
- float f2 = ked->f2;
-
- if (ked->iterflags & (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP)) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-
- if (ked->iterflags & KED_F1_NLA_UNMAP)
- ked->f1 = BKE_nla_tweakedit_remap(adt, f1, NLATIME_CONVERT_UNMAP);
- if (ked->iterflags & KED_F2_NLA_UNMAP)
- ked->f2 = BKE_nla_tweakedit_remap(adt, f2, NLATIME_CONVERT_UNMAP);
- }
-
- /* now operate on the channel as per normal */
- ret_code = ANIM_fcurve_keyframes_loop(ked, ale->data, key_ok, key_cb, fcu_cb);
-
- /* reset */
- ked->f1 = f1;
- ked->f2 = f2;
- }
- else {
- /* no special handling required... */
- ret_code = ANIM_fcurve_keyframes_loop(ked, ale->data, key_ok, key_cb, fcu_cb);
- }
- break;
- }
- }
-
- if (ret_code)
- break;
- }
-
- ANIM_animdata_freelist(&anim_data);
-
- return ret_code;
+static short summary_keyframes_loop(KeyframeEditData *ked,
+ bAnimContext *ac,
+ KeyframeEditFunc key_ok,
+ KeyframeEditFunc key_cb,
+ FcuEditFunc fcu_cb)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter, ret_code = 0;
+
+ /* sanity check */
+ if (ac == NULL)
+ return 0;
+
+ /* get F-Curves to take keyframes from */
+ filter = ANIMFILTER_DATA_VISIBLE;
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through each F-Curve, working on the keyframes until the first curve aborts */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ switch (ale->datatype) {
+ case ALE_MASKLAY:
+ case ALE_GPFRAME:
+ break;
+
+ case ALE_FCURVE:
+ default: {
+ if (ked && ked->iterflags) {
+ /* make backups of the current values, so that a localised fix
+ * (e.g. NLA time remapping) can be applied to these values
+ */
+ float f1 = ked->f1;
+ float f2 = ked->f2;
+
+ if (ked->iterflags & (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP)) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ if (ked->iterflags & KED_F1_NLA_UNMAP)
+ ked->f1 = BKE_nla_tweakedit_remap(adt, f1, NLATIME_CONVERT_UNMAP);
+ if (ked->iterflags & KED_F2_NLA_UNMAP)
+ ked->f2 = BKE_nla_tweakedit_remap(adt, f2, NLATIME_CONVERT_UNMAP);
+ }
+
+ /* now operate on the channel as per normal */
+ ret_code = ANIM_fcurve_keyframes_loop(ked, ale->data, key_ok, key_cb, fcu_cb);
+
+ /* reset */
+ ked->f1 = f1;
+ ked->f2 = f2;
+ }
+ else {
+ /* no special handling required... */
+ ret_code = ANIM_fcurve_keyframes_loop(ked, ale->data, key_ok, key_cb, fcu_cb);
+ }
+ break;
+ }
+ }
+
+ if (ret_code)
+ break;
+ }
+
+ ANIM_animdata_freelist(&anim_data);
+
+ return ret_code;
}
/* --- */
/* This function is used to apply operation to all keyframes, regardless of the type */
-short ANIM_animchannel_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, bAnimListElem *ale, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
-{
- /* sanity checks */
- if (ale == NULL)
- return 0;
-
- /* method to use depends on the type of keyframe data */
- switch (ale->datatype) {
- /* direct keyframe data (these loops are exposed) */
- case ALE_FCURVE: /* F-Curve */
- return ANIM_fcurve_keyframes_loop(ked, ale->key_data, key_ok, key_cb, fcu_cb);
-
- /* indirect 'summaries' (these are not exposed directly)
- * NOTE: must keep this code in sync with the drawing code and also the filtering code!
- */
- case ALE_GROUP: /* action group */
- return agrp_keyframes_loop(ked, (bActionGroup *)ale->data, key_ok, key_cb, fcu_cb);
- case ALE_ACT: /* action */
- return act_keyframes_loop(ked, (bAction *)ale->key_data, key_ok, key_cb, fcu_cb);
-
- case ALE_OB: /* object */
- return ob_keyframes_loop(ked, ads, (Object *)ale->key_data, key_ok, key_cb, fcu_cb);
- case ALE_SCE: /* scene */
- return scene_keyframes_loop(ked, ads, (Scene *)ale->data, key_ok, key_cb, fcu_cb);
- case ALE_ALL: /* 'all' (DopeSheet summary) */
- return summary_keyframes_loop(ked, (bAnimContext *)ale->data, key_ok, key_cb, fcu_cb);
- }
-
- return 0;
+short ANIM_animchannel_keyframes_loop(KeyframeEditData *ked,
+ bDopeSheet *ads,
+ bAnimListElem *ale,
+ KeyframeEditFunc key_ok,
+ KeyframeEditFunc key_cb,
+ FcuEditFunc fcu_cb)
+{
+ /* sanity checks */
+ if (ale == NULL)
+ return 0;
+
+ /* method to use depends on the type of keyframe data */
+ switch (ale->datatype) {
+ /* direct keyframe data (these loops are exposed) */
+ case ALE_FCURVE: /* F-Curve */
+ return ANIM_fcurve_keyframes_loop(ked, ale->key_data, key_ok, key_cb, fcu_cb);
+
+ /* indirect 'summaries' (these are not exposed directly)
+ * NOTE: must keep this code in sync with the drawing code and also the filtering code!
+ */
+ case ALE_GROUP: /* action group */
+ return agrp_keyframes_loop(ked, (bActionGroup *)ale->data, key_ok, key_cb, fcu_cb);
+ case ALE_ACT: /* action */
+ return act_keyframes_loop(ked, (bAction *)ale->key_data, key_ok, key_cb, fcu_cb);
+
+ case ALE_OB: /* object */
+ return ob_keyframes_loop(ked, ads, (Object *)ale->key_data, key_ok, key_cb, fcu_cb);
+ case ALE_SCE: /* scene */
+ return scene_keyframes_loop(ked, ads, (Scene *)ale->data, key_ok, key_cb, fcu_cb);
+ case ALE_ALL: /* 'all' (DopeSheet summary) */
+ return summary_keyframes_loop(ked, (bAnimContext *)ale->data, key_ok, key_cb, fcu_cb);
+ }
+
+ return 0;
}
/* This function is used to apply operation to all keyframes,
* regardless of the type without needed an AnimListElem wrapper */
-short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, void *data, int keytype, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
-{
- /* sanity checks */
- if (data == NULL)
- return 0;
-
- /* method to use depends on the type of keyframe data */
- switch (keytype) {
- /* direct keyframe data (these loops are exposed) */
- case ALE_FCURVE: /* F-Curve */
- return ANIM_fcurve_keyframes_loop(ked, data, key_ok, key_cb, fcu_cb);
-
- /* indirect 'summaries' (these are not exposed directly)
- * NOTE: must keep this code in sync with the drawing code and also the filtering code!
- */
- case ALE_GROUP: /* action group */
- return agrp_keyframes_loop(ked, (bActionGroup *)data, key_ok, key_cb, fcu_cb);
- case ALE_ACT: /* action */
- return act_keyframes_loop(ked, (bAction *)data, key_ok, key_cb, fcu_cb);
-
- case ALE_OB: /* object */
- return ob_keyframes_loop(ked, ads, (Object *)data, key_ok, key_cb, fcu_cb);
- case ALE_SCE: /* scene */
- return scene_keyframes_loop(ked, ads, (Scene *)data, key_ok, key_cb, fcu_cb);
- case ALE_ALL: /* 'all' (DopeSheet summary) */
- return summary_keyframes_loop(ked, (bAnimContext *)data, key_ok, key_cb, fcu_cb);
- }
-
- return 0;
+short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked,
+ bDopeSheet *ads,
+ void *data,
+ int keytype,
+ KeyframeEditFunc key_ok,
+ KeyframeEditFunc key_cb,
+ FcuEditFunc fcu_cb)
+{
+ /* sanity checks */
+ if (data == NULL)
+ return 0;
+
+ /* method to use depends on the type of keyframe data */
+ switch (keytype) {
+ /* direct keyframe data (these loops are exposed) */
+ case ALE_FCURVE: /* F-Curve */
+ return ANIM_fcurve_keyframes_loop(ked, data, key_ok, key_cb, fcu_cb);
+
+ /* indirect 'summaries' (these are not exposed directly)
+ * NOTE: must keep this code in sync with the drawing code and also the filtering code!
+ */
+ case ALE_GROUP: /* action group */
+ return agrp_keyframes_loop(ked, (bActionGroup *)data, key_ok, key_cb, fcu_cb);
+ case ALE_ACT: /* action */
+ return act_keyframes_loop(ked, (bAction *)data, key_ok, key_cb, fcu_cb);
+
+ case ALE_OB: /* object */
+ return ob_keyframes_loop(ked, ads, (Object *)data, key_ok, key_cb, fcu_cb);
+ case ALE_SCE: /* scene */
+ return scene_keyframes_loop(ked, ads, (Scene *)data, key_ok, key_cb, fcu_cb);
+ case ALE_ALL: /* 'all' (DopeSheet summary) */
+ return summary_keyframes_loop(ked, (bAnimContext *)data, key_ok, key_cb, fcu_cb);
+ }
+
+ return 0;
}
/* ************************************************************************** */
@@ -403,23 +442,23 @@ short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads
// used to be recalc_*_ipos() where * was object or action
void ANIM_editkeyframes_refresh(bAnimContext *ac)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- /* filter animation data */
- filter = ANIMFILTER_DATA_VISIBLE;
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ /* filter animation data */
+ filter = ANIMFILTER_DATA_VISIBLE;
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* Loop over F-Curves that are likely to have been edited, and tag them to
- * ensure the keyframes are in order and handles are in a valid position. */
- for (ale = anim_data.first; ale; ale = ale->next) {
- ale->update |= ANIM_UPDATE_DEPS | ANIM_UPDATE_HANDLES | ANIM_UPDATE_ORDER;
- }
+ /* Loop over F-Curves that are likely to have been edited, and tag them to
+ * ensure the keyframes are in order and handles are in a valid position. */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ ale->update |= ANIM_UPDATE_DEPS | ANIM_UPDATE_HANDLES | ANIM_UPDATE_ORDER;
+ }
- /* free temp data */
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ /* free temp data */
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ************************************************************************** */
@@ -433,271 +472,267 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac)
* - requires that a var, of type short, is named 'ok', and has been initialized to 0
*/
#define KEYFRAME_OK_CHECKS(check) \
- { \
- CHECK_TYPE(ok, short); \
- if (check(1)) \
- ok |= KEYFRAME_OK_KEY; \
- \
- if (ked && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) { \
- if (check(0)) \
- ok |= KEYFRAME_OK_H1; \
- if (check(2)) \
- ok |= KEYFRAME_OK_H2; \
- } \
- } (void)0
+ { \
+ CHECK_TYPE(ok, short); \
+ if (check(1)) \
+ ok |= KEYFRAME_OK_KEY; \
+\
+ if (ked && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) { \
+ if (check(0)) \
+ ok |= KEYFRAME_OK_H1; \
+ if (check(2)) \
+ ok |= KEYFRAME_OK_H2; \
+ } \
+ } \
+ (void)0
/* ------------------------ */
static short ok_bezier_frame(KeyframeEditData *ked, BezTriple *bezt)
{
- short ok = 0;
+ short ok = 0;
- /* frame is stored in f1 property (this float accuracy check may need to be dropped?) */
+ /* frame is stored in f1 property (this float accuracy check may need to be dropped?) */
#define KEY_CHECK_OK(_index) IS_EQF(bezt->vec[_index][0], ked->f1)
- KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
+ KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
#undef KEY_CHECK_OK
- /* return ok flags */
- return ok;
+ /* return ok flags */
+ return ok;
}
static short ok_bezier_framerange(KeyframeEditData *ked, BezTriple *bezt)
{
- short ok = 0;
+ short ok = 0;
- /* frame range is stored in float properties */
+ /* frame range is stored in float properties */
#define KEY_CHECK_OK(_index) ((bezt->vec[_index][0] > ked->f1) && (bezt->vec[_index][0] < ked->f2))
- KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
+ KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
#undef KEY_CHECK_OK
- /* return ok flags */
- return ok;
+ /* return ok flags */
+ return ok;
}
static short ok_bezier_selected(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- /* this macro checks all beztriple handles for selection...
- * only one of the verts has to be selected for this to be ok...
- */
- if (BEZT_ISSEL_ANY(bezt))
- return KEYFRAME_OK_ALL;
- else
- return 0;
+ /* this macro checks all beztriple handles for selection...
+ * only one of the verts has to be selected for this to be ok...
+ */
+ if (BEZT_ISSEL_ANY(bezt))
+ return KEYFRAME_OK_ALL;
+ else
+ return 0;
}
static short ok_bezier_value(KeyframeEditData *ked, BezTriple *bezt)
{
- short ok = 0;
+ short ok = 0;
- /* value is stored in f1 property
- * - this float accuracy check may need to be dropped?
- * - should value be stored in f2 instead so that we won't have conflicts when using f1 for frames too?
- */
+ /* value is stored in f1 property
+ * - this float accuracy check may need to be dropped?
+ * - should value be stored in f2 instead so that we won't have conflicts when using f1 for frames too?
+ */
#define KEY_CHECK_OK(_index) IS_EQF(bezt->vec[_index][1], ked->f1)
- KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
+ KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
#undef KEY_CHECK_OK
- /* return ok flags */
- return ok;
+ /* return ok flags */
+ return ok;
}
static short ok_bezier_valuerange(KeyframeEditData *ked, BezTriple *bezt)
{
- short ok = 0;
+ short ok = 0;
- /* value range is stored in float properties */
+ /* value range is stored in float properties */
#define KEY_CHECK_OK(_index) ((bezt->vec[_index][1] > ked->f1) && (bezt->vec[_index][1] < ked->f2))
- KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
+ KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
#undef KEY_CHECK_OK
- /* return ok flags */
- return ok;
+ /* return ok flags */
+ return ok;
}
static short ok_bezier_region(KeyframeEditData *ked, BezTriple *bezt)
{
- /* rect is stored in data property (it's of type rectf, but may not be set) */
- if (ked->data) {
- short ok = 0;
+ /* rect is stored in data property (it's of type rectf, but may not be set) */
+ if (ked->data) {
+ short ok = 0;
#define KEY_CHECK_OK(_index) BLI_rctf_isect_pt_v(ked->data, bezt->vec[_index])
- KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
+ KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
#undef KEY_CHECK_OK
- /* return ok flags */
- return ok;
- }
- else
- return 0;
+ /* return ok flags */
+ return ok;
+ }
+ else
+ return 0;
}
/**
* Called from #ok_bezier_region_lasso and #ok_bezier_channel_lasso
*/
-bool keyframe_region_lasso_test(
- const KeyframeEdit_LassoData *data_lasso,
- const float xy[2])
+bool keyframe_region_lasso_test(const KeyframeEdit_LassoData *data_lasso, const float xy[2])
{
- if (BLI_rctf_isect_pt_v(data_lasso->rectf_scaled, xy)) {
- float xy_view[2];
+ if (BLI_rctf_isect_pt_v(data_lasso->rectf_scaled, xy)) {
+ float xy_view[2];
- BLI_rctf_transform_pt_v(data_lasso->rectf_view, data_lasso->rectf_scaled, xy_view, xy);
+ 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)) {
- return true;
- }
- }
+ if (BLI_lasso_is_point_inside(
+ data_lasso->mcords, data_lasso->mcords_tot, xy_view[0], xy_view[1], INT_MAX)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
static short ok_bezier_region_lasso(KeyframeEditData *ked, BezTriple *bezt)
{
- /* check for lasso customdata (KeyframeEdit_LassoData) */
- if (ked->data) {
- short ok = 0;
+ /* check for lasso customdata (KeyframeEdit_LassoData) */
+ if (ked->data) {
+ short ok = 0;
#define KEY_CHECK_OK(_index) keyframe_region_lasso_test(ked->data, bezt->vec[_index])
- KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
+ KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
#undef KEY_CHECK_OK
- /* return ok flags */
- return ok;
- }
- else
- return 0;
+ /* return ok flags */
+ return ok;
+ }
+ else
+ return 0;
}
static short ok_bezier_channel_lasso(KeyframeEditData *ked, BezTriple *bezt)
{
- /* check for lasso customdata (KeyframeEdit_LassoData) */
- if (ked->data) {
- KeyframeEdit_LassoData *data = ked->data;
- float pt[2];
+ /* check for lasso customdata (KeyframeEdit_LassoData) */
+ if (ked->data) {
+ KeyframeEdit_LassoData *data = ked->data;
+ float pt[2];
- /* late-binding remap of the x values (for summary channels) */
- /* XXX: Ideally we reset, but it should be fine just leaving it as-is
- * as the next channel will reset it properly, while the next summary-channel
- * curve will also reset by itself...
- */
- if (ked->iterflags & (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP)) {
- data->rectf_scaled->xmin = ked->f1;
- data->rectf_scaled->xmax = ked->f2;
- }
+ /* late-binding remap of the x values (for summary channels) */
+ /* XXX: Ideally we reset, but it should be fine just leaving it as-is
+ * as the next channel will reset it properly, while the next summary-channel
+ * curve will also reset by itself...
+ */
+ if (ked->iterflags & (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP)) {
+ data->rectf_scaled->xmin = ked->f1;
+ data->rectf_scaled->xmax = ked->f2;
+ }
- /* only use the x-coordinate of the point; the y is the channel range... */
- pt[0] = bezt->vec[1][0];
- pt[1] = ked->channel_y;
+ /* only use the x-coordinate of the point; the y is the channel range... */
+ pt[0] = bezt->vec[1][0];
+ pt[1] = ked->channel_y;
- if (keyframe_region_lasso_test(data, pt))
- return KEYFRAME_OK_KEY;
- }
- return 0;
+ if (keyframe_region_lasso_test(data, pt))
+ return KEYFRAME_OK_KEY;
+ }
+ return 0;
}
/**
* Called from #ok_bezier_region_circle and #ok_bezier_channel_circle
*/
-bool keyframe_region_circle_test(
- const KeyframeEdit_CircleData *data_circle,
- const float xy[2])
+bool keyframe_region_circle_test(const KeyframeEdit_CircleData *data_circle, const float xy[2])
{
- if (BLI_rctf_isect_pt_v(data_circle->rectf_scaled, xy)) {
- float xy_view[2];
+ if (BLI_rctf_isect_pt_v(data_circle->rectf_scaled, xy)) {
+ float xy_view[2];
- BLI_rctf_transform_pt_v(data_circle->rectf_view, data_circle->rectf_scaled, xy_view, xy);
+ BLI_rctf_transform_pt_v(data_circle->rectf_view, data_circle->rectf_scaled, xy_view, xy);
- xy_view[0] = xy_view[0] - data_circle->mval[0];
- xy_view[1] = xy_view[1] - data_circle->mval[1];
- return len_squared_v2(xy_view) < data_circle->radius_squared;
- }
+ xy_view[0] = xy_view[0] - data_circle->mval[0];
+ xy_view[1] = xy_view[1] - data_circle->mval[1];
+ return len_squared_v2(xy_view) < data_circle->radius_squared;
+ }
- return false;
+ return false;
}
-
static short ok_bezier_region_circle(KeyframeEditData *ked, BezTriple *bezt)
{
- /* check for circle select customdata (KeyframeEdit_CircleData) */
- if (ked->data) {
- short ok = 0;
+ /* check for circle select customdata (KeyframeEdit_CircleData) */
+ if (ked->data) {
+ short ok = 0;
#define KEY_CHECK_OK(_index) keyframe_region_circle_test(ked->data, bezt->vec[_index])
- KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
+ KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
#undef KEY_CHECK_OK
- /* return ok flags */
- return ok;
- }
- else
- return 0;
+ /* return ok flags */
+ return ok;
+ }
+ else
+ return 0;
}
static short ok_bezier_channel_circle(KeyframeEditData *ked, BezTriple *bezt)
{
- /* check for circle select customdata (KeyframeEdit_CircleData) */
- if (ked->data) {
- KeyframeEdit_CircleData *data = ked->data;
- float pt[2];
+ /* check for circle select customdata (KeyframeEdit_CircleData) */
+ if (ked->data) {
+ KeyframeEdit_CircleData *data = ked->data;
+ float pt[2];
- /* late-binding remap of the x values (for summary channels) */
- /* XXX: Ideally we reset, but it should be fine just leaving it as-is
- * as the next channel will reset it properly, while the next summary-channel
- * curve will also reset by itself...
- */
- if (ked->iterflags & (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP)) {
- data->rectf_scaled->xmin = ked->f1;
- data->rectf_scaled->xmax = ked->f2;
- }
+ /* late-binding remap of the x values (for summary channels) */
+ /* XXX: Ideally we reset, but it should be fine just leaving it as-is
+ * as the next channel will reset it properly, while the next summary-channel
+ * curve will also reset by itself...
+ */
+ if (ked->iterflags & (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP)) {
+ data->rectf_scaled->xmin = ked->f1;
+ data->rectf_scaled->xmax = ked->f2;
+ }
- /* only use the x-coordinate of the point; the y is the channel range... */
- pt[0] = bezt->vec[1][0];
- pt[1] = ked->channel_y;
+ /* only use the x-coordinate of the point; the y is the channel range... */
+ pt[0] = bezt->vec[1][0];
+ pt[1] = ked->channel_y;
- if (keyframe_region_circle_test(data, pt))
- return KEYFRAME_OK_KEY;
- }
- return 0;
+ if (keyframe_region_circle_test(data, pt))
+ return KEYFRAME_OK_KEY;
+ }
+ return 0;
}
-
KeyframeEditFunc ANIM_editkeyframes_ok(short mode)
{
- /* eEditKeyframes_Validate */
- switch (mode) {
- case BEZT_OK_FRAME:
- /* only if bezt falls on the right frame (float) */
- return ok_bezier_frame;
- case BEZT_OK_FRAMERANGE:
- /* only if bezt falls within the specified frame range (floats) */
- return ok_bezier_framerange;
- case BEZT_OK_SELECTED:
- /* only if bezt is selected (self) */
- return ok_bezier_selected;
- case BEZT_OK_VALUE:
- /* only if bezt value matches (float) */
- return ok_bezier_value;
- case BEZT_OK_VALUERANGE:
- /* only if bezier falls within the specified value range (floats) */
- return ok_bezier_valuerange;
- case BEZT_OK_REGION:
- /* only if bezier falls within the specified rect (data -> rectf) */
- return ok_bezier_region;
- case BEZT_OK_REGION_LASSO:
- /* only if the point falls within KeyframeEdit_LassoData defined data */
- return ok_bezier_region_lasso;
- case BEZT_OK_REGION_CIRCLE:
- /* only if the point falls within KeyframeEdit_CircleData defined data */
- return ok_bezier_region_circle;
- case BEZT_OK_CHANNEL_LASSO:
- /* same as BEZT_OK_REGION_LASSO, but we're only using the x-value of the points */
- return ok_bezier_channel_lasso;
- case BEZT_OK_CHANNEL_CIRCLE:
- /* same as BEZT_OK_REGION_CIRCLE, but we're only using the x-value of the points */
- return ok_bezier_channel_circle;
- default: /* nothing was ok */
- return NULL;
- }
+ /* eEditKeyframes_Validate */
+ switch (mode) {
+ case BEZT_OK_FRAME:
+ /* only if bezt falls on the right frame (float) */
+ return ok_bezier_frame;
+ case BEZT_OK_FRAMERANGE:
+ /* only if bezt falls within the specified frame range (floats) */
+ return ok_bezier_framerange;
+ case BEZT_OK_SELECTED:
+ /* only if bezt is selected (self) */
+ return ok_bezier_selected;
+ case BEZT_OK_VALUE:
+ /* only if bezt value matches (float) */
+ return ok_bezier_value;
+ case BEZT_OK_VALUERANGE:
+ /* only if bezier falls within the specified value range (floats) */
+ return ok_bezier_valuerange;
+ case BEZT_OK_REGION:
+ /* only if bezier falls within the specified rect (data -> rectf) */
+ return ok_bezier_region;
+ case BEZT_OK_REGION_LASSO:
+ /* only if the point falls within KeyframeEdit_LassoData defined data */
+ return ok_bezier_region_lasso;
+ case BEZT_OK_REGION_CIRCLE:
+ /* only if the point falls within KeyframeEdit_CircleData defined data */
+ return ok_bezier_region_circle;
+ case BEZT_OK_CHANNEL_LASSO:
+ /* same as BEZT_OK_REGION_LASSO, but we're only using the x-value of the points */
+ return ok_bezier_channel_lasso;
+ case BEZT_OK_CHANNEL_CIRCLE:
+ /* same as BEZT_OK_REGION_CIRCLE, but we're only using the x-value of the points */
+ return ok_bezier_channel_circle;
+ default: /* nothing was ok */
+ return NULL;
+ }
}
/* ******************************************* */
@@ -709,36 +744,36 @@ KeyframeEditFunc ANIM_editkeyframes_ok(short mode)
*/
short bezt_calc_average(KeyframeEditData *ked, BezTriple *bezt)
{
- /* only if selected */
- if (bezt->f2 & SELECT) {
- /* store average time in float 1 (only do rounding at last step) */
- ked->f1 += bezt->vec[1][0];
+ /* only if selected */
+ if (bezt->f2 & SELECT) {
+ /* store average time in float 1 (only do rounding at last step) */
+ ked->f1 += bezt->vec[1][0];
- /* store average value in float 2 (only do rounding at last step)
- * - this isn't always needed, but some operators may also require this
- */
- ked->f2 += bezt->vec[1][1];
+ /* store average value in float 2 (only do rounding at last step)
+ * - this isn't always needed, but some operators may also require this
+ */
+ ked->f2 += bezt->vec[1][1];
- /* increment number of items */
- ked->i1++;
- }
+ /* increment number of items */
+ ked->i1++;
+ }
- return 0;
+ return 0;
}
/* helper callback for columnselect_<animeditor>_keys() -> populate
* list CfraElems with frame numbers from selected beztriples */
short bezt_to_cfraelem(KeyframeEditData *ked, BezTriple *bezt)
{
- /* only if selected */
- if (bezt->f2 & SELECT) {
- CfraElem *ce = MEM_callocN(sizeof(CfraElem), "cfraElem");
- BLI_addtail(&ked->list, ce);
+ /* only if selected */
+ if (bezt->f2 & SELECT) {
+ CfraElem *ce = MEM_callocN(sizeof(CfraElem), "cfraElem");
+ BLI_addtail(&ked->list, ce);
- ce->cfra = bezt->vec[1][0];
- }
+ ce->cfra = bezt->vec[1][0];
+ }
- return 0;
+ return 0;
}
/* used to remap times from one range to another
@@ -746,15 +781,15 @@ short bezt_to_cfraelem(KeyframeEditData *ked, BezTriple *bezt)
*/
void bezt_remap_times(KeyframeEditData *ked, BezTriple *bezt)
{
- KeyframeEditCD_Remap *rmap = (KeyframeEditCD_Remap *)ked->data;
- const float scale = (rmap->newMax - rmap->newMin) / (rmap->oldMax - rmap->oldMin);
+ KeyframeEditCD_Remap *rmap = (KeyframeEditCD_Remap *)ked->data;
+ const float scale = (rmap->newMax - rmap->newMin) / (rmap->oldMax - rmap->oldMin);
- /* perform transform on all three handles unless indicated otherwise */
- // TODO: need to include some checks for that
+ /* perform transform on all three handles unless indicated otherwise */
+ // TODO: need to include some checks for that
- bezt->vec[0][0] = scale * (bezt->vec[0][0] - rmap->oldMin) + rmap->newMin;
- bezt->vec[1][0] = scale * (bezt->vec[1][0] - rmap->oldMin) + rmap->newMin;
- bezt->vec[2][0] = scale * (bezt->vec[2][0] - rmap->oldMin) + rmap->newMin;
+ bezt->vec[0][0] = scale * (bezt->vec[0][0] - rmap->oldMin) + rmap->newMin;
+ bezt->vec[1][0] = scale * (bezt->vec[1][0] - rmap->oldMin) + rmap->newMin;
+ bezt->vec[2][0] = scale * (bezt->vec[2][0] - rmap->oldMin) + rmap->newMin;
}
/* ******************************************* */
@@ -763,199 +798,201 @@ void bezt_remap_times(KeyframeEditData *ked, BezTriple *bezt)
/* snaps the keyframe to the nearest frame */
static short snap_bezier_nearest(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->vec[1][0] = (float)(floorf(bezt->vec[1][0] + 0.5f));
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->vec[1][0] = (float)(floorf(bezt->vec[1][0] + 0.5f));
+ return 0;
}
/* snaps the keyframe to the nearest second */
static short snap_bezier_nearestsec(KeyframeEditData *ked, BezTriple *bezt)
{
- const Scene *scene = ked->scene;
- const float secf = (float)FPS;
+ const Scene *scene = ked->scene;
+ const float secf = (float)FPS;
- if (bezt->f2 & SELECT)
- bezt->vec[1][0] = (floorf(bezt->vec[1][0] / secf + 0.5f) * secf);
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->vec[1][0] = (floorf(bezt->vec[1][0] / secf + 0.5f) * secf);
+ return 0;
}
/* snaps the keyframe to the current frame */
static short snap_bezier_cframe(KeyframeEditData *ked, BezTriple *bezt)
{
- const Scene *scene = ked->scene;
- if (bezt->f2 & SELECT)
- bezt->vec[1][0] = (float)CFRA;
- return 0;
+ const Scene *scene = ked->scene;
+ if (bezt->f2 & SELECT)
+ bezt->vec[1][0] = (float)CFRA;
+ return 0;
}
/* snaps the keyframe time to the nearest marker's frame */
static short snap_bezier_nearmarker(KeyframeEditData *ked, BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->vec[1][0] = (float)ED_markers_find_nearest_marker_time(&ked->list, bezt->vec[1][0]);
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->vec[1][0] = (float)ED_markers_find_nearest_marker_time(&ked->list, bezt->vec[1][0]);
+ return 0;
}
/* make the handles have the same value as the key */
static short snap_bezier_horizontal(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT) {
- bezt->vec[0][1] = bezt->vec[2][1] = bezt->vec[1][1];
+ if (bezt->f2 & SELECT) {
+ bezt->vec[0][1] = bezt->vec[2][1] = bezt->vec[1][1];
- if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) bezt->h1 = HD_ALIGN;
- if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) bezt->h2 = HD_ALIGN;
- }
- return 0;
+ if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM, HD_VECT))
+ bezt->h1 = HD_ALIGN;
+ if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM, HD_VECT))
+ bezt->h2 = HD_ALIGN;
+ }
+ return 0;
}
/* frame to snap to is stored in the custom data -> first float value slot */
static short snap_bezier_time(KeyframeEditData *ked, BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->vec[1][0] = ked->f1;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->vec[1][0] = ked->f1;
+ return 0;
}
/* value to snap to is stored in the custom data -> first float value slot */
static short snap_bezier_value(KeyframeEditData *ked, BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->vec[1][1] = ked->f1;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->vec[1][1] = ked->f1;
+ return 0;
}
KeyframeEditFunc ANIM_editkeyframes_snap(short type)
{
- /* eEditKeyframes_Snap */
- switch (type) {
- case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */
- return snap_bezier_nearest;
- case SNAP_KEYS_CURFRAME: /* snap to current frame */
- return snap_bezier_cframe;
- case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */
- return snap_bezier_nearmarker;
- case SNAP_KEYS_NEARSEC: /* snap to nearest second */
- return snap_bezier_nearestsec;
- case SNAP_KEYS_HORIZONTAL: /* snap handles to same value */
- return snap_bezier_horizontal;
- case SNAP_KEYS_TIME: /* snap to given frame/time */
- return snap_bezier_time;
- case SNAP_KEYS_VALUE: /* snap to given value */
- return snap_bezier_value;
- default: /* just in case */
- return snap_bezier_nearest;
- }
+ /* eEditKeyframes_Snap */
+ switch (type) {
+ case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */
+ return snap_bezier_nearest;
+ case SNAP_KEYS_CURFRAME: /* snap to current frame */
+ return snap_bezier_cframe;
+ case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */
+ return snap_bezier_nearmarker;
+ case SNAP_KEYS_NEARSEC: /* snap to nearest second */
+ return snap_bezier_nearestsec;
+ case SNAP_KEYS_HORIZONTAL: /* snap handles to same value */
+ return snap_bezier_horizontal;
+ case SNAP_KEYS_TIME: /* snap to given frame/time */
+ return snap_bezier_time;
+ case SNAP_KEYS_VALUE: /* snap to given value */
+ return snap_bezier_value;
+ default: /* just in case */
+ return snap_bezier_nearest;
+ }
}
/* --------- */
static void mirror_bezier_xaxis_ex(BezTriple *bezt, const float center)
{
- float diff;
- int i;
+ float diff;
+ int i;
- for (i = 0; i < 3; i++) {
- diff = (center - bezt->vec[i][0]);
- bezt->vec[i][0] = (center + diff);
- }
- swap_v3_v3(bezt->vec[0], bezt->vec[2]);
+ for (i = 0; i < 3; i++) {
+ diff = (center - bezt->vec[i][0]);
+ bezt->vec[i][0] = (center + diff);
+ }
+ swap_v3_v3(bezt->vec[0], bezt->vec[2]);
- SWAP(char, bezt->h1, bezt->h2);
- SWAP(char, bezt->f1, bezt->f3);
+ SWAP(char, bezt->h1, bezt->h2);
+ SWAP(char, bezt->f1, bezt->f3);
}
static void mirror_bezier_yaxis_ex(BezTriple *bezt, const float center)
{
- float diff;
- int i;
+ float diff;
+ int i;
- for (i = 0; i < 3; i++) {
- diff = (center - bezt->vec[i][1]);
- bezt->vec[i][1] = (center + diff);
- }
+ for (i = 0; i < 3; i++) {
+ diff = (center - bezt->vec[i][1]);
+ bezt->vec[i][1] = (center + diff);
+ }
}
static short mirror_bezier_cframe(KeyframeEditData *ked, BezTriple *bezt)
{
- const Scene *scene = ked->scene;
+ const Scene *scene = ked->scene;
- if (bezt->f2 & SELECT) {
- mirror_bezier_xaxis_ex(bezt, CFRA);
- }
+ if (bezt->f2 & SELECT) {
+ mirror_bezier_xaxis_ex(bezt, CFRA);
+ }
- return 0;
+ return 0;
}
static short mirror_bezier_yaxis(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT) {
- /* Yes, names are inverted, we are mirroring across y axis, hence along x axis... */
- mirror_bezier_xaxis_ex(bezt, 0.0f);
- }
+ if (bezt->f2 & SELECT) {
+ /* Yes, names are inverted, we are mirroring across y axis, hence along x axis... */
+ mirror_bezier_xaxis_ex(bezt, 0.0f);
+ }
- return 0;
+ return 0;
}
static short mirror_bezier_xaxis(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT) {
- /* Yes, names are inverted, we are mirroring across x axis, hence along y axis... */
- mirror_bezier_yaxis_ex(bezt, 0.0f);
- }
+ if (bezt->f2 & SELECT) {
+ /* Yes, names are inverted, we are mirroring across x axis, hence along y axis... */
+ mirror_bezier_yaxis_ex(bezt, 0.0f);
+ }
- return 0;
+ return 0;
}
static short mirror_bezier_marker(KeyframeEditData *ked, BezTriple *bezt)
{
- /* mirroring time stored in f1 */
- if (bezt->f2 & SELECT) {
- mirror_bezier_xaxis_ex(bezt, ked->f1);
- }
+ /* mirroring time stored in f1 */
+ if (bezt->f2 & SELECT) {
+ mirror_bezier_xaxis_ex(bezt, ked->f1);
+ }
- return 0;
+ return 0;
}
static short mirror_bezier_time(KeyframeEditData *ked, BezTriple *bezt)
{
- /* value to mirror over is stored in f1 */
- if (bezt->f2 & SELECT) {
- mirror_bezier_xaxis_ex(bezt, ked->f1);
- }
+ /* value to mirror over is stored in f1 */
+ if (bezt->f2 & SELECT) {
+ mirror_bezier_xaxis_ex(bezt, ked->f1);
+ }
- return 0;
+ return 0;
}
static short mirror_bezier_value(KeyframeEditData *ked, BezTriple *bezt)
{
- /* value to mirror over is stored in the custom data -> first float value slot */
- if (bezt->f2 & SELECT) {
- mirror_bezier_yaxis_ex(bezt, ked->f1);
- }
+ /* value to mirror over is stored in the custom data -> first float value slot */
+ if (bezt->f2 & SELECT) {
+ mirror_bezier_yaxis_ex(bezt, ked->f1);
+ }
- return 0;
+ return 0;
}
/* Note: for markers and 'value', the values to use must be supplied as the first float value */
// calchandles_fcurve
KeyframeEditFunc ANIM_editkeyframes_mirror(short type)
{
- switch (type) {
- case MIRROR_KEYS_CURFRAME: /* mirror over current frame */
- return mirror_bezier_cframe;
- case MIRROR_KEYS_YAXIS: /* mirror over frame 0 */
- return mirror_bezier_yaxis;
- case MIRROR_KEYS_XAXIS: /* mirror over value 0 */
- return mirror_bezier_xaxis;
- case MIRROR_KEYS_MARKER: /* mirror over marker */
- return mirror_bezier_marker;
- case MIRROR_KEYS_TIME: /* mirror over frame/time */
- return mirror_bezier_time;
- case MIRROR_KEYS_VALUE: /* mirror over given value */
- return mirror_bezier_value;
- default: /* just in case */
- return mirror_bezier_yaxis;
- }
+ switch (type) {
+ case MIRROR_KEYS_CURFRAME: /* mirror over current frame */
+ return mirror_bezier_cframe;
+ case MIRROR_KEYS_YAXIS: /* mirror over frame 0 */
+ return mirror_bezier_yaxis;
+ case MIRROR_KEYS_XAXIS: /* mirror over value 0 */
+ return mirror_bezier_xaxis;
+ case MIRROR_KEYS_MARKER: /* mirror over marker */
+ return mirror_bezier_marker;
+ case MIRROR_KEYS_TIME: /* mirror over frame/time */
+ return mirror_bezier_time;
+ case MIRROR_KEYS_VALUE: /* mirror over given value */
+ return mirror_bezier_value;
+ default: /* just in case */
+ return mirror_bezier_yaxis;
+ }
}
/* ******************************************* */
@@ -964,24 +1001,27 @@ KeyframeEditFunc ANIM_editkeyframes_mirror(short type)
/* standard validation step for a few of these (implemented as macro for inlining without fn-call overhead):
* "if the handles are not of the same type, set them to type free"
*/
-#define ENSURE_HANDLES_MATCH(bezt) \
- if (bezt->h1 != bezt->h2) { \
- if (ELEM(bezt->h1, HD_ALIGN, HD_AUTO, HD_AUTO_ANIM)) \
- bezt->h1 = HD_FREE; \
- if (ELEM(bezt->h2, HD_ALIGN, HD_AUTO, HD_AUTO_ANIM)) \
- bezt->h2 = HD_FREE; \
- } (void)0
+#define ENSURE_HANDLES_MATCH(bezt) \
+ if (bezt->h1 != bezt->h2) { \
+ if (ELEM(bezt->h1, HD_ALIGN, HD_AUTO, HD_AUTO_ANIM)) \
+ bezt->h1 = HD_FREE; \
+ if (ELEM(bezt->h2, HD_ALIGN, HD_AUTO, HD_AUTO_ANIM)) \
+ bezt->h2 = HD_FREE; \
+ } \
+ (void)0
/* Sets the selected bezier handles to type 'auto' */
static short set_bezier_auto(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if ((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) {
- if (bezt->f1 & SELECT) bezt->h1 = HD_AUTO;
- if (bezt->f3 & SELECT) bezt->h2 = HD_AUTO;
+ if ((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) {
+ if (bezt->f1 & SELECT)
+ bezt->h1 = HD_AUTO;
+ if (bezt->f3 & SELECT)
+ bezt->h2 = HD_AUTO;
- ENSURE_HANDLES_MATCH(bezt);
- }
- return 0;
+ ENSURE_HANDLES_MATCH(bezt);
+ }
+ return 0;
}
/* Sets the selected bezier handles to type 'auto-clamped'
@@ -989,307 +1029,317 @@ static short set_bezier_auto(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
*/
static short set_bezier_auto_clamped(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if ((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) {
- if (bezt->f1 & SELECT) bezt->h1 = HD_AUTO_ANIM;
- if (bezt->f3 & SELECT) bezt->h2 = HD_AUTO_ANIM;
+ if ((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) {
+ if (bezt->f1 & SELECT)
+ bezt->h1 = HD_AUTO_ANIM;
+ if (bezt->f3 & SELECT)
+ bezt->h2 = HD_AUTO_ANIM;
- ENSURE_HANDLES_MATCH(bezt);
- }
- return 0;
+ ENSURE_HANDLES_MATCH(bezt);
+ }
+ return 0;
}
/* Sets the selected bezier handles to type 'vector' */
static short set_bezier_vector(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f1 & SELECT) bezt->h1 = HD_VECT;
- if (bezt->f3 & SELECT) bezt->h2 = HD_VECT;
- return 0;
+ if (bezt->f1 & SELECT)
+ bezt->h1 = HD_VECT;
+ if (bezt->f3 & SELECT)
+ bezt->h2 = HD_VECT;
+ return 0;
}
/* Queries if the handle should be set to 'free' or 'align' */
// NOTE: this was used for the 'toggle free/align' option
-// currently this isn't used, but may be restored later
+// currently this isn't used, but may be restored later
static short bezier_isfree(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if ((bezt->f1 & SELECT) && (bezt->h1)) return 1;
- if ((bezt->f3 & SELECT) && (bezt->h2)) return 1;
- return 0;
+ if ((bezt->f1 & SELECT) && (bezt->h1))
+ return 1;
+ if ((bezt->f3 & SELECT) && (bezt->h2))
+ return 1;
+ return 0;
}
/* Sets selected bezier handles to type 'align' */
static short set_bezier_align(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f1 & SELECT) bezt->h1 = HD_ALIGN;
- if (bezt->f3 & SELECT) bezt->h2 = HD_ALIGN;
- return 0;
+ if (bezt->f1 & SELECT)
+ bezt->h1 = HD_ALIGN;
+ if (bezt->f3 & SELECT)
+ bezt->h2 = HD_ALIGN;
+ return 0;
}
/* Sets selected bezier handles to type 'free' */
static short set_bezier_free(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f1 & SELECT) bezt->h1 = HD_FREE;
- if (bezt->f3 & SELECT) bezt->h2 = HD_FREE;
- return 0;
+ if (bezt->f1 & SELECT)
+ bezt->h1 = HD_FREE;
+ if (bezt->f3 & SELECT)
+ bezt->h2 = HD_FREE;
+ return 0;
}
/* Set all selected Bezier Handles to a single type */
// calchandles_fcurve
KeyframeEditFunc ANIM_editkeyframes_handles(short code)
{
- switch (code) {
- case HD_AUTO: /* auto */
- return set_bezier_auto;
- case HD_AUTO_ANIM: /* auto clamped */
- return set_bezier_auto_clamped;
+ switch (code) {
+ case HD_AUTO: /* auto */
+ return set_bezier_auto;
+ case HD_AUTO_ANIM: /* auto clamped */
+ return set_bezier_auto_clamped;
- case HD_VECT: /* vector */
- return set_bezier_vector;
- case HD_FREE: /* free */
- return set_bezier_free;
- case HD_ALIGN: /* align */
- return set_bezier_align;
+ case HD_VECT: /* vector */
+ return set_bezier_vector;
+ case HD_FREE: /* free */
+ return set_bezier_free;
+ case HD_ALIGN: /* align */
+ return set_bezier_align;
- default: /* check for toggle free or align? */
- return bezier_isfree;
- }
+ default: /* check for toggle free or align? */
+ return bezier_isfree;
+ }
}
/* ------- */
static short set_bezt_constant(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->ipo = BEZT_IPO_CONST;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->ipo = BEZT_IPO_CONST;
+ return 0;
}
static short set_bezt_linear(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->ipo = BEZT_IPO_LIN;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->ipo = BEZT_IPO_LIN;
+ return 0;
}
static short set_bezt_bezier(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->ipo = BEZT_IPO_BEZ;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->ipo = BEZT_IPO_BEZ;
+ return 0;
}
static short set_bezt_back(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->ipo = BEZT_IPO_BACK;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->ipo = BEZT_IPO_BACK;
+ return 0;
}
static short set_bezt_bounce(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->ipo = BEZT_IPO_BOUNCE;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->ipo = BEZT_IPO_BOUNCE;
+ return 0;
}
static short set_bezt_circle(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->ipo = BEZT_IPO_CIRC;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->ipo = BEZT_IPO_CIRC;
+ return 0;
}
static short set_bezt_cubic(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->ipo = BEZT_IPO_CUBIC;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->ipo = BEZT_IPO_CUBIC;
+ return 0;
}
static short set_bezt_elastic(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->ipo = BEZT_IPO_ELASTIC;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->ipo = BEZT_IPO_ELASTIC;
+ return 0;
}
static short set_bezt_expo(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->ipo = BEZT_IPO_EXPO;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->ipo = BEZT_IPO_EXPO;
+ return 0;
}
static short set_bezt_quad(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->ipo = BEZT_IPO_QUAD;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->ipo = BEZT_IPO_QUAD;
+ return 0;
}
static short set_bezt_quart(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->ipo = BEZT_IPO_QUART;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->ipo = BEZT_IPO_QUART;
+ return 0;
}
static short set_bezt_quint(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->ipo = BEZT_IPO_QUINT;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->ipo = BEZT_IPO_QUINT;
+ return 0;
}
static short set_bezt_sine(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->ipo = BEZT_IPO_SINE;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->ipo = BEZT_IPO_SINE;
+ return 0;
}
/* Set the interpolation type of the selected BezTriples in each F-Curve to the specified one */
// ANIM_editkeyframes_ipocurve_ipotype() !
KeyframeEditFunc ANIM_editkeyframes_ipo(short code)
{
- switch (code) {
- /* interpolation */
- case BEZT_IPO_CONST: /* constant */
- return set_bezt_constant;
- case BEZT_IPO_LIN: /* linear */
- return set_bezt_linear;
-
- /* easing */
- case BEZT_IPO_BACK:
- return set_bezt_back;
- case BEZT_IPO_BOUNCE:
- return set_bezt_bounce;
- case BEZT_IPO_CIRC:
- return set_bezt_circle;
- case BEZT_IPO_CUBIC:
- return set_bezt_cubic;
- case BEZT_IPO_ELASTIC:
- return set_bezt_elastic;
- case BEZT_IPO_EXPO:
- return set_bezt_expo;
- case BEZT_IPO_QUAD:
- return set_bezt_quad;
- case BEZT_IPO_QUART:
- return set_bezt_quart;
- case BEZT_IPO_QUINT:
- return set_bezt_quint;
- case BEZT_IPO_SINE:
- return set_bezt_sine;
-
- default: /* bezier */
- return set_bezt_bezier;
- }
+ switch (code) {
+ /* interpolation */
+ case BEZT_IPO_CONST: /* constant */
+ return set_bezt_constant;
+ case BEZT_IPO_LIN: /* linear */
+ return set_bezt_linear;
+
+ /* easing */
+ case BEZT_IPO_BACK:
+ return set_bezt_back;
+ case BEZT_IPO_BOUNCE:
+ return set_bezt_bounce;
+ case BEZT_IPO_CIRC:
+ return set_bezt_circle;
+ case BEZT_IPO_CUBIC:
+ return set_bezt_cubic;
+ case BEZT_IPO_ELASTIC:
+ return set_bezt_elastic;
+ case BEZT_IPO_EXPO:
+ return set_bezt_expo;
+ case BEZT_IPO_QUAD:
+ return set_bezt_quad;
+ case BEZT_IPO_QUART:
+ return set_bezt_quart;
+ case BEZT_IPO_QUINT:
+ return set_bezt_quint;
+ case BEZT_IPO_SINE:
+ return set_bezt_sine;
+
+ default: /* bezier */
+ return set_bezt_bezier;
+ }
}
/* ------- */
static short set_keytype_keyframe(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- BEZKEYTYPE(bezt) = BEZT_KEYTYPE_KEYFRAME;
- return 0;
+ if (bezt->f2 & SELECT)
+ BEZKEYTYPE(bezt) = BEZT_KEYTYPE_KEYFRAME;
+ return 0;
}
static short set_keytype_breakdown(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- BEZKEYTYPE(bezt) = BEZT_KEYTYPE_BREAKDOWN;
- return 0;
+ if (bezt->f2 & SELECT)
+ BEZKEYTYPE(bezt) = BEZT_KEYTYPE_BREAKDOWN;
+ return 0;
}
static short set_keytype_extreme(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- BEZKEYTYPE(bezt) = BEZT_KEYTYPE_EXTREME;
- return 0;
+ if (bezt->f2 & SELECT)
+ BEZKEYTYPE(bezt) = BEZT_KEYTYPE_EXTREME;
+ return 0;
}
static short set_keytype_jitter(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- BEZKEYTYPE(bezt) = BEZT_KEYTYPE_JITTER;
- return 0;
+ if (bezt->f2 & SELECT)
+ BEZKEYTYPE(bezt) = BEZT_KEYTYPE_JITTER;
+ return 0;
}
static short set_keytype_moving_hold(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- BEZKEYTYPE(bezt) = BEZT_KEYTYPE_MOVEHOLD;
- return 0;
+ if (bezt->f2 & SELECT)
+ BEZKEYTYPE(bezt) = BEZT_KEYTYPE_MOVEHOLD;
+ return 0;
}
/* Set the interpolation type of the selected BezTriples in each F-Curve to the specified one */
KeyframeEditFunc ANIM_editkeyframes_keytype(short code)
{
- switch (code) {
- case BEZT_KEYTYPE_BREAKDOWN: /* breakdown */
- return set_keytype_breakdown;
+ switch (code) {
+ case BEZT_KEYTYPE_BREAKDOWN: /* breakdown */
+ return set_keytype_breakdown;
- case BEZT_KEYTYPE_EXTREME: /* extreme keyframe */
- return set_keytype_extreme;
+ case BEZT_KEYTYPE_EXTREME: /* extreme keyframe */
+ return set_keytype_extreme;
- case BEZT_KEYTYPE_JITTER: /* jitter keyframe */
- return set_keytype_jitter;
+ case BEZT_KEYTYPE_JITTER: /* jitter keyframe */
+ return set_keytype_jitter;
- case BEZT_KEYTYPE_MOVEHOLD: /* moving hold */
- return set_keytype_moving_hold;
+ case BEZT_KEYTYPE_MOVEHOLD: /* moving hold */
+ return set_keytype_moving_hold;
- case BEZT_KEYTYPE_KEYFRAME: /* proper keyframe */
- default:
- return set_keytype_keyframe;
- }
+ case BEZT_KEYTYPE_KEYFRAME: /* proper keyframe */
+ default:
+ return set_keytype_keyframe;
+ }
}
/* ------- */
static short set_easingtype_easein(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->easing = BEZT_IPO_EASE_IN;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->easing = BEZT_IPO_EASE_IN;
+ return 0;
}
static short set_easingtype_easeout(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->easing = BEZT_IPO_EASE_OUT;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->easing = BEZT_IPO_EASE_OUT;
+ return 0;
}
static short set_easingtype_easeinout(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->easing = BEZT_IPO_EASE_IN_OUT;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->easing = BEZT_IPO_EASE_IN_OUT;
+ return 0;
}
static short set_easingtype_easeauto(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- if (bezt->f2 & SELECT)
- bezt->easing = BEZT_IPO_EASE_AUTO;
- return 0;
+ if (bezt->f2 & SELECT)
+ bezt->easing = BEZT_IPO_EASE_AUTO;
+ return 0;
}
/* Set the easing type of the selected BezTriples in each F-Curve to the specified one */
KeyframeEditFunc ANIM_editkeyframes_easing(short mode)
{
- switch (mode) {
- case BEZT_IPO_EASE_IN: /* ease in */
- return set_easingtype_easein;
+ switch (mode) {
+ case BEZT_IPO_EASE_IN: /* ease in */
+ return set_easingtype_easein;
- case BEZT_IPO_EASE_OUT: /* ease out */
- return set_easingtype_easeout;
+ case BEZT_IPO_EASE_OUT: /* ease out */
+ return set_easingtype_easeout;
- case BEZT_IPO_EASE_IN_OUT: /* both */
- return set_easingtype_easeinout;
+ case BEZT_IPO_EASE_IN_OUT: /* both */
+ return set_easingtype_easeinout;
- default: /* auto */
- return set_easingtype_easeauto;
- }
+ default: /* auto */
+ return set_easingtype_easeauto;
+ }
}
/* ******************************************* */
@@ -1297,67 +1347,67 @@ KeyframeEditFunc ANIM_editkeyframes_easing(short mode)
static short select_bezier_add(KeyframeEditData *ked, BezTriple *bezt)
{
- /* if we've got info on what to select, use it, otherwise select all */
- if ((ked) && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) {
- if (ked->curflags & KEYFRAME_OK_KEY)
- bezt->f2 |= SELECT;
- if (ked->curflags & KEYFRAME_OK_H1)
- bezt->f1 |= SELECT;
- if (ked->curflags & KEYFRAME_OK_H2)
- bezt->f3 |= SELECT;
- }
- else {
- BEZT_SEL_ALL(bezt);
- }
+ /* if we've got info on what to select, use it, otherwise select all */
+ if ((ked) && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) {
+ if (ked->curflags & KEYFRAME_OK_KEY)
+ bezt->f2 |= SELECT;
+ if (ked->curflags & KEYFRAME_OK_H1)
+ bezt->f1 |= SELECT;
+ if (ked->curflags & KEYFRAME_OK_H2)
+ bezt->f3 |= SELECT;
+ }
+ else {
+ BEZT_SEL_ALL(bezt);
+ }
- return 0;
+ return 0;
}
static short select_bezier_subtract(KeyframeEditData *ked, BezTriple *bezt)
{
- /* if we've got info on what to deselect, use it, otherwise deselect all */
- if ((ked) && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) {
- if (ked->curflags & KEYFRAME_OK_KEY)
- bezt->f2 &= ~SELECT;
- if (ked->curflags & KEYFRAME_OK_H1)
- bezt->f1 &= ~SELECT;
- if (ked->curflags & KEYFRAME_OK_H2)
- bezt->f3 &= ~SELECT;
- }
- else {
- BEZT_DESEL_ALL(bezt);
- }
+ /* if we've got info on what to deselect, use it, otherwise deselect all */
+ if ((ked) && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) {
+ if (ked->curflags & KEYFRAME_OK_KEY)
+ bezt->f2 &= ~SELECT;
+ if (ked->curflags & KEYFRAME_OK_H1)
+ bezt->f1 &= ~SELECT;
+ if (ked->curflags & KEYFRAME_OK_H2)
+ bezt->f3 &= ~SELECT;
+ }
+ else {
+ BEZT_DESEL_ALL(bezt);
+ }
- return 0;
+ return 0;
}
static short select_bezier_invert(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
- /* Invert the selection for the whole bezier triple */
- bezt->f2 ^= SELECT;
- if (bezt->f2 & SELECT) {
- bezt->f1 |= SELECT;
- bezt->f3 |= SELECT;
- }
- else {
- bezt->f1 &= ~SELECT;
- bezt->f3 &= ~SELECT;
- }
- return 0;
+ /* Invert the selection for the whole bezier triple */
+ bezt->f2 ^= SELECT;
+ if (bezt->f2 & SELECT) {
+ bezt->f1 |= SELECT;
+ bezt->f3 |= SELECT;
+ }
+ else {
+ bezt->f1 &= ~SELECT;
+ bezt->f3 &= ~SELECT;
+ }
+ return 0;
}
KeyframeEditFunc ANIM_editkeyframes_select(short selectmode)
{
- switch (selectmode) {
- case SELECT_ADD: /* add */
- return select_bezier_add;
- case SELECT_SUBTRACT: /* subtract */
- return select_bezier_subtract;
- case SELECT_INVERT: /* invert */
- return select_bezier_invert;
- default: /* replace (need to clear all, then add) */
- return select_bezier_add;
- }
+ switch (selectmode) {
+ case SELECT_ADD: /* add */
+ return select_bezier_add;
+ case SELECT_SUBTRACT: /* subtract */
+ return select_bezier_subtract;
+ case SELECT_INVERT: /* invert */
+ return select_bezier_invert;
+ default: /* replace (need to clear all, then add) */
+ return select_bezier_add;
+ }
}
/* ******************************************* */
@@ -1373,91 +1423,91 @@ KeyframeEditFunc ANIM_editkeyframes_select(short selectmode)
static short selmap_build_bezier_more(KeyframeEditData *ked, BezTriple *bezt)
{
- FCurve *fcu = ked->fcu;
- char *map = ked->data;
- int i = ked->curIndex;
+ FCurve *fcu = ked->fcu;
+ char *map = ked->data;
+ int i = ked->curIndex;
- /* if current is selected, just make sure it stays this way */
- if (BEZT_ISSEL_ANY(bezt)) {
- map[i] = 1;
- return 0;
- }
+ /* if current is selected, just make sure it stays this way */
+ if (BEZT_ISSEL_ANY(bezt)) {
+ map[i] = 1;
+ return 0;
+ }
- /* if previous is selected, that means that selection should extend across */
- if (i > 0) {
- BezTriple *prev = bezt - 1;
+ /* if previous is selected, that means that selection should extend across */
+ if (i > 0) {
+ BezTriple *prev = bezt - 1;
- if (BEZT_ISSEL_ANY(prev)) {
- map[i] = 1;
- return 0;
- }
- }
+ if (BEZT_ISSEL_ANY(prev)) {
+ map[i] = 1;
+ return 0;
+ }
+ }
- /* if next is selected, that means that selection should extend across */
- if (i < (fcu->totvert - 1)) {
- BezTriple *next = bezt + 1;
+ /* if next is selected, that means that selection should extend across */
+ if (i < (fcu->totvert - 1)) {
+ BezTriple *next = bezt + 1;
- if (BEZT_ISSEL_ANY(next)) {
- map[i] = 1;
- return 0;
- }
- }
+ if (BEZT_ISSEL_ANY(next)) {
+ map[i] = 1;
+ return 0;
+ }
+ }
- return 0;
+ return 0;
}
static short selmap_build_bezier_less(KeyframeEditData *ked, BezTriple *bezt)
{
- FCurve *fcu = ked->fcu;
- char *map = ked->data;
- int i = ked->curIndex;
-
- /* if current is selected, check the left/right keyframes
- * since it might need to be deselected (but otherwise no)
- */
- if (BEZT_ISSEL_ANY(bezt)) {
- /* if previous is not selected, we're on the tip of an iceberg */
- if (i > 0) {
- BezTriple *prev = bezt - 1;
-
- if (BEZT_ISSEL_ANY(prev) == 0)
- return 0;
- }
- else if (i == 0) {
- /* current keyframe is selected at an endpoint, so should get deselected */
- return 0;
- }
-
- /* if next is not selected, we're on the tip of an iceberg */
- if (i < (fcu->totvert - 1)) {
- BezTriple *next = bezt + 1;
-
- if (BEZT_ISSEL_ANY(next) == 0)
- return 0;
- }
- else if (i == (fcu->totvert - 1)) {
- /* current keyframe is selected at an endpoint, so should get deselected */
- return 0;
- }
-
- /* if we're still here, that means that keyframe should remain untouched */
- map[i] = 1;
- }
-
- return 0;
+ FCurve *fcu = ked->fcu;
+ char *map = ked->data;
+ int i = ked->curIndex;
+
+ /* if current is selected, check the left/right keyframes
+ * since it might need to be deselected (but otherwise no)
+ */
+ if (BEZT_ISSEL_ANY(bezt)) {
+ /* if previous is not selected, we're on the tip of an iceberg */
+ if (i > 0) {
+ BezTriple *prev = bezt - 1;
+
+ if (BEZT_ISSEL_ANY(prev) == 0)
+ return 0;
+ }
+ else if (i == 0) {
+ /* current keyframe is selected at an endpoint, so should get deselected */
+ return 0;
+ }
+
+ /* if next is not selected, we're on the tip of an iceberg */
+ if (i < (fcu->totvert - 1)) {
+ BezTriple *next = bezt + 1;
+
+ if (BEZT_ISSEL_ANY(next) == 0)
+ return 0;
+ }
+ else if (i == (fcu->totvert - 1)) {
+ /* current keyframe is selected at an endpoint, so should get deselected */
+ return 0;
+ }
+
+ /* if we're still here, that means that keyframe should remain untouched */
+ map[i] = 1;
+ }
+
+ return 0;
}
/* Get callback for building selection map */
KeyframeEditFunc ANIM_editkeyframes_buildselmap(short mode)
{
- switch (mode) {
- case SELMAP_LESS: /* less */
- return selmap_build_bezier_less;
+ switch (mode) {
+ case SELMAP_LESS: /* less */
+ return selmap_build_bezier_less;
- case SELMAP_MORE: /* more */
- default:
- return selmap_build_bezier_more;
- }
+ case SELMAP_MORE: /* more */
+ default:
+ return selmap_build_bezier_more;
+ }
}
/* ----------- */
@@ -1465,16 +1515,16 @@ KeyframeEditFunc ANIM_editkeyframes_buildselmap(short mode)
/* flush selection map values to the given beztriple */
short bezt_selmap_flush(KeyframeEditData *ked, BezTriple *bezt)
{
- const char *map = ked->data;
- short on = map[ked->curIndex];
+ const char *map = ked->data;
+ short on = map[ked->curIndex];
- /* select or deselect based on whether the map allows it or not */
- if (on) {
- BEZT_SEL_ALL(bezt);
- }
- else {
- BEZT_DESEL_ALL(bezt);
- }
+ /* select or deselect based on whether the map allows it or not */
+ if (on) {
+ BEZT_SEL_ALL(bezt);
+ }
+ else {
+ BEZT_DESEL_ALL(bezt);
+ }
- return 0;
+ return 0;
}
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index c9e672a111d..945327ed78b 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -21,7 +21,6 @@
* \ingroup edanimation
*/
-
#include <stdlib.h>
#include <string.h>
#include <math.h>
@@ -37,7 +36,6 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-
#include "BKE_action.h"
#include "BKE_fcurve.h"
#include "BKE_report.h"
@@ -71,68 +69,68 @@
*/
void delete_fcurve_key(FCurve *fcu, int index, bool do_recalc)
{
- /* sanity check */
- if (fcu == NULL)
- return;
-
- /* verify the index:
- * 1) cannot be greater than the number of available keyframes
- * 2) negative indices are for specifying a value from the end of the array
- */
- if (abs(index) >= fcu->totvert)
- return;
- else if (index < 0)
- index += fcu->totvert;
-
- /* Delete this keyframe */
- memmove(&fcu->bezt[index], &fcu->bezt[index + 1], sizeof(BezTriple) * (fcu->totvert - index - 1));
- fcu->totvert--;
-
- if (fcu->totvert == 0) {
- if (fcu->bezt)
- MEM_freeN(fcu->bezt);
- fcu->bezt = NULL;
- }
-
- /* recalc handles - only if it won't cause problems */
- if (do_recalc)
- calchandles_fcurve(fcu);
+ /* sanity check */
+ if (fcu == NULL)
+ return;
+
+ /* verify the index:
+ * 1) cannot be greater than the number of available keyframes
+ * 2) negative indices are for specifying a value from the end of the array
+ */
+ if (abs(index) >= fcu->totvert)
+ return;
+ else if (index < 0)
+ index += fcu->totvert;
+
+ /* Delete this keyframe */
+ memmove(
+ &fcu->bezt[index], &fcu->bezt[index + 1], sizeof(BezTriple) * (fcu->totvert - index - 1));
+ fcu->totvert--;
+
+ if (fcu->totvert == 0) {
+ if (fcu->bezt)
+ MEM_freeN(fcu->bezt);
+ fcu->bezt = NULL;
+ }
+
+ /* recalc handles - only if it won't cause problems */
+ if (do_recalc)
+ calchandles_fcurve(fcu);
}
/* Delete selected keyframes in given F-Curve */
bool delete_fcurve_keys(FCurve *fcu)
{
- int i;
- bool changed = false;
-
- if (fcu->bezt == NULL) /* ignore baked curves */
- return false;
-
- /* Delete selected BezTriples */
- for (i = 0; i < fcu->totvert; i++) {
- if (fcu->bezt[i].f2 & SELECT) {
- memmove(&fcu->bezt[i], &fcu->bezt[i + 1], sizeof(BezTriple) * (fcu->totvert - i - 1));
- fcu->totvert--;
- i--;
- changed = true;
- }
- }
-
- /* Free the array of BezTriples if there are not keyframes */
- if (fcu->totvert == 0)
- clear_fcurve_keys(fcu);
-
- return changed;
+ int i;
+ bool changed = false;
+
+ if (fcu->bezt == NULL) /* ignore baked curves */
+ return false;
+
+ /* Delete selected BezTriples */
+ for (i = 0; i < fcu->totvert; i++) {
+ if (fcu->bezt[i].f2 & SELECT) {
+ memmove(&fcu->bezt[i], &fcu->bezt[i + 1], sizeof(BezTriple) * (fcu->totvert - i - 1));
+ fcu->totvert--;
+ i--;
+ changed = true;
+ }
+ }
+
+ /* Free the array of BezTriples if there are not keyframes */
+ if (fcu->totvert == 0)
+ clear_fcurve_keys(fcu);
+
+ return changed;
}
-
void clear_fcurve_keys(FCurve *fcu)
{
- if (fcu->bezt)
- MEM_freeN(fcu->bezt);
- fcu->bezt = NULL;
+ if (fcu->bezt)
+ MEM_freeN(fcu->bezt);
+ fcu->bezt = NULL;
- fcu->totvert = 0;
+ fcu->totvert = 0;
}
/* ---------------- */
@@ -140,36 +138,36 @@ void clear_fcurve_keys(FCurve *fcu)
/* duplicate selected keyframes for the given F-Curve */
void duplicate_fcurve_keys(FCurve *fcu)
{
- BezTriple *newbezt;
- int i;
-
- /* this can only work when there is an F-Curve, and also when there are some BezTriples */
- if (ELEM(NULL, fcu, fcu->bezt))
- return;
-
- for (i = 0; i < fcu->totvert; i++) {
- /* If a key is selected */
- if (fcu->bezt[i].f2 & SELECT) {
- /* Expand the list */
- newbezt = MEM_callocN(sizeof(BezTriple) * (fcu->totvert + 1), "beztriple");
-
- memcpy(newbezt, fcu->bezt, sizeof(BezTriple) * (i + 1));
- memcpy(newbezt + i + 1, fcu->bezt + i, sizeof(BezTriple));
- memcpy(newbezt + i + 2, fcu->bezt + i + 1, sizeof(BezTriple) * (fcu->totvert - (i + 1)));
- fcu->totvert++;
-
- /* reassign pointers... (free old, and add new) */
- MEM_freeN(fcu->bezt);
- fcu->bezt = newbezt;
-
- /* Unselect the current key */
- BEZT_DESEL_ALL(&fcu->bezt[i]);
- i++;
-
- /* Select the copied key */
- BEZT_SEL_ALL(&fcu->bezt[i]);
- }
- }
+ BezTriple *newbezt;
+ int i;
+
+ /* this can only work when there is an F-Curve, and also when there are some BezTriples */
+ if (ELEM(NULL, fcu, fcu->bezt))
+ return;
+
+ for (i = 0; i < fcu->totvert; i++) {
+ /* If a key is selected */
+ if (fcu->bezt[i].f2 & SELECT) {
+ /* Expand the list */
+ newbezt = MEM_callocN(sizeof(BezTriple) * (fcu->totvert + 1), "beztriple");
+
+ memcpy(newbezt, fcu->bezt, sizeof(BezTriple) * (i + 1));
+ memcpy(newbezt + i + 1, fcu->bezt + i, sizeof(BezTriple));
+ memcpy(newbezt + i + 2, fcu->bezt + i + 1, sizeof(BezTriple) * (fcu->totvert - (i + 1)));
+ fcu->totvert++;
+
+ /* reassign pointers... (free old, and add new) */
+ MEM_freeN(fcu->bezt);
+ fcu->bezt = newbezt;
+
+ /* Unselect the current key */
+ BEZT_DESEL_ALL(&fcu->bezt[i]);
+ i++;
+
+ /* Select the copied key */
+ BEZT_SEL_ALL(&fcu->bezt[i]);
+ }
+ }
}
/* **************************************************** */
@@ -180,327 +178,325 @@ void duplicate_fcurve_keys(FCurve *fcu)
*/
void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, bool cleardefault)
{
- FCurve *fcu = (FCurve *)ale->key_data;
- BezTriple *old_bezts, *bezt, *beztn;
- BezTriple *lastb;
- int totCount, i;
-
- /* check if any points */
- if ((fcu == NULL) || (fcu->bezt == NULL) || (fcu->totvert == 0) ||
- (!cleardefault && fcu->totvert == 1))
- {
- return;
- }
-
- /* make a copy of the old BezTriples, and clear F-Curve */
- old_bezts = fcu->bezt;
- totCount = fcu->totvert;
- fcu->bezt = NULL;
- fcu->totvert = 0;
-
- /* now insert first keyframe, as it should be ok */
- bezt = old_bezts;
- insert_bezt_fcurve(fcu, bezt, 0);
- if (!(bezt->f2 & SELECT)) {
- lastb = fcu->bezt;
- lastb->f1 = lastb->f2 = lastb->f3 = 0;
- }
-
- /* Loop through BezTriples, comparing them. Skip any that do
- * not fit the criteria for "ok" points.
- */
- for (i = 1; i < totCount; i++) {
- float prev[2], cur[2], next[2];
-
- /* get BezTriples and their values */
- if (i < (totCount - 1)) {
- beztn = (old_bezts + (i + 1));
- next[0] = beztn->vec[1][0]; next[1] = beztn->vec[1][1];
- }
- else {
- beztn = NULL;
- next[0] = next[1] = 0.0f;
- }
- lastb = (fcu->bezt + (fcu->totvert - 1));
- bezt = (old_bezts + i);
-
- /* get references for quicker access */
- prev[0] = lastb->vec[1][0]; prev[1] = lastb->vec[1][1];
- cur[0] = bezt->vec[1][0]; cur[1] = bezt->vec[1][1];
-
- if (!(bezt->f2 & SELECT)) {
- insert_bezt_fcurve(fcu, bezt, 0);
- lastb = (fcu->bezt + (fcu->totvert - 1));
- lastb->f1 = lastb->f2 = lastb->f3 = 0;
- continue;
- }
-
- /* check if current bezt occurs at same time as last ok */
- if (IS_EQT(cur[0], prev[0], thresh)) {
- /* If there is a next beztriple, and if occurs at the same time, only insert
- * if there is a considerable distance between the points, and also if the
- * current is further away than the next one is to the previous.
- */
- if (beztn && (IS_EQT(cur[0], next[0], thresh)) &&
- (IS_EQT(next[1], prev[1], thresh) == 0))
- {
- /* only add if current is further away from previous */
- if (cur[1] > next[1]) {
- if (IS_EQT(cur[1], prev[1], thresh) == 0) {
- /* add new keyframe */
- insert_bezt_fcurve(fcu, bezt, 0);
- }
- }
- }
- else {
- /* only add if values are a considerable distance apart */
- if (IS_EQT(cur[1], prev[1], thresh) == 0) {
- /* add new keyframe */
- insert_bezt_fcurve(fcu, bezt, 0);
- }
- }
- }
- else {
- /* checks required are dependent on whether this is last keyframe or not */
- if (beztn) {
- /* does current have same value as previous and next? */
- if (IS_EQT(cur[1], prev[1], thresh) == 0) {
- /* add new keyframe */
- insert_bezt_fcurve(fcu, bezt, 0);
- }
- else if (IS_EQT(cur[1], next[1], thresh) == 0) {
- /* add new keyframe */
- insert_bezt_fcurve(fcu, bezt, 0);
- }
- }
- else {
- /* add if value doesn't equal that of previous */
- if (IS_EQT(cur[1], prev[1], thresh) == 0) {
- /* add new keyframe */
- insert_bezt_fcurve(fcu, bezt, 0);
- }
- }
- }
- }
-
- /* now free the memory used by the old BezTriples */
- if (old_bezts)
- MEM_freeN(old_bezts);
-
- /* final step, if there is just one key in fcurve, check if it's
- * the default value and if is, remove fcurve completely. */
- if (cleardefault && fcu->totvert == 1) {
- float default_value = 0.0f;
- PointerRNA id_ptr, ptr;
- PropertyRNA *prop;
- RNA_id_pointer_create(ale->id, &id_ptr);
-
- /* get property to read from, and get value as appropriate */
- if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
- if (RNA_property_type(prop) == PROP_FLOAT)
- default_value = RNA_property_float_get_default_index(&ptr, prop, fcu->array_index);
- }
-
- if (fcu->bezt->vec[1][1] == default_value) {
- clear_fcurve_keys(fcu);
-
- /* check if curve is really unused and if it is, return signal for deletion */
- if ((list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0) &&
- (fcu->driver == NULL))
- {
- AnimData *adt = ale->adt;
- ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
- ale->key_data = NULL;
- }
- }
- }
+ FCurve *fcu = (FCurve *)ale->key_data;
+ BezTriple *old_bezts, *bezt, *beztn;
+ BezTriple *lastb;
+ int totCount, i;
+
+ /* check if any points */
+ if ((fcu == NULL) || (fcu->bezt == NULL) || (fcu->totvert == 0) ||
+ (!cleardefault && fcu->totvert == 1)) {
+ return;
+ }
+
+ /* make a copy of the old BezTriples, and clear F-Curve */
+ old_bezts = fcu->bezt;
+ totCount = fcu->totvert;
+ fcu->bezt = NULL;
+ fcu->totvert = 0;
+
+ /* now insert first keyframe, as it should be ok */
+ bezt = old_bezts;
+ insert_bezt_fcurve(fcu, bezt, 0);
+ if (!(bezt->f2 & SELECT)) {
+ lastb = fcu->bezt;
+ lastb->f1 = lastb->f2 = lastb->f3 = 0;
+ }
+
+ /* Loop through BezTriples, comparing them. Skip any that do
+ * not fit the criteria for "ok" points.
+ */
+ for (i = 1; i < totCount; i++) {
+ float prev[2], cur[2], next[2];
+
+ /* get BezTriples and their values */
+ if (i < (totCount - 1)) {
+ beztn = (old_bezts + (i + 1));
+ next[0] = beztn->vec[1][0];
+ next[1] = beztn->vec[1][1];
+ }
+ else {
+ beztn = NULL;
+ next[0] = next[1] = 0.0f;
+ }
+ lastb = (fcu->bezt + (fcu->totvert - 1));
+ bezt = (old_bezts + i);
+
+ /* get references for quicker access */
+ prev[0] = lastb->vec[1][0];
+ prev[1] = lastb->vec[1][1];
+ cur[0] = bezt->vec[1][0];
+ cur[1] = bezt->vec[1][1];
+
+ if (!(bezt->f2 & SELECT)) {
+ insert_bezt_fcurve(fcu, bezt, 0);
+ lastb = (fcu->bezt + (fcu->totvert - 1));
+ lastb->f1 = lastb->f2 = lastb->f3 = 0;
+ continue;
+ }
+
+ /* check if current bezt occurs at same time as last ok */
+ if (IS_EQT(cur[0], prev[0], thresh)) {
+ /* If there is a next beztriple, and if occurs at the same time, only insert
+ * if there is a considerable distance between the points, and also if the
+ * current is further away than the next one is to the previous.
+ */
+ if (beztn && (IS_EQT(cur[0], next[0], thresh)) && (IS_EQT(next[1], prev[1], thresh) == 0)) {
+ /* only add if current is further away from previous */
+ if (cur[1] > next[1]) {
+ if (IS_EQT(cur[1], prev[1], thresh) == 0) {
+ /* add new keyframe */
+ insert_bezt_fcurve(fcu, bezt, 0);
+ }
+ }
+ }
+ else {
+ /* only add if values are a considerable distance apart */
+ if (IS_EQT(cur[1], prev[1], thresh) == 0) {
+ /* add new keyframe */
+ insert_bezt_fcurve(fcu, bezt, 0);
+ }
+ }
+ }
+ else {
+ /* checks required are dependent on whether this is last keyframe or not */
+ if (beztn) {
+ /* does current have same value as previous and next? */
+ if (IS_EQT(cur[1], prev[1], thresh) == 0) {
+ /* add new keyframe */
+ insert_bezt_fcurve(fcu, bezt, 0);
+ }
+ else if (IS_EQT(cur[1], next[1], thresh) == 0) {
+ /* add new keyframe */
+ insert_bezt_fcurve(fcu, bezt, 0);
+ }
+ }
+ else {
+ /* add if value doesn't equal that of previous */
+ if (IS_EQT(cur[1], prev[1], thresh) == 0) {
+ /* add new keyframe */
+ insert_bezt_fcurve(fcu, bezt, 0);
+ }
+ }
+ }
+ }
+
+ /* now free the memory used by the old BezTriples */
+ if (old_bezts)
+ MEM_freeN(old_bezts);
+
+ /* final step, if there is just one key in fcurve, check if it's
+ * the default value and if is, remove fcurve completely. */
+ if (cleardefault && fcu->totvert == 1) {
+ float default_value = 0.0f;
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ RNA_id_pointer_create(ale->id, &id_ptr);
+
+ /* get property to read from, and get value as appropriate */
+ if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
+ if (RNA_property_type(prop) == PROP_FLOAT)
+ default_value = RNA_property_float_get_default_index(&ptr, prop, fcu->array_index);
+ }
+
+ if (fcu->bezt->vec[1][1] == default_value) {
+ clear_fcurve_keys(fcu);
+
+ /* check if curve is really unused and if it is, return signal for deletion */
+ if ((list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0) &&
+ (fcu->driver == NULL)) {
+ AnimData *adt = ale->adt;
+ ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
+ ale->key_data = NULL;
+ }
+ }
+ }
}
/* ---------------- */
/* temp struct used for smooth_fcurve */
typedef struct tSmooth_Bezt {
- float *h1, *h2, *h3; /* bezt->vec[0,1,2][1] */
- float y1, y2, y3; /* averaged before/new/after y-values */
+ float *h1, *h2, *h3; /* bezt->vec[0,1,2][1] */
+ float y1, y2, y3; /* averaged before/new/after y-values */
} tSmooth_Bezt;
/* Use a weighted moving-means method to reduce intensity of fluctuations */
// TODO: introduce scaling factor for weighting falloff
void smooth_fcurve(FCurve *fcu)
{
- BezTriple *bezt;
- int i, x, totSel = 0;
-
- if (fcu->bezt == NULL) {
- return;
- }
-
- /* first loop through - count how many verts are selected */
- bezt = fcu->bezt;
- for (i = 0; i < fcu->totvert; i++, bezt++) {
- if (BEZT_ISSEL_ANY(bezt))
- totSel++;
- }
-
- /* if any points were selected, allocate tSmooth_Bezt points to work on */
- if (totSel >= 3) {
- tSmooth_Bezt *tarray, *tsb;
-
- /* allocate memory in one go */
- tsb = tarray = MEM_callocN(totSel * sizeof(tSmooth_Bezt), "tSmooth_Bezt Array");
-
- /* populate tarray with data of selected points */
- bezt = fcu->bezt;
- for (i = 0, x = 0; (i < fcu->totvert) && (x < totSel); i++, bezt++) {
- if (BEZT_ISSEL_ANY(bezt)) {
- /* tsb simply needs pointer to vec, and index */
- tsb->h1 = &bezt->vec[0][1];
- tsb->h2 = &bezt->vec[1][1];
- tsb->h3 = &bezt->vec[2][1];
-
- /* advance to the next tsb to populate */
- if (x < totSel - 1)
- tsb++;
- else
- break;
- }
- }
-
- /* calculate the new smoothed F-Curve's with weighted averages:
- * - this is done with two passes to avoid progressive corruption errors
- * - uses 5 points for each operation (which stores in the relevant handles)
- * - previous: w/a ratio = 3:5:2:1:1
- * - next: w/a ratio = 1:1:2:5:3
- */
-
- /* round 1: calculate smoothing deltas and new values */
- tsb = tarray;
- for (i = 0; i < totSel; i++, tsb++) {
- /* don't touch end points (otherwise, curves slowly explode, as we don't have enough data there) */
- if (ELEM(i, 0, (totSel - 1)) == 0) {
- const tSmooth_Bezt *tP1 = tsb - 1;
- const tSmooth_Bezt *tP2 = (i - 2 > 0) ? (tsb - 2) : (NULL);
- const tSmooth_Bezt *tN1 = tsb + 1;
- const tSmooth_Bezt *tN2 = (i + 2 < totSel) ? (tsb + 2) : (NULL);
-
- const float p1 = *tP1->h2;
- const float p2 = (tP2) ? (*tP2->h2) : (*tP1->h2);
- const float c1 = *tsb->h2;
- const float n1 = *tN1->h2;
- const float n2 = (tN2) ? (*tN2->h2) : (*tN1->h2);
-
- /* calculate previous and next, then new position by averaging these */
- tsb->y1 = (3 * p2 + 5 * p1 + 2 * c1 + n1 + n2) / 12;
- tsb->y3 = (p2 + p1 + 2 * c1 + 5 * n1 + 3 * n2) / 12;
-
- tsb->y2 = (tsb->y1 + tsb->y3) / 2;
- }
- }
-
- /* round 2: apply new values */
- tsb = tarray;
- for (i = 0; i < totSel; i++, tsb++) {
- /* don't touch end points, as their values weren't touched above */
- if (ELEM(i, 0, (totSel - 1)) == 0) {
- /* y2 takes the average of the 2 points */
- *tsb->h2 = tsb->y2;
-
- /* handles are weighted between their original values and the averaged values */
- *tsb->h1 = ((*tsb->h1) * 0.7f) + (tsb->y1 * 0.3f);
- *tsb->h3 = ((*tsb->h3) * 0.7f) + (tsb->y3 * 0.3f);
- }
- }
-
- /* free memory required for tarray */
- MEM_freeN(tarray);
- }
-
- /* recalculate handles */
- calchandles_fcurve(fcu);
+ BezTriple *bezt;
+ int i, x, totSel = 0;
+
+ if (fcu->bezt == NULL) {
+ return;
+ }
+
+ /* first loop through - count how many verts are selected */
+ bezt = fcu->bezt;
+ for (i = 0; i < fcu->totvert; i++, bezt++) {
+ if (BEZT_ISSEL_ANY(bezt))
+ totSel++;
+ }
+
+ /* if any points were selected, allocate tSmooth_Bezt points to work on */
+ if (totSel >= 3) {
+ tSmooth_Bezt *tarray, *tsb;
+
+ /* allocate memory in one go */
+ tsb = tarray = MEM_callocN(totSel * sizeof(tSmooth_Bezt), "tSmooth_Bezt Array");
+
+ /* populate tarray with data of selected points */
+ bezt = fcu->bezt;
+ for (i = 0, x = 0; (i < fcu->totvert) && (x < totSel); i++, bezt++) {
+ if (BEZT_ISSEL_ANY(bezt)) {
+ /* tsb simply needs pointer to vec, and index */
+ tsb->h1 = &bezt->vec[0][1];
+ tsb->h2 = &bezt->vec[1][1];
+ tsb->h3 = &bezt->vec[2][1];
+
+ /* advance to the next tsb to populate */
+ if (x < totSel - 1)
+ tsb++;
+ else
+ break;
+ }
+ }
+
+ /* calculate the new smoothed F-Curve's with weighted averages:
+ * - this is done with two passes to avoid progressive corruption errors
+ * - uses 5 points for each operation (which stores in the relevant handles)
+ * - previous: w/a ratio = 3:5:2:1:1
+ * - next: w/a ratio = 1:1:2:5:3
+ */
+
+ /* round 1: calculate smoothing deltas and new values */
+ tsb = tarray;
+ for (i = 0; i < totSel; i++, tsb++) {
+ /* don't touch end points (otherwise, curves slowly explode, as we don't have enough data there) */
+ if (ELEM(i, 0, (totSel - 1)) == 0) {
+ const tSmooth_Bezt *tP1 = tsb - 1;
+ const tSmooth_Bezt *tP2 = (i - 2 > 0) ? (tsb - 2) : (NULL);
+ const tSmooth_Bezt *tN1 = tsb + 1;
+ const tSmooth_Bezt *tN2 = (i + 2 < totSel) ? (tsb + 2) : (NULL);
+
+ const float p1 = *tP1->h2;
+ const float p2 = (tP2) ? (*tP2->h2) : (*tP1->h2);
+ const float c1 = *tsb->h2;
+ const float n1 = *tN1->h2;
+ const float n2 = (tN2) ? (*tN2->h2) : (*tN1->h2);
+
+ /* calculate previous and next, then new position by averaging these */
+ tsb->y1 = (3 * p2 + 5 * p1 + 2 * c1 + n1 + n2) / 12;
+ tsb->y3 = (p2 + p1 + 2 * c1 + 5 * n1 + 3 * n2) / 12;
+
+ tsb->y2 = (tsb->y1 + tsb->y3) / 2;
+ }
+ }
+
+ /* round 2: apply new values */
+ tsb = tarray;
+ for (i = 0; i < totSel; i++, tsb++) {
+ /* don't touch end points, as their values weren't touched above */
+ if (ELEM(i, 0, (totSel - 1)) == 0) {
+ /* y2 takes the average of the 2 points */
+ *tsb->h2 = tsb->y2;
+
+ /* handles are weighted between their original values and the averaged values */
+ *tsb->h1 = ((*tsb->h1) * 0.7f) + (tsb->y1 * 0.3f);
+ *tsb->h3 = ((*tsb->h3) * 0.7f) + (tsb->y3 * 0.3f);
+ }
+ }
+
+ /* free memory required for tarray */
+ MEM_freeN(tarray);
+ }
+
+ /* recalculate handles */
+ calchandles_fcurve(fcu);
}
/* ---------------- */
/* little cache for values... */
typedef struct TempFrameValCache {
- float frame, val;
+ float frame, val;
} TempFrameValCache;
-
/* Evaluates the curves between each selected keyframe on each frame, and keys the value */
void sample_fcurve(FCurve *fcu)
{
- BezTriple *bezt, *start = NULL, *end = NULL;
- TempFrameValCache *value_cache, *fp;
- int sfra, range;
- int i, n;
-
- if (fcu->bezt == NULL) /* ignore baked */
- return;
-
- /* find selected keyframes... once pair has been found, add keyframes */
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- /* check if selected, and which end this is */
- if (BEZT_ISSEL_ANY(bezt)) {
- if (start) {
- /* If next bezt is also selected, don't start sampling yet,
- * but instead wait for that one to reconsider, to avoid
- * changing the curve when sampling consecutive segments
- * (T53229)
- */
- if (i < fcu->totvert - 1) {
- BezTriple *next = &fcu->bezt[i + 1];
- if (BEZT_ISSEL_ANY(next)) {
- continue;
- }
- }
-
- /* set end */
- end = bezt;
-
- /* cache values then add keyframes using these values, as adding
- * keyframes while sampling will affect the outcome...
- * - only start sampling+adding from index=1, so that we don't overwrite original keyframe
- */
- range = (int)(ceil(end->vec[1][0] - start->vec[1][0]));
- sfra = (int)(floor(start->vec[1][0]));
-
- if (range) {
- value_cache = MEM_callocN(sizeof(TempFrameValCache) * range, "IcuFrameValCache");
-
- /* sample values */
- for (n = 1, fp = value_cache; n < range && fp; n++, fp++) {
- fp->frame = (float)(sfra + n);
- fp->val = evaluate_fcurve(fcu, fp->frame);
- }
-
- /* add keyframes with these, tagging as 'breakdowns' */
- for (n = 1, fp = value_cache; n < range && fp; n++, fp++) {
- insert_vert_fcurve(fcu, fp->frame, fp->val, BEZT_KEYTYPE_BREAKDOWN, 1);
- }
-
- /* free temp cache */
- MEM_freeN(value_cache);
-
- /* as we added keyframes, we need to compensate so that bezt is at the right place */
- bezt = fcu->bezt + i + range - 1;
- i += (range - 1);
- }
-
- /* the current selection island has ended, so start again from scratch */
- start = NULL;
- end = NULL;
- }
- else {
- /* just set start keyframe */
- start = bezt;
- end = NULL;
- }
- }
- }
-
- /* recalculate channel's handles? */
- calchandles_fcurve(fcu);
+ BezTriple *bezt, *start = NULL, *end = NULL;
+ TempFrameValCache *value_cache, *fp;
+ int sfra, range;
+ int i, n;
+
+ if (fcu->bezt == NULL) /* ignore baked */
+ return;
+
+ /* find selected keyframes... once pair has been found, add keyframes */
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ /* check if selected, and which end this is */
+ if (BEZT_ISSEL_ANY(bezt)) {
+ if (start) {
+ /* If next bezt is also selected, don't start sampling yet,
+ * but instead wait for that one to reconsider, to avoid
+ * changing the curve when sampling consecutive segments
+ * (T53229)
+ */
+ if (i < fcu->totvert - 1) {
+ BezTriple *next = &fcu->bezt[i + 1];
+ if (BEZT_ISSEL_ANY(next)) {
+ continue;
+ }
+ }
+
+ /* set end */
+ end = bezt;
+
+ /* cache values then add keyframes using these values, as adding
+ * keyframes while sampling will affect the outcome...
+ * - only start sampling+adding from index=1, so that we don't overwrite original keyframe
+ */
+ range = (int)(ceil(end->vec[1][0] - start->vec[1][0]));
+ sfra = (int)(floor(start->vec[1][0]));
+
+ if (range) {
+ value_cache = MEM_callocN(sizeof(TempFrameValCache) * range, "IcuFrameValCache");
+
+ /* sample values */
+ for (n = 1, fp = value_cache; n < range && fp; n++, fp++) {
+ fp->frame = (float)(sfra + n);
+ fp->val = evaluate_fcurve(fcu, fp->frame);
+ }
+
+ /* add keyframes with these, tagging as 'breakdowns' */
+ for (n = 1, fp = value_cache; n < range && fp; n++, fp++) {
+ insert_vert_fcurve(fcu, fp->frame, fp->val, BEZT_KEYTYPE_BREAKDOWN, 1);
+ }
+
+ /* free temp cache */
+ MEM_freeN(value_cache);
+
+ /* as we added keyframes, we need to compensate so that bezt is at the right place */
+ bezt = fcu->bezt + i + range - 1;
+ i += (range - 1);
+ }
+
+ /* the current selection island has ended, so start again from scratch */
+ start = NULL;
+ end = NULL;
+ }
+ else {
+ /* just set start keyframe */
+ start = bezt;
+ end = NULL;
+ }
+ }
+ }
+
+ /* recalculate channel's handles? */
+ calchandles_fcurve(fcu);
}
/* **************************************************** */
@@ -520,46 +516,45 @@ static float animcopy_cfra = 0.0;
/* datatype for use in copy/paste buffer */
typedef struct tAnimCopybufItem {
- struct tAnimCopybufItem *next, *prev;
+ struct tAnimCopybufItem *next, *prev;
- ID *id; /* ID which owns the curve */
- bActionGroup *grp; /* Action Group */
- char *rna_path; /* RNA-Path */
- int array_index; /* array index */
+ ID *id; /* ID which owns the curve */
+ bActionGroup *grp; /* Action Group */
+ char *rna_path; /* RNA-Path */
+ int array_index; /* array index */
- int totvert; /* number of keyframes stored for this channel */
- BezTriple *bezt; /* keyframes in buffer */
+ int totvert; /* number of keyframes stored for this channel */
+ BezTriple *bezt; /* keyframes in buffer */
- short id_type; /* Result of GS(id->name)*/
- bool is_bone; /* special flag for armature bones */
+ short id_type; /* Result of GS(id->name)*/
+ bool is_bone; /* special flag for armature bones */
} tAnimCopybufItem;
-
/* This function frees any MEM_calloc'ed copy/paste buffer data */
void ANIM_fcurves_copybuf_free(void)
{
- tAnimCopybufItem *aci, *acn;
+ tAnimCopybufItem *aci, *acn;
- /* free each buffer element */
- for (aci = animcopybuf.first; aci; aci = acn) {
- acn = aci->next;
+ /* free each buffer element */
+ for (aci = animcopybuf.first; aci; aci = acn) {
+ acn = aci->next;
- /* free keyframes */
- if (aci->bezt)
- MEM_freeN(aci->bezt);
+ /* free keyframes */
+ if (aci->bezt)
+ MEM_freeN(aci->bezt);
- /* free RNA-path */
- if (aci->rna_path)
- MEM_freeN(aci->rna_path);
+ /* free RNA-path */
+ if (aci->rna_path)
+ MEM_freeN(aci->rna_path);
- /* free ourself */
- BLI_freelinkN(&animcopybuf, aci);
- }
+ /* free ourself */
+ BLI_freelinkN(&animcopybuf, aci);
+ }
- /* restore initial state */
- BLI_listbase_clear(&animcopybuf);
- animcopy_firstframe = 999999999.0f;
- animcopy_lastframe = -999999999.0f;
+ /* restore initial state */
+ BLI_listbase_clear(&animcopybuf);
+ animcopy_firstframe = 999999999.0f;
+ animcopy_lastframe = -999999999.0f;
}
/* ------------------- */
@@ -567,468 +562,501 @@ void ANIM_fcurves_copybuf_free(void)
/* This function adds data to the keyframes copy/paste buffer, freeing existing data first */
short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data)
{
- bAnimListElem *ale;
- Scene *scene = ac->scene;
-
- /* clear buffer first */
- ANIM_fcurves_copybuf_free();
-
- /* assume that each of these is an F-Curve */
- for (ale = anim_data->first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
- tAnimCopybufItem *aci;
- BezTriple *bezt, *nbezt, *newbuf;
- int i;
-
- /* firstly, check if F-Curve has any selected keyframes
- * - skip if no selected keyframes found (so no need to create unnecessary copy-buffer data)
- * - this check should also eliminate any problems associated with using sample-data
- */
- if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ANIM_editkeyframes_ok(BEZT_OK_SELECTED), NULL) == 0)
- continue;
-
- /* init copybuf item info */
- aci = MEM_callocN(sizeof(tAnimCopybufItem), "AnimCopybufItem");
- aci->id = ale->id;
- aci->id_type = GS(ale->id->name);
- aci->grp = fcu->grp;
- aci->rna_path = MEM_dupallocN(fcu->rna_path);
- aci->array_index = fcu->array_index;
-
- /* detect if this is a bone. We do that here rather than during pasting because ID pointers will get invalidated if we undo.
- * storing the relevant information here helps avoiding crashes if we undo-repaste */
- if ((aci->id_type == ID_OB) && (((Object *)aci->id)->type == OB_ARMATURE) && aci->rna_path) {
- Object *ob = (Object *)aci->id;
- bPoseChannel *pchan;
- char *bone_name;
-
- bone_name = BLI_str_quoted_substrN(aci->rna_path, "pose.bones[");
- pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
- if (pchan) {
- aci->is_bone = true;
- }
- if (bone_name) MEM_freeN(bone_name);
- }
-
- BLI_addtail(&animcopybuf, aci);
-
- /* add selected keyframes to buffer */
- /* TODO: currently, we resize array every time we add a new vert -
- * this works ok as long as it is assumed only a few keys are copied */
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- if (BEZT_ISSEL_ANY(bezt)) {
- /* add to buffer */
- newbuf = MEM_callocN(sizeof(BezTriple) * (aci->totvert + 1), "copybuf beztriple");
-
- /* assume that since we are just re-sizing the array, just copy all existing data across */
- if (aci->bezt)
- memcpy(newbuf, aci->bezt, sizeof(BezTriple) * (aci->totvert));
-
- /* copy current beztriple across too */
- nbezt = &newbuf[aci->totvert];
- *nbezt = *bezt;
-
- /* ensure copy buffer is selected so pasted keys are selected */
- BEZT_SEL_ALL(nbezt);
-
- /* free old array and set the new */
- if (aci->bezt) MEM_freeN(aci->bezt);
- aci->bezt = newbuf;
- aci->totvert++;
-
- /* check if this is the earliest frame encountered so far */
- if (bezt->vec[1][0] < animcopy_firstframe)
- animcopy_firstframe = bezt->vec[1][0];
- if (bezt->vec[1][0] > animcopy_lastframe)
- animcopy_lastframe = bezt->vec[1][0];
- }
- }
-
- }
-
- /* check if anything ended up in the buffer */
- if (ELEM(NULL, animcopybuf.first, animcopybuf.last))
- return -1;
-
- /* in case 'relative' paste method is used */
- animcopy_cfra = CFRA;
-
- /* everything went fine */
- return 0;
+ bAnimListElem *ale;
+ Scene *scene = ac->scene;
+
+ /* clear buffer first */
+ ANIM_fcurves_copybuf_free();
+
+ /* assume that each of these is an F-Curve */
+ for (ale = anim_data->first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
+ tAnimCopybufItem *aci;
+ BezTriple *bezt, *nbezt, *newbuf;
+ int i;
+
+ /* firstly, check if F-Curve has any selected keyframes
+ * - skip if no selected keyframes found (so no need to create unnecessary copy-buffer data)
+ * - this check should also eliminate any problems associated with using sample-data
+ */
+ if (ANIM_fcurve_keyframes_loop(
+ NULL, fcu, NULL, ANIM_editkeyframes_ok(BEZT_OK_SELECTED), NULL) == 0)
+ continue;
+
+ /* init copybuf item info */
+ aci = MEM_callocN(sizeof(tAnimCopybufItem), "AnimCopybufItem");
+ aci->id = ale->id;
+ aci->id_type = GS(ale->id->name);
+ aci->grp = fcu->grp;
+ aci->rna_path = MEM_dupallocN(fcu->rna_path);
+ aci->array_index = fcu->array_index;
+
+ /* detect if this is a bone. We do that here rather than during pasting because ID pointers will get invalidated if we undo.
+ * storing the relevant information here helps avoiding crashes if we undo-repaste */
+ if ((aci->id_type == ID_OB) && (((Object *)aci->id)->type == OB_ARMATURE) && aci->rna_path) {
+ Object *ob = (Object *)aci->id;
+ bPoseChannel *pchan;
+ char *bone_name;
+
+ bone_name = BLI_str_quoted_substrN(aci->rna_path, "pose.bones[");
+ pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
+ if (pchan) {
+ aci->is_bone = true;
+ }
+ if (bone_name)
+ MEM_freeN(bone_name);
+ }
+
+ BLI_addtail(&animcopybuf, aci);
+
+ /* add selected keyframes to buffer */
+ /* TODO: currently, we resize array every time we add a new vert -
+ * this works ok as long as it is assumed only a few keys are copied */
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (BEZT_ISSEL_ANY(bezt)) {
+ /* add to buffer */
+ newbuf = MEM_callocN(sizeof(BezTriple) * (aci->totvert + 1), "copybuf beztriple");
+
+ /* assume that since we are just re-sizing the array, just copy all existing data across */
+ if (aci->bezt)
+ memcpy(newbuf, aci->bezt, sizeof(BezTriple) * (aci->totvert));
+
+ /* copy current beztriple across too */
+ nbezt = &newbuf[aci->totvert];
+ *nbezt = *bezt;
+
+ /* ensure copy buffer is selected so pasted keys are selected */
+ BEZT_SEL_ALL(nbezt);
+
+ /* free old array and set the new */
+ if (aci->bezt)
+ MEM_freeN(aci->bezt);
+ aci->bezt = newbuf;
+ aci->totvert++;
+
+ /* check if this is the earliest frame encountered so far */
+ if (bezt->vec[1][0] < animcopy_firstframe)
+ animcopy_firstframe = bezt->vec[1][0];
+ if (bezt->vec[1][0] > animcopy_lastframe)
+ animcopy_lastframe = bezt->vec[1][0];
+ }
+ }
+ }
+
+ /* check if anything ended up in the buffer */
+ if (ELEM(NULL, animcopybuf.first, animcopybuf.last))
+ return -1;
+
+ /* in case 'relative' paste method is used */
+ animcopy_cfra = CFRA;
+
+ /* everything went fine */
+ return 0;
}
static void flip_names(tAnimCopybufItem *aci, char **name)
{
- if (aci->is_bone) {
- char *str_start;
- if ((str_start = strstr(aci->rna_path, "pose.bones["))) {
- /* ninja coding, try to change the name */
- char bname_new[MAX_VGROUP_NAME];
- char *str_iter, *str_end;
- int length, prefix_l, postfix_l;
-
- str_start += 12;
- prefix_l = str_start - aci->rna_path;
-
- str_end = strchr(str_start, '\"');
-
- length = str_end - str_start;
- postfix_l = strlen(str_end);
-
- /* more ninja stuff, temporary substitute with NULL terminator */
- str_start[length] = 0;
- BLI_string_flip_side_name(bname_new, str_start, false, sizeof(bname_new));
- str_start[length] = '\"';
-
- str_iter = *name = MEM_mallocN(sizeof(char) * (prefix_l + postfix_l + length + 1), "flipped_path");
-
- BLI_strncpy(str_iter, aci->rna_path, prefix_l + 1);
- str_iter += prefix_l;
- BLI_strncpy(str_iter, bname_new, length + 1);
- str_iter += length;
- BLI_strncpy(str_iter, str_end, postfix_l + 1);
- str_iter[postfix_l] = '\0';
- }
- }
+ if (aci->is_bone) {
+ char *str_start;
+ if ((str_start = strstr(aci->rna_path, "pose.bones["))) {
+ /* ninja coding, try to change the name */
+ char bname_new[MAX_VGROUP_NAME];
+ char *str_iter, *str_end;
+ int length, prefix_l, postfix_l;
+
+ str_start += 12;
+ prefix_l = str_start - aci->rna_path;
+
+ str_end = strchr(str_start, '\"');
+
+ length = str_end - str_start;
+ postfix_l = strlen(str_end);
+
+ /* more ninja stuff, temporary substitute with NULL terminator */
+ str_start[length] = 0;
+ BLI_string_flip_side_name(bname_new, str_start, false, sizeof(bname_new));
+ str_start[length] = '\"';
+
+ str_iter = *name = MEM_mallocN(sizeof(char) * (prefix_l + postfix_l + length + 1),
+ "flipped_path");
+
+ BLI_strncpy(str_iter, aci->rna_path, prefix_l + 1);
+ str_iter += prefix_l;
+ BLI_strncpy(str_iter, bname_new, length + 1);
+ str_iter += length;
+ BLI_strncpy(str_iter, str_end, postfix_l + 1);
+ str_iter[postfix_l] = '\0';
+ }
+ }
}
/* ------------------- */
/* most strict method: exact matches only */
-static tAnimCopybufItem *pastebuf_match_path_full(FCurve *fcu, const short from_single, const short to_simple, bool flip)
+static tAnimCopybufItem *pastebuf_match_path_full(FCurve *fcu,
+ const short from_single,
+ const short to_simple,
+ bool flip)
{
- tAnimCopybufItem *aci;
-
- for (aci = animcopybuf.first; aci; aci = aci->next) {
- if (to_simple || (aci->rna_path && fcu->rna_path)) {
- if (!to_simple && flip && aci->is_bone && fcu->rna_path) {
- if ((from_single) || (aci->array_index == fcu->array_index)) {
- char *name = NULL;
- flip_names(aci, &name);
- if (STREQ(name, fcu->rna_path)) {
- MEM_freeN(name);
- break;
- }
- MEM_freeN(name);
- }
- }
- else if (to_simple || STREQ(aci->rna_path, fcu->rna_path)) {
- if ((from_single) || (aci->array_index == fcu->array_index)) {
- break;
- }
- }
- }
- }
-
- return aci;
+ tAnimCopybufItem *aci;
+
+ for (aci = animcopybuf.first; aci; aci = aci->next) {
+ if (to_simple || (aci->rna_path && fcu->rna_path)) {
+ if (!to_simple && flip && aci->is_bone && fcu->rna_path) {
+ if ((from_single) || (aci->array_index == fcu->array_index)) {
+ char *name = NULL;
+ flip_names(aci, &name);
+ if (STREQ(name, fcu->rna_path)) {
+ MEM_freeN(name);
+ break;
+ }
+ MEM_freeN(name);
+ }
+ }
+ else if (to_simple || STREQ(aci->rna_path, fcu->rna_path)) {
+ if ((from_single) || (aci->array_index == fcu->array_index)) {
+ break;
+ }
+ }
+ }
+ }
+
+ return aci;
}
/* medium match strictness: path match only (i.e. ignore ID) */
-static tAnimCopybufItem *pastebuf_match_path_property(
- Main *bmain, FCurve *fcu, const short from_single, const short UNUSED(to_simple))
+static tAnimCopybufItem *pastebuf_match_path_property(Main *bmain,
+ FCurve *fcu,
+ const short from_single,
+ const short UNUSED(to_simple))
{
- tAnimCopybufItem *aci;
-
- for (aci = animcopybuf.first; aci; aci = aci->next) {
- /* check that paths exist */
- if (aci->rna_path && fcu->rna_path) {
- /* find the property of the fcurve and compare against the end of the tAnimCopybufItem
- * more involved since it needs to do path lookups.
- * This is not 100% reliable since the user could be editing the curves on a path that wont
- * resolve, or a bone could be renamed after copying for eg. but in normal copy & paste
- * this should work out ok.
- */
- if (BLI_findindex(which_libbase(bmain, aci->id_type), aci->id) == -1) {
- /* pedantic but the ID could have been removed, and beats crashing! */
- printf("paste_animedit_keys: error ID has been removed!\n");
- }
- else {
- PointerRNA id_ptr, rptr;
- PropertyRNA *prop;
-
- RNA_id_pointer_create(aci->id, &id_ptr);
-
- if (RNA_path_resolve_property(&id_ptr, aci->rna_path, &rptr, &prop)) {
- const char *identifier = RNA_property_identifier(prop);
- int len_id = strlen(identifier);
- int len_path = strlen(fcu->rna_path);
- if (len_id <= len_path) {
- /* note, paths which end with "] will fail with this test - Animated ID Props */
- if (STREQ(identifier, fcu->rna_path + (len_path - len_id))) {
- if ((from_single) || (aci->array_index == fcu->array_index))
- break;
- }
- }
- }
- else {
- printf("paste_animedit_keys: failed to resolve path id:%s, '%s'!\n", aci->id->name, aci->rna_path);
- }
- }
- }
- }
-
- return aci;
+ tAnimCopybufItem *aci;
+
+ for (aci = animcopybuf.first; aci; aci = aci->next) {
+ /* check that paths exist */
+ if (aci->rna_path && fcu->rna_path) {
+ /* find the property of the fcurve and compare against the end of the tAnimCopybufItem
+ * more involved since it needs to do path lookups.
+ * This is not 100% reliable since the user could be editing the curves on a path that wont
+ * resolve, or a bone could be renamed after copying for eg. but in normal copy & paste
+ * this should work out ok.
+ */
+ if (BLI_findindex(which_libbase(bmain, aci->id_type), aci->id) == -1) {
+ /* pedantic but the ID could have been removed, and beats crashing! */
+ printf("paste_animedit_keys: error ID has been removed!\n");
+ }
+ else {
+ PointerRNA id_ptr, rptr;
+ PropertyRNA *prop;
+
+ RNA_id_pointer_create(aci->id, &id_ptr);
+
+ if (RNA_path_resolve_property(&id_ptr, aci->rna_path, &rptr, &prop)) {
+ const char *identifier = RNA_property_identifier(prop);
+ int len_id = strlen(identifier);
+ int len_path = strlen(fcu->rna_path);
+ if (len_id <= len_path) {
+ /* note, paths which end with "] will fail with this test - Animated ID Props */
+ if (STREQ(identifier, fcu->rna_path + (len_path - len_id))) {
+ if ((from_single) || (aci->array_index == fcu->array_index))
+ break;
+ }
+ }
+ }
+ else {
+ printf("paste_animedit_keys: failed to resolve path id:%s, '%s'!\n",
+ aci->id->name,
+ aci->rna_path);
+ }
+ }
+ }
+ }
+
+ return aci;
}
/* least strict matching heuristic: indices only */
-static tAnimCopybufItem *pastebuf_match_index_only(FCurve *fcu, const short from_single, const short UNUSED(to_simple))
+static tAnimCopybufItem *pastebuf_match_index_only(FCurve *fcu,
+ const short from_single,
+ const short UNUSED(to_simple))
{
- tAnimCopybufItem *aci;
+ tAnimCopybufItem *aci;
- for (aci = animcopybuf.first; aci; aci = aci->next) {
- /* check that paths exist */
- if ((from_single) || (aci->array_index == fcu->array_index)) {
- break;
- }
- }
+ for (aci = animcopybuf.first; aci; aci = aci->next) {
+ /* check that paths exist */
+ if ((from_single) || (aci->array_index == fcu->array_index)) {
+ break;
+ }
+ }
- return aci;
+ return aci;
}
/* ................ */
static void do_curve_mirror_flippping(tAnimCopybufItem *aci, BezTriple *bezt)
{
- if (aci->is_bone) {
- const size_t slength = strlen(aci->rna_path);
- bool flip = false;
- if (BLI_strn_endswith(aci->rna_path, "location", slength) && aci->array_index == 0)
- flip = true;
- else if (BLI_strn_endswith(aci->rna_path, "rotation_quaternion", slength) && ELEM(aci->array_index, 2, 3))
- flip = true;
- else if (BLI_strn_endswith(aci->rna_path, "rotation_euler", slength) && ELEM(aci->array_index, 1, 2))
- flip = true;
- else if (BLI_strn_endswith(aci->rna_path, "rotation_axis_angle", slength) && ELEM(aci->array_index, 2, 3))
- flip = true;
-
- if (flip) {
- bezt->vec[0][1] = -bezt->vec[0][1];
- bezt->vec[1][1] = -bezt->vec[1][1];
- bezt->vec[2][1] = -bezt->vec[2][1];
- }
- }
+ if (aci->is_bone) {
+ const size_t slength = strlen(aci->rna_path);
+ bool flip = false;
+ if (BLI_strn_endswith(aci->rna_path, "location", slength) && aci->array_index == 0)
+ flip = true;
+ else if (BLI_strn_endswith(aci->rna_path, "rotation_quaternion", slength) &&
+ ELEM(aci->array_index, 2, 3))
+ flip = true;
+ else if (BLI_strn_endswith(aci->rna_path, "rotation_euler", slength) &&
+ ELEM(aci->array_index, 1, 2))
+ flip = true;
+ else if (BLI_strn_endswith(aci->rna_path, "rotation_axis_angle", slength) &&
+ ELEM(aci->array_index, 2, 3))
+ flip = true;
+
+ if (flip) {
+ bezt->vec[0][1] = -bezt->vec[0][1];
+ bezt->vec[1][1] = -bezt->vec[1][1];
+ bezt->vec[2][1] = -bezt->vec[2][1];
+ }
+ }
}
/* helper for paste_animedit_keys() - performs the actual pasting */
-static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float offset, const eKeyMergeMode merge_mode, bool flip)
+static void paste_animedit_keys_fcurve(
+ FCurve *fcu, tAnimCopybufItem *aci, float offset, const eKeyMergeMode merge_mode, bool flip)
{
- BezTriple *bezt;
- int i;
-
- /* First de-select existing FCurve's keyframes */
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- BEZT_DESEL_ALL(bezt);
- }
-
- /* mix mode with existing data */
- switch (merge_mode) {
- case KEYFRAME_PASTE_MERGE_MIX:
- /* do-nothing */
- break;
-
- case KEYFRAME_PASTE_MERGE_OVER:
- /* remove all keys */
- clear_fcurve_keys(fcu);
- break;
-
- case KEYFRAME_PASTE_MERGE_OVER_RANGE:
- case KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL:
- {
- float f_min;
- float f_max;
-
- if (merge_mode == KEYFRAME_PASTE_MERGE_OVER_RANGE) {
- f_min = aci->bezt[0].vec[1][0] + offset;
- f_max = aci->bezt[aci->totvert - 1].vec[1][0] + offset;
- }
- else { /* Entire Range */
- f_min = animcopy_firstframe + offset;
- f_max = animcopy_lastframe + offset;
- }
-
- /* remove keys in range */
- if (f_min < f_max) {
- /* select verts in range for removal */
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- if ((f_min < bezt[0].vec[1][0]) && (bezt[0].vec[1][0] < f_max)) {
- bezt->f2 |= SELECT;
- }
- }
-
- /* remove frames in the range */
- delete_fcurve_keys(fcu);
- }
- break;
- }
- }
-
- /* just start pasting, with the first keyframe on the current frame, and so on */
- for (i = 0, bezt = aci->bezt; i < aci->totvert; i++, bezt++) {
- /* temporarily apply offset to src beztriple while copying */
- if (flip)
- do_curve_mirror_flippping(aci, bezt);
-
- bezt->vec[0][0] += offset;
- bezt->vec[1][0] += offset;
- bezt->vec[2][0] += offset;
-
- /* insert the keyframe
- * NOTE: we do not want to inherit handles from existing keyframes in this case!
- */
-
- insert_bezt_fcurve(fcu, bezt, INSERTKEY_OVERWRITE_FULL);
-
- /* un-apply offset from src beztriple after copying */
- bezt->vec[0][0] -= offset;
- bezt->vec[1][0] -= offset;
- bezt->vec[2][0] -= offset;
-
- if (flip)
- do_curve_mirror_flippping(aci, bezt);
- }
-
- /* recalculate F-Curve's handles? */
- calchandles_fcurve(fcu);
+ BezTriple *bezt;
+ int i;
+
+ /* First de-select existing FCurve's keyframes */
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ BEZT_DESEL_ALL(bezt);
+ }
+
+ /* mix mode with existing data */
+ switch (merge_mode) {
+ case KEYFRAME_PASTE_MERGE_MIX:
+ /* do-nothing */
+ break;
+
+ case KEYFRAME_PASTE_MERGE_OVER:
+ /* remove all keys */
+ clear_fcurve_keys(fcu);
+ break;
+
+ case KEYFRAME_PASTE_MERGE_OVER_RANGE:
+ case KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL: {
+ float f_min;
+ float f_max;
+
+ if (merge_mode == KEYFRAME_PASTE_MERGE_OVER_RANGE) {
+ f_min = aci->bezt[0].vec[1][0] + offset;
+ f_max = aci->bezt[aci->totvert - 1].vec[1][0] + offset;
+ }
+ else { /* Entire Range */
+ f_min = animcopy_firstframe + offset;
+ f_max = animcopy_lastframe + offset;
+ }
+
+ /* remove keys in range */
+ if (f_min < f_max) {
+ /* select verts in range for removal */
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if ((f_min < bezt[0].vec[1][0]) && (bezt[0].vec[1][0] < f_max)) {
+ bezt->f2 |= SELECT;
+ }
+ }
+
+ /* remove frames in the range */
+ delete_fcurve_keys(fcu);
+ }
+ break;
+ }
+ }
+
+ /* just start pasting, with the first keyframe on the current frame, and so on */
+ for (i = 0, bezt = aci->bezt; i < aci->totvert; i++, bezt++) {
+ /* temporarily apply offset to src beztriple while copying */
+ if (flip)
+ do_curve_mirror_flippping(aci, bezt);
+
+ bezt->vec[0][0] += offset;
+ bezt->vec[1][0] += offset;
+ bezt->vec[2][0] += offset;
+
+ /* insert the keyframe
+ * NOTE: we do not want to inherit handles from existing keyframes in this case!
+ */
+
+ insert_bezt_fcurve(fcu, bezt, INSERTKEY_OVERWRITE_FULL);
+
+ /* un-apply offset from src beztriple after copying */
+ bezt->vec[0][0] -= offset;
+ bezt->vec[1][0] -= offset;
+ bezt->vec[2][0] -= offset;
+
+ if (flip)
+ do_curve_mirror_flippping(aci, bezt);
+ }
+
+ /* recalculate F-Curve's handles? */
+ calchandles_fcurve(fcu);
}
/* ------------------- */
const EnumPropertyItem rna_enum_keyframe_paste_offset_items[] = {
- {KEYFRAME_PASTE_OFFSET_CFRA_START, "START", 0, "Frame Start", "Paste keys starting at current frame"},
- {KEYFRAME_PASTE_OFFSET_CFRA_END, "END", 0, "Frame End", "Paste keys ending at current frame"},
- {KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE, "RELATIVE", 0, "Frame Relative", "Paste keys relative to the current frame when copying"},
- {KEYFRAME_PASTE_OFFSET_NONE, "NONE", 0, "No Offset", "Paste keys from original time"},
- {0, NULL, 0, NULL, NULL},
+ {KEYFRAME_PASTE_OFFSET_CFRA_START,
+ "START",
+ 0,
+ "Frame Start",
+ "Paste keys starting at current frame"},
+ {KEYFRAME_PASTE_OFFSET_CFRA_END, "END", 0, "Frame End", "Paste keys ending at current frame"},
+ {KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE,
+ "RELATIVE",
+ 0,
+ "Frame Relative",
+ "Paste keys relative to the current frame when copying"},
+ {KEYFRAME_PASTE_OFFSET_NONE, "NONE", 0, "No Offset", "Paste keys from original time"},
+ {0, NULL, 0, NULL, NULL},
};
const EnumPropertyItem rna_enum_keyframe_paste_merge_items[] = {
- {KEYFRAME_PASTE_MERGE_MIX, "MIX", 0, "Mix", "Overlay existing with new keys"},
- {KEYFRAME_PASTE_MERGE_OVER, "OVER_ALL", 0, "Overwrite All", "Replace all keys"},
- {KEYFRAME_PASTE_MERGE_OVER_RANGE, "OVER_RANGE", 0, "Overwrite Range", "Overwrite keys in pasted range"},
- {KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL, "OVER_RANGE_ALL", 0, "Overwrite Entire Range", "Overwrite keys in pasted range, using the range of all copied keys"},
- {0, NULL, 0, NULL, NULL},
+ {KEYFRAME_PASTE_MERGE_MIX, "MIX", 0, "Mix", "Overlay existing with new keys"},
+ {KEYFRAME_PASTE_MERGE_OVER, "OVER_ALL", 0, "Overwrite All", "Replace all keys"},
+ {KEYFRAME_PASTE_MERGE_OVER_RANGE,
+ "OVER_RANGE",
+ 0,
+ "Overwrite Range",
+ "Overwrite keys in pasted range"},
+ {KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL,
+ "OVER_RANGE_ALL",
+ 0,
+ "Overwrite Entire Range",
+ "Overwrite keys in pasted range, using the range of all copied keys"},
+ {0, NULL, 0, NULL, NULL},
};
-
/**
* This function pastes data from the keyframes copy/paste buffer
*
* \return Status code is whether the method FAILED to do anything
*/
-short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data,
- const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip)
+short paste_animedit_keys(bAnimContext *ac,
+ ListBase *anim_data,
+ const eKeyPasteOffset offset_mode,
+ const eKeyMergeMode merge_mode,
+ bool flip)
{
- bAnimListElem *ale;
-
- const Scene *scene = (ac->scene);
-
- const bool from_single = BLI_listbase_is_single(&animcopybuf);
- const bool to_simple = BLI_listbase_is_single(anim_data);
-
- float offset = 0.0f;
- int pass;
-
- /* check if buffer is empty */
- if (BLI_listbase_is_empty(&animcopybuf)) {
- BKE_report(ac->reports, RPT_ERROR, "No animation data in buffer to paste");
- return -1;
- }
-
- if (BLI_listbase_is_empty(anim_data)) {
- BKE_report(ac->reports, RPT_ERROR, "No selected F-Curves to paste into");
- return -1;
- }
-
- /* methods of offset */
- switch (offset_mode) {
- case KEYFRAME_PASTE_OFFSET_CFRA_START:
- offset = (float)(CFRA - animcopy_firstframe);
- break;
- case KEYFRAME_PASTE_OFFSET_CFRA_END:
- offset = (float)(CFRA - animcopy_lastframe);
- break;
- case KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE:
- offset = (float)(CFRA - animcopy_cfra);
- break;
- case KEYFRAME_PASTE_OFFSET_NONE:
- offset = 0.0f;
- break;
- }
-
- if (from_single && to_simple) {
- /* 1:1 match, no tricky checking, just paste */
- FCurve *fcu;
- tAnimCopybufItem *aci;
-
- ale = anim_data->first;
- fcu = (FCurve *)ale->data; /* destination F-Curve */
- aci = animcopybuf.first;
-
- paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, false);
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
- else {
- /* from selected channels
- * This "passes" system aims to try to find "matching" channels to paste keyframes
- * into with increasingly loose matching heuristics. The process finishes when at least
- * one F-Curve has been pasted into.
- */
- for (pass = 0; pass < 3; pass++) {
- unsigned int totmatch = 0;
-
- for (ale = anim_data->first; ale; ale = ale->next) {
- /* find buffer item to paste from
- * - if names don't matter (i.e. only 1 channel in buffer), don't check id/group
- * - if names do matter, only check if id-type is ok for now (group check is not that important)
- * - most importantly, rna-paths should match (array indices are unimportant for now)
- */
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
- FCurve *fcu = (FCurve *)ale->data; /* destination F-Curve */
- tAnimCopybufItem *aci = NULL;
-
- switch (pass) {
- case 0:
- /* most strict, must be exact path match data_path & index */
- aci = pastebuf_match_path_full(fcu, from_single, to_simple, flip);
- break;
-
- case 1:
- /* less strict, just compare property names */
- aci = pastebuf_match_path_property(ac->bmain, fcu, from_single, to_simple);
- break;
-
- case 2:
- /* Comparing properties gave no results, so just do index comparisons */
- aci = pastebuf_match_index_only(fcu, from_single, to_simple);
- break;
- }
-
- /* copy the relevant data from the matching buffer curve */
- if (aci) {
- totmatch++;
-
- if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
- paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, flip);
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
- }
- else {
- paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, flip);
- }
- }
-
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
-
- /* don't continue if some fcurves were pasted */
- if (totmatch)
- break;
- }
- }
-
- ANIM_animdata_update(ac, anim_data);
-
- return 0;
+ bAnimListElem *ale;
+
+ const Scene *scene = (ac->scene);
+
+ const bool from_single = BLI_listbase_is_single(&animcopybuf);
+ const bool to_simple = BLI_listbase_is_single(anim_data);
+
+ float offset = 0.0f;
+ int pass;
+
+ /* check if buffer is empty */
+ if (BLI_listbase_is_empty(&animcopybuf)) {
+ BKE_report(ac->reports, RPT_ERROR, "No animation data in buffer to paste");
+ return -1;
+ }
+
+ if (BLI_listbase_is_empty(anim_data)) {
+ BKE_report(ac->reports, RPT_ERROR, "No selected F-Curves to paste into");
+ return -1;
+ }
+
+ /* methods of offset */
+ switch (offset_mode) {
+ case KEYFRAME_PASTE_OFFSET_CFRA_START:
+ offset = (float)(CFRA - animcopy_firstframe);
+ break;
+ case KEYFRAME_PASTE_OFFSET_CFRA_END:
+ offset = (float)(CFRA - animcopy_lastframe);
+ break;
+ case KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE:
+ offset = (float)(CFRA - animcopy_cfra);
+ break;
+ case KEYFRAME_PASTE_OFFSET_NONE:
+ offset = 0.0f;
+ break;
+ }
+
+ if (from_single && to_simple) {
+ /* 1:1 match, no tricky checking, just paste */
+ FCurve *fcu;
+ tAnimCopybufItem *aci;
+
+ ale = anim_data->first;
+ fcu = (FCurve *)ale->data; /* destination F-Curve */
+ aci = animcopybuf.first;
+
+ paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, false);
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
+ else {
+ /* from selected channels
+ * This "passes" system aims to try to find "matching" channels to paste keyframes
+ * into with increasingly loose matching heuristics. The process finishes when at least
+ * one F-Curve has been pasted into.
+ */
+ for (pass = 0; pass < 3; pass++) {
+ unsigned int totmatch = 0;
+
+ for (ale = anim_data->first; ale; ale = ale->next) {
+ /* find buffer item to paste from
+ * - if names don't matter (i.e. only 1 channel in buffer), don't check id/group
+ * - if names do matter, only check if id-type is ok for now (group check is not that important)
+ * - most importantly, rna-paths should match (array indices are unimportant for now)
+ */
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+ FCurve *fcu = (FCurve *)ale->data; /* destination F-Curve */
+ tAnimCopybufItem *aci = NULL;
+
+ switch (pass) {
+ case 0:
+ /* most strict, must be exact path match data_path & index */
+ aci = pastebuf_match_path_full(fcu, from_single, to_simple, flip);
+ break;
+
+ case 1:
+ /* less strict, just compare property names */
+ aci = pastebuf_match_path_property(ac->bmain, fcu, from_single, to_simple);
+ break;
+
+ case 2:
+ /* Comparing properties gave no results, so just do index comparisons */
+ aci = pastebuf_match_index_only(fcu, from_single, to_simple);
+ break;
+ }
+
+ /* copy the relevant data from the matching buffer curve */
+ if (aci) {
+ totmatch++;
+
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
+ paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, flip);
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
+ }
+ else {
+ paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, flip);
+ }
+ }
+
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
+
+ /* don't continue if some fcurves were pasted */
+ if (totmatch)
+ break;
+ }
+ }
+
+ ANIM_animdata_update(ac, anim_data);
+
+ return 0;
}
/* **************************************************** */
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 793a73e6939..cc8dbbca439 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -21,7 +21,6 @@
* \ingroup edanimation
*/
-
#include <stdio.h>
#include <stddef.h>
#include <string.h>
@@ -80,7 +79,9 @@
#include "anim_intern.h"
-static KeyingSet *keyingset_get_from_op_with_error(wmOperator *op, PropertyRNA *prop, Scene *scene);
+static KeyingSet *keyingset_get_from_op_with_error(wmOperator *op,
+ PropertyRNA *prop,
+ Scene *scene);
/* ************************************************** */
/* Keyframing Setting Wrangling */
@@ -88,35 +89,35 @@ static KeyingSet *keyingset_get_from_op_with_error(wmOperator *op, PropertyRNA *
/* Get the active settings for keyframing settings from context (specifically the given scene) */
short ANIM_get_keyframing_flags(Scene *scene, short incl_mode)
{
- eInsertKeyFlags flag = INSERTKEY_NOFLAGS;
-
- /* standard flags */
- {
- /* visual keying */
- if (IS_AUTOKEY_FLAG(scene, AUTOMATKEY))
- flag |= INSERTKEY_MATRIX;
-
- /* only needed */
- if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED))
- flag |= INSERTKEY_NEEDED;
-
- /* default F-Curve color mode - RGB from XYZ indices */
- if (IS_AUTOKEY_FLAG(scene, XYZ2RGB))
- flag |= INSERTKEY_XYZ2RGB;
- }
-
- /* only if including settings from the autokeying mode... */
- if (incl_mode) {
- /* keyframing mode - only replace existing keyframes */
- if (IS_AUTOKEY_MODE(scene, EDITKEYS))
- flag |= INSERTKEY_REPLACE;
-
- /* cycle-aware keyframe insertion - preserve cycle period and flow */
- if (IS_AUTOKEY_FLAG(scene, CYCLEAWARE))
- flag |= INSERTKEY_CYCLE_AWARE;
- }
-
- return flag;
+ eInsertKeyFlags flag = INSERTKEY_NOFLAGS;
+
+ /* standard flags */
+ {
+ /* visual keying */
+ if (IS_AUTOKEY_FLAG(scene, AUTOMATKEY))
+ flag |= INSERTKEY_MATRIX;
+
+ /* only needed */
+ if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED))
+ flag |= INSERTKEY_NEEDED;
+
+ /* default F-Curve color mode - RGB from XYZ indices */
+ if (IS_AUTOKEY_FLAG(scene, XYZ2RGB))
+ flag |= INSERTKEY_XYZ2RGB;
+ }
+
+ /* only if including settings from the autokeying mode... */
+ if (incl_mode) {
+ /* keyframing mode - only replace existing keyframes */
+ if (IS_AUTOKEY_MODE(scene, EDITKEYS))
+ flag |= INSERTKEY_REPLACE;
+
+ /* cycle-aware keyframe insertion - preserve cycle period and flow */
+ if (IS_AUTOKEY_FLAG(scene, CYCLEAWARE))
+ flag |= INSERTKEY_CYCLE_AWARE;
+ }
+
+ return flag;
}
/* ******************************************* */
@@ -127,140 +128,145 @@ short ANIM_get_keyframing_flags(Scene *scene, short incl_mode)
*/
bAction *verify_adt_action(Main *bmain, ID *id, short add)
{
- AnimData *adt;
-
- /* init animdata if none available yet */
- adt = BKE_animdata_from_id(id);
- if ((adt == NULL) && (add))
- adt = BKE_animdata_add_id(id);
- if (adt == NULL) {
- /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
- printf("ERROR: Couldn't add AnimData (ID = %s)\n", (id) ? (id->name) : "<None>");
- return NULL;
- }
-
- /* init action if none available yet */
- /* TODO: need some wizardry to handle NLA stuff correct */
- if ((adt->action == NULL) && (add)) {
- /* init action name from name of ID block */
- char actname[sizeof(id->name) - 2];
- BLI_snprintf(actname, sizeof(actname), "%sAction", id->name + 2);
-
- /* create action */
- adt->action = BKE_action_add(bmain, actname);
-
- /* set ID-type from ID-block that this is going to be assigned to
- * so that users can't accidentally break actions by assigning them
- * to the wrong places
- */
- adt->action->idroot = GS(id->name);
-
- /* Tag depsgraph to be rebuilt to include time dependency. */
- DEG_relations_tag_update(bmain);
- }
-
- DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
-
- /* return the action */
- return adt->action;
+ AnimData *adt;
+
+ /* init animdata if none available yet */
+ adt = BKE_animdata_from_id(id);
+ if ((adt == NULL) && (add))
+ adt = BKE_animdata_add_id(id);
+ if (adt == NULL) {
+ /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
+ printf("ERROR: Couldn't add AnimData (ID = %s)\n", (id) ? (id->name) : "<None>");
+ return NULL;
+ }
+
+ /* init action if none available yet */
+ /* TODO: need some wizardry to handle NLA stuff correct */
+ if ((adt->action == NULL) && (add)) {
+ /* init action name from name of ID block */
+ char actname[sizeof(id->name) - 2];
+ BLI_snprintf(actname, sizeof(actname), "%sAction", id->name + 2);
+
+ /* create action */
+ adt->action = BKE_action_add(bmain, actname);
+
+ /* set ID-type from ID-block that this is going to be assigned to
+ * so that users can't accidentally break actions by assigning them
+ * to the wrong places
+ */
+ adt->action->idroot = GS(id->name);
+
+ /* Tag depsgraph to be rebuilt to include time dependency. */
+ DEG_relations_tag_update(bmain);
+ }
+
+ DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
+
+ /* return the action */
+ return adt->action;
}
/* 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 *verify_fcurve(Main *bmain, bAction *act, const char group[], PointerRNA *ptr,
- const char rna_path[], const int array_index, short add)
+FCurve *verify_fcurve(Main *bmain,
+ bAction *act,
+ const char group[],
+ PointerRNA *ptr,
+ const char rna_path[],
+ const int array_index,
+ short add)
{
- bActionGroup *agrp;
- FCurve *fcu;
-
- /* sanity checks */
- if (ELEM(NULL, act, rna_path))
- return NULL;
-
- /* try to find f-curve matching for this setting
- * - add if not found and allowed to add one
- * TODO: add auto-grouping support? how this works will need to be resolved
- */
- fcu = list_find_fcurve(&act->curves, rna_path, array_index);
-
- if ((fcu == NULL) && (add)) {
- /* use default settings to make a F-Curve */
- fcu = MEM_callocN(sizeof(FCurve), "FCurve");
-
- fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
- fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
- if (BLI_listbase_is_empty(&act->curves))
- fcu->flag |= FCURVE_ACTIVE; /* first one added active */
-
- /* store path - make copy, and store that */
- fcu->rna_path = BLI_strdup(rna_path);
- fcu->array_index = array_index;
-
- /* if a group name has been provided, try to add or find a group, then add F-Curve to it */
- if (group) {
- /* try to find group */
- agrp = BKE_action_group_find_name(act, group);
-
- /* no matching groups, so add one */
- if (agrp == NULL) {
- agrp = action_groups_add_new(act, group);
-
- /* sync bone group colors if applicable */
- if (ptr && (ptr->type == &RNA_PoseBone)) {
- Object *ob = (Object *)ptr->id.data;
- bPoseChannel *pchan = (bPoseChannel *)ptr->data;
- bPose *pose = ob->pose;
- bActionGroup *grp;
-
- /* find bone group (if present), and use the color from that */
- grp = (bActionGroup *)BLI_findlink(&pose->agroups, (pchan->agrp_index - 1));
- if (grp) {
- agrp->customCol = grp->customCol;
- action_group_colors_sync(agrp, grp);
- }
- }
- }
-
- /* add F-Curve to group */
- action_groups_add_channel(act, agrp, fcu);
- }
- else {
- /* just add F-Curve to end of Action's list */
- BLI_addtail(&act->curves, fcu);
- }
-
- /* New f-curve was added, meaning it's possible that it affects
- * dependency graph component which wasn't previously animated.
- */
- DEG_relations_tag_update(bmain);
- }
-
- /* return the F-Curve */
- return fcu;
+ bActionGroup *agrp;
+ FCurve *fcu;
+
+ /* sanity checks */
+ if (ELEM(NULL, act, rna_path))
+ return NULL;
+
+ /* try to find f-curve matching for this setting
+ * - add if not found and allowed to add one
+ * TODO: add auto-grouping support? how this works will need to be resolved
+ */
+ fcu = list_find_fcurve(&act->curves, rna_path, array_index);
+
+ if ((fcu == NULL) && (add)) {
+ /* use default settings to make a F-Curve */
+ fcu = MEM_callocN(sizeof(FCurve), "FCurve");
+
+ fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
+ fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
+ if (BLI_listbase_is_empty(&act->curves))
+ fcu->flag |= FCURVE_ACTIVE; /* first one added active */
+
+ /* store path - make copy, and store that */
+ fcu->rna_path = BLI_strdup(rna_path);
+ fcu->array_index = array_index;
+
+ /* if a group name has been provided, try to add or find a group, then add F-Curve to it */
+ if (group) {
+ /* try to find group */
+ agrp = BKE_action_group_find_name(act, group);
+
+ /* no matching groups, so add one */
+ if (agrp == NULL) {
+ agrp = action_groups_add_new(act, group);
+
+ /* sync bone group colors if applicable */
+ if (ptr && (ptr->type == &RNA_PoseBone)) {
+ Object *ob = (Object *)ptr->id.data;
+ bPoseChannel *pchan = (bPoseChannel *)ptr->data;
+ bPose *pose = ob->pose;
+ bActionGroup *grp;
+
+ /* find bone group (if present), and use the color from that */
+ grp = (bActionGroup *)BLI_findlink(&pose->agroups, (pchan->agrp_index - 1));
+ if (grp) {
+ agrp->customCol = grp->customCol;
+ action_group_colors_sync(agrp, grp);
+ }
+ }
+ }
+
+ /* add F-Curve to group */
+ action_groups_add_channel(act, agrp, fcu);
+ }
+ else {
+ /* just add F-Curve to end of Action's list */
+ BLI_addtail(&act->curves, fcu);
+ }
+
+ /* New f-curve was added, meaning it's possible that it affects
+ * dependency graph component which wasn't previously animated.
+ */
+ DEG_relations_tag_update(bmain);
+ }
+
+ /* return the F-Curve */
+ return fcu;
}
/* Helper for update_autoflags_fcurve() */
static void update_autoflags_fcurve_direct(FCurve *fcu, PropertyRNA *prop)
{
- /* set additional flags for the F-Curve (i.e. only integer values) */
- fcu->flag &= ~(FCURVE_INT_VALUES | FCURVE_DISCRETE_VALUES);
- switch (RNA_property_type(prop)) {
- case PROP_FLOAT:
- /* do nothing */
- break;
- case PROP_INT:
- /* do integer (only 'whole' numbers) interpolation between all points */
- fcu->flag |= FCURVE_INT_VALUES;
- break;
- default:
- /* do 'discrete' (i.e. enum, boolean values which cannot take any intermediate
- * values at all) interpolation between all points
- * - however, we must also ensure that evaluated values are only integers still
- */
- fcu->flag |= (FCURVE_DISCRETE_VALUES | FCURVE_INT_VALUES);
- break;
- }
+ /* set additional flags for the F-Curve (i.e. only integer values) */
+ fcu->flag &= ~(FCURVE_INT_VALUES | FCURVE_DISCRETE_VALUES);
+ switch (RNA_property_type(prop)) {
+ case PROP_FLOAT:
+ /* do nothing */
+ break;
+ case PROP_INT:
+ /* do integer (only 'whole' numbers) interpolation between all points */
+ fcu->flag |= FCURVE_INT_VALUES;
+ break;
+ default:
+ /* do 'discrete' (i.e. enum, boolean values which cannot take any intermediate
+ * values at all) interpolation between all points
+ * - however, we must also ensure that evaluated values are only integers still
+ */
+ fcu->flag |= (FCURVE_DISCRETE_VALUES | FCURVE_INT_VALUES);
+ break;
+ }
}
/* Update integer/discrete flags of the FCurve (used when creating/inserting keyframes,
@@ -268,34 +274,36 @@ static void update_autoflags_fcurve_direct(FCurve *fcu, PropertyRNA *prop)
*/
void update_autoflags_fcurve(FCurve *fcu, bContext *C, ReportList *reports, PointerRNA *ptr)
{
- PointerRNA tmp_ptr;
- PropertyRNA *prop;
- int old_flag = fcu->flag;
-
- if ((ptr->id.data == NULL) && (ptr->data == NULL)) {
- BKE_report(reports, RPT_ERROR, "No RNA pointer available to retrieve values for this fcurve");
- return;
- }
-
- /* try to get property we should be affecting */
- if (RNA_path_resolve_property(ptr, fcu->rna_path, &tmp_ptr, &prop) == false) {
- /* property not found... */
- const char *idname = (ptr->id.data) ? ((ID *)ptr->id.data)->name : TIP_("<No ID pointer>");
-
- BKE_reportf(reports, RPT_ERROR,
- "Could not update flags for this fcurve, as RNA path is invalid for the given ID "
- "(ID = %s, path = %s)",
- idname, fcu->rna_path);
- return;
- }
-
- /* update F-Curve flags */
- update_autoflags_fcurve_direct(fcu, prop);
-
- if (old_flag != fcu->flag) {
- /* Same as if keyframes had been changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- }
+ PointerRNA tmp_ptr;
+ PropertyRNA *prop;
+ int old_flag = fcu->flag;
+
+ if ((ptr->id.data == NULL) && (ptr->data == NULL)) {
+ BKE_report(reports, RPT_ERROR, "No RNA pointer available to retrieve values for this fcurve");
+ return;
+ }
+
+ /* try to get property we should be affecting */
+ if (RNA_path_resolve_property(ptr, fcu->rna_path, &tmp_ptr, &prop) == false) {
+ /* property not found... */
+ const char *idname = (ptr->id.data) ? ((ID *)ptr->id.data)->name : TIP_("<No ID pointer>");
+
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Could not update flags for this fcurve, as RNA path is invalid for the given ID "
+ "(ID = %s, path = %s)",
+ idname,
+ fcu->rna_path);
+ return;
+ }
+
+ /* update F-Curve flags */
+ update_autoflags_fcurve_direct(fcu, prop);
+
+ if (old_flag != fcu->flag) {
+ /* Same as if keyframes had been changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ }
}
/* ************************************************** */
@@ -306,40 +314,40 @@ void update_autoflags_fcurve(FCurve *fcu, bContext *C, ReportList *reports, Poin
*/
static eFCU_Cycle_Type remap_cyclic_keyframe_location(FCurve *fcu, float *px, float *py)
{
- if (fcu->totvert < 2 || !fcu->bezt) {
- return FCU_CYCLE_NONE;
- }
+ if (fcu->totvert < 2 || !fcu->bezt) {
+ return FCU_CYCLE_NONE;
+ }
- eFCU_Cycle_Type type = BKE_fcurve_get_cycle_type(fcu);
+ eFCU_Cycle_Type type = BKE_fcurve_get_cycle_type(fcu);
- if (type == FCU_CYCLE_NONE) {
- return FCU_CYCLE_NONE;
- }
+ if (type == FCU_CYCLE_NONE) {
+ return FCU_CYCLE_NONE;
+ }
- BezTriple *first = &fcu->bezt[0], *last = &fcu->bezt[fcu->totvert - 1];
- float start = first->vec[1][0], end = last->vec[1][0];
+ BezTriple *first = &fcu->bezt[0], *last = &fcu->bezt[fcu->totvert - 1];
+ float start = first->vec[1][0], end = last->vec[1][0];
- if (start >= end) {
- return FCU_CYCLE_NONE;
- }
+ if (start >= end) {
+ return FCU_CYCLE_NONE;
+ }
- if (*px < start || *px > end) {
- float period = end - start;
- float step = floorf((*px - start) / period);
- *px -= step * period;
+ if (*px < start || *px > end) {
+ float period = end - start;
+ float step = floorf((*px - start) / period);
+ *px -= step * period;
- if (type == FCU_CYCLE_OFFSET) {
- /* Nasty check to handle the case when the modes are different better. */
- FMod_Cycles *data = ((FModifier *)fcu->modifiers.first)->data;
- short mode = (step >= 0) ? data->after_mode : data->before_mode;
+ if (type == FCU_CYCLE_OFFSET) {
+ /* Nasty check to handle the case when the modes are different better. */
+ FMod_Cycles *data = ((FModifier *)fcu->modifiers.first)->data;
+ short mode = (step >= 0) ? data->after_mode : data->before_mode;
- if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
- *py -= step * (last->vec[1][1] - first->vec[1][1]);
- }
- }
- }
+ if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
+ *py -= step * (last->vec[1][1] - first->vec[1][1]);
+ }
+ }
+ }
- return type;
+ return type;
}
/* -------------- BezTriple Insertion -------------------- */
@@ -347,19 +355,19 @@ static eFCU_Cycle_Type remap_cyclic_keyframe_location(FCurve *fcu, float *px, fl
/* Change the Y position of a keyframe to match the input, adjusting handles. */
static void replace_bezt_keyframe_ypos(BezTriple *dst, const BezTriple *bezt)
{
- /* just change the values when replacing, so as to not overwrite handles */
- float dy = bezt->vec[1][1] - dst->vec[1][1];
+ /* just change the values when replacing, so as to not overwrite handles */
+ float dy = bezt->vec[1][1] - dst->vec[1][1];
- /* just apply delta value change to the handle values */
- dst->vec[0][1] += dy;
- dst->vec[1][1] += dy;
- dst->vec[2][1] += dy;
+ /* just apply delta value change to the handle values */
+ dst->vec[0][1] += dy;
+ dst->vec[1][1] += dy;
+ dst->vec[2][1] += dy;
- dst->f1 = bezt->f1;
- dst->f2 = bezt->f2;
- dst->f3 = bezt->f3;
+ dst->f1 = bezt->f1;
+ dst->f2 = bezt->f2;
+ dst->f3 = bezt->f3;
- /* TODO: perform some other operations? */
+ /* TODO: perform some other operations? */
}
/* This function adds a given BezTriple to an F-Curve. It will allocate
@@ -371,81 +379,81 @@ static void replace_bezt_keyframe_ypos(BezTriple *dst, const BezTriple *bezt)
*/
int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag)
{
- int i = 0;
-
- /* are there already keyframes? */
- if (fcu->bezt) {
- bool replace;
- i = binarysearch_bezt_index(fcu->bezt, bezt->vec[1][0], fcu->totvert, &replace);
-
- /* replace an existing keyframe? */
- if (replace) {
- /* sanity check: 'i' may in rare cases exceed arraylen */
- if ((i >= 0) && (i < fcu->totvert)) {
- if (flag & INSERTKEY_OVERWRITE_FULL) {
- fcu->bezt[i] = *bezt;
- }
- else {
- replace_bezt_keyframe_ypos(&fcu->bezt[i], bezt);
- }
-
- if (flag & INSERTKEY_CYCLE_AWARE) {
- /* If replacing an end point of a cyclic curve without offset, modify the other end too. */
- if ((i == 0 || i == fcu->totvert - 1) && BKE_fcurve_get_cycle_type(fcu) == FCU_CYCLE_PERFECT) {
- replace_bezt_keyframe_ypos(&fcu->bezt[i == 0 ? fcu->totvert - 1 : 0], bezt);
- }
- }
- }
- }
- /* keyframing modes allow to not replace keyframe */
- else if ((flag & INSERTKEY_REPLACE) == 0) {
- /* insert new - if we're not restricted to replacing keyframes only */
- BezTriple *newb = MEM_callocN((fcu->totvert + 1) * sizeof(BezTriple), "beztriple");
-
- /* add the beztriples that should occur before the beztriple to be pasted (originally in fcu) */
- if (i > 0)
- memcpy(newb, fcu->bezt, i * sizeof(BezTriple));
-
- /* add beztriple to paste at index i */
- *(newb + i) = *bezt;
-
- /* add the beztriples that occur after the beztriple to be pasted (originally in fcu) */
- if (i < fcu->totvert)
- memcpy(newb + i + 1, fcu->bezt + i, (fcu->totvert - i) * sizeof(BezTriple));
-
- /* replace (+ free) old with new, only if necessary to do so */
- MEM_freeN(fcu->bezt);
- fcu->bezt = newb;
-
- fcu->totvert++;
- }
- else {
- return -1;
- }
- }
- /* no keyframes already, but can only add if...
- * 1) keyframing modes say that keyframes can only be replaced, so adding new ones won't know
- * 2) there are no samples on the curve
- * // NOTE: maybe we may want to allow this later when doing samples -> bezt conversions,
- * // but for now, having both is asking for trouble
- */
- else if ((flag & INSERTKEY_REPLACE) == 0 && (fcu->fpt == NULL)) {
- /* create new keyframes array */
- fcu->bezt = MEM_callocN(sizeof(BezTriple), "beztriple");
- *(fcu->bezt) = *bezt;
- fcu->totvert = 1;
- }
- /* cannot add anything */
- else {
- /* return error code -1 to prevent any misunderstandings */
- return -1;
- }
-
-
- /* we need to return the index, so that some tools which do post-processing can
- * detect where we added the BezTriple in the array
- */
- return i;
+ int i = 0;
+
+ /* are there already keyframes? */
+ if (fcu->bezt) {
+ bool replace;
+ i = binarysearch_bezt_index(fcu->bezt, bezt->vec[1][0], fcu->totvert, &replace);
+
+ /* replace an existing keyframe? */
+ if (replace) {
+ /* sanity check: 'i' may in rare cases exceed arraylen */
+ if ((i >= 0) && (i < fcu->totvert)) {
+ if (flag & INSERTKEY_OVERWRITE_FULL) {
+ fcu->bezt[i] = *bezt;
+ }
+ else {
+ replace_bezt_keyframe_ypos(&fcu->bezt[i], bezt);
+ }
+
+ if (flag & INSERTKEY_CYCLE_AWARE) {
+ /* If replacing an end point of a cyclic curve without offset, modify the other end too. */
+ if ((i == 0 || i == fcu->totvert - 1) &&
+ BKE_fcurve_get_cycle_type(fcu) == FCU_CYCLE_PERFECT) {
+ replace_bezt_keyframe_ypos(&fcu->bezt[i == 0 ? fcu->totvert - 1 : 0], bezt);
+ }
+ }
+ }
+ }
+ /* keyframing modes allow to not replace keyframe */
+ else if ((flag & INSERTKEY_REPLACE) == 0) {
+ /* insert new - if we're not restricted to replacing keyframes only */
+ BezTriple *newb = MEM_callocN((fcu->totvert + 1) * sizeof(BezTriple), "beztriple");
+
+ /* add the beztriples that should occur before the beztriple to be pasted (originally in fcu) */
+ if (i > 0)
+ memcpy(newb, fcu->bezt, i * sizeof(BezTriple));
+
+ /* add beztriple to paste at index i */
+ *(newb + i) = *bezt;
+
+ /* add the beztriples that occur after the beztriple to be pasted (originally in fcu) */
+ if (i < fcu->totvert)
+ memcpy(newb + i + 1, fcu->bezt + i, (fcu->totvert - i) * sizeof(BezTriple));
+
+ /* replace (+ free) old with new, only if necessary to do so */
+ MEM_freeN(fcu->bezt);
+ fcu->bezt = newb;
+
+ fcu->totvert++;
+ }
+ else {
+ return -1;
+ }
+ }
+ /* no keyframes already, but can only add if...
+ * 1) keyframing modes say that keyframes can only be replaced, so adding new ones won't know
+ * 2) there are no samples on the curve
+ * // NOTE: maybe we may want to allow this later when doing samples -> bezt conversions,
+ * // but for now, having both is asking for trouble
+ */
+ else if ((flag & INSERTKEY_REPLACE) == 0 && (fcu->fpt == NULL)) {
+ /* create new keyframes array */
+ fcu->bezt = MEM_callocN(sizeof(BezTriple), "beztriple");
+ *(fcu->bezt) = *bezt;
+ fcu->totvert = 1;
+ }
+ /* cannot add anything */
+ else {
+ /* return error code -1 to prevent any misunderstandings */
+ return -1;
+ }
+
+ /* we need to return the index, so that some tools which do post-processing can
+ * detect where we added the BezTriple in the array
+ */
+ return i;
}
/**
@@ -457,114 +465,116 @@ int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag)
* \param flag: Optional flags (eInsertKeyFlags) for controlling how keys get added
* and/or whether updates get done.
*/
-int insert_vert_fcurve(FCurve *fcu, float x, float y, eBezTriple_KeyframeType keyframe_type, eInsertKeyFlags flag)
+int insert_vert_fcurve(
+ FCurve *fcu, float x, float y, eBezTriple_KeyframeType keyframe_type, eInsertKeyFlags flag)
{
- BezTriple beztr = {{{0}}};
- unsigned int oldTot = fcu->totvert;
- int a;
-
- /* set all three points, for nicer start position
- * NOTE: +/- 1 on vec.x for left and right handles is so that 'free' handles work ok...
- */
- beztr.vec[0][0] = x - 1.0f;
- beztr.vec[0][1] = y;
- beztr.vec[1][0] = x;
- beztr.vec[1][1] = y;
- beztr.vec[2][0] = x + 1.0f;
- beztr.vec[2][1] = y;
- beztr.f1 = beztr.f2 = beztr.f3 = SELECT;
-
- /* set default handle types and interpolation mode */
- if (flag & INSERTKEY_NO_USERPREF) {
- /* for Py-API, we want scripts to have predictable behavior,
- * hence the option to not depend on the userpref defaults
- */
- beztr.h1 = beztr.h2 = HD_AUTO_ANIM;
- beztr.ipo = BEZT_IPO_BEZ;
- }
- else {
- /* for UI usage - defaults should come from the userprefs and/or toolsettings */
- beztr.h1 = beztr.h2 = U.keyhandles_new; /* use default handle type here */
-
- /* use default interpolation mode, with exceptions for int/discrete values */
- beztr.ipo = U.ipo_new;
- }
-
- /* interpolation type used is constrained by the type of values the curve can take */
- if (fcu->flag & FCURVE_DISCRETE_VALUES) {
- beztr.ipo = BEZT_IPO_CONST;
- }
- else if ((beztr.ipo == BEZT_IPO_BEZ) && (fcu->flag & FCURVE_INT_VALUES)) {
- beztr.ipo = BEZT_IPO_LIN;
- }
-
- /* set keyframe type value (supplied), which should come from the scene settings in most cases */
- BEZKEYTYPE(&beztr) = keyframe_type;
-
- /* set default values for "easing" interpolation mode settings
- * NOTE: Even if these modes aren't currently used, if users switch
- * to these later, we want these to work in a sane way out of
- * the box.
- */
-
- /* "back" easing - this value used to be used when overshoot=0, but that
- * introduced discontinuities in how the param worked. */
- beztr.back = 1.70158f;
-
- /* "elastic" easing - values here were hand-optimised for a default duration of
- * ~10 frames (typical mograph motion length) */
- beztr.amplitude = 0.8f;
- beztr.period = 4.1f;
-
- /* add temp beztriple to keyframes */
- a = insert_bezt_fcurve(fcu, &beztr, flag);
-
- /* what if 'a' is a negative index?
- * for now, just exit to prevent any segfaults
- */
- if (a < 0) return -1;
-
- /* don't recalculate handles if fast is set
- * - this is a hack to make importers faster
- * - we may calculate twice (due to autohandle needing to be calculated twice)
- */
- if ((flag & INSERTKEY_FAST) == 0)
- calchandles_fcurve(fcu);
-
- /* set handletype and interpolation */
- if ((fcu->totvert > 2) && (flag & INSERTKEY_REPLACE) == 0) {
- BezTriple *bezt = (fcu->bezt + a);
-
- /* set interpolation from previous (if available), but only if we didn't just replace some keyframe
- * - replacement is indicated by no-change in number of verts
- * - when replacing, the user may have specified some interpolation that should be kept
- */
- if (fcu->totvert > oldTot) {
- if (a > 0)
- bezt->ipo = (bezt - 1)->ipo;
- else if (a < fcu->totvert - 1)
- bezt->ipo = (bezt + 1)->ipo;
- }
-
- /* don't recalculate handles if fast is set
- * - this is a hack to make importers faster
- * - we may calculate twice (due to autohandle needing to be calculated twice)
- */
- if ((flag & INSERTKEY_FAST) == 0)
- calchandles_fcurve(fcu);
- }
-
- /* return the index at which the keyframe was added */
- return a;
+ BezTriple beztr = {{{0}}};
+ unsigned int oldTot = fcu->totvert;
+ int a;
+
+ /* set all three points, for nicer start position
+ * NOTE: +/- 1 on vec.x for left and right handles is so that 'free' handles work ok...
+ */
+ beztr.vec[0][0] = x - 1.0f;
+ beztr.vec[0][1] = y;
+ beztr.vec[1][0] = x;
+ beztr.vec[1][1] = y;
+ beztr.vec[2][0] = x + 1.0f;
+ beztr.vec[2][1] = y;
+ beztr.f1 = beztr.f2 = beztr.f3 = SELECT;
+
+ /* set default handle types and interpolation mode */
+ if (flag & INSERTKEY_NO_USERPREF) {
+ /* for Py-API, we want scripts to have predictable behavior,
+ * hence the option to not depend on the userpref defaults
+ */
+ beztr.h1 = beztr.h2 = HD_AUTO_ANIM;
+ beztr.ipo = BEZT_IPO_BEZ;
+ }
+ else {
+ /* for UI usage - defaults should come from the userprefs and/or toolsettings */
+ beztr.h1 = beztr.h2 = U.keyhandles_new; /* use default handle type here */
+
+ /* use default interpolation mode, with exceptions for int/discrete values */
+ beztr.ipo = U.ipo_new;
+ }
+
+ /* interpolation type used is constrained by the type of values the curve can take */
+ if (fcu->flag & FCURVE_DISCRETE_VALUES) {
+ beztr.ipo = BEZT_IPO_CONST;
+ }
+ else if ((beztr.ipo == BEZT_IPO_BEZ) && (fcu->flag & FCURVE_INT_VALUES)) {
+ beztr.ipo = BEZT_IPO_LIN;
+ }
+
+ /* set keyframe type value (supplied), which should come from the scene settings in most cases */
+ BEZKEYTYPE(&beztr) = keyframe_type;
+
+ /* set default values for "easing" interpolation mode settings
+ * NOTE: Even if these modes aren't currently used, if users switch
+ * to these later, we want these to work in a sane way out of
+ * the box.
+ */
+
+ /* "back" easing - this value used to be used when overshoot=0, but that
+ * introduced discontinuities in how the param worked. */
+ beztr.back = 1.70158f;
+
+ /* "elastic" easing - values here were hand-optimised for a default duration of
+ * ~10 frames (typical mograph motion length) */
+ beztr.amplitude = 0.8f;
+ beztr.period = 4.1f;
+
+ /* add temp beztriple to keyframes */
+ a = insert_bezt_fcurve(fcu, &beztr, flag);
+
+ /* what if 'a' is a negative index?
+ * for now, just exit to prevent any segfaults
+ */
+ if (a < 0)
+ return -1;
+
+ /* don't recalculate handles if fast is set
+ * - this is a hack to make importers faster
+ * - we may calculate twice (due to autohandle needing to be calculated twice)
+ */
+ if ((flag & INSERTKEY_FAST) == 0)
+ calchandles_fcurve(fcu);
+
+ /* set handletype and interpolation */
+ if ((fcu->totvert > 2) && (flag & INSERTKEY_REPLACE) == 0) {
+ BezTriple *bezt = (fcu->bezt + a);
+
+ /* set interpolation from previous (if available), but only if we didn't just replace some keyframe
+ * - replacement is indicated by no-change in number of verts
+ * - when replacing, the user may have specified some interpolation that should be kept
+ */
+ if (fcu->totvert > oldTot) {
+ if (a > 0)
+ bezt->ipo = (bezt - 1)->ipo;
+ else if (a < fcu->totvert - 1)
+ bezt->ipo = (bezt + 1)->ipo;
+ }
+
+ /* don't recalculate handles if fast is set
+ * - this is a hack to make importers faster
+ * - we may calculate twice (due to autohandle needing to be calculated twice)
+ */
+ if ((flag & INSERTKEY_FAST) == 0)
+ calchandles_fcurve(fcu);
+ }
+
+ /* return the index at which the keyframe was added */
+ return a;
}
/* -------------- 'Smarter' Keyframing Functions -------------------- */
/* return codes for new_key_needed */
enum {
- KEYNEEDED_DONTADD = 0,
- KEYNEEDED_JUSTADD,
- KEYNEEDED_DELPREV,
- KEYNEEDED_DELNEXT,
+ KEYNEEDED_DONTADD = 0,
+ KEYNEEDED_JUSTADD,
+ KEYNEEDED_DELPREV,
+ KEYNEEDED_DELNEXT,
} /*eKeyNeededStatus*/;
/* This helper function determines whether a new keyframe is needed */
@@ -575,187 +585,195 @@ enum {
*/
static short new_key_needed(FCurve *fcu, float cFrame, float nValue)
{
- BezTriple *bezt = NULL, *prev = NULL;
- int totCount, i;
- float valA = 0.0f, valB = 0.0f;
-
- /* safety checking */
- if (fcu == NULL) return KEYNEEDED_JUSTADD;
- totCount = fcu->totvert;
- if (totCount == 0) return KEYNEEDED_JUSTADD;
-
- /* loop through checking if any are the same */
- bezt = fcu->bezt;
- for (i = 0; i < totCount; i++) {
- float prevPosi = 0.0f, prevVal = 0.0f;
- float beztPosi = 0.0f, beztVal = 0.0f;
-
- /* get current time+value */
- beztPosi = bezt->vec[1][0];
- beztVal = bezt->vec[1][1];
-
- if (prev) {
- /* there is a keyframe before the one currently being examined */
-
- /* get previous time+value */
- prevPosi = prev->vec[1][0];
- prevVal = prev->vec[1][1];
-
- /* keyframe to be added at point where there are already two similar points? */
- if (IS_EQF(prevPosi, cFrame) && IS_EQF(beztPosi, cFrame) && IS_EQF(beztPosi, prevPosi)) {
- return KEYNEEDED_DONTADD;
- }
-
- /* keyframe between prev+current points ? */
- if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) {
- /* is the value of keyframe to be added the same as keyframes on either side ? */
- if (IS_EQF(prevVal, nValue) && IS_EQF(beztVal, nValue) && IS_EQF(prevVal, beztVal)) {
- return KEYNEEDED_DONTADD;
- }
- else {
- float realVal;
-
- /* get real value of curve at that point */
- realVal = evaluate_fcurve(fcu, cFrame);
-
- /* compare whether it's the same as proposed */
- if (IS_EQF(realVal, nValue))
- return KEYNEEDED_DONTADD;
- else
- return KEYNEEDED_JUSTADD;
- }
- }
-
- /* new keyframe before prev beztriple? */
- if (cFrame < prevPosi) {
- /* A new keyframe will be added. However, whether the previous beztriple
- * stays around or not depends on whether the values of previous/current
- * beztriples and new keyframe are the same.
- */
- if (IS_EQF(prevVal, nValue) && IS_EQF(beztVal, nValue) && IS_EQF(prevVal, beztVal))
- return KEYNEEDED_DELNEXT;
- else
- return KEYNEEDED_JUSTADD;
- }
- }
- else {
- /* just add a keyframe if there's only one keyframe
- * and the new one occurs before the existing one does.
- */
- if ((cFrame < beztPosi) && (totCount == 1))
- return KEYNEEDED_JUSTADD;
- }
-
- /* continue. frame to do not yet passed (or other conditions not met) */
- if (i < (totCount - 1)) {
- prev = bezt;
- bezt++;
- }
- else
- break;
- }
-
- /* Frame in which to add a new-keyframe occurs after all other keys
- * -> If there are at least two existing keyframes, then if the values of the
- * last two keyframes and the new-keyframe match, the last existing keyframe
- * gets deleted as it is no longer required.
- * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last
- * keyframe is not equal to last keyframe.
- */
- bezt = (fcu->bezt + (fcu->totvert - 1));
- valA = bezt->vec[1][1];
-
- if (prev)
- valB = prev->vec[1][1];
- else
- valB = bezt->vec[1][1] + 1.0f;
-
- if (IS_EQF(valA, nValue) && IS_EQF(valA, valB))
- return KEYNEEDED_DELPREV;
- else
- return KEYNEEDED_JUSTADD;
+ BezTriple *bezt = NULL, *prev = NULL;
+ int totCount, i;
+ float valA = 0.0f, valB = 0.0f;
+
+ /* safety checking */
+ if (fcu == NULL)
+ return KEYNEEDED_JUSTADD;
+ totCount = fcu->totvert;
+ if (totCount == 0)
+ return KEYNEEDED_JUSTADD;
+
+ /* loop through checking if any are the same */
+ bezt = fcu->bezt;
+ for (i = 0; i < totCount; i++) {
+ float prevPosi = 0.0f, prevVal = 0.0f;
+ float beztPosi = 0.0f, beztVal = 0.0f;
+
+ /* get current time+value */
+ beztPosi = bezt->vec[1][0];
+ beztVal = bezt->vec[1][1];
+
+ if (prev) {
+ /* there is a keyframe before the one currently being examined */
+
+ /* get previous time+value */
+ prevPosi = prev->vec[1][0];
+ prevVal = prev->vec[1][1];
+
+ /* keyframe to be added at point where there are already two similar points? */
+ if (IS_EQF(prevPosi, cFrame) && IS_EQF(beztPosi, cFrame) && IS_EQF(beztPosi, prevPosi)) {
+ return KEYNEEDED_DONTADD;
+ }
+
+ /* keyframe between prev+current points ? */
+ if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) {
+ /* is the value of keyframe to be added the same as keyframes on either side ? */
+ if (IS_EQF(prevVal, nValue) && IS_EQF(beztVal, nValue) && IS_EQF(prevVal, beztVal)) {
+ return KEYNEEDED_DONTADD;
+ }
+ else {
+ float realVal;
+
+ /* get real value of curve at that point */
+ realVal = evaluate_fcurve(fcu, cFrame);
+
+ /* compare whether it's the same as proposed */
+ if (IS_EQF(realVal, nValue))
+ return KEYNEEDED_DONTADD;
+ else
+ return KEYNEEDED_JUSTADD;
+ }
+ }
+
+ /* new keyframe before prev beztriple? */
+ if (cFrame < prevPosi) {
+ /* A new keyframe will be added. However, whether the previous beztriple
+ * stays around or not depends on whether the values of previous/current
+ * beztriples and new keyframe are the same.
+ */
+ if (IS_EQF(prevVal, nValue) && IS_EQF(beztVal, nValue) && IS_EQF(prevVal, beztVal))
+ return KEYNEEDED_DELNEXT;
+ else
+ return KEYNEEDED_JUSTADD;
+ }
+ }
+ else {
+ /* just add a keyframe if there's only one keyframe
+ * and the new one occurs before the existing one does.
+ */
+ if ((cFrame < beztPosi) && (totCount == 1))
+ return KEYNEEDED_JUSTADD;
+ }
+
+ /* continue. frame to do not yet passed (or other conditions not met) */
+ if (i < (totCount - 1)) {
+ prev = bezt;
+ bezt++;
+ }
+ else
+ break;
+ }
+
+ /* Frame in which to add a new-keyframe occurs after all other keys
+ * -> If there are at least two existing keyframes, then if the values of the
+ * last two keyframes and the new-keyframe match, the last existing keyframe
+ * gets deleted as it is no longer required.
+ * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last
+ * keyframe is not equal to last keyframe.
+ */
+ bezt = (fcu->bezt + (fcu->totvert - 1));
+ valA = bezt->vec[1][1];
+
+ if (prev)
+ valB = prev->vec[1][1];
+ else
+ valB = bezt->vec[1][1] + 1.0f;
+
+ if (IS_EQF(valA, nValue) && IS_EQF(valA, valB))
+ return KEYNEEDED_DELPREV;
+ else
+ return KEYNEEDED_JUSTADD;
}
/* ------------------ RNA Data-Access Functions ------------------ */
/* Try to read value using RNA-properties obtained already */
-static float *setting_get_rna_values(Depsgraph *depsgraph, PointerRNA *ptr, PropertyRNA *prop, const bool get_evaluated, float *buffer, int buffer_size, int *r_count)
+static float *setting_get_rna_values(Depsgraph *depsgraph,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ const bool get_evaluated,
+ float *buffer,
+ int buffer_size,
+ int *r_count)
{
- BLI_assert(buffer_size >= 1);
-
- float *values = buffer;
- PointerRNA ptr_eval;
-
- if (get_evaluated) {
- DEG_get_evaluated_rna_pointer(depsgraph, ptr, &ptr_eval);
- ptr = &ptr_eval;
- }
-
- if (RNA_property_array_check(prop)) {
- int length = *r_count = RNA_property_array_length(ptr, prop);
- bool *tmp_bool;
- int *tmp_int;
-
- if (length > buffer_size) {
- values = MEM_malloc_arrayN(sizeof(float), length, __func__);
- }
-
- switch (RNA_property_type(prop)) {
- case PROP_BOOLEAN:
- tmp_bool = MEM_malloc_arrayN(sizeof(*tmp_bool), length, __func__);
- RNA_property_boolean_get_array(ptr, prop, tmp_bool);
- for (int i = 0; i < length; i++) {
- values[i] = (float)tmp_bool[i];
- }
- MEM_freeN(tmp_bool);
- break;
- case PROP_INT:
- tmp_int = MEM_malloc_arrayN(sizeof(*tmp_int), length, __func__);
- RNA_property_int_get_array(ptr, prop, tmp_int);
- for (int i = 0; i < length; i++) {
- values[i] = (float)tmp_int[i];
- }
- MEM_freeN(tmp_int);
- break;
- case PROP_FLOAT:
- RNA_property_float_get_array(ptr, prop, values);
- break;
- default:
- memset(values, 0, sizeof(float) * length);
- }
- }
- else {
- *r_count = 1;
-
- switch (RNA_property_type(prop)) {
- case PROP_BOOLEAN:
- *values = (float)RNA_property_boolean_get(ptr, prop);
- break;
- case PROP_INT:
- *values = (float)RNA_property_int_get(ptr, prop);
- break;
- case PROP_FLOAT:
- *values = RNA_property_float_get(ptr, prop);
- break;
- case PROP_ENUM:
- *values = (float)RNA_property_enum_get(ptr, prop);
- break;
- default:
- *values = 0.0f;
- }
- }
-
- return values;
+ BLI_assert(buffer_size >= 1);
+
+ float *values = buffer;
+ PointerRNA ptr_eval;
+
+ if (get_evaluated) {
+ DEG_get_evaluated_rna_pointer(depsgraph, ptr, &ptr_eval);
+ ptr = &ptr_eval;
+ }
+
+ if (RNA_property_array_check(prop)) {
+ int length = *r_count = RNA_property_array_length(ptr, prop);
+ bool *tmp_bool;
+ int *tmp_int;
+
+ if (length > buffer_size) {
+ values = MEM_malloc_arrayN(sizeof(float), length, __func__);
+ }
+
+ switch (RNA_property_type(prop)) {
+ case PROP_BOOLEAN:
+ tmp_bool = MEM_malloc_arrayN(sizeof(*tmp_bool), length, __func__);
+ RNA_property_boolean_get_array(ptr, prop, tmp_bool);
+ for (int i = 0; i < length; i++) {
+ values[i] = (float)tmp_bool[i];
+ }
+ MEM_freeN(tmp_bool);
+ break;
+ case PROP_INT:
+ tmp_int = MEM_malloc_arrayN(sizeof(*tmp_int), length, __func__);
+ RNA_property_int_get_array(ptr, prop, tmp_int);
+ for (int i = 0; i < length; i++) {
+ values[i] = (float)tmp_int[i];
+ }
+ MEM_freeN(tmp_int);
+ break;
+ case PROP_FLOAT:
+ RNA_property_float_get_array(ptr, prop, values);
+ break;
+ default:
+ memset(values, 0, sizeof(float) * length);
+ }
+ }
+ else {
+ *r_count = 1;
+
+ switch (RNA_property_type(prop)) {
+ case PROP_BOOLEAN:
+ *values = (float)RNA_property_boolean_get(ptr, prop);
+ break;
+ case PROP_INT:
+ *values = (float)RNA_property_int_get(ptr, prop);
+ break;
+ case PROP_FLOAT:
+ *values = RNA_property_float_get(ptr, prop);
+ break;
+ case PROP_ENUM:
+ *values = (float)RNA_property_enum_get(ptr, prop);
+ break;
+ default:
+ *values = 0.0f;
+ }
+ }
+
+ return values;
}
/* ------------------ 'Visual' Keyframing Functions ------------------ */
/* internal status codes for visualkey_can_use */
enum {
- VISUALKEY_NONE = 0,
- VISUALKEY_LOC,
- VISUALKEY_ROT,
- VISUALKEY_SCA,
+ VISUALKEY_NONE = 0,
+ VISUALKEY_LOC,
+ VISUALKEY_ROT,
+ VISUALKEY_SCA,
};
/* This helper function determines if visual-keyframing should be used when
@@ -766,331 +784,365 @@ enum {
*/
static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
{
- bConstraint *con = NULL;
- short searchtype = VISUALKEY_NONE;
- bool has_rigidbody = false;
- bool has_parent = false;
- const char *identifier = NULL;
-
- /* validate data */
- if (ELEM(NULL, ptr, ptr->data, prop))
- return false;
-
- /* get first constraint and determine type of keyframe constraints to check for
- * - constraints can be on either Objects or PoseChannels, so we only check if the
- * ptr->type is RNA_Object or RNA_PoseBone, which are the RNA wrapping-info for
- * those structs, allowing us to identify the owner of the data
- */
- if (ptr->type == &RNA_Object) {
- /* Object */
- Object *ob = (Object *)ptr->data;
- RigidBodyOb *rbo = ob->rigidbody_object;
-
- con = ob->constraints.first;
- identifier = RNA_property_identifier(prop);
- has_parent = (ob->parent != NULL);
-
- /* active rigidbody objects only, as only those are affected by sim */
- has_rigidbody = ((rbo) && (rbo->type == RBO_TYPE_ACTIVE));
- }
- else if (ptr->type == &RNA_PoseBone) {
- /* Pose Channel */
- bPoseChannel *pchan = (bPoseChannel *)ptr->data;
-
- con = pchan->constraints.first;
- identifier = RNA_property_identifier(prop);
- has_parent = (pchan->parent != NULL);
- }
-
- /* check if any data to search using */
- if (ELEM(NULL, con, identifier) && (has_parent == false) && (has_rigidbody == false))
- return false;
-
- /* location or rotation identifiers only... */
- if (identifier == NULL) {
- printf("%s failed: NULL identifier\n", __func__);
- return false;
- }
- else if (strstr(identifier, "location")) {
- searchtype = VISUALKEY_LOC;
- }
- else if (strstr(identifier, "rotation")) {
- searchtype = VISUALKEY_ROT;
- }
- else if (strstr(identifier, "scale")) {
- searchtype = VISUALKEY_SCA;
- }
- else {
- printf("%s failed: identifier - '%s'\n", __func__, identifier);
- return false;
- }
-
-
- /* only search if a searchtype and initial constraint are available */
- if (searchtype) {
- /* parent or rigidbody are always matching */
- if (has_parent || has_rigidbody)
- return true;
-
- /* constraints */
- for (; con; con = con->next) {
- /* only consider constraint if it is not disabled, and has influence */
- if (con->flag & CONSTRAINT_DISABLE) continue;
- if (con->enforce == 0.0f) continue;
-
- /* some constraints may alter these transforms */
- switch (con->type) {
- /* multi-transform constraints */
- case CONSTRAINT_TYPE_CHILDOF:
- case CONSTRAINT_TYPE_ARMATURE:
- return true;
- case CONSTRAINT_TYPE_TRANSFORM:
- case CONSTRAINT_TYPE_TRANSLIKE:
- return true;
- case CONSTRAINT_TYPE_FOLLOWPATH:
- return true;
- case CONSTRAINT_TYPE_KINEMATIC:
- return true;
-
- /* single-transform constraints */
- case CONSTRAINT_TYPE_TRACKTO:
- if (searchtype == VISUALKEY_ROT) return true;
- break;
- case CONSTRAINT_TYPE_DAMPTRACK:
- if (searchtype == VISUALKEY_ROT) return true;
- break;
- case CONSTRAINT_TYPE_ROTLIMIT:
- if (searchtype == VISUALKEY_ROT) return true;
- break;
- case CONSTRAINT_TYPE_LOCLIMIT:
- if (searchtype == VISUALKEY_LOC) return true;
- break;
- case CONSTRAINT_TYPE_SIZELIMIT:
- if (searchtype == VISUALKEY_SCA) return true;
- break;
- case CONSTRAINT_TYPE_DISTLIMIT:
- if (searchtype == VISUALKEY_LOC) return true;
- break;
- case CONSTRAINT_TYPE_ROTLIKE:
- if (searchtype == VISUALKEY_ROT) return true;
- break;
- case CONSTRAINT_TYPE_LOCLIKE:
- if (searchtype == VISUALKEY_LOC) return true;
- break;
- case CONSTRAINT_TYPE_SIZELIKE:
- if (searchtype == VISUALKEY_SCA) return true;
- break;
- case CONSTRAINT_TYPE_LOCKTRACK:
- if (searchtype == VISUALKEY_ROT) return true;
- break;
- case CONSTRAINT_TYPE_MINMAX:
- if (searchtype == VISUALKEY_LOC) return true;
- break;
-
- default:
- break;
- }
- }
- }
-
- /* when some condition is met, this function returns, so that means we've got nothing */
- return false;
+ bConstraint *con = NULL;
+ short searchtype = VISUALKEY_NONE;
+ bool has_rigidbody = false;
+ bool has_parent = false;
+ const char *identifier = NULL;
+
+ /* validate data */
+ if (ELEM(NULL, ptr, ptr->data, prop))
+ return false;
+
+ /* get first constraint and determine type of keyframe constraints to check for
+ * - constraints can be on either Objects or PoseChannels, so we only check if the
+ * ptr->type is RNA_Object or RNA_PoseBone, which are the RNA wrapping-info for
+ * those structs, allowing us to identify the owner of the data
+ */
+ if (ptr->type == &RNA_Object) {
+ /* Object */
+ Object *ob = (Object *)ptr->data;
+ RigidBodyOb *rbo = ob->rigidbody_object;
+
+ con = ob->constraints.first;
+ identifier = RNA_property_identifier(prop);
+ has_parent = (ob->parent != NULL);
+
+ /* active rigidbody objects only, as only those are affected by sim */
+ has_rigidbody = ((rbo) && (rbo->type == RBO_TYPE_ACTIVE));
+ }
+ else if (ptr->type == &RNA_PoseBone) {
+ /* Pose Channel */
+ bPoseChannel *pchan = (bPoseChannel *)ptr->data;
+
+ con = pchan->constraints.first;
+ identifier = RNA_property_identifier(prop);
+ has_parent = (pchan->parent != NULL);
+ }
+
+ /* check if any data to search using */
+ if (ELEM(NULL, con, identifier) && (has_parent == false) && (has_rigidbody == false))
+ return false;
+
+ /* location or rotation identifiers only... */
+ if (identifier == NULL) {
+ printf("%s failed: NULL identifier\n", __func__);
+ return false;
+ }
+ else if (strstr(identifier, "location")) {
+ searchtype = VISUALKEY_LOC;
+ }
+ else if (strstr(identifier, "rotation")) {
+ searchtype = VISUALKEY_ROT;
+ }
+ else if (strstr(identifier, "scale")) {
+ searchtype = VISUALKEY_SCA;
+ }
+ else {
+ printf("%s failed: identifier - '%s'\n", __func__, identifier);
+ return false;
+ }
+
+ /* only search if a searchtype and initial constraint are available */
+ if (searchtype) {
+ /* parent or rigidbody are always matching */
+ if (has_parent || has_rigidbody)
+ return true;
+
+ /* constraints */
+ for (; con; con = con->next) {
+ /* only consider constraint if it is not disabled, and has influence */
+ if (con->flag & CONSTRAINT_DISABLE)
+ continue;
+ if (con->enforce == 0.0f)
+ continue;
+
+ /* some constraints may alter these transforms */
+ switch (con->type) {
+ /* multi-transform constraints */
+ case CONSTRAINT_TYPE_CHILDOF:
+ case CONSTRAINT_TYPE_ARMATURE:
+ return true;
+ case CONSTRAINT_TYPE_TRANSFORM:
+ case CONSTRAINT_TYPE_TRANSLIKE:
+ return true;
+ case CONSTRAINT_TYPE_FOLLOWPATH:
+ return true;
+ case CONSTRAINT_TYPE_KINEMATIC:
+ return true;
+
+ /* single-transform constraints */
+ case CONSTRAINT_TYPE_TRACKTO:
+ if (searchtype == VISUALKEY_ROT)
+ return true;
+ break;
+ case CONSTRAINT_TYPE_DAMPTRACK:
+ if (searchtype == VISUALKEY_ROT)
+ return true;
+ break;
+ case CONSTRAINT_TYPE_ROTLIMIT:
+ if (searchtype == VISUALKEY_ROT)
+ return true;
+ break;
+ case CONSTRAINT_TYPE_LOCLIMIT:
+ if (searchtype == VISUALKEY_LOC)
+ return true;
+ break;
+ case CONSTRAINT_TYPE_SIZELIMIT:
+ if (searchtype == VISUALKEY_SCA)
+ return true;
+ break;
+ case CONSTRAINT_TYPE_DISTLIMIT:
+ if (searchtype == VISUALKEY_LOC)
+ return true;
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ if (searchtype == VISUALKEY_ROT)
+ return true;
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ if (searchtype == VISUALKEY_LOC)
+ return true;
+ break;
+ case CONSTRAINT_TYPE_SIZELIKE:
+ if (searchtype == VISUALKEY_SCA)
+ return true;
+ break;
+ case CONSTRAINT_TYPE_LOCKTRACK:
+ if (searchtype == VISUALKEY_ROT)
+ return true;
+ break;
+ case CONSTRAINT_TYPE_MINMAX:
+ if (searchtype == VISUALKEY_LOC)
+ return true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ /* when some condition is met, this function returns, so that means we've got nothing */
+ return false;
}
/* This helper function extracts the value to use for visual-keyframing
* In the event that it is not possible to perform visual keying, try to fall-back
* to using the default method. Assumes that all data it has been passed is valid.
*/
-static float *visualkey_get_values(Depsgraph *depsgraph, PointerRNA *ptr, PropertyRNA *prop, float *buffer, int buffer_size, int *r_count)
+static float *visualkey_get_values(Depsgraph *depsgraph,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ float *buffer,
+ int buffer_size,
+ int *r_count)
{
- BLI_assert(buffer_size >= 4);
-
- const char *identifier = RNA_property_identifier(prop);
- float tmat[4][4];
- int rotmode;
-
- /* handle for Objects or PoseChannels only
- * - only Location, Rotation or Scale keyframes are supported currently
- * - constraints can be on either Objects or PoseChannels, so we only check if the
- * ptr->type is RNA_Object or RNA_PoseBone, which are the RNA wrapping-info for
- * those structs, allowing us to identify the owner of the data
- * - assume that array_index will be sane
- */
- if (ptr->type == &RNA_Object) {
- Object *ob = (Object *)ptr->data;
- const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
-
- /* Loc code is specific... */
- if (strstr(identifier, "location")) {
- copy_v3_v3(buffer, ob_eval->obmat[3]);
- *r_count = 3;
- return buffer;
- }
-
- copy_m4_m4(tmat, ob_eval->obmat);
- rotmode = ob_eval->rotmode;
- }
- else if (ptr->type == &RNA_PoseBone) {
- Object *ob = (Object *)ptr->id.data;
- bPoseChannel *pchan = (bPoseChannel *)ptr->data;
-
- const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
-
- BKE_armature_mat_pose_to_bone(pchan_eval, pchan_eval->pose_mat, tmat);
- rotmode = pchan_eval->rotmode;
-
- /* Loc code is specific... */
- if (strstr(identifier, "location")) {
- /* only use for non-connected bones */
- if ((pchan->bone->parent == NULL) || !(pchan->bone->flag & BONE_CONNECTED)) {
- copy_v3_v3(buffer, tmat[3]);
- *r_count = 3;
- return buffer;
- }
- }
- }
- else {
- return setting_get_rna_values(depsgraph, ptr, prop, true, buffer, buffer_size, r_count);
- }
-
- /* Rot/Scale code are common! */
- if (strstr(identifier, "rotation_euler")) {
- mat4_to_eulO(buffer, rotmode, tmat);
-
- *r_count = 3;
- return buffer;
- }
- else if (strstr(identifier, "rotation_quaternion")) {
- float mat3[3][3];
-
- copy_m3_m4(mat3, tmat);
- mat3_to_quat_is_ok(buffer, mat3);
-
- *r_count = 4;
- return buffer;
- }
- else if (strstr(identifier, "rotation_axis_angle")) {
- /* w = 0, x,y,z = 1,2,3 */
- mat4_to_axis_angle(buffer + 1, buffer, tmat);
-
- *r_count = 4;
- return buffer;
- }
- else if (strstr(identifier, "scale")) {
- mat4_to_size(buffer, tmat);
-
- *r_count = 3;
- return buffer;
- }
-
- /* as the function hasn't returned yet, read value from system in the default way */
- return setting_get_rna_values(depsgraph, ptr, prop, true, buffer, buffer_size, r_count);
+ BLI_assert(buffer_size >= 4);
+
+ const char *identifier = RNA_property_identifier(prop);
+ float tmat[4][4];
+ int rotmode;
+
+ /* handle for Objects or PoseChannels only
+ * - only Location, Rotation or Scale keyframes are supported currently
+ * - constraints can be on either Objects or PoseChannels, so we only check if the
+ * ptr->type is RNA_Object or RNA_PoseBone, which are the RNA wrapping-info for
+ * those structs, allowing us to identify the owner of the data
+ * - assume that array_index will be sane
+ */
+ if (ptr->type == &RNA_Object) {
+ Object *ob = (Object *)ptr->data;
+ const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+
+ /* Loc code is specific... */
+ if (strstr(identifier, "location")) {
+ copy_v3_v3(buffer, ob_eval->obmat[3]);
+ *r_count = 3;
+ return buffer;
+ }
+
+ copy_m4_m4(tmat, ob_eval->obmat);
+ rotmode = ob_eval->rotmode;
+ }
+ else if (ptr->type == &RNA_PoseBone) {
+ Object *ob = (Object *)ptr->id.data;
+ bPoseChannel *pchan = (bPoseChannel *)ptr->data;
+
+ const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
+
+ BKE_armature_mat_pose_to_bone(pchan_eval, pchan_eval->pose_mat, tmat);
+ rotmode = pchan_eval->rotmode;
+
+ /* Loc code is specific... */
+ if (strstr(identifier, "location")) {
+ /* only use for non-connected bones */
+ if ((pchan->bone->parent == NULL) || !(pchan->bone->flag & BONE_CONNECTED)) {
+ copy_v3_v3(buffer, tmat[3]);
+ *r_count = 3;
+ return buffer;
+ }
+ }
+ }
+ else {
+ return setting_get_rna_values(depsgraph, ptr, prop, true, buffer, buffer_size, r_count);
+ }
+
+ /* Rot/Scale code are common! */
+ if (strstr(identifier, "rotation_euler")) {
+ mat4_to_eulO(buffer, rotmode, tmat);
+
+ *r_count = 3;
+ return buffer;
+ }
+ else if (strstr(identifier, "rotation_quaternion")) {
+ float mat3[3][3];
+
+ copy_m3_m4(mat3, tmat);
+ mat3_to_quat_is_ok(buffer, mat3);
+
+ *r_count = 4;
+ return buffer;
+ }
+ else if (strstr(identifier, "rotation_axis_angle")) {
+ /* w = 0, x,y,z = 1,2,3 */
+ mat4_to_axis_angle(buffer + 1, buffer, tmat);
+
+ *r_count = 4;
+ return buffer;
+ }
+ else if (strstr(identifier, "scale")) {
+ mat4_to_size(buffer, tmat);
+
+ *r_count = 3;
+ return buffer;
+ }
+
+ /* as the function hasn't returned yet, read value from system in the default way */
+ return setting_get_rna_values(depsgraph, ptr, prop, true, buffer, buffer_size, r_count);
}
/* ------------------------- Insert Key API ------------------------- */
/* Retrieve current property values to keyframe, possibly applying NLA correction when necessary. */
-static float *get_keyframe_values(
- Depsgraph *depsgraph, ReportList *reports, PointerRNA ptr, PropertyRNA *prop, int index,
- struct NlaKeyframingContext *nla_context, eInsertKeyFlags flag,
- float *buffer, int buffer_size, int *r_count, bool *r_force_all)
+static float *get_keyframe_values(Depsgraph *depsgraph,
+ ReportList *reports,
+ PointerRNA ptr,
+ PropertyRNA *prop,
+ int index,
+ struct NlaKeyframingContext *nla_context,
+ eInsertKeyFlags flag,
+ float *buffer,
+ int buffer_size,
+ int *r_count,
+ bool *r_force_all)
{
- float *values;
-
- if ( (flag & INSERTKEY_MATRIX) &&
- (visualkey_can_use(&ptr, prop)) )
- {
- /* visual-keying is only available for object and pchan datablocks, as
- * it works by keyframing using a value extracted from the final matrix
- * instead of using the kt system to extract a value.
- */
- values = visualkey_get_values(depsgraph, &ptr, prop, buffer, buffer_size, r_count);
- }
- else {
- /* read value from system */
- values = setting_get_rna_values(depsgraph, &ptr, prop, false, buffer, buffer_size, r_count);
- }
-
- /* adjust the value for NLA factors */
- if (!BKE_animsys_nla_remap_keyframe_values(nla_context, &ptr, prop, values, *r_count, index, r_force_all)) {
- BKE_report(reports, RPT_ERROR, "Could not insert keyframe due to zero NLA influence or base value");
-
- if (values != buffer) {
- MEM_freeN(values);
- }
- return NULL;
- }
-
- return values;
+ float *values;
+
+ if ((flag & INSERTKEY_MATRIX) && (visualkey_can_use(&ptr, prop))) {
+ /* visual-keying is only available for object and pchan datablocks, as
+ * it works by keyframing using a value extracted from the final matrix
+ * instead of using the kt system to extract a value.
+ */
+ values = visualkey_get_values(depsgraph, &ptr, prop, buffer, buffer_size, r_count);
+ }
+ else {
+ /* read value from system */
+ values = setting_get_rna_values(depsgraph, &ptr, prop, false, buffer, buffer_size, r_count);
+ }
+
+ /* adjust the value for NLA factors */
+ if (!BKE_animsys_nla_remap_keyframe_values(
+ nla_context, &ptr, prop, values, *r_count, index, r_force_all)) {
+ BKE_report(
+ reports, RPT_ERROR, "Could not insert keyframe due to zero NLA influence or base value");
+
+ if (values != buffer) {
+ MEM_freeN(values);
+ }
+ return NULL;
+ }
+
+ return values;
}
/* Insert the specified keyframe value into a single F-Curve. */
-static bool insert_keyframe_value(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, FCurve *fcu, float cfra, float curval, eBezTriple_KeyframeType keytype, eInsertKeyFlags flag)
+static bool insert_keyframe_value(ReportList *reports,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ FCurve *fcu,
+ float cfra,
+ float curval,
+ eBezTriple_KeyframeType keytype,
+ eInsertKeyFlags flag)
{
- /* F-Curve not editable? */
- if (fcurve_is_keyframable(fcu) == 0) {
- BKE_reportf(reports, RPT_ERROR,
- "F-Curve with path '%s[%d]' cannot be keyframed, ensure that it is not locked or sampled, "
- "and try removing F-Modifiers",
- fcu->rna_path, fcu->array_index);
- return false;
- }
-
- /* adjust frame on which to add keyframe */
- if ((flag & INSERTKEY_DRIVER) && (fcu->driver)) {
- PathResolvedRNA anim_rna;
-
- if (RNA_path_resolved_create(ptr, prop, fcu->array_index, &anim_rna)) {
- /* for making it easier to add corrective drivers... */
- cfra = evaluate_driver(&anim_rna, fcu->driver, fcu->driver, cfra);
- }
- else {
- cfra = 0.0f;
- }
- }
-
- /* adjust coordinates for cycle aware insertion */
- if (flag & INSERTKEY_CYCLE_AWARE) {
- if (remap_cyclic_keyframe_location(fcu, &cfra, &curval) != FCU_CYCLE_PERFECT) {
- /* inhibit action from insert_vert_fcurve unless it's a perfect cycle */
- flag &= ~INSERTKEY_CYCLE_AWARE;
- }
- }
-
- /* only insert keyframes where they are needed */
- if (flag & INSERTKEY_NEEDED) {
- short insert_mode;
-
- /* check whether this curve really needs a new keyframe */
- insert_mode = new_key_needed(fcu, cfra, curval);
-
- /* only return success if keyframe added */
- if (insert_mode == KEYNEEDED_DONTADD) {
- return false;
- }
-
- /* insert new keyframe at current frame */
- if (insert_vert_fcurve(fcu, cfra, curval, keytype, flag) < 0) {
- return false;
- }
-
- /* delete keyframe immediately before/after newly added */
- switch (insert_mode) {
- case KEYNEEDED_DELPREV:
- delete_fcurve_key(fcu, fcu->totvert - 2, 1);
- break;
- case KEYNEEDED_DELNEXT:
- delete_fcurve_key(fcu, 1, 1);
- break;
- }
-
- return true;
- }
- else {
- /* just insert keyframe */
- return insert_vert_fcurve(fcu, cfra, curval, keytype, flag) >= 0;
- }
+ /* F-Curve not editable? */
+ if (fcurve_is_keyframable(fcu) == 0) {
+ BKE_reportf(
+ reports,
+ RPT_ERROR,
+ "F-Curve with path '%s[%d]' cannot be keyframed, ensure that it is not locked or sampled, "
+ "and try removing F-Modifiers",
+ fcu->rna_path,
+ fcu->array_index);
+ return false;
+ }
+
+ /* adjust frame on which to add keyframe */
+ if ((flag & INSERTKEY_DRIVER) && (fcu->driver)) {
+ PathResolvedRNA anim_rna;
+
+ if (RNA_path_resolved_create(ptr, prop, fcu->array_index, &anim_rna)) {
+ /* for making it easier to add corrective drivers... */
+ cfra = evaluate_driver(&anim_rna, fcu->driver, fcu->driver, cfra);
+ }
+ else {
+ cfra = 0.0f;
+ }
+ }
+
+ /* adjust coordinates for cycle aware insertion */
+ if (flag & INSERTKEY_CYCLE_AWARE) {
+ if (remap_cyclic_keyframe_location(fcu, &cfra, &curval) != FCU_CYCLE_PERFECT) {
+ /* inhibit action from insert_vert_fcurve unless it's a perfect cycle */
+ flag &= ~INSERTKEY_CYCLE_AWARE;
+ }
+ }
+
+ /* only insert keyframes where they are needed */
+ if (flag & INSERTKEY_NEEDED) {
+ short insert_mode;
+
+ /* check whether this curve really needs a new keyframe */
+ insert_mode = new_key_needed(fcu, cfra, curval);
+
+ /* only return success if keyframe added */
+ if (insert_mode == KEYNEEDED_DONTADD) {
+ return false;
+ }
+
+ /* insert new keyframe at current frame */
+ if (insert_vert_fcurve(fcu, cfra, curval, keytype, flag) < 0) {
+ return false;
+ }
+
+ /* delete keyframe immediately before/after newly added */
+ switch (insert_mode) {
+ case KEYNEEDED_DELPREV:
+ delete_fcurve_key(fcu, fcu->totvert - 2, 1);
+ break;
+ case KEYNEEDED_DELNEXT:
+ delete_fcurve_key(fcu, 1, 1);
+ break;
+ }
+
+ return true;
+ }
+ else {
+ /* just insert keyframe */
+ return insert_vert_fcurve(fcu, cfra, curval, keytype, flag) >= 0;
+ }
}
/* Secondary Keyframing API call:
@@ -1105,104 +1157,134 @@ static bool insert_keyframe_value(ReportList *reports, PointerRNA *ptr, Property
* the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
* and extra keyframe filtering.
*/
-bool insert_keyframe_direct(Depsgraph *depsgraph, ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, float cfra, eBezTriple_KeyframeType keytype, struct NlaKeyframingContext *nla_context, eInsertKeyFlags flag)
+bool insert_keyframe_direct(Depsgraph *depsgraph,
+ ReportList *reports,
+ PointerRNA ptr,
+ PropertyRNA *prop,
+ FCurve *fcu,
+ float cfra,
+ eBezTriple_KeyframeType keytype,
+ struct NlaKeyframingContext *nla_context,
+ eInsertKeyFlags flag)
{
- float curval = 0.0f;
-
- /* no F-Curve to add keyframe to? */
- if (fcu == NULL) {
- BKE_report(reports, RPT_ERROR, "No F-Curve to add keyframes to");
- return false;
- }
-
- /* if no property given yet, try to validate from F-Curve info */
- if ((ptr.id.data == NULL) && (ptr.data == NULL)) {
- BKE_report(reports, RPT_ERROR, "No RNA pointer available to retrieve values for keyframing from");
- return false;
- }
- if (prop == NULL) {
- PointerRNA tmp_ptr;
-
- /* try to get property we should be affecting */
- if (RNA_path_resolve_property(&ptr, fcu->rna_path, &tmp_ptr, &prop) == false) {
- /* property not found... */
- const char *idname = (ptr.id.data) ? ((ID *)ptr.id.data)->name : TIP_("<No ID pointer>");
-
- BKE_reportf(reports, RPT_ERROR,
- "Could not insert keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
- idname, fcu->rna_path);
- return false;
- }
- else {
- /* property found, so overwrite 'ptr' to make later code easier */
- ptr = tmp_ptr;
- }
- }
-
- /* update F-Curve flags to ensure proper behavior for property type */
- update_autoflags_fcurve_direct(fcu, prop);
-
- /* Obtain the value to insert. */
- float value_buffer[RNA_MAX_ARRAY_LENGTH];
- int value_count;
- int index = fcu->array_index;
-
- float *values = get_keyframe_values(depsgraph, reports, ptr, prop, index, nla_context, flag,
- value_buffer, RNA_MAX_ARRAY_LENGTH, &value_count, NULL);
-
- if (values == NULL) {
- /* This happens if NLA rejects this insertion. */
- return false;
- }
-
- if (index >= 0 && index < value_count) {
- curval = values[index];
- }
-
- if (values != value_buffer) {
- MEM_freeN(values);
- }
-
- return insert_keyframe_value(reports, &ptr, prop, fcu, cfra, curval, keytype, flag);
+ float curval = 0.0f;
+
+ /* no F-Curve to add keyframe to? */
+ if (fcu == NULL) {
+ BKE_report(reports, RPT_ERROR, "No F-Curve to add keyframes to");
+ return false;
+ }
+
+ /* if no property given yet, try to validate from F-Curve info */
+ if ((ptr.id.data == NULL) && (ptr.data == NULL)) {
+ BKE_report(
+ reports, RPT_ERROR, "No RNA pointer available to retrieve values for keyframing from");
+ return false;
+ }
+ if (prop == NULL) {
+ PointerRNA tmp_ptr;
+
+ /* try to get property we should be affecting */
+ if (RNA_path_resolve_property(&ptr, fcu->rna_path, &tmp_ptr, &prop) == false) {
+ /* property not found... */
+ const char *idname = (ptr.id.data) ? ((ID *)ptr.id.data)->name : TIP_("<No ID pointer>");
+
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Could not insert keyframe, as RNA path is invalid for the given ID (ID = %s, "
+ "path = %s)",
+ idname,
+ fcu->rna_path);
+ return false;
+ }
+ else {
+ /* property found, so overwrite 'ptr' to make later code easier */
+ ptr = tmp_ptr;
+ }
+ }
+
+ /* update F-Curve flags to ensure proper behavior for property type */
+ update_autoflags_fcurve_direct(fcu, prop);
+
+ /* Obtain the value to insert. */
+ float value_buffer[RNA_MAX_ARRAY_LENGTH];
+ int value_count;
+ int index = fcu->array_index;
+
+ float *values = get_keyframe_values(depsgraph,
+ reports,
+ ptr,
+ prop,
+ index,
+ nla_context,
+ flag,
+ value_buffer,
+ RNA_MAX_ARRAY_LENGTH,
+ &value_count,
+ NULL);
+
+ if (values == NULL) {
+ /* This happens if NLA rejects this insertion. */
+ return false;
+ }
+
+ if (index >= 0 && index < value_count) {
+ curval = values[index];
+ }
+
+ if (values != value_buffer) {
+ MEM_freeN(values);
+ }
+
+ return insert_keyframe_value(reports, &ptr, prop, fcu, cfra, curval, keytype, flag);
}
/* Find or create the FCurve based on the given path, and insert the specified value into it. */
-static bool insert_keyframe_fcurve_value(
- Main *bmain, ReportList *reports, PointerRNA *ptr, PropertyRNA *prop,
- bAction *act, const char group[], const char rna_path[], int array_index,
- float cfra, float curval, eBezTriple_KeyframeType keytype, eInsertKeyFlags flag)
+static bool insert_keyframe_fcurve_value(Main *bmain,
+ ReportList *reports,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ bAction *act,
+ const char group[],
+ const char rna_path[],
+ int array_index,
+ float cfra,
+ float curval,
+ eBezTriple_KeyframeType keytype,
+ eInsertKeyFlags flag)
{
- /* make sure the F-Curve exists
- * - if we're replacing keyframes only, DO NOT create new F-Curves if they do not exist yet
- * but still try to get the F-Curve if it exists...
- */
- FCurve *fcu = verify_fcurve(bmain, act, group, ptr, rna_path, array_index, (flag & INSERTKEY_REPLACE) == 0);
-
- /* we may not have a F-Curve when we're replacing only... */
- if (fcu) {
- /* set color mode if the F-Curve is new (i.e. without any keyframes) */
- if ((fcu->totvert == 0) && (flag & INSERTKEY_XYZ2RGB)) {
- /* for Loc/Rot/Scale and also Color F-Curves, the color of the F-Curve in the Graph Editor,
- * is determined by the array index for the F-Curve
- */
- PropertySubType prop_subtype = RNA_property_subtype(prop);
- if (ELEM(prop_subtype, PROP_TRANSLATION, PROP_XYZ, PROP_EULER, PROP_COLOR, PROP_COORDS)) {
- fcu->color_mode = FCURVE_COLOR_AUTO_RGB;
- }
- else if (ELEM(prop_subtype, PROP_QUATERNION)) {
- fcu->color_mode = FCURVE_COLOR_AUTO_YRGB;
- }
- }
-
- /* update F-Curve flags to ensure proper behavior for property type */
- update_autoflags_fcurve_direct(fcu, prop);
-
- /* insert keyframe */
- return insert_keyframe_value(reports, ptr, prop, fcu, cfra, curval, keytype, flag);
- }
- else {
- return false;
- }
+ /* make sure the F-Curve exists
+ * - if we're replacing keyframes only, DO NOT create new F-Curves if they do not exist yet
+ * but still try to get the F-Curve if it exists...
+ */
+ FCurve *fcu = verify_fcurve(
+ bmain, act, group, ptr, rna_path, array_index, (flag & INSERTKEY_REPLACE) == 0);
+
+ /* we may not have a F-Curve when we're replacing only... */
+ if (fcu) {
+ /* set color mode if the F-Curve is new (i.e. without any keyframes) */
+ if ((fcu->totvert == 0) && (flag & INSERTKEY_XYZ2RGB)) {
+ /* for Loc/Rot/Scale and also Color F-Curves, the color of the F-Curve in the Graph Editor,
+ * is determined by the array index for the F-Curve
+ */
+ PropertySubType prop_subtype = RNA_property_subtype(prop);
+ if (ELEM(prop_subtype, PROP_TRANSLATION, PROP_XYZ, PROP_EULER, PROP_COLOR, PROP_COORDS)) {
+ fcu->color_mode = FCURVE_COLOR_AUTO_RGB;
+ }
+ else if (ELEM(prop_subtype, PROP_QUATERNION)) {
+ fcu->color_mode = FCURVE_COLOR_AUTO_YRGB;
+ }
+ }
+
+ /* update F-Curve flags to ensure proper behavior for property type */
+ update_autoflags_fcurve_direct(fcu, prop);
+
+ /* insert keyframe */
+ return insert_keyframe_value(reports, ptr, prop, fcu, cfra, curval, keytype, flag);
+ }
+ else {
+ return false;
+ }
}
/* Main Keyframing API call:
@@ -1214,119 +1296,188 @@ static bool insert_keyframe_fcurve_value(
*
* index of -1 keys all array indices
*/
-short insert_keyframe(
- Main *bmain, Depsgraph *depsgraph, 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)
+short insert_keyframe(Main *bmain,
+ Depsgraph *depsgraph,
+ 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;
- AnimData *adt;
- ListBase tmp_nla_cache = {NULL, NULL};
- NlaKeyframingContext *nla_context = NULL;
- int ret = 0;
-
- /* validate pointer first - exit if failure */
- if (id == NULL) {
- BKE_reportf(reports, RPT_ERROR, "No ID block to insert keyframe in (path = %s)", rna_path);
- return 0;
- }
-
- RNA_id_pointer_create(id, &id_ptr);
- if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
- BKE_reportf(reports, RPT_ERROR,
- "Could not insert keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
- (id) ? id->name : TIP_("<Missing ID block>"), rna_path);
- return 0;
- }
-
- /* 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);
-
- if (act == NULL) {
- BKE_reportf(reports, RPT_ERROR,
- "Could not insert keyframe, as this type does not support animation data (ID = %s, path = %s)",
- id->name, rna_path);
- return 0;
- }
- }
-
- /* apply NLA-mapping to frame to use (if applicable) */
- adt = BKE_animdata_from_id(id);
-
- if (adt && adt->action == act) {
- /* Get NLA context for value remapping. */
- nla_context = BKE_animsys_get_nla_keyframing_context(nla_cache ? nla_cache : &tmp_nla_cache, depsgraph, &id_ptr, adt, cfra);
-
- /* Apply NLA-mapping to frame. */
- cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
- }
-
- /* Obtain values to insert. */
- float value_buffer[RNA_MAX_ARRAY_LENGTH];
- int value_count;
- bool force_all;
-
- float *values = get_keyframe_values(depsgraph, reports, ptr, prop, array_index, nla_context, flag,
- value_buffer, RNA_MAX_ARRAY_LENGTH, &value_count, &force_all);
-
- if (values != NULL) {
- /* Key the entire array. */
- if (array_index == -1 || force_all) {
- /* In force mode, if any of the curves succeeds, drop the replace mode and restart. */
- if (force_all && (flag & INSERTKEY_REPLACE) != 0) {
- int exclude = -1;
-
- for (array_index = 0; array_index < value_count; array_index++) {
- if (insert_keyframe_fcurve_value(bmain, reports, &ptr, prop, act, group, rna_path, array_index, cfra, values[array_index], keytype, flag)) {
- ret++;
- exclude = array_index;
- break;
- }
- }
-
- if (exclude != -1) {
- flag &= ~INSERTKEY_REPLACE;
-
- for (array_index = 0; array_index < value_count; array_index++) {
- if (array_index != exclude) {
- ret += insert_keyframe_fcurve_value(bmain, reports, &ptr, prop, act, group, rna_path, array_index, cfra, values[array_index], keytype, flag);
- }
- }
- }
- }
- /* Simply insert all channels. */
- else {
- for (array_index = 0; array_index < value_count; array_index++) {
- ret += insert_keyframe_fcurve_value(bmain, reports, &ptr, prop, act, group, rna_path, array_index, cfra, values[array_index], keytype, flag);
- }
- }
- }
- /* Key a single index. */
- else {
- if (array_index >= 0 && array_index < value_count) {
- ret += insert_keyframe_fcurve_value(bmain, reports, &ptr, prop, act, group, rna_path, array_index, cfra, values[array_index], keytype, flag);
- }
- }
- }
-
- if (values != value_buffer) {
- MEM_freeN(values);
- }
-
- BKE_animsys_free_nla_keyframing_context_cache(&tmp_nla_cache);
-
- if (ret) {
- if (act != NULL) {
- DEG_id_tag_update(&act->id, ID_RECALC_ANIMATION_NO_FLUSH);
- }
- if (adt != NULL && adt->action != NULL && adt->action != act) {
- DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
- }
- }
-
- return ret;
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop = NULL;
+ AnimData *adt;
+ ListBase tmp_nla_cache = {NULL, NULL};
+ NlaKeyframingContext *nla_context = NULL;
+ int ret = 0;
+
+ /* validate pointer first - exit if failure */
+ if (id == NULL) {
+ BKE_reportf(reports, RPT_ERROR, "No ID block to insert keyframe in (path = %s)", rna_path);
+ return 0;
+ }
+
+ RNA_id_pointer_create(id, &id_ptr);
+ if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
+ BKE_reportf(
+ reports,
+ RPT_ERROR,
+ "Could not insert keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
+ (id) ? id->name : TIP_("<Missing ID block>"),
+ rna_path);
+ return 0;
+ }
+
+ /* 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);
+
+ if (act == NULL) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Could not insert keyframe, as this type does not support animation data (ID = "
+ "%s, path = %s)",
+ id->name,
+ rna_path);
+ return 0;
+ }
+ }
+
+ /* apply NLA-mapping to frame to use (if applicable) */
+ adt = BKE_animdata_from_id(id);
+
+ if (adt && adt->action == act) {
+ /* Get NLA context for value remapping. */
+ nla_context = BKE_animsys_get_nla_keyframing_context(
+ nla_cache ? nla_cache : &tmp_nla_cache, depsgraph, &id_ptr, adt, cfra);
+
+ /* Apply NLA-mapping to frame. */
+ cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
+ }
+
+ /* Obtain values to insert. */
+ float value_buffer[RNA_MAX_ARRAY_LENGTH];
+ int value_count;
+ bool force_all;
+
+ float *values = get_keyframe_values(depsgraph,
+ reports,
+ ptr,
+ prop,
+ array_index,
+ nla_context,
+ flag,
+ value_buffer,
+ RNA_MAX_ARRAY_LENGTH,
+ &value_count,
+ &force_all);
+
+ if (values != NULL) {
+ /* Key the entire array. */
+ if (array_index == -1 || force_all) {
+ /* In force mode, if any of the curves succeeds, drop the replace mode and restart. */
+ if (force_all && (flag & INSERTKEY_REPLACE) != 0) {
+ int exclude = -1;
+
+ for (array_index = 0; array_index < value_count; array_index++) {
+ if (insert_keyframe_fcurve_value(bmain,
+ reports,
+ &ptr,
+ prop,
+ act,
+ group,
+ rna_path,
+ array_index,
+ cfra,
+ values[array_index],
+ keytype,
+ flag)) {
+ ret++;
+ exclude = array_index;
+ break;
+ }
+ }
+
+ if (exclude != -1) {
+ flag &= ~INSERTKEY_REPLACE;
+
+ for (array_index = 0; array_index < value_count; array_index++) {
+ if (array_index != exclude) {
+ ret += insert_keyframe_fcurve_value(bmain,
+ reports,
+ &ptr,
+ prop,
+ act,
+ group,
+ rna_path,
+ array_index,
+ cfra,
+ values[array_index],
+ keytype,
+ flag);
+ }
+ }
+ }
+ }
+ /* Simply insert all channels. */
+ else {
+ for (array_index = 0; array_index < value_count; array_index++) {
+ ret += insert_keyframe_fcurve_value(bmain,
+ reports,
+ &ptr,
+ prop,
+ act,
+ group,
+ rna_path,
+ array_index,
+ cfra,
+ values[array_index],
+ keytype,
+ flag);
+ }
+ }
+ }
+ /* Key a single index. */
+ else {
+ if (array_index >= 0 && array_index < value_count) {
+ ret += insert_keyframe_fcurve_value(bmain,
+ reports,
+ &ptr,
+ prop,
+ act,
+ group,
+ rna_path,
+ array_index,
+ cfra,
+ values[array_index],
+ keytype,
+ flag);
+ }
+ }
+ }
+
+ if (values != value_buffer) {
+ MEM_freeN(values);
+ }
+
+ BKE_animsys_free_nla_keyframing_context_cache(&tmp_nla_cache);
+
+ if (ret) {
+ if (act != NULL) {
+ DEG_id_tag_update(&act->id, ID_RECALC_ANIMATION_NO_FLUSH);
+ }
+ if (adt != NULL && adt->action != NULL && adt->action != act) {
+ DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
+ }
+ }
+
+ return ret;
}
/* ************************************************** */
@@ -1340,128 +1491,138 @@ short insert_keyframe(
* the keyframe deletion. These include the quick refresh options.
*/
-
-
/**
* \note caller needs to run #BKE_nla_tweakedit_remap to get NLA relative frame.
* caller should also check #BKE_fcurve_is_protected before keying.
*/
static bool delete_keyframe_fcurve(AnimData *adt, FCurve *fcu, float cfra)
{
- bool found;
- int i;
-
- /* try to find index of beztriple to get rid of */
- i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
- if (found) {
- /* delete the key at the index (will sanity check + do recalc afterwards) */
- delete_fcurve_key(fcu, i, 1);
-
- /* Only delete curve too if it won't be doing anything anymore */
- if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0))
- ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
-
- /* return success */
- return true;
- }
- return false;
+ bool found;
+ int i;
+
+ /* try to find index of beztriple to get rid of */
+ i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
+ if (found) {
+ /* delete the key at the index (will sanity check + do recalc afterwards) */
+ delete_fcurve_key(fcu, i, 1);
+
+ /* Only delete curve too if it won't be doing anything anymore */
+ if ((fcu->totvert == 0) &&
+ (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0))
+ ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
+
+ /* return success */
+ return true;
+ }
+ return false;
}
static void deg_tag_after_keyframe_delete(Main *bmain, ID *id, AnimData *adt)
{
- if (adt->action == NULL) {
- /* In the case last f-curve wes removed need to inform dependency graph
- * about relations update, since it needs to get rid of animation operation
- * for this datablock. */
- DEG_id_tag_update_ex(bmain, id, ID_RECALC_ANIMATION_NO_FLUSH);
- DEG_relations_tag_update(bmain);
- }
- else {
- DEG_id_tag_update_ex(bmain, &adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
- }
+ if (adt->action == NULL) {
+ /* In the case last f-curve wes removed need to inform dependency graph
+ * about relations update, since it needs to get rid of animation operation
+ * for this datablock. */
+ DEG_id_tag_update_ex(bmain, id, ID_RECALC_ANIMATION_NO_FLUSH);
+ DEG_relations_tag_update(bmain);
+ }
+ else {
+ DEG_id_tag_update_ex(bmain, &adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
+ }
}
-short delete_keyframe(Main *bmain, ReportList *reports, ID *id, bAction *act,
- const char group[], const char rna_path[], int array_index, float cfra,
+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))
{
- AnimData *adt = BKE_animdata_from_id(id);
- PointerRNA id_ptr, ptr;
- PropertyRNA *prop;
- int array_index_max = array_index + 1;
- int ret = 0;
-
- /* sanity checks */
- if (ELEM(NULL, id, adt)) {
- BKE_report(reports, RPT_ERROR, "No ID block and/or AnimData to delete keyframe from");
- return 0;
- }
-
- /* validate pointer first - exit if failure */
- RNA_id_pointer_create(id, &id_ptr);
- if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
- BKE_reportf(reports, RPT_ERROR,
- "Could not delete keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
- id->name, rna_path);
- return 0;
- }
-
- /* get F-Curve
- * Note: here is one of the places where we don't want new Action + F-Curve added!
- * so 'add' var must be 0
- */
- if (act == NULL) {
- /* if no action is provided, use the default one attached to this ID-block
- * - if it doesn't exist, then we're out of options...
- */
- if (adt->action) {
- act = adt->action;
-
- /* apply NLA-mapping to frame to use (if applicable) */
- cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "No action to delete keyframes from for ID = %s", id->name);
- return 0;
- }
- }
-
- /* key entire array convenience method */
- if (array_index == -1) {
- array_index = 0;
- array_index_max = RNA_property_array_length(&ptr, prop);
-
- /* for single properties, increase max_index so that the property itself gets included,
- * but don't do this for standard arrays since that can cause corruption issues
- * (extra unused curves)
- */
- if (array_index_max == array_index)
- array_index_max++;
- }
-
- /* 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);
-
- /* check if F-Curve exists and/or whether it can be edited */
- if (fcu == NULL)
- continue;
-
- if (BKE_fcurve_is_protected(fcu)) {
- BKE_reportf(reports, RPT_WARNING,
- "Not deleting keyframe for locked F-Curve '%s' for %s '%s'",
- fcu->rna_path, BKE_idcode_to_name(GS(id->name)), id->name + 2);
- continue;
- }
-
- ret += delete_keyframe_fcurve(adt, fcu, cfra);
-
- }
- if (ret) {
- deg_tag_after_keyframe_delete(bmain, id, adt);
- }
- /* return success/failure */
- return ret;
+ AnimData *adt = BKE_animdata_from_id(id);
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ int array_index_max = array_index + 1;
+ int ret = 0;
+
+ /* sanity checks */
+ if (ELEM(NULL, id, adt)) {
+ BKE_report(reports, RPT_ERROR, "No ID block and/or AnimData to delete keyframe from");
+ return 0;
+ }
+
+ /* validate pointer first - exit if failure */
+ RNA_id_pointer_create(id, &id_ptr);
+ if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
+ BKE_reportf(
+ reports,
+ RPT_ERROR,
+ "Could not delete keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
+ id->name,
+ rna_path);
+ return 0;
+ }
+
+ /* get F-Curve
+ * Note: here is one of the places where we don't want new Action + F-Curve added!
+ * so 'add' var must be 0
+ */
+ if (act == NULL) {
+ /* if no action is provided, use the default one attached to this ID-block
+ * - if it doesn't exist, then we're out of options...
+ */
+ if (adt->action) {
+ act = adt->action;
+
+ /* apply NLA-mapping to frame to use (if applicable) */
+ cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
+ }
+ else {
+ BKE_reportf(reports, RPT_ERROR, "No action to delete keyframes from for ID = %s", id->name);
+ return 0;
+ }
+ }
+
+ /* key entire array convenience method */
+ if (array_index == -1) {
+ array_index = 0;
+ array_index_max = RNA_property_array_length(&ptr, prop);
+
+ /* for single properties, increase max_index so that the property itself gets included,
+ * but don't do this for standard arrays since that can cause corruption issues
+ * (extra unused curves)
+ */
+ if (array_index_max == array_index)
+ array_index_max++;
+ }
+
+ /* 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);
+
+ /* check if F-Curve exists and/or whether it can be edited */
+ if (fcu == NULL)
+ continue;
+
+ if (BKE_fcurve_is_protected(fcu)) {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Not deleting keyframe for locked F-Curve '%s' for %s '%s'",
+ fcu->rna_path,
+ BKE_idcode_to_name(GS(id->name)),
+ id->name + 2);
+ continue;
+ }
+
+ ret += delete_keyframe_fcurve(adt, fcu, cfra);
+ }
+ if (ret) {
+ deg_tag_after_keyframe_delete(bmain, id, adt);
+ }
+ /* return success/failure */
+ return ret;
}
/* ************************************************** */
@@ -1474,86 +1635,97 @@ short delete_keyframe(Main *bmain, ReportList *reports, ID *id, bAction *act,
* The flag argument is used for special settings that alter the behavior of
* the keyframe deletion. These include the quick refresh options.
*/
-static short clear_keyframe(Main *bmain, ReportList *reports, ID *id, bAction *act,
- const char group[], const char rna_path[], int array_index,
+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))
{
- AnimData *adt = BKE_animdata_from_id(id);
- PointerRNA id_ptr, ptr;
- PropertyRNA *prop;
- int array_index_max = array_index + 1;
- int ret = 0;
-
- /* sanity checks */
- if (ELEM(NULL, id, adt)) {
- BKE_report(reports, RPT_ERROR, "No ID block and/or AnimData to delete keyframe from");
- return 0;
- }
-
- /* validate pointer first - exit if failure */
- RNA_id_pointer_create(id, &id_ptr);
- if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
- BKE_reportf(reports, RPT_ERROR,
- "Could not clear keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
- id->name, rna_path);
- return 0;
- }
-
- /* get F-Curve
- * Note: here is one of the places where we don't want new Action + F-Curve added!
- * so 'add' var must be 0
- */
- if (act == NULL) {
- /* if no action is provided, use the default one attached to this ID-block
- * - if it doesn't exist, then we're out of options...
- */
- if (adt->action) {
- act = adt->action;
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "No action to delete keyframes from for ID = %s", id->name);
- return 0;
- }
- }
-
- /* key entire array convenience method */
- if (array_index == -1) {
- array_index = 0;
- array_index_max = RNA_property_array_length(&ptr, prop);
-
- /* for single properties, increase max_index so that the property itself gets included,
- * but don't do this for standard arrays since that can cause corruption issues
- * (extra unused curves)
- */
- if (array_index_max == array_index)
- array_index_max++;
- }
-
- /* 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);
-
- /* check if F-Curve exists and/or whether it can be edited */
- if (fcu == NULL)
- continue;
-
- if (BKE_fcurve_is_protected(fcu)) {
- BKE_reportf(reports, RPT_WARNING,
- "Not clearing all keyframes from locked F-Curve '%s' for %s '%s'",
- fcu->rna_path, BKE_idcode_to_name(GS(id->name)), id->name + 2);
- continue;
- }
-
- ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
-
- /* return success */
- ret++;
- }
- if (ret) {
- deg_tag_after_keyframe_delete(bmain, id, adt);
- }
- /* return success/failure */
- return ret;
+ AnimData *adt = BKE_animdata_from_id(id);
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ int array_index_max = array_index + 1;
+ int ret = 0;
+
+ /* sanity checks */
+ if (ELEM(NULL, id, adt)) {
+ BKE_report(reports, RPT_ERROR, "No ID block and/or AnimData to delete keyframe from");
+ return 0;
+ }
+
+ /* validate pointer first - exit if failure */
+ RNA_id_pointer_create(id, &id_ptr);
+ if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
+ BKE_reportf(
+ reports,
+ RPT_ERROR,
+ "Could not clear keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
+ id->name,
+ rna_path);
+ return 0;
+ }
+
+ /* get F-Curve
+ * Note: here is one of the places where we don't want new Action + F-Curve added!
+ * so 'add' var must be 0
+ */
+ if (act == NULL) {
+ /* if no action is provided, use the default one attached to this ID-block
+ * - if it doesn't exist, then we're out of options...
+ */
+ if (adt->action) {
+ act = adt->action;
+ }
+ else {
+ BKE_reportf(reports, RPT_ERROR, "No action to delete keyframes from for ID = %s", id->name);
+ return 0;
+ }
+ }
+
+ /* key entire array convenience method */
+ if (array_index == -1) {
+ array_index = 0;
+ array_index_max = RNA_property_array_length(&ptr, prop);
+
+ /* for single properties, increase max_index so that the property itself gets included,
+ * but don't do this for standard arrays since that can cause corruption issues
+ * (extra unused curves)
+ */
+ if (array_index_max == array_index)
+ array_index_max++;
+ }
+
+ /* 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);
+
+ /* check if F-Curve exists and/or whether it can be edited */
+ if (fcu == NULL)
+ continue;
+
+ if (BKE_fcurve_is_protected(fcu)) {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Not clearing all keyframes from locked F-Curve '%s' for %s '%s'",
+ fcu->rna_path,
+ BKE_idcode_to_name(GS(id->name)),
+ id->name + 2);
+ continue;
+ }
+
+ ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
+
+ /* return success */
+ ret++;
+ }
+ if (ret) {
+ deg_tag_after_keyframe_delete(bmain, id, adt);
+ }
+ /* return success/failure */
+ return ret;
}
/* ******************************************* */
@@ -1561,8 +1733,8 @@ static short clear_keyframe(Main *bmain, ReportList *reports, ID *id, bAction *a
/* mode for commonkey_modifykey */
enum {
- COMMONKEY_MODE_INSERT = 0,
- COMMONKEY_MODE_DELETE,
+ COMMONKEY_MODE_INSERT = 0,
+ COMMONKEY_MODE_DELETE,
} /*eCommonModifyKey_Modes*/;
/* Polling callback for use with ANIM_*_keyframe() operators
@@ -1571,128 +1743,144 @@ enum {
*/
static bool modify_key_op_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- Scene *scene = CTX_data_scene(C);
+ ScrArea *sa = CTX_wm_area(C);
+ Scene *scene = CTX_data_scene(C);
- /* if no area or active scene */
- if (ELEM(NULL, sa, scene))
- return false;
+ /* if no area or active scene */
+ if (ELEM(NULL, sa, scene))
+ return false;
- /* should be fine */
- return true;
+ /* should be fine */
+ return true;
}
/* Insert Key Operator ------------------------ */
static int insert_key_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- bool ob_edit_mode = false;
-
- float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
- short success;
-
- KeyingSet *ks = keyingset_get_from_op_with_error(op, op->type->prop, scene);
- if (ks == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- /* exit the edit mode to make sure that those object data properties that have been
- * updated since the last switching to the edit mode will be keyframed correctly
- */
- if (obedit && ANIM_keyingset_find_id(ks, (ID *)obedit->data)) {
- ED_object_mode_toggle(C, OB_MODE_EDIT);
- ob_edit_mode = true;
- }
-
- /* try to insert keyframes for the channels specified by KeyingSet */
- success = 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);
-
- /* restore the edit mode if necessary */
- if (ob_edit_mode) {
- ED_object_mode_toggle(C, OB_MODE_EDIT);
- }
-
- /* report failure or do updates? */
- if (success == MODIFYKEY_INVALID_CONTEXT) {
- BKE_report(op->reports, RPT_ERROR, "No suitable context info for active keying set");
- return OPERATOR_CANCELLED;
- }
- else if (success) {
- /* 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, ks->name);
-
- /* send notifiers that keyframes have been changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
- }
- else
- BKE_report(op->reports, RPT_WARNING, "Keying set failed to insert any keyframes");
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ bool ob_edit_mode = false;
+
+ float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
+ short success;
+
+ KeyingSet *ks = keyingset_get_from_op_with_error(op, op->type->prop, scene);
+ if (ks == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* exit the edit mode to make sure that those object data properties that have been
+ * updated since the last switching to the edit mode will be keyframed correctly
+ */
+ if (obedit && ANIM_keyingset_find_id(ks, (ID *)obedit->data)) {
+ ED_object_mode_toggle(C, OB_MODE_EDIT);
+ ob_edit_mode = true;
+ }
+
+ /* try to insert keyframes for the channels specified by KeyingSet */
+ success = 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);
+
+ /* restore the edit mode if necessary */
+ if (ob_edit_mode) {
+ ED_object_mode_toggle(C, OB_MODE_EDIT);
+ }
+
+ /* report failure or do updates? */
+ if (success == MODIFYKEY_INVALID_CONTEXT) {
+ BKE_report(op->reports, RPT_ERROR, "No suitable context info for active keying set");
+ return OPERATOR_CANCELLED;
+ }
+ else if (success) {
+ /* 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,
+ ks->name);
+
+ /* send notifiers that keyframes have been changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
+ }
+ else
+ BKE_report(op->reports, RPT_WARNING, "Keying set failed to insert any keyframes");
+
+ return OPERATOR_FINISHED;
}
void ANIM_OT_keyframe_insert(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Insert Keyframe";
- ot->idname = "ANIM_OT_keyframe_insert";
- ot->description = "Insert keyframes on the current frame for all properties in the specified Keying Set";
-
- /* callbacks */
- ot->exec = insert_key_exec;
- ot->poll = modify_key_op_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* keyingset to use (dynamic enum) */
- prop = RNA_def_enum(ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
- RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf);
- RNA_def_property_flag(prop, PROP_HIDDEN);
- ot->prop = prop;
-
- /* confirm whether a keyframe was added by showing a popup
- * - by default, this is enabled, since this operator is assumed to be called independently
- */
- prop = RNA_def_boolean(ot->srna, "confirm_success", 1, "Confirm Successful Insert",
- "Show a popup when the keyframes get successfully added");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Insert Keyframe";
+ ot->idname = "ANIM_OT_keyframe_insert";
+ ot->description =
+ "Insert keyframes on the current frame for all properties in the specified Keying Set";
+
+ /* callbacks */
+ ot->exec = insert_key_exec;
+ ot->poll = modify_key_op_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* keyingset to use (dynamic enum) */
+ prop = RNA_def_enum(
+ ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
+ RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ ot->prop = prop;
+
+ /* confirm whether a keyframe was added by showing a popup
+ * - by default, this is enabled, since this operator is assumed to be called independently
+ */
+ prop = RNA_def_boolean(ot->srna,
+ "confirm_success",
+ 1,
+ "Confirm Successful Insert",
+ "Show a popup when the keyframes get successfully added");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/* Clone of 'ANIM_OT_keyframe_insert' which uses a name for the keying set instead of an enum. */
void ANIM_OT_keyframe_insert_by_name(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Insert Keyframe (by name)";
- ot->idname = "ANIM_OT_keyframe_insert_by_name";
- ot->description = "Alternate access to 'Insert Keyframe' for keymaps to use";
-
- /* callbacks */
- ot->exec = insert_key_exec;
- ot->poll = modify_key_op_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* keyingset to use (idname) */
- prop = RNA_def_string_file_path(ot->srna, "type", "Type", MAX_ID_NAME - 2, "", "");
- RNA_def_property_flag(prop, PROP_HIDDEN);
- ot->prop = prop;
-
- /* confirm whether a keyframe was added by showing a popup
- * - by default, this is enabled, since this operator is assumed to be called independently
- */
- prop = RNA_def_boolean(ot->srna, "confirm_success", 1, "Confirm Successful Insert",
- "Show a popup when the keyframes get successfully added");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Insert Keyframe (by name)";
+ ot->idname = "ANIM_OT_keyframe_insert_by_name";
+ ot->description = "Alternate access to 'Insert Keyframe' for keymaps to use";
+
+ /* callbacks */
+ ot->exec = insert_key_exec;
+ ot->poll = modify_key_op_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* keyingset to use (idname) */
+ prop = RNA_def_string_file_path(ot->srna, "type", "Type", MAX_ID_NAME - 2, "", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ ot->prop = prop;
+
+ /* confirm whether a keyframe was added by showing a popup
+ * - by default, this is enabled, since this operator is assumed to be called independently
+ */
+ prop = RNA_def_boolean(ot->srna,
+ "confirm_success",
+ 1,
+ "Confirm Successful Insert",
+ "Show a popup when the keyframes get successfully added");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/* Insert Key Operator (With Menu) ------------------------ */
@@ -1702,190 +1890,207 @@ void ANIM_OT_keyframe_insert_by_name(wmOperatorType *ot)
static int insert_key_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Scene *scene = CTX_data_scene(C);
-
- /* if prompting or no active Keying Set, show the menu */
- if ((scene->active_keyingset == 0) || RNA_boolean_get(op->ptr, "always_prompt")) {
- uiPopupMenu *pup;
- uiLayout *layout;
-
- /* call the menu, which will call this operator again, hence the canceled */
- pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
- uiItemsEnumO(layout, "ANIM_OT_keyframe_insert_menu", "type");
- UI_popup_menu_end(C, pup);
-
- return OPERATOR_INTERFACE;
- }
- else {
- /* just call the exec() on the active keyingset */
- RNA_enum_set(op->ptr, "type", 0);
- RNA_boolean_set(op->ptr, "confirm_success", true);
-
- return op->type->exec(C, op);
- }
+ Scene *scene = CTX_data_scene(C);
+
+ /* if prompting or no active Keying Set, show the menu */
+ if ((scene->active_keyingset == 0) || RNA_boolean_get(op->ptr, "always_prompt")) {
+ uiPopupMenu *pup;
+ uiLayout *layout;
+
+ /* call the menu, which will call this operator again, hence the canceled */
+ pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ uiItemsEnumO(layout, "ANIM_OT_keyframe_insert_menu", "type");
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
+ }
+ else {
+ /* just call the exec() on the active keyingset */
+ RNA_enum_set(op->ptr, "type", 0);
+ RNA_boolean_set(op->ptr, "confirm_success", true);
+
+ return op->type->exec(C, op);
+ }
}
void ANIM_OT_keyframe_insert_menu(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Insert Keyframe Menu";
- ot->idname = "ANIM_OT_keyframe_insert_menu";
- ot->description = "Insert Keyframes for specified Keying Set, with menu of available Keying Sets if undefined";
-
- /* callbacks */
- ot->invoke = insert_key_menu_invoke;
- ot->exec = insert_key_exec;
- ot->poll = ED_operator_areaactive;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* keyingset to use (dynamic enum) */
- prop = RNA_def_enum(ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
- RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf);
- RNA_def_property_flag(prop, PROP_HIDDEN);
- ot->prop = prop;
-
- /* confirm whether a keyframe was added by showing a popup
- * - by default, this is disabled so that if a menu is shown, this doesn't come up too
- */
- // XXX should this just be always on?
- prop = RNA_def_boolean(ot->srna, "confirm_success", 0, "Confirm Successful Insert",
- "Show a popup when the keyframes get successfully added");
- RNA_def_property_flag(prop, PROP_HIDDEN);
-
- /* whether the menu should always be shown
- * - by default, the menu should only be shown when there is no active Keying Set (2.5 behavior),
- * although in some cases it might be useful to always shown (pre 2.5 behavior)
- */
- prop = RNA_def_boolean(ot->srna, "always_prompt", 0, "Always Show Menu", "");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Insert Keyframe Menu";
+ ot->idname = "ANIM_OT_keyframe_insert_menu";
+ ot->description =
+ "Insert Keyframes for specified Keying Set, with menu of available Keying Sets if undefined";
+
+ /* callbacks */
+ ot->invoke = insert_key_menu_invoke;
+ ot->exec = insert_key_exec;
+ ot->poll = ED_operator_areaactive;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* keyingset to use (dynamic enum) */
+ prop = RNA_def_enum(
+ ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
+ RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ ot->prop = prop;
+
+ /* confirm whether a keyframe was added by showing a popup
+ * - by default, this is disabled so that if a menu is shown, this doesn't come up too
+ */
+ // XXX should this just be always on?
+ prop = RNA_def_boolean(ot->srna,
+ "confirm_success",
+ 0,
+ "Confirm Successful Insert",
+ "Show a popup when the keyframes get successfully added");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ /* whether the menu should always be shown
+ * - by default, the menu should only be shown when there is no active Keying Set (2.5 behavior),
+ * although in some cases it might be useful to always shown (pre 2.5 behavior)
+ */
+ prop = RNA_def_boolean(ot->srna, "always_prompt", 0, "Always Show Menu", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/* Delete Key Operator ------------------------ */
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;
-
- KeyingSet *ks = keyingset_get_from_op_with_error(op, op->type->prop, scene);
- if (ks == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- const int prop_type = RNA_property_type(op->type->prop);
- if (prop_type == PROP_ENUM) {
- int type = RNA_property_enum_get(op->ptr, op->type->prop);
- ks = ANIM_keyingset_get_from_enum_type(scene, type);
- if (ks == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active keying set");
- return OPERATOR_CANCELLED;
- }
- }
- else if (prop_type == PROP_STRING) {
- char type_id[MAX_ID_NAME - 2];
- RNA_property_string_get(op->ptr, op->type->prop, type_id);
- ks = ANIM_keyingset_get_from_idname(scene, type_id);
-
- if (ks == NULL) {
- BKE_reportf(op->reports, RPT_ERROR, "No active keying set '%s' not found", type_id);
- return OPERATOR_CANCELLED;
- }
- }
- else {
- BLI_assert(0);
- }
-
- /* report failure */
- if (ks == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
- return OPERATOR_CANCELLED;
- }
-
- /* try to delete keyframes for the channels specified by KeyingSet */
- success = 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);
-
- /* report failure or do updates? */
- if (success == MODIFYKEY_INVALID_CONTEXT) {
- BKE_report(op->reports, RPT_ERROR, "No suitable context info for active keying set");
- return OPERATOR_CANCELLED;
- }
- else if (success) {
- /* 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, ks->name);
-
- /* send notifiers that keyframes have been changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
- }
- else
- BKE_report(op->reports, RPT_WARNING, "Keying set failed to remove any keyframes");
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
+ short success;
+
+ KeyingSet *ks = keyingset_get_from_op_with_error(op, op->type->prop, scene);
+ if (ks == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ const int prop_type = RNA_property_type(op->type->prop);
+ if (prop_type == PROP_ENUM) {
+ int type = RNA_property_enum_get(op->ptr, op->type->prop);
+ ks = ANIM_keyingset_get_from_enum_type(scene, type);
+ if (ks == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active keying set");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else if (prop_type == PROP_STRING) {
+ char type_id[MAX_ID_NAME - 2];
+ RNA_property_string_get(op->ptr, op->type->prop, type_id);
+ ks = ANIM_keyingset_get_from_idname(scene, type_id);
+
+ if (ks == NULL) {
+ BKE_reportf(op->reports, RPT_ERROR, "No active keying set '%s' not found", type_id);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ /* report failure */
+ if (ks == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* try to delete keyframes for the channels specified by KeyingSet */
+ success = 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);
+
+ /* report failure or do updates? */
+ if (success == MODIFYKEY_INVALID_CONTEXT) {
+ BKE_report(op->reports, RPT_ERROR, "No suitable context info for active keying set");
+ return OPERATOR_CANCELLED;
+ }
+ else if (success) {
+ /* 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,
+ ks->name);
+
+ /* send notifiers that keyframes have been changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
+ }
+ else
+ BKE_report(op->reports, RPT_WARNING, "Keying set failed to remove any keyframes");
+
+ return OPERATOR_FINISHED;
}
void ANIM_OT_keyframe_delete(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Delete Keying-Set Keyframe";
- ot->idname = "ANIM_OT_keyframe_delete";
- ot->description = "Delete keyframes on the current frame for all properties in the specified Keying Set";
-
- /* callbacks */
- ot->exec = delete_key_exec;
- ot->poll = modify_key_op_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* keyingset to use (dynamic enum) */
- prop = RNA_def_enum(ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
- RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf);
- RNA_def_property_flag(prop, PROP_HIDDEN);
- ot->prop = prop;
-
- /* confirm whether a keyframe was added by showing a popup
- * - by default, this is enabled, since this operator is assumed to be called independently
- */
- RNA_def_boolean(ot->srna, "confirm_success", 1, "Confirm Successful Delete",
- "Show a popup when the keyframes get successfully removed");
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Delete Keying-Set Keyframe";
+ ot->idname = "ANIM_OT_keyframe_delete";
+ ot->description =
+ "Delete keyframes on the current frame for all properties in the specified Keying Set";
+
+ /* callbacks */
+ ot->exec = delete_key_exec;
+ ot->poll = modify_key_op_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* keyingset to use (dynamic enum) */
+ prop = RNA_def_enum(
+ ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
+ RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ ot->prop = prop;
+
+ /* confirm whether a keyframe was added by showing a popup
+ * - by default, this is enabled, since this operator is assumed to be called independently
+ */
+ RNA_def_boolean(ot->srna,
+ "confirm_success",
+ 1,
+ "Confirm Successful Delete",
+ "Show a popup when the keyframes get successfully removed");
}
void ANIM_OT_keyframe_delete_by_name(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Delete Keying-Set Keyframe (by name)";
- ot->idname = "ANIM_OT_keyframe_delete_by_name";
- ot->description = "Alternate access to 'Delete Keyframe' for keymaps to use";
-
- /* callbacks */
- ot->exec = delete_key_exec;
- ot->poll = modify_key_op_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* keyingset to use (idname) */
- prop = RNA_def_string_file_path(ot->srna, "type", "Type", MAX_ID_NAME - 2, "", "");
- RNA_def_property_flag(prop, PROP_HIDDEN);
- ot->prop = prop;
-
- /* confirm whether a keyframe was added by showing a popup
- * - by default, this is enabled, since this operator is assumed to be called independently
- */
- RNA_def_boolean(ot->srna, "confirm_success", 1, "Confirm Successful Delete",
- "Show a popup when the keyframes get successfully removed");
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Delete Keying-Set Keyframe (by name)";
+ ot->idname = "ANIM_OT_keyframe_delete_by_name";
+ ot->description = "Alternate access to 'Delete Keyframe' for keymaps to use";
+
+ /* callbacks */
+ ot->exec = delete_key_exec;
+ ot->poll = modify_key_op_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* keyingset to use (idname) */
+ prop = RNA_def_string_file_path(ot->srna, "type", "Type", MAX_ID_NAME - 2, "", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ ot->prop = prop;
+
+ /* confirm whether a keyframe was added by showing a popup
+ * - by default, this is enabled, since this operator is assumed to be called independently
+ */
+ RNA_def_boolean(ot->srna,
+ "confirm_success",
+ 1,
+ "Confirm Successful Delete",
+ "Show a popup when the keyframes get successfully removed");
}
/* Delete Key Operator ------------------------ */
@@ -1895,503 +2100,533 @@ void ANIM_OT_keyframe_delete_by_name(wmOperatorType *ot)
static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op))
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- /* just those in active action... */
- if ((ob->adt) && (ob->adt->action)) {
- AnimData *adt = ob->adt;
- bAction *act = adt->action;
- FCurve *fcu, *fcn;
-
- for (fcu = act->curves.first; fcu; fcu = fcn) {
- bool can_delete = false;
-
- fcn = fcu->next;
-
- /* in pose mode, only delete the F-Curve if it belongs to a selected bone */
- if (ob->mode & OB_MODE_POSE) {
- if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones[")) {
- bPoseChannel *pchan;
- char *bone_name;
-
- /* get bone-name, and check if this bone is selected */
- bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
- pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
- if (bone_name) MEM_freeN(bone_name);
-
- /* delete if bone is selected*/
- if ((pchan) && (pchan->bone)) {
- if (pchan->bone->flag & BONE_SELECTED)
- can_delete = true;
- }
- }
- }
- else {
- /* object mode - all of Object's F-Curves are affected */
- can_delete = true;
- }
-
- /* delete F-Curve completely */
- if (can_delete) {
- ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- changed = true;
- }
- }
- }
- }
- CTX_DATA_END;
-
- if (!changed) {
- return OPERATOR_CANCELLED;
- }
-
- /* send updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
-
- return OPERATOR_FINISHED;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ /* just those in active action... */
+ if ((ob->adt) && (ob->adt->action)) {
+ AnimData *adt = ob->adt;
+ bAction *act = adt->action;
+ FCurve *fcu, *fcn;
+
+ for (fcu = act->curves.first; fcu; fcu = fcn) {
+ bool can_delete = false;
+
+ fcn = fcu->next;
+
+ /* in pose mode, only delete the F-Curve if it belongs to a selected bone */
+ if (ob->mode & OB_MODE_POSE) {
+ if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones[")) {
+ bPoseChannel *pchan;
+ char *bone_name;
+
+ /* get bone-name, and check if this bone is selected */
+ bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
+ pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
+ if (bone_name)
+ MEM_freeN(bone_name);
+
+ /* delete if bone is selected*/
+ if ((pchan) && (pchan->bone)) {
+ if (pchan->bone->flag & BONE_SELECTED)
+ can_delete = true;
+ }
+ }
+ }
+ else {
+ /* object mode - all of Object's F-Curves are affected */
+ can_delete = true;
+ }
+
+ /* delete F-Curve completely */
+ if (can_delete) {
+ ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ changed = true;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ if (!changed) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* send updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
+
+ return OPERATOR_FINISHED;
}
void ANIM_OT_keyframe_clear_v3d(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Animation";
- ot->description = "Remove all keyframe animation for selected objects";
- ot->idname = "ANIM_OT_keyframe_clear_v3d";
+ /* identifiers */
+ ot->name = "Remove Animation";
+ ot->description = "Remove all keyframe animation for selected objects";
+ ot->idname = "ANIM_OT_keyframe_clear_v3d";
- /* callbacks */
- ot->invoke = WM_operator_confirm;
- ot->exec = clear_anim_v3d_exec;
+ /* callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = clear_anim_v3d_exec;
- ot->poll = ED_operator_areaactive;
+ ot->poll = ED_operator_areaactive;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
static int delete_key_v3d_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- float cfra = (float)CFRA;
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- ID *id = &ob->id;
- int success = 0;
-
- /* just those in active action... */
- if ((ob->adt) && (ob->adt->action)) {
- AnimData *adt = ob->adt;
- bAction *act = adt->action;
- FCurve *fcu, *fcn;
- const float cfra_unmap = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
-
- for (fcu = act->curves.first; fcu; fcu = fcn) {
- fcn = fcu->next;
-
- /* don't touch protected F-Curves */
- if (BKE_fcurve_is_protected(fcu)) {
- BKE_reportf(op->reports, RPT_WARNING,
- "Not deleting keyframe for locked F-Curve '%s', object '%s'",
- fcu->rna_path, id->name + 2);
- continue;
- }
-
- /* special exception for bones, as this makes this operator more convenient to use
- * NOTE: This is only done in pose mode. In object mode, we're dealing with the entire object.
- */
- if ((ob->mode & OB_MODE_POSE) && strstr(fcu->rna_path, "pose.bones[\"")) {
- bPoseChannel *pchan;
- char *bone_name;
-
- /* get bone-name, and check if this bone is selected */
- bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
- pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
- if (bone_name) MEM_freeN(bone_name);
-
- /* skip if bone is not selected */
- if ((pchan) && (pchan->bone)) {
- /* bones are only selected/editable if visible... */
- bArmature *arm = (bArmature *)ob->data;
-
- /* skipping - not visible on currently visible layers */
- if ((arm->layer & pchan->bone->layer) == 0)
- continue;
- /* skipping - is currently hidden */
- if (pchan->bone->flag & BONE_HIDDEN_P)
- continue;
-
- /* selection flag... */
- if ((pchan->bone->flag & BONE_SELECTED) == 0)
- continue;
- }
- }
-
- /* delete keyframes on current frame
- * WARNING: this can delete the next F-Curve, hence the "fcn" copying
- */
- success += delete_keyframe_fcurve(adt, fcu, cfra_unmap);
- }
- DEG_id_tag_update(&ob->adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
- }
-
- /* report success (or failure) */
- if (success)
- BKE_reportf(op->reports, RPT_INFO, "Object '%s' successfully had %d keyframes removed", id->name + 2, success);
- else
- BKE_reportf(op->reports, RPT_ERROR, "No keyframes removed from Object '%s'", id->name + 2);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
- CTX_DATA_END;
-
- /* send updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ float cfra = (float)CFRA;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ ID *id = &ob->id;
+ int success = 0;
+
+ /* just those in active action... */
+ if ((ob->adt) && (ob->adt->action)) {
+ AnimData *adt = ob->adt;
+ bAction *act = adt->action;
+ FCurve *fcu, *fcn;
+ const float cfra_unmap = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
+
+ for (fcu = act->curves.first; fcu; fcu = fcn) {
+ fcn = fcu->next;
+
+ /* don't touch protected F-Curves */
+ if (BKE_fcurve_is_protected(fcu)) {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Not deleting keyframe for locked F-Curve '%s', object '%s'",
+ fcu->rna_path,
+ id->name + 2);
+ continue;
+ }
+
+ /* special exception for bones, as this makes this operator more convenient to use
+ * NOTE: This is only done in pose mode. In object mode, we're dealing with the entire object.
+ */
+ if ((ob->mode & OB_MODE_POSE) && strstr(fcu->rna_path, "pose.bones[\"")) {
+ bPoseChannel *pchan;
+ char *bone_name;
+
+ /* get bone-name, and check if this bone is selected */
+ bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
+ pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
+ if (bone_name)
+ MEM_freeN(bone_name);
+
+ /* skip if bone is not selected */
+ if ((pchan) && (pchan->bone)) {
+ /* bones are only selected/editable if visible... */
+ bArmature *arm = (bArmature *)ob->data;
+
+ /* skipping - not visible on currently visible layers */
+ if ((arm->layer & pchan->bone->layer) == 0)
+ continue;
+ /* skipping - is currently hidden */
+ if (pchan->bone->flag & BONE_HIDDEN_P)
+ continue;
+
+ /* selection flag... */
+ if ((pchan->bone->flag & BONE_SELECTED) == 0)
+ continue;
+ }
+ }
+
+ /* delete keyframes on current frame
+ * WARNING: this can delete the next F-Curve, hence the "fcn" copying
+ */
+ success += delete_keyframe_fcurve(adt, fcu, cfra_unmap);
+ }
+ DEG_id_tag_update(&ob->adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
+ }
+
+ /* report success (or failure) */
+ if (success)
+ BKE_reportf(op->reports,
+ RPT_INFO,
+ "Object '%s' successfully had %d keyframes removed",
+ id->name + 2,
+ success);
+ else
+ BKE_reportf(op->reports, RPT_ERROR, "No keyframes removed from Object '%s'", id->name + 2);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+ CTX_DATA_END;
+
+ /* send updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
+
+ return OPERATOR_FINISHED;
}
void ANIM_OT_keyframe_delete_v3d(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Keyframe";
- ot->description = "Remove keyframes on current frame for selected objects and bones";
- ot->idname = "ANIM_OT_keyframe_delete_v3d";
+ /* identifiers */
+ ot->name = "Delete Keyframe";
+ ot->description = "Remove keyframes on current frame for selected objects and bones";
+ ot->idname = "ANIM_OT_keyframe_delete_v3d";
- /* callbacks */
- ot->invoke = WM_operator_confirm;
- ot->exec = delete_key_v3d_exec;
+ /* callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = delete_key_v3d_exec;
- ot->poll = ED_operator_areaactive;
+ ot->poll = ED_operator_areaactive;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/* Insert Key Button Operator ------------------------ */
static int insert_key_button_exec(bContext *C, wmOperator *op)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = scene->toolsettings;
- PointerRNA ptr = {{NULL}};
- PropertyRNA *prop = NULL;
- char *path;
- uiBut *but;
- float cfra = (float)CFRA;
- short success = 0;
- 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);
-
- /* try to insert keyframe using property retrieved from UI */
- if (!(but = UI_context_active_but_prop_get(C, &ptr, &prop, &index))) {
- /* pass event on if no active button found */
- return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
- }
-
- if ((ptr.id.data && ptr.data && prop) && RNA_property_animateable(&ptr, prop)) {
- if (ptr.type == &RNA_NlaStrip) {
- /* Handle special properties for NLA Strips, whose F-Curves are stored on the
- * strips themselves. These are stored separately or else the properties will
- * not have any effect.
- */
- NlaStrip *strip = (NlaStrip *)ptr.data;
- FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index);
-
- if (fcu) {
- success = insert_keyframe_direct(depsgraph, op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, NULL, 0);
- }
- else {
- BKE_report(op->reports, RPT_ERROR,
- "This property cannot be animated as it will not get updated correctly");
- }
- }
- else if (UI_but_flag_is_set(but, UI_BUT_DRIVEN)) {
- /* Driven property - Find driver */
- FCurve *fcu;
- bool driven, special;
-
- fcu = rna_get_fcurve_context_ui(C, &ptr, prop, index, NULL, NULL, &driven, &special);
-
- if (fcu && driven) {
- success = insert_keyframe_direct(depsgraph, op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, NULL, INSERTKEY_DRIVER);
- }
- }
- else {
- /* standard properties */
- path = RNA_path_from_ID_to_property(&ptr, prop);
-
- if (path) {
- const char *identifier = RNA_property_identifier(prop);
- const char *group = NULL;
-
- /* Special exception for keyframing transforms:
- * Set "group" for this manually, instead of having them appearing at the bottom (ungrouped)
- * part of the channels list. Leaving these ungrouped is not a nice user behavior in this case.
- *
- * TODO: Perhaps we can extend this behavior in future for other properties...
- */
- if (ptr.type == &RNA_PoseBone) {
- bPoseChannel *pchan = (bPoseChannel *)ptr.data;
- group = pchan->name;
- }
- else if ((ptr.type == &RNA_Object) &&
- (strstr(identifier, "location") || strstr(identifier, "rotation") || strstr(identifier, "scale")))
- {
- /* NOTE: Keep this label in sync with the "ID" case in
- * keyingsets_utils.py :: get_transform_generators_base_info()
- */
- group = "Object Transforms";
- }
-
-
- if (all) {
- /* -1 indicates operating on the entire array (or the property itself otherwise) */
- index = -1;
- }
-
- success = insert_keyframe(bmain, depsgraph, op->reports, ptr.id.data, NULL, group, path, index, cfra, ts->keyframe_type, NULL, flag);
-
- MEM_freeN(path);
- }
- else {
- BKE_report(op->reports, RPT_WARNING,
- "Failed to resolve path to property, "
- "try manually specifying this using a Keying Set instead");
- }
- }
- }
- else {
- if (prop && !RNA_property_animateable(&ptr, prop)) {
- BKE_reportf(op->reports, RPT_WARNING,
- "\"%s\" property cannot be animated",
- RNA_property_identifier(prop));
- }
- else {
- BKE_reportf(op->reports, RPT_WARNING,
- "Button doesn't appear to have any property information attached (ptr.data = %p, prop = %p)",
- (void *)ptr.data, (void *)prop);
- }
- }
-
- if (success) {
- ID *id = ptr.id.data;
- AnimData *adt = BKE_animdata_from_id(id);
- if (adt->action != NULL) {
- DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
- }
- DEG_id_tag_update(id, ID_RECALC_ANIMATION_NO_FLUSH);
-
- /* send updates */
- UI_context_update_anim_flag(C);
-
- /* send notifiers that keyframes have been changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
- }
-
- return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop = NULL;
+ char *path;
+ uiBut *but;
+ float cfra = (float)CFRA;
+ short success = 0;
+ 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);
+
+ /* try to insert keyframe using property retrieved from UI */
+ if (!(but = UI_context_active_but_prop_get(C, &ptr, &prop, &index))) {
+ /* pass event on if no active button found */
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+ if ((ptr.id.data && ptr.data && prop) && RNA_property_animateable(&ptr, prop)) {
+ if (ptr.type == &RNA_NlaStrip) {
+ /* Handle special properties for NLA Strips, whose F-Curves are stored on the
+ * strips themselves. These are stored separately or else the properties will
+ * not have any effect.
+ */
+ NlaStrip *strip = (NlaStrip *)ptr.data;
+ FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index);
+
+ if (fcu) {
+ success = insert_keyframe_direct(
+ depsgraph, op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, NULL, 0);
+ }
+ else {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "This property cannot be animated as it will not get updated correctly");
+ }
+ }
+ else if (UI_but_flag_is_set(but, UI_BUT_DRIVEN)) {
+ /* Driven property - Find driver */
+ FCurve *fcu;
+ bool driven, special;
+
+ fcu = rna_get_fcurve_context_ui(C, &ptr, prop, index, NULL, NULL, &driven, &special);
+
+ if (fcu && driven) {
+ success = insert_keyframe_direct(depsgraph,
+ op->reports,
+ ptr,
+ prop,
+ fcu,
+ cfra,
+ ts->keyframe_type,
+ NULL,
+ INSERTKEY_DRIVER);
+ }
+ }
+ else {
+ /* standard properties */
+ path = RNA_path_from_ID_to_property(&ptr, prop);
+
+ if (path) {
+ const char *identifier = RNA_property_identifier(prop);
+ const char *group = NULL;
+
+ /* Special exception for keyframing transforms:
+ * Set "group" for this manually, instead of having them appearing at the bottom (ungrouped)
+ * part of the channels list. Leaving these ungrouped is not a nice user behavior in this case.
+ *
+ * TODO: Perhaps we can extend this behavior in future for other properties...
+ */
+ if (ptr.type == &RNA_PoseBone) {
+ bPoseChannel *pchan = (bPoseChannel *)ptr.data;
+ group = pchan->name;
+ }
+ else if ((ptr.type == &RNA_Object) &&
+ (strstr(identifier, "location") || strstr(identifier, "rotation") ||
+ strstr(identifier, "scale"))) {
+ /* NOTE: Keep this label in sync with the "ID" case in
+ * keyingsets_utils.py :: get_transform_generators_base_info()
+ */
+ group = "Object Transforms";
+ }
+
+ if (all) {
+ /* -1 indicates operating on the entire array (or the property itself otherwise) */
+ index = -1;
+ }
+
+ success = insert_keyframe(bmain,
+ depsgraph,
+ op->reports,
+ ptr.id.data,
+ NULL,
+ group,
+ path,
+ index,
+ cfra,
+ ts->keyframe_type,
+ NULL,
+ flag);
+
+ MEM_freeN(path);
+ }
+ else {
+ BKE_report(op->reports,
+ RPT_WARNING,
+ "Failed to resolve path to property, "
+ "try manually specifying this using a Keying Set instead");
+ }
+ }
+ }
+ else {
+ if (prop && !RNA_property_animateable(&ptr, prop)) {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "\"%s\" property cannot be animated",
+ RNA_property_identifier(prop));
+ }
+ else {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Button doesn't appear to have any property information attached (ptr.data = "
+ "%p, prop = %p)",
+ (void *)ptr.data,
+ (void *)prop);
+ }
+ }
+
+ if (success) {
+ ID *id = ptr.id.data;
+ AnimData *adt = BKE_animdata_from_id(id);
+ if (adt->action != NULL) {
+ DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
+ }
+ DEG_id_tag_update(id, ID_RECALC_ANIMATION_NO_FLUSH);
+
+ /* send updates */
+ UI_context_update_anim_flag(C);
+
+ /* send notifiers that keyframes have been changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
+ }
+
+ return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void ANIM_OT_keyframe_insert_button(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Insert Keyframe (Buttons)";
- ot->idname = "ANIM_OT_keyframe_insert_button";
- ot->description = "Insert a keyframe for current UI-active property";
+ /* identifiers */
+ ot->name = "Insert Keyframe (Buttons)";
+ ot->idname = "ANIM_OT_keyframe_insert_button";
+ ot->description = "Insert a keyframe for current UI-active property";
- /* callbacks */
- ot->exec = insert_key_button_exec;
- ot->poll = modify_key_op_poll;
+ /* callbacks */
+ ot->exec = insert_key_button_exec;
+ ot->poll = modify_key_op_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
- /* properties */
- RNA_def_boolean(ot->srna, "all", 1, "All", "Insert a keyframe for all element of the array");
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Insert a keyframe for all element of the array");
}
/* Delete Key Button Operator ------------------------ */
static int delete_key_button_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- PointerRNA ptr = {{NULL}};
- PropertyRNA *prop = NULL;
- 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;
- int index;
- const bool all = RNA_boolean_get(op->ptr, "all");
-
- /* try to insert keyframe using property retrieved from UI */
- if (!UI_context_active_but_prop_get(C, &ptr, &prop, &index)) {
- /* pass event on if no active button found */
- return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
- }
-
- if (ptr.id.data && ptr.data && prop) {
- if (BKE_nlastrip_has_curves_for_property(&ptr, prop)) {
- /* Handle special properties for NLA Strips, whose F-Curves are stored on the
- * strips themselves. These are stored separately or else the properties will
- * not have any effect.
- */
- ID *id = ptr.id.data;
- NlaStrip *strip = (NlaStrip *)ptr.data;
- FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), 0);
-
- if (fcu) {
- if (BKE_fcurve_is_protected(fcu)) {
- BKE_reportf(op->reports, 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)), id->name + 2);
- }
- else {
- /* remove the keyframe directly
- * NOTE: cannot use delete_keyframe_fcurve(), as that will free the curve,
- * and delete_keyframe() expects the FCurve to be part of an action
- */
- bool found = false;
- int i;
-
- /* try to find index of beztriple to get rid of */
- i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
- if (found) {
- /* delete the key at the index (will sanity check + do recalc afterwards) */
- delete_fcurve_key(fcu, i, 1);
- success = true;
- }
- }
- }
- }
- else {
- /* standard properties */
- path = RNA_path_from_ID_to_property(&ptr, prop);
-
- if (path) {
- if (all) {
- /* -1 indicates operating on the entire array (or the property itself otherwise) */
- index = -1;
- }
-
- success = delete_keyframe(bmain, op->reports, ptr.id.data, NULL, NULL, path, index, cfra, 0);
- MEM_freeN(path);
- }
- else if (G.debug & G_DEBUG)
- printf("Button Delete-Key: no path to property\n");
- }
- }
- else if (G.debug & G_DEBUG) {
- printf("ptr.data = %p, prop = %p\n", (void *)ptr.data, (void *)prop);
- }
-
-
- if (success) {
- /* send updates */
- UI_context_update_anim_flag(C);
-
- /* send notifiers that keyframes have been changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
- }
-
- return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop = NULL;
+ 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;
+ int index;
+ const bool all = RNA_boolean_get(op->ptr, "all");
+
+ /* try to insert keyframe using property retrieved from UI */
+ if (!UI_context_active_but_prop_get(C, &ptr, &prop, &index)) {
+ /* pass event on if no active button found */
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+ if (ptr.id.data && ptr.data && prop) {
+ if (BKE_nlastrip_has_curves_for_property(&ptr, prop)) {
+ /* Handle special properties for NLA Strips, whose F-Curves are stored on the
+ * strips themselves. These are stored separately or else the properties will
+ * not have any effect.
+ */
+ ID *id = ptr.id.data;
+ NlaStrip *strip = (NlaStrip *)ptr.data;
+ FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), 0);
+
+ if (fcu) {
+ if (BKE_fcurve_is_protected(fcu)) {
+ BKE_reportf(
+ op->reports,
+ 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)),
+ id->name + 2);
+ }
+ else {
+ /* remove the keyframe directly
+ * NOTE: cannot use delete_keyframe_fcurve(), as that will free the curve,
+ * and delete_keyframe() expects the FCurve to be part of an action
+ */
+ bool found = false;
+ int i;
+
+ /* try to find index of beztriple to get rid of */
+ i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
+ if (found) {
+ /* delete the key at the index (will sanity check + do recalc afterwards) */
+ delete_fcurve_key(fcu, i, 1);
+ success = true;
+ }
+ }
+ }
+ }
+ else {
+ /* standard properties */
+ path = RNA_path_from_ID_to_property(&ptr, prop);
+
+ if (path) {
+ if (all) {
+ /* -1 indicates operating on the entire array (or the property itself otherwise) */
+ index = -1;
+ }
+
+ success = delete_keyframe(
+ bmain, op->reports, ptr.id.data, NULL, NULL, path, index, cfra, 0);
+ MEM_freeN(path);
+ }
+ else if (G.debug & G_DEBUG)
+ printf("Button Delete-Key: no path to property\n");
+ }
+ }
+ else if (G.debug & G_DEBUG) {
+ printf("ptr.data = %p, prop = %p\n", (void *)ptr.data, (void *)prop);
+ }
+
+ if (success) {
+ /* send updates */
+ UI_context_update_anim_flag(C);
+
+ /* send notifiers that keyframes have been changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
+ }
+
+ return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void ANIM_OT_keyframe_delete_button(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Keyframe (Buttons)";
- ot->idname = "ANIM_OT_keyframe_delete_button";
- ot->description = "Delete current keyframe of current UI-active property";
+ /* identifiers */
+ ot->name = "Delete Keyframe (Buttons)";
+ ot->idname = "ANIM_OT_keyframe_delete_button";
+ ot->description = "Delete current keyframe of current UI-active property";
- /* callbacks */
- ot->exec = delete_key_button_exec;
- ot->poll = modify_key_op_poll;
+ /* callbacks */
+ ot->exec = delete_key_button_exec;
+ ot->poll = modify_key_op_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
- /* properties */
- RNA_def_boolean(ot->srna, "all", 1, "All", "Delete keyframes from all elements of the array");
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Delete keyframes from all elements of the array");
}
-
/* Clear Key Button Operator ------------------------ */
static int clear_key_button_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr = {{NULL}};
- PropertyRNA *prop = NULL;
- Main *bmain = CTX_data_main(C);
- char *path;
- short success = 0;
- int index;
- const bool all = RNA_boolean_get(op->ptr, "all");
-
- /* try to insert keyframe using property retrieved from UI */
- if (!UI_context_active_but_prop_get(C, &ptr, &prop, &index)) {
- /* pass event on if no active button found */
- return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
- }
-
- if (ptr.id.data && ptr.data && prop) {
- path = RNA_path_from_ID_to_property(&ptr, prop);
-
- if (path) {
- if (all) {
- /* -1 indicates operating on the entire array (or the property itself otherwise) */
- index = -1;
- }
-
- success += clear_keyframe(bmain, op->reports, ptr.id.data, NULL, NULL, path, index, 0);
- MEM_freeN(path);
- }
- else if (G.debug & G_DEBUG)
- printf("Button Clear-Key: no path to property\n");
- }
- else if (G.debug & G_DEBUG) {
- printf("ptr.data = %p, prop = %p\n", (void *)ptr.data, (void *)prop);
- }
-
-
- if (success) {
- /* send updates */
- UI_context_update_anim_flag(C);
-
- /* send notifiers that keyframes have been changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
- }
-
- return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop = NULL;
+ Main *bmain = CTX_data_main(C);
+ char *path;
+ short success = 0;
+ int index;
+ const bool all = RNA_boolean_get(op->ptr, "all");
+
+ /* try to insert keyframe using property retrieved from UI */
+ if (!UI_context_active_but_prop_get(C, &ptr, &prop, &index)) {
+ /* pass event on if no active button found */
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+ if (ptr.id.data && ptr.data && prop) {
+ path = RNA_path_from_ID_to_property(&ptr, prop);
+
+ if (path) {
+ if (all) {
+ /* -1 indicates operating on the entire array (or the property itself otherwise) */
+ index = -1;
+ }
+
+ success += clear_keyframe(bmain, op->reports, ptr.id.data, NULL, NULL, path, index, 0);
+ MEM_freeN(path);
+ }
+ else if (G.debug & G_DEBUG)
+ printf("Button Clear-Key: no path to property\n");
+ }
+ else if (G.debug & G_DEBUG) {
+ printf("ptr.data = %p, prop = %p\n", (void *)ptr.data, (void *)prop);
+ }
+
+ if (success) {
+ /* send updates */
+ UI_context_update_anim_flag(C);
+
+ /* send notifiers that keyframes have been changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
+ }
+
+ return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void ANIM_OT_keyframe_clear_button(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Keyframe (Buttons)";
- ot->idname = "ANIM_OT_keyframe_clear_button";
- ot->description = "Clear all keyframes on the currently active property";
+ /* identifiers */
+ ot->name = "Clear Keyframe (Buttons)";
+ ot->idname = "ANIM_OT_keyframe_clear_button";
+ ot->description = "Clear all keyframes on the currently active property";
- /* callbacks */
- ot->exec = clear_key_button_exec;
- ot->poll = modify_key_op_poll;
+ /* callbacks */
+ ot->exec = clear_key_button_exec;
+ ot->poll = modify_key_op_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
- /* properties */
- RNA_def_boolean(ot->srna, "all", 1, "All", "Clear keyframes from all elements of the array");
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Clear keyframes from all elements of the array");
}
/* ******************************************* */
@@ -2399,30 +2634,30 @@ void ANIM_OT_keyframe_clear_button(wmOperatorType *ot)
bool autokeyframe_cfra_can_key(Scene *scene, ID *id)
{
- float cfra = (float)CFRA; // XXX for now, this will do
-
- /* only filter if auto-key mode requires this */
- if (IS_AUTOKEY_ON(scene) == 0)
- return false;
-
- if (IS_AUTOKEY_MODE(scene, EDITKEYS)) {
- /* Replace Mode:
- * For whole block, only key if there's a keyframe on that frame already
- * This is a valid assumption when we're blocking + tweaking
- */
- return id_frame_has_keyframe(id, cfra, ANIMFILTER_KEYS_LOCAL);
- }
- else {
- /* Normal Mode (or treat as being normal mode):
- *
- * Just in case the flags aren't set properly (i.e. only on/off is set, without a mode)
- * let's set the "normal" flag too, so that it will all be sane everywhere...
- */
- scene->toolsettings->autokey_mode = AUTOKEY_MODE_NORMAL;
-
- /* Can insert anytime we like... */
- return true;
- }
+ float cfra = (float)CFRA; // XXX for now, this will do
+
+ /* only filter if auto-key mode requires this */
+ if (IS_AUTOKEY_ON(scene) == 0)
+ return false;
+
+ if (IS_AUTOKEY_MODE(scene, EDITKEYS)) {
+ /* Replace Mode:
+ * For whole block, only key if there's a keyframe on that frame already
+ * This is a valid assumption when we're blocking + tweaking
+ */
+ return id_frame_has_keyframe(id, cfra, ANIMFILTER_KEYS_LOCAL);
+ }
+ else {
+ /* Normal Mode (or treat as being normal mode):
+ *
+ * Just in case the flags aren't set properly (i.e. only on/off is set, without a mode)
+ * let's set the "normal" flag too, so that it will all be sane everywhere...
+ */
+ scene->toolsettings->autokey_mode = AUTOKEY_MODE_NORMAL;
+
+ /* Can insert anytime we like... */
+ return true;
+ }
}
/* ******************************************* */
@@ -2433,48 +2668,49 @@ bool autokeyframe_cfra_can_key(Scene *scene, ID *id)
/* Checks if some F-Curve has a keyframe for a given frame */
bool fcurve_frame_has_keyframe(FCurve *fcu, float frame, short filter)
{
- /* quick sanity check */
- if (ELEM(NULL, fcu, fcu->bezt))
- return false;
-
- /* we either include all regardless of muting, or only non-muted */
- if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED) == 0) {
- bool replace;
- int i = binarysearch_bezt_index(fcu->bezt, frame, fcu->totvert, &replace);
-
- /* binarysearch_bezt_index will set replace to be 0 or 1
- * - obviously, 1 represents a match
- */
- if (replace) {
- /* sanity check: 'i' may in rare cases exceed arraylen */
- if ((i >= 0) && (i < fcu->totvert))
- return true;
- }
- }
-
- return false;
+ /* quick sanity check */
+ if (ELEM(NULL, fcu, fcu->bezt))
+ return false;
+
+ /* we either include all regardless of muting, or only non-muted */
+ if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED) == 0) {
+ bool replace;
+ int i = binarysearch_bezt_index(fcu->bezt, frame, fcu->totvert, &replace);
+
+ /* binarysearch_bezt_index will set replace to be 0 or 1
+ * - obviously, 1 represents a match
+ */
+ if (replace) {
+ /* sanity check: 'i' may in rare cases exceed arraylen */
+ if ((i >= 0) && (i < fcu->totvert))
+ return true;
+ }
+ }
+
+ return false;
}
/* Returns whether the current value of a given property differs from the interpolated value. */
bool fcurve_is_changed(PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, float frame)
{
- PathResolvedRNA anim_rna;
- anim_rna.ptr = ptr;
- anim_rna.prop = prop;
- anim_rna.prop_index = fcu->array_index;
+ PathResolvedRNA anim_rna;
+ anim_rna.ptr = ptr;
+ anim_rna.prop = prop;
+ anim_rna.prop_index = fcu->array_index;
- float buffer[RNA_MAX_ARRAY_LENGTH];
- int count, index = fcu->array_index;
- float *values = setting_get_rna_values(NULL, &ptr, prop, false, buffer, RNA_MAX_ARRAY_LENGTH, &count);
+ float buffer[RNA_MAX_ARRAY_LENGTH];
+ int count, index = fcu->array_index;
+ float *values = setting_get_rna_values(
+ NULL, &ptr, prop, false, buffer, RNA_MAX_ARRAY_LENGTH, &count);
- float fcurve_val = calculate_fcurve(&anim_rna, fcu, frame);
- float cur_val = (index >= 0 && index < count) ? values[index] : 0.0f;
+ float fcurve_val = calculate_fcurve(&anim_rna, fcu, frame);
+ float cur_val = (index >= 0 && index < count) ? values[index] : 0.0f;
- if (values != buffer) {
- MEM_freeN(values);
- }
+ if (values != buffer) {
+ MEM_freeN(values);
+ }
- return !compare_ff_relative(fcurve_val, cur_val, FLT_EPSILON, 64);
+ return !compare_ff_relative(fcurve_val, cur_val, FLT_EPSILON, 64);
}
/* Checks whether an Action has a keyframe for a given frame
@@ -2482,91 +2718,91 @@ bool fcurve_is_changed(PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, float fra
*/
static bool action_frame_has_keyframe(bAction *act, float frame, short filter)
{
- FCurve *fcu;
-
- /* can only find if there is data */
- if (act == NULL)
- return false;
-
- /* if only check non-muted, check if muted */
- if ((filter & ANIMFILTER_KEYS_MUTED) || (act->flag & ACT_MUTED))
- return false;
-
- /* loop over F-Curves, using binary-search to try to find matches
- * - this assumes that keyframes are only beztriples
- */
- for (fcu = act->curves.first; fcu; fcu = fcu->next) {
- /* only check if there are keyframes (currently only of type BezTriple) */
- if (fcu->bezt && fcu->totvert) {
- if (fcurve_frame_has_keyframe(fcu, frame, filter))
- return true;
- }
- }
-
- /* nothing found */
- return false;
+ FCurve *fcu;
+
+ /* can only find if there is data */
+ if (act == NULL)
+ return false;
+
+ /* if only check non-muted, check if muted */
+ if ((filter & ANIMFILTER_KEYS_MUTED) || (act->flag & ACT_MUTED))
+ return false;
+
+ /* loop over F-Curves, using binary-search to try to find matches
+ * - this assumes that keyframes are only beztriples
+ */
+ for (fcu = act->curves.first; fcu; fcu = fcu->next) {
+ /* only check if there are keyframes (currently only of type BezTriple) */
+ if (fcu->bezt && fcu->totvert) {
+ if (fcurve_frame_has_keyframe(fcu, frame, filter))
+ return true;
+ }
+ }
+
+ /* nothing found */
+ return false;
}
/* Checks whether an Object has a keyframe for a given frame */
static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
{
- /* error checking */
- if (ob == NULL)
- return false;
-
- /* check own animation data - specifically, the action it contains */
- if ((ob->adt) && (ob->adt->action)) {
- /* T41525 - When the active action is a NLA strip being edited,
- * we need to correct the frame number to "look inside" the
- * remapped action
- */
- float ob_frame = BKE_nla_tweakedit_remap(ob->adt, frame, NLATIME_CONVERT_UNMAP);
-
- if (action_frame_has_keyframe(ob->adt->action, ob_frame, filter))
- return true;
- }
-
- /* try shapekey keyframes (if available, and allowed by filter) */
- if (!(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOSKEY)) {
- Key *key = BKE_key_from_object(ob);
-
- /* shapekeys can have keyframes ('Relative Shape Keys')
- * or depend on time (old 'Absolute Shape Keys')
- */
-
- /* 1. test for relative (with keyframes) */
- if (id_frame_has_keyframe((ID *)key, frame, filter))
- return true;
-
- /* 2. test for time */
- /* TODO... yet to be implemented (this feature may evolve before then anyway) */
- }
-
- /* try materials */
- 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));
-
- /* we only retrieve the active material... */
- if (id_frame_has_keyframe((ID *)ma, frame, filter))
- return true;
- }
- else {
- int a;
-
- /* loop over materials */
- for (a = 0; a < ob->totcol; a++) {
- Material *ma = give_current_material(ob, a + 1);
-
- if (id_frame_has_keyframe((ID *)ma, frame, filter))
- return true;
- }
- }
- }
-
- /* nothing found */
- return false;
+ /* error checking */
+ if (ob == NULL)
+ return false;
+
+ /* check own animation data - specifically, the action it contains */
+ if ((ob->adt) && (ob->adt->action)) {
+ /* T41525 - When the active action is a NLA strip being edited,
+ * we need to correct the frame number to "look inside" the
+ * remapped action
+ */
+ float ob_frame = BKE_nla_tweakedit_remap(ob->adt, frame, NLATIME_CONVERT_UNMAP);
+
+ if (action_frame_has_keyframe(ob->adt->action, ob_frame, filter))
+ return true;
+ }
+
+ /* try shapekey keyframes (if available, and allowed by filter) */
+ if (!(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOSKEY)) {
+ Key *key = BKE_key_from_object(ob);
+
+ /* shapekeys can have keyframes ('Relative Shape Keys')
+ * or depend on time (old 'Absolute Shape Keys')
+ */
+
+ /* 1. test for relative (with keyframes) */
+ if (id_frame_has_keyframe((ID *)key, frame, filter))
+ return true;
+
+ /* 2. test for time */
+ /* TODO... yet to be implemented (this feature may evolve before then anyway) */
+ }
+
+ /* try materials */
+ 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));
+
+ /* we only retrieve the active material... */
+ if (id_frame_has_keyframe((ID *)ma, frame, filter))
+ return true;
+ }
+ else {
+ int a;
+
+ /* loop over materials */
+ for (a = 0; a < ob->totcol; a++) {
+ Material *ma = give_current_material(ob, a + 1);
+
+ if (id_frame_has_keyframe((ID *)ma, frame, filter))
+ return true;
+ }
+ }
+ }
+
+ /* nothing found */
+ return false;
}
/* --------------- API ------------------- */
@@ -2574,88 +2810,88 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
/* Checks whether a keyframe exists for the given ID-block one the given frame */
bool id_frame_has_keyframe(ID *id, float frame, short filter)
{
- /* sanity checks */
- if (id == NULL)
- return false;
-
- /* perform special checks for 'macro' types */
- switch (GS(id->name)) {
- case ID_OB: /* object */
- return object_frame_has_keyframe((Object *)id, frame, filter);
+ /* sanity checks */
+ if (id == NULL)
+ return false;
+
+ /* perform special checks for 'macro' types */
+ switch (GS(id->name)) {
+ case ID_OB: /* object */
+ return object_frame_has_keyframe((Object *)id, frame, filter);
#if 0
- // XXX TODO... for now, just use 'normal' behavior
- case ID_SCE: /* scene */
- break;
+ // XXX TODO... for now, just use 'normal' behavior
+ case ID_SCE: /* scene */
+ break;
#endif
- default: /* 'normal type' */
- {
- AnimData *adt = BKE_animdata_from_id(id);
-
- /* only check keyframes in active action */
- if (adt)
- return action_frame_has_keyframe(adt->action, frame, filter);
- break;
- }
- }
-
-
- /* no keyframe found */
- return false;
+ default: /* 'normal type' */
+ {
+ AnimData *adt = BKE_animdata_from_id(id);
+
+ /* only check keyframes in active action */
+ if (adt)
+ return action_frame_has_keyframe(adt->action, frame, filter);
+ break;
+ }
+ }
+
+ /* no keyframe found */
+ return false;
}
/* ************************************************** */
bool ED_autokeyframe_object(bContext *C, Scene *scene, Object *ob, KeyingSet *ks)
{
- /* auto keyframing */
- 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
- */
- ANIM_relative_keyingset_add_source(&dsources, &ob->id, NULL, NULL);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
- BLI_freelistN(&dsources);
-
- return true;
- }
- else {
- return false;
- }
+ /* auto keyframing */
+ 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
+ */
+ ANIM_relative_keyingset_add_source(&dsources, &ob->id, NULL, NULL);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ BLI_freelistN(&dsources);
+
+ return true;
+ }
+ else {
+ return false;
+ }
}
-bool ED_autokeyframe_pchan(bContext *C, Scene *scene, Object *ob, bPoseChannel *pchan, KeyingSet *ks)
+bool ED_autokeyframe_pchan(
+ bContext *C, Scene *scene, Object *ob, bPoseChannel *pchan, 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 PoseChannel
- * 2) insert keyframes
- * 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);
- BLI_freelistN(&dsources);
-
- /* clear any unkeyed tags */
- if (pchan->bone) {
- pchan->bone->flag &= ~BONE_UNKEYED;
- }
-
- return true;
- }
- else {
- /* add unkeyed tags */
- if (pchan->bone) {
- pchan->bone->flag |= BONE_UNKEYED;
- }
-
- return false;
- }
+ 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
+ */
+ ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ BLI_freelistN(&dsources);
+
+ /* clear any unkeyed tags */
+ if (pchan->bone) {
+ pchan->bone->flag &= ~BONE_UNKEYED;
+ }
+
+ return true;
+ }
+ else {
+ /* add unkeyed tags */
+ if (pchan->bone) {
+ pchan->bone->flag |= BONE_UNKEYED;
+ }
+
+ return false;
+ }
}
/* -------------------------------------------------------------------- */
@@ -2665,28 +2901,28 @@ bool ED_autokeyframe_pchan(bContext *C, Scene *scene, Object *ob, bPoseChannel *
/** Use for insert/delete key-frame. */
static KeyingSet *keyingset_get_from_op_with_error(wmOperator *op, PropertyRNA *prop, Scene *scene)
{
- KeyingSet *ks = NULL;
- const int prop_type = RNA_property_type(prop);
- if (prop_type == PROP_ENUM) {
- int type = RNA_property_enum_get(op->ptr, prop);
- ks = ANIM_keyingset_get_from_enum_type(scene, type);
- if (ks == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active keying set");
- }
- }
- else if (prop_type == PROP_STRING) {
- char type_id[MAX_ID_NAME - 2];
- RNA_property_string_get(op->ptr, prop, type_id);
- ks = ANIM_keyingset_get_from_idname(scene, type_id);
-
- if (ks == NULL) {
- BKE_reportf(op->reports, RPT_ERROR, "Keying set '%s' not found", type_id);
- }
- }
- else {
- BLI_assert(0);
- }
- return ks;
+ KeyingSet *ks = NULL;
+ const int prop_type = RNA_property_type(prop);
+ if (prop_type == PROP_ENUM) {
+ int type = RNA_property_enum_get(op->ptr, prop);
+ ks = ANIM_keyingset_get_from_enum_type(scene, type);
+ if (ks == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active keying set");
+ }
+ }
+ else if (prop_type == PROP_STRING) {
+ char type_id[MAX_ID_NAME - 2];
+ RNA_property_string_get(op->ptr, prop, type_id);
+ ks = ANIM_keyingset_get_from_idname(scene, type_id);
+
+ if (ks == NULL) {
+ BKE_reportf(op->reports, RPT_ERROR, "Keying set '%s' not found", type_id);
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+ return ks;
}
/** \} */
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index 654543c9d5d..93bae636571 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -21,7 +21,6 @@
* \ingroup edanimation
*/
-
#include <stdio.h>
#include <stddef.h>
#include <string.h>
@@ -68,209 +67,208 @@
/* poll callback for adding default KeyingSet */
static bool keyingset_poll_default_add(bContext *C)
{
- /* as long as there's an active Scene, it's fine */
- return (CTX_data_scene(C) != NULL);
+ /* as long as there's an active Scene, it's fine */
+ return (CTX_data_scene(C) != NULL);
}
/* poll callback for editing active KeyingSet */
static bool keyingset_poll_active_edit(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- if (scene == NULL)
- return 0;
+ if (scene == NULL)
+ return 0;
- /* there must be an active KeyingSet (and KeyingSets) */
- return ((scene->active_keyingset > 0) && (scene->keyingsets.first));
+ /* there must be an active KeyingSet (and KeyingSets) */
+ return ((scene->active_keyingset > 0) && (scene->keyingsets.first));
}
/* poll callback for editing active KeyingSet Path */
static bool keyingset_poll_activePath_edit(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- KeyingSet *ks;
-
- if (scene == NULL)
- return 0;
- if (scene->active_keyingset <= 0)
- return 0;
- else
- ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1);
-
- /* there must be an active KeyingSet and an active path */
- return ((ks) && (ks->paths.first) && (ks->active_path > 0));
+ Scene *scene = CTX_data_scene(C);
+ KeyingSet *ks;
+
+ if (scene == NULL)
+ return 0;
+ if (scene->active_keyingset <= 0)
+ return 0;
+ else
+ ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1);
+
+ /* there must be an active KeyingSet and an active path */
+ return ((ks) && (ks->paths.first) && (ks->active_path > 0));
}
-
/* Add a Default (Empty) Keying Set ------------------------- */
static int add_default_keyingset_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- short flag = 0, keyingflag = 0;
+ Scene *scene = CTX_data_scene(C);
+ short flag = 0, keyingflag = 0;
- /* validate flags
- * - absolute KeyingSets should be created by default
- */
- flag |= KEYINGSET_ABSOLUTE;
+ /* validate flags
+ * - absolute KeyingSets should be created by default
+ */
+ 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);
+ /* 2nd arg is 0 to indicate that we don't want to include autokeying mode related settings */
+ keyingflag = ANIM_get_keyframing_flags(scene, 0);
- /* call the API func, and set the active keyingset index */
- BKE_keyingset_add(&scene->keyingsets, NULL, NULL, flag, keyingflag);
+ /* call the API func, and set the active keyingset index */
+ BKE_keyingset_add(&scene->keyingsets, NULL, NULL, flag, keyingflag);
- scene->active_keyingset = BLI_listbase_count(&scene->keyingsets);
+ scene->active_keyingset = BLI_listbase_count(&scene->keyingsets);
- /* send notifiers */
- WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
+ /* send notifiers */
+ WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ANIM_OT_keying_set_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Empty Keying Set";
- ot->idname = "ANIM_OT_keying_set_add";
- ot->description = "Add a new (empty) Keying Set to the active Scene";
-
- /* callbacks */
- ot->exec = add_default_keyingset_exec;
- ot->poll = keyingset_poll_default_add;
+ /* identifiers */
+ ot->name = "Add Empty Keying Set";
+ ot->idname = "ANIM_OT_keying_set_add";
+ ot->description = "Add a new (empty) Keying Set to the active Scene";
+
+ /* callbacks */
+ ot->exec = add_default_keyingset_exec;
+ ot->poll = keyingset_poll_default_add;
}
/* Remove 'Active' Keying Set ------------------------- */
static int remove_active_keyingset_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- KeyingSet *ks;
-
- /* verify the Keying Set to use:
- * - use the active one
- * - return error if it doesn't exist
- */
- if (scene->active_keyingset == 0) {
- BKE_report(op->reports, RPT_ERROR, "No active keying set to remove");
- return OPERATOR_CANCELLED;
- }
- else if (scene->active_keyingset < 0) {
- BKE_report(op->reports, RPT_ERROR, "Cannot remove built in keying set");
- return OPERATOR_CANCELLED;
- }
- else
- ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1);
-
- /* free KeyingSet's data, then remove it from the scene */
- BKE_keyingset_free(ks);
- BLI_freelinkN(&scene->keyingsets, ks);
-
- /* the active one should now be the previously second-to-last one */
- scene->active_keyingset--;
-
- /* send notifiers */
- WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ KeyingSet *ks;
+
+ /* verify the Keying Set to use:
+ * - use the active one
+ * - return error if it doesn't exist
+ */
+ if (scene->active_keyingset == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No active keying set to remove");
+ return OPERATOR_CANCELLED;
+ }
+ else if (scene->active_keyingset < 0) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot remove built in keying set");
+ return OPERATOR_CANCELLED;
+ }
+ else
+ ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1);
+
+ /* free KeyingSet's data, then remove it from the scene */
+ BKE_keyingset_free(ks);
+ BLI_freelinkN(&scene->keyingsets, ks);
+
+ /* the active one should now be the previously second-to-last one */
+ scene->active_keyingset--;
+
+ /* send notifiers */
+ WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
+
+ return OPERATOR_FINISHED;
}
void ANIM_OT_keying_set_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Active Keying Set";
- ot->idname = "ANIM_OT_keying_set_remove";
- ot->description = "Remove the active Keying Set";
-
- /* callbacks */
- ot->exec = remove_active_keyingset_exec;
- ot->poll = keyingset_poll_active_edit;
+ /* identifiers */
+ ot->name = "Remove Active Keying Set";
+ ot->idname = "ANIM_OT_keying_set_remove";
+ ot->description = "Remove the active Keying Set";
+
+ /* callbacks */
+ ot->exec = remove_active_keyingset_exec;
+ ot->poll = keyingset_poll_active_edit;
}
/* Add Empty Keying Set Path ------------------------- */
static int add_empty_ks_path_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- KeyingSet *ks;
- KS_Path *ksp;
-
- /* verify the Keying Set to use:
- * - use the active one
- * - return error if it doesn't exist
- */
- if (scene->active_keyingset == 0) {
- BKE_report(op->reports, RPT_ERROR, "No active keying set to add empty path to");
- return OPERATOR_CANCELLED;
- }
- else
- ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1);
-
- /* don't use the API method for this, since that checks on values... */
- ksp = MEM_callocN(sizeof(KS_Path), "KeyingSetPath Empty");
- BLI_addtail(&ks->paths, ksp);
- ks->active_path = BLI_listbase_count(&ks->paths);
-
- ksp->groupmode = KSP_GROUP_KSNAME; // XXX?
- ksp->idtype = ID_OB;
- ksp->flag = KSP_FLAG_WHOLE_ARRAY;
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ KeyingSet *ks;
+ KS_Path *ksp;
+
+ /* verify the Keying Set to use:
+ * - use the active one
+ * - return error if it doesn't exist
+ */
+ if (scene->active_keyingset == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No active keying set to add empty path to");
+ return OPERATOR_CANCELLED;
+ }
+ else
+ ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1);
+
+ /* don't use the API method for this, since that checks on values... */
+ ksp = MEM_callocN(sizeof(KS_Path), "KeyingSetPath Empty");
+ BLI_addtail(&ks->paths, ksp);
+ ks->active_path = BLI_listbase_count(&ks->paths);
+
+ ksp->groupmode = KSP_GROUP_KSNAME; // XXX?
+ ksp->idtype = ID_OB;
+ ksp->flag = KSP_FLAG_WHOLE_ARRAY;
+
+ return OPERATOR_FINISHED;
}
void ANIM_OT_keying_set_path_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Empty Keying Set Path";
- ot->idname = "ANIM_OT_keying_set_path_add";
- ot->description = "Add empty path to active Keying Set";
-
- /* callbacks */
- ot->exec = add_empty_ks_path_exec;
- ot->poll = keyingset_poll_active_edit;
+ /* identifiers */
+ ot->name = "Add Empty Keying Set Path";
+ ot->idname = "ANIM_OT_keying_set_path_add";
+ ot->description = "Add empty path to active Keying Set";
+
+ /* callbacks */
+ ot->exec = add_empty_ks_path_exec;
+ ot->poll = keyingset_poll_active_edit;
}
/* Remove Active Keying Set Path ------------------------- */
static int remove_active_ks_path_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- KeyingSet *ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1);
-
- /* if there is a KeyingSet, find the nominated path to remove */
- if (ks) {
- KS_Path *ksp = BLI_findlink(&ks->paths, ks->active_path - 1);
-
- if (ksp) {
- /* remove the active path from the KeyingSet */
- BKE_keyingset_free_path(ks, ksp);
-
- /* the active path should now be the previously second-to-last active one */
- ks->active_path--;
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "No active keying set path to remove");
- return OPERATOR_CANCELLED;
- }
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "No active keying set to remove a path from");
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ KeyingSet *ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1);
+
+ /* if there is a KeyingSet, find the nominated path to remove */
+ if (ks) {
+ KS_Path *ksp = BLI_findlink(&ks->paths, ks->active_path - 1);
+
+ if (ksp) {
+ /* remove the active path from the KeyingSet */
+ BKE_keyingset_free_path(ks, ksp);
+
+ /* the active path should now be the previously second-to-last active one */
+ ks->active_path--;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No active keying set path to remove");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No active keying set to remove a path from");
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
void ANIM_OT_keying_set_path_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Active Keying Set Path";
- ot->idname = "ANIM_OT_keying_set_path_remove";
- ot->description = "Remove active Path from active Keying Set";
-
- /* callbacks */
- ot->exec = remove_active_ks_path_exec;
- ot->poll = keyingset_poll_activePath_edit;
+ /* identifiers */
+ ot->name = "Remove Active Keying Set Path";
+ ot->idname = "ANIM_OT_keying_set_path_remove";
+ ot->description = "Remove active Path from active Keying Set";
+
+ /* callbacks */
+ ot->exec = remove_active_ks_path_exec;
+ ot->poll = keyingset_poll_activePath_edit;
}
/* ************************************************** */
@@ -280,184 +278,184 @@ void ANIM_OT_keying_set_path_remove(wmOperatorType *ot)
static int add_keyingset_button_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- KeyingSet *ks = NULL;
- PropertyRNA *prop = NULL;
- PointerRNA ptr = {{NULL}};
- char *path = NULL;
- short success = 0;
- int index = 0, pflag = 0;
- const bool all = RNA_boolean_get(op->ptr, "all");
-
- /* try to add to keyingset using property retrieved from UI */
- if (!UI_context_active_but_prop_get(C, &ptr, &prop, &index)) {
- /* pass event on if no active button found */
- return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
- }
-
- /* verify the Keying Set to use:
- * - use the active one for now (more control over this can be added later)
- * - add a new one if it doesn't exist
- */
- if (scene->active_keyingset == 0) {
- short flag = 0, keyingflag = 0;
-
- /* validate flags
- * - absolute KeyingSets should be created by default
- */
- flag |= KEYINGSET_ABSOLUTE;
-
- keyingflag |= ANIM_get_keyframing_flags(scene, 0);
-
- if (IS_AUTOKEY_FLAG(scene, XYZ2RGB))
- keyingflag |= INSERTKEY_XYZ2RGB;
-
- /* call the API func, and set the active keyingset index */
- ks = BKE_keyingset_add(&scene->keyingsets, "ButtonKeyingSet", "Button Keying Set", flag, keyingflag);
-
- scene->active_keyingset = BLI_listbase_count(&scene->keyingsets);
- }
- else if (scene->active_keyingset < 0) {
- BKE_report(op->reports, RPT_ERROR, "Cannot add property to built in keying set");
- return OPERATOR_CANCELLED;
- }
- else {
- ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1);
- }
-
- /* check if property is able to be added */
- if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
- path = RNA_path_from_ID_to_property(&ptr, prop);
-
- if (path) {
- /* set flags */
- if (all) {
- pflag |= KSP_FLAG_WHOLE_ARRAY;
-
- /* we need to set the index for this to 0, even though it may break in some cases, this is
- * necessary if we want the entire array for most cases to get included without the user
- * having to worry about where they clicked
- */
- index = 0;
- }
-
- /* add path to this setting */
- BKE_keyingset_add_path(ks, ptr.id.data, NULL, path, index, pflag, KSP_GROUP_KSNAME);
- ks->active_path = BLI_listbase_count(&ks->paths);
- success = 1;
-
- /* free the temp path created */
- MEM_freeN(path);
- }
- }
-
- if (success) {
- /* send updates */
- WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
-
- /* show notification/report header, so that users notice that something changed */
- BKE_reportf(op->reports, RPT_INFO, "Property added to Keying Set: '%s'", ks->name);
- }
-
- return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ KeyingSet *ks = NULL;
+ PropertyRNA *prop = NULL;
+ PointerRNA ptr = {{NULL}};
+ char *path = NULL;
+ short success = 0;
+ int index = 0, pflag = 0;
+ const bool all = RNA_boolean_get(op->ptr, "all");
+
+ /* try to add to keyingset using property retrieved from UI */
+ if (!UI_context_active_but_prop_get(C, &ptr, &prop, &index)) {
+ /* pass event on if no active button found */
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+ /* verify the Keying Set to use:
+ * - use the active one for now (more control over this can be added later)
+ * - add a new one if it doesn't exist
+ */
+ if (scene->active_keyingset == 0) {
+ short flag = 0, keyingflag = 0;
+
+ /* validate flags
+ * - absolute KeyingSets should be created by default
+ */
+ flag |= KEYINGSET_ABSOLUTE;
+
+ keyingflag |= ANIM_get_keyframing_flags(scene, 0);
+
+ if (IS_AUTOKEY_FLAG(scene, XYZ2RGB))
+ keyingflag |= INSERTKEY_XYZ2RGB;
+
+ /* call the API func, and set the active keyingset index */
+ ks = BKE_keyingset_add(
+ &scene->keyingsets, "ButtonKeyingSet", "Button Keying Set", flag, keyingflag);
+
+ scene->active_keyingset = BLI_listbase_count(&scene->keyingsets);
+ }
+ else if (scene->active_keyingset < 0) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot add property to built in keying set");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1);
+ }
+
+ /* check if property is able to be added */
+ if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
+ path = RNA_path_from_ID_to_property(&ptr, prop);
+
+ if (path) {
+ /* set flags */
+ if (all) {
+ pflag |= KSP_FLAG_WHOLE_ARRAY;
+
+ /* we need to set the index for this to 0, even though it may break in some cases, this is
+ * necessary if we want the entire array for most cases to get included without the user
+ * having to worry about where they clicked
+ */
+ index = 0;
+ }
+
+ /* add path to this setting */
+ BKE_keyingset_add_path(ks, ptr.id.data, NULL, path, index, pflag, KSP_GROUP_KSNAME);
+ ks->active_path = BLI_listbase_count(&ks->paths);
+ success = 1;
+
+ /* free the temp path created */
+ MEM_freeN(path);
+ }
+ }
+
+ if (success) {
+ /* send updates */
+ WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
+
+ /* show notification/report header, so that users notice that something changed */
+ BKE_reportf(op->reports, RPT_INFO, "Property added to Keying Set: '%s'", ks->name);
+ }
+
+ return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void ANIM_OT_keyingset_button_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add to Keying Set";
- ot->idname = "ANIM_OT_keyingset_button_add";
- ot->description = "Add current UI-active property to current keying set";
+ /* identifiers */
+ ot->name = "Add to Keying Set";
+ ot->idname = "ANIM_OT_keyingset_button_add";
+ ot->description = "Add current UI-active property to current keying set";
- /* callbacks */
- ot->exec = add_keyingset_button_exec;
- //op->poll = ???
+ /* callbacks */
+ ot->exec = add_keyingset_button_exec;
+ //op->poll = ???
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "all", 1, "All", "Add all elements of the array to a Keying Set");
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Add all elements of the array to a Keying Set");
}
/* Remove from KeyingSet Button Operator ------------------------ */
static int remove_keyingset_button_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- KeyingSet *ks = NULL;
- PropertyRNA *prop = NULL;
- PointerRNA ptr = {{NULL}};
- char *path = NULL;
- short success = 0;
- int index = 0;
-
- /* try to add to keyingset using property retrieved from UI */
- if (UI_context_active_but_prop_get(C, &ptr, &prop, &index)) {
- /* pass event on if no active button found */
- return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
- }
-
- /* verify the Keying Set to use:
- * - use the active one for now (more control over this can be added later)
- * - return error if it doesn't exist
- */
- if (scene->active_keyingset == 0) {
- BKE_report(op->reports, RPT_ERROR, "No active keying set to remove property from");
- return OPERATOR_CANCELLED;
- }
- else if (scene->active_keyingset < 0) {
- BKE_report(op->reports, RPT_ERROR, "Cannot remove property from built in keying set");
- return OPERATOR_CANCELLED;
- }
- else {
- ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1);
- }
-
- if (ptr.id.data && ptr.data && prop) {
- path = RNA_path_from_ID_to_property(&ptr, prop);
-
- if (path) {
- KS_Path *ksp;
-
- /* try to find a path matching this description */
- ksp = BKE_keyingset_find_path(ks, ptr.id.data, ks->name, path, index, KSP_GROUP_KSNAME);
-
- if (ksp) {
- BKE_keyingset_free_path(ks, ksp);
- success = 1;
- }
-
- /* free temp path used */
- MEM_freeN(path);
- }
- }
-
-
- if (success) {
- /* send updates */
- WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
-
- /* show warning */
- BKE_report(op->reports, RPT_INFO, "Property removed from Keying Set");
- }
-
- return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ KeyingSet *ks = NULL;
+ PropertyRNA *prop = NULL;
+ PointerRNA ptr = {{NULL}};
+ char *path = NULL;
+ short success = 0;
+ int index = 0;
+
+ /* try to add to keyingset using property retrieved from UI */
+ if (UI_context_active_but_prop_get(C, &ptr, &prop, &index)) {
+ /* pass event on if no active button found */
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+ /* verify the Keying Set to use:
+ * - use the active one for now (more control over this can be added later)
+ * - return error if it doesn't exist
+ */
+ if (scene->active_keyingset == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No active keying set to remove property from");
+ return OPERATOR_CANCELLED;
+ }
+ else if (scene->active_keyingset < 0) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot remove property from built in keying set");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1);
+ }
+
+ if (ptr.id.data && ptr.data && prop) {
+ path = RNA_path_from_ID_to_property(&ptr, prop);
+
+ if (path) {
+ KS_Path *ksp;
+
+ /* try to find a path matching this description */
+ ksp = BKE_keyingset_find_path(ks, ptr.id.data, ks->name, path, index, KSP_GROUP_KSNAME);
+
+ if (ksp) {
+ BKE_keyingset_free_path(ks, ksp);
+ success = 1;
+ }
+
+ /* free temp path used */
+ MEM_freeN(path);
+ }
+ }
+
+ if (success) {
+ /* send updates */
+ WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
+
+ /* show warning */
+ BKE_report(op->reports, RPT_INFO, "Property removed from Keying Set");
+ }
+
+ return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void ANIM_OT_keyingset_button_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove from Keying Set";
- ot->idname = "ANIM_OT_keyingset_button_remove";
- ot->description = "Remove current UI-active property from current keying set";
+ /* identifiers */
+ ot->name = "Remove from Keying Set";
+ ot->idname = "ANIM_OT_keyingset_button_remove";
+ ot->description = "Remove current UI-active property from current keying set";
- /* callbacks */
- ot->exec = remove_keyingset_button_exec;
- //op->poll = ???
+ /* callbacks */
+ ot->exec = remove_keyingset_button_exec;
+ //op->poll = ???
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************************************* */
@@ -467,53 +465,54 @@ void ANIM_OT_keyingset_button_remove(wmOperatorType *ot)
static int keyingset_active_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- uiPopupMenu *pup;
- uiLayout *layout;
+ uiPopupMenu *pup;
+ uiLayout *layout;
- /* call the menu, which will call this operator again, hence the canceled */
- pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
- layout = UI_popup_menu_layout(pup);
- uiItemsEnumO(layout, "ANIM_OT_keying_set_active_set", "type");
- UI_popup_menu_end(C, pup);
+ /* call the menu, which will call this operator again, hence the canceled */
+ pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ uiItemsEnumO(layout, "ANIM_OT_keying_set_active_set", "type");
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
static int keyingset_active_menu_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- int type = RNA_enum_get(op->ptr, "type");
+ Scene *scene = CTX_data_scene(C);
+ int type = RNA_enum_get(op->ptr, "type");
- /* If type == 0, it will deselect any active keying set. */
- scene->active_keyingset = type;
+ /* If type == 0, it will deselect any active keying set. */
+ scene->active_keyingset = type;
- /* send notifiers */
- WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
+ /* send notifiers */
+ WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ANIM_OT_keying_set_active_set(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Set Active Keying Set";
- ot->idname = "ANIM_OT_keying_set_active_set";
- ot->description = "Select a new keying set as the active one";
-
- /* callbacks */
- ot->invoke = keyingset_active_menu_invoke;
- ot->exec = keyingset_active_menu_exec;
- ot->poll = ED_operator_areaactive;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* keyingset to use (dynamic enum) */
- prop = RNA_def_enum(ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
- RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf);
- // RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Set Active Keying Set";
+ ot->idname = "ANIM_OT_keying_set_active_set";
+ ot->description = "Select a new keying set as the active one";
+
+ /* callbacks */
+ ot->invoke = keyingset_active_menu_invoke;
+ ot->exec = keyingset_active_menu_exec;
+ ot->poll = ED_operator_areaactive;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* keyingset to use (dynamic enum) */
+ prop = RNA_def_enum(
+ ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
+ RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf);
+ // RNA_def_property_flag(prop, PROP_HIDDEN);
}
/* ******************************************* */
@@ -530,42 +529,42 @@ ListBase builtin_keyingsets = {NULL, NULL};
/* Find KeyingSet type info given a name */
KeyingSetInfo *ANIM_keyingset_info_find_name(const char name[])
{
- /* sanity checks */
- if ((name == NULL) || (name[0] == 0))
- return NULL;
+ /* sanity checks */
+ if ((name == NULL) || (name[0] == 0))
+ return NULL;
- /* search by comparing names */
- return BLI_findstring(&keyingset_type_infos, name, offsetof(KeyingSetInfo, idname));
+ /* search by comparing names */
+ return BLI_findstring(&keyingset_type_infos, name, offsetof(KeyingSetInfo, idname));
}
/* Find builtin KeyingSet by name */
KeyingSet *ANIM_builtin_keyingset_get_named(KeyingSet *prevKS, const char name[])
{
- KeyingSet *ks, *first = NULL;
+ KeyingSet *ks, *first = NULL;
- /* sanity checks any name to check? */
- if (name[0] == 0)
- return NULL;
+ /* sanity checks any name to check? */
+ if (name[0] == 0)
+ return NULL;
- /* get first KeyingSet to use */
- if (prevKS && prevKS->next)
- first = prevKS->next;
- else
- first = builtin_keyingsets.first;
+ /* get first KeyingSet to use */
+ if (prevKS && prevKS->next)
+ first = prevKS->next;
+ else
+ first = builtin_keyingsets.first;
- /* loop over KeyingSets checking names */
- for (ks = first; ks; ks = ks->next) {
- if (STREQ(name, ks->idname))
- return ks;
- }
+ /* loop over KeyingSets checking names */
+ for (ks = first; ks; ks = ks->next) {
+ if (STREQ(name, ks->idname))
+ return ks;
+ }
- /* complain about missing keying sets on debug builds */
+ /* complain about missing keying sets on debug builds */
#ifndef NDEBUG
- printf("%s: '%s' not found\n", __func__, name);
+ printf("%s: '%s' not found\n", __func__, name);
#endif
- /* no matches found */
- return NULL;
+ /* no matches found */
+ return NULL;
}
/* --------------- */
@@ -573,79 +572,79 @@ KeyingSet *ANIM_builtin_keyingset_get_named(KeyingSet *prevKS, const char name[]
/* Add the given KeyingSetInfo to the list of type infos, and create an appropriate builtin set too */
void ANIM_keyingset_info_register(KeyingSetInfo *ksi)
{
- KeyingSet *ks;
+ KeyingSet *ks;
- /* create a new KeyingSet
- * - inherit name and keyframing settings from the typeinfo
- */
- ks = BKE_keyingset_add(&builtin_keyingsets, ksi->idname, ksi->name, 1, ksi->keyingflag);
+ /* create a new KeyingSet
+ * - inherit name and keyframing settings from the typeinfo
+ */
+ ks = BKE_keyingset_add(&builtin_keyingsets, ksi->idname, ksi->name, 1, ksi->keyingflag);
- /* link this KeyingSet with its typeinfo */
- memcpy(&ks->typeinfo, ksi->idname, sizeof(ks->typeinfo));
+ /* link this KeyingSet with its typeinfo */
+ memcpy(&ks->typeinfo, ksi->idname, sizeof(ks->typeinfo));
- /* Copy description... */
- BLI_strncpy(ks->description, ksi->description, sizeof(ks->description));
+ /* Copy description... */
+ BLI_strncpy(ks->description, ksi->description, sizeof(ks->description));
- /* add type-info to the list */
- BLI_addtail(&keyingset_type_infos, ksi);
+ /* add type-info to the list */
+ BLI_addtail(&keyingset_type_infos, ksi);
}
/* Remove the given KeyingSetInfo from the list of type infos, and also remove the builtin set if appropriate */
void ANIM_keyingset_info_unregister(Main *bmain, KeyingSetInfo *ksi)
{
- KeyingSet *ks, *ksn;
+ KeyingSet *ks, *ksn;
- /* find relevant builtin KeyingSets which use this, and remove them */
- /* TODO: this isn't done now, since unregister is really only used atm when we
- * reload the scripts, which kindof defeats the purpose of "builtin"? */
- for (ks = builtin_keyingsets.first; ks; ks = ksn) {
- ksn = ks->next;
+ /* find relevant builtin KeyingSets which use this, and remove them */
+ /* TODO: this isn't done now, since unregister is really only used atm when we
+ * reload the scripts, which kindof defeats the purpose of "builtin"? */
+ for (ks = builtin_keyingsets.first; ks; ks = ksn) {
+ ksn = ks->next;
- /* remove if matching typeinfo name */
- if (STREQ(ks->typeinfo, ksi->idname)) {
- Scene *scene;
- BKE_keyingset_free(ks);
- BLI_remlink(&builtin_keyingsets, ks);
+ /* remove if matching typeinfo name */
+ if (STREQ(ks->typeinfo, ksi->idname)) {
+ Scene *scene;
+ BKE_keyingset_free(ks);
+ BLI_remlink(&builtin_keyingsets, ks);
- for (scene = bmain->scenes.first; scene; scene = scene->id.next)
- BLI_remlink_safe(&scene->keyingsets, ks);
+ for (scene = bmain->scenes.first; scene; scene = scene->id.next)
+ BLI_remlink_safe(&scene->keyingsets, ks);
- MEM_freeN(ks);
- }
- }
+ MEM_freeN(ks);
+ }
+ }
- /* free the type info */
- BLI_freelinkN(&keyingset_type_infos, ksi);
+ /* free the type info */
+ BLI_freelinkN(&keyingset_type_infos, ksi);
}
/* --------------- */
void ANIM_keyingset_infos_exit(void)
{
- KeyingSetInfo *ksi, *next;
+ KeyingSetInfo *ksi, *next;
- /* free type infos */
- for (ksi = keyingset_type_infos.first; ksi; ksi = next) {
- next = ksi->next;
+ /* free type infos */
+ for (ksi = keyingset_type_infos.first; ksi; ksi = next) {
+ next = ksi->next;
- /* free extra RNA data, and remove from list */
- if (ksi->ext.free)
- ksi->ext.free(ksi->ext.data);
- BLI_freelinkN(&keyingset_type_infos, ksi);
- }
+ /* free extra RNA data, and remove from list */
+ if (ksi->ext.free)
+ ksi->ext.free(ksi->ext.data);
+ BLI_freelinkN(&keyingset_type_infos, ksi);
+ }
- /* free builtin sets */
- BKE_keyingsets_free(&builtin_keyingsets);
+ /* free builtin sets */
+ BKE_keyingsets_free(&builtin_keyingsets);
}
/* Check if the ID appears in the paths specified by the KeyingSet */
bool ANIM_keyingset_find_id(KeyingSet *ks, ID *id)
{
- /* sanity checks */
- if (ELEM(NULL, ks, id))
- return false;
+ /* sanity checks */
+ if (ELEM(NULL, ks, id))
+ return false;
- return BLI_findptr(&ks->paths, id, offsetof(KS_Path, id)) != NULL;
+ return BLI_findptr(&ks->paths, id, offsetof(KS_Path, id)) != NULL;
}
/* ******************************************* */
@@ -656,132 +655,135 @@ bool ANIM_keyingset_find_id(KeyingSet *ks, ID *id)
/* Get the active Keying Set for the Scene provided */
KeyingSet *ANIM_scene_get_active_keyingset(Scene *scene)
{
- /* if no scene, we've got no hope of finding the Keying Set */
- if (scene == NULL)
- return NULL;
-
- /* currently, there are several possibilities here:
- * - 0: no active keying set
- * - > 0: one of the user-defined Keying Sets, but indices start from 0 (hence the -1)
- * - < 0: a builtin keying set
- */
- if (scene->active_keyingset > 0)
- return BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1);
- else
- return BLI_findlink(&builtin_keyingsets, (-scene->active_keyingset) - 1);
+ /* if no scene, we've got no hope of finding the Keying Set */
+ if (scene == NULL)
+ return NULL;
+
+ /* currently, there are several possibilities here:
+ * - 0: no active keying set
+ * - > 0: one of the user-defined Keying Sets, but indices start from 0 (hence the -1)
+ * - < 0: a builtin keying set
+ */
+ if (scene->active_keyingset > 0)
+ return BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1);
+ else
+ return BLI_findlink(&builtin_keyingsets, (-scene->active_keyingset) - 1);
}
/* Get the index of the Keying Set provided, for the given Scene */
int ANIM_scene_get_keyingset_index(Scene *scene, KeyingSet *ks)
{
- int index;
-
- /* if no KeyingSet provided, have none */
- if (ks == NULL)
- return 0;
-
- /* check if the KeyingSet exists in scene list */
- if (scene) {
- /* get index and if valid, return
- * - (absolute) Scene KeyingSets are from (>= 1)
- */
- index = BLI_findindex(&scene->keyingsets, ks);
- if (index != -1)
- return (index + 1);
- }
-
- /* still here, so try builtins list too
- * - builtins are from (<= -1)
- * - none/invalid is (= 0)
- */
- index = BLI_findindex(&builtin_keyingsets, ks);
- if (index != -1)
- return -(index + 1);
- else
- return 0;
+ int index;
+
+ /* if no KeyingSet provided, have none */
+ if (ks == NULL)
+ return 0;
+
+ /* check if the KeyingSet exists in scene list */
+ if (scene) {
+ /* get index and if valid, return
+ * - (absolute) Scene KeyingSets are from (>= 1)
+ */
+ index = BLI_findindex(&scene->keyingsets, ks);
+ if (index != -1)
+ return (index + 1);
+ }
+
+ /* still here, so try builtins list too
+ * - builtins are from (<= -1)
+ * - none/invalid is (= 0)
+ */
+ index = BLI_findindex(&builtin_keyingsets, ks);
+ if (index != -1)
+ return -(index + 1);
+ else
+ return 0;
}
/* Get Keying Set to use for Auto-Keyframing some transforms */
KeyingSet *ANIM_get_keyingset_for_autokeying(Scene *scene, const char *transformKSName)
{
- /* get KeyingSet to use
- * - use the active KeyingSet if defined (and user wants to use it for all autokeying),
- * or otherwise key transforms only
- */
- if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (scene->active_keyingset))
- return ANIM_scene_get_active_keyingset(scene);
- else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL))
- return ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_AVAILABLE_ID);
- else
- return ANIM_builtin_keyingset_get_named(NULL, transformKSName);
+ /* get KeyingSet to use
+ * - use the active KeyingSet if defined (and user wants to use it for all autokeying),
+ * or otherwise key transforms only
+ */
+ if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (scene->active_keyingset))
+ return ANIM_scene_get_active_keyingset(scene);
+ else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL))
+ return ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_AVAILABLE_ID);
+ else
+ return ANIM_builtin_keyingset_get_named(NULL, transformKSName);
}
/* Menu of All Keying Sets ----------------------------- */
/* Dynamically populate an enum of Keying Sets */
-const EnumPropertyItem *ANIM_keying_sets_enum_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+const EnumPropertyItem *ANIM_keying_sets_enum_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- Scene *scene = CTX_data_scene(C);
- KeyingSet *ks;
- EnumPropertyItem *item = NULL, item_tmp = {0};
- int totitem = 0;
- int i = 0;
-
- if (C == NULL) {
- return DummyRNA_DEFAULT_items;
- }
-
- /* active Keying Set
- * - only include entry if it exists
- */
- if (scene->active_keyingset) {
- /* active Keying Set */
- item_tmp.identifier = "__ACTIVE__";
- item_tmp.name = "Active Keying Set";
- item_tmp.value = i;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
-
- /* separator */
- RNA_enum_item_add_separator(&item, &totitem);
- }
-
- i++;
-
- /* user-defined Keying Sets
- * - these are listed in the order in which they were defined for the active scene
- */
- if (scene->keyingsets.first) {
- for (ks = scene->keyingsets.first; ks; ks = ks->next, i++) {
- if (ANIM_keyingset_context_ok_poll(C, ks)) {
- item_tmp.identifier = ks->idname;
- item_tmp.name = ks->name;
- item_tmp.description = ks->description;
- item_tmp.value = i;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- }
- }
-
- /* separator */
- RNA_enum_item_add_separator(&item, &totitem);
- }
-
- /* builtin Keying Sets */
- i = -1;
- for (ks = builtin_keyingsets.first; ks; ks = ks->next, i--) {
- /* only show KeyingSet if context is suitable */
- if (ANIM_keyingset_context_ok_poll(C, ks)) {
- item_tmp.identifier = ks->idname;
- item_tmp.name = ks->name;
- item_tmp.description = ks->description;
- item_tmp.value = i;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- }
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ Scene *scene = CTX_data_scene(C);
+ KeyingSet *ks;
+ EnumPropertyItem *item = NULL, item_tmp = {0};
+ int totitem = 0;
+ int i = 0;
+
+ if (C == NULL) {
+ return DummyRNA_DEFAULT_items;
+ }
+
+ /* active Keying Set
+ * - only include entry if it exists
+ */
+ if (scene->active_keyingset) {
+ /* active Keying Set */
+ item_tmp.identifier = "__ACTIVE__";
+ item_tmp.name = "Active Keying Set";
+ item_tmp.value = i;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+
+ /* separator */
+ RNA_enum_item_add_separator(&item, &totitem);
+ }
+
+ i++;
+
+ /* user-defined Keying Sets
+ * - these are listed in the order in which they were defined for the active scene
+ */
+ if (scene->keyingsets.first) {
+ for (ks = scene->keyingsets.first; ks; ks = ks->next, i++) {
+ if (ANIM_keyingset_context_ok_poll(C, ks)) {
+ item_tmp.identifier = ks->idname;
+ item_tmp.name = ks->name;
+ item_tmp.description = ks->description;
+ item_tmp.value = i;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
+ }
+
+ /* separator */
+ RNA_enum_item_add_separator(&item, &totitem);
+ }
+
+ /* builtin Keying Sets */
+ i = -1;
+ for (ks = builtin_keyingsets.first; ks; ks = ks->next, i--) {
+ /* only show KeyingSet if context is suitable */
+ if (ANIM_keyingset_context_ok_poll(C, ks)) {
+ item_tmp.identifier = ks->idname;
+ item_tmp.name = ks->name;
+ item_tmp.description = ks->description;
+ item_tmp.value = i;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
/**
@@ -794,28 +796,28 @@ const EnumPropertyItem *ANIM_keying_sets_enum_itemf(bContext *C, PointerRNA *UNU
*/
KeyingSet *ANIM_keyingset_get_from_enum_type(Scene *scene, int type)
{
- KeyingSet *ks = NULL;
-
- if (type == 0) {
- type = scene->active_keyingset;
- }
-
- if (type > 0) {
- ks = BLI_findlink(&scene->keyingsets, type - 1);
- }
- else {
- ks = BLI_findlink(&builtin_keyingsets, -type - 1);
- }
- return ks;
+ KeyingSet *ks = NULL;
+
+ if (type == 0) {
+ type = scene->active_keyingset;
+ }
+
+ if (type > 0) {
+ ks = BLI_findlink(&scene->keyingsets, type - 1);
+ }
+ else {
+ ks = BLI_findlink(&builtin_keyingsets, -type - 1);
+ }
+ return ks;
}
KeyingSet *ANIM_keyingset_get_from_idname(Scene *scene, const char *idname)
{
- KeyingSet *ks = BLI_findstring(&scene->keyingsets, idname, offsetof(KeyingSet, idname));
- if (ks == NULL) {
- ks = BLI_findstring(&builtin_keyingsets, idname, offsetof(KeyingSet, idname));
- }
- return ks;
+ KeyingSet *ks = BLI_findstring(&scene->keyingsets, idname, offsetof(KeyingSet, idname));
+ if (ks == NULL) {
+ ks = BLI_findstring(&builtin_keyingsets, idname, offsetof(KeyingSet, idname));
+ }
+ return ks;
}
/* ******************************************* */
@@ -826,19 +828,19 @@ KeyingSet *ANIM_keyingset_get_from_idname(Scene *scene, const char *idname)
/* Check if KeyingSet can be used in the current context */
bool ANIM_keyingset_context_ok_poll(bContext *C, KeyingSet *ks)
{
- if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
- KeyingSetInfo *ksi = ANIM_keyingset_info_find_name(ks->typeinfo);
+ if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
+ KeyingSetInfo *ksi = ANIM_keyingset_info_find_name(ks->typeinfo);
- /* get the associated 'type info' for this KeyingSet */
- if (ksi == NULL)
- return 0;
- /* TODO: check for missing callbacks! */
+ /* get the associated 'type info' for this KeyingSet */
+ if (ksi == NULL)
+ return 0;
+ /* TODO: check for missing callbacks! */
- /* check if it can be used in the current context */
- return (ksi->poll(ksi, C));
- }
+ /* check if it can be used in the current context */
+ return (ksi->poll(ksi, C));
+ }
- return true;
+ return true;
}
/* Special 'Overrides' Iterator for Relative KeyingSets ------ */
@@ -848,48 +850,50 @@ bool ANIM_keyingset_context_ok_poll(bContext *C, KeyingSet *ks)
* - do not allow this to be accessed from outside for now
*/
typedef struct tRKS_DSource {
- struct tRKS_DSource *next, *prev;
- PointerRNA ptr; /* the whole point of this exercise! */
+ struct tRKS_DSource *next, *prev;
+ PointerRNA ptr; /* the whole point of this exercise! */
} tRKS_DSource;
-
/* Iterator used for overriding the behavior of iterators defined for
* relative Keying Sets, with the main usage of this being operators
* requiring Auto Keyframing. Internal Use Only!
*/
-static void RKS_ITER_overrides_list(KeyingSetInfo *ksi, bContext *C, KeyingSet *ks, ListBase *dsources)
+static void RKS_ITER_overrides_list(KeyingSetInfo *ksi,
+ bContext *C,
+ KeyingSet *ks,
+ ListBase *dsources)
{
- tRKS_DSource *ds;
+ tRKS_DSource *ds;
- for (ds = dsources->first; ds; ds = ds->next) {
- /* run generate callback on this data */
- ksi->generate(ksi, C, ks, &ds->ptr);
- }
+ for (ds = dsources->first; ds; ds = ds->next) {
+ /* run generate callback on this data */
+ ksi->generate(ksi, C, ks, &ds->ptr);
+ }
}
/* Add new data source for relative Keying Sets */
void ANIM_relative_keyingset_add_source(ListBase *dsources, ID *id, StructRNA *srna, void *data)
{
- tRKS_DSource *ds;
-
- /* sanity checks
- * - we must have somewhere to output the data
- * - we must have both srna+data (and with id too optionally), or id by itself only
- */
- if (dsources == NULL)
- return;
- if (ELEM(NULL, srna, data) && (id == NULL))
- return;
-
- /* allocate new elem, and add to the list */
- ds = MEM_callocN(sizeof(tRKS_DSource), "tRKS_DSource");
- BLI_addtail(dsources, ds);
-
- /* depending on what data we have, create using ID or full pointer call */
- if (srna && data)
- RNA_pointer_create(id, srna, data, &ds->ptr);
- else
- RNA_id_pointer_create(id, &ds->ptr);
+ tRKS_DSource *ds;
+
+ /* sanity checks
+ * - we must have somewhere to output the data
+ * - we must have both srna+data (and with id too optionally), or id by itself only
+ */
+ if (dsources == NULL)
+ return;
+ if (ELEM(NULL, srna, data) && (id == NULL))
+ return;
+
+ /* allocate new elem, and add to the list */
+ ds = MEM_callocN(sizeof(tRKS_DSource), "tRKS_DSource");
+ BLI_addtail(dsources, ds);
+
+ /* depending on what data we have, create using ID or full pointer call */
+ if (srna && data)
+ RNA_pointer_create(id, srna, data, &ds->ptr);
+ else
+ RNA_id_pointer_create(id, &ds->ptr);
}
/* KeyingSet Operations (Insert/Delete Keyframes) ------------ */
@@ -903,198 +907,216 @@ void ANIM_relative_keyingset_add_source(ListBase *dsources, ID *id, StructRNA *s
*/
short ANIM_validate_keyingset(bContext *C, ListBase *dsources, KeyingSet *ks)
{
- /* sanity check */
- if (ks == NULL)
- return 0;
-
- /* if relative Keying Sets, poll and build up the paths */
- if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
- KeyingSetInfo *ksi = ANIM_keyingset_info_find_name(ks->typeinfo);
-
- /* clear all existing paths
- * NOTE: BKE_keyingset_free() frees all of the paths for the KeyingSet, but not the set itself
- */
- BKE_keyingset_free(ks);
-
- /* get the associated 'type info' for this KeyingSet */
- if (ksi == NULL)
- return MODIFYKEY_MISSING_TYPEINFO;
- /* TODO: check for missing callbacks! */
-
- /* check if it can be used in the current context */
- if (ksi->poll(ksi, C)) {
- /* if a list of data sources are provided, run a special iterator over them,
- * otherwise, just continue per normal
- */
- if (dsources)
- RKS_ITER_overrides_list(ksi, C, ks, dsources);
- else
- ksi->iter(ksi, C, ks);
-
- /* if we don't have any paths now, then this still qualifies as invalid context */
- // FIXME: we need some error conditions (to be retrieved from the iterator why this failed!)
- if (BLI_listbase_is_empty(&ks->paths))
- return MODIFYKEY_INVALID_CONTEXT;
- }
- else {
- /* poll callback tells us that KeyingSet is useless in current context */
- // FIXME: the poll callback needs to give us more info why
- return MODIFYKEY_INVALID_CONTEXT;
- }
- }
-
- /* succeeded; return 0 to tag error free */
- return 0;
+ /* sanity check */
+ if (ks == NULL)
+ return 0;
+
+ /* if relative Keying Sets, poll and build up the paths */
+ if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
+ KeyingSetInfo *ksi = ANIM_keyingset_info_find_name(ks->typeinfo);
+
+ /* clear all existing paths
+ * NOTE: BKE_keyingset_free() frees all of the paths for the KeyingSet, but not the set itself
+ */
+ BKE_keyingset_free(ks);
+
+ /* get the associated 'type info' for this KeyingSet */
+ if (ksi == NULL)
+ return MODIFYKEY_MISSING_TYPEINFO;
+ /* TODO: check for missing callbacks! */
+
+ /* check if it can be used in the current context */
+ if (ksi->poll(ksi, C)) {
+ /* if a list of data sources are provided, run a special iterator over them,
+ * otherwise, just continue per normal
+ */
+ if (dsources)
+ RKS_ITER_overrides_list(ksi, C, ks, dsources);
+ else
+ ksi->iter(ksi, C, ks);
+
+ /* if we don't have any paths now, then this still qualifies as invalid context */
+ // FIXME: we need some error conditions (to be retrieved from the iterator why this failed!)
+ if (BLI_listbase_is_empty(&ks->paths))
+ return MODIFYKEY_INVALID_CONTEXT;
+ }
+ else {
+ /* poll callback tells us that KeyingSet is useless in current context */
+ // FIXME: the poll callback needs to give us more info why
+ return MODIFYKEY_INVALID_CONTEXT;
+ }
+ }
+
+ /* succeeded; return 0 to tag error free */
+ return 0;
}
/* 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 short keyingset_apply_keying_flags(const short base_flags,
+ const short overrides,
+ const short own_flags)
{
- /* Pass through all flags by default (i.e. even not explicitly listed ones). */
- short 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
- * status of that flag in "own_flags" is used
- * - If however the flag isn't set, then its value in "base_flags" is used
- * instead (i.e. no override)
- */
+ /* Pass through all flags by default (i.e. even not explicitly listed ones). */
+ short 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
+ * status of that flag in "own_flags" is used
+ * - If however the flag isn't set, then its value in "base_flags" is used
+ * instead (i.e. no override)
+ */
#define APPLY_KEYINGFLAG_OVERRIDE(kflag) \
- if (overrides & kflag) { \
- result &= ~kflag; \
- result |= (own_flags & kflag); \
- }
-
- /* Apply the flags one by one...
- * (See rna_def_common_keying_flags() for the supported flags)
- */
- APPLY_KEYINGFLAG_OVERRIDE(INSERTKEY_NEEDED)
- APPLY_KEYINGFLAG_OVERRIDE(INSERTKEY_MATRIX)
- APPLY_KEYINGFLAG_OVERRIDE(INSERTKEY_XYZ2RGB)
+ if (overrides & kflag) { \
+ result &= ~kflag; \
+ result |= (own_flags & kflag); \
+ }
+
+ /* Apply the flags one by one...
+ * (See rna_def_common_keying_flags() for the supported flags)
+ */
+ APPLY_KEYINGFLAG_OVERRIDE(INSERTKEY_NEEDED)
+ APPLY_KEYINGFLAG_OVERRIDE(INSERTKEY_MATRIX)
+ APPLY_KEYINGFLAG_OVERRIDE(INSERTKEY_XYZ2RGB)
#undef APPLY_KEYINGFLAG_OVERRIDE
- return result;
+ return result;
}
/* 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
*/
-int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra)
+int ANIM_apply_keyingset(
+ bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- 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 char *groupname = NULL;
- short kflag = 0, success = 0;
- char keytype = scene->toolsettings->keyframe_type;
-
- /* sanity checks */
- if (ks == NULL)
- return 0;
-
- /* get flags to use */
- if (mode == MODIFYKEY_MODE_INSERT) {
- /* use context settings as base */
- kflag = keyingset_apply_keying_flags(base_kflags, ks->keyingoverride, ks->keyingflag);
- }
- else if (mode == MODIFYKEY_MODE_DELETE)
- kflag = 0;
-
- /* 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;
- }
-
- /* apply the paths as specified in the KeyingSet now */
- for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
- int arraylen, i;
- short kflag2;
-
- /* skip path if no ID pointer is specified */
- if (ksp->id == NULL) {
- BKE_reportf(reports, RPT_WARNING,
- "Skipping path in keying set, as it has no ID (KS = '%s', path = '%s[%d]')",
- ks->name, ksp->rna_path, ksp->array_index);
- continue;
- }
-
- /* since keying settings can be defined on the paths too, apply the settings for this path first */
- kflag2 = keyingset_apply_keying_flags(kflag, ksp->keyingoverride, ksp->keyingflag);
-
- /* get pointer to name of group to add channels to */
- if (ksp->groupmode == KSP_GROUP_NONE)
- groupname = NULL;
- else if (ksp->groupmode == KSP_GROUP_KSNAME)
- groupname = ks->name;
- else
- groupname = ksp->group;
-
- /* init arraylen and i - arraylen should be greater than i so that
- * normal non-array entries get keyframed correctly
- */
- i = ksp->array_index;
- arraylen = i;
-
- /* get length of array if whole array option is enabled */
- if (ksp->flag & KSP_FLAG_WHOLE_ARRAY) {
- PointerRNA id_ptr, ptr;
- PropertyRNA *prop;
-
- RNA_id_pointer_create(ksp->id, &id_ptr);
- if (RNA_path_resolve_property(&id_ptr, ksp->rna_path, &ptr, &prop)) {
- arraylen = RNA_property_array_length(&ptr, prop);
- /* start from start of array, instead of the previously specified index - T48020 */
- i = 0;
- }
- }
-
- /* we should do at least one step */
- if (arraylen == i)
- arraylen++;
-
- /* for each possible index, perform operation
- * - assume that arraylen is greater than index
- */
- for (; i < arraylen; i++) {
- /* action to take depends on mode */
- if (mode == MODIFYKEY_MODE_INSERT)
- success += insert_keyframe(bmain, depsgraph, 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);
- }
-
- /* set recalc-flags */
- switch (GS(ksp->id->name)) {
- case ID_OB: /* Object (or Object-Related) Keyframes */
- {
- Object *ob = (Object *)ksp->id;
-
- // XXX: only object transforms?
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- break;
- }
- default:
- DEG_id_tag_update(ksp->id, ID_RECALC_ANIMATION_NO_FLUSH);
- break;
- }
-
- /* send notifiers for updates (this doesn't require context to work!) */
- WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
- }
-
- BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
-
- /* return the number of channels successfully affected */
- return success;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ 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 char *groupname = NULL;
+ short kflag = 0, success = 0;
+ char keytype = scene->toolsettings->keyframe_type;
+
+ /* sanity checks */
+ if (ks == NULL)
+ return 0;
+
+ /* get flags to use */
+ if (mode == MODIFYKEY_MODE_INSERT) {
+ /* use context settings as base */
+ kflag = keyingset_apply_keying_flags(base_kflags, ks->keyingoverride, ks->keyingflag);
+ }
+ else if (mode == MODIFYKEY_MODE_DELETE)
+ kflag = 0;
+
+ /* 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;
+ }
+
+ /* apply the paths as specified in the KeyingSet now */
+ for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
+ int arraylen, i;
+ short kflag2;
+
+ /* skip path if no ID pointer is specified */
+ if (ksp->id == NULL) {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Skipping path in keying set, as it has no ID (KS = '%s', path = '%s[%d]')",
+ ks->name,
+ ksp->rna_path,
+ ksp->array_index);
+ continue;
+ }
+
+ /* since keying settings can be defined on the paths too, apply the settings for this path first */
+ kflag2 = keyingset_apply_keying_flags(kflag, ksp->keyingoverride, ksp->keyingflag);
+
+ /* get pointer to name of group to add channels to */
+ if (ksp->groupmode == KSP_GROUP_NONE)
+ groupname = NULL;
+ else if (ksp->groupmode == KSP_GROUP_KSNAME)
+ groupname = ks->name;
+ else
+ groupname = ksp->group;
+
+ /* init arraylen and i - arraylen should be greater than i so that
+ * normal non-array entries get keyframed correctly
+ */
+ i = ksp->array_index;
+ arraylen = i;
+
+ /* get length of array if whole array option is enabled */
+ if (ksp->flag & KSP_FLAG_WHOLE_ARRAY) {
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+
+ RNA_id_pointer_create(ksp->id, &id_ptr);
+ if (RNA_path_resolve_property(&id_ptr, ksp->rna_path, &ptr, &prop)) {
+ arraylen = RNA_property_array_length(&ptr, prop);
+ /* start from start of array, instead of the previously specified index - T48020 */
+ i = 0;
+ }
+ }
+
+ /* we should do at least one step */
+ if (arraylen == i)
+ arraylen++;
+
+ /* for each possible index, perform operation
+ * - assume that arraylen is greater than index
+ */
+ for (; i < arraylen; i++) {
+ /* action to take depends on mode */
+ if (mode == MODIFYKEY_MODE_INSERT)
+ success += insert_keyframe(bmain,
+ depsgraph,
+ 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);
+ }
+
+ /* set recalc-flags */
+ switch (GS(ksp->id->name)) {
+ case ID_OB: /* Object (or Object-Related) Keyframes */
+ {
+ Object *ob = (Object *)ksp->id;
+
+ // XXX: only object transforms?
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ break;
+ }
+ default:
+ DEG_id_tag_update(ksp->id, ID_RECALC_ANIMATION_NO_FLUSH);
+ break;
+ }
+
+ /* send notifiers for updates (this doesn't require context to work!) */
+ WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
+ }
+
+ BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
+
+ /* return the number of channels successfully affected */
+ return success;
}
/* ************************************************** */
diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt
index 27eddd7e1dd..274fa86184d 100644
--- a/source/blender/editors/armature/CMakeLists.txt
+++ b/source/blender/editors/armature/CMakeLists.txt
@@ -16,55 +16,55 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../depsgraph
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/clog
- ../../../../intern/guardedalloc
- ../../../../intern/eigen
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../depsgraph
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/clog
+ ../../../../intern/guardedalloc
+ ../../../../intern/eigen
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- armature_add.c
- armature_edit.c
- armature_naming.c
- armature_ops.c
- armature_relations.c
- armature_select.c
- armature_skinning.c
- armature_utils.c
- editarmature_undo.c
- meshlaplacian.c
- pose_edit.c
- pose_group.c
- pose_lib.c
- pose_select.c
- pose_slide.c
- pose_transform.c
- pose_utils.c
+ armature_add.c
+ armature_edit.c
+ armature_naming.c
+ armature_ops.c
+ armature_relations.c
+ armature_select.c
+ armature_skinning.c
+ armature_utils.c
+ editarmature_undo.c
+ meshlaplacian.c
+ pose_edit.c
+ pose_group.c
+ pose_lib.c
+ pose_select.c
+ pose_slide.c
+ pose_transform.c
+ pose_utils.c
- armature_intern.h
- meshlaplacian.h
+ armature_intern.h
+ meshlaplacian.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
+ bf_blenkernel
+ bf_blenlib
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index 20978a42812..6943d6bdc54 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -59,59 +59,58 @@
/* XXX should be used everywhere, now it mallocs bones still locally in functions */
EditBone *ED_armature_ebone_add(bArmature *arm, const char *name)
{
- EditBone *bone = MEM_callocN(sizeof(EditBone), "eBone");
-
- BLI_strncpy(bone->name, name, sizeof(bone->name));
- ED_armature_ebone_unique_name(arm->edbo, bone->name, NULL);
-
- BLI_addtail(arm->edbo, bone);
-
- bone->flag |= BONE_TIPSEL;
- bone->weight = 1.0f;
- bone->dist = 0.25f;
- bone->xwidth = 0.1f;
- bone->zwidth = 0.1f;
- bone->rad_head = 0.10f;
- bone->rad_tail = 0.05f;
- bone->segments = 1;
- bone->layer = arm->layer;
-
- /* Bendy-Bone parameters */
- bone->roll1 = 0.0f;
- bone->roll2 = 0.0f;
- bone->curveInX = 0.0f;
- bone->curveInY = 0.0f;
- bone->curveOutX = 0.0f;
- bone->curveOutY = 0.0f;
- bone->ease1 = 1.0f;
- bone->ease2 = 1.0f;
- bone->scaleIn = 1.0f;
- bone->scaleOut = 1.0f;
-
- return bone;
+ EditBone *bone = MEM_callocN(sizeof(EditBone), "eBone");
+
+ BLI_strncpy(bone->name, name, sizeof(bone->name));
+ ED_armature_ebone_unique_name(arm->edbo, bone->name, NULL);
+
+ BLI_addtail(arm->edbo, bone);
+
+ bone->flag |= BONE_TIPSEL;
+ bone->weight = 1.0f;
+ bone->dist = 0.25f;
+ bone->xwidth = 0.1f;
+ bone->zwidth = 0.1f;
+ bone->rad_head = 0.10f;
+ bone->rad_tail = 0.05f;
+ bone->segments = 1;
+ bone->layer = arm->layer;
+
+ /* Bendy-Bone parameters */
+ bone->roll1 = 0.0f;
+ bone->roll2 = 0.0f;
+ bone->curveInX = 0.0f;
+ bone->curveInY = 0.0f;
+ bone->curveOutX = 0.0f;
+ bone->curveOutY = 0.0f;
+ bone->ease1 = 1.0f;
+ bone->ease2 = 1.0f;
+ bone->scaleIn = 1.0f;
+ bone->scaleOut = 1.0f;
+
+ return bone;
}
EditBone *ED_armature_ebone_add_primitive(Object *obedit_arm, float length, bool view_aligned)
{
- bArmature *arm = obedit_arm->data;
- EditBone *bone;
+ bArmature *arm = obedit_arm->data;
+ EditBone *bone;
- ED_armature_edit_deselect_all(obedit_arm);
+ ED_armature_edit_deselect_all(obedit_arm);
- /* Create a bone */
- bone = ED_armature_ebone_add(arm, "Bone");
+ /* Create a bone */
+ bone = ED_armature_ebone_add(arm, "Bone");
- arm->act_edbone = bone;
+ arm->act_edbone = bone;
- zero_v3(bone->head);
- zero_v3(bone->tail);
+ zero_v3(bone->head);
+ zero_v3(bone->tail);
- bone->tail[view_aligned ? 1 : 2] = length;
+ bone->tail[view_aligned ? 1 : 2] = length;
- return bone;
+ return bone;
}
-
/* previously addvert_armature */
/* the ctrl-click method */
@@ -124,517 +123,520 @@ EditBone *ED_armature_ebone_add_primitive(Object *obedit_arm, float length, bool
*/
static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
{
- bArmature *arm;
- EditBone *ebone, *newbone, *flipbone;
- float mat[3][3], imat[3][3];
- int a, to_root = 0;
- Object *obedit;
- Scene *scene;
-
- scene = CTX_data_scene(C);
- obedit = CTX_data_edit_object(C);
- arm = obedit->data;
-
- /* find the active or selected bone */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone)) {
- if (ebone->flag & BONE_TIPSEL || arm->act_edbone == ebone)
- break;
- }
- }
-
- if (ebone == NULL) {
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone)) {
- if (ebone->flag & BONE_ROOTSEL || arm->act_edbone == ebone)
- break;
- }
- }
- if (ebone == NULL)
- return OPERATOR_CANCELLED;
-
- to_root = 1;
- }
-
- ED_armature_edit_deselect_all(obedit);
-
- /* we re-use code for mirror editing... */
- flipbone = NULL;
- if (arm->flag & ARM_MIRROR_EDIT)
- flipbone = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
-
- for (a = 0; a < 2; a++) {
- if (a == 1) {
- if (flipbone == NULL)
- break;
- else {
- SWAP(EditBone *, flipbone, ebone);
- }
- }
-
- newbone = ED_armature_ebone_add(arm, ebone->name);
- arm->act_edbone = newbone;
-
- if (to_root) {
- copy_v3_v3(newbone->head, ebone->head);
- newbone->rad_head = ebone->rad_tail;
- newbone->parent = ebone->parent;
- }
- else {
- copy_v3_v3(newbone->head, ebone->tail);
- newbone->rad_head = ebone->rad_tail;
- newbone->parent = ebone;
- newbone->flag |= BONE_CONNECTED;
- }
-
- const View3DCursor *curs = &scene->cursor;
- copy_v3_v3(newbone->tail, curs->location);
- sub_v3_v3v3(newbone->tail, newbone->tail, obedit->obmat[3]);
-
- if (a == 1)
- newbone->tail[0] = -newbone->tail[0];
-
- copy_m3_m4(mat, obedit->obmat);
- invert_m3_m3(imat, mat);
- mul_m3_v3(imat, newbone->tail);
-
- newbone->length = len_v3v3(newbone->head, newbone->tail);
- newbone->rad_tail = newbone->length * 0.05f;
- newbone->dist = newbone->length * 0.25f;
-
- }
-
- ED_armature_edit_sync_selection(arm->edbo);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
-
- return OPERATOR_FINISHED;
+ bArmature *arm;
+ EditBone *ebone, *newbone, *flipbone;
+ float mat[3][3], imat[3][3];
+ int a, to_root = 0;
+ Object *obedit;
+ Scene *scene;
+
+ scene = CTX_data_scene(C);
+ obedit = CTX_data_edit_object(C);
+ arm = obedit->data;
+
+ /* find the active or selected bone */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (ebone->flag & BONE_TIPSEL || arm->act_edbone == ebone)
+ break;
+ }
+ }
+
+ if (ebone == NULL) {
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (ebone->flag & BONE_ROOTSEL || arm->act_edbone == ebone)
+ break;
+ }
+ }
+ if (ebone == NULL)
+ return OPERATOR_CANCELLED;
+
+ to_root = 1;
+ }
+
+ ED_armature_edit_deselect_all(obedit);
+
+ /* we re-use code for mirror editing... */
+ flipbone = NULL;
+ if (arm->flag & ARM_MIRROR_EDIT)
+ flipbone = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
+
+ for (a = 0; a < 2; a++) {
+ if (a == 1) {
+ if (flipbone == NULL)
+ break;
+ else {
+ SWAP(EditBone *, flipbone, ebone);
+ }
+ }
+
+ newbone = ED_armature_ebone_add(arm, ebone->name);
+ arm->act_edbone = newbone;
+
+ if (to_root) {
+ copy_v3_v3(newbone->head, ebone->head);
+ newbone->rad_head = ebone->rad_tail;
+ newbone->parent = ebone->parent;
+ }
+ else {
+ copy_v3_v3(newbone->head, ebone->tail);
+ newbone->rad_head = ebone->rad_tail;
+ newbone->parent = ebone;
+ newbone->flag |= BONE_CONNECTED;
+ }
+
+ const View3DCursor *curs = &scene->cursor;
+ copy_v3_v3(newbone->tail, curs->location);
+ sub_v3_v3v3(newbone->tail, newbone->tail, obedit->obmat[3]);
+
+ if (a == 1)
+ newbone->tail[0] = -newbone->tail[0];
+
+ copy_m3_m4(mat, obedit->obmat);
+ invert_m3_m3(imat, mat);
+ mul_m3_v3(imat, newbone->tail);
+
+ newbone->length = len_v3v3(newbone->head, newbone->tail);
+ newbone->rad_tail = newbone->length * 0.05f;
+ newbone->dist = newbone->length * 0.25f;
+ }
+
+ ED_armature_edit_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
}
static int armature_click_extrude_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- /* TODO most of this code is copied from set3dcursor_invoke,
- * it would be better to reuse code in set3dcursor_invoke */
+ /* TODO most of this code is copied from set3dcursor_invoke,
+ * it would be better to reuse code in set3dcursor_invoke */
- /* temporarily change 3d cursor position */
- Scene *scene;
- ARegion *ar;
- View3D *v3d;
- float tvec[3], oldcurs[3], mval_f[2];
- int retv;
+ /* temporarily change 3d cursor position */
+ Scene *scene;
+ ARegion *ar;
+ View3D *v3d;
+ float tvec[3], oldcurs[3], mval_f[2];
+ int retv;
- scene = CTX_data_scene(C);
- ar = CTX_wm_region(C);
- v3d = CTX_wm_view3d(C);
+ scene = CTX_data_scene(C);
+ ar = CTX_wm_region(C);
+ v3d = CTX_wm_view3d(C);
- View3DCursor *cursor = &scene->cursor;
+ View3DCursor *cursor = &scene->cursor;
- copy_v3_v3(oldcurs, cursor->location);
+ 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);
- copy_v3_v3(cursor->location, tvec);
+ copy_v2fl_v2i(mval_f, event->mval);
+ ED_view3d_win_to_3d(v3d, ar, cursor->location, mval_f, tvec);
+ copy_v3_v3(cursor->location, tvec);
- /* extrude to the where new cursor is and store the operation result */
- retv = armature_click_extrude_exec(C, op);
+ /* extrude to the where new cursor is and store the operation result */
+ retv = armature_click_extrude_exec(C, op);
- /* restore previous 3d cursor position */
- copy_v3_v3(cursor->location, oldcurs);
+ /* restore previous 3d cursor position */
+ copy_v3_v3(cursor->location, oldcurs);
- return retv;
+ return retv;
}
void ARMATURE_OT_click_extrude(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Click-Extrude";
- ot->idname = "ARMATURE_OT_click_extrude";
- ot->description = "Create a new bone going from the last selected joint to the mouse position";
+ /* identifiers */
+ ot->name = "Click-Extrude";
+ ot->idname = "ARMATURE_OT_click_extrude";
+ ot->description = "Create a new bone going from the last selected joint to the mouse position";
- /* api callbacks */
- ot->invoke = armature_click_extrude_invoke;
- ot->exec = armature_click_extrude_exec;
- ot->poll = ED_operator_editarmature;
+ /* api callbacks */
+ ot->invoke = armature_click_extrude_invoke;
+ ot->exec = armature_click_extrude_exec;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
+ /* props */
}
/* adds an EditBone between the nominated locations (should be in the right space) */
EditBone *add_points_bone(Object *obedit, float head[3], float tail[3])
{
- EditBone *ebo;
+ EditBone *ebo;
- ebo = ED_armature_ebone_add(obedit->data, "Bone");
+ ebo = ED_armature_ebone_add(obedit->data, "Bone");
- copy_v3_v3(ebo->head, head);
- copy_v3_v3(ebo->tail, tail);
+ copy_v3_v3(ebo->head, head);
+ copy_v3_v3(ebo->tail, tail);
- return ebo;
+ return ebo;
}
-
static EditBone *get_named_editbone(ListBase *edbo, const char *name)
{
- EditBone *eBone;
+ EditBone *eBone;
- if (name) {
- for (eBone = edbo->first; eBone; eBone = eBone->next) {
- if (STREQ(name, eBone->name))
- return eBone;
- }
- }
+ if (name) {
+ for (eBone = edbo->first; eBone; eBone = eBone->next) {
+ if (STREQ(name, eBone->name))
+ return eBone;
+ }
+ }
- return NULL;
+ return NULL;
}
/* Call this before doing any duplications
* */
void preEditBoneDuplicate(ListBase *editbones)
{
- /* clear temp */
- ED_armature_ebone_listbase_temp_clear(editbones);
+ /* clear temp */
+ ED_armature_ebone_listbase_temp_clear(editbones);
}
/**
* Helper function for #postEditBoneDuplicate,
* return the destination pchan from the original.
*/
-static bPoseChannel *pchan_duplicate_map(const bPose *pose, GHash *name_map, bPoseChannel *pchan_src)
+static bPoseChannel *pchan_duplicate_map(const bPose *pose,
+ GHash *name_map,
+ bPoseChannel *pchan_src)
{
- bPoseChannel *pchan_dst = NULL;
- const char *name_src = pchan_src->name;
- const char *name_dst = BLI_ghash_lookup(name_map, name_src);
- if (name_dst) {
- pchan_dst = BKE_pose_channel_find_name(pose, name_dst);
- }
-
- if (pchan_dst == NULL) {
- pchan_dst = pchan_src;
- }
-
- return pchan_dst;
+ bPoseChannel *pchan_dst = NULL;
+ const char *name_src = pchan_src->name;
+ const char *name_dst = BLI_ghash_lookup(name_map, name_src);
+ if (name_dst) {
+ pchan_dst = BKE_pose_channel_find_name(pose, name_dst);
+ }
+
+ if (pchan_dst == NULL) {
+ pchan_dst = pchan_src;
+ }
+
+ return pchan_dst;
}
void postEditBoneDuplicate(struct ListBase *editbones, Object *ob)
{
- if (ob->pose == NULL) {
- return;
- }
-
- BKE_pose_channels_hash_free(ob->pose);
- BKE_pose_channels_hash_make(ob->pose);
-
- GHash *name_map = BLI_ghash_str_new(__func__);
-
- for (EditBone *ebone_src = editbones->first; ebone_src; ebone_src = ebone_src->next) {
- EditBone *ebone_dst = ebone_src->temp.ebone;
- if (!ebone_dst) {
- ebone_dst = ED_armature_ebone_get_mirrored(editbones, ebone_src);
- }
- if (ebone_dst) {
- BLI_ghash_insert(name_map, ebone_src->name, ebone_dst->name);
- }
- }
-
- for (EditBone *ebone_src = editbones->first; ebone_src; ebone_src = ebone_src->next) {
- EditBone *ebone_dst = ebone_src->temp.ebone;
- if (ebone_dst) {
- bPoseChannel *pchan_src = BKE_pose_channel_find_name(ob->pose, ebone_src->name);
- if (pchan_src) {
- bPoseChannel *pchan_dst = BKE_pose_channel_find_name(ob->pose, ebone_dst->name);
- if (pchan_dst) {
- if (pchan_src->custom_tx) {
- pchan_dst->custom_tx = pchan_duplicate_map(ob->pose, name_map, pchan_src->custom_tx);
- }
- if (pchan_src->bbone_prev) {
- pchan_dst->bbone_prev = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_prev);
- }
- if (pchan_src->bbone_next) {
- pchan_dst->bbone_next = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_next);
- }
- }
- }
- }
- }
-
- BLI_ghash_free(name_map, NULL, NULL);
+ if (ob->pose == NULL) {
+ return;
+ }
+
+ BKE_pose_channels_hash_free(ob->pose);
+ BKE_pose_channels_hash_make(ob->pose);
+
+ GHash *name_map = BLI_ghash_str_new(__func__);
+
+ for (EditBone *ebone_src = editbones->first; ebone_src; ebone_src = ebone_src->next) {
+ EditBone *ebone_dst = ebone_src->temp.ebone;
+ if (!ebone_dst) {
+ ebone_dst = ED_armature_ebone_get_mirrored(editbones, ebone_src);
+ }
+ if (ebone_dst) {
+ BLI_ghash_insert(name_map, ebone_src->name, ebone_dst->name);
+ }
+ }
+
+ for (EditBone *ebone_src = editbones->first; ebone_src; ebone_src = ebone_src->next) {
+ EditBone *ebone_dst = ebone_src->temp.ebone;
+ if (ebone_dst) {
+ bPoseChannel *pchan_src = BKE_pose_channel_find_name(ob->pose, ebone_src->name);
+ if (pchan_src) {
+ bPoseChannel *pchan_dst = BKE_pose_channel_find_name(ob->pose, ebone_dst->name);
+ if (pchan_dst) {
+ if (pchan_src->custom_tx) {
+ pchan_dst->custom_tx = pchan_duplicate_map(ob->pose, name_map, pchan_src->custom_tx);
+ }
+ if (pchan_src->bbone_prev) {
+ pchan_dst->bbone_prev = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_prev);
+ }
+ if (pchan_src->bbone_next) {
+ pchan_dst->bbone_next = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_next);
+ }
+ }
+ }
+ }
+ }
+
+ 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, ListBase *editbones, Object *src_ob, Object *dst_ob)
+void updateDuplicateSubtargetObjects(EditBone *dupBone,
+ ListBase *editbones,
+ Object *src_ob,
+ Object *dst_ob)
{
- /* 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 ((conlist = &pchan->constraints)) {
- for (curcon = conlist->first; curcon; curcon = curcon->next) {
- /* does this constraint have a subtarget in
- * this armature?
- */
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (cti && cti->get_constraint_targets) {
- 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 */
- oldtarget = get_named_editbone(editbones, ct->subtarget);
- if (oldtarget) {
- /* was the subtarget bone duplicated too? If
- * so, update the constraint to point at the
- * duplicate of the old subtarget.
- */
- if (oldtarget->temp.ebone) {
- newtarget = oldtarget->temp.ebone;
- BLI_strncpy(ct->subtarget, newtarget->name, sizeof(ct->subtarget));
- }
- }
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(curcon, &targets, 0);
- }
- }
- }
- }
+ /* 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 ((conlist = &pchan->constraints)) {
+ for (curcon = conlist->first; curcon; curcon = curcon->next) {
+ /* does this constraint have a subtarget in
+ * this armature?
+ */
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ if (cti && cti->get_constraint_targets) {
+ 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 */
+ oldtarget = get_named_editbone(editbones, ct->subtarget);
+ if (oldtarget) {
+ /* was the subtarget bone duplicated too? If
+ * so, update the constraint to point at the
+ * duplicate of the old subtarget.
+ */
+ if (oldtarget->temp.ebone) {
+ newtarget = oldtarget->temp.ebone;
+ BLI_strncpy(ct->subtarget, newtarget->name, sizeof(ct->subtarget));
+ }
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(curcon, &targets, 0);
+ }
+ }
+ }
+ }
}
void updateDuplicateSubtarget(EditBone *dupBone, ListBase *editbones, Object *ob)
{
- updateDuplicateSubtargetObjects(dupBone, editbones, ob, ob);
+ updateDuplicateSubtargetObjects(dupBone, editbones, ob, ob);
}
-
-EditBone *duplicateEditBoneObjects(EditBone *curBone, const char *name, ListBase *editbones,
- Object *src_ob, Object *dst_ob)
+EditBone *duplicateEditBoneObjects(
+ EditBone *curBone, const char *name, ListBase *editbones, Object *src_ob, Object *dst_ob)
{
- EditBone *eBone = MEM_mallocN(sizeof(EditBone), "addup_editbone");
+ EditBone *eBone = MEM_mallocN(sizeof(EditBone), "addup_editbone");
- /* Copy data from old bone to new bone */
- memcpy(eBone, curBone, sizeof(EditBone));
+ /* Copy data from old bone to new bone */
+ memcpy(eBone, curBone, sizeof(EditBone));
- curBone->temp.ebone = eBone;
- eBone->temp.ebone = curBone;
+ curBone->temp.ebone = eBone;
+ eBone->temp.ebone = curBone;
- if (name != NULL) {
- BLI_strncpy(eBone->name, name, sizeof(eBone->name));
- }
+ if (name != NULL) {
+ BLI_strncpy(eBone->name, name, sizeof(eBone->name));
+ }
- ED_armature_ebone_unique_name(editbones, eBone->name, NULL);
- BLI_addtail(editbones, eBone);
+ ED_armature_ebone_unique_name(editbones, eBone->name, NULL);
+ BLI_addtail(editbones, eBone);
- /* copy the ID property */
- if (curBone->prop)
- eBone->prop = IDP_CopyProperty(curBone->prop);
+ /* copy the ID property */
+ if (curBone->prop)
+ eBone->prop = IDP_CopyProperty(curBone->prop);
- /* Lets duplicate the list of constraints that the
- * current bone has.
- */
- if (src_ob->pose) {
- bPoseChannel *chanold, *channew;
+ /* Lets duplicate the list of constraints that the
+ * current bone has.
+ */
+ if (src_ob->pose) {
+ bPoseChannel *chanold, *channew;
- chanold = BKE_pose_channel_verify(src_ob->pose, curBone->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);
+ chanold = BKE_pose_channel_verify(src_ob->pose, curBone->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);
- if (channew) {
- BKE_pose_channel_copy_data(channew, chanold);
- }
- }
- }
+ if (channew) {
+ BKE_pose_channel_copy_data(channew, chanold);
+ }
+ }
+ }
- return eBone;
+ return eBone;
}
EditBone *duplicateEditBone(EditBone *curBone, const char *name, ListBase *editbones, Object *ob)
{
- return duplicateEditBoneObjects(curBone, name, editbones, ob, ob);
+ return duplicateEditBoneObjects(curBone, name, editbones, ob, ob);
}
static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const bool do_flip_names = RNA_boolean_get(op->ptr, "do_flip_names");
-
- /* cancel if nothing selected */
- if (CTX_DATA_COUNT(C, selected_bones) == 0)
- return OPERATOR_CANCELLED;
-
- 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++) {
- EditBone *ebone_iter;
- /* The beginning of the duplicated bones in the edbo list */
- EditBone *ebone_first_dupe = NULL;
-
- Object *ob = objects[ob_index];
- bArmature *arm = ob->data;
-
- ED_armature_edit_sync_selection(arm->edbo); // XXX why is this needed?
-
- preEditBoneDuplicate(arm->edbo);
-
- /* Select mirrored bones */
- if (arm->flag & ARM_MIRROR_EDIT) {
- for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
- if (EBONE_VISIBLE(arm, ebone_iter) &&
- (ebone_iter->flag & BONE_SELECTED))
- {
- EditBone *ebone;
-
- ebone = ED_armature_ebone_get_mirrored(arm->edbo, ebone_iter);
- if (ebone) {
- ebone->flag |= BONE_SELECTED;
- }
- }
- }
- }
-
- /* Find the selected bones and duplicate them as needed */
- 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))
- {
- EditBone *ebone;
- char new_bone_name_buff[MAXBONENAME];
- char *new_bone_name = ebone_iter->name;
-
- if (do_flip_names) {
- 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. */
- if (ED_armature_ebone_find_name(arm->edbo, new_bone_name_buff) == NULL) {
- new_bone_name = new_bone_name_buff;
- }
- }
-
- ebone = duplicateEditBone(ebone_iter, new_bone_name, arm->edbo, ob);
-
- if (!ebone_first_dupe) {
- ebone_first_dupe = ebone;
- }
- }
- }
-
- /* Run though 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_VISIBLE(arm, ebone_iter) &&
- (ebone_iter->flag & BONE_SELECTED))
- {
- EditBone *ebone = ebone_iter->temp.ebone;
-
- if (!ebone_iter->parent) {
- /* If this bone has no parent,
- * Set the duplicate->parent to NULL
- */
- ebone->parent = NULL;
- }
- 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
- */
- 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
- */
- ebone->parent = (EditBone *) ebone_iter->parent;
- ebone->flag &= ~BONE_CONNECTED;
- }
-
- /* Update custom handle links. */
- if (ebone_iter->bbone_prev && ebone_iter->bbone_prev->temp.ebone) {
- ebone->bbone_prev = ebone_iter->bbone_prev->temp.ebone;
- }
- if (ebone_iter->bbone_next && ebone_iter->bbone_next->temp.ebone) {
- ebone->bbone_next = ebone_iter->bbone_next->temp.ebone;
- }
-
- /* Lets try to fix any constraint subtargets that might
- * have been duplicated
- */
- updateDuplicateSubtarget(ebone, arm->edbo, ob);
- }
- }
-
- /* correct the active bone */
- if (arm->act_edbone && arm->act_edbone->temp.ebone) {
- arm->act_edbone = arm->act_edbone->temp.ebone;
- }
-
- /* Deselect the old bones and select the new ones */
- 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 | BONE_TIPSEL | BONE_ROOTSEL);
- }
- }
-
- postEditBoneDuplicate(arm->edbo, ob);
-
- ED_armature_edit_validate_active(arm);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool do_flip_names = RNA_boolean_get(op->ptr, "do_flip_names");
+
+ /* cancel if nothing selected */
+ if (CTX_DATA_COUNT(C, selected_bones) == 0)
+ return OPERATOR_CANCELLED;
+
+ 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++) {
+ EditBone *ebone_iter;
+ /* The beginning of the duplicated bones in the edbo list */
+ EditBone *ebone_first_dupe = NULL;
+
+ Object *ob = objects[ob_index];
+ bArmature *arm = ob->data;
+
+ ED_armature_edit_sync_selection(arm->edbo); // XXX why is this needed?
+
+ preEditBoneDuplicate(arm->edbo);
+
+ /* Select mirrored bones */
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ if (EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED)) {
+ EditBone *ebone;
+
+ ebone = ED_armature_ebone_get_mirrored(arm->edbo, ebone_iter);
+ if (ebone) {
+ ebone->flag |= BONE_SELECTED;
+ }
+ }
+ }
+ }
+
+ /* Find the selected bones and duplicate them as needed */
+ 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)) {
+ EditBone *ebone;
+ char new_bone_name_buff[MAXBONENAME];
+ char *new_bone_name = ebone_iter->name;
+
+ if (do_flip_names) {
+ 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. */
+ if (ED_armature_ebone_find_name(arm->edbo, new_bone_name_buff) == NULL) {
+ new_bone_name = new_bone_name_buff;
+ }
+ }
+
+ ebone = duplicateEditBone(ebone_iter, new_bone_name, arm->edbo, ob);
+
+ if (!ebone_first_dupe) {
+ ebone_first_dupe = ebone;
+ }
+ }
+ }
+
+ /* Run though 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_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED)) {
+ EditBone *ebone = ebone_iter->temp.ebone;
+
+ if (!ebone_iter->parent) {
+ /* If this bone has no parent,
+ * Set the duplicate->parent to NULL
+ */
+ ebone->parent = NULL;
+ }
+ 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
+ */
+ 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
+ */
+ ebone->parent = (EditBone *)ebone_iter->parent;
+ ebone->flag &= ~BONE_CONNECTED;
+ }
+
+ /* Update custom handle links. */
+ if (ebone_iter->bbone_prev && ebone_iter->bbone_prev->temp.ebone) {
+ ebone->bbone_prev = ebone_iter->bbone_prev->temp.ebone;
+ }
+ if (ebone_iter->bbone_next && ebone_iter->bbone_next->temp.ebone) {
+ ebone->bbone_next = ebone_iter->bbone_next->temp.ebone;
+ }
+
+ /* Lets try to fix any constraint subtargets that might
+ * have been duplicated
+ */
+ updateDuplicateSubtarget(ebone, arm->edbo, ob);
+ }
+ }
+
+ /* correct the active bone */
+ if (arm->act_edbone && arm->act_edbone->temp.ebone) {
+ arm->act_edbone = arm->act_edbone->temp.ebone;
+ }
+
+ /* Deselect the old bones and select the new ones */
+ 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 | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
+
+ postEditBoneDuplicate(arm->edbo, ob);
+
+ ED_armature_edit_validate_active(arm);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
-
void ARMATURE_OT_duplicate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Duplicate Selected Bone(s)";
- ot->idname = "ARMATURE_OT_duplicate";
- ot->description = "Make copies of the selected bones within the same armature";
-
- /* api callbacks */
- ot->exec = armature_duplicate_selected_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(
- ot->srna, "do_flip_names", false,
- "Flip Names", "Try to flip names of the bones, if possible, instead of adding a number extension");
+ /* identifiers */
+ ot->name = "Duplicate Selected Bone(s)";
+ ot->idname = "ARMATURE_OT_duplicate";
+ ot->description = "Make copies of the selected bones within the same armature";
+
+ /* api callbacks */
+ ot->exec = armature_duplicate_selected_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(
+ ot->srna,
+ "do_flip_names",
+ false,
+ "Flip Names",
+ "Try to flip names of the bones, if possible, instead of adding a number extension");
}
/* Get the duplicated or existing mirrored copy of the bone. */
static EditBone *get_symmetrized_bone(bArmature *arm, EditBone *bone)
{
- if (bone == NULL) {
- return NULL;
- }
- else if (bone->temp.ebone != NULL) {
- return bone->temp.ebone;
- }
- else {
- EditBone *mirror = ED_armature_ebone_get_mirrored(arm->edbo, bone);
- return (mirror != NULL) ? mirror : bone;
- }
+ if (bone == NULL) {
+ return NULL;
+ }
+ else if (bone->temp.ebone != NULL) {
+ return bone->temp.ebone;
+ }
+ else {
+ EditBone *mirror = ED_armature_ebone_get_mirrored(arm->edbo, bone);
+ return (mirror != NULL) ? mirror : bone;
+ }
}
/**
@@ -643,222 +645,220 @@ static EditBone *get_symmetrized_bone(bArmature *arm, EditBone *bone)
*/
static int armature_symmetrize_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const int direction = RNA_enum_get(op->ptr, "direction");
- const int axis = 0;
-
- /* cancel if nothing selected */
- if (CTX_DATA_COUNT(C, selected_bones) == 0) {
- return OPERATOR_CANCELLED;
- }
-
- 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;
-
- EditBone *ebone_iter;
- /* The beginning of the duplicated mirrored bones in the edbo list */
- EditBone *ebone_first_dupe = NULL;
-
- ED_armature_edit_sync_selection(arm->edbo); // XXX why is this needed?
-
- preEditBoneDuplicate(arm->edbo);
-
- /* Select mirrored bones */
- for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
- if (EBONE_VISIBLE(arm, ebone_iter) &&
- (ebone_iter->flag & BONE_SELECTED))
- {
- char name_flip[MAXBONENAME];
-
- BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip));
-
- if (STREQ(name_flip, ebone_iter->name)) {
- /* if the name matches, we don't have the potential to be mirrored, just skip */
- ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else {
- EditBone *ebone = ED_armature_ebone_find_name(arm->edbo, name_flip);
-
- if (ebone) {
- if ((ebone->flag & BONE_SELECTED) == 0) {
- /* simple case, we're selected, the other bone isn't! */
- ebone_iter->temp.ebone = ebone;
- }
- else {
- /* complicated - choose which direction to copy */
- float axis_delta;
-
- axis_delta = ebone->head[axis] - ebone_iter->head[axis];
- if (axis_delta == 0.0f) {
- axis_delta = ebone->tail[axis] - ebone_iter->tail[axis];
- }
-
- if (axis_delta == 0.0f) {
- /* both mirrored bones exist and point to eachother and overlap exactly.
- *
- * in this case there's no well defined solution, so de-select both and skip.
- */
- ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else {
- EditBone *ebone_src, *ebone_dst;
- if (((axis_delta < 0.0f) ? -1 : 1) == direction) {
- ebone_src = ebone;
- ebone_dst = ebone_iter;
- }
- else {
- ebone_src = ebone_iter;
- ebone_dst = ebone;
- }
-
- ebone_src->temp.ebone = ebone_dst;
- ebone_dst->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- }
- }
- }
- }
- }
-
- /* 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))
- {
- char name_flip[MAXBONENAME];
-
- BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip));
-
- /* bones must have a side-suffix */
- if (!STREQ(name_flip, ebone_iter->name)) {
- EditBone *ebone;
-
- ebone = duplicateEditBone(ebone_iter, name_flip, arm->edbo, obedit);
-
- if (!ebone_first_dupe) {
- ebone_first_dupe = ebone;
- }
- }
- }
- }
-
- /* 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) {
- /* copy all flags except for ... */
- const int flag_copy = ((int)~0) & ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
-
- EditBone *ebone = ebone_iter->temp.ebone;
-
- /* copy flags incase bone is pre-existing data */
- ebone->flag = (ebone->flag & ~flag_copy) | (ebone_iter->flag & flag_copy);
-
- if (ebone_iter->parent == NULL) {
- /* If this bone has no parent,
- * Set the duplicate->parent to NULL
- */
- ebone->parent = NULL;
- ebone->flag &= ~BONE_CONNECTED;
- }
- else {
- /* the parent may have been duplicated, if not lookup the mirror parent */
- EditBone *ebone_parent = get_symmetrized_bone(arm, ebone_iter->parent);
-
- if (ebone_parent == ebone_iter->parent) {
- /* If the mirror lookup failed, (but the current bone has a parent)
- * 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;
- }
-
- ebone->parent = ebone_parent;
- }
-
- /* Update custom handle links. */
- ebone->bbone_prev = get_symmetrized_bone(arm, ebone_iter->bbone_prev);
- ebone->bbone_next = get_symmetrized_bone(arm, ebone_iter->bbone_next);
-
- /* Lets try to fix any constraint subtargets that might
- * have been duplicated
- */
- updateDuplicateSubtarget(ebone, arm->edbo, obedit);
- }
- }
-
- ED_armature_edit_transform_mirror_update(obedit);
-
- /* Selected bones now have their 'temp' pointer set,
- * so we don't need this anymore */
-
- /* Deselect the old bones and select the new ones */
- 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 | BONE_TIPSEL | BONE_ROOTSEL);
- }
- }
-
- /* New bones will be selected, but some of the bones may already exist */
- for (ebone_iter = arm->edbo->first;
- ebone_iter && ebone_iter != ebone_first_dupe;
- ebone_iter = ebone_iter->next)
- {
- EditBone *ebone = ebone_iter->temp.ebone;
- if (ebone && EBONE_SELECTABLE(arm, ebone)) {
- ED_armature_ebone_select_set(ebone, true);
- }
- }
-
- /* correct the active bone */
- if (arm->act_edbone && arm->act_edbone->temp.ebone) {
- arm->act_edbone = arm->act_edbone->temp.ebone;
- }
-
- postEditBoneDuplicate(arm->edbo, obedit);
-
- ED_armature_edit_validate_active(arm);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const int direction = RNA_enum_get(op->ptr, "direction");
+ const int axis = 0;
+
+ /* cancel if nothing selected */
+ if (CTX_DATA_COUNT(C, selected_bones) == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ 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;
+
+ EditBone *ebone_iter;
+ /* The beginning of the duplicated mirrored bones in the edbo list */
+ EditBone *ebone_first_dupe = NULL;
+
+ ED_armature_edit_sync_selection(arm->edbo); // XXX why is this needed?
+
+ preEditBoneDuplicate(arm->edbo);
+
+ /* Select mirrored bones */
+ for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ if (EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED)) {
+ char name_flip[MAXBONENAME];
+
+ BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip));
+
+ if (STREQ(name_flip, ebone_iter->name)) {
+ /* if the name matches, we don't have the potential to be mirrored, just skip */
+ ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else {
+ EditBone *ebone = ED_armature_ebone_find_name(arm->edbo, name_flip);
+
+ if (ebone) {
+ if ((ebone->flag & BONE_SELECTED) == 0) {
+ /* simple case, we're selected, the other bone isn't! */
+ ebone_iter->temp.ebone = ebone;
+ }
+ else {
+ /* complicated - choose which direction to copy */
+ float axis_delta;
+
+ axis_delta = ebone->head[axis] - ebone_iter->head[axis];
+ if (axis_delta == 0.0f) {
+ axis_delta = ebone->tail[axis] - ebone_iter->tail[axis];
+ }
+
+ if (axis_delta == 0.0f) {
+ /* both mirrored bones exist and point to eachother and overlap exactly.
+ *
+ * in this case there's no well defined solution, so de-select both and skip.
+ */
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else {
+ EditBone *ebone_src, *ebone_dst;
+ if (((axis_delta < 0.0f) ? -1 : 1) == direction) {
+ ebone_src = ebone;
+ ebone_dst = ebone_iter;
+ }
+ else {
+ ebone_src = ebone_iter;
+ ebone_dst = ebone;
+ }
+
+ ebone_src->temp.ebone = ebone_dst;
+ ebone_dst->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* 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)) {
+ char name_flip[MAXBONENAME];
+
+ BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip));
+
+ /* bones must have a side-suffix */
+ if (!STREQ(name_flip, ebone_iter->name)) {
+ EditBone *ebone;
+
+ ebone = duplicateEditBone(ebone_iter, name_flip, arm->edbo, obedit);
+
+ if (!ebone_first_dupe) {
+ ebone_first_dupe = ebone;
+ }
+ }
+ }
+ }
+
+ /* 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) {
+ /* copy all flags except for ... */
+ const int flag_copy = ((int)~0) & ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
+
+ EditBone *ebone = ebone_iter->temp.ebone;
+
+ /* copy flags incase bone is pre-existing data */
+ ebone->flag = (ebone->flag & ~flag_copy) | (ebone_iter->flag & flag_copy);
+
+ if (ebone_iter->parent == NULL) {
+ /* If this bone has no parent,
+ * Set the duplicate->parent to NULL
+ */
+ ebone->parent = NULL;
+ ebone->flag &= ~BONE_CONNECTED;
+ }
+ else {
+ /* the parent may have been duplicated, if not lookup the mirror parent */
+ EditBone *ebone_parent = get_symmetrized_bone(arm, ebone_iter->parent);
+
+ if (ebone_parent == ebone_iter->parent) {
+ /* If the mirror lookup failed, (but the current bone has a parent)
+ * 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;
+ }
+
+ ebone->parent = ebone_parent;
+ }
+
+ /* Update custom handle links. */
+ ebone->bbone_prev = get_symmetrized_bone(arm, ebone_iter->bbone_prev);
+ ebone->bbone_next = get_symmetrized_bone(arm, ebone_iter->bbone_next);
+
+ /* Lets try to fix any constraint subtargets that might
+ * have been duplicated
+ */
+ updateDuplicateSubtarget(ebone, arm->edbo, obedit);
+ }
+ }
+
+ ED_armature_edit_transform_mirror_update(obedit);
+
+ /* Selected bones now have their 'temp' pointer set,
+ * so we don't need this anymore */
+
+ /* Deselect the old bones and select the new ones */
+ 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 | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
+
+ /* New bones will be selected, but some of the bones may already exist */
+ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe;
+ ebone_iter = ebone_iter->next) {
+ EditBone *ebone = ebone_iter->temp.ebone;
+ if (ebone && EBONE_SELECTABLE(arm, ebone)) {
+ ED_armature_ebone_select_set(ebone, true);
+ }
+ }
+
+ /* correct the active bone */
+ if (arm->act_edbone && arm->act_edbone->temp.ebone) {
+ arm->act_edbone = arm->act_edbone->temp.ebone;
+ }
+
+ postEditBoneDuplicate(arm->edbo, obedit);
+
+ ED_armature_edit_validate_active(arm);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
/* following conventions from #MESH_OT_symmetrize */
void ARMATURE_OT_symmetrize(wmOperatorType *ot)
{
- /* subset of 'rna_enum_symmetrize_direction_items' */
- static const EnumPropertyItem arm_symmetrize_direction_items[] = {
- {-1, "NEGATIVE_X", 0, "-X to +X", ""},
- {+1, "POSITIVE_X", 0, "+X to -X", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Symmetrize";
- ot->idname = "ARMATURE_OT_symmetrize";
- ot->description = "Enforce symmetry, make copies of the selection or use existing";
-
- /* api callbacks */
- ot->exec = armature_symmetrize_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ot->prop = RNA_def_enum(
- ot->srna, "direction", arm_symmetrize_direction_items, -1,
- "Direction", "Which sides to copy from and to (when both are selected)");
+ /* subset of 'rna_enum_symmetrize_direction_items' */
+ static const EnumPropertyItem arm_symmetrize_direction_items[] = {
+ {-1, "NEGATIVE_X", 0, "-X to +X", ""},
+ {+1, "POSITIVE_X", 0, "+X to -X", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Symmetrize";
+ ot->idname = "ARMATURE_OT_symmetrize";
+ ot->description = "Enforce symmetry, make copies of the selection or use existing";
+
+ /* api callbacks */
+ ot->exec = armature_symmetrize_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna,
+ "direction",
+ arm_symmetrize_direction_items,
+ -1,
+ "Direction",
+ "Which sides to copy from and to (when both are selected)");
}
/* ------------------------------------------ */
@@ -868,186 +868,189 @@ void ARMATURE_OT_symmetrize(wmOperatorType *ot)
/* if forked && mirror-edit: makes two bones with flipped names */
static int armature_extrude_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const bool forked = RNA_boolean_get(op->ptr, "forked");
- bool changed_multi = false;
-
- 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 forked_iter = forked;
-
- EditBone *newbone = NULL, *ebone, *flipbone, *first = NULL;
- int a, totbone = 0, do_extrude;
-
- /* since we allow root extrude too, we have to make sure selection is OK */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone)) {
- if (ebone->flag & BONE_ROOTSEL) {
- if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
- if (ebone->parent->flag & BONE_TIPSEL)
- ebone->flag &= ~BONE_ROOTSEL;
- }
- }
- }
- }
-
- /* Duplicate the necessary bones */
- for (ebone = arm->edbo->first; ((ebone) && (ebone != first)); ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone)) {
- /* we extrude per definition the tip */
- do_extrude = false;
- if (ebone->flag & (BONE_TIPSEL | BONE_SELECTED)) {
- do_extrude = true;
- }
- else if (ebone->flag & BONE_ROOTSEL) {
- /* but, a bone with parent deselected we do the root... */
- if (ebone->parent && (ebone->parent->flag & BONE_TIPSEL)) {
- /* pass */
- }
- else {
- do_extrude = 2;
- }
- }
-
- if (do_extrude) {
- /* we re-use code for mirror editing... */
- flipbone = NULL;
- if (arm->flag & ARM_MIRROR_EDIT) {
- flipbone = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
- if (flipbone) {
- forked_iter = 0; // we extrude 2 different bones
- if (flipbone->flag & (BONE_TIPSEL | BONE_ROOTSEL | BONE_SELECTED))
- /* don't want this bone to be selected... */
- flipbone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
- }
- if ((flipbone == NULL) && (forked_iter))
- flipbone = ebone;
- }
-
- for (a = 0; a < 2; a++) {
- if (a == 1) {
- if (flipbone == NULL)
- break;
- else {
- SWAP(EditBone *, flipbone, ebone);
- }
- }
-
- totbone++;
- newbone = MEM_callocN(sizeof(EditBone), "extrudebone");
-
- if (do_extrude == true) {
- copy_v3_v3(newbone->head, ebone->tail);
- copy_v3_v3(newbone->tail, newbone->head);
- newbone->parent = ebone;
-
- /* copies it, in case mirrored bone */
- newbone->flag = ebone->flag & (BONE_TIPSEL | BONE_RELATIVE_PARENTING);
-
- if (newbone->parent) newbone->flag |= BONE_CONNECTED;
- }
- else {
- copy_v3_v3(newbone->head, ebone->head);
- copy_v3_v3(newbone->tail, ebone->head);
- newbone->parent = ebone->parent;
-
- newbone->flag = BONE_TIPSEL;
-
- if (newbone->parent && (ebone->flag & BONE_CONNECTED)) {
- newbone->flag |= BONE_CONNECTED;
- }
- }
-
- newbone->weight = ebone->weight;
- newbone->dist = ebone->dist;
- newbone->xwidth = ebone->xwidth;
- newbone->zwidth = ebone->zwidth;
- newbone->rad_head = ebone->rad_tail; // don't copy entire bone...
- newbone->rad_tail = ebone->rad_tail;
- newbone->segments = 1;
- newbone->layer = ebone->layer;
-
- /* Bendy-Bone parameters */
- newbone->roll1 = ebone->roll1;
- newbone->roll2 = ebone->roll2;
- newbone->curveInX = ebone->curveInX;
- newbone->curveInY = ebone->curveInY;
- newbone->curveOutX = ebone->curveOutX;
- newbone->curveOutY = ebone->curveOutY;
- newbone->ease1 = ebone->ease1;
- newbone->ease2 = ebone->ease2;
- newbone->scaleIn = ebone->scaleIn;
- newbone->scaleOut = ebone->scaleOut;
-
-
- BLI_strncpy(newbone->name, ebone->name, sizeof(newbone->name));
-
- if (flipbone && forked_iter) { // only set if mirror edit
- if (strlen(newbone->name) < (MAXBONENAME - 2)) {
- if (a == 0) strcat(newbone->name, "_L");
- else strcat(newbone->name, "_R");
- }
- }
- ED_armature_ebone_unique_name(arm->edbo, newbone->name, NULL);
-
- /* Add the new bone to the list */
- BLI_addtail(arm->edbo, newbone);
- if (!first)
- first = newbone;
-
- /* restore ebone if we were flipping */
- if (a == 1 && flipbone)
- SWAP(EditBone *, flipbone, ebone);
- }
- }
-
- /* Deselect the old bone */
- ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
- }
- }
- /* if only one bone, make this one active */
- if (totbone == 1 && first) {
- arm->act_edbone = first;
- }
- else {
- arm->act_edbone = newbone;
- }
-
- if (totbone == 0) {
- continue;
- }
-
- changed_multi = true;
-
- /* Transform the endpoints */
- ED_armature_edit_sync_selection(arm->edbo);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- MEM_freeN(objects);
-
- return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool forked = RNA_boolean_get(op->ptr, "forked");
+ bool changed_multi = false;
+
+ 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 forked_iter = forked;
+
+ EditBone *newbone = NULL, *ebone, *flipbone, *first = NULL;
+ int a, totbone = 0, do_extrude;
+
+ /* since we allow root extrude too, we have to make sure selection is OK */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (ebone->flag & BONE_ROOTSEL) {
+ if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+ if (ebone->parent->flag & BONE_TIPSEL)
+ ebone->flag &= ~BONE_ROOTSEL;
+ }
+ }
+ }
+ }
+
+ /* Duplicate the necessary bones */
+ for (ebone = arm->edbo->first; ((ebone) && (ebone != first)); ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ /* we extrude per definition the tip */
+ do_extrude = false;
+ if (ebone->flag & (BONE_TIPSEL | BONE_SELECTED)) {
+ do_extrude = true;
+ }
+ else if (ebone->flag & BONE_ROOTSEL) {
+ /* but, a bone with parent deselected we do the root... */
+ if (ebone->parent && (ebone->parent->flag & BONE_TIPSEL)) {
+ /* pass */
+ }
+ else {
+ do_extrude = 2;
+ }
+ }
+
+ if (do_extrude) {
+ /* we re-use code for mirror editing... */
+ flipbone = NULL;
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ flipbone = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
+ if (flipbone) {
+ forked_iter = 0; // we extrude 2 different bones
+ if (flipbone->flag & (BONE_TIPSEL | BONE_ROOTSEL | BONE_SELECTED))
+ /* don't want this bone to be selected... */
+ flipbone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ }
+ if ((flipbone == NULL) && (forked_iter))
+ flipbone = ebone;
+ }
+
+ for (a = 0; a < 2; a++) {
+ if (a == 1) {
+ if (flipbone == NULL)
+ break;
+ else {
+ SWAP(EditBone *, flipbone, ebone);
+ }
+ }
+
+ totbone++;
+ newbone = MEM_callocN(sizeof(EditBone), "extrudebone");
+
+ if (do_extrude == true) {
+ copy_v3_v3(newbone->head, ebone->tail);
+ copy_v3_v3(newbone->tail, newbone->head);
+ newbone->parent = ebone;
+
+ /* copies it, in case mirrored bone */
+ newbone->flag = ebone->flag & (BONE_TIPSEL | BONE_RELATIVE_PARENTING);
+
+ if (newbone->parent)
+ newbone->flag |= BONE_CONNECTED;
+ }
+ else {
+ copy_v3_v3(newbone->head, ebone->head);
+ copy_v3_v3(newbone->tail, ebone->head);
+ newbone->parent = ebone->parent;
+
+ newbone->flag = BONE_TIPSEL;
+
+ if (newbone->parent && (ebone->flag & BONE_CONNECTED)) {
+ newbone->flag |= BONE_CONNECTED;
+ }
+ }
+
+ newbone->weight = ebone->weight;
+ newbone->dist = ebone->dist;
+ newbone->xwidth = ebone->xwidth;
+ newbone->zwidth = ebone->zwidth;
+ newbone->rad_head = ebone->rad_tail; // don't copy entire bone...
+ newbone->rad_tail = ebone->rad_tail;
+ newbone->segments = 1;
+ newbone->layer = ebone->layer;
+
+ /* Bendy-Bone parameters */
+ newbone->roll1 = ebone->roll1;
+ newbone->roll2 = ebone->roll2;
+ newbone->curveInX = ebone->curveInX;
+ newbone->curveInY = ebone->curveInY;
+ newbone->curveOutX = ebone->curveOutX;
+ newbone->curveOutY = ebone->curveOutY;
+ newbone->ease1 = ebone->ease1;
+ newbone->ease2 = ebone->ease2;
+ newbone->scaleIn = ebone->scaleIn;
+ newbone->scaleOut = ebone->scaleOut;
+
+ BLI_strncpy(newbone->name, ebone->name, sizeof(newbone->name));
+
+ if (flipbone && forked_iter) { // only set if mirror edit
+ if (strlen(newbone->name) < (MAXBONENAME - 2)) {
+ if (a == 0)
+ strcat(newbone->name, "_L");
+ else
+ strcat(newbone->name, "_R");
+ }
+ }
+ ED_armature_ebone_unique_name(arm->edbo, newbone->name, NULL);
+
+ /* Add the new bone to the list */
+ BLI_addtail(arm->edbo, newbone);
+ if (!first)
+ first = newbone;
+
+ /* restore ebone if we were flipping */
+ if (a == 1 && flipbone)
+ SWAP(EditBone *, flipbone, ebone);
+ }
+ }
+
+ /* Deselect the old bone */
+ ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ }
+ }
+ /* if only one bone, make this one active */
+ if (totbone == 1 && first) {
+ arm->act_edbone = first;
+ }
+ else {
+ arm->act_edbone = newbone;
+ }
+
+ if (totbone == 0) {
+ continue;
+ }
+
+ changed_multi = true;
+
+ /* Transform the endpoints */
+ ED_armature_edit_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ MEM_freeN(objects);
+
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void ARMATURE_OT_extrude(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Extrude";
- ot->idname = "ARMATURE_OT_extrude";
- ot->description = "Create new bones from the selected joints";
+ /* identifiers */
+ ot->name = "Extrude";
+ ot->idname = "ARMATURE_OT_extrude";
+ ot->description = "Create new bones from the selected joints";
- /* api callbacks */
- ot->exec = armature_extrude_exec;
- ot->poll = ED_operator_editarmature;
+ /* api callbacks */
+ ot->exec = armature_extrude_exec;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "forked", 0, "Forked", "");
+ /* props */
+ RNA_def_boolean(ot->srna, "forked", 0, "Forked", "");
}
/* ********************** Bone Add *************************************/
@@ -1056,62 +1059,62 @@ void ARMATURE_OT_extrude(wmOperatorType *ot)
static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- Object *obedit = CTX_data_edit_object(C);
- EditBone *bone;
- float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
- char name[MAXBONENAME];
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ Object *obedit = CTX_data_edit_object(C);
+ EditBone *bone;
+ float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
+ char name[MAXBONENAME];
- RNA_string_get(op->ptr, "name", name);
+ RNA_string_get(op->ptr, "name", name);
- copy_v3_v3(curs, CTX_data_scene(C)->cursor.location);
+ copy_v3_v3(curs, CTX_data_scene(C)->cursor.location);
- /* Get inverse point for head and orientation for tail */
- invert_m4_m4(obedit->imat, obedit->obmat);
- mul_m4_v3(obedit->imat, curs);
+ /* Get inverse point for head and orientation for tail */
+ invert_m4_m4(obedit->imat, obedit->obmat);
+ mul_m4_v3(obedit->imat, curs);
- if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
- copy_m3_m4(obmat, rv3d->viewmat);
- else unit_m3(obmat);
+ if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
+ copy_m3_m4(obmat, rv3d->viewmat);
+ else
+ unit_m3(obmat);
- copy_m3_m4(viewmat, obedit->obmat);
- mul_m3_m3m3(totmat, obmat, viewmat);
- invert_m3_m3(imat, totmat);
+ copy_m3_m4(viewmat, obedit->obmat);
+ mul_m3_m3m3(totmat, obmat, viewmat);
+ invert_m3_m3(imat, totmat);
- ED_armature_edit_deselect_all(obedit);
+ ED_armature_edit_deselect_all(obedit);
- /* Create a bone */
- bone = ED_armature_ebone_add(obedit->data, name);
+ /* Create a bone */
+ bone = ED_armature_ebone_add(obedit->data, name);
- copy_v3_v3(bone->head, curs);
+ copy_v3_v3(bone->head, curs);
- if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
- add_v3_v3v3(bone->tail, bone->head, imat[1]); // bone with unit length 1
- else
- add_v3_v3v3(bone->tail, bone->head, imat[2]); // bone with unit length 1, pointing up Z
+ if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
+ add_v3_v3v3(bone->tail, bone->head, imat[1]); // bone with unit length 1
+ else
+ add_v3_v3v3(bone->tail, bone->head, imat[2]); // bone with unit length 1, pointing up Z
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_bone_primitive_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Bone";
- ot->idname = "ARMATURE_OT_bone_primitive_add";
- ot->description = "Add a new bone located at the 3D-Cursor";
-
- /* api callbacks */
- ot->exec = armature_bone_primitive_add_exec;
- ot->poll = ED_operator_editarmature;
+ /* identifiers */
+ ot->name = "Add Bone";
+ ot->idname = "ARMATURE_OT_bone_primitive_add";
+ ot->description = "Add a new bone located at the 3D-Cursor";
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* api callbacks */
+ ot->exec = armature_bone_primitive_add_exec;
+ ot->poll = ED_operator_editarmature;
- RNA_def_string(ot->srna, "name", "Bone", MAXBONENAME, "Name", "Name of the newly created bone");
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ RNA_def_string(ot->srna, "name", "Bone", MAXBONENAME, "Name", "Name of the newly created bone");
}
/* ********************** Subdivide *******************************/
@@ -1124,86 +1127,86 @@ void ARMATURE_OT_bone_primitive_add(wmOperatorType *ot)
static int armature_subdivide_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- EditBone *newbone, *tbone;
- int cuts, i;
-
- /* there may not be a number_cuts property defined (for 'simple' subdivide) */
- cuts = RNA_int_get(op->ptr, "number_cuts");
-
- /* loop over all editable bones */
- // XXX the old code did this in reverse order though!
- CTX_DATA_BEGIN_WITH_ID(C, EditBone *, ebone, selected_editable_bones, bArmature *, arm)
- {
- for (i = cuts + 1; i > 1; i--) {
- /* compute cut ratio first */
- float cutratio = 1.0f / (float)i;
- float cutratioI = 1.0f - cutratio;
-
- float val1[3];
- float val2[3];
- float val3[3];
-
- newbone = MEM_mallocN(sizeof(EditBone), "ebone subdiv");
- *newbone = *ebone;
- BLI_addtail(arm->edbo, newbone);
-
- /* calculate location of newbone->head */
- copy_v3_v3(val1, ebone->head);
- copy_v3_v3(val2, ebone->tail);
- copy_v3_v3(val3, newbone->head);
-
- val3[0] = val1[0] * cutratio + val2[0] * cutratioI;
- val3[1] = val1[1] * cutratio + val2[1] * cutratioI;
- val3[2] = val1[2] * cutratio + val2[2] * cutratioI;
-
- copy_v3_v3(newbone->head, val3);
- copy_v3_v3(newbone->tail, ebone->tail);
- copy_v3_v3(ebone->tail, newbone->head);
-
- newbone->rad_head = ((ebone->rad_head * cutratio) + (ebone->rad_tail * cutratioI));
- ebone->rad_tail = newbone->rad_head;
-
- newbone->flag |= BONE_CONNECTED;
-
- newbone->prop = NULL;
-
- ED_armature_ebone_unique_name(arm->edbo, newbone->name, NULL);
-
- /* correct parent bones */
- for (tbone = arm->edbo->first; tbone; tbone = tbone->next) {
- if (tbone->parent == ebone)
- tbone->parent = newbone;
- }
- newbone->parent = ebone;
- }
- }
- CTX_DATA_END;
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
-
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_edit_object(C);
+ EditBone *newbone, *tbone;
+ int cuts, i;
+
+ /* there may not be a number_cuts property defined (for 'simple' subdivide) */
+ cuts = RNA_int_get(op->ptr, "number_cuts");
+
+ /* loop over all editable bones */
+ // XXX the old code did this in reverse order though!
+ CTX_DATA_BEGIN_WITH_ID(C, EditBone *, ebone, selected_editable_bones, bArmature *, arm)
+ {
+ for (i = cuts + 1; i > 1; i--) {
+ /* compute cut ratio first */
+ float cutratio = 1.0f / (float)i;
+ float cutratioI = 1.0f - cutratio;
+
+ float val1[3];
+ float val2[3];
+ float val3[3];
+
+ newbone = MEM_mallocN(sizeof(EditBone), "ebone subdiv");
+ *newbone = *ebone;
+ BLI_addtail(arm->edbo, newbone);
+
+ /* calculate location of newbone->head */
+ copy_v3_v3(val1, ebone->head);
+ copy_v3_v3(val2, ebone->tail);
+ copy_v3_v3(val3, newbone->head);
+
+ val3[0] = val1[0] * cutratio + val2[0] * cutratioI;
+ val3[1] = val1[1] * cutratio + val2[1] * cutratioI;
+ val3[2] = val1[2] * cutratio + val2[2] * cutratioI;
+
+ copy_v3_v3(newbone->head, val3);
+ copy_v3_v3(newbone->tail, ebone->tail);
+ copy_v3_v3(ebone->tail, newbone->head);
+
+ newbone->rad_head = ((ebone->rad_head * cutratio) + (ebone->rad_tail * cutratioI));
+ ebone->rad_tail = newbone->rad_head;
+
+ newbone->flag |= BONE_CONNECTED;
+
+ newbone->prop = NULL;
+
+ ED_armature_ebone_unique_name(arm->edbo, newbone->name, NULL);
+
+ /* correct parent bones */
+ for (tbone = arm->edbo->first; tbone; tbone = tbone->next) {
+ if (tbone->parent == ebone)
+ tbone->parent = newbone;
+ }
+ newbone->parent = ebone;
+ }
+ }
+ CTX_DATA_END;
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_subdivide(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Subdivide Multi";
- ot->idname = "ARMATURE_OT_subdivide";
- ot->description = "Break selected bones into chains of smaller bones";
+ /* identifiers */
+ ot->name = "Subdivide Multi";
+ ot->idname = "ARMATURE_OT_subdivide";
+ ot->description = "Break selected bones into chains of smaller bones";
- /* api callbacks */
- ot->exec = armature_subdivide_exec;
- ot->poll = ED_operator_editarmature;
+ /* api callbacks */
+ ot->exec = armature_subdivide_exec;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* Properties */
- prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000, "Number of Cuts", "", 1, 10);
- /* avoid re-using last var because it can cause _very_ high poly meshes and annoy users (or worse crash) */
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* Properties */
+ prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000, "Number of Cuts", "", 1, 10);
+ /* avoid re-using last var because it can cause _very_ high poly meshes and annoy users (or worse crash) */
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index e3db0ca8f2c..dfcd0bf69f7 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -64,135 +64,136 @@
void ED_armature_transform_apply(Main *bmain, Object *ob, float mat[4][4], const bool do_props)
{
- bArmature *arm = ob->data;
+ bArmature *arm = ob->data;
- /* Put the armature into editmode */
- ED_armature_to_edit(arm);
+ /* Put the armature into editmode */
+ ED_armature_to_edit(arm);
- /* Transform the bones */
- ED_armature_transform_bones(arm, mat, do_props);
+ /* Transform the bones */
+ ED_armature_transform_bones(arm, mat, do_props);
- /* Turn the list into an armature */
- ED_armature_from_edit(bmain, arm);
- ED_armature_edit_free(arm);
+ /* Turn the list into an armature */
+ ED_armature_from_edit(bmain, arm);
+ ED_armature_edit_free(arm);
}
void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4], const bool do_props)
{
- EditBone *ebone;
- float scale = mat4_to_scale(mat); /* store the scale of the matrix here to use on envelopes */
- float mat3[3][3];
-
- copy_m3_m4(mat3, mat);
- normalize_m3(mat3);
- /* Do the rotations */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- float tmat[3][3];
-
- /* find the current bone's roll matrix */
- ED_armature_ebone_to_mat3(ebone, tmat);
-
- /* transform the roll matrix */
- mul_m3_m3m3(tmat, mat3, tmat);
-
- /* transform the bone */
- mul_m4_v3(mat, ebone->head);
- mul_m4_v3(mat, ebone->tail);
-
- /* apply the transformed roll back */
- mat3_to_vec_roll(tmat, NULL, &ebone->roll);
-
- if (do_props) {
- ebone->rad_head *= scale;
- ebone->rad_tail *= scale;
- ebone->dist *= scale;
-
- /* we could be smarter and scale by the matrix along the x & z axis */
- ebone->xwidth *= scale;
- ebone->zwidth *= scale;
- }
- }
+ EditBone *ebone;
+ float scale = mat4_to_scale(mat); /* store the scale of the matrix here to use on envelopes */
+ float mat3[3][3];
+
+ copy_m3_m4(mat3, mat);
+ normalize_m3(mat3);
+ /* Do the rotations */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ float tmat[3][3];
+
+ /* find the current bone's roll matrix */
+ ED_armature_ebone_to_mat3(ebone, tmat);
+
+ /* transform the roll matrix */
+ mul_m3_m3m3(tmat, mat3, tmat);
+
+ /* transform the bone */
+ mul_m4_v3(mat, ebone->head);
+ mul_m4_v3(mat, ebone->tail);
+
+ /* apply the transformed roll back */
+ mat3_to_vec_roll(tmat, NULL, &ebone->roll);
+
+ if (do_props) {
+ ebone->rad_head *= scale;
+ ebone->rad_tail *= scale;
+ ebone->dist *= scale;
+
+ /* we could be smarter and scale by the matrix along the x & z axis */
+ ebone->xwidth *= scale;
+ ebone->zwidth *= scale;
+ }
+ }
}
void ED_armature_transform(Main *bmain, bArmature *arm, float mat[4][4], const bool do_props)
{
- if (arm->edbo) {
- ED_armature_transform_bones(arm, mat, do_props);
- }
- else {
- /* Put the armature into editmode */
- ED_armature_to_edit(arm);
-
- /* Transform the bones */
- ED_armature_transform_bones(arm, mat, do_props);
-
- /* Go back to object mode*/
- ED_armature_from_edit(bmain, arm);
- ED_armature_edit_free(arm);
- }
+ if (arm->edbo) {
+ ED_armature_transform_bones(arm, mat, do_props);
+ }
+ else {
+ /* Put the armature into editmode */
+ ED_armature_to_edit(arm);
+
+ /* Transform the bones */
+ ED_armature_transform_bones(arm, mat, do_props);
+
+ /* Go back to object mode*/
+ ED_armature_from_edit(bmain, arm);
+ ED_armature_edit_free(arm);
+ }
}
/* exported for use in editors/object/ */
/* 0 == do center, 1 == center new, 2 == center cursor */
-void ED_armature_origin_set(Main *bmain, Object *ob, const float cursor[3], int centermode, int around)
+void ED_armature_origin_set(
+ Main *bmain, Object *ob, const float cursor[3], int centermode, int around)
{
- const bool is_editmode = BKE_object_is_in_editmode(ob);
- EditBone *ebone;
- bArmature *arm = ob->data;
- float cent[3];
-
- /* Put the armature into editmode */
- if (is_editmode == false) {
- ED_armature_to_edit(arm);
- }
-
- /* Find the centerpoint */
- if (centermode == 2) {
- copy_v3_v3(cent, cursor);
- invert_m4_m4(ob->imat, ob->obmat);
- mul_m4_v3(ob->imat, cent);
- }
- else {
- if (around == V3D_AROUND_CENTER_MEDIAN) {
- int total = 0;
- zero_v3(cent);
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- total += 2;
- add_v3_v3(cent, ebone->head);
- add_v3_v3(cent, ebone->tail);
- }
- if (total) {
- mul_v3_fl(cent, 1.0f / (float)total);
- }
- }
- else {
- float min[3], max[3];
- INIT_MINMAX(min, max);
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- minmax_v3v3_v3(min, max, ebone->head);
- minmax_v3v3_v3(min, max, ebone->tail);
- }
- mid_v3_v3v3(cent, min, max);
- }
- }
-
- /* Do the adjustments */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- sub_v3_v3(ebone->head, cent);
- sub_v3_v3(ebone->tail, cent);
- }
-
- /* Turn the list into an armature */
- if (is_editmode == false) {
- ED_armature_from_edit(bmain, arm);
- ED_armature_edit_free(arm);
- }
-
- /* Adjust object location for new centerpoint */
- if (centermode && (is_editmode == false)) {
- mul_mat3_m4_v3(ob->obmat, cent); /* omit translation part */
- add_v3_v3(ob->loc, cent);
- }
+ const bool is_editmode = BKE_object_is_in_editmode(ob);
+ EditBone *ebone;
+ bArmature *arm = ob->data;
+ float cent[3];
+
+ /* Put the armature into editmode */
+ if (is_editmode == false) {
+ ED_armature_to_edit(arm);
+ }
+
+ /* Find the centerpoint */
+ if (centermode == 2) {
+ copy_v3_v3(cent, cursor);
+ invert_m4_m4(ob->imat, ob->obmat);
+ mul_m4_v3(ob->imat, cent);
+ }
+ else {
+ if (around == V3D_AROUND_CENTER_MEDIAN) {
+ int total = 0;
+ zero_v3(cent);
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ total += 2;
+ add_v3_v3(cent, ebone->head);
+ add_v3_v3(cent, ebone->tail);
+ }
+ if (total) {
+ mul_v3_fl(cent, 1.0f / (float)total);
+ }
+ }
+ else {
+ float min[3], max[3];
+ INIT_MINMAX(min, max);
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ minmax_v3v3_v3(min, max, ebone->head);
+ minmax_v3v3_v3(min, max, ebone->tail);
+ }
+ mid_v3_v3v3(cent, min, max);
+ }
+ }
+
+ /* Do the adjustments */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ sub_v3_v3(ebone->head, cent);
+ sub_v3_v3(ebone->tail, cent);
+ }
+
+ /* Turn the list into an armature */
+ if (is_editmode == false) {
+ ED_armature_from_edit(bmain, arm);
+ ED_armature_edit_free(arm);
+ }
+
+ /* Adjust object location for new centerpoint */
+ if (centermode && (is_editmode == false)) {
+ mul_mat3_m4_v3(ob->obmat, cent); /* omit translation part */
+ add_v3_v3(ob->loc, cent);
+ }
}
/* ********************************* Roll ******************************* */
@@ -200,651 +201,676 @@ void ED_armature_origin_set(Main *bmain, Object *ob, const float cursor[3], int
/* adjust bone roll to align Z axis with vector
* vec is in local space and is normalized
*/
-float ED_armature_ebone_roll_to_vector(const EditBone *bone, const float align_axis[3], const bool axis_only)
+float ED_armature_ebone_roll_to_vector(const EditBone *bone,
+ const float align_axis[3],
+ const bool axis_only)
{
- float mat[3][3], nor[3];
- float vec[3], align_axis_proj[3], roll = 0.0f;
+ float mat[3][3], nor[3];
+ float vec[3], align_axis_proj[3], roll = 0.0f;
- BLI_ASSERT_UNIT_V3(align_axis);
+ BLI_ASSERT_UNIT_V3(align_axis);
- sub_v3_v3v3(nor, bone->tail, bone->head);
+ sub_v3_v3v3(nor, bone->tail, bone->head);
- /* If tail == head or the bone is aligned with the axis... */
- if (normalize_v3(nor) <= FLT_EPSILON || (fabsf(dot_v3v3(align_axis, nor)) >= (1.0f - FLT_EPSILON))) {
- return roll;
- }
+ /* If tail == head or the bone is aligned with the axis... */
+ if (normalize_v3(nor) <= FLT_EPSILON ||
+ (fabsf(dot_v3v3(align_axis, nor)) >= (1.0f - FLT_EPSILON))) {
+ return roll;
+ }
- vec_roll_to_mat3_normalized(nor, 0.0f, mat);
+ vec_roll_to_mat3_normalized(nor, 0.0f, mat);
- /* project the new_up_axis along the normal */
- project_v3_v3v3_normalized(vec, align_axis, nor);
- sub_v3_v3v3(align_axis_proj, align_axis, vec);
+ /* project the new_up_axis along the normal */
+ project_v3_v3v3_normalized(vec, align_axis, nor);
+ sub_v3_v3v3(align_axis_proj, align_axis, vec);
- if (axis_only) {
- if (angle_v3v3(align_axis_proj, mat[2]) > (float)(M_PI_2)) {
- negate_v3(align_axis_proj);
- }
- }
+ if (axis_only) {
+ if (angle_v3v3(align_axis_proj, mat[2]) > (float)(M_PI_2)) {
+ negate_v3(align_axis_proj);
+ }
+ }
- roll = angle_v3v3(align_axis_proj, mat[2]);
+ roll = angle_v3v3(align_axis_proj, mat[2]);
- cross_v3_v3v3(vec, mat[2], align_axis_proj);
+ cross_v3_v3v3(vec, mat[2], align_axis_proj);
- if (dot_v3v3(vec, nor) < 0.0f) {
- return -roll;
- }
- return roll;
+ if (dot_v3v3(vec, nor) < 0.0f) {
+ return -roll;
+ }
+ return roll;
}
/* note, ranges arithmetic is used below */
typedef enum eCalcRollTypes {
- /* pos */
- CALC_ROLL_POS_X = 0,
- CALC_ROLL_POS_Y,
- CALC_ROLL_POS_Z,
-
- CALC_ROLL_TAN_POS_X,
- CALC_ROLL_TAN_POS_Z,
-
- /* neg */
- CALC_ROLL_NEG_X,
- CALC_ROLL_NEG_Y,
- CALC_ROLL_NEG_Z,
-
- CALC_ROLL_TAN_NEG_X,
- CALC_ROLL_TAN_NEG_Z,
-
- /* no sign */
- CALC_ROLL_ACTIVE,
- CALC_ROLL_VIEW,
- CALC_ROLL_CURSOR,
+ /* pos */
+ CALC_ROLL_POS_X = 0,
+ CALC_ROLL_POS_Y,
+ CALC_ROLL_POS_Z,
+
+ CALC_ROLL_TAN_POS_X,
+ CALC_ROLL_TAN_POS_Z,
+
+ /* neg */
+ CALC_ROLL_NEG_X,
+ CALC_ROLL_NEG_Y,
+ CALC_ROLL_NEG_Z,
+
+ CALC_ROLL_TAN_NEG_X,
+ CALC_ROLL_TAN_NEG_Z,
+
+ /* no sign */
+ CALC_ROLL_ACTIVE,
+ CALC_ROLL_VIEW,
+ CALC_ROLL_CURSOR,
} eCalcRollTypes;
static const EnumPropertyItem prop_calc_roll_types[] = {
- {0, "", 0, N_("Positive"), ""},
- {CALC_ROLL_TAN_POS_X, "POS_X", 0, "Local +X Tangent", ""},
- {CALC_ROLL_TAN_POS_Z, "POS_Z", 0, "Local +Z Tangent", ""},
+ {0, "", 0, N_("Positive"), ""},
+ {CALC_ROLL_TAN_POS_X, "POS_X", 0, "Local +X Tangent", ""},
+ {CALC_ROLL_TAN_POS_Z, "POS_Z", 0, "Local +Z Tangent", ""},
- {CALC_ROLL_POS_X, "GLOBAL_POS_X", 0, "Global +X Axis", ""},
- {CALC_ROLL_POS_Y, "GLOBAL_POS_Y", 0, "Global +Y Axis", ""},
- {CALC_ROLL_POS_Z, "GLOBAL_POS_Z", 0, "Global +Z Axis", ""},
+ {CALC_ROLL_POS_X, "GLOBAL_POS_X", 0, "Global +X Axis", ""},
+ {CALC_ROLL_POS_Y, "GLOBAL_POS_Y", 0, "Global +Y Axis", ""},
+ {CALC_ROLL_POS_Z, "GLOBAL_POS_Z", 0, "Global +Z Axis", ""},
- {0, "", 0, N_("Negative"), ""},
+ {0, "", 0, N_("Negative"), ""},
- {CALC_ROLL_TAN_NEG_X, "NEG_X", 0, "Local -X Tangent", ""},
- {CALC_ROLL_TAN_NEG_Z, "NEG_Z", 0, "Local -Z Tangent", ""},
+ {CALC_ROLL_TAN_NEG_X, "NEG_X", 0, "Local -X Tangent", ""},
+ {CALC_ROLL_TAN_NEG_Z, "NEG_Z", 0, "Local -Z Tangent", ""},
- {CALC_ROLL_NEG_X, "GLOBAL_NEG_X", 0, "Global -X Axis", ""},
- {CALC_ROLL_NEG_Y, "GLOBAL_NEG_Y", 0, "Global -Y Axis", ""},
- {CALC_ROLL_NEG_Z, "GLOBAL_NEG_Z", 0, "Global -Z Axis", ""},
+ {CALC_ROLL_NEG_X, "GLOBAL_NEG_X", 0, "Global -X Axis", ""},
+ {CALC_ROLL_NEG_Y, "GLOBAL_NEG_Y", 0, "Global -Y Axis", ""},
+ {CALC_ROLL_NEG_Z, "GLOBAL_NEG_Z", 0, "Global -Z Axis", ""},
- {0, "", 0, N_("Other"), ""},
- {CALC_ROLL_ACTIVE, "ACTIVE", 0, "Active Bone", ""},
- {CALC_ROLL_VIEW, "VIEW", 0, "View Axis", ""},
- {CALC_ROLL_CURSOR, "CURSOR", 0, "Cursor", ""},
- {0, NULL, 0, NULL, NULL},
+ {0, "", 0, N_("Other"), ""},
+ {CALC_ROLL_ACTIVE, "ACTIVE", 0, "Active Bone", ""},
+ {CALC_ROLL_VIEW, "VIEW", 0, "View Axis", ""},
+ {CALC_ROLL_CURSOR, "CURSOR", 0, "Cursor", ""},
+ {0, NULL, 0, NULL, NULL},
};
-
static int armature_calc_roll_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob_active = CTX_data_edit_object(C);
- int ret = OPERATOR_FINISHED;
-
- eCalcRollTypes type = RNA_enum_get(op->ptr, "type");
- const bool axis_only = RNA_boolean_get(op->ptr, "axis_only");
- /* axis_flip when matching the active bone never makes sense */
- bool axis_flip = ((type >= CALC_ROLL_ACTIVE) ? RNA_boolean_get(op->ptr, "axis_flip") :
- (type >= CALC_ROLL_TAN_NEG_X) ? true : false);
-
- 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 changed = false;
-
- float imat[3][3];
- EditBone *ebone;
-
- if ((type >= CALC_ROLL_NEG_X) && (type <= CALC_ROLL_TAN_NEG_Z)) {
- type -= (CALC_ROLL_ACTIVE - CALC_ROLL_NEG_X);
- axis_flip = true;
- }
-
- copy_m3_m4(imat, ob->obmat);
- invert_m3(imat);
-
- if (type == CALC_ROLL_CURSOR) { /* Cursor */
- Scene *scene = CTX_data_scene(C);
- float cursor_local[3];
- const View3DCursor *cursor = &scene->cursor;
-
- invert_m4_m4(ob->imat, ob->obmat);
- copy_v3_v3(cursor_local, cursor->location);
- mul_m4_v3(ob->imat, cursor_local);
-
- /* cursor */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
- float cursor_rel[3];
- sub_v3_v3v3(cursor_rel, cursor_local, ebone->head);
- if (axis_flip) negate_v3(cursor_rel);
- if (normalize_v3(cursor_rel) != 0.0f) {
- ebone->roll = ED_armature_ebone_roll_to_vector(ebone, cursor_rel, axis_only);
- changed = true;
- }
- }
- }
- }
- else if (ELEM(type, CALC_ROLL_TAN_POS_X, CALC_ROLL_TAN_POS_Z)) {
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (ebone->parent) {
- bool is_edit = (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone));
- bool is_edit_parent = (EBONE_VISIBLE(arm, ebone->parent) && EBONE_EDITABLE(ebone->parent));
-
- if (is_edit || is_edit_parent) {
- EditBone *ebone_other = ebone->parent;
- float dir_a[3];
- float dir_b[3];
- float vec[3];
- bool is_vec_zero;
-
- sub_v3_v3v3(dir_a, ebone->tail, ebone->head);
- normalize_v3(dir_a);
-
- /* find the first bone in the chane with a different direction */
- do {
- sub_v3_v3v3(dir_b, ebone_other->head, ebone_other->tail);
- normalize_v3(dir_b);
-
- if (type == CALC_ROLL_TAN_POS_Z) {
- cross_v3_v3v3(vec, dir_a, dir_b);
- }
- else {
- add_v3_v3v3(vec, dir_a, dir_b);
- }
- } while ((is_vec_zero = (normalize_v3(vec) < 0.00001f)) &&
- (ebone_other = ebone_other->parent));
-
- if (!is_vec_zero) {
- if (axis_flip) negate_v3(vec);
-
- if (is_edit) {
- ebone->roll = ED_armature_ebone_roll_to_vector(ebone, vec, axis_only);
- changed = true;
- }
-
- /* parentless bones use cross product with child */
- if (is_edit_parent) {
- if (ebone->parent->parent == NULL) {
- ebone->parent->roll = ED_armature_ebone_roll_to_vector(ebone->parent, vec, axis_only);
- changed = true;
- }
- }
- }
- }
- }
- }
- }
- else {
- float vec[3] = {0.0f, 0.0f, 0.0f};
- if (type == CALC_ROLL_VIEW) { /* View */
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- if (rv3d == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No region view3d available");
- ret = OPERATOR_CANCELLED;
- goto cleanup;
- }
-
- copy_v3_v3(vec, rv3d->viewinv[2]);
- mul_m3_v3(imat, vec);
- }
- else if (type == CALC_ROLL_ACTIVE) {
- float mat[3][3];
- bArmature *arm_active = ob_active->data;
- ebone = (EditBone *)arm_active->act_edbone;
- if (ebone == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active bone set");
- ret = OPERATOR_CANCELLED;
- goto cleanup;
- }
-
- ED_armature_ebone_to_mat3(ebone, mat);
- copy_v3_v3(vec, mat[2]);
- }
- else { /* Axis */
- assert(type <= 5);
- if (type < 3) vec[type] = 1.0f;
- else vec[type - 2] = -1.0f;
- mul_m3_v3(imat, vec);
- normalize_v3(vec);
- }
-
- if (axis_flip) negate_v3(vec);
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
- /* roll func is a callback which assumes that all is well */
- ebone->roll = ED_armature_ebone_roll_to_vector(ebone, vec, axis_only);
- changed = true;
- }
- }
- }
-
- if (arm->flag & ARM_MIRROR_EDIT) {
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- 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))) {
- ebone->roll = -ebone_mirr->roll;
- }
- }
- }
- }
-
- if (changed) {
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- }
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob_active = CTX_data_edit_object(C);
+ int ret = OPERATOR_FINISHED;
+
+ eCalcRollTypes type = RNA_enum_get(op->ptr, "type");
+ const bool axis_only = RNA_boolean_get(op->ptr, "axis_only");
+ /* axis_flip when matching the active bone never makes sense */
+ bool axis_flip = ((type >= CALC_ROLL_ACTIVE) ? RNA_boolean_get(op->ptr, "axis_flip") :
+ (type >= CALC_ROLL_TAN_NEG_X) ? true : false);
+
+ 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 changed = false;
+
+ float imat[3][3];
+ EditBone *ebone;
+
+ if ((type >= CALC_ROLL_NEG_X) && (type <= CALC_ROLL_TAN_NEG_Z)) {
+ type -= (CALC_ROLL_ACTIVE - CALC_ROLL_NEG_X);
+ axis_flip = true;
+ }
+
+ copy_m3_m4(imat, ob->obmat);
+ invert_m3(imat);
+
+ if (type == CALC_ROLL_CURSOR) { /* Cursor */
+ Scene *scene = CTX_data_scene(C);
+ float cursor_local[3];
+ const View3DCursor *cursor = &scene->cursor;
+
+ invert_m4_m4(ob->imat, ob->obmat);
+ copy_v3_v3(cursor_local, cursor->location);
+ mul_m4_v3(ob->imat, cursor_local);
+
+ /* cursor */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
+ float cursor_rel[3];
+ sub_v3_v3v3(cursor_rel, cursor_local, ebone->head);
+ if (axis_flip)
+ negate_v3(cursor_rel);
+ if (normalize_v3(cursor_rel) != 0.0f) {
+ ebone->roll = ED_armature_ebone_roll_to_vector(ebone, cursor_rel, axis_only);
+ changed = true;
+ }
+ }
+ }
+ }
+ else if (ELEM(type, CALC_ROLL_TAN_POS_X, CALC_ROLL_TAN_POS_Z)) {
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ebone->parent) {
+ bool is_edit = (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone));
+ bool is_edit_parent = (EBONE_VISIBLE(arm, ebone->parent) &&
+ EBONE_EDITABLE(ebone->parent));
+
+ if (is_edit || is_edit_parent) {
+ EditBone *ebone_other = ebone->parent;
+ float dir_a[3];
+ float dir_b[3];
+ float vec[3];
+ bool is_vec_zero;
+
+ sub_v3_v3v3(dir_a, ebone->tail, ebone->head);
+ normalize_v3(dir_a);
+
+ /* find the first bone in the chane with a different direction */
+ do {
+ sub_v3_v3v3(dir_b, ebone_other->head, ebone_other->tail);
+ normalize_v3(dir_b);
+
+ if (type == CALC_ROLL_TAN_POS_Z) {
+ cross_v3_v3v3(vec, dir_a, dir_b);
+ }
+ else {
+ add_v3_v3v3(vec, dir_a, dir_b);
+ }
+ } while ((is_vec_zero = (normalize_v3(vec) < 0.00001f)) &&
+ (ebone_other = ebone_other->parent));
+
+ if (!is_vec_zero) {
+ if (axis_flip)
+ negate_v3(vec);
+
+ if (is_edit) {
+ ebone->roll = ED_armature_ebone_roll_to_vector(ebone, vec, axis_only);
+ changed = true;
+ }
+
+ /* parentless bones use cross product with child */
+ if (is_edit_parent) {
+ if (ebone->parent->parent == NULL) {
+ ebone->parent->roll = ED_armature_ebone_roll_to_vector(
+ ebone->parent, vec, axis_only);
+ changed = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ float vec[3] = {0.0f, 0.0f, 0.0f};
+ if (type == CALC_ROLL_VIEW) { /* View */
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if (rv3d == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No region view3d available");
+ ret = OPERATOR_CANCELLED;
+ goto cleanup;
+ }
+
+ copy_v3_v3(vec, rv3d->viewinv[2]);
+ mul_m3_v3(imat, vec);
+ }
+ else if (type == CALC_ROLL_ACTIVE) {
+ float mat[3][3];
+ bArmature *arm_active = ob_active->data;
+ ebone = (EditBone *)arm_active->act_edbone;
+ if (ebone == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active bone set");
+ ret = OPERATOR_CANCELLED;
+ goto cleanup;
+ }
+
+ ED_armature_ebone_to_mat3(ebone, mat);
+ copy_v3_v3(vec, mat[2]);
+ }
+ else { /* Axis */
+ assert(type <= 5);
+ if (type < 3)
+ vec[type] = 1.0f;
+ else
+ vec[type - 2] = -1.0f;
+ mul_m3_v3(imat, vec);
+ normalize_v3(vec);
+ }
+
+ if (axis_flip)
+ negate_v3(vec);
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
+ /* roll func is a callback which assumes that all is well */
+ ebone->roll = ED_armature_ebone_roll_to_vector(ebone, vec, axis_only);
+ changed = true;
+ }
+ }
+ }
+
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ 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))) {
+ ebone->roll = -ebone_mirr->roll;
+ }
+ }
+ }
+ }
+
+ if (changed) {
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ }
cleanup:
- MEM_freeN(objects);
- return ret;
+ MEM_freeN(objects);
+ return ret;
}
void ARMATURE_OT_calculate_roll(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Recalculate Roll";
- ot->idname = "ARMATURE_OT_calculate_roll";
- ot->description = "Automatically fix alignment of select bones' axes";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = armature_calc_roll_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_calc_roll_types, CALC_ROLL_TAN_POS_X, "Type", "");
- RNA_def_boolean(ot->srna, "axis_flip", 0, "Flip Axis", "Negate the alignment axis");
- RNA_def_boolean(ot->srna, "axis_only", 0, "Shortest Rotation", "Ignore the axis direction, use the shortest rotation to align");
+ /* identifiers */
+ ot->name = "Recalculate Roll";
+ ot->idname = "ARMATURE_OT_calculate_roll";
+ ot->description = "Automatically fix alignment of select bones' axes";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = armature_calc_roll_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_calc_roll_types, CALC_ROLL_TAN_POS_X, "Type", "");
+ RNA_def_boolean(ot->srna, "axis_flip", 0, "Flip Axis", "Negate the alignment axis");
+ RNA_def_boolean(ot->srna,
+ "axis_only",
+ 0,
+ "Shortest Rotation",
+ "Ignore the axis direction, use the shortest rotation to align");
}
static int armature_roll_clear_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const float roll = RNA_float_get(op->ptr, "roll");
-
- 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 changed = false;
-
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
- /* Roll func is a callback which assumes that all is well. */
- ebone->roll = roll;
- changed = true;
- }
- }
-
- if (arm->flag & ARM_MIRROR_EDIT) {
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- 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))) {
- ebone->roll = -ebone_mirr->roll;
- changed = true;
- }
- }
- }
- }
-
- if (changed) {
- /* Note, notifier might evolve. */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const float roll = RNA_float_get(op->ptr, "roll");
+
+ 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 changed = false;
+
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
+ /* Roll func is a callback which assumes that all is well. */
+ ebone->roll = roll;
+ changed = true;
+ }
+ }
+
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ 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))) {
+ ebone->roll = -ebone_mirr->roll;
+ changed = true;
+ }
+ }
+ }
+ }
+
+ if (changed) {
+ /* Note, notifier might evolve. */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_roll_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Roll";
- ot->idname = "ARMATURE_OT_roll_clear";
- ot->description = "Clear roll for selected bones";
-
- /* api callbacks */
- ot->exec = armature_roll_clear_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_float_rotation(
- ot->srna, "roll", 0, NULL, DEG2RADF(-360.0f), DEG2RADF(360.0f),
- "Roll", "", DEG2RADF(-360.0f), DEG2RADF(360.0f));
+ /* identifiers */
+ ot->name = "Clear Roll";
+ ot->idname = "ARMATURE_OT_roll_clear";
+ ot->description = "Clear roll for selected bones";
+
+ /* api callbacks */
+ ot->exec = armature_roll_clear_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_float_rotation(ot->srna,
+ "roll",
+ 0,
+ NULL,
+ DEG2RADF(-360.0f),
+ DEG2RADF(360.0f),
+ "Roll",
+ "",
+ DEG2RADF(-360.0f),
+ DEG2RADF(360.0f));
}
/* ******************************** Chain-Based Tools ********************************* */
/* temporary data-structure for merge/fill bones */
typedef struct EditBonePoint {
- struct EditBonePoint *next, *prev;
+ struct EditBonePoint *next, *prev;
- EditBone *head_owner; /* EditBone which uses this point as a 'head' point */
- EditBone *tail_owner; /* EditBone which uses this point as a 'tail' point */
+ EditBone *head_owner; /* EditBone which uses this point as a 'head' point */
+ EditBone *tail_owner; /* EditBone which uses this point as a 'tail' point */
- float vec[3]; /* the actual location of the point in local/EditMode space */
+ float vec[3]; /* the actual location of the point in local/EditMode space */
} EditBonePoint;
/* find chain-tips (i.e. bones without children) */
static void chains_find_tips(ListBase *edbo, ListBase *list)
{
- EditBone *curBone, *ebo;
- LinkData *ld;
-
- /* note: this is potentially very slow ... there's got to be a better way */
- for (curBone = edbo->first; curBone; curBone = curBone->next) {
- short stop = 0;
-
- /* is this bone contained within any existing chain? (skip if so) */
- for (ld = list->first; ld; ld = ld->next) {
- for (ebo = ld->data; ebo; ebo = ebo->parent) {
- if (ebo == curBone) {
- stop = 1;
- break;
- }
- }
-
- if (stop) break;
- }
- /* skip current bone if it is part of an existing chain */
- if (stop) continue;
-
- /* is any existing chain part of the chain formed by this bone? */
- stop = 0;
- for (ebo = curBone->parent; ebo; ebo = ebo->parent) {
- for (ld = list->first; ld; ld = ld->next) {
- if (ld->data == ebo) {
- ld->data = curBone;
- stop = 1;
- break;
- }
- }
-
- if (stop) break;
- }
- /* current bone has already been added to a chain? */
- if (stop) continue;
-
- /* add current bone to a new chain */
- ld = MEM_callocN(sizeof(LinkData), "BoneChain");
- ld->data = curBone;
- BLI_addtail(list, ld);
- }
+ EditBone *curBone, *ebo;
+ LinkData *ld;
+
+ /* note: this is potentially very slow ... there's got to be a better way */
+ for (curBone = edbo->first; curBone; curBone = curBone->next) {
+ short stop = 0;
+
+ /* is this bone contained within any existing chain? (skip if so) */
+ for (ld = list->first; ld; ld = ld->next) {
+ for (ebo = ld->data; ebo; ebo = ebo->parent) {
+ if (ebo == curBone) {
+ stop = 1;
+ break;
+ }
+ }
+
+ if (stop)
+ break;
+ }
+ /* skip current bone if it is part of an existing chain */
+ if (stop)
+ continue;
+
+ /* is any existing chain part of the chain formed by this bone? */
+ stop = 0;
+ for (ebo = curBone->parent; ebo; ebo = ebo->parent) {
+ for (ld = list->first; ld; ld = ld->next) {
+ if (ld->data == ebo) {
+ ld->data = curBone;
+ stop = 1;
+ break;
+ }
+ }
+
+ if (stop)
+ break;
+ }
+ /* current bone has already been added to a chain? */
+ if (stop)
+ continue;
+
+ /* add current bone to a new chain */
+ ld = MEM_callocN(sizeof(LinkData), "BoneChain");
+ ld->data = curBone;
+ BLI_addtail(list, ld);
+ }
}
/* --------------------- */
static void fill_add_joint(EditBone *ebo, short eb_tail, ListBase *points)
{
- EditBonePoint *ebp;
- float vec[3];
- short found = 0;
-
- if (eb_tail) {
- copy_v3_v3(vec, ebo->tail);
- }
- else {
- copy_v3_v3(vec, ebo->head);
- }
-
- for (ebp = points->first; ebp; ebp = ebp->next) {
- if (equals_v3v3(ebp->vec, vec)) {
- if (eb_tail) {
- if ((ebp->head_owner) && (ebp->head_owner->parent == ebo)) {
- /* so this bone's tail owner is this bone */
- ebp->tail_owner = ebo;
- found = 1;
- break;
- }
- }
- else {
- if ((ebp->tail_owner) && (ebo->parent == ebp->tail_owner)) {
- /* so this bone's head owner is this bone */
- ebp->head_owner = ebo;
- found = 1;
- break;
- }
- }
- }
- }
-
- /* allocate a new point if no existing point was related */
- if (found == 0) {
- ebp = MEM_callocN(sizeof(EditBonePoint), "EditBonePoint");
-
- if (eb_tail) {
- copy_v3_v3(ebp->vec, ebo->tail);
- ebp->tail_owner = ebo;
- }
- else {
- copy_v3_v3(ebp->vec, ebo->head);
- ebp->head_owner = ebo;
- }
-
- BLI_addtail(points, ebp);
- }
+ EditBonePoint *ebp;
+ float vec[3];
+ short found = 0;
+
+ if (eb_tail) {
+ copy_v3_v3(vec, ebo->tail);
+ }
+ else {
+ copy_v3_v3(vec, ebo->head);
+ }
+
+ for (ebp = points->first; ebp; ebp = ebp->next) {
+ if (equals_v3v3(ebp->vec, vec)) {
+ if (eb_tail) {
+ if ((ebp->head_owner) && (ebp->head_owner->parent == ebo)) {
+ /* so this bone's tail owner is this bone */
+ ebp->tail_owner = ebo;
+ found = 1;
+ break;
+ }
+ }
+ else {
+ if ((ebp->tail_owner) && (ebo->parent == ebp->tail_owner)) {
+ /* so this bone's head owner is this bone */
+ ebp->head_owner = ebo;
+ found = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ /* allocate a new point if no existing point was related */
+ if (found == 0) {
+ ebp = MEM_callocN(sizeof(EditBonePoint), "EditBonePoint");
+
+ if (eb_tail) {
+ copy_v3_v3(ebp->vec, ebo->tail);
+ ebp->tail_owner = ebo;
+ }
+ else {
+ copy_v3_v3(ebp->vec, ebo->head);
+ ebp->head_owner = ebo;
+ }
+
+ BLI_addtail(points, ebp);
+ }
}
/* bone adding between selected joints */
static int armature_fill_bones_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- ListBase points = {NULL, NULL};
- EditBone *newbone = NULL;
- int count;
- bool mixed_object_error = false;
-
- /* loop over all bones, and only consider if visible */
- bArmature *arm = NULL;
- CTX_DATA_BEGIN_WITH_ID(C, EditBone *, ebone, visible_bones, bArmature *, arm_iter)
- {
- bool check = false;
- if (!(ebone->flag & BONE_CONNECTED) && (ebone->flag & BONE_ROOTSEL)) {
- fill_add_joint(ebone, 0, &points);
- check = true;
- }
- if (ebone->flag & BONE_TIPSEL) {
- fill_add_joint(ebone, 1, &points);
- check = true;
- }
-
- if (check) {
- if (arm && (arm != arm_iter)) {
- mixed_object_error = true;
- }
- arm = arm_iter;
- }
- }
- CTX_DATA_END;
-
- /* the number of joints determines how we fill:
- * 1) between joint and cursor (joint=head, cursor=tail)
- * 2) between the two joints (order is dependent on active-bone/hierarchy)
- * 3+) error (a smarter method involving finding chains needs to be worked out
- */
- count = BLI_listbase_count(&points);
-
- if (count == 0) {
- BKE_report(op->reports, RPT_ERROR, "No joints selected");
- return OPERATOR_CANCELLED;
- }
- else if (mixed_object_error) {
- BKE_report(op->reports, RPT_ERROR, "Bones for different objects selected");
- BLI_freelistN(&points);
- return OPERATOR_CANCELLED;
- }
-
- Object *obedit = NULL;
- {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- FOREACH_OBJECT_IN_EDIT_MODE_BEGIN (view_layer, v3d, ob_iter) {
- if (ob_iter->data == arm) {
- obedit = ob_iter;
- }
- }
- FOREACH_OBJECT_IN_MODE_END;
- }
- BLI_assert(obedit != NULL);
-
- if (count == 1) {
- EditBonePoint *ebp;
- float curs[3];
-
- /* Get Points - selected joint */
- ebp = points.first;
-
- /* Get points - cursor (tail) */
- invert_m4_m4(obedit->imat, obedit->obmat);
- mul_v3_m4v3(curs, obedit->imat, scene->cursor.location);
-
- /* Create a bone */
- newbone = add_points_bone(obedit, ebp->vec, curs);
- }
- else if (count == 2) {
- EditBonePoint *ebp_a, *ebp_b;
- float head[3], tail[3];
- short headtail = 0;
-
- /* check that the points don't belong to the same bone */
- ebp_a = (EditBonePoint *)points.first;
- ebp_b = ebp_a->next;
-
- if (((ebp_a->head_owner == ebp_b->tail_owner) && (ebp_a->head_owner != NULL)) ||
- ((ebp_a->tail_owner == ebp_b->head_owner) && (ebp_a->tail_owner != NULL)))
- {
- BKE_report(op->reports, RPT_ERROR, "Same bone selected...");
- BLI_freelistN(&points);
- return OPERATOR_CANCELLED;
- }
-
- /* find which one should be the 'head' */
- if ((ebp_a->head_owner && ebp_b->head_owner) || (ebp_a->tail_owner && ebp_b->tail_owner)) {
- /* use active, nice predictable */
- if (arm->act_edbone && ELEM(arm->act_edbone, ebp_a->head_owner, ebp_a->tail_owner)) {
- headtail = 1;
- }
- else if (arm->act_edbone && ELEM(arm->act_edbone, ebp_b->head_owner, ebp_b->tail_owner)) {
- headtail = 2;
- }
- else {
- /* rule: whichever one is closer to 3d-cursor */
- float curs[3];
- float dist_sq_a, dist_sq_b;
-
- /* get cursor location */
- invert_m4_m4(obedit->imat, obedit->obmat);
- mul_v3_m4v3(curs, obedit->imat, scene->cursor.location);
-
- /* get distances */
- dist_sq_a = len_squared_v3v3(ebp_a->vec, curs);
- dist_sq_b = len_squared_v3v3(ebp_b->vec, curs);
-
- /* compare distances - closer one therefore acts as direction for bone to go */
- headtail = (dist_sq_a < dist_sq_b) ? 2 : 1;
- }
- }
- else if (ebp_a->head_owner) {
- headtail = 1;
- }
- else if (ebp_b->head_owner) {
- headtail = 2;
- }
-
- /* assign head/tail combinations */
- if (headtail == 2) {
- copy_v3_v3(head, ebp_a->vec);
- copy_v3_v3(tail, ebp_b->vec);
- }
- else if (headtail == 1) {
- copy_v3_v3(head, ebp_b->vec);
- copy_v3_v3(tail, ebp_a->vec);
- }
-
- /* add new bone and parent it to the appropriate end */
- if (headtail) {
- newbone = add_points_bone(obedit, head, tail);
-
- /* do parenting (will need to set connected flag too) */
- if (headtail == 2) {
- /* ebp tail or head - tail gets priority */
- if (ebp_a->tail_owner)
- newbone->parent = ebp_a->tail_owner;
- else
- newbone->parent = ebp_a->head_owner;
- }
- else {
- /* ebp_b tail or head - tail gets priority */
- if (ebp_b->tail_owner)
- newbone->parent = ebp_b->tail_owner;
- else
- newbone->parent = ebp_b->head_owner;
- }
-
- /* don't set for bone connecting two head points of bones */
- if (ebp_a->tail_owner || ebp_b->tail_owner) {
- newbone->flag |= BONE_CONNECTED;
- }
- }
- }
- else {
- BKE_reportf(op->reports, RPT_ERROR, "Too many points selected: %d", count);
- BLI_freelistN(&points);
- return OPERATOR_CANCELLED;
- }
-
- if (newbone) {
- ED_armature_edit_deselect_all(obedit);
- arm->act_edbone = newbone;
- newbone->flag |= BONE_TIPSEL;
- }
-
- /* updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
-
- /* free points */
- BLI_freelistN(&points);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ ListBase points = {NULL, NULL};
+ EditBone *newbone = NULL;
+ int count;
+ bool mixed_object_error = false;
+
+ /* loop over all bones, and only consider if visible */
+ bArmature *arm = NULL;
+ CTX_DATA_BEGIN_WITH_ID(C, EditBone *, ebone, visible_bones, bArmature *, arm_iter)
+ {
+ bool check = false;
+ if (!(ebone->flag & BONE_CONNECTED) && (ebone->flag & BONE_ROOTSEL)) {
+ fill_add_joint(ebone, 0, &points);
+ check = true;
+ }
+ if (ebone->flag & BONE_TIPSEL) {
+ fill_add_joint(ebone, 1, &points);
+ check = true;
+ }
+
+ if (check) {
+ if (arm && (arm != arm_iter)) {
+ mixed_object_error = true;
+ }
+ arm = arm_iter;
+ }
+ }
+ CTX_DATA_END;
+
+ /* the number of joints determines how we fill:
+ * 1) between joint and cursor (joint=head, cursor=tail)
+ * 2) between the two joints (order is dependent on active-bone/hierarchy)
+ * 3+) error (a smarter method involving finding chains needs to be worked out
+ */
+ count = BLI_listbase_count(&points);
+
+ if (count == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No joints selected");
+ return OPERATOR_CANCELLED;
+ }
+ else if (mixed_object_error) {
+ BKE_report(op->reports, RPT_ERROR, "Bones for different objects selected");
+ BLI_freelistN(&points);
+ return OPERATOR_CANCELLED;
+ }
+
+ Object *obedit = NULL;
+ {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ FOREACH_OBJECT_IN_EDIT_MODE_BEGIN (view_layer, v3d, ob_iter) {
+ if (ob_iter->data == arm) {
+ obedit = ob_iter;
+ }
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+ }
+ BLI_assert(obedit != NULL);
+
+ if (count == 1) {
+ EditBonePoint *ebp;
+ float curs[3];
+
+ /* Get Points - selected joint */
+ ebp = points.first;
+
+ /* Get points - cursor (tail) */
+ invert_m4_m4(obedit->imat, obedit->obmat);
+ mul_v3_m4v3(curs, obedit->imat, scene->cursor.location);
+
+ /* Create a bone */
+ newbone = add_points_bone(obedit, ebp->vec, curs);
+ }
+ else if (count == 2) {
+ EditBonePoint *ebp_a, *ebp_b;
+ float head[3], tail[3];
+ short headtail = 0;
+
+ /* check that the points don't belong to the same bone */
+ ebp_a = (EditBonePoint *)points.first;
+ ebp_b = ebp_a->next;
+
+ if (((ebp_a->head_owner == ebp_b->tail_owner) && (ebp_a->head_owner != NULL)) ||
+ ((ebp_a->tail_owner == ebp_b->head_owner) && (ebp_a->tail_owner != NULL))) {
+ BKE_report(op->reports, RPT_ERROR, "Same bone selected...");
+ BLI_freelistN(&points);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* find which one should be the 'head' */
+ if ((ebp_a->head_owner && ebp_b->head_owner) || (ebp_a->tail_owner && ebp_b->tail_owner)) {
+ /* use active, nice predictable */
+ if (arm->act_edbone && ELEM(arm->act_edbone, ebp_a->head_owner, ebp_a->tail_owner)) {
+ headtail = 1;
+ }
+ else if (arm->act_edbone && ELEM(arm->act_edbone, ebp_b->head_owner, ebp_b->tail_owner)) {
+ headtail = 2;
+ }
+ else {
+ /* rule: whichever one is closer to 3d-cursor */
+ float curs[3];
+ float dist_sq_a, dist_sq_b;
+
+ /* get cursor location */
+ invert_m4_m4(obedit->imat, obedit->obmat);
+ mul_v3_m4v3(curs, obedit->imat, scene->cursor.location);
+
+ /* get distances */
+ dist_sq_a = len_squared_v3v3(ebp_a->vec, curs);
+ dist_sq_b = len_squared_v3v3(ebp_b->vec, curs);
+
+ /* compare distances - closer one therefore acts as direction for bone to go */
+ headtail = (dist_sq_a < dist_sq_b) ? 2 : 1;
+ }
+ }
+ else if (ebp_a->head_owner) {
+ headtail = 1;
+ }
+ else if (ebp_b->head_owner) {
+ headtail = 2;
+ }
+
+ /* assign head/tail combinations */
+ if (headtail == 2) {
+ copy_v3_v3(head, ebp_a->vec);
+ copy_v3_v3(tail, ebp_b->vec);
+ }
+ else if (headtail == 1) {
+ copy_v3_v3(head, ebp_b->vec);
+ copy_v3_v3(tail, ebp_a->vec);
+ }
+
+ /* add new bone and parent it to the appropriate end */
+ if (headtail) {
+ newbone = add_points_bone(obedit, head, tail);
+
+ /* do parenting (will need to set connected flag too) */
+ if (headtail == 2) {
+ /* ebp tail or head - tail gets priority */
+ if (ebp_a->tail_owner)
+ newbone->parent = ebp_a->tail_owner;
+ else
+ newbone->parent = ebp_a->head_owner;
+ }
+ else {
+ /* ebp_b tail or head - tail gets priority */
+ if (ebp_b->tail_owner)
+ newbone->parent = ebp_b->tail_owner;
+ else
+ newbone->parent = ebp_b->head_owner;
+ }
+
+ /* don't set for bone connecting two head points of bones */
+ if (ebp_a->tail_owner || ebp_b->tail_owner) {
+ newbone->flag |= BONE_CONNECTED;
+ }
+ }
+ }
+ else {
+ BKE_reportf(op->reports, RPT_ERROR, "Too many points selected: %d", count);
+ BLI_freelistN(&points);
+ return OPERATOR_CANCELLED;
+ }
+
+ if (newbone) {
+ ED_armature_edit_deselect_all(obedit);
+ arm->act_edbone = newbone;
+ newbone->flag |= BONE_TIPSEL;
+ }
+
+ /* updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
+
+ /* free points */
+ BLI_freelistN(&points);
+
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_fill(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Fill Between Joints";
- ot->idname = "ARMATURE_OT_fill";
- ot->description = "Add bone between selected joint(s) and/or 3D-Cursor";
+ /* identifiers */
+ ot->name = "Fill Between Joints";
+ ot->idname = "ARMATURE_OT_fill";
+ ot->description = "Add bone between selected joint(s) and/or 3D-Cursor";
- /* callbacks */
- ot->exec = armature_fill_bones_exec;
- ot->poll = ED_operator_editarmature;
+ /* callbacks */
+ ot->exec = armature_fill_bones_exec;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* --------------------- */
@@ -852,194 +878,193 @@ void ARMATURE_OT_fill(wmOperatorType *ot)
/* 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)
+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_SCALE |
- BONE_NO_CYCLICOFFSET | BONE_NO_LOCAL_LOCATION | BONE_DONE);
-
- /* 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);
+ 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_SCALE |
+ BONE_NO_CYCLICOFFSET | BONE_NO_LOCAL_LOCATION | BONE_DONE);
+
+ /* 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);
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ 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);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
+ }
+ 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", "");
+ 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", "");
}
/* --------------------- */
@@ -1053,125 +1078,126 @@ void ARMATURE_OT_merge(wmOperatorType *ot)
/* helper to clear BONE_TRANSFORM flags */
static void armature_clear_swap_done_flags(bArmature *arm)
{
- EditBone *ebone;
+ EditBone *ebone;
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- ebone->flag &= ~BONE_TRANSFORM;
- }
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ ebone->flag &= ~BONE_TRANSFORM;
+ }
}
static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
{
- 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;
-
- ListBase chains = {NULL, NULL};
- LinkData *chain;
-
- /* get chains of bones (ends on chains) */
- chains_find_tips(arm->edbo, &chains);
- if (BLI_listbase_is_empty(&chains)) {
- continue;
- }
-
- /* ensure that mirror bones will also be operated on */
- armature_tag_select_mirrored(arm);
-
- /* clear BONE_TRANSFORM flags
- * - used to prevent duplicate/canceling operations from occurring [#34123]
- * - BONE_DONE cannot be used here as that's already used for mirroring
- */
- armature_clear_swap_done_flags(arm);
-
- /* loop over chains, only considering selected and visible bones */
- for (chain = chains.first; chain; chain = chain->next) {
- EditBone *ebo, *child = NULL, *parent = NULL;
-
- /* loop over bones in chain */
- for (ebo = chain->data; ebo; ebo = parent) {
- /* parent is this bone's original parent
- * - we store this, as the next bone that is checked is this one
- * but the value of ebo->parent may change here...
- */
- parent = ebo->parent;
-
- /* skip bone if already handled... [#34123] */
- if ((ebo->flag & BONE_TRANSFORM) == 0) {
- /* only if selected and editable */
- if (EBONE_VISIBLE(arm, ebo) && EBONE_EDITABLE(ebo)) {
- /* swap head and tail coordinates */
- swap_v3_v3(ebo->head, ebo->tail);
-
- /* do parent swapping:
- * - use 'child' as new parent
- * - connected flag is only set if points are coincidental
- */
- ebo->parent = child;
- if ((child) && equals_v3v3(ebo->head, child->tail))
- ebo->flag |= BONE_CONNECTED;
- else
- ebo->flag &= ~BONE_CONNECTED;
-
- /* get next bones
- * - child will become the new parent of next bone
- */
- child = ebo;
- }
- else {
- /* not swapping this bone, however, if its 'parent' got swapped, unparent us from it
- * as it will be facing in opposite direction
- */
- if ((parent) && (EBONE_VISIBLE(arm, parent) && EBONE_EDITABLE(parent))) {
- ebo->parent = NULL;
- ebo->flag &= ~BONE_CONNECTED;
- }
-
- /* get next bones
- * - child will become new parent of next bone (not swapping occurred,
- * so set to NULL to prevent infinite-loop)
- */
- child = NULL;
- }
-
- /* tag as done (to prevent double-swaps) */
- ebo->flag |= BONE_TRANSFORM;
- }
- }
- }
-
- /* free chains */
- BLI_freelistN(&chains);
-
- /* clear temp flags */
- armature_clear_swap_done_flags(arm);
- armature_tag_unselect(arm);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ 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;
+
+ ListBase chains = {NULL, NULL};
+ LinkData *chain;
+
+ /* get chains of bones (ends on chains) */
+ chains_find_tips(arm->edbo, &chains);
+ if (BLI_listbase_is_empty(&chains)) {
+ continue;
+ }
+
+ /* ensure that mirror bones will also be operated on */
+ armature_tag_select_mirrored(arm);
+
+ /* clear BONE_TRANSFORM flags
+ * - used to prevent duplicate/canceling operations from occurring [#34123]
+ * - BONE_DONE cannot be used here as that's already used for mirroring
+ */
+ armature_clear_swap_done_flags(arm);
+
+ /* loop over chains, only considering selected and visible bones */
+ for (chain = chains.first; chain; chain = chain->next) {
+ EditBone *ebo, *child = NULL, *parent = NULL;
+
+ /* loop over bones in chain */
+ for (ebo = chain->data; ebo; ebo = parent) {
+ /* parent is this bone's original parent
+ * - we store this, as the next bone that is checked is this one
+ * but the value of ebo->parent may change here...
+ */
+ parent = ebo->parent;
+
+ /* skip bone if already handled... [#34123] */
+ if ((ebo->flag & BONE_TRANSFORM) == 0) {
+ /* only if selected and editable */
+ if (EBONE_VISIBLE(arm, ebo) && EBONE_EDITABLE(ebo)) {
+ /* swap head and tail coordinates */
+ swap_v3_v3(ebo->head, ebo->tail);
+
+ /* do parent swapping:
+ * - use 'child' as new parent
+ * - connected flag is only set if points are coincidental
+ */
+ ebo->parent = child;
+ if ((child) && equals_v3v3(ebo->head, child->tail))
+ ebo->flag |= BONE_CONNECTED;
+ else
+ ebo->flag &= ~BONE_CONNECTED;
+
+ /* get next bones
+ * - child will become the new parent of next bone
+ */
+ child = ebo;
+ }
+ else {
+ /* not swapping this bone, however, if its 'parent' got swapped, unparent us from it
+ * as it will be facing in opposite direction
+ */
+ if ((parent) && (EBONE_VISIBLE(arm, parent) && EBONE_EDITABLE(parent))) {
+ ebo->parent = NULL;
+ ebo->flag &= ~BONE_CONNECTED;
+ }
+
+ /* get next bones
+ * - child will become new parent of next bone (not swapping occurred,
+ * so set to NULL to prevent infinite-loop)
+ */
+ child = NULL;
+ }
+
+ /* tag as done (to prevent double-swaps) */
+ ebo->flag |= BONE_TRANSFORM;
+ }
+ }
+ }
+
+ /* free chains */
+ BLI_freelistN(&chains);
+
+ /* clear temp flags */
+ armature_clear_swap_done_flags(arm);
+ armature_tag_unselect(arm);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_switch_direction(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Switch Direction";
- ot->idname = "ARMATURE_OT_switch_direction";
- ot->description = "Change the direction that a chain of bones points in (head <-> tail swap)";
+ /* identifiers */
+ ot->name = "Switch Direction";
+ ot->idname = "ARMATURE_OT_switch_direction";
+ ot->description = "Change the direction that a chain of bones points in (head <-> tail swap)";
- /* api callbacks */
- ot->exec = armature_switch_direction_exec;
- ot->poll = ED_operator_editarmature;
+ /* api callbacks */
+ ot->exec = armature_switch_direction_exec;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************************* Align ******************************* */
@@ -1179,538 +1205,544 @@ void ARMATURE_OT_switch_direction(wmOperatorType *ot)
/* helper to fix a ebone position if its parent has moved due to alignment*/
static void fix_connected_bone(EditBone *ebone)
{
- float diff[3];
+ float diff[3];
- if (!(ebone->parent) || !(ebone->flag & BONE_CONNECTED) || equals_v3v3(ebone->parent->tail, ebone->head))
- return;
+ if (!(ebone->parent) || !(ebone->flag & BONE_CONNECTED) ||
+ equals_v3v3(ebone->parent->tail, ebone->head))
+ return;
- /* if the parent has moved we translate child's head and tail accordingly */
- sub_v3_v3v3(diff, ebone->parent->tail, ebone->head);
- add_v3_v3(ebone->head, diff);
- add_v3_v3(ebone->tail, diff);
+ /* if the parent has moved we translate child's head and tail accordingly */
+ sub_v3_v3v3(diff, ebone->parent->tail, ebone->head);
+ add_v3_v3(ebone->head, diff);
+ add_v3_v3(ebone->tail, diff);
}
/* helper to recursively find chains of connected bones starting at ebone and fix their position */
static void fix_editbone_connected_children(ListBase *edbo, EditBone *ebone)
{
- EditBone *selbone;
-
- for (selbone = edbo->first; selbone; selbone = selbone->next) {
- if ((selbone->parent) && (selbone->parent == ebone) && (selbone->flag & BONE_CONNECTED)) {
- fix_connected_bone(selbone);
- fix_editbone_connected_children(edbo, selbone);
- }
- }
+ EditBone *selbone;
+
+ for (selbone = edbo->first; selbone; selbone = selbone->next) {
+ if ((selbone->parent) && (selbone->parent == ebone) && (selbone->flag & BONE_CONNECTED)) {
+ fix_connected_bone(selbone);
+ fix_editbone_connected_children(edbo, selbone);
+ }
+ }
}
static void bone_align_to_bone(ListBase *edbo, EditBone *selbone, EditBone *actbone)
{
- float selboneaxis[3], actboneaxis[3], length;
+ float selboneaxis[3], actboneaxis[3], length;
- sub_v3_v3v3(actboneaxis, actbone->tail, actbone->head);
- normalize_v3(actboneaxis);
+ sub_v3_v3v3(actboneaxis, actbone->tail, actbone->head);
+ normalize_v3(actboneaxis);
- sub_v3_v3v3(selboneaxis, selbone->tail, selbone->head);
- length = len_v3(selboneaxis);
+ sub_v3_v3v3(selboneaxis, selbone->tail, selbone->head);
+ length = len_v3(selboneaxis);
- mul_v3_fl(actboneaxis, length);
- add_v3_v3v3(selbone->tail, selbone->head, actboneaxis);
- selbone->roll = actbone->roll;
+ mul_v3_fl(actboneaxis, length);
+ add_v3_v3v3(selbone->tail, selbone->head, actboneaxis);
+ selbone->roll = actbone->roll;
- /* if the bone being aligned has connected descendants they must be moved
- * according to their parent new position, otherwise they would be left
- * in an inconsistent state: connected but away from the parent*/
- fix_editbone_connected_children(edbo, selbone);
+ /* if the bone being aligned has connected descendants they must be moved
+ * according to their parent new position, otherwise they would be left
+ * in an inconsistent state: connected but away from the parent*/
+ fix_editbone_connected_children(edbo, selbone);
}
static int armature_align_bones_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_edit_object(C);
- bArmature *arm = (bArmature *)ob->data;
- EditBone *actbone = CTX_data_active_bone(C);
- EditBone *actmirb = NULL;
- int num_selected_bones;
-
- /* there must be an active bone */
- if (actbone == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
- return OPERATOR_CANCELLED;
- }
- else if (arm->flag & ARM_MIRROR_EDIT) {
- /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
- * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone
- * (i.e. selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
- * This is useful for arm-chains, for example parenting lower arm to upper arm
- * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
- * then just use actbone. Useful when doing upper arm to spine.
- */
- actmirb = ED_armature_ebone_get_mirrored(arm->edbo, actbone);
- if (actmirb == NULL)
- actmirb = actbone;
- }
-
- /* if there is only 1 selected bone, we assume that that is the active bone,
- * since a user will need to have clicked on a bone (thus selecting it) to make it active
- */
- num_selected_bones = CTX_DATA_COUNT(C, selected_editable_bones);
- if (num_selected_bones <= 1) {
- /* When only the active bone is selected, and it has a parent,
- * align it to the parent, as that is the only possible outcome.
- */
- if (actbone->parent) {
- bone_align_to_bone(arm->edbo, actbone, actbone->parent);
-
- if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
- bone_align_to_bone(arm->edbo, actmirb, actmirb->parent);
-
- BKE_reportf(op->reports, RPT_INFO, "Aligned bone '%s' to parent", actbone->name);
- }
- }
- else {
- /* Align 'selected' bones to the active one
- * - the context iterator contains both selected bones and their mirrored copies,
- * so we assume that unselected bones are mirrored copies of some selected bone
- * - since the active one (and/or its mirror) will also be selected, we also need
- * to check that we are not trying to operate on them, since such an operation
- * would cause errors
- */
-
- /* align selected bones to the active one */
- CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
- {
- if (ELEM(ebone, actbone, actmirb) == 0) {
- if (ebone->flag & BONE_SELECTED)
- bone_align_to_bone(arm->edbo, ebone, actbone);
- else
- bone_align_to_bone(arm->edbo, ebone, actmirb);
- }
- }
- CTX_DATA_END;
-
- BKE_reportf(op->reports, RPT_INFO, "%d bones aligned to bone '%s'", num_selected_bones, actbone->name);
- }
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
- return OPERATOR_FINISHED;
+ Object *ob = CTX_data_edit_object(C);
+ bArmature *arm = (bArmature *)ob->data;
+ EditBone *actbone = CTX_data_active_bone(C);
+ EditBone *actmirb = NULL;
+ int num_selected_bones;
+
+ /* there must be an active bone */
+ if (actbone == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
+ return OPERATOR_CANCELLED;
+ }
+ else if (arm->flag & ARM_MIRROR_EDIT) {
+ /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
+ * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone
+ * (i.e. selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
+ * This is useful for arm-chains, for example parenting lower arm to upper arm
+ * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
+ * then just use actbone. Useful when doing upper arm to spine.
+ */
+ actmirb = ED_armature_ebone_get_mirrored(arm->edbo, actbone);
+ if (actmirb == NULL)
+ actmirb = actbone;
+ }
+
+ /* if there is only 1 selected bone, we assume that that is the active bone,
+ * since a user will need to have clicked on a bone (thus selecting it) to make it active
+ */
+ num_selected_bones = CTX_DATA_COUNT(C, selected_editable_bones);
+ if (num_selected_bones <= 1) {
+ /* When only the active bone is selected, and it has a parent,
+ * align it to the parent, as that is the only possible outcome.
+ */
+ if (actbone->parent) {
+ bone_align_to_bone(arm->edbo, actbone, actbone->parent);
+
+ if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
+ bone_align_to_bone(arm->edbo, actmirb, actmirb->parent);
+
+ BKE_reportf(op->reports, RPT_INFO, "Aligned bone '%s' to parent", actbone->name);
+ }
+ }
+ else {
+ /* Align 'selected' bones to the active one
+ * - the context iterator contains both selected bones and their mirrored copies,
+ * so we assume that unselected bones are mirrored copies of some selected bone
+ * - since the active one (and/or its mirror) will also be selected, we also need
+ * to check that we are not trying to operate on them, since such an operation
+ * would cause errors
+ */
+
+ /* align selected bones to the active one */
+ CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones) {
+ if (ELEM(ebone, actbone, actmirb) == 0) {
+ if (ebone->flag & BONE_SELECTED)
+ bone_align_to_bone(arm->edbo, ebone, actbone);
+ else
+ bone_align_to_bone(arm->edbo, ebone, actmirb);
+ }
+ }
+ CTX_DATA_END;
+
+ BKE_reportf(
+ op->reports, RPT_INFO, "%d bones aligned to bone '%s'", num_selected_bones, actbone->name);
+ }
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_align(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Align Bones";
- ot->idname = "ARMATURE_OT_align";
- ot->description = "Align selected bones to the active bone (or to their parent)";
+ /* identifiers */
+ ot->name = "Align Bones";
+ ot->idname = "ARMATURE_OT_align";
+ ot->description = "Align selected bones to the active bone (or to their parent)";
- /* api callbacks */
- ot->exec = armature_align_bones_exec;
- ot->poll = ED_operator_editarmature;
+ /* api callbacks */
+ ot->exec = armature_align_bones_exec;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************************* Split ******************************* */
static int armature_split_exec(bContext *C, wmOperator *UNUSED(op))
{
- 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;
-
- for (EditBone *bone = arm->edbo->first; bone; bone = bone->next) {
- 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) {
- ED_armature_ebone_select_set(bone, (bone->flag & BONE_SELECTED) != 0);
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
-
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ 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;
+
+ for (EditBone *bone = arm->edbo->first; bone; bone = bone->next) {
+ 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) {
+ ED_armature_ebone_select_set(bone, (bone->flag & BONE_SELECTED) != 0);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_split(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Split";
- ot->idname = "ARMATURE_OT_split";
- ot->description = "Split off selected bones from connected unselected bones";
+ /* identifiers */
+ ot->name = "Split";
+ ot->idname = "ARMATURE_OT_split";
+ ot->description = "Split off selected bones from connected unselected bones";
- /* api callbacks */
- ot->exec = armature_split_exec;
- ot->poll = ED_operator_editarmature;
+ /* api callbacks */
+ ot->exec = armature_split_exec;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************************* Delete ******************************* */
static bool armature_delete_ebone_cb(const char *bone_name, void *arm_p)
{
- bArmature *arm = arm_p;
- EditBone *ebone;
+ bArmature *arm = arm_p;
+ EditBone *ebone;
- ebone = ED_armature_ebone_find_name(arm->edbo, bone_name);
- return (ebone && (ebone->flag & BONE_SELECTED) && (arm->layer & ebone->layer));
+ ebone = ED_armature_ebone_find_name(arm->edbo, bone_name);
+ return (ebone && (ebone->flag & BONE_SELECTED) && (arm->layer & ebone->layer));
}
/* previously delete_armature */
/* only editmode! */
static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
{
- EditBone *curBone, *ebone_next;
- bool changed_multi = false;
-
- /* cancel if nothing selected */
- if (CTX_DATA_COUNT(C, selected_bones) == 0)
- return OPERATOR_CANCELLED;
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- bArmature *arm = obedit->data;
- bool changed = false;
-
- armature_select_mirrored(arm);
-
- BKE_pose_channels_remove(obedit, armature_delete_ebone_cb, arm);
-
- for (curBone = arm->edbo->first; curBone; curBone = ebone_next) {
- ebone_next = curBone->next;
- if (arm->layer & curBone->layer) {
- if (curBone->flag & BONE_SELECTED) {
- if (curBone == arm->act_edbone) arm->act_edbone = NULL;
- ED_armature_ebone_remove(arm, curBone);
- changed = true;
- }
- }
- }
-
- if (changed) {
- changed_multi = true;
-
- ED_armature_edit_sync_selection(arm->edbo);
- BKE_pose_tag_recalc(CTX_data_main(C), obedit->pose);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
- }
- }
- MEM_freeN(objects);
-
- if (!changed_multi) {
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ EditBone *curBone, *ebone_next;
+ bool changed_multi = false;
+
+ /* cancel if nothing selected */
+ if (CTX_DATA_COUNT(C, selected_bones) == 0)
+ return OPERATOR_CANCELLED;
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ bArmature *arm = obedit->data;
+ bool changed = false;
+
+ armature_select_mirrored(arm);
+
+ BKE_pose_channels_remove(obedit, armature_delete_ebone_cb, arm);
+
+ for (curBone = arm->edbo->first; curBone; curBone = ebone_next) {
+ ebone_next = curBone->next;
+ if (arm->layer & curBone->layer) {
+ if (curBone->flag & BONE_SELECTED) {
+ if (curBone == arm->act_edbone)
+ arm->act_edbone = NULL;
+ ED_armature_ebone_remove(arm, curBone);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ changed_multi = true;
+
+ ED_armature_edit_sync_selection(arm->edbo);
+ BKE_pose_tag_recalc(CTX_data_main(C), obedit->pose);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+ }
+ }
+ MEM_freeN(objects);
+
+ if (!changed_multi) {
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Selected Bone(s)";
- ot->idname = "ARMATURE_OT_delete";
- ot->description = "Remove selected bones from the armature";
-
- /* api callbacks */
- ot->invoke = WM_operator_confirm;
- ot->exec = armature_delete_selected_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Delete Selected Bone(s)";
+ ot->idname = "ARMATURE_OT_delete";
+ ot->description = "Remove selected bones from the armature";
+
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = armature_delete_selected_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static bool armature_dissolve_ebone_cb(const char *bone_name, void *arm_p)
{
- bArmature *arm = arm_p;
- EditBone *ebone;
+ bArmature *arm = arm_p;
+ EditBone *ebone;
- ebone = ED_armature_ebone_find_name(arm->edbo, bone_name);
- return (ebone && (ebone->flag & BONE_DONE));
+ ebone = ED_armature_ebone_find_name(arm->edbo, bone_name);
+ return (ebone && (ebone->flag & BONE_DONE));
}
static int armature_dissolve_selected_exec(bContext *C, wmOperator *UNUSED(op))
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- EditBone *ebone, *ebone_next;
- bool changed_multi = false;
-
- 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;
- bool changed = false;
-
- /* store for mirror */
- GHash *ebone_flag_orig = NULL;
- int ebone_num = 0;
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- ebone->temp.p = NULL;
- ebone->flag &= ~BONE_DONE;
- ebone_num++;
- }
-
- if (arm->flag & ARM_MIRROR_EDIT) {
- GHashIterator gh_iter;
-
- ebone_flag_orig = BLI_ghash_ptr_new_ex(__func__, ebone_num);
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- union { int flag; void *p; } val = {0};
- val.flag = ebone->flag;
- BLI_ghash_insert(ebone_flag_orig, ebone, val.p);
- }
-
- armature_select_mirrored_ex(arm, BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
-
- GHASH_ITER (gh_iter, ebone_flag_orig) {
- union { int flag; void *p; } *val_p = (void *)BLI_ghashIterator_getValue_p(&gh_iter);
- ebone = BLI_ghashIterator_getKey(&gh_iter);
- val_p->flag = ebone->flag & ~val_p->flag;
- }
- }
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (ebone->parent && ebone->flag & BONE_CONNECTED) {
- if (ebone->parent->temp.ebone == ebone->parent) {
- /* ignore */
- }
- else if (ebone->parent->temp.ebone) {
- /* set ignored */
- ebone->parent->temp.ebone = ebone->parent;
- }
- else {
- /* set child */
- ebone->parent->temp.ebone = ebone;
- }
- }
- }
-
- /* cleanup multiple used bones */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (ebone->temp.ebone == ebone) {
- ebone->temp.ebone = NULL;
- }
- }
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- /* break connections for unseen bones */
- if (((arm->layer & ebone->layer) &&
- ((ED_armature_ebone_selectflag_get(ebone) & (BONE_TIPSEL | BONE_SELECTED)))) == 0)
- {
- ebone->temp.ebone = NULL;
- }
-
- if (((arm->layer & ebone->layer) &&
- ((ED_armature_ebone_selectflag_get(ebone) & (BONE_ROOTSEL | BONE_SELECTED)))) == 0)
- {
- if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
- ebone->parent->temp.ebone = NULL;
- }
-
- }
- }
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
-
- if (ebone->parent &&
- (ebone->parent->temp.ebone == ebone))
- {
- ebone->flag |= BONE_DONE;
- }
- }
-
- BKE_pose_channels_remove(obedit, armature_dissolve_ebone_cb, arm);
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone_next) {
- ebone_next = ebone->next;
-
- if (ebone->flag & BONE_DONE) {
- copy_v3_v3(ebone->parent->tail, ebone->tail);
- ebone->parent->rad_tail = ebone->rad_tail;
- SET_FLAG_FROM_TEST(ebone->parent->flag, ebone->flag & BONE_TIPSEL, BONE_TIPSEL);
-
- ED_armature_ebone_remove_ex(arm, ebone, false);
- changed = true;
- }
- }
-
- if (changed) {
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (ebone->parent &&
- ebone->parent->temp.ebone &&
- (ebone->flag & BONE_CONNECTED))
- {
- ebone->rad_head = ebone->parent->rad_tail;
- }
- }
-
- if (arm->flag & ARM_MIRROR_EDIT) {
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- union { int flag; void *p; } *val_p = (void *)BLI_ghash_lookup_p(ebone_flag_orig, ebone);
- if (val_p && val_p->flag) {
- ebone->flag &= ~val_p->flag;
- }
- }
- }
- }
-
- if (arm->flag & ARM_MIRROR_EDIT) {
- BLI_ghash_free(ebone_flag_orig, NULL, NULL);
- }
-
- if (changed) {
- changed_multi = true;
- ED_armature_edit_sync_selection(arm->edbo);
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
- }
- }
- MEM_freeN(objects);
-
- if (!changed_multi) {
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ EditBone *ebone, *ebone_next;
+ bool changed_multi = false;
+
+ 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;
+ bool changed = false;
+
+ /* store for mirror */
+ GHash *ebone_flag_orig = NULL;
+ int ebone_num = 0;
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ ebone->temp.p = NULL;
+ ebone->flag &= ~BONE_DONE;
+ ebone_num++;
+ }
+
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ GHashIterator gh_iter;
+
+ ebone_flag_orig = BLI_ghash_ptr_new_ex(__func__, ebone_num);
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ union {
+ int flag;
+ void *p;
+ } val = {0};
+ val.flag = ebone->flag;
+ BLI_ghash_insert(ebone_flag_orig, ebone, val.p);
+ }
+
+ armature_select_mirrored_ex(arm, BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
+
+ GHASH_ITER (gh_iter, ebone_flag_orig) {
+ union {
+ int flag;
+ void *p;
+ } *val_p = (void *)BLI_ghashIterator_getValue_p(&gh_iter);
+ ebone = BLI_ghashIterator_getKey(&gh_iter);
+ val_p->flag = ebone->flag & ~val_p->flag;
+ }
+ }
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ebone->parent && ebone->flag & BONE_CONNECTED) {
+ if (ebone->parent->temp.ebone == ebone->parent) {
+ /* ignore */
+ }
+ else if (ebone->parent->temp.ebone) {
+ /* set ignored */
+ ebone->parent->temp.ebone = ebone->parent;
+ }
+ else {
+ /* set child */
+ ebone->parent->temp.ebone = ebone;
+ }
+ }
+ }
+
+ /* cleanup multiple used bones */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ebone->temp.ebone == ebone) {
+ ebone->temp.ebone = NULL;
+ }
+ }
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ /* break connections for unseen bones */
+ if (((arm->layer & ebone->layer) &&
+ ((ED_armature_ebone_selectflag_get(ebone) & (BONE_TIPSEL | BONE_SELECTED)))) == 0) {
+ ebone->temp.ebone = NULL;
+ }
+
+ if (((arm->layer & ebone->layer) &&
+ ((ED_armature_ebone_selectflag_get(ebone) & (BONE_ROOTSEL | BONE_SELECTED)))) == 0) {
+ if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+ ebone->parent->temp.ebone = NULL;
+ }
+ }
+ }
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+
+ if (ebone->parent && (ebone->parent->temp.ebone == ebone)) {
+ ebone->flag |= BONE_DONE;
+ }
+ }
+
+ BKE_pose_channels_remove(obedit, armature_dissolve_ebone_cb, arm);
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone_next) {
+ ebone_next = ebone->next;
+
+ if (ebone->flag & BONE_DONE) {
+ copy_v3_v3(ebone->parent->tail, ebone->tail);
+ ebone->parent->rad_tail = ebone->rad_tail;
+ SET_FLAG_FROM_TEST(ebone->parent->flag, ebone->flag & BONE_TIPSEL, BONE_TIPSEL);
+
+ ED_armature_ebone_remove_ex(arm, ebone, false);
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ebone->parent && ebone->parent->temp.ebone && (ebone->flag & BONE_CONNECTED)) {
+ ebone->rad_head = ebone->parent->rad_tail;
+ }
+ }
+
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ union {
+ int flag;
+ void *p;
+ } *val_p = (void *)BLI_ghash_lookup_p(ebone_flag_orig, ebone);
+ if (val_p && val_p->flag) {
+ ebone->flag &= ~val_p->flag;
+ }
+ }
+ }
+ }
+
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ BLI_ghash_free(ebone_flag_orig, NULL, NULL);
+ }
+
+ if (changed) {
+ changed_multi = true;
+ ED_armature_edit_sync_selection(arm->edbo);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+ }
+ }
+ MEM_freeN(objects);
+
+ if (!changed_multi) {
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_dissolve(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Dissolve Selected Bone(s)";
- ot->idname = "ARMATURE_OT_dissolve";
- ot->description = "Dissolve selected bones from the armature";
+ /* identifiers */
+ ot->name = "Dissolve Selected Bone(s)";
+ ot->idname = "ARMATURE_OT_dissolve";
+ ot->description = "Dissolve selected bones from the armature";
- /* api callbacks */
- ot->exec = armature_dissolve_selected_exec;
- ot->poll = ED_operator_editarmature;
+ /* api callbacks */
+ ot->exec = armature_dissolve_selected_exec;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
-
/* ********************************* Show/Hide ******************************* */
static int armature_hide_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const int invert = RNA_boolean_get(op->ptr, "unselected") ? BONE_SELECTED : 0;
-
- /* cancel if nothing selected */
- if (CTX_DATA_COUNT(C, selected_bones) == 0)
- return OPERATOR_CANCELLED;
-
- 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;
- bool changed = false;
-
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone)) {
- if ((ebone->flag & BONE_SELECTED) != invert) {
- ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
- ebone->flag |= BONE_HIDDEN_A;
- changed = true;
- }
- }
- }
-
- if (!changed) {
- continue;
- }
- ED_armature_edit_validate_active(arm);
- ED_armature_edit_sync_selection(arm->edbo);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const int invert = RNA_boolean_get(op->ptr, "unselected") ? BONE_SELECTED : 0;
+
+ /* cancel if nothing selected */
+ if (CTX_DATA_COUNT(C, selected_bones) == 0)
+ return OPERATOR_CANCELLED;
+
+ 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;
+ bool changed = false;
+
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if ((ebone->flag & BONE_SELECTED) != invert) {
+ ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ ebone->flag |= BONE_HIDDEN_A;
+ changed = true;
+ }
+ }
+ }
+
+ if (!changed) {
+ continue;
+ }
+ ED_armature_edit_validate_active(arm);
+ ED_armature_edit_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_hide(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Selected";
- ot->idname = "ARMATURE_OT_hide";
- ot->description = "Tag selected bones to not be visible in Edit Mode";
+ /* identifiers */
+ ot->name = "Hide Selected";
+ ot->idname = "ARMATURE_OT_hide";
+ ot->description = "Tag selected bones to not be visible in Edit Mode";
- /* api callbacks */
- ot->exec = armature_hide_exec;
- ot->poll = ED_operator_editarmature;
+ /* api callbacks */
+ ot->exec = armature_hide_exec;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
}
static int armature_reveal_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const bool select = RNA_boolean_get(op->ptr, "select");
- 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;
- bool changed = false;
-
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (arm->layer & ebone->layer) {
- if (ebone->flag & BONE_HIDDEN_A) {
- if (!(ebone->flag & BONE_UNSELECTABLE)) {
- SET_FLAG_FROM_TEST(ebone->flag, select, (BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL));
- }
- ebone->flag &= ~BONE_HIDDEN_A;
- changed = true;
- }
- }
- }
-
- if (changed) {
- ED_armature_edit_validate_active(arm);
- ED_armature_edit_sync_selection(arm->edbo);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
- }
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool select = RNA_boolean_get(op->ptr, "select");
+ 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;
+ bool changed = false;
+
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (arm->layer & ebone->layer) {
+ if (ebone->flag & BONE_HIDDEN_A) {
+ if (!(ebone->flag & BONE_UNSELECTABLE)) {
+ SET_FLAG_FROM_TEST(ebone->flag, select, (BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL));
+ }
+ ebone->flag &= ~BONE_HIDDEN_A;
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ ED_armature_edit_validate_active(arm);
+ ED_armature_edit_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+ }
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_reveal(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reveal Hidden";
- ot->idname = "ARMATURE_OT_reveal";
- ot->description = "Reveal all bones hidden in Edit Mode";
+ /* identifiers */
+ ot->name = "Reveal Hidden";
+ ot->idname = "ARMATURE_OT_reveal";
+ ot->description = "Reveal all bones hidden in Edit Mode";
- /* api callbacks */
- ot->exec = armature_reveal_exec;
- ot->poll = ED_operator_editarmature;
+ /* api callbacks */
+ ot->exec = armature_reveal_exec;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "select", true, "Select", "");
+ 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 7fe4810762e..09e4c1acae7 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -138,37 +138,37 @@ void POSE_OT_bone_layers(struct wmOperatorType *ot);
/* Temporary data linking PoseChannels with the F-Curves they affect */
typedef struct tPChanFCurveLink {
- struct tPChanFCurveLink *next, *prev;
-
- /** Object this Pose Channel belongs to. */
- struct Object *ob;
-
- /** F-Curves for this PoseChannel (wrapped with LinkData) */
- ListBase fcurves;
- /** Pose Channel which data is attached to */
- struct bPoseChannel *pchan;
-
- /** RNA Path to this Pose Channel (needs to be freed when we're done) */
- char *pchan_path;
-
- /** transform values at start of operator (to be restored before each modal step) */
- float oldloc[3];
- float oldrot[3];
- float oldscale[3];
- float oldquat[4];
- float oldangle;
- float oldaxis[3];
-
- /** old bbone values (to be restored along with the transform properties) */
- float roll1, roll2;
- /** (NOTE: we haven't renamed these this time, as their names are already long enough) */
- float curveInX, curveInY;
- float curveOutX, curveOutY;
- float ease1, ease2;
- float scaleIn, scaleOut;
-
- /** copy of custom properties at start of operator (to be restored before each modal step) */
- struct IDProperty *oldprops;
+ struct tPChanFCurveLink *next, *prev;
+
+ /** Object this Pose Channel belongs to. */
+ struct Object *ob;
+
+ /** F-Curves for this PoseChannel (wrapped with LinkData) */
+ ListBase fcurves;
+ /** Pose Channel which data is attached to */
+ struct bPoseChannel *pchan;
+
+ /** RNA Path to this Pose Channel (needs to be freed when we're done) */
+ char *pchan_path;
+
+ /** transform values at start of operator (to be restored before each modal step) */
+ float oldloc[3];
+ float oldrot[3];
+ float oldscale[3];
+ float oldquat[4];
+ float oldangle;
+ float oldaxis[3];
+
+ /** old bbone values (to be restored along with the transform properties) */
+ float roll1, roll2;
+ /** (NOTE: we haven't renamed these this time, as their names are already long enough) */
+ float curveInX, curveInY;
+ float curveOutX, curveOutY;
+ float ease1, ease2;
+ float scaleIn, scaleOut;
+
+ /** copy of custom properties at start of operator (to be restored before each modal step) */
+ struct IDProperty *oldprops;
} tPChanFCurveLink;
/* ----------- */
@@ -179,7 +179,10 @@ void poseAnim_mapping_free(ListBase *pfLinks);
void poseAnim_mapping_refresh(struct bContext *C, struct Scene *scene, struct Object *ob);
void poseAnim_mapping_reset(ListBase *pfLinks);
-void poseAnim_mapping_autoKeyframe(struct bContext *C, struct Scene *scene, ListBase *pfLinks, float cframe);
+void poseAnim_mapping_autoKeyframe(struct bContext *C,
+ struct Scene *scene,
+ ListBase *pfLinks,
+ float cframe);
LinkData *poseAnim_mapping_getNextFCurve(ListBase *fcuLinks, LinkData *prev, const char *path);
@@ -222,15 +225,27 @@ EditBone *make_boneList(struct ListBase *edbo, struct ListBase *bones, struct Bo
/* duplicate method */
void preEditBoneDuplicate(struct ListBase *editbones);
void postEditBoneDuplicate(struct ListBase *editbones, struct Object *ob);
-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);
+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 */
-struct EditBone *duplicateEditBoneObjects(struct EditBone *curBone, const char *name, struct ListBase *editbones, struct Object *src_ob, struct Object *dst_ob);
+struct EditBone *duplicateEditBoneObjects(struct EditBone *curBone,
+ const char *name,
+ struct ListBase *editbones,
+ 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);
+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);
@@ -240,18 +255,20 @@ 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_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,
- bool findunsel, bool do_nearest,
- struct Base **r_base);
+void *get_bone_from_selectbuffer(struct Base **bases,
+ uint bases_len,
+ bool is_editmode,
+ const unsigned int *buffer,
+ short hits,
+ bool findunsel,
+ bool do_nearest,
+ struct Base **r_base);
-int bone_looper(struct Object *ob, struct Bone *bone, void *data,
+int bone_looper(struct Object *ob,
+ struct Bone *bone,
+ void *data,
int (*bone_func)(struct Object *, struct Bone *, void *));
-
#endif /* __ARMATURE_INTERN_H__ */
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index 6d4babe9674..b1f0297bb29 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -71,18 +71,24 @@
/* note: there's a unique_bone_name() too! */
static bool editbone_unique_check(void *arg, const char *name)
{
- struct {ListBase *lb; void *bone; } *data = arg;
- EditBone *dupli = ED_armature_ebone_find_name(data->lb, name);
- return dupli && dupli != data->bone;
+ struct {
+ ListBase *lb;
+ void *bone;
+ } *data = arg;
+ EditBone *dupli = ED_armature_ebone_find_name(data->lb, name);
+ return dupli && dupli != data->bone;
}
void ED_armature_ebone_unique_name(ListBase *edbo, char *name, EditBone *bone)
{
- struct {ListBase *lb; void *bone; } data;
- data.lb = edbo;
- data.bone = bone;
-
- BLI_uniquename_cb(editbone_unique_check, &data, DATA_("Bone"), '.', name, sizeof(bone->name));
+ struct {
+ ListBase *lb;
+ void *bone;
+ } data;
+ data.lb = edbo;
+ data.bone = bone;
+
+ BLI_uniquename_cb(editbone_unique_check, &data, DATA_("Bone"), '.', name, sizeof(bone->name));
}
/* ************************************************** */
@@ -90,261 +96,265 @@ void ED_armature_ebone_unique_name(ListBase *edbo, char *name, EditBone *bone)
static bool bone_unique_check(void *arg, const char *name)
{
- return BKE_armature_find_bone_name((bArmature *)arg, name) != NULL;
+ return BKE_armature_find_bone_name((bArmature *)arg, name) != NULL;
}
static void unique_bone_name(bArmature *arm, char *name)
{
- BLI_uniquename_cb(bone_unique_check, (void *)arm, DATA_("Bone"), '.', name, sizeof(((Bone *)NULL)->name));
+ BLI_uniquename_cb(
+ bone_unique_check, (void *)arm, DATA_("Bone"), '.', name, sizeof(((Bone *)NULL)->name));
}
/* helper call for armature_bone_rename */
-static void constraint_bone_name_fix(Object *ob, ListBase *conlist, const char *oldname, const char *newname)
+static void constraint_bone_name_fix(Object *ob,
+ ListBase *conlist,
+ const char *oldname,
+ const char *newname)
{
- bConstraint *curcon;
- bConstraintTarget *ct;
-
- for (curcon = conlist->first; curcon; curcon = curcon->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon);
- ListBase targets = {NULL, NULL};
-
- /* constraint targets */
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(curcon, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar == ob) {
- if (STREQ(ct->subtarget, oldname)) {
- BLI_strncpy(ct->subtarget, newname, MAXBONENAME);
- }
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(curcon, &targets, 0);
- }
-
- /* action constraints */
- if (curcon->type == CONSTRAINT_TYPE_ACTION) {
- bActionConstraint *actcon = (bActionConstraint *)curcon->data;
- BKE_action_fix_paths_rename(&ob->id, actcon->act, "pose.bones", oldname, newname, 0, 0, 1);
- }
- }
+ bConstraint *curcon;
+ bConstraintTarget *ct;
+
+ for (curcon = conlist->first; curcon; curcon = curcon->next) {
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon);
+ ListBase targets = {NULL, NULL};
+
+ /* constraint targets */
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(curcon, &targets);
+
+ for (ct = targets.first; ct; ct = ct->next) {
+ if (ct->tar == ob) {
+ if (STREQ(ct->subtarget, oldname)) {
+ BLI_strncpy(ct->subtarget, newname, MAXBONENAME);
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(curcon, &targets, 0);
+ }
+
+ /* action constraints */
+ if (curcon->type == CONSTRAINT_TYPE_ACTION) {
+ bActionConstraint *actcon = (bActionConstraint *)curcon->data;
+ BKE_action_fix_paths_rename(&ob->id, actcon->act, "pose.bones", oldname, newname, 0, 0, 1);
+ }
+ }
}
/* called by UI for renaming a bone */
/* warning: make sure the original bone was not renamed yet! */
/* seems messy, but that's what you get with not using pointers but channel names :) */
-void ED_armature_bone_rename(Main *bmain, bArmature *arm, const char *oldnamep, const char *newnamep)
+void ED_armature_bone_rename(Main *bmain,
+ bArmature *arm,
+ const char *oldnamep,
+ const char *newnamep)
{
- Object *ob;
- char newname[MAXBONENAME];
- char oldname[MAXBONENAME];
-
- /* names better differ! */
- if (!STREQLEN(oldnamep, newnamep, MAXBONENAME)) {
-
- /* we alter newname string... so make copy */
- BLI_strncpy(newname, newnamep, MAXBONENAME);
- /* we use oldname for search... so make copy */
- BLI_strncpy(oldname, oldnamep, MAXBONENAME);
-
- /* now check if we're in editmode, we need to find the unique name */
- if (arm->edbo) {
- EditBone *eBone = ED_armature_ebone_find_name(arm->edbo, oldname);
-
- if (eBone) {
- ED_armature_ebone_unique_name(arm->edbo, newname, NULL);
- BLI_strncpy(eBone->name, newname, MAXBONENAME);
- }
- else {
- return;
- }
- }
- else {
- Bone *bone = BKE_armature_find_bone_name(arm, oldname);
-
- if (bone) {
- unique_bone_name(arm, newname);
- BLI_strncpy(bone->name, newname, MAXBONENAME);
- }
- else {
- return;
- }
- }
-
- /* force copy on write to update database */
- DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
-
- /* do entire dbase - objects */
- for (ob = bmain->objects.first; ob; ob = ob->id.next) {
- ModifierData *md;
-
- /* we have the object using the armature */
- if (arm == ob->data) {
- Object *cob;
-
- /* Rename the pose channel, if it exists */
- if (ob->pose) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, oldname);
- if (pchan) {
- GHash *gh = ob->pose->chanhash;
-
- /* remove the old hash entry, and replace with the new name */
- if (gh) {
- BLI_assert(BLI_ghash_haskey(gh, pchan->name));
- BLI_ghash_remove(gh, pchan->name, NULL, NULL);
- }
-
- BLI_strncpy(pchan->name, newname, MAXBONENAME);
-
- if (gh) {
- BLI_ghash_insert(gh, pchan->name, pchan);
- }
- }
-
- BLI_assert(BKE_pose_channels_is_valid(ob->pose) == true);
- }
-
- /* Update any object constraints to use the new bone name */
- for (cob = bmain->objects.first; cob; cob = cob->id.next) {
- if (cob->constraints.first)
- constraint_bone_name_fix(ob, &cob->constraints, oldname, newname);
- if (cob->pose) {
- bPoseChannel *pchan;
- for (pchan = cob->pose->chanbase.first; pchan; pchan = pchan->next) {
- constraint_bone_name_fix(ob, &pchan->constraints, oldname, newname);
- }
- }
- }
- }
-
- /* See if an object is parented to this armature */
- if (ob->parent && (ob->parent->data == arm)) {
- if (ob->partype == PARBONE) {
- /* bone name in object */
- if (STREQ(ob->parsubstr, oldname))
- BLI_strncpy(ob->parsubstr, newname, MAXBONENAME);
- }
- }
-
- if (modifiers_usesArmature(ob, arm)) {
- bDeformGroup *dg = defgroup_find_name(ob, oldname);
- if (dg) {
- BLI_strncpy(dg->name, newname, MAXBONENAME);
- }
- }
-
- /* fix modifiers that might be using this name */
- for (md = ob->modifiers.first; md; md = md->next) {
- switch (md->type) {
- case eModifierType_Hook:
- {
- HookModifierData *hmd = (HookModifierData *)md;
-
- if (hmd->object && (hmd->object->data == arm)) {
- if (STREQ(hmd->subtarget, oldname))
- BLI_strncpy(hmd->subtarget, newname, MAXBONENAME);
- }
- break;
- }
- case eModifierType_UVWarp:
- {
- UVWarpModifierData *umd = (UVWarpModifierData *)md;
-
- if (umd->object_src && (umd->object_src->data == arm)) {
- if (STREQ(umd->bone_src, oldname))
- BLI_strncpy(umd->bone_src, newname, MAXBONENAME);
- }
- if (umd->object_dst && (umd->object_dst->data == arm)) {
- if (STREQ(umd->bone_dst, oldname))
- BLI_strncpy(umd->bone_dst, newname, MAXBONENAME);
- }
- break;
- }
- default:
- break;
- }
- }
-
- /* fix grease pencil modifiers and vertex groups */
- if (ob->type == OB_GPENCIL) {
-
- bGPdata *gpd = (bGPdata *)ob->data;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if ((gpl->parent != NULL) && (gpl->parent->data == arm)) {
- if (STREQ(gpl->parsubstr, oldname))
- BLI_strncpy(gpl->parsubstr, newname, MAXBONENAME);
- }
- }
-
- for (GpencilModifierData *gp_md = ob->greasepencil_modifiers.first; gp_md; gp_md = gp_md->next) {
- 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);
- if (dg) {
- BLI_strncpy(dg->name, newname, MAXBONENAME);
- }
- }
- break;
- }
- case eGpencilModifierType_Hook:
- {
- HookGpencilModifierData *hgp_md = (HookGpencilModifierData *)gp_md;
- if (hgp_md->object && (hgp_md->object->data == arm)) {
- if (STREQ(hgp_md->subtarget, oldname))
- BLI_strncpy(hgp_md->subtarget, newname, MAXBONENAME);
- }
- break;
- }
- default:
- break;
- }
- }
- }
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
- }
-
- /* Fix all animdata that may refer to this bone - we can't just do the ones attached to objects, since
- * other ID-blocks may have drivers referring to this bone [#29822]
- */
- // XXX: the ID here is for armatures, but most bone drivers are actually on the object instead...
- {
-
- BKE_animdata_fix_paths_rename_all(&arm->id, "pose.bones", oldname, newname);
- }
-
- /* correct view locking */
- {
- bScreen *screen;
- for (screen = bmain->screens.first; screen; screen = screen->id.next) {
- ScrArea *sa;
- /* add regions */
- for (sa = screen->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- for (sl = sa->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);
- }
- }
- }
- }
- }
- }
- }
- }
+ Object *ob;
+ char newname[MAXBONENAME];
+ char oldname[MAXBONENAME];
+
+ /* names better differ! */
+ if (!STREQLEN(oldnamep, newnamep, MAXBONENAME)) {
+
+ /* we alter newname string... so make copy */
+ BLI_strncpy(newname, newnamep, MAXBONENAME);
+ /* we use oldname for search... so make copy */
+ BLI_strncpy(oldname, oldnamep, MAXBONENAME);
+
+ /* now check if we're in editmode, we need to find the unique name */
+ if (arm->edbo) {
+ EditBone *eBone = ED_armature_ebone_find_name(arm->edbo, oldname);
+
+ if (eBone) {
+ ED_armature_ebone_unique_name(arm->edbo, newname, NULL);
+ BLI_strncpy(eBone->name, newname, MAXBONENAME);
+ }
+ else {
+ return;
+ }
+ }
+ else {
+ Bone *bone = BKE_armature_find_bone_name(arm, oldname);
+
+ if (bone) {
+ unique_bone_name(arm, newname);
+ BLI_strncpy(bone->name, newname, MAXBONENAME);
+ }
+ else {
+ return;
+ }
+ }
+
+ /* force copy on write to update database */
+ DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
+
+ /* do entire dbase - objects */
+ for (ob = bmain->objects.first; ob; ob = ob->id.next) {
+ ModifierData *md;
+
+ /* we have the object using the armature */
+ if (arm == ob->data) {
+ Object *cob;
+
+ /* Rename the pose channel, if it exists */
+ if (ob->pose) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, oldname);
+ if (pchan) {
+ GHash *gh = ob->pose->chanhash;
+
+ /* remove the old hash entry, and replace with the new name */
+ if (gh) {
+ BLI_assert(BLI_ghash_haskey(gh, pchan->name));
+ BLI_ghash_remove(gh, pchan->name, NULL, NULL);
+ }
+
+ BLI_strncpy(pchan->name, newname, MAXBONENAME);
+
+ if (gh) {
+ BLI_ghash_insert(gh, pchan->name, pchan);
+ }
+ }
+
+ BLI_assert(BKE_pose_channels_is_valid(ob->pose) == true);
+ }
+
+ /* Update any object constraints to use the new bone name */
+ for (cob = bmain->objects.first; cob; cob = cob->id.next) {
+ if (cob->constraints.first)
+ constraint_bone_name_fix(ob, &cob->constraints, oldname, newname);
+ if (cob->pose) {
+ bPoseChannel *pchan;
+ for (pchan = cob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ constraint_bone_name_fix(ob, &pchan->constraints, oldname, newname);
+ }
+ }
+ }
+ }
+
+ /* See if an object is parented to this armature */
+ if (ob->parent && (ob->parent->data == arm)) {
+ if (ob->partype == PARBONE) {
+ /* bone name in object */
+ if (STREQ(ob->parsubstr, oldname))
+ BLI_strncpy(ob->parsubstr, newname, MAXBONENAME);
+ }
+ }
+
+ if (modifiers_usesArmature(ob, arm)) {
+ bDeformGroup *dg = defgroup_find_name(ob, oldname);
+ if (dg) {
+ BLI_strncpy(dg->name, newname, MAXBONENAME);
+ }
+ }
+
+ /* fix modifiers that might be using this name */
+ for (md = ob->modifiers.first; md; md = md->next) {
+ switch (md->type) {
+ case eModifierType_Hook: {
+ HookModifierData *hmd = (HookModifierData *)md;
+
+ if (hmd->object && (hmd->object->data == arm)) {
+ if (STREQ(hmd->subtarget, oldname))
+ BLI_strncpy(hmd->subtarget, newname, MAXBONENAME);
+ }
+ break;
+ }
+ case eModifierType_UVWarp: {
+ UVWarpModifierData *umd = (UVWarpModifierData *)md;
+
+ if (umd->object_src && (umd->object_src->data == arm)) {
+ if (STREQ(umd->bone_src, oldname))
+ BLI_strncpy(umd->bone_src, newname, MAXBONENAME);
+ }
+ if (umd->object_dst && (umd->object_dst->data == arm)) {
+ if (STREQ(umd->bone_dst, oldname))
+ BLI_strncpy(umd->bone_dst, newname, MAXBONENAME);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ /* fix grease pencil modifiers and vertex groups */
+ if (ob->type == OB_GPENCIL) {
+
+ bGPdata *gpd = (bGPdata *)ob->data;
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if ((gpl->parent != NULL) && (gpl->parent->data == arm)) {
+ if (STREQ(gpl->parsubstr, oldname))
+ BLI_strncpy(gpl->parsubstr, newname, MAXBONENAME);
+ }
+ }
+
+ for (GpencilModifierData *gp_md = ob->greasepencil_modifiers.first; gp_md;
+ gp_md = gp_md->next) {
+ 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);
+ if (dg) {
+ BLI_strncpy(dg->name, newname, MAXBONENAME);
+ }
+ }
+ break;
+ }
+ case eGpencilModifierType_Hook: {
+ HookGpencilModifierData *hgp_md = (HookGpencilModifierData *)gp_md;
+ if (hgp_md->object && (hgp_md->object->data == arm)) {
+ if (STREQ(hgp_md->subtarget, oldname))
+ BLI_strncpy(hgp_md->subtarget, newname, MAXBONENAME);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ }
+
+ /* Fix all animdata that may refer to this bone - we can't just do the ones attached to objects, since
+ * other ID-blocks may have drivers referring to this bone [#29822]
+ */
+ // XXX: the ID here is for armatures, but most bone drivers are actually on the object instead...
+ {
+
+ BKE_animdata_fix_paths_rename_all(&arm->id, "pose.bones", oldname, newname);
+ }
+
+ /* correct view locking */
+ {
+ bScreen *screen;
+ for (screen = bmain->screens.first; screen; screen = screen->id.next) {
+ ScrArea *sa;
+ /* add regions */
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->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);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
typedef struct BoneFlipNameData {
- struct BoneFlipNameData *next, *prev;
- char *name;
- char name_flip[MAXBONENAME];
+ struct BoneFlipNameData *next, *prev;
+ char *name;
+ char name_flip[MAXBONENAME];
} BoneFlipNameData;
/**
@@ -357,38 +367,41 @@ typedef struct BoneFlipNameData {
* \param bones_names: List of BoneConflict elems.
* \param do_strip_numbers: if set, try to get rid of dot-numbers at end of bone names.
*/
-void ED_armature_bones_flip_names(Main *bmain, bArmature *arm, ListBase *bones_names, const bool do_strip_numbers)
+void ED_armature_bones_flip_names(Main *bmain,
+ bArmature *arm,
+ ListBase *bones_names,
+ const bool do_strip_numbers)
{
- ListBase bones_names_conflicts = {NULL};
- BoneFlipNameData *bfn;
-
- /* 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) {
- char name_flip[MAXBONENAME];
- char *name = link->data;
-
- /* WARNING: if do_strip_numbers is set, expect completely mismatched names in cases like
- * Bone.R, Bone.R.001, Bone.R.002, etc. */
- BLI_string_flip_side_name(name_flip, name, do_strip_numbers, sizeof(name_flip));
-
- ED_armature_bone_rename(bmain, arm, name, name_flip);
-
- if (!STREQ(name, name_flip)) {
- bfn = alloca(sizeof(BoneFlipNameData));
- bfn->name = name;
- BLI_strncpy(bfn->name_flip, name_flip, sizeof(bfn->name_flip));
- BLI_addtail(&bones_names_conflicts, bfn);
- }
- }
-
- /* Second pass to handle the bones that have naming conflicts with other bones.
- * Note that if the other bone was not selected, its name was not flipped, so conflict remains and that second
- * rename simply generates a new numbered alternative name. */
- for (bfn = bones_names_conflicts.first; bfn; bfn = bfn->next) {
- ED_armature_bone_rename(bmain, arm, bfn->name, bfn->name_flip);
- }
+ ListBase bones_names_conflicts = {NULL};
+ BoneFlipNameData *bfn;
+
+ /* 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) {
+ char name_flip[MAXBONENAME];
+ char *name = link->data;
+
+ /* WARNING: if do_strip_numbers is set, expect completely mismatched names in cases like
+ * Bone.R, Bone.R.001, Bone.R.002, etc. */
+ BLI_string_flip_side_name(name_flip, name, do_strip_numbers, sizeof(name_flip));
+
+ ED_armature_bone_rename(bmain, arm, name, name_flip);
+
+ if (!STREQ(name, name_flip)) {
+ bfn = alloca(sizeof(BoneFlipNameData));
+ bfn->name = name;
+ BLI_strncpy(bfn->name_flip, name_flip, sizeof(bfn->name_flip));
+ BLI_addtail(&bones_names_conflicts, bfn);
+ }
+ }
+
+ /* Second pass to handle the bones that have naming conflicts with other bones.
+ * Note that if the other bone was not selected, its name was not flipped, so conflict remains and that second
+ * rename simply generates a new numbered alternative name. */
+ for (bfn = bones_names_conflicts.first; bfn; bfn = bfn->next) {
+ ED_armature_bone_rename(bmain, arm, bfn->name, bfn->name_flip);
+ }
}
/* ************************************************** */
@@ -396,165 +409,171 @@ void ED_armature_bones_flip_names(Main *bmain, bArmature *arm, ListBase *bones_n
static int armature_flip_names_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob_active = CTX_data_edit_object(C);
-
- const bool do_strip_numbers = RNA_boolean_get(op->ptr, "do_strip_numbers");
-
- 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;
-
- /* Paranoia check. */
- if (ob_active->pose == NULL) {
- continue;
- }
-
- ListBase bones_names = {NULL};
-
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone)) {
- if (ebone->flag & BONE_SELECTED) {
- BLI_addtail(&bones_names, BLI_genericNodeN(ebone->name));
-
- if (arm->flag & ARM_MIRROR_EDIT) {
- EditBone *flipbone = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
- if ((flipbone) && !(flipbone->flag & BONE_SELECTED)) {
- BLI_addtail(&bones_names, BLI_genericNodeN(flipbone->name));
- }
- }
- }
- }
- }
-
- if (BLI_listbase_is_empty(&bones_names)) {
- continue;
- }
-
- ED_armature_bones_flip_names(bmain, arm, &bones_names, do_strip_numbers);
-
- BLI_freelistN(&bones_names);
-
- /* since we renamed stuff... */
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
-
- /* copied from #rna_Bone_update_renamed */
- /* redraw view */
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
-
- /* update animation channels */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, ob->data);
-
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob_active = CTX_data_edit_object(C);
+
+ const bool do_strip_numbers = RNA_boolean_get(op->ptr, "do_strip_numbers");
+
+ 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;
+
+ /* Paranoia check. */
+ if (ob_active->pose == NULL) {
+ continue;
+ }
+
+ ListBase bones_names = {NULL};
+
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (ebone->flag & BONE_SELECTED) {
+ BLI_addtail(&bones_names, BLI_genericNodeN(ebone->name));
+
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ EditBone *flipbone = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
+ if ((flipbone) && !(flipbone->flag & BONE_SELECTED)) {
+ BLI_addtail(&bones_names, BLI_genericNodeN(flipbone->name));
+ }
+ }
+ }
+ }
+ }
+
+ if (BLI_listbase_is_empty(&bones_names)) {
+ continue;
+ }
+
+ ED_armature_bones_flip_names(bmain, arm, &bones_names, do_strip_numbers);
+
+ BLI_freelistN(&bones_names);
+
+ /* since we renamed stuff... */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+
+ /* copied from #rna_Bone_update_renamed */
+ /* redraw view */
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+
+ /* update animation channels */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, ob->data);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_flip_names(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Flip Names";
- ot->idname = "ARMATURE_OT_flip_names";
- ot->description = "Flips (and corrects) the axis suffixes of the names of selected bones";
-
- /* api callbacks */
- ot->exec = armature_flip_names_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "do_strip_numbers", false, "Strip Numbers",
- "Try to remove right-most dot-number from flipped names "
- "(WARNING: may result in incoherent naming in some cases)");
+ /* identifiers */
+ ot->name = "Flip Names";
+ ot->idname = "ARMATURE_OT_flip_names";
+ ot->description = "Flips (and corrects) the axis suffixes of the names of selected bones";
+
+ /* api callbacks */
+ ot->exec = armature_flip_names_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna,
+ "do_strip_numbers",
+ false,
+ "Strip Numbers",
+ "Try to remove right-most dot-number from flipped names "
+ "(WARNING: may result in incoherent naming in some cases)");
}
static int armature_autoside_names_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Main *bmain = CTX_data_main(C);
- char newname[MAXBONENAME];
- const short axis = RNA_enum_get(op->ptr, "type");
- bool changed_multi = false;
-
- 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 changed = false;
-
- /* Paranoia checks. */
- if (ELEM(NULL, ob, ob->pose)) {
- continue;
- }
-
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_EDITABLE(ebone)) {
-
- /* We first need to do the flipped bone, then the original one.
- * Otherwise we can't find the flipped one because of the bone name change. */
- if (arm->flag & ARM_MIRROR_EDIT) {
- EditBone *flipbone = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
- if ((flipbone) && !(flipbone->flag & BONE_SELECTED)) {
- BLI_strncpy(newname, flipbone->name, sizeof(newname));
- if (bone_autoside_name(newname, 1, axis, flipbone->head[axis], flipbone->tail[axis])) {
- ED_armature_bone_rename(bmain, arm, flipbone->name, newname);
- changed = true;
- }
- }
- }
-
- BLI_strncpy(newname, ebone->name, sizeof(newname));
- if (bone_autoside_name(newname, 1, axis, ebone->head[axis], ebone->tail[axis])) {
- ED_armature_bone_rename(bmain, arm, ebone->name, newname);
- changed = true;
- }
- }
- }
-
- if (!changed) {
- continue;
- }
-
- changed_multi = true;
-
- /* Since we renamed stuff... */
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
-
- /* Note, notifier might evolve. */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- }
- MEM_freeN(objects);
- return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Main *bmain = CTX_data_main(C);
+ char newname[MAXBONENAME];
+ const short axis = RNA_enum_get(op->ptr, "type");
+ bool changed_multi = false;
+
+ 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 changed = false;
+
+ /* Paranoia checks. */
+ if (ELEM(NULL, ob, ob->pose)) {
+ continue;
+ }
+
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_EDITABLE(ebone)) {
+
+ /* We first need to do the flipped bone, then the original one.
+ * Otherwise we can't find the flipped one because of the bone name change. */
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ EditBone *flipbone = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
+ if ((flipbone) && !(flipbone->flag & BONE_SELECTED)) {
+ BLI_strncpy(newname, flipbone->name, sizeof(newname));
+ if (bone_autoside_name(newname, 1, axis, flipbone->head[axis], flipbone->tail[axis])) {
+ ED_armature_bone_rename(bmain, arm, flipbone->name, newname);
+ changed = true;
+ }
+ }
+ }
+
+ BLI_strncpy(newname, ebone->name, sizeof(newname));
+ if (bone_autoside_name(newname, 1, axis, ebone->head[axis], ebone->tail[axis])) {
+ ED_armature_bone_rename(bmain, arm, ebone->name, newname);
+ changed = true;
+ }
+ }
+ }
+
+ if (!changed) {
+ continue;
+ }
+
+ changed_multi = true;
+
+ /* Since we renamed stuff... */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+
+ /* Note, notifier might evolve. */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ }
+ MEM_freeN(objects);
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void ARMATURE_OT_autoside_names(wmOperatorType *ot)
{
- static const EnumPropertyItem axis_items[] = {
- {0, "XAXIS", 0, "X-Axis", "Left/Right"},
- {1, "YAXIS", 0, "Y-Axis", "Front/Back"},
- {2, "ZAXIS", 0, "Z-Axis", "Top/Bottom"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "AutoName by Axis";
- ot->idname = "ARMATURE_OT_autoside_names";
- ot->description = "Automatically renames the selected bones according to which side of the target axis they fall on";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = armature_autoside_names_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* settings */
- ot->prop = RNA_def_enum(ot->srna, "type", axis_items, 0, "Axis", "Axis tag names with");
+ static const EnumPropertyItem axis_items[] = {
+ {0, "XAXIS", 0, "X-Axis", "Left/Right"},
+ {1, "YAXIS", 0, "Y-Axis", "Front/Back"},
+ {2, "ZAXIS", 0, "Z-Axis", "Top/Bottom"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "AutoName by Axis";
+ ot->idname = "ARMATURE_OT_autoside_names";
+ ot->description =
+ "Automatically renames the selected bones according to which side of the target axis they "
+ "fall on";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = armature_autoside_names_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* 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 36ca3dd486d..c820077fbf9 100644
--- a/source/blender/editors/armature/armature_ops.c
+++ b/source/blender/editors/armature/armature_ops.c
@@ -38,160 +38,163 @@
/* Both operators ARMATURE_OT_xxx and POSE_OT_xxx here */
void ED_operatortypes_armature(void)
{
- /* EDIT ARMATURE */
- WM_operatortype_append(ARMATURE_OT_bone_primitive_add);
-
- WM_operatortype_append(ARMATURE_OT_align);
- WM_operatortype_append(ARMATURE_OT_calculate_roll);
- WM_operatortype_append(ARMATURE_OT_roll_clear);
- WM_operatortype_append(ARMATURE_OT_switch_direction);
- WM_operatortype_append(ARMATURE_OT_subdivide);
-
- WM_operatortype_append(ARMATURE_OT_parent_set);
- WM_operatortype_append(ARMATURE_OT_parent_clear);
-
- WM_operatortype_append(ARMATURE_OT_select_all);
- WM_operatortype_append(ARMATURE_OT_select_mirror);
- WM_operatortype_append(ARMATURE_OT_select_more);
- 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_similar);
- WM_operatortype_append(ARMATURE_OT_shortest_path_pick);
-
- WM_operatortype_append(ARMATURE_OT_delete);
- WM_operatortype_append(ARMATURE_OT_dissolve);
- WM_operatortype_append(ARMATURE_OT_duplicate);
- WM_operatortype_append(ARMATURE_OT_symmetrize);
- WM_operatortype_append(ARMATURE_OT_extrude);
- WM_operatortype_append(ARMATURE_OT_hide);
- 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);
-
- WM_operatortype_append(ARMATURE_OT_autoside_names);
- WM_operatortype_append(ARMATURE_OT_flip_names);
-
- WM_operatortype_append(ARMATURE_OT_layers_show_all);
- WM_operatortype_append(ARMATURE_OT_armature_layers);
- WM_operatortype_append(ARMATURE_OT_bone_layers);
-
- /* POSE */
- WM_operatortype_append(POSE_OT_hide);
- WM_operatortype_append(POSE_OT_reveal);
-
- WM_operatortype_append(POSE_OT_armature_apply);
- WM_operatortype_append(POSE_OT_visual_transform_apply);
-
- WM_operatortype_append(POSE_OT_rot_clear);
- WM_operatortype_append(POSE_OT_loc_clear);
- WM_operatortype_append(POSE_OT_scale_clear);
- WM_operatortype_append(POSE_OT_transforms_clear);
- WM_operatortype_append(POSE_OT_user_transforms_clear);
-
- WM_operatortype_append(POSE_OT_copy);
- WM_operatortype_append(POSE_OT_paste);
-
- WM_operatortype_append(POSE_OT_select_all);
-
- 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_constraint_target);
- WM_operatortype_append(POSE_OT_select_grouped);
- WM_operatortype_append(POSE_OT_select_mirror);
-
- WM_operatortype_append(POSE_OT_group_add);
- WM_operatortype_append(POSE_OT_group_remove);
- WM_operatortype_append(POSE_OT_group_move);
- WM_operatortype_append(POSE_OT_group_sort);
- WM_operatortype_append(POSE_OT_group_assign);
- WM_operatortype_append(POSE_OT_group_unassign);
- WM_operatortype_append(POSE_OT_group_select);
- WM_operatortype_append(POSE_OT_group_deselect);
-
- WM_operatortype_append(POSE_OT_paths_calculate);
- WM_operatortype_append(POSE_OT_paths_update);
- WM_operatortype_append(POSE_OT_paths_clear);
- WM_operatortype_append(POSE_OT_paths_range_update);
-
- WM_operatortype_append(POSE_OT_autoside_names);
- WM_operatortype_append(POSE_OT_flip_names);
-
- WM_operatortype_append(POSE_OT_rotation_mode_set);
-
- WM_operatortype_append(POSE_OT_quaternions_flip);
-
- WM_operatortype_append(POSE_OT_bone_layers);
-
- WM_operatortype_append(POSE_OT_propagate);
-
- /* POSELIB */
- WM_operatortype_append(POSELIB_OT_browse_interactive);
- WM_operatortype_append(POSELIB_OT_apply_pose);
-
- WM_operatortype_append(POSELIB_OT_pose_add);
- WM_operatortype_append(POSELIB_OT_pose_remove);
- WM_operatortype_append(POSELIB_OT_pose_rename);
- WM_operatortype_append(POSELIB_OT_pose_move);
-
- WM_operatortype_append(POSELIB_OT_new);
- WM_operatortype_append(POSELIB_OT_unlink);
-
- WM_operatortype_append(POSELIB_OT_action_sanitize);
-
- /* POSE SLIDING */
- WM_operatortype_append(POSE_OT_push);
- WM_operatortype_append(POSE_OT_relax);
- WM_operatortype_append(POSE_OT_breakdown);
+ /* EDIT ARMATURE */
+ WM_operatortype_append(ARMATURE_OT_bone_primitive_add);
+
+ WM_operatortype_append(ARMATURE_OT_align);
+ WM_operatortype_append(ARMATURE_OT_calculate_roll);
+ WM_operatortype_append(ARMATURE_OT_roll_clear);
+ WM_operatortype_append(ARMATURE_OT_switch_direction);
+ WM_operatortype_append(ARMATURE_OT_subdivide);
+
+ WM_operatortype_append(ARMATURE_OT_parent_set);
+ WM_operatortype_append(ARMATURE_OT_parent_clear);
+
+ WM_operatortype_append(ARMATURE_OT_select_all);
+ WM_operatortype_append(ARMATURE_OT_select_mirror);
+ WM_operatortype_append(ARMATURE_OT_select_more);
+ 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_similar);
+ WM_operatortype_append(ARMATURE_OT_shortest_path_pick);
+
+ WM_operatortype_append(ARMATURE_OT_delete);
+ WM_operatortype_append(ARMATURE_OT_dissolve);
+ WM_operatortype_append(ARMATURE_OT_duplicate);
+ WM_operatortype_append(ARMATURE_OT_symmetrize);
+ WM_operatortype_append(ARMATURE_OT_extrude);
+ WM_operatortype_append(ARMATURE_OT_hide);
+ 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);
+
+ WM_operatortype_append(ARMATURE_OT_autoside_names);
+ WM_operatortype_append(ARMATURE_OT_flip_names);
+
+ WM_operatortype_append(ARMATURE_OT_layers_show_all);
+ WM_operatortype_append(ARMATURE_OT_armature_layers);
+ WM_operatortype_append(ARMATURE_OT_bone_layers);
+
+ /* POSE */
+ WM_operatortype_append(POSE_OT_hide);
+ WM_operatortype_append(POSE_OT_reveal);
+
+ WM_operatortype_append(POSE_OT_armature_apply);
+ WM_operatortype_append(POSE_OT_visual_transform_apply);
+
+ WM_operatortype_append(POSE_OT_rot_clear);
+ WM_operatortype_append(POSE_OT_loc_clear);
+ WM_operatortype_append(POSE_OT_scale_clear);
+ WM_operatortype_append(POSE_OT_transforms_clear);
+ WM_operatortype_append(POSE_OT_user_transforms_clear);
+
+ WM_operatortype_append(POSE_OT_copy);
+ WM_operatortype_append(POSE_OT_paste);
+
+ WM_operatortype_append(POSE_OT_select_all);
+
+ 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_constraint_target);
+ WM_operatortype_append(POSE_OT_select_grouped);
+ WM_operatortype_append(POSE_OT_select_mirror);
+
+ WM_operatortype_append(POSE_OT_group_add);
+ WM_operatortype_append(POSE_OT_group_remove);
+ WM_operatortype_append(POSE_OT_group_move);
+ WM_operatortype_append(POSE_OT_group_sort);
+ WM_operatortype_append(POSE_OT_group_assign);
+ WM_operatortype_append(POSE_OT_group_unassign);
+ WM_operatortype_append(POSE_OT_group_select);
+ WM_operatortype_append(POSE_OT_group_deselect);
+
+ WM_operatortype_append(POSE_OT_paths_calculate);
+ WM_operatortype_append(POSE_OT_paths_update);
+ WM_operatortype_append(POSE_OT_paths_clear);
+ WM_operatortype_append(POSE_OT_paths_range_update);
+
+ WM_operatortype_append(POSE_OT_autoside_names);
+ WM_operatortype_append(POSE_OT_flip_names);
+
+ WM_operatortype_append(POSE_OT_rotation_mode_set);
+
+ WM_operatortype_append(POSE_OT_quaternions_flip);
+
+ WM_operatortype_append(POSE_OT_bone_layers);
+
+ WM_operatortype_append(POSE_OT_propagate);
+
+ /* POSELIB */
+ WM_operatortype_append(POSELIB_OT_browse_interactive);
+ WM_operatortype_append(POSELIB_OT_apply_pose);
+
+ WM_operatortype_append(POSELIB_OT_pose_add);
+ WM_operatortype_append(POSELIB_OT_pose_remove);
+ WM_operatortype_append(POSELIB_OT_pose_rename);
+ WM_operatortype_append(POSELIB_OT_pose_move);
+
+ WM_operatortype_append(POSELIB_OT_new);
+ WM_operatortype_append(POSELIB_OT_unlink);
+
+ WM_operatortype_append(POSELIB_OT_action_sanitize);
+
+ /* POSE SLIDING */
+ WM_operatortype_append(POSE_OT_push);
+ WM_operatortype_append(POSE_OT_relax);
+ WM_operatortype_append(POSE_OT_breakdown);
}
void ED_operatormacros_armature(void)
{
- wmOperatorType *ot;
- wmOperatorTypeMacro *otmacro;
-
- ot = WM_operatortype_append_macro("ARMATURE_OT_duplicate_move", "Duplicate",
- "Make copies of the selected bones within the same armature and move them",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "ARMATURE_OT_duplicate");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", 0);
-
- ot = WM_operatortype_append_macro("ARMATURE_OT_extrude_move", "Extrude",
- "Create new bones from the selected joints and move them",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- otmacro = WM_operatortype_macro_define(ot, "ARMATURE_OT_extrude");
- RNA_boolean_set(otmacro->ptr, "forked", false);
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", 0);
-
- /* XXX would it be nicer to just be able to have standard extrude_move, but set the forked property separate?
- * that would require fixing a properties bug 19733 */
- ot = WM_operatortype_append_macro("ARMATURE_OT_extrude_forked", "Extrude Forked",
- "Create new bones from the selected joints and move them",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- otmacro = WM_operatortype_macro_define(ot, "ARMATURE_OT_extrude");
- RNA_boolean_set(otmacro->ptr, "forked", true);
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", 0);
+ wmOperatorType *ot;
+ wmOperatorTypeMacro *otmacro;
+
+ ot = WM_operatortype_append_macro(
+ "ARMATURE_OT_duplicate_move",
+ "Duplicate",
+ "Make copies of the selected bones within the same armature and move them",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "ARMATURE_OT_duplicate");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+
+ ot = WM_operatortype_append_macro("ARMATURE_OT_extrude_move",
+ "Extrude",
+ "Create new bones from the selected joints and move them",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ otmacro = WM_operatortype_macro_define(ot, "ARMATURE_OT_extrude");
+ RNA_boolean_set(otmacro->ptr, "forked", false);
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+
+ /* XXX would it be nicer to just be able to have standard extrude_move, but set the forked property separate?
+ * that would require fixing a properties bug 19733 */
+ ot = WM_operatortype_append_macro("ARMATURE_OT_extrude_forked",
+ "Extrude Forked",
+ "Create new bones from the selected joints and move them",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ otmacro = WM_operatortype_macro_define(ot, "ARMATURE_OT_extrude");
+ RNA_boolean_set(otmacro->ptr, "forked", true);
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
}
void ED_keymap_armature(wmKeyConfig *keyconf)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- /* Armature ------------------------ */
- /* only set in editmode armature, by space_view3d listener */
- keymap = WM_keymap_ensure(keyconf, "Armature", 0, 0);
- keymap->poll = ED_operator_editarmature;
-
- /* Pose ------------------------ */
- /* only set in posemode, by space_view3d listener */
- keymap = WM_keymap_ensure(keyconf, "Pose", 0, 0);
- keymap->poll = ED_operator_posemode;
+ /* Armature ------------------------ */
+ /* only set in editmode armature, by space_view3d listener */
+ keymap = WM_keymap_ensure(keyconf, "Armature", 0, 0);
+ keymap->poll = ED_operator_editarmature;
+ /* Pose ------------------------ */
+ /* only set in posemode, by space_view3d listener */
+ keymap = WM_keymap_ensure(keyconf, "Pose", 0, 0);
+ keymap->poll = ED_operator_posemode;
}
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index 5928e1cd12c..6226059e794 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -67,55 +67,53 @@
/* NOTE: no operator define here as this is exported to the Object-level operator */
static void joined_armature_fix_links_constraints(
- Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone,
- ListBase *lb)
+ Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone, ListBase *lb)
{
- bConstraint *con;
-
- for (con = lb->first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- /* constraint targets */
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar == srcArm) {
- if (ct->subtarget[0] == '\0') {
- ct->tar = tarArm;
- }
- else if (STREQ(ct->subtarget, pchan->name)) {
- ct->tar = tarArm;
- BLI_strncpy(ct->subtarget, curbone->name, sizeof(ct->subtarget));
- }
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 0);
- }
-
- /* action constraint? (pose constraints only) */
- if (con->type == CONSTRAINT_TYPE_ACTION) {
- bActionConstraint *data = con->data;
-
- if (data->act) {
- BKE_action_fix_paths_rename(&tarArm->id, data->act, "pose.bones[",
- pchan->name, curbone->name, 0, 0, false);
- }
- }
-
- }
+ bConstraint *con;
+
+ for (con = lb->first; con; con = con->next) {
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ /* constraint targets */
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct = targets.first; ct; ct = ct->next) {
+ if (ct->tar == srcArm) {
+ if (ct->subtarget[0] == '\0') {
+ ct->tar = tarArm;
+ }
+ else if (STREQ(ct->subtarget, pchan->name)) {
+ ct->tar = tarArm;
+ BLI_strncpy(ct->subtarget, curbone->name, sizeof(ct->subtarget));
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+
+ /* action constraint? (pose constraints only) */
+ if (con->type == CONSTRAINT_TYPE_ACTION) {
+ bActionConstraint *data = con->data;
+
+ if (data->act) {
+ BKE_action_fix_paths_rename(
+ &tarArm->id, data->act, "pose.bones[", pchan->name, curbone->name, 0, 0, false);
+ }
+ }
+ }
}
/* userdata for joined_armature_fix_animdata_cb() */
typedef struct tJoinArmature_AdtFixData {
- Object *srcArm;
- Object *tarArm;
+ Object *srcArm;
+ Object *tarArm;
- GHash *names_map;
+ GHash *names_map;
} tJoinArmature_AdtFixData;
/* Callback to pass to BKE_animdata_main_cb() for fixing driver ID's to point to the new ID */
@@ -124,282 +122,281 @@ typedef struct tJoinArmature_AdtFixData {
*/
static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data)
{
- tJoinArmature_AdtFixData *afd = (tJoinArmature_AdtFixData *)user_data;
- ID *src_id = &afd->srcArm->id;
- ID *dst_id = &afd->tarArm->id;
-
- GHashIterator gh_iter;
-
- /* Fix paths - If this is the target object, it will have some "dirty" paths */
- if ((id == src_id) && strstr(fcu->rna_path, "pose.bones[")) {
- GHASH_ITER(gh_iter, afd->names_map) {
- const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
- const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
-
- /* only remap if changed; this still means there will be some
- * waste if there aren't many drivers/keys */
- if (!STREQ(old_name, new_name) && strstr(fcu->rna_path, old_name)) {
- fcu->rna_path = BKE_animsys_fix_rna_path_rename(id, fcu->rna_path, "pose.bones",
- old_name, new_name, 0, 0, false);
-
- /* we don't want to apply a second remapping on this driver now,
- * so stop trying names, but keep fixing drivers
- */
- break;
- }
- }
- }
-
-
- /* Driver targets */
- if (fcu->driver) {
- ChannelDriver *driver = fcu->driver;
- DriverVar *dvar;
-
- /* Fix driver references to invalid ID's */
- for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
- /* only change the used targets, since the others will need fixing manually anyway */
- DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar)
- {
- /* change the ID's used... */
- if (dtar->id == src_id) {
- dtar->id = dst_id;
-
- /* also check on the subtarget...
- * XXX: We duplicate the logic from drivers_path_rename_fix() here, with our own
- * little twists so that we know that it isn't going to clobber the wrong data
- */
- if ((dtar->rna_path && strstr(dtar->rna_path, "pose.bones[")) || (dtar->pchan_name[0])) {
- GHASH_ITER(gh_iter, afd->names_map) {
- const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
- const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
-
- /* only remap if changed */
- if (!STREQ(old_name, new_name)) {
- if ((dtar->rna_path) && strstr(dtar->rna_path, old_name)) {
- /* Fix up path */
- dtar->rna_path = BKE_animsys_fix_rna_path_rename(id, dtar->rna_path, "pose.bones",
- old_name, new_name, 0, 0, false);
- break; /* no need to try any more names for bone path */
- }
- else if (STREQ(dtar->pchan_name, old_name)) {
- /* Change target bone name */
- BLI_strncpy(dtar->pchan_name, new_name, sizeof(dtar->pchan_name));
- break; /* no need to try any more names for bone subtarget */
- }
- }
- }
- }
- }
- }
- DRIVER_TARGETS_LOOPER_END;
- }
- }
+ tJoinArmature_AdtFixData *afd = (tJoinArmature_AdtFixData *)user_data;
+ ID *src_id = &afd->srcArm->id;
+ ID *dst_id = &afd->tarArm->id;
+
+ GHashIterator gh_iter;
+
+ /* Fix paths - If this is the target object, it will have some "dirty" paths */
+ if ((id == src_id) && strstr(fcu->rna_path, "pose.bones[")) {
+ GHASH_ITER (gh_iter, afd->names_map) {
+ const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
+ const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
+
+ /* only remap if changed; this still means there will be some
+ * waste if there aren't many drivers/keys */
+ if (!STREQ(old_name, new_name) && strstr(fcu->rna_path, old_name)) {
+ fcu->rna_path = BKE_animsys_fix_rna_path_rename(
+ id, fcu->rna_path, "pose.bones", old_name, new_name, 0, 0, false);
+
+ /* we don't want to apply a second remapping on this driver now,
+ * so stop trying names, but keep fixing drivers
+ */
+ break;
+ }
+ }
+ }
+
+ /* Driver targets */
+ if (fcu->driver) {
+ ChannelDriver *driver = fcu->driver;
+ DriverVar *dvar;
+
+ /* Fix driver references to invalid ID's */
+ for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
+ /* only change the used targets, since the others will need fixing manually anyway */
+ DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
+ /* change the ID's used... */
+ if (dtar->id == src_id) {
+ dtar->id = dst_id;
+
+ /* also check on the subtarget...
+ * XXX: We duplicate the logic from drivers_path_rename_fix() here, with our own
+ * little twists so that we know that it isn't going to clobber the wrong data
+ */
+ if ((dtar->rna_path && strstr(dtar->rna_path, "pose.bones[")) || (dtar->pchan_name[0])) {
+ GHASH_ITER (gh_iter, afd->names_map) {
+ const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
+ const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
+
+ /* only remap if changed */
+ if (!STREQ(old_name, new_name)) {
+ if ((dtar->rna_path) && strstr(dtar->rna_path, old_name)) {
+ /* Fix up path */
+ dtar->rna_path = BKE_animsys_fix_rna_path_rename(
+ id, dtar->rna_path, "pose.bones", old_name, new_name, 0, 0, false);
+ break; /* no need to try any more names for bone path */
+ }
+ else if (STREQ(dtar->pchan_name, old_name)) {
+ /* Change target bone name */
+ BLI_strncpy(dtar->pchan_name, new_name, sizeof(dtar->pchan_name));
+ break; /* no need to try any more names for bone subtarget */
+ }
+ }
+ }
+ }
+ }
+ }
+ DRIVER_TARGETS_LOOPER_END;
+ }
+ }
}
/* Helper function for armature joining - link fixing */
-static void joined_armature_fix_links(Main *bmain, Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone)
+static void joined_armature_fix_links(
+ Main *bmain, Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone)
{
- Object *ob;
- bPose *pose;
- bPoseChannel *pchant;
-
- /* let's go through all objects in database */
- for (ob = bmain->objects.first; ob; ob = ob->id.next) {
- /* do some object-type specific things */
- if (ob->type == OB_ARMATURE) {
- pose = ob->pose;
- for (pchant = pose->chanbase.first; pchant; pchant = pchant->next) {
- joined_armature_fix_links_constraints(tarArm, srcArm, pchan, curbone, &pchant->constraints);
- }
- }
-
- /* fix object-level constraints */
- if (ob != srcArm) {
- joined_armature_fix_links_constraints(tarArm, srcArm, pchan, curbone, &ob->constraints);
- }
-
- /* See if an object is parented to this armature */
- if (ob->parent && (ob->parent == srcArm)) {
- /* Is object parented to a bone of this src armature? */
- if (ob->partype == PARBONE) {
- /* bone name in object */
- if (STREQ(ob->parsubstr, pchan->name)) {
- BLI_strncpy(ob->parsubstr, curbone->name, sizeof(ob->parsubstr));
- }
- }
-
- /* make tar armature be new parent */
- ob->parent = tarArm;
- }
- }
+ Object *ob;
+ bPose *pose;
+ bPoseChannel *pchant;
+
+ /* let's go through all objects in database */
+ for (ob = bmain->objects.first; ob; ob = ob->id.next) {
+ /* do some object-type specific things */
+ if (ob->type == OB_ARMATURE) {
+ pose = ob->pose;
+ for (pchant = pose->chanbase.first; pchant; pchant = pchant->next) {
+ joined_armature_fix_links_constraints(
+ tarArm, srcArm, pchan, curbone, &pchant->constraints);
+ }
+ }
+
+ /* fix object-level constraints */
+ if (ob != srcArm) {
+ joined_armature_fix_links_constraints(tarArm, srcArm, pchan, curbone, &ob->constraints);
+ }
+
+ /* See if an object is parented to this armature */
+ if (ob->parent && (ob->parent == srcArm)) {
+ /* Is object parented to a bone of this src armature? */
+ if (ob->partype == PARBONE) {
+ /* bone name in object */
+ if (STREQ(ob->parsubstr, pchan->name)) {
+ BLI_strncpy(ob->parsubstr, curbone->name, sizeof(ob->parsubstr));
+ }
+ }
+
+ /* make tar armature be new parent */
+ ob->parent = tarArm;
+ }
+ }
}
/* join armature exec is exported for use in object->join objects operator... */
int join_armature_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob_active = CTX_data_active_object(C);
- bArmature *arm = (ob_active) ? ob_active->data : NULL;
- bPose *pose, *opose;
- bPoseChannel *pchan, *pchann;
- EditBone *curbone;
- float mat[4][4], oimat[4][4];
- bool ok = false;
-
- /* Ensure we're not in editmode and that the active object is an armature*/
- if (!ob_active || ob_active->type != OB_ARMATURE)
- return OPERATOR_CANCELLED;
- if (!arm || arm->edbo)
- return OPERATOR_CANCELLED;
-
- CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
- {
- if (ob_iter == ob_active) {
- ok = true;
- break;
- }
- }
- CTX_DATA_END;
-
- /* that way the active object is always selected */
- if (ok == false) {
- BKE_report(op->reports, RPT_WARNING, "Active object is not a selected armature");
- return OPERATOR_CANCELLED;
- }
-
- /* Get editbones of active armature to add editbones to */
- ED_armature_to_edit(arm);
-
- /* get pose of active object and move it out of posemode */
- pose = ob_active->pose;
- ob_active->mode &= ~OB_MODE_POSE;
-
- CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
- {
- if ((ob_iter->type == OB_ARMATURE) && (ob_iter != ob_active)) {
- tJoinArmature_AdtFixData afd = {NULL};
- bArmature *curarm = ob_iter->data;
-
- /* we assume that each armature datablock is only used in a single place */
- BLI_assert(ob_active->data != ob_iter->data);
-
- /* init callback data for fixing up AnimData links later */
- afd.srcArm = ob_iter;
- afd.tarArm = ob_active;
- afd.names_map = BLI_ghash_str_new("join_armature_adt_fix");
-
- /* Make a list of editbones in current armature */
- ED_armature_to_edit(ob_iter->data);
-
- /* Get Pose of current armature */
- opose = ob_iter->pose;
- ob_iter->mode &= ~OB_MODE_POSE;
- //BASACT->flag &= ~OB_MODE_POSE;
-
- /* Find the difference matrix */
- invert_m4_m4(oimat, ob_active->obmat);
- mul_m4_m4m4(mat, oimat, ob_iter->obmat);
-
- /* Copy bones and posechannels from the object to the edit armature */
- for (pchan = opose->chanbase.first; pchan; pchan = pchann) {
- pchann = pchan->next;
- curbone = ED_armature_ebone_find_name(curarm->edbo, pchan->name);
-
- /* Get new name */
- ED_armature_ebone_unique_name(arm->edbo, curbone->name, NULL);
- BLI_ghash_insert(afd.names_map, BLI_strdup(pchan->name), curbone->name);
-
- /* Transform the bone */
- {
- float premat[4][4];
- float postmat[4][4];
- float difmat[4][4];
- float imat[4][4];
- float temp[3][3];
-
- /* Get the premat */
- ED_armature_ebone_to_mat3(curbone, temp);
-
- unit_m4(premat); /* mul_m4_m3m4 only sets 3x3 part */
- mul_m4_m3m4(premat, temp, mat);
-
- mul_m4_v3(mat, curbone->head);
- mul_m4_v3(mat, curbone->tail);
-
- /* Get the postmat */
- ED_armature_ebone_to_mat3(curbone, temp);
- copy_m4_m3(postmat, temp);
-
- /* Find the roll */
- invert_m4_m4(imat, premat);
- mul_m4_m4m4(difmat, imat, postmat);
-
- curbone->roll -= atan2f(difmat[2][0], difmat[2][2]);
- }
-
- /* Fix Constraints and Other Links to this Bone and Armature */
- joined_armature_fix_links(bmain, ob_active, ob_iter, pchan, curbone);
-
- /* Rename pchan */
- BLI_strncpy(pchan->name, curbone->name, sizeof(pchan->name));
-
- /* Jump Ship! */
- BLI_remlink(curarm->edbo, curbone);
- BLI_addtail(arm->edbo, curbone);
-
- BLI_remlink(&opose->chanbase, pchan);
- BLI_addtail(&pose->chanbase, pchan);
- BKE_pose_channels_hash_free(opose);
- BKE_pose_channels_hash_free(pose);
- }
-
- /* Fix all the drivers (and animation data) */
- BKE_fcurves_main_cb(bmain, joined_armature_fix_animdata_cb, &afd);
- BLI_ghash_free(afd.names_map, MEM_freeN, NULL);
-
- /* Only copy over animdata now, after all the remapping has been done,
- * so that we don't have to worry about ambiguities re which armature
- * a bone came from!
- */
- if (ob_iter->adt) {
- if (ob_active->adt == NULL) {
- /* no animdata, so just use a copy of the whole thing */
- ob_active->adt = BKE_animdata_copy(bmain, ob_iter->adt, 0);
- }
- else {
- /* merge in data - we'll fix the drivers manually */
- BKE_animdata_merge_copy(bmain, &ob_active->id, &ob_iter->id, ADT_MERGECOPY_KEEP_DST, false);
- }
- }
-
- if (curarm->adt) {
- if (arm->adt == NULL) {
- /* no animdata, so just use a copy of the whole thing */
- arm->adt = BKE_animdata_copy(bmain, curarm->adt, 0);
- }
- else {
- /* merge in data - we'll fix the drivers manually */
- BKE_animdata_merge_copy(bmain, &arm->id, &curarm->id, ADT_MERGECOPY_KEEP_DST, false);
- }
- }
-
- /* Free the old object data */
- ED_object_base_free_and_unlink(bmain, scene, ob_iter);
- }
- }
- CTX_DATA_END;
-
- DEG_relations_tag_update(bmain); /* because we removed object(s) */
-
- ED_armature_from_edit(bmain, arm);
- ED_armature_edit_free(arm);
-
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob_active = CTX_data_active_object(C);
+ bArmature *arm = (ob_active) ? ob_active->data : NULL;
+ bPose *pose, *opose;
+ bPoseChannel *pchan, *pchann;
+ EditBone *curbone;
+ float mat[4][4], oimat[4][4];
+ bool ok = false;
+
+ /* Ensure we're not in editmode and that the active object is an armature*/
+ if (!ob_active || ob_active->type != OB_ARMATURE)
+ return OPERATOR_CANCELLED;
+ if (!arm || arm->edbo)
+ return OPERATOR_CANCELLED;
+
+ CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
+ if (ob_iter == ob_active) {
+ ok = true;
+ break;
+ }
+ }
+ CTX_DATA_END;
+
+ /* that way the active object is always selected */
+ if (ok == false) {
+ BKE_report(op->reports, RPT_WARNING, "Active object is not a selected armature");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Get editbones of active armature to add editbones to */
+ ED_armature_to_edit(arm);
+
+ /* get pose of active object and move it out of posemode */
+ pose = ob_active->pose;
+ ob_active->mode &= ~OB_MODE_POSE;
+
+ CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
+ if ((ob_iter->type == OB_ARMATURE) && (ob_iter != ob_active)) {
+ tJoinArmature_AdtFixData afd = {NULL};
+ bArmature *curarm = ob_iter->data;
+
+ /* we assume that each armature datablock is only used in a single place */
+ BLI_assert(ob_active->data != ob_iter->data);
+
+ /* init callback data for fixing up AnimData links later */
+ afd.srcArm = ob_iter;
+ afd.tarArm = ob_active;
+ afd.names_map = BLI_ghash_str_new("join_armature_adt_fix");
+
+ /* Make a list of editbones in current armature */
+ ED_armature_to_edit(ob_iter->data);
+
+ /* Get Pose of current armature */
+ opose = ob_iter->pose;
+ ob_iter->mode &= ~OB_MODE_POSE;
+ //BASACT->flag &= ~OB_MODE_POSE;
+
+ /* Find the difference matrix */
+ invert_m4_m4(oimat, ob_active->obmat);
+ mul_m4_m4m4(mat, oimat, ob_iter->obmat);
+
+ /* Copy bones and posechannels from the object to the edit armature */
+ for (pchan = opose->chanbase.first; pchan; pchan = pchann) {
+ pchann = pchan->next;
+ curbone = ED_armature_ebone_find_name(curarm->edbo, pchan->name);
+
+ /* Get new name */
+ ED_armature_ebone_unique_name(arm->edbo, curbone->name, NULL);
+ BLI_ghash_insert(afd.names_map, BLI_strdup(pchan->name), curbone->name);
+
+ /* Transform the bone */
+ {
+ float premat[4][4];
+ float postmat[4][4];
+ float difmat[4][4];
+ float imat[4][4];
+ float temp[3][3];
+
+ /* Get the premat */
+ ED_armature_ebone_to_mat3(curbone, temp);
+
+ unit_m4(premat); /* mul_m4_m3m4 only sets 3x3 part */
+ mul_m4_m3m4(premat, temp, mat);
+
+ mul_m4_v3(mat, curbone->head);
+ mul_m4_v3(mat, curbone->tail);
+
+ /* Get the postmat */
+ ED_armature_ebone_to_mat3(curbone, temp);
+ copy_m4_m3(postmat, temp);
+
+ /* Find the roll */
+ invert_m4_m4(imat, premat);
+ mul_m4_m4m4(difmat, imat, postmat);
+
+ curbone->roll -= atan2f(difmat[2][0], difmat[2][2]);
+ }
+
+ /* Fix Constraints and Other Links to this Bone and Armature */
+ joined_armature_fix_links(bmain, ob_active, ob_iter, pchan, curbone);
+
+ /* Rename pchan */
+ BLI_strncpy(pchan->name, curbone->name, sizeof(pchan->name));
+
+ /* Jump Ship! */
+ BLI_remlink(curarm->edbo, curbone);
+ BLI_addtail(arm->edbo, curbone);
+
+ BLI_remlink(&opose->chanbase, pchan);
+ BLI_addtail(&pose->chanbase, pchan);
+ BKE_pose_channels_hash_free(opose);
+ BKE_pose_channels_hash_free(pose);
+ }
+
+ /* Fix all the drivers (and animation data) */
+ BKE_fcurves_main_cb(bmain, joined_armature_fix_animdata_cb, &afd);
+ BLI_ghash_free(afd.names_map, MEM_freeN, NULL);
+
+ /* Only copy over animdata now, after all the remapping has been done,
+ * so that we don't have to worry about ambiguities re which armature
+ * a bone came from!
+ */
+ if (ob_iter->adt) {
+ if (ob_active->adt == NULL) {
+ /* no animdata, so just use a copy of the whole thing */
+ ob_active->adt = BKE_animdata_copy(bmain, ob_iter->adt, 0);
+ }
+ else {
+ /* merge in data - we'll fix the drivers manually */
+ BKE_animdata_merge_copy(
+ bmain, &ob_active->id, &ob_iter->id, ADT_MERGECOPY_KEEP_DST, false);
+ }
+ }
+
+ if (curarm->adt) {
+ if (arm->adt == NULL) {
+ /* no animdata, so just use a copy of the whole thing */
+ arm->adt = BKE_animdata_copy(bmain, curarm->adt, 0);
+ }
+ else {
+ /* merge in data - we'll fix the drivers manually */
+ BKE_animdata_merge_copy(bmain, &arm->id, &curarm->id, ADT_MERGECOPY_KEEP_DST, false);
+ }
+ }
+
+ /* Free the old object data */
+ ED_object_base_free_and_unlink(bmain, scene, ob_iter);
+ }
+ }
+ CTX_DATA_END;
+
+ DEG_relations_tag_update(bmain); /* because we removed object(s) */
+
+ ED_armature_from_edit(bmain, arm);
+ ED_armature_edit_free(arm);
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+
+ return OPERATOR_FINISHED;
}
/* *********************************** Separate *********************************************** */
@@ -407,103 +404,103 @@ int join_armature_exec(bContext *C, wmOperator *op)
/* Helper function for armature separating - link fixing */
static void separated_armature_fix_links(Main *bmain, Object *origArm, Object *newArm)
{
- Object *ob;
- bPoseChannel *pchan;
- bConstraint *con;
- ListBase *opchans, *npchans;
-
- /* get reference to list of bones in original and new armatures */
- opchans = &origArm->pose->chanbase;
- npchans = &newArm->pose->chanbase;
-
- /* let's go through all objects in database */
- for (ob = bmain->objects.first; ob; ob = ob->id.next) {
- /* do some object-type specific things */
- if (ob->type == OB_ARMATURE) {
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- for (con = pchan->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- /* constraint targets */
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- /* any targets which point to original armature are redirected to the new one only if:
- * - the target isn't origArm/newArm itself
- * - the target is one that can be found in newArm/origArm
- */
- if (ct->subtarget[0] != 0) {
- if (ct->tar == origArm) {
- if (BLI_findstring(npchans, ct->subtarget, offsetof(bPoseChannel, name))) {
- ct->tar = newArm;
- }
- }
- else if (ct->tar == newArm) {
- if (BLI_findstring(opchans, ct->subtarget, offsetof(bPoseChannel, name))) {
- ct->tar = origArm;
- }
- }
- }
- }
-
- if (cti->flush_constraint_targets) {
- cti->flush_constraint_targets(con, &targets, 0);
- }
- }
- }
- }
- }
-
- /* fix object-level constraints */
- if (ob != origArm) {
- for (con = ob->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- /* constraint targets */
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- /* any targets which point to original armature are redirected to the new one only if:
- * - the target isn't origArm/newArm itself
- * - the target is one that can be found in newArm/origArm
- */
- if (ct->subtarget[0] != '\0') {
- if (ct->tar == origArm) {
- if (BLI_findstring(npchans, ct->subtarget, offsetof(bPoseChannel, name))) {
- ct->tar = newArm;
- }
- }
- else if (ct->tar == newArm) {
- if (BLI_findstring(opchans, ct->subtarget, offsetof(bPoseChannel, name))) {
- ct->tar = origArm;
- }
- }
- }
- }
-
- if (cti->flush_constraint_targets) {
- cti->flush_constraint_targets(con, &targets, 0);
- }
- }
- }
- }
-
- /* See if an object is parented to this armature */
- if (ob->parent && (ob->parent == origArm)) {
- /* Is object parented to a bone of this src armature? */
- if ((ob->partype == PARBONE) && (ob->parsubstr[0] != '\0')) {
- if (BLI_findstring(npchans, ob->parsubstr, offsetof(bPoseChannel, name))) {
- ob->parent = newArm;
- }
- }
- }
- }
+ Object *ob;
+ bPoseChannel *pchan;
+ bConstraint *con;
+ ListBase *opchans, *npchans;
+
+ /* get reference to list of bones in original and new armatures */
+ opchans = &origArm->pose->chanbase;
+ npchans = &newArm->pose->chanbase;
+
+ /* let's go through all objects in database */
+ for (ob = bmain->objects.first; ob; ob = ob->id.next) {
+ /* do some object-type specific things */
+ if (ob->type == OB_ARMATURE) {
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ for (con = pchan->constraints.first; con; con = con->next) {
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ /* constraint targets */
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct = targets.first; ct; ct = ct->next) {
+ /* any targets which point to original armature are redirected to the new one only if:
+ * - the target isn't origArm/newArm itself
+ * - the target is one that can be found in newArm/origArm
+ */
+ if (ct->subtarget[0] != 0) {
+ if (ct->tar == origArm) {
+ if (BLI_findstring(npchans, ct->subtarget, offsetof(bPoseChannel, name))) {
+ ct->tar = newArm;
+ }
+ }
+ else if (ct->tar == newArm) {
+ if (BLI_findstring(opchans, ct->subtarget, offsetof(bPoseChannel, name))) {
+ ct->tar = origArm;
+ }
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets) {
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+ }
+ }
+ }
+ }
+
+ /* fix object-level constraints */
+ if (ob != origArm) {
+ for (con = ob->constraints.first; con; con = con->next) {
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ /* constraint targets */
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct = targets.first; ct; ct = ct->next) {
+ /* any targets which point to original armature are redirected to the new one only if:
+ * - the target isn't origArm/newArm itself
+ * - the target is one that can be found in newArm/origArm
+ */
+ if (ct->subtarget[0] != '\0') {
+ if (ct->tar == origArm) {
+ if (BLI_findstring(npchans, ct->subtarget, offsetof(bPoseChannel, name))) {
+ ct->tar = newArm;
+ }
+ }
+ else if (ct->tar == newArm) {
+ if (BLI_findstring(opchans, ct->subtarget, offsetof(bPoseChannel, name))) {
+ ct->tar = origArm;
+ }
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets) {
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+ }
+ }
+ }
+
+ /* See if an object is parented to this armature */
+ if (ob->parent && (ob->parent == origArm)) {
+ /* Is object parented to a bone of this src armature? */
+ if ((ob->partype == PARBONE) && (ob->parsubstr[0] != '\0')) {
+ if (BLI_findstring(npchans, ob->parsubstr, offsetof(bPoseChannel, name))) {
+ ob->parent = newArm;
+ }
+ }
+ }
+ }
}
/* Helper function for armature separating - remove certain bones from the given armature
@@ -512,429 +509,432 @@ static void separated_armature_fix_links(Main *bmain, Object *origArm, Object *n
*/
static void separate_armature_bones(Main *bmain, Object *ob, short sel)
{
- bArmature *arm = (bArmature *)ob->data;
- bPoseChannel *pchan, *pchann;
- EditBone *curbone;
-
- /* make local set of editbones to manipulate here */
- ED_armature_to_edit(arm);
-
- /* go through pose-channels, checking if a bone should be removed */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchann) {
- pchann = pchan->next;
- curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name);
-
- /* check if bone needs to be removed */
- if ( (sel && (curbone->flag & BONE_SELECTED)) ||
- (!sel && !(curbone->flag & BONE_SELECTED)) )
- {
- EditBone *ebo;
- bPoseChannel *pchn;
-
- /* clear the bone->parent var of any bone that had this as its parent */
- for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
- if (ebo->parent == curbone) {
- ebo->parent = NULL;
- /* this is needed to prevent random crashes with in ED_armature_from_edit */
- ebo->temp.p = NULL;
- ebo->flag &= ~BONE_CONNECTED;
- }
- }
-
- /* clear the pchan->parent var of any pchan that had this as its parent */
- for (pchn = ob->pose->chanbase.first; pchn; pchn = pchn->next) {
- if (pchn->parent == pchan) {
- pchn->parent = NULL;
- }
- if (pchn->bbone_next == pchan) {
- pchn->bbone_next = NULL;
- }
- if (pchn->bbone_prev == pchan) {
- pchn->bbone_prev = NULL;
- }
- }
-
- /* free any of the extra-data this pchan might have */
- BKE_pose_channel_free(pchan);
- BKE_pose_channels_hash_free(ob->pose);
-
- /* get rid of unneeded bone */
- bone_free(arm, curbone);
- BLI_freelinkN(&ob->pose->chanbase, pchan);
- }
- }
-
- /* exit editmode (recalculates pchans too) */
- ED_armature_from_edit(bmain, ob->data);
- ED_armature_edit_free(ob->data);
+ bArmature *arm = (bArmature *)ob->data;
+ bPoseChannel *pchan, *pchann;
+ EditBone *curbone;
+
+ /* make local set of editbones to manipulate here */
+ ED_armature_to_edit(arm);
+
+ /* go through pose-channels, checking if a bone should be removed */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchann) {
+ pchann = pchan->next;
+ curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name);
+
+ /* check if bone needs to be removed */
+ if ((sel && (curbone->flag & BONE_SELECTED)) || (!sel && !(curbone->flag & BONE_SELECTED))) {
+ EditBone *ebo;
+ bPoseChannel *pchn;
+
+ /* clear the bone->parent var of any bone that had this as its parent */
+ for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ if (ebo->parent == curbone) {
+ ebo->parent = NULL;
+ /* this is needed to prevent random crashes with in ED_armature_from_edit */
+ ebo->temp.p = NULL;
+ ebo->flag &= ~BONE_CONNECTED;
+ }
+ }
+
+ /* clear the pchan->parent var of any pchan that had this as its parent */
+ for (pchn = ob->pose->chanbase.first; pchn; pchn = pchn->next) {
+ if (pchn->parent == pchan) {
+ pchn->parent = NULL;
+ }
+ if (pchn->bbone_next == pchan) {
+ pchn->bbone_next = NULL;
+ }
+ if (pchn->bbone_prev == pchan) {
+ pchn->bbone_prev = NULL;
+ }
+ }
+
+ /* free any of the extra-data this pchan might have */
+ BKE_pose_channel_free(pchan);
+ BKE_pose_channels_hash_free(ob->pose);
+
+ /* get rid of unneeded bone */
+ bone_free(arm, curbone);
+ BLI_freelinkN(&ob->pose->chanbase, pchan);
+ }
+ }
+
+ /* exit editmode (recalculates pchans too) */
+ ED_armature_from_edit(bmain, ob->data);
+ ED_armature_edit_free(ob->data);
}
/* separate selected bones into their armature */
static int separate_armature_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);
- bool ok = false;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ bool ok = false;
- /* set wait cursor in case this takes a while */
- WM_cursor_wait(1);
+ /* set wait cursor in case this takes a while */
+ WM_cursor_wait(1);
- 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);
+ 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);
- CTX_DATA_BEGIN(C, Base *, base, visible_bases)
- {
- ED_object_base_select(base, BA_DESELECT);
- }
- CTX_DATA_END;
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ ED_object_base_select(base, BA_DESELECT);
+ }
+ CTX_DATA_END;
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *obedit = base_iter->object;
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ Object *obedit = base_iter->object;
- Object *oldob, *newob;
- Base *oldbase, *newbase;
+ Object *oldob, *newob;
+ Base *oldbase, *newbase;
- /* we are going to do this as follows (unlike every other instance of separate):
- * 1. exit editmode +posemode for active armature/base. Take note of what this is.
- * 2. duplicate base - BASACT is the new one now
- * 3. for each of the two armatures, enter editmode -> remove appropriate bones -> exit editmode + recalc
- * 4. fix constraint links
- * 5. make original armature active and enter editmode
- */
+ /* we are going to do this as follows (unlike every other instance of separate):
+ * 1. exit editmode +posemode for active armature/base. Take note of what this is.
+ * 2. duplicate base - BASACT is the new one now
+ * 3. for each of the two armatures, enter editmode -> remove appropriate bones -> exit editmode + recalc
+ * 4. fix constraint links
+ * 5. make original armature active and enter editmode
+ */
- /* 1) only edit-base selected */
- ED_object_base_select(base_iter, BA_SELECT);
+ /* 1) only edit-base selected */
+ ED_object_base_select(base_iter, BA_SELECT);
- /* 1) store starting settings and exit editmode */
- oldob = obedit;
- oldbase = base_iter;
- oldob->mode &= ~OB_MODE_POSE;
- //oldbase->flag &= ~OB_POSEMODE;
+ /* 1) store starting settings and exit editmode */
+ oldob = obedit;
+ oldbase = base_iter;
+ oldob->mode &= ~OB_MODE_POSE;
+ //oldbase->flag &= ~OB_POSEMODE;
- ED_armature_from_edit(bmain, obedit->data);
- ED_armature_edit_free(obedit->data);
+ ED_armature_from_edit(bmain, obedit->data);
+ ED_armature_edit_free(obedit->data);
- /* 2) duplicate base */
+ /* 2) duplicate base */
- /* only duplicate linked armature */
- newbase = ED_object_add_duplicate(bmain, scene, view_layer, oldbase, USER_DUP_ARM);
+ /* only duplicate linked armature */
+ newbase = ED_object_add_duplicate(bmain, scene, view_layer, oldbase, USER_DUP_ARM);
- DEG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
- newob = newbase->object;
- newbase->flag &= ~BASE_SELECTED;
+ newob = newbase->object;
+ newbase->flag &= ~BASE_SELECTED;
+ /* 3) remove bones that shouldn't still be around on both armatures */
+ separate_armature_bones(bmain, oldob, 1);
+ separate_armature_bones(bmain, newob, 0);
- /* 3) remove bones that shouldn't still be around on both armatures */
- separate_armature_bones(bmain, oldob, 1);
- separate_armature_bones(bmain, newob, 0);
+ /* 4) fix links before depsgraph flushes */ // err... or after?
+ separated_armature_fix_links(bmain, oldob, newob);
+ DEG_id_tag_update(&oldob->id, ID_RECALC_GEOMETRY); /* this is the original one */
+ DEG_id_tag_update(&newob->id, ID_RECALC_GEOMETRY); /* this is the separated one */
- /* 4) fix links before depsgraph flushes */ // err... or after?
- separated_armature_fix_links(bmain, oldob, newob);
+ /* 5) restore original conditions */
+ obedit = oldob;
- DEG_id_tag_update(&oldob->id, ID_RECALC_GEOMETRY); /* this is the original one */
- DEG_id_tag_update(&newob->id, ID_RECALC_GEOMETRY); /* this is the separated one */
+ ED_armature_to_edit(obedit->data);
+ /* parents tips remain selected when connected children are removed. */
+ ED_armature_edit_deselect_all(obedit);
- /* 5) restore original conditions */
- obedit = oldob;
+ ok = true;
- ED_armature_to_edit(obedit->data);
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
+ }
+ MEM_freeN(bases);
- /* parents tips remain selected when connected children are removed. */
- ED_armature_edit_deselect_all(obedit);
+ /* recalc/redraw + cleanup */
+ WM_cursor_wait(0);
- ok = true;
+ if (ok) {
+ BKE_report(op->reports, RPT_INFO, "Separated bones");
+ }
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
- }
- MEM_freeN(bases);
-
- /* recalc/redraw + cleanup */
- WM_cursor_wait(0);
-
- if (ok) {
- BKE_report(op->reports, RPT_INFO, "Separated bones");
- }
-
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_separate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Separate Bones";
- ot->idname = "ARMATURE_OT_separate";
- ot->description = "Isolate selected bones into a separate armature";
-
- /* callbacks */
- ot->invoke = WM_operator_confirm;
- ot->exec = separate_armature_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Separate Bones";
+ ot->idname = "ARMATURE_OT_separate";
+ ot->description = "Isolate selected bones into a separate armature";
+
+ /* callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = separate_armature_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************************************** Parenting ************************************************* */
/* armature parenting options */
#define ARM_PAR_CONNECT 1
-#define ARM_PAR_OFFSET 2
-
+#define ARM_PAR_OFFSET 2
/* check for null, before calling! */
static void bone_connect_to_existing_parent(EditBone *bone)
{
- bone->flag |= BONE_CONNECTED;
- copy_v3_v3(bone->head, bone->parent->tail);
- bone->rad_head = bone->parent->rad_tail;
+ bone->flag |= BONE_CONNECTED;
+ copy_v3_v3(bone->head, bone->parent->tail);
+ bone->rad_head = bone->parent->rad_tail;
}
-static void bone_connect_to_new_parent(ListBase *edbo, EditBone *selbone, EditBone *actbone, short mode)
+static void bone_connect_to_new_parent(ListBase *edbo,
+ EditBone *selbone,
+ EditBone *actbone,
+ short mode)
{
- EditBone *ebone;
- float offset[3];
-
- if ((selbone->parent) && (selbone->flag & BONE_CONNECTED))
- selbone->parent->flag &= ~(BONE_TIPSEL);
-
- /* make actbone the parent of selbone */
- selbone->parent = actbone;
-
- /* in actbone tree we cannot have a loop */
- for (ebone = actbone->parent; ebone; ebone = ebone->parent) {
- if (ebone->parent == selbone) {
- ebone->parent = NULL;
- ebone->flag &= ~BONE_CONNECTED;
- }
- }
-
- if (mode == ARM_PAR_CONNECT) {
- /* Connected: Child bones will be moved to the parent tip */
- selbone->flag |= BONE_CONNECTED;
- sub_v3_v3v3(offset, actbone->tail, selbone->head);
-
- copy_v3_v3(selbone->head, actbone->tail);
- selbone->rad_head = actbone->rad_tail;
-
- add_v3_v3(selbone->tail, offset);
-
- /* offset for all its children */
- for (ebone = edbo->first; ebone; ebone = ebone->next) {
- EditBone *par;
-
- for (par = ebone->parent; par; par = par->parent) {
- if (par == selbone) {
- add_v3_v3(ebone->head, offset);
- add_v3_v3(ebone->tail, offset);
- break;
- }
- }
- }
- }
- else {
- /* Offset: Child bones will retain their distance from the parent tip */
- selbone->flag &= ~BONE_CONNECTED;
- }
+ EditBone *ebone;
+ float offset[3];
+
+ if ((selbone->parent) && (selbone->flag & BONE_CONNECTED))
+ selbone->parent->flag &= ~(BONE_TIPSEL);
+
+ /* make actbone the parent of selbone */
+ selbone->parent = actbone;
+
+ /* in actbone tree we cannot have a loop */
+ for (ebone = actbone->parent; ebone; ebone = ebone->parent) {
+ if (ebone->parent == selbone) {
+ ebone->parent = NULL;
+ ebone->flag &= ~BONE_CONNECTED;
+ }
+ }
+
+ if (mode == ARM_PAR_CONNECT) {
+ /* Connected: Child bones will be moved to the parent tip */
+ selbone->flag |= BONE_CONNECTED;
+ sub_v3_v3v3(offset, actbone->tail, selbone->head);
+
+ copy_v3_v3(selbone->head, actbone->tail);
+ selbone->rad_head = actbone->rad_tail;
+
+ add_v3_v3(selbone->tail, offset);
+
+ /* offset for all its children */
+ for (ebone = edbo->first; ebone; ebone = ebone->next) {
+ EditBone *par;
+
+ for (par = ebone->parent; par; par = par->parent) {
+ if (par == selbone) {
+ add_v3_v3(ebone->head, offset);
+ add_v3_v3(ebone->tail, offset);
+ break;
+ }
+ }
+ }
+ }
+ else {
+ /* Offset: Child bones will retain their distance from the parent tip */
+ selbone->flag &= ~BONE_CONNECTED;
+ }
}
-
static const EnumPropertyItem prop_editarm_make_parent_types[] = {
- {ARM_PAR_CONNECT, "CONNECTED", 0, "Connected", ""},
- {ARM_PAR_OFFSET, "OFFSET", 0, "Keep Offset", ""},
- {0, NULL, 0, NULL, NULL},
+ {ARM_PAR_CONNECT, "CONNECTED", 0, "Connected", ""},
+ {ARM_PAR_OFFSET, "OFFSET", 0, "Keep Offset", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int armature_parent_set_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_edit_object(C);
- bArmature *arm = (bArmature *)ob->data;
- EditBone *actbone = CTX_data_active_bone(C);
- EditBone *actmirb = NULL;
- short val = RNA_enum_get(op->ptr, "type");
-
- /* there must be an active bone */
- if (actbone == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
- return OPERATOR_CANCELLED;
- }
- else if (arm->flag & ARM_MIRROR_EDIT) {
- /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
- * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone
- * (i.e. selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
- * This is useful for arm-chains, for example parenting lower arm to upper arm
- * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
- * then just use actbone. Useful when doing upper arm to spine.
- */
- actmirb = ED_armature_ebone_get_mirrored(arm->edbo, actbone);
- if (actmirb == NULL)
- actmirb = actbone;
- }
-
- /* if there is only 1 selected bone, we assume that that is the active bone,
- * since a user will need to have clicked on a bone (thus selecting it) to make it active
- */
- if (CTX_DATA_COUNT(C, selected_editable_bones) <= 1) {
- /* When only the active bone is selected, and it has a parent,
- * connect it to the parent, as that is the only possible outcome.
- */
- if (actbone->parent) {
- bone_connect_to_existing_parent(actbone);
-
- if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
- bone_connect_to_existing_parent(actmirb);
- }
- }
- else {
- /* Parent 'selected' bones to the active one
- * - the context iterator contains both selected bones and their mirrored copies,
- * so we assume that unselected bones are mirrored copies of some selected bone
- * - since the active one (and/or its mirror) will also be selected, we also need
- * to check that we are not trying to operate on them, since such an operation
- * would cause errors
- */
-
- /* parent selected bones to the active one */
- CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
- {
- if (ELEM(ebone, actbone, actmirb) == 0) {
- if (ebone->flag & BONE_SELECTED)
- bone_connect_to_new_parent(arm->edbo, ebone, actbone, val);
- else
- bone_connect_to_new_parent(arm->edbo, ebone, actmirb, val);
- }
- }
- CTX_DATA_END;
- }
-
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
- return OPERATOR_FINISHED;
+ Object *ob = CTX_data_edit_object(C);
+ bArmature *arm = (bArmature *)ob->data;
+ EditBone *actbone = CTX_data_active_bone(C);
+ EditBone *actmirb = NULL;
+ short val = RNA_enum_get(op->ptr, "type");
+
+ /* there must be an active bone */
+ if (actbone == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
+ return OPERATOR_CANCELLED;
+ }
+ else if (arm->flag & ARM_MIRROR_EDIT) {
+ /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
+ * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone
+ * (i.e. selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
+ * This is useful for arm-chains, for example parenting lower arm to upper arm
+ * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
+ * then just use actbone. Useful when doing upper arm to spine.
+ */
+ actmirb = ED_armature_ebone_get_mirrored(arm->edbo, actbone);
+ if (actmirb == NULL)
+ actmirb = actbone;
+ }
+
+ /* if there is only 1 selected bone, we assume that that is the active bone,
+ * since a user will need to have clicked on a bone (thus selecting it) to make it active
+ */
+ if (CTX_DATA_COUNT(C, selected_editable_bones) <= 1) {
+ /* When only the active bone is selected, and it has a parent,
+ * connect it to the parent, as that is the only possible outcome.
+ */
+ if (actbone->parent) {
+ bone_connect_to_existing_parent(actbone);
+
+ if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
+ bone_connect_to_existing_parent(actmirb);
+ }
+ }
+ else {
+ /* Parent 'selected' bones to the active one
+ * - the context iterator contains both selected bones and their mirrored copies,
+ * so we assume that unselected bones are mirrored copies of some selected bone
+ * - since the active one (and/or its mirror) will also be selected, we also need
+ * to check that we are not trying to operate on them, since such an operation
+ * would cause errors
+ */
+
+ /* parent selected bones to the active one */
+ CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones) {
+ if (ELEM(ebone, actbone, actmirb) == 0) {
+ if (ebone->flag & BONE_SELECTED)
+ bone_connect_to_new_parent(arm->edbo, ebone, actbone, val);
+ else
+ bone_connect_to_new_parent(arm->edbo, ebone, actmirb, val);
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+
+ return OPERATOR_FINISHED;
}
-static int armature_parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
+static int armature_parent_set_invoke(bContext *C,
+ wmOperator *UNUSED(op),
+ const wmEvent *UNUSED(event))
{
- EditBone *actbone = CTX_data_active_bone(C);
- uiPopupMenu *pup = UI_popup_menu_begin(C, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Make Parent"), ICON_NONE);
- uiLayout *layout = UI_popup_menu_layout(pup);
- int allchildbones = 0;
+ EditBone *actbone = CTX_data_active_bone(C);
+ uiPopupMenu *pup = UI_popup_menu_begin(
+ C, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Make Parent"), ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+ int allchildbones = 0;
- CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
- {
- if (ebone != actbone) {
- if (ebone->parent != actbone) allchildbones = 1;
- }
- }
- CTX_DATA_END;
+ CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones) {
+ if (ebone != actbone) {
+ if (ebone->parent != actbone)
+ allchildbones = 1;
+ }
+ }
+ CTX_DATA_END;
- uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_CONNECT);
+ uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_CONNECT);
- /* ob becomes parent, make the associated menus */
- if (allchildbones)
- uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_OFFSET);
+ /* ob becomes parent, make the associated menus */
+ if (allchildbones)
+ uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_OFFSET);
- UI_popup_menu_end(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
void ARMATURE_OT_parent_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Parent";
- ot->idname = "ARMATURE_OT_parent_set";
- ot->description = "Set the active bone as the parent of the selected bones";
+ /* identifiers */
+ ot->name = "Make Parent";
+ ot->idname = "ARMATURE_OT_parent_set";
+ ot->description = "Set the active bone as the parent of the selected bones";
- /* api callbacks */
- ot->invoke = armature_parent_set_invoke;
- ot->exec = armature_parent_set_exec;
- ot->poll = ED_operator_editarmature;
+ /* api callbacks */
+ ot->invoke = armature_parent_set_invoke;
+ ot->exec = armature_parent_set_exec;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_enum(ot->srna, "type", prop_editarm_make_parent_types, 0, "ParentType", "Type of parenting");
+ RNA_def_enum(
+ ot->srna, "type", prop_editarm_make_parent_types, 0, "ParentType", "Type of parenting");
}
-
-
static const EnumPropertyItem prop_editarm_clear_parent_types[] = {
- {1, "CLEAR", 0, "Clear Parent", ""},
- {2, "DISCONNECT", 0, "Disconnect Bone", ""},
- {0, NULL, 0, NULL, NULL},
+ {1, "CLEAR", 0, "Clear Parent", ""},
+ {2, "DISCONNECT", 0, "Disconnect Bone", ""},
+ {0, NULL, 0, NULL, NULL},
};
static void editbone_clear_parent(EditBone *ebone, int mode)
{
- if (ebone->parent) {
- /* for nice selection */
- ebone->parent->flag &= ~(BONE_TIPSEL);
- }
-
- if (mode == 1) ebone->parent = NULL;
- ebone->flag &= ~BONE_CONNECTED;
+ if (ebone->parent) {
+ /* for nice selection */
+ ebone->parent->flag &= ~(BONE_TIPSEL);
+ }
+
+ if (mode == 1)
+ ebone->parent = NULL;
+ ebone->flag &= ~BONE_CONNECTED;
}
static int armature_parent_clear_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const int val = RNA_enum_get(op->ptr, "type");
-
- CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
- {
- editbone_clear_parent(ebone, val);
- }
- CTX_DATA_END;
-
- 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 changed = false;
-
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_EDITABLE(ebone)) {
- changed = true;
- break;
- }
- }
-
- if (!changed) {
- continue;
- }
-
- ED_armature_edit_sync_selection(arm->edbo);
-
- /* Note, notifier might evolve. */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const int val = RNA_enum_get(op->ptr, "type");
+
+ CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones) {
+ editbone_clear_parent(ebone, val);
+ }
+ CTX_DATA_END;
+
+ 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 changed = false;
+
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_EDITABLE(ebone)) {
+ changed = true;
+ break;
+ }
+ }
+
+ if (!changed) {
+ continue;
+ }
+
+ ED_armature_edit_sync_selection(arm->edbo);
+
+ /* Note, notifier might evolve. */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_parent_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Parent";
- ot->idname = "ARMATURE_OT_parent_clear";
- ot->description = "Remove the parent-child relationship between selected bones and their parents";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = armature_parent_clear_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ot->prop = RNA_def_enum(ot->srna, "type", prop_editarm_clear_parent_types, 0, "ClearType", "What way to clear parenting");
+ /* identifiers */
+ ot->name = "Clear Parent";
+ ot->idname = "ARMATURE_OT_parent_clear";
+ ot->description =
+ "Remove the parent-child relationship between selected bones and their parents";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = armature_parent_clear_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna,
+ "type",
+ prop_editarm_clear_parent_types,
+ 0,
+ "ClearType",
+ "What way to clear parenting");
}
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index 4aab80bcbdd..0c493672d9e 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -60,695 +60,713 @@
/* **************** PoseMode & EditMode Selection Buffer Queries *************************** */
-Base *ED_armature_base_and_ebone_from_select_buffer(
- Base **bases, uint bases_len, int hit, EditBone **r_ebone)
+Base *ED_armature_base_and_ebone_from_select_buffer(Base **bases,
+ uint bases_len,
+ int hit,
+ EditBone **r_ebone)
{
- const uint hit_object = hit & 0xFFFF;
- Base *base = NULL;
- EditBone *ebone = NULL;
- /* TODO(campbell): optimize, eg: sort & binary search. */
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- if (bases[base_index]->object->select_id == hit_object) {
- base = bases[base_index];
- break;
- }
- }
- if (base != NULL) {
- const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
- bArmature *arm = base->object->data;
- ebone = BLI_findlink(arm->edbo, hit_bone);
- }
- *r_ebone = ebone;
- return base;
+ const uint hit_object = hit & 0xFFFF;
+ Base *base = NULL;
+ EditBone *ebone = NULL;
+ /* TODO(campbell): optimize, eg: sort & binary search. */
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ if (bases[base_index]->object->select_id == hit_object) {
+ base = bases[base_index];
+ break;
+ }
+ }
+ if (base != NULL) {
+ const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
+ bArmature *arm = base->object->data;
+ ebone = BLI_findlink(arm->edbo, hit_bone);
+ }
+ *r_ebone = ebone;
+ return base;
}
-Object *ED_armature_object_and_ebone_from_select_buffer(
- Object **objects, uint objects_len, int hit, EditBone **r_ebone)
+Object *ED_armature_object_and_ebone_from_select_buffer(Object **objects,
+ uint objects_len,
+ int hit,
+ EditBone **r_ebone)
{
- const uint hit_object = hit & 0xFFFF;
- Object *ob = NULL;
- EditBone *ebone = NULL;
- /* TODO(campbell): optimize, eg: sort & binary search. */
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- if (objects[ob_index]->select_id == hit_object) {
- ob = objects[ob_index];
- break;
- }
- }
- if (ob != NULL) {
- const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
- bArmature *arm = ob->data;
- ebone = BLI_findlink(arm->edbo, hit_bone);
- }
- *r_ebone = ebone;
- return ob;
+ const uint hit_object = hit & 0xFFFF;
+ Object *ob = NULL;
+ EditBone *ebone = NULL;
+ /* TODO(campbell): optimize, eg: sort & binary search. */
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ if (objects[ob_index]->select_id == hit_object) {
+ ob = objects[ob_index];
+ break;
+ }
+ }
+ if (ob != NULL) {
+ const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
+ bArmature *arm = ob->data;
+ ebone = BLI_findlink(arm->edbo, hit_bone);
+ }
+ *r_ebone = ebone;
+ 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_bone_from_select_buffer(Base **bases,
+ uint bases_len,
+ int hit,
+ Bone **r_bone)
{
- const uint hit_object = hit & 0xFFFF;
- Base *base = NULL;
- Bone *bone = NULL;
- /* TODO(campbell): optimize, eg: sort & binary search. */
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- if (bases[base_index]->object->select_id == hit_object) {
- base = bases[base_index];
- break;
- }
- }
- 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;
- }
- }
- *r_bone = bone;
- return base;
+ const uint hit_object = hit & 0xFFFF;
+ Base *base = NULL;
+ Bone *bone = NULL;
+ /* TODO(campbell): optimize, eg: sort & binary search. */
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ if (bases[base_index]->object->select_id == hit_object) {
+ base = bases[base_index];
+ break;
+ }
+ }
+ 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;
+ }
+ }
+ *r_bone = bone;
+ return base;
}
/* 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)
+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)
{
- Bone *bone;
- EditBone *ebone;
- void *firstunSel = NULL, *firstSel = NULL, *data;
- Base *firstunSel_base = NULL, *firstSel_base = NULL;
- unsigned int hitresult;
- short i;
- bool takeNext = false;
- int minsel = 0xffffffff, minunsel = 0xffffffff;
-
- for (i = 0; i < hits; i++) {
- hitresult = buffer[3 + (i * 4)];
-
- if (!(hitresult & BONESEL_NOSEL)) {
- if (hitresult & BONESEL_ANY) { /* to avoid including objects in selection */
- Base *base = NULL;
- bool sel;
-
- hitresult &= ~(BONESEL_ANY);
- /* Determine what the current bone is */
- if (is_editmode == false) {
- base = ED_armature_base_and_bone_from_select_buffer(bases, bases_len, hitresult, &bone);
- if (bone != NULL) {
- if (findunsel)
- sel = (bone->flag & BONE_SELECTED);
- else
- sel = !(bone->flag & BONE_SELECTED);
-
- data = bone;
- }
- else {
- data = NULL;
- sel = 0;
- }
- }
- else {
- base = ED_armature_base_and_ebone_from_select_buffer(bases, bases_len, hitresult, &ebone);
- if (findunsel)
- sel = (ebone->flag & BONE_SELECTED);
- else
- sel = !(ebone->flag & BONE_SELECTED);
-
- data = ebone;
- }
-
- if (data) {
- if (sel) {
- if (do_nearest) {
- if (minsel > buffer[4 * i + 1]) {
- firstSel = data;
- firstSel_base = base;
- minsel = buffer[4 * i + 1];
- }
- }
- else {
- if (!firstSel) {
- firstSel = data;
- firstSel_base = base;
- }
- takeNext = 1;
- }
- }
- else {
- if (do_nearest) {
- if (minunsel > buffer[4 * i + 1]) {
- firstunSel = data;
- firstunSel_base = base;
- minunsel = buffer[4 * i + 1];
- }
- }
- else {
- if (!firstunSel) {
- firstunSel = data;
- firstunSel_base = base;
- }
- if (takeNext) {
- *r_base = base;
- return data;
- }
- }
- }
- }
- }
- }
- }
-
- if (firstunSel) {
- *r_base = firstunSel_base;
- return firstunSel;
- }
- else {
- *r_base = firstSel_base;
- return firstSel;
- }
+ Bone *bone;
+ EditBone *ebone;
+ void *firstunSel = NULL, *firstSel = NULL, *data;
+ Base *firstunSel_base = NULL, *firstSel_base = NULL;
+ unsigned int hitresult;
+ short i;
+ bool takeNext = false;
+ int minsel = 0xffffffff, minunsel = 0xffffffff;
+
+ for (i = 0; i < hits; i++) {
+ hitresult = buffer[3 + (i * 4)];
+
+ if (!(hitresult & BONESEL_NOSEL)) {
+ if (hitresult & BONESEL_ANY) { /* to avoid including objects in selection */
+ Base *base = NULL;
+ bool sel;
+
+ hitresult &= ~(BONESEL_ANY);
+ /* Determine what the current bone is */
+ if (is_editmode == false) {
+ base = ED_armature_base_and_bone_from_select_buffer(bases, bases_len, hitresult, &bone);
+ if (bone != NULL) {
+ if (findunsel)
+ sel = (bone->flag & BONE_SELECTED);
+ else
+ sel = !(bone->flag & BONE_SELECTED);
+
+ data = bone;
+ }
+ else {
+ data = NULL;
+ sel = 0;
+ }
+ }
+ else {
+ base = ED_armature_base_and_ebone_from_select_buffer(
+ bases, bases_len, hitresult, &ebone);
+ if (findunsel)
+ sel = (ebone->flag & BONE_SELECTED);
+ else
+ sel = !(ebone->flag & BONE_SELECTED);
+
+ data = ebone;
+ }
+
+ if (data) {
+ if (sel) {
+ if (do_nearest) {
+ if (minsel > buffer[4 * i + 1]) {
+ firstSel = data;
+ firstSel_base = base;
+ minsel = buffer[4 * i + 1];
+ }
+ }
+ else {
+ if (!firstSel) {
+ firstSel = data;
+ firstSel_base = base;
+ }
+ takeNext = 1;
+ }
+ }
+ else {
+ if (do_nearest) {
+ if (minunsel > buffer[4 * i + 1]) {
+ firstunSel = data;
+ firstunSel_base = base;
+ minunsel = buffer[4 * i + 1];
+ }
+ }
+ else {
+ if (!firstunSel) {
+ firstunSel = data;
+ firstunSel_base = base;
+ }
+ if (takeNext) {
+ *r_base = base;
+ return data;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (firstunSel) {
+ *r_base = firstunSel_base;
+ return firstunSel;
+ }
+ else {
+ *r_base = firstSel_base;
+ return firstSel;
+ }
}
/* 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)
+void *get_nearest_bone(bContext *C, const int xy[2], bool findunsel, Base **r_base)
{
- ViewContext vc;
- rcti rect;
- unsigned int buffer[MAXPICKBUF];
- short hits;
-
- ED_view3d_viewcontext_init(C, &vc);
-
- // rect.xmin = ... mouseco!
- rect.xmin = rect.xmax = xy[0];
- rect.ymin = rect.ymax = xy[1];
-
- hits = view3d_opengl_select(
- &vc, buffer, MAXPICKBUF, &rect,
- VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP);
-
- *r_base = NULL;
-
- if (hits > 0) {
- uint bases_len = 0;
- Base **bases;
-
- if (vc.obedit != NULL) {
- bases = BKE_view_layer_array_from_bases_in_mode(
- vc.view_layer, vc.v3d, &bases_len, {
- .object_mode = OB_MODE_EDIT,
- });
- }
- else {
- 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);
-
- MEM_freeN(bases);
- return bone;
- }
- return NULL;
+ ViewContext vc;
+ rcti rect;
+ unsigned int buffer[MAXPICKBUF];
+ short hits;
+
+ ED_view3d_viewcontext_init(C, &vc);
+
+ // rect.xmin = ... mouseco!
+ rect.xmin = rect.xmax = xy[0];
+ rect.ymin = rect.ymax = xy[1];
+
+ hits = view3d_opengl_select(
+ &vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP);
+
+ *r_base = NULL;
+
+ if (hits > 0) {
+ uint bases_len = 0;
+ Base **bases;
+
+ if (vc.obedit != NULL) {
+ bases = BKE_view_layer_array_from_bases_in_mode(vc.view_layer,
+ vc.v3d,
+ &bases_len,
+ {
+ .object_mode = OB_MODE_EDIT,
+ });
+ }
+ else {
+ 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);
+
+ MEM_freeN(bases);
+ return bone;
+ }
+ return NULL;
}
/* **************** EditMode stuff ********************** */
static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bArmature *arm;
- EditBone *bone, *curBone, *next;
- const bool sel = !RNA_boolean_get(op->ptr, "deselect");
-
- view3d_operator_needs_opengl(C);
-
- Base *base = NULL;
- bone = get_nearest_bone(C, event->mval, true, &base);
-
- if (!bone)
- return OPERATOR_CANCELLED;
-
- arm = base->object->data;
-
- /* Select parents */
- for (curBone = bone; curBone; curBone = next) {
- if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
- if (sel) {
- curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else {
- curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- }
-
- if (curBone->flag & BONE_CONNECTED)
- next = curBone->parent;
- else
- next = NULL;
- }
-
- /* 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;
- }
- }
- }
- if (!curBone)
- bone = NULL;
- }
-
- ED_armature_edit_sync_selection(arm->edbo);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object);
-
- return OPERATOR_FINISHED;
+ bArmature *arm;
+ EditBone *bone, *curBone, *next;
+ const bool sel = !RNA_boolean_get(op->ptr, "deselect");
+
+ view3d_operator_needs_opengl(C);
+
+ Base *base = NULL;
+ bone = get_nearest_bone(C, event->mval, true, &base);
+
+ if (!bone)
+ return OPERATOR_CANCELLED;
+
+ arm = base->object->data;
+
+ /* Select parents */
+ for (curBone = bone; curBone; curBone = next) {
+ if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
+ if (sel) {
+ curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else {
+ curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
+
+ if (curBone->flag & BONE_CONNECTED)
+ next = curBone->parent;
+ else
+ next = NULL;
+ }
+
+ /* 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;
+ }
+ }
+ }
+ if (!curBone)
+ bone = NULL;
+ }
+
+ ED_armature_edit_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object);
+
+ return OPERATOR_FINISHED;
}
static bool armature_select_linked_poll(bContext *C)
{
- return (ED_operator_view3d_active(C) && ED_operator_editarmature(C));
+ return (ED_operator_view3d_active(C) && ED_operator_editarmature(C));
}
void ARMATURE_OT_select_linked(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";
+ /* identifiers */
+ ot->name = "Select Connected";
+ ot->idname = "ARMATURE_OT_select_linked";
+ ot->description = "Select bones related to selected ones by parent/child relationships";
- /* api callbacks */
- /* leave 'exec' unset */
- ot->invoke = armature_select_linked_invoke;
- ot->poll = armature_select_linked_poll;
+ /* api callbacks */
+ /* leave 'exec' unset */
+ ot->invoke = armature_select_linked_invoke;
+ ot->poll = armature_select_linked_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
}
/* utility function for get_nearest_editbonepoint */
static int selectbuffer_ret_hits_12(unsigned int *UNUSED(buffer), const int hits12)
{
- return hits12;
+ return hits12;
}
static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits12, const int hits5)
{
- const int offs = 4 * hits12;
- memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(unsigned int));
- return hits5;
+ const int offs = 4 * hits12;
+ memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(unsigned int));
+ return hits5;
}
/* does bones and points */
/* note that BONE ROOT only gets drawn for root bones (or without IK) */
static EditBone *get_nearest_editbonepoint(
- ViewContext *vc,
- bool findunsel, bool use_cycle,
- Base **r_base, int *r_selmask)
+ ViewContext *vc, bool findunsel, bool use_cycle, Base **r_base, int *r_selmask)
{
- uint buffer[MAXPICKBUF];
- struct {
- uint hitresult;
- Base *base;
- EditBone *ebone;
- } best = {
- .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;
- }
- }
-
- 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;
- }
- }
- copy_v2_v2_int(last_mval, vc->mval);
- }
- else {
- if (!XRAY_ACTIVE(vc->v3d)) {
- do_nearest = true;
- }
- }
-
- /* matching logic from 'mixed_bones_object_selectbuffer' */
- int hits = 0;
-
- /* we _must_ end cache before return, use 'goto cache_end' */
- view3d_opengl_select_cache_begin();
-
- {
- const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
- const eV3DSelectObjectFilter select_filter = VIEW3D_SELECT_FILTER_NOP;
-
- rcti rect;
- BLI_rcti_init_pt_radius(&rect, vc->mval, 12);
- const int hits12 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter);
- if (hits12 == 1) {
- hits = selectbuffer_ret_hits_12(buffer, hits12);
- goto cache_end;
- }
- else if (hits12 > 0) {
- int offs;
-
- offs = 4 * hits12;
- BLI_rcti_init_pt_radius(&rect, vc->mval, 5);
- const int hits5 = view3d_opengl_select(
- vc, buffer + offs, MAXPICKBUF - offs, &rect,
- select_mode, select_filter);
-
- if (hits5 == 1) {
- hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
- goto cache_end;
- }
-
- if (hits5 > 0) { hits = selectbuffer_ret_hits_5(buffer, hits12, hits5); goto cache_end; }
- else { hits = selectbuffer_ret_hits_12(buffer, hits12); goto cache_end; }
- }
- }
+ uint buffer[MAXPICKBUF];
+ struct {
+ uint hitresult;
+ Base *base;
+ EditBone *ebone;
+ } best = {
+ .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;
+ }
+ }
+
+ 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;
+ }
+ }
+ copy_v2_v2_int(last_mval, vc->mval);
+ }
+ else {
+ if (!XRAY_ACTIVE(vc->v3d)) {
+ do_nearest = true;
+ }
+ }
+
+ /* matching logic from 'mixed_bones_object_selectbuffer' */
+ int hits = 0;
+
+ /* we _must_ end cache before return, use 'goto cache_end' */
+ view3d_opengl_select_cache_begin();
+
+ {
+ const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
+ const eV3DSelectObjectFilter select_filter = VIEW3D_SELECT_FILTER_NOP;
+
+ rcti rect;
+ BLI_rcti_init_pt_radius(&rect, vc->mval, 12);
+ const int hits12 = view3d_opengl_select(
+ vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter);
+ if (hits12 == 1) {
+ hits = selectbuffer_ret_hits_12(buffer, hits12);
+ goto cache_end;
+ }
+ else if (hits12 > 0) {
+ int offs;
+
+ offs = 4 * hits12;
+ BLI_rcti_init_pt_radius(&rect, vc->mval, 5);
+ const int hits5 = view3d_opengl_select(
+ vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter);
+
+ if (hits5 == 1) {
+ hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
+ goto cache_end;
+ }
+
+ if (hits5 > 0) {
+ hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
+ goto cache_end;
+ }
+ else {
+ hits = selectbuffer_ret_hits_12(buffer, hits12);
+ goto cache_end;
+ }
+ }
+ }
cache_end:
- view3d_opengl_select_cache_end();
-
- uint bases_len;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc->view_layer, vc->v3d, &bases_len);
-
- /* See if there are any selected bones in this group */
- 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);
- }
- }
- else {
- int dep_min = 5;
- for (int i = 0; i < hits; i++) {
- const uint hitresult = buffer[3 + (i * 4)];
- if (!(hitresult & BONESEL_NOSEL)) {
- Base *base = NULL;
- EditBone *ebone;
- base = ED_armature_base_and_ebone_from_select_buffer(bases, bases_len, hitresult, &ebone);
- /* If this fails, selection code is setting the selection ID's incorrectly. */
- BLI_assert(base && ebone);
-
- 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;
- else
- dep = 2;
- }
- else {
- dep = 1;
- }
- }
- else {
- /* bone found */
- if (findunsel) {
- if ((ebone->flag & BONE_SELECTED) == 0)
- dep = 3;
- else
- dep = 4;
- }
- else {
- dep = 3;
- }
- }
-
- if (ebone == ebone_next_act) {
- dep -= 1;
- }
-
- if (dep < dep_min) {
- dep_min = dep;
- best.hitresult = hitresult;
- best.base = base;
- best.ebone = ebone;
- }
- }
- }
- }
-
- if (!(best.hitresult & BONESEL_NOSEL)) {
- *r_base = best.base;
-
- *r_selmask = 0;
- if (best.hitresult & BONESEL_ROOT) {
- *r_selmask |= BONE_ROOTSEL;
- }
- if (best.hitresult & BONESEL_TIP) {
- *r_selmask |= BONE_TIPSEL;
- }
- if (best.hitresult & BONESEL_BONE) {
- *r_selmask |= BONE_SELECTED;
- }
- MEM_freeN(bases);
- return best.ebone;
- }
- }
- *r_selmask = 0;
- *r_base = NULL;
- MEM_freeN(bases);
- return NULL;
+ view3d_opengl_select_cache_end();
+
+ uint bases_len;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
+ vc->view_layer, vc->v3d, &bases_len);
+
+ /* See if there are any selected bones in this group */
+ 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);
+ }
+ }
+ else {
+ int dep_min = 5;
+ for (int i = 0; i < hits; i++) {
+ const uint hitresult = buffer[3 + (i * 4)];
+ if (!(hitresult & BONESEL_NOSEL)) {
+ Base *base = NULL;
+ EditBone *ebone;
+ base = ED_armature_base_and_ebone_from_select_buffer(
+ bases, bases_len, hitresult, &ebone);
+ /* If this fails, selection code is setting the selection ID's incorrectly. */
+ BLI_assert(base && ebone);
+
+ 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;
+ else
+ dep = 2;
+ }
+ else {
+ dep = 1;
+ }
+ }
+ else {
+ /* bone found */
+ if (findunsel) {
+ if ((ebone->flag & BONE_SELECTED) == 0)
+ dep = 3;
+ else
+ dep = 4;
+ }
+ else {
+ dep = 3;
+ }
+ }
+
+ if (ebone == ebone_next_act) {
+ dep -= 1;
+ }
+
+ if (dep < dep_min) {
+ dep_min = dep;
+ best.hitresult = hitresult;
+ best.base = base;
+ best.ebone = ebone;
+ }
+ }
+ }
+ }
+
+ if (!(best.hitresult & BONESEL_NOSEL)) {
+ *r_base = best.base;
+
+ *r_selmask = 0;
+ if (best.hitresult & BONESEL_ROOT) {
+ *r_selmask |= BONE_ROOTSEL;
+ }
+ if (best.hitresult & BONESEL_TIP) {
+ *r_selmask |= BONE_TIPSEL;
+ }
+ if (best.hitresult & BONESEL_BONE) {
+ *r_selmask |= BONE_SELECTED;
+ }
+ MEM_freeN(bases);
+ return best.ebone;
+ }
+ }
+ *r_selmask = 0;
+ *r_base = NULL;
+ MEM_freeN(bases);
+ return NULL;
}
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) {
- if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
- ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- changed = true;
- }
- }
- return changed;
+ bArmature *arm = obedit->data;
+ bool changed = false;
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ changed = true;
+ }
+ }
+ return changed;
}
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) {
- /* first and foremost, bone must be visible and selected */
- if (EBONE_VISIBLE(arm, ebone)) {
- if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
- ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- changed = true;
- }
- }
- }
-
- if (changed) {
- ED_armature_edit_sync_selection(arm->edbo);
- }
- return changed;
+ bArmature *arm = obedit->data;
+ bool changed = false;
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ /* first and foremost, bone must be visible and selected */
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ ED_armature_edit_sync_selection(arm->edbo);
+ }
+ return changed;
}
-
bool ED_armature_edit_deselect_all_multi_ex(struct Base **bases, uint bases_len)
{
- bool changed_multi = false;
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Object *obedit = bases[base_index]->object;
- changed_multi |= ED_armature_edit_deselect_all(obedit);
- }
- return changed_multi;
+ bool changed_multi = false;
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Object *obedit = bases[base_index]->object;
+ changed_multi |= ED_armature_edit_deselect_all(obedit);
+ }
+ return changed_multi;
}
bool ED_armature_edit_deselect_all_visible_multi_ex(struct Base **bases, uint bases_len)
{
- bool changed_multi = false;
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Object *obedit = bases[base_index]->object;
- changed_multi |= ED_armature_edit_deselect_all_visible(obedit);
- }
- return changed_multi;
+ bool changed_multi = false;
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Object *obedit = bases[base_index]->object;
+ changed_multi |= ED_armature_edit_deselect_all_visible(obedit);
+ }
+ return changed_multi;
}
bool ED_armature_edit_deselect_all_visible_multi(bContext *C)
{
- ViewContext vc;
- ED_view3d_viewcontext_init(C, &vc);
- uint bases_len = 0;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &bases_len);
- bool changed_multi = ED_armature_edit_deselect_all_multi_ex(bases, bases_len);
- MEM_freeN(bases);
- return changed_multi;
+ ViewContext vc;
+ ED_view3d_viewcontext_init(C, &vc);
+ uint bases_len = 0;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
+ vc.view_layer, vc.v3d, &bases_len);
+ bool changed_multi = ED_armature_edit_deselect_all_multi_ex(bases, bases_len);
+ MEM_freeN(bases);
+ 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);
- }
+ 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);
+ }
}
/* context: editmode armature in view3d */
-bool ED_armature_edit_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
+bool ED_armature_edit_select_pick(
+ bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
{
- ViewContext vc;
- EditBone *nearBone = NULL;
- int selmask;
- Base *basact = NULL;
-
- ED_view3d_viewcontext_init(C, &vc);
- vc.mval[0] = mval[0];
- vc.mval[1] = mval[1];
-
- nearBone = get_nearest_editbonepoint(&vc, true, true, &basact, &selmask);
- if (nearBone) {
- ED_view3d_viewcontext_init_object(&vc, basact->object);
- bArmature *arm = vc.obedit->data;
-
- if (!EBONE_SELECTABLE(arm, nearBone)) {
- return false;
- }
-
- if (!extend && !deselect && !toggle) {
- uint bases_len = 0;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &bases_len);
- ED_armature_edit_deselect_all_multi_ex(bases, bases_len);
- MEM_freeN(bases);
- }
-
- /* by definition the non-root connected bones have no root point drawn,
- * so a root selection needs to be delivered to the parent tip */
-
- if (selmask & BONE_SELECTED) {
- if (nearBone->parent && (nearBone->flag & BONE_CONNECTED)) {
- /* click in a chain */
- if (extend) {
- /* select this bone */
- nearBone->flag |= BONE_TIPSEL;
- nearBone->parent->flag |= BONE_TIPSEL;
- }
- else if (deselect) {
- /* deselect this bone */
- nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
- /* only deselect parent tip if it is not selected */
- if (!(nearBone->parent->flag & BONE_SELECTED))
- nearBone->parent->flag &= ~BONE_TIPSEL;
- }
- else if (toggle) {
- /* hold shift inverts this bone's selection */
- if (nearBone->flag & BONE_SELECTED) {
- /* deselect this bone */
- nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
- /* only deselect parent tip if it is not selected */
- if (!(nearBone->parent->flag & BONE_SELECTED))
- nearBone->parent->flag &= ~BONE_TIPSEL;
- }
- else {
- /* select this bone */
- nearBone->flag |= BONE_TIPSEL;
- nearBone->parent->flag |= BONE_TIPSEL;
- }
- }
- else {
- /* select this bone */
- nearBone->flag |= BONE_TIPSEL;
- nearBone->parent->flag |= BONE_TIPSEL;
- }
- }
- else {
- if (extend) {
- nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
- }
- else if (deselect) {
- nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
- }
- else if (toggle) {
- /* hold shift inverts this bone's selection */
- if (nearBone->flag & BONE_SELECTED)
- nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
- else
- nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
- }
- else
- nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
- }
- }
- else {
- if (extend)
- nearBone->flag |= selmask;
- else if (deselect)
- nearBone->flag &= ~selmask;
- else if (toggle && (nearBone->flag & selmask))
- nearBone->flag &= ~selmask;
- else
- nearBone->flag |= selmask;
- }
-
- ED_armature_edit_sync_selection(arm->edbo);
-
- /* then now check for active status */
- if (ebone_select_flag(nearBone)) {
- arm->act_edbone = nearBone;
- }
-
- if (vc.view_layer->basact != basact) {
- ED_object_base_activate(C, basact);
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object);
- return true;
- }
-
- return false;
+ ViewContext vc;
+ EditBone *nearBone = NULL;
+ int selmask;
+ Base *basact = NULL;
+
+ ED_view3d_viewcontext_init(C, &vc);
+ vc.mval[0] = mval[0];
+ vc.mval[1] = mval[1];
+
+ nearBone = get_nearest_editbonepoint(&vc, true, true, &basact, &selmask);
+ if (nearBone) {
+ ED_view3d_viewcontext_init_object(&vc, basact->object);
+ bArmature *arm = vc.obedit->data;
+
+ if (!EBONE_SELECTABLE(arm, nearBone)) {
+ return false;
+ }
+
+ if (!extend && !deselect && !toggle) {
+ uint bases_len = 0;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
+ vc.view_layer, vc.v3d, &bases_len);
+ ED_armature_edit_deselect_all_multi_ex(bases, bases_len);
+ MEM_freeN(bases);
+ }
+
+ /* by definition the non-root connected bones have no root point drawn,
+ * so a root selection needs to be delivered to the parent tip */
+
+ if (selmask & BONE_SELECTED) {
+ if (nearBone->parent && (nearBone->flag & BONE_CONNECTED)) {
+ /* click in a chain */
+ if (extend) {
+ /* select this bone */
+ nearBone->flag |= BONE_TIPSEL;
+ nearBone->parent->flag |= BONE_TIPSEL;
+ }
+ else if (deselect) {
+ /* deselect this bone */
+ nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
+ /* only deselect parent tip if it is not selected */
+ if (!(nearBone->parent->flag & BONE_SELECTED))
+ nearBone->parent->flag &= ~BONE_TIPSEL;
+ }
+ else if (toggle) {
+ /* hold shift inverts this bone's selection */
+ if (nearBone->flag & BONE_SELECTED) {
+ /* deselect this bone */
+ nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
+ /* only deselect parent tip if it is not selected */
+ if (!(nearBone->parent->flag & BONE_SELECTED))
+ nearBone->parent->flag &= ~BONE_TIPSEL;
+ }
+ else {
+ /* select this bone */
+ nearBone->flag |= BONE_TIPSEL;
+ nearBone->parent->flag |= BONE_TIPSEL;
+ }
+ }
+ else {
+ /* select this bone */
+ nearBone->flag |= BONE_TIPSEL;
+ nearBone->parent->flag |= BONE_TIPSEL;
+ }
+ }
+ else {
+ if (extend) {
+ nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else if (deselect) {
+ nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else if (toggle) {
+ /* hold shift inverts this bone's selection */
+ if (nearBone->flag & BONE_SELECTED)
+ nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
+ else
+ nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else
+ nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
+ else {
+ if (extend)
+ nearBone->flag |= selmask;
+ else if (deselect)
+ nearBone->flag &= ~selmask;
+ else if (toggle && (nearBone->flag & selmask))
+ nearBone->flag &= ~selmask;
+ else
+ nearBone->flag |= selmask;
+ }
+
+ ED_armature_edit_sync_selection(arm->edbo);
+
+ /* then now check for active status */
+ if (ebone_select_flag(nearBone)) {
+ arm->act_edbone = nearBone;
+ }
+
+ if (vc.view_layer->basact != basact) {
+ ED_object_base_activate(C, basact);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object);
+ return true;
+ }
+
+ return false;
}
/* -------------------------------------------------------------------- */
@@ -757,69 +775,73 @@ bool ED_armature_edit_select_pick(bContext *C, const int mval[2], bool extend, b
* Implements #ED_armature_edit_select_op_from_tagged
* \{ */
-static bool armature_edit_select_op_apply(
- bArmature *arm, EditBone *ebone, const eSelectOp sel_op, int is_ignore_flag, int is_inside_flag)
+static bool armature_edit_select_op_apply(bArmature *arm,
+ EditBone *ebone,
+ const eSelectOp sel_op,
+ int is_ignore_flag,
+ int is_inside_flag)
{
- BLI_assert(!(is_ignore_flag & ~(BONESEL_ROOT | BONESEL_TIP)));
- BLI_assert(!(is_inside_flag & ~(BONESEL_ROOT | BONESEL_TIP | BONESEL_BONE)));
- BLI_assert(EBONE_VISIBLE(arm, ebone));
- bool changed = false;
- bool is_point_done = false;
- int points_proj_tot = 0;
- BLI_assert(ebone->flag == ebone->temp.i);
- const int ebone_flag_prev = ebone->flag;
-
- if ((is_ignore_flag & BONE_ROOTSEL) == 0) {
- points_proj_tot++;
- const bool is_select = ebone->flag & BONE_ROOTSEL;
- const bool is_inside = is_inside_flag & BONESEL_ROOT;
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
- SET_FLAG_FROM_TEST(ebone->flag, sel_op_result, BONE_ROOTSEL);
- }
- }
- is_point_done |= is_inside;
- }
-
- if ((is_ignore_flag & BONE_TIPSEL) == 0) {
- points_proj_tot++;
- const bool is_select = ebone->flag & BONE_TIPSEL;
- const bool is_inside = is_inside_flag & BONESEL_TIP;
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
- SET_FLAG_FROM_TEST(ebone->flag, sel_op_result, BONE_TIPSEL);
- }
- }
- is_point_done |= is_inside;
- }
-
- /* if one of points selected, we skip the bone itself */
- if ((is_point_done == false) && (points_proj_tot == 2)) {
- const bool is_select = ebone->flag & BONE_SELECTED;
- {
- const bool is_inside = is_inside_flag & BONESEL_BONE;
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
- SET_FLAG_FROM_TEST(ebone->flag, sel_op_result, BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
- }
- }
- }
-
- changed = true;
- }
- changed |= is_point_done;
-
- if (ebone_flag_prev != ebone->flag) {
- ebone->temp.i = ebone->flag;
- ebone->flag = ebone_flag_prev;
- ebone->flag = ebone_flag_prev | BONE_DONE;
- changed = true;
- }
-
- return changed;
+ BLI_assert(!(is_ignore_flag & ~(BONESEL_ROOT | BONESEL_TIP)));
+ BLI_assert(!(is_inside_flag & ~(BONESEL_ROOT | BONESEL_TIP | BONESEL_BONE)));
+ BLI_assert(EBONE_VISIBLE(arm, ebone));
+ bool changed = false;
+ bool is_point_done = false;
+ int points_proj_tot = 0;
+ BLI_assert(ebone->flag == ebone->temp.i);
+ const int ebone_flag_prev = ebone->flag;
+
+ if ((is_ignore_flag & BONE_ROOTSEL) == 0) {
+ points_proj_tot++;
+ const bool is_select = ebone->flag & BONE_ROOTSEL;
+ const bool is_inside = is_inside_flag & BONESEL_ROOT;
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
+ SET_FLAG_FROM_TEST(ebone->flag, sel_op_result, BONE_ROOTSEL);
+ }
+ }
+ is_point_done |= is_inside;
+ }
+
+ if ((is_ignore_flag & BONE_TIPSEL) == 0) {
+ points_proj_tot++;
+ const bool is_select = ebone->flag & BONE_TIPSEL;
+ const bool is_inside = is_inside_flag & BONESEL_TIP;
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
+ SET_FLAG_FROM_TEST(ebone->flag, sel_op_result, BONE_TIPSEL);
+ }
+ }
+ is_point_done |= is_inside;
+ }
+
+ /* if one of points selected, we skip the bone itself */
+ if ((is_point_done == false) && (points_proj_tot == 2)) {
+ const bool is_select = ebone->flag & BONE_SELECTED;
+ {
+ const bool is_inside = is_inside_flag & BONESEL_BONE;
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
+ SET_FLAG_FROM_TEST(
+ ebone->flag, sel_op_result, BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
+ }
+ }
+ }
+
+ changed = true;
+ }
+ changed |= is_point_done;
+
+ if (ebone_flag_prev != ebone->flag) {
+ ebone->temp.i = ebone->flag;
+ ebone->flag = ebone_flag_prev;
+ ebone->flag = ebone_flag_prev | BONE_DONE;
+ changed = true;
+ }
+
+ return changed;
}
/**
@@ -836,101 +858,97 @@ static bool armature_edit_select_op_apply(
*/
bool ED_armature_edit_select_op_from_tagged(bArmature *arm, const int sel_op)
{
- bool changed = false;
-
- /* Initialize flags. */
- {
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
-
- /* Flush the parent flag to this bone
- * so we don't need to check the parent when adjusting the selection. */
- if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
- if (ebone->parent->flag & BONE_TIPSEL) {
- ebone->flag |= BONE_ROOTSEL;
- }
- else {
- ebone->flag &= ~BONE_ROOTSEL;
- }
-
- /* Flush the 'temp.i' flag. */
- if (ebone->parent->temp.i & BONESEL_TIP) {
- ebone->temp.i |= BONESEL_ROOT;
- }
- }
- ebone->flag &= ~BONE_DONE;
- }
- }
-
- /* Apply selection from bone selection flags. */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- 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));
-
- /* Use as previous bone flag from now on. */
- ebone->temp.i = ebone->flag;
-
- /* When there is a partial selection without both endpoints, only select an endpoint. */
- if ((is_inside_flag & BONESEL_BONE) &&
- (is_inside_flag & (BONESEL_ROOT | BONESEL_TIP)) &&
- ((is_inside_flag & (BONESEL_ROOT | BONESEL_TIP)) != (BONESEL_ROOT | BONESEL_TIP)))
- {
- is_inside_flag &= ~BONESEL_BONE;
- }
-
- changed |= armature_edit_select_op_apply(arm, ebone, sel_op, is_ignore_flag, is_inside_flag);
- }
- }
-
- if (changed) {
- /* Cleanup flags. */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (ebone->flag & BONE_DONE) {
- SWAP(int, ebone->temp.i, ebone->flag);
- ebone->flag |= BONE_DONE;
- if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
- if ((ebone->parent->flag & BONE_DONE) == 0) {
- /* Checked below. */
- ebone->parent->temp.i = ebone->parent->flag;
- }
- }
- }
- }
-
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (ebone->flag & BONE_DONE) {
- if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
- bool is_parent_tip_changed = (ebone->parent->flag & BONE_TIPSEL) != (ebone->parent->temp.i & BONE_TIPSEL);
- if ((ebone->temp.i & BONE_ROOTSEL) == 0) {
- if ((ebone->flag & BONE_ROOTSEL) != 0) {
- ebone->parent->flag |= BONE_TIPSEL;
- }
- }
- else {
- if ((ebone->flag & BONE_ROOTSEL) == 0) {
- ebone->parent->flag &= ~BONE_TIPSEL;
-
- }
- }
-
-
- if (is_parent_tip_changed == false) {
- /* Keep tip selected if the parent remains selected. */
- if (ebone->parent->flag & BONE_SELECTED) {
- ebone->parent->flag |= BONE_TIPSEL;
- }
- }
-
- }
- ebone->flag &= ~BONE_DONE;
- }
- }
-
- ED_armature_edit_sync_selection(arm->edbo);
- ED_armature_edit_validate_active(arm);
- }
-
- return changed;
+ bool changed = false;
+
+ /* Initialize flags. */
+ {
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+
+ /* Flush the parent flag to this bone
+ * so we don't need to check the parent when adjusting the selection. */
+ if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
+ if (ebone->parent->flag & BONE_TIPSEL) {
+ ebone->flag |= BONE_ROOTSEL;
+ }
+ else {
+ ebone->flag &= ~BONE_ROOTSEL;
+ }
+
+ /* Flush the 'temp.i' flag. */
+ if (ebone->parent->temp.i & BONESEL_TIP) {
+ ebone->temp.i |= BONESEL_ROOT;
+ }
+ }
+ ebone->flag &= ~BONE_DONE;
+ }
+ }
+
+ /* Apply selection from bone selection flags. */
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ 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));
+
+ /* Use as previous bone flag from now on. */
+ ebone->temp.i = ebone->flag;
+
+ /* When there is a partial selection without both endpoints, only select an endpoint. */
+ if ((is_inside_flag & BONESEL_BONE) && (is_inside_flag & (BONESEL_ROOT | BONESEL_TIP)) &&
+ ((is_inside_flag & (BONESEL_ROOT | BONESEL_TIP)) != (BONESEL_ROOT | BONESEL_TIP))) {
+ is_inside_flag &= ~BONESEL_BONE;
+ }
+
+ changed |= armature_edit_select_op_apply(arm, ebone, sel_op, is_ignore_flag, is_inside_flag);
+ }
+ }
+
+ if (changed) {
+ /* Cleanup flags. */
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ebone->flag & BONE_DONE) {
+ SWAP(int, ebone->temp.i, ebone->flag);
+ ebone->flag |= BONE_DONE;
+ if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
+ if ((ebone->parent->flag & BONE_DONE) == 0) {
+ /* Checked below. */
+ ebone->parent->temp.i = ebone->parent->flag;
+ }
+ }
+ }
+ }
+
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ebone->flag & BONE_DONE) {
+ if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
+ bool is_parent_tip_changed = (ebone->parent->flag & BONE_TIPSEL) !=
+ (ebone->parent->temp.i & BONE_TIPSEL);
+ if ((ebone->temp.i & BONE_ROOTSEL) == 0) {
+ if ((ebone->flag & BONE_ROOTSEL) != 0) {
+ ebone->parent->flag |= BONE_TIPSEL;
+ }
+ }
+ else {
+ if ((ebone->flag & BONE_ROOTSEL) == 0) {
+ ebone->parent->flag &= ~BONE_TIPSEL;
+ }
+ }
+
+ if (is_parent_tip_changed == false) {
+ /* Keep tip selected if the parent remains selected. */
+ if (ebone->parent->flag & BONE_SELECTED) {
+ ebone->parent->flag |= BONE_TIPSEL;
+ }
+ }
+ }
+ ebone->flag &= ~BONE_DONE;
+ }
+ }
+
+ ED_armature_edit_sync_selection(arm->edbo);
+ ED_armature_edit_validate_active(arm);
+ }
+
+ return changed;
}
/** \} */
@@ -939,613 +957,612 @@ bool ED_armature_edit_select_op_from_tagged(bArmature *arm, const int sel_op)
static int armature_de_select_all_exec(bContext *C, wmOperator *op)
{
- int action = RNA_enum_get(op->ptr, "action");
-
- if (action == SEL_TOGGLE) {
- /* Determine if there are any selected bones
- * And therefore whether we are selecting or deselecting */
- action = SEL_SELECT;
- CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
- {
- if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
- action = SEL_DESELECT;
- break;
- }
- }
- CTX_DATA_END;
- }
-
- /* Set the flags */
- CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
- {
- /* ignore bone if selection can't change */
- switch (action) {
- case SEL_SELECT:
- if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
- ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- if (ebone->parent) {
- ebone->parent->flag |= (BONE_TIPSEL);
- }
- }
- break;
- case SEL_DESELECT:
- ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- break;
- case SEL_INVERT:
- if (ebone->flag & BONE_SELECTED) {
- ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else {
- if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
- ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- if (ebone->parent) {
- ebone->parent->flag |= (BONE_TIPSEL);
- }
- }
- }
- break;
- }
- }
- CTX_DATA_END;
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
-
- return OPERATOR_FINISHED;
+ int action = RNA_enum_get(op->ptr, "action");
+
+ if (action == SEL_TOGGLE) {
+ /* Determine if there are any selected bones
+ * And therefore whether we are selecting or deselecting */
+ action = SEL_SELECT;
+ CTX_DATA_BEGIN (C, EditBone *, ebone, visible_bones) {
+ if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
+ action = SEL_DESELECT;
+ break;
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ /* Set the flags */
+ CTX_DATA_BEGIN (C, EditBone *, ebone, visible_bones) {
+ /* ignore bone if selection can't change */
+ switch (action) {
+ case SEL_SELECT:
+ if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
+ ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ if (ebone->parent) {
+ ebone->parent->flag |= (BONE_TIPSEL);
+ }
+ }
+ break;
+ case SEL_DESELECT:
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ break;
+ case SEL_INVERT:
+ if (ebone->flag & BONE_SELECTED) {
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else {
+ if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
+ ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ if (ebone->parent) {
+ ebone->parent->flag |= (BONE_TIPSEL);
+ }
+ }
+ }
+ break;
+ }
+ }
+ CTX_DATA_END;
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
+
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All";
- ot->idname = "ARMATURE_OT_select_all";
- ot->description = "Toggle selection status of all bones";
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->idname = "ARMATURE_OT_select_all";
+ ot->description = "Toggle selection status of all bones";
- /* api callbacks */
- ot->exec = armature_de_select_all_exec;
- ot->poll = ED_operator_editarmature;
+ /* api callbacks */
+ ot->exec = armature_de_select_all_exec;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_select_all(ot);
+ WM_operator_properties_select_all(ot);
}
/**************** Select more/less **************/
static void armature_select_more(bArmature *arm, EditBone *ebone)
{
- if ((EBONE_PREV_FLAG_GET(ebone) & (BONE_ROOTSEL | BONE_TIPSEL)) != 0) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- ED_armature_ebone_select_set(ebone, true);
- }
- }
-
- if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
- /* to parent */
- if ((EBONE_PREV_FLAG_GET(ebone) & BONE_ROOTSEL) != 0) {
- if (EBONE_SELECTABLE(arm, ebone->parent)) {
- ED_armature_ebone_selectflag_enable(ebone->parent, (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL));
- }
- }
-
- /* from parent (difference from select less) */
- if ((EBONE_PREV_FLAG_GET(ebone->parent) & BONE_TIPSEL) != 0) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- ED_armature_ebone_selectflag_enable(ebone, (BONE_SELECTED | BONE_ROOTSEL));
- }
- }
- }
+ if ((EBONE_PREV_FLAG_GET(ebone) & (BONE_ROOTSEL | BONE_TIPSEL)) != 0) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ ED_armature_ebone_select_set(ebone, true);
+ }
+ }
+
+ if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+ /* to parent */
+ if ((EBONE_PREV_FLAG_GET(ebone) & BONE_ROOTSEL) != 0) {
+ if (EBONE_SELECTABLE(arm, ebone->parent)) {
+ ED_armature_ebone_selectflag_enable(ebone->parent,
+ (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL));
+ }
+ }
+
+ /* from parent (difference from select less) */
+ if ((EBONE_PREV_FLAG_GET(ebone->parent) & BONE_TIPSEL) != 0) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ ED_armature_ebone_selectflag_enable(ebone, (BONE_SELECTED | BONE_ROOTSEL));
+ }
+ }
+ }
}
static void armature_select_less(bArmature *UNUSED(arm), EditBone *ebone)
{
- if ((EBONE_PREV_FLAG_GET(ebone) & (BONE_ROOTSEL | BONE_TIPSEL)) != (BONE_ROOTSEL | BONE_TIPSEL)) {
- ED_armature_ebone_select_set(ebone, false);
- }
-
- if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
- /* to parent */
- if ((EBONE_PREV_FLAG_GET(ebone) & BONE_SELECTED) == 0) {
- ED_armature_ebone_selectflag_disable(ebone->parent, (BONE_SELECTED | BONE_TIPSEL));
- }
-
- /* from parent (difference from select more) */
- if ((EBONE_PREV_FLAG_GET(ebone->parent) & BONE_SELECTED) == 0) {
- ED_armature_ebone_selectflag_disable(ebone, (BONE_SELECTED | BONE_ROOTSEL));
- }
- }
+ if ((EBONE_PREV_FLAG_GET(ebone) & (BONE_ROOTSEL | BONE_TIPSEL)) !=
+ (BONE_ROOTSEL | BONE_TIPSEL)) {
+ ED_armature_ebone_select_set(ebone, false);
+ }
+
+ if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+ /* to parent */
+ if ((EBONE_PREV_FLAG_GET(ebone) & BONE_SELECTED) == 0) {
+ ED_armature_ebone_selectflag_disable(ebone->parent, (BONE_SELECTED | BONE_TIPSEL));
+ }
+
+ /* from parent (difference from select more) */
+ if ((EBONE_PREV_FLAG_GET(ebone->parent) & BONE_SELECTED) == 0) {
+ ED_armature_ebone_selectflag_disable(ebone, (BONE_SELECTED | BONE_ROOTSEL));
+ }
+ }
}
static void armature_select_more_less(Object *ob, bool more)
{
- bArmature *arm = (bArmature *)ob->data;
- EditBone *ebone;
-
- /* XXX, eventually we shouldn't need this - campbell */
- ED_armature_edit_sync_selection(arm->edbo);
-
- /* count bones & store selection state */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- EBONE_PREV_FLAG_SET(ebone, ED_armature_ebone_selectflag_get(ebone));
- }
-
- /* do selection */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone)) {
- if (more) {
- armature_select_more(arm, ebone);
- }
- else {
- armature_select_less(arm, ebone);
- }
- }
- }
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone)) {
- if (more == false) {
- if (ebone->flag & BONE_SELECTED) {
- ED_armature_ebone_select_set(ebone, true);
- }
- }
- }
- ebone->temp.p = NULL;
- }
-
- ED_armature_edit_sync_selection(arm->edbo);
+ bArmature *arm = (bArmature *)ob->data;
+ EditBone *ebone;
+
+ /* XXX, eventually we shouldn't need this - campbell */
+ ED_armature_edit_sync_selection(arm->edbo);
+
+ /* count bones & store selection state */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ EBONE_PREV_FLAG_SET(ebone, ED_armature_ebone_selectflag_get(ebone));
+ }
+
+ /* do selection */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (more) {
+ armature_select_more(arm, ebone);
+ }
+ else {
+ armature_select_less(arm, ebone);
+ }
+ }
+ }
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (more == false) {
+ if (ebone->flag & BONE_SELECTED) {
+ ED_armature_ebone_select_set(ebone, true);
+ }
+ }
+ }
+ ebone->temp.p = NULL;
+ }
+
+ ED_armature_edit_sync_selection(arm->edbo);
}
static int armature_de_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
- 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];
- armature_select_more_less(ob, true);
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ 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];
+ armature_select_more_less(ob, true);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_select_more(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select More";
- ot->idname = "ARMATURE_OT_select_more";
- ot->description = "Select those bones connected to the initial selection";
+ /* identifiers */
+ ot->name = "Select More";
+ ot->idname = "ARMATURE_OT_select_more";
+ ot->description = "Select those bones connected to the initial selection";
- /* api callbacks */
- ot->exec = armature_de_select_more_exec;
- ot->poll = ED_operator_editarmature;
+ /* api callbacks */
+ ot->exec = armature_de_select_more_exec;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int armature_de_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
- 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];
- armature_select_more_less(ob, false);
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ 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];
+ armature_select_more_less(ob, false);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_select_less(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Less";
- ot->idname = "ARMATURE_OT_select_less";
- ot->description = "Deselect those bones at the boundary of each selection region";
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->idname = "ARMATURE_OT_select_less";
+ ot->description = "Deselect those bones at the boundary of each selection region";
- /* api callbacks */
- ot->exec = armature_de_select_less_exec;
- ot->poll = ED_operator_editarmature;
+ /* api callbacks */
+ ot->exec = armature_de_select_less_exec;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
enum {
- SIMEDBONE_CHILDREN = 1,
- SIMEDBONE_CHILDREN_IMMEDIATE,
- SIMEDBONE_SIBLINGS,
- SIMEDBONE_LENGTH,
- SIMEDBONE_DIRECTION,
- SIMEDBONE_PREFIX,
- SIMEDBONE_SUFFIX,
- SIMEDBONE_LAYER,
- SIMEDBONE_GROUP,
- SIMEDBONE_SHAPE,
+ SIMEDBONE_CHILDREN = 1,
+ SIMEDBONE_CHILDREN_IMMEDIATE,
+ SIMEDBONE_SIBLINGS,
+ SIMEDBONE_LENGTH,
+ SIMEDBONE_DIRECTION,
+ SIMEDBONE_PREFIX,
+ SIMEDBONE_SUFFIX,
+ SIMEDBONE_LAYER,
+ SIMEDBONE_GROUP,
+ SIMEDBONE_SHAPE,
};
static const EnumPropertyItem prop_similar_types[] = {
- {SIMEDBONE_CHILDREN, "CHILDREN", 0, "Children", ""},
- {SIMEDBONE_CHILDREN_IMMEDIATE, "CHILDREN_IMMEDIATE", 0, "Immediate children", ""},
- {SIMEDBONE_SIBLINGS, "SIBLINGS", 0, "Siblings", ""},
- {SIMEDBONE_LENGTH, "LENGTH", 0, "Length", ""},
- {SIMEDBONE_DIRECTION, "DIRECTION", 0, "Direction (Y axis)", ""},
- {SIMEDBONE_PREFIX, "PREFIX", 0, "Prefix", ""},
- {SIMEDBONE_SUFFIX, "SUFFIX", 0, "Suffix", ""},
- {SIMEDBONE_LAYER, "LAYER", 0, "Layer", ""},
- {SIMEDBONE_GROUP, "GROUP", 0, "Group", ""},
- {SIMEDBONE_SHAPE, "SHAPE", 0, "Shape", ""},
- {0, NULL, 0, NULL, NULL},
+ {SIMEDBONE_CHILDREN, "CHILDREN", 0, "Children", ""},
+ {SIMEDBONE_CHILDREN_IMMEDIATE, "CHILDREN_IMMEDIATE", 0, "Immediate children", ""},
+ {SIMEDBONE_SIBLINGS, "SIBLINGS", 0, "Siblings", ""},
+ {SIMEDBONE_LENGTH, "LENGTH", 0, "Length", ""},
+ {SIMEDBONE_DIRECTION, "DIRECTION", 0, "Direction (Y axis)", ""},
+ {SIMEDBONE_PREFIX, "PREFIX", 0, "Prefix", ""},
+ {SIMEDBONE_SUFFIX, "SUFFIX", 0, "Suffix", ""},
+ {SIMEDBONE_LAYER, "LAYER", 0, "Layer", ""},
+ {SIMEDBONE_GROUP, "GROUP", 0, "Group", ""},
+ {SIMEDBONE_SHAPE, "SHAPE", 0, "Shape", ""},
+ {0, NULL, 0, NULL, NULL},
};
static float bone_length_squared_worldspace_get(Object *ob, EditBone *ebone)
{
- float v1[3], v2[3];
- mul_v3_mat3_m4v3(v1, ob->obmat, ebone->head);
- mul_v3_mat3_m4v3(v2, ob->obmat, ebone->tail);
- return len_squared_v3v3(v1, v2);
+ float v1[3], v2[3];
+ mul_v3_mat3_m4v3(v1, ob->obmat, ebone->head);
+ mul_v3_mat3_m4v3(v2, ob->obmat, ebone->tail);
+ return len_squared_v3v3(v1, v2);
}
static void select_similar_length(bContext *C, const float thresh)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob_act = CTX_data_edit_object(C);
- EditBone *ebone_act = CTX_data_active_bone(C);
-
- /* Thresh is always relative to current length. */
- const float len = bone_length_squared_worldspace_get(ob_act, ebone_act);
- const float len_min = len / (1.0f + (thresh - FLT_EPSILON));
- const float len_max = len * (1.0f + (thresh + FLT_EPSILON));
-
- 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 changed = false;
-
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- 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))
- {
- ED_armature_ebone_select_set(ebone, true);
- changed = true;
- }
- }
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- }
- MEM_freeN(objects);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob_act = CTX_data_edit_object(C);
+ EditBone *ebone_act = CTX_data_active_bone(C);
+
+ /* Thresh is always relative to current length. */
+ const float len = bone_length_squared_worldspace_get(ob_act, ebone_act);
+ const float len_min = len / (1.0f + (thresh - FLT_EPSILON));
+ const float len_max = len * (1.0f + (thresh + FLT_EPSILON));
+
+ 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 changed = false;
+
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ 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)) {
+ ED_armature_ebone_select_set(ebone, true);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ }
+ MEM_freeN(objects);
}
static void bone_direction_worldspace_get(Object *ob, EditBone *ebone, float *r_dir)
{
- float v1[3], v2[3];
- copy_v3_v3(v1, ebone->head);
- copy_v3_v3(v2, ebone->tail);
+ float v1[3], v2[3];
+ copy_v3_v3(v1, ebone->head);
+ copy_v3_v3(v2, ebone->tail);
- mul_m4_v3(ob->obmat, v1);
- mul_m4_v3(ob->obmat, v2);
+ mul_m4_v3(ob->obmat, v1);
+ mul_m4_v3(ob->obmat, v2);
- sub_v3_v3v3(r_dir, v1, v2);
- normalize_v3(r_dir);
+ sub_v3_v3v3(r_dir, v1, v2);
+ normalize_v3(r_dir);
}
static void select_similar_direction(bContext *C, const float thresh)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob_act = CTX_data_edit_object(C);
- EditBone *ebone_act = CTX_data_active_bone(C);
-
- float dir_act[3];
- bone_direction_worldspace_get(ob_act, ebone_act, dir_act);
-
- 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 changed = false;
-
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- float dir[3];
- bone_direction_worldspace_get(ob, ebone, dir);
-
- if (angle_v3v3(dir_act, dir) / (float)M_PI < (thresh + FLT_EPSILON)) {
- ED_armature_ebone_select_set(ebone, true);
- changed = true;
- }
- }
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- }
- MEM_freeN(objects);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob_act = CTX_data_edit_object(C);
+ EditBone *ebone_act = CTX_data_active_bone(C);
+
+ float dir_act[3];
+ bone_direction_worldspace_get(ob_act, ebone_act, dir_act);
+
+ 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 changed = false;
+
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ float dir[3];
+ bone_direction_worldspace_get(ob, ebone, dir);
+
+ if (angle_v3v3(dir_act, dir) / (float)M_PI < (thresh + FLT_EPSILON)) {
+ ED_armature_ebone_select_set(ebone, true);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ }
+ MEM_freeN(objects);
}
static void select_similar_layer(bContext *C)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- EditBone *ebone_act = CTX_data_active_bone(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 changed = false;
-
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- if (ebone->layer & ebone_act->layer) {
- ED_armature_ebone_select_set(ebone, true);
- changed = true;
- }
- }
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- }
- MEM_freeN(objects);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ EditBone *ebone_act = CTX_data_active_bone(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 changed = false;
+
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ if (ebone->layer & ebone_act->layer) {
+ ED_armature_ebone_select_set(ebone, true);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ }
+ MEM_freeN(objects);
}
static void select_similar_prefix(bContext *C)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- EditBone *ebone_act = CTX_data_active_bone(C);
-
- char body_tmp[MAXBONENAME];
- char prefix_act[MAXBONENAME];
-
- BLI_string_split_prefix(ebone_act->name, prefix_act, body_tmp, sizeof(ebone_act->name));
-
- if (prefix_act[0] == '\0') {
- return;
- }
-
- 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 changed = false;
-
- /* Find matches */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- char prefix_other[MAXBONENAME];
- BLI_string_split_prefix(ebone->name, prefix_other, body_tmp, sizeof(ebone->name));
- if (STREQ(prefix_act, prefix_other)) {
- ED_armature_ebone_select_set(ebone, true);
- changed = true;
- }
- }
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- }
- MEM_freeN(objects);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ EditBone *ebone_act = CTX_data_active_bone(C);
+
+ char body_tmp[MAXBONENAME];
+ char prefix_act[MAXBONENAME];
+
+ BLI_string_split_prefix(ebone_act->name, prefix_act, body_tmp, sizeof(ebone_act->name));
+
+ if (prefix_act[0] == '\0') {
+ return;
+ }
+
+ 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 changed = false;
+
+ /* Find matches */
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ char prefix_other[MAXBONENAME];
+ BLI_string_split_prefix(ebone->name, prefix_other, body_tmp, sizeof(ebone->name));
+ if (STREQ(prefix_act, prefix_other)) {
+ ED_armature_ebone_select_set(ebone, true);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ }
+ MEM_freeN(objects);
}
static void select_similar_suffix(bContext *C)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- EditBone *ebone_act = CTX_data_active_bone(C);
-
- char body_tmp[MAXBONENAME];
- char suffix_act[MAXBONENAME];
-
- BLI_string_split_suffix(ebone_act->name, body_tmp, suffix_act, sizeof(ebone_act->name));
-
- if (suffix_act[0] == '\0')
- return;
-
- 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 changed = false;
-
- /* Find matches */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- char suffix_other[MAXBONENAME];
- BLI_string_split_suffix(ebone->name, body_tmp, suffix_other, sizeof(ebone->name));
- if (STREQ(suffix_act, suffix_other)) {
- ED_armature_ebone_select_set(ebone, true);
- changed = true;
- }
- }
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- }
- MEM_freeN(objects);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ EditBone *ebone_act = CTX_data_active_bone(C);
+
+ char body_tmp[MAXBONENAME];
+ char suffix_act[MAXBONENAME];
+
+ BLI_string_split_suffix(ebone_act->name, body_tmp, suffix_act, sizeof(ebone_act->name));
+
+ if (suffix_act[0] == '\0')
+ return;
+
+ 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 changed = false;
+
+ /* Find matches */
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ char suffix_other[MAXBONENAME];
+ BLI_string_split_suffix(ebone->name, body_tmp, suffix_other, sizeof(ebone->name));
+ if (STREQ(suffix_act, suffix_other)) {
+ ED_armature_ebone_select_set(ebone, true);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ }
+ MEM_freeN(objects);
}
/** Use for matching any pose channel data. */
-static void select_similar_data_pchan(
- bContext *C,
- const size_t bytes_size, const int offset)
+static void select_similar_data_pchan(bContext *C, const size_t bytes_size, const int offset)
{
- Object *obedit = CTX_data_edit_object(C);
- bArmature *arm = obedit->data;
- EditBone *ebone_act = CTX_data_active_bone(C);
-
- const bPoseChannel *pchan_active = BKE_pose_channel_find_name(obedit->pose, ebone_act->name);
- const char *data_active = (const char *)POINTER_OFFSET(pchan_active, offset);
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- const bPoseChannel *pchan = BKE_pose_channel_find_name(obedit->pose, ebone->name);
- if (pchan) {
- const char *data_test = (const char *)POINTER_OFFSET(pchan, offset);
- if (memcmp(data_active, data_test, bytes_size) == 0) {
- ED_armature_ebone_select_set(ebone, true);
- }
- }
- }
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm = obedit->data;
+ EditBone *ebone_act = CTX_data_active_bone(C);
+
+ const bPoseChannel *pchan_active = BKE_pose_channel_find_name(obedit->pose, ebone_act->name);
+ const char *data_active = (const char *)POINTER_OFFSET(pchan_active, offset);
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ const bPoseChannel *pchan = BKE_pose_channel_find_name(obedit->pose, ebone->name);
+ if (pchan) {
+ const char *data_test = (const char *)POINTER_OFFSET(pchan, offset);
+ if (memcmp(data_active, data_test, bytes_size) == 0) {
+ ED_armature_ebone_select_set(ebone, true);
+ }
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
}
static void is_ancestor(EditBone *bone, EditBone *ancestor)
{
- if (bone->temp.ebone == ancestor || bone->temp.ebone == NULL)
- return;
+ if (bone->temp.ebone == ancestor || bone->temp.ebone == NULL)
+ return;
- if (bone->temp.ebone->temp.ebone != NULL && bone->temp.ebone->temp.ebone != ancestor)
- is_ancestor(bone->temp.ebone, ancestor);
+ if (bone->temp.ebone->temp.ebone != NULL && bone->temp.ebone->temp.ebone != ancestor)
+ is_ancestor(bone->temp.ebone, ancestor);
- bone->temp.ebone = bone->temp.ebone->temp.ebone;
+ bone->temp.ebone = bone->temp.ebone->temp.ebone;
}
static void select_similar_children(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- bArmature *arm = obedit->data;
- EditBone *ebone_act = CTX_data_active_bone(C);
+ Object *obedit = CTX_data_edit_object(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) {
- ebone_iter->temp.ebone = ebone_iter->parent;
- }
+ for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ ebone_iter->temp.ebone = ebone_iter->parent;
+ }
- for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
- is_ancestor(ebone_iter, ebone_act);
+ for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ is_ancestor(ebone_iter, ebone_act);
- if (ebone_iter->temp.ebone == ebone_act && EBONE_SELECTABLE(arm, ebone_iter))
- ED_armature_ebone_select_set(ebone_iter, true);
- }
+ if (ebone_iter->temp.ebone == ebone_act && EBONE_SELECTABLE(arm, ebone_iter))
+ ED_armature_ebone_select_set(ebone_iter, true);
+ }
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
}
static void select_similar_children_immediate(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- bArmature *arm = obedit->data;
- EditBone *ebone_act = CTX_data_active_bone(C);
+ Object *obedit = CTX_data_edit_object(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) {
- if (ebone_iter->parent == ebone_act && EBONE_SELECTABLE(arm, ebone_iter)) {
- ED_armature_ebone_select_set(ebone_iter, true);
- }
- }
+ for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ if (ebone_iter->parent == ebone_act && EBONE_SELECTABLE(arm, ebone_iter)) {
+ ED_armature_ebone_select_set(ebone_iter, true);
+ }
+ }
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
}
static void select_similar_siblings(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- bArmature *arm = obedit->data;
- EditBone *ebone_act = CTX_data_active_bone(C);
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm = obedit->data;
+ EditBone *ebone_act = CTX_data_active_bone(C);
- if (ebone_act->parent == NULL) {
- return;
- }
+ if (ebone_act->parent == NULL) {
+ return;
+ }
- for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
- if (ebone_iter->parent == ebone_act->parent && EBONE_SELECTABLE(arm, ebone_iter)) {
- ED_armature_ebone_select_set(ebone_iter, true);
- }
- }
+ for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ if (ebone_iter->parent == ebone_act->parent && EBONE_SELECTABLE(arm, ebone_iter)) {
+ ED_armature_ebone_select_set(ebone_iter, true);
+ }
+ }
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
}
static int armature_select_similar_exec(bContext *C, wmOperator *op)
{
- /* Get props */
- int type = RNA_enum_get(op->ptr, "type");
- float thresh = RNA_float_get(op->ptr, "threshold");
+ /* Get props */
+ int type = RNA_enum_get(op->ptr, "type");
+ float thresh = RNA_float_get(op->ptr, "threshold");
- /* Check for active bone */
- if (CTX_data_active_bone(C) == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
- return OPERATOR_CANCELLED;
- }
+ /* Check for active bone */
+ if (CTX_data_active_bone(C) == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
+ return OPERATOR_CANCELLED;
+ }
#define STRUCT_SIZE_AND_OFFSET(_struct, _member) \
- sizeof(((_struct *)NULL)->_member), offsetof(_struct, _member)
-
- switch (type) {
- case SIMEDBONE_CHILDREN:
- select_similar_children(C);
- break;
- case SIMEDBONE_CHILDREN_IMMEDIATE:
- select_similar_children_immediate(C);
- break;
- case SIMEDBONE_SIBLINGS:
- select_similar_siblings(C);
- break;
- case SIMEDBONE_LENGTH:
- select_similar_length(C, thresh);
- break;
- case SIMEDBONE_DIRECTION:
- select_similar_direction(C, thresh);
- break;
- case SIMEDBONE_PREFIX:
- select_similar_prefix(C);
- break;
- case SIMEDBONE_SUFFIX:
- select_similar_suffix(C);
- break;
- case SIMEDBONE_LAYER:
- select_similar_layer(C);
- break;
- case SIMEDBONE_GROUP:
- select_similar_data_pchan(
- C,
- STRUCT_SIZE_AND_OFFSET(bPoseChannel, agrp_index));
- break;
- case SIMEDBONE_SHAPE:
- select_similar_data_pchan(
- C,
- STRUCT_SIZE_AND_OFFSET(bPoseChannel, custom));
- break;
- }
+ sizeof(((_struct *)NULL)->_member), offsetof(_struct, _member)
+
+ switch (type) {
+ case SIMEDBONE_CHILDREN:
+ select_similar_children(C);
+ break;
+ case SIMEDBONE_CHILDREN_IMMEDIATE:
+ select_similar_children_immediate(C);
+ break;
+ case SIMEDBONE_SIBLINGS:
+ select_similar_siblings(C);
+ break;
+ case SIMEDBONE_LENGTH:
+ select_similar_length(C, thresh);
+ break;
+ case SIMEDBONE_DIRECTION:
+ select_similar_direction(C, thresh);
+ break;
+ case SIMEDBONE_PREFIX:
+ select_similar_prefix(C);
+ break;
+ case SIMEDBONE_SUFFIX:
+ select_similar_suffix(C);
+ break;
+ case SIMEDBONE_LAYER:
+ select_similar_layer(C);
+ break;
+ case SIMEDBONE_GROUP:
+ select_similar_data_pchan(C, STRUCT_SIZE_AND_OFFSET(bPoseChannel, agrp_index));
+ break;
+ case SIMEDBONE_SHAPE:
+ select_similar_data_pchan(C, STRUCT_SIZE_AND_OFFSET(bPoseChannel, custom));
+ break;
+ }
#undef STRUCT_SIZE_AND_OFFSET
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_select_similar(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Similar";
- ot->idname = "ARMATURE_OT_select_similar";
-
- /* callback functions */
- ot->invoke = WM_menu_invoke;
- ot->exec = armature_select_similar_exec;
- ot->poll = ED_operator_editarmature;
- ot->description = "Select similar bones by property types";
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, SIMEDBONE_LENGTH, "Type", "");
- RNA_def_float(ot->srna, "threshold", 0.1f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
+ /* identifiers */
+ ot->name = "Select Similar";
+ ot->idname = "ARMATURE_OT_select_similar";
+
+ /* callback functions */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = armature_select_similar_exec;
+ ot->poll = ED_operator_editarmature;
+ ot->description = "Select similar bones by property types";
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, SIMEDBONE_LENGTH, "Type", "");
+ RNA_def_float(ot->srna, "threshold", 0.1f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
}
/* ********************* select hierarchy operator ************** */
@@ -1554,103 +1571,101 @@ void ARMATURE_OT_select_similar(wmOperatorType *ot)
* selected we then keep the non-active objects untouched (selected/unselected). */
static int armature_select_hierarchy_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_edit_object(C);
- EditBone *ebone_active;
- int direction = RNA_enum_get(op->ptr, "direction");
- const bool add_to_sel = RNA_boolean_get(op->ptr, "extend");
- bool changed = false;
- bArmature *arm = (bArmature *)ob->data;
-
- ebone_active = arm->act_edbone;
- if (ebone_active == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- if (direction == BONE_SELECT_PARENT) {
- if (ebone_active->parent) {
- EditBone *ebone_parent;
-
- ebone_parent = ebone_active->parent;
-
- if (EBONE_SELECTABLE(arm, ebone_parent)) {
- arm->act_edbone = ebone_parent;
-
- if (!add_to_sel) {
- ED_armature_ebone_select_set(ebone_active, false);
- }
- ED_armature_ebone_select_set(ebone_parent, true);
-
- changed = true;
- }
- }
-
- }
- else { /* BONE_SELECT_CHILD */
- EditBone *ebone_iter, *ebone_child = NULL;
- int pass;
-
- /* first pass, only connected bones (the logical direct child) */
- for (pass = 0; pass < 2 && (ebone_child == NULL); pass++) {
- for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
- /* possible we have multiple children, some invisible */
- if (EBONE_SELECTABLE(arm, ebone_iter)) {
- if (ebone_iter->parent == ebone_active) {
- if ((pass == 1) || (ebone_iter->flag & BONE_CONNECTED)) {
- ebone_child = ebone_iter;
- break;
- }
- }
- }
- }
- }
-
- if (ebone_child) {
- arm->act_edbone = ebone_child;
-
- if (!add_to_sel) {
- ED_armature_ebone_select_set(ebone_active, false);
- }
- ED_armature_ebone_select_set(ebone_child, true);
-
- changed = true;
- }
- }
-
- if (changed == false) {
- return OPERATOR_CANCELLED;
- }
-
- ED_armature_edit_sync_selection(arm->edbo);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
- return OPERATOR_FINISHED;
+ Object *ob = CTX_data_edit_object(C);
+ EditBone *ebone_active;
+ int direction = RNA_enum_get(op->ptr, "direction");
+ const bool add_to_sel = RNA_boolean_get(op->ptr, "extend");
+ bool changed = false;
+ bArmature *arm = (bArmature *)ob->data;
+
+ ebone_active = arm->act_edbone;
+ if (ebone_active == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (direction == BONE_SELECT_PARENT) {
+ if (ebone_active->parent) {
+ EditBone *ebone_parent;
+
+ ebone_parent = ebone_active->parent;
+
+ if (EBONE_SELECTABLE(arm, ebone_parent)) {
+ arm->act_edbone = ebone_parent;
+
+ if (!add_to_sel) {
+ ED_armature_ebone_select_set(ebone_active, false);
+ }
+ ED_armature_ebone_select_set(ebone_parent, true);
+
+ changed = true;
+ }
+ }
+ }
+ else { /* BONE_SELECT_CHILD */
+ EditBone *ebone_iter, *ebone_child = NULL;
+ int pass;
+
+ /* first pass, only connected bones (the logical direct child) */
+ for (pass = 0; pass < 2 && (ebone_child == NULL); pass++) {
+ for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ /* possible we have multiple children, some invisible */
+ if (EBONE_SELECTABLE(arm, ebone_iter)) {
+ if (ebone_iter->parent == ebone_active) {
+ if ((pass == 1) || (ebone_iter->flag & BONE_CONNECTED)) {
+ ebone_child = ebone_iter;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (ebone_child) {
+ arm->act_edbone = ebone_child;
+
+ if (!add_to_sel) {
+ ED_armature_ebone_select_set(ebone_active, false);
+ }
+ ED_armature_ebone_select_set(ebone_child, true);
+
+ changed = true;
+ }
+ }
+
+ if (changed == false) {
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_armature_edit_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_select_hierarchy(wmOperatorType *ot)
{
- static const EnumPropertyItem direction_items[] = {
- {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
- {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Select Hierarchy";
- ot->idname = "ARMATURE_OT_select_hierarchy";
- ot->description = "Select immediate parent/children of selected bones";
-
- /* api callbacks */
- ot->exec = armature_select_hierarchy_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- RNA_def_enum(ot->srna, "direction", direction_items,
- BONE_SELECT_PARENT, "Direction", "");
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+ static const EnumPropertyItem direction_items[] = {
+ {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
+ {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Select Hierarchy";
+ ot->idname = "ARMATURE_OT_select_hierarchy";
+ ot->description = "Select immediate parent/children of selected bones";
+
+ /* api callbacks */
+ ot->exec = armature_select_hierarchy_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", direction_items, BONE_SELECT_PARENT, "Direction", "");
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
/****************** Mirror Select ****************/
@@ -1660,202 +1675,199 @@ void ARMATURE_OT_select_hierarchy(wmOperatorType *ot)
*/
static int armature_select_mirror_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const bool active_only = RNA_boolean_get(op->ptr, "only_active");
- const bool extend = RNA_boolean_get(op->ptr, "extend");
-
- 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;
-
- EditBone *ebone, *ebone_mirror_act = NULL;
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- const int flag = ED_armature_ebone_selectflag_get(ebone);
- EBONE_PREV_FLAG_SET(ebone, flag);
- }
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- EditBone *ebone_mirror;
- int flag_new = extend ? EBONE_PREV_FLAG_GET(ebone) : 0;
-
- if ((ebone_mirror = ED_armature_ebone_get_mirrored(arm->edbo, ebone)) &&
- (EBONE_VISIBLE(arm, ebone_mirror)))
- {
- const int flag_mirror = EBONE_PREV_FLAG_GET(ebone_mirror);
- flag_new |= flag_mirror;
-
- if (ebone == arm->act_edbone) {
- ebone_mirror_act = ebone_mirror;
- }
-
- /* skip all but the active or its mirror */
- if (active_only && !ELEM(arm->act_edbone, ebone, ebone_mirror)) {
- continue;
- }
- }
-
- ED_armature_ebone_selectflag_set(ebone, flag_new);
- }
- }
-
- if (ebone_mirror_act) {
- arm->act_edbone = ebone_mirror_act;
- }
-
- ED_armature_edit_sync_selection(arm->edbo);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool active_only = RNA_boolean_get(op->ptr, "only_active");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+
+ 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;
+
+ EditBone *ebone, *ebone_mirror_act = NULL;
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ const int flag = ED_armature_ebone_selectflag_get(ebone);
+ EBONE_PREV_FLAG_SET(ebone, flag);
+ }
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ EditBone *ebone_mirror;
+ int flag_new = extend ? EBONE_PREV_FLAG_GET(ebone) : 0;
+
+ if ((ebone_mirror = ED_armature_ebone_get_mirrored(arm->edbo, ebone)) &&
+ (EBONE_VISIBLE(arm, ebone_mirror))) {
+ const int flag_mirror = EBONE_PREV_FLAG_GET(ebone_mirror);
+ flag_new |= flag_mirror;
+
+ if (ebone == arm->act_edbone) {
+ ebone_mirror_act = ebone_mirror;
+ }
+
+ /* skip all but the active or its mirror */
+ if (active_only && !ELEM(arm->act_edbone, ebone, ebone_mirror)) {
+ continue;
+ }
+ }
+
+ ED_armature_ebone_selectflag_set(ebone, flag_new);
+ }
+ }
+
+ if (ebone_mirror_act) {
+ arm->act_edbone = ebone_mirror_act;
+ }
+
+ ED_armature_edit_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_select_mirror(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Flip Active/Selected Bone";
- ot->idname = "ARMATURE_OT_select_mirror";
- ot->description = "Mirror the bone selection";
-
- /* api callbacks */
- ot->exec = armature_select_mirror_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "only_active", false, "Active Only", "Only operate on the active bone");
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+ /* identifiers */
+ ot->name = "Flip Active/Selected Bone";
+ ot->idname = "ARMATURE_OT_select_mirror";
+ ot->description = "Mirror the bone selection";
+
+ /* api callbacks */
+ ot->exec = armature_select_mirror_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(
+ ot->srna, "only_active", false, "Active Only", "Only operate on the active bone");
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
-
/****************** Select Path ****************/
-static bool armature_shortest_path_select(bArmature *arm, EditBone *ebone_parent, EditBone *ebone_child,
- bool use_parent, bool is_test)
+static bool armature_shortest_path_select(
+ bArmature *arm, EditBone *ebone_parent, EditBone *ebone_child, bool use_parent, bool is_test)
{
- do {
+ do {
- if (!use_parent && (ebone_child == ebone_parent))
- break;
+ if (!use_parent && (ebone_child == ebone_parent))
+ break;
- if (is_test) {
- if (!EBONE_SELECTABLE(arm, ebone_child)) {
- return false;
- }
- }
- else {
- ED_armature_ebone_selectflag_set(ebone_child, (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL));
- }
+ if (is_test) {
+ if (!EBONE_SELECTABLE(arm, ebone_child)) {
+ return false;
+ }
+ }
+ else {
+ ED_armature_ebone_selectflag_set(ebone_child, (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL));
+ }
- if (ebone_child == ebone_parent)
- break;
+ if (ebone_child == ebone_parent)
+ break;
- ebone_child = ebone_child->parent;
- } while (true);
+ ebone_child = ebone_child->parent;
+ } while (true);
- return true;
+ return true;
}
static int armature_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Object *obedit = CTX_data_edit_object(C);
- bArmature *arm = obedit->data;
- EditBone *ebone_src, *ebone_dst;
- EditBone *ebone_isect_parent = NULL;
- EditBone *ebone_isect_child[2];
- bool changed;
- Base *base_dst = NULL;
-
- view3d_operator_needs_opengl(C);
-
- ebone_src = arm->act_edbone;
- ebone_dst = get_nearest_bone(C, event->mval, false, &base_dst);
-
- /* fallback to object selection */
- if (ELEM(NULL, ebone_src, ebone_dst) || (ebone_src == ebone_dst)) {
- return OPERATOR_PASS_THROUGH;
- }
-
- if (base_dst && base_dst->object != obedit) {
- /* Disconnected, ignore. */
- return OPERATOR_CANCELLED;
- }
-
- ebone_isect_child[0] = ebone_src;
- ebone_isect_child[1] = ebone_dst;
-
-
- /* ensure 'ebone_src' is the parent of 'ebone_dst', or set 'ebone_isect_parent' */
- if (ED_armature_ebone_is_child_recursive(ebone_src, ebone_dst)) {
- /* pass */
- }
- else if (ED_armature_ebone_is_child_recursive(ebone_dst, ebone_src)) {
- SWAP(EditBone *, ebone_src, ebone_dst);
- }
- else if ((ebone_isect_parent = ED_armature_ebone_find_shared_parent(ebone_isect_child, 2))) {
- /* pass */
- }
- else {
- /* disconnected bones */
- return OPERATOR_CANCELLED;
- }
-
-
- if (ebone_isect_parent) {
- if (armature_shortest_path_select(arm, ebone_isect_parent, ebone_src, false, true) &&
- armature_shortest_path_select(arm, ebone_isect_parent, ebone_dst, false, true))
- {
- armature_shortest_path_select(arm, ebone_isect_parent, ebone_src, false, false);
- armature_shortest_path_select(arm, ebone_isect_parent, ebone_dst, false, false);
- changed = true;
- }
- else {
- /* unselectable */
- changed = false;
- }
- }
- else {
- if (armature_shortest_path_select(arm, ebone_src, ebone_dst, true, true)) {
- armature_shortest_path_select(arm, ebone_src, ebone_dst, true, false);
- changed = true;
- }
- else {
- /* unselectable */
- changed = false;
- }
- }
-
- if (changed) {
- arm->act_edbone = ebone_dst;
- ED_armature_edit_sync_selection(arm->edbo);
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
-
- return OPERATOR_FINISHED;
- }
- else {
- BKE_report(op->reports, RPT_WARNING, "Unselectable bone in chain");
- return OPERATOR_CANCELLED;
- }
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm = obedit->data;
+ EditBone *ebone_src, *ebone_dst;
+ EditBone *ebone_isect_parent = NULL;
+ EditBone *ebone_isect_child[2];
+ bool changed;
+ Base *base_dst = NULL;
+
+ view3d_operator_needs_opengl(C);
+
+ ebone_src = arm->act_edbone;
+ ebone_dst = get_nearest_bone(C, event->mval, false, &base_dst);
+
+ /* fallback to object selection */
+ if (ELEM(NULL, ebone_src, ebone_dst) || (ebone_src == ebone_dst)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ if (base_dst && base_dst->object != obedit) {
+ /* Disconnected, ignore. */
+ return OPERATOR_CANCELLED;
+ }
+
+ ebone_isect_child[0] = ebone_src;
+ ebone_isect_child[1] = ebone_dst;
+
+ /* ensure 'ebone_src' is the parent of 'ebone_dst', or set 'ebone_isect_parent' */
+ if (ED_armature_ebone_is_child_recursive(ebone_src, ebone_dst)) {
+ /* pass */
+ }
+ else if (ED_armature_ebone_is_child_recursive(ebone_dst, ebone_src)) {
+ SWAP(EditBone *, ebone_src, ebone_dst);
+ }
+ else if ((ebone_isect_parent = ED_armature_ebone_find_shared_parent(ebone_isect_child, 2))) {
+ /* pass */
+ }
+ else {
+ /* disconnected bones */
+ return OPERATOR_CANCELLED;
+ }
+
+ if (ebone_isect_parent) {
+ if (armature_shortest_path_select(arm, ebone_isect_parent, ebone_src, false, true) &&
+ armature_shortest_path_select(arm, ebone_isect_parent, ebone_dst, false, true)) {
+ armature_shortest_path_select(arm, ebone_isect_parent, ebone_src, false, false);
+ armature_shortest_path_select(arm, ebone_isect_parent, ebone_dst, false, false);
+ changed = true;
+ }
+ else {
+ /* unselectable */
+ changed = false;
+ }
+ }
+ else {
+ if (armature_shortest_path_select(arm, ebone_src, ebone_dst, true, true)) {
+ armature_shortest_path_select(arm, ebone_src, ebone_dst, true, false);
+ changed = true;
+ }
+ else {
+ /* unselectable */
+ changed = false;
+ }
+ }
+
+ if (changed) {
+ arm->act_edbone = ebone_dst;
+ ED_armature_edit_sync_selection(arm->edbo);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_WARNING, "Unselectable bone in chain");
+ return OPERATOR_CANCELLED;
+ }
}
void ARMATURE_OT_shortest_path_pick(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Pick Shortest Path";
- ot->idname = "ARMATURE_OT_shortest_path_pick";
- ot->description = "Select shortest path between two bones";
+ /* identifiers */
+ ot->name = "Pick Shortest Path";
+ ot->idname = "ARMATURE_OT_shortest_path_pick";
+ ot->description = "Select shortest path between two bones";
- /* api callbacks */
- ot->invoke = armature_shortest_path_pick_invoke;
- ot->poll = ED_operator_editarmature;
+ /* api callbacks */
+ ot->invoke = armature_shortest_path_pick_invoke;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* 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 5aec55bd1ed..afbeb8e4377 100644
--- a/source/blender/editors/armature/armature_skinning.c
+++ b/source/blender/editors/armature/armature_skinning.c
@@ -59,395 +59,436 @@
static int bone_skinnable_cb(Object *UNUSED(ob), Bone *bone, void *datap)
{
- /* Bones that are deforming
- * are regarded to be "skinnable" and are eligible for
- * auto-skinning.
- *
- * This function performs 2 functions:
- *
- * a) It returns 1 if the bone is skinnable.
- * If we loop over all bones with this
- * function, we can count the number of
- * skinnable bones.
- * b) If the pointer data is non null,
- * it is treated like a handle to a
- * bone pointer -- the bone pointer
- * is set to point at this bone, and
- * the pointer the handle points to
- * is incremented to point to the
- * next member of an array of pointers
- * to bones. This way we can loop using
- * this function to construct an array of
- * pointers to bones that point to all
- * skinnable bones.
- */
- Bone ***hbone;
- int a, segments;
- struct { Object *armob; void *list; int heat; bool is_weight_paint; } *data = datap;
-
- if (!(data->is_weight_paint) || !(bone->flag & BONE_HIDDEN_P)) {
- if (!(bone->flag & BONE_NO_DEFORM)) {
- if (data->heat && data->armob->pose && BKE_pose_channel_find_name(data->armob->pose, bone->name))
- segments = bone->segments;
- else
- segments = 1;
-
- if (data->list != NULL) {
- hbone = (Bone ***) &data->list;
-
- for (a = 0; a < segments; a++) {
- **hbone = bone;
- (*hbone)++;
- }
- }
- return segments;
- }
- }
- return 0;
+ /* Bones that are deforming
+ * are regarded to be "skinnable" and are eligible for
+ * auto-skinning.
+ *
+ * This function performs 2 functions:
+ *
+ * a) It returns 1 if the bone is skinnable.
+ * If we loop over all bones with this
+ * function, we can count the number of
+ * skinnable bones.
+ * b) If the pointer data is non null,
+ * it is treated like a handle to a
+ * bone pointer -- the bone pointer
+ * is set to point at this bone, and
+ * the pointer the handle points to
+ * is incremented to point to the
+ * next member of an array of pointers
+ * to bones. This way we can loop using
+ * this function to construct an array of
+ * pointers to bones that point to all
+ * skinnable bones.
+ */
+ Bone ***hbone;
+ int a, segments;
+ struct {
+ Object *armob;
+ void *list;
+ int heat;
+ bool is_weight_paint;
+ } *data = datap;
+
+ if (!(data->is_weight_paint) || !(bone->flag & BONE_HIDDEN_P)) {
+ if (!(bone->flag & BONE_NO_DEFORM)) {
+ if (data->heat && data->armob->pose &&
+ BKE_pose_channel_find_name(data->armob->pose, bone->name))
+ segments = bone->segments;
+ else
+ segments = 1;
+
+ if (data->list != NULL) {
+ hbone = (Bone ***)&data->list;
+
+ for (a = 0; a < segments; a++) {
+ **hbone = bone;
+ (*hbone)++;
+ }
+ }
+ return segments;
+ }
+ }
+ return 0;
}
static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
{
- /* This group creates a vertex group to ob that has the
- * same name as bone (provided the bone is skinnable).
- * If such a vertex group already exist the routine exits.
- */
- if (!(bone->flag & BONE_NO_DEFORM)) {
- if (!defgroup_find_name(ob, bone->name)) {
- BKE_object_defgroup_add_name(ob, bone->name);
- return 1;
- }
- }
- return 0;
+ /* This group creates a vertex group to ob that has the
+ * same name as bone (provided the bone is skinnable).
+ * If such a vertex group already exist the routine exits.
+ */
+ if (!(bone->flag & BONE_NO_DEFORM)) {
+ if (!defgroup_find_name(ob, bone->name)) {
+ BKE_object_defgroup_add_name(ob, bone->name);
+ return 1;
+ }
+ }
+ return 0;
}
static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
{
- /* Bones that are deforming
- * are regarded to be "skinnable" and are eligible for
- * auto-skinning.
- *
- * This function performs 2 functions:
- *
- * a) If the bone is skinnable, it creates
- * a vertex group for ob that has
- * the name of the skinnable bone
- * (if one doesn't exist already).
- * b) If the pointer data is non null,
- * it is treated like a handle to a
- * bDeformGroup pointer -- the
- * bDeformGroup pointer is set to point
- * to the deform group with the bone's
- * name, and the pointer the handle
- * points to is incremented to point to the
- * next member of an array of pointers
- * to bDeformGroups. This way we can loop using
- * this function to construct an array of
- * pointers to bDeformGroups, all with names
- * of skinnable bones.
- */
- bDeformGroup ***hgroup, *defgroup = NULL;
- int a, segments;
- struct { Object *armob; void *list; int heat; bool is_weight_paint; } *data = datap;
- bArmature *arm = data->armob->data;
-
- if (!data->is_weight_paint || !(bone->flag & BONE_HIDDEN_P)) {
- if (!(bone->flag & BONE_NO_DEFORM)) {
- if (data->heat && data->armob->pose && BKE_pose_channel_find_name(data->armob->pose, bone->name))
- segments = bone->segments;
- else
- segments = 1;
-
- if (!data->is_weight_paint || ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))) {
- if (!(defgroup = defgroup_find_name(ob, bone->name))) {
- defgroup = BKE_object_defgroup_add_name(ob, bone->name);
- }
- else if (defgroup->flag & DG_LOCK_WEIGHT) {
- /* In case vgroup already exists and is locked, do not modify it here. See T43814. */
- defgroup = NULL;
- }
- }
-
- if (data->list != NULL) {
- hgroup = (bDeformGroup ***) &data->list;
-
- for (a = 0; a < segments; a++) {
- **hgroup = defgroup;
- (*hgroup)++;
- }
- }
- return segments;
- }
- }
- return 0;
+ /* Bones that are deforming
+ * are regarded to be "skinnable" and are eligible for
+ * auto-skinning.
+ *
+ * This function performs 2 functions:
+ *
+ * a) If the bone is skinnable, it creates
+ * a vertex group for ob that has
+ * the name of the skinnable bone
+ * (if one doesn't exist already).
+ * b) If the pointer data is non null,
+ * it is treated like a handle to a
+ * bDeformGroup pointer -- the
+ * bDeformGroup pointer is set to point
+ * to the deform group with the bone's
+ * name, and the pointer the handle
+ * points to is incremented to point to the
+ * next member of an array of pointers
+ * to bDeformGroups. This way we can loop using
+ * this function to construct an array of
+ * pointers to bDeformGroups, all with names
+ * of skinnable bones.
+ */
+ bDeformGroup ***hgroup, *defgroup = NULL;
+ int a, segments;
+ struct {
+ Object *armob;
+ void *list;
+ int heat;
+ bool is_weight_paint;
+ } *data = datap;
+ bArmature *arm = data->armob->data;
+
+ if (!data->is_weight_paint || !(bone->flag & BONE_HIDDEN_P)) {
+ if (!(bone->flag & BONE_NO_DEFORM)) {
+ if (data->heat && data->armob->pose &&
+ BKE_pose_channel_find_name(data->armob->pose, bone->name))
+ segments = bone->segments;
+ else
+ segments = 1;
+
+ if (!data->is_weight_paint || ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))) {
+ if (!(defgroup = defgroup_find_name(ob, bone->name))) {
+ defgroup = BKE_object_defgroup_add_name(ob, bone->name);
+ }
+ else if (defgroup->flag & DG_LOCK_WEIGHT) {
+ /* In case vgroup already exists and is locked, do not modify it here. See T43814. */
+ defgroup = NULL;
+ }
+ }
+
+ if (data->list != NULL) {
+ hgroup = (bDeformGroup ***)&data->list;
+
+ for (a = 0; a < segments; a++) {
+ **hgroup = defgroup;
+ (*hgroup)++;
+ }
+ }
+ return segments;
+ }
+ }
+ return 0;
}
-static void envelope_bone_weighting(
- Object *ob, Mesh *mesh, float (*verts)[3], int numbones, Bone **bonelist,
- bDeformGroup **dgrouplist, bDeformGroup **dgroupflip,
- float (*root)[3], float (*tip)[3], const int *selected, float scale)
+static void envelope_bone_weighting(Object *ob,
+ Mesh *mesh,
+ float (*verts)[3],
+ int numbones,
+ Bone **bonelist,
+ bDeformGroup **dgrouplist,
+ bDeformGroup **dgroupflip,
+ float (*root)[3],
+ float (*tip)[3],
+ const int *selected,
+ float scale)
{
- /* Create vertex group weights from envelopes */
-
- Bone *bone;
- bDeformGroup *dgroup;
- float distance;
- int i, iflip, j;
- bool use_topology = (mesh->editflag & ME_EDIT_MIRROR_TOPO) != 0;
- bool use_mask = false;
-
- if ((ob->mode & OB_MODE_WEIGHT_PAINT) &&
- (mesh->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)))
- {
- use_mask = true;
- }
-
- /* for each vertex in the mesh */
- for (i = 0; i < mesh->totvert; i++) {
-
- if (use_mask && !(mesh->mvert[i].flag & SELECT)) {
- continue;
- }
-
- iflip = (dgroupflip) ? mesh_get_x_mirror_vert(ob, NULL, i, use_topology) : -1;
-
- /* for each skinnable bone */
- for (j = 0; j < numbones; ++j) {
- if (!selected[j])
- continue;
-
- bone = bonelist[j];
- dgroup = dgrouplist[j];
-
- /* store the distance-factor from the vertex to the bone */
- distance = distfactor_to_bone(verts[i], root[j], tip[j],
- bone->rad_head * scale, bone->rad_tail * scale, bone->dist * scale);
-
- /* add the vert to the deform group if (weight != 0.0) */
- if (distance != 0.0f)
- ED_vgroup_vert_add(ob, dgroup, i, distance, WEIGHT_REPLACE);
- else
- ED_vgroup_vert_remove(ob, dgroup, i);
-
- /* do same for mirror */
- if (dgroupflip && dgroupflip[j] && iflip != -1) {
- if (distance != 0.0f)
- ED_vgroup_vert_add(ob, dgroupflip[j], iflip, distance,
- WEIGHT_REPLACE);
- else
- ED_vgroup_vert_remove(ob, dgroupflip[j], iflip);
- }
- }
- }
+ /* Create vertex group weights from envelopes */
+
+ Bone *bone;
+ bDeformGroup *dgroup;
+ float distance;
+ int i, iflip, j;
+ bool use_topology = (mesh->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+ bool use_mask = false;
+
+ if ((ob->mode & OB_MODE_WEIGHT_PAINT) &&
+ (mesh->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL))) {
+ use_mask = true;
+ }
+
+ /* for each vertex in the mesh */
+ for (i = 0; i < mesh->totvert; i++) {
+
+ if (use_mask && !(mesh->mvert[i].flag & SELECT)) {
+ continue;
+ }
+
+ iflip = (dgroupflip) ? mesh_get_x_mirror_vert(ob, NULL, i, use_topology) : -1;
+
+ /* for each skinnable bone */
+ for (j = 0; j < numbones; ++j) {
+ if (!selected[j])
+ continue;
+
+ bone = bonelist[j];
+ dgroup = dgrouplist[j];
+
+ /* store the distance-factor from the vertex to the bone */
+ distance = distfactor_to_bone(verts[i],
+ root[j],
+ tip[j],
+ bone->rad_head * scale,
+ bone->rad_tail * scale,
+ bone->dist * scale);
+
+ /* add the vert to the deform group if (weight != 0.0) */
+ if (distance != 0.0f)
+ ED_vgroup_vert_add(ob, dgroup, i, distance, WEIGHT_REPLACE);
+ else
+ ED_vgroup_vert_remove(ob, dgroup, i);
+
+ /* do same for mirror */
+ if (dgroupflip && dgroupflip[j] && iflip != -1) {
+ if (distance != 0.0f)
+ ED_vgroup_vert_add(ob, dgroupflip[j], iflip, distance, WEIGHT_REPLACE);
+ else
+ ED_vgroup_vert_remove(ob, dgroupflip[j], iflip);
+ }
+ }
+ }
}
-static void add_verts_to_dgroups(
- ReportList *reports, Depsgraph *depsgraph, Scene *UNUSED(scene), Object *ob, Object *par,
- int heat, const bool mirror)
+static void add_verts_to_dgroups(ReportList *reports,
+ Depsgraph *depsgraph,
+ Scene *UNUSED(scene),
+ Object *ob,
+ Object *par,
+ int heat,
+ const bool mirror)
{
- /* This functions implements the automatic computation of vertex group
- * weights, either through envelopes or using a heat equilibrium.
- *
- * This function can be called both when parenting a mesh to an armature,
- * or in weightpaint + posemode. In the latter case selection is taken
- * into account and vertex weights can be mirrored.
- *
- * The mesh vertex positions used are either the final deformed coords
- * from the evaluated mesh in weightpaint mode, the final subsurf coords
- * when parenting, or simply the original mesh coords.
- */
-
- bArmature *arm = par->data;
- Bone **bonelist, *bone;
- bDeformGroup **dgrouplist, **dgroupflip;
- bDeformGroup *dgroup;
- bPoseChannel *pchan;
- Mesh *mesh;
- Mat4 bbone_array[MAX_BBONE_SUBDIV], *bbone = NULL;
- float (*root)[3], (*tip)[3], (*verts)[3];
- int *selected;
- int numbones, vertsfilled = 0, i, j, segments = 0;
- const bool wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT);
- struct { Object *armob; void *list; int heat; bool is_weight_paint; } looper_data;
-
- looper_data.armob = par;
- looper_data.heat = heat;
- looper_data.list = NULL;
- looper_data.is_weight_paint = wpmode;
-
- /* count the number of skinnable bones */
- numbones = bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
-
- if (numbones == 0)
- return;
-
- if (BKE_object_defgroup_data_create(ob->data) == NULL)
- return;
-
- /* create an array of pointer to bones that are skinnable
- * and fill it with all of the skinnable bones */
- bonelist = MEM_callocN(numbones * sizeof(Bone *), "bonelist");
- looper_data.list = bonelist;
- bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
-
- /* create an array of pointers to the deform groups that
- * correspond to the skinnable bones (creating them
- * as necessary. */
- dgrouplist = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgrouplist");
- dgroupflip = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgroupflip");
-
- looper_data.list = dgrouplist;
- bone_looper(ob, arm->bonebase.first, &looper_data, dgroup_skinnable_cb);
-
- /* create an array of root and tip positions transformed into
- * global coords */
- root = MEM_callocN(numbones * sizeof(float) * 3, "root");
- tip = MEM_callocN(numbones * sizeof(float) * 3, "tip");
- selected = MEM_callocN(numbones * sizeof(int), "selected");
-
- for (j = 0; j < numbones; ++j) {
- bone = bonelist[j];
- dgroup = dgrouplist[j];
-
- /* handle bbone */
- if (heat) {
- if (segments == 0) {
- segments = 1;
- bbone = NULL;
-
- if ((par->pose) && (pchan = BKE_pose_channel_find_name(par->pose, bone->name))) {
- if (bone->segments > 1) {
- segments = bone->segments;
- BKE_pchan_bbone_spline_setup(pchan, true, false, bbone_array);
- bbone = bbone_array;
- }
- }
- }
-
- segments--;
- }
-
- /* compute root and tip */
- if (bbone) {
- mul_v3_m4v3(root[j], bone->arm_mat, bbone[segments].mat[3]);
- if ((segments + 1) < bone->segments) {
- mul_v3_m4v3(tip[j], bone->arm_mat, bbone[segments + 1].mat[3]);
- }
- else {
- copy_v3_v3(tip[j], bone->arm_tail);
- }
- }
- else {
- copy_v3_v3(root[j], bone->arm_head);
- copy_v3_v3(tip[j], bone->arm_tail);
- }
-
- mul_m4_v3(par->obmat, root[j]);
- mul_m4_v3(par->obmat, tip[j]);
-
- /* set selected */
- if (wpmode) {
- if ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))
- selected[j] = 1;
- }
- else
- selected[j] = 1;
-
- /* find flipped group */
- if (dgroup && mirror) {
- 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);
- }
- }
-
- /* create verts */
- mesh = (Mesh *)ob->data;
- verts = MEM_callocN(mesh->totvert * sizeof(*verts), "closestboneverts");
-
- if (wpmode) {
- /* if in weight paint mode, use final verts from evaluated mesh */
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
-
- BKE_mesh_foreach_mapped_vert_coords_get(me_eval, verts, mesh->totvert);
- vertsfilled = 1;
- }
- else if (modifiers_findByType(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'. */
- subsurf_calculate_limit_positions(mesh, verts);
- vertsfilled = 1;
- }
-
- /* transform verts to global space */
- for (i = 0; i < mesh->totvert; i++) {
- if (!vertsfilled)
- copy_v3_v3(verts[i], mesh->mvert[i].co);
- mul_m4_v3(ob->obmat, verts[i]);
- }
-
- /* compute the weights based on gathered vertices and bones */
- if (heat) {
- const char *error = NULL;
-
- heat_bone_weighting(
- ob, mesh, verts, numbones, dgrouplist, dgroupflip,
- root, tip, selected, &error);
- if (error) {
- BKE_report(reports, RPT_WARNING, error);
- }
- }
- else {
- envelope_bone_weighting(
- ob, mesh, verts, numbones, bonelist, dgrouplist,
- dgroupflip, root, tip, selected, mat4_to_scale(par->obmat));
- }
-
- /* only generated in some cases but can call anyway */
- ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 'e');
-
- /* free the memory allocated */
- MEM_freeN(bonelist);
- MEM_freeN(dgrouplist);
- MEM_freeN(dgroupflip);
- MEM_freeN(root);
- MEM_freeN(tip);
- MEM_freeN(selected);
- MEM_freeN(verts);
+ /* This functions implements the automatic computation of vertex group
+ * weights, either through envelopes or using a heat equilibrium.
+ *
+ * This function can be called both when parenting a mesh to an armature,
+ * or in weightpaint + posemode. In the latter case selection is taken
+ * into account and vertex weights can be mirrored.
+ *
+ * The mesh vertex positions used are either the final deformed coords
+ * from the evaluated mesh in weightpaint mode, the final subsurf coords
+ * when parenting, or simply the original mesh coords.
+ */
+
+ bArmature *arm = par->data;
+ Bone **bonelist, *bone;
+ bDeformGroup **dgrouplist, **dgroupflip;
+ bDeformGroup *dgroup;
+ bPoseChannel *pchan;
+ Mesh *mesh;
+ Mat4 bbone_array[MAX_BBONE_SUBDIV], *bbone = NULL;
+ float(*root)[3], (*tip)[3], (*verts)[3];
+ int *selected;
+ int numbones, vertsfilled = 0, i, j, segments = 0;
+ const bool wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT);
+ struct {
+ Object *armob;
+ void *list;
+ int heat;
+ bool is_weight_paint;
+ } looper_data;
+
+ looper_data.armob = par;
+ looper_data.heat = heat;
+ looper_data.list = NULL;
+ looper_data.is_weight_paint = wpmode;
+
+ /* count the number of skinnable bones */
+ numbones = bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
+
+ if (numbones == 0)
+ return;
+
+ if (BKE_object_defgroup_data_create(ob->data) == NULL)
+ return;
+
+ /* create an array of pointer to bones that are skinnable
+ * and fill it with all of the skinnable bones */
+ bonelist = MEM_callocN(numbones * sizeof(Bone *), "bonelist");
+ looper_data.list = bonelist;
+ bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
+
+ /* create an array of pointers to the deform groups that
+ * correspond to the skinnable bones (creating them
+ * as necessary. */
+ dgrouplist = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgrouplist");
+ dgroupflip = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgroupflip");
+
+ looper_data.list = dgrouplist;
+ bone_looper(ob, arm->bonebase.first, &looper_data, dgroup_skinnable_cb);
+
+ /* create an array of root and tip positions transformed into
+ * global coords */
+ root = MEM_callocN(numbones * sizeof(float) * 3, "root");
+ tip = MEM_callocN(numbones * sizeof(float) * 3, "tip");
+ selected = MEM_callocN(numbones * sizeof(int), "selected");
+
+ for (j = 0; j < numbones; ++j) {
+ bone = bonelist[j];
+ dgroup = dgrouplist[j];
+
+ /* handle bbone */
+ if (heat) {
+ if (segments == 0) {
+ segments = 1;
+ bbone = NULL;
+
+ if ((par->pose) && (pchan = BKE_pose_channel_find_name(par->pose, bone->name))) {
+ if (bone->segments > 1) {
+ segments = bone->segments;
+ BKE_pchan_bbone_spline_setup(pchan, true, false, bbone_array);
+ bbone = bbone_array;
+ }
+ }
+ }
+
+ segments--;
+ }
+
+ /* compute root and tip */
+ if (bbone) {
+ mul_v3_m4v3(root[j], bone->arm_mat, bbone[segments].mat[3]);
+ if ((segments + 1) < bone->segments) {
+ mul_v3_m4v3(tip[j], bone->arm_mat, bbone[segments + 1].mat[3]);
+ }
+ else {
+ copy_v3_v3(tip[j], bone->arm_tail);
+ }
+ }
+ else {
+ copy_v3_v3(root[j], bone->arm_head);
+ copy_v3_v3(tip[j], bone->arm_tail);
+ }
+
+ mul_m4_v3(par->obmat, root[j]);
+ mul_m4_v3(par->obmat, tip[j]);
+
+ /* set selected */
+ if (wpmode) {
+ if ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))
+ selected[j] = 1;
+ }
+ else
+ selected[j] = 1;
+
+ /* find flipped group */
+ if (dgroup && mirror) {
+ 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);
+ }
+ }
+
+ /* create verts */
+ mesh = (Mesh *)ob->data;
+ verts = MEM_callocN(mesh->totvert * sizeof(*verts), "closestboneverts");
+
+ if (wpmode) {
+ /* if in weight paint mode, use final verts from evaluated mesh */
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
+
+ BKE_mesh_foreach_mapped_vert_coords_get(me_eval, verts, mesh->totvert);
+ vertsfilled = 1;
+ }
+ else if (modifiers_findByType(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'. */
+ subsurf_calculate_limit_positions(mesh, verts);
+ vertsfilled = 1;
+ }
+
+ /* transform verts to global space */
+ for (i = 0; i < mesh->totvert; i++) {
+ if (!vertsfilled)
+ copy_v3_v3(verts[i], mesh->mvert[i].co);
+ mul_m4_v3(ob->obmat, verts[i]);
+ }
+
+ /* compute the weights based on gathered vertices and bones */
+ if (heat) {
+ const char *error = NULL;
+
+ heat_bone_weighting(
+ ob, mesh, verts, numbones, dgrouplist, dgroupflip, root, tip, selected, &error);
+ if (error) {
+ BKE_report(reports, RPT_WARNING, error);
+ }
+ }
+ else {
+ envelope_bone_weighting(ob,
+ mesh,
+ verts,
+ numbones,
+ bonelist,
+ dgrouplist,
+ dgroupflip,
+ root,
+ tip,
+ selected,
+ mat4_to_scale(par->obmat));
+ }
+
+ /* only generated in some cases but can call anyway */
+ ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 'e');
+
+ /* free the memory allocated */
+ MEM_freeN(bonelist);
+ MEM_freeN(dgrouplist);
+ MEM_freeN(dgroupflip);
+ MEM_freeN(root);
+ MEM_freeN(tip);
+ MEM_freeN(selected);
+ MEM_freeN(verts);
}
-void ED_object_vgroup_calc_from_armature(
- ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, Object *par,
- const int mode, const bool mirror)
+void ED_object_vgroup_calc_from_armature(ReportList *reports,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ Object *par,
+ const int mode,
+ const bool mirror)
{
- /* Lets try to create some vertex groups
- * based on the bones of the parent armature.
- */
- bArmature *arm = par->data;
-
- if (mode == ARM_GROUPS_NAME) {
- const int defbase_tot = BLI_listbase_count(&ob->defbase);
- int defbase_add;
- /* Traverse the bone list, trying to create empty vertex
- * groups corresponding to the bone.
- */
- defbase_add = bone_looper(ob, arm->bonebase.first, NULL, vgroup_add_unique_bone_cb);
-
- if (defbase_add) {
- /* its possible there are DWeight's outside the range of the current
- * objects deform groups, in this case the new groups wont be empty [#33889] */
- ED_vgroup_data_clamp_range(ob->data, defbase_tot);
- }
- }
- else if (ELEM(mode, ARM_GROUPS_ENVELOPE, ARM_GROUPS_AUTO)) {
- /* Traverse the bone list, trying to create vertex groups
- * that are populated with the vertices for which the
- * bone is closest.
- */
- add_verts_to_dgroups(reports, depsgraph, scene, ob, par, (mode == ARM_GROUPS_AUTO), mirror);
- }
+ /* Lets try to create some vertex groups
+ * based on the bones of the parent armature.
+ */
+ bArmature *arm = par->data;
+
+ if (mode == ARM_GROUPS_NAME) {
+ const int defbase_tot = BLI_listbase_count(&ob->defbase);
+ int defbase_add;
+ /* Traverse the bone list, trying to create empty vertex
+ * groups corresponding to the bone.
+ */
+ defbase_add = bone_looper(ob, arm->bonebase.first, NULL, vgroup_add_unique_bone_cb);
+
+ if (defbase_add) {
+ /* its possible there are DWeight's outside the range of the current
+ * objects deform groups, in this case the new groups wont be empty [#33889] */
+ ED_vgroup_data_clamp_range(ob->data, defbase_tot);
+ }
+ }
+ else if (ELEM(mode, ARM_GROUPS_ENVELOPE, ARM_GROUPS_AUTO)) {
+ /* Traverse the bone list, trying to create vertex groups
+ * that are populated with the vertices for which the
+ * bone is closest.
+ */
+ add_verts_to_dgroups(reports, depsgraph, scene, ob, par, (mode == ARM_GROUPS_AUTO), mirror);
+ }
}
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index 465209eb9c5..50289197ed4 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -50,34 +50,34 @@
/* Sync selection to parent for connected children */
void ED_armature_edit_sync_selection(ListBase *edbo)
{
- EditBone *ebo;
-
- for (ebo = edbo->first; ebo; ebo = ebo->next) {
- /* if bone is not selectable, we shouldn't alter this setting... */
- if ((ebo->flag & BONE_UNSELECTABLE) == 0) {
- if ((ebo->flag & BONE_CONNECTED) && (ebo->parent)) {
- if (ebo->parent->flag & BONE_TIPSEL)
- ebo->flag |= BONE_ROOTSEL;
- else
- ebo->flag &= ~BONE_ROOTSEL;
- }
-
- if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL))
- ebo->flag |= BONE_SELECTED;
- else
- ebo->flag &= ~BONE_SELECTED;
- }
- }
+ EditBone *ebo;
+
+ for (ebo = edbo->first; ebo; ebo = ebo->next) {
+ /* if bone is not selectable, we shouldn't alter this setting... */
+ if ((ebo->flag & BONE_UNSELECTABLE) == 0) {
+ if ((ebo->flag & BONE_CONNECTED) && (ebo->parent)) {
+ if (ebo->parent->flag & BONE_TIPSEL)
+ ebo->flag |= BONE_ROOTSEL;
+ else
+ ebo->flag &= ~BONE_ROOTSEL;
+ }
+
+ if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL))
+ ebo->flag |= BONE_SELECTED;
+ else
+ ebo->flag &= ~BONE_SELECTED;
+ }
+ }
}
void ED_armature_edit_validate_active(struct bArmature *arm)
{
- EditBone *ebone = arm->act_edbone;
+ EditBone *ebone = arm->act_edbone;
- if (ebone) {
- if (ebone->flag & BONE_HIDDEN_A)
- arm->act_edbone = NULL;
- }
+ if (ebone) {
+ if (ebone->flag & BONE_HIDDEN_A)
+ arm->act_edbone = NULL;
+ }
}
/* *************************************************************** */
@@ -85,31 +85,30 @@ void ED_armature_edit_validate_active(struct bArmature *arm)
/* XXX bone_looper is only to be used when we want to access settings
* (i.e. editability/visibility/selected) that context doesn't offer */
-int bone_looper(Object *ob, Bone *bone, void *data,
- int (*bone_func)(Object *, Bone *, void *))
+int bone_looper(Object *ob, Bone *bone, void *data, int (*bone_func)(Object *, Bone *, void *))
{
- /* We want to apply the function bone_func to every bone
- * in an armature -- feed bone_looper the first bone and
- * a pointer to the bone_func and watch it go!. The int count
- * can be useful for counting bones with a certain property
- * (e.g. skinnable)
- */
- int count = 0;
+ /* We want to apply the function bone_func to every bone
+ * in an armature -- feed bone_looper the first bone and
+ * a pointer to the bone_func and watch it go!. The int count
+ * can be useful for counting bones with a certain property
+ * (e.g. skinnable)
+ */
+ int count = 0;
- if (bone) {
- /* only do bone_func if the bone is non null */
- count += bone_func(ob, bone, data);
+ if (bone) {
+ /* only do bone_func if the bone is non null */
+ count += bone_func(ob, bone, data);
- /* try to execute bone_func for the first child */
- count += bone_looper(ob, bone->childbase.first, data, bone_func);
+ /* try to execute bone_func for the first child */
+ count += bone_looper(ob, bone->childbase.first, data, bone_func);
- /* try to execute bone_func for the next bone at this
- * depth of the recursion.
- */
- count += bone_looper(ob, bone->next, data, bone_func);
- }
+ /* try to execute bone_func for the next bone at this
+ * depth of the recursion.
+ */
+ count += bone_looper(ob, bone->next, data, bone_func);
+ }
- return count;
+ return count;
}
/* *************************************************************** */
@@ -117,25 +116,25 @@ int bone_looper(Object *ob, Bone *bone, void *data,
void bone_free(bArmature *arm, EditBone *bone)
{
- if (arm->act_edbone == bone)
- arm->act_edbone = NULL;
+ if (arm->act_edbone == bone)
+ arm->act_edbone = NULL;
- if (bone->prop) {
- IDP_FreeProperty(bone->prop);
- MEM_freeN(bone->prop);
- }
+ if (bone->prop) {
+ IDP_FreeProperty(bone->prop);
+ MEM_freeN(bone->prop);
+ }
- /* Clear references from other edit bones. */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (ebone->bbone_next == bone) {
- ebone->bbone_next = NULL;
- }
- if (ebone->bbone_prev == bone) {
- ebone->bbone_prev = NULL;
- }
- }
+ /* Clear references from other edit bones. */
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ebone->bbone_next == bone) {
+ ebone->bbone_next = NULL;
+ }
+ if (ebone->bbone_prev == bone) {
+ ebone->bbone_prev = NULL;
+ }
+ }
- BLI_freelinkN(arm->edbo, bone);
+ BLI_freelinkN(arm->edbo, bone);
}
/**
@@ -143,33 +142,33 @@ void bone_free(bArmature *arm, EditBone *bone)
*/
void ED_armature_ebone_remove_ex(bArmature *arm, EditBone *exBone, bool clear_connected)
{
- EditBone *curBone;
+ EditBone *curBone;
- /* Find any bones that refer to this bone */
- for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
- if (curBone->parent == exBone) {
- curBone->parent = exBone->parent;
- if (clear_connected) {
- curBone->flag &= ~BONE_CONNECTED;
- }
- }
- }
+ /* Find any bones that refer to this bone */
+ for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
+ if (curBone->parent == exBone) {
+ curBone->parent = exBone->parent;
+ if (clear_connected) {
+ curBone->flag &= ~BONE_CONNECTED;
+ }
+ }
+ }
- bone_free(arm, exBone);
+ bone_free(arm, exBone);
}
void ED_armature_ebone_remove(bArmature *arm, EditBone *exBone)
{
- ED_armature_ebone_remove_ex(arm, exBone, true);
+ ED_armature_ebone_remove_ex(arm, exBone, true);
}
bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebone_child)
{
- for (ebone_child = ebone_child->parent; ebone_child; ebone_child = ebone_child->parent) {
- if (ebone_child == ebone_parent)
- return true;
- }
- return false;
+ for (ebone_child = ebone_child->parent; ebone_child; ebone_child = ebone_child->parent) {
+ if (ebone_child == ebone_parent)
+ return true;
+ }
+ return false;
}
/**
@@ -179,81 +178,82 @@ 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 unsigned int ebone_child_tot)
{
- unsigned int i;
- EditBone *ebone_iter;
+ unsigned int i;
+ EditBone *ebone_iter;
#define EBONE_TEMP_UINT(ebone) (*((unsigned int *)(&((ebone)->temp))))
- /* clear all */
- for (i = 0; i < ebone_child_tot; i++) {
- for (ebone_iter = ebone_child[i]; ebone_iter; ebone_iter = ebone_iter->parent) {
- EBONE_TEMP_UINT(ebone_iter) = 0;
- }
- }
-
- /* accumulate */
- for (i = 0; i < ebone_child_tot; i++) {
- for (ebone_iter = ebone_child[i]->parent; ebone_iter; ebone_iter = ebone_iter->parent) {
- EBONE_TEMP_UINT(ebone_iter) += 1;
- }
- }
-
- /* only need search the first chain */
- for (ebone_iter = ebone_child[0]->parent; ebone_iter; ebone_iter = ebone_iter->parent) {
- if (EBONE_TEMP_UINT(ebone_iter) == ebone_child_tot) {
- return ebone_iter;
- }
- }
+ /* clear all */
+ for (i = 0; i < ebone_child_tot; i++) {
+ for (ebone_iter = ebone_child[i]; ebone_iter; ebone_iter = ebone_iter->parent) {
+ EBONE_TEMP_UINT(ebone_iter) = 0;
+ }
+ }
+
+ /* accumulate */
+ for (i = 0; i < ebone_child_tot; i++) {
+ for (ebone_iter = ebone_child[i]->parent; ebone_iter; ebone_iter = ebone_iter->parent) {
+ EBONE_TEMP_UINT(ebone_iter) += 1;
+ }
+ }
+
+ /* only need search the first chain */
+ for (ebone_iter = ebone_child[0]->parent; ebone_iter; ebone_iter = ebone_iter->parent) {
+ if (EBONE_TEMP_UINT(ebone_iter) == ebone_child_tot) {
+ return ebone_iter;
+ }
+ }
#undef EBONE_TEMP_UINT
- return NULL;
+ return NULL;
}
void ED_armature_ebone_to_mat3(EditBone *ebone, float mat[3][3])
{
- float delta[3];
+ float delta[3];
- /* Find the current bone matrix */
- sub_v3_v3v3(delta, ebone->tail, ebone->head);
- vec_roll_to_mat3(delta, ebone->roll, mat);
+ /* Find the current bone matrix */
+ sub_v3_v3v3(delta, ebone->tail, ebone->head);
+ vec_roll_to_mat3(delta, ebone->roll, mat);
}
void ED_armature_ebone_to_mat4(EditBone *ebone, float mat[4][4])
{
- float m3[3][3];
+ float m3[3][3];
- ED_armature_ebone_to_mat3(ebone, m3);
+ ED_armature_ebone_to_mat3(ebone, m3);
- copy_m4_m3(mat, m3);
- copy_v3_v3(mat[3], ebone->head);
+ copy_m4_m3(mat, m3);
+ copy_v3_v3(mat[3], ebone->head);
}
void ED_armature_ebone_from_mat3(EditBone *ebone, float mat[3][3])
{
- float vec[3], roll;
- const float len = len_v3v3(ebone->head, ebone->tail);
+ float vec[3], roll;
+ const float len = len_v3v3(ebone->head, ebone->tail);
- mat3_to_vec_roll(mat, vec, &roll);
+ mat3_to_vec_roll(mat, vec, &roll);
- madd_v3_v3v3fl(ebone->tail, ebone->head, vec, len);
- ebone->roll = roll;
+ madd_v3_v3v3fl(ebone->tail, ebone->head, vec, len);
+ ebone->roll = roll;
}
void ED_armature_ebone_from_mat4(EditBone *ebone, float mat[4][4])
{
- float mat3[3][3];
+ float mat3[3][3];
- copy_m3_m4(mat3, mat);
- /* We want normalized matrix here, to be consistent with ebone_to_mat. */
- BLI_ASSERT_UNIT_M3(mat3);
+ copy_m3_m4(mat3, mat);
+ /* We want normalized matrix here, to be consistent with ebone_to_mat. */
+ BLI_ASSERT_UNIT_M3(mat3);
- sub_v3_v3(ebone->tail, ebone->head);
- copy_v3_v3(ebone->head, mat[3]);
- add_v3_v3(ebone->tail, mat[3]);
- ED_armature_ebone_from_mat3(ebone, mat3);
+ sub_v3_v3(ebone->tail, ebone->head);
+ copy_v3_v3(ebone->head, mat[3]);
+ add_v3_v3(ebone->tail, mat[3]);
+ ED_armature_ebone_from_mat3(ebone, mat3);
}
/**
@@ -261,10 +261,9 @@ void ED_armature_ebone_from_mat4(EditBone *ebone, float mat[4][4])
*/
EditBone *ED_armature_ebone_find_name(const ListBase *edbo, const char *name)
{
- return BLI_findstring(edbo, name, offsetof(EditBone, name));
+ return BLI_findstring(edbo, name, offsetof(EditBone, name));
}
-
/* *************************************************************** */
/* Mirroring */
@@ -273,18 +272,18 @@ EditBone *ED_armature_ebone_find_name(const ListBase *edbo, const char *name)
*/
EditBone *ED_armature_ebone_get_mirrored(const ListBase *edbo, EditBone *ebo)
{
- char name_flip[MAXBONENAME];
+ char name_flip[MAXBONENAME];
- if (ebo == NULL)
- return NULL;
+ if (ebo == NULL)
+ return NULL;
- BLI_string_flip_side_name(name_flip, ebo->name, false, sizeof(name_flip));
+ BLI_string_flip_side_name(name_flip, ebo->name, false, sizeof(name_flip));
- if (!STREQ(name_flip, ebo->name)) {
- return ED_armature_ebone_find_name(edbo, name_flip);
- }
+ if (!STREQ(name_flip, ebo->name)) {
+ return ED_armature_ebone_find_name(edbo, name_flip);
+ }
- return NULL;
+ return NULL;
}
/* ------------------------------------- */
@@ -293,70 +292,69 @@ EditBone *ED_armature_ebone_get_mirrored(const ListBase *edbo, EditBone *ebo)
* it leaves mirrored bones selected then too, which is a good indication of what happened */
void armature_select_mirrored_ex(bArmature *arm, const int flag)
{
- BLI_assert((flag & ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) == 0);
- /* Select mirrored bones */
- if (arm->flag & ARM_MIRROR_EDIT) {
- EditBone *curBone, *ebone_mirr;
-
- for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
- if (arm->layer & curBone->layer) {
- if (curBone->flag & flag) {
- ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone);
- if (ebone_mirr)
- ebone_mirr->flag |= (curBone->flag & flag);
- }
- }
- }
- }
+ BLI_assert((flag & ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) == 0);
+ /* Select mirrored bones */
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ EditBone *curBone, *ebone_mirr;
+ for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
+ if (arm->layer & curBone->layer) {
+ if (curBone->flag & flag) {
+ ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone);
+ if (ebone_mirr)
+ ebone_mirr->flag |= (curBone->flag & flag);
+ }
+ }
+ }
+ }
}
void armature_select_mirrored(bArmature *arm)
{
- armature_select_mirrored_ex(arm, BONE_SELECTED);
+ armature_select_mirrored_ex(arm, BONE_SELECTED);
}
void armature_tag_select_mirrored(bArmature *arm)
{
- EditBone *curBone;
-
- /* always untag */
- for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
- curBone->flag &= ~BONE_DONE;
- }
-
- /* Select mirrored bones */
- if (arm->flag & ARM_MIRROR_EDIT) {
- for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
- if (arm->layer & curBone->layer) {
- if (curBone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) {
- EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone);
- if (ebone_mirr && (ebone_mirr->flag & BONE_SELECTED) == 0) {
- ebone_mirr->flag |= BONE_DONE;
- }
- }
- }
- }
-
- for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
- if (curBone->flag & BONE_DONE) {
- EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone);
- curBone->flag |= ebone_mirr->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
- }
- }
- }
+ EditBone *curBone;
+
+ /* always untag */
+ for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
+ curBone->flag &= ~BONE_DONE;
+ }
+
+ /* Select mirrored bones */
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
+ if (arm->layer & curBone->layer) {
+ if (curBone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) {
+ EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone);
+ if (ebone_mirr && (ebone_mirr->flag & BONE_SELECTED) == 0) {
+ ebone_mirr->flag |= BONE_DONE;
+ }
+ }
+ }
+ }
+
+ for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
+ if (curBone->flag & BONE_DONE) {
+ EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone);
+ curBone->flag |= ebone_mirr->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
+ }
+ }
+ }
}
/* only works when tagged */
void armature_tag_unselect(bArmature *arm)
{
- EditBone *curBone;
+ EditBone *curBone;
- for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
- if (curBone->flag & BONE_DONE) {
- curBone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL | BONE_DONE);
- }
- }
+ for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
+ if (curBone->flag & BONE_DONE) {
+ curBone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL | BONE_DONE);
+ }
+ }
}
/* ------------------------------------- */
@@ -365,186 +363,189 @@ void armature_tag_unselect(bArmature *arm)
/* context; editmode armature, with mirror editing enabled */
void ED_armature_edit_transform_mirror_update(Object *obedit)
{
- bArmature *arm = obedit->data;
- EditBone *ebo, *eboflip;
-
- for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
- /* no layer check, correct mirror is more important */
- if (ebo->flag & (BONE_TIPSEL | BONE_ROOTSEL)) {
- eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
-
- if (eboflip) {
- /* we assume X-axis flipping for now */
- if (ebo->flag & BONE_TIPSEL) {
- EditBone *children;
-
- eboflip->tail[0] = -ebo->tail[0];
- eboflip->tail[1] = ebo->tail[1];
- eboflip->tail[2] = ebo->tail[2];
- eboflip->rad_tail = ebo->rad_tail;
- eboflip->roll = -ebo->roll;
- eboflip->curveOutX = -ebo->curveOutX;
- eboflip->roll2 = -ebo->roll2;
-
- /* Also move connected children, in case children's name aren't mirrored properly */
- for (children = arm->edbo->first; children; children = children->next) {
- if (children->parent == eboflip && children->flag & BONE_CONNECTED) {
- copy_v3_v3(children->head, eboflip->tail);
- children->rad_head = ebo->rad_tail;
- }
- }
- }
- if (ebo->flag & BONE_ROOTSEL) {
- eboflip->head[0] = -ebo->head[0];
- eboflip->head[1] = ebo->head[1];
- eboflip->head[2] = ebo->head[2];
- eboflip->rad_head = ebo->rad_head;
- eboflip->roll = -ebo->roll;
- eboflip->curveInX = -ebo->curveInX;
- eboflip->roll1 = -ebo->roll1;
-
- /* Also move connected parent, in case parent's name isn't mirrored properly */
- if (eboflip->parent && eboflip->flag & BONE_CONNECTED) {
- EditBone *parent = eboflip->parent;
- copy_v3_v3(parent->tail, eboflip->head);
- parent->rad_tail = ebo->rad_head;
- }
- }
- if (ebo->flag & BONE_SELECTED) {
- eboflip->dist = ebo->dist;
- eboflip->roll = -ebo->roll;
- eboflip->xwidth = ebo->xwidth;
- eboflip->zwidth = ebo->zwidth;
-
- eboflip->curveInX = -ebo->curveInX;
- eboflip->curveOutX = -ebo->curveOutX;
- eboflip->roll1 = -ebo->roll1;
- eboflip->roll2 = -ebo->roll2;
- }
- }
- }
- }
+ bArmature *arm = obedit->data;
+ EditBone *ebo, *eboflip;
+
+ for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ /* no layer check, correct mirror is more important */
+ if (ebo->flag & (BONE_TIPSEL | BONE_ROOTSEL)) {
+ eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
+
+ if (eboflip) {
+ /* we assume X-axis flipping for now */
+ if (ebo->flag & BONE_TIPSEL) {
+ EditBone *children;
+
+ eboflip->tail[0] = -ebo->tail[0];
+ eboflip->tail[1] = ebo->tail[1];
+ eboflip->tail[2] = ebo->tail[2];
+ eboflip->rad_tail = ebo->rad_tail;
+ eboflip->roll = -ebo->roll;
+ eboflip->curveOutX = -ebo->curveOutX;
+ eboflip->roll2 = -ebo->roll2;
+
+ /* Also move connected children, in case children's name aren't mirrored properly */
+ for (children = arm->edbo->first; children; children = children->next) {
+ if (children->parent == eboflip && children->flag & BONE_CONNECTED) {
+ copy_v3_v3(children->head, eboflip->tail);
+ children->rad_head = ebo->rad_tail;
+ }
+ }
+ }
+ if (ebo->flag & BONE_ROOTSEL) {
+ eboflip->head[0] = -ebo->head[0];
+ eboflip->head[1] = ebo->head[1];
+ eboflip->head[2] = ebo->head[2];
+ eboflip->rad_head = ebo->rad_head;
+ eboflip->roll = -ebo->roll;
+ eboflip->curveInX = -ebo->curveInX;
+ eboflip->roll1 = -ebo->roll1;
+
+ /* Also move connected parent, in case parent's name isn't mirrored properly */
+ if (eboflip->parent && eboflip->flag & BONE_CONNECTED) {
+ EditBone *parent = eboflip->parent;
+ copy_v3_v3(parent->tail, eboflip->head);
+ parent->rad_tail = ebo->rad_head;
+ }
+ }
+ if (ebo->flag & BONE_SELECTED) {
+ eboflip->dist = ebo->dist;
+ eboflip->roll = -ebo->roll;
+ eboflip->xwidth = ebo->xwidth;
+ eboflip->zwidth = ebo->zwidth;
+
+ eboflip->curveInX = -ebo->curveInX;
+ eboflip->curveOutX = -ebo->curveOutX;
+ eboflip->roll1 = -ebo->roll1;
+ eboflip->roll2 = -ebo->roll2;
+ }
+ }
+ }
+ }
}
/* *************************************************************** */
/* 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)
-{
- EditBone *eBone;
- EditBone *eBoneAct = NULL;
- EditBone *eBoneTest = NULL;
- Bone *curBone;
-
- for (curBone = bones->first; curBone; curBone = curBone->next) {
- eBone = MEM_callocN(sizeof(EditBone), "make_editbone");
- eBone->temp.bone = curBone;
-
- /* Copy relevant data from bone to eBone
- * Keep selection logic in sync with ED_armature_edit_sync_selection.
- */
- eBone->parent = parent;
- BLI_strncpy(eBone->name, curBone->name, sizeof(eBone->name));
- eBone->flag = curBone->flag;
-
- /* fix selection flags */
- if (eBone->flag & BONE_SELECTED) {
- /* if the bone is selected the copy its root selection to the parents tip */
- eBone->flag |= BONE_TIPSEL;
- if (eBone->parent && (eBone->flag & BONE_CONNECTED)) {
- eBone->parent->flag |= BONE_TIPSEL;
- }
-
- /* For connected bones, take care when changing the selection when we have a connected parent,
- * this flag is a copy of '(eBone->parent->flag & BONE_TIPSEL)'. */
- eBone->flag |= BONE_ROOTSEL;
- }
- else {
- /* if the bone is not selected, but connected to its parent
- * always use the parents tip selection state */
- if (eBone->parent && (eBone->flag & BONE_CONNECTED)) {
- eBone->flag &= ~BONE_ROOTSEL;
- }
- }
-
- copy_v3_v3(eBone->head, curBone->arm_head);
- copy_v3_v3(eBone->tail, curBone->arm_tail);
- eBone->roll = curBone->arm_roll;
-
- /* rest of stuff copy */
- eBone->length = curBone->length;
- eBone->dist = curBone->dist;
- eBone->weight = curBone->weight;
- eBone->xwidth = curBone->xwidth;
- eBone->zwidth = curBone->zwidth;
- eBone->rad_head = curBone->rad_head;
- eBone->rad_tail = curBone->rad_tail;
- eBone->segments = curBone->segments;
- eBone->layer = curBone->layer;
-
- /* Bendy-Bone parameters */
- eBone->roll1 = curBone->roll1;
- eBone->roll2 = curBone->roll2;
- eBone->curveInX = curBone->curveInX;
- eBone->curveInY = curBone->curveInY;
- eBone->curveOutX = curBone->curveOutX;
- eBone->curveOutY = curBone->curveOutY;
- eBone->ease1 = curBone->ease1;
- eBone->ease2 = curBone->ease2;
- eBone->scaleIn = curBone->scaleIn;
- eBone->scaleOut = curBone->scaleOut;
-
- eBone->bbone_prev_type = curBone->bbone_prev_type;
- eBone->bbone_next_type = curBone->bbone_next_type;
-
- if (curBone->prop)
- eBone->prop = IDP_CopyProperty(curBone->prop);
-
- BLI_addtail(edbo, eBone);
-
- /* Add children if necessary */
- if (curBone->childbase.first) {
- eBoneTest = make_boneList_rec(edbo, &curBone->childbase, eBone, actBone);
- if (eBoneTest)
- eBoneAct = eBoneTest;
- }
-
- if (curBone == actBone)
- eBoneAct = eBone;
- }
-
- return eBoneAct;
+static EditBone *make_boneList_rec(ListBase *edbo,
+ ListBase *bones,
+ EditBone *parent,
+ Bone *actBone)
+{
+ EditBone *eBone;
+ EditBone *eBoneAct = NULL;
+ EditBone *eBoneTest = NULL;
+ Bone *curBone;
+
+ for (curBone = bones->first; curBone; curBone = curBone->next) {
+ eBone = MEM_callocN(sizeof(EditBone), "make_editbone");
+ eBone->temp.bone = curBone;
+
+ /* Copy relevant data from bone to eBone
+ * Keep selection logic in sync with ED_armature_edit_sync_selection.
+ */
+ eBone->parent = parent;
+ BLI_strncpy(eBone->name, curBone->name, sizeof(eBone->name));
+ eBone->flag = curBone->flag;
+
+ /* fix selection flags */
+ if (eBone->flag & BONE_SELECTED) {
+ /* if the bone is selected the copy its root selection to the parents tip */
+ eBone->flag |= BONE_TIPSEL;
+ if (eBone->parent && (eBone->flag & BONE_CONNECTED)) {
+ eBone->parent->flag |= BONE_TIPSEL;
+ }
+
+ /* For connected bones, take care when changing the selection when we have a connected parent,
+ * this flag is a copy of '(eBone->parent->flag & BONE_TIPSEL)'. */
+ eBone->flag |= BONE_ROOTSEL;
+ }
+ else {
+ /* if the bone is not selected, but connected to its parent
+ * always use the parents tip selection state */
+ if (eBone->parent && (eBone->flag & BONE_CONNECTED)) {
+ eBone->flag &= ~BONE_ROOTSEL;
+ }
+ }
+
+ copy_v3_v3(eBone->head, curBone->arm_head);
+ copy_v3_v3(eBone->tail, curBone->arm_tail);
+ eBone->roll = curBone->arm_roll;
+
+ /* rest of stuff copy */
+ eBone->length = curBone->length;
+ eBone->dist = curBone->dist;
+ eBone->weight = curBone->weight;
+ eBone->xwidth = curBone->xwidth;
+ eBone->zwidth = curBone->zwidth;
+ eBone->rad_head = curBone->rad_head;
+ eBone->rad_tail = curBone->rad_tail;
+ eBone->segments = curBone->segments;
+ eBone->layer = curBone->layer;
+
+ /* Bendy-Bone parameters */
+ eBone->roll1 = curBone->roll1;
+ eBone->roll2 = curBone->roll2;
+ eBone->curveInX = curBone->curveInX;
+ eBone->curveInY = curBone->curveInY;
+ eBone->curveOutX = curBone->curveOutX;
+ eBone->curveOutY = curBone->curveOutY;
+ eBone->ease1 = curBone->ease1;
+ eBone->ease2 = curBone->ease2;
+ eBone->scaleIn = curBone->scaleIn;
+ eBone->scaleOut = curBone->scaleOut;
+
+ eBone->bbone_prev_type = curBone->bbone_prev_type;
+ eBone->bbone_next_type = curBone->bbone_next_type;
+
+ if (curBone->prop)
+ eBone->prop = IDP_CopyProperty(curBone->prop);
+
+ BLI_addtail(edbo, eBone);
+
+ /* Add children if necessary */
+ if (curBone->childbase.first) {
+ eBoneTest = make_boneList_rec(edbo, &curBone->childbase, eBone, actBone);
+ if (eBoneTest)
+ eBoneAct = eBoneTest;
+ }
+
+ if (curBone == actBone)
+ eBoneAct = eBone;
+ }
+
+ return eBoneAct;
}
static EditBone *find_ebone_link(ListBase *edbo, Bone *link)
{
- if (link != NULL) {
- for (EditBone *ebone = edbo->first; ebone; ebone = ebone->next) {
- if (ebone->temp.bone == link) {
- return ebone;
- }
- }
- }
+ if (link != NULL) {
+ for (EditBone *ebone = edbo->first; ebone; ebone = ebone->next) {
+ if (ebone->temp.bone == link) {
+ return ebone;
+ }
+ }
+ }
- return NULL;
+ return NULL;
}
EditBone *make_boneList(ListBase *edbo, ListBase *bones, struct Bone *actBone)
{
- BLI_assert(!edbo->first && !edbo->last);
+ BLI_assert(!edbo->first && !edbo->last);
- EditBone *active = make_boneList_rec(edbo, bones, NULL, actBone);
+ EditBone *active = make_boneList_rec(edbo, bones, NULL, actBone);
- for (EditBone *ebone = edbo->first; ebone; ebone = ebone->next) {
- Bone *bone = ebone->temp.bone;
+ for (EditBone *ebone = edbo->first; ebone; ebone = ebone->next) {
+ Bone *bone = ebone->temp.bone;
- /* Convert custom B-Bone handle links. */
- ebone->bbone_prev = find_ebone_link(edbo, bone->bbone_prev);
- ebone->bbone_next = find_ebone_link(edbo, bone->bbone_next);
- }
+ /* Convert custom B-Bone handle links. */
+ ebone->bbone_prev = find_ebone_link(edbo, bone->bbone_prev);
+ ebone->bbone_next = find_ebone_link(edbo, bone->bbone_next);
+ }
- return active;
+ return active;
}
/**
@@ -559,217 +560,217 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, struct Bone *actBone)
*/
static void armature_finalize_restpose(ListBase *bonelist, ListBase *editbonelist)
{
- Bone *curBone;
- EditBone *ebone;
+ Bone *curBone;
+ EditBone *ebone;
- for (curBone = bonelist->first; curBone; curBone = curBone->next) {
- /* Set bone's local head/tail.
- * Note that it's important to use final parent's restpose (arm_mat) here, instead of setting those values
- * from editbone's matrix (see T46010). */
- if (curBone->parent) {
- float parmat_inv[4][4];
+ for (curBone = bonelist->first; curBone; curBone = curBone->next) {
+ /* Set bone's local head/tail.
+ * Note that it's important to use final parent's restpose (arm_mat) here, instead of setting those values
+ * from editbone's matrix (see T46010). */
+ if (curBone->parent) {
+ float parmat_inv[4][4];
- invert_m4_m4(parmat_inv, curBone->parent->arm_mat);
+ invert_m4_m4(parmat_inv, curBone->parent->arm_mat);
- /* Get the new head and tail */
- sub_v3_v3v3(curBone->head, curBone->arm_head, curBone->parent->arm_tail);
- sub_v3_v3v3(curBone->tail, curBone->arm_tail, curBone->parent->arm_tail);
+ /* Get the new head and tail */
+ sub_v3_v3v3(curBone->head, curBone->arm_head, curBone->parent->arm_tail);
+ sub_v3_v3v3(curBone->tail, curBone->arm_tail, curBone->parent->arm_tail);
- mul_mat3_m4_v3(parmat_inv, curBone->head);
- mul_mat3_m4_v3(parmat_inv, curBone->tail);
- }
- else {
- copy_v3_v3(curBone->head, curBone->arm_head);
- copy_v3_v3(curBone->tail, curBone->arm_tail);
- }
+ mul_mat3_m4_v3(parmat_inv, curBone->head);
+ mul_mat3_m4_v3(parmat_inv, curBone->tail);
+ }
+ else {
+ copy_v3_v3(curBone->head, curBone->arm_head);
+ copy_v3_v3(curBone->tail, curBone->arm_tail);
+ }
- /* Set local matrix and arm_mat (restpose).
- * Do not recurse into children here, armature_finalize_restpose() is already recursive. */
- BKE_armature_where_is_bone(curBone, curBone->parent, false);
+ /* Set local matrix and arm_mat (restpose).
+ * Do not recurse into children here, armature_finalize_restpose() is already recursive. */
+ BKE_armature_where_is_bone(curBone, curBone->parent, false);
- /* Find the associated editbone */
- for (ebone = editbonelist->first; ebone; ebone = ebone->next) {
- if (ebone->temp.bone == curBone) {
- float premat[3][3];
- float postmat[3][3];
- float difmat[3][3];
- float imat[3][3];
+ /* Find the associated editbone */
+ for (ebone = editbonelist->first; ebone; ebone = ebone->next) {
+ if (ebone->temp.bone == curBone) {
+ float premat[3][3];
+ float postmat[3][3];
+ float difmat[3][3];
+ float imat[3][3];
- /* Get the ebone premat and its inverse. */
- ED_armature_ebone_to_mat3(ebone, premat);
- invert_m3_m3(imat, premat);
+ /* Get the ebone premat and its inverse. */
+ ED_armature_ebone_to_mat3(ebone, premat);
+ invert_m3_m3(imat, premat);
- /* Get the bone postmat. */
- copy_m3_m4(postmat, curBone->arm_mat);
+ /* Get the bone postmat. */
+ copy_m3_m4(postmat, curBone->arm_mat);
- mul_m3_m3m3(difmat, imat, postmat);
+ mul_m3_m3m3(difmat, imat, postmat);
#if 0
- printf("Bone %s\n", curBone->name);
- print_m4("premat", premat);
- print_m4("postmat", postmat);
- print_m4("difmat", difmat);
- printf("Roll = %f\n", RAD2DEGF(-atan2(difmat[2][0], difmat[2][2])));
+ printf("Bone %s\n", curBone->name);
+ print_m4("premat", premat);
+ print_m4("postmat", postmat);
+ print_m4("difmat", difmat);
+ printf("Roll = %f\n", RAD2DEGF(-atan2(difmat[2][0], difmat[2][2])));
#endif
- curBone->roll = -atan2f(difmat[2][0], difmat[2][2]);
+ curBone->roll = -atan2f(difmat[2][0], difmat[2][2]);
- /* and set restposition again */
- BKE_armature_where_is_bone(curBone, curBone->parent, false);
- break;
- }
- }
+ /* and set restposition again */
+ BKE_armature_where_is_bone(curBone, curBone->parent, false);
+ break;
+ }
+ }
- /* Recurse into children... */
- armature_finalize_restpose(&curBone->childbase, editbonelist);
- }
+ /* Recurse into children... */
+ armature_finalize_restpose(&curBone->childbase, editbonelist);
+ }
}
/* put EditMode back in Object */
void ED_armature_from_edit(Main *bmain, bArmature *arm)
{
- EditBone *eBone, *neBone;
- Bone *newBone;
- Object *obt;
-
- /* armature bones */
- BKE_armature_bonelist_free(&arm->bonebase);
- arm->act_bone = NULL;
-
- /* remove zero sized bones, this gives unstable restposes */
- 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? */
- EditBone *fBone;
-
- /* Find any bones that refer to this bone */
- for (fBone = arm->edbo->first; fBone; fBone = fBone->next) {
- if (fBone->parent == eBone)
- fBone->parent = eBone->parent;
- }
- if (G.debug & G_DEBUG)
- printf("Warning: removed zero sized bone: %s\n", eBone->name);
- bone_free(arm, eBone);
- }
- }
-
- /* Copy the bones from the editData 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 */
-
- BLI_strncpy(newBone->name, eBone->name, sizeof(newBone->name));
- copy_v3_v3(newBone->arm_head, eBone->head);
- copy_v3_v3(newBone->arm_tail, eBone->tail);
- newBone->arm_roll = eBone->roll;
-
- newBone->flag = eBone->flag;
-
- if (eBone == arm->act_edbone) {
- /* don't change active selection, this messes up separate which uses
- * editmode toggle and can separate active bone which is de-selected originally */
-
- /* important, editbones can be active with only 1 point selected */
- /* newBone->flag |= BONE_SELECTED; */
- arm->act_bone = newBone;
- }
- newBone->roll = 0.0f;
-
- newBone->weight = eBone->weight;
- newBone->dist = eBone->dist;
-
- newBone->xwidth = eBone->xwidth;
- newBone->zwidth = eBone->zwidth;
- newBone->rad_head = eBone->rad_head;
- newBone->rad_tail = eBone->rad_tail;
- newBone->segments = eBone->segments;
- newBone->layer = eBone->layer;
-
- /* Bendy-Bone parameters */
- newBone->roll1 = eBone->roll1;
- newBone->roll2 = eBone->roll2;
- newBone->curveInX = eBone->curveInX;
- newBone->curveInY = eBone->curveInY;
- newBone->curveOutX = eBone->curveOutX;
- newBone->curveOutY = eBone->curveOutY;
- newBone->ease1 = eBone->ease1;
- newBone->ease2 = eBone->ease2;
- newBone->scaleIn = eBone->scaleIn;
- newBone->scaleOut = eBone->scaleOut;
-
- newBone->bbone_prev_type = eBone->bbone_prev_type;
- newBone->bbone_next_type = eBone->bbone_next_type;
-
- if (eBone->prop)
- newBone->prop = IDP_CopyProperty(eBone->prop);
- }
-
- /* Fix parenting in a separate pass to ensure ebone->bone connections are valid at this point.
- * Do not set bone->head/tail here anymore,
- * using EditBone data for that is not OK since our later fiddling with parent's arm_mat
- * (for roll conversion) may have some small but visible impact on locations (T46010). */
- for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
- newBone = eBone->temp.bone;
- if (eBone->parent) {
- newBone->parent = eBone->parent->temp.bone;
- BLI_addtail(&newBone->parent->childbase, newBone);
- }
- /* ...otherwise add this bone to the armature's bonebase */
- else {
- BLI_addtail(&arm->bonebase, newBone);
- }
-
- /* Also transfer B-Bone custom handles. */
- if (eBone->bbone_prev) {
- newBone->bbone_prev = eBone->bbone_prev->temp.bone;
- }
- if (eBone->bbone_next) {
- newBone->bbone_next = eBone->bbone_next->temp.bone;
- }
- }
-
- /* Finalize definition of restpose data (roll, bone_mat, arm_mat, head/tail...). */
- armature_finalize_restpose(&arm->bonebase, arm->edbo);
-
- /* so all users of this armature should get rebuilt */
- for (obt = bmain->objects.first; obt; obt = obt->id.next) {
- if (obt->data == arm) {
- BKE_pose_rebuild(bmain, obt, arm, true);
- }
- }
-
- DEG_id_tag_update(&arm->id, 0);
+ EditBone *eBone, *neBone;
+ Bone *newBone;
+ Object *obt;
+
+ /* armature bones */
+ BKE_armature_bonelist_free(&arm->bonebase);
+ arm->act_bone = NULL;
+
+ /* remove zero sized bones, this gives unstable restposes */
+ 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? */
+ EditBone *fBone;
+
+ /* Find any bones that refer to this bone */
+ for (fBone = arm->edbo->first; fBone; fBone = fBone->next) {
+ if (fBone->parent == eBone)
+ fBone->parent = eBone->parent;
+ }
+ if (G.debug & G_DEBUG)
+ printf("Warning: removed zero sized bone: %s\n", eBone->name);
+ bone_free(arm, eBone);
+ }
+ }
+
+ /* Copy the bones from the editData 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 */
+
+ BLI_strncpy(newBone->name, eBone->name, sizeof(newBone->name));
+ copy_v3_v3(newBone->arm_head, eBone->head);
+ copy_v3_v3(newBone->arm_tail, eBone->tail);
+ newBone->arm_roll = eBone->roll;
+
+ newBone->flag = eBone->flag;
+
+ if (eBone == arm->act_edbone) {
+ /* don't change active selection, this messes up separate which uses
+ * editmode toggle and can separate active bone which is de-selected originally */
+
+ /* important, editbones can be active with only 1 point selected */
+ /* newBone->flag |= BONE_SELECTED; */
+ arm->act_bone = newBone;
+ }
+ newBone->roll = 0.0f;
+
+ newBone->weight = eBone->weight;
+ newBone->dist = eBone->dist;
+
+ newBone->xwidth = eBone->xwidth;
+ newBone->zwidth = eBone->zwidth;
+ newBone->rad_head = eBone->rad_head;
+ newBone->rad_tail = eBone->rad_tail;
+ newBone->segments = eBone->segments;
+ newBone->layer = eBone->layer;
+
+ /* Bendy-Bone parameters */
+ newBone->roll1 = eBone->roll1;
+ newBone->roll2 = eBone->roll2;
+ newBone->curveInX = eBone->curveInX;
+ newBone->curveInY = eBone->curveInY;
+ newBone->curveOutX = eBone->curveOutX;
+ newBone->curveOutY = eBone->curveOutY;
+ newBone->ease1 = eBone->ease1;
+ newBone->ease2 = eBone->ease2;
+ newBone->scaleIn = eBone->scaleIn;
+ newBone->scaleOut = eBone->scaleOut;
+
+ newBone->bbone_prev_type = eBone->bbone_prev_type;
+ newBone->bbone_next_type = eBone->bbone_next_type;
+
+ if (eBone->prop)
+ newBone->prop = IDP_CopyProperty(eBone->prop);
+ }
+
+ /* Fix parenting in a separate pass to ensure ebone->bone connections are valid at this point.
+ * Do not set bone->head/tail here anymore,
+ * using EditBone data for that is not OK since our later fiddling with parent's arm_mat
+ * (for roll conversion) may have some small but visible impact on locations (T46010). */
+ for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
+ newBone = eBone->temp.bone;
+ if (eBone->parent) {
+ newBone->parent = eBone->parent->temp.bone;
+ BLI_addtail(&newBone->parent->childbase, newBone);
+ }
+ /* ...otherwise add this bone to the armature's bonebase */
+ else {
+ BLI_addtail(&arm->bonebase, newBone);
+ }
+
+ /* Also transfer B-Bone custom handles. */
+ if (eBone->bbone_prev) {
+ newBone->bbone_prev = eBone->bbone_prev->temp.bone;
+ }
+ if (eBone->bbone_next) {
+ newBone->bbone_next = eBone->bbone_next->temp.bone;
+ }
+ }
+
+ /* Finalize definition of restpose data (roll, bone_mat, arm_mat, head/tail...). */
+ armature_finalize_restpose(&arm->bonebase, arm->edbo);
+
+ /* so all users of this armature should get rebuilt */
+ for (obt = bmain->objects.first; obt; obt = obt->id.next) {
+ if (obt->data == arm) {
+ BKE_pose_rebuild(bmain, obt, arm, true);
+ }
+ }
+
+ DEG_id_tag_update(&arm->id, 0);
}
void ED_armature_edit_free(struct bArmature *arm)
{
- EditBone *eBone;
+ EditBone *eBone;
- /* Clear the editbones list */
- if (arm->edbo) {
- if (arm->edbo->first) {
- for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
- if (eBone->prop) {
- IDP_FreeProperty(eBone->prop);
- MEM_freeN(eBone->prop);
- }
- }
+ /* Clear the editbones list */
+ if (arm->edbo) {
+ if (arm->edbo->first) {
+ for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
+ if (eBone->prop) {
+ IDP_FreeProperty(eBone->prop);
+ MEM_freeN(eBone->prop);
+ }
+ }
- BLI_freelistN(arm->edbo);
- }
- MEM_freeN(arm->edbo);
- arm->edbo = NULL;
- arm->act_edbone = NULL;
- }
+ BLI_freelistN(arm->edbo);
+ }
+ MEM_freeN(arm->edbo);
+ arm->edbo = NULL;
+ arm->act_edbone = NULL;
+ }
}
/* Put armature in EditMode */
void ED_armature_to_edit(bArmature *arm)
{
- ED_armature_edit_free(arm);
- arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature");
- arm->act_edbone = make_boneList(arm->edbo, &arm->bonebase, arm->act_bone);
+ ED_armature_edit_free(arm);
+ arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature");
+ arm->act_edbone = make_boneList(arm->edbo, &arm->bonebase, arm->act_bone);
}
/* *************************************************************** */
@@ -779,59 +780,59 @@ void ED_armature_to_edit(bArmature *arm)
void ED_armature_ebone_listbase_free(ListBase *lb)
{
- EditBone *ebone, *ebone_next;
+ EditBone *ebone, *ebone_next;
- for (ebone = lb->first; ebone; ebone = ebone_next) {
- ebone_next = ebone->next;
+ for (ebone = lb->first; ebone; ebone = ebone_next) {
+ ebone_next = ebone->next;
- if (ebone->prop) {
- IDP_FreeProperty(ebone->prop);
- MEM_freeN(ebone->prop);
- }
+ if (ebone->prop) {
+ IDP_FreeProperty(ebone->prop);
+ MEM_freeN(ebone->prop);
+ }
- MEM_freeN(ebone);
- }
+ MEM_freeN(ebone);
+ }
- BLI_listbase_clear(lb);
+ BLI_listbase_clear(lb);
}
void ED_armature_ebone_listbase_copy(ListBase *lb_dst, ListBase *lb_src)
{
- EditBone *ebone_src;
- EditBone *ebone_dst;
-
- BLI_assert(BLI_listbase_is_empty(lb_dst));
-
- for (ebone_src = lb_src->first; ebone_src; ebone_src = ebone_src->next) {
- ebone_dst = MEM_dupallocN(ebone_src);
- if (ebone_dst->prop) {
- ebone_dst->prop = IDP_CopyProperty(ebone_dst->prop);
- }
- ebone_src->temp.ebone = ebone_dst;
- BLI_addtail(lb_dst, ebone_dst);
- }
-
- /* set pointers */
- for (ebone_dst = lb_dst->first; ebone_dst; ebone_dst = ebone_dst->next) {
- if (ebone_dst->parent) {
- ebone_dst->parent = ebone_dst->parent->temp.ebone;
- }
- if (ebone_dst->bbone_next) {
- ebone_dst->bbone_next = ebone_dst->bbone_next->temp.ebone;
- }
- if (ebone_dst->bbone_prev) {
- ebone_dst->bbone_prev = ebone_dst->bbone_prev->temp.ebone;
- }
- }
+ EditBone *ebone_src;
+ EditBone *ebone_dst;
+
+ BLI_assert(BLI_listbase_is_empty(lb_dst));
+
+ for (ebone_src = lb_src->first; ebone_src; ebone_src = ebone_src->next) {
+ ebone_dst = MEM_dupallocN(ebone_src);
+ if (ebone_dst->prop) {
+ ebone_dst->prop = IDP_CopyProperty(ebone_dst->prop);
+ }
+ ebone_src->temp.ebone = ebone_dst;
+ BLI_addtail(lb_dst, ebone_dst);
+ }
+
+ /* set pointers */
+ for (ebone_dst = lb_dst->first; ebone_dst; ebone_dst = ebone_dst->next) {
+ if (ebone_dst->parent) {
+ ebone_dst->parent = ebone_dst->parent->temp.ebone;
+ }
+ if (ebone_dst->bbone_next) {
+ ebone_dst->bbone_next = ebone_dst->bbone_next->temp.ebone;
+ }
+ if (ebone_dst->bbone_prev) {
+ ebone_dst->bbone_prev = ebone_dst->bbone_prev->temp.ebone;
+ }
+ }
}
void ED_armature_ebone_listbase_temp_clear(ListBase *lb)
{
- EditBone *ebone;
- /* be sure they don't hang ever */
- for (ebone = lb->first; ebone; ebone = ebone->next) {
- ebone->temp.p = NULL;
- }
+ EditBone *ebone;
+ /* be sure they don't hang ever */
+ for (ebone = lb->first; ebone; ebone = ebone->next) {
+ ebone->temp.p = NULL;
+ }
}
/* *************************************************************** */
@@ -841,54 +842,54 @@ void ED_armature_ebone_listbase_temp_clear(ListBase *lb)
int ED_armature_ebone_selectflag_get(const EditBone *ebone)
{
- if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
- return ((ebone->flag & (BONE_SELECTED | BONE_TIPSEL)) |
- ((ebone->parent->flag & BONE_TIPSEL) ? BONE_ROOTSEL : 0));
- }
- else {
- return (ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL));
- }
+ if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+ return ((ebone->flag & (BONE_SELECTED | BONE_TIPSEL)) |
+ ((ebone->parent->flag & BONE_TIPSEL) ? BONE_ROOTSEL : 0));
+ }
+ else {
+ return (ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL));
+ }
}
void ED_armature_ebone_selectflag_set(EditBone *ebone, int flag)
{
- flag = flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
+ flag = flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
- if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
- ebone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
- ebone->parent->flag &= ~BONE_TIPSEL;
+ if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+ ebone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
+ ebone->parent->flag &= ~BONE_TIPSEL;
- ebone->flag |= flag;
- ebone->parent->flag |= (flag & BONE_ROOTSEL) ? BONE_TIPSEL : 0;
- }
- else {
- ebone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
- ebone->flag |= flag;
- }
+ ebone->flag |= flag;
+ ebone->parent->flag |= (flag & BONE_ROOTSEL) ? BONE_TIPSEL : 0;
+ }
+ else {
+ ebone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
+ ebone->flag |= flag;
+ }
}
void ED_armature_ebone_selectflag_enable(EditBone *ebone, int flag)
{
- BLI_assert((flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) != 0);
- ED_armature_ebone_selectflag_set(ebone, ebone->flag | flag);
+ BLI_assert((flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) != 0);
+ ED_armature_ebone_selectflag_set(ebone, ebone->flag | flag);
}
void ED_armature_ebone_selectflag_disable(EditBone *ebone, int flag)
{
- BLI_assert((flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) != 0);
- ED_armature_ebone_selectflag_set(ebone, ebone->flag & ~flag);
+ BLI_assert((flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) != 0);
+ ED_armature_ebone_selectflag_set(ebone, ebone->flag & ~flag);
}
/* could be used in more places */
void ED_armature_ebone_select_set(EditBone *ebone, bool select)
{
- int flag;
- if (select) {
- BLI_assert((ebone->flag & BONE_UNSELECTABLE) == 0);
- flag = (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else {
- flag = 0;
- }
- ED_armature_ebone_selectflag_set(ebone, flag);
+ int flag;
+ if (select) {
+ BLI_assert((ebone->flag & BONE_UNSELECTABLE) == 0);
+ flag = (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else {
+ flag = 0;
+ }
+ ED_armature_ebone_selectflag_set(ebone, flag);
}
diff --git a/source/blender/editors/armature/editarmature_undo.c b/source/blender/editors/armature/editarmature_undo.c
index 39e8371a824..3a2440af2da 100644
--- a/source/blender/editors/armature/editarmature_undo.c
+++ b/source/blender/editors/armature/editarmature_undo.c
@@ -23,7 +23,6 @@
#include "MEM_guardedalloc.h"
-
#include "CLG_log.h"
#include "DNA_armature_types.h"
@@ -53,69 +52,69 @@ static CLG_LogRef LOG = {"ed.undo.armature"};
* \{ */
typedef struct UndoArmature {
- EditBone *act_edbone;
- ListBase lb;
- size_t undo_size;
+ EditBone *act_edbone;
+ ListBase lb;
+ size_t undo_size;
} UndoArmature;
static void undoarm_to_editarm(UndoArmature *uarm, bArmature *arm)
{
- EditBone *ebone;
+ EditBone *ebone;
- ED_armature_ebone_listbase_free(arm->edbo);
- ED_armature_ebone_listbase_copy(arm->edbo, &uarm->lb);
+ ED_armature_ebone_listbase_free(arm->edbo);
+ ED_armature_ebone_listbase_copy(arm->edbo, &uarm->lb);
- /* active bone */
- if (uarm->act_edbone) {
- ebone = uarm->act_edbone;
- arm->act_edbone = ebone->temp.ebone;
- }
- else {
- arm->act_edbone = NULL;
- }
+ /* active bone */
+ if (uarm->act_edbone) {
+ ebone = uarm->act_edbone;
+ arm->act_edbone = ebone->temp.ebone;
+ }
+ else {
+ arm->act_edbone = NULL;
+ }
- ED_armature_ebone_listbase_temp_clear(arm->edbo);
+ ED_armature_ebone_listbase_temp_clear(arm->edbo);
}
static void *undoarm_from_editarm(UndoArmature *uarm, bArmature *arm)
{
- BLI_assert(BLI_array_is_zeroed(uarm, 1));
+ BLI_assert(BLI_array_is_zeroed(uarm, 1));
- /* TODO: include size of ID-properties. */
- uarm->undo_size = 0;
+ /* TODO: include size of ID-properties. */
+ uarm->undo_size = 0;
- ED_armature_ebone_listbase_copy(&uarm->lb, arm->edbo);
+ ED_armature_ebone_listbase_copy(&uarm->lb, arm->edbo);
- /* active bone */
- if (arm->act_edbone) {
- EditBone *ebone = arm->act_edbone;
- uarm->act_edbone = ebone->temp.ebone;
- }
+ /* active bone */
+ if (arm->act_edbone) {
+ EditBone *ebone = arm->act_edbone;
+ uarm->act_edbone = ebone->temp.ebone;
+ }
- ED_armature_ebone_listbase_temp_clear(&uarm->lb);
+ ED_armature_ebone_listbase_temp_clear(&uarm->lb);
- for (EditBone *ebone = uarm->lb.first; ebone; ebone = ebone->next) {
- uarm->undo_size += sizeof(EditBone);
- }
+ for (EditBone *ebone = uarm->lb.first; ebone; ebone = ebone->next) {
+ uarm->undo_size += sizeof(EditBone);
+ }
- return uarm;
+ return uarm;
}
static void undoarm_free_data(UndoArmature *uarm)
{
- ED_armature_ebone_listbase_free(&uarm->lb);
+ ED_armature_ebone_listbase_free(&uarm->lb);
}
static Object *editarm_object_from_context(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_ARMATURE) {
- bArmature *arm = obedit->data;
- if (arm->edbo != NULL) {
- return obedit;
- }
- }
- return NULL;
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_ARMATURE) {
+ bArmature *arm = obedit->data;
+ if (arm->edbo != NULL) {
+ return obedit;
+ }
+ }
+ return NULL;
}
/** \} */
@@ -127,112 +126,124 @@ static Object *editarm_object_from_context(bContext *C)
* \{ */
typedef struct ArmatureUndoStep_Elem {
- struct ArmatureUndoStep_Elem *next, *prev;
- UndoRefID_Object obedit_ref;
- UndoArmature data;
+ struct ArmatureUndoStep_Elem *next, *prev;
+ UndoRefID_Object obedit_ref;
+ UndoArmature data;
} ArmatureUndoStep_Elem;
typedef struct ArmatureUndoStep {
- UndoStep step;
- ArmatureUndoStep_Elem *elems;
- uint elems_len;
+ UndoStep step;
+ ArmatureUndoStep_Elem *elems;
+ uint elems_len;
} ArmatureUndoStep;
static bool armature_undosys_poll(bContext *C)
{
- return editarm_object_from_context(C) != NULL;
+ return editarm_object_from_context(C) != NULL;
}
-static bool armature_undosys_step_encode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p)
+static bool armature_undosys_step_encode(struct bContext *C,
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p)
{
- ArmatureUndoStep *us = (ArmatureUndoStep *)us_p;
-
- /* Important not to use the 3D view when getting objects because all objects
- * 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);
-
- us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
- us->elems_len = objects_len;
-
- for (uint i = 0; i < objects_len; i++) {
- Object *ob = objects[i];
- ArmatureUndoStep_Elem *elem = &us->elems[i];
-
- elem->obedit_ref.ptr = ob;
- bArmature *arm = elem->obedit_ref.ptr->data;
- undoarm_from_editarm(&elem->data, arm);
- us->step.data_size += elem->data.undo_size;
- }
- MEM_freeN(objects);
- return true;
+ ArmatureUndoStep *us = (ArmatureUndoStep *)us_p;
+
+ /* Important not to use the 3D view when getting objects because all objects
+ * 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);
+
+ us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
+ us->elems_len = objects_len;
+
+ for (uint i = 0; i < objects_len; i++) {
+ Object *ob = objects[i];
+ ArmatureUndoStep_Elem *elem = &us->elems[i];
+
+ elem->obedit_ref.ptr = ob;
+ bArmature *arm = elem->obedit_ref.ptr->data;
+ undoarm_from_editarm(&elem->data, arm);
+ us->step.data_size += elem->data.undo_size;
+ }
+ MEM_freeN(objects);
+ return true;
}
-static void armature_undosys_step_decode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p, int UNUSED(dir))
+static void armature_undosys_step_decode(struct bContext *C,
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p,
+ int UNUSED(dir))
{
- ArmatureUndoStep *us = (ArmatureUndoStep *)us_p;
-
- /* Load all our objects into edit-mode, clear everything else. */
- ED_undo_object_editmode_restore_helper(C, &us->elems[0].obedit_ref.ptr, us->elems_len, sizeof(*us->elems));
-
- BLI_assert(armature_undosys_poll(C));
-
- for (uint i = 0; i < us->elems_len; i++) {
- ArmatureUndoStep_Elem *elem = &us->elems[i];
- Object *obedit = elem->obedit_ref.ptr;
- bArmature *arm = obedit->data;
- if (arm->edbo == NULL) {
- /* Should never fail, may not crash but can give odd behavior. */
- CLOG_ERROR(&LOG, "name='%s', failed to enter edit-mode for object '%s', undo state invalid", us_p->name, obedit->id.name);
- continue;
- }
- undoarm_to_editarm(&elem->data, arm);
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
-
- /* The first element is always active */
- ED_undo_object_set_active_or_warn(CTX_data_view_layer(C), us->elems[0].obedit_ref.ptr, us_p->name, &LOG);
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+ ArmatureUndoStep *us = (ArmatureUndoStep *)us_p;
+
+ /* Load all our objects into edit-mode, clear everything else. */
+ ED_undo_object_editmode_restore_helper(
+ C, &us->elems[0].obedit_ref.ptr, us->elems_len, sizeof(*us->elems));
+
+ BLI_assert(armature_undosys_poll(C));
+
+ for (uint i = 0; i < us->elems_len; i++) {
+ ArmatureUndoStep_Elem *elem = &us->elems[i];
+ Object *obedit = elem->obedit_ref.ptr;
+ bArmature *arm = obedit->data;
+ if (arm->edbo == NULL) {
+ /* Should never fail, may not crash but can give odd behavior. */
+ CLOG_ERROR(&LOG,
+ "name='%s', failed to enter edit-mode for object '%s', undo state invalid",
+ us_p->name,
+ obedit->id.name);
+ continue;
+ }
+ undoarm_to_editarm(&elem->data, arm);
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ }
+
+ /* The first element is always active */
+ ED_undo_object_set_active_or_warn(
+ CTX_data_view_layer(C), us->elems[0].obedit_ref.ptr, us_p->name, &LOG);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
}
static void armature_undosys_step_free(UndoStep *us_p)
{
- ArmatureUndoStep *us = (ArmatureUndoStep *)us_p;
+ ArmatureUndoStep *us = (ArmatureUndoStep *)us_p;
- for (uint i = 0; i < us->elems_len; i++) {
- ArmatureUndoStep_Elem *elem = &us->elems[i];
- undoarm_free_data(&elem->data);
- }
- MEM_freeN(us->elems);
+ for (uint i = 0; i < us->elems_len; i++) {
+ ArmatureUndoStep_Elem *elem = &us->elems[i];
+ undoarm_free_data(&elem->data);
+ }
+ MEM_freeN(us->elems);
}
-static void armature_undosys_foreach_ID_ref(
- UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+static void armature_undosys_foreach_ID_ref(UndoStep *us_p,
+ UndoTypeForEachIDRefFn foreach_ID_ref_fn,
+ void *user_data)
{
- ArmatureUndoStep *us = (ArmatureUndoStep *)us_p;
+ ArmatureUndoStep *us = (ArmatureUndoStep *)us_p;
- for (uint i = 0; i < us->elems_len; i++) {
- ArmatureUndoStep_Elem *elem = &us->elems[i];
- foreach_ID_ref_fn(user_data, ((UndoRefID *)&elem->obedit_ref));
- }
+ for (uint i = 0; i < us->elems_len; i++) {
+ ArmatureUndoStep_Elem *elem = &us->elems[i];
+ foreach_ID_ref_fn(user_data, ((UndoRefID *)&elem->obedit_ref));
+ }
}
/* Export for ED_undo_sys. */
void ED_armature_undosys_type(UndoType *ut)
{
- ut->name = "Edit Armature";
- ut->poll = armature_undosys_poll;
- ut->step_encode = armature_undosys_step_encode;
- ut->step_decode = armature_undosys_step_decode;
- ut->step_free = armature_undosys_step_free;
+ ut->name = "Edit Armature";
+ ut->poll = armature_undosys_poll;
+ ut->step_encode = armature_undosys_step_encode;
+ ut->step_decode = armature_undosys_step_decode;
+ ut->step_free = armature_undosys_step_free;
- ut->step_foreach_ID_ref = armature_undosys_foreach_ID_ref;
+ ut->step_foreach_ID_ref = armature_undosys_foreach_ID_ref;
- ut->use_context = true;
+ ut->use_context = true;
- ut->step_size = sizeof(ArmatureUndoStep);
+ ut->step_size = sizeof(ArmatureUndoStep);
}
/** \} */
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 66bd7a8db80..febe2a49174 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -49,53 +49,63 @@
#include "meshlaplacian.h"
/* ************* XXX *************** */
-static void waitcursor(int UNUSED(val)) {}
-static void progress_bar(int UNUSED(dummy_val), const char *UNUSED(dummy)) {}
-static void start_progress_bar(void) {}
-static void end_progress_bar(void) {}
-static void error(const char *str) { printf("error: %s\n", str); }
+static void waitcursor(int UNUSED(val))
+{
+}
+static void progress_bar(int UNUSED(dummy_val), const char *UNUSED(dummy))
+{
+}
+static void start_progress_bar(void)
+{
+}
+static void end_progress_bar(void)
+{
+}
+static void error(const char *str)
+{
+ printf("error: %s\n", str);
+}
/* ************* XXX *************** */
-
/************************** Laplacian System *****************************/
struct LaplacianSystem {
- LinearSolver *context; /* linear solver */
-
- int totvert, totface;
-
- float **verts; /* vertex coordinates */
- float *varea; /* vertex weights for laplacian computation */
- char *vpinned; /* vertex pinning */
- int (*faces)[3]; /* face vertex indices */
- float (*fweights)[3]; /* cotangent weights per face */
-
- int areaweights; /* use area in cotangent weights? */
- int storeweights; /* store cotangent weights in fweights */
- bool variablesdone; /* variables set in linear system */
-
- EdgeHash *edgehash; /* edge hash for construction */
-
- struct HeatWeighting {
- const MLoopTri *mlooptri;
- const MLoop *mloop; /* needed to find vertices by index */
- int totvert;
- int tottri;
- float (*verts)[3]; /* vertex coordinates */
- float (*vnors)[3]; /* vertex normals */
-
- float (*root)[3]; /* bone root */
- float (*tip)[3]; /* bone tip */
- float (*source)[3]; /* vertex source */
- int numsource;
-
- float *H; /* diagonal H matrix */
- float *p; /* values from all p vectors */
- float *mindist; /* minimum distance to a bone for all vertices */
-
- BVHTree *bvhtree; /* ray tracing acceleration structure */
- const MLoopTri **vltree; /* a looptri that the vertex belongs to */
- } heat;
+ LinearSolver *context; /* linear solver */
+
+ int totvert, totface;
+
+ float **verts; /* vertex coordinates */
+ float *varea; /* vertex weights for laplacian computation */
+ char *vpinned; /* vertex pinning */
+ int (*faces)[3]; /* face vertex indices */
+ float (*fweights)[3]; /* cotangent weights per face */
+
+ int areaweights; /* use area in cotangent weights? */
+ int storeweights; /* store cotangent weights in fweights */
+ bool variablesdone; /* variables set in linear system */
+
+ EdgeHash *edgehash; /* edge hash for construction */
+
+ struct HeatWeighting {
+ const MLoopTri *mlooptri;
+ const MLoop *mloop; /* needed to find vertices by index */
+ int totvert;
+ int tottri;
+ float (*verts)[3]; /* vertex coordinates */
+ float (*vnors)[3]; /* vertex normals */
+
+ float (*root)[3]; /* bone root */
+ float (*tip)[3]; /* bone tip */
+ float (*source)[3]; /* vertex source */
+ int numsource;
+
+ float *H; /* diagonal H matrix */
+ float *p; /* values from all p vectors */
+ float *mindist; /* minimum distance to a bone for all vertices */
+
+ BVHTree *bvhtree; /* ray tracing acceleration structure */
+ const MLoopTri **vltree; /* a looptri that the vertex belongs to */
+ } heat;
};
/* Laplacian matrix construction */
@@ -110,676 +120,685 @@ struct LaplacianSystem {
static void laplacian_increase_edge_count(EdgeHash *edgehash, int v1, int v2)
{
- void **p;
+ void **p;
- if (BLI_edgehash_ensure_p(edgehash, v1, v2, &p))
- *p = (void *)((intptr_t)*p + (intptr_t)1);
- else
- *p = (void *)((intptr_t)1);
+ if (BLI_edgehash_ensure_p(edgehash, v1, v2, &p))
+ *p = (void *)((intptr_t)*p + (intptr_t)1);
+ else
+ *p = (void *)((intptr_t)1);
}
static int laplacian_edge_count(EdgeHash *edgehash, int v1, int v2)
{
- return (int)(intptr_t)BLI_edgehash_lookup(edgehash, v1, v2);
+ return (int)(intptr_t)BLI_edgehash_lookup(edgehash, v1, v2);
}
static void laplacian_triangle_area(LaplacianSystem *sys, int i1, int i2, int i3)
{
- float t1, t2, t3, len1, len2, len3, area;
- float *varea = sys->varea, *v1, *v2, *v3;
- int obtuse = 0;
-
- v1 = sys->verts[i1];
- v2 = sys->verts[i2];
- v3 = sys->verts[i3];
-
- t1 = cotangent_tri_weight_v3(v1, v2, v3);
- t2 = cotangent_tri_weight_v3(v2, v3, v1);
- t3 = cotangent_tri_weight_v3(v3, v1, v2);
-
- if (angle_v3v3v3(v2, v1, v3) > DEG2RADF(90.0f)) obtuse = 1;
- else if (angle_v3v3v3(v1, v2, v3) > DEG2RADF(90.0f)) obtuse = 2;
- else if (angle_v3v3v3(v1, v3, v2) > DEG2RADF(90.0f)) obtuse = 3;
-
- if (obtuse > 0) {
- area = area_tri_v3(v1, v2, v3);
-
- varea[i1] += (obtuse == 1) ? area : area * 0.5f;
- varea[i2] += (obtuse == 2) ? area : area * 0.5f;
- varea[i3] += (obtuse == 3) ? area : area * 0.5f;
- }
- else {
- len1 = len_v3v3(v2, v3);
- len2 = len_v3v3(v1, v3);
- len3 = len_v3v3(v1, v2);
-
- t1 *= len1 * len1;
- t2 *= len2 * len2;
- t3 *= len3 * len3;
-
- varea[i1] += (t2 + t3) * 0.25f;
- varea[i2] += (t1 + t3) * 0.25f;
- varea[i3] += (t1 + t2) * 0.25f;
- }
+ float t1, t2, t3, len1, len2, len3, area;
+ float *varea = sys->varea, *v1, *v2, *v3;
+ int obtuse = 0;
+
+ v1 = sys->verts[i1];
+ v2 = sys->verts[i2];
+ v3 = sys->verts[i3];
+
+ t1 = cotangent_tri_weight_v3(v1, v2, v3);
+ t2 = cotangent_tri_weight_v3(v2, v3, v1);
+ t3 = cotangent_tri_weight_v3(v3, v1, v2);
+
+ if (angle_v3v3v3(v2, v1, v3) > DEG2RADF(90.0f))
+ obtuse = 1;
+ else if (angle_v3v3v3(v1, v2, v3) > DEG2RADF(90.0f))
+ obtuse = 2;
+ else if (angle_v3v3v3(v1, v3, v2) > DEG2RADF(90.0f))
+ obtuse = 3;
+
+ if (obtuse > 0) {
+ area = area_tri_v3(v1, v2, v3);
+
+ varea[i1] += (obtuse == 1) ? area : area * 0.5f;
+ varea[i2] += (obtuse == 2) ? area : area * 0.5f;
+ varea[i3] += (obtuse == 3) ? area : area * 0.5f;
+ }
+ else {
+ len1 = len_v3v3(v2, v3);
+ len2 = len_v3v3(v1, v3);
+ len3 = len_v3v3(v1, v2);
+
+ t1 *= len1 * len1;
+ t2 *= len2 * len2;
+ t3 *= len3 * len3;
+
+ varea[i1] += (t2 + t3) * 0.25f;
+ varea[i2] += (t1 + t3) * 0.25f;
+ varea[i3] += (t1 + t2) * 0.25f;
+ }
}
static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int i2, int i3)
{
- float t1, t2, t3;
- float *varea = sys->varea, *v1, *v2, *v3;
+ float t1, t2, t3;
+ float *varea = sys->varea, *v1, *v2, *v3;
- v1 = sys->verts[i1];
- v2 = sys->verts[i2];
- v3 = sys->verts[i3];
+ v1 = sys->verts[i1];
+ v2 = sys->verts[i2];
+ v3 = sys->verts[i3];
- /* instead of *0.5 we divided by the number of faces of the edge, it still
- * needs to be verified that this is indeed the correct thing to do! */
- t1 = cotangent_tri_weight_v3(v1, v2, v3) / laplacian_edge_count(sys->edgehash, i2, i3);
- t2 = cotangent_tri_weight_v3(v2, v3, v1) / laplacian_edge_count(sys->edgehash, i3, i1);
- t3 = cotangent_tri_weight_v3(v3, v1, v2) / laplacian_edge_count(sys->edgehash, i1, i2);
+ /* instead of *0.5 we divided by the number of faces of the edge, it still
+ * needs to be verified that this is indeed the correct thing to do! */
+ t1 = cotangent_tri_weight_v3(v1, v2, v3) / laplacian_edge_count(sys->edgehash, i2, i3);
+ t2 = cotangent_tri_weight_v3(v2, v3, v1) / laplacian_edge_count(sys->edgehash, i3, i1);
+ t3 = cotangent_tri_weight_v3(v3, v1, v2) / laplacian_edge_count(sys->edgehash, i1, i2);
- EIG_linear_solver_matrix_add(sys->context, i1, i1, (t2 + t3) * varea[i1]);
- EIG_linear_solver_matrix_add(sys->context, i2, i2, (t1 + t3) * varea[i2]);
- EIG_linear_solver_matrix_add(sys->context, i3, i3, (t1 + t2) * varea[i3]);
+ EIG_linear_solver_matrix_add(sys->context, i1, i1, (t2 + t3) * varea[i1]);
+ EIG_linear_solver_matrix_add(sys->context, i2, i2, (t1 + t3) * varea[i2]);
+ EIG_linear_solver_matrix_add(sys->context, i3, i3, (t1 + t2) * varea[i3]);
- EIG_linear_solver_matrix_add(sys->context, i1, i2, -t3 * varea[i1]);
- EIG_linear_solver_matrix_add(sys->context, i2, i1, -t3 * varea[i2]);
+ EIG_linear_solver_matrix_add(sys->context, i1, i2, -t3 * varea[i1]);
+ EIG_linear_solver_matrix_add(sys->context, i2, i1, -t3 * varea[i2]);
- EIG_linear_solver_matrix_add(sys->context, i2, i3, -t1 * varea[i2]);
- EIG_linear_solver_matrix_add(sys->context, i3, i2, -t1 * varea[i3]);
+ EIG_linear_solver_matrix_add(sys->context, i2, i3, -t1 * varea[i2]);
+ EIG_linear_solver_matrix_add(sys->context, i3, i2, -t1 * varea[i3]);
- EIG_linear_solver_matrix_add(sys->context, i3, i1, -t2 * varea[i3]);
- EIG_linear_solver_matrix_add(sys->context, i1, i3, -t2 * varea[i1]);
+ EIG_linear_solver_matrix_add(sys->context, i3, i1, -t2 * varea[i3]);
+ EIG_linear_solver_matrix_add(sys->context, i1, i3, -t2 * varea[i1]);
- if (sys->storeweights) {
- sys->fweights[f][0] = t1 * varea[i1];
- sys->fweights[f][1] = t2 * varea[i2];
- sys->fweights[f][2] = t3 * varea[i3];
- }
+ if (sys->storeweights) {
+ sys->fweights[f][0] = t1 * varea[i1];
+ sys->fweights[f][1] = t2 * varea[i2];
+ sys->fweights[f][2] = t3 * varea[i3];
+ }
}
static LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface, int lsq)
{
- LaplacianSystem *sys;
+ LaplacianSystem *sys;
- sys = MEM_callocN(sizeof(LaplacianSystem), "LaplacianSystem");
+ sys = MEM_callocN(sizeof(LaplacianSystem), "LaplacianSystem");
- sys->verts = MEM_callocN(sizeof(float *) * totvert, "LaplacianSystemVerts");
- sys->vpinned = MEM_callocN(sizeof(char) * totvert, "LaplacianSystemVpinned");
- sys->faces = MEM_callocN(sizeof(int) * 3 * totface, "LaplacianSystemFaces");
+ sys->verts = MEM_callocN(sizeof(float *) * totvert, "LaplacianSystemVerts");
+ sys->vpinned = MEM_callocN(sizeof(char) * totvert, "LaplacianSystemVpinned");
+ sys->faces = MEM_callocN(sizeof(int) * 3 * totface, "LaplacianSystemFaces");
- sys->totvert = 0;
- sys->totface = 0;
+ sys->totvert = 0;
+ sys->totface = 0;
- sys->areaweights = 1;
- sys->storeweights = 0;
+ sys->areaweights = 1;
+ sys->storeweights = 0;
- /* create linear solver */
- if (lsq)
- sys->context = EIG_linear_least_squares_solver_new(0, totvert, 1);
- else
- sys->context = EIG_linear_solver_new(0, totvert, 1);
+ /* create linear solver */
+ if (lsq)
+ sys->context = EIG_linear_least_squares_solver_new(0, totvert, 1);
+ else
+ sys->context = EIG_linear_solver_new(0, totvert, 1);
- return sys;
+ return sys;
}
void laplacian_add_vertex(LaplacianSystem *sys, float *co, int pinned)
{
- sys->verts[sys->totvert] = co;
- sys->vpinned[sys->totvert] = pinned;
- sys->totvert++;
+ sys->verts[sys->totvert] = co;
+ sys->vpinned[sys->totvert] = pinned;
+ sys->totvert++;
}
void laplacian_add_triangle(LaplacianSystem *sys, int v1, int v2, int v3)
{
- sys->faces[sys->totface][0] = v1;
- sys->faces[sys->totface][1] = v2;
- sys->faces[sys->totface][2] = v3;
- sys->totface++;
+ sys->faces[sys->totface][0] = v1;
+ sys->faces[sys->totface][1] = v2;
+ sys->faces[sys->totface][2] = v3;
+ sys->totface++;
}
static void laplacian_system_construct_end(LaplacianSystem *sys)
{
- int (*face)[3];
- int a, totvert = sys->totvert, totface = sys->totface;
+ int(*face)[3];
+ int a, totvert = sys->totvert, totface = sys->totface;
- laplacian_begin_solve(sys, 0);
+ laplacian_begin_solve(sys, 0);
- sys->varea = MEM_callocN(sizeof(float) * totvert, "LaplacianSystemVarea");
+ sys->varea = MEM_callocN(sizeof(float) * totvert, "LaplacianSystemVarea");
- sys->edgehash = BLI_edgehash_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(sys->totface));
- for (a = 0, face = sys->faces; a < sys->totface; a++, face++) {
- laplacian_increase_edge_count(sys->edgehash, (*face)[0], (*face)[1]);
- laplacian_increase_edge_count(sys->edgehash, (*face)[1], (*face)[2]);
- laplacian_increase_edge_count(sys->edgehash, (*face)[2], (*face)[0]);
- }
+ sys->edgehash = BLI_edgehash_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(sys->totface));
+ for (a = 0, face = sys->faces; a < sys->totface; a++, face++) {
+ laplacian_increase_edge_count(sys->edgehash, (*face)[0], (*face)[1]);
+ laplacian_increase_edge_count(sys->edgehash, (*face)[1], (*face)[2]);
+ laplacian_increase_edge_count(sys->edgehash, (*face)[2], (*face)[0]);
+ }
- if (sys->areaweights)
- for (a = 0, face = sys->faces; a < sys->totface; a++, face++)
- laplacian_triangle_area(sys, (*face)[0], (*face)[1], (*face)[2]);
+ if (sys->areaweights)
+ for (a = 0, face = sys->faces; a < sys->totface; a++, face++)
+ laplacian_triangle_area(sys, (*face)[0], (*face)[1], (*face)[2]);
- for (a = 0; a < totvert; a++) {
- if (sys->areaweights) {
- if (sys->varea[a] != 0.0f)
- sys->varea[a] = 0.5f / sys->varea[a];
- }
- else
- sys->varea[a] = 1.0f;
+ for (a = 0; a < totvert; a++) {
+ if (sys->areaweights) {
+ if (sys->varea[a] != 0.0f)
+ sys->varea[a] = 0.5f / sys->varea[a];
+ }
+ else
+ sys->varea[a] = 1.0f;
- /* for heat weighting */
- if (sys->heat.H)
- EIG_linear_solver_matrix_add(sys->context, a, a, sys->heat.H[a]);
- }
+ /* for heat weighting */
+ if (sys->heat.H)
+ EIG_linear_solver_matrix_add(sys->context, a, a, sys->heat.H[a]);
+ }
- if (sys->storeweights)
- sys->fweights = MEM_callocN(sizeof(float) * 3 * totface, "LaplacianFWeight");
+ if (sys->storeweights)
+ sys->fweights = MEM_callocN(sizeof(float) * 3 * totface, "LaplacianFWeight");
- for (a = 0, face = sys->faces; a < totface; a++, face++)
- laplacian_triangle_weights(sys, a, (*face)[0], (*face)[1], (*face)[2]);
+ for (a = 0, face = sys->faces; a < totface; a++, face++)
+ laplacian_triangle_weights(sys, a, (*face)[0], (*face)[1], (*face)[2]);
- MEM_freeN(sys->faces);
- sys->faces = NULL;
+ MEM_freeN(sys->faces);
+ sys->faces = NULL;
- if (sys->varea) {
- MEM_freeN(sys->varea);
- sys->varea = NULL;
- }
+ if (sys->varea) {
+ MEM_freeN(sys->varea);
+ sys->varea = NULL;
+ }
- BLI_edgehash_free(sys->edgehash, NULL);
- sys->edgehash = NULL;
+ BLI_edgehash_free(sys->edgehash, NULL);
+ sys->edgehash = NULL;
}
static void laplacian_system_delete(LaplacianSystem *sys)
{
- if (sys->verts) MEM_freeN(sys->verts);
- if (sys->varea) MEM_freeN(sys->varea);
- if (sys->vpinned) MEM_freeN(sys->vpinned);
- if (sys->faces) MEM_freeN(sys->faces);
- if (sys->fweights) MEM_freeN(sys->fweights);
-
- EIG_linear_solver_delete(sys->context);
- MEM_freeN(sys);
+ if (sys->verts)
+ MEM_freeN(sys->verts);
+ if (sys->varea)
+ MEM_freeN(sys->varea);
+ if (sys->vpinned)
+ MEM_freeN(sys->vpinned);
+ if (sys->faces)
+ MEM_freeN(sys->faces);
+ if (sys->fweights)
+ MEM_freeN(sys->fweights);
+
+ EIG_linear_solver_delete(sys->context);
+ MEM_freeN(sys);
}
void laplacian_begin_solve(LaplacianSystem *sys, int index)
{
- int a;
-
- if (!sys->variablesdone) {
- if (index >= 0) {
- for (a = 0; a < sys->totvert; a++) {
- if (sys->vpinned[a]) {
- EIG_linear_solver_variable_set(sys->context, 0, a, sys->verts[a][index]);
- EIG_linear_solver_variable_lock(sys->context, a);
- }
- }
- }
-
- sys->variablesdone = true;
- }
+ int a;
+
+ if (!sys->variablesdone) {
+ if (index >= 0) {
+ for (a = 0; a < sys->totvert; a++) {
+ if (sys->vpinned[a]) {
+ EIG_linear_solver_variable_set(sys->context, 0, a, sys->verts[a][index]);
+ EIG_linear_solver_variable_lock(sys->context, a);
+ }
+ }
+ }
+
+ sys->variablesdone = true;
+ }
}
void laplacian_add_right_hand_side(LaplacianSystem *sys, int v, float value)
{
- EIG_linear_solver_right_hand_side_add(sys->context, 0, v, value);
+ EIG_linear_solver_right_hand_side_add(sys->context, 0, v, value);
}
int laplacian_system_solve(LaplacianSystem *sys)
{
- sys->variablesdone = false;
+ sys->variablesdone = false;
- //EIG_linear_solver_print_matrix(sys->context, );
+ //EIG_linear_solver_print_matrix(sys->context, );
- return EIG_linear_solver_solve(sys->context);
+ return EIG_linear_solver_solve(sys->context);
}
float laplacian_system_get_solution(LaplacianSystem *sys, int v)
{
- return EIG_linear_solver_variable_get(sys->context, 0, v);
+ return EIG_linear_solver_variable_get(sys->context, 0, v);
}
/************************* Heat Bone Weighting ******************************/
/* From "Automatic Rigging and Animation of 3D Characters"
* Ilya Baran and Jovan Popovic, SIGGRAPH 2007 */
-#define C_WEIGHT 1.0f
-#define WEIGHT_LIMIT_START 0.05f
-#define WEIGHT_LIMIT_END 0.025f
-#define DISTANCE_EPSILON 1e-4f
+#define C_WEIGHT 1.0f
+#define WEIGHT_LIMIT_START 0.05f
+#define WEIGHT_LIMIT_END 0.025f
+#define DISTANCE_EPSILON 1e-4f
typedef struct BVHCallbackUserData {
- float start[3];
- float vec[3];
- LaplacianSystem *sys;
+ float start[3];
+ float vec[3];
+ LaplacianSystem *sys;
} BVHCallbackUserData;
static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
- BVHCallbackUserData *data = (struct BVHCallbackUserData *)userdata;
- const MLoopTri *lt = &data->sys->heat.mlooptri[index];
- const MLoop *mloop = data->sys->heat.mloop;
- float (*verts)[3] = data->sys->heat.verts;
- const float *vtri_co[3];
- float dist_test;
+ BVHCallbackUserData *data = (struct BVHCallbackUserData *)userdata;
+ const MLoopTri *lt = &data->sys->heat.mlooptri[index];
+ const MLoop *mloop = data->sys->heat.mloop;
+ float(*verts)[3] = data->sys->heat.verts;
+ const float *vtri_co[3];
+ float dist_test;
- vtri_co[0] = verts[mloop[lt->tri[0]].v];
- vtri_co[1] = verts[mloop[lt->tri[1]].v];
- vtri_co[2] = verts[mloop[lt->tri[2]].v];
+ vtri_co[0] = verts[mloop[lt->tri[0]].v];
+ vtri_co[1] = verts[mloop[lt->tri[1]].v];
+ vtri_co[2] = verts[mloop[lt->tri[2]].v];
#ifdef USE_KDOPBVH_WATERTIGHT
- if (isect_ray_tri_watertight_v3(data->start, ray->isect_precalc, UNPACK3(vtri_co), &dist_test, NULL))
+ if (isect_ray_tri_watertight_v3(
+ data->start, ray->isect_precalc, UNPACK3(vtri_co), &dist_test, NULL))
#else
- UNUSED_VARS(ray);
- if (isect_ray_tri_v3(data->start, data->vec, UNPACK3(vtri_co), &dist_test, NULL))
+ UNUSED_VARS(ray);
+ if (isect_ray_tri_v3(data->start, data->vec, UNPACK3(vtri_co), &dist_test, NULL))
#endif
- {
- if (dist_test < hit->dist) {
- float n[3];
- normal_tri_v3(n, UNPACK3(vtri_co));
- if (dot_v3v3(n, data->vec) < -1e-5f) {
- hit->index = index;
- hit->dist = dist_test;
- }
- }
- }
+ {
+ if (dist_test < hit->dist) {
+ float n[3];
+ normal_tri_v3(n, UNPACK3(vtri_co));
+ if (dot_v3v3(n, data->vec) < -1e-5f) {
+ hit->index = index;
+ hit->dist = dist_test;
+ }
+ }
+ }
}
/* Raytracing for vertex to bone/vertex visibility */
static void heat_ray_tree_create(LaplacianSystem *sys)
{
- const MLoopTri *looptri = sys->heat.mlooptri;
- const MLoop *mloop = sys->heat.mloop;
- float (*verts)[3] = sys->heat.verts;
- int tottri = sys->heat.tottri;
- int totvert = sys->heat.totvert;
- int a;
-
- sys->heat.bvhtree = BLI_bvhtree_new(tottri, 0.0f, 4, 6);
- sys->heat.vltree = MEM_callocN(sizeof(MLoopTri *) * totvert, "HeatVFaces");
-
- for (a = 0; a < tottri; a++) {
- const MLoopTri *lt = &looptri[a];
- float bb[6];
- int vtri[3];
-
- vtri[0] = mloop[lt->tri[0]].v;
- vtri[1] = mloop[lt->tri[1]].v;
- vtri[2] = mloop[lt->tri[2]].v;
-
- INIT_MINMAX(bb, bb + 3);
- minmax_v3v3_v3(bb, bb + 3, verts[vtri[0]]);
- minmax_v3v3_v3(bb, bb + 3, verts[vtri[1]]);
- minmax_v3v3_v3(bb, bb + 3, verts[vtri[2]]);
-
- BLI_bvhtree_insert(sys->heat.bvhtree, a, bb, 2);
-
- //Setup inverse pointers to use on isect.orig
- sys->heat.vltree[vtri[0]] = lt;
- sys->heat.vltree[vtri[1]] = lt;
- sys->heat.vltree[vtri[2]] = lt;
- }
-
- BLI_bvhtree_balance(sys->heat.bvhtree);
+ const MLoopTri *looptri = sys->heat.mlooptri;
+ const MLoop *mloop = sys->heat.mloop;
+ float(*verts)[3] = sys->heat.verts;
+ int tottri = sys->heat.tottri;
+ int totvert = sys->heat.totvert;
+ int a;
+
+ sys->heat.bvhtree = BLI_bvhtree_new(tottri, 0.0f, 4, 6);
+ sys->heat.vltree = MEM_callocN(sizeof(MLoopTri *) * totvert, "HeatVFaces");
+
+ for (a = 0; a < tottri; a++) {
+ const MLoopTri *lt = &looptri[a];
+ float bb[6];
+ int vtri[3];
+
+ vtri[0] = mloop[lt->tri[0]].v;
+ vtri[1] = mloop[lt->tri[1]].v;
+ vtri[2] = mloop[lt->tri[2]].v;
+
+ INIT_MINMAX(bb, bb + 3);
+ minmax_v3v3_v3(bb, bb + 3, verts[vtri[0]]);
+ minmax_v3v3_v3(bb, bb + 3, verts[vtri[1]]);
+ minmax_v3v3_v3(bb, bb + 3, verts[vtri[2]]);
+
+ BLI_bvhtree_insert(sys->heat.bvhtree, a, bb, 2);
+
+ //Setup inverse pointers to use on isect.orig
+ sys->heat.vltree[vtri[0]] = lt;
+ sys->heat.vltree[vtri[1]] = lt;
+ sys->heat.vltree[vtri[2]] = lt;
+ }
+
+ BLI_bvhtree_balance(sys->heat.bvhtree);
}
static int heat_ray_source_visible(LaplacianSystem *sys, int vertex, int source)
{
- BVHTreeRayHit hit;
- BVHCallbackUserData data;
- const MLoopTri *lt;
- float end[3];
- int visible;
+ BVHTreeRayHit hit;
+ BVHCallbackUserData data;
+ const MLoopTri *lt;
+ float end[3];
+ int visible;
- lt = sys->heat.vltree[vertex];
- if (lt == NULL)
- return 1;
+ lt = sys->heat.vltree[vertex];
+ if (lt == NULL)
+ return 1;
- data.sys = sys;
- copy_v3_v3(data.start, sys->heat.verts[vertex]);
+ data.sys = sys;
+ copy_v3_v3(data.start, sys->heat.verts[vertex]);
- closest_to_line_segment_v3(end, data.start, sys->heat.root[source], sys->heat.tip[source]);
+ closest_to_line_segment_v3(end, data.start, sys->heat.root[source], sys->heat.tip[source]);
- sub_v3_v3v3(data.vec, end, data.start);
- madd_v3_v3v3fl(data.start, data.start, data.vec, 1e-5);
- mul_v3_fl(data.vec, 1.0f - 2e-5f);
+ sub_v3_v3v3(data.vec, end, data.start);
+ madd_v3_v3v3fl(data.start, data.start, data.vec, 1e-5);
+ mul_v3_fl(data.vec, 1.0f - 2e-5f);
- /* pass normalized vec + distance to bvh */
- hit.index = -1;
- hit.dist = normalize_v3(data.vec);
+ /* pass normalized vec + distance to bvh */
+ hit.index = -1;
+ hit.dist = normalize_v3(data.vec);
- visible = BLI_bvhtree_ray_cast(sys->heat.bvhtree, data.start, data.vec, 0.0f, &hit, bvh_callback, (void *)&data) == -1;
+ visible =
+ BLI_bvhtree_ray_cast(
+ sys->heat.bvhtree, data.start, data.vec, 0.0f, &hit, bvh_callback, (void *)&data) == -1;
- return visible;
+ return visible;
}
static float heat_source_distance(LaplacianSystem *sys, int vertex, int source)
{
- float closest[3], d[3], dist, cosine;
+ float closest[3], d[3], dist, cosine;
- /* compute euclidian distance */
- closest_to_line_segment_v3(closest, sys->heat.verts[vertex], sys->heat.root[source], sys->heat.tip[source]);
+ /* compute euclidian distance */
+ closest_to_line_segment_v3(
+ closest, sys->heat.verts[vertex], sys->heat.root[source], sys->heat.tip[source]);
- sub_v3_v3v3(d, sys->heat.verts[vertex], closest);
- dist = normalize_v3(d);
+ sub_v3_v3v3(d, sys->heat.verts[vertex], closest);
+ dist = normalize_v3(d);
- /* if the vertex normal does not point along the bone, increase distance */
- cosine = dot_v3v3(d, sys->heat.vnors[vertex]);
+ /* if the vertex normal does not point along the bone, increase distance */
+ cosine = dot_v3v3(d, sys->heat.vnors[vertex]);
- return dist / (0.5f * (cosine + 1.001f));
+ return dist / (0.5f * (cosine + 1.001f));
}
static int heat_source_closest(LaplacianSystem *sys, int vertex, int source)
{
- float dist;
+ float dist;
- dist = heat_source_distance(sys, vertex, source);
+ dist = heat_source_distance(sys, vertex, source);
- if (dist <= sys->heat.mindist[vertex] * (1.0f + DISTANCE_EPSILON))
- if (heat_ray_source_visible(sys, vertex, source))
- return 1;
+ if (dist <= sys->heat.mindist[vertex] * (1.0f + DISTANCE_EPSILON))
+ if (heat_ray_source_visible(sys, vertex, source))
+ return 1;
- return 0;
+ return 0;
}
static void heat_set_H(LaplacianSystem *sys, int vertex)
{
- float dist, mindist, h;
- int j, numclosest = 0;
+ float dist, mindist, h;
+ int j, numclosest = 0;
- mindist = 1e10;
+ mindist = 1e10;
- /* compute minimum distance */
- for (j = 0; j < sys->heat.numsource; j++) {
- dist = heat_source_distance(sys, vertex, j);
+ /* compute minimum distance */
+ for (j = 0; j < sys->heat.numsource; j++) {
+ dist = heat_source_distance(sys, vertex, j);
- if (dist < mindist)
- mindist = dist;
- }
+ if (dist < mindist)
+ mindist = dist;
+ }
- sys->heat.mindist[vertex] = mindist;
+ sys->heat.mindist[vertex] = mindist;
- /* count number of sources with approximately this minimum distance */
- for (j = 0; j < sys->heat.numsource; j++)
- if (heat_source_closest(sys, vertex, j))
- numclosest++;
+ /* count number of sources with approximately this minimum distance */
+ for (j = 0; j < sys->heat.numsource; j++)
+ if (heat_source_closest(sys, vertex, j))
+ numclosest++;
- sys->heat.p[vertex] = (numclosest > 0) ? 1.0f / numclosest : 0.0f;
+ sys->heat.p[vertex] = (numclosest > 0) ? 1.0f / numclosest : 0.0f;
- /* compute H entry */
- if (numclosest > 0) {
- mindist = max_ff(mindist, 1e-4f);
- h = numclosest * C_WEIGHT / (mindist * mindist);
- }
- else
- h = 0.0f;
+ /* compute H entry */
+ if (numclosest > 0) {
+ mindist = max_ff(mindist, 1e-4f);
+ h = numclosest * C_WEIGHT / (mindist * mindist);
+ }
+ else
+ h = 0.0f;
- sys->heat.H[vertex] = h;
+ sys->heat.H[vertex] = h;
}
static void heat_calc_vnormals(LaplacianSystem *sys)
{
- float fnor[3];
- int a, v1, v2, v3, (*face)[3];
+ float fnor[3];
+ int a, v1, v2, v3, (*face)[3];
- sys->heat.vnors = MEM_callocN(sizeof(float) * 3 * sys->totvert, "HeatVNors");
+ sys->heat.vnors = MEM_callocN(sizeof(float) * 3 * sys->totvert, "HeatVNors");
- for (a = 0, face = sys->faces; a < sys->totface; a++, face++) {
- v1 = (*face)[0];
- v2 = (*face)[1];
- v3 = (*face)[2];
+ for (a = 0, face = sys->faces; a < sys->totface; a++, face++) {
+ v1 = (*face)[0];
+ v2 = (*face)[1];
+ v3 = (*face)[2];
- normal_tri_v3(fnor, sys->verts[v1], sys->verts[v2], sys->verts[v3]);
+ normal_tri_v3(fnor, sys->verts[v1], sys->verts[v2], sys->verts[v3]);
- add_v3_v3(sys->heat.vnors[v1], fnor);
- add_v3_v3(sys->heat.vnors[v2], fnor);
- add_v3_v3(sys->heat.vnors[v3], fnor);
- }
+ add_v3_v3(sys->heat.vnors[v1], fnor);
+ add_v3_v3(sys->heat.vnors[v2], fnor);
+ add_v3_v3(sys->heat.vnors[v3], fnor);
+ }
- for (a = 0; a < sys->totvert; a++)
- normalize_v3(sys->heat.vnors[a]);
+ for (a = 0; a < sys->totvert; a++)
+ normalize_v3(sys->heat.vnors[a]);
}
static void heat_laplacian_create(LaplacianSystem *sys)
{
- const MLoopTri *mlooptri = sys->heat.mlooptri, *lt;
- const MLoop *mloop = sys->heat.mloop;
- int tottri = sys->heat.tottri;
- int totvert = sys->heat.totvert;
- int a;
-
- /* heat specific definitions */
- sys->heat.mindist = MEM_callocN(sizeof(float) * totvert, "HeatMinDist");
- sys->heat.H = MEM_callocN(sizeof(float) * totvert, "HeatH");
- sys->heat.p = MEM_callocN(sizeof(float) * totvert, "HeatP");
-
- /* add verts and faces to laplacian */
- for (a = 0; a < totvert; a++)
- laplacian_add_vertex(sys, sys->heat.verts[a], 0);
-
- for (a = 0, lt = mlooptri; a < tottri; a++, lt++) {
- int vtri[3];
- vtri[0] = mloop[lt->tri[0]].v;
- vtri[1] = mloop[lt->tri[1]].v;
- vtri[2] = mloop[lt->tri[2]].v;
- laplacian_add_triangle(sys, UNPACK3(vtri));
- }
-
- /* for distance computation in set_H */
- heat_calc_vnormals(sys);
-
- for (a = 0; a < totvert; a++)
- heat_set_H(sys, a);
+ const MLoopTri *mlooptri = sys->heat.mlooptri, *lt;
+ const MLoop *mloop = sys->heat.mloop;
+ int tottri = sys->heat.tottri;
+ int totvert = sys->heat.totvert;
+ int a;
+
+ /* heat specific definitions */
+ sys->heat.mindist = MEM_callocN(sizeof(float) * totvert, "HeatMinDist");
+ sys->heat.H = MEM_callocN(sizeof(float) * totvert, "HeatH");
+ sys->heat.p = MEM_callocN(sizeof(float) * totvert, "HeatP");
+
+ /* add verts and faces to laplacian */
+ for (a = 0; a < totvert; a++)
+ laplacian_add_vertex(sys, sys->heat.verts[a], 0);
+
+ for (a = 0, lt = mlooptri; a < tottri; a++, lt++) {
+ int vtri[3];
+ vtri[0] = mloop[lt->tri[0]].v;
+ vtri[1] = mloop[lt->tri[1]].v;
+ vtri[2] = mloop[lt->tri[2]].v;
+ laplacian_add_triangle(sys, UNPACK3(vtri));
+ }
+
+ /* for distance computation in set_H */
+ heat_calc_vnormals(sys);
+
+ for (a = 0; a < totvert; a++)
+ heat_set_H(sys, a);
}
static void heat_system_free(LaplacianSystem *sys)
{
- BLI_bvhtree_free(sys->heat.bvhtree);
- MEM_freeN((void *)sys->heat.vltree);
- MEM_freeN((void *)sys->heat.mlooptri);
-
- MEM_freeN(sys->heat.mindist);
- MEM_freeN(sys->heat.H);
- MEM_freeN(sys->heat.p);
- MEM_freeN(sys->heat.vnors);
+ BLI_bvhtree_free(sys->heat.bvhtree);
+ MEM_freeN((void *)sys->heat.vltree);
+ MEM_freeN((void *)sys->heat.mlooptri);
+
+ MEM_freeN(sys->heat.mindist);
+ MEM_freeN(sys->heat.H);
+ MEM_freeN(sys->heat.p);
+ MEM_freeN(sys->heat.vnors);
}
static float heat_limit_weight(float weight)
{
- float t;
-
- if (weight < WEIGHT_LIMIT_END) {
- return 0.0f;
- }
- else if (weight < WEIGHT_LIMIT_START) {
- t = (weight - WEIGHT_LIMIT_END) / (WEIGHT_LIMIT_START - WEIGHT_LIMIT_END);
- return t * WEIGHT_LIMIT_START;
- }
- else
- return weight;
+ float t;
+
+ if (weight < WEIGHT_LIMIT_END) {
+ return 0.0f;
+ }
+ else if (weight < WEIGHT_LIMIT_START) {
+ t = (weight - WEIGHT_LIMIT_END) / (WEIGHT_LIMIT_START - WEIGHT_LIMIT_END);
+ return t * WEIGHT_LIMIT_START;
+ }
+ else
+ return weight;
}
-void heat_bone_weighting(
- Object *ob, Mesh *me, float (*verts)[3], int numsource,
- bDeformGroup **dgrouplist, bDeformGroup **dgroupflip,
- float (*root)[3], float (*tip)[3], int *selected, const char **err_str)
+void heat_bone_weighting(Object *ob,
+ Mesh *me,
+ float (*verts)[3],
+ int numsource,
+ bDeformGroup **dgrouplist,
+ bDeformGroup **dgroupflip,
+ float (*root)[3],
+ float (*tip)[3],
+ int *selected,
+ const char **err_str)
{
- LaplacianSystem *sys;
- MLoopTri *mlooptri;
- MPoly *mp;
- MLoop *ml;
- float solution, weight;
- int *vertsflipped = NULL, *mask = NULL;
- int a, tottri, j, bbone, firstsegment, lastsegment;
- bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
-
- MVert *mvert = me->mvert;
- bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
- bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
-
- *err_str = NULL;
-
- /* bone heat needs triangulated faces */
- tottri = poly_to_tri_count(me->totpoly, me->totloop);
-
- /* count triangles and create mask */
- if (ob->mode & OB_MODE_WEIGHT_PAINT &&
- (use_face_sel || use_vert_sel))
- {
- mask = MEM_callocN(sizeof(int) * me->totvert, "heat_bone_weighting mask");
-
- /* (added selectedVerts content for vertex mask, they used to just equal 1) */
- if (use_vert_sel) {
- for (a = 0, mp = me->mpoly; a < me->totpoly; mp++, a++) {
- for (j = 0, ml = me->mloop + mp->loopstart; j < mp->totloop; j++, ml++) {
- mask[ml->v] = (mvert[ml->v].flag & SELECT) != 0;
- }
- }
- }
- else if (use_face_sel) {
- for (a = 0, mp = me->mpoly; a < me->totpoly; mp++, a++) {
- if (mp->flag & ME_FACE_SEL) {
- for (j = 0, ml = me->mloop + mp->loopstart; j < mp->totloop; j++, ml++) {
- mask[ml->v] = 1;
- }
- }
- }
- }
- }
-
- /* create laplacian */
- sys = laplacian_system_construct_begin(me->totvert, tottri, 1);
-
- sys->heat.tottri = poly_to_tri_count(me->totpoly, me->totloop);
- mlooptri = MEM_mallocN(sizeof(*sys->heat.mlooptri) * sys->heat.tottri, __func__);
-
- BKE_mesh_recalc_looptri(
- me->mloop, me->mpoly,
- me->mvert,
- me->totloop, me->totpoly,
- mlooptri);
-
- sys->heat.mlooptri = mlooptri;
- sys->heat.mloop = me->mloop;
- sys->heat.totvert = me->totvert;
- sys->heat.verts = verts;
- sys->heat.root = root;
- sys->heat.tip = tip;
- sys->heat.numsource = numsource;
-
- heat_ray_tree_create(sys);
- heat_laplacian_create(sys);
-
- laplacian_system_construct_end(sys);
-
- if (dgroupflip) {
- vertsflipped = MEM_callocN(sizeof(int) * me->totvert, "vertsflipped");
- for (a = 0; a < me->totvert; a++)
- vertsflipped[a] = mesh_get_x_mirror_vert(ob, NULL, a, use_topology);
- }
-
- /* compute weights per bone */
- for (j = 0; j < numsource; j++) {
- if (!selected[j])
- continue;
-
- firstsegment = (j == 0 || dgrouplist[j - 1] != dgrouplist[j]);
- lastsegment = (j == numsource - 1 || dgrouplist[j] != dgrouplist[j + 1]);
- bbone = !(firstsegment && lastsegment);
-
- /* clear weights */
- if (bbone && firstsegment) {
- for (a = 0; a < me->totvert; a++) {
- if (mask && !mask[a])
- continue;
-
- ED_vgroup_vert_remove(ob, dgrouplist[j], a);
- if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0)
- ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
- }
- }
-
- /* fill right hand side */
- laplacian_begin_solve(sys, -1);
-
- for (a = 0; a < me->totvert; a++)
- if (heat_source_closest(sys, a, j))
- laplacian_add_right_hand_side(sys, a,
- sys->heat.H[a] * sys->heat.p[a]);
-
- /* solve */
- if (laplacian_system_solve(sys)) {
- /* load solution into vertex groups */
- for (a = 0; a < me->totvert; a++) {
- if (mask && !mask[a])
- continue;
-
- solution = laplacian_system_get_solution(sys, a);
-
- if (bbone) {
- if (solution > 0.0f)
- ED_vgroup_vert_add(ob, dgrouplist[j], a, solution,
- WEIGHT_ADD);
- }
- else {
- weight = heat_limit_weight(solution);
- if (weight > 0.0f)
- ED_vgroup_vert_add(ob, dgrouplist[j], a, weight,
- WEIGHT_REPLACE);
- else
- ED_vgroup_vert_remove(ob, dgrouplist[j], a);
- }
-
- /* do same for mirror */
- if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
- if (bbone) {
- if (solution > 0.0f)
- ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a],
- solution, WEIGHT_ADD);
- }
- else {
- weight = heat_limit_weight(solution);
- if (weight > 0.0f)
- ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a],
- weight, WEIGHT_REPLACE);
- else
- ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
- }
- }
- }
- }
- else if (*err_str == NULL) {
- *err_str = N_("Bone Heat Weighting: failed to find solution for one or more bones");
- break;
- }
-
- /* remove too small vertex weights */
- if (bbone && lastsegment) {
- for (a = 0; a < me->totvert; a++) {
- if (mask && !mask[a])
- continue;
-
- weight = ED_vgroup_vert_weight(ob, dgrouplist[j], a);
- weight = heat_limit_weight(weight);
- if (weight <= 0.0f)
- ED_vgroup_vert_remove(ob, dgrouplist[j], a);
-
- if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
- weight = ED_vgroup_vert_weight(ob, dgroupflip[j], vertsflipped[a]);
- weight = heat_limit_weight(weight);
- if (weight <= 0.0f)
- ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
- }
- }
- }
- }
-
- /* free */
- if (vertsflipped) MEM_freeN(vertsflipped);
- if (mask) MEM_freeN(mask);
-
- heat_system_free(sys);
-
- laplacian_system_delete(sys);
+ LaplacianSystem *sys;
+ MLoopTri *mlooptri;
+ MPoly *mp;
+ MLoop *ml;
+ float solution, weight;
+ int *vertsflipped = NULL, *mask = NULL;
+ int a, tottri, j, bbone, firstsegment, lastsegment;
+ bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+
+ MVert *mvert = me->mvert;
+ bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+ bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+
+ *err_str = NULL;
+
+ /* bone heat needs triangulated faces */
+ tottri = poly_to_tri_count(me->totpoly, me->totloop);
+
+ /* count triangles and create mask */
+ if (ob->mode & OB_MODE_WEIGHT_PAINT && (use_face_sel || use_vert_sel)) {
+ mask = MEM_callocN(sizeof(int) * me->totvert, "heat_bone_weighting mask");
+
+ /* (added selectedVerts content for vertex mask, they used to just equal 1) */
+ if (use_vert_sel) {
+ for (a = 0, mp = me->mpoly; a < me->totpoly; mp++, a++) {
+ for (j = 0, ml = me->mloop + mp->loopstart; j < mp->totloop; j++, ml++) {
+ mask[ml->v] = (mvert[ml->v].flag & SELECT) != 0;
+ }
+ }
+ }
+ else if (use_face_sel) {
+ for (a = 0, mp = me->mpoly; a < me->totpoly; mp++, a++) {
+ if (mp->flag & ME_FACE_SEL) {
+ for (j = 0, ml = me->mloop + mp->loopstart; j < mp->totloop; j++, ml++) {
+ mask[ml->v] = 1;
+ }
+ }
+ }
+ }
+ }
+
+ /* create laplacian */
+ sys = laplacian_system_construct_begin(me->totvert, tottri, 1);
+
+ sys->heat.tottri = poly_to_tri_count(me->totpoly, me->totloop);
+ mlooptri = MEM_mallocN(sizeof(*sys->heat.mlooptri) * sys->heat.tottri, __func__);
+
+ BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, mlooptri);
+
+ sys->heat.mlooptri = mlooptri;
+ sys->heat.mloop = me->mloop;
+ sys->heat.totvert = me->totvert;
+ sys->heat.verts = verts;
+ sys->heat.root = root;
+ sys->heat.tip = tip;
+ sys->heat.numsource = numsource;
+
+ heat_ray_tree_create(sys);
+ heat_laplacian_create(sys);
+
+ laplacian_system_construct_end(sys);
+
+ if (dgroupflip) {
+ vertsflipped = MEM_callocN(sizeof(int) * me->totvert, "vertsflipped");
+ for (a = 0; a < me->totvert; a++)
+ vertsflipped[a] = mesh_get_x_mirror_vert(ob, NULL, a, use_topology);
+ }
+
+ /* compute weights per bone */
+ for (j = 0; j < numsource; j++) {
+ if (!selected[j])
+ continue;
+
+ firstsegment = (j == 0 || dgrouplist[j - 1] != dgrouplist[j]);
+ lastsegment = (j == numsource - 1 || dgrouplist[j] != dgrouplist[j + 1]);
+ bbone = !(firstsegment && lastsegment);
+
+ /* clear weights */
+ if (bbone && firstsegment) {
+ for (a = 0; a < me->totvert; a++) {
+ if (mask && !mask[a])
+ continue;
+
+ ED_vgroup_vert_remove(ob, dgrouplist[j], a);
+ if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0)
+ ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
+ }
+ }
+
+ /* fill right hand side */
+ laplacian_begin_solve(sys, -1);
+
+ for (a = 0; a < me->totvert; a++)
+ if (heat_source_closest(sys, a, j))
+ laplacian_add_right_hand_side(sys, a, sys->heat.H[a] * sys->heat.p[a]);
+
+ /* solve */
+ if (laplacian_system_solve(sys)) {
+ /* load solution into vertex groups */
+ for (a = 0; a < me->totvert; a++) {
+ if (mask && !mask[a])
+ continue;
+
+ solution = laplacian_system_get_solution(sys, a);
+
+ if (bbone) {
+ if (solution > 0.0f)
+ ED_vgroup_vert_add(ob, dgrouplist[j], a, solution, WEIGHT_ADD);
+ }
+ else {
+ weight = heat_limit_weight(solution);
+ if (weight > 0.0f)
+ ED_vgroup_vert_add(ob, dgrouplist[j], a, weight, WEIGHT_REPLACE);
+ else
+ ED_vgroup_vert_remove(ob, dgrouplist[j], a);
+ }
+
+ /* do same for mirror */
+ if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
+ if (bbone) {
+ if (solution > 0.0f)
+ ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a], solution, WEIGHT_ADD);
+ }
+ else {
+ weight = heat_limit_weight(solution);
+ if (weight > 0.0f)
+ ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a], weight, WEIGHT_REPLACE);
+ else
+ ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
+ }
+ }
+ }
+ }
+ else if (*err_str == NULL) {
+ *err_str = N_("Bone Heat Weighting: failed to find solution for one or more bones");
+ break;
+ }
+
+ /* remove too small vertex weights */
+ if (bbone && lastsegment) {
+ for (a = 0; a < me->totvert; a++) {
+ if (mask && !mask[a])
+ continue;
+
+ weight = ED_vgroup_vert_weight(ob, dgrouplist[j], a);
+ weight = heat_limit_weight(weight);
+ if (weight <= 0.0f)
+ ED_vgroup_vert_remove(ob, dgrouplist[j], a);
+
+ if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
+ weight = ED_vgroup_vert_weight(ob, dgroupflip[j], vertsflipped[a]);
+ weight = heat_limit_weight(weight);
+ if (weight <= 0.0f)
+ ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
+ }
+ }
+ }
+ }
+
+ /* free */
+ if (vertsflipped)
+ MEM_freeN(vertsflipped);
+ if (mask)
+ MEM_freeN(mask);
+
+ heat_system_free(sys);
+
+ laplacian_system_delete(sys);
}
/************************** Harmonic Coordinates ****************************/
@@ -789,7 +808,7 @@ void heat_bone_weighting(
#define EPSILON 0.0001f
-#define MESHDEFORM_TAG_UNTYPED 0
+#define MESHDEFORM_TAG_UNTYPED 0
#define MESHDEFORM_TAG_BOUNDARY 1
#define MESHDEFORM_TAG_INTERIOR 2
#define MESHDEFORM_TAG_EXTERIOR 3
@@ -800,828 +819,874 @@ void heat_bone_weighting(
#define MESHDEFORM_MIN_INFLUENCE 0.0005f
static const int MESHDEFORM_OFFSET[7][3] = {
- {0, 0, 0}, {1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1},
+ {0, 0, 0},
+ {1, 0, 0},
+ {-1, 0, 0},
+ {0, 1, 0},
+ {0, -1, 0},
+ {0, 0, 1},
+ {0, 0, -1},
};
typedef struct MDefBoundIsect {
- /* intersection on the cage 'cagecos' */
- float co[3];
- /* non-facing intersections are considered interior */
- bool facing;
- /* ray-cast index aligned with MPoly (ray-hit-triangle isn't needed) */
- int poly_index;
- /* distance from 'co' to the ray-cast start (clamped to avoid zero division) */
- float len;
- /* weights aligned with the MPoly's loop indices */
- float poly_weights[0];
+ /* intersection on the cage 'cagecos' */
+ float co[3];
+ /* non-facing intersections are considered interior */
+ bool facing;
+ /* ray-cast index aligned with MPoly (ray-hit-triangle isn't needed) */
+ int poly_index;
+ /* distance from 'co' to the ray-cast start (clamped to avoid zero division) */
+ float len;
+ /* weights aligned with the MPoly's loop indices */
+ float poly_weights[0];
} MDefBoundIsect;
typedef struct MDefBindInfluence {
- struct MDefBindInfluence *next;
- float weight;
- int vertex;
+ struct MDefBindInfluence *next;
+ float weight;
+ int vertex;
} MDefBindInfluence;
typedef struct MeshDeformBind {
- /* grid dimensions */
- float min[3], max[3];
- float width[3], halfwidth[3];
- int size, size3;
-
- /* meshes */
- Mesh *cagemesh;
- float (*cagecos)[3];
- float (*vertexcos)[3];
- int totvert, totcagevert;
-
- /* grids */
- MemArena *memarena;
- MDefBoundIsect *(*boundisect)[6];
- int *semibound;
- int *tag;
- float *phi, *totalphi;
-
- /* mesh stuff */
- int *inside;
- float *weights;
- MDefBindInfluence **dyngrid;
- float cagemat[4][4];
-
- /* direct solver */
- int *varidx;
-
- BVHTree *bvhtree;
- BVHTreeFromMesh bvhdata;
-
- /* avoid DM function calls during intersections */
- struct {
- const MPoly *mpoly;
- const MLoop *mloop;
- const MLoopTri *looptri;
- const float (*poly_nors)[3];
- } cagemesh_cache;
+ /* grid dimensions */
+ float min[3], max[3];
+ float width[3], halfwidth[3];
+ int size, size3;
+
+ /* meshes */
+ Mesh *cagemesh;
+ float (*cagecos)[3];
+ float (*vertexcos)[3];
+ int totvert, totcagevert;
+
+ /* grids */
+ MemArena *memarena;
+ MDefBoundIsect *(*boundisect)[6];
+ int *semibound;
+ int *tag;
+ float *phi, *totalphi;
+
+ /* mesh stuff */
+ int *inside;
+ float *weights;
+ MDefBindInfluence **dyngrid;
+ float cagemat[4][4];
+
+ /* direct solver */
+ int *varidx;
+
+ BVHTree *bvhtree;
+ BVHTreeFromMesh bvhdata;
+
+ /* avoid DM function calls during intersections */
+ struct {
+ const MPoly *mpoly;
+ const MLoop *mloop;
+ const MLoopTri *looptri;
+ const float (*poly_nors)[3];
+ } cagemesh_cache;
} MeshDeformBind;
typedef struct MeshDeformIsect {
- float start[3];
- float vec[3];
- float vec_length;
- float lambda;
+ float start[3];
+ float vec[3];
+ float vec_length;
+ float lambda;
- bool isect;
- float u, v;
+ bool isect;
+ float u, v;
} MeshDeformIsect;
/* ray intersection */
struct MeshRayCallbackData {
- MeshDeformBind *mdb;
- MeshDeformIsect *isec;
+ MeshDeformBind *mdb;
+ MeshDeformIsect *isec;
};
-static void harmonic_ray_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+static void harmonic_ray_callback(void *userdata,
+ int index,
+ const BVHTreeRay *ray,
+ BVHTreeRayHit *hit)
{
- struct MeshRayCallbackData *data = userdata;
- MeshDeformBind *mdb = data->mdb;
- const MLoop *mloop = mdb->cagemesh_cache.mloop;
- const MLoopTri *looptri = mdb->cagemesh_cache.looptri, *lt;
- const float (*poly_nors)[3] = mdb->cagemesh_cache.poly_nors;
- MeshDeformIsect *isec = data->isec;
- float no[3], co[3], dist;
- float *face[3];
-
- lt = &looptri[index];
-
- face[0] = mdb->cagecos[mloop[lt->tri[0]].v];
- face[1] = mdb->cagecos[mloop[lt->tri[1]].v];
- face[2] = mdb->cagecos[mloop[lt->tri[2]].v];
-
- bool isect_ray_tri = isect_ray_tri_watertight_v3(
- ray->origin, ray->isect_precalc, UNPACK3(face), &dist, NULL);
-
- if (!isect_ray_tri || dist > isec->vec_length) {
- return;
- }
-
- if (poly_nors) {
- copy_v3_v3(no, poly_nors[lt->poly]);
- }
- else {
- normal_tri_v3(no, UNPACK3(face));
- }
-
- madd_v3_v3v3fl(co, ray->origin, ray->direction, dist);
- dist /= isec->vec_length;
- if (dist < hit->dist) {
- hit->index = index;
- hit->dist = dist;
- copy_v3_v3(hit->co, co);
-
- isec->isect = (dot_v3v3(no, ray->direction) <= 0.0f);
- isec->lambda = dist;
- }
+ struct MeshRayCallbackData *data = userdata;
+ MeshDeformBind *mdb = data->mdb;
+ const MLoop *mloop = mdb->cagemesh_cache.mloop;
+ const MLoopTri *looptri = mdb->cagemesh_cache.looptri, *lt;
+ const float(*poly_nors)[3] = mdb->cagemesh_cache.poly_nors;
+ MeshDeformIsect *isec = data->isec;
+ float no[3], co[3], dist;
+ float *face[3];
+
+ lt = &looptri[index];
+
+ face[0] = mdb->cagecos[mloop[lt->tri[0]].v];
+ face[1] = mdb->cagecos[mloop[lt->tri[1]].v];
+ face[2] = mdb->cagecos[mloop[lt->tri[2]].v];
+
+ bool isect_ray_tri = isect_ray_tri_watertight_v3(
+ ray->origin, ray->isect_precalc, UNPACK3(face), &dist, NULL);
+
+ if (!isect_ray_tri || dist > isec->vec_length) {
+ return;
+ }
+
+ if (poly_nors) {
+ copy_v3_v3(no, poly_nors[lt->poly]);
+ }
+ else {
+ normal_tri_v3(no, UNPACK3(face));
+ }
+
+ madd_v3_v3v3fl(co, ray->origin, ray->direction, dist);
+ dist /= isec->vec_length;
+ if (dist < hit->dist) {
+ hit->index = index;
+ hit->dist = dist;
+ copy_v3_v3(hit->co, co);
+
+ isec->isect = (dot_v3v3(no, ray->direction) <= 0.0f);
+ isec->lambda = dist;
+ }
}
-static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, const float co1[3], const float co2[3])
+static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb,
+ const float co1[3],
+ const float co2[3])
{
- BVHTreeRayHit hit;
- MeshDeformIsect isect_mdef;
- struct MeshRayCallbackData data = {
- mdb,
- &isect_mdef,
- };
- float end[3], vec_normal[3];
-
- /* happens binding when a cage has no faces */
- if (UNLIKELY(mdb->bvhtree == NULL))
- return NULL;
-
- /* setup isec */
- memset(&isect_mdef, 0, sizeof(isect_mdef));
- isect_mdef.lambda = 1e10f;
-
- copy_v3_v3(isect_mdef.start, co1);
- copy_v3_v3(end, co2);
- sub_v3_v3v3(isect_mdef.vec, end, isect_mdef.start);
- isect_mdef.vec_length = normalize_v3_v3(vec_normal, isect_mdef.vec);
-
- hit.index = -1;
- hit.dist = BVH_RAYCAST_DIST_MAX;
- if (BLI_bvhtree_ray_cast_ex(mdb->bvhtree, isect_mdef.start, vec_normal,
- 0.0, &hit, harmonic_ray_callback, &data, BVH_RAYCAST_WATERTIGHT) != -1)
- {
- const MLoop *mloop = mdb->cagemesh_cache.mloop;
- const MLoopTri *lt = &mdb->cagemesh_cache.looptri[hit.index];
- const MPoly *mp = &mdb->cagemesh_cache.mpoly[lt->poly];
- const float (*cagecos)[3] = mdb->cagecos;
- const float len = isect_mdef.lambda;
- MDefBoundIsect *isect;
-
- float (*mp_cagecos)[3] = BLI_array_alloca(mp_cagecos, mp->totloop);
- int i;
-
- /* create MDefBoundIsect, and extra for 'poly_weights[]' */
- isect = BLI_memarena_alloc(mdb->memarena, sizeof(*isect) + (sizeof(float) * mp->totloop));
-
- /* compute intersection coordinate */
- madd_v3_v3v3fl(isect->co, co1, isect_mdef.vec, len);
-
- isect->facing = isect_mdef.isect;
-
- isect->poly_index = lt->poly;
-
- isect->len = max_ff(len_v3v3(co1, isect->co), MESHDEFORM_LEN_THRESHOLD);
-
- /* compute mean value coordinates for interpolation */
- for (i = 0; i < mp->totloop; i++) {
- copy_v3_v3(mp_cagecos[i], cagecos[mloop[mp->loopstart + i].v]);
- }
-
- interp_weights_poly_v3(isect->poly_weights, mp_cagecos, mp->totloop, isect->co);
-
- return isect;
- }
-
- return NULL;
+ BVHTreeRayHit hit;
+ MeshDeformIsect isect_mdef;
+ struct MeshRayCallbackData data = {
+ mdb,
+ &isect_mdef,
+ };
+ float end[3], vec_normal[3];
+
+ /* happens binding when a cage has no faces */
+ if (UNLIKELY(mdb->bvhtree == NULL))
+ return NULL;
+
+ /* setup isec */
+ memset(&isect_mdef, 0, sizeof(isect_mdef));
+ isect_mdef.lambda = 1e10f;
+
+ copy_v3_v3(isect_mdef.start, co1);
+ copy_v3_v3(end, co2);
+ sub_v3_v3v3(isect_mdef.vec, end, isect_mdef.start);
+ isect_mdef.vec_length = normalize_v3_v3(vec_normal, isect_mdef.vec);
+
+ hit.index = -1;
+ hit.dist = BVH_RAYCAST_DIST_MAX;
+ if (BLI_bvhtree_ray_cast_ex(mdb->bvhtree,
+ isect_mdef.start,
+ vec_normal,
+ 0.0,
+ &hit,
+ harmonic_ray_callback,
+ &data,
+ BVH_RAYCAST_WATERTIGHT) != -1) {
+ const MLoop *mloop = mdb->cagemesh_cache.mloop;
+ const MLoopTri *lt = &mdb->cagemesh_cache.looptri[hit.index];
+ const MPoly *mp = &mdb->cagemesh_cache.mpoly[lt->poly];
+ const float(*cagecos)[3] = mdb->cagecos;
+ const float len = isect_mdef.lambda;
+ MDefBoundIsect *isect;
+
+ float(*mp_cagecos)[3] = BLI_array_alloca(mp_cagecos, mp->totloop);
+ int i;
+
+ /* create MDefBoundIsect, and extra for 'poly_weights[]' */
+ isect = BLI_memarena_alloc(mdb->memarena, sizeof(*isect) + (sizeof(float) * mp->totloop));
+
+ /* compute intersection coordinate */
+ madd_v3_v3v3fl(isect->co, co1, isect_mdef.vec, len);
+
+ isect->facing = isect_mdef.isect;
+
+ isect->poly_index = lt->poly;
+
+ isect->len = max_ff(len_v3v3(co1, isect->co), MESHDEFORM_LEN_THRESHOLD);
+
+ /* compute mean value coordinates for interpolation */
+ for (i = 0; i < mp->totloop; i++) {
+ copy_v3_v3(mp_cagecos[i], cagecos[mloop[mp->loopstart + i].v]);
+ }
+
+ interp_weights_poly_v3(isect->poly_weights, mp_cagecos, mp->totloop, isect->co);
+
+ return isect;
+ }
+
+ return NULL;
}
static int meshdeform_inside_cage(MeshDeformBind *mdb, float *co)
{
- MDefBoundIsect *isect;
- float outside[3], start[3], dir[3];
- int i;
+ MDefBoundIsect *isect;
+ float outside[3], start[3], dir[3];
+ int i;
- for (i = 1; i <= 6; i++) {
- outside[0] = co[0] + (mdb->max[0] - mdb->min[0] + 1.0f) * MESHDEFORM_OFFSET[i][0];
- outside[1] = co[1] + (mdb->max[1] - mdb->min[1] + 1.0f) * MESHDEFORM_OFFSET[i][1];
- outside[2] = co[2] + (mdb->max[2] - mdb->min[2] + 1.0f) * MESHDEFORM_OFFSET[i][2];
+ for (i = 1; i <= 6; i++) {
+ outside[0] = co[0] + (mdb->max[0] - mdb->min[0] + 1.0f) * MESHDEFORM_OFFSET[i][0];
+ outside[1] = co[1] + (mdb->max[1] - mdb->min[1] + 1.0f) * MESHDEFORM_OFFSET[i][1];
+ outside[2] = co[2] + (mdb->max[2] - mdb->min[2] + 1.0f) * MESHDEFORM_OFFSET[i][2];
- copy_v3_v3(start, co);
- sub_v3_v3v3(dir, outside, start);
- normalize_v3(dir);
+ copy_v3_v3(start, co);
+ sub_v3_v3v3(dir, outside, start);
+ normalize_v3(dir);
- isect = meshdeform_ray_tree_intersect(mdb, start, outside);
- if (isect && !isect->facing)
- return 1;
- }
+ isect = meshdeform_ray_tree_intersect(mdb, start, outside);
+ if (isect && !isect->facing)
+ return 1;
+ }
- return 0;
+ return 0;
}
/* solving */
BLI_INLINE int meshdeform_index(MeshDeformBind *mdb, int x, int y, int z, int n)
{
- int size = mdb->size;
+ int size = mdb->size;
- x += MESHDEFORM_OFFSET[n][0];
- y += MESHDEFORM_OFFSET[n][1];
- z += MESHDEFORM_OFFSET[n][2];
+ x += MESHDEFORM_OFFSET[n][0];
+ y += MESHDEFORM_OFFSET[n][1];
+ z += MESHDEFORM_OFFSET[n][2];
- if (x < 0 || x >= mdb->size)
- return -1;
- if (y < 0 || y >= mdb->size)
- return -1;
- if (z < 0 || z >= mdb->size)
- return -1;
+ if (x < 0 || x >= mdb->size)
+ return -1;
+ if (y < 0 || y >= mdb->size)
+ return -1;
+ if (z < 0 || z >= mdb->size)
+ return -1;
- return x + y * size + z * size * size;
+ return x + y * size + z * size * size;
}
-BLI_INLINE void meshdeform_cell_center(MeshDeformBind *mdb, int x, int y, int z, int n, float *center)
+BLI_INLINE void meshdeform_cell_center(
+ MeshDeformBind *mdb, int x, int y, int z, int n, float *center)
{
- x += MESHDEFORM_OFFSET[n][0];
- y += MESHDEFORM_OFFSET[n][1];
- z += MESHDEFORM_OFFSET[n][2];
+ x += MESHDEFORM_OFFSET[n][0];
+ y += MESHDEFORM_OFFSET[n][1];
+ z += MESHDEFORM_OFFSET[n][2];
- center[0] = mdb->min[0] + x * mdb->width[0] + mdb->halfwidth[0];
- center[1] = mdb->min[1] + y * mdb->width[1] + mdb->halfwidth[1];
- center[2] = mdb->min[2] + z * mdb->width[2] + mdb->halfwidth[2];
+ center[0] = mdb->min[0] + x * mdb->width[0] + mdb->halfwidth[0];
+ center[1] = mdb->min[1] + y * mdb->width[1] + mdb->halfwidth[1];
+ center[2] = mdb->min[2] + z * mdb->width[2] + mdb->halfwidth[2];
}
static void meshdeform_add_intersections(MeshDeformBind *mdb, int x, int y, int z)
{
- MDefBoundIsect *isect;
- float center[3], ncenter[3];
- int i, a;
-
- a = meshdeform_index(mdb, x, y, z, 0);
- meshdeform_cell_center(mdb, x, y, z, 0, center);
-
- /* check each outgoing edge for intersection */
- for (i = 1; i <= 6; i++) {
- if (meshdeform_index(mdb, x, y, z, i) == -1)
- continue;
-
- meshdeform_cell_center(mdb, x, y, z, i, ncenter);
-
- isect = meshdeform_ray_tree_intersect(mdb, center, ncenter);
- if (isect) {
- mdb->boundisect[a][i - 1] = isect;
- mdb->tag[a] = MESHDEFORM_TAG_BOUNDARY;
- }
- }
+ MDefBoundIsect *isect;
+ float center[3], ncenter[3];
+ int i, a;
+
+ a = meshdeform_index(mdb, x, y, z, 0);
+ meshdeform_cell_center(mdb, x, y, z, 0, center);
+
+ /* check each outgoing edge for intersection */
+ for (i = 1; i <= 6; i++) {
+ if (meshdeform_index(mdb, x, y, z, i) == -1)
+ continue;
+
+ meshdeform_cell_center(mdb, x, y, z, i, ncenter);
+
+ isect = meshdeform_ray_tree_intersect(mdb, center, ncenter);
+ if (isect) {
+ mdb->boundisect[a][i - 1] = isect;
+ mdb->tag[a] = MESHDEFORM_TAG_BOUNDARY;
+ }
+ }
}
static void meshdeform_bind_floodfill(MeshDeformBind *mdb)
{
- int *stack, *tag = mdb->tag;
- int a, b, i, xyz[3], stacksize, size = mdb->size;
-
- stack = MEM_callocN(sizeof(int) * mdb->size3, "MeshDeformBindStack");
-
- /* we know lower left corner is EXTERIOR because of padding */
- tag[0] = MESHDEFORM_TAG_EXTERIOR;
- stack[0] = 0;
- stacksize = 1;
-
- /* floodfill exterior tag */
- while (stacksize > 0) {
- a = stack[--stacksize];
-
- xyz[2] = a / (size * size);
- xyz[1] = (a - xyz[2] * size * size) / size;
- xyz[0] = a - xyz[1] * size - xyz[2] * size * size;
-
- for (i = 1; i <= 6; i++) {
- b = meshdeform_index(mdb, xyz[0], xyz[1], xyz[2], i);
-
- if (b != -1) {
- if (tag[b] == MESHDEFORM_TAG_UNTYPED ||
- (tag[b] == MESHDEFORM_TAG_BOUNDARY && !mdb->boundisect[a][i - 1]))
- {
- tag[b] = MESHDEFORM_TAG_EXTERIOR;
- stack[stacksize++] = b;
- }
- }
- }
- }
-
- /* other cells are interior */
- for (a = 0; a < size * size * size; a++)
- if (tag[a] == MESHDEFORM_TAG_UNTYPED)
- tag[a] = MESHDEFORM_TAG_INTERIOR;
+ int *stack, *tag = mdb->tag;
+ int a, b, i, xyz[3], stacksize, size = mdb->size;
+
+ stack = MEM_callocN(sizeof(int) * mdb->size3, "MeshDeformBindStack");
+
+ /* we know lower left corner is EXTERIOR because of padding */
+ tag[0] = MESHDEFORM_TAG_EXTERIOR;
+ stack[0] = 0;
+ stacksize = 1;
+
+ /* floodfill exterior tag */
+ while (stacksize > 0) {
+ a = stack[--stacksize];
+
+ xyz[2] = a / (size * size);
+ xyz[1] = (a - xyz[2] * size * size) / size;
+ xyz[0] = a - xyz[1] * size - xyz[2] * size * size;
+
+ for (i = 1; i <= 6; i++) {
+ b = meshdeform_index(mdb, xyz[0], xyz[1], xyz[2], i);
+
+ if (b != -1) {
+ if (tag[b] == MESHDEFORM_TAG_UNTYPED ||
+ (tag[b] == MESHDEFORM_TAG_BOUNDARY && !mdb->boundisect[a][i - 1])) {
+ tag[b] = MESHDEFORM_TAG_EXTERIOR;
+ stack[stacksize++] = b;
+ }
+ }
+ }
+ }
+
+ /* other cells are interior */
+ for (a = 0; a < size * size * size; a++)
+ if (tag[a] == MESHDEFORM_TAG_UNTYPED)
+ tag[a] = MESHDEFORM_TAG_INTERIOR;
#if 0
- {
- int tb, ti, te, ts;
- tb = ti = te = ts = 0;
- for (a = 0; a < size * size * size; a++)
- if (tag[a] == MESHDEFORM_TAG_BOUNDARY)
- tb++;
- else if (tag[a] == MESHDEFORM_TAG_INTERIOR)
- ti++;
- else if (tag[a] == MESHDEFORM_TAG_EXTERIOR) {
- te++;
-
- if (mdb->semibound[a])
- ts++;
- }
-
- printf("interior %d exterior %d boundary %d semi-boundary %d\n", ti, te, tb, ts);
- }
+ {
+ int tb, ti, te, ts;
+ tb = ti = te = ts = 0;
+ for (a = 0; a < size * size * size; a++)
+ if (tag[a] == MESHDEFORM_TAG_BOUNDARY)
+ tb++;
+ else if (tag[a] == MESHDEFORM_TAG_INTERIOR)
+ ti++;
+ else if (tag[a] == MESHDEFORM_TAG_EXTERIOR) {
+ te++;
+
+ if (mdb->semibound[a])
+ ts++;
+ }
+
+ printf("interior %d exterior %d boundary %d semi-boundary %d\n", ti, te, tb, ts);
+ }
#endif
- MEM_freeN(stack);
+ MEM_freeN(stack);
}
-static float meshdeform_boundary_phi(const MeshDeformBind *mdb, const MDefBoundIsect *isect, int cagevert)
+static float meshdeform_boundary_phi(const MeshDeformBind *mdb,
+ const MDefBoundIsect *isect,
+ int cagevert)
{
- const MLoop *mloop = mdb->cagemesh_cache.mloop;
- const MPoly *mp = &mdb->cagemesh_cache.mpoly[isect->poly_index];
- int i;
+ const MLoop *mloop = mdb->cagemesh_cache.mloop;
+ const MPoly *mp = &mdb->cagemesh_cache.mpoly[isect->poly_index];
+ int i;
- for (i = 0; i < mp->totloop; i++) {
- if (mloop[mp->loopstart + i].v == cagevert) {
- return isect->poly_weights[i];
- }
- }
+ for (i = 0; i < mp->totloop; i++) {
+ if (mloop[mp->loopstart + i].v == cagevert) {
+ return isect->poly_weights[i];
+ }
+ }
- return 0.0f;
+ return 0.0f;
}
-static float meshdeform_interp_w(MeshDeformBind *mdb, float *gridvec, float *UNUSED(vec), int UNUSED(cagevert))
+static float meshdeform_interp_w(MeshDeformBind *mdb,
+ float *gridvec,
+ float *UNUSED(vec),
+ int UNUSED(cagevert))
{
- float dvec[3], ivec[3], wx, wy, wz, result = 0.0f;
- float weight, totweight = 0.0f;
- int i, a, x, y, z;
-
- for (i = 0; i < 3; i++) {
- ivec[i] = (int)gridvec[i];
- dvec[i] = gridvec[i] - ivec[i];
- }
-
- for (i = 0; i < 8; i++) {
- if (i & 1) { x = ivec[0] + 1; wx = dvec[0]; }
- else { x = ivec[0]; wx = 1.0f - dvec[0]; }
-
- if (i & 2) { y = ivec[1] + 1; wy = dvec[1]; }
- else { y = ivec[1]; wy = 1.0f - dvec[1]; }
-
- if (i & 4) { z = ivec[2] + 1; wz = dvec[2]; }
- else { z = ivec[2]; wz = 1.0f - dvec[2]; }
-
- CLAMP(x, 0, mdb->size - 1);
- CLAMP(y, 0, mdb->size - 1);
- CLAMP(z, 0, mdb->size - 1);
-
- a = meshdeform_index(mdb, x, y, z, 0);
- weight = wx * wy * wz;
- result += weight * mdb->phi[a];
- totweight += weight;
- }
-
- if (totweight > 0.0f)
- result /= totweight;
-
- return result;
+ float dvec[3], ivec[3], wx, wy, wz, result = 0.0f;
+ float weight, totweight = 0.0f;
+ int i, a, x, y, z;
+
+ for (i = 0; i < 3; i++) {
+ ivec[i] = (int)gridvec[i];
+ dvec[i] = gridvec[i] - ivec[i];
+ }
+
+ for (i = 0; i < 8; i++) {
+ if (i & 1) {
+ x = ivec[0] + 1;
+ wx = dvec[0];
+ }
+ else {
+ x = ivec[0];
+ wx = 1.0f - dvec[0];
+ }
+
+ if (i & 2) {
+ y = ivec[1] + 1;
+ wy = dvec[1];
+ }
+ else {
+ y = ivec[1];
+ wy = 1.0f - dvec[1];
+ }
+
+ if (i & 4) {
+ z = ivec[2] + 1;
+ wz = dvec[2];
+ }
+ else {
+ z = ivec[2];
+ wz = 1.0f - dvec[2];
+ }
+
+ CLAMP(x, 0, mdb->size - 1);
+ CLAMP(y, 0, mdb->size - 1);
+ CLAMP(z, 0, mdb->size - 1);
+
+ a = meshdeform_index(mdb, x, y, z, 0);
+ weight = wx * wy * wz;
+ result += weight * mdb->phi[a];
+ totweight += weight;
+ }
+
+ if (totweight > 0.0f)
+ result /= totweight;
+
+ return result;
}
static void meshdeform_check_semibound(MeshDeformBind *mdb, int x, int y, int z)
{
- int i, a;
+ int i, a;
- a = meshdeform_index(mdb, x, y, z, 0);
- if (mdb->tag[a] != MESHDEFORM_TAG_EXTERIOR)
- return;
+ a = meshdeform_index(mdb, x, y, z, 0);
+ if (mdb->tag[a] != MESHDEFORM_TAG_EXTERIOR)
+ return;
- for (i = 1; i <= 6; i++)
- if (mdb->boundisect[a][i - 1])
- mdb->semibound[a] = 1;
+ for (i = 1; i <= 6; i++)
+ if (mdb->boundisect[a][i - 1])
+ mdb->semibound[a] = 1;
}
static float meshdeform_boundary_total_weight(MeshDeformBind *mdb, int x, int y, int z)
{
- float weight, totweight = 0.0f;
- int i, a;
+ float weight, totweight = 0.0f;
+ int i, a;
- a = meshdeform_index(mdb, x, y, z, 0);
+ a = meshdeform_index(mdb, x, y, z, 0);
- /* count weight for neighbor cells */
- for (i = 1; i <= 6; i++) {
- if (meshdeform_index(mdb, x, y, z, i) == -1)
- continue;
+ /* count weight for neighbor cells */
+ for (i = 1; i <= 6; i++) {
+ if (meshdeform_index(mdb, x, y, z, i) == -1)
+ continue;
- if (mdb->boundisect[a][i - 1])
- weight = 1.0f / mdb->boundisect[a][i - 1]->len;
- else if (!mdb->semibound[a])
- weight = 1.0f / mdb->width[0];
- else
- weight = 0.0f;
+ if (mdb->boundisect[a][i - 1])
+ weight = 1.0f / mdb->boundisect[a][i - 1]->len;
+ else if (!mdb->semibound[a])
+ weight = 1.0f / mdb->width[0];
+ else
+ weight = 0.0f;
- totweight += weight;
- }
+ totweight += weight;
+ }
- return totweight;
+ return totweight;
}
-static void meshdeform_matrix_add_cell(MeshDeformBind *mdb, LinearSolver *context, int x, int y, int z)
+static void meshdeform_matrix_add_cell(
+ MeshDeformBind *mdb, LinearSolver *context, int x, int y, int z)
{
- MDefBoundIsect *isect;
- float weight, totweight;
- int i, a, acenter;
-
- acenter = meshdeform_index(mdb, x, y, z, 0);
- if (mdb->tag[acenter] == MESHDEFORM_TAG_EXTERIOR)
- return;
-
- EIG_linear_solver_matrix_add(context, mdb->varidx[acenter], mdb->varidx[acenter], 1.0f);
-
- totweight = meshdeform_boundary_total_weight(mdb, x, y, z);
- for (i = 1; i <= 6; i++) {
- a = meshdeform_index(mdb, x, y, z, i);
- if (a == -1 || mdb->tag[a] == MESHDEFORM_TAG_EXTERIOR)
- continue;
-
- isect = mdb->boundisect[acenter][i - 1];
- if (!isect) {
- weight = (1.0f / mdb->width[0]) / totweight;
- EIG_linear_solver_matrix_add(context, mdb->varidx[acenter], mdb->varidx[a], -weight);
- }
- }
+ MDefBoundIsect *isect;
+ float weight, totweight;
+ int i, a, acenter;
+
+ acenter = meshdeform_index(mdb, x, y, z, 0);
+ if (mdb->tag[acenter] == MESHDEFORM_TAG_EXTERIOR)
+ return;
+
+ EIG_linear_solver_matrix_add(context, mdb->varidx[acenter], mdb->varidx[acenter], 1.0f);
+
+ totweight = meshdeform_boundary_total_weight(mdb, x, y, z);
+ for (i = 1; i <= 6; i++) {
+ a = meshdeform_index(mdb, x, y, z, i);
+ if (a == -1 || mdb->tag[a] == MESHDEFORM_TAG_EXTERIOR)
+ continue;
+
+ isect = mdb->boundisect[acenter][i - 1];
+ if (!isect) {
+ weight = (1.0f / mdb->width[0]) / totweight;
+ EIG_linear_solver_matrix_add(context, mdb->varidx[acenter], mdb->varidx[a], -weight);
+ }
+ }
}
-static void meshdeform_matrix_add_rhs(MeshDeformBind *mdb, LinearSolver *context, int x, int y, int z, int cagevert)
+static void meshdeform_matrix_add_rhs(
+ MeshDeformBind *mdb, LinearSolver *context, int x, int y, int z, int cagevert)
{
- MDefBoundIsect *isect;
- float rhs, weight, totweight;
- int i, a, acenter;
-
- acenter = meshdeform_index(mdb, x, y, z, 0);
- if (mdb->tag[acenter] == MESHDEFORM_TAG_EXTERIOR)
- return;
-
- totweight = meshdeform_boundary_total_weight(mdb, x, y, z);
- for (i = 1; i <= 6; i++) {
- a = meshdeform_index(mdb, x, y, z, i);
- if (a == -1)
- continue;
-
- isect = mdb->boundisect[acenter][i - 1];
-
- if (isect) {
- weight = (1.0f / isect->len) / totweight;
- rhs = weight * meshdeform_boundary_phi(mdb, isect, cagevert);
- EIG_linear_solver_right_hand_side_add(context, 0, mdb->varidx[acenter], rhs);
- }
- }
+ MDefBoundIsect *isect;
+ float rhs, weight, totweight;
+ int i, a, acenter;
+
+ acenter = meshdeform_index(mdb, x, y, z, 0);
+ if (mdb->tag[acenter] == MESHDEFORM_TAG_EXTERIOR)
+ return;
+
+ totweight = meshdeform_boundary_total_weight(mdb, x, y, z);
+ for (i = 1; i <= 6; i++) {
+ a = meshdeform_index(mdb, x, y, z, i);
+ if (a == -1)
+ continue;
+
+ isect = mdb->boundisect[acenter][i - 1];
+
+ if (isect) {
+ weight = (1.0f / isect->len) / totweight;
+ rhs = weight * meshdeform_boundary_phi(mdb, isect, cagevert);
+ EIG_linear_solver_right_hand_side_add(context, 0, mdb->varidx[acenter], rhs);
+ }
+ }
}
-static void meshdeform_matrix_add_semibound_phi(MeshDeformBind *mdb, int x, int y, int z, int cagevert)
+static void meshdeform_matrix_add_semibound_phi(
+ MeshDeformBind *mdb, int x, int y, int z, int cagevert)
{
- MDefBoundIsect *isect;
- float rhs, weight, totweight;
- int i, a;
-
- a = meshdeform_index(mdb, x, y, z, 0);
- if (!mdb->semibound[a])
- return;
-
- mdb->phi[a] = 0.0f;
-
- totweight = meshdeform_boundary_total_weight(mdb, x, y, z);
- for (i = 1; i <= 6; i++) {
- isect = mdb->boundisect[a][i - 1];
-
- if (isect) {
- weight = (1.0f / isect->len) / totweight;
- rhs = weight * meshdeform_boundary_phi(mdb, isect, cagevert);
- mdb->phi[a] += rhs;
- }
- }
+ MDefBoundIsect *isect;
+ float rhs, weight, totweight;
+ int i, a;
+
+ a = meshdeform_index(mdb, x, y, z, 0);
+ if (!mdb->semibound[a])
+ return;
+
+ mdb->phi[a] = 0.0f;
+
+ totweight = meshdeform_boundary_total_weight(mdb, x, y, z);
+ for (i = 1; i <= 6; i++) {
+ isect = mdb->boundisect[a][i - 1];
+
+ if (isect) {
+ weight = (1.0f / isect->len) / totweight;
+ rhs = weight * meshdeform_boundary_phi(mdb, isect, cagevert);
+ mdb->phi[a] += rhs;
+ }
+ }
}
-static void meshdeform_matrix_add_exterior_phi(MeshDeformBind *mdb, int x, int y, int z, int UNUSED(cagevert))
+static void meshdeform_matrix_add_exterior_phi(
+ MeshDeformBind *mdb, int x, int y, int z, int UNUSED(cagevert))
{
- float phi, totweight;
- int i, a, acenter;
-
- acenter = meshdeform_index(mdb, x, y, z, 0);
- if (mdb->tag[acenter] != MESHDEFORM_TAG_EXTERIOR || mdb->semibound[acenter])
- return;
-
- phi = 0.0f;
- totweight = 0.0f;
- for (i = 1; i <= 6; i++) {
- a = meshdeform_index(mdb, x, y, z, i);
-
- if (a != -1 && mdb->semibound[a]) {
- phi += mdb->phi[a];
- totweight += 1.0f;
- }
- }
-
- if (totweight != 0.0f)
- mdb->phi[acenter] = phi / totweight;
+ float phi, totweight;
+ int i, a, acenter;
+
+ acenter = meshdeform_index(mdb, x, y, z, 0);
+ if (mdb->tag[acenter] != MESHDEFORM_TAG_EXTERIOR || mdb->semibound[acenter])
+ return;
+
+ phi = 0.0f;
+ totweight = 0.0f;
+ for (i = 1; i <= 6; i++) {
+ a = meshdeform_index(mdb, x, y, z, i);
+
+ if (a != -1 && mdb->semibound[a]) {
+ phi += mdb->phi[a];
+ totweight += 1.0f;
+ }
+ }
+
+ if (totweight != 0.0f)
+ mdb->phi[acenter] = phi / totweight;
}
static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind *mdb)
{
- LinearSolver *context;
- float vec[3], gridvec[3];
- int a, b, x, y, z, totvar;
- char message[256];
-
- /* setup variable indices */
- mdb->varidx = MEM_callocN(sizeof(int) * mdb->size3, "MeshDeformDSvaridx");
- for (a = 0, totvar = 0; a < mdb->size3; a++)
- mdb->varidx[a] = (mdb->tag[a] == MESHDEFORM_TAG_EXTERIOR) ? -1 : totvar++;
-
- if (totvar == 0) {
- MEM_freeN(mdb->varidx);
- return;
- }
-
- progress_bar(0, "Starting mesh deform solve");
-
- /* setup linear solver */
- context = EIG_linear_solver_new(totvar, totvar, 1);
-
- /* build matrix */
- for (z = 0; z < mdb->size; z++)
- for (y = 0; y < mdb->size; y++)
- for (x = 0; x < mdb->size; x++)
- meshdeform_matrix_add_cell(mdb, context, x, y, z);
-
- /* solve for each cage vert */
- for (a = 0; a < mdb->totcagevert; a++) {
- /* fill in right hand side and solve */
- for (z = 0; z < mdb->size; z++)
- for (y = 0; y < mdb->size; y++)
- for (x = 0; x < mdb->size; x++)
- meshdeform_matrix_add_rhs(mdb, context, x, y, z, a);
-
- if (EIG_linear_solver_solve(context)) {
- for (z = 0; z < mdb->size; z++)
- for (y = 0; y < mdb->size; y++)
- for (x = 0; x < mdb->size; x++)
- meshdeform_matrix_add_semibound_phi(mdb, x, y, z, a);
-
- for (z = 0; z < mdb->size; z++)
- for (y = 0; y < mdb->size; y++)
- for (x = 0; x < mdb->size; x++)
- meshdeform_matrix_add_exterior_phi(mdb, x, y, z, a);
-
- for (b = 0; b < mdb->size3; b++) {
- if (mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR)
- mdb->phi[b] = EIG_linear_solver_variable_get(context, 0, mdb->varidx[b]);
- mdb->totalphi[b] += mdb->phi[b];
- }
-
- if (mdb->weights) {
- /* static bind : compute weights for each vertex */
- for (b = 0; b < mdb->totvert; b++) {
- if (mdb->inside[b]) {
- copy_v3_v3(vec, mdb->vertexcos[b]);
- gridvec[0] = (vec[0] - mdb->min[0] - mdb->halfwidth[0]) / mdb->width[0];
- gridvec[1] = (vec[1] - mdb->min[1] - mdb->halfwidth[1]) / mdb->width[1];
- gridvec[2] = (vec[2] - mdb->min[2] - mdb->halfwidth[2]) / mdb->width[2];
-
- mdb->weights[b * mdb->totcagevert + a] = meshdeform_interp_w(mdb, gridvec, vec, a);
- }
- }
- }
- else {
- MDefBindInfluence *inf;
-
- /* dynamic bind */
- for (b = 0; b < mdb->size3; b++) {
- if (mdb->phi[b] >= MESHDEFORM_MIN_INFLUENCE) {
- inf = BLI_memarena_alloc(mdb->memarena, sizeof(*inf));
- inf->vertex = a;
- inf->weight = mdb->phi[b];
- inf->next = mdb->dyngrid[b];
- mdb->dyngrid[b] = inf;
- }
- }
- }
- }
- else {
- modifier_setError(&mmd->modifier, "Failed to find bind solution (increase precision?)");
- error("Mesh Deform: failed to find bind solution.");
- break;
- }
-
- BLI_snprintf(message, sizeof(message), "Mesh deform solve %d / %d |||", a + 1, mdb->totcagevert);
- progress_bar((float)(a + 1) / (float)(mdb->totcagevert), message);
- }
+ LinearSolver *context;
+ float vec[3], gridvec[3];
+ int a, b, x, y, z, totvar;
+ char message[256];
+
+ /* setup variable indices */
+ mdb->varidx = MEM_callocN(sizeof(int) * mdb->size3, "MeshDeformDSvaridx");
+ for (a = 0, totvar = 0; a < mdb->size3; a++)
+ mdb->varidx[a] = (mdb->tag[a] == MESHDEFORM_TAG_EXTERIOR) ? -1 : totvar++;
+
+ if (totvar == 0) {
+ MEM_freeN(mdb->varidx);
+ return;
+ }
+
+ progress_bar(0, "Starting mesh deform solve");
+
+ /* setup linear solver */
+ context = EIG_linear_solver_new(totvar, totvar, 1);
+
+ /* build matrix */
+ for (z = 0; z < mdb->size; z++)
+ for (y = 0; y < mdb->size; y++)
+ for (x = 0; x < mdb->size; x++)
+ meshdeform_matrix_add_cell(mdb, context, x, y, z);
+
+ /* solve for each cage vert */
+ for (a = 0; a < mdb->totcagevert; a++) {
+ /* fill in right hand side and solve */
+ for (z = 0; z < mdb->size; z++)
+ for (y = 0; y < mdb->size; y++)
+ for (x = 0; x < mdb->size; x++)
+ meshdeform_matrix_add_rhs(mdb, context, x, y, z, a);
+
+ if (EIG_linear_solver_solve(context)) {
+ for (z = 0; z < mdb->size; z++)
+ for (y = 0; y < mdb->size; y++)
+ for (x = 0; x < mdb->size; x++)
+ meshdeform_matrix_add_semibound_phi(mdb, x, y, z, a);
+
+ for (z = 0; z < mdb->size; z++)
+ for (y = 0; y < mdb->size; y++)
+ for (x = 0; x < mdb->size; x++)
+ meshdeform_matrix_add_exterior_phi(mdb, x, y, z, a);
+
+ for (b = 0; b < mdb->size3; b++) {
+ if (mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR)
+ mdb->phi[b] = EIG_linear_solver_variable_get(context, 0, mdb->varidx[b]);
+ mdb->totalphi[b] += mdb->phi[b];
+ }
+
+ if (mdb->weights) {
+ /* static bind : compute weights for each vertex */
+ for (b = 0; b < mdb->totvert; b++) {
+ if (mdb->inside[b]) {
+ copy_v3_v3(vec, mdb->vertexcos[b]);
+ gridvec[0] = (vec[0] - mdb->min[0] - mdb->halfwidth[0]) / mdb->width[0];
+ gridvec[1] = (vec[1] - mdb->min[1] - mdb->halfwidth[1]) / mdb->width[1];
+ gridvec[2] = (vec[2] - mdb->min[2] - mdb->halfwidth[2]) / mdb->width[2];
+
+ mdb->weights[b * mdb->totcagevert + a] = meshdeform_interp_w(mdb, gridvec, vec, a);
+ }
+ }
+ }
+ else {
+ MDefBindInfluence *inf;
+
+ /* dynamic bind */
+ for (b = 0; b < mdb->size3; b++) {
+ if (mdb->phi[b] >= MESHDEFORM_MIN_INFLUENCE) {
+ inf = BLI_memarena_alloc(mdb->memarena, sizeof(*inf));
+ inf->vertex = a;
+ inf->weight = mdb->phi[b];
+ inf->next = mdb->dyngrid[b];
+ mdb->dyngrid[b] = inf;
+ }
+ }
+ }
+ }
+ else {
+ modifier_setError(&mmd->modifier, "Failed to find bind solution (increase precision?)");
+ error("Mesh Deform: failed to find bind solution.");
+ break;
+ }
+
+ BLI_snprintf(
+ message, sizeof(message), "Mesh deform solve %d / %d |||", a + 1, mdb->totcagevert);
+ progress_bar((float)(a + 1) / (float)(mdb->totcagevert), message);
+ }
#if 0
- /* sanity check */
- for (b = 0; b < mdb->size3; b++)
- if (mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR)
- if (fabsf(mdb->totalphi[b] - 1.0f) > 1e-4f)
- printf("totalphi deficiency [%s|%d] %d: %.10f\n",
- (mdb->tag[b] == MESHDEFORM_TAG_INTERIOR) ? "interior" : "boundary", mdb->semibound[b], mdb->varidx[b], mdb->totalphi[b]);
+ /* sanity check */
+ for (b = 0; b < mdb->size3; b++)
+ if (mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR)
+ if (fabsf(mdb->totalphi[b] - 1.0f) > 1e-4f)
+ printf("totalphi deficiency [%s|%d] %d: %.10f\n",
+ (mdb->tag[b] == MESHDEFORM_TAG_INTERIOR) ? "interior" : "boundary", mdb->semibound[b], mdb->varidx[b], mdb->totalphi[b]);
#endif
- /* free */
- MEM_freeN(mdb->varidx);
+ /* free */
+ MEM_freeN(mdb->varidx);
- EIG_linear_solver_delete(context);
+ EIG_linear_solver_delete(context);
}
static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBind *mdb)
{
- MDefBindInfluence *inf;
- MDefInfluence *mdinf;
- MDefCell *cell;
- float center[3], vec[3], maxwidth, totweight;
- int a, b, x, y, z, totinside, offset;
-
- /* compute bounding box of the cage mesh */
- INIT_MINMAX(mdb->min, mdb->max);
-
- for (a = 0; a < mdb->totcagevert; a++)
- minmax_v3v3_v3(mdb->min, mdb->max, mdb->cagecos[a]);
-
- /* allocate memory */
- mdb->size = (2 << (mmd->gridsize - 1)) + 2;
- mdb->size3 = mdb->size * mdb->size * mdb->size;
- mdb->tag = MEM_callocN(sizeof(int) * mdb->size3, "MeshDeformBindTag");
- mdb->phi = MEM_callocN(sizeof(float) * mdb->size3, "MeshDeformBindPhi");
- mdb->totalphi = MEM_callocN(sizeof(float) * mdb->size3, "MeshDeformBindTotalPhi");
- mdb->boundisect = MEM_callocN(sizeof(*mdb->boundisect) * mdb->size3, "MDefBoundIsect");
- mdb->semibound = MEM_callocN(sizeof(int) * mdb->size3, "MDefSemiBound");
- mdb->bvhtree = BKE_bvhtree_from_mesh_get(&mdb->bvhdata, mdb->cagemesh, BVHTREE_FROM_LOOPTRI, 4);
- mdb->inside = MEM_callocN(sizeof(int) * mdb->totvert, "MDefInside");
-
- if (mmd->flag & MOD_MDEF_DYNAMIC_BIND)
- mdb->dyngrid = MEM_callocN(sizeof(MDefBindInfluence *) * mdb->size3, "MDefDynGrid");
- else
- mdb->weights = MEM_callocN(sizeof(float) * mdb->totvert * mdb->totcagevert, "MDefWeights");
-
- mdb->memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "harmonic coords arena");
- BLI_memarena_use_calloc(mdb->memarena);
-
- /* initialize data from 'cagedm' for reuse */
- {
- Mesh *me = mdb->cagemesh;
- mdb->cagemesh_cache.mpoly = me->mpoly;
- mdb->cagemesh_cache.mloop = me->mloop;
- mdb->cagemesh_cache.looptri = BKE_mesh_runtime_looptri_ensure(me);
- /* can be NULL */
- mdb->cagemesh_cache.poly_nors = CustomData_get_layer(&me->pdata, CD_NORMAL);
- }
-
- /* make bounding box equal size in all directions, add padding, and compute
- * width of the cells */
- maxwidth = -1.0f;
- for (a = 0; a < 3; a++)
- if (mdb->max[a] - mdb->min[a] > maxwidth)
- maxwidth = mdb->max[a] - mdb->min[a];
-
- for (a = 0; a < 3; a++) {
- center[a] = (mdb->min[a] + mdb->max[a]) * 0.5f;
- mdb->min[a] = center[a] - maxwidth * 0.5f;
- mdb->max[a] = center[a] + maxwidth * 0.5f;
-
- mdb->width[a] = (mdb->max[a] - mdb->min[a]) / (mdb->size - 4);
- mdb->min[a] -= 2.1f * mdb->width[a];
- mdb->max[a] += 2.1f * mdb->width[a];
-
- mdb->width[a] = (mdb->max[a] - mdb->min[a]) / mdb->size;
- mdb->halfwidth[a] = mdb->width[a] * 0.5f;
- }
-
- progress_bar(0, "Setting up mesh deform system");
-
- totinside = 0;
- for (a = 0; a < mdb->totvert; a++) {
- copy_v3_v3(vec, mdb->vertexcos[a]);
- mdb->inside[a] = meshdeform_inside_cage(mdb, vec);
- if (mdb->inside[a])
- totinside++;
- }
-
- /* free temporary MDefBoundIsects */
- BLI_memarena_free(mdb->memarena);
- mdb->memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "harmonic coords arena");
-
- /* start with all cells untyped */
- for (a = 0; a < mdb->size3; a++)
- mdb->tag[a] = MESHDEFORM_TAG_UNTYPED;
-
- /* detect intersections and tag boundary cells */
- for (z = 0; z < mdb->size; z++)
- for (y = 0; y < mdb->size; y++)
- for (x = 0; x < mdb->size; x++)
- meshdeform_add_intersections(mdb, x, y, z);
-
- /* compute exterior and interior tags */
- meshdeform_bind_floodfill(mdb);
-
- for (z = 0; z < mdb->size; z++)
- for (y = 0; y < mdb->size; y++)
- for (x = 0; x < mdb->size; x++)
- meshdeform_check_semibound(mdb, x, y, z);
-
- /* solve */
- meshdeform_matrix_solve(mmd, mdb);
-
- /* assign results */
- if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
- mmd->totinfluence = 0;
- for (a = 0; a < mdb->size3; a++)
- for (inf = mdb->dyngrid[a]; inf; inf = inf->next)
- mmd->totinfluence++;
-
- /* convert MDefBindInfluences to smaller MDefInfluences */
- mmd->dyngrid = MEM_callocN(sizeof(MDefCell) * mdb->size3, "MDefDynGrid");
- mmd->dyninfluences = MEM_callocN(sizeof(MDefInfluence) * mmd->totinfluence, "MDefInfluence");
- offset = 0;
- for (a = 0; a < mdb->size3; a++) {
- cell = &mmd->dyngrid[a];
- cell->offset = offset;
-
- totweight = 0.0f;
- mdinf = mmd->dyninfluences + cell->offset;
- for (inf = mdb->dyngrid[a]; inf; inf = inf->next, mdinf++) {
- mdinf->weight = inf->weight;
- mdinf->vertex = inf->vertex;
- totweight += mdinf->weight;
- cell->totinfluence++;
- }
-
- if (totweight > 0.0f) {
- mdinf = mmd->dyninfluences + cell->offset;
- for (b = 0; b < cell->totinfluence; b++, mdinf++)
- mdinf->weight /= totweight;
- }
-
- offset += cell->totinfluence;
- }
-
- mmd->dynverts = mdb->inside;
- mmd->dyngridsize = mdb->size;
- copy_v3_v3(mmd->dyncellmin, mdb->min);
- mmd->dyncellwidth = mdb->width[0];
- MEM_freeN(mdb->dyngrid);
- }
- else {
- mmd->bindweights = mdb->weights;
- MEM_freeN(mdb->inside);
- }
-
- MEM_freeN(mdb->tag);
- MEM_freeN(mdb->phi);
- MEM_freeN(mdb->totalphi);
- MEM_freeN(mdb->boundisect);
- MEM_freeN(mdb->semibound);
- BLI_memarena_free(mdb->memarena);
- free_bvhtree_from_mesh(&mdb->bvhdata);
+ MDefBindInfluence *inf;
+ MDefInfluence *mdinf;
+ MDefCell *cell;
+ float center[3], vec[3], maxwidth, totweight;
+ int a, b, x, y, z, totinside, offset;
+
+ /* compute bounding box of the cage mesh */
+ INIT_MINMAX(mdb->min, mdb->max);
+
+ for (a = 0; a < mdb->totcagevert; a++)
+ minmax_v3v3_v3(mdb->min, mdb->max, mdb->cagecos[a]);
+
+ /* allocate memory */
+ mdb->size = (2 << (mmd->gridsize - 1)) + 2;
+ mdb->size3 = mdb->size * mdb->size * mdb->size;
+ mdb->tag = MEM_callocN(sizeof(int) * mdb->size3, "MeshDeformBindTag");
+ mdb->phi = MEM_callocN(sizeof(float) * mdb->size3, "MeshDeformBindPhi");
+ mdb->totalphi = MEM_callocN(sizeof(float) * mdb->size3, "MeshDeformBindTotalPhi");
+ mdb->boundisect = MEM_callocN(sizeof(*mdb->boundisect) * mdb->size3, "MDefBoundIsect");
+ mdb->semibound = MEM_callocN(sizeof(int) * mdb->size3, "MDefSemiBound");
+ mdb->bvhtree = BKE_bvhtree_from_mesh_get(&mdb->bvhdata, mdb->cagemesh, BVHTREE_FROM_LOOPTRI, 4);
+ mdb->inside = MEM_callocN(sizeof(int) * mdb->totvert, "MDefInside");
+
+ if (mmd->flag & MOD_MDEF_DYNAMIC_BIND)
+ mdb->dyngrid = MEM_callocN(sizeof(MDefBindInfluence *) * mdb->size3, "MDefDynGrid");
+ else
+ mdb->weights = MEM_callocN(sizeof(float) * mdb->totvert * mdb->totcagevert, "MDefWeights");
+
+ mdb->memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "harmonic coords arena");
+ BLI_memarena_use_calloc(mdb->memarena);
+
+ /* initialize data from 'cagedm' for reuse */
+ {
+ Mesh *me = mdb->cagemesh;
+ mdb->cagemesh_cache.mpoly = me->mpoly;
+ mdb->cagemesh_cache.mloop = me->mloop;
+ mdb->cagemesh_cache.looptri = BKE_mesh_runtime_looptri_ensure(me);
+ /* can be NULL */
+ mdb->cagemesh_cache.poly_nors = CustomData_get_layer(&me->pdata, CD_NORMAL);
+ }
+
+ /* make bounding box equal size in all directions, add padding, and compute
+ * width of the cells */
+ maxwidth = -1.0f;
+ for (a = 0; a < 3; a++)
+ if (mdb->max[a] - mdb->min[a] > maxwidth)
+ maxwidth = mdb->max[a] - mdb->min[a];
+
+ for (a = 0; a < 3; a++) {
+ center[a] = (mdb->min[a] + mdb->max[a]) * 0.5f;
+ mdb->min[a] = center[a] - maxwidth * 0.5f;
+ mdb->max[a] = center[a] + maxwidth * 0.5f;
+
+ mdb->width[a] = (mdb->max[a] - mdb->min[a]) / (mdb->size - 4);
+ mdb->min[a] -= 2.1f * mdb->width[a];
+ mdb->max[a] += 2.1f * mdb->width[a];
+
+ mdb->width[a] = (mdb->max[a] - mdb->min[a]) / mdb->size;
+ mdb->halfwidth[a] = mdb->width[a] * 0.5f;
+ }
+
+ progress_bar(0, "Setting up mesh deform system");
+
+ totinside = 0;
+ for (a = 0; a < mdb->totvert; a++) {
+ copy_v3_v3(vec, mdb->vertexcos[a]);
+ mdb->inside[a] = meshdeform_inside_cage(mdb, vec);
+ if (mdb->inside[a])
+ totinside++;
+ }
+
+ /* free temporary MDefBoundIsects */
+ BLI_memarena_free(mdb->memarena);
+ mdb->memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "harmonic coords arena");
+
+ /* start with all cells untyped */
+ for (a = 0; a < mdb->size3; a++)
+ mdb->tag[a] = MESHDEFORM_TAG_UNTYPED;
+
+ /* detect intersections and tag boundary cells */
+ for (z = 0; z < mdb->size; z++)
+ for (y = 0; y < mdb->size; y++)
+ for (x = 0; x < mdb->size; x++)
+ meshdeform_add_intersections(mdb, x, y, z);
+
+ /* compute exterior and interior tags */
+ meshdeform_bind_floodfill(mdb);
+
+ for (z = 0; z < mdb->size; z++)
+ for (y = 0; y < mdb->size; y++)
+ for (x = 0; x < mdb->size; x++)
+ meshdeform_check_semibound(mdb, x, y, z);
+
+ /* solve */
+ meshdeform_matrix_solve(mmd, mdb);
+
+ /* assign results */
+ if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
+ mmd->totinfluence = 0;
+ for (a = 0; a < mdb->size3; a++)
+ for (inf = mdb->dyngrid[a]; inf; inf = inf->next)
+ mmd->totinfluence++;
+
+ /* convert MDefBindInfluences to smaller MDefInfluences */
+ mmd->dyngrid = MEM_callocN(sizeof(MDefCell) * mdb->size3, "MDefDynGrid");
+ mmd->dyninfluences = MEM_callocN(sizeof(MDefInfluence) * mmd->totinfluence, "MDefInfluence");
+ offset = 0;
+ for (a = 0; a < mdb->size3; a++) {
+ cell = &mmd->dyngrid[a];
+ cell->offset = offset;
+
+ totweight = 0.0f;
+ mdinf = mmd->dyninfluences + cell->offset;
+ for (inf = mdb->dyngrid[a]; inf; inf = inf->next, mdinf++) {
+ mdinf->weight = inf->weight;
+ mdinf->vertex = inf->vertex;
+ totweight += mdinf->weight;
+ cell->totinfluence++;
+ }
+
+ if (totweight > 0.0f) {
+ mdinf = mmd->dyninfluences + cell->offset;
+ for (b = 0; b < cell->totinfluence; b++, mdinf++)
+ mdinf->weight /= totweight;
+ }
+
+ offset += cell->totinfluence;
+ }
+
+ mmd->dynverts = mdb->inside;
+ mmd->dyngridsize = mdb->size;
+ copy_v3_v3(mmd->dyncellmin, mdb->min);
+ mmd->dyncellwidth = mdb->width[0];
+ MEM_freeN(mdb->dyngrid);
+ }
+ else {
+ mmd->bindweights = mdb->weights;
+ MEM_freeN(mdb->inside);
+ }
+
+ MEM_freeN(mdb->tag);
+ MEM_freeN(mdb->phi);
+ MEM_freeN(mdb->totalphi);
+ MEM_freeN(mdb->boundisect);
+ MEM_freeN(mdb->semibound);
+ BLI_memarena_free(mdb->memarena);
+ free_bvhtree_from_mesh(&mdb->bvhdata);
}
-void ED_mesh_deform_bind_callback(
- MeshDeformModifierData *mmd, Mesh *cagemesh,
- float *vertexcos, int totvert, float cagemat[4][4])
+void ED_mesh_deform_bind_callback(MeshDeformModifierData *mmd,
+ Mesh *cagemesh,
+ float *vertexcos,
+ int totvert,
+ float cagemat[4][4])
{
- MeshDeformModifierData *mmd_orig =
- (MeshDeformModifierData *)modifier_get_original(&mmd->modifier);
- MeshDeformBind mdb;
- MVert *mvert;
- int a;
+ MeshDeformModifierData *mmd_orig = (MeshDeformModifierData *)modifier_get_original(
+ &mmd->modifier);
+ MeshDeformBind mdb;
+ MVert *mvert;
+ int a;
- waitcursor(1);
- start_progress_bar();
+ waitcursor(1);
+ start_progress_bar();
- memset(&mdb, 0, sizeof(MeshDeformBind));
+ memset(&mdb, 0, sizeof(MeshDeformBind));
- /* get mesh and cage mesh */
- mdb.vertexcos = MEM_callocN(sizeof(float) * 3 * totvert, "MeshDeformCos");
- mdb.totvert = totvert;
+ /* get mesh and cage mesh */
+ mdb.vertexcos = MEM_callocN(sizeof(float) * 3 * totvert, "MeshDeformCos");
+ mdb.totvert = totvert;
- mdb.cagemesh = cagemesh;
- mdb.totcagevert = mdb.cagemesh->totvert;
- mdb.cagecos = MEM_callocN(sizeof(*mdb.cagecos) * mdb.totcagevert, "MeshDeformBindCos");
- copy_m4_m4(mdb.cagemat, cagemat);
+ mdb.cagemesh = cagemesh;
+ mdb.totcagevert = mdb.cagemesh->totvert;
+ mdb.cagecos = MEM_callocN(sizeof(*mdb.cagecos) * mdb.totcagevert, "MeshDeformBindCos");
+ copy_m4_m4(mdb.cagemat, cagemat);
- mvert = mdb.cagemesh->mvert;
- for (a = 0; a < mdb.totcagevert; a++)
- copy_v3_v3(mdb.cagecos[a], mvert[a].co);
- for (a = 0; a < mdb.totvert; a++)
- mul_v3_m4v3(mdb.vertexcos[a], mdb.cagemat, vertexcos + a * 3);
+ mvert = mdb.cagemesh->mvert;
+ for (a = 0; a < mdb.totcagevert; a++)
+ copy_v3_v3(mdb.cagecos[a], mvert[a].co);
+ for (a = 0; a < mdb.totvert; a++)
+ mul_v3_m4v3(mdb.vertexcos[a], mdb.cagemat, vertexcos + a * 3);
- /* solve */
- harmonic_coordinates_bind(mmd_orig, &mdb);
+ /* solve */
+ harmonic_coordinates_bind(mmd_orig, &mdb);
- /* assign bind variables */
- mmd_orig->bindcagecos = (float *)mdb.cagecos;
- mmd_orig->totvert = mdb.totvert;
- mmd_orig->totcagevert = mdb.totcagevert;
- copy_m4_m4(mmd_orig->bindmat, mmd_orig->object->obmat);
+ /* assign bind variables */
+ mmd_orig->bindcagecos = (float *)mdb.cagecos;
+ mmd_orig->totvert = mdb.totvert;
+ mmd_orig->totcagevert = mdb.totcagevert;
+ copy_m4_m4(mmd_orig->bindmat, mmd_orig->object->obmat);
- /* transform bindcagecos to world space */
- for (a = 0; a < mdb.totcagevert; a++)
- mul_m4_v3(mmd_orig->object->obmat, mmd_orig->bindcagecos + a * 3);
+ /* transform bindcagecos to world space */
+ for (a = 0; a < mdb.totcagevert; a++)
+ mul_m4_v3(mmd_orig->object->obmat, mmd_orig->bindcagecos + a * 3);
- /* free */
- MEM_freeN(mdb.vertexcos);
+ /* free */
+ MEM_freeN(mdb.vertexcos);
- /* compact weights */
- modifier_mdef_compact_influences((ModifierData *)mmd_orig);
+ /* compact weights */
+ modifier_mdef_compact_influences((ModifierData *)mmd_orig);
- end_progress_bar();
- waitcursor(0);
+ end_progress_bar();
+ waitcursor(0);
}
diff --git a/source/blender/editors/armature/meshlaplacian.h b/source/blender/editors/armature/meshlaplacian.h
index cf0c1de6b67..ef4759eab4a 100644
--- a/source/blender/editors/armature/meshlaplacian.h
+++ b/source/blender/editors/armature/meshlaplacian.h
@@ -20,7 +20,6 @@
* \ingroup edarmature
*/
-
#ifndef __MESHLAPLACIAN_H__
#define __MESHLAPLACIAN_H__
@@ -49,11 +48,16 @@ float laplacian_system_get_solution(LaplacianSystem *sys, int v);
/* Heat Weighting */
-void heat_bone_weighting(
- struct Object *ob, struct Mesh *me, float (*verts)[3],
- int numbones, struct bDeformGroup **dgrouplist,
- struct bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3],
- int *selected, const char **error);
+void heat_bone_weighting(struct Object *ob,
+ struct Mesh *me,
+ float (*verts)[3],
+ int numbones,
+ struct bDeformGroup **dgrouplist,
+ struct bDeformGroup **dgroupflip,
+ float (*root)[3],
+ float (*tip)[3],
+ int *selected,
+ const char **error);
#ifdef RIGID_DEFORM
/* As-Rigid-As-Possible Deformation */
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index 9323e00db65..51641041ea1 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -65,7 +65,6 @@
#include "armature_intern.h"
-
#define DEBUG_TIME
#include "PIL_time.h"
@@ -73,81 +72,80 @@
# include "PIL_time_utildefines.h"
#endif
-
/* matches logic with ED_operator_posemode_context() */
Object *ED_pose_object_from_context(bContext *C)
{
- ScrArea *sa = 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) {
- ob = ED_object_context(C);
- }
- else {
- ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- }
-
- return ob;
+ ScrArea *sa = 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) {
+ ob = ED_object_context(C);
+ }
+ else {
+ ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ }
+
+ return ob;
}
/* This function is used to process the necessary updates for */
bool ED_object_posemode_enter_ex(struct Main *bmain, Object *ob)
{
- BLI_assert(!ID_IS_LINKED(ob));
- bool ok = false;
-
- switch (ob->type) {
- case OB_ARMATURE:
- ob->restore_mode = ob->mode;
- ob->mode |= OB_MODE_POSE;
- /* Inform all CoW versions that we changed the mode. */
- DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_COPY_ON_WRITE);
- ok = true;
-
- break;
- default:
- break;
- }
-
- return ok;
+ BLI_assert(!ID_IS_LINKED(ob));
+ bool ok = false;
+
+ switch (ob->type) {
+ case OB_ARMATURE:
+ ob->restore_mode = ob->mode;
+ ob->mode |= OB_MODE_POSE;
+ /* Inform all CoW versions that we changed the mode. */
+ DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_COPY_ON_WRITE);
+ ok = true;
+
+ break;
+ default:
+ break;
+ }
+
+ return ok;
}
bool ED_object_posemode_enter(bContext *C, Object *ob)
{
- ReportList *reports = CTX_wm_reports(C);
- if (ID_IS_LINKED(ob)) {
- BKE_report(reports, RPT_WARNING, "Cannot pose libdata");
- return false;
- }
- struct Main *bmain = CTX_data_main(C);
- bool ok = ED_object_posemode_enter_ex(bmain, ob);
- if (ok) {
- WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_POSE, NULL);
- }
- return ok;
+ ReportList *reports = CTX_wm_reports(C);
+ if (ID_IS_LINKED(ob)) {
+ BKE_report(reports, RPT_WARNING, "Cannot pose libdata");
+ return false;
+ }
+ struct Main *bmain = CTX_data_main(C);
+ bool ok = ED_object_posemode_enter_ex(bmain, ob);
+ if (ok) {
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_POSE, NULL);
+ }
+ return ok;
}
bool ED_object_posemode_exit_ex(struct Main *bmain, Object *ob)
{
- bool ok = false;
- if (ob) {
- ob->restore_mode = ob->mode;
- ob->mode &= ~OB_MODE_POSE;
-
- /* Inform all CoW versions that we changed the mode. */
- DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_COPY_ON_WRITE);
- ok = true;
- }
- return ok;
+ bool ok = false;
+ if (ob) {
+ ob->restore_mode = ob->mode;
+ ob->mode &= ~OB_MODE_POSE;
+
+ /* Inform all CoW versions that we changed the mode. */
+ DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_COPY_ON_WRITE);
+ ok = true;
+ }
+ return ok;
}
bool ED_object_posemode_exit(bContext *C, Object *ob)
{
- struct Main *bmain = CTX_data_main(C);
- bool ok = ED_object_posemode_exit_ex(bmain, ob);
- if (ok) {
- WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
- }
- return ok;
+ struct Main *bmain = CTX_data_main(C);
+ bool ok = ED_object_posemode_exit_ex(bmain, ob);
+ if (ok) {
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
+ }
+ return ok;
}
/* if a selected or active bone is protected, throw error (oonly if warn == 1) and return 1 */
@@ -155,25 +153,25 @@ bool ED_object_posemode_exit(bContext *C, Object *ob)
#if 0 /* UNUSED 2.5 */
static bool pose_has_protected_selected(Object *ob, short warn)
{
- /* check protection */
- if (ob->proxy) {
- bPoseChannel *pchan;
- bArmature *arm = ob->data;
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone && (pchan->bone->layer & arm->layer)) {
- if (pchan->bone->layer & arm->layer_protected) {
- if (pchan->bone->flag & BONE_SELECTED)
- break;
- }
- }
- }
- if (pchan) {
- if (warn) error("Cannot change Proxy protected bones");
- return 1;
- }
- }
- return 0;
+ /* check protection */
+ if (ob->proxy) {
+ bPoseChannel *pchan;
+ bArmature *arm = ob->data;
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->bone && (pchan->bone->layer & arm->layer)) {
+ if (pchan->bone->layer & arm->layer_protected) {
+ if (pchan->bone->flag & BONE_SELECTED)
+ break;
+ }
+ }
+ }
+ if (pchan) {
+ if (warn) error("Cannot change Proxy protected bones");
+ return 1;
+ }
+ }
+ return 0;
}
#endif
@@ -187,101 +185,100 @@ static bool pose_has_protected_selected(Object *ob, short warn)
*/
void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob, bool current_frame_only)
{
- /* Transform doesn't always have context available to do update. */
- if (C == NULL) {
- return;
- }
+ /* Transform doesn't always have context available to do update. */
+ if (C == NULL) {
+ return;
+ }
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ListBase targets = {NULL, NULL};
- bool free_depsgraph = false;
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ListBase targets = {NULL, NULL};
+ bool free_depsgraph = false;
- /* Override depsgraph with a filtered, simpler copy */
- if (!current_frame_only && G.debug_value != -1) {
- DEG_FilterQuery query = {{0}};
+ /* Override depsgraph with a filtered, simpler copy */
+ if (!current_frame_only && G.debug_value != -1) {
+ DEG_FilterQuery query = {{0}};
- DEG_FilterTarget *dft_ob = MEM_callocN(sizeof(DEG_FilterTarget), "DEG_FilterTarget");
- dft_ob->id = &ob->id;
- BLI_addtail(&query.targets, dft_ob);
+ DEG_FilterTarget *dft_ob = MEM_callocN(sizeof(DEG_FilterTarget), "DEG_FilterTarget");
+ dft_ob->id = &ob->id;
+ BLI_addtail(&query.targets, dft_ob);
#ifdef DEBUG_TIME
- TIMEIT_START(filter_pose_depsgraph);
+ TIMEIT_START(filter_pose_depsgraph);
#endif
- depsgraph = DEG_graph_filter(depsgraph, bmain, &query);
+ depsgraph = DEG_graph_filter(depsgraph, bmain, &query);
#ifdef DEBUG_TIME
- TIMEIT_END(filter_pose_depsgraph);
+ TIMEIT_END(filter_pose_depsgraph);
#endif
- free_depsgraph = true;
- MEM_freeN(dft_ob);
+ free_depsgraph = true;
+ MEM_freeN(dft_ob);
#ifdef DEBUG_TIME
- TIMEIT_START(filter_pose_update);
+ TIMEIT_START(filter_pose_update);
#endif
- BKE_scene_graph_update_tagged(depsgraph, bmain);
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
#ifdef DEBUG_TIME
- TIMEIT_END(filter_pose_update);
+ TIMEIT_END(filter_pose_update);
#endif
- }
+ }
- /* set flag to force recalc, then grab the relevant bones to target */
- ob->pose->avs.recalc |= ANIMVIZ_RECALC_PATHS;
- animviz_get_object_motionpaths(ob, &targets);
+ /* set flag to force recalc, then grab the relevant bones to target */
+ ob->pose->avs.recalc |= ANIMVIZ_RECALC_PATHS;
+ animviz_get_object_motionpaths(ob, &targets);
- /* recalculate paths, then free */
+ /* recalculate paths, then free */
#ifdef DEBUG_TIME
- TIMEIT_START(pose_path_calc);
+ TIMEIT_START(pose_path_calc);
#endif
- animviz_calc_motionpaths(depsgraph, bmain, scene, &targets, !free_depsgraph, current_frame_only);
+ animviz_calc_motionpaths(depsgraph, bmain, scene, &targets, !free_depsgraph, current_frame_only);
#ifdef DEBUG_TIME
- TIMEIT_END(pose_path_calc);
+ TIMEIT_END(pose_path_calc);
#endif
- BLI_freelistN(&targets);
+ BLI_freelistN(&targets);
- if (!current_frame_only) {
- /* Tag armature object for copy on write - so paths will draw/redraw.
- * For currently frame only we update evaluated object directly. */
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
- }
+ if (!current_frame_only) {
+ /* Tag armature object for copy on write - so paths will draw/redraw.
+ * For currently frame only we update evaluated object directly. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ }
- /* Free temporary depsgraph instance */
- if (free_depsgraph) {
- DEG_graph_free(depsgraph);
- }
+ /* Free temporary depsgraph instance */
+ if (free_depsgraph) {
+ DEG_graph_free(depsgraph);
+ }
}
-
/* show popup to determine settings */
static int pose_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
- /* set default settings from existing/stored settings */
- {
- bAnimVizSettings *avs = &ob->pose->avs;
- PointerRNA avs_ptr;
+ /* set default settings from existing/stored settings */
+ {
+ bAnimVizSettings *avs = &ob->pose->avs;
+ PointerRNA avs_ptr;
- RNA_int_set(op->ptr, "start_frame", avs->path_sf);
- RNA_int_set(op->ptr, "end_frame", avs->path_ef);
+ RNA_int_set(op->ptr, "start_frame", avs->path_sf);
+ RNA_int_set(op->ptr, "end_frame", avs->path_ef);
- RNA_pointer_create(NULL, &RNA_AnimVizMotionPaths, avs, &avs_ptr);
- RNA_enum_set(op->ptr, "bake_location", RNA_enum_get(&avs_ptr, "bake_location"));
- }
+ RNA_pointer_create(NULL, &RNA_AnimVizMotionPaths, avs, &avs_ptr);
+ RNA_enum_set(op->ptr, "bake_location", RNA_enum_get(&avs_ptr, "bake_location"));
+ }
- /* 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);
+ /* 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);
}
/* For the object with pose/action: create path curves for selected bones
@@ -289,120 +286,135 @@ static int pose_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEven
*/
static int pose_calculate_paths_exec(bContext *C, wmOperator *op)
{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- Scene *scene = CTX_data_scene(C);
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ Scene *scene = CTX_data_scene(C);
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
- /* grab baking settings from operator settings */
- {
- bAnimVizSettings *avs = &ob->pose->avs;
- PointerRNA avs_ptr;
+ /* grab baking settings from operator settings */
+ {
+ bAnimVizSettings *avs = &ob->pose->avs;
+ PointerRNA avs_ptr;
- avs->path_sf = RNA_int_get(op->ptr, "start_frame");
- avs->path_ef = RNA_int_get(op->ptr, "end_frame");
+ avs->path_sf = RNA_int_get(op->ptr, "start_frame");
+ avs->path_ef = RNA_int_get(op->ptr, "end_frame");
- RNA_pointer_create(NULL, &RNA_AnimVizMotionPaths, avs, &avs_ptr);
- RNA_enum_set(&avs_ptr, "bake_location", RNA_enum_get(op->ptr, "bake_location"));
- }
+ RNA_pointer_create(NULL, &RNA_AnimVizMotionPaths, avs, &avs_ptr);
+ RNA_enum_set(&avs_ptr, "bake_location", RNA_enum_get(op->ptr, "bake_location"));
+ }
- /* set up path data for bones being calculated */
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones_from_active_object)
- {
- /* verify makes sure that the selected bone has a bone with the appropriate settings */
- animviz_verify_motionpaths(op->reports, scene, ob, pchan);
- }
- CTX_DATA_END;
+ /* set up path data for bones being calculated */
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones_from_active_object) {
+ /* verify makes sure that the selected bone has a bone with the appropriate settings */
+ animviz_verify_motionpaths(op->reports, scene, ob, pchan);
+ }
+ CTX_DATA_END;
#ifdef DEBUG_TIME
- TIMEIT_START(recalc_pose_paths);
+ TIMEIT_START(recalc_pose_paths);
#endif
- /* calculate the bones that now have motionpaths... */
- /* TODO: only make for the selected bones? */
- ED_pose_recalculate_paths(C, scene, ob, false);
+ /* calculate the bones that now have motionpaths... */
+ /* TODO: only make for the selected bones? */
+ ED_pose_recalculate_paths(C, scene, ob, false);
#ifdef DEBUG_TIME
- TIMEIT_END(recalc_pose_paths);
+ TIMEIT_END(recalc_pose_paths);
#endif
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void POSE_OT_paths_calculate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Calculate Bone Paths";
- ot->idname = "POSE_OT_paths_calculate";
- ot->description = "Calculate paths for the selected bones";
-
- /* api callbacks */
- ot->invoke = pose_calculate_paths_invoke;
- ot->exec = pose_calculate_paths_exec;
- ot->poll = ED_operator_posemode_exclusive;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_int(ot->srna, "start_frame", 1, MINAFRAME, MAXFRAME, "Start",
- "First frame to calculate bone paths on", MINFRAME, MAXFRAME / 2.0);
- RNA_def_int(ot->srna, "end_frame", 250, MINAFRAME, MAXFRAME, "End",
- "Last frame to calculate bone paths on", MINFRAME, MAXFRAME / 2.0);
-
- RNA_def_enum(ot->srna, "bake_location", rna_enum_motionpath_bake_location_items,
- MOTIONPATH_BAKE_HEADS,
- "Bake Location",
- "Which point on the bones is used when calculating paths");
+ /* identifiers */
+ ot->name = "Calculate Bone Paths";
+ ot->idname = "POSE_OT_paths_calculate";
+ ot->description = "Calculate paths for the selected bones";
+
+ /* api callbacks */
+ ot->invoke = pose_calculate_paths_invoke;
+ ot->exec = pose_calculate_paths_exec;
+ ot->poll = ED_operator_posemode_exclusive;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna,
+ "start_frame",
+ 1,
+ MINAFRAME,
+ MAXFRAME,
+ "Start",
+ "First frame to calculate bone paths on",
+ MINFRAME,
+ MAXFRAME / 2.0);
+ RNA_def_int(ot->srna,
+ "end_frame",
+ 250,
+ MINAFRAME,
+ MAXFRAME,
+ "End",
+ "Last frame to calculate bone paths on",
+ MINFRAME,
+ MAXFRAME / 2.0);
+
+ RNA_def_enum(ot->srna,
+ "bake_location",
+ rna_enum_motionpath_bake_location_items,
+ MOTIONPATH_BAKE_HEADS,
+ "Bake Location",
+ "Which point on the bones is used when calculating paths");
}
/* --------- */
static bool pose_update_paths_poll(bContext *C)
{
- if (ED_operator_posemode_exclusive(C)) {
- Object *ob = CTX_data_active_object(C);
- return (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
- }
+ if (ED_operator_posemode_exclusive(C)) {
+ Object *ob = CTX_data_active_object(C);
+ return (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
+ }
- return false;
+ return false;
}
static int pose_update_paths_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- Scene *scene = CTX_data_scene(C);
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ Scene *scene = CTX_data_scene(C);
- if (ELEM(NULL, ob, scene))
- return OPERATOR_CANCELLED;
+ if (ELEM(NULL, ob, scene))
+ return OPERATOR_CANCELLED;
- /* calculate the bones that now have motionpaths... */
- /* TODO: only make for the selected bones? */
- ED_pose_recalculate_paths(C, scene, ob, false);
+ /* calculate the bones that now have motionpaths... */
+ /* TODO: only make for the selected bones? */
+ ED_pose_recalculate_paths(C, scene, ob, false);
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void POSE_OT_paths_update(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Update Bone Paths";
- ot->idname = "POSE_OT_paths_update";
- ot->description = "Recalculate paths for bones that already have them";
+ /* identifiers */
+ ot->name = "Update Bone Paths";
+ ot->idname = "POSE_OT_paths_update";
+ ot->description = "Recalculate paths for bones that already have them";
- /* api callbakcs */
- ot->exec = pose_update_paths_exec;
- ot->poll = pose_update_paths_poll;
+ /* api callbakcs */
+ ot->exec = pose_update_paths_exec;
+ ot->poll = pose_update_paths_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* --------- */
@@ -410,354 +422,358 @@ void POSE_OT_paths_update(wmOperatorType *ot)
/* for the object with pose/action: clear path curves for selected bones only */
static void ED_pose_clear_paths(Object *ob, bool only_selected)
{
- bPoseChannel *pchan;
- bool skipped = false;
-
- if (ELEM(NULL, ob, ob->pose))
- return;
-
- /* free the motionpath blocks for all bones - This is easier for users to quickly clear all */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->mpath) {
- if ((only_selected == false) || ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))) {
- animviz_free_motionpath(pchan->mpath);
- pchan->mpath = NULL;
- }
- else {
- skipped = true;
- }
- }
- }
-
- /* if nothing was skipped, there should be no paths left! */
- if (skipped == false)
- ob->pose->avs.path_bakeflag &= ~MOTIONPATH_BAKE_HAS_PATHS;
-
- /* tag armature object for copy on write - so removed paths don't still show */
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ bPoseChannel *pchan;
+ bool skipped = false;
+
+ if (ELEM(NULL, ob, ob->pose))
+ return;
+
+ /* free the motionpath blocks for all bones - This is easier for users to quickly clear all */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->mpath) {
+ if ((only_selected == false) || ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))) {
+ animviz_free_motionpath(pchan->mpath);
+ pchan->mpath = NULL;
+ }
+ else {
+ skipped = true;
+ }
+ }
+ }
+
+ /* if nothing was skipped, there should be no paths left! */
+ if (skipped == false)
+ ob->pose->avs.path_bakeflag &= ~MOTIONPATH_BAKE_HAS_PATHS;
+
+ /* tag armature object for copy on write - so removed paths don't still show */
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
}
/* operator callback - wrapper for the backend function */
static int pose_clear_paths_exec(bContext *C, wmOperator *op)
{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bool only_selected = RNA_boolean_get(op->ptr, "only_selected");
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ bool only_selected = RNA_boolean_get(op->ptr, "only_selected");
- /* only continue if there's an object */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
+ /* only continue if there's an object */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
- /* use the backend function for this */
- ED_pose_clear_paths(ob, only_selected);
+ /* use the backend function for this */
+ ED_pose_clear_paths(ob, only_selected);
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* operator callback/wrapper */
static int pose_clear_paths_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
{
- if ((evt->shift) && !RNA_struct_property_is_set(op->ptr, "only_selected")) {
- RNA_boolean_set(op->ptr, "only_selected", true);
- }
- return pose_clear_paths_exec(C, op);
+ if ((evt->shift) && !RNA_struct_property_is_set(op->ptr, "only_selected")) {
+ RNA_boolean_set(op->ptr, "only_selected", true);
+ }
+ return pose_clear_paths_exec(C, op);
}
void POSE_OT_paths_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Bone Paths";
- ot->idname = "POSE_OT_paths_clear";
- ot->description = "Clear path caches for all bones, hold Shift key for selected bones only";
-
- /* api callbacks */
- ot->invoke = pose_clear_paths_invoke;
- ot->exec = pose_clear_paths_exec;
- ot->poll = ED_operator_posemode_exclusive;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_boolean(ot->srna, "only_selected", false, "Only Selected",
- "Only clear paths from selected bones");
- RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+ /* identifiers */
+ ot->name = "Clear Bone Paths";
+ ot->idname = "POSE_OT_paths_clear";
+ ot->description = "Clear path caches for all bones, hold Shift key for selected bones only";
+
+ /* api callbacks */
+ ot->invoke = pose_clear_paths_invoke;
+ ot->exec = pose_clear_paths_exec;
+ ot->poll = ED_operator_posemode_exclusive;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_boolean(
+ ot->srna, "only_selected", false, "Only Selected", "Only clear paths from selected bones");
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
}
/* --------- */
static int pose_update_paths_range_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- if (ELEM(NULL, scene, ob, ob->pose)) {
- return OPERATOR_CANCELLED;
- }
+ if (ELEM(NULL, scene, ob, ob->pose)) {
+ return OPERATOR_CANCELLED;
+ }
- /* use Preview Range or Full Frame Range - whichever is in use */
- ob->pose->avs.path_sf = PSFRA;
- ob->pose->avs.path_ef = PEFRA;
+ /* use Preview Range or Full Frame Range - whichever is in use */
+ ob->pose->avs.path_sf = PSFRA;
+ ob->pose->avs.path_ef = PEFRA;
- /* tag for updates */
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ /* tag for updates */
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void POSE_OT_paths_range_update(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Update Range from Scene";
- ot->idname = "POSE_OT_paths_range_update";
- ot->description = "Update frame range for motion paths from the Scene's current frame range";
+ /* identifiers */
+ ot->name = "Update Range from Scene";
+ ot->idname = "POSE_OT_paths_range_update";
+ ot->description = "Update frame range for motion paths from the Scene's current frame range";
- /* callbacks */
- ot->exec = pose_update_paths_range_exec;
- ot->poll = ED_operator_posemode_exclusive;
+ /* callbacks */
+ ot->exec = pose_update_paths_range_exec;
+ ot->poll = ED_operator_posemode_exclusive;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************************************** */
static int pose_flip_names_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- const bool do_strip_numbers = RNA_boolean_get(op->ptr, "do_strip_numbers");
+ Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ const bool do_strip_numbers = RNA_boolean_get(op->ptr, "do_strip_numbers");
- FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob)
- {
- bArmature *arm = ob->data;
- ListBase bones_names = {NULL};
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
+ bArmature *arm = ob->data;
+ ListBase bones_names = {NULL};
- FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob, pchan)
- {
- BLI_addtail(&bones_names, BLI_genericNodeN(pchan->name));
- }
- FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob, pchan) {
+ BLI_addtail(&bones_names, BLI_genericNodeN(pchan->name));
+ }
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
- ED_armature_bones_flip_names(bmain, arm, &bones_names, do_strip_numbers);
+ ED_armature_bones_flip_names(bmain, arm, &bones_names, do_strip_numbers);
- BLI_freelistN(&bones_names);
+ BLI_freelistN(&bones_names);
- /* since we renamed stuff... */
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ /* since we renamed stuff... */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- }
- FOREACH_OBJECT_IN_MODE_END;
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ }
+ FOREACH_OBJECT_IN_MODE_END;
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void POSE_OT_flip_names(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Flip Names";
- ot->idname = "POSE_OT_flip_names";
- ot->description = "Flips (and corrects) the axis suffixes of the names of selected bones";
-
- /* api callbacks */
- ot->exec = pose_flip_names_exec;
- ot->poll = ED_operator_posemode_local;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "do_strip_numbers", false, "Strip Numbers",
- "Try to remove right-most dot-number from flipped names "
- "(WARNING: may result in incoherent naming in some cases)");
+ /* identifiers */
+ ot->name = "Flip Names";
+ ot->idname = "POSE_OT_flip_names";
+ ot->description = "Flips (and corrects) the axis suffixes of the names of selected bones";
+
+ /* api callbacks */
+ ot->exec = pose_flip_names_exec;
+ ot->poll = ED_operator_posemode_local;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna,
+ "do_strip_numbers",
+ false,
+ "Strip Numbers",
+ "Try to remove right-most dot-number from flipped names "
+ "(WARNING: may result in incoherent naming in some cases)");
}
/* ------------------ */
static int pose_autoside_names_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- char newname[MAXBONENAME];
- short axis = RNA_enum_get(op->ptr, "axis");
- Object *ob_prev = NULL;
-
- /* loop through selected bones, auto-naming them */
- CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob)
- {
- bArmature *arm = ob->data;
- BLI_strncpy(newname, pchan->name, sizeof(newname));
- if (bone_autoside_name(newname, 1, axis, pchan->bone->head[axis], pchan->bone->tail[axis])) {
- ED_armature_bone_rename(bmain, arm, pchan->name, newname);
- }
-
- if (ob_prev != ob) {
- /* since we renamed stuff... */
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- ob_prev = ob;
- }
- }
- CTX_DATA_END;
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ char newname[MAXBONENAME];
+ short axis = RNA_enum_get(op->ptr, "axis");
+ Object *ob_prev = NULL;
+
+ /* loop through selected bones, auto-naming them */
+ CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob)
+ {
+ bArmature *arm = ob->data;
+ BLI_strncpy(newname, pchan->name, sizeof(newname));
+ if (bone_autoside_name(newname, 1, axis, pchan->bone->head[axis], pchan->bone->tail[axis])) {
+ ED_armature_bone_rename(bmain, arm, pchan->name, newname);
+ }
+
+ if (ob_prev != ob) {
+ /* since we renamed stuff... */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ ob_prev = ob;
+ }
+ }
+ CTX_DATA_END;
+
+ return OPERATOR_FINISHED;
}
void POSE_OT_autoside_names(wmOperatorType *ot)
{
- static const EnumPropertyItem axis_items[] = {
- {0, "XAXIS", 0, "X-Axis", "Left/Right"},
- {1, "YAXIS", 0, "Y-Axis", "Front/Back"},
- {2, "ZAXIS", 0, "Z-Axis", "Top/Bottom"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "AutoName by Axis";
- ot->idname = "POSE_OT_autoside_names";
- ot->description = "Automatically renames the selected bones according to which side of the target axis they fall on";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = pose_autoside_names_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* settings */
- ot->prop = RNA_def_enum(ot->srna, "axis", axis_items, 0, "Axis", "Axis tag names with");
+ static const EnumPropertyItem axis_items[] = {
+ {0, "XAXIS", 0, "X-Axis", "Left/Right"},
+ {1, "YAXIS", 0, "Y-Axis", "Front/Back"},
+ {2, "ZAXIS", 0, "Z-Axis", "Top/Bottom"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "AutoName by Axis";
+ ot->idname = "POSE_OT_autoside_names";
+ ot->description =
+ "Automatically renames the selected bones according to which side of the target axis they "
+ "fall on";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = pose_autoside_names_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* settings */
+ ot->prop = RNA_def_enum(ot->srna, "axis", axis_items, 0, "Axis", "Axis tag names with");
}
/* ********************************************** */
static int pose_bone_rotmode_exec(bContext *C, wmOperator *op)
{
- const int mode = RNA_enum_get(op->ptr, "type");
- Object *prev_ob = NULL;
-
- /* set rotation mode of selected bones */
- CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob)
- {
- pchan->rotmode = mode;
-
- if (prev_ob != ob) {
- /* Notifiers and updates. */
- DEG_id_tag_update((ID *)ob, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- prev_ob = ob;
- }
- }
- CTX_DATA_END;
-
- return OPERATOR_FINISHED;
+ const int mode = RNA_enum_get(op->ptr, "type");
+ Object *prev_ob = NULL;
+
+ /* set rotation mode of selected bones */
+ CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob)
+ {
+ pchan->rotmode = mode;
+
+ if (prev_ob != ob) {
+ /* Notifiers and updates. */
+ DEG_id_tag_update((ID *)ob, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ prev_ob = ob;
+ }
+ }
+ CTX_DATA_END;
+
+ return OPERATOR_FINISHED;
}
void POSE_OT_rotation_mode_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Rotation Mode";
- ot->idname = "POSE_OT_rotation_mode_set";
- ot->description = "Set the rotation representation used by selected bones";
-
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = pose_bone_rotmode_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(
- ot->srna, "type", rna_enum_object_rotation_mode_items, 0, "Rotation Mode", "");
+ /* identifiers */
+ ot->name = "Set Rotation Mode";
+ ot->idname = "POSE_OT_rotation_mode_set";
+ ot->description = "Set the rotation representation used by selected bones";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = pose_bone_rotmode_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", rna_enum_object_rotation_mode_items, 0, "Rotation Mode", "");
}
/* ********************************************** */
static bool armature_layers_poll(bContext *C)
{
- /* Armature layers operators can be used in posemode OR editmode for armatures */
- return ED_operator_posemode(C) || ED_operator_editarmature(C);
+ /* Armature layers operators can be used in posemode OR editmode for armatures */
+ return ED_operator_posemode(C) || ED_operator_editarmature(C);
}
static bArmature *armature_layers_get_data(Object **ob)
{
- bArmature *arm = NULL;
-
- /* Sanity checking and handling of posemode. */
- if (*ob) {
- Object *tob = BKE_object_pose_armature_get(*ob);
- if (tob) {
- *ob = tob;
- arm = (*ob)->data;
- }
- else if ((*ob)->type == OB_ARMATURE) {
- arm = (*ob)->data;
- }
- }
-
- return arm;
+ bArmature *arm = NULL;
+
+ /* Sanity checking and handling of posemode. */
+ if (*ob) {
+ Object *tob = BKE_object_pose_armature_get(*ob);
+ if (tob) {
+ *ob = tob;
+ arm = (*ob)->data;
+ }
+ else if ((*ob)->type == OB_ARMATURE) {
+ arm = (*ob)->data;
+ }
+ }
+
+ return arm;
}
/* Show all armature layers */
static int pose_armature_layers_showall_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
- bArmature *arm = armature_layers_get_data(&ob);
- PointerRNA ptr;
- int maxLayers = (RNA_boolean_get(op->ptr, "all")) ? 32 : 16;
- /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
- bool layers[32] = {false};
- int i;
-
- /* sanity checking */
- if (arm == NULL)
- return OPERATOR_CANCELLED;
-
- /* use RNA to set the layers
- * although it would be faster to just set directly using bitflags, we still
- * need to setup a RNA pointer so that we get the "update" callbacks for free...
- */
- RNA_id_pointer_create(&arm->id, &ptr);
-
- for (i = 0; i < maxLayers; i++)
- layers[i] = 1;
-
- RNA_boolean_set_array(&ptr, "layers", layers);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
-
- /* done */
- return OPERATOR_FINISHED;
+ Object *ob = CTX_data_active_object(C);
+ bArmature *arm = armature_layers_get_data(&ob);
+ PointerRNA ptr;
+ int maxLayers = (RNA_boolean_get(op->ptr, "all")) ? 32 : 16;
+ /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
+ bool layers[32] = {false};
+ int i;
+
+ /* sanity checking */
+ if (arm == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* use RNA to set the layers
+ * although it would be faster to just set directly using bitflags, we still
+ * need to setup a RNA pointer so that we get the "update" callbacks for free...
+ */
+ RNA_id_pointer_create(&arm->id, &ptr);
+
+ for (i = 0; i < maxLayers; i++)
+ layers[i] = 1;
+
+ RNA_boolean_set_array(&ptr, "layers", layers);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_layers_show_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Show All Layers";
- ot->idname = "ARMATURE_OT_layers_show_all";
- ot->description = "Make all armature layers visible";
+ /* identifiers */
+ ot->name = "Show All Layers";
+ ot->idname = "ARMATURE_OT_layers_show_all";
+ ot->description = "Make all armature layers visible";
- /* callbacks */
- ot->exec = pose_armature_layers_showall_exec;
- ot->poll = armature_layers_poll;
+ /* callbacks */
+ ot->exec = pose_armature_layers_showall_exec;
+ ot->poll = armature_layers_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_boolean(ot->srna, "all", 1, "All Layers", "Enable all layers or just the first 16 (top row)");
+ /* properties */
+ ot->prop = RNA_def_boolean(
+ ot->srna, "all", 1, "All Layers", "Enable all layers or just the first 16 (top row)");
}
/* ------------------- */
@@ -765,69 +781,70 @@ void ARMATURE_OT_layers_show_all(wmOperatorType *ot)
/* Present a popup to get the layers that should be used */
static int armature_layers_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Object *ob = CTX_data_active_object(C);
- bArmature *arm = armature_layers_get_data(&ob);
- PointerRNA ptr;
- /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
- bool layers[32];
-
- /* sanity checking */
- if (arm == NULL)
- return OPERATOR_CANCELLED;
-
- /* get RNA pointer to armature data to use that to retrieve the layers as ints to init the operator */
- RNA_id_pointer_create((ID *)arm, &ptr);
- RNA_boolean_get_array(&ptr, "layers", layers);
- RNA_boolean_set_array(op->ptr, "layers", layers);
-
- /* part to sync with other similar operators... */
- return WM_operator_props_popup(C, op, event);
+ Object *ob = CTX_data_active_object(C);
+ bArmature *arm = armature_layers_get_data(&ob);
+ PointerRNA ptr;
+ /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
+ bool layers[32];
+
+ /* sanity checking */
+ if (arm == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* get RNA pointer to armature data to use that to retrieve the layers as ints to init the operator */
+ RNA_id_pointer_create((ID *)arm, &ptr);
+ RNA_boolean_get_array(&ptr, "layers", layers);
+ RNA_boolean_set_array(op->ptr, "layers", layers);
+
+ /* part to sync with other similar operators... */
+ return WM_operator_props_popup(C, op, event);
}
/* Set the visible layers for the active armature (edit and pose modes) */
static int armature_layers_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
- bArmature *arm = armature_layers_get_data(&ob);
- PointerRNA ptr;
- /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
- bool layers[32];
+ Object *ob = CTX_data_active_object(C);
+ bArmature *arm = armature_layers_get_data(&ob);
+ PointerRNA ptr;
+ /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
+ bool layers[32];
- if (arm == NULL) {
- return OPERATOR_CANCELLED;
- }
+ if (arm == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- /* get the values set in the operator properties */
- RNA_boolean_get_array(op->ptr, "layers", layers);
+ /* get the values set in the operator properties */
+ RNA_boolean_get_array(op->ptr, "layers", layers);
- /* get pointer for armature, and write data there... */
- RNA_id_pointer_create((ID *)arm, &ptr);
- RNA_boolean_set_array(&ptr, "layers", layers);
+ /* get pointer for armature, and write data there... */
+ RNA_id_pointer_create((ID *)arm, &ptr);
+ RNA_boolean_set_array(&ptr, "layers", layers);
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_armature_layers(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Change Armature Layers";
- ot->idname = "ARMATURE_OT_armature_layers";
- ot->description = "Change the visible armature layers";
-
- /* callbacks */
- ot->invoke = armature_layers_invoke;
- ot->exec = armature_layers_exec;
- ot->poll = armature_layers_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers to make visible");
+ /* identifiers */
+ ot->name = "Change Armature Layers";
+ ot->idname = "ARMATURE_OT_armature_layers";
+ ot->description = "Change the visible armature layers";
+
+ /* callbacks */
+ ot->invoke = armature_layers_invoke;
+ ot->exec = armature_layers_exec;
+ ot->poll = armature_layers_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean_layer_member(
+ ot->srna, "layers", 32, NULL, "Layer", "Armature layers to make visible");
}
/* ------------------- */
@@ -835,75 +852,75 @@ void ARMATURE_OT_armature_layers(wmOperatorType *ot)
/* Present a popup to get the layers that should be used */
static int pose_bone_layers_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
- bool layers[32] = {0};
-
- /* get layers that are active already */
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
- {
- short bit;
-
- /* loop over the bits for this pchan's layers, adding layers where they're needed */
- for (bit = 0; bit < 32; bit++) {
- layers[bit] = (pchan->bone->layer & (1u << bit)) != 0;
- }
- }
- CTX_DATA_END;
-
- /* copy layers to operator */
- RNA_boolean_set_array(op->ptr, "layers", layers);
-
- /* part to sync with other similar operators... */
- return WM_operator_props_popup(C, op, event);
+ /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
+ bool layers[32] = {0};
+
+ /* get layers that are active already */
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones) {
+ short bit;
+
+ /* loop over the bits for this pchan's layers, adding layers where they're needed */
+ for (bit = 0; bit < 32; bit++) {
+ layers[bit] = (pchan->bone->layer & (1u << bit)) != 0;
+ }
+ }
+ CTX_DATA_END;
+
+ /* copy layers to operator */
+ RNA_boolean_set_array(op->ptr, "layers", layers);
+
+ /* part to sync with other similar operators... */
+ return WM_operator_props_popup(C, op, event);
}
/* Set the visible layers for the active armature (edit and pose modes) */
static int pose_bone_layers_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr;
- /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
- bool layers[32];
-
- /* get the values set in the operator properties */
- RNA_boolean_get_array(op->ptr, "layers", layers);
-
- Object *prev_ob = NULL;
-
- /* set layers of pchans based on the values set in the operator props */
- CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob)
- {
- /* get pointer for pchan, and write flags this way */
- RNA_pointer_create((ID *)ob->data, &RNA_Bone, pchan->bone, &ptr);
- RNA_boolean_set_array(&ptr, "layers", layers);
-
- if (prev_ob != ob) {
- /* Note, notifier might evolve. */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- DEG_id_tag_update((ID *)ob->data, ID_RECALC_COPY_ON_WRITE);
- prev_ob = ob;
- }
- }
- CTX_DATA_END;
- return OPERATOR_FINISHED;
+ PointerRNA ptr;
+ /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
+ bool layers[32];
+
+ /* get the values set in the operator properties */
+ RNA_boolean_get_array(op->ptr, "layers", layers);
+
+ Object *prev_ob = NULL;
+
+ /* set layers of pchans based on the values set in the operator props */
+ CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob)
+ {
+ /* get pointer for pchan, and write flags this way */
+ RNA_pointer_create((ID *)ob->data, &RNA_Bone, pchan->bone, &ptr);
+ RNA_boolean_set_array(&ptr, "layers", layers);
+
+ if (prev_ob != ob) {
+ /* Note, notifier might evolve. */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ DEG_id_tag_update((ID *)ob->data, ID_RECALC_COPY_ON_WRITE);
+ prev_ob = ob;
+ }
+ }
+ CTX_DATA_END;
+ return OPERATOR_FINISHED;
}
void POSE_OT_bone_layers(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Change Bone Layers";
- ot->idname = "POSE_OT_bone_layers";
- ot->description = "Change the layers that the selected bones belong to";
-
- /* callbacks */
- ot->invoke = pose_bone_layers_invoke;
- ot->exec = pose_bone_layers_exec;
- ot->poll = ED_operator_posemode_exclusive;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers that bone belongs to");
+ /* identifiers */
+ ot->name = "Change Bone Layers";
+ ot->idname = "POSE_OT_bone_layers";
+ ot->description = "Change the layers that the selected bones belong to";
+
+ /* callbacks */
+ ot->invoke = pose_bone_layers_invoke;
+ ot->exec = pose_bone_layers_exec;
+ ot->poll = ED_operator_posemode_exclusive;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean_layer_member(
+ ot->srna, "layers", 32, NULL, "Layer", "Armature layers that bone belongs to");
}
/* ------------------- */
@@ -911,73 +928,73 @@ void POSE_OT_bone_layers(wmOperatorType *ot)
/* Present a popup to get the layers that should be used */
static int armature_bone_layers_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
- bool layers[32] = {0};
-
- /* get layers that are active already */
- CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones)
- {
- short bit;
-
- /* loop over the bits for this pchan's layers, adding layers where they're needed */
- for (bit = 0; bit < 32; bit++) {
- if (ebone->layer & (1u << bit)) {
- layers[bit] = 1;
- }
- }
- }
- CTX_DATA_END;
-
- /* copy layers to operator */
- RNA_boolean_set_array(op->ptr, "layers", layers);
-
- /* part to sync with other similar operators... */
- return WM_operator_props_popup(C, op, event);
+ /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
+ bool layers[32] = {0};
+
+ /* get layers that are active already */
+ CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones) {
+ short bit;
+
+ /* loop over the bits for this pchan's layers, adding layers where they're needed */
+ for (bit = 0; bit < 32; bit++) {
+ if (ebone->layer & (1u << bit)) {
+ layers[bit] = 1;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* copy layers to operator */
+ RNA_boolean_set_array(op->ptr, "layers", layers);
+
+ /* part to sync with other similar operators... */
+ return WM_operator_props_popup(C, op, event);
}
/* Set the visible layers for the active armature (edit and pose modes) */
static int armature_bone_layers_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_edit_object(C);
- PointerRNA ptr;
- /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
- bool layers[32];
-
- /* get the values set in the operator properties */
- RNA_boolean_get_array(op->ptr, "layers", layers);
-
- /* set layers of pchans based on the values set in the operator props */
- CTX_DATA_BEGIN_WITH_ID (C, EditBone *, ebone, selected_editable_bones, bArmature *, arm)
- {
- /* get pointer for pchan, and write flags this way */
- RNA_pointer_create((ID *)arm, &RNA_EditBone, ebone, &ptr);
- RNA_boolean_set_array(&ptr, "layers", layers);
- }
- CTX_DATA_END;
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
+ Object *ob = CTX_data_edit_object(C);
+ PointerRNA ptr;
+ /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
+ bool layers[32];
+
+ /* get the values set in the operator properties */
+ RNA_boolean_get_array(op->ptr, "layers", layers);
+
+ /* set layers of pchans based on the values set in the operator props */
+ CTX_DATA_BEGIN_WITH_ID(C, EditBone *, ebone, selected_editable_bones, bArmature *, arm)
+ {
+ /* get pointer for pchan, and write flags this way */
+ RNA_pointer_create((ID *)arm, &RNA_EditBone, ebone, &ptr);
+ RNA_boolean_set_array(&ptr, "layers", layers);
+ }
+ CTX_DATA_END;
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_bone_layers(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Change Bone Layers";
- ot->idname = "ARMATURE_OT_bone_layers";
- ot->description = "Change the layers that the selected bones belong to";
-
- /* callbacks */
- ot->invoke = armature_bone_layers_invoke;
- ot->exec = armature_bone_layers_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers that bone belongs to");
+ /* identifiers */
+ ot->name = "Change Bone Layers";
+ ot->idname = "ARMATURE_OT_bone_layers";
+ ot->description = "Change the layers that the selected bones belong to";
+
+ /* callbacks */
+ ot->invoke = armature_bone_layers_invoke;
+ ot->exec = armature_bone_layers_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean_layer_member(
+ ot->srna, "layers", 32, NULL, "Layer", "Armature layers that bone belongs to");
}
/* ********************************************** */
@@ -985,132 +1002,133 @@ void ARMATURE_OT_bone_layers(wmOperatorType *ot)
static int hide_pose_bone_fn(Object *ob, Bone *bone, void *ptr)
{
- bArmature *arm = ob->data;
- const bool hide_select = (bool)POINTER_AS_INT(ptr);
- int count = 0;
- if (arm->layer & bone->layer) {
- if (((bone->flag & BONE_SELECTED) != 0) == hide_select) {
- bone->flag |= BONE_HIDDEN_P;
- /* only needed when 'hide_select' is true, but harmless. */
- bone->flag &= ~BONE_SELECTED;
- if (arm->act_bone == bone) {
- arm->act_bone = NULL;
- }
- count += 1;
- }
- }
- return count;
+ bArmature *arm = ob->data;
+ const bool hide_select = (bool)POINTER_AS_INT(ptr);
+ int count = 0;
+ if (arm->layer & bone->layer) {
+ if (((bone->flag & BONE_SELECTED) != 0) == hide_select) {
+ bone->flag |= BONE_HIDDEN_P;
+ /* only needed when 'hide_select' is true, but harmless. */
+ bone->flag &= ~BONE_SELECTED;
+ if (arm->act_bone == bone) {
+ arm->act_bone = NULL;
+ }
+ count += 1;
+ }
+ }
+ return count;
}
/* active object is armature in posemode, poll checked */
static int pose_hide_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len;
- Object **objects = BKE_object_pose_array_get_unique(view_layer, CTX_wm_view3d(C), &objects_len);
- bool changed_multi = false;
-
- const int hide_select = !RNA_boolean_get(op->ptr, "unselected");
- void *hide_select_p = POINTER_FROM_INT(hide_select);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob_iter = objects[ob_index];
- bArmature *arm = ob_iter->data;
-
- if (ob_iter->proxy != NULL) {
- BKE_report(op->reports, RPT_INFO, "Undo of hiding can only be done with Reveal Selected");
- }
-
- bool changed = bone_looper(ob_iter, arm->bonebase.first, hide_select_p, hide_pose_bone_fn) != 0;
- if (changed) {
- changed_multi = true;
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob_iter);
- DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
- }
- }
- MEM_freeN(objects);
-
- return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len;
+ Object **objects = BKE_object_pose_array_get_unique(view_layer, CTX_wm_view3d(C), &objects_len);
+ bool changed_multi = false;
+
+ const int hide_select = !RNA_boolean_get(op->ptr, "unselected");
+ void *hide_select_p = POINTER_FROM_INT(hide_select);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob_iter = objects[ob_index];
+ bArmature *arm = ob_iter->data;
+
+ if (ob_iter->proxy != NULL) {
+ BKE_report(op->reports, RPT_INFO, "Undo of hiding can only be done with Reveal Selected");
+ }
+
+ bool changed = bone_looper(ob_iter, arm->bonebase.first, hide_select_p, hide_pose_bone_fn) !=
+ 0;
+ if (changed) {
+ changed_multi = true;
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob_iter);
+ DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ }
+ MEM_freeN(objects);
+
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void POSE_OT_hide(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Selected";
- ot->idname = "POSE_OT_hide";
- ot->description = "Tag selected bones to not be visible in Pose Mode";
+ /* identifiers */
+ ot->name = "Hide Selected";
+ ot->idname = "POSE_OT_hide";
+ ot->description = "Tag selected bones to not be visible in Pose Mode";
- /* api callbacks */
- ot->exec = pose_hide_exec;
- ot->poll = ED_operator_posemode;
+ /* api callbacks */
+ ot->exec = pose_hide_exec;
+ ot->poll = ED_operator_posemode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "");
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "");
}
static int show_pose_bone_cb(Object *ob, Bone *bone, void *data)
{
- const bool select = POINTER_AS_INT(data);
-
- bArmature *arm = ob->data;
- int count = 0;
- if (arm->layer & bone->layer) {
- if (bone->flag & BONE_HIDDEN_P) {
- if (!(bone->flag & BONE_UNSELECTABLE)) {
- SET_FLAG_FROM_TEST(bone->flag, select, BONE_SELECTED);
- }
- bone->flag &= ~BONE_HIDDEN_P;
- count += 1;
- }
- }
-
- return count;
+ const bool select = POINTER_AS_INT(data);
+
+ bArmature *arm = ob->data;
+ int count = 0;
+ if (arm->layer & bone->layer) {
+ if (bone->flag & BONE_HIDDEN_P) {
+ if (!(bone->flag & BONE_UNSELECTABLE)) {
+ SET_FLAG_FROM_TEST(bone->flag, select, BONE_SELECTED);
+ }
+ bone->flag &= ~BONE_HIDDEN_P;
+ count += 1;
+ }
+ }
+
+ return count;
}
/* active object is armature in posemode, poll checked */
static int pose_reveal_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len;
- Object **objects = BKE_object_pose_array_get_unique(view_layer, CTX_wm_view3d(C), &objects_len);
- bool changed_multi = false;
- const bool select = RNA_boolean_get(op->ptr, "select");
- void *select_p = POINTER_FROM_INT(select);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob_iter = objects[ob_index];
- bArmature *arm = ob_iter->data;
-
- bool changed = bone_looper(ob_iter, arm->bonebase.first, select_p, show_pose_bone_cb);
- if (changed) {
- changed_multi = true;
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob_iter);
- DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
- }
- }
- MEM_freeN(objects);
-
- return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len;
+ Object **objects = BKE_object_pose_array_get_unique(view_layer, CTX_wm_view3d(C), &objects_len);
+ bool changed_multi = false;
+ const bool select = RNA_boolean_get(op->ptr, "select");
+ void *select_p = POINTER_FROM_INT(select);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob_iter = objects[ob_index];
+ bArmature *arm = ob_iter->data;
+
+ bool changed = bone_looper(ob_iter, arm->bonebase.first, select_p, show_pose_bone_cb);
+ if (changed) {
+ changed_multi = true;
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob_iter);
+ DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ }
+ MEM_freeN(objects);
+
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void POSE_OT_reveal(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reveal Selected";
- ot->idname = "POSE_OT_reveal";
- ot->description = "Reveal all bones hidden in Pose Mode";
+ /* identifiers */
+ ot->name = "Reveal Selected";
+ ot->idname = "POSE_OT_reveal";
+ ot->description = "Reveal all bones hidden in Pose Mode";
- /* api callbacks */
- ot->exec = pose_reveal_exec;
- ot->poll = ED_operator_posemode;
+ /* api callbacks */
+ ot->exec = pose_reveal_exec;
+ ot->poll = ED_operator_posemode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "select", true, "Select", "");
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
/* ********************************************** */
@@ -1118,49 +1136,53 @@ void POSE_OT_reveal(wmOperatorType *ot)
static int pose_flip_quats_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID);
-
- bool changed_multi = false;
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) {
- bool changed = false;
- /* loop through all selected pchans, flipping and keying (as needed) */
- FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob_iter, pchan) {
- /* only if bone is using quaternion rotation */
- if (pchan->rotmode == ROT_MODE_QUAT) {
- changed = true;
- /* quaternions have 720 degree range */
- negate_v4(pchan->quat);
-
- ED_autokeyframe_pchan(C, scene, ob_iter, pchan, ks);
- }
- } FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
-
- if (changed) {
- changed_multi = true;
- /* notifiers and updates */
- DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob_iter);
- }
- } FOREACH_OBJECT_IN_MODE_END;
-
- return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID);
+
+ bool changed_multi = false;
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) {
+ bool changed = false;
+ /* loop through all selected pchans, flipping and keying (as needed) */
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob_iter, pchan) {
+ /* only if bone is using quaternion rotation */
+ if (pchan->rotmode == ROT_MODE_QUAT) {
+ changed = true;
+ /* quaternions have 720 degree range */
+ negate_v4(pchan->quat);
+
+ ED_autokeyframe_pchan(C, scene, ob_iter, pchan, ks);
+ }
+ }
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
+
+ if (changed) {
+ changed_multi = true;
+ /* notifiers and updates */
+ DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob_iter);
+ }
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void POSE_OT_quaternions_flip(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Flip Quats";
- ot->idname = "POSE_OT_quaternions_flip";
- ot->description = "Flip quaternion values to achieve desired rotations, while maintaining the same orientations";
-
- /* callbacks */
- ot->exec = pose_flip_quats_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Flip Quats";
+ ot->idname = "POSE_OT_quaternions_flip";
+ ot->description =
+ "Flip quaternion values to achieve desired rotations, while maintaining the same "
+ "orientations";
+
+ /* callbacks */
+ ot->exec = pose_flip_quats_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/armature/pose_group.c b/source/blender/editors/armature/pose_group.c
index 596e64b54fe..0d100a09dfd 100644
--- a/source/blender/editors/armature/pose_group.c
+++ b/source/blender/editors/armature/pose_group.c
@@ -56,68 +56,67 @@
static int pose_group_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_pose_object_from_context(C);
+ Object *ob = ED_pose_object_from_context(C);
- /* only continue if there's an object and pose */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
+ /* only continue if there's an object and pose */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
- /* for now, just call the API function for this */
- BKE_pose_add_group(ob->pose, NULL);
+ /* for now, just call the API function for this */
+ BKE_pose_add_group(ob->pose, NULL);
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void POSE_OT_group_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Bone Group";
- ot->idname = "POSE_OT_group_add";
- ot->description = "Add a new bone group";
+ /* identifiers */
+ ot->name = "Add Bone Group";
+ ot->idname = "POSE_OT_group_add";
+ ot->description = "Add a new bone group";
- /* api callbacks */
- ot->exec = pose_group_add_exec;
- ot->poll = ED_operator_posemode_context;
+ /* api callbacks */
+ ot->exec = pose_group_add_exec;
+ ot->poll = ED_operator_posemode_context;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
static int pose_group_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_pose_object_from_context(C);
+ Object *ob = ED_pose_object_from_context(C);
- /* only continue if there's an object and pose */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
+ /* only continue if there's an object and pose */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
- /* for now, just call the API function for this */
- BKE_pose_remove_group_index(ob->pose, ob->pose->active_group);
+ /* for now, just call the API function for this */
+ BKE_pose_remove_group_index(ob->pose, ob->pose->active_group);
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void POSE_OT_group_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Bone Group";
- ot->idname = "POSE_OT_group_remove";
- ot->description = "Remove the active bone group";
+ /* identifiers */
+ ot->name = "Remove Bone Group";
+ ot->idname = "POSE_OT_group_remove";
+ ot->description = "Remove the active bone group";
- /* api callbacks */
- ot->exec = pose_group_remove_exec;
- ot->poll = ED_operator_posemode_context;
+ /* api callbacks */
+ ot->exec = pose_group_remove_exec;
+ ot->poll = ED_operator_posemode_context;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ------------ */
@@ -125,397 +124,397 @@ void POSE_OT_group_remove(wmOperatorType *ot)
/* invoke callback which presents a list of bone-groups for the user to choose from */
static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Object *ob = ED_pose_object_from_context(C);
- bPose *pose;
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, "type");
-
- uiPopupMenu *pup;
- uiLayout *layout;
- bActionGroup *grp;
- int i;
-
- /* only continue if there's an object, and a pose there too */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
- pose = ob->pose;
-
- /* If group index is set, try to use it! */
- if (RNA_property_is_set(op->ptr, prop)) {
- const int num_groups = BLI_listbase_count(&pose->agroups);
- const int group = RNA_property_int_get(op->ptr, prop);
-
- /* just use the active group index, and call the exec callback for the calling operator */
- if (group > 0 && group <= num_groups) {
- return op->type->exec(C, op);
- }
- }
-
- /* if there's no active group (or active is invalid), create a new menu to find it */
- if (pose->active_group <= 0) {
- /* create a new menu, and start populating it with group names */
- pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
- layout = UI_popup_menu_layout(pup);
-
- /* special entry - allow to create new group, then use that
- * (not to be used for removing though)
- */
- if (strstr(op->idname, "assign")) {
- uiItemIntO(layout, "New Group", ICON_NONE, op->idname, "type", 0);
- uiItemS(layout);
- }
-
- /* add entries for each group */
- for (grp = pose->agroups.first, i = 1; grp; grp = grp->next, i++)
- uiItemIntO(layout, grp->name, ICON_NONE, op->idname, "type", i);
-
- /* finish building the menu, and process it (should result in calling self again) */
- UI_popup_menu_end(C, pup);
-
- return OPERATOR_INTERFACE;
- }
- else {
- /* just use the active group index, and call the exec callback for the calling operator */
- RNA_int_set(op->ptr, "type", pose->active_group);
- return op->type->exec(C, op);
- }
+ Object *ob = ED_pose_object_from_context(C);
+ bPose *pose;
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "type");
+
+ uiPopupMenu *pup;
+ uiLayout *layout;
+ bActionGroup *grp;
+ int i;
+
+ /* only continue if there's an object, and a pose there too */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+ pose = ob->pose;
+
+ /* If group index is set, try to use it! */
+ if (RNA_property_is_set(op->ptr, prop)) {
+ const int num_groups = BLI_listbase_count(&pose->agroups);
+ const int group = RNA_property_int_get(op->ptr, prop);
+
+ /* just use the active group index, and call the exec callback for the calling operator */
+ if (group > 0 && group <= num_groups) {
+ return op->type->exec(C, op);
+ }
+ }
+
+ /* if there's no active group (or active is invalid), create a new menu to find it */
+ if (pose->active_group <= 0) {
+ /* create a new menu, and start populating it with group names */
+ pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+
+ /* special entry - allow to create new group, then use that
+ * (not to be used for removing though)
+ */
+ if (strstr(op->idname, "assign")) {
+ uiItemIntO(layout, "New Group", ICON_NONE, op->idname, "type", 0);
+ uiItemS(layout);
+ }
+
+ /* add entries for each group */
+ for (grp = pose->agroups.first, i = 1; grp; grp = grp->next, i++)
+ uiItemIntO(layout, grp->name, ICON_NONE, op->idname, "type", i);
+
+ /* finish building the menu, and process it (should result in calling self again) */
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
+ }
+ else {
+ /* just use the active group index, and call the exec callback for the calling operator */
+ RNA_int_set(op->ptr, "type", pose->active_group);
+ return op->type->exec(C, op);
+ }
}
/* Assign selected pchans to the bone group that the user selects */
static int pose_group_assign_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_pose_object_from_context(C);
- bPose *pose;
- bool done = false;
-
- /* only continue if there's an object, and a pose there too */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
-
- pose = ob->pose;
-
- /* set the active group number to the one from operator props
- * - if 0 after this, make a new group...
- */
- pose->active_group = RNA_int_get(op->ptr, "type");
- if (pose->active_group == 0)
- BKE_pose_add_group(ob->pose, NULL);
-
- /* add selected bones to group then */
- FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob, pchan)
- {
- pchan->agrp_index = pose->active_group;
- done = true;
- }
- FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
-
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
-
- /* report done status */
- if (done)
- return OPERATOR_FINISHED;
- else
- return OPERATOR_CANCELLED;
+ Object *ob = ED_pose_object_from_context(C);
+ bPose *pose;
+ bool done = false;
+
+ /* only continue if there's an object, and a pose there too */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+
+ pose = ob->pose;
+
+ /* set the active group number to the one from operator props
+ * - if 0 after this, make a new group...
+ */
+ pose->active_group = RNA_int_get(op->ptr, "type");
+ if (pose->active_group == 0)
+ BKE_pose_add_group(ob->pose, NULL);
+
+ /* add selected bones to group then */
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob, pchan) {
+ pchan->agrp_index = pose->active_group;
+ done = true;
+ }
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+
+ /* report done status */
+ if (done)
+ return OPERATOR_FINISHED;
+ else
+ return OPERATOR_CANCELLED;
}
void POSE_OT_group_assign(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Selected to Bone Group";
- ot->idname = "POSE_OT_group_assign";
- ot->description = "Add selected bones to the chosen bone group";
+ /* identifiers */
+ ot->name = "Add Selected to Bone Group";
+ ot->idname = "POSE_OT_group_assign";
+ ot->description = "Add selected bones to the chosen bone group";
- /* api callbacks */
- ot->invoke = pose_groups_menu_invoke;
- ot->exec = pose_group_assign_exec;
- ot->poll = ED_operator_posemode_context;
+ /* api callbacks */
+ ot->invoke = pose_groups_menu_invoke;
+ ot->exec = pose_group_assign_exec;
+ ot->poll = ED_operator_posemode_context;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_int(ot->srna, "type", 0, 0, INT_MAX, "Bone Group Index", "", 0, 10);
+ /* properties */
+ RNA_def_int(ot->srna, "type", 0, 0, INT_MAX, "Bone Group Index", "", 0, 10);
}
-
static int pose_group_unassign_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_pose_object_from_context(C);
- bool done = false;
-
- /* only continue if there's an object, and a pose there too */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
-
- /* find selected bones to remove from all bone groups */
- FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob, pchan)
- {
- if (pchan->agrp_index) {
- pchan->agrp_index = 0;
- done = true;
- }
- }
- FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
-
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
-
- /* report done status */
- if (done)
- return OPERATOR_FINISHED;
- else
- return OPERATOR_CANCELLED;
+ Object *ob = ED_pose_object_from_context(C);
+ bool done = false;
+
+ /* only continue if there's an object, and a pose there too */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+
+ /* find selected bones to remove from all bone groups */
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob, pchan) {
+ if (pchan->agrp_index) {
+ pchan->agrp_index = 0;
+ done = true;
+ }
+ }
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+
+ /* report done status */
+ if (done)
+ return OPERATOR_FINISHED;
+ else
+ return OPERATOR_CANCELLED;
}
void POSE_OT_group_unassign(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Selected from Bone Groups";
- ot->idname = "POSE_OT_group_unassign";
- ot->description = "Remove selected bones from all bone groups";
+ /* identifiers */
+ ot->name = "Remove Selected from Bone Groups";
+ ot->idname = "POSE_OT_group_unassign";
+ ot->description = "Remove selected bones from all bone groups";
- /* api callbacks */
- ot->exec = pose_group_unassign_exec;
- ot->poll = ED_operator_posemode_context;
+ /* api callbacks */
+ ot->exec = pose_group_unassign_exec;
+ ot->poll = ED_operator_posemode_context;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int group_move_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_pose_object_from_context(C);
- bPose *pose = (ob) ? ob->pose : NULL;
- bPoseChannel *pchan;
- bActionGroup *grp;
- int dir = RNA_enum_get(op->ptr, "direction");
-
- if (ELEM(NULL, ob, pose))
- return OPERATOR_CANCELLED;
- if (pose->active_group <= 0)
- return OPERATOR_CANCELLED;
-
- /* get group to move */
- grp = BLI_findlink(&pose->agroups, pose->active_group - 1);
- if (grp == NULL)
- return OPERATOR_CANCELLED;
-
- /* move bone group */
- if (BLI_listbase_link_move(&pose->agroups, grp, dir)) {
- int grpIndexA = pose->active_group;
- int grpIndexB = grpIndexA + dir;
-
- pose->active_group += dir;
- /* fix changed bone group indices in bones (swap grpIndexA with grpIndexB) */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->agrp_index == grpIndexB) {
- pchan->agrp_index = grpIndexA;
- }
- else if (pchan->agrp_index == grpIndexA) {
- pchan->agrp_index = grpIndexB;
- }
- }
-
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- }
-
- return OPERATOR_FINISHED;
+ Object *ob = ED_pose_object_from_context(C);
+ bPose *pose = (ob) ? ob->pose : NULL;
+ bPoseChannel *pchan;
+ bActionGroup *grp;
+ int dir = RNA_enum_get(op->ptr, "direction");
+
+ if (ELEM(NULL, ob, pose))
+ return OPERATOR_CANCELLED;
+ if (pose->active_group <= 0)
+ return OPERATOR_CANCELLED;
+
+ /* get group to move */
+ grp = BLI_findlink(&pose->agroups, pose->active_group - 1);
+ if (grp == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* move bone group */
+ if (BLI_listbase_link_move(&pose->agroups, grp, dir)) {
+ int grpIndexA = pose->active_group;
+ int grpIndexB = grpIndexA + dir;
+
+ pose->active_group += dir;
+ /* fix changed bone group indices in bones (swap grpIndexA with grpIndexB) */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->agrp_index == grpIndexB) {
+ pchan->agrp_index = grpIndexA;
+ }
+ else if (pchan->agrp_index == grpIndexA) {
+ pchan->agrp_index = grpIndexB;
+ }
+ }
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ }
+
+ return OPERATOR_FINISHED;
}
void POSE_OT_group_move(wmOperatorType *ot)
{
- static const EnumPropertyItem group_slot_move[] = {
- {-1, "UP", 0, "Up", ""},
- {1, "DOWN", 0, "Down", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Move Bone Group";
- ot->idname = "POSE_OT_group_move";
- ot->description = "Change position of active Bone Group in list of Bone Groups";
-
- /* api callbacks */
- ot->exec = group_move_exec;
- ot->poll = ED_operator_posemode_context;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "direction", group_slot_move, 0, "Direction",
- "Direction to move the active Bone Group towards");
+ static const EnumPropertyItem group_slot_move[] = {
+ {-1, "UP", 0, "Up", ""},
+ {1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Move Bone Group";
+ ot->idname = "POSE_OT_group_move";
+ ot->description = "Change position of active Bone Group in list of Bone Groups";
+
+ /* api callbacks */
+ ot->exec = group_move_exec;
+ ot->poll = ED_operator_posemode_context;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna,
+ "direction",
+ group_slot_move,
+ 0,
+ "Direction",
+ "Direction to move the active Bone Group towards");
}
/* bone group sort element */
typedef struct tSortActionGroup {
- bActionGroup *agrp;
- int index;
+ bActionGroup *agrp;
+ int index;
} tSortActionGroup;
/* compare bone groups by name */
static int compare_agroup(const void *sgrp_a_ptr, const void *sgrp_b_ptr)
{
- const tSortActionGroup *sgrp_a = sgrp_a_ptr;
- const tSortActionGroup *sgrp_b = sgrp_b_ptr;
+ const tSortActionGroup *sgrp_a = sgrp_a_ptr;
+ const tSortActionGroup *sgrp_b = sgrp_b_ptr;
- return strcmp(sgrp_a->agrp->name, sgrp_b->agrp->name);
+ return strcmp(sgrp_a->agrp->name, sgrp_b->agrp->name);
}
static int group_sort_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_pose_object_from_context(C);
- bPose *pose = (ob) ? ob->pose : NULL;
- bPoseChannel *pchan;
- tSortActionGroup *agrp_array;
- bActionGroup *agrp;
- int agrp_count;
- int i;
-
- if (ELEM(NULL, ob, pose))
- return OPERATOR_CANCELLED;
- if (pose->active_group <= 0)
- return OPERATOR_CANCELLED;
-
- /* create temporary array with bone groups and indices */
- agrp_count = BLI_listbase_count(&pose->agroups);
- agrp_array = MEM_mallocN(sizeof(tSortActionGroup) * agrp_count, "sort bone groups");
- for (agrp = pose->agroups.first, i = 0; agrp; agrp = agrp->next, i++) {
- BLI_assert(i < agrp_count);
- agrp_array[i].agrp = agrp;
- agrp_array[i].index = i + 1;
- }
-
- /* sort bone groups by name */
- qsort(agrp_array, agrp_count, sizeof(tSortActionGroup), compare_agroup);
-
- /* create sorted bone group list from sorted array */
- BLI_listbase_clear(&pose->agroups);
- for (i = 0; i < agrp_count; i++) {
- BLI_addtail(&pose->agroups, agrp_array[i].agrp);
- }
-
- /* fix changed bone group indizes in bones */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- for (i = 0; i < agrp_count; i++) {
- if (pchan->agrp_index == agrp_array[i].index) {
- pchan->agrp_index = i + 1;
- break;
- }
- }
- }
-
- /* free temp resources */
- MEM_freeN(agrp_array);
-
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
-
- return OPERATOR_FINISHED;
+ Object *ob = ED_pose_object_from_context(C);
+ bPose *pose = (ob) ? ob->pose : NULL;
+ bPoseChannel *pchan;
+ tSortActionGroup *agrp_array;
+ bActionGroup *agrp;
+ int agrp_count;
+ int i;
+
+ if (ELEM(NULL, ob, pose))
+ return OPERATOR_CANCELLED;
+ if (pose->active_group <= 0)
+ return OPERATOR_CANCELLED;
+
+ /* create temporary array with bone groups and indices */
+ agrp_count = BLI_listbase_count(&pose->agroups);
+ agrp_array = MEM_mallocN(sizeof(tSortActionGroup) * agrp_count, "sort bone groups");
+ for (agrp = pose->agroups.first, i = 0; agrp; agrp = agrp->next, i++) {
+ BLI_assert(i < agrp_count);
+ agrp_array[i].agrp = agrp;
+ agrp_array[i].index = i + 1;
+ }
+
+ /* sort bone groups by name */
+ qsort(agrp_array, agrp_count, sizeof(tSortActionGroup), compare_agroup);
+
+ /* create sorted bone group list from sorted array */
+ BLI_listbase_clear(&pose->agroups);
+ for (i = 0; i < agrp_count; i++) {
+ BLI_addtail(&pose->agroups, agrp_array[i].agrp);
+ }
+
+ /* fix changed bone group indizes in bones */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ for (i = 0; i < agrp_count; i++) {
+ if (pchan->agrp_index == agrp_array[i].index) {
+ pchan->agrp_index = i + 1;
+ break;
+ }
+ }
+ }
+
+ /* free temp resources */
+ MEM_freeN(agrp_array);
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+
+ return OPERATOR_FINISHED;
}
void POSE_OT_group_sort(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Sort Bone Groups";
- ot->idname = "POSE_OT_group_sort";
- ot->description = "Sort Bone Groups by their names in ascending order";
+ /* identifiers */
+ ot->name = "Sort Bone Groups";
+ ot->idname = "POSE_OT_group_sort";
+ ot->description = "Sort Bone Groups by their names in ascending order";
- /* api callbacks */
- ot->exec = group_sort_exec;
- ot->poll = ED_operator_posemode_context;
+ /* api callbacks */
+ ot->exec = group_sort_exec;
+ ot->poll = ED_operator_posemode_context;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static void pose_group_select(Object *ob, bool select)
{
- bPose *pose = ob->pose;
-
- FOREACH_PCHAN_VISIBLE_IN_OBJECT_BEGIN (ob, pchan)
- {
- if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
- if (select) {
- if (pchan->agrp_index == pose->active_group)
- pchan->bone->flag |= BONE_SELECTED;
- }
- else {
- if (pchan->agrp_index == pose->active_group)
- pchan->bone->flag &= ~BONE_SELECTED;
- }
- }
- }
- FOREACH_PCHAN_VISIBLE_IN_OBJECT_END;
+ bPose *pose = ob->pose;
+
+ FOREACH_PCHAN_VISIBLE_IN_OBJECT_BEGIN (ob, pchan) {
+ if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
+ if (select) {
+ if (pchan->agrp_index == pose->active_group)
+ pchan->bone->flag |= BONE_SELECTED;
+ }
+ else {
+ if (pchan->agrp_index == pose->active_group)
+ pchan->bone->flag &= ~BONE_SELECTED;
+ }
+ }
+ }
+ FOREACH_PCHAN_VISIBLE_IN_OBJECT_END;
}
static int pose_group_select_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_pose_object_from_context(C);
+ Object *ob = ED_pose_object_from_context(C);
- /* only continue if there's an object, and a pose there too */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
+ /* only continue if there's an object, and a pose there too */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
- pose_group_select(ob, 1);
+ pose_group_select(ob, 1);
- /* notifiers for updates */
- bArmature *arm = ob->data;
- DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ /* notifiers for updates */
+ bArmature *arm = ob->data;
+ DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void POSE_OT_group_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Bones of Bone Group";
- ot->idname = "POSE_OT_group_select";
- ot->description = "Select bones in active Bone Group";
+ /* identifiers */
+ ot->name = "Select Bones of Bone Group";
+ ot->idname = "POSE_OT_group_select";
+ ot->description = "Select bones in active Bone Group";
- /* api callbacks */
- ot->exec = pose_group_select_exec;
- ot->poll = ED_operator_posemode_context;
+ /* api callbacks */
+ ot->exec = pose_group_select_exec;
+ ot->poll = ED_operator_posemode_context;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int pose_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_pose_object_from_context(C);
+ Object *ob = ED_pose_object_from_context(C);
- /* only continue if there's an object, and a pose there too */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
+ /* only continue if there's an object, and a pose there too */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
- pose_group_select(ob, 0);
+ pose_group_select(ob, 0);
- /* notifiers for updates */
- bArmature *arm = ob->data;
- DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ /* notifiers for updates */
+ bArmature *arm = ob->data;
+ DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void POSE_OT_group_deselect(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Deselect Bone Group";
- ot->idname = "POSE_OT_group_deselect";
- ot->description = "Deselect bones of active Bone Group";
+ /* identifiers */
+ ot->name = "Deselect Bone Group";
+ ot->idname = "POSE_OT_group_deselect";
+ ot->description = "Deselect bones of active Bone Group";
- /* api callbacks */
- ot->exec = pose_group_deselect_exec;
- ot->poll = ED_operator_posemode_context;
+ /* api callbacks */
+ ot->exec = pose_group_deselect_exec;
+ ot->poll = ED_operator_posemode_context;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************************************** */
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index 41df3086fa8..443bcdde028 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -72,7 +72,9 @@
/* ******* XXX ********** */
-static void action_set_activemarker(void *UNUSED(a), void *UNUSED(b), void *UNUSED(c)) {}
+static void action_set_activemarker(void *UNUSED(a), void *UNUSED(b), void *UNUSED(c))
+{
+}
/* ************************************************************* */
/* == POSE-LIBRARY TOOL FOR BLENDER ==
@@ -93,84 +95,84 @@ static void action_set_activemarker(void *UNUSED(a), void *UNUSED(b), void *UNUS
*/
/* ************************************************************* */
-
/* gets the first available frame in poselib to store a pose on
* - frames start from 1, and a pose should occur on every frame... 0 is error!
*/
static int poselib_get_free_index(bAction *act)
{
- TimeMarker *marker;
- int low = 0, high = 0;
- bool changed = false;
-
- /* sanity checks */
- if (ELEM(NULL, act, act->markers.first)) return 1;
-
- /* As poses are not stored in chronological order, we must iterate over this list
- * a few times until we don't make any new discoveries (mostly about the lower bound).
- * Prevents problems with deleting then trying to add new poses [#27412]
- */
- do {
- changed = false;
-
- for (marker = act->markers.first; marker; marker = marker->next) {
- /* only increase low if value is 1 greater than low, to find "gaps" where
- * poses were removed from the poselib
- */
- if (marker->frame == (low + 1)) {
- low++;
- changed = true;
- }
-
- /* value replaces high if it is the highest value encountered yet */
- if (marker->frame > high) {
- high = marker->frame;
- changed = true;
- }
- }
- } while (changed != 0);
-
- /* - if low is not equal to high, then low+1 is a gap
- * - if low is equal to high, then high+1 is the next index (add at end)
- */
- if (low < high)
- return (low + 1);
- else
- return (high + 1);
+ TimeMarker *marker;
+ int low = 0, high = 0;
+ bool changed = false;
+
+ /* sanity checks */
+ if (ELEM(NULL, act, act->markers.first))
+ return 1;
+
+ /* As poses are not stored in chronological order, we must iterate over this list
+ * a few times until we don't make any new discoveries (mostly about the lower bound).
+ * Prevents problems with deleting then trying to add new poses [#27412]
+ */
+ do {
+ changed = false;
+
+ for (marker = act->markers.first; marker; marker = marker->next) {
+ /* only increase low if value is 1 greater than low, to find "gaps" where
+ * poses were removed from the poselib
+ */
+ if (marker->frame == (low + 1)) {
+ low++;
+ changed = true;
+ }
+
+ /* value replaces high if it is the highest value encountered yet */
+ if (marker->frame > high) {
+ high = marker->frame;
+ changed = true;
+ }
+ }
+ } while (changed != 0);
+
+ /* - if low is not equal to high, then low+1 is a gap
+ * - if low is equal to high, then high+1 is the next index (add at end)
+ */
+ if (low < high)
+ return (low + 1);
+ else
+ return (high + 1);
}
/* returns the active pose for a poselib */
static TimeMarker *poselib_get_active_pose(bAction *act)
{
- if ((act) && (act->active_marker))
- return BLI_findlink(&act->markers, act->active_marker - 1);
- else
- return NULL;
+ if ((act) && (act->active_marker))
+ return BLI_findlink(&act->markers, act->active_marker - 1);
+ else
+ return NULL;
}
/* Get object that Pose Lib should be found on */
/* XXX C can be zero */
static Object *get_poselib_object(bContext *C)
{
- ScrArea *sa;
+ ScrArea *sa;
- /* sanity check */
- if (C == NULL)
- return NULL;
+ /* sanity check */
+ if (C == NULL)
+ return NULL;
- sa = CTX_wm_area(C);
+ sa = CTX_wm_area(C);
- if (sa && (sa->spacetype == SPACE_PROPERTIES))
- return ED_object_context(C);
- else
- return BKE_object_pose_armature_get(CTX_data_active_object(C));
+ if (sa && (sa->spacetype == SPACE_PROPERTIES))
+ return ED_object_context(C);
+ else
+ return BKE_object_pose_armature_get(CTX_data_active_object(C));
}
/* Poll callback for operators that require existing PoseLib data (with poses) to work */
static bool has_poselib_pose_data_poll(bContext *C)
{
- Object *ob = get_poselib_object(C);
- return (ob && ob->poselib);
+ Object *ob = get_poselib_object(C);
+ return (ob && ob->poselib);
}
/* Poll callback for operators that require existing PoseLib data (with poses)
@@ -178,8 +180,8 @@ static bool has_poselib_pose_data_poll(bContext *C)
*/
static bool has_poselib_pose_data_for_editing_poll(bContext *C)
{
- Object *ob = get_poselib_object(C);
- return (ob && ob->poselib && !ID_IS_LINKED(ob->poselib));
+ Object *ob = get_poselib_object(C);
+ return (ob && ob->poselib && !ID_IS_LINKED(ob->poselib));
}
/* ----------------------------------- */
@@ -187,29 +189,29 @@ static bool has_poselib_pose_data_for_editing_poll(bContext *C)
/* Initialize a new poselib (whether it is needed or not) */
static bAction *poselib_init_new(Main *bmain, Object *ob)
{
- /* sanity checks - only for armatures */
- if (ELEM(NULL, ob, ob->pose))
- return NULL;
+ /* sanity checks - only for armatures */
+ if (ELEM(NULL, ob, ob->pose))
+ return NULL;
- /* init object's poselib action (unlink old one if there) */
- if (ob->poselib)
- id_us_min(&ob->poselib->id);
+ /* init object's poselib action (unlink old one if there) */
+ if (ob->poselib)
+ id_us_min(&ob->poselib->id);
- ob->poselib = BKE_action_add(bmain, "PoseLib");
- ob->poselib->idroot = ID_OB;
+ ob->poselib = BKE_action_add(bmain, "PoseLib");
+ ob->poselib->idroot = ID_OB;
- return ob->poselib;
+ return ob->poselib;
}
/* Initialize a new poselib (checks if that needs to happen) */
static bAction *poselib_validate(Main *bmain, Object *ob)
{
- if (ELEM(NULL, ob, ob->pose))
- return NULL;
- else if (ob->poselib == NULL)
- return poselib_init_new(bmain, ob);
- else
- return ob->poselib;
+ if (ELEM(NULL, ob, ob->pose))
+ return NULL;
+ else if (ob->poselib == NULL)
+ return poselib_init_new(bmain, ob);
+ else
+ return ob->poselib;
}
/* ************************************************************* */
@@ -217,70 +219,70 @@ static bAction *poselib_validate(Main *bmain, Object *ob)
static int poselib_new_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Object *ob = get_poselib_object(C);
+ Main *bmain = CTX_data_main(C);
+ Object *ob = get_poselib_object(C);
- /* sanity checks */
- if (ob == NULL)
- return OPERATOR_CANCELLED;
+ /* sanity checks */
+ if (ob == NULL)
+ return OPERATOR_CANCELLED;
- /* new method here deals with the rest... */
- poselib_init_new(bmain, ob);
+ /* new method here deals with the rest... */
+ poselib_init_new(bmain, ob);
- /* notifier here might evolve? */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+ /* notifier here might evolve? */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void POSELIB_OT_new(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "New Pose Library";
- ot->idname = "POSELIB_OT_new";
- ot->description = "Add New Pose Library to active Object";
+ /* identifiers */
+ ot->name = "New Pose Library";
+ ot->idname = "POSELIB_OT_new";
+ ot->description = "Add New Pose Library to active Object";
- /* callbacks */
- ot->exec = poselib_new_exec;
- ot->poll = ED_operator_posemode;
+ /* callbacks */
+ ot->exec = poselib_new_exec;
+ ot->poll = ED_operator_posemode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ------------------------------------------------ */
static int poselib_unlink_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = get_poselib_object(C);
+ Object *ob = get_poselib_object(C);
- /* sanity checks */
- if (ELEM(NULL, ob, ob->poselib))
- return OPERATOR_CANCELLED;
+ /* sanity checks */
+ if (ELEM(NULL, ob, ob->poselib))
+ return OPERATOR_CANCELLED;
- /* there should be a poselib (we just checked above!), so just lower its user count and remove */
- id_us_min(&ob->poselib->id);
- ob->poselib = NULL;
+ /* there should be a poselib (we just checked above!), so just lower its user count and remove */
+ id_us_min(&ob->poselib->id);
+ ob->poselib = NULL;
- /* notifier here might evolve? */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+ /* notifier here might evolve? */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void POSELIB_OT_unlink(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unlink Pose Library";
- ot->idname = "POSELIB_OT_unlink";
- ot->description = "Remove Pose Library from active Object";
+ /* identifiers */
+ ot->name = "Unlink Pose Library";
+ ot->idname = "POSELIB_OT_unlink";
+ ot->description = "Remove Pose Library from active Object";
- /* callbacks */
- ot->exec = poselib_unlink_exec;
- ot->poll = has_poselib_pose_data_poll;
+ /* callbacks */
+ ot->exec = poselib_unlink_exec;
+ ot->poll = has_poselib_pose_data_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ************************************************************* */
@@ -291,81 +293,81 @@ void POSELIB_OT_unlink(wmOperatorType *ot)
*/
static int poselib_sanitize_exec(bContext *C, wmOperator *op)
{
- Object *ob = get_poselib_object(C);
- bAction *act = (ob) ? ob->poselib : NULL;
- DLRBT_Tree keys;
- ActKeyColumn *ak;
- TimeMarker *marker, *markern;
-
- /* validate action */
- if (act == NULL) {
- BKE_report(op->reports, RPT_WARNING, "No action to validate");
- return OPERATOR_CANCELLED;
- }
-
- /* determine which frames have keys */
- BLI_dlrbTree_init(&keys);
- action_to_keylist(NULL, act, &keys, 0);
-
- /* for each key, make sure there is a corresponding pose */
- for (ak = keys.first; ak; ak = ak->next) {
- /* check if any pose matches this */
- /* TODO: don't go looking through the list like this every time... */
- for (marker = act->markers.first; marker; marker = marker->next) {
- if (IS_EQ((double)marker->frame, (double)ak->cfra)) {
- marker->flag = -1;
- break;
- }
- }
-
- /* add new if none found */
- if (marker == NULL) {
- /* add pose to poselib */
- marker = MEM_callocN(sizeof(TimeMarker), "ActionMarker");
-
- BLI_snprintf(marker->name, sizeof(marker->name), "F%d Pose", (int)ak->cfra);
-
- marker->frame = (int)ak->cfra;
- marker->flag = -1;
-
- BLI_addtail(&act->markers, marker);
- }
- }
-
- /* remove all untagged poses (unused), and remove all tags */
- for (marker = act->markers.first; marker; marker = markern) {
- markern = marker->next;
-
- if (marker->flag != -1)
- BLI_freelinkN(&act->markers, marker);
- else
- marker->flag = 0;
- }
-
- /* free temp memory */
- BLI_dlrbTree_free(&keys);
-
- /* send notifiers for this - using keyframe editing notifiers, since action
- * may be being shown in anim editors as active action
- */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
+ Object *ob = get_poselib_object(C);
+ bAction *act = (ob) ? ob->poselib : NULL;
+ DLRBT_Tree keys;
+ ActKeyColumn *ak;
+ TimeMarker *marker, *markern;
+
+ /* validate action */
+ if (act == NULL) {
+ BKE_report(op->reports, RPT_WARNING, "No action to validate");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* determine which frames have keys */
+ BLI_dlrbTree_init(&keys);
+ action_to_keylist(NULL, act, &keys, 0);
+
+ /* for each key, make sure there is a corresponding pose */
+ for (ak = keys.first; ak; ak = ak->next) {
+ /* check if any pose matches this */
+ /* TODO: don't go looking through the list like this every time... */
+ for (marker = act->markers.first; marker; marker = marker->next) {
+ if (IS_EQ((double)marker->frame, (double)ak->cfra)) {
+ marker->flag = -1;
+ break;
+ }
+ }
+
+ /* add new if none found */
+ if (marker == NULL) {
+ /* add pose to poselib */
+ marker = MEM_callocN(sizeof(TimeMarker), "ActionMarker");
+
+ BLI_snprintf(marker->name, sizeof(marker->name), "F%d Pose", (int)ak->cfra);
+
+ marker->frame = (int)ak->cfra;
+ marker->flag = -1;
+
+ BLI_addtail(&act->markers, marker);
+ }
+ }
+
+ /* remove all untagged poses (unused), and remove all tags */
+ for (marker = act->markers.first; marker; marker = markern) {
+ markern = marker->next;
+
+ if (marker->flag != -1)
+ BLI_freelinkN(&act->markers, marker);
+ else
+ marker->flag = 0;
+ }
+
+ /* free temp memory */
+ BLI_dlrbTree_free(&keys);
+
+ /* send notifiers for this - using keyframe editing notifiers, since action
+ * may be being shown in anim editors as active action
+ */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
}
void POSELIB_OT_action_sanitize(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Sanitize Pose Library Action";
- ot->idname = "POSELIB_OT_action_sanitize";
- ot->description = "Make action suitable for use as a Pose Library";
+ /* identifiers */
+ ot->name = "Sanitize Pose Library Action";
+ ot->idname = "POSELIB_OT_action_sanitize";
+ ot->description = "Make action suitable for use as a Pose Library";
- /* callbacks */
- ot->exec = poselib_sanitize_exec;
- ot->poll = has_poselib_pose_data_for_editing_poll;
+ /* callbacks */
+ ot->exec = poselib_sanitize_exec;
+ ot->poll = has_poselib_pose_data_for_editing_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ------------------------------------------ */
@@ -373,615 +375,631 @@ void POSELIB_OT_action_sanitize(wmOperatorType *ot)
/* Poll callback for adding poses to a PoseLib */
static bool poselib_add_poll(bContext *C)
{
- /* There are 2 cases we need to be careful with:
- * 1) When this operator is invoked from a hotkey, there may be no PoseLib yet
- * 2) If a PoseLib already exists, we can't edit the action if it is a lib-linked
- * actions, as data will be lost when saving the file
- */
- if (ED_operator_posemode(C)) {
- Object *ob = get_poselib_object(C);
- if (ob) {
- if ((ob->poselib == NULL) || !ID_IS_LINKED(ob->poselib)) {
- return true;
- }
- }
- }
- return false;
+ /* There are 2 cases we need to be careful with:
+ * 1) When this operator is invoked from a hotkey, there may be no PoseLib yet
+ * 2) If a PoseLib already exists, we can't edit the action if it is a lib-linked
+ * actions, as data will be lost when saving the file
+ */
+ if (ED_operator_posemode(C)) {
+ Object *ob = get_poselib_object(C);
+ if (ob) {
+ if ((ob->poselib == NULL) || !ID_IS_LINKED(ob->poselib)) {
+ return true;
+ }
+ }
+ }
+ return false;
}
static void poselib_add_menu_invoke__replacemenu(bContext *C, uiLayout *layout, void *UNUSED(arg))
{
- Object *ob = get_poselib_object(C);
- bAction *act = ob->poselib; /* never NULL */
- TimeMarker *marker;
-
- wmOperatorType *ot = WM_operatortype_find("POSELIB_OT_pose_add", 1);
-
- BLI_assert(ot != NULL);
-
- /* set the operator execution context correctly */
- uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
-
- /* add each marker to this menu */
- for (marker = act->markers.first; marker; marker = marker->next) {
- PointerRNA props_ptr;
- uiItemFullO_ptr(
- layout, ot,
- marker->name, ICON_ARMATURE_DATA, NULL,
- WM_OP_EXEC_DEFAULT, 0, &props_ptr);
- RNA_int_set(&props_ptr, "frame", marker->frame);
- RNA_string_set(&props_ptr, "name", marker->name);
- }
-}
-
-static int poselib_add_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- Scene *scene = CTX_data_scene(C);
- Object *ob = get_poselib_object(C);
- bPose *pose = (ob) ? ob->pose : NULL;
- uiPopupMenu *pup;
- uiLayout *layout;
-
- /* sanity check */
- if (ELEM(NULL, ob, pose))
- return OPERATOR_CANCELLED;
-
- /* start building */
- pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
- layout = UI_popup_menu_layout(pup);
- uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
+ Object *ob = get_poselib_object(C);
+ bAction *act = ob->poselib; /* never NULL */
+ TimeMarker *marker;
- /* add new (adds to the first unoccupied frame) */
- uiItemIntO(layout, IFACE_("Add New"), ICON_NONE, "POSELIB_OT_pose_add", "frame", poselib_get_free_index(ob->poselib));
+ wmOperatorType *ot = WM_operatortype_find("POSELIB_OT_pose_add", 1);
- /* check if we have any choices to add a new pose in any other way */
- if ((ob->poselib) && (ob->poselib->markers.first)) {
- /* add new (on current frame) */
- uiItemIntO(layout, IFACE_("Add New (Current Frame)"), ICON_NONE, "POSELIB_OT_pose_add", "frame", CFRA);
+ BLI_assert(ot != NULL);
- /* replace existing - submenu */
- uiItemMenuF(layout, IFACE_("Replace Existing..."), 0, poselib_add_menu_invoke__replacemenu, NULL);
- }
+ /* set the operator execution context correctly */
+ uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
- UI_popup_menu_end(C, pup);
-
- /* this operator is only for a menu, not used further */
- return OPERATOR_INTERFACE;
+ /* add each marker to this menu */
+ for (marker = act->markers.first; marker; marker = marker->next) {
+ PointerRNA props_ptr;
+ uiItemFullO_ptr(
+ layout, ot, marker->name, ICON_ARMATURE_DATA, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
+ RNA_int_set(&props_ptr, "frame", marker->frame);
+ RNA_string_set(&props_ptr, "name", marker->name);
+ }
}
+static int poselib_add_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = get_poselib_object(C);
+ bPose *pose = (ob) ? ob->pose : NULL;
+ uiPopupMenu *pup;
+ uiLayout *layout;
+
+ /* sanity check */
+ if (ELEM(NULL, ob, pose))
+ return OPERATOR_CANCELLED;
+
+ /* start building */
+ pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
+
+ /* add new (adds to the first unoccupied frame) */
+ uiItemIntO(layout,
+ IFACE_("Add New"),
+ ICON_NONE,
+ "POSELIB_OT_pose_add",
+ "frame",
+ poselib_get_free_index(ob->poselib));
+
+ /* check if we have any choices to add a new pose in any other way */
+ if ((ob->poselib) && (ob->poselib->markers.first)) {
+ /* add new (on current frame) */
+ uiItemIntO(layout,
+ IFACE_("Add New (Current Frame)"),
+ ICON_NONE,
+ "POSELIB_OT_pose_add",
+ "frame",
+ CFRA);
+
+ /* replace existing - submenu */
+ uiItemMenuF(
+ layout, IFACE_("Replace Existing..."), 0, poselib_add_menu_invoke__replacemenu, NULL);
+ }
+
+ UI_popup_menu_end(C, pup);
+
+ /* this operator is only for a menu, not used further */
+ return OPERATOR_INTERFACE;
+}
static int poselib_add_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = get_poselib_object(C);
- bAction *act = poselib_validate(bmain, ob);
- bPose *pose = (ob) ? ob->pose : NULL;
- TimeMarker *marker;
- KeyingSet *ks;
- int frame = RNA_int_get(op->ptr, "frame");
- char name[64];
-
- /* sanity check (invoke should have checked this anyway) */
- if (ELEM(NULL, ob, pose))
- return OPERATOR_CANCELLED;
-
- /* get name to give to pose */
- RNA_string_get(op->ptr, "name", name);
-
- /* add pose to poselib - replaces any existing pose there
- * - for the 'replace' option, this should end up finding the appropriate marker,
- * so no new one will be added
- */
- for (marker = act->markers.first; marker; marker = marker->next) {
- if (marker->frame == frame) {
- BLI_strncpy(marker->name, name, sizeof(marker->name));
- break;
- }
- }
- if (marker == NULL) {
- marker = MEM_callocN(sizeof(TimeMarker), "ActionMarker");
-
- BLI_strncpy(marker->name, name, sizeof(marker->name));
- marker->frame = frame;
-
- BLI_addtail(&act->markers, marker);
- }
-
- /* validate name */
- BLI_uniquename(&act->markers, marker, DATA_("Pose"), '.', offsetof(TimeMarker, name), sizeof(marker->name));
-
- /* use Keying Set to determine what to store for the pose */
-
- /* this includes custom props :)*/
- ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_WHOLE_CHARACTER_SELECTED_ID);
-
- ANIM_apply_keyingset(C, NULL, act, ks, MODIFYKEY_MODE_INSERT, (float)frame);
-
- /* store new 'active' pose number */
- act->active_marker = BLI_listbase_count(&act->markers);
- DEG_id_tag_update(&act->id, ID_RECALC_COPY_ON_WRITE);
-
- /* done */
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Object *ob = get_poselib_object(C);
+ bAction *act = poselib_validate(bmain, ob);
+ bPose *pose = (ob) ? ob->pose : NULL;
+ TimeMarker *marker;
+ KeyingSet *ks;
+ int frame = RNA_int_get(op->ptr, "frame");
+ char name[64];
+
+ /* sanity check (invoke should have checked this anyway) */
+ if (ELEM(NULL, ob, pose))
+ return OPERATOR_CANCELLED;
+
+ /* get name to give to pose */
+ RNA_string_get(op->ptr, "name", name);
+
+ /* add pose to poselib - replaces any existing pose there
+ * - for the 'replace' option, this should end up finding the appropriate marker,
+ * so no new one will be added
+ */
+ for (marker = act->markers.first; marker; marker = marker->next) {
+ if (marker->frame == frame) {
+ BLI_strncpy(marker->name, name, sizeof(marker->name));
+ break;
+ }
+ }
+ if (marker == NULL) {
+ marker = MEM_callocN(sizeof(TimeMarker), "ActionMarker");
+
+ BLI_strncpy(marker->name, name, sizeof(marker->name));
+ marker->frame = frame;
+
+ BLI_addtail(&act->markers, marker);
+ }
+
+ /* validate name */
+ BLI_uniquename(
+ &act->markers, marker, DATA_("Pose"), '.', offsetof(TimeMarker, name), sizeof(marker->name));
+
+ /* use Keying Set to determine what to store for the pose */
+
+ /* this includes custom props :)*/
+ ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_WHOLE_CHARACTER_SELECTED_ID);
+
+ ANIM_apply_keyingset(C, NULL, act, ks, MODIFYKEY_MODE_INSERT, (float)frame);
+
+ /* store new 'active' pose number */
+ act->active_marker = BLI_listbase_count(&act->markers);
+ DEG_id_tag_update(&act->id, ID_RECALC_COPY_ON_WRITE);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void POSELIB_OT_pose_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "PoseLib Add Pose";
- ot->idname = "POSELIB_OT_pose_add";
- ot->description = "Add the current Pose to the active Pose Library";
-
- /* api callbacks */
- ot->invoke = poselib_add_menu_invoke;
- ot->exec = poselib_add_exec;
- ot->poll = poselib_add_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_int(ot->srna, "frame", 1, 0, INT_MAX, "Frame", "Frame to store pose on", 0, INT_MAX);
- RNA_def_string(ot->srna, "name", "Pose", 64, "Pose Name", "Name of newly added Pose");
+ /* identifiers */
+ ot->name = "PoseLib Add Pose";
+ ot->idname = "POSELIB_OT_pose_add";
+ ot->description = "Add the current Pose to the active Pose Library";
+
+ /* api callbacks */
+ ot->invoke = poselib_add_menu_invoke;
+ ot->exec = poselib_add_exec;
+ ot->poll = poselib_add_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "frame", 1, 0, INT_MAX, "Frame", "Frame to store pose on", 0, INT_MAX);
+ RNA_def_string(ot->srna, "name", "Pose", 64, "Pose Name", "Name of newly added Pose");
}
/* ----- */
/* can be called with C == NULL */
-static const EnumPropertyItem *poselib_stored_pose_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *poselib_stored_pose_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- Object *ob = get_poselib_object(C);
- bAction *act = (ob) ? ob->poselib : NULL;
- TimeMarker *marker;
- EnumPropertyItem *item = NULL, item_tmp = {0};
- int totitem = 0;
- int i = 0;
-
- if (C == NULL) {
- return DummyRNA_NULL_items;
- }
-
- /* check that the action exists */
- if (act) {
- /* add each marker to the list */
- for (marker = act->markers.first, i = 0; marker; marker = marker->next, i++) {
- item_tmp.identifier = item_tmp.name = marker->name;
- item_tmp.icon = ICON_ARMATURE_DATA;
- item_tmp.value = i;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- }
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ Object *ob = get_poselib_object(C);
+ bAction *act = (ob) ? ob->poselib : NULL;
+ TimeMarker *marker;
+ EnumPropertyItem *item = NULL, item_tmp = {0};
+ int totitem = 0;
+ int i = 0;
+
+ if (C == NULL) {
+ return DummyRNA_NULL_items;
+ }
+
+ /* check that the action exists */
+ if (act) {
+ /* add each marker to the list */
+ for (marker = act->markers.first, i = 0; marker; marker = marker->next, i++) {
+ item_tmp.identifier = item_tmp.name = marker->name;
+ item_tmp.icon = ICON_ARMATURE_DATA;
+ item_tmp.value = i;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
static int poselib_remove_exec(bContext *C, wmOperator *op)
{
- Object *ob = get_poselib_object(C);
- bAction *act = (ob) ? ob->poselib : NULL;
- TimeMarker *marker;
- int marker_index;
- FCurve *fcu;
- PropertyRNA *prop;
-
- /* check if valid poselib */
- if (act == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data");
- return OPERATOR_CANCELLED;
- }
-
- prop = RNA_struct_find_property(op->ptr, "pose");
- if (RNA_property_is_set(op->ptr, prop)) {
- marker_index = RNA_property_enum_get(op->ptr, prop);
- }
- else {
- marker_index = act->active_marker - 1;
- }
-
- /* get index (and pointer) of pose to remove */
- marker = BLI_findlink(&act->markers, marker_index);
- if (marker == NULL) {
- BKE_reportf(op->reports, RPT_ERROR, "Invalid pose specified %d", marker_index);
- return OPERATOR_CANCELLED;
- }
-
- /* remove relevant keyframes */
- for (fcu = act->curves.first; fcu; fcu = fcu->next) {
- BezTriple *bezt;
- unsigned int i;
-
- if (fcu->bezt) {
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- /* check if remove */
- if (IS_EQF(bezt->vec[1][0], (float)marker->frame)) {
- delete_fcurve_key(fcu, i, 1);
- break;
- }
- }
- }
- }
-
- /* remove poselib from list */
- BLI_freelinkN(&act->markers, marker);
-
- /* fix active pose number */
- act->active_marker = 0;
-
- /* send notifiers for this - using keyframe editing notifiers, since action
- * may be being shown in anim editors as active action
- */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- DEG_id_tag_update(&act->id, ID_RECALC_COPY_ON_WRITE);
-
- /* done */
- return OPERATOR_FINISHED;
+ Object *ob = get_poselib_object(C);
+ bAction *act = (ob) ? ob->poselib : NULL;
+ TimeMarker *marker;
+ int marker_index;
+ FCurve *fcu;
+ PropertyRNA *prop;
+
+ /* check if valid poselib */
+ if (act == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data");
+ return OPERATOR_CANCELLED;
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "pose");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ marker_index = RNA_property_enum_get(op->ptr, prop);
+ }
+ else {
+ marker_index = act->active_marker - 1;
+ }
+
+ /* get index (and pointer) of pose to remove */
+ marker = BLI_findlink(&act->markers, marker_index);
+ if (marker == NULL) {
+ BKE_reportf(op->reports, RPT_ERROR, "Invalid pose specified %d", marker_index);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* remove relevant keyframes */
+ for (fcu = act->curves.first; fcu; fcu = fcu->next) {
+ BezTriple *bezt;
+ unsigned int i;
+
+ if (fcu->bezt) {
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ /* check if remove */
+ if (IS_EQF(bezt->vec[1][0], (float)marker->frame)) {
+ delete_fcurve_key(fcu, i, 1);
+ break;
+ }
+ }
+ }
+ }
+
+ /* remove poselib from list */
+ BLI_freelinkN(&act->markers, marker);
+
+ /* fix active pose number */
+ act->active_marker = 0;
+
+ /* send notifiers for this - using keyframe editing notifiers, since action
+ * may be being shown in anim editors as active action
+ */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ DEG_id_tag_update(&act->id, ID_RECALC_COPY_ON_WRITE);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void POSELIB_OT_pose_remove(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "PoseLib Remove Pose";
- ot->idname = "POSELIB_OT_pose_remove";
- ot->description = "Remove nth pose from the active Pose Library";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = poselib_remove_exec;
- ot->poll = has_poselib_pose_data_for_editing_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "pose", DummyRNA_NULL_items, 0, "Pose", "The pose to remove");
- RNA_def_enum_funcs(prop, poselib_stored_pose_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "PoseLib Remove Pose";
+ ot->idname = "POSELIB_OT_pose_remove";
+ ot->description = "Remove nth pose from the active Pose Library";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = poselib_remove_exec;
+ ot->poll = has_poselib_pose_data_for_editing_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna, "pose", DummyRNA_NULL_items, 0, "Pose", "The pose to remove");
+ RNA_def_enum_funcs(prop, poselib_stored_pose_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
static int poselib_rename_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Object *ob = get_poselib_object(C);
- bAction *act = (ob) ? ob->poselib : NULL;
- TimeMarker *marker;
-
- /* check if valid poselib */
- if (act == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data");
- return OPERATOR_CANCELLED;
- }
-
- /* get index (and pointer) of pose to remove */
- marker = BLI_findlink(&act->markers, act->active_marker - 1);
- if (marker == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Invalid index for pose");
- return OPERATOR_CANCELLED;
- }
- else {
- /* use the existing name of the marker as the name, and use the active marker as the one to rename */
- RNA_enum_set(op->ptr, "pose", act->active_marker - 1);
- RNA_string_set(op->ptr, "name", marker->name);
- }
-
- /* part to sync with other similar operators... */
- return WM_operator_props_popup_confirm(C, op, event);
+ Object *ob = get_poselib_object(C);
+ bAction *act = (ob) ? ob->poselib : NULL;
+ TimeMarker *marker;
+
+ /* check if valid poselib */
+ if (act == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get index (and pointer) of pose to remove */
+ marker = BLI_findlink(&act->markers, act->active_marker - 1);
+ if (marker == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Invalid index for pose");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* use the existing name of the marker as the name, and use the active marker as the one to rename */
+ RNA_enum_set(op->ptr, "pose", act->active_marker - 1);
+ RNA_string_set(op->ptr, "name", marker->name);
+ }
+
+ /* part to sync with other similar operators... */
+ return WM_operator_props_popup_confirm(C, op, event);
}
static int poselib_rename_exec(bContext *C, wmOperator *op)
{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bAction *act = (ob) ? ob->poselib : NULL;
- TimeMarker *marker;
- char newname[64];
-
- /* check if valid poselib */
- if (act == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data");
- return OPERATOR_CANCELLED;
- }
-
- /* get index (and pointer) of pose to remove */
- marker = BLI_findlink(&act->markers, RNA_enum_get(op->ptr, "pose"));
- if (marker == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Invalid index for pose");
- return OPERATOR_CANCELLED;
- }
-
- /* get new name */
- RNA_string_get(op->ptr, "name", newname);
-
- /* copy name and validate it */
- BLI_strncpy(marker->name, newname, sizeof(marker->name));
- BLI_uniquename(&act->markers, marker, DATA_("Pose"), '.', offsetof(TimeMarker, name), sizeof(marker->name));
-
- /* send notifiers for this - using keyframe editing notifiers, since action
- * may be being shown in anim editors as active action
- */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ bAction *act = (ob) ? ob->poselib : NULL;
+ TimeMarker *marker;
+ char newname[64];
+
+ /* check if valid poselib */
+ if (act == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get index (and pointer) of pose to remove */
+ marker = BLI_findlink(&act->markers, RNA_enum_get(op->ptr, "pose"));
+ if (marker == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Invalid index for pose");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get new name */
+ RNA_string_get(op->ptr, "name", newname);
+
+ /* copy name and validate it */
+ BLI_strncpy(marker->name, newname, sizeof(marker->name));
+ BLI_uniquename(
+ &act->markers, marker, DATA_("Pose"), '.', offsetof(TimeMarker, name), sizeof(marker->name));
+
+ /* send notifiers for this - using keyframe editing notifiers, since action
+ * may be being shown in anim editors as active action
+ */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void POSELIB_OT_pose_rename(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "PoseLib Rename Pose";
- ot->idname = "POSELIB_OT_pose_rename";
- ot->description = "Rename specified pose from the active Pose Library";
-
- /* api callbacks */
- ot->invoke = poselib_rename_invoke;
- ot->exec = poselib_rename_exec;
- ot->poll = has_poselib_pose_data_for_editing_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- /* NOTE: name not pose is the operator's "main" property,
- * so that it will get activated in the popup for easy renaming */
- ot->prop = RNA_def_string(ot->srna, "name", "RenamedPose", 64, "New Pose Name", "New name for pose");
- prop = RNA_def_enum(ot->srna, "pose", DummyRNA_NULL_items, 0, "Pose", "The pose to rename");
- RNA_def_enum_funcs(prop, poselib_stored_pose_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "PoseLib Rename Pose";
+ ot->idname = "POSELIB_OT_pose_rename";
+ ot->description = "Rename specified pose from the active Pose Library";
+
+ /* api callbacks */
+ ot->invoke = poselib_rename_invoke;
+ ot->exec = poselib_rename_exec;
+ ot->poll = has_poselib_pose_data_for_editing_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ /* NOTE: name not pose is the operator's "main" property,
+ * so that it will get activated in the popup for easy renaming */
+ ot->prop = RNA_def_string(
+ ot->srna, "name", "RenamedPose", 64, "New Pose Name", "New name for pose");
+ prop = RNA_def_enum(ot->srna, "pose", DummyRNA_NULL_items, 0, "Pose", "The pose to rename");
+ RNA_def_enum_funcs(prop, poselib_stored_pose_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
}
static int poselib_move_exec(bContext *C, wmOperator *op)
{
- Object *ob = get_poselib_object(C);
- bAction *act = (ob) ? ob->poselib : NULL;
- TimeMarker *marker;
- int marker_index;
- int dir;
- PropertyRNA *prop;
-
- /* check if valid poselib */
- if (act == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data");
- return OPERATOR_CANCELLED;
- }
-
- prop = RNA_struct_find_property(op->ptr, "pose");
- if (RNA_property_is_set(op->ptr, prop)) {
- marker_index = RNA_property_enum_get(op->ptr, prop);
- }
- else {
- marker_index = act->active_marker - 1;
- }
-
- /* get index (and pointer) of pose to remove */
- marker = BLI_findlink(&act->markers, marker_index);
- if (marker == NULL) {
- BKE_reportf(op->reports, RPT_ERROR, "Invalid pose specified %d", marker_index);
- return OPERATOR_CANCELLED;
- }
-
- dir = RNA_enum_get(op->ptr, "direction");
-
- /* move pose */
- if (BLI_listbase_link_move(&act->markers, marker, dir)) {
- act->active_marker = marker_index + dir + 1;
-
- /* send notifiers for this - using keyframe editing notifiers, since action
- * may be being shown in anim editors as active action
- */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- }
- else {
- return OPERATOR_CANCELLED;
- }
-
- /* done */
- return OPERATOR_FINISHED;
+ Object *ob = get_poselib_object(C);
+ bAction *act = (ob) ? ob->poselib : NULL;
+ TimeMarker *marker;
+ int marker_index;
+ int dir;
+ PropertyRNA *prop;
+
+ /* check if valid poselib */
+ if (act == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data");
+ return OPERATOR_CANCELLED;
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "pose");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ marker_index = RNA_property_enum_get(op->ptr, prop);
+ }
+ else {
+ marker_index = act->active_marker - 1;
+ }
+
+ /* get index (and pointer) of pose to remove */
+ marker = BLI_findlink(&act->markers, marker_index);
+ if (marker == NULL) {
+ BKE_reportf(op->reports, RPT_ERROR, "Invalid pose specified %d", marker_index);
+ return OPERATOR_CANCELLED;
+ }
+
+ dir = RNA_enum_get(op->ptr, "direction");
+
+ /* move pose */
+ if (BLI_listbase_link_move(&act->markers, marker, dir)) {
+ act->active_marker = marker_index + dir + 1;
+
+ /* send notifiers for this - using keyframe editing notifiers, since action
+ * may be being shown in anim editors as active action
+ */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void POSELIB_OT_pose_move(wmOperatorType *ot)
{
- PropertyRNA *prop;
- static const EnumPropertyItem pose_lib_pose_move[] = {
- {-1, "UP", 0, "Up", ""},
- {1, "DOWN", 0, "Down", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "PoseLib Move Pose";
- ot->idname = "POSELIB_OT_pose_move";
- ot->description = "Move the pose up or down in the active Pose Library";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = poselib_move_exec;
- ot->poll = has_poselib_pose_data_for_editing_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "pose", DummyRNA_NULL_items, 0, "Pose", "The pose to move");
- RNA_def_enum_funcs(prop, poselib_stored_pose_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
-
- RNA_def_enum(ot->srna, "direction", pose_lib_pose_move, 0, "Direction",
- "Direction to move the chosen pose towards");
+ PropertyRNA *prop;
+ static const EnumPropertyItem pose_lib_pose_move[] = {
+ {-1, "UP", 0, "Up", ""},
+ {1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "PoseLib Move Pose";
+ ot->idname = "POSELIB_OT_pose_move";
+ ot->description = "Move the pose up or down in the active Pose Library";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = poselib_move_exec;
+ ot->poll = has_poselib_pose_data_for_editing_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna, "pose", DummyRNA_NULL_items, 0, "Pose", "The pose to move");
+ RNA_def_enum_funcs(prop, poselib_stored_pose_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
+
+ RNA_def_enum(ot->srna,
+ "direction",
+ pose_lib_pose_move,
+ 0,
+ "Direction",
+ "Direction to move the chosen pose towards");
}
-
-
/* ************************************************************* */
/* Pose-Lib Browsing/Previewing Operator */
/* Simple struct for storing settings/data for use during PoseLib preview */
typedef struct tPoseLib_PreviewData {
- /** tPoseLib_Backup structs for restoring poses. */
- ListBase backups;
- /** LinkData structs storing list of poses which match the current search-string. */
- ListBase searchp;
-
- /** active scene. */
- Scene *scene;
- /** active area. */
- ScrArea *sa;
-
- /** RNA-Pointer to Object 'ob' .*/
- PointerRNA rna_ptr;
- /** object to work on. */
- Object *ob;
- /** object's armature data. */
- bArmature *arm;
- /** object's pose. */
- bPose *pose;
- /** poselib to use. */
- bAction *act;
- /** 'active' pose. */
- TimeMarker *marker;
-
- /** total number of elements to work on. */
- int totcount;
-
- /** state of main loop. */
- short state;
- /** redraw/update settings during main loop. */
- short redraw;
- /** flags for various settings. */
- short flag;
-
- /** position of cursor in searchstr (cursor occurs before the item at the nominated index) */
- short search_cursor;
- /** (Part of) Name to search for to filter poses that get shown. */
- char searchstr[64];
- /** Previously set searchstr (from last loop run),
- * so that we can detected when to rebuild searchp. */
- char searchold[64];
-
- /** Info-text to print in header. */
- char headerstr[UI_MAX_DRAW_STR];
+ /** tPoseLib_Backup structs for restoring poses. */
+ ListBase backups;
+ /** LinkData structs storing list of poses which match the current search-string. */
+ ListBase searchp;
+
+ /** active scene. */
+ Scene *scene;
+ /** active area. */
+ ScrArea *sa;
+
+ /** RNA-Pointer to Object 'ob' .*/
+ PointerRNA rna_ptr;
+ /** object to work on. */
+ Object *ob;
+ /** object's armature data. */
+ bArmature *arm;
+ /** object's pose. */
+ bPose *pose;
+ /** poselib to use. */
+ bAction *act;
+ /** 'active' pose. */
+ TimeMarker *marker;
+
+ /** total number of elements to work on. */
+ int totcount;
+
+ /** state of main loop. */
+ short state;
+ /** redraw/update settings during main loop. */
+ short redraw;
+ /** flags for various settings. */
+ short flag;
+
+ /** position of cursor in searchstr (cursor occurs before the item at the nominated index) */
+ short search_cursor;
+ /** (Part of) Name to search for to filter poses that get shown. */
+ char searchstr[64];
+ /** Previously set searchstr (from last loop run),
+ * so that we can detected when to rebuild searchp. */
+ char searchold[64];
+
+ /** Info-text to print in header. */
+ char headerstr[UI_MAX_DRAW_STR];
} tPoseLib_PreviewData;
/* defines for tPoseLib_PreviewData->state values */
enum {
- PL_PREVIEW_ERROR = -1,
- PL_PREVIEW_RUNNING,
- PL_PREVIEW_CONFIRM,
- PL_PREVIEW_CANCEL,
- PL_PREVIEW_RUNONCE,
+ PL_PREVIEW_ERROR = -1,
+ PL_PREVIEW_RUNNING,
+ PL_PREVIEW_CONFIRM,
+ PL_PREVIEW_CANCEL,
+ PL_PREVIEW_RUNONCE,
};
/* defines for tPoseLib_PreviewData->redraw values */
enum {
- PL_PREVIEW_NOREDRAW = 0,
- PL_PREVIEW_REDRAWALL,
- PL_PREVIEW_REDRAWHEADER,
+ PL_PREVIEW_NOREDRAW = 0,
+ PL_PREVIEW_REDRAWALL,
+ PL_PREVIEW_REDRAWHEADER,
};
/* defines for tPoseLib_PreviewData->flag values */
enum {
- PL_PREVIEW_FIRSTTIME = (1 << 0),
- PL_PREVIEW_SHOWORIGINAL = (1 << 1),
- PL_PREVIEW_ANY_BONE_SELECTED = (1 << 2),
+ PL_PREVIEW_FIRSTTIME = (1 << 0),
+ PL_PREVIEW_SHOWORIGINAL = (1 << 1),
+ PL_PREVIEW_ANY_BONE_SELECTED = (1 << 2),
};
/* ---------------------------- */
/* simple struct for storing backup info */
typedef struct tPoseLib_Backup {
- struct tPoseLib_Backup *next, *prev;
+ struct tPoseLib_Backup *next, *prev;
- bPoseChannel *pchan; /* pose channel backups are for */
+ bPoseChannel *pchan; /* pose channel backups are for */
- bPoseChannel olddata; /* copy of pose channel's old data (at start) */
- IDProperty *oldprops; /* copy (needs freeing) of pose channel's properties (at start) */
+ bPoseChannel olddata; /* copy of pose channel's old data (at start) */
+ IDProperty *oldprops; /* copy (needs freeing) of pose channel's properties (at start) */
} tPoseLib_Backup;
/* Makes a copy of the current pose for restoration purposes - doesn't do constraints currently */
static void poselib_backup_posecopy(tPoseLib_PreviewData *pld)
{
- bActionGroup *agrp;
- bPoseChannel *pchan;
- bool selected = false;
-
- /* determine whether any bone is selected. */
- LISTBASE_FOREACH (bPoseChannel *, bchan, &pld->pose->chanbase) {
- selected = bchan->bone != NULL && bchan->bone->flag & BONE_SELECTED;
- if (selected) {
- pld->flag |= PL_PREVIEW_ANY_BONE_SELECTED;
- break;
- }
- }
- if (!selected) {
- pld->flag &= ~PL_PREVIEW_ANY_BONE_SELECTED;
- }
-
- /* for each posechannel that has an actionchannel in */
- for (agrp = pld->act->groups.first; agrp; agrp = agrp->next) {
- /* try to find posechannel */
- pchan = BKE_pose_channel_find_name(pld->pose, agrp->name);
-
- /* backup data if available */
- if (pchan) {
- tPoseLib_Backup *plb;
-
- /* store backup */
- plb = MEM_callocN(sizeof(tPoseLib_Backup), "tPoseLib_Backup");
-
- plb->pchan = pchan;
- memcpy(&plb->olddata, plb->pchan, sizeof(bPoseChannel));
-
- if (pchan->prop)
- plb->oldprops = IDP_CopyProperty(pchan->prop);
-
- BLI_addtail(&pld->backups, plb);
-
- /* mark as being affected */
- pld->totcount++;
- }
- }
+ bActionGroup *agrp;
+ bPoseChannel *pchan;
+ bool selected = false;
+
+ /* determine whether any bone is selected. */
+ LISTBASE_FOREACH (bPoseChannel *, bchan, &pld->pose->chanbase) {
+ selected = bchan->bone != NULL && bchan->bone->flag & BONE_SELECTED;
+ if (selected) {
+ pld->flag |= PL_PREVIEW_ANY_BONE_SELECTED;
+ break;
+ }
+ }
+ if (!selected) {
+ pld->flag &= ~PL_PREVIEW_ANY_BONE_SELECTED;
+ }
+
+ /* for each posechannel that has an actionchannel in */
+ for (agrp = pld->act->groups.first; agrp; agrp = agrp->next) {
+ /* try to find posechannel */
+ pchan = BKE_pose_channel_find_name(pld->pose, agrp->name);
+
+ /* backup data if available */
+ if (pchan) {
+ tPoseLib_Backup *plb;
+
+ /* store backup */
+ plb = MEM_callocN(sizeof(tPoseLib_Backup), "tPoseLib_Backup");
+
+ plb->pchan = pchan;
+ memcpy(&plb->olddata, plb->pchan, sizeof(bPoseChannel));
+
+ if (pchan->prop)
+ plb->oldprops = IDP_CopyProperty(pchan->prop);
+
+ BLI_addtail(&pld->backups, plb);
+
+ /* mark as being affected */
+ pld->totcount++;
+ }
+ }
}
/* Restores original pose */
static void poselib_backup_restore(tPoseLib_PreviewData *pld)
{
- tPoseLib_Backup *plb;
+ tPoseLib_Backup *plb;
- for (plb = pld->backups.first; plb; plb = plb->next) {
- /* copy most of data straight back */
- memcpy(plb->pchan, &plb->olddata, sizeof(bPoseChannel));
+ for (plb = pld->backups.first; plb; plb = plb->next) {
+ /* copy most of data straight back */
+ memcpy(plb->pchan, &plb->olddata, sizeof(bPoseChannel));
- /* just overwrite values of properties from the stored copies (there should be some) */
- if (plb->oldprops)
- IDP_SyncGroupValues(plb->pchan->prop, plb->oldprops);
+ /* just overwrite values of properties from the stored copies (there should be some) */
+ if (plb->oldprops)
+ IDP_SyncGroupValues(plb->pchan->prop, plb->oldprops);
- /* TODO: constraints settings aren't restored yet,
- * even though these could change (though not that likely) */
- }
+ /* TODO: constraints settings aren't restored yet,
+ * even though these could change (though not that likely) */
+ }
}
/* Free list of backups, including any side data it may use */
static void poselib_backup_free_data(tPoseLib_PreviewData *pld)
{
- tPoseLib_Backup *plb, *plbn;
+ tPoseLib_Backup *plb, *plbn;
- for (plb = pld->backups.first; plb; plb = plbn) {
- plbn = plb->next;
+ for (plb = pld->backups.first; plb; plb = plbn) {
+ plbn = plb->next;
- /* free custom data */
- if (plb->oldprops) {
- IDP_FreeProperty(plb->oldprops);
- MEM_freeN(plb->oldprops);
- }
+ /* free custom data */
+ if (plb->oldprops) {
+ IDP_FreeProperty(plb->oldprops);
+ MEM_freeN(plb->oldprops);
+ }
- /* free backup element now */
- BLI_freelinkN(&pld->backups, plb);
- }
+ /* free backup element now */
+ BLI_freelinkN(&pld->backups, plb);
+ }
}
/* ---------------------------- */
@@ -993,186 +1011,187 @@ static void poselib_backup_free_data(tPoseLib_PreviewData *pld)
*/
static void poselib_apply_pose(tPoseLib_PreviewData *pld)
{
- PointerRNA *ptr = &pld->rna_ptr;
- bArmature *arm = pld->arm;
- bPose *pose = pld->pose;
- bPoseChannel *pchan;
- bAction *act = pld->act;
- bActionGroup *agrp;
-
- KeyframeEditData ked = {{NULL}};
- KeyframeEditFunc group_ok_cb;
- int frame = 1;
- const bool any_bone_selected = pld->flag & PL_PREVIEW_ANY_BONE_SELECTED;
-
- /* get the frame */
- if (pld->marker)
- frame = pld->marker->frame;
- else
- return;
-
-
- /* init settings for testing groups for keyframes */
- group_ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
- ked.f1 = ((float)frame) - 0.5f;
- ked.f2 = ((float)frame) + 0.5f;
-
- /* start applying - only those channels which have a key at this point in time! */
- for (agrp = act->groups.first; agrp; agrp = agrp->next) {
- /* check if group has any keyframes */
- if (ANIM_animchanneldata_keyframes_loop(&ked, NULL, agrp, ALE_GROUP, NULL, group_ok_cb, NULL)) {
- /* has keyframe on this frame, so try to get a PoseChannel with this name */
- pchan = BKE_pose_channel_find_name(pose, agrp->name);
-
- if (pchan) {
- bool ok = 0;
-
- /* check if this bone should get any animation applied */
- if (!any_bone_selected) {
- /* if no bones are selected, then any bone is ok */
- ok = 1;
- }
- else if (pchan->bone) {
- /* only ok if bone is visible and selected */
- if ((pchan->bone->flag & BONE_SELECTED) &&
- (pchan->bone->flag & BONE_HIDDEN_P) == 0 &&
- (pchan->bone->layer & arm->layer))
- {
- ok = 1;
- }
- }
-
- if (ok)
- animsys_evaluate_action_group(ptr, act, agrp, (float)frame);
- }
- }
- }
+ PointerRNA *ptr = &pld->rna_ptr;
+ bArmature *arm = pld->arm;
+ bPose *pose = pld->pose;
+ bPoseChannel *pchan;
+ bAction *act = pld->act;
+ bActionGroup *agrp;
+
+ KeyframeEditData ked = {{NULL}};
+ KeyframeEditFunc group_ok_cb;
+ int frame = 1;
+ const bool any_bone_selected = pld->flag & PL_PREVIEW_ANY_BONE_SELECTED;
+
+ /* get the frame */
+ if (pld->marker)
+ frame = pld->marker->frame;
+ else
+ return;
+
+ /* init settings for testing groups for keyframes */
+ group_ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
+ ked.f1 = ((float)frame) - 0.5f;
+ ked.f2 = ((float)frame) + 0.5f;
+
+ /* start applying - only those channels which have a key at this point in time! */
+ for (agrp = act->groups.first; agrp; agrp = agrp->next) {
+ /* check if group has any keyframes */
+ if (ANIM_animchanneldata_keyframes_loop(
+ &ked, NULL, agrp, ALE_GROUP, NULL, group_ok_cb, NULL)) {
+ /* has keyframe on this frame, so try to get a PoseChannel with this name */
+ pchan = BKE_pose_channel_find_name(pose, agrp->name);
+
+ if (pchan) {
+ bool ok = 0;
+
+ /* check if this bone should get any animation applied */
+ if (!any_bone_selected) {
+ /* if no bones are selected, then any bone is ok */
+ ok = 1;
+ }
+ else if (pchan->bone) {
+ /* only ok if bone is visible and selected */
+ if ((pchan->bone->flag & BONE_SELECTED) && (pchan->bone->flag & BONE_HIDDEN_P) == 0 &&
+ (pchan->bone->layer & arm->layer)) {
+ ok = 1;
+ }
+ }
+
+ if (ok)
+ animsys_evaluate_action_group(ptr, act, agrp, (float)frame);
+ }
+ }
+ }
}
/* Auto-keys/tags bones affected by the pose used from the poselib */
static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData *pld)
{
- bPose *pose = pld->pose;
- bPoseChannel *pchan;
- bAction *act = pld->act;
- bActionGroup *agrp;
-
- KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
- ListBase dsources = {NULL, NULL};
- bool autokey = autokeyframe_cfra_can_key(scene, &pld->ob->id);
- const bool any_bone_selected = pld->flag & PL_PREVIEW_ANY_BONE_SELECTED;
-
- /* start tagging/keying */
- for (agrp = act->groups.first; agrp; agrp = agrp->next) {
- /* only for selected bones unless there aren't any selected, in which case all are included */
- pchan = BKE_pose_channel_find_name(pose, agrp->name);
-
- if (pchan) {
- if (!any_bone_selected || ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))) {
- if (autokey) {
- /* add datasource override for the PoseChannel, to be used later */
- ANIM_relative_keyingset_add_source(&dsources, &pld->ob->id, &RNA_PoseBone, pchan);
-
- /* clear any unkeyed tags */
- if (pchan->bone)
- pchan->bone->flag &= ~BONE_UNKEYED;
- }
- else {
- /* add unkeyed tags */
- if (pchan->bone)
- pchan->bone->flag |= BONE_UNKEYED;
- }
- }
- }
- }
-
- /* perform actual auto-keying now */
- if (autokey) {
- /* insert keyframes for all relevant bones in one go */
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
- BLI_freelistN(&dsources);
- }
-
- /* send notifiers for this */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ bPose *pose = pld->pose;
+ bPoseChannel *pchan;
+ bAction *act = pld->act;
+ bActionGroup *agrp;
+
+ KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
+ ListBase dsources = {NULL, NULL};
+ bool autokey = autokeyframe_cfra_can_key(scene, &pld->ob->id);
+ const bool any_bone_selected = pld->flag & PL_PREVIEW_ANY_BONE_SELECTED;
+
+ /* start tagging/keying */
+ for (agrp = act->groups.first; agrp; agrp = agrp->next) {
+ /* only for selected bones unless there aren't any selected, in which case all are included */
+ pchan = BKE_pose_channel_find_name(pose, agrp->name);
+
+ if (pchan) {
+ if (!any_bone_selected || ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))) {
+ if (autokey) {
+ /* add datasource override for the PoseChannel, to be used later */
+ ANIM_relative_keyingset_add_source(&dsources, &pld->ob->id, &RNA_PoseBone, pchan);
+
+ /* clear any unkeyed tags */
+ if (pchan->bone)
+ pchan->bone->flag &= ~BONE_UNKEYED;
+ }
+ else {
+ /* add unkeyed tags */
+ if (pchan->bone)
+ pchan->bone->flag |= BONE_UNKEYED;
+ }
+ }
+ }
+ }
+
+ /* perform actual auto-keying now */
+ if (autokey) {
+ /* insert keyframes for all relevant bones in one go */
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ BLI_freelistN(&dsources);
+ }
+
+ /* send notifiers for this */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
}
/* Apply the relevant changes to the pose */
static void poselib_preview_apply(bContext *C, wmOperator *op)
{
- tPoseLib_PreviewData *pld = (tPoseLib_PreviewData *)op->customdata;
-
- /* only recalc pose (and its dependencies) if pose has changed */
- if (pld->redraw == PL_PREVIEW_REDRAWALL) {
- /* don't clear pose if firsttime */
- if ((pld->flag & PL_PREVIEW_FIRSTTIME) == 0)
- poselib_backup_restore(pld);
- else
- pld->flag &= ~PL_PREVIEW_FIRSTTIME;
-
- /* pose should be the right one to draw (unless we're temporarily not showing it) */
- if ((pld->flag & PL_PREVIEW_SHOWORIGINAL) == 0) {
- RNA_int_set(op->ptr, "pose_index", BLI_findindex(&pld->act->markers, pld->marker));
- poselib_apply_pose(pld);
- }
- else
- RNA_int_set(op->ptr, "pose_index", -2); /* -2 means don't apply any pose */
-
- /* old optimize trick... this enforces to bypass the depsgraph
- * - note: code copied from transform_generics.c -> recalcData()
- */
- // FIXME: shouldn't this use the builtin stuff?
- if ((pld->arm->flag & ARM_DELAYDEFORM) == 0)
- DEG_id_tag_update(&pld->ob->id, ID_RECALC_GEOMETRY); /* sets recalc flags */
- else
- BKE_pose_where_is(CTX_data_depsgraph(C), pld->scene, pld->ob);
- }
-
- /* do header print - if interactively previewing */
- if (pld->state == PL_PREVIEW_RUNNING) {
- if (pld->flag & PL_PREVIEW_SHOWORIGINAL) {
- ED_area_status_text(pld->sa, IFACE_("PoseLib Previewing Pose: [Showing Original Pose]"));
- ED_workspace_status_text(C, IFACE_("Use Tab to start previewing poses again"));
- }
- else if (pld->searchstr[0]) {
- char tempstr[65];
- char markern[64];
- short index;
-
- /* get search-string */
- index = pld->search_cursor;
-
- if (index >= 0 && index < sizeof(tempstr) - 1) {
- memcpy(&tempstr[0], &pld->searchstr[0], index);
- tempstr[index] = '|';
- memcpy(&tempstr[index + 1], &pld->searchstr[index], (sizeof(tempstr) - 1) - index);
- }
- else {
- BLI_strncpy(tempstr, pld->searchstr, sizeof(tempstr));
- }
-
- /* get marker name */
- BLI_strncpy(markern, pld->marker ? pld->marker->name : "No Matches", sizeof(markern));
-
- BLI_snprintf(pld->headerstr, sizeof(pld->headerstr),
- IFACE_("PoseLib Previewing Pose: Filter - [%s] | "
- "Current Pose - \"%s\""),
- tempstr, markern);
- ED_area_status_text(pld->sa, pld->headerstr);
- ED_workspace_status_text(C, IFACE_("Use ScrollWheel or PageUp/Down to change pose"));
- }
- else {
- BLI_snprintf(pld->headerstr, sizeof(pld->headerstr),
- IFACE_("PoseLib Previewing Pose: \"%s\""),
- pld->marker->name);
- ED_area_status_text(pld->sa, pld->headerstr);
- ED_workspace_status_text(C, NULL);
- }
- }
-
- /* request drawing of view + clear redraw flag */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, pld->ob);
- pld->redraw = PL_PREVIEW_NOREDRAW;
+ tPoseLib_PreviewData *pld = (tPoseLib_PreviewData *)op->customdata;
+
+ /* only recalc pose (and its dependencies) if pose has changed */
+ if (pld->redraw == PL_PREVIEW_REDRAWALL) {
+ /* don't clear pose if firsttime */
+ if ((pld->flag & PL_PREVIEW_FIRSTTIME) == 0)
+ poselib_backup_restore(pld);
+ else
+ pld->flag &= ~PL_PREVIEW_FIRSTTIME;
+
+ /* pose should be the right one to draw (unless we're temporarily not showing it) */
+ if ((pld->flag & PL_PREVIEW_SHOWORIGINAL) == 0) {
+ RNA_int_set(op->ptr, "pose_index", BLI_findindex(&pld->act->markers, pld->marker));
+ poselib_apply_pose(pld);
+ }
+ else
+ RNA_int_set(op->ptr, "pose_index", -2); /* -2 means don't apply any pose */
+
+ /* old optimize trick... this enforces to bypass the depsgraph
+ * - note: code copied from transform_generics.c -> recalcData()
+ */
+ // FIXME: shouldn't this use the builtin stuff?
+ if ((pld->arm->flag & ARM_DELAYDEFORM) == 0)
+ DEG_id_tag_update(&pld->ob->id, ID_RECALC_GEOMETRY); /* sets recalc flags */
+ else
+ BKE_pose_where_is(CTX_data_depsgraph(C), pld->scene, pld->ob);
+ }
+
+ /* do header print - if interactively previewing */
+ if (pld->state == PL_PREVIEW_RUNNING) {
+ if (pld->flag & PL_PREVIEW_SHOWORIGINAL) {
+ ED_area_status_text(pld->sa, IFACE_("PoseLib Previewing Pose: [Showing Original Pose]"));
+ ED_workspace_status_text(C, IFACE_("Use Tab to start previewing poses again"));
+ }
+ else if (pld->searchstr[0]) {
+ char tempstr[65];
+ char markern[64];
+ short index;
+
+ /* get search-string */
+ index = pld->search_cursor;
+
+ if (index >= 0 && index < sizeof(tempstr) - 1) {
+ memcpy(&tempstr[0], &pld->searchstr[0], index);
+ tempstr[index] = '|';
+ memcpy(&tempstr[index + 1], &pld->searchstr[index], (sizeof(tempstr) - 1) - index);
+ }
+ else {
+ BLI_strncpy(tempstr, pld->searchstr, sizeof(tempstr));
+ }
+
+ /* get marker name */
+ BLI_strncpy(markern, pld->marker ? pld->marker->name : "No Matches", sizeof(markern));
+
+ BLI_snprintf(pld->headerstr,
+ sizeof(pld->headerstr),
+ IFACE_("PoseLib Previewing Pose: Filter - [%s] | "
+ "Current Pose - \"%s\""),
+ tempstr,
+ markern);
+ ED_area_status_text(pld->sa, pld->headerstr);
+ ED_workspace_status_text(C, IFACE_("Use ScrollWheel or PageUp/Down to change pose"));
+ }
+ else {
+ BLI_snprintf(pld->headerstr,
+ sizeof(pld->headerstr),
+ IFACE_("PoseLib Previewing Pose: \"%s\""),
+ pld->marker->name);
+ ED_area_status_text(pld->sa, pld->headerstr);
+ ED_workspace_status_text(C, NULL);
+ }
+ }
+
+ /* request drawing of view + clear redraw flag */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, pld->ob);
+ pld->redraw = PL_PREVIEW_NOREDRAW;
}
/* ---------------------------- */
@@ -1182,351 +1201,373 @@ static void poselib_preview_apply(bContext *C, wmOperator *op)
*/
static void poselib_preview_get_next(tPoseLib_PreviewData *pld, int step)
{
- /* stop if not going anywhere, as we assume that there is a direction to move in */
- if (step == 0)
- return;
-
- /* search-string dictates a special approach */
- if (pld->searchstr[0]) {
- TimeMarker *marker;
- LinkData *ld, *ldn, *ldc;
-
- /* free and rebuild if needed (i.e. if search-str changed) */
- if (!STREQ(pld->searchstr, pld->searchold)) {
- /* free list of temporary search matches */
- BLI_freelistN(&pld->searchp);
-
- /* generate a new list of search matches */
- for (marker = pld->act->markers.first; marker; marker = marker->next) {
- /* does the name partially match?
- * - don't worry about case, to make it easier for users to quickly input a name (or
- * part of one), which is the whole point of this feature
- */
- if (BLI_strcasestr(marker->name, pld->searchstr)) {
- /* make link-data to store reference to it */
- ld = MEM_callocN(sizeof(LinkData), "PoseMatch");
- ld->data = marker;
- BLI_addtail(&pld->searchp, ld);
- }
- }
-
- /* set current marker to NULL (so that we start from first) */
- pld->marker = NULL;
- }
-
- /* check if any matches */
- if (BLI_listbase_is_empty(&pld->searchp)) {
- pld->marker = NULL;
- return;
- }
-
- /* find first match */
- for (ldc = pld->searchp.first; ldc; ldc = ldc->next) {
- if (ldc->data == pld->marker)
- break;
- }
- if (ldc == NULL)
- ldc = pld->searchp.first;
-
- /* Loop through the matches in a cyclic fashion, incrementing/decrementing step as appropriate
- * until step == 0. At this point, marker should be the correct marker.
- */
- if (step > 0) {
- for (ld = ldc; ld && step; ld = ldn, step--)
- ldn = (ld->next) ? ld->next : pld->searchp.first;
- }
- else {
- for (ld = ldc; ld && step; ld = ldn, step++)
- ldn = (ld->prev) ? ld->prev : pld->searchp.last;
- }
-
- /* set marker */
- if (ld)
- pld->marker = ld->data;
- }
- else {
- TimeMarker *marker, *next;
-
- /* if no marker, because we just ended searching, then set that to the start of the list */
- if (pld->marker == NULL)
- pld->marker = pld->act->markers.first;
-
- /* Loop through the markers in a cyclic fashion, incrementing/decrementing step as appropriate
- * until step == 0. At this point, marker should be the correct marker.
- */
- if (step > 0) {
- for (marker = pld->marker; marker && step; marker = next, step--)
- next = (marker->next) ? marker->next : pld->act->markers.first;
- }
- else {
- for (marker = pld->marker; marker && step; marker = next, step++)
- next = (marker->prev) ? marker->prev : pld->act->markers.last;
- }
-
- /* it should be fairly impossible for marker to be NULL */
- if (marker)
- pld->marker = marker;
- }
+ /* stop if not going anywhere, as we assume that there is a direction to move in */
+ if (step == 0)
+ return;
+
+ /* search-string dictates a special approach */
+ if (pld->searchstr[0]) {
+ TimeMarker *marker;
+ LinkData *ld, *ldn, *ldc;
+
+ /* free and rebuild if needed (i.e. if search-str changed) */
+ if (!STREQ(pld->searchstr, pld->searchold)) {
+ /* free list of temporary search matches */
+ BLI_freelistN(&pld->searchp);
+
+ /* generate a new list of search matches */
+ for (marker = pld->act->markers.first; marker; marker = marker->next) {
+ /* does the name partially match?
+ * - don't worry about case, to make it easier for users to quickly input a name (or
+ * part of one), which is the whole point of this feature
+ */
+ if (BLI_strcasestr(marker->name, pld->searchstr)) {
+ /* make link-data to store reference to it */
+ ld = MEM_callocN(sizeof(LinkData), "PoseMatch");
+ ld->data = marker;
+ BLI_addtail(&pld->searchp, ld);
+ }
+ }
+
+ /* set current marker to NULL (so that we start from first) */
+ pld->marker = NULL;
+ }
+
+ /* check if any matches */
+ if (BLI_listbase_is_empty(&pld->searchp)) {
+ pld->marker = NULL;
+ return;
+ }
+
+ /* find first match */
+ for (ldc = pld->searchp.first; ldc; ldc = ldc->next) {
+ if (ldc->data == pld->marker)
+ break;
+ }
+ if (ldc == NULL)
+ ldc = pld->searchp.first;
+
+ /* Loop through the matches in a cyclic fashion, incrementing/decrementing step as appropriate
+ * until step == 0. At this point, marker should be the correct marker.
+ */
+ if (step > 0) {
+ for (ld = ldc; ld && step; ld = ldn, step--)
+ ldn = (ld->next) ? ld->next : pld->searchp.first;
+ }
+ else {
+ for (ld = ldc; ld && step; ld = ldn, step++)
+ ldn = (ld->prev) ? ld->prev : pld->searchp.last;
+ }
+
+ /* set marker */
+ if (ld)
+ pld->marker = ld->data;
+ }
+ else {
+ TimeMarker *marker, *next;
+
+ /* if no marker, because we just ended searching, then set that to the start of the list */
+ if (pld->marker == NULL)
+ pld->marker = pld->act->markers.first;
+
+ /* Loop through the markers in a cyclic fashion, incrementing/decrementing step as appropriate
+ * until step == 0. At this point, marker should be the correct marker.
+ */
+ if (step > 0) {
+ for (marker = pld->marker; marker && step; marker = next, step--)
+ next = (marker->next) ? marker->next : pld->act->markers.first;
+ }
+ else {
+ for (marker = pld->marker; marker && step; marker = next, step++)
+ next = (marker->prev) ? marker->prev : pld->act->markers.last;
+ }
+
+ /* it should be fairly impossible for marker to be NULL */
+ if (marker)
+ pld->marker = marker;
+ }
}
/* 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,
+ unsigned short event,
+ char ascii)
{
- /* try doing some form of string manipulation first */
- switch (event) {
- case BACKSPACEKEY:
- if (pld->searchstr[0] && pld->search_cursor) {
- short len = strlen(pld->searchstr);
- short index = pld->search_cursor;
- short i;
-
- for (i = index; i <= len; i++)
- pld->searchstr[i - 1] = pld->searchstr[i];
-
- pld->search_cursor--;
-
- poselib_preview_get_next(pld, 1);
- pld->redraw = PL_PREVIEW_REDRAWALL;
- return;
- }
- break;
-
- case DELKEY:
- if (pld->searchstr[0] && pld->searchstr[1]) {
- short len = strlen(pld->searchstr);
- short index = pld->search_cursor;
- int i;
-
- if (index < len) {
- for (i = index; i < len; i++)
- pld->searchstr[i] = pld->searchstr[i + 1];
-
- poselib_preview_get_next(pld, 1);
- pld->redraw = PL_PREVIEW_REDRAWALL;
- return;
- }
- }
- break;
- }
-
- if (ascii) {
- /* character to add to the string */
- short index = pld->search_cursor;
- short len = (pld->searchstr[0]) ? strlen(pld->searchstr) : 0;
- short i;
-
- if (len) {
- for (i = len; i > index; i--)
- pld->searchstr[i] = pld->searchstr[i - 1];
- }
- else
- pld->searchstr[1] = 0;
-
- pld->searchstr[index] = ascii;
- pld->search_cursor++;
-
- poselib_preview_get_next(pld, 1);
- pld->redraw = PL_PREVIEW_REDRAWALL;
- }
+ /* try doing some form of string manipulation first */
+ switch (event) {
+ case BACKSPACEKEY:
+ if (pld->searchstr[0] && pld->search_cursor) {
+ short len = strlen(pld->searchstr);
+ short index = pld->search_cursor;
+ short i;
+
+ for (i = index; i <= len; i++)
+ pld->searchstr[i - 1] = pld->searchstr[i];
+
+ pld->search_cursor--;
+
+ poselib_preview_get_next(pld, 1);
+ pld->redraw = PL_PREVIEW_REDRAWALL;
+ return;
+ }
+ break;
+
+ case DELKEY:
+ if (pld->searchstr[0] && pld->searchstr[1]) {
+ short len = strlen(pld->searchstr);
+ short index = pld->search_cursor;
+ int i;
+
+ if (index < len) {
+ for (i = index; i < len; i++)
+ pld->searchstr[i] = pld->searchstr[i + 1];
+
+ poselib_preview_get_next(pld, 1);
+ pld->redraw = PL_PREVIEW_REDRAWALL;
+ return;
+ }
+ }
+ break;
+ }
+
+ if (ascii) {
+ /* character to add to the string */
+ short index = pld->search_cursor;
+ short len = (pld->searchstr[0]) ? strlen(pld->searchstr) : 0;
+ short i;
+
+ if (len) {
+ for (i = len; i > index; i--)
+ pld->searchstr[i] = pld->searchstr[i - 1];
+ }
+ else
+ pld->searchstr[1] = 0;
+
+ pld->searchstr[index] = ascii;
+ pld->search_cursor++;
+
+ poselib_preview_get_next(pld, 1);
+ pld->redraw = PL_PREVIEW_REDRAWALL;
+ }
}
/* handle events for poselib_preview_poses */
static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, const wmEvent *event)
{
- tPoseLib_PreviewData *pld = op->customdata;
- int ret = OPERATOR_RUNNING_MODAL;
-
- /* only accept 'press' event, and ignore 'release', so that we don't get double actions */
- if (ELEM(event->val, KM_PRESS, KM_NOTHING) == 0) {
- //printf("PoseLib: skipping event with type '%s' and val %d\n", WM_key_event_string(event->type, false), event->val);
- return ret;
- }
-
- /* backup stuff that needs to occur before every operation
- * - make a copy of searchstr, so that we know if cache needs to be rebuilt
- */
- BLI_strncpy(pld->searchold, pld->searchstr, sizeof(pld->searchold));
-
- /* if we're currently showing the original pose, only certain events are handled */
- if (pld->flag & PL_PREVIEW_SHOWORIGINAL) {
- switch (event->type) {
- /* exit - cancel */
- case ESCKEY:
- case RIGHTMOUSE:
- pld->state = PL_PREVIEW_CANCEL;
- break;
-
- /* exit - confirm */
- case LEFTMOUSE:
- case RETKEY:
- case PADENTER:
- case SPACEKEY:
- pld->state = PL_PREVIEW_CONFIRM;
- break;
-
- /* view manipulation */
- /* 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 MIDDLEMOUSE: case MOUSEMOVE:
- //pld->redraw = PL_PREVIEW_REDRAWHEADER;
- ret = OPERATOR_PASS_THROUGH;
- break;
-
- /* quicky compare to original */
- case TABKEY:
- pld->flag &= ~PL_PREVIEW_SHOWORIGINAL;
- pld->redraw = PL_PREVIEW_REDRAWALL;
- break;
- }
-
- /* EXITS HERE... */
- return ret;
- }
-
- /* NORMAL EVENT HANDLING... */
- /* searching takes priority over normal activity */
- switch (event->type) {
- /* exit - cancel */
- case ESCKEY:
- case RIGHTMOUSE:
- pld->state = PL_PREVIEW_CANCEL;
- break;
-
- /* exit - confirm */
- case LEFTMOUSE:
- case RETKEY:
- case PADENTER:
- case SPACEKEY:
- pld->state = PL_PREVIEW_CONFIRM;
- break;
-
- /* toggle between original pose and poselib pose*/
- case TABKEY:
- pld->flag |= PL_PREVIEW_SHOWORIGINAL;
- pld->redraw = PL_PREVIEW_REDRAWALL;
- break;
-
- /* change to previous pose (cyclic) */
- case PAGEUPKEY:
- case WHEELUPMOUSE:
- poselib_preview_get_next(pld, -1);
- pld->redraw = PL_PREVIEW_REDRAWALL;
- break;
-
- /* change to next pose (cyclic) */
- case PAGEDOWNKEY:
- case WHEELDOWNMOUSE:
- poselib_preview_get_next(pld, 1);
- pld->redraw = PL_PREVIEW_REDRAWALL;
- break;
-
- /* jump 5 poses (cyclic, back) */
- case DOWNARROWKEY:
- poselib_preview_get_next(pld, -5);
- pld->redraw = PL_PREVIEW_REDRAWALL;
- break;
-
- /* jump 5 poses (cyclic, forward) */
- case UPARROWKEY:
- poselib_preview_get_next(pld, 5);
- pld->redraw = PL_PREVIEW_REDRAWALL;
- break;
-
- /* change to next pose or searching cursor control */
- case RIGHTARROWKEY:
- if (pld->searchstr[0]) {
- /* move text-cursor to the right */
- if (pld->search_cursor < strlen(pld->searchstr))
- pld->search_cursor++;
- pld->redraw = PL_PREVIEW_REDRAWHEADER;
- }
- else {
- /* change to next pose (cyclic) */
- poselib_preview_get_next(pld, 1);
- pld->redraw = PL_PREVIEW_REDRAWALL;
- }
- break;
-
- /* change to next pose or searching cursor control */
- case LEFTARROWKEY:
- if (pld->searchstr[0]) {
- /* move text-cursor to the left */
- if (pld->search_cursor)
- pld->search_cursor--;
- pld->redraw = PL_PREVIEW_REDRAWHEADER;
- }
- else {
- /* change to previous pose (cyclic) */
- poselib_preview_get_next(pld, -1);
- pld->redraw = PL_PREVIEW_REDRAWALL;
- }
- break;
-
- /* change to first pose or start of searching string */
- case HOMEKEY:
- if (pld->searchstr[0]) {
- pld->search_cursor = 0;
- pld->redraw = PL_PREVIEW_REDRAWHEADER;
- }
- else {
- /* change to first pose */
- pld->marker = pld->act->markers.first;
- pld->act->active_marker = 1;
-
- pld->redraw = PL_PREVIEW_REDRAWALL;
- }
- break;
-
- /* change to last pose or start of searching string */
- case ENDKEY:
- if (pld->searchstr[0]) {
- pld->search_cursor = strlen(pld->searchstr);
- pld->redraw = PL_PREVIEW_REDRAWHEADER;
- }
- else {
- /* change to last pose */
- pld->marker = pld->act->markers.last;
- pld->act->active_marker = BLI_listbase_count(&pld->act->markers);
-
- pld->redraw = PL_PREVIEW_REDRAWALL;
- }
- break;
-
- /* view manipulation */
- /* 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 MIDDLEMOUSE: case MOUSEMOVE:
- //pld->redraw = PL_PREVIEW_REDRAWHEADER;
- ret = OPERATOR_PASS_THROUGH;
- 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:
- if (pld->searchstr[0]) {
- /* searching... */
- poselib_preview_handle_search(pld, event->type, event->ascii);
- }
- else {
- /* view manipulation (see above) */
- //pld->redraw = PL_PREVIEW_REDRAWHEADER;
- ret = OPERATOR_PASS_THROUGH;
- }
- break;
-
- /* otherwise, assume that searching might be able to handle it */
- default:
- poselib_preview_handle_search(pld, event->type, event->ascii);
- break;
- }
-
- return ret;
+ tPoseLib_PreviewData *pld = op->customdata;
+ int ret = OPERATOR_RUNNING_MODAL;
+
+ /* only accept 'press' event, and ignore 'release', so that we don't get double actions */
+ if (ELEM(event->val, KM_PRESS, KM_NOTHING) == 0) {
+ //printf("PoseLib: skipping event with type '%s' and val %d\n", WM_key_event_string(event->type, false), event->val);
+ return ret;
+ }
+
+ /* backup stuff that needs to occur before every operation
+ * - make a copy of searchstr, so that we know if cache needs to be rebuilt
+ */
+ BLI_strncpy(pld->searchold, pld->searchstr, sizeof(pld->searchold));
+
+ /* if we're currently showing the original pose, only certain events are handled */
+ if (pld->flag & PL_PREVIEW_SHOWORIGINAL) {
+ switch (event->type) {
+ /* exit - cancel */
+ case ESCKEY:
+ case RIGHTMOUSE:
+ pld->state = PL_PREVIEW_CANCEL;
+ break;
+
+ /* exit - confirm */
+ case LEFTMOUSE:
+ case RETKEY:
+ case PADENTER:
+ case SPACEKEY:
+ pld->state = PL_PREVIEW_CONFIRM;
+ break;
+
+ /* view manipulation */
+ /* 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 MIDDLEMOUSE:
+ case MOUSEMOVE:
+ //pld->redraw = PL_PREVIEW_REDRAWHEADER;
+ ret = OPERATOR_PASS_THROUGH;
+ break;
+
+ /* quicky compare to original */
+ case TABKEY:
+ pld->flag &= ~PL_PREVIEW_SHOWORIGINAL;
+ pld->redraw = PL_PREVIEW_REDRAWALL;
+ break;
+ }
+
+ /* EXITS HERE... */
+ return ret;
+ }
+
+ /* NORMAL EVENT HANDLING... */
+ /* searching takes priority over normal activity */
+ switch (event->type) {
+ /* exit - cancel */
+ case ESCKEY:
+ case RIGHTMOUSE:
+ pld->state = PL_PREVIEW_CANCEL;
+ break;
+
+ /* exit - confirm */
+ case LEFTMOUSE:
+ case RETKEY:
+ case PADENTER:
+ case SPACEKEY:
+ pld->state = PL_PREVIEW_CONFIRM;
+ break;
+
+ /* toggle between original pose and poselib pose*/
+ case TABKEY:
+ pld->flag |= PL_PREVIEW_SHOWORIGINAL;
+ pld->redraw = PL_PREVIEW_REDRAWALL;
+ break;
+
+ /* change to previous pose (cyclic) */
+ case PAGEUPKEY:
+ case WHEELUPMOUSE:
+ poselib_preview_get_next(pld, -1);
+ pld->redraw = PL_PREVIEW_REDRAWALL;
+ break;
+
+ /* change to next pose (cyclic) */
+ case PAGEDOWNKEY:
+ case WHEELDOWNMOUSE:
+ poselib_preview_get_next(pld, 1);
+ pld->redraw = PL_PREVIEW_REDRAWALL;
+ break;
+
+ /* jump 5 poses (cyclic, back) */
+ case DOWNARROWKEY:
+ poselib_preview_get_next(pld, -5);
+ pld->redraw = PL_PREVIEW_REDRAWALL;
+ break;
+
+ /* jump 5 poses (cyclic, forward) */
+ case UPARROWKEY:
+ poselib_preview_get_next(pld, 5);
+ pld->redraw = PL_PREVIEW_REDRAWALL;
+ break;
+
+ /* change to next pose or searching cursor control */
+ case RIGHTARROWKEY:
+ if (pld->searchstr[0]) {
+ /* move text-cursor to the right */
+ if (pld->search_cursor < strlen(pld->searchstr))
+ pld->search_cursor++;
+ pld->redraw = PL_PREVIEW_REDRAWHEADER;
+ }
+ else {
+ /* change to next pose (cyclic) */
+ poselib_preview_get_next(pld, 1);
+ pld->redraw = PL_PREVIEW_REDRAWALL;
+ }
+ break;
+
+ /* change to next pose or searching cursor control */
+ case LEFTARROWKEY:
+ if (pld->searchstr[0]) {
+ /* move text-cursor to the left */
+ if (pld->search_cursor)
+ pld->search_cursor--;
+ pld->redraw = PL_PREVIEW_REDRAWHEADER;
+ }
+ else {
+ /* change to previous pose (cyclic) */
+ poselib_preview_get_next(pld, -1);
+ pld->redraw = PL_PREVIEW_REDRAWALL;
+ }
+ break;
+
+ /* change to first pose or start of searching string */
+ case HOMEKEY:
+ if (pld->searchstr[0]) {
+ pld->search_cursor = 0;
+ pld->redraw = PL_PREVIEW_REDRAWHEADER;
+ }
+ else {
+ /* change to first pose */
+ pld->marker = pld->act->markers.first;
+ pld->act->active_marker = 1;
+
+ pld->redraw = PL_PREVIEW_REDRAWALL;
+ }
+ break;
+
+ /* change to last pose or start of searching string */
+ case ENDKEY:
+ if (pld->searchstr[0]) {
+ pld->search_cursor = strlen(pld->searchstr);
+ pld->redraw = PL_PREVIEW_REDRAWHEADER;
+ }
+ else {
+ /* change to last pose */
+ pld->marker = pld->act->markers.last;
+ pld->act->active_marker = BLI_listbase_count(&pld->act->markers);
+
+ pld->redraw = PL_PREVIEW_REDRAWALL;
+ }
+ break;
+
+ /* view manipulation */
+ /* 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 MIDDLEMOUSE:
+ case MOUSEMOVE:
+ //pld->redraw = PL_PREVIEW_REDRAWHEADER;
+ ret = OPERATOR_PASS_THROUGH;
+ 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:
+ if (pld->searchstr[0]) {
+ /* searching... */
+ poselib_preview_handle_search(pld, event->type, event->ascii);
+ }
+ else {
+ /* view manipulation (see above) */
+ //pld->redraw = PL_PREVIEW_REDRAWHEADER;
+ ret = OPERATOR_PASS_THROUGH;
+ }
+ break;
+
+ /* otherwise, assume that searching might be able to handle it */
+ default:
+ poselib_preview_handle_search(pld, event->type, event->ascii);
+ break;
+ }
+
+ return ret;
}
/* ---------------------------- */
@@ -1534,277 +1575,295 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
/* Init PoseLib Previewing data */
static void poselib_preview_init_data(bContext *C, wmOperator *op)
{
- tPoseLib_PreviewData *pld;
- Object *ob = get_poselib_object(C);
- int pose_index = RNA_int_get(op->ptr, "pose_index");
-
- /* set up preview state info */
- op->customdata = pld = MEM_callocN(sizeof(tPoseLib_PreviewData), "PoseLib Preview Data");
-
- /* get basic data */
- pld->ob = ob;
- pld->arm = (ob) ? (ob->data) : NULL;
- pld->pose = (ob) ? (ob->pose) : NULL;
- pld->act = (ob) ? (ob->poselib) : NULL;
-
- pld->scene = CTX_data_scene(C);
- pld->sa = CTX_wm_area(C);
-
- /* get starting pose based on RNA-props for this operator */
- if (pose_index == -1)
- pld->marker = poselib_get_active_pose(pld->act);
- else if (pose_index == -2)
- pld->flag |= PL_PREVIEW_SHOWORIGINAL;
- else
- pld->marker = (pld->act) ? BLI_findlink(&pld->act->markers, pose_index) : NULL;
-
- /* check if valid poselib */
- if (ELEM(NULL, pld->ob, pld->pose, pld->arm)) {
- BKE_report(op->reports, RPT_ERROR, "Pose lib is only for armatures in pose mode");
- pld->state = PL_PREVIEW_ERROR;
- return;
- }
- if (pld->act == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Object does not have a valid pose lib");
- pld->state = PL_PREVIEW_ERROR;
- return;
- }
- if (pld->marker == NULL) {
- if (pld->act->markers.first) {
- /* just use first one then... */
- pld->marker = pld->act->markers.first;
- if (pose_index > -2)
- BKE_report(op->reports, RPT_WARNING, "Pose lib had no active pose");
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Pose lib has no poses to preview/apply");
- pld->state = PL_PREVIEW_ERROR;
- return;
- }
- }
-
- /* get ID pointer for applying poses */
- RNA_id_pointer_create(&ob->id, &pld->rna_ptr);
-
- /* make backups for restoring pose */
- poselib_backup_posecopy(pld);
-
- /* set flags for running */
- pld->state = PL_PREVIEW_RUNNING;
- pld->redraw = PL_PREVIEW_REDRAWALL;
- pld->flag |= PL_PREVIEW_FIRSTTIME;
-
- /* set depsgraph flags */
- /* make sure the lock is set OK, unlock can be accidentally saved? */
- pld->pose->flag |= POSE_LOCKED;
- pld->pose->flag &= ~POSE_DO_UNLOCK;
-
- /* clear strings + search */
- pld->headerstr[0] = pld->searchstr[0] = pld->searchold[0] = '\0';
- pld->search_cursor = 0;
+ tPoseLib_PreviewData *pld;
+ Object *ob = get_poselib_object(C);
+ int pose_index = RNA_int_get(op->ptr, "pose_index");
+
+ /* set up preview state info */
+ op->customdata = pld = MEM_callocN(sizeof(tPoseLib_PreviewData), "PoseLib Preview Data");
+
+ /* get basic data */
+ pld->ob = ob;
+ pld->arm = (ob) ? (ob->data) : NULL;
+ pld->pose = (ob) ? (ob->pose) : NULL;
+ pld->act = (ob) ? (ob->poselib) : NULL;
+
+ pld->scene = CTX_data_scene(C);
+ pld->sa = CTX_wm_area(C);
+
+ /* get starting pose based on RNA-props for this operator */
+ if (pose_index == -1)
+ pld->marker = poselib_get_active_pose(pld->act);
+ else if (pose_index == -2)
+ pld->flag |= PL_PREVIEW_SHOWORIGINAL;
+ else
+ pld->marker = (pld->act) ? BLI_findlink(&pld->act->markers, pose_index) : NULL;
+
+ /* check if valid poselib */
+ if (ELEM(NULL, pld->ob, pld->pose, pld->arm)) {
+ BKE_report(op->reports, RPT_ERROR, "Pose lib is only for armatures in pose mode");
+ pld->state = PL_PREVIEW_ERROR;
+ return;
+ }
+ if (pld->act == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Object does not have a valid pose lib");
+ pld->state = PL_PREVIEW_ERROR;
+ return;
+ }
+ if (pld->marker == NULL) {
+ if (pld->act->markers.first) {
+ /* just use first one then... */
+ pld->marker = pld->act->markers.first;
+ if (pose_index > -2)
+ BKE_report(op->reports, RPT_WARNING, "Pose lib had no active pose");
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Pose lib has no poses to preview/apply");
+ pld->state = PL_PREVIEW_ERROR;
+ return;
+ }
+ }
+
+ /* get ID pointer for applying poses */
+ RNA_id_pointer_create(&ob->id, &pld->rna_ptr);
+
+ /* make backups for restoring pose */
+ poselib_backup_posecopy(pld);
+
+ /* set flags for running */
+ pld->state = PL_PREVIEW_RUNNING;
+ pld->redraw = PL_PREVIEW_REDRAWALL;
+ pld->flag |= PL_PREVIEW_FIRSTTIME;
+
+ /* set depsgraph flags */
+ /* make sure the lock is set OK, unlock can be accidentally saved? */
+ pld->pose->flag |= POSE_LOCKED;
+ pld->pose->flag &= ~POSE_DO_UNLOCK;
+
+ /* clear strings + search */
+ pld->headerstr[0] = pld->searchstr[0] = pld->searchold[0] = '\0';
+ pld->search_cursor = 0;
}
/* After previewing poses */
static void poselib_preview_cleanup(bContext *C, wmOperator *op)
{
- tPoseLib_PreviewData *pld = (tPoseLib_PreviewData *)op->customdata;
- Scene *scene = pld->scene;
- Object *ob = pld->ob;
- bPose *pose = pld->pose;
- bArmature *arm = pld->arm;
- bAction *act = pld->act;
- 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_workspace_status_text(C, NULL);
-
- /* this signal does one recalc on pose, then unlocks, so ESC or edit will work */
- pose->flag |= POSE_DO_UNLOCK;
-
- /* clear pose if canceled */
- if (pld->state == PL_PREVIEW_CANCEL) {
- poselib_backup_restore(pld);
-
- /* old optimize trick... this enforces to bypass the depgraph
- * - note: code copied from transform_generics.c -> recalcData()
- */
- if ((arm->flag & ARM_DELAYDEFORM) == 0)
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); /* sets recalc flags */
- else
- BKE_pose_where_is(CTX_data_depsgraph(C), scene, ob);
- }
- else if (pld->state == PL_PREVIEW_CONFIRM) {
- /* tag poses as appropriate */
- poselib_keytag_pose(C, scene, pld);
-
- /* change active pose setting */
- act->active_marker = BLI_findindex(&act->markers, marker) + 1;
- action_set_activemarker(act, marker, NULL);
-
- /* Update event for pose and deformation children */
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
-
- /* updates */
- if (IS_AUTOKEY_MODE(scene, NORMAL)) {
- //remake_action_ipos(ob->action);
- }
- else
- BKE_pose_where_is(CTX_data_depsgraph(C), scene, ob);
- }
-
- /* Request final redraw of the view. */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, pld->ob);
-
- /* free memory used for backups and searching */
- poselib_backup_free_data(pld);
- BLI_freelistN(&pld->searchp);
-
- /* free temp data for operator */
- MEM_freeN(pld);
- op->customdata = NULL;
+ tPoseLib_PreviewData *pld = (tPoseLib_PreviewData *)op->customdata;
+ Scene *scene = pld->scene;
+ Object *ob = pld->ob;
+ bPose *pose = pld->pose;
+ bArmature *arm = pld->arm;
+ bAction *act = pld->act;
+ 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_workspace_status_text(C, NULL);
+
+ /* this signal does one recalc on pose, then unlocks, so ESC or edit will work */
+ pose->flag |= POSE_DO_UNLOCK;
+
+ /* clear pose if canceled */
+ if (pld->state == PL_PREVIEW_CANCEL) {
+ poselib_backup_restore(pld);
+
+ /* old optimize trick... this enforces to bypass the depgraph
+ * - note: code copied from transform_generics.c -> recalcData()
+ */
+ if ((arm->flag & ARM_DELAYDEFORM) == 0)
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); /* sets recalc flags */
+ else
+ BKE_pose_where_is(CTX_data_depsgraph(C), scene, ob);
+ }
+ else if (pld->state == PL_PREVIEW_CONFIRM) {
+ /* tag poses as appropriate */
+ poselib_keytag_pose(C, scene, pld);
+
+ /* change active pose setting */
+ act->active_marker = BLI_findindex(&act->markers, marker) + 1;
+ action_set_activemarker(act, marker, NULL);
+
+ /* Update event for pose and deformation children */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+
+ /* updates */
+ if (IS_AUTOKEY_MODE(scene, NORMAL)) {
+ //remake_action_ipos(ob->action);
+ }
+ else
+ BKE_pose_where_is(CTX_data_depsgraph(C), scene, ob);
+ }
+
+ /* Request final redraw of the view. */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, pld->ob);
+
+ /* free memory used for backups and searching */
+ poselib_backup_free_data(pld);
+ BLI_freelistN(&pld->searchp);
+
+ /* free temp data for operator */
+ MEM_freeN(pld);
+ op->customdata = NULL;
}
/* End previewing operation */
static int poselib_preview_exit(bContext *C, wmOperator *op)
{
- tPoseLib_PreviewData *pld = op->customdata;
- int exit_state = pld->state;
+ tPoseLib_PreviewData *pld = op->customdata;
+ int exit_state = pld->state;
- /* finish up */
- poselib_preview_cleanup(C, op);
+ /* finish up */
+ poselib_preview_cleanup(C, op);
- if (ELEM(exit_state, PL_PREVIEW_CANCEL, PL_PREVIEW_ERROR))
- return OPERATOR_CANCELLED;
- else
- return OPERATOR_FINISHED;
+ if (ELEM(exit_state, PL_PREVIEW_CANCEL, PL_PREVIEW_ERROR))
+ return OPERATOR_CANCELLED;
+ else
+ return OPERATOR_FINISHED;
}
/* Cancel previewing operation (called when exiting Blender) */
static void poselib_preview_cancel(bContext *C, wmOperator *op)
{
- poselib_preview_exit(C, op);
+ poselib_preview_exit(C, op);
}
/* main modal status check */
static int poselib_preview_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- tPoseLib_PreviewData *pld = op->customdata;
- int ret;
+ tPoseLib_PreviewData *pld = op->customdata;
+ int ret;
- /* 1) check state to see if we're still running */
- if (pld->state != PL_PREVIEW_RUNNING)
- return poselib_preview_exit(C, op);
+ /* 1) check state to see if we're still running */
+ if (pld->state != PL_PREVIEW_RUNNING)
+ return poselib_preview_exit(C, op);
- /* 2) handle events */
- ret = poselib_preview_handle_event(C, op, event);
+ /* 2) handle events */
+ ret = poselib_preview_handle_event(C, op, event);
- /* 3) apply changes and redraw, otherwise, confirming goes wrong */
- if (pld->redraw)
- poselib_preview_apply(C, op);
+ /* 3) apply changes and redraw, otherwise, confirming goes wrong */
+ if (pld->redraw)
+ poselib_preview_apply(C, op);
- return ret;
+ return ret;
}
/* Modal Operator init */
static int poselib_preview_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- tPoseLib_PreviewData *pld;
+ tPoseLib_PreviewData *pld;
- /* check if everything is ok, and init settings for modal operator */
- poselib_preview_init_data(C, op);
- pld = (tPoseLib_PreviewData *)op->customdata;
+ /* check if everything is ok, and init settings for modal operator */
+ poselib_preview_init_data(C, op);
+ pld = (tPoseLib_PreviewData *)op->customdata;
- if (pld->state == PL_PREVIEW_ERROR) {
- /* an error occurred, so free temp mem used */
- poselib_preview_cleanup(C, op);
- return OPERATOR_CANCELLED;
- }
+ if (pld->state == PL_PREVIEW_ERROR) {
+ /* an error occurred, so free temp mem used */
+ poselib_preview_cleanup(C, op);
+ return OPERATOR_CANCELLED;
+ }
- /* do initial apply to have something to look at */
- poselib_preview_apply(C, op);
+ /* do initial apply to have something to look at */
+ poselib_preview_apply(C, op);
- /* add temp handler if we're running as a modal operator */
- WM_event_add_modal_handler(C, op);
+ /* add temp handler if we're running as a modal operator */
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
/* Repeat operator */
static int poselib_preview_exec(bContext *C, wmOperator *op)
{
- tPoseLib_PreviewData *pld;
+ tPoseLib_PreviewData *pld;
- /* check if everything is ok, and init settings for modal operator */
- poselib_preview_init_data(C, op);
- pld = (tPoseLib_PreviewData *)op->customdata;
+ /* check if everything is ok, and init settings for modal operator */
+ poselib_preview_init_data(C, op);
+ pld = (tPoseLib_PreviewData *)op->customdata;
- if (pld->state == PL_PREVIEW_ERROR) {
- /* an error occurred, so free temp mem used */
- poselib_preview_cleanup(C, op);
- return OPERATOR_CANCELLED;
- }
+ if (pld->state == PL_PREVIEW_ERROR) {
+ /* an error occurred, so free temp mem used */
+ poselib_preview_cleanup(C, op);
+ return OPERATOR_CANCELLED;
+ }
- /* the exec() callback is effectively a 'run-once' scenario, so set the state to that
- * so that everything draws correctly
- */
- pld->state = PL_PREVIEW_RUNONCE;
+ /* the exec() callback is effectively a 'run-once' scenario, so set the state to that
+ * so that everything draws correctly
+ */
+ pld->state = PL_PREVIEW_RUNONCE;
- /* apply the active pose */
- poselib_preview_apply(C, op);
+ /* apply the active pose */
+ poselib_preview_apply(C, op);
- /* now, set the status to exit */
- pld->state = PL_PREVIEW_CONFIRM;
+ /* now, set the status to exit */
+ pld->state = PL_PREVIEW_CONFIRM;
- /* cleanup */
- return poselib_preview_exit(C, op);
+ /* cleanup */
+ return poselib_preview_exit(C, op);
}
void POSELIB_OT_browse_interactive(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "PoseLib Browse Poses";
- ot->idname = "POSELIB_OT_browse_interactive";
- ot->description = "Interactively browse poses in 3D-View";
-
- /* callbacks */
- ot->invoke = poselib_preview_invoke;
- ot->modal = poselib_preview_modal;
- ot->cancel = poselib_preview_cancel;
- ot->exec = poselib_preview_exec;
- ot->poll = has_poselib_pose_data_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* properties */
- // TODO: make the pose_index into a proper enum instead of a cryptic int...
- ot->prop = RNA_def_int(ot->srna, "pose_index", -1, -2, INT_MAX, "Pose", "Index of the pose to apply (-2 for no change to pose, -1 for poselib active pose)", 0, INT_MAX);
-
- // XXX: percentage vs factor?
- /* not used yet */
+ /* identifiers */
+ ot->name = "PoseLib Browse Poses";
+ ot->idname = "POSELIB_OT_browse_interactive";
+ ot->description = "Interactively browse poses in 3D-View";
+
+ /* callbacks */
+ ot->invoke = poselib_preview_invoke;
+ ot->modal = poselib_preview_modal;
+ ot->cancel = poselib_preview_cancel;
+ ot->exec = poselib_preview_exec;
+ ot->poll = has_poselib_pose_data_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* properties */
+ // TODO: make the pose_index into a proper enum instead of a cryptic int...
+ ot->prop = RNA_def_int(
+ ot->srna,
+ "pose_index",
+ -1,
+ -2,
+ INT_MAX,
+ "Pose",
+ "Index of the pose to apply (-2 for no change to pose, -1 for poselib active pose)",
+ 0,
+ INT_MAX);
+
+ // XXX: percentage vs factor?
+ /* not used yet */
#if 0
- RNA_def_float_factor(
- ot->srna, "blend_factor", 1.0f, 0.0f, 1.0f, "Blend Factor",
- "Amount that the pose is applied on top of the existing poses", 0.0f, 1.0f);
+ RNA_def_float_factor(
+ ot->srna, "blend_factor", 1.0f, 0.0f, 1.0f, "Blend Factor",
+ "Amount that the pose is applied on top of the existing poses", 0.0f, 1.0f);
#endif
}
void POSELIB_OT_apply_pose(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Apply Pose Library Pose";
- ot->idname = "POSELIB_OT_apply_pose";
- ot->description = "Apply specified Pose Library pose to the rig";
-
- /* callbacks */
- ot->exec = poselib_preview_exec;
- ot->poll = has_poselib_pose_data_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- /* TODO: make the pose_index into a proper enum instead of a cryptic int... */
- ot->prop = RNA_def_int(ot->srna, "pose_index", -1, -2, INT_MAX, "Pose", "Index of the pose to apply (-2 for no change to pose, -1 for poselib active pose)", 0, INT_MAX);
+ /* identifiers */
+ ot->name = "Apply Pose Library Pose";
+ ot->idname = "POSELIB_OT_apply_pose";
+ ot->description = "Apply specified Pose Library pose to the rig";
+
+ /* callbacks */
+ ot->exec = poselib_preview_exec;
+ ot->poll = has_poselib_pose_data_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ /* TODO: make the pose_index into a proper enum instead of a cryptic int... */
+ ot->prop = RNA_def_int(
+ ot->srna,
+ "pose_index",
+ -1,
+ -2,
+ INT_MAX,
+ "Pose",
+ "Index of the pose to apply (-2 for no change to pose, -1 for poselib active pose)",
+ 0,
+ INT_MAX);
}
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index 5ef61f0f6c6..b825d821fe8 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -63,172 +63,178 @@
#define PBONE_PREV_FLAG_GET(pchan) ((void)0, (POINTER_AS_INT((pchan)->temp)))
#define PBONE_PREV_FLAG_SET(pchan, val) ((pchan)->temp = POINTER_FROM_INT(val))
-
/* ***************** Pose Select Utilities ********************* */
/* Note: SEL_TOGGLE is assumed to have already been handled! */
static void pose_do_bone_select(bPoseChannel *pchan, const int select_mode)
{
- /* select pchan only if selectable, but deselect works always */
- switch (select_mode) {
- case SEL_SELECT:
- if (!(pchan->bone->flag & BONE_UNSELECTABLE))
- pchan->bone->flag |= BONE_SELECTED;
- break;
- case SEL_DESELECT:
- pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- break;
- case SEL_INVERT:
- if (pchan->bone->flag & BONE_SELECTED) {
- pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else if (!(pchan->bone->flag & BONE_UNSELECTABLE)) {
- pchan->bone->flag |= BONE_SELECTED;
- }
- break;
- }
+ /* select pchan only if selectable, but deselect works always */
+ switch (select_mode) {
+ case SEL_SELECT:
+ if (!(pchan->bone->flag & BONE_UNSELECTABLE))
+ pchan->bone->flag |= BONE_SELECTED;
+ break;
+ case SEL_DESELECT:
+ pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ break;
+ case SEL_INVERT:
+ if (pchan->bone->flag & BONE_SELECTED) {
+ pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else if (!(pchan->bone->flag & BONE_UNSELECTABLE)) {
+ pchan->bone->flag |= BONE_SELECTED;
+ }
+ break;
+ }
}
void ED_pose_bone_select_tag_update(Object *ob)
{
- BLI_assert(ob->type == OB_ARMATURE);
- bArmature *arm = ob->data;
- WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, ob);
- WM_main_add_notifier(NC_GEOM | ND_DATA, ob);
+ BLI_assert(ob->type == OB_ARMATURE);
+ bArmature *arm = ob->data;
+ WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, ob);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, ob);
- if (arm->flag & ARM_HAS_VIZ_DEPS) {
- /* mask modifier ('armature' mode), etc. */
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
+ if (arm->flag & ARM_HAS_VIZ_DEPS) {
+ /* mask modifier ('armature' mode), etc. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
- DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
+ DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
}
-
/* Utility method for changing the selection status of a bone */
void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select)
{
- bArmature *arm;
-
- /* sanity checks */
- // XXX: actually, we can probably still get away with no object - at most we have no updates
- if (ELEM(NULL, ob, ob->pose, pchan, pchan->bone))
- return;
-
- arm = ob->data;
-
- /* can only change selection state if bone can be modified */
- if (PBONE_SELECTABLE(arm, pchan->bone)) {
- /* change selection state - activate too if selected */
- if (select) {
- pchan->bone->flag |= BONE_SELECTED;
- arm->act_bone = pchan->bone;
- }
- else {
- pchan->bone->flag &= ~BONE_SELECTED;
- arm->act_bone = NULL;
- }
-
- // TODO: select and activate corresponding vgroup?
- ED_pose_bone_select_tag_update(ob);
- }
+ bArmature *arm;
+
+ /* sanity checks */
+ // XXX: actually, we can probably still get away with no object - at most we have no updates
+ if (ELEM(NULL, ob, ob->pose, pchan, pchan->bone))
+ return;
+
+ arm = ob->data;
+
+ /* can only change selection state if bone can be modified */
+ if (PBONE_SELECTABLE(arm, pchan->bone)) {
+ /* change selection state - activate too if selected */
+ if (select) {
+ pchan->bone->flag |= BONE_SELECTED;
+ arm->act_bone = pchan->bone;
+ }
+ else {
+ pchan->bone->flag &= ~BONE_SELECTED;
+ arm->act_bone = NULL;
+ }
+
+ // TODO: select and activate corresponding vgroup?
+ ED_pose_bone_select_tag_update(ob);
+ }
}
/* called from editview.c, for mode-less pose selection */
/* assumes scene obact and basact is still on old situation */
-bool ED_armature_pose_select_pick_with_buffer(
- ViewLayer *view_layer, View3D *v3d, Base *base, const unsigned int *buffer, short hits,
- bool extend, bool deselect, bool toggle, bool do_nearest)
+bool ED_armature_pose_select_pick_with_buffer(ViewLayer *view_layer,
+ View3D *v3d,
+ Base *base,
+ const unsigned int *buffer,
+ short hits,
+ bool extend,
+ bool deselect,
+ bool toggle,
+ bool do_nearest)
{
- Object *ob = base->object;
- Bone *nearBone;
-
- if (!ob || !ob->pose) return 0;
-
- Object *ob_act = OBACT(view_layer);
- Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
-
- /* 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);
-
- /* if the bone cannot be affected, don't do anything */
- if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) {
- bArmature *arm = ob->data;
-
- /* since we do unified select, we don't shift+select a bone if the
- * armature object was not active yet.
- * note, special exception for armature mode so we can do multi-select
- * we could check for multi-select explicitly but think its fine to
- * always give predictable behavior in weight paint mode - campbell */
- if ((ob_act == NULL) || ((ob_act != ob) && (ob_act->mode & OB_MODE_WEIGHT_PAINT) == 0)) {
- /* when we are entering into posemode via toggle-select,
- * from another active object - always select the bone. */
- if (!extend && !deselect && toggle) {
- /* re-select below */
- nearBone->flag &= ~BONE_SELECTED;
- }
- }
-
- if (!extend && !deselect && !toggle) {
- {
- uint bases_len = 0;
- Base **bases = BKE_object_pose_base_array_get_unique(view_layer, v3d, &bases_len);
- ED_pose_deselect_all_multi_ex(bases, bases_len, SEL_DESELECT, true);
- MEM_freeN(bases);
- }
- nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- arm->act_bone = nearBone;
- }
- else {
- if (extend) {
- nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- arm->act_bone = nearBone;
- }
- else if (deselect) {
- nearBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else if (toggle) {
- if (nearBone->flag & BONE_SELECTED) {
- /* if not active, we make it active */
- if (nearBone != arm->act_bone) {
- arm->act_bone = nearBone;
- }
- else {
- nearBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- }
- else {
- nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- arm->act_bone = nearBone;
- }
- }
- }
-
- if (ob_act) {
- /* in weightpaint we select the associated vertex group too */
- if (ob_act->mode & OB_MODE_WEIGHT_PAINT) {
- if (nearBone == arm->act_bone) {
- ED_vgroup_select_by_name(ob_act, nearBone->name);
- DEG_id_tag_update(&ob_act->id, ID_RECALC_GEOMETRY);
- }
- }
- /* if there are some dependencies for visualizing armature state
- * (e.g. Mask Modifier in 'Armature' mode), force update
- */
- else if (arm->flag & ARM_HAS_VIZ_DEPS) {
- /* NOTE: ob not ob_act here is intentional - it's the source of the
- * bones being selected [T37247]
- */
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
-
- /* tag armature for copy-on-write update (since act_bone is in armature not object) */
- DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
- }
- }
-
- return nearBone != NULL;
+ Object *ob = base->object;
+ Bone *nearBone;
+
+ if (!ob || !ob->pose)
+ return 0;
+
+ Object *ob_act = OBACT(view_layer);
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
+
+ /* 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);
+
+ /* if the bone cannot be affected, don't do anything */
+ if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) {
+ bArmature *arm = ob->data;
+
+ /* since we do unified select, we don't shift+select a bone if the
+ * armature object was not active yet.
+ * note, special exception for armature mode so we can do multi-select
+ * we could check for multi-select explicitly but think its fine to
+ * always give predictable behavior in weight paint mode - campbell */
+ if ((ob_act == NULL) || ((ob_act != ob) && (ob_act->mode & OB_MODE_WEIGHT_PAINT) == 0)) {
+ /* when we are entering into posemode via toggle-select,
+ * from another active object - always select the bone. */
+ if (!extend && !deselect && toggle) {
+ /* re-select below */
+ nearBone->flag &= ~BONE_SELECTED;
+ }
+ }
+
+ if (!extend && !deselect && !toggle) {
+ {
+ uint bases_len = 0;
+ Base **bases = BKE_object_pose_base_array_get_unique(view_layer, v3d, &bases_len);
+ ED_pose_deselect_all_multi_ex(bases, bases_len, SEL_DESELECT, true);
+ MEM_freeN(bases);
+ }
+ nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ arm->act_bone = nearBone;
+ }
+ else {
+ if (extend) {
+ nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ arm->act_bone = nearBone;
+ }
+ else if (deselect) {
+ nearBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else if (toggle) {
+ if (nearBone->flag & BONE_SELECTED) {
+ /* if not active, we make it active */
+ if (nearBone != arm->act_bone) {
+ arm->act_bone = nearBone;
+ }
+ else {
+ nearBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
+ else {
+ nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ arm->act_bone = nearBone;
+ }
+ }
+ }
+
+ if (ob_act) {
+ /* in weightpaint we select the associated vertex group too */
+ if (ob_act->mode & OB_MODE_WEIGHT_PAINT) {
+ if (nearBone == arm->act_bone) {
+ ED_vgroup_select_by_name(ob_act, nearBone->name);
+ DEG_id_tag_update(&ob_act->id, ID_RECALC_GEOMETRY);
+ }
+ }
+ /* if there are some dependencies for visualizing armature state
+ * (e.g. Mask Modifier in 'Armature' mode), force update
+ */
+ else if (arm->flag & ARM_HAS_VIZ_DEPS) {
+ /* NOTE: ob not ob_act here is intentional - it's the source of the
+ * bones being selected [T37247]
+ */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+
+ /* tag armature for copy-on-write update (since act_bone is in armature not object) */
+ DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ }
+
+ return nearBone != NULL;
}
/* 'select_mode' is usual SEL_SELECT/SEL_DESELECT/SEL_TOGGLE/SEL_INVERT.
@@ -236,340 +242,349 @@ bool ED_armature_pose_select_pick_with_buffer(
* (hidden or on hidden layers). */
bool ED_pose_deselect_all(Object *ob, int select_mode, const bool ignore_visibility)
{
- bArmature *arm = ob->data;
- bPoseChannel *pchan;
-
- /* we call this from outliner too */
- if (ob->pose == NULL) {
- return false;
- }
-
- /* Determine if we're selecting or deselecting */
- if (select_mode == SEL_TOGGLE) {
- select_mode = SEL_SELECT;
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (ignore_visibility || PBONE_VISIBLE(arm, pchan->bone)) {
- if (pchan->bone->flag & BONE_SELECTED) {
- select_mode = SEL_DESELECT;
- break;
- }
- }
- }
- }
-
- /* Set the flags accordingly */
- bool changed = false;
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- /* ignore the pchan if it isn't visible or if its selection cannot be changed */
- if (ignore_visibility || PBONE_VISIBLE(arm, pchan->bone)) {
- int flag_prev = pchan->bone->flag;
- pose_do_bone_select(pchan, select_mode);
- changed = (changed || flag_prev != pchan->bone->flag);
- }
- }
- return changed;
+ bArmature *arm = ob->data;
+ bPoseChannel *pchan;
+
+ /* we call this from outliner too */
+ if (ob->pose == NULL) {
+ return false;
+ }
+
+ /* Determine if we're selecting or deselecting */
+ if (select_mode == SEL_TOGGLE) {
+ select_mode = SEL_SELECT;
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (ignore_visibility || PBONE_VISIBLE(arm, pchan->bone)) {
+ if (pchan->bone->flag & BONE_SELECTED) {
+ select_mode = SEL_DESELECT;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Set the flags accordingly */
+ bool changed = false;
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ /* ignore the pchan if it isn't visible or if its selection cannot be changed */
+ if (ignore_visibility || PBONE_VISIBLE(arm, pchan->bone)) {
+ int flag_prev = pchan->bone->flag;
+ pose_do_bone_select(pchan, select_mode);
+ changed = (changed || flag_prev != pchan->bone->flag);
+ }
+ }
+ return changed;
}
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) {
- if (ignore_visibility || PBONE_VISIBLE(arm, pchan->bone)) {
- if (pchan->bone->flag & BONE_SELECTED) {
- return true;
- }
- }
- }
- return false;
+ bArmature *arm = ob->data;
+ for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (ignore_visibility || PBONE_VISIBLE(arm, pchan->bone)) {
+ if (pchan->bone->flag & BONE_SELECTED) {
+ return true;
+ }
+ }
+ }
+ return false;
}
static bool ed_pose_is_any_selected_multi(Base **bases, uint bases_len, bool ignore_visibility)
{
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Object *ob_iter = bases[base_index]->object;
- if (ed_pose_is_any_selected(ob_iter, ignore_visibility)) {
- return true;
- }
- }
- return false;
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Object *ob_iter = bases[base_index]->object;
+ if (ed_pose_is_any_selected(ob_iter, ignore_visibility)) {
+ return true;
+ }
+ }
+ return false;
}
-bool ED_pose_deselect_all_multi_ex(Base **bases, uint bases_len, int select_mode, const bool ignore_visibility)
+bool ED_pose_deselect_all_multi_ex(Base **bases,
+ uint bases_len,
+ int select_mode,
+ const bool ignore_visibility)
{
- if (select_mode == SEL_TOGGLE) {
- select_mode = ed_pose_is_any_selected_multi(
- bases, bases_len, ignore_visibility) ? SEL_DESELECT : SEL_SELECT;
- }
-
- bool changed_multi = false;
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Object *ob_iter = bases[base_index]->object;
- if (ED_pose_deselect_all(ob_iter, select_mode, ignore_visibility)) {
- ED_pose_bone_select_tag_update(ob_iter);
- changed_multi = true;
- }
- }
- return changed_multi;
+ if (select_mode == SEL_TOGGLE) {
+ select_mode = ed_pose_is_any_selected_multi(bases, bases_len, ignore_visibility) ?
+ SEL_DESELECT :
+ SEL_SELECT;
+ }
+
+ bool changed_multi = false;
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Object *ob_iter = bases[base_index]->object;
+ if (ED_pose_deselect_all(ob_iter, select_mode, ignore_visibility)) {
+ ED_pose_bone_select_tag_update(ob_iter);
+ changed_multi = true;
+ }
+ }
+ return changed_multi;
}
-
bool ED_pose_deselect_all_multi(bContext *C, int select_mode, const bool ignore_visibility)
{
- ViewContext vc;
- ED_view3d_viewcontext_init(C, &vc);
- uint bases_len = 0;
- Base **bases = BKE_view_layer_array_from_bases_in_mode(vc.view_layer, vc.v3d, &bases_len, {.object_mode = OB_MODE_POSE,});
- bool changed_multi = ED_pose_deselect_all_multi_ex(bases, bases_len, select_mode, ignore_visibility);
- MEM_freeN(bases);
- return changed_multi;
+ ViewContext vc;
+ ED_view3d_viewcontext_init(C, &vc);
+ uint bases_len = 0;
+ Base **bases = BKE_view_layer_array_from_bases_in_mode(vc.view_layer,
+ vc.v3d,
+ &bases_len,
+ {
+ .object_mode = OB_MODE_POSE,
+ });
+ bool changed_multi = ED_pose_deselect_all_multi_ex(
+ bases, bases_len, select_mode, ignore_visibility);
+ MEM_freeN(bases);
+ return changed_multi;
}
/* ***************** Selections ********************** */
static void selectconnected_posebonechildren(Object *ob, Bone *bone, int extend)
{
- Bone *curBone;
+ Bone *curBone;
- /* stop when unconnected child is encountered, or when unselectable bone is encountered */
- if (!(bone->flag & BONE_CONNECTED) || (bone->flag & BONE_UNSELECTABLE))
- return;
+ /* stop when unconnected child is encountered, or when unselectable bone is encountered */
+ if (!(bone->flag & BONE_CONNECTED) || (bone->flag & BONE_UNSELECTABLE))
+ return;
- if (extend)
- bone->flag &= ~BONE_SELECTED;
- else
- bone->flag |= BONE_SELECTED;
+ if (extend)
+ bone->flag &= ~BONE_SELECTED;
+ else
+ bone->flag |= BONE_SELECTED;
- for (curBone = bone->childbase.first; curBone; curBone = curBone->next)
- selectconnected_posebonechildren(ob, curBone, extend);
+ for (curBone = bone->childbase.first; curBone; curBone = curBone->next)
+ selectconnected_posebonechildren(ob, curBone, extend);
}
/* within active object context */
/* previously known as "selectconnected_posearmature" */
static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Bone *bone, *curBone, *next = NULL;
- const bool extend = RNA_boolean_get(op->ptr, "extend");
-
- view3d_operator_needs_opengl(C);
-
- Base *base = NULL;
- bone = get_nearest_bone(C, event->mval, !extend, &base);
-
- if (!bone)
- return OPERATOR_CANCELLED;
-
- /* Select parents */
- for (curBone = bone; curBone; curBone = next) {
- /* ignore bone if cannot be selected */
- if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
- if (extend)
- curBone->flag &= ~BONE_SELECTED;
- else
- curBone->flag |= BONE_SELECTED;
-
- if (curBone->flag & BONE_CONNECTED)
- next = curBone->parent;
- else
- next = NULL;
- }
- else
- next = NULL;
- }
-
- /* Select children */
- for (curBone = bone->childbase.first; curBone; curBone = next)
- selectconnected_posebonechildren(base->object, curBone, extend);
-
- ED_pose_bone_select_tag_update(base->object);
-
- return OPERATOR_FINISHED;
+ Bone *bone, *curBone, *next = NULL;
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+
+ view3d_operator_needs_opengl(C);
+
+ Base *base = NULL;
+ bone = get_nearest_bone(C, event->mval, !extend, &base);
+
+ if (!bone)
+ return OPERATOR_CANCELLED;
+
+ /* Select parents */
+ for (curBone = bone; curBone; curBone = next) {
+ /* ignore bone if cannot be selected */
+ if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
+ if (extend)
+ curBone->flag &= ~BONE_SELECTED;
+ else
+ curBone->flag |= BONE_SELECTED;
+
+ if (curBone->flag & BONE_CONNECTED)
+ next = curBone->parent;
+ else
+ next = NULL;
+ }
+ else
+ next = NULL;
+ }
+
+ /* Select children */
+ for (curBone = bone->childbase.first; curBone; curBone = next)
+ selectconnected_posebonechildren(base->object, curBone, extend);
+
+ ED_pose_bone_select_tag_update(base->object);
+
+ return OPERATOR_FINISHED;
}
static bool pose_select_linked_poll(bContext *C)
{
- return (ED_operator_view3d_active(C) && ED_operator_posemode(C));
+ return (ED_operator_view3d_active(C) && ED_operator_posemode(C));
}
void POSE_OT_select_linked(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";
-
- /* callbacks */
- /* leave 'exec' unset */
- ot->invoke = pose_select_connected_invoke;
- ot->poll = pose_select_linked_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
+ /* identifiers */
+ ot->name = "Select Connected";
+ ot->idname = "POSE_OT_select_linked";
+ ot->description = "Select bones related to selected ones by parent/child relationships";
+
+ /* callbacks */
+ /* leave 'exec' unset */
+ ot->invoke = pose_select_connected_invoke;
+ ot->poll = pose_select_linked_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna,
+ "extend",
+ false,
+ "Extend",
+ "Extend selection instead of deselecting everything first");
}
/* -------------------------------------- */
static int pose_de_select_all_exec(bContext *C, wmOperator *op)
{
- int action = RNA_enum_get(op->ptr, "action");
-
- Scene *scene = CTX_data_scene(C);
- int multipaint = scene->toolsettings->multipaint;
-
- if (action == SEL_TOGGLE) {
- action = CTX_DATA_COUNT(C, selected_pose_bones) ? SEL_DESELECT : SEL_SELECT;
- }
-
- Object *ob_prev = NULL;
-
- /* 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);
-
- if (ob_prev != ob) {
- /* weightpaint or mask modifiers need depsgraph updates */
- if (multipaint || (arm->flag & ARM_HAS_VIZ_DEPS)) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- /* need to tag armature for cow updates, or else selection doesn't update */
- DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
- ob_prev = ob;
- }
- }
- CTX_DATA_END;
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
-
- return OPERATOR_FINISHED;
+ int action = RNA_enum_get(op->ptr, "action");
+
+ Scene *scene = CTX_data_scene(C);
+ int multipaint = scene->toolsettings->multipaint;
+
+ if (action == SEL_TOGGLE) {
+ action = CTX_DATA_COUNT(C, selected_pose_bones) ? SEL_DESELECT : SEL_SELECT;
+ }
+
+ Object *ob_prev = NULL;
+
+ /* 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);
+
+ if (ob_prev != ob) {
+ /* weightpaint or mask modifiers need depsgraph updates */
+ if (multipaint || (arm->flag & ARM_HAS_VIZ_DEPS)) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ /* need to tag armature for cow updates, or else selection doesn't update */
+ DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
+ ob_prev = ob;
+ }
+ }
+ CTX_DATA_END;
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
+
+ return OPERATOR_FINISHED;
}
void POSE_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All";
- ot->idname = "POSE_OT_select_all";
- ot->description = "Toggle selection status of all bones";
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->idname = "POSE_OT_select_all";
+ ot->description = "Toggle selection status of all bones";
- /* api callbacks */
- ot->exec = pose_de_select_all_exec;
- ot->poll = ED_operator_posemode;
+ /* api callbacks */
+ ot->exec = pose_de_select_all_exec;
+ ot->poll = ED_operator_posemode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_select_all(ot);
+ WM_operator_properties_select_all(ot);
}
/* -------------------------------------- */
static int pose_select_parent_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bArmature *arm = (bArmature *)ob->data;
- bPoseChannel *pchan, *parent;
-
- /* Determine if there is an active bone */
- pchan = CTX_data_active_pose_bone(C);
- if (pchan) {
- parent = pchan->parent;
- if ((parent) && !(parent->bone->flag & (BONE_HIDDEN_P | BONE_UNSELECTABLE))) {
- parent->bone->flag |= BONE_SELECTED;
- arm->act_bone = parent->bone;
- }
- else {
- return OPERATOR_CANCELLED;
- }
- }
- else {
- return OPERATOR_CANCELLED;
- }
-
- ED_pose_bone_select_tag_update(ob);
- return OPERATOR_FINISHED;
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ bArmature *arm = (bArmature *)ob->data;
+ bPoseChannel *pchan, *parent;
+
+ /* Determine if there is an active bone */
+ pchan = CTX_data_active_pose_bone(C);
+ if (pchan) {
+ parent = pchan->parent;
+ if ((parent) && !(parent->bone->flag & (BONE_HIDDEN_P | BONE_UNSELECTABLE))) {
+ parent->bone->flag |= BONE_SELECTED;
+ arm->act_bone = parent->bone;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_pose_bone_select_tag_update(ob);
+ return OPERATOR_FINISHED;
}
void POSE_OT_select_parent(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Parent Bone";
- ot->idname = "POSE_OT_select_parent";
- ot->description = "Select bones that are parents of the currently selected bones";
+ /* identifiers */
+ ot->name = "Select Parent Bone";
+ ot->idname = "POSE_OT_select_parent";
+ ot->description = "Select bones that are parents of the currently selected bones";
- /* api callbacks */
- ot->exec = pose_select_parent_exec;
- ot->poll = ED_operator_posemode;
+ /* api callbacks */
+ ot->exec = pose_select_parent_exec;
+ ot->poll = ED_operator_posemode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* -------------------------------------- */
static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op))
{
- bConstraint *con;
- int found = 0;
-
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
- {
- if (pchan->bone->flag & BONE_SELECTED) {
- for (con = pchan->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- Object *ob = ct->tar;
-
- /* Any armature that is also in pose mode should be selected. */
- if ((ct->subtarget[0] != '\0') &&
- (ob != NULL) &&
- (ob->type == OB_ARMATURE) &&
- (ob->mode == OB_MODE_POSE))
- {
- bPoseChannel *pchanc = BKE_pose_channel_find_name(ob->pose, ct->subtarget);
- if ((pchanc) && !(pchanc->bone->flag & BONE_UNSELECTABLE)) {
- pchanc->bone->flag |= BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL;
- ED_pose_bone_select_tag_update(ob);
- found = 1;
- }
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
- }
- }
- }
- }
- CTX_DATA_END;
-
- if (!found)
- return OPERATOR_CANCELLED;
-
- return OPERATOR_FINISHED;
+ bConstraint *con;
+ int found = 0;
+
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones) {
+ if (pchan->bone->flag & BONE_SELECTED) {
+ for (con = pchan->constraints.first; con; con = con->next) {
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct = targets.first; ct; ct = ct->next) {
+ Object *ob = ct->tar;
+
+ /* Any armature that is also in pose mode should be selected. */
+ if ((ct->subtarget[0] != '\0') && (ob != NULL) && (ob->type == OB_ARMATURE) &&
+ (ob->mode == OB_MODE_POSE)) {
+ bPoseChannel *pchanc = BKE_pose_channel_find_name(ob->pose, ct->subtarget);
+ if ((pchanc) && !(pchanc->bone->flag & BONE_UNSELECTABLE)) {
+ pchanc->bone->flag |= BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL;
+ ED_pose_bone_select_tag_update(ob);
+ found = 1;
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 1);
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ if (!found)
+ return OPERATOR_CANCELLED;
+
+ return OPERATOR_FINISHED;
}
void POSE_OT_select_constraint_target(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Constraint Target";
- ot->idname = "POSE_OT_select_constraint_target";
- ot->description = "Select bones used as targets for the currently selected bones";
+ /* identifiers */
+ ot->name = "Select Constraint Target";
+ ot->idname = "POSE_OT_select_constraint_target";
+ ot->description = "Select bones used as targets for the currently selected bones";
- /* api callbacks */
- ot->exec = pose_select_constraint_target_exec;
- ot->poll = ED_operator_posemode;
+ /* api callbacks */
+ ot->exec = pose_select_constraint_target_exec;
+ ot->poll = ED_operator_posemode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* -------------------------------------- */
@@ -578,444 +593,457 @@ void POSE_OT_select_constraint_target(wmOperatorType *ot)
* selected we then keep the non-active objects untouched (selected/unselected). */
static int pose_select_hierarchy_exec(bContext *C, wmOperator *op)
{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bArmature *arm = ob->data;
- bPoseChannel *pchan_act;
- int direction = RNA_enum_get(op->ptr, "direction");
- const bool add_to_sel = RNA_boolean_get(op->ptr, "extend");
- bool changed = false;
-
- pchan_act = BKE_pose_channel_active(ob);
- if (pchan_act == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- if (direction == BONE_SELECT_PARENT) {
- if (pchan_act->parent) {
- Bone *bone_parent;
- bone_parent = pchan_act->parent->bone;
-
- if (PBONE_SELECTABLE(arm, bone_parent)) {
- if (!add_to_sel) {
- pchan_act->bone->flag &= ~BONE_SELECTED;
- }
- bone_parent->flag |= BONE_SELECTED;
- arm->act_bone = bone_parent;
-
- changed = true;
- }
- }
- }
- else { /* direction == BONE_SELECT_CHILD */
- bPoseChannel *pchan_iter;
- Bone *bone_child = NULL;
- int pass;
-
- /* first pass, only connected bones (the logical direct child) */
- for (pass = 0; pass < 2 && (bone_child == NULL); pass++) {
- for (pchan_iter = ob->pose->chanbase.first; pchan_iter; pchan_iter = pchan_iter->next) {
- /* possible we have multiple children, some invisible */
- if (PBONE_SELECTABLE(arm, pchan_iter->bone)) {
- if (pchan_iter->parent == pchan_act) {
- if ((pass == 1) || (pchan_iter->bone->flag & BONE_CONNECTED)) {
- bone_child = pchan_iter->bone;
- break;
- }
- }
- }
- }
- }
-
- if (bone_child) {
- arm->act_bone = bone_child;
-
- if (!add_to_sel) {
- pchan_act->bone->flag &= ~BONE_SELECTED;
- }
- bone_child->flag |= BONE_SELECTED;
-
- changed = true;
- }
- }
-
- if (changed == false) {
- return OPERATOR_CANCELLED;
- }
-
- ED_pose_bone_select_tag_update(ob);
-
- return OPERATOR_FINISHED;
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ bArmature *arm = ob->data;
+ bPoseChannel *pchan_act;
+ int direction = RNA_enum_get(op->ptr, "direction");
+ const bool add_to_sel = RNA_boolean_get(op->ptr, "extend");
+ bool changed = false;
+
+ pchan_act = BKE_pose_channel_active(ob);
+ if (pchan_act == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (direction == BONE_SELECT_PARENT) {
+ if (pchan_act->parent) {
+ Bone *bone_parent;
+ bone_parent = pchan_act->parent->bone;
+
+ if (PBONE_SELECTABLE(arm, bone_parent)) {
+ if (!add_to_sel) {
+ pchan_act->bone->flag &= ~BONE_SELECTED;
+ }
+ bone_parent->flag |= BONE_SELECTED;
+ arm->act_bone = bone_parent;
+
+ changed = true;
+ }
+ }
+ }
+ else { /* direction == BONE_SELECT_CHILD */
+ bPoseChannel *pchan_iter;
+ Bone *bone_child = NULL;
+ int pass;
+
+ /* first pass, only connected bones (the logical direct child) */
+ for (pass = 0; pass < 2 && (bone_child == NULL); pass++) {
+ for (pchan_iter = ob->pose->chanbase.first; pchan_iter; pchan_iter = pchan_iter->next) {
+ /* possible we have multiple children, some invisible */
+ if (PBONE_SELECTABLE(arm, pchan_iter->bone)) {
+ if (pchan_iter->parent == pchan_act) {
+ if ((pass == 1) || (pchan_iter->bone->flag & BONE_CONNECTED)) {
+ bone_child = pchan_iter->bone;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (bone_child) {
+ arm->act_bone = bone_child;
+
+ if (!add_to_sel) {
+ pchan_act->bone->flag &= ~BONE_SELECTED;
+ }
+ bone_child->flag |= BONE_SELECTED;
+
+ changed = true;
+ }
+ }
+
+ if (changed == false) {
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_pose_bone_select_tag_update(ob);
+
+ return OPERATOR_FINISHED;
}
void POSE_OT_select_hierarchy(wmOperatorType *ot)
{
- static const EnumPropertyItem direction_items[] = {
- {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
- {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Select Hierarchy";
- ot->idname = "POSE_OT_select_hierarchy";
- ot->description = "Select immediate parent/children of selected bones";
-
- /* api callbacks */
- ot->exec = pose_select_hierarchy_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- ot->prop = RNA_def_enum(ot->srna, "direction", direction_items, BONE_SELECT_PARENT, "Direction", "");
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+ static const EnumPropertyItem direction_items[] = {
+ {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
+ {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Select Hierarchy";
+ ot->idname = "POSE_OT_select_hierarchy";
+ ot->description = "Select immediate parent/children of selected bones";
+
+ /* api callbacks */
+ ot->exec = pose_select_hierarchy_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ ot->prop = RNA_def_enum(
+ ot->srna, "direction", direction_items, BONE_SELECT_PARENT, "Direction", "");
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
/* -------------------------------------- */
/* modes for select same */
typedef enum ePose_SelectSame_Mode {
- POSE_SEL_SAME_LAYER = 0,
- POSE_SEL_SAME_GROUP = 1,
- POSE_SEL_SAME_KEYINGSET = 2,
+ POSE_SEL_SAME_LAYER = 0,
+ POSE_SEL_SAME_GROUP = 1,
+ POSE_SEL_SAME_KEYINGSET = 2,
} ePose_SelectSame_Mode;
static bool pose_select_same_group(bContext *C, bool extend)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- bool *group_flags_array;
- bool *group_flags = NULL;
- int groups_len = 0;
- bool changed = false, tagged = false;
- Object *ob_prev = NULL;
- uint ob_index;
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len, OB_MODE_POSE);
- for (ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = BKE_object_pose_armature_get(objects[ob_index]);
- bArmature *arm = (ob) ? ob->data : NULL;
- bPose *pose = (ob) ? ob->pose : NULL;
-
- /* Sanity checks. */
- if (ELEM(NULL, ob, pose, arm)) {
- continue;
- }
-
- ob->id.tag &= ~LIB_TAG_DOIT;
- groups_len = MAX2(groups_len, BLI_listbase_count(&pose->agroups));
- }
-
- /* Nothing to do here. */
- if (groups_len == 0) {
- MEM_freeN(objects);
- return false;
- }
-
- /* alloc a small array to keep track of the groups to use
- * - each cell stores on/off state for whether group should be used
- * - size is (groups_len + 1), since (index = 0) is used for no-group
- */
- groups_len++;
- group_flags_array = MEM_callocN(objects_len * groups_len * sizeof(bool), "pose_select_same_group");
-
- group_flags = NULL;
- ob_index = -1;
- ob_prev = NULL;
- CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object, *ob)
- {
- if (ob != ob_prev) {
- ob_index++;
- group_flags = group_flags_array + (ob_index * groups_len);
- ob_prev = ob;
- }
-
- /* keep track of group as group to use later? */
- if (pchan->bone->flag & BONE_SELECTED) {
- group_flags[pchan->agrp_index] = true;
- tagged = true;
- }
-
- /* deselect all bones before selecting new ones? */
- if ((extend == false) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
- pchan->bone->flag &= ~BONE_SELECTED;
- }
- }
- CTX_DATA_END;
-
- /* small optimization: only loop through bones a second time if there are any groups tagged */
- if (tagged) {
- group_flags = NULL;
- ob_index = -1;
- ob_prev = NULL;
- /* only if group matches (and is not selected or current bone) */
- CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob)
- {
- if (ob != ob_prev) {
- ob_index++;
- group_flags = group_flags_array + (ob_index * groups_len);
- ob_prev = ob;
- }
-
- if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
- /* check if the group used by this bone is counted */
- if (group_flags[pchan->agrp_index]) {
- pchan->bone->flag |= BONE_SELECTED;
- ob->id.tag |= LIB_TAG_DOIT;
- }
- }
- }
- CTX_DATA_END;
- }
-
- for (ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- if (ob->id.tag & LIB_TAG_DOIT) {
- ED_pose_bone_select_tag_update(ob);
- changed = true;
- }
- }
-
- /* Cleanup. */
- MEM_freeN(group_flags_array);
- MEM_freeN(objects);
-
- return changed;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ bool *group_flags_array;
+ bool *group_flags = NULL;
+ int groups_len = 0;
+ bool changed = false, tagged = false;
+ Object *ob_prev = NULL;
+ uint ob_index;
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len, OB_MODE_POSE);
+ for (ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = BKE_object_pose_armature_get(objects[ob_index]);
+ bArmature *arm = (ob) ? ob->data : NULL;
+ bPose *pose = (ob) ? ob->pose : NULL;
+
+ /* Sanity checks. */
+ if (ELEM(NULL, ob, pose, arm)) {
+ continue;
+ }
+
+ ob->id.tag &= ~LIB_TAG_DOIT;
+ groups_len = MAX2(groups_len, BLI_listbase_count(&pose->agroups));
+ }
+
+ /* Nothing to do here. */
+ if (groups_len == 0) {
+ MEM_freeN(objects);
+ return false;
+ }
+
+ /* alloc a small array to keep track of the groups to use
+ * - each cell stores on/off state for whether group should be used
+ * - size is (groups_len + 1), since (index = 0) is used for no-group
+ */
+ groups_len++;
+ group_flags_array = MEM_callocN(objects_len * groups_len * sizeof(bool),
+ "pose_select_same_group");
+
+ group_flags = NULL;
+ ob_index = -1;
+ ob_prev = NULL;
+ CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, pchan, visible_pose_bones, Object, *ob)
+ {
+ if (ob != ob_prev) {
+ ob_index++;
+ group_flags = group_flags_array + (ob_index * groups_len);
+ ob_prev = ob;
+ }
+
+ /* keep track of group as group to use later? */
+ if (pchan->bone->flag & BONE_SELECTED) {
+ group_flags[pchan->agrp_index] = true;
+ tagged = true;
+ }
+
+ /* deselect all bones before selecting new ones? */
+ if ((extend == false) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
+ pchan->bone->flag &= ~BONE_SELECTED;
+ }
+ }
+ CTX_DATA_END;
+
+ /* small optimization: only loop through bones a second time if there are any groups tagged */
+ if (tagged) {
+ group_flags = NULL;
+ ob_index = -1;
+ ob_prev = NULL;
+ /* only if group matches (and is not selected or current bone) */
+ CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob)
+ {
+ if (ob != ob_prev) {
+ ob_index++;
+ group_flags = group_flags_array + (ob_index * groups_len);
+ ob_prev = ob;
+ }
+
+ if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
+ /* check if the group used by this bone is counted */
+ if (group_flags[pchan->agrp_index]) {
+ pchan->bone->flag |= BONE_SELECTED;
+ ob->id.tag |= LIB_TAG_DOIT;
+ }
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ for (ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ if (ob->id.tag & LIB_TAG_DOIT) {
+ ED_pose_bone_select_tag_update(ob);
+ changed = true;
+ }
+ }
+
+ /* Cleanup. */
+ MEM_freeN(group_flags_array);
+ MEM_freeN(objects);
+
+ return changed;
}
static bool pose_select_same_layer(bContext *C, bool extend)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- int *layers_array, *layers = NULL;
- Object *ob_prev = NULL;
- uint ob_index;
- bool changed = false;
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len, OB_MODE_POSE);
- for (ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- ob->id.tag &= ~LIB_TAG_DOIT;
- }
-
- layers_array = MEM_callocN(objects_len * sizeof(*layers_array), "pose_select_same_layer");
-
- /* Figure out what bones are selected. */
- layers = NULL;
- ob_prev = NULL;
- ob_index = -1;
- CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob)
- {
- if (ob != ob_prev) {
- layers = &layers_array[++ob_index];
- ob_prev = ob;
- }
-
- /* Keep track of layers to use later? */
- if (pchan->bone->flag & BONE_SELECTED)
- *layers |= pchan->bone->layer;
-
- /* Deselect all bones before selecting new ones? */
- if ((extend == false) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0)
- pchan->bone->flag &= ~BONE_SELECTED;
- }
- CTX_DATA_END;
-
- bool any_layer = false;
- for (ob_index = 0; ob_index < objects_len; ob_index++) {
- if (layers_array[ob_index]) {
- any_layer = true;
- break;
- }
- }
-
- if (!any_layer) {
- goto cleanup;
- }
-
- /* Select bones that are on same layers as layers flag. */
- ob_prev = NULL;
- ob_index = -1;
- CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob)
- {
- if (ob != ob_prev) {
- layers = &layers_array[++ob_index];
- ob_prev = ob;
- }
-
- /* if bone is on a suitable layer, and the bone can have its selection changed, select it */
- if ((*layers & pchan->bone->layer) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
- pchan->bone->flag |= BONE_SELECTED;
- ob->id.tag |= LIB_TAG_DOIT;
- }
- }
- CTX_DATA_END;
-
- for (ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- if (ob->id.tag & LIB_TAG_DOIT) {
- ED_pose_bone_select_tag_update(ob);
- changed = true;
- }
- }
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ int *layers_array, *layers = NULL;
+ Object *ob_prev = NULL;
+ uint ob_index;
+ bool changed = false;
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len, OB_MODE_POSE);
+ for (ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ ob->id.tag &= ~LIB_TAG_DOIT;
+ }
+
+ layers_array = MEM_callocN(objects_len * sizeof(*layers_array), "pose_select_same_layer");
+
+ /* Figure out what bones are selected. */
+ layers = NULL;
+ ob_prev = NULL;
+ ob_index = -1;
+ CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob)
+ {
+ if (ob != ob_prev) {
+ layers = &layers_array[++ob_index];
+ ob_prev = ob;
+ }
+
+ /* Keep track of layers to use later? */
+ if (pchan->bone->flag & BONE_SELECTED)
+ *layers |= pchan->bone->layer;
+
+ /* Deselect all bones before selecting new ones? */
+ if ((extend == false) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0)
+ pchan->bone->flag &= ~BONE_SELECTED;
+ }
+ CTX_DATA_END;
+
+ bool any_layer = false;
+ for (ob_index = 0; ob_index < objects_len; ob_index++) {
+ if (layers_array[ob_index]) {
+ any_layer = true;
+ break;
+ }
+ }
+
+ if (!any_layer) {
+ goto cleanup;
+ }
+
+ /* Select bones that are on same layers as layers flag. */
+ ob_prev = NULL;
+ ob_index = -1;
+ CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob)
+ {
+ if (ob != ob_prev) {
+ layers = &layers_array[++ob_index];
+ ob_prev = ob;
+ }
+
+ /* if bone is on a suitable layer, and the bone can have its selection changed, select it */
+ if ((*layers & pchan->bone->layer) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
+ pchan->bone->flag |= BONE_SELECTED;
+ ob->id.tag |= LIB_TAG_DOIT;
+ }
+ }
+ CTX_DATA_END;
+
+ for (ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ if (ob->id.tag & LIB_TAG_DOIT) {
+ ED_pose_bone_select_tag_update(ob);
+ changed = true;
+ }
+ }
cleanup:
- /* Cleanup. */
- MEM_freeN(layers_array);
- MEM_freeN(objects);
+ /* Cleanup. */
+ MEM_freeN(layers_array);
+ MEM_freeN(objects);
- return changed;
+ return changed;
}
static bool pose_select_same_keyingset(bContext *C, ReportList *reports, bool extend)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- bool changed_multi = false;
- KeyingSet *ks = ANIM_scene_get_active_keyingset(CTX_data_scene(C));
- KS_Path *ksp;
-
- /* sanity checks: validate Keying Set and object */
- if (ks == NULL) {
- BKE_report(reports, RPT_ERROR, "No active Keying Set to use");
- return false;
- }
- else if (ANIM_validate_keyingset(C, NULL, ks) != 0) {
- if (ks->paths.first == NULL) {
- if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
- BKE_report(reports, RPT_ERROR,
- "Use another Keying Set, as the active one depends on the currently "
- "selected items or cannot find any targets due to unsuitable context");
- }
- else {
- BKE_report(reports, RPT_ERROR, "Keying Set does not contain any paths");
- }
- }
- return false;
- }
-
- /* if not extending selection, deselect all selected first */
- if (extend == false) {
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
- {
- if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0)
- pchan->bone->flag &= ~BONE_SELECTED;
- }
- CTX_DATA_END;
- }
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len, OB_MODE_POSE);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = BKE_object_pose_armature_get(objects[ob_index]);
- bArmature *arm = (ob) ? ob->data : NULL;
- bPose *pose = (ob) ? ob->pose : NULL;
- bool changed = false;
-
- /* Sanity checks. */
- if (ELEM(NULL, ob, pose, arm)) {
- continue;
- }
-
- /* iterate over elements in the Keying Set, setting selection depending on whether
- * that bone is visible or not...
- */
- for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
- /* only items related to this object will be relevant */
- if ((ksp->id == &ob->id) && (ksp->rna_path != NULL)) {
- if (strstr(ksp->rna_path, "bones")) {
- char *boneName = BLI_str_quoted_substrN(ksp->rna_path, "bones[");
-
- if (boneName) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(pose, boneName);
-
- if (pchan) {
- /* select if bone is visible and can be affected */
- if (PBONE_SELECTABLE(arm, pchan->bone)) {
- pchan->bone->flag |= BONE_SELECTED;
- changed = true;
- }
- }
-
- /* free temp memory */
- MEM_freeN(boneName);
- }
- }
- }
- }
-
- if (changed || !extend) {
- ED_pose_bone_select_tag_update(ob);
- changed_multi = true;
- }
- }
- MEM_freeN(objects);
-
- return changed_multi;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ bool changed_multi = false;
+ KeyingSet *ks = ANIM_scene_get_active_keyingset(CTX_data_scene(C));
+ KS_Path *ksp;
+
+ /* sanity checks: validate Keying Set and object */
+ if (ks == NULL) {
+ BKE_report(reports, RPT_ERROR, "No active Keying Set to use");
+ return false;
+ }
+ else if (ANIM_validate_keyingset(C, NULL, ks) != 0) {
+ if (ks->paths.first == NULL) {
+ if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
+ BKE_report(reports,
+ RPT_ERROR,
+ "Use another Keying Set, as the active one depends on the currently "
+ "selected items or cannot find any targets due to unsuitable context");
+ }
+ else {
+ BKE_report(reports, RPT_ERROR, "Keying Set does not contain any paths");
+ }
+ }
+ return false;
+ }
+
+ /* if not extending selection, deselect all selected first */
+ if (extend == false) {
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones) {
+ if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0)
+ pchan->bone->flag &= ~BONE_SELECTED;
+ }
+ CTX_DATA_END;
+ }
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len, OB_MODE_POSE);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = BKE_object_pose_armature_get(objects[ob_index]);
+ bArmature *arm = (ob) ? ob->data : NULL;
+ bPose *pose = (ob) ? ob->pose : NULL;
+ bool changed = false;
+
+ /* Sanity checks. */
+ if (ELEM(NULL, ob, pose, arm)) {
+ continue;
+ }
+
+ /* iterate over elements in the Keying Set, setting selection depending on whether
+ * that bone is visible or not...
+ */
+ for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
+ /* only items related to this object will be relevant */
+ if ((ksp->id == &ob->id) && (ksp->rna_path != NULL)) {
+ if (strstr(ksp->rna_path, "bones")) {
+ char *boneName = BLI_str_quoted_substrN(ksp->rna_path, "bones[");
+
+ if (boneName) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(pose, boneName);
+
+ if (pchan) {
+ /* select if bone is visible and can be affected */
+ if (PBONE_SELECTABLE(arm, pchan->bone)) {
+ pchan->bone->flag |= BONE_SELECTED;
+ changed = true;
+ }
+ }
+
+ /* free temp memory */
+ MEM_freeN(boneName);
+ }
+ }
+ }
+ }
+
+ if (changed || !extend) {
+ ED_pose_bone_select_tag_update(ob);
+ changed_multi = true;
+ }
+ }
+ MEM_freeN(objects);
+
+ return changed_multi;
}
static int pose_select_grouped_exec(bContext *C, wmOperator *op)
{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- const ePose_SelectSame_Mode type = RNA_enum_get(op->ptr, "type");
- const bool extend = RNA_boolean_get(op->ptr, "extend");
- bool changed = false;
-
- /* sanity check */
- if (ob->pose == NULL)
- return OPERATOR_CANCELLED;
-
- /* selection types */
- switch (type) {
- case POSE_SEL_SAME_LAYER: /* layer */
- changed = pose_select_same_layer(C, extend);
- break;
-
- case POSE_SEL_SAME_GROUP: /* group */
- changed = pose_select_same_group(C, extend);
- break;
-
- case POSE_SEL_SAME_KEYINGSET: /* Keying Set */
- changed = pose_select_same_keyingset(C, op->reports, extend);
- break;
-
- default:
- printf("pose_select_grouped() - Unknown selection type %u\n", type);
- break;
- }
-
- /* report done status */
- if (changed)
- return OPERATOR_FINISHED;
- else
- return OPERATOR_CANCELLED;
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ const ePose_SelectSame_Mode type = RNA_enum_get(op->ptr, "type");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ bool changed = false;
+
+ /* sanity check */
+ if (ob->pose == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* selection types */
+ switch (type) {
+ case POSE_SEL_SAME_LAYER: /* layer */
+ changed = pose_select_same_layer(C, extend);
+ break;
+
+ case POSE_SEL_SAME_GROUP: /* group */
+ changed = pose_select_same_group(C, extend);
+ break;
+
+ case POSE_SEL_SAME_KEYINGSET: /* Keying Set */
+ changed = pose_select_same_keyingset(C, op->reports, extend);
+ break;
+
+ default:
+ printf("pose_select_grouped() - Unknown selection type %u\n", type);
+ break;
+ }
+
+ /* report done status */
+ if (changed)
+ return OPERATOR_FINISHED;
+ else
+ return OPERATOR_CANCELLED;
}
void POSE_OT_select_grouped(wmOperatorType *ot)
{
- static const EnumPropertyItem prop_select_grouped_types[] = {
- {POSE_SEL_SAME_LAYER, "LAYER", 0, "Layer", "Shared layers"},
- {POSE_SEL_SAME_GROUP, "GROUP", 0, "Group", "Shared group"},
- {POSE_SEL_SAME_KEYINGSET, "KEYINGSET", 0, "Keying Set", "All bones affected by active Keying Set"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Select Grouped";
- ot->description = "Select all visible bones grouped by similar properties";
- ot->idname = "POSE_OT_select_grouped";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = pose_select_grouped_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
- ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
+ static const EnumPropertyItem prop_select_grouped_types[] = {
+ {POSE_SEL_SAME_LAYER, "LAYER", 0, "Layer", "Shared layers"},
+ {POSE_SEL_SAME_GROUP, "GROUP", 0, "Group", "Shared group"},
+ {POSE_SEL_SAME_KEYINGSET,
+ "KEYINGSET",
+ 0,
+ "Keying Set",
+ "All bones affected by active Keying Set"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Select Grouped";
+ ot->description = "Select all visible bones grouped by similar properties";
+ ot->idname = "POSE_OT_select_grouped";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = pose_select_grouped_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "extend",
+ false,
+ "Extend",
+ "Extend selection instead of deselecting everything first");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
}
/* -------------------------------------- */
@@ -1025,85 +1053,87 @@ void POSE_OT_select_grouped(wmOperatorType *ot)
*/
static int pose_select_mirror_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob_active = CTX_data_active_object(C);
-
- const bool is_weight_paint = (ob_active->mode & OB_MODE_WEIGHT_PAINT) != 0;
- const bool active_only = RNA_boolean_get(op->ptr, "only_active");
- const bool extend = RNA_boolean_get(op->ptr, "extend");
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len, OB_MODE_POSE);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- bArmature *arm = ob->data;
- bPoseChannel *pchan, *pchan_mirror_act = NULL;
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- const int flag = (pchan->bone->flag & BONE_SELECTED);
- PBONE_PREV_FLAG_SET(pchan, flag);
- }
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (PBONE_SELECTABLE(arm, pchan->bone)) {
- bPoseChannel *pchan_mirror;
- int flag_new = extend ? PBONE_PREV_FLAG_GET(pchan) : 0;
-
- if ((pchan_mirror = BKE_pose_channel_get_mirrored(ob->pose, pchan->name)) &&
- (PBONE_VISIBLE(arm, pchan_mirror->bone)))
- {
- const int flag_mirror = PBONE_PREV_FLAG_GET(pchan_mirror);
- flag_new |= flag_mirror;
-
- if (pchan->bone == arm->act_bone) {
- pchan_mirror_act = pchan_mirror;
- }
-
- /* Skip all but the active or its mirror. */
- if (active_only && !ELEM(arm->act_bone, pchan->bone, pchan_mirror->bone)) {
- continue;
- }
- }
-
- pchan->bone->flag = (pchan->bone->flag & ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) | flag_new;
- }
- }
-
- if (pchan_mirror_act) {
- arm->act_bone = pchan_mirror_act->bone;
-
- /* In weightpaint we select the associated vertex group too. */
- if (is_weight_paint) {
- ED_vgroup_select_by_name(ob, pchan_mirror_act->name);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
- /* Need to tag armature for cow updates, or else selection doesn't update. */
- DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob_active = CTX_data_active_object(C);
+
+ const bool is_weight_paint = (ob_active->mode & OB_MODE_WEIGHT_PAINT) != 0;
+ const bool active_only = RNA_boolean_get(op->ptr, "only_active");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len, OB_MODE_POSE);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ bArmature *arm = ob->data;
+ bPoseChannel *pchan, *pchan_mirror_act = NULL;
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ const int flag = (pchan->bone->flag & BONE_SELECTED);
+ PBONE_PREV_FLAG_SET(pchan, flag);
+ }
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (PBONE_SELECTABLE(arm, pchan->bone)) {
+ bPoseChannel *pchan_mirror;
+ int flag_new = extend ? PBONE_PREV_FLAG_GET(pchan) : 0;
+
+ if ((pchan_mirror = BKE_pose_channel_get_mirrored(ob->pose, pchan->name)) &&
+ (PBONE_VISIBLE(arm, pchan_mirror->bone))) {
+ const int flag_mirror = PBONE_PREV_FLAG_GET(pchan_mirror);
+ flag_new |= flag_mirror;
+
+ if (pchan->bone == arm->act_bone) {
+ pchan_mirror_act = pchan_mirror;
+ }
+
+ /* Skip all but the active or its mirror. */
+ if (active_only && !ELEM(arm->act_bone, pchan->bone, pchan_mirror->bone)) {
+ continue;
+ }
+ }
+
+ pchan->bone->flag = (pchan->bone->flag & ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) |
+ flag_new;
+ }
+ }
+
+ if (pchan_mirror_act) {
+ arm->act_bone = pchan_mirror_act->bone;
+
+ /* In weightpaint we select the associated vertex group too. */
+ if (is_weight_paint) {
+ ED_vgroup_select_by_name(ob, pchan_mirror_act->name);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+
+ /* Need to tag armature for cow updates, or else selection doesn't update. */
+ DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void POSE_OT_select_mirror(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Flip Active/Selected Bone";
- ot->idname = "POSE_OT_select_mirror";
- ot->description = "Mirror the bone selection";
-
- /* api callbacks */
- ot->exec = pose_select_mirror_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "only_active", false, "Active Only", "Only operate on the active bone");
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+ /* identifiers */
+ ot->name = "Flip Active/Selected Bone";
+ ot->idname = "POSE_OT_select_mirror";
+ ot->description = "Mirror the bone selection";
+
+ /* api callbacks */
+ ot->exec = pose_select_mirror_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(
+ ot->srna, "only_active", false, "Active Only", "Only operate on the active bone");
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index 90de331b3e0..cb9cfa64181 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -81,102 +81,104 @@
/* Temporary data shared between these operators */
typedef struct tPoseSlideOp {
- /** current scene */
- Scene *scene;
- /** area that we're operating in (needed for modal()) */
- ScrArea *sa;
- /** region that we're operating in (needed for modal()) */
- ARegion *ar;
- /** len of the PoseSlideObject array. */
- uint objects_len;
-
- /** links between posechannels and f-curves for all the pose objects. */
- ListBase pfLinks;
- /** binary tree for quicker searching for keyframes (when applicable) */
- DLRBT_Tree keys;
-
- /** current frame number - global time */
- int cframe;
-
- /** frame before current frame (blend-from) - global time */
- int prevFrame;
- /** frame after current frame (blend-to) - global time */
- int nextFrame;
-
- /** sliding mode (ePoseSlide_Modes) */
- short mode;
- /** unused for now, but can later get used for storing runtime settings.... */
- short flag;
-
- /** which transforms/channels are affected (ePoseSlide_Channels) */
- short channels;
- /** axis-limits for transforms (ePoseSlide_AxisLock) */
- short axislock;
-
- /** 0-1 value for determining the influence of whatever is relevant */
- float percentage;
-
- /** numeric input */
- NumInput num;
-
- struct tPoseSlideObject *ob_data_array;
+ /** current scene */
+ Scene *scene;
+ /** area that we're operating in (needed for modal()) */
+ ScrArea *sa;
+ /** region that we're operating in (needed for modal()) */
+ ARegion *ar;
+ /** len of the PoseSlideObject array. */
+ uint objects_len;
+
+ /** links between posechannels and f-curves for all the pose objects. */
+ ListBase pfLinks;
+ /** binary tree for quicker searching for keyframes (when applicable) */
+ DLRBT_Tree keys;
+
+ /** current frame number - global time */
+ int cframe;
+
+ /** frame before current frame (blend-from) - global time */
+ int prevFrame;
+ /** frame after current frame (blend-to) - global time */
+ int nextFrame;
+
+ /** sliding mode (ePoseSlide_Modes) */
+ short mode;
+ /** unused for now, but can later get used for storing runtime settings.... */
+ short flag;
+
+ /** which transforms/channels are affected (ePoseSlide_Channels) */
+ short channels;
+ /** axis-limits for transforms (ePoseSlide_AxisLock) */
+ short axislock;
+
+ /** 0-1 value for determining the influence of whatever is relevant */
+ float percentage;
+
+ /** numeric input */
+ NumInput num;
+
+ struct tPoseSlideObject *ob_data_array;
} tPoseSlideOp;
typedef struct tPoseSlideObject {
- Object *ob; /* active object that Pose Info comes from */
- float prevFrameF; /* prevFrame, but in local action time (for F-Curve lookups to work) */
- float nextFrameF; /* nextFrame, but in local action time (for F-Curve lookups to work) */
- bool valid;
+ Object *ob; /* active object that Pose Info comes from */
+ float prevFrameF; /* prevFrame, but in local action time (for F-Curve lookups to work) */
+ float nextFrameF; /* nextFrame, but in local action time (for F-Curve lookups to work) */
+ bool valid;
} tPoseSlideObject;
/* Pose Sliding Modes */
typedef enum ePoseSlide_Modes {
- POSESLIDE_PUSH = 0, /* exaggerate the pose... */
- POSESLIDE_RELAX, /* soften the pose... */
- POSESLIDE_BREAKDOWN, /* slide between the endpoint poses, finding a 'soft' spot */
+ POSESLIDE_PUSH = 0, /* exaggerate the pose... */
+ POSESLIDE_RELAX, /* soften the pose... */
+ POSESLIDE_BREAKDOWN, /* slide between the endpoint poses, finding a 'soft' spot */
} ePoseSlide_Modes;
-
/* Transforms/Channels to Affect */
typedef enum ePoseSlide_Channels {
- PS_TFM_ALL = 0, /* All transforms and properties */
+ PS_TFM_ALL = 0, /* All transforms and properties */
- PS_TFM_LOC, /* Loc/Rot/Scale */
- PS_TFM_ROT,
- PS_TFM_SIZE,
+ PS_TFM_LOC, /* Loc/Rot/Scale */
+ PS_TFM_ROT,
+ PS_TFM_SIZE,
- PS_TFM_BBONE_SHAPE, /* Bendy Bones */
+ PS_TFM_BBONE_SHAPE, /* Bendy Bones */
- PS_TFM_PROPS, /* Custom Properties */
+ PS_TFM_PROPS, /* Custom Properties */
} ePoseSlide_Channels;
/* Property enum for ePoseSlide_Channels */
static const EnumPropertyItem prop_channels_types[] = {
- {PS_TFM_ALL, "ALL", 0, "All Properties",
- "All properties, including transforms, bendy bone shape, and custom properties"},
- {PS_TFM_LOC, "LOC", 0, "Location", "Location only"},
- {PS_TFM_ROT, "ROT", 0, "Rotation", "Rotation only"},
- {PS_TFM_SIZE, "SIZE", 0, "Scale", "Scale only"},
- {PS_TFM_BBONE_SHAPE, "BBONE", 0, "Bendy Bone", "Bendy Bone shape properties"},
- {PS_TFM_PROPS, "CUSTOM", 0, "Custom Properties", "Custom properties"},
- {0, NULL, 0, NULL, NULL},
+ {PS_TFM_ALL,
+ "ALL",
+ 0,
+ "All Properties",
+ "All properties, including transforms, bendy bone shape, and custom properties"},
+ {PS_TFM_LOC, "LOC", 0, "Location", "Location only"},
+ {PS_TFM_ROT, "ROT", 0, "Rotation", "Rotation only"},
+ {PS_TFM_SIZE, "SIZE", 0, "Scale", "Scale only"},
+ {PS_TFM_BBONE_SHAPE, "BBONE", 0, "Bendy Bone", "Bendy Bone shape properties"},
+ {PS_TFM_PROPS, "CUSTOM", 0, "Custom Properties", "Custom properties"},
+ {0, NULL, 0, NULL, NULL},
};
/* Axis Locks */
typedef enum ePoseSlide_AxisLock {
- PS_LOCK_X = (1 << 0),
- PS_LOCK_Y = (1 << 1),
- PS_LOCK_Z = (1 << 2),
+ PS_LOCK_X = (1 << 0),
+ PS_LOCK_Y = (1 << 1),
+ PS_LOCK_Z = (1 << 2),
} ePoseSlide_AxisLock;
/* Property enum for ePoseSlide_AxisLock */
static const EnumPropertyItem prop_axis_lock_types[] = {
- {0, "FREE", 0, "Free", "All axes are affected"},
- {PS_LOCK_X, "X", 0, "X", "Only X-axis transforms are affected"},
- {PS_LOCK_Y, "Y", 0, "Y", "Only Y-axis transforms are affected"},
- {PS_LOCK_Z, "Z", 0, "Z", "Only Z-axis transforms are affected"},
- /* TODO: Combinations? */
- {0, NULL, 0, NULL, NULL},
+ {0, "FREE", 0, "Free", "All axes are affected"},
+ {PS_LOCK_X, "X", 0, "X", "Only X-axis transforms are affected"},
+ {PS_LOCK_Y, "Y", 0, "Y", "Only Y-axis transforms are affected"},
+ {PS_LOCK_Z, "Z", 0, "Z", "Only Z-axis transforms are affected"},
+ /* TODO: Combinations? */
+ {0, NULL, 0, NULL, NULL},
};
/* ------------------------------------ */
@@ -184,99 +186,100 @@ static const EnumPropertyItem prop_axis_lock_types[] = {
/* operator init */
static int pose_slide_init(bContext *C, wmOperator *op, ePoseSlide_Modes mode)
{
- tPoseSlideOp *pso;
-
- /* init slide-op data */
- pso = op->customdata = MEM_callocN(sizeof(tPoseSlideOp), "tPoseSlideOp");
-
- /* 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->cframe = pso->scene->r.cfra;
- pso->mode = mode;
-
- /* set range info from property values - these may get overridden for the invoke() */
- pso->percentage = RNA_float_get(op->ptr, "percentage");
- pso->prevFrame = RNA_int_get(op->ptr, "prev_frame");
- pso->nextFrame = RNA_int_get(op->ptr, "next_frame");
-
- /* get the set of properties/axes that can be operated on */
- pso->channels = RNA_enum_get(op->ptr, "channels");
- pso->axislock = RNA_enum_get(op->ptr, "axis_lock");
-
- /* for each Pose-Channel which gets affected, get the F-Curves for that channel
- * and set the relevant transform flags... */
- poseAnim_mapping_get(C, &pso->pfLinks);
-
- Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(CTX_data_view_layer(C),
- CTX_wm_view3d(C),
- &pso->objects_len,
- OB_MODE_POSE);
- pso->ob_data_array = MEM_callocN(pso->objects_len * sizeof(tPoseSlideObject), "pose slide objects data");
-
- for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
- tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
- Object *ob_iter = poseAnim_object_get(objects[ob_index]);
-
- /* Ensure validity of the settings from the context. */
- if (ob_iter == NULL) {
- continue;
- }
-
- ob_data->ob = ob_iter;
- ob_data->valid = true;
-
- /* apply NLA mapping corrections so the frame lookups work */
- ob_data->prevFrameF = BKE_nla_tweakedit_remap(ob_data->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP);
- ob_data->nextFrameF = BKE_nla_tweakedit_remap(ob_data->ob->adt, pso->nextFrame, NLATIME_CONVERT_UNMAP);
-
- /* set depsgraph flags */
- /* make sure the lock is set OK, unlock can be accidentally saved? */
- ob_data->ob->pose->flag |= POSE_LOCKED;
- ob_data->ob->pose->flag &= ~POSE_DO_UNLOCK;
- }
- MEM_freeN(objects);
-
- /* do basic initialize of RB-BST used for finding keyframes, but leave the filling of it up
- * to the caller of this (usually only invoke() will do it, to make things more efficient).
- */
- BLI_dlrbTree_init(&pso->keys);
-
- /* initialise numeric input */
- initNumInput(&pso->num);
- pso->num.idx_max = 0; /* one axis */
- pso->num.val_flag[0] |= NUM_NO_NEGATIVE;
- pso->num.unit_type[0] = B_UNIT_NONE; /* percentages don't have any units... */
-
- /* return status is whether we've got all the data we were requested to get */
- return 1;
+ tPoseSlideOp *pso;
+
+ /* init slide-op data */
+ pso = op->customdata = MEM_callocN(sizeof(tPoseSlideOp), "tPoseSlideOp");
+
+ /* 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->cframe = pso->scene->r.cfra;
+ pso->mode = mode;
+
+ /* set range info from property values - these may get overridden for the invoke() */
+ pso->percentage = RNA_float_get(op->ptr, "percentage");
+ pso->prevFrame = RNA_int_get(op->ptr, "prev_frame");
+ pso->nextFrame = RNA_int_get(op->ptr, "next_frame");
+
+ /* get the set of properties/axes that can be operated on */
+ pso->channels = RNA_enum_get(op->ptr, "channels");
+ pso->axislock = RNA_enum_get(op->ptr, "axis_lock");
+
+ /* for each Pose-Channel which gets affected, get the F-Curves for that channel
+ * and set the relevant transform flags... */
+ poseAnim_mapping_get(C, &pso->pfLinks);
+
+ Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(
+ CTX_data_view_layer(C), CTX_wm_view3d(C), &pso->objects_len, OB_MODE_POSE);
+ pso->ob_data_array = MEM_callocN(pso->objects_len * sizeof(tPoseSlideObject),
+ "pose slide objects data");
+
+ for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
+ tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
+ Object *ob_iter = poseAnim_object_get(objects[ob_index]);
+
+ /* Ensure validity of the settings from the context. */
+ if (ob_iter == NULL) {
+ continue;
+ }
+
+ ob_data->ob = ob_iter;
+ ob_data->valid = true;
+
+ /* apply NLA mapping corrections so the frame lookups work */
+ ob_data->prevFrameF = BKE_nla_tweakedit_remap(
+ ob_data->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP);
+ ob_data->nextFrameF = BKE_nla_tweakedit_remap(
+ ob_data->ob->adt, pso->nextFrame, NLATIME_CONVERT_UNMAP);
+
+ /* set depsgraph flags */
+ /* make sure the lock is set OK, unlock can be accidentally saved? */
+ ob_data->ob->pose->flag |= POSE_LOCKED;
+ ob_data->ob->pose->flag &= ~POSE_DO_UNLOCK;
+ }
+ MEM_freeN(objects);
+
+ /* do basic initialize of RB-BST used for finding keyframes, but leave the filling of it up
+ * to the caller of this (usually only invoke() will do it, to make things more efficient).
+ */
+ BLI_dlrbTree_init(&pso->keys);
+
+ /* initialise numeric input */
+ initNumInput(&pso->num);
+ pso->num.idx_max = 0; /* one axis */
+ pso->num.val_flag[0] |= NUM_NO_NEGATIVE;
+ pso->num.unit_type[0] = B_UNIT_NONE; /* percentages don't have any units... */
+
+ /* return status is whether we've got all the data we were requested to get */
+ return 1;
}
/* exiting the operator - free data */
static void pose_slide_exit(wmOperator *op)
{
- tPoseSlideOp *pso = op->customdata;
+ tPoseSlideOp *pso = op->customdata;
- /* if data exists, clear its data and exit */
- if (pso) {
- /* free the temp pchan links and their data */
- poseAnim_mapping_free(&pso->pfLinks);
+ /* if data exists, clear its data and exit */
+ if (pso) {
+ /* free the temp pchan links and their data */
+ poseAnim_mapping_free(&pso->pfLinks);
- /* free RB-BST for keyframes (if it contained data) */
- BLI_dlrbTree_free(&pso->keys);
+ /* free RB-BST for keyframes (if it contained data) */
+ BLI_dlrbTree_free(&pso->keys);
- if (pso->ob_data_array != NULL) {
- MEM_freeN(pso->ob_data_array);
- }
+ if (pso->ob_data_array != NULL) {
+ MEM_freeN(pso->ob_data_array);
+ }
- /* free data itself */
- MEM_freeN(pso);
- }
+ /* free data itself */
+ MEM_freeN(pso);
+ }
- /* cleanup */
- op->customdata = NULL;
+ /* cleanup */
+ op->customdata = NULL;
}
/* ------------------------------------ */
@@ -284,438 +287,437 @@ static void pose_slide_exit(wmOperator *op)
/* helper for apply() / reset() - refresh the data */
static void pose_slide_refresh(bContext *C, tPoseSlideOp *pso)
{
- /* wrapper around the generic version, allowing us to add some custom stuff later still */
- for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
- tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
- if (ob_data->valid) {
- poseAnim_mapping_refresh(C, pso->scene, ob_data->ob);
- }
- }
+ /* wrapper around the generic version, allowing us to add some custom stuff later still */
+ for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
+ tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
+ if (ob_data->valid) {
+ poseAnim_mapping_refresh(C, pso->scene, ob_data->ob);
+ }
+ }
}
/**
* Although this lookup is not ideal, we won't be dealing with a lot of objects at a given time.
* But if it comes to that we can instead store prev/next frame in the #tPChanFCurveLink.
*/
-static bool pose_frame_range_from_object_get(tPoseSlideOp *pso, Object *ob, float *prevFrameF, float *nextFrameF)
+static bool pose_frame_range_from_object_get(tPoseSlideOp *pso,
+ Object *ob,
+ float *prevFrameF,
+ float *nextFrameF)
{
- for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
- tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
- Object *ob_iter = ob_data->ob;
-
- if (ob_iter == ob) {
- *prevFrameF = ob_data->prevFrameF;
- *nextFrameF = ob_data->nextFrameF;
- return true;
- }
- }
- *prevFrameF = *nextFrameF = 0.0f;
- return false;
+ for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
+ tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
+ Object *ob_iter = ob_data->ob;
+
+ if (ob_iter == ob) {
+ *prevFrameF = ob_data->prevFrameF;
+ *nextFrameF = ob_data->nextFrameF;
+ return true;
+ }
+ }
+ *prevFrameF = *nextFrameF = 0.0f;
+ return false;
}
/* helper for apply() - perform sliding for some value */
-static void pose_slide_apply_val(
- tPoseSlideOp *pso,
- FCurve *fcu,
- Object *ob,
- float *val)
+static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, Object *ob, float *val)
{
- float prevFrameF, nextFrameF;
- float cframe = (float)pso->cframe;
- float sVal, eVal;
- float w1, w2;
-
- pose_frame_range_from_object_get(pso, ob, &prevFrameF, &nextFrameF);
-
- /* get keyframe values for endpoint poses to blend with */
- /* previous/start */
- sVal = evaluate_fcurve(fcu, prevFrameF);
- /* next/end */
- eVal = evaluate_fcurve(fcu, nextFrameF);
-
- /* if both values are equal, don't do anything */
- if (IS_EQF(sVal, eVal)) {
- (*val) = sVal;
- return;
- }
-
- /* calculate the relative weights of the endpoints */
- if (pso->mode == POSESLIDE_BREAKDOWN) {
- /* get weights from the percentage control */
- w1 = pso->percentage; /* this must come second */
- w2 = 1.0f - w1; /* this must come first */
- }
- else {
- /* - these weights are derived from the relative distance of these
- * poses from the current frame
- * - they then get normalized so that they only sum up to 1
- */
- float wtot;
-
- w1 = cframe - (float)pso->prevFrame;
- w2 = (float)pso->nextFrame - cframe;
-
- wtot = w1 + w2;
- w1 = (w1 / wtot);
- w2 = (w2 / wtot);
- }
-
- /* depending on the mode, calculate the new value
- * - in all of these, the start+end values are multiplied by w2 and w1 (respectively),
- * since multiplication in another order would decrease the value the current frame is closer to
- */
- switch (pso->mode) {
- case POSESLIDE_PUSH: /* make the current pose more pronounced */
- {
- /* perform a weighted average here, favoring the middle pose
- * - numerator should be larger than denominator to 'expand' the result
- * - perform this weighting a number of times given by the percentage...
- */
- /* TODO: maybe a sensitivity ctrl on top of this is needed */
- int iters = (int)ceil(10.0f * pso->percentage);
-
- while (iters-- > 0) {
- (*val) = (-((sVal * w2) + (eVal * w1)) + ((*val) * 6.0f) ) / 5.0f;
- }
- break;
- }
- case POSESLIDE_RELAX: /* make the current pose more like its surrounding ones */
- {
- /* perform a weighted average here, favoring the middle pose
- * - numerator should be smaller than denominator to 'relax' the result
- * - perform this weighting a number of times given by the percentage...
- */
- /* TODO: maybe a sensitivity ctrl on top of this is needed */
- int iters = (int)ceil(10.0f * pso->percentage);
-
- while (iters-- > 0) {
- (*val) = ( ((sVal * w2) + (eVal * w1)) + ((*val) * 5.0f) ) / 6.0f;
- }
- break;
- }
- case POSESLIDE_BREAKDOWN: /* make the current pose slide around between the endpoints */
- {
- /* perform simple linear interpolation - coefficient for start must come from pso->percentage... */
- /* TODO: make this use some kind of spline interpolation instead? */
- (*val) = ((sVal * w2) + (eVal * w1));
- break;
- }
- }
+ float prevFrameF, nextFrameF;
+ float cframe = (float)pso->cframe;
+ float sVal, eVal;
+ float w1, w2;
+
+ pose_frame_range_from_object_get(pso, ob, &prevFrameF, &nextFrameF);
+
+ /* get keyframe values for endpoint poses to blend with */
+ /* previous/start */
+ sVal = evaluate_fcurve(fcu, prevFrameF);
+ /* next/end */
+ eVal = evaluate_fcurve(fcu, nextFrameF);
+
+ /* if both values are equal, don't do anything */
+ if (IS_EQF(sVal, eVal)) {
+ (*val) = sVal;
+ return;
+ }
+
+ /* calculate the relative weights of the endpoints */
+ if (pso->mode == POSESLIDE_BREAKDOWN) {
+ /* get weights from the percentage control */
+ w1 = pso->percentage; /* this must come second */
+ w2 = 1.0f - w1; /* this must come first */
+ }
+ else {
+ /* - these weights are derived from the relative distance of these
+ * poses from the current frame
+ * - they then get normalized so that they only sum up to 1
+ */
+ float wtot;
+
+ w1 = cframe - (float)pso->prevFrame;
+ w2 = (float)pso->nextFrame - cframe;
+
+ wtot = w1 + w2;
+ w1 = (w1 / wtot);
+ w2 = (w2 / wtot);
+ }
+
+ /* depending on the mode, calculate the new value
+ * - in all of these, the start+end values are multiplied by w2 and w1 (respectively),
+ * since multiplication in another order would decrease the value the current frame is closer to
+ */
+ switch (pso->mode) {
+ case POSESLIDE_PUSH: /* make the current pose more pronounced */
+ {
+ /* perform a weighted average here, favoring the middle pose
+ * - numerator should be larger than denominator to 'expand' the result
+ * - perform this weighting a number of times given by the percentage...
+ */
+ /* TODO: maybe a sensitivity ctrl on top of this is needed */
+ int iters = (int)ceil(10.0f * pso->percentage);
+
+ while (iters-- > 0) {
+ (*val) = (-((sVal * w2) + (eVal * w1)) + ((*val) * 6.0f)) / 5.0f;
+ }
+ break;
+ }
+ case POSESLIDE_RELAX: /* make the current pose more like its surrounding ones */
+ {
+ /* perform a weighted average here, favoring the middle pose
+ * - numerator should be smaller than denominator to 'relax' the result
+ * - perform this weighting a number of times given by the percentage...
+ */
+ /* TODO: maybe a sensitivity ctrl on top of this is needed */
+ int iters = (int)ceil(10.0f * pso->percentage);
+
+ while (iters-- > 0) {
+ (*val) = (((sVal * w2) + (eVal * w1)) + ((*val) * 5.0f)) / 6.0f;
+ }
+ break;
+ }
+ case POSESLIDE_BREAKDOWN: /* make the current pose slide around between the endpoints */
+ {
+ /* perform simple linear interpolation - coefficient for start must come from pso->percentage... */
+ /* TODO: make this use some kind of spline interpolation instead? */
+ (*val) = ((sVal * w2) + (eVal * w1));
+ break;
+ }
+ }
}
/* helper for apply() - perform sliding for some 3-element vector */
-static void pose_slide_apply_vec3(tPoseSlideOp *pso, tPChanFCurveLink *pfl, float vec[3], const char propName[])
+static void pose_slide_apply_vec3(tPoseSlideOp *pso,
+ tPChanFCurveLink *pfl,
+ float vec[3],
+ const char propName[])
{
- LinkData *ld = NULL;
- char *path = NULL;
-
- /* get the path to use... */
- path = BLI_sprintfN("%s.%s", pfl->pchan_path, propName);
-
- /* using this path, find each matching F-Curve for the variables we're interested in */
- while ( (ld = poseAnim_mapping_getNextFCurve(&pfl->fcurves, ld, path)) ) {
- FCurve *fcu = (FCurve *)ld->data;
- const int idx = fcu->array_index;
- const int lock = pso->axislock;
-
- /* check if this F-Curve is ok given the current axis locks */
- BLI_assert(fcu->array_index < 3);
-
- if ((lock == 0) ||
- ((lock & PS_LOCK_X) && (idx == 0)) ||
- ((lock & PS_LOCK_Y) && (idx == 1)) ||
- ((lock & PS_LOCK_Z) && (idx == 2)))
- {
- /* just work on these channels one by one... there's no interaction between values */
- pose_slide_apply_val(pso, fcu, pfl->ob, &vec[fcu->array_index]);
- }
- }
-
- /* free the temp path we got */
- MEM_freeN(path);
+ LinkData *ld = NULL;
+ char *path = NULL;
+
+ /* get the path to use... */
+ path = BLI_sprintfN("%s.%s", pfl->pchan_path, propName);
+
+ /* using this path, find each matching F-Curve for the variables we're interested in */
+ while ((ld = poseAnim_mapping_getNextFCurve(&pfl->fcurves, ld, path))) {
+ FCurve *fcu = (FCurve *)ld->data;
+ const int idx = fcu->array_index;
+ const int lock = pso->axislock;
+
+ /* check if this F-Curve is ok given the current axis locks */
+ BLI_assert(fcu->array_index < 3);
+
+ if ((lock == 0) || ((lock & PS_LOCK_X) && (idx == 0)) || ((lock & PS_LOCK_Y) && (idx == 1)) ||
+ ((lock & PS_LOCK_Z) && (idx == 2))) {
+ /* just work on these channels one by one... there's no interaction between values */
+ pose_slide_apply_val(pso, fcu, pfl->ob, &vec[fcu->array_index]);
+ }
+ }
+
+ /* free the temp path we got */
+ MEM_freeN(path);
}
/* helper for apply() - perform sliding for custom properties or bbone properties */
-static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl, const char prop_prefix[])
+static void pose_slide_apply_props(tPoseSlideOp *pso,
+ tPChanFCurveLink *pfl,
+ const char prop_prefix[])
{
- PointerRNA ptr = {{NULL}};
- LinkData *ld;
- int len = strlen(pfl->pchan_path);
-
- /* setup pointer RNA for resolving paths */
- RNA_pointer_create(NULL, &RNA_PoseBone, pfl->pchan, &ptr);
-
- /* - custom properties are just denoted using ["..."][etc.] after the end of the base path,
- * so just check for opening pair after the end of the path
- * - bbone properties are similar, but they always start with a prefix "bbone_*",
- * so a similar method should work here for those too
- */
- for (ld = pfl->fcurves.first; ld; ld = ld->next) {
- FCurve *fcu = (FCurve *)ld->data;
- const char *bPtr, *pPtr;
-
- if (fcu->rna_path == NULL)
- continue;
-
- /* do we have a match?
- * - bPtr is the RNA Path with the standard part chopped off
- * - pPtr is the chunk of the path which is left over
- */
- bPtr = strstr(fcu->rna_path, pfl->pchan_path) + len;
- pPtr = strstr(bPtr, prop_prefix);
-
- if (pPtr) {
- /* use RNA to try and get a handle on this property, then, assuming that it is just
- * numerical, try and grab the value as a float for temp editing before setting back
- */
- PropertyRNA *prop = RNA_struct_find_property(&ptr, pPtr);
-
- if (prop) {
- switch (RNA_property_type(prop)) {
- /* continuous values that can be smoothly interpolated... */
- case PROP_FLOAT:
- {
- float tval = RNA_property_float_get(&ptr, prop);
- pose_slide_apply_val(pso, fcu, pfl->ob, &tval);
- RNA_property_float_set(&ptr, prop, tval);
- break;
- }
- case PROP_INT:
- {
- float tval = (float)RNA_property_int_get(&ptr, prop);
- pose_slide_apply_val(pso, fcu, pfl->ob, &tval);
- RNA_property_int_set(&ptr, prop, (int)tval);
- break;
- }
-
- /* values which can only take discrete values */
- case PROP_BOOLEAN:
- {
- float tval = (float)RNA_property_boolean_get(&ptr, prop);
- pose_slide_apply_val(pso, fcu, pfl->ob, &tval);
- RNA_property_boolean_set(&ptr, prop, (int)tval); // XXX: do we need threshold clamping here?
- break;
- }
- case PROP_ENUM:
- {
- /* don't handle this case - these don't usually represent interchangeable
- * set of values which should be interpolated between
- */
- break;
- }
-
- default:
- /* cannot handle */
- //printf("Cannot Pose Slide non-numerical property\n");
- break;
- }
- }
- }
- }
+ PointerRNA ptr = {{NULL}};
+ LinkData *ld;
+ int len = strlen(pfl->pchan_path);
+
+ /* setup pointer RNA for resolving paths */
+ RNA_pointer_create(NULL, &RNA_PoseBone, pfl->pchan, &ptr);
+
+ /* - custom properties are just denoted using ["..."][etc.] after the end of the base path,
+ * so just check for opening pair after the end of the path
+ * - bbone properties are similar, but they always start with a prefix "bbone_*",
+ * so a similar method should work here for those too
+ */
+ for (ld = pfl->fcurves.first; ld; ld = ld->next) {
+ FCurve *fcu = (FCurve *)ld->data;
+ const char *bPtr, *pPtr;
+
+ if (fcu->rna_path == NULL)
+ continue;
+
+ /* do we have a match?
+ * - bPtr is the RNA Path with the standard part chopped off
+ * - pPtr is the chunk of the path which is left over
+ */
+ bPtr = strstr(fcu->rna_path, pfl->pchan_path) + len;
+ pPtr = strstr(bPtr, prop_prefix);
+
+ if (pPtr) {
+ /* use RNA to try and get a handle on this property, then, assuming that it is just
+ * numerical, try and grab the value as a float for temp editing before setting back
+ */
+ PropertyRNA *prop = RNA_struct_find_property(&ptr, pPtr);
+
+ if (prop) {
+ switch (RNA_property_type(prop)) {
+ /* continuous values that can be smoothly interpolated... */
+ case PROP_FLOAT: {
+ float tval = RNA_property_float_get(&ptr, prop);
+ pose_slide_apply_val(pso, fcu, pfl->ob, &tval);
+ RNA_property_float_set(&ptr, prop, tval);
+ break;
+ }
+ case PROP_INT: {
+ float tval = (float)RNA_property_int_get(&ptr, prop);
+ pose_slide_apply_val(pso, fcu, pfl->ob, &tval);
+ RNA_property_int_set(&ptr, prop, (int)tval);
+ break;
+ }
+
+ /* values which can only take discrete values */
+ case PROP_BOOLEAN: {
+ float tval = (float)RNA_property_boolean_get(&ptr, prop);
+ pose_slide_apply_val(pso, fcu, pfl->ob, &tval);
+ RNA_property_boolean_set(
+ &ptr, prop, (int)tval); // XXX: do we need threshold clamping here?
+ break;
+ }
+ case PROP_ENUM: {
+ /* don't handle this case - these don't usually represent interchangeable
+ * set of values which should be interpolated between
+ */
+ break;
+ }
+
+ default:
+ /* cannot handle */
+ //printf("Cannot Pose Slide non-numerical property\n");
+ break;
+ }
+ }
+ }
+ }
}
/* helper for apply() - perform sliding for quaternion rotations (using quat blending) */
static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
{
- FCurve *fcu_w = NULL, *fcu_x = NULL, *fcu_y = NULL, *fcu_z = NULL;
- bPoseChannel *pchan = pfl->pchan;
- LinkData *ld = NULL;
- char *path = NULL;
- float cframe;
- float prevFrameF, nextFrameF;
-
- if (!pose_frame_range_from_object_get(pso, pfl->ob, &prevFrameF, &nextFrameF)) {
- BLI_assert(!"Invalid pfl data");
- return;
- }
-
- /* get the path to use - this should be quaternion rotations only (needs care) */
- path = BLI_sprintfN("%s.%s", pfl->pchan_path, "rotation_quaternion");
-
- /* get the current frame number */
- cframe = (float)pso->cframe;
-
- /* using this path, find each matching F-Curve for the variables we're interested in */
- while ( (ld = poseAnim_mapping_getNextFCurve(&pfl->fcurves, ld, path)) ) {
- FCurve *fcu = (FCurve *)ld->data;
-
- /* assign this F-Curve to one of the relevant pointers... */
- switch (fcu->array_index) {
- case 3: /* z */
- fcu_z = fcu;
- break;
- case 2: /* y */
- fcu_y = fcu;
- break;
- case 1: /* x */
- fcu_x = fcu;
- break;
- case 0: /* w */
- fcu_w = fcu;
- break;
- }
- }
-
- /* 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 interpol 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];
-
- /* 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);
-
- /* 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_final);
- }
- 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);
-
- copy_qt_qt(quat_final, quat_curr);
-
- /* 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));
-
- normalize_qt_qt(quat_final_prev, quat_final);
-
- /* tricky interpolations - blending between original and new */
- interp_qt_qtqt(quat_final, quat_final_prev, quat_interp, 1.0f / 6.0f);
- }
- }
-
- /* Apply final to the pose bone, keeping compatible for similar keyframe positions. */
- quat_to_compatible_quat(pchan->quat, quat_final, quat_curr_orig);
- }
-
- /* free the path now */
- MEM_freeN(path);
+ FCurve *fcu_w = NULL, *fcu_x = NULL, *fcu_y = NULL, *fcu_z = NULL;
+ bPoseChannel *pchan = pfl->pchan;
+ LinkData *ld = NULL;
+ char *path = NULL;
+ float cframe;
+ float prevFrameF, nextFrameF;
+
+ if (!pose_frame_range_from_object_get(pso, pfl->ob, &prevFrameF, &nextFrameF)) {
+ BLI_assert(!"Invalid pfl data");
+ return;
+ }
+
+ /* get the path to use - this should be quaternion rotations only (needs care) */
+ path = BLI_sprintfN("%s.%s", pfl->pchan_path, "rotation_quaternion");
+
+ /* get the current frame number */
+ cframe = (float)pso->cframe;
+
+ /* using this path, find each matching F-Curve for the variables we're interested in */
+ while ((ld = poseAnim_mapping_getNextFCurve(&pfl->fcurves, ld, path))) {
+ FCurve *fcu = (FCurve *)ld->data;
+
+ /* assign this F-Curve to one of the relevant pointers... */
+ switch (fcu->array_index) {
+ case 3: /* z */
+ fcu_z = fcu;
+ break;
+ case 2: /* y */
+ fcu_y = fcu;
+ break;
+ case 1: /* x */
+ fcu_x = fcu;
+ break;
+ case 0: /* w */
+ fcu_w = fcu;
+ break;
+ }
+ }
+
+ /* 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 interpol 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];
+
+ /* 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);
+
+ /* 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_final);
+ }
+ 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);
+
+ copy_qt_qt(quat_final, quat_curr);
+
+ /* 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));
+
+ normalize_qt_qt(quat_final_prev, quat_final);
+
+ /* tricky interpolations - blending between original and new */
+ interp_qt_qtqt(quat_final, quat_final_prev, quat_interp, 1.0f / 6.0f);
+ }
+ }
+
+ /* Apply final to the pose bone, keeping compatible for similar keyframe positions. */
+ quat_to_compatible_quat(pchan->quat, quat_final, quat_curr_orig);
+ }
+
+ /* free the path now */
+ MEM_freeN(path);
}
/* apply() - perform the pose sliding based on weighting various poses */
static void pose_slide_apply(bContext *C, tPoseSlideOp *pso)
{
- tPChanFCurveLink *pfl;
-
- /* sanitise the frame ranges */
- if (pso->prevFrame == pso->nextFrame) {
- /* move out one step either side */
- pso->prevFrame--;
- pso->nextFrame++;
-
- for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
- tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
-
- if (!ob_data->valid) {
- continue;
- }
-
- /* apply NLA mapping corrections so the frame lookups work */
- ob_data->prevFrameF = BKE_nla_tweakedit_remap(ob_data->ob->adt,
- pso->prevFrame,
- NLATIME_CONVERT_UNMAP);
- ob_data->nextFrameF = BKE_nla_tweakedit_remap(ob_data->ob->adt,
- pso->nextFrame,
- NLATIME_CONVERT_UNMAP);
- }
- }
-
- /* for each link, handle each set of transforms */
- for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) {
- /* valid transforms for each PoseChannel should have been noted already
- * - sliding the pose should be a straightforward exercise for location+rotation,
- * but rotations get more complicated since we may want to use quaternion blending
- * for quaternions instead...
- */
- bPoseChannel *pchan = pfl->pchan;
-
- if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_LOC) && (pchan->flag & POSE_LOC)) {
- /* calculate these for the 'location' vector, and use location curves */
- pose_slide_apply_vec3(pso, pfl, pchan->loc, "location");
- }
-
- if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_SIZE) && (pchan->flag & POSE_SIZE)) {
- /* calculate these for the 'scale' vector, and use scale curves */
- pose_slide_apply_vec3(pso, pfl, pchan->size, "scale");
- }
-
- if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_ROT) && (pchan->flag & POSE_ROT)) {
- /* everything depends on the rotation mode */
- if (pchan->rotmode > 0) {
- /* eulers - so calculate these for the 'eul' vector, and use euler_rotation curves */
- pose_slide_apply_vec3(pso, pfl, pchan->eul, "rotation_euler");
- }
- else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- /* TODO: need to figure out how to do this! */
- }
- else {
- /* quaternions - use quaternion blending */
- pose_slide_apply_quat(pso, pfl);
- }
- }
-
- if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE) && (pchan->flag & POSE_BBONE_SHAPE)) {
- /* bbone properties - they all start a "bbone_" prefix */
- pose_slide_apply_props(pso, pfl, "bbone_");
- }
-
- if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_PROPS) && (pfl->oldprops)) {
- /* not strictly a transform, but custom properties contribute to the pose produced in many rigs
- * (e.g. the facial rigs used in Sintel)
- */
- pose_slide_apply_props(pso, pfl, "[\""); /* dummy " for texteditor bugs */
- }
- }
-
- /* depsgraph updates + redraws */
- pose_slide_refresh(C, pso);
+ tPChanFCurveLink *pfl;
+
+ /* sanitise the frame ranges */
+ if (pso->prevFrame == pso->nextFrame) {
+ /* move out one step either side */
+ pso->prevFrame--;
+ pso->nextFrame++;
+
+ for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
+ tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
+
+ if (!ob_data->valid) {
+ continue;
+ }
+
+ /* apply NLA mapping corrections so the frame lookups work */
+ ob_data->prevFrameF = BKE_nla_tweakedit_remap(
+ ob_data->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP);
+ ob_data->nextFrameF = BKE_nla_tweakedit_remap(
+ ob_data->ob->adt, pso->nextFrame, NLATIME_CONVERT_UNMAP);
+ }
+ }
+
+ /* for each link, handle each set of transforms */
+ for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) {
+ /* valid transforms for each PoseChannel should have been noted already
+ * - sliding the pose should be a straightforward exercise for location+rotation,
+ * but rotations get more complicated since we may want to use quaternion blending
+ * for quaternions instead...
+ */
+ bPoseChannel *pchan = pfl->pchan;
+
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_LOC) && (pchan->flag & POSE_LOC)) {
+ /* calculate these for the 'location' vector, and use location curves */
+ pose_slide_apply_vec3(pso, pfl, pchan->loc, "location");
+ }
+
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_SIZE) && (pchan->flag & POSE_SIZE)) {
+ /* calculate these for the 'scale' vector, and use scale curves */
+ pose_slide_apply_vec3(pso, pfl, pchan->size, "scale");
+ }
+
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_ROT) && (pchan->flag & POSE_ROT)) {
+ /* everything depends on the rotation mode */
+ if (pchan->rotmode > 0) {
+ /* eulers - so calculate these for the 'eul' vector, and use euler_rotation curves */
+ pose_slide_apply_vec3(pso, pfl, pchan->eul, "rotation_euler");
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ /* TODO: need to figure out how to do this! */
+ }
+ else {
+ /* quaternions - use quaternion blending */
+ pose_slide_apply_quat(pso, pfl);
+ }
+ }
+
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE) && (pchan->flag & POSE_BBONE_SHAPE)) {
+ /* bbone properties - they all start a "bbone_" prefix */
+ pose_slide_apply_props(pso, pfl, "bbone_");
+ }
+
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_PROPS) && (pfl->oldprops)) {
+ /* not strictly a transform, but custom properties contribute to the pose produced in many rigs
+ * (e.g. the facial rigs used in Sintel)
+ */
+ pose_slide_apply_props(pso, pfl, "[\""); /* dummy " for texteditor bugs */
+ }
+ }
+
+ /* depsgraph updates + redraws */
+ pose_slide_refresh(C, pso);
}
/* perform auto-key-framing after changes were made + confirmed */
static void pose_slide_autoKeyframe(bContext *C, tPoseSlideOp *pso)
{
- /* wrapper around the generic call */
- poseAnim_mapping_autoKeyframe(C, pso->scene, &pso->pfLinks, (float)pso->cframe);
+ /* wrapper around the generic call */
+ poseAnim_mapping_autoKeyframe(C, pso->scene, &pso->pfLinks, (float)pso->cframe);
}
/* reset changes made to current pose */
static void pose_slide_reset(tPoseSlideOp *pso)
{
- /* wrapper around the generic call, so that custom stuff can be added later */
- poseAnim_mapping_reset(&pso->pfLinks);
+ /* wrapper around the generic call, so that custom stuff can be added later */
+ poseAnim_mapping_reset(&pso->pfLinks);
}
/* ------------------------------------ */
@@ -724,425 +726,472 @@ static void pose_slide_reset(tPoseSlideOp *pso)
// TODO: Include hints about locks here...
static void pose_slide_draw_status(tPoseSlideOp *pso)
{
- char status_str[UI_MAX_DRAW_STR];
- char limits_str[UI_MAX_DRAW_STR];
- char axis_str[50];
- char mode_str[32];
-
- switch (pso->mode) {
- case POSESLIDE_PUSH:
- strcpy(mode_str, "Push Pose");
- break;
- case POSESLIDE_RELAX:
- strcpy(mode_str, "Relax Pose");
- break;
- case POSESLIDE_BREAKDOWN:
- strcpy(mode_str, "Breakdown");
- break;
-
- default:
- /* unknown */
- strcpy(mode_str, "Sliding-Tool");
- break;
- }
-
- switch (pso->axislock) {
- case PS_LOCK_X:
- BLI_strncpy(axis_str, "[X]/Y/Z axis only (X to clear)", sizeof(axis_str));
- break;
- case PS_LOCK_Y:
- BLI_strncpy(axis_str, "X/[Y]/Z axis only (Y to clear)", sizeof(axis_str));
- break;
- case PS_LOCK_Z:
- BLI_strncpy(axis_str, "X/Y/[Z] axis only (Z to clear)", sizeof(axis_str));
- break;
-
- default:
- if (ELEM(pso->channels, PS_TFM_LOC, PS_TFM_ROT, PS_TFM_SIZE)) {
- BLI_strncpy(axis_str, "X/Y/Z = Axis Constraint", sizeof(axis_str));
- }
- else {
- axis_str[0] = '\0';
- }
- break;
- }
-
- switch (pso->channels) {
- case PS_TFM_LOC:
- BLI_snprintf(limits_str, sizeof(limits_str), "[G]/R/S/B/C - Location only (G to clear) | %s", axis_str);
- break;
- case PS_TFM_ROT:
- BLI_snprintf(limits_str, sizeof(limits_str), "G/[R]/S/B/C - Rotation only (R to clear) | %s", axis_str);
- break;
- case PS_TFM_SIZE:
- BLI_snprintf(limits_str, sizeof(limits_str), "G/R/[S]/B/C - Scale only (S to clear) | %s", axis_str);
- break;
- case PS_TFM_BBONE_SHAPE:
- BLI_strncpy(limits_str, "G/R/S/[B]/C - Bendy Bone properties only (B to clear) | %s", sizeof(limits_str));
- break;
- case PS_TFM_PROPS:
- BLI_strncpy(limits_str, "G/R/S/B/[C] - Custom Properties only (C to clear) | %s", sizeof(limits_str));
- break;
- default:
- BLI_strncpy(limits_str, "G/R/S/B/C - Limit to Transform/Property Set", sizeof(limits_str));
- break;
- }
-
- if (hasNumInput(&pso->num)) {
- Scene *scene = pso->scene;
- char str_offs[NUM_STR_REP_LEN];
-
- outputNumInput(&pso->num, str_offs, &scene->unit);
-
- BLI_snprintf(status_str, sizeof(status_str), "%s: %s | %s", mode_str, str_offs, limits_str);
- }
- else {
- BLI_snprintf(status_str, sizeof(status_str), "%s: %d %% | %s", mode_str, (int)(pso->percentage * 100.0f), limits_str);
- }
-
- ED_area_status_text(pso->sa, status_str);
+ char status_str[UI_MAX_DRAW_STR];
+ char limits_str[UI_MAX_DRAW_STR];
+ char axis_str[50];
+ char mode_str[32];
+
+ switch (pso->mode) {
+ case POSESLIDE_PUSH:
+ strcpy(mode_str, "Push Pose");
+ break;
+ case POSESLIDE_RELAX:
+ strcpy(mode_str, "Relax Pose");
+ break;
+ case POSESLIDE_BREAKDOWN:
+ strcpy(mode_str, "Breakdown");
+ break;
+
+ default:
+ /* unknown */
+ strcpy(mode_str, "Sliding-Tool");
+ break;
+ }
+
+ switch (pso->axislock) {
+ case PS_LOCK_X:
+ BLI_strncpy(axis_str, "[X]/Y/Z axis only (X to clear)", sizeof(axis_str));
+ break;
+ case PS_LOCK_Y:
+ BLI_strncpy(axis_str, "X/[Y]/Z axis only (Y to clear)", sizeof(axis_str));
+ break;
+ case PS_LOCK_Z:
+ BLI_strncpy(axis_str, "X/Y/[Z] axis only (Z to clear)", sizeof(axis_str));
+ break;
+
+ default:
+ if (ELEM(pso->channels, PS_TFM_LOC, PS_TFM_ROT, PS_TFM_SIZE)) {
+ BLI_strncpy(axis_str, "X/Y/Z = Axis Constraint", sizeof(axis_str));
+ }
+ else {
+ axis_str[0] = '\0';
+ }
+ break;
+ }
+
+ switch (pso->channels) {
+ case PS_TFM_LOC:
+ BLI_snprintf(limits_str,
+ sizeof(limits_str),
+ "[G]/R/S/B/C - Location only (G to clear) | %s",
+ axis_str);
+ break;
+ case PS_TFM_ROT:
+ BLI_snprintf(limits_str,
+ sizeof(limits_str),
+ "G/[R]/S/B/C - Rotation only (R to clear) | %s",
+ axis_str);
+ break;
+ case PS_TFM_SIZE:
+ BLI_snprintf(
+ limits_str, sizeof(limits_str), "G/R/[S]/B/C - Scale only (S to clear) | %s", axis_str);
+ break;
+ case PS_TFM_BBONE_SHAPE:
+ BLI_strncpy(limits_str,
+ "G/R/S/[B]/C - Bendy Bone properties only (B to clear) | %s",
+ sizeof(limits_str));
+ break;
+ case PS_TFM_PROPS:
+ BLI_strncpy(limits_str,
+ "G/R/S/B/[C] - Custom Properties only (C to clear) | %s",
+ sizeof(limits_str));
+ break;
+ default:
+ BLI_strncpy(limits_str, "G/R/S/B/C - Limit to Transform/Property Set", sizeof(limits_str));
+ break;
+ }
+
+ if (hasNumInput(&pso->num)) {
+ Scene *scene = pso->scene;
+ char str_offs[NUM_STR_REP_LEN];
+
+ outputNumInput(&pso->num, str_offs, &scene->unit);
+
+ BLI_snprintf(
+ status_str, sizeof(status_str), "%s: %s | %s", mode_str, str_offs, limits_str);
+ }
+ else {
+ BLI_snprintf(status_str,
+ sizeof(status_str),
+ "%s: %d %% | %s",
+ mode_str,
+ (int)(pso->percentage * 100.0f),
+ limits_str);
+ }
+
+ ED_area_status_text(pso->sa, status_str);
}
/* common code for invoke() methods */
static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *pso)
{
- tPChanFCurveLink *pfl;
- wmWindow *win = CTX_wm_window(C);
-
- /* for each link, add all its keyframes to the search tree */
- for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) {
- LinkData *ld;
-
- /* do this for each F-Curve */
- for (ld = pfl->fcurves.first; ld; ld = ld->next) {
- FCurve *fcu = (FCurve *)ld->data;
- fcurve_to_keylist(pfl->ob->adt, fcu, &pso->keys, 0);
- }
- }
-
- /* cancel if no keyframes found... */
- if (pso->keys.root) {
- ActKeyColumn *ak;
- float cframe = (float)pso->cframe;
-
- /* firstly, check if the current frame is a keyframe... */
- ak = (ActKeyColumn *)BLI_dlrbTree_search_exact(&pso->keys, compare_ak_cfraPtr, &cframe);
-
- if (ak == NULL) {
- /* current frame is not a keyframe, so search */
- ActKeyColumn *pk = (ActKeyColumn *)BLI_dlrbTree_search_prev(&pso->keys, compare_ak_cfraPtr, &cframe);
- ActKeyColumn *nk = (ActKeyColumn *)BLI_dlrbTree_search_next(&pso->keys, compare_ak_cfraPtr, &cframe);
-
- /* new set the frames */
- /* prev frame */
- pso->prevFrame = (pk) ? (pk->cfra) : (pso->cframe - 1);
- RNA_int_set(op->ptr, "prev_frame", pso->prevFrame);
- /* next frame */
- pso->nextFrame = (nk) ? (nk->cfra) : (pso->cframe + 1);
- RNA_int_set(op->ptr, "next_frame", pso->nextFrame);
- }
- else {
- /* current frame itself is a keyframe, so just take keyframes on either side */
- /* prev frame */
- pso->prevFrame = (ak->prev) ? (ak->prev->cfra) : (pso->cframe - 1);
- RNA_int_set(op->ptr, "prev_frame", pso->prevFrame);
- /* next frame */
- pso->nextFrame = (ak->next) ? (ak->next->cfra) : (pso->cframe + 1);
- RNA_int_set(op->ptr, "next_frame", pso->nextFrame);
- }
-
- /* apply NLA mapping corrections so the frame lookups work */
- for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
- tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
- if (ob_data->valid) {
- ob_data->prevFrameF = BKE_nla_tweakedit_remap(ob_data->ob->adt,
- pso->prevFrame,
- NLATIME_CONVERT_UNMAP);
- ob_data->nextFrameF = BKE_nla_tweakedit_remap(ob_data->ob->adt,
- pso->nextFrame,
- NLATIME_CONVERT_UNMAP);
- }
- }
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "No keyframes to slide between");
- pose_slide_exit(op);
- return OPERATOR_CANCELLED;
- }
-
- /* initial apply for operator... */
- /* TODO: need to calculate percentage for initial round too... */
- pose_slide_apply(C, pso);
-
- /* depsgraph updates + redraws */
- pose_slide_refresh(C, pso);
-
- /* set cursor to indicate modal */
- WM_cursor_modal_set(win, BC_EW_SCROLLCURSOR);
-
- /* header print */
- pose_slide_draw_status(pso);
-
- /* add a modal handler for this operator */
- WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ tPChanFCurveLink *pfl;
+ wmWindow *win = CTX_wm_window(C);
+
+ /* for each link, add all its keyframes to the search tree */
+ for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) {
+ LinkData *ld;
+
+ /* do this for each F-Curve */
+ for (ld = pfl->fcurves.first; ld; ld = ld->next) {
+ FCurve *fcu = (FCurve *)ld->data;
+ fcurve_to_keylist(pfl->ob->adt, fcu, &pso->keys, 0);
+ }
+ }
+
+ /* cancel if no keyframes found... */
+ if (pso->keys.root) {
+ ActKeyColumn *ak;
+ float cframe = (float)pso->cframe;
+
+ /* firstly, check if the current frame is a keyframe... */
+ ak = (ActKeyColumn *)BLI_dlrbTree_search_exact(&pso->keys, compare_ak_cfraPtr, &cframe);
+
+ if (ak == NULL) {
+ /* current frame is not a keyframe, so search */
+ ActKeyColumn *pk = (ActKeyColumn *)BLI_dlrbTree_search_prev(
+ &pso->keys, compare_ak_cfraPtr, &cframe);
+ ActKeyColumn *nk = (ActKeyColumn *)BLI_dlrbTree_search_next(
+ &pso->keys, compare_ak_cfraPtr, &cframe);
+
+ /* new set the frames */
+ /* prev frame */
+ pso->prevFrame = (pk) ? (pk->cfra) : (pso->cframe - 1);
+ RNA_int_set(op->ptr, "prev_frame", pso->prevFrame);
+ /* next frame */
+ pso->nextFrame = (nk) ? (nk->cfra) : (pso->cframe + 1);
+ RNA_int_set(op->ptr, "next_frame", pso->nextFrame);
+ }
+ else {
+ /* current frame itself is a keyframe, so just take keyframes on either side */
+ /* prev frame */
+ pso->prevFrame = (ak->prev) ? (ak->prev->cfra) : (pso->cframe - 1);
+ RNA_int_set(op->ptr, "prev_frame", pso->prevFrame);
+ /* next frame */
+ pso->nextFrame = (ak->next) ? (ak->next->cfra) : (pso->cframe + 1);
+ RNA_int_set(op->ptr, "next_frame", pso->nextFrame);
+ }
+
+ /* apply NLA mapping corrections so the frame lookups work */
+ for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
+ tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
+ if (ob_data->valid) {
+ ob_data->prevFrameF = BKE_nla_tweakedit_remap(
+ ob_data->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP);
+ ob_data->nextFrameF = BKE_nla_tweakedit_remap(
+ ob_data->ob->adt, pso->nextFrame, NLATIME_CONVERT_UNMAP);
+ }
+ }
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No keyframes to slide between");
+ pose_slide_exit(op);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* initial apply for operator... */
+ /* TODO: need to calculate percentage for initial round too... */
+ pose_slide_apply(C, pso);
+
+ /* depsgraph updates + redraws */
+ pose_slide_refresh(C, pso);
+
+ /* set cursor to indicate modal */
+ WM_cursor_modal_set(win, BC_EW_SCROLLCURSOR);
+
+ /* header print */
+ pose_slide_draw_status(pso);
+
+ /* add a modal handler for this operator */
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
}
/* calculate percentage based on position of mouse (we only use x-axis for now.
* since this is more convenient for users to do), and store new percentage value
*/
-static void pose_slide_mouse_update_percentage(tPoseSlideOp *pso, wmOperator *op, const wmEvent *event)
+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);
- RNA_float_set(op->ptr, "percentage", pso->percentage);
+ pso->percentage = (event->x - pso->ar->winrct.xmin) / ((float)pso->ar->winx);
+ RNA_float_set(op->ptr, "percentage", pso->percentage);
}
/* handle an event to toggle channels mode */
-static void pose_slide_toggle_channels_mode(wmOperator *op, tPoseSlideOp *pso, ePoseSlide_Channels channel)
+static void pose_slide_toggle_channels_mode(wmOperator *op,
+ tPoseSlideOp *pso,
+ ePoseSlide_Channels channel)
{
- /* Turn channel on or off? */
- if (pso->channels == channel) {
- /* Already limiting to transform only, so pressing this again turns it off */
- pso->channels = PS_TFM_ALL;
- }
- else {
- /* Only this set of channels */
- pso->channels = channel;
- }
- RNA_enum_set(op->ptr, "channels", pso->channels);
-
-
- /* Reset axis limits too for good measure */
- pso->axislock = 0;
- RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
+ /* Turn channel on or off? */
+ if (pso->channels == channel) {
+ /* Already limiting to transform only, so pressing this again turns it off */
+ pso->channels = PS_TFM_ALL;
+ }
+ else {
+ /* Only this set of channels */
+ pso->channels = channel;
+ }
+ RNA_enum_set(op->ptr, "channels", pso->channels);
+
+ /* Reset axis limits too for good measure */
+ pso->axislock = 0;
+ RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
}
/* handle an event to toggle axis locks - returns whether any change in state is needed */
-static bool pose_slide_toggle_axis_locks(wmOperator *op, tPoseSlideOp *pso, ePoseSlide_AxisLock axis)
+static bool pose_slide_toggle_axis_locks(wmOperator *op,
+ tPoseSlideOp *pso,
+ ePoseSlide_AxisLock axis)
{
- /* Axis can only be set when a transform is set - it doesn't make sense otherwise */
- if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE, PS_TFM_PROPS)) {
- pso->axislock = 0;
- RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
- return false;
- }
-
- /* Turn on or off? */
- if (pso->axislock == axis) {
- /* Already limiting on this axis, so turn off */
- pso->axislock = 0;
- }
- else {
- /* Only this axis */
- pso->axislock = axis;
- }
- RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
-
- /* Setting changed, so pose update is needed */
- return true;
+ /* Axis can only be set when a transform is set - it doesn't make sense otherwise */
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE, PS_TFM_PROPS)) {
+ pso->axislock = 0;
+ RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
+ return false;
+ }
+
+ /* Turn on or off? */
+ if (pso->axislock == axis) {
+ /* Already limiting on this axis, so turn off */
+ pso->axislock = 0;
+ }
+ else {
+ /* Only this axis */
+ pso->axislock = axis;
+ }
+ RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
+
+ /* Setting changed, so pose update is needed */
+ return true;
}
/* common code for modal() */
static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- tPoseSlideOp *pso = op->customdata;
- wmWindow *win = CTX_wm_window(C);
- bool do_pose_update = false;
-
- const bool has_numinput = hasNumInput(&pso->num);
-
- switch (event->type) {
- case LEFTMOUSE: /* confirm */
- case RETKEY:
- case PADENTER:
- {
- /* return to normal cursor and header status */
- ED_area_status_text(pso->sa, NULL);
- WM_cursor_modal_restore(win);
-
- /* insert keyframes as required... */
- pose_slide_autoKeyframe(C, pso);
- pose_slide_exit(op);
-
- /* done! */
- return OPERATOR_FINISHED;
- }
-
- case ESCKEY: /* cancel */
- case RIGHTMOUSE:
- {
- /* return to normal cursor and header status */
- ED_area_status_text(pso->sa, NULL);
- WM_cursor_modal_restore(win);
-
- /* reset transforms back to original state */
- pose_slide_reset(pso);
-
- /* depsgraph updates + redraws */
- pose_slide_refresh(C, pso);
-
- /* clean up temp data */
- pose_slide_exit(op);
-
- /* canceled! */
- return OPERATOR_CANCELLED;
- }
-
- /* Percentage Chane... */
- case MOUSEMOVE: /* calculate new position */
- {
- /* only handle mousemove if not doing numinput */
- if (has_numinput == false) {
- /* update percentage based on position of mouse */
- pose_slide_mouse_update_percentage(pso, op, event);
-
- /* update pose to reflect the new values (see below) */
- do_pose_update = true;
- }
- break;
- }
- default:
- {
- if ((event->val == KM_PRESS) && handleNumInput(C, &pso->num, event)) {
- float value;
-
- /* Grab percentage from numeric input, and store this new value for redo
- * NOTE: users see ints, while internally we use a 0-1 float
- */
- value = pso->percentage * 100.0f;
- applyNumInput(&pso->num, &value);
-
- pso->percentage = value / 100.0f;
- CLAMP(pso->percentage, 0.0f, 1.0f);
- RNA_float_set(op->ptr, "percentage", pso->percentage);
-
- /* Update pose to reflect the new values (see below) */
- do_pose_update = true;
- break;
- }
- else if (event->val == KM_PRESS) {
- switch (event->type) {
- /* Transform Channel Limits */
- /* XXX: Replace these hardcoded hotkeys with a modalmap that can be customised */
- case GKEY: /* Location */
- {
- pose_slide_toggle_channels_mode(op, pso, PS_TFM_LOC);
- do_pose_update = true;
- break;
- }
- case RKEY: /* Rotation */
- {
- pose_slide_toggle_channels_mode(op, pso, PS_TFM_ROT);
- do_pose_update = true;
- break;
- }
- case SKEY: /* Scale */
- {
- pose_slide_toggle_channels_mode(op, pso, PS_TFM_SIZE);
- do_pose_update = true;
- break;
- }
- case BKEY: /* Bendy Bones */
- {
- pose_slide_toggle_channels_mode(op, pso, PS_TFM_BBONE_SHAPE);
- do_pose_update = true;
- break;
- }
- case CKEY: /* Custom Properties */
- {
- pose_slide_toggle_channels_mode(op, pso, PS_TFM_PROPS);
- do_pose_update = true;
- break;
- }
-
-
- /* Axis Locks */
- /* XXX: Hardcoded... */
- case XKEY:
- {
- if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_X)) {
- do_pose_update = true;
- }
- break;
- }
- case YKEY:
- {
- if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_Y)) {
- do_pose_update = true;
- }
- break;
- }
- case ZKEY:
- {
- if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_Z)) {
- do_pose_update = true;
- }
- break;
- }
-
-
- default: /* Some other unhandled key... */
- break;
- }
- }
- else {
- /* unhandled event - maybe it was some view manip? */
- /* allow to pass through */
- return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH;
- }
- }
- }
-
-
- /* perform pose updates - in response to some user action (e.g. pressing a key or moving the mouse) */
- if (do_pose_update) {
- /* update percentage indicator in header */
- pose_slide_draw_status(pso);
-
- /* reset transforms (to avoid accumulation errors) */
- pose_slide_reset(pso);
-
- /* apply... */
- pose_slide_apply(C, pso);
- }
-
- /* still running... */
- return OPERATOR_RUNNING_MODAL;
+ tPoseSlideOp *pso = op->customdata;
+ wmWindow *win = CTX_wm_window(C);
+ bool do_pose_update = false;
+
+ const bool has_numinput = hasNumInput(&pso->num);
+
+ switch (event->type) {
+ case LEFTMOUSE: /* confirm */
+ case RETKEY:
+ case PADENTER: {
+ /* return to normal cursor and header status */
+ ED_area_status_text(pso->sa, NULL);
+ WM_cursor_modal_restore(win);
+
+ /* insert keyframes as required... */
+ pose_slide_autoKeyframe(C, pso);
+ pose_slide_exit(op);
+
+ /* done! */
+ return OPERATOR_FINISHED;
+ }
+
+ case ESCKEY: /* cancel */
+ case RIGHTMOUSE: {
+ /* return to normal cursor and header status */
+ ED_area_status_text(pso->sa, NULL);
+ WM_cursor_modal_restore(win);
+
+ /* reset transforms back to original state */
+ pose_slide_reset(pso);
+
+ /* depsgraph updates + redraws */
+ pose_slide_refresh(C, pso);
+
+ /* clean up temp data */
+ pose_slide_exit(op);
+
+ /* canceled! */
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Percentage Chane... */
+ case MOUSEMOVE: /* calculate new position */
+ {
+ /* only handle mousemove if not doing numinput */
+ if (has_numinput == false) {
+ /* update percentage based on position of mouse */
+ pose_slide_mouse_update_percentage(pso, op, event);
+
+ /* update pose to reflect the new values (see below) */
+ do_pose_update = true;
+ }
+ break;
+ }
+ default: {
+ if ((event->val == KM_PRESS) && handleNumInput(C, &pso->num, event)) {
+ float value;
+
+ /* Grab percentage from numeric input, and store this new value for redo
+ * NOTE: users see ints, while internally we use a 0-1 float
+ */
+ value = pso->percentage * 100.0f;
+ applyNumInput(&pso->num, &value);
+
+ pso->percentage = value / 100.0f;
+ CLAMP(pso->percentage, 0.0f, 1.0f);
+ RNA_float_set(op->ptr, "percentage", pso->percentage);
+
+ /* Update pose to reflect the new values (see below) */
+ do_pose_update = true;
+ break;
+ }
+ else if (event->val == KM_PRESS) {
+ switch (event->type) {
+ /* Transform Channel Limits */
+ /* XXX: Replace these hardcoded hotkeys with a modalmap that can be customised */
+ case GKEY: /* Location */
+ {
+ pose_slide_toggle_channels_mode(op, pso, PS_TFM_LOC);
+ do_pose_update = true;
+ break;
+ }
+ case RKEY: /* Rotation */
+ {
+ pose_slide_toggle_channels_mode(op, pso, PS_TFM_ROT);
+ do_pose_update = true;
+ break;
+ }
+ case SKEY: /* Scale */
+ {
+ pose_slide_toggle_channels_mode(op, pso, PS_TFM_SIZE);
+ do_pose_update = true;
+ break;
+ }
+ case BKEY: /* Bendy Bones */
+ {
+ pose_slide_toggle_channels_mode(op, pso, PS_TFM_BBONE_SHAPE);
+ do_pose_update = true;
+ break;
+ }
+ case CKEY: /* Custom Properties */
+ {
+ pose_slide_toggle_channels_mode(op, pso, PS_TFM_PROPS);
+ do_pose_update = true;
+ break;
+ }
+
+ /* Axis Locks */
+ /* XXX: Hardcoded... */
+ case XKEY: {
+ if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_X)) {
+ do_pose_update = true;
+ }
+ break;
+ }
+ case YKEY: {
+ if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_Y)) {
+ do_pose_update = true;
+ }
+ break;
+ }
+ case ZKEY: {
+ if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_Z)) {
+ do_pose_update = true;
+ }
+ break;
+ }
+
+ default: /* Some other unhandled key... */
+ break;
+ }
+ }
+ else {
+ /* unhandled event - maybe it was some view manip? */
+ /* allow to pass through */
+ return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH;
+ }
+ }
+ }
+
+ /* perform pose updates - in response to some user action (e.g. pressing a key or moving the mouse) */
+ if (do_pose_update) {
+ /* update percentage indicator in header */
+ pose_slide_draw_status(pso);
+
+ /* reset transforms (to avoid accumulation errors) */
+ pose_slide_reset(pso);
+
+ /* apply... */
+ pose_slide_apply(C, pso);
+ }
+
+ /* still running... */
+ return OPERATOR_RUNNING_MODAL;
}
/* common code for cancel() */
static void pose_slide_cancel(bContext *UNUSED(C), wmOperator *op)
{
- /* cleanup and done */
- pose_slide_exit(op);
+ /* cleanup and done */
+ pose_slide_exit(op);
}
/* common code for exec() methods */
static int pose_slide_exec_common(bContext *C, wmOperator *op, tPoseSlideOp *pso)
{
- /* settings should have been set up ok for applying, so just apply! */
- pose_slide_apply(C, pso);
+ /* settings should have been set up ok for applying, so just apply! */
+ pose_slide_apply(C, pso);
- /* insert keyframes if needed */
- pose_slide_autoKeyframe(C, pso);
+ /* insert keyframes if needed */
+ pose_slide_autoKeyframe(C, pso);
- /* cleanup and done */
- pose_slide_exit(op);
+ /* cleanup and done */
+ pose_slide_exit(op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* common code for defining RNA properties */
/* TODO: Skip save on these? */
static void pose_slide_opdef_properties(wmOperatorType *ot)
{
- RNA_def_float_percentage(ot->srna, "percentage", 0.5f, 0.0f, 1.0f, "Percentage", "Weighting factor for which keyframe is favored more", 0.3, 0.7);
-
- RNA_def_int(ot->srna, "prev_frame", 0, MINAFRAME, MAXFRAME, "Previous Keyframe", "Frame number of keyframe immediately before the current frame", 0, 50);
- RNA_def_int(ot->srna, "next_frame", 0, MINAFRAME, MAXFRAME, "Next Keyframe", "Frame number of keyframe immediately after the current frame", 0, 50);
-
- RNA_def_enum(ot->srna, "channels", prop_channels_types, PS_TFM_ALL, "Channels", "Set of properties that are affected");
- RNA_def_enum(ot->srna, "axis_lock", prop_axis_lock_types, 0, "Axis Lock", "Transform axis to restrict effects to");
+ RNA_def_float_percentage(ot->srna,
+ "percentage",
+ 0.5f,
+ 0.0f,
+ 1.0f,
+ "Percentage",
+ "Weighting factor for which keyframe is favored more",
+ 0.3,
+ 0.7);
+
+ RNA_def_int(ot->srna,
+ "prev_frame",
+ 0,
+ MINAFRAME,
+ MAXFRAME,
+ "Previous Keyframe",
+ "Frame number of keyframe immediately before the current frame",
+ 0,
+ 50);
+ RNA_def_int(ot->srna,
+ "next_frame",
+ 0,
+ MINAFRAME,
+ MAXFRAME,
+ "Next Keyframe",
+ "Frame number of keyframe immediately after the current frame",
+ 0,
+ 50);
+
+ RNA_def_enum(ot->srna,
+ "channels",
+ prop_channels_types,
+ PS_TFM_ALL,
+ "Channels",
+ "Set of properties that are affected");
+ RNA_def_enum(ot->srna,
+ "axis_lock",
+ prop_axis_lock_types,
+ 0,
+ "Axis Lock",
+ "Transform axis to restrict effects to");
}
/* ------------------------------------ */
@@ -1150,59 +1199,59 @@ static void pose_slide_opdef_properties(wmOperatorType *ot)
/* invoke() - for 'push' mode */
static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- tPoseSlideOp *pso;
+ tPoseSlideOp *pso;
- /* initialize data */
- if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) {
- pose_slide_exit(op);
- return OPERATOR_CANCELLED;
- }
- else
- pso = op->customdata;
+ /* initialize data */
+ if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) {
+ pose_slide_exit(op);
+ return OPERATOR_CANCELLED;
+ }
+ else
+ pso = op->customdata;
- /* initialise percentage so that it won't pop on first mouse move */
- pose_slide_mouse_update_percentage(pso, op, event);
+ /* initialise percentage so that it won't pop on first mouse move */
+ pose_slide_mouse_update_percentage(pso, op, event);
- /* do common setup work */
- return pose_slide_invoke_common(C, op, pso);
+ /* do common setup work */
+ return pose_slide_invoke_common(C, op, pso);
}
/* exec() - for push */
static int pose_slide_push_exec(bContext *C, wmOperator *op)
{
- tPoseSlideOp *pso;
-
- /* initialize data (from RNA-props) */
- if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) {
- pose_slide_exit(op);
- return OPERATOR_CANCELLED;
- }
- else
- pso = op->customdata;
-
- /* do common exec work */
- return pose_slide_exec_common(C, op, pso);
+ tPoseSlideOp *pso;
+
+ /* initialize data (from RNA-props) */
+ if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) {
+ pose_slide_exit(op);
+ return OPERATOR_CANCELLED;
+ }
+ else
+ pso = op->customdata;
+
+ /* do common exec work */
+ return pose_slide_exec_common(C, op, pso);
}
void POSE_OT_push(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Push Pose";
- ot->idname = "POSE_OT_push";
- ot->description = "Exaggerate the current pose";
-
- /* callbacks */
- ot->exec = pose_slide_push_exec;
- ot->invoke = pose_slide_push_invoke;
- ot->modal = pose_slide_modal;
- ot->cancel = pose_slide_cancel;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* Properties */
- pose_slide_opdef_properties(ot);
+ /* identifiers */
+ ot->name = "Push Pose";
+ ot->idname = "POSE_OT_push";
+ ot->description = "Exaggerate the current pose";
+
+ /* callbacks */
+ ot->exec = pose_slide_push_exec;
+ ot->invoke = pose_slide_push_invoke;
+ ot->modal = pose_slide_modal;
+ ot->cancel = pose_slide_cancel;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* Properties */
+ pose_slide_opdef_properties(ot);
}
/* ........................ */
@@ -1210,59 +1259,59 @@ void POSE_OT_push(wmOperatorType *ot)
/* invoke() - for 'relax' mode */
static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- tPoseSlideOp *pso;
+ tPoseSlideOp *pso;
- /* initialize data */
- if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) {
- pose_slide_exit(op);
- return OPERATOR_CANCELLED;
- }
- else
- pso = op->customdata;
+ /* initialize data */
+ if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) {
+ pose_slide_exit(op);
+ return OPERATOR_CANCELLED;
+ }
+ else
+ pso = op->customdata;
- /* initialise percentage so that it won't pop on first mouse move */
- pose_slide_mouse_update_percentage(pso, op, event);
+ /* initialise percentage so that it won't pop on first mouse move */
+ pose_slide_mouse_update_percentage(pso, op, event);
- /* do common setup work */
- return pose_slide_invoke_common(C, op, pso);
+ /* do common setup work */
+ return pose_slide_invoke_common(C, op, pso);
}
/* exec() - for relax */
static int pose_slide_relax_exec(bContext *C, wmOperator *op)
{
- tPoseSlideOp *pso;
-
- /* initialize data (from RNA-props) */
- if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) {
- pose_slide_exit(op);
- return OPERATOR_CANCELLED;
- }
- else
- pso = op->customdata;
-
- /* do common exec work */
- return pose_slide_exec_common(C, op, pso);
+ tPoseSlideOp *pso;
+
+ /* initialize data (from RNA-props) */
+ if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) {
+ pose_slide_exit(op);
+ return OPERATOR_CANCELLED;
+ }
+ else
+ pso = op->customdata;
+
+ /* do common exec work */
+ return pose_slide_exec_common(C, op, pso);
}
void POSE_OT_relax(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Relax Pose";
- ot->idname = "POSE_OT_relax";
- ot->description = "Make the current pose more similar to its surrounding ones";
-
- /* callbacks */
- ot->exec = pose_slide_relax_exec;
- ot->invoke = pose_slide_relax_invoke;
- ot->modal = pose_slide_modal;
- ot->cancel = pose_slide_cancel;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* Properties */
- pose_slide_opdef_properties(ot);
+ /* identifiers */
+ ot->name = "Relax Pose";
+ ot->idname = "POSE_OT_relax";
+ ot->description = "Make the current pose more similar to its surrounding ones";
+
+ /* callbacks */
+ ot->exec = pose_slide_relax_exec;
+ ot->invoke = pose_slide_relax_invoke;
+ ot->modal = pose_slide_modal;
+ ot->cancel = pose_slide_cancel;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* Properties */
+ pose_slide_opdef_properties(ot);
}
/* ........................ */
@@ -1270,59 +1319,59 @@ void POSE_OT_relax(wmOperatorType *ot)
/* invoke() - for 'breakdown' mode */
static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- tPoseSlideOp *pso;
+ tPoseSlideOp *pso;
- /* initialize data */
- if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) {
- pose_slide_exit(op);
- return OPERATOR_CANCELLED;
- }
- else
- pso = op->customdata;
+ /* initialize data */
+ if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) {
+ pose_slide_exit(op);
+ return OPERATOR_CANCELLED;
+ }
+ else
+ pso = op->customdata;
- /* initialise percentage so that it won't pop on first mouse move */
- pose_slide_mouse_update_percentage(pso, op, event);
+ /* initialise percentage so that it won't pop on first mouse move */
+ pose_slide_mouse_update_percentage(pso, op, event);
- /* do common setup work */
- return pose_slide_invoke_common(C, op, pso);
+ /* do common setup work */
+ return pose_slide_invoke_common(C, op, pso);
}
/* exec() - for breakdown */
static int pose_slide_breakdown_exec(bContext *C, wmOperator *op)
{
- tPoseSlideOp *pso;
-
- /* initialize data (from RNA-props) */
- if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) {
- pose_slide_exit(op);
- return OPERATOR_CANCELLED;
- }
- else
- pso = op->customdata;
-
- /* do common exec work */
- return pose_slide_exec_common(C, op, pso);
+ tPoseSlideOp *pso;
+
+ /* initialize data (from RNA-props) */
+ if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) {
+ pose_slide_exit(op);
+ return OPERATOR_CANCELLED;
+ }
+ else
+ pso = op->customdata;
+
+ /* do common exec work */
+ return pose_slide_exec_common(C, op, pso);
}
void POSE_OT_breakdown(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Pose Breakdowner";
- ot->idname = "POSE_OT_breakdown";
- ot->description = "Create a suitable breakdown pose on the current frame";
-
- /* callbacks */
- ot->exec = pose_slide_breakdown_exec;
- ot->invoke = pose_slide_breakdown_invoke;
- ot->modal = pose_slide_modal;
- ot->cancel = pose_slide_cancel;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* Properties */
- pose_slide_opdef_properties(ot);
+ /* identifiers */
+ ot->name = "Pose Breakdowner";
+ ot->idname = "POSE_OT_breakdown";
+ ot->description = "Create a suitable breakdown pose on the current frame";
+
+ /* callbacks */
+ ot->exec = pose_slide_breakdown_exec;
+ ot->invoke = pose_slide_breakdown_invoke;
+ ot->modal = pose_slide_modal;
+ ot->cancel = pose_slide_cancel;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* Properties */
+ pose_slide_opdef_properties(ot);
}
/* **************************************************** */
@@ -1330,30 +1379,30 @@ void POSE_OT_breakdown(wmOperatorType *ot)
/* "termination conditions" - i.e. when we stop */
typedef enum ePosePropagate_Termination {
- /* stop after the current hold ends */
- POSE_PROPAGATE_SMART_HOLDS = 0,
- /* only do on the last keyframe */
- POSE_PROPAGATE_LAST_KEY,
- /* stop after the next keyframe */
- POSE_PROPAGATE_NEXT_KEY,
- /* stop after the specified frame */
- POSE_PROPAGATE_BEFORE_FRAME,
- /* stop when we run out of keyframes */
- POSE_PROPAGATE_BEFORE_END,
-
- /* only do on keyframes that are selected */
- POSE_PROPAGATE_SELECTED_KEYS,
- /* only do on the frames where markers are selected */
- POSE_PROPAGATE_SELECTED_MARKERS,
+ /* stop after the current hold ends */
+ POSE_PROPAGATE_SMART_HOLDS = 0,
+ /* only do on the last keyframe */
+ POSE_PROPAGATE_LAST_KEY,
+ /* stop after the next keyframe */
+ POSE_PROPAGATE_NEXT_KEY,
+ /* stop after the specified frame */
+ POSE_PROPAGATE_BEFORE_FRAME,
+ /* stop when we run out of keyframes */
+ POSE_PROPAGATE_BEFORE_END,
+
+ /* only do on keyframes that are selected */
+ POSE_PROPAGATE_SELECTED_KEYS,
+ /* only do on the frames where markers are selected */
+ POSE_PROPAGATE_SELECTED_MARKERS,
} ePosePropagate_Termination;
/* termination data needed for some modes - assumes only one of these entries will be needed at a time */
typedef union tPosePropagate_ModeData {
- /* smart holds + before frame: frame number to stop on */
- float end_frame;
+ /* smart holds + before frame: frame number to stop on */
+ float end_frame;
- /* selected markers: listbase for CfraElem's marking these frames */
- ListBase sel_markers;
+ /* selected markers: listbase for CfraElem's marking these frames */
+ ListBase sel_markers;
} tPosePropagate_ModeData;
/* --------------------------------- */
@@ -1365,333 +1414,371 @@ typedef union tPosePropagate_ModeData {
*/
static float pose_propagate_get_boneHoldEndFrame(tPChanFCurveLink *pfl, float startFrame)
{
- DLRBT_Tree keys;
-
- Object *ob = pfl->ob;
- AnimData *adt = ob->adt;
- LinkData *ld;
- float endFrame = startFrame;
-
- /* set up optimized data-structures for searching for relevant keyframes + holds */
- BLI_dlrbTree_init(&keys);
-
- for (ld = pfl->fcurves.first; ld; ld = ld->next) {
- FCurve *fcu = (FCurve *)ld->data;
- fcurve_to_keylist(adt, fcu, &keys, 0);
- }
-
- /* find the long keyframe (i.e. hold), and hence obtain the endFrame value
- * - the best case would be one that starts on the frame itself
- */
- ActKeyColumn *ab = (ActKeyColumn *)BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &startFrame);
-
- /* There are only two cases for no-exact match:
- * 1) the current frame is just before another key but not on a key itself
- * 2) the current frame is on a key, but that key doesn't link to the next
- *
- * If we've got the first case, then we can search for another block,
- * otherwise forget it, as we'd be overwriting some valid data.
- */
- if (ab == NULL) {
- /* we've got case 1, so try the one after */
- ab = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &startFrame);
-
- if ((actkeyblock_get_valid_hold(ab) & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) {
- /* try the block before this frame then as last resort */
- ab = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &startFrame);
- }
- }
-
- /* whatever happens, stop searching now... */
- if ((actkeyblock_get_valid_hold(ab) & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) {
- /* restrict range to just the frame itself
- * i.e. everything is in motion, so no holds to safely overwrite
- */
- ab = NULL;
- }
-
- /* check if we can go any further than we've already gone */
- if (ab) {
- /* go to next if it is also valid and meets "extension" criteria */
- while (ab->next) {
- ActKeyColumn *abn = ab->next;
-
- /* must be valid */
- if ((actkeyblock_get_valid_hold(abn) & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) {
- break;
- }
- /* should have the same number of curves */
- if (ab->totblock != abn->totblock) {
- break;
- }
-
- /* we can extend the bounds to the end of this "next" block now */
- ab = abn;
- }
-
- /* end frame can now take the value of the end of the block */
- endFrame = ab->next->cfra;
- }
-
- /* free temp memory */
- BLI_dlrbTree_free(&keys);
-
- /* return the end frame we've found */
- return endFrame;
+ DLRBT_Tree keys;
+
+ Object *ob = pfl->ob;
+ AnimData *adt = ob->adt;
+ LinkData *ld;
+ float endFrame = startFrame;
+
+ /* set up optimized data-structures for searching for relevant keyframes + holds */
+ BLI_dlrbTree_init(&keys);
+
+ for (ld = pfl->fcurves.first; ld; ld = ld->next) {
+ FCurve *fcu = (FCurve *)ld->data;
+ fcurve_to_keylist(adt, fcu, &keys, 0);
+ }
+
+ /* find the long keyframe (i.e. hold), and hence obtain the endFrame value
+ * - the best case would be one that starts on the frame itself
+ */
+ ActKeyColumn *ab = (ActKeyColumn *)BLI_dlrbTree_search_exact(
+ &keys, compare_ak_cfraPtr, &startFrame);
+
+ /* There are only two cases for no-exact match:
+ * 1) the current frame is just before another key but not on a key itself
+ * 2) the current frame is on a key, but that key doesn't link to the next
+ *
+ * If we've got the first case, then we can search for another block,
+ * otherwise forget it, as we'd be overwriting some valid data.
+ */
+ if (ab == NULL) {
+ /* we've got case 1, so try the one after */
+ ab = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &startFrame);
+
+ if ((actkeyblock_get_valid_hold(ab) & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) {
+ /* try the block before this frame then as last resort */
+ ab = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &startFrame);
+ }
+ }
+
+ /* whatever happens, stop searching now... */
+ if ((actkeyblock_get_valid_hold(ab) & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) {
+ /* restrict range to just the frame itself
+ * i.e. everything is in motion, so no holds to safely overwrite
+ */
+ ab = NULL;
+ }
+
+ /* check if we can go any further than we've already gone */
+ if (ab) {
+ /* go to next if it is also valid and meets "extension" criteria */
+ while (ab->next) {
+ ActKeyColumn *abn = ab->next;
+
+ /* must be valid */
+ if ((actkeyblock_get_valid_hold(abn) & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) {
+ break;
+ }
+ /* should have the same number of curves */
+ if (ab->totblock != abn->totblock) {
+ break;
+ }
+
+ /* we can extend the bounds to the end of this "next" block now */
+ ab = abn;
+ }
+
+ /* end frame can now take the value of the end of the block */
+ endFrame = ab->next->cfra;
+ }
+
+ /* free temp memory */
+ BLI_dlrbTree_free(&keys);
+
+ /* return the end frame we've found */
+ return endFrame;
}
/* get reference value from F-Curve using RNA */
static bool pose_propagate_get_refVal(Object *ob, FCurve *fcu, float *value)
{
- PointerRNA id_ptr, ptr;
- PropertyRNA *prop;
- bool found = false;
-
- /* base pointer is always the object -> id_ptr */
- RNA_id_pointer_create(&ob->id, &id_ptr);
-
- /* resolve the property... */
- if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
- if (RNA_property_array_check(prop)) {
- /* array */
- if (fcu->array_index < RNA_property_array_length(&ptr, prop)) {
- found = true;
- switch (RNA_property_type(prop)) {
- case PROP_BOOLEAN:
- *value = (float)RNA_property_boolean_get_index(&ptr, prop, fcu->array_index);
- break;
- case PROP_INT:
- *value = (float)RNA_property_int_get_index(&ptr, prop, fcu->array_index);
- break;
- case PROP_FLOAT:
- *value = RNA_property_float_get_index(&ptr, prop, fcu->array_index);
- break;
- default:
- found = false;
- break;
- }
- }
- }
- else {
- /* not an array */
- found = true;
- switch (RNA_property_type(prop)) {
- case PROP_BOOLEAN:
- *value = (float)RNA_property_boolean_get(&ptr, prop);
- break;
- case PROP_INT:
- *value = (float)RNA_property_int_get(&ptr, prop);
- break;
- case PROP_ENUM:
- *value = (float)RNA_property_enum_get(&ptr, prop);
- break;
- case PROP_FLOAT:
- *value = RNA_property_float_get(&ptr, prop);
- break;
- default:
- found = false;
- break;
- }
- }
- }
-
- return found;
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ bool found = false;
+
+ /* base pointer is always the object -> id_ptr */
+ RNA_id_pointer_create(&ob->id, &id_ptr);
+
+ /* resolve the property... */
+ if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
+ if (RNA_property_array_check(prop)) {
+ /* array */
+ if (fcu->array_index < RNA_property_array_length(&ptr, prop)) {
+ found = true;
+ switch (RNA_property_type(prop)) {
+ case PROP_BOOLEAN:
+ *value = (float)RNA_property_boolean_get_index(&ptr, prop, fcu->array_index);
+ break;
+ case PROP_INT:
+ *value = (float)RNA_property_int_get_index(&ptr, prop, fcu->array_index);
+ break;
+ case PROP_FLOAT:
+ *value = RNA_property_float_get_index(&ptr, prop, fcu->array_index);
+ break;
+ default:
+ found = false;
+ break;
+ }
+ }
+ }
+ else {
+ /* not an array */
+ found = true;
+ switch (RNA_property_type(prop)) {
+ case PROP_BOOLEAN:
+ *value = (float)RNA_property_boolean_get(&ptr, prop);
+ break;
+ case PROP_INT:
+ *value = (float)RNA_property_int_get(&ptr, prop);
+ break;
+ case PROP_ENUM:
+ *value = (float)RNA_property_enum_get(&ptr, prop);
+ break;
+ case PROP_FLOAT:
+ *value = RNA_property_float_get(&ptr, prop);
+ break;
+ default:
+ found = false;
+ break;
+ }
+ }
+ }
+
+ return found;
}
/* propagate just works along each F-Curve in turn */
-static void pose_propagate_fcurve(wmOperator *op, Object *ob, FCurve *fcu,
- float startFrame, tPosePropagate_ModeData modeData)
+static void pose_propagate_fcurve(
+ wmOperator *op, Object *ob, FCurve *fcu, float startFrame, tPosePropagate_ModeData modeData)
{
- const int mode = RNA_enum_get(op->ptr, "mode");
-
- BezTriple *bezt;
- float refVal = 0.0f;
- bool keyExists;
- int i, match;
- short first = 1;
-
- /* skip if no keyframes to edit */
- if ((fcu->bezt == NULL) || (fcu->totvert < 2))
- return;
-
- /* find the reference value from bones directly, which means that the user
- * doesn't need to firstly keyframe the pose (though this doesn't mean that
- * they can't either)
- */
- if (!pose_propagate_get_refVal(ob, fcu, &refVal))
- return;
-
- /* find the first keyframe to start propagating from
- * - if there's a keyframe on the current frame, we probably want to save this value there too
- * since it may be as of yet unkeyed
- * - if starting before the starting frame, don't touch the key, as it may have had some valid
- * values
- * - if only doing selected keyframes, start from the first one
- */
- if (mode != POSE_PROPAGATE_SELECTED_KEYS) {
- match = binarysearch_bezt_index(fcu->bezt, startFrame, fcu->totvert, &keyExists);
-
- if (fcu->bezt[match].vec[1][0] < startFrame)
- i = match + 1;
- else
- i = match;
- }
- else {
- /* selected - start from first keyframe */
- i = 0;
- }
-
- for (bezt = &fcu->bezt[i]; i < fcu->totvert; i++, bezt++) {
- /* additional termination conditions based on the operator 'mode' property go here... */
- if (ELEM(mode, POSE_PROPAGATE_BEFORE_FRAME, POSE_PROPAGATE_SMART_HOLDS)) {
- /* stop if keyframe is outside the accepted range */
- if (bezt->vec[1][0] > modeData.end_frame)
- break;
- }
- else if (mode == POSE_PROPAGATE_NEXT_KEY) {
- /* stop after the first keyframe has been processed */
- if (first == 0)
- break;
- }
- else if (mode == POSE_PROPAGATE_LAST_KEY) {
- /* only affect this frame if it will be the last one */
- if (i != (fcu->totvert - 1))
- continue;
- }
- else if (mode == POSE_PROPAGATE_SELECTED_MARKERS) {
- /* only allow if there's a marker on this frame */
- CfraElem *ce = NULL;
-
- /* stop on matching marker if there is one */
- for (ce = modeData.sel_markers.first; ce; ce = ce->next) {
- if (ce->cfra == round_fl_to_int(bezt->vec[1][0]))
- break;
- }
-
- /* skip this keyframe if no marker */
- if (ce == NULL)
- continue;
- }
- else if (mode == POSE_PROPAGATE_SELECTED_KEYS) {
- /* only allow if this keyframe is already selected - skip otherwise */
- if (BEZT_ISSEL_ANY(bezt) == 0)
- continue;
- }
-
- /* just flatten handles, since values will now be the same either side... */
- /* TODO: perhaps a fade-out modulation of the value is required here (optional once again)? */
- bezt->vec[0][1] = bezt->vec[1][1] = bezt->vec[2][1] = refVal;
-
- /* select keyframe to indicate that it's been changed */
- bezt->f2 |= SELECT;
- first = 0;
- }
+ const int mode = RNA_enum_get(op->ptr, "mode");
+
+ BezTriple *bezt;
+ float refVal = 0.0f;
+ bool keyExists;
+ int i, match;
+ short first = 1;
+
+ /* skip if no keyframes to edit */
+ if ((fcu->bezt == NULL) || (fcu->totvert < 2))
+ return;
+
+ /* find the reference value from bones directly, which means that the user
+ * doesn't need to firstly keyframe the pose (though this doesn't mean that
+ * they can't either)
+ */
+ if (!pose_propagate_get_refVal(ob, fcu, &refVal))
+ return;
+
+ /* find the first keyframe to start propagating from
+ * - if there's a keyframe on the current frame, we probably want to save this value there too
+ * since it may be as of yet unkeyed
+ * - if starting before the starting frame, don't touch the key, as it may have had some valid
+ * values
+ * - if only doing selected keyframes, start from the first one
+ */
+ if (mode != POSE_PROPAGATE_SELECTED_KEYS) {
+ match = binarysearch_bezt_index(fcu->bezt, startFrame, fcu->totvert, &keyExists);
+
+ if (fcu->bezt[match].vec[1][0] < startFrame)
+ i = match + 1;
+ else
+ i = match;
+ }
+ else {
+ /* selected - start from first keyframe */
+ i = 0;
+ }
+
+ for (bezt = &fcu->bezt[i]; i < fcu->totvert; i++, bezt++) {
+ /* additional termination conditions based on the operator 'mode' property go here... */
+ if (ELEM(mode, POSE_PROPAGATE_BEFORE_FRAME, POSE_PROPAGATE_SMART_HOLDS)) {
+ /* stop if keyframe is outside the accepted range */
+ if (bezt->vec[1][0] > modeData.end_frame)
+ break;
+ }
+ else if (mode == POSE_PROPAGATE_NEXT_KEY) {
+ /* stop after the first keyframe has been processed */
+ if (first == 0)
+ break;
+ }
+ else if (mode == POSE_PROPAGATE_LAST_KEY) {
+ /* only affect this frame if it will be the last one */
+ if (i != (fcu->totvert - 1))
+ continue;
+ }
+ else if (mode == POSE_PROPAGATE_SELECTED_MARKERS) {
+ /* only allow if there's a marker on this frame */
+ CfraElem *ce = NULL;
+
+ /* stop on matching marker if there is one */
+ for (ce = modeData.sel_markers.first; ce; ce = ce->next) {
+ if (ce->cfra == round_fl_to_int(bezt->vec[1][0]))
+ break;
+ }
+
+ /* skip this keyframe if no marker */
+ if (ce == NULL)
+ continue;
+ }
+ else if (mode == POSE_PROPAGATE_SELECTED_KEYS) {
+ /* only allow if this keyframe is already selected - skip otherwise */
+ if (BEZT_ISSEL_ANY(bezt) == 0)
+ continue;
+ }
+
+ /* just flatten handles, since values will now be the same either side... */
+ /* TODO: perhaps a fade-out modulation of the value is required here (optional once again)? */
+ bezt->vec[0][1] = bezt->vec[1][1] = bezt->vec[2][1] = refVal;
+
+ /* select keyframe to indicate that it's been changed */
+ bezt->f2 |= SELECT;
+ first = 0;
+ }
}
/* --------------------------------- */
static int pose_propagate_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
-
- ListBase pflinks = {NULL, NULL};
- tPChanFCurveLink *pfl;
-
- tPosePropagate_ModeData modeData;
- const int mode = RNA_enum_get(op->ptr, "mode");
-
- /* isolate F-Curves related to the selected bones */
- poseAnim_mapping_get(C, &pflinks);
-
- if (BLI_listbase_is_empty(&pflinks)) {
- /* There is a change the reason the list is empty is that there is no valid object to propagate poses for.
- * This is very unlikely though, so we focus on the most likely issue. */
- BKE_report(op->reports, RPT_ERROR, "No keyframed poses to propagate to");
- return OPERATOR_CANCELLED;
- }
-
- /* mode-specific data preprocessing (requiring no access to curves) */
- if (mode == POSE_PROPAGATE_SELECTED_MARKERS) {
- /* get a list of selected markers */
- ED_markers_make_cfra_list(&scene->markers, &modeData.sel_markers, SELECT);
- }
- else {
- /* assume everything else wants endFrame */
- modeData.end_frame = RNA_float_get(op->ptr, "end_frame");
- }
-
- /* for each bone, perform the copying required */
- for (pfl = pflinks.first; pfl; pfl = pfl->next) {
- LinkData *ld;
-
- /* mode-specific data preprocessing (requiring access to all curves) */
- if (mode == POSE_PROPAGATE_SMART_HOLDS) {
- /* we store in endFrame the end frame of the "long keyframe" (i.e. a held value) starting
- * from the keyframe that occurs after the current frame
- */
- modeData.end_frame = pose_propagate_get_boneHoldEndFrame(pfl, (float)CFRA);
- }
-
- /* go through propagating pose to keyframes, curve by curve */
- for (ld = pfl->fcurves.first; ld; ld = ld->next) {
- pose_propagate_fcurve(op, pfl->ob, (FCurve *)ld->data, (float)CFRA, modeData);
- }
- }
-
- /* free temp data */
- poseAnim_mapping_free(&pflinks);
-
- if (mode == POSE_PROPAGATE_SELECTED_MARKERS)
- BLI_freelistN(&modeData.sel_markers);
-
- /* updates + notifiers */
- FOREACH_OBJECT_IN_MODE_BEGIN(view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
- poseAnim_mapping_refresh(C, scene, ob);
- } FOREACH_OBJECT_IN_MODE_END;
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ ListBase pflinks = {NULL, NULL};
+ tPChanFCurveLink *pfl;
+
+ tPosePropagate_ModeData modeData;
+ const int mode = RNA_enum_get(op->ptr, "mode");
+
+ /* isolate F-Curves related to the selected bones */
+ poseAnim_mapping_get(C, &pflinks);
+
+ if (BLI_listbase_is_empty(&pflinks)) {
+ /* There is a change the reason the list is empty is that there is no valid object to propagate poses for.
+ * This is very unlikely though, so we focus on the most likely issue. */
+ BKE_report(op->reports, RPT_ERROR, "No keyframed poses to propagate to");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* mode-specific data preprocessing (requiring no access to curves) */
+ if (mode == POSE_PROPAGATE_SELECTED_MARKERS) {
+ /* get a list of selected markers */
+ ED_markers_make_cfra_list(&scene->markers, &modeData.sel_markers, SELECT);
+ }
+ else {
+ /* assume everything else wants endFrame */
+ modeData.end_frame = RNA_float_get(op->ptr, "end_frame");
+ }
+
+ /* for each bone, perform the copying required */
+ for (pfl = pflinks.first; pfl; pfl = pfl->next) {
+ LinkData *ld;
+
+ /* mode-specific data preprocessing (requiring access to all curves) */
+ if (mode == POSE_PROPAGATE_SMART_HOLDS) {
+ /* we store in endFrame the end frame of the "long keyframe" (i.e. a held value) starting
+ * from the keyframe that occurs after the current frame
+ */
+ modeData.end_frame = pose_propagate_get_boneHoldEndFrame(pfl, (float)CFRA);
+ }
+
+ /* go through propagating pose to keyframes, curve by curve */
+ for (ld = pfl->fcurves.first; ld; ld = ld->next) {
+ pose_propagate_fcurve(op, pfl->ob, (FCurve *)ld->data, (float)CFRA, modeData);
+ }
+ }
+
+ /* free temp data */
+ poseAnim_mapping_free(&pflinks);
+
+ if (mode == POSE_PROPAGATE_SELECTED_MARKERS)
+ BLI_freelistN(&modeData.sel_markers);
+
+ /* updates + notifiers */
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
+ poseAnim_mapping_refresh(C, scene, ob);
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+
+ return OPERATOR_FINISHED;
}
/* --------------------------------- */
void POSE_OT_propagate(wmOperatorType *ot)
{
- static const EnumPropertyItem terminate_items[] = {
- {POSE_PROPAGATE_SMART_HOLDS, "WHILE_HELD", 0, "While Held",
- "Propagate pose to all keyframes after current frame that don't change (Default behavior)"},
- {POSE_PROPAGATE_NEXT_KEY, "NEXT_KEY", 0, "To Next Keyframe",
- "Propagate pose to first keyframe following the current frame only"},
- {POSE_PROPAGATE_LAST_KEY, "LAST_KEY", 0, "To Last Keyframe",
- "Propagate pose to the last keyframe only (i.e. making action cyclic)"},
- {POSE_PROPAGATE_BEFORE_FRAME, "BEFORE_FRAME", 0, "Before Frame",
- "Propagate pose to all keyframes between current frame and 'Frame' property"},
- {POSE_PROPAGATE_BEFORE_END, "BEFORE_END", 0, "Before Last Keyframe",
- "Propagate pose to all keyframes from current frame until no more are found"},
- {POSE_PROPAGATE_SELECTED_KEYS, "SELECTED_KEYS", 0, "On Selected Keyframes",
- "Propagate pose to all selected keyframes"},
- {POSE_PROPAGATE_SELECTED_MARKERS, "SELECTED_MARKERS", 0, "On Selected Markers",
- "Propagate pose to all keyframes occurring on frames with Scene Markers after the current frame"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Propagate Pose";
- ot->idname = "POSE_OT_propagate";
- ot->description = "Copy selected aspects of the current pose to subsequent poses already keyframed";
-
- /* callbacks */
- ot->exec = pose_propagate_exec;
- ot->poll = ED_operator_posemode; /* XXX: needs selected bones! */
-
- /* flag */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- /* TODO: add "fade out" control for tapering off amount of propagation as time goes by? */
- ot->prop = RNA_def_enum(ot->srna, "mode", terminate_items, POSE_PROPAGATE_SMART_HOLDS, "Terminate Mode", "Method used to determine when to stop propagating pose to keyframes");
- RNA_def_float(ot->srna, "end_frame", 250.0, FLT_MIN, FLT_MAX, "End Frame", "Frame to stop propagating frames to (for 'Before Frame' mode)", 1.0, 250.0);
+ static const EnumPropertyItem terminate_items[] = {
+ {POSE_PROPAGATE_SMART_HOLDS,
+ "WHILE_HELD",
+ 0,
+ "While Held",
+ "Propagate pose to all keyframes after current frame that don't change (Default behavior)"},
+ {POSE_PROPAGATE_NEXT_KEY,
+ "NEXT_KEY",
+ 0,
+ "To Next Keyframe",
+ "Propagate pose to first keyframe following the current frame only"},
+ {POSE_PROPAGATE_LAST_KEY,
+ "LAST_KEY",
+ 0,
+ "To Last Keyframe",
+ "Propagate pose to the last keyframe only (i.e. making action cyclic)"},
+ {POSE_PROPAGATE_BEFORE_FRAME,
+ "BEFORE_FRAME",
+ 0,
+ "Before Frame",
+ "Propagate pose to all keyframes between current frame and 'Frame' property"},
+ {POSE_PROPAGATE_BEFORE_END,
+ "BEFORE_END",
+ 0,
+ "Before Last Keyframe",
+ "Propagate pose to all keyframes from current frame until no more are found"},
+ {POSE_PROPAGATE_SELECTED_KEYS,
+ "SELECTED_KEYS",
+ 0,
+ "On Selected Keyframes",
+ "Propagate pose to all selected keyframes"},
+ {POSE_PROPAGATE_SELECTED_MARKERS,
+ "SELECTED_MARKERS",
+ 0,
+ "On Selected Markers",
+ "Propagate pose to all keyframes occurring on frames with Scene Markers after the current "
+ "frame"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Propagate Pose";
+ ot->idname = "POSE_OT_propagate";
+ ot->description =
+ "Copy selected aspects of the current pose to subsequent poses already keyframed";
+
+ /* callbacks */
+ ot->exec = pose_propagate_exec;
+ ot->poll = ED_operator_posemode; /* XXX: needs selected bones! */
+
+ /* flag */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ /* TODO: add "fade out" control for tapering off amount of propagation as time goes by? */
+ ot->prop = RNA_def_enum(ot->srna,
+ "mode",
+ terminate_items,
+ POSE_PROPAGATE_SMART_HOLDS,
+ "Terminate Mode",
+ "Method used to determine when to stop propagating pose to keyframes");
+ RNA_def_float(ot->srna,
+ "end_frame",
+ 250.0,
+ FLT_MIN,
+ FLT_MAX,
+ "End Frame",
+ "Frame to stop propagating frames to (for 'Before Frame' mode)",
+ 1.0,
+ 250.0);
}
/* **************************************************** */
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index cbb6d63aefe..3a4413f8c1d 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -61,7 +61,6 @@
#include "armature_intern.h"
-
/* ********************************************** */
/* Pose Apply */
@@ -69,216 +68,214 @@
* that are bone-parented to armature */
static void applyarmature_fix_boneparents(const bContext *C, Scene *scene, Object *armob)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Main *bmain = CTX_data_main(C);
- Object workob, *ob;
-
- /* go through all objects in database */
- for (ob = bmain->objects.first; ob; ob = ob->id.next) {
- /* if parent is bone in this armature, apply corrections */
- if ((ob->parent == armob) && (ob->partype == PARBONE)) {
- /* apply current transform from parent (not yet destroyed),
- * then calculate new parent inverse matrix
- */
- BKE_object_apply_mat4(ob, ob->obmat, false, false);
-
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
- }
- }
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Main *bmain = CTX_data_main(C);
+ Object workob, *ob;
+
+ /* go through all objects in database */
+ for (ob = bmain->objects.first; ob; ob = ob->id.next) {
+ /* if parent is bone in this armature, apply corrections */
+ if ((ob->parent == armob) && (ob->partype == PARBONE)) {
+ /* apply current transform from parent (not yet destroyed),
+ * then calculate new parent inverse matrix
+ */
+ BKE_object_apply_mat4(ob, ob->obmat, false, false);
+
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
+ invert_m4_m4(ob->parentinv, workob.obmat);
+ }
+ }
}
/* set the current pose as the restpose */
static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- // must be active object, not edit-object
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- bArmature *arm = BKE_armature_from_object(ob);
- bPose *pose;
- bPoseChannel *pchan;
- EditBone *curbone;
-
- /* don't check if editmode (should be done by caller) */
- if (ob->type != OB_ARMATURE)
- return OPERATOR_CANCELLED;
- if (BKE_object_obdata_is_libdata(ob)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot apply pose to lib-linked armature");
- return OPERATOR_CANCELLED;
- }
-
- /* helpful warnings... */
- /* TODO: add warnings to be careful about actions, applying deforms first, etc. */
- if (ob->adt && ob->adt->action)
- BKE_report(op->reports, RPT_WARNING,
- "Actions on this armature will be destroyed by this new rest pose as the "
- "transforms stored are relative to the old rest pose");
-
- /* Get editbones of active armature to alter */
- ED_armature_to_edit(arm);
-
- /* get pose of active object and move it out of posemode */
- pose = ob->pose;
-
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
- curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name);
-
- /* simply copy the head/tail values from pchan over to curbone */
- copy_v3_v3(curbone->head, pchan_eval->pose_head);
- copy_v3_v3(curbone->tail, pchan_eval->pose_tail);
-
- /* fix roll:
- * 1. find auto-calculated roll value for this bone now
- * 2. remove this from the 'visual' y-rotation
- */
- {
- float premat[3][3], imat[3][3], pmat[3][3], tmat[3][3];
- float delta[3], eul[3];
-
- /* obtain new auto y-rotation */
- sub_v3_v3v3(delta, curbone->tail, curbone->head);
- vec_roll_to_mat3(delta, 0.0f, premat);
- invert_m3_m3(imat, premat);
-
- /* get pchan 'visual' matrix */
- copy_m3_m4(pmat, pchan_eval->pose_mat);
-
- /* remove auto from visual and get euler rotation */
- mul_m3_m3m3(tmat, imat, pmat);
- mat3_to_eul(eul, tmat);
-
- /* just use this euler-y as new roll value */
- curbone->roll = eul[1];
- }
-
- /* combine pose and rest values for bendy bone settings,
- * then clear the pchan values (so we don't get a double-up)
- */
- if (pchan->bone->segments > 1) {
- /* combine rest/pose values */
- curbone->curveInX += pchan_eval->curveInX;
- curbone->curveInY += pchan_eval->curveInY;
- curbone->curveOutX += pchan_eval->curveOutX;
- curbone->curveOutY += pchan_eval->curveOutY;
- curbone->roll1 += pchan_eval->roll1;
- curbone->roll2 += pchan_eval->roll2;
- curbone->ease1 += pchan_eval->ease1;
- curbone->ease2 += pchan_eval->ease2;
- curbone->scaleIn += pchan_eval->scaleIn;
- curbone->scaleOut += pchan_eval->scaleOut;
-
- /* reset pose values */
- pchan->curveInX = pchan->curveOutX = 0.0f;
- pchan->curveInY = pchan->curveOutY = 0.0f;
- pchan->roll1 = pchan->roll2 = 0.0f;
- pchan->ease1 = pchan->ease2 = 0.0f;
- pchan->scaleIn = pchan->scaleOut = 1.0f;
- }
-
- /* clear transform values for pchan */
- zero_v3(pchan->loc);
- zero_v3(pchan->eul);
- unit_qt(pchan->quat);
- unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
- pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f;
-
- /* set anim lock */
- curbone->flag |= BONE_UNKEYED;
- }
-
- /* convert editbones back to bones, and then free the edit-data */
- ED_armature_from_edit(bmain, arm);
- ED_armature_edit_free(arm);
-
- /* flush positions of posebones */
- BKE_pose_where_is(depsgraph, scene, ob);
-
- /* fix parenting of objects which are bone-parented */
- applyarmature_fix_boneparents(C, scene, ob);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ // must be active object, not edit-object
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ bArmature *arm = BKE_armature_from_object(ob);
+ bPose *pose;
+ bPoseChannel *pchan;
+ EditBone *curbone;
+
+ /* don't check if editmode (should be done by caller) */
+ if (ob->type != OB_ARMATURE)
+ return OPERATOR_CANCELLED;
+ if (BKE_object_obdata_is_libdata(ob)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot apply pose to lib-linked armature");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* helpful warnings... */
+ /* TODO: add warnings to be careful about actions, applying deforms first, etc. */
+ if (ob->adt && ob->adt->action)
+ BKE_report(op->reports,
+ RPT_WARNING,
+ "Actions on this armature will be destroyed by this new rest pose as the "
+ "transforms stored are relative to the old rest pose");
+
+ /* Get editbones of active armature to alter */
+ ED_armature_to_edit(arm);
+
+ /* get pose of active object and move it out of posemode */
+ pose = ob->pose;
+
+ for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
+ const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
+ curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name);
+
+ /* simply copy the head/tail values from pchan over to curbone */
+ copy_v3_v3(curbone->head, pchan_eval->pose_head);
+ copy_v3_v3(curbone->tail, pchan_eval->pose_tail);
+
+ /* fix roll:
+ * 1. find auto-calculated roll value for this bone now
+ * 2. remove this from the 'visual' y-rotation
+ */
+ {
+ float premat[3][3], imat[3][3], pmat[3][3], tmat[3][3];
+ float delta[3], eul[3];
+
+ /* obtain new auto y-rotation */
+ sub_v3_v3v3(delta, curbone->tail, curbone->head);
+ vec_roll_to_mat3(delta, 0.0f, premat);
+ invert_m3_m3(imat, premat);
+
+ /* get pchan 'visual' matrix */
+ copy_m3_m4(pmat, pchan_eval->pose_mat);
+
+ /* remove auto from visual and get euler rotation */
+ mul_m3_m3m3(tmat, imat, pmat);
+ mat3_to_eul(eul, tmat);
+
+ /* just use this euler-y as new roll value */
+ curbone->roll = eul[1];
+ }
+
+ /* combine pose and rest values for bendy bone settings,
+ * then clear the pchan values (so we don't get a double-up)
+ */
+ if (pchan->bone->segments > 1) {
+ /* combine rest/pose values */
+ curbone->curveInX += pchan_eval->curveInX;
+ curbone->curveInY += pchan_eval->curveInY;
+ curbone->curveOutX += pchan_eval->curveOutX;
+ curbone->curveOutY += pchan_eval->curveOutY;
+ curbone->roll1 += pchan_eval->roll1;
+ curbone->roll2 += pchan_eval->roll2;
+ curbone->ease1 += pchan_eval->ease1;
+ curbone->ease2 += pchan_eval->ease2;
+ curbone->scaleIn += pchan_eval->scaleIn;
+ curbone->scaleOut += pchan_eval->scaleOut;
+
+ /* reset pose values */
+ pchan->curveInX = pchan->curveOutX = 0.0f;
+ pchan->curveInY = pchan->curveOutY = 0.0f;
+ pchan->roll1 = pchan->roll2 = 0.0f;
+ pchan->ease1 = pchan->ease2 = 0.0f;
+ pchan->scaleIn = pchan->scaleOut = 1.0f;
+ }
+
+ /* clear transform values for pchan */
+ zero_v3(pchan->loc);
+ zero_v3(pchan->eul);
+ unit_qt(pchan->quat);
+ unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
+ pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f;
+
+ /* set anim lock */
+ curbone->flag |= BONE_UNKEYED;
+ }
+
+ /* convert editbones back to bones, and then free the edit-data */
+ ED_armature_from_edit(bmain, arm);
+ ED_armature_edit_free(arm);
+
+ /* flush positions of posebones */
+ BKE_pose_where_is(depsgraph, scene, ob);
+
+ /* fix parenting of objects which are bone-parented */
+ applyarmature_fix_boneparents(C, scene, ob);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+
+ return OPERATOR_FINISHED;
}
void POSE_OT_armature_apply(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Apply Pose as Rest Pose";
- ot->idname = "POSE_OT_armature_apply";
- ot->description = "Apply the current pose as the new rest pose";
+ /* identifiers */
+ ot->name = "Apply Pose as Rest Pose";
+ ot->idname = "POSE_OT_armature_apply";
+ ot->description = "Apply the current pose as the new rest pose";
- /* callbacks */
- ot->exec = apply_armature_pose2bones_exec;
- ot->poll = ED_operator_posemode;
+ /* callbacks */
+ ot->exec = apply_armature_pose2bones_exec;
+ ot->poll = ED_operator_posemode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/* set the current pose as the restpose */
static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
-
- FOREACH_OBJECT_IN_MODE_BEGIN(view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob)
- {
- /* loop over all selected pchans
- *
- * TODO, loop over children before parents if multiple bones
- * at once are to be predictable*/
- FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob, pchan)
- {
- const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
- float delta_mat[4][4];
-
- /* chan_mat already contains the delta transform from rest pose to pose-mode pose
- * as that is baked into there so that B-Bones will work. Once we've set this as the
- * new raw-transform components, don't recalc the poses yet, otherwise IK result will
- * change, thus changing the result we may be trying to record.
- */
- /* XXX For some reason, we can't use pchan->chan_mat here, gives odd rotation/offset (see T38251).
- * Using pchan->pose_mat and bringing it back in bone space seems to work as expected!
- */
- BKE_armature_mat_pose_to_bone(pchan_eval, pchan_eval->pose_mat, delta_mat);
-
- BKE_pchan_apply_mat4(pchan, delta_mat, true);
- }
- FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- }
- FOREACH_OBJECT_IN_MODE_END;
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
+ /* loop over all selected pchans
+ *
+ * TODO, loop over children before parents if multiple bones
+ * at once are to be predictable*/
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob, pchan) {
+ const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
+ float delta_mat[4][4];
+
+ /* chan_mat already contains the delta transform from rest pose to pose-mode pose
+ * as that is baked into there so that B-Bones will work. Once we've set this as the
+ * new raw-transform components, don't recalc the poses yet, otherwise IK result will
+ * change, thus changing the result we may be trying to record.
+ */
+ /* XXX For some reason, we can't use pchan->chan_mat here, gives odd rotation/offset (see T38251).
+ * Using pchan->pose_mat and bringing it back in bone space seems to work as expected!
+ */
+ BKE_armature_mat_pose_to_bone(pchan_eval, pchan_eval->pose_mat, delta_mat);
+
+ BKE_pchan_apply_mat4(pchan, delta_mat, true);
+ }
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+
+ return OPERATOR_FINISHED;
}
void POSE_OT_visual_transform_apply(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Apply Visual Transform to Pose";
- ot->idname = "POSE_OT_visual_transform_apply";
- ot->description = "Apply final constrained position of pose bones to their transform";
+ /* identifiers */
+ ot->name = "Apply Visual Transform to Pose";
+ ot->idname = "POSE_OT_visual_transform_apply";
+ ot->description = "Apply final constrained position of pose bones to their transform";
- /* callbacks */
- ot->exec = pose_visual_transform_apply_exec;
- ot->poll = ED_operator_posemode;
+ /* callbacks */
+ ot->exec = pose_visual_transform_apply_exec;
+ ot->poll = ED_operator_posemode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************************************** */
@@ -289,18 +286,18 @@ void POSE_OT_visual_transform_apply(wmOperatorType *ot)
*/
static void set_pose_keys(Object *ob)
{
- bArmature *arm = ob->data;
- bPoseChannel *chan;
-
- if (ob->pose) {
- for (chan = ob->pose->chanbase.first; chan; chan = chan->next) {
- Bone *bone = chan->bone;
- if ((bone) && (bone->flag & BONE_SELECTED) && (arm->layer & bone->layer))
- chan->flag |= POSE_KEY;
- else
- chan->flag &= ~POSE_KEY;
- }
- }
+ bArmature *arm = ob->data;
+ bPoseChannel *chan;
+
+ if (ob->pose) {
+ for (chan = ob->pose->chanbase.first; chan; chan = chan->next) {
+ Bone *bone = chan->bone;
+ if ((bone) && (bone->flag & BONE_SELECTED) && (arm->layer & bone->layer))
+ chan->flag |= POSE_KEY;
+ else
+ chan->flag &= ~POSE_KEY;
+ }
+ }
}
/**
@@ -312,304 +309,315 @@ static void set_pose_keys(Object *ob)
* \param flip: Flip on x-axis
* \return Whether the bone that we pasted to if we succeeded
*/
-static bPoseChannel *pose_bone_do_paste(Object *ob, bPoseChannel *chan, const bool selOnly, const bool flip)
+static bPoseChannel *pose_bone_do_paste(Object *ob,
+ bPoseChannel *chan,
+ const bool selOnly,
+ const bool flip)
{
- bPoseChannel *pchan;
- char name[MAXBONENAME];
- short paste_ok;
-
- /* get the name - if flipping, we must flip this first */
- if (flip)
- BLI_string_flip_side_name(name, chan->name, false, sizeof(name));
- else
- BLI_strncpy(name, chan->name, sizeof(name));
-
- /* only copy when:
- * 1) channel exists - poses are not meant to add random channels to anymore
- * 2) if selection-masking is on, channel is selected - only selected bones get pasted on, allowing making both sides symmetrical
- */
- pchan = BKE_pose_channel_find_name(ob->pose, name);
-
- if (selOnly)
- paste_ok = ((pchan) && (pchan->bone->flag & BONE_SELECTED));
- else
- paste_ok = (pchan != NULL);
-
- /* continue? */
- if (paste_ok) {
- /* only loc rot size
- * - only copies transform info for the pose
- */
- copy_v3_v3(pchan->loc, chan->loc);
- copy_v3_v3(pchan->size, chan->size);
- pchan->flag = chan->flag;
-
- /* check if rotation modes are compatible (i.e. do they need any conversions) */
- if (pchan->rotmode == chan->rotmode) {
- /* copy the type of rotation in use */
- if (pchan->rotmode > 0) {
- copy_v3_v3(pchan->eul, chan->eul);
- }
- else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- copy_v3_v3(pchan->rotAxis, chan->rotAxis);
- pchan->rotAngle = chan->rotAngle;
- }
- else {
- copy_qt_qt(pchan->quat, chan->quat);
- }
- }
- else if (pchan->rotmode > 0) {
- /* quat/axis-angle to euler */
- if (chan->rotmode == ROT_MODE_AXISANGLE)
- axis_angle_to_eulO(pchan->eul, pchan->rotmode, chan->rotAxis, chan->rotAngle);
- else
- quat_to_eulO(pchan->eul, pchan->rotmode, chan->quat);
- }
- else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- /* quat/euler to axis angle */
- if (chan->rotmode > 0)
- eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->eul, chan->rotmode);
- else
- quat_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->quat);
- }
- else {
- /* euler/axis-angle to quat */
- if (chan->rotmode > 0)
- eulO_to_quat(pchan->quat, chan->eul, chan->rotmode);
- else
- axis_angle_to_quat(pchan->quat, chan->rotAxis, pchan->rotAngle);
- }
-
- /* B-Bone posing options should also be included... */
- pchan->curveInX = chan->curveInX;
- pchan->curveInY = chan->curveInY;
- pchan->curveOutX = chan->curveOutX;
- pchan->curveOutY = chan->curveOutY;
-
- pchan->roll1 = chan->roll1;
- pchan->roll2 = chan->roll2;
- pchan->ease1 = chan->ease1;
- pchan->ease2 = chan->ease2;
- pchan->scaleIn = chan->scaleIn;
- pchan->scaleOut = chan->scaleOut;
-
- /* paste flipped pose? */
- if (flip) {
- pchan->loc[0] *= -1;
-
- pchan->curveInX *= -1;
- pchan->curveOutX *= -1;
- pchan->roll1 *= -1; // XXX?
- pchan->roll2 *= -1; // XXX?
-
- /* has to be done as eulers... */
- if (pchan->rotmode > 0) {
- pchan->eul[1] *= -1;
- pchan->eul[2] *= -1;
- }
- else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- float eul[3];
-
- axis_angle_to_eulO(eul, EULER_ORDER_DEFAULT, pchan->rotAxis, pchan->rotAngle);
- eul[1] *= -1;
- eul[2] *= -1;
- eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, eul, EULER_ORDER_DEFAULT);
- }
- else {
- float eul[3];
-
- normalize_qt(pchan->quat);
- quat_to_eul(eul, pchan->quat);
- eul[1] *= -1;
- eul[2] *= -1;
- eul_to_quat(pchan->quat, eul);
- }
- }
-
- /* ID properties */
- if (chan->prop) {
- if (pchan->prop) {
- /* if we have existing properties on a bone, just copy over the values of
- * matching properties (i.e. ones which will have some impact) on to the
- * target instead of just blinding replacing all [
- */
- IDP_SyncGroupValues(pchan->prop, chan->prop);
- }
- else {
- /* no existing properties, so assume that we want copies too? */
- pchan->prop = IDP_CopyProperty(chan->prop);
- }
- }
- }
-
- /* return whether paste went ahead */
- return pchan;
+ bPoseChannel *pchan;
+ char name[MAXBONENAME];
+ short paste_ok;
+
+ /* get the name - if flipping, we must flip this first */
+ if (flip)
+ BLI_string_flip_side_name(name, chan->name, false, sizeof(name));
+ else
+ BLI_strncpy(name, chan->name, sizeof(name));
+
+ /* only copy when:
+ * 1) channel exists - poses are not meant to add random channels to anymore
+ * 2) if selection-masking is on, channel is selected - only selected bones get pasted on, allowing making both sides symmetrical
+ */
+ pchan = BKE_pose_channel_find_name(ob->pose, name);
+
+ if (selOnly)
+ paste_ok = ((pchan) && (pchan->bone->flag & BONE_SELECTED));
+ else
+ paste_ok = (pchan != NULL);
+
+ /* continue? */
+ if (paste_ok) {
+ /* only loc rot size
+ * - only copies transform info for the pose
+ */
+ copy_v3_v3(pchan->loc, chan->loc);
+ copy_v3_v3(pchan->size, chan->size);
+ pchan->flag = chan->flag;
+
+ /* check if rotation modes are compatible (i.e. do they need any conversions) */
+ if (pchan->rotmode == chan->rotmode) {
+ /* copy the type of rotation in use */
+ if (pchan->rotmode > 0) {
+ copy_v3_v3(pchan->eul, chan->eul);
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ copy_v3_v3(pchan->rotAxis, chan->rotAxis);
+ pchan->rotAngle = chan->rotAngle;
+ }
+ else {
+ copy_qt_qt(pchan->quat, chan->quat);
+ }
+ }
+ else if (pchan->rotmode > 0) {
+ /* quat/axis-angle to euler */
+ if (chan->rotmode == ROT_MODE_AXISANGLE)
+ axis_angle_to_eulO(pchan->eul, pchan->rotmode, chan->rotAxis, chan->rotAngle);
+ else
+ quat_to_eulO(pchan->eul, pchan->rotmode, chan->quat);
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ /* quat/euler to axis angle */
+ if (chan->rotmode > 0)
+ eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->eul, chan->rotmode);
+ else
+ quat_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->quat);
+ }
+ else {
+ /* euler/axis-angle to quat */
+ if (chan->rotmode > 0)
+ eulO_to_quat(pchan->quat, chan->eul, chan->rotmode);
+ else
+ axis_angle_to_quat(pchan->quat, chan->rotAxis, pchan->rotAngle);
+ }
+
+ /* B-Bone posing options should also be included... */
+ pchan->curveInX = chan->curveInX;
+ pchan->curveInY = chan->curveInY;
+ pchan->curveOutX = chan->curveOutX;
+ pchan->curveOutY = chan->curveOutY;
+
+ pchan->roll1 = chan->roll1;
+ pchan->roll2 = chan->roll2;
+ pchan->ease1 = chan->ease1;
+ pchan->ease2 = chan->ease2;
+ pchan->scaleIn = chan->scaleIn;
+ pchan->scaleOut = chan->scaleOut;
+
+ /* paste flipped pose? */
+ if (flip) {
+ pchan->loc[0] *= -1;
+
+ pchan->curveInX *= -1;
+ pchan->curveOutX *= -1;
+ pchan->roll1 *= -1; // XXX?
+ pchan->roll2 *= -1; // XXX?
+
+ /* has to be done as eulers... */
+ if (pchan->rotmode > 0) {
+ pchan->eul[1] *= -1;
+ pchan->eul[2] *= -1;
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ float eul[3];
+
+ axis_angle_to_eulO(eul, EULER_ORDER_DEFAULT, pchan->rotAxis, pchan->rotAngle);
+ eul[1] *= -1;
+ eul[2] *= -1;
+ eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, eul, EULER_ORDER_DEFAULT);
+ }
+ else {
+ float eul[3];
+
+ normalize_qt(pchan->quat);
+ quat_to_eul(eul, pchan->quat);
+ eul[1] *= -1;
+ eul[2] *= -1;
+ eul_to_quat(pchan->quat, eul);
+ }
+ }
+
+ /* ID properties */
+ if (chan->prop) {
+ if (pchan->prop) {
+ /* if we have existing properties on a bone, just copy over the values of
+ * matching properties (i.e. ones which will have some impact) on to the
+ * target instead of just blinding replacing all [
+ */
+ IDP_SyncGroupValues(pchan->prop, chan->prop);
+ }
+ else {
+ /* no existing properties, so assume that we want copies too? */
+ pchan->prop = IDP_CopyProperty(chan->prop);
+ }
+ }
+ }
+
+ /* return whether paste went ahead */
+ return pchan;
}
/* ---- */
static int pose_copy_exec(bContext *C, wmOperator *op)
{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- char str[FILE_MAX];
- /* Sanity checking. */
- if (ELEM(NULL, ob, ob->pose)) {
- BKE_report(op->reports, RPT_ERROR, "No pose to copy");
- return OPERATOR_CANCELLED;
- }
- /* Sets chan->flag to POSE_KEY if bone selected. */
- set_pose_keys(ob);
- /* Construct a local bmain and only put object and it's data into it,
- * o this way we don't expand any other objects into the copy buffer
- * file.
- *
- * TODO(sergey): Find an easier way to tell copy buffer to only store
- * data we are actually interested in. Maybe pass it a flag to skip
- * any datablock expansion?
- */
- Main *temp_bmain = BKE_main_new();
- Object ob_copy = *ob;
- bArmature arm_copy = *((bArmature *)ob->data);
- ob_copy.data = &arm_copy;
- BLI_addtail(&temp_bmain->objects, &ob_copy);
- BLI_addtail(&temp_bmain->armatures, &arm_copy);
- /* begin copy buffer on a temp bmain. */
- BKE_copybuffer_begin(temp_bmain);
- /* Store the whole object to the copy buffer because pose can't be
- * existing on it's own.
- */
- BKE_copybuffer_tag_ID(&ob_copy.id);
- BLI_make_file_string("/", 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
- * as the real ones.
- */
- BLI_listbase_clear(&temp_bmain->objects);
- BLI_listbase_clear(&temp_bmain->armatures);
- BKE_main_free(temp_bmain);
- /* We are all done! */
- BKE_report(op->reports, RPT_INFO, "Copied pose to buffer");
- return OPERATOR_FINISHED;
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ char str[FILE_MAX];
+ /* Sanity checking. */
+ if (ELEM(NULL, ob, ob->pose)) {
+ BKE_report(op->reports, RPT_ERROR, "No pose to copy");
+ return OPERATOR_CANCELLED;
+ }
+ /* Sets chan->flag to POSE_KEY if bone selected. */
+ set_pose_keys(ob);
+ /* Construct a local bmain and only put object and it's data into it,
+ * o this way we don't expand any other objects into the copy buffer
+ * file.
+ *
+ * TODO(sergey): Find an easier way to tell copy buffer to only store
+ * data we are actually interested in. Maybe pass it a flag to skip
+ * any datablock expansion?
+ */
+ Main *temp_bmain = BKE_main_new();
+ Object ob_copy = *ob;
+ bArmature arm_copy = *((bArmature *)ob->data);
+ ob_copy.data = &arm_copy;
+ BLI_addtail(&temp_bmain->objects, &ob_copy);
+ BLI_addtail(&temp_bmain->armatures, &arm_copy);
+ /* begin copy buffer on a temp bmain. */
+ BKE_copybuffer_begin(temp_bmain);
+ /* Store the whole object to the copy buffer because pose can't be
+ * existing on it's own.
+ */
+ BKE_copybuffer_tag_ID(&ob_copy.id);
+ BLI_make_file_string("/", 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
+ * as the real ones.
+ */
+ BLI_listbase_clear(&temp_bmain->objects);
+ BLI_listbase_clear(&temp_bmain->armatures);
+ BKE_main_free(temp_bmain);
+ /* We are all done! */
+ BKE_report(op->reports, RPT_INFO, "Copied pose to buffer");
+ return OPERATOR_FINISHED;
}
void POSE_OT_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Pose";
- ot->idname = "POSE_OT_copy";
- ot->description = "Copies the current pose of the selected bones to copy/paste buffer";
+ /* identifiers */
+ ot->name = "Copy Pose";
+ ot->idname = "POSE_OT_copy";
+ ot->description = "Copies the current pose of the selected bones to copy/paste buffer";
- /* api callbacks */
- ot->exec = pose_copy_exec;
- ot->poll = ED_operator_posemode;
+ /* api callbacks */
+ ot->exec = pose_copy_exec;
+ ot->poll = ED_operator_posemode;
- /* flag */
- ot->flag = OPTYPE_REGISTER;
+ /* flag */
+ ot->flag = OPTYPE_REGISTER;
}
/* ---- */
static int pose_paste_exec(bContext *C, wmOperator *op)
{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- Scene *scene = CTX_data_scene(C);
- bPoseChannel *chan;
- const bool flip = RNA_boolean_get(op->ptr, "flipped");
- bool selOnly = RNA_boolean_get(op->ptr, "selected_mask");
-
- /* Get KeyingSet to use. */
- KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
-
- /* Sanity checks. */
- if (ELEM(NULL, ob, ob->pose)) {
- return OPERATOR_CANCELLED;
- }
-
- /* 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");
- 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);
- return OPERATOR_CANCELLED;
- }
- /* Make sure data from this file is usable for pose paste. */
- if (BLI_listbase_count_at_most(&tmp_bmain->objects, 2) != 1) {
- BKE_report(op->reports, RPT_ERROR, "Copy buffer is not from pose mode");
- BKE_main_free(tmp_bmain);
- return OPERATOR_CANCELLED;
- }
-
- Object *object_from = tmp_bmain->objects.first;
- bPose *pose_from = object_from->pose;
- if (pose_from == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Copy buffer has no pose");
- BKE_main_free(tmp_bmain);
- return OPERATOR_CANCELLED;
- }
-
- /* If selOnly option is enabled, if user hasn't selected any bones,
- * just go back to default behavior to be more in line with other
- * pose tools.
- */
- if (selOnly) {
- if (CTX_DATA_COUNT(C, selected_pose_bones) == 0) {
- selOnly = false;
- }
- }
-
- /* Safely merge all of the channels in the buffer pose into any
- * existing pose.
- */
- for (chan = pose_from->chanbase.first; chan; chan = chan->next) {
- if (chan->flag & POSE_KEY) {
- /* Try to perform paste on this bone. */
- bPoseChannel *pchan = pose_bone_do_paste(ob, chan, selOnly, flip);
- if (pchan != NULL) {
- /* Keyframing tagging for successful paste, */
- ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
- }
- }
- }
- BKE_main_free(tmp_bmain);
-
- /* Update event for pose and deformation children. */
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
-
- /* Recalculate paths if any of the bones have paths... */
- if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) {
- ED_pose_recalculate_paths(C, scene, ob, false);
- }
-
- /* Notifiers for updates, */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ Scene *scene = CTX_data_scene(C);
+ bPoseChannel *chan;
+ const bool flip = RNA_boolean_get(op->ptr, "flipped");
+ bool selOnly = RNA_boolean_get(op->ptr, "selected_mask");
+
+ /* Get KeyingSet to use. */
+ KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
+
+ /* Sanity checks. */
+ if (ELEM(NULL, ob, ob->pose)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* 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");
+ 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);
+ return OPERATOR_CANCELLED;
+ }
+ /* Make sure data from this file is usable for pose paste. */
+ if (BLI_listbase_count_at_most(&tmp_bmain->objects, 2) != 1) {
+ BKE_report(op->reports, RPT_ERROR, "Copy buffer is not from pose mode");
+ BKE_main_free(tmp_bmain);
+ return OPERATOR_CANCELLED;
+ }
+
+ Object *object_from = tmp_bmain->objects.first;
+ bPose *pose_from = object_from->pose;
+ if (pose_from == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Copy buffer has no pose");
+ BKE_main_free(tmp_bmain);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* If selOnly option is enabled, if user hasn't selected any bones,
+ * just go back to default behavior to be more in line with other
+ * pose tools.
+ */
+ if (selOnly) {
+ if (CTX_DATA_COUNT(C, selected_pose_bones) == 0) {
+ selOnly = false;
+ }
+ }
+
+ /* Safely merge all of the channels in the buffer pose into any
+ * existing pose.
+ */
+ for (chan = pose_from->chanbase.first; chan; chan = chan->next) {
+ if (chan->flag & POSE_KEY) {
+ /* Try to perform paste on this bone. */
+ bPoseChannel *pchan = pose_bone_do_paste(ob, chan, selOnly, flip);
+ if (pchan != NULL) {
+ /* Keyframing tagging for successful paste, */
+ ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
+ }
+ }
+ }
+ BKE_main_free(tmp_bmain);
+
+ /* Update event for pose and deformation children. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+
+ /* Recalculate paths if any of the bones have paths... */
+ if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) {
+ ED_pose_recalculate_paths(C, scene, ob, false);
+ }
+
+ /* Notifiers for updates, */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
}
void POSE_OT_paste(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Paste Pose";
- ot->idname = "POSE_OT_paste";
- ot->description = "Paste the stored pose on to the current pose";
-
- /* api callbacks */
- ot->exec = pose_paste_exec;
- ot->poll = ED_operator_posemode;
-
- /* flag */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_boolean(ot->srna, "flipped", false, "Flipped on X-Axis", "Paste the stored pose flipped on to current pose");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- RNA_def_boolean(ot->srna, "selected_mask", false, "On Selected Only", "Only paste the stored pose on to selected bones in the current pose");
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Paste Pose";
+ ot->idname = "POSE_OT_paste";
+ ot->description = "Paste the stored pose on to the current pose";
+
+ /* api callbacks */
+ ot->exec = pose_paste_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flag */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna,
+ "flipped",
+ false,
+ "Flipped on X-Axis",
+ "Paste the stored pose flipped on to current pose");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ RNA_def_boolean(ot->srna,
+ "selected_mask",
+ false,
+ "On Selected Only",
+ "Only paste the stored pose on to selected bones in the current pose");
}
/* ********************************************** */
@@ -618,313 +626,317 @@ void POSE_OT_paste(wmOperatorType *ot)
/* clear scale of pose-channel */
static void pchan_clear_scale(bPoseChannel *pchan)
{
- if ((pchan->protectflag & OB_LOCK_SCALEX) == 0)
- pchan->size[0] = 1.0f;
- if ((pchan->protectflag & OB_LOCK_SCALEY) == 0)
- pchan->size[1] = 1.0f;
- if ((pchan->protectflag & OB_LOCK_SCALEZ) == 0)
- pchan->size[2] = 1.0f;
-
- pchan->ease1 = 0.0f;
- pchan->ease2 = 0.0f;
- pchan->scaleIn = 1.0f;
- pchan->scaleOut = 1.0f;
+ if ((pchan->protectflag & OB_LOCK_SCALEX) == 0)
+ pchan->size[0] = 1.0f;
+ if ((pchan->protectflag & OB_LOCK_SCALEY) == 0)
+ pchan->size[1] = 1.0f;
+ if ((pchan->protectflag & OB_LOCK_SCALEZ) == 0)
+ pchan->size[2] = 1.0f;
+
+ pchan->ease1 = 0.0f;
+ pchan->ease2 = 0.0f;
+ pchan->scaleIn = 1.0f;
+ pchan->scaleOut = 1.0f;
}
/* clear location of pose-channel */
static void pchan_clear_loc(bPoseChannel *pchan)
{
- if ((pchan->protectflag & OB_LOCK_LOCX) == 0)
- pchan->loc[0] = 0.0f;
- if ((pchan->protectflag & OB_LOCK_LOCY) == 0)
- pchan->loc[1] = 0.0f;
- if ((pchan->protectflag & OB_LOCK_LOCZ) == 0)
- pchan->loc[2] = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_LOCX) == 0)
+ pchan->loc[0] = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_LOCY) == 0)
+ pchan->loc[1] = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_LOCZ) == 0)
+ pchan->loc[2] = 0.0f;
}
/* clear rotation of pose-channel */
static void pchan_clear_rot(bPoseChannel *pchan)
{
- if (pchan->protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) {
- /* check if convert to eulers for locking... */
- if (pchan->protectflag & OB_LOCK_ROT4D) {
- /* perform clamping on a component by component basis */
- if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
- pchan->rotAngle = 0.0f;
- if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
- pchan->rotAxis[0] = 0.0f;
- if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
- pchan->rotAxis[1] = 0.0f;
- if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
- pchan->rotAxis[2] = 0.0f;
-
- /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */
- if (IS_EQF(pchan->rotAxis[0], pchan->rotAxis[1]) && IS_EQF(pchan->rotAxis[1], pchan->rotAxis[2]))
- pchan->rotAxis[1] = 1.0f;
- }
- else if (pchan->rotmode == ROT_MODE_QUAT) {
- if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
- pchan->quat[0] = 1.0f;
- if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
- pchan->quat[1] = 0.0f;
- if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
- pchan->quat[2] = 0.0f;
- if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
- pchan->quat[3] = 0.0f;
- }
- else {
- /* the flag may have been set for the other modes, so just ignore the extra flag... */
- if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
- pchan->eul[0] = 0.0f;
- if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
- pchan->eul[1] = 0.0f;
- if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
- pchan->eul[2] = 0.0f;
- }
- }
- else {
- /* perform clamping using euler form (3-components) */
- float eul[3], oldeul[3], quat1[4] = {0};
- float qlen = 0.0f;
-
- if (pchan->rotmode == ROT_MODE_QUAT) {
- qlen = normalize_qt_qt(quat1, pchan->quat);
- quat_to_eul(oldeul, quat1);
- }
- else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, pchan->rotAxis, pchan->rotAngle);
- }
- else {
- copy_v3_v3(oldeul, pchan->eul);
- }
-
- eul[0] = eul[1] = eul[2] = 0.0f;
-
- if (pchan->protectflag & OB_LOCK_ROTX)
- eul[0] = oldeul[0];
- if (pchan->protectflag & OB_LOCK_ROTY)
- eul[1] = oldeul[1];
- if (pchan->protectflag & OB_LOCK_ROTZ)
- eul[2] = oldeul[2];
-
- if (pchan->rotmode == ROT_MODE_QUAT) {
- eul_to_quat(pchan->quat, eul);
-
- /* restore original quat size */
- mul_qt_fl(pchan->quat, qlen);
-
- /* quaternions flip w sign to accumulate rotations correctly */
- if ((quat1[0] < 0.0f && pchan->quat[0] > 0.0f) || (quat1[0] > 0.0f && pchan->quat[0] < 0.0f)) {
- mul_qt_fl(pchan->quat, -1.0f);
- }
- }
- else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, eul, EULER_ORDER_DEFAULT);
- }
- else {
- copy_v3_v3(pchan->eul, eul);
- }
- }
- } /* Duplicated in source/blender/editors/object/object_transform.c */
- else {
- if (pchan->rotmode == ROT_MODE_QUAT) {
- unit_qt(pchan->quat);
- }
- else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- /* by default, make rotation of 0 radians around y-axis (roll) */
- unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
- }
- else {
- zero_v3(pchan->eul);
- }
- }
-
- /* Clear also Bendy Bone stuff - Roll is obvious,
- * but Curve X/Y stuff is also kindof rotational in nature... */
- pchan->roll1 = 0.0f;
- pchan->roll2 = 0.0f;
-
- pchan->curveInX = 0.0f;
- pchan->curveInY = 0.0f;
- pchan->curveOutX = 0.0f;
- pchan->curveOutY = 0.0f;
+ if (pchan->protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) {
+ /* check if convert to eulers for locking... */
+ if (pchan->protectflag & OB_LOCK_ROT4D) {
+ /* perform clamping on a component by component basis */
+ if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
+ pchan->rotAngle = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
+ pchan->rotAxis[0] = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
+ pchan->rotAxis[1] = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
+ pchan->rotAxis[2] = 0.0f;
+
+ /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */
+ if (IS_EQF(pchan->rotAxis[0], pchan->rotAxis[1]) &&
+ IS_EQF(pchan->rotAxis[1], pchan->rotAxis[2]))
+ pchan->rotAxis[1] = 1.0f;
+ }
+ else if (pchan->rotmode == ROT_MODE_QUAT) {
+ if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
+ pchan->quat[0] = 1.0f;
+ if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
+ pchan->quat[1] = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
+ pchan->quat[2] = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
+ pchan->quat[3] = 0.0f;
+ }
+ else {
+ /* the flag may have been set for the other modes, so just ignore the extra flag... */
+ if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
+ pchan->eul[0] = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
+ pchan->eul[1] = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
+ pchan->eul[2] = 0.0f;
+ }
+ }
+ else {
+ /* perform clamping using euler form (3-components) */
+ float eul[3], oldeul[3], quat1[4] = {0};
+ float qlen = 0.0f;
+
+ if (pchan->rotmode == ROT_MODE_QUAT) {
+ qlen = normalize_qt_qt(quat1, pchan->quat);
+ quat_to_eul(oldeul, quat1);
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, pchan->rotAxis, pchan->rotAngle);
+ }
+ else {
+ copy_v3_v3(oldeul, pchan->eul);
+ }
+
+ eul[0] = eul[1] = eul[2] = 0.0f;
+
+ if (pchan->protectflag & OB_LOCK_ROTX)
+ eul[0] = oldeul[0];
+ if (pchan->protectflag & OB_LOCK_ROTY)
+ eul[1] = oldeul[1];
+ if (pchan->protectflag & OB_LOCK_ROTZ)
+ eul[2] = oldeul[2];
+
+ if (pchan->rotmode == ROT_MODE_QUAT) {
+ eul_to_quat(pchan->quat, eul);
+
+ /* restore original quat size */
+ mul_qt_fl(pchan->quat, qlen);
+
+ /* quaternions flip w sign to accumulate rotations correctly */
+ if ((quat1[0] < 0.0f && pchan->quat[0] > 0.0f) ||
+ (quat1[0] > 0.0f && pchan->quat[0] < 0.0f)) {
+ mul_qt_fl(pchan->quat, -1.0f);
+ }
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, eul, EULER_ORDER_DEFAULT);
+ }
+ else {
+ copy_v3_v3(pchan->eul, eul);
+ }
+ }
+ } /* Duplicated in source/blender/editors/object/object_transform.c */
+ else {
+ if (pchan->rotmode == ROT_MODE_QUAT) {
+ unit_qt(pchan->quat);
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ /* by default, make rotation of 0 radians around y-axis (roll) */
+ unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
+ }
+ else {
+ zero_v3(pchan->eul);
+ }
+ }
+
+ /* Clear also Bendy Bone stuff - Roll is obvious,
+ * but Curve X/Y stuff is also kindof rotational in nature... */
+ pchan->roll1 = 0.0f;
+ pchan->roll2 = 0.0f;
+
+ pchan->curveInX = 0.0f;
+ pchan->curveInY = 0.0f;
+ pchan->curveOutX = 0.0f;
+ pchan->curveOutY = 0.0f;
}
/* clear loc/rot/scale of pose-channel */
static void pchan_clear_transforms(bPoseChannel *pchan)
{
- pchan_clear_loc(pchan);
- pchan_clear_rot(pchan);
- pchan_clear_scale(pchan);
+ pchan_clear_loc(pchan);
+ pchan_clear_rot(pchan);
+ pchan_clear_scale(pchan);
}
/* --------------- */
/* generic exec for clear-pose operators */
-static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op,
- void (*clear_func)(bPoseChannel *), const char default_ksName[])
+static int pose_clear_transform_generic_exec(bContext *C,
+ wmOperator *op,
+ void (*clear_func)(bPoseChannel *),
+ const char default_ksName[])
{
- Scene *scene = CTX_data_scene(C);
- bool changed_multi = false;
-
- /* 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");
- return OPERATOR_CANCELLED;
- }
-
- /* only clear relevant transforms for selected bones */
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter)
- {
- Object *ob_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), ob_iter); // XXX: UGLY HACK (for autokey + clear transforms)
- ListBase dsources = {NULL, NULL};
- bool changed = false;
-
- FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob_iter, pchan)
- {
- /* run provided clearing function */
- clear_func(pchan);
- changed = true;
-
- /* do auto-keyframing as appropriate */
- if (autokeyframe_cfra_can_key(scene, &ob_iter->id)) {
- /* clear any unkeyed tags */
- if (pchan->bone) {
- pchan->bone->flag &= ~BONE_UNKEYED;
- }
- /* tag for autokeying later */
- ANIM_relative_keyingset_add_source(&dsources, &ob_iter->id, &RNA_PoseBone, pchan);
-
-#if 1 /* XXX: Ugly Hack - Run clearing function on evaluated copy of pchan */
- bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
- clear_func(pchan_eval);
+ Scene *scene = CTX_data_scene(C);
+ bool changed_multi = false;
+
+ /* 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");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* only clear relevant transforms for selected bones */
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) {
+ Object *ob_eval = DEG_get_evaluated_object(
+ CTX_data_depsgraph(C), ob_iter); // XXX: UGLY HACK (for autokey + clear transforms)
+ ListBase dsources = {NULL, NULL};
+ bool changed = false;
+
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob_iter, pchan) {
+ /* run provided clearing function */
+ clear_func(pchan);
+ changed = true;
+
+ /* do auto-keyframing as appropriate */
+ if (autokeyframe_cfra_can_key(scene, &ob_iter->id)) {
+ /* clear any unkeyed tags */
+ if (pchan->bone) {
+ pchan->bone->flag &= ~BONE_UNKEYED;
+ }
+ /* tag for autokeying later */
+ ANIM_relative_keyingset_add_source(&dsources, &ob_iter->id, &RNA_PoseBone, pchan);
+
+#if 1 /* XXX: Ugly Hack - Run clearing function on evaluated copy of pchan */
+ bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
+ clear_func(pchan_eval);
#endif
- }
- else {
- /* add unkeyed tags */
- if (pchan->bone) {
- pchan->bone->flag |= BONE_UNKEYED;
- }
- }
- }
- FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
-
- if (changed) {
- changed_multi = true;
-
- /* perform autokeying on the bones if needed */
- if (!BLI_listbase_is_empty(&dsources)) {
- /* get KeyingSet to use */
- KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
-
- /* insert keyframes */
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
-
- /* now recalculate paths */
- if ((ob_iter->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) {
- ED_pose_recalculate_paths(C, scene, ob_iter, false);
- }
-
- BLI_freelistN(&dsources);
- }
-
- DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob_iter);
- }
- }
- FOREACH_OBJECT_IN_MODE_END;
-
- return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ }
+ else {
+ /* add unkeyed tags */
+ if (pchan->bone) {
+ pchan->bone->flag |= BONE_UNKEYED;
+ }
+ }
+ }
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
+
+ if (changed) {
+ changed_multi = true;
+
+ /* perform autokeying on the bones if needed */
+ if (!BLI_listbase_is_empty(&dsources)) {
+ /* get KeyingSet to use */
+ KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
+
+ /* insert keyframes */
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+
+ /* now recalculate paths */
+ if ((ob_iter->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) {
+ ED_pose_recalculate_paths(C, scene, ob_iter, false);
+ }
+
+ BLI_freelistN(&dsources);
+ }
+
+ DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob_iter);
+ }
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
/* --------------- */
static int pose_clear_scale_exec(bContext *C, wmOperator *op)
{
- return pose_clear_transform_generic_exec(C, op, pchan_clear_scale, ANIM_KS_SCALING_ID);
+ return pose_clear_transform_generic_exec(C, op, pchan_clear_scale, ANIM_KS_SCALING_ID);
}
void POSE_OT_scale_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Pose Scale";
- ot->idname = "POSE_OT_scale_clear";
- ot->description = "Reset scaling of selected bones to their default values";
+ /* identifiers */
+ ot->name = "Clear Pose Scale";
+ ot->idname = "POSE_OT_scale_clear";
+ ot->description = "Reset scaling of selected bones to their default values";
- /* api callbacks */
- ot->exec = pose_clear_scale_exec;
- ot->poll = ED_operator_posemode;
+ /* api callbacks */
+ ot->exec = pose_clear_scale_exec;
+ ot->poll = ED_operator_posemode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
static int pose_clear_rot_exec(bContext *C, wmOperator *op)
{
- return pose_clear_transform_generic_exec(C, op, pchan_clear_rot, ANIM_KS_ROTATION_ID);
+ return pose_clear_transform_generic_exec(C, op, pchan_clear_rot, ANIM_KS_ROTATION_ID);
}
void POSE_OT_rot_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Pose Rotation";
- ot->idname = "POSE_OT_rot_clear";
- ot->description = "Reset rotations of selected bones to their default values";
+ /* identifiers */
+ ot->name = "Clear Pose Rotation";
+ ot->idname = "POSE_OT_rot_clear";
+ ot->description = "Reset rotations of selected bones to their default values";
- /* api callbacks */
- ot->exec = pose_clear_rot_exec;
- ot->poll = ED_operator_posemode;
+ /* api callbacks */
+ ot->exec = pose_clear_rot_exec;
+ ot->poll = ED_operator_posemode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
static int pose_clear_loc_exec(bContext *C, wmOperator *op)
{
- return pose_clear_transform_generic_exec(C, op, pchan_clear_loc, ANIM_KS_LOCATION_ID);
+ return pose_clear_transform_generic_exec(C, op, pchan_clear_loc, ANIM_KS_LOCATION_ID);
}
void POSE_OT_loc_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Pose Location";
- ot->idname = "POSE_OT_loc_clear";
- ot->description = "Reset locations of selected bones to their default values";
+ /* identifiers */
+ ot->name = "Clear Pose Location";
+ ot->idname = "POSE_OT_loc_clear";
+ ot->description = "Reset locations of selected bones to their default values";
- /* api callbacks */
- ot->exec = pose_clear_loc_exec;
- ot->poll = ED_operator_posemode;
+ /* api callbacks */
+ ot->exec = pose_clear_loc_exec;
+ ot->poll = ED_operator_posemode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
static int pose_clear_transforms_exec(bContext *C, wmOperator *op)
{
- return pose_clear_transform_generic_exec(C, op, pchan_clear_transforms, ANIM_KS_LOC_ROT_SCALE_ID);
+ return pose_clear_transform_generic_exec(
+ C, op, pchan_clear_transforms, ANIM_KS_LOC_ROT_SCALE_ID);
}
void POSE_OT_transforms_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Pose Transforms";
- ot->idname = "POSE_OT_transforms_clear";
- ot->description = "Reset location, rotation, and scaling of selected bones to their default values";
-
- /* api callbacks */
- ot->exec = pose_clear_transforms_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Clear Pose Transforms";
+ ot->idname = "POSE_OT_transforms_clear";
+ ot->description =
+ "Reset location, rotation, and scaling of selected bones to their default values";
+
+ /* api callbacks */
+ ot->exec = pose_clear_transforms_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************************************** */
@@ -932,80 +944,79 @@ void POSE_OT_transforms_clear(wmOperatorType *ot)
static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- Scene *scene = CTX_data_scene(C);
- float cframe = (float)CFRA;
- const bool only_select = RNA_boolean_get(op->ptr, "only_selected");
-
- FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob)
- {
- if ((ob->adt) && (ob->adt->action)) {
- /* XXX: this is just like this to avoid contaminating anything else;
- * just pose values should change, so this should be fine
- */
- bPose *dummyPose = NULL;
- Object workob = {{NULL}};
- bPoseChannel *pchan;
-
- /* execute animation step for current frame using a dummy copy of the pose */
- BKE_pose_copy_data(&dummyPose, ob->pose, 0);
-
- BLI_strncpy(workob.id.name, "OB<ClearTfmWorkOb>", sizeof(workob.id.name));
- workob.type = OB_ARMATURE;
- workob.data = ob->data;
- workob.adt = ob->adt;
- workob.pose = dummyPose;
-
- BKE_animsys_evaluate_animdata(NULL, scene, &workob.id, workob.adt, cframe, ADT_RECALC_ANIM);
-
- /* copy back values, but on selected bones only */
- for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
- pose_bone_do_paste(ob, pchan, only_select, 0);
- }
-
- /* free temp data - free manually as was copied without constraints */
- for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->prop) {
- IDP_FreeProperty(pchan->prop);
- MEM_freeN(pchan->prop);
- }
- }
-
- /* was copied without constraints */
- BLI_freelistN(&dummyPose->chanbase);
- MEM_freeN(dummyPose);
- }
- else {
- /* no animation, so just reset whole pose to rest pose
- * (cannot just restore for selected though)
- */
- BKE_pose_rest(ob->pose);
- }
-
- /* notifiers and updates */
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
- }
- FOREACH_OBJECT_IN_MODE_END;
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ float cframe = (float)CFRA;
+ const bool only_select = RNA_boolean_get(op->ptr, "only_selected");
+
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
+ if ((ob->adt) && (ob->adt->action)) {
+ /* XXX: this is just like this to avoid contaminating anything else;
+ * just pose values should change, so this should be fine
+ */
+ bPose *dummyPose = NULL;
+ Object workob = {{NULL}};
+ bPoseChannel *pchan;
+
+ /* execute animation step for current frame using a dummy copy of the pose */
+ BKE_pose_copy_data(&dummyPose, ob->pose, 0);
+
+ BLI_strncpy(workob.id.name, "OB<ClearTfmWorkOb>", sizeof(workob.id.name));
+ workob.type = OB_ARMATURE;
+ workob.data = ob->data;
+ workob.adt = ob->adt;
+ workob.pose = dummyPose;
+
+ BKE_animsys_evaluate_animdata(NULL, scene, &workob.id, workob.adt, cframe, ADT_RECALC_ANIM);
+
+ /* copy back values, but on selected bones only */
+ for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
+ pose_bone_do_paste(ob, pchan, only_select, 0);
+ }
+
+ /* free temp data - free manually as was copied without constraints */
+ for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->prop) {
+ IDP_FreeProperty(pchan->prop);
+ MEM_freeN(pchan->prop);
+ }
+ }
+
+ /* was copied without constraints */
+ BLI_freelistN(&dummyPose->chanbase);
+ MEM_freeN(dummyPose);
+ }
+ else {
+ /* no animation, so just reset whole pose to rest pose
+ * (cannot just restore for selected though)
+ */
+ BKE_pose_rest(ob->pose);
+ }
+
+ /* notifiers and updates */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+
+ return OPERATOR_FINISHED;
}
void POSE_OT_user_transforms_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear User Transforms";
- ot->idname = "POSE_OT_user_transforms_clear";
- ot->description = "Reset pose on selected bones to keyframed state";
+ /* identifiers */
+ ot->name = "Clear User Transforms";
+ ot->idname = "POSE_OT_user_transforms_clear";
+ ot->description = "Reset pose on selected bones to keyframed state";
- /* callbacks */
- ot->exec = pose_clear_user_transforms_exec;
- ot->poll = ED_operator_posemode;
+ /* callbacks */
+ ot->exec = pose_clear_user_transforms_exec;
+ ot->poll = ED_operator_posemode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "only_selected", true, "Only Selected", "Only visible/selected bones");
+ /* properties */
+ RNA_def_boolean(ot->srna, "only_selected", true, "Only Selected", "Only visible/selected bones");
}
diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c
index 25ddcee52cf..d8793bc2a1e 100644
--- a/source/blender/editors/armature/pose_utils.c
+++ b/source/blender/editors/armature/pose_utils.c
@@ -63,64 +63,67 @@
/* FCurves <-> PoseChannels Links */
/* helper for poseAnim_mapping_get() -> get the relevant F-Curves per PoseChannel */
-static void fcurves_to_pchan_links_get(ListBase *pfLinks, Object *ob, bAction *act, bPoseChannel *pchan)
+static void fcurves_to_pchan_links_get(ListBase *pfLinks,
+ Object *ob,
+ bAction *act,
+ bPoseChannel *pchan)
{
- ListBase curves = {NULL, NULL};
- int transFlags = action_get_item_transforms(act, ob, pchan, &curves);
-
- pchan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SIZE | POSE_BBONE_SHAPE);
-
- /* check if any transforms found... */
- if (transFlags) {
- /* make new linkage data */
- tPChanFCurveLink *pfl = MEM_callocN(sizeof(tPChanFCurveLink), "tPChanFCurveLink");
- PointerRNA ptr;
-
- pfl->ob = ob;
- pfl->fcurves = curves;
- pfl->pchan = pchan;
-
- /* get the RNA path to this pchan - this needs to be freed! */
- RNA_pointer_create((ID *)ob, &RNA_PoseBone, pchan, &ptr);
- pfl->pchan_path = RNA_path_from_ID_to_struct(&ptr);
-
- /* add linkage data to operator data */
- BLI_addtail(pfLinks, pfl);
-
- /* set pchan's transform flags */
- if (transFlags & ACT_TRANS_LOC)
- pchan->flag |= POSE_LOC;
- if (transFlags & ACT_TRANS_ROT)
- pchan->flag |= POSE_ROT;
- if (transFlags & ACT_TRANS_SCALE)
- pchan->flag |= POSE_SIZE;
- if (transFlags & ACT_TRANS_BBONE)
- pchan->flag |= POSE_BBONE_SHAPE;
-
- /* store current transforms */
- copy_v3_v3(pfl->oldloc, pchan->loc);
- copy_v3_v3(pfl->oldrot, pchan->eul);
- copy_v3_v3(pfl->oldscale, pchan->size);
- copy_qt_qt(pfl->oldquat, pchan->quat);
- copy_v3_v3(pfl->oldaxis, pchan->rotAxis);
- pfl->oldangle = pchan->rotAngle;
-
- /* store current bbone values */
- pfl->roll1 = pchan->roll1;
- pfl->roll2 = pchan->roll2;
- pfl->curveInX = pchan->curveInX;
- pfl->curveInY = pchan->curveInY;
- pfl->curveOutX = pchan->curveOutX;
- pfl->curveOutY = pchan->curveOutY;
- pfl->ease1 = pchan->ease1;
- pfl->ease2 = pchan->ease2;
- pfl->scaleIn = pchan->scaleIn;
- pfl->scaleOut = pchan->scaleOut;
-
- /* make copy of custom properties */
- if (pchan->prop && (transFlags & ACT_TRANS_PROP))
- pfl->oldprops = IDP_CopyProperty(pchan->prop);
- }
+ ListBase curves = {NULL, NULL};
+ int transFlags = action_get_item_transforms(act, ob, pchan, &curves);
+
+ pchan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SIZE | POSE_BBONE_SHAPE);
+
+ /* check if any transforms found... */
+ if (transFlags) {
+ /* make new linkage data */
+ tPChanFCurveLink *pfl = MEM_callocN(sizeof(tPChanFCurveLink), "tPChanFCurveLink");
+ PointerRNA ptr;
+
+ pfl->ob = ob;
+ pfl->fcurves = curves;
+ pfl->pchan = pchan;
+
+ /* get the RNA path to this pchan - this needs to be freed! */
+ RNA_pointer_create((ID *)ob, &RNA_PoseBone, pchan, &ptr);
+ pfl->pchan_path = RNA_path_from_ID_to_struct(&ptr);
+
+ /* add linkage data to operator data */
+ BLI_addtail(pfLinks, pfl);
+
+ /* set pchan's transform flags */
+ if (transFlags & ACT_TRANS_LOC)
+ pchan->flag |= POSE_LOC;
+ if (transFlags & ACT_TRANS_ROT)
+ pchan->flag |= POSE_ROT;
+ if (transFlags & ACT_TRANS_SCALE)
+ pchan->flag |= POSE_SIZE;
+ if (transFlags & ACT_TRANS_BBONE)
+ pchan->flag |= POSE_BBONE_SHAPE;
+
+ /* store current transforms */
+ copy_v3_v3(pfl->oldloc, pchan->loc);
+ copy_v3_v3(pfl->oldrot, pchan->eul);
+ copy_v3_v3(pfl->oldscale, pchan->size);
+ copy_qt_qt(pfl->oldquat, pchan->quat);
+ copy_v3_v3(pfl->oldaxis, pchan->rotAxis);
+ pfl->oldangle = pchan->rotAngle;
+
+ /* store current bbone values */
+ pfl->roll1 = pchan->roll1;
+ pfl->roll2 = pchan->roll2;
+ pfl->curveInX = pchan->curveInX;
+ pfl->curveInY = pchan->curveInY;
+ pfl->curveOutX = pchan->curveOutX;
+ pfl->curveOutY = pchan->curveOutY;
+ pfl->ease1 = pchan->ease1;
+ pfl->ease2 = pchan->ease2;
+ pfl->scaleIn = pchan->scaleIn;
+ pfl->scaleOut = pchan->scaleOut;
+
+ /* make copy of custom properties */
+ if (pchan->prop && (transFlags & ACT_TRANS_PROP))
+ pfl->oldprops = IDP_CopyProperty(pchan->prop);
+ }
}
/**
@@ -128,96 +131,85 @@ static void fcurves_to_pchan_links_get(ListBase *pfLinks, Object *ob, bAction *a
*/
Object *poseAnim_object_get(Object *ob_)
{
- Object *ob = BKE_object_pose_armature_get(ob_);
- if (!ELEM(NULL,
- ob,
- ob->data,
- ob->adt,
- ob->adt->action))
- {
- return ob;
- }
- return NULL;
+ Object *ob = BKE_object_pose_armature_get(ob_);
+ if (!ELEM(NULL, ob, ob->data, ob->adt, ob->adt->action)) {
+ return ob;
+ }
+ return NULL;
}
/* get sets of F-Curves providing transforms for the bones in the Pose */
void poseAnim_mapping_get(bContext *C, ListBase *pfLinks)
{
- /* for each Pose-Channel which gets affected, get the F-Curves for that channel
- * and set the relevant transform flags...
- */
- Object *prev_ob, *ob_pose_armature;
-
- prev_ob = NULL;
- ob_pose_armature = NULL;
- CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob)
- {
- if (ob != prev_ob) {
- prev_ob = ob;
- ob_pose_armature = poseAnim_object_get(ob);
- }
-
- if (ob_pose_armature == NULL) {
- continue;
- }
-
- fcurves_to_pchan_links_get(pfLinks,
- ob_pose_armature,
- ob_pose_armature->adt->action,
- pchan);
- }
- CTX_DATA_END;
-
- /* if no PoseChannels were found, try a second pass, doing visible ones instead
- * i.e. if nothing selected, do whole pose
- */
- if (BLI_listbase_is_empty(pfLinks)) {
- prev_ob = NULL;
- ob_pose_armature = NULL;
- CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob)
- {
- if (ob != prev_ob) {
- prev_ob = ob;
- ob_pose_armature = poseAnim_object_get(ob);
- }
-
- if (ob_pose_armature == NULL) {
- continue;
- }
-
- fcurves_to_pchan_links_get(pfLinks,
- ob_pose_armature,
- ob_pose_armature->adt->action,
- pchan);
- }
- CTX_DATA_END;
- }
+ /* for each Pose-Channel which gets affected, get the F-Curves for that channel
+ * and set the relevant transform flags...
+ */
+ Object *prev_ob, *ob_pose_armature;
+
+ prev_ob = NULL;
+ ob_pose_armature = NULL;
+ CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob)
+ {
+ if (ob != prev_ob) {
+ prev_ob = ob;
+ ob_pose_armature = poseAnim_object_get(ob);
+ }
+
+ if (ob_pose_armature == NULL) {
+ continue;
+ }
+
+ fcurves_to_pchan_links_get(pfLinks, ob_pose_armature, ob_pose_armature->adt->action, pchan);
+ }
+ CTX_DATA_END;
+
+ /* if no PoseChannels were found, try a second pass, doing visible ones instead
+ * i.e. if nothing selected, do whole pose
+ */
+ if (BLI_listbase_is_empty(pfLinks)) {
+ prev_ob = NULL;
+ ob_pose_armature = NULL;
+ CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob)
+ {
+ if (ob != prev_ob) {
+ prev_ob = ob;
+ ob_pose_armature = poseAnim_object_get(ob);
+ }
+
+ if (ob_pose_armature == NULL) {
+ continue;
+ }
+
+ fcurves_to_pchan_links_get(pfLinks, ob_pose_armature, ob_pose_armature->adt->action, pchan);
+ }
+ CTX_DATA_END;
+ }
}
/* free F-Curve <-> PoseChannel links */
void poseAnim_mapping_free(ListBase *pfLinks)
{
- tPChanFCurveLink *pfl, *pfln = NULL;
+ tPChanFCurveLink *pfl, *pfln = NULL;
- /* free the temp pchan links and their data */
- for (pfl = pfLinks->first; pfl; pfl = pfln) {
- pfln = pfl->next;
+ /* free the temp pchan links and their data */
+ for (pfl = pfLinks->first; pfl; pfl = pfln) {
+ pfln = pfl->next;
- /* free custom properties */
- if (pfl->oldprops) {
- IDP_FreeProperty(pfl->oldprops);
- MEM_freeN(pfl->oldprops);
- }
+ /* free custom properties */
+ if (pfl->oldprops) {
+ IDP_FreeProperty(pfl->oldprops);
+ MEM_freeN(pfl->oldprops);
+ }
- /* free list of F-Curve reference links */
- BLI_freelistN(&pfl->fcurves);
+ /* free list of F-Curve reference links */
+ BLI_freelistN(&pfl->fcurves);
- /* free pchan RNA Path */
- MEM_freeN(pfl->pchan_path);
+ /* free pchan RNA Path */
+ MEM_freeN(pfl->pchan_path);
- /* free link itself */
- BLI_freelinkN(pfLinks, pfl);
- }
+ /* free link itself */
+ BLI_freelinkN(pfLinks, pfl);
+ }
}
/* ------------------------- */
@@ -225,125 +217,127 @@ void poseAnim_mapping_free(ListBase *pfLinks)
/* helper for apply() / reset() - refresh the data */
void poseAnim_mapping_refresh(bContext *C, Scene *scene, Object *ob)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- bArmature *arm = (bArmature *)ob->data;
-
- /* old optimize trick... this enforces to bypass the depgraph
- * - note: code copied from transform_generics.c -> recalcData()
- */
- /* FIXME: shouldn't this use the builtin stuff? */
- if ((arm->flag & ARM_DELAYDEFORM) == 0)
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); /* sets recalc flags */
- else
- BKE_pose_where_is(depsgraph, scene, ob);
-
- /* otherwise animation doesn't get updated */
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ bArmature *arm = (bArmature *)ob->data;
+
+ /* old optimize trick... this enforces to bypass the depgraph
+ * - note: code copied from transform_generics.c -> recalcData()
+ */
+ /* FIXME: shouldn't this use the builtin stuff? */
+ if ((arm->flag & ARM_DELAYDEFORM) == 0)
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); /* sets recalc flags */
+ else
+ BKE_pose_where_is(depsgraph, scene, ob);
+
+ /* otherwise animation doesn't get updated */
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
}
/* reset changes made to current pose */
void poseAnim_mapping_reset(ListBase *pfLinks)
{
- tPChanFCurveLink *pfl;
-
- /* iterate over each pose-channel affected, restoring all channels to their original values */
- for (pfl = pfLinks->first; pfl; pfl = pfl->next) {
- bPoseChannel *pchan = pfl->pchan;
-
- /* just copy all the values over regardless of whether they changed or not */
- copy_v3_v3(pchan->loc, pfl->oldloc);
- copy_v3_v3(pchan->eul, pfl->oldrot);
- copy_v3_v3(pchan->size, pfl->oldscale);
- copy_qt_qt(pchan->quat, pfl->oldquat);
- copy_v3_v3(pchan->rotAxis, pfl->oldaxis);
- pchan->rotAngle = pfl->oldangle;
-
- /* store current bbone values */
- pchan->roll1 = pfl->roll1;
- pchan->roll2 = pfl->roll2;
- pchan->curveInX = pfl->curveInX;
- pchan->curveInY = pfl->curveInY;
- pchan->curveOutX = pfl->curveOutX;
- pchan->curveOutY = pfl->curveOutY;
- pchan->ease1 = pfl->ease1;
- pchan->ease2 = pfl->ease2;
- pchan->scaleIn = pfl->scaleIn;
- pchan->scaleOut = pfl->scaleOut;
-
- /* just overwrite values of properties from the stored copies (there should be some) */
- if (pfl->oldprops)
- IDP_SyncGroupValues(pfl->pchan->prop, pfl->oldprops);
- }
+ tPChanFCurveLink *pfl;
+
+ /* iterate over each pose-channel affected, restoring all channels to their original values */
+ for (pfl = pfLinks->first; pfl; pfl = pfl->next) {
+ bPoseChannel *pchan = pfl->pchan;
+
+ /* just copy all the values over regardless of whether they changed or not */
+ copy_v3_v3(pchan->loc, pfl->oldloc);
+ copy_v3_v3(pchan->eul, pfl->oldrot);
+ copy_v3_v3(pchan->size, pfl->oldscale);
+ copy_qt_qt(pchan->quat, pfl->oldquat);
+ copy_v3_v3(pchan->rotAxis, pfl->oldaxis);
+ pchan->rotAngle = pfl->oldangle;
+
+ /* store current bbone values */
+ pchan->roll1 = pfl->roll1;
+ pchan->roll2 = pfl->roll2;
+ pchan->curveInX = pfl->curveInX;
+ pchan->curveInY = pfl->curveInY;
+ pchan->curveOutX = pfl->curveOutX;
+ pchan->curveOutY = pfl->curveOutY;
+ pchan->ease1 = pfl->ease1;
+ pchan->ease2 = pfl->ease2;
+ pchan->scaleIn = pfl->scaleIn;
+ pchan->scaleOut = pfl->scaleOut;
+
+ /* just overwrite values of properties from the stored copies (there should be some) */
+ if (pfl->oldprops)
+ IDP_SyncGroupValues(pfl->pchan->prop, pfl->oldprops);
+ }
}
/* perform auto-key-framing after changes were made + confirmed */
void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, ListBase *pfLinks, float cframe)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- bool skip = true;
-
- FOREACH_OBJECT_IN_MODE_BEGIN(view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
- ob->id.tag &= ~LIB_TAG_DOIT;
- ob = poseAnim_object_get(ob);
-
- /* Ensure validity of the settings from the context. */
- if (ob == NULL) {
- continue;
- }
-
- if (autokeyframe_cfra_can_key(scene, &ob->id)) {
- ob->id.tag |= LIB_TAG_DOIT;
- skip = false;
- }
- } FOREACH_OBJECT_IN_MODE_END;
-
- if (skip) {
- return;
- }
-
- /* Insert keyframes as necessary if auto-key-framing. */
- KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
- ListBase dsources = {NULL, NULL};
- tPChanFCurveLink *pfl;
-
- /* iterate over each pose-channel affected, tagging bones to be keyed */
- /* XXX: here we already have the information about what transforms exist, though
- * it might be easier to just overwrite all using normal mechanisms
- */
- for (pfl = pfLinks->first; pfl; pfl = pfl->next) {
- bPoseChannel *pchan = pfl->pchan;
-
- if ((pfl->ob->id.tag & LIB_TAG_DOIT) == 0) {
- continue;
- }
-
- /* add datasource override for the PoseChannel, to be used later */
- ANIM_relative_keyingset_add_source(&dsources, &pfl->ob->id, &RNA_PoseBone, pchan);
-
- /* clear any unkeyed tags */
- if (pchan->bone) {
- pchan->bone->flag &= ~BONE_UNKEYED;
- }
- }
-
- /* insert keyframes for all relevant bones in one go */
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cframe);
- BLI_freelistN(&dsources);
-
- /* do the bone paths
- * - only do this if keyframes should have been added
- * - do not calculate unless there are paths already to update...
- */
- FOREACH_OBJECT_IN_MODE_BEGIN(view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
- if (ob->id.tag & LIB_TAG_DOIT) {
- if (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) {
- //ED_pose_clear_paths(C, ob); // XXX for now, don't need to clear
- ED_pose_recalculate_paths(C, scene, ob, false);
- }
- }
- } FOREACH_OBJECT_IN_MODE_END;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ bool skip = true;
+
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
+ ob->id.tag &= ~LIB_TAG_DOIT;
+ ob = poseAnim_object_get(ob);
+
+ /* Ensure validity of the settings from the context. */
+ if (ob == NULL) {
+ continue;
+ }
+
+ if (autokeyframe_cfra_can_key(scene, &ob->id)) {
+ ob->id.tag |= LIB_TAG_DOIT;
+ skip = false;
+ }
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+
+ if (skip) {
+ return;
+ }
+
+ /* Insert keyframes as necessary if auto-key-framing. */
+ KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
+ ListBase dsources = {NULL, NULL};
+ tPChanFCurveLink *pfl;
+
+ /* iterate over each pose-channel affected, tagging bones to be keyed */
+ /* XXX: here we already have the information about what transforms exist, though
+ * it might be easier to just overwrite all using normal mechanisms
+ */
+ for (pfl = pfLinks->first; pfl; pfl = pfl->next) {
+ bPoseChannel *pchan = pfl->pchan;
+
+ if ((pfl->ob->id.tag & LIB_TAG_DOIT) == 0) {
+ continue;
+ }
+
+ /* add datasource override for the PoseChannel, to be used later */
+ ANIM_relative_keyingset_add_source(&dsources, &pfl->ob->id, &RNA_PoseBone, pchan);
+
+ /* clear any unkeyed tags */
+ if (pchan->bone) {
+ pchan->bone->flag &= ~BONE_UNKEYED;
+ }
+ }
+
+ /* insert keyframes for all relevant bones in one go */
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cframe);
+ BLI_freelistN(&dsources);
+
+ /* do the bone paths
+ * - only do this if keyframes should have been added
+ * - do not calculate unless there are paths already to update...
+ */
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
+ if (ob->id.tag & LIB_TAG_DOIT) {
+ if (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) {
+ //ED_pose_clear_paths(C, ob); // XXX for now, don't need to clear
+ ED_pose_recalculate_paths(C, scene, ob, false);
+ }
+ }
+ }
+ FOREACH_OBJECT_IN_MODE_END;
}
/* ------------------------- */
@@ -353,20 +347,20 @@ void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, ListBase *pfLinks,
*/
LinkData *poseAnim_mapping_getNextFCurve(ListBase *fcuLinks, LinkData *prev, const char *path)
{
- LinkData *first = (prev) ? prev->next : (fcuLinks) ? fcuLinks->first : NULL;
- LinkData *ld;
+ LinkData *first = (prev) ? prev->next : (fcuLinks) ? fcuLinks->first : NULL;
+ LinkData *ld;
- /* check each link to see if the linked F-Curve has a matching path */
- for (ld = first; ld; ld = ld->next) {
- FCurve *fcu = (FCurve *)ld->data;
+ /* check each link to see if the linked F-Curve has a matching path */
+ for (ld = first; ld; ld = ld->next) {
+ FCurve *fcu = (FCurve *)ld->data;
- /* check if paths match */
- if (STREQ(path, fcu->rna_path))
- return ld;
- }
+ /* check if paths match */
+ if (STREQ(path, fcu->rna_path))
+ return ld;
+ }
- /* none found */
- return NULL;
+ /* none found */
+ return NULL;
}
/* *********************************************** */
diff --git a/source/blender/editors/curve/CMakeLists.txt b/source/blender/editors/curve/CMakeLists.txt
index 4ccf8d59e1f..3df6f3c97d4 100644
--- a/source/blender/editors/curve/CMakeLists.txt
+++ b/source/blender/editors/curve/CMakeLists.txt
@@ -16,46 +16,46 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../depsgraph
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/clog
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
- ../../../../extern/curve_fit_nd
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../depsgraph
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/clog
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
+ ../../../../extern/curve_fit_nd
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- curve_ops.c
- editcurve.c
- editcurve_add.c
- editcurve_paint.c
- editcurve_select.c
- editcurve_undo.c
- editfont.c
- editfont_undo.c
-
- curve_intern.h
+ curve_ops.c
+ editcurve.c
+ editcurve_add.c
+ editcurve_paint.c
+ editcurve_select.c
+ editcurve_undo.c
+ editfont.c
+ editfont_undo.c
+
+ curve_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
- extern_curve_fit_nd
+ bf_blenkernel
+ bf_blenlib
+ extern_curve_fit_nd
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h
index c741b5393dc..201ba2560dc 100644
--- a/source/blender/editors/curve/curve_intern.h
+++ b/source/blender/editors/curve/curve_intern.h
@@ -21,7 +21,6 @@
* \ingroup edcurve
*/
-
#ifndef __CURVE_INTERN_H__
#define __CURVE_INTERN_H__
@@ -34,24 +33,42 @@ struct ViewContext;
struct wmOperatorType;
/* editfont.c */
-enum { DEL_NEXT_CHAR, DEL_PREV_CHAR, DEL_NEXT_WORD, DEL_PREV_WORD, DEL_SELECTION, DEL_NEXT_SEL, DEL_PREV_SEL };
+enum {
+ DEL_NEXT_CHAR,
+ DEL_PREV_CHAR,
+ DEL_NEXT_WORD,
+ DEL_PREV_WORD,
+ DEL_SELECTION,
+ DEL_NEXT_SEL,
+ DEL_PREV_SEL
+};
enum { CASE_LOWER, CASE_UPPER };
-enum { LINE_BEGIN, LINE_END, PREV_CHAR, NEXT_CHAR, PREV_WORD, NEXT_WORD,
- PREV_LINE, NEXT_LINE, PREV_PAGE, NEXT_PAGE };
+enum {
+ LINE_BEGIN,
+ LINE_END,
+ PREV_CHAR,
+ NEXT_CHAR,
+ PREV_WORD,
+ NEXT_WORD,
+ PREV_LINE,
+ NEXT_LINE,
+ PREV_PAGE,
+ NEXT_PAGE
+};
typedef enum eVisible_Types {
- HIDDEN = true,
- VISIBLE = false,
+ HIDDEN = true,
+ VISIBLE = false,
} eVisible_Types;
typedef enum eEndPoint_Types {
- FIRST = true,
- LAST = false,
+ FIRST = true,
+ LAST = false,
} eEndPoint_Types;
typedef enum eCurveElem_Types {
- CURVE_VERTEX = 0,
- CURVE_SEGMENT,
+ CURVE_VERTEX = 0,
+ CURVE_SEGMENT,
} eCurveElem_Types;
/* internal select utils */
@@ -86,7 +103,6 @@ void FONT_OT_unlink(struct wmOperatorType *ot);
void FONT_OT_textbox_add(struct wmOperatorType *ot);
void FONT_OT_textbox_remove(struct wmOperatorType *ot);
-
/* editcurve.c */
void CURVE_OT_hide(struct wmOperatorType *ot);
void CURVE_OT_reveal(struct wmOperatorType *ot);
@@ -124,17 +140,24 @@ void CURVE_OT_match_texture_space(struct wmOperatorType *ot);
/* exported for editcurve_undo.c */
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);
+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);
+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);
-bool ed_editnurb_spin(float viewmat[4][4], struct View3D *v3d, struct Object *obedit, const float axis[3], const float cent[3]);
+bool ed_editnurb_spin(float viewmat[4][4],
+ struct View3D *v3d,
+ struct Object *obedit,
+ const float axis[3],
+ const float cent[3]);
/* editcurve_select.c */
void CURVE_OT_de_select_first(struct wmOperatorType *ot);
diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c
index de6fe686356..782b093fab4 100644
--- a/source/blender/editors/curve/curve_ops.c
+++ b/source/blender/editors/curve/curve_ops.c
@@ -21,11 +21,9 @@
* \ingroup edcurve
*/
-
#include <stdlib.h>
#include <math.h>
-
#include "DNA_curve_types.h"
#include "DNA_scene_types.h"
@@ -46,125 +44,129 @@
void ED_operatortypes_curve(void)
{
- WM_operatortype_append(FONT_OT_text_insert);
- WM_operatortype_append(FONT_OT_line_break);
-
- WM_operatortype_append(FONT_OT_case_toggle);
- WM_operatortype_append(FONT_OT_case_set);
- WM_operatortype_append(FONT_OT_style_toggle);
- WM_operatortype_append(FONT_OT_style_set);
-
- WM_operatortype_append(FONT_OT_select_all);
-
- WM_operatortype_append(FONT_OT_text_copy);
- WM_operatortype_append(FONT_OT_text_cut);
- WM_operatortype_append(FONT_OT_text_paste);
- WM_operatortype_append(FONT_OT_text_paste_from_file);
-
- WM_operatortype_append(FONT_OT_move);
- WM_operatortype_append(FONT_OT_move_select);
- WM_operatortype_append(FONT_OT_delete);
-
- WM_operatortype_append(FONT_OT_change_character);
- WM_operatortype_append(FONT_OT_change_spacing);
-
- WM_operatortype_append(FONT_OT_open);
- WM_operatortype_append(FONT_OT_unlink);
-
- WM_operatortype_append(FONT_OT_textbox_add);
- WM_operatortype_append(FONT_OT_textbox_remove);
-
- WM_operatortype_append(CURVE_OT_hide);
- WM_operatortype_append(CURVE_OT_reveal);
-
- WM_operatortype_append(CURVE_OT_separate);
- WM_operatortype_append(CURVE_OT_split);
- WM_operatortype_append(CURVE_OT_duplicate);
- WM_operatortype_append(CURVE_OT_delete);
- WM_operatortype_append(CURVE_OT_dissolve_verts);
-
- WM_operatortype_append(CURVE_OT_spline_type_set);
- WM_operatortype_append(CURVE_OT_radius_set);
- WM_operatortype_append(CURVE_OT_spline_weight_set);
- WM_operatortype_append(CURVE_OT_handle_type_set);
- WM_operatortype_append(CURVE_OT_normals_make_consistent);
- WM_operatortype_append(CURVE_OT_decimate);
- WM_operatortype_append(CURVE_OT_shade_smooth);
- WM_operatortype_append(CURVE_OT_shade_flat);
- WM_operatortype_append(CURVE_OT_tilt_clear);
-
- WM_operatortype_append(CURVE_OT_primitive_bezier_curve_add);
- WM_operatortype_append(CURVE_OT_primitive_bezier_circle_add);
- WM_operatortype_append(CURVE_OT_primitive_nurbs_curve_add);
- WM_operatortype_append(CURVE_OT_primitive_nurbs_circle_add);
- WM_operatortype_append(CURVE_OT_primitive_nurbs_path_add);
-
- WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_curve_add);
- WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_circle_add);
- WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_surface_add);
- WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_cylinder_add);
- WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_sphere_add);
- WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_torus_add);
-
- WM_operatortype_append(CURVE_OT_smooth);
- WM_operatortype_append(CURVE_OT_smooth_weight);
- WM_operatortype_append(CURVE_OT_smooth_radius);
- WM_operatortype_append(CURVE_OT_smooth_tilt);
-
- WM_operatortype_append(CURVE_OT_de_select_first);
- WM_operatortype_append(CURVE_OT_de_select_last);
- WM_operatortype_append(CURVE_OT_select_all);
- WM_operatortype_append(CURVE_OT_select_linked);
- WM_operatortype_append(CURVE_OT_select_linked_pick);
- WM_operatortype_append(CURVE_OT_select_row);
- WM_operatortype_append(CURVE_OT_select_next);
- WM_operatortype_append(CURVE_OT_select_previous);
- WM_operatortype_append(CURVE_OT_select_more);
- WM_operatortype_append(CURVE_OT_select_less);
- WM_operatortype_append(CURVE_OT_select_random);
- WM_operatortype_append(CURVE_OT_select_nth);
- WM_operatortype_append(CURVE_OT_select_similar);
- WM_operatortype_append(CURVE_OT_shortest_path_pick);
-
- WM_operatortype_append(CURVE_OT_switch_direction);
- WM_operatortype_append(CURVE_OT_subdivide);
- WM_operatortype_append(CURVE_OT_make_segment);
- WM_operatortype_append(CURVE_OT_spin);
- WM_operatortype_append(CURVE_OT_vertex_add);
- WM_operatortype_append(CURVE_OT_draw);
- WM_operatortype_append(CURVE_OT_extrude);
- WM_operatortype_append(CURVE_OT_cyclic_toggle);
-
- WM_operatortype_append(CURVE_OT_match_texture_space);
+ WM_operatortype_append(FONT_OT_text_insert);
+ WM_operatortype_append(FONT_OT_line_break);
+
+ WM_operatortype_append(FONT_OT_case_toggle);
+ WM_operatortype_append(FONT_OT_case_set);
+ WM_operatortype_append(FONT_OT_style_toggle);
+ WM_operatortype_append(FONT_OT_style_set);
+
+ WM_operatortype_append(FONT_OT_select_all);
+
+ WM_operatortype_append(FONT_OT_text_copy);
+ WM_operatortype_append(FONT_OT_text_cut);
+ WM_operatortype_append(FONT_OT_text_paste);
+ WM_operatortype_append(FONT_OT_text_paste_from_file);
+
+ WM_operatortype_append(FONT_OT_move);
+ WM_operatortype_append(FONT_OT_move_select);
+ WM_operatortype_append(FONT_OT_delete);
+
+ WM_operatortype_append(FONT_OT_change_character);
+ WM_operatortype_append(FONT_OT_change_spacing);
+
+ WM_operatortype_append(FONT_OT_open);
+ WM_operatortype_append(FONT_OT_unlink);
+
+ WM_operatortype_append(FONT_OT_textbox_add);
+ WM_operatortype_append(FONT_OT_textbox_remove);
+
+ WM_operatortype_append(CURVE_OT_hide);
+ WM_operatortype_append(CURVE_OT_reveal);
+
+ WM_operatortype_append(CURVE_OT_separate);
+ WM_operatortype_append(CURVE_OT_split);
+ WM_operatortype_append(CURVE_OT_duplicate);
+ WM_operatortype_append(CURVE_OT_delete);
+ WM_operatortype_append(CURVE_OT_dissolve_verts);
+
+ WM_operatortype_append(CURVE_OT_spline_type_set);
+ WM_operatortype_append(CURVE_OT_radius_set);
+ WM_operatortype_append(CURVE_OT_spline_weight_set);
+ WM_operatortype_append(CURVE_OT_handle_type_set);
+ WM_operatortype_append(CURVE_OT_normals_make_consistent);
+ WM_operatortype_append(CURVE_OT_decimate);
+ WM_operatortype_append(CURVE_OT_shade_smooth);
+ WM_operatortype_append(CURVE_OT_shade_flat);
+ WM_operatortype_append(CURVE_OT_tilt_clear);
+
+ WM_operatortype_append(CURVE_OT_primitive_bezier_curve_add);
+ WM_operatortype_append(CURVE_OT_primitive_bezier_circle_add);
+ WM_operatortype_append(CURVE_OT_primitive_nurbs_curve_add);
+ WM_operatortype_append(CURVE_OT_primitive_nurbs_circle_add);
+ WM_operatortype_append(CURVE_OT_primitive_nurbs_path_add);
+
+ WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_curve_add);
+ WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_circle_add);
+ WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_surface_add);
+ WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_cylinder_add);
+ WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_sphere_add);
+ WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_torus_add);
+
+ WM_operatortype_append(CURVE_OT_smooth);
+ WM_operatortype_append(CURVE_OT_smooth_weight);
+ WM_operatortype_append(CURVE_OT_smooth_radius);
+ WM_operatortype_append(CURVE_OT_smooth_tilt);
+
+ WM_operatortype_append(CURVE_OT_de_select_first);
+ WM_operatortype_append(CURVE_OT_de_select_last);
+ WM_operatortype_append(CURVE_OT_select_all);
+ WM_operatortype_append(CURVE_OT_select_linked);
+ WM_operatortype_append(CURVE_OT_select_linked_pick);
+ WM_operatortype_append(CURVE_OT_select_row);
+ WM_operatortype_append(CURVE_OT_select_next);
+ WM_operatortype_append(CURVE_OT_select_previous);
+ WM_operatortype_append(CURVE_OT_select_more);
+ WM_operatortype_append(CURVE_OT_select_less);
+ WM_operatortype_append(CURVE_OT_select_random);
+ WM_operatortype_append(CURVE_OT_select_nth);
+ WM_operatortype_append(CURVE_OT_select_similar);
+ WM_operatortype_append(CURVE_OT_shortest_path_pick);
+
+ WM_operatortype_append(CURVE_OT_switch_direction);
+ WM_operatortype_append(CURVE_OT_subdivide);
+ WM_operatortype_append(CURVE_OT_make_segment);
+ WM_operatortype_append(CURVE_OT_spin);
+ WM_operatortype_append(CURVE_OT_vertex_add);
+ WM_operatortype_append(CURVE_OT_draw);
+ WM_operatortype_append(CURVE_OT_extrude);
+ WM_operatortype_append(CURVE_OT_cyclic_toggle);
+
+ WM_operatortype_append(CURVE_OT_match_texture_space);
}
void ED_operatormacros_curve(void)
{
- wmOperatorType *ot;
- wmOperatorTypeMacro *otmacro;
-
- ot = WM_operatortype_append_macro("CURVE_OT_duplicate_move", "Add Duplicate", "Duplicate curve and move",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "CURVE_OT_duplicate");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", false);
-
- ot = WM_operatortype_append_macro("CURVE_OT_extrude_move", "Extrude Curve and Move",
- "Extrude curve and move result", OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "CURVE_OT_extrude");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", false);
+ wmOperatorType *ot;
+ wmOperatorTypeMacro *otmacro;
+
+ ot = WM_operatortype_append_macro("CURVE_OT_duplicate_move",
+ "Add Duplicate",
+ "Duplicate curve and move",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "CURVE_OT_duplicate");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
+
+ ot = WM_operatortype_append_macro("CURVE_OT_extrude_move",
+ "Extrude Curve and Move",
+ "Extrude curve and move result",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "CURVE_OT_extrude");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
}
void ED_keymap_curve(wmKeyConfig *keyconf)
{
- /* only set in editmode font, by space_view3d listener */
- wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Font", 0, 0);
- keymap->poll = ED_operator_editfont;
+ /* only set in editmode font, by space_view3d listener */
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Font", 0, 0);
+ keymap->poll = ED_operator_editfont;
- /* only set in editmode curve, by space_view3d listener */
- keymap = WM_keymap_ensure(keyconf, "Curve", 0, 0);
- keymap->poll = ED_operator_editsurfcurve;
+ /* only set in editmode curve, by space_view3d listener */
+ keymap = WM_keymap_ensure(keyconf, "Curve", 0, 0);
+ keymap->poll = ED_operator_editsurfcurve;
}
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 4aaf0dc2a2f..c37ce4cc89d 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -77,17 +77,18 @@
#include "RNA_enum_types.h"
void selectend_nurb(Object *obedit, enum eEndPoint_Types selfirst, bool doswap, bool selstatus);
-static void adduplicateflagNurb(Object *obedit, View3D *v3d, ListBase *newnurb, const short flag, const bool split);
+static void adduplicateflagNurb(
+ Object *obedit, View3D *v3d, ListBase *newnurb, const short flag, const bool split);
static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split);
static bool curve_delete_vertices(Object *obedit, View3D *v3d);
ListBase *object_editcurve_get(Object *ob)
{
- if (ob && ELEM(ob->type, OB_CURVE, OB_SURF)) {
- Curve *cu = ob->data;
- return &cu->editnurb->nurbs;
- }
- return NULL;
+ if (ob && ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ Curve *cu = ob->data;
+ return &cu->editnurb->nurbs;
+ }
+ return NULL;
}
/* ******************* PRINTS ********************* */
@@ -95,2725 +96,2741 @@ ListBase *object_editcurve_get(Object *ob)
#if 0
void printknots(Object *obedit)
{
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- int a, num;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (ED_curve_nurb_select_check(nu) && nu->type == CU_NURBS) {
- if (nu->knotsu) {
- num = KNOTSU(nu);
- for (a = 0; a < num; a++) printf("knotu %d: %f\n", a, nu->knotsu[a]);
- }
- if (nu->knotsv) {
- num = KNOTSV(nu);
- for (a = 0; a < num; a++) printf("knotv %d: %f\n", a, nu->knotsv[a]);
- }
- }
- }
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ int a, num;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (ED_curve_nurb_select_check(nu) && nu->type == CU_NURBS) {
+ if (nu->knotsu) {
+ num = KNOTSU(nu);
+ for (a = 0; a < num; a++) printf("knotu %d: %f\n", a, nu->knotsu[a]);
+ }
+ if (nu->knotsv) {
+ num = KNOTSV(nu);
+ for (a = 0; a < num; a++) printf("knotv %d: %f\n", a, nu->knotsv[a]);
+ }
+ }
+ }
}
#endif
/* ********************* Shape keys *************** */
-static CVKeyIndex *init_cvKeyIndex(void *cv, int key_index, int nu_index, int pt_index, int vertex_index)
+static CVKeyIndex *init_cvKeyIndex(
+ void *cv, int key_index, int nu_index, int pt_index, int vertex_index)
{
- CVKeyIndex *cvIndex = MEM_callocN(sizeof(CVKeyIndex), __func__);
+ CVKeyIndex *cvIndex = MEM_callocN(sizeof(CVKeyIndex), __func__);
- cvIndex->orig_cv = cv;
- cvIndex->key_index = key_index;
- cvIndex->nu_index = nu_index;
- cvIndex->pt_index = pt_index;
- cvIndex->vertex_index = vertex_index;
- cvIndex->switched = false;
+ cvIndex->orig_cv = cv;
+ cvIndex->key_index = key_index;
+ cvIndex->nu_index = nu_index;
+ cvIndex->pt_index = pt_index;
+ cvIndex->vertex_index = vertex_index;
+ cvIndex->switched = false;
- return cvIndex;
+ return cvIndex;
}
static void init_editNurb_keyIndex(EditNurb *editnurb, ListBase *origBase)
{
- Nurb *nu = editnurb->nurbs.first;
- Nurb *orignu = origBase->first;
- GHash *gh;
- BezTriple *bezt, *origbezt;
- BPoint *bp, *origbp;
- CVKeyIndex *keyIndex;
- int a, key_index = 0, nu_index = 0, pt_index = 0, vertex_index = 0;
-
- if (editnurb->keyindex) {
- return;
- }
-
- gh = BLI_ghash_ptr_new("editNurb keyIndex");
-
- while (orignu) {
- if (orignu->bezt) {
- a = orignu->pntsu;
- bezt = nu->bezt;
- origbezt = orignu->bezt;
- pt_index = 0;
- while (a--) {
- /* We cannot keep *any* reference to curve obdata,
- * it might be replaced and freed while editcurve remain in use
- * (in viewport render case e.g.). Note that we could use a pool to avoid
- * lots of malloc's here, but... not really a problem for now. */
- BezTriple *origbezt_cpy = MEM_mallocN(sizeof(*origbezt), __func__);
- *origbezt_cpy = *origbezt;
- keyIndex = init_cvKeyIndex(origbezt_cpy, key_index, nu_index, pt_index, vertex_index);
- BLI_ghash_insert(gh, bezt, keyIndex);
- key_index += KEYELEM_FLOAT_LEN_BEZTRIPLE;
- vertex_index += 3;
- bezt++;
- origbezt++;
- pt_index++;
- }
- }
- else {
- a = orignu->pntsu * orignu->pntsv;
- bp = nu->bp;
- origbp = orignu->bp;
- pt_index = 0;
- while (a--) {
- /* We cannot keep *any* reference to curve obdata,
- * it might be replaced and freed while editcurve remain in use
- * (in viewport render case e.g.). Note that we could use a pool to avoid
- * lots of malloc's here, but... not really a problem for now. */
- BPoint *origbp_cpy = MEM_mallocN(sizeof(*origbp_cpy), __func__);
- *origbp_cpy = *origbp;
- keyIndex = init_cvKeyIndex(origbp_cpy, key_index, nu_index, pt_index, vertex_index);
- BLI_ghash_insert(gh, bp, keyIndex);
- key_index += KEYELEM_FLOAT_LEN_BPOINT;
- bp++;
- origbp++;
- pt_index++;
- vertex_index++;
- }
- }
-
- nu = nu->next;
- orignu = orignu->next;
- nu_index++;
- }
-
- editnurb->keyindex = gh;
+ Nurb *nu = editnurb->nurbs.first;
+ Nurb *orignu = origBase->first;
+ GHash *gh;
+ BezTriple *bezt, *origbezt;
+ BPoint *bp, *origbp;
+ CVKeyIndex *keyIndex;
+ int a, key_index = 0, nu_index = 0, pt_index = 0, vertex_index = 0;
+
+ if (editnurb->keyindex) {
+ return;
+ }
+
+ gh = BLI_ghash_ptr_new("editNurb keyIndex");
+
+ while (orignu) {
+ if (orignu->bezt) {
+ a = orignu->pntsu;
+ bezt = nu->bezt;
+ origbezt = orignu->bezt;
+ pt_index = 0;
+ while (a--) {
+ /* We cannot keep *any* reference to curve obdata,
+ * it might be replaced and freed while editcurve remain in use
+ * (in viewport render case e.g.). Note that we could use a pool to avoid
+ * lots of malloc's here, but... not really a problem for now. */
+ BezTriple *origbezt_cpy = MEM_mallocN(sizeof(*origbezt), __func__);
+ *origbezt_cpy = *origbezt;
+ keyIndex = init_cvKeyIndex(origbezt_cpy, key_index, nu_index, pt_index, vertex_index);
+ BLI_ghash_insert(gh, bezt, keyIndex);
+ key_index += KEYELEM_FLOAT_LEN_BEZTRIPLE;
+ vertex_index += 3;
+ bezt++;
+ origbezt++;
+ pt_index++;
+ }
+ }
+ else {
+ a = orignu->pntsu * orignu->pntsv;
+ bp = nu->bp;
+ origbp = orignu->bp;
+ pt_index = 0;
+ while (a--) {
+ /* We cannot keep *any* reference to curve obdata,
+ * it might be replaced and freed while editcurve remain in use
+ * (in viewport render case e.g.). Note that we could use a pool to avoid
+ * lots of malloc's here, but... not really a problem for now. */
+ BPoint *origbp_cpy = MEM_mallocN(sizeof(*origbp_cpy), __func__);
+ *origbp_cpy = *origbp;
+ keyIndex = init_cvKeyIndex(origbp_cpy, key_index, nu_index, pt_index, vertex_index);
+ BLI_ghash_insert(gh, bp, keyIndex);
+ key_index += KEYELEM_FLOAT_LEN_BPOINT;
+ bp++;
+ origbp++;
+ pt_index++;
+ vertex_index++;
+ }
+ }
+
+ nu = nu->next;
+ orignu = orignu->next;
+ nu_index++;
+ }
+
+ editnurb->keyindex = gh;
}
static CVKeyIndex *getCVKeyIndex(EditNurb *editnurb, const void *cv)
{
- return BLI_ghash_lookup(editnurb->keyindex, cv);
+ return BLI_ghash_lookup(editnurb->keyindex, cv);
}
static CVKeyIndex *popCVKeyIndex(EditNurb *editnurb, const void *cv)
{
- return BLI_ghash_popkey(editnurb->keyindex, cv, NULL);
+ return BLI_ghash_popkey(editnurb->keyindex, cv, NULL);
}
static BezTriple *getKeyIndexOrig_bezt(EditNurb *editnurb, const BezTriple *bezt)
{
- CVKeyIndex *index = getCVKeyIndex(editnurb, bezt);
+ CVKeyIndex *index = getCVKeyIndex(editnurb, bezt);
- if (!index) {
- return NULL;
- }
+ if (!index) {
+ return NULL;
+ }
- return (BezTriple *)index->orig_cv;
+ return (BezTriple *)index->orig_cv;
}
static BPoint *getKeyIndexOrig_bp(EditNurb *editnurb, BPoint *bp)
{
- CVKeyIndex *index = getCVKeyIndex(editnurb, bp);
+ CVKeyIndex *index = getCVKeyIndex(editnurb, bp);
- if (!index) {
- return NULL;
- }
+ if (!index) {
+ return NULL;
+ }
- return (BPoint *)index->orig_cv;
+ return (BPoint *)index->orig_cv;
}
static int getKeyIndexOrig_keyIndex(EditNurb *editnurb, void *cv)
{
- CVKeyIndex *index = getCVKeyIndex(editnurb, cv);
+ CVKeyIndex *index = getCVKeyIndex(editnurb, cv);
- if (!index) {
- return -1;
- }
+ if (!index) {
+ return -1;
+ }
- return index->key_index;
+ return index->key_index;
}
static void keyIndex_delBezt(EditNurb *editnurb, BezTriple *bezt)
{
- if (!editnurb->keyindex) {
- return;
- }
+ if (!editnurb->keyindex) {
+ return;
+ }
- BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bezt);
+ BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bezt);
}
static void keyIndex_delBP(EditNurb *editnurb, BPoint *bp)
{
- if (!editnurb->keyindex) {
- return;
- }
+ if (!editnurb->keyindex) {
+ return;
+ }
- BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bp);
+ BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bp);
}
static void keyIndex_delNurb(EditNurb *editnurb, Nurb *nu)
{
- int a;
+ int a;
- if (!editnurb->keyindex) {
- return;
- }
+ if (!editnurb->keyindex) {
+ return;
+ }
- if (nu->bezt) {
- const BezTriple *bezt = nu->bezt;
- a = nu->pntsu;
+ if (nu->bezt) {
+ const BezTriple *bezt = nu->bezt;
+ a = nu->pntsu;
- while (a--) {
- BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bezt);
- bezt++;
- }
- }
- else {
- const BPoint *bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bezt);
+ bezt++;
+ }
+ }
+ else {
+ const BPoint *bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
- while (a--) {
- BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bp);
- bp++;
- }
- }
+ while (a--) {
+ BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bp);
+ bp++;
+ }
+ }
}
static void keyIndex_delNurbList(EditNurb *editnurb, ListBase *nubase)
{
- Nurb *nu = nubase->first;
+ Nurb *nu = nubase->first;
- while (nu) {
- keyIndex_delNurb(editnurb, nu);
+ while (nu) {
+ keyIndex_delNurb(editnurb, nu);
- nu = nu->next;
- }
+ nu = nu->next;
+ }
}
-static void keyIndex_updateCV(EditNurb *editnurb, char *cv,
- char *newcv, int count, int size)
+static void keyIndex_updateCV(EditNurb *editnurb, char *cv, char *newcv, int count, int size)
{
- int i;
- CVKeyIndex *index;
+ int i;
+ CVKeyIndex *index;
- if (editnurb->keyindex == NULL) {
- /* No shape keys - updating not needed */
- return;
- }
+ if (editnurb->keyindex == NULL) {
+ /* No shape keys - updating not needed */
+ return;
+ }
- for (i = 0; i < count; i++) {
- index = popCVKeyIndex(editnurb, cv);
+ for (i = 0; i < count; i++) {
+ index = popCVKeyIndex(editnurb, cv);
- if (index) {
- BLI_ghash_insert(editnurb->keyindex, newcv, index);
- }
+ if (index) {
+ BLI_ghash_insert(editnurb->keyindex, newcv, index);
+ }
- newcv += size;
- cv += size;
- }
+ newcv += size;
+ cv += size;
+ }
}
-static void keyIndex_updateBezt(EditNurb *editnurb, BezTriple *bezt,
- BezTriple *newbezt, int count)
+static void keyIndex_updateBezt(EditNurb *editnurb, BezTriple *bezt, BezTriple *newbezt, int count)
{
- keyIndex_updateCV(editnurb, (char *)bezt, (char *)newbezt, count, sizeof(BezTriple));
+ keyIndex_updateCV(editnurb, (char *)bezt, (char *)newbezt, count, sizeof(BezTriple));
}
-static void keyIndex_updateBP(EditNurb *editnurb, BPoint *bp,
- BPoint *newbp, int count)
+static void keyIndex_updateBP(EditNurb *editnurb, BPoint *bp, BPoint *newbp, int count)
{
- keyIndex_updateCV(editnurb, (char *)bp, (char *)newbp, count, sizeof(BPoint));
+ keyIndex_updateCV(editnurb, (char *)bp, (char *)newbp, count, sizeof(BPoint));
}
void ED_curve_keyindex_update_nurb(EditNurb *editnurb, Nurb *nu, Nurb *newnu)
{
- if (nu->bezt) {
- keyIndex_updateBezt(editnurb, nu->bezt, newnu->bezt, newnu->pntsu);
- }
- else {
- keyIndex_updateBP(editnurb, nu->bp, newnu->bp, newnu->pntsu * newnu->pntsv);
- }
+ if (nu->bezt) {
+ keyIndex_updateBezt(editnurb, nu->bezt, newnu->bezt, newnu->pntsu);
+ }
+ else {
+ keyIndex_updateBP(editnurb, nu->bp, newnu->bp, newnu->pntsu * newnu->pntsv);
+ }
}
static void keyIndex_swap(EditNurb *editnurb, void *a, void *b)
{
- CVKeyIndex *index1 = popCVKeyIndex(editnurb, a);
- CVKeyIndex *index2 = popCVKeyIndex(editnurb, b);
+ CVKeyIndex *index1 = popCVKeyIndex(editnurb, a);
+ CVKeyIndex *index2 = popCVKeyIndex(editnurb, b);
- if (index2) {
- BLI_ghash_insert(editnurb->keyindex, a, index2);
- }
- if (index1) {
- BLI_ghash_insert(editnurb->keyindex, b, index1);
- }
+ if (index2) {
+ BLI_ghash_insert(editnurb->keyindex, a, index2);
+ }
+ if (index1) {
+ BLI_ghash_insert(editnurb->keyindex, b, index1);
+ }
}
static void keyIndex_switchDirection(EditNurb *editnurb, Nurb *nu)
{
- int a;
- CVKeyIndex *index1, *index2;
+ int a;
+ CVKeyIndex *index1, *index2;
- if (nu->bezt) {
- BezTriple *bezt1, *bezt2;
+ if (nu->bezt) {
+ BezTriple *bezt1, *bezt2;
- a = nu->pntsu;
+ a = nu->pntsu;
- bezt1 = nu->bezt;
- bezt2 = bezt1 + (a - 1);
+ bezt1 = nu->bezt;
+ bezt2 = bezt1 + (a - 1);
- if (a & 1) {
- a++;
- }
+ if (a & 1) {
+ a++;
+ }
- a /= 2;
+ a /= 2;
- while (a--) {
- index1 = getCVKeyIndex(editnurb, bezt1);
- index2 = getCVKeyIndex(editnurb, bezt2);
+ while (a--) {
+ index1 = getCVKeyIndex(editnurb, bezt1);
+ index2 = getCVKeyIndex(editnurb, bezt2);
- if (index1) {
- index1->switched = !index1->switched;
- }
+ if (index1) {
+ index1->switched = !index1->switched;
+ }
- if (bezt1 != bezt2) {
- keyIndex_swap(editnurb, bezt1, bezt2);
+ if (bezt1 != bezt2) {
+ keyIndex_swap(editnurb, bezt1, bezt2);
- if (index2) {
- index2->switched = !index2->switched;
- }
- }
+ if (index2) {
+ index2->switched = !index2->switched;
+ }
+ }
- bezt1++;
- bezt2--;
- }
- }
- else {
- BPoint *bp1, *bp2;
+ bezt1++;
+ bezt2--;
+ }
+ }
+ else {
+ BPoint *bp1, *bp2;
- if (nu->pntsv == 1) {
- a = nu->pntsu;
- bp1 = nu->bp;
- bp2 = bp1 + (a - 1);
- a /= 2;
- while (bp1 != bp2 && a > 0) {
- index1 = getCVKeyIndex(editnurb, bp1);
- index2 = getCVKeyIndex(editnurb, bp2);
+ if (nu->pntsv == 1) {
+ a = nu->pntsu;
+ bp1 = nu->bp;
+ bp2 = bp1 + (a - 1);
+ a /= 2;
+ while (bp1 != bp2 && a > 0) {
+ index1 = getCVKeyIndex(editnurb, bp1);
+ index2 = getCVKeyIndex(editnurb, bp2);
- if (index1) {
- index1->switched = !index1->switched;
- }
+ if (index1) {
+ index1->switched = !index1->switched;
+ }
- if (bp1 != bp2) {
- if (index2) {
- index2->switched = !index2->switched;
- }
+ if (bp1 != bp2) {
+ if (index2) {
+ index2->switched = !index2->switched;
+ }
- keyIndex_swap(editnurb, bp1, bp2);
- }
+ keyIndex_swap(editnurb, bp1, bp2);
+ }
- a--;
- bp1++;
- bp2--;
- }
- }
- else {
- int b;
+ a--;
+ bp1++;
+ bp2--;
+ }
+ }
+ else {
+ int b;
- for (b = 0; b < nu->pntsv; b++) {
+ for (b = 0; b < nu->pntsv; b++) {
- bp1 = &nu->bp[b * nu->pntsu];
- a = nu->pntsu;
- bp2 = bp1 + (a - 1);
- a /= 2;
+ bp1 = &nu->bp[b * nu->pntsu];
+ a = nu->pntsu;
+ bp2 = bp1 + (a - 1);
+ a /= 2;
- while (bp1 != bp2 && a > 0) {
- index1 = getCVKeyIndex(editnurb, bp1);
- index2 = getCVKeyIndex(editnurb, bp2);
+ while (bp1 != bp2 && a > 0) {
+ index1 = getCVKeyIndex(editnurb, bp1);
+ index2 = getCVKeyIndex(editnurb, bp2);
- if (index1) {
- index1->switched = !index1->switched;
- }
+ if (index1) {
+ index1->switched = !index1->switched;
+ }
- if (bp1 != bp2) {
- if (index2) {
- index2->switched = !index2->switched;
- }
+ if (bp1 != bp2) {
+ if (index2) {
+ index2->switched = !index2->switched;
+ }
- keyIndex_swap(editnurb, bp1, bp2);
- }
+ keyIndex_swap(editnurb, bp1, bp2);
+ }
- a--;
- bp1++;
- bp2--;
- }
- }
-
- }
- }
+ a--;
+ bp1++;
+ bp2--;
+ }
+ }
+ }
+ }
}
static void switch_keys_direction(Curve *cu, Nurb *actnu)
{
- KeyBlock *currkey;
- EditNurb *editnurb = cu->editnurb;
- ListBase *nubase = &editnurb->nurbs;
- Nurb *nu;
- float *fp;
- int a;
-
- currkey = cu->key->block.first;
- while (currkey) {
- fp = currkey->data;
-
- nu = nubase->first;
- while (nu) {
- if (nu->bezt) {
- BezTriple *bezt = nu->bezt;
- a = nu->pntsu;
- if (nu == actnu) {
- while (a--) {
- if (getKeyIndexOrig_bezt(editnurb, bezt)) {
- swap_v3_v3(fp, fp + 6);
- *(fp + 9) = -*(fp + 9);
- fp += KEYELEM_FLOAT_LEN_BEZTRIPLE;
- }
- bezt++;
- }
- }
- else {
- fp += a * KEYELEM_FLOAT_LEN_BEZTRIPLE;
- }
- }
- else {
- BPoint *bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- if (nu == actnu) {
- while (a--) {
- if (getKeyIndexOrig_bp(editnurb, bp)) {
- *(fp + 3) = -*(fp + 3);
- fp += KEYELEM_FLOAT_LEN_BPOINT;
- }
- bp++;
- }
- }
- else {
- fp += a * KEYELEM_FLOAT_LEN_BPOINT;
- }
- }
-
- nu = nu->next;
- }
-
- currkey = currkey->next;
- }
+ KeyBlock *currkey;
+ EditNurb *editnurb = cu->editnurb;
+ ListBase *nubase = &editnurb->nurbs;
+ Nurb *nu;
+ float *fp;
+ int a;
+
+ currkey = cu->key->block.first;
+ while (currkey) {
+ fp = currkey->data;
+
+ nu = nubase->first;
+ while (nu) {
+ if (nu->bezt) {
+ BezTriple *bezt = nu->bezt;
+ a = nu->pntsu;
+ if (nu == actnu) {
+ while (a--) {
+ if (getKeyIndexOrig_bezt(editnurb, bezt)) {
+ swap_v3_v3(fp, fp + 6);
+ *(fp + 9) = -*(fp + 9);
+ fp += KEYELEM_FLOAT_LEN_BEZTRIPLE;
+ }
+ bezt++;
+ }
+ }
+ else {
+ fp += a * KEYELEM_FLOAT_LEN_BEZTRIPLE;
+ }
+ }
+ else {
+ BPoint *bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ if (nu == actnu) {
+ while (a--) {
+ if (getKeyIndexOrig_bp(editnurb, bp)) {
+ *(fp + 3) = -*(fp + 3);
+ fp += KEYELEM_FLOAT_LEN_BPOINT;
+ }
+ bp++;
+ }
+ }
+ else {
+ fp += a * KEYELEM_FLOAT_LEN_BPOINT;
+ }
+ }
+
+ nu = nu->next;
+ }
+
+ currkey = currkey->next;
+ }
}
static void keyData_switchDirectionNurb(Curve *cu, Nurb *nu)
{
- EditNurb *editnurb = cu->editnurb;
+ EditNurb *editnurb = cu->editnurb;
- if (!editnurb->keyindex) {
- /* no shape keys - nothing to do */
- return;
- }
+ if (!editnurb->keyindex) {
+ /* no shape keys - nothing to do */
+ return;
+ }
- keyIndex_switchDirection(editnurb, nu);
- if (cu->key) {
- switch_keys_direction(cu, nu);
- }
+ keyIndex_switchDirection(editnurb, nu);
+ if (cu->key) {
+ switch_keys_direction(cu, nu);
+ }
}
GHash *ED_curve_keyindex_hash_duplicate(GHash *keyindex)
{
- GHash *gh;
- GHashIterator gh_iter;
+ GHash *gh;
+ GHashIterator gh_iter;
- gh = BLI_ghash_ptr_new_ex("dupli_keyIndex gh", BLI_ghash_len(keyindex));
+ gh = BLI_ghash_ptr_new_ex("dupli_keyIndex gh", BLI_ghash_len(keyindex));
- GHASH_ITER (gh_iter, keyindex) {
- void *cv = BLI_ghashIterator_getKey(&gh_iter);
- CVKeyIndex *index = BLI_ghashIterator_getValue(&gh_iter);
- CVKeyIndex *newIndex = MEM_mallocN(sizeof(CVKeyIndex), "dupli_keyIndexHash index");
+ GHASH_ITER (gh_iter, keyindex) {
+ void *cv = BLI_ghashIterator_getKey(&gh_iter);
+ CVKeyIndex *index = BLI_ghashIterator_getValue(&gh_iter);
+ CVKeyIndex *newIndex = MEM_mallocN(sizeof(CVKeyIndex), "dupli_keyIndexHash index");
- memcpy(newIndex, index, sizeof(CVKeyIndex));
- newIndex->orig_cv = MEM_dupallocN(index->orig_cv);
+ memcpy(newIndex, index, sizeof(CVKeyIndex));
+ newIndex->orig_cv = MEM_dupallocN(index->orig_cv);
- BLI_ghash_insert(gh, cv, newIndex);
- }
+ BLI_ghash_insert(gh, cv, newIndex);
+ }
- return gh;
+ return gh;
}
static void key_to_bezt(float *key, BezTriple *basebezt, BezTriple *bezt)
{
- memcpy(bezt, basebezt, sizeof(BezTriple));
- memcpy(bezt->vec, key, sizeof(float) * 9);
- bezt->tilt = key[9];
- bezt->radius = key[10];
+ memcpy(bezt, basebezt, sizeof(BezTriple));
+ memcpy(bezt->vec, key, sizeof(float) * 9);
+ bezt->tilt = key[9];
+ bezt->radius = key[10];
}
static void bezt_to_key(BezTriple *bezt, float *key)
{
- memcpy(key, bezt->vec, sizeof(float) * 9);
- key[9] = bezt->tilt;
- key[10] = bezt->radius;
+ memcpy(key, bezt->vec, sizeof(float) * 9);
+ key[9] = bezt->tilt;
+ key[10] = bezt->radius;
}
static void calc_keyHandles(ListBase *nurb, float *key)
{
- Nurb *nu;
- int a;
- float *fp = key;
- BezTriple *bezt;
-
- nu = nurb->first;
- while (nu) {
- if (nu->bezt) {
- BezTriple *prevp, *nextp;
- BezTriple cur, prev, next;
- float *startfp, *prevfp, *nextfp;
-
- bezt = nu->bezt;
- a = nu->pntsu;
- startfp = fp;
-
- if (nu->flagu & CU_NURB_CYCLIC) {
- prevp = bezt + (a - 1);
- prevfp = fp + (KEYELEM_FLOAT_LEN_BEZTRIPLE * (a - 1));
- }
- else {
- prevp = NULL;
- prevfp = NULL;
- }
-
- nextp = bezt + 1;
- nextfp = fp + KEYELEM_FLOAT_LEN_BEZTRIPLE;
-
- while (a--) {
- key_to_bezt(fp, bezt, &cur);
-
- if (nextp) {
- key_to_bezt(nextfp, nextp, &next);
- }
- if (prevp) {
- key_to_bezt(prevfp, prevp, &prev);
- }
-
- BKE_nurb_handle_calc(&cur, prevp ? &prev : NULL, nextp ? &next : NULL, 0, 0);
- bezt_to_key(&cur, fp);
-
- prevp = bezt;
- prevfp = fp;
- if (a == 1) {
- if (nu->flagu & CU_NURB_CYCLIC) {
- nextp = nu->bezt;
- nextfp = startfp;
- }
- else {
- nextp = NULL;
- nextfp = NULL;
- }
- }
- else {
- nextp++;
- nextfp += KEYELEM_FLOAT_LEN_BEZTRIPLE;
- }
-
- bezt++;
- fp += KEYELEM_FLOAT_LEN_BEZTRIPLE;
- }
- }
- else {
- a = nu->pntsu * nu->pntsv;
- fp += a * KEYELEM_FLOAT_LEN_BPOINT;
- }
-
- nu = nu->next;
- }
+ Nurb *nu;
+ int a;
+ float *fp = key;
+ BezTriple *bezt;
+
+ nu = nurb->first;
+ while (nu) {
+ if (nu->bezt) {
+ BezTriple *prevp, *nextp;
+ BezTriple cur, prev, next;
+ float *startfp, *prevfp, *nextfp;
+
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ startfp = fp;
+
+ if (nu->flagu & CU_NURB_CYCLIC) {
+ prevp = bezt + (a - 1);
+ prevfp = fp + (KEYELEM_FLOAT_LEN_BEZTRIPLE * (a - 1));
+ }
+ else {
+ prevp = NULL;
+ prevfp = NULL;
+ }
+
+ nextp = bezt + 1;
+ nextfp = fp + KEYELEM_FLOAT_LEN_BEZTRIPLE;
+
+ while (a--) {
+ key_to_bezt(fp, bezt, &cur);
+
+ if (nextp) {
+ key_to_bezt(nextfp, nextp, &next);
+ }
+ if (prevp) {
+ key_to_bezt(prevfp, prevp, &prev);
+ }
+
+ BKE_nurb_handle_calc(&cur, prevp ? &prev : NULL, nextp ? &next : NULL, 0, 0);
+ bezt_to_key(&cur, fp);
+
+ prevp = bezt;
+ prevfp = fp;
+ if (a == 1) {
+ if (nu->flagu & CU_NURB_CYCLIC) {
+ nextp = nu->bezt;
+ nextfp = startfp;
+ }
+ else {
+ nextp = NULL;
+ nextfp = NULL;
+ }
+ }
+ else {
+ nextp++;
+ nextfp += KEYELEM_FLOAT_LEN_BEZTRIPLE;
+ }
+
+ bezt++;
+ fp += KEYELEM_FLOAT_LEN_BEZTRIPLE;
+ }
+ }
+ else {
+ a = nu->pntsu * nu->pntsv;
+ fp += a * KEYELEM_FLOAT_LEN_BPOINT;
+ }
+
+ nu = nu->next;
+ }
}
static void calc_shapeKeys(Object *obedit, ListBase *newnurbs)
{
- Curve *cu = (Curve *)obedit->data;
-
- /* are there keys? */
- if (cu->key) {
- int a, i;
- EditNurb *editnurb = cu->editnurb;
- KeyBlock *currkey;
- KeyBlock *actkey = BLI_findlink(&cu->key->block, editnurb->shapenr - 1);
- BezTriple *bezt, *oldbezt;
- BPoint *bp, *oldbp;
- Nurb *nu, *newnu;
- int totvert = BKE_keyblock_curve_element_count(&editnurb->nurbs);
-
- float (*ofs)[3] = NULL;
- float *oldkey, *newkey, *ofp;
-
- /* editing the base key should update others */
- if (cu->key->type == KEY_RELATIVE) {
- if (BKE_keyblock_is_basis(cu->key, editnurb->shapenr - 1)) { /* active key is a base */
- int totvec = 0;
-
- /* Calculate needed memory to store offset */
- nu = editnurb->nurbs.first;
- while (nu) {
- if (nu->bezt) {
- /* Three vects to store handles and one for tilt. */
- totvec += nu->pntsu * 4;
- }
- else {
- totvec += 2 * nu->pntsu * nu->pntsv;
- }
-
- nu = nu->next;
- }
-
- ofs = MEM_callocN(sizeof(float) * 3 * totvec, "currkey->data");
- nu = editnurb->nurbs.first;
- i = 0;
- while (nu) {
- if (nu->bezt) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- oldbezt = getKeyIndexOrig_bezt(editnurb, bezt);
-
- if (oldbezt) {
- int j;
- for (j = 0; j < 3; ++j) {
- sub_v3_v3v3(ofs[i], bezt->vec[j], oldbezt->vec[j]);
- i++;
- }
- ofs[i][0] = bezt->tilt - oldbezt->tilt;
- ofs[i][1] = bezt->radius - oldbezt->radius;
- i++;
- }
- else {
- i += 4;
- }
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- oldbp = getKeyIndexOrig_bp(editnurb, bp);
- if (oldbp) {
- sub_v3_v3v3(ofs[i], bp->vec, oldbp->vec);
- ofs[i + 1][0] = bp->tilt - oldbp->tilt;
- ofs[i + 1][1] = bp->radius - oldbp->radius;
- }
- i += 2;
- bp++;
- }
- }
-
- nu = nu->next;
- }
- }
- }
-
- currkey = cu->key->block.first;
- while (currkey) {
- const bool apply_offset = (ofs && (currkey != actkey) && (editnurb->shapenr - 1 == currkey->relative));
-
- float *fp = newkey = MEM_callocN(cu->key->elemsize * totvert, "currkey->data");
- ofp = oldkey = currkey->data;
-
- nu = editnurb->nurbs.first;
- /* We need to restore to original curve into newnurb, *not* editcurve's nurbs.
- * Otherwise, in case we update obdata *without* leaving editmode (e.g. viewport render), we would
- * invalidate editcurve. */
- newnu = newnurbs->first;
- i = 0;
- while (nu) {
- if (currkey == actkey) {
- const bool restore = actkey != cu->key->refkey;
-
- if (nu->bezt) {
- bezt = nu->bezt;
- a = nu->pntsu;
- BezTriple *newbezt = newnu->bezt;
- while (a--) {
- int j;
- oldbezt = getKeyIndexOrig_bezt(editnurb, bezt);
-
- for (j = 0; j < 3; j++, i++) {
- copy_v3_v3(&fp[j * 3], bezt->vec[j]);
-
- if (restore && oldbezt) {
- copy_v3_v3(newbezt->vec[j], oldbezt->vec[j]);
- }
- }
- fp[9] = bezt->tilt;
- fp[10] = bezt->radius;
-
- if (restore && oldbezt) {
- newbezt->tilt = oldbezt->tilt;
- newbezt->radius = oldbezt->radius;
- }
-
- fp += KEYELEM_FLOAT_LEN_BEZTRIPLE;
- i++;
- bezt++;
- newbezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- BPoint *newbp = newnu->bp;
- while (a--) {
- oldbp = getKeyIndexOrig_bp(editnurb, bp);
-
- copy_v3_v3(fp, bp->vec);
-
- fp[3] = bp->tilt;
- fp[4] = bp->radius;
-
- if (restore && oldbp) {
- copy_v3_v3(newbp->vec, oldbp->vec);
- newbp->tilt = oldbp->tilt;
- newbp->radius = oldbp->radius;
- }
-
- fp += KEYELEM_FLOAT_LEN_BPOINT;
- bp++;
- newbp++;
- i += 2;
- }
- }
- }
- else {
- int index;
- const float *curofp;
-
- if (oldkey) {
- if (nu->bezt) {
- bezt = nu->bezt;
- a = nu->pntsu;
-
- while (a--) {
- index = getKeyIndexOrig_keyIndex(editnurb, bezt);
- if (index >= 0) {
- int j;
- curofp = ofp + index;
-
- for (j = 0; j < 3; j++, i++) {
- copy_v3_v3(&fp[j * 3], &curofp[j * 3]);
-
- if (apply_offset) {
- add_v3_v3(&fp[j * 3], ofs[i]);
- }
- }
- fp[9] = curofp[9];
- fp[10] = curofp[10];
-
- if (apply_offset) {
- /* Apply tilt offsets. */
- add_v3_v3(fp + 9, ofs[i]);
- i++;
- }
-
- fp += KEYELEM_FLOAT_LEN_BEZTRIPLE;
- }
- else {
- int j;
- for (j = 0; j < 3; j++, i++) {
- copy_v3_v3(&fp[j * 3], bezt->vec[j]);
- }
- fp[9] = bezt->tilt;
- fp[10] = bezt->radius;
-
- fp += KEYELEM_FLOAT_LEN_BEZTRIPLE;
- }
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- index = getKeyIndexOrig_keyIndex(editnurb, bp);
-
- if (index >= 0) {
- curofp = ofp + index;
- copy_v3_v3(fp, curofp);
- fp[3] = curofp[3];
- fp[4] = curofp[4];
-
- if (apply_offset) {
- add_v3_v3(fp, ofs[i]);
- add_v3_v3(&fp[3], ofs[i + 1]);
- }
- }
- else {
- copy_v3_v3(fp, bp->vec);
- fp[3] = bp->tilt;
- fp[4] = bp->radius;
- }
-
- fp += KEYELEM_FLOAT_LEN_BPOINT;
- bp++;
- i += 2;
- }
- }
- }
- }
-
- nu = nu->next;
- newnu = newnu->next;
- }
-
- if (apply_offset) {
- /* handles could become malicious after offsets applying */
- calc_keyHandles(&editnurb->nurbs, newkey);
- }
-
- currkey->totelem = totvert;
- if (currkey->data) {
- MEM_freeN(currkey->data);
- }
- currkey->data = newkey;
-
- currkey = currkey->next;
- }
-
- if (ofs) {
- MEM_freeN(ofs);
- }
- }
+ Curve *cu = (Curve *)obedit->data;
+
+ /* are there keys? */
+ if (cu->key) {
+ int a, i;
+ EditNurb *editnurb = cu->editnurb;
+ KeyBlock *currkey;
+ KeyBlock *actkey = BLI_findlink(&cu->key->block, editnurb->shapenr - 1);
+ BezTriple *bezt, *oldbezt;
+ BPoint *bp, *oldbp;
+ Nurb *nu, *newnu;
+ int totvert = BKE_keyblock_curve_element_count(&editnurb->nurbs);
+
+ float(*ofs)[3] = NULL;
+ float *oldkey, *newkey, *ofp;
+
+ /* editing the base key should update others */
+ if (cu->key->type == KEY_RELATIVE) {
+ if (BKE_keyblock_is_basis(cu->key, editnurb->shapenr - 1)) { /* active key is a base */
+ int totvec = 0;
+
+ /* Calculate needed memory to store offset */
+ nu = editnurb->nurbs.first;
+ while (nu) {
+ if (nu->bezt) {
+ /* Three vects to store handles and one for tilt. */
+ totvec += nu->pntsu * 4;
+ }
+ else {
+ totvec += 2 * nu->pntsu * nu->pntsv;
+ }
+
+ nu = nu->next;
+ }
+
+ ofs = MEM_callocN(sizeof(float) * 3 * totvec, "currkey->data");
+ nu = editnurb->nurbs.first;
+ i = 0;
+ while (nu) {
+ if (nu->bezt) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ oldbezt = getKeyIndexOrig_bezt(editnurb, bezt);
+
+ if (oldbezt) {
+ int j;
+ for (j = 0; j < 3; ++j) {
+ sub_v3_v3v3(ofs[i], bezt->vec[j], oldbezt->vec[j]);
+ i++;
+ }
+ ofs[i][0] = bezt->tilt - oldbezt->tilt;
+ ofs[i][1] = bezt->radius - oldbezt->radius;
+ i++;
+ }
+ else {
+ i += 4;
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ oldbp = getKeyIndexOrig_bp(editnurb, bp);
+ if (oldbp) {
+ sub_v3_v3v3(ofs[i], bp->vec, oldbp->vec);
+ ofs[i + 1][0] = bp->tilt - oldbp->tilt;
+ ofs[i + 1][1] = bp->radius - oldbp->radius;
+ }
+ i += 2;
+ bp++;
+ }
+ }
+
+ nu = nu->next;
+ }
+ }
+ }
+
+ currkey = cu->key->block.first;
+ while (currkey) {
+ const bool apply_offset = (ofs && (currkey != actkey) &&
+ (editnurb->shapenr - 1 == currkey->relative));
+
+ float *fp = newkey = MEM_callocN(cu->key->elemsize * totvert, "currkey->data");
+ ofp = oldkey = currkey->data;
+
+ nu = editnurb->nurbs.first;
+ /* We need to restore to original curve into newnurb, *not* editcurve's nurbs.
+ * Otherwise, in case we update obdata *without* leaving editmode (e.g. viewport render), we would
+ * invalidate editcurve. */
+ newnu = newnurbs->first;
+ i = 0;
+ while (nu) {
+ if (currkey == actkey) {
+ const bool restore = actkey != cu->key->refkey;
+
+ if (nu->bezt) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ BezTriple *newbezt = newnu->bezt;
+ while (a--) {
+ int j;
+ oldbezt = getKeyIndexOrig_bezt(editnurb, bezt);
+
+ for (j = 0; j < 3; j++, i++) {
+ copy_v3_v3(&fp[j * 3], bezt->vec[j]);
+
+ if (restore && oldbezt) {
+ copy_v3_v3(newbezt->vec[j], oldbezt->vec[j]);
+ }
+ }
+ fp[9] = bezt->tilt;
+ fp[10] = bezt->radius;
+
+ if (restore && oldbezt) {
+ newbezt->tilt = oldbezt->tilt;
+ newbezt->radius = oldbezt->radius;
+ }
+
+ fp += KEYELEM_FLOAT_LEN_BEZTRIPLE;
+ i++;
+ bezt++;
+ newbezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ BPoint *newbp = newnu->bp;
+ while (a--) {
+ oldbp = getKeyIndexOrig_bp(editnurb, bp);
+
+ copy_v3_v3(fp, bp->vec);
+
+ fp[3] = bp->tilt;
+ fp[4] = bp->radius;
+
+ if (restore && oldbp) {
+ copy_v3_v3(newbp->vec, oldbp->vec);
+ newbp->tilt = oldbp->tilt;
+ newbp->radius = oldbp->radius;
+ }
+
+ fp += KEYELEM_FLOAT_LEN_BPOINT;
+ bp++;
+ newbp++;
+ i += 2;
+ }
+ }
+ }
+ else {
+ int index;
+ const float *curofp;
+
+ if (oldkey) {
+ if (nu->bezt) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+
+ while (a--) {
+ index = getKeyIndexOrig_keyIndex(editnurb, bezt);
+ if (index >= 0) {
+ int j;
+ curofp = ofp + index;
+
+ for (j = 0; j < 3; j++, i++) {
+ copy_v3_v3(&fp[j * 3], &curofp[j * 3]);
+
+ if (apply_offset) {
+ add_v3_v3(&fp[j * 3], ofs[i]);
+ }
+ }
+ fp[9] = curofp[9];
+ fp[10] = curofp[10];
+
+ if (apply_offset) {
+ /* Apply tilt offsets. */
+ add_v3_v3(fp + 9, ofs[i]);
+ i++;
+ }
+
+ fp += KEYELEM_FLOAT_LEN_BEZTRIPLE;
+ }
+ else {
+ int j;
+ for (j = 0; j < 3; j++, i++) {
+ copy_v3_v3(&fp[j * 3], bezt->vec[j]);
+ }
+ fp[9] = bezt->tilt;
+ fp[10] = bezt->radius;
+
+ fp += KEYELEM_FLOAT_LEN_BEZTRIPLE;
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ index = getKeyIndexOrig_keyIndex(editnurb, bp);
+
+ if (index >= 0) {
+ curofp = ofp + index;
+ copy_v3_v3(fp, curofp);
+ fp[3] = curofp[3];
+ fp[4] = curofp[4];
+
+ if (apply_offset) {
+ add_v3_v3(fp, ofs[i]);
+ add_v3_v3(&fp[3], ofs[i + 1]);
+ }
+ }
+ else {
+ copy_v3_v3(fp, bp->vec);
+ fp[3] = bp->tilt;
+ fp[4] = bp->radius;
+ }
+
+ fp += KEYELEM_FLOAT_LEN_BPOINT;
+ bp++;
+ i += 2;
+ }
+ }
+ }
+ }
+
+ nu = nu->next;
+ newnu = newnu->next;
+ }
+
+ if (apply_offset) {
+ /* handles could become malicious after offsets applying */
+ calc_keyHandles(&editnurb->nurbs, newkey);
+ }
+
+ currkey->totelem = totvert;
+ if (currkey->data) {
+ MEM_freeN(currkey->data);
+ }
+ currkey->data = newkey;
+
+ currkey = currkey->next;
+ }
+
+ if (ofs) {
+ MEM_freeN(ofs);
+ }
+ }
}
/* ********************* Amimation data *************** */
static bool curve_is_animated(Curve *cu)
{
- AnimData *ad = BKE_animdata_from_id(&cu->id);
+ AnimData *ad = BKE_animdata_from_id(&cu->id);
- return ad && (ad->action || ad->drivers.first);
+ return ad && (ad->action || ad->drivers.first);
}
-static void fcurve_path_rename(AnimData *adt, const char *orig_rna_path, char *rna_path,
- ListBase *orig_curves, ListBase *curves)
+static void fcurve_path_rename(AnimData *adt,
+ const char *orig_rna_path,
+ char *rna_path,
+ ListBase *orig_curves,
+ ListBase *curves)
{
- FCurve *fcu, *nfcu, *nextfcu;
- int len = strlen(orig_rna_path);
+ FCurve *fcu, *nfcu, *nextfcu;
+ int len = strlen(orig_rna_path);
- for (fcu = orig_curves->first; fcu; fcu = nextfcu) {
- nextfcu = fcu->next;
- if (STREQLEN(fcu->rna_path, orig_rna_path, len)) {
- char *spath, *suffix = fcu->rna_path + len;
- nfcu = copy_fcurve(fcu);
- spath = nfcu->rna_path;
- nfcu->rna_path = BLI_sprintfN("%s%s", rna_path, suffix);
- BLI_addtail(curves, nfcu);
+ for (fcu = orig_curves->first; fcu; fcu = nextfcu) {
+ nextfcu = fcu->next;
+ if (STREQLEN(fcu->rna_path, orig_rna_path, len)) {
+ char *spath, *suffix = fcu->rna_path + len;
+ nfcu = copy_fcurve(fcu);
+ spath = nfcu->rna_path;
+ nfcu->rna_path = BLI_sprintfN("%s%s", rna_path, suffix);
+ BLI_addtail(curves, nfcu);
- if (fcu->grp) {
- action_groups_remove_channel(adt->action, fcu);
- action_groups_add_channel(adt->action, fcu->grp, nfcu);
- }
- else if ((adt->action) && (&adt->action->curves == orig_curves)) {
- BLI_remlink(&adt->action->curves, fcu);
- }
- else {
- BLI_remlink(&adt->drivers, fcu);
- }
+ if (fcu->grp) {
+ action_groups_remove_channel(adt->action, fcu);
+ action_groups_add_channel(adt->action, fcu->grp, nfcu);
+ }
+ else if ((adt->action) && (&adt->action->curves == orig_curves)) {
+ BLI_remlink(&adt->action->curves, fcu);
+ }
+ else {
+ BLI_remlink(&adt->drivers, fcu);
+ }
- free_fcurve(fcu);
+ free_fcurve(fcu);
- MEM_freeN(spath);
- }
- }
+ MEM_freeN(spath);
+ }
+ }
}
static void fcurve_remove(AnimData *adt, ListBase *orig_curves, FCurve *fcu)
{
- if (orig_curves == &adt->drivers) {
- BLI_remlink(&adt->drivers, fcu);
- }
- else {
- action_groups_remove_channel(adt->action, fcu);
- }
+ if (orig_curves == &adt->drivers) {
+ BLI_remlink(&adt->drivers, fcu);
+ }
+ else {
+ action_groups_remove_channel(adt->action, fcu);
+ }
- free_fcurve(fcu);
+ free_fcurve(fcu);
}
static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves)
{
- int nu_index = 0, a, pt_index;
- EditNurb *editnurb = cu->editnurb;
- Nurb *nu;
- CVKeyIndex *keyIndex;
- char rna_path[64], orig_rna_path[64];
- AnimData *adt = BKE_animdata_from_id(&cu->id);
- ListBase curves = {NULL, NULL};
- FCurve *fcu, *next;
-
- for (nu = editnurb->nurbs.first, nu_index = 0; nu != NULL; nu = nu->next, nu_index++) {
- if (nu->bezt) {
- BezTriple *bezt = nu->bezt;
- a = nu->pntsu;
- pt_index = 0;
-
- while (a--) {
- keyIndex = getCVKeyIndex(editnurb, bezt);
- if (keyIndex) {
- BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d].bezier_points[%d]", nu_index, pt_index);
- BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d].bezier_points[%d]", keyIndex->nu_index, keyIndex->pt_index);
-
- if (keyIndex->switched) {
- char handle_path[64], orig_handle_path[64];
- BLI_snprintf(orig_handle_path, sizeof(orig_rna_path), "%s.handle_left", orig_rna_path);
- BLI_snprintf(handle_path, sizeof(rna_path), "%s.handle_right", rna_path);
- fcurve_path_rename(adt, orig_handle_path, handle_path, orig_curves, &curves);
-
- BLI_snprintf(orig_handle_path, sizeof(orig_rna_path), "%s.handle_right", orig_rna_path);
- BLI_snprintf(handle_path, sizeof(rna_path), "%s.handle_left", rna_path);
- fcurve_path_rename(adt, orig_handle_path, handle_path, orig_curves, &curves);
- }
-
- fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves);
-
- keyIndex->nu_index = nu_index;
- keyIndex->pt_index = pt_index;
- }
-
- bezt++;
- pt_index++;
- }
- }
- else {
- BPoint *bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- pt_index = 0;
-
- while (a--) {
- keyIndex = getCVKeyIndex(editnurb, bp);
- if (keyIndex) {
- BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d].points[%d]", nu_index, pt_index);
- BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d].points[%d]", keyIndex->nu_index, keyIndex->pt_index);
- fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves);
-
- keyIndex->nu_index = nu_index;
- keyIndex->pt_index = pt_index;
- }
-
- bp++;
- pt_index++;
- }
- }
- }
-
- /* remove paths for removed control points
- * need this to make further step with copying non-cv related curves copying
- * not touching cv's f-curves */
- for (fcu = orig_curves->first; fcu; fcu = next) {
- next = fcu->next;
-
- if (STREQLEN(fcu->rna_path, "splines", 7)) {
- const char *ch = strchr(fcu->rna_path, '.');
-
- if (ch && (STREQLEN(ch, ".bezier_points", 14) || STREQLEN(ch, ".points", 7))) {
- fcurve_remove(adt, orig_curves, fcu);
- }
- }
- }
-
- for (nu = editnurb->nurbs.first, nu_index = 0; nu != NULL; nu = nu->next, nu_index++) {
- keyIndex = NULL;
- if (nu->pntsu) {
- if (nu->bezt) {
- keyIndex = getCVKeyIndex(editnurb, &nu->bezt[0]);
- }
- else {
- keyIndex = getCVKeyIndex(editnurb, &nu->bp[0]);
- }
- }
-
- if (keyIndex) {
- BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d]", nu_index);
- BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d]", keyIndex->nu_index);
- fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves);
- }
- }
-
- /* the remainders in orig_curves can be copied back (like follow path) */
- /* (if it's not path to spline) */
- for (fcu = orig_curves->first; fcu; fcu = next) {
- next = fcu->next;
-
- if (STREQLEN(fcu->rna_path, "splines", 7)) {
- fcurve_remove(adt, orig_curves, fcu);
- }
- else {
- BLI_addtail(&curves, fcu);
- }
- }
-
- *orig_curves = curves;
+ int nu_index = 0, a, pt_index;
+ EditNurb *editnurb = cu->editnurb;
+ Nurb *nu;
+ CVKeyIndex *keyIndex;
+ char rna_path[64], orig_rna_path[64];
+ AnimData *adt = BKE_animdata_from_id(&cu->id);
+ ListBase curves = {NULL, NULL};
+ FCurve *fcu, *next;
+
+ for (nu = editnurb->nurbs.first, nu_index = 0; nu != NULL; nu = nu->next, nu_index++) {
+ if (nu->bezt) {
+ BezTriple *bezt = nu->bezt;
+ a = nu->pntsu;
+ pt_index = 0;
+
+ while (a--) {
+ keyIndex = getCVKeyIndex(editnurb, bezt);
+ if (keyIndex) {
+ BLI_snprintf(
+ rna_path, sizeof(rna_path), "splines[%d].bezier_points[%d]", nu_index, pt_index);
+ BLI_snprintf(orig_rna_path,
+ sizeof(orig_rna_path),
+ "splines[%d].bezier_points[%d]",
+ keyIndex->nu_index,
+ keyIndex->pt_index);
+
+ if (keyIndex->switched) {
+ char handle_path[64], orig_handle_path[64];
+ BLI_snprintf(orig_handle_path, sizeof(orig_rna_path), "%s.handle_left", orig_rna_path);
+ BLI_snprintf(handle_path, sizeof(rna_path), "%s.handle_right", rna_path);
+ fcurve_path_rename(adt, orig_handle_path, handle_path, orig_curves, &curves);
+
+ BLI_snprintf(
+ orig_handle_path, sizeof(orig_rna_path), "%s.handle_right", orig_rna_path);
+ BLI_snprintf(handle_path, sizeof(rna_path), "%s.handle_left", rna_path);
+ fcurve_path_rename(adt, orig_handle_path, handle_path, orig_curves, &curves);
+ }
+
+ fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves);
+
+ keyIndex->nu_index = nu_index;
+ keyIndex->pt_index = pt_index;
+ }
+
+ bezt++;
+ pt_index++;
+ }
+ }
+ else {
+ BPoint *bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ pt_index = 0;
+
+ while (a--) {
+ keyIndex = getCVKeyIndex(editnurb, bp);
+ if (keyIndex) {
+ BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d].points[%d]", nu_index, pt_index);
+ BLI_snprintf(orig_rna_path,
+ sizeof(orig_rna_path),
+ "splines[%d].points[%d]",
+ keyIndex->nu_index,
+ keyIndex->pt_index);
+ fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves);
+
+ keyIndex->nu_index = nu_index;
+ keyIndex->pt_index = pt_index;
+ }
+
+ bp++;
+ pt_index++;
+ }
+ }
+ }
+
+ /* remove paths for removed control points
+ * need this to make further step with copying non-cv related curves copying
+ * not touching cv's f-curves */
+ for (fcu = orig_curves->first; fcu; fcu = next) {
+ next = fcu->next;
+
+ if (STREQLEN(fcu->rna_path, "splines", 7)) {
+ const char *ch = strchr(fcu->rna_path, '.');
+
+ if (ch && (STREQLEN(ch, ".bezier_points", 14) || STREQLEN(ch, ".points", 7))) {
+ fcurve_remove(adt, orig_curves, fcu);
+ }
+ }
+ }
+
+ for (nu = editnurb->nurbs.first, nu_index = 0; nu != NULL; nu = nu->next, nu_index++) {
+ keyIndex = NULL;
+ if (nu->pntsu) {
+ if (nu->bezt) {
+ keyIndex = getCVKeyIndex(editnurb, &nu->bezt[0]);
+ }
+ else {
+ keyIndex = getCVKeyIndex(editnurb, &nu->bp[0]);
+ }
+ }
+
+ if (keyIndex) {
+ BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d]", nu_index);
+ BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d]", keyIndex->nu_index);
+ fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves);
+ }
+ }
+
+ /* the remainders in orig_curves can be copied back (like follow path) */
+ /* (if it's not path to spline) */
+ for (fcu = orig_curves->first; fcu; fcu = next) {
+ next = fcu->next;
+
+ if (STREQLEN(fcu->rna_path, "splines", 7)) {
+ fcurve_remove(adt, orig_curves, fcu);
+ }
+ else {
+ BLI_addtail(&curves, fcu);
+ }
+ }
+
+ *orig_curves = curves;
}
/* return 0 if animation data wasn't changed, 1 otherwise */
int ED_curve_updateAnimPaths(Main *bmain, Curve *cu)
{
- AnimData *adt = BKE_animdata_from_id(&cu->id);
- EditNurb *editnurb = cu->editnurb;
+ AnimData *adt = BKE_animdata_from_id(&cu->id);
+ EditNurb *editnurb = cu->editnurb;
- if (!editnurb->keyindex) {
- return 0;
- }
+ if (!editnurb->keyindex) {
+ return 0;
+ }
- if (!curve_is_animated(cu)) {
- return 0;
- }
+ if (!curve_is_animated(cu)) {
+ return 0;
+ }
- if (adt->action != NULL) {
- curve_rename_fcurves(cu, &adt->action->curves);
- DEG_id_tag_update(&adt->action->id, ID_RECALC_COPY_ON_WRITE);
- }
+ if (adt->action != NULL) {
+ curve_rename_fcurves(cu, &adt->action->curves);
+ DEG_id_tag_update(&adt->action->id, ID_RECALC_COPY_ON_WRITE);
+ }
- curve_rename_fcurves(cu, &adt->drivers);
- DEG_id_tag_update(&cu->id, ID_RECALC_COPY_ON_WRITE);
+ curve_rename_fcurves(cu, &adt->drivers);
+ DEG_id_tag_update(&cu->id, ID_RECALC_COPY_ON_WRITE);
- /* TODO(sergey): Only update if something actually changed. */
- DEG_relations_tag_update(bmain);
+ /* TODO(sergey): Only update if something actually changed. */
+ DEG_relations_tag_update(bmain);
- return 1;
+ return 1;
}
/* ********************* LOAD and MAKE *************** */
static int *initialize_index_map(Object *obedit, int *r_old_totvert)
{
- Curve *curve = (Curve *) obedit->data;
- EditNurb *editnurb = curve->editnurb;
- Nurb *nu;
- CVKeyIndex *keyIndex;
- int *old_to_new_map;
- int old_totvert, i;
- int vertex_index;
-
- for (nu = curve->nurb.first, old_totvert = 0; nu != NULL; nu = nu->next) {
- if (nu->bezt) {
- old_totvert += nu->pntsu * 3;
- }
- else {
- old_totvert += nu->pntsu * nu->pntsv;
- }
- }
-
- old_to_new_map = MEM_mallocN(old_totvert * sizeof(int), "curve old to new index map");
- for (i = 0; i < old_totvert; i++) {
- old_to_new_map[i] = -1;
- }
-
- for (nu = editnurb->nurbs.first, vertex_index = 0;
- nu != NULL;
- nu = nu->next)
- {
- if (nu->bezt) {
- BezTriple *bezt = nu->bezt;
- int a = nu->pntsu;
-
- while (a--) {
- keyIndex = getCVKeyIndex(editnurb, bezt);
- if (keyIndex && keyIndex->vertex_index + 2 < old_totvert) {
- if (keyIndex->switched) {
- old_to_new_map[keyIndex->vertex_index] = vertex_index + 2;
- old_to_new_map[keyIndex->vertex_index + 1] = vertex_index + 1;
- old_to_new_map[keyIndex->vertex_index + 2] = vertex_index;
- }
- else {
- old_to_new_map[keyIndex->vertex_index] = vertex_index;
- old_to_new_map[keyIndex->vertex_index + 1] = vertex_index + 1;
- old_to_new_map[keyIndex->vertex_index + 2] = vertex_index + 2;
- }
- }
- vertex_index += 3;
- bezt++;
- }
- }
- else {
- BPoint *bp = nu->bp;
- int a = nu->pntsu * nu->pntsv;
-
- while (a--) {
- keyIndex = getCVKeyIndex(editnurb, bp);
- if (keyIndex) {
- old_to_new_map[keyIndex->vertex_index] = vertex_index;
- }
- vertex_index++;
- bp++;
- }
- }
- }
-
- *r_old_totvert = old_totvert;
- return old_to_new_map;
+ Curve *curve = (Curve *)obedit->data;
+ EditNurb *editnurb = curve->editnurb;
+ Nurb *nu;
+ CVKeyIndex *keyIndex;
+ int *old_to_new_map;
+ int old_totvert, i;
+ int vertex_index;
+
+ for (nu = curve->nurb.first, old_totvert = 0; nu != NULL; nu = nu->next) {
+ if (nu->bezt) {
+ old_totvert += nu->pntsu * 3;
+ }
+ else {
+ old_totvert += nu->pntsu * nu->pntsv;
+ }
+ }
+
+ old_to_new_map = MEM_mallocN(old_totvert * sizeof(int), "curve old to new index map");
+ for (i = 0; i < old_totvert; i++) {
+ old_to_new_map[i] = -1;
+ }
+
+ for (nu = editnurb->nurbs.first, vertex_index = 0; nu != NULL; nu = nu->next) {
+ if (nu->bezt) {
+ BezTriple *bezt = nu->bezt;
+ int a = nu->pntsu;
+
+ while (a--) {
+ keyIndex = getCVKeyIndex(editnurb, bezt);
+ if (keyIndex && keyIndex->vertex_index + 2 < old_totvert) {
+ if (keyIndex->switched) {
+ old_to_new_map[keyIndex->vertex_index] = vertex_index + 2;
+ old_to_new_map[keyIndex->vertex_index + 1] = vertex_index + 1;
+ old_to_new_map[keyIndex->vertex_index + 2] = vertex_index;
+ }
+ else {
+ old_to_new_map[keyIndex->vertex_index] = vertex_index;
+ old_to_new_map[keyIndex->vertex_index + 1] = vertex_index + 1;
+ old_to_new_map[keyIndex->vertex_index + 2] = vertex_index + 2;
+ }
+ }
+ vertex_index += 3;
+ bezt++;
+ }
+ }
+ else {
+ BPoint *bp = nu->bp;
+ int a = nu->pntsu * nu->pntsv;
+
+ while (a--) {
+ keyIndex = getCVKeyIndex(editnurb, bp);
+ if (keyIndex) {
+ old_to_new_map[keyIndex->vertex_index] = vertex_index;
+ }
+ vertex_index++;
+ bp++;
+ }
+ }
+ }
+
+ *r_old_totvert = old_totvert;
+ return old_to_new_map;
}
static void remap_hooks_and_vertex_parents(Main *bmain, Object *obedit)
{
- Object *object;
- Curve *curve = (Curve *) obedit->data;
- EditNurb *editnurb = curve->editnurb;
- int *old_to_new_map = NULL;
- int old_totvert;
-
- if (editnurb->keyindex == NULL) {
- /* TODO(sergey): Happens when separating curves, this would lead to
- * the wrong indices in the hook modifier, address this together with
- * other indices issues.
- */
- return;
- }
-
- for (object = bmain->objects.first; object; object = object->id.next) {
- ModifierData *md;
- int index;
- if ((object->parent) &&
- (object->parent->data == curve) &&
- ELEM(object->partype, PARVERT1, PARVERT3))
- {
- if (old_to_new_map == NULL) {
- old_to_new_map = initialize_index_map(obedit, &old_totvert);
- }
-
- if (object->par1 < old_totvert) {
- index = old_to_new_map[object->par1];
- if (index != -1) {
- object->par1 = index;
- }
- }
- if (object->par2 < old_totvert) {
- index = old_to_new_map[object->par2];
- if (index != -1) {
- object->par2 = index;
- }
- }
- if (object->par3 < old_totvert) {
- index = old_to_new_map[object->par3];
- if (index != -1) {
- object->par3 = index;
- }
- }
- }
- if (object->data == curve) {
- for (md = object->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Hook) {
- HookModifierData *hmd = (HookModifierData *) md;
- int i, j;
-
- if (old_to_new_map == NULL) {
- old_to_new_map = initialize_index_map(obedit, &old_totvert);
- }
-
- for (i = j = 0; i < hmd->totindex; i++) {
- if (hmd->indexar[i] < old_totvert) {
- index = old_to_new_map[hmd->indexar[i]];
- if (index != -1) {
- hmd->indexar[j++] = index;
- }
- }
- else {
- j++;
- }
- }
-
- hmd->totindex = j;
- }
- }
- }
- }
- if (old_to_new_map != NULL) {
- MEM_freeN(old_to_new_map);
- }
+ Object *object;
+ Curve *curve = (Curve *)obedit->data;
+ EditNurb *editnurb = curve->editnurb;
+ int *old_to_new_map = NULL;
+ int old_totvert;
+
+ if (editnurb->keyindex == NULL) {
+ /* TODO(sergey): Happens when separating curves, this would lead to
+ * the wrong indices in the hook modifier, address this together with
+ * other indices issues.
+ */
+ return;
+ }
+
+ for (object = bmain->objects.first; object; object = object->id.next) {
+ ModifierData *md;
+ int index;
+ if ((object->parent) && (object->parent->data == curve) &&
+ ELEM(object->partype, PARVERT1, PARVERT3)) {
+ if (old_to_new_map == NULL) {
+ old_to_new_map = initialize_index_map(obedit, &old_totvert);
+ }
+
+ if (object->par1 < old_totvert) {
+ index = old_to_new_map[object->par1];
+ if (index != -1) {
+ object->par1 = index;
+ }
+ }
+ if (object->par2 < old_totvert) {
+ index = old_to_new_map[object->par2];
+ if (index != -1) {
+ object->par2 = index;
+ }
+ }
+ if (object->par3 < old_totvert) {
+ index = old_to_new_map[object->par3];
+ if (index != -1) {
+ object->par3 = index;
+ }
+ }
+ }
+ if (object->data == curve) {
+ for (md = object->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Hook) {
+ HookModifierData *hmd = (HookModifierData *)md;
+ int i, j;
+
+ if (old_to_new_map == NULL) {
+ old_to_new_map = initialize_index_map(obedit, &old_totvert);
+ }
+
+ for (i = j = 0; i < hmd->totindex; i++) {
+ if (hmd->indexar[i] < old_totvert) {
+ index = old_to_new_map[hmd->indexar[i]];
+ if (index != -1) {
+ hmd->indexar[j++] = index;
+ }
+ }
+ else {
+ j++;
+ }
+ }
+
+ hmd->totindex = j;
+ }
+ }
+ }
+ }
+ if (old_to_new_map != NULL) {
+ MEM_freeN(old_to_new_map);
+ }
}
/* load editNurb in object */
void ED_curve_editnurb_load(Main *bmain, Object *obedit)
{
- ListBase *editnurb = object_editcurve_get(obedit);
+ ListBase *editnurb = object_editcurve_get(obedit);
- if (obedit == NULL) {
- return;
- }
+ if (obedit == NULL) {
+ return;
+ }
- if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
- Curve *cu = obedit->data;
- Nurb *nu, *newnu;
- ListBase newnurb = {NULL, NULL}, oldnurb = cu->nurb;
+ if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ Curve *cu = obedit->data;
+ Nurb *nu, *newnu;
+ ListBase newnurb = {NULL, NULL}, oldnurb = cu->nurb;
- remap_hooks_and_vertex_parents(bmain, obedit);
+ remap_hooks_and_vertex_parents(bmain, obedit);
- for (nu = editnurb->first; nu; nu = nu->next) {
- newnu = BKE_nurb_duplicate(nu);
- BLI_addtail(&newnurb, newnu);
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ newnu = BKE_nurb_duplicate(nu);
+ BLI_addtail(&newnurb, newnu);
- if (nu->type == CU_NURBS) {
- BKE_nurb_order_clamp_u(nu);
- }
- }
+ if (nu->type == CU_NURBS) {
+ BKE_nurb_order_clamp_u(nu);
+ }
+ }
- /* We have to pass also new copied nurbs, since we want to restore original curve (without edited shapekey)
- * on obdata, but *not* on editcurve itself (ED_curve_editnurb_load call does not always implies freeing
- * of editcurve, e.g. when called to generate render data...). */
- calc_shapeKeys(obedit, &newnurb);
+ /* We have to pass also new copied nurbs, since we want to restore original curve (without edited shapekey)
+ * on obdata, but *not* on editcurve itself (ED_curve_editnurb_load call does not always implies freeing
+ * of editcurve, e.g. when called to generate render data...). */
+ calc_shapeKeys(obedit, &newnurb);
- cu->nurb = newnurb;
+ cu->nurb = newnurb;
- ED_curve_updateAnimPaths(bmain, obedit->data);
+ ED_curve_updateAnimPaths(bmain, obedit->data);
- BKE_nurbList_free(&oldnurb);
- }
+ BKE_nurbList_free(&oldnurb);
+ }
}
/* make copy in cu->editnurb */
void ED_curve_editnurb_make(Object *obedit)
{
- Curve *cu = (Curve *)obedit->data;
- EditNurb *editnurb = cu->editnurb;
- Nurb *nu, *newnu;
- KeyBlock *actkey;
+ Curve *cu = (Curve *)obedit->data;
+ EditNurb *editnurb = cu->editnurb;
+ Nurb *nu, *newnu;
+ KeyBlock *actkey;
- if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
- actkey = BKE_keyblock_from_object(obedit);
+ if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ actkey = BKE_keyblock_from_object(obedit);
- if (actkey) {
- // XXX strcpy(G.editModeTitleExtra, "(Key) ");
- /* TODO(campbell): undo_system: investigate why this was needed. */
+ if (actkey) {
+ // XXX strcpy(G.editModeTitleExtra, "(Key) ");
+ /* TODO(campbell): undo_system: investigate why this was needed. */
#if 0
- undo_editmode_clear();
+ undo_editmode_clear();
#endif
- }
-
- if (editnurb) {
- BKE_nurbList_free(&editnurb->nurbs);
- BKE_curve_editNurb_keyIndex_free(&editnurb->keyindex);
- }
- else {
- editnurb = MEM_callocN(sizeof(EditNurb), "editnurb");
- cu->editnurb = editnurb;
- }
-
- nu = cu->nurb.first;
- while (nu) {
- newnu = BKE_nurb_duplicate(nu);
- BKE_nurb_test_2d(newnu); // after join, or any other creation of curve
- BLI_addtail(&editnurb->nurbs, newnu);
- nu = nu->next;
- }
-
- /* animation could be added in editmode even if there was no animdata in
- * object mode hence we always need CVs index be created */
- init_editNurb_keyIndex(editnurb, &cu->nurb);
-
- if (actkey) {
- editnurb->shapenr = obedit->shapenr;
- /* Apply shapekey to new nurbs of editnurb, not those of original curve
- * (and *after* we generated keyIndex), else we do not have valid 'original' data
- * to properly restore curve when leaving editmode. */
- BKE_keyblock_convert_to_curve(actkey, cu, &editnurb->nurbs);
- }
- }
+ }
+
+ if (editnurb) {
+ BKE_nurbList_free(&editnurb->nurbs);
+ BKE_curve_editNurb_keyIndex_free(&editnurb->keyindex);
+ }
+ else {
+ editnurb = MEM_callocN(sizeof(EditNurb), "editnurb");
+ cu->editnurb = editnurb;
+ }
+
+ nu = cu->nurb.first;
+ while (nu) {
+ newnu = BKE_nurb_duplicate(nu);
+ BKE_nurb_test_2d(newnu); // after join, or any other creation of curve
+ BLI_addtail(&editnurb->nurbs, newnu);
+ nu = nu->next;
+ }
+
+ /* animation could be added in editmode even if there was no animdata in
+ * object mode hence we always need CVs index be created */
+ init_editNurb_keyIndex(editnurb, &cu->nurb);
+
+ if (actkey) {
+ editnurb->shapenr = obedit->shapenr;
+ /* Apply shapekey to new nurbs of editnurb, not those of original curve
+ * (and *after* we generated keyIndex), else we do not have valid 'original' data
+ * to properly restore curve when leaving editmode. */
+ BKE_keyblock_convert_to_curve(actkey, cu, &editnurb->nurbs);
+ }
+ }
}
void ED_curve_editnurb_free(Object *obedit)
{
- Curve *cu = obedit->data;
+ Curve *cu = obedit->data;
- BKE_curve_editNurb_free(cu);
+ BKE_curve_editNurb_free(cu);
}
/******************** separate operator ***********************/
static int 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);
- View3D *v3d = CTX_wm_view3d(C);
-
- struct {
- int changed;
- int unselected;
- int error_vertex_keys;
- int error_generic;
- } status = {0};
-
- WM_cursor_wait(1);
-
- 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 b_index = 0; b_index < bases_len; b_index++) {
- Base *oldbase = bases[b_index];
- Base *newbase;
- Object *oldob, *newob;
- Curve *oldcu, *newcu;
- EditNurb *newedit;
- ListBase newnurb = {NULL, NULL};
-
- oldob = oldbase->object;
- oldcu = oldob->data;
-
- if (oldcu->key) {
- status.error_vertex_keys++;
- continue;
- }
-
- if (!ED_curve_select_check(v3d, oldcu->editnurb)) {
- status.unselected++;
- continue;
- }
-
- /* 1. Duplicate geometry and check for valid selection for separate. */
- adduplicateflagNurb(oldob, v3d, &newnurb, SELECT, true);
-
- if (BLI_listbase_is_empty(&newnurb)) {
- status.error_generic++;
- continue;
- }
-
- /* 2. Duplicate the object and data. */
- newbase = ED_object_add_duplicate(
- bmain, scene, view_layer, oldbase, 0); /* 0 = fully linked. */
- DEG_relations_tag_update(bmain);
-
- newob = newbase->object;
- newcu = newob->data = BKE_curve_copy(bmain, oldcu);
- newcu->editnurb = NULL;
- id_us_min(&oldcu->id); /* Because new curve is a copy: reduce user count. */
-
- /* 3. Put new object in editmode, clear it and set separated nurbs. */
- ED_curve_editnurb_make(newob);
- newedit = newcu->editnurb;
- BKE_nurbList_free(&newedit->nurbs);
- BKE_curve_editNurb_keyIndex_free(&newedit->keyindex);
- BLI_movelisttolist(&newedit->nurbs, &newnurb);
-
- /* 4. Put old object out of editmode and delete separated geometry. */
- ED_curve_editnurb_load(bmain, newob);
- ED_curve_editnurb_free(newob);
- curve_delete_segments(oldob, v3d, true);
-
- DEG_id_tag_update(&oldob->id, ID_RECALC_GEOMETRY); /* This is the original one. */
- DEG_id_tag_update(&newob->id, ID_RECALC_GEOMETRY); /* This is the separated one. */
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, oldob->data);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, newob);
- status.changed++;
- }
- MEM_freeN(bases);
- WM_cursor_wait(0);
-
- if (status.unselected == bases_len) {
- BKE_report(op->reports, RPT_ERROR, "No point was selected");
- return OPERATOR_CANCELLED;
- }
-
- const int tot_errors = status.error_vertex_keys + status.error_generic;
- if (tot_errors > 0) {
-
- /* Some curves changed, but some curves failed: don't explain why it failed. */
- if (status.changed) {
- BKE_reportf(op->reports,
- RPT_INFO,
- tot_errors == 1 ? "%d curve could not be separated" :
- "%d curves could not be separated",
- tot_errors);
- return OPERATOR_FINISHED;
- }
-
- /* All curves failed: If there is more than one error give a generic error report. */
- if (((status.error_vertex_keys ? 1 : 0) + (status.error_generic ? 1 : 0)) > 1) {
- BKE_report(op->reports,
- RPT_ERROR,
- tot_errors == 1 ? "Could not separate selected curves" :
- "Could not separate selected curve");
- }
-
- /* All curves failed due to the same error. */
- if (status.error_vertex_keys) {
- BKE_report(op->reports, RPT_ERROR, "Cannot separate curves with vertex keys");
- }
- else {
- BLI_assert(status.error_generic);
- BKE_report(op->reports, RPT_ERROR, "Cannot separate current selection");
- }
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ struct {
+ int changed;
+ int unselected;
+ int error_vertex_keys;
+ int error_generic;
+ } status = {0};
+
+ WM_cursor_wait(1);
+
+ 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 b_index = 0; b_index < bases_len; b_index++) {
+ Base *oldbase = bases[b_index];
+ Base *newbase;
+ Object *oldob, *newob;
+ Curve *oldcu, *newcu;
+ EditNurb *newedit;
+ ListBase newnurb = {NULL, NULL};
+
+ oldob = oldbase->object;
+ oldcu = oldob->data;
+
+ if (oldcu->key) {
+ status.error_vertex_keys++;
+ continue;
+ }
+
+ if (!ED_curve_select_check(v3d, oldcu->editnurb)) {
+ status.unselected++;
+ continue;
+ }
+
+ /* 1. Duplicate geometry and check for valid selection for separate. */
+ adduplicateflagNurb(oldob, v3d, &newnurb, SELECT, true);
+
+ if (BLI_listbase_is_empty(&newnurb)) {
+ status.error_generic++;
+ continue;
+ }
+
+ /* 2. Duplicate the object and data. */
+ newbase = ED_object_add_duplicate(
+ bmain, scene, view_layer, oldbase, 0); /* 0 = fully linked. */
+ DEG_relations_tag_update(bmain);
+
+ newob = newbase->object;
+ newcu = newob->data = BKE_curve_copy(bmain, oldcu);
+ newcu->editnurb = NULL;
+ id_us_min(&oldcu->id); /* Because new curve is a copy: reduce user count. */
+
+ /* 3. Put new object in editmode, clear it and set separated nurbs. */
+ ED_curve_editnurb_make(newob);
+ newedit = newcu->editnurb;
+ BKE_nurbList_free(&newedit->nurbs);
+ BKE_curve_editNurb_keyIndex_free(&newedit->keyindex);
+ BLI_movelisttolist(&newedit->nurbs, &newnurb);
+
+ /* 4. Put old object out of editmode and delete separated geometry. */
+ ED_curve_editnurb_load(bmain, newob);
+ ED_curve_editnurb_free(newob);
+ curve_delete_segments(oldob, v3d, true);
+
+ DEG_id_tag_update(&oldob->id, ID_RECALC_GEOMETRY); /* This is the original one. */
+ DEG_id_tag_update(&newob->id, ID_RECALC_GEOMETRY); /* This is the separated one. */
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, oldob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, newob);
+ status.changed++;
+ }
+ MEM_freeN(bases);
+ WM_cursor_wait(0);
+
+ if (status.unselected == bases_len) {
+ BKE_report(op->reports, RPT_ERROR, "No point was selected");
+ return OPERATOR_CANCELLED;
+ }
+
+ const int tot_errors = status.error_vertex_keys + status.error_generic;
+ if (tot_errors > 0) {
+
+ /* Some curves changed, but some curves failed: don't explain why it failed. */
+ if (status.changed) {
+ BKE_reportf(op->reports,
+ RPT_INFO,
+ tot_errors == 1 ? "%d curve could not be separated" :
+ "%d curves could not be separated",
+ tot_errors);
+ return OPERATOR_FINISHED;
+ }
+
+ /* All curves failed: If there is more than one error give a generic error report. */
+ if (((status.error_vertex_keys ? 1 : 0) + (status.error_generic ? 1 : 0)) > 1) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ tot_errors == 1 ? "Could not separate selected curves" :
+ "Could not separate selected curve");
+ }
+
+ /* All curves failed due to the same error. */
+ if (status.error_vertex_keys) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot separate curves with vertex keys");
+ }
+ else {
+ BLI_assert(status.error_generic);
+ BKE_report(op->reports, RPT_ERROR, "Cannot separate current selection");
+ }
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
void CURVE_OT_separate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Separate";
- ot->idname = "CURVE_OT_separate";
- ot->description = "Separate selected points from connected unselected points into a new object";
+ /* identifiers */
+ ot->name = "Separate";
+ ot->idname = "CURVE_OT_separate";
+ ot->description = "Separate selected points from connected unselected points into a new object";
- /* api callbacks */
- ot->invoke = WM_operator_confirm;
- ot->exec = separate_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = separate_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************** split operator ***********************/
static int curve_split_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- int ok = -1;
+ Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ int ok = -1;
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Curve *cu = obedit->data;
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Curve *cu = obedit->data;
- if (!ED_curve_select_check(v3d, cu->editnurb)) {
- continue;
- }
+ if (!ED_curve_select_check(v3d, cu->editnurb)) {
+ continue;
+ }
- ListBase newnurb = {NULL, NULL};
+ ListBase newnurb = {NULL, NULL};
- adduplicateflagNurb(obedit, v3d, &newnurb, SELECT, true);
+ adduplicateflagNurb(obedit, v3d, &newnurb, SELECT, true);
- if (BLI_listbase_is_empty(&newnurb)) {
- ok = MAX2(ok, 0);
- continue;
- }
+ if (BLI_listbase_is_empty(&newnurb)) {
+ ok = MAX2(ok, 0);
+ continue;
+ }
- ListBase *editnurb = object_editcurve_get(obedit);
- const int len_orig = BLI_listbase_count(editnurb);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ const int len_orig = BLI_listbase_count(editnurb);
- curve_delete_segments(obedit, v3d, true);
- cu->actnu -= len_orig - BLI_listbase_count(editnurb);
- BLI_movelisttolist(editnurb, &newnurb);
+ curve_delete_segments(obedit, v3d, true);
+ cu->actnu -= len_orig - BLI_listbase_count(editnurb);
+ BLI_movelisttolist(editnurb, &newnurb);
- if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
- }
+ if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ }
- ok = 1;
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
- }
- MEM_freeN(objects);
+ ok = 1;
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+ }
+ MEM_freeN(objects);
- if (ok == 0) {
- BKE_report(op->reports, RPT_ERROR, "Cannot split current selection");
- return OPERATOR_CANCELLED;
- }
- return OPERATOR_FINISHED;
+ if (ok == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot split current selection");
+ return OPERATOR_CANCELLED;
+ }
+ return OPERATOR_FINISHED;
}
void CURVE_OT_split(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Split";
- ot->idname = "CURVE_OT_split";
- ot->description = "Split off selected points from connected unselected points";
+ /* identifiers */
+ ot->name = "Split";
+ ot->idname = "CURVE_OT_split";
+ ot->description = "Split off selected points from connected unselected points";
- /* api callbacks */
- ot->exec = curve_split_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = curve_split_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************* FLAGS ********************* */
-static bool isNurbselUV(
- const Nurb *nu, int flag,
- int *r_u, int *r_v)
-{
- /* return (u != -1): 1 row in u-direction selected. U has value between 0-pntsv
- * return (v != -1): 1 column in v-direction selected. V has value between 0-pntsu
- */
- BPoint *bp;
- int a, b, sel;
-
- *r_u = *r_v = -1;
-
- bp = nu->bp;
- for (b = 0; b < nu->pntsv; b++) {
- sel = 0;
- for (a = 0; a < nu->pntsu; a++, bp++) {
- if (bp->f1 & flag) {
- sel++;
- }
- }
- if (sel == nu->pntsu) {
- if (*r_u == -1) {
- *r_u = b;
- }
- else {
- return 0;
- }
- }
- else if (sel > 1) {
- return 0; /* because sel == 1 is still ok */
- }
- }
-
- for (a = 0; a < nu->pntsu; a++) {
- sel = 0;
- bp = &nu->bp[a];
- for (b = 0; b < nu->pntsv; b++, bp += nu->pntsu) {
- if (bp->f1 & flag) {
- sel++;
- }
- }
- if (sel == nu->pntsv) {
- if (*r_v == -1) {
- *r_v = a;
- }
- else {
- return 0;
- }
- }
- else if (sel > 1) {
- return 0;
- }
- }
-
- if (*r_u == -1 && *r_v > -1) {
- return 1;
- }
- if (*r_v == -1 && *r_u > -1) {
- return 1;
- }
- return 0;
+static bool isNurbselUV(const Nurb *nu, int flag, int *r_u, int *r_v)
+{
+ /* return (u != -1): 1 row in u-direction selected. U has value between 0-pntsv
+ * return (v != -1): 1 column in v-direction selected. V has value between 0-pntsu
+ */
+ BPoint *bp;
+ int a, b, sel;
+
+ *r_u = *r_v = -1;
+
+ bp = nu->bp;
+ for (b = 0; b < nu->pntsv; b++) {
+ sel = 0;
+ for (a = 0; a < nu->pntsu; a++, bp++) {
+ if (bp->f1 & flag) {
+ sel++;
+ }
+ }
+ if (sel == nu->pntsu) {
+ if (*r_u == -1) {
+ *r_u = b;
+ }
+ else {
+ return 0;
+ }
+ }
+ else if (sel > 1) {
+ return 0; /* because sel == 1 is still ok */
+ }
+ }
+
+ for (a = 0; a < nu->pntsu; a++) {
+ sel = 0;
+ bp = &nu->bp[a];
+ for (b = 0; b < nu->pntsv; b++, bp += nu->pntsu) {
+ if (bp->f1 & flag) {
+ sel++;
+ }
+ }
+ if (sel == nu->pntsv) {
+ if (*r_v == -1) {
+ *r_v = a;
+ }
+ else {
+ return 0;
+ }
+ }
+ else if (sel > 1) {
+ return 0;
+ }
+ }
+
+ if (*r_u == -1 && *r_v > -1) {
+ return 1;
+ }
+ if (*r_v == -1 && *r_u > -1) {
+ return 1;
+ }
+ return 0;
}
/* return true if U direction is selected and number of selected columns v */
static bool isNurbselU(Nurb *nu, int *v, int flag)
{
- BPoint *bp;
- int a, b, sel;
+ BPoint *bp;
+ int a, b, sel;
- *v = 0;
+ *v = 0;
- for (b = 0, bp = nu->bp; b < nu->pntsv; b++) {
- sel = 0;
- for (a = 0; a < nu->pntsu; a++, bp++) {
- if (bp->f1 & flag) {
- sel++;
- }
- }
- if (sel == nu->pntsu) {
- (*v)++;
- }
- else if (sel >= 1) {
- *v = 0;
- return 0;
- }
- }
+ for (b = 0, bp = nu->bp; b < nu->pntsv; b++) {
+ sel = 0;
+ for (a = 0; a < nu->pntsu; a++, bp++) {
+ if (bp->f1 & flag) {
+ sel++;
+ }
+ }
+ if (sel == nu->pntsu) {
+ (*v)++;
+ }
+ else if (sel >= 1) {
+ *v = 0;
+ return 0;
+ }
+ }
- return 1;
+ return 1;
}
/* return true if V direction is selected and number of selected rows u */
static bool isNurbselV(Nurb *nu, int *u, int flag)
{
- BPoint *bp;
- int a, b, sel;
+ BPoint *bp;
+ int a, b, sel;
- *u = 0;
+ *u = 0;
- for (a = 0; a < nu->pntsu; a++) {
- bp = &nu->bp[a];
- sel = 0;
- for (b = 0; b < nu->pntsv; b++, bp += nu->pntsu) {
- if (bp->f1 & flag) {
- sel++;
- }
- }
- if (sel == nu->pntsv) {
- (*u)++;
- }
- else if (sel >= 1) {
- *u = 0;
- return 0;
- }
- }
+ for (a = 0; a < nu->pntsu; a++) {
+ bp = &nu->bp[a];
+ sel = 0;
+ for (b = 0; b < nu->pntsv; b++, bp += nu->pntsu) {
+ if (bp->f1 & flag) {
+ sel++;
+ }
+ }
+ if (sel == nu->pntsv) {
+ (*u)++;
+ }
+ else if (sel >= 1) {
+ *u = 0;
+ return 0;
+ }
+ }
- return 1;
+ return 1;
}
static void rotateflagNurb(ListBase *editnurb, short flag, const float cent[3], float rotmat[3][3])
{
- /* all verts with (flag & 'flag') rotate */
- Nurb *nu;
- BPoint *bp;
- int a;
+ /* all verts with (flag & 'flag') rotate */
+ Nurb *nu;
+ BPoint *bp;
+ int a;
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_NURBS) {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_NURBS) {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (bp->f1 & flag) {
- sub_v3_v3(bp->vec, cent);
- mul_m3_v3(rotmat, bp->vec);
- add_v3_v3(bp->vec, cent);
- }
- bp++;
- }
- }
- }
+ while (a--) {
+ if (bp->f1 & flag) {
+ sub_v3_v3(bp->vec, cent);
+ mul_m3_v3(rotmat, bp->vec);
+ add_v3_v3(bp->vec, cent);
+ }
+ bp++;
+ }
+ }
+ }
}
void ed_editnurb_translate_flag(ListBase *editnurb, short flag, const float vec[3])
{
- /* all verts with ('flag' & flag) translate */
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- a = nu->pntsu;
- bezt = nu->bezt;
- while (a--) {
- if (bezt->f1 & flag) { add_v3_v3(bezt->vec[0], vec); }
- if (bezt->f2 & flag) { add_v3_v3(bezt->vec[1], vec); }
- if (bezt->f3 & flag) { add_v3_v3(bezt->vec[2], vec); }
- bezt++;
- }
- }
- else {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a--) {
- if (bp->f1 & flag) {
- add_v3_v3(bp->vec, vec);
- }
- bp++;
- }
- }
-
- BKE_nurb_test_2d(nu);
- }
+ /* all verts with ('flag' & flag) translate */
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ while (a--) {
+ if (bezt->f1 & flag) {
+ add_v3_v3(bezt->vec[0], vec);
+ }
+ if (bezt->f2 & flag) {
+ add_v3_v3(bezt->vec[1], vec);
+ }
+ if (bezt->f3 & flag) {
+ add_v3_v3(bezt->vec[2], vec);
+ }
+ bezt++;
+ }
+ }
+ else {
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a--) {
+ if (bp->f1 & flag) {
+ add_v3_v3(bp->vec, vec);
+ }
+ bp++;
+ }
+ }
+
+ BKE_nurb_test_2d(nu);
+ }
}
static void weightflagNurb(ListBase *editnurb, short flag, float w)
{
- Nurb *nu;
- BPoint *bp;
- int a;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_NURBS) {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a--) {
- if (bp->f1 & flag) {
- /* a mode used to exist for replace/multiple but is was unused */
- bp->vec[3] *= w;
- }
- bp++;
- }
- }
- }
+ Nurb *nu;
+ BPoint *bp;
+ int a;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_NURBS) {
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a--) {
+ if (bp->f1 & flag) {
+ /* a mode used to exist for replace/multiple but is was unused */
+ bp->vec[3] *= w;
+ }
+ bp++;
+ }
+ }
+ }
}
static void ed_surf_delete_selected(Object *obedit)
{
- Curve *cu = obedit->data;
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu, *next;
- BPoint *bp, *bpn, *newbp;
- int a, b, newu, newv;
-
- BLI_assert(obedit->type == OB_SURF);
-
- nu = editnurb->first;
- while (nu) {
- next = nu->next;
-
- /* is entire nurb selected */
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a) {
- a--;
- if (bp->f1 & SELECT) {
- /* pass */
- }
- else {
- break;
- }
- bp++;
- }
- if (a == 0) {
- BLI_remlink(editnurb, nu);
- keyIndex_delNurb(cu->editnurb, nu);
- BKE_nurb_free(nu); nu = NULL;
- }
- else {
- if (isNurbselU(nu, &newv, SELECT)) {
- /* U direction selected */
- newv = nu->pntsv - newv;
- if (newv != nu->pntsv) {
- /* delete */
- bp = nu->bp;
- bpn = newbp = (BPoint *)MEM_mallocN(newv * nu->pntsu * sizeof(BPoint), "deleteNurb");
- for (b = 0; b < nu->pntsv; b++) {
- if ((bp->f1 & SELECT) == 0) {
- memcpy(bpn, bp, nu->pntsu * sizeof(BPoint));
- keyIndex_updateBP(cu->editnurb, bp, bpn, nu->pntsu);
- bpn += nu->pntsu;
- }
- else {
- keyIndex_delBP(cu->editnurb, bp);
- }
- bp += nu->pntsu;
- }
- nu->pntsv = newv;
- MEM_freeN(nu->bp);
- nu->bp = newbp;
- BKE_nurb_order_clamp_v(nu);
-
- BKE_nurb_knot_calc_v(nu);
- }
- }
- else if (isNurbselV(nu, &newu, SELECT)) {
- /* V direction selected */
- newu = nu->pntsu - newu;
- if (newu != nu->pntsu) {
- /* delete */
- bp = nu->bp;
- bpn = newbp = (BPoint *)MEM_mallocN(newu * nu->pntsv * sizeof(BPoint), "deleteNurb");
- for (b = 0; b < nu->pntsv; b++) {
- for (a = 0; a < nu->pntsu; a++, bp++) {
- if ((bp->f1 & SELECT) == 0) {
- *bpn = *bp;
- keyIndex_updateBP(cu->editnurb, bp, bpn, 1);
- bpn++;
- }
- else {
- keyIndex_delBP(cu->editnurb, bp);
- }
- }
- }
- MEM_freeN(nu->bp);
- nu->bp = newbp;
- if (newu == 1 && nu->pntsv > 1) { /* make a U spline */
- nu->pntsu = nu->pntsv;
- nu->pntsv = 1;
- SWAP(short, nu->orderu, nu->orderv);
- BKE_nurb_order_clamp_u(nu);
- if (nu->knotsv) {
- MEM_freeN(nu->knotsv);
- }
- nu->knotsv = NULL;
- }
- else {
- nu->pntsu = newu;
- BKE_nurb_order_clamp_u(nu);
- }
- BKE_nurb_knot_calc_u(nu);
- }
- }
- }
- nu = next;
- }
+ Curve *cu = obedit->data;
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu, *next;
+ BPoint *bp, *bpn, *newbp;
+ int a, b, newu, newv;
+
+ BLI_assert(obedit->type == OB_SURF);
+
+ nu = editnurb->first;
+ while (nu) {
+ next = nu->next;
+
+ /* is entire nurb selected */
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a) {
+ a--;
+ if (bp->f1 & SELECT) {
+ /* pass */
+ }
+ else {
+ break;
+ }
+ bp++;
+ }
+ if (a == 0) {
+ BLI_remlink(editnurb, nu);
+ keyIndex_delNurb(cu->editnurb, nu);
+ BKE_nurb_free(nu);
+ nu = NULL;
+ }
+ else {
+ if (isNurbselU(nu, &newv, SELECT)) {
+ /* U direction selected */
+ newv = nu->pntsv - newv;
+ if (newv != nu->pntsv) {
+ /* delete */
+ bp = nu->bp;
+ bpn = newbp = (BPoint *)MEM_mallocN(newv * nu->pntsu * sizeof(BPoint), "deleteNurb");
+ for (b = 0; b < nu->pntsv; b++) {
+ if ((bp->f1 & SELECT) == 0) {
+ memcpy(bpn, bp, nu->pntsu * sizeof(BPoint));
+ keyIndex_updateBP(cu->editnurb, bp, bpn, nu->pntsu);
+ bpn += nu->pntsu;
+ }
+ else {
+ keyIndex_delBP(cu->editnurb, bp);
+ }
+ bp += nu->pntsu;
+ }
+ nu->pntsv = newv;
+ MEM_freeN(nu->bp);
+ nu->bp = newbp;
+ BKE_nurb_order_clamp_v(nu);
+
+ BKE_nurb_knot_calc_v(nu);
+ }
+ }
+ else if (isNurbselV(nu, &newu, SELECT)) {
+ /* V direction selected */
+ newu = nu->pntsu - newu;
+ if (newu != nu->pntsu) {
+ /* delete */
+ bp = nu->bp;
+ bpn = newbp = (BPoint *)MEM_mallocN(newu * nu->pntsv * sizeof(BPoint), "deleteNurb");
+ for (b = 0; b < nu->pntsv; b++) {
+ for (a = 0; a < nu->pntsu; a++, bp++) {
+ if ((bp->f1 & SELECT) == 0) {
+ *bpn = *bp;
+ keyIndex_updateBP(cu->editnurb, bp, bpn, 1);
+ bpn++;
+ }
+ else {
+ keyIndex_delBP(cu->editnurb, bp);
+ }
+ }
+ }
+ MEM_freeN(nu->bp);
+ nu->bp = newbp;
+ if (newu == 1 && nu->pntsv > 1) { /* make a U spline */
+ nu->pntsu = nu->pntsv;
+ nu->pntsv = 1;
+ SWAP(short, nu->orderu, nu->orderv);
+ BKE_nurb_order_clamp_u(nu);
+ if (nu->knotsv) {
+ MEM_freeN(nu->knotsv);
+ }
+ nu->knotsv = NULL;
+ }
+ else {
+ nu->pntsu = newu;
+ BKE_nurb_order_clamp_u(nu);
+ }
+ BKE_nurb_knot_calc_u(nu);
+ }
+ }
+ }
+ nu = next;
+ }
}
static void ed_curve_delete_selected(Object *obedit, View3D *v3d)
{
- Curve *cu = obedit->data;
- EditNurb *editnurb = cu->editnurb;
- ListBase *nubase = &editnurb->nurbs;
- Nurb *nu, *next;
- BezTriple *bezt, *bezt1;
- BPoint *bp, *bp1;
- int a, type, nuindex = 0;
-
- /* first loop, can we remove entire pieces? */
- nu = nubase->first;
- while (nu) {
- next = nu->next;
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- if (a) {
- while (a) {
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
- /* pass */
- }
- else {
- break;
- }
- a--;
- bezt++;
- }
- if (a == 0) {
- if (cu->actnu == nuindex) {
- cu->actnu = CU_ACT_NONE;
- }
-
- BLI_remlink(nubase, nu);
- keyIndex_delNurb(editnurb, nu);
- BKE_nurb_free(nu); nu = NULL;
- }
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- if (a) {
- while (a) {
- if (bp->f1 & SELECT) {
- /* pass */
- }
- else {
- break;
- }
- a--;
- bp++;
- }
- if (a == 0) {
- if (cu->actnu == nuindex) {
- cu->actnu = CU_ACT_NONE;
- }
-
- BLI_remlink(nubase, nu);
- keyIndex_delNurb(editnurb, nu);
- BKE_nurb_free(nu); nu = NULL;
- }
- }
- }
-
- /* Never allow the order to exceed the number of points
- * - note, this is ok but changes unselected nurbs, disable for now */
+ Curve *cu = obedit->data;
+ EditNurb *editnurb = cu->editnurb;
+ ListBase *nubase = &editnurb->nurbs;
+ Nurb *nu, *next;
+ BezTriple *bezt, *bezt1;
+ BPoint *bp, *bp1;
+ int a, type, nuindex = 0;
+
+ /* first loop, can we remove entire pieces? */
+ nu = nubase->first;
+ while (nu) {
+ next = nu->next;
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ if (a) {
+ while (a) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
+ /* pass */
+ }
+ else {
+ break;
+ }
+ a--;
+ bezt++;
+ }
+ if (a == 0) {
+ if (cu->actnu == nuindex) {
+ cu->actnu = CU_ACT_NONE;
+ }
+
+ BLI_remlink(nubase, nu);
+ keyIndex_delNurb(editnurb, nu);
+ BKE_nurb_free(nu);
+ nu = NULL;
+ }
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ if (a) {
+ while (a) {
+ if (bp->f1 & SELECT) {
+ /* pass */
+ }
+ else {
+ break;
+ }
+ a--;
+ bp++;
+ }
+ if (a == 0) {
+ if (cu->actnu == nuindex) {
+ cu->actnu = CU_ACT_NONE;
+ }
+
+ BLI_remlink(nubase, nu);
+ keyIndex_delNurb(editnurb, nu);
+ BKE_nurb_free(nu);
+ nu = NULL;
+ }
+ }
+ }
+
+ /* Never allow the order to exceed the number of points
+ * - note, this is ok but changes unselected nurbs, disable for now */
#if 0
- if ((nu != NULL) && (nu->type == CU_NURBS)) {
- clamp_nurb_order_u(nu);
- }
+ if ((nu != NULL) && (nu->type == CU_NURBS)) {
+ clamp_nurb_order_u(nu);
+ }
#endif
- nu = next;
- nuindex++;
- }
- /* 2nd loop, delete small pieces: just for curves */
- nu = nubase->first;
- while (nu) {
- next = nu->next;
- type = 0;
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- for (a = 0; a < nu->pntsu; a++) {
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
- memmove(bezt, bezt + 1, (nu->pntsu - a - 1) * sizeof(BezTriple));
- keyIndex_delBezt(editnurb, bezt);
- keyIndex_updateBezt(editnurb, bezt + 1, bezt, nu->pntsu - a - 1);
- nu->pntsu--;
- a--;
- type = 1;
- }
- else {
- bezt++;
- }
- }
- if (type) {
- bezt1 = (BezTriple *)MEM_mallocN((nu->pntsu) * sizeof(BezTriple), "delNurb");
- memcpy(bezt1, nu->bezt, (nu->pntsu) * sizeof(BezTriple));
- keyIndex_updateBezt(editnurb, nu->bezt, bezt1, nu->pntsu);
- MEM_freeN(nu->bezt);
- nu->bezt = bezt1;
- BKE_nurb_handles_calc(nu);
- }
- }
- else if (nu->pntsv == 1) {
- bp = nu->bp;
-
- for (a = 0; a < nu->pntsu; a++) {
- if (bp->f1 & SELECT) {
- memmove(bp, bp + 1, (nu->pntsu - a - 1) * sizeof(BPoint));
- keyIndex_delBP(editnurb, bp);
- keyIndex_updateBP(editnurb, bp + 1, bp, nu->pntsu - a - 1);
- nu->pntsu--;
- a--;
- type = 1;
- }
- else {
- bp++;
- }
- }
- if (type) {
- bp1 = (BPoint *)MEM_mallocN(nu->pntsu * sizeof(BPoint), "delNurb2");
- memcpy(bp1, nu->bp, (nu->pntsu) * sizeof(BPoint));
- keyIndex_updateBP(editnurb, nu->bp, bp1, nu->pntsu);
- MEM_freeN(nu->bp);
- nu->bp = bp1;
-
- /* Never allow the order to exceed the number of points
- * - note, this is ok but changes unselected nurbs, disable for now */
+ nu = next;
+ nuindex++;
+ }
+ /* 2nd loop, delete small pieces: just for curves */
+ nu = nubase->first;
+ while (nu) {
+ next = nu->next;
+ type = 0;
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ for (a = 0; a < nu->pntsu; a++) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
+ memmove(bezt, bezt + 1, (nu->pntsu - a - 1) * sizeof(BezTriple));
+ keyIndex_delBezt(editnurb, bezt);
+ keyIndex_updateBezt(editnurb, bezt + 1, bezt, nu->pntsu - a - 1);
+ nu->pntsu--;
+ a--;
+ type = 1;
+ }
+ else {
+ bezt++;
+ }
+ }
+ if (type) {
+ bezt1 = (BezTriple *)MEM_mallocN((nu->pntsu) * sizeof(BezTriple), "delNurb");
+ memcpy(bezt1, nu->bezt, (nu->pntsu) * sizeof(BezTriple));
+ keyIndex_updateBezt(editnurb, nu->bezt, bezt1, nu->pntsu);
+ MEM_freeN(nu->bezt);
+ nu->bezt = bezt1;
+ BKE_nurb_handles_calc(nu);
+ }
+ }
+ else if (nu->pntsv == 1) {
+ bp = nu->bp;
+
+ for (a = 0; a < nu->pntsu; a++) {
+ if (bp->f1 & SELECT) {
+ memmove(bp, bp + 1, (nu->pntsu - a - 1) * sizeof(BPoint));
+ keyIndex_delBP(editnurb, bp);
+ keyIndex_updateBP(editnurb, bp + 1, bp, nu->pntsu - a - 1);
+ nu->pntsu--;
+ a--;
+ type = 1;
+ }
+ else {
+ bp++;
+ }
+ }
+ if (type) {
+ bp1 = (BPoint *)MEM_mallocN(nu->pntsu * sizeof(BPoint), "delNurb2");
+ memcpy(bp1, nu->bp, (nu->pntsu) * sizeof(BPoint));
+ keyIndex_updateBP(editnurb, nu->bp, bp1, nu->pntsu);
+ MEM_freeN(nu->bp);
+ nu->bp = bp1;
+
+ /* Never allow the order to exceed the number of points
+ * - note, this is ok but changes unselected nurbs, disable for now */
#if 0
- if (nu->type == CU_NURBS) {
- clamp_nurb_order_u(nu);
- }
+ if (nu->type == CU_NURBS) {
+ clamp_nurb_order_u(nu);
+ }
#endif
- }
- BKE_nurb_order_clamp_u(nu);
- BKE_nurb_knot_calc_u(nu);
- }
- nu = next;
- }
+ }
+ BKE_nurb_order_clamp_u(nu);
+ BKE_nurb_knot_calc_u(nu);
+ }
+ nu = next;
+ }
}
/* only for OB_SURF */
bool ed_editnurb_extrude_flag(EditNurb *editnurb, const short flag)
{
- Nurb *nu;
- BPoint *bp, *bpn, *newbp;
- int a, u, v, len;
- bool ok = false;
-
- nu = editnurb->nurbs.first;
- while (nu) {
-
- if (nu->pntsv == 1) {
- bp = nu->bp;
- a = nu->pntsu;
- while (a) {
- if (bp->f1 & flag) {
- /* pass */
- }
- else {
- break;
- }
- bp++;
- a--;
- }
- if (a == 0) {
- ok = true;
- newbp = (BPoint *)MEM_mallocN(2 * nu->pntsu * sizeof(BPoint), "extrudeNurb1");
- ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu);
- bp = newbp + nu->pntsu;
- ED_curve_bpcpy(editnurb, bp, nu->bp, nu->pntsu);
- MEM_freeN(nu->bp);
- nu->bp = newbp;
- a = nu->pntsu;
- while (a--) {
- select_bpoint(bp, SELECT, flag, HIDDEN);
- select_bpoint(newbp, DESELECT, flag, HIDDEN);
- bp++;
- newbp++;
- }
-
- nu->pntsv = 2;
- nu->orderv = 2;
- BKE_nurb_knot_calc_v(nu);
- }
- }
- else {
- /* which row or column is selected */
-
- if (isNurbselUV(nu, flag, &u, &v)) {
-
- /* deselect all */
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- select_bpoint(bp, DESELECT, flag, HIDDEN);
- bp++;
- }
-
- if (u == 0 || u == nu->pntsv - 1) { /* row in u-direction selected */
- ok = true;
- newbp = (BPoint *)MEM_mallocN(nu->pntsu * (nu->pntsv + 1) *
- sizeof(BPoint), "extrudeNurb1");
- if (u == 0) {
- len = nu->pntsv * nu->pntsu;
- ED_curve_bpcpy(editnurb, newbp + nu->pntsu, nu->bp, len);
- ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu);
- bp = newbp;
- }
- else {
- len = nu->pntsv * nu->pntsu;
- ED_curve_bpcpy(editnurb, newbp, nu->bp, len);
- ED_curve_bpcpy(editnurb, newbp + len, &nu->bp[len - nu->pntsu], nu->pntsu);
- bp = newbp + len;
- }
-
- a = nu->pntsu;
- while (a--) {
- select_bpoint(bp, SELECT, flag, HIDDEN);
- bp++;
- }
-
- MEM_freeN(nu->bp);
- nu->bp = newbp;
- nu->pntsv++;
- BKE_nurb_knot_calc_v(nu);
- }
- else if (v == 0 || v == nu->pntsu - 1) { /* column in v-direction selected */
- ok = true;
- bpn = newbp = (BPoint *)MEM_mallocN((nu->pntsu + 1) * nu->pntsv * sizeof(BPoint), "extrudeNurb1");
- bp = nu->bp;
-
- for (a = 0; a < nu->pntsv; a++) {
- if (v == 0) {
- *bpn = *bp;
- bpn->f1 |= flag;
- bpn++;
- }
- ED_curve_bpcpy(editnurb, bpn, bp, nu->pntsu);
- bp += nu->pntsu;
- bpn += nu->pntsu;
- if (v == nu->pntsu - 1) {
- *bpn = *(bp - 1);
- bpn->f1 |= flag;
- bpn++;
- }
- }
-
- MEM_freeN(nu->bp);
- nu->bp = newbp;
- nu->pntsu++;
- BKE_nurb_knot_calc_u(nu);
- }
- }
- }
- nu = nu->next;
- }
-
- return ok;
+ Nurb *nu;
+ BPoint *bp, *bpn, *newbp;
+ int a, u, v, len;
+ bool ok = false;
+
+ nu = editnurb->nurbs.first;
+ while (nu) {
+
+ if (nu->pntsv == 1) {
+ bp = nu->bp;
+ a = nu->pntsu;
+ while (a) {
+ if (bp->f1 & flag) {
+ /* pass */
+ }
+ else {
+ break;
+ }
+ bp++;
+ a--;
+ }
+ if (a == 0) {
+ ok = true;
+ newbp = (BPoint *)MEM_mallocN(2 * nu->pntsu * sizeof(BPoint), "extrudeNurb1");
+ ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu);
+ bp = newbp + nu->pntsu;
+ ED_curve_bpcpy(editnurb, bp, nu->bp, nu->pntsu);
+ MEM_freeN(nu->bp);
+ nu->bp = newbp;
+ a = nu->pntsu;
+ while (a--) {
+ select_bpoint(bp, SELECT, flag, HIDDEN);
+ select_bpoint(newbp, DESELECT, flag, HIDDEN);
+ bp++;
+ newbp++;
+ }
+
+ nu->pntsv = 2;
+ nu->orderv = 2;
+ BKE_nurb_knot_calc_v(nu);
+ }
+ }
+ else {
+ /* which row or column is selected */
+
+ if (isNurbselUV(nu, flag, &u, &v)) {
+
+ /* deselect all */
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ select_bpoint(bp, DESELECT, flag, HIDDEN);
+ bp++;
+ }
+
+ if (u == 0 || u == nu->pntsv - 1) { /* row in u-direction selected */
+ ok = true;
+ newbp = (BPoint *)MEM_mallocN(nu->pntsu * (nu->pntsv + 1) * sizeof(BPoint),
+ "extrudeNurb1");
+ if (u == 0) {
+ len = nu->pntsv * nu->pntsu;
+ ED_curve_bpcpy(editnurb, newbp + nu->pntsu, nu->bp, len);
+ ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu);
+ bp = newbp;
+ }
+ else {
+ len = nu->pntsv * nu->pntsu;
+ ED_curve_bpcpy(editnurb, newbp, nu->bp, len);
+ ED_curve_bpcpy(editnurb, newbp + len, &nu->bp[len - nu->pntsu], nu->pntsu);
+ bp = newbp + len;
+ }
+
+ a = nu->pntsu;
+ while (a--) {
+ select_bpoint(bp, SELECT, flag, HIDDEN);
+ bp++;
+ }
+
+ MEM_freeN(nu->bp);
+ nu->bp = newbp;
+ nu->pntsv++;
+ BKE_nurb_knot_calc_v(nu);
+ }
+ else if (v == 0 || v == nu->pntsu - 1) { /* column in v-direction selected */
+ ok = true;
+ bpn = newbp = (BPoint *)MEM_mallocN((nu->pntsu + 1) * nu->pntsv * sizeof(BPoint),
+ "extrudeNurb1");
+ bp = nu->bp;
+
+ for (a = 0; a < nu->pntsv; a++) {
+ if (v == 0) {
+ *bpn = *bp;
+ bpn->f1 |= flag;
+ bpn++;
+ }
+ ED_curve_bpcpy(editnurb, bpn, bp, nu->pntsu);
+ bp += nu->pntsu;
+ bpn += nu->pntsu;
+ if (v == nu->pntsu - 1) {
+ *bpn = *(bp - 1);
+ bpn->f1 |= flag;
+ bpn++;
+ }
+ }
+
+ MEM_freeN(nu->bp);
+ nu->bp = newbp;
+ nu->pntsu++;
+ BKE_nurb_knot_calc_u(nu);
+ }
+ }
+ }
+ nu = nu->next;
+ }
+
+ return ok;
}
static bool calc_duplicate_actvert(
- const ListBase *editnurb, const ListBase *newnurb, Curve *cu,
- int start, int end, int vert)
-{
- if ((start <= cu->actvert) && (end > cu->actvert)) {
- cu->actvert = vert;
- cu->actnu = BLI_listbase_count(editnurb) + BLI_listbase_count(newnurb);
- return true;
- }
- return false;
-}
-
-static void adduplicateflagNurb(Object *obedit, View3D *v3d, ListBase *newnurb,
- const short flag, const bool split)
-{
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu, *newnu;
- BezTriple *bezt, *bezt1;
- BPoint *bp, *bp1, *bp2, *bp3;
- Curve *cu = (Curve *)obedit->data;
- int a, b, c, starta, enda, diffa, cyclicu, cyclicv, newu, newv, i;
- char *usel;
-
- for (i = 0, nu = editnurb->first; nu; i++, nu = nu->next) {
- cyclicu = cyclicv = 0;
- if (nu->type == CU_BEZIER) {
- for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
- enda = -1;
- starta = a;
- while ((bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag)) {
- if (!split) {
- select_beztriple(bezt, DESELECT, flag, HIDDEN);
- }
- enda = a;
- if (a >= nu->pntsu - 1) {
- break;
- }
- a++;
- bezt++;
- }
- if (enda >= starta) {
- newu = diffa = enda - starta + 1; /* set newu and diffa, may use both */
-
- if (starta == 0 && newu != nu->pntsu && (nu->flagu & CU_NURB_CYCLIC)) {
- cyclicu = newu;
- }
- else {
- if (enda == nu->pntsu - 1) {
- newu += cyclicu;
- }
- if (i == cu->actnu) {
- calc_duplicate_actvert(
- editnurb, newnurb, cu,
- starta, starta + diffa, cu->actvert - starta);
- }
-
- newnu = BKE_nurb_copy(nu, newu, 1);
- memcpy(newnu->bezt, &nu->bezt[starta], diffa * sizeof(BezTriple));
- if (newu != diffa) {
- memcpy(&newnu->bezt[diffa], nu->bezt, cyclicu * sizeof(BezTriple));
- if (i == cu->actnu) {
- calc_duplicate_actvert(
- editnurb, newnurb, cu,
- 0, cyclicu, newu - cyclicu + cu->actvert);
- }
- cyclicu = 0;
- }
-
- if (newu != nu->pntsu) {
- newnu->flagu &= ~CU_NURB_CYCLIC;
- }
-
- for (b = 0, bezt1 = newnu->bezt; b < newnu->pntsu; b++, bezt1++) {
- select_beztriple(bezt1, SELECT, flag, HIDDEN);
- }
-
- BLI_addtail(newnurb, newnu);
- }
- }
- }
-
- if (cyclicu != 0) {
- if (i == cu->actnu) {
- calc_duplicate_actvert(
- editnurb, newnurb, cu,
- 0, cyclicu, cu->actvert);
- }
-
- newnu = BKE_nurb_copy(nu, cyclicu, 1);
- memcpy(newnu->bezt, nu->bezt, cyclicu * sizeof(BezTriple));
- newnu->flagu &= ~CU_NURB_CYCLIC;
-
- for (b = 0, bezt1 = newnu->bezt; b < newnu->pntsu; b++, bezt1++) {
- select_beztriple(bezt1, SELECT, flag, HIDDEN);
- }
-
- BLI_addtail(newnurb, newnu);
- }
- }
- else if (nu->pntsv == 1) { /* because UV Nurb has a different method for dupli */
- for (a = 0, bp = nu->bp; a < nu->pntsu; a++, bp++) {
- enda = -1;
- starta = a;
- while (bp->f1 & flag) {
- if (!split) {
- select_bpoint(bp, DESELECT, flag, HIDDEN);
- }
- enda = a;
- if (a >= nu->pntsu - 1) {
- break;
- }
- a++;
- bp++;
- }
- if (enda >= starta) {
- newu = diffa = enda - starta + 1; /* set newu and diffa, may use both */
-
- if (starta == 0 && newu != nu->pntsu && (nu->flagu & CU_NURB_CYCLIC)) {
- cyclicu = newu;
- }
- else {
- if (enda == nu->pntsu - 1) {
- newu += cyclicu;
- }
- if (i == cu->actnu) {
- calc_duplicate_actvert(
- editnurb, newnurb, cu,
- starta, starta + diffa, cu->actvert - starta);
- }
-
- newnu = BKE_nurb_copy(nu, newu, 1);
- memcpy(newnu->bp, &nu->bp[starta], diffa * sizeof(BPoint));
- if (newu != diffa) {
- memcpy(&newnu->bp[diffa], nu->bp, cyclicu * sizeof(BPoint));
- if (i == cu->actnu) {
- calc_duplicate_actvert(
- editnurb, newnurb, cu,
- 0, cyclicu, newu - cyclicu + cu->actvert);
- }
- cyclicu = 0;
- }
-
- if (newu != nu->pntsu) {
- newnu->flagu &= ~CU_NURB_CYCLIC;
- }
-
- for (b = 0, bp1 = newnu->bp; b < newnu->pntsu; b++, bp1++) {
- select_bpoint(bp1, SELECT, flag, HIDDEN);
- }
-
- BLI_addtail(newnurb, newnu);
- }
- }
- }
-
- if (cyclicu != 0) {
- if (i == cu->actnu) {
- calc_duplicate_actvert(
- editnurb, newnurb, cu,
- 0, cyclicu, cu->actvert);
- }
-
- newnu = BKE_nurb_copy(nu, cyclicu, 1);
- memcpy(newnu->bp, nu->bp, cyclicu * sizeof(BPoint));
- newnu->flagu &= ~CU_NURB_CYCLIC;
-
- for (b = 0, bp1 = newnu->bp; b < newnu->pntsu; b++, bp1++) {
- select_bpoint(bp1, SELECT, flag, HIDDEN);
- }
-
- BLI_addtail(newnurb, newnu);
- }
- }
- else {
- if (ED_curve_nurb_select_check(v3d, nu)) {
- /* a rectangular area in nurb has to be selected and if splitting must be in U or V direction */
- usel = MEM_callocN(nu->pntsu, "adduplicateN3");
- bp = nu->bp;
- for (a = 0; a < nu->pntsv; a++) {
- for (b = 0; b < nu->pntsu; b++, bp++) {
- if (bp->f1 & flag) {
- usel[b]++;
- }
- }
- }
- newu = 0;
- newv = 0;
- for (a = 0; a < nu->pntsu; a++) {
- if (usel[a]) {
- if (newv == 0 || usel[a] == newv) {
- newv = usel[a];
- newu++;
- }
- else {
- newv = 0;
- break;
- }
- }
- }
- MEM_freeN(usel);
-
- if ((newu == 0 || newv == 0) ||
- (split && !isNurbselU(nu, &newv, SELECT) && !isNurbselV(nu, &newu, SELECT)))
- {
- if (G.debug & G_DEBUG) {
- printf("Can't duplicate Nurb\n");
- }
- }
- else {
- for (a = 0, bp1 = nu->bp; a < nu->pntsu * nu->pntsv; a++, bp1++) {
- newv = newu = 0;
-
- if ((bp1->f1 & flag) && !(bp1->f1 & SURF_SEEN)) {
- /* point selected, now loop over points in U and V directions */
- for (b = a % nu->pntsu, bp2 = bp1; b < nu->pntsu; b++, bp2++) {
- if (bp2->f1 & flag) {
- newu++;
- for (c = a / nu->pntsu, bp3 = bp2; c < nu->pntsv; c++, bp3 += nu->pntsu) {
- if (bp3->f1 & flag) {
- /* flag as seen so skipped on future iterations */
- bp3->f1 |= SURF_SEEN;
- if (newu == 1) {
- newv++;
- }
- }
- else {
- break;
- }
- }
- }
- else {
- break;
- }
- }
- }
-
- if ((newu + newv) > 2) {
- /* ignore single points */
- if (a == 0) {
- /* check if need to save cyclic selection and continue if so */
- if (newu == nu->pntsu && (nu->flagv & CU_NURB_CYCLIC)) {
- cyclicv = newv;
- }
- if (newv == nu->pntsv && (nu->flagu & CU_NURB_CYCLIC)) {
- cyclicu = newu;
- }
- if (cyclicu != 0 || cyclicv != 0) {
- continue;
- }
- }
-
- if (a + newu == nu->pntsu && cyclicu != 0) {
- /* cyclic in U direction */
- newnu = BKE_nurb_copy(nu, newu + cyclicu, newv);
- for (b = 0; b < newv; b++) {
- memcpy(&newnu->bp[b * newnu->pntsu], &nu->bp[b * nu->pntsu + a], newu * sizeof(BPoint));
- memcpy(&newnu->bp[b * newnu->pntsu + newu], &nu->bp[b * nu->pntsu], cyclicu * sizeof(BPoint));
- }
-
- if (cu->actnu == i) {
- for (b = 0, diffa = 0; b < newv; b++, diffa += nu->pntsu - newu) {
- starta = b * nu->pntsu + a;
- if (calc_duplicate_actvert(
- editnurb, newnurb, cu,
- cu->actvert, starta,
- cu->actvert % nu->pntsu + newu + b * newnu->pntsu))
- {
- /* actvert in cyclicu selection */
- break;
- }
- else if (calc_duplicate_actvert(
- editnurb, newnurb, cu,
- starta, starta + newu,
- cu->actvert - starta + b * newnu->pntsu))
- {
- /* actvert in 'current' iteration selection */
- break;
- }
- }
- }
- cyclicu = cyclicv = 0;
- }
- else if ((a / nu->pntsu) + newv == nu->pntsv && cyclicv != 0) {
- /* cyclic in V direction */
- newnu = BKE_nurb_copy(nu, newu, newv + cyclicv);
- memcpy(newnu->bp, &nu->bp[a], newu * newv * sizeof(BPoint));
- memcpy(&newnu->bp[newu * newv], nu->bp, newu * cyclicv * sizeof(BPoint));
-
- /* check for actvert in cylicv selection */
- if (cu->actnu == i) {
- calc_duplicate_actvert(
- editnurb, newnurb, cu,
- cu->actvert, a,
- (newu * newv) + cu->actvert);
- }
- cyclicu = cyclicv = 0;
- }
- else {
- newnu = BKE_nurb_copy(nu, newu, newv);
- for (b = 0; b < newv; b++) {
- memcpy(&newnu->bp[b * newu], &nu->bp[b * nu->pntsu + a], newu * sizeof(BPoint));
- }
- }
-
- /* general case if not handled by cyclicu or cyclicv */
- if (cu->actnu == i) {
- for (b = 0, diffa = 0; b < newv; b++, diffa += nu->pntsu - newu) {
- starta = b * nu->pntsu + a;
- if (calc_duplicate_actvert(
- editnurb, newnurb, cu,
- starta, starta + newu,
- cu->actvert - (a / nu->pntsu * nu->pntsu + diffa + (starta % nu->pntsu))))
- {
- break;
- }
- }
- }
- BLI_addtail(newnurb, newnu);
-
- if (newu != nu->pntsu) {
- newnu->flagu &= ~CU_NURB_CYCLIC;
- }
- if (newv != nu->pntsv) {
- newnu->flagv &= ~CU_NURB_CYCLIC;
- }
- }
- }
-
- if (cyclicu != 0 || cyclicv != 0) {
- /* copy start of a cyclic surface, or copying all selected points */
- newu = cyclicu == 0 ? nu->pntsu : cyclicu;
- newv = cyclicv == 0 ? nu->pntsv : cyclicv;
-
- newnu = BKE_nurb_copy(nu, newu, newv);
- for (b = 0; b < newv; b++) {
- memcpy(&newnu->bp[b * newu], &nu->bp[b * nu->pntsu], newu * sizeof(BPoint));
- }
-
- /* check for actvert in the unused cyclicuv selection */
- if (cu->actnu == i) {
- for (b = 0, diffa = 0; b < newv; b++, diffa += nu->pntsu - newu) {
- starta = b * nu->pntsu;
- if (calc_duplicate_actvert(
- editnurb, newnurb, cu,
- starta, starta + newu,
- cu->actvert - (diffa + (starta % nu->pntsu))))
- {
- break;
- }
- }
- }
- BLI_addtail(newnurb, newnu);
-
- if (newu != nu->pntsu) {
- newnu->flagu &= ~CU_NURB_CYCLIC;
- }
- if (newv != nu->pntsv) {
- newnu->flagv &= ~CU_NURB_CYCLIC;
- }
- }
-
- for (b = 0, bp1 = nu->bp; b < nu->pntsu * nu->pntsv; b++, bp1++) {
- bp1->f1 &= ~SURF_SEEN;
- if (!split) {
- select_bpoint(bp1, DESELECT, flag, HIDDEN);
- }
- }
- }
- }
- }
- }
-
- if (BLI_listbase_is_empty(newnurb) == false) {
- for (nu = newnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- if (split) {
- /* recalc first and last */
- BKE_nurb_handle_calc_simple(nu, &nu->bezt[0]);
- BKE_nurb_handle_calc_simple(nu, &nu->bezt[nu->pntsu - 1]);
- }
- }
- else {
- /* knots done after duplicate as pntsu may change */
- BKE_nurb_order_clamp_u(nu);
- BKE_nurb_knot_calc_u(nu);
-
- if (obedit->type == OB_SURF) {
- for (a = 0, bp = nu->bp; a < nu->pntsu * nu->pntsv; a++, bp++) {
- bp->f1 &= ~SURF_SEEN;
- }
-
- BKE_nurb_order_clamp_v(nu);
- BKE_nurb_knot_calc_v(nu);
- }
- }
- }
- }
+ const ListBase *editnurb, const ListBase *newnurb, Curve *cu, int start, int end, int vert)
+{
+ if ((start <= cu->actvert) && (end > cu->actvert)) {
+ cu->actvert = vert;
+ cu->actnu = BLI_listbase_count(editnurb) + BLI_listbase_count(newnurb);
+ return true;
+ }
+ return false;
+}
+
+static void adduplicateflagNurb(
+ Object *obedit, View3D *v3d, ListBase *newnurb, const short flag, const bool split)
+{
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu, *newnu;
+ BezTriple *bezt, *bezt1;
+ BPoint *bp, *bp1, *bp2, *bp3;
+ Curve *cu = (Curve *)obedit->data;
+ int a, b, c, starta, enda, diffa, cyclicu, cyclicv, newu, newv, i;
+ char *usel;
+
+ for (i = 0, nu = editnurb->first; nu; i++, nu = nu->next) {
+ cyclicu = cyclicv = 0;
+ if (nu->type == CU_BEZIER) {
+ for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
+ enda = -1;
+ starta = a;
+ while ((bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag)) {
+ if (!split) {
+ select_beztriple(bezt, DESELECT, flag, HIDDEN);
+ }
+ enda = a;
+ if (a >= nu->pntsu - 1) {
+ break;
+ }
+ a++;
+ bezt++;
+ }
+ if (enda >= starta) {
+ newu = diffa = enda - starta + 1; /* set newu and diffa, may use both */
+
+ if (starta == 0 && newu != nu->pntsu && (nu->flagu & CU_NURB_CYCLIC)) {
+ cyclicu = newu;
+ }
+ else {
+ if (enda == nu->pntsu - 1) {
+ newu += cyclicu;
+ }
+ if (i == cu->actnu) {
+ calc_duplicate_actvert(
+ editnurb, newnurb, cu, starta, starta + diffa, cu->actvert - starta);
+ }
+
+ newnu = BKE_nurb_copy(nu, newu, 1);
+ memcpy(newnu->bezt, &nu->bezt[starta], diffa * sizeof(BezTriple));
+ if (newu != diffa) {
+ memcpy(&newnu->bezt[diffa], nu->bezt, cyclicu * sizeof(BezTriple));
+ if (i == cu->actnu) {
+ calc_duplicate_actvert(
+ editnurb, newnurb, cu, 0, cyclicu, newu - cyclicu + cu->actvert);
+ }
+ cyclicu = 0;
+ }
+
+ if (newu != nu->pntsu) {
+ newnu->flagu &= ~CU_NURB_CYCLIC;
+ }
+
+ for (b = 0, bezt1 = newnu->bezt; b < newnu->pntsu; b++, bezt1++) {
+ select_beztriple(bezt1, SELECT, flag, HIDDEN);
+ }
+
+ BLI_addtail(newnurb, newnu);
+ }
+ }
+ }
+
+ if (cyclicu != 0) {
+ if (i == cu->actnu) {
+ calc_duplicate_actvert(editnurb, newnurb, cu, 0, cyclicu, cu->actvert);
+ }
+
+ newnu = BKE_nurb_copy(nu, cyclicu, 1);
+ memcpy(newnu->bezt, nu->bezt, cyclicu * sizeof(BezTriple));
+ newnu->flagu &= ~CU_NURB_CYCLIC;
+
+ for (b = 0, bezt1 = newnu->bezt; b < newnu->pntsu; b++, bezt1++) {
+ select_beztriple(bezt1, SELECT, flag, HIDDEN);
+ }
+
+ BLI_addtail(newnurb, newnu);
+ }
+ }
+ else if (nu->pntsv == 1) { /* because UV Nurb has a different method for dupli */
+ for (a = 0, bp = nu->bp; a < nu->pntsu; a++, bp++) {
+ enda = -1;
+ starta = a;
+ while (bp->f1 & flag) {
+ if (!split) {
+ select_bpoint(bp, DESELECT, flag, HIDDEN);
+ }
+ enda = a;
+ if (a >= nu->pntsu - 1) {
+ break;
+ }
+ a++;
+ bp++;
+ }
+ if (enda >= starta) {
+ newu = diffa = enda - starta + 1; /* set newu and diffa, may use both */
+
+ if (starta == 0 && newu != nu->pntsu && (nu->flagu & CU_NURB_CYCLIC)) {
+ cyclicu = newu;
+ }
+ else {
+ if (enda == nu->pntsu - 1) {
+ newu += cyclicu;
+ }
+ if (i == cu->actnu) {
+ calc_duplicate_actvert(
+ editnurb, newnurb, cu, starta, starta + diffa, cu->actvert - starta);
+ }
+
+ newnu = BKE_nurb_copy(nu, newu, 1);
+ memcpy(newnu->bp, &nu->bp[starta], diffa * sizeof(BPoint));
+ if (newu != diffa) {
+ memcpy(&newnu->bp[diffa], nu->bp, cyclicu * sizeof(BPoint));
+ if (i == cu->actnu) {
+ calc_duplicate_actvert(
+ editnurb, newnurb, cu, 0, cyclicu, newu - cyclicu + cu->actvert);
+ }
+ cyclicu = 0;
+ }
+
+ if (newu != nu->pntsu) {
+ newnu->flagu &= ~CU_NURB_CYCLIC;
+ }
+
+ for (b = 0, bp1 = newnu->bp; b < newnu->pntsu; b++, bp1++) {
+ select_bpoint(bp1, SELECT, flag, HIDDEN);
+ }
+
+ BLI_addtail(newnurb, newnu);
+ }
+ }
+ }
+
+ if (cyclicu != 0) {
+ if (i == cu->actnu) {
+ calc_duplicate_actvert(editnurb, newnurb, cu, 0, cyclicu, cu->actvert);
+ }
+
+ newnu = BKE_nurb_copy(nu, cyclicu, 1);
+ memcpy(newnu->bp, nu->bp, cyclicu * sizeof(BPoint));
+ newnu->flagu &= ~CU_NURB_CYCLIC;
+
+ for (b = 0, bp1 = newnu->bp; b < newnu->pntsu; b++, bp1++) {
+ select_bpoint(bp1, SELECT, flag, HIDDEN);
+ }
+
+ BLI_addtail(newnurb, newnu);
+ }
+ }
+ else {
+ if (ED_curve_nurb_select_check(v3d, nu)) {
+ /* a rectangular area in nurb has to be selected and if splitting must be in U or V direction */
+ usel = MEM_callocN(nu->pntsu, "adduplicateN3");
+ bp = nu->bp;
+ for (a = 0; a < nu->pntsv; a++) {
+ for (b = 0; b < nu->pntsu; b++, bp++) {
+ if (bp->f1 & flag) {
+ usel[b]++;
+ }
+ }
+ }
+ newu = 0;
+ newv = 0;
+ for (a = 0; a < nu->pntsu; a++) {
+ if (usel[a]) {
+ if (newv == 0 || usel[a] == newv) {
+ newv = usel[a];
+ newu++;
+ }
+ else {
+ newv = 0;
+ break;
+ }
+ }
+ }
+ MEM_freeN(usel);
+
+ if ((newu == 0 || newv == 0) ||
+ (split && !isNurbselU(nu, &newv, SELECT) && !isNurbselV(nu, &newu, SELECT))) {
+ if (G.debug & G_DEBUG) {
+ printf("Can't duplicate Nurb\n");
+ }
+ }
+ else {
+ for (a = 0, bp1 = nu->bp; a < nu->pntsu * nu->pntsv; a++, bp1++) {
+ newv = newu = 0;
+
+ if ((bp1->f1 & flag) && !(bp1->f1 & SURF_SEEN)) {
+ /* point selected, now loop over points in U and V directions */
+ for (b = a % nu->pntsu, bp2 = bp1; b < nu->pntsu; b++, bp2++) {
+ if (bp2->f1 & flag) {
+ newu++;
+ for (c = a / nu->pntsu, bp3 = bp2; c < nu->pntsv; c++, bp3 += nu->pntsu) {
+ if (bp3->f1 & flag) {
+ /* flag as seen so skipped on future iterations */
+ bp3->f1 |= SURF_SEEN;
+ if (newu == 1) {
+ newv++;
+ }
+ }
+ else {
+ break;
+ }
+ }
+ }
+ else {
+ break;
+ }
+ }
+ }
+
+ if ((newu + newv) > 2) {
+ /* ignore single points */
+ if (a == 0) {
+ /* check if need to save cyclic selection and continue if so */
+ if (newu == nu->pntsu && (nu->flagv & CU_NURB_CYCLIC)) {
+ cyclicv = newv;
+ }
+ if (newv == nu->pntsv && (nu->flagu & CU_NURB_CYCLIC)) {
+ cyclicu = newu;
+ }
+ if (cyclicu != 0 || cyclicv != 0) {
+ continue;
+ }
+ }
+
+ if (a + newu == nu->pntsu && cyclicu != 0) {
+ /* cyclic in U direction */
+ newnu = BKE_nurb_copy(nu, newu + cyclicu, newv);
+ for (b = 0; b < newv; b++) {
+ memcpy(&newnu->bp[b * newnu->pntsu],
+ &nu->bp[b * nu->pntsu + a],
+ newu * sizeof(BPoint));
+ memcpy(&newnu->bp[b * newnu->pntsu + newu],
+ &nu->bp[b * nu->pntsu],
+ cyclicu * sizeof(BPoint));
+ }
+
+ if (cu->actnu == i) {
+ for (b = 0, diffa = 0; b < newv; b++, diffa += nu->pntsu - newu) {
+ starta = b * nu->pntsu + a;
+ if (calc_duplicate_actvert(editnurb,
+ newnurb,
+ cu,
+ cu->actvert,
+ starta,
+ cu->actvert % nu->pntsu + newu +
+ b * newnu->pntsu)) {
+ /* actvert in cyclicu selection */
+ break;
+ }
+ else if (calc_duplicate_actvert(editnurb,
+ newnurb,
+ cu,
+ starta,
+ starta + newu,
+ cu->actvert - starta + b * newnu->pntsu)) {
+ /* actvert in 'current' iteration selection */
+ break;
+ }
+ }
+ }
+ cyclicu = cyclicv = 0;
+ }
+ else if ((a / nu->pntsu) + newv == nu->pntsv && cyclicv != 0) {
+ /* cyclic in V direction */
+ newnu = BKE_nurb_copy(nu, newu, newv + cyclicv);
+ memcpy(newnu->bp, &nu->bp[a], newu * newv * sizeof(BPoint));
+ memcpy(&newnu->bp[newu * newv], nu->bp, newu * cyclicv * sizeof(BPoint));
+
+ /* check for actvert in cylicv selection */
+ if (cu->actnu == i) {
+ calc_duplicate_actvert(
+ editnurb, newnurb, cu, cu->actvert, a, (newu * newv) + cu->actvert);
+ }
+ cyclicu = cyclicv = 0;
+ }
+ else {
+ newnu = BKE_nurb_copy(nu, newu, newv);
+ for (b = 0; b < newv; b++) {
+ memcpy(&newnu->bp[b * newu], &nu->bp[b * nu->pntsu + a], newu * sizeof(BPoint));
+ }
+ }
+
+ /* general case if not handled by cyclicu or cyclicv */
+ if (cu->actnu == i) {
+ for (b = 0, diffa = 0; b < newv; b++, diffa += nu->pntsu - newu) {
+ starta = b * nu->pntsu + a;
+ if (calc_duplicate_actvert(editnurb,
+ newnurb,
+ cu,
+ starta,
+ starta + newu,
+ cu->actvert - (a / nu->pntsu * nu->pntsu + diffa +
+ (starta % nu->pntsu)))) {
+ break;
+ }
+ }
+ }
+ BLI_addtail(newnurb, newnu);
+
+ if (newu != nu->pntsu) {
+ newnu->flagu &= ~CU_NURB_CYCLIC;
+ }
+ if (newv != nu->pntsv) {
+ newnu->flagv &= ~CU_NURB_CYCLIC;
+ }
+ }
+ }
+
+ if (cyclicu != 0 || cyclicv != 0) {
+ /* copy start of a cyclic surface, or copying all selected points */
+ newu = cyclicu == 0 ? nu->pntsu : cyclicu;
+ newv = cyclicv == 0 ? nu->pntsv : cyclicv;
+
+ newnu = BKE_nurb_copy(nu, newu, newv);
+ for (b = 0; b < newv; b++) {
+ memcpy(&newnu->bp[b * newu], &nu->bp[b * nu->pntsu], newu * sizeof(BPoint));
+ }
+
+ /* check for actvert in the unused cyclicuv selection */
+ if (cu->actnu == i) {
+ for (b = 0, diffa = 0; b < newv; b++, diffa += nu->pntsu - newu) {
+ starta = b * nu->pntsu;
+ if (calc_duplicate_actvert(editnurb,
+ newnurb,
+ cu,
+ starta,
+ starta + newu,
+ cu->actvert - (diffa + (starta % nu->pntsu)))) {
+ break;
+ }
+ }
+ }
+ BLI_addtail(newnurb, newnu);
+
+ if (newu != nu->pntsu) {
+ newnu->flagu &= ~CU_NURB_CYCLIC;
+ }
+ if (newv != nu->pntsv) {
+ newnu->flagv &= ~CU_NURB_CYCLIC;
+ }
+ }
+
+ for (b = 0, bp1 = nu->bp; b < nu->pntsu * nu->pntsv; b++, bp1++) {
+ bp1->f1 &= ~SURF_SEEN;
+ if (!split) {
+ select_bpoint(bp1, DESELECT, flag, HIDDEN);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (BLI_listbase_is_empty(newnurb) == false) {
+ for (nu = newnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ if (split) {
+ /* recalc first and last */
+ BKE_nurb_handle_calc_simple(nu, &nu->bezt[0]);
+ BKE_nurb_handle_calc_simple(nu, &nu->bezt[nu->pntsu - 1]);
+ }
+ }
+ else {
+ /* knots done after duplicate as pntsu may change */
+ BKE_nurb_order_clamp_u(nu);
+ BKE_nurb_knot_calc_u(nu);
+
+ if (obedit->type == OB_SURF) {
+ for (a = 0, bp = nu->bp; a < nu->pntsu * nu->pntsv; a++, bp++) {
+ bp->f1 &= ~SURF_SEEN;
+ }
+
+ BKE_nurb_order_clamp_v(nu);
+ BKE_nurb_knot_calc_v(nu);
+ }
+ }
+ }
+ }
}
/**************** switch direction operator ***************/
static int switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
-
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Curve *cu = obedit->data;
-
- if (!ED_curve_select_check(v3d, cu->editnurb)) {
- continue;
- }
-
- EditNurb *editnurb = cu->editnurb;
- Nurb *nu;
- int i;
-
- for (nu = editnurb->nurbs.first, i = 0; nu; nu = nu->next, i++) {
- if (ED_curve_nurb_select_check(v3d, nu)) {
- BKE_nurb_direction_switch(nu);
- keyData_switchDirectionNurb(cu, nu);
- if ((i == cu->actnu) && (cu->actvert != CU_ACT_NONE)) {
- cu->actvert = (nu->pntsu - 1) - cu->actvert;
- }
- }
- }
-
- if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
- }
-
- DEG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Curve *cu = obedit->data;
+
+ if (!ED_curve_select_check(v3d, cu->editnurb)) {
+ continue;
+ }
+
+ EditNurb *editnurb = cu->editnurb;
+ Nurb *nu;
+ int i;
+
+ for (nu = editnurb->nurbs.first, i = 0; nu; nu = nu->next, i++) {
+ if (ED_curve_nurb_select_check(v3d, nu)) {
+ BKE_nurb_direction_switch(nu);
+ keyData_switchDirectionNurb(cu, nu);
+ if ((i == cu->actnu) && (cu->actvert != CU_ACT_NONE)) {
+ cu->actvert = (nu->pntsu - 1) - cu->actvert;
+ }
+ }
+ }
+
+ if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ }
+
+ DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void CURVE_OT_switch_direction(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Switch Direction";
- ot->description = "Switch direction of selected splines";
- ot->idname = "CURVE_OT_switch_direction";
+ /* identifiers */
+ ot->name = "Switch Direction";
+ ot->description = "Switch direction of selected splines";
+ ot->idname = "CURVE_OT_switch_direction";
- /* api callbacks */
- ot->exec = switch_direction_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = switch_direction_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/****************** set weight operator *******************/
static int set_goal_weight_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- float weight = RNA_float_get(op->ptr, "weight");
- int a;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->bezt) {
- for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
- if (bezt->f2 & SELECT) {
- bezt->weight = weight;
- }
- }
- }
- else if (nu->bp) {
- for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
- if (bp->f1 & SELECT) {
- bp->weight = weight;
- }
- }
- }
- }
-
- DEG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ float weight = RNA_float_get(op->ptr, "weight");
+ int a;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
+ if (bezt->f2 & SELECT) {
+ bezt->weight = weight;
+ }
+ }
+ }
+ else if (nu->bp) {
+ for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
+ if (bp->f1 & SELECT) {
+ bp->weight = weight;
+ }
+ }
+ }
+ }
+
+ DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
}
void CURVE_OT_spline_weight_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Goal Weight";
- ot->description = "Set softbody goal weight for selected points";
- ot->idname = "CURVE_OT_spline_weight_set";
+ /* identifiers */
+ ot->name = "Set Goal Weight";
+ ot->description = "Set softbody goal weight for selected points";
+ ot->idname = "CURVE_OT_spline_weight_set";
- /* api callbacks */
- ot->exec = set_goal_weight_exec;
- ot->invoke = WM_operator_props_popup;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = set_goal_weight_exec;
+ ot->invoke = WM_operator_props_popup;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_float_factor(ot->srna, "weight", 1.0f, 0.0f, 1.0f, "Weight", "", 0.0f, 1.0f);
+ /* properties */
+ RNA_def_float_factor(ot->srna, "weight", 1.0f, 0.0f, 1.0f, "Weight", "", 0.0f, 1.0f);
}
/******************* set radius operator ******************/
static int set_radius_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- float radius = RNA_float_get(op->ptr, "radius");
- int a;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->bezt) {
- for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
- if (bezt->f2 & SELECT) {
- bezt->radius = radius;
- }
- }
- }
- else if (nu->bp) {
- for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
- if (bp->f1 & SELECT) {
- bp->radius = radius;
- }
- }
- }
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
-
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ float radius = RNA_float_get(op->ptr, "radius");
+ int a;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
+ if (bezt->f2 & SELECT) {
+ bezt->radius = radius;
+ }
+ }
+ }
+ else if (nu->bp) {
+ for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
+ if (bp->f1 & SELECT) {
+ bp->radius = radius;
+ }
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+
+ return OPERATOR_FINISHED;
}
void CURVE_OT_radius_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Curve Radius";
- ot->description = "Set per-point radius which is used for bevel tapering";
- ot->idname = "CURVE_OT_radius_set";
+ /* identifiers */
+ ot->name = "Set Curve Radius";
+ ot->description = "Set per-point radius which is used for bevel tapering";
+ ot->idname = "CURVE_OT_radius_set";
- /* api callbacks */
- ot->exec = set_radius_exec;
- ot->invoke = WM_operator_props_popup;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = set_radius_exec;
+ ot->invoke = WM_operator_props_popup;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_float(ot->srna, "radius", 1.0f, 0.0f, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.0001f, 10.0f);
+ /* properties */
+ RNA_def_float(
+ ot->srna, "radius", 1.0f, 0.0f, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.0001f, 10.0f);
}
/********************* smooth operator ********************/
-static void smooth_single_bezt(
- BezTriple *bezt,
- const BezTriple *bezt_orig_prev, const BezTriple *bezt_orig_next,
- float factor)
+static void smooth_single_bezt(BezTriple *bezt,
+ const BezTriple *bezt_orig_prev,
+ const BezTriple *bezt_orig_next,
+ float factor)
{
- int i;
+ int i;
- BLI_assert(IN_RANGE_INCL(factor, 0.0f, 1.0f));
+ BLI_assert(IN_RANGE_INCL(factor, 0.0f, 1.0f));
- for (i = 0; i < 3; i++) {
- float val_old, val_new, offset;
+ for (i = 0; i < 3; i++) {
+ float val_old, val_new, offset;
- /* get single dimension pos of the mid handle */
- val_old = bezt->vec[1][i];
+ /* get single dimension pos of the mid handle */
+ val_old = bezt->vec[1][i];
- /* get the weights of the previous/next mid handles and calc offset */
- val_new = (bezt_orig_prev->vec[1][i] * 0.5f) + (bezt_orig_next->vec[1][i] * 0.5f);
- offset = (val_old * (1.0f - factor)) + (val_new * factor) - val_old;
+ /* get the weights of the previous/next mid handles and calc offset */
+ val_new = (bezt_orig_prev->vec[1][i] * 0.5f) + (bezt_orig_next->vec[1][i] * 0.5f);
+ offset = (val_old * (1.0f - factor)) + (val_new * factor) - val_old;
- /* offset midpoint and 2 handles */
- bezt->vec[1][i] += offset;
- bezt->vec[0][i] += offset;
- bezt->vec[2][i] += offset;
- }
+ /* offset midpoint and 2 handles */
+ bezt->vec[1][i] += offset;
+ bezt->vec[0][i] += offset;
+ bezt->vec[2][i] += offset;
+ }
}
/**
* Same as #smooth_single_bezt(), keep in sync.
*/
-static void smooth_single_bp(
- BPoint *bp,
- const BPoint *bp_orig_prev, const BPoint *bp_orig_next,
- float factor)
+static void smooth_single_bp(BPoint *bp,
+ const BPoint *bp_orig_prev,
+ const BPoint *bp_orig_next,
+ float factor)
{
- int i;
+ int i;
- BLI_assert(IN_RANGE_INCL(factor, 0.0f, 1.0f));
+ BLI_assert(IN_RANGE_INCL(factor, 0.0f, 1.0f));
- for (i = 0; i < 3; i++) {
- float val_old, val_new, offset;
+ for (i = 0; i < 3; i++) {
+ float val_old, val_new, offset;
- val_old = bp->vec[i];
- val_new = (bp_orig_prev->vec[i] * 0.5f) + (bp_orig_next->vec[i] * 0.5f);
- offset = (val_old * (1.0f - factor)) + (val_new * factor) - val_old;
+ val_old = bp->vec[i];
+ val_new = (bp_orig_prev->vec[i] * 0.5f) + (bp_orig_next->vec[i] * 0.5f);
+ offset = (val_old * (1.0f - factor)) + (val_new * factor) - val_old;
- bp->vec[i] += offset;
- }
+ bp->vec[i] += offset;
+ }
}
static int smooth_exec(bContext *C, wmOperator *UNUSED(op))
{
- const float factor = 1.0f / 6.0f;
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
-
- int a, a_end;
- bool changed = false;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->bezt) {
- /* duplicate the curve to use in weight calculation */
- const BezTriple *bezt_orig = MEM_dupallocN(nu->bezt);
- BezTriple *bezt;
- changed = false;
-
- /* check whether its cyclic or not, and set initial & final conditions */
- if (nu->flagu & CU_NURB_CYCLIC) {
- a = 0;
- a_end = nu->pntsu;
- }
- else {
- a = 1;
- a_end = nu->pntsu - 1;
- }
-
- /* for all the curve points */
- for (; a < a_end; a++) {
- /* respect selection */
- bezt = &nu->bezt[a];
- if (bezt->f2 & SELECT) {
- const BezTriple *bezt_orig_prev, *bezt_orig_next;
-
- bezt_orig_prev = &bezt_orig[mod_i(a - 1, nu->pntsu)];
- bezt_orig_next = &bezt_orig[mod_i(a + 1, nu->pntsu)];
-
- smooth_single_bezt(bezt, bezt_orig_prev, bezt_orig_next, factor);
-
- changed = true;
- }
- }
- MEM_freeN((void *)bezt_orig);
- if (changed) {
- BKE_nurb_handles_calc(nu);
- }
- }
- else if (nu->bp) {
- /* Same as above, keep these the same! */
- const BPoint *bp_orig = MEM_dupallocN(nu->bp);
- BPoint *bp;
-
- if (nu->flagu & CU_NURB_CYCLIC) {
- a = 0;
- a_end = nu->pntsu;
- }
- else {
- a = 1;
- a_end = nu->pntsu - 1;
- }
-
- for (; a < a_end; a++) {
- bp = &nu->bp[a];
- if (bp->f1 & SELECT) {
- const BPoint *bp_orig_prev, *bp_orig_next;
-
- bp_orig_prev = &bp_orig[mod_i(a - 1, nu->pntsu)];
- bp_orig_next = &bp_orig[mod_i(a + 1, nu->pntsu)];
-
- smooth_single_bp(bp, bp_orig_prev, bp_orig_next, factor);
- }
- }
- MEM_freeN((void *)bp_orig);
- }
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
-
- return OPERATOR_FINISHED;
+ const float factor = 1.0f / 6.0f;
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+
+ int a, a_end;
+ bool changed = false;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ /* duplicate the curve to use in weight calculation */
+ const BezTriple *bezt_orig = MEM_dupallocN(nu->bezt);
+ BezTriple *bezt;
+ changed = false;
+
+ /* check whether its cyclic or not, and set initial & final conditions */
+ if (nu->flagu & CU_NURB_CYCLIC) {
+ a = 0;
+ a_end = nu->pntsu;
+ }
+ else {
+ a = 1;
+ a_end = nu->pntsu - 1;
+ }
+
+ /* for all the curve points */
+ for (; a < a_end; a++) {
+ /* respect selection */
+ bezt = &nu->bezt[a];
+ if (bezt->f2 & SELECT) {
+ const BezTriple *bezt_orig_prev, *bezt_orig_next;
+
+ bezt_orig_prev = &bezt_orig[mod_i(a - 1, nu->pntsu)];
+ bezt_orig_next = &bezt_orig[mod_i(a + 1, nu->pntsu)];
+
+ smooth_single_bezt(bezt, bezt_orig_prev, bezt_orig_next, factor);
+
+ changed = true;
+ }
+ }
+ MEM_freeN((void *)bezt_orig);
+ if (changed) {
+ BKE_nurb_handles_calc(nu);
+ }
+ }
+ else if (nu->bp) {
+ /* Same as above, keep these the same! */
+ const BPoint *bp_orig = MEM_dupallocN(nu->bp);
+ BPoint *bp;
+
+ if (nu->flagu & CU_NURB_CYCLIC) {
+ a = 0;
+ a_end = nu->pntsu;
+ }
+ else {
+ a = 1;
+ a_end = nu->pntsu - 1;
+ }
+
+ for (; a < a_end; a++) {
+ bp = &nu->bp[a];
+ if (bp->f1 & SELECT) {
+ const BPoint *bp_orig_prev, *bp_orig_next;
+
+ bp_orig_prev = &bp_orig[mod_i(a - 1, nu->pntsu)];
+ bp_orig_next = &bp_orig[mod_i(a + 1, nu->pntsu)];
+
+ smooth_single_bp(bp, bp_orig_prev, bp_orig_next, factor);
+ }
+ }
+ MEM_freeN((void *)bp_orig);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+
+ return OPERATOR_FINISHED;
}
void CURVE_OT_smooth(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Smooth";
- ot->description = "Flatten angles of selected points";
- ot->idname = "CURVE_OT_smooth";
+ /* identifiers */
+ ot->name = "Smooth";
+ ot->description = "Flatten angles of selected points";
+ ot->idname = "CURVE_OT_smooth";
- /* api callbacks */
- ot->exec = smooth_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = smooth_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* -------------------------------------------------------------------- */
@@ -2823,418 +2840,439 @@ void CURVE_OT_smooth(wmOperatorType *ot)
* TODO: support cyclic curves
*/
-static void curve_smooth_value(ListBase *editnurb,
- const int bezt_offsetof, const int bp_offset)
+static void curve_smooth_value(ListBase *editnurb, const int bezt_offsetof, const int bp_offset)
{
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
- /* use for smoothing */
- int last_sel;
- int start_sel, end_sel; /* selection indices, inclusive */
- float start_rad, end_rad, fac, range;
+ /* use for smoothing */
+ int last_sel;
+ int start_sel, end_sel; /* selection indices, inclusive */
+ float start_rad, end_rad, fac, range;
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->bezt) {
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->bezt) {
#define BEZT_VALUE(bezt) (*((float *)((char *)(bezt) + bezt_offsetof)))
- for (last_sel = 0; last_sel < nu->pntsu; last_sel++) {
- /* loop over selection segments of a curve, smooth each */
-
- /* Start BezTriple code,
- * this is duplicated below for points, make sure these functions stay in sync */
- start_sel = -1;
- for (bezt = &nu->bezt[last_sel], a = last_sel; a < nu->pntsu; a++, bezt++) {
- if (bezt->f2 & SELECT) {
- start_sel = a;
- break;
- }
- }
- /* in case there are no other selected verts */
- end_sel = start_sel;
- for (bezt = &nu->bezt[start_sel + 1], a = start_sel + 1; a < nu->pntsu; a++, bezt++) {
- if ((bezt->f2 & SELECT) == 0) {
- break;
- }
- end_sel = a;
- }
-
- if (start_sel == -1) {
- last_sel = nu->pntsu; /* next... */
- }
- else {
- last_sel = end_sel; /* before we modify it */
-
- /* now blend between start and end sel */
- start_rad = end_rad = FLT_MAX;
-
- if (start_sel == end_sel) {
- /* simple, only 1 point selected */
- if (start_sel > 0) { start_rad = BEZT_VALUE(&nu->bezt[start_sel - 1]); }
- if (end_sel != -1 && end_sel < nu->pntsu) { end_rad = BEZT_VALUE(&nu->bezt[start_sel + 1]); }
-
- if (start_rad != FLT_MAX && end_rad >= FLT_MAX) { BEZT_VALUE(&nu->bezt[start_sel]) = (start_rad + end_rad) / 2.0f; }
- else if (start_rad != FLT_MAX) { BEZT_VALUE(&nu->bezt[start_sel]) = start_rad; }
- else if (end_rad != FLT_MAX) { BEZT_VALUE(&nu->bezt[start_sel]) = end_rad; }
- }
- else {
- /* if endpoints selected, then use them */
- if (start_sel == 0) {
- start_rad = BEZT_VALUE(&nu->bezt[start_sel]);
- start_sel++; /* we don't want to edit the selected endpoint */
- }
- else {
- start_rad = BEZT_VALUE(&nu->bezt[start_sel - 1]);
- }
- if (end_sel == nu->pntsu - 1) {
- end_rad = BEZT_VALUE(&nu->bezt[end_sel]);
- end_sel--; /* we don't want to edit the selected endpoint */
- }
- else {
- end_rad = BEZT_VALUE(&nu->bezt[end_sel + 1]);
- }
-
- /* Now Blend between the points */
- range = (float)(end_sel - start_sel) + 2.0f;
- for (bezt = &nu->bezt[start_sel], a = start_sel; a <= end_sel; a++, bezt++) {
- fac = (float)(1 + a - start_sel) / range;
- BEZT_VALUE(bezt) = start_rad * (1.0f - fac) + end_rad * fac;
- }
- }
- }
- }
+ for (last_sel = 0; last_sel < nu->pntsu; last_sel++) {
+ /* loop over selection segments of a curve, smooth each */
+
+ /* Start BezTriple code,
+ * this is duplicated below for points, make sure these functions stay in sync */
+ start_sel = -1;
+ for (bezt = &nu->bezt[last_sel], a = last_sel; a < nu->pntsu; a++, bezt++) {
+ if (bezt->f2 & SELECT) {
+ start_sel = a;
+ break;
+ }
+ }
+ /* in case there are no other selected verts */
+ end_sel = start_sel;
+ for (bezt = &nu->bezt[start_sel + 1], a = start_sel + 1; a < nu->pntsu; a++, bezt++) {
+ if ((bezt->f2 & SELECT) == 0) {
+ break;
+ }
+ end_sel = a;
+ }
+
+ if (start_sel == -1) {
+ last_sel = nu->pntsu; /* next... */
+ }
+ else {
+ last_sel = end_sel; /* before we modify it */
+
+ /* now blend between start and end sel */
+ start_rad = end_rad = FLT_MAX;
+
+ if (start_sel == end_sel) {
+ /* simple, only 1 point selected */
+ if (start_sel > 0) {
+ start_rad = BEZT_VALUE(&nu->bezt[start_sel - 1]);
+ }
+ if (end_sel != -1 && end_sel < nu->pntsu) {
+ end_rad = BEZT_VALUE(&nu->bezt[start_sel + 1]);
+ }
+
+ if (start_rad != FLT_MAX && end_rad >= FLT_MAX) {
+ BEZT_VALUE(&nu->bezt[start_sel]) = (start_rad + end_rad) / 2.0f;
+ }
+ else if (start_rad != FLT_MAX) {
+ BEZT_VALUE(&nu->bezt[start_sel]) = start_rad;
+ }
+ else if (end_rad != FLT_MAX) {
+ BEZT_VALUE(&nu->bezt[start_sel]) = end_rad;
+ }
+ }
+ else {
+ /* if endpoints selected, then use them */
+ if (start_sel == 0) {
+ start_rad = BEZT_VALUE(&nu->bezt[start_sel]);
+ start_sel++; /* we don't want to edit the selected endpoint */
+ }
+ else {
+ start_rad = BEZT_VALUE(&nu->bezt[start_sel - 1]);
+ }
+ if (end_sel == nu->pntsu - 1) {
+ end_rad = BEZT_VALUE(&nu->bezt[end_sel]);
+ end_sel--; /* we don't want to edit the selected endpoint */
+ }
+ else {
+ end_rad = BEZT_VALUE(&nu->bezt[end_sel + 1]);
+ }
+
+ /* Now Blend between the points */
+ range = (float)(end_sel - start_sel) + 2.0f;
+ for (bezt = &nu->bezt[start_sel], a = start_sel; a <= end_sel; a++, bezt++) {
+ fac = (float)(1 + a - start_sel) / range;
+ BEZT_VALUE(bezt) = start_rad * (1.0f - fac) + end_rad * fac;
+ }
+ }
+ }
+ }
#undef BEZT_VALUE
- }
- else if (nu->bp) {
+ }
+ else if (nu->bp) {
#define BP_VALUE(bp) (*((float *)((char *)(bp) + bp_offset)))
- /* Same as above, keep these the same! */
- for (last_sel = 0; last_sel < nu->pntsu; last_sel++) {
- /* loop over selection segments of a curve, smooth each */
-
- /* Start BezTriple code,
- * this is duplicated below for points, make sure these functions stay in sync */
- start_sel = -1;
- for (bp = &nu->bp[last_sel], a = last_sel; a < nu->pntsu; a++, bp++) {
- if (bp->f1 & SELECT) {
- start_sel = a;
- break;
- }
- }
- /* in case there are no other selected verts */
- end_sel = start_sel;
- for (bp = &nu->bp[start_sel + 1], a = start_sel + 1; a < nu->pntsu; a++, bp++) {
- if ((bp->f1 & SELECT) == 0) {
- break;
- }
- end_sel = a;
- }
-
- if (start_sel == -1) {
- last_sel = nu->pntsu; /* next... */
- }
- else {
- last_sel = end_sel; /* before we modify it */
-
- /* now blend between start and end sel */
- start_rad = end_rad = FLT_MAX;
-
- if (start_sel == end_sel) {
- /* simple, only 1 point selected */
- if (start_sel > 0) { start_rad = BP_VALUE(&nu->bp[start_sel - 1]); }
- if (end_sel != -1 && end_sel < nu->pntsu) { end_rad = BP_VALUE(&nu->bp[start_sel + 1]); }
-
- if (start_rad != FLT_MAX && end_rad != FLT_MAX) { BP_VALUE(&nu->bp[start_sel]) = (start_rad + end_rad) / 2; }
- else if (start_rad != FLT_MAX) { BP_VALUE(&nu->bp[start_sel]) = start_rad; }
- else if (end_rad != FLT_MAX) { BP_VALUE(&nu->bp[start_sel]) = end_rad; }
- }
- else {
- /* if endpoints selected, then use them */
- if (start_sel == 0) {
- start_rad = BP_VALUE(&nu->bp[start_sel]);
- start_sel++; /* we don't want to edit the selected endpoint */
- }
- else {
- start_rad = BP_VALUE(&nu->bp[start_sel - 1]);
- }
- if (end_sel == nu->pntsu - 1) {
- end_rad = BP_VALUE(&nu->bp[end_sel]);
- end_sel--; /* we don't want to edit the selected endpoint */
- }
- else {
- end_rad = BP_VALUE(&nu->bp[end_sel + 1]);
- }
-
- /* Now Blend between the points */
- range = (float)(end_sel - start_sel) + 2.0f;
- for (bp = &nu->bp[start_sel], a = start_sel; a <= end_sel; a++, bp++) {
- fac = (float)(1 + a - start_sel) / range;
- BP_VALUE(bp) = start_rad * (1.0f - fac) + end_rad * fac;
- }
- }
- }
- }
+ /* Same as above, keep these the same! */
+ for (last_sel = 0; last_sel < nu->pntsu; last_sel++) {
+ /* loop over selection segments of a curve, smooth each */
+
+ /* Start BezTriple code,
+ * this is duplicated below for points, make sure these functions stay in sync */
+ start_sel = -1;
+ for (bp = &nu->bp[last_sel], a = last_sel; a < nu->pntsu; a++, bp++) {
+ if (bp->f1 & SELECT) {
+ start_sel = a;
+ break;
+ }
+ }
+ /* in case there are no other selected verts */
+ end_sel = start_sel;
+ for (bp = &nu->bp[start_sel + 1], a = start_sel + 1; a < nu->pntsu; a++, bp++) {
+ if ((bp->f1 & SELECT) == 0) {
+ break;
+ }
+ end_sel = a;
+ }
+
+ if (start_sel == -1) {
+ last_sel = nu->pntsu; /* next... */
+ }
+ else {
+ last_sel = end_sel; /* before we modify it */
+
+ /* now blend between start and end sel */
+ start_rad = end_rad = FLT_MAX;
+
+ if (start_sel == end_sel) {
+ /* simple, only 1 point selected */
+ if (start_sel > 0) {
+ start_rad = BP_VALUE(&nu->bp[start_sel - 1]);
+ }
+ if (end_sel != -1 && end_sel < nu->pntsu) {
+ end_rad = BP_VALUE(&nu->bp[start_sel + 1]);
+ }
+
+ if (start_rad != FLT_MAX && end_rad != FLT_MAX) {
+ BP_VALUE(&nu->bp[start_sel]) = (start_rad + end_rad) / 2;
+ }
+ else if (start_rad != FLT_MAX) {
+ BP_VALUE(&nu->bp[start_sel]) = start_rad;
+ }
+ else if (end_rad != FLT_MAX) {
+ BP_VALUE(&nu->bp[start_sel]) = end_rad;
+ }
+ }
+ else {
+ /* if endpoints selected, then use them */
+ if (start_sel == 0) {
+ start_rad = BP_VALUE(&nu->bp[start_sel]);
+ start_sel++; /* we don't want to edit the selected endpoint */
+ }
+ else {
+ start_rad = BP_VALUE(&nu->bp[start_sel - 1]);
+ }
+ if (end_sel == nu->pntsu - 1) {
+ end_rad = BP_VALUE(&nu->bp[end_sel]);
+ end_sel--; /* we don't want to edit the selected endpoint */
+ }
+ else {
+ end_rad = BP_VALUE(&nu->bp[end_sel + 1]);
+ }
+
+ /* Now Blend between the points */
+ range = (float)(end_sel - start_sel) + 2.0f;
+ for (bp = &nu->bp[start_sel], a = start_sel; a <= end_sel; a++, bp++) {
+ fac = (float)(1 + a - start_sel) / range;
+ BP_VALUE(bp) = start_rad * (1.0f - fac) + end_rad * fac;
+ }
+ }
+ }
+ }
#undef BP_VALUE
- }
- }
+ }
+ }
}
static int curve_smooth_weight_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
- curve_smooth_value(editnurb, offsetof(BezTriple, weight), offsetof(BPoint, weight));
+ curve_smooth_value(editnurb, offsetof(BezTriple, weight), offsetof(BPoint, weight));
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CURVE_OT_smooth_weight(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Smooth Curve Weight";
- ot->description = "Interpolate weight of selected points";
- ot->idname = "CURVE_OT_smooth_weight";
+ /* identifiers */
+ ot->name = "Smooth Curve Weight";
+ ot->description = "Interpolate weight of selected points";
+ ot->idname = "CURVE_OT_smooth_weight";
- /* api clastbacks */
- ot->exec = curve_smooth_weight_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api clastbacks */
+ ot->exec = curve_smooth_weight_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int curve_smooth_radius_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
- curve_smooth_value(editnurb, offsetof(BezTriple, radius), offsetof(BPoint, radius));
+ curve_smooth_value(editnurb, offsetof(BezTriple, radius), offsetof(BPoint, radius));
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CURVE_OT_smooth_radius(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Smooth Curve Radius";
- ot->description = "Interpolate radii of selected points";
- ot->idname = "CURVE_OT_smooth_radius";
+ /* identifiers */
+ ot->name = "Smooth Curve Radius";
+ ot->description = "Interpolate radii of selected points";
+ ot->idname = "CURVE_OT_smooth_radius";
- /* api clastbacks */
- ot->exec = curve_smooth_radius_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api clastbacks */
+ ot->exec = curve_smooth_radius_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int curve_smooth_tilt_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
- curve_smooth_value(editnurb, offsetof(BezTriple, tilt), offsetof(BPoint, tilt));
+ curve_smooth_value(editnurb, offsetof(BezTriple, tilt), offsetof(BPoint, tilt));
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CURVE_OT_smooth_tilt(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Smooth Curve Tilt";
- ot->description = "Interpolate tilt of selected points";
- ot->idname = "CURVE_OT_smooth_tilt";
+ /* identifiers */
+ ot->name = "Smooth Curve Tilt";
+ ot->description = "Interpolate tilt of selected points";
+ ot->idname = "CURVE_OT_smooth_tilt";
- /* api clastbacks */
- ot->exec = curve_smooth_tilt_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api clastbacks */
+ ot->exec = curve_smooth_tilt_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** hide operator *********************/
static int hide_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
-
- const bool invert = RNA_boolean_get(op->ptr, "unselected");
-
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Curve *cu = obedit->data;
-
- if (!(invert || ED_curve_select_check(v3d, cu->editnurb))) {
- continue;
- }
-
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- int a, sel;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- sel = 0;
- while (a--) {
- if (invert == 0 && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
- select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
- bezt->hide = 1;
- }
- else if (invert && !BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
- select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
- bezt->hide = 1;
- }
- if (bezt->hide) {
- sel++;
- }
- bezt++;
- }
- if (sel == nu->pntsu) {
- nu->hide = 1;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- sel = 0;
- while (a--) {
- if (invert == 0 && (bp->f1 & SELECT)) {
- select_bpoint(bp, DESELECT, SELECT, HIDDEN);
- bp->hide = 1;
- }
- else if (invert && (bp->f1 & SELECT) == 0) {
- select_bpoint(bp, DESELECT, SELECT, HIDDEN);
- bp->hide = 1;
- }
- if (bp->hide) {
- sel++;
- }
- bp++;
- }
- if (sel == nu->pntsu * nu->pntsv) {
- nu->hide = 1;
- }
- }
- }
-
- DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- BKE_curve_nurb_vert_active_validate(obedit->data);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ const bool invert = RNA_boolean_get(op->ptr, "unselected");
+
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Curve *cu = obedit->data;
+
+ if (!(invert || ED_curve_select_check(v3d, cu->editnurb))) {
+ continue;
+ }
+
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a, sel;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ sel = 0;
+ while (a--) {
+ if (invert == 0 && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
+ select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
+ bezt->hide = 1;
+ }
+ else if (invert && !BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
+ select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
+ bezt->hide = 1;
+ }
+ if (bezt->hide) {
+ sel++;
+ }
+ bezt++;
+ }
+ if (sel == nu->pntsu) {
+ nu->hide = 1;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ sel = 0;
+ while (a--) {
+ if (invert == 0 && (bp->f1 & SELECT)) {
+ select_bpoint(bp, DESELECT, SELECT, HIDDEN);
+ bp->hide = 1;
+ }
+ else if (invert && (bp->f1 & SELECT) == 0) {
+ select_bpoint(bp, DESELECT, SELECT, HIDDEN);
+ bp->hide = 1;
+ }
+ if (bp->hide) {
+ sel++;
+ }
+ bp++;
+ }
+ if (sel == nu->pntsu * nu->pntsv) {
+ nu->hide = 1;
+ }
+ }
+ }
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ BKE_curve_nurb_vert_active_validate(obedit->data);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void CURVE_OT_hide(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Selected";
- ot->idname = "CURVE_OT_hide";
- ot->description = "Hide (un)selected control points";
+ /* identifiers */
+ ot->name = "Hide Selected";
+ ot->idname = "CURVE_OT_hide";
+ ot->description = "Hide (un)selected control points";
- /* api callbacks */
- ot->exec = hide_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = hide_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
}
/********************** reveal operator *********************/
static int reveal_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const bool select = RNA_boolean_get(op->ptr, "select");
- bool changed_multi = false;
-
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- int a;
- bool changed = false;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- nu->hide = 0;
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (bezt->hide) {
- select_beztriple(bezt, select, SELECT, HIDDEN);
- bezt->hide = 0;
- changed = true;
- }
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (bp->hide) {
- select_bpoint(bp, select, SELECT, HIDDEN);
- bp->hide = 0;
- changed = true;
- }
- bp++;
- }
- }
- }
-
- if (changed) {
- 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);
- changed_multi = true;
- }
- }
- MEM_freeN(objects);
- return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool select = RNA_boolean_get(op->ptr, "select");
+ bool changed_multi = false;
+
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a;
+ bool changed = false;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ nu->hide = 0;
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ if (bezt->hide) {
+ select_beztriple(bezt, select, SELECT, HIDDEN);
+ bezt->hide = 0;
+ changed = true;
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ if (bp->hide) {
+ select_bpoint(bp, select, SELECT, HIDDEN);
+ bp->hide = 0;
+ changed = true;
+ }
+ bp++;
+ }
+ }
+ }
+
+ if (changed) {
+ 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);
+ changed_multi = true;
+ }
+ }
+ MEM_freeN(objects);
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void CURVE_OT_reveal(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reveal Hidden";
- ot->idname = "CURVE_OT_reveal";
- ot->description = "Reveal hidden control points";
+ /* identifiers */
+ ot->name = "Reveal Hidden";
+ ot->idname = "CURVE_OT_reveal";
+ ot->description = "Reveal hidden control points";
- /* api callbacks */
- ot->exec = reveal_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = reveal_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "select", true, "Select", "");
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
/********************** subdivide operator *********************/
@@ -3245,779 +3283,814 @@ void CURVE_OT_reveal(wmOperatorType *ot)
*/
static void subdividenurb(Object *obedit, View3D *v3d, int number_cuts)
{
- Curve *cu = obedit->data;
- EditNurb *editnurb = cu->editnurb;
- Nurb *nu;
- BezTriple *bezt, *beztnew, *beztn;
- BPoint *bp, *prevbp, *bpnew, *bpn;
- float vec[15];
- int a, b, sel, amount, *usel, *vsel, i;
- float factor;
-
- // printf("*** subdivideNurb: entering subdivide\n");
-
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
- amount = 0;
- if (nu->type == CU_BEZIER) {
- BezTriple *nextbezt;
-
- /*
- * Insert a point into a 2D Bezier curve.
- * Endpoints are preserved. Otherwise, all selected and inserted points are
- * newly created. Old points are discarded.
- */
- /* count */
- a = nu->pntsu;
- bezt = nu->bezt;
- while (a--) {
- nextbezt = BKE_nurb_bezt_get_next(nu, bezt);
- if (nextbezt == NULL) {
- break;
- }
-
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt) && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nextbezt)) {
- amount += number_cuts;
- }
- bezt++;
- }
-
- if (amount) {
- /* insert */
- beztnew = (BezTriple *)MEM_mallocN((amount + nu->pntsu) * sizeof(BezTriple), "subdivNurb");
- beztn = beztnew;
- a = nu->pntsu;
- bezt = nu->bezt;
- while (a--) {
- memcpy(beztn, bezt, sizeof(BezTriple));
- keyIndex_updateBezt(editnurb, bezt, beztn, 1);
- beztn++;
-
- nextbezt = BKE_nurb_bezt_get_next(nu, bezt);
- if (nextbezt == NULL) {
- break;
- }
-
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt) && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nextbezt)) {
- float prevvec[3][3];
-
- memcpy(prevvec, bezt->vec, sizeof(float) * 9);
-
- for (i = 0; i < number_cuts; i++) {
- factor = 1.0f / (number_cuts + 1 - i);
-
- memcpy(beztn, nextbezt, sizeof(BezTriple));
-
- /* midpoint subdividing */
- interp_v3_v3v3(vec, prevvec[1], prevvec[2], factor);
- interp_v3_v3v3(vec + 3, prevvec[2], nextbezt->vec[0], factor);
- interp_v3_v3v3(vec + 6, nextbezt->vec[0], nextbezt->vec[1], factor);
-
- interp_v3_v3v3(vec + 9, vec, vec + 3, factor);
- interp_v3_v3v3(vec + 12, vec + 3, vec + 6, factor);
-
- /* change handle of prev beztn */
- copy_v3_v3((beztn - 1)->vec[2], vec);
- /* new point */
- copy_v3_v3(beztn->vec[0], vec + 9);
- interp_v3_v3v3(beztn->vec[1], vec + 9, vec + 12, factor);
- copy_v3_v3(beztn->vec[2], vec + 12);
- /* handle of next bezt */
- if (a == 0 && i == number_cuts - 1 && (nu->flagu & CU_NURB_CYCLIC)) { copy_v3_v3(beztnew->vec[0], vec + 6); }
- else { copy_v3_v3(nextbezt->vec[0], vec + 6); }
-
- beztn->radius = (bezt->radius + nextbezt->radius) / 2;
- beztn->weight = (bezt->weight + nextbezt->weight) / 2;
-
- memcpy(prevvec, beztn->vec, sizeof(float) * 9);
- beztn++;
- }
- }
-
- bezt++;
- }
-
- MEM_freeN(nu->bezt);
- nu->bezt = beztnew;
- nu->pntsu += amount;
-
- BKE_nurb_handles_calc(nu);
- }
- } /* End of 'if (nu->type == CU_BEZIER)' */
- else if (nu->pntsv == 1) {
- BPoint *nextbp;
-
- /*
- * All flat lines (ie. co-planar), except flat Nurbs. Flat NURB curves
- * are handled together with the regular NURB plane division, as it
- * should be. I split it off just now, let's see if it is
- * stable... nzc 30-5-'00
- */
- /* count */
- a = nu->pntsu;
- bp = nu->bp;
- while (a--) {
- nextbp = BKE_nurb_bpoint_get_next(nu, bp);
- if (nextbp == NULL) {
- break;
- }
-
- if ((bp->f1 & SELECT) && (nextbp->f1 & SELECT)) {
- amount += number_cuts;
- }
- bp++;
- }
-
- if (amount) {
- /* insert */
- bpnew = (BPoint *)MEM_mallocN((amount + nu->pntsu) * sizeof(BPoint), "subdivNurb2");
- bpn = bpnew;
-
- a = nu->pntsu;
- bp = nu->bp;
-
- while (a--) {
- /* Copy "old" point. */
- memcpy(bpn, bp, sizeof(BPoint));
- keyIndex_updateBP(editnurb, bp, bpn, 1);
- bpn++;
-
- nextbp = BKE_nurb_bpoint_get_next(nu, bp);
- if (nextbp == NULL) {
- break;
- }
-
- if ((bp->f1 & SELECT) && (nextbp->f1 & SELECT)) {
- // printf("*** subdivideNurb: insert 'linear' point\n");
- for (i = 0; i < number_cuts; i++) {
- factor = (float)(i + 1) / (number_cuts + 1);
-
- memcpy(bpn, nextbp, sizeof(BPoint));
- interp_v4_v4v4(bpn->vec, bp->vec, nextbp->vec, factor);
- bpn++;
- }
-
- }
- bp++;
- }
-
- MEM_freeN(nu->bp);
- nu->bp = bpnew;
- nu->pntsu += amount;
-
- if (nu->type & CU_NURBS) {
- BKE_nurb_knot_calc_u(nu);
- }
- }
- } /* End of 'else if (nu->pntsv == 1)' */
- else if (nu->type == CU_NURBS) {
- /* This is a very strange test ... */
- /**
- * Subdivide NURB surfaces - nzc 30-5-'00 -
- *
- * Subdivision of a NURB curve can be effected by adding a
- * control point (insertion of a knot), or by raising the
- * degree of the functions used to build the NURB. The
- * expression
- *
- * degree = #knots - #controlpoints + 1 (J Walter piece)
- * degree = #knots - #controlpoints (Blender
- * implementation)
- * ( this is confusing.... what is true? Another concern
- * is that the JW piece allows the curve to become
- * explicitly 1st order derivative discontinuous, while
- * this is not what we want here... )
- *
- * is an invariant for a single NURB curve. Raising the degree
- * of the NURB is done elsewhere; the degree is assumed
- * constant during this operation. Degree is a property shared
- * by all controlpoints in a curve (even though it is stored
- * per control point - this can be misleading).
- * Adding a knot is done by searching for the place in the
- * knot vector where a certain knot value must be inserted, or
- * by picking an appropriate knot value between two existing
- * ones. The number of controlpoints that is influenced by the
- * insertion depends on the order of the curve. A certain
- * minimum number of knots is needed to form high-order
- * curves, as can be seen from the equation above. In Blender,
- * currently NURBs may be up to 6th order, so we modify at
- * most 6 points. One point is added. For an n-degree curve,
- * n points are discarded, and n+1 points inserted
- * (so effectively, n points are modified). (that holds for
- * the JW piece, but it seems not for our NURBs)
- * In practice, the knot spacing is copied, but the tail
- * (the points following the insertion point) need to be
- * offset to keep the knot series ascending. The knot series
- * is always a series of monotonically ascending integers in
- * Blender. When not enough control points are available to
- * fit the order, duplicates of the endpoints are added as
- * needed.
- */
- /* selection-arrays */
- usel = MEM_callocN(sizeof(int) * nu->pntsu, "subivideNurb3");
- vsel = MEM_callocN(sizeof(int) * nu->pntsv, "subivideNurb3");
- sel = 0;
-
- /* Count the number of selected points. */
- bp = nu->bp;
- for (a = 0; a < nu->pntsv; a++) {
- for (b = 0; b < nu->pntsu; b++) {
- if (bp->f1 & SELECT) {
- usel[b]++;
- vsel[a]++;
- sel++;
- }
- bp++;
- }
- }
- if (sel == (nu->pntsu * nu->pntsv)) { /* subdivide entire nurb */
- /* Global subdivision is a special case of partial
- * subdivision. Strange it is considered separately... */
-
- /* count of nodes (after subdivision) along U axis */
- int countu = nu->pntsu + (nu->pntsu - 1) * number_cuts;
-
- /* total count of nodes after subdivision */
- int tot = ((number_cuts + 1) * nu->pntsu - number_cuts) * ((number_cuts + 1) * nu->pntsv - number_cuts);
-
- bpn = bpnew = MEM_mallocN(tot * sizeof(BPoint), "subdivideNurb4");
- bp = nu->bp;
- /* first subdivide rows */
- for (a = 0; a < nu->pntsv; a++) {
- for (b = 0; b < nu->pntsu; b++) {
- *bpn = *bp;
- keyIndex_updateBP(editnurb, bp, bpn, 1);
- bpn++;
- bp++;
- if (b < nu->pntsu - 1) {
- prevbp = bp - 1;
- for (i = 0; i < number_cuts; i++) {
- factor = (float)(i + 1) / (number_cuts + 1);
- *bpn = *bp;
- interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor);
- bpn++;
- }
- }
- }
- bpn += number_cuts * countu;
- }
- /* now insert new */
- bpn = bpnew + ((number_cuts + 1) * nu->pntsu - number_cuts);
- bp = bpnew + (number_cuts + 1) * ((number_cuts + 1) * nu->pntsu - number_cuts);
- prevbp = bpnew;
- for (a = 1; a < nu->pntsv; a++) {
-
- for (b = 0; b < (number_cuts + 1) * nu->pntsu - number_cuts; b++) {
- BPoint *tmp = bpn;
- for (i = 0; i < number_cuts; i++) {
- factor = (float)(i + 1) / (number_cuts + 1);
- *tmp = *bp;
- interp_v4_v4v4(tmp->vec, prevbp->vec, bp->vec, factor);
- tmp += countu;
- }
- bp++;
- prevbp++;
- bpn++;
- }
- bp += number_cuts * countu;
- bpn += number_cuts * countu;
- prevbp += number_cuts * countu;
- }
- MEM_freeN(nu->bp);
- nu->bp = bpnew;
- nu->pntsu = (number_cuts + 1) * nu->pntsu - number_cuts;
- nu->pntsv = (number_cuts + 1) * nu->pntsv - number_cuts;
- BKE_nurb_knot_calc_u(nu);
- BKE_nurb_knot_calc_v(nu);
- } /* End of 'if (sel == nu->pntsu * nu->pntsv)' (subdivide entire NURB) */
- else {
- /* subdivide in v direction? */
- sel = 0;
- for (a = 0; a < nu->pntsv - 1; a++) {
- if (vsel[a] == nu->pntsu && vsel[a + 1] == nu->pntsu) {
- sel += number_cuts;
- }
- }
-
- if (sel) { /* V ! */
- bpn = bpnew = MEM_mallocN((sel + nu->pntsv) * nu->pntsu * sizeof(BPoint), "subdivideNurb4");
- bp = nu->bp;
- for (a = 0; a < nu->pntsv; a++) {
- for (b = 0; b < nu->pntsu; b++) {
- *bpn = *bp;
- keyIndex_updateBP(editnurb, bp, bpn, 1);
- bpn++;
- bp++;
- }
- if ( (a < nu->pntsv - 1) && vsel[a] == nu->pntsu && vsel[a + 1] == nu->pntsu) {
- for (i = 0; i < number_cuts; i++) {
- factor = (float)(i + 1) / (number_cuts + 1);
- prevbp = bp - nu->pntsu;
- for (b = 0; b < nu->pntsu; b++) {
- /*
- * This simple bisection must be replaces by a
- * subtle resampling of a number of points. Our
- * task is made slightly easier because each
- * point in our curve is a separate data
- * node. (is it?)
- */
- *bpn = *prevbp;
- interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor);
- bpn++;
-
- prevbp++;
- bp++;
- }
- bp -= nu->pntsu;
- }
- }
- }
- MEM_freeN(nu->bp);
- nu->bp = bpnew;
- nu->pntsv += sel;
- BKE_nurb_knot_calc_v(nu);
- }
- else {
- /* or in u direction? */
- sel = 0;
- for (a = 0; a < nu->pntsu - 1; a++) {
- if (usel[a] == nu->pntsv && usel[a + 1] == nu->pntsv) {
- sel += number_cuts;
- }
- }
-
- if (sel) { /* U ! */
- /* Inserting U points is sort of 'default' Flat curves only get */
- /* U points inserted in them. */
- bpn = bpnew = MEM_mallocN((sel + nu->pntsu) * nu->pntsv * sizeof(BPoint), "subdivideNurb4");
- bp = nu->bp;
- for (a = 0; a < nu->pntsv; a++) {
- for (b = 0; b < nu->pntsu; b++) {
- *bpn = *bp;
- keyIndex_updateBP(editnurb, bp, bpn, 1);
- bpn++;
- bp++;
- if ( (b < nu->pntsu - 1) && usel[b] == nu->pntsv && usel[b + 1] == nu->pntsv) {
- /*
- * One thing that bugs me here is that the
- * orders of things are not the same as in
- * the JW piece. Also, this implies that we
- * handle at most 3rd order curves? I miss
- * some symmetry here...
- */
- for (i = 0; i < number_cuts; i++) {
- factor = (float)(i + 1) / (number_cuts + 1);
- prevbp = bp - 1;
- *bpn = *prevbp;
- interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor);
- bpn++;
- }
- }
- }
- }
- MEM_freeN(nu->bp);
- nu->bp = bpnew;
- nu->pntsu += sel;
- BKE_nurb_knot_calc_u(nu); /* shift knots forward */
- }
- }
- }
- MEM_freeN(usel);
- MEM_freeN(vsel);
-
- } /* End of 'if (nu->type == CU_NURBS)' */
- }
+ Curve *cu = obedit->data;
+ EditNurb *editnurb = cu->editnurb;
+ Nurb *nu;
+ BezTriple *bezt, *beztnew, *beztn;
+ BPoint *bp, *prevbp, *bpnew, *bpn;
+ float vec[15];
+ int a, b, sel, amount, *usel, *vsel, i;
+ float factor;
+
+ // printf("*** subdivideNurb: entering subdivide\n");
+
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ amount = 0;
+ if (nu->type == CU_BEZIER) {
+ BezTriple *nextbezt;
+
+ /*
+ * Insert a point into a 2D Bezier curve.
+ * Endpoints are preserved. Otherwise, all selected and inserted points are
+ * newly created. Old points are discarded.
+ */
+ /* count */
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ while (a--) {
+ nextbezt = BKE_nurb_bezt_get_next(nu, bezt);
+ if (nextbezt == NULL) {
+ break;
+ }
+
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt) &&
+ BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nextbezt)) {
+ amount += number_cuts;
+ }
+ bezt++;
+ }
+
+ if (amount) {
+ /* insert */
+ beztnew = (BezTriple *)MEM_mallocN((amount + nu->pntsu) * sizeof(BezTriple), "subdivNurb");
+ beztn = beztnew;
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ while (a--) {
+ memcpy(beztn, bezt, sizeof(BezTriple));
+ keyIndex_updateBezt(editnurb, bezt, beztn, 1);
+ beztn++;
+
+ nextbezt = BKE_nurb_bezt_get_next(nu, bezt);
+ if (nextbezt == NULL) {
+ break;
+ }
+
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt) &&
+ BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nextbezt)) {
+ float prevvec[3][3];
+
+ memcpy(prevvec, bezt->vec, sizeof(float) * 9);
+
+ for (i = 0; i < number_cuts; i++) {
+ factor = 1.0f / (number_cuts + 1 - i);
+
+ memcpy(beztn, nextbezt, sizeof(BezTriple));
+
+ /* midpoint subdividing */
+ interp_v3_v3v3(vec, prevvec[1], prevvec[2], factor);
+ interp_v3_v3v3(vec + 3, prevvec[2], nextbezt->vec[0], factor);
+ interp_v3_v3v3(vec + 6, nextbezt->vec[0], nextbezt->vec[1], factor);
+
+ interp_v3_v3v3(vec + 9, vec, vec + 3, factor);
+ interp_v3_v3v3(vec + 12, vec + 3, vec + 6, factor);
+
+ /* change handle of prev beztn */
+ copy_v3_v3((beztn - 1)->vec[2], vec);
+ /* new point */
+ copy_v3_v3(beztn->vec[0], vec + 9);
+ interp_v3_v3v3(beztn->vec[1], vec + 9, vec + 12, factor);
+ copy_v3_v3(beztn->vec[2], vec + 12);
+ /* handle of next bezt */
+ if (a == 0 && i == number_cuts - 1 && (nu->flagu & CU_NURB_CYCLIC)) {
+ copy_v3_v3(beztnew->vec[0], vec + 6);
+ }
+ else {
+ copy_v3_v3(nextbezt->vec[0], vec + 6);
+ }
+
+ beztn->radius = (bezt->radius + nextbezt->radius) / 2;
+ beztn->weight = (bezt->weight + nextbezt->weight) / 2;
+
+ memcpy(prevvec, beztn->vec, sizeof(float) * 9);
+ beztn++;
+ }
+ }
+
+ bezt++;
+ }
+
+ MEM_freeN(nu->bezt);
+ nu->bezt = beztnew;
+ nu->pntsu += amount;
+
+ BKE_nurb_handles_calc(nu);
+ }
+ } /* End of 'if (nu->type == CU_BEZIER)' */
+ else if (nu->pntsv == 1) {
+ BPoint *nextbp;
+
+ /*
+ * All flat lines (ie. co-planar), except flat Nurbs. Flat NURB curves
+ * are handled together with the regular NURB plane division, as it
+ * should be. I split it off just now, let's see if it is
+ * stable... nzc 30-5-'00
+ */
+ /* count */
+ a = nu->pntsu;
+ bp = nu->bp;
+ while (a--) {
+ nextbp = BKE_nurb_bpoint_get_next(nu, bp);
+ if (nextbp == NULL) {
+ break;
+ }
+
+ if ((bp->f1 & SELECT) && (nextbp->f1 & SELECT)) {
+ amount += number_cuts;
+ }
+ bp++;
+ }
+
+ if (amount) {
+ /* insert */
+ bpnew = (BPoint *)MEM_mallocN((amount + nu->pntsu) * sizeof(BPoint), "subdivNurb2");
+ bpn = bpnew;
+
+ a = nu->pntsu;
+ bp = nu->bp;
+
+ while (a--) {
+ /* Copy "old" point. */
+ memcpy(bpn, bp, sizeof(BPoint));
+ keyIndex_updateBP(editnurb, bp, bpn, 1);
+ bpn++;
+
+ nextbp = BKE_nurb_bpoint_get_next(nu, bp);
+ if (nextbp == NULL) {
+ break;
+ }
+
+ if ((bp->f1 & SELECT) && (nextbp->f1 & SELECT)) {
+ // printf("*** subdivideNurb: insert 'linear' point\n");
+ for (i = 0; i < number_cuts; i++) {
+ factor = (float)(i + 1) / (number_cuts + 1);
+
+ memcpy(bpn, nextbp, sizeof(BPoint));
+ interp_v4_v4v4(bpn->vec, bp->vec, nextbp->vec, factor);
+ bpn++;
+ }
+ }
+ bp++;
+ }
+
+ MEM_freeN(nu->bp);
+ nu->bp = bpnew;
+ nu->pntsu += amount;
+
+ if (nu->type & CU_NURBS) {
+ BKE_nurb_knot_calc_u(nu);
+ }
+ }
+ } /* End of 'else if (nu->pntsv == 1)' */
+ else if (nu->type == CU_NURBS) {
+ /* This is a very strange test ... */
+ /**
+ * Subdivide NURB surfaces - nzc 30-5-'00 -
+ *
+ * Subdivision of a NURB curve can be effected by adding a
+ * control point (insertion of a knot), or by raising the
+ * degree of the functions used to build the NURB. The
+ * expression
+ *
+ * degree = #knots - #controlpoints + 1 (J Walter piece)
+ * degree = #knots - #controlpoints (Blender
+ * implementation)
+ * ( this is confusing.... what is true? Another concern
+ * is that the JW piece allows the curve to become
+ * explicitly 1st order derivative discontinuous, while
+ * this is not what we want here... )
+ *
+ * is an invariant for a single NURB curve. Raising the degree
+ * of the NURB is done elsewhere; the degree is assumed
+ * constant during this operation. Degree is a property shared
+ * by all controlpoints in a curve (even though it is stored
+ * per control point - this can be misleading).
+ * Adding a knot is done by searching for the place in the
+ * knot vector where a certain knot value must be inserted, or
+ * by picking an appropriate knot value between two existing
+ * ones. The number of controlpoints that is influenced by the
+ * insertion depends on the order of the curve. A certain
+ * minimum number of knots is needed to form high-order
+ * curves, as can be seen from the equation above. In Blender,
+ * currently NURBs may be up to 6th order, so we modify at
+ * most 6 points. One point is added. For an n-degree curve,
+ * n points are discarded, and n+1 points inserted
+ * (so effectively, n points are modified). (that holds for
+ * the JW piece, but it seems not for our NURBs)
+ * In practice, the knot spacing is copied, but the tail
+ * (the points following the insertion point) need to be
+ * offset to keep the knot series ascending. The knot series
+ * is always a series of monotonically ascending integers in
+ * Blender. When not enough control points are available to
+ * fit the order, duplicates of the endpoints are added as
+ * needed.
+ */
+ /* selection-arrays */
+ usel = MEM_callocN(sizeof(int) * nu->pntsu, "subivideNurb3");
+ vsel = MEM_callocN(sizeof(int) * nu->pntsv, "subivideNurb3");
+ sel = 0;
+
+ /* Count the number of selected points. */
+ bp = nu->bp;
+ for (a = 0; a < nu->pntsv; a++) {
+ for (b = 0; b < nu->pntsu; b++) {
+ if (bp->f1 & SELECT) {
+ usel[b]++;
+ vsel[a]++;
+ sel++;
+ }
+ bp++;
+ }
+ }
+ if (sel == (nu->pntsu * nu->pntsv)) { /* subdivide entire nurb */
+ /* Global subdivision is a special case of partial
+ * subdivision. Strange it is considered separately... */
+
+ /* count of nodes (after subdivision) along U axis */
+ int countu = nu->pntsu + (nu->pntsu - 1) * number_cuts;
+
+ /* total count of nodes after subdivision */
+ int tot = ((number_cuts + 1) * nu->pntsu - number_cuts) *
+ ((number_cuts + 1) * nu->pntsv - number_cuts);
+
+ bpn = bpnew = MEM_mallocN(tot * sizeof(BPoint), "subdivideNurb4");
+ bp = nu->bp;
+ /* first subdivide rows */
+ for (a = 0; a < nu->pntsv; a++) {
+ for (b = 0; b < nu->pntsu; b++) {
+ *bpn = *bp;
+ keyIndex_updateBP(editnurb, bp, bpn, 1);
+ bpn++;
+ bp++;
+ if (b < nu->pntsu - 1) {
+ prevbp = bp - 1;
+ for (i = 0; i < number_cuts; i++) {
+ factor = (float)(i + 1) / (number_cuts + 1);
+ *bpn = *bp;
+ interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor);
+ bpn++;
+ }
+ }
+ }
+ bpn += number_cuts * countu;
+ }
+ /* now insert new */
+ bpn = bpnew + ((number_cuts + 1) * nu->pntsu - number_cuts);
+ bp = bpnew + (number_cuts + 1) * ((number_cuts + 1) * nu->pntsu - number_cuts);
+ prevbp = bpnew;
+ for (a = 1; a < nu->pntsv; a++) {
+
+ for (b = 0; b < (number_cuts + 1) * nu->pntsu - number_cuts; b++) {
+ BPoint *tmp = bpn;
+ for (i = 0; i < number_cuts; i++) {
+ factor = (float)(i + 1) / (number_cuts + 1);
+ *tmp = *bp;
+ interp_v4_v4v4(tmp->vec, prevbp->vec, bp->vec, factor);
+ tmp += countu;
+ }
+ bp++;
+ prevbp++;
+ bpn++;
+ }
+ bp += number_cuts * countu;
+ bpn += number_cuts * countu;
+ prevbp += number_cuts * countu;
+ }
+ MEM_freeN(nu->bp);
+ nu->bp = bpnew;
+ nu->pntsu = (number_cuts + 1) * nu->pntsu - number_cuts;
+ nu->pntsv = (number_cuts + 1) * nu->pntsv - number_cuts;
+ BKE_nurb_knot_calc_u(nu);
+ BKE_nurb_knot_calc_v(nu);
+ } /* End of 'if (sel == nu->pntsu * nu->pntsv)' (subdivide entire NURB) */
+ else {
+ /* subdivide in v direction? */
+ sel = 0;
+ for (a = 0; a < nu->pntsv - 1; a++) {
+ if (vsel[a] == nu->pntsu && vsel[a + 1] == nu->pntsu) {
+ sel += number_cuts;
+ }
+ }
+
+ if (sel) { /* V ! */
+ bpn = bpnew = MEM_mallocN((sel + nu->pntsv) * nu->pntsu * sizeof(BPoint),
+ "subdivideNurb4");
+ bp = nu->bp;
+ for (a = 0; a < nu->pntsv; a++) {
+ for (b = 0; b < nu->pntsu; b++) {
+ *bpn = *bp;
+ keyIndex_updateBP(editnurb, bp, bpn, 1);
+ bpn++;
+ bp++;
+ }
+ if ((a < nu->pntsv - 1) && vsel[a] == nu->pntsu && vsel[a + 1] == nu->pntsu) {
+ for (i = 0; i < number_cuts; i++) {
+ factor = (float)(i + 1) / (number_cuts + 1);
+ prevbp = bp - nu->pntsu;
+ for (b = 0; b < nu->pntsu; b++) {
+ /*
+ * This simple bisection must be replaces by a
+ * subtle resampling of a number of points. Our
+ * task is made slightly easier because each
+ * point in our curve is a separate data
+ * node. (is it?)
+ */
+ *bpn = *prevbp;
+ interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor);
+ bpn++;
+
+ prevbp++;
+ bp++;
+ }
+ bp -= nu->pntsu;
+ }
+ }
+ }
+ MEM_freeN(nu->bp);
+ nu->bp = bpnew;
+ nu->pntsv += sel;
+ BKE_nurb_knot_calc_v(nu);
+ }
+ else {
+ /* or in u direction? */
+ sel = 0;
+ for (a = 0; a < nu->pntsu - 1; a++) {
+ if (usel[a] == nu->pntsv && usel[a + 1] == nu->pntsv) {
+ sel += number_cuts;
+ }
+ }
+
+ if (sel) { /* U ! */
+ /* Inserting U points is sort of 'default' Flat curves only get */
+ /* U points inserted in them. */
+ bpn = bpnew = MEM_mallocN((sel + nu->pntsu) * nu->pntsv * sizeof(BPoint),
+ "subdivideNurb4");
+ bp = nu->bp;
+ for (a = 0; a < nu->pntsv; a++) {
+ for (b = 0; b < nu->pntsu; b++) {
+ *bpn = *bp;
+ keyIndex_updateBP(editnurb, bp, bpn, 1);
+ bpn++;
+ bp++;
+ if ((b < nu->pntsu - 1) && usel[b] == nu->pntsv && usel[b + 1] == nu->pntsv) {
+ /*
+ * One thing that bugs me here is that the
+ * orders of things are not the same as in
+ * the JW piece. Also, this implies that we
+ * handle at most 3rd order curves? I miss
+ * some symmetry here...
+ */
+ for (i = 0; i < number_cuts; i++) {
+ factor = (float)(i + 1) / (number_cuts + 1);
+ prevbp = bp - 1;
+ *bpn = *prevbp;
+ interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor);
+ bpn++;
+ }
+ }
+ }
+ }
+ MEM_freeN(nu->bp);
+ nu->bp = bpnew;
+ nu->pntsu += sel;
+ BKE_nurb_knot_calc_u(nu); /* shift knots forward */
+ }
+ }
+ }
+ MEM_freeN(usel);
+ MEM_freeN(vsel);
+
+ } /* End of 'if (nu->type == CU_NURBS)' */
+ }
}
static int subdivide_exec(bContext *C, wmOperator *op)
{
- const int number_cuts = RNA_int_get(op->ptr, "number_cuts");
+ const int number_cuts = RNA_int_get(op->ptr, "number_cuts");
- Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
+ Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(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];
- Curve *cu = obedit->data;
+ 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];
+ Curve *cu = obedit->data;
- if (!ED_curve_select_check(v3d, cu->editnurb)) {
- continue;
- }
+ if (!ED_curve_select_check(v3d, cu->editnurb)) {
+ continue;
+ }
- subdividenurb(obedit, v3d, number_cuts);
+ subdividenurb(obedit, v3d, number_cuts);
- if (ED_curve_updateAnimPaths(bmain, cu)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
- }
+ if (ED_curve_updateAnimPaths(bmain, cu)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ }
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, cu);
- DEG_id_tag_update(obedit->data, 0);
- }
- MEM_freeN(objects);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, cu);
+ DEG_id_tag_update(obedit->data, 0);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CURVE_OT_subdivide(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Subdivide";
- ot->description = "Subdivide selected segments";
- ot->idname = "CURVE_OT_subdivide";
+ /* identifiers */
+ ot->name = "Subdivide";
+ ot->description = "Subdivide selected segments";
+ ot->idname = "CURVE_OT_subdivide";
- /* api callbacks */
- ot->exec = subdivide_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = subdivide_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000, "Number of cuts", "", 1, 10);
- /* avoid re-using last var because it can cause _very_ high poly meshes and annoy users (or worse crash) */
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000, "Number of cuts", "", 1, 10);
+ /* avoid re-using last var because it can cause _very_ high poly meshes and annoy users (or worse crash) */
+ 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 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++;
- }
- }
- }
+ 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 *******************/
static int set_spline_type_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *obedit = CTX_data_edit_object(C);
- View3D *v3d = CTX_wm_view3d(C);
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- bool changed = false;
- bool changed_size = false;
- const bool use_handles = RNA_boolean_get(op->ptr, "use_handles");
- const int type = RNA_enum_get(op->ptr, "type");
-
- if (type == CU_CARDINAL || type == CU_BSPLINE) {
- BKE_report(op->reports, RPT_ERROR, "Not yet implemented");
- return OPERATOR_CANCELLED;
- }
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (ED_curve_nurb_select_check(v3d, nu)) {
- const int pntsu_prev = nu->pntsu;
- if (BKE_nurb_type_convert(nu, type, use_handles)) {
- changed = true;
- if (pntsu_prev != nu->pntsu) {
- changed_size = true;
- }
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "No conversion possible");
- }
- }
- }
-
- if (changed) {
- if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
- }
-
- DEG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
-
- if (changed_size) {
- Curve *cu = obedit->data;
- cu->actvert = CU_ACT_NONE;
- }
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Main *bmain = CTX_data_main(C);
+ Object *obedit = CTX_data_edit_object(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ bool changed = false;
+ bool changed_size = false;
+ const bool use_handles = RNA_boolean_get(op->ptr, "use_handles");
+ const int type = RNA_enum_get(op->ptr, "type");
+
+ if (type == CU_CARDINAL || type == CU_BSPLINE) {
+ BKE_report(op->reports, RPT_ERROR, "Not yet implemented");
+ return OPERATOR_CANCELLED;
+ }
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (ED_curve_nurb_select_check(v3d, nu)) {
+ const int pntsu_prev = nu->pntsu;
+ if (BKE_nurb_type_convert(nu, type, use_handles)) {
+ changed = true;
+ if (pntsu_prev != nu->pntsu) {
+ changed_size = true;
+ }
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No conversion possible");
+ }
+ }
+ }
+
+ if (changed) {
+ if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ }
+
+ DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+
+ if (changed_size) {
+ Curve *cu = obedit->data;
+ cu->actvert = CU_ACT_NONE;
+ }
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void CURVE_OT_spline_type_set(wmOperatorType *ot)
{
- static const EnumPropertyItem type_items[] = {
- {CU_POLY, "POLY", 0, "Poly", ""},
- {CU_BEZIER, "BEZIER", 0, "Bezier", ""},
-// {CU_CARDINAL, "CARDINAL", 0, "Cardinal", ""},
-// {CU_BSPLINE, "B_SPLINE", 0, "B-Spline", ""},
- {CU_NURBS, "NURBS", 0, "NURBS", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Set Spline Type";
- ot->description = "Set type of active spline";
- ot->idname = "CURVE_OT_spline_type_set";
-
- /* api callbacks */
- ot->exec = set_spline_type_exec;
- ot->invoke = WM_menu_invoke;
- ot->poll = ED_operator_editcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", type_items, CU_POLY, "Type", "Spline type");
- RNA_def_boolean(ot->srna, "use_handles", 0, "Handles", "Use handles when converting bezier curves into polygons");
+ static const EnumPropertyItem type_items[] = {
+ {CU_POLY, "POLY", 0, "Poly", ""},
+ {CU_BEZIER, "BEZIER", 0, "Bezier", ""},
+ // {CU_CARDINAL, "CARDINAL", 0, "Cardinal", ""},
+ // {CU_BSPLINE, "B_SPLINE", 0, "B-Spline", ""},
+ {CU_NURBS, "NURBS", 0, "NURBS", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Set Spline Type";
+ ot->description = "Set type of active spline";
+ ot->idname = "CURVE_OT_spline_type_set";
+
+ /* api callbacks */
+ ot->exec = set_spline_type_exec;
+ ot->invoke = WM_menu_invoke;
+ ot->poll = ED_operator_editcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", type_items, CU_POLY, "Type", "Spline type");
+ RNA_def_boolean(ot->srna,
+ "use_handles",
+ 0,
+ "Handles",
+ "Use handles when converting bezier curves into polygons");
}
/***************** set handle type operator *******************/
static int set_handle_type_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- const int handle_type = RNA_enum_get(op->ptr, "type");
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ const int handle_type = RNA_enum_get(op->ptr, "type");
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Curve *cu = obedit->data;
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Curve *cu = obedit->data;
- if (!ED_curve_select_check(v3d, cu->editnurb)) {
- continue;
- }
+ if (!ED_curve_select_check(v3d, cu->editnurb)) {
+ continue;
+ }
- ListBase *editnurb = object_editcurve_get(obedit);
- BKE_nurbList_handles_set(editnurb, handle_type);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ BKE_nurbList_handles_set(editnurb, handle_type);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void CURVE_OT_handle_type_set(wmOperatorType *ot)
{
- /* keep in sync with graphkeys_handle_type_items */
- static const EnumPropertyItem editcurve_handle_type_items[] = {
- {HD_AUTO, "AUTOMATIC", 0, "Automatic", ""},
- {HD_VECT, "VECTOR", 0, "Vector", ""},
- {5, "ALIGNED", 0, "Aligned", ""},
- {6, "FREE_ALIGN", 0, "Free", ""},
- {3, "TOGGLE_FREE_ALIGN", 0, "Toggle Free/Align", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ /* keep in sync with graphkeys_handle_type_items */
+ static const EnumPropertyItem editcurve_handle_type_items[] = {
+ {HD_AUTO, "AUTOMATIC", 0, "Automatic", ""},
+ {HD_VECT, "VECTOR", 0, "Vector", ""},
+ {5, "ALIGNED", 0, "Aligned", ""},
+ {6, "FREE_ALIGN", 0, "Free", ""},
+ {3, "TOGGLE_FREE_ALIGN", 0, "Toggle Free/Align", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Set Handle Type";
- ot->description = "Set type of handles for selected control points";
- ot->idname = "CURVE_OT_handle_type_set";
+ /* identifiers */
+ ot->name = "Set Handle Type";
+ ot->description = "Set type of handles for selected control points";
+ ot->idname = "CURVE_OT_handle_type_set";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = set_handle_type_exec;
- ot->poll = ED_operator_editcurve;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = set_handle_type_exec;
+ ot->poll = ED_operator_editcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type");
}
/***************** recalculate handles operator **********************/
static int curve_normals_make_consistent_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
- const bool calc_length = RNA_boolean_get(op->ptr, "calc_length");
+ const bool calc_length = RNA_boolean_get(op->ptr, "calc_length");
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Curve *cu = obedit->data;
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Curve *cu = obedit->data;
- if (!ED_curve_select_check(v3d, cu->editnurb)) {
- continue;
- }
+ if (!ED_curve_select_check(v3d, cu->editnurb)) {
+ continue;
+ }
- ListBase *editnurb = object_editcurve_get(obedit);
- BKE_nurbList_handles_recalculate(editnurb, calc_length, SELECT);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ BKE_nurbList_handles_recalculate(editnurb, calc_length, SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void CURVE_OT_normals_make_consistent(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Recalc Normals";
- ot->description = "Recalculate the direction of selected handles";
- ot->idname = "CURVE_OT_normals_make_consistent";
+ /* identifiers */
+ ot->name = "Recalc Normals";
+ ot->description = "Recalculate the direction of selected handles";
+ ot->idname = "CURVE_OT_normals_make_consistent";
- /* api callbacks */
- ot->exec = curve_normals_make_consistent_exec;
- ot->poll = ED_operator_editcurve;
+ /* api callbacks */
+ ot->exec = curve_normals_make_consistent_exec;
+ ot->poll = ED_operator_editcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "calc_length", false, "Length", "Recalculate handle length");
+ /* props */
+ RNA_def_boolean(ot->srna, "calc_length", false, "Length", "Recalculate handle length");
}
/***************** make segment operator **********************/
@@ -4026,94 +4099,94 @@ void CURVE_OT_normals_make_consistent(wmOperatorType *ot)
static void switchdirection_knots(float *base, int tot)
{
- float *fp1, *fp2, *tempf;
- int a;
-
- if (base == NULL || tot == 0) {
- return;
- }
-
- /* reverse knots */
- a = tot;
- fp1 = base;
- fp2 = fp1 + (a - 1);
- a /= 2;
- while (fp1 != fp2 && a > 0) {
- SWAP(float, *fp1, *fp2);
- a--;
- fp1++;
- fp2--;
- }
-
- /* and make in increasing order again */
- a = tot - 1;
- fp1 = base;
- fp2 = tempf = MEM_mallocN(sizeof(float) * tot, "switchdirect");
- while (a--) {
- fp2[0] = fabsf(fp1[1] - fp1[0]);
- fp1++;
- fp2++;
- }
- fp2[0] = 0.0f;
-
- a = tot - 1;
- fp1 = base;
- fp2 = tempf;
- fp1[0] = 0.0;
- fp1++;
- while (a--) {
- fp1[0] = fp1[-1] + fp2[0];
- fp1++;
- fp2++;
- }
- MEM_freeN(tempf);
+ float *fp1, *fp2, *tempf;
+ int a;
+
+ if (base == NULL || tot == 0) {
+ return;
+ }
+
+ /* reverse knots */
+ a = tot;
+ fp1 = base;
+ fp2 = fp1 + (a - 1);
+ a /= 2;
+ while (fp1 != fp2 && a > 0) {
+ SWAP(float, *fp1, *fp2);
+ a--;
+ fp1++;
+ fp2--;
+ }
+
+ /* and make in increasing order again */
+ a = tot - 1;
+ fp1 = base;
+ fp2 = tempf = MEM_mallocN(sizeof(float) * tot, "switchdirect");
+ while (a--) {
+ fp2[0] = fabsf(fp1[1] - fp1[0]);
+ fp1++;
+ fp2++;
+ }
+ fp2[0] = 0.0f;
+
+ a = tot - 1;
+ fp1 = base;
+ fp2 = tempf;
+ fp1[0] = 0.0;
+ fp1++;
+ while (a--) {
+ fp1[0] = fp1[-1] + fp2[0];
+ fp1++;
+ fp2++;
+ }
+ MEM_freeN(tempf);
}
static void rotate_direction_nurb(Nurb *nu)
{
- BPoint *bp1, *bp2, *temp;
- int u, v;
+ BPoint *bp1, *bp2, *temp;
+ int u, v;
- SWAP(int, nu->pntsu, nu->pntsv);
- SWAP(short, nu->orderu, nu->orderv);
- SWAP(short, nu->resolu, nu->resolv);
- SWAP(short, nu->flagu, nu->flagv);
+ SWAP(int, nu->pntsu, nu->pntsv);
+ SWAP(short, nu->orderu, nu->orderv);
+ SWAP(short, nu->resolu, nu->resolv);
+ SWAP(short, nu->flagu, nu->flagv);
- SWAP(float *, nu->knotsu, nu->knotsv);
- switchdirection_knots(nu->knotsv, KNOTSV(nu));
+ SWAP(float *, nu->knotsu, nu->knotsv);
+ switchdirection_knots(nu->knotsv, KNOTSV(nu));
- temp = MEM_dupallocN(nu->bp);
- bp1 = nu->bp;
- for (v = 0; v < nu->pntsv; v++) {
- for (u = 0; u < nu->pntsu; u++, bp1++) {
- bp2 = temp + (nu->pntsu - u - 1) * (nu->pntsv) + v;
- *bp1 = *bp2;
- }
- }
+ temp = MEM_dupallocN(nu->bp);
+ bp1 = nu->bp;
+ for (v = 0; v < nu->pntsv; v++) {
+ for (u = 0; u < nu->pntsu; u++, bp1++) {
+ bp2 = temp + (nu->pntsu - u - 1) * (nu->pntsv) + v;
+ *bp1 = *bp2;
+ }
+ }
- MEM_freeN(temp);
+ MEM_freeN(temp);
}
static bool is_u_selected(Nurb *nu, int u)
{
- BPoint *bp;
- int v;
+ BPoint *bp;
+ int v;
- /* what about resolu == 2? */
- bp = &nu->bp[u];
- for (v = 0; v < nu->pntsv - 1; v++, bp += nu->pntsu) {
- if ((v != 0) && (bp->f1 & SELECT)) {
- return true;
- }
- }
+ /* what about resolu == 2? */
+ bp = &nu->bp[u];
+ for (v = 0; v < nu->pntsv - 1; v++, bp += nu->pntsu) {
+ if ((v != 0) && (bp->f1 & SELECT)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
typedef struct NurbSort {
- struct NurbSort *next, *prev;
- Nurb *nu;
- float vec[3];
+ struct NurbSort *next, *prev;
+ Nurb *nu;
+ float vec[3];
} NurbSort;
static ListBase nsortbase = {NULL, NULL};
@@ -4121,2837 +4194,2877 @@ static ListBase nsortbase = {NULL, NULL};
static void make_selection_list_nurb(View3D *v3d, ListBase *editnurb)
{
- ListBase nbase = {NULL, NULL};
- NurbSort *nus, *nustest, *headdo, *taildo;
- Nurb *nu;
- BPoint *bp;
- float dist, headdist, taildist;
- int a;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (ED_curve_nurb_select_check(v3d, nu)) {
-
- nus = (NurbSort *)MEM_callocN(sizeof(NurbSort), "sort");
- BLI_addhead(&nbase, nus);
- nus->nu = nu;
-
- bp = nu->bp;
- a = nu->pntsu;
- while (a--) {
- add_v3_v3(nus->vec, bp->vec);
- bp++;
- }
- mul_v3_fl(nus->vec, 1.0f / (float)nu->pntsu);
-
-
- }
- }
-
- /* just add the first one */
- nus = nbase.first;
- BLI_remlink(&nbase, nus);
- BLI_addtail(&nsortbase, nus);
-
- /* now add, either at head or tail, the closest one */
- while (nbase.first) {
-
- headdist = taildist = 1.0e30;
- headdo = taildo = NULL;
-
- nustest = nbase.first;
- while (nustest) {
- 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);
-
- if (dist < taildist) {
- taildist = dist;
- taildo = nustest;
- }
- nustest = nustest->next;
- }
-
- if (headdist < taildist) {
- BLI_remlink(&nbase, headdo);
- BLI_addhead(&nsortbase, headdo);
- }
- else {
- BLI_remlink(&nbase, taildo);
- BLI_addtail(&nsortbase, taildo);
- }
- }
+ ListBase nbase = {NULL, NULL};
+ NurbSort *nus, *nustest, *headdo, *taildo;
+ Nurb *nu;
+ BPoint *bp;
+ float dist, headdist, taildist;
+ int a;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (ED_curve_nurb_select_check(v3d, nu)) {
+
+ nus = (NurbSort *)MEM_callocN(sizeof(NurbSort), "sort");
+ BLI_addhead(&nbase, nus);
+ nus->nu = nu;
+
+ bp = nu->bp;
+ a = nu->pntsu;
+ while (a--) {
+ add_v3_v3(nus->vec, bp->vec);
+ bp++;
+ }
+ mul_v3_fl(nus->vec, 1.0f / (float)nu->pntsu);
+ }
+ }
+
+ /* just add the first one */
+ nus = nbase.first;
+ BLI_remlink(&nbase, nus);
+ BLI_addtail(&nsortbase, nus);
+
+ /* now add, either at head or tail, the closest one */
+ while (nbase.first) {
+
+ headdist = taildist = 1.0e30;
+ headdo = taildo = NULL;
+
+ nustest = nbase.first;
+ while (nustest) {
+ 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);
+
+ if (dist < taildist) {
+ taildist = dist;
+ taildo = nustest;
+ }
+ nustest = nustest->next;
+ }
+
+ if (headdist < taildist) {
+ BLI_remlink(&nbase, headdo);
+ BLI_addhead(&nsortbase, headdo);
+ }
+ else {
+ BLI_remlink(&nbase, taildo);
+ BLI_addtail(&nsortbase, taildo);
+ }
+ }
}
enum {
- CURVE_MERGE_OK = 0,
- CURVE_MERGE_ERR_FEW_SELECTION,
- CURVE_MERGE_ERR_RESOLUTION_ALL,
- CURVE_MERGE_ERR_RESOLUTION_SOME,
+ CURVE_MERGE_OK = 0,
+ CURVE_MERGE_ERR_FEW_SELECTION,
+ CURVE_MERGE_ERR_RESOLUTION_ALL,
+ CURVE_MERGE_ERR_RESOLUTION_SOME,
};
static bool merge_2_nurb(Curve *cu, ListBase *editnurb, Nurb *nu1, Nurb *nu2)
{
- BPoint *bp, *bp1, *bp2, *temp;
- float len1, len2;
- int origu, u, v;
-
- /* first nurbs will be changed to make u = resolu-1 selected */
- /* 2nd nurbs will be changed to make u = 0 selected */
-
- /* first nurbs: u = resolu-1 selected */
-
- if (is_u_selected(nu1, nu1->pntsu - 1)) {
- /* pass */
- }
- else {
- /* For 2D curves blender uses (orderv = 0). It doesn't make any sense mathematically. */
- /* but after rotating (orderu = 0) will be confusing. */
- if (nu1->orderv == 0) {
- nu1->orderv = 1;
- }
-
- rotate_direction_nurb(nu1);
- if (is_u_selected(nu1, nu1->pntsu - 1)) {
- /* pass */
- }
- else {
- rotate_direction_nurb(nu1);
- if (is_u_selected(nu1, nu1->pntsu - 1)) {
- /* pass */
- }
- else {
- rotate_direction_nurb(nu1);
- if (is_u_selected(nu1, nu1->pntsu - 1)) {
- /* pass */
- }
- else {
- /* rotate again, now its OK! */
- if (nu1->pntsv != 1) {
- rotate_direction_nurb(nu1);
- }
- return true;
- }
- }
- }
- }
-
- /* 2nd nurbs: u = 0 selected */
- if (is_u_selected(nu2, 0)) {
- /* pass */
- }
- else {
- if (nu2->orderv == 0) {
- nu2->orderv = 1;
- }
- rotate_direction_nurb(nu2);
- if (is_u_selected(nu2, 0)) {
- /* pass */
- }
- else {
- rotate_direction_nurb(nu2);
- if (is_u_selected(nu2, 0)) {
- /* pass */
- }
- else {
- rotate_direction_nurb(nu2);
- if (is_u_selected(nu2, 0)) {
- /* pass */
- }
- else {
- /* rotate again, now its OK! */
- if (nu1->pntsu == 1) {
- rotate_direction_nurb(nu1);
- }
- if (nu2->pntsv != 1) {
- rotate_direction_nurb(nu2);
- }
- return true;
- }
- }
- }
- }
-
- if (nu1->pntsv != nu2->pntsv) {
- return false;
- }
-
- /* ok, now nu1 has the rightmost column and nu2 the leftmost column selected */
- /* maybe we need a 'v' flip of nu2? */
-
- bp1 = &nu1->bp[nu1->pntsu - 1];
- bp2 = nu2->bp;
- len1 = 0.0;
-
- for (v = 0; v < nu1->pntsv; v++, bp1 += nu1->pntsu, bp2 += nu2->pntsu) {
- len1 += len_v3v3(bp1->vec, bp2->vec);
- }
-
- bp1 = &nu1->bp[nu1->pntsu - 1];
- bp2 = &nu2->bp[nu2->pntsu * (nu2->pntsv - 1)];
- len2 = 0.0;
-
- for (v = 0; v < nu1->pntsv; v++, bp1 += nu1->pntsu, bp2 -= nu2->pntsu) {
- len2 += len_v3v3(bp1->vec, bp2->vec);
- }
-
- /* merge */
- origu = nu1->pntsu;
- nu1->pntsu += nu2->pntsu;
- if (nu1->orderu < 3 && nu1->orderu < nu1->pntsu) {
- nu1->orderu++;
- }
- if (nu1->orderv < 3 && nu1->orderv < nu1->pntsv) {
- nu1->orderv++;
- }
- temp = nu1->bp;
- nu1->bp = MEM_mallocN(nu1->pntsu * nu1->pntsv * sizeof(BPoint), "mergeBP");
-
- bp = nu1->bp;
- bp1 = temp;
-
- for (v = 0; v < nu1->pntsv; v++) {
-
- /* switch direction? */
- if (len1 < len2) {
- bp2 = &nu2->bp[v * nu2->pntsu];
- }
- else {
- bp2 = &nu2->bp[(nu1->pntsv - v - 1) * nu2->pntsu];
- }
-
- for (u = 0; u < nu1->pntsu; u++, bp++) {
- if (u < origu) {
- keyIndex_updateBP(cu->editnurb, bp1, bp, 1);
- *bp = *bp1; bp1++;
- select_bpoint(bp, SELECT, SELECT, HIDDEN);
- }
- else {
- keyIndex_updateBP(cu->editnurb, bp2, bp, 1);
- *bp = *bp2; bp2++;
- }
- }
- }
-
- if (nu1->type == CU_NURBS) {
- /* merge knots */
- BKE_nurb_knot_calc_u(nu1);
-
- /* make knots, for merged curved for example */
- BKE_nurb_knot_calc_v(nu1);
- }
-
- MEM_freeN(temp);
- BLI_remlink(editnurb, nu2);
- BKE_nurb_free(nu2);
- return true;
+ BPoint *bp, *bp1, *bp2, *temp;
+ float len1, len2;
+ int origu, u, v;
+
+ /* first nurbs will be changed to make u = resolu-1 selected */
+ /* 2nd nurbs will be changed to make u = 0 selected */
+
+ /* first nurbs: u = resolu-1 selected */
+
+ if (is_u_selected(nu1, nu1->pntsu - 1)) {
+ /* pass */
+ }
+ else {
+ /* For 2D curves blender uses (orderv = 0). It doesn't make any sense mathematically. */
+ /* but after rotating (orderu = 0) will be confusing. */
+ if (nu1->orderv == 0) {
+ nu1->orderv = 1;
+ }
+
+ rotate_direction_nurb(nu1);
+ if (is_u_selected(nu1, nu1->pntsu - 1)) {
+ /* pass */
+ }
+ else {
+ rotate_direction_nurb(nu1);
+ if (is_u_selected(nu1, nu1->pntsu - 1)) {
+ /* pass */
+ }
+ else {
+ rotate_direction_nurb(nu1);
+ if (is_u_selected(nu1, nu1->pntsu - 1)) {
+ /* pass */
+ }
+ else {
+ /* rotate again, now its OK! */
+ if (nu1->pntsv != 1) {
+ rotate_direction_nurb(nu1);
+ }
+ return true;
+ }
+ }
+ }
+ }
+
+ /* 2nd nurbs: u = 0 selected */
+ if (is_u_selected(nu2, 0)) {
+ /* pass */
+ }
+ else {
+ if (nu2->orderv == 0) {
+ nu2->orderv = 1;
+ }
+ rotate_direction_nurb(nu2);
+ if (is_u_selected(nu2, 0)) {
+ /* pass */
+ }
+ else {
+ rotate_direction_nurb(nu2);
+ if (is_u_selected(nu2, 0)) {
+ /* pass */
+ }
+ else {
+ rotate_direction_nurb(nu2);
+ if (is_u_selected(nu2, 0)) {
+ /* pass */
+ }
+ else {
+ /* rotate again, now its OK! */
+ if (nu1->pntsu == 1) {
+ rotate_direction_nurb(nu1);
+ }
+ if (nu2->pntsv != 1) {
+ rotate_direction_nurb(nu2);
+ }
+ return true;
+ }
+ }
+ }
+ }
+
+ if (nu1->pntsv != nu2->pntsv) {
+ return false;
+ }
+
+ /* ok, now nu1 has the rightmost column and nu2 the leftmost column selected */
+ /* maybe we need a 'v' flip of nu2? */
+
+ bp1 = &nu1->bp[nu1->pntsu - 1];
+ bp2 = nu2->bp;
+ len1 = 0.0;
+
+ for (v = 0; v < nu1->pntsv; v++, bp1 += nu1->pntsu, bp2 += nu2->pntsu) {
+ len1 += len_v3v3(bp1->vec, bp2->vec);
+ }
+
+ bp1 = &nu1->bp[nu1->pntsu - 1];
+ bp2 = &nu2->bp[nu2->pntsu * (nu2->pntsv - 1)];
+ len2 = 0.0;
+
+ for (v = 0; v < nu1->pntsv; v++, bp1 += nu1->pntsu, bp2 -= nu2->pntsu) {
+ len2 += len_v3v3(bp1->vec, bp2->vec);
+ }
+
+ /* merge */
+ origu = nu1->pntsu;
+ nu1->pntsu += nu2->pntsu;
+ if (nu1->orderu < 3 && nu1->orderu < nu1->pntsu) {
+ nu1->orderu++;
+ }
+ if (nu1->orderv < 3 && nu1->orderv < nu1->pntsv) {
+ nu1->orderv++;
+ }
+ temp = nu1->bp;
+ nu1->bp = MEM_mallocN(nu1->pntsu * nu1->pntsv * sizeof(BPoint), "mergeBP");
+
+ bp = nu1->bp;
+ bp1 = temp;
+
+ for (v = 0; v < nu1->pntsv; v++) {
+
+ /* switch direction? */
+ if (len1 < len2) {
+ bp2 = &nu2->bp[v * nu2->pntsu];
+ }
+ else {
+ bp2 = &nu2->bp[(nu1->pntsv - v - 1) * nu2->pntsu];
+ }
+
+ for (u = 0; u < nu1->pntsu; u++, bp++) {
+ if (u < origu) {
+ keyIndex_updateBP(cu->editnurb, bp1, bp, 1);
+ *bp = *bp1;
+ bp1++;
+ select_bpoint(bp, SELECT, SELECT, HIDDEN);
+ }
+ else {
+ keyIndex_updateBP(cu->editnurb, bp2, bp, 1);
+ *bp = *bp2;
+ bp2++;
+ }
+ }
+ }
+
+ if (nu1->type == CU_NURBS) {
+ /* merge knots */
+ BKE_nurb_knot_calc_u(nu1);
+
+ /* make knots, for merged curved for example */
+ BKE_nurb_knot_calc_v(nu1);
+ }
+
+ MEM_freeN(temp);
+ BLI_remlink(editnurb, nu2);
+ BKE_nurb_free(nu2);
+ return true;
}
static int merge_nurb(View3D *v3d, Object *obedit)
{
- Curve *cu = obedit->data;
- ListBase *editnurb = object_editcurve_get(obedit);
- NurbSort *nus1, *nus2;
- bool ok = true;
-
- make_selection_list_nurb(v3d, editnurb);
-
- if (nsortbase.first == nsortbase.last) {
- BLI_freelistN(&nsortbase);
- return CURVE_MERGE_ERR_FEW_SELECTION;
- }
-
- nus1 = nsortbase.first;
- nus2 = nus1->next;
-
- /* resolution match, to avoid uv rotations */
- if (nus1->nu->pntsv == 1) {
- if (nus1->nu->pntsu == nus2->nu->pntsu || nus1->nu->pntsu == nus2->nu->pntsv) {
- /* pass */
- }
- else {
- ok = false;
- }
- }
- else if (nus2->nu->pntsv == 1) {
- if (nus2->nu->pntsu == nus1->nu->pntsu || nus2->nu->pntsu == nus1->nu->pntsv) {
- /* pass */
- }
- else {
- ok = false;
- }
- }
- else if (nus1->nu->pntsu == nus2->nu->pntsu || nus1->nu->pntsv == nus2->nu->pntsv) {
- /* pass */
- }
- else if (nus1->nu->pntsu == nus2->nu->pntsv || nus1->nu->pntsv == nus2->nu->pntsu) {
- /* pass */
- }
- else {
- ok = false;
- }
-
- if (ok == false) {
- BLI_freelistN(&nsortbase);
- return CURVE_MERGE_ERR_RESOLUTION_ALL;
- }
-
- while (nus2) {
- /* There is a change a few curves merged properly, but not all.
- * In this case we still update the curve, yet report the error. */
- ok &= merge_2_nurb(cu, editnurb, nus1->nu, nus2->nu);
- nus2 = nus2->next;
- }
-
- BLI_freelistN(&nsortbase);
- BKE_curve_nurb_active_set(obedit->data, NULL);
-
- return ok ? CURVE_MERGE_OK : CURVE_MERGE_ERR_RESOLUTION_SOME;
+ Curve *cu = obedit->data;
+ ListBase *editnurb = object_editcurve_get(obedit);
+ NurbSort *nus1, *nus2;
+ bool ok = true;
+
+ make_selection_list_nurb(v3d, editnurb);
+
+ if (nsortbase.first == nsortbase.last) {
+ BLI_freelistN(&nsortbase);
+ return CURVE_MERGE_ERR_FEW_SELECTION;
+ }
+
+ nus1 = nsortbase.first;
+ nus2 = nus1->next;
+
+ /* resolution match, to avoid uv rotations */
+ if (nus1->nu->pntsv == 1) {
+ if (nus1->nu->pntsu == nus2->nu->pntsu || nus1->nu->pntsu == nus2->nu->pntsv) {
+ /* pass */
+ }
+ else {
+ ok = false;
+ }
+ }
+ else if (nus2->nu->pntsv == 1) {
+ if (nus2->nu->pntsu == nus1->nu->pntsu || nus2->nu->pntsu == nus1->nu->pntsv) {
+ /* pass */
+ }
+ else {
+ ok = false;
+ }
+ }
+ else if (nus1->nu->pntsu == nus2->nu->pntsu || nus1->nu->pntsv == nus2->nu->pntsv) {
+ /* pass */
+ }
+ else if (nus1->nu->pntsu == nus2->nu->pntsv || nus1->nu->pntsv == nus2->nu->pntsu) {
+ /* pass */
+ }
+ else {
+ ok = false;
+ }
+
+ if (ok == false) {
+ BLI_freelistN(&nsortbase);
+ return CURVE_MERGE_ERR_RESOLUTION_ALL;
+ }
+
+ while (nus2) {
+ /* There is a change a few curves merged properly, but not all.
+ * In this case we still update the curve, yet report the error. */
+ ok &= merge_2_nurb(cu, editnurb, nus1->nu, nus2->nu);
+ nus2 = nus2->next;
+ }
+
+ BLI_freelistN(&nsortbase);
+ BKE_curve_nurb_active_set(obedit->data, NULL);
+
+ return ok ? CURVE_MERGE_OK : CURVE_MERGE_ERR_RESOLUTION_SOME;
}
static int make_segment_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
-
- struct {
- int changed;
- int unselected;
- int error_selected_few;
- int error_resolution;
- int error_generic;
- } status = {0};
-
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Curve *cu = obedit->data;
-
- if (!ED_curve_select_check(v3d, cu->editnurb)) {
- status.unselected++;
- continue;
- }
-
- ListBase *nubase = object_editcurve_get(obedit);
- Nurb *nu, *nu1 = NULL, *nu2 = NULL;
- BPoint *bp;
- bool ok = false;
-
- /* first decide if this is a surface merge! */
- if (obedit->type == OB_SURF) {
- nu = nubase->first;
- }
- else {
- nu = NULL;
- }
-
- while (nu) {
- const int nu_select_num = ED_curve_nurb_select_count(v3d, nu);
- if (nu_select_num) {
-
- if (nu->pntsu > 1 && nu->pntsv > 1) {
- break;
- }
-
- if (nu_select_num > 1) {
- break;
- }
- else {
- /* only 1 selected, not first or last, a little complex, but intuitive */
- if (nu->pntsv == 1) {
- if ((nu->bp->f1 & SELECT) || (nu->bp[nu->pntsu - 1].f1 & SELECT)) {
- /* pass */
- }
- else {
- break;
- }
- }
- }
- }
- nu = nu->next;
- }
-
- if (nu) {
- int merge_result = merge_nurb(v3d, obedit);
- switch (merge_result) {
- case CURVE_MERGE_OK:
- status.changed++;
- goto curve_merge_tag_object;
- case CURVE_MERGE_ERR_RESOLUTION_SOME:
- status.error_resolution++;
- goto curve_merge_tag_object;
- case CURVE_MERGE_ERR_FEW_SELECTION:
- status.error_selected_few++;
- break;
- case CURVE_MERGE_ERR_RESOLUTION_ALL:
- status.error_resolution++;
- break;
- }
- continue;
- }
-
- /* find both nurbs and points, nu1 will be put behind nu2 */
- for (nu = nubase->first; nu; nu = nu->next) {
- if (nu->pntsu == 1) {
- nu->flagu &= ~CU_NURB_CYCLIC;
- }
-
- if ((nu->flagu & CU_NURB_CYCLIC) == 0) { /* not cyclic */
- if (nu->type == CU_BEZIER) {
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &(nu->bezt[nu->pntsu - 1]))) {
- /* Last point is selected, preferred for nu2 */
- if (nu2 == NULL) {
- nu2 = nu;
- }
- else if (nu1 == NULL) {
- nu1 = nu;
-
- /* Just in case both of first/last CV are selected check
- * whether we really need to switch the direction.
- */
- if (!BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nu1->bezt)) {
- BKE_nurb_direction_switch(nu1);
- keyData_switchDirectionNurb(cu, nu1);
- }
- }
- }
- else if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nu->bezt)) {
- /* First point is selected, preferred for nu1 */
- if (nu1 == NULL) {
- nu1 = nu;
- }
- else if (nu2 == NULL) {
- nu2 = nu;
-
- /* Just in case both of first/last CV are selected check
- * whether we really need to switch the direction.
- */
- if (!BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &(nu->bezt[nu2->pntsu - 1]))) {
- BKE_nurb_direction_switch(nu2);
- keyData_switchDirectionNurb(cu, nu2);
- }
- }
- }
- }
- else if (nu->pntsv == 1) {
- /* Same logic as above: if first point is selected spline is
- * preferred for nu1, if last point is selected spline is
- * preferred for u2u.
- */
-
- bp = nu->bp;
- if (bp[nu->pntsu - 1].f1 & SELECT) {
- if (nu2 == NULL) {
- nu2 = nu;
- }
- else if (nu1 == NULL) {
- nu1 = nu;
-
- if ((bp->f1 & SELECT) == 0) {
- BKE_nurb_direction_switch(nu);
- keyData_switchDirectionNurb(cu, nu);
- }
- }
- }
- else if (bp->f1 & SELECT) {
- if (nu1 == NULL) {
- nu1 = nu;
- }
- else if (nu2 == NULL) {
- nu2 = nu;
-
- if ((bp[nu->pntsu - 1].f1 & SELECT) == 0) {
- BKE_nurb_direction_switch(nu);
- keyData_switchDirectionNurb(cu, nu);
- }
- }
- }
- }
- }
-
- if (nu1 && nu2) {
- /* Got second spline, no need to loop over rest of the splines. */
- break;
- }
- }
-
- if ((nu1 && nu2) && (nu1 != nu2)) {
- if (nu1->type == nu2->type) {
- if (nu1->type == CU_BEZIER) {
- BezTriple *bezt = (BezTriple *)MEM_mallocN((nu1->pntsu + nu2->pntsu) * sizeof(BezTriple), "addsegmentN");
- ED_curve_beztcpy(cu->editnurb, bezt, nu2->bezt, nu2->pntsu);
- ED_curve_beztcpy(cu->editnurb, bezt + nu2->pntsu, nu1->bezt, nu1->pntsu);
-
- MEM_freeN(nu1->bezt);
- nu1->bezt = bezt;
- nu1->pntsu += nu2->pntsu;
- BLI_remlink(nubase, nu2);
- keyIndex_delNurb(cu->editnurb, nu2);
- BKE_nurb_free(nu2); nu2 = NULL;
- BKE_nurb_handles_calc(nu1);
- }
- else {
- bp = (BPoint *)MEM_mallocN((nu1->pntsu + nu2->pntsu) * sizeof(BPoint), "addsegmentN2");
- ED_curve_bpcpy(cu->editnurb, bp, nu2->bp, nu2->pntsu);
- ED_curve_bpcpy(cu->editnurb, bp + nu2->pntsu, nu1->bp, nu1->pntsu);
- MEM_freeN(nu1->bp);
- nu1->bp = bp;
-
- /* a = nu1->pntsu + nu1->orderu; */ /* UNUSED */
-
- nu1->pntsu += nu2->pntsu;
- BLI_remlink(nubase, nu2);
-
- /* now join the knots */
- if (nu1->type == CU_NURBS) {
- if (nu1->knotsu != NULL) {
- MEM_freeN(nu1->knotsu);
- nu1->knotsu = NULL;
- }
-
- BKE_nurb_knot_calc_u(nu1);
- }
- keyIndex_delNurb(cu->editnurb, nu2);
- BKE_nurb_free(nu2); nu2 = NULL;
- }
-
- BKE_curve_nurb_active_set(cu, nu1); /* for selected */
- ok = true;
- }
- }
- else if ((nu1 && !nu2) || (!nu1 && nu2)) {
- if (nu2) {
- SWAP(Nurb *, nu1, nu2);
- }
-
- if (!(nu1->flagu & CU_NURB_CYCLIC) && nu1->pntsu > 1) {
- if (nu1->type == CU_BEZIER && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nu1->bezt) &&
- BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &nu1->bezt[nu1->pntsu - 1]))
- {
- nu1->flagu |= CU_NURB_CYCLIC;
- BKE_nurb_handles_calc(nu1);
- ok = true;
- }
- else if (nu1->type == CU_NURBS && nu1->bp->f1 & SELECT && (nu1->bp[nu1->pntsu - 1].f1 & SELECT)) {
- nu1->flagu |= CU_NURB_CYCLIC;
- BKE_nurb_knot_calc_u(nu1);
- ok = true;
- }
- }
- }
-
- if (!ok) {
- status.error_generic++;
- continue;
- }
-
- if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
- }
-
- status.changed++;
-
-curve_merge_tag_object:
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
- }
- MEM_freeN(objects);
-
- if (status.unselected == objects_len) {
- BKE_report(op->reports, RPT_ERROR, "No points were selected");
- return OPERATOR_CANCELLED;
- }
-
- const int tot_errors = status.error_selected_few + status.error_resolution + status.error_generic;
- if (tot_errors > 0) {
- /* Some curves changed, but some curves failed: don't explain why it failed. */
- if (status.changed) {
- BKE_reportf(op->reports,
- RPT_INFO,
- tot_errors == 1 ? "%d curve could not make segments" :
- "%d curves could not make segments",
- tot_errors);
- return OPERATOR_FINISHED;
- }
-
- /* All curves failed: If there is more than one error give a generic error report. */
- if (((status.error_selected_few ? 1 : 0) +
- (status.error_resolution ? 1 : 0) +
- (status.error_generic ? 1 : 0)) > 1)
- {
- BKE_report(op->reports, RPT_ERROR, "Could not make new segments");
- }
-
- /* All curves failed due to the same error. */
- if (status.error_selected_few) {
- BKE_report(op->reports, RPT_ERROR, "Too few selections to merge");
- }
- else if (status.error_resolution) {
- BKE_report(op->reports, RPT_ERROR, "Resolution does not match");
- }
- else {
- BLI_assert(status.error_generic);
- BKE_report(op->reports, RPT_ERROR, "Cannot make segment");
- }
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ struct {
+ int changed;
+ int unselected;
+ int error_selected_few;
+ int error_resolution;
+ int error_generic;
+ } status = {0};
+
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Curve *cu = obedit->data;
+
+ if (!ED_curve_select_check(v3d, cu->editnurb)) {
+ status.unselected++;
+ continue;
+ }
+
+ ListBase *nubase = object_editcurve_get(obedit);
+ Nurb *nu, *nu1 = NULL, *nu2 = NULL;
+ BPoint *bp;
+ bool ok = false;
+
+ /* first decide if this is a surface merge! */
+ if (obedit->type == OB_SURF) {
+ nu = nubase->first;
+ }
+ else {
+ nu = NULL;
+ }
+
+ while (nu) {
+ const int nu_select_num = ED_curve_nurb_select_count(v3d, nu);
+ if (nu_select_num) {
+
+ if (nu->pntsu > 1 && nu->pntsv > 1) {
+ break;
+ }
+
+ if (nu_select_num > 1) {
+ break;
+ }
+ else {
+ /* only 1 selected, not first or last, a little complex, but intuitive */
+ if (nu->pntsv == 1) {
+ if ((nu->bp->f1 & SELECT) || (nu->bp[nu->pntsu - 1].f1 & SELECT)) {
+ /* pass */
+ }
+ else {
+ break;
+ }
+ }
+ }
+ }
+ nu = nu->next;
+ }
+
+ if (nu) {
+ int merge_result = merge_nurb(v3d, obedit);
+ switch (merge_result) {
+ case CURVE_MERGE_OK:
+ status.changed++;
+ goto curve_merge_tag_object;
+ case CURVE_MERGE_ERR_RESOLUTION_SOME:
+ status.error_resolution++;
+ goto curve_merge_tag_object;
+ case CURVE_MERGE_ERR_FEW_SELECTION:
+ status.error_selected_few++;
+ break;
+ case CURVE_MERGE_ERR_RESOLUTION_ALL:
+ status.error_resolution++;
+ break;
+ }
+ continue;
+ }
+
+ /* find both nurbs and points, nu1 will be put behind nu2 */
+ for (nu = nubase->first; nu; nu = nu->next) {
+ if (nu->pntsu == 1) {
+ nu->flagu &= ~CU_NURB_CYCLIC;
+ }
+
+ if ((nu->flagu & CU_NURB_CYCLIC) == 0) { /* not cyclic */
+ if (nu->type == CU_BEZIER) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &(nu->bezt[nu->pntsu - 1]))) {
+ /* Last point is selected, preferred for nu2 */
+ if (nu2 == NULL) {
+ nu2 = nu;
+ }
+ else if (nu1 == NULL) {
+ nu1 = nu;
+
+ /* Just in case both of first/last CV are selected check
+ * whether we really need to switch the direction.
+ */
+ if (!BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nu1->bezt)) {
+ BKE_nurb_direction_switch(nu1);
+ keyData_switchDirectionNurb(cu, nu1);
+ }
+ }
+ }
+ else if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nu->bezt)) {
+ /* First point is selected, preferred for nu1 */
+ if (nu1 == NULL) {
+ nu1 = nu;
+ }
+ else if (nu2 == NULL) {
+ nu2 = nu;
+
+ /* Just in case both of first/last CV are selected check
+ * whether we really need to switch the direction.
+ */
+ if (!BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &(nu->bezt[nu2->pntsu - 1]))) {
+ BKE_nurb_direction_switch(nu2);
+ keyData_switchDirectionNurb(cu, nu2);
+ }
+ }
+ }
+ }
+ else if (nu->pntsv == 1) {
+ /* Same logic as above: if first point is selected spline is
+ * preferred for nu1, if last point is selected spline is
+ * preferred for u2u.
+ */
+
+ bp = nu->bp;
+ if (bp[nu->pntsu - 1].f1 & SELECT) {
+ if (nu2 == NULL) {
+ nu2 = nu;
+ }
+ else if (nu1 == NULL) {
+ nu1 = nu;
+
+ if ((bp->f1 & SELECT) == 0) {
+ BKE_nurb_direction_switch(nu);
+ keyData_switchDirectionNurb(cu, nu);
+ }
+ }
+ }
+ else if (bp->f1 & SELECT) {
+ if (nu1 == NULL) {
+ nu1 = nu;
+ }
+ else if (nu2 == NULL) {
+ nu2 = nu;
+
+ if ((bp[nu->pntsu - 1].f1 & SELECT) == 0) {
+ BKE_nurb_direction_switch(nu);
+ keyData_switchDirectionNurb(cu, nu);
+ }
+ }
+ }
+ }
+ }
+
+ if (nu1 && nu2) {
+ /* Got second spline, no need to loop over rest of the splines. */
+ break;
+ }
+ }
+
+ if ((nu1 && nu2) && (nu1 != nu2)) {
+ if (nu1->type == nu2->type) {
+ if (nu1->type == CU_BEZIER) {
+ BezTriple *bezt = (BezTriple *)MEM_mallocN((nu1->pntsu + nu2->pntsu) * sizeof(BezTriple),
+ "addsegmentN");
+ ED_curve_beztcpy(cu->editnurb, bezt, nu2->bezt, nu2->pntsu);
+ ED_curve_beztcpy(cu->editnurb, bezt + nu2->pntsu, nu1->bezt, nu1->pntsu);
+
+ MEM_freeN(nu1->bezt);
+ nu1->bezt = bezt;
+ nu1->pntsu += nu2->pntsu;
+ BLI_remlink(nubase, nu2);
+ keyIndex_delNurb(cu->editnurb, nu2);
+ BKE_nurb_free(nu2);
+ nu2 = NULL;
+ BKE_nurb_handles_calc(nu1);
+ }
+ else {
+ bp = (BPoint *)MEM_mallocN((nu1->pntsu + nu2->pntsu) * sizeof(BPoint), "addsegmentN2");
+ ED_curve_bpcpy(cu->editnurb, bp, nu2->bp, nu2->pntsu);
+ ED_curve_bpcpy(cu->editnurb, bp + nu2->pntsu, nu1->bp, nu1->pntsu);
+ MEM_freeN(nu1->bp);
+ nu1->bp = bp;
+
+ /* a = nu1->pntsu + nu1->orderu; */ /* UNUSED */
+
+ nu1->pntsu += nu2->pntsu;
+ BLI_remlink(nubase, nu2);
+
+ /* now join the knots */
+ if (nu1->type == CU_NURBS) {
+ if (nu1->knotsu != NULL) {
+ MEM_freeN(nu1->knotsu);
+ nu1->knotsu = NULL;
+ }
+
+ BKE_nurb_knot_calc_u(nu1);
+ }
+ keyIndex_delNurb(cu->editnurb, nu2);
+ BKE_nurb_free(nu2);
+ nu2 = NULL;
+ }
+
+ BKE_curve_nurb_active_set(cu, nu1); /* for selected */
+ ok = true;
+ }
+ }
+ else if ((nu1 && !nu2) || (!nu1 && nu2)) {
+ if (nu2) {
+ SWAP(Nurb *, nu1, nu2);
+ }
+
+ if (!(nu1->flagu & CU_NURB_CYCLIC) && nu1->pntsu > 1) {
+ if (nu1->type == CU_BEZIER && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nu1->bezt) &&
+ BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &nu1->bezt[nu1->pntsu - 1])) {
+ nu1->flagu |= CU_NURB_CYCLIC;
+ BKE_nurb_handles_calc(nu1);
+ ok = true;
+ }
+ else if (nu1->type == CU_NURBS && nu1->bp->f1 & SELECT &&
+ (nu1->bp[nu1->pntsu - 1].f1 & SELECT)) {
+ nu1->flagu |= CU_NURB_CYCLIC;
+ BKE_nurb_knot_calc_u(nu1);
+ ok = true;
+ }
+ }
+ }
+
+ if (!ok) {
+ status.error_generic++;
+ continue;
+ }
+
+ if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ }
+
+ status.changed++;
+
+ curve_merge_tag_object:
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+ }
+ MEM_freeN(objects);
+
+ if (status.unselected == objects_len) {
+ BKE_report(op->reports, RPT_ERROR, "No points were selected");
+ return OPERATOR_CANCELLED;
+ }
+
+ const int tot_errors = status.error_selected_few + status.error_resolution +
+ status.error_generic;
+ if (tot_errors > 0) {
+ /* Some curves changed, but some curves failed: don't explain why it failed. */
+ if (status.changed) {
+ BKE_reportf(op->reports,
+ RPT_INFO,
+ tot_errors == 1 ? "%d curve could not make segments" :
+ "%d curves could not make segments",
+ tot_errors);
+ return OPERATOR_FINISHED;
+ }
+
+ /* All curves failed: If there is more than one error give a generic error report. */
+ if (((status.error_selected_few ? 1 : 0) + (status.error_resolution ? 1 : 0) +
+ (status.error_generic ? 1 : 0)) > 1) {
+ BKE_report(op->reports, RPT_ERROR, "Could not make new segments");
+ }
+
+ /* All curves failed due to the same error. */
+ if (status.error_selected_few) {
+ BKE_report(op->reports, RPT_ERROR, "Too few selections to merge");
+ }
+ else if (status.error_resolution) {
+ BKE_report(op->reports, RPT_ERROR, "Resolution does not match");
+ }
+ else {
+ BLI_assert(status.error_generic);
+ BKE_report(op->reports, RPT_ERROR, "Cannot make segment");
+ }
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
void CURVE_OT_make_segment(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Segment";
- ot->idname = "CURVE_OT_make_segment";
- ot->description = "Join two curves by their selected ends";
+ /* identifiers */
+ ot->name = "Make Segment";
+ ot->idname = "CURVE_OT_make_segment";
+ ot->description = "Join two curves by their selected ends";
- /* api callbacks */
- ot->exec = make_segment_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = make_segment_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/***************** pick select from 3d view **********************/
-bool ED_curve_editnurb_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
-{
- ViewContext vc;
- Nurb *nu;
- BezTriple *bezt = NULL;
- BPoint *bp = NULL;
- Base *basact = NULL;
- short hand;
-
- view3d_operator_needs_opengl(C);
- ED_view3d_viewcontext_init(C, &vc);
- copy_v2_v2_int(vc.mval, mval);
-
- if (ED_curve_pick_vert(&vc, 1, &nu, &bezt, &bp, &hand, &basact)) {
- Object *obedit = basact->object;
- Curve *cu = obedit->data;
- ListBase *editnurb = object_editcurve_get(obedit);
- const void *vert = BKE_curve_vert_active_get(cu);
-
- if (!extend && !deselect && !toggle) {
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob_iter = objects[ob_index];
-
- ED_curve_deselect_all(((Curve *)ob_iter->data)->editnurb);
-
- DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
- }
- MEM_freeN(objects);
- }
-
- if (extend) {
- if (bezt) {
- if (hand == 1) {
- select_beztriple(bezt, SELECT, SELECT, HIDDEN);
- }
- else {
- if (hand == 0) {
- bezt->f1 |= SELECT;
- }
- else {
- bezt->f3 |= SELECT;
- }
- }
- BKE_curve_nurb_vert_active_set(cu, nu, bezt);
- }
- else {
- select_bpoint(bp, SELECT, SELECT, HIDDEN);
- BKE_curve_nurb_vert_active_set(cu, nu, bp);
- }
- }
- else if (deselect) {
- if (bezt) {
- if (hand == 1) {
- select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
- if (bezt == vert) {
- cu->actvert = CU_ACT_NONE;
- }
- }
- else if (hand == 0) {
- bezt->f1 &= ~SELECT;
- }
- else {
- bezt->f3 &= ~SELECT;
- }
- }
- else {
- select_bpoint(bp, DESELECT, SELECT, HIDDEN);
- if (bp == vert) {
- cu->actvert = CU_ACT_NONE;
- }
- }
- }
- else if (toggle) {
- if (bezt) {
- if (hand == 1) {
- if (bezt->f2 & SELECT) {
- select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
- if (bezt == vert) {
- cu->actvert = CU_ACT_NONE;
- }
- }
- else {
- select_beztriple(bezt, SELECT, SELECT, HIDDEN);
- BKE_curve_nurb_vert_active_set(cu, nu, bezt);
- }
- }
- else if (hand == 0) {
- bezt->f1 ^= SELECT;
- }
- else {
- bezt->f3 ^= SELECT;
- }
- }
- else {
- if (bp->f1 & SELECT) {
- select_bpoint(bp, DESELECT, SELECT, HIDDEN);
- if (bp == vert) {
- cu->actvert = CU_ACT_NONE;
- }
- }
- else {
- select_bpoint(bp, SELECT, SELECT, HIDDEN);
- BKE_curve_nurb_vert_active_set(cu, nu, bp);
- }
- }
- }
- else {
- BKE_nurbList_flag_set(editnurb, 0);
-
- if (bezt) {
-
- if (hand == 1) {
- select_beztriple(bezt, SELECT, SELECT, HIDDEN);
- }
- else {
- if (hand == 0) {
- bezt->f1 |= SELECT;
- }
- else {
- bezt->f3 |= SELECT;
- }
- }
- BKE_curve_nurb_vert_active_set(cu, nu, bezt);
- }
- else {
- select_bpoint(bp, SELECT, SELECT, HIDDEN);
- BKE_curve_nurb_vert_active_set(cu, nu, bp);
- }
- }
-
- if (nu != BKE_curve_nurb_active_get(cu)) {
- cu->actvert = CU_ACT_NONE;
- BKE_curve_nurb_active_set(cu, nu);
- }
-
- if (vc.view_layer->basact != basact) {
- ED_object_base_activate(C, basact);
- }
-
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- return true;
- }
-
- return false;
+bool ED_curve_editnurb_select_pick(
+ bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
+{
+ ViewContext vc;
+ Nurb *nu;
+ BezTriple *bezt = NULL;
+ BPoint *bp = NULL;
+ Base *basact = NULL;
+ short hand;
+
+ view3d_operator_needs_opengl(C);
+ ED_view3d_viewcontext_init(C, &vc);
+ copy_v2_v2_int(vc.mval, mval);
+
+ if (ED_curve_pick_vert(&vc, 1, &nu, &bezt, &bp, &hand, &basact)) {
+ Object *obedit = basact->object;
+ Curve *cu = obedit->data;
+ ListBase *editnurb = object_editcurve_get(obedit);
+ const void *vert = BKE_curve_vert_active_get(cu);
+
+ if (!extend && !deselect && !toggle) {
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ vc.view_layer, vc.v3d, &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob_iter = objects[ob_index];
+
+ ED_curve_deselect_all(((Curve *)ob_iter->data)->editnurb);
+
+ DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
+ }
+ MEM_freeN(objects);
+ }
+
+ if (extend) {
+ if (bezt) {
+ if (hand == 1) {
+ select_beztriple(bezt, SELECT, SELECT, HIDDEN);
+ }
+ else {
+ if (hand == 0) {
+ bezt->f1 |= SELECT;
+ }
+ else {
+ bezt->f3 |= SELECT;
+ }
+ }
+ BKE_curve_nurb_vert_active_set(cu, nu, bezt);
+ }
+ else {
+ select_bpoint(bp, SELECT, SELECT, HIDDEN);
+ BKE_curve_nurb_vert_active_set(cu, nu, bp);
+ }
+ }
+ else if (deselect) {
+ if (bezt) {
+ if (hand == 1) {
+ select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
+ if (bezt == vert) {
+ cu->actvert = CU_ACT_NONE;
+ }
+ }
+ else if (hand == 0) {
+ bezt->f1 &= ~SELECT;
+ }
+ else {
+ bezt->f3 &= ~SELECT;
+ }
+ }
+ else {
+ select_bpoint(bp, DESELECT, SELECT, HIDDEN);
+ if (bp == vert) {
+ cu->actvert = CU_ACT_NONE;
+ }
+ }
+ }
+ else if (toggle) {
+ if (bezt) {
+ if (hand == 1) {
+ if (bezt->f2 & SELECT) {
+ select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
+ if (bezt == vert) {
+ cu->actvert = CU_ACT_NONE;
+ }
+ }
+ else {
+ select_beztriple(bezt, SELECT, SELECT, HIDDEN);
+ BKE_curve_nurb_vert_active_set(cu, nu, bezt);
+ }
+ }
+ else if (hand == 0) {
+ bezt->f1 ^= SELECT;
+ }
+ else {
+ bezt->f3 ^= SELECT;
+ }
+ }
+ else {
+ if (bp->f1 & SELECT) {
+ select_bpoint(bp, DESELECT, SELECT, HIDDEN);
+ if (bp == vert) {
+ cu->actvert = CU_ACT_NONE;
+ }
+ }
+ else {
+ select_bpoint(bp, SELECT, SELECT, HIDDEN);
+ BKE_curve_nurb_vert_active_set(cu, nu, bp);
+ }
+ }
+ }
+ else {
+ BKE_nurbList_flag_set(editnurb, 0);
+
+ if (bezt) {
+
+ if (hand == 1) {
+ select_beztriple(bezt, SELECT, SELECT, HIDDEN);
+ }
+ else {
+ if (hand == 0) {
+ bezt->f1 |= SELECT;
+ }
+ else {
+ bezt->f3 |= SELECT;
+ }
+ }
+ BKE_curve_nurb_vert_active_set(cu, nu, bezt);
+ }
+ else {
+ select_bpoint(bp, SELECT, SELECT, HIDDEN);
+ BKE_curve_nurb_vert_active_set(cu, nu, bp);
+ }
+ }
+
+ if (nu != BKE_curve_nurb_active_get(cu)) {
+ cu->actvert = CU_ACT_NONE;
+ BKE_curve_nurb_active_set(cu, nu);
+ }
+
+ if (vc.view_layer->basact != basact) {
+ ED_object_base_activate(C, basact);
+ }
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return true;
+ }
+
+ return false;
}
/******************** spin operator ***********************/
/* 'cent' is in object space and 'dvec' in worldspace.
*/
-bool ed_editnurb_spin(float viewmat[4][4], View3D *v3d, Object *obedit, const float axis[3], const float cent[3])
-{
- Curve *cu = (Curve *)obedit->data;
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- float cmat[3][3], tmat[3][3], imat[3][3];
- float bmat[3][3], rotmat[3][3], scalemat1[3][3], scalemat2[3][3];
- float persmat[3][3], persinv[3][3];
- bool ok, changed = false;
- int a;
-
- copy_m3_m4(persmat, viewmat);
- invert_m3_m3(persinv, persmat);
-
- /* imat and center and size */
- copy_m3_m4(bmat, obedit->obmat);
- invert_m3_m3(imat, bmat);
-
- axis_angle_to_mat3(cmat, axis, M_PI / 4.0);
- mul_m3_m3m3(tmat, cmat, bmat);
- mul_m3_m3m3(rotmat, imat, tmat);
-
- unit_m3(scalemat1);
- scalemat1[0][0] = M_SQRT2;
- scalemat1[1][1] = M_SQRT2;
-
- mul_m3_m3m3(tmat, persmat, bmat);
- mul_m3_m3m3(cmat, scalemat1, tmat);
- mul_m3_m3m3(tmat, persinv, cmat);
- mul_m3_m3m3(scalemat1, imat, tmat);
-
- unit_m3(scalemat2);
- scalemat2[0][0] /= (float)M_SQRT2;
- scalemat2[1][1] /= (float)M_SQRT2;
-
- mul_m3_m3m3(tmat, persmat, bmat);
- mul_m3_m3m3(cmat, scalemat2, tmat);
- mul_m3_m3m3(tmat, persinv, cmat);
- mul_m3_m3m3(scalemat2, imat, tmat);
-
- ok = true;
-
- for (a = 0; a < 7; a++) {
- ok = ed_editnurb_extrude_flag(cu->editnurb, SELECT);
-
- if (ok == false) {
- return changed;
- }
-
- changed = true;
-
- rotateflagNurb(editnurb, SELECT, cent, rotmat);
-
- if ((a & 1) == 0) {
- rotateflagNurb(editnurb, SELECT, cent, scalemat1);
- weightflagNurb(editnurb, SELECT, 0.25 * M_SQRT2);
- }
- else {
- rotateflagNurb(editnurb, SELECT, cent, scalemat2);
- weightflagNurb(editnurb, SELECT, 4.0 / M_SQRT2);
- }
- }
-
- if (ok) {
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (ED_curve_nurb_select_check(v3d, nu)) {
- nu->orderv = 4;
- nu->flagv |= CU_NURB_CYCLIC;
- BKE_nurb_knot_calc_v(nu);
- }
- }
- }
-
- return changed;
+bool ed_editnurb_spin(
+ float viewmat[4][4], View3D *v3d, Object *obedit, const float axis[3], const float cent[3])
+{
+ Curve *cu = (Curve *)obedit->data;
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ float cmat[3][3], tmat[3][3], imat[3][3];
+ float bmat[3][3], rotmat[3][3], scalemat1[3][3], scalemat2[3][3];
+ float persmat[3][3], persinv[3][3];
+ bool ok, changed = false;
+ int a;
+
+ copy_m3_m4(persmat, viewmat);
+ invert_m3_m3(persinv, persmat);
+
+ /* imat and center and size */
+ copy_m3_m4(bmat, obedit->obmat);
+ invert_m3_m3(imat, bmat);
+
+ axis_angle_to_mat3(cmat, axis, M_PI / 4.0);
+ mul_m3_m3m3(tmat, cmat, bmat);
+ mul_m3_m3m3(rotmat, imat, tmat);
+
+ unit_m3(scalemat1);
+ scalemat1[0][0] = M_SQRT2;
+ scalemat1[1][1] = M_SQRT2;
+
+ mul_m3_m3m3(tmat, persmat, bmat);
+ mul_m3_m3m3(cmat, scalemat1, tmat);
+ mul_m3_m3m3(tmat, persinv, cmat);
+ mul_m3_m3m3(scalemat1, imat, tmat);
+
+ unit_m3(scalemat2);
+ scalemat2[0][0] /= (float)M_SQRT2;
+ scalemat2[1][1] /= (float)M_SQRT2;
+
+ mul_m3_m3m3(tmat, persmat, bmat);
+ mul_m3_m3m3(cmat, scalemat2, tmat);
+ mul_m3_m3m3(tmat, persinv, cmat);
+ mul_m3_m3m3(scalemat2, imat, tmat);
+
+ ok = true;
+
+ for (a = 0; a < 7; a++) {
+ ok = ed_editnurb_extrude_flag(cu->editnurb, SELECT);
+
+ if (ok == false) {
+ return changed;
+ }
+
+ changed = true;
+
+ rotateflagNurb(editnurb, SELECT, cent, rotmat);
+
+ if ((a & 1) == 0) {
+ rotateflagNurb(editnurb, SELECT, cent, scalemat1);
+ weightflagNurb(editnurb, SELECT, 0.25 * M_SQRT2);
+ }
+ else {
+ rotateflagNurb(editnurb, SELECT, cent, scalemat2);
+ weightflagNurb(editnurb, SELECT, 4.0 / M_SQRT2);
+ }
+ }
+
+ if (ok) {
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (ED_curve_nurb_select_check(v3d, nu)) {
+ nu->orderv = 4;
+ nu->flagv |= CU_NURB_CYCLIC;
+ BKE_nurb_knot_calc_v(nu);
+ }
+ }
+ }
+
+ return changed;
}
static int spin_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = ED_view3d_context_rv3d(C);
- float cent[3], axis[3], viewmat[4][4];
- int ok = -1;
-
- RNA_float_get_array(op->ptr, "center", cent);
- RNA_float_get_array(op->ptr, "axis", axis);
-
- if (rv3d) {
- copy_m4_m4(viewmat, rv3d->viewmat);
- }
- else {
- unit_m4(viewmat);
- }
-
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Curve *cu = (Curve *)obedit->data;
-
- if (!ED_curve_select_check(v3d, cu->editnurb)) {
- continue;
- }
-
- invert_m4_m4(obedit->imat, obedit->obmat);
- mul_m4_v3(obedit->imat, cent);
-
- if (!ed_editnurb_spin(viewmat, v3d, obedit, axis, cent)) {
- ok = MAX2(ok, 0);
- continue;
- }
-
- ok = 1;
- if (ED_curve_updateAnimPaths(bmain, cu)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
- }
- MEM_freeN(objects);
-
- if (ok == 0) {
- BKE_report(op->reports, RPT_ERROR, "Cannot spin");
- }
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = ED_view3d_context_rv3d(C);
+ float cent[3], axis[3], viewmat[4][4];
+ int ok = -1;
+
+ RNA_float_get_array(op->ptr, "center", cent);
+ RNA_float_get_array(op->ptr, "axis", axis);
+
+ if (rv3d) {
+ copy_m4_m4(viewmat, rv3d->viewmat);
+ }
+ else {
+ unit_m4(viewmat);
+ }
+
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Curve *cu = (Curve *)obedit->data;
+
+ if (!ED_curve_select_check(v3d, cu->editnurb)) {
+ continue;
+ }
+
+ invert_m4_m4(obedit->imat, obedit->obmat);
+ mul_m4_v3(obedit->imat, cent);
+
+ if (!ed_editnurb_spin(viewmat, v3d, obedit, axis, cent)) {
+ ok = MAX2(ok, 0);
+ continue;
+ }
+
+ ok = 1;
+ if (ED_curve_updateAnimPaths(bmain, cu)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+ }
+ MEM_freeN(objects);
+
+ if (ok == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot spin");
+ }
+ return OPERATOR_FINISHED;
}
static int spin_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Scene *scene = CTX_data_scene(C);
- RegionView3D *rv3d = ED_view3d_context_rv3d(C);
- float axis[3] = {0.0f, 0.0f, 1.0f};
+ Scene *scene = CTX_data_scene(C);
+ RegionView3D *rv3d = ED_view3d_context_rv3d(C);
+ float axis[3] = {0.0f, 0.0f, 1.0f};
- if (rv3d) {
- copy_v3_v3(axis, rv3d->viewinv[2]);
- }
+ if (rv3d) {
+ copy_v3_v3(axis, rv3d->viewinv[2]);
+ }
- RNA_float_set_array(op->ptr, "center", scene->cursor.location);
- RNA_float_set_array(op->ptr, "axis", axis);
+ RNA_float_set_array(op->ptr, "center", scene->cursor.location);
+ RNA_float_set_array(op->ptr, "axis", axis);
- return spin_exec(C, op);
+ return spin_exec(C, op);
}
void CURVE_OT_spin(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Spin";
- ot->idname = "CURVE_OT_spin";
- ot->description = "Extrude selected boundary row around pivot point and current view axis";
-
- /* api callbacks */
- ot->exec = spin_exec;
- ot->invoke = spin_invoke;
- ot->poll = ED_operator_editsurf;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_float_vector_xyz(ot->srna, "center", 3, NULL, -OBJECT_ADD_SIZE_MAXF, OBJECT_ADD_SIZE_MAXF,
- "Center", "Center in global view space", -1000.0f, 1000.0f);
- RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -1.0f, 1.0f);
+ /* identifiers */
+ ot->name = "Spin";
+ ot->idname = "CURVE_OT_spin";
+ ot->description = "Extrude selected boundary row around pivot point and current view axis";
+
+ /* api callbacks */
+ ot->exec = spin_exec;
+ ot->invoke = spin_invoke;
+ ot->poll = ED_operator_editsurf;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_float_vector_xyz(ot->srna,
+ "center",
+ 3,
+ NULL,
+ -OBJECT_ADD_SIZE_MAXF,
+ OBJECT_ADD_SIZE_MAXF,
+ "Center",
+ "Center in global view space",
+ -1000.0f,
+ 1000.0f);
+ RNA_def_float_vector(
+ ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -1.0f, 1.0f);
}
/***************** 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;
- union {
- BezTriple *bezt;
- BPoint *bp;
- void *p;
- } cu_actvert;
+ Nurb *nu = NULL;
+ Nurb *nu_last = NULL;
- if (BLI_listbase_is_empty(&editnurb->nurbs)) {
- return changed;
- }
+ bool changed = false;
- BKE_curve_nurb_vert_active_get(cu, &cu_actnu, &cu_actvert.p);
- BKE_curve_nurb_vert_active_set(cu, NULL, NULL);
+ Nurb *cu_actnu;
+ union {
+ BezTriple *bezt;
+ BPoint *bp;
+ void *p;
+ } cu_actvert;
- /* first pass (endpoints) */
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ if (BLI_listbase_is_empty(&editnurb->nurbs)) {
+ return changed;
+ }
- if ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) {
- continue;
- }
+ 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->type == CU_BEZIER) {
+ if ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) {
+ continue;
+ }
- /* 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 (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);
+ 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;
+ 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;
- MEM_freeN(nu->bezt);
- nu->bezt = bezt_new;
+ nu->pntsu += 1;
- 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);
+ }
- 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;
+ }
+ }
- BEZT_SEL_ALL(bezt_new);
- changed = true;
- }
- }
-
- /* 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);
- }
-
- BEZT_SEL_ALL(bezt_new);
- changed = true;
- }
- }
- }
- 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;
- }
- }
-
- /* 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;
-
- bp_new += nu->pntsu;
- nu->pntsu += 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);
- }
-
- BKE_nurb_knot_calc_u(nu);
-
- bp_new->f1 |= SELECT;
- changed = true;
- }
- }
- }
- }
-
- /* 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 ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) {
- /* all points are interior */
- i = 0;
- i_end = nu->pntsu;
- }
- else {
- /* skip endpoints */
- i = 1;
- i_end = nu->pntsu - 1;
- }
-
- if (nu->type == CU_BEZIER) {
- BezTriple *bezt;
-
- for (bezt = &nu->bezt[i]; i < i_end; i++, bezt++) {
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
- Nurb *nurb_new;
- BezTriple *bezt_new;
-
- 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);
-
- if (cu_actvert.bezt == bezt || cu_actnu == NULL) {
- BKE_curve_nurb_vert_active_set(cu, nurb_new, bezt_new);
- }
-
- changed = true;
- }
- }
- }
- else {
- BPoint *bp;
-
- for (bp = &nu->bp[i]; i < i_end; i++, bp++) {
- if (bp->f1 & SELECT) {
- Nurb *nurb_new;
- BPoint *bp_new;
-
- 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 (cu_actvert.bp == bp || cu_actnu == NULL) {
- BKE_curve_nurb_vert_active_set(cu, nurb_new, bp_new);
- }
-
- changed = true;
- }
- }
- }
- }
-
- if (changed == false) {
- BKE_curve_nurb_vert_active_set(cu, cu_actnu, cu_actvert.p);
- }
-
- return changed;
+ /* 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);
+ }
+
+ BEZT_SEL_ALL(bezt_new);
+ changed = true;
+ }
+ }
+ }
+ 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;
+ }
+ }
+
+ /* 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;
+
+ bp_new += nu->pntsu;
+ nu->pntsu += 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);
+ }
+
+ BKE_nurb_knot_calc_u(nu);
+
+ bp_new->f1 |= SELECT;
+ changed = true;
+ }
+ }
+ }
+ }
+
+ /* 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 ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) {
+ /* all points are interior */
+ i = 0;
+ i_end = nu->pntsu;
+ }
+ else {
+ /* skip endpoints */
+ i = 1;
+ i_end = nu->pntsu - 1;
+ }
+
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt;
+
+ for (bezt = &nu->bezt[i]; i < i_end; i++, bezt++) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
+ Nurb *nurb_new;
+ BezTriple *bezt_new;
+
+ 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);
+
+ if (cu_actvert.bezt == bezt || cu_actnu == NULL) {
+ BKE_curve_nurb_vert_active_set(cu, nurb_new, bezt_new);
+ }
+
+ changed = true;
+ }
+ }
+ }
+ else {
+ BPoint *bp;
+
+ for (bp = &nu->bp[i]; i < i_end; i++, bp++) {
+ if (bp->f1 & SELECT) {
+ Nurb *nurb_new;
+ BPoint *bp_new;
+
+ 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 (cu_actvert.bp == bp || cu_actnu == NULL) {
+ BKE_curve_nurb_vert_active_set(cu, nurb_new, bp_new);
+ }
+
+ changed = true;
+ }
+ }
+ }
+ }
+
+ if (changed == false) {
+ BKE_curve_nurb_vert_active_set(cu, cu_actnu, cu_actvert.p);
+ }
+
+ return changed;
}
/***************** add vertex operator **********************/
-static int ed_editcurve_addvert(Curve *cu, EditNurb *editnurb, View3D *v3d, const float location_init[3])
-{
- Nurb *nu;
-
- float center[3];
- float temp[3];
- uint verts_len;
- bool changed = false;
-
- zero_v3(center);
- verts_len = 0;
-
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
- int i;
- if (nu->type == CU_BEZIER) {
- BezTriple *bezt;
-
- for (i = 0, bezt = nu->bezt; i < nu->pntsu; i++, bezt++) {
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
- add_v3_v3(center, bezt->vec[1]);
- verts_len += 1;
- }
- }
- }
- else {
- BPoint *bp;
-
- for (i = 0, bp = nu->bp; i < nu->pntsu; i++, bp++) {
- if (bp->f1 & SELECT) {
- add_v3_v3(center, bp->vec);
- verts_len += 1;
- }
- }
- }
- }
-
- if (verts_len && ed_editcurve_extrude(cu, editnurb, v3d)) {
- float ofs[3];
- int i;
-
- mul_v3_fl(center, 1.0f / (float)verts_len);
- sub_v3_v3v3(ofs, location_init, center);
-
- if ((cu->flag & CU_3D) == 0) {
- ofs[2] = 0.0f;
- }
-
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- BezTriple *bezt;
- for (i = 0, bezt = nu->bezt; i < nu->pntsu; i++, bezt++) {
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
- add_v3_v3(bezt->vec[0], ofs);
- add_v3_v3(bezt->vec[1], ofs);
- add_v3_v3(bezt->vec[2], ofs);
-
- if (((nu->flagu & CU_NURB_CYCLIC) == 0) &&
- (i == 0 || i == nu->pntsu - 1))
- {
- BKE_nurb_handle_calc_simple_auto(nu, bezt);
- }
- }
- }
-
- BKE_nurb_handles_calc(nu);
- }
- else {
- BPoint *bp;
-
- for (i = 0, bp = nu->bp; i < nu->pntsu; i++, bp++) {
- if (bp->f1 & SELECT) {
- add_v3_v3(bp->vec, ofs);
- }
- }
- }
- }
- changed = true;
- }
- else {
- float location[3];
-
- copy_v3_v3(location, location_init);
-
- if ((cu->flag & CU_3D) == 0) {
- location[2] = 0.0f;
- }
-
- /* nothing selected: create a new curve */
- nu = BKE_curve_nurb_active_get(cu);
-
- if (!nu || nu->type == CU_BEZIER) {
- Nurb *nurb_new;
- BezTriple *bezt_new;
-
- if (nu) {
- nurb_new = BKE_nurb_copy(nu, 1, 1);
- }
- else {
- nurb_new = MEM_callocN(sizeof(Nurb), "BLI_editcurve_addvert new_bezt_nurb 2");
- nurb_new->type = CU_BEZIER;
- nurb_new->resolu = cu->resolu;
- nurb_new->orderu = 4;
- nurb_new->flag |= CU_SMOOTH;
- BKE_nurb_bezierPoints_add(nurb_new, 1);
-
- if ((cu->flag & CU_3D) == 0) {
- nurb_new->flag |= CU_2D;
- }
- }
- BLI_addtail(&editnurb->nurbs, nurb_new);
-
- bezt_new = nurb_new->bezt;
-
- BEZT_SEL_ALL(bezt_new);
-
- bezt_new->h1 = HD_AUTO;
- bezt_new->h2 = HD_AUTO;
-
- temp[0] = 1.0f;
- temp[1] = 0.0f;
- temp[2] = 0.0f;
-
- copy_v3_v3(bezt_new->vec[1], location);
- sub_v3_v3v3(bezt_new->vec[0], bezt_new->vec[1], temp);
- add_v3_v3v3(bezt_new->vec[2], bezt_new->vec[1], temp);
-
- changed = true;
- }
- else {
- Nurb *nurb_new;
- BPoint *bp_new;
-
- {
- nurb_new = MEM_callocN(sizeof(Nurb), __func__);
- nurb_new->type = CU_POLY;
- nurb_new->resolu = cu->resolu;
- nurb_new->flag |= CU_SMOOTH;
- nurb_new->orderu = 4;
- BKE_nurb_points_add(nurb_new, 1);
-
- if ((cu->flag & CU_3D) == 0) {
- nurb_new->flag |= CU_2D;
- }
- }
- BLI_addtail(&editnurb->nurbs, nurb_new);
-
- bp_new = nurb_new->bp;
-
- bp_new->f1 |= SELECT;
-
- copy_v3_v3(bp_new->vec, location);
- bp_new->vec[3] = 1.0f;
-
- BKE_nurb_knot_calc_u(nurb_new);
-
- changed = true;
- }
- }
-
- return changed;
+static int ed_editcurve_addvert(Curve *cu,
+ EditNurb *editnurb,
+ View3D *v3d,
+ const float location_init[3])
+{
+ Nurb *nu;
+
+ float center[3];
+ float temp[3];
+ uint verts_len;
+ bool changed = false;
+
+ zero_v3(center);
+ verts_len = 0;
+
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ int i;
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt;
+
+ for (i = 0, bezt = nu->bezt; i < nu->pntsu; i++, bezt++) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
+ add_v3_v3(center, bezt->vec[1]);
+ verts_len += 1;
+ }
+ }
+ }
+ else {
+ BPoint *bp;
+
+ for (i = 0, bp = nu->bp; i < nu->pntsu; i++, bp++) {
+ if (bp->f1 & SELECT) {
+ add_v3_v3(center, bp->vec);
+ verts_len += 1;
+ }
+ }
+ }
+ }
+
+ if (verts_len && ed_editcurve_extrude(cu, editnurb, v3d)) {
+ float ofs[3];
+ int i;
+
+ mul_v3_fl(center, 1.0f / (float)verts_len);
+ sub_v3_v3v3(ofs, location_init, center);
+
+ if ((cu->flag & CU_3D) == 0) {
+ ofs[2] = 0.0f;
+ }
+
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt;
+ for (i = 0, bezt = nu->bezt; i < nu->pntsu; i++, bezt++) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
+ add_v3_v3(bezt->vec[0], ofs);
+ add_v3_v3(bezt->vec[1], ofs);
+ add_v3_v3(bezt->vec[2], ofs);
+
+ if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (i == 0 || i == nu->pntsu - 1)) {
+ BKE_nurb_handle_calc_simple_auto(nu, bezt);
+ }
+ }
+ }
+
+ BKE_nurb_handles_calc(nu);
+ }
+ else {
+ BPoint *bp;
+
+ for (i = 0, bp = nu->bp; i < nu->pntsu; i++, bp++) {
+ if (bp->f1 & SELECT) {
+ add_v3_v3(bp->vec, ofs);
+ }
+ }
+ }
+ }
+ changed = true;
+ }
+ else {
+ float location[3];
+
+ copy_v3_v3(location, location_init);
+
+ if ((cu->flag & CU_3D) == 0) {
+ location[2] = 0.0f;
+ }
+
+ /* nothing selected: create a new curve */
+ nu = BKE_curve_nurb_active_get(cu);
+
+ if (!nu || nu->type == CU_BEZIER) {
+ Nurb *nurb_new;
+ BezTriple *bezt_new;
+
+ if (nu) {
+ nurb_new = BKE_nurb_copy(nu, 1, 1);
+ }
+ else {
+ nurb_new = MEM_callocN(sizeof(Nurb), "BLI_editcurve_addvert new_bezt_nurb 2");
+ nurb_new->type = CU_BEZIER;
+ nurb_new->resolu = cu->resolu;
+ nurb_new->orderu = 4;
+ nurb_new->flag |= CU_SMOOTH;
+ BKE_nurb_bezierPoints_add(nurb_new, 1);
+
+ if ((cu->flag & CU_3D) == 0) {
+ nurb_new->flag |= CU_2D;
+ }
+ }
+ BLI_addtail(&editnurb->nurbs, nurb_new);
+
+ bezt_new = nurb_new->bezt;
+
+ BEZT_SEL_ALL(bezt_new);
+
+ bezt_new->h1 = HD_AUTO;
+ bezt_new->h2 = HD_AUTO;
+
+ temp[0] = 1.0f;
+ temp[1] = 0.0f;
+ temp[2] = 0.0f;
+
+ copy_v3_v3(bezt_new->vec[1], location);
+ sub_v3_v3v3(bezt_new->vec[0], bezt_new->vec[1], temp);
+ add_v3_v3v3(bezt_new->vec[2], bezt_new->vec[1], temp);
+
+ changed = true;
+ }
+ else {
+ Nurb *nurb_new;
+ BPoint *bp_new;
+
+ {
+ nurb_new = MEM_callocN(sizeof(Nurb), __func__);
+ nurb_new->type = CU_POLY;
+ nurb_new->resolu = cu->resolu;
+ nurb_new->flag |= CU_SMOOTH;
+ nurb_new->orderu = 4;
+ BKE_nurb_points_add(nurb_new, 1);
+
+ if ((cu->flag & CU_3D) == 0) {
+ nurb_new->flag |= CU_2D;
+ }
+ }
+ BLI_addtail(&editnurb->nurbs, nurb_new);
+
+ bp_new = nurb_new->bp;
+
+ bp_new->f1 |= SELECT;
+
+ copy_v3_v3(bp_new->vec, location);
+ bp_new->vec[3] = 1.0f;
+
+ BKE_nurb_knot_calc_u(nurb_new);
+
+ changed = true;
+ }
+ }
+
+ return changed;
}
static int add_vertex_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *obedit = CTX_data_edit_object(C);
- View3D *v3d = CTX_wm_view3d(C);
- Curve *cu = obedit->data;
- EditNurb *editnurb = cu->editnurb;
- float location[3];
- float imat[4][4];
+ Main *bmain = CTX_data_main(C);
+ Object *obedit = CTX_data_edit_object(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Curve *cu = obedit->data;
+ EditNurb *editnurb = cu->editnurb;
+ float location[3];
+ float imat[4][4];
- RNA_float_get_array(op->ptr, "location", location);
+ RNA_float_get_array(op->ptr, "location", location);
- invert_m4_m4(imat, obedit->obmat);
- mul_m4_v3(imat, location);
+ invert_m4_m4(imat, obedit->obmat);
+ mul_m4_v3(imat, location);
- if (ed_editcurve_addvert(cu, editnurb, v3d, location)) {
- if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
- }
+ if (ed_editcurve_addvert(cu, editnurb, v3d, location)) {
+ if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ }
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewContext vc;
-
- ED_view3d_viewcontext_init(C, &vc);
-
- if (vc.rv3d && !RNA_struct_property_is_set(op->ptr, "location")) {
- Curve *cu;
- float location[3];
- const bool use_proj = ((vc.scene->toolsettings->snap_flag & SCE_SNAP) &&
- (vc.scene->toolsettings->snap_mode == SCE_SNAP_MODE_FACE));
-
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
-
- cu = vc.obedit->data;
-
- findselectedNurbvert(cu, vc.v3d, &nu, &bezt, &bp);
-
- if (bezt) {
- mul_v3_m4v3(location, vc.obedit->obmat, bezt->vec[1]);
- }
- else if (bp) {
- mul_v3_m4v3(location, vc.obedit->obmat, bp->vec);
- }
- else {
- copy_v3_v3(location, vc.scene->cursor.location);
- }
-
- ED_view3d_win_to_3d_int(vc.v3d, vc.ar, 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);
-
- ED_transform_snap_object_project_view3d(
- snap_context,
- SCE_SNAP_MODE_FACE,
- &(const struct SnapObjectParams){
- .snap_select = (vc.obedit != NULL) ? SNAP_NOT_ACTIVE : SNAP_ALL,
- .use_object_edit_cage = false,
- },
- mval, NULL,
- location, NULL);
-
-
- ED_transform_snap_object_context_destroy(snap_context);
- }
-
- if ((cu->flag & CU_3D) == 0) {
- const float eps = 1e-6f;
-
- /* get the view vector to 'location' */
- float view_dir[3];
- ED_view3d_global_to_vector(vc.rv3d, location, view_dir);
-
- /* get the plane */
- float plane[4];
- /* only normalize to avoid precision errors */
- normalize_v3_v3(plane, vc.obedit->obmat[2]);
- plane[3] = -dot_v3v3(plane, vc.obedit->obmat[3]);
-
- if (fabsf(dot_v3v3(view_dir, plane)) < eps) {
- /* can't project on an aligned plane. */
- }
- else {
- float lambda;
- if (isect_ray_plane_v3(location, view_dir, plane, &lambda, false)) {
- /* check if we're behind the viewport */
- float location_test[3];
- madd_v3_v3v3fl(location_test, location, view_dir, lambda);
- if ((vc.rv3d->is_persp == false) ||
- (mul_project_m4_v3_zfac(vc.rv3d->persmat, location_test) > 0.0f))
- {
- copy_v3_v3(location, location_test);
- }
- }
- }
- }
-
- RNA_float_set_array(op->ptr, "location", location);
- }
-
- return add_vertex_exec(C, op);
+ ViewContext vc;
+
+ ED_view3d_viewcontext_init(C, &vc);
+
+ if (vc.rv3d && !RNA_struct_property_is_set(op->ptr, "location")) {
+ Curve *cu;
+ float location[3];
+ const bool use_proj = ((vc.scene->toolsettings->snap_flag & SCE_SNAP) &&
+ (vc.scene->toolsettings->snap_mode == SCE_SNAP_MODE_FACE));
+
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+
+ cu = vc.obedit->data;
+
+ findselectedNurbvert(cu, vc.v3d, &nu, &bezt, &bp);
+
+ if (bezt) {
+ mul_v3_m4v3(location, vc.obedit->obmat, bezt->vec[1]);
+ }
+ else if (bp) {
+ mul_v3_m4v3(location, vc.obedit->obmat, bp->vec);
+ }
+ else {
+ copy_v3_v3(location, vc.scene->cursor.location);
+ }
+
+ ED_view3d_win_to_3d_int(vc.v3d, vc.ar, 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);
+
+ ED_transform_snap_object_project_view3d(
+ snap_context,
+ SCE_SNAP_MODE_FACE,
+ &(const struct SnapObjectParams){
+ .snap_select = (vc.obedit != NULL) ? SNAP_NOT_ACTIVE : SNAP_ALL,
+ .use_object_edit_cage = false,
+ },
+ mval,
+ NULL,
+ location,
+ NULL);
+
+ ED_transform_snap_object_context_destroy(snap_context);
+ }
+
+ if ((cu->flag & CU_3D) == 0) {
+ const float eps = 1e-6f;
+
+ /* get the view vector to 'location' */
+ float view_dir[3];
+ ED_view3d_global_to_vector(vc.rv3d, location, view_dir);
+
+ /* get the plane */
+ float plane[4];
+ /* only normalize to avoid precision errors */
+ normalize_v3_v3(plane, vc.obedit->obmat[2]);
+ plane[3] = -dot_v3v3(plane, vc.obedit->obmat[3]);
+
+ if (fabsf(dot_v3v3(view_dir, plane)) < eps) {
+ /* can't project on an aligned plane. */
+ }
+ else {
+ float lambda;
+ if (isect_ray_plane_v3(location, view_dir, plane, &lambda, false)) {
+ /* check if we're behind the viewport */
+ float location_test[3];
+ madd_v3_v3v3fl(location_test, location, view_dir, lambda);
+ if ((vc.rv3d->is_persp == false) ||
+ (mul_project_m4_v3_zfac(vc.rv3d->persmat, location_test) > 0.0f)) {
+ copy_v3_v3(location, location_test);
+ }
+ }
+ }
+ }
+
+ RNA_float_set_array(op->ptr, "location", location);
+ }
+
+ return add_vertex_exec(C, op);
}
void CURVE_OT_vertex_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Vertex";
- ot->idname = "CURVE_OT_vertex_add";
- ot->description = "Add a new control point (linked to only selected end-curve one, if any)";
+ /* identifiers */
+ ot->name = "Add Vertex";
+ ot->idname = "CURVE_OT_vertex_add";
+ ot->description = "Add a new control point (linked to only selected end-curve one, if any)";
- /* api callbacks */
- ot->exec = add_vertex_exec;
- ot->invoke = add_vertex_invoke;
- ot->poll = ED_operator_editcurve;
+ /* api callbacks */
+ ot->exec = add_vertex_exec;
+ ot->invoke = add_vertex_invoke;
+ ot->poll = ED_operator_editcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_float_vector_xyz(ot->srna, "location", 3, NULL, -OBJECT_ADD_SIZE_MAXF, OBJECT_ADD_SIZE_MAXF,
- "Location", "Location to add new vertex at", -1.0e4f, 1.0e4f);
+ /* properties */
+ RNA_def_float_vector_xyz(ot->srna,
+ "location",
+ 3,
+ NULL,
+ -OBJECT_ADD_SIZE_MAXF,
+ OBJECT_ADD_SIZE_MAXF,
+ "Location",
+ "Location to add new vertex at",
+ -1.0e4f,
+ 1.0e4f);
}
/***************** extrude operator **********************/
static int curve_extrude_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
-
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Curve *cu = obedit->data;
- EditNurb *editnurb = cu->editnurb;
- bool changed = false;
- bool as_curve = false;
-
- if (!ED_curve_select_check(v3d, cu->editnurb)) {
- continue;
- }
-
- /* First test: curve? */
- if (obedit->type != OB_CURVE) {
- Nurb *nu;
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
- if ((nu->pntsv == 1) &&
- (ED_curve_nurb_select_count(v3d, nu) == 1))
- {
- as_curve = true;
- break;
- }
- }
- }
-
- if (obedit->type == OB_CURVE || as_curve) {
- changed = ed_editcurve_extrude(cu, editnurb, v3d);
- }
- else {
- changed = ed_editnurb_extrude_flag(editnurb, SELECT);
- }
-
- if (changed) {
- if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
- }
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Curve *cu = obedit->data;
+ EditNurb *editnurb = cu->editnurb;
+ bool changed = false;
+ bool as_curve = false;
+
+ if (!ED_curve_select_check(v3d, cu->editnurb)) {
+ continue;
+ }
+
+ /* First test: curve? */
+ if (obedit->type != OB_CURVE) {
+ Nurb *nu;
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ if ((nu->pntsv == 1) && (ED_curve_nurb_select_count(v3d, nu) == 1)) {
+ as_curve = true;
+ break;
+ }
+ }
+ }
+
+ if (obedit->type == OB_CURVE || as_curve) {
+ changed = ed_editcurve_extrude(cu, editnurb, v3d);
+ }
+ else {
+ changed = ed_editnurb_extrude_flag(editnurb, SELECT);
+ }
+
+ if (changed) {
+ if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+ }
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void CURVE_OT_extrude(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Extrude";
- ot->description = "Extrude selected control point(s)";
- ot->idname = "CURVE_OT_extrude";
+ /* identifiers */
+ ot->name = "Extrude";
+ ot->description = "Extrude selected control point(s)";
+ ot->idname = "CURVE_OT_extrude";
- /* api callbacks */
- ot->exec = curve_extrude_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = curve_extrude_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* to give to transform */
- RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
+ /* to give to transform */
+ RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
}
/***************** make cyclic operator **********************/
static bool curve_toggle_cyclic(View3D *v3d, ListBase *editnurb, int direction)
{
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
- bool changed = false;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->pntsu > 1 || nu->pntsv > 1) {
- if (nu->type == CU_POLY) {
- a = nu->pntsu;
- bp = nu->bp;
- while (a--) {
- if (bp->f1 & SELECT) {
- nu->flagu ^= CU_NURB_CYCLIC;
- changed = true;
- break;
- }
- bp++;
- }
- }
- else if (nu->type == CU_BEZIER) {
- a = nu->pntsu;
- bezt = nu->bezt;
- while (a--) {
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
- nu->flagu ^= CU_NURB_CYCLIC;
- changed = true;
- break;
- }
- bezt++;
- }
- BKE_nurb_handles_calc(nu);
- }
- else if (nu->pntsv == 1 && nu->type == CU_NURBS) {
- if (nu->knotsu) { /* if check_valid_nurb_u fails the knotsu can be NULL */
- a = nu->pntsu;
- bp = nu->bp;
- while (a--) {
- if (bp->f1 & SELECT) {
- nu->flagu ^= CU_NURB_CYCLIC;
- /* 1==u type is ignored for cyclic curves */
- BKE_nurb_knot_calc_u(nu);
- changed = true;
- break;
- }
- bp++;
- }
- }
- }
- else if (nu->type == CU_NURBS) {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a--) {
-
- if (bp->f1 & SELECT) {
- if (direction == 0 && nu->pntsu > 1) {
- nu->flagu ^= CU_NURB_CYCLIC;
- /* 1==u type is ignored for cyclic curves */
- BKE_nurb_knot_calc_u(nu);
- changed = true;
- }
- if (direction == 1 && nu->pntsv > 1) {
- nu->flagv ^= CU_NURB_CYCLIC;
- /* 2==v type is ignored for cyclic curves */
- BKE_nurb_knot_calc_v(nu);
- changed = true;
- }
- break;
- }
- bp++;
- }
- }
- }
- }
- return changed;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+ bool changed = false;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->pntsu > 1 || nu->pntsv > 1) {
+ if (nu->type == CU_POLY) {
+ a = nu->pntsu;
+ bp = nu->bp;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ nu->flagu ^= CU_NURB_CYCLIC;
+ changed = true;
+ break;
+ }
+ bp++;
+ }
+ }
+ else if (nu->type == CU_BEZIER) {
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ while (a--) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
+ nu->flagu ^= CU_NURB_CYCLIC;
+ changed = true;
+ break;
+ }
+ bezt++;
+ }
+ BKE_nurb_handles_calc(nu);
+ }
+ else if (nu->pntsv == 1 && nu->type == CU_NURBS) {
+ if (nu->knotsu) { /* if check_valid_nurb_u fails the knotsu can be NULL */
+ a = nu->pntsu;
+ bp = nu->bp;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ nu->flagu ^= CU_NURB_CYCLIC;
+ /* 1==u type is ignored for cyclic curves */
+ BKE_nurb_knot_calc_u(nu);
+ changed = true;
+ break;
+ }
+ bp++;
+ }
+ }
+ }
+ else if (nu->type == CU_NURBS) {
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a--) {
+
+ if (bp->f1 & SELECT) {
+ if (direction == 0 && nu->pntsu > 1) {
+ nu->flagu ^= CU_NURB_CYCLIC;
+ /* 1==u type is ignored for cyclic curves */
+ BKE_nurb_knot_calc_u(nu);
+ changed = true;
+ }
+ if (direction == 1 && nu->pntsv > 1) {
+ nu->flagv ^= CU_NURB_CYCLIC;
+ /* 2==v type is ignored for cyclic curves */
+ BKE_nurb_knot_calc_v(nu);
+ changed = true;
+ }
+ break;
+ }
+ bp++;
+ }
+ }
+ }
+ }
+ return changed;
}
static int toggle_cyclic_exec(bContext *C, wmOperator *op)
{
- const int direction = RNA_enum_get(op->ptr, "direction");
- View3D *v3d = CTX_wm_view3d(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- bool changed_multi = false;
+ const int direction = RNA_enum_get(op->ptr, "direction");
+ View3D *v3d = CTX_wm_view3d(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ bool changed_multi = false;
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Curve *cu = obedit->data;
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Curve *cu = obedit->data;
- if (!ED_curve_select_check(v3d, cu->editnurb)) {
- continue;
- }
+ if (!ED_curve_select_check(v3d, cu->editnurb)) {
+ continue;
+ }
- ListBase *editnurb = object_editcurve_get(obedit);
- if (curve_toggle_cyclic(v3d, editnurb, direction)) {
- changed_multi = true;
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
- }
- }
- MEM_freeN(objects);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ if (curve_toggle_cyclic(v3d, editnurb, direction)) {
+ changed_multi = true;
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+ }
+ }
+ MEM_freeN(objects);
- return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static int toggle_cyclic_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
- uiPopupMenu *pup;
- uiLayout *layout;
- Nurb *nu;
-
- if (obedit->type == OB_SURF) {
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->pntsu > 1 || nu->pntsv > 1) {
- if (nu->type == CU_NURBS) {
- pup = UI_popup_menu_begin(C, IFACE_("Direction"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
- uiItemsEnumO(layout, op->type->idname, "direction");
- UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
- }
- }
- }
- }
-
- return toggle_cyclic_exec(C, op);
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ uiPopupMenu *pup;
+ uiLayout *layout;
+ Nurb *nu;
+
+ if (obedit->type == OB_SURF) {
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->pntsu > 1 || nu->pntsv > 1) {
+ if (nu->type == CU_NURBS) {
+ pup = UI_popup_menu_begin(C, IFACE_("Direction"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ uiItemsEnumO(layout, op->type->idname, "direction");
+ UI_popup_menu_end(C, pup);
+ return OPERATOR_INTERFACE;
+ }
+ }
+ }
+ }
+
+ return toggle_cyclic_exec(C, op);
}
void CURVE_OT_cyclic_toggle(wmOperatorType *ot)
{
- static const EnumPropertyItem direction_items[] = {
- {0, "CYCLIC_U", 0, "Cyclic U", ""},
- {1, "CYCLIC_V", 0, "Cyclic V", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem direction_items[] = {
+ {0, "CYCLIC_U", 0, "Cyclic U", ""},
+ {1, "CYCLIC_V", 0, "Cyclic V", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Toggle Cyclic";
- ot->description = "Make active spline closed/opened loop";
- ot->idname = "CURVE_OT_cyclic_toggle";
+ /* identifiers */
+ ot->name = "Toggle Cyclic";
+ ot->description = "Make active spline closed/opened loop";
+ ot->idname = "CURVE_OT_cyclic_toggle";
- /* api callbacks */
- ot->exec = toggle_cyclic_exec;
- ot->invoke = toggle_cyclic_invoke;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = toggle_cyclic_exec;
+ ot->invoke = toggle_cyclic_invoke;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to make surface cyclic in");
+ /* properties */
+ RNA_def_enum(ot->srna,
+ "direction",
+ direction_items,
+ 0,
+ "Direction",
+ "Direction to make surface cyclic in");
}
/********************** add duplicate operator *********************/
static int duplicate_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- int ok = -1;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ int ok = -1;
- 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];
- Curve *cu = obedit->data;
+ 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];
+ Curve *cu = obedit->data;
- if (!ED_curve_select_check(v3d, cu->editnurb)) {
- continue;
- }
+ if (!ED_curve_select_check(v3d, cu->editnurb)) {
+ continue;
+ }
- ListBase newnurb = {NULL, NULL};
- adduplicateflagNurb(obedit, v3d, &newnurb, SELECT, false);
+ ListBase newnurb = {NULL, NULL};
+ adduplicateflagNurb(obedit, v3d, &newnurb, SELECT, false);
- if (BLI_listbase_is_empty(&newnurb)) {
- ok = MAX2(ok, 0);
- continue;
- }
+ if (BLI_listbase_is_empty(&newnurb)) {
+ ok = MAX2(ok, 0);
+ continue;
+ }
- ok = 1;
- BLI_movelisttolist(object_editcurve_get(obedit), &newnurb);
- DEG_id_tag_update(&cu->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, &cu->id);
- }
- MEM_freeN(objects);
+ ok = 1;
+ BLI_movelisttolist(object_editcurve_get(obedit), &newnurb);
+ DEG_id_tag_update(&cu->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, &cu->id);
+ }
+ MEM_freeN(objects);
- if (ok == 0) {
- BKE_report(op->reports, RPT_ERROR, "Cannot duplicate current selection");
- return OPERATOR_CANCELLED;
- }
- return OPERATOR_FINISHED;
+ if (ok == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot duplicate current selection");
+ return OPERATOR_CANCELLED;
+ }
+ return OPERATOR_FINISHED;
}
void CURVE_OT_duplicate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Duplicate Curve";
- ot->description = "Duplicate selected control points";
- ot->idname = "CURVE_OT_duplicate";
+ /* identifiers */
+ ot->name = "Duplicate Curve";
+ ot->description = "Duplicate selected control points";
+ ot->idname = "CURVE_OT_duplicate";
- /* api callbacks */
- ot->exec = duplicate_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = duplicate_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** delete operator *********************/
static bool curve_delete_vertices(Object *obedit, View3D *v3d)
{
- if (obedit->type == OB_SURF) {
- ed_surf_delete_selected(obedit);
- }
- else {
- ed_curve_delete_selected(obedit, v3d);
- }
+ if (obedit->type == OB_SURF) {
+ ed_surf_delete_selected(obedit);
+ }
+ else {
+ ed_curve_delete_selected(obedit, v3d);
+ }
- return true;
+ return true;
}
static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split)
{
- Curve *cu = obedit->data;
- EditNurb *editnurb = cu->editnurb;
- ListBase *nubase = &editnurb->nurbs, newnurb = {NULL, NULL};
- Nurb *nu, *nu1;
- BezTriple *bezt, *bezt1, *bezt2;
- BPoint *bp, *bp1, *bp2;
- int a, b, starta, enda, cut, cyclicut;
-
- for (nu = nubase->first; nu; nu = nu->next) {
- nu1 = NULL;
- starta = enda = cut = -1;
- cyclicut = 0;
-
- if (nu->type == CU_BEZIER) {
- for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
- if (!BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
- enda = a;
- if (starta == -1) {
- starta = a;
- }
- if (a < nu->pntsu - 1) {
- continue;
- }
- }
- else if (a < nu->pntsu - 1 && !BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt + 1)) {
- /* if just single selected point then continue */
- continue;
- }
-
- if (starta >= 0) {
- /* got selected segment, now check where and copy */
- if (starta <= 1 && a == nu->pntsu - 1) {
- /* copying all points in spline */
- if (starta == 1 && enda != a) {
- nu->flagu &= ~CU_NURB_CYCLIC;
- }
-
- starta = 0;
- enda = a;
- cut = enda - starta + 1;
- nu1 = BKE_nurb_copy(nu, cut, 1);
- }
- else if (starta == 0) {
- /* if start of curve copy next end point */
- enda++;
- cut = enda - starta + 1;
- bezt1 = &nu->bezt[nu->pntsu - 1];
- bezt2 = &nu->bezt[nu->pntsu - 2];
-
- if ((nu->flagu & CU_NURB_CYCLIC) &&
- BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1) &&
- BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt2))
- {
- /* check if need to join start of spline to end */
- nu1 = BKE_nurb_copy(nu, cut + 1, 1);
- ED_curve_beztcpy(editnurb, &nu1->bezt[1], nu->bezt, cut);
- starta = nu->pntsu - 1;
- cut = 1;
- }
- else {
- if (nu->flagu & CU_NURB_CYCLIC) {
- cyclicut = cut;
- }
- else {
- nu1 = BKE_nurb_copy(nu, cut, 1);
- }
- }
- }
- else if (enda == nu->pntsu - 1) {
- /* if end of curve copy previous start point */
- starta--;
- cut = enda - starta + 1;
- bezt1 = nu->bezt;
- bezt2 = &nu->bezt[1];
-
- if ((nu->flagu & CU_NURB_CYCLIC) &&
- BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1) &&
- BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt2))
- {
- /* check if need to join start of spline to end */
- nu1 = BKE_nurb_copy(nu, cut + 1, 1);
- ED_curve_beztcpy(editnurb, &nu1->bezt[cut], nu->bezt, 1);
- }
- else if (cyclicut != 0) {
- /* if cyclicut exists it is a cyclic spline, start and end should be connected */
- nu1 = BKE_nurb_copy(nu, cut + cyclicut, 1);
- ED_curve_beztcpy(editnurb, &nu1->bezt[cut], nu->bezt, cyclicut);
- cyclicut = 0;
- }
- else {
- nu1 = BKE_nurb_copy(nu, cut, 1);
- }
- }
- else {
- /* mid spline selection, copy adjacent start and end */
- starta--;
- enda++;
- cut = enda - starta + 1;
- nu1 = BKE_nurb_copy(nu, cut, 1);
- }
-
- if (nu1 != NULL) {
- ED_curve_beztcpy(editnurb, nu1->bezt, &nu->bezt[starta], cut);
- BLI_addtail(&newnurb, nu1);
-
- if (starta != 0 || enda != nu->pntsu - 1) {
- nu1->flagu &= ~CU_NURB_CYCLIC;
- }
- nu1 = NULL;
- }
- starta = enda = -1;
- }
- }
-
- if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) {
- /* start and points copied if connecting segment was deleted and not cylic spline */
- bezt1 = nu->bezt;
- bezt2 = &nu->bezt[1];
-
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1) &&
- BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt2))
- {
- nu1 = BKE_nurb_copy(nu, 1, 1);
- ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1);
- BLI_addtail(&newnurb, nu1);
- }
-
- bezt1 = &nu->bezt[nu->pntsu - 1];
- bezt2 = &nu->bezt[nu->pntsu - 2];
-
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1) &&
- BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt2))
- {
- nu1 = BKE_nurb_copy(nu, 1, 1);
- ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1);
- BLI_addtail(&newnurb, nu1);
- }
- }
- }
- else if (nu->pntsv >= 1) {
- int u, v;
-
- if (isNurbselV(nu, &u, SELECT)) {
- for (a = 0, bp = nu->bp; a < nu->pntsu; a++, bp++) {
- if (!(bp->f1 & SELECT)) {
- enda = a;
- if (starta == -1) {
- starta = a;
- }
- if (a < nu->pntsu - 1) {
- continue;
- }
- }
- else if (a < nu->pntsu - 1 && !((bp + 1)->f1 & SELECT)) {
- /* if just single selected point then continue */
- continue;
- }
-
- if (starta >= 0) {
- /* got selected segment, now check where and copy */
- if (starta <= 1 && a == nu->pntsu - 1) {
- /* copying all points in spline */
- if (starta == 1 && enda != a) {
- nu->flagu &= ~CU_NURB_CYCLIC;
- }
-
- starta = 0;
- enda = a;
- cut = enda - starta + 1;
- nu1 = BKE_nurb_copy(nu, cut, nu->pntsv);
- }
- else if (starta == 0) {
- /* if start of curve copy next end point */
- enda++;
- cut = enda - starta + 1;
- bp1 = &nu->bp[nu->pntsu - 1];
- bp2 = &nu->bp[nu->pntsu - 2];
-
- if ((nu->flagu & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
- /* check if need to join start of spline to end */
- nu1 = BKE_nurb_copy(nu, cut + 1, nu->pntsv);
- for (b = 0; b < nu->pntsv; b++) {
- ED_curve_bpcpy(editnurb, &nu1->bp[b * nu1->pntsu + 1], &nu->bp[b * nu->pntsu], cut);
- }
- starta = nu->pntsu - 1;
- cut = 1;
- }
- else {
- if (nu->flagu & CU_NURB_CYCLIC) {
- cyclicut = cut;
- }
- else {
- nu1 = BKE_nurb_copy(nu, cut, nu->pntsv);
- }
- }
- }
- else if (enda == nu->pntsu - 1) {
- /* if end of curve copy previous start point */
- starta--;
- cut = enda - starta + 1;
- bp1 = nu->bp;
- bp2 = &nu->bp[1];
-
- if ((nu->flagu & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
- /* check if need to join start of spline to end */
- nu1 = BKE_nurb_copy(nu, cut + 1, nu->pntsv);
- for (b = 0; b < nu->pntsv; b++) {
- ED_curve_bpcpy(editnurb, &nu1->bp[b * nu1->pntsu + cut], &nu->bp[b * nu->pntsu], 1);
- }
- }
- else if (cyclicut != 0) {
- /* if cyclicut exists it is a cyclic spline, start and end should be connected */
- nu1 = BKE_nurb_copy(nu, cut + cyclicut, nu->pntsv);
- for (b = 0; b < nu->pntsv; b++) {
- ED_curve_bpcpy(editnurb, &nu1->bp[b * nu1->pntsu + cut], &nu->bp[b * nu->pntsu], cyclicut);
- }
- }
- else {
- nu1 = BKE_nurb_copy(nu, cut, nu->pntsv);
- }
- }
- else {
- /* mid spline selection, copy adjacent start and end */
- starta--;
- enda++;
- cut = enda - starta + 1;
- nu1 = BKE_nurb_copy(nu, cut, nu->pntsv);
- }
-
- if (nu1 != NULL) {
- for (b = 0; b < nu->pntsv; b++) {
- ED_curve_bpcpy(editnurb, &nu1->bp[b * nu1->pntsu], &nu->bp[b * nu->pntsu + starta], cut);
- }
- BLI_addtail(&newnurb, nu1);
-
- if (starta != 0 || enda != nu->pntsu - 1) {
- nu1->flagu &= ~CU_NURB_CYCLIC;
- }
- nu1 = NULL;
- }
- starta = enda = -1;
- }
- }
-
- if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) {
- /* start and points copied if connecting segment was deleted and not cylic spline */
- bp1 = nu->bp;
- bp2 = &nu->bp[1];
-
- if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
- nu1 = BKE_nurb_copy(nu, 1, nu->pntsv);
- for (b = 0; b < nu->pntsv; b++) {
- ED_curve_bpcpy(editnurb, &nu1->bp[b], &nu->bp[b * nu->pntsu], 1);
- }
- BLI_addtail(&newnurb, nu1);
- }
-
- bp1 = &nu->bp[nu->pntsu - 1];
- bp2 = &nu->bp[nu->pntsu - 2];
-
- if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
- nu1 = BKE_nurb_copy(nu, 1, nu->pntsv);
- for (b = 0; b < nu->pntsv; b++) {
- ED_curve_bpcpy(editnurb, &nu1->bp[b], &nu->bp[b * nu->pntsu + nu->pntsu - 1], 1);
- }
- BLI_addtail(&newnurb, nu1);
- }
- }
- }
- else if (isNurbselU(nu, &v, SELECT)) {
- for (a = 0, bp = nu->bp; a < nu->pntsv; a++, bp += nu->pntsu) {
- if (!(bp->f1 & SELECT)) {
- enda = a;
- if (starta == -1) {
- starta = a;
- }
- if (a < nu->pntsv - 1) {
- continue;
- }
- }
- else if (a < nu->pntsv - 1 && !((bp + nu->pntsu)->f1 & SELECT)) {
- /* if just single selected point then continue */
- continue;
- }
-
- if (starta >= 0) {
- /* got selected segment, now check where and copy */
- if (starta <= 1 && a == nu->pntsv - 1) {
- /* copying all points in spline */
- if (starta == 1 && enda != a) {
- nu->flagv &= ~CU_NURB_CYCLIC;
- }
-
- starta = 0;
- enda = a;
- cut = enda - starta + 1;
- nu1 = BKE_nurb_copy(nu, nu->pntsu, cut);
- }
- else if (starta == 0) {
- /* if start of curve copy next end point */
- enda++;
- cut = enda - starta + 1;
- bp1 = &nu->bp[nu->pntsv * nu->pntsu - nu->pntsu];
- bp2 = &nu->bp[nu->pntsv * nu->pntsu - (nu->pntsu * 2)];
-
- if ((nu->flagv & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
- /* check if need to join start of spline to end */
- nu1 = BKE_nurb_copy(nu, nu->pntsu, cut + 1);
- ED_curve_bpcpy(editnurb, &nu1->bp[nu->pntsu], nu->bp, cut * nu->pntsu);
- starta = nu->pntsv - 1;
- cut = 1;
- }
- else {
- if (nu->flagv & CU_NURB_CYCLIC) {
- cyclicut = cut;
- }
- else {
- nu1 = BKE_nurb_copy(nu, nu->pntsu, cut);
- }
- }
- }
- else if (enda == nu->pntsv - 1) {
- /* if end of curve copy previous start point */
- starta--;
- cut = enda - starta + 1;
- bp1 = nu->bp;
- bp2 = &nu->bp[nu->pntsu];
-
- if ((nu->flagv & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
- /* check if need to join start of spline to end */
- nu1 = BKE_nurb_copy(nu, nu->pntsu, cut + 1);
- ED_curve_bpcpy(editnurb, &nu1->bp[cut * nu->pntsu], nu->bp, nu->pntsu);
- }
- else if (cyclicut != 0) {
- /* if cyclicut exists it is a cyclic spline, start and end should be connected */
- nu1 = BKE_nurb_copy(nu, nu->pntsu, cut + cyclicut);
- ED_curve_bpcpy(editnurb, &nu1->bp[cut * nu->pntsu], nu->bp, nu->pntsu * cyclicut);
- cyclicut = 0;
- }
- else {
- nu1 = BKE_nurb_copy(nu, nu->pntsu, cut);
- }
- }
- else {
- /* mid spline selection, copy adjacent start and end */
- starta--;
- enda++;
- cut = enda - starta + 1;
- nu1 = BKE_nurb_copy(nu, nu->pntsu, cut);
- }
-
- if (nu1 != NULL) {
- ED_curve_bpcpy(editnurb, nu1->bp, &nu->bp[starta * nu->pntsu], cut * nu->pntsu);
- BLI_addtail(&newnurb, nu1);
-
- if (starta != 0 || enda != nu->pntsv - 1) {
- nu1->flagv &= ~CU_NURB_CYCLIC;
- }
- nu1 = NULL;
- }
- starta = enda = -1;
- }
- }
-
- if (!split && cut != -1 && nu->pntsv > 2 && !(nu->flagv & CU_NURB_CYCLIC)) {
- /* start and points copied if connecting segment was deleted and not cylic spline */
- bp1 = nu->bp;
- bp2 = &nu->bp[nu->pntsu];
-
- if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
- nu1 = BKE_nurb_copy(nu, nu->pntsu, 1);
- ED_curve_bpcpy(editnurb, nu1->bp, nu->bp, nu->pntsu);
- BLI_addtail(&newnurb, nu1);
- }
-
- bp1 = &nu->bp[nu->pntsu * nu->pntsv - nu->pntsu];
- bp2 = &nu->bp[nu->pntsu * nu->pntsv - (nu->pntsu * 2)];
-
- if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
- nu1 = BKE_nurb_copy(nu, nu->pntsu, 1);
- ED_curve_bpcpy(editnurb, nu1->bp, &nu->bp[nu->pntsu * nu->pntsv - nu->pntsu], nu->pntsu);
- BLI_addtail(&newnurb, nu1);
- }
- }
- }
- else {
- /* selection not valid, just copy nurb to new list */
- nu1 = BKE_nurb_copy(nu, nu->pntsu, nu->pntsv);
- ED_curve_bpcpy(editnurb, nu1->bp, nu->bp, nu->pntsu * nu->pntsv);
- BLI_addtail(&newnurb, nu1);
- }
- }
- }
-
- for (nu = newnurb.first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- if (split) {
- /* deselect for split operator */
- for (b = 0, bezt1 = nu->bezt; b < nu->pntsu; b++, bezt1++) {
- select_beztriple(bezt1, DESELECT, SELECT, true);
- }
- }
-
- BKE_nurb_handles_calc(nu);
- }
- else {
- if (split) {
- /* deselect for split operator */
- for (b = 0, bp1 = nu->bp; b < nu->pntsu * nu->pntsv; b++, bp1++) {
- select_bpoint(bp1, DESELECT, SELECT, HIDDEN);
- }
- }
-
- BKE_nurb_order_clamp_u(nu);
- BKE_nurb_knot_calc_u(nu);
-
- if (nu->pntsv > 1) {
- BKE_nurb_order_clamp_v(nu);
- BKE_nurb_knot_calc_v(nu);
- }
- }
- }
-
- keyIndex_delNurbList(editnurb, nubase);
- BKE_nurbList_free(nubase);
- BLI_movelisttolist(nubase, &newnurb);
-
- return true;
+ Curve *cu = obedit->data;
+ EditNurb *editnurb = cu->editnurb;
+ ListBase *nubase = &editnurb->nurbs, newnurb = {NULL, NULL};
+ Nurb *nu, *nu1;
+ BezTriple *bezt, *bezt1, *bezt2;
+ BPoint *bp, *bp1, *bp2;
+ int a, b, starta, enda, cut, cyclicut;
+
+ for (nu = nubase->first; nu; nu = nu->next) {
+ nu1 = NULL;
+ starta = enda = cut = -1;
+ cyclicut = 0;
+
+ if (nu->type == CU_BEZIER) {
+ for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
+ if (!BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
+ enda = a;
+ if (starta == -1) {
+ starta = a;
+ }
+ if (a < nu->pntsu - 1) {
+ continue;
+ }
+ }
+ else if (a < nu->pntsu - 1 && !BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt + 1)) {
+ /* if just single selected point then continue */
+ continue;
+ }
+
+ if (starta >= 0) {
+ /* got selected segment, now check where and copy */
+ if (starta <= 1 && a == nu->pntsu - 1) {
+ /* copying all points in spline */
+ if (starta == 1 && enda != a) {
+ nu->flagu &= ~CU_NURB_CYCLIC;
+ }
+
+ starta = 0;
+ enda = a;
+ cut = enda - starta + 1;
+ nu1 = BKE_nurb_copy(nu, cut, 1);
+ }
+ else if (starta == 0) {
+ /* if start of curve copy next end point */
+ enda++;
+ cut = enda - starta + 1;
+ bezt1 = &nu->bezt[nu->pntsu - 1];
+ bezt2 = &nu->bezt[nu->pntsu - 2];
+
+ if ((nu->flagu & CU_NURB_CYCLIC) && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1) &&
+ BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt2)) {
+ /* check if need to join start of spline to end */
+ nu1 = BKE_nurb_copy(nu, cut + 1, 1);
+ ED_curve_beztcpy(editnurb, &nu1->bezt[1], nu->bezt, cut);
+ starta = nu->pntsu - 1;
+ cut = 1;
+ }
+ else {
+ if (nu->flagu & CU_NURB_CYCLIC) {
+ cyclicut = cut;
+ }
+ else {
+ nu1 = BKE_nurb_copy(nu, cut, 1);
+ }
+ }
+ }
+ else if (enda == nu->pntsu - 1) {
+ /* if end of curve copy previous start point */
+ starta--;
+ cut = enda - starta + 1;
+ bezt1 = nu->bezt;
+ bezt2 = &nu->bezt[1];
+
+ if ((nu->flagu & CU_NURB_CYCLIC) && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1) &&
+ BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt2)) {
+ /* check if need to join start of spline to end */
+ nu1 = BKE_nurb_copy(nu, cut + 1, 1);
+ ED_curve_beztcpy(editnurb, &nu1->bezt[cut], nu->bezt, 1);
+ }
+ else if (cyclicut != 0) {
+ /* if cyclicut exists it is a cyclic spline, start and end should be connected */
+ nu1 = BKE_nurb_copy(nu, cut + cyclicut, 1);
+ ED_curve_beztcpy(editnurb, &nu1->bezt[cut], nu->bezt, cyclicut);
+ cyclicut = 0;
+ }
+ else {
+ nu1 = BKE_nurb_copy(nu, cut, 1);
+ }
+ }
+ else {
+ /* mid spline selection, copy adjacent start and end */
+ starta--;
+ enda++;
+ cut = enda - starta + 1;
+ nu1 = BKE_nurb_copy(nu, cut, 1);
+ }
+
+ if (nu1 != NULL) {
+ ED_curve_beztcpy(editnurb, nu1->bezt, &nu->bezt[starta], cut);
+ BLI_addtail(&newnurb, nu1);
+
+ if (starta != 0 || enda != nu->pntsu - 1) {
+ nu1->flagu &= ~CU_NURB_CYCLIC;
+ }
+ nu1 = NULL;
+ }
+ starta = enda = -1;
+ }
+ }
+
+ if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) {
+ /* start and points copied if connecting segment was deleted and not cylic spline */
+ bezt1 = nu->bezt;
+ bezt2 = &nu->bezt[1];
+
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1) && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt2)) {
+ nu1 = BKE_nurb_copy(nu, 1, 1);
+ ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1);
+ BLI_addtail(&newnurb, nu1);
+ }
+
+ bezt1 = &nu->bezt[nu->pntsu - 1];
+ bezt2 = &nu->bezt[nu->pntsu - 2];
+
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1) && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt2)) {
+ nu1 = BKE_nurb_copy(nu, 1, 1);
+ ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1);
+ BLI_addtail(&newnurb, nu1);
+ }
+ }
+ }
+ else if (nu->pntsv >= 1) {
+ int u, v;
+
+ if (isNurbselV(nu, &u, SELECT)) {
+ for (a = 0, bp = nu->bp; a < nu->pntsu; a++, bp++) {
+ if (!(bp->f1 & SELECT)) {
+ enda = a;
+ if (starta == -1) {
+ starta = a;
+ }
+ if (a < nu->pntsu - 1) {
+ continue;
+ }
+ }
+ else if (a < nu->pntsu - 1 && !((bp + 1)->f1 & SELECT)) {
+ /* if just single selected point then continue */
+ continue;
+ }
+
+ if (starta >= 0) {
+ /* got selected segment, now check where and copy */
+ if (starta <= 1 && a == nu->pntsu - 1) {
+ /* copying all points in spline */
+ if (starta == 1 && enda != a) {
+ nu->flagu &= ~CU_NURB_CYCLIC;
+ }
+
+ starta = 0;
+ enda = a;
+ cut = enda - starta + 1;
+ nu1 = BKE_nurb_copy(nu, cut, nu->pntsv);
+ }
+ else if (starta == 0) {
+ /* if start of curve copy next end point */
+ enda++;
+ cut = enda - starta + 1;
+ bp1 = &nu->bp[nu->pntsu - 1];
+ bp2 = &nu->bp[nu->pntsu - 2];
+
+ if ((nu->flagu & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ /* check if need to join start of spline to end */
+ nu1 = BKE_nurb_copy(nu, cut + 1, nu->pntsv);
+ for (b = 0; b < nu->pntsv; b++) {
+ ED_curve_bpcpy(
+ editnurb, &nu1->bp[b * nu1->pntsu + 1], &nu->bp[b * nu->pntsu], cut);
+ }
+ starta = nu->pntsu - 1;
+ cut = 1;
+ }
+ else {
+ if (nu->flagu & CU_NURB_CYCLIC) {
+ cyclicut = cut;
+ }
+ else {
+ nu1 = BKE_nurb_copy(nu, cut, nu->pntsv);
+ }
+ }
+ }
+ else if (enda == nu->pntsu - 1) {
+ /* if end of curve copy previous start point */
+ starta--;
+ cut = enda - starta + 1;
+ bp1 = nu->bp;
+ bp2 = &nu->bp[1];
+
+ if ((nu->flagu & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ /* check if need to join start of spline to end */
+ nu1 = BKE_nurb_copy(nu, cut + 1, nu->pntsv);
+ for (b = 0; b < nu->pntsv; b++) {
+ ED_curve_bpcpy(
+ editnurb, &nu1->bp[b * nu1->pntsu + cut], &nu->bp[b * nu->pntsu], 1);
+ }
+ }
+ else if (cyclicut != 0) {
+ /* if cyclicut exists it is a cyclic spline, start and end should be connected */
+ nu1 = BKE_nurb_copy(nu, cut + cyclicut, nu->pntsv);
+ for (b = 0; b < nu->pntsv; b++) {
+ ED_curve_bpcpy(
+ editnurb, &nu1->bp[b * nu1->pntsu + cut], &nu->bp[b * nu->pntsu], cyclicut);
+ }
+ }
+ else {
+ nu1 = BKE_nurb_copy(nu, cut, nu->pntsv);
+ }
+ }
+ else {
+ /* mid spline selection, copy adjacent start and end */
+ starta--;
+ enda++;
+ cut = enda - starta + 1;
+ nu1 = BKE_nurb_copy(nu, cut, nu->pntsv);
+ }
+
+ if (nu1 != NULL) {
+ for (b = 0; b < nu->pntsv; b++) {
+ ED_curve_bpcpy(
+ editnurb, &nu1->bp[b * nu1->pntsu], &nu->bp[b * nu->pntsu + starta], cut);
+ }
+ BLI_addtail(&newnurb, nu1);
+
+ if (starta != 0 || enda != nu->pntsu - 1) {
+ nu1->flagu &= ~CU_NURB_CYCLIC;
+ }
+ nu1 = NULL;
+ }
+ starta = enda = -1;
+ }
+ }
+
+ if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) {
+ /* start and points copied if connecting segment was deleted and not cylic spline */
+ bp1 = nu->bp;
+ bp2 = &nu->bp[1];
+
+ if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ nu1 = BKE_nurb_copy(nu, 1, nu->pntsv);
+ for (b = 0; b < nu->pntsv; b++) {
+ ED_curve_bpcpy(editnurb, &nu1->bp[b], &nu->bp[b * nu->pntsu], 1);
+ }
+ BLI_addtail(&newnurb, nu1);
+ }
+
+ bp1 = &nu->bp[nu->pntsu - 1];
+ bp2 = &nu->bp[nu->pntsu - 2];
+
+ if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ nu1 = BKE_nurb_copy(nu, 1, nu->pntsv);
+ for (b = 0; b < nu->pntsv; b++) {
+ ED_curve_bpcpy(editnurb, &nu1->bp[b], &nu->bp[b * nu->pntsu + nu->pntsu - 1], 1);
+ }
+ BLI_addtail(&newnurb, nu1);
+ }
+ }
+ }
+ else if (isNurbselU(nu, &v, SELECT)) {
+ for (a = 0, bp = nu->bp; a < nu->pntsv; a++, bp += nu->pntsu) {
+ if (!(bp->f1 & SELECT)) {
+ enda = a;
+ if (starta == -1) {
+ starta = a;
+ }
+ if (a < nu->pntsv - 1) {
+ continue;
+ }
+ }
+ else if (a < nu->pntsv - 1 && !((bp + nu->pntsu)->f1 & SELECT)) {
+ /* if just single selected point then continue */
+ continue;
+ }
+
+ if (starta >= 0) {
+ /* got selected segment, now check where and copy */
+ if (starta <= 1 && a == nu->pntsv - 1) {
+ /* copying all points in spline */
+ if (starta == 1 && enda != a) {
+ nu->flagv &= ~CU_NURB_CYCLIC;
+ }
+
+ starta = 0;
+ enda = a;
+ cut = enda - starta + 1;
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, cut);
+ }
+ else if (starta == 0) {
+ /* if start of curve copy next end point */
+ enda++;
+ cut = enda - starta + 1;
+ bp1 = &nu->bp[nu->pntsv * nu->pntsu - nu->pntsu];
+ bp2 = &nu->bp[nu->pntsv * nu->pntsu - (nu->pntsu * 2)];
+
+ if ((nu->flagv & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ /* check if need to join start of spline to end */
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, cut + 1);
+ ED_curve_bpcpy(editnurb, &nu1->bp[nu->pntsu], nu->bp, cut * nu->pntsu);
+ starta = nu->pntsv - 1;
+ cut = 1;
+ }
+ else {
+ if (nu->flagv & CU_NURB_CYCLIC) {
+ cyclicut = cut;
+ }
+ else {
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, cut);
+ }
+ }
+ }
+ else if (enda == nu->pntsv - 1) {
+ /* if end of curve copy previous start point */
+ starta--;
+ cut = enda - starta + 1;
+ bp1 = nu->bp;
+ bp2 = &nu->bp[nu->pntsu];
+
+ if ((nu->flagv & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ /* check if need to join start of spline to end */
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, cut + 1);
+ ED_curve_bpcpy(editnurb, &nu1->bp[cut * nu->pntsu], nu->bp, nu->pntsu);
+ }
+ else if (cyclicut != 0) {
+ /* if cyclicut exists it is a cyclic spline, start and end should be connected */
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, cut + cyclicut);
+ ED_curve_bpcpy(editnurb, &nu1->bp[cut * nu->pntsu], nu->bp, nu->pntsu * cyclicut);
+ cyclicut = 0;
+ }
+ else {
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, cut);
+ }
+ }
+ else {
+ /* mid spline selection, copy adjacent start and end */
+ starta--;
+ enda++;
+ cut = enda - starta + 1;
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, cut);
+ }
+
+ if (nu1 != NULL) {
+ ED_curve_bpcpy(editnurb, nu1->bp, &nu->bp[starta * nu->pntsu], cut * nu->pntsu);
+ BLI_addtail(&newnurb, nu1);
+
+ if (starta != 0 || enda != nu->pntsv - 1) {
+ nu1->flagv &= ~CU_NURB_CYCLIC;
+ }
+ nu1 = NULL;
+ }
+ starta = enda = -1;
+ }
+ }
+
+ if (!split && cut != -1 && nu->pntsv > 2 && !(nu->flagv & CU_NURB_CYCLIC)) {
+ /* start and points copied if connecting segment was deleted and not cylic spline */
+ bp1 = nu->bp;
+ bp2 = &nu->bp[nu->pntsu];
+
+ if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, 1);
+ ED_curve_bpcpy(editnurb, nu1->bp, nu->bp, nu->pntsu);
+ BLI_addtail(&newnurb, nu1);
+ }
+
+ bp1 = &nu->bp[nu->pntsu * nu->pntsv - nu->pntsu];
+ bp2 = &nu->bp[nu->pntsu * nu->pntsv - (nu->pntsu * 2)];
+
+ if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, 1);
+ ED_curve_bpcpy(
+ editnurb, nu1->bp, &nu->bp[nu->pntsu * nu->pntsv - nu->pntsu], nu->pntsu);
+ BLI_addtail(&newnurb, nu1);
+ }
+ }
+ }
+ else {
+ /* selection not valid, just copy nurb to new list */
+ nu1 = BKE_nurb_copy(nu, nu->pntsu, nu->pntsv);
+ ED_curve_bpcpy(editnurb, nu1->bp, nu->bp, nu->pntsu * nu->pntsv);
+ BLI_addtail(&newnurb, nu1);
+ }
+ }
+ }
+
+ for (nu = newnurb.first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ if (split) {
+ /* deselect for split operator */
+ for (b = 0, bezt1 = nu->bezt; b < nu->pntsu; b++, bezt1++) {
+ select_beztriple(bezt1, DESELECT, SELECT, true);
+ }
+ }
+
+ BKE_nurb_handles_calc(nu);
+ }
+ else {
+ if (split) {
+ /* deselect for split operator */
+ for (b = 0, bp1 = nu->bp; b < nu->pntsu * nu->pntsv; b++, bp1++) {
+ select_bpoint(bp1, DESELECT, SELECT, HIDDEN);
+ }
+ }
+
+ BKE_nurb_order_clamp_u(nu);
+ BKE_nurb_knot_calc_u(nu);
+
+ if (nu->pntsv > 1) {
+ BKE_nurb_order_clamp_v(nu);
+ BKE_nurb_knot_calc_v(nu);
+ }
+ }
+ }
+
+ keyIndex_delNurbList(editnurb, nubase);
+ BKE_nurbList_free(nubase);
+ BLI_movelisttolist(nubase, &newnurb);
+
+ return true;
}
static int curve_delete_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- View3D *v3d = CTX_wm_view3d(C);
- eCurveElem_Types 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(view_layer, CTX_wm_view3d(C), &objects_len);
- bool changed_multi = false;
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Curve *cu = (Curve *)obedit->data;
- bool changed = false;
-
- if (!ED_curve_select_check(v3d, cu->editnurb)) {
- continue;
- }
-
- if (type == CURVE_VERTEX) {
- changed = curve_delete_vertices(obedit, v3d);
- }
- else if (type == CURVE_SEGMENT) {
- changed = curve_delete_segments(obedit, v3d, false);
- }
- else {
- BLI_assert(0);
- }
-
- if (changed) {
- changed_multi = true;
- cu->actnu = cu->actvert = CU_ACT_NONE;
-
- if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
- }
- }
- MEM_freeN(objects);
-
- if (changed_multi) {
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Main *bmain = CTX_data_main(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ eCurveElem_Types 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(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ bool changed_multi = false;
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Curve *cu = (Curve *)obedit->data;
+ bool changed = false;
+
+ if (!ED_curve_select_check(v3d, cu->editnurb)) {
+ continue;
+ }
+
+ if (type == CURVE_VERTEX) {
+ changed = curve_delete_vertices(obedit, v3d);
+ }
+ else if (type == CURVE_SEGMENT) {
+ changed = curve_delete_segments(obedit, v3d, false);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ if (changed) {
+ changed_multi = true;
+ cu->actnu = cu->actvert = CU_ACT_NONE;
+
+ if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+ }
+ }
+ MEM_freeN(objects);
+
+ if (changed_multi) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static const EnumPropertyItem curve_delete_type_items[] = {
- {CURVE_VERTEX, "VERT", 0, "Vertices", ""},
- {CURVE_SEGMENT, "SEGMENT", 0, "Segments", ""},
- {0, NULL, 0, NULL, NULL},
+ {CURVE_VERTEX, "VERT", 0, "Vertices", ""},
+ {CURVE_SEGMENT, "SEGMENT", 0, "Segments", ""},
+ {0, NULL, 0, NULL, NULL},
};
-static const EnumPropertyItem *rna_curve_delete_type_itemf(
- bContext *C, PointerRNA *UNUSED(ptr),
- PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *rna_curve_delete_type_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- EnumPropertyItem *item = NULL;
- int totitem = 0;
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
- if (!C) { /* needed for docs and i18n tools */
- return curve_delete_type_items;
- }
+ if (!C) { /* needed for docs and i18n tools */
+ return curve_delete_type_items;
+ }
- RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_VERTEX);
- RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_SEGMENT);
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
+ RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_VERTEX);
+ RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_SEGMENT);
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
- return item;
+ return item;
}
void CURVE_OT_delete(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Delete";
- ot->description = "Delete selected control points or segments";
- ot->idname = "CURVE_OT_delete";
+ /* identifiers */
+ ot->name = "Delete";
+ ot->description = "Delete selected control points or segments";
+ ot->idname = "CURVE_OT_delete";
- /* api callbacks */
- ot->exec = curve_delete_exec;
- ot->invoke = WM_menu_invoke;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = curve_delete_exec;
+ ot->invoke = WM_menu_invoke;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- prop = RNA_def_enum(ot->srna, "type", curve_delete_type_items, 0, "Type", "Which elements to delete");
- RNA_def_enum_funcs(prop, rna_curve_delete_type_itemf);
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- ot->prop = prop;
+ /* properties */
+ prop = RNA_def_enum(
+ ot->srna, "type", curve_delete_type_items, 0, "Type", "Which elements to delete");
+ RNA_def_enum_funcs(prop, rna_curve_delete_type_itemf);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ ot->prop = prop;
}
static bool test_bezt_is_sel_any(const void *bezt_v, void *user_data)
{
- View3D *v3d = user_data;
- const BezTriple *bezt = bezt_v;
- return BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt);
+ View3D *v3d = user_data;
+ const BezTriple *bezt = bezt_v;
+ return BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt);
}
static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
-
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Curve *cu = (Curve *)obedit->data;
-
- if (!ED_curve_select_check(v3d, cu->editnurb)) {
- continue;
- }
-
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
-
- 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;
-
- while (BLI_array_iter_span(
- nu->bezt, nu->pntsu,
- (nu->flagu & CU_NURB_CYCLIC) != 0, false,
- test_bezt_is_sel_any, v3d,
- span_step, &span_len))
- {
- BezTriple *bezt_prev = &nu->bezt[mod_i(span_step[0] - 1, nu->pntsu)];
- 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 unsigned int 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);
-
- for (int segment = 0; segment < i_span_edge_len; segment++) {
- BezTriple *bezt_a = &nu->bezt[mod_i((span_step[0] + segment) - 1, nu->pntsu)];
- BezTriple *bezt_b = &nu->bezt[mod_i((span_step[0] + segment), nu->pntsu)];
-
- for (int axis = 0; axis < dims; axis++) {
- BKE_curve_forward_diff_bezier(
- bezt_a->vec[1][axis], bezt_a->vec[2][axis],
- bezt_b->vec[0][axis], bezt_b->vec[1][axis],
- points_stride + axis, points_stride_len, dims * sizeof(float));
- }
-
- points_stride += dims * points_stride_len;
- }
-
- BLI_assert(points_stride + dims == points + (points_len * dims));
-
- float tan_l[3], tan_r[3], error_sq_dummy;
- unsigned int error_index_dummy;
-
- sub_v3_v3v3(tan_l, bezt_prev->vec[1], bezt_prev->vec[2]);
- normalize_v3(tan_l);
- sub_v3_v3v3(tan_r, bezt_next->vec[0], bezt_next->vec[1]);
- normalize_v3(tan_r);
-
- curve_fit_cubic_to_points_single_fl(
- points, points_len, NULL, dims, FLT_EPSILON,
- tan_l, tan_r,
- bezt_prev->vec[2], bezt_next->vec[0],
- &error_sq_dummy, &error_index_dummy);
-
- if (!ELEM(bezt_prev->h2, HD_FREE, HD_ALIGN)) {
- bezt_prev->h2 = (bezt_prev->h2 == HD_VECT) ? HD_FREE : HD_ALIGN;
- }
- if (!ELEM(bezt_next->h1, HD_FREE, HD_ALIGN)) {
- bezt_next->h1 = (bezt_next->h1 == HD_VECT) ? HD_FREE : HD_ALIGN;
- }
-
- MEM_freeN(points);
- }
- }
- }
-
- ed_curve_delete_selected(obedit, v3d);
-
- cu->actnu = cu->actvert = CU_ACT_NONE;
-
- if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Curve *cu = (Curve *)obedit->data;
+
+ if (!ED_curve_select_check(v3d, cu->editnurb)) {
+ continue;
+ }
+
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+
+ 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;
+
+ while (BLI_array_iter_span(nu->bezt,
+ nu->pntsu,
+ (nu->flagu & CU_NURB_CYCLIC) != 0,
+ false,
+ test_bezt_is_sel_any,
+ v3d,
+ span_step,
+ &span_len)) {
+ BezTriple *bezt_prev = &nu->bezt[mod_i(span_step[0] - 1, nu->pntsu)];
+ 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 unsigned int 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);
+
+ for (int segment = 0; segment < i_span_edge_len; segment++) {
+ BezTriple *bezt_a = &nu->bezt[mod_i((span_step[0] + segment) - 1, nu->pntsu)];
+ BezTriple *bezt_b = &nu->bezt[mod_i((span_step[0] + segment), nu->pntsu)];
+
+ for (int axis = 0; axis < dims; axis++) {
+ BKE_curve_forward_diff_bezier(bezt_a->vec[1][axis],
+ bezt_a->vec[2][axis],
+ bezt_b->vec[0][axis],
+ bezt_b->vec[1][axis],
+ points_stride + axis,
+ points_stride_len,
+ dims * sizeof(float));
+ }
+
+ points_stride += dims * points_stride_len;
+ }
+
+ BLI_assert(points_stride + dims == points + (points_len * dims));
+
+ float tan_l[3], tan_r[3], error_sq_dummy;
+ unsigned int error_index_dummy;
+
+ sub_v3_v3v3(tan_l, bezt_prev->vec[1], bezt_prev->vec[2]);
+ normalize_v3(tan_l);
+ sub_v3_v3v3(tan_r, bezt_next->vec[0], bezt_next->vec[1]);
+ normalize_v3(tan_r);
+
+ curve_fit_cubic_to_points_single_fl(points,
+ points_len,
+ NULL,
+ dims,
+ FLT_EPSILON,
+ tan_l,
+ tan_r,
+ bezt_prev->vec[2],
+ bezt_next->vec[0],
+ &error_sq_dummy,
+ &error_index_dummy);
+
+ if (!ELEM(bezt_prev->h2, HD_FREE, HD_ALIGN)) {
+ bezt_prev->h2 = (bezt_prev->h2 == HD_VECT) ? HD_FREE : HD_ALIGN;
+ }
+ if (!ELEM(bezt_next->h1, HD_FREE, HD_ALIGN)) {
+ bezt_next->h1 = (bezt_next->h1 == HD_VECT) ? HD_FREE : HD_ALIGN;
+ }
+
+ MEM_freeN(points);
+ }
+ }
+ }
+
+ ed_curve_delete_selected(obedit, v3d);
+
+ cu->actnu = cu->actvert = CU_ACT_NONE;
+
+ if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void CURVE_OT_dissolve_verts(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Dissolve Vertices";
- ot->description = "Delete selected control points, correcting surrounding handles";
- ot->idname = "CURVE_OT_dissolve_verts";
+ /* identifiers */
+ ot->name = "Dissolve Vertices";
+ ot->description = "Delete selected control points, correcting surrounding handles";
+ ot->idname = "CURVE_OT_dissolve_verts";
- /* api callbacks */
- ot->exec = curve_dissolve_exec;
- ot->poll = ED_operator_editcurve;
+ /* api callbacks */
+ ot->exec = curve_dissolve_exec;
+ ot->poll = ED_operator_editcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static bool nurb_bezt_flag_any(const Nurb *nu, const char flag_test)
{
- BezTriple *bezt = nu->bezt;
- int i;
+ BezTriple *bezt = nu->bezt;
+ int i;
- for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
- if (bezt->f2 & flag_test) {
- return true;
- }
- }
+ for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
+ if (bezt->f2 & flag_test) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
static int curve_decimate_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- const float error_sq_max = FLT_MAX;
- float ratio = RNA_float_get(op->ptr, "ratio");
- bool all_supported_multi = true;
-
- 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];
- Curve *cu = (Curve *)obedit->data;
- bool all_supported = true;
- bool changed = false;
-
- {
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- if ((nu->pntsu > 2) && nurb_bezt_flag_any(nu, SELECT)) {
- const int error_target_len = max_ii(2, nu->pntsu * ratio);
- if (error_target_len != nu->pntsu) {
- BKE_curve_decimate_nurb(nu, cu->resolu, error_sq_max, error_target_len);
- changed = true;
- }
- }
- }
- else {
- all_supported = false;
- }
- }
- }
-
- if (all_supported == false) {
- all_supported_multi = false;
- }
-
- if (changed) {
- cu->actnu = cu->actvert = CU_ACT_NONE;
- if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
- }
- }
-
- if (all_supported_multi == false) {
- BKE_report(op->reports, RPT_WARNING, "Only bezier curves are supported");
- }
-
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ const float error_sq_max = FLT_MAX;
+ float ratio = RNA_float_get(op->ptr, "ratio");
+ bool all_supported_multi = true;
+
+ 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];
+ Curve *cu = (Curve *)obedit->data;
+ bool all_supported = true;
+ bool changed = false;
+
+ {
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ if ((nu->pntsu > 2) && nurb_bezt_flag_any(nu, SELECT)) {
+ const int error_target_len = max_ii(2, nu->pntsu * ratio);
+ if (error_target_len != nu->pntsu) {
+ BKE_curve_decimate_nurb(nu, cu->resolu, error_sq_max, error_target_len);
+ changed = true;
+ }
+ }
+ }
+ else {
+ all_supported = false;
+ }
+ }
+ }
+
+ if (all_supported == false) {
+ all_supported_multi = false;
+ }
+
+ if (changed) {
+ cu->actnu = cu->actvert = CU_ACT_NONE;
+ if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+ }
+ }
+
+ if (all_supported_multi == false) {
+ BKE_report(op->reports, RPT_WARNING, "Only bezier curves are supported");
+ }
+
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void CURVE_OT_decimate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Decimate Curve";
- ot->description = "Simplify selected curves";
- ot->idname = "CURVE_OT_decimate";
+ /* identifiers */
+ ot->name = "Decimate Curve";
+ ot->description = "Simplify selected curves";
+ ot->idname = "CURVE_OT_decimate";
- /* api callbacks */
- ot->exec = curve_decimate_exec;
- ot->poll = ED_operator_editcurve;
+ /* api callbacks */
+ ot->exec = curve_decimate_exec;
+ ot->poll = ED_operator_editcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_float_factor(ot->srna, "ratio", 1.0f, 0.0f, 1.0f, "Ratio", "", 0.0f, 1.0f);
+ /* properties */
+ RNA_def_float_factor(ot->srna, "ratio", 1.0f, 0.0f, 1.0f, "Ratio", "", 0.0f, 1.0f);
}
-
/********************** shade smooth/flat operator *********************/
static int shade_smooth_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- View3D *v3d = CTX_wm_view3d(C);
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- int clear = (STREQ(op->idname, "CURVE_OT_shade_flat"));
+ Object *obedit = CTX_data_edit_object(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ int clear = (STREQ(op->idname, "CURVE_OT_shade_flat"));
- if (obedit->type != OB_CURVE) {
- return OPERATOR_CANCELLED;
- }
+ if (obedit->type != OB_CURVE) {
+ return OPERATOR_CANCELLED;
+ }
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (ED_curve_nurb_select_check(v3d, nu)) {
- if (!clear) {
- nu->flag |= CU_SMOOTH;
- }
- else {
- nu->flag &= ~CU_SMOOTH;
- }
- }
- }
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (ED_curve_nurb_select_check(v3d, nu)) {
+ if (!clear) {
+ nu->flag |= CU_SMOOTH;
+ }
+ else {
+ nu->flag &= ~CU_SMOOTH;
+ }
+ }
+ }
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CURVE_OT_shade_smooth(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Shade Smooth";
- ot->idname = "CURVE_OT_shade_smooth";
- ot->description = "Set shading to smooth";
+ /* identifiers */
+ ot->name = "Shade Smooth";
+ ot->idname = "CURVE_OT_shade_smooth";
+ ot->description = "Set shading to smooth";
- /* api callbacks */
- ot->exec = shade_smooth_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = shade_smooth_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void CURVE_OT_shade_flat(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Shade Flat";
- ot->idname = "CURVE_OT_shade_flat";
- ot->description = "Set shading to flat";
+ /* identifiers */
+ ot->name = "Shade Flat";
+ ot->idname = "CURVE_OT_shade_flat";
+ ot->description = "Set shading to flat";
- /* api callbacks */
- ot->exec = shade_smooth_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = shade_smooth_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************** join operator, to be used externally? ****************/
/* TODO: shape keys - as with meshes */
int join_curve_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob_active = CTX_data_active_object(C);
- Curve *cu;
- Nurb *nu, *newnu;
- BezTriple *bezt;
- BPoint *bp;
- ListBase tempbase;
- float imat[4][4], cmat[4][4];
- int a;
- bool ok = false;
-
- CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
- {
- if (ob_iter == ob_active) {
- ok = true;
- break;
- }
- }
- CTX_DATA_END;
-
- /* that way the active object is always selected */
- if (ok == false) {
- BKE_report(op->reports, RPT_WARNING, "Active object is not a selected curve");
- return OPERATOR_CANCELLED;
- }
-
- BLI_listbase_clear(&tempbase);
-
- /* trasnform all selected curves inverse in obact */
- invert_m4_m4(imat, ob_active->obmat);
-
- CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
- {
- if (ob_iter->type == ob_active->type) {
- if (ob_iter != ob_active) {
-
- cu = ob_iter->data;
-
- if (cu->nurb.first) {
- /* watch it: switch order here really goes wrong */
- mul_m4_m4m4(cmat, imat, ob_iter->obmat);
-
- nu = cu->nurb.first;
- while (nu) {
- newnu = BKE_nurb_duplicate(nu);
- if (ob_active->totcol) { /* TODO, merge material lists */
- CLAMP(newnu->mat_nr, 0, ob_active->totcol - 1);
- }
- else {
- newnu->mat_nr = 0;
- }
- BLI_addtail(&tempbase, newnu);
-
- if ((bezt = newnu->bezt)) {
- a = newnu->pntsu;
- while (a--) {
- mul_m4_v3(cmat, bezt->vec[0]);
- mul_m4_v3(cmat, bezt->vec[1]);
- mul_m4_v3(cmat, bezt->vec[2]);
- bezt++;
- }
- BKE_nurb_handles_calc(newnu);
- }
- if ((bp = newnu->bp)) {
- a = newnu->pntsu * nu->pntsv;
- while (a--) {
- mul_m4_v3(cmat, bp->vec);
- bp++;
- }
- }
- nu = nu->next;
- }
- }
-
- ED_object_base_free_and_unlink(bmain, scene, ob_iter);
- }
- }
- }
- CTX_DATA_END;
-
- cu = ob_active->data;
- BLI_movelisttolist(&cu->nurb, &tempbase);
-
- if (ob_active->type == OB_CURVE) {
- /* Account for mixed 2D/3D curves when joining */
- BKE_curve_curve_dimension_update(cu);
- }
-
- DEG_relations_tag_update(bmain); // because we removed object(s), call before editmode!
-
- DEG_id_tag_update(&ob_active->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob_active = CTX_data_active_object(C);
+ Curve *cu;
+ Nurb *nu, *newnu;
+ BezTriple *bezt;
+ BPoint *bp;
+ ListBase tempbase;
+ float imat[4][4], cmat[4][4];
+ int a;
+ bool ok = false;
+
+ CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
+ if (ob_iter == ob_active) {
+ ok = true;
+ break;
+ }
+ }
+ CTX_DATA_END;
+
+ /* that way the active object is always selected */
+ if (ok == false) {
+ BKE_report(op->reports, RPT_WARNING, "Active object is not a selected curve");
+ return OPERATOR_CANCELLED;
+ }
+
+ BLI_listbase_clear(&tempbase);
+
+ /* trasnform all selected curves inverse in obact */
+ invert_m4_m4(imat, ob_active->obmat);
+
+ CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
+ if (ob_iter->type == ob_active->type) {
+ if (ob_iter != ob_active) {
+
+ cu = ob_iter->data;
+
+ if (cu->nurb.first) {
+ /* watch it: switch order here really goes wrong */
+ mul_m4_m4m4(cmat, imat, ob_iter->obmat);
+
+ nu = cu->nurb.first;
+ while (nu) {
+ newnu = BKE_nurb_duplicate(nu);
+ if (ob_active->totcol) { /* TODO, merge material lists */
+ CLAMP(newnu->mat_nr, 0, ob_active->totcol - 1);
+ }
+ else {
+ newnu->mat_nr = 0;
+ }
+ BLI_addtail(&tempbase, newnu);
+
+ if ((bezt = newnu->bezt)) {
+ a = newnu->pntsu;
+ while (a--) {
+ mul_m4_v3(cmat, bezt->vec[0]);
+ mul_m4_v3(cmat, bezt->vec[1]);
+ mul_m4_v3(cmat, bezt->vec[2]);
+ bezt++;
+ }
+ BKE_nurb_handles_calc(newnu);
+ }
+ if ((bp = newnu->bp)) {
+ a = newnu->pntsu * nu->pntsv;
+ while (a--) {
+ mul_m4_v3(cmat, bp->vec);
+ bp++;
+ }
+ }
+ nu = nu->next;
+ }
+ }
+
+ ED_object_base_free_and_unlink(bmain, scene, ob_iter);
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ cu = ob_active->data;
+ BLI_movelisttolist(&cu->nurb, &tempbase);
+
+ if (ob_active->type == OB_CURVE) {
+ /* Account for mixed 2D/3D curves when joining */
+ BKE_curve_curve_dimension_update(cu);
+ }
+
+ DEG_relations_tag_update(bmain); // because we removed object(s), call before editmode!
+
+ DEG_id_tag_update(&ob_active->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+
+ return OPERATOR_FINISHED;
}
-
/***************** clear tilt operator ********************/
static int clear_tilt_exec(bContext *C, wmOperator *UNUSED(op))
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
-
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Curve *cu = obedit->data;
-
- if (!ED_curve_select_check(v3d, cu->editnurb)) {
- continue;
- }
-
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->bezt) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
- bezt->tilt = 0.0;
- }
- bezt++;
- }
- }
- else if (nu->bp) {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (bp->f1 & SELECT) {
- bp->tilt = 0.0f;
- }
- bp++;
- }
- }
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Curve *cu = obedit->data;
+
+ if (!ED_curve_select_check(v3d, cu->editnurb)) {
+ continue;
+ }
+
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
+ bezt->tilt = 0.0;
+ }
+ bezt++;
+ }
+ }
+ else if (nu->bp) {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ bp->tilt = 0.0f;
+ }
+ bp++;
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void CURVE_OT_tilt_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Tilt";
- ot->idname = "CURVE_OT_tilt_clear";
- ot->description = "Clear the tilt of selected control points";
+ /* identifiers */
+ ot->name = "Clear Tilt";
+ ot->idname = "CURVE_OT_tilt_clear";
+ ot->description = "Clear the tilt of selected control points";
- /* api callbacks */
- ot->exec = clear_tilt_exec;
- ot->poll = ED_operator_editcurve;
+ /* api callbacks */
+ ot->exec = clear_tilt_exec;
+ ot->poll = ED_operator_editcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void ED_curve_beztcpy(EditNurb *editnurb, BezTriple *dst, BezTriple *src, int count)
{
- memcpy(dst, src, count * sizeof(BezTriple));
- keyIndex_updateBezt(editnurb, src, dst, count);
+ memcpy(dst, src, count * sizeof(BezTriple));
+ keyIndex_updateBezt(editnurb, src, dst, count);
}
void ED_curve_bpcpy(EditNurb *editnurb, BPoint *dst, BPoint *src, int count)
{
- memcpy(dst, src, count * sizeof(BPoint));
- keyIndex_updateBP(editnurb, src, dst, count);
+ memcpy(dst, src, count * sizeof(BPoint));
+ keyIndex_updateBP(editnurb, src, dst, count);
}
bool ED_curve_active_center(Curve *cu, float center[3])
{
- Nurb *nu = NULL;
- void *vert = NULL;
+ Nurb *nu = NULL;
+ void *vert = NULL;
- if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) {
- return false;
- }
+ 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);
- }
+ 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;
+ return true;
}
/******************** Match texture space operator ***********************/
static bool match_texture_space_poll(bContext *C)
{
- Object *object = CTX_data_active_object(C);
+ Object *object = CTX_data_active_object(C);
- return object && ELEM(object->type, OB_CURVE, OB_SURF, OB_FONT);
+ return object && ELEM(object->type, OB_CURVE, OB_SURF, OB_FONT);
}
static int match_texture_space_exec(bContext *C, wmOperator *UNUSED(op))
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Object *object = CTX_data_active_object(C);
- Curve *curve = (Curve *) object->data;
- float min[3], max[3], size[3], loc[3];
- int a;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *object = CTX_data_active_object(C);
+ Curve *curve = (Curve *)object->data;
+ float min[3], max[3], size[3], loc[3];
+ int a;
- if (object->runtime.curve_cache == NULL) {
- BKE_displist_make_curveTypes(depsgraph, scene, object, false, false, NULL);
- }
+ if (object->runtime.curve_cache == NULL) {
+ BKE_displist_make_curveTypes(depsgraph, scene, object, false, false, NULL);
+ }
- INIT_MINMAX(min, max);
- BKE_displist_minmax(&object->runtime.curve_cache->disp, min, max);
+ INIT_MINMAX(min, max);
+ BKE_displist_minmax(&object->runtime.curve_cache->disp, min, max);
- mid_v3_v3v3(loc, min, max);
+ mid_v3_v3v3(loc, min, max);
- size[0] = (max[0] - min[0]) / 2.0f;
- size[1] = (max[1] - min[1]) / 2.0f;
- size[2] = (max[2] - min[2]) / 2.0f;
+ size[0] = (max[0] - min[0]) / 2.0f;
+ size[1] = (max[1] - min[1]) / 2.0f;
+ size[2] = (max[2] - min[2]) / 2.0f;
- for (a = 0; a < 3; a++) {
- if (size[a] == 0.0f) {
- size[a] = 1.0f;
- }
- else if (size[a] > 0.0f && size[a] < 0.00001f) {
- size[a] = 0.00001f;
- }
- else if (size[a] < 0.0f && size[a] > -0.00001f) {
- size[a] = -0.00001f;
- }
- }
+ for (a = 0; a < 3; a++) {
+ if (size[a] == 0.0f) {
+ size[a] = 1.0f;
+ }
+ else if (size[a] > 0.0f && size[a] < 0.00001f) {
+ size[a] = 0.00001f;
+ }
+ else if (size[a] < 0.0f && size[a] > -0.00001f) {
+ size[a] = -0.00001f;
+ }
+ }
- copy_v3_v3(curve->loc, loc);
- copy_v3_v3(curve->size, size);
- zero_v3(curve->rot);
+ copy_v3_v3(curve->loc, loc);
+ copy_v3_v3(curve->size, size);
+ zero_v3(curve->rot);
- curve->texflag &= ~CU_AUTOSPACE;
+ curve->texflag &= ~CU_AUTOSPACE;
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, curve);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, curve);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CURVE_OT_match_texture_space(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Match Texture Space";
- ot->idname = "CURVE_OT_match_texture_space";
- ot->description = "Match texture space to object's bounding box";
+ /* identifiers */
+ ot->name = "Match Texture Space";
+ ot->idname = "CURVE_OT_match_texture_space";
+ ot->description = "Match texture space to object's bounding box";
- /* api callbacks */
- ot->exec = match_texture_space_exec;
- ot->poll = match_texture_space_poll;
+ /* api callbacks */
+ ot->exec = match_texture_space_exec;
+ ot->poll = match_texture_space_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* 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 0b6d4f6585a..4912ae5451d 100644
--- a/source/blender/editors/curve/editcurve_add.c
+++ b/source/blender/editors/curve/editcurve_add.c
@@ -51,775 +51,791 @@
#include "curve_intern.h"
static const float nurbcircle[8][2] = {
- {0.0, -1.0}, {-1.0, -1.0}, {-1.0, 0.0}, {-1.0, 1.0},
- {0.0, 1.0}, { 1.0, 1.0}, { 1.0, 0.0}, { 1.0, -1.0},
+ {0.0, -1.0},
+ {-1.0, -1.0},
+ {-1.0, 0.0},
+ {-1.0, 1.0},
+ {0.0, 1.0},
+ {1.0, 1.0},
+ {1.0, 0.0},
+ {1.0, -1.0},
};
/************ add primitive, used by object/ module ****************/
static const char *get_curve_defname(int type)
{
- int stype = type & CU_PRIMITIVE;
-
- if ((type & CU_TYPE) == CU_BEZIER) {
- switch (stype) {
- case CU_PRIM_CURVE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "BezierCurve");
- case CU_PRIM_CIRCLE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "BezierCircle");
- case CU_PRIM_PATH: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "CurvePath");
- default:
- return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Curve");
- }
- }
- else {
- switch (stype) {
- case CU_PRIM_CURVE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsCurve");
- case CU_PRIM_CIRCLE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsCircle");
- case CU_PRIM_PATH: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsPath");
- default:
- return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Curve");
- }
- }
+ int stype = type & CU_PRIMITIVE;
+
+ if ((type & CU_TYPE) == CU_BEZIER) {
+ switch (stype) {
+ case CU_PRIM_CURVE:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "BezierCurve");
+ case CU_PRIM_CIRCLE:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "BezierCircle");
+ case CU_PRIM_PATH:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "CurvePath");
+ default:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Curve");
+ }
+ }
+ else {
+ switch (stype) {
+ case CU_PRIM_CURVE:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsCurve");
+ case CU_PRIM_CIRCLE:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsCircle");
+ case CU_PRIM_PATH:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsPath");
+ default:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Curve");
+ }
+ }
}
static const char *get_surf_defname(int type)
{
- int stype = type & CU_PRIMITIVE;
-
- switch (stype) {
- case CU_PRIM_CURVE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfCurve");
- case CU_PRIM_CIRCLE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfCircle");
- case CU_PRIM_PATCH: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfPatch");
- case CU_PRIM_SPHERE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfSphere");
- case CU_PRIM_DONUT: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfTorus");
- default:
- return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Surface");
- }
+ int stype = type & CU_PRIMITIVE;
+
+ switch (stype) {
+ case CU_PRIM_CURVE:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfCurve");
+ case CU_PRIM_CIRCLE:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfCircle");
+ case CU_PRIM_PATCH:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfPatch");
+ case CU_PRIM_SPHERE:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfSphere");
+ case CU_PRIM_DONUT:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfTorus");
+ default:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Surface");
+ }
}
-
-Nurb *ED_curve_add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type, int newob)
+Nurb *ED_curve_add_nurbs_primitive(
+ bContext *C, Object *obedit, float mat[4][4], int type, int newob)
{
- static int xzproj = 0; /* this function calls itself... */
- ListBase *editnurb = object_editcurve_get(obedit);
- RegionView3D *rv3d = ED_view3d_context_rv3d(C);
- Nurb *nu = NULL;
- BezTriple *bezt;
- BPoint *bp;
- Curve *cu = (Curve *)obedit->data;
- float vec[3], zvec[3] = {0.0f, 0.0f, 1.0f};
- float umat[4][4], viewmat[4][4];
- float fac;
- int a, b;
- const float grid = 1.0f;
- const int cutype = (type & CU_TYPE); // poly, bezier, nurbs, etc
- const int stype = (type & CU_PRIMITIVE);
-
- unit_m4(umat);
- unit_m4(viewmat);
-
- if (rv3d) {
- copy_m4_m4(viewmat, rv3d->viewmat);
- copy_v3_v3(zvec, rv3d->viewinv[2]);
- }
-
- BKE_nurbList_flag_set(editnurb, 0);
-
- /* these types call this function to return a Nurb */
- if (stype != CU_PRIM_TUBE && stype != CU_PRIM_DONUT) {
- nu = (Nurb *)MEM_callocN(sizeof(Nurb), "addNurbprim");
- nu->type = cutype;
- nu->resolu = cu->resolu;
- nu->resolv = cu->resolv;
- }
-
- switch (stype) {
- case CU_PRIM_CURVE: /* curve */
- nu->resolu = cu->resolu;
- if (cutype == CU_BEZIER) {
- nu->pntsu = 2;
- nu->bezt = (BezTriple *)MEM_callocN(2 * sizeof(BezTriple), "addNurbprim1");
- bezt = nu->bezt;
- bezt->h1 = bezt->h2 = HD_ALIGN;
- bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- bezt->radius = 1.0;
-
- bezt->vec[1][0] += -grid;
- bezt->vec[0][0] += -1.5f * grid;
- bezt->vec[0][1] += -0.5f * grid;
- bezt->vec[2][0] += -0.5f * grid;
- bezt->vec[2][1] += 0.5f * grid;
- for (a = 0; a < 3; a++) {
- mul_m4_v3(mat, bezt->vec[a]);
- }
-
- bezt++;
- bezt->h1 = bezt->h2 = HD_ALIGN;
- bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- bezt->radius = bezt->weight = 1.0;
-
- bezt->vec[0][0] = 0;
- bezt->vec[0][1] = 0;
- bezt->vec[1][0] = grid;
- bezt->vec[1][1] = 0;
- bezt->vec[2][0] = grid * 2;
- bezt->vec[2][1] = 0;
- for (a = 0; a < 3; a++) {
- mul_m4_v3(mat, bezt->vec[a]);
- }
-
- BKE_nurb_handles_calc(nu);
- }
- else {
-
- nu->pntsu = 4;
- nu->pntsv = 1;
- nu->orderu = 4;
- nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 4, "addNurbprim3");
-
- bp = nu->bp;
- for (a = 0; a < 4; a++, bp++) {
- bp->vec[3] = 1.0;
- bp->f1 = SELECT;
- bp->radius = bp->weight = 1.0;
- }
-
- bp = nu->bp;
- bp->vec[0] += -1.5f * grid;
- bp++;
- bp->vec[0] += -grid;
- bp->vec[1] += grid;
- bp++;
- bp->vec[0] += grid;
- bp->vec[1] += grid;
- bp++;
- bp->vec[0] += 1.5f * grid;
-
- bp = nu->bp;
- for (a = 0; a < 4; a++, bp++) {
- mul_m4_v3(mat, bp->vec);
- }
-
- if (cutype == CU_NURBS) {
- nu->knotsu = NULL; /* nurbs_knot_calc_u allocates */
- BKE_nurb_knot_calc_u(nu);
- }
-
- }
- break;
- case CU_PRIM_PATH: /* 5 point path */
- nu->pntsu = 5;
- nu->pntsv = 1;
- nu->orderu = 5;
- nu->flagu = CU_NURB_ENDPOINT; /* endpoint */
- nu->resolu = cu->resolu;
- nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim3");
-
- bp = nu->bp;
- for (a = 0; a < 5; a++, bp++) {
- bp->vec[3] = 1.0;
- bp->f1 = SELECT;
- bp->radius = bp->weight = 1.0;
- }
-
- bp = nu->bp;
- bp->vec[0] += -2.0f * grid;
- bp++;
- bp->vec[0] += -grid;
- bp++; bp++;
- bp->vec[0] += grid;
- bp++;
- bp->vec[0] += 2.0f * grid;
-
- bp = nu->bp;
- for (a = 0; a < 5; a++, bp++) {
- mul_m4_v3(mat, bp->vec);
- }
-
- if (cutype == CU_NURBS) {
- nu->knotsu = NULL; /* nurbs_knot_calc_u allocates */
- BKE_nurb_knot_calc_u(nu);
- }
-
- break;
- case CU_PRIM_CIRCLE: /* circle */
- nu->resolu = cu->resolu;
-
- if (cutype == CU_BEZIER) {
- nu->pntsu = 4;
- nu->bezt = (BezTriple *)MEM_callocN(sizeof(BezTriple) * 4, "addNurbprim1");
- nu->flagu = CU_NURB_CYCLIC;
- bezt = nu->bezt;
-
- bezt->h1 = bezt->h2 = HD_AUTO;
- bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- bezt->vec[1][0] += -grid;
- for (a = 0; a < 3; a++) {
- mul_m4_v3(mat, bezt->vec[a]);
- }
- bezt->radius = bezt->weight = 1.0;
-
- bezt++;
- bezt->h1 = bezt->h2 = HD_AUTO;
- bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- bezt->vec[1][1] += grid;
- for (a = 0; a < 3; a++) {
- mul_m4_v3(mat, bezt->vec[a]);
- }
- bezt->radius = bezt->weight = 1.0;
-
- bezt++;
- bezt->h1 = bezt->h2 = HD_AUTO;
- bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- bezt->vec[1][0] += grid;
- for (a = 0; a < 3; a++) {
- mul_m4_v3(mat, bezt->vec[a]);
- }
- bezt->radius = bezt->weight = 1.0;
-
- bezt++;
- bezt->h1 = bezt->h2 = HD_AUTO;
- bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- bezt->vec[1][1] += -grid;
- for (a = 0; a < 3; a++) {
- mul_m4_v3(mat, bezt->vec[a]);
- }
- bezt->radius = bezt->weight = 1.0;
-
- BKE_nurb_handles_calc(nu);
- }
- else if (cutype == CU_NURBS) { /* nurb */
- nu->pntsu = 8;
- nu->pntsv = 1;
- nu->orderu = 4;
- nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 8, "addNurbprim6");
- nu->flagu = CU_NURB_CYCLIC;
- bp = nu->bp;
-
- for (a = 0; a < 8; a++) {
- bp->f1 = SELECT;
- if (xzproj == 0) {
- bp->vec[0] += nurbcircle[a][0] * grid;
- bp->vec[1] += nurbcircle[a][1] * grid;
- }
- else {
- bp->vec[0] += 0.25f * nurbcircle[a][0] * grid - 0.75f * grid;
- bp->vec[2] += 0.25f * nurbcircle[a][1] * grid;
- }
- if (a & 1) {
- bp->vec[3] = 0.25 * M_SQRT2;
- }
- else {
- bp->vec[3] = 1.0;
- }
- mul_m4_v3(mat, bp->vec);
- bp->radius = bp->weight = 1.0;
-
- bp++;
- }
-
- BKE_nurb_knot_calc_u(nu);
- }
- break;
- case CU_PRIM_PATCH: /* 4x4 patch */
- if (cutype == CU_NURBS) { /* nurb */
-
- nu->pntsu = 4;
- nu->pntsv = 4;
- nu->orderu = 4;
- nu->orderv = 4;
- nu->flag = CU_SMOOTH;
- nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * (4 * 4), "addNurbprim6");
- nu->flagu = 0;
- nu->flagv = 0;
- bp = nu->bp;
-
- for (a = 0; a < 4; a++) {
- for (b = 0; b < 4; b++) {
- bp->f1 = SELECT;
- fac = (float)a - 1.5f;
- bp->vec[0] += fac * grid;
- fac = (float)b - 1.5f;
- bp->vec[1] += fac * grid;
- if ((a == 1 || a == 2) && (b == 1 || b == 2)) {
- bp->vec[2] += grid;
- }
- mul_m4_v3(mat, bp->vec);
- bp->vec[3] = 1.0;
- bp++;
- }
- }
-
- BKE_nurb_knot_calc_u(nu);
- BKE_nurb_knot_calc_v(nu);
- }
- break;
- case CU_PRIM_TUBE: /* Cylinder */
- if (cutype == CU_NURBS) {
- nu = ED_curve_add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0);
- nu->resolu = cu->resolu;
- nu->flag = CU_SMOOTH;
- BLI_addtail(editnurb, nu); /* temporal for extrude and translate */
- vec[0] = vec[1] = 0.0;
- vec[2] = -grid;
-
- mul_mat3_m4_v3(mat, vec);
-
- ed_editnurb_translate_flag(editnurb, SELECT, vec);
- ed_editnurb_extrude_flag(cu->editnurb, SELECT);
- mul_v3_fl(vec, -2.0f);
- ed_editnurb_translate_flag(editnurb, SELECT, vec);
-
- BLI_remlink(editnurb, nu);
-
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a-- > 0) {
- bp->f1 |= SELECT;
- bp++;
- }
- }
- break;
- case CU_PRIM_SPHERE: /* sphere */
- if (cutype == CU_NURBS) {
- float tmp_cent[3] = {0.f, 0.f, 0.f};
- float tmp_vec[3] = {0.f, 0.f, 1.f};
-
- nu->pntsu = 5;
- nu->pntsv = 1;
- nu->orderu = 3;
- nu->resolu = cu->resolu;
- nu->resolv = cu->resolv;
- nu->flag = CU_SMOOTH;
- nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim6");
- nu->flagu = 0;
- bp = nu->bp;
-
- for (a = 0; a < 5; a++) {
- bp->f1 = SELECT;
- bp->vec[0] += nurbcircle[a][0] * grid;
- bp->vec[2] += nurbcircle[a][1] * grid;
- if (a & 1) {
- bp->vec[3] = 0.5 * M_SQRT2;
- }
- else {
- bp->vec[3] = 1.0;
- }
- mul_m4_v3(mat, bp->vec);
- bp++;
- }
- nu->flagu = CU_NURB_BEZIER;
- BKE_nurb_knot_calc_u(nu);
-
- BLI_addtail(editnurb, nu); /* temporal for spin */
-
- if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) {
- ed_editnurb_spin(umat, NULL, obedit, tmp_vec, tmp_cent);
- }
- else if ((U.flag & USER_ADD_VIEWALIGNED)) {
- ed_editnurb_spin(viewmat, NULL, obedit, zvec, mat[3]);
- }
- else {
- ed_editnurb_spin(umat, NULL, obedit, tmp_vec, mat[3]);
- }
-
- BKE_nurb_knot_calc_v(nu);
-
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a-- > 0) {
- bp->f1 |= SELECT;
- bp++;
- }
- BLI_remlink(editnurb, nu);
- }
- break;
- case CU_PRIM_DONUT: /* torus */
- if (cutype == CU_NURBS) {
- float tmp_cent[3] = {0.f, 0.f, 0.f};
- float tmp_vec[3] = {0.f, 0.f, 1.f};
-
- xzproj = 1;
- nu = ED_curve_add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0);
- xzproj = 0;
- nu->resolu = cu->resolu;
- nu->resolv = cu->resolv;
- nu->flag = CU_SMOOTH;
- BLI_addtail(editnurb, nu); /* temporal for spin */
-
- /* same as above */
- if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) {
- ed_editnurb_spin(umat, NULL, obedit, tmp_vec, tmp_cent);
- }
- else if ((U.flag & USER_ADD_VIEWALIGNED)) {
- ed_editnurb_spin(viewmat, NULL, obedit, zvec, mat[3]);
- }
- else {
- ed_editnurb_spin(umat, NULL, obedit, tmp_vec, mat[3]);
- }
-
-
- BLI_remlink(editnurb, nu);
-
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a-- > 0) {
- bp->f1 |= SELECT;
- bp++;
- }
-
- }
- break;
-
- default: /* should never happen */
- BLI_assert(!"invalid nurbs type");
- return NULL;
- }
-
- BLI_assert(nu != NULL);
-
- if (nu) { /* should always be set */
- if ((obedit->type != OB_SURF) && ((cu->flag & CU_3D) == 0)) {
- nu->flag |= CU_2D;
- }
-
- nu->flag |= CU_SMOOTH;
- cu->actnu = BLI_listbase_count(editnurb);
- cu->actvert = CU_ACT_NONE;
-
- BKE_nurb_test_2d(nu);
- }
-
- return nu;
+ static int xzproj = 0; /* this function calls itself... */
+ ListBase *editnurb = object_editcurve_get(obedit);
+ RegionView3D *rv3d = ED_view3d_context_rv3d(C);
+ Nurb *nu = NULL;
+ BezTriple *bezt;
+ BPoint *bp;
+ Curve *cu = (Curve *)obedit->data;
+ float vec[3], zvec[3] = {0.0f, 0.0f, 1.0f};
+ float umat[4][4], viewmat[4][4];
+ float fac;
+ int a, b;
+ const float grid = 1.0f;
+ const int cutype = (type & CU_TYPE); // poly, bezier, nurbs, etc
+ const int stype = (type & CU_PRIMITIVE);
+
+ unit_m4(umat);
+ unit_m4(viewmat);
+
+ if (rv3d) {
+ copy_m4_m4(viewmat, rv3d->viewmat);
+ copy_v3_v3(zvec, rv3d->viewinv[2]);
+ }
+
+ BKE_nurbList_flag_set(editnurb, 0);
+
+ /* these types call this function to return a Nurb */
+ if (stype != CU_PRIM_TUBE && stype != CU_PRIM_DONUT) {
+ nu = (Nurb *)MEM_callocN(sizeof(Nurb), "addNurbprim");
+ nu->type = cutype;
+ nu->resolu = cu->resolu;
+ nu->resolv = cu->resolv;
+ }
+
+ switch (stype) {
+ case CU_PRIM_CURVE: /* curve */
+ nu->resolu = cu->resolu;
+ if (cutype == CU_BEZIER) {
+ nu->pntsu = 2;
+ nu->bezt = (BezTriple *)MEM_callocN(2 * sizeof(BezTriple), "addNurbprim1");
+ bezt = nu->bezt;
+ bezt->h1 = bezt->h2 = HD_ALIGN;
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ bezt->radius = 1.0;
+
+ bezt->vec[1][0] += -grid;
+ bezt->vec[0][0] += -1.5f * grid;
+ bezt->vec[0][1] += -0.5f * grid;
+ bezt->vec[2][0] += -0.5f * grid;
+ bezt->vec[2][1] += 0.5f * grid;
+ for (a = 0; a < 3; a++) {
+ mul_m4_v3(mat, bezt->vec[a]);
+ }
+
+ bezt++;
+ bezt->h1 = bezt->h2 = HD_ALIGN;
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ bezt->radius = bezt->weight = 1.0;
+
+ bezt->vec[0][0] = 0;
+ bezt->vec[0][1] = 0;
+ bezt->vec[1][0] = grid;
+ bezt->vec[1][1] = 0;
+ bezt->vec[2][0] = grid * 2;
+ bezt->vec[2][1] = 0;
+ for (a = 0; a < 3; a++) {
+ mul_m4_v3(mat, bezt->vec[a]);
+ }
+
+ BKE_nurb_handles_calc(nu);
+ }
+ else {
+
+ nu->pntsu = 4;
+ nu->pntsv = 1;
+ nu->orderu = 4;
+ nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 4, "addNurbprim3");
+
+ bp = nu->bp;
+ for (a = 0; a < 4; a++, bp++) {
+ bp->vec[3] = 1.0;
+ bp->f1 = SELECT;
+ bp->radius = bp->weight = 1.0;
+ }
+
+ bp = nu->bp;
+ bp->vec[0] += -1.5f * grid;
+ bp++;
+ bp->vec[0] += -grid;
+ bp->vec[1] += grid;
+ bp++;
+ bp->vec[0] += grid;
+ bp->vec[1] += grid;
+ bp++;
+ bp->vec[0] += 1.5f * grid;
+
+ bp = nu->bp;
+ for (a = 0; a < 4; a++, bp++) {
+ mul_m4_v3(mat, bp->vec);
+ }
+
+ if (cutype == CU_NURBS) {
+ nu->knotsu = NULL; /* nurbs_knot_calc_u allocates */
+ BKE_nurb_knot_calc_u(nu);
+ }
+ }
+ break;
+ case CU_PRIM_PATH: /* 5 point path */
+ nu->pntsu = 5;
+ nu->pntsv = 1;
+ nu->orderu = 5;
+ nu->flagu = CU_NURB_ENDPOINT; /* endpoint */
+ nu->resolu = cu->resolu;
+ nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim3");
+
+ bp = nu->bp;
+ for (a = 0; a < 5; a++, bp++) {
+ bp->vec[3] = 1.0;
+ bp->f1 = SELECT;
+ bp->radius = bp->weight = 1.0;
+ }
+
+ bp = nu->bp;
+ bp->vec[0] += -2.0f * grid;
+ bp++;
+ bp->vec[0] += -grid;
+ bp++;
+ bp++;
+ bp->vec[0] += grid;
+ bp++;
+ bp->vec[0] += 2.0f * grid;
+
+ bp = nu->bp;
+ for (a = 0; a < 5; a++, bp++) {
+ mul_m4_v3(mat, bp->vec);
+ }
+
+ if (cutype == CU_NURBS) {
+ nu->knotsu = NULL; /* nurbs_knot_calc_u allocates */
+ BKE_nurb_knot_calc_u(nu);
+ }
+
+ break;
+ case CU_PRIM_CIRCLE: /* circle */
+ nu->resolu = cu->resolu;
+
+ if (cutype == CU_BEZIER) {
+ nu->pntsu = 4;
+ nu->bezt = (BezTriple *)MEM_callocN(sizeof(BezTriple) * 4, "addNurbprim1");
+ nu->flagu = CU_NURB_CYCLIC;
+ bezt = nu->bezt;
+
+ bezt->h1 = bezt->h2 = HD_AUTO;
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ bezt->vec[1][0] += -grid;
+ for (a = 0; a < 3; a++) {
+ mul_m4_v3(mat, bezt->vec[a]);
+ }
+ bezt->radius = bezt->weight = 1.0;
+
+ bezt++;
+ bezt->h1 = bezt->h2 = HD_AUTO;
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ bezt->vec[1][1] += grid;
+ for (a = 0; a < 3; a++) {
+ mul_m4_v3(mat, bezt->vec[a]);
+ }
+ bezt->radius = bezt->weight = 1.0;
+
+ bezt++;
+ bezt->h1 = bezt->h2 = HD_AUTO;
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ bezt->vec[1][0] += grid;
+ for (a = 0; a < 3; a++) {
+ mul_m4_v3(mat, bezt->vec[a]);
+ }
+ bezt->radius = bezt->weight = 1.0;
+
+ bezt++;
+ bezt->h1 = bezt->h2 = HD_AUTO;
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ bezt->vec[1][1] += -grid;
+ for (a = 0; a < 3; a++) {
+ mul_m4_v3(mat, bezt->vec[a]);
+ }
+ bezt->radius = bezt->weight = 1.0;
+
+ BKE_nurb_handles_calc(nu);
+ }
+ else if (cutype == CU_NURBS) { /* nurb */
+ nu->pntsu = 8;
+ nu->pntsv = 1;
+ nu->orderu = 4;
+ nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 8, "addNurbprim6");
+ nu->flagu = CU_NURB_CYCLIC;
+ bp = nu->bp;
+
+ for (a = 0; a < 8; a++) {
+ bp->f1 = SELECT;
+ if (xzproj == 0) {
+ bp->vec[0] += nurbcircle[a][0] * grid;
+ bp->vec[1] += nurbcircle[a][1] * grid;
+ }
+ else {
+ bp->vec[0] += 0.25f * nurbcircle[a][0] * grid - 0.75f * grid;
+ bp->vec[2] += 0.25f * nurbcircle[a][1] * grid;
+ }
+ if (a & 1) {
+ bp->vec[3] = 0.25 * M_SQRT2;
+ }
+ else {
+ bp->vec[3] = 1.0;
+ }
+ mul_m4_v3(mat, bp->vec);
+ bp->radius = bp->weight = 1.0;
+
+ bp++;
+ }
+
+ BKE_nurb_knot_calc_u(nu);
+ }
+ break;
+ case CU_PRIM_PATCH: /* 4x4 patch */
+ if (cutype == CU_NURBS) { /* nurb */
+
+ nu->pntsu = 4;
+ nu->pntsv = 4;
+ nu->orderu = 4;
+ nu->orderv = 4;
+ nu->flag = CU_SMOOTH;
+ nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * (4 * 4), "addNurbprim6");
+ nu->flagu = 0;
+ nu->flagv = 0;
+ bp = nu->bp;
+
+ for (a = 0; a < 4; a++) {
+ for (b = 0; b < 4; b++) {
+ bp->f1 = SELECT;
+ fac = (float)a - 1.5f;
+ bp->vec[0] += fac * grid;
+ fac = (float)b - 1.5f;
+ bp->vec[1] += fac * grid;
+ if ((a == 1 || a == 2) && (b == 1 || b == 2)) {
+ bp->vec[2] += grid;
+ }
+ mul_m4_v3(mat, bp->vec);
+ bp->vec[3] = 1.0;
+ bp++;
+ }
+ }
+
+ BKE_nurb_knot_calc_u(nu);
+ BKE_nurb_knot_calc_v(nu);
+ }
+ break;
+ case CU_PRIM_TUBE: /* Cylinder */
+ if (cutype == CU_NURBS) {
+ nu = ED_curve_add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0);
+ nu->resolu = cu->resolu;
+ nu->flag = CU_SMOOTH;
+ BLI_addtail(editnurb, nu); /* temporal for extrude and translate */
+ vec[0] = vec[1] = 0.0;
+ vec[2] = -grid;
+
+ mul_mat3_m4_v3(mat, vec);
+
+ ed_editnurb_translate_flag(editnurb, SELECT, vec);
+ ed_editnurb_extrude_flag(cu->editnurb, SELECT);
+ mul_v3_fl(vec, -2.0f);
+ ed_editnurb_translate_flag(editnurb, SELECT, vec);
+
+ BLI_remlink(editnurb, nu);
+
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a-- > 0) {
+ bp->f1 |= SELECT;
+ bp++;
+ }
+ }
+ break;
+ case CU_PRIM_SPHERE: /* sphere */
+ if (cutype == CU_NURBS) {
+ float tmp_cent[3] = {0.f, 0.f, 0.f};
+ float tmp_vec[3] = {0.f, 0.f, 1.f};
+
+ nu->pntsu = 5;
+ nu->pntsv = 1;
+ nu->orderu = 3;
+ nu->resolu = cu->resolu;
+ nu->resolv = cu->resolv;
+ nu->flag = CU_SMOOTH;
+ nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim6");
+ nu->flagu = 0;
+ bp = nu->bp;
+
+ for (a = 0; a < 5; a++) {
+ bp->f1 = SELECT;
+ bp->vec[0] += nurbcircle[a][0] * grid;
+ bp->vec[2] += nurbcircle[a][1] * grid;
+ if (a & 1) {
+ bp->vec[3] = 0.5 * M_SQRT2;
+ }
+ else {
+ bp->vec[3] = 1.0;
+ }
+ mul_m4_v3(mat, bp->vec);
+ bp++;
+ }
+ nu->flagu = CU_NURB_BEZIER;
+ BKE_nurb_knot_calc_u(nu);
+
+ BLI_addtail(editnurb, nu); /* temporal for spin */
+
+ if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) {
+ ed_editnurb_spin(umat, NULL, obedit, tmp_vec, tmp_cent);
+ }
+ else if ((U.flag & USER_ADD_VIEWALIGNED)) {
+ ed_editnurb_spin(viewmat, NULL, obedit, zvec, mat[3]);
+ }
+ else {
+ ed_editnurb_spin(umat, NULL, obedit, tmp_vec, mat[3]);
+ }
+
+ BKE_nurb_knot_calc_v(nu);
+
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a-- > 0) {
+ bp->f1 |= SELECT;
+ bp++;
+ }
+ BLI_remlink(editnurb, nu);
+ }
+ break;
+ case CU_PRIM_DONUT: /* torus */
+ if (cutype == CU_NURBS) {
+ float tmp_cent[3] = {0.f, 0.f, 0.f};
+ float tmp_vec[3] = {0.f, 0.f, 1.f};
+
+ xzproj = 1;
+ nu = ED_curve_add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0);
+ xzproj = 0;
+ nu->resolu = cu->resolu;
+ nu->resolv = cu->resolv;
+ nu->flag = CU_SMOOTH;
+ BLI_addtail(editnurb, nu); /* temporal for spin */
+
+ /* same as above */
+ if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) {
+ ed_editnurb_spin(umat, NULL, obedit, tmp_vec, tmp_cent);
+ }
+ else if ((U.flag & USER_ADD_VIEWALIGNED)) {
+ ed_editnurb_spin(viewmat, NULL, obedit, zvec, mat[3]);
+ }
+ else {
+ ed_editnurb_spin(umat, NULL, obedit, tmp_vec, mat[3]);
+ }
+
+ BLI_remlink(editnurb, nu);
+
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a-- > 0) {
+ bp->f1 |= SELECT;
+ bp++;
+ }
+ }
+ break;
+
+ default: /* should never happen */
+ BLI_assert(!"invalid nurbs type");
+ return NULL;
+ }
+
+ BLI_assert(nu != NULL);
+
+ if (nu) { /* should always be set */
+ if ((obedit->type != OB_SURF) && ((cu->flag & CU_3D) == 0)) {
+ nu->flag |= CU_2D;
+ }
+
+ nu->flag |= CU_SMOOTH;
+ cu->actnu = BLI_listbase_count(editnurb);
+ cu->actvert = CU_ACT_NONE;
+
+ BKE_nurb_test_2d(nu);
+ }
+
+ return nu;
}
static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb;
- Nurb *nu;
- bool newob = false;
- bool enter_editmode;
- ushort local_view_bits;
- float dia;
- float loc[3], rot[3];
- float mat[4][4];
-
- WM_operator_view3d_unit_defaults(C, op);
-
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
-
- if (!isSurf) { /* adding curve */
- if (obedit == NULL || obedit->type != OB_CURVE) {
- const char *name = get_curve_defname(type);
- Curve *cu;
-
- obedit = ED_object_add_type(C, OB_CURVE, name, loc, rot, true, local_view_bits);
- newob = true;
-
- cu = (Curve *)obedit->data;
- cu->flag |= CU_DEFORM_FILL;
-
- if (type & CU_PRIM_PATH) {
- cu->flag |= CU_PATH | CU_3D;
- }
- }
- else {
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
- }
- else { /* adding surface */
- if (obedit == NULL || obedit->type != OB_SURF) {
- const char *name = get_surf_defname(type);
- obedit = ED_object_add_type(C, OB_SURF, name, loc, rot, true, local_view_bits);
- newob = true;
- }
- else {
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
- }
-
- ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
- dia = RNA_float_get(op->ptr, "radius");
- mul_mat3_m4_fl(mat, dia);
-
- nu = ED_curve_add_nurbs_primitive(C, obedit, mat, type, newob);
- editnurb = object_editcurve_get(obedit);
- BLI_addtail(editnurb, nu);
-
- /* userdef */
- if (newob && !enter_editmode) {
- ED_object_editmode_exit(C, EM_FREEDATA);
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
-
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb;
+ Nurb *nu;
+ bool newob = false;
+ bool enter_editmode;
+ ushort local_view_bits;
+ float dia;
+ float loc[3], rot[3];
+ float mat[4][4];
+
+ WM_operator_view3d_unit_defaults(C, op);
+
+ if (!ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!isSurf) { /* adding curve */
+ if (obedit == NULL || obedit->type != OB_CURVE) {
+ const char *name = get_curve_defname(type);
+ Curve *cu;
+
+ obedit = ED_object_add_type(C, OB_CURVE, name, loc, rot, true, local_view_bits);
+ newob = true;
+
+ cu = (Curve *)obedit->data;
+ cu->flag |= CU_DEFORM_FILL;
+
+ if (type & CU_PRIM_PATH) {
+ cu->flag |= CU_PATH | CU_3D;
+ }
+ }
+ else {
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ }
+ }
+ else { /* adding surface */
+ if (obedit == NULL || obedit->type != OB_SURF) {
+ const char *name = get_surf_defname(type);
+ obedit = ED_object_add_type(C, OB_SURF, name, loc, rot, true, local_view_bits);
+ newob = true;
+ }
+ else {
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ }
+ }
+
+ ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
+ dia = RNA_float_get(op->ptr, "radius");
+ mul_mat3_m4_fl(mat, dia);
+
+ nu = ED_curve_add_nurbs_primitive(C, obedit, mat, type, newob);
+ editnurb = object_editcurve_get(obedit);
+ BLI_addtail(editnurb, nu);
+
+ /* userdef */
+ if (newob && !enter_editmode) {
+ ED_object_editmode_exit(C, EM_FREEDATA);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
+
+ return OPERATOR_FINISHED;
}
static int curve_prim_add(bContext *C, wmOperator *op, int type)
{
- return curvesurf_prim_add(C, op, type, 0);
+ return curvesurf_prim_add(C, op, type, 0);
}
static int surf_prim_add(bContext *C, wmOperator *op, int type)
{
- return curvesurf_prim_add(C, op, type, 1);
+ return curvesurf_prim_add(C, op, type, 1);
}
/* ******************** Curves ******************* */
static int add_primitive_bezier_exec(bContext *C, wmOperator *op)
{
- return curve_prim_add(C, op, CU_BEZIER | CU_PRIM_CURVE);
+ return curve_prim_add(C, op, CU_BEZIER | CU_PRIM_CURVE);
}
void CURVE_OT_primitive_bezier_curve_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Bezier";
- ot->description = "Construct a Bezier Curve";
- ot->idname = "CURVE_OT_primitive_bezier_curve_add";
+ /* identifiers */
+ ot->name = "Add Bezier";
+ ot->description = "Construct a Bezier Curve";
+ ot->idname = "CURVE_OT_primitive_bezier_curve_add";
- /* api callbacks */
- ot->exec = add_primitive_bezier_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = add_primitive_bezier_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_bezier_circle_exec(bContext *C, wmOperator *op)
{
- return curve_prim_add(C, op, CU_BEZIER | CU_PRIM_CIRCLE);
+ return curve_prim_add(C, op, CU_BEZIER | CU_PRIM_CIRCLE);
}
void CURVE_OT_primitive_bezier_circle_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Bezier Circle";
- ot->description = "Construct a Bezier Circle";
- ot->idname = "CURVE_OT_primitive_bezier_circle_add";
+ /* identifiers */
+ ot->name = "Add Bezier Circle";
+ ot->description = "Construct a Bezier Circle";
+ ot->idname = "CURVE_OT_primitive_bezier_circle_add";
- /* api callbacks */
- ot->exec = add_primitive_bezier_circle_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = add_primitive_bezier_circle_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_nurbs_curve_exec(bContext *C, wmOperator *op)
{
- return curve_prim_add(C, op, CU_NURBS | CU_PRIM_CURVE);
+ return curve_prim_add(C, op, CU_NURBS | CU_PRIM_CURVE);
}
void CURVE_OT_primitive_nurbs_curve_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Nurbs Curve";
- ot->description = "Construct a Nurbs Curve";
- ot->idname = "CURVE_OT_primitive_nurbs_curve_add";
+ /* identifiers */
+ ot->name = "Add Nurbs Curve";
+ ot->description = "Construct a Nurbs Curve";
+ ot->idname = "CURVE_OT_primitive_nurbs_curve_add";
- /* api callbacks */
- ot->exec = add_primitive_nurbs_curve_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = add_primitive_nurbs_curve_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_nurbs_circle_exec(bContext *C, wmOperator *op)
{
- return curve_prim_add(C, op, CU_NURBS | CU_PRIM_CIRCLE);
+ return curve_prim_add(C, op, CU_NURBS | CU_PRIM_CIRCLE);
}
void CURVE_OT_primitive_nurbs_circle_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Nurbs Circle";
- ot->description = "Construct a Nurbs Circle";
- ot->idname = "CURVE_OT_primitive_nurbs_circle_add";
+ /* identifiers */
+ ot->name = "Add Nurbs Circle";
+ ot->description = "Construct a Nurbs Circle";
+ ot->idname = "CURVE_OT_primitive_nurbs_circle_add";
- /* api callbacks */
- ot->exec = add_primitive_nurbs_circle_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = add_primitive_nurbs_circle_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_curve_path_exec(bContext *C, wmOperator *op)
{
- return curve_prim_add(C, op, CU_NURBS | CU_PRIM_PATH);
+ return curve_prim_add(C, op, CU_NURBS | CU_PRIM_PATH);
}
void CURVE_OT_primitive_nurbs_path_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Path";
- ot->description = "Construct a Path";
- ot->idname = "CURVE_OT_primitive_nurbs_path_add";
+ /* identifiers */
+ ot->name = "Add Path";
+ ot->description = "Construct a Path";
+ ot->idname = "CURVE_OT_primitive_nurbs_path_add";
- /* api callbacks */
- ot->exec = add_primitive_curve_path_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = add_primitive_curve_path_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
/* **************** NURBS surfaces ********************** */
static int add_primitive_nurbs_surface_curve_exec(bContext *C, wmOperator *op)
{
- return surf_prim_add(C, op, CU_PRIM_CURVE | CU_NURBS);
+ return surf_prim_add(C, op, CU_PRIM_CURVE | CU_NURBS);
}
void SURFACE_OT_primitive_nurbs_surface_curve_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Surface Curve";
- ot->description = "Construct a Nurbs surface Curve";
- ot->idname = "SURFACE_OT_primitive_nurbs_surface_curve_add";
+ /* identifiers */
+ ot->name = "Add Surface Curve";
+ ot->description = "Construct a Nurbs surface Curve";
+ ot->idname = "SURFACE_OT_primitive_nurbs_surface_curve_add";
- /* api callbacks */
- ot->exec = add_primitive_nurbs_surface_curve_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = add_primitive_nurbs_surface_curve_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_nurbs_surface_circle_exec(bContext *C, wmOperator *op)
{
- return surf_prim_add(C, op, CU_PRIM_CIRCLE | CU_NURBS);
+ return surf_prim_add(C, op, CU_PRIM_CIRCLE | CU_NURBS);
}
void SURFACE_OT_primitive_nurbs_surface_circle_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Surface Circle";
- ot->description = "Construct a Nurbs surface Circle";
- ot->idname = "SURFACE_OT_primitive_nurbs_surface_circle_add";
+ /* identifiers */
+ ot->name = "Add Surface Circle";
+ ot->description = "Construct a Nurbs surface Circle";
+ ot->idname = "SURFACE_OT_primitive_nurbs_surface_circle_add";
- /* api callbacks */
- ot->exec = add_primitive_nurbs_surface_circle_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = add_primitive_nurbs_surface_circle_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_nurbs_surface_surface_exec(bContext *C, wmOperator *op)
{
- return surf_prim_add(C, op, CU_PRIM_PATCH | CU_NURBS);
+ return surf_prim_add(C, op, CU_PRIM_PATCH | CU_NURBS);
}
void SURFACE_OT_primitive_nurbs_surface_surface_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Surface Patch";
- ot->description = "Construct a Nurbs surface Patch";
- ot->idname = "SURFACE_OT_primitive_nurbs_surface_surface_add";
+ /* identifiers */
+ ot->name = "Add Surface Patch";
+ ot->description = "Construct a Nurbs surface Patch";
+ ot->idname = "SURFACE_OT_primitive_nurbs_surface_surface_add";
- /* api callbacks */
- ot->exec = add_primitive_nurbs_surface_surface_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = add_primitive_nurbs_surface_surface_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_nurbs_surface_cylinder_exec(bContext *C, wmOperator *op)
{
- return surf_prim_add(C, op, CU_PRIM_TUBE | CU_NURBS);
+ return surf_prim_add(C, op, CU_PRIM_TUBE | CU_NURBS);
}
void SURFACE_OT_primitive_nurbs_surface_cylinder_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Surface Cylinder";
- ot->description = "Construct a Nurbs surface Cylinder";
- ot->idname = "SURFACE_OT_primitive_nurbs_surface_cylinder_add";
+ /* identifiers */
+ ot->name = "Add Surface Cylinder";
+ ot->description = "Construct a Nurbs surface Cylinder";
+ ot->idname = "SURFACE_OT_primitive_nurbs_surface_cylinder_add";
- /* api callbacks */
- ot->exec = add_primitive_nurbs_surface_cylinder_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = add_primitive_nurbs_surface_cylinder_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_nurbs_surface_sphere_exec(bContext *C, wmOperator *op)
{
- return surf_prim_add(C, op, CU_PRIM_SPHERE | CU_NURBS);
+ return surf_prim_add(C, op, CU_PRIM_SPHERE | CU_NURBS);
}
void SURFACE_OT_primitive_nurbs_surface_sphere_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Surface Sphere";
- ot->description = "Construct a Nurbs surface Sphere";
- ot->idname = "SURFACE_OT_primitive_nurbs_surface_sphere_add";
+ /* identifiers */
+ ot->name = "Add Surface Sphere";
+ ot->description = "Construct a Nurbs surface Sphere";
+ ot->idname = "SURFACE_OT_primitive_nurbs_surface_sphere_add";
- /* api callbacks */
- ot->exec = add_primitive_nurbs_surface_sphere_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = add_primitive_nurbs_surface_sphere_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_nurbs_surface_torus_exec(bContext *C, wmOperator *op)
{
- return surf_prim_add(C, op, CU_PRIM_DONUT | CU_NURBS);
+ return surf_prim_add(C, op, CU_PRIM_DONUT | CU_NURBS);
}
void SURFACE_OT_primitive_nurbs_surface_torus_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Surface Torus";
- ot->description = "Construct a Nurbs surface Torus";
- ot->idname = "SURFACE_OT_primitive_nurbs_surface_torus_add";
+ /* identifiers */
+ ot->name = "Add Surface Torus";
+ ot->description = "Construct a Nurbs surface Torus";
+ ot->idname = "SURFACE_OT_primitive_nurbs_surface_torus_add";
- /* api callbacks */
- ot->exec = add_primitive_nurbs_surface_torus_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = add_primitive_nurbs_surface_torus_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c
index d930174c25b..6811e32cc2a 100644
--- a/source/blender/editors/curve/editcurve_paint.c
+++ b/source/blender/editors/curve/editcurve_paint.c
@@ -43,7 +43,6 @@
#include "ED_view3d.h"
#include "ED_curve.h"
-
#include "GPU_batch.h"
#include "GPU_batch_presets.h"
#include "GPU_immediate.h"
@@ -63,7 +62,7 @@
#define USE_SPLINE_FIT
#ifdef USE_SPLINE_FIT
-#include "curve_fit_nd.h"
+# include "curve_fit_nd.h"
#endif
/* Distance between input samples */
@@ -71,573 +70,567 @@
#define STROKE_SAMPLE_DIST_MAX_PX 3
/* Distance between start/end points to consider cyclic */
-#define STROKE_CYCLIC_DIST_PX 8
+#define STROKE_CYCLIC_DIST_PX 8
/* -------------------------------------------------------------------- */
/** \name StrokeElem / #RNA_OperatorStrokeElement Conversion Functions
* \{ */
struct StrokeElem {
- float mval[2];
- float location_world[3];
- float location_local[3];
+ float mval[2];
+ float location_world[3];
+ float location_local[3];
- /* surface normal, may be zero'd */
- float normal_world[3];
- float normal_local[3];
+ /* surface normal, may be zero'd */
+ float normal_world[3];
+ float normal_local[3];
- float pressure;
+ float pressure;
};
struct CurveDrawData {
- Depsgraph *depsgraph;
+ Depsgraph *depsgraph;
- short init_event_type;
- short curve_type;
+ short init_event_type;
+ short curve_type;
- /* projecting 2D into 3D space */
- struct {
- /* use a plane or project to the surface */
- bool use_plane;
- float plane[4];
+ /* projecting 2D into 3D space */
+ struct {
+ /* use a plane or project to the surface */
+ bool use_plane;
+ float plane[4];
- /* use 'rv3d->depths', note that this will become 'damaged' while drawing, but that's OK. */
- bool use_depth;
+ /* use 'rv3d->depths', note that this will become 'damaged' while drawing, but that's OK. */
+ bool use_depth;
- /* offset projection by this value */
- bool use_offset;
- float offset[3]; /* worldspace */
- float surface_offset;
- bool use_surface_offset_absolute;
- } project;
+ /* offset projection by this value */
+ bool use_offset;
+ float offset[3]; /* worldspace */
+ float surface_offset;
+ bool use_surface_offset_absolute;
+ } project;
- /* cursor sampling */
- struct {
- /* use substeps, needed for nicely interpolating depth */
- bool use_substeps;
- } sample;
+ /* cursor sampling */
+ struct {
+ /* use substeps, needed for nicely interpolating depth */
+ bool use_substeps;
+ } sample;
- struct {
- float min, max, range;
- } radius;
+ struct {
+ float min, max, range;
+ } radius;
- struct {
- float mouse[2];
- /* used incase we can't calculate the depth */
- float location_world[3];
+ struct {
+ float mouse[2];
+ /* used incase we can't calculate the depth */
+ float location_world[3];
- float location_world_valid[3];
+ float location_world_valid[3];
- const struct StrokeElem *selem;
- } prev;
+ const struct StrokeElem *selem;
+ } prev;
- ViewContext vc;
- enum {
- CURVE_DRAW_IDLE = 0,
- CURVE_DRAW_PAINTING = 1,
- } state;
+ ViewContext vc;
+ enum {
+ CURVE_DRAW_IDLE = 0,
+ CURVE_DRAW_PAINTING = 1,
+ } state;
- /* StrokeElem */
- BLI_mempool *stroke_elem_pool;
+ /* StrokeElem */
+ BLI_mempool *stroke_elem_pool;
- void *draw_handle_view;
+ void *draw_handle_view;
};
-static float stroke_elem_radius_from_pressure(const struct CurveDrawData *cdd, const float pressure)
+static float stroke_elem_radius_from_pressure(const struct CurveDrawData *cdd,
+ const float pressure)
{
- const Curve *cu = cdd->vc.obedit->data;
- return ((pressure * cdd->radius.range) + cdd->radius.min) * cu->ext2;
+ const Curve *cu = cdd->vc.obedit->data;
+ return ((pressure * cdd->radius.range) + cdd->radius.min) * cu->ext2;
}
static float stroke_elem_radius(const struct CurveDrawData *cdd, const struct StrokeElem *selem)
{
- return stroke_elem_radius_from_pressure(cdd, selem->pressure);
+ return stroke_elem_radius_from_pressure(cdd, selem->pressure);
}
-static void stroke_elem_pressure_set(const struct CurveDrawData *cdd, struct StrokeElem *selem, float pressure)
+static void stroke_elem_pressure_set(const struct CurveDrawData *cdd,
+ struct StrokeElem *selem,
+ float pressure)
{
- if ((cdd->project.surface_offset != 0.0f) &&
- !cdd->project.use_surface_offset_absolute &&
- !is_zero_v3(selem->normal_local))
- {
- const float adjust = stroke_elem_radius_from_pressure(cdd, pressure) -
- stroke_elem_radius_from_pressure(cdd, selem->pressure);
- madd_v3_v3fl(selem->location_local, selem->normal_local, adjust);
- mul_v3_m4v3(selem->location_world, cdd->vc.obedit->obmat, selem->location_local);
- }
- selem->pressure = pressure;
+ if ((cdd->project.surface_offset != 0.0f) && !cdd->project.use_surface_offset_absolute &&
+ !is_zero_v3(selem->normal_local)) {
+ const float adjust = stroke_elem_radius_from_pressure(cdd, pressure) -
+ stroke_elem_radius_from_pressure(cdd, selem->pressure);
+ madd_v3_v3fl(selem->location_local, selem->normal_local, adjust);
+ mul_v3_m4v3(selem->location_world, cdd->vc.obedit->obmat, selem->location_local);
+ }
+ selem->pressure = pressure;
}
-static void stroke_elem_interp(
- struct StrokeElem *selem_out,
- const struct StrokeElem *selem_a, const struct StrokeElem *selem_b, float t)
+static void stroke_elem_interp(struct StrokeElem *selem_out,
+ const struct StrokeElem *selem_a,
+ const struct StrokeElem *selem_b,
+ float t)
{
- interp_v2_v2v2(selem_out->mval, selem_a->mval, selem_b->mval, t);
- interp_v3_v3v3(selem_out->location_world, selem_a->location_world, selem_b->location_world, t);
- interp_v3_v3v3(selem_out->location_local, selem_a->location_local, selem_b->location_local, t);
- selem_out->pressure = interpf(selem_a->pressure, selem_b->pressure, t);
+ interp_v2_v2v2(selem_out->mval, selem_a->mval, selem_b->mval, t);
+ interp_v3_v3v3(selem_out->location_world, selem_a->location_world, selem_b->location_world, t);
+ interp_v3_v3v3(selem_out->location_local, selem_a->location_local, selem_b->location_local, t);
+ selem_out->pressure = interpf(selem_a->pressure, selem_b->pressure, t);
}
-
/**
* Sets the depth from #StrokeElem.mval
*/
-static bool stroke_elem_project(
- const struct CurveDrawData *cdd,
- const int mval_i[2], const float mval_fl[2],
- float surface_offset, const float radius,
- float r_location_world[3], float r_normal_world[3])
+static bool stroke_elem_project(const struct CurveDrawData *cdd,
+ const int mval_i[2],
+ const float mval_fl[2],
+ float surface_offset,
+ const float radius,
+ float r_location_world[3],
+ float r_normal_world[3])
{
- ARegion *ar = cdd->vc.ar;
- RegionView3D *rv3d = cdd->vc.rv3d;
-
- bool is_location_world_set = false;
-
- /* 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 (r_normal_world) {
- zero_v3(r_normal_world);
- }
- is_location_world_set = true;
- }
- }
- else {
- const ViewDepths *depths = rv3d->depths;
- if (depths &&
- ((unsigned int)mval_i[0] < depths->w) &&
- ((unsigned int)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)) {
- is_location_world_set = true;
- if (r_normal_world) {
- zero_v3(r_normal_world);
- }
-
- if (surface_offset != 0.0f) {
- const float offset = cdd->project.use_surface_offset_absolute ? 1.0f : radius;
- float normal[3];
- if (ED_view3d_depth_read_cached_normal(&cdd->vc, mval_i, normal)) {
- madd_v3_v3fl(r_location_world, normal, offset * surface_offset);
- if (r_normal_world) {
- copy_v3_v3(r_normal_world, normal);
- }
- }
- }
- }
- }
- }
- }
-
- if (is_location_world_set) {
- if (cdd->project.use_offset) {
- add_v3_v3(r_location_world, cdd->project.offset);
- }
- }
-
- return is_location_world_set;
+ ARegion *ar = cdd->vc.ar;
+ RegionView3D *rv3d = cdd->vc.rv3d;
+
+ bool is_location_world_set = false;
+
+ /* 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 (r_normal_world) {
+ zero_v3(r_normal_world);
+ }
+ is_location_world_set = true;
+ }
+ }
+ else {
+ const ViewDepths *depths = rv3d->depths;
+ if (depths && ((unsigned int)mval_i[0] < depths->w) && ((unsigned int)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)) {
+ is_location_world_set = true;
+ if (r_normal_world) {
+ zero_v3(r_normal_world);
+ }
+
+ if (surface_offset != 0.0f) {
+ const float offset = cdd->project.use_surface_offset_absolute ? 1.0f : radius;
+ float normal[3];
+ if (ED_view3d_depth_read_cached_normal(&cdd->vc, mval_i, normal)) {
+ madd_v3_v3fl(r_location_world, normal, offset * surface_offset);
+ if (r_normal_world) {
+ copy_v3_v3(r_normal_world, normal);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (is_location_world_set) {
+ if (cdd->project.use_offset) {
+ add_v3_v3(r_location_world, cdd->project.offset);
+ }
+ }
+
+ return is_location_world_set;
}
-static bool stroke_elem_project_fallback(
- const struct CurveDrawData *cdd,
- const int mval_i[2], const float mval_fl[2],
- const float surface_offset, const float radius,
- const float location_fallback_depth[3],
- float r_location_world[3], float r_location_local[3],
- float r_normal_world[3], float r_normal_local[3])
+static bool stroke_elem_project_fallback(const struct CurveDrawData *cdd,
+ const int mval_i[2],
+ const float mval_fl[2],
+ const float surface_offset,
+ const float radius,
+ const float location_fallback_depth[3],
+ float r_location_world[3],
+ float r_location_local[3],
+ float r_normal_world[3],
+ float r_normal_local[3])
{
- bool is_depth_found = stroke_elem_project(
- 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);
- zero_v3(r_normal_local);
- }
- mul_v3_m4v3(r_location_local, cdd->vc.obedit->imat, r_location_world);
-
- if (!is_zero_v3(r_normal_world)) {
- copy_v3_v3(r_normal_local, r_normal_world);
- mul_transposed_mat3_m4_v3(cdd->vc.obedit->obmat, r_normal_local);
- normalize_v3(r_normal_local);
- }
- else {
- zero_v3(r_normal_local);
- }
-
- return is_depth_found;
+ bool is_depth_found = stroke_elem_project(
+ 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);
+ zero_v3(r_normal_local);
+ }
+ mul_v3_m4v3(r_location_local, cdd->vc.obedit->imat, r_location_world);
+
+ if (!is_zero_v3(r_normal_world)) {
+ copy_v3_v3(r_normal_local, r_normal_world);
+ mul_transposed_mat3_m4_v3(cdd->vc.obedit->obmat, r_normal_local);
+ normalize_v3(r_normal_local);
+ }
+ else {
+ zero_v3(r_normal_local);
+ }
+
+ return is_depth_found;
}
/**
* \note #StrokeElem.mval & #StrokeElem.pressure must be set first.
*/
-static bool stroke_elem_project_fallback_elem(
- const struct CurveDrawData *cdd,
- const float location_fallback_depth[3],
- struct StrokeElem *selem)
+static bool stroke_elem_project_fallback_elem(const struct CurveDrawData *cdd,
+ const float location_fallback_depth[3],
+ struct StrokeElem *selem)
{
- const int mval_i[2] = {UNPACK2(selem->mval)};
- const float radius = stroke_elem_radius(cdd, selem);
- return stroke_elem_project_fallback(
- cdd, mval_i, selem->mval,
- cdd->project.surface_offset, radius,
- location_fallback_depth,
- selem->location_world, selem->location_local,
- selem->normal_world, selem->normal_local);
+ const int mval_i[2] = {UNPACK2(selem->mval)};
+ const float radius = stroke_elem_radius(cdd, selem);
+ return stroke_elem_project_fallback(cdd,
+ mval_i,
+ selem->mval,
+ cdd->project.surface_offset,
+ radius,
+ location_fallback_depth,
+ selem->location_world,
+ selem->location_local,
+ selem->normal_world,
+ selem->normal_local);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Operator/Stroke Conversion
* \{ */
-static void curve_draw_stroke_to_operator_elem(
- wmOperator *op, const struct StrokeElem *selem)
+static void curve_draw_stroke_to_operator_elem(wmOperator *op, const struct StrokeElem *selem)
{
- PointerRNA itemptr;
- RNA_collection_add(op->ptr, "stroke", &itemptr);
+ PointerRNA itemptr;
+ RNA_collection_add(op->ptr, "stroke", &itemptr);
- RNA_float_set_array(&itemptr, "mouse", selem->mval);
- RNA_float_set_array(&itemptr, "location", selem->location_world);
- RNA_float_set(&itemptr, "pressure", selem->pressure);
+ RNA_float_set_array(&itemptr, "mouse", selem->mval);
+ RNA_float_set_array(&itemptr, "location", selem->location_world);
+ RNA_float_set(&itemptr, "pressure", selem->pressure);
}
-static void curve_draw_stroke_from_operator_elem(
- wmOperator *op, PointerRNA *itemptr)
+static void curve_draw_stroke_from_operator_elem(wmOperator *op, PointerRNA *itemptr)
{
- struct CurveDrawData *cdd = op->customdata;
+ struct CurveDrawData *cdd = op->customdata;
- struct StrokeElem *selem = BLI_mempool_calloc(cdd->stroke_elem_pool);
+ struct StrokeElem *selem = BLI_mempool_calloc(cdd->stroke_elem_pool);
- RNA_float_get_array(itemptr, "mouse", selem->mval);
- RNA_float_get_array(itemptr, "location", selem->location_world);
- mul_v3_m4v3(selem->location_local, cdd->vc.obedit->imat, selem->location_world);
- selem->pressure = RNA_float_get(itemptr, "pressure");
+ RNA_float_get_array(itemptr, "mouse", selem->mval);
+ RNA_float_get_array(itemptr, "location", selem->location_world);
+ mul_v3_m4v3(selem->location_local, cdd->vc.obedit->imat, selem->location_world);
+ selem->pressure = RNA_float_get(itemptr, "pressure");
}
static void curve_draw_stroke_to_operator(wmOperator *op)
{
- struct CurveDrawData *cdd = op->customdata;
+ struct CurveDrawData *cdd = op->customdata;
- BLI_mempool_iter iter;
- const struct StrokeElem *selem;
+ BLI_mempool_iter iter;
+ const struct StrokeElem *selem;
- BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
- for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
- curve_draw_stroke_to_operator_elem(op, selem);
- }
+ BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
+ for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
+ curve_draw_stroke_to_operator_elem(op, selem);
+ }
}
static void curve_draw_stroke_from_operator(wmOperator *op)
{
- RNA_BEGIN (op->ptr, itemptr, "stroke")
- {
- curve_draw_stroke_from_operator_elem(op, &itemptr);
- }
- RNA_END;
+ RNA_BEGIN (op->ptr, itemptr, "stroke") {
+ curve_draw_stroke_from_operator_elem(op, &itemptr);
+ }
+ RNA_END;
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Operator Callbacks & Helpers
* \{ */
static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
{
- wmOperator *op = arg;
- struct CurveDrawData *cdd = op->customdata;
-
- const int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
-
- if (stroke_len == 0) {
- return;
- }
-
- Object *obedit = cdd->vc.obedit;
- Curve *cu = obedit->data;
-
- if (cu->ext2 > 0.0f) {
- BLI_mempool_iter iter;
- const struct StrokeElem *selem;
-
- const float location_zero[3] = {0};
- const float *location_prev = location_zero;
-
- float color[3];
- UI_GetThemeColor3fv(TH_WIRE, color);
-
- GPUBatch *sphere = GPU_batch_preset_sphere(0);
- GPU_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR);
- GPU_batch_uniform_3fv(sphere, "color", color);
-
- /* scale to edit-mode space */
- GPU_matrix_push();
- GPU_matrix_mul(obedit->obmat);
-
- BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
- for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
- GPU_matrix_translate_3f(
- selem->location_local[0] - location_prev[0],
- selem->location_local[1] - location_prev[1],
- selem->location_local[2] - location_prev[2]);
- location_prev = selem->location_local;
-
- const float radius = stroke_elem_radius(cdd, selem);
-
- GPU_matrix_push();
- GPU_matrix_scale_1f(radius);
- GPU_batch_draw(sphere);
- GPU_matrix_pop();
-
- location_prev = selem->location_local;
- }
-
- GPU_matrix_pop();
- }
-
- if (stroke_len > 1) {
- float (*coord_array)[3] = MEM_mallocN(sizeof(*coord_array) * stroke_len, __func__);
-
- {
- BLI_mempool_iter iter;
- const struct StrokeElem *selem;
- int i;
- BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
- for (selem = BLI_mempool_iterstep(&iter), i = 0; selem; selem = BLI_mempool_iterstep(&iter), i++) {
- copy_v3_v3(coord_array[i], selem->location_world);
- }
- }
-
- {
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
-
- GPU_depth_test(false);
- GPU_blend(true);
- GPU_line_smooth(true);
- GPU_line_width(3.0f);
-
- imm_cpack(0x0);
- immBegin(GPU_PRIM_LINE_STRIP, stroke_len);
- for (int i = 0; i < stroke_len; i++) {
- immVertex3fv(pos, coord_array[i]);
- }
- immEnd();
-
- GPU_line_width(1.0f);
-
- imm_cpack(0xffffffff);
- immBegin(GPU_PRIM_LINE_STRIP, stroke_len);
- for (int i = 0; i < stroke_len; i++) {
- immVertex3fv(pos, coord_array[i]);
- }
- immEnd();
-
- /* Reset defaults */
- GPU_depth_test(true);
- GPU_blend(false);
- GPU_line_smooth(false);
-
- immUnbindProgram();
- }
-
- MEM_freeN(coord_array);
- }
+ wmOperator *op = arg;
+ struct CurveDrawData *cdd = op->customdata;
+
+ const int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
+
+ if (stroke_len == 0) {
+ return;
+ }
+
+ Object *obedit = cdd->vc.obedit;
+ Curve *cu = obedit->data;
+
+ if (cu->ext2 > 0.0f) {
+ BLI_mempool_iter iter;
+ const struct StrokeElem *selem;
+
+ const float location_zero[3] = {0};
+ const float *location_prev = location_zero;
+
+ float color[3];
+ UI_GetThemeColor3fv(TH_WIRE, color);
+
+ GPUBatch *sphere = GPU_batch_preset_sphere(0);
+ GPU_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR);
+ GPU_batch_uniform_3fv(sphere, "color", color);
+
+ /* scale to edit-mode space */
+ GPU_matrix_push();
+ GPU_matrix_mul(obedit->obmat);
+
+ BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
+ for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
+ GPU_matrix_translate_3f(selem->location_local[0] - location_prev[0],
+ selem->location_local[1] - location_prev[1],
+ selem->location_local[2] - location_prev[2]);
+ location_prev = selem->location_local;
+
+ const float radius = stroke_elem_radius(cdd, selem);
+
+ GPU_matrix_push();
+ GPU_matrix_scale_1f(radius);
+ GPU_batch_draw(sphere);
+ GPU_matrix_pop();
+
+ location_prev = selem->location_local;
+ }
+
+ GPU_matrix_pop();
+ }
+
+ if (stroke_len > 1) {
+ float(*coord_array)[3] = MEM_mallocN(sizeof(*coord_array) * stroke_len, __func__);
+
+ {
+ BLI_mempool_iter iter;
+ const struct StrokeElem *selem;
+ int i;
+ BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
+ for (selem = BLI_mempool_iterstep(&iter), i = 0; selem;
+ selem = BLI_mempool_iterstep(&iter), i++) {
+ copy_v3_v3(coord_array[i], selem->location_world);
+ }
+ }
+
+ {
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ GPU_depth_test(false);
+ GPU_blend(true);
+ GPU_line_smooth(true);
+ GPU_line_width(3.0f);
+
+ imm_cpack(0x0);
+ immBegin(GPU_PRIM_LINE_STRIP, stroke_len);
+ for (int i = 0; i < stroke_len; i++) {
+ immVertex3fv(pos, coord_array[i]);
+ }
+ immEnd();
+
+ GPU_line_width(1.0f);
+
+ imm_cpack(0xffffffff);
+ immBegin(GPU_PRIM_LINE_STRIP, stroke_len);
+ for (int i = 0; i < stroke_len; i++) {
+ immVertex3fv(pos, coord_array[i]);
+ }
+ immEnd();
+
+ /* Reset defaults */
+ GPU_depth_test(true);
+ GPU_blend(false);
+ GPU_line_smooth(false);
+
+ immUnbindProgram();
+ }
+
+ MEM_freeN(coord_array);
+ }
}
static void curve_draw_event_add(wmOperator *op, const wmEvent *event)
{
- struct CurveDrawData *cdd = op->customdata;
- Object *obedit = cdd->vc.obedit;
-
- invert_m4_m4(obedit->imat, obedit->obmat);
-
- struct StrokeElem *selem = BLI_mempool_calloc(cdd->stroke_elem_pool);
-
- ARRAY_SET_ITEMS(selem->mval, event->mval[0], event->mval[1]);
-
- /* handle pressure sensitivity (which is supplied by tablets) */
- if (event->tablet_data) {
- const wmTabletData *wmtab = event->tablet_data;
- selem->pressure = wmtab->Pressure;
- }
- else {
- selem->pressure = 1.0f;
- }
-
- bool is_depth_found = stroke_elem_project_fallback_elem(
- cdd, cdd->prev.location_world_valid, selem);
-
- if (is_depth_found) {
- /* use the depth if a fallback wasn't used */
- copy_v3_v3(cdd->prev.location_world_valid, selem->location_world);
- }
- copy_v3_v3(cdd->prev.location_world, selem->location_world);
-
- float len_sq = len_squared_v2v2(cdd->prev.mouse, selem->mval);
- copy_v2_v2(cdd->prev.mouse, selem->mval);
-
- 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)) {
- int n = (int)ceil(sqrt((double)len_sq)) / STROKE_SAMPLE_DIST_MAX_PX ;
-
- for (int i = 1; i < n; i++) {
- struct StrokeElem *selem_new = selem_new_last;
- stroke_elem_interp(selem_new, cdd->prev.selem, &selem_target, (float)i / n);
-
- const bool is_depth_found_substep = stroke_elem_project_fallback_elem(
- cdd, cdd->prev.location_world_valid, selem_new);
- if (is_depth_found == false) {
- if (is_depth_found_substep) {
- copy_v3_v3(cdd->prev.location_world_valid, selem_new->location_world);
- }
- }
-
- selem_new_last = BLI_mempool_calloc(cdd->stroke_elem_pool);
- }
- }
- selem = selem_new_last;
- *selem_new_last = selem_target;
- }
-
- cdd->prev.selem = selem;
-
- ED_region_tag_redraw(cdd->vc.ar);
+ struct CurveDrawData *cdd = op->customdata;
+ Object *obedit = cdd->vc.obedit;
+
+ invert_m4_m4(obedit->imat, obedit->obmat);
+
+ struct StrokeElem *selem = BLI_mempool_calloc(cdd->stroke_elem_pool);
+
+ ARRAY_SET_ITEMS(selem->mval, event->mval[0], event->mval[1]);
+
+ /* handle pressure sensitivity (which is supplied by tablets) */
+ if (event->tablet_data) {
+ const wmTabletData *wmtab = event->tablet_data;
+ selem->pressure = wmtab->Pressure;
+ }
+ else {
+ selem->pressure = 1.0f;
+ }
+
+ bool is_depth_found = stroke_elem_project_fallback_elem(
+ cdd, cdd->prev.location_world_valid, selem);
+
+ if (is_depth_found) {
+ /* use the depth if a fallback wasn't used */
+ copy_v3_v3(cdd->prev.location_world_valid, selem->location_world);
+ }
+ copy_v3_v3(cdd->prev.location_world, selem->location_world);
+
+ float len_sq = len_squared_v2v2(cdd->prev.mouse, selem->mval);
+ copy_v2_v2(cdd->prev.mouse, selem->mval);
+
+ 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)) {
+ int n = (int)ceil(sqrt((double)len_sq)) / STROKE_SAMPLE_DIST_MAX_PX;
+
+ for (int i = 1; i < n; i++) {
+ struct StrokeElem *selem_new = selem_new_last;
+ stroke_elem_interp(selem_new, cdd->prev.selem, &selem_target, (float)i / n);
+
+ const bool is_depth_found_substep = stroke_elem_project_fallback_elem(
+ cdd, cdd->prev.location_world_valid, selem_new);
+ if (is_depth_found == false) {
+ if (is_depth_found_substep) {
+ copy_v3_v3(cdd->prev.location_world_valid, selem_new->location_world);
+ }
+ }
+
+ selem_new_last = BLI_mempool_calloc(cdd->stroke_elem_pool);
+ }
+ }
+ selem = selem_new_last;
+ *selem_new_last = selem_target;
+ }
+
+ cdd->prev.selem = selem;
+
+ ED_region_tag_redraw(cdd->vc.ar);
}
static void curve_draw_event_add_first(wmOperator *op, const wmEvent *event)
{
- struct CurveDrawData *cdd = op->customdata;
- const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings;
-
- /* add first point */
- curve_draw_event_add(op, event);
-
- if ((cps->depth_mode == CURVE_PAINT_PROJECT_SURFACE) && cdd->project.use_depth &&
- (cps->flag & CURVE_PAINT_FLAG_DEPTH_STROKE_ENDPOINTS))
- {
- RegionView3D *rv3d = cdd->vc.rv3d;
-
- cdd->project.use_depth = false;
- cdd->project.use_plane = true;
-
- float normal[3] = {0.0f};
- if (ELEM(cps->surface_plane,
- CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW,
- CURVE_PAINT_SURFACE_PLANE_NORMAL_SURFACE))
- {
- if (ED_view3d_depth_read_cached_normal(&cdd->vc, event->mval, normal)) {
- if (cps->surface_plane == CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW) {
- float cross_a[3], cross_b[3];
- cross_v3_v3v3(cross_a, rv3d->viewinv[2], normal);
- cross_v3_v3v3(cross_b, normal, cross_a);
- copy_v3_v3(normal, cross_b);
- }
- }
- }
-
- /* CURVE_PAINT_SURFACE_PLANE_VIEW or fallback */
- if (is_zero_v3(normal)) {
- copy_v3_v3(normal, rv3d->viewinv[2]);
- }
-
- normalize_v3_v3(cdd->project.plane, normal);
- cdd->project.plane[3] = -dot_v3v3(cdd->project.plane, cdd->prev.location_world_valid);
-
- /* Special case for when we only have offset applied on the first-hit,
- * the remaining stroke must be offset too. */
- if (cdd->project.surface_offset != 0.0f) {
- const float mval_fl[2] = {UNPACK2(event->mval)};
-
- float location_no_offset[3];
-
- if (stroke_elem_project(
- cdd, event->mval, mval_fl, 0.0f, 0.0f,
- location_no_offset, NULL))
- {
- sub_v3_v3v3(cdd->project.offset, cdd->prev.location_world_valid, location_no_offset);
- if (!is_zero_v3(cdd->project.offset)) {
- cdd->project.use_offset = true;
- }
- }
- }
- /* end special case */
-
- }
-
- cdd->init_event_type = event->type;
- cdd->state = CURVE_DRAW_PAINTING;
+ struct CurveDrawData *cdd = op->customdata;
+ const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings;
+
+ /* add first point */
+ curve_draw_event_add(op, event);
+
+ if ((cps->depth_mode == CURVE_PAINT_PROJECT_SURFACE) && cdd->project.use_depth &&
+ (cps->flag & CURVE_PAINT_FLAG_DEPTH_STROKE_ENDPOINTS)) {
+ RegionView3D *rv3d = cdd->vc.rv3d;
+
+ cdd->project.use_depth = false;
+ cdd->project.use_plane = true;
+
+ float normal[3] = {0.0f};
+ if (ELEM(cps->surface_plane,
+ CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW,
+ CURVE_PAINT_SURFACE_PLANE_NORMAL_SURFACE)) {
+ if (ED_view3d_depth_read_cached_normal(&cdd->vc, event->mval, normal)) {
+ if (cps->surface_plane == CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW) {
+ float cross_a[3], cross_b[3];
+ cross_v3_v3v3(cross_a, rv3d->viewinv[2], normal);
+ cross_v3_v3v3(cross_b, normal, cross_a);
+ copy_v3_v3(normal, cross_b);
+ }
+ }
+ }
+
+ /* CURVE_PAINT_SURFACE_PLANE_VIEW or fallback */
+ if (is_zero_v3(normal)) {
+ copy_v3_v3(normal, rv3d->viewinv[2]);
+ }
+
+ normalize_v3_v3(cdd->project.plane, normal);
+ cdd->project.plane[3] = -dot_v3v3(cdd->project.plane, cdd->prev.location_world_valid);
+
+ /* Special case for when we only have offset applied on the first-hit,
+ * the remaining stroke must be offset too. */
+ if (cdd->project.surface_offset != 0.0f) {
+ const float mval_fl[2] = {UNPACK2(event->mval)};
+
+ float location_no_offset[3];
+
+ if (stroke_elem_project(cdd, event->mval, mval_fl, 0.0f, 0.0f, location_no_offset, NULL)) {
+ sub_v3_v3v3(cdd->project.offset, cdd->prev.location_world_valid, location_no_offset);
+ if (!is_zero_v3(cdd->project.offset)) {
+ cdd->project.use_offset = true;
+ }
+ }
+ }
+ /* end special case */
+ }
+
+ cdd->init_event_type = event->type;
+ cdd->state = CURVE_DRAW_PAINTING;
}
static bool curve_draw_init(bContext *C, wmOperator *op, bool is_invoke)
{
- BLI_assert(op->customdata == NULL);
+ BLI_assert(op->customdata == NULL);
- struct CurveDrawData *cdd = MEM_callocN(sizeof(*cdd), __func__);
+ struct CurveDrawData *cdd = MEM_callocN(sizeof(*cdd), __func__);
- cdd->depsgraph = CTX_data_depsgraph(C);
+ cdd->depsgraph = CTX_data_depsgraph(C);
- if (is_invoke) {
- ED_view3d_viewcontext_init(C, &cdd->vc);
- if (ELEM(NULL, cdd->vc.ar, 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;
- }
- }
- else {
- cdd->vc.bmain = CTX_data_main(C);
- cdd->vc.depsgraph = CTX_data_depsgraph(C);
- cdd->vc.scene = CTX_data_scene(C);
- cdd->vc.view_layer = CTX_data_view_layer(C);
- cdd->vc.obedit = CTX_data_edit_object(C);
- }
+ if (is_invoke) {
+ ED_view3d_viewcontext_init(C, &cdd->vc);
+ if (ELEM(NULL, cdd->vc.ar, 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;
+ }
+ }
+ else {
+ cdd->vc.bmain = CTX_data_main(C);
+ cdd->vc.depsgraph = CTX_data_depsgraph(C);
+ cdd->vc.scene = CTX_data_scene(C);
+ cdd->vc.view_layer = CTX_data_view_layer(C);
+ cdd->vc.obedit = CTX_data_edit_object(C);
+ }
- op->customdata = cdd;
+ op->customdata = cdd;
- const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings;
+ const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings;
- cdd->curve_type = cps->curve_type;
+ cdd->curve_type = cps->curve_type;
- cdd->radius.min = cps->radius_min;
- cdd->radius.max = cps->radius_max;
- cdd->radius.range = cps->radius_max - cps->radius_min;
- cdd->project.surface_offset = cps->surface_offset;
- cdd->project.use_surface_offset_absolute = (cps->flag & CURVE_PAINT_FLAG_DEPTH_STROKE_OFFSET_ABS) != 0;
+ cdd->radius.min = cps->radius_min;
+ cdd->radius.max = cps->radius_max;
+ cdd->radius.range = cps->radius_max - cps->radius_min;
+ cdd->project.surface_offset = cps->surface_offset;
+ cdd->project.use_surface_offset_absolute = (cps->flag &
+ CURVE_PAINT_FLAG_DEPTH_STROKE_OFFSET_ABS) != 0;
- cdd->stroke_elem_pool = BLI_mempool_create(
- sizeof(struct StrokeElem), 0, 512, BLI_MEMPOOL_ALLOW_ITER);
+ cdd->stroke_elem_pool = BLI_mempool_create(
+ sizeof(struct StrokeElem), 0, 512, BLI_MEMPOOL_ALLOW_ITER);
- return true;
+ return true;
}
-
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);
- WM_cursor_modal_restore(cdd->vc.win);
- }
-
- if (cdd->stroke_elem_pool) {
- BLI_mempool_destroy(cdd->stroke_elem_pool);
- }
-
- MEM_freeN(cdd);
- op->customdata = NULL;
- }
+ 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);
+ WM_cursor_modal_restore(cdd->vc.win);
+ }
+
+ if (cdd->stroke_elem_pool) {
+ BLI_mempool_destroy(cdd->stroke_elem_pool);
+ }
+
+ MEM_freeN(cdd);
+ op->customdata = NULL;
+ }
}
/**
@@ -645,583 +638,601 @@ static void curve_draw_exit(wmOperator *op)
*/
static void curve_draw_exec_precalc(wmOperator *op)
{
- struct CurveDrawData *cdd = op->customdata;
- const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings;
- PropertyRNA *prop;
-
- prop = RNA_struct_find_property(op->ptr, "fit_method");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_enum_set(op->ptr, prop, cps->fit_method);
- }
-
- prop = RNA_struct_find_property(op->ptr, "corner_angle");
- if (!RNA_property_is_set(op->ptr, prop)) {
- const float corner_angle = (cps->flag & CURVE_PAINT_FLAG_CORNERS_DETECT) ? cps->corner_angle : (float)M_PI;
- RNA_property_float_set(op->ptr, prop, corner_angle);
- }
-
- prop = RNA_struct_find_property(op->ptr, "error_threshold");
- if (!RNA_property_is_set(op->ptr, prop)) {
-
- /* error isnt set so we'll have to calculate it from the pixel values */
- BLI_mempool_iter iter;
- const struct StrokeElem *selem, *selem_prev;
-
- float len_3d = 0.0f, len_2d = 0.0f;
- float scale_px; /* pixel to local space scale */
-
- int i = 0;
- BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
- selem_prev = BLI_mempool_iterstep(&iter);
- for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter), i++) {
- len_3d += len_v3v3(selem->location_local, selem_prev->location_local);
- len_2d += len_v2v2(selem->mval, selem_prev->mval);
- selem_prev = selem;
- }
- scale_px = ((len_3d > 0.0f) && (len_2d > 0.0f)) ? (len_3d / len_2d) : 0.0f;
- float error_threshold = (cps->error_threshold * U.pixelsize) * scale_px;
- RNA_property_float_set(op->ptr, prop, error_threshold);
- }
-
- prop = RNA_struct_find_property(op->ptr, "use_cyclic");
- if (!RNA_property_is_set(op->ptr, prop)) {
- bool use_cyclic = false;
-
- if (BLI_mempool_len(cdd->stroke_elem_pool) > 2) {
- BLI_mempool_iter iter;
- const struct StrokeElem *selem, *selem_first, *selem_last;
-
- BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
- selem_first = selem_last = BLI_mempool_iterstep(&iter);
- for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
- selem_last = selem;
- }
-
- if (len_squared_v2v2(
- selem_first->mval,
- selem_last->mval) <= SQUARE(STROKE_CYCLIC_DIST_PX * U.pixelsize))
- {
- use_cyclic = true;
- }
- }
-
- RNA_property_boolean_set(op->ptr, prop, use_cyclic);
- }
-
-
- if ((cps->radius_taper_start != 0.0f) ||
- (cps->radius_taper_end != 0.0f))
- {
- /* note, we could try to de-duplicate the length calculations above */
- const int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
-
- BLI_mempool_iter iter;
- struct StrokeElem *selem, *selem_prev;
-
- float *lengths = MEM_mallocN(sizeof(float) * stroke_len, __func__);
- struct StrokeElem **selem_array = MEM_mallocN(sizeof(*selem_array) * stroke_len, __func__);
- lengths[0] = 0.0f;
-
- float len_3d = 0.0f;
-
- int i = 1;
- BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
- selem_prev = BLI_mempool_iterstep(&iter);
- selem_array[0] = selem_prev;
- for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter), i++) {
- const float len_3d_segment = len_v3v3(selem->location_local, selem_prev->location_local);
- len_3d += len_3d_segment;
- lengths[i] = len_3d;
- selem_array[i] = selem;
- selem_prev = selem;
- }
-
- if (cps->radius_taper_start != 0.0f) {
- const float len_taper_max = cps->radius_taper_start * len_3d;
- for (i = 0; i < stroke_len && lengths[i] < len_taper_max; i++) {
- const float pressure_new = selem_array[i]->pressure * (lengths[i] / len_taper_max);
- stroke_elem_pressure_set(cdd, selem_array[i], pressure_new);
- }
- }
-
- if (cps->radius_taper_end != 0.0f) {
- const float len_taper_max = cps->radius_taper_end * len_3d;
- const float len_taper_min = len_3d - len_taper_max;
- for (i = stroke_len - 1; i > 0 && lengths[i] > len_taper_min; i--) {
- const float pressure_new = selem_array[i]->pressure * ((len_3d - lengths[i]) / len_taper_max);
- stroke_elem_pressure_set(cdd, selem_array[i], pressure_new);
- }
- }
-
- MEM_freeN(lengths);
- MEM_freeN(selem_array);
- }
+ struct CurveDrawData *cdd = op->customdata;
+ const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings;
+ PropertyRNA *prop;
+
+ prop = RNA_struct_find_property(op->ptr, "fit_method");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_enum_set(op->ptr, prop, cps->fit_method);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "corner_angle");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ const float corner_angle = (cps->flag & CURVE_PAINT_FLAG_CORNERS_DETECT) ? cps->corner_angle :
+ (float)M_PI;
+ RNA_property_float_set(op->ptr, prop, corner_angle);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "error_threshold");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+
+ /* error isnt set so we'll have to calculate it from the pixel values */
+ BLI_mempool_iter iter;
+ const struct StrokeElem *selem, *selem_prev;
+
+ float len_3d = 0.0f, len_2d = 0.0f;
+ float scale_px; /* pixel to local space scale */
+
+ int i = 0;
+ BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
+ selem_prev = BLI_mempool_iterstep(&iter);
+ for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter), i++) {
+ len_3d += len_v3v3(selem->location_local, selem_prev->location_local);
+ len_2d += len_v2v2(selem->mval, selem_prev->mval);
+ selem_prev = selem;
+ }
+ scale_px = ((len_3d > 0.0f) && (len_2d > 0.0f)) ? (len_3d / len_2d) : 0.0f;
+ float error_threshold = (cps->error_threshold * U.pixelsize) * scale_px;
+ RNA_property_float_set(op->ptr, prop, error_threshold);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "use_cyclic");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ bool use_cyclic = false;
+
+ if (BLI_mempool_len(cdd->stroke_elem_pool) > 2) {
+ BLI_mempool_iter iter;
+ const struct StrokeElem *selem, *selem_first, *selem_last;
+
+ BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
+ selem_first = selem_last = BLI_mempool_iterstep(&iter);
+ for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
+ selem_last = selem;
+ }
+
+ if (len_squared_v2v2(selem_first->mval, selem_last->mval) <=
+ SQUARE(STROKE_CYCLIC_DIST_PX * U.pixelsize)) {
+ use_cyclic = true;
+ }
+ }
+
+ RNA_property_boolean_set(op->ptr, prop, use_cyclic);
+ }
+
+ if ((cps->radius_taper_start != 0.0f) || (cps->radius_taper_end != 0.0f)) {
+ /* note, we could try to de-duplicate the length calculations above */
+ const int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
+
+ BLI_mempool_iter iter;
+ struct StrokeElem *selem, *selem_prev;
+
+ float *lengths = MEM_mallocN(sizeof(float) * stroke_len, __func__);
+ struct StrokeElem **selem_array = MEM_mallocN(sizeof(*selem_array) * stroke_len, __func__);
+ lengths[0] = 0.0f;
+
+ float len_3d = 0.0f;
+
+ int i = 1;
+ BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
+ selem_prev = BLI_mempool_iterstep(&iter);
+ selem_array[0] = selem_prev;
+ for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter), i++) {
+ const float len_3d_segment = len_v3v3(selem->location_local, selem_prev->location_local);
+ len_3d += len_3d_segment;
+ lengths[i] = len_3d;
+ selem_array[i] = selem;
+ selem_prev = selem;
+ }
+
+ if (cps->radius_taper_start != 0.0f) {
+ const float len_taper_max = cps->radius_taper_start * len_3d;
+ for (i = 0; i < stroke_len && lengths[i] < len_taper_max; i++) {
+ const float pressure_new = selem_array[i]->pressure * (lengths[i] / len_taper_max);
+ stroke_elem_pressure_set(cdd, selem_array[i], pressure_new);
+ }
+ }
+
+ if (cps->radius_taper_end != 0.0f) {
+ const float len_taper_max = cps->radius_taper_end * len_3d;
+ const float len_taper_min = len_3d - len_taper_max;
+ for (i = stroke_len - 1; i > 0 && lengths[i] > len_taper_min; i--) {
+ const float pressure_new = selem_array[i]->pressure *
+ ((len_3d - lengths[i]) / len_taper_max);
+ stroke_elem_pressure_set(cdd, selem_array[i], pressure_new);
+ }
+ }
+
+ MEM_freeN(lengths);
+ MEM_freeN(selem_array);
+ }
}
static int curve_draw_exec(bContext *C, wmOperator *op)
{
- if (op->customdata == NULL) {
- if (!curve_draw_init(C, op, false)) {
- return OPERATOR_CANCELLED;
- }
- }
+ if (op->customdata == NULL) {
+ if (!curve_draw_init(C, op, false)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
- struct CurveDrawData *cdd = op->customdata;
+ struct CurveDrawData *cdd = op->customdata;
- const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings;
- Object *obedit = cdd->vc.obedit;
- Curve *cu = obedit->data;
- ListBase *nurblist = object_editcurve_get(obedit);
+ const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings;
+ Object *obedit = cdd->vc.obedit;
+ Curve *cu = obedit->data;
+ ListBase *nurblist = object_editcurve_get(obedit);
- int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
+ int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
- const bool is_3d = (cu->flag & CU_3D) != 0;
- invert_m4_m4(obedit->imat, obedit->obmat);
+ const bool is_3d = (cu->flag & CU_3D) != 0;
+ invert_m4_m4(obedit->imat, obedit->obmat);
- if (BLI_mempool_len(cdd->stroke_elem_pool) == 0) {
- curve_draw_stroke_from_operator(op);
- stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
- }
+ if (BLI_mempool_len(cdd->stroke_elem_pool) == 0) {
+ curve_draw_stroke_from_operator(op);
+ stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
+ }
- /* Deselect all existing curves. */
- ED_curve_deselect_all_multi(C);
+ /* Deselect all existing curves. */
+ ED_curve_deselect_all_multi(C);
- const float radius_min = cps->radius_min;
- const float radius_max = cps->radius_max;
- const float radius_range = cps->radius_max - cps->radius_min;
+ const float radius_min = cps->radius_min;
+ const float radius_max = cps->radius_max;
+ const float radius_range = cps->radius_max - cps->radius_min;
- Nurb *nu = MEM_callocN(sizeof(Nurb), __func__);
- nu->pntsv = 0;
- nu->resolu = cu->resolu;
- nu->resolv = cu->resolv;
- nu->flag |= CU_SMOOTH;
+ Nurb *nu = MEM_callocN(sizeof(Nurb), __func__);
+ nu->pntsv = 0;
+ nu->resolu = cu->resolu;
+ nu->resolv = cu->resolv;
+ nu->flag |= CU_SMOOTH;
- const bool use_pressure_radius =
- (cps->flag & CURVE_PAINT_FLAG_PRESSURE_RADIUS) ||
- ((cps->radius_taper_start != 0.0f) ||
- (cps->radius_taper_end != 0.0f));
+ const bool use_pressure_radius = (cps->flag & CURVE_PAINT_FLAG_PRESSURE_RADIUS) ||
+ ((cps->radius_taper_start != 0.0f) ||
+ (cps->radius_taper_end != 0.0f));
- if (cdd->curve_type == CU_BEZIER) {
- nu->type = CU_BEZIER;
+ if (cdd->curve_type == CU_BEZIER) {
+ nu->type = CU_BEZIER;
#ifdef USE_SPLINE_FIT
- /* Allow to interpolate multiple channels */
- int dims = 3;
- struct {
- int radius;
- } coords_indices;
- coords_indices.radius = use_pressure_radius ? dims++ : -1;
-
- float *coords = MEM_mallocN(sizeof(*coords) * stroke_len * dims, __func__);
-
- float *cubic_spline = NULL;
- unsigned int cubic_spline_len = 0;
-
- /* error in object local space */
- const int fit_method = RNA_enum_get(op->ptr, "fit_method");
- const float error_threshold = RNA_float_get(op->ptr, "error_threshold");
- const float corner_angle = RNA_float_get(op->ptr, "corner_angle");
- const bool use_cyclic = RNA_boolean_get(op->ptr, "use_cyclic");
-
- {
- BLI_mempool_iter iter;
- const struct StrokeElem *selem;
- float *co = coords;
-
- BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
- for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter), co += dims) {
- copy_v3_v3(co, selem->location_local);
- if (coords_indices.radius != -1) {
- co[coords_indices.radius] = selem->pressure;
- }
-
- /* remove doubles */
- if ((co != coords) && UNLIKELY(memcmp(co, co - dims, sizeof(float) * dims) == 0)) {
- co -= dims;
- stroke_len--;
- }
- }
- }
-
- unsigned int *corners = NULL;
- unsigned int 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;
-
- curve_fit_corners_detect_fl(
- coords, stroke_len, dims,
- corner_radius_min, corner_radius_max,
- samples_max, corner_angle,
- &corners, &corners_len);
- }
-
- unsigned int *corners_index = NULL;
- unsigned int corners_index_len = 0;
- unsigned int calc_flag = CURVE_FIT_CALC_HIGH_QUALIY;
-
- if ((stroke_len > 2) && use_cyclic) {
- calc_flag |= CURVE_FIT_CALC_CYCLIC;
- }
-
- int result;
- if (fit_method == CURVE_PAINT_FIT_METHOD_REFIT) {
- result = curve_fit_cubic_to_points_refit_fl(
- coords, stroke_len, dims, error_threshold, calc_flag,
- NULL, 0, corner_angle,
- &cubic_spline, &cubic_spline_len,
- NULL,
- &corners_index, &corners_index_len);
- }
- else {
- result = curve_fit_cubic_to_points_fl(
- coords, stroke_len, dims, error_threshold, calc_flag,
- corners, corners_len,
- &cubic_spline, &cubic_spline_len,
- NULL,
- &corners_index, &corners_index_len);
- }
-
- MEM_freeN(coords);
- if (corners) {
- free(corners);
- }
-
- if (result == 0) {
- nu->pntsu = cubic_spline_len;
- nu->bezt = MEM_callocN(sizeof(BezTriple) * nu->pntsu, __func__);
-
- float *co = cubic_spline;
- BezTriple *bezt = nu->bezt;
- for (int j = 0; j < cubic_spline_len; j++, bezt++, co += (dims * 3)) {
- const float *handle_l = co + (dims * 0);
- const float *pt = co + (dims * 1);
- const float *handle_r = co + (dims * 2);
-
- copy_v3_v3(bezt->vec[0], handle_l);
- copy_v3_v3(bezt->vec[1], pt);
- copy_v3_v3(bezt->vec[2], handle_r);
-
- if (coords_indices.radius != -1) {
- bezt->radius = (pt[coords_indices.radius] * cdd->radius.range) + cdd->radius.min;
- }
- else {
- bezt->radius = radius_max;
- }
-
- bezt->h1 = bezt->h2 = HD_ALIGN; /* will set to free in second pass */
- bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- }
-
- if (corners_index) {
- /* ignore the first and last */
- unsigned int 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++) {
- bezt = &nu->bezt[corners_index[i]];
- bezt->h1 = bezt->h2 = HD_FREE;
- }
- }
-
- if (calc_flag & CURVE_FIT_CALC_CYCLIC) {
- nu->flagu |= CU_NURB_CYCLIC;
- }
- }
-
- if (corners_index) {
- free(corners_index);
- }
-
- if (cubic_spline) {
- free(cubic_spline);
- }
+ /* Allow to interpolate multiple channels */
+ int dims = 3;
+ struct {
+ int radius;
+ } coords_indices;
+ coords_indices.radius = use_pressure_radius ? dims++ : -1;
+
+ float *coords = MEM_mallocN(sizeof(*coords) * stroke_len * dims, __func__);
+
+ float *cubic_spline = NULL;
+ unsigned int cubic_spline_len = 0;
+
+ /* error in object local space */
+ const int fit_method = RNA_enum_get(op->ptr, "fit_method");
+ const float error_threshold = RNA_float_get(op->ptr, "error_threshold");
+ const float corner_angle = RNA_float_get(op->ptr, "corner_angle");
+ const bool use_cyclic = RNA_boolean_get(op->ptr, "use_cyclic");
+
+ {
+ BLI_mempool_iter iter;
+ const struct StrokeElem *selem;
+ float *co = coords;
+
+ BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
+ for (selem = BLI_mempool_iterstep(&iter); selem;
+ selem = BLI_mempool_iterstep(&iter), co += dims) {
+ copy_v3_v3(co, selem->location_local);
+ if (coords_indices.radius != -1) {
+ co[coords_indices.radius] = selem->pressure;
+ }
+
+ /* remove doubles */
+ if ((co != coords) && UNLIKELY(memcmp(co, co - dims, sizeof(float) * dims) == 0)) {
+ co -= dims;
+ stroke_len--;
+ }
+ }
+ }
+
+ unsigned int *corners = NULL;
+ unsigned int 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;
+
+ curve_fit_corners_detect_fl(coords,
+ stroke_len,
+ dims,
+ corner_radius_min,
+ corner_radius_max,
+ samples_max,
+ corner_angle,
+ &corners,
+ &corners_len);
+ }
+
+ unsigned int *corners_index = NULL;
+ unsigned int corners_index_len = 0;
+ unsigned int calc_flag = CURVE_FIT_CALC_HIGH_QUALIY;
+
+ if ((stroke_len > 2) && use_cyclic) {
+ calc_flag |= CURVE_FIT_CALC_CYCLIC;
+ }
+
+ int result;
+ if (fit_method == CURVE_PAINT_FIT_METHOD_REFIT) {
+ result = curve_fit_cubic_to_points_refit_fl(coords,
+ stroke_len,
+ dims,
+ error_threshold,
+ calc_flag,
+ NULL,
+ 0,
+ corner_angle,
+ &cubic_spline,
+ &cubic_spline_len,
+ NULL,
+ &corners_index,
+ &corners_index_len);
+ }
+ else {
+ result = curve_fit_cubic_to_points_fl(coords,
+ stroke_len,
+ dims,
+ error_threshold,
+ calc_flag,
+ corners,
+ corners_len,
+ &cubic_spline,
+ &cubic_spline_len,
+ NULL,
+ &corners_index,
+ &corners_index_len);
+ }
+
+ MEM_freeN(coords);
+ if (corners) {
+ free(corners);
+ }
+
+ if (result == 0) {
+ nu->pntsu = cubic_spline_len;
+ nu->bezt = MEM_callocN(sizeof(BezTriple) * nu->pntsu, __func__);
+
+ float *co = cubic_spline;
+ BezTriple *bezt = nu->bezt;
+ for (int j = 0; j < cubic_spline_len; j++, bezt++, co += (dims * 3)) {
+ const float *handle_l = co + (dims * 0);
+ const float *pt = co + (dims * 1);
+ const float *handle_r = co + (dims * 2);
+
+ copy_v3_v3(bezt->vec[0], handle_l);
+ copy_v3_v3(bezt->vec[1], pt);
+ copy_v3_v3(bezt->vec[2], handle_r);
+
+ if (coords_indices.radius != -1) {
+ bezt->radius = (pt[coords_indices.radius] * cdd->radius.range) + cdd->radius.min;
+ }
+ else {
+ bezt->radius = radius_max;
+ }
+
+ bezt->h1 = bezt->h2 = HD_ALIGN; /* will set to free in second pass */
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ }
+
+ if (corners_index) {
+ /* ignore the first and last */
+ unsigned int 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++) {
+ bezt = &nu->bezt[corners_index[i]];
+ bezt->h1 = bezt->h2 = HD_FREE;
+ }
+ }
+
+ if (calc_flag & CURVE_FIT_CALC_CYCLIC) {
+ nu->flagu |= CU_NURB_CYCLIC;
+ }
+ }
+
+ if (corners_index) {
+ free(corners_index);
+ }
+
+ if (cubic_spline) {
+ free(cubic_spline);
+ }
#else
- nu->pntsu = stroke_len;
- nu->bezt = MEM_callocN(nu->pntsu * sizeof(BezTriple), __func__);
-
- BezTriple *bezt = nu->bezt;
-
- {
- BLI_mempool_iter iter;
- const struct StrokeElem *selem;
-
- BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
- for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
- copy_v3_v3(bezt->vec[1], selem->location_local);
- if (!is_3d) {
- bezt->vec[1][2] = 0.0f;
- }
-
- if (use_pressure_radius) {
- bezt->radius = selem->pressure;
- }
- else {
- bezt->radius = radius_max;
- }
-
- bezt->h1 = bezt->h2 = HD_AUTO;
-
- bezt->f1 |= SELECT;
- bezt->f2 |= SELECT;
- bezt->f3 |= SELECT;
-
- bezt++;
- }
- }
+ nu->pntsu = stroke_len;
+ nu->bezt = MEM_callocN(nu->pntsu * sizeof(BezTriple), __func__);
+
+ BezTriple *bezt = nu->bezt;
+
+ {
+ BLI_mempool_iter iter;
+ const struct StrokeElem *selem;
+
+ BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
+ for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
+ copy_v3_v3(bezt->vec[1], selem->location_local);
+ if (!is_3d) {
+ bezt->vec[1][2] = 0.0f;
+ }
+
+ if (use_pressure_radius) {
+ bezt->radius = selem->pressure;
+ }
+ else {
+ bezt->radius = radius_max;
+ }
+
+ bezt->h1 = bezt->h2 = HD_AUTO;
+
+ bezt->f1 |= SELECT;
+ bezt->f2 |= SELECT;
+ bezt->f3 |= SELECT;
+
+ bezt++;
+ }
+ }
#endif
- BKE_nurb_handles_calc(nu);
- }
- else { /* CU_POLY */
- BLI_mempool_iter iter;
- const struct StrokeElem *selem;
+ BKE_nurb_handles_calc(nu);
+ }
+ else { /* CU_POLY */
+ BLI_mempool_iter iter;
+ const struct StrokeElem *selem;
- nu->pntsu = stroke_len;
- nu->pntsv = 1;
- nu->type = CU_POLY;
- nu->bp = MEM_callocN(nu->pntsu * sizeof(BPoint), __func__);
+ nu->pntsu = stroke_len;
+ nu->pntsv = 1;
+ nu->type = CU_POLY;
+ nu->bp = MEM_callocN(nu->pntsu * sizeof(BPoint), __func__);
- /* Misc settings. */
- nu->resolu = cu->resolu;
- nu->resolv = 1;
- nu->orderu = 4;
- nu->orderv = 1;
+ /* Misc settings. */
+ nu->resolu = cu->resolu;
+ nu->resolv = 1;
+ nu->orderu = 4;
+ nu->orderv = 1;
- BPoint *bp = nu->bp;
+ BPoint *bp = nu->bp;
- BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
- for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
- copy_v3_v3(bp->vec, selem->location_local);
- if (!is_3d) {
- bp->vec[2] = 0.0f;
- }
+ BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
+ for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
+ copy_v3_v3(bp->vec, selem->location_local);
+ if (!is_3d) {
+ bp->vec[2] = 0.0f;
+ }
- if (use_pressure_radius) {
- bp->radius = (selem->pressure * radius_range) + radius_min;
- }
- else {
- bp->radius = cps->radius_max;
- }
- bp->f1 = SELECT;
- bp->vec[3] = 1.0f;
+ if (use_pressure_radius) {
+ bp->radius = (selem->pressure * radius_range) + radius_min;
+ }
+ else {
+ bp->radius = cps->radius_max;
+ }
+ bp->f1 = SELECT;
+ bp->vec[3] = 1.0f;
- bp++;
- }
+ bp++;
+ }
- BKE_nurb_knot_calc_u(nu);
- }
+ BKE_nurb_knot_calc_u(nu);
+ }
- BLI_addtail(nurblist, nu);
+ BLI_addtail(nurblist, nu);
- BKE_curve_nurb_active_set(cu, nu);
- cu->actvert = nu->pntsu - 1;
+ BKE_curve_nurb_active_set(cu, nu);
+ cu->actvert = nu->pntsu - 1;
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
- curve_draw_exit(op);
+ curve_draw_exit(op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int curve_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (RNA_struct_property_is_set(op->ptr, "stroke")) {
- return curve_draw_exec(C, op);
- }
-
- if (!curve_draw_init(C, op, true)) {
- return OPERATOR_CANCELLED;
- }
-
- struct CurveDrawData *cdd = op->customdata;
-
- const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings;
-
- const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input");
-
- /* fallback (incase we can't find the depth on first test) */
- {
- 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);
- 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);
- WM_cursor_modal_set(cdd->vc.win, BC_PAINTBRUSHCURSOR);
-
- {
- View3D *v3d = cdd->vc.v3d;
- RegionView3D *rv3d = cdd->vc.rv3d;
- Object *obedit = cdd->vc.obedit;
- Curve *cu = obedit->data;
-
- const float *plane_no = NULL;
- const float *plane_co = NULL;
-
- if ((cu->flag & CU_3D) == 0) {
- /* 2D overrides other options */
- plane_co = obedit->obmat[3];
- plane_no = obedit->obmat[2];
- cdd->project.use_plane = true;
- }
- else {
- if ((cps->depth_mode == CURVE_PAINT_PROJECT_SURFACE) &&
- (v3d->shading.type > OB_WIRE))
- {
- /* 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);
-
- if (cdd->vc.rv3d->depths) {
- cdd->vc.rv3d->depths->damaged = true;
- }
-
- ED_view3d_depth_update(cdd->vc.ar);
-
- if (cdd->vc.rv3d->depths != NULL) {
- cdd->project.use_depth = true;
- }
- else {
- BKE_report(op->reports, RPT_WARNING, "Unable to access depth buffer, using view plane");
- cdd->project.use_depth = false;
- }
- }
-
- /* use view plane (when set or as fallback when surface can't be found) */
- if (cdd->project.use_depth == false) {
- plane_co = cdd->vc.scene->cursor.location;
- plane_no = rv3d->viewinv[2];
- cdd->project.use_plane = true;
- }
-
- if (cdd->project.use_depth && (cdd->curve_type != CU_POLY)) {
- cdd->sample.use_substeps = true;
- }
- }
-
- if (cdd->project.use_plane) {
- normalize_v3_v3(cdd->project.plane, plane_no);
- cdd->project.plane[3] = -dot_v3v3(cdd->project.plane, plane_co);
- }
- }
-
- if (is_modal == false) {
- curve_draw_event_add_first(op, event);
- }
-
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
+ if (RNA_struct_property_is_set(op->ptr, "stroke")) {
+ return curve_draw_exec(C, op);
+ }
+
+ if (!curve_draw_init(C, op, true)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ struct CurveDrawData *cdd = op->customdata;
+
+ const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings;
+
+ const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input");
+
+ /* fallback (incase we can't find the depth on first test) */
+ {
+ 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);
+ 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);
+ WM_cursor_modal_set(cdd->vc.win, BC_PAINTBRUSHCURSOR);
+
+ {
+ View3D *v3d = cdd->vc.v3d;
+ RegionView3D *rv3d = cdd->vc.rv3d;
+ Object *obedit = cdd->vc.obedit;
+ Curve *cu = obedit->data;
+
+ const float *plane_no = NULL;
+ const float *plane_co = NULL;
+
+ if ((cu->flag & CU_3D) == 0) {
+ /* 2D overrides other options */
+ plane_co = obedit->obmat[3];
+ plane_no = obedit->obmat[2];
+ cdd->project.use_plane = true;
+ }
+ else {
+ if ((cps->depth_mode == CURVE_PAINT_PROJECT_SURFACE) && (v3d->shading.type > OB_WIRE)) {
+ /* 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);
+
+ if (cdd->vc.rv3d->depths) {
+ cdd->vc.rv3d->depths->damaged = true;
+ }
+
+ ED_view3d_depth_update(cdd->vc.ar);
+
+ if (cdd->vc.rv3d->depths != NULL) {
+ cdd->project.use_depth = true;
+ }
+ else {
+ BKE_report(op->reports, RPT_WARNING, "Unable to access depth buffer, using view plane");
+ cdd->project.use_depth = false;
+ }
+ }
+
+ /* use view plane (when set or as fallback when surface can't be found) */
+ if (cdd->project.use_depth == false) {
+ plane_co = cdd->vc.scene->cursor.location;
+ plane_no = rv3d->viewinv[2];
+ cdd->project.use_plane = true;
+ }
+
+ if (cdd->project.use_depth && (cdd->curve_type != CU_POLY)) {
+ cdd->sample.use_substeps = true;
+ }
+ }
+
+ if (cdd->project.use_plane) {
+ normalize_v3_v3(cdd->project.plane, plane_no);
+ cdd->project.plane[3] = -dot_v3v3(cdd->project.plane, plane_co);
+ }
+ }
+
+ if (is_modal == false) {
+ curve_draw_event_add_first(op, event);
+ }
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
}
static void curve_draw_cancel(bContext *UNUSED(C), wmOperator *op)
{
- curve_draw_exit(op);
+ curve_draw_exit(op);
}
-
/* Modal event handling of frame changing */
static int curve_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- int ret = OPERATOR_RUNNING_MODAL;
- struct CurveDrawData *cdd = op->customdata;
-
- UNUSED_VARS(C, op);
-
- if (event->type == cdd->init_event_type) {
- if (event->val == KM_RELEASE) {
- ED_region_tag_redraw(cdd->vc.ar);
-
- curve_draw_exec_precalc(op);
-
- curve_draw_stroke_to_operator(op);
-
- curve_draw_exec(C, op);
-
- return OPERATOR_FINISHED;
- }
- }
- else if (ELEM(event->type, ESCKEY, RIGHTMOUSE)) {
- ED_region_tag_redraw(cdd->vc.ar);
- curve_draw_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- else if (ELEM(event->type, LEFTMOUSE)) {
- if (event->val == KM_PRESS) {
- curve_draw_event_add_first(op, 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)) {
- curve_draw_event_add(op, event);
- }
- }
- }
-
- return ret;
+ int ret = OPERATOR_RUNNING_MODAL;
+ struct CurveDrawData *cdd = op->customdata;
+
+ UNUSED_VARS(C, op);
+
+ if (event->type == cdd->init_event_type) {
+ if (event->val == KM_RELEASE) {
+ ED_region_tag_redraw(cdd->vc.ar);
+
+ curve_draw_exec_precalc(op);
+
+ curve_draw_stroke_to_operator(op);
+
+ curve_draw_exec(C, op);
+
+ return OPERATOR_FINISHED;
+ }
+ }
+ else if (ELEM(event->type, ESCKEY, RIGHTMOUSE)) {
+ ED_region_tag_redraw(cdd->vc.ar);
+ curve_draw_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ else if (ELEM(event->type, LEFTMOUSE)) {
+ if (event->val == KM_PRESS) {
+ curve_draw_event_add_first(op, 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)) {
+ curve_draw_event_add(op, event);
+ }
+ }
+ }
+
+ return ret;
}
void CURVE_OT_draw(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Draw Curve";
- ot->idname = "CURVE_OT_draw";
- ot->description = "Draw a freehand spline";
-
- /* api callbacks */
- ot->exec = curve_draw_exec;
- ot->invoke = curve_draw_invoke;
- ot->cancel = curve_draw_cancel;
- ot->modal = curve_draw_modal;
- ot->poll = ED_operator_editcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- PropertyRNA *prop;
-
- prop = RNA_def_float_distance(
- ot->srna, "error_threshold", 0.0f, 0.0f, 10.0f, "Error",
- "Error distance threshold (in object units)",
- 0.0001f, 10.0f);
- RNA_def_property_ui_range(prop, 0.0, 10, 1, 4);
-
- RNA_def_enum(ot->srna, "fit_method", rna_enum_curve_fit_method_items, CURVE_PAINT_FIT_METHOD_REFIT,
- "Fit Method", "");
-
- prop = RNA_def_float_distance(
- ot->srna, "corner_angle", DEG2RADF(70.0f), 0.0f, M_PI, "Corner Angle", "", 0.0f, M_PI);
- RNA_def_property_subtype(prop, PROP_ANGLE);
-
- prop = RNA_def_boolean(ot->srna, "use_cyclic", true, "Cyclic", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- 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);
+ /* identifiers */
+ ot->name = "Draw Curve";
+ ot->idname = "CURVE_OT_draw";
+ ot->description = "Draw a freehand spline";
+
+ /* api callbacks */
+ ot->exec = curve_draw_exec;
+ ot->invoke = curve_draw_invoke;
+ ot->cancel = curve_draw_cancel;
+ ot->modal = curve_draw_modal;
+ ot->poll = ED_operator_editcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ PropertyRNA *prop;
+
+ prop = RNA_def_float_distance(ot->srna,
+ "error_threshold",
+ 0.0f,
+ 0.0f,
+ 10.0f,
+ "Error",
+ "Error distance threshold (in object units)",
+ 0.0001f,
+ 10.0f);
+ RNA_def_property_ui_range(prop, 0.0, 10, 1, 4);
+
+ RNA_def_enum(ot->srna,
+ "fit_method",
+ rna_enum_curve_fit_method_items,
+ CURVE_PAINT_FIT_METHOD_REFIT,
+ "Fit Method",
+ "");
+
+ prop = RNA_def_float_distance(
+ ot->srna, "corner_angle", DEG2RADF(70.0f), 0.0f, M_PI, "Corner Angle", "", 0.0f, M_PI);
+ RNA_def_property_subtype(prop, PROP_ANGLE);
+
+ prop = RNA_def_boolean(ot->srna, "use_cyclic", true, "Cyclic", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ 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/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c
index d9392090166..d3f0ebfda3c 100644
--- a/source/blender/editors/curve/editcurve_select.c
+++ b/source/blender/editors/curve/editcurve_select.c
@@ -59,271 +59,272 @@
/* returns 1 in case (de)selection was successful */
bool select_beztriple(BezTriple *bezt, bool selstatus, short flag, eVisible_Types hidden)
{
- if ((bezt->hide == 0) || (hidden == HIDDEN)) {
- if (selstatus == SELECT) { /* selects */
- bezt->f1 |= flag;
- bezt->f2 |= flag;
- bezt->f3 |= flag;
- return true;
- }
- else { /* deselects */
- bezt->f1 &= ~flag;
- bezt->f2 &= ~flag;
- bezt->f3 &= ~flag;
- return true;
- }
- }
-
- return false;
+ if ((bezt->hide == 0) || (hidden == HIDDEN)) {
+ if (selstatus == SELECT) { /* selects */
+ bezt->f1 |= flag;
+ bezt->f2 |= flag;
+ bezt->f3 |= flag;
+ return true;
+ }
+ else { /* deselects */
+ bezt->f1 &= ~flag;
+ bezt->f2 &= ~flag;
+ bezt->f3 &= ~flag;
+ return true;
+ }
+ }
+
+ return false;
}
/* returns 1 in case (de)selection was successful */
bool select_bpoint(BPoint *bp, bool selstatus, short flag, bool hidden)
{
- if ((bp->hide == 0) || (hidden == 1)) {
- if (selstatus == SELECT) {
- bp->f1 |= flag;
- return true;
- }
- else {
- bp->f1 &= ~flag;
- return true;
- }
- }
-
- return false;
+ if ((bp->hide == 0) || (hidden == 1)) {
+ if (selstatus == SELECT) {
+ bp->f1 |= flag;
+ return true;
+ }
+ else {
+ bp->f1 &= ~flag;
+ return true;
+ }
+ }
+
+ return false;
}
static bool swap_selection_beztriple(BezTriple *bezt)
{
- if (bezt->f2 & SELECT) {
- return select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
- }
- else {
- return select_beztriple(bezt, SELECT, SELECT, VISIBLE);
- }
+ if (bezt->f2 & SELECT) {
+ return select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
+ }
+ else {
+ return select_beztriple(bezt, SELECT, SELECT, VISIBLE);
+ }
}
static bool swap_selection_bpoint(BPoint *bp)
{
- if (bp->f1 & SELECT) {
- return select_bpoint(bp, DESELECT, SELECT, VISIBLE);
- }
- else {
- return select_bpoint(bp, SELECT, SELECT, VISIBLE);
- }
+ if (bp->f1 & SELECT) {
+ return select_bpoint(bp, DESELECT, SELECT, VISIBLE);
+ }
+ else {
+ return select_bpoint(bp, SELECT, SELECT, VISIBLE);
+ }
}
bool ED_curve_nurb_select_check(View3D *v3d, Nurb *nu)
{
- if (nu->type == CU_BEZIER) {
- BezTriple *bezt;
- int i;
-
- for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
- return true;
- }
- }
- }
- else {
- BPoint *bp;
- int i;
-
- for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
- if (bp->f1 & SELECT) {
- return true;
- }
- }
- }
- return false;
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt;
+ int i;
+
+ for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
+ return true;
+ }
+ }
+ }
+ else {
+ BPoint *bp;
+ int i;
+
+ for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
+ if (bp->f1 & SELECT) {
+ return true;
+ }
+ }
+ }
+ return false;
}
int ED_curve_nurb_select_count(View3D *v3d, Nurb *nu)
{
- int sel = 0;
-
- if (nu->type == CU_BEZIER) {
- BezTriple *bezt;
- int i;
-
- for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
- sel++;
- }
- }
- }
- else {
- BPoint *bp;
- int i;
-
- for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
- if (bp->f1 & SELECT) {
- sel++;
- }
- }
- }
-
- return sel;
+ int sel = 0;
+
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt;
+ int i;
+
+ for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
+ sel++;
+ }
+ }
+ }
+ else {
+ BPoint *bp;
+ int i;
+
+ for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
+ if (bp->f1 & SELECT) {
+ sel++;
+ }
+ }
+ }
+
+ return sel;
}
bool ED_curve_nurb_select_all(const Nurb *nu)
{
- bool changed = false;
- int i;
- if (nu->bezt) {
- BezTriple *bezt;
- for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
- if (bezt->hide == 0) {
- if (BEZT_ISSEL_ALL(bezt) == false) {
- BEZT_SEL_ALL(bezt);
- changed = true;
- }
- }
- }
- }
- else if (nu->bp) {
- BPoint *bp;
- for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
- if (bp->hide == 0) {
- if ((bp->f1 & SELECT) == 0) {
- bp->f1 |= SELECT;
- changed = true;
- }
- }
- }
- }
- return changed;
+ bool changed = false;
+ int i;
+ if (nu->bezt) {
+ BezTriple *bezt;
+ for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
+ if (bezt->hide == 0) {
+ if (BEZT_ISSEL_ALL(bezt) == false) {
+ BEZT_SEL_ALL(bezt);
+ changed = true;
+ }
+ }
+ }
+ }
+ else if (nu->bp) {
+ BPoint *bp;
+ for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
+ if (bp->hide == 0) {
+ if ((bp->f1 & SELECT) == 0) {
+ bp->f1 |= SELECT;
+ changed = true;
+ }
+ }
+ }
+ }
+ return changed;
}
bool ED_curve_select_all(EditNurb *editnurb)
{
- bool changed = false;
- for (Nurb *nu = editnurb->nurbs.first; nu; nu = nu->next) {
- changed |= ED_curve_nurb_select_all(nu);
- }
- return changed;
+ bool changed = false;
+ for (Nurb *nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ changed |= ED_curve_nurb_select_all(nu);
+ }
+ return changed;
}
bool ED_curve_nurb_deselect_all(const Nurb *nu)
{
- bool changed = false;
- int i;
- if (nu->bezt) {
- BezTriple *bezt;
- for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
- if (BEZT_ISSEL_ANY(bezt)) {
- BEZT_DESEL_ALL(bezt);
- changed = true;
- }
- }
- }
- else if (nu->bp) {
- BPoint *bp;
- for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
- if (bp->f1 & SELECT) {
- bp->f1 &= ~SELECT;
- changed = true;
- }
- }
- }
- return changed;
+ bool changed = false;
+ int i;
+ if (nu->bezt) {
+ BezTriple *bezt;
+ for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
+ if (BEZT_ISSEL_ANY(bezt)) {
+ BEZT_DESEL_ALL(bezt);
+ changed = true;
+ }
+ }
+ }
+ else if (nu->bp) {
+ BPoint *bp;
+ for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
+ if (bp->f1 & SELECT) {
+ bp->f1 &= ~SELECT;
+ changed = true;
+ }
+ }
+ }
+ return changed;
}
int ED_curve_select_count(View3D *v3d, struct EditNurb *editnurb)
{
- int sel = 0;
- Nurb *nu;
+ int sel = 0;
+ Nurb *nu;
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
- sel += ED_curve_nurb_select_count(v3d, nu);
- }
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ sel += ED_curve_nurb_select_count(v3d, nu);
+ }
- return sel;
+ return sel;
}
bool ED_curve_select_check(View3D *v3d, struct EditNurb *editnurb)
{
- Nurb *nu;
+ Nurb *nu;
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
- if (ED_curve_nurb_select_check(v3d, nu)) {
- return true;
- }
- }
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ if (ED_curve_nurb_select_check(v3d, nu)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
bool ED_curve_deselect_all(EditNurb *editnurb)
{
- bool changed = false;
- for (Nurb *nu = editnurb->nurbs.first; nu; nu = nu->next) {
- changed |= ED_curve_nurb_deselect_all(nu);
- }
- return changed;
+ bool changed = false;
+ for (Nurb *nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ changed |= ED_curve_nurb_deselect_all(nu);
+ }
+ return changed;
}
bool ED_curve_deselect_all_multi_ex(Base **bases, int bases_len)
{
- bool changed_multi = false;
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Object *obedit = bases[base_index]->object;
- Curve *cu = obedit->data;
- changed_multi |= ED_curve_deselect_all(cu->editnurb);
- DEG_id_tag_update(&cu->id, ID_RECALC_SELECT);
- }
- return changed_multi;
+ bool changed_multi = false;
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Object *obedit = bases[base_index]->object;
+ Curve *cu = obedit->data;
+ changed_multi |= ED_curve_deselect_all(cu->editnurb);
+ DEG_id_tag_update(&cu->id, ID_RECALC_SELECT);
+ }
+ return changed_multi;
}
bool ED_curve_deselect_all_multi(struct bContext *C)
{
- ViewContext vc;
- ED_view3d_viewcontext_init(C, &vc);
- uint bases_len = 0;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &bases_len);
- bool changed_multi = ED_curve_deselect_all_multi_ex(bases, bases_len);
- MEM_freeN(bases);
- return changed_multi;
+ ViewContext vc;
+ ED_view3d_viewcontext_init(C, &vc);
+ uint bases_len = 0;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
+ vc.view_layer, vc.v3d, &bases_len);
+ bool changed_multi = ED_curve_deselect_all_multi_ex(bases, bases_len);
+ MEM_freeN(bases);
+ return changed_multi;
}
bool ED_curve_select_swap(EditNurb *editnurb, bool hide_handles)
{
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- int a;
- bool changed = false;
-
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (bezt->hide == 0) {
- bezt->f2 ^= SELECT; /* always do the center point */
- if (!hide_handles) {
- bezt->f1 ^= SELECT;
- bezt->f3 ^= SELECT;
- }
- changed = true;
- }
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (bp->hide == 0) {
- swap_selection_bpoint(bp);
- changed = true;
- }
- bp++;
- }
- }
- }
- return changed;
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a;
+ bool changed = false;
+
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ if (bezt->hide == 0) {
+ bezt->f2 ^= SELECT; /* always do the center point */
+ if (!hide_handles) {
+ bezt->f1 ^= SELECT;
+ bezt->f3 ^= SELECT;
+ }
+ changed = true;
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ if (bp->hide == 0) {
+ swap_selection_bpoint(bp);
+ changed = true;
+ }
+ bp++;
+ }
+ }
+ }
+ return changed;
}
/**
@@ -331,77 +332,80 @@ bool ED_curve_select_swap(EditNurb *editnurb, bool hide_handles)
* \param cont: when true select continuously
* \param selstatus: inverts behavior
*/
-static void select_adjacent_cp(
- ListBase *editnurb, short next,
- const bool cont, const bool selstatus)
+static void select_adjacent_cp(ListBase *editnurb,
+ short next,
+ const bool cont,
+ const bool selstatus)
{
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
- bool lastsel = false;
-
- if (next == 0) {
- return;
- }
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- lastsel = false;
- if (nu->type == CU_BEZIER) {
- a = nu->pntsu;
- bezt = nu->bezt;
- if (next < 0) {
- bezt = &nu->bezt[a - 1];
- }
- while (a--) {
- if (a - abs(next) < 0) {
- break;
- }
- if ((lastsel == false) && (bezt->hide == 0) && ((bezt->f2 & SELECT) || (selstatus == DESELECT))) {
- bezt += next;
- if (!(bezt->f2 & SELECT) || (selstatus == DESELECT)) {
- bool sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE);
- if (sel && !cont) {
- lastsel = true;
- }
- }
- }
- else {
- bezt += next;
- lastsel = false;
- }
- /* move around in zigzag way so that we go through each */
- bezt -= (next - next / abs(next));
- }
- }
- else {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- if (next < 0) {
- bp = &nu->bp[a - 1];
- }
- while (a--) {
- if (a - abs(next) < 0) {
- break;
- }
- if ((lastsel == false) && (bp->hide == 0) && ((bp->f1 & SELECT) || (selstatus == DESELECT))) {
- bp += next;
- if (!(bp->f1 & SELECT) || (selstatus == DESELECT)) {
- bool sel = select_bpoint(bp, selstatus, SELECT, VISIBLE);
- if (sel && !cont) {
- lastsel = true;
- }
- }
- }
- else {
- bp += next;
- lastsel = false;
- }
- /* move around in zigzag way so that we go through each */
- bp -= (next - next / abs(next));
- }
- }
- }
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+ bool lastsel = false;
+
+ if (next == 0) {
+ return;
+ }
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ lastsel = false;
+ if (nu->type == CU_BEZIER) {
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ if (next < 0) {
+ bezt = &nu->bezt[a - 1];
+ }
+ while (a--) {
+ if (a - abs(next) < 0) {
+ break;
+ }
+ if ((lastsel == false) && (bezt->hide == 0) &&
+ ((bezt->f2 & SELECT) || (selstatus == DESELECT))) {
+ bezt += next;
+ if (!(bezt->f2 & SELECT) || (selstatus == DESELECT)) {
+ bool sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE);
+ if (sel && !cont) {
+ lastsel = true;
+ }
+ }
+ }
+ else {
+ bezt += next;
+ lastsel = false;
+ }
+ /* move around in zigzag way so that we go through each */
+ bezt -= (next - next / abs(next));
+ }
+ }
+ else {
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ if (next < 0) {
+ bp = &nu->bp[a - 1];
+ }
+ while (a--) {
+ if (a - abs(next) < 0) {
+ break;
+ }
+ if ((lastsel == false) && (bp->hide == 0) &&
+ ((bp->f1 & SELECT) || (selstatus == DESELECT))) {
+ bp += next;
+ if (!(bp->f1 & SELECT) || (selstatus == DESELECT)) {
+ bool sel = select_bpoint(bp, selstatus, SELECT, VISIBLE);
+ if (sel && !cont) {
+ lastsel = true;
+ }
+ }
+ }
+ else {
+ bp += next;
+ lastsel = false;
+ }
+ /* move around in zigzag way so that we go through each */
+ bp -= (next - next / abs(next));
+ }
+ }
+ }
}
/**************** select start/end operators **************/
@@ -413,570 +417,579 @@ static void select_adjacent_cp(
*/
static void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap, bool selstatus)
{
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- Curve *cu;
- int a;
-
- if (obedit == NULL) {
- return;
- }
-
- cu = (Curve *)obedit->data;
- cu->actvert = CU_ACT_NONE;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- a = nu->pntsu;
-
- /* which point? */
- if (selfirst == LAST) { /* select last */
- bezt = &nu->bezt[a - 1];
- }
- else { /* select first */
- bezt = nu->bezt;
- }
-
- while (a--) {
- bool sel;
- if (doswap) {
- sel = swap_selection_beztriple(bezt);
- }
- else {
- sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE);
- }
-
- if (sel == true) {
- break;
- }
- }
- }
- else {
- a = nu->pntsu * nu->pntsv;
-
- /* which point? */
- if (selfirst == LAST) { /* select last */
- bp = &nu->bp[a - 1];
- }
- else { /* select first */
- bp = nu->bp;
- }
-
- while (a--) {
- if (bp->hide == 0) {
- bool sel;
- if (doswap) {
- sel = swap_selection_bpoint(bp);
- }
- else {
- sel = select_bpoint(bp, selstatus, SELECT, VISIBLE);
- }
-
- if (sel == true) {
- break;
- }
- }
- }
- }
- }
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ Curve *cu;
+ int a;
+
+ if (obedit == NULL) {
+ return;
+ }
+
+ cu = (Curve *)obedit->data;
+ cu->actvert = CU_ACT_NONE;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ a = nu->pntsu;
+
+ /* which point? */
+ if (selfirst == LAST) { /* select last */
+ bezt = &nu->bezt[a - 1];
+ }
+ else { /* select first */
+ bezt = nu->bezt;
+ }
+
+ while (a--) {
+ bool sel;
+ if (doswap) {
+ sel = swap_selection_beztriple(bezt);
+ }
+ else {
+ sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE);
+ }
+
+ if (sel == true) {
+ break;
+ }
+ }
+ }
+ else {
+ a = nu->pntsu * nu->pntsv;
+
+ /* which point? */
+ if (selfirst == LAST) { /* select last */
+ bp = &nu->bp[a - 1];
+ }
+ else { /* select first */
+ bp = nu->bp;
+ }
+
+ while (a--) {
+ if (bp->hide == 0) {
+ bool sel;
+ if (doswap) {
+ sel = swap_selection_bpoint(bp);
+ }
+ else {
+ sel = select_bpoint(bp, selstatus, SELECT, VISIBLE);
+ }
+
+ if (sel == true) {
+ break;
+ }
+ }
+ }
+ }
+ }
}
static int de_select_first_exec(bContext *C, wmOperator *UNUSED(op))
{
- 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];
- selectend_nurb(obedit, FIRST, true, DESELECT);
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- BKE_curve_nurb_vert_active_validate(obedit->data);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ 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];
+ selectend_nurb(obedit, FIRST, true, DESELECT);
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ BKE_curve_nurb_vert_active_validate(obedit->data);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void CURVE_OT_de_select_first(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select First";
- ot->idname = "CURVE_OT_de_select_first";
- ot->description = "(De)select first of visible part of each NURBS";
+ /* identifiers */
+ ot->name = "(De)select First";
+ ot->idname = "CURVE_OT_de_select_first";
+ ot->description = "(De)select first of visible part of each NURBS";
- /* api cfirstbacks */
- ot->exec = de_select_first_exec;
- ot->poll = ED_operator_editcurve;
+ /* api cfirstbacks */
+ ot->exec = de_select_first_exec;
+ ot->poll = ED_operator_editcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int de_select_last_exec(bContext *C, wmOperator *UNUSED(op))
{
- 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];
- selectend_nurb(obedit, LAST, true, DESELECT);
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- BKE_curve_nurb_vert_active_validate(obedit->data);
- }
-
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ 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];
+ selectend_nurb(obedit, LAST, true, DESELECT);
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ BKE_curve_nurb_vert_active_validate(obedit->data);
+ }
+
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void CURVE_OT_de_select_last(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select Last";
- ot->idname = "CURVE_OT_de_select_last";
- ot->description = "(De)select last of visible part of each NURBS";
+ /* identifiers */
+ ot->name = "(De)select Last";
+ ot->idname = "CURVE_OT_de_select_last";
+ ot->description = "(De)select last of visible part of each NURBS";
- /* api clastbacks */
- ot->exec = de_select_last_exec;
- ot->poll = ED_operator_editcurve;
+ /* api clastbacks */
+ ot->exec = de_select_last_exec;
+ ot->poll = ED_operator_editcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int de_select_all_exec(bContext *C, wmOperator *op)
{
- int action = RNA_enum_get(op->ptr, "action");
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(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);
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Curve *cu = obedit->data;
-
- if (ED_curve_select_check(v3d, cu->editnurb)) {
- action = SEL_DESELECT;
- break;
- }
- }
- }
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Curve *cu = obedit->data;
- bool changed = false;
-
- switch (action) {
- case SEL_SELECT:
- changed = ED_curve_select_all(cu->editnurb);
- break;
- case SEL_DESELECT:
- changed = ED_curve_deselect_all(cu->editnurb);
- break;
- case SEL_INVERT:
- changed = ED_curve_select_swap(cu->editnurb, (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0);
- break;
- }
-
- if (changed) {
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- BKE_curve_nurb_vert_active_validate(cu);
- }
- }
-
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ int action = RNA_enum_get(op->ptr, "action");
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(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);
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Curve *cu = obedit->data;
+
+ if (ED_curve_select_check(v3d, cu->editnurb)) {
+ action = SEL_DESELECT;
+ break;
+ }
+ }
+ }
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Curve *cu = obedit->data;
+ bool changed = false;
+
+ switch (action) {
+ case SEL_SELECT:
+ changed = ED_curve_select_all(cu->editnurb);
+ break;
+ case SEL_DESELECT:
+ changed = ED_curve_deselect_all(cu->editnurb);
+ break;
+ case SEL_INVERT:
+ changed = ED_curve_select_swap(
+ cu->editnurb, (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0);
+ break;
+ }
+
+ if (changed) {
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ BKE_curve_nurb_vert_active_validate(cu);
+ }
+ }
+
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void CURVE_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All";
- ot->idname = "CURVE_OT_select_all";
- ot->description = "(De)select all control points";
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->idname = "CURVE_OT_select_all";
+ ot->description = "(De)select all control points";
- /* api callbacks */
- ot->exec = de_select_all_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = de_select_all_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_select_all(ot);
+ /* properties */
+ WM_operator_properties_select_all(ot);
}
-
-
/***************** select linked operator ******************/
static int select_linked_exec(bContext *C, wmOperator *UNUSED(op))
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(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];
- Curve *cu = obedit->data;
- EditNurb *editnurb = cu->editnurb;
- ListBase *nurbs = &editnurb->nurbs;
- Nurb *nu;
- bool changed = false;
-
- for (nu = nurbs->first; nu; nu = nu->next) {
- if (ED_curve_nurb_select_check(v3d, nu)) {
- changed |= ED_curve_nurb_select_all(nu);
- }
- }
-
- if (changed) {
- 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;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(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];
+ Curve *cu = obedit->data;
+ EditNurb *editnurb = cu->editnurb;
+ ListBase *nurbs = &editnurb->nurbs;
+ Nurb *nu;
+ bool changed = false;
+
+ for (nu = nurbs->first; nu; nu = nu->next) {
+ if (ED_curve_nurb_select_check(v3d, nu)) {
+ changed |= ED_curve_nurb_select_all(nu);
+ }
+ }
+
+ if (changed) {
+ 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 select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- return select_linked_exec(C, op);
+ return select_linked_exec(C, op);
}
void CURVE_OT_select_linked(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Linked All";
- ot->idname = "CURVE_OT_select_linked";
- ot->description = "Select all control points linked to the current selection";
+ /* identifiers */
+ ot->name = "Select Linked All";
+ ot->idname = "CURVE_OT_select_linked";
+ ot->description = "Select all control points linked to the current selection";
- /* api callbacks */
- ot->exec = select_linked_exec;
- ot->invoke = select_linked_invoke;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = select_linked_exec;
+ ot->invoke = select_linked_invoke;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
+ /* properties */
}
-
/***************** select linked pick operator ******************/
static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewContext vc;
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
- const bool select = !RNA_boolean_get(op->ptr, "deselect");
- Base *basact = NULL;
-
- view3d_operator_needs_opengl(C);
- ED_view3d_viewcontext_init(C, &vc);
- copy_v2_v2_int(vc.mval, event->mval);
-
- if (!ED_curve_pick_vert(&vc, 1, &nu, &bezt, &bp, NULL, &basact)) {
- return OPERATOR_CANCELLED;
- }
-
- if (bezt) {
- a = nu->pntsu;
- bezt = nu->bezt;
- while (a--) {
- select_beztriple(bezt, select, SELECT, VISIBLE);
- bezt++;
- }
- }
- else if (bp) {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a--) {
- select_bpoint(bp, select, SELECT, VISIBLE);
- bp++;
- }
- }
-
- Object *obedit = basact->object;
-
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- if (!select) {
- BKE_curve_nurb_vert_active_validate(obedit->data);
- }
-
- return OPERATOR_FINISHED;
+ ViewContext vc;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+ const bool select = !RNA_boolean_get(op->ptr, "deselect");
+ Base *basact = NULL;
+
+ view3d_operator_needs_opengl(C);
+ ED_view3d_viewcontext_init(C, &vc);
+ copy_v2_v2_int(vc.mval, event->mval);
+
+ if (!ED_curve_pick_vert(&vc, 1, &nu, &bezt, &bp, NULL, &basact)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (bezt) {
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ while (a--) {
+ select_beztriple(bezt, select, SELECT, VISIBLE);
+ bezt++;
+ }
+ }
+ else if (bp) {
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a--) {
+ select_bpoint(bp, select, SELECT, VISIBLE);
+ bp++;
+ }
+ }
+
+ Object *obedit = basact->object;
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ if (!select) {
+ BKE_curve_nurb_vert_active_validate(obedit->data);
+ }
+
+ return OPERATOR_FINISHED;
}
void CURVE_OT_select_linked_pick(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Linked";
- ot->idname = "CURVE_OT_select_linked_pick";
- ot->description = "Select all control points linked to already selected ones";
-
- /* api callbacks */
- ot->invoke = select_linked_pick_invoke;
- ot->poll = ED_operator_editsurfcurve_region_view3d;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect linked control points rather than selecting them");
+ /* identifiers */
+ ot->name = "Select Linked";
+ ot->idname = "CURVE_OT_select_linked_pick";
+ ot->description = "Select all control points linked to already selected ones";
+
+ /* api callbacks */
+ ot->invoke = select_linked_pick_invoke;
+ ot->poll = ED_operator_editsurfcurve_region_view3d;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "deselect",
+ 0,
+ "Deselect",
+ "Deselect linked control points rather than selecting them");
}
/***************** select row operator **********************/
static int select_row_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = obedit->data;
- ListBase *editnurb = object_editcurve_get(obedit);
- static BPoint *last = NULL;
- static int direction = 0;
- Nurb *nu = NULL;
- BPoint *bp = NULL;
- int u = 0, v = 0, a, b;
-
- if (!BKE_curve_nurb_vert_active_get(cu, &nu, (void *)&bp)) {
- return OPERATOR_CANCELLED;
- }
-
- if (last == bp) {
- direction = 1 - direction;
- BKE_nurbList_flag_set(editnurb, 0);
- }
- last = bp;
-
- u = cu->actvert % nu->pntsu;
- v = cu->actvert / nu->pntsu;
- bp = nu->bp;
- for (a = 0; a < nu->pntsv; a++) {
- for (b = 0; b < nu->pntsu; b++, bp++) {
- if (direction) {
- if (a == v) {
- select_bpoint(bp, SELECT, SELECT, VISIBLE);
- }
- }
- else {
- if (b == u) {
- select_bpoint(bp, SELECT, SELECT, VISIBLE);
- }
- }
- }
- }
-
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ ListBase *editnurb = object_editcurve_get(obedit);
+ static BPoint *last = NULL;
+ static int direction = 0;
+ Nurb *nu = NULL;
+ BPoint *bp = NULL;
+ int u = 0, v = 0, a, b;
+
+ if (!BKE_curve_nurb_vert_active_get(cu, &nu, (void *)&bp)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (last == bp) {
+ direction = 1 - direction;
+ BKE_nurbList_flag_set(editnurb, 0);
+ }
+ last = bp;
+
+ u = cu->actvert % nu->pntsu;
+ v = cu->actvert / nu->pntsu;
+ bp = nu->bp;
+ for (a = 0; a < nu->pntsv; a++) {
+ for (b = 0; b < nu->pntsu; b++, bp++) {
+ if (direction) {
+ if (a == v) {
+ select_bpoint(bp, SELECT, SELECT, VISIBLE);
+ }
+ }
+ else {
+ if (b == u) {
+ select_bpoint(bp, SELECT, SELECT, VISIBLE);
+ }
+ }
+ }
+ }
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
}
void CURVE_OT_select_row(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Control Point Row";
- ot->idname = "CURVE_OT_select_row";
- ot->description = "Select a row of control points including active one";
+ /* identifiers */
+ ot->name = "Select Control Point Row";
+ ot->idname = "CURVE_OT_select_row";
+ ot->description = "Select a row of control points including active one";
- /* api callbacks */
- ot->exec = select_row_exec;
- ot->poll = ED_operator_editsurf;
+ /* api callbacks */
+ ot->exec = select_row_exec;
+ ot->poll = ED_operator_editsurf;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/***************** select next operator **********************/
static int select_next_exec(bContext *C, wmOperator *UNUSED(op))
{
- 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];
- ListBase *editnurb = object_editcurve_get(obedit);
- select_adjacent_cp(editnurb, 1, 0, SELECT);
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ 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];
+ ListBase *editnurb = object_editcurve_get(obedit);
+ select_adjacent_cp(editnurb, 1, 0, SELECT);
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void CURVE_OT_select_next(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Next";
- ot->idname = "CURVE_OT_select_next";
- ot->description = "Select control points following already selected ones along the curves";
+ /* identifiers */
+ ot->name = "Select Next";
+ ot->idname = "CURVE_OT_select_next";
+ ot->description = "Select control points following already selected ones along the curves";
- /* api callbacks */
- ot->exec = select_next_exec;
- ot->poll = ED_operator_editcurve;
+ /* api callbacks */
+ ot->exec = select_next_exec;
+ ot->poll = ED_operator_editcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/***************** select previous operator **********************/
static int select_previous_exec(bContext *C, wmOperator *UNUSED(op))
{
- 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];
- ListBase *editnurb = object_editcurve_get(obedit);
- select_adjacent_cp(editnurb, -1, 0, SELECT);
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ 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];
+ ListBase *editnurb = object_editcurve_get(obedit);
+ select_adjacent_cp(editnurb, -1, 0, SELECT);
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void CURVE_OT_select_previous(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Previous";
- ot->idname = "CURVE_OT_select_previous";
- ot->description = "Select control points preceding already selected ones along the curves";
+ /* identifiers */
+ ot->name = "Select Previous";
+ ot->idname = "CURVE_OT_select_previous";
+ ot->description = "Select control points preceding already selected ones along the curves";
- /* api callbacks */
- ot->exec = select_previous_exec;
- ot->poll = ED_operator_editcurve;
+ /* api callbacks */
+ ot->exec = select_previous_exec;
+ ot->poll = ED_operator_editcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/***************** select more operator **********************/
static void curve_select_more(Object *obedit)
{
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BPoint *bp, *tempbp;
- int a;
- short sel = 0;
-
- /* note that NURBS surface is a special case because we mimic */
- /* the behavior of "select more" of mesh tools. */
- /* The algorithm is designed to work in planar cases so it */
- /* may not be optimal always (example: end of NURBS sphere) */
- if (obedit->type == OB_SURF) {
- for (nu = editnurb->first; nu; nu = nu->next) {
- BLI_bitmap *selbpoints;
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- selbpoints = BLI_BITMAP_NEW(a, "selectlist");
- while (a > 0) {
- if ((!BLI_BITMAP_TEST(selbpoints, a)) && (bp->hide == 0) && (bp->f1 & SELECT)) {
- /* upper control point */
- if (a % nu->pntsu != 0) {
- tempbp = bp - 1;
- if (!(tempbp->f1 & SELECT)) {
- select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
- }
- }
-
- /* left control point. select only if it is not selected already */
- if (a - nu->pntsu > 0) {
- sel = 0;
- tempbp = bp + nu->pntsu;
- if (!(tempbp->f1 & SELECT)) {
- sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
- }
- /* make sure selected bpoint is discarded */
- if (sel == 1) {
- BLI_BITMAP_ENABLE(selbpoints, a - nu->pntsu);
- }
- }
-
- /* right control point */
- if (a + nu->pntsu < nu->pntsu * nu->pntsv) {
- tempbp = bp - nu->pntsu;
- if (!(tempbp->f1 & SELECT)) {
- select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
- }
- }
-
- /* lower control point. skip next bp in case selection was made */
- if (a % nu->pntsu != 1) {
- sel = 0;
- tempbp = bp + 1;
- if (!(tempbp->f1 & SELECT)) {
- sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
- }
- if (sel) {
- bp++;
- a--;
- }
- }
- }
-
- bp++;
- a--;
- }
-
- MEM_freeN(selbpoints);
- }
- }
- else {
- select_adjacent_cp(editnurb, 1, 0, SELECT);
- select_adjacent_cp(editnurb, -1, 0, SELECT);
- }
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BPoint *bp, *tempbp;
+ int a;
+ short sel = 0;
+
+ /* note that NURBS surface is a special case because we mimic */
+ /* the behavior of "select more" of mesh tools. */
+ /* The algorithm is designed to work in planar cases so it */
+ /* may not be optimal always (example: end of NURBS sphere) */
+ if (obedit->type == OB_SURF) {
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ BLI_bitmap *selbpoints;
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ selbpoints = BLI_BITMAP_NEW(a, "selectlist");
+ while (a > 0) {
+ if ((!BLI_BITMAP_TEST(selbpoints, a)) && (bp->hide == 0) && (bp->f1 & SELECT)) {
+ /* upper control point */
+ if (a % nu->pntsu != 0) {
+ tempbp = bp - 1;
+ if (!(tempbp->f1 & SELECT)) {
+ select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
+ }
+ }
+
+ /* left control point. select only if it is not selected already */
+ if (a - nu->pntsu > 0) {
+ sel = 0;
+ tempbp = bp + nu->pntsu;
+ if (!(tempbp->f1 & SELECT)) {
+ sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
+ }
+ /* make sure selected bpoint is discarded */
+ if (sel == 1) {
+ BLI_BITMAP_ENABLE(selbpoints, a - nu->pntsu);
+ }
+ }
+
+ /* right control point */
+ if (a + nu->pntsu < nu->pntsu * nu->pntsv) {
+ tempbp = bp - nu->pntsu;
+ if (!(tempbp->f1 & SELECT)) {
+ select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
+ }
+ }
+
+ /* lower control point. skip next bp in case selection was made */
+ if (a % nu->pntsu != 1) {
+ sel = 0;
+ tempbp = bp + 1;
+ if (!(tempbp->f1 & SELECT)) {
+ sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
+ }
+ if (sel) {
+ bp++;
+ a--;
+ }
+ }
+ }
+
+ bp++;
+ a--;
+ }
+
+ MEM_freeN(selbpoints);
+ }
+ }
+ else {
+ select_adjacent_cp(editnurb, 1, 0, SELECT);
+ select_adjacent_cp(editnurb, -1, 0, SELECT);
+ }
}
static int curve_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
- 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];
- curve_select_more(obedit);
- 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;
+ 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];
+ curve_select_more(obedit);
+ 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;
}
void CURVE_OT_select_more(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select More";
- ot->idname = "CURVE_OT_select_more";
- ot->description = "Select control points directly linked to already selected ones";
+ /* identifiers */
+ ot->name = "Select More";
+ ot->idname = "CURVE_OT_select_more";
+ ot->description = "Select control points directly linked to already selected ones";
- /* api callbacks */
- ot->exec = curve_select_more_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = curve_select_more_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************** select less operator *****************/
@@ -984,437 +997,439 @@ void CURVE_OT_select_more(wmOperatorType *ot)
/* basic method: deselect if control point doesn't have all neighbors selected */
static void curve_select_less(Object *obedit)
{
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- int a;
- int sel = 0;
- bool lastsel = false;
-
- if (obedit->type == OB_SURF) {
- for (nu = editnurb->first; nu; nu = nu->next) {
- BLI_bitmap *selbpoints;
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- selbpoints = BLI_BITMAP_NEW(a, "selectlist");
- while (a--) {
- if ((bp->hide == 0) && (bp->f1 & SELECT)) {
- sel = 0;
-
- /* check if neighbors have been selected */
- /* edges of surface are an exception */
- if ((a + 1) % nu->pntsu == 0) {
- sel++;
- }
- else {
- bp--;
- if (BLI_BITMAP_TEST(selbpoints, a + 1) || ((bp->hide == 0) && (bp->f1 & SELECT))) {
- sel++;
- }
- bp++;
- }
-
- if ((a + 1) % nu->pntsu == 1) {
- sel++;
- }
- else {
- bp++;
- if ((bp->hide == 0) && (bp->f1 & SELECT)) {
- sel++;
- }
- bp--;
- }
-
- if (a + 1 > nu->pntsu * nu->pntsv - nu->pntsu) {
- sel++;
- }
- else {
- bp -= nu->pntsu;
- if (BLI_BITMAP_TEST(selbpoints, a + nu->pntsu) || ((bp->hide == 0) && (bp->f1 & SELECT))) {
- sel++;
- }
- bp += nu->pntsu;
- }
-
- if (a < nu->pntsu) {
- sel++;
- }
- else {
- bp += nu->pntsu;
- if ((bp->hide == 0) && (bp->f1 & SELECT)) {
- sel++;
- }
- bp -= nu->pntsu;
- }
-
- if (sel != 4) {
- select_bpoint(bp, DESELECT, SELECT, VISIBLE);
- BLI_BITMAP_ENABLE(selbpoints, a);
- }
- }
- else {
- lastsel = false;
- }
-
- bp++;
- }
-
- MEM_freeN(selbpoints);
- }
- }
- else {
- for (nu = editnurb->first; nu; nu = nu->next) {
- lastsel = false;
- /* check what type of curve/nurb it is */
- if (nu->type == CU_BEZIER) {
- a = nu->pntsu;
- bezt = nu->bezt;
- while (a--) {
- if ((bezt->hide == 0) && (bezt->f2 & SELECT)) {
- sel = (lastsel == 1);
-
- /* check if neighbors have been selected */
- /* first and last are exceptions */
- if (a == nu->pntsu - 1) {
- sel++;
- }
- else {
- bezt--;
- if ((bezt->hide == 0) && (bezt->f2 & SELECT)) {
- sel++;
- }
- bezt++;
- }
-
- if (a == 0) {
- sel++;
- }
- else {
- bezt++;
- if ((bezt->hide == 0) && (bezt->f2 & SELECT)) {
- sel++;
- }
- bezt--;
- }
-
- if (sel != 2) {
- select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
- lastsel = true;
- }
- else {
- lastsel = false;
- }
- }
- else {
- lastsel = false;
- }
-
- bezt++;
- }
- }
- else {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a--) {
- if ((lastsel == false) && (bp->hide == 0) && (bp->f1 & SELECT)) {
- sel = 0;
-
- /* first and last are exceptions */
- if (a == nu->pntsu * nu->pntsv - 1) {
- sel++;
- }
- else {
- bp--;
- if ((bp->hide == 0) && (bp->f1 & SELECT)) {
- sel++;
- }
- bp++;
- }
-
- if (a == 0) {
- sel++;
- }
- else {
- bp++;
- if ((bp->hide == 0) && (bp->f1 & SELECT)) {
- sel++;
- }
- bp--;
- }
-
- if (sel != 2) {
- select_bpoint(bp, DESELECT, SELECT, VISIBLE);
- lastsel = true;
- }
- else {
- lastsel = false;
- }
- }
- else {
- lastsel = false;
- }
-
- bp++;
- }
- }
- }
- }
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a;
+ int sel = 0;
+ bool lastsel = false;
+
+ if (obedit->type == OB_SURF) {
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ BLI_bitmap *selbpoints;
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ selbpoints = BLI_BITMAP_NEW(a, "selectlist");
+ while (a--) {
+ if ((bp->hide == 0) && (bp->f1 & SELECT)) {
+ sel = 0;
+
+ /* check if neighbors have been selected */
+ /* edges of surface are an exception */
+ if ((a + 1) % nu->pntsu == 0) {
+ sel++;
+ }
+ else {
+ bp--;
+ if (BLI_BITMAP_TEST(selbpoints, a + 1) || ((bp->hide == 0) && (bp->f1 & SELECT))) {
+ sel++;
+ }
+ bp++;
+ }
+
+ if ((a + 1) % nu->pntsu == 1) {
+ sel++;
+ }
+ else {
+ bp++;
+ if ((bp->hide == 0) && (bp->f1 & SELECT)) {
+ sel++;
+ }
+ bp--;
+ }
+
+ if (a + 1 > nu->pntsu * nu->pntsv - nu->pntsu) {
+ sel++;
+ }
+ else {
+ bp -= nu->pntsu;
+ if (BLI_BITMAP_TEST(selbpoints, a + nu->pntsu) ||
+ ((bp->hide == 0) && (bp->f1 & SELECT))) {
+ sel++;
+ }
+ bp += nu->pntsu;
+ }
+
+ if (a < nu->pntsu) {
+ sel++;
+ }
+ else {
+ bp += nu->pntsu;
+ if ((bp->hide == 0) && (bp->f1 & SELECT)) {
+ sel++;
+ }
+ bp -= nu->pntsu;
+ }
+
+ if (sel != 4) {
+ select_bpoint(bp, DESELECT, SELECT, VISIBLE);
+ BLI_BITMAP_ENABLE(selbpoints, a);
+ }
+ }
+ else {
+ lastsel = false;
+ }
+
+ bp++;
+ }
+
+ MEM_freeN(selbpoints);
+ }
+ }
+ else {
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ lastsel = false;
+ /* check what type of curve/nurb it is */
+ if (nu->type == CU_BEZIER) {
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ while (a--) {
+ if ((bezt->hide == 0) && (bezt->f2 & SELECT)) {
+ sel = (lastsel == 1);
+
+ /* check if neighbors have been selected */
+ /* first and last are exceptions */
+ if (a == nu->pntsu - 1) {
+ sel++;
+ }
+ else {
+ bezt--;
+ if ((bezt->hide == 0) && (bezt->f2 & SELECT)) {
+ sel++;
+ }
+ bezt++;
+ }
+
+ if (a == 0) {
+ sel++;
+ }
+ else {
+ bezt++;
+ if ((bezt->hide == 0) && (bezt->f2 & SELECT)) {
+ sel++;
+ }
+ bezt--;
+ }
+
+ if (sel != 2) {
+ select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
+ lastsel = true;
+ }
+ else {
+ lastsel = false;
+ }
+ }
+ else {
+ lastsel = false;
+ }
+
+ bezt++;
+ }
+ }
+ else {
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a--) {
+ if ((lastsel == false) && (bp->hide == 0) && (bp->f1 & SELECT)) {
+ sel = 0;
+
+ /* first and last are exceptions */
+ if (a == nu->pntsu * nu->pntsv - 1) {
+ sel++;
+ }
+ else {
+ bp--;
+ if ((bp->hide == 0) && (bp->f1 & SELECT)) {
+ sel++;
+ }
+ bp++;
+ }
+
+ if (a == 0) {
+ sel++;
+ }
+ else {
+ bp++;
+ if ((bp->hide == 0) && (bp->f1 & SELECT)) {
+ sel++;
+ }
+ bp--;
+ }
+
+ if (sel != 2) {
+ select_bpoint(bp, DESELECT, SELECT, VISIBLE);
+ lastsel = true;
+ }
+ else {
+ lastsel = false;
+ }
+ }
+ else {
+ lastsel = false;
+ }
+
+ bp++;
+ }
+ }
+ }
+ }
}
static int curve_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
- 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];
- curve_select_less(obedit);
- 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;
+ 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];
+ curve_select_less(obedit);
+ 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;
}
void CURVE_OT_select_less(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Less";
- ot->idname = "CURVE_OT_select_less";
- ot->description = "Reduce current selection by deselecting boundary elements";
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->idname = "CURVE_OT_select_less";
+ ot->description = "Reduce current selection by deselecting boundary elements";
- /* api callbacks */
- ot->exec = curve_select_less_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = curve_select_less_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** select random *********************/
static void curve_select_random(ListBase *editnurb, float randfac, int seed, bool select)
{
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
-
- RNG *rng = BLI_rng_new_srandom(seed);
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (!bezt->hide) {
- if (BLI_rng_get_float(rng) < randfac) {
- select_beztriple(bezt, select, SELECT, VISIBLE);
- }
- }
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
-
- while (a--) {
- if (!bp->hide) {
- if (BLI_rng_get_float(rng) < randfac) {
- select_bpoint(bp, select, SELECT, VISIBLE);
- }
- }
- bp++;
- }
- }
- }
-
- BLI_rng_free(rng);
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ RNG *rng = BLI_rng_new_srandom(seed);
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ if (!bezt->hide) {
+ if (BLI_rng_get_float(rng) < randfac) {
+ select_beztriple(bezt, select, SELECT, VISIBLE);
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+
+ while (a--) {
+ if (!bp->hide) {
+ if (BLI_rng_get_float(rng) < randfac) {
+ select_bpoint(bp, select, SELECT, VISIBLE);
+ }
+ }
+ bp++;
+ }
+ }
+ }
+
+ BLI_rng_free(rng);
}
static int curve_select_random_exec(bContext *C, wmOperator *op)
{
- const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
- const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
- const int seed = WM_operator_properties_select_random_seed_increment_get(op);
-
- 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];
- ListBase *editnurb = object_editcurve_get(obedit);
- int seed_iter = seed;
-
- /* This gives a consistent result regardless of object order. */
- if (ob_index) {
- seed_iter += BLI_ghashutil_strhash_p(obedit->id.name);
- }
-
- curve_select_random(editnurb, randfac, seed_iter, select);
- BKE_curve_nurb_vert_active_validate(obedit->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;
+ const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
+ const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
+ const int seed = WM_operator_properties_select_random_seed_increment_get(op);
+
+ 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];
+ ListBase *editnurb = object_editcurve_get(obedit);
+ int seed_iter = seed;
+
+ /* This gives a consistent result regardless of object order. */
+ if (ob_index) {
+ seed_iter += BLI_ghashutil_strhash_p(obedit->id.name);
+ }
+
+ curve_select_random(editnurb, randfac, seed_iter, select);
+ BKE_curve_nurb_vert_active_validate(obedit->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;
}
void CURVE_OT_select_random(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Random";
- ot->idname = "CURVE_OT_select_random";
- ot->description = "Randomly select some control points";
+ /* identifiers */
+ ot->name = "Select Random";
+ ot->idname = "CURVE_OT_select_random";
+ ot->description = "Randomly select some control points";
- /* api callbacks */
- ot->exec = curve_select_random_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = curve_select_random_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_select_random(ot);
+ /* properties */
+ WM_operator_properties_select_random(ot);
}
/********************* every nth number of point *******************/
static void select_nth_bezt(Nurb *nu, BezTriple *bezt, const struct CheckerIntervalParams *params)
{
- int a, start;
+ int a, start;
- start = bezt - nu->bezt;
- a = nu->pntsu;
- bezt = &nu->bezt[a - 1];
+ start = bezt - nu->bezt;
+ a = nu->pntsu;
+ bezt = &nu->bezt[a - 1];
- while (a--) {
- const int depth = abs(start - a);
- if (WM_operator_properties_checker_interval_test(params, depth)) {
- select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
- }
+ while (a--) {
+ const int depth = abs(start - a);
+ if (WM_operator_properties_checker_interval_test(params, depth)) {
+ select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
+ }
- bezt--;
- }
+ bezt--;
+ }
}
static void select_nth_bp(Nurb *nu, BPoint *bp, const struct CheckerIntervalParams *params)
{
- int a, startrow, startpnt;
- int row, pnt;
-
- startrow = (bp - nu->bp) / nu->pntsu;
- startpnt = (bp - nu->bp) % nu->pntsu;
-
- a = nu->pntsu * nu->pntsv;
- bp = &nu->bp[a - 1];
- row = nu->pntsv - 1;
- pnt = nu->pntsu - 1;
-
- while (a--) {
- const int depth = abs(pnt - startpnt) + abs(row - startrow);
- if (WM_operator_properties_checker_interval_test(params, depth)) {
- select_bpoint(bp, DESELECT, SELECT, HIDDEN);
- }
-
- pnt--;
- if (pnt < 0) {
- pnt = nu->pntsu - 1;
- row--;
- }
-
- bp--;
- }
+ int a, startrow, startpnt;
+ int row, pnt;
+
+ startrow = (bp - nu->bp) / nu->pntsu;
+ startpnt = (bp - nu->bp) % nu->pntsu;
+
+ a = nu->pntsu * nu->pntsv;
+ bp = &nu->bp[a - 1];
+ row = nu->pntsv - 1;
+ pnt = nu->pntsu - 1;
+
+ while (a--) {
+ const int depth = abs(pnt - startpnt) + abs(row - startrow);
+ if (WM_operator_properties_checker_interval_test(params, depth)) {
+ select_bpoint(bp, DESELECT, SELECT, HIDDEN);
+ }
+
+ pnt--;
+ if (pnt < 0) {
+ pnt = nu->pntsu - 1;
+ row--;
+ }
+
+ bp--;
+ }
}
static bool ed_curve_select_nth(Curve *cu, const struct CheckerIntervalParams *params)
{
- Nurb *nu = NULL;
- void *vert = NULL;
+ Nurb *nu = NULL;
+ void *vert = NULL;
- if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) {
- return false;
- }
+ if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) {
+ return false;
+ }
- if (nu->bezt) {
- select_nth_bezt(nu, vert, params);
- }
- else {
- select_nth_bp(nu, vert, params);
- }
+ if (nu->bezt) {
+ select_nth_bezt(nu, vert, params);
+ }
+ else {
+ select_nth_bp(nu, vert, params);
+ }
- return true;
+ return true;
}
static int select_nth_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *obact = CTX_data_edit_object(C);
- View3D *v3d = CTX_wm_view3d(C);
- bool changed = false;
-
- struct CheckerIntervalParams op_params;
- WM_operator_properties_checker_interval_from_op(op, &op_params);
-
- 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];
- Curve *cu = obedit->data;
-
- if (!ED_curve_select_check(v3d, cu->editnurb)) {
- continue;
- }
-
- if (ed_curve_select_nth(obedit->data, &op_params) == true) {
- changed = true;
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- }
- MEM_freeN(objects);
-
- if (!changed) {
- if (obact->type == OB_SURF) {
- BKE_report(op->reports, RPT_ERROR,
- (objects_len == 1 ?
- "Surface has no active point" :
- "Surfaces have no active point"));
- }
- else {
- BKE_report(op->reports, RPT_ERROR,
- (objects_len == 1 ?
- "Curve has no active point" :
- "Curves have no active point"));
- }
- return OPERATOR_CANCELLED;
- }
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obact = CTX_data_edit_object(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ bool changed = false;
+
+ struct CheckerIntervalParams op_params;
+ WM_operator_properties_checker_interval_from_op(op, &op_params);
+
+ 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];
+ Curve *cu = obedit->data;
+
+ if (!ED_curve_select_check(v3d, cu->editnurb)) {
+ continue;
+ }
+
+ if (ed_curve_select_nth(obedit->data, &op_params) == true) {
+ changed = true;
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ }
+ MEM_freeN(objects);
+
+ if (!changed) {
+ if (obact->type == OB_SURF) {
+ BKE_report(
+ op->reports,
+ RPT_ERROR,
+ (objects_len == 1 ? "Surface has no active point" : "Surfaces have no active point"));
+ }
+ else {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ (objects_len == 1 ? "Curve has no active point" : "Curves have no active point"));
+ }
+ return OPERATOR_CANCELLED;
+ }
+ return OPERATOR_FINISHED;
}
void CURVE_OT_select_nth(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Checker Deselect";
- ot->description = "Deselect every other vertex";
- ot->idname = "CURVE_OT_select_nth";
+ /* identifiers */
+ ot->name = "Checker Deselect";
+ ot->description = "Deselect every other vertex";
+ ot->idname = "CURVE_OT_select_nth";
- /* api callbacks */
- ot->exec = select_nth_exec;
- ot->poll = ED_operator_editsurfcurve;
+ /* api callbacks */
+ ot->exec = select_nth_exec;
+ ot->poll = ED_operator_editsurfcurve;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_checker_interval(ot, false);
+ WM_operator_properties_checker_interval(ot, false);
}
-
/* -------------------------------------------------------------------- */
/* Select Similar */
@@ -1422,373 +1437,365 @@ void CURVE_OT_select_nth(wmOperatorType *ot)
* \{ */
static const EnumPropertyItem curve_prop_similar_compare_types[] = {
- {SIM_CMP_EQ, "EQUAL", 0, "Equal", ""},
- {SIM_CMP_GT, "GREATER", 0, "Greater", ""},
- {SIM_CMP_LT, "LESS", 0, "Less", ""},
+ {SIM_CMP_EQ, "EQUAL", 0, "Equal", ""},
+ {SIM_CMP_GT, "GREATER", 0, "Greater", ""},
+ {SIM_CMP_LT, "LESS", 0, "Less", ""},
- {0, NULL, 0, NULL, NULL},
+ {0, NULL, 0, NULL, NULL},
};
enum {
- SIMCURHAND_TYPE = 0,
- SIMCURHAND_RADIUS,
- SIMCURHAND_WEIGHT,
- SIMCURHAND_DIRECTION,
+ SIMCURHAND_TYPE = 0,
+ SIMCURHAND_RADIUS,
+ SIMCURHAND_WEIGHT,
+ SIMCURHAND_DIRECTION,
};
static const EnumPropertyItem curve_prop_similar_types[] = {
- {SIMCURHAND_TYPE, "TYPE", 0, "Type", ""},
- {SIMCURHAND_RADIUS, "RADIUS", 0, "Radius", ""},
- {SIMCURHAND_WEIGHT, "WEIGHT", 0, "Weight", ""},
- {SIMCURHAND_DIRECTION, "DIRECTION", 0, "Direction", ""},
- {0, NULL, 0, NULL, NULL},
+ {SIMCURHAND_TYPE, "TYPE", 0, "Type", ""},
+ {SIMCURHAND_RADIUS, "RADIUS", 0, "Radius", ""},
+ {SIMCURHAND_WEIGHT, "WEIGHT", 0, "Weight", ""},
+ {SIMCURHAND_DIRECTION, "DIRECTION", 0, "Direction", ""},
+ {0, NULL, 0, NULL, NULL},
};
-static void nurb_bezt_direction_worldspace_get(Object *ob, Nurb *nu, BezTriple *bezt, float r_dir[3])
+static void nurb_bezt_direction_worldspace_get(Object *ob,
+ Nurb *nu,
+ BezTriple *bezt,
+ float r_dir[3])
{
- float rsmat[3][3];
- BKE_nurb_bezt_calc_normal(nu, bezt, r_dir);
- copy_m3_m4(rsmat, ob->obmat);
- mul_m3_v3(rsmat, r_dir);
- normalize_v3(r_dir);
+ float rsmat[3][3];
+ BKE_nurb_bezt_calc_normal(nu, bezt, r_dir);
+ copy_m3_m4(rsmat, ob->obmat);
+ mul_m3_v3(rsmat, r_dir);
+ normalize_v3(r_dir);
}
static void nurb_bpoint_direction_worldspace_get(Object *ob, Nurb *nu, BPoint *bp, float r_dir[3])
{
- float rsmat[3][3];
- BKE_nurb_bpoint_calc_normal(nu, bp, r_dir);
- copy_m3_m4(rsmat, ob->obmat);
- mul_m3_v3(rsmat, r_dir);
- normalize_v3(r_dir);
+ float rsmat[3][3];
+ BKE_nurb_bpoint_calc_normal(nu, bp, r_dir);
+ copy_m3_m4(rsmat, ob->obmat);
+ mul_m3_v3(rsmat, r_dir);
+ normalize_v3(r_dir);
}
static void curve_nurb_selected_type_get(
- Object *ob, Nurb *nu, const int type, KDTree_1d *tree_1d, KDTree_3d *tree_3d)
+ Object *ob, Nurb *nu, const int type, KDTree_1d *tree_1d, KDTree_3d *tree_3d)
{
- float tree_entry[3] = {0.0f, 0.0f, 0.0f};
-
- if (nu->type == CU_BEZIER) {
- BezTriple *bezt;
- int i;
- int tree_index = 0;
-
- for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
- if ((!bezt->hide) && (bezt->f1 & SELECT)) {
-
- switch (type) {
- case SIMCURHAND_RADIUS:
- {
- float radius_ref = bezt->radius;
- tree_entry[0] = radius_ref;
- break;
- }
- case SIMCURHAND_WEIGHT:
- {
- float weight_ref = bezt->weight;
- tree_entry[0] = weight_ref;
- break;
- }
- case SIMCURHAND_DIRECTION:
- {
- nurb_bezt_direction_worldspace_get(ob, nu, bezt, tree_entry);
- break;
- }
- }
- if (tree_1d) {
- BLI_kdtree_1d_insert(tree_1d, tree_index++, tree_entry);
- }
- else {
- BLI_kdtree_3d_insert(tree_3d, tree_index++, tree_entry);
- }
- }
- }
- }
- else {
- BPoint *bp;
- int i;
- int tree_index = 0;
-
- for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
- if (!bp->hide && bp->f1 & SELECT) {
- switch (type) {
- case SIMCURHAND_RADIUS:
- {
- float radius_ref = bp->radius;
- tree_entry[0] = radius_ref;
- break;
- }
- case SIMCURHAND_WEIGHT:
- {
- float weight_ref = bp->weight;
- tree_entry[0] = weight_ref;
- break;
- }
- case SIMCURHAND_DIRECTION:
- {
- nurb_bpoint_direction_worldspace_get(ob, nu, bp, tree_entry);
- break;
- }
- }
- if (tree_1d) {
- BLI_kdtree_1d_insert(tree_1d, tree_index++, tree_entry);
- }
- else {
- BLI_kdtree_3d_insert(tree_3d, tree_index++, tree_entry);
- }
- }
- }
- }
+ float tree_entry[3] = {0.0f, 0.0f, 0.0f};
+
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt;
+ int i;
+ int tree_index = 0;
+
+ for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
+ if ((!bezt->hide) && (bezt->f1 & SELECT)) {
+
+ switch (type) {
+ case SIMCURHAND_RADIUS: {
+ float radius_ref = bezt->radius;
+ tree_entry[0] = radius_ref;
+ break;
+ }
+ case SIMCURHAND_WEIGHT: {
+ float weight_ref = bezt->weight;
+ tree_entry[0] = weight_ref;
+ break;
+ }
+ case SIMCURHAND_DIRECTION: {
+ nurb_bezt_direction_worldspace_get(ob, nu, bezt, tree_entry);
+ break;
+ }
+ }
+ if (tree_1d) {
+ BLI_kdtree_1d_insert(tree_1d, tree_index++, tree_entry);
+ }
+ else {
+ BLI_kdtree_3d_insert(tree_3d, tree_index++, tree_entry);
+ }
+ }
+ }
+ }
+ else {
+ BPoint *bp;
+ int i;
+ int tree_index = 0;
+
+ for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
+ if (!bp->hide && bp->f1 & SELECT) {
+ switch (type) {
+ case SIMCURHAND_RADIUS: {
+ float radius_ref = bp->radius;
+ tree_entry[0] = radius_ref;
+ break;
+ }
+ case SIMCURHAND_WEIGHT: {
+ float weight_ref = bp->weight;
+ tree_entry[0] = weight_ref;
+ break;
+ }
+ case SIMCURHAND_DIRECTION: {
+ nurb_bpoint_direction_worldspace_get(ob, nu, bp, tree_entry);
+ break;
+ }
+ }
+ if (tree_1d) {
+ BLI_kdtree_1d_insert(tree_1d, tree_index++, tree_entry);
+ }
+ else {
+ BLI_kdtree_3d_insert(tree_3d, tree_index++, tree_entry);
+ }
+ }
+ }
+ }
}
-static bool curve_nurb_select_similar_type(
- Object *ob, Nurb *nu, const int type,
- const KDTree_1d *tree_1d, const KDTree_3d *tree_3d,
- const float thresh, const int compare)
+static bool curve_nurb_select_similar_type(Object *ob,
+ Nurb *nu,
+ const int type,
+ const KDTree_1d *tree_1d,
+ const KDTree_3d *tree_3d,
+ const float thresh,
+ const int compare)
{
- const float thresh_cos = cosf(thresh * (float)M_PI_2);
- bool changed = false;
-
- if (nu->type == CU_BEZIER) {
- BezTriple *bezt;
- int i;
-
- for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
- if (!bezt->hide) {
- bool select = false;
-
- switch (type) {
- case SIMCURHAND_RADIUS:
- {
- float radius_ref = bezt->radius;
- if (ED_select_similar_compare_float_tree(tree_1d, radius_ref, thresh, compare)) {
- select = true;
- }
- break;
- }
- case SIMCURHAND_WEIGHT:
- {
- float weight_ref = bezt->weight;
- if (ED_select_similar_compare_float_tree(tree_1d, weight_ref, thresh, compare)) {
- select = true;
- }
- break;
- }
- case SIMCURHAND_DIRECTION:
- {
- float dir[3];
- nurb_bezt_direction_worldspace_get(ob, nu, bezt, dir);
- KDTreeNearest_3d nearest;
- if (BLI_kdtree_3d_find_nearest(tree_3d, dir, &nearest) != -1) {
- float orient = angle_normalized_v3v3(dir, nearest.co);
- float delta = thresh_cos - fabsf(cosf(orient));
- if (ED_select_similar_compare_float(delta, thresh, compare)) {
- select = true;
- }
- }
- break;
- }
- }
-
- if (select) {
- select_beztriple(bezt, SELECT, SELECT, VISIBLE);
- changed = true;
- }
- }
- }
- }
- else {
- BPoint *bp;
- int i;
-
- for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
- if (!bp->hide) {
- bool select = false;
-
- switch (type) {
- case SIMCURHAND_RADIUS:
- {
- float radius_ref = bp->radius;
- if (ED_select_similar_compare_float_tree(tree_1d, radius_ref, thresh, compare)) {
- select = true;
- }
- break;
- }
- case SIMCURHAND_WEIGHT:
- {
- float weight_ref = bp->weight;
- if (ED_select_similar_compare_float_tree(tree_1d, weight_ref, thresh, compare)) {
- select = true;
- }
- break;
- }
- case SIMCURHAND_DIRECTION:
- {
- float dir[3];
- nurb_bpoint_direction_worldspace_get(ob, nu, bp, dir);
- KDTreeNearest_3d nearest;
- if (BLI_kdtree_3d_find_nearest(tree_3d, dir, &nearest) != -1) {
- float orient = angle_normalized_v3v3(dir, nearest.co);
- float delta = fabsf(cosf(orient)) - thresh_cos;
- if (ED_select_similar_compare_float(delta, thresh, compare)) {
- select = true;
- }
- }
- break;
- }
- }
-
- if (select) {
- select_bpoint(bp, SELECT, SELECT, VISIBLE);
- changed = true;
- }
- }
- }
- }
- return changed;
+ const float thresh_cos = cosf(thresh * (float)M_PI_2);
+ bool changed = false;
+
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt;
+ int i;
+
+ for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
+ if (!bezt->hide) {
+ bool select = false;
+
+ switch (type) {
+ case SIMCURHAND_RADIUS: {
+ float radius_ref = bezt->radius;
+ if (ED_select_similar_compare_float_tree(tree_1d, radius_ref, thresh, compare)) {
+ select = true;
+ }
+ break;
+ }
+ case SIMCURHAND_WEIGHT: {
+ float weight_ref = bezt->weight;
+ if (ED_select_similar_compare_float_tree(tree_1d, weight_ref, thresh, compare)) {
+ select = true;
+ }
+ break;
+ }
+ case SIMCURHAND_DIRECTION: {
+ float dir[3];
+ nurb_bezt_direction_worldspace_get(ob, nu, bezt, dir);
+ KDTreeNearest_3d nearest;
+ if (BLI_kdtree_3d_find_nearest(tree_3d, dir, &nearest) != -1) {
+ float orient = angle_normalized_v3v3(dir, nearest.co);
+ float delta = thresh_cos - fabsf(cosf(orient));
+ if (ED_select_similar_compare_float(delta, thresh, compare)) {
+ select = true;
+ }
+ }
+ break;
+ }
+ }
+
+ if (select) {
+ select_beztriple(bezt, SELECT, SELECT, VISIBLE);
+ changed = true;
+ }
+ }
+ }
+ }
+ else {
+ BPoint *bp;
+ int i;
+
+ for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
+ if (!bp->hide) {
+ bool select = false;
+
+ switch (type) {
+ case SIMCURHAND_RADIUS: {
+ float radius_ref = bp->radius;
+ if (ED_select_similar_compare_float_tree(tree_1d, radius_ref, thresh, compare)) {
+ select = true;
+ }
+ break;
+ }
+ case SIMCURHAND_WEIGHT: {
+ float weight_ref = bp->weight;
+ if (ED_select_similar_compare_float_tree(tree_1d, weight_ref, thresh, compare)) {
+ select = true;
+ }
+ break;
+ }
+ case SIMCURHAND_DIRECTION: {
+ float dir[3];
+ nurb_bpoint_direction_worldspace_get(ob, nu, bp, dir);
+ KDTreeNearest_3d nearest;
+ if (BLI_kdtree_3d_find_nearest(tree_3d, dir, &nearest) != -1) {
+ float orient = angle_normalized_v3v3(dir, nearest.co);
+ float delta = fabsf(cosf(orient)) - thresh_cos;
+ if (ED_select_similar_compare_float(delta, thresh, compare)) {
+ select = true;
+ }
+ }
+ break;
+ }
+ }
+
+ if (select) {
+ select_bpoint(bp, SELECT, SELECT, VISIBLE);
+ changed = true;
+ }
+ }
+ }
+ }
+ return changed;
}
static int curve_select_similar_exec(bContext *C, wmOperator *op)
{
- /* Get props. */
- const int optype = RNA_enum_get(op->ptr, "type");
- const float thresh = RNA_float_get(op->ptr, "threshold");
- const int compare = RNA_enum_get(op->ptr, "compare");
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- int tot_nurbs_selected_all = 0;
- 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];
- Curve *cu = obedit->data;
- tot_nurbs_selected_all += ED_curve_select_count(v3d, cu->editnurb);
- }
-
- if (tot_nurbs_selected_all == 0) {
- BKE_report(op->reports, RPT_ERROR, "No control point selected");
- MEM_freeN(objects);
- return OPERATOR_CANCELLED;
- }
-
- KDTree_1d *tree_1d = NULL;
- KDTree_3d *tree_3d = NULL;
- short type_ref = 0;
-
- switch (optype) {
- case SIMCURHAND_RADIUS:
- case SIMCURHAND_WEIGHT:
- tree_1d = BLI_kdtree_1d_new(tot_nurbs_selected_all);
- break;
- case SIMCURHAND_DIRECTION:
- tree_3d = BLI_kdtree_3d_new(tot_nurbs_selected_all);
- break;
- }
-
- /* Get type of selected control points. */
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Curve *cu = obedit->data;
- EditNurb *editnurb = cu->editnurb;
-
- Nurb *nu;
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
- if (!ED_curve_nurb_select_check(v3d, nu)) {
- continue;
- }
- switch (optype) {
- case SIMCURHAND_TYPE:
- {
- type_ref |= nu->type;
- break;
- }
- case SIMCURHAND_RADIUS:
- case SIMCURHAND_WEIGHT:
- case SIMCURHAND_DIRECTION:
- curve_nurb_selected_type_get(obedit, nu, optype, tree_1d, tree_3d);
- break;
- }
- }
- }
-
- if (tree_1d != NULL) {
- BLI_kdtree_1d_deduplicate(tree_1d);
- BLI_kdtree_1d_balance(tree_1d);
- }
- if (tree_3d != NULL) {
- BLI_kdtree_3d_deduplicate(tree_3d);
- BLI_kdtree_3d_balance(tree_3d);
- }
-
- /* Select control points with desired type. */
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Curve *cu = obedit->data;
- EditNurb *editnurb = cu->editnurb;
- bool changed = false;
- Nurb *nu;
-
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
- switch (optype) {
- case SIMCURHAND_TYPE:
- {
- if (nu->type & type_ref) {
- changed |= ED_curve_nurb_select_all(nu);
- }
- break;
- }
- case SIMCURHAND_RADIUS:
- case SIMCURHAND_WEIGHT:
- case SIMCURHAND_DIRECTION:
- changed = curve_nurb_select_similar_type(
- obedit, nu, optype, tree_1d, tree_3d, thresh, compare);
- break;
- }
- }
-
- if (changed) {
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- }
-
- MEM_freeN(objects);
-
- if (tree_1d != NULL) {
- BLI_kdtree_1d_free(tree_1d);
- }
- if (tree_3d != NULL) {
- BLI_kdtree_3d_free(tree_3d);
- }
- return OPERATOR_FINISHED;
-
+ /* Get props. */
+ const int optype = RNA_enum_get(op->ptr, "type");
+ const float thresh = RNA_float_get(op->ptr, "threshold");
+ const int compare = RNA_enum_get(op->ptr, "compare");
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ int tot_nurbs_selected_all = 0;
+ 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];
+ Curve *cu = obedit->data;
+ tot_nurbs_selected_all += ED_curve_select_count(v3d, cu->editnurb);
+ }
+
+ if (tot_nurbs_selected_all == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No control point selected");
+ MEM_freeN(objects);
+ return OPERATOR_CANCELLED;
+ }
+
+ KDTree_1d *tree_1d = NULL;
+ KDTree_3d *tree_3d = NULL;
+ short type_ref = 0;
+
+ switch (optype) {
+ case SIMCURHAND_RADIUS:
+ case SIMCURHAND_WEIGHT:
+ tree_1d = BLI_kdtree_1d_new(tot_nurbs_selected_all);
+ break;
+ case SIMCURHAND_DIRECTION:
+ tree_3d = BLI_kdtree_3d_new(tot_nurbs_selected_all);
+ break;
+ }
+
+ /* Get type of selected control points. */
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Curve *cu = obedit->data;
+ EditNurb *editnurb = cu->editnurb;
+
+ Nurb *nu;
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ if (!ED_curve_nurb_select_check(v3d, nu)) {
+ continue;
+ }
+ switch (optype) {
+ case SIMCURHAND_TYPE: {
+ type_ref |= nu->type;
+ break;
+ }
+ case SIMCURHAND_RADIUS:
+ case SIMCURHAND_WEIGHT:
+ case SIMCURHAND_DIRECTION:
+ curve_nurb_selected_type_get(obedit, nu, optype, tree_1d, tree_3d);
+ break;
+ }
+ }
+ }
+
+ if (tree_1d != NULL) {
+ BLI_kdtree_1d_deduplicate(tree_1d);
+ BLI_kdtree_1d_balance(tree_1d);
+ }
+ if (tree_3d != NULL) {
+ BLI_kdtree_3d_deduplicate(tree_3d);
+ BLI_kdtree_3d_balance(tree_3d);
+ }
+
+ /* Select control points with desired type. */
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Curve *cu = obedit->data;
+ EditNurb *editnurb = cu->editnurb;
+ bool changed = false;
+ Nurb *nu;
+
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ switch (optype) {
+ case SIMCURHAND_TYPE: {
+ if (nu->type & type_ref) {
+ changed |= ED_curve_nurb_select_all(nu);
+ }
+ break;
+ }
+ case SIMCURHAND_RADIUS:
+ case SIMCURHAND_WEIGHT:
+ case SIMCURHAND_DIRECTION:
+ changed = curve_nurb_select_similar_type(
+ obedit, nu, optype, tree_1d, tree_3d, thresh, compare);
+ break;
+ }
+ }
+
+ if (changed) {
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ }
+
+ MEM_freeN(objects);
+
+ if (tree_1d != NULL) {
+ BLI_kdtree_1d_free(tree_1d);
+ }
+ if (tree_3d != NULL) {
+ BLI_kdtree_3d_free(tree_3d);
+ }
+ return OPERATOR_FINISHED;
}
void CURVE_OT_select_similar(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Similar";
- ot->idname = "CURVE_OT_select_similar";
- ot->description = "Select similar curve points by property type";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = curve_select_similar_exec;
- ot->poll = ED_operator_editsurfcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", curve_prop_similar_types, SIMCURHAND_WEIGHT, "Type", "");
- RNA_def_enum(ot->srna, "compare", curve_prop_similar_compare_types, SIM_CMP_EQ, "Compare", "");
- RNA_def_float(ot->srna, "threshold", 0.1, 0.0, FLT_MAX, "Threshold", "", 0.0, 100.0);
+ /* identifiers */
+ ot->name = "Select Similar";
+ ot->idname = "CURVE_OT_select_similar";
+ ot->description = "Select similar curve points by property type";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = curve_select_similar_exec;
+ ot->poll = ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", curve_prop_similar_types, SIMCURHAND_WEIGHT, "Type", "");
+ RNA_def_enum(ot->srna, "compare", curve_prop_similar_compare_types, SIM_CMP_EQ, "Compare", "");
+ RNA_def_float(ot->srna, "threshold", 0.1, 0.0, FLT_MAX, "Threshold", "", 0.0, 100.0);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Select Shortest Path */
@@ -1797,232 +1804,230 @@ void CURVE_OT_select_similar(wmOperatorType *ot)
static float curve_calc_dist_pair(const Nurb *nu, int a, int b)
{
- const float *a_fl, *b_fl;
-
- if (nu->type == CU_BEZIER) {
- a_fl = nu->bezt[a].vec[1];
- b_fl = nu->bezt[b].vec[1];
- }
- else {
- a_fl = nu->bp[a].vec;
- b_fl = nu->bp[b].vec;
- }
-
- return len_v3v3(a_fl, b_fl);
+ const float *a_fl, *b_fl;
+
+ if (nu->type == CU_BEZIER) {
+ a_fl = nu->bezt[a].vec[1];
+ b_fl = nu->bezt[b].vec[1];
+ }
+ else {
+ a_fl = nu->bp[a].vec;
+ b_fl = nu->bp[b].vec;
+ }
+
+ return len_v3v3(a_fl, b_fl);
}
static float curve_calc_dist_span(Nurb *nu, int vert_src, int vert_dst)
{
- const int u = nu->pntsu;
- int i_prev, i;
- float dist = 0.0f;
+ const int u = nu->pntsu;
+ 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;
+ i_prev = vert_src;
+ i = (i_prev + 1) % u;
- while (true) {
- dist += curve_calc_dist_pair(nu, i_prev, i);
+ while (true) {
+ dist += curve_calc_dist_pair(nu, i_prev, i);
- if (i == vert_dst) {
- break;
- }
- i = (i + 1) % u;
- }
- return dist;
+ if (i == vert_dst) {
+ break;
+ }
+ i = (i + 1) % u;
+ }
+ return dist;
}
static void curve_select_shortest_path_curve(Nurb *nu, int vert_src, int vert_dst)
{
- const int u = nu->pntsu;
- int i;
-
- if (vert_src > vert_dst) {
- SWAP(int, vert_src, vert_dst);
- }
-
- if (nu->flagu & CU_NURB_CYCLIC) {
- if (curve_calc_dist_span(nu, vert_src, vert_dst) >
- curve_calc_dist_span(nu, vert_dst, vert_src))
- {
- SWAP(int, vert_src, vert_dst);
- }
- }
-
- i = vert_src;
- while (true) {
- if (nu->type & CU_BEZIER) {
- select_beztriple(&nu->bezt[i], SELECT, SELECT, HIDDEN);
- }
- else {
- select_bpoint(&nu->bp[i], SELECT, SELECT, HIDDEN);
- }
-
- if (i == vert_dst) {
- break;
- }
- i = (i + 1) % u;
- }
+ const int u = nu->pntsu;
+ int i;
+
+ if (vert_src > vert_dst) {
+ SWAP(int, vert_src, vert_dst);
+ }
+
+ if (nu->flagu & CU_NURB_CYCLIC) {
+ if (curve_calc_dist_span(nu, vert_src, vert_dst) >
+ curve_calc_dist_span(nu, vert_dst, vert_src)) {
+ SWAP(int, vert_src, vert_dst);
+ }
+ }
+
+ i = vert_src;
+ while (true) {
+ if (nu->type & CU_BEZIER) {
+ select_beztriple(&nu->bezt[i], SELECT, SELECT, HIDDEN);
+ }
+ else {
+ select_bpoint(&nu->bp[i], SELECT, SELECT, HIDDEN);
+ }
+
+ if (i == vert_dst) {
+ break;
+ }
+ i = (i + 1) % u;
+ }
}
static void curve_select_shortest_path_surf(Nurb *nu, int vert_src, int vert_dst)
{
- HeapSimple *heap;
-
- int i, vert_curr;
-
- int totu = nu->pntsu;
- int totv = nu->pntsv;
- int vert_num = totu * totv;
-
- /* custom data */
- struct PointAdj {
- int vert, vert_prev;
- float cost;
- } *data;
-
- /* init connectivity data */
- data = MEM_mallocN(sizeof(*data) * vert_num, __func__);
- for (i = 0; i < vert_num; i++) {
- data[i].vert = i;
- data[i].vert_prev = -1;
- data[i].cost = FLT_MAX;
- }
-
- /* init heap */
- heap = BLI_heapsimple_new();
-
- vert_curr = data[vert_src].vert;
- BLI_heapsimple_insert(heap, 0.0f, &data[vert_src].vert);
- data[vert_src].cost = 0.0f;
- data[vert_src].vert_prev = vert_src; /* nop */
-
- while (!BLI_heapsimple_is_empty(heap)) {
- int axis, sign;
- int u, v;
-
- vert_curr = *((int *)BLI_heapsimple_pop_min(heap));
- if (vert_curr == vert_dst) {
- break;
- }
-
- BKE_nurb_index_to_uv(nu, vert_curr, &u, &v);
-
- /* loop over 4 adjacent verts */
- for (sign = -1; sign != 3; sign += 2) {
- for (axis = 0; axis != 2; axis += 1) {
- int uv_other[2] = {u, v};
- int vert_other;
-
- uv_other[axis] += sign;
-
- vert_other = BKE_nurb_index_from_uv(nu, uv_other[0], uv_other[1]);
- if (vert_other != -1) {
- const float dist = data[vert_curr].cost + curve_calc_dist_pair(nu, vert_curr, vert_other);
-
- if (data[vert_other].cost > dist) {
- data[vert_other].cost = dist;
- if (data[vert_other].vert_prev == -1) {
- BLI_heapsimple_insert(heap, data[vert_other].cost, &data[vert_other].vert);
- }
- data[vert_other].vert_prev = vert_curr;
- }
- }
-
- }
- }
-
- }
-
- BLI_heapsimple_free(heap, NULL);
-
- if (vert_curr == vert_dst) {
- i = 0;
- while (vert_curr != vert_src && i++ < vert_num) {
- if (nu->type == CU_BEZIER) {
- select_beztriple(&nu->bezt[vert_curr], SELECT, SELECT, HIDDEN);
- }
- else {
- select_bpoint(&nu->bp[vert_curr], SELECT, SELECT, HIDDEN);
- }
- vert_curr = data[vert_curr].vert_prev;
- }
- }
-
- MEM_freeN(data);
+ HeapSimple *heap;
+
+ int i, vert_curr;
+
+ int totu = nu->pntsu;
+ int totv = nu->pntsv;
+ int vert_num = totu * totv;
+
+ /* custom data */
+ struct PointAdj {
+ int vert, vert_prev;
+ float cost;
+ } * data;
+
+ /* init connectivity data */
+ data = MEM_mallocN(sizeof(*data) * vert_num, __func__);
+ for (i = 0; i < vert_num; i++) {
+ data[i].vert = i;
+ data[i].vert_prev = -1;
+ data[i].cost = FLT_MAX;
+ }
+
+ /* init heap */
+ heap = BLI_heapsimple_new();
+
+ vert_curr = data[vert_src].vert;
+ BLI_heapsimple_insert(heap, 0.0f, &data[vert_src].vert);
+ data[vert_src].cost = 0.0f;
+ data[vert_src].vert_prev = vert_src; /* nop */
+
+ while (!BLI_heapsimple_is_empty(heap)) {
+ int axis, sign;
+ int u, v;
+
+ vert_curr = *((int *)BLI_heapsimple_pop_min(heap));
+ if (vert_curr == vert_dst) {
+ break;
+ }
+
+ BKE_nurb_index_to_uv(nu, vert_curr, &u, &v);
+
+ /* loop over 4 adjacent verts */
+ for (sign = -1; sign != 3; sign += 2) {
+ for (axis = 0; axis != 2; axis += 1) {
+ int uv_other[2] = {u, v};
+ int vert_other;
+
+ uv_other[axis] += sign;
+
+ vert_other = BKE_nurb_index_from_uv(nu, uv_other[0], uv_other[1]);
+ if (vert_other != -1) {
+ const float dist = data[vert_curr].cost +
+ curve_calc_dist_pair(nu, vert_curr, vert_other);
+
+ if (data[vert_other].cost > dist) {
+ data[vert_other].cost = dist;
+ if (data[vert_other].vert_prev == -1) {
+ BLI_heapsimple_insert(heap, data[vert_other].cost, &data[vert_other].vert);
+ }
+ data[vert_other].vert_prev = vert_curr;
+ }
+ }
+ }
+ }
+ }
+
+ BLI_heapsimple_free(heap, NULL);
+
+ if (vert_curr == vert_dst) {
+ i = 0;
+ while (vert_curr != vert_src && i++ < vert_num) {
+ if (nu->type == CU_BEZIER) {
+ select_beztriple(&nu->bezt[vert_curr], SELECT, SELECT, HIDDEN);
+ }
+ else {
+ select_bpoint(&nu->bp[vert_curr], SELECT, SELECT, HIDDEN);
+ }
+ vert_curr = data[vert_curr].vert_prev;
+ }
+ }
+
+ MEM_freeN(data);
}
static int edcu_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewContext vc;
- Nurb *nu_dst;
- BezTriple *bezt_dst;
- BPoint *bp_dst;
- int vert_dst;
- void *vert_dst_p;
- Base *basact = NULL;
-
- view3d_operator_needs_opengl(C);
- ED_view3d_viewcontext_init(C, &vc);
- copy_v2_v2_int(vc.mval, event->mval);
-
- if (!ED_curve_pick_vert(&vc, 1, &nu_dst, &bezt_dst, &bp_dst, NULL, &basact)) {
- return OPERATOR_PASS_THROUGH;
- }
-
- ED_view3d_viewcontext_init_object(&vc, basact->object);
- Object *obedit = basact->object;
- Curve *cu = obedit->data;
- Nurb *nu_src = BKE_curve_nurb_active_get(cu);
- int vert_src = cu->actvert;
-
- if (vert_src == CU_ACT_NONE) {
- return OPERATOR_PASS_THROUGH;
- }
-
- if (nu_src != nu_dst) {
- BKE_report(op->reports, RPT_ERROR, "Control point belongs to another spline");
- return OPERATOR_CANCELLED;
- }
-
- vert_dst_p = bezt_dst ? (void *)bezt_dst : (void *)bp_dst;
- vert_dst = BKE_curve_nurb_vert_index_get(nu_dst, vert_dst_p);
- if (vert_src == vert_dst) {
- return OPERATOR_CANCELLED;
- }
-
- if ((obedit->type == OB_SURF) && (nu_src->pntsv > 1)) {
- curve_select_shortest_path_surf(nu_src, vert_src, vert_dst);
- }
- else {
- curve_select_shortest_path_curve(nu_src, vert_src, vert_dst);
- }
-
- BKE_curve_nurb_vert_active_set(cu, nu_dst, vert_dst_p);
-
- if (vc.view_layer->basact != basact) {
- ED_object_base_activate(C, basact);
- }
-
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- return OPERATOR_FINISHED;
+ ViewContext vc;
+ Nurb *nu_dst;
+ BezTriple *bezt_dst;
+ BPoint *bp_dst;
+ int vert_dst;
+ void *vert_dst_p;
+ Base *basact = NULL;
+
+ view3d_operator_needs_opengl(C);
+ ED_view3d_viewcontext_init(C, &vc);
+ copy_v2_v2_int(vc.mval, event->mval);
+
+ if (!ED_curve_pick_vert(&vc, 1, &nu_dst, &bezt_dst, &bp_dst, NULL, &basact)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ ED_view3d_viewcontext_init_object(&vc, basact->object);
+ Object *obedit = basact->object;
+ Curve *cu = obedit->data;
+ Nurb *nu_src = BKE_curve_nurb_active_get(cu);
+ int vert_src = cu->actvert;
+
+ if (vert_src == CU_ACT_NONE) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ if (nu_src != nu_dst) {
+ BKE_report(op->reports, RPT_ERROR, "Control point belongs to another spline");
+ return OPERATOR_CANCELLED;
+ }
+
+ vert_dst_p = bezt_dst ? (void *)bezt_dst : (void *)bp_dst;
+ vert_dst = BKE_curve_nurb_vert_index_get(nu_dst, vert_dst_p);
+ if (vert_src == vert_dst) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if ((obedit->type == OB_SURF) && (nu_src->pntsv > 1)) {
+ curve_select_shortest_path_surf(nu_src, vert_src, vert_dst);
+ }
+ else {
+ curve_select_shortest_path_curve(nu_src, vert_src, vert_dst);
+ }
+
+ BKE_curve_nurb_vert_active_set(cu, nu_dst, vert_dst_p);
+
+ if (vc.view_layer->basact != basact) {
+ ED_object_base_activate(C, basact);
+ }
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ return OPERATOR_FINISHED;
}
void CURVE_OT_shortest_path_pick(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Pick Shortest Path";
- ot->idname = "CURVE_OT_shortest_path_pick";
- ot->description = "Select shortest path between two selections";
+ /* identifiers */
+ ot->name = "Pick Shortest Path";
+ ot->idname = "CURVE_OT_shortest_path_pick";
+ ot->description = "Select shortest path between two selections";
- /* api callbacks */
- ot->invoke = edcu_shortest_path_pick_invoke;
- ot->poll = ED_operator_editsurfcurve_region_view3d;
+ /* api callbacks */
+ ot->invoke = edcu_shortest_path_pick_invoke;
+ ot->poll = ED_operator_editsurfcurve_region_view3d;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
diff --git a/source/blender/editors/curve/editcurve_undo.c b/source/blender/editors/curve/editcurve_undo.c
index 6cde9abb33f..d0c2afcb1d2 100644
--- a/source/blender/editors/curve/editcurve_undo.c
+++ b/source/blender/editors/curve/editcurve_undo.c
@@ -58,133 +58,131 @@ static CLG_LogRef LOG = {"ed.undo.curve"};
* \{ */
typedef struct {
- ListBase nubase;
- int actvert;
- GHash *undoIndex;
- ListBase fcurves, drivers;
- int actnu;
- int flag;
-
- /* Stored in the object, needed since users may change the active key while in edit-mode. */
- struct {
- short shapenr;
- } obedit;
-
- size_t undo_size;
+ ListBase nubase;
+ int actvert;
+ GHash *undoIndex;
+ ListBase fcurves, drivers;
+ int actnu;
+ int flag;
+
+ /* Stored in the object, needed since users may change the active key while in edit-mode. */
+ struct {
+ short shapenr;
+ } obedit;
+
+ size_t undo_size;
} UndoCurve;
static void undocurve_to_editcurve(Main *bmain, UndoCurve *ucu, Curve *cu, short *r_shapenr)
{
- ListBase *undobase = &ucu->nubase;
- ListBase *editbase = BKE_curve_editNurbs_get(cu);
- Nurb *nu, *newnu;
- EditNurb *editnurb = cu->editnurb;
- AnimData *ad = BKE_animdata_from_id(&cu->id);
-
- BKE_nurbList_free(editbase);
-
- if (ucu->undoIndex) {
- BKE_curve_editNurb_keyIndex_free(&editnurb->keyindex);
- editnurb->keyindex = ED_curve_keyindex_hash_duplicate(ucu->undoIndex);
- }
-
- if (ad) {
- if (ad->action) {
- free_fcurves(&ad->action->curves);
- copy_fcurves(&ad->action->curves, &ucu->fcurves);
- }
-
- free_fcurves(&ad->drivers);
- copy_fcurves(&ad->drivers, &ucu->drivers);
- }
-
- /* copy */
- for (nu = undobase->first; nu; nu = nu->next) {
- newnu = BKE_nurb_duplicate(nu);
-
- if (editnurb->keyindex) {
- ED_curve_keyindex_update_nurb(editnurb, nu, newnu);
- }
-
- BLI_addtail(editbase, newnu);
- }
-
- cu->actvert = ucu->actvert;
- cu->actnu = ucu->actnu;
- cu->flag = ucu->flag;
- *r_shapenr = ucu->obedit.shapenr;
- ED_curve_updateAnimPaths(bmain, cu);
+ ListBase *undobase = &ucu->nubase;
+ ListBase *editbase = BKE_curve_editNurbs_get(cu);
+ Nurb *nu, *newnu;
+ EditNurb *editnurb = cu->editnurb;
+ AnimData *ad = BKE_animdata_from_id(&cu->id);
+
+ BKE_nurbList_free(editbase);
+
+ if (ucu->undoIndex) {
+ BKE_curve_editNurb_keyIndex_free(&editnurb->keyindex);
+ editnurb->keyindex = ED_curve_keyindex_hash_duplicate(ucu->undoIndex);
+ }
+
+ if (ad) {
+ if (ad->action) {
+ free_fcurves(&ad->action->curves);
+ copy_fcurves(&ad->action->curves, &ucu->fcurves);
+ }
+
+ free_fcurves(&ad->drivers);
+ copy_fcurves(&ad->drivers, &ucu->drivers);
+ }
+
+ /* copy */
+ for (nu = undobase->first; nu; nu = nu->next) {
+ newnu = BKE_nurb_duplicate(nu);
+
+ if (editnurb->keyindex) {
+ ED_curve_keyindex_update_nurb(editnurb, nu, newnu);
+ }
+
+ BLI_addtail(editbase, newnu);
+ }
+
+ cu->actvert = ucu->actvert;
+ cu->actnu = ucu->actnu;
+ cu->flag = ucu->flag;
+ *r_shapenr = ucu->obedit.shapenr;
+ ED_curve_updateAnimPaths(bmain, cu);
}
static void undocurve_from_editcurve(UndoCurve *ucu, Curve *cu, const short shapenr)
{
- BLI_assert(BLI_array_is_zeroed(ucu, 1));
- ListBase *nubase = BKE_curve_editNurbs_get(cu);
- EditNurb *editnurb = cu->editnurb, tmpEditnurb;
- Nurb *nu, *newnu;
- AnimData *ad = BKE_animdata_from_id(&cu->id);
-
- /* TODO: include size of fcurve & undoIndex */
- // ucu->undo_size = 0;
-
- if (editnurb->keyindex) {
- ucu->undoIndex = ED_curve_keyindex_hash_duplicate(editnurb->keyindex);
- tmpEditnurb.keyindex = ucu->undoIndex;
- }
-
- if (ad) {
- if (ad->action) {
- copy_fcurves(&ucu->fcurves, &ad->action->curves);
- }
-
- copy_fcurves(&ucu->drivers, &ad->drivers);
- }
-
- /* copy */
- for (nu = nubase->first; nu; nu = nu->next) {
- newnu = BKE_nurb_duplicate(nu);
-
- if (ucu->undoIndex) {
- ED_curve_keyindex_update_nurb(&tmpEditnurb, nu, newnu);
- }
-
- BLI_addtail(&ucu->nubase, newnu);
-
- ucu->undo_size += (
- (nu->bezt ? (sizeof(BezTriple) * nu->pntsu) : 0) +
- (nu->bp ? (sizeof(BPoint) * (nu->pntsu * nu->pntsv)) : 0) +
- (nu->knotsu ? (sizeof(float) * KNOTSU(nu)) : 0) +
- (nu->knotsv ? (sizeof(float) * KNOTSV(nu)) : 0) +
- sizeof(Nurb));
- }
-
- ucu->actvert = cu->actvert;
- ucu->actnu = cu->actnu;
- ucu->flag = cu->flag;
-
- ucu->obedit.shapenr = shapenr;
+ BLI_assert(BLI_array_is_zeroed(ucu, 1));
+ ListBase *nubase = BKE_curve_editNurbs_get(cu);
+ EditNurb *editnurb = cu->editnurb, tmpEditnurb;
+ Nurb *nu, *newnu;
+ AnimData *ad = BKE_animdata_from_id(&cu->id);
+
+ /* TODO: include size of fcurve & undoIndex */
+ // ucu->undo_size = 0;
+
+ if (editnurb->keyindex) {
+ ucu->undoIndex = ED_curve_keyindex_hash_duplicate(editnurb->keyindex);
+ tmpEditnurb.keyindex = ucu->undoIndex;
+ }
+
+ if (ad) {
+ if (ad->action) {
+ copy_fcurves(&ucu->fcurves, &ad->action->curves);
+ }
+
+ copy_fcurves(&ucu->drivers, &ad->drivers);
+ }
+
+ /* copy */
+ for (nu = nubase->first; nu; nu = nu->next) {
+ newnu = BKE_nurb_duplicate(nu);
+
+ if (ucu->undoIndex) {
+ ED_curve_keyindex_update_nurb(&tmpEditnurb, nu, newnu);
+ }
+
+ BLI_addtail(&ucu->nubase, newnu);
+
+ ucu->undo_size += ((nu->bezt ? (sizeof(BezTriple) * nu->pntsu) : 0) +
+ (nu->bp ? (sizeof(BPoint) * (nu->pntsu * nu->pntsv)) : 0) +
+ (nu->knotsu ? (sizeof(float) * KNOTSU(nu)) : 0) +
+ (nu->knotsv ? (sizeof(float) * KNOTSV(nu)) : 0) + sizeof(Nurb));
+ }
+
+ ucu->actvert = cu->actvert;
+ ucu->actnu = cu->actnu;
+ ucu->flag = cu->flag;
+
+ ucu->obedit.shapenr = shapenr;
}
static void undocurve_free_data(UndoCurve *uc)
{
- BKE_nurbList_free(&uc->nubase);
+ BKE_nurbList_free(&uc->nubase);
- BKE_curve_editNurb_keyIndex_free(&uc->undoIndex);
+ BKE_curve_editNurb_keyIndex_free(&uc->undoIndex);
- free_fcurves(&uc->fcurves);
- free_fcurves(&uc->drivers);
+ free_fcurves(&uc->fcurves);
+ free_fcurves(&uc->drivers);
}
static Object *editcurve_object_from_context(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && ELEM(obedit->type, OB_CURVE, OB_SURF)) {
- Curve *cu = obedit->data;
- if (BKE_curve_editNurbs_get(cu) != NULL) {
- return obedit;
- }
- }
- return NULL;
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ Curve *cu = obedit->data;
+ if (BKE_curve_editNurbs_get(cu) != NULL) {
+ return obedit;
+ }
+ }
+ return NULL;
}
/** \} */
@@ -196,113 +194,123 @@ static Object *editcurve_object_from_context(bContext *C)
* \{ */
typedef struct CurveUndoStep_Elem {
- UndoRefID_Object obedit_ref;
- UndoCurve data;
+ UndoRefID_Object obedit_ref;
+ UndoCurve data;
} CurveUndoStep_Elem;
typedef struct CurveUndoStep {
- UndoStep step;
- CurveUndoStep_Elem *elems;
- uint elems_len;
+ UndoStep step;
+ CurveUndoStep_Elem *elems;
+ uint elems_len;
} CurveUndoStep;
static bool curve_undosys_poll(bContext *C)
{
- Object *obedit = editcurve_object_from_context(C);
- return (obedit != NULL);
+ Object *obedit = editcurve_object_from_context(C);
+ return (obedit != NULL);
}
-static bool curve_undosys_step_encode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p)
+static bool curve_undosys_step_encode(struct bContext *C,
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p)
{
- CurveUndoStep *us = (CurveUndoStep *)us_p;
-
- /* Important not to use the 3D view when getting objects because all objects
- * 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);
-
- us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
- us->elems_len = objects_len;
-
- for (uint i = 0; i < objects_len; i++) {
- Object *ob = objects[i];
- CurveUndoStep_Elem *elem = &us->elems[i];
-
- elem->obedit_ref.ptr = ob;
- undocurve_from_editcurve(&elem->data, ob->data, ob->shapenr);
- us->step.data_size += elem->data.undo_size;
- }
- MEM_freeN(objects);
- return true;
+ CurveUndoStep *us = (CurveUndoStep *)us_p;
+
+ /* Important not to use the 3D view when getting objects because all objects
+ * 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);
+
+ us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
+ us->elems_len = objects_len;
+
+ for (uint i = 0; i < objects_len; i++) {
+ Object *ob = objects[i];
+ CurveUndoStep_Elem *elem = &us->elems[i];
+
+ elem->obedit_ref.ptr = ob;
+ undocurve_from_editcurve(&elem->data, ob->data, ob->shapenr);
+ us->step.data_size += elem->data.undo_size;
+ }
+ MEM_freeN(objects);
+ return true;
}
-static void curve_undosys_step_decode(struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir))
+static void curve_undosys_step_decode(struct bContext *C,
+ struct Main *bmain,
+ UndoStep *us_p,
+ int UNUSED(dir))
{
- CurveUndoStep *us = (CurveUndoStep *)us_p;
-
- /* Load all our objects into edit-mode, clear everything else. */
- ED_undo_object_editmode_restore_helper(
- C, &us->elems[0].obedit_ref.ptr, us->elems_len, sizeof(*us->elems));
-
- BLI_assert(curve_undosys_poll(C));
-
- for (uint i = 0; i < us->elems_len; i++) {
- CurveUndoStep_Elem *elem = &us->elems[i];
- Object *obedit = elem->obedit_ref.ptr;
- Curve *cu = obedit->data;
- if (cu->editnurb == NULL) {
- /* Should never fail, may not crash but can give odd behavior. */
- CLOG_ERROR(&LOG, "name='%s', failed to enter edit-mode for object '%s', undo state invalid",
- us_p->name, obedit->id.name);
- continue;
- }
- undocurve_to_editcurve(bmain, &elem->data, obedit->data, &obedit->shapenr);
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
-
- /* The first element is always active */
- ED_undo_object_set_active_or_warn(CTX_data_view_layer(C), us->elems[0].obedit_ref.ptr, us_p->name, &LOG);
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+ CurveUndoStep *us = (CurveUndoStep *)us_p;
+
+ /* Load all our objects into edit-mode, clear everything else. */
+ ED_undo_object_editmode_restore_helper(
+ C, &us->elems[0].obedit_ref.ptr, us->elems_len, sizeof(*us->elems));
+
+ BLI_assert(curve_undosys_poll(C));
+
+ for (uint i = 0; i < us->elems_len; i++) {
+ CurveUndoStep_Elem *elem = &us->elems[i];
+ Object *obedit = elem->obedit_ref.ptr;
+ Curve *cu = obedit->data;
+ if (cu->editnurb == NULL) {
+ /* Should never fail, may not crash but can give odd behavior. */
+ CLOG_ERROR(&LOG,
+ "name='%s', failed to enter edit-mode for object '%s', undo state invalid",
+ us_p->name,
+ obedit->id.name);
+ continue;
+ }
+ undocurve_to_editcurve(bmain, &elem->data, obedit->data, &obedit->shapenr);
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ }
+
+ /* The first element is always active */
+ ED_undo_object_set_active_or_warn(
+ CTX_data_view_layer(C), us->elems[0].obedit_ref.ptr, us_p->name, &LOG);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
}
static void curve_undosys_step_free(UndoStep *us_p)
{
- CurveUndoStep *us = (CurveUndoStep *)us_p;
+ CurveUndoStep *us = (CurveUndoStep *)us_p;
- for (uint i = 0; i < us->elems_len; i++) {
- CurveUndoStep_Elem *elem = &us->elems[i];
- undocurve_free_data(&elem->data);
- }
- MEM_freeN(us->elems);
+ for (uint i = 0; i < us->elems_len; i++) {
+ CurveUndoStep_Elem *elem = &us->elems[i];
+ undocurve_free_data(&elem->data);
+ }
+ MEM_freeN(us->elems);
}
-static void curve_undosys_foreach_ID_ref(
- UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+static void curve_undosys_foreach_ID_ref(UndoStep *us_p,
+ UndoTypeForEachIDRefFn foreach_ID_ref_fn,
+ void *user_data)
{
- CurveUndoStep *us = (CurveUndoStep *)us_p;
+ CurveUndoStep *us = (CurveUndoStep *)us_p;
- for (uint i = 0; i < us->elems_len; i++) {
- CurveUndoStep_Elem *elem = &us->elems[i];
- foreach_ID_ref_fn(user_data, ((UndoRefID *)&elem->obedit_ref));
- }
+ for (uint i = 0; i < us->elems_len; i++) {
+ CurveUndoStep_Elem *elem = &us->elems[i];
+ foreach_ID_ref_fn(user_data, ((UndoRefID *)&elem->obedit_ref));
+ }
}
/* Export for ED_undo_sys. */
void ED_curve_undosys_type(UndoType *ut)
{
- ut->name = "Edit Curve";
- ut->poll = curve_undosys_poll;
- ut->step_encode = curve_undosys_step_encode;
- ut->step_decode = curve_undosys_step_decode;
- ut->step_free = curve_undosys_step_free;
+ ut->name = "Edit Curve";
+ ut->poll = curve_undosys_poll;
+ ut->step_encode = curve_undosys_step_encode;
+ ut->step_decode = curve_undosys_step_decode;
+ ut->step_free = curve_undosys_step_free;
- ut->step_foreach_ID_ref = curve_undosys_foreach_ID_ref;
+ ut->step_foreach_ID_ref = curve_undosys_foreach_ID_ref;
- ut->use_context = true;
+ ut->use_context = true;
- ut->step_size = sizeof(CurveUndoStep);
+ ut->step_size = sizeof(CurveUndoStep);
}
/** \} */
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 480819dd47a..d1b1f43d8dd 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -21,7 +21,6 @@
* \ingroup edcurve
*/
-
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
@@ -76,1927 +75,2118 @@ static int kill_selection(Object *obedit, int ins);
static char findaccent(char char1, unsigned int code)
{
- char new = 0;
-
- if (char1 == 'a') {
- if (code == '`') { new = 224; }
- else if (code == 39) { new = 225; }
- else if (code == '^') { new = 226; }
- else if (code == '~') { new = 227; }
- else if (code == '"') { new = 228; }
- else if (code == 'o') { new = 229; }
- else if (code == 'e') { new = 230; }
- else if (code == '-') { new = 170; }
- }
- else if (char1 == 'c') {
- if (code == ',') { new = 231; }
- else if (code == '|') { new = 162; }
- else if (code == 'o') { new = 169; }
- }
- else if (char1 == 'e') {
- if (code == '`') { new = 232; }
- else if (code == 39) { new = 233; }
- else if (code == '^') { new = 234; }
- else if (code == '"') { new = 235; }
- }
- else if (char1 == 'i') {
- if (code == '`') { new = 236; }
- else if (code == 39) { new = 237; }
- else if (code == '^') { new = 238; }
- else if (code == '"') { new = 239; }
- }
- else if (char1 == 'n') {
- if (code == '~') { new = 241; }
- }
- else if (char1 == 'o') {
- if (code == '`') { new = 242; }
- else if (code == 39) { new = 243; }
- else if (code == '^') { new = 244; }
- else if (code == '~') { new = 245; }
- else if (code == '"') { new = 246; }
- else if (code == '/') { new = 248; }
- else if (code == '-') { new = 186; }
- else if (code == 'e') { new = 143; }
- else if (code == 'c') { new = 169; }
- else if (code == 'r') { new = 174; }
- }
- else if (char1 == 'r') {
- if (code == 'o') { new = 174; }
- }
- else if (char1 == 's') {
- if (code == 's') { new = 167; }
- }
- else if (char1 == 't') {
- if (code == 'm') { new = 153; }
- }
- else if (char1 == 'u') {
- if (code == '`') { new = 249; }
- else if (code == 39) { new = 250; }
- else if (code == '^') { new = 251; }
- else if (code == '"') { new = 252; }
- }
- else if (char1 == 'y') {
- if (code == 39) { new = 253; }
- else if (code == '"') { new = 255; }
- }
- else if (char1 == 'A') {
- if (code == '`') { new = 192; }
- else if (code == 39) { new = 193; }
- else if (code == '^') { new = 194; }
- else if (code == '~') { new = 195; }
- else if (code == '"') { new = 196; }
- else if (code == 'o') { new = 197; }
- else if (code == 'e') { new = 198; }
- }
- else if (char1 == 'C') {
- if (code == ',') { new = 199; }
- }
- else if (char1 == 'E') {
- if (code == '`') { new = 200; }
- else if (code == 39) { new = 201; }
- else if (code == '^') { new = 202; }
- else if (code == '"') { new = 203; }
- }
- else if (char1 == 'I') {
- if (code == '`') { new = 204; }
- else if (code == 39) { new = 205; }
- else if (code == '^') { new = 206; }
- else if (code == '"') { new = 207; }
- }
- else if (char1 == 'N') {
- if (code == '~') { new = 209; }
- }
- else if (char1 == 'O') {
- if (code == '`') { new = 210; }
- else if (code == 39) { new = 211; }
- else if (code == '^') { new = 212; }
- else if (code == '~') { new = 213; }
- else if (code == '"') { new = 214; }
- else if (code == '/') { new = 216; }
- else if (code == 'e') { new = 141; }
- }
- else if (char1 == 'U') {
- if (code == '`') { new = 217; }
- else if (code == 39) { new = 218; }
- else if (code == '^') { new = 219; }
- else if (code == '"') { new = 220; }
- }
- else if (char1 == 'Y') {
- if (code == 39) { new = 221; }
- }
- else if (char1 == '1') {
- if (code == '4') { new = 188; }
- if (code == '2') { new = 189; }
- }
- else if (char1 == '3') {
- if (code == '4') { new = 190; }
- }
- else if (char1 == ':') {
- if (code == '-') { new = 247; }
- }
- else if (char1 == '-') {
- if (code == ':') { new = 247; }
- if (code == '|') { new = 135; }
- if (code == '+') { new = 177; }
- }
- else if (char1 == '|') {
- if (code == '-') { new = 135; }
- if (code == '=') { new = 136; }
- }
- else if (char1 == '=') {
- if (code == '|') { new = 136; }
- }
- else if (char1 == '+') {
- if (code == '-') { new = 177; }
- }
-
- if (new) {
- return new;
- }
- else {
- return char1;
- }
+ char new = 0;
+
+ if (char1 == 'a') {
+ if (code == '`') {
+ new = 224;
+ }
+ else if (code == 39) {
+ new = 225;
+ }
+ else if (code == '^') {
+ new = 226;
+ }
+ else if (code == '~') {
+ new = 227;
+ }
+ else if (code == '"') {
+ new = 228;
+ }
+ else if (code == 'o') {
+ new = 229;
+ }
+ else if (code == 'e') {
+ new = 230;
+ }
+ else if (code == '-') {
+ new = 170;
+ }
+ }
+ else if (char1 == 'c') {
+ if (code == ',') {
+ new = 231;
+ }
+ else if (code == '|') {
+ new = 162;
+ }
+ else if (code == 'o') {
+ new = 169;
+ }
+ }
+ else if (char1 == 'e') {
+ if (code == '`') {
+ new = 232;
+ }
+ else if (code == 39) {
+ new = 233;
+ }
+ else if (code == '^') {
+ new = 234;
+ }
+ else if (code == '"') {
+ new = 235;
+ }
+ }
+ else if (char1 == 'i') {
+ if (code == '`') {
+ new = 236;
+ }
+ else if (code == 39) {
+ new = 237;
+ }
+ else if (code == '^') {
+ new = 238;
+ }
+ else if (code == '"') {
+ new = 239;
+ }
+ }
+ else if (char1 == 'n') {
+ if (code == '~') {
+ new = 241;
+ }
+ }
+ else if (char1 == 'o') {
+ if (code == '`') {
+ new = 242;
+ }
+ else if (code == 39) {
+ new = 243;
+ }
+ else if (code == '^') {
+ new = 244;
+ }
+ else if (code == '~') {
+ new = 245;
+ }
+ else if (code == '"') {
+ new = 246;
+ }
+ else if (code == '/') {
+ new = 248;
+ }
+ else if (code == '-') {
+ new = 186;
+ }
+ else if (code == 'e') {
+ new = 143;
+ }
+ else if (code == 'c') {
+ new = 169;
+ }
+ else if (code == 'r') {
+ new = 174;
+ }
+ }
+ else if (char1 == 'r') {
+ if (code == 'o') {
+ new = 174;
+ }
+ }
+ else if (char1 == 's') {
+ if (code == 's') {
+ new = 167;
+ }
+ }
+ else if (char1 == 't') {
+ if (code == 'm') {
+ new = 153;
+ }
+ }
+ else if (char1 == 'u') {
+ if (code == '`') {
+ new = 249;
+ }
+ else if (code == 39) {
+ new = 250;
+ }
+ else if (code == '^') {
+ new = 251;
+ }
+ else if (code == '"') {
+ new = 252;
+ }
+ }
+ else if (char1 == 'y') {
+ if (code == 39) {
+ new = 253;
+ }
+ else if (code == '"') {
+ new = 255;
+ }
+ }
+ else if (char1 == 'A') {
+ if (code == '`') {
+ new = 192;
+ }
+ else if (code == 39) {
+ new = 193;
+ }
+ else if (code == '^') {
+ new = 194;
+ }
+ else if (code == '~') {
+ new = 195;
+ }
+ else if (code == '"') {
+ new = 196;
+ }
+ else if (code == 'o') {
+ new = 197;
+ }
+ else if (code == 'e') {
+ new = 198;
+ }
+ }
+ else if (char1 == 'C') {
+ if (code == ',') {
+ new = 199;
+ }
+ }
+ else if (char1 == 'E') {
+ if (code == '`') {
+ new = 200;
+ }
+ else if (code == 39) {
+ new = 201;
+ }
+ else if (code == '^') {
+ new = 202;
+ }
+ else if (code == '"') {
+ new = 203;
+ }
+ }
+ else if (char1 == 'I') {
+ if (code == '`') {
+ new = 204;
+ }
+ else if (code == 39) {
+ new = 205;
+ }
+ else if (code == '^') {
+ new = 206;
+ }
+ else if (code == '"') {
+ new = 207;
+ }
+ }
+ else if (char1 == 'N') {
+ if (code == '~') {
+ new = 209;
+ }
+ }
+ else if (char1 == 'O') {
+ if (code == '`') {
+ new = 210;
+ }
+ else if (code == 39) {
+ new = 211;
+ }
+ else if (code == '^') {
+ new = 212;
+ }
+ else if (code == '~') {
+ new = 213;
+ }
+ else if (code == '"') {
+ new = 214;
+ }
+ else if (code == '/') {
+ new = 216;
+ }
+ else if (code == 'e') {
+ new = 141;
+ }
+ }
+ else if (char1 == 'U') {
+ if (code == '`') {
+ new = 217;
+ }
+ else if (code == 39) {
+ new = 218;
+ }
+ else if (code == '^') {
+ new = 219;
+ }
+ else if (code == '"') {
+ new = 220;
+ }
+ }
+ else if (char1 == 'Y') {
+ if (code == 39) {
+ new = 221;
+ }
+ }
+ else if (char1 == '1') {
+ if (code == '4') {
+ new = 188;
+ }
+ if (code == '2') {
+ new = 189;
+ }
+ }
+ else if (char1 == '3') {
+ if (code == '4') {
+ new = 190;
+ }
+ }
+ else if (char1 == ':') {
+ if (code == '-') {
+ new = 247;
+ }
+ }
+ else if (char1 == '-') {
+ if (code == ':') {
+ new = 247;
+ }
+ if (code == '|') {
+ new = 135;
+ }
+ if (code == '+') {
+ new = 177;
+ }
+ }
+ else if (char1 == '|') {
+ if (code == '-') {
+ new = 135;
+ }
+ if (code == '=') {
+ new = 136;
+ }
+ }
+ else if (char1 == '=') {
+ if (code == '|') {
+ new = 136;
+ }
+ }
+ else if (char1 == '+') {
+ if (code == '-') {
+ new = 177;
+ }
+ }
+
+ if (new) {
+ return new;
+ }
+ else {
+ return char1;
+ }
}
static int insert_into_textbuf(Object *obedit, uintptr_t c)
{
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
-
- if (ef->len < MAXTEXT - 1) {
- int x;
-
- for (x = ef->len; x > ef->pos; x--) {
- ef->textbuf[x] = ef->textbuf[x - 1];
- }
- for (x = ef->len; x > ef->pos; x--) {
- ef->textbufinfo[x] = ef->textbufinfo[x - 1];
- }
- ef->textbuf[ef->pos] = c;
- ef->textbufinfo[ef->pos] = cu->curinfo;
- ef->textbufinfo[ef->pos].kern = 0;
- ef->textbufinfo[ef->pos].mat_nr = obedit->actcol;
-
- ef->pos++;
- ef->len++;
- ef->textbuf[ef->len] = '\0';
-
- return 1;
- }
- else {
- return 0;
- }
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
+
+ if (ef->len < MAXTEXT - 1) {
+ int x;
+
+ for (x = ef->len; x > ef->pos; x--) {
+ ef->textbuf[x] = ef->textbuf[x - 1];
+ }
+ for (x = ef->len; x > ef->pos; x--) {
+ ef->textbufinfo[x] = ef->textbufinfo[x - 1];
+ }
+ ef->textbuf[ef->pos] = c;
+ ef->textbufinfo[ef->pos] = cu->curinfo;
+ ef->textbufinfo[ef->pos].kern = 0;
+ ef->textbufinfo[ef->pos].mat_nr = obedit->actcol;
+
+ ef->pos++;
+ ef->len++;
+ ef->textbuf[ef->len] = '\0';
+
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
static void text_update_edited(bContext *C, Object *obedit, int mode)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
-
- BLI_assert(ef->len >= 0);
-
- /* run update first since it can move the cursor */
- if (mode == FO_EDIT) {
- /* re-tesselllate */
- DEG_id_tag_update(obedit->data, 0);
- }
- else {
- /* depsgraph runs above, but since we're not tagging for update, call direct */
- /* We need evaluated data here. */
- BKE_vfont_to_curve(DEG_get_evaluated_object(depsgraph, obedit), mode);
- }
-
- cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0];
-
- if (obedit->totcol > 0) {
- obedit->actcol = cu->curinfo.mat_nr;
-
- /* since this array is calloc'd, it can be 0 even though we try ensure
- * (mat_nr > 0) almost everywhere */
- if (obedit->actcol < 1) {
- obedit->actcol = 1;
- }
- }
-
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
+
+ BLI_assert(ef->len >= 0);
+
+ /* run update first since it can move the cursor */
+ if (mode == FO_EDIT) {
+ /* re-tesselllate */
+ DEG_id_tag_update(obedit->data, 0);
+ }
+ else {
+ /* depsgraph runs above, but since we're not tagging for update, call direct */
+ /* We need evaluated data here. */
+ BKE_vfont_to_curve(DEG_get_evaluated_object(depsgraph, obedit), mode);
+ }
+
+ cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0];
+
+ if (obedit->totcol > 0) {
+ obedit->actcol = cu->curinfo.mat_nr;
+
+ /* since this array is calloc'd, it can be 0 even though we try ensure
+ * (mat_nr > 0) almost everywhere */
+ if (obedit->actcol < 1) {
+ obedit->actcol = 1;
+ }
+ }
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
}
/* -------------------------------------------------------------------- */
/* Generic Paste Functions */
/* text_update_edited(C, scene, obedit, 1, FO_EDIT); */
-static bool font_paste_wchar(Object *obedit, const wchar_t *str, const size_t str_len,
+static bool font_paste_wchar(Object *obedit,
+ const wchar_t *str,
+ const size_t str_len,
/* optional */
struct CharInfo *str_info)
{
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
- int selend, selstart;
-
- if (BKE_vfont_select_get(obedit, &selstart, &selend) == 0) {
- selstart = selend = 0;
- }
-
- /* Verify that the copy buffer => [copy buffer len] + ef->len < MAXTEXT */
- if ((ef->len + str_len) - (selend - selstart) <= MAXTEXT) {
-
- kill_selection(obedit, 0);
-
- if (str_len) {
- int size = (ef->len * sizeof(wchar_t)) - (ef->pos * sizeof(wchar_t)) + sizeof(wchar_t);
- memmove(ef->textbuf + ef->pos + str_len, ef->textbuf + ef->pos, size);
- memcpy(ef->textbuf + ef->pos, str, str_len * sizeof(wchar_t));
-
- memmove(ef->textbufinfo + ef->pos + str_len, ef->textbufinfo + ef->pos, (ef->len - ef->pos + 1) * sizeof(CharInfo));
- if (str_info) {
- memcpy(ef->textbufinfo + ef->pos, str_info, str_len * sizeof(CharInfo));
- }
- else {
- memset(ef->textbufinfo + ef->pos, '\0', str_len * sizeof(CharInfo));
- }
-
- ef->len += str_len;
- ef->pos += str_len;
- }
-
- return true;
- }
-
- return false;
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
+ int selend, selstart;
+
+ if (BKE_vfont_select_get(obedit, &selstart, &selend) == 0) {
+ selstart = selend = 0;
+ }
+
+ /* Verify that the copy buffer => [copy buffer len] + ef->len < MAXTEXT */
+ if ((ef->len + str_len) - (selend - selstart) <= MAXTEXT) {
+
+ kill_selection(obedit, 0);
+
+ if (str_len) {
+ int size = (ef->len * sizeof(wchar_t)) - (ef->pos * sizeof(wchar_t)) + sizeof(wchar_t);
+ memmove(ef->textbuf + ef->pos + str_len, ef->textbuf + ef->pos, size);
+ memcpy(ef->textbuf + ef->pos, str, str_len * sizeof(wchar_t));
+
+ memmove(ef->textbufinfo + ef->pos + str_len,
+ ef->textbufinfo + ef->pos,
+ (ef->len - ef->pos + 1) * sizeof(CharInfo));
+ if (str_info) {
+ memcpy(ef->textbufinfo + ef->pos, str_info, str_len * sizeof(CharInfo));
+ }
+ else {
+ memset(ef->textbufinfo + ef->pos, '\0', str_len * sizeof(CharInfo));
+ }
+
+ ef->len += str_len;
+ ef->pos += str_len;
+ }
+
+ return true;
+ }
+
+ return false;
}
static bool font_paste_utf8(bContext *C, const char *str, const size_t str_len)
{
- Object *obedit = CTX_data_edit_object(C);
- bool retval;
+ Object *obedit = CTX_data_edit_object(C);
+ bool retval;
- int tmplen;
+ int tmplen;
- wchar_t *mem = MEM_mallocN((sizeof(wchar_t) * (str_len + 1)), __func__);
+ wchar_t *mem = MEM_mallocN((sizeof(wchar_t) * (str_len + 1)), __func__);
- tmplen = BLI_strncpy_wchar_from_utf8(mem, str, str_len + 1);
+ tmplen = BLI_strncpy_wchar_from_utf8(mem, str, str_len + 1);
- retval = font_paste_wchar(obedit, mem, tmplen, NULL);
+ retval = font_paste_wchar(obedit, mem, tmplen, NULL);
- MEM_freeN(mem);
+ MEM_freeN(mem);
- return retval;
+ return retval;
}
-
/* -------------------------------------------------------------------- */
/* Paste From File*/
static int paste_from_file(bContext *C, ReportList *reports, const char *filename)
{
- Object *obedit = CTX_data_edit_object(C);
- char *strp;
- size_t filelen;
- int retval;
-
- strp = BLI_file_read_text_as_mem(filename, 1, &filelen);
- if (strp == NULL) {
- BKE_reportf(reports, RPT_ERROR, "Failed to open file '%s'", filename);
- return OPERATOR_CANCELLED;
- }
- strp[filelen] = 0;
-
- if (font_paste_utf8(C, strp, filelen)) {
- text_update_edited(C, obedit, FO_EDIT);
- retval = OPERATOR_FINISHED;
-
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "File too long %s", filename);
- retval = OPERATOR_CANCELLED;
- }
-
- MEM_freeN(strp);
-
- return retval;
+ Object *obedit = CTX_data_edit_object(C);
+ char *strp;
+ size_t filelen;
+ int retval;
+
+ strp = BLI_file_read_text_as_mem(filename, 1, &filelen);
+ if (strp == NULL) {
+ BKE_reportf(reports, RPT_ERROR, "Failed to open file '%s'", filename);
+ return OPERATOR_CANCELLED;
+ }
+ strp[filelen] = 0;
+
+ if (font_paste_utf8(C, strp, filelen)) {
+ text_update_edited(C, obedit, FO_EDIT);
+ retval = OPERATOR_FINISHED;
+ }
+ else {
+ BKE_reportf(reports, RPT_ERROR, "File too long %s", filename);
+ retval = OPERATOR_CANCELLED;
+ }
+
+ MEM_freeN(strp);
+
+ return retval;
}
static int paste_from_file_exec(bContext *C, wmOperator *op)
{
- char *path;
- int retval;
+ char *path;
+ int retval;
- path = RNA_string_get_alloc(op->ptr, "filepath", NULL, 0);
- retval = paste_from_file(C, op->reports, path);
- MEM_freeN(path);
+ path = RNA_string_get_alloc(op->ptr, "filepath", NULL, 0);
+ retval = paste_from_file(C, op->reports, path);
+ MEM_freeN(path);
- return retval;
+ return retval;
}
static int paste_from_file_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (RNA_struct_property_is_set(op->ptr, "filepath")) {
- return paste_from_file_exec(C, op);
- }
+ if (RNA_struct_property_is_set(op->ptr, "filepath")) {
+ return paste_from_file_exec(C, op);
+ }
- WM_event_add_fileselect(C, op);
+ WM_event_add_fileselect(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void FONT_OT_text_paste_from_file(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Paste File";
- ot->description = "Paste contents from file";
- ot->idname = "FONT_OT_text_paste_from_file";
-
- /* api callbacks */
- ot->exec = paste_from_file_exec;
- ot->invoke = paste_from_file_invoke;
- ot->poll = ED_operator_editfont;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_TEXT, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+ /* identifiers */
+ ot->name = "Paste File";
+ ot->description = "Paste contents from file";
+ ot->idname = "FONT_OT_text_paste_from_file";
+
+ /* api callbacks */
+ ot->exec = paste_from_file_exec;
+ ot->invoke = paste_from_file_invoke;
+ ot->poll = ED_operator_editfont;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_TEXT,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_FILEPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
}
/******************* text to object operator ********************/
static void txt_add_object(bContext *C, TextLine *firstline, int totline, const float offset[3])
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Curve *cu;
- Object *obedit;
- Base *base;
- struct TextLine *tmp;
- int nchars = 0, nbytes = 0;
- char *s;
- int a;
- float rot[3] = {0.f, 0.f, 0.f};
-
- obedit = BKE_object_add(bmain, scene, view_layer, OB_FONT, NULL);
- base = view_layer->basact;
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Curve *cu;
+ Object *obedit;
+ Base *base;
+ struct TextLine *tmp;
+ int nchars = 0, nbytes = 0;
+ char *s;
+ int a;
+ float rot[3] = {0.f, 0.f, 0.f};
- /* seems to assume view align ? TODO - look into this, could be an operator option */
- ED_object_base_init_transform(C, base, NULL, rot);
+ obedit = BKE_object_add(bmain, scene, view_layer, OB_FONT, NULL);
+ base = view_layer->basact;
- BKE_object_where_is_calc(depsgraph, scene, obedit);
+ /* seems to assume view align ? TODO - look into this, could be an operator option */
+ ED_object_base_init_transform(C, base, NULL, rot);
- add_v3_v3(obedit->loc, offset);
+ BKE_object_where_is_calc(depsgraph, scene, obedit);
- cu = obedit->data;
- cu->vfont = BKE_vfont_builtin_get();
- id_us_plus(&cu->vfont->id);
+ add_v3_v3(obedit->loc, offset);
- for (tmp = firstline, a = 0; nbytes < MAXTEXT && a < totline; tmp = tmp->next, a++) {
- size_t nchars_line, nbytes_line;
- nchars_line = BLI_strlen_utf8_ex(tmp->line, &nbytes_line);
- nchars += nchars_line + 1;
- nbytes += nbytes_line + 1;
- }
+ cu = obedit->data;
+ cu->vfont = BKE_vfont_builtin_get();
+ id_us_plus(&cu->vfont->id);
- if (cu->str) {
- MEM_freeN(cu->str);
- }
- if (cu->strinfo) {
- MEM_freeN(cu->strinfo);
- }
+ for (tmp = firstline, a = 0; nbytes < MAXTEXT && a < totline; tmp = tmp->next, a++) {
+ size_t nchars_line, nbytes_line;
+ nchars_line = BLI_strlen_utf8_ex(tmp->line, &nbytes_line);
+ nchars += nchars_line + 1;
+ nbytes += nbytes_line + 1;
+ }
- cu->str = MEM_mallocN(nbytes + 4, "str");
- cu->strinfo = MEM_callocN((nchars + 4) * sizeof(CharInfo), "strinfo");
+ if (cu->str) {
+ MEM_freeN(cu->str);
+ }
+ if (cu->strinfo) {
+ MEM_freeN(cu->strinfo);
+ }
- cu->len = 0;
- cu->len_wchar = nchars - 1;
- cu->pos = 0;
+ cu->str = MEM_mallocN(nbytes + 4, "str");
+ cu->strinfo = MEM_callocN((nchars + 4) * sizeof(CharInfo), "strinfo");
- s = cu->str;
+ cu->len = 0;
+ cu->len_wchar = nchars - 1;
+ cu->pos = 0;
- for (tmp = firstline, a = 0; cu->len < MAXTEXT && a < totline; tmp = tmp->next, a++) {
- size_t nbytes_line;
+ s = cu->str;
- nbytes_line = BLI_strcpy_rlen(s, tmp->line);
+ for (tmp = firstline, a = 0; cu->len < MAXTEXT && a < totline; tmp = tmp->next, a++) {
+ size_t nbytes_line;
- s += nbytes_line;
- cu->len += nbytes_line;
+ nbytes_line = BLI_strcpy_rlen(s, tmp->line);
- if (tmp->next) {
- nbytes_line = BLI_strcpy_rlen(s, "\n");
+ s += nbytes_line;
+ cu->len += nbytes_line;
- s += nbytes_line;
- cu->len += nbytes_line;
- }
+ if (tmp->next) {
+ nbytes_line = BLI_strcpy_rlen(s, "\n");
- }
+ s += nbytes_line;
+ cu->len += nbytes_line;
+ }
+ }
- cu->pos = cu->len_wchar;
- *s = '\0';
+ cu->pos = cu->len_wchar;
+ *s = '\0';
- WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, obedit);
+ WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, obedit);
}
void ED_text_to_object(bContext *C, Text *text, const bool split_lines)
{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- TextLine *line;
- float offset[3];
- int linenum = 0;
-
- if (!text || !text->lines.first) {
- return;
- }
-
- if (split_lines) {
- for (line = text->lines.first; line; line = line->next) {
- /* skip lines with no text, but still make space for them */
- if (line->line[0] == '\0') {
- linenum++;
- continue;
- }
-
- /* do the translation */
- offset[0] = 0;
- offset[1] = -linenum;
- offset[2] = 0;
-
- if (rv3d) {
- mul_mat3_m4_v3(rv3d->viewinv, offset);
- }
-
- txt_add_object(C, line, 1, offset);
-
- linenum++;
- }
- }
- else {
- offset[0] = 0.0f;
- offset[1] = 0.0f;
- offset[2] = 0.0f;
-
- txt_add_object(C, text->lines.first, BLI_listbase_count(&text->lines), offset);
- }
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ TextLine *line;
+ float offset[3];
+ int linenum = 0;
+
+ if (!text || !text->lines.first) {
+ return;
+ }
+
+ if (split_lines) {
+ for (line = text->lines.first; line; line = line->next) {
+ /* skip lines with no text, but still make space for them */
+ if (line->line[0] == '\0') {
+ linenum++;
+ continue;
+ }
+
+ /* do the translation */
+ offset[0] = 0;
+ offset[1] = -linenum;
+ offset[2] = 0;
+
+ if (rv3d) {
+ mul_mat3_m4_v3(rv3d->viewinv, offset);
+ }
+
+ txt_add_object(C, line, 1, offset);
+
+ linenum++;
+ }
+ }
+ else {
+ offset[0] = 0.0f;
+ offset[1] = 0.0f;
+ offset[2] = 0.0f;
+
+ txt_add_object(C, text->lines.first, BLI_listbase_count(&text->lines), offset);
+ }
}
/********************** utilities ***************************/
-static int kill_selection(Object *obedit, int ins) /* 1 == new character */
+static int kill_selection(Object *obedit, int ins) /* 1 == new character */
{
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
- int selend, selstart, direction;
- int offset = 0;
- int getfrom;
-
- direction = BKE_vfont_select_get(obedit, &selstart, &selend);
- if (direction) {
- int size;
- if (ins) {
- offset = 1;
- }
- if (ef->pos >= selstart) {
- ef->pos = selstart + offset;
- }
- if ((direction == -1) && ins) {
- selstart++;
- selend++;
- }
- getfrom = selend + offset;
- if (ins == 0) {
- getfrom++;
- }
- size = (ef->len * sizeof(wchar_t)) - (selstart * sizeof(wchar_t)) + (offset * sizeof(wchar_t));
- memmove(ef->textbuf + selstart, ef->textbuf + getfrom, size);
- memmove(ef->textbufinfo + selstart, ef->textbufinfo + getfrom, ((ef->len - selstart) + offset) * sizeof(CharInfo));
- ef->len -= ((selend - selstart) + 1);
- ef->selstart = ef->selend = 0;
- }
-
- return(direction);
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
+ int selend, selstart, direction;
+ int offset = 0;
+ int getfrom;
+
+ direction = BKE_vfont_select_get(obedit, &selstart, &selend);
+ if (direction) {
+ int size;
+ if (ins) {
+ offset = 1;
+ }
+ if (ef->pos >= selstart) {
+ ef->pos = selstart + offset;
+ }
+ if ((direction == -1) && ins) {
+ selstart++;
+ selend++;
+ }
+ getfrom = selend + offset;
+ if (ins == 0) {
+ getfrom++;
+ }
+ size = (ef->len * sizeof(wchar_t)) - (selstart * sizeof(wchar_t)) + (offset * sizeof(wchar_t));
+ memmove(ef->textbuf + selstart, ef->textbuf + getfrom, size);
+ memmove(ef->textbufinfo + selstart,
+ ef->textbufinfo + getfrom,
+ ((ef->len - selstart) + offset) * sizeof(CharInfo));
+ ef->len -= ((selend - selstart) + 1);
+ ef->selstart = ef->selend = 0;
+ }
+
+ return (direction);
}
/******************* set style operator ********************/
static const EnumPropertyItem style_items[] = {
- {CU_CHINFO_BOLD, "BOLD", 0, "Bold", ""},
- {CU_CHINFO_ITALIC, "ITALIC", 0, "Italic", ""},
- {CU_CHINFO_UNDERLINE, "UNDERLINE", 0, "Underline", ""},
- {CU_CHINFO_SMALLCAPS, "SMALL_CAPS", 0, "Small Caps", ""},
- {0, NULL, 0, NULL, NULL},
+ {CU_CHINFO_BOLD, "BOLD", 0, "Bold", ""},
+ {CU_CHINFO_ITALIC, "ITALIC", 0, "Italic", ""},
+ {CU_CHINFO_UNDERLINE, "UNDERLINE", 0, "Underline", ""},
+ {CU_CHINFO_SMALLCAPS, "SMALL_CAPS", 0, "Small Caps", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int set_style(bContext *C, const int style, const bool clear)
{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
- int i, selstart, selend;
-
- if (!BKE_vfont_select_get(obedit, &selstart, &selend)) {
- return OPERATOR_CANCELLED;
- }
-
- for (i = selstart; i <= selend; i++) {
- if (clear) {
- ef->textbufinfo[i].flag &= ~style;
- }
- else {
- ef->textbufinfo[i].flag |= style;
- }
- }
-
- DEG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
+ int i, selstart, selend;
+
+ if (!BKE_vfont_select_get(obedit, &selstart, &selend)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ for (i = selstart; i <= selend; i++) {
+ if (clear) {
+ ef->textbufinfo[i].flag &= ~style;
+ }
+ else {
+ ef->textbufinfo[i].flag |= style;
+ }
+ }
+
+ DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
}
static int set_style_exec(bContext *C, wmOperator *op)
{
- const int style = RNA_enum_get(op->ptr, "style");
- const bool clear = RNA_boolean_get(op->ptr, "clear");
+ const int style = RNA_enum_get(op->ptr, "style");
+ const bool clear = RNA_boolean_get(op->ptr, "clear");
- return set_style(C, style, clear);
+ return set_style(C, style, clear);
}
void FONT_OT_style_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Style";
- ot->description = "Set font style";
- ot->idname = "FONT_OT_style_set";
-
- /* api callbacks */
- ot->exec = set_style_exec;
- ot->poll = ED_operator_editfont;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "style", style_items, CU_CHINFO_BOLD, "Style", "Style to set selection to");
- RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear style rather than setting it");
+ /* identifiers */
+ ot->name = "Set Style";
+ ot->description = "Set font style";
+ ot->idname = "FONT_OT_style_set";
+
+ /* api callbacks */
+ ot->exec = set_style_exec;
+ ot->poll = ED_operator_editfont;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(
+ ot->srna, "style", style_items, CU_CHINFO_BOLD, "Style", "Style to set selection to");
+ RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear style rather than setting it");
}
/******************* toggle style operator ********************/
static int toggle_style_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = obedit->data;
- int style, clear, selstart, selend;
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ int style, clear, selstart, selend;
- if (!BKE_vfont_select_get(obedit, &selstart, &selend)) {
- return OPERATOR_CANCELLED;
- }
+ if (!BKE_vfont_select_get(obedit, &selstart, &selend)) {
+ return OPERATOR_CANCELLED;
+ }
- style = RNA_enum_get(op->ptr, "style");
+ style = RNA_enum_get(op->ptr, "style");
- cu->curinfo.flag ^= style;
- clear = (cu->curinfo.flag & style) == 0;
+ cu->curinfo.flag ^= style;
+ clear = (cu->curinfo.flag & style) == 0;
- return set_style(C, style, clear);
+ return set_style(C, style, clear);
}
void FONT_OT_style_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Style";
- ot->description = "Toggle font style";
- ot->idname = "FONT_OT_style_toggle";
+ /* identifiers */
+ ot->name = "Toggle Style";
+ ot->description = "Toggle font style";
+ ot->idname = "FONT_OT_style_toggle";
- /* api callbacks */
- ot->exec = toggle_style_exec;
- ot->poll = ED_operator_editfont;
+ /* api callbacks */
+ ot->exec = toggle_style_exec;
+ ot->poll = ED_operator_editfont;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_enum(ot->srna, "style", style_items, CU_CHINFO_BOLD, "Style", "Style to set selection to");
+ /* properties */
+ RNA_def_enum(
+ ot->srna, "style", style_items, CU_CHINFO_BOLD, "Style", "Style to set selection to");
}
-
/* -------------------------------------------------------------------- */
/* Select All */
static int font_select_all_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
-
- if (ef->len) {
- ef->selstart = 1;
- ef->selend = ef->len;
- ef->pos = ef->len;
-
- text_update_edited(C, obedit, FO_SELCHANGE);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
-
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
+
+ if (ef->len) {
+ ef->selstart = 1;
+ ef->selend = ef->len;
+ ef->pos = ef->len;
+
+ text_update_edited(C, obedit, FO_SELCHANGE);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void FONT_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select All";
- ot->description = "Select all text";
- ot->idname = "FONT_OT_select_all";
+ /* identifiers */
+ ot->name = "Select All";
+ ot->description = "Select all text";
+ ot->idname = "FONT_OT_select_all";
- /* api callbacks */
- ot->exec = font_select_all_exec;
- ot->poll = ED_operator_editfont;
+ /* api callbacks */
+ ot->exec = font_select_all_exec;
+ ot->poll = ED_operator_editfont;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/******************* copy text operator ********************/
static void copy_selection(Object *obedit)
{
- int selstart, selend;
-
- if (BKE_vfont_select_get(obedit, &selstart, &selend)) {
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
- char *buf = NULL;
- wchar_t *text_buf;
- size_t len_utf8;
-
- /* internal clipboard (for style) */
- BKE_vfont_clipboard_set(ef->textbuf + selstart, ef->textbufinfo + selstart, selend - selstart + 1);
- BKE_vfont_clipboard_get(&text_buf, NULL, &len_utf8, NULL);
-
- /* system clipboard */
- buf = MEM_mallocN(len_utf8 + 1, __func__);
- if (buf) {
- BLI_strncpy_wchar_as_utf8(buf, text_buf, len_utf8 + 1);
- WM_clipboard_text_set(buf, false);
- MEM_freeN(buf);
- }
- }
+ int selstart, selend;
+
+ if (BKE_vfont_select_get(obedit, &selstart, &selend)) {
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
+ char *buf = NULL;
+ wchar_t *text_buf;
+ size_t len_utf8;
+
+ /* internal clipboard (for style) */
+ BKE_vfont_clipboard_set(
+ ef->textbuf + selstart, ef->textbufinfo + selstart, selend - selstart + 1);
+ BKE_vfont_clipboard_get(&text_buf, NULL, &len_utf8, NULL);
+
+ /* system clipboard */
+ buf = MEM_mallocN(len_utf8 + 1, __func__);
+ if (buf) {
+ BLI_strncpy_wchar_as_utf8(buf, text_buf, len_utf8 + 1);
+ WM_clipboard_text_set(buf, false);
+ MEM_freeN(buf);
+ }
+ }
}
static int copy_text_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obedit = CTX_data_edit_object(C);
+ Object *obedit = CTX_data_edit_object(C);
- copy_selection(obedit);
+ copy_selection(obedit);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void FONT_OT_text_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Text";
- ot->description = "Copy selected text to clipboard";
- ot->idname = "FONT_OT_text_copy";
-
- /* api callbacks */
- ot->exec = copy_text_exec;
- ot->poll = ED_operator_editfont;
+ /* identifiers */
+ ot->name = "Copy Text";
+ ot->description = "Copy selected text to clipboard";
+ ot->idname = "FONT_OT_text_copy";
+
+ /* api callbacks */
+ ot->exec = copy_text_exec;
+ ot->poll = ED_operator_editfont;
}
/******************* cut text operator ********************/
static int cut_text_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obedit = CTX_data_edit_object(C);
- int selstart, selend;
+ Object *obedit = CTX_data_edit_object(C);
+ int selstart, selend;
- if (!BKE_vfont_select_get(obedit, &selstart, &selend)) {
- return OPERATOR_CANCELLED;
- }
+ if (!BKE_vfont_select_get(obedit, &selstart, &selend)) {
+ return OPERATOR_CANCELLED;
+ }
- copy_selection(obedit);
- kill_selection(obedit, 0);
+ copy_selection(obedit);
+ kill_selection(obedit, 0);
- text_update_edited(C, obedit, FO_EDIT);
+ text_update_edited(C, obedit, FO_EDIT);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void FONT_OT_text_cut(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Cut Text";
- ot->description = "Cut selected text to clipboard";
- ot->idname = "FONT_OT_text_cut";
+ /* identifiers */
+ ot->name = "Cut Text";
+ ot->description = "Cut selected text to clipboard";
+ ot->idname = "FONT_OT_text_cut";
- /* api callbacks */
- ot->exec = cut_text_exec;
- ot->poll = ED_operator_editfont;
+ /* api callbacks */
+ ot->exec = cut_text_exec;
+ ot->poll = ED_operator_editfont;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************* paste text operator ********************/
static bool paste_selection(Object *obedit, ReportList *reports)
{
- wchar_t *text_buf;
- CharInfo *info_buf;
- size_t len;
-
- BKE_vfont_clipboard_get(&text_buf, &info_buf, NULL, &len);
-
- if (font_paste_wchar(obedit, text_buf, len, info_buf)) {
- return true;
- }
- else {
- BKE_report(reports, RPT_WARNING, "Text too long");
- return false;
- }
+ wchar_t *text_buf;
+ CharInfo *info_buf;
+ size_t len;
+
+ BKE_vfont_clipboard_get(&text_buf, &info_buf, NULL, &len);
+
+ if (font_paste_wchar(obedit, text_buf, len, info_buf)) {
+ return true;
+ }
+ else {
+ BKE_report(reports, RPT_WARNING, "Text too long");
+ return false;
+ }
}
static int paste_text_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- int retval;
- size_t len_utf8;
- wchar_t *text_buf;
-
- /* Store both clipboards as utf8 for comparison,
- * Give priority to the internal 'vfont' clipboard with its 'CharInfo' text styles
- * as long as its synchronized with the systems clipboard. */
- struct {
- char *buf;
- int len;
- } clipboard_system = {NULL}, clipboard_vfont = {NULL};
-
- clipboard_system.buf = WM_clipboard_text_get(false, &clipboard_system.len);
-
- if (clipboard_system.buf == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- BKE_vfont_clipboard_get(&text_buf, NULL, &len_utf8, NULL);
-
- if (text_buf) {
- clipboard_vfont.buf = MEM_mallocN(len_utf8 + 1, __func__);
-
- if (clipboard_vfont.buf == NULL) {
- MEM_freeN(clipboard_system.buf);
- return OPERATOR_CANCELLED;
- }
-
- BLI_strncpy_wchar_as_utf8(clipboard_vfont.buf, text_buf, len_utf8 + 1);
- }
-
- if (clipboard_vfont.buf && STREQ(clipboard_vfont.buf, clipboard_system.buf)) {
- retval = paste_selection(obedit, op->reports) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
- }
- else {
- if ((clipboard_system.len <= MAXTEXT) &&
- font_paste_utf8(C, clipboard_system.buf, clipboard_system.len))
- {
- text_update_edited(C, obedit, FO_EDIT);
- retval = OPERATOR_FINISHED;
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Clipboard too long");
- retval = OPERATOR_CANCELLED;
- }
-
- /* free the existent clipboard buffer */
- BKE_vfont_clipboard_free();
- }
-
- if (retval != OPERATOR_CANCELLED) {
- text_update_edited(C, obedit, FO_EDIT);
- }
-
- /* cleanup */
- if (clipboard_vfont.buf) {
- MEM_freeN(clipboard_vfont.buf);
- }
-
- MEM_freeN(clipboard_system.buf);
-
- return retval;
+ Object *obedit = CTX_data_edit_object(C);
+ int retval;
+ size_t len_utf8;
+ wchar_t *text_buf;
+
+ /* Store both clipboards as utf8 for comparison,
+ * Give priority to the internal 'vfont' clipboard with its 'CharInfo' text styles
+ * as long as its synchronized with the systems clipboard. */
+ struct {
+ char *buf;
+ int len;
+ } clipboard_system = {NULL}, clipboard_vfont = {NULL};
+
+ clipboard_system.buf = WM_clipboard_text_get(false, &clipboard_system.len);
+
+ if (clipboard_system.buf == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_vfont_clipboard_get(&text_buf, NULL, &len_utf8, NULL);
+
+ if (text_buf) {
+ clipboard_vfont.buf = MEM_mallocN(len_utf8 + 1, __func__);
+
+ if (clipboard_vfont.buf == NULL) {
+ MEM_freeN(clipboard_system.buf);
+ return OPERATOR_CANCELLED;
+ }
+
+ BLI_strncpy_wchar_as_utf8(clipboard_vfont.buf, text_buf, len_utf8 + 1);
+ }
+
+ if (clipboard_vfont.buf && STREQ(clipboard_vfont.buf, clipboard_system.buf)) {
+ retval = paste_selection(obedit, op->reports) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ }
+ else {
+ if ((clipboard_system.len <= MAXTEXT) &&
+ font_paste_utf8(C, clipboard_system.buf, clipboard_system.len)) {
+ text_update_edited(C, obedit, FO_EDIT);
+ retval = OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Clipboard too long");
+ retval = OPERATOR_CANCELLED;
+ }
+
+ /* free the existent clipboard buffer */
+ BKE_vfont_clipboard_free();
+ }
+
+ if (retval != OPERATOR_CANCELLED) {
+ text_update_edited(C, obedit, FO_EDIT);
+ }
+
+ /* cleanup */
+ if (clipboard_vfont.buf) {
+ MEM_freeN(clipboard_vfont.buf);
+ }
+
+ MEM_freeN(clipboard_system.buf);
+
+ return retval;
}
void FONT_OT_text_paste(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Paste Text";
- ot->description = "Paste text from clipboard";
- ot->idname = "FONT_OT_text_paste";
+ /* identifiers */
+ ot->name = "Paste Text";
+ ot->description = "Paste text from clipboard";
+ ot->idname = "FONT_OT_text_paste";
- /* api callbacks */
- ot->exec = paste_text_exec;
- ot->poll = ED_operator_editfont;
+ /* api callbacks */
+ ot->exec = paste_text_exec;
+ ot->poll = ED_operator_editfont;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************ move operator ************************/
static const EnumPropertyItem move_type_items[] = {
- {LINE_BEGIN, "LINE_BEGIN", 0, "Line Begin", ""},
- {LINE_END, "LINE_END", 0, "Line End", ""},
- {PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
- {NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
- {PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
- {NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
- {PREV_LINE, "PREVIOUS_LINE", 0, "Previous Line", ""},
- {NEXT_LINE, "NEXT_LINE", 0, "Next Line", ""},
- {PREV_PAGE, "PREVIOUS_PAGE", 0, "Previous Page", ""},
- {NEXT_PAGE, "NEXT_PAGE", 0, "Next Page", ""},
- {0, NULL, 0, NULL, NULL},
+ {LINE_BEGIN, "LINE_BEGIN", 0, "Line Begin", ""},
+ {LINE_END, "LINE_END", 0, "Line End", ""},
+ {PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
+ {NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
+ {PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
+ {NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
+ {PREV_LINE, "PREVIOUS_LINE", 0, "Previous Line", ""},
+ {NEXT_LINE, "NEXT_LINE", 0, "Next Line", ""},
+ {PREV_PAGE, "PREVIOUS_PAGE", 0, "Previous Page", ""},
+ {NEXT_PAGE, "NEXT_PAGE", 0, "Next Page", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int move_cursor(bContext *C, int type, const bool select)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
- int cursmove = -1;
-
- if ((select) && (ef->selstart == 0)) {
- ef->selstart = ef->selend = ef->pos + 1;
- }
-
- switch (type) {
- case LINE_BEGIN:
- while (ef->pos > 0) {
- if (ef->textbuf[ef->pos - 1] == '\n') {
- break;
- }
- if (ef->textbufinfo[ef->pos - 1].flag & CU_CHINFO_WRAP) {
- break;
- }
- ef->pos--;
- }
- cursmove = FO_CURS;
- break;
-
- case LINE_END:
- while (ef->pos < ef->len) {
- if (ef->textbuf[ef->pos] == 0) {
- break;
- }
- if (ef->textbuf[ef->pos] == '\n') {
- break;
- }
- if (ef->textbufinfo[ef->pos].flag & CU_CHINFO_WRAP) {
- break;
- }
- ef->pos++;
- }
- cursmove = FO_CURS;
- break;
-
- case PREV_WORD:
- {
- int pos = ef->pos;
- BLI_str_cursor_step_wchar(ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
- ef->pos = pos;
- cursmove = FO_CURS;
- break;
- }
-
- case NEXT_WORD:
- {
- int pos = ef->pos;
- BLI_str_cursor_step_wchar(ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
- ef->pos = pos;
- cursmove = FO_CURS;
- break;
- }
-
- case PREV_CHAR:
- ef->pos--;
- cursmove = FO_CURS;
- break;
-
- case NEXT_CHAR:
- ef->pos++;
- cursmove = FO_CURS;
-
- break;
-
- case PREV_LINE:
- cursmove = FO_CURSUP;
- break;
-
- case NEXT_LINE:
- cursmove = FO_CURSDOWN;
- break;
-
- case PREV_PAGE:
- cursmove = FO_PAGEUP;
- break;
-
- case NEXT_PAGE:
- cursmove = FO_PAGEDOWN;
- break;
- }
-
- if (cursmove == -1) {
- return OPERATOR_CANCELLED;
- }
-
- if (ef->pos > ef->len) { ef->pos = ef->len; }
- else if (ef->pos >= MAXTEXT) { ef->pos = MAXTEXT; }
- else if (ef->pos < 0) { ef->pos = 0; }
-
- /* apply vertical cursor motion to position immediately
- * otherwise the selection will lag behind */
- if (FO_CURS_IS_MOTION(cursmove)) {
- BKE_vfont_to_curve(DEG_get_evaluated_object(depsgraph, obedit), cursmove);
- cursmove = FO_CURS;
- }
-
- if (select == 0) {
- if (ef->selstart) {
- ef->selstart = ef->selend = 0;
- BKE_vfont_to_curve(DEG_get_evaluated_object(depsgraph, obedit), FO_SELCHANGE);
- }
- }
-
- if (select) {
- ef->selend = ef->pos;
- }
-
- text_update_edited(C, obedit, cursmove);
-
- return OPERATOR_FINISHED;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
+ int cursmove = -1;
+
+ if ((select) && (ef->selstart == 0)) {
+ ef->selstart = ef->selend = ef->pos + 1;
+ }
+
+ switch (type) {
+ case LINE_BEGIN:
+ while (ef->pos > 0) {
+ if (ef->textbuf[ef->pos - 1] == '\n') {
+ break;
+ }
+ if (ef->textbufinfo[ef->pos - 1].flag & CU_CHINFO_WRAP) {
+ break;
+ }
+ ef->pos--;
+ }
+ cursmove = FO_CURS;
+ break;
+
+ case LINE_END:
+ while (ef->pos < ef->len) {
+ if (ef->textbuf[ef->pos] == 0) {
+ break;
+ }
+ if (ef->textbuf[ef->pos] == '\n') {
+ break;
+ }
+ if (ef->textbufinfo[ef->pos].flag & CU_CHINFO_WRAP) {
+ break;
+ }
+ ef->pos++;
+ }
+ cursmove = FO_CURS;
+ break;
+
+ case PREV_WORD: {
+ int pos = ef->pos;
+ BLI_str_cursor_step_wchar(
+ ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
+ ef->pos = pos;
+ cursmove = FO_CURS;
+ break;
+ }
+
+ case NEXT_WORD: {
+ int pos = ef->pos;
+ BLI_str_cursor_step_wchar(
+ ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
+ ef->pos = pos;
+ cursmove = FO_CURS;
+ break;
+ }
+
+ case PREV_CHAR:
+ ef->pos--;
+ cursmove = FO_CURS;
+ break;
+
+ case NEXT_CHAR:
+ ef->pos++;
+ cursmove = FO_CURS;
+
+ break;
+
+ case PREV_LINE:
+ cursmove = FO_CURSUP;
+ break;
+
+ case NEXT_LINE:
+ cursmove = FO_CURSDOWN;
+ break;
+
+ case PREV_PAGE:
+ cursmove = FO_PAGEUP;
+ break;
+
+ case NEXT_PAGE:
+ cursmove = FO_PAGEDOWN;
+ break;
+ }
+
+ if (cursmove == -1) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (ef->pos > ef->len) {
+ ef->pos = ef->len;
+ }
+ else if (ef->pos >= MAXTEXT) {
+ ef->pos = MAXTEXT;
+ }
+ else if (ef->pos < 0) {
+ ef->pos = 0;
+ }
+
+ /* apply vertical cursor motion to position immediately
+ * otherwise the selection will lag behind */
+ if (FO_CURS_IS_MOTION(cursmove)) {
+ BKE_vfont_to_curve(DEG_get_evaluated_object(depsgraph, obedit), cursmove);
+ cursmove = FO_CURS;
+ }
+
+ if (select == 0) {
+ if (ef->selstart) {
+ ef->selstart = ef->selend = 0;
+ BKE_vfont_to_curve(DEG_get_evaluated_object(depsgraph, obedit), FO_SELCHANGE);
+ }
+ }
+
+ if (select) {
+ ef->selend = ef->pos;
+ }
+
+ text_update_edited(C, obedit, cursmove);
+
+ return OPERATOR_FINISHED;
}
static int move_exec(bContext *C, wmOperator *op)
{
- int type = RNA_enum_get(op->ptr, "type");
+ int type = RNA_enum_get(op->ptr, "type");
- return move_cursor(C, type, false);
+ return move_cursor(C, type, false);
}
void FONT_OT_move(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move Cursor";
- ot->description = "Move cursor to position type";
- ot->idname = "FONT_OT_move";
+ /* identifiers */
+ ot->name = "Move Cursor";
+ ot->description = "Move cursor to position type";
+ ot->idname = "FONT_OT_move";
- /* api callbacks */
- ot->exec = move_exec;
- ot->poll = ED_operator_editfont;
+ /* api callbacks */
+ ot->exec = move_exec;
+ ot->poll = ED_operator_editfont;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to");
+ /* properties */
+ RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to");
}
/******************* move select operator ********************/
static int move_select_exec(bContext *C, wmOperator *op)
{
- int type = RNA_enum_get(op->ptr, "type");
+ int type = RNA_enum_get(op->ptr, "type");
- return move_cursor(C, type, true);
+ return move_cursor(C, type, true);
}
void FONT_OT_move_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move Select";
- ot->description = "Move the cursor while selecting";
- ot->idname = "FONT_OT_move_select";
-
- /* api callbacks */
- ot->exec = move_select_exec;
- ot->poll = ED_operator_editfont;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to, to make a selection");
+ /* identifiers */
+ ot->name = "Move Select";
+ ot->description = "Move the cursor while selecting";
+ ot->idname = "FONT_OT_move_select";
+
+ /* api callbacks */
+ ot->exec = move_select_exec;
+ ot->poll = ED_operator_editfont;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna,
+ "type",
+ move_type_items,
+ LINE_BEGIN,
+ "Type",
+ "Where to move cursor to, to make a selection");
}
/************************* change spacing **********************/
static int change_spacing_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
- int kern, delta = RNA_int_get(op->ptr, "delta");
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
+ int kern, delta = RNA_int_get(op->ptr, "delta");
- kern = ef->textbufinfo[ef->pos - 1].kern;
- kern += delta;
- CLAMP(kern, -20, 20);
+ kern = ef->textbufinfo[ef->pos - 1].kern;
+ kern += delta;
+ CLAMP(kern, -20, 20);
- if (ef->textbufinfo[ef->pos - 1].kern == kern) {
- return OPERATOR_CANCELLED;
- }
+ if (ef->textbufinfo[ef->pos - 1].kern == kern) {
+ return OPERATOR_CANCELLED;
+ }
- ef->textbufinfo[ef->pos - 1].kern = kern;
+ ef->textbufinfo[ef->pos - 1].kern = kern;
- text_update_edited(C, obedit, FO_EDIT);
+ text_update_edited(C, obedit, FO_EDIT);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void FONT_OT_change_spacing(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Change Spacing";
- ot->description = "Change font spacing";
- ot->idname = "FONT_OT_change_spacing";
-
- /* api callbacks */
- ot->exec = change_spacing_exec;
- ot->poll = ED_operator_editfont;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_int(ot->srna, "delta", 1, -20, 20, "Delta", "Amount to decrease or increase character spacing with", -20, 20);
+ /* identifiers */
+ ot->name = "Change Spacing";
+ ot->description = "Change font spacing";
+ ot->idname = "FONT_OT_change_spacing";
+
+ /* api callbacks */
+ ot->exec = change_spacing_exec;
+ ot->poll = ED_operator_editfont;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna,
+ "delta",
+ 1,
+ -20,
+ 20,
+ "Delta",
+ "Amount to decrease or increase character spacing with",
+ -20,
+ 20);
}
/************************* change character **********************/
static int change_character_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
- int character, delta = RNA_int_get(op->ptr, "delta");
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
+ int character, delta = RNA_int_get(op->ptr, "delta");
- if (ef->pos <= 0) {
- return OPERATOR_CANCELLED;
- }
+ if (ef->pos <= 0) {
+ return OPERATOR_CANCELLED;
+ }
- character = ef->textbuf[ef->pos - 1];
- character += delta;
- CLAMP(character, 0, 255);
+ character = ef->textbuf[ef->pos - 1];
+ character += delta;
+ CLAMP(character, 0, 255);
- if (character == ef->textbuf[ef->pos - 1]) {
- return OPERATOR_CANCELLED;
- }
+ if (character == ef->textbuf[ef->pos - 1]) {
+ return OPERATOR_CANCELLED;
+ }
- ef->textbuf[ef->pos - 1] = character;
+ ef->textbuf[ef->pos - 1] = character;
- text_update_edited(C, obedit, FO_EDIT);
+ text_update_edited(C, obedit, FO_EDIT);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void FONT_OT_change_character(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Change Character";
- ot->description = "Change font character code";
- ot->idname = "FONT_OT_change_character";
-
- /* api callbacks */
- ot->exec = change_character_exec;
- ot->poll = ED_operator_editfont;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_int(ot->srna, "delta", 1, -255, 255, "Delta", "Number to increase or decrease character code with", -255, 255);
+ /* identifiers */
+ ot->name = "Change Character";
+ ot->description = "Change font character code";
+ ot->idname = "FONT_OT_change_character";
+
+ /* api callbacks */
+ ot->exec = change_character_exec;
+ ot->poll = ED_operator_editfont;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna,
+ "delta",
+ 1,
+ -255,
+ 255,
+ "Delta",
+ "Number to increase or decrease character code with",
+ -255,
+ 255);
}
/******************* line break operator ********************/
static int line_break_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
- insert_into_textbuf(obedit, '\n');
+ insert_into_textbuf(obedit, '\n');
- ef->selstart = ef->selend = 0;
+ ef->selstart = ef->selend = 0;
- text_update_edited(C, obedit, FO_EDIT);
+ text_update_edited(C, obedit, FO_EDIT);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void FONT_OT_line_break(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Line Break";
- ot->description = "Insert line break at cursor position";
- ot->idname = "FONT_OT_line_break";
+ /* identifiers */
+ ot->name = "Line Break";
+ ot->description = "Insert line break at cursor position";
+ ot->idname = "FONT_OT_line_break";
- /* api callbacks */
- ot->exec = line_break_exec;
- ot->poll = ED_operator_editfont;
+ /* api callbacks */
+ ot->exec = line_break_exec;
+ ot->poll = ED_operator_editfont;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************* delete operator **********************/
static const EnumPropertyItem delete_type_items[] = {
- {DEL_NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
- {DEL_PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
- {DEL_NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
- {DEL_PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
- {DEL_SELECTION, "SELECTION", 0, "Selection", ""},
- {DEL_NEXT_SEL, "NEXT_OR_SELECTION", 0, "Next or Selection", ""},
- {DEL_PREV_SEL, "PREVIOUS_OR_SELECTION", 0, "Previous or Selection", ""},
- {0, NULL, 0, NULL, NULL},
+ {DEL_NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
+ {DEL_PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
+ {DEL_NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
+ {DEL_PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
+ {DEL_SELECTION, "SELECTION", 0, "Selection", ""},
+ {DEL_NEXT_SEL, "NEXT_OR_SELECTION", 0, "Next or Selection", ""},
+ {DEL_PREV_SEL, "PREVIOUS_OR_SELECTION", 0, "Previous or Selection", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int delete_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
- int selstart, selend, type = RNA_enum_get(op->ptr, "type");
- int range[2] = {0, 0};
- bool has_select = false;
-
- if (ef->len == 0) {
- return OPERATOR_CANCELLED;
- }
-
- if (BKE_vfont_select_get(obedit, &selstart, &selend)) {
- if (type == DEL_NEXT_SEL) {
- type = DEL_SELECTION;
- }
- else if (type == DEL_PREV_SEL) {
- type = DEL_SELECTION;
- }
- has_select = true;
- }
- else {
- if (type == DEL_NEXT_SEL) {
- type = DEL_NEXT_CHAR;
- }
- else if (type == DEL_PREV_SEL) {
- type = DEL_PREV_CHAR;
- }
- }
-
- switch (type) {
- case DEL_SELECTION:
- if (!kill_selection(obedit, 0)) {
- return OPERATOR_CANCELLED;
- }
- break;
- case DEL_PREV_CHAR:
- if (ef->pos <= 0) {
- return OPERATOR_CANCELLED;
- }
-
- range[0] = ef->pos - 1;
- range[1] = ef->pos;
-
- ef->pos--;
- break;
- case DEL_NEXT_CHAR:
- if (ef->pos >= ef->len) {
- return OPERATOR_CANCELLED;
- }
-
- range[0] = ef->pos;
- range[1] = ef->pos + 1;
- break;
- case DEL_NEXT_WORD:
- {
- int pos = ef->pos;
- BLI_str_cursor_step_wchar(ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
- range[0] = ef->pos;
- range[1] = pos;
- break;
- }
-
- case DEL_PREV_WORD:
- {
- int pos = ef->pos;
- BLI_str_cursor_step_wchar(ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
- range[0] = pos;
- range[1] = ef->pos;
- ef->pos = pos;
- break;
- }
- default:
- return OPERATOR_CANCELLED;
- }
-
- if (range[0] != range[1]) {
- BLI_assert(range[0] < range[1]);
- int len_remove = range[1] - range[0];
- int len_tail = ef->len - range[1];
- if (has_select) {
- for (int i = 0; i < 2; i++) {
- int *sel = i ? &ef->selend : &ef->selstart;
- if (*sel <= range[0]) {
- /* pass */
- }
- else if (*sel >= range[1]) {
- *sel -= len_remove;
- }
- else if (*sel < range[1]) {
- /* pass */
- *sel = range[0];
- }
- }
- }
-
- memmove(&ef->textbuf[range[0]], &ef->textbuf[range[1]], sizeof(*ef->textbuf) * len_tail);
- memmove(&ef->textbufinfo[range[0]], &ef->textbufinfo[range[1]], sizeof(*ef->textbufinfo) * len_tail);
-
- ef->len -= len_remove;
- ef->textbuf[ef->len] = '\0';
-
- BKE_vfont_select_clamp(obedit);
- }
-
- text_update_edited(C, obedit, FO_EDIT);
-
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
+ int selstart, selend, type = RNA_enum_get(op->ptr, "type");
+ int range[2] = {0, 0};
+ bool has_select = false;
+
+ if (ef->len == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (BKE_vfont_select_get(obedit, &selstart, &selend)) {
+ if (type == DEL_NEXT_SEL) {
+ type = DEL_SELECTION;
+ }
+ else if (type == DEL_PREV_SEL) {
+ type = DEL_SELECTION;
+ }
+ has_select = true;
+ }
+ else {
+ if (type == DEL_NEXT_SEL) {
+ type = DEL_NEXT_CHAR;
+ }
+ else if (type == DEL_PREV_SEL) {
+ type = DEL_PREV_CHAR;
+ }
+ }
+
+ switch (type) {
+ case DEL_SELECTION:
+ if (!kill_selection(obedit, 0)) {
+ return OPERATOR_CANCELLED;
+ }
+ break;
+ case DEL_PREV_CHAR:
+ if (ef->pos <= 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ range[0] = ef->pos - 1;
+ range[1] = ef->pos;
+
+ ef->pos--;
+ break;
+ case DEL_NEXT_CHAR:
+ if (ef->pos >= ef->len) {
+ return OPERATOR_CANCELLED;
+ }
+
+ range[0] = ef->pos;
+ range[1] = ef->pos + 1;
+ break;
+ case DEL_NEXT_WORD: {
+ int pos = ef->pos;
+ BLI_str_cursor_step_wchar(
+ ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
+ range[0] = ef->pos;
+ range[1] = pos;
+ break;
+ }
+
+ case DEL_PREV_WORD: {
+ int pos = ef->pos;
+ BLI_str_cursor_step_wchar(
+ ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
+ range[0] = pos;
+ range[1] = ef->pos;
+ ef->pos = pos;
+ break;
+ }
+ default:
+ return OPERATOR_CANCELLED;
+ }
+
+ if (range[0] != range[1]) {
+ BLI_assert(range[0] < range[1]);
+ int len_remove = range[1] - range[0];
+ int len_tail = ef->len - range[1];
+ if (has_select) {
+ for (int i = 0; i < 2; i++) {
+ int *sel = i ? &ef->selend : &ef->selstart;
+ if (*sel <= range[0]) {
+ /* pass */
+ }
+ else if (*sel >= range[1]) {
+ *sel -= len_remove;
+ }
+ else if (*sel < range[1]) {
+ /* pass */
+ *sel = range[0];
+ }
+ }
+ }
+
+ memmove(&ef->textbuf[range[0]], &ef->textbuf[range[1]], sizeof(*ef->textbuf) * len_tail);
+ memmove(&ef->textbufinfo[range[0]],
+ &ef->textbufinfo[range[1]],
+ sizeof(*ef->textbufinfo) * len_tail);
+
+ ef->len -= len_remove;
+ ef->textbuf[ef->len] = '\0';
+
+ BKE_vfont_select_clamp(obedit);
+ }
+
+ text_update_edited(C, obedit, FO_EDIT);
+
+ return OPERATOR_FINISHED;
}
void FONT_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete";
- ot->description = "Delete text by cursor position";
- ot->idname = "FONT_OT_delete";
-
- /* api callbacks */
- ot->exec = delete_exec;
- ot->poll = ED_operator_editfont;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "type", delete_type_items, DEL_PREV_CHAR, "Type", "Which part of the text to delete");
+ /* identifiers */
+ ot->name = "Delete";
+ ot->description = "Delete text by cursor position";
+ ot->idname = "FONT_OT_delete";
+
+ /* api callbacks */
+ ot->exec = delete_exec;
+ ot->poll = ED_operator_editfont;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna,
+ "type",
+ delete_type_items,
+ DEL_PREV_CHAR,
+ "Type",
+ "Which part of the text to delete");
}
/*********************** insert text operator *************************/
static int insert_text_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- char *inserted_utf8;
- wchar_t *inserted_text;
- int a, len;
+ Object *obedit = CTX_data_edit_object(C);
+ char *inserted_utf8;
+ wchar_t *inserted_text;
+ int a, len;
- if (!RNA_struct_property_is_set(op->ptr, "text")) {
- return OPERATOR_CANCELLED;
- }
+ if (!RNA_struct_property_is_set(op->ptr, "text")) {
+ return OPERATOR_CANCELLED;
+ }
- inserted_utf8 = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
- len = BLI_strlen_utf8(inserted_utf8);
+ inserted_utf8 = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
+ len = BLI_strlen_utf8(inserted_utf8);
- inserted_text = MEM_callocN(sizeof(wchar_t) * (len + 1), "FONT_insert_text");
- BLI_strncpy_wchar_from_utf8(inserted_text, inserted_utf8, len + 1);
+ inserted_text = MEM_callocN(sizeof(wchar_t) * (len + 1), "FONT_insert_text");
+ BLI_strncpy_wchar_from_utf8(inserted_text, inserted_utf8, len + 1);
- for (a = 0; a < len; a++) {
- insert_into_textbuf(obedit, inserted_text[a]);
- }
+ for (a = 0; a < len; a++) {
+ insert_into_textbuf(obedit, inserted_text[a]);
+ }
- MEM_freeN(inserted_text);
- MEM_freeN(inserted_utf8);
+ MEM_freeN(inserted_text);
+ MEM_freeN(inserted_utf8);
- kill_selection(obedit, 1);
- text_update_edited(C, obedit, FO_EDIT);
+ kill_selection(obedit, 1);
+ text_update_edited(C, obedit, FO_EDIT);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
- static int accentcode = 0;
- uintptr_t ascii = event->ascii;
- int alt = event->alt, shift = event->shift, ctrl = event->ctrl;
- int event_type = event->type, event_val = event->val;
- wchar_t inserted_text[2] = {0};
-
- if (RNA_struct_property_is_set(op->ptr, "text")) {
- return insert_text_exec(C, op);
- }
-
- if (RNA_struct_property_is_set(op->ptr, "accent")) {
- if (ef->len != 0 && ef->pos > 0) {
- accentcode = 1;
- }
- return OPERATOR_FINISHED;
- }
-
- /* tab should exit editmode, but we allow it to be typed using modifier keys */
- if (event_type == TABKEY) {
- if ((alt || ctrl || shift) == 0) {
- return OPERATOR_PASS_THROUGH;
- }
- else {
- ascii = 9;
- }
- }
-
- if (event_type == BACKSPACEKEY) {
- if (alt && ef->len != 0 && ef->pos > 0) {
- accentcode = 1;
- }
- return OPERATOR_PASS_THROUGH;
- }
-
- if (event_val && (ascii || event->utf8_buf[0])) {
- /* handle case like TAB (== 9) */
- if ( (ascii > 31 && ascii < 254 && ascii != 127) ||
- (ascii == 13) ||
- (ascii == 10) ||
- (ascii == 8) ||
- (event->utf8_buf[0]))
- {
-
- if (accentcode) {
- if (ef->pos > 0) {
- inserted_text[0] = findaccent(ef->textbuf[ef->pos - 1], ascii);
- ef->textbuf[ef->pos - 1] = inserted_text[0];
- }
- accentcode = 0;
- }
- else if (event->utf8_buf[0]) {
- inserted_text[0] = BLI_str_utf8_as_unicode(event->utf8_buf);
- ascii = inserted_text[0];
- insert_into_textbuf(obedit, ascii);
- accentcode = 0;
- }
- else if (ascii) {
- insert_into_textbuf(obedit, ascii);
- accentcode = 0;
- }
- else {
- BLI_assert(0);
- }
-
- kill_selection(obedit, 1);
- text_update_edited(C, obedit, FO_EDIT);
- }
- else {
- inserted_text[0] = ascii;
- insert_into_textbuf(obedit, ascii);
- text_update_edited(C, obedit, FO_EDIT);
- }
- }
- else {
- return OPERATOR_PASS_THROUGH;
- }
-
- if (inserted_text[0]) {
- /* store as utf8 in RNA string */
- char inserted_utf8[8] = {0};
-
- BLI_strncpy_wchar_as_utf8(inserted_utf8, inserted_text, sizeof(inserted_utf8));
- RNA_string_set(op->ptr, "text", inserted_utf8);
- }
-
- /* reset property? */
- if (event_val == 0) {
- accentcode = 0;
- }
-
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
+ static int accentcode = 0;
+ uintptr_t ascii = event->ascii;
+ int alt = event->alt, shift = event->shift, ctrl = event->ctrl;
+ int event_type = event->type, event_val = event->val;
+ wchar_t inserted_text[2] = {0};
+
+ if (RNA_struct_property_is_set(op->ptr, "text")) {
+ return insert_text_exec(C, op);
+ }
+
+ if (RNA_struct_property_is_set(op->ptr, "accent")) {
+ if (ef->len != 0 && ef->pos > 0) {
+ accentcode = 1;
+ }
+ return OPERATOR_FINISHED;
+ }
+
+ /* tab should exit editmode, but we allow it to be typed using modifier keys */
+ if (event_type == TABKEY) {
+ if ((alt || ctrl || shift) == 0) {
+ return OPERATOR_PASS_THROUGH;
+ }
+ else {
+ ascii = 9;
+ }
+ }
+
+ if (event_type == BACKSPACEKEY) {
+ if (alt && ef->len != 0 && ef->pos > 0) {
+ accentcode = 1;
+ }
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ if (event_val && (ascii || event->utf8_buf[0])) {
+ /* handle case like TAB (== 9) */
+ if ((ascii > 31 && ascii < 254 && ascii != 127) || (ascii == 13) || (ascii == 10) ||
+ (ascii == 8) || (event->utf8_buf[0])) {
+
+ if (accentcode) {
+ if (ef->pos > 0) {
+ inserted_text[0] = findaccent(ef->textbuf[ef->pos - 1], ascii);
+ ef->textbuf[ef->pos - 1] = inserted_text[0];
+ }
+ accentcode = 0;
+ }
+ else if (event->utf8_buf[0]) {
+ inserted_text[0] = BLI_str_utf8_as_unicode(event->utf8_buf);
+ ascii = inserted_text[0];
+ insert_into_textbuf(obedit, ascii);
+ accentcode = 0;
+ }
+ else if (ascii) {
+ insert_into_textbuf(obedit, ascii);
+ accentcode = 0;
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ kill_selection(obedit, 1);
+ text_update_edited(C, obedit, FO_EDIT);
+ }
+ else {
+ inserted_text[0] = ascii;
+ insert_into_textbuf(obedit, ascii);
+ text_update_edited(C, obedit, FO_EDIT);
+ }
+ }
+ else {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ if (inserted_text[0]) {
+ /* store as utf8 in RNA string */
+ char inserted_utf8[8] = {0};
+
+ BLI_strncpy_wchar_as_utf8(inserted_utf8, inserted_text, sizeof(inserted_utf8));
+ RNA_string_set(op->ptr, "text", inserted_utf8);
+ }
+
+ /* reset property? */
+ if (event_val == 0) {
+ accentcode = 0;
+ }
+
+ return OPERATOR_FINISHED;
}
void FONT_OT_text_insert(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Insert Text";
- ot->description = "Insert text at cursor position";
- ot->idname = "FONT_OT_text_insert";
-
- /* api callbacks */
- ot->exec = insert_text_exec;
- ot->invoke = insert_text_invoke;
- ot->poll = ED_operator_editfont;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- RNA_def_string(ot->srna, "text", NULL, 0, "Text", "Text to insert at the cursor position");
- RNA_def_boolean(ot->srna, "accent", 0, "Accent mode", "Next typed character will strike through previous, for special character input");
+ /* identifiers */
+ ot->name = "Insert Text";
+ ot->description = "Insert text at cursor position";
+ ot->idname = "FONT_OT_text_insert";
+
+ /* api callbacks */
+ ot->exec = insert_text_exec;
+ ot->invoke = insert_text_invoke;
+ ot->poll = ED_operator_editfont;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_string(ot->srna, "text", NULL, 0, "Text", "Text to insert at the cursor position");
+ RNA_def_boolean(
+ ot->srna,
+ "accent",
+ 0,
+ "Accent mode",
+ "Next typed character will strike through previous, for special character input");
}
-
/*********************** textbox add operator *************************/
static int textbox_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obedit = CTX_data_active_object(C);
- Curve *cu = obedit->data;
- int i;
-
- if (cu->totbox < 256) {
- for (i = cu->totbox; i > cu->actbox; i--) {
- cu->tb[i] = cu->tb[i - 1];
- }
- cu->tb[cu->actbox] = cu->tb[cu->actbox - 1];
- cu->actbox++;
- cu->totbox++;
- }
-
- DEG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_active_object(C);
+ Curve *cu = obedit->data;
+ int i;
+
+ if (cu->totbox < 256) {
+ for (i = cu->totbox; i > cu->actbox; i--) {
+ cu->tb[i] = cu->tb[i - 1];
+ }
+ cu->tb[cu->actbox] = cu->tb[cu->actbox - 1];
+ cu->actbox++;
+ cu->totbox++;
+ }
+
+ DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ return OPERATOR_FINISHED;
}
void FONT_OT_textbox_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Textbox";
- ot->description = "Add a new text box";
- ot->idname = "FONT_OT_textbox_add";
-
- /* api callbacks */
- ot->exec = textbox_add_exec;
- ot->poll = ED_operator_object_active_editable_font;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Add Textbox";
+ ot->description = "Add a new text box";
+ ot->idname = "FONT_OT_textbox_add";
+ /* api callbacks */
+ ot->exec = textbox_add_exec;
+ ot->poll = ED_operator_object_active_editable_font;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
-
/*********************** textbox remove operator *************************/
-
-
static int textbox_remove_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_active_object(C);
- Curve *cu = obedit->data;
- int i;
- int index = RNA_int_get(op->ptr, "index");
-
-
- if (cu->totbox > 1) {
- for (i = index; i < cu->totbox; i++) {
- cu->tb[i] = cu->tb[i + 1];
- }
- cu->totbox--;
- if (cu->actbox >= index) {
- cu->actbox--;
- }
- }
-
- DEG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_active_object(C);
+ Curve *cu = obedit->data;
+ int i;
+ int index = RNA_int_get(op->ptr, "index");
+
+ if (cu->totbox > 1) {
+ for (i = index; i < cu->totbox; i++) {
+ cu->tb[i] = cu->tb[i + 1];
+ }
+ cu->totbox--;
+ if (cu->actbox >= index) {
+ cu->actbox--;
+ }
+ }
+
+ DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
}
void FONT_OT_textbox_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Textbox";
- ot->description = "Remove the textbox";
- ot->idname = "FONT_OT_textbox_remove";
+ /* identifiers */
+ ot->name = "Remove Textbox";
+ ot->description = "Remove the textbox";
+ ot->idname = "FONT_OT_textbox_remove";
- /* api callbacks */
- ot->exec = textbox_remove_exec;
- ot->poll = ED_operator_object_active_editable_font;
+ /* api callbacks */
+ ot->exec = textbox_remove_exec;
+ ot->poll = ED_operator_object_active_editable_font;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "The current text box", 0, INT_MAX);
+ RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "The current text box", 0, INT_MAX);
}
-
-
/***************** editmode enter/exit ********************/
void ED_curve_editfont_make(Object *obedit)
{
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
- int len_wchar;
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
+ int len_wchar;
- if (ef == NULL) {
- ef = cu->editfont = MEM_callocN(sizeof(EditFont), "editfont");
+ if (ef == NULL) {
+ ef = cu->editfont = MEM_callocN(sizeof(EditFont), "editfont");
- ef->textbuf = MEM_callocN((MAXTEXT + 4) * sizeof(wchar_t), "texteditbuf");
- ef->textbufinfo = MEM_callocN((MAXTEXT + 4) * sizeof(CharInfo), "texteditbufinfo");
- }
+ ef->textbuf = MEM_callocN((MAXTEXT + 4) * sizeof(wchar_t), "texteditbuf");
+ ef->textbufinfo = MEM_callocN((MAXTEXT + 4) * sizeof(CharInfo), "texteditbufinfo");
+ }
- /* Convert the original text to wchar_t */
- len_wchar = BLI_strncpy_wchar_from_utf8(ef->textbuf, cu->str, MAXTEXT + 4);
- BLI_assert(len_wchar == cu->len_wchar);
- ef->len = len_wchar;
- BLI_assert(ef->len >= 0);
+ /* Convert the original text to wchar_t */
+ len_wchar = BLI_strncpy_wchar_from_utf8(ef->textbuf, cu->str, MAXTEXT + 4);
+ BLI_assert(len_wchar == cu->len_wchar);
+ ef->len = len_wchar;
+ BLI_assert(ef->len >= 0);
- memcpy(ef->textbufinfo, cu->strinfo, ef->len * sizeof(CharInfo));
+ memcpy(ef->textbufinfo, cu->strinfo, ef->len * sizeof(CharInfo));
- if (ef->pos > ef->len) {
- ef->pos = ef->len;
- }
+ if (ef->pos > ef->len) {
+ ef->pos = ef->len;
+ }
- cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0];
+ cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0];
- /* Other vars */
- ef->pos = cu->pos;
- ef->selstart = cu->selstart;
- ef->selend = cu->selend;
+ /* Other vars */
+ ef->pos = cu->pos;
+ ef->selstart = cu->selstart;
+ ef->selend = cu->selend;
- /* text may have been modified by Python */
- BKE_vfont_select_clamp(obedit);
+ /* text may have been modified by Python */
+ BKE_vfont_select_clamp(obedit);
}
void ED_curve_editfont_load(Object *obedit)
{
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
- /* Free the old curve string */
- MEM_freeN(cu->str);
+ /* Free the old curve string */
+ MEM_freeN(cu->str);
- /* Calculate the actual string length in UTF-8 variable characters */
- cu->len_wchar = ef->len;
- cu->len = BLI_wstrlen_utf8(ef->textbuf);
+ /* Calculate the actual string length in UTF-8 variable characters */
+ cu->len_wchar = ef->len;
+ cu->len = BLI_wstrlen_utf8(ef->textbuf);
- /* Alloc memory for UTF-8 variable char length string */
- cu->str = MEM_mallocN(cu->len + sizeof(wchar_t), "str");
+ /* Alloc memory for UTF-8 variable char length string */
+ cu->str = MEM_mallocN(cu->len + sizeof(wchar_t), "str");
- /* Copy the wchar to UTF-8 */
- BLI_strncpy_wchar_as_utf8(cu->str, ef->textbuf, cu->len + 1);
+ /* Copy the wchar to UTF-8 */
+ BLI_strncpy_wchar_as_utf8(cu->str, ef->textbuf, cu->len + 1);
- if (cu->strinfo) {
- MEM_freeN(cu->strinfo);
- }
- cu->strinfo = MEM_callocN((cu->len_wchar + 4) * sizeof(CharInfo), "texteditinfo");
- memcpy(cu->strinfo, ef->textbufinfo, cu->len_wchar * sizeof(CharInfo));
+ if (cu->strinfo) {
+ MEM_freeN(cu->strinfo);
+ }
+ cu->strinfo = MEM_callocN((cu->len_wchar + 4) * sizeof(CharInfo), "texteditinfo");
+ memcpy(cu->strinfo, ef->textbufinfo, cu->len_wchar * sizeof(CharInfo));
- /* Other vars */
- cu->pos = ef->pos;
- cu->selstart = ef->selstart;
- cu->selend = ef->selend;
+ /* Other vars */
+ cu->pos = ef->pos;
+ cu->selstart = ef->selstart;
+ cu->selend = ef->selend;
}
void ED_curve_editfont_free(Object *obedit)
{
- BKE_curve_editfont_free((Curve *)obedit->data);
+ BKE_curve_editfont_free((Curve *)obedit->data);
}
/********************** set case operator *********************/
static const EnumPropertyItem case_items[] = {
- {CASE_LOWER, "LOWER", 0, "Lower", ""},
- {CASE_UPPER, "UPPER", 0, "Upper", ""},
- {0, NULL, 0, NULL, NULL},
+ {CASE_LOWER, "LOWER", 0, "Lower", ""},
+ {CASE_UPPER, "UPPER", 0, "Upper", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int set_case(bContext *C, int ccase)
{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
- wchar_t *str;
- int len;
- int selstart, selend;
-
- if (BKE_vfont_select_get(obedit, &selstart, &selend)) {
- len = (selend - selstart) + 1;
- str = &ef->textbuf[selstart];
- while (len) {
- if (*str >= 'a' && *str <= 'z') {
- *str -= 32;
- }
- len--;
- str++;
- }
-
- if (ccase == CASE_LOWER) {
- len = (selend - selstart) + 1;
- str = &ef->textbuf[selstart];
- while (len) {
- if (*str >= 'A' && *str <= 'Z') {
- *str += 32;
- }
- len--;
- str++;
- }
- }
-
- text_update_edited(C, obedit, FO_EDIT);
- }
-
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
+ wchar_t *str;
+ int len;
+ int selstart, selend;
+
+ if (BKE_vfont_select_get(obedit, &selstart, &selend)) {
+ len = (selend - selstart) + 1;
+ str = &ef->textbuf[selstart];
+ while (len) {
+ if (*str >= 'a' && *str <= 'z') {
+ *str -= 32;
+ }
+ len--;
+ str++;
+ }
+
+ if (ccase == CASE_LOWER) {
+ len = (selend - selstart) + 1;
+ str = &ef->textbuf[selstart];
+ while (len) {
+ if (*str >= 'A' && *str <= 'Z') {
+ *str += 32;
+ }
+ len--;
+ str++;
+ }
+ }
+
+ text_update_edited(C, obedit, FO_EDIT);
+ }
+
+ return OPERATOR_FINISHED;
}
static int set_case_exec(bContext *C, wmOperator *op)
{
- return set_case(C, RNA_enum_get(op->ptr, "case"));
+ return set_case(C, RNA_enum_get(op->ptr, "case"));
}
void FONT_OT_case_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Case";
- ot->description = "Set font case";
- ot->idname = "FONT_OT_case_set";
+ /* identifiers */
+ ot->name = "Set Case";
+ ot->description = "Set font case";
+ ot->idname = "FONT_OT_case_set";
- /* api callbacks */
- ot->exec = set_case_exec;
- ot->poll = ED_operator_editfont;
+ /* api callbacks */
+ ot->exec = set_case_exec;
+ ot->poll = ED_operator_editfont;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_enum(ot->srna, "case", case_items, CASE_LOWER, "Case", "Lower or upper case");
+ /* properties */
+ RNA_def_enum(ot->srna, "case", case_items, CASE_LOWER, "Case", "Lower or upper case");
}
/********************** toggle case operator *********************/
static int toggle_case_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
- wchar_t *str;
- int len, ccase = CASE_UPPER;
-
- len = wcslen(ef->textbuf);
- str = ef->textbuf;
- while (len) {
- if (*str >= 'a' && *str <= 'z') {
- ccase = CASE_LOWER;
- break;
- }
-
- len--;
- str++;
- }
-
- return set_case(C, ccase);
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
+ wchar_t *str;
+ int len, ccase = CASE_UPPER;
+
+ len = wcslen(ef->textbuf);
+ str = ef->textbuf;
+ while (len) {
+ if (*str >= 'a' && *str <= 'z') {
+ ccase = CASE_LOWER;
+ break;
+ }
+
+ len--;
+ str++;
+ }
+
+ return set_case(C, ccase);
}
void FONT_OT_case_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Case";
- ot->description = "Toggle font case";
- ot->idname = "FONT_OT_case_toggle";
+ /* identifiers */
+ ot->name = "Toggle Case";
+ ot->description = "Toggle font case";
+ ot->idname = "FONT_OT_case_toggle";
- /* api callbacks */
- ot->exec = toggle_case_exec;
- ot->poll = ED_operator_editfont;
+ /* api callbacks */
+ ot->exec = toggle_case_exec;
+ ot->poll = ED_operator_editfont;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* **************** Open Font ************** */
static void font_ui_template_init(bContext *C, wmOperator *op)
{
- PropertyPointerRNA *pprop;
+ PropertyPointerRNA *pprop;
- op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
- UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
+ op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
+ UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
}
static void font_open_cancel(bContext *UNUSED(C), wmOperator *op)
{
- MEM_freeN(op->customdata);
- op->customdata = NULL;
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
}
static int font_open_exec(bContext *C, wmOperator *op)
{
- struct Main *bmain = CTX_data_main(C);
- VFont *font;
- PropertyPointerRNA *pprop;
- PointerRNA idptr;
- char filepath[FILE_MAX];
- RNA_string_get(op->ptr, "filepath", filepath);
-
- font = BKE_vfont_load(bmain, filepath);
-
- if (!font) {
- if (op->customdata) {
- MEM_freeN(op->customdata);
- }
- return OPERATOR_CANCELLED;
- }
-
- if (!op->customdata) {
- font_ui_template_init(C, op);
- }
-
- /* hook into UI */
- pprop = op->customdata;
-
- if (pprop->prop) {
- /* when creating new ID blocks, use is already 1, but RNA
- * pointer use also increases user, so this compensates it */
- id_us_min(&font->id);
-
- RNA_id_pointer_create(&font->id, &idptr);
- RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
- RNA_property_update(C, &pprop->ptr, pprop->prop);
- }
-
- MEM_freeN(op->customdata);
-
- return OPERATOR_FINISHED;
+ struct Main *bmain = CTX_data_main(C);
+ VFont *font;
+ PropertyPointerRNA *pprop;
+ PointerRNA idptr;
+ char filepath[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filepath);
+
+ font = BKE_vfont_load(bmain, filepath);
+
+ if (!font) {
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ }
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!op->customdata) {
+ font_ui_template_init(C, op);
+ }
+
+ /* hook into UI */
+ pprop = op->customdata;
+
+ if (pprop->prop) {
+ /* when creating new ID blocks, use is already 1, but RNA
+ * pointer use also increases user, so this compensates it */
+ id_us_min(&font->id);
+
+ RNA_id_pointer_create(&font->id, &idptr);
+ RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
+ RNA_property_update(C, &pprop->ptr, pprop->prop);
+ }
+
+ MEM_freeN(op->customdata);
+
+ return OPERATOR_FINISHED;
}
static int open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- VFont *vfont = NULL;
- const char *path;
+ VFont *vfont = NULL;
+ const char *path;
- PointerRNA idptr;
- PropertyPointerRNA *pprop;
+ PointerRNA idptr;
+ PropertyPointerRNA *pprop;
- font_ui_template_init(C, op);
+ font_ui_template_init(C, op);
- /* hook into UI */
- pprop = op->customdata;
+ /* hook into UI */
+ pprop = op->customdata;
- if (pprop->prop) {
- idptr = RNA_property_pointer_get((PointerRNA *)pprop, pprop->prop);
- vfont = idptr.id.data;
- }
+ if (pprop->prop) {
+ idptr = RNA_property_pointer_get((PointerRNA *)pprop, pprop->prop);
+ vfont = idptr.id.data;
+ }
- path = (vfont && !BKE_vfont_is_builtin(vfont)) ? vfont->name : U.fontdir;
+ path = (vfont && !BKE_vfont_is_builtin(vfont)) ? vfont->name : U.fontdir;
- if (RNA_struct_property_is_set(op->ptr, "filepath")) {
- return font_open_exec(C, op);
- }
+ if (RNA_struct_property_is_set(op->ptr, "filepath")) {
+ return font_open_exec(C, op);
+ }
- RNA_string_set(op->ptr, "filepath", path);
- WM_event_add_fileselect(C, op);
+ RNA_string_set(op->ptr, "filepath", path);
+ WM_event_add_fileselect(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void FONT_OT_open(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Open Font";
- ot->idname = "FONT_OT_open";
- ot->description = "Load a new font from a file";
-
- /* api callbacks */
- ot->exec = font_open_exec;
- ot->invoke = open_invoke;
- ot->cancel = font_open_cancel;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_FTFONT, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+ /* identifiers */
+ ot->name = "Open Font";
+ ot->idname = "FONT_OT_open";
+ ot->description = "Load a new font from a file";
+
+ /* api callbacks */
+ ot->exec = font_open_exec;
+ ot->invoke = open_invoke;
+ ot->cancel = font_open_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_FTFONT,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
}
/******************* delete operator *********************/
static int font_unlink_exec(bContext *C, wmOperator *op)
{
- VFont *builtin_font;
+ VFont *builtin_font;
- PointerRNA idptr;
- PropertyPointerRNA pprop;
+ PointerRNA idptr;
+ PropertyPointerRNA pprop;
- UI_context_active_but_prop_get_templateID(C, &pprop.ptr, &pprop.prop);
+ UI_context_active_but_prop_get_templateID(C, &pprop.ptr, &pprop.prop);
- if (pprop.prop == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Incorrect context for running font unlink");
- return OPERATOR_CANCELLED;
- }
+ if (pprop.prop == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Incorrect context for running font unlink");
+ return OPERATOR_CANCELLED;
+ }
- builtin_font = BKE_vfont_builtin_get();
+ builtin_font = BKE_vfont_builtin_get();
- RNA_id_pointer_create(&builtin_font->id, &idptr);
- RNA_property_pointer_set(&pprop.ptr, pprop.prop, idptr);
- RNA_property_update(C, &pprop.ptr, pprop.prop);
+ RNA_id_pointer_create(&builtin_font->id, &idptr);
+ RNA_property_pointer_set(&pprop.ptr, pprop.prop, idptr);
+ RNA_property_update(C, &pprop.ptr, pprop.prop);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void FONT_OT_unlink(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unlink";
- ot->idname = "FONT_OT_unlink";
- ot->description = "Unlink active font data-block";
+ /* identifiers */
+ ot->name = "Unlink";
+ ot->idname = "FONT_OT_unlink";
+ ot->description = "Unlink active font data-block";
- /* api callbacks */
- ot->exec = font_unlink_exec;
+ /* api callbacks */
+ ot->exec = font_unlink_exec;
}
/**
* TextBox selection
*/
-bool ED_curve_editfont_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
+bool ED_curve_editfont_select_pick(
+ bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = obedit->data;
- ViewContext vc;
- /* bias against the active, in pixels, allows cycling */
- const float active_bias_px = 4.0f;
- const float mval_fl[2] = {UNPACK2(mval)};
- const int i_actbox = max_ii(0, cu->actbox - 1);
- int i_iter, actbox_select = -1;
- const float dist = ED_view3d_select_dist_px();
- float dist_sq_best = dist * dist;
-
- ED_view3d_viewcontext_init(C, &vc);
-
- ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
-
- /* currently only select active */
- (void)extend;
- (void)deselect;
- (void)toggle;
-
- for (i_iter = 0; i_iter < cu->totbox; i_iter++) {
- int i = (i_iter + i_actbox) % cu->totbox;
- float dist_sq_min;
- int j, j_prev;
-
- float obedit_co[4][3];
- float screen_co[4][2];
- rctf rect;
- int project_ok = 0;
-
-
- BKE_curve_rect_from_textbox(cu, &cu->tb[i], &rect);
-
- copy_v3_fl3(obedit_co[0], rect.xmin, rect.ymin, 0.0f);
- copy_v3_fl3(obedit_co[1], rect.xmin, rect.ymax, 0.0f);
- copy_v3_fl3(obedit_co[2], rect.xmax, rect.ymax, 0.0f);
- copy_v3_fl3(obedit_co[3], rect.xmax, rect.ymin, 0.0f);
-
- 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)
- {
- project_ok |= (1 << j);
- }
- }
-
- dist_sq_min = dist_sq_best;
- for (j = 0, j_prev = 3; j < 4; j_prev = j++) {
- if ((project_ok & (1 << j)) &&
- (project_ok & (1 << j_prev)))
- {
- const float dist_test_sq = dist_squared_to_line_segment_v2(mval_fl, screen_co[j_prev], screen_co[j]);
- if (dist_sq_min > dist_test_sq) {
- dist_sq_min = dist_test_sq;
- }
- }
- }
-
- /* bias in pixels to cycle seletion */
- if (i_iter == 0) {
- dist_sq_min += active_bias_px;
- }
-
- if (dist_sq_min < dist_sq_best) {
- dist_sq_best = dist_sq_min;
- actbox_select = i + 1;
- }
- }
-
- if (actbox_select != -1) {
- if (cu->actbox != actbox_select) {
- cu->actbox = actbox_select;
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- }
- return true;
- }
- else {
- return false;
- }
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ ViewContext vc;
+ /* bias against the active, in pixels, allows cycling */
+ const float active_bias_px = 4.0f;
+ const float mval_fl[2] = {UNPACK2(mval)};
+ const int i_actbox = max_ii(0, cu->actbox - 1);
+ int i_iter, actbox_select = -1;
+ const float dist = ED_view3d_select_dist_px();
+ float dist_sq_best = dist * dist;
+
+ ED_view3d_viewcontext_init(C, &vc);
+
+ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
+
+ /* currently only select active */
+ (void)extend;
+ (void)deselect;
+ (void)toggle;
+
+ for (i_iter = 0; i_iter < cu->totbox; i_iter++) {
+ int i = (i_iter + i_actbox) % cu->totbox;
+ float dist_sq_min;
+ int j, j_prev;
+
+ float obedit_co[4][3];
+ float screen_co[4][2];
+ rctf rect;
+ int project_ok = 0;
+
+ BKE_curve_rect_from_textbox(cu, &cu->tb[i], &rect);
+
+ copy_v3_fl3(obedit_co[0], rect.xmin, rect.ymin, 0.0f);
+ copy_v3_fl3(obedit_co[1], rect.xmin, rect.ymax, 0.0f);
+ copy_v3_fl3(obedit_co[2], rect.xmax, rect.ymax, 0.0f);
+ copy_v3_fl3(obedit_co[3], rect.xmax, rect.ymin, 0.0f);
+
+ 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) {
+ project_ok |= (1 << j);
+ }
+ }
+
+ dist_sq_min = dist_sq_best;
+ for (j = 0, j_prev = 3; j < 4; j_prev = j++) {
+ if ((project_ok & (1 << j)) && (project_ok & (1 << j_prev))) {
+ const float dist_test_sq = dist_squared_to_line_segment_v2(
+ mval_fl, screen_co[j_prev], screen_co[j]);
+ if (dist_sq_min > dist_test_sq) {
+ dist_sq_min = dist_test_sq;
+ }
+ }
+ }
+
+ /* bias in pixels to cycle seletion */
+ if (i_iter == 0) {
+ dist_sq_min += active_bias_px;
+ }
+
+ if (dist_sq_min < dist_sq_best) {
+ dist_sq_best = dist_sq_min;
+ actbox_select = i + 1;
+ }
+ }
+
+ if (actbox_select != -1) {
+ if (cu->actbox != actbox_select) {
+ cu->actbox = actbox_select;
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ }
+ return true;
+ }
+ else {
+ return false;
+ }
}
diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c
index 13cbea77ab8..82c19db7a4a 100644
--- a/source/blender/editors/curve/editfont_undo.c
+++ b/source/blender/editors/curve/editfont_undo.c
@@ -27,7 +27,6 @@
#include "BLI_utildefines.h"
#include "BLI_array_utils.h"
-
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -60,33 +59,32 @@
* \{ */
typedef struct UndoFont {
- wchar_t *textbuf;
- struct CharInfo *textbufinfo;
+ wchar_t *textbuf;
+ struct CharInfo *textbufinfo;
- int len, pos;
+ int len, pos;
#ifdef USE_ARRAY_STORE
- struct {
- BArrayState *textbuf;
- BArrayState *textbufinfo;
- } store;
+ struct {
+ BArrayState *textbuf;
+ BArrayState *textbufinfo;
+ } store;
#endif
- size_t undo_size;
+ size_t undo_size;
} UndoFont;
-
#ifdef USE_ARRAY_STORE
/** \name Array Store
* \{ */
static struct {
- struct BArrayStore_AtSize bs_stride;
- int users;
+ struct BArrayStore_AtSize bs_stride;
+ int users;
- /* We could have the undo API pass in the previous state, for now store a local list */
- ListBase local_links;
+ /* We could have the undo API pass in the previous state, for now store a local list */
+ ListBase local_links;
} uf_arraystore = {{NULL}};
@@ -95,33 +93,33 @@ static struct {
* This is done since when reading from an undo state, they must be temporarily expanded.
* then discarded afterwards, having this argument avoids having 2x code paths.
*/
-static void uf_arraystore_compact_ex(
- UndoFont *uf, const UndoFont *uf_ref,
- bool create)
+static void uf_arraystore_compact_ex(UndoFont *uf, const UndoFont *uf_ref, bool create)
{
-#define STATE_COMPACT(uf, id, len) \
- if ((uf)->id) { \
- BLI_assert(create == ((uf)->store.id == NULL)); \
- if (create) { \
- BArrayState *state_reference = uf_ref ? uf_ref->store.id : NULL; \
- const size_t stride = sizeof(*(uf)->id); \
- BArrayStore *bs = BLI_array_store_at_size_ensure(&uf_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE); \
- (uf)->store.id = BLI_array_store_state_add( \
- bs, (uf)->id, (size_t)(len) * stride, state_reference); \
- } \
- /* keep uf->len for validation */ \
- MEM_freeN((uf)->id); \
- (uf)->id = NULL; \
- } ((void)0)
-
- STATE_COMPACT(uf, textbuf, uf->len + 1);
- STATE_COMPACT(uf, textbufinfo, uf->len + 1);
-
-#undef STATE_COMPACT
-
- if (create) {
- uf_arraystore.users += 1;
- }
+# define STATE_COMPACT(uf, id, len) \
+ if ((uf)->id) { \
+ BLI_assert(create == ((uf)->store.id == NULL)); \
+ if (create) { \
+ BArrayState *state_reference = uf_ref ? uf_ref->store.id : NULL; \
+ const size_t stride = sizeof(*(uf)->id); \
+ BArrayStore *bs = BLI_array_store_at_size_ensure( \
+ &uf_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE); \
+ (uf)->store.id = BLI_array_store_state_add( \
+ bs, (uf)->id, (size_t)(len)*stride, state_reference); \
+ } \
+ /* keep uf->len for validation */ \
+ MEM_freeN((uf)->id); \
+ (uf)->id = NULL; \
+ } \
+ ((void)0)
+
+ STATE_COMPACT(uf, textbuf, uf->len + 1);
+ STATE_COMPACT(uf, textbufinfo, uf->len + 1);
+
+# undef STATE_COMPACT
+
+ if (create) {
+ uf_arraystore.users += 1;
+ }
}
/**
@@ -129,35 +127,40 @@ static void uf_arraystore_compact_ex(
*/
static void uf_arraystore_compact(UndoFont *um, const UndoFont *uf_ref)
{
- uf_arraystore_compact_ex(um, uf_ref, true);
+ uf_arraystore_compact_ex(um, uf_ref, true);
}
static void uf_arraystore_compact_with_info(UndoFont *um, const UndoFont *uf_ref)
{
-#ifdef DEBUG_PRINT
- size_t size_expanded_prev, size_compacted_prev;
- BLI_array_store_at_size_calc_memory_usage(&uf_arraystore.bs_stride, &size_expanded_prev, &size_compacted_prev);
-#endif
-
- uf_arraystore_compact(um, uf_ref);
-
-#ifdef DEBUG_PRINT
- {
- size_t size_expanded, size_compacted;
- BLI_array_store_at_size_calc_memory_usage(&uf_arraystore.bs_stride, &size_expanded, &size_compacted);
-
- const double percent_total = size_expanded ?
- (((double)size_compacted / (double)size_expanded) * 100.0) : -1.0;
-
- size_t size_expanded_step = size_expanded - size_expanded_prev;
- size_t size_compacted_step = size_compacted - size_compacted_prev;
- const double percent_step = size_expanded_step ?
- (((double)size_compacted_step / (double)size_expanded_step) * 100.0) : -1.0;
-
- printf("overall memory use: %.8f%% of expanded size\n", percent_total);
- printf("step memory use: %.8f%% of expanded size\n", percent_step);
- }
-#endif
+# ifdef DEBUG_PRINT
+ size_t size_expanded_prev, size_compacted_prev;
+ BLI_array_store_at_size_calc_memory_usage(
+ &uf_arraystore.bs_stride, &size_expanded_prev, &size_compacted_prev);
+# endif
+
+ uf_arraystore_compact(um, uf_ref);
+
+# ifdef DEBUG_PRINT
+ {
+ size_t size_expanded, size_compacted;
+ BLI_array_store_at_size_calc_memory_usage(
+ &uf_arraystore.bs_stride, &size_expanded, &size_compacted);
+
+ const double percent_total = size_expanded ?
+ (((double)size_compacted / (double)size_expanded) * 100.0) :
+ -1.0;
+
+ size_t size_expanded_step = size_expanded - size_expanded_prev;
+ size_t size_compacted_step = size_compacted - size_compacted_prev;
+ const double percent_step = size_expanded_step ?
+ (((double)size_compacted_step / (double)size_expanded_step) *
+ 100.0) :
+ -1.0;
+
+ printf("overall memory use: %.8f%% of expanded size\n", percent_total);
+ printf("step memory use: %.8f%% of expanded size\n", percent_step);
+ }
+# endif
}
/**
@@ -165,156 +168,159 @@ static void uf_arraystore_compact_with_info(UndoFont *um, const UndoFont *uf_ref
*/
static void uf_arraystore_expand_clear(UndoFont *um)
{
- uf_arraystore_compact_ex(um, NULL, false);
+ uf_arraystore_compact_ex(um, NULL, false);
}
static void uf_arraystore_expand(UndoFont *uf)
{
-#define STATE_EXPAND(uf, id, len) \
- if ((uf)->store.id) { \
- const size_t stride = sizeof(*(uf)->id); \
- BArrayState *state = (uf)->store.id; \
- size_t state_len; \
- (uf)->id = BLI_array_store_state_data_get_alloc(state, &state_len); \
- BLI_assert((len) == (state_len / stride)); \
- UNUSED_VARS_NDEBUG(stride); \
- } ((void)0)
-
- STATE_EXPAND(uf, textbuf, uf->len + 1);
- STATE_EXPAND(uf, textbufinfo, uf->len + 1);
-
-#undef STATE_EXPAND
+# define STATE_EXPAND(uf, id, len) \
+ if ((uf)->store.id) { \
+ const size_t stride = sizeof(*(uf)->id); \
+ BArrayState *state = (uf)->store.id; \
+ size_t state_len; \
+ (uf)->id = BLI_array_store_state_data_get_alloc(state, &state_len); \
+ BLI_assert((len) == (state_len / stride)); \
+ UNUSED_VARS_NDEBUG(stride); \
+ } \
+ ((void)0)
+
+ STATE_EXPAND(uf, textbuf, uf->len + 1);
+ STATE_EXPAND(uf, textbufinfo, uf->len + 1);
+
+# undef STATE_EXPAND
}
static void uf_arraystore_free(UndoFont *uf)
{
-#define STATE_FREE(uf, id) \
- if ((uf)->store.id) { \
- const size_t stride = sizeof(*(uf)->id); \
- BArrayStore *bs = BLI_array_store_at_size_get(&uf_arraystore.bs_stride, stride); \
- BArrayState *state = (uf)->store.id; \
- BLI_array_store_state_remove(bs, state); \
- (uf)->store.id = NULL; \
- } ((void)0)
+# define STATE_FREE(uf, id) \
+ if ((uf)->store.id) { \
+ const size_t stride = sizeof(*(uf)->id); \
+ BArrayStore *bs = BLI_array_store_at_size_get(&uf_arraystore.bs_stride, stride); \
+ BArrayState *state = (uf)->store.id; \
+ BLI_array_store_state_remove(bs, state); \
+ (uf)->store.id = NULL; \
+ } \
+ ((void)0)
- STATE_FREE(uf, textbuf);
- STATE_FREE(uf, textbufinfo);
+ STATE_FREE(uf, textbuf);
+ STATE_FREE(uf, textbufinfo);
-#undef STATE_FREE
+# undef STATE_FREE
- uf_arraystore.users -= 1;
+ uf_arraystore.users -= 1;
- BLI_assert(uf_arraystore.users >= 0);
+ BLI_assert(uf_arraystore.users >= 0);
- if (uf_arraystore.users == 0) {
-#ifdef DEBUG_PRINT
- printf("editfont undo store: freeing all data!\n");
-#endif
+ if (uf_arraystore.users == 0) {
+# ifdef DEBUG_PRINT
+ printf("editfont undo store: freeing all data!\n");
+# endif
- BLI_array_store_at_size_clear(&uf_arraystore.bs_stride);
- }
+ BLI_array_store_at_size_clear(&uf_arraystore.bs_stride);
+ }
}
/** \} */
-#endif /* USE_ARRAY_STORE */
+#endif /* USE_ARRAY_STORE */
static void undofont_to_editfont(UndoFont *uf, Curve *cu)
{
- EditFont *ef = cu->editfont;
+ EditFont *ef = cu->editfont;
- size_t final_size;
+ size_t final_size;
#ifdef USE_ARRAY_STORE
- uf_arraystore_expand(uf);
+ uf_arraystore_expand(uf);
#endif
- final_size = sizeof(wchar_t) * (uf->len + 1);
- memcpy(ef->textbuf, uf->textbuf, final_size);
+ final_size = sizeof(wchar_t) * (uf->len + 1);
+ memcpy(ef->textbuf, uf->textbuf, final_size);
- final_size = sizeof(CharInfo) * (uf->len + 1);
- memcpy(ef->textbufinfo, uf->textbufinfo, final_size);
+ final_size = sizeof(CharInfo) * (uf->len + 1);
+ memcpy(ef->textbufinfo, uf->textbufinfo, final_size);
- ef->pos = uf->pos;
- ef->len = uf->len;
+ ef->pos = uf->pos;
+ ef->len = uf->len;
- ef->selstart = ef->selend = 0;
+ ef->selstart = ef->selend = 0;
#ifdef USE_ARRAY_STORE
- uf_arraystore_expand_clear(uf);
+ uf_arraystore_expand_clear(uf);
#endif
}
static void *undofont_from_editfont(UndoFont *uf, Curve *cu)
{
- BLI_assert(BLI_array_is_zeroed(uf, 1));
+ BLI_assert(BLI_array_is_zeroed(uf, 1));
- EditFont *ef = cu->editfont;
+ EditFont *ef = cu->editfont;
- size_t mem_used_prev = MEM_get_memory_in_use();
+ size_t mem_used_prev = MEM_get_memory_in_use();
- size_t final_size;
+ size_t final_size;
- final_size = sizeof(wchar_t) * (ef->len + 1);
- uf->textbuf = MEM_mallocN(final_size, __func__);
- memcpy(uf->textbuf, ef->textbuf, final_size);
+ final_size = sizeof(wchar_t) * (ef->len + 1);
+ uf->textbuf = MEM_mallocN(final_size, __func__);
+ memcpy(uf->textbuf, ef->textbuf, final_size);
- final_size = sizeof(CharInfo) * (ef->len + 1);
- uf->textbufinfo = MEM_mallocN(final_size, __func__);
- memcpy(uf->textbufinfo, ef->textbufinfo, final_size);
+ final_size = sizeof(CharInfo) * (ef->len + 1);
+ uf->textbufinfo = MEM_mallocN(final_size, __func__);
+ memcpy(uf->textbufinfo, ef->textbufinfo, final_size);
- uf->pos = ef->pos;
- uf->len = ef->len;
+ uf->pos = ef->pos;
+ uf->len = ef->len;
#ifdef USE_ARRAY_STORE
- {
- const UndoFont *uf_ref = uf_arraystore.local_links.last ?
- ((LinkData *)uf_arraystore.local_links.last)->data : NULL;
+ {
+ const UndoFont *uf_ref = uf_arraystore.local_links.last ?
+ ((LinkData *)uf_arraystore.local_links.last)->data :
+ NULL;
- /* add oursrlves */
- BLI_addtail(&uf_arraystore.local_links, BLI_genericNodeN(uf));
+ /* add oursrlves */
+ BLI_addtail(&uf_arraystore.local_links, BLI_genericNodeN(uf));
- uf_arraystore_compact_with_info(uf, uf_ref);
- }
+ uf_arraystore_compact_with_info(uf, uf_ref);
+ }
#endif
- size_t mem_used_curr = MEM_get_memory_in_use();
+ size_t mem_used_curr = MEM_get_memory_in_use();
- uf->undo_size = mem_used_prev < mem_used_curr ? mem_used_curr - mem_used_prev : sizeof(UndoFont);
+ uf->undo_size = mem_used_prev < mem_used_curr ? mem_used_curr - mem_used_prev : sizeof(UndoFont);
- return uf;
+ return uf;
}
static void undofont_free_data(UndoFont *uf)
{
#ifdef USE_ARRAY_STORE
- {
- LinkData *link = BLI_findptr(&uf_arraystore.local_links, uf, offsetof(LinkData, data));
- BLI_remlink(&uf_arraystore.local_links, link);
- MEM_freeN(link);
- }
- uf_arraystore_free(uf);
+ {
+ LinkData *link = BLI_findptr(&uf_arraystore.local_links, uf, offsetof(LinkData, data));
+ BLI_remlink(&uf_arraystore.local_links, link);
+ MEM_freeN(link);
+ }
+ uf_arraystore_free(uf);
#endif
- if (uf->textbuf) {
- MEM_freeN(uf->textbuf);
- }
- if (uf->textbufinfo) {
- MEM_freeN(uf->textbufinfo);
- }
+ if (uf->textbuf) {
+ MEM_freeN(uf->textbuf);
+ }
+ if (uf->textbufinfo) {
+ MEM_freeN(uf->textbufinfo);
+ }
}
static Object *editfont_object_from_context(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_FONT) {
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
- if (ef != NULL) {
- return obedit;
- }
- }
- return NULL;
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_FONT) {
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
+ if (ef != NULL) {
+ return obedit;
+ }
+ }
+ return NULL;
}
/** \} */
@@ -324,68 +330,74 @@ static Object *editfont_object_from_context(bContext *C)
* \{ */
typedef struct FontUndoStep {
- UndoStep step;
- /* note: will split out into list for multi-object-editmode. */
- UndoRefID_Object obedit_ref;
- UndoFont data;
+ UndoStep step;
+ /* note: will split out into list for multi-object-editmode. */
+ UndoRefID_Object obedit_ref;
+ UndoFont data;
} FontUndoStep;
static bool font_undosys_poll(bContext *C)
{
- return editfont_object_from_context(C) != NULL;
+ return editfont_object_from_context(C) != NULL;
}
-static bool font_undosys_step_encode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p)
+static bool font_undosys_step_encode(struct bContext *C,
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p)
{
- FontUndoStep *us = (FontUndoStep *)us_p;
- us->obedit_ref.ptr = editfont_object_from_context(C);
- Curve *cu = us->obedit_ref.ptr->data;
- undofont_from_editfont(&us->data, cu);
- us->step.data_size = us->data.undo_size;
- return true;
+ FontUndoStep *us = (FontUndoStep *)us_p;
+ us->obedit_ref.ptr = editfont_object_from_context(C);
+ Curve *cu = us->obedit_ref.ptr->data;
+ undofont_from_editfont(&us->data, cu);
+ us->step.data_size = us->data.undo_size;
+ return true;
}
-static void font_undosys_step_decode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p, int UNUSED(dir))
+static void font_undosys_step_decode(struct bContext *C,
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p,
+ int UNUSED(dir))
{
- /* TODO(campbell): undo_system: use low-level API to set mode. */
- ED_object_mode_set(C, OB_MODE_EDIT);
- BLI_assert(font_undosys_poll(C));
-
- FontUndoStep *us = (FontUndoStep *)us_p;
- Object *obedit = us->obedit_ref.ptr;
- Curve *cu = obedit->data;
- undofont_to_editfont(&us->data, cu);
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+ /* TODO(campbell): undo_system: use low-level API to set mode. */
+ ED_object_mode_set(C, OB_MODE_EDIT);
+ BLI_assert(font_undosys_poll(C));
+
+ FontUndoStep *us = (FontUndoStep *)us_p;
+ Object *obedit = us->obedit_ref.ptr;
+ Curve *cu = obedit->data;
+ undofont_to_editfont(&us->data, cu);
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
}
static void font_undosys_step_free(UndoStep *us_p)
{
- FontUndoStep *us = (FontUndoStep *)us_p;
- undofont_free_data(&us->data);
+ FontUndoStep *us = (FontUndoStep *)us_p;
+ undofont_free_data(&us->data);
}
-static void font_undosys_foreach_ID_ref(
- UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+static void font_undosys_foreach_ID_ref(UndoStep *us_p,
+ UndoTypeForEachIDRefFn foreach_ID_ref_fn,
+ void *user_data)
{
- FontUndoStep *us = (FontUndoStep *)us_p;
- foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->obedit_ref));
+ FontUndoStep *us = (FontUndoStep *)us_p;
+ foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->obedit_ref));
}
/* Export for ED_undo_sys. */
void ED_font_undosys_type(UndoType *ut)
{
- ut->name = "Edit Font";
- ut->poll = font_undosys_poll;
- ut->step_encode = font_undosys_step_encode;
- ut->step_decode = font_undosys_step_decode;
- ut->step_free = font_undosys_step_free;
+ ut->name = "Edit Font";
+ ut->poll = font_undosys_poll;
+ ut->step_encode = font_undosys_step_encode;
+ ut->step_decode = font_undosys_step_decode;
+ ut->step_free = font_undosys_step_free;
- ut->step_foreach_ID_ref = font_undosys_foreach_ID_ref;
+ ut->step_foreach_ID_ref = font_undosys_foreach_ID_ref;
- ut->use_context = true;
+ ut->use_context = true;
- ut->step_size = sizeof(FontUndoStep);
+ ut->step_size = sizeof(FontUndoStep);
}
/** \} */
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index 04bd067b146..316ad3f91d6 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -33,727 +33,727 @@ set(LIB
# Order matches "UI_icons.h", final name will be formatted: "icons{size}_{name}.dat"
set(ICON_NAMES
- question
- error
- cancel
- tria_right
- tria_down
- tria_left
- tria_up
- arrow_leftright
- plus
- disclosure_tri_right
- disclosure_tri_down
- radiobut_off
- radiobut_on
- menu_panel
- blender
- grip
- dot
- collapsemenu
- x
- duplicate
- node
- node_sel
- window
- workspace
- rightarrow_thin
- bordermove
- viewzoom
- add
- remove
- panel_close
- copy_id
- eyedropper
- auto
- checkbox_dehlt
- checkbox_hlt
- unlocked
- locked
- unpinned
- pinned
- screen_back
- rightarrow
- downarrow_hlt
- plugin
- help
- ghost_enabled
- color
- unlinked
- linked
- hand
- zoom_all
- zoom_selected
- zoom_previous
- zoom_in
- zoom_out
- driver_distance
- driver_rotational_difference
- driver_transform
- freeze
- stylus_pressure
- ghost_disabled
- file_new
- file_tick
- quit
- url
- recover_last
- three_dots
- fullscreen_enter
- fullscreen_exit
- light
- material
- texture
- anim
- world
- scene
- output
- script
- particles
- physics
- speaker
- tool_settings
- shaderfx
- fake_user_off
- fake_user_on
- view3d
- graph
- outliner
- properties
- filebrowser
- image
- info
- sequence
- text
- sound
- action
- nla
- preferences
- time
- nodetree
- console
- clip
- asset_manager
- node_compositing
- node_texture
- node_material
- object_datamode
- editmode_hlt
- uv
- vpaint_hlt
- tpaint_hlt
- wpaint_hlt
- sculptmode_hlt
- pose_hlt
- particlemode
- tracking
- tracking_backwards
- tracking_forwards
- tracking_backwards_single
- tracking_forwards_single
- tracking_clear_backwards
- tracking_clear_forwards
- tracking_refine_backwards
- tracking_refine_forwards
- scene_data
- renderlayers
- world_data
- object_data
- mesh_data
- curve_data
- meta_data
- lattice_data
- light_data
- material_data
- texture_data
- anim_data
- camera_data
- particle_data
- library_data_direct
- group
- armature_data
- community
- bone_data
- constraint
- shapekey_data
- constraint_bone
- camera_stereo
- package
- uglypackage
- experimental
- brush_data
- image_data
- file
- fcurve
- font_data
- render_result
- surface_data
- empty_data
- preset
- render_animation
- render_still
- library_data_broken
- boids
- strands
- library_data_indirect
- greasepencil
- line_data
- library_data_override
- group_bone
- group_vertex
- group_vcol
- group_uvs
- face_maps
- rna
- rna_add
- mouse_lmb
- mouse_mmb
- mouse_rmb
- mouse_move
- mouse_lmb_drag
- mouse_mmb_drag
- mouse_rmb_drag
- preset_new
- decorate
- decorate_keyframe
- decorate_animate
- decorate_driver
- decorate_linked
- decorate_library_override
- decorate_unlocked
- decorate_locked
- decorate_override
- sealed
- heart
- orphan_data
- user
- system
- settings
- outliner_ob_empty
- outliner_ob_mesh
- outliner_ob_curve
- outliner_ob_lattice
- outliner_ob_meta
- outliner_ob_light
- outliner_ob_camera
- outliner_ob_armature
- outliner_ob_font
- outliner_ob_surface
- outliner_ob_speaker
- outliner_ob_force_field
- outliner_ob_group_instance
- outliner_ob_greasepencil
- outliner_ob_lightprobe
- outliner_ob_image
- restrict_color_off
- restrict_color_on
- hide_on
- hide_off
- restrict_select_on
- restrict_select_off
- restrict_render_on
- restrict_render_off
- outliner_data_empty
- outliner_data_mesh
- outliner_data_curve
- outliner_data_lattice
- outliner_data_meta
- outliner_data_light
- outliner_data_camera
- outliner_data_armature
- outliner_data_font
- outliner_data_surface
- outliner_data_speaker
- outliner_data_greasepencil
- gp_select_points
- gp_select_strokes
- gp_multiframe_editing
- gp_only_selected
- modifier_off
- modifier_on
- onionskin_off
- onionskin_on
- restrict_view_on
- restrict_view_off
- mesh_plane
- mesh_cube
- mesh_circle
- mesh_uvsphere
- mesh_icosphere
- mesh_grid
- mesh_monkey
- mesh_cylinder
- mesh_torus
- mesh_cone
- mesh_capsule
- empty_single_arrow
- light_point
- light_sun
- light_spot
- light_hemi
- light_area
- cube
- sphere
- cone
- meta_plane
- meta_cube
- meta_ball
- meta_ellipsoid
- meta_capsule
- surface_ncurve
- surface_ncircle
- surface_nsurface
- surface_ncylinder
- surface_nsphere
- surface_ntorus
- empty_axis
- stroke
- empty_arrows
- curve_bezcurve
- curve_bezcircle
- curve_ncurve
- curve_ncircle
- curve_path
- lightprobe_cubemap
- lightprobe_planar
- lightprobe_grid
- color_red
- color_green
- color_blue
- tria_right_bar
- tria_down_bar
- tria_left_bar
- tria_up_bar
- force_force
- force_wind
- force_vortex
- force_magnetic
- force_harmonic
- force_charge
- force_lennardjones
- force_texture
- force_curve
- force_boid
- force_turbulence
- force_drag
- force_smokeflow
- image_plane
- image_background
- image_reference
- node_insert_on
- node_insert_off
- node_top
- node_side
- node_corner
- align_left
- align_center
- align_right
- align_justify
- align_flush
- align_top
- align_middle
- align_bottom
- bold
- italic
- underline
- small_caps
- modifier
- mod_wave
- mod_build
- mod_decim
- mod_mirror
- mod_soft
- mod_subsurf
- hook
- mod_physics
- mod_particles
- mod_boolean
- mod_edgesplit
- mod_array
- mod_uvproject
- mod_displace
- mod_curve
- mod_lattice
- mod_tint
- mod_armature
- mod_shrinkwrap
- mod_cast
- mod_meshdeform
- mod_bevel
- mod_smooth
- mod_simpledeform
- mod_mask
- mod_cloth
- mod_explode
- mod_fluidsim
- mod_multires
- mod_smoke
- mod_solidify
- mod_screw
- mod_vertex_weight
- mod_dynamicpaint
- mod_remesh
- mod_ocean
- mod_warp
- mod_skin
- mod_triangulate
- mod_wireframe
- mod_data_transfer
- mod_normaledit
- mod_particle_instance
- mod_hue_saturation
- mod_noise
- mod_offset
- mod_simplify
- mod_thickness
- mod_instance
- mod_time
- mod_opacity
- rec
- play
- ff
- rew
- pause
- prev_keyframe
- next_keyframe
- play_reverse
- preview_range
- action_tweak
- pmarker_act
- pmarker_sel
- pmarker
- marker_hlt
- marker
- keyframe_hlt
- keyframe
- keyingset
- key_dehlt
- key_hlt
- mute_ipo_off
- mute_ipo_on
- visible_ipo_off
- visible_ipo_on
- driver
- solo_off
- solo_on
- frame_prev
- frame_next
- nla_pushdown
- ipo_constant
- ipo_linear
- ipo_bezier
- ipo_sine
- ipo_quad
- ipo_cubic
- ipo_quart
- ipo_quint
- ipo_expo
- ipo_circ
- ipo_bounce
- ipo_elastic
- ipo_back
- ipo_ease_in
- ipo_ease_out
- ipo_ease_in_out
- normalize_fcurves
- vertexsel
- edgesel
- facesel
- pivot_boundbox
- pivot_cursor
- pivot_individual
- pivot_median
- pivot_active
- center_only
- smoothcurve
- spherecurve
- rootcurve
- sharpcurve
- lincurve
- nocurve
- rndcurve
- prop_off
- prop_on
- prop_con
- sculpt_dyntopo
- particle_point
- particle_tip
- particle_path
- snap_off
- snap_on
- snap_normal
- snap_grid
- snap_vertex
- snap_edge
- snap_face
- snap_volume
- snap_increment
- sticky_uvs_loc
- sticky_uvs_disable
- sticky_uvs_vert
- clipuv_dehlt
- clipuv_hlt
- snap_peel_object
- grid
- object_origin
- orientation_global
- orientation_gimbal
- orientation_local
- orientation_normal
- orientation_view
- copydown
- pastedown
- pasteflipup
- pasteflipdown
- vis_sel_11
- vis_sel_10
- vis_sel_01
- vis_sel_00
- automerge_on
- automerge_off
- uv_vertexsel
- uv_edgesel
- uv_facesel
- uv_islandsel
- uv_sync_select
- normals_vertex
- normals_face
- normals_vertex_face
- shading_bbox
- shading_wire
- shading_solid
- shading_rendered
- shading_texture
- overlay
- xray
- lockview_off
- lockview_on
- axis_side
- axis_front
- axis_top
- ndof_dom
- ndof_turn
- ndof_fly
- ndof_trans
- layer_used
- layer_active
- sortalpha
- sortbyext
- sorttime
- sortsize
- shortdisplay
- longdisplay
- imgdisplay
- bookmarks
- fontpreview
- filter
- newfolder
- file_parent
- file_refresh
- file_folder
- file_blank
- file_blend
- file_image
- file_movie
- file_script
- file_sound
- file_font
- file_text
- sort_desc
- sort_asc
- link_blend
- append_blend
- import
- export
- loop_back
- loop_forwards
- back
- forward
- file_volume
- alembic
- volume
- file_hidden
- file_backup
- disk_drive
- matplane
- matsphere
- matcube
- monkey
- hair
- aliased
- antialiased
- mat_sphere_sky
- matshaderball
- matcloth
- matfluid
- wordwrap_off
- wordwrap_on
- syntax_off
- syntax_on
- linenumbers_off
- linenumbers_on
- scriptplugins
- seq_sequencer
- seq_preview
- seq_luma_waveform
- seq_chroma_scope
- seq_histogram
- seq_splitview
- image_rgb
- image_rgb_alpha
- image_alpha
- image_zdepth
- view_perspective
- view_ortho
- view_camera
- view_pan
- view_zoom
+ question
+ error
+ cancel
+ tria_right
+ tria_down
+ tria_left
+ tria_up
+ arrow_leftright
+ plus
+ disclosure_tri_right
+ disclosure_tri_down
+ radiobut_off
+ radiobut_on
+ menu_panel
+ blender
+ grip
+ dot
+ collapsemenu
+ x
+ duplicate
+ node
+ node_sel
+ window
+ workspace
+ rightarrow_thin
+ bordermove
+ viewzoom
+ add
+ remove
+ panel_close
+ copy_id
+ eyedropper
+ auto
+ checkbox_dehlt
+ checkbox_hlt
+ unlocked
+ locked
+ unpinned
+ pinned
+ screen_back
+ rightarrow
+ downarrow_hlt
+ plugin
+ help
+ ghost_enabled
+ color
+ unlinked
+ linked
+ hand
+ zoom_all
+ zoom_selected
+ zoom_previous
+ zoom_in
+ zoom_out
+ driver_distance
+ driver_rotational_difference
+ driver_transform
+ freeze
+ stylus_pressure
+ ghost_disabled
+ file_new
+ file_tick
+ quit
+ url
+ recover_last
+ three_dots
+ fullscreen_enter
+ fullscreen_exit
+ light
+ material
+ texture
+ anim
+ world
+ scene
+ output
+ script
+ particles
+ physics
+ speaker
+ tool_settings
+ shaderfx
+ fake_user_off
+ fake_user_on
+ view3d
+ graph
+ outliner
+ properties
+ filebrowser
+ image
+ info
+ sequence
+ text
+ sound
+ action
+ nla
+ preferences
+ time
+ nodetree
+ console
+ clip
+ asset_manager
+ node_compositing
+ node_texture
+ node_material
+ object_datamode
+ editmode_hlt
+ uv
+ vpaint_hlt
+ tpaint_hlt
+ wpaint_hlt
+ sculptmode_hlt
+ pose_hlt
+ particlemode
+ tracking
+ tracking_backwards
+ tracking_forwards
+ tracking_backwards_single
+ tracking_forwards_single
+ tracking_clear_backwards
+ tracking_clear_forwards
+ tracking_refine_backwards
+ tracking_refine_forwards
+ scene_data
+ renderlayers
+ world_data
+ object_data
+ mesh_data
+ curve_data
+ meta_data
+ lattice_data
+ light_data
+ material_data
+ texture_data
+ anim_data
+ camera_data
+ particle_data
+ library_data_direct
+ group
+ armature_data
+ community
+ bone_data
+ constraint
+ shapekey_data
+ constraint_bone
+ camera_stereo
+ package
+ uglypackage
+ experimental
+ brush_data
+ image_data
+ file
+ fcurve
+ font_data
+ render_result
+ surface_data
+ empty_data
+ preset
+ render_animation
+ render_still
+ library_data_broken
+ boids
+ strands
+ library_data_indirect
+ greasepencil
+ line_data
+ library_data_override
+ group_bone
+ group_vertex
+ group_vcol
+ group_uvs
+ face_maps
+ rna
+ rna_add
+ mouse_lmb
+ mouse_mmb
+ mouse_rmb
+ mouse_move
+ mouse_lmb_drag
+ mouse_mmb_drag
+ mouse_rmb_drag
+ preset_new
+ decorate
+ decorate_keyframe
+ decorate_animate
+ decorate_driver
+ decorate_linked
+ decorate_library_override
+ decorate_unlocked
+ decorate_locked
+ decorate_override
+ sealed
+ heart
+ orphan_data
+ user
+ system
+ settings
+ outliner_ob_empty
+ outliner_ob_mesh
+ outliner_ob_curve
+ outliner_ob_lattice
+ outliner_ob_meta
+ outliner_ob_light
+ outliner_ob_camera
+ outliner_ob_armature
+ outliner_ob_font
+ outliner_ob_surface
+ outliner_ob_speaker
+ outliner_ob_force_field
+ outliner_ob_group_instance
+ outliner_ob_greasepencil
+ outliner_ob_lightprobe
+ outliner_ob_image
+ restrict_color_off
+ restrict_color_on
+ hide_on
+ hide_off
+ restrict_select_on
+ restrict_select_off
+ restrict_render_on
+ restrict_render_off
+ outliner_data_empty
+ outliner_data_mesh
+ outliner_data_curve
+ outliner_data_lattice
+ outliner_data_meta
+ outliner_data_light
+ outliner_data_camera
+ outliner_data_armature
+ outliner_data_font
+ outliner_data_surface
+ outliner_data_speaker
+ outliner_data_greasepencil
+ gp_select_points
+ gp_select_strokes
+ gp_multiframe_editing
+ gp_only_selected
+ modifier_off
+ modifier_on
+ onionskin_off
+ onionskin_on
+ restrict_view_on
+ restrict_view_off
+ mesh_plane
+ mesh_cube
+ mesh_circle
+ mesh_uvsphere
+ mesh_icosphere
+ mesh_grid
+ mesh_monkey
+ mesh_cylinder
+ mesh_torus
+ mesh_cone
+ mesh_capsule
+ empty_single_arrow
+ light_point
+ light_sun
+ light_spot
+ light_hemi
+ light_area
+ cube
+ sphere
+ cone
+ meta_plane
+ meta_cube
+ meta_ball
+ meta_ellipsoid
+ meta_capsule
+ surface_ncurve
+ surface_ncircle
+ surface_nsurface
+ surface_ncylinder
+ surface_nsphere
+ surface_ntorus
+ empty_axis
+ stroke
+ empty_arrows
+ curve_bezcurve
+ curve_bezcircle
+ curve_ncurve
+ curve_ncircle
+ curve_path
+ lightprobe_cubemap
+ lightprobe_planar
+ lightprobe_grid
+ color_red
+ color_green
+ color_blue
+ tria_right_bar
+ tria_down_bar
+ tria_left_bar
+ tria_up_bar
+ force_force
+ force_wind
+ force_vortex
+ force_magnetic
+ force_harmonic
+ force_charge
+ force_lennardjones
+ force_texture
+ force_curve
+ force_boid
+ force_turbulence
+ force_drag
+ force_smokeflow
+ image_plane
+ image_background
+ image_reference
+ node_insert_on
+ node_insert_off
+ node_top
+ node_side
+ node_corner
+ align_left
+ align_center
+ align_right
+ align_justify
+ align_flush
+ align_top
+ align_middle
+ align_bottom
+ bold
+ italic
+ underline
+ small_caps
+ modifier
+ mod_wave
+ mod_build
+ mod_decim
+ mod_mirror
+ mod_soft
+ mod_subsurf
+ hook
+ mod_physics
+ mod_particles
+ mod_boolean
+ mod_edgesplit
+ mod_array
+ mod_uvproject
+ mod_displace
+ mod_curve
+ mod_lattice
+ mod_tint
+ mod_armature
+ mod_shrinkwrap
+ mod_cast
+ mod_meshdeform
+ mod_bevel
+ mod_smooth
+ mod_simpledeform
+ mod_mask
+ mod_cloth
+ mod_explode
+ mod_fluidsim
+ mod_multires
+ mod_smoke
+ mod_solidify
+ mod_screw
+ mod_vertex_weight
+ mod_dynamicpaint
+ mod_remesh
+ mod_ocean
+ mod_warp
+ mod_skin
+ mod_triangulate
+ mod_wireframe
+ mod_data_transfer
+ mod_normaledit
+ mod_particle_instance
+ mod_hue_saturation
+ mod_noise
+ mod_offset
+ mod_simplify
+ mod_thickness
+ mod_instance
+ mod_time
+ mod_opacity
+ rec
+ play
+ ff
+ rew
+ pause
+ prev_keyframe
+ next_keyframe
+ play_reverse
+ preview_range
+ action_tweak
+ pmarker_act
+ pmarker_sel
+ pmarker
+ marker_hlt
+ marker
+ keyframe_hlt
+ keyframe
+ keyingset
+ key_dehlt
+ key_hlt
+ mute_ipo_off
+ mute_ipo_on
+ visible_ipo_off
+ visible_ipo_on
+ driver
+ solo_off
+ solo_on
+ frame_prev
+ frame_next
+ nla_pushdown
+ ipo_constant
+ ipo_linear
+ ipo_bezier
+ ipo_sine
+ ipo_quad
+ ipo_cubic
+ ipo_quart
+ ipo_quint
+ ipo_expo
+ ipo_circ
+ ipo_bounce
+ ipo_elastic
+ ipo_back
+ ipo_ease_in
+ ipo_ease_out
+ ipo_ease_in_out
+ normalize_fcurves
+ vertexsel
+ edgesel
+ facesel
+ pivot_boundbox
+ pivot_cursor
+ pivot_individual
+ pivot_median
+ pivot_active
+ center_only
+ smoothcurve
+ spherecurve
+ rootcurve
+ sharpcurve
+ lincurve
+ nocurve
+ rndcurve
+ prop_off
+ prop_on
+ prop_con
+ sculpt_dyntopo
+ particle_point
+ particle_tip
+ particle_path
+ snap_off
+ snap_on
+ snap_normal
+ snap_grid
+ snap_vertex
+ snap_edge
+ snap_face
+ snap_volume
+ snap_increment
+ sticky_uvs_loc
+ sticky_uvs_disable
+ sticky_uvs_vert
+ clipuv_dehlt
+ clipuv_hlt
+ snap_peel_object
+ grid
+ object_origin
+ orientation_global
+ orientation_gimbal
+ orientation_local
+ orientation_normal
+ orientation_view
+ copydown
+ pastedown
+ pasteflipup
+ pasteflipdown
+ vis_sel_11
+ vis_sel_10
+ vis_sel_01
+ vis_sel_00
+ automerge_on
+ automerge_off
+ uv_vertexsel
+ uv_edgesel
+ uv_facesel
+ uv_islandsel
+ uv_sync_select
+ normals_vertex
+ normals_face
+ normals_vertex_face
+ shading_bbox
+ shading_wire
+ shading_solid
+ shading_rendered
+ shading_texture
+ overlay
+ xray
+ lockview_off
+ lockview_on
+ axis_side
+ axis_front
+ axis_top
+ ndof_dom
+ ndof_turn
+ ndof_fly
+ ndof_trans
+ layer_used
+ layer_active
+ sortalpha
+ sortbyext
+ sorttime
+ sortsize
+ shortdisplay
+ longdisplay
+ imgdisplay
+ bookmarks
+ fontpreview
+ filter
+ newfolder
+ file_parent
+ file_refresh
+ file_folder
+ file_blank
+ file_blend
+ file_image
+ file_movie
+ file_script
+ file_sound
+ file_font
+ file_text
+ sort_desc
+ sort_asc
+ link_blend
+ append_blend
+ import
+ export
+ loop_back
+ loop_forwards
+ back
+ forward
+ file_volume
+ alembic
+ volume
+ file_hidden
+ file_backup
+ disk_drive
+ matplane
+ matsphere
+ matcube
+ monkey
+ hair
+ aliased
+ antialiased
+ mat_sphere_sky
+ matshaderball
+ matcloth
+ matfluid
+ wordwrap_off
+ wordwrap_on
+ syntax_off
+ syntax_on
+ linenumbers_off
+ linenumbers_on
+ scriptplugins
+ seq_sequencer
+ seq_preview
+ seq_luma_waveform
+ seq_chroma_scope
+ seq_histogram
+ seq_splitview
+ image_rgb
+ image_rgb_alpha
+ image_alpha
+ image_zdepth
+ view_perspective
+ view_ortho
+ view_camera
+ view_pan
+ view_zoom
)
# This section is maintained by the updating script, keep BEGIN/END comments.
set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
- # BEGIN ICON_GEOM_NAMES
- brush.gpencil_draw.draw
- brush.gpencil_draw.erase
- brush.gpencil_draw.fill
- brush.paint_texture.airbrush
- brush.paint_texture.clone
- brush.paint_texture.draw
- brush.paint_texture.fill
- brush.paint_texture.mask
- brush.paint_texture.masklort
- brush.paint_texture.multiply
- brush.paint_texture.smear
- brush.paint_texture.soften
- brush.paint_vertex.alpha
- brush.paint_vertex.average
- brush.paint_vertex.blur
- brush.paint_vertex.draw
- brush.paint_vertex.smear
- brush.paint_weight.average
- brush.paint_weight.blur
- brush.paint_weight.draw
- brush.paint_weight.mix
- brush.paint_weight.smear
- brush.particle.add
- brush.particle.comb
- brush.particle.cut
- brush.particle.length
- brush.particle.puff
- brush.particle.smooth
- brush.particle.weight
- brush.sculpt.blob
- brush.sculpt.clay
- brush.sculpt.clay_strips
- brush.sculpt.crease
- brush.sculpt.draw
- brush.sculpt.fill
- brush.sculpt.flatten
- brush.sculpt.grab
- brush.sculpt.inflate
- brush.sculpt.layer
- brush.sculpt.mask
- brush.sculpt.nudge
- brush.sculpt.pinch
- brush.sculpt.rotate
- brush.sculpt.scrape
- brush.sculpt.simplify
- brush.sculpt.smooth
- brush.sculpt.snake_hook
- brush.sculpt.thumb
- brush.uv_sculpt.grab
- brush.uv_sculpt.pinch
- brush.uv_sculpt.relax
- none
- ops.armature.bone.roll
- ops.armature.extrude_cursor
- ops.armature.extrude_move
- ops.curve.draw
- ops.curve.extrude_cursor
- ops.curve.extrude_move
- ops.curve.radius
- ops.curve.vertex_random
- ops.generic.cursor
- ops.generic.select
- ops.generic.select_box
- ops.generic.select_circle
- ops.generic.select_lasso
- ops.gpencil.draw
- ops.gpencil.draw.eraser
- ops.gpencil.draw.line
- ops.gpencil.draw.poly
- ops.gpencil.edit_bend
- ops.gpencil.edit_mirror
- ops.gpencil.edit_shear
- ops.gpencil.edit_to_sphere
- ops.gpencil.extrude_move
- ops.gpencil.primitive_arc
- ops.gpencil.primitive_box
- ops.gpencil.primitive_circle
- ops.gpencil.primitive_curve
- ops.gpencil.primitive_line
- ops.gpencil.radius
- ops.gpencil.sculpt_clone
- ops.gpencil.sculpt_grab
- ops.gpencil.sculpt_pinch
- ops.gpencil.sculpt_push
- ops.gpencil.sculpt_randomize
- ops.gpencil.sculpt_smooth
- ops.gpencil.sculpt_strength
- ops.gpencil.sculpt_thickness
- ops.gpencil.sculpt_twist
- ops.gpencil.sculpt_weight
- ops.gpencil.stroke_cutter
- ops.mesh.bevel
- ops.mesh.bisect
- ops.mesh.dupli_extrude_cursor
- ops.mesh.extrude_faces_move
- ops.mesh.extrude_region_move
- ops.mesh.extrude_region_shrink_fatten
- ops.mesh.inset
- ops.mesh.knife_tool
- ops.mesh.loopcut_slide
- ops.mesh.offset_edge_loops_slide
- ops.mesh.polybuild_hover
- ops.mesh.primitive_cone_add_gizmo
- ops.mesh.primitive_cube_add_gizmo
- ops.mesh.primitive_cylinder_add_gizmo
- ops.mesh.primitive_grid_add_gizmo
- ops.mesh.primitive_sphere_add_gizmo
- ops.mesh.primitive_torus_add_gizmo
- ops.mesh.rip
- ops.mesh.rip_edge
- ops.mesh.spin
- ops.mesh.spin.duplicate
- ops.mesh.vertices_smooth
- ops.node.links_cut
- ops.paint.vertex_color_fill
- ops.paint.weight_fill
- ops.paint.weight_gradient
- ops.paint.weight_sample
- ops.paint.weight_sample_group
- ops.pose.breakdowner
- ops.pose.push
- ops.pose.relax
- ops.sculpt.border_hide
- ops.sculpt.border_mask
- ops.transform.bone_envelope
- ops.transform.bone_size
- ops.transform.edge_slide
- ops.transform.push_pull
- ops.transform.resize.cage
- ops.transform.resize
- ops.transform.rotate
- ops.transform.shear
- ops.transform.shrink_fatten
- ops.transform.tilt
- ops.transform.tosphere
- ops.transform.transform
- ops.transform.translate
- ops.transform.vert_slide
- ops.transform.vertex_random
- ops.view3d.ruler
- # END ICON_GEOM_NAMES
+ # BEGIN ICON_GEOM_NAMES
+ brush.gpencil_draw.draw
+ brush.gpencil_draw.erase
+ brush.gpencil_draw.fill
+ brush.paint_texture.airbrush
+ brush.paint_texture.clone
+ brush.paint_texture.draw
+ brush.paint_texture.fill
+ brush.paint_texture.mask
+ brush.paint_texture.masklort
+ brush.paint_texture.multiply
+ brush.paint_texture.smear
+ brush.paint_texture.soften
+ brush.paint_vertex.alpha
+ brush.paint_vertex.average
+ brush.paint_vertex.blur
+ brush.paint_vertex.draw
+ brush.paint_vertex.smear
+ brush.paint_weight.average
+ brush.paint_weight.blur
+ brush.paint_weight.draw
+ brush.paint_weight.mix
+ brush.paint_weight.smear
+ brush.particle.add
+ brush.particle.comb
+ brush.particle.cut
+ brush.particle.length
+ brush.particle.puff
+ brush.particle.smooth
+ brush.particle.weight
+ brush.sculpt.blob
+ brush.sculpt.clay
+ brush.sculpt.clay_strips
+ brush.sculpt.crease
+ brush.sculpt.draw
+ brush.sculpt.fill
+ brush.sculpt.flatten
+ brush.sculpt.grab
+ brush.sculpt.inflate
+ brush.sculpt.layer
+ brush.sculpt.mask
+ brush.sculpt.nudge
+ brush.sculpt.pinch
+ brush.sculpt.rotate
+ brush.sculpt.scrape
+ brush.sculpt.simplify
+ brush.sculpt.smooth
+ brush.sculpt.snake_hook
+ brush.sculpt.thumb
+ brush.uv_sculpt.grab
+ brush.uv_sculpt.pinch
+ brush.uv_sculpt.relax
+ none
+ ops.armature.bone.roll
+ ops.armature.extrude_cursor
+ ops.armature.extrude_move
+ ops.curve.draw
+ ops.curve.extrude_cursor
+ ops.curve.extrude_move
+ ops.curve.radius
+ ops.curve.vertex_random
+ ops.generic.cursor
+ ops.generic.select
+ ops.generic.select_box
+ ops.generic.select_circle
+ ops.generic.select_lasso
+ ops.gpencil.draw
+ ops.gpencil.draw.eraser
+ ops.gpencil.draw.line
+ ops.gpencil.draw.poly
+ ops.gpencil.edit_bend
+ ops.gpencil.edit_mirror
+ ops.gpencil.edit_shear
+ ops.gpencil.edit_to_sphere
+ ops.gpencil.extrude_move
+ ops.gpencil.primitive_arc
+ ops.gpencil.primitive_box
+ ops.gpencil.primitive_circle
+ ops.gpencil.primitive_curve
+ ops.gpencil.primitive_line
+ ops.gpencil.radius
+ ops.gpencil.sculpt_clone
+ ops.gpencil.sculpt_grab
+ ops.gpencil.sculpt_pinch
+ ops.gpencil.sculpt_push
+ ops.gpencil.sculpt_randomize
+ ops.gpencil.sculpt_smooth
+ ops.gpencil.sculpt_strength
+ ops.gpencil.sculpt_thickness
+ ops.gpencil.sculpt_twist
+ ops.gpencil.sculpt_weight
+ ops.gpencil.stroke_cutter
+ ops.mesh.bevel
+ ops.mesh.bisect
+ ops.mesh.dupli_extrude_cursor
+ ops.mesh.extrude_faces_move
+ ops.mesh.extrude_region_move
+ ops.mesh.extrude_region_shrink_fatten
+ ops.mesh.inset
+ ops.mesh.knife_tool
+ ops.mesh.loopcut_slide
+ ops.mesh.offset_edge_loops_slide
+ ops.mesh.polybuild_hover
+ ops.mesh.primitive_cone_add_gizmo
+ ops.mesh.primitive_cube_add_gizmo
+ ops.mesh.primitive_cylinder_add_gizmo
+ ops.mesh.primitive_grid_add_gizmo
+ ops.mesh.primitive_sphere_add_gizmo
+ ops.mesh.primitive_torus_add_gizmo
+ ops.mesh.rip
+ ops.mesh.rip_edge
+ ops.mesh.spin
+ ops.mesh.spin.duplicate
+ ops.mesh.vertices_smooth
+ ops.node.links_cut
+ ops.paint.vertex_color_fill
+ ops.paint.weight_fill
+ ops.paint.weight_gradient
+ ops.paint.weight_sample
+ ops.paint.weight_sample_group
+ ops.pose.breakdowner
+ ops.pose.push
+ ops.pose.relax
+ ops.sculpt.border_hide
+ ops.sculpt.border_mask
+ ops.transform.bone_envelope
+ ops.transform.bone_size
+ ops.transform.edge_slide
+ ops.transform.push_pull
+ ops.transform.resize.cage
+ ops.transform.resize
+ ops.transform.rotate
+ ops.transform.shear
+ ops.transform.shrink_fatten
+ ops.transform.tilt
+ ops.transform.tosphere
+ ops.transform.transform
+ ops.transform.translate
+ ops.transform.vert_slide
+ ops.transform.vertex_random
+ ops.view3d.ruler
+ # END ICON_GEOM_NAMES
)
data_to_c_simple(../../../../release/datafiles/bfont.pfb SRC)
@@ -761,89 +761,89 @@ 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)
+ # blender only (not player)
- if(NOT WITH_HEADLESS)
- # blender UI only
+ if(NOT WITH_HEADLESS)
+ # blender UI only
- # blends
- data_to_c_simple(../../../../release/datafiles/preview.blend SRC)
- data_to_c_simple(../../../../release/datafiles/preview_grease_pencil.blend SRC)
+ # blends
+ data_to_c_simple(../../../../release/datafiles/preview.blend SRC)
+ data_to_c_simple(../../../../release/datafiles/preview_grease_pencil.blend SRC)
- # images
- data_to_c_simple(../../../../release/datafiles/splash.png SRC)
- data_to_c_simple(../../../../release/datafiles/splash_2x.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
- #90 SRC)
+ # images
+ data_to_c_simple(../../../../release/datafiles/splash.png SRC)
+ data_to_c_simple(../../../../release/datafiles/splash_2x.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
+ #90 SRC)
- data_to_c_simple_icons(../../../../release/datafiles/blender_icons16 "icon16_" "${ICON_NAMES}" SRC)
- #data_to_c_simple(../../../../release/datafiles/blender_icons16.png SRC)
- #svg_to_png(../../../../release/datafiles/blender_icons.svg
- #../../../../release/datafiles/blender_icons32.png
- #180 SRC)
- data_to_c_simple_icons(../../../../release/datafiles/blender_icons32 "icon32_" "${ICON_NAMES}" SRC)
- #data_to_c_simple(../../../../release/datafiles/blender_icons32.png SRC)
- #svg_to_png(../../../../release/datafiles/prvicons.svg
- #../../../../release/datafiles/prvicons.png
- #90 SRC)
- data_to_c_simple(../../../../release/datafiles/prvicons.png SRC)
+ data_to_c_simple_icons(../../../../release/datafiles/blender_icons16 "icon16_" "${ICON_NAMES}" SRC)
+ #data_to_c_simple(../../../../release/datafiles/blender_icons16.png SRC)
+ #svg_to_png(../../../../release/datafiles/blender_icons.svg
+ #../../../../release/datafiles/blender_icons32.png
+ #180 SRC)
+ data_to_c_simple_icons(../../../../release/datafiles/blender_icons32 "icon32_" "${ICON_NAMES}" SRC)
+ #data_to_c_simple(../../../../release/datafiles/blender_icons32.png SRC)
+ #svg_to_png(../../../../release/datafiles/prvicons.svg
+ #../../../../release/datafiles/prvicons.png
+ #90 SRC)
+ data_to_c_simple(../../../../release/datafiles/prvicons.png SRC)
- # brushes
- data_to_c_simple(../../../../release/datafiles/brushicons/blob.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/blur.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/clay.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/claystrips.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/clone.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/crease.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/draw.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/fill.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/flatten.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/grab.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/inflate.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/layer.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/mask.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/mix.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/nudge.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/pinch.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/scrape.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/smear.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/smooth.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/snake_hook.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/soften.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/texdraw.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/texfill.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/texmask.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/thumb.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/twist.png SRC)
+ # brushes
+ data_to_c_simple(../../../../release/datafiles/brushicons/blob.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/blur.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/clay.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/claystrips.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/clone.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/crease.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/draw.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/fill.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/flatten.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/grab.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/inflate.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/layer.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/mask.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/mix.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/nudge.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/pinch.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/scrape.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/smear.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/smooth.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/snake_hook.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/soften.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/texdraw.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/texfill.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/texmask.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/thumb.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/twist.png SRC)
- # grease pencil sculpt
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_smooth.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_thickness.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_strength.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_grab.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_push.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_twist.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_pinch.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_randomize.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_clone.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_weight.png SRC)
+ # grease pencil sculpt
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_smooth.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_thickness.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_strength.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_grab.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_push.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_twist.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_pinch.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_randomize.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_clone.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_weight.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_pencil.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_pen.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_ink.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_inknoise.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_block.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_marker.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_fill.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_erase_soft.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_erase_hard.png SRC)
- data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_erase_stroke.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_pencil.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_pen.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_ink.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_inknoise.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_block.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_marker.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_fill.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_erase_soft.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_erase_hard.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_erase_stroke.png SRC)
- endif()
+ endif()
- data_to_c_simple(../../../../release/datafiles/startup.blend SRC)
+ data_to_c_simple(../../../../release/datafiles/startup.blend SRC)
endif()
unset(ICON_NAMES)
diff --git a/source/blender/editors/gizmo_library/CMakeLists.txt b/source/blender/editors/gizmo_library/CMakeLists.txt
index 0d2d9446889..8b035d3207d 100644
--- a/source/blender/editors/gizmo_library/CMakeLists.txt
+++ b/source/blender/editors/gizmo_library/CMakeLists.txt
@@ -17,45 +17,45 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../bmesh
- ../../depsgraph
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/eigen
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../bmesh
+ ../../depsgraph
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/eigen
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- gizmo_draw_utils.c
- gizmo_geometry.h
- gizmo_library_intern.h
- gizmo_library_presets.c
- gizmo_library_utils.c
- geometry/geom_arrow_gizmo.c
- geometry/geom_cube_gizmo.c
- geometry/geom_dial_gizmo.c
- gizmo_group_types/value2d_gizmo_group.c
- gizmo_types/arrow2d_gizmo.c
- gizmo_types/arrow3d_gizmo.c
- gizmo_types/blank3d_gizmo.c
- gizmo_types/button2d_gizmo.c
- gizmo_types/cage2d_gizmo.c
- gizmo_types/cage3d_gizmo.c
- gizmo_types/dial3d_gizmo.c
- gizmo_types/move3d_gizmo.c
- gizmo_types/primitive3d_gizmo.c
- gizmo_types/value2d_gizmo.c
+ gizmo_draw_utils.c
+ gizmo_geometry.h
+ gizmo_library_intern.h
+ gizmo_library_presets.c
+ gizmo_library_utils.c
+ geometry/geom_arrow_gizmo.c
+ geometry/geom_cube_gizmo.c
+ geometry/geom_dial_gizmo.c
+ gizmo_group_types/value2d_gizmo_group.c
+ gizmo_types/arrow2d_gizmo.c
+ gizmo_types/arrow3d_gizmo.c
+ gizmo_types/blank3d_gizmo.c
+ gizmo_types/button2d_gizmo.c
+ gizmo_types/cage2d_gizmo.c
+ gizmo_types/cage3d_gizmo.c
+ gizmo_types/dial3d_gizmo.c
+ gizmo_types/move3d_gizmo.c
+ gizmo_types/primitive3d_gizmo.c
+ gizmo_types/value2d_gizmo.c
)
set(LIB
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 d62d397c783..90196988d94 100644
--- a/source/blender/editors/gizmo_library/geometry/geom_arrow_gizmo.c
+++ b/source/blender/editors/gizmo_library/geometry/geom_arrow_gizmo.c
@@ -24,114 +24,50 @@
#include "../gizmo_geometry.h"
static float verts[][3] = {
- {-0.000000, 0.012320, 0.000000},
- {-0.000000, 0.012320, 0.974306},
- {0.008711, 0.008711, 0.000000},
- {0.008711, 0.008711, 0.974306},
- {0.012320, -0.000000, 0.000000},
- {0.012320, -0.000000, 0.974306},
- {0.008711, -0.008711, 0.000000},
- {0.008711, -0.008711, 0.974306},
- {-0.000000, -0.012320, 0.000000},
- {-0.000000, -0.012320, 0.974306},
- {-0.008711, -0.008711, 0.000000},
- {-0.008711, -0.008711, 0.974306},
- {-0.012320, 0.000000, 0.000000},
- {-0.012320, 0.000000, 0.974306},
- {-0.008711, 0.008711, 0.000000},
- {-0.008711, 0.008711, 0.974306},
- {0.000000, 0.072555, 0.974306},
- {0.051304, 0.051304, 0.974306},
- {0.072555, -0.000000, 0.974306},
- {0.051304, -0.051304, 0.974306},
- {-0.000000, -0.072555, 0.974306},
- {-0.051304, -0.051304, 0.974306},
- {-0.072555, 0.000000, 0.974306},
- {-0.051304, 0.051304, 0.974306},
- {0.000000, -0.000000, 1.268098},
+ {-0.000000, 0.012320, 0.000000}, {-0.000000, 0.012320, 0.974306},
+ {0.008711, 0.008711, 0.000000}, {0.008711, 0.008711, 0.974306},
+ {0.012320, -0.000000, 0.000000}, {0.012320, -0.000000, 0.974306},
+ {0.008711, -0.008711, 0.000000}, {0.008711, -0.008711, 0.974306},
+ {-0.000000, -0.012320, 0.000000}, {-0.000000, -0.012320, 0.974306},
+ {-0.008711, -0.008711, 0.000000}, {-0.008711, -0.008711, 0.974306},
+ {-0.012320, 0.000000, 0.000000}, {-0.012320, 0.000000, 0.974306},
+ {-0.008711, 0.008711, 0.000000}, {-0.008711, 0.008711, 0.974306},
+ {0.000000, 0.072555, 0.974306}, {0.051304, 0.051304, 0.974306},
+ {0.072555, -0.000000, 0.974306}, {0.051304, -0.051304, 0.974306},
+ {-0.000000, -0.072555, 0.974306}, {-0.051304, -0.051304, 0.974306},
+ {-0.072555, 0.000000, 0.974306}, {-0.051304, 0.051304, 0.974306},
+ {0.000000, -0.000000, 1.268098},
};
static float normals[][3] = {
- {0.000000, 0.776360, -0.630238},
- {0.000000, 0.594348, -0.804163},
- {0.548967, 0.548967, -0.630238},
- {0.420270, 0.420270, -0.804163},
- {0.776360, 0.000000, -0.630238},
- {0.594378, 0.000000, -0.804163},
- {0.548967, -0.548967, -0.630238},
- {0.420270, -0.420270, -0.804163},
- {0.000000, -0.776360, -0.630238},
- {0.000000, -0.594378, -0.804163},
- {-0.548967, -0.548967, -0.630238},
- {-0.420270, -0.420270, -0.804163},
- {-0.776360, 0.000000, -0.630238},
- {-0.594378, 0.000000, -0.804163},
- {-0.548967, 0.548967, -0.630238},
- {-0.420270, 0.420270, -0.804163},
- {0.000000, 0.843226, -0.537492},
- {0.596271, 0.596271, -0.537492},
- {0.843226, 0.000000, -0.537492},
- {0.596271, -0.596271, -0.537492},
- {0.000000, -0.843226, -0.537492},
- {-0.596271, -0.596271, -0.537492},
- {-0.843226, 0.000000, -0.537492},
- {-0.596271, 0.596271, -0.537492},
- {0.000000, 0.000000, 1.000000},
+ {0.000000, 0.776360, -0.630238}, {0.000000, 0.594348, -0.804163},
+ {0.548967, 0.548967, -0.630238}, {0.420270, 0.420270, -0.804163},
+ {0.776360, 0.000000, -0.630238}, {0.594378, 0.000000, -0.804163},
+ {0.548967, -0.548967, -0.630238}, {0.420270, -0.420270, -0.804163},
+ {0.000000, -0.776360, -0.630238}, {0.000000, -0.594378, -0.804163},
+ {-0.548967, -0.548967, -0.630238}, {-0.420270, -0.420270, -0.804163},
+ {-0.776360, 0.000000, -0.630238}, {-0.594378, 0.000000, -0.804163},
+ {-0.548967, 0.548967, -0.630238}, {-0.420270, 0.420270, -0.804163},
+ {0.000000, 0.843226, -0.537492}, {0.596271, 0.596271, -0.537492},
+ {0.843226, 0.000000, -0.537492}, {0.596271, -0.596271, -0.537492},
+ {0.000000, -0.843226, -0.537492}, {-0.596271, -0.596271, -0.537492},
+ {-0.843226, 0.000000, -0.537492}, {-0.596271, 0.596271, -0.537492},
+ {0.000000, 0.000000, 1.000000},
};
static unsigned short 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,
- 20, 19, 24,
- 18, 17, 24,
- 0, 1, 2,
- 2, 3, 4,
- 4, 5, 6,
- 6, 7, 8,
- 8, 9, 10,
- 10, 11, 12,
- 7, 5, 19,
- 14, 15, 0,
- 12, 13, 14,
- 14, 0, 2,
- 2, 4, 6,
- 6, 8, 10,
- 10, 12, 14,
- 14, 2, 6,
- 13, 11, 22,
- 9, 7, 20,
- 15, 13, 23,
- 5, 3, 18,
- 11, 9, 21,
- 1, 15, 16,
- 3, 1, 17,
+ 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,
+ 20, 19, 24, 18, 17, 24, 0, 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 11,
+ 12, 7, 5, 19, 14, 15, 0, 12, 13, 14, 14, 0, 2, 2, 4, 6, 6, 8, 10, 10, 12, 14, 14,
+ 2, 6, 13, 11, 22, 9, 7, 20, 15, 13, 23, 5, 3, 18, 11, 9, 21, 1, 15, 16, 3, 1, 17,
};
GizmoGeomInfo wm_gizmo_geom_data_arrow = {
- .nverts = 25,
- .ntris = 46,
- .verts = verts,
- .normals = normals,
- .indices = indices,
+ .nverts = 25,
+ .ntris = 46,
+ .verts = verts,
+ .normals = normals,
+ .indices = indices,
};
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 e89d20a41bd..ea1a3147148 100644
--- a/source/blender/editors/gizmo_library/geometry/geom_cube_gizmo.c
+++ b/source/blender/editors/gizmo_library/geometry/geom_cube_gizmo.c
@@ -24,46 +24,36 @@
#include "../gizmo_geometry.h"
static const float verts[][3] = {
- {1.000000, 1.000000, -1.000000},
- {1.000000, -1.000000, -1.000000},
- {-1.000000, -1.000000, -1.000000},
- {-1.000000, 1.000000, -1.000000},
- {1.000000, 1.000000, 1.000000},
- {0.999999, -1.000001, 1.000000},
- {-1.000000, -1.000000, 1.000000},
- {-1.000000, 1.000000, 1.000000},
+ {1.000000, 1.000000, -1.000000},
+ {1.000000, -1.000000, -1.000000},
+ {-1.000000, -1.000000, -1.000000},
+ {-1.000000, 1.000000, -1.000000},
+ {1.000000, 1.000000, 1.000000},
+ {0.999999, -1.000001, 1.000000},
+ {-1.000000, -1.000000, 1.000000},
+ {-1.000000, 1.000000, 1.000000},
};
static const float normals[][3] = {
- {0.577349, 0.577349, -0.577349},
- {0.577349, -0.577349, -0.577349},
- {-0.577349, -0.577349, -0.577349},
- {-0.577349, 0.577349, -0.577349},
- {0.577349, 0.577349, 0.577349},
- {0.577349, -0.577349, 0.577349},
- {-0.577349, -0.577349, 0.577349},
- {-0.577349, 0.577349, 0.577349},
+ {0.577349, 0.577349, -0.577349},
+ {0.577349, -0.577349, -0.577349},
+ {-0.577349, -0.577349, -0.577349},
+ {-0.577349, 0.577349, -0.577349},
+ {0.577349, 0.577349, 0.577349},
+ {0.577349, -0.577349, 0.577349},
+ {-0.577349, -0.577349, 0.577349},
+ {-0.577349, 0.577349, 0.577349},
};
static const unsigned short 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,
+ 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,
};
GizmoGeomInfo wm_gizmo_geom_data_cube = {
- .nverts = 8,
- .ntris = 12,
- .verts = verts,
- .normals = normals,
- .indices = indices,
+ .nverts = 8,
+ .ntris = 12,
+ .verts = verts,
+ .normals = normals,
+ .indices = indices,
};
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 5ead50f67d1..273f957e9b6 100644
--- a/source/blender/editors/gizmo_library/geometry/geom_dial_gizmo.c
+++ b/source/blender/editors/gizmo_library/geometry/geom_dial_gizmo.c
@@ -24,786 +24,271 @@
#include "../gizmo_geometry.h"
static const float verts[][3] = {
- {1.034000, 0.000000, 0.000000},
- {1.017000, 0.000000, 0.029445},
- {0.983000, 0.000000, 0.029445},
- {0.966000, 0.000000, 0.000000},
- {0.983000, 0.000000, -0.029445},
- {1.017000, 0.000000, -0.029445},
- {1.014132, 0.201723, 0.000000},
- {0.997459, 0.198407, 0.029445},
- {0.964112, 0.191774, 0.029445},
- {0.947439, 0.188457, 0.000000},
- {0.964112, 0.191774, -0.029445},
- {0.997459, 0.198407, -0.029445},
- {0.955292, 0.395695, 0.000000},
- {0.939586, 0.389189, 0.029445},
- {0.908174, 0.376178, 0.029445},
- {0.892468, 0.369672, 0.000000},
- {0.908174, 0.376178, -0.029445},
- {0.939586, 0.389189, -0.029445},
- {0.859740, 0.574460, 0.000000},
- {0.845605, 0.565015, 0.029445},
- {0.817335, 0.546126, 0.029445},
- {0.803200, 0.536681, 0.000000},
- {0.817335, 0.546126, -0.029445},
- {0.845605, 0.565015, -0.029445},
- {0.731148, 0.731148, 0.000000},
- {0.719128, 0.719128, 0.029445},
- {0.695086, 0.695086, 0.029445},
- {0.683065, 0.683065, 0.000000},
- {0.695086, 0.695086, -0.029445},
- {0.719128, 0.719128, -0.029445},
- {0.574460, 0.859740, 0.000000},
- {0.565015, 0.845605, 0.029445},
- {0.546125, 0.817335, 0.029445},
- {0.536681, 0.803200, 0.000000},
- {0.546125, 0.817335, -0.029445},
- {0.565015, 0.845605, -0.029445},
- {0.395695, 0.955291, 0.000000},
- {0.389189, 0.939585, 0.029445},
- {0.376178, 0.908173, 0.029445},
- {0.369672, 0.892467, 0.000000},
- {0.376178, 0.908173, -0.029445},
- {0.389189, 0.939585, -0.029445},
- {0.201724, 1.014132, 0.000000},
- {0.198407, 0.997459, 0.029445},
- {0.191774, 0.964112, 0.029445},
- {0.188457, 0.947439, 0.000000},
- {0.191774, 0.964112, -0.029445},
- {0.198407, 0.997459, -0.029445},
- {0.000000, 1.034000, 0.000000},
- {0.000000, 1.017000, 0.029445},
- {0.000000, 0.983000, 0.029445},
- {0.000000, 0.966000, 0.000000},
- {0.000000, 0.983000, -0.029445},
- {0.000000, 1.017000, -0.029445},
- {-0.201723, 1.014132, 0.000000},
- {-0.198407, 0.997459, 0.029445},
- {-0.191774, 0.964112, 0.029445},
- {-0.188457, 0.947439, 0.000000},
- {-0.191774, 0.964112, -0.029445},
- {-0.198407, 0.997459, -0.029445},
- {-0.395695, 0.955291, 0.000000},
- {-0.389189, 0.939585, 0.029445},
- {-0.376178, 0.908174, 0.029445},
- {-0.369672, 0.892468, 0.000000},
- {-0.376178, 0.908174, -0.029445},
- {-0.389189, 0.939585, -0.029445},
- {-0.574459, 0.859740, 0.000000},
- {-0.565015, 0.845605, 0.029445},
- {-0.546125, 0.817335, 0.029445},
- {-0.536681, 0.803200, 0.000000},
- {-0.546125, 0.817335, -0.029445},
- {-0.565015, 0.845605, -0.029445},
- {-0.731149, 0.731148, 0.000000},
- {-0.719128, 0.719127, 0.029445},
- {-0.695086, 0.695086, 0.029445},
- {-0.683065, 0.683065, 0.000000},
- {-0.695086, 0.695086, -0.029445},
- {-0.719128, 0.719127, -0.029445},
- {-0.859740, 0.574460, 0.000000},
- {-0.845604, 0.565015, 0.029445},
- {-0.817335, 0.546126, 0.029445},
- {-0.803200, 0.536681, 0.000000},
- {-0.817335, 0.546126, -0.029445},
- {-0.845604, 0.565015, -0.029445},
- {-0.955291, 0.395695, 0.000000},
- {-0.939585, 0.389189, 0.029445},
- {-0.908173, 0.376178, 0.029445},
- {-0.892468, 0.369672, 0.000000},
- {-0.908173, 0.376178, -0.029445},
- {-0.939585, 0.389189, -0.029445},
- {-1.014132, 0.201723, 0.000000},
- {-0.997459, 0.198407, 0.029445},
- {-0.964112, 0.191774, 0.029445},
- {-0.947439, 0.188457, 0.000000},
- {-0.964112, 0.191774, -0.029445},
- {-0.997459, 0.198407, -0.029445},
- {-1.034000, 0.000000, 0.000000},
- {-1.017000, 0.000000, 0.029445},
- {-0.983000, 0.000000, 0.029445},
- {-0.966000, 0.000000, 0.000000},
- {-0.983000, 0.000000, -0.029445},
- {-1.017000, 0.000000, -0.029445},
- {-1.014132, -0.201723, 0.000000},
- {-0.997459, -0.198407, 0.029445},
- {-0.964112, -0.191774, 0.029445},
- {-0.947439, -0.188457, 0.000000},
- {-0.964112, -0.191774, -0.029445},
- {-0.997459, -0.198407, -0.029445},
- {-0.955292, -0.395694, 0.000000},
- {-0.939586, -0.389189, 0.029445},
- {-0.908174, -0.376177, 0.029445},
- {-0.892468, -0.369672, 0.000000},
- {-0.908174, -0.376177, -0.029445},
- {-0.939586, -0.389189, -0.029445},
- {-0.859740, -0.574460, 0.000000},
- {-0.845604, -0.565015, 0.029445},
- {-0.817335, -0.546126, 0.029445},
- {-0.803200, -0.536681, 0.000000},
- {-0.817335, -0.546126, -0.029445},
- {-0.845604, -0.565015, -0.029445},
- {-0.731149, -0.731148, 0.000000},
- {-0.719128, -0.719127, 0.029445},
- {-0.695086, -0.695086, 0.029445},
- {-0.683065, -0.683065, 0.000000},
- {-0.695086, -0.695086, -0.029445},
- {-0.719128, -0.719127, -0.029445},
- {-0.574460, -0.859739, 0.000000},
- {-0.565015, -0.845604, 0.029445},
- {-0.546126, -0.817334, 0.029445},
- {-0.536681, -0.803199, 0.000000},
- {-0.546126, -0.817334, -0.029445},
- {-0.565015, -0.845604, -0.029445},
- {-0.395695, -0.955291, 0.000000},
- {-0.389189, -0.939585, 0.029445},
- {-0.376178, -0.908174, 0.029445},
- {-0.369672, -0.892468, 0.000000},
- {-0.376178, -0.908174, -0.029445},
- {-0.389189, -0.939585, -0.029445},
- {-0.201724, -1.014132, 0.000000},
- {-0.198407, -0.997459, 0.029445},
- {-0.191774, -0.964112, 0.029445},
- {-0.188458, -0.947438, 0.000000},
- {-0.191774, -0.964112, -0.029445},
- {-0.198407, -0.997459, -0.029445},
- {0.000000, -1.034000, 0.000000},
- {0.000000, -1.017000, 0.029445},
- {0.000000, -0.983000, 0.029445},
- {0.000000, -0.966000, 0.000000},
- {0.000000, -0.983000, -0.029445},
- {0.000000, -1.017000, -0.029445},
- {0.201723, -1.014132, 0.000000},
- {0.198407, -0.997459, 0.029445},
- {0.191773, -0.964112, 0.029445},
- {0.188457, -0.947439, 0.000000},
- {0.191773, -0.964112, -0.029445},
- {0.198407, -0.997459, -0.029445},
- {0.395695, -0.955291, 0.000000},
- {0.389189, -0.939585, 0.029445},
- {0.376178, -0.908173, 0.029445},
- {0.369672, -0.892467, 0.000000},
- {0.376178, -0.908173, -0.029445},
- {0.389189, -0.939585, -0.029445},
- {0.574460, -0.859740, 0.000000},
- {0.565015, -0.845605, 0.029445},
- {0.546125, -0.817335, 0.029445},
- {0.536681, -0.803200, 0.000000},
- {0.546125, -0.817335, -0.029445},
- {0.565015, -0.845605, -0.029445},
- {0.731148, -0.731149, 0.000000},
- {0.719127, -0.719128, 0.029445},
- {0.695086, -0.695086, 0.029445},
- {0.683065, -0.683066, 0.000000},
- {0.695086, -0.695086, -0.029445},
- {0.719127, -0.719128, -0.029445},
- {0.859740, -0.574460, 0.000000},
- {0.845605, -0.565015, 0.029445},
- {0.817335, -0.546126, 0.029445},
- {0.803200, -0.536681, 0.000000},
- {0.817335, -0.546126, -0.029445},
- {0.845605, -0.565015, -0.029445},
- {0.955291, -0.395695, 0.000000},
- {0.939585, -0.389189, 0.029445},
- {0.908173, -0.376178, 0.029445},
- {0.892467, -0.369673, 0.000000},
- {0.908173, -0.376178, -0.029445},
- {0.939585, -0.389189, -0.029445},
- {1.014132, -0.201723, 0.000000},
- {0.997459, -0.198407, 0.029445},
- {0.964112, -0.191774, 0.029445},
- {0.947439, -0.188457, 0.000000},
- {0.964112, -0.191774, -0.029445},
- {0.997459, -0.198407, -0.029445},
+ {1.034000, 0.000000, 0.000000}, {1.017000, 0.000000, 0.029445},
+ {0.983000, 0.000000, 0.029445}, {0.966000, 0.000000, 0.000000},
+ {0.983000, 0.000000, -0.029445}, {1.017000, 0.000000, -0.029445},
+ {1.014132, 0.201723, 0.000000}, {0.997459, 0.198407, 0.029445},
+ {0.964112, 0.191774, 0.029445}, {0.947439, 0.188457, 0.000000},
+ {0.964112, 0.191774, -0.029445}, {0.997459, 0.198407, -0.029445},
+ {0.955292, 0.395695, 0.000000}, {0.939586, 0.389189, 0.029445},
+ {0.908174, 0.376178, 0.029445}, {0.892468, 0.369672, 0.000000},
+ {0.908174, 0.376178, -0.029445}, {0.939586, 0.389189, -0.029445},
+ {0.859740, 0.574460, 0.000000}, {0.845605, 0.565015, 0.029445},
+ {0.817335, 0.546126, 0.029445}, {0.803200, 0.536681, 0.000000},
+ {0.817335, 0.546126, -0.029445}, {0.845605, 0.565015, -0.029445},
+ {0.731148, 0.731148, 0.000000}, {0.719128, 0.719128, 0.029445},
+ {0.695086, 0.695086, 0.029445}, {0.683065, 0.683065, 0.000000},
+ {0.695086, 0.695086, -0.029445}, {0.719128, 0.719128, -0.029445},
+ {0.574460, 0.859740, 0.000000}, {0.565015, 0.845605, 0.029445},
+ {0.546125, 0.817335, 0.029445}, {0.536681, 0.803200, 0.000000},
+ {0.546125, 0.817335, -0.029445}, {0.565015, 0.845605, -0.029445},
+ {0.395695, 0.955291, 0.000000}, {0.389189, 0.939585, 0.029445},
+ {0.376178, 0.908173, 0.029445}, {0.369672, 0.892467, 0.000000},
+ {0.376178, 0.908173, -0.029445}, {0.389189, 0.939585, -0.029445},
+ {0.201724, 1.014132, 0.000000}, {0.198407, 0.997459, 0.029445},
+ {0.191774, 0.964112, 0.029445}, {0.188457, 0.947439, 0.000000},
+ {0.191774, 0.964112, -0.029445}, {0.198407, 0.997459, -0.029445},
+ {0.000000, 1.034000, 0.000000}, {0.000000, 1.017000, 0.029445},
+ {0.000000, 0.983000, 0.029445}, {0.000000, 0.966000, 0.000000},
+ {0.000000, 0.983000, -0.029445}, {0.000000, 1.017000, -0.029445},
+ {-0.201723, 1.014132, 0.000000}, {-0.198407, 0.997459, 0.029445},
+ {-0.191774, 0.964112, 0.029445}, {-0.188457, 0.947439, 0.000000},
+ {-0.191774, 0.964112, -0.029445}, {-0.198407, 0.997459, -0.029445},
+ {-0.395695, 0.955291, 0.000000}, {-0.389189, 0.939585, 0.029445},
+ {-0.376178, 0.908174, 0.029445}, {-0.369672, 0.892468, 0.000000},
+ {-0.376178, 0.908174, -0.029445}, {-0.389189, 0.939585, -0.029445},
+ {-0.574459, 0.859740, 0.000000}, {-0.565015, 0.845605, 0.029445},
+ {-0.546125, 0.817335, 0.029445}, {-0.536681, 0.803200, 0.000000},
+ {-0.546125, 0.817335, -0.029445}, {-0.565015, 0.845605, -0.029445},
+ {-0.731149, 0.731148, 0.000000}, {-0.719128, 0.719127, 0.029445},
+ {-0.695086, 0.695086, 0.029445}, {-0.683065, 0.683065, 0.000000},
+ {-0.695086, 0.695086, -0.029445}, {-0.719128, 0.719127, -0.029445},
+ {-0.859740, 0.574460, 0.000000}, {-0.845604, 0.565015, 0.029445},
+ {-0.817335, 0.546126, 0.029445}, {-0.803200, 0.536681, 0.000000},
+ {-0.817335, 0.546126, -0.029445}, {-0.845604, 0.565015, -0.029445},
+ {-0.955291, 0.395695, 0.000000}, {-0.939585, 0.389189, 0.029445},
+ {-0.908173, 0.376178, 0.029445}, {-0.892468, 0.369672, 0.000000},
+ {-0.908173, 0.376178, -0.029445}, {-0.939585, 0.389189, -0.029445},
+ {-1.014132, 0.201723, 0.000000}, {-0.997459, 0.198407, 0.029445},
+ {-0.964112, 0.191774, 0.029445}, {-0.947439, 0.188457, 0.000000},
+ {-0.964112, 0.191774, -0.029445}, {-0.997459, 0.198407, -0.029445},
+ {-1.034000, 0.000000, 0.000000}, {-1.017000, 0.000000, 0.029445},
+ {-0.983000, 0.000000, 0.029445}, {-0.966000, 0.000000, 0.000000},
+ {-0.983000, 0.000000, -0.029445}, {-1.017000, 0.000000, -0.029445},
+ {-1.014132, -0.201723, 0.000000}, {-0.997459, -0.198407, 0.029445},
+ {-0.964112, -0.191774, 0.029445}, {-0.947439, -0.188457, 0.000000},
+ {-0.964112, -0.191774, -0.029445}, {-0.997459, -0.198407, -0.029445},
+ {-0.955292, -0.395694, 0.000000}, {-0.939586, -0.389189, 0.029445},
+ {-0.908174, -0.376177, 0.029445}, {-0.892468, -0.369672, 0.000000},
+ {-0.908174, -0.376177, -0.029445}, {-0.939586, -0.389189, -0.029445},
+ {-0.859740, -0.574460, 0.000000}, {-0.845604, -0.565015, 0.029445},
+ {-0.817335, -0.546126, 0.029445}, {-0.803200, -0.536681, 0.000000},
+ {-0.817335, -0.546126, -0.029445}, {-0.845604, -0.565015, -0.029445},
+ {-0.731149, -0.731148, 0.000000}, {-0.719128, -0.719127, 0.029445},
+ {-0.695086, -0.695086, 0.029445}, {-0.683065, -0.683065, 0.000000},
+ {-0.695086, -0.695086, -0.029445}, {-0.719128, -0.719127, -0.029445},
+ {-0.574460, -0.859739, 0.000000}, {-0.565015, -0.845604, 0.029445},
+ {-0.546126, -0.817334, 0.029445}, {-0.536681, -0.803199, 0.000000},
+ {-0.546126, -0.817334, -0.029445}, {-0.565015, -0.845604, -0.029445},
+ {-0.395695, -0.955291, 0.000000}, {-0.389189, -0.939585, 0.029445},
+ {-0.376178, -0.908174, 0.029445}, {-0.369672, -0.892468, 0.000000},
+ {-0.376178, -0.908174, -0.029445}, {-0.389189, -0.939585, -0.029445},
+ {-0.201724, -1.014132, 0.000000}, {-0.198407, -0.997459, 0.029445},
+ {-0.191774, -0.964112, 0.029445}, {-0.188458, -0.947438, 0.000000},
+ {-0.191774, -0.964112, -0.029445}, {-0.198407, -0.997459, -0.029445},
+ {0.000000, -1.034000, 0.000000}, {0.000000, -1.017000, 0.029445},
+ {0.000000, -0.983000, 0.029445}, {0.000000, -0.966000, 0.000000},
+ {0.000000, -0.983000, -0.029445}, {0.000000, -1.017000, -0.029445},
+ {0.201723, -1.014132, 0.000000}, {0.198407, -0.997459, 0.029445},
+ {0.191773, -0.964112, 0.029445}, {0.188457, -0.947439, 0.000000},
+ {0.191773, -0.964112, -0.029445}, {0.198407, -0.997459, -0.029445},
+ {0.395695, -0.955291, 0.000000}, {0.389189, -0.939585, 0.029445},
+ {0.376178, -0.908173, 0.029445}, {0.369672, -0.892467, 0.000000},
+ {0.376178, -0.908173, -0.029445}, {0.389189, -0.939585, -0.029445},
+ {0.574460, -0.859740, 0.000000}, {0.565015, -0.845605, 0.029445},
+ {0.546125, -0.817335, 0.029445}, {0.536681, -0.803200, 0.000000},
+ {0.546125, -0.817335, -0.029445}, {0.565015, -0.845605, -0.029445},
+ {0.731148, -0.731149, 0.000000}, {0.719127, -0.719128, 0.029445},
+ {0.695086, -0.695086, 0.029445}, {0.683065, -0.683066, 0.000000},
+ {0.695086, -0.695086, -0.029445}, {0.719127, -0.719128, -0.029445},
+ {0.859740, -0.574460, 0.000000}, {0.845605, -0.565015, 0.029445},
+ {0.817335, -0.546126, 0.029445}, {0.803200, -0.536681, 0.000000},
+ {0.817335, -0.546126, -0.029445}, {0.845605, -0.565015, -0.029445},
+ {0.955291, -0.395695, 0.000000}, {0.939585, -0.389189, 0.029445},
+ {0.908173, -0.376178, 0.029445}, {0.892467, -0.369673, 0.000000},
+ {0.908173, -0.376178, -0.029445}, {0.939585, -0.389189, -0.029445},
+ {1.014132, -0.201723, 0.000000}, {0.997459, -0.198407, 0.029445},
+ {0.964112, -0.191774, 0.029445}, {0.947439, -0.188457, 0.000000},
+ {0.964112, -0.191774, -0.029445}, {0.997459, -0.198407, -0.029445},
};
static const float normals[][3] = {
- {1.000000, 0.000000, 0.000000},
- {0.522691, 0.000000, 0.852504},
- {-0.475845, 0.000000, 0.879513},
- {-1.000000, 0.000000, 0.000000},
- {-0.475845, 0.000000, -0.879513},
- {0.522691, 0.000000, -0.852504},
- {0.980773, 0.195074, 0.000000},
- {0.512650, 0.101962, 0.852504},
- {-0.466689, -0.092807, 0.879513},
- {-0.980773, -0.195074, 0.000000},
- {-0.466689, -0.092807, -0.879513},
- {0.512650, 0.101962, -0.852504},
- {0.923856, 0.382672, 0.000000},
- {0.482894, 0.200018, 0.852504},
- {-0.439619, -0.182073, 0.879513},
- {-0.923856, -0.382672, 0.000000},
- {-0.439619, -0.182073, -0.879513},
- {0.482894, 0.200018, -0.852504},
- {0.831446, 0.555559, 0.000000},
- {0.434614, 0.290384, 0.852504},
- {-0.395642, -0.264351, 0.879513},
- {-0.831446, -0.555559, 0.000000},
- {-0.395642, -0.264351, -0.879513},
- {0.434614, 0.290384, -0.852504},
- {0.707083, 0.707083, 0.000000},
- {0.369610, 0.369610, 0.852504},
- {-0.336467, -0.336467, 0.879513},
- {-0.707083, -0.707083, 0.000000},
- {-0.336467, -0.336467, -0.879513},
- {0.369610, 0.369610, -0.852504},
- {0.555559, 0.831446, 0.000000},
- {0.290384, 0.434614, 0.852504},
- {-0.264351, -0.395642, 0.879513},
- {-0.555559, -0.831446, 0.000000},
- {-0.264351, -0.395642, -0.879513},
- {0.290384, 0.434614, -0.852504},
- {0.382672, 0.923856, 0.000000},
- {0.200018, 0.482894, 0.852504},
- {-0.182073, -0.439619, 0.879513},
- {-0.382672, -0.923856, 0.000000},
- {-0.182073, -0.439619, -0.879513},
- {0.200018, 0.482894, -0.852504},
- {0.195074, 0.980773, 0.000000},
- {0.101962, 0.512650, 0.852504},
- {-0.092807, -0.466689, 0.879513},
- {-0.195074, -0.980773, 0.000000},
- {-0.092807, -0.466689, -0.879513},
- {0.101962, 0.512650, -0.852504},
- {0.000000, 1.000000, 0.000000},
- {0.000000, 0.522691, 0.852504},
- {0.000000, -0.475845, 0.879513},
- {0.000000, -1.000000, 0.000000},
- {0.000000, -0.475845, -0.879513},
- {0.000000, 0.522691, -0.852504},
- {-0.195074, 0.980773, 0.000000},
- {-0.101962, 0.512650, 0.852504},
- {0.092807, -0.466689, 0.879513},
- {0.195074, -0.980773, 0.000000},
- {0.092807, -0.466689, -0.879513},
- {-0.101962, 0.512650, -0.852504},
- {-0.382672, 0.923856, 0.000000},
- {-0.200018, 0.482894, 0.852504},
- {0.182073, -0.439619, 0.879513},
- {0.382672, -0.923856, 0.000000},
- {0.182073, -0.439619, -0.879513},
- {-0.200018, 0.482894, -0.852504},
- {-0.555559, 0.831446, 0.000000},
- {-0.290384, 0.434614, 0.852504},
- {0.264351, -0.395642, 0.879513},
- {0.555559, -0.831446, 0.000000},
- {0.264351, -0.395642, -0.879513},
- {-0.290384, 0.434614, -0.852504},
- {-0.707083, 0.707083, 0.000000},
- {-0.369610, 0.369610, 0.852504},
- {0.336467, -0.336467, 0.879513},
- {0.707083, -0.707083, 0.000000},
- {0.336467, -0.336467, -0.879513},
- {-0.369610, 0.369610, -0.852504},
- {-0.831446, 0.555559, 0.000000},
- {-0.434614, 0.290384, 0.852504},
- {0.395642, -0.264351, 0.879513},
- {0.831446, -0.555559, 0.000000},
- {0.395642, -0.264351, -0.879513},
- {-0.434614, 0.290384, -0.852504},
- {-0.923856, 0.382672, 0.000000},
- {-0.482894, 0.200018, 0.852504},
- {0.439619, -0.182073, 0.879513},
- {0.923856, -0.382672, 0.000000},
- {0.439619, -0.182073, -0.879513},
- {-0.482894, 0.200018, -0.852504},
- {-0.980773, 0.195074, 0.000000},
- {-0.512650, 0.101962, 0.852504},
- {0.466689, -0.092807, 0.879513},
- {0.980773, -0.195074, 0.000000},
- {0.466689, -0.092807, -0.879513},
- {-0.512650, 0.101962, -0.852504},
- {-1.000000, 0.000000, 0.000000},
- {-0.522691, 0.000000, 0.852504},
- {0.475845, 0.000000, 0.879513},
- {1.000000, 0.000000, 0.000000},
- {0.475845, 0.000000, -0.879513},
- {-0.522691, 0.000000, -0.852504},
- {-0.980773, -0.195074, 0.000000},
- {-0.512650, -0.101962, 0.852504},
- {0.466689, 0.092807, 0.879513},
- {0.980773, 0.195074, 0.000000},
- {0.466689, 0.092807, -0.879513},
- {-0.512650, -0.101962, -0.852504},
- {-0.923856, -0.382672, 0.000000},
- {-0.482894, -0.200018, 0.852504},
- {0.439619, 0.182073, 0.879513},
- {0.923856, 0.382672, 0.000000},
- {0.439619, 0.182073, -0.879513},
- {-0.482894, -0.200018, -0.852504},
- {-0.831446, -0.555559, 0.000000},
- {-0.434614, -0.290384, 0.852504},
- {0.395642, 0.264351, 0.879513},
- {0.831446, 0.555559, 0.000000},
- {0.395642, 0.264351, -0.879513},
- {-0.434614, -0.290384, -0.852504},
- {-0.707083, -0.707083, 0.000000},
- {-0.369610, -0.369610, 0.852504},
- {0.336467, 0.336467, 0.879513},
- {0.707083, 0.707083, 0.000000},
- {0.336467, 0.336467, -0.879513},
- {-0.369610, -0.369610, -0.852504},
- {-0.555559, -0.831446, 0.000000},
- {-0.290384, -0.434614, 0.852504},
- {0.264351, 0.395642, 0.879513},
- {0.555559, 0.831446, 0.000000},
- {0.264351, 0.395642, -0.879513},
- {-0.290384, -0.434614, -0.852504},
- {-0.382672, -0.923856, 0.000000},
- {-0.200018, -0.482894, 0.852504},
- {0.182073, 0.439619, 0.879513},
- {0.382672, 0.923856, 0.000000},
- {0.182073, 0.439619, -0.879513},
- {-0.200018, -0.482894, -0.852504},
- {-0.195074, -0.980773, 0.000000},
- {-0.101962, -0.512650, 0.852504},
- {0.092807, 0.466689, 0.879513},
- {0.195074, 0.980773, 0.000000},
- {0.092807, 0.466689, -0.879513},
- {-0.101962, -0.512650, -0.852504},
- {0.000000, -1.000000, 0.000000},
- {0.000000, -0.522691, 0.852504},
- {0.000000, 0.475845, 0.879513},
- {0.000000, 1.000000, 0.000000},
- {0.000000, 0.475845, -0.879513},
- {0.000000, -0.522691, -0.852504},
- {0.195074, -0.980773, 0.000000},
- {0.101962, -0.512650, 0.852504},
- {-0.092807, 0.466689, 0.879513},
- {-0.195074, 0.980773, 0.000000},
- {-0.092807, 0.466689, -0.879513},
- {0.101962, -0.512650, -0.852504},
- {0.382672, -0.923856, 0.000000},
- {0.200018, -0.482894, 0.852504},
- {-0.182073, 0.439619, 0.879513},
- {-0.382672, 0.923856, 0.000000},
- {-0.182073, 0.439619, -0.879513},
- {0.200018, -0.482894, -0.852504},
- {0.555559, -0.831446, 0.000000},
- {0.290384, -0.434614, 0.852504},
- {-0.264351, 0.395642, 0.879513},
- {-0.555559, 0.831446, 0.000000},
- {-0.264351, 0.395642, -0.879513},
- {0.290384, -0.434614, -0.852504},
- {0.707083, -0.707083, 0.000000},
- {0.369610, -0.369610, 0.852504},
- {-0.336467, 0.336467, 0.879513},
- {-0.707083, 0.707083, 0.000000},
- {-0.336467, 0.336467, -0.879513},
- {0.369610, -0.369610, -0.852504},
- {0.831446, -0.555559, 0.000000},
- {0.434614, -0.290384, 0.852504},
- {-0.395642, 0.264351, 0.879513},
- {-0.831446, 0.555559, 0.000000},
- {-0.395642, 0.264351, -0.879513},
- {0.434614, -0.290384, -0.852504},
- {0.923856, -0.382672, 0.000000},
- {0.482894, -0.200018, 0.852504},
- {-0.439619, 0.182073, 0.879513},
- {-0.923856, 0.382672, 0.000000},
- {-0.439619, 0.182073, -0.879513},
- {0.482894, -0.200018, -0.852504},
- {0.980773, -0.195074, 0.000000},
- {0.512650, -0.101962, 0.852504},
- {-0.466689, 0.092807, 0.879513},
- {-0.980773, 0.195074, 0.000000},
- {-0.466689, 0.092807, -0.879513},
- {0.512650, -0.101962, -0.852504},
+ {1.000000, 0.000000, 0.000000}, {0.522691, 0.000000, 0.852504},
+ {-0.475845, 0.000000, 0.879513}, {-1.000000, 0.000000, 0.000000},
+ {-0.475845, 0.000000, -0.879513}, {0.522691, 0.000000, -0.852504},
+ {0.980773, 0.195074, 0.000000}, {0.512650, 0.101962, 0.852504},
+ {-0.466689, -0.092807, 0.879513}, {-0.980773, -0.195074, 0.000000},
+ {-0.466689, -0.092807, -0.879513}, {0.512650, 0.101962, -0.852504},
+ {0.923856, 0.382672, 0.000000}, {0.482894, 0.200018, 0.852504},
+ {-0.439619, -0.182073, 0.879513}, {-0.923856, -0.382672, 0.000000},
+ {-0.439619, -0.182073, -0.879513}, {0.482894, 0.200018, -0.852504},
+ {0.831446, 0.555559, 0.000000}, {0.434614, 0.290384, 0.852504},
+ {-0.395642, -0.264351, 0.879513}, {-0.831446, -0.555559, 0.000000},
+ {-0.395642, -0.264351, -0.879513}, {0.434614, 0.290384, -0.852504},
+ {0.707083, 0.707083, 0.000000}, {0.369610, 0.369610, 0.852504},
+ {-0.336467, -0.336467, 0.879513}, {-0.707083, -0.707083, 0.000000},
+ {-0.336467, -0.336467, -0.879513}, {0.369610, 0.369610, -0.852504},
+ {0.555559, 0.831446, 0.000000}, {0.290384, 0.434614, 0.852504},
+ {-0.264351, -0.395642, 0.879513}, {-0.555559, -0.831446, 0.000000},
+ {-0.264351, -0.395642, -0.879513}, {0.290384, 0.434614, -0.852504},
+ {0.382672, 0.923856, 0.000000}, {0.200018, 0.482894, 0.852504},
+ {-0.182073, -0.439619, 0.879513}, {-0.382672, -0.923856, 0.000000},
+ {-0.182073, -0.439619, -0.879513}, {0.200018, 0.482894, -0.852504},
+ {0.195074, 0.980773, 0.000000}, {0.101962, 0.512650, 0.852504},
+ {-0.092807, -0.466689, 0.879513}, {-0.195074, -0.980773, 0.000000},
+ {-0.092807, -0.466689, -0.879513}, {0.101962, 0.512650, -0.852504},
+ {0.000000, 1.000000, 0.000000}, {0.000000, 0.522691, 0.852504},
+ {0.000000, -0.475845, 0.879513}, {0.000000, -1.000000, 0.000000},
+ {0.000000, -0.475845, -0.879513}, {0.000000, 0.522691, -0.852504},
+ {-0.195074, 0.980773, 0.000000}, {-0.101962, 0.512650, 0.852504},
+ {0.092807, -0.466689, 0.879513}, {0.195074, -0.980773, 0.000000},
+ {0.092807, -0.466689, -0.879513}, {-0.101962, 0.512650, -0.852504},
+ {-0.382672, 0.923856, 0.000000}, {-0.200018, 0.482894, 0.852504},
+ {0.182073, -0.439619, 0.879513}, {0.382672, -0.923856, 0.000000},
+ {0.182073, -0.439619, -0.879513}, {-0.200018, 0.482894, -0.852504},
+ {-0.555559, 0.831446, 0.000000}, {-0.290384, 0.434614, 0.852504},
+ {0.264351, -0.395642, 0.879513}, {0.555559, -0.831446, 0.000000},
+ {0.264351, -0.395642, -0.879513}, {-0.290384, 0.434614, -0.852504},
+ {-0.707083, 0.707083, 0.000000}, {-0.369610, 0.369610, 0.852504},
+ {0.336467, -0.336467, 0.879513}, {0.707083, -0.707083, 0.000000},
+ {0.336467, -0.336467, -0.879513}, {-0.369610, 0.369610, -0.852504},
+ {-0.831446, 0.555559, 0.000000}, {-0.434614, 0.290384, 0.852504},
+ {0.395642, -0.264351, 0.879513}, {0.831446, -0.555559, 0.000000},
+ {0.395642, -0.264351, -0.879513}, {-0.434614, 0.290384, -0.852504},
+ {-0.923856, 0.382672, 0.000000}, {-0.482894, 0.200018, 0.852504},
+ {0.439619, -0.182073, 0.879513}, {0.923856, -0.382672, 0.000000},
+ {0.439619, -0.182073, -0.879513}, {-0.482894, 0.200018, -0.852504},
+ {-0.980773, 0.195074, 0.000000}, {-0.512650, 0.101962, 0.852504},
+ {0.466689, -0.092807, 0.879513}, {0.980773, -0.195074, 0.000000},
+ {0.466689, -0.092807, -0.879513}, {-0.512650, 0.101962, -0.852504},
+ {-1.000000, 0.000000, 0.000000}, {-0.522691, 0.000000, 0.852504},
+ {0.475845, 0.000000, 0.879513}, {1.000000, 0.000000, 0.000000},
+ {0.475845, 0.000000, -0.879513}, {-0.522691, 0.000000, -0.852504},
+ {-0.980773, -0.195074, 0.000000}, {-0.512650, -0.101962, 0.852504},
+ {0.466689, 0.092807, 0.879513}, {0.980773, 0.195074, 0.000000},
+ {0.466689, 0.092807, -0.879513}, {-0.512650, -0.101962, -0.852504},
+ {-0.923856, -0.382672, 0.000000}, {-0.482894, -0.200018, 0.852504},
+ {0.439619, 0.182073, 0.879513}, {0.923856, 0.382672, 0.000000},
+ {0.439619, 0.182073, -0.879513}, {-0.482894, -0.200018, -0.852504},
+ {-0.831446, -0.555559, 0.000000}, {-0.434614, -0.290384, 0.852504},
+ {0.395642, 0.264351, 0.879513}, {0.831446, 0.555559, 0.000000},
+ {0.395642, 0.264351, -0.879513}, {-0.434614, -0.290384, -0.852504},
+ {-0.707083, -0.707083, 0.000000}, {-0.369610, -0.369610, 0.852504},
+ {0.336467, 0.336467, 0.879513}, {0.707083, 0.707083, 0.000000},
+ {0.336467, 0.336467, -0.879513}, {-0.369610, -0.369610, -0.852504},
+ {-0.555559, -0.831446, 0.000000}, {-0.290384, -0.434614, 0.852504},
+ {0.264351, 0.395642, 0.879513}, {0.555559, 0.831446, 0.000000},
+ {0.264351, 0.395642, -0.879513}, {-0.290384, -0.434614, -0.852504},
+ {-0.382672, -0.923856, 0.000000}, {-0.200018, -0.482894, 0.852504},
+ {0.182073, 0.439619, 0.879513}, {0.382672, 0.923856, 0.000000},
+ {0.182073, 0.439619, -0.879513}, {-0.200018, -0.482894, -0.852504},
+ {-0.195074, -0.980773, 0.000000}, {-0.101962, -0.512650, 0.852504},
+ {0.092807, 0.466689, 0.879513}, {0.195074, 0.980773, 0.000000},
+ {0.092807, 0.466689, -0.879513}, {-0.101962, -0.512650, -0.852504},
+ {0.000000, -1.000000, 0.000000}, {0.000000, -0.522691, 0.852504},
+ {0.000000, 0.475845, 0.879513}, {0.000000, 1.000000, 0.000000},
+ {0.000000, 0.475845, -0.879513}, {0.000000, -0.522691, -0.852504},
+ {0.195074, -0.980773, 0.000000}, {0.101962, -0.512650, 0.852504},
+ {-0.092807, 0.466689, 0.879513}, {-0.195074, 0.980773, 0.000000},
+ {-0.092807, 0.466689, -0.879513}, {0.101962, -0.512650, -0.852504},
+ {0.382672, -0.923856, 0.000000}, {0.200018, -0.482894, 0.852504},
+ {-0.182073, 0.439619, 0.879513}, {-0.382672, 0.923856, 0.000000},
+ {-0.182073, 0.439619, -0.879513}, {0.200018, -0.482894, -0.852504},
+ {0.555559, -0.831446, 0.000000}, {0.290384, -0.434614, 0.852504},
+ {-0.264351, 0.395642, 0.879513}, {-0.555559, 0.831446, 0.000000},
+ {-0.264351, 0.395642, -0.879513}, {0.290384, -0.434614, -0.852504},
+ {0.707083, -0.707083, 0.000000}, {0.369610, -0.369610, 0.852504},
+ {-0.336467, 0.336467, 0.879513}, {-0.707083, 0.707083, 0.000000},
+ {-0.336467, 0.336467, -0.879513}, {0.369610, -0.369610, -0.852504},
+ {0.831446, -0.555559, 0.000000}, {0.434614, -0.290384, 0.852504},
+ {-0.395642, 0.264351, 0.879513}, {-0.831446, 0.555559, 0.000000},
+ {-0.395642, 0.264351, -0.879513}, {0.434614, -0.290384, -0.852504},
+ {0.923856, -0.382672, 0.000000}, {0.482894, -0.200018, 0.852504},
+ {-0.439619, 0.182073, 0.879513}, {-0.923856, 0.382672, 0.000000},
+ {-0.439619, 0.182073, -0.879513}, {0.482894, -0.200018, -0.852504},
+ {0.980773, -0.195074, 0.000000}, {0.512650, -0.101962, 0.852504},
+ {-0.466689, 0.092807, 0.879513}, {-0.980773, 0.195074, 0.000000},
+ {-0.466689, 0.092807, -0.879513}, {0.512650, -0.101962, -0.852504},
};
static const unsigned short 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,
- 19, 25, 26,
- 26, 27, 21,
- 21, 27, 28,
- 28, 29, 23,
- 23, 29, 24,
- 30, 31, 25,
- 25, 31, 32,
- 26, 32, 33,
- 27, 33, 34,
- 34, 35, 29,
- 29, 35, 30,
- 36, 37, 31,
- 31, 37, 38,
- 38, 39, 33,
- 39, 40, 34,
- 40, 41, 35,
- 35, 41, 36,
- 36, 42, 43,
- 43, 44, 38,
- 44, 45, 39,
- 45, 46, 40,
- 46, 47, 41,
- 47, 42, 36,
- 48, 49, 43,
- 49, 50, 44,
- 50, 51, 45,
- 51, 52, 46,
- 52, 53, 47,
- 47, 53, 48,
- 54, 55, 49,
- 49, 55, 56,
- 50, 56, 57,
- 57, 58, 52,
- 58, 59, 53,
- 53, 59, 54,
- 60, 61, 55,
- 55, 61, 62,
- 56, 62, 63,
- 63, 64, 58,
- 64, 65, 59,
- 59, 65, 60,
- 66, 67, 61,
- 61, 67, 68,
- 68, 69, 63,
- 69, 70, 64,
- 70, 71, 65,
- 71, 66, 60,
- 72, 73, 67,
- 73, 74, 68,
- 68, 74, 75,
- 75, 76, 70,
- 76, 77, 71,
- 71, 77, 72,
- 78, 79, 73,
- 79, 80, 74,
- 74, 80, 81,
- 81, 82, 76,
- 82, 83, 77,
- 83, 78, 72,
- 78, 84, 85,
- 85, 86, 80,
- 80, 86, 87,
- 87, 88, 82,
- 82, 88, 89,
- 89, 84, 78,
- 90, 91, 85,
- 91, 92, 86,
- 86, 92, 93,
- 93, 94, 88,
- 88, 94, 95,
- 95, 90, 84,
- 96, 97, 91,
- 97, 98, 92,
- 98, 99, 93,
- 99, 100, 94,
- 100, 101, 95,
- 101, 96, 90,
- 102, 103, 97,
- 103, 104, 98,
- 104, 105, 99,
- 99, 105, 106,
- 106, 107, 101,
- 101, 107, 102,
- 108, 109, 103,
- 103, 109, 110,
- 110, 111, 105,
- 105, 111, 112,
- 112, 113, 107,
- 107, 113, 108,
- 114, 115, 109,
- 115, 116, 110,
- 116, 117, 111,
- 111, 117, 118,
- 112, 118, 119,
- 113, 119, 114,
- 114, 120, 121,
- 121, 122, 116,
- 122, 123, 117,
- 117, 123, 124,
- 124, 125, 119,
- 125, 120, 114,
- 126, 127, 121,
- 121, 127, 128,
- 128, 129, 123,
- 123, 129, 130,
- 130, 131, 125,
- 125, 131, 126,
- 132, 133, 127,
- 133, 134, 128,
- 128, 134, 135,
- 135, 136, 130,
- 136, 137, 131,
- 131, 137, 132,
- 132, 138, 139,
- 133, 139, 140,
- 134, 140, 141,
- 141, 142, 136,
- 142, 143, 137,
- 143, 138, 132,
- 138, 144, 145,
- 139, 145, 146,
- 146, 147, 141,
- 141, 147, 148,
- 148, 149, 143,
- 149, 144, 138,
- 144, 150, 151,
- 151, 152, 146,
- 146, 152, 153,
- 153, 154, 148,
- 154, 155, 149,
- 155, 150, 144,
- 156, 157, 151,
- 151, 157, 158,
- 158, 159, 153,
- 159, 160, 154,
- 160, 161, 155,
- 155, 161, 156,
- 156, 162, 163,
- 163, 164, 158,
- 158, 164, 165,
- 165, 166, 160,
- 160, 166, 167,
- 167, 162, 156,
- 162, 168, 169,
- 169, 170, 164,
- 164, 170, 171,
- 165, 171, 172,
- 166, 172, 173,
- 173, 168, 162,
- 174, 175, 169,
- 175, 176, 170,
- 170, 176, 177,
- 177, 178, 172,
- 172, 178, 179,
- 173, 179, 174,
- 174, 180, 181,
- 181, 182, 176,
- 176, 182, 183,
- 183, 184, 178,
- 178, 184, 185,
- 179, 185, 180,
- 186, 187, 181,
- 187, 188, 182,
- 188, 189, 183,
- 183, 189, 190,
- 190, 191, 185,
- 191, 186, 180,
- 0, 1, 187,
- 1, 2, 188,
- 2, 3, 189,
- 3, 4, 190,
- 190, 4, 5,
- 191, 5, 0,
- 0, 6, 1,
- 1, 7, 2,
- 2, 8, 3,
- 3, 9, 4,
- 4, 10, 5,
- 0, 5, 6,
- 6, 12, 7,
- 7, 13, 8,
- 8, 14, 9,
- 9, 15, 10,
- 10, 16, 11,
- 6, 11, 12,
- 12, 18, 13,
- 14, 13, 20,
- 14, 20, 15,
- 16, 15, 22,
- 16, 22, 17,
- 12, 17, 18,
- 18, 24, 19,
- 20, 19, 26,
- 20, 26, 21,
- 22, 21, 28,
- 22, 28, 23,
- 18, 23, 24,
- 24, 30, 25,
- 26, 25, 32,
- 27, 26, 33,
- 28, 27, 34,
- 28, 34, 29,
- 24, 29, 30,
- 30, 36, 31,
- 32, 31, 38,
- 32, 38, 33,
- 33, 39, 34,
- 34, 40, 35,
- 30, 35, 36,
- 37, 36, 43,
- 37, 43, 38,
- 38, 44, 39,
- 39, 45, 40,
- 40, 46, 41,
- 41, 47, 36,
- 42, 48, 43,
- 43, 49, 44,
- 44, 50, 45,
- 45, 51, 46,
- 46, 52, 47,
- 42, 47, 48,
- 48, 54, 49,
- 50, 49, 56,
- 51, 50, 57,
- 51, 57, 52,
- 52, 58, 53,
- 48, 53, 54,
- 54, 60, 55,
- 56, 55, 62,
- 57, 56, 63,
- 57, 63, 58,
- 58, 64, 59,
- 54, 59, 60,
- 60, 66, 61,
- 62, 61, 68,
- 62, 68, 63,
- 63, 69, 64,
- 64, 70, 65,
- 65, 71, 60,
- 66, 72, 67,
- 67, 73, 68,
- 69, 68, 75,
- 69, 75, 70,
- 70, 76, 71,
- 66, 71, 72,
- 72, 78, 73,
- 73, 79, 74,
- 75, 74, 81,
- 75, 81, 76,
- 76, 82, 77,
- 77, 83, 72,
- 79, 78, 85,
- 79, 85, 80,
- 81, 80, 87,
- 81, 87, 82,
- 83, 82, 89,
- 83, 89, 78,
- 84, 90, 85,
- 85, 91, 86,
- 87, 86, 93,
- 87, 93, 88,
- 89, 88, 95,
- 89, 95, 84,
- 90, 96, 91,
- 91, 97, 92,
- 92, 98, 93,
- 93, 99, 94,
- 94, 100, 95,
- 95, 101, 90,
- 96, 102, 97,
- 97, 103, 98,
- 98, 104, 99,
- 100, 99, 106,
- 100, 106, 101,
- 96, 101, 102,
- 102, 108, 103,
- 104, 103, 110,
- 104, 110, 105,
- 106, 105, 112,
- 106, 112, 107,
- 102, 107, 108,
- 108, 114, 109,
- 109, 115, 110,
- 110, 116, 111,
- 112, 111, 118,
- 113, 112, 119,
- 108, 113, 114,
- 115, 114, 121,
- 115, 121, 116,
- 116, 122, 117,
- 118, 117, 124,
- 118, 124, 119,
- 119, 125, 114,
- 120, 126, 121,
- 122, 121, 128,
- 122, 128, 123,
- 124, 123, 130,
- 124, 130, 125,
- 120, 125, 126,
- 126, 132, 127,
- 127, 133, 128,
- 129, 128, 135,
- 129, 135, 130,
- 130, 136, 131,
- 126, 131, 132,
- 133, 132, 139,
- 134, 133, 140,
- 135, 134, 141,
- 135, 141, 136,
- 136, 142, 137,
- 137, 143, 132,
- 139, 138, 145,
- 140, 139, 146,
- 140, 146, 141,
- 142, 141, 148,
- 142, 148, 143,
- 143, 149, 138,
- 145, 144, 151,
- 145, 151, 146,
- 147, 146, 153,
- 147, 153, 148,
- 148, 154, 149,
- 149, 155, 144,
- 150, 156, 151,
- 152, 151, 158,
- 152, 158, 153,
- 153, 159, 154,
- 154, 160, 155,
- 150, 155, 156,
- 157, 156, 163,
- 157, 163, 158,
- 159, 158, 165,
- 159, 165, 160,
- 161, 160, 167,
- 161, 167, 156,
- 163, 162, 169,
- 163, 169, 164,
- 165, 164, 171,
- 166, 165, 172,
- 167, 166, 173,
- 167, 173, 162,
- 168, 174, 169,
- 169, 175, 170,
- 171, 170, 177,
- 171, 177, 172,
- 173, 172, 179,
- 168, 173, 174,
- 175, 174, 181,
- 175, 181, 176,
- 177, 176, 183,
- 177, 183, 178,
- 179, 178, 185,
- 174, 179, 180,
- 180, 186, 181,
- 181, 187, 182,
- 182, 188, 183,
- 184, 183, 190,
- 184, 190, 185,
- 185, 191, 180,
- 186, 0, 187,
- 187, 1, 188,
- 188, 2, 189,
- 189, 3, 190,
- 191, 190, 5,
- 186, 191, 0,
+ 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,
+ 19, 25, 26, 26, 27, 21, 21, 27, 28, 28, 29, 23, 23, 29, 24, 30, 31, 25, 25,
+ 31, 32, 26, 32, 33, 27, 33, 34, 34, 35, 29, 29, 35, 30, 36, 37, 31, 31, 37,
+ 38, 38, 39, 33, 39, 40, 34, 40, 41, 35, 35, 41, 36, 36, 42, 43, 43, 44, 38,
+ 44, 45, 39, 45, 46, 40, 46, 47, 41, 47, 42, 36, 48, 49, 43, 49, 50, 44, 50,
+ 51, 45, 51, 52, 46, 52, 53, 47, 47, 53, 48, 54, 55, 49, 49, 55, 56, 50, 56,
+ 57, 57, 58, 52, 58, 59, 53, 53, 59, 54, 60, 61, 55, 55, 61, 62, 56, 62, 63,
+ 63, 64, 58, 64, 65, 59, 59, 65, 60, 66, 67, 61, 61, 67, 68, 68, 69, 63, 69,
+ 70, 64, 70, 71, 65, 71, 66, 60, 72, 73, 67, 73, 74, 68, 68, 74, 75, 75, 76,
+ 70, 76, 77, 71, 71, 77, 72, 78, 79, 73, 79, 80, 74, 74, 80, 81, 81, 82, 76,
+ 82, 83, 77, 83, 78, 72, 78, 84, 85, 85, 86, 80, 80, 86, 87, 87, 88, 82, 82,
+ 88, 89, 89, 84, 78, 90, 91, 85, 91, 92, 86, 86, 92, 93, 93, 94, 88, 88, 94,
+ 95, 95, 90, 84, 96, 97, 91, 97, 98, 92, 98, 99, 93, 99, 100, 94, 100, 101, 95,
+ 101, 96, 90, 102, 103, 97, 103, 104, 98, 104, 105, 99, 99, 105, 106, 106, 107, 101, 101,
+ 107, 102, 108, 109, 103, 103, 109, 110, 110, 111, 105, 105, 111, 112, 112, 113, 107, 107, 113,
+ 108, 114, 115, 109, 115, 116, 110, 116, 117, 111, 111, 117, 118, 112, 118, 119, 113, 119, 114,
+ 114, 120, 121, 121, 122, 116, 122, 123, 117, 117, 123, 124, 124, 125, 119, 125, 120, 114, 126,
+ 127, 121, 121, 127, 128, 128, 129, 123, 123, 129, 130, 130, 131, 125, 125, 131, 126, 132, 133,
+ 127, 133, 134, 128, 128, 134, 135, 135, 136, 130, 136, 137, 131, 131, 137, 132, 132, 138, 139,
+ 133, 139, 140, 134, 140, 141, 141, 142, 136, 142, 143, 137, 143, 138, 132, 138, 144, 145, 139,
+ 145, 146, 146, 147, 141, 141, 147, 148, 148, 149, 143, 149, 144, 138, 144, 150, 151, 151, 152,
+ 146, 146, 152, 153, 153, 154, 148, 154, 155, 149, 155, 150, 144, 156, 157, 151, 151, 157, 158,
+ 158, 159, 153, 159, 160, 154, 160, 161, 155, 155, 161, 156, 156, 162, 163, 163, 164, 158, 158,
+ 164, 165, 165, 166, 160, 160, 166, 167, 167, 162, 156, 162, 168, 169, 169, 170, 164, 164, 170,
+ 171, 165, 171, 172, 166, 172, 173, 173, 168, 162, 174, 175, 169, 175, 176, 170, 170, 176, 177,
+ 177, 178, 172, 172, 178, 179, 173, 179, 174, 174, 180, 181, 181, 182, 176, 176, 182, 183, 183,
+ 184, 178, 178, 184, 185, 179, 185, 180, 186, 187, 181, 187, 188, 182, 188, 189, 183, 183, 189,
+ 190, 190, 191, 185, 191, 186, 180, 0, 1, 187, 1, 2, 188, 2, 3, 189, 3, 4, 190,
+ 190, 4, 5, 191, 5, 0, 0, 6, 1, 1, 7, 2, 2, 8, 3, 3, 9, 4, 4,
+ 10, 5, 0, 5, 6, 6, 12, 7, 7, 13, 8, 8, 14, 9, 9, 15, 10, 10, 16,
+ 11, 6, 11, 12, 12, 18, 13, 14, 13, 20, 14, 20, 15, 16, 15, 22, 16, 22, 17,
+ 12, 17, 18, 18, 24, 19, 20, 19, 26, 20, 26, 21, 22, 21, 28, 22, 28, 23, 18,
+ 23, 24, 24, 30, 25, 26, 25, 32, 27, 26, 33, 28, 27, 34, 28, 34, 29, 24, 29,
+ 30, 30, 36, 31, 32, 31, 38, 32, 38, 33, 33, 39, 34, 34, 40, 35, 30, 35, 36,
+ 37, 36, 43, 37, 43, 38, 38, 44, 39, 39, 45, 40, 40, 46, 41, 41, 47, 36, 42,
+ 48, 43, 43, 49, 44, 44, 50, 45, 45, 51, 46, 46, 52, 47, 42, 47, 48, 48, 54,
+ 49, 50, 49, 56, 51, 50, 57, 51, 57, 52, 52, 58, 53, 48, 53, 54, 54, 60, 55,
+ 56, 55, 62, 57, 56, 63, 57, 63, 58, 58, 64, 59, 54, 59, 60, 60, 66, 61, 62,
+ 61, 68, 62, 68, 63, 63, 69, 64, 64, 70, 65, 65, 71, 60, 66, 72, 67, 67, 73,
+ 68, 69, 68, 75, 69, 75, 70, 70, 76, 71, 66, 71, 72, 72, 78, 73, 73, 79, 74,
+ 75, 74, 81, 75, 81, 76, 76, 82, 77, 77, 83, 72, 79, 78, 85, 79, 85, 80, 81,
+ 80, 87, 81, 87, 82, 83, 82, 89, 83, 89, 78, 84, 90, 85, 85, 91, 86, 87, 86,
+ 93, 87, 93, 88, 89, 88, 95, 89, 95, 84, 90, 96, 91, 91, 97, 92, 92, 98, 93,
+ 93, 99, 94, 94, 100, 95, 95, 101, 90, 96, 102, 97, 97, 103, 98, 98, 104, 99, 100,
+ 99, 106, 100, 106, 101, 96, 101, 102, 102, 108, 103, 104, 103, 110, 104, 110, 105, 106, 105,
+ 112, 106, 112, 107, 102, 107, 108, 108, 114, 109, 109, 115, 110, 110, 116, 111, 112, 111, 118,
+ 113, 112, 119, 108, 113, 114, 115, 114, 121, 115, 121, 116, 116, 122, 117, 118, 117, 124, 118,
+ 124, 119, 119, 125, 114, 120, 126, 121, 122, 121, 128, 122, 128, 123, 124, 123, 130, 124, 130,
+ 125, 120, 125, 126, 126, 132, 127, 127, 133, 128, 129, 128, 135, 129, 135, 130, 130, 136, 131,
+ 126, 131, 132, 133, 132, 139, 134, 133, 140, 135, 134, 141, 135, 141, 136, 136, 142, 137, 137,
+ 143, 132, 139, 138, 145, 140, 139, 146, 140, 146, 141, 142, 141, 148, 142, 148, 143, 143, 149,
+ 138, 145, 144, 151, 145, 151, 146, 147, 146, 153, 147, 153, 148, 148, 154, 149, 149, 155, 144,
+ 150, 156, 151, 152, 151, 158, 152, 158, 153, 153, 159, 154, 154, 160, 155, 150, 155, 156, 157,
+ 156, 163, 157, 163, 158, 159, 158, 165, 159, 165, 160, 161, 160, 167, 161, 167, 156, 163, 162,
+ 169, 163, 169, 164, 165, 164, 171, 166, 165, 172, 167, 166, 173, 167, 173, 162, 168, 174, 169,
+ 169, 175, 170, 171, 170, 177, 171, 177, 172, 173, 172, 179, 168, 173, 174, 175, 174, 181, 175,
+ 181, 176, 177, 176, 183, 177, 183, 178, 179, 178, 185, 174, 179, 180, 180, 186, 181, 181, 187,
+ 182, 182, 188, 183, 184, 183, 190, 184, 190, 185, 185, 191, 180, 186, 0, 187, 187, 1, 188,
+ 188, 2, 189, 189, 3, 190, 191, 190, 5, 186, 191, 0,
};
GizmoGeomInfo wm_gizmo_geom_data_dial = {
- .nverts = 192,
- .ntris = 384,
- .verts = verts,
- .normals = normals,
- .indices = indices,
+ .nverts = 192,
+ .ntris = 384,
+ .verts = verts,
+ .normals = normals,
+ .indices = indices,
};
diff --git a/source/blender/editors/gizmo_library/gizmo_draw_utils.c b/source/blender/editors/gizmo_library/gizmo_draw_utils.c
index 999e211a492..f1d8c1ac6b0 100644
--- a/source/blender/editors/gizmo_library/gizmo_draw_utils.c
+++ b/source/blender/editors/gizmo_library/gizmo_draw_utils.c
@@ -49,63 +49,63 @@
/**
* Main draw call for GizmoGeomInfo data
*/
-void wm_gizmo_geometryinfo_draw(const GizmoGeomInfo *info, const bool UNUSED(select), const float color[4])
+void wm_gizmo_geometryinfo_draw(const GizmoGeomInfo *info,
+ const bool UNUSED(select),
+ const float color[4])
{
- /* TODO store the Batches inside the GizmoGeomInfo and updated it when geom changes
- * So we don't need to re-created and discard it every time */
+ /* TODO store the Batches inside the GizmoGeomInfo and updated it when geom changes
+ * So we don't need to re-created and discard it every time */
- GPUVertBuf *vbo;
- GPUIndexBuf *el;
- GPUBatch *batch;
- GPUIndexBufBuilder elb = {0};
+ GPUVertBuf *vbo;
+ GPUIndexBuf *el;
+ GPUBatch *batch;
+ GPUIndexBufBuilder elb = {0};
- GPUVertFormat format = {0};
- uint pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ GPUVertFormat format = {0};
+ uint pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- /* 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];
- GPU_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]);
- }
- el = GPU_indexbuf_build(&elb);
+ /* 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];
+ GPU_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]);
+ }
+ el = GPU_indexbuf_build(&elb);
- vbo = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, info->nverts);
+ vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, info->nverts);
- GPU_vertbuf_attr_fill(vbo, pos_id, info->verts);
+ GPU_vertbuf_attr_fill(vbo, pos_id, info->verts);
- batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, el, GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
- GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+ batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, el, GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
- GPU_batch_uniform_4fv(batch, "color", color);
+ GPU_batch_uniform_4fv(batch, "color", color);
- /* We may want to re-visit this, for now disable
- * since it causes issues leaving the GL state modified. */
+ /* We may want to re-visit this, for now disable
+ * since it causes issues leaving the GL state modified. */
#if 0
- glEnable(GL_CULL_FACE);
- GPU_depth_test(true);
+ glEnable(GL_CULL_FACE);
+ GPU_depth_test(true);
#endif
- GPU_batch_draw(batch);
+ GPU_batch_draw(batch);
#if 0
- GPU_depth_test(false);
- glDisable(GL_CULL_FACE);
+ GPU_depth_test(false);
+ glDisable(GL_CULL_FACE);
#endif
-
- GPU_batch_discard(batch);
+ GPU_batch_discard(batch);
}
void wm_gizmo_vec_draw(
- const float color[4], const float (*verts)[3], uint vert_count,
- uint pos, uint primitive_type)
+ const float color[4], const float (*verts)[3], uint vert_count, uint pos, uint primitive_type)
{
- immUniformColor4fv(color);
- immBegin(primitive_type, vert_count);
- for (int i = 0; i < vert_count; i++) {
- immVertex3fv(pos, verts[i]);
- }
- immEnd();
+ immUniformColor4fv(color);
+ immBegin(primitive_type, vert_count);
+ for (int i = 0; i < vert_count; i++) {
+ immVertex3fv(pos, verts[i]);
+ }
+ immEnd();
}
diff --git a/source/blender/editors/gizmo_library/gizmo_geometry.h b/source/blender/editors/gizmo_library/gizmo_geometry.h
index 71d8919c91d..42cb0c0bc1b 100644
--- a/source/blender/editors/gizmo_library/gizmo_geometry.h
+++ b/source/blender/editors/gizmo_library/gizmo_geometry.h
@@ -26,16 +26,15 @@
* called geom_xxx_gizmo.c
*/
-
#ifndef __GIZMO_GEOMETRY_H__
#define __GIZMO_GEOMETRY_H__
typedef struct GizmoGeomInfo {
- int nverts;
- int ntris;
- const float (*verts)[3];
- const float (*normals)[3];
- const unsigned short *indices;
+ int nverts;
+ int ntris;
+ const float (*verts)[3];
+ const float (*normals)[3];
+ const unsigned short *indices;
} GizmoGeomInfo;
/* arrow gizmo */
@@ -47,4 +46,4 @@ extern GizmoGeomInfo wm_gizmo_geom_data_cube;
/* dial gizmo */
extern GizmoGeomInfo wm_gizmo_geom_data_dial;
-#endif /* __GIZMO_GEOMETRY_H__ */
+#endif /* __GIZMO_GEOMETRY_H__ */
diff --git a/source/blender/editors/gizmo_library/gizmo_group_types/value2d_gizmo_group.c b/source/blender/editors/gizmo_library/gizmo_group_types/value2d_gizmo_group.c
index 28a5200a041..3b61aed5e27 100644
--- a/source/blender/editors/gizmo_library/gizmo_group_types/value2d_gizmo_group.c
+++ b/source/blender/editors/gizmo_library/gizmo_group_types/value2d_gizmo_group.c
@@ -44,118 +44,115 @@
* \{ */
struct ValueOpRedoGroup {
- wmGizmo *gizmo;
- struct {
- const bContext *context; /* needed for redo. */
- wmOperator *op;
- } state;
+ wmGizmo *gizmo;
+ struct {
+ const bContext *context; /* needed for redo. */
+ wmOperator *op;
+ } state;
};
static void gizmo_op_redo_exec(struct ValueOpRedoGroup *igzgroup)
{
- wmOperator *op = igzgroup->state.op;
- if (op == WM_operator_last_redo((bContext *)igzgroup->state.context)) {
- ED_undo_operator_repeat((bContext *)igzgroup->state.context, op);
- }
+ wmOperator *op = igzgroup->state.op;
+ if (op == WM_operator_last_redo((bContext *)igzgroup->state.context)) {
+ ED_undo_operator_repeat((bContext *)igzgroup->state.context, op);
+ }
}
/* translate callbacks */
-static void gizmo_value_operator_redo_value_get(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- void *value_p)
+static void gizmo_value_operator_redo_value_get(const wmGizmo *gz,
+ wmGizmoProperty *gz_prop,
+ void *value_p)
{
- float *value = value_p;
- BLI_assert(gz_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(gz_prop);
+ float *value = value_p;
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
- struct ValueOpRedoGroup *igzgroup = gz->parent_gzgroup->customdata;
- wmOperator *op = igzgroup->state.op;
- *value = RNA_property_float_get(op->ptr, op->type->prop);
+ struct ValueOpRedoGroup *igzgroup = gz->parent_gzgroup->customdata;
+ wmOperator *op = igzgroup->state.op;
+ *value = RNA_property_float_get(op->ptr, op->type->prop);
}
-static void gizmo_value_operator_redo_value_set(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- const void *value_p)
+static void gizmo_value_operator_redo_value_set(const wmGizmo *gz,
+ wmGizmoProperty *gz_prop,
+ const void *value_p)
{
- const float *value = value_p;
- BLI_assert(gz_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(gz_prop);
-
- struct ValueOpRedoGroup *igzgroup = gz->parent_gzgroup->customdata;
- wmOperator *op = igzgroup->state.op;
- RNA_property_float_set(op->ptr, op->type->prop, *value);
- gizmo_op_redo_exec(igzgroup);
+ const float *value = value_p;
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
+
+ struct ValueOpRedoGroup *igzgroup = gz->parent_gzgroup->customdata;
+ wmOperator *op = igzgroup->state.op;
+ RNA_property_float_set(op->ptr, op->type->prop, *value);
+ gizmo_op_redo_exec(igzgroup);
}
-static void WIDGETGROUP_value_operator_redo_modal_from_setup(
- const bContext *C, wmGizmoGroup *gzgroup)
+static void WIDGETGROUP_value_operator_redo_modal_from_setup(const bContext *C,
+ wmGizmoGroup *gzgroup)
{
- /* Start off dragging. */
- wmWindow *win = CTX_wm_window(C);
- wmGizmo *gz = gzgroup->gizmos.first;
- wmGizmoMap *gzmap = gzgroup->parent_gzmap;
- WM_gizmo_modal_set_from_setup(
- gzmap, (bContext *)C, gz, 0, win->eventstate);
+ /* Start off dragging. */
+ wmWindow *win = CTX_wm_window(C);
+ wmGizmo *gz = gzgroup->gizmos.first;
+ wmGizmoMap *gzmap = gzgroup->parent_gzmap;
+ WM_gizmo_modal_set_from_setup(gzmap, (bContext *)C, gz, 0, win->eventstate);
}
static void WIDGETGROUP_value_operator_redo_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct ValueOpRedoGroup *igzgroup = MEM_mallocN(sizeof(struct ValueOpRedoGroup), __func__);
+ struct ValueOpRedoGroup *igzgroup = MEM_mallocN(sizeof(struct ValueOpRedoGroup), __func__);
- igzgroup->gizmo = WM_gizmo_new("GIZMO_GT_value_2d", gzgroup, NULL);
- wmGizmo *gz = igzgroup->gizmo;
+ igzgroup->gizmo = WM_gizmo_new("GIZMO_GT_value_2d", gzgroup, NULL);
+ wmGizmo *gz = igzgroup->gizmo;
- igzgroup->state.context = C;
- igzgroup->state.op = WM_operator_last_redo(C);
+ igzgroup->state.context = C;
+ igzgroup->state.op = WM_operator_last_redo(C);
- gzgroup->customdata = igzgroup;
+ gzgroup->customdata = igzgroup;
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
- WM_gizmo_target_property_def_func(
- gz, "offset",
- &(const struct wmGizmoPropertyFnParams) {
- .value_get_fn = gizmo_value_operator_redo_value_get,
- .value_set_fn = gizmo_value_operator_redo_value_set,
- .range_get_fn = NULL,
- .user_data = igzgroup,
- });
+ WM_gizmo_target_property_def_func(gz,
+ "offset",
+ &(const struct wmGizmoPropertyFnParams){
+ .value_get_fn = gizmo_value_operator_redo_value_get,
+ .value_set_fn = gizmo_value_operator_redo_value_set,
+ .range_get_fn = NULL,
+ .user_data = igzgroup,
+ });
- /* Become modal as soon as it's started. */
- WIDGETGROUP_value_operator_redo_modal_from_setup(C, gzgroup);
+ /* Become modal as soon as it's started. */
+ WIDGETGROUP_value_operator_redo_modal_from_setup(C, gzgroup);
}
-static void WIDGETGROUP_value_operator_redo_refresh(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
+static void WIDGETGROUP_value_operator_redo_refresh(const bContext *UNUSED(C),
+ wmGizmoGroup *gzgroup)
{
- struct ValueOpRedoGroup *igzgroup = gzgroup->customdata;
- wmGizmo *gz = igzgroup->gizmo;
- wmOperator *op = WM_operator_last_redo((bContext *)igzgroup->state.context);
- wmGizmoMap *gzmap = gzgroup->parent_gzmap;
-
- /* FIXME */
- extern struct wmGizmo *wm_gizmomap_modal_get(struct wmGizmoMap *gzmap);
- if ((op != igzgroup->state.op) ||
- (wm_gizmomap_modal_get(gzmap) != gz))
- {
- WM_gizmo_group_type_unlink_delayed_ptr(gzgroup->type);
- }
+ struct ValueOpRedoGroup *igzgroup = gzgroup->customdata;
+ wmGizmo *gz = igzgroup->gizmo;
+ wmOperator *op = WM_operator_last_redo((bContext *)igzgroup->state.context);
+ wmGizmoMap *gzmap = gzgroup->parent_gzmap;
+
+ /* FIXME */
+ extern struct wmGizmo *wm_gizmomap_modal_get(struct wmGizmoMap * gzmap);
+ if ((op != igzgroup->state.op) || (wm_gizmomap_modal_get(gzmap) != gz)) {
+ WM_gizmo_group_type_unlink_delayed_ptr(gzgroup->type);
+ }
}
static void WM_GGT_value_operator_redo(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Value Operator Redo";
- gzgt->idname = "WM_GGT_value_operator_redo";
+ gzgt->name = "Value Operator Redo";
+ gzgt->idname = "WM_GGT_value_operator_redo";
- /* FIXME, allow multiple. */
- gzgt->flag = WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_TOOL_INIT;
+ /* FIXME, allow multiple. */
+ gzgt->flag = WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_TOOL_INIT;
- gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
- gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
-
- gzgt->setup = WIDGETGROUP_value_operator_redo_setup;
- gzgt->refresh = WIDGETGROUP_value_operator_redo_refresh;
+ gzgt->setup = WIDGETGROUP_value_operator_redo_setup;
+ gzgt->refresh = WIDGETGROUP_value_operator_redo_refresh;
}
/** \} */
@@ -166,7 +163,7 @@ static void WM_GGT_value_operator_redo(wmGizmoGroupType *gzgt)
void ED_gizmogrouptypes_value_2d(void)
{
- WM_gizmogrouptype_append(WM_GGT_value_operator_redo);
+ WM_gizmogrouptype_append(WM_GGT_value_operator_redo);
}
/** \} */
diff --git a/source/blender/editors/gizmo_library/gizmo_library_intern.h b/source/blender/editors/gizmo_library/gizmo_library_intern.h
index 7712767c5ad..35782ea8b95 100644
--- a/source/blender/editors/gizmo_library/gizmo_library_intern.h
+++ b/source/blender/editors/gizmo_library/gizmo_library_intern.h
@@ -31,69 +31,76 @@
* Data for common interactions. Used in gizmo_library_utils.c functions.
*/
typedef struct GizmoCommonData {
- float range_fac; /* factor for arrow min/max distance */
- float offset;
+ float range_fac; /* factor for arrow min/max distance */
+ float offset;
- /* property range for constrained gizmos */
- float range;
- /* min/max value for constrained gizmos */
- float min, max;
+ /* property range for constrained gizmos */
+ float range;
+ /* min/max value for constrained gizmos */
+ float min, max;
- uint is_custom_range_set : 1;
+ uint is_custom_range_set : 1;
} GizmoCommonData;
typedef struct GizmoInteraction {
- float init_value; /* initial property value */
- float init_mval[2];
- float init_offset;
- float init_matrix_final[4][4];
- float init_matrix_basis[4][4];
-
- /* offset of last handling step */
- float prev_offset;
- /* Total offset added by precision tweaking.
- * Needed to allow toggling precision on/off without causing jumps */
- float precision_offset;
+ float init_value; /* initial property value */
+ float init_mval[2];
+ float init_offset;
+ float init_matrix_final[4][4];
+ float init_matrix_basis[4][4];
+
+ /* offset of last handling step */
+ float prev_offset;
+ /* Total offset added by precision tweaking.
+ * Needed to allow toggling precision on/off without causing jumps */
+ float precision_offset;
} GizmoInteraction;
-float gizmo_offset_from_value(
- GizmoCommonData *data, const float value,
- const bool constrained, const bool inverted);
-float gizmo_value_from_offset(
- GizmoCommonData *data, GizmoInteraction *inter, const float offset,
- const bool constrained, const bool inverted, const bool use_precision);
-
-void gizmo_property_data_update(
- struct wmGizmo *gz, GizmoCommonData *data, wmGizmoProperty *gz_prop,
- const bool constrained, const bool inverted);
-
-void gizmo_property_value_reset(
- bContext *C, const struct wmGizmo *gz, GizmoInteraction *inter, wmGizmoProperty *gz_prop);
-
+float gizmo_offset_from_value(GizmoCommonData *data,
+ const float value,
+ const bool constrained,
+ const bool inverted);
+float gizmo_value_from_offset(GizmoCommonData *data,
+ GizmoInteraction *inter,
+ const float offset,
+ const bool constrained,
+ const bool inverted,
+ const bool use_precision);
+
+void gizmo_property_data_update(struct wmGizmo *gz,
+ GizmoCommonData *data,
+ wmGizmoProperty *gz_prop,
+ const bool constrained,
+ const bool inverted);
+
+void gizmo_property_value_reset(bContext *C,
+ const struct wmGizmo *gz,
+ GizmoInteraction *inter,
+ wmGizmoProperty *gz_prop);
/* -------------------------------------------------------------------- */
-void gizmo_color_get(
- const struct wmGizmo *gz, const bool highlight,
- float r_color[4]);
+void gizmo_color_get(const struct wmGizmo *gz, const bool highlight, float r_color[4]);
-bool gizmo_window_project_2d(
- bContext *C, const struct wmGizmo *gz, const float mval[2], int axis, bool use_offset,
- float r_co[2]);
+bool gizmo_window_project_2d(bContext *C,
+ const struct wmGizmo *gz,
+ const float mval[2],
+ int axis,
+ bool use_offset,
+ float r_co[2]);
bool gizmo_window_project_3d(
- bContext *C, const struct wmGizmo *gz, const float mval[2], bool use_offset,
- float r_co[3]);
+ bContext *C, const struct wmGizmo *gz, const float mval[2], bool use_offset, float r_co[3]);
/* -------------------------------------------------------------------- */
/* Gizmo drawing */
#include "gizmo_geometry.h"
-void wm_gizmo_geometryinfo_draw(const struct GizmoGeomInfo *info, const bool select, const float color[4]);
+void wm_gizmo_geometryinfo_draw(const struct GizmoGeomInfo *info,
+ const bool select,
+ const float color[4]);
void wm_gizmo_vec_draw(
- const float color[4], const float (*verts)[3], uint vert_count,
- uint pos, uint primitive_type);
-
+ const float color[4], const float (*verts)[3], uint vert_count, uint pos, uint primitive_type);
-#endif /* __GIZMO_LIBRARY_INTERN_H__ */
+#endif /* __GIZMO_LIBRARY_INTERN_H__ */
diff --git a/source/blender/editors/gizmo_library/gizmo_library_presets.c b/source/blender/editors/gizmo_library/gizmo_library_presets.c
index 9dba0c0d515..ce62171ccb0 100644
--- a/source/blender/editors/gizmo_library/gizmo_library_presets.c
+++ b/source/blender/editors/gizmo_library/gizmo_library_presets.c
@@ -48,97 +48,99 @@
#include "ED_screen.h"
/* own includes */
-#include "ED_gizmo_library.h" /* own include */
-#include "gizmo_library_intern.h" /* own include */
+#include "ED_gizmo_library.h" /* own include */
+#include "gizmo_library_intern.h" /* own include */
/* TODO, this is to be used by RNA. might move to ED_gizmo_library */
/**
* Given a single axis, orient the matrix to a different direction.
*/
-static void single_axis_convert(
- int src_axis, float src_mat[4][4],
- int dst_axis, float dst_mat[4][4])
+static void single_axis_convert(int src_axis,
+ float src_mat[4][4],
+ int dst_axis,
+ float dst_mat[4][4])
{
- copy_m4_m4(dst_mat, src_mat);
- if (src_axis == dst_axis) {
- return;
- }
-
- float rotmat[3][3];
- mat3_from_axis_conversion_single(src_axis, dst_axis, rotmat);
- transpose_m3(rotmat);
- mul_m4_m4m3(dst_mat, src_mat, rotmat);
+ copy_m4_m4(dst_mat, src_mat);
+ if (src_axis == dst_axis) {
+ return;
+ }
+
+ float rotmat[3][3];
+ mat3_from_axis_conversion_single(src_axis, dst_axis, rotmat);
+ transpose_m3(rotmat);
+ mul_m4_m4m3(dst_mat, src_mat, rotmat);
}
/**
* Use for all geometry.
*/
-static void ed_gizmo_draw_preset_geometry(
- const struct wmGizmo *gz, float mat[4][4], int select_id,
- const GizmoGeomInfo *info)
+static void ed_gizmo_draw_preset_geometry(const struct wmGizmo *gz,
+ float mat[4][4],
+ int select_id,
+ const GizmoGeomInfo *info)
{
- const bool is_select = (select_id != -1);
- const bool is_highlight = is_select && (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
+ const bool is_select = (select_id != -1);
+ const bool is_highlight = is_select && (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
- float color[4];
- gizmo_color_get(gz, is_highlight, color);
+ float color[4];
+ gizmo_color_get(gz, is_highlight, color);
- if (is_select) {
- GPU_select_load_id(select_id);
- }
+ if (is_select) {
+ GPU_select_load_id(select_id);
+ }
- GPU_matrix_push();
- GPU_matrix_mul(mat);
- wm_gizmo_geometryinfo_draw(info, is_select, color);
- GPU_matrix_pop();
+ GPU_matrix_push();
+ GPU_matrix_mul(mat);
+ wm_gizmo_geometryinfo_draw(info, is_select, color);
+ GPU_matrix_pop();
- if (is_select) {
- GPU_select_load_id(-1);
- }
+ if (is_select) {
+ GPU_select_load_id(-1);
+ }
}
-void ED_gizmo_draw_preset_box(
- const struct wmGizmo *gz, float mat[4][4], int select_id)
+void ED_gizmo_draw_preset_box(const struct wmGizmo *gz, float mat[4][4], int select_id)
{
- ed_gizmo_draw_preset_geometry(gz, mat, select_id, &wm_gizmo_geom_data_cube);
+ ed_gizmo_draw_preset_geometry(gz, mat, select_id, &wm_gizmo_geom_data_cube);
}
-void ED_gizmo_draw_preset_arrow(
- const struct wmGizmo *gz, float mat[4][4], int axis, int select_id)
+void ED_gizmo_draw_preset_arrow(const struct wmGizmo *gz, float mat[4][4], int axis, int select_id)
{
- float mat_rotate[4][4];
- single_axis_convert(OB_POSZ, mat, axis, mat_rotate);
- ed_gizmo_draw_preset_geometry(gz, mat_rotate, select_id, &wm_gizmo_geom_data_arrow);
+ float mat_rotate[4][4];
+ single_axis_convert(OB_POSZ, mat, axis, mat_rotate);
+ ed_gizmo_draw_preset_geometry(gz, mat_rotate, select_id, &wm_gizmo_geom_data_arrow);
}
-void ED_gizmo_draw_preset_circle(
- const struct wmGizmo *gz, float mat[4][4], int axis, int select_id)
+void ED_gizmo_draw_preset_circle(const struct wmGizmo *gz,
+ float mat[4][4],
+ int axis,
+ int select_id)
{
- float mat_rotate[4][4];
- single_axis_convert(OB_POSZ, mat, axis, mat_rotate);
- ed_gizmo_draw_preset_geometry(gz, mat_rotate, select_id, &wm_gizmo_geom_data_dial);
+ float mat_rotate[4][4];
+ single_axis_convert(OB_POSZ, mat, axis, mat_rotate);
+ ed_gizmo_draw_preset_geometry(gz, mat_rotate, select_id, &wm_gizmo_geom_data_dial);
}
void ED_gizmo_draw_preset_facemap(
- const bContext *C, const struct wmGizmo *gz, Object *ob, const int facemap, int select_id)
+ const bContext *C, const struct wmGizmo *gz, Object *ob, const int facemap, int select_id)
{
- const bool is_select = (select_id != -1);
- const bool is_highlight = is_select && (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
+ const bool is_select = (select_id != -1);
+ const bool is_highlight = is_select && (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
- float color[4];
- gizmo_color_get(gz, is_highlight, color);
+ float color[4];
+ gizmo_color_get(gz, is_highlight, color);
- if (is_select) {
- GPU_select_load_id(select_id);
- }
+ if (is_select) {
+ GPU_select_load_id(select_id);
+ }
- GPU_matrix_push();
- GPU_matrix_mul(ob->obmat);
- ED_draw_object_facemap(CTX_data_depsgraph(C), ob, color, facemap);
- GPU_matrix_pop();
+ GPU_matrix_push();
+ GPU_matrix_mul(ob->obmat);
+ ED_draw_object_facemap(CTX_data_depsgraph(C), ob, color, facemap);
+ GPU_matrix_pop();
- if (is_select) {
- GPU_select_load_id(-1);
- }
+ if (is_select) {
+ GPU_select_load_id(-1);
+ }
}
diff --git a/source/blender/editors/gizmo_library/gizmo_library_utils.c b/source/blender/editors/gizmo_library/gizmo_library_utils.c
index 0ae312d552e..2e5c3b37542 100644
--- a/source/blender/editors/gizmo_library/gizmo_library_utils.c
+++ b/source/blender/editors/gizmo_library/gizmo_library_utils.c
@@ -45,114 +45,127 @@
/* factor for precision tweaking */
#define GIZMO_PRECISION_FAC 0.05f
-
-BLI_INLINE float gizmo_offset_from_value_constr(
- const float range_fac, const float min, const float range, const float value,
- const bool inverted)
+BLI_INLINE float gizmo_offset_from_value_constr(const float range_fac,
+ const float min,
+ const float range,
+ const float value,
+ const bool inverted)
{
- return inverted ? (range_fac * (min + range - value) / range) : (range_fac * (value / range));
+ return inverted ? (range_fac * (min + range - value) / range) : (range_fac * (value / range));
}
-BLI_INLINE float gizmo_value_from_offset_constr(
- const float range_fac, const float min, const float range, const float value,
- const bool inverted)
+BLI_INLINE float gizmo_value_from_offset_constr(const float range_fac,
+ const float min,
+ const float range,
+ const float value,
+ const bool inverted)
{
- return inverted ? (min + range - (value * range / range_fac)) : (value * range / range_fac);
+ return inverted ? (min + range - (value * range / range_fac)) : (value * range / range_fac);
}
-float gizmo_offset_from_value(
- GizmoCommonData *data, const float value, const bool constrained, const bool inverted)
+float gizmo_offset_from_value(GizmoCommonData *data,
+ const float value,
+ const bool constrained,
+ const bool inverted)
{
- if (constrained)
- return gizmo_offset_from_value_constr(data->range_fac, data->min, data->range, value, inverted);
+ if (constrained)
+ return gizmo_offset_from_value_constr(
+ data->range_fac, data->min, data->range, value, inverted);
- return value;
+ return value;
}
-float gizmo_value_from_offset(
- GizmoCommonData *data, GizmoInteraction *inter, const float offset,
- const bool constrained, const bool inverted, const bool use_precision)
+float gizmo_value_from_offset(GizmoCommonData *data,
+ GizmoInteraction *inter,
+ const float offset,
+ const bool constrained,
+ const bool inverted,
+ const bool use_precision)
{
- const float max = data->min + data->range;
-
- if (use_precision) {
- /* add delta offset of this step to total precision_offset */
- inter->precision_offset += offset - inter->prev_offset;
- }
- inter->prev_offset = offset;
-
- float ofs_new = inter->init_offset + offset - inter->precision_offset * (1.0f - GIZMO_PRECISION_FAC);
- float value;
-
- if (constrained) {
- value = gizmo_value_from_offset_constr(data->range_fac, data->min, data->range, ofs_new, inverted);
- }
- else {
- value = ofs_new;
- }
-
- /* clamp to custom range */
- if (data->is_custom_range_set) {
- CLAMP(value, data->min, max);
- }
-
- return value;
+ const float max = data->min + data->range;
+
+ if (use_precision) {
+ /* add delta offset of this step to total precision_offset */
+ inter->precision_offset += offset - inter->prev_offset;
+ }
+ inter->prev_offset = offset;
+
+ float ofs_new = inter->init_offset + offset -
+ inter->precision_offset * (1.0f - GIZMO_PRECISION_FAC);
+ float value;
+
+ if (constrained) {
+ value = gizmo_value_from_offset_constr(
+ data->range_fac, data->min, data->range, ofs_new, inverted);
+ }
+ else {
+ value = ofs_new;
+ }
+
+ /* clamp to custom range */
+ if (data->is_custom_range_set) {
+ CLAMP(value, data->min, max);
+ }
+
+ return value;
}
-void gizmo_property_data_update(
- wmGizmo *gz, GizmoCommonData *data, wmGizmoProperty *gz_prop,
- const bool constrained, const bool inverted)
+void gizmo_property_data_update(wmGizmo *gz,
+ GizmoCommonData *data,
+ wmGizmoProperty *gz_prop,
+ const bool constrained,
+ const bool inverted)
{
- if (gz_prop->custom_func.value_get_fn != NULL) {
- /* pass */
- }
- else if (gz_prop->prop != NULL) {
- /* pass */
- }
- else {
- data->offset = 0.0f;
- return;
- }
-
- float value = WM_gizmo_target_property_float_get(gz, gz_prop);
-
- if (constrained) {
- if (data->is_custom_range_set == false) {
- float range[2];
- if (WM_gizmo_target_property_float_range_get(gz, gz_prop, range)) {
- data->range = range[1] - range[0];
- data->min = range[0];
- }
- else {
- BLI_assert(0);
- }
- }
- data->offset = gizmo_offset_from_value_constr(data->range_fac, data->min, data->range, value, inverted);
- }
- else {
- data->offset = value;
- }
+ if (gz_prop->custom_func.value_get_fn != NULL) {
+ /* pass */
+ }
+ else if (gz_prop->prop != NULL) {
+ /* pass */
+ }
+ else {
+ data->offset = 0.0f;
+ return;
+ }
+
+ float value = WM_gizmo_target_property_float_get(gz, gz_prop);
+
+ if (constrained) {
+ if (data->is_custom_range_set == false) {
+ float range[2];
+ if (WM_gizmo_target_property_float_range_get(gz, gz_prop, range)) {
+ data->range = range[1] - range[0];
+ data->min = range[0];
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ data->offset = gizmo_offset_from_value_constr(
+ data->range_fac, data->min, data->range, value, inverted);
+ }
+ else {
+ data->offset = value;
+ }
}
-void gizmo_property_value_reset(
- bContext *C, const wmGizmo *gz, GizmoInteraction *inter,
- wmGizmoProperty *gz_prop)
+void gizmo_property_value_reset(bContext *C,
+ const wmGizmo *gz,
+ GizmoInteraction *inter,
+ wmGizmoProperty *gz_prop)
{
- WM_gizmo_target_property_float_set(C, gz, gz_prop, inter->init_value);
+ WM_gizmo_target_property_float_set(C, gz, gz_prop, inter->init_value);
}
/* -------------------------------------------------------------------- */
-void gizmo_color_get(
- const wmGizmo *gz, const bool highlight,
- float r_col[4])
+void gizmo_color_get(const wmGizmo *gz, const bool highlight, float r_col[4])
{
- if (highlight && !(gz->flag & WM_GIZMO_DRAW_HOVER)) {
- copy_v4_v4(r_col, gz->color_hi);
- }
- else {
- copy_v4_v4(r_col, gz->color);
- }
+ if (highlight && !(gz->flag & WM_GIZMO_DRAW_HOVER)) {
+ copy_v4_v4(r_col, gz->color_hi);
+ }
+ else {
+ copy_v4_v4(r_col, gz->color);
+ }
}
/* -------------------------------------------------------------------- */
@@ -161,80 +174,82 @@ void gizmo_color_get(
* Takes mouse coordinates and returns them in relation to the gizmo.
* Both 2D & 3D supported, use so we can use 2D gizmos in the 3D view.
*/
-bool gizmo_window_project_2d(
- bContext *C, const struct wmGizmo *gz, const float mval[2], int axis, bool use_offset,
- float r_co[2])
+bool gizmo_window_project_2d(bContext *C,
+ const struct wmGizmo *gz,
+ const float mval[2],
+ int axis,
+ bool use_offset,
+ float r_co[2])
{
- float mat[4][4];
- {
- float mat_identity[4][4];
- struct WM_GizmoMatrixParams params = {NULL};
- if (use_offset == false) {
- unit_m4(mat_identity);
- params.matrix_offset = mat_identity;
- }
- WM_gizmo_calc_matrix_final_params(gz, &params, mat);
- }
-
- /* 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);
-
- 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)) {
- float imat[4][4];
- invert_m4_m4(imat, mat);
- mul_m4_v3(imat, co);
- r_co[0] = co[(axis + 1) % 3];
- r_co[1] = co[(axis + 2) % 3];
- return true;
- }
- return false;
- }
- else {
- float co[3] = {mval[0], mval[1], 0.0f};
- float imat[4][4];
- invert_m4_m4(imat, mat);
- mul_m4_v3(imat, co);
- copy_v2_v2(r_co, co);
- return true;
- }
+ float mat[4][4];
+ {
+ float mat_identity[4][4];
+ struct WM_GizmoMatrixParams params = {NULL};
+ if (use_offset == false) {
+ unit_m4(mat_identity);
+ params.matrix_offset = mat_identity;
+ }
+ WM_gizmo_calc_matrix_final_params(gz, &params, mat);
+ }
+
+ /* 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);
+
+ 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)) {
+ float imat[4][4];
+ invert_m4_m4(imat, mat);
+ mul_m4_v3(imat, co);
+ r_co[0] = co[(axis + 1) % 3];
+ r_co[1] = co[(axis + 2) % 3];
+ return true;
+ }
+ return false;
+ }
+ else {
+ float co[3] = {mval[0], mval[1], 0.0f};
+ float imat[4][4];
+ invert_m4_m4(imat, mat);
+ mul_m4_v3(imat, co);
+ copy_v2_v2(r_co, co);
+ return true;
+ }
}
bool gizmo_window_project_3d(
- bContext *C, const struct wmGizmo *gz, const float mval[2], bool use_offset,
- float r_co[3])
+ bContext *C, const struct wmGizmo *gz, const float mval[2], bool use_offset, float r_co[3])
{
- float mat[4][4];
- {
- float mat_identity[4][4];
- struct WM_GizmoMatrixParams params = {NULL};
- if (use_offset == false) {
- unit_m4(mat_identity);
- params.matrix_offset = mat_identity;
- }
- WM_gizmo_calc_matrix_final_params(gz, &params, mat);
- }
-
- if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
- View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = 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);
- invert_m4(mat);
- mul_m4_v3(mat, r_co);
- return true;
- }
- else {
- float co[3] = {mval[0], mval[1], 0.0f};
- float imat[4][4];
- invert_m4_m4(imat, mat);
- mul_m4_v3(imat, co);
- copy_v2_v2(r_co, co);
- return true;
- }
+ float mat[4][4];
+ {
+ float mat_identity[4][4];
+ struct WM_GizmoMatrixParams params = {NULL};
+ if (use_offset == false) {
+ unit_m4(mat_identity);
+ params.matrix_offset = mat_identity;
+ }
+ WM_gizmo_calc_matrix_final_params(gz, &params, mat);
+ }
+
+ if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = 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);
+ invert_m4(mat);
+ mul_m4_v3(mat, r_co);
+ return true;
+ }
+ else {
+ float co[3] = {mval[0], mval[1], 0.0f};
+ float imat[4][4];
+ invert_m4_m4(imat, mat);
+ mul_m4_v3(imat, co);
+ copy_v2_v2(r_co, co);
+ return true;
+ }
}
diff --git a/source/blender/editors/gizmo_library/gizmo_types/arrow2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/arrow2d_gizmo.c
index b4bf4c6726c..c175bfb90ab 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/arrow2d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/arrow2d_gizmo.c
@@ -31,7 +31,6 @@
#include "BKE_context.h"
-
#include "GPU_draw.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
@@ -54,133 +53,130 @@
static void arrow2d_draw_geom(wmGizmo *gz, const float matrix[4][4], const float color[4])
{
- const float size = 0.11f;
- const float size_breadth = size / 2.0f;
- const float size_length = size * 1.7f;
- /* Subtract the length so the arrow fits in the hotspot. */
- const float arrow_length = RNA_float_get(gz->ptr, "length") - size_length;
- const float arrow_angle = RNA_float_get(gz->ptr, "angle");
+ const float size = 0.11f;
+ const float size_breadth = size / 2.0f;
+ const float size_length = size * 1.7f;
+ /* Subtract the length so the arrow fits in the hotspot. */
+ const float arrow_length = RNA_float_get(gz->ptr, "length") - size_length;
+ const float arrow_angle = RNA_float_get(gz->ptr, "angle");
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- GPU_matrix_push();
- GPU_matrix_mul(matrix);
- GPU_matrix_rotate_2d(RAD2DEGF(arrow_angle));
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix);
+ GPU_matrix_rotate_2d(RAD2DEGF(arrow_angle));
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4fv(color);
+ immUniformColor4fv(color);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, 0.0f, 0.0f);
- immVertex2f(pos, 0.0f, arrow_length);
- immEnd();
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, 0.0f, 0.0f);
+ immVertex2f(pos, 0.0f, arrow_length);
+ immEnd();
- immBegin(GPU_PRIM_TRIS, 3);
- immVertex2f(pos, size_breadth, arrow_length);
- immVertex2f(pos, -size_breadth, arrow_length);
- immVertex2f(pos, 0.0f, arrow_length + size_length);
- immEnd();
+ immBegin(GPU_PRIM_TRIS, 3);
+ immVertex2f(pos, size_breadth, arrow_length);
+ immVertex2f(pos, -size_breadth, arrow_length);
+ immVertex2f(pos, 0.0f, arrow_length + size_length);
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
- GPU_matrix_pop();
+ GPU_matrix_pop();
}
static void gizmo_arrow2d_draw(const bContext *UNUSED(C), wmGizmo *gz)
{
- float color[4];
+ float color[4];
- float matrix_final[4][4];
+ float matrix_final[4][4];
- gizmo_color_get(gz, gz->state & WM_GIZMO_STATE_HIGHLIGHT, color);
+ gizmo_color_get(gz, gz->state & WM_GIZMO_STATE_HIGHLIGHT, color);
- GPU_line_width(gz->line_width);
+ GPU_line_width(gz->line_width);
- WM_gizmo_calc_matrix_final(gz, matrix_final);
+ WM_gizmo_calc_matrix_final(gz, matrix_final);
- GPU_blend(true);
- arrow2d_draw_geom(gz, matrix_final, color);
- GPU_blend(false);
+ GPU_blend(true);
+ arrow2d_draw_geom(gz, matrix_final, color);
+ GPU_blend(false);
- if (gz->interaction_data) {
- GizmoInteraction *inter = gz->interaction_data;
+ if (gz->interaction_data) {
+ GizmoInteraction *inter = gz->interaction_data;
- GPU_blend(true);
- arrow2d_draw_geom(gz, inter->init_matrix_final, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f});
- GPU_blend(false);
- }
+ GPU_blend(true);
+ arrow2d_draw_geom(gz, inter->init_matrix_final, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f});
+ GPU_blend(false);
+ }
}
static void gizmo_arrow2d_setup(wmGizmo *gz)
{
- gz->flag |= WM_GIZMO_DRAW_MODAL;
+ gz->flag |= WM_GIZMO_DRAW_MODAL;
}
-static int gizmo_arrow2d_invoke(
- bContext *UNUSED(C), wmGizmo *gz, const wmEvent *UNUSED(event))
+static int gizmo_arrow2d_invoke(bContext *UNUSED(C), wmGizmo *gz, const wmEvent *UNUSED(event))
{
- GizmoInteraction *inter = MEM_callocN(sizeof(GizmoInteraction), __func__);
+ GizmoInteraction *inter = MEM_callocN(sizeof(GizmoInteraction), __func__);
- copy_m4_m4(inter->init_matrix_basis, gz->matrix_basis);
- WM_gizmo_calc_matrix_final(gz, inter->init_matrix_final);
+ copy_m4_m4(inter->init_matrix_basis, gz->matrix_basis);
+ WM_gizmo_calc_matrix_final(gz, inter->init_matrix_final);
- gz->interaction_data = inter;
+ gz->interaction_data = inter;
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
-static int gizmo_arrow2d_test_select(
- bContext *UNUSED(C), wmGizmo *gz, const int mval[2])
+static int gizmo_arrow2d_test_select(bContext *UNUSED(C), wmGizmo *gz, const int mval[2])
{
- const float mval_fl[2] = {UNPACK2(mval)};
- const float arrow_length = RNA_float_get(gz->ptr, "length");
- const float arrow_angle = RNA_float_get(gz->ptr, "angle");
- const float line_len = arrow_length * gz->scale_final;
- float mval_local[2];
-
- copy_v2_v2(mval_local, mval_fl);
- sub_v2_v2(mval_local, gz->matrix_basis[3]);
-
- float line[2][2];
- line[0][0] = line[0][1] = line[1][0] = 0.0f;
- line[1][1] = line_len;
-
- /* rotate only if needed */
- if (arrow_angle != 0.0f) {
- float rot_point[2];
- copy_v2_v2(rot_point, line[1]);
- rotate_v2_v2fl(line[1], rot_point, arrow_angle);
- }
-
- /* arrow line intersection check */
- float isect_1[2], isect_2[2];
- const int isect = isect_line_sphere_v2(
- line[0], line[1], mval_local, GIZMO_HOTSPOT + gz->line_width * 0.5f,
- isect_1, isect_2);
-
- if (isect > 0) {
- float line_ext[2][2]; /* extended line for segment check including hotspot */
- copy_v2_v2(line_ext[0], line[0]);
- line_ext[1][0] = line[1][0] + GIZMO_HOTSPOT * ((line[1][0] - line[0][0]) / line_len);
- line_ext[1][1] = line[1][1] + GIZMO_HOTSPOT * ((line[1][1] - line[0][1]) / line_len);
-
- const float lambda_1 = line_point_factor_v2(isect_1, line_ext[0], line_ext[1]);
- if (isect == 1) {
- if (IN_RANGE_INCL(lambda_1, 0.0f, 1.0f)) {
- return 0;
- }
- }
- else {
- BLI_assert(isect == 2);
- const float lambda_2 = line_point_factor_v2(isect_2, line_ext[0], line_ext[1]);
- if (IN_RANGE_INCL(lambda_1, 0.0f, 1.0f) && IN_RANGE_INCL(lambda_2, 0.0f, 1.0f)) {
- return 0;
- }
- }
- }
-
- return -1;
+ const float mval_fl[2] = {UNPACK2(mval)};
+ const float arrow_length = RNA_float_get(gz->ptr, "length");
+ const float arrow_angle = RNA_float_get(gz->ptr, "angle");
+ const float line_len = arrow_length * gz->scale_final;
+ float mval_local[2];
+
+ copy_v2_v2(mval_local, mval_fl);
+ sub_v2_v2(mval_local, gz->matrix_basis[3]);
+
+ float line[2][2];
+ line[0][0] = line[0][1] = line[1][0] = 0.0f;
+ line[1][1] = line_len;
+
+ /* rotate only if needed */
+ if (arrow_angle != 0.0f) {
+ float rot_point[2];
+ copy_v2_v2(rot_point, line[1]);
+ rotate_v2_v2fl(line[1], rot_point, arrow_angle);
+ }
+
+ /* arrow line intersection check */
+ float isect_1[2], isect_2[2];
+ const int isect = isect_line_sphere_v2(
+ line[0], line[1], mval_local, GIZMO_HOTSPOT + gz->line_width * 0.5f, isect_1, isect_2);
+
+ if (isect > 0) {
+ float line_ext[2][2]; /* extended line for segment check including hotspot */
+ copy_v2_v2(line_ext[0], line[0]);
+ line_ext[1][0] = line[1][0] + GIZMO_HOTSPOT * ((line[1][0] - line[0][0]) / line_len);
+ line_ext[1][1] = line[1][1] + GIZMO_HOTSPOT * ((line[1][1] - line[0][1]) / line_len);
+
+ const float lambda_1 = line_point_factor_v2(isect_1, line_ext[0], line_ext[1]);
+ if (isect == 1) {
+ if (IN_RANGE_INCL(lambda_1, 0.0f, 1.0f)) {
+ return 0;
+ }
+ }
+ else {
+ BLI_assert(isect == 2);
+ const float lambda_2 = line_point_factor_v2(isect_2, line_ext[0], line_ext[1]);
+ if (IN_RANGE_INCL(lambda_1, 0.0f, 1.0f) && IN_RANGE_INCL(lambda_2, 0.0f, 1.0f)) {
+ return 0;
+ }
+ }
+ }
+
+ return -1;
}
/* -------------------------------------------------------------------- */
@@ -190,27 +186,34 @@ static int gizmo_arrow2d_test_select(
static void GIZMO_GT_arrow_2d(wmGizmoType *gzt)
{
- /* identifiers */
- gzt->idname = "GIZMO_GT_arrow_2d";
-
- /* api callbacks */
- gzt->draw = gizmo_arrow2d_draw;
- gzt->setup = gizmo_arrow2d_setup;
- gzt->invoke = gizmo_arrow2d_invoke;
- gzt->test_select = gizmo_arrow2d_test_select;
-
- gzt->struct_size = sizeof(wmGizmo);
-
- /* rna */
- RNA_def_float(gzt->srna, "length", 1.0f, 0.0f, FLT_MAX, "Arrow Line Length", "", 0.0f, FLT_MAX);
- RNA_def_float_rotation(
- gzt->srna, "angle", 0, NULL, DEG2RADF(-360.0f), DEG2RADF(360.0f),
- "Roll", "", DEG2RADF(-360.0f), DEG2RADF(360.0f));
+ /* identifiers */
+ gzt->idname = "GIZMO_GT_arrow_2d";
+
+ /* api callbacks */
+ gzt->draw = gizmo_arrow2d_draw;
+ gzt->setup = gizmo_arrow2d_setup;
+ gzt->invoke = gizmo_arrow2d_invoke;
+ gzt->test_select = gizmo_arrow2d_test_select;
+
+ gzt->struct_size = sizeof(wmGizmo);
+
+ /* rna */
+ RNA_def_float(gzt->srna, "length", 1.0f, 0.0f, FLT_MAX, "Arrow Line Length", "", 0.0f, FLT_MAX);
+ RNA_def_float_rotation(gzt->srna,
+ "angle",
+ 0,
+ NULL,
+ DEG2RADF(-360.0f),
+ DEG2RADF(360.0f),
+ "Roll",
+ "",
+ DEG2RADF(-360.0f),
+ DEG2RADF(360.0f));
}
void ED_gizmotypes_arrow_2d(void)
{
- WM_gizmotype_append(GIZMO_GT_arrow_2d);
+ WM_gizmotype_append(GIZMO_GT_arrow_2d);
}
/** \} */
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 3e3aa13f184..d23965269ab 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c
@@ -32,7 +32,6 @@
* - `matrix[2]` is the arrow direction (for all arrowes).
*/
-
#include "BLI_math.h"
#include "DNA_view3d_types.h"
@@ -66,329 +65,323 @@
//#define USE_GIZMO_CUSTOM_ARROWS
typedef struct ArrowGizmo3D {
- wmGizmo gizmo;
- GizmoCommonData data;
+ wmGizmo gizmo;
+ GizmoCommonData data;
} ArrowGizmo3D;
-
/* -------------------------------------------------------------------- */
static void gizmo_arrow_matrix_basis_get(const wmGizmo *gz, float r_matrix[4][4])
{
- ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
+ ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
- copy_m4_m4(r_matrix, arrow->gizmo.matrix_basis);
- madd_v3_v3fl(r_matrix[3], arrow->gizmo.matrix_basis[2], arrow->data.offset);
+ copy_m4_m4(r_matrix, arrow->gizmo.matrix_basis);
+ madd_v3_v3fl(r_matrix[3], arrow->gizmo.matrix_basis[2], arrow->data.offset);
}
static void arrow_draw_geom(const ArrowGizmo3D *arrow, const bool select, const float color[4])
{
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- bool unbind_shader = true;
- 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);
-
- if (draw_style == ED_GIZMO_ARROW_STYLE_CROSS) {
- immUniformColor4fv(color);
-
- immBegin(GPU_PRIM_LINES, 4);
- immVertex3f(pos, -1.0f, 0.0f, 0.0f);
- immVertex3f(pos, 1.0f, 0.0f, 0.0f);
- immVertex3f(pos, 0.0f, -1.0f, 0.0f);
- immVertex3f(pos, 0.0f, 1.0f, 0.0f);
- immEnd();
- }
- else if (draw_style == ED_GIZMO_ARROW_STYLE_CONE) {
- float aspect[2];
- RNA_float_get_array(arrow->gizmo.ptr, "aspect", aspect);
- const float unitx = aspect[0];
- const float unity = aspect[1];
- const float vec[4][3] = {
- {-unitx, -unity, 0},
- { unitx, -unity, 0},
- { unitx, unity, 0},
- {-unitx, unity, 0},
- };
-
- GPU_line_width(arrow->gizmo.line_width);
- wm_gizmo_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GPU_PRIM_LINE_LOOP);
- }
- else {
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ bool unbind_shader = true;
+ 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);
+
+ if (draw_style == ED_GIZMO_ARROW_STYLE_CROSS) {
+ immUniformColor4fv(color);
+
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex3f(pos, -1.0f, 0.0f, 0.0f);
+ immVertex3f(pos, 1.0f, 0.0f, 0.0f);
+ immVertex3f(pos, 0.0f, -1.0f, 0.0f);
+ immVertex3f(pos, 0.0f, 1.0f, 0.0f);
+ immEnd();
+ }
+ else if (draw_style == ED_GIZMO_ARROW_STYLE_CONE) {
+ float aspect[2];
+ RNA_float_get_array(arrow->gizmo.ptr, "aspect", aspect);
+ const float unitx = aspect[0];
+ const float unity = aspect[1];
+ const float vec[4][3] = {
+ {-unitx, -unity, 0},
+ {unitx, -unity, 0},
+ {unitx, unity, 0},
+ {-unitx, unity, 0},
+ };
+
+ GPU_line_width(arrow->gizmo.line_width);
+ wm_gizmo_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GPU_PRIM_LINE_LOOP);
+ }
+ else {
#ifdef USE_GIZMO_CUSTOM_ARROWS
- wm_gizmo_geometryinfo_draw(&wm_gizmo_geom_data_arrow, select, color);
+ wm_gizmo_geometryinfo_draw(&wm_gizmo_geom_data_arrow, select, color);
#else
- const float arrow_length = RNA_float_get(arrow->gizmo.ptr, "length");
-
- const float vec[2][3] = {
- {0.0f, 0.0f, 0.0f},
- {0.0f, 0.0f, arrow_length},
- };
-
- if (draw_options & ED_GIZMO_ARROW_DRAW_FLAG_STEM) {
- GPU_line_width(arrow->gizmo.line_width);
- wm_gizmo_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GPU_PRIM_LINE_STRIP);
- }
- else {
- immUniformColor4fv(color);
- }
-
- /* *** draw arrow head *** */
-
- GPU_matrix_push();
-
- if (draw_style == ED_GIZMO_ARROW_STYLE_BOX) {
- const float size = 0.05f;
-
- /* translate to line end with some extra offset so box starts exactly where line ends */
- GPU_matrix_translate_3f(0.0f, 0.0f, arrow_length + size);
- /* scale down to box size */
- GPU_matrix_scale_3f(size, size, size);
-
- /* draw cube */
- immUnbindProgram();
- unbind_shader = false;
- wm_gizmo_geometryinfo_draw(&wm_gizmo_geom_data_cube, select, color);
- }
- else {
- BLI_assert(draw_style == ED_GIZMO_ARROW_STYLE_NORMAL);
-
- const float len = 0.25f;
- const float width = 0.06f;
-
- /* translate to line end */
- GPU_matrix_translate_3f(0.0f, 0.0f, arrow_length);
-
- imm_draw_circle_fill_3d(pos, 0.0, 0.0, width, 8);
- imm_draw_cylinder_fill_3d(pos, width, 0.0, len, 8, 1);
- }
-
- GPU_matrix_pop();
-#endif /* USE_GIZMO_CUSTOM_ARROWS */
- }
-
- if (unbind_shader) {
- immUnbindProgram();
- }
+ const float arrow_length = RNA_float_get(arrow->gizmo.ptr, "length");
+
+ const float vec[2][3] = {
+ {0.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, arrow_length},
+ };
+
+ if (draw_options & ED_GIZMO_ARROW_DRAW_FLAG_STEM) {
+ GPU_line_width(arrow->gizmo.line_width);
+ wm_gizmo_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GPU_PRIM_LINE_STRIP);
+ }
+ else {
+ immUniformColor4fv(color);
+ }
+
+ /* *** draw arrow head *** */
+
+ GPU_matrix_push();
+
+ if (draw_style == ED_GIZMO_ARROW_STYLE_BOX) {
+ const float size = 0.05f;
+
+ /* translate to line end with some extra offset so box starts exactly where line ends */
+ GPU_matrix_translate_3f(0.0f, 0.0f, arrow_length + size);
+ /* scale down to box size */
+ GPU_matrix_scale_3f(size, size, size);
+
+ /* draw cube */
+ immUnbindProgram();
+ unbind_shader = false;
+ wm_gizmo_geometryinfo_draw(&wm_gizmo_geom_data_cube, select, color);
+ }
+ else {
+ BLI_assert(draw_style == ED_GIZMO_ARROW_STYLE_NORMAL);
+
+ const float len = 0.25f;
+ const float width = 0.06f;
+
+ /* translate to line end */
+ GPU_matrix_translate_3f(0.0f, 0.0f, arrow_length);
+
+ imm_draw_circle_fill_3d(pos, 0.0, 0.0, width, 8);
+ imm_draw_cylinder_fill_3d(pos, width, 0.0, len, 8, 1);
+ }
+
+ GPU_matrix_pop();
+#endif /* USE_GIZMO_CUSTOM_ARROWS */
+ }
+
+ if (unbind_shader) {
+ immUnbindProgram();
+ }
}
static void arrow_draw_intern(ArrowGizmo3D *arrow, const bool select, const bool highlight)
{
- wmGizmo *gz = &arrow->gizmo;
- float color[4];
- float matrix_final[4][4];
+ wmGizmo *gz = &arrow->gizmo;
+ float color[4];
+ float matrix_final[4][4];
- gizmo_color_get(gz, highlight, color);
+ gizmo_color_get(gz, highlight, color);
- WM_gizmo_calc_matrix_final(gz, matrix_final);
+ WM_gizmo_calc_matrix_final(gz, matrix_final);
- GPU_matrix_push();
- GPU_matrix_mul(matrix_final);
- GPU_blend(true);
- arrow_draw_geom(arrow, select, color);
- GPU_blend(false);
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix_final);
+ GPU_blend(true);
+ arrow_draw_geom(arrow, select, color);
+ GPU_blend(false);
- GPU_matrix_pop();
+ GPU_matrix_pop();
- if (gz->interaction_data) {
- GizmoInteraction *inter = gz->interaction_data;
+ if (gz->interaction_data) {
+ GizmoInteraction *inter = gz->interaction_data;
- GPU_matrix_push();
- GPU_matrix_mul(inter->init_matrix_final);
+ GPU_matrix_push();
+ GPU_matrix_mul(inter->init_matrix_final);
+ GPU_blend(true);
+ arrow_draw_geom(arrow, select, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f});
+ GPU_blend(false);
- GPU_blend(true);
- arrow_draw_geom(arrow, select, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f});
- GPU_blend(false);
-
- GPU_matrix_pop();
- }
+ GPU_matrix_pop();
+ }
}
-static void gizmo_arrow_draw_select(
- const bContext *UNUSED(C), wmGizmo *gz,
- int select_id)
+static void gizmo_arrow_draw_select(const bContext *UNUSED(C), wmGizmo *gz, int select_id)
{
- GPU_select_load_id(select_id);
- arrow_draw_intern((ArrowGizmo3D *)gz, true, false);
+ GPU_select_load_id(select_id);
+ arrow_draw_intern((ArrowGizmo3D *)gz, true, false);
}
static void gizmo_arrow_draw(const bContext *UNUSED(C), wmGizmo *gz)
{
- arrow_draw_intern((ArrowGizmo3D *)gz, false, (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0);
+ arrow_draw_intern((ArrowGizmo3D *)gz, false, (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0);
}
/**
* Calculate arrow offset independent from prop min value,
* meaning the range will not be offset by min value first.
*/
-static int gizmo_arrow_modal(
- bContext *C, wmGizmo *gz, const wmEvent *event,
- eWM_GizmoFlagTweak tweak_flag)
+static int gizmo_arrow_modal(bContext *C,
+ wmGizmo *gz,
+ const wmEvent *event,
+ eWM_GizmoFlagTweak tweak_flag)
{
- if (event->type != MOUSEMOVE) {
- return OPERATOR_RUNNING_MODAL;
- }
- ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
- GizmoInteraction *inter = gz->interaction_data;
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
-
- float offset[3];
- float facdir = 1.0f;
-
- /* (src, dst) */
- struct {
- float mval[2];
- float ray_origin[3], ray_direction[3];
- float location[3];
- } proj[2] = {
- {.mval = {UNPACK2(inter->init_mval)}},
- {.mval = {UNPACK2(event->mval)}},
- };
-
- float arrow_co[3];
- float arrow_no[3];
- copy_v3_v3(arrow_co, inter->init_matrix_basis[3]);
- normalize_v3_v3(arrow_no, arrow->gizmo.matrix_basis[2]);
-
- 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);
- /* 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) {
- normalize_v3_v3(arrow_no, rv3d->viewinv[1]);
- }
- }
-
- float arrow_no_proj[3];
- project_plane_v3_v3v3(arrow_no_proj, arrow_no, proj[j].ray_direction);
-
- normalize_v3(arrow_no_proj);
-
- float plane[4];
- plane_from_point_normal_v3(plane, proj[j].ray_origin, arrow_no_proj);
-
- float lambda;
- if (isect_ray_plane_v3(arrow_co, arrow_no, plane, &lambda, false)) {
- madd_v3_v3v3fl(proj[j].location, arrow_co, arrow_no, lambda);
- ok++;
- }
- }
-
- if (ok != 2) {
- return OPERATOR_RUNNING_MODAL;
- }
-
- sub_v3_v3v3(offset, proj[1].location, proj[0].location);
- facdir = dot_v3v3(arrow_no, offset) < 0.0f ? -1 : 1;
-
- GizmoCommonData *data = &arrow->data;
- const float ofs_new = facdir * len_v3(offset);
-
- wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
-
- /* set the property for the operator and call its modal function */
- if (WM_gizmo_target_property_is_valid(gz_prop)) {
- const int transform_flag = RNA_enum_get(arrow->gizmo.ptr, "transform");
- const bool constrained = (transform_flag & ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED) != 0;
- const bool inverted = (transform_flag & ED_GIZMO_ARROW_XFORM_FLAG_INVERTED) != 0;
- const bool use_precision = (tweak_flag & WM_GIZMO_TWEAK_PRECISE) != 0;
- float value = gizmo_value_from_offset(data, inter, ofs_new, constrained, inverted, use_precision);
-
- WM_gizmo_target_property_float_set(C, gz, gz_prop, value);
- /* get clamped value */
- value = WM_gizmo_target_property_float_get(gz, gz_prop);
-
- data->offset = gizmo_offset_from_value(data, value, constrained, inverted);
- }
- else {
- data->offset = ofs_new;
- }
-
- /* tag the region for redraw */
- ED_region_tag_redraw(ar);
- WM_event_add_mousemove(C);
-
- return OPERATOR_RUNNING_MODAL;
+ if (event->type != MOUSEMOVE) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+ ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
+ GizmoInteraction *inter = gz->interaction_data;
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ float offset[3];
+ float facdir = 1.0f;
+
+ /* (src, dst) */
+ struct {
+ float mval[2];
+ float ray_origin[3], ray_direction[3];
+ float location[3];
+ } proj[2] = {
+ {.mval = {UNPACK2(inter->init_mval)}},
+ {.mval = {UNPACK2(event->mval)}},
+ };
+
+ float arrow_co[3];
+ float arrow_no[3];
+ copy_v3_v3(arrow_co, inter->init_matrix_basis[3]);
+ normalize_v3_v3(arrow_no, arrow->gizmo.matrix_basis[2]);
+
+ 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);
+ /* 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) {
+ normalize_v3_v3(arrow_no, rv3d->viewinv[1]);
+ }
+ }
+
+ float arrow_no_proj[3];
+ project_plane_v3_v3v3(arrow_no_proj, arrow_no, proj[j].ray_direction);
+
+ normalize_v3(arrow_no_proj);
+
+ float plane[4];
+ plane_from_point_normal_v3(plane, proj[j].ray_origin, arrow_no_proj);
+
+ float lambda;
+ if (isect_ray_plane_v3(arrow_co, arrow_no, plane, &lambda, false)) {
+ madd_v3_v3v3fl(proj[j].location, arrow_co, arrow_no, lambda);
+ ok++;
+ }
+ }
+
+ if (ok != 2) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ sub_v3_v3v3(offset, proj[1].location, proj[0].location);
+ facdir = dot_v3v3(arrow_no, offset) < 0.0f ? -1 : 1;
+
+ GizmoCommonData *data = &arrow->data;
+ const float ofs_new = facdir * len_v3(offset);
+
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+
+ /* set the property for the operator and call its modal function */
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ const int transform_flag = RNA_enum_get(arrow->gizmo.ptr, "transform");
+ const bool constrained = (transform_flag & ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED) != 0;
+ const bool inverted = (transform_flag & ED_GIZMO_ARROW_XFORM_FLAG_INVERTED) != 0;
+ const bool use_precision = (tweak_flag & WM_GIZMO_TWEAK_PRECISE) != 0;
+ float value = gizmo_value_from_offset(
+ data, inter, ofs_new, constrained, inverted, use_precision);
+
+ WM_gizmo_target_property_float_set(C, gz, gz_prop, value);
+ /* get clamped value */
+ value = WM_gizmo_target_property_float_get(gz, gz_prop);
+
+ data->offset = gizmo_offset_from_value(data, value, constrained, inverted);
+ }
+ else {
+ data->offset = ofs_new;
+ }
+
+ /* tag the region for redraw */
+ ED_region_tag_redraw(ar);
+ WM_event_add_mousemove(C);
+
+ return OPERATOR_RUNNING_MODAL;
}
static void gizmo_arrow_setup(wmGizmo *gz)
{
- ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
+ ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
- arrow->gizmo.flag |= WM_GIZMO_DRAW_MODAL;
+ arrow->gizmo.flag |= WM_GIZMO_DRAW_MODAL;
- arrow->data.range_fac = 1.0f;
+ arrow->data.range_fac = 1.0f;
}
-static int gizmo_arrow_invoke(
- bContext *UNUSED(C), wmGizmo *gz, const wmEvent *event)
+static int gizmo_arrow_invoke(bContext *UNUSED(C), wmGizmo *gz, const wmEvent *event)
{
- ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
- GizmoInteraction *inter = MEM_callocN(sizeof(GizmoInteraction), __func__);
- wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
+ GizmoInteraction *inter = MEM_callocN(sizeof(GizmoInteraction), __func__);
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
- /* Some gizmos don't use properties. */
- if (WM_gizmo_target_property_is_valid(gz_prop)) {
- inter->init_value = WM_gizmo_target_property_float_get(gz, gz_prop);
- }
+ /* Some gizmos don't use properties. */
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ inter->init_value = WM_gizmo_target_property_float_get(gz, gz_prop);
+ }
- inter->init_offset = arrow->data.offset;
+ inter->init_offset = arrow->data.offset;
- inter->init_mval[0] = event->mval[0];
- inter->init_mval[1] = event->mval[1];
+ inter->init_mval[0] = event->mval[0];
+ inter->init_mval[1] = event->mval[1];
- gizmo_arrow_matrix_basis_get(gz, inter->init_matrix_basis);
- WM_gizmo_calc_matrix_final(gz, inter->init_matrix_final);
+ gizmo_arrow_matrix_basis_get(gz, inter->init_matrix_basis);
+ WM_gizmo_calc_matrix_final(gz, inter->init_matrix_final);
- gz->interaction_data = inter;
+ gz->interaction_data = inter;
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static void gizmo_arrow_property_update(wmGizmo *gz, wmGizmoProperty *gz_prop)
{
- ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
- const int transform_flag = RNA_enum_get(arrow->gizmo.ptr, "transform");
- const bool constrained = (transform_flag & ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED) != 0;
- const bool inverted = (transform_flag & ED_GIZMO_ARROW_XFORM_FLAG_INVERTED) != 0;
- gizmo_property_data_update(gz, &arrow->data, gz_prop, constrained, inverted);
+ ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
+ const int transform_flag = RNA_enum_get(arrow->gizmo.ptr, "transform");
+ const bool constrained = (transform_flag & ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED) != 0;
+ const bool inverted = (transform_flag & ED_GIZMO_ARROW_XFORM_FLAG_INVERTED) != 0;
+ gizmo_property_data_update(gz, &arrow->data, gz_prop, constrained, inverted);
}
static void gizmo_arrow_exit(bContext *C, wmGizmo *gz, const bool cancel)
{
- ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
- GizmoCommonData *data = &arrow->data;
- wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
- const bool is_prop_valid = WM_gizmo_target_property_is_valid(gz_prop);
-
- if (!cancel) {
- /* Assign incase applying the operation needs an updated offset
- * editmesh bisect needs this. */
- if (is_prop_valid) {
- const int transform_flag = RNA_enum_get(arrow->gizmo.ptr, "transform");
- const bool constrained = (transform_flag & ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED) != 0;
- const bool inverted = (transform_flag & ED_GIZMO_ARROW_XFORM_FLAG_INVERTED) != 0;
- const float value = WM_gizmo_target_property_float_get(gz, gz_prop);
- data->offset = gizmo_offset_from_value(data, value, constrained, inverted);
- }
- return;
- }
-
- GizmoInteraction *inter = gz->interaction_data;
- if (is_prop_valid) {
- gizmo_property_value_reset(C, gz, inter, gz_prop);
- }
- data->offset = inter->init_offset;
+ ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
+ GizmoCommonData *data = &arrow->data;
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ const bool is_prop_valid = WM_gizmo_target_property_is_valid(gz_prop);
+
+ if (!cancel) {
+ /* Assign incase applying the operation needs an updated offset
+ * editmesh bisect needs this. */
+ if (is_prop_valid) {
+ const int transform_flag = RNA_enum_get(arrow->gizmo.ptr, "transform");
+ const bool constrained = (transform_flag & ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED) != 0;
+ const bool inverted = (transform_flag & ED_GIZMO_ARROW_XFORM_FLAG_INVERTED) != 0;
+ const float value = WM_gizmo_target_property_float_get(gz, gz_prop);
+ data->offset = gizmo_offset_from_value(data, value, constrained, inverted);
+ }
+ return;
+ }
+
+ GizmoInteraction *inter = gz->interaction_data;
+ if (is_prop_valid) {
+ gizmo_property_value_reset(C, gz, inter, gz_prop);
+ }
+ data->offset = inter->init_offset;
}
-
/* -------------------------------------------------------------------- */
/** \name Arrow Gizmo API
*
@@ -401,16 +394,16 @@ static void gizmo_arrow_exit(bContext *C, wmGizmo *gz, const bool cancel)
*/
void ED_gizmo_arrow3d_set_ui_range(wmGizmo *gz, const float min, const float max)
{
- ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
+ ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
- BLI_assert(min < max);
- BLI_assert(!(WM_gizmo_target_property_is_valid(WM_gizmo_target_property_find(gz, "offset")) &&
- "Make sure this function is called before WM_gizmo_target_property_def_rna"));
+ BLI_assert(min < max);
+ BLI_assert(!(WM_gizmo_target_property_is_valid(WM_gizmo_target_property_find(gz, "offset")) &&
+ "Make sure this function is called before WM_gizmo_target_property_def_rna"));
- arrow->data.range = max - min;
- arrow->data.min = min;
- arrow->data.max = max;
- arrow->data.is_custom_range_set = true;
+ arrow->data.range = max - min;
+ arrow->data.min = min;
+ arrow->data.max = max;
+ arrow->data.is_custom_range_set = true;
}
/**
@@ -420,70 +413,72 @@ void ED_gizmo_arrow3d_set_ui_range(wmGizmo *gz, const float min, const float max
*/
void ED_gizmo_arrow3d_set_range_fac(wmGizmo *gz, const float range_fac)
{
- ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
- BLI_assert(!(WM_gizmo_target_property_is_valid(WM_gizmo_target_property_find(gz, "offset")) &&
- "Make sure this function is called before WM_gizmo_target_property_def_rna"));
+ ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
+ BLI_assert(!(WM_gizmo_target_property_is_valid(WM_gizmo_target_property_find(gz, "offset")) &&
+ "Make sure this function is called before WM_gizmo_target_property_def_rna"));
- arrow->data.range_fac = range_fac;
+ arrow->data.range_fac = range_fac;
}
static void GIZMO_GT_arrow_3d(wmGizmoType *gzt)
{
- /* identifiers */
- gzt->idname = "GIZMO_GT_arrow_3d";
-
- /* api callbacks */
- gzt->draw = gizmo_arrow_draw;
- gzt->draw_select = gizmo_arrow_draw_select;
- gzt->matrix_basis_get = gizmo_arrow_matrix_basis_get;
- gzt->modal = gizmo_arrow_modal;
- gzt->setup = gizmo_arrow_setup;
- gzt->invoke = gizmo_arrow_invoke;
- gzt->property_update = gizmo_arrow_property_update;
- gzt->exit = gizmo_arrow_exit;
-
- gzt->struct_size = sizeof(ArrowGizmo3D);
-
- /* rna */
- static EnumPropertyItem rna_enum_draw_style_items[] = {
- {ED_GIZMO_ARROW_STYLE_NORMAL, "NORMAL", 0, "Normal", ""},
- {ED_GIZMO_ARROW_STYLE_CROSS, "CROSS", 0, "Cross", ""},
- {ED_GIZMO_ARROW_STYLE_BOX, "BOX", 0, "Box", ""},
- {ED_GIZMO_ARROW_STYLE_CONE, "CONE", 0, "Cone", ""},
- {0, NULL, 0, NULL, NULL},
- };
- static EnumPropertyItem rna_enum_draw_options_items[] = {
- {ED_GIZMO_ARROW_DRAW_FLAG_STEM, "STEM", 0, "Stem", ""},
- {0, NULL, 0, NULL, NULL},
- };
- static EnumPropertyItem rna_enum_transform_items[] = {
- {ED_GIZMO_ARROW_XFORM_FLAG_INVERTED, "INVERT", 0, "Inverted", ""},
- {ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED, "CONSTRAIN", 0, "Constrained", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- RNA_def_enum(
- gzt->srna, "draw_style", rna_enum_draw_style_items,
- ED_GIZMO_ARROW_STYLE_NORMAL,
- "Draw Style", "");
- RNA_def_enum_flag(
- gzt->srna, "draw_options", rna_enum_draw_options_items,
- ED_GIZMO_ARROW_DRAW_FLAG_STEM,
- "Draw Options", "");
- RNA_def_enum_flag(
- gzt->srna, "transform", rna_enum_transform_items,
- 0,
- "Transform", "");
-
- RNA_def_float(gzt->srna, "length", 1.0f, 0.0f, FLT_MAX, "Arrow Line Length", "", 0.0f, FLT_MAX);
- RNA_def_float_vector(gzt->srna, "aspect", 2, NULL, 0, FLT_MAX, "Aspect", "Cone/box style only", 0.0f, FLT_MAX);
-
- WM_gizmotype_target_property_def(gzt, "offset", PROP_FLOAT, 1);
+ /* identifiers */
+ gzt->idname = "GIZMO_GT_arrow_3d";
+
+ /* api callbacks */
+ gzt->draw = gizmo_arrow_draw;
+ gzt->draw_select = gizmo_arrow_draw_select;
+ gzt->matrix_basis_get = gizmo_arrow_matrix_basis_get;
+ gzt->modal = gizmo_arrow_modal;
+ gzt->setup = gizmo_arrow_setup;
+ gzt->invoke = gizmo_arrow_invoke;
+ gzt->property_update = gizmo_arrow_property_update;
+ gzt->exit = gizmo_arrow_exit;
+
+ gzt->struct_size = sizeof(ArrowGizmo3D);
+
+ /* rna */
+ static EnumPropertyItem rna_enum_draw_style_items[] = {
+ {ED_GIZMO_ARROW_STYLE_NORMAL, "NORMAL", 0, "Normal", ""},
+ {ED_GIZMO_ARROW_STYLE_CROSS, "CROSS", 0, "Cross", ""},
+ {ED_GIZMO_ARROW_STYLE_BOX, "BOX", 0, "Box", ""},
+ {ED_GIZMO_ARROW_STYLE_CONE, "CONE", 0, "Cone", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+ static EnumPropertyItem rna_enum_draw_options_items[] = {
+ {ED_GIZMO_ARROW_DRAW_FLAG_STEM, "STEM", 0, "Stem", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+ static EnumPropertyItem rna_enum_transform_items[] = {
+ {ED_GIZMO_ARROW_XFORM_FLAG_INVERTED, "INVERT", 0, "Inverted", ""},
+ {ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED, "CONSTRAIN", 0, "Constrained", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ RNA_def_enum(gzt->srna,
+ "draw_style",
+ rna_enum_draw_style_items,
+ ED_GIZMO_ARROW_STYLE_NORMAL,
+ "Draw Style",
+ "");
+ RNA_def_enum_flag(gzt->srna,
+ "draw_options",
+ rna_enum_draw_options_items,
+ ED_GIZMO_ARROW_DRAW_FLAG_STEM,
+ "Draw Options",
+ "");
+ RNA_def_enum_flag(gzt->srna, "transform", rna_enum_transform_items, 0, "Transform", "");
+
+ RNA_def_float(gzt->srna, "length", 1.0f, 0.0f, FLT_MAX, "Arrow Line Length", "", 0.0f, FLT_MAX);
+ RNA_def_float_vector(
+ gzt->srna, "aspect", 2, NULL, 0, FLT_MAX, "Aspect", "Cone/box style only", 0.0f, FLT_MAX);
+
+ WM_gizmotype_target_property_def(gzt, "offset", PROP_FLOAT, 1);
}
void ED_gizmotypes_arrow_3d(void)
{
- WM_gizmotype_append(GIZMO_GT_arrow_3d);
+ WM_gizmotype_append(GIZMO_GT_arrow_3d);
}
/** \} */
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 55054d1b4ad..e36ab0a0610 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c
@@ -25,7 +25,6 @@
* \brief Gizmo to use as a fallback (catch events).
*/
-
#include "BKE_context.h"
#include "ED_view3d.h"
@@ -38,22 +37,23 @@
#include "../gizmo_geometry.h"
#include "../gizmo_library_intern.h"
-
static void gizmo_blank_draw(const bContext *UNUSED(C), wmGizmo *UNUSED(gz))
{
- /* pass */
+ /* pass */
}
-static int gizmo_blank_invoke(
- bContext *UNUSED(C), wmGizmo *UNUSED(gz), const wmEvent *UNUSED(event))
+static int gizmo_blank_invoke(bContext *UNUSED(C),
+ wmGizmo *UNUSED(gz),
+ const wmEvent *UNUSED(event))
{
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
-static int gizmo_blank_test_select(
- bContext *UNUSED(C), wmGizmo *UNUSED(gz), const int UNUSED(mval[2]))
+static int gizmo_blank_test_select(bContext *UNUSED(C),
+ wmGizmo *UNUSED(gz),
+ const int UNUSED(mval[2]))
{
- return 0;
+ return 0;
}
/* -------------------------------------------------------------------- */
@@ -63,20 +63,20 @@ static int gizmo_blank_test_select(
static void GIZMO_GT_blank_3d(wmGizmoType *gzt)
{
- /* identifiers */
- gzt->idname = "GIZMO_GT_blank_3d";
+ /* identifiers */
+ gzt->idname = "GIZMO_GT_blank_3d";
- /* api callbacks */
- gzt->draw = gizmo_blank_draw;
- gzt->invoke = gizmo_blank_invoke;
- gzt->test_select = gizmo_blank_test_select;
+ /* api callbacks */
+ gzt->draw = gizmo_blank_draw;
+ gzt->invoke = gizmo_blank_invoke;
+ gzt->test_select = gizmo_blank_test_select;
- gzt->struct_size = sizeof(wmGizmo);
+ gzt->struct_size = sizeof(wmGizmo);
}
void ED_gizmotypes_blank_3d(void)
{
- WM_gizmotype_append(GIZMO_GT_blank_3d);
+ WM_gizmotype_append(GIZMO_GT_blank_3d);
}
/** \} */
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 542b9aa19e3..1a132c2957a 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c
@@ -32,7 +32,6 @@
#include "BKE_context.h"
-
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
@@ -61,218 +60,216 @@
#include "../gizmo_library_intern.h"
typedef struct ButtonGizmo2D {
- wmGizmo gizmo;
- bool is_init;
- /* Use an icon or shape */
- int icon;
- GPUBatch *shape_batch[2];
+ wmGizmo gizmo;
+ bool is_init;
+ /* Use an icon or shape */
+ int icon;
+ GPUBatch *shape_batch[2];
} ButtonGizmo2D;
#define CIRCLE_RESOLUTION 32
/* -------------------------------------------------------------------- */
-static void button2d_geom_draw_backdrop(
- const wmGizmo *gz, const float color[4], const bool select)
+static void button2d_geom_draw_backdrop(const wmGizmo *gz, const float color[4], const bool select)
{
- GPU_line_width(gz->line_width);
+ GPU_line_width(gz->line_width);
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ 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(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformColor4fv(color);
+ immUniformColor4fv(color);
- /* TODO, other draw styles */
- imm_draw_circle_fill_2d(pos, 0, 0, 1.0f, CIRCLE_RESOLUTION);
+ /* TODO, other draw styles */
+ imm_draw_circle_fill_2d(pos, 0, 0, 1.0f, CIRCLE_RESOLUTION);
- immUnbindProgram();
+ immUnbindProgram();
- UNUSED_VARS(select);
+ UNUSED_VARS(select);
}
-static void button2d_draw_intern(
- const bContext *C, wmGizmo *gz,
- const bool select, const bool highlight)
+static void button2d_draw_intern(const bContext *C,
+ wmGizmo *gz,
+ const bool select,
+ const bool highlight)
{
- ButtonGizmo2D *button = (ButtonGizmo2D *)gz;
-
- const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
- if (button->is_init == false) {
- button->is_init = true;
- PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon");
- if (RNA_property_is_set(gz->ptr, prop)) {
- button->icon = RNA_property_enum_get(gz->ptr, prop);
- }
- else {
- prop = RNA_struct_find_property(gz->ptr, "shape");
- const uint polys_len = RNA_property_string_length(gz->ptr, prop);
- /* We shouldn't need the +1, but a NULL char is set. */
- char *polys = MEM_mallocN(polys_len + 1, __func__);
- RNA_property_string_get(gz->ptr, prop, polys);
- button->shape_batch[0] = GPU_batch_tris_from_poly_2d_encoded((uchar *)polys, polys_len, NULL);
- button->shape_batch[1] = GPU_batch_wire_from_poly_2d_encoded((uchar *)polys, polys_len, NULL);
- MEM_freeN(polys);
- }
- }
-
- float color[4];
- float matrix_final[4][4];
-
- gizmo_color_get(gz, highlight, color);
- WM_gizmo_calc_matrix_final(gz, matrix_final);
-
-
- bool is_3d = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) != 0;
-
- if ((select == false) &&
- (draw_options & ED_GIZMO_BUTTON_SHOW_HELPLINE))
- {
- 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);
- immUniformColor4fv(color);
- immBegin(GPU_PRIM_LINE_STRIP, 2);
- immVertex3fv(pos, matrix_final[3]);
- immVertex3fv(pos, matrix_final_no_offset[3]);
- immEnd();
- immUnbindProgram();
- }
-
- bool need_to_pop = true;
- GPU_matrix_push();
- GPU_matrix_mul(matrix_final);
-
- if (is_3d) {
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- float matrix_align[4][4];
- float matrix_final_unit[4][4];
- normalize_m4_m4(matrix_final_unit, matrix_final);
- mul_m4_m4m4(matrix_align, rv3d->viewmat, matrix_final_unit);
- zero_v3(matrix_align[3]);
- transpose_m4(matrix_align);
- GPU_matrix_mul(matrix_align);
- }
-
- if (select) {
- BLI_assert(is_3d);
- button2d_geom_draw_backdrop(gz, color, select);
- }
- else {
-
- GPU_blend(true);
- 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);
- GPU_batch_uniform_4f(button->shape_batch[i], "color", UNPACK4(color));
- GPU_batch_draw(button->shape_batch[i]);
-
- if (draw_options & ED_GIZMO_BUTTON_SHOW_OUTLINE) {
- color[0] = 1.0f - color[0];
- color[1] = 1.0f - color[1];
- color[2] = 1.0f - color[2];
- }
- }
- GPU_line_smooth(false);
- GPU_polygon_smooth(true);
- }
- else if (button->icon != ICON_NONE) {
- if (draw_options & ED_GIZMO_BUTTON_SHOW_BACKDROP) {
- button2d_geom_draw_backdrop(gz, color, select);
- }
-
- float pos[2];
- if (is_3d) {
- const float fac = 2.0f;
- GPU_matrix_translate_2f(-(fac / 2), -(fac / 2));
- GPU_matrix_scale_2f(fac / (ICON_DEFAULT_WIDTH * UI_DPI_FAC), fac / (ICON_DEFAULT_HEIGHT * UI_DPI_FAC));
- pos[0] = 1.0f;
- pos[1] = 1.0f;
- }
- else {
- pos[0] = gz->matrix_basis[3][0] - (ICON_DEFAULT_WIDTH / 2.0) * UI_DPI_FAC;
- pos[1] = gz->matrix_basis[3][1] - (ICON_DEFAULT_HEIGHT / 2.0) * UI_DPI_FAC;
- GPU_matrix_pop();
- need_to_pop = false;
- }
-
- float alpha = (highlight) ? 1.0f : 0.8f;
- GPU_polygon_smooth(false);
- UI_icon_draw_alpha(pos[0], pos[1], button->icon, alpha);
- GPU_polygon_smooth(true);
- }
- GPU_blend(false);
- }
-
- if (need_to_pop) {
- GPU_matrix_pop();
- }
+ ButtonGizmo2D *button = (ButtonGizmo2D *)gz;
+
+ const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
+ if (button->is_init == false) {
+ button->is_init = true;
+ PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon");
+ if (RNA_property_is_set(gz->ptr, prop)) {
+ button->icon = RNA_property_enum_get(gz->ptr, prop);
+ }
+ else {
+ prop = RNA_struct_find_property(gz->ptr, "shape");
+ const uint polys_len = RNA_property_string_length(gz->ptr, prop);
+ /* We shouldn't need the +1, but a NULL char is set. */
+ char *polys = MEM_mallocN(polys_len + 1, __func__);
+ RNA_property_string_get(gz->ptr, prop, polys);
+ button->shape_batch[0] = GPU_batch_tris_from_poly_2d_encoded(
+ (uchar *)polys, polys_len, NULL);
+ button->shape_batch[1] = GPU_batch_wire_from_poly_2d_encoded(
+ (uchar *)polys, polys_len, NULL);
+ MEM_freeN(polys);
+ }
+ }
+
+ float color[4];
+ float matrix_final[4][4];
+
+ gizmo_color_get(gz, highlight, color);
+ WM_gizmo_calc_matrix_final(gz, matrix_final);
+
+ bool is_3d = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) != 0;
+
+ if ((select == false) && (draw_options & ED_GIZMO_BUTTON_SHOW_HELPLINE)) {
+ 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);
+ immUniformColor4fv(color);
+ immBegin(GPU_PRIM_LINE_STRIP, 2);
+ immVertex3fv(pos, matrix_final[3]);
+ immVertex3fv(pos, matrix_final_no_offset[3]);
+ immEnd();
+ immUnbindProgram();
+ }
+
+ bool need_to_pop = true;
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix_final);
+
+ if (is_3d) {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float matrix_align[4][4];
+ float matrix_final_unit[4][4];
+ normalize_m4_m4(matrix_final_unit, matrix_final);
+ mul_m4_m4m4(matrix_align, rv3d->viewmat, matrix_final_unit);
+ zero_v3(matrix_align[3]);
+ transpose_m4(matrix_align);
+ GPU_matrix_mul(matrix_align);
+ }
+
+ if (select) {
+ BLI_assert(is_3d);
+ button2d_geom_draw_backdrop(gz, color, select);
+ }
+ else {
+
+ GPU_blend(true);
+ 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);
+ GPU_batch_uniform_4f(button->shape_batch[i], "color", UNPACK4(color));
+ GPU_batch_draw(button->shape_batch[i]);
+
+ if (draw_options & ED_GIZMO_BUTTON_SHOW_OUTLINE) {
+ color[0] = 1.0f - color[0];
+ color[1] = 1.0f - color[1];
+ color[2] = 1.0f - color[2];
+ }
+ }
+ GPU_line_smooth(false);
+ GPU_polygon_smooth(true);
+ }
+ else if (button->icon != ICON_NONE) {
+ if (draw_options & ED_GIZMO_BUTTON_SHOW_BACKDROP) {
+ button2d_geom_draw_backdrop(gz, color, select);
+ }
+
+ float pos[2];
+ if (is_3d) {
+ const float fac = 2.0f;
+ GPU_matrix_translate_2f(-(fac / 2), -(fac / 2));
+ GPU_matrix_scale_2f(fac / (ICON_DEFAULT_WIDTH * UI_DPI_FAC),
+ fac / (ICON_DEFAULT_HEIGHT * UI_DPI_FAC));
+ pos[0] = 1.0f;
+ pos[1] = 1.0f;
+ }
+ else {
+ pos[0] = gz->matrix_basis[3][0] - (ICON_DEFAULT_WIDTH / 2.0) * UI_DPI_FAC;
+ pos[1] = gz->matrix_basis[3][1] - (ICON_DEFAULT_HEIGHT / 2.0) * UI_DPI_FAC;
+ GPU_matrix_pop();
+ need_to_pop = false;
+ }
+
+ float alpha = (highlight) ? 1.0f : 0.8f;
+ GPU_polygon_smooth(false);
+ UI_icon_draw_alpha(pos[0], pos[1], button->icon, alpha);
+ GPU_polygon_smooth(true);
+ }
+ GPU_blend(false);
+ }
+
+ if (need_to_pop) {
+ GPU_matrix_pop();
+ }
}
static void gizmo_button2d_draw_select(const bContext *C, wmGizmo *gz, int select_id)
{
- GPU_select_load_id(select_id);
- button2d_draw_intern(C, gz, true, false);
+ GPU_select_load_id(select_id);
+ button2d_draw_intern(C, gz, true, false);
}
static void gizmo_button2d_draw(const bContext *C, wmGizmo *gz)
{
- const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
+ const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
- GPU_blend(true);
- button2d_draw_intern(C, gz, false, is_highlight);
- GPU_blend(false);
+ GPU_blend(true);
+ button2d_draw_intern(C, gz, false, is_highlight);
+ GPU_blend(false);
}
-static int gizmo_button2d_test_select(
- bContext *C, wmGizmo *gz, const int mval[2])
+static int gizmo_button2d_test_select(bContext *C, wmGizmo *gz, const int mval[2])
{
- float point_local[2];
-
- if (0) {
- /* correct, but unnecessarily slow. */
- if (gizmo_window_project_2d(
- C, gz, (const float[2]){UNPACK2(mval)}, 2, true, point_local) == false)
- {
- return -1;
- }
- }
- else {
- copy_v2_v2(point_local, (float[2]){UNPACK2(mval)});
- sub_v2_v2(point_local, gz->matrix_basis[3]);
- mul_v2_fl(point_local, 1.0f / (gz->scale_basis * UI_DPI_FAC));
- }
- /* The 'gz->scale_final' is already applied when projecting. */
- if (len_squared_v2(point_local) < 1.0f) {
- return 0;
- }
-
- return -1;
+ float point_local[2];
+
+ if (0) {
+ /* correct, but unnecessarily slow. */
+ if (gizmo_window_project_2d(C, gz, (const float[2]){UNPACK2(mval)}, 2, true, point_local) ==
+ false) {
+ return -1;
+ }
+ }
+ else {
+ copy_v2_v2(point_local, (float[2]){UNPACK2(mval)});
+ sub_v2_v2(point_local, gz->matrix_basis[3]);
+ mul_v2_fl(point_local, 1.0f / (gz->scale_basis * UI_DPI_FAC));
+ }
+ /* The 'gz->scale_final' is already applied when projecting. */
+ if (len_squared_v2(point_local) < 1.0f) {
+ return 0;
+ }
+
+ return -1;
}
static int gizmo_button2d_cursor_get(wmGizmo *gz)
{
- if (RNA_boolean_get(gz->ptr, "show_drag")) {
- return BC_NSEW_SCROLLCURSOR;
- }
- return CURSOR_STD;
+ if (RNA_boolean_get(gz->ptr, "show_drag")) {
+ return BC_NSEW_SCROLLCURSOR;
+ }
+ return CURSOR_STD;
}
static void gizmo_button2d_free(wmGizmo *gz)
{
- ButtonGizmo2D *shape = (ButtonGizmo2D *)gz;
+ ButtonGizmo2D *shape = (ButtonGizmo2D *)gz;
- for (uint i = 0; i < ARRAY_SIZE(shape->shape_batch); i++) {
- GPU_BATCH_DISCARD_SAFE(shape->shape_batch[i]);
- }
+ for (uint i = 0; i < ARRAY_SIZE(shape->shape_batch); i++) {
+ GPU_BATCH_DISCARD_SAFE(shape->shape_batch[i]);
+ }
}
/** \} */
@@ -284,42 +281,42 @@ static void gizmo_button2d_free(wmGizmo *gz)
static void GIZMO_GT_button_2d(wmGizmoType *gzt)
{
- /* identifiers */
- gzt->idname = "GIZMO_GT_button_2d";
+ /* identifiers */
+ gzt->idname = "GIZMO_GT_button_2d";
- /* api callbacks */
- gzt->draw = gizmo_button2d_draw;
- gzt->draw_select = gizmo_button2d_draw_select;
- gzt->test_select = gizmo_button2d_test_select;
- gzt->cursor_get = gizmo_button2d_cursor_get;
- gzt->free = gizmo_button2d_free;
+ /* api callbacks */
+ gzt->draw = gizmo_button2d_draw;
+ gzt->draw_select = gizmo_button2d_draw_select;
+ gzt->test_select = gizmo_button2d_test_select;
+ gzt->cursor_get = gizmo_button2d_cursor_get;
+ gzt->free = gizmo_button2d_free;
- gzt->struct_size = sizeof(ButtonGizmo2D);
+ gzt->struct_size = sizeof(ButtonGizmo2D);
- /* rna */
- static EnumPropertyItem rna_enum_draw_options[] = {
- {ED_GIZMO_BUTTON_SHOW_OUTLINE, "OUTLINE", 0, "Outline", ""},
- {ED_GIZMO_BUTTON_SHOW_BACKDROP, "BACKDROP", 0, "Backdrop", ""},
- {ED_GIZMO_BUTTON_SHOW_HELPLINE, "HELPLINE", 0, "Help Line", ""},
- {0, NULL, 0, NULL, NULL},
- };
- PropertyRNA *prop;
+ /* rna */
+ static EnumPropertyItem rna_enum_draw_options[] = {
+ {ED_GIZMO_BUTTON_SHOW_OUTLINE, "OUTLINE", 0, "Outline", ""},
+ {ED_GIZMO_BUTTON_SHOW_BACKDROP, "BACKDROP", 0, "Backdrop", ""},
+ {ED_GIZMO_BUTTON_SHOW_HELPLINE, "HELPLINE", 0, "Help Line", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+ PropertyRNA *prop;
- RNA_def_enum_flag(gzt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
+ RNA_def_enum_flag(gzt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
- prop = RNA_def_property(gzt->srna, "icon", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, rna_enum_icon_items);
+ prop = RNA_def_property(gzt->srna, "icon", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_enum_icon_items);
- /* Passed to 'GPU_batch_tris_from_poly_2d_encoded' */
- RNA_def_property(gzt->srna, "shape", PROP_STRING, PROP_BYTESTRING);
+ /* Passed to 'GPU_batch_tris_from_poly_2d_encoded' */
+ RNA_def_property(gzt->srna, "shape", PROP_STRING, PROP_BYTESTRING);
- /* Currently only used for cursor display. */
- RNA_def_boolean(gzt->srna, "show_drag", true, "Show Drag", "");
+ /* Currently only used for cursor display. */
+ RNA_def_boolean(gzt->srna, "show_drag", true, "Show Drag", "");
}
void ED_gizmotypes_button_2d(void)
{
- WM_gizmotype_append(GIZMO_GT_button_2d);
+ WM_gizmotype_append(GIZMO_GT_button_2d);
}
-/** \} */ // Button Gizmo API
+/** \} */ // Button Gizmo API
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 45b7b37eb8d..77658b8495e 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
@@ -36,7 +36,6 @@
#include "BKE_context.h"
-
#include "GPU_matrix.h"
#include "GPU_shader.h"
#include "GPU_immediate.h"
@@ -60,75 +59,106 @@
#define GIZMO_RESIZER_SIZE 10.0f
#define GIZMO_MARGIN_OFFSET_SCALE 1.5f
-static bool gizmo_calc_rect_view_scale(
- const wmGizmo *gz, const float dims[2], float scale[2])
+static bool gizmo_calc_rect_view_scale(const wmGizmo *gz, const float dims[2], float scale[2])
{
- float matrix_final_no_offset[4][4];
- float asp[2] = {1.0f, 1.0f};
- if (dims[0] > dims[1]) {
- asp[0] = dims[1] / dims[0];
- }
- else {
- asp[1] = dims[0] / dims[1];
- }
- float x_axis[3], y_axis[3];
- WM_gizmo_calc_matrix_final_no_offset(gz, matrix_final_no_offset);
- mul_v3_mat3_m4v3(x_axis, matrix_final_no_offset, gz->matrix_offset[0]);
- mul_v3_mat3_m4v3(y_axis, matrix_final_no_offset, gz->matrix_offset[1]);
-
- mul_v2_v2(x_axis, asp);
- mul_v2_v2(y_axis, asp);
-
- float len_x_axis = len_v3(x_axis);
- float len_y_axis = len_v3(y_axis);
-
- if (len_x_axis == 0.0f || len_y_axis == 0.0f) {
- return false;
- }
-
- scale[0] = 1.0f / len_x_axis;
- scale[1] = 1.0f / len_y_axis;
- return true;
+ float matrix_final_no_offset[4][4];
+ float asp[2] = {1.0f, 1.0f};
+ if (dims[0] > dims[1]) {
+ asp[0] = dims[1] / dims[0];
+ }
+ else {
+ asp[1] = dims[0] / dims[1];
+ }
+ float x_axis[3], y_axis[3];
+ WM_gizmo_calc_matrix_final_no_offset(gz, matrix_final_no_offset);
+ mul_v3_mat3_m4v3(x_axis, matrix_final_no_offset, gz->matrix_offset[0]);
+ mul_v3_mat3_m4v3(y_axis, matrix_final_no_offset, gz->matrix_offset[1]);
+
+ mul_v2_v2(x_axis, asp);
+ mul_v2_v2(y_axis, asp);
+
+ float len_x_axis = len_v3(x_axis);
+ float len_y_axis = len_v3(y_axis);
+
+ if (len_x_axis == 0.0f || len_y_axis == 0.0f) {
+ return false;
+ }
+
+ scale[0] = 1.0f / len_x_axis;
+ scale[1] = 1.0f / len_y_axis;
+ return true;
}
-static bool gizmo_calc_rect_view_margin(
- const wmGizmo *gz, const float dims[2], float margin[2])
+static bool gizmo_calc_rect_view_margin(const wmGizmo *gz, const float dims[2], float margin[2])
{
- float handle_size;
- if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
- handle_size = 0.15f;
- }
- else {
- handle_size = GIZMO_RESIZER_SIZE;
- }
- handle_size *= gz->scale_final;
- float scale_xy[2];
- if (!gizmo_calc_rect_view_scale(gz, dims, scale_xy)) {
- return false;
- }
- margin[0] = ((handle_size * scale_xy[0]));
- margin[1] = ((handle_size * scale_xy[1]));
- return true;
+ float handle_size;
+ if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
+ handle_size = 0.15f;
+ }
+ else {
+ handle_size = GIZMO_RESIZER_SIZE;
+ }
+ handle_size *= gz->scale_final;
+ float scale_xy[2];
+ if (!gizmo_calc_rect_view_scale(gz, dims, scale_xy)) {
+ return false;
+ }
+ margin[0] = ((handle_size * scale_xy[0]));
+ margin[1] = ((handle_size * scale_xy[1]));
+ return true;
}
/* -------------------------------------------------------------------- */
static void gizmo_rect_pivot_from_scale_part(int part, float r_pt[2], bool r_constrain_axis[2])
{
- bool x = true, y = true;
- switch (part) {
- case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X: { ARRAY_SET_ITEMS(r_pt, 0.5, 0.0); x = false; break; }
- case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X: { ARRAY_SET_ITEMS(r_pt, -0.5, 0.0); x = false; break; }
- case ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y: { ARRAY_SET_ITEMS(r_pt, 0.0, 0.5); y = false; break; }
- case ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y: { ARRAY_SET_ITEMS(r_pt, 0.0, -0.5); y = false; break; }
- case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y: { ARRAY_SET_ITEMS(r_pt, 0.5, 0.5); x = y = false; break; }
- case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y: { ARRAY_SET_ITEMS(r_pt, 0.5, -0.5); x = y = false; break; }
- case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y: { ARRAY_SET_ITEMS(r_pt, -0.5, 0.5); x = y = false; break; }
- case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y: { ARRAY_SET_ITEMS(r_pt, -0.5, -0.5); x = y = false; break; }
- default: BLI_assert(0);
- }
- r_constrain_axis[0] = x;
- r_constrain_axis[1] = y;
+ bool x = true, y = true;
+ switch (part) {
+ case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X: {
+ ARRAY_SET_ITEMS(r_pt, 0.5, 0.0);
+ x = false;
+ break;
+ }
+ case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X: {
+ ARRAY_SET_ITEMS(r_pt, -0.5, 0.0);
+ x = false;
+ break;
+ }
+ case ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y: {
+ ARRAY_SET_ITEMS(r_pt, 0.0, 0.5);
+ y = false;
+ break;
+ }
+ case ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y: {
+ ARRAY_SET_ITEMS(r_pt, 0.0, -0.5);
+ y = false;
+ break;
+ }
+ case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y: {
+ ARRAY_SET_ITEMS(r_pt, 0.5, 0.5);
+ x = y = false;
+ break;
+ }
+ case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y: {
+ ARRAY_SET_ITEMS(r_pt, 0.5, -0.5);
+ x = y = false;
+ break;
+ }
+ case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y: {
+ ARRAY_SET_ITEMS(r_pt, -0.5, 0.5);
+ x = y = false;
+ break;
+ }
+ case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y: {
+ ARRAY_SET_ITEMS(r_pt, -0.5, -0.5);
+ x = y = false;
+ break;
+ }
+ default:
+ BLI_assert(0);
+ }
+ r_constrain_axis[0] = x;
+ r_constrain_axis[1] = y;
}
/* -------------------------------------------------------------------- */
@@ -137,315 +167,324 @@ 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])
{
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3fv(color);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
- immBegin(GPU_PRIM_LINES, 16);
+ immBegin(GPU_PRIM_LINES, 16);
- immVertex2f(pos, r->xmin, r->ymin + margin[1]);
- immVertex2f(pos, r->xmin, r->ymin);
- immVertex2f(pos, r->xmin, r->ymin);
- immVertex2f(pos, r->xmin + margin[0], r->ymin);
+ immVertex2f(pos, r->xmin, r->ymin + margin[1]);
+ immVertex2f(pos, r->xmin, r->ymin);
+ immVertex2f(pos, r->xmin, r->ymin);
+ immVertex2f(pos, r->xmin + margin[0], r->ymin);
- immVertex2f(pos, r->xmax, r->ymin + margin[1]);
- immVertex2f(pos, r->xmax, r->ymin);
- immVertex2f(pos, r->xmax, r->ymin);
- immVertex2f(pos, r->xmax - margin[0], r->ymin);
+ immVertex2f(pos, r->xmax, r->ymin + margin[1]);
+ immVertex2f(pos, r->xmax, r->ymin);
+ immVertex2f(pos, r->xmax, r->ymin);
+ immVertex2f(pos, r->xmax - margin[0], r->ymin);
- immVertex2f(pos, r->xmax, r->ymax - margin[1]);
- immVertex2f(pos, r->xmax, r->ymax);
- immVertex2f(pos, r->xmax, r->ymax);
- immVertex2f(pos, r->xmax - margin[0], r->ymax);
+ immVertex2f(pos, r->xmax, r->ymax - margin[1]);
+ immVertex2f(pos, r->xmax, r->ymax);
+ immVertex2f(pos, r->xmax, r->ymax);
+ immVertex2f(pos, r->xmax - margin[0], r->ymax);
- immVertex2f(pos, r->xmin, r->ymax - margin[1]);
- immVertex2f(pos, r->xmin, r->ymax);
- immVertex2f(pos, r->xmin, r->ymax);
- immVertex2f(pos, r->xmin + margin[0], r->ymax);
+ immVertex2f(pos, r->xmin, r->ymax - margin[1]);
+ immVertex2f(pos, r->xmin, r->ymax);
+ immVertex2f(pos, r->xmin, r->ymax);
+ immVertex2f(pos, r->xmin + margin[0], r->ymax);
- immEnd();
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
}
-static void cage2d_draw_box_interaction(
- const float color[4], const int highlighted,
- const float size[2], const float margin[2],
- const float line_width, const bool is_solid, const int draw_options)
+static void cage2d_draw_box_interaction(const float color[4],
+ const int highlighted,
+ const float size[2],
+ const float margin[2],
+ const float line_width,
+ const bool is_solid,
+ const int draw_options)
{
- /* 4 verts for translate, otherwise only 3 are used. */
- float verts[4][2];
- uint verts_len = 0;
- GPUPrimType prim_type = GPU_PRIM_NONE;
-
- switch (highlighted) {
- case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X:
- {
- rctf r = {
- .xmin = -size[0], .xmax = -size[0] + margin[0],
- .ymin = -size[1] + margin[1], .ymax = size[1] - margin[1],
- };
- ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymin);
- ARRAY_SET_ITEMS(verts[1], r.xmin, r.ymax);
- verts_len = 2;
- if (is_solid) {
- ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax);
- ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymin);
- verts_len += 2;
- prim_type = GPU_PRIM_TRI_FAN;
- }
- else {
- prim_type = GPU_PRIM_LINE_STRIP;
- }
- break;
- }
- case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X:
- {
- rctf r = {
- .xmin = size[0] - margin[0], .xmax = size[0],
- .ymin = -size[1] + margin[1], .ymax = size[1] - margin[1],
- };
- ARRAY_SET_ITEMS(verts[0], r.xmax, r.ymin);
- ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymax);
- verts_len = 2;
- if (is_solid) {
- ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymax);
- ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin);
- verts_len += 2;
- prim_type = GPU_PRIM_TRI_FAN;
- }
- else {
- prim_type = GPU_PRIM_LINE_STRIP;
- }
- break;
- }
- case ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y:
- {
- rctf r = {
- .xmin = -size[0] + margin[0], .xmax = size[0] - margin[0],
- .ymin = -size[1], .ymax = -size[1] + margin[1],
- };
- ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymin);
- ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymin);
- verts_len = 2;
- if (is_solid) {
- ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax);
- ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymax);
- verts_len += 2;
- prim_type = GPU_PRIM_TRI_FAN;
- }
- else {
- prim_type = GPU_PRIM_LINE_STRIP;
- }
- break;
- }
- case ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y:
- {
- rctf r = {
- .xmin = -size[0] + margin[0], .xmax = size[0] - margin[0],
- .ymin = size[1] - margin[1], .ymax = size[1],
- };
- ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymax);
- ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymax);
- verts_len = 2;
- if (is_solid) {
- ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymin);
- ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin);
- verts_len += 2;
- prim_type = GPU_PRIM_TRI_FAN;
- }
- else {
- prim_type = GPU_PRIM_LINE_STRIP;
- }
- break;
- }
- case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y:
- {
- rctf r = {
- .xmin = -size[0], .xmax = -size[0] + margin[0],
- .ymin = -size[1], .ymax = -size[1] + margin[1],
- };
- ARRAY_SET_ITEMS(verts[0], r.xmax, r.ymin);
- ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymax);
- ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymax);
- verts_len = 3;
- if (is_solid) {
- ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin);
- verts_len += 1;
- prim_type = GPU_PRIM_TRI_FAN;
- }
- else {
- prim_type = GPU_PRIM_LINE_STRIP;
- }
- break;
- }
- case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y:
- {
- rctf r = {
- .xmin = -size[0], .xmax = -size[0] + margin[0],
- .ymin = size[1] - margin[1], .ymax = size[1],
- };
- ARRAY_SET_ITEMS(verts[0], r.xmax, r.ymax);
- ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymin);
- ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymin);
- verts_len = 3;
- if (is_solid) {
- ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymax);
- verts_len += 1;
- prim_type = GPU_PRIM_TRI_FAN;
- }
- else {
- prim_type = GPU_PRIM_LINE_STRIP;
- }
- break;
- }
- case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y:
- {
- rctf r = {
- .xmin = size[0] - margin[0], .xmax = size[0],
- .ymin = -size[1], .ymax = -size[1] + margin[1],
- };
- ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymin);
- ARRAY_SET_ITEMS(verts[1], r.xmin, r.ymax);
- ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax);
- verts_len = 3;
- if (is_solid) {
- ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymin);
- verts_len += 1;
- prim_type = GPU_PRIM_TRI_FAN;
- }
- else {
- prim_type = GPU_PRIM_LINE_STRIP;
- }
- break;
- }
- case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y:
- {
- rctf r = {
- .xmin = size[0] - margin[0], .xmax = size[0],
- .ymin = size[1] - margin[1], .ymax = size[1],
- };
- ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymax);
- ARRAY_SET_ITEMS(verts[1], r.xmin, r.ymin);
- ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymin);
- verts_len = 3;
- if (is_solid) {
- ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymax);
- verts_len += 1;
- prim_type = GPU_PRIM_TRI_FAN;
- }
- else {
- prim_type = GPU_PRIM_LINE_STRIP;
- }
- break;
- }
- case ED_GIZMO_CAGE2D_PART_ROTATE:
- {
- const float rotate_pt[2] = {0.0f, size[1] + margin[1]};
- const rctf r_rotate = {
- .xmin = rotate_pt[0] - margin[0] / 2.0f,
- .xmax = rotate_pt[0] + margin[0] / 2.0f,
- .ymin = rotate_pt[1] - margin[1] / 2.0f,
- .ymax = rotate_pt[1] + margin[1] / 2.0f,
- };
-
- ARRAY_SET_ITEMS(verts[0], r_rotate.xmin, r_rotate.ymin);
- ARRAY_SET_ITEMS(verts[1], r_rotate.xmin, r_rotate.ymax);
- ARRAY_SET_ITEMS(verts[2], r_rotate.xmax, r_rotate.ymax);
- ARRAY_SET_ITEMS(verts[3], r_rotate.xmax, r_rotate.ymin);
- verts_len = 4;
- if (is_solid) {
- prim_type = GPU_PRIM_TRI_FAN;
- }
- else {
- prim_type = GPU_PRIM_LINE_STRIP;
- }
- break;
- }
-
- case ED_GIZMO_CAGE2D_PART_TRANSLATE:
- if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
- ARRAY_SET_ITEMS(verts[0], -margin[0] / 2, -margin[1] / 2);
- ARRAY_SET_ITEMS(verts[1], margin[0] / 2, margin[1] / 2);
- ARRAY_SET_ITEMS(verts[2], -margin[0] / 2, margin[1] / 2);
- ARRAY_SET_ITEMS(verts[3], margin[0] / 2, -margin[1] / 2);
- verts_len = 4;
- if (is_solid) {
- prim_type = GPU_PRIM_TRI_FAN;
- }
- else {
- prim_type = GPU_PRIM_LINES;
- }
- }
- else {
- /* Only used for 3D view selection, never displayed to the user. */
- ARRAY_SET_ITEMS(verts[0], -size[0], -size[1]);
- ARRAY_SET_ITEMS(verts[1], -size[0], size[1]);
- ARRAY_SET_ITEMS(verts[2], size[0], size[1]);
- ARRAY_SET_ITEMS(verts[3], size[0], -size[1]);
- verts_len = 4;
- if (is_solid) {
- prim_type = GPU_PRIM_TRI_FAN;
- }
- else {
- /* unreachable */
- BLI_assert(0);
- prim_type = GPU_PRIM_LINE_STRIP;
- }
- }
- break;
- default:
- return;
- }
-
- BLI_assert(prim_type != GPU_PRIM_NONE);
-
- GPUVertFormat *format = immVertexFormat();
- struct {
- uint pos, col;
- } attr_id = {
- .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);
-
- {
- if (is_solid) {
- BLI_assert(ELEM(prim_type, GPU_PRIM_TRI_FAN));
- immBegin(prim_type, verts_len);
- immAttr3f(attr_id.col, 0.0f, 0.0f, 0.0f);
- for (uint i = 0; i < verts_len; i++) {
- immVertex2fv(attr_id.pos, verts[i]);
- }
- immEnd();
- }
- else {
- BLI_assert(ELEM(prim_type, GPU_PRIM_LINE_STRIP, GPU_PRIM_LINES));
- GPU_line_width(line_width + 3.0f);
-
- immBegin(prim_type, verts_len);
- immAttr3f(attr_id.col, 0.0f, 0.0f, 0.0f);
- for (uint i = 0; i < verts_len; i++) {
- immVertex2fv(attr_id.pos, verts[i]);
- }
- immEnd();
-
- GPU_line_width(line_width);
-
- immBegin(prim_type, verts_len);
- immAttr3fv(attr_id.col, color);
- for (uint i = 0; i < verts_len; i++) {
- immVertex2fv(attr_id.pos, verts[i]);
- }
- immEnd();
- }
- }
-
- immUnbindProgram();
+ /* 4 verts for translate, otherwise only 3 are used. */
+ float verts[4][2];
+ uint verts_len = 0;
+ GPUPrimType prim_type = GPU_PRIM_NONE;
+
+ switch (highlighted) {
+ case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X: {
+ rctf r = {
+ .xmin = -size[0],
+ .xmax = -size[0] + margin[0],
+ .ymin = -size[1] + margin[1],
+ .ymax = size[1] - margin[1],
+ };
+ ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymin);
+ ARRAY_SET_ITEMS(verts[1], r.xmin, r.ymax);
+ verts_len = 2;
+ if (is_solid) {
+ ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax);
+ ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymin);
+ verts_len += 2;
+ prim_type = GPU_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GPU_PRIM_LINE_STRIP;
+ }
+ break;
+ }
+ case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X: {
+ rctf r = {
+ .xmin = size[0] - margin[0],
+ .xmax = size[0],
+ .ymin = -size[1] + margin[1],
+ .ymax = size[1] - margin[1],
+ };
+ ARRAY_SET_ITEMS(verts[0], r.xmax, r.ymin);
+ ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymax);
+ verts_len = 2;
+ if (is_solid) {
+ ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymax);
+ ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin);
+ verts_len += 2;
+ prim_type = GPU_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GPU_PRIM_LINE_STRIP;
+ }
+ break;
+ }
+ case ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y: {
+ rctf r = {
+ .xmin = -size[0] + margin[0],
+ .xmax = size[0] - margin[0],
+ .ymin = -size[1],
+ .ymax = -size[1] + margin[1],
+ };
+ ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymin);
+ ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymin);
+ verts_len = 2;
+ if (is_solid) {
+ ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax);
+ ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymax);
+ verts_len += 2;
+ prim_type = GPU_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GPU_PRIM_LINE_STRIP;
+ }
+ break;
+ }
+ case ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y: {
+ rctf r = {
+ .xmin = -size[0] + margin[0],
+ .xmax = size[0] - margin[0],
+ .ymin = size[1] - margin[1],
+ .ymax = size[1],
+ };
+ ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymax);
+ ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymax);
+ verts_len = 2;
+ if (is_solid) {
+ ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymin);
+ ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin);
+ verts_len += 2;
+ prim_type = GPU_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GPU_PRIM_LINE_STRIP;
+ }
+ break;
+ }
+ case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y: {
+ rctf r = {
+ .xmin = -size[0],
+ .xmax = -size[0] + margin[0],
+ .ymin = -size[1],
+ .ymax = -size[1] + margin[1],
+ };
+ ARRAY_SET_ITEMS(verts[0], r.xmax, r.ymin);
+ ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymax);
+ ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymax);
+ verts_len = 3;
+ if (is_solid) {
+ ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin);
+ verts_len += 1;
+ prim_type = GPU_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GPU_PRIM_LINE_STRIP;
+ }
+ break;
+ }
+ case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y: {
+ rctf r = {
+ .xmin = -size[0],
+ .xmax = -size[0] + margin[0],
+ .ymin = size[1] - margin[1],
+ .ymax = size[1],
+ };
+ ARRAY_SET_ITEMS(verts[0], r.xmax, r.ymax);
+ ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymin);
+ ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymin);
+ verts_len = 3;
+ if (is_solid) {
+ ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymax);
+ verts_len += 1;
+ prim_type = GPU_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GPU_PRIM_LINE_STRIP;
+ }
+ break;
+ }
+ case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y: {
+ rctf r = {
+ .xmin = size[0] - margin[0],
+ .xmax = size[0],
+ .ymin = -size[1],
+ .ymax = -size[1] + margin[1],
+ };
+ ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymin);
+ ARRAY_SET_ITEMS(verts[1], r.xmin, r.ymax);
+ ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax);
+ verts_len = 3;
+ if (is_solid) {
+ ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymin);
+ verts_len += 1;
+ prim_type = GPU_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GPU_PRIM_LINE_STRIP;
+ }
+ break;
+ }
+ case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y: {
+ rctf r = {
+ .xmin = size[0] - margin[0],
+ .xmax = size[0],
+ .ymin = size[1] - margin[1],
+ .ymax = size[1],
+ };
+ ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymax);
+ ARRAY_SET_ITEMS(verts[1], r.xmin, r.ymin);
+ ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymin);
+ verts_len = 3;
+ if (is_solid) {
+ ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymax);
+ verts_len += 1;
+ prim_type = GPU_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GPU_PRIM_LINE_STRIP;
+ }
+ break;
+ }
+ case ED_GIZMO_CAGE2D_PART_ROTATE: {
+ const float rotate_pt[2] = {0.0f, size[1] + margin[1]};
+ const rctf r_rotate = {
+ .xmin = rotate_pt[0] - margin[0] / 2.0f,
+ .xmax = rotate_pt[0] + margin[0] / 2.0f,
+ .ymin = rotate_pt[1] - margin[1] / 2.0f,
+ .ymax = rotate_pt[1] + margin[1] / 2.0f,
+ };
+
+ ARRAY_SET_ITEMS(verts[0], r_rotate.xmin, r_rotate.ymin);
+ ARRAY_SET_ITEMS(verts[1], r_rotate.xmin, r_rotate.ymax);
+ ARRAY_SET_ITEMS(verts[2], r_rotate.xmax, r_rotate.ymax);
+ ARRAY_SET_ITEMS(verts[3], r_rotate.xmax, r_rotate.ymin);
+ verts_len = 4;
+ if (is_solid) {
+ prim_type = GPU_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GPU_PRIM_LINE_STRIP;
+ }
+ break;
+ }
+
+ case ED_GIZMO_CAGE2D_PART_TRANSLATE:
+ if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
+ ARRAY_SET_ITEMS(verts[0], -margin[0] / 2, -margin[1] / 2);
+ ARRAY_SET_ITEMS(verts[1], margin[0] / 2, margin[1] / 2);
+ ARRAY_SET_ITEMS(verts[2], -margin[0] / 2, margin[1] / 2);
+ ARRAY_SET_ITEMS(verts[3], margin[0] / 2, -margin[1] / 2);
+ verts_len = 4;
+ if (is_solid) {
+ prim_type = GPU_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GPU_PRIM_LINES;
+ }
+ }
+ else {
+ /* Only used for 3D view selection, never displayed to the user. */
+ ARRAY_SET_ITEMS(verts[0], -size[0], -size[1]);
+ ARRAY_SET_ITEMS(verts[1], -size[0], size[1]);
+ ARRAY_SET_ITEMS(verts[2], size[0], size[1]);
+ ARRAY_SET_ITEMS(verts[3], size[0], -size[1]);
+ verts_len = 4;
+ if (is_solid) {
+ prim_type = GPU_PRIM_TRI_FAN;
+ }
+ else {
+ /* unreachable */
+ BLI_assert(0);
+ prim_type = GPU_PRIM_LINE_STRIP;
+ }
+ }
+ break;
+ default:
+ return;
+ }
+
+ BLI_assert(prim_type != GPU_PRIM_NONE);
+
+ GPUVertFormat *format = immVertexFormat();
+ struct {
+ uint pos, col;
+ } attr_id = {
+ .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);
+
+ {
+ if (is_solid) {
+ BLI_assert(ELEM(prim_type, GPU_PRIM_TRI_FAN));
+ immBegin(prim_type, verts_len);
+ immAttr3f(attr_id.col, 0.0f, 0.0f, 0.0f);
+ for (uint i = 0; i < verts_len; i++) {
+ immVertex2fv(attr_id.pos, verts[i]);
+ }
+ immEnd();
+ }
+ else {
+ BLI_assert(ELEM(prim_type, GPU_PRIM_LINE_STRIP, GPU_PRIM_LINES));
+ GPU_line_width(line_width + 3.0f);
+
+ immBegin(prim_type, verts_len);
+ immAttr3f(attr_id.col, 0.0f, 0.0f, 0.0f);
+ for (uint i = 0; i < verts_len; i++) {
+ immVertex2fv(attr_id.pos, verts[i]);
+ }
+ immEnd();
+
+ GPU_line_width(line_width);
+
+ immBegin(prim_type, verts_len);
+ immAttr3fv(attr_id.col, color);
+ for (uint i = 0; i < verts_len; i++) {
+ immVertex2fv(attr_id.pos, verts[i]);
+ }
+ immEnd();
+ }
+ }
+
+ immUnbindProgram();
}
/** \} */
@@ -457,222 +496,238 @@ static void cage2d_draw_box_interaction(
* \{ */
static void imm_draw_point_aspect_2d(
- uint pos, float x, float y, float rad_x, float rad_y, bool solid)
+ uint pos, float x, float y, float rad_x, float rad_y, bool solid)
{
- immBegin(solid ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, 4);
- immVertex2f(pos, x - rad_x, y - rad_y);
- immVertex2f(pos, x - rad_x, y + rad_y);
- immVertex2f(pos, x + rad_x, y + rad_y);
- immVertex2f(pos, x + rad_x, y - rad_y);
- immEnd();
+ immBegin(solid ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, 4);
+ immVertex2f(pos, x - rad_x, y - rad_y);
+ immVertex2f(pos, x - rad_x, y + rad_y);
+ immVertex2f(pos, x + rad_x, y + rad_y);
+ immVertex2f(pos, x + rad_x, y - rad_y);
+ immEnd();
}
-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)
+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)
{
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3fv(color);
-
- immBegin(GPU_PRIM_LINE_LOOP, 4);
- immVertex2f(pos, r->xmin, r->ymin);
- immVertex2f(pos, r->xmax, r->ymin);
- immVertex2f(pos, r->xmax, r->ymax);
- immVertex2f(pos, r->xmin, r->ymax);
- immEnd();
-
- if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
- immBegin(GPU_PRIM_LINE_LOOP, 2);
- immVertex2f(pos, BLI_rctf_cent_x(r), r->ymax);
- immVertex2f(pos, BLI_rctf_cent_x(r), r->ymax + margin[1]);
- immEnd();
- }
-
- if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
- if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
- const float rad[2] = {margin[0] / 2, margin[1] / 2};
- const float center[2] = {BLI_rctf_cent_x(r), BLI_rctf_cent_y(r)};
-
- immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, center[0] - rad[0], center[1] - rad[1]);
- immVertex2f(pos, center[0] + rad[0], center[1] + rad[1]);
- immVertex2f(pos, center[0] + rad[0], center[1] - rad[1]);
- immVertex2f(pos, center[0] - rad[0], center[1] + rad[1]);
- immEnd();
- }
- }
-
- immUnbindProgram();
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
+
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
+ immVertex2f(pos, r->xmin, r->ymin);
+ immVertex2f(pos, r->xmax, r->ymin);
+ immVertex2f(pos, r->xmax, r->ymax);
+ immVertex2f(pos, r->xmin, r->ymax);
+ immEnd();
+
+ if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
+ immBegin(GPU_PRIM_LINE_LOOP, 2);
+ immVertex2f(pos, BLI_rctf_cent_x(r), r->ymax);
+ immVertex2f(pos, BLI_rctf_cent_x(r), r->ymax + margin[1]);
+ immEnd();
+ }
+
+ if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
+ if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
+ const float rad[2] = {margin[0] / 2, margin[1] / 2};
+ const float center[2] = {BLI_rctf_cent_x(r), BLI_rctf_cent_y(r)};
+
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex2f(pos, center[0] - rad[0], center[1] - rad[1]);
+ immVertex2f(pos, center[0] + rad[0], center[1] + rad[1]);
+ immVertex2f(pos, center[0] + rad[0], center[1] - rad[1]);
+ immVertex2f(pos, center[0] - rad[0], center[1] + rad[1]);
+ immEnd();
+ }
+ }
+
+ immUnbindProgram();
}
-static void cage2d_draw_circle_handles(
- const rctf *r, const float margin[2], const float color[3],
- const int transform_flag,
- bool solid)
+static void cage2d_draw_circle_handles(const rctf *r,
+ const float margin[2],
+ const float color[3],
+ const int transform_flag,
+ bool solid)
{
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- void (*circle_fn)(uint, float, float, float, float, int) =
- (solid) ? imm_draw_circle_fill_aspect_2d : imm_draw_circle_wire_aspect_2d;
- const int resolu = 12;
- const float rad[2] = {margin[0] / 3, margin[1] / 3};
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3fv(color);
-
- /* should really divide by two, but looks too bulky. */
- {
- imm_draw_point_aspect_2d(pos, r->xmin, r->ymin, rad[0], rad[1], solid);
- imm_draw_point_aspect_2d(pos, r->xmax, r->ymin, rad[0], rad[1], solid);
- imm_draw_point_aspect_2d(pos, r->xmax, r->ymax, rad[0], rad[1], solid);
- imm_draw_point_aspect_2d(pos, r->xmin, r->ymax, rad[0], rad[1], solid);
- }
-
- if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
- const float handle[2] = {BLI_rctf_cent_x(r), r->ymax + (margin[1] * GIZMO_MARGIN_OFFSET_SCALE)};
- circle_fn(pos, handle[0], handle[1], rad[0], rad[1], resolu);
- }
-
- immUnbindProgram();
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ void (*circle_fn)(uint, float, float, float, float, int) = (solid) ?
+ imm_draw_circle_fill_aspect_2d :
+ imm_draw_circle_wire_aspect_2d;
+ const int resolu = 12;
+ const float rad[2] = {margin[0] / 3, margin[1] / 3};
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
+
+ /* should really divide by two, but looks too bulky. */
+ {
+ imm_draw_point_aspect_2d(pos, r->xmin, r->ymin, rad[0], rad[1], solid);
+ imm_draw_point_aspect_2d(pos, r->xmax, r->ymin, rad[0], rad[1], solid);
+ imm_draw_point_aspect_2d(pos, r->xmax, r->ymax, rad[0], rad[1], solid);
+ imm_draw_point_aspect_2d(pos, r->xmin, r->ymax, rad[0], rad[1], solid);
+ }
+
+ if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
+ const float handle[2] = {BLI_rctf_cent_x(r),
+ r->ymax + (margin[1] * GIZMO_MARGIN_OFFSET_SCALE)};
+ circle_fn(pos, handle[0], handle[1], rad[0], rad[1], resolu);
+ }
+
+ immUnbindProgram();
}
/** \} */
-static void gizmo_cage2d_draw_intern(
- wmGizmo *gz, const bool select, const bool highlight, const int select_id)
+static void gizmo_cage2d_draw_intern(wmGizmo *gz,
+ const bool select,
+ const bool highlight,
+ const int select_id)
{
- // const bool use_clamp = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0;
- float dims[2];
- RNA_float_get_array(gz->ptr, "dimensions", dims);
- float matrix_final[4][4];
-
- const int transform_flag = RNA_enum_get(gz->ptr, "transform");
- const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
- const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
-
- const float size_real[2] = {dims[0] / 2.0f, dims[1] / 2.0f};
-
- WM_gizmo_calc_matrix_final(gz, matrix_final);
-
- GPU_matrix_push();
- GPU_matrix_mul(matrix_final);
-
- float margin[2];
- gizmo_calc_rect_view_margin(gz, dims, margin);
-
- /* Handy for quick testing draw (if it's outside bounds). */
- if (false) {
- GPU_blend(true);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4fv((const float[4]){1, 1, 1, 0.5f});
- float s = 0.5f;
- immRectf(pos, -s, -s, s, s);
- immUnbindProgram();
- GPU_blend(false);
- }
-
- if (select) {
- /* expand for hotspot */
- const float size[2] = {size_real[0] + margin[0] / 2, size_real[1] + margin[1] / 2};
-
- if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE) {
- int scale_parts[] = {
- ED_GIZMO_CAGE2D_PART_SCALE_MIN_X,
- ED_GIZMO_CAGE2D_PART_SCALE_MAX_X,
- ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y,
- ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y,
-
- ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y,
- ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y,
- ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y,
- ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y,
- };
- for (int i = 0; i < ARRAY_SIZE(scale_parts); i++) {
- GPU_select_load_id(select_id | scale_parts[i]);
- cage2d_draw_box_interaction(
- gz->color, scale_parts[i], size, margin, gz->line_width, true, draw_options);
- }
- }
- if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
- const int transform_part = ED_GIZMO_CAGE2D_PART_TRANSLATE;
- GPU_select_load_id(select_id | transform_part);
- cage2d_draw_box_interaction(
- gz->color, transform_part, size, margin, gz->line_width, true, draw_options);
- }
- if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
- cage2d_draw_box_interaction(
- gz->color, ED_GIZMO_CAGE2D_PART_ROTATE, size_real, margin, gz->line_width, true, draw_options);
- }
- }
- else {
- const rctf r = {
- .xmin = -size_real[0],
- .ymin = -size_real[1],
- .xmax = size_real[0],
- .ymax = size_real[1],
- };
- if (draw_style == ED_GIZMO_CAGE2D_STYLE_BOX) {
- /* corner gizmos */
- GPU_line_width(gz->line_width + 3.0f);
- cage2d_draw_box_corners(&r, margin, (const float[3]){0, 0, 0});
-
- /* corner gizmos */
- float color[4];
- gizmo_color_get(gz, highlight, color);
- GPU_line_width(gz->line_width);
- cage2d_draw_box_corners(&r, margin, color);
-
- bool show = false;
- if (gz->highlight_part == ED_GIZMO_CAGE2D_PART_TRANSLATE) {
- /* Only show if we're drawing the center handle
- * otherwise the entire rectangle is the hotspot. */
- if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
- show = true;
- }
- }
- else {
- show = true;
- }
-
- if (show) {
- cage2d_draw_box_interaction(
- gz->color, gz->highlight_part, size_real, margin, gz->line_width, false, draw_options);
- }
-
- if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
- cage2d_draw_box_interaction(
- gz->color, ED_GIZMO_CAGE2D_PART_ROTATE, size_real, margin, gz->line_width, false, draw_options);
- }
- }
- else if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
- float color[4];
- 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);
-
-
- /* 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();
+ // const bool use_clamp = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0;
+ float dims[2];
+ RNA_float_get_array(gz->ptr, "dimensions", dims);
+ float matrix_final[4][4];
+
+ const int transform_flag = RNA_enum_get(gz->ptr, "transform");
+ const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
+ const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
+
+ const float size_real[2] = {dims[0] / 2.0f, dims[1] / 2.0f};
+
+ WM_gizmo_calc_matrix_final(gz, matrix_final);
+
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix_final);
+
+ float margin[2];
+ gizmo_calc_rect_view_margin(gz, dims, margin);
+
+ /* Handy for quick testing draw (if it's outside bounds). */
+ if (false) {
+ GPU_blend(true);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv((const float[4]){1, 1, 1, 0.5f});
+ float s = 0.5f;
+ immRectf(pos, -s, -s, s, s);
+ immUnbindProgram();
+ GPU_blend(false);
+ }
+
+ if (select) {
+ /* expand for hotspot */
+ const float size[2] = {size_real[0] + margin[0] / 2, size_real[1] + margin[1] / 2};
+
+ if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE) {
+ int scale_parts[] = {
+ ED_GIZMO_CAGE2D_PART_SCALE_MIN_X,
+ ED_GIZMO_CAGE2D_PART_SCALE_MAX_X,
+ ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y,
+ ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y,
+
+ ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y,
+ ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y,
+ ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y,
+ ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y,
+ };
+ for (int i = 0; i < ARRAY_SIZE(scale_parts); i++) {
+ GPU_select_load_id(select_id | scale_parts[i]);
+ cage2d_draw_box_interaction(
+ gz->color, scale_parts[i], size, margin, gz->line_width, true, draw_options);
+ }
+ }
+ if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
+ const int transform_part = ED_GIZMO_CAGE2D_PART_TRANSLATE;
+ GPU_select_load_id(select_id | transform_part);
+ cage2d_draw_box_interaction(
+ gz->color, transform_part, size, margin, gz->line_width, true, draw_options);
+ }
+ if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
+ cage2d_draw_box_interaction(gz->color,
+ ED_GIZMO_CAGE2D_PART_ROTATE,
+ size_real,
+ margin,
+ gz->line_width,
+ true,
+ draw_options);
+ }
+ }
+ else {
+ const rctf r = {
+ .xmin = -size_real[0],
+ .ymin = -size_real[1],
+ .xmax = size_real[0],
+ .ymax = size_real[1],
+ };
+ if (draw_style == ED_GIZMO_CAGE2D_STYLE_BOX) {
+ /* corner gizmos */
+ GPU_line_width(gz->line_width + 3.0f);
+ cage2d_draw_box_corners(&r, margin, (const float[3]){0, 0, 0});
+
+ /* corner gizmos */
+ float color[4];
+ gizmo_color_get(gz, highlight, color);
+ GPU_line_width(gz->line_width);
+ cage2d_draw_box_corners(&r, margin, color);
+
+ bool show = false;
+ if (gz->highlight_part == ED_GIZMO_CAGE2D_PART_TRANSLATE) {
+ /* Only show if we're drawing the center handle
+ * otherwise the entire rectangle is the hotspot. */
+ if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
+ show = true;
+ }
+ }
+ else {
+ show = true;
+ }
+
+ if (show) {
+ cage2d_draw_box_interaction(
+ gz->color, gz->highlight_part, size_real, margin, gz->line_width, false, draw_options);
+ }
+
+ if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
+ cage2d_draw_box_interaction(gz->color,
+ ED_GIZMO_CAGE2D_PART_ROTATE,
+ size_real,
+ margin,
+ gz->line_width,
+ false,
+ draw_options);
+ }
+ }
+ else if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
+ float color[4];
+ 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);
+
+ /* 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();
}
/**
@@ -680,377 +735,400 @@ static void gizmo_cage2d_draw_intern(
*/
static void gizmo_cage2d_draw_select(const bContext *UNUSED(C), wmGizmo *gz, int select_id)
{
- gizmo_cage2d_draw_intern(gz, true, false, select_id);
+ gizmo_cage2d_draw_intern(gz, true, false, select_id);
}
static void gizmo_cage2d_draw(const bContext *UNUSED(C), wmGizmo *gz)
{
- const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
- gizmo_cage2d_draw_intern(gz, false, is_highlight, -1);
+ const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
+ gizmo_cage2d_draw_intern(gz, false, is_highlight, -1);
}
static int gizmo_cage2d_get_cursor(wmGizmo *gz)
{
- int highlight_part = gz->highlight_part;
-
- if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
- return BC_NSEW_SCROLLCURSOR;
- }
-
- switch (highlight_part) {
- case ED_GIZMO_CAGE2D_PART_TRANSLATE:
- return BC_NSEW_SCROLLCURSOR;
- case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X:
- case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X:
- return CURSOR_X_MOVE;
- case ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y:
- case ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y:
- return CURSOR_Y_MOVE;
-
- /* TODO diagonal cursor */
- case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y:
- case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y:
- return BC_NSEW_SCROLLCURSOR;
- case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y:
- case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y:
- return BC_NSEW_SCROLLCURSOR;
- case ED_GIZMO_CAGE2D_PART_ROTATE:
- return BC_CROSSCURSOR;
- default:
- return CURSOR_STD;
- }
+ int highlight_part = gz->highlight_part;
+
+ if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
+ return BC_NSEW_SCROLLCURSOR;
+ }
+
+ switch (highlight_part) {
+ case ED_GIZMO_CAGE2D_PART_TRANSLATE:
+ return BC_NSEW_SCROLLCURSOR;
+ case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X:
+ case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X:
+ return CURSOR_X_MOVE;
+ case ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y:
+ case ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y:
+ return CURSOR_Y_MOVE;
+
+ /* TODO diagonal cursor */
+ case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y:
+ case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y:
+ return BC_NSEW_SCROLLCURSOR;
+ case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y:
+ case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y:
+ return BC_NSEW_SCROLLCURSOR;
+ case ED_GIZMO_CAGE2D_PART_ROTATE:
+ return BC_CROSSCURSOR;
+ default:
+ return CURSOR_STD;
+ }
}
-static int gizmo_cage2d_test_select(
- bContext *C, wmGizmo *gz, const int mval[2])
+static int gizmo_cage2d_test_select(bContext *C, wmGizmo *gz, const int mval[2])
{
- float point_local[2];
- float dims[2];
- RNA_float_get_array(gz->ptr, "dimensions", dims);
- const float size_real[2] = {dims[0] / 2.0f, dims[1] / 2.0f};
-
- if (gizmo_window_project_2d(
- C, gz, (const float[2]){UNPACK2(mval)}, 2, true, point_local) == false)
- {
- return -1;
- }
-
- float margin[2];
- if (!gizmo_calc_rect_view_margin(gz, dims, margin)) {
- return -1;
- }
-
- /* expand for hotspot */
- const float size[2] = {size_real[0] + margin[0] / 2, size_real[1] + margin[1] / 2};
-
- const int transform_flag = RNA_enum_get(gz->ptr, "transform");
- const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
-
- if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
- rctf r;
- if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
- r.xmin = -margin[0] / 2;
- r.ymin = -margin[1] / 2;
- r.xmax = margin[0] / 2;
- r.ymax = margin[1] / 2;
- }
- else {
- r.xmin = -size[0] + margin[0];
- r.ymin = -size[1] + margin[1];
- r.xmax = size[0] - margin[0];
- r.ymax = size[1] - margin[1];
- }
- bool isect = BLI_rctf_isect_pt_v(&r, point_local);
- if (isect) {
- return ED_GIZMO_CAGE2D_PART_TRANSLATE;
- }
- }
-
- /* if gizmo does not have a scale intersection, don't do it */
- if (transform_flag & (ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM)) {
- const rctf r_xmin = { .xmin = -size[0], .ymin = -size[1], .xmax = -size[0] + margin[0], .ymax = size[1], };
- const rctf r_xmax = { .xmin = size[0] - margin[0], .ymin = -size[1], .xmax = size[0], .ymax = size[1], };
- const rctf r_ymin = { .xmin = -size[0], .ymin = -size[1], .xmax = size[0], .ymax = -size[1] + margin[1], };
- const rctf r_ymax = { .xmin = -size[0], .ymin = size[1] - margin[1], .xmax = size[0], .ymax = size[1], };
-
- if (BLI_rctf_isect_pt_v(&r_xmin, point_local)) {
- if (BLI_rctf_isect_pt_v(&r_ymin, point_local)) {
- return ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y;
- }
- if (BLI_rctf_isect_pt_v(&r_ymax, point_local)) {
- return ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y;
- }
- return ED_GIZMO_CAGE2D_PART_SCALE_MIN_X;
- }
- if (BLI_rctf_isect_pt_v(&r_xmax, point_local)) {
- if (BLI_rctf_isect_pt_v(&r_ymin, point_local)) {
- return ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y;
- }
- if (BLI_rctf_isect_pt_v(&r_ymax, point_local)) {
- return ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y;
- }
- return ED_GIZMO_CAGE2D_PART_SCALE_MAX_X;
- }
- if (BLI_rctf_isect_pt_v(&r_ymin, point_local)) {
- return ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y;
- }
- if (BLI_rctf_isect_pt_v(&r_ymax, point_local)) {
- return ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y;
- }
- }
-
- if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
- /* Rotate:
- * (*) <-- hot spot is here!
- * +---+
- * | |
- * +---+ */
- const float r_rotate_pt[2] = {0.0f, size_real[1] + (margin[1] * GIZMO_MARGIN_OFFSET_SCALE)};
- const rctf r_rotate = {
- .xmin = r_rotate_pt[0] - margin[0] / 2.0f,
- .xmax = r_rotate_pt[0] + margin[0] / 2.0f,
- .ymin = r_rotate_pt[1] - margin[1] / 2.0f,
- .ymax = r_rotate_pt[1] + margin[1] / 2.0f,
- };
-
- if (BLI_rctf_isect_pt_v(&r_rotate, point_local)) {
- return ED_GIZMO_CAGE2D_PART_ROTATE;
- }
- }
-
- return -1;
+ float point_local[2];
+ float dims[2];
+ RNA_float_get_array(gz->ptr, "dimensions", dims);
+ const float size_real[2] = {dims[0] / 2.0f, dims[1] / 2.0f};
+
+ if (gizmo_window_project_2d(C, gz, (const float[2]){UNPACK2(mval)}, 2, true, point_local) ==
+ false) {
+ return -1;
+ }
+
+ float margin[2];
+ if (!gizmo_calc_rect_view_margin(gz, dims, margin)) {
+ return -1;
+ }
+
+ /* expand for hotspot */
+ const float size[2] = {size_real[0] + margin[0] / 2, size_real[1] + margin[1] / 2};
+
+ const int transform_flag = RNA_enum_get(gz->ptr, "transform");
+ const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
+
+ if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
+ rctf r;
+ if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
+ r.xmin = -margin[0] / 2;
+ r.ymin = -margin[1] / 2;
+ r.xmax = margin[0] / 2;
+ r.ymax = margin[1] / 2;
+ }
+ else {
+ r.xmin = -size[0] + margin[0];
+ r.ymin = -size[1] + margin[1];
+ r.xmax = size[0] - margin[0];
+ r.ymax = size[1] - margin[1];
+ }
+ bool isect = BLI_rctf_isect_pt_v(&r, point_local);
+ if (isect) {
+ return ED_GIZMO_CAGE2D_PART_TRANSLATE;
+ }
+ }
+
+ /* if gizmo does not have a scale intersection, don't do it */
+ if (transform_flag &
+ (ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM)) {
+ const rctf r_xmin = {
+ .xmin = -size[0],
+ .ymin = -size[1],
+ .xmax = -size[0] + margin[0],
+ .ymax = size[1],
+ };
+ const rctf r_xmax = {
+ .xmin = size[0] - margin[0],
+ .ymin = -size[1],
+ .xmax = size[0],
+ .ymax = size[1],
+ };
+ const rctf r_ymin = {
+ .xmin = -size[0],
+ .ymin = -size[1],
+ .xmax = size[0],
+ .ymax = -size[1] + margin[1],
+ };
+ const rctf r_ymax = {
+ .xmin = -size[0],
+ .ymin = size[1] - margin[1],
+ .xmax = size[0],
+ .ymax = size[1],
+ };
+
+ if (BLI_rctf_isect_pt_v(&r_xmin, point_local)) {
+ if (BLI_rctf_isect_pt_v(&r_ymin, point_local)) {
+ return ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y;
+ }
+ if (BLI_rctf_isect_pt_v(&r_ymax, point_local)) {
+ return ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y;
+ }
+ return ED_GIZMO_CAGE2D_PART_SCALE_MIN_X;
+ }
+ if (BLI_rctf_isect_pt_v(&r_xmax, point_local)) {
+ if (BLI_rctf_isect_pt_v(&r_ymin, point_local)) {
+ return ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y;
+ }
+ if (BLI_rctf_isect_pt_v(&r_ymax, point_local)) {
+ return ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y;
+ }
+ return ED_GIZMO_CAGE2D_PART_SCALE_MAX_X;
+ }
+ if (BLI_rctf_isect_pt_v(&r_ymin, point_local)) {
+ return ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y;
+ }
+ if (BLI_rctf_isect_pt_v(&r_ymax, point_local)) {
+ return ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y;
+ }
+ }
+
+ if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
+ /* Rotate:
+ * (*) <-- hot spot is here!
+ * +---+
+ * | |
+ * +---+ */
+ const float r_rotate_pt[2] = {0.0f, size_real[1] + (margin[1] * GIZMO_MARGIN_OFFSET_SCALE)};
+ const rctf r_rotate = {
+ .xmin = r_rotate_pt[0] - margin[0] / 2.0f,
+ .xmax = r_rotate_pt[0] + margin[0] / 2.0f,
+ .ymin = r_rotate_pt[1] - margin[1] / 2.0f,
+ .ymax = r_rotate_pt[1] + margin[1] / 2.0f,
+ };
+
+ if (BLI_rctf_isect_pt_v(&r_rotate, point_local)) {
+ return ED_GIZMO_CAGE2D_PART_ROTATE;
+ }
+ }
+
+ return -1;
}
typedef struct RectTransformInteraction {
- float orig_mouse[2];
- float orig_matrix_offset[4][4];
- float orig_matrix_final_no_offset[4][4];
- Dial *dial;
+ float orig_mouse[2];
+ float orig_matrix_offset[4][4];
+ float orig_matrix_final_no_offset[4][4];
+ Dial *dial;
} RectTransformInteraction;
static void gizmo_cage2d_setup(wmGizmo *gz)
{
- gz->flag |= WM_GIZMO_DRAW_MODAL | WM_GIZMO_DRAW_NO_SCALE;
+ gz->flag |= WM_GIZMO_DRAW_MODAL | WM_GIZMO_DRAW_NO_SCALE;
}
-static int gizmo_cage2d_invoke(
- bContext *C, wmGizmo *gz, const wmEvent *event)
+static int gizmo_cage2d_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
{
- RectTransformInteraction *data = MEM_callocN(sizeof(RectTransformInteraction), "cage_interaction");
+ RectTransformInteraction *data = MEM_callocN(sizeof(RectTransformInteraction),
+ "cage_interaction");
- copy_m4_m4(data->orig_matrix_offset, gz->matrix_offset);
- WM_gizmo_calc_matrix_final_no_offset(gz, data->orig_matrix_final_no_offset);
+ copy_m4_m4(data->orig_matrix_offset, gz->matrix_offset);
+ WM_gizmo_calc_matrix_final_no_offset(gz, data->orig_matrix_final_no_offset);
- if (gizmo_window_project_2d(
- C, gz, (const float[2]){UNPACK2(event->mval)}, 2, false, data->orig_mouse) == 0)
- {
- zero_v2(data->orig_mouse);
- }
+ if (gizmo_window_project_2d(
+ C, gz, (const float[2]){UNPACK2(event->mval)}, 2, false, data->orig_mouse) == 0) {
+ zero_v2(data->orig_mouse);
+ }
- gz->interaction_data = data;
+ gz->interaction_data = data;
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
-static int gizmo_cage2d_modal(
- bContext *C, wmGizmo *gz, const wmEvent *event,
- eWM_GizmoFlagTweak UNUSED(tweak_flag))
+static int gizmo_cage2d_modal(bContext *C,
+ wmGizmo *gz,
+ const wmEvent *event,
+ eWM_GizmoFlagTweak UNUSED(tweak_flag))
{
- if (event->type != MOUSEMOVE) {
- return OPERATOR_RUNNING_MODAL;
- }
- /* For transform logic to be manageable we operate in -0.5..0.5 2D space,
- * no matter the size of the rectangle, mouse coords are scaled to unit space.
- * The mouse coords have been projected into the matrix so we don't need to worry about axis alignment.
- *
- * - The cursor offset are multiplied by 'dims'.
- * - Matrix translation is also multiplied by 'dims'.
- */
- RectTransformInteraction *data = gz->interaction_data;
- float point_local[2];
-
- float dims[2];
- RNA_float_get_array(gz->ptr, "dimensions", dims);
-
- {
- float matrix_back[4][4];
- copy_m4_m4(matrix_back, gz->matrix_offset);
- copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
-
- bool ok = gizmo_window_project_2d(
- C, gz, (const float[2]){UNPACK2(event->mval)}, 2, false, point_local);
- copy_m4_m4(gz->matrix_offset, matrix_back);
- if (!ok) {
- return OPERATOR_RUNNING_MODAL;
- }
- }
-
- const int transform_flag = RNA_enum_get(gz->ptr, "transform");
- wmGizmoProperty *gz_prop;
-
- gz_prop = WM_gizmo_target_property_find(gz, "matrix");
- if (gz_prop->type != NULL) {
- WM_gizmo_target_property_float_get_array(gz, gz_prop, &gz->matrix_offset[0][0]);
- }
-
- if (gz->highlight_part == ED_GIZMO_CAGE2D_PART_TRANSLATE) {
- /* do this to prevent clamping from changing size */
- copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
- gz->matrix_offset[3][0] = data->orig_matrix_offset[3][0] + (point_local[0] - data->orig_mouse[0]);
- gz->matrix_offset[3][1] = data->orig_matrix_offset[3][1] + (point_local[1] - data->orig_mouse[1]);
- }
- else if (gz->highlight_part == ED_GIZMO_CAGE2D_PART_ROTATE) {
+ if (event->type != MOUSEMOVE) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+ /* For transform logic to be manageable we operate in -0.5..0.5 2D space,
+ * no matter the size of the rectangle, mouse coords are scaled to unit space.
+ * The mouse coords have been projected into the matrix so we don't need to worry about axis alignment.
+ *
+ * - The cursor offset are multiplied by 'dims'.
+ * - Matrix translation is also multiplied by 'dims'.
+ */
+ RectTransformInteraction *data = gz->interaction_data;
+ float point_local[2];
+
+ float dims[2];
+ RNA_float_get_array(gz->ptr, "dimensions", dims);
+
+ {
+ float matrix_back[4][4];
+ copy_m4_m4(matrix_back, gz->matrix_offset);
+ copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
+
+ bool ok = gizmo_window_project_2d(
+ C, gz, (const float[2]){UNPACK2(event->mval)}, 2, false, point_local);
+ copy_m4_m4(gz->matrix_offset, matrix_back);
+ if (!ok) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+
+ const int transform_flag = RNA_enum_get(gz->ptr, "transform");
+ wmGizmoProperty *gz_prop;
+
+ gz_prop = WM_gizmo_target_property_find(gz, "matrix");
+ if (gz_prop->type != NULL) {
+ WM_gizmo_target_property_float_get_array(gz, gz_prop, &gz->matrix_offset[0][0]);
+ }
+
+ if (gz->highlight_part == ED_GIZMO_CAGE2D_PART_TRANSLATE) {
+ /* do this to prevent clamping from changing size */
+ copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
+ gz->matrix_offset[3][0] = data->orig_matrix_offset[3][0] +
+ (point_local[0] - data->orig_mouse[0]);
+ gz->matrix_offset[3][1] = data->orig_matrix_offset[3][1] +
+ (point_local[1] - data->orig_mouse[1]);
+ }
+ else if (gz->highlight_part == ED_GIZMO_CAGE2D_PART_ROTATE) {
#define MUL_V2_V3_M4_FINAL(test_co, mouse_co) \
- mul_v3_m4v3(test_co, data->orig_matrix_final_no_offset, ((const float[3]){UNPACK2(mouse_co), 0.0}))
+ mul_v3_m4v3( \
+ test_co, data->orig_matrix_final_no_offset, ((const float[3]){UNPACK2(mouse_co), 0.0}))
- float test_co[3];
+ float test_co[3];
- if (data->dial == NULL) {
- MUL_V2_V3_M4_FINAL(test_co, data->orig_matrix_offset[3]);
+ if (data->dial == NULL) {
+ MUL_V2_V3_M4_FINAL(test_co, data->orig_matrix_offset[3]);
- data->dial = BLI_dial_initialize(test_co, FLT_EPSILON);
+ data->dial = BLI_dial_initialize(test_co, FLT_EPSILON);
- MUL_V2_V3_M4_FINAL(test_co, data->orig_mouse);
- BLI_dial_angle(data->dial, test_co);
- }
+ MUL_V2_V3_M4_FINAL(test_co, data->orig_mouse);
+ BLI_dial_angle(data->dial, test_co);
+ }
- /* rotate */
- MUL_V2_V3_M4_FINAL(test_co, point_local);
- const float angle = BLI_dial_angle(data->dial, test_co);
+ /* rotate */
+ MUL_V2_V3_M4_FINAL(test_co, point_local);
+ const float angle = BLI_dial_angle(data->dial, test_co);
- float matrix_space_inv[4][4];
- float matrix_rotate[4][4];
- float pivot[3];
+ float matrix_space_inv[4][4];
+ float matrix_rotate[4][4];
+ float pivot[3];
- copy_v3_v3(pivot, data->orig_matrix_offset[3]);
+ copy_v3_v3(pivot, data->orig_matrix_offset[3]);
- invert_m4_m4(matrix_space_inv, gz->matrix_space);
+ invert_m4_m4(matrix_space_inv, gz->matrix_space);
- unit_m4(matrix_rotate);
- mul_m4_m4m4(matrix_rotate, matrix_rotate, matrix_space_inv);
- rotate_m4(matrix_rotate, 'Z', -angle);
- mul_m4_m4m4(matrix_rotate, matrix_rotate, gz->matrix_space);
+ unit_m4(matrix_rotate);
+ mul_m4_m4m4(matrix_rotate, matrix_rotate, matrix_space_inv);
+ rotate_m4(matrix_rotate, 'Z', -angle);
+ mul_m4_m4m4(matrix_rotate, matrix_rotate, gz->matrix_space);
- zero_v3(matrix_rotate[3]);
- transform_pivot_set_m4(matrix_rotate, pivot);
+ zero_v3(matrix_rotate[3]);
+ transform_pivot_set_m4(matrix_rotate, pivot);
- mul_m4_m4m4(gz->matrix_offset, matrix_rotate, data->orig_matrix_offset);
+ mul_m4_m4m4(gz->matrix_offset, matrix_rotate, data->orig_matrix_offset);
#undef MUL_V2_V3_M4_FINAL
- }
- else {
- /* scale */
- copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
- float pivot[2];
- bool constrain_axis[2] = {false};
-
- if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
- gizmo_rect_pivot_from_scale_part(gz->highlight_part, pivot, constrain_axis);
- }
- else {
- zero_v2(pivot);
- }
-
- /* Cursor deltas scaled to (-0.5..0.5). */
- float delta_orig[2], delta_curr[2];
- for (int i = 0; i < 2; i++) {
- delta_orig[i] = ((data->orig_mouse[i] - data->orig_matrix_offset[3][i]) / dims[i]) - pivot[i];
- delta_curr[i] = ((point_local[i] - data->orig_matrix_offset[3][i]) / dims[i]) - pivot[i];
- }
-
- float scale[2] = {1.0f, 1.0f};
- for (int i = 0; i < 2; i++) {
- if (constrain_axis[i] == false) {
- if (delta_orig[i] < 0.0f) {
- delta_orig[i] *= -1.0f;
- delta_curr[i] *= -1.0f;
- }
- const int sign = signum_i(scale[i]);
-
- scale[i] = 1.0f + ((delta_curr[i] - delta_orig[i]) / len_v3(data->orig_matrix_offset[i]));
-
- if ((transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_SIGNED) == 0) {
- if (sign != signum_i(scale[i])) {
- scale[i] = 0.0f;
- }
- }
- }
- }
-
- if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM) {
- if (constrain_axis[0] == false && constrain_axis[1] == false) {
- scale[1] = scale[0] = (scale[1] + scale[0]) / 2.0f;
- }
- else if (constrain_axis[0] == false) {
- scale[1] = scale[0];
- }
- else if (constrain_axis[1] == false) {
- scale[0] = scale[1];
- }
- else {
- BLI_assert(0);
- }
- }
-
- /* scale around pivot */
- float matrix_scale[4][4];
- unit_m4(matrix_scale);
-
- mul_v3_fl(matrix_scale[0], scale[0]);
- mul_v3_fl(matrix_scale[1], scale[1]);
-
- transform_pivot_set_m4(matrix_scale, (const float[3]){pivot[0] * dims[0], pivot[1] * dims[1], 0.0f});
- mul_m4_m4m4(gz->matrix_offset, data->orig_matrix_offset, matrix_scale);
- }
-
- if (gz_prop->type != NULL) {
- WM_gizmo_target_property_float_set_array(C, gz, gz_prop, &gz->matrix_offset[0][0]);
- }
-
- /* tag the region for redraw */
- ED_region_tag_redraw(CTX_wm_region(C));
- WM_event_add_mousemove(C);
-
- return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ /* scale */
+ copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
+ float pivot[2];
+ bool constrain_axis[2] = {false};
+
+ if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
+ gizmo_rect_pivot_from_scale_part(gz->highlight_part, pivot, constrain_axis);
+ }
+ else {
+ zero_v2(pivot);
+ }
+
+ /* Cursor deltas scaled to (-0.5..0.5). */
+ float delta_orig[2], delta_curr[2];
+ for (int i = 0; i < 2; i++) {
+ delta_orig[i] = ((data->orig_mouse[i] - data->orig_matrix_offset[3][i]) / dims[i]) -
+ pivot[i];
+ delta_curr[i] = ((point_local[i] - data->orig_matrix_offset[3][i]) / dims[i]) - pivot[i];
+ }
+
+ float scale[2] = {1.0f, 1.0f};
+ for (int i = 0; i < 2; i++) {
+ if (constrain_axis[i] == false) {
+ if (delta_orig[i] < 0.0f) {
+ delta_orig[i] *= -1.0f;
+ delta_curr[i] *= -1.0f;
+ }
+ const int sign = signum_i(scale[i]);
+
+ scale[i] = 1.0f + ((delta_curr[i] - delta_orig[i]) / len_v3(data->orig_matrix_offset[i]));
+
+ if ((transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_SIGNED) == 0) {
+ if (sign != signum_i(scale[i])) {
+ scale[i] = 0.0f;
+ }
+ }
+ }
+ }
+
+ if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM) {
+ if (constrain_axis[0] == false && constrain_axis[1] == false) {
+ scale[1] = scale[0] = (scale[1] + scale[0]) / 2.0f;
+ }
+ else if (constrain_axis[0] == false) {
+ scale[1] = scale[0];
+ }
+ else if (constrain_axis[1] == false) {
+ scale[0] = scale[1];
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+
+ /* scale around pivot */
+ float matrix_scale[4][4];
+ unit_m4(matrix_scale);
+
+ mul_v3_fl(matrix_scale[0], scale[0]);
+ mul_v3_fl(matrix_scale[1], scale[1]);
+
+ transform_pivot_set_m4(matrix_scale,
+ (const float[3]){pivot[0] * dims[0], pivot[1] * dims[1], 0.0f});
+ mul_m4_m4m4(gz->matrix_offset, data->orig_matrix_offset, matrix_scale);
+ }
+
+ if (gz_prop->type != NULL) {
+ WM_gizmo_target_property_float_set_array(C, gz, gz_prop, &gz->matrix_offset[0][0]);
+ }
+
+ /* tag the region for redraw */
+ ED_region_tag_redraw(CTX_wm_region(C));
+ WM_event_add_mousemove(C);
+
+ return OPERATOR_RUNNING_MODAL;
}
static void gizmo_cage2d_property_update(wmGizmo *gz, wmGizmoProperty *gz_prop)
{
- if (STREQ(gz_prop->type->idname, "matrix")) {
- if (WM_gizmo_target_property_array_length(gz, gz_prop) == 16) {
- WM_gizmo_target_property_float_get_array(gz, gz_prop, &gz->matrix_offset[0][0]);
- }
- else {
- BLI_assert(0);
- }
- }
- else {
- BLI_assert(0);
- }
+ if (STREQ(gz_prop->type->idname, "matrix")) {
+ if (WM_gizmo_target_property_array_length(gz, gz_prop) == 16) {
+ WM_gizmo_target_property_float_get_array(gz, gz_prop, &gz->matrix_offset[0][0]);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
}
static void gizmo_cage2d_exit(bContext *C, wmGizmo *gz, const bool cancel)
{
- RectTransformInteraction *data = gz->interaction_data;
+ RectTransformInteraction *data = gz->interaction_data;
- MEM_SAFE_FREE(data->dial);
+ MEM_SAFE_FREE(data->dial);
- if (!cancel)
- return;
+ if (!cancel)
+ return;
- wmGizmoProperty *gz_prop;
+ wmGizmoProperty *gz_prop;
- /* reset properties */
- gz_prop = WM_gizmo_target_property_find(gz, "matrix");
- if (gz_prop->type != NULL) {
- WM_gizmo_target_property_float_set_array(C, gz, gz_prop, &data->orig_matrix_offset[0][0]);
- }
+ /* reset properties */
+ gz_prop = WM_gizmo_target_property_find(gz, "matrix");
+ if (gz_prop->type != NULL) {
+ WM_gizmo_target_property_float_set_array(C, gz, gz_prop, &data->orig_matrix_offset[0][0]);
+ }
- copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
+ copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
}
-
/* -------------------------------------------------------------------- */
/** \name Cage Gizmo API
*
@@ -1058,53 +1136,66 @@ static void gizmo_cage2d_exit(bContext *C, wmGizmo *gz, const bool cancel)
static void GIZMO_GT_cage_2d(wmGizmoType *gzt)
{
- /* identifiers */
- gzt->idname = "GIZMO_GT_cage_2d";
-
- /* api callbacks */
- gzt->draw = gizmo_cage2d_draw;
- gzt->draw_select = gizmo_cage2d_draw_select;
- gzt->test_select = gizmo_cage2d_test_select;
- gzt->setup = gizmo_cage2d_setup;
- gzt->invoke = gizmo_cage2d_invoke;
- gzt->property_update = gizmo_cage2d_property_update;
- gzt->modal = gizmo_cage2d_modal;
- gzt->exit = gizmo_cage2d_exit;
- gzt->cursor_get = gizmo_cage2d_get_cursor;
-
- gzt->struct_size = sizeof(wmGizmo);
-
- /* rna */
- static EnumPropertyItem rna_enum_draw_style[] = {
- {ED_GIZMO_CAGE2D_STYLE_BOX, "BOX", 0, "Box", ""},
- {ED_GIZMO_CAGE2D_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""},
- {0, NULL, 0, NULL, NULL},
- };
- static EnumPropertyItem rna_enum_transform[] = {
- {ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE, "TRANSLATE", 0, "Move", ""},
- {ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE, "ROTATE", 0, "Rotate", ""},
- {ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE, "SCALE", 0, "Scale", ""},
- {ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM, "SCALE_UNIFORM", 0, "Scale Uniform", ""},
- {0, NULL, 0, NULL, NULL},
- };
- static EnumPropertyItem rna_enum_draw_options[] = {
- {ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE, "XFORM_CENTER_HANDLE", 0, "Center Handle", ""},
- {0, NULL, 0, NULL, NULL},
- };
- static float unit_v2[2] = {1.0f, 1.0f};
- RNA_def_float_vector(gzt->srna, "dimensions", 2, unit_v2, 0, FLT_MAX, "Dimensions", "", 0.0f, FLT_MAX);
- RNA_def_enum_flag(gzt->srna, "transform", rna_enum_transform, 0, "Transform Options", "");
- RNA_def_enum(gzt->srna, "draw_style", rna_enum_draw_style, ED_GIZMO_CAGE2D_STYLE_CIRCLE, "Draw Style", "");
- RNA_def_enum_flag(
- gzt->srna, "draw_options", rna_enum_draw_options,
- ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE, "Draw Options", "");
-
- WM_gizmotype_target_property_def(gzt, "matrix", PROP_FLOAT, 16);
+ /* identifiers */
+ gzt->idname = "GIZMO_GT_cage_2d";
+
+ /* api callbacks */
+ gzt->draw = gizmo_cage2d_draw;
+ gzt->draw_select = gizmo_cage2d_draw_select;
+ gzt->test_select = gizmo_cage2d_test_select;
+ gzt->setup = gizmo_cage2d_setup;
+ gzt->invoke = gizmo_cage2d_invoke;
+ gzt->property_update = gizmo_cage2d_property_update;
+ gzt->modal = gizmo_cage2d_modal;
+ gzt->exit = gizmo_cage2d_exit;
+ gzt->cursor_get = gizmo_cage2d_get_cursor;
+
+ gzt->struct_size = sizeof(wmGizmo);
+
+ /* rna */
+ static EnumPropertyItem rna_enum_draw_style[] = {
+ {ED_GIZMO_CAGE2D_STYLE_BOX, "BOX", 0, "Box", ""},
+ {ED_GIZMO_CAGE2D_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+ static EnumPropertyItem rna_enum_transform[] = {
+ {ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE, "TRANSLATE", 0, "Move", ""},
+ {ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE, "ROTATE", 0, "Rotate", ""},
+ {ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE, "SCALE", 0, "Scale", ""},
+ {ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM, "SCALE_UNIFORM", 0, "Scale Uniform", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+ static EnumPropertyItem rna_enum_draw_options[] = {
+ {ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE,
+ "XFORM_CENTER_HANDLE",
+ 0,
+ "Center Handle",
+ ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+ static float unit_v2[2] = {1.0f, 1.0f};
+ RNA_def_float_vector(
+ gzt->srna, "dimensions", 2, unit_v2, 0, FLT_MAX, "Dimensions", "", 0.0f, FLT_MAX);
+ RNA_def_enum_flag(gzt->srna, "transform", rna_enum_transform, 0, "Transform Options", "");
+ RNA_def_enum(gzt->srna,
+ "draw_style",
+ rna_enum_draw_style,
+ ED_GIZMO_CAGE2D_STYLE_CIRCLE,
+ "Draw Style",
+ "");
+ RNA_def_enum_flag(gzt->srna,
+ "draw_options",
+ rna_enum_draw_options,
+ ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE,
+ "Draw Options",
+ "");
+
+ WM_gizmotype_target_property_def(gzt, "matrix", PROP_FLOAT, 16);
}
void ED_gizmotypes_cage_2d(void)
{
- WM_gizmotype_append(GIZMO_GT_cage_2d);
+ WM_gizmotype_append(GIZMO_GT_cage_2d);
}
/** \} */
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 9579f7db196..3273012930a 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c
@@ -57,79 +57,77 @@
#define GIZMO_RESIZER_SIZE 10.0f
#define GIZMO_MARGIN_OFFSET_SCALE 1.5f
-static void gizmo_calc_matrix_final_no_offset(
- const wmGizmo *gz, float orig_matrix_final_no_offset[4][4], bool use_space)
+static void gizmo_calc_matrix_final_no_offset(const wmGizmo *gz,
+ float orig_matrix_final_no_offset[4][4],
+ bool use_space)
{
- float mat_identity[4][4];
- struct WM_GizmoMatrixParams params = {NULL};
- unit_m4(mat_identity);
- if (use_space == false) {
- params.matrix_basis = mat_identity;
- }
- params.matrix_offset = mat_identity;
- WM_gizmo_calc_matrix_final_params(gz, &params, orig_matrix_final_no_offset);
+ float mat_identity[4][4];
+ struct WM_GizmoMatrixParams params = {NULL};
+ unit_m4(mat_identity);
+ if (use_space == false) {
+ params.matrix_basis = mat_identity;
+ }
+ params.matrix_offset = mat_identity;
+ WM_gizmo_calc_matrix_final_params(gz, &params, orig_matrix_final_no_offset);
}
-static void gizmo_calc_rect_view_scale(
- const wmGizmo *gz, const float dims[3], float scale[3])
+static void gizmo_calc_rect_view_scale(const wmGizmo *gz, const float dims[3], float scale[3])
{
- UNUSED_VARS(dims);
+ UNUSED_VARS(dims);
- /* Unlike cage2d, no need to correct for aspect. */
- float matrix_final_no_offset[4][4];
+ /* Unlike cage2d, no need to correct for aspect. */
+ float matrix_final_no_offset[4][4];
- float x_axis[3], y_axis[3], z_axis[3];
- gizmo_calc_matrix_final_no_offset(gz, matrix_final_no_offset, false);
- mul_v3_mat3_m4v3(x_axis, matrix_final_no_offset, gz->matrix_offset[0]);
- mul_v3_mat3_m4v3(y_axis, matrix_final_no_offset, gz->matrix_offset[1]);
- mul_v3_mat3_m4v3(z_axis, matrix_final_no_offset, gz->matrix_offset[2]);
+ float x_axis[3], y_axis[3], z_axis[3];
+ gizmo_calc_matrix_final_no_offset(gz, matrix_final_no_offset, false);
+ mul_v3_mat3_m4v3(x_axis, matrix_final_no_offset, gz->matrix_offset[0]);
+ mul_v3_mat3_m4v3(y_axis, matrix_final_no_offset, gz->matrix_offset[1]);
+ mul_v3_mat3_m4v3(z_axis, matrix_final_no_offset, gz->matrix_offset[2]);
- scale[0] = 1.0f / len_v3(x_axis);
- scale[1] = 1.0f / len_v3(y_axis);
- scale[2] = 1.0f / len_v3(z_axis);
+ scale[0] = 1.0f / len_v3(x_axis);
+ scale[1] = 1.0f / len_v3(y_axis);
+ scale[2] = 1.0f / len_v3(z_axis);
}
-static void gizmo_calc_rect_view_margin(
- const wmGizmo *gz, const float dims[3], float margin[3])
+static void gizmo_calc_rect_view_margin(const wmGizmo *gz, const float dims[3], float margin[3])
{
- float handle_size;
- if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
- handle_size = 0.15f;
- }
- else {
- handle_size = GIZMO_RESIZER_SIZE;
- }
- // XXX, the scale isn't taking offset into account, we need to calculate scale per handle!
- // handle_size *= gz->scale_final;
-
- float scale_xyz[3];
- gizmo_calc_rect_view_scale(gz, dims, scale_xyz);
- margin[0] = ((handle_size * scale_xyz[0]));
- margin[1] = ((handle_size * scale_xyz[1]));
- margin[2] = ((handle_size * scale_xyz[2]));
+ float handle_size;
+ if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
+ handle_size = 0.15f;
+ }
+ else {
+ handle_size = GIZMO_RESIZER_SIZE;
+ }
+ // XXX, the scale isn't taking offset into account, we need to calculate scale per handle!
+ // handle_size *= gz->scale_final;
+
+ float scale_xyz[3];
+ gizmo_calc_rect_view_scale(gz, dims, scale_xyz);
+ margin[0] = ((handle_size * scale_xyz[0]));
+ margin[1] = ((handle_size * scale_xyz[1]));
+ margin[2] = ((handle_size * scale_xyz[2]));
}
/* -------------------------------------------------------------------- */
static void gizmo_rect_pivot_from_scale_part(int part, float r_pt[3], bool r_constrain_axis[3])
{
- if (part >= ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z &&
- part <= ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z)
- {
- int index = (part - ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z);
- int range[3];
- range[2] = index % 3;
- index = index / 3;
- range[1] = index % 3;
- index = index / 3;
- range[0] = index % 3;
-
- const float sign[3] = {0.5f, 0.0f, -0.5f};
- for (int i = 0; i < 3; i++) {
- r_pt[i] = sign[range[i]];
- r_constrain_axis[i] = (range[i] == 1);
- }
- }
+ if (part >= ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z &&
+ part <= ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z) {
+ int index = (part - ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z);
+ int range[3];
+ range[2] = index % 3;
+ index = index / 3;
+ range[1] = index % 3;
+ index = index / 3;
+ range[0] = index % 3;
+
+ const float sign[3] = {0.5f, 0.0f, -0.5f};
+ for (int i = 0; i < 3; i++) {
+ r_pt[i] = sign[range[i]];
+ r_constrain_axis[i] = (range[i] == 1);
+ }
+ }
}
/* -------------------------------------------------------------------- */
@@ -138,51 +136,51 @@ 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])
{
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- UNUSED_VARS(margin);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ UNUSED_VARS(margin);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformColor3fv(color);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
- imm_draw_cube_wire_3d(pos, (float[3]){0}, r);
+ imm_draw_cube_wire_3d(pos, (float[3]){0}, r);
- immUnbindProgram();
+ immUnbindProgram();
}
-static void cage3d_draw_box_interaction(
- const float color[4], const int highlighted,
- const float size[3], const float margin[3])
+static void cage3d_draw_box_interaction(const float color[4],
+ const int highlighted,
+ const float size[3],
+ const float margin[3])
{
- if (highlighted >= ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z &&
- highlighted <= ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z)
- {
- int index = (highlighted - ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z);
- int range[3];
- range[2] = index % 3;
- index = index / 3;
- range[1] = index % 3;
- index = index / 3;
- range[0] = index % 3;
-
- const float sign[3] = {-1.0f, 0.0f, 1.0f};
- float co[3];
-
- for (int i = 0; i < 3; i++) {
- co[i] = size[i] * sign[range[i]];
- }
- const float rad[3] = {margin[0] / 3, margin[1] / 3, margin[2] / 3};
-
- {
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformColor3fv(color);
- imm_draw_cube_fill_3d(pos, co, rad);
- immUnbindProgram();
- }
- }
+ if (highlighted >= ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z &&
+ highlighted <= ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z) {
+ int index = (highlighted - ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z);
+ int range[3];
+ range[2] = index % 3;
+ index = index / 3;
+ range[1] = index % 3;
+ index = index / 3;
+ range[0] = index % 3;
+
+ const float sign[3] = {-1.0f, 0.0f, 1.0f};
+ float co[3];
+
+ for (int i = 0; i < 3; i++) {
+ co[i] = size[i] * sign[range[i]];
+ }
+ const float rad[3] = {margin[0] / 3, margin[1] / 3, margin[2] / 3};
+
+ {
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
+ imm_draw_cube_fill_3d(pos, co, rad);
+ immUnbindProgram();
+ }
+ }
}
/** \} */
@@ -193,217 +191,216 @@ static void cage3d_draw_box_interaction(
* Useful for 2D views, see: #ED_GIZMO_CAGE2D_STYLE_CIRCLE
* \{ */
-static void imm_draw_point_aspect_3d(
- uint pos, const float co[3], const float rad[3], bool solid)
+static void imm_draw_point_aspect_3d(uint pos, const float co[3], const float rad[3], bool solid)
{
- if (solid) {
- imm_draw_cube_fill_3d(pos, co, rad);
- }
- else {
- imm_draw_cube_wire_3d(pos, co, rad);
- }
+ if (solid) {
+ imm_draw_cube_fill_3d(pos, co, rad);
+ }
+ else {
+ imm_draw_cube_wire_3d(pos, co, rad);
+ }
}
-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)
+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)
{
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformColor3fv(color);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
- imm_draw_cube_wire_3d(pos, (float[3]){0}, r);
+ imm_draw_cube_wire_3d(pos, (float[3]){0}, r);
#if 0
- if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
- if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
- const float rad[2] = {margin[0] / 2, margin[1] / 2};
- const float center[2] = {0.0f, 0.0f};
-
- immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, center[0] - rad[0], center[1] - rad[1]);
- immVertex2f(pos, center[0] + rad[0], center[1] + rad[1]);
- immVertex2f(pos, center[0] + rad[0], center[1] - rad[1]);
- immVertex2f(pos, center[0] - rad[0], center[1] + rad[1]);
- immEnd();
- }
- }
+ if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
+ if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
+ const float rad[2] = {margin[0] / 2, margin[1] / 2};
+ const float center[2] = {0.0f, 0.0f};
+
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex2f(pos, center[0] - rad[0], center[1] - rad[1]);
+ immVertex2f(pos, center[0] + rad[0], center[1] + rad[1]);
+ immVertex2f(pos, center[0] + rad[0], center[1] - rad[1]);
+ immVertex2f(pos, center[0] - rad[0], center[1] + rad[1]);
+ immEnd();
+ }
+ }
#else
- UNUSED_VARS(margin, transform_flag, draw_options);
+ UNUSED_VARS(margin, transform_flag, draw_options);
#endif
-
- immUnbindProgram();
+ immUnbindProgram();
}
-static void cage3d_draw_circle_handles(
- const RegionView3D *rv3d, const float matrix_final[4][4],
- const float r[3], const float margin[3], const float color[3],
- bool solid, float scale)
+static void cage3d_draw_circle_handles(const RegionView3D *rv3d,
+ const float matrix_final[4][4],
+ const float r[3],
+ const float margin[3],
+ const float color[3],
+ bool solid,
+ float scale)
{
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- const float rad[3] = {margin[0] / 3, margin[1] / 3, margin[2] / 3};
-
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformColor3fv(color);
-
- float sign[3] = {-1.0f, 0.0f, 1.0f};
- for (int x = 0; x < 3; x++) {
- for (int y = 0; y < 3; y++) {
- for (int z = 0; z < 3; z++) {
- if (x == 1 && y == 1 && z == 1) {
- continue;
- }
- const float co[3] = {r[0] * sign[x], r[1] * sign[y], r[2] * sign[z]};
- float co_test[3];
- mul_v3_m4v3(co_test, matrix_final, co);
- float rad_scale[3];
- mul_v3_v3fl(rad_scale, rad, ED_view3d_pixel_size(rv3d, co_test) * scale);
- imm_draw_point_aspect_3d(pos, co, rad_scale, solid);
- }
- }
- }
-
- immUnbindProgram();
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ const float rad[3] = {margin[0] / 3, margin[1] / 3, margin[2] / 3};
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
+
+ float sign[3] = {-1.0f, 0.0f, 1.0f};
+ for (int x = 0; x < 3; x++) {
+ for (int y = 0; y < 3; y++) {
+ for (int z = 0; z < 3; z++) {
+ if (x == 1 && y == 1 && z == 1) {
+ continue;
+ }
+ const float co[3] = {r[0] * sign[x], r[1] * sign[y], r[2] * sign[z]};
+ float co_test[3];
+ mul_v3_m4v3(co_test, matrix_final, co);
+ float rad_scale[3];
+ mul_v3_v3fl(rad_scale, rad, ED_view3d_pixel_size(rv3d, co_test) * scale);
+ imm_draw_point_aspect_3d(pos, co, rad_scale, solid);
+ }
+ }
+ }
+
+ immUnbindProgram();
}
/** \} */
static void gizmo_cage3d_draw_intern(
- RegionView3D *rv3d,
- wmGizmo *gz, const bool select, const bool highlight, const int select_id)
+ RegionView3D *rv3d, wmGizmo *gz, const bool select, const bool highlight, const int select_id)
{
- // const bool use_clamp = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0;
- float dims[3];
- RNA_float_get_array(gz->ptr, "dimensions", dims);
- float matrix_final[4][4];
-
- const int transform_flag = RNA_enum_get(gz->ptr, "transform");
- const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
- const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
-
- const float size_real[3] = {dims[0] / 2.0f, dims[1] / 2.0f, dims[2] / 2.0f};
-
- WM_gizmo_calc_matrix_final(gz, matrix_final);
-
- GPU_matrix_push();
- GPU_matrix_mul(matrix_final);
-
- float margin[3];
- gizmo_calc_rect_view_margin(gz, dims, margin);
-
- /* Handy for quick testing draw (if it's outside bounds). */
- if (false) {
- GPU_blend(true);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformColor4fv((const float[4]){1, 1, 1, 0.5f});
- float s = 0.5f;
- immRectf(pos, -s, -s, s, s);
- immUnbindProgram();
- GPU_blend(false);
- }
-
- if (select) {
- /* expand for hotspot */
+ // const bool use_clamp = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0;
+ float dims[3];
+ RNA_float_get_array(gz->ptr, "dimensions", dims);
+ float matrix_final[4][4];
+
+ const int transform_flag = RNA_enum_get(gz->ptr, "transform");
+ const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
+ const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
+
+ const float size_real[3] = {dims[0] / 2.0f, dims[1] / 2.0f, dims[2] / 2.0f};
+
+ WM_gizmo_calc_matrix_final(gz, matrix_final);
+
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix_final);
+
+ float margin[3];
+ gizmo_calc_rect_view_margin(gz, dims, margin);
+
+ /* Handy for quick testing draw (if it's outside bounds). */
+ if (false) {
+ GPU_blend(true);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv((const float[4]){1, 1, 1, 0.5f});
+ float s = 0.5f;
+ immRectf(pos, -s, -s, s, s);
+ immUnbindProgram();
+ GPU_blend(false);
+ }
+
+ if (select) {
+ /* expand for hotspot */
#if 0
- const float size[3] = {
- size_real[0] + margin[0] / 2,
- size_real[1] + margin[1] / 2,
- size_real[2] + margin[2] / 2,
- };
+ const float size[3] = {
+ size_real[0] + margin[0] / 2,
+ size_real[1] + margin[1] / 2,
+ size_real[2] + margin[2] / 2,
+ };
#else
- /* just use same value for now. */
- const float size[3] = {UNPACK3(size_real)};
+ /* just use same value for now. */
+ const float size[3] = {UNPACK3(size_real)};
#endif
-
- if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE) {
- for (int i = ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z;
- i <= ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z;
- i++)
- {
- if (i == ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MID_Y_MID_Z) {
- continue;
- }
- GPU_select_load_id(select_id | i);
- cage3d_draw_box_interaction(
- gz->color, i, size, margin);
- }
- }
- if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
- const int transform_part = ED_GIZMO_CAGE3D_PART_TRANSLATE;
- GPU_select_load_id(select_id | transform_part);
- cage3d_draw_box_interaction(
- gz->color, transform_part, size, margin);
- }
- }
- else {
+ if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE) {
+ for (int i = ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z;
+ i <= ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z;
+ i++) {
+ if (i == ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MID_Y_MID_Z) {
+ continue;
+ }
+ GPU_select_load_id(select_id | i);
+ cage3d_draw_box_interaction(gz->color, i, size, margin);
+ }
+ }
+ if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
+ const int transform_part = ED_GIZMO_CAGE3D_PART_TRANSLATE;
+ GPU_select_load_id(select_id | transform_part);
+ cage3d_draw_box_interaction(gz->color, transform_part, size, margin);
+ }
+ }
+ else {
#if 0
- const rctf _r = {
- .xmin = -size_real[0],
- .ymin = -size_real[1],
- .xmax = size_real[0],
- .ymax = size_real[1],
- };
+ const rctf _r = {
+ .xmin = -size_real[0],
+ .ymin = -size_real[1],
+ .xmax = size_real[0],
+ .ymax = size_real[1],
+ };
#endif
- if (draw_style == ED_GIZMO_CAGE2D_STYLE_BOX) {
- /* corner gizmos */
- GPU_line_width(gz->line_width + 3.0f);
- cage3d_draw_box_corners(size_real, margin, (const float[3]){0, 0, 0});
-
- /* 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);
-
- bool show = false;
- if (gz->highlight_part == ED_GIZMO_CAGE3D_PART_TRANSLATE) {
- /* Only show if we're drawing the center handle
- * otherwise the entire rectangle is the hotspot. */
- if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
- show = true;
- }
- }
- else {
- show = true;
- }
-
- if (show) {
- cage3d_draw_box_interaction(
- gz->color, gz->highlight_part, size_real, margin);
- }
- }
- else if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
- float color[4];
- 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);
-
- /* corner gizmos */
- cage3d_draw_circle_handles(rv3d, matrix_final, size_real, margin, (const float[3]){0, 0, 0}, true, 60);
- cage3d_draw_circle_handles(rv3d, matrix_final, size_real, margin, color, true, 40);
-
- GPU_blend(false);
- GPU_polygon_smooth(false);
- GPU_line_smooth(false);
- }
- else {
- BLI_assert(0);
- }
- }
-
- GPU_line_width(1.0);
- GPU_matrix_pop();
+ if (draw_style == ED_GIZMO_CAGE2D_STYLE_BOX) {
+ /* corner gizmos */
+ GPU_line_width(gz->line_width + 3.0f);
+ cage3d_draw_box_corners(size_real, margin, (const float[3]){0, 0, 0});
+
+ /* 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);
+
+ bool show = false;
+ if (gz->highlight_part == ED_GIZMO_CAGE3D_PART_TRANSLATE) {
+ /* Only show if we're drawing the center handle
+ * otherwise the entire rectangle is the hotspot. */
+ if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
+ show = true;
+ }
+ }
+ else {
+ show = true;
+ }
+
+ if (show) {
+ cage3d_draw_box_interaction(gz->color, gz->highlight_part, size_real, margin);
+ }
+ }
+ else if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
+ float color[4];
+ 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);
+
+ /* corner gizmos */
+ cage3d_draw_circle_handles(
+ rv3d, matrix_final, size_real, margin, (const float[3]){0, 0, 0}, true, 60);
+ cage3d_draw_circle_handles(rv3d, matrix_final, size_real, margin, color, true, 40);
+
+ GPU_blend(false);
+ GPU_polygon_smooth(false);
+ GPU_line_smooth(false);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+
+ GPU_line_width(1.0);
+ GPU_matrix_pop();
}
/**
@@ -411,224 +408,227 @@ 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;
- gizmo_cage3d_draw_intern(rv3d, gz, true, false, select_id);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->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;
- const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
- gizmo_cage3d_draw_intern(rv3d, gz, false, is_highlight, -1);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
+ gizmo_cage3d_draw_intern(rv3d, gz, false, is_highlight, -1);
}
static int gizmo_cage3d_get_cursor(wmGizmo *gz)
{
- if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
- return BC_NSEW_SCROLLCURSOR;
- }
+ if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
+ return BC_NSEW_SCROLLCURSOR;
+ }
- return CURSOR_STD;
+ return CURSOR_STD;
}
typedef struct RectTransformInteraction {
- float orig_mouse[3];
- float orig_matrix_offset[4][4];
- float orig_matrix_final_no_offset[4][4];
+ float orig_mouse[3];
+ float orig_matrix_offset[4][4];
+ float orig_matrix_final_no_offset[4][4];
} RectTransformInteraction;
static void gizmo_cage3d_setup(wmGizmo *gz)
{
- gz->flag |= /* WM_GIZMO_DRAW_MODAL | */ /* TODO */
- WM_GIZMO_DRAW_NO_SCALE;
+ gz->flag |= /* WM_GIZMO_DRAW_MODAL | */ /* TODO */
+ WM_GIZMO_DRAW_NO_SCALE;
}
-static int gizmo_cage3d_invoke(
- bContext *C, wmGizmo *gz, const wmEvent *event)
+static int gizmo_cage3d_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
{
- RectTransformInteraction *data = MEM_callocN(sizeof(RectTransformInteraction), "cage_interaction");
+ RectTransformInteraction *data = MEM_callocN(sizeof(RectTransformInteraction),
+ "cage_interaction");
- copy_m4_m4(data->orig_matrix_offset, gz->matrix_offset);
- gizmo_calc_matrix_final_no_offset(gz, data->orig_matrix_final_no_offset, true);
+ copy_m4_m4(data->orig_matrix_offset, gz->matrix_offset);
+ gizmo_calc_matrix_final_no_offset(gz, data->orig_matrix_final_no_offset, true);
- if (gizmo_window_project_3d(
- C, gz, (const float[2]){UNPACK2(event->mval)}, false, data->orig_mouse) == 0)
- {
- zero_v3(data->orig_mouse);
- }
+ if (gizmo_window_project_3d(
+ C, gz, (const float[2]){UNPACK2(event->mval)}, false, data->orig_mouse) == 0) {
+ zero_v3(data->orig_mouse);
+ }
- gz->interaction_data = data;
+ gz->interaction_data = data;
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
-static int gizmo_cage3d_modal(
- bContext *C, wmGizmo *gz, const wmEvent *event,
- eWM_GizmoFlagTweak UNUSED(tweak_flag))
+static int gizmo_cage3d_modal(bContext *C,
+ wmGizmo *gz,
+ const wmEvent *event,
+ eWM_GizmoFlagTweak UNUSED(tweak_flag))
{
- if (event->type != MOUSEMOVE) {
- return OPERATOR_RUNNING_MODAL;
- }
- /* For transform logic to be manageable we operate in -0.5..0.5 2D space,
- * no matter the size of the rectangle, mouse coords are scaled to unit space.
- * The mouse coords have been projected into the matrix so we don't need to worry about axis alignment.
- *
- * - The cursor offset are multiplied by 'dims'.
- * - Matrix translation is also multiplied by 'dims'.
- */
- RectTransformInteraction *data = gz->interaction_data;
- float point_local[3];
-
- float dims[3];
- RNA_float_get_array(gz->ptr, "dimensions", dims);
-
- {
- float matrix_back[4][4];
- copy_m4_m4(matrix_back, gz->matrix_offset);
- copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
-
- bool ok = gizmo_window_project_3d(
- C, gz, (const float[2]){UNPACK2(event->mval)}, false, point_local);
- copy_m4_m4(gz->matrix_offset, matrix_back);
- if (!ok) {
- return OPERATOR_RUNNING_MODAL;
- }
- }
-
- const int transform_flag = RNA_enum_get(gz->ptr, "transform");
- wmGizmoProperty *gz_prop;
-
- gz_prop = WM_gizmo_target_property_find(gz, "matrix");
- if (gz_prop->type != NULL) {
- WM_gizmo_target_property_float_get_array(gz, gz_prop, &gz->matrix_offset[0][0]);
- }
-
- if (gz->highlight_part == ED_GIZMO_CAGE3D_PART_TRANSLATE) {
- /* do this to prevent clamping from changing size */
- copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
- gz->matrix_offset[3][0] = data->orig_matrix_offset[3][0] + (point_local[0] - data->orig_mouse[0]);
- gz->matrix_offset[3][1] = data->orig_matrix_offset[3][1] + (point_local[1] - data->orig_mouse[1]);
- gz->matrix_offset[3][2] = data->orig_matrix_offset[3][2] + (point_local[2] - data->orig_mouse[2]);
- }
- else if (gz->highlight_part == ED_GIZMO_CAGE3D_PART_ROTATE) {
- /* TODO (if needed) */
- }
- else {
- /* scale */
- copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
- float pivot[3];
- bool constrain_axis[3] = {false};
-
- if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
- gizmo_rect_pivot_from_scale_part(gz->highlight_part, pivot, constrain_axis);
- }
- else {
- zero_v3(pivot);
- }
-
- /* Cursor deltas scaled to (-0.5..0.5). */
- float delta_orig[3], delta_curr[3];
-
- for (int i = 0; i < 3; i++) {
- delta_orig[i] = ((data->orig_mouse[i] - data->orig_matrix_offset[3][i]) / dims[i]) - pivot[i];
- delta_curr[i] = ((point_local[i] - data->orig_matrix_offset[3][i]) / dims[i]) - pivot[i];
- }
-
- float scale[3] = {1.0f, 1.0f, 1.0f};
- for (int i = 0; i < 3; i++) {
- if (constrain_axis[i] == false) {
- if (delta_orig[i] < 0.0f) {
- delta_orig[i] *= -1.0f;
- delta_curr[i] *= -1.0f;
- }
- const int sign = signum_i(scale[i]);
-
- scale[i] = 1.0f + ((delta_curr[i] - delta_orig[i]) / len_v3(data->orig_matrix_offset[i]));
-
- if ((transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_SIGNED) == 0) {
- if (sign != signum_i(scale[i])) {
- scale[i] = 0.0f;
- }
- }
- }
- }
-
- if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM) {
- if (constrain_axis[0] == false && constrain_axis[1] == false) {
- scale[1] = scale[0] = (scale[1] + scale[0]) / 2.0f;
- }
- else if (constrain_axis[0] == false) {
- scale[1] = scale[0];
- }
- else if (constrain_axis[1] == false) {
- scale[0] = scale[1];
- }
- else {
- BLI_assert(0);
- }
- }
-
- /* scale around pivot */
- float matrix_scale[4][4];
- unit_m4(matrix_scale);
-
- mul_v3_fl(matrix_scale[0], scale[0]);
- mul_v3_fl(matrix_scale[1], scale[1]);
- mul_v3_fl(matrix_scale[2], scale[2]);
-
- transform_pivot_set_m4(
- matrix_scale,
- (const float[3]){pivot[0] * dims[0], pivot[1] * dims[1], pivot[2] * dims[2]});
- mul_m4_m4m4(gz->matrix_offset, data->orig_matrix_offset, matrix_scale);
- }
-
- if (gz_prop->type != NULL) {
- WM_gizmo_target_property_float_set_array(C, gz, gz_prop, &gz->matrix_offset[0][0]);
- }
-
- /* tag the region for redraw */
- ED_region_tag_redraw(CTX_wm_region(C));
- WM_event_add_mousemove(C);
-
- return OPERATOR_RUNNING_MODAL;
+ if (event->type != MOUSEMOVE) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+ /* For transform logic to be manageable we operate in -0.5..0.5 2D space,
+ * no matter the size of the rectangle, mouse coords are scaled to unit space.
+ * The mouse coords have been projected into the matrix so we don't need to worry about axis alignment.
+ *
+ * - The cursor offset are multiplied by 'dims'.
+ * - Matrix translation is also multiplied by 'dims'.
+ */
+ RectTransformInteraction *data = gz->interaction_data;
+ float point_local[3];
+
+ float dims[3];
+ RNA_float_get_array(gz->ptr, "dimensions", dims);
+
+ {
+ float matrix_back[4][4];
+ copy_m4_m4(matrix_back, gz->matrix_offset);
+ copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
+
+ bool ok = gizmo_window_project_3d(
+ C, gz, (const float[2]){UNPACK2(event->mval)}, false, point_local);
+ copy_m4_m4(gz->matrix_offset, matrix_back);
+ if (!ok) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+
+ const int transform_flag = RNA_enum_get(gz->ptr, "transform");
+ wmGizmoProperty *gz_prop;
+
+ gz_prop = WM_gizmo_target_property_find(gz, "matrix");
+ if (gz_prop->type != NULL) {
+ WM_gizmo_target_property_float_get_array(gz, gz_prop, &gz->matrix_offset[0][0]);
+ }
+
+ if (gz->highlight_part == ED_GIZMO_CAGE3D_PART_TRANSLATE) {
+ /* do this to prevent clamping from changing size */
+ copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
+ gz->matrix_offset[3][0] = data->orig_matrix_offset[3][0] +
+ (point_local[0] - data->orig_mouse[0]);
+ gz->matrix_offset[3][1] = data->orig_matrix_offset[3][1] +
+ (point_local[1] - data->orig_mouse[1]);
+ gz->matrix_offset[3][2] = data->orig_matrix_offset[3][2] +
+ (point_local[2] - data->orig_mouse[2]);
+ }
+ else if (gz->highlight_part == ED_GIZMO_CAGE3D_PART_ROTATE) {
+ /* TODO (if needed) */
+ }
+ else {
+ /* scale */
+ copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
+ float pivot[3];
+ bool constrain_axis[3] = {false};
+
+ if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
+ gizmo_rect_pivot_from_scale_part(gz->highlight_part, pivot, constrain_axis);
+ }
+ else {
+ zero_v3(pivot);
+ }
+
+ /* Cursor deltas scaled to (-0.5..0.5). */
+ float delta_orig[3], delta_curr[3];
+
+ for (int i = 0; i < 3; i++) {
+ delta_orig[i] = ((data->orig_mouse[i] - data->orig_matrix_offset[3][i]) / dims[i]) -
+ pivot[i];
+ delta_curr[i] = ((point_local[i] - data->orig_matrix_offset[3][i]) / dims[i]) - pivot[i];
+ }
+
+ float scale[3] = {1.0f, 1.0f, 1.0f};
+ for (int i = 0; i < 3; i++) {
+ if (constrain_axis[i] == false) {
+ if (delta_orig[i] < 0.0f) {
+ delta_orig[i] *= -1.0f;
+ delta_curr[i] *= -1.0f;
+ }
+ const int sign = signum_i(scale[i]);
+
+ scale[i] = 1.0f + ((delta_curr[i] - delta_orig[i]) / len_v3(data->orig_matrix_offset[i]));
+
+ if ((transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_SIGNED) == 0) {
+ if (sign != signum_i(scale[i])) {
+ scale[i] = 0.0f;
+ }
+ }
+ }
+ }
+
+ if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM) {
+ if (constrain_axis[0] == false && constrain_axis[1] == false) {
+ scale[1] = scale[0] = (scale[1] + scale[0]) / 2.0f;
+ }
+ else if (constrain_axis[0] == false) {
+ scale[1] = scale[0];
+ }
+ else if (constrain_axis[1] == false) {
+ scale[0] = scale[1];
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+
+ /* scale around pivot */
+ float matrix_scale[4][4];
+ unit_m4(matrix_scale);
+
+ mul_v3_fl(matrix_scale[0], scale[0]);
+ mul_v3_fl(matrix_scale[1], scale[1]);
+ mul_v3_fl(matrix_scale[2], scale[2]);
+
+ transform_pivot_set_m4(
+ matrix_scale,
+ (const float[3]){pivot[0] * dims[0], pivot[1] * dims[1], pivot[2] * dims[2]});
+ mul_m4_m4m4(gz->matrix_offset, data->orig_matrix_offset, matrix_scale);
+ }
+
+ if (gz_prop->type != NULL) {
+ WM_gizmo_target_property_float_set_array(C, gz, gz_prop, &gz->matrix_offset[0][0]);
+ }
+
+ /* tag the region for redraw */
+ ED_region_tag_redraw(CTX_wm_region(C));
+ WM_event_add_mousemove(C);
+
+ return OPERATOR_RUNNING_MODAL;
}
static void gizmo_cage3d_property_update(wmGizmo *gz, wmGizmoProperty *gz_prop)
{
- if (STREQ(gz_prop->type->idname, "matrix")) {
- if (WM_gizmo_target_property_array_length(gz, gz_prop) == 16) {
- WM_gizmo_target_property_float_get_array(gz, gz_prop, &gz->matrix_offset[0][0]);
- }
- else {
- BLI_assert(0);
- }
- }
- else {
- BLI_assert(0);
- }
+ if (STREQ(gz_prop->type->idname, "matrix")) {
+ if (WM_gizmo_target_property_array_length(gz, gz_prop) == 16) {
+ WM_gizmo_target_property_float_get_array(gz, gz_prop, &gz->matrix_offset[0][0]);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
}
static void gizmo_cage3d_exit(bContext *C, wmGizmo *gz, const bool cancel)
{
- RectTransformInteraction *data = gz->interaction_data;
+ RectTransformInteraction *data = gz->interaction_data;
- if (!cancel)
- return;
+ if (!cancel)
+ return;
- wmGizmoProperty *gz_prop;
+ wmGizmoProperty *gz_prop;
- /* reset properties */
- gz_prop = WM_gizmo_target_property_find(gz, "matrix");
- if (gz_prop->type != NULL) {
- WM_gizmo_target_property_float_set_array(C, gz, gz_prop, &data->orig_matrix_offset[0][0]);
- }
+ /* reset properties */
+ gz_prop = WM_gizmo_target_property_find(gz, "matrix");
+ if (gz_prop->type != NULL) {
+ WM_gizmo_target_property_float_set_array(C, gz, gz_prop, &data->orig_matrix_offset[0][0]);
+ }
- copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
+ copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
}
-
/* -------------------------------------------------------------------- */
/** \name Cage Gizmo API
*
@@ -636,51 +636,64 @@ static void gizmo_cage3d_exit(bContext *C, wmGizmo *gz, const bool cancel)
static void GIZMO_GT_cage_3d(wmGizmoType *gzt)
{
- /* identifiers */
- gzt->idname = "GIZMO_GT_cage_3d";
-
- /* api callbacks */
- gzt->draw = gizmo_cage3d_draw;
- gzt->draw_select = gizmo_cage3d_draw_select;
- gzt->setup = gizmo_cage3d_setup;
- gzt->invoke = gizmo_cage3d_invoke;
- gzt->property_update = gizmo_cage3d_property_update;
- gzt->modal = gizmo_cage3d_modal;
- gzt->exit = gizmo_cage3d_exit;
- gzt->cursor_get = gizmo_cage3d_get_cursor;
-
- gzt->struct_size = sizeof(wmGizmo);
-
- /* rna */
- static EnumPropertyItem rna_enum_draw_style[] = {
- {ED_GIZMO_CAGE2D_STYLE_BOX, "BOX", 0, "Box", ""},
- {ED_GIZMO_CAGE2D_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""},
- {0, NULL, 0, NULL, NULL},
- };
- static EnumPropertyItem rna_enum_transform[] = {
- {ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE, "TRANSLATE", 0, "Move", ""},
- {ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE, "SCALE", 0, "Scale", ""},
- {ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM, "SCALE_UNIFORM", 0, "Scale Uniform", ""},
- {0, NULL, 0, NULL, NULL},
- };
- static EnumPropertyItem rna_enum_draw_options[] = {
- {ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE, "XFORM_CENTER_HANDLE", 0, "Center Handle", ""},
- {0, NULL, 0, NULL, NULL},
- };
- static float unit_v3[3] = {1.0f, 1.0f, 1.0f};
- RNA_def_float_vector(gzt->srna, "dimensions", 3, unit_v3, 0, FLT_MAX, "Dimensions", "", 0.0f, FLT_MAX);
- RNA_def_enum_flag(gzt->srna, "transform", rna_enum_transform, 0, "Transform Options", "");
- RNA_def_enum(gzt->srna, "draw_style", rna_enum_draw_style, ED_GIZMO_CAGE2D_STYLE_CIRCLE, "Draw Style", "");
- RNA_def_enum_flag(
- gzt->srna, "draw_options", rna_enum_draw_options,
- ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE, "Draw Options", "");
-
- WM_gizmotype_target_property_def(gzt, "matrix", PROP_FLOAT, 16);
+ /* identifiers */
+ gzt->idname = "GIZMO_GT_cage_3d";
+
+ /* api callbacks */
+ gzt->draw = gizmo_cage3d_draw;
+ gzt->draw_select = gizmo_cage3d_draw_select;
+ gzt->setup = gizmo_cage3d_setup;
+ gzt->invoke = gizmo_cage3d_invoke;
+ gzt->property_update = gizmo_cage3d_property_update;
+ gzt->modal = gizmo_cage3d_modal;
+ gzt->exit = gizmo_cage3d_exit;
+ gzt->cursor_get = gizmo_cage3d_get_cursor;
+
+ gzt->struct_size = sizeof(wmGizmo);
+
+ /* rna */
+ static EnumPropertyItem rna_enum_draw_style[] = {
+ {ED_GIZMO_CAGE2D_STYLE_BOX, "BOX", 0, "Box", ""},
+ {ED_GIZMO_CAGE2D_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+ static EnumPropertyItem rna_enum_transform[] = {
+ {ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE, "TRANSLATE", 0, "Move", ""},
+ {ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE, "SCALE", 0, "Scale", ""},
+ {ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM, "SCALE_UNIFORM", 0, "Scale Uniform", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+ static EnumPropertyItem rna_enum_draw_options[] = {
+ {ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE,
+ "XFORM_CENTER_HANDLE",
+ 0,
+ "Center Handle",
+ ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+ static float unit_v3[3] = {1.0f, 1.0f, 1.0f};
+ RNA_def_float_vector(
+ gzt->srna, "dimensions", 3, unit_v3, 0, FLT_MAX, "Dimensions", "", 0.0f, FLT_MAX);
+ RNA_def_enum_flag(gzt->srna, "transform", rna_enum_transform, 0, "Transform Options", "");
+ RNA_def_enum(gzt->srna,
+ "draw_style",
+ rna_enum_draw_style,
+ ED_GIZMO_CAGE2D_STYLE_CIRCLE,
+ "Draw Style",
+ "");
+ RNA_def_enum_flag(gzt->srna,
+ "draw_options",
+ rna_enum_draw_options,
+ ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE,
+ "Draw Options",
+ "");
+
+ WM_gizmotype_target_property_def(gzt, "matrix", PROP_FLOAT, 16);
}
void ED_gizmotypes_cage_3d(void)
{
- WM_gizmotype_append(GIZMO_GT_cage_3d);
+ WM_gizmotype_append(GIZMO_GT_cage_3d);
}
/** \} */
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 9072ced0bd1..31e30a0dd1a 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c
@@ -38,7 +38,6 @@
#include "BKE_context.h"
-
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
@@ -64,30 +63,30 @@
// #define USE_GIZMO_CUSTOM_DIAL
typedef struct DialInteraction {
- struct {
- float mval[2];
- /* Only for when using properties. */
- float prop_angle;
- } init;
- struct {
- /* Cache the last angle to detect rotations bigger than -/+ PI. */
- eWM_GizmoFlagTweak tweak_flag;
- float angle;
- } prev;
-
- /* Number of full rotations. */
- int rotations;
- bool has_drag;
- float angle_increment;
-
- /* Final output values, used for drawing. */
- struct {
- float angle_ofs;
- float angle_delta;
- } output;
+ struct {
+ float mval[2];
+ /* Only for when using properties. */
+ float prop_angle;
+ } init;
+ struct {
+ /* Cache the last angle to detect rotations bigger than -/+ PI. */
+ eWM_GizmoFlagTweak tweak_flag;
+ float angle;
+ } prev;
+
+ /* Number of full rotations. */
+ int rotations;
+ bool has_drag;
+ float angle_increment;
+
+ /* Final output values, used for drawing. */
+ struct {
+ float angle_ofs;
+ float angle_delta;
+ } output;
} DialInteraction;
-#define DIAL_WIDTH 1.0f
+#define DIAL_WIDTH 1.0f
#define DIAL_RESOLUTION 48
/* Could make option, negative to clip more (don't show when view aligned). */
@@ -95,439 +94,455 @@ typedef struct DialInteraction {
/* -------------------------------------------------------------------- */
-static void dial_geom_draw(
- const float color[4], const float line_width,
- const bool select,
- const float axis_modal_mat[4][4], const float clip_plane[4],
- const float arc_partial_angle, const float arc_inner_factor,
- const int draw_options)
+static void dial_geom_draw(const float color[4],
+ const float line_width,
+ const bool select,
+ const float axis_modal_mat[4][4],
+ const float clip_plane[4],
+ const float arc_partial_angle,
+ const float arc_inner_factor,
+ const int draw_options)
{
#ifdef USE_GIZMO_CUSTOM_DIAL
- UNUSED_VARS(gz, axis_modal_mat, clip_plane);
- wm_gizmo_geometryinfo_draw(&wm_gizmo_geom_data_dial, select, color);
+ UNUSED_VARS(gz, axis_modal_mat, clip_plane);
+ wm_gizmo_geometryinfo_draw(&wm_gizmo_geom_data_dial, select, color);
#else
- const bool filled = (
- (draw_options &
- (select ?
- (ED_GIZMO_DIAL_DRAW_FLAG_FILL | 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);
- immUniform4fv("ClipPlane", clip_plane);
- immUniformMatrix4fv("ModelMatrix", axis_modal_mat);
- glEnable(GL_CLIP_DISTANCE0);
- }
- else {
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- }
-
- immUniformColor4fv(color);
-
- if (filled) {
- imm_draw_circle_fill_2d(pos, 0, 0, 1.0, DIAL_RESOLUTION);
- }
- else {
- if (arc_partial_angle == 0.0f) {
- imm_draw_circle_wire_2d(pos, 0, 0, 1.0, DIAL_RESOLUTION);
- if (arc_inner_factor != 0.0f) {
- imm_draw_circle_wire_2d(pos, 0, 0, arc_inner_factor, DIAL_RESOLUTION);
- }
- }
- else {
- float arc_partial_deg = RAD2DEGF((M_PI * 2) - arc_partial_angle);
- imm_draw_circle_partial_wire_2d(
- pos, 0, 0, 1.0, DIAL_RESOLUTION,
- -arc_partial_deg / 2, arc_partial_deg);
-#if 0
- if (arc_inner_factor != 0.0f) {
- BLI_assert(0);
- }
-#endif
- }
- }
-
- immUnbindProgram();
-
- if (clip_plane) {
- glDisable(GL_CLIP_DISTANCE0);
- }
-
- UNUSED_VARS(select);
+ const bool filled = ((draw_options & (select ? (ED_GIZMO_DIAL_DRAW_FLAG_FILL |
+ 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);
+ immUniform4fv("ClipPlane", clip_plane);
+ immUniformMatrix4fv("ModelMatrix", axis_modal_mat);
+ glEnable(GL_CLIP_DISTANCE0);
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+
+ immUniformColor4fv(color);
+
+ if (filled) {
+ imm_draw_circle_fill_2d(pos, 0, 0, 1.0, DIAL_RESOLUTION);
+ }
+ else {
+ if (arc_partial_angle == 0.0f) {
+ imm_draw_circle_wire_2d(pos, 0, 0, 1.0, DIAL_RESOLUTION);
+ if (arc_inner_factor != 0.0f) {
+ imm_draw_circle_wire_2d(pos, 0, 0, arc_inner_factor, DIAL_RESOLUTION);
+ }
+ }
+ else {
+ float arc_partial_deg = RAD2DEGF((M_PI * 2) - arc_partial_angle);
+ imm_draw_circle_partial_wire_2d(
+ pos, 0, 0, 1.0, DIAL_RESOLUTION, -arc_partial_deg / 2, arc_partial_deg);
+# if 0
+ if (arc_inner_factor != 0.0f) {
+ BLI_assert(0);
+ }
+# endif
+ }
+ }
+
+ immUnbindProgram();
+
+ if (clip_plane) {
+ glDisable(GL_CLIP_DISTANCE0);
+ }
+
+ UNUSED_VARS(select);
#endif
}
/**
* Draws a line from (0, 0, 0) to \a co_outer, at \a angle.
*/
-static void dial_ghostarc_draw_helpline(
- const float angle, const float co_outer[3], const float color[4])
+static void dial_ghostarc_draw_helpline(const float angle,
+ const float co_outer[3],
+ const float color[4])
{
- GPU_matrix_push();
- GPU_matrix_rotate_3f(RAD2DEGF(angle), 0.0f, 0.0f, -1.0f);
+ 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);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformColor4fv(color);
+ immUniformColor4fv(color);
- immBegin(GPU_PRIM_LINE_STRIP, 2);
- immVertex3f(pos, 0.0f, 0, 0.0f);
- immVertex3fv(pos, co_outer);
- immEnd();
+ immBegin(GPU_PRIM_LINE_STRIP, 2);
+ immVertex3f(pos, 0.0f, 0, 0.0f);
+ immVertex3fv(pos, co_outer);
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
- GPU_matrix_pop();
+ GPU_matrix_pop();
}
/**
* Draws segments to indicate the position of each increment.
*/
-static void dial_ghostarc_draw_incremental_angle(
- const float incremental_angle, const float offset)
+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);
+ 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);
- immUniformColor3f(1.0f, 1.0f, 1.0f);
- immBegin(GPU_PRIM_LINES, tot_incr * 2);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
+ immBegin(GPU_PRIM_LINES, tot_incr * 2);
- float v[3] = { 0 };
- for (int i = 0; i < tot_incr; i++) {
- v[0] = sinf(offset + incremental_angle * i);
- v[1] = cosf(offset + incremental_angle * i);
+ float v[3] = {0};
+ for (int i = 0; i < tot_incr; i++) {
+ v[0] = sinf(offset + incremental_angle * i);
+ v[1] = cosf(offset + incremental_angle * i);
- mul_v2_fl(v, DIAL_WIDTH * 1.1f);
- immVertex3fv(pos, v);
+ mul_v2_fl(v, DIAL_WIDTH * 1.1f);
+ immVertex3fv(pos, v);
- mul_v2_fl(v, 1.1f);
- immVertex3fv(pos, v);
- }
+ mul_v2_fl(v, 1.1f);
+ immVertex3fv(pos, v);
+ }
- immEnd();
- immUnbindProgram();
+ immEnd();
+ immUnbindProgram();
}
-static void dial_ghostarc_draw(
- const float angle_ofs, const float angle_delta,
- const float arc_inner_factor, const float color[4])
+static void dial_ghostarc_draw(const float angle_ofs,
+ const float angle_delta,
+ const float arc_inner_factor,
+ const float color[4])
{
- const float width_inner = DIAL_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);
-
- if (arc_inner_factor != 0.0) {
- float color_dark[4] = {0};
- color_dark[3] = color[3] / 2;
- immUniformColor4fv(color_dark);
- imm_draw_disk_partial_fill_2d(
- pos, 0, 0, arc_inner_factor, width_inner, DIAL_RESOLUTION, RAD2DEGF(angle_ofs), RAD2DEGF(M_PI * 2));
- }
-
- immUniformColor4fv(color);
- imm_draw_disk_partial_fill_2d(
- pos, 0, 0, arc_inner_factor, width_inner, DIAL_RESOLUTION, RAD2DEGF(angle_ofs), RAD2DEGF(angle_delta));
- immUnbindProgram();
+ const float width_inner = DIAL_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);
+
+ if (arc_inner_factor != 0.0) {
+ float color_dark[4] = {0};
+ color_dark[3] = color[3] / 2;
+ immUniformColor4fv(color_dark);
+ imm_draw_disk_partial_fill_2d(pos,
+ 0,
+ 0,
+ arc_inner_factor,
+ width_inner,
+ DIAL_RESOLUTION,
+ RAD2DEGF(angle_ofs),
+ RAD2DEGF(M_PI * 2));
+ }
+
+ immUniformColor4fv(color);
+ imm_draw_disk_partial_fill_2d(pos,
+ 0,
+ 0,
+ arc_inner_factor,
+ width_inner,
+ DIAL_RESOLUTION,
+ RAD2DEGF(angle_ofs),
+ RAD2DEGF(angle_delta));
+ immUnbindProgram();
}
-static void dial_ghostarc_get_angles(
- const wmGizmo *gz,
- const wmEvent *event,
- const ARegion *ar,
- float mat[4][4], const float co_outer[3],
- float *r_start, float *r_delta)
+static void dial_ghostarc_get_angles(const wmGizmo *gz,
+ const wmEvent *event,
+ const ARegion *ar,
+ 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};
-
- /* We might need to invert the direction of the angles. */
- float view_vec[3], axis_vec[3];
- ED_view3d_global_to_vector(rv3d, gz->matrix_basis[3], view_vec);
- normalize_v3_v3(axis_vec, gz->matrix_basis[2]);
-
- float proj_outer_rel[3];
- mul_v3_project_m4_v3(proj_outer_rel, mat, co_outer);
- sub_v3_v3(proj_outer_rel, gz->matrix_basis[3]);
-
- float proj_mval_new_rel[3];
- float proj_mval_init_rel[3];
- float dial_plane[4];
-
- 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)) {
- 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)) {
- goto fail;
- }
- sub_v3_v3(proj_mval_new_rel, gz->matrix_basis[3]);
-
- const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
-
- /* Start direction from mouse or set by user. */
- const float *proj_init_rel =
- (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y) ?
- gz->matrix_basis[1] : proj_mval_init_rel;
-
- /* Return angles. */
- const float start = angle_wrap_rad(angle_signed_on_axis_v3v3_v3(proj_outer_rel, proj_init_rel, axis_vec));
- const float delta = angle_wrap_rad(angle_signed_on_axis_v3v3_v3(proj_mval_init_rel, proj_mval_new_rel, axis_vec));
-
- /* Change of sign, we passed the 180 degree threshold. This means we need to add a turn
- * to distinguish between transition from 0 to -1 and -PI to +PI, use comparison with PI/2.
- * Logic taken from #BLI_dial_angle */
- if ((delta * inter->prev.angle < 0.0f) &&
- (fabsf(inter->prev.angle) > (float)M_PI_2))
- {
- if (inter->prev.angle < 0.0f) {
- inter->rotations--;
- }
- else {
- inter->rotations++;
- }
- }
- inter->prev.angle = delta;
-
- const bool wrap_angle = RNA_boolean_get(gz->ptr, "wrap_angle");
- const double delta_final = (double)delta + ((2 * M_PI) * (double)inter->rotations);
- *r_start = start;
- *r_delta = (float)(wrap_angle ? fmod(delta_final, 2 * M_PI) : delta_final);
- return;
-
- /* If we can't project (unlikely). */
+ DialInteraction *inter = gz->interaction_data;
+ const RegionView3D *rv3d = ar->regiondata;
+ const float mval[2] = {event->x - ar->winrct.xmin, event->y - ar->winrct.ymin};
+
+ /* We might need to invert the direction of the angles. */
+ float view_vec[3], axis_vec[3];
+ ED_view3d_global_to_vector(rv3d, gz->matrix_basis[3], view_vec);
+ normalize_v3_v3(axis_vec, gz->matrix_basis[2]);
+
+ float proj_outer_rel[3];
+ mul_v3_project_m4_v3(proj_outer_rel, mat, co_outer);
+ sub_v3_v3(proj_outer_rel, gz->matrix_basis[3]);
+
+ float proj_mval_new_rel[3];
+ float proj_mval_init_rel[3];
+ float dial_plane[4];
+
+ 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)) {
+ 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)) {
+ goto fail;
+ }
+ sub_v3_v3(proj_mval_new_rel, gz->matrix_basis[3]);
+
+ const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
+
+ /* Start direction from mouse or set by user. */
+ const float *proj_init_rel = (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y) ?
+ gz->matrix_basis[1] :
+ proj_mval_init_rel;
+
+ /* Return angles. */
+ const float start = angle_wrap_rad(
+ angle_signed_on_axis_v3v3_v3(proj_outer_rel, proj_init_rel, axis_vec));
+ const float delta = angle_wrap_rad(
+ angle_signed_on_axis_v3v3_v3(proj_mval_init_rel, proj_mval_new_rel, axis_vec));
+
+ /* Change of sign, we passed the 180 degree threshold. This means we need to add a turn
+ * to distinguish between transition from 0 to -1 and -PI to +PI, use comparison with PI/2.
+ * Logic taken from #BLI_dial_angle */
+ if ((delta * inter->prev.angle < 0.0f) && (fabsf(inter->prev.angle) > (float)M_PI_2)) {
+ if (inter->prev.angle < 0.0f) {
+ inter->rotations--;
+ }
+ else {
+ inter->rotations++;
+ }
+ }
+ inter->prev.angle = delta;
+
+ const bool wrap_angle = RNA_boolean_get(gz->ptr, "wrap_angle");
+ const double delta_final = (double)delta + ((2 * M_PI) * (double)inter->rotations);
+ *r_start = start;
+ *r_delta = (float)(wrap_angle ? fmod(delta_final, 2 * M_PI) : delta_final);
+ return;
+
+ /* If we can't project (unlikely). */
fail:
- *r_start = 0.0;
- *r_delta = 0.0;
+ *r_start = 0.0;
+ *r_delta = 0.0;
}
-static void dial_ghostarc_draw_with_helplines(
- const float angle_ofs, const float angle_delta,
- const float arc_inner_factor, const float color_helpline[4], const int draw_options)
+static void dial_ghostarc_draw_with_helplines(const float angle_ofs,
+ const float angle_delta,
+ const float arc_inner_factor,
+ const float color_helpline[4],
+ const int draw_options)
{
- /* 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);
+ /* 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);
}
static void dial_draw_intern(
- const bContext *C, wmGizmo *gz,
- const bool select, const bool highlight, float clip_plane[4])
+ const bContext *C, wmGizmo *gz, const bool select, const bool highlight, float clip_plane[4])
{
- float matrix_final[4][4];
- float color[4];
-
- (void)C;
- BLI_assert(CTX_wm_area(C)->spacetype == SPACE_VIEW3D);
-
- gizmo_color_get(gz, highlight, color);
-
- WM_gizmo_calc_matrix_final(gz, matrix_final);
-
- const float arc_partial_angle = RNA_float_get(gz->ptr, "arc_partial_angle");
- const float arc_inner_factor = RNA_float_get(gz->ptr, "arc_inner_factor");
- int draw_options = RNA_enum_get(gz->ptr, "draw_options");
- float angle_ofs = 0.0f;
- float angle_delta = 0.0f;
- float angle_increment = 0.0f;
-
- if (select) {
- draw_options &= ~ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE;
- }
-
- if (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE &&
- (gz->flag & WM_GIZMO_DRAW_VALUE))
- {
- DialInteraction *inter = gz->interaction_data;
- if (inter) {
- angle_ofs = inter->output.angle_ofs;
- angle_delta = inter->output.angle_delta;
- angle_increment = inter->angle_increment;
- }
- else {
- wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
- if (WM_gizmo_target_property_is_valid(gz_prop)) {
- angle_delta = WM_gizmo_target_property_float_get(gz, gz_prop);
- }
- }
- }
-
- ED_gizmotypes_dial_3d_draw_util(
- gz->matrix_basis, matrix_final, gz->line_width, color, select,
- &(struct Dial3dParams){
- .draw_options = draw_options,
- .angle_ofs = angle_ofs,
- .angle_delta = angle_delta,
- .angle_increment = angle_increment,
- .arc_partial_angle = arc_partial_angle,
- .arc_inner_factor = arc_inner_factor,
- .clip_plane = clip_plane,
- });
+ float matrix_final[4][4];
+ float color[4];
+
+ (void)C;
+ BLI_assert(CTX_wm_area(C)->spacetype == SPACE_VIEW3D);
+
+ gizmo_color_get(gz, highlight, color);
+
+ WM_gizmo_calc_matrix_final(gz, matrix_final);
+
+ const float arc_partial_angle = RNA_float_get(gz->ptr, "arc_partial_angle");
+ const float arc_inner_factor = RNA_float_get(gz->ptr, "arc_inner_factor");
+ int draw_options = RNA_enum_get(gz->ptr, "draw_options");
+ float angle_ofs = 0.0f;
+ float angle_delta = 0.0f;
+ float angle_increment = 0.0f;
+
+ if (select) {
+ draw_options &= ~ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE;
+ }
+
+ if (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE && (gz->flag & WM_GIZMO_DRAW_VALUE)) {
+ DialInteraction *inter = gz->interaction_data;
+ if (inter) {
+ angle_ofs = inter->output.angle_ofs;
+ angle_delta = inter->output.angle_delta;
+ angle_increment = inter->angle_increment;
+ }
+ else {
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ angle_delta = WM_gizmo_target_property_float_get(gz, gz_prop);
+ }
+ }
+ }
+
+ ED_gizmotypes_dial_3d_draw_util(gz->matrix_basis,
+ matrix_final,
+ gz->line_width,
+ color,
+ select,
+ &(struct Dial3dParams){
+ .draw_options = draw_options,
+ .angle_ofs = angle_ofs,
+ .angle_delta = angle_delta,
+ .angle_increment = angle_increment,
+ .arc_partial_angle = arc_partial_angle,
+ .arc_inner_factor = arc_inner_factor,
+ .clip_plane = clip_plane,
+ });
}
static void gizmo_dial_draw_select(const bContext *C, wmGizmo *gz, int select_id)
{
- float clip_plane_buf[4];
- const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
- float *clip_plane = (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_CLIP) ? clip_plane_buf : NULL;
+ float clip_plane_buf[4];
+ const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
+ 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;
+ if (clip_plane) {
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
- copy_v3_v3(clip_plane, rv3d->viewinv[2]);
- clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], gz->matrix_basis[3]);
- clip_plane[3] += DIAL_CLIP_BIAS;
- }
+ copy_v3_v3(clip_plane, rv3d->viewinv[2]);
+ clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], gz->matrix_basis[3]);
+ clip_plane[3] += DIAL_CLIP_BIAS;
+ }
- GPU_select_load_id(select_id);
- dial_draw_intern(C, gz, true, false, clip_plane);
+ GPU_select_load_id(select_id);
+ dial_draw_intern(C, gz, true, false, clip_plane);
- if (clip_plane) {
- glDisable(GL_CLIP_DISTANCE0);
- }
+ if (clip_plane) {
+ glDisable(GL_CLIP_DISTANCE0);
+ }
}
static void gizmo_dial_draw(const bContext *C, wmGizmo *gz)
{
- const bool is_modal = gz->state & WM_GIZMO_STATE_MODAL;
- const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
- float clip_plane_buf[4];
- const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
- float *clip_plane = (!is_modal && (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;
-
- copy_v3_v3(clip_plane, rv3d->viewinv[2]);
- clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], gz->matrix_basis[3]);
- clip_plane[3] += DIAL_CLIP_BIAS;
- }
-
- GPU_blend(true);
- dial_draw_intern(C, gz, false, is_highlight, clip_plane);
- GPU_blend(false);
+ const bool is_modal = gz->state & WM_GIZMO_STATE_MODAL;
+ const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
+ float clip_plane_buf[4];
+ const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
+ float *clip_plane = (!is_modal && (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;
+
+ copy_v3_v3(clip_plane, rv3d->viewinv[2]);
+ clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], gz->matrix_basis[3]);
+ clip_plane[3] += DIAL_CLIP_BIAS;
+ }
+
+ GPU_blend(true);
+ dial_draw_intern(C, gz, false, is_highlight, clip_plane);
+ GPU_blend(false);
}
-static int gizmo_dial_modal(
- bContext *C, wmGizmo *gz, const wmEvent *event,
- eWM_GizmoFlagTweak tweak_flag)
+static int gizmo_dial_modal(bContext *C,
+ wmGizmo *gz,
+ const wmEvent *event,
+ eWM_GizmoFlagTweak tweak_flag)
{
- DialInteraction *inter = gz->interaction_data;
- if ((event->type != MOUSEMOVE) && (inter->prev.tweak_flag == tweak_flag)) {
- return OPERATOR_RUNNING_MODAL;
- }
- /* Coordinate at which the arc drawing will be started. */
- const float co_outer[4] = {0.0f, DIAL_WIDTH, 0.0f};
- float angle_ofs, angle_delta, angle_increment = 0.0f;
-
- dial_ghostarc_get_angles(
- gz, event, CTX_wm_region(C), gz->matrix_basis, co_outer, &angle_ofs, &angle_delta);
-
- if (tweak_flag & WM_GIZMO_TWEAK_SNAP) {
- angle_increment = RNA_float_get(gz->ptr, "incremental_angle");
- angle_delta = (float)roundf((double)angle_delta / angle_increment) * angle_increment;
- }
- if (tweak_flag & WM_GIZMO_TWEAK_PRECISE) {
- angle_increment *= 0.2f;
- angle_delta *= 0.2f;
- }
- if (angle_delta != 0.0f) {
- inter->has_drag = true;
- }
-
- inter->angle_increment = angle_increment;
- inter->output.angle_delta = angle_delta;
- inter->output.angle_ofs = angle_ofs;
-
- /* Set the property for the operator and call its modal function. */
- wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
- if (WM_gizmo_target_property_is_valid(gz_prop)) {
- WM_gizmo_target_property_float_set(C, gz, gz_prop, inter->init.prop_angle + angle_delta);
- }
-
- inter->prev.tweak_flag = tweak_flag;
-
- return OPERATOR_RUNNING_MODAL;
+ DialInteraction *inter = gz->interaction_data;
+ if ((event->type != MOUSEMOVE) && (inter->prev.tweak_flag == tweak_flag)) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+ /* Coordinate at which the arc drawing will be started. */
+ const float co_outer[4] = {0.0f, DIAL_WIDTH, 0.0f};
+ float angle_ofs, angle_delta, angle_increment = 0.0f;
+
+ dial_ghostarc_get_angles(
+ gz, event, CTX_wm_region(C), gz->matrix_basis, co_outer, &angle_ofs, &angle_delta);
+
+ if (tweak_flag & WM_GIZMO_TWEAK_SNAP) {
+ angle_increment = RNA_float_get(gz->ptr, "incremental_angle");
+ angle_delta = (float)roundf((double)angle_delta / angle_increment) * angle_increment;
+ }
+ if (tweak_flag & WM_GIZMO_TWEAK_PRECISE) {
+ angle_increment *= 0.2f;
+ angle_delta *= 0.2f;
+ }
+ if (angle_delta != 0.0f) {
+ inter->has_drag = true;
+ }
+
+ inter->angle_increment = angle_increment;
+ inter->output.angle_delta = angle_delta;
+ inter->output.angle_ofs = angle_ofs;
+
+ /* Set the property for the operator and call its modal function. */
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ WM_gizmo_target_property_float_set(C, gz, gz_prop, inter->init.prop_angle + angle_delta);
+ }
+
+ inter->prev.tweak_flag = tweak_flag;
+
+ return OPERATOR_RUNNING_MODAL;
}
static void gizmo_dial_exit(bContext *C, wmGizmo *gz, const bool cancel)
{
- DialInteraction *inter = gz->interaction_data;
- bool use_reset_value = false;
- float reset_value = 0.0f;
- if (cancel) {
- /* Set the property for the operator and call its modal function. */
- wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
- if (WM_gizmo_target_property_is_valid(gz_prop)) {
- use_reset_value = true;
- reset_value = inter->init.prop_angle;
- }
- }
- else {
- if (inter->has_drag == false) {
- PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "click_value");
- if (RNA_property_is_set(gz->ptr, prop)) {
- use_reset_value = true;
- reset_value = RNA_property_float_get(gz->ptr, prop);
- }
- }
- }
-
- if (use_reset_value) {
- wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
- if (WM_gizmo_target_property_is_valid(gz_prop)) {
- WM_gizmo_target_property_float_set(C, gz, gz_prop, reset_value);
- }
- }
-
+ DialInteraction *inter = gz->interaction_data;
+ bool use_reset_value = false;
+ float reset_value = 0.0f;
+ if (cancel) {
+ /* Set the property for the operator and call its modal function. */
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ use_reset_value = true;
+ reset_value = inter->init.prop_angle;
+ }
+ }
+ else {
+ if (inter->has_drag == false) {
+ PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "click_value");
+ if (RNA_property_is_set(gz->ptr, prop)) {
+ use_reset_value = true;
+ reset_value = RNA_property_float_get(gz->ptr, prop);
+ }
+ }
+ }
+
+ if (use_reset_value) {
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ WM_gizmo_target_property_float_set(C, gz, gz_prop, reset_value);
+ }
+ }
}
-
static void gizmo_dial_setup(wmGizmo *gz)
{
- const float dir_default[3] = {0.0f, 0.0f, 1.0f};
+ const float dir_default[3] = {0.0f, 0.0f, 1.0f};
- /* defaults */
- copy_v3_v3(gz->matrix_basis[2], dir_default);
+ /* defaults */
+ copy_v3_v3(gz->matrix_basis[2], dir_default);
}
-static int gizmo_dial_invoke(
- bContext *UNUSED(C), wmGizmo *gz, const wmEvent *event)
+static int gizmo_dial_invoke(bContext *UNUSED(C), wmGizmo *gz, const wmEvent *event)
{
- DialInteraction *inter = MEM_callocN(sizeof(DialInteraction), __func__);
+ DialInteraction *inter = MEM_callocN(sizeof(DialInteraction), __func__);
- inter->init.mval[0] = event->mval[0];
- inter->init.mval[1] = event->mval[1];
+ inter->init.mval[0] = event->mval[0];
+ inter->init.mval[1] = event->mval[1];
- wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
- if (WM_gizmo_target_property_is_valid(gz_prop)) {
- inter->init.prop_angle = WM_gizmo_target_property_float_get(gz, gz_prop);
- }
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ inter->init.prop_angle = WM_gizmo_target_property_float_get(gz, gz_prop);
+ }
- gz->interaction_data = inter;
+ gz->interaction_data = inter;
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
/* -------------------------------------------------------------------- */
@@ -535,87 +550,115 @@ static int gizmo_dial_invoke(
*
* \{ */
-void ED_gizmotypes_dial_3d_draw_util(
- const float matrix_basis[4][4],
- const float matrix_final[4][4],
- const float line_width,
- const float color[4],
- const bool select,
- struct Dial3dParams *params)
+void ED_gizmotypes_dial_3d_draw_util(const float matrix_basis[4][4],
+ const float matrix_final[4][4],
+ const float line_width,
+ const float color[4],
+ const bool select,
+ struct Dial3dParams *params)
{
- GPU_matrix_push();
- GPU_matrix_mul(matrix_final);
-
- GPU_polygon_smooth(false);
-
- if ((params->draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE) != 0) {
- /* Draw rotation indicator arc first. */
- dial_ghostarc_draw_with_helplines(
- params->angle_ofs, params->angle_delta,
- params->arc_inner_factor, color, params->draw_options);
-
- if ((params->draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR) != 0) {
- dial_ghostarc_draw_with_helplines(
- params->angle_ofs + M_PI, params->angle_delta,
- params->arc_inner_factor, color, params->draw_options);
- }
- }
-
- if (params->angle_increment) {
- dial_ghostarc_draw_incremental_angle(params->angle_increment, params->angle_ofs);
- }
-
- /* Draw actual dial gizmo. */
- dial_geom_draw(
- color, line_width, select, matrix_basis, params->clip_plane,
- params->arc_partial_angle, params->arc_inner_factor, params->draw_options);
-
- GPU_matrix_pop();
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix_final);
+
+ GPU_polygon_smooth(false);
+
+ if ((params->draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE) != 0) {
+ /* Draw rotation indicator arc first. */
+ dial_ghostarc_draw_with_helplines(params->angle_ofs,
+ params->angle_delta,
+ params->arc_inner_factor,
+ color,
+ params->draw_options);
+
+ if ((params->draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR) != 0) {
+ dial_ghostarc_draw_with_helplines(params->angle_ofs + M_PI,
+ params->angle_delta,
+ params->arc_inner_factor,
+ color,
+ params->draw_options);
+ }
+ }
+
+ if (params->angle_increment) {
+ dial_ghostarc_draw_incremental_angle(params->angle_increment, params->angle_ofs);
+ }
+
+ /* Draw actual dial gizmo. */
+ dial_geom_draw(color,
+ line_width,
+ select,
+ matrix_basis,
+ params->clip_plane,
+ params->arc_partial_angle,
+ params->arc_inner_factor,
+ params->draw_options);
+
+ GPU_matrix_pop();
}
static void GIZMO_GT_dial_3d(wmGizmoType *gzt)
{
- /* identifiers */
- gzt->idname = "GIZMO_GT_dial_3d";
-
- /* api callbacks */
- gzt->draw = gizmo_dial_draw;
- gzt->draw_select = gizmo_dial_draw_select;
- gzt->setup = gizmo_dial_setup;
- gzt->invoke = gizmo_dial_invoke;
- gzt->modal = gizmo_dial_modal;
- gzt->exit = gizmo_dial_exit;
-
- gzt->struct_size = sizeof(wmGizmo);
-
- /* rna */
- static EnumPropertyItem rna_enum_draw_options[] = {
- {ED_GIZMO_DIAL_DRAW_FLAG_CLIP, "CLIP", 0, "Clipped", ""},
- {ED_GIZMO_DIAL_DRAW_FLAG_FILL, "FILL", 0, "Filled", ""},
- {ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT, "FILL_SELECT", 0, "Use fill for selection test", ""},
- {ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR, "ANGLE_MIRROR", 0, "Angle Mirror", ""},
- {ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y, "ANGLE_START_Y", 0, "Angle Start Y", ""},
- {ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE, "ANGLE_VALUE", 0, "Show Angle Value", ""},
- {0, NULL, 0, NULL, NULL},
- };
- RNA_def_enum_flag(gzt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
- RNA_def_boolean(gzt->srna, "wrap_angle", true, "Wrap Angle", "");
- RNA_def_float_factor(gzt->srna, "arc_inner_factor", 0.0f, 0.0f, 1.0f, "Arc Inner Factor", "", 0.0f, 1.0f);
- RNA_def_float_factor(gzt->srna, "arc_partial_angle", 0.0f, 0.0f, M_PI * 2, "Show Partial Dial", "", 0.0f, M_PI * 2);
- RNA_def_float_factor(
- gzt->srna, "incremental_angle", SNAP_INCREMENTAL_ANGLE, 0.0f,
- M_PI * 2, "Incremental Angle", "Angle to snap in steps", 0.0f, M_PI * 2);
- RNA_def_float(
- gzt->srna, "click_value", 0.0f, -FLT_MAX, FLT_MAX,
- "Click Value", "Value to use for a single click action",
- -FLT_MAX, FLT_MAX);
-
- WM_gizmotype_target_property_def(gzt, "offset", PROP_FLOAT, 1);
+ /* identifiers */
+ gzt->idname = "GIZMO_GT_dial_3d";
+
+ /* api callbacks */
+ gzt->draw = gizmo_dial_draw;
+ gzt->draw_select = gizmo_dial_draw_select;
+ gzt->setup = gizmo_dial_setup;
+ gzt->invoke = gizmo_dial_invoke;
+ gzt->modal = gizmo_dial_modal;
+ gzt->exit = gizmo_dial_exit;
+
+ gzt->struct_size = sizeof(wmGizmo);
+
+ /* rna */
+ static EnumPropertyItem rna_enum_draw_options[] = {
+ {ED_GIZMO_DIAL_DRAW_FLAG_CLIP, "CLIP", 0, "Clipped", ""},
+ {ED_GIZMO_DIAL_DRAW_FLAG_FILL, "FILL", 0, "Filled", ""},
+ {ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT, "FILL_SELECT", 0, "Use fill for selection test", ""},
+ {ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR, "ANGLE_MIRROR", 0, "Angle Mirror", ""},
+ {ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y, "ANGLE_START_Y", 0, "Angle Start Y", ""},
+ {ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE, "ANGLE_VALUE", 0, "Show Angle Value", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+ RNA_def_enum_flag(gzt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
+ RNA_def_boolean(gzt->srna, "wrap_angle", true, "Wrap Angle", "");
+ RNA_def_float_factor(
+ gzt->srna, "arc_inner_factor", 0.0f, 0.0f, 1.0f, "Arc Inner Factor", "", 0.0f, 1.0f);
+ RNA_def_float_factor(gzt->srna,
+ "arc_partial_angle",
+ 0.0f,
+ 0.0f,
+ M_PI * 2,
+ "Show Partial Dial",
+ "",
+ 0.0f,
+ M_PI * 2);
+ RNA_def_float_factor(gzt->srna,
+ "incremental_angle",
+ SNAP_INCREMENTAL_ANGLE,
+ 0.0f,
+ M_PI * 2,
+ "Incremental Angle",
+ "Angle to snap in steps",
+ 0.0f,
+ M_PI * 2);
+ RNA_def_float(gzt->srna,
+ "click_value",
+ 0.0f,
+ -FLT_MAX,
+ FLT_MAX,
+ "Click Value",
+ "Value to use for a single click action",
+ -FLT_MAX,
+ FLT_MAX);
+
+ WM_gizmotype_target_property_def(gzt, "offset", PROP_FLOAT, 1);
}
void ED_gizmotypes_dial_3d(void)
{
- WM_gizmotype_append(GIZMO_GT_dial_3d);
+ WM_gizmotype_append(GIZMO_GT_dial_3d);
}
/** \} */
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 3870ce984b5..f9ad836b054 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c
@@ -34,7 +34,6 @@
#include "BKE_context.h"
-
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
@@ -59,36 +58,37 @@
#define MVAL_MAX_PX_DIST 12.0f
typedef struct MoveGizmo3D {
- wmGizmo gizmo;
- /* Added to 'matrix_basis' when calculating the matrix. */
- float prop_co[3];
+ wmGizmo gizmo;
+ /* Added to 'matrix_basis' when calculating the matrix. */
+ float prop_co[3];
} MoveGizmo3D;
static void gizmo_move_matrix_basis_get(const wmGizmo *gz, float r_matrix[4][4])
{
- MoveGizmo3D *move = (MoveGizmo3D *)gz;
+ MoveGizmo3D *move = (MoveGizmo3D *)gz;
- copy_m4_m4(r_matrix, move->gizmo.matrix_basis);
- add_v3_v3(r_matrix[3], move->prop_co);
+ copy_m4_m4(r_matrix, move->gizmo.matrix_basis);
+ add_v3_v3(r_matrix[3], move->prop_co);
}
-static int gizmo_move_modal(
- bContext *C, wmGizmo *gz, const wmEvent *event,
- eWM_GizmoFlagTweak tweak_flag);
+static int gizmo_move_modal(bContext *C,
+ wmGizmo *gz,
+ const wmEvent *event,
+ eWM_GizmoFlagTweak tweak_flag);
typedef struct MoveInteraction {
- struct {
- float mval[2];
- /* Only for when using properties. */
- float prop_co[3];
- float matrix_final[4][4];
- } init;
- struct {
- eWM_GizmoFlagTweak tweak_flag;
- } prev;
-
- /* We could have other snap contexts, for now only support 3D view. */
- struct SnapObjectContext *snap_context_v3d;
+ struct {
+ float mval[2];
+ /* Only for when using properties. */
+ float prop_co[3];
+ float matrix_final[4][4];
+ } init;
+ struct {
+ eWM_GizmoFlagTweak tweak_flag;
+ } prev;
+
+ /* We could have other snap contexts, for now only support 3D view. */
+ struct SnapObjectContext *snap_context_v3d;
} MoveInteraction;
@@ -96,321 +96,322 @@ typedef struct MoveInteraction {
/* -------------------------------------------------------------------- */
-static void move_geom_draw(
- const wmGizmo *gz, const float color[4], const bool select, const int draw_options)
+static void move_geom_draw(const wmGizmo *gz,
+ const float color[4],
+ const bool select,
+ const int draw_options)
{
#ifdef USE_GIZMO_CUSTOM_DIAL
- UNUSED_VARS(move3d, col, axis_modal_mat);
- wm_gizmo_geometryinfo_draw(&wm_gizmo_geom_data_move3d, select);
+ UNUSED_VARS(move3d, col, axis_modal_mat);
+ 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 | 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);
-
- immUniformColor4fv(color);
-
- if (draw_style == ED_GIZMO_MOVE_STYLE_RING_2D) {
- if (filled) {
- imm_draw_circle_fill_2d(pos, 0, 0, 1.0f, DIAL_RESOLUTION);
- }
- else {
- imm_draw_circle_wire_2d(pos, 0, 0, 1.0f, DIAL_RESOLUTION);
- }
- }
- else if (draw_style == ED_GIZMO_MOVE_STYLE_CROSS_2D) {
- immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, 1.0f, 1.0f);
- immVertex2f(pos, -1.0f, -1.0f);
-
- immVertex2f(pos, -1.0f, 1.0f);
- immVertex2f(pos, 1.0f, -1.0f);
- immEnd();
- }
- else {
- BLI_assert(0);
- }
-
- immUnbindProgram();
-
- UNUSED_VARS(select);
+ const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
+ const bool filled = ((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);
+
+ immUniformColor4fv(color);
+
+ if (draw_style == ED_GIZMO_MOVE_STYLE_RING_2D) {
+ if (filled) {
+ imm_draw_circle_fill_2d(pos, 0, 0, 1.0f, DIAL_RESOLUTION);
+ }
+ else {
+ imm_draw_circle_wire_2d(pos, 0, 0, 1.0f, DIAL_RESOLUTION);
+ }
+ }
+ else if (draw_style == ED_GIZMO_MOVE_STYLE_CROSS_2D) {
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex2f(pos, 1.0f, 1.0f);
+ immVertex2f(pos, -1.0f, -1.0f);
+
+ immVertex2f(pos, -1.0f, 1.0f);
+ immVertex2f(pos, 1.0f, -1.0f);
+ immEnd();
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ immUnbindProgram();
+
+ UNUSED_VARS(select);
#endif
}
-static void move3d_get_translate(
- const wmGizmo *gz, const wmEvent *event, const ARegion *ar,
- float co_delta[3])
+static void move3d_get_translate(const wmGizmo *gz,
+ const wmEvent *event,
+ const ARegion *ar,
+ float co_delta[3])
{
- MoveInteraction *inter = gz->interaction_data;
- const float mval_delta[2] = {
- event->mval[0] - inter->init.mval[0],
- event->mval[1] - inter->init.mval[1],
- };
-
- RegionView3D *rv3d = ar->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);
-
- float matrix_space_inv[3][3];
- copy_m3_m4(matrix_space_inv, gz->matrix_space);
- invert_m3(matrix_space_inv);
- mul_m3_v3(matrix_space_inv, co_delta);
+ MoveInteraction *inter = gz->interaction_data;
+ const float mval_delta[2] = {
+ event->mval[0] - inter->init.mval[0],
+ event->mval[1] - inter->init.mval[1],
+ };
+
+ RegionView3D *rv3d = ar->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);
+
+ float matrix_space_inv[3][3];
+ copy_m3_m4(matrix_space_inv, gz->matrix_space);
+ invert_m3(matrix_space_inv);
+ mul_m3_v3(matrix_space_inv, co_delta);
}
-static void move3d_draw_intern(
- const bContext *C, wmGizmo *gz,
- const bool select, const bool highlight)
+static void move3d_draw_intern(const bContext *C,
+ wmGizmo *gz,
+ const bool select,
+ const bool highlight)
{
- MoveInteraction *inter = gz->interaction_data;
- const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
- const bool align_view = (draw_options & ED_GIZMO_MOVE_DRAW_FLAG_ALIGN_VIEW) != 0;
- float color[4];
- float matrix_final[4][4];
- float matrix_align[4][4];
-
- gizmo_color_get(gz, highlight, color);
- WM_gizmo_calc_matrix_final(gz, matrix_final);
-
- GPU_matrix_push();
- GPU_matrix_mul(matrix_final);
-
- if (align_view) {
- float matrix_final_unit[4][4];
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- normalize_m4_m4(matrix_final_unit, matrix_final);
- mul_m4_m4m4(matrix_align, rv3d->viewmat, matrix_final_unit);
- zero_v3(matrix_align[3]);
- transpose_m4(matrix_align);
- GPU_matrix_mul(matrix_align);
- }
-
- GPU_blend(true);
- move_geom_draw(gz, color, select, draw_options);
- GPU_blend(false);
- GPU_matrix_pop();
-
- if (gz->interaction_data) {
- GPU_matrix_push();
- GPU_matrix_mul(inter->init.matrix_final);
-
- if (align_view) {
- GPU_matrix_mul(matrix_align);
- }
-
- GPU_blend(true);
- move_geom_draw(gz, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f}, select, draw_options);
- GPU_blend(false);
- GPU_matrix_pop();
- }
+ MoveInteraction *inter = gz->interaction_data;
+ const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
+ const bool align_view = (draw_options & ED_GIZMO_MOVE_DRAW_FLAG_ALIGN_VIEW) != 0;
+ float color[4];
+ float matrix_final[4][4];
+ float matrix_align[4][4];
+
+ gizmo_color_get(gz, highlight, color);
+ WM_gizmo_calc_matrix_final(gz, matrix_final);
+
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix_final);
+
+ if (align_view) {
+ float matrix_final_unit[4][4];
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ normalize_m4_m4(matrix_final_unit, matrix_final);
+ mul_m4_m4m4(matrix_align, rv3d->viewmat, matrix_final_unit);
+ zero_v3(matrix_align[3]);
+ transpose_m4(matrix_align);
+ GPU_matrix_mul(matrix_align);
+ }
+
+ GPU_blend(true);
+ move_geom_draw(gz, color, select, draw_options);
+ GPU_blend(false);
+ GPU_matrix_pop();
+
+ if (gz->interaction_data) {
+ GPU_matrix_push();
+ GPU_matrix_mul(inter->init.matrix_final);
+
+ if (align_view) {
+ GPU_matrix_mul(matrix_align);
+ }
+
+ GPU_blend(true);
+ move_geom_draw(gz, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f}, select, draw_options);
+ GPU_blend(false);
+ GPU_matrix_pop();
+ }
}
static void gizmo_move_draw_select(const bContext *C, wmGizmo *gz, int select_id)
{
- GPU_select_load_id(select_id);
- move3d_draw_intern(C, gz, true, false);
+ GPU_select_load_id(select_id);
+ move3d_draw_intern(C, gz, true, false);
}
static void gizmo_move_draw(const bContext *C, wmGizmo *gz)
{
- const bool is_modal = gz->state & WM_GIZMO_STATE_MODAL;
- const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
+ const bool is_modal = gz->state & WM_GIZMO_STATE_MODAL;
+ const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
- (void)is_modal;
+ (void)is_modal;
- GPU_blend(true);
- move3d_draw_intern(C, gz, false, is_highlight);
- GPU_blend(false);
+ GPU_blend(true);
+ move3d_draw_intern(C, gz, false, is_highlight);
+ GPU_blend(false);
}
-static int gizmo_move_modal(
- bContext *C, wmGizmo *gz, const wmEvent *event,
- eWM_GizmoFlagTweak tweak_flag)
+static int gizmo_move_modal(bContext *C,
+ wmGizmo *gz,
+ const wmEvent *event,
+ eWM_GizmoFlagTweak tweak_flag)
{
- MoveInteraction *inter = gz->interaction_data;
- if ((event->type != MOUSEMOVE) && (inter->prev.tweak_flag == tweak_flag)) {
- return OPERATOR_RUNNING_MODAL;
- }
- MoveGizmo3D *move = (MoveGizmo3D *)gz;
- ARegion *ar = CTX_wm_region(C);
-
- float prop_delta[3];
- if (CTX_wm_area(C)->spacetype == SPACE_VIEW3D) {
- move3d_get_translate(gz, event, ar, prop_delta);
- }
- else {
- float mval_proj_init[2], mval_proj_curr[2];
- if ((gizmo_window_project_2d(
- C, gz, inter->init.mval, 2, false, mval_proj_init) == false) ||
- (gizmo_window_project_2d(
- C, gz, (const float[2]){UNPACK2(event->mval)}, 2, false, mval_proj_curr) == false))
- {
- return OPERATOR_RUNNING_MODAL;
- }
- sub_v2_v2v2(prop_delta, mval_proj_curr, mval_proj_init);
- prop_delta[2] = 0.0f;
- }
-
- if (tweak_flag & WM_GIZMO_TWEAK_PRECISE) {
- mul_v3_fl(prop_delta, 0.1f);
- }
-
- add_v3_v3v3(move->prop_co, inter->init.prop_co, prop_delta);
-
- if (tweak_flag & WM_GIZMO_TWEAK_SNAP) {
- if (inter->snap_context_v3d) {
- float dist_px = MVAL_MAX_PX_DIST * U.pixelsize;
- const float mval_fl[2] = {UNPACK2(event->mval)};
- float co[3];
- if (ED_transform_snap_object_project_view3d(
- inter->snap_context_v3d,
- (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE),
- &(const struct SnapObjectParams){
- .snap_select = SNAP_ALL,
- .use_object_edit_cage = true,
- .use_occlusion_test = true,
- },
- mval_fl, &dist_px,
- co, NULL))
- {
- float matrix_space_inv[4][4];
- invert_m4_m4(matrix_space_inv, gz->matrix_space);
- mul_v3_m4v3(move->prop_co, matrix_space_inv, co);
- }
- }
- }
-
- /* set the property for the operator and call its modal function */
- wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
- if (WM_gizmo_target_property_is_valid(gz_prop)) {
- WM_gizmo_target_property_float_set_array(C, gz, gz_prop, move->prop_co);
- }
- else {
- zero_v3(move->prop_co);
- }
-
- ED_region_tag_redraw(ar);
-
- inter->prev.tweak_flag = tweak_flag;
-
- return OPERATOR_RUNNING_MODAL;
+ MoveInteraction *inter = gz->interaction_data;
+ if ((event->type != MOUSEMOVE) && (inter->prev.tweak_flag == tweak_flag)) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+ MoveGizmo3D *move = (MoveGizmo3D *)gz;
+ ARegion *ar = CTX_wm_region(C);
+
+ float prop_delta[3];
+ if (CTX_wm_area(C)->spacetype == SPACE_VIEW3D) {
+ move3d_get_translate(gz, event, ar, prop_delta);
+ }
+ else {
+ float mval_proj_init[2], mval_proj_curr[2];
+ if ((gizmo_window_project_2d(C, gz, inter->init.mval, 2, false, mval_proj_init) == false) ||
+ (gizmo_window_project_2d(
+ C, gz, (const float[2]){UNPACK2(event->mval)}, 2, false, mval_proj_curr) == false)) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+ sub_v2_v2v2(prop_delta, mval_proj_curr, mval_proj_init);
+ prop_delta[2] = 0.0f;
+ }
+
+ if (tweak_flag & WM_GIZMO_TWEAK_PRECISE) {
+ mul_v3_fl(prop_delta, 0.1f);
+ }
+
+ add_v3_v3v3(move->prop_co, inter->init.prop_co, prop_delta);
+
+ if (tweak_flag & WM_GIZMO_TWEAK_SNAP) {
+ if (inter->snap_context_v3d) {
+ float dist_px = MVAL_MAX_PX_DIST * U.pixelsize;
+ const float mval_fl[2] = {UNPACK2(event->mval)};
+ float co[3];
+ if (ED_transform_snap_object_project_view3d(
+ inter->snap_context_v3d,
+ (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE),
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ .use_object_edit_cage = true,
+ .use_occlusion_test = true,
+ },
+ mval_fl,
+ &dist_px,
+ co,
+ NULL)) {
+ float matrix_space_inv[4][4];
+ invert_m4_m4(matrix_space_inv, gz->matrix_space);
+ mul_v3_m4v3(move->prop_co, matrix_space_inv, co);
+ }
+ }
+ }
+
+ /* set the property for the operator and call its modal function */
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ WM_gizmo_target_property_float_set_array(C, gz, gz_prop, move->prop_co);
+ }
+ else {
+ zero_v3(move->prop_co);
+ }
+
+ ED_region_tag_redraw(ar);
+
+ inter->prev.tweak_flag = tweak_flag;
+
+ return OPERATOR_RUNNING_MODAL;
}
static void gizmo_move_exit(bContext *C, wmGizmo *gz, const bool cancel)
{
- MoveInteraction *inter = gz->interaction_data;
- bool use_reset_value = false;
- const float *reset_value = NULL;
- if (cancel) {
- /* Set the property for the operator and call its modal function. */
- wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
- if (WM_gizmo_target_property_is_valid(gz_prop)) {
- use_reset_value = true;
- reset_value = inter->init.prop_co;
- }
- }
-
- if (use_reset_value) {
- wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
- if (WM_gizmo_target_property_is_valid(gz_prop)) {
- WM_gizmo_target_property_float_set_array(C, gz, gz_prop, reset_value);
- }
- }
-
- if (inter->snap_context_v3d) {
- ED_transform_snap_object_context_destroy(inter->snap_context_v3d);
- inter->snap_context_v3d = NULL;
- }
+ MoveInteraction *inter = gz->interaction_data;
+ bool use_reset_value = false;
+ const float *reset_value = NULL;
+ if (cancel) {
+ /* Set the property for the operator and call its modal function. */
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ use_reset_value = true;
+ reset_value = inter->init.prop_co;
+ }
+ }
+
+ if (use_reset_value) {
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ WM_gizmo_target_property_float_set_array(C, gz, gz_prop, reset_value);
+ }
+ }
+
+ if (inter->snap_context_v3d) {
+ ED_transform_snap_object_context_destroy(inter->snap_context_v3d);
+ inter->snap_context_v3d = NULL;
+ }
}
-static int gizmo_move_invoke(
- bContext *C, wmGizmo *gz, const wmEvent *event)
+static int gizmo_move_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
{
- const bool use_snap = RNA_boolean_get(gz->ptr, "use_snap");
+ const bool use_snap = RNA_boolean_get(gz->ptr, "use_snap");
- MoveInteraction *inter = MEM_callocN(sizeof(MoveInteraction), __func__);
- inter->init.mval[0] = event->mval[0];
- inter->init.mval[1] = event->mval[1];
+ MoveInteraction *inter = MEM_callocN(sizeof(MoveInteraction), __func__);
+ inter->init.mval[0] = event->mval[0];
+ inter->init.mval[1] = event->mval[1];
#if 0
- copy_v3_v3(inter->init.prop_co, move->prop_co);
+ copy_v3_v3(inter->init.prop_co, move->prop_co);
#else
- wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
- if (WM_gizmo_target_property_is_valid(gz_prop)) {
- WM_gizmo_target_property_float_get_array(gz, gz_prop, inter->init.prop_co);
- }
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ WM_gizmo_target_property_float_get_array(gz, gz_prop, inter->init.prop_co);
+ }
#endif
- WM_gizmo_calc_matrix_final(gz, inter->init.matrix_final);
-
- if (use_snap) {
- ScrArea *sa = CTX_wm_area(C);
- if (sa) {
- switch (sa->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_depsgraph(C), 0,
- CTX_wm_region(C), CTX_wm_view3d(C));
- break;
- }
- default:
- /* Not yet supported. */
- BLI_assert(0);
- }
- }
- }
-
- gz->interaction_data = inter;
-
- return OPERATOR_RUNNING_MODAL;
+ WM_gizmo_calc_matrix_final(gz, inter->init.matrix_final);
+
+ if (use_snap) {
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa) {
+ switch (sa->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_depsgraph(C),
+ 0,
+ CTX_wm_region(C),
+ CTX_wm_view3d(C));
+ break;
+ }
+ default:
+ /* Not yet supported. */
+ BLI_assert(0);
+ }
+ }
+ }
+
+ gz->interaction_data = inter;
+
+ return OPERATOR_RUNNING_MODAL;
}
-
-static int gizmo_move_test_select(
- bContext *C, wmGizmo *gz, const int mval[2])
+static int gizmo_move_test_select(bContext *C, wmGizmo *gz, const int mval[2])
{
- float point_local[2];
+ float point_local[2];
- if (gizmo_window_project_2d(
- C, gz, (const float[2]){UNPACK2(mval)}, 2, true, point_local) == false)
- {
- return -1;
- }
+ if (gizmo_window_project_2d(C, gz, (const float[2]){UNPACK2(mval)}, 2, true, point_local) ==
+ false) {
+ return -1;
+ }
- /* The 'gz->scale_final' is already applied when projecting. */
- if (len_squared_v2(point_local) < 1.0f) {
- return 0;
- }
+ /* The 'gz->scale_final' is already applied when projecting. */
+ if (len_squared_v2(point_local) < 1.0f) {
+ return 0;
+ }
- return -1;
+ return -1;
}
static void gizmo_move_property_update(wmGizmo *gz, wmGizmoProperty *gz_prop)
{
- MoveGizmo3D *move = (MoveGizmo3D *)gz;
- if (WM_gizmo_target_property_is_valid(gz_prop)) {
- WM_gizmo_target_property_float_get_array(gz, gz_prop, move->prop_co);
- }
- else {
- zero_v3(move->prop_co);
- }
+ MoveGizmo3D *move = (MoveGizmo3D *)gz;
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ WM_gizmo_target_property_float_get_array(gz, gz_prop, move->prop_co);
+ }
+ else {
+ zero_v3(move->prop_co);
+ }
}
static int gizmo_move_cursor_get(wmGizmo *UNUSED(gz))
{
- return BC_NSEW_SCROLLCURSOR;
+ return BC_NSEW_SCROLLCURSOR;
}
/* -------------------------------------------------------------------- */
@@ -420,45 +421,46 @@ static int gizmo_move_cursor_get(wmGizmo *UNUSED(gz))
static void GIZMO_GT_move_3d(wmGizmoType *gzt)
{
- /* identifiers */
- gzt->idname = "GIZMO_GT_move_3d";
-
- /* api callbacks */
- gzt->draw = gizmo_move_draw;
- gzt->draw_select = gizmo_move_draw_select;
- gzt->test_select = gizmo_move_test_select;
- gzt->matrix_basis_get = gizmo_move_matrix_basis_get;
- gzt->invoke = gizmo_move_invoke;
- gzt->property_update = gizmo_move_property_update;
- gzt->modal = gizmo_move_modal;
- gzt->exit = gizmo_move_exit;
- gzt->cursor_get = gizmo_move_cursor_get;
-
- gzt->struct_size = sizeof(MoveGizmo3D);
-
- /* rna */
- static EnumPropertyItem rna_enum_draw_style[] = {
- {ED_GIZMO_MOVE_STYLE_RING_2D, "RING_2D", 0, "Ring", ""},
- {ED_GIZMO_MOVE_STYLE_CROSS_2D, "CROSS_2D", 0, "Ring", ""},
- {0, NULL, 0, NULL, NULL},
- };
- static EnumPropertyItem rna_enum_draw_options[] = {
- {ED_GIZMO_MOVE_DRAW_FLAG_FILL, "FILL", 0, "Filled", ""},
- {ED_GIZMO_MOVE_DRAW_FLAG_FILL_SELECT, "FILL_SELECT", 0, "Use fill for selection test", ""},
- {ED_GIZMO_MOVE_DRAW_FLAG_ALIGN_VIEW, "ALIGN_VIEW", 0, "Align View", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- RNA_def_enum(gzt->srna, "draw_style", rna_enum_draw_style, ED_GIZMO_MOVE_STYLE_RING_2D, "Draw Style", "");
- RNA_def_enum_flag(gzt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
- RNA_def_boolean(gzt->srna, "use_snap", false, "Use Snap", "");
-
- WM_gizmotype_target_property_def(gzt, "offset", PROP_FLOAT, 3);
+ /* identifiers */
+ gzt->idname = "GIZMO_GT_move_3d";
+
+ /* api callbacks */
+ gzt->draw = gizmo_move_draw;
+ gzt->draw_select = gizmo_move_draw_select;
+ gzt->test_select = gizmo_move_test_select;
+ gzt->matrix_basis_get = gizmo_move_matrix_basis_get;
+ gzt->invoke = gizmo_move_invoke;
+ gzt->property_update = gizmo_move_property_update;
+ gzt->modal = gizmo_move_modal;
+ gzt->exit = gizmo_move_exit;
+ gzt->cursor_get = gizmo_move_cursor_get;
+
+ gzt->struct_size = sizeof(MoveGizmo3D);
+
+ /* rna */
+ static EnumPropertyItem rna_enum_draw_style[] = {
+ {ED_GIZMO_MOVE_STYLE_RING_2D, "RING_2D", 0, "Ring", ""},
+ {ED_GIZMO_MOVE_STYLE_CROSS_2D, "CROSS_2D", 0, "Ring", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+ static EnumPropertyItem rna_enum_draw_options[] = {
+ {ED_GIZMO_MOVE_DRAW_FLAG_FILL, "FILL", 0, "Filled", ""},
+ {ED_GIZMO_MOVE_DRAW_FLAG_FILL_SELECT, "FILL_SELECT", 0, "Use fill for selection test", ""},
+ {ED_GIZMO_MOVE_DRAW_FLAG_ALIGN_VIEW, "ALIGN_VIEW", 0, "Align View", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ RNA_def_enum(
+ gzt->srna, "draw_style", rna_enum_draw_style, ED_GIZMO_MOVE_STYLE_RING_2D, "Draw Style", "");
+ RNA_def_enum_flag(gzt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
+ RNA_def_boolean(gzt->srna, "use_snap", false, "Use Snap", "");
+
+ WM_gizmotype_target_property_def(gzt, "offset", PROP_FLOAT, 3);
}
void ED_gizmotypes_move_3d(void)
{
- WM_gizmotype_append(GIZMO_GT_move_3d);
+ WM_gizmotype_append(GIZMO_GT_move_3d);
}
-/** \} */ // Move Gizmo API
+/** \} */ // Move Gizmo API
diff --git a/source/blender/editors/gizmo_library/gizmo_types/primitive3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/primitive3d_gizmo.c
index 2b13398dc4c..48b2e3348c9 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/primitive3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/primitive3d_gizmo.c
@@ -33,7 +33,6 @@
#include "BKE_context.h"
-
#include "GPU_immediate.h"
#include "GPU_matrix.h"
#include "GPU_select.h"
@@ -51,106 +50,101 @@
#include "../gizmo_library_intern.h"
static float verts_plane[4][3] = {
- {-1, -1, 0},
- { 1, -1, 0},
- { 1, 1, 0},
- {-1, 1, 0},
+ {-1, -1, 0},
+ {1, -1, 0},
+ {1, 1, 0},
+ {-1, 1, 0},
};
-
/* -------------------------------------------------------------------- */
-static void gizmo_primitive_draw_geom(
- const float col_inner[4], const float col_outer[4], const int draw_style)
+static void gizmo_primitive_draw_geom(const float col_inner[4],
+ const float col_outer[4],
+ const int draw_style)
{
- float (*verts)[3];
- uint vert_count = 0;
-
- if (draw_style == ED_GIZMO_PRIMITIVE_STYLE_PLANE) {
- verts = verts_plane;
- vert_count = ARRAY_SIZE(verts_plane);
- }
-
- if (vert_count > 0) {
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- wm_gizmo_vec_draw(col_inner, verts, vert_count, pos, GPU_PRIM_TRI_FAN);
- wm_gizmo_vec_draw(col_outer, verts, vert_count, pos, GPU_PRIM_LINE_LOOP);
- immUnbindProgram();
- }
+ float(*verts)[3];
+ uint vert_count = 0;
+
+ if (draw_style == ED_GIZMO_PRIMITIVE_STYLE_PLANE) {
+ verts = verts_plane;
+ vert_count = ARRAY_SIZE(verts_plane);
+ }
+
+ if (vert_count > 0) {
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ wm_gizmo_vec_draw(col_inner, verts, vert_count, pos, GPU_PRIM_TRI_FAN);
+ wm_gizmo_vec_draw(col_outer, verts, vert_count, pos, GPU_PRIM_LINE_LOOP);
+ immUnbindProgram();
+ }
}
-static void gizmo_primitive_draw_intern(
- wmGizmo *gz, const bool UNUSED(select),
- const bool highlight)
+static void gizmo_primitive_draw_intern(wmGizmo *gz,
+ const bool UNUSED(select),
+ const bool highlight)
{
- float color_inner[4], color_outer[4];
- float matrix_final[4][4];
- const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
+ float color_inner[4], color_outer[4];
+ float matrix_final[4][4];
+ const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
- gizmo_color_get(gz, highlight, color_outer);
- copy_v4_v4(color_inner, color_outer);
- color_inner[3] *= 0.5f;
+ gizmo_color_get(gz, highlight, color_outer);
+ copy_v4_v4(color_inner, color_outer);
+ color_inner[3] *= 0.5f;
- WM_gizmo_calc_matrix_final(gz, matrix_final);
+ WM_gizmo_calc_matrix_final(gz, matrix_final);
- GPU_matrix_push();
- GPU_matrix_mul(matrix_final);
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix_final);
- GPU_blend(true);
- gizmo_primitive_draw_geom(color_inner, color_outer, draw_style);
- GPU_blend(false);
+ GPU_blend(true);
+ gizmo_primitive_draw_geom(color_inner, color_outer, draw_style);
+ GPU_blend(false);
- GPU_matrix_pop();
+ GPU_matrix_pop();
- if (gz->interaction_data) {
- GizmoInteraction *inter = gz->interaction_data;
+ if (gz->interaction_data) {
+ GizmoInteraction *inter = gz->interaction_data;
- copy_v4_fl(color_inner, 0.5f);
- copy_v3_fl(color_outer, 0.5f);
- color_outer[3] = 0.8f;
+ copy_v4_fl(color_inner, 0.5f);
+ copy_v3_fl(color_outer, 0.5f);
+ color_outer[3] = 0.8f;
- GPU_matrix_push();
- GPU_matrix_mul(inter->init_matrix_final);
+ GPU_matrix_push();
+ GPU_matrix_mul(inter->init_matrix_final);
- GPU_blend(true);
- gizmo_primitive_draw_geom(color_inner, color_outer, draw_style);
- GPU_blend(false);
+ GPU_blend(true);
+ gizmo_primitive_draw_geom(color_inner, color_outer, draw_style);
+ GPU_blend(false);
- GPU_matrix_pop();
- }
+ GPU_matrix_pop();
+ }
}
-static void gizmo_primitive_draw_select(
- const bContext *UNUSED(C), wmGizmo *gz,
- int select_id)
+static void gizmo_primitive_draw_select(const bContext *UNUSED(C), wmGizmo *gz, int select_id)
{
- GPU_select_load_id(select_id);
- gizmo_primitive_draw_intern(gz, true, false);
+ GPU_select_load_id(select_id);
+ gizmo_primitive_draw_intern(gz, true, false);
}
static void gizmo_primitive_draw(const bContext *UNUSED(C), wmGizmo *gz)
{
- gizmo_primitive_draw_intern(
- gz, false,
- (gz->state & WM_GIZMO_STATE_HIGHLIGHT));
+ gizmo_primitive_draw_intern(gz, false, (gz->state & WM_GIZMO_STATE_HIGHLIGHT));
}
static void gizmo_primitive_setup(wmGizmo *gz)
{
- gz->flag |= WM_GIZMO_DRAW_MODAL;
+ gz->flag |= WM_GIZMO_DRAW_MODAL;
}
-static int gizmo_primitive_invoke(
- bContext *UNUSED(C), wmGizmo *gz, const wmEvent *UNUSED(event))
+static int gizmo_primitive_invoke(bContext *UNUSED(C), wmGizmo *gz, const wmEvent *UNUSED(event))
{
- GizmoInteraction *inter = MEM_callocN(sizeof(GizmoInteraction), __func__);
+ GizmoInteraction *inter = MEM_callocN(sizeof(GizmoInteraction), __func__);
- WM_gizmo_calc_matrix_final(gz, inter->init_matrix_final);
+ WM_gizmo_calc_matrix_final(gz, inter->init_matrix_final);
- gz->interaction_data = inter;
+ gz->interaction_data = inter;
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
/* -------------------------------------------------------------------- */
@@ -160,27 +154,32 @@ static int gizmo_primitive_invoke(
static void GIZMO_GT_primitive_3d(wmGizmoType *gzt)
{
- /* identifiers */
- gzt->idname = "GIZMO_GT_primitive_3d";
-
- /* api callbacks */
- gzt->draw = gizmo_primitive_draw;
- gzt->draw_select = gizmo_primitive_draw_select;
- gzt->setup = gizmo_primitive_setup;
- gzt->invoke = gizmo_primitive_invoke;
-
- gzt->struct_size = sizeof(wmGizmo);
-
- static EnumPropertyItem rna_enum_draw_style[] = {
- {ED_GIZMO_PRIMITIVE_STYLE_PLANE, "PLANE", 0, "Plane", ""},
- {0, NULL, 0, NULL, NULL},
- };
- RNA_def_enum(gzt->srna, "draw_style", rna_enum_draw_style, ED_GIZMO_PRIMITIVE_STYLE_PLANE, "Draw Style", "");
+ /* identifiers */
+ gzt->idname = "GIZMO_GT_primitive_3d";
+
+ /* api callbacks */
+ gzt->draw = gizmo_primitive_draw;
+ gzt->draw_select = gizmo_primitive_draw_select;
+ gzt->setup = gizmo_primitive_setup;
+ gzt->invoke = gizmo_primitive_invoke;
+
+ gzt->struct_size = sizeof(wmGizmo);
+
+ static EnumPropertyItem rna_enum_draw_style[] = {
+ {ED_GIZMO_PRIMITIVE_STYLE_PLANE, "PLANE", 0, "Plane", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+ RNA_def_enum(gzt->srna,
+ "draw_style",
+ rna_enum_draw_style,
+ ED_GIZMO_PRIMITIVE_STYLE_PLANE,
+ "Draw Style",
+ "");
}
void ED_gizmotypes_primitive_3d(void)
{
- WM_gizmotype_append(GIZMO_GT_primitive_3d);
+ WM_gizmotype_append(GIZMO_GT_primitive_3d);
}
/** \} */
diff --git a/source/blender/editors/gizmo_library/gizmo_types/value2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/value2d_gizmo.c
index 9854b62dade..059d3acbd9c 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/value2d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/value2d_gizmo.c
@@ -55,110 +55,108 @@
* \{ */
typedef struct ValueInteraction {
- struct {
- float mval[2];
- float prop_value;
- } init;
- struct {
- float prop_value;
- eWM_GizmoFlagTweak tweak_flag;
- } prev;
- float range[2];
+ struct {
+ float mval[2];
+ float prop_value;
+ } init;
+ struct {
+ float prop_value;
+ eWM_GizmoFlagTweak tweak_flag;
+ } prev;
+ float range[2];
} ValueInteraction;
static void gizmo_value_draw(const bContext *UNUSED(C), wmGizmo *UNUSED(gz))
{
- /* pass */
+ /* pass */
}
-static int gizmo_value_modal(
- bContext *C, wmGizmo *gz, const wmEvent *event,
- eWM_GizmoFlagTweak tweak_flag)
+static int gizmo_value_modal(bContext *C,
+ wmGizmo *gz,
+ const wmEvent *event,
+ eWM_GizmoFlagTweak tweak_flag)
{
- ValueInteraction *inter = gz->interaction_data;
- if ((event->type != MOUSEMOVE) && (inter->prev.tweak_flag == tweak_flag)) {
- return OPERATOR_RUNNING_MODAL;
- }
- ARegion *ar = CTX_wm_region(C);
- const float value_scale = 4.0f; /* Could be option. */
- const float value_range = inter->range[1] - inter->range[0];
- float value_delta = (
- inter->init.prop_value +
- (((event->mval[0] - inter->init.mval[0]) / ar->winx) * value_range)) * value_scale;
-
-
- if (tweak_flag & WM_GIZMO_TWEAK_SNAP) {
- const double snap = 0.1;
- value_delta = (float)roundf((double)value_delta / snap) * snap;
-
- }
- if (tweak_flag & WM_GIZMO_TWEAK_PRECISE) {
- value_delta *= 0.1f;
- }
- const float value_final = inter->init.prop_value + value_delta;
-
- if (value_final != inter->prev.prop_value) {
- /* set the property for the operator and call its modal function */
- wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
- if (WM_gizmo_target_property_is_valid(gz_prop)) {
- WM_gizmo_target_property_float_set(C, gz, gz_prop, value_final);
- }
-
- {
- ScrArea *sa = CTX_wm_area(C);
- char str[64];
- SNPRINTF(str, "%.4f", value_final);
- ED_area_status_text(sa, str);
- }
- }
-
- inter->prev.prop_value = value_final;
- inter->prev.tweak_flag = tweak_flag;
-
- return OPERATOR_RUNNING_MODAL;
+ ValueInteraction *inter = gz->interaction_data;
+ if ((event->type != MOUSEMOVE) && (inter->prev.tweak_flag == tweak_flag)) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+ ARegion *ar = CTX_wm_region(C);
+ const float value_scale = 4.0f; /* Could be option. */
+ const float value_range = inter->range[1] - inter->range[0];
+ float value_delta = (inter->init.prop_value +
+ (((event->mval[0] - inter->init.mval[0]) / ar->winx) * value_range)) *
+ value_scale;
+
+ if (tweak_flag & WM_GIZMO_TWEAK_SNAP) {
+ const double snap = 0.1;
+ value_delta = (float)roundf((double)value_delta / snap) * snap;
+ }
+ if (tweak_flag & WM_GIZMO_TWEAK_PRECISE) {
+ value_delta *= 0.1f;
+ }
+ const float value_final = inter->init.prop_value + value_delta;
+
+ if (value_final != inter->prev.prop_value) {
+ /* set the property for the operator and call its modal function */
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ WM_gizmo_target_property_float_set(C, gz, gz_prop, value_final);
+ }
+
+ {
+ ScrArea *sa = CTX_wm_area(C);
+ char str[64];
+ SNPRINTF(str, "%.4f", value_final);
+ ED_area_status_text(sa, str);
+ }
+ }
+
+ inter->prev.prop_value = value_final;
+ inter->prev.tweak_flag = tweak_flag;
+
+ return OPERATOR_RUNNING_MODAL;
}
-
-static int gizmo_value_invoke(
- bContext *UNUSED(C), wmGizmo *gz, const wmEvent *event)
+static int gizmo_value_invoke(bContext *UNUSED(C), wmGizmo *gz, const wmEvent *event)
{
- ValueInteraction *inter = MEM_callocN(sizeof(ValueInteraction), __func__);
+ ValueInteraction *inter = MEM_callocN(sizeof(ValueInteraction), __func__);
- inter->init.mval[0] = event->mval[0];
- inter->init.mval[1] = event->mval[1];
- inter->prev.prop_value = -FLT_MAX;
+ inter->init.mval[0] = event->mval[0];
+ inter->init.mval[1] = event->mval[1];
+ inter->prev.prop_value = -FLT_MAX;
- wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
- if (WM_gizmo_target_property_is_valid(gz_prop)) {
- inter->init.prop_value = WM_gizmo_target_property_float_get(gz, gz_prop);
- if (!WM_gizmo_target_property_float_range_get(gz, gz_prop, inter->range)) {
- inter->range[0] = 0.0f;
- inter->range[1] = 1.0f;
- }
- }
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ inter->init.prop_value = WM_gizmo_target_property_float_get(gz, gz_prop);
+ if (!WM_gizmo_target_property_float_range_get(gz, gz_prop, inter->range)) {
+ inter->range[0] = 0.0f;
+ inter->range[1] = 1.0f;
+ }
+ }
- gz->interaction_data = inter;
+ gz->interaction_data = inter;
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static void gizmo_value_exit(bContext *C, wmGizmo *gz, const bool cancel)
{
- ScrArea *sa = CTX_wm_area(C);
- ED_area_status_text(sa, NULL);
- if (cancel) {
- ValueInteraction *inter = gz->interaction_data;
- wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
- if (WM_gizmo_target_property_is_valid(gz_prop)) {
- WM_gizmo_target_property_float_set(C, gz, gz_prop, inter->init.prop_value);
- }
- }
+ ScrArea *sa = CTX_wm_area(C);
+ ED_area_status_text(sa, NULL);
+ if (cancel) {
+ ValueInteraction *inter = gz->interaction_data;
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ WM_gizmo_target_property_float_set(C, gz, gz_prop, inter->init.prop_value);
+ }
+ }
}
-static int gizmo_value_test_select(
- bContext *UNUSED(C), wmGizmo *UNUSED(gz), const int UNUSED(mval[2]))
+static int gizmo_value_test_select(bContext *UNUSED(C),
+ wmGizmo *UNUSED(gz),
+ const int UNUSED(mval[2]))
{
- return 0;
+ return 0;
}
/** \} */
@@ -170,25 +168,25 @@ static int gizmo_value_test_select(
static void GIZMO_GT_value_2d(wmGizmoType *gzt)
{
- /* identifiers */
- gzt->idname = "GIZMO_GT_value_2d";
+ /* identifiers */
+ gzt->idname = "GIZMO_GT_value_2d";
- /* api callbacks */
- gzt->draw = gizmo_value_draw;
- gzt->invoke = gizmo_value_invoke;
- gzt->exit = gizmo_value_exit;
- gzt->modal = gizmo_value_modal;
- gzt->test_select = gizmo_value_test_select;
+ /* api callbacks */
+ gzt->draw = gizmo_value_draw;
+ gzt->invoke = gizmo_value_invoke;
+ gzt->exit = gizmo_value_exit;
+ gzt->modal = gizmo_value_modal;
+ gzt->test_select = gizmo_value_test_select;
- gzt->struct_size = sizeof(wmGizmo);
+ gzt->struct_size = sizeof(wmGizmo);
- WM_gizmotype_target_property_def(gzt, "offset", PROP_FLOAT, 1);
- /* Options: relative / absolute */
+ WM_gizmotype_target_property_def(gzt, "offset", PROP_FLOAT, 1);
+ /* Options: relative / absolute */
}
void ED_gizmotypes_value_2d(void)
{
- WM_gizmotype_append(GIZMO_GT_value_2d);
+ WM_gizmotype_append(GIZMO_GT_value_2d);
}
/** \} */
diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt
index fa91ffd1e72..5573c88c710 100644
--- a/source/blender/editors/gpencil/CMakeLists.txt
+++ b/source/blender/editors/gpencil/CMakeLists.txt
@@ -16,58 +16,58 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenfont
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../depsgraph
- ../../imbuf
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenfont
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../depsgraph
+ ../../imbuf
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- annotate_draw.c
- annotate_paint.c
- drawgpencil.c
- editaction_gpencil.c
- gpencil_add_monkey.c
- gpencil_add_stroke.c
- gpencil_armature.c
- gpencil_brush.c
- gpencil_convert.c
- gpencil_data.c
- gpencil_edit.c
- gpencil_fill.c
- gpencil_interpolate.c
- gpencil_merge.c
- gpencil_ops.c
- gpencil_ops_versioning.c
- gpencil_paint.c
- gpencil_primitive.c
- gpencil_select.c
- gpencil_undo.c
- gpencil_utils.c
+ annotate_draw.c
+ annotate_paint.c
+ drawgpencil.c
+ editaction_gpencil.c
+ gpencil_add_monkey.c
+ gpencil_add_stroke.c
+ gpencil_armature.c
+ gpencil_brush.c
+ gpencil_convert.c
+ gpencil_data.c
+ gpencil_edit.c
+ gpencil_fill.c
+ gpencil_interpolate.c
+ gpencil_merge.c
+ gpencil_ops.c
+ gpencil_ops_versioning.c
+ gpencil_paint.c
+ gpencil_primitive.c
+ gpencil_select.c
+ gpencil_undo.c
+ gpencil_utils.c
- gpencil_intern.h
+ gpencil_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
+ bf_blenkernel
+ bf_blenlib
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/gpencil/annotate_draw.c b/source/blender/editors/gpencil/annotate_draw.c
index 2a7f9a715ad..a7fa51350ba 100644
--- a/source/blender/editors/gpencil/annotate_draw.c
+++ b/source/blender/editors/gpencil/annotate_draw.c
@@ -21,7 +21,6 @@
* \ingroup edgpencil
*/
-
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -73,418 +72,436 @@
/* ----- General Defines ------ */
/* flags for sflag */
typedef enum eDrawStrokeFlags {
- /** don't draw status info */
- GP_DRAWDATA_NOSTATUS = (1 << 0),
- /** only draw 3d-strokes */
- GP_DRAWDATA_ONLY3D = (1 << 1),
- /** only draw 'canvas' strokes */
- GP_DRAWDATA_ONLYV2D = (1 << 2),
- /** only draw 'image' strokes */
- GP_DRAWDATA_ONLYI2D = (1 << 3),
- /** special hack for drawing strokes in Image Editor (weird coordinates) */
- GP_DRAWDATA_IEDITHACK = (1 << 4),
- /** don't draw xray in 3D view (which is default) */
- GP_DRAWDATA_NO_XRAY = (1 << 5),
- /** no onionskins should be drawn (for animation playback) */
- GP_DRAWDATA_NO_ONIONS = (1 << 6),
+ /** don't draw status info */
+ GP_DRAWDATA_NOSTATUS = (1 << 0),
+ /** only draw 3d-strokes */
+ GP_DRAWDATA_ONLY3D = (1 << 1),
+ /** only draw 'canvas' strokes */
+ GP_DRAWDATA_ONLYV2D = (1 << 2),
+ /** only draw 'image' strokes */
+ GP_DRAWDATA_ONLYI2D = (1 << 3),
+ /** special hack for drawing strokes in Image Editor (weird coordinates) */
+ GP_DRAWDATA_IEDITHACK = (1 << 4),
+ /** don't draw xray in 3D view (which is default) */
+ GP_DRAWDATA_NO_XRAY = (1 << 5),
+ /** no onionskins should be drawn (for animation playback) */
+ GP_DRAWDATA_NO_ONIONS = (1 << 6),
} eDrawStrokeFlags;
-
/* ----- Tool Buffer Drawing ------ */
/* draw stroke defined in buffer (simple ogl lines/points for now, as dotted lines) */
-static void gp_draw_stroke_buffer(
- const tGPspoint *points, int totpoints, short thickness,
- short dflag, short sflag, float ink[4])
+static void gp_draw_stroke_buffer(const tGPspoint *points,
+ int totpoints,
+ short thickness,
+ short dflag,
+ short sflag,
+ float ink[4])
{
- int draw_points = 0;
-
- /* error checking */
- if ((points == NULL) || (totpoints <= 0))
- return;
-
- /* check if buffer can be drawn */
- if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D))
- return;
-
- if (sflag & GP_STROKE_ERASER) {
- /* don't draw stroke at all! */
- return;
- }
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- const tGPspoint *pt = points;
-
- 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);
- immVertex2fv(pos, &pt->x);
- }
- else {
- float oldpressure = points[0].pressure;
-
- /* draw stroke curve */
- GPU_line_width(max_ff(oldpressure * thickness, 1.0));
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3fvAlpha(ink, ink[3]);
-
- immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints);
-
- for (int i = 0; i < totpoints; i++, pt++) {
- /* 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) {
- immVertex2fv(pos, &(pt - 1)->x);
- }
-
- immEnd();
- draw_points = 0;
-
- 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) {
- immVertex2fv(pos, &(pt - 1)->x);
- draw_points++;
- }
-
- oldpressure = pt->pressure; /* reset our threshold */
- }
-
- /* now the point we want */
- immVertex2fv(pos, &pt->x);
- draw_points++;
- }
- /* need to have 2 points to avoid immEnd assert error */
- if (draw_points < 2) {
- immVertex2fv(pos, &(pt - 1)->x);
- }
- }
-
- immEnd();
- immUnbindProgram();
+ int draw_points = 0;
+
+ /* error checking */
+ if ((points == NULL) || (totpoints <= 0))
+ return;
+
+ /* check if buffer can be drawn */
+ if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D))
+ return;
+
+ if (sflag & GP_STROKE_ERASER) {
+ /* don't draw stroke at all! */
+ return;
+ }
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ const tGPspoint *pt = points;
+
+ 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);
+ immVertex2fv(pos, &pt->x);
+ }
+ else {
+ float oldpressure = points[0].pressure;
+
+ /* draw stroke curve */
+ GPU_line_width(max_ff(oldpressure * thickness, 1.0));
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fvAlpha(ink, ink[3]);
+
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints);
+
+ for (int i = 0; i < totpoints; i++, pt++) {
+ /* 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) {
+ immVertex2fv(pos, &(pt - 1)->x);
+ }
+
+ immEnd();
+ draw_points = 0;
+
+ 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) {
+ immVertex2fv(pos, &(pt - 1)->x);
+ draw_points++;
+ }
+
+ oldpressure = pt->pressure; /* reset our threshold */
+ }
+
+ /* now the point we want */
+ immVertex2fv(pos, &pt->x);
+ draw_points++;
+ }
+ /* need to have 2 points to avoid immEnd assert error */
+ if (draw_points < 2) {
+ immVertex2fv(pos, &(pt - 1)->x);
+ }
+ }
+
+ immEnd();
+ immUnbindProgram();
}
/* --------- 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])
+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;
- }
+ 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;
+ }
}
/* ----- 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 ink[4])
+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 ink[4])
{
- const bGPDspoint *pt = points;
+ const bGPDspoint *pt = points;
- /* get final position using parent matrix */
- float fpt[3];
- copy_v3_v3(fpt, &pt->x);
+ /* get final position using parent matrix */
+ float fpt[3];
+ copy_v3_v3(fpt, &pt->x);
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ 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);
+ 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);
- }
+ /* 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);
+ }
- /* set color */
- immUniformColor3fvAlpha(ink, ink[3]);
+ /* set color */
+ immUniformColor3fvAlpha(ink, ink[3]);
- /* set point thickness (since there's only one of these) */
- immUniform1f("size", (float)(thickness + 2) * pt->pressure);
+ /* 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();
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex3fv(pos, fpt);
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
}
/* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */
-static void gp_draw_stroke_3d(
- const bGPDspoint *points, int totpoints, short thickness,
- short UNUSED(sflag), const float ink[4], bool cyclic)
+static void gp_draw_stroke_3d(const bGPDspoint *points,
+ int totpoints,
+ short thickness,
+ short UNUSED(sflag),
+ const float ink[4],
+ bool cyclic)
{
- float curpressure = points[0].pressure;
- float cyclic_fpt[3];
- int draw_points = 0;
-
- /* if cyclic needs one vertex more */
- int cyclic_add = 0;
- if (cyclic) {
- cyclic_add++;
- }
-
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformColor3fvAlpha(ink, ink[3]);
-
- /* draw stroke curve */
- GPU_line_width(max_ff(curpressure * thickness, 1.0f));
- immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints + cyclic_add);
- const bGPDspoint *pt = points;
- for (int i = 0; i < totpoints; i++, pt++) {
- /* 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)
- * Note: we want more visible levels of pressures when thickness is bigger.
- */
- if (fabsf(pt->pressure - curpressure) > 0.2f / (float)thickness) {
- /* if the pressure changes before get at least 2 vertices,
- * need to repeat last point to avoid assert in immEnd() */
- if (draw_points < 2) {
- const bGPDspoint *pt2 = pt - 1;
- immVertex3fv(pos, &pt2->x);
- }
- immEnd();
- draw_points = 0;
-
- curpressure = pt->pressure;
- GPU_line_width(max_ff(curpressure * thickness, 1.0f));
- immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints - i + 1 + cyclic_add);
-
- /* need to roll-back one point to ensure that there are no gaps in the stroke */
- if (i != 0) {
- const bGPDspoint *pt2 = pt - 1;
- immVertex3fv(pos, &pt2->x);
- draw_points++;
- }
- }
-
- /* now the point we want */
- immVertex3fv(pos, &pt->x);
- draw_points++;
-
- if (cyclic && i == 0) {
- /* save first point to use in cyclic */
- copy_v3_v3(cyclic_fpt, &pt->x);
- }
- }
-
- if (cyclic) {
- /* draw line to first point to complete the cycle */
- immVertex3fv(pos, cyclic_fpt);
- draw_points++;
- }
-
- /* if less of two points, need to repeat last point to avoid assert in immEnd() */
- if (draw_points < 2) {
- const bGPDspoint *pt2 = pt - 1;
- immVertex3fv(pos, &pt2->x);
- }
-
- immEnd();
- immUnbindProgram();
+ float curpressure = points[0].pressure;
+ float cyclic_fpt[3];
+ int draw_points = 0;
+
+ /* if cyclic needs one vertex more */
+ int cyclic_add = 0;
+ if (cyclic) {
+ cyclic_add++;
+ }
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3fvAlpha(ink, ink[3]);
+
+ /* draw stroke curve */
+ GPU_line_width(max_ff(curpressure * thickness, 1.0f));
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints + cyclic_add);
+ const bGPDspoint *pt = points;
+ for (int i = 0; i < totpoints; i++, pt++) {
+ /* 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)
+ * Note: we want more visible levels of pressures when thickness is bigger.
+ */
+ if (fabsf(pt->pressure - curpressure) > 0.2f / (float)thickness) {
+ /* if the pressure changes before get at least 2 vertices,
+ * need to repeat last point to avoid assert in immEnd() */
+ if (draw_points < 2) {
+ const bGPDspoint *pt2 = pt - 1;
+ immVertex3fv(pos, &pt2->x);
+ }
+ immEnd();
+ draw_points = 0;
+
+ curpressure = pt->pressure;
+ GPU_line_width(max_ff(curpressure * thickness, 1.0f));
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints - i + 1 + cyclic_add);
+
+ /* need to roll-back one point to ensure that there are no gaps in the stroke */
+ if (i != 0) {
+ const bGPDspoint *pt2 = pt - 1;
+ immVertex3fv(pos, &pt2->x);
+ draw_points++;
+ }
+ }
+
+ /* now the point we want */
+ immVertex3fv(pos, &pt->x);
+ draw_points++;
+
+ if (cyclic && i == 0) {
+ /* save first point to use in cyclic */
+ copy_v3_v3(cyclic_fpt, &pt->x);
+ }
+ }
+
+ if (cyclic) {
+ /* draw line to first point to complete the cycle */
+ immVertex3fv(pos, cyclic_fpt);
+ draw_points++;
+ }
+
+ /* if less of two points, need to repeat last point to avoid assert in immEnd() */
+ if (draw_points < 2) {
+ const bGPDspoint *pt2 = pt - 1;
+ immVertex3fv(pos, &pt2->x);
+ }
+
+ immEnd();
+ 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,
- int offsx, int offsy, int winx, int winy, const float ink[4])
+static void gp_draw_stroke_2d(const bGPDspoint *points,
+ int totpoints,
+ short thickness_s,
+ short dflag,
+ short sflag,
+ int offsx,
+ int offsy,
+ int winx,
+ 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;
- }
-
- /* 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);
-
- 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 */
- gp_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). */
- gp_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);
- }
-
- /* 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(pos, t0);
- immVertex2fv(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);
-
- /* 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);
- }
-
- /* 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();
- }
+ /* 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;
+ }
+
+ /* 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);
+
+ 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 */
+ gp_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). */
+ gp_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);
+ }
+
+ /* 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(pos, t0);
+ immVertex2fv(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);
+
+ /* 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);
+ }
+
+ /* 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 ------ */
@@ -492,484 +509,507 @@ static void gp_draw_stroke_2d(
/* Helper for doing all the checks on whether a stroke can be drawn */
static bool gp_can_draw_stroke(const bGPDstroke *gps, const int dflag)
{
- /* skip stroke if it isn't in the right display space for this drawing context */
- /* 1) 3D Strokes */
- if ((dflag & GP_DRAWDATA_ONLY3D) && !(gps->flag & GP_STROKE_3DSPACE))
- return false;
- if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE))
- return false;
-
- /* 2) Screen Space 2D Strokes */
- if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE))
- return false;
- if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE))
- return false;
-
- /* 3) Image Space (2D) */
- if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE))
- return false;
- if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE))
- return false;
-
- /* skip stroke if it doesn't have any valid data */
- if ((gps->points == NULL) || (gps->totpoints < 1))
- return false;
-
- /* stroke can be drawn */
- return true;
+ /* skip stroke if it isn't in the right display space for this drawing context */
+ /* 1) 3D Strokes */
+ if ((dflag & GP_DRAWDATA_ONLY3D) && !(gps->flag & GP_STROKE_3DSPACE))
+ return false;
+ if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE))
+ return false;
+
+ /* 2) Screen Space 2D Strokes */
+ if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE))
+ return false;
+ if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE))
+ return false;
+
+ /* 3) Image Space (2D) */
+ if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE))
+ return false;
+ if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE))
+ return false;
+
+ /* skip stroke if it doesn't have any valid data */
+ if ((gps->points == NULL) || (gps->totpoints < 1))
+ return false;
+
+ /* stroke can be drawn */
+ return true;
}
/* draw a set of strokes */
-static void gp_draw_strokes(
- bGPdata *UNUSED(gpd), bGPDlayer *UNUSED(gpl), const bGPDframe *gpf, int offsx, int offsy, int winx, int winy,
- int dflag, short lthick, const float color[4])
+static void gp_draw_strokes(bGPdata *UNUSED(gpd),
+ bGPDlayer *UNUSED(gpl),
+ const bGPDframe *gpf,
+ int offsx,
+ int offsy,
+ int winx,
+ int winy,
+ int dflag,
+ short lthick,
+ const float color[4])
{
- GPU_enable_program_point_size();
-
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- /* check if stroke can be drawn */
- if (gp_can_draw_stroke(gps, dflag) == false) {
- continue;
- }
-
- /* check which stroke-drawer to use */
- if (dflag & GP_DRAWDATA_ONLY3D) {
- const int no_xray = (dflag & GP_DRAWDATA_NO_XRAY);
- int mask_orig = 0;
-
- 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);
- }
-
- /* 3D Lines - OpenGL primitives-based */
- if (gps->totpoints == 1) {
- gp_draw_stroke_point(gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy, color);
- }
- else {
- gp_draw_stroke_3d(
- gps->points, gps->totpoints, lthick, gps->flag,
- color, gps->flag & GP_STROKE_CYCLIC);
- }
-
- if (no_xray) {
- glDepthMask(mask_orig);
- GPU_depth_test(false);
-
- bglPolygonOffset(0.0, 0.0);
- }
- }
- else {
- /* 2D Strokes... */
- if (gps->totpoints == 1) {
- gp_draw_stroke_point(gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy, color);
- }
- else {
- gp_draw_stroke_2d(
- gps->points, gps->totpoints, lthick, dflag, gps->flag,
- offsx, offsy, winx, winy, color);
- }
- }
- }
-
- GPU_disable_program_point_size();
+ GPU_enable_program_point_size();
+
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* check if stroke can be drawn */
+ if (gp_can_draw_stroke(gps, dflag) == false) {
+ continue;
+ }
+
+ /* check which stroke-drawer to use */
+ if (dflag & GP_DRAWDATA_ONLY3D) {
+ const int no_xray = (dflag & GP_DRAWDATA_NO_XRAY);
+ int mask_orig = 0;
+
+ 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);
+ }
+
+ /* 3D Lines - OpenGL primitives-based */
+ if (gps->totpoints == 1) {
+ gp_draw_stroke_point(
+ gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy, color);
+ }
+ else {
+ gp_draw_stroke_3d(
+ gps->points, gps->totpoints, lthick, gps->flag, color, gps->flag & GP_STROKE_CYCLIC);
+ }
+
+ if (no_xray) {
+ glDepthMask(mask_orig);
+ GPU_depth_test(false);
+
+ bglPolygonOffset(0.0, 0.0);
+ }
+ }
+ else {
+ /* 2D Strokes... */
+ if (gps->totpoints == 1) {
+ gp_draw_stroke_point(
+ gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy, color);
+ }
+ else {
+ gp_draw_stroke_2d(gps->points,
+ gps->totpoints,
+ lthick,
+ dflag,
+ gps->flag,
+ offsx,
+ offsy,
+ winx,
+ winy,
+ color);
+ }
+ }
+ }
+
+ GPU_disable_program_point_size();
}
/* Draw selected verts for strokes being edited */
-static void gp_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)
+static void gp_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_enable_program_point_size();
-
- /* draw stroke verts */
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- /* check if stroke can be drawn */
- if (gp_can_draw_stroke(gps, dflag) == false)
- continue;
-
- /* Optimisation: 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);
- }
- else {
- immAttr3fv(color, gpl->color);
- immAttr1f(size, bsize);
- }
-
- /* then position */
- if (gps->flag & GP_STROKE_3DSPACE) {
- immVertex3fv(pos, &pt->x);
- }
- else {
- float co[2];
- gp_calc_2d_stroke_fxy(&pt->x, gps->flag, offsx, offsy, winx, winy, co);
- immVertex2fv(pos, co);
- }
- }
-
- immEnd();
- immUnbindProgram();
- }
-
- GPU_disable_program_point_size();
-
- /* clear depth mask */
- if (dflag & GP_DRAWDATA_ONLY3D) {
- if (no_xray) {
- glDepthMask(mask_orig);
- GPU_depth_test(false);
-
- bglPolygonOffset(0.0, 0.0);
+ /* 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_enable_program_point_size();
+
+ /* draw stroke verts */
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* check if stroke can be drawn */
+ if (gp_can_draw_stroke(gps, dflag) == false)
+ continue;
+
+ /* Optimisation: 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);
+ }
+ else {
+ immAttr3fv(color, gpl->color);
+ immAttr1f(size, bsize);
+ }
+
+ /* then position */
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ immVertex3fv(pos, &pt->x);
+ }
+ else {
+ float co[2];
+ gp_calc_2d_stroke_fxy(&pt->x, gps->flag, offsx, offsy, winx, winy, co);
+ immVertex2fv(pos, co);
+ }
+ }
+
+ immEnd();
+ immUnbindProgram();
+ }
+
+ GPU_disable_program_point_size();
+
+ /* 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);
+ glDisable(GL_POLYGON_OFFSET_LINE);
+ glPolygonOffset(0, 0);
#endif
- }
- }
+ }
+ }
}
/* ----- General Drawing ------ */
/* draw onion-skinning for a layer */
-static void gp_draw_onionskins(
- bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, int offsx, int offsy, int winx, int winy,
- int UNUSED(cfra), int dflag)
+static void gp_draw_onionskins(bGPdata *gpd,
+ bGPDlayer *gpl,
+ bGPDframe *gpf,
+ int offsx,
+ int offsy,
+ int winx,
+ int winy,
+ int UNUSED(cfra),
+ int dflag)
{
- const float alpha = 1.0f;
- float color[4];
-
- /* 1) Draw Previous Frames First */
- copy_v3_v3(color, gpl->gcolor_prev);
-
- if (gpl->gstep > 0) {
- bGPDframe *gf;
- float fac;
-
- /* draw previous frames first */
- for (gf = gpf->prev; gf; gf = gf->prev) {
- /* check if frame is drawable */
- if ((gpf->framenum - gf->framenum) <= gpl->gstep) {
- /* 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;
- gp_draw_strokes(
- gpd, gpl, gf, offsx, offsy, winx, winy, dflag,
- gpl->thickness, color);
- }
- else
- break;
- }
- }
- else if (gpl->gstep == 0) {
- /* draw the strokes for the ghost frames (at half of the alpha set by user) */
- if (gpf->prev) {
- color[3] = (alpha / 7);
- gp_draw_strokes(
- gpd, gpl, gpf->prev, offsx, offsy, winx, winy, dflag,
- gpl->thickness, color);
- }
- }
- else {
- /* don't draw - disabled */
- }
-
-
- /* 2) Now draw next frames */
- copy_v3_v3(color, gpl->gcolor_next);
-
- if (gpl->gstep_next > 0) {
- bGPDframe *gf;
- float fac;
-
- /* now draw next frames */
- for (gf = gpf->next; gf; gf = gf->next) {
- /* check if frame is drawable */
- if ((gf->framenum - gpf->framenum) <= gpl->gstep_next) {
- /* 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;
- gp_draw_strokes(
- gpd, gpl, gf, offsx, offsy, winx, winy, dflag,
- gpl->thickness, color);
- }
- else
- break;
- }
- }
- else if (gpl->gstep_next == 0) {
- /* draw the strokes for the ghost frames (at half of the alpha set by user) */
- if (gpf->next) {
- color[3] = (alpha / 4);
- gp_draw_strokes(
- gpd, gpl, gpf->next, offsx, offsy, winx, winy, dflag,
- gpl->thickness, color);
- }
- }
- else {
- /* don't draw - disabled */
- }
-
+ const float alpha = 1.0f;
+ float color[4];
+
+ /* 1) Draw Previous Frames First */
+ copy_v3_v3(color, gpl->gcolor_prev);
+
+ if (gpl->gstep > 0) {
+ bGPDframe *gf;
+ float fac;
+
+ /* draw previous frames first */
+ for (gf = gpf->prev; gf; gf = gf->prev) {
+ /* check if frame is drawable */
+ if ((gpf->framenum - gf->framenum) <= gpl->gstep) {
+ /* 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;
+ gp_draw_strokes(gpd, gpl, gf, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
+ }
+ else
+ break;
+ }
+ }
+ else if (gpl->gstep == 0) {
+ /* draw the strokes for the ghost frames (at half of the alpha set by user) */
+ if (gpf->prev) {
+ color[3] = (alpha / 7);
+ gp_draw_strokes(gpd, gpl, gpf->prev, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
+ }
+ }
+ else {
+ /* don't draw - disabled */
+ }
+
+ /* 2) Now draw next frames */
+ copy_v3_v3(color, gpl->gcolor_next);
+
+ if (gpl->gstep_next > 0) {
+ bGPDframe *gf;
+ float fac;
+
+ /* now draw next frames */
+ for (gf = gpf->next; gf; gf = gf->next) {
+ /* check if frame is drawable */
+ if ((gf->framenum - gpf->framenum) <= gpl->gstep_next) {
+ /* 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;
+ gp_draw_strokes(gpd, gpl, gf, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
+ }
+ else
+ break;
+ }
+ }
+ else if (gpl->gstep_next == 0) {
+ /* draw the strokes for the ghost frames (at half of the alpha set by user) */
+ if (gpf->next) {
+ color[3] = (alpha / 4);
+ gp_draw_strokes(gpd, gpl, gpf->next, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
+ }
+ }
+ else {
+ /* don't draw - disabled */
+ }
}
/* loop over gpencil data layers, drawing them */
static void gp_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 alpha)
{
- float ink[4];
-
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* verify never thickness is less than 1 */
- CLAMP_MIN(gpl->thickness, 1.0f);
- short lthick = gpl->thickness;
-
- /* apply layer opacity */
- copy_v3_v3(ink, gpl->color);
- ink[3] = gpl->opacity;
-
- /* don't draw layer if hidden */
- if (gpl->flag & GP_LAYER_HIDE)
- continue;
-
- /* get frame to draw */
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra, GP_GETFRAME_USE_PREV);
- if (gpf == NULL)
- continue;
-
- /* set basic stroke thickness */
- GPU_line_width(lthick);
-
- /* Add layer drawing settings to the set of "draw flags"
- * NOTE: If the setting doesn't apply, it *must* be cleared,
- * as dflag's carry over from the previous layer
- */
-
- /* xray... */
- SET_FLAG_FROM_TEST(dflag, gpl->flag & GP_LAYER_NO_XRAY, GP_DRAWDATA_NO_XRAY);
-
- /* Draw 'onionskins' (frame left + right) */
- if (gpl->onion_flag & GP_LAYER_ONIONSKIN) {
- gp_draw_onionskins(gpd, gpl, gpf, offsx, offsy, winx, winy, cfra, dflag);
- }
-
- /* draw the strokes already in active frame */
- gp_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))
- {
- gp_draw_strokes_edit(gpd, gpl, gpf, offsx, offsy, winx, winy, dflag, gpl->flag, alpha);
- }
-
- /* 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)
- */
- if (ED_gpencil_session_active() && (gpl->flag & GP_LAYER_ACTIVE) &&
- (gpf->flag & GP_FRAME_PAINT))
- {
- /* Buffer stroke needs to be drawn with a different linestyle
- * to help differentiate them from normal strokes.
- *
- * It should also be noted that sbuffer contains temporary point types
- * i.e. tGPspoints NOT bGPDspoints
- */
- gp_draw_stroke_buffer(
- gpd->runtime.sbuffer,
- gpd->runtime.sbuffer_size, lthick,
- dflag, gpd->runtime.sbuffer_sflag, ink);
- }
- }
+ float ink[4];
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* verify never thickness is less than 1 */
+ CLAMP_MIN(gpl->thickness, 1.0f);
+ short lthick = gpl->thickness;
+
+ /* apply layer opacity */
+ copy_v3_v3(ink, gpl->color);
+ ink[3] = gpl->opacity;
+
+ /* don't draw layer if hidden */
+ if (gpl->flag & GP_LAYER_HIDE)
+ continue;
+
+ /* get frame to draw */
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra, GP_GETFRAME_USE_PREV);
+ if (gpf == NULL)
+ continue;
+
+ /* set basic stroke thickness */
+ GPU_line_width(lthick);
+
+ /* Add layer drawing settings to the set of "draw flags"
+ * NOTE: If the setting doesn't apply, it *must* be cleared,
+ * as dflag's carry over from the previous layer
+ */
+
+ /* xray... */
+ SET_FLAG_FROM_TEST(dflag, gpl->flag & GP_LAYER_NO_XRAY, GP_DRAWDATA_NO_XRAY);
+
+ /* Draw 'onionskins' (frame left + right) */
+ if (gpl->onion_flag & GP_LAYER_ONIONSKIN) {
+ gp_draw_onionskins(gpd, gpl, gpf, offsx, offsy, winx, winy, cfra, dflag);
+ }
+
+ /* draw the strokes already in active frame */
+ gp_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)) {
+ gp_draw_strokes_edit(gpd, gpl, gpf, offsx, offsy, winx, winy, dflag, gpl->flag, alpha);
+ }
+
+ /* 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)
+ */
+ if (ED_gpencil_session_active() && (gpl->flag & GP_LAYER_ACTIVE) &&
+ (gpf->flag & GP_FRAME_PAINT)) {
+ /* Buffer stroke needs to be drawn with a different linestyle
+ * to help differentiate them from normal strokes.
+ *
+ * It should also be noted that sbuffer contains temporary point types
+ * i.e. tGPspoints NOT bGPDspoints
+ */
+ gp_draw_stroke_buffer(gpd->runtime.sbuffer,
+ gpd->runtime.sbuffer_size,
+ lthick,
+ dflag,
+ gpd->runtime.sbuffer_sflag,
+ ink);
+ }
+ }
}
/* draw a short status message in the top-right corner */
static void gp_draw_status_text(const bGPdata *gpd, ARegion *ar)
{
- rcti rect;
+ rcti rect;
- /* Cannot draw any status text when drawing OpenGL Renders */
- if (G.f & G_FLAG_RENDER_VIEWPORT)
- return;
+ /* 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 */
- ED_region_visible_rect(ar, &rect);
+ /* Get bounds of region - Necessary to avoid problems with region overlap */
+ ED_region_visible_rect(ar, &rect);
- /* 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];
+ /* 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();
+ int font_id = BLF_default();
- BLF_width_and_height(font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
+ 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);
+ 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);
+ /* 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);
+ 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);
+ 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);
+ /* 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;
+ xco -= U.widget_unit;
+ yco -= (int)printable_size[1] / 2;
- UI_icon_draw(xco, yco, ICON_GREASEPENCIL);
+ UI_icon_draw(xco, yco, ICON_GREASEPENCIL);
- GPU_blend(false);
- }
+ GPU_blend(false);
+ }
}
/* draw grease-pencil datablock */
static void gp_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, float alpha)
{
- /* turn on smooth lines (i.e. anti-aliasing) */
- GPU_line_smooth(true);
+ /* turn on smooth lines (i.e. anti-aliasing) */
+ GPU_line_smooth(true);
- /* turn on alpha-blending */
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
+ /* turn on alpha-blending */
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
- /* draw! */
- gp_draw_data_layers(gpd, offsx, offsy, winx, winy, cfra, dflag, alpha);
+ /* draw! */
+ gp_draw_data_layers(gpd, offsx, offsy, winx, winy, cfra, dflag, alpha);
- /* turn off alpha blending, then smooth lines */
- GPU_blend(false); // alpha blending
- GPU_line_smooth(false); // smooth lines
+ /* turn off alpha blending, then smooth lines */
+ GPU_blend(false); // alpha blending
+ GPU_line_smooth(false); // smooth lines
}
/* if we have strokes for scenes (3d view)/clips (movie clip editor)
* and objects/tracks, multiple data blocks have to be drawn */
-static void gp_draw_data_all(
- Scene *scene, bGPdata *gpd, int offsx, int offsy, int winx, int winy,
- int cfra, int dflag, const char spacetype)
+static void gp_draw_data_all(Scene *scene,
+ bGPdata *gpd,
+ int offsx,
+ int offsy,
+ int winx,
+ int winy,
+ int cfra,
+ int dflag,
+ const char spacetype)
{
- bGPdata *gpd_source = NULL;
- float alpha = 1.0f;
-
- if (scene) {
- if (spacetype == SPACE_VIEW3D) {
- gpd_source = (scene->gpd ? scene->gpd : NULL);
- }
- else if (spacetype == SPACE_CLIP && scene->clip) {
- /* currently drawing only gpencil data from either clip or track,
- * but not both - XXX fix logic behind */
- gpd_source = (scene->clip->gpd ? scene->clip->gpd : NULL);
- }
-
- if (gpd_source) {
- gp_draw_data(gpd_source, offsx, offsy, winx, winy, cfra, dflag, alpha);
- }
- }
-
- /* 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)) {
- gp_draw_data(gpd, offsx, offsy, winx, winy, cfra, dflag, alpha);
- }
+ bGPdata *gpd_source = NULL;
+ float alpha = 1.0f;
+
+ if (scene) {
+ if (spacetype == SPACE_VIEW3D) {
+ gpd_source = (scene->gpd ? scene->gpd : NULL);
+ }
+ else if (spacetype == SPACE_CLIP && scene->clip) {
+ /* currently drawing only gpencil data from either clip or track,
+ * but not both - XXX fix logic behind */
+ gpd_source = (scene->clip->gpd ? scene->clip->gpd : NULL);
+ }
+
+ if (gpd_source) {
+ gp_draw_data(gpd_source, offsx, offsy, winx, winy, cfra, dflag, alpha);
+ }
+ }
+
+ /* 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)) {
+ gp_draw_data(gpd, offsx, offsy, winx, winy, cfra, dflag, alpha);
+ }
}
/* ----- Grease Pencil Sketches Drawing API ------ */
@@ -983,66 +1023,67 @@ static void gp_draw_data_all(
/* draw grease-pencil sketches to specified 2d-view that uses ibuf corrections */
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);
- Scene *scene = CTX_data_scene(C);
-
- int offsx, offsy, sizex, sizey;
- int dflag = GP_DRAWDATA_NOSTATUS;
-
- bGPdata *gpd = ED_gpencil_data_get_active(C); // XXX
- if (gpd == NULL) return;
-
- /* calculate rect */
- switch (sa->spacetype) {
- case SPACE_IMAGE: /* image */
- case SPACE_CLIP: /* clip */
- {
- /* just draw using standard scaling (settings here are currently ignored anyways) */
- /* FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled */
- offsx = 0;
- offsy = 0;
- sizex = ar->winx;
- sizey = ar->winy;
-
- wmOrtho2(ar->v2d.cur.xmin, ar->v2d.cur.xmax, ar->v2d.cur.ymin, ar->v2d.cur.ymax);
-
- dflag |= GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_IEDITHACK;
- break;
- }
- case SPACE_SEQ: /* sequence */
- {
- /* just draw using standard scaling (settings here are currently ignored anyways) */
- offsx = 0;
- offsy = 0;
- sizex = ar->winx;
- sizey = ar->winy;
-
- /* NOTE: I2D was used in 2.4x, but the old settings for that have been deprecated
- * and everything moved to standard View2d
- */
- dflag |= GP_DRAWDATA_ONLYV2D;
- break;
- }
- default: /* for spacetype not yet handled */
- offsx = 0;
- offsy = 0;
- sizex = ar->winx;
- sizey = ar->winy;
-
- dflag |= GP_DRAWDATA_ONLYI2D;
- break;
- }
-
- if (ED_screen_animation_playing(wm)) {
- /* Don't show onion-skins during animation playback/scrub (i.e. it obscures the poses)
- * OpenGL Renders (i.e. final output), or depth buffer (i.e. not real strokes). */
- dflag |= GP_DRAWDATA_NO_ONIONS;
- }
-
- /* draw it! */
- gp_draw_data_all(scene, gpd, offsx, offsy, sizex, sizey, CFRA, dflag, sa->spacetype);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+
+ int offsx, offsy, sizex, sizey;
+ int dflag = GP_DRAWDATA_NOSTATUS;
+
+ bGPdata *gpd = ED_gpencil_data_get_active(C); // XXX
+ if (gpd == NULL)
+ return;
+
+ /* calculate rect */
+ switch (sa->spacetype) {
+ case SPACE_IMAGE: /* image */
+ case SPACE_CLIP: /* clip */
+ {
+ /* just draw using standard scaling (settings here are currently ignored anyways) */
+ /* FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled */
+ offsx = 0;
+ offsy = 0;
+ sizex = ar->winx;
+ sizey = ar->winy;
+
+ wmOrtho2(ar->v2d.cur.xmin, ar->v2d.cur.xmax, ar->v2d.cur.ymin, ar->v2d.cur.ymax);
+
+ dflag |= GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_IEDITHACK;
+ break;
+ }
+ case SPACE_SEQ: /* sequence */
+ {
+ /* just draw using standard scaling (settings here are currently ignored anyways) */
+ offsx = 0;
+ offsy = 0;
+ sizex = ar->winx;
+ sizey = ar->winy;
+
+ /* NOTE: I2D was used in 2.4x, but the old settings for that have been deprecated
+ * and everything moved to standard View2d
+ */
+ dflag |= GP_DRAWDATA_ONLYV2D;
+ break;
+ }
+ default: /* for spacetype not yet handled */
+ offsx = 0;
+ offsy = 0;
+ sizex = ar->winx;
+ sizey = ar->winy;
+
+ dflag |= GP_DRAWDATA_ONLYI2D;
+ break;
+ }
+
+ if (ED_screen_animation_playing(wm)) {
+ /* Don't show onion-skins during animation playback/scrub (i.e. it obscures the poses)
+ * OpenGL Renders (i.e. final output), or depth buffer (i.e. not real strokes). */
+ dflag |= GP_DRAWDATA_NO_ONIONS;
+ }
+
+ /* draw it! */
+ gp_draw_data_all(scene, gpd, offsx, offsy, sizex, sizey, CFRA, dflag, sa->spacetype);
}
/* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly
@@ -1050,95 +1091,96 @@ void ED_annotation_draw_2dimage(const bContext *C)
* second time with onlyv2d=false for screen-aligned strokes */
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);
- Scene *scene = CTX_data_scene(C);
- int dflag = 0;
-
- /* check that we have grease-pencil stuff to draw */
- if (sa == NULL) return;
- bGPdata *gpd = ED_gpencil_data_get_active(C); // XXX
- if (gpd == NULL) return;
-
- /* 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))
- dflag |= GP_DRAWDATA_IEDITHACK;
-
- /* draw it! */
- if (onlyv2d) dflag |= (GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_NOSTATUS);
- if (ED_screen_animation_playing(wm)) dflag |= GP_DRAWDATA_NO_ONIONS;
-
- gp_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) {
- gp_draw_status_text(gpd, ar);
- }
+ wmWindowManager *wm = CTX_wm_manager(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = 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)
+ return;
+ bGPdata *gpd = ED_gpencil_data_get_active(C); // XXX
+ if (gpd == NULL)
+ return;
+
+ /* 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))
+ dflag |= GP_DRAWDATA_IEDITHACK;
+
+ /* draw it! */
+ if (onlyv2d)
+ dflag |= (GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_NOSTATUS);
+ if (ED_screen_animation_playing(wm))
+ dflag |= GP_DRAWDATA_NO_ONIONS;
+
+ gp_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) {
+ gp_draw_status_text(gpd, ar);
+ }
}
-
/* 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 *ar, bool only3d)
{
- int dflag = 0;
- RegionView3D *rv3d = ar->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 */
- bGPdata *gpd = scene->gpd;
- if (gpd == NULL) return;
-
- /* when rendering to the offscreen buffer we don't want to
- * 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 */
-
- offsx = round_fl_to_int(rectf.xmin);
- offsy = round_fl_to_int(rectf.ymin);
- winx = round_fl_to_int(rectf.xmax - rectf.xmin);
- winy = round_fl_to_int(rectf.ymax - rectf.ymin);
- }
- else {
- offsx = 0;
- offsy = 0;
- winx = ar->winx;
- winy = ar->winy;
- }
-
- /* set flags */
- if (only3d) {
- /* 3D strokes/3D space:
- * - only 3D space points
- * - don't status text either (as it's the wrong space)
- */
- dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS);
- }
-
- if (v3d->flag2 & V3D_HIDE_OVERLAYS) {
- /* don't draw status text when "only render" flag is set */
- dflag |= GP_DRAWDATA_NOSTATUS;
- }
-
- /* draw it! */
- gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype);
+ int dflag = 0;
+ RegionView3D *rv3d = ar->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 */
+ bGPdata *gpd = scene->gpd;
+ if (gpd == NULL)
+ return;
+
+ /* when rendering to the offscreen buffer we don't want to
+ * 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 */
+
+ offsx = round_fl_to_int(rectf.xmin);
+ offsy = round_fl_to_int(rectf.ymin);
+ winx = round_fl_to_int(rectf.xmax - rectf.xmin);
+ winy = round_fl_to_int(rectf.ymax - rectf.ymin);
+ }
+ else {
+ offsx = 0;
+ offsy = 0;
+ winx = ar->winx;
+ winy = ar->winy;
+ }
+
+ /* set flags */
+ if (only3d) {
+ /* 3D strokes/3D space:
+ * - only 3D space points
+ * - don't status text either (as it's the wrong space)
+ */
+ dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS);
+ }
+
+ if (v3d->flag2 & V3D_HIDE_OVERLAYS) {
+ /* don't draw status text when "only render" flag is set */
+ dflag |= GP_DRAWDATA_NOSTATUS;
+ }
+
+ /* draw it! */
+ gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype);
}
void ED_annotation_draw_ex(
- Scene *scene, bGPdata *gpd,
- int winx, int winy, const int cfra, const char spacetype)
+ Scene *scene, bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype)
{
- int dflag = GP_DRAWDATA_NOSTATUS | GP_DRAWDATA_ONLYV2D;
+ int dflag = GP_DRAWDATA_NOSTATUS | GP_DRAWDATA_ONLYV2D;
- gp_draw_data_all(scene, gpd, 0, 0, winx, winy, cfra, dflag, spacetype);
+ gp_draw_data_all(scene, gpd, 0, 0, winx, winy, cfra, dflag, spacetype);
}
/* ************************************************** */
diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c
index bfbf319b1c6..4933f081790 100644
--- a/source/blender/editors/gpencil/annotate_paint.c
+++ b/source/blender/editors/gpencil/annotate_paint.c
@@ -21,7 +21,6 @@
* \ingroup edgpencil
*/
-
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
@@ -61,7 +60,6 @@
#include "ED_view3d.h"
#include "ED_clip.h"
-
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_state.h"
@@ -81,132 +79,131 @@
/* values for tGPsdata->status */
typedef enum eGPencil_PaintStatus {
- GP_STATUS_IDLING = 0, /* stroke isn't in progress yet */
- GP_STATUS_PAINTING, /* a stroke is in progress */
- GP_STATUS_ERROR, /* something wasn't correctly set up */
- GP_STATUS_DONE, /* painting done */
- GP_STATUS_CAPTURE /* capture event, but cancel */
+ GP_STATUS_IDLING = 0, /* stroke isn't in progress yet */
+ GP_STATUS_PAINTING, /* a stroke is in progress */
+ GP_STATUS_ERROR, /* something wasn't correctly set up */
+ GP_STATUS_DONE, /* painting done */
+ GP_STATUS_CAPTURE /* capture event, but cancel */
} eGPencil_PaintStatus;
/* Return flags for adding points to stroke buffer */
typedef enum eGP_StrokeAdd_Result {
- GP_STROKEADD_INVALID = -2, /* error occurred - insufficient info to do so */
- GP_STROKEADD_OVERFLOW = -1, /* error occurred - cannot fit any more points */
- GP_STROKEADD_NORMAL, /* point was successfully added */
- GP_STROKEADD_FULL, /* cannot add any more points to buffer */
+ GP_STROKEADD_INVALID = -2, /* error occurred - insufficient info to do so */
+ GP_STROKEADD_OVERFLOW = -1, /* error occurred - cannot fit any more points */
+ GP_STROKEADD_NORMAL, /* point was successfully added */
+ GP_STROKEADD_FULL, /* cannot add any more points to buffer */
} eGP_StrokeAdd_Result;
/* Runtime flags */
typedef enum eGPencil_PaintFlags {
- GP_PAINTFLAG_FIRSTRUN = (1 << 0), /* operator just started */
- GP_PAINTFLAG_STROKEADDED = (1 << 1),
- GP_PAINTFLAG_V3D_ERASER_DEPTH = (1 << 2),
- GP_PAINTFLAG_SELECTMASK = (1 << 3),
+ GP_PAINTFLAG_FIRSTRUN = (1 << 0), /* operator just started */
+ GP_PAINTFLAG_STROKEADDED = (1 << 1),
+ GP_PAINTFLAG_V3D_ERASER_DEPTH = (1 << 2),
+ GP_PAINTFLAG_SELECTMASK = (1 << 3),
} eGPencil_PaintFlags;
-
/* Temporary 'Stroke' Operation data
* "p" = op->customdata
*/
typedef struct tGPsdata {
- Main *bmain;
- /** current scene from context. */
- Scene *scene;
- struct Depsgraph *depsgraph;
-
- /** window where painting originated. */
- wmWindow *win;
- /** area where painting originated. */
- ScrArea *sa;
- /** region where painting originated. */
- ARegion *ar;
- /** needed for GP_STROKE_2DSPACE. */
- View2D *v2d;
- /** for using the camera rect within the 3d view. */
- rctf *subrect;
- rctf subrect_data;
-
- /** settings to pass to gp_points_to_xy(). */
- GP_SpaceConversion gsc;
-
- /** pointer to owner of gp-datablock. */
- PointerRNA ownerPtr;
- /** gp-datablock layer comes from. */
- bGPdata *gpd;
- /** layer we're working on. */
- bGPDlayer *gpl;
- /** frame we're working on. */
- bGPDframe *gpf;
-
- /** projection-mode flags (toolsettings - eGPencil_Placement_Flags) */
- char *align_flag;
-
- /** current status of painting. */
- eGPencil_PaintStatus status;
- /** mode for painting. */
- eGPencil_PaintModes paintmode;
- /** flags that can get set during runtime (eGPencil_PaintFlags) */
- eGPencil_PaintFlags flags;
-
- /** radius of influence for eraser. */
- short radius;
-
- /** current mouse-position. */
- float mval[2];
- /** previous recorded mouse-position. */
- float mvalo[2];
-
- /** current stylus pressure. */
- float pressure;
- /** previous stylus pressure. */
- float opressure;
-
- /* These need to be doubles, as (at least under unix) they are in seconds since epoch,
- * float (and its 7 digits precision) is definitively not enough here!
- * double, with its 15 digits precision, ensures us millisecond precision for a few centuries at least.
- */
- /** Used when converting to path. */
- double inittime;
- /** Used when converting to path. */
- double curtime;
- /** Used when converting to path. */
- double ocurtime;
-
- /** Inverted transformation matrix applying when converting coords from screen-space
- * to region space. */
- float imat[4][4];
- float mat[4][4];
-
- /** custom color - hack for enforcing a particular color for track/mask editing. */
- float custom_color[4];
-
- /** radial cursor data for drawing eraser. */
- void *erasercursor;
-
- /** 1: line horizontal, 2: line vertical, other: not defined, second element position. */
- short straight[2];
-
- /** key used for invoking the operator. */
- short keymodifier;
+ Main *bmain;
+ /** current scene from context. */
+ Scene *scene;
+ struct Depsgraph *depsgraph;
+
+ /** window where painting originated. */
+ wmWindow *win;
+ /** area where painting originated. */
+ ScrArea *sa;
+ /** region where painting originated. */
+ ARegion *ar;
+ /** needed for GP_STROKE_2DSPACE. */
+ View2D *v2d;
+ /** for using the camera rect within the 3d view. */
+ rctf *subrect;
+ rctf subrect_data;
+
+ /** settings to pass to gp_points_to_xy(). */
+ GP_SpaceConversion gsc;
+
+ /** pointer to owner of gp-datablock. */
+ PointerRNA ownerPtr;
+ /** gp-datablock layer comes from. */
+ bGPdata *gpd;
+ /** layer we're working on. */
+ bGPDlayer *gpl;
+ /** frame we're working on. */
+ bGPDframe *gpf;
+
+ /** projection-mode flags (toolsettings - eGPencil_Placement_Flags) */
+ char *align_flag;
+
+ /** current status of painting. */
+ eGPencil_PaintStatus status;
+ /** mode for painting. */
+ eGPencil_PaintModes paintmode;
+ /** flags that can get set during runtime (eGPencil_PaintFlags) */
+ eGPencil_PaintFlags flags;
+
+ /** radius of influence for eraser. */
+ short radius;
+
+ /** current mouse-position. */
+ float mval[2];
+ /** previous recorded mouse-position. */
+ float mvalo[2];
+
+ /** current stylus pressure. */
+ float pressure;
+ /** previous stylus pressure. */
+ float opressure;
+
+ /* These need to be doubles, as (at least under unix) they are in seconds since epoch,
+ * float (and its 7 digits precision) is definitively not enough here!
+ * double, with its 15 digits precision, ensures us millisecond precision for a few centuries at least.
+ */
+ /** Used when converting to path. */
+ double inittime;
+ /** Used when converting to path. */
+ double curtime;
+ /** Used when converting to path. */
+ double ocurtime;
+
+ /** Inverted transformation matrix applying when converting coords from screen-space
+ * to region space. */
+ float imat[4][4];
+ float mat[4][4];
+
+ /** custom color - hack for enforcing a particular color for track/mask editing. */
+ float custom_color[4];
+
+ /** radial cursor data for drawing eraser. */
+ void *erasercursor;
+
+ /** 1: line horizontal, 2: line vertical, other: not defined, second element position. */
+ short straight[2];
+
+ /** key used for invoking the operator. */
+ short keymodifier;
} tGPsdata;
/* ------ */
/* Macros for accessing sensitivity thresholds... */
/* minimum number of pixels mouse should move before new point created */
-#define MIN_MANHATTEN_PX (U.gp_manhattendist)
+#define MIN_MANHATTEN_PX (U.gp_manhattendist)
/* minimum length of new segment before new point can be added */
-#define MIN_EUCLIDEAN_PX (U.gp_euclideandist)
+#define MIN_EUCLIDEAN_PX (U.gp_euclideandist)
static bool gp_stroke_added_check(tGPsdata *p)
{
- return (p->gpf && p->gpf->strokes.last && p->flags & GP_PAINTFLAG_STROKEADDED);
+ 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);
- p->flags |= GP_PAINTFLAG_STROKEADDED;
+ BLI_assert(p->gpf->strokes.last != NULL);
+ p->flags |= GP_PAINTFLAG_STROKEADDED;
}
/* ------ */
@@ -220,43 +217,42 @@ static void gp_session_validatebuffer(tGPsdata *p);
/* check if context is suitable for drawing */
static bool gpencil_draw_poll(bContext *C)
{
- /* if is inside grease pencil draw mode cannot use annotations */
- Object *obact = CTX_data_active_object(C);
- ScrArea *sa = CTX_wm_area(C);
- if ((sa) && (sa->spacetype == SPACE_VIEW3D)) {
- if ((obact) && (obact->type == OB_GPENCIL) &&
- (obact->mode == OB_MODE_PAINT_GPENCIL))
- {
- CTX_wm_operator_poll_msg_set(C, "Annotation cannot be used in grease pencil draw mode");
- return false;
- }
- }
-
- if (ED_operator_regionactive(C)) {
- /* check if current context can support GPencil data */
- if (ED_gpencil_data_get_pointers(C, NULL) != NULL) {
- /* check if Grease Pencil isn't already running */
- if (ED_gpencil_session_active() == 0)
- return true;
- else
- CTX_wm_operator_poll_msg_set(C, "Annotation operator is already active");
- }
- 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 false;
+ /* if is inside grease pencil draw mode cannot use annotations */
+ Object *obact = CTX_data_active_object(C);
+ ScrArea *sa = CTX_wm_area(C);
+ if ((sa) && (sa->spacetype == SPACE_VIEW3D)) {
+ if ((obact) && (obact->type == OB_GPENCIL) && (obact->mode == OB_MODE_PAINT_GPENCIL)) {
+ CTX_wm_operator_poll_msg_set(C, "Annotation cannot be used in grease pencil draw mode");
+ return false;
+ }
+ }
+
+ if (ED_operator_regionactive(C)) {
+ /* check if current context can support GPencil data */
+ if (ED_gpencil_data_get_pointers(C, NULL) != NULL) {
+ /* check if Grease Pencil isn't already running */
+ if (ED_gpencil_session_active() == 0)
+ return true;
+ else
+ CTX_wm_operator_poll_msg_set(C, "Annotation operator is already active");
+ }
+ 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 false;
}
/* check if projecting strokes into 3d-geometry in the 3D-View */
static bool gpencil_project_check(tGPsdata *p)
{
- bGPdata *gpd = p->gpd;
- return ((gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) && (*p->align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE)));
+ bGPdata *gpd = p->gpd;
+ return ((gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) &&
+ (*p->align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE)));
}
/* ******************************************* */
@@ -267,10 +263,10 @@ static bool gpencil_project_check(tGPsdata *p)
/* get the reference point for stroke-point conversions */
static void gp_get_3d_reference(tGPsdata *p, float vec[3])
{
- const float *fp = p->scene->cursor.location;
+ const float *fp = p->scene->cursor.location;
- /* use 3D-cursor */
- copy_v3_v3(vec, fp);
+ /* use 3D-cursor */
+ copy_v3_v3(vec, fp);
}
/* Stroke Editing ---------------------------- */
@@ -278,91 +274,92 @@ static void gp_get_3d_reference(tGPsdata *p, float vec[3])
/* check if the current mouse position is suitable for adding a new point */
static bool gp_stroke_filtermval(tGPsdata *p, const float mval[2], float pmval[2])
{
- int dx = (int)fabsf(mval[0] - pmval[0]);
- int dy = (int)fabsf(mval[1] - pmval[1]);
-
- /* if buffer is empty, just let this go through (i.e. so that dots will work) */
- if (p->gpd->runtime.sbuffer_size == 0)
- return true;
-
- /* check if mouse moved at least certain distance on both axes (best case)
- * - aims to eliminate some jitter-noise from input when trying to draw straight lines freehand
- */
- else if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX))
- return true;
-
- /* check if the distance since the last point is significant enough
- * - prevents points being added too densely
- * - distance here doesn't use sqrt to prevent slowness... we should still be safe from overflows though
- */
- else if ((dx * dx + dy * dy) > MIN_EUCLIDEAN_PX * MIN_EUCLIDEAN_PX)
- return true;
-
- /* mouse 'didn't move' */
- else
- return false;
+ int dx = (int)fabsf(mval[0] - pmval[0]);
+ int dy = (int)fabsf(mval[1] - pmval[1]);
+
+ /* if buffer is empty, just let this go through (i.e. so that dots will work) */
+ if (p->gpd->runtime.sbuffer_size == 0)
+ return true;
+
+ /* check if mouse moved at least certain distance on both axes (best case)
+ * - aims to eliminate some jitter-noise from input when trying to draw straight lines freehand
+ */
+ else if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX))
+ return true;
+
+ /* check if the distance since the last point is significant enough
+ * - prevents points being added too densely
+ * - distance here doesn't use sqrt to prevent slowness... we should still be safe from overflows though
+ */
+ else if ((dx * dx + dy * dy) > MIN_EUCLIDEAN_PX * MIN_EUCLIDEAN_PX)
+ return true;
+
+ /* mouse 'didn't move' */
+ else
+ return false;
}
/* convert screen-coordinates to buffer-coordinates */
static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[3], float *depth)
{
- bGPdata *gpd = p->gpd;
-
- /* in 3d-space - pt->x/y/z are 3 side-by-side floats */
- 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))) {
- /* projecting onto 3D-Geometry
- * - nothing more needs to be done here, since view_autodist_simple() has already done it
- */
- }
- else {
- float mval_prj[2];
- float rvec[3], dvec[3];
- float zfac;
-
- /* Current method just converts each point in screen-coordinates to
- * 3D-coordinates using the 3D-cursor as reference. In general, this
- * works OK, but it could of course be improved.
- *
- * TODO:
- * - investigate using nearest point(s) on a previous stroke as
- * reference point instead or as offset, for easier stroke matching
- */
-
- gp_get_3d_reference(p, rvec);
- zfac = ED_view3d_calc_zfac(p->ar->regiondata, rvec, NULL);
-
- if (ED_view3d_project_float_global(p->ar, 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);
- sub_v3_v3v3(out, rvec, dvec);
- }
- else {
- zero_v3(out);
- }
- }
- }
-
- /* 2d - on 'canvas' (assume that p->v2d is set) */
- else if ((gpd->runtime.sbuffer_sflag & GP_STROKE_2DSPACE) && (p->v2d)) {
- UI_view2d_region_to_view(p->v2d, mval[0], mval[1], &out[0], &out[1]);
- mul_v3_m4v3(out, p->imat, 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;
- }
- else { /* camera view, use subrect */
- out[0] = ((mval[0] - p->subrect->xmin) / BLI_rctf_size_x(p->subrect)) * 100;
- out[1] = ((mval[1] - p->subrect->ymin) / BLI_rctf_size_y(p->subrect)) * 100;
- }
- }
+ bGPdata *gpd = p->gpd;
+
+ /* in 3d-space - pt->x/y/z are 3 side-by-side floats */
+ 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))) {
+ /* projecting onto 3D-Geometry
+ * - nothing more needs to be done here, since view_autodist_simple() has already done it
+ */
+ }
+ else {
+ float mval_prj[2];
+ float rvec[3], dvec[3];
+ float zfac;
+
+ /* Current method just converts each point in screen-coordinates to
+ * 3D-coordinates using the 3D-cursor as reference. In general, this
+ * works OK, but it could of course be improved.
+ *
+ * TODO:
+ * - investigate using nearest point(s) on a previous stroke as
+ * reference point instead or as offset, for easier stroke matching
+ */
+
+ gp_get_3d_reference(p, rvec);
+ zfac = ED_view3d_calc_zfac(p->ar->regiondata, rvec, NULL);
+
+ if (ED_view3d_project_float_global(p->ar, 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);
+ sub_v3_v3v3(out, rvec, dvec);
+ }
+ else {
+ zero_v3(out);
+ }
+ }
+ }
+
+ /* 2d - on 'canvas' (assume that p->v2d is set) */
+ else if ((gpd->runtime.sbuffer_sflag & GP_STROKE_2DSPACE) && (p->v2d)) {
+ UI_view2d_region_to_view(p->v2d, mval[0], mval[1], &out[0], &out[1]);
+ mul_v3_m4v3(out, p->imat, 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;
+ }
+ else { /* camera view, use subrect */
+ out[0] = ((mval[0] - p->subrect->xmin) / BLI_rctf_size_x(p->subrect)) * 100;
+ out[1] = ((mval[1] - p->subrect->ymin) / BLI_rctf_size_y(p->subrect)) * 100;
+ }
+ }
}
/* Apply smooth to buffer while drawing
@@ -376,188 +373,187 @@ static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[
*/
static void gp_smooth_buffer(tGPsdata *p, float inf, int idx)
{
- bGPdata *gpd = p->gpd;
- short num_points = gpd->runtime.sbuffer_size;
-
- /* Do nothing if not enough points to smooth out */
- if ((num_points < 3) || (idx < 3) || (inf == 0.0f)) {
- return;
- }
-
- tGPspoint *points = (tGPspoint *)gpd->runtime.sbuffer;
- float steps = 4.0f;
- if (idx < 4) {
- steps--;
- }
-
- tGPspoint *pta = idx >= 4 ? &points[idx - 4] : NULL;
- tGPspoint *ptb = idx >= 3 ? &points[idx - 3] : NULL;
- tGPspoint *ptc = idx >= 2 ? &points[idx - 2] : NULL;
- tGPspoint *ptd = &points[idx - 1];
-
- float sco[2] = { 0.0f };
- float a[2], b[2], c[2], d[2];
- const float average_fac = 1.0f / steps;
-
- /* Compute smoothed coordinate by taking the ones nearby */
- if (pta) {
- copy_v2_v2(a, &pta->x);
- madd_v2_v2fl(sco, a, average_fac);
- }
- if (ptb) {
- copy_v2_v2(b, &ptb->x);
- madd_v2_v2fl(sco, b, average_fac);
- }
- if (ptc) {
- copy_v2_v2(c, &ptc->x);
- madd_v2_v2fl(sco, c, average_fac);
- }
- if (ptd) {
- copy_v2_v2(d, &ptd->x);
- madd_v2_v2fl(sco, d, 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);
+ bGPdata *gpd = p->gpd;
+ short num_points = gpd->runtime.sbuffer_size;
+
+ /* Do nothing if not enough points to smooth out */
+ if ((num_points < 3) || (idx < 3) || (inf == 0.0f)) {
+ return;
+ }
+
+ tGPspoint *points = (tGPspoint *)gpd->runtime.sbuffer;
+ float steps = 4.0f;
+ if (idx < 4) {
+ steps--;
+ }
+
+ tGPspoint *pta = idx >= 4 ? &points[idx - 4] : NULL;
+ tGPspoint *ptb = idx >= 3 ? &points[idx - 3] : NULL;
+ tGPspoint *ptc = idx >= 2 ? &points[idx - 2] : NULL;
+ tGPspoint *ptd = &points[idx - 1];
+
+ float sco[2] = {0.0f};
+ float a[2], b[2], c[2], d[2];
+ const float average_fac = 1.0f / steps;
+
+ /* Compute smoothed coordinate by taking the ones nearby */
+ if (pta) {
+ copy_v2_v2(a, &pta->x);
+ madd_v2_v2fl(sco, a, average_fac);
+ }
+ if (ptb) {
+ copy_v2_v2(b, &ptb->x);
+ madd_v2_v2fl(sco, b, average_fac);
+ }
+ if (ptc) {
+ copy_v2_v2(c, &ptc->x);
+ madd_v2_v2fl(sco, c, average_fac);
+ }
+ if (ptd) {
+ copy_v2_v2(d, &ptd->x);
+ madd_v2_v2fl(sco, d, 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);
}
/* 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)
+static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure, double curtime)
{
- bGPdata *gpd = p->gpd;
- tGPspoint *pt;
- ToolSettings *ts = p->scene->toolsettings;
-
- /* check painting mode */
- if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
- /* straight lines only - i.e. only store start and end point in buffer */
- if (gpd->runtime.sbuffer_size == 0) {
- /* first point in buffer (start 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);
-
- /* increment buffer size */
- gpd->runtime.sbuffer_size++;
- }
- else {
- /* just reset the endpoint to the latest value
- * - assume that pointers for this are always valid...
- */
- pt = ((tGPspoint *)(gpd->runtime.sbuffer) + 1);
-
- /* 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);
-
- /* now the buffer has 2 points (and shouldn't be allowed to get any larger) */
- gpd->runtime.sbuffer_size = 2;
- }
-
- /* can keep carrying on this way :) */
- return GP_STROKEADD_NORMAL;
- }
- else if (p->paintmode == GP_PAINTMODE_DRAW) { /* normal drawing */
- /* check if still room in buffer */
- if (gpd->runtime.sbuffer_size >= GP_STROKE_BUFFER_MAX)
- return GP_STROKEADD_OVERFLOW;
-
- /* get pointer to destination point */
- pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_size);
-
- /* store settings */
- copy_v2_v2(&pt->x, mval);
- pt->pressure = pressure;
- /* unused for annotations, but initialise for easier conversions to GP Object */
- pt->strength = 1.0f;
-
- /* point time */
- pt->time = (float)(curtime - p->inittime);
-
- /* increment counters */
- gpd->runtime.sbuffer_size++;
- /* 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_size - s);
- }
-
- /* check if another operation can still occur */
- if (gpd->runtime.sbuffer_size == GP_STROKE_BUFFER_MAX)
- return GP_STROKEADD_FULL;
- else
- return GP_STROKEADD_NORMAL;
- }
- else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
- /* 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;
-
- /* first time point is adding to temporary buffer -- need to allocate new point in stroke */
- if (gpd->runtime.sbuffer_size == 0) {
- gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1));
- gps->totpoints++;
- }
-
- pts = &gps->points[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 *v3d = p->sa->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);
- }
-
- /* convert screen-coordinates to appropriate coordinates (and store them) */
- gp_stroke_convertcoords(p, &pt->x, &pts->x, NULL);
-
- /* copy pressure and time */
- pts->pressure = pt->pressure;
- pts->strength = pt->strength;
- pts->time = pt->time;
-
- /* force fill recalc */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- }
-
- /* increment counters */
- if (gpd->runtime.sbuffer_size == 0)
- gpd->runtime.sbuffer_size++;
-
- return GP_STROKEADD_NORMAL;
- }
-
- /* return invalid state for now... */
- return GP_STROKEADD_INVALID;
+ bGPdata *gpd = p->gpd;
+ tGPspoint *pt;
+ ToolSettings *ts = p->scene->toolsettings;
+
+ /* check painting mode */
+ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
+ /* straight lines only - i.e. only store start and end point in buffer */
+ if (gpd->runtime.sbuffer_size == 0) {
+ /* first point in buffer (start 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);
+
+ /* increment buffer size */
+ gpd->runtime.sbuffer_size++;
+ }
+ else {
+ /* just reset the endpoint to the latest value
+ * - assume that pointers for this are always valid...
+ */
+ pt = ((tGPspoint *)(gpd->runtime.sbuffer) + 1);
+
+ /* 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);
+
+ /* now the buffer has 2 points (and shouldn't be allowed to get any larger) */
+ gpd->runtime.sbuffer_size = 2;
+ }
+
+ /* can keep carrying on this way :) */
+ return GP_STROKEADD_NORMAL;
+ }
+ else if (p->paintmode == GP_PAINTMODE_DRAW) { /* normal drawing */
+ /* check if still room in buffer */
+ if (gpd->runtime.sbuffer_size >= GP_STROKE_BUFFER_MAX)
+ return GP_STROKEADD_OVERFLOW;
+
+ /* get pointer to destination point */
+ pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_size);
+
+ /* store settings */
+ copy_v2_v2(&pt->x, mval);
+ pt->pressure = pressure;
+ /* unused for annotations, but initialise for easier conversions to GP Object */
+ pt->strength = 1.0f;
+
+ /* point time */
+ pt->time = (float)(curtime - p->inittime);
+
+ /* increment counters */
+ gpd->runtime.sbuffer_size++;
+ /* 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_size - s);
+ }
+
+ /* check if another operation can still occur */
+ if (gpd->runtime.sbuffer_size == GP_STROKE_BUFFER_MAX)
+ return GP_STROKEADD_FULL;
+ else
+ return GP_STROKEADD_NORMAL;
+ }
+ else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
+ /* 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;
+
+ /* first time point is adding to temporary buffer -- need to allocate new point in stroke */
+ if (gpd->runtime.sbuffer_size == 0) {
+ gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1));
+ gps->totpoints++;
+ }
+
+ pts = &gps->points[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 *v3d = p->sa->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);
+ }
+
+ /* convert screen-coordinates to appropriate coordinates (and store them) */
+ gp_stroke_convertcoords(p, &pt->x, &pts->x, NULL);
+
+ /* copy pressure and time */
+ pts->pressure = pt->pressure;
+ pts->strength = pt->strength;
+ pts->time = pt->time;
+
+ /* force fill recalc */
+ gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ }
+
+ /* increment counters */
+ if (gpd->runtime.sbuffer_size == 0)
+ gpd->runtime.sbuffer_size++;
+
+ return GP_STROKEADD_NORMAL;
+ }
+
+ /* return invalid state for now... */
+ return GP_STROKEADD_INVALID;
}
/* simplify a stroke (in buffer) before storing it
@@ -566,266 +562,270 @@ static short gp_stroke_addpoint(
*/
static void gp_stroke_simplify(tGPsdata *p)
{
- bGPdata *gpd = p->gpd;
- tGPspoint *old_points = (tGPspoint *)gpd->runtime.sbuffer;
- short num_points = gpd->runtime.sbuffer_size;
- short flag = gpd->runtime.sbuffer_sflag;
- short i, j;
-
- /* only simplify if simplification is enabled, and we're not doing a straight line */
- if (!(U.gp_settings & GP_PAINT_DOSIMPLIFY) || (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT))
- return;
-
- /* don't simplify if less than 4 points in buffer */
- if ((num_points <= 4) || (old_points == NULL))
- return;
-
- /* clear buffer (but don't free mem yet) so that we can write to it
- * - firstly set sbuffer to NULL, so a new one is allocated
- * - secondly, reset flag after, as it gets cleared auto
- */
- gpd->runtime.sbuffer = NULL;
- gp_session_validatebuffer(p);
- gpd->runtime.sbuffer_sflag = flag;
+ bGPdata *gpd = p->gpd;
+ tGPspoint *old_points = (tGPspoint *)gpd->runtime.sbuffer;
+ short num_points = gpd->runtime.sbuffer_size;
+ short flag = gpd->runtime.sbuffer_sflag;
+ short i, j;
+
+ /* only simplify if simplification is enabled, and we're not doing a straight line */
+ if (!(U.gp_settings & GP_PAINT_DOSIMPLIFY) || (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT))
+ return;
+
+ /* don't simplify if less than 4 points in buffer */
+ if ((num_points <= 4) || (old_points == NULL))
+ return;
+
+ /* clear buffer (but don't free mem yet) so that we can write to it
+ * - firstly set sbuffer to NULL, so a new one is allocated
+ * - secondly, reset flag after, as it gets cleared auto
+ */
+ gpd->runtime.sbuffer = NULL;
+ gp_session_validatebuffer(p);
+ gpd->runtime.sbuffer_sflag = flag;
/* macro used in loop to get position of new point
* - used due to the mixture of datatypes in use here
*/
#define GP_SIMPLIFY_AVPOINT(offs, sfac) \
- { \
- co[0] += (float)(old_points[offs].x * sfac); \
- co[1] += (float)(old_points[offs].y * sfac); \
- pressure += old_points[offs].pressure * sfac; \
- time += old_points[offs].time * sfac; \
- } (void)0
-
- /* XXX Here too, do not lose start and end points! */
- gp_stroke_addpoint(p, &old_points->x, old_points->pressure, p->inittime + (double)old_points->time);
- for (i = 0, j = 0; i < num_points; i++) {
- if (i - j == 3) {
- float co[2], pressure, time;
- float mco[2];
-
- /* initialize values */
- co[0] = 0.0f;
- co[1] = 0.0f;
- pressure = 0.0f;
- time = 0.0f;
-
- /* using macro, calculate new point */
- GP_SIMPLIFY_AVPOINT(j, -0.25f);
- GP_SIMPLIFY_AVPOINT(j + 1, 0.75f);
- GP_SIMPLIFY_AVPOINT(j + 2, 0.75f);
- GP_SIMPLIFY_AVPOINT(j + 3, -0.25f);
-
- /* set values for adding */
- mco[0] = co[0];
- mco[1] = co[1];
-
- /* ignore return values on this... assume to be ok for now */
- gp_stroke_addpoint(p, mco, pressure, p->inittime + (double)time);
-
- j += 2;
- }
- }
- gp_stroke_addpoint(
- p, &old_points[num_points - 1].x, old_points[num_points - 1].pressure,
- p->inittime + (double)old_points[num_points - 1].time);
-
- /* free old buffer */
- MEM_freeN(old_points);
+ { \
+ co[0] += (float)(old_points[offs].x * sfac); \
+ co[1] += (float)(old_points[offs].y * sfac); \
+ pressure += old_points[offs].pressure * sfac; \
+ time += old_points[offs].time * sfac; \
+ } \
+ (void)0
+
+ /* XXX Here too, do not lose start and end points! */
+ gp_stroke_addpoint(
+ p, &old_points->x, old_points->pressure, p->inittime + (double)old_points->time);
+ for (i = 0, j = 0; i < num_points; i++) {
+ if (i - j == 3) {
+ float co[2], pressure, time;
+ float mco[2];
+
+ /* initialize values */
+ co[0] = 0.0f;
+ co[1] = 0.0f;
+ pressure = 0.0f;
+ time = 0.0f;
+
+ /* using macro, calculate new point */
+ GP_SIMPLIFY_AVPOINT(j, -0.25f);
+ GP_SIMPLIFY_AVPOINT(j + 1, 0.75f);
+ GP_SIMPLIFY_AVPOINT(j + 2, 0.75f);
+ GP_SIMPLIFY_AVPOINT(j + 3, -0.25f);
+
+ /* set values for adding */
+ mco[0] = co[0];
+ mco[1] = co[1];
+
+ /* ignore return values on this... assume to be ok for now */
+ gp_stroke_addpoint(p, mco, pressure, p->inittime + (double)time);
+
+ j += 2;
+ }
+ }
+ gp_stroke_addpoint(p,
+ &old_points[num_points - 1].x,
+ old_points[num_points - 1].pressure,
+ p->inittime + (double)old_points[num_points - 1].time);
+
+ /* free old buffer */
+ MEM_freeN(old_points);
}
/* make a new stroke from the buffer data */
static void gp_stroke_newfrombuffer(tGPsdata *p)
{
- bGPdata *gpd = p->gpd;
- bGPDlayer *gpl = p->gpl;
- bGPDstroke *gps;
- bGPDspoint *pt;
- tGPspoint *ptc;
- ToolSettings *ts = p->scene->toolsettings;
-
- int i, totelem;
- /* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */
- int depth_margin = (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 4 : 0;
-
- /* get total number of points to allocate space for
- * - drawing straight-lines only requires the endpoints
- */
- if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT)
- totelem = (gpd->runtime.sbuffer_size >= 2) ? 2 : gpd->runtime.sbuffer_size;
- else
- totelem = gpd->runtime.sbuffer_size;
-
- /* exit with error if no valid points from this stroke */
- if (totelem == 0) {
- if (G.debug & G_DEBUG)
- printf("Error: No valid points in stroke buffer to convert (tot=%d)\n", gpd->runtime.sbuffer_size);
- 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) {
- 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 = gpl->thickness;
- gps->gradient_f = 1.0f;
- gps->gradient_s[0] = 1.0f;
- gps->gradient_s[1] = 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;
-
- /* allocate enough memory for a continuous array for storage points */
- gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
- gps->tot_triangles = 0;
-
- /* set pointer to first non-initialized point */
- pt = gps->points + (gps->totpoints - totelem);
-
- /* copy points from the buffer to the stroke */
- if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
- /* straight lines only -> only endpoints */
- {
- /* first point */
- ptc = gpd->runtime.sbuffer;
-
- /* convert screen-coordinates to appropriate coordinates (and store them) */
- gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
-
- /* copy pressure and time */
- pt->pressure = ptc->pressure;
- pt->strength = ptc->strength;
- CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
- pt->time = ptc->time;
-
- pt++;
- }
-
- if (totelem == 2) {
- /* last point if applicable */
- ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_size - 1);
-
- /* convert screen-coordinates to appropriate coordinates (and store them) */
- gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
-
- /* copy pressure and time */
- pt->pressure = ptc->pressure;
- pt->strength = ptc->strength;
- CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
- pt->time = ptc->time;
- }
- }
- 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);
-
- /* copy pressure and time */
- pt->pressure = ptc->pressure;
- pt->strength = ptc->strength;
- pt->time = ptc->time;
- }
- else {
- float *depth_arr = NULL;
-
- /* get an array of depths, far depths are blended */
- if (gpencil_project_check(p)) {
- int mval_i[2], mval_prev[2] = { 0 };
- int interp_depth = 0;
- int found_depth = 0;
-
- depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_size, "depth_points");
-
- for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size; 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) &&
- (i && (ED_view3d_autodist_depth_seg(p->ar, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0)))
- {
- interp_depth = true;
- }
- else {
- found_depth = true;
- }
-
- copy_v2_v2_int(mval_prev, mval_i);
- }
-
- if (found_depth == false) {
- /* eeh... not much we can do.. :/, ignore depth in this case, use the 3D cursor */
- for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--)
- depth_arr[i] = 0.9999f;
- }
- else {
- if (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE_ENDPOINTS) {
- /* remove all info between the valid endpoints */
- int first_valid = 0;
- int last_valid = 0;
-
- for (i = 0; i < gpd->runtime.sbuffer_size; i++) {
- if (depth_arr[i] != FLT_MAX)
- break;
- }
- first_valid = i;
-
- for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--) {
- if (depth_arr[i] != FLT_MAX)
- break;
- }
- last_valid = i;
-
- /* invalidate non-endpoints, so only blend between first and last */
- for (i = first_valid + 1; i < last_valid; i++)
- depth_arr[i] = FLT_MAX;
-
- interp_depth = true;
- }
-
- if (interp_depth) {
- interp_sparse_array(depth_arr, gpd->runtime.sbuffer_size, FLT_MAX);
- }
- }
- }
-
-
- pt = gps->points;
-
- /* convert all points (normal behavior) */
- for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size && ptc; i++, ptc++, pt++) {
- /* convert screen-coordinates to appropriate coordinates (and store them) */
- gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL);
-
- /* 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 (depth_arr)
- MEM_freeN(depth_arr);
- }
-
- /* add stroke to frame */
- BLI_addtail(&p->gpf->strokes, gps);
- gp_stroke_added_enable(p);
+ bGPdata *gpd = p->gpd;
+ bGPDlayer *gpl = p->gpl;
+ bGPDstroke *gps;
+ bGPDspoint *pt;
+ tGPspoint *ptc;
+ ToolSettings *ts = p->scene->toolsettings;
+
+ int i, totelem;
+ /* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */
+ int depth_margin = (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 4 : 0;
+
+ /* get total number of points to allocate space for
+ * - drawing straight-lines only requires the endpoints
+ */
+ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT)
+ totelem = (gpd->runtime.sbuffer_size >= 2) ? 2 : gpd->runtime.sbuffer_size;
+ else
+ totelem = gpd->runtime.sbuffer_size;
+
+ /* exit with error if no valid points from this stroke */
+ if (totelem == 0) {
+ if (G.debug & G_DEBUG)
+ printf("Error: No valid points in stroke buffer to convert (tot=%d)\n",
+ gpd->runtime.sbuffer_size);
+ 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) {
+ 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 = gpl->thickness;
+ gps->gradient_f = 1.0f;
+ gps->gradient_s[0] = 1.0f;
+ gps->gradient_s[1] = 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;
+
+ /* allocate enough memory for a continuous array for storage points */
+ gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ gps->tot_triangles = 0;
+
+ /* set pointer to first non-initialized point */
+ pt = gps->points + (gps->totpoints - totelem);
+
+ /* copy points from the buffer to the stroke */
+ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
+ /* straight lines only -> only endpoints */
+ {
+ /* first point */
+ ptc = gpd->runtime.sbuffer;
+
+ /* convert screen-coordinates to appropriate coordinates (and store them) */
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
+
+ /* copy pressure and time */
+ pt->pressure = ptc->pressure;
+ pt->strength = ptc->strength;
+ CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
+ pt->time = ptc->time;
+
+ pt++;
+ }
+
+ if (totelem == 2) {
+ /* last point if applicable */
+ ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_size - 1);
+
+ /* convert screen-coordinates to appropriate coordinates (and store them) */
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
+
+ /* copy pressure and time */
+ pt->pressure = ptc->pressure;
+ pt->strength = ptc->strength;
+ CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
+ pt->time = ptc->time;
+ }
+ }
+ 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);
+
+ /* copy pressure and time */
+ pt->pressure = ptc->pressure;
+ pt->strength = ptc->strength;
+ pt->time = ptc->time;
+ }
+ else {
+ float *depth_arr = NULL;
+
+ /* get an array of depths, far depths are blended */
+ if (gpencil_project_check(p)) {
+ int mval_i[2], mval_prev[2] = {0};
+ int interp_depth = 0;
+ int found_depth = 0;
+
+ depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_size, "depth_points");
+
+ for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size; 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) &&
+ (i && (ED_view3d_autodist_depth_seg(
+ p->ar, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0))) {
+ interp_depth = true;
+ }
+ else {
+ found_depth = true;
+ }
+
+ copy_v2_v2_int(mval_prev, mval_i);
+ }
+
+ if (found_depth == false) {
+ /* eeh... not much we can do.. :/, ignore depth in this case, use the 3D cursor */
+ for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--)
+ depth_arr[i] = 0.9999f;
+ }
+ else {
+ if (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE_ENDPOINTS) {
+ /* remove all info between the valid endpoints */
+ int first_valid = 0;
+ int last_valid = 0;
+
+ for (i = 0; i < gpd->runtime.sbuffer_size; i++) {
+ if (depth_arr[i] != FLT_MAX)
+ break;
+ }
+ first_valid = i;
+
+ for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--) {
+ if (depth_arr[i] != FLT_MAX)
+ break;
+ }
+ last_valid = i;
+
+ /* invalidate non-endpoints, so only blend between first and last */
+ for (i = first_valid + 1; i < last_valid; i++)
+ depth_arr[i] = FLT_MAX;
+
+ interp_depth = true;
+ }
+
+ if (interp_depth) {
+ interp_sparse_array(depth_arr, gpd->runtime.sbuffer_size, FLT_MAX);
+ }
+ }
+ }
+
+ pt = gps->points;
+
+ /* convert all points (normal behavior) */
+ for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size && ptc;
+ i++, ptc++, pt++) {
+ /* convert screen-coordinates to appropriate coordinates (and store them) */
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL);
+
+ /* 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 (depth_arr)
+ MEM_freeN(depth_arr);
+ }
+
+ /* add stroke to frame */
+ BLI_addtail(&p->gpf->strokes, gps);
+ gp_stroke_added_enable(p);
}
/* --- 'Eraser' for 'Paint' Tool ------ */
@@ -835,186 +835,186 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
*/
static void gp_free_stroke(bGPDframe *gpf, bGPDstroke *gps)
{
- if (gps->points) {
- MEM_freeN(gps->points);
- }
+ if (gps->points) {
+ MEM_freeN(gps->points);
+ }
- if (gps->dvert) {
- BKE_gpencil_free_stroke_weights(gps);
- MEM_freeN(gps->dvert);
- }
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
- if (gps->triangles) {
- MEM_freeN(gps->triangles);
- }
+ if (gps->triangles) {
+ MEM_freeN(gps->triangles);
+ }
- BLI_freelinkN(&gpf->strokes, gps);
+ BLI_freelinkN(&gpf->strokes, gps);
}
-
/* which which point is infront (result should only be used for comparison) */
static float view3d_point_depth(const RegionView3D *rv3d, const float co[3])
{
- if (rv3d->is_persp) {
- return ED_view3d_calc_zfac(rv3d, co, NULL);
- }
- else {
- return -dot_v3v3(rv3d->viewinv[2], co);
- }
+ if (rv3d->is_persp) {
+ return ED_view3d_calc_zfac(rv3d, co, NULL);
+ }
+ else {
+ return -dot_v3v3(rv3d->viewinv[2], co);
+ }
}
/* only erase stroke points that are visible (3d view) */
-static bool gp_stroke_eraser_is_occluded(tGPsdata *p, const bGPDspoint *pt, const int x, const int y)
+static bool gp_stroke_eraser_is_occluded(tGPsdata *p,
+ const bGPDspoint *pt,
+ const int x,
+ const int y)
{
- if ((p->sa->spacetype == SPACE_VIEW3D) &&
- (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH))
- {
- RegionView3D *rv3d = p->ar->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)) {
- const float depth_mval = view3d_point_depth(rv3d, mval_3d);
- const float depth_pt = view3d_point_depth(rv3d, &pt->x);
-
- if (depth_pt > depth_mval) {
- return true;
- }
- }
- }
- return false;
+ if ((p->sa->spacetype == SPACE_VIEW3D) && (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH)) {
+ RegionView3D *rv3d = p->ar->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)) {
+ const float depth_mval = view3d_point_depth(rv3d, mval_3d);
+ const float depth_pt = view3d_point_depth(rv3d, &pt->x);
+
+ if (depth_pt > depth_mval) {
+ return true;
+ }
+ }
+ }
+ return false;
}
/* eraser tool - evaluation per stroke */
/* TODO: this could really do with some optimization (KD-Tree/BVH?) */
-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)
+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)
{
- bGPDspoint *pt1, *pt2;
- int pc1[2] = {0};
- int pc2[2] = {0};
- int i;
- int mval_i[2];
- round_v2i_v2fl(mval_i, mval);
-
- if (gps->totpoints == 0) {
- /* just free stroke */
- gp_free_stroke(gpf, gps);
- }
- else if (gps->totpoints == 1) {
- /* only process if it hasn't been masked out... */
- if (!(p->flags & GP_PAINTFLAG_SELECTMASK) || (gps->points->flag & GP_SPOINT_SELECT)) {
- gp_point_to_xy(&p->gsc, gps, gps->points, &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])) {
- /* only check if point is inside */
- if (len_v2v2_int(mval_i, pc1) <= radius) {
- /* free stroke */
- gp_free_stroke(gpf, gps);
- }
- }
- }
- }
- else {
- /* Perform culling? */
- bool do_cull = false;
-
- /* Clear Tags
- *
- * Note: It's better this way, as we are sure that
- * we don't miss anything, though things will be
- * slightly slower as a result
- */
- for (i = 0; i < gps->totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
- pt->flag &= ~GP_SPOINT_TAG;
- }
-
- /* First Pass: Loop over the points in the stroke
- * 1) Thin out parts of the stroke under the brush
- * 2) Tag "too thin" parts for removal (in second pass)
- */
- for (i = 0; (i + 1) < gps->totpoints; i++) {
- /* get points to work with */
- pt1 = gps->points + i;
- pt2 = gps->points + i + 1;
-
- /* only process if it hasn't been masked out... */
- if ((p->flags & GP_PAINTFLAG_SELECTMASK) && !(gps->points->flag & GP_SPOINT_SELECT))
- continue;
-
- gp_point_to_xy(&p->gsc, gps, pt1, &pc1[0], &pc1[1]);
- gp_point_to_xy(&p->gsc, gps, pt2, &pc2[0], &pc2[1]);
-
- /* Check that point segment of the boundbox of the eraser 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
- * 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_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 */
- if (len_v2v2_int(mval_i, pc1) <= radius) {
- pt1->flag |= GP_SPOINT_TAG;
- }
- if (len_v2v2_int(mval_i, pc2) <= radius) {
- pt2->flag |= GP_SPOINT_TAG;
- }
- do_cull = true;
- }
- }
- }
- }
-
- /* Second Pass: Remove any points that are tagged */
- if (do_cull) {
- gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG, false, 0);
- }
- }
+ bGPDspoint *pt1, *pt2;
+ int pc1[2] = {0};
+ int pc2[2] = {0};
+ int i;
+ int mval_i[2];
+ round_v2i_v2fl(mval_i, mval);
+
+ if (gps->totpoints == 0) {
+ /* just free stroke */
+ gp_free_stroke(gpf, gps);
+ }
+ else if (gps->totpoints == 1) {
+ /* only process if it hasn't been masked out... */
+ if (!(p->flags & GP_PAINTFLAG_SELECTMASK) || (gps->points->flag & GP_SPOINT_SELECT)) {
+ gp_point_to_xy(&p->gsc, gps, gps->points, &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])) {
+ /* only check if point is inside */
+ if (len_v2v2_int(mval_i, pc1) <= radius) {
+ /* free stroke */
+ gp_free_stroke(gpf, gps);
+ }
+ }
+ }
+ }
+ else {
+ /* Perform culling? */
+ bool do_cull = false;
+
+ /* Clear Tags
+ *
+ * Note: It's better this way, as we are sure that
+ * we don't miss anything, though things will be
+ * slightly slower as a result
+ */
+ for (i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ pt->flag &= ~GP_SPOINT_TAG;
+ }
+
+ /* First Pass: Loop over the points in the stroke
+ * 1) Thin out parts of the stroke under the brush
+ * 2) Tag "too thin" parts for removal (in second pass)
+ */
+ for (i = 0; (i + 1) < gps->totpoints; i++) {
+ /* get points to work with */
+ pt1 = gps->points + i;
+ pt2 = gps->points + i + 1;
+
+ /* only process if it hasn't been masked out... */
+ if ((p->flags & GP_PAINTFLAG_SELECTMASK) && !(gps->points->flag & GP_SPOINT_SELECT))
+ continue;
+
+ gp_point_to_xy(&p->gsc, gps, pt1, &pc1[0], &pc1[1]);
+ gp_point_to_xy(&p->gsc, gps, pt2, &pc2[0], &pc2[1]);
+
+ /* Check that point segment of the boundbox of the eraser 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
+ * 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_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 */
+ if (len_v2v2_int(mval_i, pc1) <= radius) {
+ pt1->flag |= GP_SPOINT_TAG;
+ }
+ if (len_v2v2_int(mval_i, pc2) <= radius) {
+ pt2->flag |= GP_SPOINT_TAG;
+ }
+ do_cull = true;
+ }
+ }
+ }
+ }
+
+ /* Second Pass: Remove any points that are tagged */
+ if (do_cull) {
+ gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG, false, 0);
+ }
+ }
}
/* erase strokes which fall under the eraser strokes */
static void gp_stroke_doeraser(tGPsdata *p)
{
- bGPDframe *gpf = p->gpf;
- bGPDstroke *gps, *gpn;
- rcti rect;
-
- /* rect is rectangle of eraser */
- rect.xmin = p->mval[0] - p->radius;
- rect.ymin = p->mval[1] - p->radius;
- rect.xmax = p->mval[0] + p->radius;
- rect.ymax = p->mval[1] + p->radius;
-
- if (p->sa->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);
- }
- }
-
- /* loop over strokes of active layer only (session init already took care of ensuring validity),
- * checking segments for intersections to remove
- */
- for (gps = gpf->strokes.first; gps; gps = gpn) {
- gpn = gps->next;
- /* 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);
- }
- }
+ bGPDframe *gpf = p->gpf;
+ bGPDstroke *gps, *gpn;
+ rcti rect;
+
+ /* rect is rectangle of eraser */
+ rect.xmin = p->mval[0] - p->radius;
+ rect.ymin = p->mval[1] - p->radius;
+ rect.xmax = p->mval[0] + p->radius;
+ rect.ymax = p->mval[1] + p->radius;
+
+ if (p->sa->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);
+ }
+ }
+
+ /* loop over strokes of active layer only (session init already took care of ensuring validity),
+ * checking segments for intersections to remove
+ */
+ for (gps = gpf->strokes.first; gps; gps = gpn) {
+ gpn = gps->next;
+ /* 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);
+ }
+ }
}
/* ******************************************* */
@@ -1023,462 +1023,456 @@ static void gp_stroke_doeraser(tGPsdata *p)
/* clear the session buffers (call this before AND after a paint operation) */
static void gp_session_validatebuffer(tGPsdata *p)
{
- bGPdata *gpd = p->gpd;
-
- /* clear memory of buffer (or allocate it if starting a new session) */
- if (gpd->runtime.sbuffer) {
- /* printf("\t\tGP - reset sbuffer\n"); */
- memset(gpd->runtime.sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX);
- }
- else {
- /* printf("\t\tGP - allocate sbuffer\n"); */
- gpd->runtime.sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer");
- }
-
- /* reset indices */
- gpd->runtime.sbuffer_size = 0;
-
- /* reset flags */
- gpd->runtime.sbuffer_sflag = 0;
-
- /* reset inittime */
- p->inittime = 0.0;
+ bGPdata *gpd = p->gpd;
+
+ /* clear memory of buffer (or allocate it if starting a new session) */
+ if (gpd->runtime.sbuffer) {
+ /* printf("\t\tGP - reset sbuffer\n"); */
+ memset(gpd->runtime.sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX);
+ }
+ else {
+ /* printf("\t\tGP - allocate sbuffer\n"); */
+ gpd->runtime.sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX,
+ "gp_session_strokebuffer");
+ }
+
+ /* reset indices */
+ gpd->runtime.sbuffer_size = 0;
+
+ /* reset flags */
+ gpd->runtime.sbuffer_sflag = 0;
+
+ /* reset inittime */
+ p->inittime = 0.0;
}
/* (re)init new painting data */
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);
- ToolSettings *ts = CTX_data_tool_settings(C);
-
- /* make sure the active view (at the starting time) is a 3d-view */
- if (curarea == NULL) {
- p->status = GP_STATUS_ERROR;
- if (G.debug & G_DEBUG)
- printf("Error: No active view for painting\n");
- return 0;
- }
-
- /* pass on current scene and window */
- p->bmain = CTX_data_main(C);
- p->scene = CTX_data_scene(C);
- p->depsgraph = CTX_data_depsgraph(C);
- p->win = CTX_wm_window(C);
-
- unit_m4(p->imat);
- unit_m4(p->mat);
-
- 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->align_flag = &ts->annotate_v3d_align;
-
- if (ar->regiondata == NULL) {
- p->status = GP_STATUS_ERROR;
- if (G.debug & G_DEBUG)
- printf("Error: 3D-View active region doesn't have any region data, so cannot be drawable\n");
- return 0;
- }
- break;
- }
- case SPACE_NODE:
- {
- /* SpaceNode *snode = curarea->spacedata.first; */
-
- /* set current area */
- p->sa = curarea;
- p->ar = ar;
- p->v2d = &ar->v2d;
- p->align_flag = &ts->gpencil_v2d_align;
- break;
- }
- case SPACE_SEQ:
- {
- SpaceSeq *sseq = curarea->spacedata.first;
-
- /* set current area */
- p->sa = curarea;
- p->ar = ar;
- p->v2d = &ar->v2d;
- p->align_flag = &ts->gpencil_seq_align;
-
- /* check that gpencil data is allowed to be drawn */
- if (sseq->mainb == SEQ_DRAW_SEQUENCE) {
- p->status = GP_STATUS_ERROR;
- if (G.debug & G_DEBUG)
- printf("Error: In active view (sequencer), active mode doesn't support Grease Pencil\n");
- return 0;
- }
- break;
- }
- case SPACE_IMAGE:
- {
- /* SpaceImage *sima = curarea->spacedata.first; */
-
- /* set the current area */
- p->sa = curarea;
- p->ar = ar;
- p->v2d = &ar->v2d;
- p->align_flag = &ts->gpencil_ima_align;
- break;
- }
- case SPACE_CLIP:
- {
- SpaceClip *sc = curarea->spacedata.first;
- MovieClip *clip = ED_space_clip_get_clip(sc);
-
- if (clip == NULL) {
- p->status = GP_STATUS_ERROR;
- return false;
- }
-
- /* set the current area */
- p->sa = curarea;
- p->ar = ar;
- p->v2d = &ar->v2d;
- p->align_flag = &ts->gpencil_v2d_align;
-
- invert_m4_m4(p->imat, sc->unistabmat);
-
- /* custom color for new layer */
- p->custom_color[0] = 1.0f;
- p->custom_color[1] = 0.0f;
- p->custom_color[2] = 0.5f;
- p->custom_color[3] = 0.9f;
-
- if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
- int framenr = ED_space_clip_get_clip_frame_number(sc);
- MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking);
- MovieTrackingMarker *marker = track ? BKE_tracking_marker_get(track, framenr) : NULL;
-
- if (marker) {
- p->imat[3][0] -= marker->pos[0];
- p->imat[3][1] -= marker->pos[1];
- }
- else {
- p->status = GP_STATUS_ERROR;
- return false;
- }
- }
-
- invert_m4_m4(p->mat, p->imat);
- copy_m4_m4(p->gsc.mat, p->mat);
- break;
- }
- /* unsupported views */
- default:
- {
- p->status = GP_STATUS_ERROR;
- if (G.debug & G_DEBUG)
- printf("Error: Annotations are not supported in this editor\n");
- return 0;
- }
- }
-
- /* get gp-data */
- gpd_ptr = ED_gpencil_data_get_pointers(C, &p->ownerPtr);
- if ((gpd_ptr == NULL) || !ED_gpencil_data_owner_is_annotation(&p->ownerPtr)) {
- p->status = GP_STATUS_ERROR;
- if (G.debug & G_DEBUG)
- printf("Error: Current context doesn't allow for any Annotation data\n");
- return 0;
- }
- else {
- /* if no existing GPencil block exists, add one */
- if (*gpd_ptr == NULL) {
- bGPdata *gpd = BKE_gpencil_data_addnew(bmain, "Annotations");
- *gpd_ptr = gpd;
-
- /* mark datablock as being used for annotations */
- gpd->flag |= GP_DATA_ANNOTATIONS;
- }
- p->gpd = *gpd_ptr;
- }
-
- if (ED_gpencil_session_active() == 0) {
- /* initialize undo stack,
- * also, existing undo stack would make buffer drawn
- */
- gpencil_undo_init(p->gpd);
- }
-
- /* clear out buffer (stored in gp-data), in case something contaminated it */
- gp_session_validatebuffer(p);
-
- return 1;
+ Main *bmain = CTX_data_main(C);
+ bGPdata **gpd_ptr = NULL;
+ ScrArea *curarea = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+
+ /* make sure the active view (at the starting time) is a 3d-view */
+ if (curarea == NULL) {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf("Error: No active view for painting\n");
+ return 0;
+ }
+
+ /* pass on current scene and window */
+ p->bmain = CTX_data_main(C);
+ p->scene = CTX_data_scene(C);
+ p->depsgraph = CTX_data_depsgraph(C);
+ p->win = CTX_wm_window(C);
+
+ unit_m4(p->imat);
+ unit_m4(p->mat);
+
+ 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->align_flag = &ts->annotate_v3d_align;
+
+ if (ar->regiondata == NULL) {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf(
+ "Error: 3D-View active region doesn't have any region data, so cannot be "
+ "drawable\n");
+ return 0;
+ }
+ break;
+ }
+ case SPACE_NODE: {
+ /* SpaceNode *snode = curarea->spacedata.first; */
+
+ /* set current area */
+ p->sa = curarea;
+ p->ar = ar;
+ p->v2d = &ar->v2d;
+ p->align_flag = &ts->gpencil_v2d_align;
+ break;
+ }
+ case SPACE_SEQ: {
+ SpaceSeq *sseq = curarea->spacedata.first;
+
+ /* set current area */
+ p->sa = curarea;
+ p->ar = ar;
+ p->v2d = &ar->v2d;
+ p->align_flag = &ts->gpencil_seq_align;
+
+ /* check that gpencil data is allowed to be drawn */
+ if (sseq->mainb == SEQ_DRAW_SEQUENCE) {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf("Error: In active view (sequencer), active mode doesn't support Grease Pencil\n");
+ return 0;
+ }
+ break;
+ }
+ case SPACE_IMAGE: {
+ /* SpaceImage *sima = curarea->spacedata.first; */
+
+ /* set the current area */
+ p->sa = curarea;
+ p->ar = ar;
+ p->v2d = &ar->v2d;
+ p->align_flag = &ts->gpencil_ima_align;
+ break;
+ }
+ case SPACE_CLIP: {
+ SpaceClip *sc = curarea->spacedata.first;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+
+ if (clip == NULL) {
+ p->status = GP_STATUS_ERROR;
+ return false;
+ }
+
+ /* set the current area */
+ p->sa = curarea;
+ p->ar = ar;
+ p->v2d = &ar->v2d;
+ p->align_flag = &ts->gpencil_v2d_align;
+
+ invert_m4_m4(p->imat, sc->unistabmat);
+
+ /* custom color for new layer */
+ p->custom_color[0] = 1.0f;
+ p->custom_color[1] = 0.0f;
+ p->custom_color[2] = 0.5f;
+ p->custom_color[3] = 0.9f;
+
+ if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+ MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking);
+ MovieTrackingMarker *marker = track ? BKE_tracking_marker_get(track, framenr) : NULL;
+
+ if (marker) {
+ p->imat[3][0] -= marker->pos[0];
+ p->imat[3][1] -= marker->pos[1];
+ }
+ else {
+ p->status = GP_STATUS_ERROR;
+ return false;
+ }
+ }
+
+ invert_m4_m4(p->mat, p->imat);
+ copy_m4_m4(p->gsc.mat, p->mat);
+ break;
+ }
+ /* unsupported views */
+ default: {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf("Error: Annotations are not supported in this editor\n");
+ return 0;
+ }
+ }
+
+ /* get gp-data */
+ gpd_ptr = ED_gpencil_data_get_pointers(C, &p->ownerPtr);
+ if ((gpd_ptr == NULL) || !ED_gpencil_data_owner_is_annotation(&p->ownerPtr)) {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf("Error: Current context doesn't allow for any Annotation data\n");
+ return 0;
+ }
+ else {
+ /* if no existing GPencil block exists, add one */
+ if (*gpd_ptr == NULL) {
+ bGPdata *gpd = BKE_gpencil_data_addnew(bmain, "Annotations");
+ *gpd_ptr = gpd;
+
+ /* mark datablock as being used for annotations */
+ gpd->flag |= GP_DATA_ANNOTATIONS;
+ }
+ p->gpd = *gpd_ptr;
+ }
+
+ if (ED_gpencil_session_active() == 0) {
+ /* initialize undo stack,
+ * also, existing undo stack would make buffer drawn
+ */
+ gpencil_undo_init(p->gpd);
+ }
+
+ /* clear out buffer (stored in gp-data), in case something contaminated it */
+ gp_session_validatebuffer(p);
+
+ return 1;
}
/* init new painting session */
static tGPsdata *gp_session_initpaint(bContext *C)
{
- tGPsdata *p = NULL;
-
- /* create new context data */
- p = MEM_callocN(sizeof(tGPsdata), "Annotation Drawing Data");
-
- /* Try to initialise context data
- * WARNING: This may not always succeed (e.g. using GP in an annotation-only context)
- */
- if (gp_session_initdata(C, p) == 0) {
- /* Invalid state - Exit
- * NOTE: It should be safe to just free the data, since failing context checks should
- * only happen when no data has been allocated.
- */
- MEM_freeN(p);
- return NULL;
- }
-
- /* Radius for eraser circle is defined in userprefs */
- /* NOTE: we do this here, so that if we exit immediately,
- * erase size won't get lost
- */
- p->radius = U.gp_eraser;
-
- /* return context data for running paint operator */
- return p;
+ tGPsdata *p = NULL;
+
+ /* create new context data */
+ p = MEM_callocN(sizeof(tGPsdata), "Annotation Drawing Data");
+
+ /* Try to initialise context data
+ * WARNING: This may not always succeed (e.g. using GP in an annotation-only context)
+ */
+ if (gp_session_initdata(C, p) == 0) {
+ /* Invalid state - Exit
+ * NOTE: It should be safe to just free the data, since failing context checks should
+ * only happen when no data has been allocated.
+ */
+ MEM_freeN(p);
+ return NULL;
+ }
+
+ /* Radius for eraser circle is defined in userprefs */
+ /* NOTE: we do this here, so that if we exit immediately,
+ * erase size won't get lost
+ */
+ p->radius = U.gp_eraser;
+
+ /* return context data for running paint operator */
+ return p;
}
/* cleanup after a painting session */
static void gp_session_cleanup(tGPsdata *p)
{
- bGPdata *gpd = (p) ? p->gpd : NULL;
-
- /* error checking */
- if (gpd == NULL)
- return;
-
- /* free stroke buffer */
- if (gpd->runtime.sbuffer) {
- /* printf("\t\tGP - free sbuffer\n"); */
- MEM_freeN(gpd->runtime.sbuffer);
- gpd->runtime.sbuffer = NULL;
- }
-
- /* clear flags */
- gpd->runtime.sbuffer_size = 0;
- gpd->runtime.sbuffer_sflag = 0;
- p->inittime = 0.0;
+ bGPdata *gpd = (p) ? p->gpd : NULL;
+
+ /* error checking */
+ if (gpd == NULL)
+ return;
+
+ /* free stroke buffer */
+ if (gpd->runtime.sbuffer) {
+ /* printf("\t\tGP - free sbuffer\n"); */
+ MEM_freeN(gpd->runtime.sbuffer);
+ gpd->runtime.sbuffer = NULL;
+ }
+
+ /* clear flags */
+ gpd->runtime.sbuffer_size = 0;
+ gpd->runtime.sbuffer_sflag = 0;
+ p->inittime = 0.0;
}
static void gp_session_free(tGPsdata *p)
{
- MEM_freeN(p);
+ MEM_freeN(p);
}
-
/* init new stroke */
static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Depsgraph *depsgraph)
{
- Scene *scene = p->scene;
- ToolSettings *ts = scene->toolsettings;
-
- /* get active layer (or add a new one if non-existent) */
- p->gpl = BKE_gpencil_layer_getactive(p->gpd);
- if (p->gpl == NULL) {
- /* tag for annotations */
- p->gpd->flag |= GP_DATA_ANNOTATIONS;
- p->gpl = BKE_gpencil_layer_addnew(p->gpd, DATA_("Note"), true);
-
- if (p->custom_color[3])
- copy_v3_v3(p->gpl->color, p->custom_color);
- }
- if (p->gpl->flag & GP_LAYER_LOCKED) {
- p->status = GP_STATUS_ERROR;
- if (G.debug & G_DEBUG)
- printf("Error: Cannot paint on locked layer\n");
- return;
- }
-
- /* get active frame (add a new one if not matching frame) */
- if (paintmode == GP_PAINTMODE_ERASER) {
- /* Eraser mode:
- * 1) Only allow erasing on the active layer (unlike for 3d-art Grease Pencil),
- * since we won't be exposing layer locking in the UI
- * 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;
-
- if (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;
- }
- }
-
- /* Ensure active frame is set correctly... */
- p->gpf = p->gpl->actframe;
-
- /* Restrict eraser to only affecting selected strokes, if the "selection mask" is on
- * (though this is only available in editmode)
- */
- if (p->gpd->flag & GP_DATA_STROKE_EDITMODE) {
- if (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_SELECT_MASK) {
- p->flags |= GP_PAINTFLAG_SELECTMASK;
- }
- }
-
- if (has_layer_to_erase == false) {
- p->status = GP_STATUS_CAPTURE;
- //if (G.debug & G_DEBUG)
- printf("Error: Eraser will not be affecting anything (gpencil_paint_init)\n");
- return;
- }
- }
- else {
- /* Drawing Modes - Add a new frame if needed on the active layer */
- short add_frame_mode = GP_GETFRAME_ADD_NEW;
-
- if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST)
- add_frame_mode = GP_GETFRAME_ADD_COPY;
- else
- add_frame_mode = GP_GETFRAME_ADD_NEW;
-
- p->gpf = BKE_gpencil_layer_getframe(p->gpl, CFRA, add_frame_mode);
-
- if (p->gpf == NULL) {
- p->status = GP_STATUS_ERROR;
- if (G.debug & G_DEBUG)
- printf("Error: No frame created (gpencil_paint_init)\n");
- return;
- }
- else {
- p->gpf->flag |= GP_FRAME_PAINT;
- }
- }
-
- /* set 'eraser' for this stroke if using eraser */
- p->paintmode = paintmode;
- if (p->paintmode == GP_PAINTMODE_ERASER) {
- p->gpd->runtime.sbuffer_sflag |= GP_STROKE_ERASER;
-
- /* check if we should respect depth while erasing */
- if (p->sa->spacetype == SPACE_VIEW3D) {
- if (p->gpl->flag & GP_LAYER_NO_XRAY) {
- p->flags |= GP_PAINTFLAG_V3D_ERASER_DEPTH;
- }
- }
- }
- else {
- /* 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->gpl->flag & GP_LAYER_NO_XRAY) {
- p->flags &= ~GP_PAINTFLAG_V3D_ERASER_DEPTH;
- }
- }
- }
-
- /* set 'initial run' flag, which is only used to denote when a new stroke is starting */
- p->flags |= GP_PAINTFLAG_FIRSTRUN;
-
-
- /* 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;
-
- /* 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->subrect = &p->subrect_data;
- }
- }
- }
-
- /* init stroke point space-conversion settings... */
- p->gsc.gpd = p->gpd;
- p->gsc.gpl = p->gpl;
-
- p->gsc.sa = p->sa;
- p->gsc.ar = p->ar;
- p->gsc.v2d = p->v2d;
-
- p->gsc.subrect_data = p->subrect_data;
- p->gsc.subrect = p->subrect;
-
- copy_m4_m4(p->gsc.mat, p->mat);
-
-
- /* check if points will need to be made in view-aligned space */
- if (*p->align_flag & GP_PROJECT_VIEWSPACE) {
- switch (p->sa->spacetype) {
- case SPACE_VIEW3D:
- {
- p->gpd->runtime.sbuffer_sflag |= GP_STROKE_3DSPACE;
- break;
- }
- case SPACE_NODE:
- case SPACE_SEQ:
- case SPACE_IMAGE:
- case SPACE_CLIP:
- {
- p->gpd->runtime.sbuffer_sflag |= GP_STROKE_2DSPACE;
- break;
- }
- }
- }
+ Scene *scene = p->scene;
+ ToolSettings *ts = scene->toolsettings;
+
+ /* get active layer (or add a new one if non-existent) */
+ p->gpl = BKE_gpencil_layer_getactive(p->gpd);
+ if (p->gpl == NULL) {
+ /* tag for annotations */
+ p->gpd->flag |= GP_DATA_ANNOTATIONS;
+ p->gpl = BKE_gpencil_layer_addnew(p->gpd, DATA_("Note"), true);
+
+ if (p->custom_color[3])
+ copy_v3_v3(p->gpl->color, p->custom_color);
+ }
+ if (p->gpl->flag & GP_LAYER_LOCKED) {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf("Error: Cannot paint on locked layer\n");
+ return;
+ }
+
+ /* get active frame (add a new one if not matching frame) */
+ if (paintmode == GP_PAINTMODE_ERASER) {
+ /* Eraser mode:
+ * 1) Only allow erasing on the active layer (unlike for 3d-art Grease Pencil),
+ * since we won't be exposing layer locking in the UI
+ * 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;
+
+ if (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;
+ }
+ }
+
+ /* Ensure active frame is set correctly... */
+ p->gpf = p->gpl->actframe;
+
+ /* Restrict eraser to only affecting selected strokes, if the "selection mask" is on
+ * (though this is only available in editmode)
+ */
+ if (p->gpd->flag & GP_DATA_STROKE_EDITMODE) {
+ if (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_SELECT_MASK) {
+ p->flags |= GP_PAINTFLAG_SELECTMASK;
+ }
+ }
+
+ if (has_layer_to_erase == false) {
+ p->status = GP_STATUS_CAPTURE;
+ //if (G.debug & G_DEBUG)
+ printf("Error: Eraser will not be affecting anything (gpencil_paint_init)\n");
+ return;
+ }
+ }
+ else {
+ /* Drawing Modes - Add a new frame if needed on the active layer */
+ short add_frame_mode = GP_GETFRAME_ADD_NEW;
+
+ if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST)
+ add_frame_mode = GP_GETFRAME_ADD_COPY;
+ else
+ add_frame_mode = GP_GETFRAME_ADD_NEW;
+
+ p->gpf = BKE_gpencil_layer_getframe(p->gpl, CFRA, add_frame_mode);
+
+ if (p->gpf == NULL) {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf("Error: No frame created (gpencil_paint_init)\n");
+ return;
+ }
+ else {
+ p->gpf->flag |= GP_FRAME_PAINT;
+ }
+ }
+
+ /* set 'eraser' for this stroke if using eraser */
+ p->paintmode = paintmode;
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ p->gpd->runtime.sbuffer_sflag |= GP_STROKE_ERASER;
+
+ /* check if we should respect depth while erasing */
+ if (p->sa->spacetype == SPACE_VIEW3D) {
+ if (p->gpl->flag & GP_LAYER_NO_XRAY) {
+ p->flags |= GP_PAINTFLAG_V3D_ERASER_DEPTH;
+ }
+ }
+ }
+ else {
+ /* 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->gpl->flag & GP_LAYER_NO_XRAY) {
+ p->flags &= ~GP_PAINTFLAG_V3D_ERASER_DEPTH;
+ }
+ }
+ }
+
+ /* set 'initial run' flag, which is only used to denote when a new stroke is starting */
+ p->flags |= GP_PAINTFLAG_FIRSTRUN;
+
+ /* 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;
+
+ /* 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->subrect = &p->subrect_data;
+ }
+ }
+ }
+
+ /* init stroke point space-conversion settings... */
+ p->gsc.gpd = p->gpd;
+ p->gsc.gpl = p->gpl;
+
+ p->gsc.sa = p->sa;
+ p->gsc.ar = p->ar;
+ p->gsc.v2d = p->v2d;
+
+ p->gsc.subrect_data = p->subrect_data;
+ p->gsc.subrect = p->subrect;
+
+ copy_m4_m4(p->gsc.mat, p->mat);
+
+ /* check if points will need to be made in view-aligned space */
+ if (*p->align_flag & GP_PROJECT_VIEWSPACE) {
+ switch (p->sa->spacetype) {
+ case SPACE_VIEW3D: {
+ p->gpd->runtime.sbuffer_sflag |= GP_STROKE_3DSPACE;
+ break;
+ }
+ case SPACE_NODE:
+ case SPACE_SEQ:
+ case SPACE_IMAGE:
+ case SPACE_CLIP: {
+ p->gpd->runtime.sbuffer_sflag |= GP_STROKE_2DSPACE;
+ break;
+ }
+ }
+ }
}
/* finish off a stroke (clears buffer, but doesn't finish the paint operation) */
static void gp_paint_strokeend(tGPsdata *p)
{
- ToolSettings *ts = p->scene->toolsettings;
- /* for surface sketching, need to set the right OpenGL context stuff so that
- * the conversions will project the values correctly...
- */
- if (gpencil_project_check(p)) {
- View3D *v3d = p->sa->spacedata.first;
-
- /* need to restore the original projection settings before packing up */
- 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);
- }
-
- /* check if doing eraser or not */
- if ((p->gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) {
- /* simplify stroke before transferring? */
- gp_stroke_simplify(p);
-
- /* transfer stroke to frame */
- gp_stroke_newfrombuffer(p);
- }
-
- /* clean up buffer now */
- gp_session_validatebuffer(p);
+ ToolSettings *ts = p->scene->toolsettings;
+ /* for surface sketching, need to set the right OpenGL context stuff so that
+ * the conversions will project the values correctly...
+ */
+ if (gpencil_project_check(p)) {
+ View3D *v3d = p->sa->spacedata.first;
+
+ /* need to restore the original projection settings before packing up */
+ 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);
+ }
+
+ /* check if doing eraser or not */
+ if ((p->gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) {
+ /* simplify stroke before transferring? */
+ gp_stroke_simplify(p);
+
+ /* transfer stroke to frame */
+ gp_stroke_newfrombuffer(p);
+ }
+
+ /* clean up buffer now */
+ gp_session_validatebuffer(p);
}
/* finish off stroke painting operation */
static void gp_paint_cleanup(tGPsdata *p)
{
- /* p->gpd==NULL happens when stroke failed to initialize,
- * for example when GP is hidden in current space (sergey)
- */
- if (p->gpd) {
- /* finish off a stroke */
- gp_paint_strokeend(p);
- }
-
- /* "unlock" frame */
- if (p->gpf)
- p->gpf->flag &= ~GP_FRAME_PAINT;
+ /* p->gpd==NULL happens when stroke failed to initialize,
+ * for example when GP is hidden in current space (sergey)
+ */
+ if (p->gpd) {
+ /* finish off a stroke */
+ gp_paint_strokeend(p);
+ }
+
+ /* "unlock" frame */
+ if (p->gpf)
+ p->gpf->flag &= ~GP_FRAME_PAINT;
}
/* ------------------------------- */
@@ -1486,216 +1480,227 @@ static void gp_paint_cleanup(tGPsdata *p)
/* Helper callback for drawing the cursor itself */
static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
{
- tGPsdata *p = (tGPsdata *)p_ptr;
+ tGPsdata *p = (tGPsdata *)p_ptr;
- if (p->paintmode == GP_PAINTMODE_ERASER) {
- GPUVertFormat *format = immVertexFormat();
- const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ GPUVertFormat *format = immVertexFormat();
+ const uint shdr_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_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_line_smooth(true);
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- immUniformColor4ub(255, 100, 100, 20);
- imm_draw_circle_fill_2d(shdr_pos, x, y, p->radius, 40);
+ immUniformColor4ub(255, 100, 100, 20);
+ imm_draw_circle_fill_2d(shdr_pos, x, y, p->radius, 40);
- immUnbindProgram();
+ immUnbindProgram();
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
- immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f);
- immUniform1i("colors_len", 0); /* "simple" mode */
- immUniform1f("dash_width", 12.0f);
- immUniform1f("dash_factor", 0.5f);
+ immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f);
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniform1f("dash_width", 12.0f);
+ immUniform1f("dash_factor", 0.5f);
- imm_draw_circle_wire_2d(
- shdr_pos, x, y, p->radius,
- /* XXX Dashed shader gives bad results with sets of small segments currently,
- * temp hack around the issue. :( */
- max_ii(8, p->radius / 2)); /* was fixed 40 */
+ imm_draw_circle_wire_2d(
+ shdr_pos,
+ x,
+ y,
+ p->radius,
+ /* XXX Dashed shader gives bad results with sets of small segments currently,
+ * temp hack around the issue. :( */
+ max_ii(8, p->radius / 2)); /* was fixed 40 */
- immUnbindProgram();
+ immUnbindProgram();
- GPU_blend(false);
- GPU_line_smooth(false);
- }
+ GPU_blend(false);
+ GPU_line_smooth(false);
+ }
}
/* Turn brush cursor in 3D view on/off */
static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short enable)
{
- if (p->erasercursor && !enable) {
- /* clear cursor */
- WM_paint_cursor_end(CTX_wm_manager(C), p->erasercursor);
- p->erasercursor = NULL;
- }
- else if (enable && !p->erasercursor) {
- /* enable cursor */
- p->erasercursor = WM_paint_cursor_activate(
- CTX_wm_manager(C),
- SPACE_TYPE_ANY, RGN_TYPE_ANY,
- NULL, /* XXX */
- gpencil_draw_eraser, p);
- }
+ if (p->erasercursor && !enable) {
+ /* clear cursor */
+ WM_paint_cursor_end(CTX_wm_manager(C), p->erasercursor);
+ p->erasercursor = NULL;
+ }
+ else if (enable && !p->erasercursor) {
+ /* enable cursor */
+ p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C),
+ SPACE_TYPE_ANY,
+ RGN_TYPE_ANY,
+ NULL, /* XXX */
+ gpencil_draw_eraser,
+ p);
+ }
}
/* Check if tablet eraser is being used (when processing events) */
static bool gpencil_is_tablet_eraser_active(const wmEvent *event)
{
- if (event->tablet_data) {
- const wmTabletData *wmtab = event->tablet_data;
- return (wmtab->Active == EVT_TABLET_ERASER);
- }
+ if (event->tablet_data) {
+ const wmTabletData *wmtab = event->tablet_data;
+ return (wmtab->Active == EVT_TABLET_ERASER);
+ }
- return false;
+ return false;
}
/* ------------------------------- */
static void gpencil_draw_exit(bContext *C, wmOperator *op)
{
- tGPsdata *p = op->customdata;
-
- /* restore cursor to indicate end of drawing */
- WM_cursor_modal_restore(CTX_wm_window(C));
-
- /* don't assume that operator data exists at all */
- if (p) {
- /* check size of buffer before cleanup, to determine if anything happened here */
- if (p->paintmode == GP_PAINTMODE_ERASER) {
- /* turn off radial brush cursor */
- gpencil_draw_toggle_eraser_cursor(C, p, false);
- }
-
- /* always store the new eraser size to be used again next time
- * NOTE: Do this even when not in eraser mode, as eraser may
- * have been toggled at some point.
- */
- U.gp_eraser = p->radius;
-
- /* clear undo stack */
- gpencil_undo_finish();
-
- /* cleanup */
- gp_paint_cleanup(p);
- gp_session_cleanup(p);
- gp_session_free(p);
- p = NULL;
- }
-
- op->customdata = NULL;
+ tGPsdata *p = op->customdata;
+
+ /* restore cursor to indicate end of drawing */
+ WM_cursor_modal_restore(CTX_wm_window(C));
+
+ /* don't assume that operator data exists at all */
+ if (p) {
+ /* check size of buffer before cleanup, to determine if anything happened here */
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ /* turn off radial brush cursor */
+ gpencil_draw_toggle_eraser_cursor(C, p, false);
+ }
+
+ /* always store the new eraser size to be used again next time
+ * NOTE: Do this even when not in eraser mode, as eraser may
+ * have been toggled at some point.
+ */
+ U.gp_eraser = p->radius;
+
+ /* clear undo stack */
+ gpencil_undo_finish();
+
+ /* cleanup */
+ gp_paint_cleanup(p);
+ gp_session_cleanup(p);
+ gp_session_free(p);
+ p = NULL;
+ }
+
+ op->customdata = NULL;
}
static void gpencil_draw_cancel(bContext *C, wmOperator *op)
{
- /* this is just a wrapper around exit() */
- gpencil_draw_exit(C, op);
+ /* this is just a wrapper around exit() */
+ gpencil_draw_exit(C, op);
}
/* ------------------------------- */
-
static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event)
{
- tGPsdata *p;
- eGPencil_PaintModes paintmode = RNA_enum_get(op->ptr, "mode");
-
- /* check context */
- p = op->customdata = gp_session_initpaint(C);
- if ((p == NULL) || (p->status == GP_STATUS_ERROR)) {
- /* something wasn't set correctly in context */
- gpencil_draw_exit(C, op);
- return 0;
- }
-
- /* init painting data */
- gp_paint_initstroke(p, paintmode, CTX_data_depsgraph(C));
- if (p->status == GP_STATUS_ERROR) {
- gpencil_draw_exit(C, op);
- return 0;
- }
-
- if (event != NULL) {
- p->keymodifier = event->keymodifier;
- }
- else {
- p->keymodifier = -1;
- }
-
- /* everything is now setup ok */
- return 1;
+ tGPsdata *p;
+ eGPencil_PaintModes paintmode = RNA_enum_get(op->ptr, "mode");
+
+ /* check context */
+ p = op->customdata = gp_session_initpaint(C);
+ if ((p == NULL) || (p->status == GP_STATUS_ERROR)) {
+ /* something wasn't set correctly in context */
+ gpencil_draw_exit(C, op);
+ return 0;
+ }
+
+ /* init painting data */
+ gp_paint_initstroke(p, paintmode, CTX_data_depsgraph(C));
+ if (p->status == GP_STATUS_ERROR) {
+ gpencil_draw_exit(C, op);
+ return 0;
+ }
+
+ if (event != NULL) {
+ p->keymodifier = event->keymodifier;
+ }
+ else {
+ p->keymodifier = -1;
+ }
+
+ /* everything is now setup ok */
+ return 1;
}
-
/* ------------------------------- */
/* ensure that the correct cursor icon is set */
static void gpencil_draw_cursor_set(tGPsdata *p)
{
- if (p->paintmode == GP_PAINTMODE_ERASER)
- WM_cursor_modal_set(p->win, BC_CROSSCURSOR); /* XXX need a better cursor */
- else
- WM_cursor_modal_set(p->win, BC_PAINTBRUSHCURSOR);
+ if (p->paintmode == GP_PAINTMODE_ERASER)
+ WM_cursor_modal_set(p->win, BC_CROSSCURSOR); /* XXX need a better cursor */
+ else
+ WM_cursor_modal_set(p->win, BC_PAINTBRUSHCURSOR);
}
/* update UI indicators of status, including cursor and header prints */
static void gpencil_draw_status_indicators(bContext *C, tGPsdata *p)
{
- /* header prints */
- switch (p->status) {
- case GP_STATUS_PAINTING:
- switch (p->paintmode) {
- case GP_PAINTMODE_DRAW_POLY:
- /* Provide usage tips, since this is modal, and unintuitive without hints */
- ED_workspace_status_text(C, IFACE_("Annotation Create Poly: LMB click to place next stroke vertex | "
- "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.
- */
- break;
- }
- break;
-
- case GP_STATUS_IDLING:
- /* print status info */
- switch (p->paintmode) {
- case GP_PAINTMODE_ERASER:
- ED_workspace_status_text(C, IFACE_("Annotation Eraser: Hold and drag LMB or RMB to erase | "
- "ESC/Enter to end (or click outside this area)"));
- break;
- case GP_PAINTMODE_DRAW_STRAIGHT:
- ED_workspace_status_text(C, IFACE_("Annotation Line Draw: Hold and drag LMB to draw | "
- "ESC/Enter to end (or click outside this area)"));
- break;
- case GP_PAINTMODE_DRAW:
- ED_workspace_status_text(C, IFACE_("Annotation Freehand Draw: Hold and drag LMB to draw | "
- "E/ESC/Enter to end (or click outside this area)"));
- break;
- case GP_PAINTMODE_DRAW_POLY:
- ED_workspace_status_text(C, IFACE_("Annotation Create Poly: LMB click to place next stroke vertex | "
- "ESC/Enter to end (or click outside this area)"));
- break;
-
- default: /* unhandled future cases */
- ED_workspace_status_text(C, IFACE_("Annotation Session: ESC/Enter to end (or click outside this area)"));
- break;
- }
- break;
-
- case GP_STATUS_ERROR:
- case GP_STATUS_DONE:
- case GP_STATUS_CAPTURE:
- /* clear status string */
- ED_workspace_status_text(C, NULL);
- break;
- }
+ /* header prints */
+ switch (p->status) {
+ case GP_STATUS_PAINTING:
+ switch (p->paintmode) {
+ case GP_PAINTMODE_DRAW_POLY:
+ /* Provide usage tips, since this is modal, and unintuitive without hints */
+ ED_workspace_status_text(
+ C,
+ IFACE_("Annotation Create Poly: LMB click to place next stroke vertex | "
+ "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.
+ */
+ break;
+ }
+ break;
+
+ case GP_STATUS_IDLING:
+ /* print status info */
+ switch (p->paintmode) {
+ case GP_PAINTMODE_ERASER:
+ ED_workspace_status_text(C,
+ IFACE_("Annotation Eraser: Hold and drag LMB or RMB to erase | "
+ "ESC/Enter to end (or click outside this area)"));
+ break;
+ case GP_PAINTMODE_DRAW_STRAIGHT:
+ ED_workspace_status_text(C,
+ IFACE_("Annotation Line Draw: Hold and drag LMB to draw | "
+ "ESC/Enter to end (or click outside this area)"));
+ break;
+ case GP_PAINTMODE_DRAW:
+ ED_workspace_status_text(C,
+ IFACE_("Annotation Freehand Draw: Hold and drag LMB to draw | "
+ "E/ESC/Enter to end (or click outside this area)"));
+ break;
+ case GP_PAINTMODE_DRAW_POLY:
+ ED_workspace_status_text(
+ C,
+ IFACE_("Annotation Create Poly: LMB click to place next stroke vertex | "
+ "ESC/Enter to end (or click outside this area)"));
+ break;
+
+ default: /* unhandled future cases */
+ ED_workspace_status_text(
+ C, IFACE_("Annotation Session: ESC/Enter to end (or click outside this area)"));
+ break;
+ }
+ break;
+
+ case GP_STATUS_ERROR:
+ case GP_STATUS_DONE:
+ case GP_STATUS_CAPTURE:
+ /* clear status string */
+ ED_workspace_status_text(C, NULL);
+ break;
+ }
}
/* ------------------------------- */
@@ -1703,169 +1708,170 @@ 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(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph)
{
- /* handle drawing/erasing -> test for erasing first */
- if (p->paintmode == GP_PAINTMODE_ERASER) {
- /* do 'live' erasing now */
- gp_stroke_doeraser(p);
-
- /* store used values */
- p->mvalo[0] = p->mval[0];
- p->mvalo[1] = p->mval[1];
- 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)) {
- /* 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 */
- p->mvalo[0] = p->mval[0];
- p->mvalo[1] = p->mval[1];
- p->opressure = p->pressure;
- p->ocurtime = p->curtime;
- }
+ /* handle drawing/erasing -> test for erasing first */
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ /* do 'live' erasing now */
+ gp_stroke_doeraser(p);
+
+ /* store used values */
+ p->mvalo[0] = p->mval[0];
+ p->mvalo[1] = p->mval[1];
+ 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)) {
+ /* 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 */
+ p->mvalo[0] = p->mval[0];
+ p->mvalo[1] = p->mval[1];
+ p->opressure = p->pressure;
+ p->ocurtime = p->curtime;
+ }
}
/* handle draw event */
-static void annotation_draw_apply_event(wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y)
+static void annotation_draw_apply_event(
+ wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y)
{
- tGPsdata *p = op->customdata;
- PointerRNA itemptr;
- float mousef[2];
- int tablet = 0;
-
- /* convert from window-space to area-space mouse coordinates
- * add any x,y override position for fake events
- */
- p->mval[0] = (float)event->mval[0] - x;
- p->mval[1] = (float)event->mval[1] - y;
-
- /* verify key status for straight lines */
- 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]));
- if ((dx > 0) || (dy > 0)) {
- /* check mouse direction to replace the other coordinate with previous values */
- if (dx >= dy) {
- /* horizontal */
- p->straight[0] = 1;
- p->straight[1] = p->mval[1]; /* save y */
- }
- else {
- /* vertical */
- p->straight[0] = 2;
- p->straight[1] = p->mval[0]; /* save x */
- }
- }
- }
- }
- else {
- p->straight[0] = 0;
- }
-
- p->curtime = PIL_check_seconds_timer();
-
- /* handle pressure sensitivity (which is supplied by tablets) */
- if (event->tablet_data) {
- const wmTabletData *wmtab = event->tablet_data;
-
- tablet = (wmtab->Active != EVT_TABLET_NONE);
- p->pressure = wmtab->Pressure;
-
- /* Hack for pressure sensitive eraser on D+RMB when using a tablet:
- * The pen has to float over the tablet surface, resulting in
- * zero pressure (T47101). Ignore pressure values if floating
- * (i.e. "effectively zero" pressure), and only when the "active"
- * end is the stylus (i.e. the default when not eraser)
- */
- if (p->paintmode == GP_PAINTMODE_ERASER) {
- if ((wmtab->Active != EVT_TABLET_ERASER) && (p->pressure < 0.001f)) {
- p->pressure = 1.0f;
- }
- }
- }
- else {
- /* No tablet data -> No pressure info is available */
- p->pressure = 1.0f;
- }
-
- /* special exception for start of strokes (i.e. maybe for just a dot) */
- if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
- p->flags &= ~GP_PAINTFLAG_FIRSTRUN;
-
- p->mvalo[0] = p->mval[0];
- p->mvalo[1] = p->mval[1];
- p->opressure = p->pressure;
- p->inittime = p->ocurtime = p->curtime;
- p->straight[0] = 0;
- p->straight[1] = 0;
-
- /* special exception here for too high pressure values on first touch in
- * windows for some tablets, then we just skip first touch...
- */
- if (tablet && (p->pressure >= 0.99f))
- return;
- }
-
- /* check if alt key is pressed and limit to straight lines */
- if ((p->paintmode != GP_PAINTMODE_ERASER) && (p->straight[0] != 0)) {
- if (p->straight[0] == 1) {
- /* horizontal */
- p->mval[1] = p->straight[1]; /* replace y */
- }
- else {
- /* vertical */
- p->mval[0] = p->straight[1]; /* replace x */
- }
- }
-
- /* fill in stroke data (not actually used directly by gpencil_draw_apply) */
- RNA_collection_add(op->ptr, "stroke", &itemptr);
-
- mousef[0] = p->mval[0];
- mousef[1] = p->mval[1];
- RNA_float_set_array(&itemptr, "mouse", mousef);
- RNA_float_set(&itemptr, "pressure", p->pressure);
- RNA_boolean_set(&itemptr, "is_start", (p->flags & GP_PAINTFLAG_FIRSTRUN) != 0);
-
- RNA_float_set(&itemptr, "time", p->curtime - p->inittime);
-
- /* apply the current latest drawing point */
- gpencil_draw_apply(op, p, depsgraph);
-
- /* force refresh */
- /* just active area for now, since doing whole screen is too slow */
- ED_region_tag_redraw(p->ar);
+ tGPsdata *p = op->customdata;
+ PointerRNA itemptr;
+ float mousef[2];
+ int tablet = 0;
+
+ /* convert from window-space to area-space mouse coordinates
+ * add any x,y override position for fake events
+ */
+ p->mval[0] = (float)event->mval[0] - x;
+ p->mval[1] = (float)event->mval[1] - y;
+
+ /* verify key status for straight lines */
+ 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]));
+ if ((dx > 0) || (dy > 0)) {
+ /* check mouse direction to replace the other coordinate with previous values */
+ if (dx >= dy) {
+ /* horizontal */
+ p->straight[0] = 1;
+ p->straight[1] = p->mval[1]; /* save y */
+ }
+ else {
+ /* vertical */
+ p->straight[0] = 2;
+ p->straight[1] = p->mval[0]; /* save x */
+ }
+ }
+ }
+ }
+ else {
+ p->straight[0] = 0;
+ }
+
+ p->curtime = PIL_check_seconds_timer();
+
+ /* handle pressure sensitivity (which is supplied by tablets) */
+ if (event->tablet_data) {
+ const wmTabletData *wmtab = event->tablet_data;
+
+ tablet = (wmtab->Active != EVT_TABLET_NONE);
+ p->pressure = wmtab->Pressure;
+
+ /* Hack for pressure sensitive eraser on D+RMB when using a tablet:
+ * The pen has to float over the tablet surface, resulting in
+ * zero pressure (T47101). Ignore pressure values if floating
+ * (i.e. "effectively zero" pressure), and only when the "active"
+ * end is the stylus (i.e. the default when not eraser)
+ */
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ if ((wmtab->Active != EVT_TABLET_ERASER) && (p->pressure < 0.001f)) {
+ p->pressure = 1.0f;
+ }
+ }
+ }
+ else {
+ /* No tablet data -> No pressure info is available */
+ p->pressure = 1.0f;
+ }
+
+ /* special exception for start of strokes (i.e. maybe for just a dot) */
+ if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
+ p->flags &= ~GP_PAINTFLAG_FIRSTRUN;
+
+ p->mvalo[0] = p->mval[0];
+ p->mvalo[1] = p->mval[1];
+ p->opressure = p->pressure;
+ p->inittime = p->ocurtime = p->curtime;
+ p->straight[0] = 0;
+ p->straight[1] = 0;
+
+ /* special exception here for too high pressure values on first touch in
+ * windows for some tablets, then we just skip first touch...
+ */
+ if (tablet && (p->pressure >= 0.99f))
+ return;
+ }
+
+ /* check if alt key is pressed and limit to straight lines */
+ if ((p->paintmode != GP_PAINTMODE_ERASER) && (p->straight[0] != 0)) {
+ if (p->straight[0] == 1) {
+ /* horizontal */
+ p->mval[1] = p->straight[1]; /* replace y */
+ }
+ else {
+ /* vertical */
+ p->mval[0] = p->straight[1]; /* replace x */
+ }
+ }
+
+ /* fill in stroke data (not actually used directly by gpencil_draw_apply) */
+ RNA_collection_add(op->ptr, "stroke", &itemptr);
+
+ mousef[0] = p->mval[0];
+ mousef[1] = p->mval[1];
+ RNA_float_set_array(&itemptr, "mouse", mousef);
+ RNA_float_set(&itemptr, "pressure", p->pressure);
+ RNA_boolean_set(&itemptr, "is_start", (p->flags & GP_PAINTFLAG_FIRSTRUN) != 0);
+
+ RNA_float_set(&itemptr, "time", p->curtime - p->inittime);
+
+ /* apply the current latest drawing point */
+ gpencil_draw_apply(op, p, depsgraph);
+
+ /* force refresh */
+ /* just active area for now, since doing whole screen is too slow */
+ ED_region_tag_redraw(p->ar);
}
/* ------------------------------- */
@@ -1873,74 +1879,74 @@ static void annotation_draw_apply_event(wmOperator *op, const wmEvent *event, De
/* operator 'redo' (i.e. after changing some properties, but also for repeat last) */
static int gpencil_draw_exec(bContext *C, wmOperator *op)
{
- tGPsdata *p = NULL;
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
-
- /* printf("GPencil - Starting Re-Drawing\n"); */
-
- /* try to initialize context data needed while drawing */
- if (!gpencil_draw_init(C, op, NULL)) {
- if (op->customdata) MEM_freeN(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] = (int)mousef[0];
- p->mval[1] = (int)mousef[1];
- p->pressure = RNA_float_get(&itemptr, "pressure");
- p->curtime = (double)RNA_float_get(&itemptr, "time") + p->inittime;
-
- if (RNA_boolean_get(&itemptr, "is_start")) {
- /* if first-run flag isn't set already (i.e. not true first stroke),
- * then we must terminate the previous one first before continuing
- */
- if ((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) {
- /* TODO: both of these ops can set error-status, but we probably don't need to worry */
- gp_paint_strokeend(p);
- gp_paint_initstroke(p, p->paintmode, depsgraph);
- }
- }
-
- /* if first run, set previous data too */
- if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
- p->flags &= ~GP_PAINTFLAG_FIRSTRUN;
-
- p->mvalo[0] = p->mval[0];
- p->mvalo[1] = p->mval[1];
- p->opressure = p->pressure;
- p->ocurtime = p->curtime;
- }
-
- /* apply this data as necessary now (as per usual) */
- gpencil_draw_apply(op, p, depsgraph);
- }
- RNA_END;
-
- /* printf("\tGP - done\n"); */
-
- /* cleanup */
- gpencil_draw_exit(C, op);
-
- /* refreshes */
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
+ tGPsdata *p = NULL;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
+ /* printf("GPencil - Starting Re-Drawing\n"); */
+
+ /* try to initialize context data needed while drawing */
+ if (!gpencil_draw_init(C, op, NULL)) {
+ if (op->customdata)
+ MEM_freeN(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] = (int)mousef[0];
+ p->mval[1] = (int)mousef[1];
+ p->pressure = RNA_float_get(&itemptr, "pressure");
+ p->curtime = (double)RNA_float_get(&itemptr, "time") + p->inittime;
+
+ if (RNA_boolean_get(&itemptr, "is_start")) {
+ /* if first-run flag isn't set already (i.e. not true first stroke),
+ * then we must terminate the previous one first before continuing
+ */
+ if ((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) {
+ /* TODO: both of these ops can set error-status, but we probably don't need to worry */
+ gp_paint_strokeend(p);
+ gp_paint_initstroke(p, p->paintmode, depsgraph);
+ }
+ }
+
+ /* if first run, set previous data too */
+ if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
+ p->flags &= ~GP_PAINTFLAG_FIRSTRUN;
+
+ p->mvalo[0] = p->mval[0];
+ p->mvalo[1] = p->mval[1];
+ p->opressure = p->pressure;
+ p->ocurtime = p->curtime;
+ }
+
+ /* apply this data as necessary now (as per usual) */
+ gpencil_draw_apply(op, p, depsgraph);
+ }
+ RNA_END;
+
+ /* printf("\tGP - done\n"); */
+
+ /* cleanup */
+ gpencil_draw_exit(C, op);
+
+ /* refreshes */
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
/* ------------------------------- */
@@ -1948,521 +1954,540 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
/* start of interactive drawing part of operator */
static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Object *ob = CTX_data_active_object(C);
- ScrArea *sa = CTX_wm_area(C);
- Scene *scene = CTX_data_scene(C);
- tGPsdata *p = NULL;
-
- /* support for tablets eraser pen */
- if (gpencil_is_tablet_eraser_active(event)) {
- RNA_enum_set(op->ptr, "mode", GP_PAINTMODE_ERASER);
- }
-
- /* if try to do annotations with a gp object selected, first
- * unselect the object to avoid conflicts.
- * The solution is not perfect but we can keep running the annotations while
- * found a better solution.
- */
- if (sa && sa->spacetype == SPACE_VIEW3D) {
- if ((ob != NULL) && (ob->type == OB_GPENCIL)) {
- ob->mode = OB_MODE_OBJECT;
- bGPdata *gpd = (bGPdata *)ob->data;
- ED_gpencil_setup_modes(C, gpd, 0);
- DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- BKE_view_layer_base_deselect_all(view_layer);
- view_layer->basact = NULL;
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
- }
-
- if (G.debug & G_DEBUG)
- printf("GPencil - Starting Drawing\n");
-
- /* try to initialize context data needed while drawing */
- if (!gpencil_draw_init(C, op, event)) {
- if (op->customdata)
- MEM_freeN(op->customdata);
- if (G.debug & G_DEBUG)
- printf("\tGP - no valid data\n");
- return OPERATOR_CANCELLED;
- }
- else
- p = op->customdata;
-
- /* if empty erase capture and finish */
- if (p->status == GP_STATUS_CAPTURE) {
- gpencil_draw_exit(C, op);
-
- BKE_report(op->reports, RPT_ERROR, "Nothing to erase");
- return OPERATOR_FINISHED;
- }
-
- /* 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... */
-
- /* if eraser is on, draw radial aid */
- if (p->paintmode == GP_PAINTMODE_ERASER) {
- gpencil_draw_toggle_eraser_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)...
- */
- 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 */
- annotation_draw_apply_event(op, event, CTX_data_depsgraph(C), 0.0f, 0.0f);
- 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;
- }
-
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
- /* add a modal handler for this operator, so that we can then draw continuous strokes */
- WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ Object *ob = CTX_data_active_object(C);
+ ScrArea *sa = CTX_wm_area(C);
+ Scene *scene = CTX_data_scene(C);
+ tGPsdata *p = NULL;
+
+ /* support for tablets eraser pen */
+ if (gpencil_is_tablet_eraser_active(event)) {
+ RNA_enum_set(op->ptr, "mode", GP_PAINTMODE_ERASER);
+ }
+
+ /* if try to do annotations with a gp object selected, first
+ * unselect the object to avoid conflicts.
+ * The solution is not perfect but we can keep running the annotations while
+ * found a better solution.
+ */
+ if (sa && sa->spacetype == SPACE_VIEW3D) {
+ if ((ob != NULL) && (ob->type == OB_GPENCIL)) {
+ ob->mode = OB_MODE_OBJECT;
+ bGPdata *gpd = (bGPdata *)ob->data;
+ ED_gpencil_setup_modes(C, gpd, 0);
+ DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_view_layer_base_deselect_all(view_layer);
+ view_layer->basact = NULL;
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ }
+ }
+
+ if (G.debug & G_DEBUG)
+ printf("GPencil - Starting Drawing\n");
+
+ /* try to initialize context data needed while drawing */
+ if (!gpencil_draw_init(C, op, event)) {
+ if (op->customdata)
+ MEM_freeN(op->customdata);
+ if (G.debug & G_DEBUG)
+ printf("\tGP - no valid data\n");
+ return OPERATOR_CANCELLED;
+ }
+ else
+ p = op->customdata;
+
+ /* if empty erase capture and finish */
+ if (p->status == GP_STATUS_CAPTURE) {
+ gpencil_draw_exit(C, op);
+
+ BKE_report(op->reports, RPT_ERROR, "Nothing to erase");
+ return OPERATOR_FINISHED;
+ }
+
+ /* 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... */
+
+ /* if eraser is on, draw radial aid */
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ gpencil_draw_toggle_eraser_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)...
+ */
+ 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 */
+ annotation_draw_apply_event(op, event, CTX_data_depsgraph(C), 0.0f, 0.0f);
+ 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;
+ }
+
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+ /* add a modal handler for this operator, so that we can then draw continuous strokes */
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
}
/* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */
static bool gpencil_area_exists(bContext *C, ScrArea *sa_test)
{
- bScreen *sc = CTX_wm_screen(C);
- return (BLI_findindex(&sc->areabase, sa_test) != -1);
+ bScreen *sc = CTX_wm_screen(C);
+ return (BLI_findindex(&sc->areabase, sa_test) != -1);
}
static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
{
- tGPsdata *p = op->customdata;
+ tGPsdata *p = op->customdata;
- /* 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) {
- printf("\t\t\tGP - wrong area execution abort!\n");
- p->status = GP_STATUS_ERROR;
- }
+ /* 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) {
+ printf("\t\t\tGP - wrong area execution abort!\n");
+ p->status = GP_STATUS_ERROR;
+ }
- /* printf("\t\tGP - start stroke\n"); */
+ /* 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 */
+ /* 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, p))
- gp_paint_initstroke(p, p->paintmode, CTX_data_depsgraph(C));
+ if (gp_session_initdata(C, p))
+ gp_paint_initstroke(p, p->paintmode, CTX_data_depsgraph(C));
- if (p->status != GP_STATUS_ERROR) {
- p->status = GP_STATUS_PAINTING;
- op->flag &= ~OP_IS_MODAL_CURSOR_REGION;
- }
+ if (p->status != GP_STATUS_ERROR) {
+ p->status = GP_STATUS_PAINTING;
+ op->flag &= ~OP_IS_MODAL_CURSOR_REGION;
+ }
- return op->customdata;
+ return op->customdata;
}
static void gpencil_stroke_end(wmOperator *op)
{
- tGPsdata *p = op->customdata;
+ tGPsdata *p = op->customdata;
- gp_paint_cleanup(p);
+ gp_paint_cleanup(p);
- gpencil_undo_push(p->gpd);
+ gpencil_undo_push(p->gpd);
- gp_session_cleanup(p);
+ gp_session_cleanup(p);
- p->status = GP_STATUS_IDLING;
- op->flag |= OP_IS_MODAL_CURSOR_REGION;
+ p->status = GP_STATUS_IDLING;
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
- p->gpd = NULL;
- p->gpl = NULL;
- p->gpf = NULL;
+ p->gpd = NULL;
+ p->gpl = NULL;
+ p->gpf = NULL;
}
/* add events for missing mouse movements when the artist draw very fast */
-static void annotation_add_missing_events(bContext *C, wmOperator *op, const wmEvent *event, tGPsdata *p)
+static void annotation_add_missing_events(bContext *C,
+ wmOperator *op,
+ const wmEvent *event,
+ tGPsdata *p)
{
- float pt[2], a[2], b[2];
- float factor = 10.0f;
-
- copy_v2_v2(a, p->mvalo);
- b[0] = (float)event->mval[0] + 1.0f;
- b[1] = (float)event->mval[1] + 1.0f;
-
- /* 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 */
- annotation_draw_apply_event(op, event, CTX_data_depsgraph(C), pt[0], pt[1]);
- }
- 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 */
- annotation_draw_apply_event(
- op, event, CTX_data_depsgraph(C),
- pt[0], pt[1]);
- }
- }
+ float pt[2], a[2], b[2];
+ float factor = 10.0f;
+
+ copy_v2_v2(a, p->mvalo);
+ b[0] = (float)event->mval[0] + 1.0f;
+ b[1] = (float)event->mval[1] + 1.0f;
+
+ /* 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 */
+ annotation_draw_apply_event(op, event, CTX_data_depsgraph(C), pt[0], pt[1]);
+ }
+ 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 */
+ annotation_draw_apply_event(op, event, CTX_data_depsgraph(C), pt[0], pt[1]);
+ }
+ }
}
/* events handling during interactive drawing part of operator */
static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- tGPsdata *p = op->customdata;
- /* default exit state - pass through to support MMB view nav, etc. */
- int estate = OPERATOR_PASS_THROUGH;
-
- /* if (event->type == NDOF_MOTION)
- * return OPERATOR_PASS_THROUGH;
- * -------------------------------
- * [mce] Not quite what I was looking
- * for, but a good start! GP continues to
- * draw on the screen while the 3D mouse
- * moves the viewpoint. Problem is that
- * the stroke is converted to 3D only after
- * it is finished. This approach should work
- * better in tools that immediately apply
- * in 3D space.
- */
-
- if (p->status == GP_STATUS_IDLING) {
- ARegion *ar = CTX_wm_region(C);
- p->ar = ar;
- }
-
- /* 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)) {
- /* 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)) {
- /* 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)) {
- /* 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
- */
- WM_operator_name_call(C, "GPENCIL_OT_blank_frame_add", WM_OP_EXEC_DEFAULT, NULL);
- estate = OPERATOR_RUNNING_MODAL;
- }
- else {
- estate = OPERATOR_RUNNING_MODAL;
- }
- }
-
- //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 [#32647]
- */
- if (ELEM(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY, 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;
- 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)
- * (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"); */
- p->status = GP_STATUS_DONE;
- estate = OPERATOR_FINISHED;
- }
- }
- else if (event->val == KM_PRESS) {
- bool in_bounds = false;
-
- /* Check if we're outside the bounds of the active region
- * 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)) {
- /* 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);
-
- if (G.debug & G_DEBUG) {
- printf("found alternative region %p (old was %p) - at %d %d (sa: %d %d -> %d %d)\n",
- current_region, p->ar, event->x, event->y,
- p->sa->totrct.xmin, p->sa->totrct.ymin, p->sa->totrct.xmax, p->sa->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;
- in_bounds = true;
- }
- else {
- /* Out of bounds, or invalid in some other way */
- p->status = GP_STATUS_ERROR;
- estate = OPERATOR_CANCELLED;
-
- if (G.debug & G_DEBUG)
- printf("%s: Region under cursor is out of bounds, so cannot be drawn on\n", __func__);
- }
- }
- else if (p->ar) {
- rcti region_rect;
-
- /* Perform bounds check using */
- ED_region_visible_rect(p->ar, &region_rect);
- in_bounds = BLI_rcti_isect_pt_v(&region_rect, event->mval);
- }
- else {
- /* No region */
- p->status = GP_STATUS_ERROR;
- estate = OPERATOR_CANCELLED;
-
- if (G.debug & G_DEBUG)
- printf("%s: No active region found in GP Paint session data\n", __func__);
- }
-
- if (in_bounds) {
- /* Switch paintmode (temporarily if need be) based on which button was used
- * NOTE: This is to make it more convenient to erase strokes when using drawing sessions
- */
- if ((event->type == RIGHTMOUSE) || gpencil_is_tablet_eraser_active(event)) {
- /* turn on eraser */
- p->paintmode = GP_PAINTMODE_ERASER;
- }
- else if (event->type == LEFTMOUSE) {
- /* restore drawmode to default */
- p->paintmode = RNA_enum_get(op->ptr, "mode");
- }
-
- gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER);
-
- /* not painting, so start stroke (this should be mouse-button down) */
- p = gpencil_stroke_begin(C, op);
-
- if (p->status == GP_STATUS_ERROR) {
- estate = OPERATOR_CANCELLED;
- }
- }
- else if (p->status != GP_STATUS_ERROR) {
- /* User clicked outside bounds of window while idling, so exit paintmode
- * NOTE: Don't enter this case if an error occurred while finding the
- * region (as above)
- */
- p->status = GP_STATUS_DONE;
- estate = OPERATOR_FINISHED;
- }
- }
- else if (event->val == KM_RELEASE) {
- p->status = GP_STATUS_IDLING;
- op->flag |= OP_IS_MODAL_CURSOR_REGION;
- }
- }
-
- /* handle mode-specific events */
- if (p->status == GP_STATUS_PAINTING) {
- /* handle painting mouse-movements? */
- if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) || (p->flags & GP_PAINTFLAG_FIRSTRUN)) {
- /* handle drawing event */
- if ((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) {
- annotation_add_missing_events(C, op, event, p);
- }
-
- annotation_draw_apply_event(op, event, CTX_data_depsgraph(C), 0.0f, 0.0f);
-
- /* finish painting operation if anything went wrong just now */
- if (p->status == GP_STATUS_ERROR) {
- printf("\t\t\t\tGP - add error done!\n");
- estate = OPERATOR_CANCELLED;
- }
- 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"); */
- switch (event->type) {
- case WHEELDOWNMOUSE: /* larger */
- case PADPLUSKEY:
- p->radius += 5;
- break;
-
- case WHEELUPMOUSE: /* smaller */
- case PADMINUS:
- p->radius -= 5;
-
- if (p->radius <= 0)
- p->radius = 1;
- break;
- }
-
- /* force refresh */
- /* just active area for now, since doing whole screen is too slow */
- ED_region_tag_redraw(p->ar);
-
- /* event handled, so just tag as running modal */
- estate = OPERATOR_RUNNING_MODAL;
- }
- /* there shouldn't be any other events, but just in case there are, let's swallow them
- * (i.e. to prevent problems with undo)
- */
- else {
- /* swallow event to save ourselves trouble */
- estate = OPERATOR_RUNNING_MODAL;
- }
- }
-
- /* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */
- if (0 == gpencil_area_exists(C, p->sa))
- estate = OPERATOR_CANCELLED;
- else {
- /* update status indicators - cursor, header, etc. */
- gpencil_draw_status_indicators(C, p);
- /* cursor may have changed outside our control - T44084 */
- gpencil_draw_cursor_set(p);
- }
-
- /* process last operations before exiting */
- switch (estate) {
- case OPERATOR_FINISHED:
- /* one last flush before we're done */
- gpencil_draw_exit(C, op);
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
- break;
-
- case OPERATOR_CANCELLED:
- gpencil_draw_exit(C, op);
- break;
-
- case OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH:
- /* event doesn't need to be handled */
+ tGPsdata *p = op->customdata;
+ /* default exit state - pass through to support MMB view nav, etc. */
+ int estate = OPERATOR_PASS_THROUGH;
+
+ /* if (event->type == NDOF_MOTION)
+ * return OPERATOR_PASS_THROUGH;
+ * -------------------------------
+ * [mce] Not quite what I was looking
+ * for, but a good start! GP continues to
+ * draw on the screen while the 3D mouse
+ * moves the viewpoint. Problem is that
+ * the stroke is converted to 3D only after
+ * it is finished. This approach should work
+ * better in tools that immediately apply
+ * in 3D space.
+ */
+
+ if (p->status == GP_STATUS_IDLING) {
+ ARegion *ar = CTX_wm_region(C);
+ p->ar = ar;
+ }
+
+ /* 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)) {
+ /* 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)) {
+ /* 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)) {
+ /* 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
+ */
+ WM_operator_name_call(C, "GPENCIL_OT_blank_frame_add", WM_OP_EXEC_DEFAULT, NULL);
+ estate = OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ estate = OPERATOR_RUNNING_MODAL;
+ }
+ }
+
+ //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 [#32647]
+ */
+ if (ELEM(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY, 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;
+ 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)
+ * (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"); */
+ p->status = GP_STATUS_DONE;
+ estate = OPERATOR_FINISHED;
+ }
+ }
+ else if (event->val == KM_PRESS) {
+ bool in_bounds = false;
+
+ /* Check if we're outside the bounds of the active region
+ * 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)) {
+ /* 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);
+
+ if (G.debug & G_DEBUG) {
+ printf("found alternative region %p (old was %p) - at %d %d (sa: %d %d -> %d %d)\n",
+ current_region,
+ p->ar,
+ event->x,
+ event->y,
+ p->sa->totrct.xmin,
+ p->sa->totrct.ymin,
+ p->sa->totrct.xmax,
+ p->sa->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;
+ in_bounds = true;
+ }
+ else {
+ /* Out of bounds, or invalid in some other way */
+ p->status = GP_STATUS_ERROR;
+ estate = OPERATOR_CANCELLED;
+
+ if (G.debug & G_DEBUG)
+ printf("%s: Region under cursor is out of bounds, so cannot be drawn on\n", __func__);
+ }
+ }
+ else if (p->ar) {
+ rcti region_rect;
+
+ /* Perform bounds check using */
+ ED_region_visible_rect(p->ar, &region_rect);
+ in_bounds = BLI_rcti_isect_pt_v(&region_rect, event->mval);
+ }
+ else {
+ /* No region */
+ p->status = GP_STATUS_ERROR;
+ estate = OPERATOR_CANCELLED;
+
+ if (G.debug & G_DEBUG)
+ printf("%s: No active region found in GP Paint session data\n", __func__);
+ }
+
+ if (in_bounds) {
+ /* Switch paintmode (temporarily if need be) based on which button was used
+ * NOTE: This is to make it more convenient to erase strokes when using drawing sessions
+ */
+ if ((event->type == RIGHTMOUSE) || gpencil_is_tablet_eraser_active(event)) {
+ /* turn on eraser */
+ p->paintmode = GP_PAINTMODE_ERASER;
+ }
+ else if (event->type == LEFTMOUSE) {
+ /* restore drawmode to default */
+ p->paintmode = RNA_enum_get(op->ptr, "mode");
+ }
+
+ gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER);
+
+ /* not painting, so start stroke (this should be mouse-button down) */
+ p = gpencil_stroke_begin(C, op);
+
+ if (p->status == GP_STATUS_ERROR) {
+ estate = OPERATOR_CANCELLED;
+ }
+ }
+ else if (p->status != GP_STATUS_ERROR) {
+ /* User clicked outside bounds of window while idling, so exit paintmode
+ * NOTE: Don't enter this case if an error occurred while finding the
+ * region (as above)
+ */
+ p->status = GP_STATUS_DONE;
+ estate = OPERATOR_FINISHED;
+ }
+ }
+ else if (event->val == KM_RELEASE) {
+ p->status = GP_STATUS_IDLING;
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+ }
+ }
+
+ /* handle mode-specific events */
+ if (p->status == GP_STATUS_PAINTING) {
+ /* handle painting mouse-movements? */
+ if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) || (p->flags & GP_PAINTFLAG_FIRSTRUN)) {
+ /* handle drawing event */
+ if ((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) {
+ annotation_add_missing_events(C, op, event, p);
+ }
+
+ annotation_draw_apply_event(op, event, CTX_data_depsgraph(C), 0.0f, 0.0f);
+
+ /* finish painting operation if anything went wrong just now */
+ if (p->status == GP_STATUS_ERROR) {
+ printf("\t\t\t\tGP - add error done!\n");
+ estate = OPERATOR_CANCELLED;
+ }
+ 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"); */
+ switch (event->type) {
+ case WHEELDOWNMOUSE: /* larger */
+ case PADPLUSKEY:
+ p->radius += 5;
+ break;
+
+ case WHEELUPMOUSE: /* smaller */
+ case PADMINUS:
+ p->radius -= 5;
+
+ if (p->radius <= 0)
+ p->radius = 1;
+ break;
+ }
+
+ /* force refresh */
+ /* just active area for now, since doing whole screen is too slow */
+ ED_region_tag_redraw(p->ar);
+
+ /* event handled, so just tag as running modal */
+ estate = OPERATOR_RUNNING_MODAL;
+ }
+ /* there shouldn't be any other events, but just in case there are, let's swallow them
+ * (i.e. to prevent problems with undo)
+ */
+ else {
+ /* swallow event to save ourselves trouble */
+ estate = OPERATOR_RUNNING_MODAL;
+ }
+ }
+
+ /* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */
+ if (0 == gpencil_area_exists(C, p->sa))
+ estate = OPERATOR_CANCELLED;
+ else {
+ /* update status indicators - cursor, header, etc. */
+ gpencil_draw_status_indicators(C, p);
+ /* cursor may have changed outside our control - T44084 */
+ gpencil_draw_cursor_set(p);
+ }
+
+ /* process last operations before exiting */
+ switch (estate) {
+ case OPERATOR_FINISHED:
+ /* one last flush before we're done */
+ gpencil_draw_exit(C, op);
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+ break;
+
+ case OPERATOR_CANCELLED:
+ gpencil_draw_exit(C, op);
+ break;
+
+ 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);
+ printf("unhandled event -> %d (mmb? = %d | mmv? = %d)\n",
+ event->type, event->type == MIDDLEMOUSE, event->type==MOUSEMOVE);
#endif
- break;
- }
+ break;
+ }
- /* return status code */
- return estate;
+ /* return status code */
+ return estate;
}
/* ------------------------------- */
static const EnumPropertyItem prop_gpencil_drawmodes[] = {
- {GP_PAINTMODE_DRAW, "DRAW", 0, "Draw Freehand", "Draw freehand stroke(s)"},
- {GP_PAINTMODE_DRAW_STRAIGHT, "DRAW_STRAIGHT", 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 Annotation strokes"},
- {0, NULL, 0, NULL, NULL},
+ {GP_PAINTMODE_DRAW, "DRAW", 0, "Draw Freehand", "Draw freehand stroke(s)"},
+ {GP_PAINTMODE_DRAW_STRAIGHT,
+ "DRAW_STRAIGHT",
+ 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 Annotation strokes"},
+ {0, NULL, 0, NULL, NULL},
};
void GPENCIL_OT_annotate(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Annotation Draw";
- ot->idname = "GPENCIL_OT_annotate";
- ot->description = "Make annotations on the active data";
-
- /* api callbacks */
- ot->exec = gpencil_draw_exec;
- ot->invoke = gpencil_draw_invoke;
- ot->modal = gpencil_draw_modal;
- ot->cancel = gpencil_draw_cancel;
- ot->poll = gpencil_draw_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* settings for drawing */
- ot->prop = RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements");
-
- prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
-
- /* NOTE: wait for input is enabled by default,
- * so that all UI code can work properly without needing users to know about this */
- prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "Wait for first click instead of painting immediately");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Annotation Draw";
+ ot->idname = "GPENCIL_OT_annotate";
+ ot->description = "Make annotations on the active data";
+
+ /* api callbacks */
+ ot->exec = gpencil_draw_exec;
+ ot->invoke = gpencil_draw_invoke;
+ ot->modal = gpencil_draw_modal;
+ ot->cancel = gpencil_draw_cancel;
+ ot->poll = gpencil_draw_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* settings for drawing */
+ ot->prop = RNA_def_enum(
+ ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements");
+
+ prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ /* NOTE: wait for input is enabled by default,
+ * so that all UI code can work properly without needing users to know about this */
+ prop = RNA_def_boolean(ot->srna,
+ "wait_for_input",
+ true,
+ "Wait for Input",
+ "Wait for first click instead of painting immediately");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 711962400ff..24bdbcc4cba 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -21,7 +21,6 @@
* \ingroup edgpencil
*/
-
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -84,31 +83,29 @@
/* ----- General Defines ------ */
/* flags for sflag */
typedef enum eDrawStrokeFlags {
- /** don't draw status info */
- GP_DRAWDATA_NOSTATUS = (1 << 0),
- /** only draw 3d-strokes */
- GP_DRAWDATA_ONLY3D = (1 << 1),
- /** only draw 'canvas' strokes */
- GP_DRAWDATA_ONLYV2D = (1 << 2),
- /** only draw 'image' strokes */
- GP_DRAWDATA_ONLYI2D = (1 << 3),
- /** special hack for drawing strokes in Image Editor (weird coordinates) */
- GP_DRAWDATA_IEDITHACK = (1 << 4),
- /** don't draw xray in 3D view (which is default) */
- GP_DRAWDATA_NO_XRAY = (1 << 5),
- /** no onionskins should be drawn (for animation playback) */
- GP_DRAWDATA_NO_ONIONS = (1 << 6),
- /** draw strokes as "volumetric" circular billboards */
- GP_DRAWDATA_VOLUMETRIC = (1 << 7),
- /** fill insides/bounded-regions of strokes */
- GP_DRAWDATA_FILL = (1 << 8),
+ /** don't draw status info */
+ GP_DRAWDATA_NOSTATUS = (1 << 0),
+ /** only draw 3d-strokes */
+ GP_DRAWDATA_ONLY3D = (1 << 1),
+ /** only draw 'canvas' strokes */
+ GP_DRAWDATA_ONLYV2D = (1 << 2),
+ /** only draw 'image' strokes */
+ GP_DRAWDATA_ONLYI2D = (1 << 3),
+ /** special hack for drawing strokes in Image Editor (weird coordinates) */
+ GP_DRAWDATA_IEDITHACK = (1 << 4),
+ /** don't draw xray in 3D view (which is default) */
+ GP_DRAWDATA_NO_XRAY = (1 << 5),
+ /** no onionskins should be drawn (for animation playback) */
+ GP_DRAWDATA_NO_ONIONS = (1 << 6),
+ /** draw strokes as "volumetric" circular billboards */
+ GP_DRAWDATA_VOLUMETRIC = (1 << 7),
+ /** fill insides/bounded-regions of strokes */
+ GP_DRAWDATA_FILL = (1 << 8),
} eDrawStrokeFlags;
-
-
/* thickness above which we should use special drawing */
#if 0
-#define GP_DRAWTHICKNESS_SPECIAL 3
+# define GP_DRAWTHICKNESS_SPECIAL 3
#endif
/* conversion utility (float --> normalized unsigned byte) */
@@ -119,644 +116,697 @@ typedef enum eDrawStrokeFlags {
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);
+ 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)
{
- float alpha = ink[3] * pt->strength;
- CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
- immAttr4ub(attr_id, F2UB(ink[0]), F2UB(ink[1]), F2UB(ink[2]), F2UB(alpha));
+ float alpha = ink[3] * pt->strength;
+ CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
+ 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])
+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;
- }
+ 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])
+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_enable_program_point_size();
- 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);
- immAttr1f(size, pt->pressure * thickness); /* TODO: scale based on view transform */
- immVertex2f(pos, co[0], co[1]);
- }
-
- immEnd();
- immUnbindProgram();
- GPU_disable_program_point_size();
+ 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_enable_program_point_size();
+ 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);
+ immAttr1f(size, pt->pressure * thickness); /* TODO: scale based on view transform */
+ immVertex2f(pos, co[0], co[1]);
+ }
+
+ immEnd();
+ immUnbindProgram();
+ GPU_disable_program_point_size();
}
/* draw a 3D stroke in "volumetric" style */
-static void gp_draw_stroke_volumetric_3d(
- const bGPDspoint *points, int totpoints, short thickness,
- const float ink[4])
+static void gp_draw_stroke_volumetric_3d(const bGPDspoint *points,
+ int totpoints,
+ short thickness,
+ const float ink[4])
{
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, 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_enable_program_point_size();
- immBegin(GPU_PRIM_POINTS, totpoints);
-
- const bGPDspoint *pt = points;
- for (int i = 0; i < totpoints && pt; i++, pt++) {
- gp_set_point_varying_color(pt, ink, color);
- /* TODO: scale based on view transform */
- immAttr1f(size, pt->pressure * thickness);
- /* we can adjust size in vertex shader based on view/projection! */
- immVertex3fv(pos, &pt->x);
- }
-
- immEnd();
- immUnbindProgram();
- GPU_disable_program_point_size();
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, 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_enable_program_point_size();
+ immBegin(GPU_PRIM_POINTS, totpoints);
+
+ const bGPDspoint *pt = points;
+ for (int i = 0; i < totpoints && pt; i++, pt++) {
+ gp_set_point_varying_color(pt, ink, color);
+ /* TODO: scale based on view transform */
+ immAttr1f(size, pt->pressure * thickness);
+ /* we can adjust size in vertex shader based on view/projection! */
+ immVertex3fv(pos, &pt->x);
+ }
+
+ immEnd();
+ immUnbindProgram();
+ GPU_disable_program_point_size();
}
-
/* --------------- 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)
+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];
- }
- }
+ 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, float minv[2], float maxv[2], float(*r_uv)[2])
+static void gp_calc_stroke_text_coordinates(
+ const float (*points2d)[2], int totpoints, 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];
- }
+ 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);
+ 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])
+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 */
+ 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;
+ 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])
+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);
- Material *ma = gpd->mat[gps->mat_nr];
- 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_COLOR_TEX_MIX) != 0);
- immUniform1i("t_flip", (gp_style->flag & GP_STYLE_COLOR_FLIP_FILL) != 0);
+ BLI_assert(gps->totpoints >= 3);
+ Material *ma = gpd->mat[gps->mat_nr];
+ 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_COLOR_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);
- }
+ /* 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();
+ /* 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])
+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;
+ const bGPDspoint *pt = points;
- /* get final position using parent matrix */
- float fpt[3];
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
+ /* 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);
+ 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);
+ 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);
- }
+ /* 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);
+ 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();
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex3fv(pos, fpt);
+ immEnd();
- immUnbindProgram();
+ 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)
{
- bGPDspoint *points = tgpw->gps->points;
- int totpoints = tgpw->gps->totpoints;
-
- const float viewport[2] = { (float)tgpw->winx, (float)tgpw->winy };
- float curpressure = points[0].pressure;
- float fpt[3];
-
- /* if cyclic needs more vertex */
- int cyclic_add = (cyclic) ? 1 : 0;
-
- GPUVertFormat *format = immVertexFormat();
- const struct {
- uint pos, color, thickness;
- } attr_id = {
- .pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT),
- .color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT),
- .thickness = GPU_vertformat_attr_add(format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT),
- };
-
- immBindBuiltinProgram(GPU_SHADER_GPENCIL_STROKE);
- immUniform2fv("Viewport", viewport);
- immUniform1f("pixsize", tgpw->rv3d->pixsize);
- float obj_scale = tgpw->ob ? (tgpw->ob->scale[0] + tgpw->ob->scale[1] + tgpw->ob->scale[2]) / 3.0f : 1.0f;
-
- immUniform1f("objscale", obj_scale);
- int keep_size = (int)((tgpw->gpd) && (tgpw->gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS));
- immUniform1i("keep_size", keep_size);
- immUniform1f("pixfactor", tgpw->gpd->pixfactor);
- /* xray mode always to 3D space to avoid wrong zdepth calculation (T60051) */
- immUniform1i("xraymode", GP_XRAY_3DSPACE);
- immUniform1i("caps_start", (int)tgpw->gps->caps[0]);
- immUniform1i("caps_end", (int)tgpw->gps->caps[1]);
- immUniform1i("fill_stroke", (int)tgpw->is_fill_stroke);
-
- /* draw stroke curve */
- GPU_line_width(max_ff(curpressure * thickness, 1.0f));
- immBeginAtMost(GPU_PRIM_LINE_STRIP_ADJ, totpoints + cyclic_add + 2);
- const bGPDspoint *pt = points;
-
- for (int i = 0; i < totpoints; i++, pt++) {
- /* first point for adjacency (not drawn) */
- if (i == 0) {
- gp_set_point_varying_color(points, ink, attr_id.color);
-
- if ((cyclic) && (totpoints > 2)) {
- immAttr1f(attr_id.thickness, max_ff((points + totpoints - 1)->pressure * thickness, 1.0f));
- mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + totpoints - 1)->x);
- }
- else {
- immAttr1f(attr_id.thickness, max_ff((points + 1)->pressure * thickness, 1.0f));
- mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + 1)->x);
- }
- immVertex3fv(attr_id.pos, fpt);
- }
- /* set point */
- gp_set_point_varying_color(pt, ink, attr_id.color);
- immAttr1f(attr_id.thickness, max_ff(pt->pressure * thickness, 1.0f));
- mul_v3_m4v3(fpt, tgpw->diff_mat, &pt->x);
- immVertex3fv(attr_id.pos, fpt);
- }
-
- if (cyclic && totpoints > 2) {
- /* draw line to first point to complete the cycle */
- immAttr1f(attr_id.thickness, max_ff(points->pressure * thickness, 1.0f));
- mul_v3_m4v3(fpt, tgpw->diff_mat, &points->x);
- immVertex3fv(attr_id.pos, fpt);
-
- /* now add adjacency point (not drawn) */
- immAttr1f(attr_id.thickness, max_ff((points + 1)->pressure * thickness, 1.0f));
- mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + 1)->x);
- immVertex3fv(attr_id.pos, fpt);
- }
- /* last adjacency point (not drawn) */
- else {
- gp_set_point_varying_color(points + totpoints - 2, ink, attr_id.color);
- immAttr1f(attr_id.thickness, max_ff((points + totpoints - 2)->pressure * thickness, 1.0f));
- mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + totpoints - 2)->x);
- immVertex3fv(attr_id.pos, fpt);
- }
-
- immEnd();
- immUnbindProgram();
+ bGPDspoint *points = tgpw->gps->points;
+ int totpoints = tgpw->gps->totpoints;
+
+ const float viewport[2] = {(float)tgpw->winx, (float)tgpw->winy};
+ float curpressure = points[0].pressure;
+ float fpt[3];
+
+ /* if cyclic needs more vertex */
+ int cyclic_add = (cyclic) ? 1 : 0;
+
+ GPUVertFormat *format = immVertexFormat();
+ const struct {
+ uint pos, color, thickness;
+ } attr_id = {
+ .pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT),
+ .color = GPU_vertformat_attr_add(
+ format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT),
+ .thickness = GPU_vertformat_attr_add(format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT),
+ };
+
+ immBindBuiltinProgram(GPU_SHADER_GPENCIL_STROKE);
+ immUniform2fv("Viewport", viewport);
+ immUniform1f("pixsize", tgpw->rv3d->pixsize);
+ float obj_scale = tgpw->ob ?
+ (tgpw->ob->scale[0] + tgpw->ob->scale[1] + tgpw->ob->scale[2]) / 3.0f :
+ 1.0f;
+
+ immUniform1f("objscale", obj_scale);
+ int keep_size = (int)((tgpw->gpd) && (tgpw->gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS));
+ immUniform1i("keep_size", keep_size);
+ immUniform1f("pixfactor", tgpw->gpd->pixfactor);
+ /* xray mode always to 3D space to avoid wrong zdepth calculation (T60051) */
+ immUniform1i("xraymode", GP_XRAY_3DSPACE);
+ immUniform1i("caps_start", (int)tgpw->gps->caps[0]);
+ immUniform1i("caps_end", (int)tgpw->gps->caps[1]);
+ immUniform1i("fill_stroke", (int)tgpw->is_fill_stroke);
+
+ /* draw stroke curve */
+ GPU_line_width(max_ff(curpressure * thickness, 1.0f));
+ immBeginAtMost(GPU_PRIM_LINE_STRIP_ADJ, totpoints + cyclic_add + 2);
+ const bGPDspoint *pt = points;
+
+ for (int i = 0; i < totpoints; i++, pt++) {
+ /* first point for adjacency (not drawn) */
+ if (i == 0) {
+ gp_set_point_varying_color(points, ink, attr_id.color);
+
+ if ((cyclic) && (totpoints > 2)) {
+ immAttr1f(attr_id.thickness, max_ff((points + totpoints - 1)->pressure * thickness, 1.0f));
+ mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + totpoints - 1)->x);
+ }
+ else {
+ immAttr1f(attr_id.thickness, max_ff((points + 1)->pressure * thickness, 1.0f));
+ mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + 1)->x);
+ }
+ immVertex3fv(attr_id.pos, fpt);
+ }
+ /* set point */
+ gp_set_point_varying_color(pt, ink, attr_id.color);
+ immAttr1f(attr_id.thickness, max_ff(pt->pressure * thickness, 1.0f));
+ mul_v3_m4v3(fpt, tgpw->diff_mat, &pt->x);
+ immVertex3fv(attr_id.pos, fpt);
+ }
+
+ if (cyclic && totpoints > 2) {
+ /* draw line to first point to complete the cycle */
+ immAttr1f(attr_id.thickness, max_ff(points->pressure * thickness, 1.0f));
+ mul_v3_m4v3(fpt, tgpw->diff_mat, &points->x);
+ immVertex3fv(attr_id.pos, fpt);
+
+ /* now add adjacency point (not drawn) */
+ immAttr1f(attr_id.thickness, max_ff((points + 1)->pressure * thickness, 1.0f));
+ mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + 1)->x);
+ immVertex3fv(attr_id.pos, fpt);
+ }
+ /* last adjacency point (not drawn) */
+ else {
+ gp_set_point_varying_color(points + totpoints - 2, ink, attr_id.color);
+ immAttr1f(attr_id.thickness, max_ff((points + totpoints - 2)->pressure * thickness, 1.0f));
+ mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + totpoints - 2)->x);
+ immVertex3fv(attr_id.pos, fpt);
+ }
+
+ immEnd();
+ 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])
+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);
-
- /* 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);
-
- /* 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();
- }
+ /* 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);
+
+ /* 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);
+
+ /* 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 ------ */
@@ -764,335 +814,371 @@ static void gp_draw_stroke_2d(
/* Helper for doing all the checks on whether a stroke can be drawn */
static bool gp_can_draw_stroke(const bGPDstroke *gps, const int dflag)
{
- /* skip stroke if it isn't in the right display space for this drawing context */
- /* 1) 3D Strokes */
- if ((dflag & GP_DRAWDATA_ONLY3D) && !(gps->flag & GP_STROKE_3DSPACE))
- return false;
- if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE))
- return false;
-
- /* 2) Screen Space 2D Strokes */
- if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE))
- return false;
- if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE))
- return false;
-
- /* 3) Image Space (2D) */
- if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE))
- return false;
- if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE))
- return false;
-
- /* skip stroke if it doesn't have any valid data */
- if ((gps->points == NULL) || (gps->totpoints < 1))
- return false;
-
- /* stroke can be drawn */
- return true;
+ /* skip stroke if it isn't in the right display space for this drawing context */
+ /* 1) 3D Strokes */
+ if ((dflag & GP_DRAWDATA_ONLY3D) && !(gps->flag & GP_STROKE_3DSPACE))
+ return false;
+ if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE))
+ return false;
+
+ /* 2) Screen Space 2D Strokes */
+ if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE))
+ return false;
+ if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE))
+ return false;
+
+ /* 3) Image Space (2D) */
+ if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE))
+ return false;
+ if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE))
+ return false;
+
+ /* skip stroke if it doesn't have any valid data */
+ if ((gps->points == NULL) || (gps->totpoints < 1))
+ return false;
+
+ /* stroke can be drawn */
+ return true;
}
/* draw a set of strokes */
static void gp_draw_strokes(tGPDdraw *tgpw)
{
- float tcolor[4];
- float tfill[4];
- short sthickness;
- float ink[4];
-
- GPU_enable_program_point_size();
-
- for (bGPDstroke *gps = tgpw->t_gpf->strokes.first; gps; gps = gps->next) {
- /* check if stroke can be drawn */
- if (gp_can_draw_stroke(gps, tgpw->dflag) == false) {
- continue;
- }
- /* check if the color is visible */
- Material *ma = tgpw->gpd->mat[gps->mat_nr];
- MaterialGPencilStyle *gp_style = (ma) ? ma->gp_style : NULL;
-
- if ((gp_style == NULL) ||
- (gp_style->flag & GP_STYLE_COLOR_HIDE) ||
- /* if onion and ghost flag do not draw*/
- (tgpw->onion && (gp_style->flag & GP_STYLE_COLOR_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))
- {
- continue;
- }
-
- /* calculate thickness */
- sthickness = gps->thickness + tgpw->lthick;
-
- if (tgpw->is_fill_stroke) {
- sthickness = (short)max_ii(1, sthickness / 2);
- }
-
- if (sthickness <= 0) {
- continue;
- }
-
- /* check which stroke-drawer to use */
- if (tgpw->dflag & GP_DRAWDATA_ONLY3D) {
- const int no_xray = (tgpw->dflag & GP_DRAWDATA_NO_XRAY);
- int mask_orig = 0;
-
- 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);
- }
-
- /* 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) {
- 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) {
- /* volumetric stroke drawing */
- if (tgpw->disable_fill != 1) {
- gp_draw_stroke_volumetric_3d(gps->points, gps->totpoints, sthickness, ink);
- }
- }
- 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 {
- tgpw->gps = gps;
- gp_draw_stroke_3d(tgpw, sthickness, ink, gps->flag & GP_STROKE_CYCLIC);
- }
- }
- if (no_xray) {
- glDepthMask(mask_orig);
- GPU_depth_test(false);
-
- 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);
- }
- }
- }
- }
-
- GPU_disable_program_point_size();
+ float tcolor[4];
+ float tfill[4];
+ short sthickness;
+ float ink[4];
+
+ GPU_enable_program_point_size();
+
+ for (bGPDstroke *gps = tgpw->t_gpf->strokes.first; gps; gps = gps->next) {
+ /* check if stroke can be drawn */
+ if (gp_can_draw_stroke(gps, tgpw->dflag) == false) {
+ continue;
+ }
+ /* check if the color is visible */
+ Material *ma = tgpw->gpd->mat[gps->mat_nr];
+ MaterialGPencilStyle *gp_style = (ma) ? ma->gp_style : NULL;
+
+ if ((gp_style == NULL) || (gp_style->flag & GP_STYLE_COLOR_HIDE) ||
+ /* if onion and ghost flag do not draw*/
+ (tgpw->onion && (gp_style->flag & GP_STYLE_COLOR_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)) {
+ continue;
+ }
+
+ /* calculate thickness */
+ sthickness = gps->thickness + tgpw->lthick;
+
+ if (tgpw->is_fill_stroke) {
+ sthickness = (short)max_ii(1, sthickness / 2);
+ }
+
+ if (sthickness <= 0) {
+ continue;
+ }
+
+ /* check which stroke-drawer to use */
+ if (tgpw->dflag & GP_DRAWDATA_ONLY3D) {
+ const int no_xray = (tgpw->dflag & GP_DRAWDATA_NO_XRAY);
+ int mask_orig = 0;
+
+ 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);
+ }
+
+ /* 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) {
+ 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) {
+ /* volumetric stroke drawing */
+ if (tgpw->disable_fill != 1) {
+ gp_draw_stroke_volumetric_3d(gps->points, gps->totpoints, sthickness, ink);
+ }
+ }
+ 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 {
+ tgpw->gps = gps;
+ gp_draw_stroke_3d(tgpw, sthickness, ink, gps->flag & GP_STROKE_CYCLIC);
+ }
+ }
+ if (no_xray) {
+ glDepthMask(mask_orig);
+ GPU_depth_test(false);
+
+ 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);
+ }
+ }
+ }
+ }
+
+ GPU_disable_program_point_size();
}
/* ----- 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);
- Depsgraph *depsgraph = CTX_data_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.lthick = tgpil->gpl->line_change;
- tgpw.opacity = 1.0;
- copy_v4_v4(tgpw.tintcolor, color);
- tgpw.onion = true;
- tgpw.custonion = true;
-
- gp_draw_strokes(&tgpw);
- }
- }
- GPU_blend(false);
+ tGPDdraw tgpw;
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ tGPDinterpolate_layer *tgpil;
+ Object *obact = CTX_data_active_object(C);
+ Depsgraph *depsgraph = CTX_data_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.lthick = tgpil->gpl->line_change;
+ tgpw.opacity = 1.0;
+ copy_v4_v4(tgpw.tintcolor, color);
+ tgpw.onion = true;
+ tgpw.custonion = true;
+
+ 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);
+ 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)
{
- rcti rect;
+ rcti rect;
- /* Cannot draw any status text when drawing OpenGL Renders */
- if (G.f & G_FLAG_RENDER_VIEWPORT)
- return;
+ /* 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 */
- ED_region_visible_rect(ar, &rect);
+ /* Get bounds of region - Necessary to avoid problems with region overlap */
+ ED_region_visible_rect(ar, &rect);
- /* 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];
+ /* 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();
+ int font_id = BLF_default();
- BLF_width_and_height(font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
+ 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);
+ 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);
+ /* 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);
+ 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);
+ 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);
+ /* 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;
+ xco -= U.widget_unit;
+ yco -= (int)printable_size[1] / 2;
- UI_icon_draw(xco, yco, ICON_GREASEPENCIL);
+ UI_icon_draw(xco, yco, ICON_GREASEPENCIL);
- GPU_blend(false);
- }
+ GPU_blend(false);
+ }
}
diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c
index 8ada5a05618..4724dc068b6 100644
--- a/source/blender/editors/gpencil/editaction_gpencil.c
+++ b/source/blender/editors/gpencil/editaction_gpencil.c
@@ -21,7 +21,6 @@
* \ingroup edgpencil
*/
-
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -59,21 +58,21 @@
/* 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;
+ bGPDframe *gpf;
- /* error checker */
- if (gpl == NULL)
- return false;
+ /* error checker */
+ if (gpl == NULL)
+ return false;
- /* do loop */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- /* execute callback */
- if (gpf_cb(gpf, scene))
- return true;
- }
+ /* do loop */
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ /* execute callback */
+ if (gpf_cb(gpf, scene))
+ return true;
+ }
- /* nothing to return */
- return false;
+ /* nothing to return */
+ return false;
}
/* ****************************************** */
@@ -82,24 +81,24 @@ 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;
+ bGPDframe *gpf;
+ CfraElem *ce;
- /* error checking */
- if (ELEM(NULL, gpl, elems))
- return;
+ /* error checking */
+ if (ELEM(NULL, gpl, elems))
+ return;
- /* loop through gp-frames, adding */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- if ((onlysel == 0) || (gpf->flag & GP_FRAME_SELECT)) {
- ce = MEM_callocN(sizeof(CfraElem), "CfraElem");
+ /* loop through gp-frames, adding */
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ if ((onlysel == 0) || (gpf->flag & GP_FRAME_SELECT)) {
+ ce = MEM_callocN(sizeof(CfraElem), "CfraElem");
- ce->cfra = (float)gpf->framenum;
- ce->sel = (gpf->flag & GP_FRAME_SELECT) ? 1 : 0;
+ ce->cfra = (float)gpf->framenum;
+ ce->sel = (gpf->flag & GP_FRAME_SELECT) ? 1 : 0;
- BLI_addtail(elems, ce);
- }
- }
+ BLI_addtail(elems, ce);
+ }
+ }
}
/* ***************************************** */
@@ -108,125 +107,128 @@ 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;
+ bGPDframe *gpf;
- /* error checking */
- if (gpl == NULL)
- return false;
+ /* error checking */
+ if (gpl == NULL)
+ return false;
- /* stop at the first one found */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- if (gpf->flag & GP_FRAME_SELECT)
- return true;
- }
+ /* stop at the first one found */
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ if (gpf->flag & GP_FRAME_SELECT)
+ return true;
+ }
- /* not found */
- return false;
+ /* not found */
+ return false;
}
/* helper function - select gp-frame based on SELECT_* mode */
static void gpframe_select(bGPDframe *gpf, short select_mode)
{
- if (gpf == NULL)
- return;
-
- switch (select_mode) {
- case SELECT_ADD:
- gpf->flag |= GP_FRAME_SELECT;
- break;
- case SELECT_SUBTRACT:
- gpf->flag &= ~GP_FRAME_SELECT;
- break;
- case SELECT_INVERT:
- gpf->flag ^= GP_FRAME_SELECT;
- break;
- }
+ if (gpf == NULL)
+ return;
+
+ switch (select_mode) {
+ case SELECT_ADD:
+ gpf->flag |= GP_FRAME_SELECT;
+ break;
+ case SELECT_SUBTRACT:
+ gpf->flag &= ~GP_FRAME_SELECT;
+ break;
+ case SELECT_INVERT:
+ gpf->flag ^= GP_FRAME_SELECT;
+ break;
+ }
}
/* set all/none/invert select (like above, but with SELECT_* modes) */
void ED_gpencil_select_frames(bGPDlayer *gpl, short select_mode)
{
- bGPDframe *gpf;
+ bGPDframe *gpf;
- /* error checking */
- if (gpl == NULL)
- return;
+ /* error checking */
+ if (gpl == NULL)
+ return;
- /* handle according to mode */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- gpframe_select(gpf, select_mode);
- }
+ /* handle according to mode */
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ gpframe_select(gpf, select_mode);
+ }
}
/* set all/none/invert select */
void ED_gplayer_frame_select_set(bGPDlayer *gpl, short mode)
{
- /* error checking */
- if (gpl == NULL)
- return;
+ /* error checking */
+ if (gpl == NULL)
+ return;
- /* now call the standard function */
- ED_gpencil_select_frames(gpl, mode);
+ /* now call the standard function */
+ ED_gpencil_select_frames(gpl, mode);
}
/* select the frame in this layer that occurs on this frame (there should only be one at most) */
void ED_gpencil_select_frame(bGPDlayer *gpl, int selx, short select_mode)
{
- bGPDframe *gpf;
+ bGPDframe *gpf;
- if (gpl == NULL)
- return;
+ if (gpl == NULL)
+ return;
- gpf = BKE_gpencil_layer_find_frame(gpl, selx);
+ gpf = BKE_gpencil_layer_find_frame(gpl, selx);
- if (gpf) {
- gpframe_select(gpf, select_mode);
- }
+ if (gpf) {
+ gpframe_select(gpf, 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;
+ bGPDframe *gpf;
- if (gpl == NULL)
- return;
+ if (gpl == NULL)
+ return;
- /* only select those frames which are in bounds */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- if (IN_RANGE(gpf->framenum, min, max))
- gpframe_select(gpf, select_mode);
- }
+ /* only select those frames which are in bounds */
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ if (IN_RANGE(gpf->framenum, min, max))
+ gpframe_select(gpf, select_mode);
+ }
}
/* select the frames in this layer that occur within the lasso/circle region specified */
-void ED_gplayer_frames_select_region(KeyframeEditData *ked, bGPDlayer *gpl, short tool, short select_mode)
+void ED_gplayer_frames_select_region(KeyframeEditData *ked,
+ bGPDlayer *gpl,
+ 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) {
- /* construct a dummy point coordinate to do this testing with */
- float pt[2] = {0};
-
- pt[0] = gpf->framenum;
- pt[1] = ked->channel_y;
-
- /* check the necessary regions */
- if (tool == BEZT_OK_CHANNEL_LASSO) {
- /* Lasso */
- if (keyframe_region_lasso_test(ked->data, pt))
- gpframe_select(gpf, select_mode);
- }
- else if (tool == BEZT_OK_CHANNEL_CIRCLE) {
- /* Circle */
- if (keyframe_region_circle_test(ked->data, pt))
- gpframe_select(gpf, 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) {
+ /* construct a dummy point coordinate to do this testing with */
+ float pt[2] = {0};
+
+ pt[0] = gpf->framenum;
+ pt[1] = ked->channel_y;
+
+ /* check the necessary regions */
+ if (tool == BEZT_OK_CHANNEL_LASSO) {
+ /* Lasso */
+ if (keyframe_region_lasso_test(ked->data, pt))
+ gpframe_select(gpf, select_mode);
+ }
+ else if (tool == BEZT_OK_CHANNEL_CIRCLE) {
+ /* Circle */
+ if (keyframe_region_circle_test(ked->data, pt))
+ gpframe_select(gpf, select_mode);
+ }
+ }
}
/* ***************************************** */
@@ -235,50 +237,50 @@ void ED_gplayer_frames_select_region(KeyframeEditData *ked, bGPDlayer *gpl, shor
/* Delete selected frames */
bool ED_gplayer_frames_delete(bGPDlayer *gpl)
{
- bGPDframe *gpf, *gpfn;
- bool changed = false;
+ bGPDframe *gpf, *gpfn;
+ bool changed = false;
- /* error checking */
- if (gpl == NULL)
- return false;
+ /* error checking */
+ if (gpl == NULL)
+ return false;
- /* check for frames to delete */
- for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
- gpfn = gpf->next;
+ /* check for frames to delete */
+ for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
+ gpfn = gpf->next;
- if (gpf->flag & GP_FRAME_SELECT) {
- BKE_gpencil_layer_delframe(gpl, gpf);
- changed = true;
- }
- }
+ if (gpf->flag & GP_FRAME_SELECT) {
+ BKE_gpencil_layer_delframe(gpl, gpf);
+ changed = true;
+ }
+ }
- return changed;
+ return changed;
}
/* Duplicate selected frames from given gp-layer */
void ED_gplayer_frames_duplicate(bGPDlayer *gpl)
{
- bGPDframe *gpf, *gpfn;
+ bGPDframe *gpf, *gpfn;
- /* error checking */
- if (gpl == NULL)
- return;
+ /* error checking */
+ if (gpl == NULL)
+ return;
- /* duplicate selected frames */
- for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
- gpfn = gpf->next;
+ /* duplicate selected frames */
+ for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
+ gpfn = gpf->next;
- /* duplicate this frame */
- if (gpf->flag & GP_FRAME_SELECT) {
- bGPDframe *gpfd;
+ /* duplicate this frame */
+ if (gpf->flag & GP_FRAME_SELECT) {
+ bGPDframe *gpfd;
- /* duplicate frame, and deselect self */
- gpfd = BKE_gpencil_frame_duplicate(gpf);
- gpf->flag &= ~GP_FRAME_SELECT;
+ /* duplicate frame, and deselect self */
+ gpfd = BKE_gpencil_frame_duplicate(gpf);
+ gpf->flag &= ~GP_FRAME_SELECT;
- BLI_insertlinkafter(&gpl->frames, gpf, gpfd);
- }
- }
+ BLI_insertlinkafter(&gpl->frames, gpf, gpfd);
+ }
+ }
}
/* Set keyframe type for selected frames from given gp-layer
@@ -286,19 +288,18 @@ void ED_gplayer_frames_duplicate(bGPDlayer *gpl)
*/
void ED_gplayer_frames_keytype_set(bGPDlayer *gpl, short type)
{
- bGPDframe *gpf;
+ bGPDframe *gpf;
- if (gpl == NULL)
- return;
+ if (gpl == NULL)
+ return;
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- if (gpf->flag & GP_FRAME_SELECT) {
- gpf->key_type = type;
- }
- }
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ if (gpf->flag & GP_FRAME_SELECT) {
+ gpf->key_type = type;
+ }
+ }
}
-
/* -------------------------------------- */
/* Copy and Paste Tools */
/* - The copy/paste buffer currently stores a set of GP_Layers, with temporary
@@ -311,23 +312,21 @@ void ED_gplayer_frames_keytype_set(bGPDlayer *gpl, short type)
/* globals for copy/paste data (like for other copy/paste buffers) */
static ListBase gp_anim_copybuf = {NULL, NULL};
-static int gp_anim_copy_firstframe = 999999999;
-static int gp_anim_copy_lastframe = -999999999;
-static int gp_anim_copy_cfra = 0;
-
+static int gp_anim_copy_firstframe = 999999999;
+static int gp_anim_copy_lastframe = -999999999;
+static int gp_anim_copy_cfra = 0;
/* This function frees any MEM_calloc'ed copy/paste buffer data */
void ED_gpencil_anim_copybuf_free(void)
{
- BKE_gpencil_free_layers(&gp_anim_copybuf);
- BLI_listbase_clear(&gp_anim_copybuf);
+ BKE_gpencil_free_layers(&gp_anim_copybuf);
+ BLI_listbase_clear(&gp_anim_copybuf);
- gp_anim_copy_firstframe = 999999999;
- gp_anim_copy_lastframe = -999999999;
- gp_anim_copy_cfra = 0;
+ gp_anim_copy_firstframe = 999999999;
+ gp_anim_copy_lastframe = -999999999;
+ gp_anim_copy_cfra = 0;
}
-
/* This function adds data to the copy/paste buffer, freeing existing data first
* Only the selected GP-layers get their selected keyframes copied.
*
@@ -335,180 +334,177 @@ void ED_gpencil_anim_copybuf_free(void)
*/
bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- Scene *scene = ac->scene;
-
-
- /* clear buffer first */
- ED_gpencil_anim_copybuf_free();
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* assume that each of these is a GP layer */
- 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) {
- /* if frame is selected, make duplicate it and its strokes */
- if (gpf->flag & GP_FRAME_SELECT) {
- /* make a copy of this frame */
- bGPDframe *new_frame = BKE_gpencil_frame_duplicate(gpf);
- BLI_addtail(&copied_frames, new_frame);
-
- /* extend extents for keyframes encountered */
- if (gpf->framenum < gp_anim_copy_firstframe)
- gp_anim_copy_firstframe = gpf->framenum;
- if (gpf->framenum > gp_anim_copy_lastframe)
- gp_anim_copy_lastframe = gpf->framenum;
- }
- }
-
- /* create a new layer in buffer if there were keyframes here */
- if (BLI_listbase_is_empty(&copied_frames) == false) {
- bGPDlayer *new_layer = MEM_callocN(sizeof(bGPDlayer), "GPCopyPasteLayer");
- BLI_addtail(&gp_anim_copybuf, new_layer);
-
- /* move over copied frames */
- BLI_movelisttolist(&new_layer->frames, &copied_frames);
- BLI_assert(copied_frames.first == NULL);
-
- /* make a copy of the layer's name - for name-based matching later... */
- BLI_strncpy(new_layer->info, gpl->info, sizeof(new_layer->info));
- }
- }
-
- /* in case 'relative' paste method is used */
- gp_anim_copy_cfra = CFRA;
-
- /* clean up */
- ANIM_animdata_freelist(&anim_data);
-
- /* check if anything ended up in the buffer */
- if (ELEM(NULL, gp_anim_copybuf.first, gp_anim_copybuf.last)) {
- BKE_report(ac->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
- return false;
- }
-
- /* report success */
- return true;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ Scene *scene = ac->scene;
+
+ /* clear buffer first */
+ ED_gpencil_anim_copybuf_free();
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* assume that each of these is a GP layer */
+ 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) {
+ /* if frame is selected, make duplicate it and its strokes */
+ if (gpf->flag & GP_FRAME_SELECT) {
+ /* make a copy of this frame */
+ bGPDframe *new_frame = BKE_gpencil_frame_duplicate(gpf);
+ BLI_addtail(&copied_frames, new_frame);
+
+ /* extend extents for keyframes encountered */
+ if (gpf->framenum < gp_anim_copy_firstframe)
+ gp_anim_copy_firstframe = gpf->framenum;
+ if (gpf->framenum > gp_anim_copy_lastframe)
+ gp_anim_copy_lastframe = gpf->framenum;
+ }
+ }
+
+ /* create a new layer in buffer if there were keyframes here */
+ if (BLI_listbase_is_empty(&copied_frames) == false) {
+ bGPDlayer *new_layer = MEM_callocN(sizeof(bGPDlayer), "GPCopyPasteLayer");
+ BLI_addtail(&gp_anim_copybuf, new_layer);
+
+ /* move over copied frames */
+ BLI_movelisttolist(&new_layer->frames, &copied_frames);
+ BLI_assert(copied_frames.first == NULL);
+
+ /* make a copy of the layer's name - for name-based matching later... */
+ BLI_strncpy(new_layer->info, gpl->info, sizeof(new_layer->info));
+ }
+ }
+
+ /* in case 'relative' paste method is used */
+ gp_anim_copy_cfra = CFRA;
+
+ /* clean up */
+ ANIM_animdata_freelist(&anim_data);
+
+ /* check if anything ended up in the buffer */
+ if (ELEM(NULL, gp_anim_copybuf.first, gp_anim_copybuf.last)) {
+ BKE_report(ac->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
+ return false;
+ }
+
+ /* report success */
+ return true;
}
-
/* Pastes keyframes from buffer, and reports success */
bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- Scene *scene = ac->scene;
- bool no_name = false;
- int offset = 0;
-
- /* check if buffer is empty */
- if (BLI_listbase_is_empty(&gp_anim_copybuf)) {
- BKE_report(ac->reports, RPT_ERROR, "No data in buffer to paste");
- return false;
- }
-
- /* check if single channel in buffer (disregard names if so) */
- if (gp_anim_copybuf.first == gp_anim_copybuf.last) {
- no_name = true;
- }
-
- /* methods of offset (eKeyPasteOffset) */
- switch (offset_mode) {
- case KEYFRAME_PASTE_OFFSET_CFRA_START:
- offset = (CFRA - gp_anim_copy_firstframe);
- break;
- case KEYFRAME_PASTE_OFFSET_CFRA_END:
- offset = (CFRA - gp_anim_copy_lastframe);
- break;
- case KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE:
- offset = (CFRA - gp_anim_copy_cfra);
- break;
- case KEYFRAME_PASTE_OFFSET_NONE:
- offset = 0;
- break;
- }
-
-
- /* filter data */
- // TODO: try doing it with selection, then without selection imits
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* from selected channels */
- for (ale = anim_data.first; ale; ale = ale->next) {
- bGPDlayer *gpld = (bGPDlayer *)ale->data;
- bGPDlayer *gpls = NULL;
- bGPDframe *gpfs, *gpf;
-
-
- /* find suitable layer from buffer to use to paste from */
- for (gpls = gp_anim_copybuf.first; gpls; gpls = gpls->next) {
- /* check if layer name matches */
- if ((no_name) || STREQ(gpls->info, gpld->info)) {
- break;
- }
- }
-
- /* this situation might occur! */
- if (gpls == NULL)
- continue;
-
- /* add frames from buffer */
- for (gpfs = gpls->frames.first; gpfs; gpfs = gpfs->next) {
- /* temporarily apply offset to buffer-frame while copying */
- 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);
- if (gpf) {
- bGPDstroke *gps, *gpsn;
-
- /* This should be the right frame... as it may be a pre-existing frame,
- * must make sure that only compatible stroke types get copied over
- * - We cannot just add a duplicate frame, as that would cause errors
- * - For now, we don't check if the types will be compatible since we
- * don't have enough info to do so. Instead, we simply just paste,
- * if it works, it will show up.
- */
- 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);
- /* 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);
- }
-
- /* unapply offset from buffer-frame */
- gpfs->framenum -= offset;
- }
- }
-
- /* clean up */
- ANIM_animdata_freelist(&anim_data);
- return true;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ Scene *scene = ac->scene;
+ bool no_name = false;
+ int offset = 0;
+
+ /* check if buffer is empty */
+ if (BLI_listbase_is_empty(&gp_anim_copybuf)) {
+ BKE_report(ac->reports, RPT_ERROR, "No data in buffer to paste");
+ return false;
+ }
+
+ /* check if single channel in buffer (disregard names if so) */
+ if (gp_anim_copybuf.first == gp_anim_copybuf.last) {
+ no_name = true;
+ }
+
+ /* methods of offset (eKeyPasteOffset) */
+ switch (offset_mode) {
+ case KEYFRAME_PASTE_OFFSET_CFRA_START:
+ offset = (CFRA - gp_anim_copy_firstframe);
+ break;
+ case KEYFRAME_PASTE_OFFSET_CFRA_END:
+ offset = (CFRA - gp_anim_copy_lastframe);
+ break;
+ case KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE:
+ offset = (CFRA - gp_anim_copy_cfra);
+ break;
+ case KEYFRAME_PASTE_OFFSET_NONE:
+ offset = 0;
+ break;
+ }
+
+ /* filter data */
+ // TODO: try doing it with selection, then without selection imits
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL |
+ ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* from selected channels */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ bGPDlayer *gpld = (bGPDlayer *)ale->data;
+ bGPDlayer *gpls = NULL;
+ bGPDframe *gpfs, *gpf;
+
+ /* find suitable layer from buffer to use to paste from */
+ for (gpls = gp_anim_copybuf.first; gpls; gpls = gpls->next) {
+ /* check if layer name matches */
+ if ((no_name) || STREQ(gpls->info, gpld->info)) {
+ break;
+ }
+ }
+
+ /* this situation might occur! */
+ if (gpls == NULL)
+ continue;
+
+ /* add frames from buffer */
+ for (gpfs = gpls->frames.first; gpfs; gpfs = gpfs->next) {
+ /* temporarily apply offset to buffer-frame while copying */
+ 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);
+ if (gpf) {
+ bGPDstroke *gps, *gpsn;
+
+ /* This should be the right frame... as it may be a pre-existing frame,
+ * must make sure that only compatible stroke types get copied over
+ * - We cannot just add a duplicate frame, as that would cause errors
+ * - For now, we don't check if the types will be compatible since we
+ * don't have enough info to do so. Instead, we simply just paste,
+ * if it works, it will show up.
+ */
+ 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);
+ /* 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);
+ }
+
+ /* unapply offset from buffer-frame */
+ gpfs->framenum -= offset;
+ }
+ }
+
+ /* clean up */
+ ANIM_animdata_freelist(&anim_data);
+ return true;
}
/* -------------------------------------- */
@@ -517,53 +513,54 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
static short snap_gpf_nearest(bGPDframe *UNUSED(gpf), Scene *UNUSED(scene))
{
#if 0 /* note: gpf->framenum is already an int! */
- if (gpf->flag & GP_FRAME_SELECT)
- gpf->framenum = (int)(floor(gpf->framenum + 0.5));
+ if (gpf->flag & GP_FRAME_SELECT)
+ gpf->framenum = (int)(floor(gpf->framenum + 0.5));
#endif
- return 0;
+ return 0;
}
static short snap_gpf_nearestsec(bGPDframe *gpf, Scene *scene)
{
- float secf = (float)FPS;
- if (gpf->flag & GP_FRAME_SELECT)
- gpf->framenum = (int)(floorf(gpf->framenum / secf + 0.5f) * secf);
- return 0;
+ float secf = (float)FPS;
+ if (gpf->flag & GP_FRAME_SELECT)
+ gpf->framenum = (int)(floorf(gpf->framenum / secf + 0.5f) * secf);
+ return 0;
}
static short snap_gpf_cframe(bGPDframe *gpf, Scene *scene)
{
- if (gpf->flag & GP_FRAME_SELECT)
- gpf->framenum = (int)CFRA;
- return 0;
+ if (gpf->flag & GP_FRAME_SELECT)
+ gpf->framenum = (int)CFRA;
+ return 0;
}
static short snap_gpf_nearmarker(bGPDframe *gpf, Scene *scene)
{
- if (gpf->flag & GP_FRAME_SELECT)
- gpf->framenum = (int)ED_markers_find_nearest_marker_time(&scene->markers, (float)gpf->framenum);
- return 0;
+ if (gpf->flag & GP_FRAME_SELECT)
+ gpf->framenum = (int)ED_markers_find_nearest_marker_time(&scene->markers,
+ (float)gpf->framenum);
+ return 0;
}
/* snap selected frames to ... */
void ED_gplayer_snap_frames(bGPDlayer *gpl, Scene *scene, short mode)
{
- switch (mode) {
- case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */
- ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearest);
- break;
- case SNAP_KEYS_CURFRAME: /* snap to current frame */
- ED_gplayer_frames_looper(gpl, scene, snap_gpf_cframe);
- break;
- case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */
- ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearmarker);
- break;
- case SNAP_KEYS_NEARSEC: /* snap to nearest second */
- ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearestsec);
- break;
- default: /* just in case */
- break;
- }
+ switch (mode) {
+ case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */
+ ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearest);
+ break;
+ case SNAP_KEYS_CURFRAME: /* snap to current frame */
+ ED_gplayer_frames_looper(gpl, scene, snap_gpf_cframe);
+ break;
+ case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */
+ ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearmarker);
+ break;
+ case SNAP_KEYS_NEARSEC: /* snap to nearest second */
+ ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearestsec);
+ break;
+ default: /* just in case */
+ break;
+ }
}
/* -------------------------------------- */
@@ -571,105 +568,104 @@ void ED_gplayer_snap_frames(bGPDlayer *gpl, Scene *scene, short mode)
static short mirror_gpf_cframe(bGPDframe *gpf, Scene *scene)
{
- int diff;
+ int diff;
- if (gpf->flag & GP_FRAME_SELECT) {
- diff = CFRA - gpf->framenum;
- gpf->framenum = CFRA + diff;
- }
+ if (gpf->flag & GP_FRAME_SELECT) {
+ diff = CFRA - gpf->framenum;
+ gpf->framenum = CFRA + diff;
+ }
- return 0;
+ return 0;
}
static short mirror_gpf_yaxis(bGPDframe *gpf, Scene *UNUSED(scene))
{
- int diff;
+ int diff;
- if (gpf->flag & GP_FRAME_SELECT) {
- diff = -gpf->framenum;
- gpf->framenum = diff;
- }
+ if (gpf->flag & GP_FRAME_SELECT) {
+ diff = -gpf->framenum;
+ gpf->framenum = diff;
+ }
- return 0;
+ return 0;
}
static short mirror_gpf_xaxis(bGPDframe *gpf, Scene *UNUSED(scene))
{
- int diff;
+ int diff;
- /* NOTE: since we can't really do this, we just do the same as for yaxis... */
- if (gpf->flag & GP_FRAME_SELECT) {
- diff = -gpf->framenum;
- gpf->framenum = diff;
- }
+ /* NOTE: since we can't really do this, we just do the same as for yaxis... */
+ if (gpf->flag & GP_FRAME_SELECT) {
+ diff = -gpf->framenum;
+ gpf->framenum = diff;
+ }
- return 0;
+ return 0;
}
static short mirror_gpf_marker(bGPDframe *gpf, Scene *scene)
{
- static TimeMarker *marker;
- static short initialized = 0;
- int diff;
-
- /* 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
- * 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) {
- /* mirroring time */
- if ((gpf->flag & GP_FRAME_SELECT) && (marker)) {
- diff = (marker->frame - gpf->framenum);
- gpf->framenum = (marker->frame + diff);
- }
- }
- else {
- /* initialization time */
- if (initialized) {
- /* reset everything for safety */
- marker = NULL;
- initialized = 0;
- }
- else {
- /* try to find a marker */
- marker = ED_markers_get_first_selected(&scene->markers);
- if (marker) {
- initialized = 1;
- }
- }
- }
-
- return 0;
+ static TimeMarker *marker;
+ static short initialized = 0;
+ int diff;
+
+ /* 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
+ * 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) {
+ /* mirroring time */
+ if ((gpf->flag & GP_FRAME_SELECT) && (marker)) {
+ diff = (marker->frame - gpf->framenum);
+ gpf->framenum = (marker->frame + diff);
+ }
+ }
+ else {
+ /* initialization time */
+ if (initialized) {
+ /* reset everything for safety */
+ marker = NULL;
+ initialized = 0;
+ }
+ else {
+ /* try to find a marker */
+ marker = ED_markers_get_first_selected(&scene->markers);
+ if (marker) {
+ initialized = 1;
+ }
+ }
+ }
+
+ return 0;
}
-
/* mirror selected gp-frames on... */
// TODO: mirror over a specific time
void ED_gplayer_mirror_frames(bGPDlayer *gpl, Scene *scene, short mode)
{
- switch (mode) {
- case MIRROR_KEYS_CURFRAME: /* mirror over current frame */
- ED_gplayer_frames_looper(gpl, scene, mirror_gpf_cframe);
- break;
- case MIRROR_KEYS_YAXIS: /* mirror over frame 0 */
- ED_gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis);
- break;
- case MIRROR_KEYS_XAXIS: /* mirror over value 0 */
- ED_gplayer_frames_looper(gpl, scene, mirror_gpf_xaxis);
- break;
- case MIRROR_KEYS_MARKER: /* mirror over marker */
- mirror_gpf_marker(NULL, NULL);
- ED_gplayer_frames_looper(gpl, scene, mirror_gpf_marker);
- mirror_gpf_marker(NULL, NULL);
- break;
- default: /* just in case */
- ED_gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis);
- break;
- }
+ switch (mode) {
+ case MIRROR_KEYS_CURFRAME: /* mirror over current frame */
+ ED_gplayer_frames_looper(gpl, scene, mirror_gpf_cframe);
+ break;
+ case MIRROR_KEYS_YAXIS: /* mirror over frame 0 */
+ ED_gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis);
+ break;
+ case MIRROR_KEYS_XAXIS: /* mirror over value 0 */
+ ED_gplayer_frames_looper(gpl, scene, mirror_gpf_xaxis);
+ break;
+ case MIRROR_KEYS_MARKER: /* mirror over marker */
+ mirror_gpf_marker(NULL, NULL);
+ ED_gplayer_frames_looper(gpl, scene, mirror_gpf_marker);
+ mirror_gpf_marker(NULL, NULL);
+ break;
+ default: /* just in case */
+ ED_gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis);
+ break;
+ }
}
/* ***************************************** */
diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c
index de6ecfefb2f..4d62d169bf8 100644
--- a/source/blender/editors/gpencil/gpencil_add_monkey.c
+++ b/source/blender/editors/gpencil/gpencil_add_monkey.c
@@ -42,1386 +42,784 @@
/* Definition of the most important info from a color */
typedef struct ColorTemplate {
- const char *name;
- float line[4];
- float fill[4];
+ const char *name;
+ float line[4];
+ float fill[4];
} ColorTemplate;
/* Add color an ensure duplications (matched by name) */
static int gpencil_monkey_color(
- Main *bmain, Object *ob, const ColorTemplate *pct, bool stroke, bool fill)
+ Main *bmain, Object *ob, const ColorTemplate *pct, bool stroke, bool fill)
{
- short *totcol = give_totcolp(ob);
- Material *ma = NULL;
- for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
- if (STREQ(ma->id.name, pct->name)) {
- return i;
- }
- }
-
- int idx;
-
- /* create a new one */
- ma = BKE_gpencil_object_material_new(bmain, ob, pct->name, &idx);
-
- copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
- copy_v4_v4(ma->gp_style->fill_rgba, pct->fill);
-
- if (!stroke) {
- ma->gp_style->flag &= ~GP_STYLE_STROKE_SHOW;
- }
-
- if (!fill) {
- ma->gp_style->flag &= ~GP_STYLE_FILL_SHOW;
- }
- else {
- ma->gp_style->flag |= GP_STYLE_FILL_SHOW;
- }
-
- return idx;
+ short *totcol = give_totcolp(ob);
+ Material *ma = NULL;
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ if (STREQ(ma->id.name, pct->name)) {
+ return i;
+ }
+ }
+
+ int idx;
+
+ /* create a new one */
+ ma = BKE_gpencil_object_material_new(bmain, ob, pct->name, &idx);
+
+ copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
+ copy_v4_v4(ma->gp_style->fill_rgba, pct->fill);
+
+ if (!stroke) {
+ ma->gp_style->flag &= ~GP_STYLE_STROKE_SHOW;
+ }
+
+ if (!fill) {
+ ma->gp_style->flag &= ~GP_STYLE_FILL_SHOW;
+ }
+ else {
+ ma->gp_style->flag |= GP_STYLE_FILL_SHOW;
+ }
+
+ return idx;
}
/* ***************************************************************** */
/* Monkey Geometry */
static const float data0[270 * GP_PRIM_DATABUF_SIZE] = {
- -0.4911f, 0.0f, -0.1781f, 0.267f, 0.362f,
- -0.5168f, 0.0f, -0.1806f, 0.31f, 0.407f,
- -0.5361f, 0.0f, -0.1817f, 0.38f, 0.439f,
- -0.5618f, 0.0f, -0.1829f, 0.433f, 0.458f,
- -0.5892f, 0.0f, -0.1827f, 0.471f, 0.5f,
- -0.6193f, 0.0f, -0.1814f, 0.496f, 0.516f,
- -0.6499f, 0.0f, -0.1782f, 0.511f, 0.519f,
- -0.6808f, 0.0f, -0.1729f, 0.521f, 0.53f,
- -0.7107f, 0.0f, -0.1651f, 0.527f, 0.533f,
- -0.7404f, 0.0f, -0.1555f, 0.531f, 0.534f,
- -0.7698f, 0.0f, -0.1447f, 0.534f, 0.535f,
- -0.7993f, 0.0f, -0.1332f, 0.535f, 0.535f,
- -0.8289f, 0.0f, -0.1209f, 0.536f, 0.537f,
- -0.8586f, 0.0f, -0.109f, 0.536f, 0.537f,
- -0.8871f, 0.0f, -0.0973f, 0.536f, 0.537f,
- -0.9125f, 0.0f, -0.0838f, 0.535f, 0.535f,
- -0.9353f, 0.0f, -0.0688f, 0.534f, 0.534f,
- -0.9561f, 0.0f, -0.0525f, 0.534f, 0.534f,
- -0.9752f, 0.0f, -0.0346f, 0.533f, 0.534f,
- -0.9944f, 0.0f, -0.016f, 0.533f, 0.534f,
- -1.0148f, 0.0f, 0.0028f, 0.532f, 0.532f,
- -1.0348f, 0.0f, 0.0215f, 0.531f, 0.531f,
- -1.05f, 0.0f, 0.0407f, 0.531f, 0.531f,
- -1.0639f, 0.0f, 0.0613f, 0.532f, 0.532f,
- -1.0752f, 0.0f, 0.0838f, 0.535f, 0.535f,
- -1.0848f, 0.0f, 0.1082f, 0.54f, 0.54f,
- -1.0936f, 0.0f, 0.1346f, 0.542f, 0.542f,
- -1.1024f, 0.0f, 0.1639f, 0.543f, 0.543f,
- -1.1102f, 0.0f, 0.1953f, 0.543f, 0.543f,
- -1.1128f, 0.0f, 0.2277f, 0.546f, 0.546f,
- -1.1091f, 0.0f, 0.2579f, 0.549f, 0.549f,
- -1.1023f, 0.0f, 0.2849f, 0.549f, 0.549f,
- -1.0934f, 0.0f, 0.3086f, 0.549f, 0.549f,
- -1.0831f, 0.0f, 0.3285f, 0.549f, 0.549f,
- -1.0724f, 0.0f, 0.3451f, 0.551f, 0.551f,
- -1.0607f, 0.0f, 0.3594f, 0.553f, 0.553f,
- -1.0474f, 0.0f, 0.3713f, 0.554f, 0.554f,
- -1.031f, 0.0f, 0.3804f, 0.554f, 0.554f,
- -1.0108f, 0.0f, 0.3874f, 0.555f, 0.555f,
- -0.9862f, 0.0f, 0.3922f, 0.556f, 0.556f,
- -0.9568f, 0.0f, 0.3941f, 0.557f, 0.557f,
- -0.9243f, 0.0f, 0.3934f, 0.557f, 0.557f,
- -0.8897f, 0.0f, 0.3861f, 0.557f, 0.557f,
- -0.8556f, 0.0f, 0.3754f, 0.557f, 0.557f,
- -0.8237f, 0.0f, 0.3608f, 0.558f, 0.557f,
- -0.7982f, 0.0f, 0.344f, 0.558f, 0.558f,
- -0.7786f, 0.0f, 0.329f, 0.557f, 0.559f,
- -0.7633f, 0.0f, 0.3183f, 0.556f, 0.559f,
- -0.7498f, 0.0f, 0.3135f, 0.554f, 0.559f,
- -0.7374f, 0.0f, 0.3134f, 0.552f, 0.548f,
- -0.7261f, 0.0f, 0.3179f, 0.551f, 0.546f,
- -0.7146f, 0.0f, 0.3262f, 0.55f, 0.547f,
- -0.703f, 0.0f, 0.3395f, 0.549f, 0.547f,
- -0.692f, 0.0f, 0.3576f, 0.549f, 0.548f,
- -0.6831f, 0.0f, 0.3806f, 0.549f, 0.548f,
- -0.6748f, 0.0f, 0.4052f, 0.55f, 0.549f,
- -0.6648f, 0.0f, 0.4305f, 0.552f, 0.548f,
- -0.6527f, 0.0f, 0.4549f, 0.556f, 0.549f,
- -0.6375f, 0.0f, 0.4783f, 0.563f, 0.549f,
- -0.6195f, 0.0f, 0.5021f, 0.572f, 0.558f,
- -0.5985f, 0.0f, 0.5256f, 0.582f, 0.587f,
- -0.5775f, 0.0f, 0.5488f, 0.591f, 0.595f,
- -0.556f, 0.0f, 0.5715f, 0.597f, 0.598f,
- -0.5339f, 0.0f, 0.593f, 0.602f, 0.603f,
- -0.5119f, 0.0f, 0.613f, 0.605f, 0.606f,
- -0.4905f, 0.0f, 0.6312f, 0.607f, 0.607f,
- -0.4697f, 0.0f, 0.6474f, 0.609f, 0.607f,
- -0.4499f, 0.0f, 0.6613f, 0.612f, 0.611f,
- -0.4306f, 0.0f, 0.6734f, 0.616f, 0.615f,
- -0.4116f, 0.0f, 0.6845f, 0.619f, 0.621f,
- -0.3918f, 0.0f, 0.6954f, 0.623f, 0.623f,
- -0.3709f, 0.0f, 0.7059f, 0.626f, 0.626f,
- -0.3486f, 0.0f, 0.7157f, 0.63f, 0.63f,
- -0.3251f, 0.0f, 0.7249f, 0.637f, 0.632f,
- -0.3006f, 0.0f, 0.7333f, 0.646f, 0.644f,
- -0.2755f, 0.0f, 0.7414f, 0.654f, 0.657f,
- -0.25f, 0.0f, 0.7489f, 0.659f, 0.661f,
- -0.2242f, 0.0f, 0.7562f, 0.664f, 0.664f,
- -0.1979f, 0.0f, 0.7631f, 0.667f, 0.668f,
- -0.171f, 0.0f, 0.7695f, 0.671f, 0.671f,
- -0.1434f, 0.0f, 0.7752f, 0.674f, 0.674f,
- -0.1151f, 0.0f, 0.7801f, 0.677f, 0.678f,
- -0.0861f, 0.0f, 0.7841f, 0.678f, 0.68f,
- -0.0563f, 0.0f, 0.7869f, 0.68f, 0.68f,
- -0.026f, 0.0f, 0.7889f, 0.68f, 0.68f,
- 0.0049f, 0.0f, 0.7899f, 0.681f, 0.681f,
- 0.0362f, 0.0f, 0.7898f, 0.682f, 0.681f,
- 0.0679f, 0.0f, 0.7881f, 0.683f, 0.683f,
- 0.0996f, 0.0f, 0.7853f, 0.685f, 0.683f,
- 0.1313f, 0.0f, 0.7812f, 0.687f, 0.685f,
- 0.1632f, 0.0f, 0.7756f, 0.69f, 0.686f,
- 0.1953f, 0.0f, 0.7687f, 0.693f, 0.694f,
- 0.2277f, 0.0f, 0.7608f, 0.697f, 0.697f,
- 0.2606f, 0.0f, 0.7513f, 0.7f, 0.7f,
- 0.2934f, 0.0f, 0.7404f, 0.704f, 0.704f,
- 0.3258f, 0.0f, 0.7276f, 0.707f, 0.71f,
- 0.357f, 0.0f, 0.7135f, 0.709f, 0.711f,
- 0.387f, 0.0f, 0.6983f, 0.711f, 0.713f,
- 0.4157f, 0.0f, 0.6819f, 0.712f, 0.714f,
- 0.444f, 0.0f, 0.6645f, 0.714f, 0.714f,
- 0.4719f, 0.0f, 0.6459f, 0.715f, 0.715f,
- 0.4994f, 0.0f, 0.6261f, 0.715f, 0.716f,
- 0.526f, 0.0f, 0.6046f, 0.716f, 0.716f,
- 0.552f, 0.0f, 0.5816f, 0.717f, 0.717f,
- 0.577f, 0.0f, 0.5575f, 0.718f, 0.717f,
- 0.6008f, 0.0f, 0.5328f, 0.718f, 0.718f,
- 0.6231f, 0.0f, 0.5077f, 0.718f, 0.718f,
- 0.6423f, 0.0f, 0.4829f, 0.719f, 0.718f,
- 0.658f, 0.0f, 0.4617f, 0.719f, 0.719f,
- 0.6713f, 0.0f, 0.4432f, 0.719f, 0.719f,
- 0.6828f, 0.0f, 0.4266f, 0.719f, 0.719f,
- 0.6928f, 0.0f, 0.4118f, 0.719f, 0.719f,
- 0.7016f, 0.0f, 0.3987f, 0.718f, 0.717f,
- 0.7094f, 0.0f, 0.3871f, 0.717f, 0.717f,
- 0.7165f, 0.0f, 0.3769f, 0.717f, 0.717f,
- 0.7233f, 0.0f, 0.3679f, 0.718f, 0.718f,
- 0.7301f, 0.0f, 0.3598f, 0.717f, 0.719f,
- 0.7373f, 0.0f, 0.3524f, 0.715f, 0.719f,
- 0.7454f, 0.0f, 0.3458f, 0.713f, 0.709f,
- 0.7545f, 0.0f, 0.3398f, 0.718f, 0.704f,
- 0.7651f, 0.0f, 0.3351f, 0.732f, 0.705f,
- 0.777f, 0.0f, 0.3317f, 0.753f, 0.713f,
- 0.7909f, 0.0f, 0.3311f, 0.774f, 0.813f,
- 0.8068f, 0.0f, 0.334f, 0.791f, 0.815f,
- 0.8246f, 0.0f, 0.3398f, 0.802f, 0.815f,
- 0.8438f, 0.0f, 0.3486f, 0.809f, 0.816f,
- 0.8651f, 0.0f, 0.3575f, 0.812f, 0.816f,
- 0.8893f, 0.0f, 0.3665f, 0.814f, 0.816f,
- 0.9166f, 0.0f, 0.374f, 0.814f, 0.817f,
- 0.9459f, 0.0f, 0.3791f, 0.812f, 0.817f,
- 0.9751f, 0.0f, 0.3811f, 0.81f, 0.815f,
- 1.0029f, 0.0f, 0.38f, 0.806f, 0.807f,
- 1.0288f, 0.0f, 0.3754f, 0.8f, 0.801f,
- 1.052f, 0.0f, 0.3673f, 0.794f, 0.8f,
- 1.0722f, 0.0f, 0.3556f, 0.788f, 0.781f,
- 1.0888f, 0.0f, 0.3403f, 0.783f, 0.78f,
- 1.1027f, 0.0f, 0.322f, 0.781f, 0.778f,
- 1.1133f, 0.0f, 0.301f, 0.779f, 0.777f,
- 1.1215f, 0.0f, 0.278f, 0.778f, 0.777f,
- 1.1269f, 0.0f, 0.2534f, 0.777f, 0.777f,
- 1.1296f, 0.0f, 0.2284f, 0.777f, 0.778f,
- 1.1292f, 0.0f, 0.2031f, 0.776f, 0.776f,
- 1.1254f, 0.0f, 0.1778f, 0.775f, 0.776f,
- 1.1178f, 0.0f, 0.153f, 0.774f, 0.774f,
- 1.1076f, 0.0f, 0.1299f, 0.774f, 0.772f,
- 1.0955f, 0.0f, 0.1079f, 0.773f, 0.773f,
- 1.0817f, 0.0f, 0.087f, 0.772f, 0.773f,
- 1.0668f, 0.0f, 0.0677f, 0.771f, 0.772f,
- 1.0508f, 0.0f, 0.0491f, 0.77f, 0.772f,
- 1.0339f, 0.0f, 0.0313f, 0.768f, 0.766f,
- 1.0157f, 0.0f, 0.0144f, 0.767f, 0.765f,
- 0.9969f, 0.0f, -0.0015f, 0.766f, 0.765f,
- 0.9784f, 0.0f, -0.017f, 0.765f, 0.766f,
- 0.96f, 0.0f, -0.0321f, 0.764f, 0.765f,
- 0.9413f, 0.0f, -0.0468f, 0.761f, 0.765f,
- 0.9216f, 0.0f, -0.0611f, 0.756f, 0.761f,
- 0.9009f, 0.0f, -0.0751f, 0.751f, 0.751f,
- 0.8787f, 0.0f, -0.0893f, 0.745f, 0.744f,
- 0.8556f, 0.0f, -0.1027f, 0.739f, 0.738f,
- 0.8312f, 0.0f, -0.1152f, 0.733f, 0.731f,
- 0.8058f, 0.0f, -0.1268f, 0.728f, 0.727f,
- 0.7788f, 0.0f, -0.1372f, 0.723f, 0.723f,
- 0.7505f, 0.0f, -0.1467f, 0.718f, 0.717f,
- 0.7214f, 0.0f, -0.1549f, 0.713f, 0.708f,
- 0.6929f, 0.0f, -0.1617f, 0.709f, 0.706f,
- 0.6652f, 0.0f, -0.1665f, 0.704f, 0.705f,
- 0.6388f, 0.0f, -0.1691f, 0.7f, 0.704f,
- 0.6131f, 0.0f, -0.1701f, 0.695f, 0.698f,
- 0.5883f, 0.0f, -0.1699f, 0.691f, 0.691f,
- 0.5644f, 0.0f, -0.1691f, 0.686f, 0.685f,
- 0.5416f, 0.0f, -0.1683f, 0.681f, 0.683f,
- 0.5195f, 0.0f, -0.168f, 0.676f, 0.676f,
- 0.4975f, 0.0f, -0.1687f, 0.671f, 0.67f,
- 0.4754f, 0.0f, -0.1705f, 0.666f, 0.663f,
- 0.4527f, 0.0f, -0.1741f, 0.663f, 0.66f,
- 0.4293f, 0.0f, -0.1797f, 0.661f, 0.659f,
- 0.4054f, 0.0f, -0.1881f, 0.66f, 0.659f,
- 0.3813f, 0.0f, -0.1992f, 0.659f, 0.657f,
- 0.3585f, 0.0f, -0.212f, 0.658f, 0.659f,
- 0.3368f, 0.0f, -0.2266f, 0.658f, 0.659f,
- 0.3174f, 0.0f, -0.2426f, 0.658f, 0.659f,
- 0.2996f, 0.0f, -0.2594f, 0.657f, 0.657f,
- 0.284f, 0.0f, -0.2768f, 0.656f, 0.658f,
- 0.2702f, 0.0f, -0.2946f, 0.653f, 0.657f,
- 0.2585f, 0.0f, -0.3127f, 0.646f, 0.656f,
- 0.25f, 0.0f, -0.3308f, 0.637f, 0.642f,
- 0.2447f, 0.0f, -0.3489f, 0.628f, 0.609f,
- 0.2418f, 0.0f, -0.3672f, 0.62f, 0.608f,
- 0.2412f, 0.0f, -0.386f, 0.614f, 0.607f,
- 0.2425f, 0.0f, -0.4051f, 0.61f, 0.606f,
- 0.2456f, 0.0f, -0.4246f, 0.608f, 0.604f,
- 0.2509f, 0.0f, -0.4447f, 0.607f, 0.606f,
- 0.2576f, 0.0f, -0.4652f, 0.606f, 0.607f,
- 0.2666f, 0.0f, -0.4867f, 0.605f, 0.607f,
- 0.2766f, 0.0f, -0.5091f, 0.603f, 0.607f,
- 0.2871f, 0.0f, -0.5326f, 0.598f, 0.606f,
- 0.2973f, 0.0f, -0.5569f, 0.591f, 0.602f,
- 0.306f, 0.0f, -0.5826f, 0.583f, 0.585f,
- 0.3131f, 0.0f, -0.61f, 0.574f, 0.576f,
- 0.3197f, 0.0f, -0.6384f, 0.564f, 0.564f,
- 0.326f, 0.0f, -0.6681f, 0.555f, 0.549f,
- 0.3315f, 0.0f, -0.6984f, 0.547f, 0.543f,
- 0.336f, 0.0f, -0.7291f, 0.541f, 0.541f,
- 0.3391f, 0.0f, -0.7593f, 0.536f, 0.538f,
- 0.3399f, 0.0f, -0.7884f, 0.532f, 0.528f,
- 0.3382f, 0.0f, -0.8158f, 0.529f, 0.528f,
- 0.334f, 0.0f, -0.8417f, 0.525f, 0.529f,
- 0.3273f, 0.0f, -0.8657f, 0.521f, 0.528f,
- 0.3185f, 0.0f, -0.8881f, 0.516f, 0.515f,
- 0.3073f, 0.0f, -0.9088f, 0.51f, 0.514f,
- 0.2941f, 0.0f, -0.9278f, 0.505f, 0.507f,
- 0.2786f, 0.0f, -0.9449f, 0.499f, 0.494f,
- 0.261f, 0.0f, -0.96f, 0.495f, 0.49f,
- 0.2413f, 0.0f, -0.9733f, 0.493f, 0.491f,
- 0.2193f, 0.0f, -0.9845f, 0.491f, 0.489f,
- 0.1953f, 0.0f, -0.9935f, 0.491f, 0.491f,
- 0.1693f, 0.0f, -1.0004f, 0.491f, 0.492f,
- 0.1421f, 0.0f, -1.0051f, 0.492f, 0.492f,
- 0.1136f, 0.0f, -1.0072f, 0.492f, 0.492f,
- 0.0842f, 0.0f, -1.0073f, 0.492f, 0.492f,
- 0.0548f, 0.0f, -1.0059f, 0.493f, 0.494f,
- 0.0258f, 0.0f, -1.0037f, 0.493f, 0.494f,
- -0.0027f, 0.0f, -1.0003f, 0.493f, 0.493f,
- -0.0309f, 0.0f, -0.9959f, 0.492f, 0.492f,
- -0.0584f, 0.0f, -0.9904f, 0.491f, 0.492f,
- -0.0858f, 0.0f, -0.9848f, 0.491f, 0.491f,
- -0.1127f, 0.0f, -0.9783f, 0.49f, 0.49f,
- -0.1386f, 0.0f, -0.9703f, 0.49f, 0.49f,
- -0.1649f, 0.0f, -0.9604f, 0.489f, 0.489f,
- -0.191f, 0.0f, -0.9479f, 0.489f, 0.489f,
- -0.2165f, 0.0f, -0.9345f, 0.489f, 0.49f,
- -0.2414f, 0.0f, -0.9205f, 0.489f, 0.489f,
- -0.2654f, 0.0f, -0.9055f, 0.489f, 0.489f,
- -0.2877f, 0.0f, -0.8898f, 0.49f, 0.49f,
- -0.3076f, 0.0f, -0.8723f, 0.49f, 0.489f,
- -0.324f, 0.0f, -0.8532f, 0.491f, 0.489f,
- -0.3367f, 0.0f, -0.8316f, 0.492f, 0.489f,
- -0.3451f, 0.0f, -0.8077f, 0.494f, 0.488f,
- -0.3505f, 0.0f, -0.7829f, 0.497f, 0.49f,
- -0.3531f, 0.0f, -0.7584f, 0.501f, 0.497f,
- -0.3528f, 0.0f, -0.7349f, 0.505f, 0.504f,
- -0.3503f, 0.0f, -0.7115f, 0.51f, 0.51f,
- -0.346f, 0.0f, -0.688f, 0.515f, 0.515f,
- -0.3411f, 0.0f, -0.6643f, 0.52f, 0.522f,
- -0.3361f, 0.0f, -0.6403f, 0.525f, 0.528f,
- -0.3304f, 0.0f, -0.6164f, 0.53f, 0.532f,
- -0.3244f, 0.0f, -0.5925f, 0.535f, 0.535f,
- -0.318f, 0.0f, -0.5687f, 0.539f, 0.54f,
- -0.3124f, 0.0f, -0.5441f, 0.542f, 0.545f,
- -0.3051f, 0.0f, -0.5191f, 0.546f, 0.549f,
- -0.2959f, 0.0f, -0.4917f, 0.548f, 0.549f,
- -0.2882f, 0.0f, -0.4639f, 0.55f, 0.552f,
- -0.2814f, 0.0f, -0.4363f, 0.551f, 0.552f,
- -0.2759f, 0.0f, -0.4084f, 0.552f, 0.553f,
- -0.2707f, 0.0f, -0.3827f, 0.553f, 0.553f,
- -0.2703f, 0.0f, -0.3586f, 0.554f, 0.553f,
- -0.2772f, 0.0f, -0.3375f, 0.554f, 0.554f,
- -0.2871f, 0.0f, -0.3178f, 0.555f, 0.555f,
- -0.2995f, 0.0f, -0.2996f, 0.556f, 0.555f,
- -0.3145f, 0.0f, -0.283f, 0.556f, 0.557f,
- -0.332f, 0.0f, -0.2672f, 0.557f, 0.557f,
- -0.3488f, 0.0f, -0.2531f, 0.558f, 0.558f,
- -0.3639f, 0.0f, -0.2407f, 0.558f, 0.558f,
- -0.3778f, 0.0f, -0.2292f, 0.558f, 0.558f,
- -0.3909f, 0.0f, -0.2191f, 0.559f, 0.559f,
- -0.4032f, 0.0f, -0.2102f, 0.559f, 0.558f,
- -0.4146f, 0.0f, -0.2027f, 0.559f, 0.559f,
- -0.426f, 0.0f, -0.1968f, 0.558f, 0.558f,
- -0.4348f, 0.0f, -0.1931f, 0.558f, 0.558f,
- -0.4479f, 0.0f, -0.1886f, 0.555f, 0.559f,
+ -0.4911f, 0.0f, -0.1781f, 0.267f, 0.362f, -0.5168f, 0.0f, -0.1806f, 0.31f, 0.407f,
+ -0.5361f, 0.0f, -0.1817f, 0.38f, 0.439f, -0.5618f, 0.0f, -0.1829f, 0.433f, 0.458f,
+ -0.5892f, 0.0f, -0.1827f, 0.471f, 0.5f, -0.6193f, 0.0f, -0.1814f, 0.496f, 0.516f,
+ -0.6499f, 0.0f, -0.1782f, 0.511f, 0.519f, -0.6808f, 0.0f, -0.1729f, 0.521f, 0.53f,
+ -0.7107f, 0.0f, -0.1651f, 0.527f, 0.533f, -0.7404f, 0.0f, -0.1555f, 0.531f, 0.534f,
+ -0.7698f, 0.0f, -0.1447f, 0.534f, 0.535f, -0.7993f, 0.0f, -0.1332f, 0.535f, 0.535f,
+ -0.8289f, 0.0f, -0.1209f, 0.536f, 0.537f, -0.8586f, 0.0f, -0.109f, 0.536f, 0.537f,
+ -0.8871f, 0.0f, -0.0973f, 0.536f, 0.537f, -0.9125f, 0.0f, -0.0838f, 0.535f, 0.535f,
+ -0.9353f, 0.0f, -0.0688f, 0.534f, 0.534f, -0.9561f, 0.0f, -0.0525f, 0.534f, 0.534f,
+ -0.9752f, 0.0f, -0.0346f, 0.533f, 0.534f, -0.9944f, 0.0f, -0.016f, 0.533f, 0.534f,
+ -1.0148f, 0.0f, 0.0028f, 0.532f, 0.532f, -1.0348f, 0.0f, 0.0215f, 0.531f, 0.531f,
+ -1.05f, 0.0f, 0.0407f, 0.531f, 0.531f, -1.0639f, 0.0f, 0.0613f, 0.532f, 0.532f,
+ -1.0752f, 0.0f, 0.0838f, 0.535f, 0.535f, -1.0848f, 0.0f, 0.1082f, 0.54f, 0.54f,
+ -1.0936f, 0.0f, 0.1346f, 0.542f, 0.542f, -1.1024f, 0.0f, 0.1639f, 0.543f, 0.543f,
+ -1.1102f, 0.0f, 0.1953f, 0.543f, 0.543f, -1.1128f, 0.0f, 0.2277f, 0.546f, 0.546f,
+ -1.1091f, 0.0f, 0.2579f, 0.549f, 0.549f, -1.1023f, 0.0f, 0.2849f, 0.549f, 0.549f,
+ -1.0934f, 0.0f, 0.3086f, 0.549f, 0.549f, -1.0831f, 0.0f, 0.3285f, 0.549f, 0.549f,
+ -1.0724f, 0.0f, 0.3451f, 0.551f, 0.551f, -1.0607f, 0.0f, 0.3594f, 0.553f, 0.553f,
+ -1.0474f, 0.0f, 0.3713f, 0.554f, 0.554f, -1.031f, 0.0f, 0.3804f, 0.554f, 0.554f,
+ -1.0108f, 0.0f, 0.3874f, 0.555f, 0.555f, -0.9862f, 0.0f, 0.3922f, 0.556f, 0.556f,
+ -0.9568f, 0.0f, 0.3941f, 0.557f, 0.557f, -0.9243f, 0.0f, 0.3934f, 0.557f, 0.557f,
+ -0.8897f, 0.0f, 0.3861f, 0.557f, 0.557f, -0.8556f, 0.0f, 0.3754f, 0.557f, 0.557f,
+ -0.8237f, 0.0f, 0.3608f, 0.558f, 0.557f, -0.7982f, 0.0f, 0.344f, 0.558f, 0.558f,
+ -0.7786f, 0.0f, 0.329f, 0.557f, 0.559f, -0.7633f, 0.0f, 0.3183f, 0.556f, 0.559f,
+ -0.7498f, 0.0f, 0.3135f, 0.554f, 0.559f, -0.7374f, 0.0f, 0.3134f, 0.552f, 0.548f,
+ -0.7261f, 0.0f, 0.3179f, 0.551f, 0.546f, -0.7146f, 0.0f, 0.3262f, 0.55f, 0.547f,
+ -0.703f, 0.0f, 0.3395f, 0.549f, 0.547f, -0.692f, 0.0f, 0.3576f, 0.549f, 0.548f,
+ -0.6831f, 0.0f, 0.3806f, 0.549f, 0.548f, -0.6748f, 0.0f, 0.4052f, 0.55f, 0.549f,
+ -0.6648f, 0.0f, 0.4305f, 0.552f, 0.548f, -0.6527f, 0.0f, 0.4549f, 0.556f, 0.549f,
+ -0.6375f, 0.0f, 0.4783f, 0.563f, 0.549f, -0.6195f, 0.0f, 0.5021f, 0.572f, 0.558f,
+ -0.5985f, 0.0f, 0.5256f, 0.582f, 0.587f, -0.5775f, 0.0f, 0.5488f, 0.591f, 0.595f,
+ -0.556f, 0.0f, 0.5715f, 0.597f, 0.598f, -0.5339f, 0.0f, 0.593f, 0.602f, 0.603f,
+ -0.5119f, 0.0f, 0.613f, 0.605f, 0.606f, -0.4905f, 0.0f, 0.6312f, 0.607f, 0.607f,
+ -0.4697f, 0.0f, 0.6474f, 0.609f, 0.607f, -0.4499f, 0.0f, 0.6613f, 0.612f, 0.611f,
+ -0.4306f, 0.0f, 0.6734f, 0.616f, 0.615f, -0.4116f, 0.0f, 0.6845f, 0.619f, 0.621f,
+ -0.3918f, 0.0f, 0.6954f, 0.623f, 0.623f, -0.3709f, 0.0f, 0.7059f, 0.626f, 0.626f,
+ -0.3486f, 0.0f, 0.7157f, 0.63f, 0.63f, -0.3251f, 0.0f, 0.7249f, 0.637f, 0.632f,
+ -0.3006f, 0.0f, 0.7333f, 0.646f, 0.644f, -0.2755f, 0.0f, 0.7414f, 0.654f, 0.657f,
+ -0.25f, 0.0f, 0.7489f, 0.659f, 0.661f, -0.2242f, 0.0f, 0.7562f, 0.664f, 0.664f,
+ -0.1979f, 0.0f, 0.7631f, 0.667f, 0.668f, -0.171f, 0.0f, 0.7695f, 0.671f, 0.671f,
+ -0.1434f, 0.0f, 0.7752f, 0.674f, 0.674f, -0.1151f, 0.0f, 0.7801f, 0.677f, 0.678f,
+ -0.0861f, 0.0f, 0.7841f, 0.678f, 0.68f, -0.0563f, 0.0f, 0.7869f, 0.68f, 0.68f,
+ -0.026f, 0.0f, 0.7889f, 0.68f, 0.68f, 0.0049f, 0.0f, 0.7899f, 0.681f, 0.681f,
+ 0.0362f, 0.0f, 0.7898f, 0.682f, 0.681f, 0.0679f, 0.0f, 0.7881f, 0.683f, 0.683f,
+ 0.0996f, 0.0f, 0.7853f, 0.685f, 0.683f, 0.1313f, 0.0f, 0.7812f, 0.687f, 0.685f,
+ 0.1632f, 0.0f, 0.7756f, 0.69f, 0.686f, 0.1953f, 0.0f, 0.7687f, 0.693f, 0.694f,
+ 0.2277f, 0.0f, 0.7608f, 0.697f, 0.697f, 0.2606f, 0.0f, 0.7513f, 0.7f, 0.7f,
+ 0.2934f, 0.0f, 0.7404f, 0.704f, 0.704f, 0.3258f, 0.0f, 0.7276f, 0.707f, 0.71f,
+ 0.357f, 0.0f, 0.7135f, 0.709f, 0.711f, 0.387f, 0.0f, 0.6983f, 0.711f, 0.713f,
+ 0.4157f, 0.0f, 0.6819f, 0.712f, 0.714f, 0.444f, 0.0f, 0.6645f, 0.714f, 0.714f,
+ 0.4719f, 0.0f, 0.6459f, 0.715f, 0.715f, 0.4994f, 0.0f, 0.6261f, 0.715f, 0.716f,
+ 0.526f, 0.0f, 0.6046f, 0.716f, 0.716f, 0.552f, 0.0f, 0.5816f, 0.717f, 0.717f,
+ 0.577f, 0.0f, 0.5575f, 0.718f, 0.717f, 0.6008f, 0.0f, 0.5328f, 0.718f, 0.718f,
+ 0.6231f, 0.0f, 0.5077f, 0.718f, 0.718f, 0.6423f, 0.0f, 0.4829f, 0.719f, 0.718f,
+ 0.658f, 0.0f, 0.4617f, 0.719f, 0.719f, 0.6713f, 0.0f, 0.4432f, 0.719f, 0.719f,
+ 0.6828f, 0.0f, 0.4266f, 0.719f, 0.719f, 0.6928f, 0.0f, 0.4118f, 0.719f, 0.719f,
+ 0.7016f, 0.0f, 0.3987f, 0.718f, 0.717f, 0.7094f, 0.0f, 0.3871f, 0.717f, 0.717f,
+ 0.7165f, 0.0f, 0.3769f, 0.717f, 0.717f, 0.7233f, 0.0f, 0.3679f, 0.718f, 0.718f,
+ 0.7301f, 0.0f, 0.3598f, 0.717f, 0.719f, 0.7373f, 0.0f, 0.3524f, 0.715f, 0.719f,
+ 0.7454f, 0.0f, 0.3458f, 0.713f, 0.709f, 0.7545f, 0.0f, 0.3398f, 0.718f, 0.704f,
+ 0.7651f, 0.0f, 0.3351f, 0.732f, 0.705f, 0.777f, 0.0f, 0.3317f, 0.753f, 0.713f,
+ 0.7909f, 0.0f, 0.3311f, 0.774f, 0.813f, 0.8068f, 0.0f, 0.334f, 0.791f, 0.815f,
+ 0.8246f, 0.0f, 0.3398f, 0.802f, 0.815f, 0.8438f, 0.0f, 0.3486f, 0.809f, 0.816f,
+ 0.8651f, 0.0f, 0.3575f, 0.812f, 0.816f, 0.8893f, 0.0f, 0.3665f, 0.814f, 0.816f,
+ 0.9166f, 0.0f, 0.374f, 0.814f, 0.817f, 0.9459f, 0.0f, 0.3791f, 0.812f, 0.817f,
+ 0.9751f, 0.0f, 0.3811f, 0.81f, 0.815f, 1.0029f, 0.0f, 0.38f, 0.806f, 0.807f,
+ 1.0288f, 0.0f, 0.3754f, 0.8f, 0.801f, 1.052f, 0.0f, 0.3673f, 0.794f, 0.8f,
+ 1.0722f, 0.0f, 0.3556f, 0.788f, 0.781f, 1.0888f, 0.0f, 0.3403f, 0.783f, 0.78f,
+ 1.1027f, 0.0f, 0.322f, 0.781f, 0.778f, 1.1133f, 0.0f, 0.301f, 0.779f, 0.777f,
+ 1.1215f, 0.0f, 0.278f, 0.778f, 0.777f, 1.1269f, 0.0f, 0.2534f, 0.777f, 0.777f,
+ 1.1296f, 0.0f, 0.2284f, 0.777f, 0.778f, 1.1292f, 0.0f, 0.2031f, 0.776f, 0.776f,
+ 1.1254f, 0.0f, 0.1778f, 0.775f, 0.776f, 1.1178f, 0.0f, 0.153f, 0.774f, 0.774f,
+ 1.1076f, 0.0f, 0.1299f, 0.774f, 0.772f, 1.0955f, 0.0f, 0.1079f, 0.773f, 0.773f,
+ 1.0817f, 0.0f, 0.087f, 0.772f, 0.773f, 1.0668f, 0.0f, 0.0677f, 0.771f, 0.772f,
+ 1.0508f, 0.0f, 0.0491f, 0.77f, 0.772f, 1.0339f, 0.0f, 0.0313f, 0.768f, 0.766f,
+ 1.0157f, 0.0f, 0.0144f, 0.767f, 0.765f, 0.9969f, 0.0f, -0.0015f, 0.766f, 0.765f,
+ 0.9784f, 0.0f, -0.017f, 0.765f, 0.766f, 0.96f, 0.0f, -0.0321f, 0.764f, 0.765f,
+ 0.9413f, 0.0f, -0.0468f, 0.761f, 0.765f, 0.9216f, 0.0f, -0.0611f, 0.756f, 0.761f,
+ 0.9009f, 0.0f, -0.0751f, 0.751f, 0.751f, 0.8787f, 0.0f, -0.0893f, 0.745f, 0.744f,
+ 0.8556f, 0.0f, -0.1027f, 0.739f, 0.738f, 0.8312f, 0.0f, -0.1152f, 0.733f, 0.731f,
+ 0.8058f, 0.0f, -0.1268f, 0.728f, 0.727f, 0.7788f, 0.0f, -0.1372f, 0.723f, 0.723f,
+ 0.7505f, 0.0f, -0.1467f, 0.718f, 0.717f, 0.7214f, 0.0f, -0.1549f, 0.713f, 0.708f,
+ 0.6929f, 0.0f, -0.1617f, 0.709f, 0.706f, 0.6652f, 0.0f, -0.1665f, 0.704f, 0.705f,
+ 0.6388f, 0.0f, -0.1691f, 0.7f, 0.704f, 0.6131f, 0.0f, -0.1701f, 0.695f, 0.698f,
+ 0.5883f, 0.0f, -0.1699f, 0.691f, 0.691f, 0.5644f, 0.0f, -0.1691f, 0.686f, 0.685f,
+ 0.5416f, 0.0f, -0.1683f, 0.681f, 0.683f, 0.5195f, 0.0f, -0.168f, 0.676f, 0.676f,
+ 0.4975f, 0.0f, -0.1687f, 0.671f, 0.67f, 0.4754f, 0.0f, -0.1705f, 0.666f, 0.663f,
+ 0.4527f, 0.0f, -0.1741f, 0.663f, 0.66f, 0.4293f, 0.0f, -0.1797f, 0.661f, 0.659f,
+ 0.4054f, 0.0f, -0.1881f, 0.66f, 0.659f, 0.3813f, 0.0f, -0.1992f, 0.659f, 0.657f,
+ 0.3585f, 0.0f, -0.212f, 0.658f, 0.659f, 0.3368f, 0.0f, -0.2266f, 0.658f, 0.659f,
+ 0.3174f, 0.0f, -0.2426f, 0.658f, 0.659f, 0.2996f, 0.0f, -0.2594f, 0.657f, 0.657f,
+ 0.284f, 0.0f, -0.2768f, 0.656f, 0.658f, 0.2702f, 0.0f, -0.2946f, 0.653f, 0.657f,
+ 0.2585f, 0.0f, -0.3127f, 0.646f, 0.656f, 0.25f, 0.0f, -0.3308f, 0.637f, 0.642f,
+ 0.2447f, 0.0f, -0.3489f, 0.628f, 0.609f, 0.2418f, 0.0f, -0.3672f, 0.62f, 0.608f,
+ 0.2412f, 0.0f, -0.386f, 0.614f, 0.607f, 0.2425f, 0.0f, -0.4051f, 0.61f, 0.606f,
+ 0.2456f, 0.0f, -0.4246f, 0.608f, 0.604f, 0.2509f, 0.0f, -0.4447f, 0.607f, 0.606f,
+ 0.2576f, 0.0f, -0.4652f, 0.606f, 0.607f, 0.2666f, 0.0f, -0.4867f, 0.605f, 0.607f,
+ 0.2766f, 0.0f, -0.5091f, 0.603f, 0.607f, 0.2871f, 0.0f, -0.5326f, 0.598f, 0.606f,
+ 0.2973f, 0.0f, -0.5569f, 0.591f, 0.602f, 0.306f, 0.0f, -0.5826f, 0.583f, 0.585f,
+ 0.3131f, 0.0f, -0.61f, 0.574f, 0.576f, 0.3197f, 0.0f, -0.6384f, 0.564f, 0.564f,
+ 0.326f, 0.0f, -0.6681f, 0.555f, 0.549f, 0.3315f, 0.0f, -0.6984f, 0.547f, 0.543f,
+ 0.336f, 0.0f, -0.7291f, 0.541f, 0.541f, 0.3391f, 0.0f, -0.7593f, 0.536f, 0.538f,
+ 0.3399f, 0.0f, -0.7884f, 0.532f, 0.528f, 0.3382f, 0.0f, -0.8158f, 0.529f, 0.528f,
+ 0.334f, 0.0f, -0.8417f, 0.525f, 0.529f, 0.3273f, 0.0f, -0.8657f, 0.521f, 0.528f,
+ 0.3185f, 0.0f, -0.8881f, 0.516f, 0.515f, 0.3073f, 0.0f, -0.9088f, 0.51f, 0.514f,
+ 0.2941f, 0.0f, -0.9278f, 0.505f, 0.507f, 0.2786f, 0.0f, -0.9449f, 0.499f, 0.494f,
+ 0.261f, 0.0f, -0.96f, 0.495f, 0.49f, 0.2413f, 0.0f, -0.9733f, 0.493f, 0.491f,
+ 0.2193f, 0.0f, -0.9845f, 0.491f, 0.489f, 0.1953f, 0.0f, -0.9935f, 0.491f, 0.491f,
+ 0.1693f, 0.0f, -1.0004f, 0.491f, 0.492f, 0.1421f, 0.0f, -1.0051f, 0.492f, 0.492f,
+ 0.1136f, 0.0f, -1.0072f, 0.492f, 0.492f, 0.0842f, 0.0f, -1.0073f, 0.492f, 0.492f,
+ 0.0548f, 0.0f, -1.0059f, 0.493f, 0.494f, 0.0258f, 0.0f, -1.0037f, 0.493f, 0.494f,
+ -0.0027f, 0.0f, -1.0003f, 0.493f, 0.493f, -0.0309f, 0.0f, -0.9959f, 0.492f, 0.492f,
+ -0.0584f, 0.0f, -0.9904f, 0.491f, 0.492f, -0.0858f, 0.0f, -0.9848f, 0.491f, 0.491f,
+ -0.1127f, 0.0f, -0.9783f, 0.49f, 0.49f, -0.1386f, 0.0f, -0.9703f, 0.49f, 0.49f,
+ -0.1649f, 0.0f, -0.9604f, 0.489f, 0.489f, -0.191f, 0.0f, -0.9479f, 0.489f, 0.489f,
+ -0.2165f, 0.0f, -0.9345f, 0.489f, 0.49f, -0.2414f, 0.0f, -0.9205f, 0.489f, 0.489f,
+ -0.2654f, 0.0f, -0.9055f, 0.489f, 0.489f, -0.2877f, 0.0f, -0.8898f, 0.49f, 0.49f,
+ -0.3076f, 0.0f, -0.8723f, 0.49f, 0.489f, -0.324f, 0.0f, -0.8532f, 0.491f, 0.489f,
+ -0.3367f, 0.0f, -0.8316f, 0.492f, 0.489f, -0.3451f, 0.0f, -0.8077f, 0.494f, 0.488f,
+ -0.3505f, 0.0f, -0.7829f, 0.497f, 0.49f, -0.3531f, 0.0f, -0.7584f, 0.501f, 0.497f,
+ -0.3528f, 0.0f, -0.7349f, 0.505f, 0.504f, -0.3503f, 0.0f, -0.7115f, 0.51f, 0.51f,
+ -0.346f, 0.0f, -0.688f, 0.515f, 0.515f, -0.3411f, 0.0f, -0.6643f, 0.52f, 0.522f,
+ -0.3361f, 0.0f, -0.6403f, 0.525f, 0.528f, -0.3304f, 0.0f, -0.6164f, 0.53f, 0.532f,
+ -0.3244f, 0.0f, -0.5925f, 0.535f, 0.535f, -0.318f, 0.0f, -0.5687f, 0.539f, 0.54f,
+ -0.3124f, 0.0f, -0.5441f, 0.542f, 0.545f, -0.3051f, 0.0f, -0.5191f, 0.546f, 0.549f,
+ -0.2959f, 0.0f, -0.4917f, 0.548f, 0.549f, -0.2882f, 0.0f, -0.4639f, 0.55f, 0.552f,
+ -0.2814f, 0.0f, -0.4363f, 0.551f, 0.552f, -0.2759f, 0.0f, -0.4084f, 0.552f, 0.553f,
+ -0.2707f, 0.0f, -0.3827f, 0.553f, 0.553f, -0.2703f, 0.0f, -0.3586f, 0.554f, 0.553f,
+ -0.2772f, 0.0f, -0.3375f, 0.554f, 0.554f, -0.2871f, 0.0f, -0.3178f, 0.555f, 0.555f,
+ -0.2995f, 0.0f, -0.2996f, 0.556f, 0.555f, -0.3145f, 0.0f, -0.283f, 0.556f, 0.557f,
+ -0.332f, 0.0f, -0.2672f, 0.557f, 0.557f, -0.3488f, 0.0f, -0.2531f, 0.558f, 0.558f,
+ -0.3639f, 0.0f, -0.2407f, 0.558f, 0.558f, -0.3778f, 0.0f, -0.2292f, 0.558f, 0.558f,
+ -0.3909f, 0.0f, -0.2191f, 0.559f, 0.559f, -0.4032f, 0.0f, -0.2102f, 0.559f, 0.558f,
+ -0.4146f, 0.0f, -0.2027f, 0.559f, 0.559f, -0.426f, 0.0f, -0.1968f, 0.558f, 0.558f,
+ -0.4348f, 0.0f, -0.1931f, 0.558f, 0.558f, -0.4479f, 0.0f, -0.1886f, 0.555f, 0.559f,
};
static const float data1[33 * GP_PRIM_DATABUF_SIZE] = {
- 0.5292f, 0.0f, 0.1742f, 0.1f, 1.0f,
- 0.5291f, 0.0f, 0.1621f, 0.2199f, 1.0f,
- 0.5274f, 0.0f, 0.1386f, 0.4615f, 1.0f,
- 0.5239f, 0.0f, 0.116f, 0.6019f, 1.0f,
- 0.5185f, 0.0f, 0.0945f, 0.6981f, 1.0f,
- 0.5115f, 0.0f, 0.0741f, 0.7689f, 1.0f,
- 0.503f, 0.0f, 0.0548f, 0.8236f, 1.0f,
- 0.4931f, 0.0f, 0.0368f, 0.866f, 1.0f,
- 0.482f, 0.0f, 0.02f, 0.9003f, 1.0f,
- 0.4697f, 0.0f, 0.0046f, 0.9272f, 1.0f,
- 0.4565f, 0.0f, -0.0094f, 0.9485f, 1.0f,
- 0.4424f, 0.0f, -0.0219f, 0.9653f, 1.0f,
- 0.4275f, 0.0f, -0.033f, 0.9781f, 1.0f,
- 0.4121f, 0.0f, -0.0424f, 0.9876f, 1.0f,
- 0.3961f, 0.0f, -0.0501f, 0.9942f, 1.0f,
- 0.3799f, 0.0f, -0.0562f, 0.9983f, 1.0f,
- 0.3634f, 0.0f, -0.0605f, 0.9997f, 1.0f,
- 0.3468f, 0.0f, -0.0629f, 0.999f, 1.0f,
- 0.3303f, 0.0f, -0.0634f, 0.9963f, 1.0f,
- 0.3139f, 0.0f, -0.062f, 0.9912f, 1.0f,
- 0.2979f, 0.0f, -0.0585f, 0.9834f, 1.0f,
- 0.2823f, 0.0f, -0.0529f, 0.9724f, 1.0f,
- 0.2672f, 0.0f, -0.0452f, 0.9576f, 1.0f,
- 0.2529f, 0.0f, -0.0352f, 0.9385f, 1.0f,
- 0.2393f, 0.0f, -0.023f, 0.9143f, 1.0f,
- 0.2267f, 0.0f, -0.0085f, 0.8841f, 1.0f,
- 0.2153f, 0.0f, 0.0085f, 0.8461f, 1.0f,
- 0.205f, 0.0f, 0.0279f, 0.7979f, 1.0f,
- 0.196f, 0.0f, 0.0499f, 0.7359f, 1.0f,
- 0.1886f, 0.0f, 0.0745f, 0.6541f, 1.0f,
- 0.1827f, 0.0f, 0.1017f, 0.5396f, 1.0f,
- 0.1786f, 0.0f, 0.1316f, 0.36f, 1.0f,
- 0.1763f, 0.0f, 0.1643f, 0.1f, 1.0f,
+ 0.5292f, 0.0f, 0.1742f, 0.1f, 1.0f, 0.5291f, 0.0f, 0.1621f, 0.2199f, 1.0f,
+ 0.5274f, 0.0f, 0.1386f, 0.4615f, 1.0f, 0.5239f, 0.0f, 0.116f, 0.6019f, 1.0f,
+ 0.5185f, 0.0f, 0.0945f, 0.6981f, 1.0f, 0.5115f, 0.0f, 0.0741f, 0.7689f, 1.0f,
+ 0.503f, 0.0f, 0.0548f, 0.8236f, 1.0f, 0.4931f, 0.0f, 0.0368f, 0.866f, 1.0f,
+ 0.482f, 0.0f, 0.02f, 0.9003f, 1.0f, 0.4697f, 0.0f, 0.0046f, 0.9272f, 1.0f,
+ 0.4565f, 0.0f, -0.0094f, 0.9485f, 1.0f, 0.4424f, 0.0f, -0.0219f, 0.9653f, 1.0f,
+ 0.4275f, 0.0f, -0.033f, 0.9781f, 1.0f, 0.4121f, 0.0f, -0.0424f, 0.9876f, 1.0f,
+ 0.3961f, 0.0f, -0.0501f, 0.9942f, 1.0f, 0.3799f, 0.0f, -0.0562f, 0.9983f, 1.0f,
+ 0.3634f, 0.0f, -0.0605f, 0.9997f, 1.0f, 0.3468f, 0.0f, -0.0629f, 0.999f, 1.0f,
+ 0.3303f, 0.0f, -0.0634f, 0.9963f, 1.0f, 0.3139f, 0.0f, -0.062f, 0.9912f, 1.0f,
+ 0.2979f, 0.0f, -0.0585f, 0.9834f, 1.0f, 0.2823f, 0.0f, -0.0529f, 0.9724f, 1.0f,
+ 0.2672f, 0.0f, -0.0452f, 0.9576f, 1.0f, 0.2529f, 0.0f, -0.0352f, 0.9385f, 1.0f,
+ 0.2393f, 0.0f, -0.023f, 0.9143f, 1.0f, 0.2267f, 0.0f, -0.0085f, 0.8841f, 1.0f,
+ 0.2153f, 0.0f, 0.0085f, 0.8461f, 1.0f, 0.205f, 0.0f, 0.0279f, 0.7979f, 1.0f,
+ 0.196f, 0.0f, 0.0499f, 0.7359f, 1.0f, 0.1886f, 0.0f, 0.0745f, 0.6541f, 1.0f,
+ 0.1827f, 0.0f, 0.1017f, 0.5396f, 1.0f, 0.1786f, 0.0f, 0.1316f, 0.36f, 1.0f,
+ 0.1763f, 0.0f, 0.1643f, 0.1f, 1.0f,
};
static const float data2[18 * GP_PRIM_DATABUF_SIZE] = {
- -0.0844f, 0.0f, -0.301f, 0.1f, 1.0f,
- -0.0825f, 0.0f, -0.3034f, 0.2199f, 1.0f,
- -0.0751f, 0.0f, -0.3128f, 0.6019f, 1.0f,
- -0.0677f, 0.0f, -0.3216f, 0.7689f, 1.0f,
- -0.06f, 0.0f, -0.3298f, 0.866f, 1.0f,
- -0.0522f, 0.0f, -0.3372f, 0.9272f, 1.0f,
- -0.044f, 0.0f, -0.3437f, 0.9653f, 1.0f,
- -0.0354f, 0.0f, -0.3491f, 0.9876f, 1.0f,
- -0.0264f, 0.0f, -0.3535f, 0.9983f, 1.0f,
- -0.0168f, 0.0f, -0.3566f, 0.999f, 1.0f,
- -0.0065f, 0.0f, -0.3583f, 0.9912f, 1.0f,
- 0.0045f, 0.0f, -0.3585f, 0.9724f, 1.0f,
- 0.0163f, 0.0f, -0.3571f, 0.9385f, 1.0f,
- 0.029f, 0.0f, -0.354f, 0.8841f, 1.0f,
- 0.0427f, 0.0f, -0.3491f, 0.7979f, 1.0f,
- 0.0574f, 0.0f, -0.3421f, 0.6541f, 1.0f,
- 0.0732f, 0.0f, -0.3331f, 0.36f, 1.0f,
- 0.0816f, 0.0f, -0.3278f, 0.1f, 1.0f,
+ -0.0844f, 0.0f, -0.301f, 0.1f, 1.0f, -0.0825f, 0.0f, -0.3034f, 0.2199f, 1.0f,
+ -0.0751f, 0.0f, -0.3128f, 0.6019f, 1.0f, -0.0677f, 0.0f, -0.3216f, 0.7689f, 1.0f,
+ -0.06f, 0.0f, -0.3298f, 0.866f, 1.0f, -0.0522f, 0.0f, -0.3372f, 0.9272f, 1.0f,
+ -0.044f, 0.0f, -0.3437f, 0.9653f, 1.0f, -0.0354f, 0.0f, -0.3491f, 0.9876f, 1.0f,
+ -0.0264f, 0.0f, -0.3535f, 0.9983f, 1.0f, -0.0168f, 0.0f, -0.3566f, 0.999f, 1.0f,
+ -0.0065f, 0.0f, -0.3583f, 0.9912f, 1.0f, 0.0045f, 0.0f, -0.3585f, 0.9724f, 1.0f,
+ 0.0163f, 0.0f, -0.3571f, 0.9385f, 1.0f, 0.029f, 0.0f, -0.354f, 0.8841f, 1.0f,
+ 0.0427f, 0.0f, -0.3491f, 0.7979f, 1.0f, 0.0574f, 0.0f, -0.3421f, 0.6541f, 1.0f,
+ 0.0732f, 0.0f, -0.3331f, 0.36f, 1.0f, 0.0816f, 0.0f, -0.3278f, 0.1f, 1.0f,
};
static const float data3[64 * GP_PRIM_DATABUF_SIZE] = {
- -0.6551f, 0.0f, 0.4448f, 0.1f, 1.0f,
- -0.6353f, 0.0f, 0.4689f, 0.2199f, 1.0f,
- -0.6211f, 0.0f, 0.4845f, 0.36f, 1.0f,
- -0.6033f, 0.0f, 0.5034f, 0.4615f, 1.0f,
- -0.5856f, 0.0f, 0.5211f, 0.5396f, 1.0f,
- -0.5672f, 0.0f, 0.5387f, 0.6019f, 1.0f,
- -0.5485f, 0.0f, 0.5555f, 0.6541f, 1.0f,
- -0.5295f, 0.0f, 0.5718f, 0.6981f, 1.0f,
- -0.5103f, 0.0f, 0.5875f, 0.7359f, 1.0f,
- -0.4909f, 0.0f, 0.6028f, 0.7689f, 1.0f,
- -0.4712f, 0.0f, 0.6174f, 0.7979f, 1.0f,
- -0.4512f, 0.0f, 0.6313f, 0.8236f, 1.0f,
- -0.4307f, 0.0f, 0.6444f, 0.8461f, 1.0f,
- -0.4099f, 0.0f, 0.6568f, 0.866f, 1.0f,
- -0.3884f, 0.0f, 0.6684f, 0.8841f, 1.0f,
- -0.3665f, 0.0f, 0.6793f, 0.9003f, 1.0f,
- -0.3439f, 0.0f, 0.6893f, 0.9143f, 1.0f,
- -0.3207f, 0.0f, 0.6984f, 0.9272f, 1.0f,
- -0.2971f, 0.0f, 0.7069f, 0.9385f, 1.0f,
- -0.2731f, 0.0f, 0.7148f, 0.9485f, 1.0f,
- -0.249f, 0.0f, 0.7222f, 0.9576f, 1.0f,
- -0.2247f, 0.0f, 0.7292f, 0.9653f, 1.0f,
- -0.2003f, 0.0f, 0.7356f, 0.9724f, 1.0f,
- -0.1759f, 0.0f, 0.7416f, 0.9781f, 1.0f,
- -0.1515f, 0.0f, 0.7471f, 0.9834f, 1.0f,
- -0.1272f, 0.0f, 0.7518f, 0.9876f, 1.0f,
- -0.1028f, 0.0f, 0.7556f, 0.9912f, 1.0f,
- -0.0785f, 0.0f, 0.7586f, 0.9942f, 1.0f,
- -0.0543f, 0.0f, 0.7607f, 0.9963f, 1.0f,
- -0.0302f, 0.0f, 0.7621f, 0.9983f, 1.0f,
- -0.0062f, 0.0f, 0.7627f, 0.999f, 1.0f,
- 0.0177f, 0.0f, 0.7625f, 0.9997f, 1.0f,
- 0.0415f, 0.0f, 0.7616f, 0.9997f, 1.0f,
- 0.0652f, 0.0f, 0.7602f, 0.999f, 1.0f,
- 0.0887f, 0.0f, 0.7583f, 0.9983f, 1.0f,
- 0.1122f, 0.0f, 0.7559f, 0.9963f, 1.0f,
- 0.1355f, 0.0f, 0.7529f, 0.9942f, 1.0f,
- 0.1585f, 0.0f, 0.7493f, 0.9912f, 1.0f,
- 0.1814f, 0.0f, 0.7451f, 0.9876f, 1.0f,
- 0.2041f, 0.0f, 0.7404f, 0.9834f, 1.0f,
- 0.2266f, 0.0f, 0.7352f, 0.9781f, 1.0f,
- 0.2488f, 0.0f, 0.729f, 0.9724f, 1.0f,
- 0.2706f, 0.0f, 0.7216f, 0.9653f, 1.0f,
- 0.2921f, 0.0f, 0.7131f, 0.9576f, 1.0f,
- 0.3135f, 0.0f, 0.7041f, 0.9485f, 1.0f,
- 0.3348f, 0.0f, 0.6945f, 0.9385f, 1.0f,
- 0.3559f, 0.0f, 0.6845f, 0.9272f, 1.0f,
- 0.3769f, 0.0f, 0.6739f, 0.9143f, 1.0f,
- 0.3978f, 0.0f, 0.6628f, 0.9003f, 1.0f,
- 0.4185f, 0.0f, 0.651f, 0.8841f, 1.0f,
- 0.439f, 0.0f, 0.6383f, 0.866f, 1.0f,
- 0.4594f, 0.0f, 0.6249f, 0.8461f, 1.0f,
- 0.4795f, 0.0f, 0.6106f, 0.8236f, 1.0f,
- 0.4995f, 0.0f, 0.5956f, 0.7979f, 1.0f,
- 0.5193f, 0.0f, 0.5801f, 0.7689f, 1.0f,
- 0.539f, 0.0f, 0.5642f, 0.7359f, 1.0f,
- 0.5586f, 0.0f, 0.5479f, 0.6981f, 1.0f,
- 0.578f, 0.0f, 0.5312f, 0.6541f, 1.0f,
- 0.597f, 0.0f, 0.5141f, 0.6019f, 1.0f,
- 0.6153f, 0.0f, 0.4966f, 0.5396f, 1.0f,
- 0.6324f, 0.0f, 0.4797f, 0.4615f, 1.0f,
- 0.6498f, 0.0f, 0.462f, 0.36f, 1.0f,
- 0.6638f, 0.0f, 0.4477f, 0.2199f, 1.0f,
- 0.6843f, 0.0f, 0.4263f, 0.1f, 1.0f,
+ -0.6551f, 0.0f, 0.4448f, 0.1f, 1.0f, -0.6353f, 0.0f, 0.4689f, 0.2199f, 1.0f,
+ -0.6211f, 0.0f, 0.4845f, 0.36f, 1.0f, -0.6033f, 0.0f, 0.5034f, 0.4615f, 1.0f,
+ -0.5856f, 0.0f, 0.5211f, 0.5396f, 1.0f, -0.5672f, 0.0f, 0.5387f, 0.6019f, 1.0f,
+ -0.5485f, 0.0f, 0.5555f, 0.6541f, 1.0f, -0.5295f, 0.0f, 0.5718f, 0.6981f, 1.0f,
+ -0.5103f, 0.0f, 0.5875f, 0.7359f, 1.0f, -0.4909f, 0.0f, 0.6028f, 0.7689f, 1.0f,
+ -0.4712f, 0.0f, 0.6174f, 0.7979f, 1.0f, -0.4512f, 0.0f, 0.6313f, 0.8236f, 1.0f,
+ -0.4307f, 0.0f, 0.6444f, 0.8461f, 1.0f, -0.4099f, 0.0f, 0.6568f, 0.866f, 1.0f,
+ -0.3884f, 0.0f, 0.6684f, 0.8841f, 1.0f, -0.3665f, 0.0f, 0.6793f, 0.9003f, 1.0f,
+ -0.3439f, 0.0f, 0.6893f, 0.9143f, 1.0f, -0.3207f, 0.0f, 0.6984f, 0.9272f, 1.0f,
+ -0.2971f, 0.0f, 0.7069f, 0.9385f, 1.0f, -0.2731f, 0.0f, 0.7148f, 0.9485f, 1.0f,
+ -0.249f, 0.0f, 0.7222f, 0.9576f, 1.0f, -0.2247f, 0.0f, 0.7292f, 0.9653f, 1.0f,
+ -0.2003f, 0.0f, 0.7356f, 0.9724f, 1.0f, -0.1759f, 0.0f, 0.7416f, 0.9781f, 1.0f,
+ -0.1515f, 0.0f, 0.7471f, 0.9834f, 1.0f, -0.1272f, 0.0f, 0.7518f, 0.9876f, 1.0f,
+ -0.1028f, 0.0f, 0.7556f, 0.9912f, 1.0f, -0.0785f, 0.0f, 0.7586f, 0.9942f, 1.0f,
+ -0.0543f, 0.0f, 0.7607f, 0.9963f, 1.0f, -0.0302f, 0.0f, 0.7621f, 0.9983f, 1.0f,
+ -0.0062f, 0.0f, 0.7627f, 0.999f, 1.0f, 0.0177f, 0.0f, 0.7625f, 0.9997f, 1.0f,
+ 0.0415f, 0.0f, 0.7616f, 0.9997f, 1.0f, 0.0652f, 0.0f, 0.7602f, 0.999f, 1.0f,
+ 0.0887f, 0.0f, 0.7583f, 0.9983f, 1.0f, 0.1122f, 0.0f, 0.7559f, 0.9963f, 1.0f,
+ 0.1355f, 0.0f, 0.7529f, 0.9942f, 1.0f, 0.1585f, 0.0f, 0.7493f, 0.9912f, 1.0f,
+ 0.1814f, 0.0f, 0.7451f, 0.9876f, 1.0f, 0.2041f, 0.0f, 0.7404f, 0.9834f, 1.0f,
+ 0.2266f, 0.0f, 0.7352f, 0.9781f, 1.0f, 0.2488f, 0.0f, 0.729f, 0.9724f, 1.0f,
+ 0.2706f, 0.0f, 0.7216f, 0.9653f, 1.0f, 0.2921f, 0.0f, 0.7131f, 0.9576f, 1.0f,
+ 0.3135f, 0.0f, 0.7041f, 0.9485f, 1.0f, 0.3348f, 0.0f, 0.6945f, 0.9385f, 1.0f,
+ 0.3559f, 0.0f, 0.6845f, 0.9272f, 1.0f, 0.3769f, 0.0f, 0.6739f, 0.9143f, 1.0f,
+ 0.3978f, 0.0f, 0.6628f, 0.9003f, 1.0f, 0.4185f, 0.0f, 0.651f, 0.8841f, 1.0f,
+ 0.439f, 0.0f, 0.6383f, 0.866f, 1.0f, 0.4594f, 0.0f, 0.6249f, 0.8461f, 1.0f,
+ 0.4795f, 0.0f, 0.6106f, 0.8236f, 1.0f, 0.4995f, 0.0f, 0.5956f, 0.7979f, 1.0f,
+ 0.5193f, 0.0f, 0.5801f, 0.7689f, 1.0f, 0.539f, 0.0f, 0.5642f, 0.7359f, 1.0f,
+ 0.5586f, 0.0f, 0.5479f, 0.6981f, 1.0f, 0.578f, 0.0f, 0.5312f, 0.6541f, 1.0f,
+ 0.597f, 0.0f, 0.5141f, 0.6019f, 1.0f, 0.6153f, 0.0f, 0.4966f, 0.5396f, 1.0f,
+ 0.6324f, 0.0f, 0.4797f, 0.4615f, 1.0f, 0.6498f, 0.0f, 0.462f, 0.36f, 1.0f,
+ 0.6638f, 0.0f, 0.4477f, 0.2199f, 1.0f, 0.6843f, 0.0f, 0.4263f, 0.1f, 1.0f,
};
static const float data4[33 * GP_PRIM_DATABUF_SIZE] = {
- -0.7765f, 0.0f, 0.3255f, 0.1f, 1.0f,
- -0.7908f, 0.0f, 0.3335f, 0.2199f, 1.0f,
- -0.8048f, 0.0f, 0.3402f, 0.4615f, 1.0f,
- -0.8225f, 0.0f, 0.3467f, 0.6019f, 1.0f,
- -0.8426f, 0.0f, 0.3529f, 0.6981f, 1.0f,
- -0.8651f, 0.0f, 0.3587f, 0.7689f, 1.0f,
- -0.8878f, 0.0f, 0.3633f, 0.8236f, 1.0f,
- -0.9105f, 0.0f, 0.367f, 0.866f, 1.0f,
- -0.9323f, 0.0f, 0.3693f, 0.9003f, 1.0f,
- -0.9529f, 0.0f, 0.3701f, 0.9272f, 1.0f,
- -0.972f, 0.0f, 0.3695f, 0.9485f, 1.0f,
- -0.9896f, 0.0f, 0.3675f, 0.9653f, 1.0f,
- -1.0057f, 0.0f, 0.364f, 0.9781f, 1.0f,
- -1.0203f, 0.0f, 0.3592f, 0.9876f, 1.0f,
- -1.0333f, 0.0f, 0.3528f, 0.9942f, 1.0f,
- -1.0447f, 0.0f, 0.3452f, 0.9983f, 1.0f,
- -1.0546f, 0.0f, 0.3362f, 0.9997f, 1.0f,
- -1.0633f, 0.0f, 0.3261f, 0.999f, 1.0f,
- -1.0708f, 0.0f, 0.315f, 0.9963f, 1.0f,
- -1.0767f, 0.0f, 0.3027f, 0.9912f, 1.0f,
- -1.0818f, 0.0f, 0.2894f, 0.9834f, 1.0f,
- -1.0861f, 0.0f, 0.2752f, 0.9724f, 1.0f,
- -1.0897f, 0.0f, 0.2604f, 0.9576f, 1.0f,
- -1.0922f, 0.0f, 0.2446f, 0.9385f, 1.0f,
- -1.0938f, 0.0f, 0.2277f, 0.9143f, 1.0f,
- -1.0944f, 0.0f, 0.2098f, 0.8841f, 1.0f,
- -1.0939f, 0.0f, 0.191f, 0.8461f, 1.0f,
- -1.0924f, 0.0f, 0.1714f, 0.7979f, 1.0f,
- -1.0897f, 0.0f, 0.1511f, 0.7359f, 1.0f,
- -1.0855f, 0.0f, 0.1303f, 0.6541f, 1.0f,
- -1.0798f, 0.0f, 0.1095f, 0.5396f, 1.0f,
- -1.0723f, 0.0f, 0.089f, 0.36f, 1.0f,
- -1.0642f, 0.0f, 0.0702f, 0.1f, 1.0f,
+ -0.7765f, 0.0f, 0.3255f, 0.1f, 1.0f, -0.7908f, 0.0f, 0.3335f, 0.2199f, 1.0f,
+ -0.8048f, 0.0f, 0.3402f, 0.4615f, 1.0f, -0.8225f, 0.0f, 0.3467f, 0.6019f, 1.0f,
+ -0.8426f, 0.0f, 0.3529f, 0.6981f, 1.0f, -0.8651f, 0.0f, 0.3587f, 0.7689f, 1.0f,
+ -0.8878f, 0.0f, 0.3633f, 0.8236f, 1.0f, -0.9105f, 0.0f, 0.367f, 0.866f, 1.0f,
+ -0.9323f, 0.0f, 0.3693f, 0.9003f, 1.0f, -0.9529f, 0.0f, 0.3701f, 0.9272f, 1.0f,
+ -0.972f, 0.0f, 0.3695f, 0.9485f, 1.0f, -0.9896f, 0.0f, 0.3675f, 0.9653f, 1.0f,
+ -1.0057f, 0.0f, 0.364f, 0.9781f, 1.0f, -1.0203f, 0.0f, 0.3592f, 0.9876f, 1.0f,
+ -1.0333f, 0.0f, 0.3528f, 0.9942f, 1.0f, -1.0447f, 0.0f, 0.3452f, 0.9983f, 1.0f,
+ -1.0546f, 0.0f, 0.3362f, 0.9997f, 1.0f, -1.0633f, 0.0f, 0.3261f, 0.999f, 1.0f,
+ -1.0708f, 0.0f, 0.315f, 0.9963f, 1.0f, -1.0767f, 0.0f, 0.3027f, 0.9912f, 1.0f,
+ -1.0818f, 0.0f, 0.2894f, 0.9834f, 1.0f, -1.0861f, 0.0f, 0.2752f, 0.9724f, 1.0f,
+ -1.0897f, 0.0f, 0.2604f, 0.9576f, 1.0f, -1.0922f, 0.0f, 0.2446f, 0.9385f, 1.0f,
+ -1.0938f, 0.0f, 0.2277f, 0.9143f, 1.0f, -1.0944f, 0.0f, 0.2098f, 0.8841f, 1.0f,
+ -1.0939f, 0.0f, 0.191f, 0.8461f, 1.0f, -1.0924f, 0.0f, 0.1714f, 0.7979f, 1.0f,
+ -1.0897f, 0.0f, 0.1511f, 0.7359f, 1.0f, -1.0855f, 0.0f, 0.1303f, 0.6541f, 1.0f,
+ -1.0798f, 0.0f, 0.1095f, 0.5396f, 1.0f, -1.0723f, 0.0f, 0.089f, 0.36f, 1.0f,
+ -1.0642f, 0.0f, 0.0702f, 0.1f, 1.0f,
};
static const float data5[64 * GP_PRIM_DATABUF_SIZE] = {
- 0.8135f, 0.0f, 0.3341f, 0.1f, 1.0f,
- 0.8191f, 0.0f, 0.3376f, 0.2199f, 1.0f,
- 0.8246f, 0.0f, 0.3408f, 0.36f, 1.0f,
- 0.8304f, 0.0f, 0.3438f, 0.4615f, 1.0f,
- 0.8368f, 0.0f, 0.3465f, 0.5396f, 1.0f,
- 0.843f, 0.0f, 0.3491f, 0.6019f, 1.0f,
- 0.8494f, 0.0f, 0.3515f, 0.6541f, 1.0f,
- 0.8558f, 0.0f, 0.3536f, 0.6981f, 1.0f,
- 0.8623f, 0.0f, 0.3557f, 0.7359f, 1.0f,
- 0.8688f, 0.0f, 0.3575f, 0.7689f, 1.0f,
- 0.8752f, 0.0f, 0.3593f, 0.7979f, 1.0f,
- 0.8813f, 0.0f, 0.3609f, 0.8236f, 1.0f,
- 0.8872f, 0.0f, 0.3625f, 0.8461f, 1.0f,
- 0.8929f, 0.0f, 0.364f, 0.866f, 1.0f,
- 0.8984f, 0.0f, 0.3653f, 0.8841f, 1.0f,
- 0.9039f, 0.0f, 0.3665f, 0.9003f, 1.0f,
- 0.9093f, 0.0f, 0.3675f, 0.9143f, 1.0f,
- 0.9146f, 0.0f, 0.3684f, 0.9272f, 1.0f,
- 0.9199f, 0.0f, 0.3692f, 0.9385f, 1.0f,
- 0.9253f, 0.0f, 0.3698f, 0.9485f, 1.0f,
- 0.9305f, 0.0f, 0.3703f, 0.9576f, 1.0f,
- 0.9358f, 0.0f, 0.3706f, 0.9653f, 1.0f,
- 0.941f, 0.0f, 0.3709f, 0.9724f, 1.0f,
- 0.9462f, 0.0f, 0.371f, 0.9781f, 1.0f,
- 0.9514f, 0.0f, 0.371f, 0.9834f, 1.0f,
- 0.9566f, 0.0f, 0.3708f, 0.9876f, 1.0f,
- 0.9617f, 0.0f, 0.3706f, 0.9912f, 1.0f,
- 0.9668f, 0.0f, 0.3702f, 0.9942f, 1.0f,
- 0.9718f, 0.0f, 0.3697f, 0.9963f, 1.0f,
- 0.9768f, 0.0f, 0.3692f, 0.9983f, 1.0f,
- 0.9818f, 0.0f, 0.3685f, 0.999f, 1.0f,
- 0.9867f, 0.0f, 0.3677f, 0.9997f, 1.0f,
- 0.9916f, 0.0f, 0.3667f, 0.9997f, 1.0f,
- 0.9964f, 0.0f, 0.3657f, 0.999f, 1.0f,
- 1.0012f, 0.0f, 0.3646f, 0.9983f, 1.0f,
- 1.006f, 0.0f, 0.3634f, 0.9963f, 1.0f,
- 1.0107f, 0.0f, 0.3621f, 0.9942f, 1.0f,
- 1.0154f, 0.0f, 0.3607f, 0.9912f, 1.0f,
- 1.02f, 0.0f, 0.3593f, 0.9876f, 1.0f,
- 1.0245f, 0.0f, 0.3577f, 0.9834f, 1.0f,
- 1.029f, 0.0f, 0.3561f, 0.9781f, 1.0f,
- 1.0335f, 0.0f, 0.3543f, 0.9724f, 1.0f,
- 1.0379f, 0.0f, 0.3525f, 0.9653f, 1.0f,
- 1.0422f, 0.0f, 0.3507f, 0.9576f, 1.0f,
- 1.0465f, 0.0f, 0.3487f, 0.9485f, 1.0f,
- 1.0507f, 0.0f, 0.3468f, 0.9385f, 1.0f,
- 1.0549f, 0.0f, 0.3447f, 0.9272f, 1.0f,
- 1.0591f, 0.0f, 0.3427f, 0.9143f, 1.0f,
- 1.0633f, 0.0f, 0.3404f, 0.9003f, 1.0f,
- 1.0675f, 0.0f, 0.338f, 0.8841f, 1.0f,
- 1.0717f, 0.0f, 0.3351f, 0.866f, 1.0f,
- 1.0761f, 0.0f, 0.3318f, 0.8461f, 1.0f,
- 1.0805f, 0.0f, 0.3279f, 0.8236f, 1.0f,
- 1.0849f, 0.0f, 0.3235f, 0.7979f, 1.0f,
- 1.0893f, 0.0f, 0.3186f, 0.7689f, 1.0f,
- 1.0936f, 0.0f, 0.3134f, 0.7359f, 1.0f,
- 1.0979f, 0.0f, 0.3076f, 0.6981f, 1.0f,
- 1.102f, 0.0f, 0.3017f, 0.6541f, 1.0f,
- 1.106f, 0.0f, 0.2953f, 0.6019f, 1.0f,
- 1.1097f, 0.0f, 0.289f, 0.5396f, 1.0f,
- 1.1132f, 0.0f, 0.2826f, 0.4615f, 1.0f,
- 1.1164f, 0.0f, 0.2766f, 0.36f, 1.0f,
- 1.1193f, 0.0f, 0.2708f, 0.2199f, 1.0f,
- 1.1221f, 0.0f, 0.2652f, 0.1f, 1.0f,
+ 0.8135f, 0.0f, 0.3341f, 0.1f, 1.0f, 0.8191f, 0.0f, 0.3376f, 0.2199f, 1.0f,
+ 0.8246f, 0.0f, 0.3408f, 0.36f, 1.0f, 0.8304f, 0.0f, 0.3438f, 0.4615f, 1.0f,
+ 0.8368f, 0.0f, 0.3465f, 0.5396f, 1.0f, 0.843f, 0.0f, 0.3491f, 0.6019f, 1.0f,
+ 0.8494f, 0.0f, 0.3515f, 0.6541f, 1.0f, 0.8558f, 0.0f, 0.3536f, 0.6981f, 1.0f,
+ 0.8623f, 0.0f, 0.3557f, 0.7359f, 1.0f, 0.8688f, 0.0f, 0.3575f, 0.7689f, 1.0f,
+ 0.8752f, 0.0f, 0.3593f, 0.7979f, 1.0f, 0.8813f, 0.0f, 0.3609f, 0.8236f, 1.0f,
+ 0.8872f, 0.0f, 0.3625f, 0.8461f, 1.0f, 0.8929f, 0.0f, 0.364f, 0.866f, 1.0f,
+ 0.8984f, 0.0f, 0.3653f, 0.8841f, 1.0f, 0.9039f, 0.0f, 0.3665f, 0.9003f, 1.0f,
+ 0.9093f, 0.0f, 0.3675f, 0.9143f, 1.0f, 0.9146f, 0.0f, 0.3684f, 0.9272f, 1.0f,
+ 0.9199f, 0.0f, 0.3692f, 0.9385f, 1.0f, 0.9253f, 0.0f, 0.3698f, 0.9485f, 1.0f,
+ 0.9305f, 0.0f, 0.3703f, 0.9576f, 1.0f, 0.9358f, 0.0f, 0.3706f, 0.9653f, 1.0f,
+ 0.941f, 0.0f, 0.3709f, 0.9724f, 1.0f, 0.9462f, 0.0f, 0.371f, 0.9781f, 1.0f,
+ 0.9514f, 0.0f, 0.371f, 0.9834f, 1.0f, 0.9566f, 0.0f, 0.3708f, 0.9876f, 1.0f,
+ 0.9617f, 0.0f, 0.3706f, 0.9912f, 1.0f, 0.9668f, 0.0f, 0.3702f, 0.9942f, 1.0f,
+ 0.9718f, 0.0f, 0.3697f, 0.9963f, 1.0f, 0.9768f, 0.0f, 0.3692f, 0.9983f, 1.0f,
+ 0.9818f, 0.0f, 0.3685f, 0.999f, 1.0f, 0.9867f, 0.0f, 0.3677f, 0.9997f, 1.0f,
+ 0.9916f, 0.0f, 0.3667f, 0.9997f, 1.0f, 0.9964f, 0.0f, 0.3657f, 0.999f, 1.0f,
+ 1.0012f, 0.0f, 0.3646f, 0.9983f, 1.0f, 1.006f, 0.0f, 0.3634f, 0.9963f, 1.0f,
+ 1.0107f, 0.0f, 0.3621f, 0.9942f, 1.0f, 1.0154f, 0.0f, 0.3607f, 0.9912f, 1.0f,
+ 1.02f, 0.0f, 0.3593f, 0.9876f, 1.0f, 1.0245f, 0.0f, 0.3577f, 0.9834f, 1.0f,
+ 1.029f, 0.0f, 0.3561f, 0.9781f, 1.0f, 1.0335f, 0.0f, 0.3543f, 0.9724f, 1.0f,
+ 1.0379f, 0.0f, 0.3525f, 0.9653f, 1.0f, 1.0422f, 0.0f, 0.3507f, 0.9576f, 1.0f,
+ 1.0465f, 0.0f, 0.3487f, 0.9485f, 1.0f, 1.0507f, 0.0f, 0.3468f, 0.9385f, 1.0f,
+ 1.0549f, 0.0f, 0.3447f, 0.9272f, 1.0f, 1.0591f, 0.0f, 0.3427f, 0.9143f, 1.0f,
+ 1.0633f, 0.0f, 0.3404f, 0.9003f, 1.0f, 1.0675f, 0.0f, 0.338f, 0.8841f, 1.0f,
+ 1.0717f, 0.0f, 0.3351f, 0.866f, 1.0f, 1.0761f, 0.0f, 0.3318f, 0.8461f, 1.0f,
+ 1.0805f, 0.0f, 0.3279f, 0.8236f, 1.0f, 1.0849f, 0.0f, 0.3235f, 0.7979f, 1.0f,
+ 1.0893f, 0.0f, 0.3186f, 0.7689f, 1.0f, 1.0936f, 0.0f, 0.3134f, 0.7359f, 1.0f,
+ 1.0979f, 0.0f, 0.3076f, 0.6981f, 1.0f, 1.102f, 0.0f, 0.3017f, 0.6541f, 1.0f,
+ 1.106f, 0.0f, 0.2953f, 0.6019f, 1.0f, 1.1097f, 0.0f, 0.289f, 0.5396f, 1.0f,
+ 1.1132f, 0.0f, 0.2826f, 0.4615f, 1.0f, 1.1164f, 0.0f, 0.2766f, 0.36f, 1.0f,
+ 1.1193f, 0.0f, 0.2708f, 0.2199f, 1.0f, 1.1221f, 0.0f, 0.2652f, 0.1f, 1.0f,
};
static const float data6[33 * GP_PRIM_DATABUF_SIZE] = {
- -0.2677f, 0.0f, -0.3496f, 0.1f, 1.0f,
- -0.2658f, 0.0f, -0.3919f, 0.2199f, 1.0f,
- -0.2657f, 0.0f, -0.4295f, 0.4615f, 1.0f,
- -0.2691f, 0.0f, -0.4621f, 0.6019f, 1.0f,
- -0.275f, 0.0f, -0.4949f, 0.6981f, 1.0f,
- -0.2828f, 0.0f, -0.527f, 0.7689f, 1.0f,
- -0.2911f, 0.0f, -0.5578f, 0.8236f, 1.0f,
- -0.2971f, 0.0f, -0.5884f, 0.866f, 1.0f,
- -0.303f, 0.0f, -0.6181f, 0.9003f, 1.0f,
- -0.3089f, 0.0f, -0.6467f, 0.9272f, 1.0f,
- -0.3148f, 0.0f, -0.6738f, 0.9485f, 1.0f,
- -0.3196f, 0.0f, -0.7f, 0.9653f, 1.0f,
- -0.323f, 0.0f, -0.7253f, 0.9781f, 1.0f,
- -0.3234f, 0.0f, -0.7496f, 0.9876f, 1.0f,
- -0.3219f, 0.0f, -0.7728f, 0.9942f, 1.0f,
- -0.3184f, 0.0f, -0.7949f, 0.9983f, 1.0f,
- -0.3103f, 0.0f, -0.8138f, 0.9997f, 1.0f,
- -0.3004f, 0.0f, -0.8307f, 0.999f, 1.0f,
- -0.2892f, 0.0f, -0.8464f, 0.9963f, 1.0f,
- -0.2766f, 0.0f, -0.8611f, 0.9912f, 1.0f,
- -0.2618f, 0.0f, -0.8735f, 0.9834f, 1.0f,
- -0.2469f, 0.0f, -0.8853f, 0.9724f, 1.0f,
- -0.2315f, 0.0f, -0.8964f, 0.9576f, 1.0f,
- -0.2158f, 0.0f, -0.9068f, 0.9385f, 1.0f,
- -0.1997f, 0.0f, -0.9167f, 0.9143f, 1.0f,
- -0.1833f, 0.0f, -0.9262f, 0.8841f, 1.0f,
- -0.1663f, 0.0f, -0.9355f, 0.8461f, 1.0f,
- -0.1481f, 0.0f, -0.9445f, 0.7979f, 1.0f,
- -0.1282f, 0.0f, -0.9534f, 0.7359f, 1.0f,
- -0.1077f, 0.0f, -0.9625f, 0.6541f, 1.0f,
- -0.0854f, 0.0f, -0.9718f, 0.5396f, 1.0f,
- -0.0616f, 0.0f, -0.9813f, 0.36f, 1.0f,
- -0.0248f, 0.0f, -0.992f, 0.1f, 1.0f,
+ -0.2677f, 0.0f, -0.3496f, 0.1f, 1.0f, -0.2658f, 0.0f, -0.3919f, 0.2199f, 1.0f,
+ -0.2657f, 0.0f, -0.4295f, 0.4615f, 1.0f, -0.2691f, 0.0f, -0.4621f, 0.6019f, 1.0f,
+ -0.275f, 0.0f, -0.4949f, 0.6981f, 1.0f, -0.2828f, 0.0f, -0.527f, 0.7689f, 1.0f,
+ -0.2911f, 0.0f, -0.5578f, 0.8236f, 1.0f, -0.2971f, 0.0f, -0.5884f, 0.866f, 1.0f,
+ -0.303f, 0.0f, -0.6181f, 0.9003f, 1.0f, -0.3089f, 0.0f, -0.6467f, 0.9272f, 1.0f,
+ -0.3148f, 0.0f, -0.6738f, 0.9485f, 1.0f, -0.3196f, 0.0f, -0.7f, 0.9653f, 1.0f,
+ -0.323f, 0.0f, -0.7253f, 0.9781f, 1.0f, -0.3234f, 0.0f, -0.7496f, 0.9876f, 1.0f,
+ -0.3219f, 0.0f, -0.7728f, 0.9942f, 1.0f, -0.3184f, 0.0f, -0.7949f, 0.9983f, 1.0f,
+ -0.3103f, 0.0f, -0.8138f, 0.9997f, 1.0f, -0.3004f, 0.0f, -0.8307f, 0.999f, 1.0f,
+ -0.2892f, 0.0f, -0.8464f, 0.9963f, 1.0f, -0.2766f, 0.0f, -0.8611f, 0.9912f, 1.0f,
+ -0.2618f, 0.0f, -0.8735f, 0.9834f, 1.0f, -0.2469f, 0.0f, -0.8853f, 0.9724f, 1.0f,
+ -0.2315f, 0.0f, -0.8964f, 0.9576f, 1.0f, -0.2158f, 0.0f, -0.9068f, 0.9385f, 1.0f,
+ -0.1997f, 0.0f, -0.9167f, 0.9143f, 1.0f, -0.1833f, 0.0f, -0.9262f, 0.8841f, 1.0f,
+ -0.1663f, 0.0f, -0.9355f, 0.8461f, 1.0f, -0.1481f, 0.0f, -0.9445f, 0.7979f, 1.0f,
+ -0.1282f, 0.0f, -0.9534f, 0.7359f, 1.0f, -0.1077f, 0.0f, -0.9625f, 0.6541f, 1.0f,
+ -0.0854f, 0.0f, -0.9718f, 0.5396f, 1.0f, -0.0616f, 0.0f, -0.9813f, 0.36f, 1.0f,
+ -0.0248f, 0.0f, -0.992f, 0.1f, 1.0f,
};
static const float data7[18 * GP_PRIM_DATABUF_SIZE] = {
- -0.0618f, 0.0f, -0.1922f, 0.1f, 1.0f,
- -0.0703f, 0.0f, -0.2021f, 0.2199f, 1.0f,
- -0.0758f, 0.0f, -0.2103f, 0.6019f, 1.0f,
- -0.0803f, 0.0f, -0.2206f, 0.7689f, 1.0f,
- -0.083f, 0.0f, -0.2307f, 0.866f, 1.0f,
- -0.0851f, 0.0f, -0.2405f, 0.9272f, 1.0f,
- -0.0865f, 0.0f, -0.2499f, 0.9653f, 1.0f,
- -0.0872f, 0.0f, -0.2588f, 0.9876f, 1.0f,
- -0.0869f, 0.0f, -0.2673f, 0.9983f, 1.0f,
- -0.0858f, 0.0f, -0.2754f, 0.999f, 1.0f,
- -0.0831f, 0.0f, -0.2829f, 0.9912f, 1.0f,
- -0.0791f, 0.0f, -0.2898f, 0.9724f, 1.0f,
- -0.074f, 0.0f, -0.2966f, 0.9385f, 1.0f,
- -0.0674f, 0.0f, -0.303f, 0.8841f, 1.0f,
- -0.0591f, 0.0f, -0.3084f, 0.7979f, 1.0f,
- -0.0465f, 0.0f, -0.3134f, 0.6541f, 1.0f,
- -0.0331f, 0.0f, -0.3165f, 0.36f, 1.0f,
- -0.015f, 0.0f, -0.318f, 0.1f, 1.0f,
+ -0.0618f, 0.0f, -0.1922f, 0.1f, 1.0f, -0.0703f, 0.0f, -0.2021f, 0.2199f, 1.0f,
+ -0.0758f, 0.0f, -0.2103f, 0.6019f, 1.0f, -0.0803f, 0.0f, -0.2206f, 0.7689f, 1.0f,
+ -0.083f, 0.0f, -0.2307f, 0.866f, 1.0f, -0.0851f, 0.0f, -0.2405f, 0.9272f, 1.0f,
+ -0.0865f, 0.0f, -0.2499f, 0.9653f, 1.0f, -0.0872f, 0.0f, -0.2588f, 0.9876f, 1.0f,
+ -0.0869f, 0.0f, -0.2673f, 0.9983f, 1.0f, -0.0858f, 0.0f, -0.2754f, 0.999f, 1.0f,
+ -0.0831f, 0.0f, -0.2829f, 0.9912f, 1.0f, -0.0791f, 0.0f, -0.2898f, 0.9724f, 1.0f,
+ -0.074f, 0.0f, -0.2966f, 0.9385f, 1.0f, -0.0674f, 0.0f, -0.303f, 0.8841f, 1.0f,
+ -0.0591f, 0.0f, -0.3084f, 0.7979f, 1.0f, -0.0465f, 0.0f, -0.3134f, 0.6541f, 1.0f,
+ -0.0331f, 0.0f, -0.3165f, 0.36f, 1.0f, -0.015f, 0.0f, -0.318f, 0.1f, 1.0f,
};
static const float data8[49 * GP_PRIM_DATABUF_SIZE] = {
- 0.5311f, 0.0f, 0.1661f, 1.0f, 1.0f,
- 0.5307f, 0.0f, 0.1794f, 1.0f, 1.0f,
- 0.5277f, 0.0f, 0.2057f, 1.0f, 1.0f,
- 0.5218f, 0.0f, 0.2314f, 1.0f, 1.0f,
- 0.513f, 0.0f, 0.256f, 1.0f, 1.0f,
- 0.5014f, 0.0f, 0.279f, 1.0f, 1.0f,
- 0.4874f, 0.0f, 0.3001f, 1.0f, 1.0f,
- 0.4711f, 0.0f, 0.3189f, 1.0f, 1.0f,
- 0.4529f, 0.0f, 0.3351f, 1.0f, 1.0f,
- 0.4329f, 0.0f, 0.3483f, 1.0f, 1.0f,
- 0.4117f, 0.0f, 0.3585f, 1.0f, 1.0f,
- 0.3894f, 0.0f, 0.3654f, 1.0f, 1.0f,
- 0.3666f, 0.0f, 0.3689f, 1.0f, 1.0f,
- 0.3435f, 0.0f, 0.3689f, 1.0f, 1.0f,
- 0.3207f, 0.0f, 0.3654f, 1.0f, 1.0f,
- 0.2985f, 0.0f, 0.3585f, 1.0f, 1.0f,
- 0.2772f, 0.0f, 0.3483f, 1.0f, 1.0f,
- 0.2573f, 0.0f, 0.3351f, 1.0f, 1.0f,
- 0.239f, 0.0f, 0.3189f, 1.0f, 1.0f,
- 0.2227f, 0.0f, 0.3001f, 1.0f, 1.0f,
- 0.2087f, 0.0f, 0.279f, 1.0f, 1.0f,
- 0.1972f, 0.0f, 0.256f, 1.0f, 1.0f,
- 0.1884f, 0.0f, 0.2314f, 1.0f, 1.0f,
- 0.1824f, 0.0f, 0.2057f, 1.0f, 1.0f,
- 0.1794f, 0.0f, 0.1794f, 1.0f, 1.0f,
- 0.1794f, 0.0f, 0.1528f, 1.0f, 1.0f,
- 0.1824f, 0.0f, 0.1264f, 1.0f, 1.0f,
- 0.1884f, 0.0f, 0.1007f, 1.0f, 1.0f,
- 0.1972f, 0.0f, 0.0762f, 1.0f, 1.0f,
- 0.2087f, 0.0f, 0.0531f, 1.0f, 1.0f,
- 0.2227f, 0.0f, 0.032f, 1.0f, 1.0f,
- 0.239f, 0.0f, 0.0132f, 1.0f, 1.0f,
- 0.2573f, 0.0f, -0.0029f, 1.0f, 1.0f,
- 0.2772f, 0.0f, -0.0162f, 1.0f, 1.0f,
- 0.2985f, 0.0f, -0.0264f, 1.0f, 1.0f,
- 0.3207f, 0.0f, -0.0333f, 1.0f, 1.0f,
- 0.3435f, 0.0f, -0.0368f, 1.0f, 1.0f,
- 0.3666f, 0.0f, -0.0368f, 1.0f, 1.0f,
- 0.3894f, 0.0f, -0.0333f, 1.0f, 1.0f,
- 0.4117f, 0.0f, -0.0264f, 1.0f, 1.0f,
- 0.4329f, 0.0f, -0.0162f, 1.0f, 1.0f,
- 0.4529f, 0.0f, -0.0029f, 1.0f, 1.0f,
- 0.4711f, 0.0f, 0.0132f, 1.0f, 1.0f,
- 0.4874f, 0.0f, 0.032f, 1.0f, 1.0f,
- 0.5014f, 0.0f, 0.0531f, 1.0f, 1.0f,
- 0.513f, 0.0f, 0.0762f, 1.0f, 1.0f,
- 0.5218f, 0.0f, 0.1007f, 1.0f, 1.0f,
- 0.5277f, 0.0f, 0.1264f, 1.0f, 1.0f,
- 0.5307f, 0.0f, 0.1528f, 1.0f, 1.0f,
+ 0.5311f, 0.0f, 0.1661f, 1.0f, 1.0f, 0.5307f, 0.0f, 0.1794f, 1.0f, 1.0f,
+ 0.5277f, 0.0f, 0.2057f, 1.0f, 1.0f, 0.5218f, 0.0f, 0.2314f, 1.0f, 1.0f,
+ 0.513f, 0.0f, 0.256f, 1.0f, 1.0f, 0.5014f, 0.0f, 0.279f, 1.0f, 1.0f,
+ 0.4874f, 0.0f, 0.3001f, 1.0f, 1.0f, 0.4711f, 0.0f, 0.3189f, 1.0f, 1.0f,
+ 0.4529f, 0.0f, 0.3351f, 1.0f, 1.0f, 0.4329f, 0.0f, 0.3483f, 1.0f, 1.0f,
+ 0.4117f, 0.0f, 0.3585f, 1.0f, 1.0f, 0.3894f, 0.0f, 0.3654f, 1.0f, 1.0f,
+ 0.3666f, 0.0f, 0.3689f, 1.0f, 1.0f, 0.3435f, 0.0f, 0.3689f, 1.0f, 1.0f,
+ 0.3207f, 0.0f, 0.3654f, 1.0f, 1.0f, 0.2985f, 0.0f, 0.3585f, 1.0f, 1.0f,
+ 0.2772f, 0.0f, 0.3483f, 1.0f, 1.0f, 0.2573f, 0.0f, 0.3351f, 1.0f, 1.0f,
+ 0.239f, 0.0f, 0.3189f, 1.0f, 1.0f, 0.2227f, 0.0f, 0.3001f, 1.0f, 1.0f,
+ 0.2087f, 0.0f, 0.279f, 1.0f, 1.0f, 0.1972f, 0.0f, 0.256f, 1.0f, 1.0f,
+ 0.1884f, 0.0f, 0.2314f, 1.0f, 1.0f, 0.1824f, 0.0f, 0.2057f, 1.0f, 1.0f,
+ 0.1794f, 0.0f, 0.1794f, 1.0f, 1.0f, 0.1794f, 0.0f, 0.1528f, 1.0f, 1.0f,
+ 0.1824f, 0.0f, 0.1264f, 1.0f, 1.0f, 0.1884f, 0.0f, 0.1007f, 1.0f, 1.0f,
+ 0.1972f, 0.0f, 0.0762f, 1.0f, 1.0f, 0.2087f, 0.0f, 0.0531f, 1.0f, 1.0f,
+ 0.2227f, 0.0f, 0.032f, 1.0f, 1.0f, 0.239f, 0.0f, 0.0132f, 1.0f, 1.0f,
+ 0.2573f, 0.0f, -0.0029f, 1.0f, 1.0f, 0.2772f, 0.0f, -0.0162f, 1.0f, 1.0f,
+ 0.2985f, 0.0f, -0.0264f, 1.0f, 1.0f, 0.3207f, 0.0f, -0.0333f, 1.0f, 1.0f,
+ 0.3435f, 0.0f, -0.0368f, 1.0f, 1.0f, 0.3666f, 0.0f, -0.0368f, 1.0f, 1.0f,
+ 0.3894f, 0.0f, -0.0333f, 1.0f, 1.0f, 0.4117f, 0.0f, -0.0264f, 1.0f, 1.0f,
+ 0.4329f, 0.0f, -0.0162f, 1.0f, 1.0f, 0.4529f, 0.0f, -0.0029f, 1.0f, 1.0f,
+ 0.4711f, 0.0f, 0.0132f, 1.0f, 1.0f, 0.4874f, 0.0f, 0.032f, 1.0f, 1.0f,
+ 0.5014f, 0.0f, 0.0531f, 1.0f, 1.0f, 0.513f, 0.0f, 0.0762f, 1.0f, 1.0f,
+ 0.5218f, 0.0f, 0.1007f, 1.0f, 1.0f, 0.5277f, 0.0f, 0.1264f, 1.0f, 1.0f,
+ 0.5307f, 0.0f, 0.1528f, 1.0f, 1.0f,
};
static const float data9[33 * GP_PRIM_DATABUF_SIZE] = {
- -0.5271f, 0.0f, 0.1742f, 0.1f, 1.0f,
- -0.527f, 0.0f, 0.1621f, 0.2199f, 1.0f,
- -0.5253f, 0.0f, 0.1386f, 0.4615f, 1.0f,
- -0.5217f, 0.0f, 0.116f, 0.6019f, 1.0f,
- -0.5164f, 0.0f, 0.0945f, 0.6981f, 1.0f,
- -0.5094f, 0.0f, 0.0741f, 0.7689f, 1.0f,
- -0.5009f, 0.0f, 0.0548f, 0.8236f, 1.0f,
- -0.491f, 0.0f, 0.0368f, 0.866f, 1.0f,
- -0.4799f, 0.0f, 0.02f, 0.9003f, 1.0f,
- -0.4676f, 0.0f, 0.0046f, 0.9272f, 1.0f,
- -0.4544f, 0.0f, -0.0094f, 0.9485f, 1.0f,
- -0.4402f, 0.0f, -0.0219f, 0.9653f, 1.0f,
- -0.4254f, 0.0f, -0.033f, 0.9781f, 1.0f,
- -0.4099f, 0.0f, -0.0424f, 0.9876f, 1.0f,
- -0.394f, 0.0f, -0.0501f, 0.9942f, 1.0f,
- -0.3777f, 0.0f, -0.0562f, 0.9983f, 1.0f,
- -0.3612f, 0.0f, -0.0605f, 0.9997f, 1.0f,
- -0.3447f, 0.0f, -0.0629f, 0.999f, 1.0f,
- -0.3281f, 0.0f, -0.0634f, 0.9963f, 1.0f,
- -0.3118f, 0.0f, -0.062f, 0.9912f, 1.0f,
- -0.2957f, 0.0f, -0.0585f, 0.9834f, 1.0f,
- -0.2801f, 0.0f, -0.0529f, 0.9724f, 1.0f,
- -0.2651f, 0.0f, -0.0452f, 0.9576f, 1.0f,
- -0.2507f, 0.0f, -0.0352f, 0.9385f, 1.0f,
- -0.2372f, 0.0f, -0.023f, 0.9143f, 1.0f,
- -0.2246f, 0.0f, -0.0085f, 0.8841f, 1.0f,
- -0.2131f, 0.0f, 0.0085f, 0.8461f, 1.0f,
- -0.2028f, 0.0f, 0.0279f, 0.7979f, 1.0f,
- -0.1939f, 0.0f, 0.0499f, 0.7359f, 1.0f,
- -0.1864f, 0.0f, 0.0745f, 0.6541f, 1.0f,
- -0.1806f, 0.0f, 0.1017f, 0.5396f, 1.0f,
- -0.1765f, 0.0f, 0.1316f, 0.36f, 1.0f,
- -0.1742f, 0.0f, 0.1643f, 0.1f, 1.0f,
+ -0.5271f, 0.0f, 0.1742f, 0.1f, 1.0f, -0.527f, 0.0f, 0.1621f, 0.2199f, 1.0f,
+ -0.5253f, 0.0f, 0.1386f, 0.4615f, 1.0f, -0.5217f, 0.0f, 0.116f, 0.6019f, 1.0f,
+ -0.5164f, 0.0f, 0.0945f, 0.6981f, 1.0f, -0.5094f, 0.0f, 0.0741f, 0.7689f, 1.0f,
+ -0.5009f, 0.0f, 0.0548f, 0.8236f, 1.0f, -0.491f, 0.0f, 0.0368f, 0.866f, 1.0f,
+ -0.4799f, 0.0f, 0.02f, 0.9003f, 1.0f, -0.4676f, 0.0f, 0.0046f, 0.9272f, 1.0f,
+ -0.4544f, 0.0f, -0.0094f, 0.9485f, 1.0f, -0.4402f, 0.0f, -0.0219f, 0.9653f, 1.0f,
+ -0.4254f, 0.0f, -0.033f, 0.9781f, 1.0f, -0.4099f, 0.0f, -0.0424f, 0.9876f, 1.0f,
+ -0.394f, 0.0f, -0.0501f, 0.9942f, 1.0f, -0.3777f, 0.0f, -0.0562f, 0.9983f, 1.0f,
+ -0.3612f, 0.0f, -0.0605f, 0.9997f, 1.0f, -0.3447f, 0.0f, -0.0629f, 0.999f, 1.0f,
+ -0.3281f, 0.0f, -0.0634f, 0.9963f, 1.0f, -0.3118f, 0.0f, -0.062f, 0.9912f, 1.0f,
+ -0.2957f, 0.0f, -0.0585f, 0.9834f, 1.0f, -0.2801f, 0.0f, -0.0529f, 0.9724f, 1.0f,
+ -0.2651f, 0.0f, -0.0452f, 0.9576f, 1.0f, -0.2507f, 0.0f, -0.0352f, 0.9385f, 1.0f,
+ -0.2372f, 0.0f, -0.023f, 0.9143f, 1.0f, -0.2246f, 0.0f, -0.0085f, 0.8841f, 1.0f,
+ -0.2131f, 0.0f, 0.0085f, 0.8461f, 1.0f, -0.2028f, 0.0f, 0.0279f, 0.7979f, 1.0f,
+ -0.1939f, 0.0f, 0.0499f, 0.7359f, 1.0f, -0.1864f, 0.0f, 0.0745f, 0.6541f, 1.0f,
+ -0.1806f, 0.0f, 0.1017f, 0.5396f, 1.0f, -0.1765f, 0.0f, 0.1316f, 0.36f, 1.0f,
+ -0.1742f, 0.0f, 0.1643f, 0.1f, 1.0f,
};
static const float data10[49 * GP_PRIM_DATABUF_SIZE] = {
- -0.174f, 0.0f, 0.1661f, 1.0f, 1.0f,
- -0.1744f, 0.0f, 0.1794f, 1.0f, 1.0f,
- -0.1774f, 0.0f, 0.2057f, 1.0f, 1.0f,
- -0.1833f, 0.0f, 0.2314f, 1.0f, 1.0f,
- -0.1922f, 0.0f, 0.256f, 1.0f, 1.0f,
- -0.2037f, 0.0f, 0.279f, 1.0f, 1.0f,
- -0.2177f, 0.0f, 0.3001f, 1.0f, 1.0f,
- -0.234f, 0.0f, 0.3189f, 1.0f, 1.0f,
- -0.2522f, 0.0f, 0.3351f, 1.0f, 1.0f,
- -0.2722f, 0.0f, 0.3483f, 1.0f, 1.0f,
- -0.2935f, 0.0f, 0.3585f, 1.0f, 1.0f,
- -0.3157f, 0.0f, 0.3654f, 1.0f, 1.0f,
- -0.3385f, 0.0f, 0.3689f, 1.0f, 1.0f,
- -0.3616f, 0.0f, 0.3689f, 1.0f, 1.0f,
- -0.3844f, 0.0f, 0.3654f, 1.0f, 1.0f,
- -0.4066f, 0.0f, 0.3585f, 1.0f, 1.0f,
- -0.4279f, 0.0f, 0.3483f, 1.0f, 1.0f,
- -0.4479f, 0.0f, 0.3351f, 1.0f, 1.0f,
- -0.4661f, 0.0f, 0.3189f, 1.0f, 1.0f,
- -0.4824f, 0.0f, 0.3001f, 1.0f, 1.0f,
- -0.4964f, 0.0f, 0.279f, 1.0f, 1.0f,
- -0.508f, 0.0f, 0.256f, 1.0f, 1.0f,
- -0.5168f, 0.0f, 0.2314f, 1.0f, 1.0f,
- -0.5227f, 0.0f, 0.2057f, 1.0f, 1.0f,
- -0.5257f, 0.0f, 0.1794f, 1.0f, 1.0f,
- -0.5257f, 0.0f, 0.1528f, 1.0f, 1.0f,
- -0.5227f, 0.0f, 0.1264f, 1.0f, 1.0f,
- -0.5168f, 0.0f, 0.1007f, 1.0f, 1.0f,
- -0.508f, 0.0f, 0.0762f, 1.0f, 1.0f,
- -0.4964f, 0.0f, 0.0531f, 1.0f, 1.0f,
- -0.4824f, 0.0f, 0.032f, 1.0f, 1.0f,
- -0.4661f, 0.0f, 0.0132f, 1.0f, 1.0f,
- -0.4479f, 0.0f, -0.0029f, 1.0f, 1.0f,
- -0.4279f, 0.0f, -0.0162f, 1.0f, 1.0f,
- -0.4066f, 0.0f, -0.0264f, 1.0f, 1.0f,
- -0.3844f, 0.0f, -0.0333f, 1.0f, 1.0f,
- -0.3616f, 0.0f, -0.0368f, 1.0f, 1.0f,
- -0.3385f, 0.0f, -0.0368f, 1.0f, 1.0f,
- -0.3157f, 0.0f, -0.0333f, 1.0f, 1.0f,
- -0.2935f, 0.0f, -0.0264f, 1.0f, 1.0f,
- -0.2722f, 0.0f, -0.0162f, 1.0f, 1.0f,
- -0.2522f, 0.0f, -0.0029f, 1.0f, 1.0f,
- -0.234f, 0.0f, 0.0132f, 1.0f, 1.0f,
- -0.2177f, 0.0f, 0.032f, 1.0f, 1.0f,
- -0.2037f, 0.0f, 0.0531f, 1.0f, 1.0f,
- -0.1922f, 0.0f, 0.0762f, 1.0f, 1.0f,
- -0.1833f, 0.0f, 0.1007f, 1.0f, 1.0f,
- -0.1774f, 0.0f, 0.1264f, 1.0f, 1.0f,
- -0.1744f, 0.0f, 0.1528f, 1.0f, 1.0f,
+ -0.174f, 0.0f, 0.1661f, 1.0f, 1.0f, -0.1744f, 0.0f, 0.1794f, 1.0f, 1.0f,
+ -0.1774f, 0.0f, 0.2057f, 1.0f, 1.0f, -0.1833f, 0.0f, 0.2314f, 1.0f, 1.0f,
+ -0.1922f, 0.0f, 0.256f, 1.0f, 1.0f, -0.2037f, 0.0f, 0.279f, 1.0f, 1.0f,
+ -0.2177f, 0.0f, 0.3001f, 1.0f, 1.0f, -0.234f, 0.0f, 0.3189f, 1.0f, 1.0f,
+ -0.2522f, 0.0f, 0.3351f, 1.0f, 1.0f, -0.2722f, 0.0f, 0.3483f, 1.0f, 1.0f,
+ -0.2935f, 0.0f, 0.3585f, 1.0f, 1.0f, -0.3157f, 0.0f, 0.3654f, 1.0f, 1.0f,
+ -0.3385f, 0.0f, 0.3689f, 1.0f, 1.0f, -0.3616f, 0.0f, 0.3689f, 1.0f, 1.0f,
+ -0.3844f, 0.0f, 0.3654f, 1.0f, 1.0f, -0.4066f, 0.0f, 0.3585f, 1.0f, 1.0f,
+ -0.4279f, 0.0f, 0.3483f, 1.0f, 1.0f, -0.4479f, 0.0f, 0.3351f, 1.0f, 1.0f,
+ -0.4661f, 0.0f, 0.3189f, 1.0f, 1.0f, -0.4824f, 0.0f, 0.3001f, 1.0f, 1.0f,
+ -0.4964f, 0.0f, 0.279f, 1.0f, 1.0f, -0.508f, 0.0f, 0.256f, 1.0f, 1.0f,
+ -0.5168f, 0.0f, 0.2314f, 1.0f, 1.0f, -0.5227f, 0.0f, 0.2057f, 1.0f, 1.0f,
+ -0.5257f, 0.0f, 0.1794f, 1.0f, 1.0f, -0.5257f, 0.0f, 0.1528f, 1.0f, 1.0f,
+ -0.5227f, 0.0f, 0.1264f, 1.0f, 1.0f, -0.5168f, 0.0f, 0.1007f, 1.0f, 1.0f,
+ -0.508f, 0.0f, 0.0762f, 1.0f, 1.0f, -0.4964f, 0.0f, 0.0531f, 1.0f, 1.0f,
+ -0.4824f, 0.0f, 0.032f, 1.0f, 1.0f, -0.4661f, 0.0f, 0.0132f, 1.0f, 1.0f,
+ -0.4479f, 0.0f, -0.0029f, 1.0f, 1.0f, -0.4279f, 0.0f, -0.0162f, 1.0f, 1.0f,
+ -0.4066f, 0.0f, -0.0264f, 1.0f, 1.0f, -0.3844f, 0.0f, -0.0333f, 1.0f, 1.0f,
+ -0.3616f, 0.0f, -0.0368f, 1.0f, 1.0f, -0.3385f, 0.0f, -0.0368f, 1.0f, 1.0f,
+ -0.3157f, 0.0f, -0.0333f, 1.0f, 1.0f, -0.2935f, 0.0f, -0.0264f, 1.0f, 1.0f,
+ -0.2722f, 0.0f, -0.0162f, 1.0f, 1.0f, -0.2522f, 0.0f, -0.0029f, 1.0f, 1.0f,
+ -0.234f, 0.0f, 0.0132f, 1.0f, 1.0f, -0.2177f, 0.0f, 0.032f, 1.0f, 1.0f,
+ -0.2037f, 0.0f, 0.0531f, 1.0f, 1.0f, -0.1922f, 0.0f, 0.0762f, 1.0f, 1.0f,
+ -0.1833f, 0.0f, 0.1007f, 1.0f, 1.0f, -0.1774f, 0.0f, 0.1264f, 1.0f, 1.0f,
+ -0.1744f, 0.0f, 0.1528f, 1.0f, 1.0f,
};
static const float data11[18 * GP_PRIM_DATABUF_SIZE] = {
- 0.963f, 0.0f, 0.1753f, 0.1f, 1.0f,
- 0.9555f, 0.0f, 0.1761f, 0.2199f, 1.0f,
- 0.9367f, 0.0f, 0.1758f, 0.6019f, 1.0f,
- 0.9202f, 0.0f, 0.1741f, 0.7689f, 1.0f,
- 0.9036f, 0.0f, 0.1714f, 0.866f, 1.0f,
- 0.8885f, 0.0f, 0.1668f, 0.9272f, 1.0f,
- 0.8746f, 0.0f, 0.1607f, 0.9653f, 1.0f,
- 0.8621f, 0.0f, 0.1531f, 0.9876f, 1.0f,
- 0.8503f, 0.0f, 0.1447f, 0.9983f, 1.0f,
- 0.8389f, 0.0f, 0.1352f, 0.999f, 1.0f,
- 0.8279f, 0.0f, 0.1244f, 0.9912f, 1.0f,
- 0.8174f, 0.0f, 0.1125f, 0.9724f, 1.0f,
- 0.8079f, 0.0f, 0.099f, 0.9385f, 1.0f,
- 0.7999f, 0.0f, 0.0839f, 0.8841f, 1.0f,
- 0.7935f, 0.0f, 0.0669f, 0.7979f, 1.0f,
- 0.7892f, 0.0f, 0.0488f, 0.6541f, 1.0f,
- 0.787f, 0.0f, 0.0305f, 0.36f, 1.0f,
- 0.7847f, 0.0f, 0.0139f, 0.1f, 1.0f,
+ 0.963f, 0.0f, 0.1753f, 0.1f, 1.0f, 0.9555f, 0.0f, 0.1761f, 0.2199f, 1.0f,
+ 0.9367f, 0.0f, 0.1758f, 0.6019f, 1.0f, 0.9202f, 0.0f, 0.1741f, 0.7689f, 1.0f,
+ 0.9036f, 0.0f, 0.1714f, 0.866f, 1.0f, 0.8885f, 0.0f, 0.1668f, 0.9272f, 1.0f,
+ 0.8746f, 0.0f, 0.1607f, 0.9653f, 1.0f, 0.8621f, 0.0f, 0.1531f, 0.9876f, 1.0f,
+ 0.8503f, 0.0f, 0.1447f, 0.9983f, 1.0f, 0.8389f, 0.0f, 0.1352f, 0.999f, 1.0f,
+ 0.8279f, 0.0f, 0.1244f, 0.9912f, 1.0f, 0.8174f, 0.0f, 0.1125f, 0.9724f, 1.0f,
+ 0.8079f, 0.0f, 0.099f, 0.9385f, 1.0f, 0.7999f, 0.0f, 0.0839f, 0.8841f, 1.0f,
+ 0.7935f, 0.0f, 0.0669f, 0.7979f, 1.0f, 0.7892f, 0.0f, 0.0488f, 0.6541f, 1.0f,
+ 0.787f, 0.0f, 0.0305f, 0.36f, 1.0f, 0.7847f, 0.0f, 0.0139f, 0.1f, 1.0f,
};
static const float data12[18 * GP_PRIM_DATABUF_SIZE] = {
- -1.0227f, 0.0f, 0.1753f, 0.1f, 1.0f,
- -1.0153f, 0.0f, 0.1761f, 0.2199f, 1.0f,
- -0.9964f, 0.0f, 0.1758f, 0.6019f, 1.0f,
- -0.9799f, 0.0f, 0.1741f, 0.7689f, 1.0f,
- -0.9634f, 0.0f, 0.1714f, 0.866f, 1.0f,
- -0.9483f, 0.0f, 0.1668f, 0.9272f, 1.0f,
- -0.9344f, 0.0f, 0.1607f, 0.9653f, 1.0f,
- -0.9219f, 0.0f, 0.1531f, 0.9876f, 1.0f,
- -0.9101f, 0.0f, 0.1447f, 0.9983f, 1.0f,
- -0.8986f, 0.0f, 0.1352f, 0.999f, 1.0f,
- -0.8876f, 0.0f, 0.1244f, 0.9912f, 1.0f,
- -0.8772f, 0.0f, 0.1125f, 0.9724f, 1.0f,
- -0.8677f, 0.0f, 0.099f, 0.9385f, 1.0f,
- -0.8597f, 0.0f, 0.0839f, 0.8841f, 1.0f,
- -0.8533f, 0.0f, 0.0669f, 0.7979f, 1.0f,
- -0.849f, 0.0f, 0.0488f, 0.6541f, 1.0f,
- -0.8467f, 0.0f, 0.0305f, 0.36f, 1.0f,
- -0.8444f, 0.0f, 0.0139f, 0.1f, 1.0f,
+ -1.0227f, 0.0f, 0.1753f, 0.1f, 1.0f, -1.0153f, 0.0f, 0.1761f, 0.2199f, 1.0f,
+ -0.9964f, 0.0f, 0.1758f, 0.6019f, 1.0f, -0.9799f, 0.0f, 0.1741f, 0.7689f, 1.0f,
+ -0.9634f, 0.0f, 0.1714f, 0.866f, 1.0f, -0.9483f, 0.0f, 0.1668f, 0.9272f, 1.0f,
+ -0.9344f, 0.0f, 0.1607f, 0.9653f, 1.0f, -0.9219f, 0.0f, 0.1531f, 0.9876f, 1.0f,
+ -0.9101f, 0.0f, 0.1447f, 0.9983f, 1.0f, -0.8986f, 0.0f, 0.1352f, 0.999f, 1.0f,
+ -0.8876f, 0.0f, 0.1244f, 0.9912f, 1.0f, -0.8772f, 0.0f, 0.1125f, 0.9724f, 1.0f,
+ -0.8677f, 0.0f, 0.099f, 0.9385f, 1.0f, -0.8597f, 0.0f, 0.0839f, 0.8841f, 1.0f,
+ -0.8533f, 0.0f, 0.0669f, 0.7979f, 1.0f, -0.849f, 0.0f, 0.0488f, 0.6541f, 1.0f,
+ -0.8467f, 0.0f, 0.0305f, 0.36f, 1.0f, -0.8444f, 0.0f, 0.0139f, 0.1f, 1.0f,
};
static const float data13[33 * GP_PRIM_DATABUF_SIZE] = {
- -0.6794f, 0.0f, 0.3908f, 0.1f, 1.0f,
- -0.6711f, 0.0f, 0.4112f, 0.2199f, 1.0f,
- -0.6513f, 0.0f, 0.4509f, 0.4615f, 1.0f,
- -0.6276f, 0.0f, 0.489f, 0.6019f, 1.0f,
- -0.6001f, 0.0f, 0.5253f, 0.6981f, 1.0f,
- -0.5692f, 0.0f, 0.5598f, 0.7689f, 1.0f,
- -0.535f, 0.0f, 0.5924f, 0.8236f, 1.0f,
- -0.4979f, 0.0f, 0.6228f, 0.866f, 1.0f,
- -0.4579f, 0.0f, 0.651f, 0.9003f, 1.0f,
- -0.4155f, 0.0f, 0.677f, 0.9272f, 1.0f,
- -0.3707f, 0.0f, 0.7005f, 0.9485f, 1.0f,
- -0.3239f, 0.0f, 0.7215f, 0.9653f, 1.0f,
- -0.2753f, 0.0f, 0.7399f, 0.9781f, 1.0f,
- -0.2251f, 0.0f, 0.7555f, 0.9876f, 1.0f,
- -0.1736f, 0.0f, 0.7683f, 0.9942f, 1.0f,
- -0.121f, 0.0f, 0.778f, 0.9983f, 1.0f,
- -0.0675f, 0.0f, 0.7847f, 0.9997f, 1.0f,
- -0.0134f, 0.0f, 0.7882f, 0.999f, 1.0f,
- 0.0411f, 0.0f, 0.7884f, 0.9963f, 1.0f,
- 0.0957f, 0.0f, 0.7851f, 0.9912f, 1.0f,
- 0.1503f, 0.0f, 0.7783f, 0.9834f, 1.0f,
- 0.2045f, 0.0f, 0.7678f, 0.9724f, 1.0f,
- 0.2581f, 0.0f, 0.7536f, 0.9576f, 1.0f,
- 0.311f, 0.0f, 0.7355f, 0.9385f, 1.0f,
- 0.3628f, 0.0f, 0.7134f, 0.9143f, 1.0f,
- 0.4133f, 0.0f, 0.6873f, 0.8841f, 1.0f,
- 0.4622f, 0.0f, 0.6569f, 0.8461f, 1.0f,
- 0.5095f, 0.0f, 0.6221f, 0.7979f, 1.0f,
- 0.5547f, 0.0f, 0.583f, 0.7359f, 1.0f,
- 0.5977f, 0.0f, 0.5393f, 0.6541f, 1.0f,
- 0.6382f, 0.0f, 0.4909f, 0.5396f, 1.0f,
- 0.676f, 0.0f, 0.4377f, 0.36f, 1.0f,
- 0.7109f, 0.0f, 0.3797f, 0.1f, 1.0f,
+ -0.6794f, 0.0f, 0.3908f, 0.1f, 1.0f, -0.6711f, 0.0f, 0.4112f, 0.2199f, 1.0f,
+ -0.6513f, 0.0f, 0.4509f, 0.4615f, 1.0f, -0.6276f, 0.0f, 0.489f, 0.6019f, 1.0f,
+ -0.6001f, 0.0f, 0.5253f, 0.6981f, 1.0f, -0.5692f, 0.0f, 0.5598f, 0.7689f, 1.0f,
+ -0.535f, 0.0f, 0.5924f, 0.8236f, 1.0f, -0.4979f, 0.0f, 0.6228f, 0.866f, 1.0f,
+ -0.4579f, 0.0f, 0.651f, 0.9003f, 1.0f, -0.4155f, 0.0f, 0.677f, 0.9272f, 1.0f,
+ -0.3707f, 0.0f, 0.7005f, 0.9485f, 1.0f, -0.3239f, 0.0f, 0.7215f, 0.9653f, 1.0f,
+ -0.2753f, 0.0f, 0.7399f, 0.9781f, 1.0f, -0.2251f, 0.0f, 0.7555f, 0.9876f, 1.0f,
+ -0.1736f, 0.0f, 0.7683f, 0.9942f, 1.0f, -0.121f, 0.0f, 0.778f, 0.9983f, 1.0f,
+ -0.0675f, 0.0f, 0.7847f, 0.9997f, 1.0f, -0.0134f, 0.0f, 0.7882f, 0.999f, 1.0f,
+ 0.0411f, 0.0f, 0.7884f, 0.9963f, 1.0f, 0.0957f, 0.0f, 0.7851f, 0.9912f, 1.0f,
+ 0.1503f, 0.0f, 0.7783f, 0.9834f, 1.0f, 0.2045f, 0.0f, 0.7678f, 0.9724f, 1.0f,
+ 0.2581f, 0.0f, 0.7536f, 0.9576f, 1.0f, 0.311f, 0.0f, 0.7355f, 0.9385f, 1.0f,
+ 0.3628f, 0.0f, 0.7134f, 0.9143f, 1.0f, 0.4133f, 0.0f, 0.6873f, 0.8841f, 1.0f,
+ 0.4622f, 0.0f, 0.6569f, 0.8461f, 1.0f, 0.5095f, 0.0f, 0.6221f, 0.7979f, 1.0f,
+ 0.5547f, 0.0f, 0.583f, 0.7359f, 1.0f, 0.5977f, 0.0f, 0.5393f, 0.6541f, 1.0f,
+ 0.6382f, 0.0f, 0.4909f, 0.5396f, 1.0f, 0.676f, 0.0f, 0.4377f, 0.36f, 1.0f,
+ 0.7109f, 0.0f, 0.3797f, 0.1f, 1.0f,
};
static const float data14[33 * GP_PRIM_DATABUF_SIZE] = {
- -0.7544f, 0.0f, 0.1799f, 0.1f, 1.0f,
- -0.7495f, 0.0f, 0.162f, 0.2199f, 1.0f,
- -0.7392f, 0.0f, 0.1283f, 0.4615f, 1.0f,
- -0.7281f, 0.0f, 0.0975f, 0.6019f, 1.0f,
- -0.7161f, 0.0f, 0.0693f, 0.6981f, 1.0f,
- -0.7033f, 0.0f, 0.0435f, 0.7689f, 1.0f,
- -0.6898f, 0.0f, 0.02f, 0.8236f, 1.0f,
- -0.6757f, 0.0f, -0.0014f, 0.866f, 1.0f,
- -0.6609f, 0.0f, -0.0208f, 0.9003f, 1.0f,
- -0.6455f, 0.0f, -0.0386f, 0.9272f, 1.0f,
- -0.6297f, 0.0f, -0.0547f, 0.9485f, 1.0f,
- -0.6133f, 0.0f, -0.0695f, 0.9653f, 1.0f,
- -0.5966f, 0.0f, -0.083f, 0.9781f, 1.0f,
- -0.5795f, 0.0f, -0.0955f, 0.9876f, 1.0f,
- -0.5621f, 0.0f, -0.1071f, 0.9942f, 1.0f,
- -0.5444f, 0.0f, -0.118f, 0.9983f, 1.0f,
- -0.5265f, 0.0f, -0.1284f, 0.9997f, 1.0f,
- -0.5084f, 0.0f, -0.1384f, 0.999f, 1.0f,
- -0.4902f, 0.0f, -0.1483f, 0.9963f, 1.0f,
- -0.4719f, 0.0f, -0.1582f, 0.9912f, 1.0f,
- -0.4537f, 0.0f, -0.1682f, 0.9834f, 1.0f,
- -0.4355f, 0.0f, -0.1787f, 0.9724f, 1.0f,
- -0.4173f, 0.0f, -0.1896f, 0.9576f, 1.0f,
- -0.3993f, 0.0f, -0.2013f, 0.9385f, 1.0f,
- -0.3815f, 0.0f, -0.2138f, 0.9143f, 1.0f,
- -0.364f, 0.0f, -0.2274f, 0.8841f, 1.0f,
- -0.3467f, 0.0f, -0.2422f, 0.8461f, 1.0f,
- -0.3298f, 0.0f, -0.2584f, 0.7979f, 1.0f,
- -0.3133f, 0.0f, -0.2762f, 0.7359f, 1.0f,
- -0.2972f, 0.0f, -0.2958f, 0.6541f, 1.0f,
- -0.2816f, 0.0f, -0.3173f, 0.5396f, 1.0f,
- -0.2665f, 0.0f, -0.3409f, 0.36f, 1.0f,
- -0.2521f, 0.0f, -0.3668f, 0.1f, 1.0f,
+ -0.7544f, 0.0f, 0.1799f, 0.1f, 1.0f, -0.7495f, 0.0f, 0.162f, 0.2199f, 1.0f,
+ -0.7392f, 0.0f, 0.1283f, 0.4615f, 1.0f, -0.7281f, 0.0f, 0.0975f, 0.6019f, 1.0f,
+ -0.7161f, 0.0f, 0.0693f, 0.6981f, 1.0f, -0.7033f, 0.0f, 0.0435f, 0.7689f, 1.0f,
+ -0.6898f, 0.0f, 0.02f, 0.8236f, 1.0f, -0.6757f, 0.0f, -0.0014f, 0.866f, 1.0f,
+ -0.6609f, 0.0f, -0.0208f, 0.9003f, 1.0f, -0.6455f, 0.0f, -0.0386f, 0.9272f, 1.0f,
+ -0.6297f, 0.0f, -0.0547f, 0.9485f, 1.0f, -0.6133f, 0.0f, -0.0695f, 0.9653f, 1.0f,
+ -0.5966f, 0.0f, -0.083f, 0.9781f, 1.0f, -0.5795f, 0.0f, -0.0955f, 0.9876f, 1.0f,
+ -0.5621f, 0.0f, -0.1071f, 0.9942f, 1.0f, -0.5444f, 0.0f, -0.118f, 0.9983f, 1.0f,
+ -0.5265f, 0.0f, -0.1284f, 0.9997f, 1.0f, -0.5084f, 0.0f, -0.1384f, 0.999f, 1.0f,
+ -0.4902f, 0.0f, -0.1483f, 0.9963f, 1.0f, -0.4719f, 0.0f, -0.1582f, 0.9912f, 1.0f,
+ -0.4537f, 0.0f, -0.1682f, 0.9834f, 1.0f, -0.4355f, 0.0f, -0.1787f, 0.9724f, 1.0f,
+ -0.4173f, 0.0f, -0.1896f, 0.9576f, 1.0f, -0.3993f, 0.0f, -0.2013f, 0.9385f, 1.0f,
+ -0.3815f, 0.0f, -0.2138f, 0.9143f, 1.0f, -0.364f, 0.0f, -0.2274f, 0.8841f, 1.0f,
+ -0.3467f, 0.0f, -0.2422f, 0.8461f, 1.0f, -0.3298f, 0.0f, -0.2584f, 0.7979f, 1.0f,
+ -0.3133f, 0.0f, -0.2762f, 0.7359f, 1.0f, -0.2972f, 0.0f, -0.2958f, 0.6541f, 1.0f,
+ -0.2816f, 0.0f, -0.3173f, 0.5396f, 1.0f, -0.2665f, 0.0f, -0.3409f, 0.36f, 1.0f,
+ -0.2521f, 0.0f, -0.3668f, 0.1f, 1.0f,
};
static const float data15[65 * GP_PRIM_DATABUF_SIZE] = {
- -0.2854f, 0.0f, -0.4528f, 0.1f, 1.0f,
- -0.2866f, 0.0f, -0.4623f, 0.1288f, 1.0f,
- -0.2899f, 0.0f, -0.4814f, 0.2962f, 1.0f,
- -0.2943f, 0.0f, -0.5008f, 0.4147f, 1.0f,
- -0.2995f, 0.0f, -0.5203f, 0.5028f, 1.0f,
- -0.3054f, 0.0f, -0.54f, 0.5723f, 1.0f,
- -0.3117f, 0.0f, -0.5598f, 0.6291f, 1.0f,
- -0.3182f, 0.0f, -0.5797f, 0.6768f, 1.0f,
- -0.3249f, 0.0f, -0.5996f, 0.7177f, 1.0f,
- -0.3314f, 0.0f, -0.6196f, 0.753f, 1.0f,
- -0.3376f, 0.0f, -0.6395f, 0.7838f, 1.0f,
- -0.3432f, 0.0f, -0.6594f, 0.8109f, 1.0f,
- -0.3482f, 0.0f, -0.6792f, 0.8349f, 1.0f,
- -0.3523f, 0.0f, -0.6989f, 0.8564f, 1.0f,
- -0.3552f, 0.0f, -0.7185f, 0.8756f, 1.0f,
- -0.3569f, 0.0f, -0.7379f, 0.8922f, 1.0f,
- -0.357f, 0.0f, -0.7571f, 0.9074f, 1.0f,
- -0.3555f, 0.0f, -0.7761f, 0.9211f, 1.0f,
- -0.3522f, 0.0f, -0.7948f, 0.9329f, 1.0f,
- -0.3467f, 0.0f, -0.8132f, 0.944f, 1.0f,
- -0.339f, 0.0f, -0.8313f, 0.9531f, 1.0f,
- -0.3289f, 0.0f, -0.849f, 0.9617f, 1.0f,
- -0.316f, 0.0f, -0.8663f, 0.9688f, 1.0f,
- -0.3004f, 0.0f, -0.8831f, 0.9755f, 1.0f,
- -0.2817f, 0.0f, -0.8996f, 0.9808f, 1.0f,
- -0.2598f, 0.0f, -0.9155f, 0.9858f, 1.0f,
- -0.2344f, 0.0f, -0.9309f, 0.9894f, 1.0f,
- -0.2051f, 0.0f, -0.9457f, 0.993f, 1.0f,
- -0.1716f, 0.0f, -0.9599f, 0.9952f, 1.0f,
- -0.1341f, 0.0f, -0.9733f, 0.9973f, 1.0f,
- -0.0928f, 0.0f, -0.9857f, 0.9987f, 1.0f,
- -0.05f, 0.0f, -0.9962f, 0.9993f, 1.0f,
- -0.0087f, 0.0f, -1.0041f, 1.0f, 1.0f,
- 0.0287f, 0.0f, -1.0087f, 0.9993f, 1.0f,
- 0.062f, 0.0f, -1.0104f, 0.9987f, 1.0f,
- 0.0924f, 0.0f, -1.0102f, 0.9973f, 1.0f,
- 0.1205f, 0.0f, -1.0086f, 0.9952f, 1.0f,
- 0.1465f, 0.0f, -1.0057f, 0.993f, 1.0f,
- 0.1706f, 0.0f, -1.0017f, 0.9894f, 1.0f,
- 0.1928f, 0.0f, -0.9964f, 0.9858f, 1.0f,
- 0.2132f, 0.0f, -0.99f, 0.9808f, 1.0f,
- 0.2318f, 0.0f, -0.9824f, 0.9755f, 1.0f,
- 0.2487f, 0.0f, -0.9738f, 0.9688f, 1.0f,
- 0.2641f, 0.0f, -0.9641f, 0.9617f, 1.0f,
- 0.2778f, 0.0f, -0.9533f, 0.9531f, 1.0f,
- 0.2901f, 0.0f, -0.9415f, 0.944f, 1.0f,
- 0.3009f, 0.0f, -0.9287f, 0.9329f, 1.0f,
- 0.3103f, 0.0f, -0.9148f, 0.9211f, 1.0f,
- 0.3183f, 0.0f, -0.8999f, 0.9074f, 1.0f,
- 0.325f, 0.0f, -0.8841f, 0.8922f, 1.0f,
- 0.3304f, 0.0f, -0.8672f, 0.8756f, 1.0f,
- 0.3345f, 0.0f, -0.8493f, 0.8564f, 1.0f,
- 0.3374f, 0.0f, -0.8305f, 0.8349f, 1.0f,
- 0.3391f, 0.0f, -0.8107f, 0.8109f, 1.0f,
- 0.3397f, 0.0f, -0.7899f, 0.7838f, 1.0f,
- 0.3392f, 0.0f, -0.7682f, 0.753f, 1.0f,
- 0.3377f, 0.0f, -0.7456f, 0.7177f, 1.0f,
- 0.3352f, 0.0f, -0.7221f, 0.6768f, 1.0f,
- 0.3317f, 0.0f, -0.6976f, 0.6291f, 1.0f,
- 0.3273f, 0.0f, -0.6722f, 0.5723f, 1.0f,
- 0.322f, 0.0f, -0.646f, 0.5028f, 1.0f,
- 0.316f, 0.0f, -0.6188f, 0.4147f, 1.0f,
- 0.3091f, 0.0f, -0.5908f, 0.2962f, 1.0f,
- 0.3015f, 0.0f, -0.5619f, 0.1288f, 1.0f,
- 0.2974f, 0.0f, -0.5472f, 0.1f, 1.0f,
+ -0.2854f, 0.0f, -0.4528f, 0.1f, 1.0f, -0.2866f, 0.0f, -0.4623f, 0.1288f, 1.0f,
+ -0.2899f, 0.0f, -0.4814f, 0.2962f, 1.0f, -0.2943f, 0.0f, -0.5008f, 0.4147f, 1.0f,
+ -0.2995f, 0.0f, -0.5203f, 0.5028f, 1.0f, -0.3054f, 0.0f, -0.54f, 0.5723f, 1.0f,
+ -0.3117f, 0.0f, -0.5598f, 0.6291f, 1.0f, -0.3182f, 0.0f, -0.5797f, 0.6768f, 1.0f,
+ -0.3249f, 0.0f, -0.5996f, 0.7177f, 1.0f, -0.3314f, 0.0f, -0.6196f, 0.753f, 1.0f,
+ -0.3376f, 0.0f, -0.6395f, 0.7838f, 1.0f, -0.3432f, 0.0f, -0.6594f, 0.8109f, 1.0f,
+ -0.3482f, 0.0f, -0.6792f, 0.8349f, 1.0f, -0.3523f, 0.0f, -0.6989f, 0.8564f, 1.0f,
+ -0.3552f, 0.0f, -0.7185f, 0.8756f, 1.0f, -0.3569f, 0.0f, -0.7379f, 0.8922f, 1.0f,
+ -0.357f, 0.0f, -0.7571f, 0.9074f, 1.0f, -0.3555f, 0.0f, -0.7761f, 0.9211f, 1.0f,
+ -0.3522f, 0.0f, -0.7948f, 0.9329f, 1.0f, -0.3467f, 0.0f, -0.8132f, 0.944f, 1.0f,
+ -0.339f, 0.0f, -0.8313f, 0.9531f, 1.0f, -0.3289f, 0.0f, -0.849f, 0.9617f, 1.0f,
+ -0.316f, 0.0f, -0.8663f, 0.9688f, 1.0f, -0.3004f, 0.0f, -0.8831f, 0.9755f, 1.0f,
+ -0.2817f, 0.0f, -0.8996f, 0.9808f, 1.0f, -0.2598f, 0.0f, -0.9155f, 0.9858f, 1.0f,
+ -0.2344f, 0.0f, -0.9309f, 0.9894f, 1.0f, -0.2051f, 0.0f, -0.9457f, 0.993f, 1.0f,
+ -0.1716f, 0.0f, -0.9599f, 0.9952f, 1.0f, -0.1341f, 0.0f, -0.9733f, 0.9973f, 1.0f,
+ -0.0928f, 0.0f, -0.9857f, 0.9987f, 1.0f, -0.05f, 0.0f, -0.9962f, 0.9993f, 1.0f,
+ -0.0087f, 0.0f, -1.0041f, 1.0f, 1.0f, 0.0287f, 0.0f, -1.0087f, 0.9993f, 1.0f,
+ 0.062f, 0.0f, -1.0104f, 0.9987f, 1.0f, 0.0924f, 0.0f, -1.0102f, 0.9973f, 1.0f,
+ 0.1205f, 0.0f, -1.0086f, 0.9952f, 1.0f, 0.1465f, 0.0f, -1.0057f, 0.993f, 1.0f,
+ 0.1706f, 0.0f, -1.0017f, 0.9894f, 1.0f, 0.1928f, 0.0f, -0.9964f, 0.9858f, 1.0f,
+ 0.2132f, 0.0f, -0.99f, 0.9808f, 1.0f, 0.2318f, 0.0f, -0.9824f, 0.9755f, 1.0f,
+ 0.2487f, 0.0f, -0.9738f, 0.9688f, 1.0f, 0.2641f, 0.0f, -0.9641f, 0.9617f, 1.0f,
+ 0.2778f, 0.0f, -0.9533f, 0.9531f, 1.0f, 0.2901f, 0.0f, -0.9415f, 0.944f, 1.0f,
+ 0.3009f, 0.0f, -0.9287f, 0.9329f, 1.0f, 0.3103f, 0.0f, -0.9148f, 0.9211f, 1.0f,
+ 0.3183f, 0.0f, -0.8999f, 0.9074f, 1.0f, 0.325f, 0.0f, -0.8841f, 0.8922f, 1.0f,
+ 0.3304f, 0.0f, -0.8672f, 0.8756f, 1.0f, 0.3345f, 0.0f, -0.8493f, 0.8564f, 1.0f,
+ 0.3374f, 0.0f, -0.8305f, 0.8349f, 1.0f, 0.3391f, 0.0f, -0.8107f, 0.8109f, 1.0f,
+ 0.3397f, 0.0f, -0.7899f, 0.7838f, 1.0f, 0.3392f, 0.0f, -0.7682f, 0.753f, 1.0f,
+ 0.3377f, 0.0f, -0.7456f, 0.7177f, 1.0f, 0.3352f, 0.0f, -0.7221f, 0.6768f, 1.0f,
+ 0.3317f, 0.0f, -0.6976f, 0.6291f, 1.0f, 0.3273f, 0.0f, -0.6722f, 0.5723f, 1.0f,
+ 0.322f, 0.0f, -0.646f, 0.5028f, 1.0f, 0.316f, 0.0f, -0.6188f, 0.4147f, 1.0f,
+ 0.3091f, 0.0f, -0.5908f, 0.2962f, 1.0f, 0.3015f, 0.0f, -0.5619f, 0.1288f, 1.0f,
+ 0.2974f, 0.0f, -0.5472f, 0.1f, 1.0f,
};
static const float data16[34 * GP_PRIM_DATABUF_SIZE] = {
- -0.4408f, 0.0f, 0.5073f, 0.1f, 1.0f,
- -0.4312f, 0.0f, 0.5132f, 0.1288f, 1.0f,
- -0.3945f, 0.0f, 0.5319f, 0.4147f, 1.0f,
- -0.3605f, 0.0f, 0.5438f, 0.5723f, 1.0f,
- -0.3288f, 0.0f, 0.5496f, 0.6768f, 1.0f,
- -0.2992f, 0.0f, 0.5501f, 0.753f, 1.0f,
- -0.2712f, 0.0f, 0.546f, 0.8109f, 1.0f,
- -0.2446f, 0.0f, 0.5381f, 0.8564f, 1.0f,
- -0.2191f, 0.0f, 0.5272f, 0.8922f, 1.0f,
- -0.1943f, 0.0f, 0.5139f, 0.9211f, 1.0f,
- -0.1699f, 0.0f, 0.4992f, 0.944f, 1.0f,
- -0.1456f, 0.0f, 0.4837f, 0.9617f, 1.0f,
- -0.1211f, 0.0f, 0.4682f, 0.9755f, 1.0f,
- -0.096f, 0.0f, 0.4535f, 0.9858f, 1.0f,
- -0.07f, 0.0f, 0.4404f, 0.993f, 1.0f,
- -0.0428f, 0.0f, 0.4301f, 0.9973f, 1.0f,
- -0.016f, 0.0f, 0.4235f, 0.9993f, 1.0f,
- 0.0076f, 0.0f, 0.4216f, 0.9993f, 1.0f,
- 0.0283f, 0.0f, 0.4237f, 0.9973f, 1.0f,
- 0.0477f, 0.0f, 0.4291f, 0.993f, 1.0f,
- 0.067f, 0.0f, 0.4369f, 0.9858f, 1.0f,
- 0.0866f, 0.0f, 0.4465f, 0.9755f, 1.0f,
- 0.1068f, 0.0f, 0.4576f, 0.9617f, 1.0f,
- 0.1278f, 0.0f, 0.4695f, 0.944f, 1.0f,
- 0.1498f, 0.0f, 0.4819f, 0.9211f, 1.0f,
- 0.173f, 0.0f, 0.4941f, 0.8922f, 1.0f,
- 0.1977f, 0.0f, 0.5056f, 0.8564f, 1.0f,
- 0.2241f, 0.0f, 0.5159f, 0.8109f, 1.0f,
- 0.2523f, 0.0f, 0.5244f, 0.753f, 1.0f,
- 0.2825f, 0.0f, 0.5307f, 0.6768f, 1.0f,
- 0.315f, 0.0f, 0.5342f, 0.5723f, 1.0f,
- 0.3499f, 0.0f, 0.5345f, 0.4147f, 1.0f,
- 0.3875f, 0.0f, 0.5311f, 0.1288f, 1.0f,
- 0.3973f, 0.0f, 0.5295f, 0.1f, 1.0f,
+ -0.4408f, 0.0f, 0.5073f, 0.1f, 1.0f, -0.4312f, 0.0f, 0.5132f, 0.1288f, 1.0f,
+ -0.3945f, 0.0f, 0.5319f, 0.4147f, 1.0f, -0.3605f, 0.0f, 0.5438f, 0.5723f, 1.0f,
+ -0.3288f, 0.0f, 0.5496f, 0.6768f, 1.0f, -0.2992f, 0.0f, 0.5501f, 0.753f, 1.0f,
+ -0.2712f, 0.0f, 0.546f, 0.8109f, 1.0f, -0.2446f, 0.0f, 0.5381f, 0.8564f, 1.0f,
+ -0.2191f, 0.0f, 0.5272f, 0.8922f, 1.0f, -0.1943f, 0.0f, 0.5139f, 0.9211f, 1.0f,
+ -0.1699f, 0.0f, 0.4992f, 0.944f, 1.0f, -0.1456f, 0.0f, 0.4837f, 0.9617f, 1.0f,
+ -0.1211f, 0.0f, 0.4682f, 0.9755f, 1.0f, -0.096f, 0.0f, 0.4535f, 0.9858f, 1.0f,
+ -0.07f, 0.0f, 0.4404f, 0.993f, 1.0f, -0.0428f, 0.0f, 0.4301f, 0.9973f, 1.0f,
+ -0.016f, 0.0f, 0.4235f, 0.9993f, 1.0f, 0.0076f, 0.0f, 0.4216f, 0.9993f, 1.0f,
+ 0.0283f, 0.0f, 0.4237f, 0.9973f, 1.0f, 0.0477f, 0.0f, 0.4291f, 0.993f, 1.0f,
+ 0.067f, 0.0f, 0.4369f, 0.9858f, 1.0f, 0.0866f, 0.0f, 0.4465f, 0.9755f, 1.0f,
+ 0.1068f, 0.0f, 0.4576f, 0.9617f, 1.0f, 0.1278f, 0.0f, 0.4695f, 0.944f, 1.0f,
+ 0.1498f, 0.0f, 0.4819f, 0.9211f, 1.0f, 0.173f, 0.0f, 0.4941f, 0.8922f, 1.0f,
+ 0.1977f, 0.0f, 0.5056f, 0.8564f, 1.0f, 0.2241f, 0.0f, 0.5159f, 0.8109f, 1.0f,
+ 0.2523f, 0.0f, 0.5244f, 0.753f, 1.0f, 0.2825f, 0.0f, 0.5307f, 0.6768f, 1.0f,
+ 0.315f, 0.0f, 0.5342f, 0.5723f, 1.0f, 0.3499f, 0.0f, 0.5345f, 0.4147f, 1.0f,
+ 0.3875f, 0.0f, 0.5311f, 0.1288f, 1.0f, 0.3973f, 0.0f, 0.5295f, 0.1f, 1.0f,
};
static const float data17[33 * GP_PRIM_DATABUF_SIZE] = {
- 0.724f, 0.0f, 0.1799f, 0.1f, 1.0f,
- 0.7192f, 0.0f, 0.162f, 0.2199f, 1.0f,
- 0.7089f, 0.0f, 0.1283f, 0.4615f, 1.0f,
- 0.6977f, 0.0f, 0.0975f, 0.6019f, 1.0f,
- 0.6858f, 0.0f, 0.0693f, 0.6981f, 1.0f,
- 0.673f, 0.0f, 0.0435f, 0.7689f, 1.0f,
- 0.6595f, 0.0f, 0.02f, 0.8236f, 1.0f,
- 0.6453f, 0.0f, -0.0014f, 0.866f, 1.0f,
- 0.6306f, 0.0f, -0.0208f, 0.9003f, 1.0f,
- 0.6152f, 0.0f, -0.0386f, 0.9272f, 1.0f,
- 0.5994f, 0.0f, -0.0547f, 0.9485f, 1.0f,
- 0.583f, 0.0f, -0.0695f, 0.9653f, 1.0f,
- 0.5663f, 0.0f, -0.083f, 0.9781f, 1.0f,
- 0.5492f, 0.0f, -0.0955f, 0.9876f, 1.0f,
- 0.5317f, 0.0f, -0.1071f, 0.9942f, 1.0f,
- 0.514f, 0.0f, -0.118f, 0.9983f, 1.0f,
- 0.4961f, 0.0f, -0.1284f, 0.9997f, 1.0f,
- 0.4781f, 0.0f, -0.1384f, 0.999f, 1.0f,
- 0.4599f, 0.0f, -0.1483f, 0.9963f, 1.0f,
- 0.4416f, 0.0f, -0.1582f, 0.9912f, 1.0f,
- 0.4234f, 0.0f, -0.1682f, 0.9834f, 1.0f,
- 0.4051f, 0.0f, -0.1787f, 0.9724f, 1.0f,
- 0.387f, 0.0f, -0.1896f, 0.9576f, 1.0f,
- 0.369f, 0.0f, -0.2013f, 0.9385f, 1.0f,
- 0.3512f, 0.0f, -0.2138f, 0.9143f, 1.0f,
- 0.3337f, 0.0f, -0.2274f, 0.8841f, 1.0f,
- 0.3164f, 0.0f, -0.2422f, 0.8461f, 1.0f,
- 0.2995f, 0.0f, -0.2584f, 0.7979f, 1.0f,
- 0.2829f, 0.0f, -0.2762f, 0.7359f, 1.0f,
- 0.2669f, 0.0f, -0.2958f, 0.6541f, 1.0f,
- 0.2513f, 0.0f, -0.3173f, 0.5396f, 1.0f,
- 0.2362f, 0.0f, -0.3409f, 0.36f, 1.0f,
- 0.2218f, 0.0f, -0.3668f, 0.1f, 1.0f,
+ 0.724f, 0.0f, 0.1799f, 0.1f, 1.0f, 0.7192f, 0.0f, 0.162f, 0.2199f, 1.0f,
+ 0.7089f, 0.0f, 0.1283f, 0.4615f, 1.0f, 0.6977f, 0.0f, 0.0975f, 0.6019f, 1.0f,
+ 0.6858f, 0.0f, 0.0693f, 0.6981f, 1.0f, 0.673f, 0.0f, 0.0435f, 0.7689f, 1.0f,
+ 0.6595f, 0.0f, 0.02f, 0.8236f, 1.0f, 0.6453f, 0.0f, -0.0014f, 0.866f, 1.0f,
+ 0.6306f, 0.0f, -0.0208f, 0.9003f, 1.0f, 0.6152f, 0.0f, -0.0386f, 0.9272f, 1.0f,
+ 0.5994f, 0.0f, -0.0547f, 0.9485f, 1.0f, 0.583f, 0.0f, -0.0695f, 0.9653f, 1.0f,
+ 0.5663f, 0.0f, -0.083f, 0.9781f, 1.0f, 0.5492f, 0.0f, -0.0955f, 0.9876f, 1.0f,
+ 0.5317f, 0.0f, -0.1071f, 0.9942f, 1.0f, 0.514f, 0.0f, -0.118f, 0.9983f, 1.0f,
+ 0.4961f, 0.0f, -0.1284f, 0.9997f, 1.0f, 0.4781f, 0.0f, -0.1384f, 0.999f, 1.0f,
+ 0.4599f, 0.0f, -0.1483f, 0.9963f, 1.0f, 0.4416f, 0.0f, -0.1582f, 0.9912f, 1.0f,
+ 0.4234f, 0.0f, -0.1682f, 0.9834f, 1.0f, 0.4051f, 0.0f, -0.1787f, 0.9724f, 1.0f,
+ 0.387f, 0.0f, -0.1896f, 0.9576f, 1.0f, 0.369f, 0.0f, -0.2013f, 0.9385f, 1.0f,
+ 0.3512f, 0.0f, -0.2138f, 0.9143f, 1.0f, 0.3337f, 0.0f, -0.2274f, 0.8841f, 1.0f,
+ 0.3164f, 0.0f, -0.2422f, 0.8461f, 1.0f, 0.2995f, 0.0f, -0.2584f, 0.7979f, 1.0f,
+ 0.2829f, 0.0f, -0.2762f, 0.7359f, 1.0f, 0.2669f, 0.0f, -0.2958f, 0.6541f, 1.0f,
+ 0.2513f, 0.0f, -0.3173f, 0.5396f, 1.0f, 0.2362f, 0.0f, -0.3409f, 0.36f, 1.0f,
+ 0.2218f, 0.0f, -0.3668f, 0.1f, 1.0f,
};
static const float data18[33 * GP_PRIM_DATABUF_SIZE] = {
- -0.1119f, 0.0f, -0.7868f, 0.1f, 1.0f,
- -0.1087f, 0.0f, -0.7905f, 0.2199f, 1.0f,
- -0.1022f, 0.0f, -0.7974f, 0.4615f, 1.0f,
- -0.0955f, 0.0f, -0.8038f, 0.6019f, 1.0f,
- -0.0886f, 0.0f, -0.8097f, 0.6981f, 1.0f,
- -0.0816f, 0.0f, -0.8152f, 0.7689f, 1.0f,
- -0.0744f, 0.0f, -0.8201f, 0.8236f, 1.0f,
- -0.0671f, 0.0f, -0.8246f, 0.866f, 1.0f,
- -0.0597f, 0.0f, -0.8286f, 0.9003f, 1.0f,
- -0.0522f, 0.0f, -0.8321f, 0.9272f, 1.0f,
- -0.0446f, 0.0f, -0.8351f, 0.9485f, 1.0f,
- -0.0369f, 0.0f, -0.8376f, 0.9653f, 1.0f,
- -0.0292f, 0.0f, -0.8397f, 0.9781f, 1.0f,
- -0.0214f, 0.0f, -0.8413f, 0.9876f, 1.0f,
- -0.0136f, 0.0f, -0.8424f, 0.9942f, 1.0f,
- -0.0057f, 0.0f, -0.843f, 0.9983f, 1.0f,
- 0.0022f, 0.0f, -0.8431f, 0.9997f, 1.0f,
- 0.01f, 0.0f, -0.8428f, 0.999f, 1.0f,
- 0.0178f, 0.0f, -0.8419f, 0.9963f, 1.0f,
- 0.0257f, 0.0f, -0.8407f, 0.9912f, 1.0f,
- 0.0334f, 0.0f, -0.8389f, 0.9834f, 1.0f,
- 0.0411f, 0.0f, -0.8366f, 0.9724f, 1.0f,
- 0.0488f, 0.0f, -0.8339f, 0.9576f, 1.0f,
- 0.0564f, 0.0f, -0.8308f, 0.9385f, 1.0f,
- 0.0638f, 0.0f, -0.8271f, 0.9143f, 1.0f,
- 0.0712f, 0.0f, -0.823f, 0.8841f, 1.0f,
- 0.0785f, 0.0f, -0.8184f, 0.8461f, 1.0f,
- 0.0856f, 0.0f, -0.8134f, 0.7979f, 1.0f,
- 0.0925f, 0.0f, -0.8079f, 0.7359f, 1.0f,
- 0.0994f, 0.0f, -0.8019f, 0.6541f, 1.0f,
- 0.106f, 0.0f, -0.7954f, 0.5396f, 1.0f,
- 0.1125f, 0.0f, -0.7885f, 0.36f, 1.0f,
- 0.1187f, 0.0f, -0.7812f, 0.1f, 1.0f,
+ -0.1119f, 0.0f, -0.7868f, 0.1f, 1.0f, -0.1087f, 0.0f, -0.7905f, 0.2199f, 1.0f,
+ -0.1022f, 0.0f, -0.7974f, 0.4615f, 1.0f, -0.0955f, 0.0f, -0.8038f, 0.6019f, 1.0f,
+ -0.0886f, 0.0f, -0.8097f, 0.6981f, 1.0f, -0.0816f, 0.0f, -0.8152f, 0.7689f, 1.0f,
+ -0.0744f, 0.0f, -0.8201f, 0.8236f, 1.0f, -0.0671f, 0.0f, -0.8246f, 0.866f, 1.0f,
+ -0.0597f, 0.0f, -0.8286f, 0.9003f, 1.0f, -0.0522f, 0.0f, -0.8321f, 0.9272f, 1.0f,
+ -0.0446f, 0.0f, -0.8351f, 0.9485f, 1.0f, -0.0369f, 0.0f, -0.8376f, 0.9653f, 1.0f,
+ -0.0292f, 0.0f, -0.8397f, 0.9781f, 1.0f, -0.0214f, 0.0f, -0.8413f, 0.9876f, 1.0f,
+ -0.0136f, 0.0f, -0.8424f, 0.9942f, 1.0f, -0.0057f, 0.0f, -0.843f, 0.9983f, 1.0f,
+ 0.0022f, 0.0f, -0.8431f, 0.9997f, 1.0f, 0.01f, 0.0f, -0.8428f, 0.999f, 1.0f,
+ 0.0178f, 0.0f, -0.8419f, 0.9963f, 1.0f, 0.0257f, 0.0f, -0.8407f, 0.9912f, 1.0f,
+ 0.0334f, 0.0f, -0.8389f, 0.9834f, 1.0f, 0.0411f, 0.0f, -0.8366f, 0.9724f, 1.0f,
+ 0.0488f, 0.0f, -0.8339f, 0.9576f, 1.0f, 0.0564f, 0.0f, -0.8308f, 0.9385f, 1.0f,
+ 0.0638f, 0.0f, -0.8271f, 0.9143f, 1.0f, 0.0712f, 0.0f, -0.823f, 0.8841f, 1.0f,
+ 0.0785f, 0.0f, -0.8184f, 0.8461f, 1.0f, 0.0856f, 0.0f, -0.8134f, 0.7979f, 1.0f,
+ 0.0925f, 0.0f, -0.8079f, 0.7359f, 1.0f, 0.0994f, 0.0f, -0.8019f, 0.6541f, 1.0f,
+ 0.106f, 0.0f, -0.7954f, 0.5396f, 1.0f, 0.1125f, 0.0f, -0.7885f, 0.36f, 1.0f,
+ 0.1187f, 0.0f, -0.7812f, 0.1f, 1.0f,
};
static const float data19[34 * GP_PRIM_DATABUF_SIZE] = {
- -0.1119f, 0.0f, -0.2655f, 0.1f, 1.0f,
- -0.1101f, 0.0f, -0.2605f, 0.1288f, 1.0f,
- -0.1032f, 0.0f, -0.2424f, 0.4147f, 1.0f,
- -0.0965f, 0.0f, -0.2276f, 0.5723f, 1.0f,
- -0.0901f, 0.0f, -0.2158f, 0.6768f, 1.0f,
- -0.0837f, 0.0f, -0.2069f, 0.753f, 1.0f,
- -0.0775f, 0.0f, -0.2006f, 0.8109f, 1.0f,
- -0.0712f, 0.0f, -0.1967f, 0.8564f, 1.0f,
- -0.065f, 0.0f, -0.1949f, 0.8922f, 1.0f,
- -0.0587f, 0.0f, -0.195f, 0.9211f, 1.0f,
- -0.0522f, 0.0f, -0.1968f, 0.944f, 1.0f,
- -0.0455f, 0.0f, -0.2001f, 0.9617f, 1.0f,
- -0.0386f, 0.0f, -0.2046f, 0.9755f, 1.0f,
- -0.0315f, 0.0f, -0.21f, 0.9858f, 1.0f,
- -0.0239f, 0.0f, -0.2163f, 0.993f, 1.0f,
- -0.016f, 0.0f, -0.223f, 0.9973f, 1.0f,
- -0.0075f, 0.0f, -0.2301f, 0.9993f, 1.0f,
- -0.0002f, 0.0f, -0.2342f, 0.9993f, 1.0f,
- 0.0054f, 0.0f, -0.234f, 0.9973f, 1.0f,
- 0.0106f, 0.0f, -0.2324f, 0.993f, 1.0f,
- 0.0155f, 0.0f, -0.2297f, 0.9858f, 1.0f,
- 0.0202f, 0.0f, -0.2261f, 0.9755f, 1.0f,
- 0.0249f, 0.0f, -0.2219f, 0.9617f, 1.0f,
- 0.0296f, 0.0f, -0.2174f, 0.944f, 1.0f,
- 0.0344f, 0.0f, -0.2128f, 0.9211f, 1.0f,
- 0.0394f, 0.0f, -0.2084f, 0.8922f, 1.0f,
- 0.0448f, 0.0f, -0.2044f, 0.8564f, 1.0f,
- 0.0506f, 0.0f, -0.2012f, 0.8109f, 1.0f,
- 0.057f, 0.0f, -0.1988f, 0.753f, 1.0f,
- 0.064f, 0.0f, -0.1977f, 0.6768f, 1.0f,
- 0.0717f, 0.0f, -0.198f, 0.5723f, 1.0f,
- 0.0804f, 0.0f, -0.2001f, 0.4147f, 1.0f,
- 0.0899f, 0.0f, -0.2042f, 0.1288f, 1.0f,
- 0.0925f, 0.0f, -0.2055f, 0.1f, 1.0f,
+ -0.1119f, 0.0f, -0.2655f, 0.1f, 1.0f, -0.1101f, 0.0f, -0.2605f, 0.1288f, 1.0f,
+ -0.1032f, 0.0f, -0.2424f, 0.4147f, 1.0f, -0.0965f, 0.0f, -0.2276f, 0.5723f, 1.0f,
+ -0.0901f, 0.0f, -0.2158f, 0.6768f, 1.0f, -0.0837f, 0.0f, -0.2069f, 0.753f, 1.0f,
+ -0.0775f, 0.0f, -0.2006f, 0.8109f, 1.0f, -0.0712f, 0.0f, -0.1967f, 0.8564f, 1.0f,
+ -0.065f, 0.0f, -0.1949f, 0.8922f, 1.0f, -0.0587f, 0.0f, -0.195f, 0.9211f, 1.0f,
+ -0.0522f, 0.0f, -0.1968f, 0.944f, 1.0f, -0.0455f, 0.0f, -0.2001f, 0.9617f, 1.0f,
+ -0.0386f, 0.0f, -0.2046f, 0.9755f, 1.0f, -0.0315f, 0.0f, -0.21f, 0.9858f, 1.0f,
+ -0.0239f, 0.0f, -0.2163f, 0.993f, 1.0f, -0.016f, 0.0f, -0.223f, 0.9973f, 1.0f,
+ -0.0075f, 0.0f, -0.2301f, 0.9993f, 1.0f, -0.0002f, 0.0f, -0.2342f, 0.9993f, 1.0f,
+ 0.0054f, 0.0f, -0.234f, 0.9973f, 1.0f, 0.0106f, 0.0f, -0.2324f, 0.993f, 1.0f,
+ 0.0155f, 0.0f, -0.2297f, 0.9858f, 1.0f, 0.0202f, 0.0f, -0.2261f, 0.9755f, 1.0f,
+ 0.0249f, 0.0f, -0.2219f, 0.9617f, 1.0f, 0.0296f, 0.0f, -0.2174f, 0.944f, 1.0f,
+ 0.0344f, 0.0f, -0.2128f, 0.9211f, 1.0f, 0.0394f, 0.0f, -0.2084f, 0.8922f, 1.0f,
+ 0.0448f, 0.0f, -0.2044f, 0.8564f, 1.0f, 0.0506f, 0.0f, -0.2012f, 0.8109f, 1.0f,
+ 0.057f, 0.0f, -0.1988f, 0.753f, 1.0f, 0.064f, 0.0f, -0.1977f, 0.6768f, 1.0f,
+ 0.0717f, 0.0f, -0.198f, 0.5723f, 1.0f, 0.0804f, 0.0f, -0.2001f, 0.4147f, 1.0f,
+ 0.0899f, 0.0f, -0.2042f, 0.1288f, 1.0f, 0.0925f, 0.0f, -0.2055f, 0.1f, 1.0f,
};
static const float data20[33 * GP_PRIM_DATABUF_SIZE] = {
- 0.7993f, 0.0f, 0.3242f, 0.1f, 1.0f,
- 0.8169f, 0.0f, 0.3354f, 0.2199f, 1.0f,
- 0.8512f, 0.0f, 0.3542f, 0.4615f, 1.0f,
- 0.884f, 0.0f, 0.3686f, 0.6019f, 1.0f,
- 0.9153f, 0.0f, 0.3787f, 0.6981f, 1.0f,
- 0.945f, 0.0f, 0.3848f, 0.7689f, 1.0f,
- 0.9729f, 0.0f, 0.3871f, 0.8236f, 1.0f,
- 0.9989f, 0.0f, 0.3857f, 0.866f, 1.0f,
- 1.0229f, 0.0f, 0.3811f, 0.9003f, 1.0f,
- 1.0447f, 0.0f, 0.3732f, 0.9272f, 1.0f,
- 1.0643f, 0.0f, 0.3624f, 0.9485f, 1.0f,
- 1.0814f, 0.0f, 0.349f, 0.9653f, 1.0f,
- 1.096f, 0.0f, 0.333f, 0.9781f, 1.0f,
- 1.108f, 0.0f, 0.3147f, 0.9876f, 1.0f,
- 1.1172f, 0.0f, 0.2944f, 0.9942f, 1.0f,
- 1.1235f, 0.0f, 0.2723f, 0.9983f, 1.0f,
- 1.1267f, 0.0f, 0.2485f, 0.9997f, 1.0f,
- 1.1269f, 0.0f, 0.2233f, 0.999f, 1.0f,
- 1.1237f, 0.0f, 0.197f, 0.9963f, 1.0f,
- 1.1172f, 0.0f, 0.1697f, 0.9912f, 1.0f,
- 1.1071f, 0.0f, 0.1417f, 0.9834f, 1.0f,
- 1.0934f, 0.0f, 0.1131f, 0.9724f, 1.0f,
- 1.0759f, 0.0f, 0.0842f, 0.9576f, 1.0f,
- 1.0545f, 0.0f, 0.0553f, 0.9385f, 1.0f,
- 1.0291f, 0.0f, 0.0265f, 0.9143f, 1.0f,
- 0.9995f, 0.0f, -0.0019f, 0.8841f, 1.0f,
- 0.9657f, 0.0f, -0.0298f, 0.8461f, 1.0f,
- 0.9275f, 0.0f, -0.0569f, 0.7979f, 1.0f,
- 0.8847f, 0.0f, -0.0829f, 0.7359f, 1.0f,
- 0.8373f, 0.0f, -0.1077f, 0.6541f, 1.0f,
- 0.7852f, 0.0f, -0.1311f, 0.5396f, 1.0f,
- 0.7281f, 0.0f, -0.1528f, 0.36f, 1.0f,
- 0.6661f, 0.0f, -0.1725f, 0.1f, 1.0f,
+ 0.7993f, 0.0f, 0.3242f, 0.1f, 1.0f, 0.8169f, 0.0f, 0.3354f, 0.2199f, 1.0f,
+ 0.8512f, 0.0f, 0.3542f, 0.4615f, 1.0f, 0.884f, 0.0f, 0.3686f, 0.6019f, 1.0f,
+ 0.9153f, 0.0f, 0.3787f, 0.6981f, 1.0f, 0.945f, 0.0f, 0.3848f, 0.7689f, 1.0f,
+ 0.9729f, 0.0f, 0.3871f, 0.8236f, 1.0f, 0.9989f, 0.0f, 0.3857f, 0.866f, 1.0f,
+ 1.0229f, 0.0f, 0.3811f, 0.9003f, 1.0f, 1.0447f, 0.0f, 0.3732f, 0.9272f, 1.0f,
+ 1.0643f, 0.0f, 0.3624f, 0.9485f, 1.0f, 1.0814f, 0.0f, 0.349f, 0.9653f, 1.0f,
+ 1.096f, 0.0f, 0.333f, 0.9781f, 1.0f, 1.108f, 0.0f, 0.3147f, 0.9876f, 1.0f,
+ 1.1172f, 0.0f, 0.2944f, 0.9942f, 1.0f, 1.1235f, 0.0f, 0.2723f, 0.9983f, 1.0f,
+ 1.1267f, 0.0f, 0.2485f, 0.9997f, 1.0f, 1.1269f, 0.0f, 0.2233f, 0.999f, 1.0f,
+ 1.1237f, 0.0f, 0.197f, 0.9963f, 1.0f, 1.1172f, 0.0f, 0.1697f, 0.9912f, 1.0f,
+ 1.1071f, 0.0f, 0.1417f, 0.9834f, 1.0f, 1.0934f, 0.0f, 0.1131f, 0.9724f, 1.0f,
+ 1.0759f, 0.0f, 0.0842f, 0.9576f, 1.0f, 1.0545f, 0.0f, 0.0553f, 0.9385f, 1.0f,
+ 1.0291f, 0.0f, 0.0265f, 0.9143f, 1.0f, 0.9995f, 0.0f, -0.0019f, 0.8841f, 1.0f,
+ 0.9657f, 0.0f, -0.0298f, 0.8461f, 1.0f, 0.9275f, 0.0f, -0.0569f, 0.7979f, 1.0f,
+ 0.8847f, 0.0f, -0.0829f, 0.7359f, 1.0f, 0.8373f, 0.0f, -0.1077f, 0.6541f, 1.0f,
+ 0.7852f, 0.0f, -0.1311f, 0.5396f, 1.0f, 0.7281f, 0.0f, -0.1528f, 0.36f, 1.0f,
+ 0.6661f, 0.0f, -0.1725f, 0.1f, 1.0f,
};
static const float data21[64 * GP_PRIM_DATABUF_SIZE] = {
- -0.7428f, 0.0f, 0.2977f, 0.1f, 1.0f,
- -0.7608f, 0.0f, 0.3138f, 0.2199f, 1.0f,
- -0.7786f, 0.0f, 0.3284f, 0.36f, 1.0f,
- -0.7962f, 0.0f, 0.3414f, 0.4615f, 1.0f,
- -0.8135f, 0.0f, 0.3531f, 0.5396f, 1.0f,
- -0.8306f, 0.0f, 0.3633f, 0.6019f, 1.0f,
- -0.8473f, 0.0f, 0.3722f, 0.6541f, 1.0f,
- -0.8637f, 0.0f, 0.3798f, 0.6981f, 1.0f,
- -0.8798f, 0.0f, 0.386f, 0.7359f, 1.0f,
- -0.8956f, 0.0f, 0.3911f, 0.7689f, 1.0f,
- -0.9109f, 0.0f, 0.3949f, 0.7979f, 1.0f,
- -0.9259f, 0.0f, 0.3975f, 0.8236f, 1.0f,
- -0.9405f, 0.0f, 0.3989f, 0.8461f, 1.0f,
- -0.9546f, 0.0f, 0.3993f, 0.866f, 1.0f,
- -0.9682f, 0.0f, 0.3986f, 0.8841f, 1.0f,
- -0.9814f, 0.0f, 0.3969f, 0.9003f, 1.0f,
- -0.994f, 0.0f, 0.3941f, 0.9143f, 1.0f,
- -1.0062f, 0.0f, 0.3904f, 0.9272f, 1.0f,
- -1.0178f, 0.0f, 0.3858f, 0.9385f, 1.0f,
- -1.0288f, 0.0f, 0.3803f, 0.9485f, 1.0f,
- -1.0393f, 0.0f, 0.3739f, 0.9576f, 1.0f,
- -1.0492f, 0.0f, 0.3668f, 0.9653f, 1.0f,
- -1.0584f, 0.0f, 0.3588f, 0.9724f, 1.0f,
- -1.067f, 0.0f, 0.3501f, 0.9781f, 1.0f,
- -1.075f, 0.0f, 0.3407f, 0.9834f, 1.0f,
- -1.0822f, 0.0f, 0.3307f, 0.9876f, 1.0f,
- -1.0888f, 0.0f, 0.32f, 0.9912f, 1.0f,
- -1.0946f, 0.0f, 0.3087f, 0.9942f, 1.0f,
- -1.0997f, 0.0f, 0.2969f, 0.9963f, 1.0f,
- -1.104f, 0.0f, 0.2845f, 0.9983f, 1.0f,
- -1.1075f, 0.0f, 0.2717f, 0.999f, 1.0f,
- -1.1103f, 0.0f, 0.2584f, 0.9997f, 1.0f,
- -1.1122f, 0.0f, 0.2447f, 0.9997f, 1.0f,
- -1.1132f, 0.0f, 0.2306f, 0.999f, 1.0f,
- -1.1134f, 0.0f, 0.2162f, 0.9983f, 1.0f,
- -1.1128f, 0.0f, 0.2015f, 0.9963f, 1.0f,
- -1.1112f, 0.0f, 0.1865f, 0.9942f, 1.0f,
- -1.1086f, 0.0f, 0.1713f, 0.9912f, 1.0f,
- -1.1052f, 0.0f, 0.1559f, 0.9876f, 1.0f,
- -1.1007f, 0.0f, 0.1404f, 0.9834f, 1.0f,
- -1.0953f, 0.0f, 0.1247f, 0.9781f, 1.0f,
- -1.0889f, 0.0f, 0.109f, 0.9724f, 1.0f,
- -1.0814f, 0.0f, 0.0932f, 0.9653f, 1.0f,
- -1.0729f, 0.0f, 0.0774f, 0.9576f, 1.0f,
- -1.0633f, 0.0f, 0.0617f, 0.9485f, 1.0f,
- -1.0527f, 0.0f, 0.046f, 0.9385f, 1.0f,
- -1.0409f, 0.0f, 0.0304f, 0.9272f, 1.0f,
- -1.028f, 0.0f, 0.015f, 0.9143f, 1.0f,
- -1.0139f, 0.0f, -0.0003f, 0.9003f, 1.0f,
- -0.9987f, 0.0f, -0.0154f, 0.8841f, 1.0f,
- -0.9823f, 0.0f, -0.0302f, 0.866f, 1.0f,
- -0.9646f, 0.0f, -0.0447f, 0.8461f, 1.0f,
- -0.9458f, 0.0f, -0.0589f, 0.8236f, 1.0f,
- -0.9257f, 0.0f, -0.0727f, 0.7979f, 1.0f,
- -0.9043f, 0.0f, -0.0862f, 0.7689f, 1.0f,
- -0.8816f, 0.0f, -0.0992f, 0.7359f, 1.0f,
- -0.8576f, 0.0f, -0.1117f, 0.6981f, 1.0f,
- -0.8323f, 0.0f, -0.1237f, 0.6541f, 1.0f,
- -0.8056f, 0.0f, -0.1352f, 0.6019f, 1.0f,
- -0.7775f, 0.0f, -0.1461f, 0.5396f, 1.0f,
- -0.7481f, 0.0f, -0.1564f, 0.4615f, 1.0f,
- -0.7172f, 0.0f, -0.166f, 0.36f, 1.0f,
- -0.6849f, 0.0f, -0.175f, 0.2199f, 1.0f,
- -0.6512f, 0.0f, -0.1832f, 0.1f, 1.0f,
+ -0.7428f, 0.0f, 0.2977f, 0.1f, 1.0f, -0.7608f, 0.0f, 0.3138f, 0.2199f, 1.0f,
+ -0.7786f, 0.0f, 0.3284f, 0.36f, 1.0f, -0.7962f, 0.0f, 0.3414f, 0.4615f, 1.0f,
+ -0.8135f, 0.0f, 0.3531f, 0.5396f, 1.0f, -0.8306f, 0.0f, 0.3633f, 0.6019f, 1.0f,
+ -0.8473f, 0.0f, 0.3722f, 0.6541f, 1.0f, -0.8637f, 0.0f, 0.3798f, 0.6981f, 1.0f,
+ -0.8798f, 0.0f, 0.386f, 0.7359f, 1.0f, -0.8956f, 0.0f, 0.3911f, 0.7689f, 1.0f,
+ -0.9109f, 0.0f, 0.3949f, 0.7979f, 1.0f, -0.9259f, 0.0f, 0.3975f, 0.8236f, 1.0f,
+ -0.9405f, 0.0f, 0.3989f, 0.8461f, 1.0f, -0.9546f, 0.0f, 0.3993f, 0.866f, 1.0f,
+ -0.9682f, 0.0f, 0.3986f, 0.8841f, 1.0f, -0.9814f, 0.0f, 0.3969f, 0.9003f, 1.0f,
+ -0.994f, 0.0f, 0.3941f, 0.9143f, 1.0f, -1.0062f, 0.0f, 0.3904f, 0.9272f, 1.0f,
+ -1.0178f, 0.0f, 0.3858f, 0.9385f, 1.0f, -1.0288f, 0.0f, 0.3803f, 0.9485f, 1.0f,
+ -1.0393f, 0.0f, 0.3739f, 0.9576f, 1.0f, -1.0492f, 0.0f, 0.3668f, 0.9653f, 1.0f,
+ -1.0584f, 0.0f, 0.3588f, 0.9724f, 1.0f, -1.067f, 0.0f, 0.3501f, 0.9781f, 1.0f,
+ -1.075f, 0.0f, 0.3407f, 0.9834f, 1.0f, -1.0822f, 0.0f, 0.3307f, 0.9876f, 1.0f,
+ -1.0888f, 0.0f, 0.32f, 0.9912f, 1.0f, -1.0946f, 0.0f, 0.3087f, 0.9942f, 1.0f,
+ -1.0997f, 0.0f, 0.2969f, 0.9963f, 1.0f, -1.104f, 0.0f, 0.2845f, 0.9983f, 1.0f,
+ -1.1075f, 0.0f, 0.2717f, 0.999f, 1.0f, -1.1103f, 0.0f, 0.2584f, 0.9997f, 1.0f,
+ -1.1122f, 0.0f, 0.2447f, 0.9997f, 1.0f, -1.1132f, 0.0f, 0.2306f, 0.999f, 1.0f,
+ -1.1134f, 0.0f, 0.2162f, 0.9983f, 1.0f, -1.1128f, 0.0f, 0.2015f, 0.9963f, 1.0f,
+ -1.1112f, 0.0f, 0.1865f, 0.9942f, 1.0f, -1.1086f, 0.0f, 0.1713f, 0.9912f, 1.0f,
+ -1.1052f, 0.0f, 0.1559f, 0.9876f, 1.0f, -1.1007f, 0.0f, 0.1404f, 0.9834f, 1.0f,
+ -1.0953f, 0.0f, 0.1247f, 0.9781f, 1.0f, -1.0889f, 0.0f, 0.109f, 0.9724f, 1.0f,
+ -1.0814f, 0.0f, 0.0932f, 0.9653f, 1.0f, -1.0729f, 0.0f, 0.0774f, 0.9576f, 1.0f,
+ -1.0633f, 0.0f, 0.0617f, 0.9485f, 1.0f, -1.0527f, 0.0f, 0.046f, 0.9385f, 1.0f,
+ -1.0409f, 0.0f, 0.0304f, 0.9272f, 1.0f, -1.028f, 0.0f, 0.015f, 0.9143f, 1.0f,
+ -1.0139f, 0.0f, -0.0003f, 0.9003f, 1.0f, -0.9987f, 0.0f, -0.0154f, 0.8841f, 1.0f,
+ -0.9823f, 0.0f, -0.0302f, 0.866f, 1.0f, -0.9646f, 0.0f, -0.0447f, 0.8461f, 1.0f,
+ -0.9458f, 0.0f, -0.0589f, 0.8236f, 1.0f, -0.9257f, 0.0f, -0.0727f, 0.7979f, 1.0f,
+ -0.9043f, 0.0f, -0.0862f, 0.7689f, 1.0f, -0.8816f, 0.0f, -0.0992f, 0.7359f, 1.0f,
+ -0.8576f, 0.0f, -0.1117f, 0.6981f, 1.0f, -0.8323f, 0.0f, -0.1237f, 0.6541f, 1.0f,
+ -0.8056f, 0.0f, -0.1352f, 0.6019f, 1.0f, -0.7775f, 0.0f, -0.1461f, 0.5396f, 1.0f,
+ -0.7481f, 0.0f, -0.1564f, 0.4615f, 1.0f, -0.7172f, 0.0f, -0.166f, 0.36f, 1.0f,
+ -0.6849f, 0.0f, -0.175f, 0.2199f, 1.0f, -0.6512f, 0.0f, -0.1832f, 0.1f, 1.0f,
};
static const float data22[26 * GP_PRIM_DATABUF_SIZE] = {
- 0.2721f, 0.0f, 0.2084f, 1.0f, 1.0f,
- 0.2721f, 0.0f, 0.2112f, 1.0f, 1.0f,
- 0.2739f, 0.0f, 0.2223f, 1.0f, 1.0f,
- 0.2778f, 0.0f, 0.2324f, 1.0f, 1.0f,
- 0.2836f, 0.0f, 0.2409f, 1.0f, 1.0f,
- 0.291f, 0.0f, 0.2471f, 1.0f, 1.0f,
- 0.2994f, 0.0f, 0.2507f, 1.0f, 1.0f,
- 0.3082f, 0.0f, 0.2515f, 1.0f, 1.0f,
- 0.3169f, 0.0f, 0.2493f, 1.0f, 1.0f,
- 0.3248f, 0.0f, 0.2443f, 1.0f, 1.0f,
- 0.3315f, 0.0f, 0.2369f, 1.0f, 1.0f,
- 0.3364f, 0.0f, 0.2275f, 1.0f, 1.0f,
- 0.3392f, 0.0f, 0.2168f, 1.0f, 1.0f,
- 0.3398f, 0.0f, 0.2056f, 1.0f, 1.0f,
- 0.3381f, 0.0f, 0.1945f, 1.0f, 1.0f,
- 0.3342f, 0.0f, 0.1844f, 1.0f, 1.0f,
- 0.3283f, 0.0f, 0.176f, 1.0f, 1.0f,
- 0.321f, 0.0f, 0.1697f, 1.0f, 1.0f,
- 0.3126f, 0.0f, 0.1661f, 1.0f, 1.0f,
- 0.3038f, 0.0f, 0.1653f, 1.0f, 1.0f,
- 0.2951f, 0.0f, 0.1675f, 1.0f, 1.0f,
- 0.2871f, 0.0f, 0.1725f, 1.0f, 1.0f,
- 0.2805f, 0.0f, 0.1799f, 1.0f, 1.0f,
- 0.2756f, 0.0f, 0.1893f, 1.0f, 1.0f,
- 0.2727f, 0.0f, 0.2f, 1.0f, 1.0f,
- 0.2721f, 0.0f, 0.2056f, 1.0f, 1.0f,
+ 0.2721f, 0.0f, 0.2084f, 1.0f, 1.0f, 0.2721f, 0.0f, 0.2112f, 1.0f, 1.0f,
+ 0.2739f, 0.0f, 0.2223f, 1.0f, 1.0f, 0.2778f, 0.0f, 0.2324f, 1.0f, 1.0f,
+ 0.2836f, 0.0f, 0.2409f, 1.0f, 1.0f, 0.291f, 0.0f, 0.2471f, 1.0f, 1.0f,
+ 0.2994f, 0.0f, 0.2507f, 1.0f, 1.0f, 0.3082f, 0.0f, 0.2515f, 1.0f, 1.0f,
+ 0.3169f, 0.0f, 0.2493f, 1.0f, 1.0f, 0.3248f, 0.0f, 0.2443f, 1.0f, 1.0f,
+ 0.3315f, 0.0f, 0.2369f, 1.0f, 1.0f, 0.3364f, 0.0f, 0.2275f, 1.0f, 1.0f,
+ 0.3392f, 0.0f, 0.2168f, 1.0f, 1.0f, 0.3398f, 0.0f, 0.2056f, 1.0f, 1.0f,
+ 0.3381f, 0.0f, 0.1945f, 1.0f, 1.0f, 0.3342f, 0.0f, 0.1844f, 1.0f, 1.0f,
+ 0.3283f, 0.0f, 0.176f, 1.0f, 1.0f, 0.321f, 0.0f, 0.1697f, 1.0f, 1.0f,
+ 0.3126f, 0.0f, 0.1661f, 1.0f, 1.0f, 0.3038f, 0.0f, 0.1653f, 1.0f, 1.0f,
+ 0.2951f, 0.0f, 0.1675f, 1.0f, 1.0f, 0.2871f, 0.0f, 0.1725f, 1.0f, 1.0f,
+ 0.2805f, 0.0f, 0.1799f, 1.0f, 1.0f, 0.2756f, 0.0f, 0.1893f, 1.0f, 1.0f,
+ 0.2727f, 0.0f, 0.2f, 1.0f, 1.0f, 0.2721f, 0.0f, 0.2056f, 1.0f, 1.0f,
};
static const float data23[26 * GP_PRIM_DATABUF_SIZE] = {
- -0.3545f, 0.0f, 0.2084f, 1.0f, 1.0f,
- -0.3544f, 0.0f, 0.2112f, 1.0f, 1.0f,
- -0.3527f, 0.0f, 0.2223f, 1.0f, 1.0f,
- -0.3488f, 0.0f, 0.2324f, 1.0f, 1.0f,
- -0.343f, 0.0f, 0.2409f, 1.0f, 1.0f,
- -0.3356f, 0.0f, 0.2471f, 1.0f, 1.0f,
- -0.3272f, 0.0f, 0.2507f, 1.0f, 1.0f,
- -0.3184f, 0.0f, 0.2515f, 1.0f, 1.0f,
- -0.3097f, 0.0f, 0.2493f, 1.0f, 1.0f,
- -0.3018f, 0.0f, 0.2443f, 1.0f, 1.0f,
- -0.2951f, 0.0f, 0.2369f, 1.0f, 1.0f,
- -0.2902f, 0.0f, 0.2275f, 1.0f, 1.0f,
- -0.2874f, 0.0f, 0.2168f, 1.0f, 1.0f,
- -0.2868f, 0.0f, 0.2056f, 1.0f, 1.0f,
- -0.2885f, 0.0f, 0.1945f, 1.0f, 1.0f,
- -0.2924f, 0.0f, 0.1844f, 1.0f, 1.0f,
- -0.2983f, 0.0f, 0.176f, 1.0f, 1.0f,
- -0.3056f, 0.0f, 0.1697f, 1.0f, 1.0f,
- -0.314f, 0.0f, 0.1661f, 1.0f, 1.0f,
- -0.3228f, 0.0f, 0.1653f, 1.0f, 1.0f,
- -0.3315f, 0.0f, 0.1675f, 1.0f, 1.0f,
- -0.3394f, 0.0f, 0.1725f, 1.0f, 1.0f,
- -0.3461f, 0.0f, 0.1799f, 1.0f, 1.0f,
- -0.351f, 0.0f, 0.1893f, 1.0f, 1.0f,
- -0.3539f, 0.0f, 0.2f, 1.0f, 1.0f,
- -0.3544f, 0.0f, 0.2056f, 1.0f, 1.0f,
+ -0.3545f, 0.0f, 0.2084f, 1.0f, 1.0f, -0.3544f, 0.0f, 0.2112f, 1.0f, 1.0f,
+ -0.3527f, 0.0f, 0.2223f, 1.0f, 1.0f, -0.3488f, 0.0f, 0.2324f, 1.0f, 1.0f,
+ -0.343f, 0.0f, 0.2409f, 1.0f, 1.0f, -0.3356f, 0.0f, 0.2471f, 1.0f, 1.0f,
+ -0.3272f, 0.0f, 0.2507f, 1.0f, 1.0f, -0.3184f, 0.0f, 0.2515f, 1.0f, 1.0f,
+ -0.3097f, 0.0f, 0.2493f, 1.0f, 1.0f, -0.3018f, 0.0f, 0.2443f, 1.0f, 1.0f,
+ -0.2951f, 0.0f, 0.2369f, 1.0f, 1.0f, -0.2902f, 0.0f, 0.2275f, 1.0f, 1.0f,
+ -0.2874f, 0.0f, 0.2168f, 1.0f, 1.0f, -0.2868f, 0.0f, 0.2056f, 1.0f, 1.0f,
+ -0.2885f, 0.0f, 0.1945f, 1.0f, 1.0f, -0.2924f, 0.0f, 0.1844f, 1.0f, 1.0f,
+ -0.2983f, 0.0f, 0.176f, 1.0f, 1.0f, -0.3056f, 0.0f, 0.1697f, 1.0f, 1.0f,
+ -0.314f, 0.0f, 0.1661f, 1.0f, 1.0f, -0.3228f, 0.0f, 0.1653f, 1.0f, 1.0f,
+ -0.3315f, 0.0f, 0.1675f, 1.0f, 1.0f, -0.3394f, 0.0f, 0.1725f, 1.0f, 1.0f,
+ -0.3461f, 0.0f, 0.1799f, 1.0f, 1.0f, -0.351f, 0.0f, 0.1893f, 1.0f, 1.0f,
+ -0.3539f, 0.0f, 0.2f, 1.0f, 1.0f, -0.3544f, 0.0f, 0.2056f, 1.0f, 1.0f,
};
static const float data24[33 * GP_PRIM_DATABUF_SIZE] = {
- 0.1904f, 0.0f, 0.0983f, 0.1f, 1.0f,
- 0.1997f, 0.0f, 0.0774f, 0.2199f, 1.0f,
- 0.2234f, 0.0f, 0.0407f, 0.4615f, 1.0f,
- 0.2477f, 0.0f, 0.0158f, 0.6019f, 1.0f,
- 0.2767f, 0.0f, -0.0047f, 0.6981f, 1.0f,
- 0.3061f, 0.0f, -0.0179f, 0.7689f, 1.0f,
- 0.3346f, 0.0f, -0.0247f, 0.8236f, 1.0f,
- 0.362f, 0.0f, -0.0262f, 0.866f, 1.0f,
- 0.3881f, 0.0f, -0.0231f, 0.9003f, 1.0f,
- 0.4128f, 0.0f, -0.0159f, 0.9272f, 1.0f,
- 0.436f, 0.0f, -0.0049f, 0.9485f, 1.0f,
- 0.4577f, 0.0f, 0.0099f, 0.9653f, 1.0f,
- 0.4778f, 0.0f, 0.0289f, 0.9781f, 1.0f,
- 0.4959f, 0.0f, 0.0524f, 0.9876f, 1.0f,
- 0.5114f, 0.0f, 0.0806f, 0.9942f, 1.0f,
- 0.5229f, 0.0f, 0.1134f, 0.9983f, 1.0f,
- 0.5291f, 0.0f, 0.1498f, 0.9997f, 1.0f,
- 0.5289f, 0.0f, 0.1884f, 0.999f, 1.0f,
- 0.5219f, 0.0f, 0.2267f, 0.9963f, 1.0f,
- 0.5087f, 0.0f, 0.2616f, 0.9912f, 1.0f,
- 0.4907f, 0.0f, 0.2916f, 0.9834f, 1.0f,
- 0.4697f, 0.0f, 0.3159f, 0.9724f, 1.0f,
- 0.4465f, 0.0f, 0.3349f, 0.9576f, 1.0f,
- 0.422f, 0.0f, 0.3489f, 0.9385f, 1.0f,
- 0.3964f, 0.0f, 0.3582f, 0.9143f, 1.0f,
- 0.3705f, 0.0f, 0.3628f, 0.8841f, 1.0f,
- 0.3436f, 0.0f, 0.363f, 0.8461f, 1.0f,
- 0.3166f, 0.0f, 0.3586f, 0.7979f, 1.0f,
- 0.2897f, 0.0f, 0.3491f, 0.7359f, 1.0f,
- 0.2635f, 0.0f, 0.3344f, 0.6541f, 1.0f,
- 0.2382f, 0.0f, 0.3137f, 0.5396f, 1.0f,
- 0.2162f, 0.0f, 0.2882f, 0.36f, 1.0f,
- 0.1949f, 0.0f, 0.2516f, 0.1f, 1.0f,
+ 0.1904f, 0.0f, 0.0983f, 0.1f, 1.0f, 0.1997f, 0.0f, 0.0774f, 0.2199f, 1.0f,
+ 0.2234f, 0.0f, 0.0407f, 0.4615f, 1.0f, 0.2477f, 0.0f, 0.0158f, 0.6019f, 1.0f,
+ 0.2767f, 0.0f, -0.0047f, 0.6981f, 1.0f, 0.3061f, 0.0f, -0.0179f, 0.7689f, 1.0f,
+ 0.3346f, 0.0f, -0.0247f, 0.8236f, 1.0f, 0.362f, 0.0f, -0.0262f, 0.866f, 1.0f,
+ 0.3881f, 0.0f, -0.0231f, 0.9003f, 1.0f, 0.4128f, 0.0f, -0.0159f, 0.9272f, 1.0f,
+ 0.436f, 0.0f, -0.0049f, 0.9485f, 1.0f, 0.4577f, 0.0f, 0.0099f, 0.9653f, 1.0f,
+ 0.4778f, 0.0f, 0.0289f, 0.9781f, 1.0f, 0.4959f, 0.0f, 0.0524f, 0.9876f, 1.0f,
+ 0.5114f, 0.0f, 0.0806f, 0.9942f, 1.0f, 0.5229f, 0.0f, 0.1134f, 0.9983f, 1.0f,
+ 0.5291f, 0.0f, 0.1498f, 0.9997f, 1.0f, 0.5289f, 0.0f, 0.1884f, 0.999f, 1.0f,
+ 0.5219f, 0.0f, 0.2267f, 0.9963f, 1.0f, 0.5087f, 0.0f, 0.2616f, 0.9912f, 1.0f,
+ 0.4907f, 0.0f, 0.2916f, 0.9834f, 1.0f, 0.4697f, 0.0f, 0.3159f, 0.9724f, 1.0f,
+ 0.4465f, 0.0f, 0.3349f, 0.9576f, 1.0f, 0.422f, 0.0f, 0.3489f, 0.9385f, 1.0f,
+ 0.3964f, 0.0f, 0.3582f, 0.9143f, 1.0f, 0.3705f, 0.0f, 0.3628f, 0.8841f, 1.0f,
+ 0.3436f, 0.0f, 0.363f, 0.8461f, 1.0f, 0.3166f, 0.0f, 0.3586f, 0.7979f, 1.0f,
+ 0.2897f, 0.0f, 0.3491f, 0.7359f, 1.0f, 0.2635f, 0.0f, 0.3344f, 0.6541f, 1.0f,
+ 0.2382f, 0.0f, 0.3137f, 0.5396f, 1.0f, 0.2162f, 0.0f, 0.2882f, 0.36f, 1.0f,
+ 0.1949f, 0.0f, 0.2516f, 0.1f, 1.0f,
};
static const float data25[18 * GP_PRIM_DATABUF_SIZE] = {
- -1.0361f, 0.0f, 0.1745f, 0.1f, 1.0f,
- -1.0319f, 0.0f, 0.177f, 0.2199f, 1.0f,
- -1.0153f, 0.0f, 0.1852f, 0.6019f, 1.0f,
- -0.999f, 0.0f, 0.1907f, 0.7689f, 1.0f,
- -0.983f, 0.0f, 0.1936f, 0.866f, 1.0f,
- -0.9673f, 0.0f, 0.1941f, 0.9272f, 1.0f,
- -0.9522f, 0.0f, 0.1923f, 0.9653f, 1.0f,
- -0.9376f, 0.0f, 0.1885f, 0.9876f, 1.0f,
- -0.9236f, 0.0f, 0.1827f, 0.9983f, 1.0f,
- -0.9103f, 0.0f, 0.1752f, 0.999f, 1.0f,
- -0.8978f, 0.0f, 0.1662f, 0.9912f, 1.0f,
- -0.8862f, 0.0f, 0.1558f, 0.9724f, 1.0f,
- -0.8756f, 0.0f, 0.1441f, 0.9385f, 1.0f,
- -0.866f, 0.0f, 0.1314f, 0.8841f, 1.0f,
- -0.8575f, 0.0f, 0.1179f, 0.7979f, 1.0f,
- -0.8501f, 0.0f, 0.1036f, 0.6541f, 1.0f,
- -0.8441f, 0.0f, 0.0889f, 0.36f, 1.0f,
- -0.8416f, 0.0f, 0.0813f, 0.1f, 1.0f,
+ -1.0361f, 0.0f, 0.1745f, 0.1f, 1.0f, -1.0319f, 0.0f, 0.177f, 0.2199f, 1.0f,
+ -1.0153f, 0.0f, 0.1852f, 0.6019f, 1.0f, -0.999f, 0.0f, 0.1907f, 0.7689f, 1.0f,
+ -0.983f, 0.0f, 0.1936f, 0.866f, 1.0f, -0.9673f, 0.0f, 0.1941f, 0.9272f, 1.0f,
+ -0.9522f, 0.0f, 0.1923f, 0.9653f, 1.0f, -0.9376f, 0.0f, 0.1885f, 0.9876f, 1.0f,
+ -0.9236f, 0.0f, 0.1827f, 0.9983f, 1.0f, -0.9103f, 0.0f, 0.1752f, 0.999f, 1.0f,
+ -0.8978f, 0.0f, 0.1662f, 0.9912f, 1.0f, -0.8862f, 0.0f, 0.1558f, 0.9724f, 1.0f,
+ -0.8756f, 0.0f, 0.1441f, 0.9385f, 1.0f, -0.866f, 0.0f, 0.1314f, 0.8841f, 1.0f,
+ -0.8575f, 0.0f, 0.1179f, 0.7979f, 1.0f, -0.8501f, 0.0f, 0.1036f, 0.6541f, 1.0f,
+ -0.8441f, 0.0f, 0.0889f, 0.36f, 1.0f, -0.8416f, 0.0f, 0.0813f, 0.1f, 1.0f,
};
static const float data26[18 * GP_PRIM_DATABUF_SIZE] = {
- 0.9747f, 0.0f, 0.1745f, 0.1f, 1.0f,
- 0.9706f, 0.0f, 0.177f, 0.2199f, 1.0f,
- 0.954f, 0.0f, 0.1852f, 0.6019f, 1.0f,
- 0.9377f, 0.0f, 0.1907f, 0.7689f, 1.0f,
- 0.9216f, 0.0f, 0.1936f, 0.866f, 1.0f,
- 0.906f, 0.0f, 0.1941f, 0.9272f, 1.0f,
- 0.8908f, 0.0f, 0.1923f, 0.9653f, 1.0f,
- 0.8762f, 0.0f, 0.1885f, 0.9876f, 1.0f,
- 0.8622f, 0.0f, 0.1827f, 0.9983f, 1.0f,
- 0.849f, 0.0f, 0.1752f, 0.999f, 1.0f,
- 0.8365f, 0.0f, 0.1662f, 0.9912f, 1.0f,
- 0.8249f, 0.0f, 0.1558f, 0.9724f, 1.0f,
- 0.8143f, 0.0f, 0.1441f, 0.9385f, 1.0f,
- 0.8046f, 0.0f, 0.1314f, 0.8841f, 1.0f,
- 0.7961f, 0.0f, 0.1179f, 0.7979f, 1.0f,
- 0.7888f, 0.0f, 0.1036f, 0.6541f, 1.0f,
- 0.7828f, 0.0f, 0.0889f, 0.36f, 1.0f,
- 0.7802f, 0.0f, 0.0813f, 0.1f, 1.0f,
+ 0.9747f, 0.0f, 0.1745f, 0.1f, 1.0f, 0.9706f, 0.0f, 0.177f, 0.2199f, 1.0f,
+ 0.954f, 0.0f, 0.1852f, 0.6019f, 1.0f, 0.9377f, 0.0f, 0.1907f, 0.7689f, 1.0f,
+ 0.9216f, 0.0f, 0.1936f, 0.866f, 1.0f, 0.906f, 0.0f, 0.1941f, 0.9272f, 1.0f,
+ 0.8908f, 0.0f, 0.1923f, 0.9653f, 1.0f, 0.8762f, 0.0f, 0.1885f, 0.9876f, 1.0f,
+ 0.8622f, 0.0f, 0.1827f, 0.9983f, 1.0f, 0.849f, 0.0f, 0.1752f, 0.999f, 1.0f,
+ 0.8365f, 0.0f, 0.1662f, 0.9912f, 1.0f, 0.8249f, 0.0f, 0.1558f, 0.9724f, 1.0f,
+ 0.8143f, 0.0f, 0.1441f, 0.9385f, 1.0f, 0.8046f, 0.0f, 0.1314f, 0.8841f, 1.0f,
+ 0.7961f, 0.0f, 0.1179f, 0.7979f, 1.0f, 0.7888f, 0.0f, 0.1036f, 0.6541f, 1.0f,
+ 0.7828f, 0.0f, 0.0889f, 0.36f, 1.0f, 0.7802f, 0.0f, 0.0813f, 0.1f, 1.0f,
};
static const float data27[33 * GP_PRIM_DATABUF_SIZE] = {
- -0.186f, 0.0f, 0.0983f, 0.1f, 1.0f,
- -0.1954f, 0.0f, 0.0774f, 0.2199f, 1.0f,
- -0.2191f, 0.0f, 0.0407f, 0.4615f, 1.0f,
- -0.2434f, 0.0f, 0.0158f, 0.6019f, 1.0f,
- -0.2723f, 0.0f, -0.0047f, 0.6981f, 1.0f,
- -0.3017f, 0.0f, -0.0179f, 0.7689f, 1.0f,
- -0.3302f, 0.0f, -0.0247f, 0.8236f, 1.0f,
- -0.3576f, 0.0f, -0.0262f, 0.866f, 1.0f,
- -0.3837f, 0.0f, -0.0231f, 0.9003f, 1.0f,
- -0.4085f, 0.0f, -0.0159f, 0.9272f, 1.0f,
- -0.4317f, 0.0f, -0.0049f, 0.9485f, 1.0f,
- -0.4533f, 0.0f, 0.0099f, 0.9653f, 1.0f,
- -0.4734f, 0.0f, 0.0289f, 0.9781f, 1.0f,
- -0.4916f, 0.0f, 0.0524f, 0.9876f, 1.0f,
- -0.507f, 0.0f, 0.0806f, 0.9942f, 1.0f,
- -0.5185f, 0.0f, 0.1134f, 0.9983f, 1.0f,
- -0.5247f, 0.0f, 0.1498f, 0.9997f, 1.0f,
- -0.5246f, 0.0f, 0.1884f, 0.999f, 1.0f,
- -0.5175f, 0.0f, 0.2267f, 0.9963f, 1.0f,
- -0.5043f, 0.0f, 0.2616f, 0.9912f, 1.0f,
- -0.4864f, 0.0f, 0.2916f, 0.9834f, 1.0f,
- -0.4653f, 0.0f, 0.3159f, 0.9724f, 1.0f,
- -0.4422f, 0.0f, 0.3349f, 0.9576f, 1.0f,
- -0.4177f, 0.0f, 0.3489f, 0.9385f, 1.0f,
- -0.3921f, 0.0f, 0.3582f, 0.9143f, 1.0f,
- -0.3661f, 0.0f, 0.3628f, 0.8841f, 1.0f,
- -0.3392f, 0.0f, 0.363f, 0.8461f, 1.0f,
- -0.3123f, 0.0f, 0.3586f, 0.7979f, 1.0f,
- -0.2853f, 0.0f, 0.3491f, 0.7359f, 1.0f,
- -0.2591f, 0.0f, 0.3344f, 0.6541f, 1.0f,
- -0.2339f, 0.0f, 0.3137f, 0.5396f, 1.0f,
- -0.2118f, 0.0f, 0.2882f, 0.36f, 1.0f,
- -0.1906f, 0.0f, 0.2516f, 0.1f, 1.0f,
+ -0.186f, 0.0f, 0.0983f, 0.1f, 1.0f, -0.1954f, 0.0f, 0.0774f, 0.2199f, 1.0f,
+ -0.2191f, 0.0f, 0.0407f, 0.4615f, 1.0f, -0.2434f, 0.0f, 0.0158f, 0.6019f, 1.0f,
+ -0.2723f, 0.0f, -0.0047f, 0.6981f, 1.0f, -0.3017f, 0.0f, -0.0179f, 0.7689f, 1.0f,
+ -0.3302f, 0.0f, -0.0247f, 0.8236f, 1.0f, -0.3576f, 0.0f, -0.0262f, 0.866f, 1.0f,
+ -0.3837f, 0.0f, -0.0231f, 0.9003f, 1.0f, -0.4085f, 0.0f, -0.0159f, 0.9272f, 1.0f,
+ -0.4317f, 0.0f, -0.0049f, 0.9485f, 1.0f, -0.4533f, 0.0f, 0.0099f, 0.9653f, 1.0f,
+ -0.4734f, 0.0f, 0.0289f, 0.9781f, 1.0f, -0.4916f, 0.0f, 0.0524f, 0.9876f, 1.0f,
+ -0.507f, 0.0f, 0.0806f, 0.9942f, 1.0f, -0.5185f, 0.0f, 0.1134f, 0.9983f, 1.0f,
+ -0.5247f, 0.0f, 0.1498f, 0.9997f, 1.0f, -0.5246f, 0.0f, 0.1884f, 0.999f, 1.0f,
+ -0.5175f, 0.0f, 0.2267f, 0.9963f, 1.0f, -0.5043f, 0.0f, 0.2616f, 0.9912f, 1.0f,
+ -0.4864f, 0.0f, 0.2916f, 0.9834f, 1.0f, -0.4653f, 0.0f, 0.3159f, 0.9724f, 1.0f,
+ -0.4422f, 0.0f, 0.3349f, 0.9576f, 1.0f, -0.4177f, 0.0f, 0.3489f, 0.9385f, 1.0f,
+ -0.3921f, 0.0f, 0.3582f, 0.9143f, 1.0f, -0.3661f, 0.0f, 0.3628f, 0.8841f, 1.0f,
+ -0.3392f, 0.0f, 0.363f, 0.8461f, 1.0f, -0.3123f, 0.0f, 0.3586f, 0.7979f, 1.0f,
+ -0.2853f, 0.0f, 0.3491f, 0.7359f, 1.0f, -0.2591f, 0.0f, 0.3344f, 0.6541f, 1.0f,
+ -0.2339f, 0.0f, 0.3137f, 0.5396f, 1.0f, -0.2118f, 0.0f, 0.2882f, 0.36f, 1.0f,
+ -0.1906f, 0.0f, 0.2516f, 0.1f, 1.0f,
};
-
/* ***************************************************************** */
/* Monkey Color Data */
static const ColorTemplate gp_monkey_pct_black = {
- "Black",
- {0.0f, 0.0f, 0.0f, 1.0f},
- {0.0f, 0.0f, 0.0f, 0.0f},
+ "Black",
+ {0.0f, 0.0f, 0.0f, 1.0f},
+ {0.0f, 0.0f, 0.0f, 0.0f},
};
static const ColorTemplate gp_monkey_pct_skin = {
- "Skin",
- {0.733f, 0.569f, 0.361f, 1.0f},
- {0.745f, 0.502f, 0.278f, 1.0f},
+ "Skin",
+ {0.733f, 0.569f, 0.361f, 1.0f},
+ {0.745f, 0.502f, 0.278f, 1.0f},
};
static const ColorTemplate gp_monkey_pct_skin_light = {
- "Skin_Light",
- {0.914f, 0.827f, 0.635f, 1.0f},
- {0.913f, 0.828f, 0.637f, 0.0f},
+ "Skin_Light",
+ {0.914f, 0.827f, 0.635f, 1.0f},
+ {0.913f, 0.828f, 0.637f, 0.0f},
};
static const ColorTemplate gp_monkey_pct_skin_shadow = {
- "Skin_Shadow",
- {0.322f, 0.29f, 0.224f, 0.5f},
- {0.32f, 0.29f, 0.223f, 0.3f},
+ "Skin_Shadow",
+ {0.322f, 0.29f, 0.224f, 0.5f},
+ {0.32f, 0.29f, 0.223f, 0.3f},
};
static const ColorTemplate gp_monkey_pct_eyes = {
- "Eyes",
- {0.553f, 0.39f, 0.266f, 0.0f},
- {0.847f, 0.723f, 0.599f, 1.0f},
+ "Eyes",
+ {0.553f, 0.39f, 0.266f, 0.0f},
+ {0.847f, 0.723f, 0.599f, 1.0f},
};
static const ColorTemplate gp_monkey_pct_pupils = {
- "Pupils",
- {0.0f, 0.0f, 0.0f, 0.0f},
- {0.0f, 0.0f, 0.0f, 1.0f},
+ "Pupils",
+ {0.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 0.0f, 1.0f},
};
/* ***************************************************************** */
@@ -1430,122 +828,121 @@ static const ColorTemplate gp_monkey_pct_pupils = {
/* add a 2D Suzanne (original model created by Matias Mendiola) */
void ED_gpencil_create_monkey(bContext *C, Object *ob, float mat[4][4])
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
- bGPdata *gpd = (bGPdata *)ob->data;
- bGPDstroke *gps;
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bGPDstroke *gps;
- /* create colors */
- int color_Black = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_black, true, false);
- int color_Skin = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_skin, false, true);
- int color_Skin_Light = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_skin_light, true, false);
- int color_Skin_Shadow = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_skin_shadow, true, false);
- int color_Eyes = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_eyes, false, true);
- int color_Pupils = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_pupils, false, true);
+ /* create colors */
+ int color_Black = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_black, true, false);
+ int color_Skin = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_skin, false, true);
+ int color_Skin_Light = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_skin_light, true, false);
+ int color_Skin_Shadow = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_skin_shadow, true, false);
+ int color_Eyes = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_eyes, false, true);
+ int color_Pupils = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_pupils, false, true);
- /* set first color as active */
- ob->actcol = color_Black + 1;
+ /* set first color as active */
+ ob->actcol = color_Black + 1;
- /* layers */
- /* NOTE: For now, we just add new layers, to make it easier to separate out old/new instances */
- bGPDlayer *Fills = BKE_gpencil_layer_addnew(gpd, "Fills", false);
- bGPDlayer *Lines = BKE_gpencil_layer_addnew(gpd, "Lines", true);
+ /* layers */
+ /* NOTE: For now, we just add new layers, to make it easier to separate out old/new instances */
+ bGPDlayer *Fills = BKE_gpencil_layer_addnew(gpd, "Fills", false);
+ bGPDlayer *Lines = BKE_gpencil_layer_addnew(gpd, "Lines", true);
- /* frames */
- /* NOTE: No need to check for existing, as this will take care of it for us */
- bGPDframe *frameFills = BKE_gpencil_frame_addnew(Fills, cfra_eval);
- bGPDframe *frameLines = BKE_gpencil_frame_addnew(Lines, cfra_eval);
+ /* frames */
+ /* NOTE: No need to check for existing, as this will take care of it for us */
+ bGPDframe *frameFills = BKE_gpencil_frame_addnew(Fills, cfra_eval);
+ bGPDframe *frameLines = BKE_gpencil_frame_addnew(Lines, cfra_eval);
- /* generate strokes */
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin, 270, 75);
- BKE_gpencil_stroke_add_points(gps, data0, 270, mat);
+ /* generate strokes */
+ gps = BKE_gpencil_add_stroke(frameFills, color_Skin, 270, 75);
+ BKE_gpencil_stroke_add_points(gps, data0, 270, mat);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 33, 60);
- BKE_gpencil_stroke_add_points(gps, data1, 33, mat);
+ gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 33, 60);
+ BKE_gpencil_stroke_add_points(gps, data1, 33, mat);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 18, 60);
- BKE_gpencil_stroke_add_points(gps, data2, 18, mat);
+ gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 18, 60);
+ BKE_gpencil_stroke_add_points(gps, data2, 18, mat);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 64, 60);
- BKE_gpencil_stroke_add_points(gps, data3, 64, mat);
+ gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 64, 60);
+ BKE_gpencil_stroke_add_points(gps, data3, 64, mat);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 33, 60);
- BKE_gpencil_stroke_add_points(gps, data4, 33, mat);
+ gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 33, 60);
+ BKE_gpencil_stroke_add_points(gps, data4, 33, mat);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 64, 60);
- BKE_gpencil_stroke_add_points(gps, data5, 64, mat);
+ gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 64, 60);
+ BKE_gpencil_stroke_add_points(gps, data5, 64, mat);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 33, 60);
- BKE_gpencil_stroke_add_points(gps, data6, 33, mat);
+ gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 33, 60);
+ BKE_gpencil_stroke_add_points(gps, data6, 33, mat);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 18, 40);
- BKE_gpencil_stroke_add_points(gps, data7, 18, mat);
+ gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 18, 40);
+ BKE_gpencil_stroke_add_points(gps, data7, 18, mat);
- gps = BKE_gpencil_add_stroke(frameFills, color_Eyes, 49, 60);
- BKE_gpencil_stroke_add_points(gps, data8, 49, mat);
+ gps = BKE_gpencil_add_stroke(frameFills, color_Eyes, 49, 60);
+ BKE_gpencil_stroke_add_points(gps, data8, 49, mat);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 33, 60);
- BKE_gpencil_stroke_add_points(gps, data9, 33, mat);
+ gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 33, 60);
+ BKE_gpencil_stroke_add_points(gps, data9, 33, mat);
- gps = BKE_gpencil_add_stroke(frameFills, color_Eyes, 49, 60);
- BKE_gpencil_stroke_add_points(gps, data10, 49, mat);
+ gps = BKE_gpencil_add_stroke(frameFills, color_Eyes, 49, 60);
+ BKE_gpencil_stroke_add_points(gps, data10, 49, mat);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 18, 40);
- BKE_gpencil_stroke_add_points(gps, data11, 18, mat);
+ gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 18, 40);
+ BKE_gpencil_stroke_add_points(gps, data11, 18, mat);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 18, 40);
- BKE_gpencil_stroke_add_points(gps, data12, 18, mat);
+ gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 18, 40);
+ BKE_gpencil_stroke_add_points(gps, data12, 18, mat);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
- BKE_gpencil_stroke_add_points(gps, data13, 33, mat);
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
+ BKE_gpencil_stroke_add_points(gps, data13, 33, mat);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
- BKE_gpencil_stroke_add_points(gps, data14, 33, mat);
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
+ BKE_gpencil_stroke_add_points(gps, data14, 33, mat);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 65, 60);
- BKE_gpencil_stroke_add_points(gps, data15, 65, mat);
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 65, 60);
+ BKE_gpencil_stroke_add_points(gps, data15, 65, mat);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 34, 60);
- BKE_gpencil_stroke_add_points(gps, data16, 34, mat);
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 34, 60);
+ BKE_gpencil_stroke_add_points(gps, data16, 34, mat);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
- BKE_gpencil_stroke_add_points(gps, data17, 33, mat);
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
+ BKE_gpencil_stroke_add_points(gps, data17, 33, mat);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 40);
- BKE_gpencil_stroke_add_points(gps, data18, 33, mat);
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 40);
+ BKE_gpencil_stroke_add_points(gps, data18, 33, mat);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 34, 40);
- BKE_gpencil_stroke_add_points(gps, data19, 34, mat);
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 34, 40);
+ BKE_gpencil_stroke_add_points(gps, data19, 34, mat);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
- BKE_gpencil_stroke_add_points(gps, data20, 33, mat);
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
+ BKE_gpencil_stroke_add_points(gps, data20, 33, mat);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 64, 60);
- BKE_gpencil_stroke_add_points(gps, data21, 64, mat);
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 64, 60);
+ BKE_gpencil_stroke_add_points(gps, data21, 64, mat);
- gps = BKE_gpencil_add_stroke(frameLines, color_Pupils, 26, 60);
- BKE_gpencil_stroke_add_points(gps, data22, 26, mat);
+ gps = BKE_gpencil_add_stroke(frameLines, color_Pupils, 26, 60);
+ BKE_gpencil_stroke_add_points(gps, data22, 26, mat);
- gps = BKE_gpencil_add_stroke(frameLines, color_Pupils, 26, 60);
- BKE_gpencil_stroke_add_points(gps, data23, 26, mat);
+ gps = BKE_gpencil_add_stroke(frameLines, color_Pupils, 26, 60);
+ BKE_gpencil_stroke_add_points(gps, data23, 26, mat);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
- BKE_gpencil_stroke_add_points(gps, data24, 33, mat);
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
+ BKE_gpencil_stroke_add_points(gps, data24, 33, mat);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 18, 40);
- BKE_gpencil_stroke_add_points(gps, data25, 18, mat);
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 18, 40);
+ BKE_gpencil_stroke_add_points(gps, data25, 18, mat);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 18, 40);
- BKE_gpencil_stroke_add_points(gps, data26, 18, mat);
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 18, 40);
+ BKE_gpencil_stroke_add_points(gps, data26, 18, mat);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
- BKE_gpencil_stroke_add_points(gps, data27, 33, mat);
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
+ BKE_gpencil_stroke_add_points(gps, data27, 33, mat);
- /* update depsgraph */
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+ /* update depsgraph */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
}
-
/* ***************************************************************** */
diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c
index 1107819a09a..d6e068926dd 100644
--- a/source/blender/editors/gpencil/gpencil_add_stroke.c
+++ b/source/blender/editors/gpencil/gpencil_add_stroke.c
@@ -42,170 +42,169 @@
/* Definition of the most important info from a color */
typedef struct ColorTemplate {
- const char *name;
- float line[4];
- float fill[4];
+ const char *name;
+ float line[4];
+ float fill[4];
} ColorTemplate;
/* Add color an ensure duplications (matched by name) */
-static int gp_stroke_material(
- Main *bmain, Object *ob, const ColorTemplate *pct, const bool fill)
+static int gp_stroke_material(Main *bmain, Object *ob, const ColorTemplate *pct, const bool fill)
{
- short *totcol = give_totcolp(ob);
- Material *ma = NULL;
- for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
- if (STREQ(ma->id.name, pct->name)) {
- return i;
- }
- }
+ short *totcol = give_totcolp(ob);
+ Material *ma = NULL;
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ if (STREQ(ma->id.name, pct->name)) {
+ return i;
+ }
+ }
- int idx;
+ int idx;
- /* create a new one */
- ma = BKE_gpencil_object_material_new(bmain, ob, pct->name, &idx);
+ /* create a new one */
+ ma = BKE_gpencil_object_material_new(bmain, ob, pct->name, &idx);
- copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
- copy_v4_v4(ma->gp_style->fill_rgba, pct->fill);
+ copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
+ copy_v4_v4(ma->gp_style->fill_rgba, pct->fill);
- if (fill) {
- ma->gp_style->flag |= GP_STYLE_FILL_SHOW;
- }
+ if (fill) {
+ ma->gp_style->flag |= GP_STYLE_FILL_SHOW;
+ }
- return idx;
+ return idx;
}
/* ***************************************************************** */
/* Stroke Geometry */
static const float data0[175 * GP_PRIM_DATABUF_SIZE] = {
- -1.281f, 0.0f, -0.315f, 0.038f, 1.0f, -1.269f, 0.0f, -0.302f, 0.069f, 1.0f,
- -1.261f, 0.0f, -0.293f, 0.089f, 1.0f, -1.251f, 0.0f, -0.282f, 0.112f, 1.0f,
- -1.241f, 0.0f, -0.271f, 0.134f, 1.0f, -1.23f, 0.0f, -0.259f, 0.155f, 1.0f,
- -1.219f, 0.0f, -0.247f, 0.175f, 1.0f, -1.208f, 0.0f, -0.234f, 0.194f, 1.0f,
- -1.196f, 0.0f, -0.221f, 0.211f, 1.0f, -1.184f, 0.0f, -0.208f, 0.227f, 1.0f,
- -1.172f, 0.0f, -0.194f, 0.242f, 1.0f, -1.159f, 0.0f, -0.18f, 0.256f, 1.0f,
- -1.147f, 0.0f, -0.165f, 0.268f, 1.0f, -1.134f, 0.0f, -0.151f, 0.28f, 1.0f,
- -1.121f, 0.0f, -0.136f, 0.29f, 1.0f, -1.108f, 0.0f, -0.121f, 0.299f, 1.0f,
- -1.094f, 0.0f, -0.106f, 0.307f, 1.0f, -1.08f, 0.0f, -0.091f, 0.315f, 1.0f,
- -1.066f, 0.0f, -0.076f, 0.322f, 1.0f, -1.052f, 0.0f, -0.061f, 0.329f, 1.0f,
- -1.037f, 0.0f, -0.047f, 0.335f, 1.0f, -1.022f, 0.0f, -0.032f, 0.341f, 1.0f,
- -1.007f, 0.0f, -0.017f, 0.346f, 1.0f, -0.991f, 0.0f, -0.003f, 0.351f, 1.0f,
- -0.975f, 0.0f, 0.012f, 0.355f, 1.0f, -0.959f, 0.0f, 0.027f, 0.36f, 1.0f,
- -0.942f, 0.0f, 0.041f, 0.364f, 1.0f, -0.926f, 0.0f, 0.056f, 0.368f, 1.0f,
- -0.909f, 0.0f, 0.071f, 0.371f, 1.0f, -0.893f, 0.0f, 0.086f, 0.373f, 1.0f,
- -0.876f, 0.0f, 0.1f, 0.376f, 1.0f, -0.859f, 0.0f, 0.115f, 0.377f, 1.0f,
- -0.842f, 0.0f, 0.129f, 0.378f, 1.0f, -0.824f, 0.0f, 0.144f, 0.379f, 1.0f,
- -0.807f, 0.0f, 0.158f, 0.379f, 1.0f, -0.79f, 0.0f, 0.172f, 0.379f, 1.0f,
- -0.773f, 0.0f, 0.186f, 0.38f, 1.0f, -0.755f, 0.0f, 0.199f, 0.38f, 1.0f,
- -0.738f, 0.0f, 0.212f, 0.381f, 1.0f, -0.721f, 0.0f, 0.224f, 0.382f, 1.0f,
- -0.703f, 0.0f, 0.236f, 0.384f, 1.0f, -0.686f, 0.0f, 0.248f, 0.386f, 1.0f,
- -0.67f, 0.0f, 0.26f, 0.388f, 1.0f, -0.653f, 0.0f, 0.27f, 0.39f, 1.0f,
- -0.637f, 0.0f, 0.28f, 0.393f, 1.0f, -0.621f, 0.0f, 0.29f, 0.396f, 1.0f,
- -0.605f, 0.0f, 0.298f, 0.399f, 1.0f, -0.589f, 0.0f, 0.306f, 0.403f, 1.0f,
- -0.574f, 0.0f, 0.313f, 0.407f, 1.0f, -0.559f, 0.0f, 0.319f, 0.411f, 1.0f,
- -0.544f, 0.0f, 0.325f, 0.415f, 1.0f, -0.53f, 0.0f, 0.331f, 0.42f, 1.0f,
- -0.516f, 0.0f, 0.336f, 0.425f, 1.0f, -0.503f, 0.0f, 0.34f, 0.431f, 1.0f,
- -0.489f, 0.0f, 0.344f, 0.437f, 1.0f, -0.477f, 0.0f, 0.347f, 0.443f, 1.0f,
- -0.464f, 0.0f, 0.35f, 0.45f, 1.0f, -0.452f, 0.0f, 0.352f, 0.457f, 1.0f,
- -0.44f, 0.0f, 0.354f, 0.464f, 1.0f, -0.429f, 0.0f, 0.355f, 0.471f, 1.0f,
- -0.418f, 0.0f, 0.355f, 0.479f, 1.0f, -0.407f, 0.0f, 0.355f, 0.487f, 1.0f,
- -0.397f, 0.0f, 0.354f, 0.495f, 1.0f, -0.387f, 0.0f, 0.353f, 0.503f, 1.0f,
- -0.378f, 0.0f, 0.351f, 0.512f, 1.0f, -0.368f, 0.0f, 0.348f, 0.52f, 1.0f,
- -0.36f, 0.0f, 0.344f, 0.528f, 1.0f, -0.351f, 0.0f, 0.34f, 0.537f, 1.0f,
- -0.344f, 0.0f, 0.336f, 0.545f, 1.0f, -0.336f, 0.0f, 0.33f, 0.553f, 1.0f,
- -0.329f, 0.0f, 0.324f, 0.562f, 1.0f, -0.322f, 0.0f, 0.318f, 0.57f, 1.0f,
- -0.316f, 0.0f, 0.31f, 0.579f, 1.0f, -0.311f, 0.0f, 0.303f, 0.588f, 1.0f,
- -0.306f, 0.0f, 0.294f, 0.597f, 1.0f, -0.301f, 0.0f, 0.285f, 0.606f, 1.0f,
- -0.297f, 0.0f, 0.275f, 0.615f, 1.0f, -0.293f, 0.0f, 0.264f, 0.625f, 1.0f,
- -0.29f, 0.0f, 0.253f, 0.635f, 1.0f, -0.288f, 0.0f, 0.241f, 0.644f, 1.0f,
- -0.286f, 0.0f, 0.229f, 0.654f, 1.0f, -0.285f, 0.0f, 0.216f, 0.664f, 1.0f,
- -0.284f, 0.0f, 0.202f, 0.675f, 1.0f, -0.283f, 0.0f, 0.188f, 0.685f, 1.0f,
- -0.283f, 0.0f, 0.173f, 0.696f, 1.0f, -0.284f, 0.0f, 0.158f, 0.707f, 1.0f,
- -0.285f, 0.0f, 0.142f, 0.718f, 1.0f, -0.286f, 0.0f, 0.125f, 0.729f, 1.0f,
- -0.288f, 0.0f, 0.108f, 0.74f, 1.0f, -0.29f, 0.0f, 0.091f, 0.751f, 1.0f,
- -0.293f, 0.0f, 0.073f, 0.761f, 1.0f, -0.295f, 0.0f, 0.054f, 0.772f, 1.0f,
- -0.298f, 0.0f, 0.035f, 0.782f, 1.0f, -0.302f, 0.0f, 0.016f, 0.793f, 1.0f,
- -0.305f, 0.0f, -0.004f, 0.804f, 1.0f, -0.309f, 0.0f, -0.024f, 0.815f, 1.0f,
- -0.313f, 0.0f, -0.044f, 0.828f, 1.0f, -0.317f, 0.0f, -0.065f, 0.843f, 1.0f,
- -0.321f, 0.0f, -0.085f, 0.86f, 1.0f, -0.326f, 0.0f, -0.106f, 0.879f, 1.0f,
- -0.33f, 0.0f, -0.127f, 0.897f, 1.0f, -0.335f, 0.0f, -0.148f, 0.915f, 1.0f,
- -0.339f, 0.0f, -0.168f, 0.932f, 1.0f, -0.344f, 0.0f, -0.189f, 0.947f, 1.0f,
- -0.348f, 0.0f, -0.21f, 0.962f, 1.0f, -0.353f, 0.0f, -0.23f, 0.974f, 1.0f,
- -0.357f, 0.0f, -0.25f, 0.985f, 1.0f, -0.361f, 0.0f, -0.27f, 0.995f, 1.0f,
- -0.365f, 0.0f, -0.29f, 1.004f, 1.0f, -0.369f, 0.0f, -0.309f, 1.011f, 1.0f,
- -0.372f, 0.0f, -0.328f, 1.018f, 1.0f, -0.375f, 0.0f, -0.347f, 1.024f, 1.0f,
- -0.377f, 0.0f, -0.365f, 1.029f, 1.0f, -0.379f, 0.0f, -0.383f, 1.033f, 1.0f,
- -0.38f, 0.0f, -0.4f, 1.036f, 1.0f, -0.38f, 0.0f, -0.417f, 1.037f, 1.0f,
- -0.38f, 0.0f, -0.434f, 1.037f, 1.0f, -0.379f, 0.0f, -0.449f, 1.035f, 1.0f,
- -0.377f, 0.0f, -0.464f, 1.032f, 1.0f, -0.374f, 0.0f, -0.478f, 1.029f, 1.0f,
- -0.371f, 0.0f, -0.491f, 1.026f, 1.0f, -0.366f, 0.0f, -0.503f, 1.023f, 1.0f,
- -0.361f, 0.0f, -0.513f, 1.021f, 1.0f, -0.354f, 0.0f, -0.523f, 1.019f, 1.0f,
- -0.347f, 0.0f, -0.531f, 1.017f, 1.0f, -0.339f, 0.0f, -0.538f, 1.016f, 1.0f,
- -0.33f, 0.0f, -0.543f, 1.016f, 1.0f, -0.32f, 0.0f, -0.547f, 1.016f, 1.0f,
- -0.31f, 0.0f, -0.549f, 1.016f, 1.0f, -0.298f, 0.0f, -0.55f, 1.017f, 1.0f,
- -0.286f, 0.0f, -0.55f, 1.017f, 1.0f, -0.274f, 0.0f, -0.548f, 1.018f, 1.0f,
- -0.261f, 0.0f, -0.544f, 1.017f, 1.0f, -0.247f, 0.0f, -0.539f, 1.017f, 1.0f,
- -0.232f, 0.0f, -0.533f, 1.016f, 1.0f, -0.218f, 0.0f, -0.525f, 1.015f, 1.0f,
- -0.202f, 0.0f, -0.515f, 1.013f, 1.0f, -0.186f, 0.0f, -0.503f, 1.009f, 1.0f,
- -0.169f, 0.0f, -0.49f, 1.005f, 1.0f, -0.151f, 0.0f, -0.475f, 0.998f, 1.0f,
- -0.132f, 0.0f, -0.458f, 0.99f, 1.0f, -0.112f, 0.0f, -0.44f, 0.98f, 1.0f,
- -0.091f, 0.0f, -0.42f, 0.968f, 1.0f, -0.069f, 0.0f, -0.398f, 0.955f, 1.0f,
- -0.045f, 0.0f, -0.375f, 0.939f, 1.0f, -0.021f, 0.0f, -0.35f, 0.923f, 1.0f,
- 0.005f, 0.0f, -0.324f, 0.908f, 1.0f, 0.031f, 0.0f, -0.297f, 0.895f, 1.0f,
- 0.06f, 0.0f, -0.268f, 0.882f, 1.0f, 0.089f, 0.0f, -0.238f, 0.87f, 1.0f,
- 0.12f, 0.0f, -0.207f, 0.858f, 1.0f, 0.153f, 0.0f, -0.175f, 0.844f, 1.0f,
- 0.187f, 0.0f, -0.14f, 0.828f, 1.0f, 0.224f, 0.0f, -0.104f, 0.81f, 1.0f,
- 0.262f, 0.0f, -0.067f, 0.79f, 1.0f, 0.302f, 0.0f, -0.027f, 0.769f, 1.0f,
- 0.344f, 0.0f, 0.014f, 0.747f, 1.0f, 0.388f, 0.0f, 0.056f, 0.724f, 1.0f,
- 0.434f, 0.0f, 0.1f, 0.7f, 1.0f, 0.483f, 0.0f, 0.145f, 0.676f, 1.0f,
- 0.533f, 0.0f, 0.191f, 0.651f, 1.0f, 0.585f, 0.0f, 0.238f, 0.625f, 1.0f,
- 0.637f, 0.0f, 0.284f, 0.599f, 1.0f, 0.69f, 0.0f, 0.33f, 0.573f, 1.0f,
- 0.746f, 0.0f, 0.376f, 0.546f, 1.0f, 0.802f, 0.0f, 0.421f, 0.516f, 1.0f,
- 0.859f, 0.0f, 0.464f, 0.483f, 1.0f, 0.915f, 0.0f, 0.506f, 0.446f, 1.0f,
- 0.97f, 0.0f, 0.545f, 0.407f, 1.0f, 1.023f, 0.0f, 0.581f, 0.365f, 1.0f,
- 1.075f, 0.0f, 0.614f, 0.322f, 1.0f, 1.122f, 0.0f, 0.643f, 0.28f, 1.0f,
- 1.169f, 0.0f, 0.671f, 0.236f, 1.0f, 1.207f, 0.0f, 0.693f, 0.202f, 1.0f,
- 1.264f, 0.0f, 0.725f, 0.155f, 1.0f,
+ -1.281f, 0.0f, -0.315f, 0.038f, 1.0f, -1.269f, 0.0f, -0.302f, 0.069f, 1.0f,
+ -1.261f, 0.0f, -0.293f, 0.089f, 1.0f, -1.251f, 0.0f, -0.282f, 0.112f, 1.0f,
+ -1.241f, 0.0f, -0.271f, 0.134f, 1.0f, -1.23f, 0.0f, -0.259f, 0.155f, 1.0f,
+ -1.219f, 0.0f, -0.247f, 0.175f, 1.0f, -1.208f, 0.0f, -0.234f, 0.194f, 1.0f,
+ -1.196f, 0.0f, -0.221f, 0.211f, 1.0f, -1.184f, 0.0f, -0.208f, 0.227f, 1.0f,
+ -1.172f, 0.0f, -0.194f, 0.242f, 1.0f, -1.159f, 0.0f, -0.18f, 0.256f, 1.0f,
+ -1.147f, 0.0f, -0.165f, 0.268f, 1.0f, -1.134f, 0.0f, -0.151f, 0.28f, 1.0f,
+ -1.121f, 0.0f, -0.136f, 0.29f, 1.0f, -1.108f, 0.0f, -0.121f, 0.299f, 1.0f,
+ -1.094f, 0.0f, -0.106f, 0.307f, 1.0f, -1.08f, 0.0f, -0.091f, 0.315f, 1.0f,
+ -1.066f, 0.0f, -0.076f, 0.322f, 1.0f, -1.052f, 0.0f, -0.061f, 0.329f, 1.0f,
+ -1.037f, 0.0f, -0.047f, 0.335f, 1.0f, -1.022f, 0.0f, -0.032f, 0.341f, 1.0f,
+ -1.007f, 0.0f, -0.017f, 0.346f, 1.0f, -0.991f, 0.0f, -0.003f, 0.351f, 1.0f,
+ -0.975f, 0.0f, 0.012f, 0.355f, 1.0f, -0.959f, 0.0f, 0.027f, 0.36f, 1.0f,
+ -0.942f, 0.0f, 0.041f, 0.364f, 1.0f, -0.926f, 0.0f, 0.056f, 0.368f, 1.0f,
+ -0.909f, 0.0f, 0.071f, 0.371f, 1.0f, -0.893f, 0.0f, 0.086f, 0.373f, 1.0f,
+ -0.876f, 0.0f, 0.1f, 0.376f, 1.0f, -0.859f, 0.0f, 0.115f, 0.377f, 1.0f,
+ -0.842f, 0.0f, 0.129f, 0.378f, 1.0f, -0.824f, 0.0f, 0.144f, 0.379f, 1.0f,
+ -0.807f, 0.0f, 0.158f, 0.379f, 1.0f, -0.79f, 0.0f, 0.172f, 0.379f, 1.0f,
+ -0.773f, 0.0f, 0.186f, 0.38f, 1.0f, -0.755f, 0.0f, 0.199f, 0.38f, 1.0f,
+ -0.738f, 0.0f, 0.212f, 0.381f, 1.0f, -0.721f, 0.0f, 0.224f, 0.382f, 1.0f,
+ -0.703f, 0.0f, 0.236f, 0.384f, 1.0f, -0.686f, 0.0f, 0.248f, 0.386f, 1.0f,
+ -0.67f, 0.0f, 0.26f, 0.388f, 1.0f, -0.653f, 0.0f, 0.27f, 0.39f, 1.0f,
+ -0.637f, 0.0f, 0.28f, 0.393f, 1.0f, -0.621f, 0.0f, 0.29f, 0.396f, 1.0f,
+ -0.605f, 0.0f, 0.298f, 0.399f, 1.0f, -0.589f, 0.0f, 0.306f, 0.403f, 1.0f,
+ -0.574f, 0.0f, 0.313f, 0.407f, 1.0f, -0.559f, 0.0f, 0.319f, 0.411f, 1.0f,
+ -0.544f, 0.0f, 0.325f, 0.415f, 1.0f, -0.53f, 0.0f, 0.331f, 0.42f, 1.0f,
+ -0.516f, 0.0f, 0.336f, 0.425f, 1.0f, -0.503f, 0.0f, 0.34f, 0.431f, 1.0f,
+ -0.489f, 0.0f, 0.344f, 0.437f, 1.0f, -0.477f, 0.0f, 0.347f, 0.443f, 1.0f,
+ -0.464f, 0.0f, 0.35f, 0.45f, 1.0f, -0.452f, 0.0f, 0.352f, 0.457f, 1.0f,
+ -0.44f, 0.0f, 0.354f, 0.464f, 1.0f, -0.429f, 0.0f, 0.355f, 0.471f, 1.0f,
+ -0.418f, 0.0f, 0.355f, 0.479f, 1.0f, -0.407f, 0.0f, 0.355f, 0.487f, 1.0f,
+ -0.397f, 0.0f, 0.354f, 0.495f, 1.0f, -0.387f, 0.0f, 0.353f, 0.503f, 1.0f,
+ -0.378f, 0.0f, 0.351f, 0.512f, 1.0f, -0.368f, 0.0f, 0.348f, 0.52f, 1.0f,
+ -0.36f, 0.0f, 0.344f, 0.528f, 1.0f, -0.351f, 0.0f, 0.34f, 0.537f, 1.0f,
+ -0.344f, 0.0f, 0.336f, 0.545f, 1.0f, -0.336f, 0.0f, 0.33f, 0.553f, 1.0f,
+ -0.329f, 0.0f, 0.324f, 0.562f, 1.0f, -0.322f, 0.0f, 0.318f, 0.57f, 1.0f,
+ -0.316f, 0.0f, 0.31f, 0.579f, 1.0f, -0.311f, 0.0f, 0.303f, 0.588f, 1.0f,
+ -0.306f, 0.0f, 0.294f, 0.597f, 1.0f, -0.301f, 0.0f, 0.285f, 0.606f, 1.0f,
+ -0.297f, 0.0f, 0.275f, 0.615f, 1.0f, -0.293f, 0.0f, 0.264f, 0.625f, 1.0f,
+ -0.29f, 0.0f, 0.253f, 0.635f, 1.0f, -0.288f, 0.0f, 0.241f, 0.644f, 1.0f,
+ -0.286f, 0.0f, 0.229f, 0.654f, 1.0f, -0.285f, 0.0f, 0.216f, 0.664f, 1.0f,
+ -0.284f, 0.0f, 0.202f, 0.675f, 1.0f, -0.283f, 0.0f, 0.188f, 0.685f, 1.0f,
+ -0.283f, 0.0f, 0.173f, 0.696f, 1.0f, -0.284f, 0.0f, 0.158f, 0.707f, 1.0f,
+ -0.285f, 0.0f, 0.142f, 0.718f, 1.0f, -0.286f, 0.0f, 0.125f, 0.729f, 1.0f,
+ -0.288f, 0.0f, 0.108f, 0.74f, 1.0f, -0.29f, 0.0f, 0.091f, 0.751f, 1.0f,
+ -0.293f, 0.0f, 0.073f, 0.761f, 1.0f, -0.295f, 0.0f, 0.054f, 0.772f, 1.0f,
+ -0.298f, 0.0f, 0.035f, 0.782f, 1.0f, -0.302f, 0.0f, 0.016f, 0.793f, 1.0f,
+ -0.305f, 0.0f, -0.004f, 0.804f, 1.0f, -0.309f, 0.0f, -0.024f, 0.815f, 1.0f,
+ -0.313f, 0.0f, -0.044f, 0.828f, 1.0f, -0.317f, 0.0f, -0.065f, 0.843f, 1.0f,
+ -0.321f, 0.0f, -0.085f, 0.86f, 1.0f, -0.326f, 0.0f, -0.106f, 0.879f, 1.0f,
+ -0.33f, 0.0f, -0.127f, 0.897f, 1.0f, -0.335f, 0.0f, -0.148f, 0.915f, 1.0f,
+ -0.339f, 0.0f, -0.168f, 0.932f, 1.0f, -0.344f, 0.0f, -0.189f, 0.947f, 1.0f,
+ -0.348f, 0.0f, -0.21f, 0.962f, 1.0f, -0.353f, 0.0f, -0.23f, 0.974f, 1.0f,
+ -0.357f, 0.0f, -0.25f, 0.985f, 1.0f, -0.361f, 0.0f, -0.27f, 0.995f, 1.0f,
+ -0.365f, 0.0f, -0.29f, 1.004f, 1.0f, -0.369f, 0.0f, -0.309f, 1.011f, 1.0f,
+ -0.372f, 0.0f, -0.328f, 1.018f, 1.0f, -0.375f, 0.0f, -0.347f, 1.024f, 1.0f,
+ -0.377f, 0.0f, -0.365f, 1.029f, 1.0f, -0.379f, 0.0f, -0.383f, 1.033f, 1.0f,
+ -0.38f, 0.0f, -0.4f, 1.036f, 1.0f, -0.38f, 0.0f, -0.417f, 1.037f, 1.0f,
+ -0.38f, 0.0f, -0.434f, 1.037f, 1.0f, -0.379f, 0.0f, -0.449f, 1.035f, 1.0f,
+ -0.377f, 0.0f, -0.464f, 1.032f, 1.0f, -0.374f, 0.0f, -0.478f, 1.029f, 1.0f,
+ -0.371f, 0.0f, -0.491f, 1.026f, 1.0f, -0.366f, 0.0f, -0.503f, 1.023f, 1.0f,
+ -0.361f, 0.0f, -0.513f, 1.021f, 1.0f, -0.354f, 0.0f, -0.523f, 1.019f, 1.0f,
+ -0.347f, 0.0f, -0.531f, 1.017f, 1.0f, -0.339f, 0.0f, -0.538f, 1.016f, 1.0f,
+ -0.33f, 0.0f, -0.543f, 1.016f, 1.0f, -0.32f, 0.0f, -0.547f, 1.016f, 1.0f,
+ -0.31f, 0.0f, -0.549f, 1.016f, 1.0f, -0.298f, 0.0f, -0.55f, 1.017f, 1.0f,
+ -0.286f, 0.0f, -0.55f, 1.017f, 1.0f, -0.274f, 0.0f, -0.548f, 1.018f, 1.0f,
+ -0.261f, 0.0f, -0.544f, 1.017f, 1.0f, -0.247f, 0.0f, -0.539f, 1.017f, 1.0f,
+ -0.232f, 0.0f, -0.533f, 1.016f, 1.0f, -0.218f, 0.0f, -0.525f, 1.015f, 1.0f,
+ -0.202f, 0.0f, -0.515f, 1.013f, 1.0f, -0.186f, 0.0f, -0.503f, 1.009f, 1.0f,
+ -0.169f, 0.0f, -0.49f, 1.005f, 1.0f, -0.151f, 0.0f, -0.475f, 0.998f, 1.0f,
+ -0.132f, 0.0f, -0.458f, 0.99f, 1.0f, -0.112f, 0.0f, -0.44f, 0.98f, 1.0f,
+ -0.091f, 0.0f, -0.42f, 0.968f, 1.0f, -0.069f, 0.0f, -0.398f, 0.955f, 1.0f,
+ -0.045f, 0.0f, -0.375f, 0.939f, 1.0f, -0.021f, 0.0f, -0.35f, 0.923f, 1.0f,
+ 0.005f, 0.0f, -0.324f, 0.908f, 1.0f, 0.031f, 0.0f, -0.297f, 0.895f, 1.0f,
+ 0.06f, 0.0f, -0.268f, 0.882f, 1.0f, 0.089f, 0.0f, -0.238f, 0.87f, 1.0f,
+ 0.12f, 0.0f, -0.207f, 0.858f, 1.0f, 0.153f, 0.0f, -0.175f, 0.844f, 1.0f,
+ 0.187f, 0.0f, -0.14f, 0.828f, 1.0f, 0.224f, 0.0f, -0.104f, 0.81f, 1.0f,
+ 0.262f, 0.0f, -0.067f, 0.79f, 1.0f, 0.302f, 0.0f, -0.027f, 0.769f, 1.0f,
+ 0.344f, 0.0f, 0.014f, 0.747f, 1.0f, 0.388f, 0.0f, 0.056f, 0.724f, 1.0f,
+ 0.434f, 0.0f, 0.1f, 0.7f, 1.0f, 0.483f, 0.0f, 0.145f, 0.676f, 1.0f,
+ 0.533f, 0.0f, 0.191f, 0.651f, 1.0f, 0.585f, 0.0f, 0.238f, 0.625f, 1.0f,
+ 0.637f, 0.0f, 0.284f, 0.599f, 1.0f, 0.69f, 0.0f, 0.33f, 0.573f, 1.0f,
+ 0.746f, 0.0f, 0.376f, 0.546f, 1.0f, 0.802f, 0.0f, 0.421f, 0.516f, 1.0f,
+ 0.859f, 0.0f, 0.464f, 0.483f, 1.0f, 0.915f, 0.0f, 0.506f, 0.446f, 1.0f,
+ 0.97f, 0.0f, 0.545f, 0.407f, 1.0f, 1.023f, 0.0f, 0.581f, 0.365f, 1.0f,
+ 1.075f, 0.0f, 0.614f, 0.322f, 1.0f, 1.122f, 0.0f, 0.643f, 0.28f, 1.0f,
+ 1.169f, 0.0f, 0.671f, 0.236f, 1.0f, 1.207f, 0.0f, 0.693f, 0.202f, 1.0f,
+ 1.264f, 0.0f, 0.725f, 0.155f, 1.0f,
};
/* ***************************************************************** */
/* Color Data */
static const ColorTemplate gp_stroke_material_black = {
- "Black",
- {0.0f, 0.0f, 0.0f, 1.0f},
- {0.0f, 0.0f, 0.0f, 0.0f},
+ "Black",
+ {0.0f, 0.0f, 0.0f, 1.0f},
+ {0.0f, 0.0f, 0.0f, 0.0f},
};
static const ColorTemplate gp_stroke_material_white = {
- "White",
- {1.0f, 1.0f, 1.0f, 1.0f},
- {0.0f, 0.0f, 0.0f, 0.0f},
+ "White",
+ {1.0f, 1.0f, 1.0f, 1.0f},
+ {0.0f, 0.0f, 0.0f, 0.0f},
};
static const ColorTemplate gp_stroke_material_red = {
- "Red",
- {1.0f, 0.0f, 0.0f, 1.0f},
- {0.0f, 0.0f, 0.0f, 0.0f},
+ "Red",
+ {1.0f, 0.0f, 0.0f, 1.0f},
+ {0.0f, 0.0f, 0.0f, 0.0f},
};
static const ColorTemplate gp_stroke_material_green = {
- "Green",
- {0.0f, 1.0f, 0.0f, 1.0f},
- {0.0f, 0.0f, 0.0f, 0.0f},
+ "Green",
+ {0.0f, 1.0f, 0.0f, 1.0f},
+ {0.0f, 0.0f, 0.0f, 0.0f},
};
static const ColorTemplate gp_stroke_material_blue = {
- "Blue",
- {0.0f, 0.0f, 1.0f, 1.0f},
- {0.0f, 0.0f, 0.0f, 0.0f},
+ "Blue",
+ {0.0f, 0.0f, 1.0f, 1.0f},
+ {0.0f, 0.0f, 0.0f, 0.0f},
};
static const ColorTemplate gp_stroke_material_grey = {
- "Grey",
- {0.358f, 0.358f, 0.358f, 1.0f},
- {0.5f, 0.5f, 0.5f, 1.0f},
+ "Grey",
+ {0.358f, 0.358f, 0.358f, 1.0f},
+ {0.5f, 0.5f, 0.5f, 1.0f},
};
/* ***************************************************************** */
@@ -214,37 +213,37 @@ static const ColorTemplate gp_stroke_material_grey = {
/* add a Simple stroke with colors (original design created by Daniel M. Lara and Matias Mendiola) */
void ED_gpencil_create_stroke(bContext *C, Object *ob, float mat[4][4])
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
- bGPdata *gpd = (bGPdata *)ob->data;
- bGPDstroke *gps;
-
- /* create colors */
- int color_black = gp_stroke_material(bmain, ob, &gp_stroke_material_black, false);
- gp_stroke_material(bmain, ob, &gp_stroke_material_white, false);
- gp_stroke_material(bmain, ob, &gp_stroke_material_red, false);
- gp_stroke_material(bmain, ob, &gp_stroke_material_green, false);
- gp_stroke_material(bmain, ob, &gp_stroke_material_blue, false);
- gp_stroke_material(bmain, ob, &gp_stroke_material_grey, true);
-
- /* set first color as active and in brushes */
- ob->actcol = color_black + 1;
-
- /* layers */
- bGPDlayer *colors = BKE_gpencil_layer_addnew(gpd, "Colors", false);
- bGPDlayer *lines = BKE_gpencil_layer_addnew(gpd, "Lines", true);
-
- /* frames */
- bGPDframe *frame_color = BKE_gpencil_frame_addnew(colors, cfra_eval);
- bGPDframe *frame_lines = BKE_gpencil_frame_addnew(lines, cfra_eval);
- UNUSED_VARS(frame_color);
-
- /* generate stroke */
- gps = BKE_gpencil_add_stroke(frame_lines, color_black, 175, 75);
- BKE_gpencil_stroke_add_points(gps, data0, 175, mat);
-
- /* update depsgraph */
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bGPDstroke *gps;
+
+ /* create colors */
+ int color_black = gp_stroke_material(bmain, ob, &gp_stroke_material_black, false);
+ gp_stroke_material(bmain, ob, &gp_stroke_material_white, false);
+ gp_stroke_material(bmain, ob, &gp_stroke_material_red, false);
+ gp_stroke_material(bmain, ob, &gp_stroke_material_green, false);
+ gp_stroke_material(bmain, ob, &gp_stroke_material_blue, false);
+ gp_stroke_material(bmain, ob, &gp_stroke_material_grey, true);
+
+ /* set first color as active and in brushes */
+ ob->actcol = color_black + 1;
+
+ /* layers */
+ bGPDlayer *colors = BKE_gpencil_layer_addnew(gpd, "Colors", false);
+ bGPDlayer *lines = BKE_gpencil_layer_addnew(gpd, "Lines", true);
+
+ /* frames */
+ bGPDframe *frame_color = BKE_gpencil_frame_addnew(colors, cfra_eval);
+ bGPDframe *frame_lines = BKE_gpencil_frame_addnew(lines, cfra_eval);
+ UNUSED_VARS(frame_color);
+
+ /* generate stroke */
+ gps = BKE_gpencil_add_stroke(frame_lines, color_black, 175, 75);
+ BKE_gpencil_stroke_add_points(gps, data0, 175, mat);
+
+ /* update depsgraph */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
}
diff --git a/source/blender/editors/gpencil/gpencil_armature.c b/source/blender/editors/gpencil/gpencil_armature.c
index 8fff6b207ba..d99a630a45c 100644
--- a/source/blender/editors/gpencil/gpencil_armature.c
+++ b/source/blender/editors/gpencil/gpencil_armature.c
@@ -22,7 +22,6 @@
* \ingroup edgpencil
*/
-
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -69,609 +68,625 @@
#include "gpencil_intern.h"
enum {
- GP_ARMATURE_NAME = 0,
- GP_ARMATURE_AUTO = 1,
+ GP_ARMATURE_NAME = 0,
+ GP_ARMATURE_AUTO = 1,
};
#define DEFAULT_RATIO 0.10f
#define DEFAULT_DECAY 0.8f
-static int gpencil_bone_looper(
- Object *ob, Bone *bone, void *data,
- int(*bone_func)(Object *, Bone *, void *))
+static int gpencil_bone_looper(Object *ob,
+ Bone *bone,
+ void *data,
+ int (*bone_func)(Object *, Bone *, void *))
{
- /* We want to apply the function bone_func to every bone
- * in an armature -- feed bone_looper the first bone and
- * a pointer to the bone_func and watch it go!. The int count
- * can be useful for counting bones with a certain property
- * (e.g. skinnable)
- */
- int count = 0;
-
- if (bone) {
- /* only do bone_func if the bone is non null */
- count += bone_func(ob, bone, data);
-
- /* try to execute bone_func for the first child */
- count += gpencil_bone_looper(ob, bone->childbase.first, data, bone_func);
-
- /* try to execute bone_func for the next bone at this
- * depth of the recursion.
- */
- count += gpencil_bone_looper(ob, bone->next, data, bone_func);
- }
-
- return count;
+ /* We want to apply the function bone_func to every bone
+ * in an armature -- feed bone_looper the first bone and
+ * a pointer to the bone_func and watch it go!. The int count
+ * can be useful for counting bones with a certain property
+ * (e.g. skinnable)
+ */
+ int count = 0;
+
+ if (bone) {
+ /* only do bone_func if the bone is non null */
+ count += bone_func(ob, bone, data);
+
+ /* try to execute bone_func for the first child */
+ count += gpencil_bone_looper(ob, bone->childbase.first, data, bone_func);
+
+ /* try to execute bone_func for the next bone at this
+ * depth of the recursion.
+ */
+ count += gpencil_bone_looper(ob, bone->next, data, bone_func);
+ }
+
+ return count;
}
static int gpencil_bone_skinnable_cb(Object *UNUSED(ob), Bone *bone, void *datap)
{
- /* Bones that are deforming
- * are regarded to be "skinnable" and are eligible for
- * auto-skinning.
- *
- * This function performs 2 functions:
- *
- * a) It returns 1 if the bone is skinnable.
- * If we loop over all bones with this
- * function, we can count the number of
- * skinnable bones.
- * b) If the pointer data is non null,
- * it is treated like a handle to a
- * bone pointer -- the bone pointer
- * is set to point at this bone, and
- * the pointer the handle points to
- * is incremented to point to the
- * next member of an array of pointers
- * to bones. This way we can loop using
- * this function to construct an array of
- * pointers to bones that point to all
- * skinnable bones.
- */
- Bone ***hbone;
- int a, segments;
- struct { Object *armob; void *list; int heat;} *data = datap;
-
- if (!(bone->flag & BONE_HIDDEN_P)) {
- if (!(bone->flag & BONE_NO_DEFORM)) {
- if (data->heat && data->armob->pose &&
- BKE_pose_channel_find_name(data->armob->pose, bone->name))
- {
- segments = bone->segments;
- }
- else {
- segments = 1;
- }
-
- if (data->list != NULL) {
- hbone = (Bone ***)&data->list;
-
- for (a = 0; a < segments; a++) {
- **hbone = bone;
- (*hbone)++;
- }
- }
- return segments;
- }
- }
- return 0;
+ /* Bones that are deforming
+ * are regarded to be "skinnable" and are eligible for
+ * auto-skinning.
+ *
+ * This function performs 2 functions:
+ *
+ * a) It returns 1 if the bone is skinnable.
+ * If we loop over all bones with this
+ * function, we can count the number of
+ * skinnable bones.
+ * b) If the pointer data is non null,
+ * it is treated like a handle to a
+ * bone pointer -- the bone pointer
+ * is set to point at this bone, and
+ * the pointer the handle points to
+ * is incremented to point to the
+ * next member of an array of pointers
+ * to bones. This way we can loop using
+ * this function to construct an array of
+ * pointers to bones that point to all
+ * skinnable bones.
+ */
+ Bone ***hbone;
+ int a, segments;
+ struct {
+ Object *armob;
+ void *list;
+ int heat;
+ } *data = datap;
+
+ if (!(bone->flag & BONE_HIDDEN_P)) {
+ if (!(bone->flag & BONE_NO_DEFORM)) {
+ if (data->heat && data->armob->pose &&
+ BKE_pose_channel_find_name(data->armob->pose, bone->name)) {
+ segments = bone->segments;
+ }
+ else {
+ segments = 1;
+ }
+
+ if (data->list != NULL) {
+ hbone = (Bone ***)&data->list;
+
+ for (a = 0; a < segments; a++) {
+ **hbone = bone;
+ (*hbone)++;
+ }
+ }
+ return segments;
+ }
+ }
+ return 0;
}
static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
{
- /* This group creates a vertex group to ob that has the
- * same name as bone (provided the bone is skinnable).
- * If such a vertex group already exist the routine exits.
- */
- if (!(bone->flag & BONE_NO_DEFORM)) {
- if (!defgroup_find_name(ob, bone->name)) {
- BKE_object_defgroup_add_name(ob, bone->name);
- return 1;
- }
- }
- return 0;
+ /* This group creates a vertex group to ob that has the
+ * same name as bone (provided the bone is skinnable).
+ * If such a vertex group already exist the routine exits.
+ */
+ if (!(bone->flag & BONE_NO_DEFORM)) {
+ if (!defgroup_find_name(ob, bone->name)) {
+ BKE_object_defgroup_add_name(ob, bone->name);
+ return 1;
+ }
+ }
+ return 0;
}
static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
{
- /* Bones that are deforming
- * are regarded to be "skinnable" and are eligible for
- * auto-skinning.
- *
- * This function performs 2 functions:
- *
- * a) If the bone is skinnable, it creates
- * a vertex group for ob that has
- * the name of the skinnable bone
- * (if one doesn't exist already).
- * b) If the pointer data is non null,
- * it is treated like a handle to a
- * bDeformGroup pointer -- the
- * bDeformGroup pointer is set to point
- * to the deform group with the bone's
- * name, and the pointer the handle
- * points to is incremented to point to the
- * next member of an array of pointers
- * to bDeformGroups. This way we can loop using
- * this function to construct an array of
- * pointers to bDeformGroups, all with names
- * of skinnable bones.
- */
- bDeformGroup ***hgroup, *defgroup = NULL;
- int a, segments;
- struct { Object *armob; void *list; int heat; } *data = datap;
- bArmature *arm = data->armob->data;
-
- if (!(bone->flag & BONE_HIDDEN_P)) {
- if (!(bone->flag & BONE_NO_DEFORM)) {
- if (data->heat && data->armob->pose &&
- BKE_pose_channel_find_name(data->armob->pose, bone->name))
- {
- segments = bone->segments;
- }
- else {
- segments = 1;
- }
-
- if (arm->layer & bone->layer) {
- if (!(defgroup = defgroup_find_name(ob, bone->name))) {
- defgroup = BKE_object_defgroup_add_name(ob, bone->name);
- }
- else if (defgroup->flag & DG_LOCK_WEIGHT) {
- /* In case vgroup already exists and is locked, do not modify it here. See T43814. */
- defgroup = NULL;
- }
- }
-
- if (data->list != NULL) {
- hgroup = (bDeformGroup ***)&data->list;
-
- for (a = 0; a < segments; a++) {
- **hgroup = defgroup;
- (*hgroup)++;
- }
- }
- return segments;
- }
- }
- return 0;
+ /* Bones that are deforming
+ * are regarded to be "skinnable" and are eligible for
+ * auto-skinning.
+ *
+ * This function performs 2 functions:
+ *
+ * a) If the bone is skinnable, it creates
+ * a vertex group for ob that has
+ * the name of the skinnable bone
+ * (if one doesn't exist already).
+ * b) If the pointer data is non null,
+ * it is treated like a handle to a
+ * bDeformGroup pointer -- the
+ * bDeformGroup pointer is set to point
+ * to the deform group with the bone's
+ * name, and the pointer the handle
+ * points to is incremented to point to the
+ * next member of an array of pointers
+ * to bDeformGroups. This way we can loop using
+ * this function to construct an array of
+ * pointers to bDeformGroups, all with names
+ * of skinnable bones.
+ */
+ bDeformGroup ***hgroup, *defgroup = NULL;
+ int a, segments;
+ struct {
+ Object *armob;
+ void *list;
+ int heat;
+ } *data = datap;
+ bArmature *arm = data->armob->data;
+
+ if (!(bone->flag & BONE_HIDDEN_P)) {
+ if (!(bone->flag & BONE_NO_DEFORM)) {
+ if (data->heat && data->armob->pose &&
+ BKE_pose_channel_find_name(data->armob->pose, bone->name)) {
+ segments = bone->segments;
+ }
+ else {
+ segments = 1;
+ }
+
+ if (arm->layer & bone->layer) {
+ if (!(defgroup = defgroup_find_name(ob, bone->name))) {
+ defgroup = BKE_object_defgroup_add_name(ob, bone->name);
+ }
+ else if (defgroup->flag & DG_LOCK_WEIGHT) {
+ /* In case vgroup already exists and is locked, do not modify it here. See T43814. */
+ defgroup = NULL;
+ }
+ }
+
+ if (data->list != NULL) {
+ hgroup = (bDeformGroup ***)&data->list;
+
+ for (a = 0; a < segments; a++) {
+ **hgroup = defgroup;
+ (*hgroup)++;
+ }
+ }
+ return segments;
+ }
+ }
+ return 0;
}
/* get weight value depending of distance and decay value */
static float get_weight(float dist, float decay_rad, float dif_rad)
{
- float weight = 1.0f;
- if (dist < decay_rad) {
- weight = 1.0f;
- }
- else {
- weight = interpf(0.0f, 0.9f, (dist - decay_rad) / dif_rad);
- }
-
- return weight;
+ float weight = 1.0f;
+ if (dist < decay_rad) {
+ weight = 1.0f;
+ }
+ else {
+ weight = interpf(0.0f, 0.9f, (dist - decay_rad) / dif_rad);
+ }
+
+ return weight;
}
/* This functions implements the automatic computation of vertex group weights */
static void gpencil_add_verts_to_dgroups(
- const bContext *C, Object *ob, Object *ob_arm, const float ratio, const float decay)
+ const bContext *C, Object *ob, Object *ob_arm, const float ratio, const float decay)
{
- bArmature *arm = ob_arm->data;
- Bone **bonelist, *bone;
- bDeformGroup **dgrouplist;
- bPoseChannel *pchan;
- bGPdata *gpd = (bGPdata *)ob->data;
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
-
- Mat4 bbone_array[MAX_BBONE_SUBDIV], *bbone = NULL;
- float(*root)[3], (*tip)[3], (*verts)[3];
- float *radsqr;
- int *selected;
- float weight;
- int numbones, i, j, segments = 0;
- struct { Object *armob; void *list; int heat; } looper_data;
-
- looper_data.armob = ob_arm;
- looper_data.heat = true;
- looper_data.list = NULL;
-
- /* count the number of skinnable bones */
- numbones = gpencil_bone_looper(ob, arm->bonebase.first, &looper_data, gpencil_bone_skinnable_cb);
-
- if (numbones == 0)
- return;
-
- /* create an array of pointer to bones that are skinnable
- * and fill it with all of the skinnable bones */
- bonelist = MEM_callocN(numbones * sizeof(Bone *), "bonelist");
- looper_data.list = bonelist;
- gpencil_bone_looper(ob, arm->bonebase.first, &looper_data, gpencil_bone_skinnable_cb);
-
- /* create an array of pointers to the deform groups that
- * correspond to the skinnable bones (creating them
- * as necessary. */
- dgrouplist = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgrouplist");
-
- looper_data.list = dgrouplist;
- gpencil_bone_looper(ob, arm->bonebase.first, &looper_data, dgroup_skinnable_cb);
-
- /* create an array of root and tip positions transformed into
- * global coords */
- root = MEM_callocN(numbones * sizeof(float) * 3, "root");
- tip = MEM_callocN(numbones * sizeof(float) * 3, "tip");
- selected = MEM_callocN(numbones * sizeof(int), "selected");
- radsqr = MEM_callocN(numbones * sizeof(float), "radsqr");
-
- for (j = 0; j < numbones; j++) {
- bone = bonelist[j];
-
- /* handle bbone */
- if (segments == 0) {
- segments = 1;
- bbone = NULL;
-
- if ((ob_arm->pose) &&
- (pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name)))
- {
- if (bone->segments > 1) {
- segments = bone->segments;
- BKE_pchan_bbone_spline_setup(pchan, true, false, bbone_array);
- bbone = bbone_array;
- }
- }
- }
-
- segments--;
-
- /* compute root and tip */
- if (bbone) {
- mul_v3_m4v3(root[j], bone->arm_mat, bbone[segments].mat[3]);
- if ((segments + 1) < bone->segments) {
- mul_v3_m4v3(tip[j], bone->arm_mat, bbone[segments + 1].mat[3]);
- }
- else {
- copy_v3_v3(tip[j], bone->arm_tail);
- }
- }
- else {
- copy_v3_v3(root[j], bone->arm_head);
- copy_v3_v3(tip[j], bone->arm_tail);
- }
-
- mul_m4_v3(ob_arm->obmat, root[j]);
- mul_m4_v3(ob_arm->obmat, tip[j]);
-
- selected[j] = 1;
-
- /* calculate radius squared */
- radsqr[j] = len_squared_v3v3(root[j], tip[j]) * ratio;
- }
-
- /* loop all strokes */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- bGPDframe *init_gpf = gpl->actframe;
- bGPDspoint *pt = NULL;
-
- 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)))
- {
-
- if (gpf == NULL)
- continue;
-
- 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;
-
- BKE_gpencil_dvert_ensure(gps);
-
- /* create verts array */
- verts = MEM_callocN(gps->totpoints * sizeof(*verts), __func__);
-
- /* transform stroke points to global space */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- copy_v3_v3(verts[i], &pt->x);
- mul_m4_v3(ob->obmat, verts[i]);
- }
-
- /* loop groups and assign weight */
- for (j = 0; j < numbones; j++) {
- int def_nr = BLI_findindex(&ob->defbase, dgrouplist[j]);
- if (def_nr < 0) {
- continue;
- }
-
- float decay_rad = radsqr[j] - (radsqr[j] * decay);
- float dif_rad = radsqr[j] - decay_rad;
-
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- MDeformVert *dvert = &gps->dvert[i];
- float dist = dist_squared_to_line_segment_v3(verts[i], root[j], tip[j]);
- if (dist > radsqr[j]) {
- /* if not in cylinder, check if inside extreme spheres */
- weight = 0.0f;
- dist = len_squared_v3v3(root[j], verts[i]);
- if (dist < radsqr[j]) {
- weight = get_weight(dist, decay_rad, dif_rad);
- }
- else {
- dist = len_squared_v3v3(tip[j], verts[i]);
- if (dist < radsqr[j]) {
- weight = get_weight(dist, decay_rad, dif_rad);
- }
- }
- }
- else {
- /* inside bone cylinder */
- weight = get_weight(dist, decay_rad, dif_rad);
- }
-
- /* assign weight */
- MDeformWeight *dw = defvert_verify_index(dvert, def_nr);
- if (dw) {
- dw->weight = weight;
- }
- }
- }
- MEM_SAFE_FREE(verts);
- }
- }
-
- /* if not multiedit, exit loop*/
- if (!is_multiedit) {
- break;
- }
- }
- }
-
- /* free the memory allocated */
- MEM_SAFE_FREE(bonelist);
- MEM_SAFE_FREE(dgrouplist);
- MEM_SAFE_FREE(root);
- MEM_SAFE_FREE(tip);
- MEM_SAFE_FREE(radsqr);
- MEM_SAFE_FREE(selected);
+ bArmature *arm = ob_arm->data;
+ Bone **bonelist, *bone;
+ bDeformGroup **dgrouplist;
+ bPoseChannel *pchan;
+ bGPdata *gpd = (bGPdata *)ob->data;
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+
+ Mat4 bbone_array[MAX_BBONE_SUBDIV], *bbone = NULL;
+ float(*root)[3], (*tip)[3], (*verts)[3];
+ float *radsqr;
+ int *selected;
+ float weight;
+ int numbones, i, j, segments = 0;
+ struct {
+ Object *armob;
+ void *list;
+ int heat;
+ } looper_data;
+
+ looper_data.armob = ob_arm;
+ looper_data.heat = true;
+ looper_data.list = NULL;
+
+ /* count the number of skinnable bones */
+ numbones = gpencil_bone_looper(ob, arm->bonebase.first, &looper_data, gpencil_bone_skinnable_cb);
+
+ if (numbones == 0)
+ return;
+
+ /* create an array of pointer to bones that are skinnable
+ * and fill it with all of the skinnable bones */
+ bonelist = MEM_callocN(numbones * sizeof(Bone *), "bonelist");
+ looper_data.list = bonelist;
+ gpencil_bone_looper(ob, arm->bonebase.first, &looper_data, gpencil_bone_skinnable_cb);
+
+ /* create an array of pointers to the deform groups that
+ * correspond to the skinnable bones (creating them
+ * as necessary. */
+ dgrouplist = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgrouplist");
+
+ looper_data.list = dgrouplist;
+ gpencil_bone_looper(ob, arm->bonebase.first, &looper_data, dgroup_skinnable_cb);
+
+ /* create an array of root and tip positions transformed into
+ * global coords */
+ root = MEM_callocN(numbones * sizeof(float) * 3, "root");
+ tip = MEM_callocN(numbones * sizeof(float) * 3, "tip");
+ selected = MEM_callocN(numbones * sizeof(int), "selected");
+ radsqr = MEM_callocN(numbones * sizeof(float), "radsqr");
+
+ for (j = 0; j < numbones; j++) {
+ bone = bonelist[j];
+
+ /* handle bbone */
+ if (segments == 0) {
+ segments = 1;
+ bbone = NULL;
+
+ if ((ob_arm->pose) && (pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name))) {
+ if (bone->segments > 1) {
+ segments = bone->segments;
+ BKE_pchan_bbone_spline_setup(pchan, true, false, bbone_array);
+ bbone = bbone_array;
+ }
+ }
+ }
+
+ segments--;
+
+ /* compute root and tip */
+ if (bbone) {
+ mul_v3_m4v3(root[j], bone->arm_mat, bbone[segments].mat[3]);
+ if ((segments + 1) < bone->segments) {
+ mul_v3_m4v3(tip[j], bone->arm_mat, bbone[segments + 1].mat[3]);
+ }
+ else {
+ copy_v3_v3(tip[j], bone->arm_tail);
+ }
+ }
+ else {
+ copy_v3_v3(root[j], bone->arm_head);
+ copy_v3_v3(tip[j], bone->arm_tail);
+ }
+
+ mul_m4_v3(ob_arm->obmat, root[j]);
+ mul_m4_v3(ob_arm->obmat, tip[j]);
+
+ selected[j] = 1;
+
+ /* calculate radius squared */
+ radsqr[j] = len_squared_v3v3(root[j], tip[j]) * ratio;
+ }
+
+ /* loop all strokes */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ bGPDframe *init_gpf = gpl->actframe;
+ bGPDspoint *pt = NULL;
+
+ 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))) {
+
+ if (gpf == NULL)
+ continue;
+
+ 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;
+
+ BKE_gpencil_dvert_ensure(gps);
+
+ /* create verts array */
+ verts = MEM_callocN(gps->totpoints * sizeof(*verts), __func__);
+
+ /* transform stroke points to global space */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ copy_v3_v3(verts[i], &pt->x);
+ mul_m4_v3(ob->obmat, verts[i]);
+ }
+
+ /* loop groups and assign weight */
+ for (j = 0; j < numbones; j++) {
+ int def_nr = BLI_findindex(&ob->defbase, dgrouplist[j]);
+ if (def_nr < 0) {
+ continue;
+ }
+
+ float decay_rad = radsqr[j] - (radsqr[j] * decay);
+ float dif_rad = radsqr[j] - decay_rad;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ MDeformVert *dvert = &gps->dvert[i];
+ float dist = dist_squared_to_line_segment_v3(verts[i], root[j], tip[j]);
+ if (dist > radsqr[j]) {
+ /* if not in cylinder, check if inside extreme spheres */
+ weight = 0.0f;
+ dist = len_squared_v3v3(root[j], verts[i]);
+ if (dist < radsqr[j]) {
+ weight = get_weight(dist, decay_rad, dif_rad);
+ }
+ else {
+ dist = len_squared_v3v3(tip[j], verts[i]);
+ if (dist < radsqr[j]) {
+ weight = get_weight(dist, decay_rad, dif_rad);
+ }
+ }
+ }
+ else {
+ /* inside bone cylinder */
+ weight = get_weight(dist, decay_rad, dif_rad);
+ }
+
+ /* assign weight */
+ MDeformWeight *dw = defvert_verify_index(dvert, def_nr);
+ if (dw) {
+ dw->weight = weight;
+ }
+ }
+ }
+ MEM_SAFE_FREE(verts);
+ }
+ }
+
+ /* if not multiedit, exit loop*/
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+
+ /* free the memory allocated */
+ MEM_SAFE_FREE(bonelist);
+ MEM_SAFE_FREE(dgrouplist);
+ MEM_SAFE_FREE(root);
+ MEM_SAFE_FREE(tip);
+ MEM_SAFE_FREE(radsqr);
+ MEM_SAFE_FREE(selected);
}
-static void gpencil_object_vgroup_calc_from_armature(
- const bContext *C,
- Object *ob, Object *ob_arm,
- const int mode, const float ratio, const float decay)
+static void gpencil_object_vgroup_calc_from_armature(const bContext *C,
+ Object *ob,
+ Object *ob_arm,
+ const int mode,
+ const float ratio,
+ const float decay)
{
- /* Lets try to create some vertex groups
- * based on the bones of the parent armature.
- */
- bArmature *arm = ob_arm->data;
-
- /* always create groups */
- const int defbase_tot = BLI_listbase_count(&ob->defbase);
- int defbase_add;
- /* Traverse the bone list, trying to create empty vertex
- * groups corresponding to the bone.
- */
- defbase_add = gpencil_bone_looper(
- ob, arm->bonebase.first, NULL,
- vgroup_add_unique_bone_cb);
-
- if (defbase_add) {
- /* its possible there are DWeight's outside the range of the current
- * objects deform groups, in this case the new groups wont be empty */
- ED_vgroup_data_clamp_range(ob->data, defbase_tot);
- }
-
- if (mode == GP_ARMATURE_AUTO) {
- /* Traverse the bone list, trying to fill vertex groups
- * with the corresponding vertice weights for which the
- * bone is closest.
- */
- gpencil_add_verts_to_dgroups(
- C, ob, ob_arm,
- ratio, decay);
- }
+ /* Lets try to create some vertex groups
+ * based on the bones of the parent armature.
+ */
+ bArmature *arm = ob_arm->data;
+
+ /* always create groups */
+ const int defbase_tot = BLI_listbase_count(&ob->defbase);
+ int defbase_add;
+ /* Traverse the bone list, trying to create empty vertex
+ * groups corresponding to the bone.
+ */
+ defbase_add = gpencil_bone_looper(ob, arm->bonebase.first, NULL, vgroup_add_unique_bone_cb);
+
+ if (defbase_add) {
+ /* its possible there are DWeight's outside the range of the current
+ * objects deform groups, in this case the new groups wont be empty */
+ ED_vgroup_data_clamp_range(ob->data, defbase_tot);
+ }
+
+ if (mode == GP_ARMATURE_AUTO) {
+ /* Traverse the bone list, trying to fill vertex groups
+ * with the corresponding vertice weights for which the
+ * bone is closest.
+ */
+ gpencil_add_verts_to_dgroups(C, ob, ob_arm, ratio, decay);
+ }
}
bool ED_gpencil_add_armature_weights(
- const bContext *C, ReportList *reports,
- Object *ob, Object *ob_arm, int mode)
+ const bContext *C, ReportList *reports, Object *ob, Object *ob_arm, int mode)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
-
- if (ob == NULL) {
- return false;
- }
-
- /* if no armature modifier, add a new one */
- GpencilModifierData *md = BKE_gpencil_modifiers_findByType(ob, eGpencilModifierType_Armature);
- if (md == NULL) {
- md = ED_object_gpencil_modifier_add(
- reports, bmain, scene,
- ob, "Armature", eGpencilModifierType_Armature);
- if (md == NULL) {
- BKE_report(reports, RPT_ERROR,
- "Unable to add a new Armature modifier to object");
- return false;
- }
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- }
-
- /* verify armature */
- ArmatureGpencilModifierData *mmd = (ArmatureGpencilModifierData *)md;
- if (mmd->object == NULL) {
- mmd->object = ob_arm;
- }
- else {
- if (ob_arm != mmd->object) {
- BKE_report(reports, RPT_ERROR,
- "The existing Armature modifier is already using a different Armature object");
- return false;
- }
- }
-
- /* add weights */
- gpencil_object_vgroup_calc_from_armature(C, ob, ob_arm, mode, DEFAULT_RATIO, DEFAULT_DECAY);
-
- return true;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+
+ if (ob == NULL) {
+ return false;
+ }
+
+ /* if no armature modifier, add a new one */
+ GpencilModifierData *md = BKE_gpencil_modifiers_findByType(ob, eGpencilModifierType_Armature);
+ if (md == NULL) {
+ md = ED_object_gpencil_modifier_add(
+ reports, bmain, scene, ob, "Armature", eGpencilModifierType_Armature);
+ if (md == NULL) {
+ BKE_report(reports, RPT_ERROR, "Unable to add a new Armature modifier to object");
+ return false;
+ }
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ }
+
+ /* verify armature */
+ ArmatureGpencilModifierData *mmd = (ArmatureGpencilModifierData *)md;
+ if (mmd->object == NULL) {
+ mmd->object = ob_arm;
+ }
+ else {
+ if (ob_arm != mmd->object) {
+ BKE_report(reports,
+ RPT_ERROR,
+ "The existing Armature modifier is already using a different Armature object");
+ return false;
+ }
+ }
+
+ /* add weights */
+ gpencil_object_vgroup_calc_from_armature(C, ob, ob_arm, mode, DEFAULT_RATIO, DEFAULT_DECAY);
+
+ return true;
}
/* ***************** Generate armature weights ************************** */
static bool gpencil_generate_weights_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if (ob == NULL) {
- return false;
- }
+ if (ob == NULL) {
+ return false;
+ }
- if (ob->type != OB_GPENCIL) {
- return false;
- }
+ if (ob->type != OB_GPENCIL) {
+ return false;
+ }
- ViewLayer *view_layer = CTX_data_view_layer(C);
- bGPdata *gpd = (bGPdata *)ob->data;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
- if (BLI_listbase_count(&gpd->layers) == 0) {
- return false;
- }
+ if (BLI_listbase_count(&gpd->layers) == 0) {
+ return false;
+ }
- /* need some armature in the view layer */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (base->object->type == OB_ARMATURE) {
- return true;
- }
- }
+ /* need some armature in the view layer */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->object->type == OB_ARMATURE) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
static int gpencil_generate_weights_exec(bContext *C, wmOperator *op)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = CTX_data_active_object(C);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- bGPdata *gpd = (bGPdata *)ob->data;
- Object *ob_arm = NULL;
-
- const int mode = RNA_enum_get(op->ptr, "mode");
- const float ratio = RNA_float_get(op->ptr, "ratio");
- const float decay = RNA_float_get(op->ptr, "decay");
-
- /* sanity checks */
- if (ELEM(NULL, ob, gpd))
- return OPERATOR_CANCELLED;
-
- /* get armature */
- const int arm_idx = RNA_enum_get(op->ptr, "armature");
- if (arm_idx > 0) {
- Base *base = BLI_findlink(&view_layer->object_bases, arm_idx - 1);
- ob_arm = base->object;
- }
- else {
- /* get armature from modifier */
- GpencilModifierData *md = BKE_gpencil_modifiers_findByType(ob_eval, eGpencilModifierType_Armature);
- if (md == NULL) {
- BKE_report(op->reports, RPT_ERROR,
- "The grease pencil object need an Armature modifier");
- return OPERATOR_CANCELLED;
- }
-
- ArmatureGpencilModifierData *mmd = (ArmatureGpencilModifierData *)md;
- if (mmd->object == NULL) {
- BKE_report(op->reports, RPT_ERROR,
- "Armature modifier is not valid or wrong defined");
- return OPERATOR_CANCELLED;
- }
-
- ob_arm = mmd->object;
- }
-
- if (ob_arm == NULL) {
- BKE_report(op->reports, RPT_ERROR,
- "No Armature object in the view layer");
- return OPERATOR_CANCELLED;
- }
-
- gpencil_object_vgroup_calc_from_armature(C, ob, ob_arm, mode, ratio, decay);
-
- /* 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;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = CTX_data_active_object(C);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ Object *ob_arm = NULL;
+
+ const int mode = RNA_enum_get(op->ptr, "mode");
+ const float ratio = RNA_float_get(op->ptr, "ratio");
+ const float decay = RNA_float_get(op->ptr, "decay");
+
+ /* sanity checks */
+ if (ELEM(NULL, ob, gpd))
+ return OPERATOR_CANCELLED;
+
+ /* get armature */
+ const int arm_idx = RNA_enum_get(op->ptr, "armature");
+ if (arm_idx > 0) {
+ Base *base = BLI_findlink(&view_layer->object_bases, arm_idx - 1);
+ ob_arm = base->object;
+ }
+ else {
+ /* get armature from modifier */
+ GpencilModifierData *md = BKE_gpencil_modifiers_findByType(ob_eval,
+ eGpencilModifierType_Armature);
+ if (md == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "The grease pencil object need an Armature modifier");
+ return OPERATOR_CANCELLED;
+ }
+
+ ArmatureGpencilModifierData *mmd = (ArmatureGpencilModifierData *)md;
+ if (mmd->object == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Armature modifier is not valid or wrong defined");
+ return OPERATOR_CANCELLED;
+ }
+
+ ob_arm = mmd->object;
+ }
+
+ if (ob_arm == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Armature object in the view layer");
+ return OPERATOR_CANCELLED;
+ }
+
+ gpencil_object_vgroup_calc_from_armature(C, ob, ob_arm, mode, ratio, decay);
+
+ /* 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;
}
/* Dynamically populate an enum of Armatures */
-static const EnumPropertyItem *gpencil_armatures_enum_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *gpencil_armatures_enum_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- EnumPropertyItem *item = NULL, item_tmp = { 0 };
- int totitem = 0;
- int i = 0;
-
- if (C == NULL) {
- return DummyRNA_DEFAULT_items;
- }
-
- /* add default */
- item_tmp.identifier = "DEFAULT";
- item_tmp.name = "Default";
- item_tmp.value = 0;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- i++;
-
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- Object *ob = base->object;
- if (ob->type == OB_ARMATURE) {
- item_tmp.identifier = item_tmp.name = ob->id.name + 2;
- item_tmp.value = i;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- }
- i++;
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ EnumPropertyItem *item = NULL, item_tmp = {0};
+ int totitem = 0;
+ int i = 0;
+
+ if (C == NULL) {
+ return DummyRNA_DEFAULT_items;
+ }
+
+ /* add default */
+ item_tmp.identifier = "DEFAULT";
+ item_tmp.name = "Default";
+ item_tmp.value = 0;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ i++;
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ Object *ob = base->object;
+ if (ob->type == OB_ARMATURE) {
+ item_tmp.identifier = item_tmp.name = ob->id.name + 2;
+ item_tmp.value = i;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
+ i++;
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
void GPENCIL_OT_generate_weights(wmOperatorType *ot)
{
- static const EnumPropertyItem mode_type[] = {
- {GP_ARMATURE_NAME, "NAME", 0, "Empty Groups", ""},
- {GP_ARMATURE_AUTO, "AUTO", 0, "Automatic Weights", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Generate Automatic Weights";
- ot->idname = "GPENCIL_OT_generate_weights";
- ot->description = "Generate automatic weights for armatures (requires armature modifier)";
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* callbacks */
- ot->exec = gpencil_generate_weights_exec;
- ot->poll = gpencil_generate_weights_poll;
-
- ot->prop = RNA_def_enum(ot->srna, "mode", mode_type, 0, "Mode", "");
-
- prop = RNA_def_enum(ot->srna, "armature", DummyRNA_DEFAULT_items, 0, "Armature", "Armature to use");
- RNA_def_enum_funcs(prop, gpencil_armatures_enum_itemf);
-
- RNA_def_float(
- ot->srna, "ratio", DEFAULT_RATIO, 0.0f, 2.0f, "Ratio",
- "Ratio between bone length and influence radius", 0.001f, 1.0f);
-
- RNA_def_float(
- ot->srna, "decay", DEFAULT_DECAY, 0.0f, 1.0f, "Decay",
- "Factor to reduce influence depending of distance to bone axis", 0.0f, 1.0f);
+ static const EnumPropertyItem mode_type[] = {
+ {GP_ARMATURE_NAME, "NAME", 0, "Empty Groups", ""},
+ {GP_ARMATURE_AUTO, "AUTO", 0, "Automatic Weights", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Generate Automatic Weights";
+ ot->idname = "GPENCIL_OT_generate_weights";
+ ot->description = "Generate automatic weights for armatures (requires armature modifier)";
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* callbacks */
+ ot->exec = gpencil_generate_weights_exec;
+ ot->poll = gpencil_generate_weights_poll;
+
+ ot->prop = RNA_def_enum(ot->srna, "mode", mode_type, 0, "Mode", "");
+
+ prop = RNA_def_enum(
+ ot->srna, "armature", DummyRNA_DEFAULT_items, 0, "Armature", "Armature to use");
+ RNA_def_enum_funcs(prop, gpencil_armatures_enum_itemf);
+
+ RNA_def_float(ot->srna,
+ "ratio",
+ DEFAULT_RATIO,
+ 0.0f,
+ 2.0f,
+ "Ratio",
+ "Ratio between bone length and influence radius",
+ 0.001f,
+ 1.0f);
+
+ RNA_def_float(ot->srna,
+ "decay",
+ DEFAULT_DECAY,
+ 0.0f,
+ 1.0f,
+ "Decay",
+ "Factor to reduce influence depending of distance to bone axis",
+ 0.0f,
+ 1.0f);
}
diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c
index 8f64ec1c868..ef0ebd06d07 100644
--- a/source/blender/editors/gpencil/gpencil_brush.c
+++ b/source/blender/editors/gpencil/gpencil_brush.c
@@ -22,7 +22,6 @@
* \ingroup edgpencil
*/
-
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -86,145 +85,133 @@
/* Context for brush operators */
typedef struct tGP_BrushEditData {
- /* Current editor/region/etc. */
- /* NOTE: This stuff is mainly needed to handle 3D view projection stuff... */
- Depsgraph *depsgraph;
- Scene *scene;
- Object *object;
-
- ScrArea *sa;
- ARegion *ar;
-
- /* Current GPencil datablock */
- bGPdata *gpd;
+ /* Current editor/region/etc. */
+ /* NOTE: This stuff is mainly needed to handle 3D view projection stuff... */
+ Depsgraph *depsgraph;
+ Scene *scene;
+ Object *object;
- /* Brush Settings */
- GP_Sculpt_Settings *settings;
- GP_Sculpt_Data *gp_brush;
- GP_Sculpt_Data *gp_brush_old;
+ ScrArea *sa;
+ ARegion *ar;
- eGP_Sculpt_Types brush_type;
- eGP_Sculpt_Types brush_type_old;
- eGP_Sculpt_Flag flag;
+ /* Current GPencil datablock */
+ bGPdata *gpd;
- /* Space Conversion Data */
- GP_SpaceConversion gsc;
+ /* Brush Settings */
+ GP_Sculpt_Settings *settings;
+ GP_Sculpt_Data *gp_brush;
+ GP_Sculpt_Data *gp_brush_old;
+ eGP_Sculpt_Types brush_type;
+ eGP_Sculpt_Types brush_type_old;
+ eGP_Sculpt_Flag flag;
- /* Is the brush currently painting? */
- bool is_painting;
- bool is_weight_mode;
+ /* Space Conversion Data */
+ GP_SpaceConversion gsc;
- /* Start of new sculpt stroke */
- bool first;
+ /* Is the brush currently painting? */
+ bool is_painting;
+ bool is_weight_mode;
- /* Is multiframe editing enabled, and are we using falloff for that? */
- bool is_multiframe;
- bool use_multiframe_falloff;
+ /* Start of new sculpt stroke */
+ bool first;
- /* Current frame */
- int cfra;
+ /* Is multiframe editing enabled, and are we using falloff for that? */
+ bool is_multiframe;
+ bool use_multiframe_falloff;
+ /* Current frame */
+ int cfra;
- /* Brush Runtime Data: */
- /* - position and pressure
- * - the *_prev variants are the previous values
- */
- float mval[2], mval_prev[2];
- float pressure, pressure_prev;
+ /* Brush Runtime Data: */
+ /* - position and pressure
+ * - the *_prev variants are the previous values
+ */
+ float mval[2], mval_prev[2];
+ float pressure, pressure_prev;
- /* - effect vector (e.g. 2D/3D translation for grab brush) */
- float dvec[3];
+ /* - effect vector (e.g. 2D/3D translation for grab brush) */
+ float dvec[3];
- /* - multiframe falloff factor */
- float mf_falloff;
+ /* - multiframe falloff factor */
+ float mf_falloff;
- /* active vertex group */
- int vrgroup;
+ /* active vertex group */
+ int vrgroup;
+ /* brush geometry (bounding box) */
+ rcti brush_rect;
- /* brush geometry (bounding box) */
- rcti brush_rect;
+ /* Custom data for certain brushes */
+ /* - map from bGPDstroke's to structs containing custom data about those strokes */
+ GHash *stroke_customdata;
+ /* - general customdata */
+ void *customdata;
- /* Custom data for certain brushes */
- /* - map from bGPDstroke's to structs containing custom data about those strokes */
- GHash *stroke_customdata;
- /* - general customdata */
- void *customdata;
+ /* Timer for in-place accumulation of brush effect */
+ wmTimer *timer;
+ bool timerTick; /* is this event from a timer */
-
- /* Timer for in-place accumulation of brush effect */
- wmTimer *timer;
- bool timerTick; /* is this event from a timer */
-
- RNG *rng;
+ RNG *rng;
} tGP_BrushEditData;
-
/* Callback for performing some brush operation on a single point */
typedef bool (*GP_BrushApplyCb)(
- tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
- const int radius, const int co[2]);
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index, const int radius, const int co[2]);
/* ************************************************ */
/* Utility Functions */
/* apply lock axis reset */
-static void gpsculpt_compute_lock_axis(tGP_BrushEditData *gso, bGPDspoint *pt, const float save_pt[3])
+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;
-
- /* lock axis control */
- switch (axis) {
- case GP_LOCKAXIS_X:
- {
- pt->x = save_pt[0];
- break;
- }
- case GP_LOCKAXIS_Y:
- {
- pt->y = save_pt[1];
- break;
- }
- case GP_LOCKAXIS_Z:
- {
- pt->z = save_pt[2];
- break;
- }
- case GP_LOCKAXIS_CURSOR:
- {
- /* compute a plane with cursor normal and position of the point
- before do the sculpt */
- const float scale[3] = { 1.0f, 1.0f, 1.0f };
- float plane_normal[3] = { 0.0f, 0.0f, 1.0f };
- float plane[4];
- float mat[4][4];
- float r_close[3];
-
- loc_eul_size_to_mat4(mat,
- cursor->location,
- cursor->rotation_euler,
- scale);
-
- mul_mat3_m4_v3(mat, plane_normal);
- plane_from_point_normal_v3(plane, save_pt, plane_normal);
-
- /* find closest point to the plane with the new position */
- closest_to_plane_v3(r_close, plane, &pt->x);
- copy_v3_v3(&pt->x, r_close);
- break;
- }
- default:
- {
- break;
- }
- }
+ 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;
+
+ /* lock axis control */
+ switch (axis) {
+ case GP_LOCKAXIS_X: {
+ pt->x = save_pt[0];
+ break;
+ }
+ case GP_LOCKAXIS_Y: {
+ pt->y = save_pt[1];
+ break;
+ }
+ case GP_LOCKAXIS_Z: {
+ pt->z = save_pt[2];
+ break;
+ }
+ case GP_LOCKAXIS_CURSOR: {
+ /* compute a plane with cursor normal and position of the point
+ before do the sculpt */
+ const float scale[3] = {1.0f, 1.0f, 1.0f};
+ float plane_normal[3] = {0.0f, 0.0f, 1.0f};
+ float plane[4];
+ float mat[4][4];
+ float r_close[3];
+
+ loc_eul_size_to_mat4(mat, cursor->location, cursor->rotation_euler, scale);
+
+ mul_mat3_m4_v3(mat, plane_normal);
+ plane_from_point_normal_v3(plane, save_pt, plane_normal);
+
+ /* find closest point to the plane with the new position */
+ closest_to_plane_v3(r_close, plane, &pt->x);
+ copy_v3_v3(&pt->x, r_close);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
}
/* Context ---------------------------------------- */
@@ -232,22 +219,22 @@ static void gpsculpt_compute_lock_axis(tGP_BrushEditData *gso, bGPDspoint *pt, c
/* Get the sculpting settings */
static GP_Sculpt_Settings *gpsculpt_get_settings(Scene *scene)
{
- return &scene->toolsettings->gp_sculpt;
+ 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;
+ 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 ------------------------------- */
@@ -255,56 +242,56 @@ static GP_Sculpt_Data *gpsculpt_get_brush(Scene *scene, bool is_weight_mode)
/* 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);
-
- /* During runtime, the user can hold down the Ctrl key to invert the basic behavior */
- if (gso->flag & GP_SCULPT_FLAG_INVERT) {
- invert ^= true;
- }
-
- /* set temporary status */
- if (invert) {
- gso->gp_brush->flag |= GP_SCULPT_FLAG_TMP_INVERT;
- }
- else {
- gso->gp_brush->flag &= ~GP_SCULPT_FLAG_TMP_INVERT;
- }
-
- return invert;
+ /* The basic setting is the brush's setting (from the panel) */
+ bool invert = ((gso->gp_brush->flag & GP_SCULPT_FLAG_INVERT) != 0);
+
+ /* During runtime, the user can hold down the Ctrl key to invert the basic behavior */
+ if (gso->flag & GP_SCULPT_FLAG_INVERT) {
+ invert ^= true;
+ }
+
+ /* set temporary status */
+ if (invert) {
+ gso->gp_brush->flag |= GP_SCULPT_FLAG_TMP_INVERT;
+ }
+ else {
+ gso->gp_brush->flag &= ~GP_SCULPT_FLAG_TMP_INVERT;
+ }
+
+ return invert;
}
/* 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;
+ GP_Sculpt_Data *gp_brush = gso->gp_brush;
- /* basic strength factor from brush settings */
- float influence = gp_brush->strength;
+ /* basic strength factor from brush settings */
+ float influence = gp_brush->strength;
- /* use pressure? */
- if (gp_brush->flag & GP_SCULPT_FLAG_USE_PRESSURE) {
- influence *= gso->pressure;
- }
+ /* use pressure? */
+ if (gp_brush->flag & GP_SCULPT_FLAG_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;
+ /* 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;
- CLAMP(distance, 0.0f, (float)radius);
- fac = 1.0f - (distance / (float)radius);
+ CLAMP(distance, 0.0f, (float)radius);
+ fac = 1.0f - (distance / (float)radius);
- influence *= fac;
- }
+ influence *= fac;
+ }
- /* apply multiframe falloff */
- influence *= gso->mf_falloff;
+ /* apply multiframe falloff */
+ influence *= gso->mf_falloff;
- /* return influence */
- return influence;
+ /* return influence */
+ return influence;
}
/* ************************************************ */
@@ -318,38 +305,34 @@ static float gp_brush_influence_calc(tGP_BrushEditData *gso, const int radius, c
/* A simple (but slower + inaccurate) smooth-brush implementation to test the algorithm for stroke smoothing */
static bool gp_brush_smooth_apply(
- tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
- const int radius, const int co[2])
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index, 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->settings->flag & GP_SCULPT_SETT_FLAG_APPLY_STRENGTH) {
- BKE_gpencil_smooth_stroke_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->settings->flag & GP_SCULPT_SETT_FLAG_APPLY_UV) {
- BKE_gpencil_smooth_stroke_uv(gps, pt_index, inf);
- }
-
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
-
- return true;
+ // 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->settings->flag & GP_SCULPT_SETT_FLAG_APPLY_STRENGTH) {
+ BKE_gpencil_smooth_stroke_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->settings->flag & GP_SCULPT_SETT_FLAG_APPLY_UV) {
+ BKE_gpencil_smooth_stroke_uv(gps, pt_index, inf);
+ }
+
+ gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+
+ return true;
}
/* ----------------------------------------------- */
@@ -357,77 +340,73 @@ static bool gp_brush_smooth_apply(
/* Make lines thicker or thinner by the specified amounts */
static bool gp_brush_thickness_apply(
- tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
- const int radius, const int co[2])
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index, const int radius, const int co[2])
{
- bGPDspoint *pt = gps->points + 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;
-
- /* apply */
- // XXX: this is much too strong, and it should probably do some smoothing with the surrounding stuff
- if (gp_brush_invert_check(gso)) {
- /* make line thinner - reduce stroke pressure */
- pt->pressure -= inf;
- }
- else {
- /* make line thicker - increase stroke pressure */
- pt->pressure += inf;
- }
-
- /* Pressure should stay within [0.0, 1.0]
- * However, it is nice for volumetric strokes to be able to exceed
- * the upper end of this range. Therefore, we don't actually clamp
- * down on the upper end.
- */
- if (pt->pressure < 0.0f)
- pt->pressure = 0.0f;
-
- return true;
+ bGPDspoint *pt = gps->points + 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;
+
+ /* apply */
+ // XXX: this is much too strong, and it should probably do some smoothing with the surrounding stuff
+ if (gp_brush_invert_check(gso)) {
+ /* make line thinner - reduce stroke pressure */
+ pt->pressure -= inf;
+ }
+ else {
+ /* make line thicker - increase stroke pressure */
+ pt->pressure += inf;
+ }
+
+ /* Pressure should stay within [0.0, 1.0]
+ * However, it is nice for volumetric strokes to be able to exceed
+ * the upper end of this range. Therefore, we don't actually clamp
+ * down on the upper end.
+ */
+ if (pt->pressure < 0.0f)
+ pt->pressure = 0.0f;
+
+ return true;
}
-
/* ----------------------------------------------- */
/* Color Strength Brush */
/* Make color more or less transparent by the specified amounts */
static bool gp_brush_strength_apply(
- tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
- const int radius, const int co[2])
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index, const int radius, const int co[2])
{
- 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) / 20.0f;
-
- /* apply */
- if (gp_brush_invert_check(gso)) {
- /* make line more transparent - reduce alpha factor */
- pt->strength -= inf;
- }
- else {
- /* make line more opaque - increase stroke strength */
- pt->strength += inf;
- }
- /* smooth the strength */
- BKE_gpencil_smooth_stroke_strength(gps, pt_index, inf);
-
- /* Strength should stay within [0.0, 1.0] */
- CLAMP(pt->strength, 0.0f, 1.0f);
-
- return true;
+ 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) / 20.0f;
+
+ /* apply */
+ if (gp_brush_invert_check(gso)) {
+ /* make line more transparent - reduce alpha factor */
+ pt->strength -= inf;
+ }
+ else {
+ /* make line more opaque - increase stroke strength */
+ pt->strength += inf;
+ }
+ /* smooth the strength */
+ BKE_gpencil_smooth_stroke_strength(gps, pt_index, inf);
+
+ /* Strength should stay within [0.0, 1.0] */
+ CLAMP(pt->strength, 0.0f, 1.0f);
+
+ return true;
}
-
/* ----------------------------------------------- */
/* Grab Brush */
@@ -438,145 +417,145 @@ static bool gp_brush_strength_apply(
* the brush region.
*/
typedef struct tGPSB_Grab_StrokeData {
- /* array of indices to corresponding points in the stroke */
- int *points;
- /* array of influence weights for each of the included points */
- float *weights;
-
- /* capacity of the arrays */
- int capacity;
- /* actual number of items currently stored */
- int size;
+ /* array of indices to corresponding points in the stroke */
+ int *points;
+ /* array of influence weights for each of the included points */
+ float *weights;
+
+ /* capacity of the arrays */
+ int capacity;
+ /* actual number of items currently stored */
+ int size;
} tGPSB_Grab_StrokeData;
/* initialise custom data for handling this stroke */
static void gp_brush_grab_stroke_init(tGP_BrushEditData *gso, bGPDstroke *gps)
{
- tGPSB_Grab_StrokeData *data = NULL;
+ tGPSB_Grab_StrokeData *data = NULL;
- BLI_assert(gps->totpoints > 0);
+ BLI_assert(gps->totpoints > 0);
- /* Check if there are buffers already (from a prior run) */
- if (BLI_ghash_haskey(gso->stroke_customdata, gps)) {
- /* Ensure that the caches are empty
- * - Since we reuse these between different strokes, we don't
- * want the previous invocation's data polluting the arrays
- */
- data = BLI_ghash_lookup(gso->stroke_customdata, gps);
- BLI_assert(data != NULL);
+ /* Check if there are buffers already (from a prior run) */
+ if (BLI_ghash_haskey(gso->stroke_customdata, gps)) {
+ /* Ensure that the caches are empty
+ * - Since we reuse these between different strokes, we don't
+ * want the previous invocation's data polluting the arrays
+ */
+ data = BLI_ghash_lookup(gso->stroke_customdata, gps);
+ BLI_assert(data != NULL);
- data->size = 0; /* minimum requirement - so that we can repopulate again */
+ data->size = 0; /* minimum requirement - so that we can repopulate again */
- memset(data->points, 0, sizeof(int) * data->capacity);
- memset(data->weights, 0, sizeof(float) * data->capacity);
- }
- else {
- /* Create new instance */
- data = MEM_callocN(sizeof(tGPSB_Grab_StrokeData), "GP Stroke Grab Data");
+ memset(data->points, 0, sizeof(int) * data->capacity);
+ memset(data->weights, 0, sizeof(float) * data->capacity);
+ }
+ else {
+ /* Create new instance */
+ data = MEM_callocN(sizeof(tGPSB_Grab_StrokeData), "GP Stroke Grab Data");
- data->capacity = gps->totpoints;
- data->size = 0;
+ data->capacity = gps->totpoints;
+ data->size = 0;
- data->points = MEM_callocN(sizeof(int) * data->capacity, "GP Stroke Grab Indices");
- data->weights = MEM_callocN(sizeof(float) * data->capacity, "GP Stroke Grab Weights");
+ data->points = MEM_callocN(sizeof(int) * data->capacity, "GP Stroke Grab Indices");
+ data->weights = MEM_callocN(sizeof(float) * data->capacity, "GP Stroke Grab Weights");
- /* hook up to the cache */
- BLI_ghash_insert(gso->stroke_customdata, gps, data);
- }
+ /* hook up to the cache */
+ BLI_ghash_insert(gso->stroke_customdata, gps, data);
+ }
}
/* store references to stroke points in the initial stage */
static bool gp_brush_grab_store_points(
- tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
- const int radius, const int co[2])
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index, const int radius, const int co[2])
{
- tGPSB_Grab_StrokeData *data = BLI_ghash_lookup(gso->stroke_customdata, gps);
- float inf = gp_brush_influence_calc(gso, radius, co);
+ tGPSB_Grab_StrokeData *data = BLI_ghash_lookup(gso->stroke_customdata, gps);
+ float inf = gp_brush_influence_calc(gso, radius, co);
- BLI_assert(data != NULL);
- BLI_assert(data->size < data->capacity);
+ BLI_assert(data != NULL);
+ BLI_assert(data->size < data->capacity);
- /* insert this point into the set of affected points */
- data->points[data->size] = pt_index;
- data->weights[data->size] = inf;
- data->size++;
+ /* insert this point into the set of affected points */
+ data->points[data->size] = pt_index;
+ data->weights[data->size] = inf;
+ data->size++;
- /* done */
- return true;
+ /* done */
+ return true;
}
/* Compute effect vector for grab brush */
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->scene->cursor.location;
- 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]);
-
- 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 */
- }
+ /* 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->scene->cursor.location;
+ 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]);
+
+ 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 */
+ }
}
/* Apply grab transform to all relevant points of the affected strokes */
-static void gp_brush_grab_apply_cached(
- tGP_BrushEditData *gso, bGPDstroke *gps, float diff_mat[4][4])
+static void gp_brush_grab_apply_cached(tGP_BrushEditData *gso,
+ bGPDstroke *gps,
+ float diff_mat[4][4])
{
- tGPSB_Grab_StrokeData *data = BLI_ghash_lookup(gso->stroke_customdata, gps);
- int i;
-
- /* Apply dvec to all of the stored points */
- for (i = 0; i < data->size; i++) {
- bGPDspoint *pt = &gps->points[data->points[i]];
- float delta[3] = {0.0f};
-
- /* adjust the amount of displacement to apply */
- mul_v3_v3fl(delta, gso->dvec, data->weights[i]);
-
- float fpt[3];
- float save_pt[3];
- copy_v3_v3(save_pt, &pt->x);
- /* apply transformation */
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- /* 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);
- }
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ tGPSB_Grab_StrokeData *data = BLI_ghash_lookup(gso->stroke_customdata, gps);
+ int i;
+
+ /* Apply dvec to all of the stored points */
+ for (i = 0; i < data->size; i++) {
+ bGPDspoint *pt = &gps->points[data->points[i]];
+ float delta[3] = {0.0f};
+
+ /* adjust the amount of displacement to apply */
+ mul_v3_v3fl(delta, gso->dvec, data->weights[i]);
+
+ float fpt[3];
+ float save_pt[3];
+ copy_v3_v3(save_pt, &pt->x);
+ /* apply transformation */
+ mul_v3_m4v3(fpt, diff_mat, &pt->x);
+ /* 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);
+ }
+ gps->flag |= GP_STROKE_RECALC_GEOMETRY;
}
/* free customdata used for handling this stroke */
static void gp_brush_grab_stroke_free(void *ptr)
{
- tGPSB_Grab_StrokeData *data = (tGPSB_Grab_StrokeData *)ptr;
+ tGPSB_Grab_StrokeData *data = (tGPSB_Grab_StrokeData *)ptr;
- /* free arrays */
- MEM_freeN(data->points);
- MEM_freeN(data->weights);
+ /* free arrays */
+ MEM_freeN(data->points);
+ MEM_freeN(data->weights);
- /* ... and this item itself, since it was also allocated */
- MEM_freeN(data);
+ /* ... and this item itself, since it was also allocated */
+ MEM_freeN(data);
}
/* ----------------------------------------------- */
@@ -584,29 +563,28 @@ static void gp_brush_grab_stroke_free(void *ptr)
/* NOTE: Depends on gp_brush_grab_calc_dvec() */
static bool gp_brush_push_apply(
- tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
- const int radius, const int co[2])
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index, const int radius, const int co[2])
{
- bGPDspoint *pt = gps->points + pt_index;
- float save_pt[3];
- copy_v3_v3(save_pt, &pt->x);
+ bGPDspoint *pt = gps->points + pt_index;
+ float save_pt[3];
+ copy_v3_v3(save_pt, &pt->x);
- float inf = gp_brush_influence_calc(gso, radius, co);
- float delta[3] = {0.0f};
+ float inf = gp_brush_influence_calc(gso, radius, co);
+ float delta[3] = {0.0f};
- /* adjust the amount of displacement to apply */
- mul_v3_v3fl(delta, gso->dvec, inf);
+ /* adjust the amount of displacement to apply */
+ mul_v3_v3fl(delta, gso->dvec, inf);
- /* apply */
- add_v3_v3(&pt->x, delta);
+ /* apply */
+ add_v3_v3(&pt->x, delta);
- /* compute lock axis */
- gpsculpt_compute_lock_axis(gso, pt, save_pt);
+ /* compute lock axis */
+ gpsculpt_compute_lock_axis(gso, pt, save_pt);
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- /* done */
- return true;
+ /* done */
+ return true;
}
/* ----------------------------------------------- */
@@ -615,84 +593,83 @@ static bool gp_brush_push_apply(
/* 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->scene->cursor.location;
- 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);
- }
- }
- 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;
- }
+ 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->scene->cursor.location;
+ 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);
+ }
+ }
+ 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;
+ }
}
/* Shrink distance between midpoint and this point... */
static bool gp_brush_pinch_apply(
- tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
- const int radius, const int co[2])
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index, const int radius, const int co[2])
{
- bGPDspoint *pt = gps->points + pt_index;
- float fac, inf;
- float vec[3];
- float save_pt[3];
- copy_v3_v3(save_pt, &pt->x);
-
- /* Scale down standard influence value to get it more manageable...
- * - No damping = Unmanageable at > 0.5 strength
- * - Div 10 = Not enough effect
- * - Div 5 = Happy medium... (by trial and error)
- */
- inf = gp_brush_influence_calc(gso, radius, co) / 5.0f;
-
- /* 1) Make this point relative to the cursor/midpoint (dvec) */
- sub_v3_v3v3(vec, &pt->x, gso->dvec);
-
- /* 2) Shrink the distance by pulling the point towards the midpoint
- * (0.0 = at midpoint, 1 = at edge of brush region)
- * OR
- * Increase the distance (if inverting the brush action!)
- */
- if (gp_brush_invert_check(gso)) {
- /* Inflate (inverse) */
- fac = 1.0f + (inf * inf); /* squared to temper the effect... */
- }
- else {
- /* Shrink (default) */
- fac = 1.0f - (inf * inf); /* squared to temper the effect... */
- }
- mul_v3_fl(vec, fac);
-
- /* 3) Translate back to original space, with the shrinkage applied */
- add_v3_v3v3(&pt->x, gso->dvec, vec);
-
- /* compute lock axis */
- gpsculpt_compute_lock_axis(gso, pt, save_pt);
-
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
-
- /* done */
- return true;
+ bGPDspoint *pt = gps->points + pt_index;
+ float fac, inf;
+ float vec[3];
+ float save_pt[3];
+ copy_v3_v3(save_pt, &pt->x);
+
+ /* Scale down standard influence value to get it more manageable...
+ * - No damping = Unmanageable at > 0.5 strength
+ * - Div 10 = Not enough effect
+ * - Div 5 = Happy medium... (by trial and error)
+ */
+ inf = gp_brush_influence_calc(gso, radius, co) / 5.0f;
+
+ /* 1) Make this point relative to the cursor/midpoint (dvec) */
+ sub_v3_v3v3(vec, &pt->x, gso->dvec);
+
+ /* 2) Shrink the distance by pulling the point towards the midpoint
+ * (0.0 = at midpoint, 1 = at edge of brush region)
+ * OR
+ * Increase the distance (if inverting the brush action!)
+ */
+ if (gp_brush_invert_check(gso)) {
+ /* Inflate (inverse) */
+ fac = 1.0f + (inf * inf); /* squared to temper the effect... */
+ }
+ else {
+ /* Shrink (default) */
+ fac = 1.0f - (inf * inf); /* squared to temper the effect... */
+ }
+ mul_v3_fl(vec, fac);
+
+ /* 3) Translate back to original space, with the shrinkage applied */
+ add_v3_v3v3(&pt->x, gso->dvec, vec);
+
+ /* compute lock axis */
+ gpsculpt_compute_lock_axis(gso, pt, save_pt);
+
+ gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+
+ /* done */
+ return true;
}
/* ----------------------------------------------- */
@@ -703,268 +680,259 @@ static bool gp_brush_pinch_apply(
*/
static bool gp_brush_twist_apply(
- tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
- const int radius, const int co[2])
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index, const int radius, const int co[2])
{
- bGPDspoint *pt = gps->points + pt_index;
- float angle, inf;
- float save_pt[3];
- copy_v3_v3(save_pt, &pt->x);
-
- /* Angle to rotate by */
- inf = gp_brush_influence_calc(gso, radius, co);
- angle = DEG2RADF(1.0f) * inf;
-
- if (gp_brush_invert_check(gso)) {
- /* invert angle that we rotate by */
- angle *= -1;
- }
-
- /* Rotate in 2D or 3D space? */
- if (gps->flag & GP_STROKE_3DSPACE) {
- /* Perform rotation in 3D space... */
- RegionView3D *rv3d = gso->ar->regiondata;
- float rmat[3][3];
- float axis[3];
- float vec[3];
-
- /* Compute rotation matrix - rotate around view vector by angle */
- negate_v3_v3(axis, rv3d->persinv[2]);
- normalize_v3(axis);
-
- axis_angle_normalized_to_mat3(rmat, axis, angle);
-
- /* Rotate point (no matrix-space transforms needed, as GP points are in world space) */
- sub_v3_v3v3(vec, &pt->x, gso->dvec); /* make relative to center
- * (center is stored in dvec) */
- mul_m3_v3(rmat, vec);
- add_v3_v3v3(&pt->x, vec, gso->dvec); /* restore */
-
- /* compute lock axis */
- gpsculpt_compute_lock_axis(gso, pt, save_pt);
- }
- else {
- const float axis[3] = {0.0f, 0.0f, 1.0f};
- float vec[3] = {0.0f};
- float rmat[3][3];
-
- /* Express position of point relative to cursor, ready to rotate */
- // XXX: There is still some offset here, but it's close to working as expected...
- vec[0] = (float)(co[0] - gso->mval[0]);
- vec[1] = (float)(co[1] - gso->mval[1]);
-
- /* rotate point */
- axis_angle_normalized_to_mat3(rmat, axis, angle);
- mul_m3_v3(rmat, vec);
-
- /* Convert back to screen-coordinates */
- vec[0] += (float)gso->mval[0];
- vec[1] += (float)gso->mval[1];
-
- /* Map from screen-coordinates to final coordinate space */
- if (gps->flag & GP_STROKE_2DSPACE) {
- View2D *v2d = gso->gsc.v2d;
- UI_view2d_region_to_view(v2d, vec[0], vec[1], &pt->x, &pt->y);
- }
- else {
- // XXX
- copy_v2_v2(&pt->x, vec);
- }
- }
-
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
-
- /* done */
- return true;
+ bGPDspoint *pt = gps->points + pt_index;
+ float angle, inf;
+ float save_pt[3];
+ copy_v3_v3(save_pt, &pt->x);
+
+ /* Angle to rotate by */
+ inf = gp_brush_influence_calc(gso, radius, co);
+ angle = DEG2RADF(1.0f) * inf;
+
+ if (gp_brush_invert_check(gso)) {
+ /* invert angle that we rotate by */
+ angle *= -1;
+ }
+
+ /* Rotate in 2D or 3D space? */
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ /* Perform rotation in 3D space... */
+ RegionView3D *rv3d = gso->ar->regiondata;
+ float rmat[3][3];
+ float axis[3];
+ float vec[3];
+
+ /* Compute rotation matrix - rotate around view vector by angle */
+ negate_v3_v3(axis, rv3d->persinv[2]);
+ normalize_v3(axis);
+
+ axis_angle_normalized_to_mat3(rmat, axis, angle);
+
+ /* Rotate point (no matrix-space transforms needed, as GP points are in world space) */
+ sub_v3_v3v3(vec, &pt->x, gso->dvec); /* make relative to center
+ * (center is stored in dvec) */
+ mul_m3_v3(rmat, vec);
+ add_v3_v3v3(&pt->x, vec, gso->dvec); /* restore */
+
+ /* compute lock axis */
+ gpsculpt_compute_lock_axis(gso, pt, save_pt);
+ }
+ else {
+ const float axis[3] = {0.0f, 0.0f, 1.0f};
+ float vec[3] = {0.0f};
+ float rmat[3][3];
+
+ /* Express position of point relative to cursor, ready to rotate */
+ // XXX: There is still some offset here, but it's close to working as expected...
+ vec[0] = (float)(co[0] - gso->mval[0]);
+ vec[1] = (float)(co[1] - gso->mval[1]);
+
+ /* rotate point */
+ axis_angle_normalized_to_mat3(rmat, axis, angle);
+ mul_m3_v3(rmat, vec);
+
+ /* Convert back to screen-coordinates */
+ vec[0] += (float)gso->mval[0];
+ vec[1] += (float)gso->mval[1];
+
+ /* Map from screen-coordinates to final coordinate space */
+ if (gps->flag & GP_STROKE_2DSPACE) {
+ View2D *v2d = gso->gsc.v2d;
+ UI_view2d_region_to_view(v2d, vec[0], vec[1], &pt->x, &pt->y);
+ }
+ else {
+ // XXX
+ copy_v2_v2(&pt->x, vec);
+ }
+ }
+
+ gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+
+ /* done */
+ return true;
}
-
/* ----------------------------------------------- */
/* Randomize Brush */
/* Apply some random jitter to the point */
static bool gp_brush_randomize_apply(
- tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
- const int radius, const int co[2])
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index, const int radius, const int co[2])
{
- bGPDspoint *pt = gps->points + pt_index;
- float save_pt[3];
- copy_v3_v3(save_pt, &pt->x);
-
- /* Amount of jitter to apply depends on the distance of the point to the cursor,
- * as well as the strength of the brush
- */
- 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) {
- /* 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
- * view-space as needed.
- */
- float mvec[2], svec[2];
-
- /* mouse movement in ints -> floats */
- mvec[0] = (float)(gso->mval[0] - gso->mval_prev[0]);
- mvec[1] = (float)(gso->mval[1] - gso->mval_prev[1]);
-
- /* rotate mvec by 90 degrees... */
- svec[0] = -mvec[1];
- svec[1] = mvec[0];
-
- /* scale the displacement by the random displacement, and apply */
- if (BLI_rng_get_float(gso->rng) > 0.5f) {
- mul_v2_fl(svec, -fac);
- }
- else {
- mul_v2_fl(svec, fac);
- }
-
- //printf("%f %f (%f), nco = {%f %f}, co = %d %d\n", svec[0], svec[1], fac, nco[0], nco[1], co[0], co[1]);
-
- /* 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);
- }
- }
- 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 (BLI_rng_get_float(gso->rng) > 0.5f) {
- pt->strength += fac;
- }
- else {
- pt->strength -= fac;
- }
- CLAMP_MIN(pt->strength, 0.0f);
- CLAMP_MAX(pt->strength, 1.0f);
- }
- /* apply random to thickness (use pressure) */
- if (gso->settings->flag & GP_SCULPT_SETT_FLAG_APPLY_THICKNESS) {
- if (BLI_rng_get_float(gso->rng) > 0.5f) {
- pt->pressure += fac;
- }
- else {
- pt->pressure -= fac;
- }
- /* only limit lower value */
- CLAMP_MIN(pt->pressure, 0.0f);
- }
- /* apply random to UV (use pressure) */
- if (gso->settings->flag & GP_SCULPT_SETT_FLAG_APPLY_UV) {
- if (BLI_rng_get_float(gso->rng) > 0.5f) {
- pt->uv_rot += fac;
- }
- else {
- pt->uv_rot -= fac;
- }
- CLAMP(pt->uv_rot, -M_PI_2, M_PI_2);
- }
-
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
-
- /* done */
- return true;
+ bGPDspoint *pt = gps->points + pt_index;
+ float save_pt[3];
+ copy_v3_v3(save_pt, &pt->x);
+
+ /* Amount of jitter to apply depends on the distance of the point to the cursor,
+ * as well as the strength of the brush
+ */
+ 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) {
+ /* 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
+ * view-space as needed.
+ */
+ float mvec[2], svec[2];
+
+ /* mouse movement in ints -> floats */
+ mvec[0] = (float)(gso->mval[0] - gso->mval_prev[0]);
+ mvec[1] = (float)(gso->mval[1] - gso->mval_prev[1]);
+
+ /* rotate mvec by 90 degrees... */
+ svec[0] = -mvec[1];
+ svec[1] = mvec[0];
+
+ /* scale the displacement by the random displacement, and apply */
+ if (BLI_rng_get_float(gso->rng) > 0.5f) {
+ mul_v2_fl(svec, -fac);
+ }
+ else {
+ mul_v2_fl(svec, fac);
+ }
+
+ //printf("%f %f (%f), nco = {%f %f}, co = %d %d\n", svec[0], svec[1], fac, nco[0], nco[1], co[0], co[1]);
+
+ /* 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);
+ }
+ }
+ 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 (BLI_rng_get_float(gso->rng) > 0.5f) {
+ pt->strength += fac;
+ }
+ else {
+ pt->strength -= fac;
+ }
+ CLAMP_MIN(pt->strength, 0.0f);
+ CLAMP_MAX(pt->strength, 1.0f);
+ }
+ /* apply random to thickness (use pressure) */
+ if (gso->settings->flag & GP_SCULPT_SETT_FLAG_APPLY_THICKNESS) {
+ if (BLI_rng_get_float(gso->rng) > 0.5f) {
+ pt->pressure += fac;
+ }
+ else {
+ pt->pressure -= fac;
+ }
+ /* only limit lower value */
+ CLAMP_MIN(pt->pressure, 0.0f);
+ }
+ /* apply random to UV (use pressure) */
+ if (gso->settings->flag & GP_SCULPT_SETT_FLAG_APPLY_UV) {
+ if (BLI_rng_get_float(gso->rng) > 0.5f) {
+ pt->uv_rot += fac;
+ }
+ else {
+ pt->uv_rot -= fac;
+ }
+ CLAMP(pt->uv_rot, -M_PI_2, M_PI_2);
+ }
+
+ gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+
+ /* done */
+ return true;
}
/* Weight Paint Brush */
/* Change weight paint for vertex groups */
static bool gp_brush_weight_apply(
- tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
- const int radius, const int co[2])
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index, const int radius, const int co[2])
{
- /* create dvert */
- BKE_gpencil_dvert_ensure(gps);
-
- bGPDspoint *pt = gps->points + pt_index;
- 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);
- 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)) {
- /* reduce weight */
- curweight -= inf;
- }
- else {
- /* increase weight */
- curweight += inf;
- }
-
- /* verify target weight */
- CLAMP_MAX(curweight, gso->gp_brush->weight);
-
- CLAMP(curweight, 0.0f, 1.0f);
- if (dw) {
- dw->weight = curweight;
- }
-
- /* weight should stay within [0.0, 1.0] */
- if (pt->pressure < 0.0f)
- pt->pressure = 0.0f;
-
- return true;
+ /* create dvert */
+ BKE_gpencil_dvert_ensure(gps);
+
+ bGPDspoint *pt = gps->points + pt_index;
+ 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);
+ 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)) {
+ /* reduce weight */
+ curweight -= inf;
+ }
+ else {
+ /* increase weight */
+ curweight += inf;
+ }
+
+ /* verify target weight */
+ CLAMP_MAX(curweight, gso->gp_brush->weight);
+
+ CLAMP(curweight, 0.0f, 1.0f);
+ if (dw) {
+ dw->weight = curweight;
+ }
+
+ /* weight should stay within [0.0, 1.0] */
+ if (pt->pressure < 0.0f)
+ pt->pressure = 0.0f;
+
+ return true;
}
-
-
/* ************************************************ */
/* Non Callback-Based Brushes */
@@ -980,217 +948,218 @@ static bool gp_brush_weight_apply(
/* Custom state data for clone brush */
typedef struct tGPSB_CloneBrushData {
- /* midpoint of the strokes on the clipboard */
- float buffer_midpoint[3];
+ /* midpoint of the strokes on the clipboard */
+ float buffer_midpoint[3];
- /* number of strokes in the paste buffer (and/or to be created each time) */
- size_t totitems;
+ /* number of strokes in the paste buffer (and/or to be created each time) */
+ size_t totitems;
- /* for "stamp" mode, the currently pasted brushes */
- bGPDstroke **new_strokes;
+ /* for "stamp" mode, the currently pasted brushes */
+ bGPDstroke **new_strokes;
- /* mapping from colors referenced per stroke, to the new colours in the "pasted" strokes */
- GHash *new_colors;
+ /* mapping from colors referenced per stroke, to the new colours in the "pasted" strokes */
+ GHash *new_colors;
} tGPSB_CloneBrushData;
/* Initialise "clone" brush data */
static void gp_brush_clone_init(bContext *C, tGP_BrushEditData *gso)
{
- tGPSB_CloneBrushData *data;
- bGPDstroke *gps;
-
- /* init custom data */
- gso->customdata = data = MEM_callocN(sizeof(tGPSB_CloneBrushData), "CloneBrushData");
-
- /* compute midpoint of strokes on clipboard */
- for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
- if (ED_gpencil_stroke_can_use(C, gps)) {
- const float dfac = 1.0f / ((float)gps->totpoints);
- float mid[3] = {0.0f};
-
- bGPDspoint *pt;
- int i;
-
- /* compute midpoint of this stroke */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- float co[3];
-
- mul_v3_v3fl(co, &pt->x, dfac);
- add_v3_v3(mid, co);
- }
-
- /* combine this stroke's data with the main data */
- add_v3_v3(data->buffer_midpoint, mid);
- data->totitems++;
- }
- }
-
- /* Divide the midpoint by the number of strokes, to finish averaging it */
- if (data->totitems > 1) {
- mul_v3_fl(data->buffer_midpoint, 1.0f / (float)data->totitems);
- }
-
- /* Create a buffer for storing the current strokes */
- if (1 /*gso->brush->mode == GP_EDITBRUSH_CLONE_MODE_STAMP*/) {
- data->new_strokes = MEM_callocN(sizeof(bGPDstroke *) * data->totitems, "cloned strokes ptr array");
- }
-
- /* Init colormap for mapping between the pasted stroke's source color (names)
- * and the final colours that will be used here instead.
- */
- data->new_colors = gp_copybuf_validate_colormap(C);
+ tGPSB_CloneBrushData *data;
+ bGPDstroke *gps;
+
+ /* init custom data */
+ gso->customdata = data = MEM_callocN(sizeof(tGPSB_CloneBrushData), "CloneBrushData");
+
+ /* compute midpoint of strokes on clipboard */
+ for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
+ if (ED_gpencil_stroke_can_use(C, gps)) {
+ const float dfac = 1.0f / ((float)gps->totpoints);
+ float mid[3] = {0.0f};
+
+ bGPDspoint *pt;
+ int i;
+
+ /* compute midpoint of this stroke */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ float co[3];
+
+ mul_v3_v3fl(co, &pt->x, dfac);
+ add_v3_v3(mid, co);
+ }
+
+ /* combine this stroke's data with the main data */
+ add_v3_v3(data->buffer_midpoint, mid);
+ data->totitems++;
+ }
+ }
+
+ /* Divide the midpoint by the number of strokes, to finish averaging it */
+ if (data->totitems > 1) {
+ mul_v3_fl(data->buffer_midpoint, 1.0f / (float)data->totitems);
+ }
+
+ /* Create a buffer for storing the current strokes */
+ if (1 /*gso->brush->mode == GP_EDITBRUSH_CLONE_MODE_STAMP*/) {
+ data->new_strokes = MEM_callocN(sizeof(bGPDstroke *) * data->totitems,
+ "cloned strokes ptr array");
+ }
+
+ /* Init colormap for mapping between the pasted stroke's source color (names)
+ * and the final colours that will be used here instead.
+ */
+ data->new_colors = gp_copybuf_validate_colormap(C);
}
/* Free custom data used for "clone" brush */
static void gp_brush_clone_free(tGP_BrushEditData *gso)
{
- tGPSB_CloneBrushData *data = gso->customdata;
-
- /* free strokes array */
- if (data->new_strokes) {
- MEM_freeN(data->new_strokes);
- data->new_strokes = NULL;
- }
-
- /* free copybuf colormap */
- if (data->new_colors) {
- BLI_ghash_free(data->new_colors, NULL, NULL);
- data->new_colors = NULL;
- }
-
- /* free the customdata itself */
- MEM_freeN(data);
- gso->customdata = NULL;
+ tGPSB_CloneBrushData *data = gso->customdata;
+
+ /* free strokes array */
+ if (data->new_strokes) {
+ MEM_freeN(data->new_strokes);
+ data->new_strokes = NULL;
+ }
+
+ /* free copybuf colormap */
+ if (data->new_colors) {
+ BLI_ghash_free(data->new_colors, NULL, NULL);
+ data->new_colors = NULL;
+ }
+
+ /* free the customdata itself */
+ MEM_freeN(data);
+ gso->customdata = NULL;
}
/* Create new copies of the strokes on the clipboard */
static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
{
- tGPSB_CloneBrushData *data = gso->customdata;
-
- Object *ob = CTX_data_active_object(C);
- bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
-
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_ADD_NEW);
- bGPDstroke *gps;
-
- float delta[3];
- size_t strokes_added = 0;
-
- /* Compute amount to offset the points by */
- /* NOTE: This assumes that screenspace strokes are NOT used in the 3D view... */
-
- gp_brush_calc_midpoint(gso); /* this puts the cursor location into gso->dvec */
- sub_v3_v3v3(delta, gso->dvec, data->buffer_midpoint);
-
- /* Copy each stroke into the layer */
- for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
- if (ED_gpencil_stroke_can_use(C, gps)) {
- bGPDstroke *new_stroke;
- bGPDspoint *pt;
- int i;
-
- /* 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->next = new_stroke->prev = NULL;
- BLI_addtail(&gpf->strokes, new_stroke);
-
- /* Fix color references */
- Material *ma = BLI_ghash_lookup(data->new_colors, &new_stroke->mat_nr);
- gps->mat_nr = BKE_gpencil_object_material_get_index(ob, ma);
- if (!ma || gps->mat_nr) {
- gps->mat_nr = 0;
- }
- /* Adjust all the stroke's points, so that the strokes
- * get pasted relative to where the cursor is now
- */
- for (i = 0, pt = new_stroke->points; i < new_stroke->totpoints; i++, pt++) {
- /* assume that the delta can just be applied, and then everything works */
- add_v3_v3(&pt->x, delta);
- }
-
- /* Store ref for later */
- if ((data->new_strokes) && (strokes_added < data->totitems)) {
- data->new_strokes[strokes_added] = new_stroke;
- strokes_added++;
- }
- }
- }
+ tGPSB_CloneBrushData *data = gso->customdata;
+
+ Object *ob = CTX_data_active_object(C);
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_ADD_NEW);
+ bGPDstroke *gps;
+
+ float delta[3];
+ size_t strokes_added = 0;
+
+ /* Compute amount to offset the points by */
+ /* NOTE: This assumes that screenspace strokes are NOT used in the 3D view... */
+
+ gp_brush_calc_midpoint(gso); /* this puts the cursor location into gso->dvec */
+ sub_v3_v3v3(delta, gso->dvec, data->buffer_midpoint);
+
+ /* Copy each stroke into the layer */
+ for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
+ if (ED_gpencil_stroke_can_use(C, gps)) {
+ bGPDstroke *new_stroke;
+ bGPDspoint *pt;
+ int i;
+
+ /* 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->next = new_stroke->prev = NULL;
+ BLI_addtail(&gpf->strokes, new_stroke);
+
+ /* Fix color references */
+ Material *ma = BLI_ghash_lookup(data->new_colors, &new_stroke->mat_nr);
+ gps->mat_nr = BKE_gpencil_object_material_get_index(ob, ma);
+ if (!ma || gps->mat_nr) {
+ gps->mat_nr = 0;
+ }
+ /* Adjust all the stroke's points, so that the strokes
+ * get pasted relative to where the cursor is now
+ */
+ for (i = 0, pt = new_stroke->points; i < new_stroke->totpoints; i++, pt++) {
+ /* assume that the delta can just be applied, and then everything works */
+ add_v3_v3(&pt->x, delta);
+ }
+
+ /* Store ref for later */
+ if ((data->new_strokes) && (strokes_added < data->totitems)) {
+ data->new_strokes[strokes_added] = new_stroke;
+ strokes_added++;
+ }
+ }
+ }
}
/* Move newly-added strokes around - "Stamp" mode of the Clone brush */
static void gp_brush_clone_adjust(tGP_BrushEditData *gso)
{
- tGPSB_CloneBrushData *data = gso->customdata;
- size_t snum;
-
- /* Compute the amount of movement to apply (overwrites dvec) */
- gp_brush_grab_calc_dvec(gso);
-
- /* For each of the stored strokes, apply the offset to each point */
- /* NOTE: Again this assumes that in the 3D view, we only have 3d space and not screenspace strokes... */
- for (snum = 0; snum < data->totitems; snum++) {
- bGPDstroke *gps = data->new_strokes[snum];
- bGPDspoint *pt;
- 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;
-
- /* 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);
-
- /* 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);
- }
- }
- }
+ tGPSB_CloneBrushData *data = gso->customdata;
+ size_t snum;
+
+ /* Compute the amount of movement to apply (overwrites dvec) */
+ gp_brush_grab_calc_dvec(gso);
+
+ /* For each of the stored strokes, apply the offset to each point */
+ /* NOTE: Again this assumes that in the 3D view, we only have 3d space and not screenspace strokes... */
+ for (snum = 0; snum < data->totitems; snum++) {
+ bGPDstroke *gps = data->new_strokes[snum];
+ bGPDspoint *pt;
+ 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;
+
+ /* 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);
+
+ /* 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);
+ }
+ }
+ }
}
/* Entrypoint for applying "clone" brush */
static bool gpsculpt_brush_apply_clone(bContext *C, tGP_BrushEditData *gso)
{
- /* Which "mode" are we operating in? */
- if (gso->first) {
- /* Create initial clones */
- gp_brush_clone_add(C, gso);
- }
- else {
- /* Stamp or Continuous Mode */
- if (1 /*gso->brush->mode == GP_EDITBRUSH_CLONE_MODE_STAMP*/) {
- /* Stamp - Proceed to translate the newly added strokes */
- gp_brush_clone_adjust(gso);
- }
- else {
- /* Continuous - Just keep pasting everytime we move */
- /* TODO: The spacing of repeat should be controlled using a "stepsize" or similar property? */
- gp_brush_clone_add(C, gso);
- }
- }
-
- return true;
+ /* Which "mode" are we operating in? */
+ if (gso->first) {
+ /* Create initial clones */
+ gp_brush_clone_add(C, gso);
+ }
+ else {
+ /* Stamp or Continuous Mode */
+ if (1 /*gso->brush->mode == GP_EDITBRUSH_CLONE_MODE_STAMP*/) {
+ /* Stamp - Proceed to translate the newly added strokes */
+ gp_brush_clone_adjust(gso);
+ }
+ else {
+ /* Continuous - Just keep pasting everytime we move */
+ /* TODO: The spacing of repeat should be controlled using a "stepsize" or similar property? */
+ gp_brush_clone_add(C, gso);
+ }
+ }
+
+ return true;
}
/* ************************************************ */
@@ -1198,18 +1167,19 @@ 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;
- char str[UI_MAX_DRAW_STR] = "";
+ const char *brush_name = NULL;
+ char str[UI_MAX_DRAW_STR] = "";
- RNA_enum_name(rna_enum_gpencil_sculpt_brush_items, gso->brush_type, &brush_name);
+ RNA_enum_name(rna_enum_gpencil_sculpt_brush_items, gso->brush_type, &brush_name);
- BLI_snprintf(str, sizeof(str),
- IFACE_("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 : "<?>");
+ BLI_snprintf(str,
+ sizeof(str),
+ IFACE_("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 : "<?>");
- ED_workspace_status_text(C, str);
+ ED_workspace_status_text(C, str);
}
/* ************************************************ */
@@ -1219,586 +1189,576 @@ 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);
- Object *ob = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = CTX_data_active_object(C);
- const bool is_weight_mode = ob->mode == OB_MODE_WEIGHT_GPENCIL;
- /* set the brush using the tool */
+ 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;
+ 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_depsgraph(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);
- rng_seed ^= POINTER_AS_UINT(gso);
- gso->rng = BLI_rng_new(rng_seed);
-
- gso->is_painting = false;
- gso->first = true;
-
- 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) {
- gso->vrgroup = ob->actdef - 1;
- if (!BLI_findlink(&ob->defbase, gso->vrgroup)) {
- gso->vrgroup = -1;
- }
- }
- else {
- gso->vrgroup = - 1;
- }
-
- gso->sa = CTX_wm_area(C);
- gso->ar = 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) {
- curvemapping_initialize(ts->gp_sculpt.cur_falloff);
- }
-
- /* initialise custom data for brushes */
- switch (gso->brush_type) {
- case GP_SCULPT_TYPE_CLONE:
- {
- bGPDstroke *gps;
- bool found = false;
-
- /* check that there are some usable strokes in the buffer */
- for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
- if (ED_gpencil_stroke_can_use(C, gps)) {
- found = true;
- break;
- }
- }
-
- if (found == false) {
- /* STOP HERE! Nothing to paste! */
- BKE_report(op->reports, RPT_ERROR,
- "Copy some strokes to the clipboard before using the Clone brush to paste copies of them");
-
- MEM_freeN(gso);
- op->customdata = NULL;
- return false;
- }
- else {
- /* initialise customdata */
- gp_brush_clone_init(C, gso);
- }
- break;
- }
-
- case GP_SCULPT_TYPE_GRAB:
- {
- /* initialise the cache needed for this brush */
- gso->stroke_customdata = BLI_ghash_ptr_new("GP Grab Brush - Strokes Hash");
- break;
- }
-
- /* Others - No customdata needed */
- default:
- break;
- }
-
-
- /* setup space conversions */
- gp_point_conversion_init(C, &gso->gsc);
-
- /* update header */
- gpsculpt_brush_header_set(C, gso);
-
- /* setup cursor drawing */
- //WM_cursor_modal_set(CTX_wm_window(C), BC_CROSSCURSOR);
- if (gso->sa->spacetype != SPACE_VIEW3D) {
- ED_gpencil_toggle_brush_cursor(C, true, NULL);
- }
- return true;
+ tGP_BrushEditData *gso;
+
+ /* setup operator data */
+ gso = MEM_callocN(sizeof(tGP_BrushEditData), "tGP_BrushEditData");
+ op->customdata = gso;
+
+ gso->depsgraph = CTX_data_depsgraph(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);
+ rng_seed ^= POINTER_AS_UINT(gso);
+ gso->rng = BLI_rng_new(rng_seed);
+
+ gso->is_painting = false;
+ gso->first = true;
+
+ 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) {
+ gso->vrgroup = ob->actdef - 1;
+ if (!BLI_findlink(&ob->defbase, gso->vrgroup)) {
+ gso->vrgroup = -1;
+ }
+ }
+ else {
+ gso->vrgroup = -1;
+ }
+
+ gso->sa = CTX_wm_area(C);
+ gso->ar = 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) {
+ curvemapping_initialize(ts->gp_sculpt.cur_falloff);
+ }
+
+ /* initialise custom data for brushes */
+ switch (gso->brush_type) {
+ case GP_SCULPT_TYPE_CLONE: {
+ bGPDstroke *gps;
+ bool found = false;
+
+ /* check that there are some usable strokes in the buffer */
+ for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
+ if (ED_gpencil_stroke_can_use(C, gps)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found == false) {
+ /* STOP HERE! Nothing to paste! */
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Copy some strokes to the clipboard before using the Clone brush to paste "
+ "copies of them");
+
+ MEM_freeN(gso);
+ op->customdata = NULL;
+ return false;
+ }
+ else {
+ /* initialise customdata */
+ gp_brush_clone_init(C, gso);
+ }
+ break;
+ }
+
+ case GP_SCULPT_TYPE_GRAB: {
+ /* initialise the cache needed for this brush */
+ gso->stroke_customdata = BLI_ghash_ptr_new("GP Grab Brush - Strokes Hash");
+ break;
+ }
+
+ /* Others - No customdata needed */
+ default:
+ break;
+ }
+
+ /* setup space conversions */
+ gp_point_conversion_init(C, &gso->gsc);
+
+ /* update header */
+ gpsculpt_brush_header_set(C, gso);
+
+ /* setup cursor drawing */
+ //WM_cursor_modal_set(CTX_wm_window(C), BC_CROSSCURSOR);
+ if (gso->sa->spacetype != SPACE_VIEW3D) {
+ ED_gpencil_toggle_brush_cursor(C, true, NULL);
+ }
+ return true;
}
static void gpsculpt_brush_exit(bContext *C, wmOperator *op)
{
- tGP_BrushEditData *gso = op->customdata;
- wmWindow *win = CTX_wm_window(C);
-
- /* free brush-specific data */
- switch (gso->brush_type) {
- case GP_SCULPT_TYPE_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
- */
- BLI_ghash_free(gso->stroke_customdata, NULL, gp_brush_grab_stroke_free);
- break;
- }
-
- case GP_SCULPT_TYPE_CLONE:
- {
- /* Free customdata */
- gp_brush_clone_free(gso);
- break;
- }
-
- default:
- break;
- }
-
- /* unregister timer (only used for realtime) */
- if (gso->timer) {
- WM_event_remove_timer(CTX_wm_manager(C), win, gso->timer);
- }
-
- if (gso->rng != NULL) {
- BLI_rng_free(gso->rng);
- }
-
- /* disable cursor and 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;
-
- /* free operator data */
- MEM_freeN(gso);
- op->customdata = NULL;
+ tGP_BrushEditData *gso = op->customdata;
+ wmWindow *win = CTX_wm_window(C);
+
+ /* free brush-specific data */
+ switch (gso->brush_type) {
+ case GP_SCULPT_TYPE_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
+ */
+ BLI_ghash_free(gso->stroke_customdata, NULL, gp_brush_grab_stroke_free);
+ break;
+ }
+
+ case GP_SCULPT_TYPE_CLONE: {
+ /* Free customdata */
+ gp_brush_clone_free(gso);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* unregister timer (only used for realtime) */
+ if (gso->timer) {
+ WM_event_remove_timer(CTX_wm_manager(C), win, gso->timer);
+ }
+
+ if (gso->rng != NULL) {
+ BLI_rng_free(gso->rng);
+ }
+
+ /* disable cursor and 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;
+
+ /* free operator data */
+ MEM_freeN(gso);
+ op->customdata = NULL;
}
/* poll callback for stroke sculpting operator(s) */
static bool gpsculpt_brush_poll(bContext *C)
{
- /* NOTE: this is a bit slower, but is the most accurate... */
- return CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0;
+ /* NOTE: this is a bit slower, but is the most accurate... */
+ return CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0;
}
/* Init Sculpt Stroke ---------------------------------- */
static void gpsculpt_brush_init_stroke(tGP_BrushEditData *gso)
{
- bGPdata *gpd = gso->gpd;
-
- bGPDlayer *gpl;
- int cfra_eval = (int)DEG_get_ctime(gso->depsgraph);
-
- /* only try to add a new frame if this is the first stroke, or the frame has changed */
- if ((gpd == NULL) || (cfra_eval == gso->cfra))
- return;
-
- /* go through each layer, and ensure that we've got a valid frame to use */
- 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)) {
- bGPDframe *gpf = gpl->actframe;
-
- /* Make a new frame to work on if the layer's frame and the current scene frame don't match up
- * - This is useful when animating as it saves that "uh-oh" moment when you realize you've
- * spent too much time editing the wrong frame...
- */
- // XXX: should this be allowed when framelock is enabled?
- if (gpf->framenum != cfra_eval) {
- BKE_gpencil_frame_addcopy(gpl, cfra_eval);
- }
- }
- }
-
- /* save off new current frame, so that next update works fine */
- gso->cfra = cfra_eval;
+ bGPdata *gpd = gso->gpd;
+
+ bGPDlayer *gpl;
+ int cfra_eval = (int)DEG_get_ctime(gso->depsgraph);
+
+ /* only try to add a new frame if this is the first stroke, or the frame has changed */
+ if ((gpd == NULL) || (cfra_eval == gso->cfra))
+ return;
+
+ /* go through each layer, and ensure that we've got a valid frame to use */
+ 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)) {
+ bGPDframe *gpf = gpl->actframe;
+
+ /* Make a new frame to work on if the layer's frame and the current scene frame don't match up
+ * - This is useful when animating as it saves that "uh-oh" moment when you realize you've
+ * spent too much time editing the wrong frame...
+ */
+ // XXX: should this be allowed when framelock is enabled?
+ if (gpf->framenum != cfra_eval) {
+ BKE_gpencil_frame_addcopy(gpl, cfra_eval);
+ }
+ }
+ }
+
+ /* save off new current frame, so that next update works fine */
+ gso->cfra = cfra_eval;
}
/* Apply ----------------------------------------------- */
/* Apply brush operation to points in this stroke */
-static bool gpsculpt_brush_do_stroke(
- tGP_BrushEditData *gso, bGPDstroke *gps,
- float diff_mat[4][4], GP_BrushApplyCb apply)
+static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso,
+ bGPDstroke *gps,
+ float diff_mat[4][4],
+ GP_BrushApplyCb apply)
{
- 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;
-
- bGPDspoint *pt1, *pt2;
- int pc1[2] = {0};
- int pc2[2] = {0};
- int i;
- bool include_last = false;
- bool changed = false;
-
- if (gps->totpoints == 1) {
- bGPDspoint pt_temp;
- gp_point_to_parent_space(gps->points, diff_mat, &pt_temp);
- gp_point_to_xy(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])) {
- /* 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 */
- changed = apply(gso, gps, 0, radius, 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 (gso->settings->flag & GP_SCULPT_SETT_FLAG_SELECT_MASK) {
- 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, gso->mval_prev, radius, pc1[0], pc1[1], pc2[0], pc2[1])) {
- /* Apply operation to these points */
- bool ok = false;
-
- /* To each point individually... */
- ok = apply(gso, gps, i, radius, 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) {
- ok |= apply(gso, gps, i + 1, radius, pc2);
- include_last = false;
- }
- else {
- include_last = true;
- }
-
- changed |= ok;
- }
- 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)
- */
- changed |= apply(gso, gps, i, radius, pc1);
- include_last = false;
- }
- }
- }
- }
-
- return changed;
+ 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;
+
+ bGPDspoint *pt1, *pt2;
+ int pc1[2] = {0};
+ int pc2[2] = {0};
+ int i;
+ bool include_last = false;
+ bool changed = false;
+
+ if (gps->totpoints == 1) {
+ bGPDspoint pt_temp;
+ gp_point_to_parent_space(gps->points, diff_mat, &pt_temp);
+ gp_point_to_xy(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])) {
+ /* 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 */
+ changed = apply(gso, gps, 0, radius, 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 (gso->settings->flag & GP_SCULPT_SETT_FLAG_SELECT_MASK) {
+ 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, gso->mval_prev, radius, pc1[0], pc1[1], pc2[0], pc2[1])) {
+ /* Apply operation to these points */
+ bool ok = false;
+
+ /* To each point individually... */
+ ok = apply(gso, gps, i, radius, 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) {
+ ok |= apply(gso, gps, i + 1, radius, pc2);
+ include_last = false;
+ }
+ else {
+ include_last = true;
+ }
+
+ changed |= ok;
+ }
+ 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)
+ */
+ changed |= apply(gso, gps, i, radius, pc1);
+ include_last = false;
+ }
+ }
+ }
+ }
+
+ return changed;
}
/* Apply sculpt brushes to strokes in the given frame */
static bool gpsculpt_brush_do_frame(
- bContext *C, tGP_BrushEditData *gso,
- bGPDlayer *gpl, bGPDframe *gpf,
- float diff_mat[4][4])
+ bContext *C, tGP_BrushEditData *gso, bGPDlayer *gpl, bGPDframe *gpf, float diff_mat[4][4])
{
- bool changed = false;
- Object *ob = CTX_data_active_object(C);
-
- 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;
- }
- /* check if the color is editable */
- if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
- continue;
- }
-
- switch (gso->brush_type) {
- case GP_SCULPT_TYPE_SMOOTH: /* Smooth strokes */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_smooth_apply);
- break;
- }
-
- case GP_SCULPT_TYPE_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 */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_strength_apply);
- break;
- }
-
- case GP_SCULPT_TYPE_GRAB: /* Grab points */
- {
- if (gso->first) {
- /* First time this brush stroke is being applied:
- * 1) Prepare data buffers (init/clear) for this stroke
- * 2) Use the points now under the cursor
- */
- gp_brush_grab_stroke_init(gso, gps);
- changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_grab_store_points);
- }
- else {
- /* Apply effect to the stored points */
- gp_brush_grab_apply_cached(gso, gps, diff_mat);
- changed |= true;
- }
- break;
- }
-
- case GP_SCULPT_TYPE_PUSH: /* Push points */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_push_apply);
- break;
- }
-
- case GP_SCULPT_TYPE_PINCH: /* Pinch points */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_pinch_apply);
- break;
- }
-
- case GP_SCULPT_TYPE_TWIST: /* Twist points around midpoint */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_twist_apply);
- break;
- }
-
- case GP_SCULPT_TYPE_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);
- break;
- }
-
-
- default:
- printf("ERROR: Unknown type of GPencil Sculpt brush - %u\n", gso->brush_type);
- break;
- }
- /* Triangulation must be calculated if changed */
- if (changed) {
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
- }
- }
-
- return changed;
+ bool changed = false;
+ Object *ob = CTX_data_active_object(C);
+
+ 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;
+ }
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
+ continue;
+ }
+
+ switch (gso->brush_type) {
+ case GP_SCULPT_TYPE_SMOOTH: /* Smooth strokes */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_smooth_apply);
+ break;
+ }
+
+ case GP_SCULPT_TYPE_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 */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_strength_apply);
+ break;
+ }
+
+ case GP_SCULPT_TYPE_GRAB: /* Grab points */
+ {
+ if (gso->first) {
+ /* First time this brush stroke is being applied:
+ * 1) Prepare data buffers (init/clear) for this stroke
+ * 2) Use the points now under the cursor
+ */
+ gp_brush_grab_stroke_init(gso, gps);
+ changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_grab_store_points);
+ }
+ else {
+ /* Apply effect to the stored points */
+ gp_brush_grab_apply_cached(gso, gps, diff_mat);
+ changed |= true;
+ }
+ break;
+ }
+
+ case GP_SCULPT_TYPE_PUSH: /* Push points */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_push_apply);
+ break;
+ }
+
+ case GP_SCULPT_TYPE_PINCH: /* Pinch points */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_pinch_apply);
+ break;
+ }
+
+ case GP_SCULPT_TYPE_TWIST: /* Twist points around midpoint */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_twist_apply);
+ break;
+ }
+
+ case GP_SCULPT_TYPE_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);
+ break;
+ }
+
+ default:
+ printf("ERROR: Unknown type of GPencil Sculpt brush - %u\n", gso->brush_type);
+ break;
+ }
+ /* Triangulation must be calculated if changed */
+ if (changed) {
+ gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gps->tot_triangles = 0;
+ }
+ }
+
+ return changed;
}
/* 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_depsgraph(C);
- Object *obact = gso->object;
- bGPdata *gpd = gso->gpd;
- bool changed = false;
-
- /* 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 */
- {
- /* calculate amount of displacement to apply */
- gp_brush_grab_calc_dvec(gso);
- break;
- }
-
- case GP_SCULPT_TYPE_PINCH: /* Pinch points */
- case GP_SCULPT_TYPE_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 */
- {
- /* compute the displacement vector for the cursor (in data space) */
- gp_brush_grab_calc_dvec(gso);
- break;
- }
-
- default:
- break;
- }
-
-
- /* Find visible strokes, and perform operations on those if hit */
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- /* If no active frame, don't do anything... */
- if (gpl->actframe == NULL) {
- continue;
- }
-
- /* calculate difference matrix */
- float diff_mat[4][4];
- ED_gpencil_parent_location(depsgraph, obact, gpd, 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_get_range_selected(gpl, &f_init, &f_end);
- }
-
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- /* 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) */
- 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 |= gpsculpt_brush_do_frame(C, gso, gpl, gpf, diff_mat);
- }
- }
- }
- else {
- /* 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;
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *obact = gso->object;
+ bGPdata *gpd = gso->gpd;
+ bool changed = false;
+
+ /* 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 */
+ {
+ /* calculate amount of displacement to apply */
+ gp_brush_grab_calc_dvec(gso);
+ break;
+ }
+
+ case GP_SCULPT_TYPE_PINCH: /* Pinch points */
+ case GP_SCULPT_TYPE_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 */
+ {
+ /* compute the displacement vector for the cursor (in data space) */
+ gp_brush_grab_calc_dvec(gso);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* Find visible strokes, and perform operations on those if hit */
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ /* If no active frame, don't do anything... */
+ if (gpl->actframe == NULL) {
+ continue;
+ }
+
+ /* calculate difference matrix */
+ float diff_mat[4][4];
+ ED_gpencil_parent_location(depsgraph, obact, gpd, 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_get_range_selected(gpl, &f_init, &f_end);
+ }
+
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ /* 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) */
+ 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 |= gpsculpt_brush_do_frame(C, gso, gpl, gpf, diff_mat);
+ }
+ }
+ }
+ else {
+ /* 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;
}
/* Calculate settings for applying brush */
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);
- 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_SCULPT_FLAG_INVERT;
- else
- gso->flag &= ~GP_SCULPT_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;
-
-
- /* Apply brush */
- if (gso->brush_type == GP_SCULPT_TYPE_CLONE) {
- changed = gpsculpt_brush_apply_clone(C, gso);
- }
- else {
- changed = gpsculpt_brush_apply_standard(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;
+ 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);
+ 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_SCULPT_FLAG_INVERT;
+ else
+ gso->flag &= ~GP_SCULPT_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;
+
+ /* Apply brush */
+ if (gso->brush_type == GP_SCULPT_TYPE_CLONE) {
+ changed = gpsculpt_brush_apply_clone(C, gso);
+ }
+ else {
+ changed = gpsculpt_brush_apply_standard(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 --------------------------------------------- */
@@ -1806,370 +1766,380 @@ static void gpsculpt_brush_apply(bContext *C, wmOperator *op, PointerRNA *itempt
/* 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];
- int tablet = 0;
-
- 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) */
- if (event->tablet_data) {
- const wmTabletData *wmtab = event->tablet_data;
- float pressure = wmtab->Pressure;
-
- tablet = (wmtab->Active != EVT_TABLET_NONE);
-
- /* special exception here for too high pressure values on first touch in
- * windows for some tablets: clamp the values to be sane
- */
- if (tablet && (pressure >= 0.99f)) {
- pressure = 1.0f;
- }
- RNA_float_set(&itemptr, "pressure", pressure);
- }
- else {
- RNA_float_set(&itemptr, "pressure", 1.0f);
- }
-
- if (!gso->is_weight_mode) {
- if (event->shift) {
- gso->gp_brush_old = gso->gp_brush;
- gso->brush_type_old = gso->brush_type;
-
- gso->gp_brush = &gset->brush[GP_SCULPT_TYPE_SMOOTH];
- gso->brush_type = GP_SCULPT_TYPE_SMOOTH;
- }
- else {
- if (gso->gp_brush_old != NULL) {
- gso->gp_brush = gso->gp_brush_old;
- gso->brush_type = gso->brush_type_old;
- }
- }
- }
-
- /* apply */
- gpsculpt_brush_apply(C, op, &itemptr);
+ tGP_BrushEditData *gso = op->customdata;
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ GP_Sculpt_Settings *gset = &ts->gp_sculpt;
+ PointerRNA itemptr;
+ float mouse[2];
+ int tablet = 0;
+
+ 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) */
+ if (event->tablet_data) {
+ const wmTabletData *wmtab = event->tablet_data;
+ float pressure = wmtab->Pressure;
+
+ tablet = (wmtab->Active != EVT_TABLET_NONE);
+
+ /* special exception here for too high pressure values on first touch in
+ * windows for some tablets: clamp the values to be sane
+ */
+ if (tablet && (pressure >= 0.99f)) {
+ pressure = 1.0f;
+ }
+ RNA_float_set(&itemptr, "pressure", pressure);
+ }
+ else {
+ RNA_float_set(&itemptr, "pressure", 1.0f);
+ }
+
+ if (!gso->is_weight_mode) {
+ if (event->shift) {
+ gso->gp_brush_old = gso->gp_brush;
+ gso->brush_type_old = gso->brush_type;
+
+ gso->gp_brush = &gset->brush[GP_SCULPT_TYPE_SMOOTH];
+ gso->brush_type = GP_SCULPT_TYPE_SMOOTH;
+ }
+ else {
+ if (gso->gp_brush_old != NULL) {
+ gso->gp_brush = gso->gp_brush_old;
+ gso->brush_type = gso->brush_type_old;
+ }
+ }
+ }
+
+ /* apply */
+ gpsculpt_brush_apply(C, op, &itemptr);
}
/* reapply */
static int gpsculpt_brush_exec(bContext *C, wmOperator *op)
{
- if (!gpsculpt_brush_init(C, op))
- return OPERATOR_CANCELLED;
+ if (!gpsculpt_brush_init(C, op))
+ return OPERATOR_CANCELLED;
- RNA_BEGIN(op->ptr, itemptr, "stroke")
- {
- gpsculpt_brush_apply(C, op, &itemptr);
- }
- RNA_END;
+ RNA_BEGIN (op->ptr, itemptr, "stroke") {
+ gpsculpt_brush_apply(C, op, &itemptr);
+ }
+ RNA_END;
- gpsculpt_brush_exit(C, op);
+ gpsculpt_brush_exit(C, op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
/* start modal painting */
static int gpsculpt_brush_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- tGP_BrushEditData *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;
- bool needs_timer = false;
- float brush_rate = 0.0f;
-
- /* the operator cannot work while play animation */
- if (is_playing) {
- BKE_report(op->reports, RPT_ERROR, "Cannot sculpt while play animation");
-
- return OPERATOR_CANCELLED;
- }
-
- /* init painting data */
- if (!gpsculpt_brush_init(C, op))
- return OPERATOR_CANCELLED;
-
- gso = op->customdata;
-
- /* initialise type-specific data (used for the entire session) */
- switch (gso->brush_type) {
- /* Brushes requiring timer... */
- case GP_SCULPT_TYPE_THICKNESS:
- brush_rate = 0.01f; // XXX: hardcoded
- needs_timer = true;
- break;
-
- case GP_SCULPT_TYPE_STRENGTH:
- brush_rate = 0.01f; // XXX: hardcoded
- needs_timer = true;
- break;
-
- case GP_SCULPT_TYPE_PINCH:
- brush_rate = 0.001f; // XXX: hardcoded
- needs_timer = true;
- break;
-
- case GP_SCULPT_TYPE_TWIST:
- brush_rate = 0.01f; // XXX: hardcoded
- needs_timer = true;
- break;
-
- default:
- break;
- }
-
- /* register timer for increasing influence by hovering over an area */
- if (needs_timer) {
- gso->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, brush_rate);
- }
-
- /* register modal handler */
- WM_event_add_modal_handler(C, op);
-
- /* start drawing immediately? */
- if (is_modal == false) {
- ARegion *ar = CTX_wm_region(C);
-
- /* ensure that we'll have a new frame to draw on */
- gpsculpt_brush_init_stroke(gso);
-
- /* apply first dab... */
- gso->is_painting = true;
- gpsculpt_brush_apply_event(C, op, event);
-
- /* redraw view with feedback */
- ED_region_tag_redraw(ar);
- }
-
- return OPERATOR_RUNNING_MODAL;
+ tGP_BrushEditData *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;
+ bool needs_timer = false;
+ float brush_rate = 0.0f;
+
+ /* the operator cannot work while play animation */
+ if (is_playing) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot sculpt while play animation");
+
+ return OPERATOR_CANCELLED;
+ }
+
+ /* init painting data */
+ if (!gpsculpt_brush_init(C, op))
+ return OPERATOR_CANCELLED;
+
+ gso = op->customdata;
+
+ /* initialise type-specific data (used for the entire session) */
+ switch (gso->brush_type) {
+ /* Brushes requiring timer... */
+ case GP_SCULPT_TYPE_THICKNESS:
+ brush_rate = 0.01f; // XXX: hardcoded
+ needs_timer = true;
+ break;
+
+ case GP_SCULPT_TYPE_STRENGTH:
+ brush_rate = 0.01f; // XXX: hardcoded
+ needs_timer = true;
+ break;
+
+ case GP_SCULPT_TYPE_PINCH:
+ brush_rate = 0.001f; // XXX: hardcoded
+ needs_timer = true;
+ break;
+
+ case GP_SCULPT_TYPE_TWIST:
+ brush_rate = 0.01f; // XXX: hardcoded
+ needs_timer = true;
+ break;
+
+ default:
+ break;
+ }
+
+ /* register timer for increasing influence by hovering over an area */
+ if (needs_timer) {
+ gso->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, brush_rate);
+ }
+
+ /* register modal handler */
+ WM_event_add_modal_handler(C, op);
+
+ /* start drawing immediately? */
+ if (is_modal == false) {
+ ARegion *ar = CTX_wm_region(C);
+
+ /* ensure that we'll have a new frame to draw on */
+ gpsculpt_brush_init_stroke(gso);
+
+ /* apply first dab... */
+ gso->is_painting = true;
+ gpsculpt_brush_apply_event(C, op, event);
+
+ /* redraw view with feedback */
+ ED_region_tag_redraw(ar);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
/* painting - handle events */
static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- tGP_BrushEditData *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 */
- gpsculpt_brush_apply_event(C, op, event);
-
- /* force redraw, so that the cursor will at least be valid */
- redraw_region = true;
- break;
-
- /* Timer Tick - Only if this was our own timer */
- case TIMER:
- if (event->customdata == gso->timer) {
- gso->timerTick = true;
- gpsculpt_brush_apply_event(C, op, event);
- gso->timerTick = false;
- }
- 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);
- if (is_modal) {
- /* go back to idling... */
- gso->is_painting = false;
- }
- else {
- /* end sculpt session, since we're not modal */
- gso->is_painting = false;
-
- gpsculpt_brush_exit(C, op);
- return OPERATOR_FINISHED;
- }
- break;
-
- /* Abort painting if any of the usual things are tried */
- case MIDDLEMOUSE:
- case RIGHTMOUSE:
- case ESCKEY:
- gpsculpt_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;
-
- gpsculpt_brush_init_stroke(gso);
- gpsculpt_brush_apply_event(C, op, event);
- break;
-
- /* Exit modal operator, based on the "standard" ops */
- case RIGHTMOUSE:
- case ESCKEY:
- gpsculpt_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;
-
- /* 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:
- 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:
- return OPERATOR_PASS_THROUGH;
-
- /* Unhandled event */
- default:
- break;
- }
- }
-
- /* Redraw region? */
- if (redraw_region) {
- ARegion *ar = CTX_wm_region(C);
- ED_region_tag_redraw(ar);
- }
-
- /* 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;
+ tGP_BrushEditData *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 */
+ gpsculpt_brush_apply_event(C, op, event);
+
+ /* force redraw, so that the cursor will at least be valid */
+ redraw_region = true;
+ break;
+
+ /* Timer Tick - Only if this was our own timer */
+ case TIMER:
+ if (event->customdata == gso->timer) {
+ gso->timerTick = true;
+ gpsculpt_brush_apply_event(C, op, event);
+ gso->timerTick = false;
+ }
+ 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);
+ if (is_modal) {
+ /* go back to idling... */
+ gso->is_painting = false;
+ }
+ else {
+ /* end sculpt session, since we're not modal */
+ gso->is_painting = false;
+
+ gpsculpt_brush_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ break;
+
+ /* Abort painting if any of the usual things are tried */
+ case MIDDLEMOUSE:
+ case RIGHTMOUSE:
+ case ESCKEY:
+ gpsculpt_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;
+
+ gpsculpt_brush_init_stroke(gso);
+ gpsculpt_brush_apply_event(C, op, event);
+ break;
+
+ /* Exit modal operator, based on the "standard" ops */
+ case RIGHTMOUSE:
+ case ESCKEY:
+ gpsculpt_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;
+
+ /* 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:
+ 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:
+ return OPERATOR_PASS_THROUGH;
+
+ /* Unhandled event */
+ default:
+ break;
+ }
+ }
+
+ /* Redraw region? */
+ if (redraw_region) {
+ ARegion *ar = CTX_wm_region(C);
+ ED_region_tag_redraw(ar);
+ }
+
+ /* 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_sculpt_paint(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Stroke Sculpt";
- ot->idname = "GPENCIL_OT_sculpt_paint";
- ot->description = "Apply tweaks to strokes by painting over the strokes"; // XXX
-
- /* api callbacks */
- ot->exec = gpsculpt_brush_exec;
- ot->invoke = gpsculpt_brush_invoke;
- ot->modal = gpsculpt_brush_modal;
- ot->cancel = gpsculpt_brush_exit;
- ot->poll = gpsculpt_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",
- "Enter a mini 'sculpt-mode' if enabled, otherwise, exit after drawing a single stroke");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ /* identifiers */
+ ot->name = "Stroke Sculpt";
+ ot->idname = "GPENCIL_OT_sculpt_paint";
+ ot->description = "Apply tweaks to strokes by painting over the strokes"; // XXX
+
+ /* api callbacks */
+ ot->exec = gpsculpt_brush_exec;
+ ot->invoke = gpsculpt_brush_invoke;
+ ot->modal = gpsculpt_brush_modal;
+ ot->cancel = gpsculpt_brush_exit;
+ ot->poll = gpsculpt_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",
+ "Enter a mini 'sculpt-mode' if enabled, otherwise, exit after drawing a single stroke");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index af2c68d6c68..c1c797b15be 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -22,7 +22,6 @@
* \ingroup edgpencil
*/
-
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -88,50 +87,62 @@
/* defines for possible modes */
enum {
- GP_STROKECONVERT_PATH = 1,
- GP_STROKECONVERT_CURVE,
- GP_STROKECONVERT_POLY,
+ GP_STROKECONVERT_PATH = 1,
+ GP_STROKECONVERT_CURVE,
+ GP_STROKECONVERT_POLY,
};
/* Defines for possible timing modes */
enum {
- GP_STROKECONVERT_TIMING_NONE = 1,
- GP_STROKECONVERT_TIMING_LINEAR = 2,
- GP_STROKECONVERT_TIMING_FULL = 3,
- GP_STROKECONVERT_TIMING_CUSTOMGAP = 4,
+ GP_STROKECONVERT_TIMING_NONE = 1,
+ GP_STROKECONVERT_TIMING_LINEAR = 2,
+ GP_STROKECONVERT_TIMING_FULL = 3,
+ GP_STROKECONVERT_TIMING_CUSTOMGAP = 4,
};
/* RNA enum define */
static const EnumPropertyItem prop_gpencil_convertmodes[] = {
- {GP_STROKECONVERT_PATH, "PATH", ICON_CURVE_PATH, "Path", "Animation path"},
- {GP_STROKECONVERT_CURVE, "CURVE", ICON_CURVE_BEZCURVE, "Bezier Curve", "Smooth Bezier curve"},
- {GP_STROKECONVERT_POLY, "POLY", ICON_MESH_DATA, "Polygon Curve", "Bezier curve with straight-line segments (vector handles)"},
- {0, NULL, 0, NULL, NULL},
+ {GP_STROKECONVERT_PATH, "PATH", ICON_CURVE_PATH, "Path", "Animation path"},
+ {GP_STROKECONVERT_CURVE, "CURVE", ICON_CURVE_BEZCURVE, "Bezier Curve", "Smooth Bezier curve"},
+ {GP_STROKECONVERT_POLY,
+ "POLY",
+ ICON_MESH_DATA,
+ "Polygon Curve",
+ "Bezier curve with straight-line segments (vector handles)"},
+ {0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem prop_gpencil_convert_timingmodes_restricted[] = {
- {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"},
- {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"},
- {0, NULL, 0, NULL, NULL},
+ {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"},
+ {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"},
+ {0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem prop_gpencil_convert_timingmodes[] = {
- {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"},
- {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"},
- {GP_STROKECONVERT_TIMING_FULL, "FULL", 0, "Original", "Use the original timing, gaps included"},
- {GP_STROKECONVERT_TIMING_CUSTOMGAP, "CUSTOMGAP", 0, "Custom Gaps",
- "Use the original timing, but with custom gap lengths (in frames)"},
- {0, NULL, 0, NULL, NULL},
+ {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"},
+ {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"},
+ {GP_STROKECONVERT_TIMING_FULL,
+ "FULL",
+ 0,
+ "Original",
+ "Use the original timing, gaps included"},
+ {GP_STROKECONVERT_TIMING_CUSTOMGAP,
+ "CUSTOMGAP",
+ 0,
+ "Custom Gaps",
+ "Use the original timing, but with custom gap lengths (in frames)"},
+ {0, NULL, 0, NULL, NULL},
};
-static const EnumPropertyItem *rna_GPConvert_mode_items(
- bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop),
- bool *UNUSED(r_free))
+static const EnumPropertyItem *rna_GPConvert_mode_items(bContext *UNUSED(C),
+ PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop),
+ bool *UNUSED(r_free))
{
- if (RNA_boolean_get(ptr, "use_timing_data")) {
- return prop_gpencil_convert_timingmodes;
- }
- return prop_gpencil_convert_timingmodes_restricted;
+ if (RNA_boolean_get(ptr, "use_timing_data")) {
+ return prop_gpencil_convert_timingmodes;
+ }
+ return prop_gpencil_convert_timingmodes_restricted;
}
/* --- */
@@ -139,81 +150,84 @@ static const EnumPropertyItem *rna_GPConvert_mode_items(
/* convert the coordinates from the given stroke point into 3d-coordinates
* - 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,
- float p3d[3], const rctf *subrect)
+static void gp_strokepoint_convertcoords(bContext *C,
+ bGPdata *gpd,
+ bGPDlayer *gpl,
+ bGPDstroke *gps,
+ bGPDspoint *source_pt,
+ float p3d[3],
+ const rctf *subrect)
{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *obact = CTX_data_active_object(C);
- bGPDspoint mypt, *pt;
-
- float diff_mat[4][4];
- pt = &mypt;
-
- /* apply parent transform */
- float fpt[3];
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
- mul_v3_m4v3(fpt, diff_mat, &source_pt->x);
- copy_v3_v3(&pt->x, fpt);
-
-
- if (gps->flag & GP_STROKE_3DSPACE) {
- /* directly use 3d-coordinates */
- copy_v3_v3(p3d, &pt->x);
- }
- else {
- const float *fp = scene->cursor.location;
- float mvalf[2];
-
- /* get screen coordinate */
- if (gps->flag & GP_STROKE_2DSPACE) {
- View2D *v2d = &ar->v2d;
- UI_view2d_view_to_region_fl(v2d, pt->x, pt->y, &mvalf[0], &mvalf[1]);
- }
- else {
- if (subrect) {
- mvalf[0] = (((float)pt->x / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin;
- 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;
- }
- }
-
- ED_view3d_win_to_3d(v3d, ar, fp, mvalf, p3d);
- }
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *obact = CTX_data_active_object(C);
+ bGPDspoint mypt, *pt;
+
+ float diff_mat[4][4];
+ pt = &mypt;
+
+ /* apply parent transform */
+ float fpt[3];
+ ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ mul_v3_m4v3(fpt, diff_mat, &source_pt->x);
+ copy_v3_v3(&pt->x, fpt);
+
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ /* directly use 3d-coordinates */
+ copy_v3_v3(p3d, &pt->x);
+ }
+ else {
+ const float *fp = scene->cursor.location;
+ float mvalf[2];
+
+ /* get screen coordinate */
+ if (gps->flag & GP_STROKE_2DSPACE) {
+ View2D *v2d = &ar->v2d;
+ UI_view2d_view_to_region_fl(v2d, pt->x, pt->y, &mvalf[0], &mvalf[1]);
+ }
+ else {
+ if (subrect) {
+ mvalf[0] = (((float)pt->x / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin;
+ 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;
+ }
+ }
+
+ ED_view3d_win_to_3d(v3d, ar, fp, mvalf, p3d);
+ }
}
/* --- */
/* temp struct for gp_stroke_path_animation() */
typedef struct tGpTimingData {
- /* Data set from operator settings */
- int mode;
- int frame_range; /* Number of frames evaluated for path animation */
- int start_frame, end_frame;
- bool realtime; /* Will overwrite end_frame in case of Original or CustomGap timing... */
- float gap_duration, gap_randomness; /* To be used with CustomGap mode*/
- int seed;
-
- /* Data set from points, used to compute final timing FCurve */
- int num_points, cur_point;
-
- /* Distances */
- float *dists;
- float tot_dist;
-
- /* Times */
- float *times; /* Note: Gap times will be negative! */
- float tot_time, gap_tot_time;
- double inittime;
-
- /* Only used during creation of dists & times lists. */
- float offset_time;
+ /* Data set from operator settings */
+ int mode;
+ int frame_range; /* Number of frames evaluated for path animation */
+ int start_frame, end_frame;
+ bool realtime; /* Will overwrite end_frame in case of Original or CustomGap timing... */
+ float gap_duration, gap_randomness; /* To be used with CustomGap mode*/
+ int seed;
+
+ /* Data set from points, used to compute final timing FCurve */
+ int num_points, cur_point;
+
+ /* Distances */
+ float *dists;
+ float tot_dist;
+
+ /* Times */
+ float *times; /* Note: Gap times will be negative! */
+ float tot_time, gap_tot_time;
+ double inittime;
+
+ /* Only used during creation of dists & times lists. */
+ float offset_time;
} tGpTimingData;
/* Init point buffers for timing data.
@@ -221,59 +235,61 @@ typedef struct tGpTimingData {
*/
static void gp_timing_data_set_nbr(tGpTimingData *gtd, const int nbr)
{
- float *tmp;
-
- BLI_assert(nbr > gtd->num_points);
-
- /* distances */
- tmp = gtd->dists;
- gtd->dists = MEM_callocN(sizeof(float) * nbr, __func__);
- if (tmp) {
- memcpy(gtd->dists, tmp, sizeof(float) * gtd->num_points);
- MEM_freeN(tmp);
- }
-
- /* times */
- tmp = gtd->times;
- gtd->times = MEM_callocN(sizeof(float) * nbr, __func__);
- if (tmp) {
- memcpy(gtd->times, tmp, sizeof(float) * gtd->num_points);
- MEM_freeN(tmp);
- }
-
- gtd->num_points = nbr;
+ float *tmp;
+
+ BLI_assert(nbr > gtd->num_points);
+
+ /* distances */
+ tmp = gtd->dists;
+ gtd->dists = MEM_callocN(sizeof(float) * nbr, __func__);
+ if (tmp) {
+ memcpy(gtd->dists, tmp, sizeof(float) * gtd->num_points);
+ MEM_freeN(tmp);
+ }
+
+ /* times */
+ tmp = gtd->times;
+ gtd->times = MEM_callocN(sizeof(float) * nbr, __func__);
+ if (tmp) {
+ memcpy(gtd->times, tmp, sizeof(float) * gtd->num_points);
+ MEM_freeN(tmp);
+ }
+
+ gtd->num_points = nbr;
}
/* add stroke point to timing buffers */
-static void gp_timing_data_add_point(
- tGpTimingData *gtd, const double stroke_inittime, const float time,
- const float delta_dist)
+static void gp_timing_data_add_point(tGpTimingData *gtd,
+ const double stroke_inittime,
+ const float time,
+ const float delta_dist)
{
- float delta_time = 0.0f;
- const int cur_point = gtd->cur_point;
-
- if (!cur_point) {
- /* Special case, first point, if time is not 0.0f we have to compensate! */
- gtd->offset_time = -time;
- gtd->times[cur_point] = 0.0f;
- }
- else if (time < 0.0f) {
- /* This is a gap, negative value! */
- gtd->times[cur_point] = -(((float)(stroke_inittime - gtd->inittime)) + time + gtd->offset_time);
- delta_time = -gtd->times[cur_point] - gtd->times[cur_point - 1];
-
- gtd->gap_tot_time += delta_time;
- }
- else {
- gtd->times[cur_point] = (((float)(stroke_inittime - gtd->inittime)) + time + gtd->offset_time);
- delta_time = gtd->times[cur_point] - fabsf(gtd->times[cur_point - 1]);
- }
-
- gtd->tot_time += delta_time;
- gtd->tot_dist += delta_dist;
- gtd->dists[cur_point] = gtd->tot_dist;
-
- gtd->cur_point++;
+ float delta_time = 0.0f;
+ const int cur_point = gtd->cur_point;
+
+ if (!cur_point) {
+ /* Special case, first point, if time is not 0.0f we have to compensate! */
+ gtd->offset_time = -time;
+ gtd->times[cur_point] = 0.0f;
+ }
+ else if (time < 0.0f) {
+ /* This is a gap, negative value! */
+ gtd->times[cur_point] = -(((float)(stroke_inittime - gtd->inittime)) + time +
+ gtd->offset_time);
+ delta_time = -gtd->times[cur_point] - gtd->times[cur_point - 1];
+
+ gtd->gap_tot_time += delta_time;
+ }
+ else {
+ gtd->times[cur_point] = (((float)(stroke_inittime - gtd->inittime)) + time + gtd->offset_time);
+ delta_time = gtd->times[cur_point] - fabsf(gtd->times[cur_point - 1]);
+ }
+
+ gtd->tot_time += delta_time;
+ gtd->tot_dist += delta_dist;
+ gtd->dists[cur_point] = gtd->tot_dist;
+
+ gtd->cur_point++;
}
/* In frames! Binary search for FCurve keys have a threshold of 0.01, so we can't set
@@ -282,271 +298,301 @@ static void gp_timing_data_add_point(
#define MIN_TIME_DELTA 0.02f
/* Loop over next points to find the end of the stroke, and compute */
-static int gp_find_end_of_stroke_idx(
- tGpTimingData *gtd, RNG *rng, const int idx, const int nbr_gaps,
- int *nbr_done_gaps, const float tot_gaps_time, const float delta_time,
- float *next_delta_time)
+static int gp_find_end_of_stroke_idx(tGpTimingData *gtd,
+ RNG *rng,
+ const int idx,
+ const int nbr_gaps,
+ int *nbr_done_gaps,
+ const float tot_gaps_time,
+ const float delta_time,
+ float *next_delta_time)
{
- int j;
-
- for (j = idx + 1; j < gtd->num_points; j++) {
- if (gtd->times[j] < 0) {
- gtd->times[j] = -gtd->times[j];
- if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
- /* In this mode, gap time between this stroke and the next should be 0 currently...
- * So we have to compute its final duration!
- */
- if (gtd->gap_randomness > 0.0f) {
- /* We want gaps that are in gtd->gap_duration +/- gtd->gap_randomness range,
- * and which sum to exactly tot_gaps_time...
- */
- int rem_gaps = nbr_gaps - (*nbr_done_gaps);
- if (rem_gaps < 2) {
- /* Last gap, just give remaining time! */
- *next_delta_time = tot_gaps_time;
- }
- else {
- float delta, min, max;
-
- /* This code ensures that if the first gaps have been shorter than average gap_duration,
- * next gaps will tend to be longer (i.e. try to recover the lateness), and vice-versa!
- */
- delta = delta_time - (gtd->gap_duration * (*nbr_done_gaps));
-
- /* Clamp min between [-gap_randomness, 0.0], with lower delta giving higher min */
- min = -gtd->gap_randomness - delta;
- CLAMP(min, -gtd->gap_randomness, 0.0f);
-
- /* Clamp max between [0.0, gap_randomness], with lower delta giving higher max */
- max = gtd->gap_randomness - delta;
- CLAMP(max, 0.0f, gtd->gap_randomness);
- *next_delta_time += gtd->gap_duration + (BLI_rng_get_float(rng) * (max - min)) + min;
- }
- }
- else {
- *next_delta_time += gtd->gap_duration;
- }
- }
- (*nbr_done_gaps)++;
- break;
- }
- }
-
- return j - 1;
+ int j;
+
+ for (j = idx + 1; j < gtd->num_points; j++) {
+ if (gtd->times[j] < 0) {
+ gtd->times[j] = -gtd->times[j];
+ if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
+ /* In this mode, gap time between this stroke and the next should be 0 currently...
+ * So we have to compute its final duration!
+ */
+ if (gtd->gap_randomness > 0.0f) {
+ /* We want gaps that are in gtd->gap_duration +/- gtd->gap_randomness range,
+ * and which sum to exactly tot_gaps_time...
+ */
+ int rem_gaps = nbr_gaps - (*nbr_done_gaps);
+ if (rem_gaps < 2) {
+ /* Last gap, just give remaining time! */
+ *next_delta_time = tot_gaps_time;
+ }
+ else {
+ float delta, min, max;
+
+ /* This code ensures that if the first gaps have been shorter than average gap_duration,
+ * next gaps will tend to be longer (i.e. try to recover the lateness), and vice-versa!
+ */
+ delta = delta_time - (gtd->gap_duration * (*nbr_done_gaps));
+
+ /* Clamp min between [-gap_randomness, 0.0], with lower delta giving higher min */
+ min = -gtd->gap_randomness - delta;
+ CLAMP(min, -gtd->gap_randomness, 0.0f);
+
+ /* Clamp max between [0.0, gap_randomness], with lower delta giving higher max */
+ max = gtd->gap_randomness - delta;
+ CLAMP(max, 0.0f, gtd->gap_randomness);
+ *next_delta_time += gtd->gap_duration + (BLI_rng_get_float(rng) * (max - min)) + min;
+ }
+ }
+ else {
+ *next_delta_time += gtd->gap_duration;
+ }
+ }
+ (*nbr_done_gaps)++;
+ break;
+ }
+ }
+
+ return j - 1;
}
-static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, RNG *rng, int *nbr_gaps, float *tot_gaps_time)
+static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd,
+ RNG *rng,
+ int *nbr_gaps,
+ float *tot_gaps_time)
{
- int i;
- float delta_time = 0.0f;
-
- for (i = 0; i < gtd->num_points; i++) {
- if (gtd->times[i] < 0 && i) {
- (*nbr_gaps)++;
- gtd->times[i] = -gtd->times[i] - delta_time;
- delta_time += gtd->times[i] - gtd->times[i - 1];
- gtd->times[i] = -gtd->times[i - 1]; /* Temp marker, values *have* to be different! */
- }
- else {
- gtd->times[i] -= delta_time;
- }
- }
- gtd->tot_time -= delta_time;
-
- *tot_gaps_time = (float)(*nbr_gaps) * gtd->gap_duration;
- gtd->tot_time += *tot_gaps_time;
- if (G.debug & G_DEBUG) {
- printf("%f, %f, %f, %d\n", gtd->tot_time, delta_time, *tot_gaps_time, *nbr_gaps);
- }
- if (gtd->gap_randomness > 0.0f) {
- BLI_rng_srandom(rng, gtd->seed);
- }
+ int i;
+ float delta_time = 0.0f;
+
+ for (i = 0; i < gtd->num_points; i++) {
+ if (gtd->times[i] < 0 && i) {
+ (*nbr_gaps)++;
+ gtd->times[i] = -gtd->times[i] - delta_time;
+ delta_time += gtd->times[i] - gtd->times[i - 1];
+ gtd->times[i] = -gtd->times[i - 1]; /* Temp marker, values *have* to be different! */
+ }
+ else {
+ gtd->times[i] -= delta_time;
+ }
+ }
+ gtd->tot_time -= delta_time;
+
+ *tot_gaps_time = (float)(*nbr_gaps) * gtd->gap_duration;
+ gtd->tot_time += *tot_gaps_time;
+ if (G.debug & G_DEBUG) {
+ printf("%f, %f, %f, %d\n", gtd->tot_time, delta_time, *tot_gaps_time, *nbr_gaps);
+ }
+ if (gtd->gap_randomness > 0.0f) {
+ BLI_rng_srandom(rng, gtd->seed);
+ }
}
-static void gp_stroke_path_animation_add_keyframes(
- Depsgraph *depsgraph, ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu,
- Curve *cu, tGpTimingData *gtd, RNG *rng, const float time_range,
- const int nbr_gaps, const float tot_gaps_time)
+static void gp_stroke_path_animation_add_keyframes(Depsgraph *depsgraph,
+ ReportList *reports,
+ PointerRNA ptr,
+ PropertyRNA *prop,
+ FCurve *fcu,
+ Curve *cu,
+ tGpTimingData *gtd,
+ RNG *rng,
+ const float time_range,
+ const int nbr_gaps,
+ const float tot_gaps_time)
{
- /* Use actual recorded timing! */
- const float time_start = (float)gtd->start_frame;
-
- float last_valid_time = 0.0f;
- int end_stroke_idx = -1, start_stroke_idx = 0;
- float end_stroke_time = 0.0f;
-
- /* CustomGaps specific */
- float delta_time = 0.0f, next_delta_time = 0.0f;
- int nbr_done_gaps = 0;
-
- int i;
- float cfra;
-
- /* This is a bit tricky, as:
- * - We can't add arbitrarily close points on FCurve (in time).
- * - We *must* have all "caps" points of all strokes in FCurve, as much as possible!
- */
- for (i = 0; i < gtd->num_points; i++) {
- /* If new stroke... */
- if (i > end_stroke_idx) {
- start_stroke_idx = i;
- delta_time = next_delta_time;
- /* find end of that new stroke */
- end_stroke_idx = gp_find_end_of_stroke_idx(
- gtd, rng, i, nbr_gaps, &nbr_done_gaps,
- tot_gaps_time, delta_time, &next_delta_time);
- /* This one should *never* be negative! */
- end_stroke_time = time_start + ((gtd->times[end_stroke_idx] + delta_time) / gtd->tot_time * time_range);
- }
-
- /* Simple proportional stuff... */
- cu->ctime = gtd->dists[i] / gtd->tot_dist * cu->pathlen;
- cfra = time_start + ((gtd->times[i] + delta_time) / gtd->tot_time * time_range);
-
- /* And now, the checks about timing... */
- if (i == start_stroke_idx) {
- /* If first point of a stroke, be sure it's enough ahead of last valid keyframe, and
- * that the end point of the stroke is far enough!
- * In case it is not, we keep the end point...
- * Note that with CustomGaps mode, this is here we set the actual gap timing!
- */
- if ((end_stroke_time - last_valid_time) > MIN_TIME_DELTA * 2) {
- if ((cfra - last_valid_time) < MIN_TIME_DELTA) {
- cfra = last_valid_time + MIN_TIME_DELTA;
- }
- insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, NULL, INSERTKEY_FAST);
- last_valid_time = cfra;
- }
- else if (G.debug & G_DEBUG) {
- printf("\t Skipping start point %d, too close from end point %d\n", i, end_stroke_idx);
- }
- }
- else if (i == end_stroke_idx) {
- /* Always try to insert end point of a curve (should be safe enough, anyway...) */
- if ((cfra - last_valid_time) < MIN_TIME_DELTA) {
- cfra = last_valid_time + MIN_TIME_DELTA;
- }
- insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, NULL, INSERTKEY_FAST);
- last_valid_time = cfra;
- }
- else {
- /* Else ("middle" point), we only insert it if it's far enough from last keyframe,
- * and also far enough from (not yet added!) end_stroke keyframe!
- */
- if ((cfra - last_valid_time) > MIN_TIME_DELTA && (end_stroke_time - cfra) > MIN_TIME_DELTA) {
- insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_BREAKDOWN, NULL, INSERTKEY_FAST);
- last_valid_time = cfra;
- }
- else if (G.debug & G_DEBUG) {
- printf("\t Skipping \"middle\" point %d, too close from last added point or end point %d\n",
- i, end_stroke_idx);
- }
- }
- }
+ /* Use actual recorded timing! */
+ const float time_start = (float)gtd->start_frame;
+
+ float last_valid_time = 0.0f;
+ int end_stroke_idx = -1, start_stroke_idx = 0;
+ float end_stroke_time = 0.0f;
+
+ /* CustomGaps specific */
+ float delta_time = 0.0f, next_delta_time = 0.0f;
+ int nbr_done_gaps = 0;
+
+ int i;
+ float cfra;
+
+ /* This is a bit tricky, as:
+ * - We can't add arbitrarily close points on FCurve (in time).
+ * - We *must* have all "caps" points of all strokes in FCurve, as much as possible!
+ */
+ for (i = 0; i < gtd->num_points; i++) {
+ /* If new stroke... */
+ if (i > end_stroke_idx) {
+ start_stroke_idx = i;
+ delta_time = next_delta_time;
+ /* find end of that new stroke */
+ end_stroke_idx = gp_find_end_of_stroke_idx(
+ gtd, rng, i, nbr_gaps, &nbr_done_gaps, tot_gaps_time, delta_time, &next_delta_time);
+ /* This one should *never* be negative! */
+ end_stroke_time = time_start +
+ ((gtd->times[end_stroke_idx] + delta_time) / gtd->tot_time * time_range);
+ }
+
+ /* Simple proportional stuff... */
+ cu->ctime = gtd->dists[i] / gtd->tot_dist * cu->pathlen;
+ cfra = time_start + ((gtd->times[i] + delta_time) / gtd->tot_time * time_range);
+
+ /* And now, the checks about timing... */
+ if (i == start_stroke_idx) {
+ /* If first point of a stroke, be sure it's enough ahead of last valid keyframe, and
+ * that the end point of the stroke is far enough!
+ * In case it is not, we keep the end point...
+ * Note that with CustomGaps mode, this is here we set the actual gap timing!
+ */
+ if ((end_stroke_time - last_valid_time) > MIN_TIME_DELTA * 2) {
+ if ((cfra - last_valid_time) < MIN_TIME_DELTA) {
+ cfra = last_valid_time + MIN_TIME_DELTA;
+ }
+ insert_keyframe_direct(
+ depsgraph, reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, NULL, INSERTKEY_FAST);
+ last_valid_time = cfra;
+ }
+ else if (G.debug & G_DEBUG) {
+ printf("\t Skipping start point %d, too close from end point %d\n", i, end_stroke_idx);
+ }
+ }
+ else if (i == end_stroke_idx) {
+ /* Always try to insert end point of a curve (should be safe enough, anyway...) */
+ if ((cfra - last_valid_time) < MIN_TIME_DELTA) {
+ cfra = last_valid_time + MIN_TIME_DELTA;
+ }
+ insert_keyframe_direct(
+ depsgraph, reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, NULL, INSERTKEY_FAST);
+ last_valid_time = cfra;
+ }
+ else {
+ /* Else ("middle" point), we only insert it if it's far enough from last keyframe,
+ * and also far enough from (not yet added!) end_stroke keyframe!
+ */
+ if ((cfra - last_valid_time) > MIN_TIME_DELTA && (end_stroke_time - cfra) > MIN_TIME_DELTA) {
+ insert_keyframe_direct(depsgraph,
+ reports,
+ ptr,
+ prop,
+ fcu,
+ cfra,
+ BEZT_KEYTYPE_BREAKDOWN,
+ NULL,
+ INSERTKEY_FAST);
+ last_valid_time = cfra;
+ }
+ else if (G.debug & G_DEBUG) {
+ printf(
+ "\t Skipping \"middle\" point %d, too close from last added point or end point %d\n",
+ i,
+ end_stroke_idx);
+ }
+ }
+ }
}
-static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu, tGpTimingData *gtd)
+static void gp_stroke_path_animation(bContext *C,
+ ReportList *reports,
+ Curve *cu,
+ tGpTimingData *gtd)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- bAction *act;
- FCurve *fcu;
- PointerRNA ptr;
- PropertyRNA *prop = NULL;
- int nbr_gaps = 0, i;
-
- if (gtd->mode == GP_STROKECONVERT_TIMING_NONE)
- return;
-
- /* gap_duration and gap_randomness are in frames, but we need seconds!!! */
- gtd->gap_duration = FRA2TIME(gtd->gap_duration);
- gtd->gap_randomness = FRA2TIME(gtd->gap_randomness);
-
- /* Enable path! */
- cu->flag |= CU_PATH;
- cu->pathlen = gtd->frame_range;
-
- /* Get RNA pointer to read/write path time values */
- RNA_id_pointer_create((ID *)cu, &ptr);
- 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);
-
- if (G.debug & G_DEBUG) {
- printf("%s: tot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time);
- for (i = 0; i < gtd->num_points; i++) {
- printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]);
- }
- }
-
- if (gtd->mode == GP_STROKECONVERT_TIMING_LINEAR) {
- float cfra;
-
- /* Linear extrapolation! */
- fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
-
- cu->ctime = 0.0f;
- cfra = (float)gtd->start_frame;
- insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, NULL, INSERTKEY_FAST);
-
- cu->ctime = cu->pathlen;
- if (gtd->realtime) {
- cfra += (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */
- }
- else {
- cfra = (float)gtd->end_frame;
- }
- insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, NULL, INSERTKEY_FAST);
- }
- else {
- /* Use actual recorded timing! */
- RNG *rng = BLI_rng_new(0);
- float time_range;
-
- /* CustomGaps specific */
- float tot_gaps_time = 0.0f;
-
- /* Pre-process gaps, in case we don't want to keep their original timing */
- if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
- gp_stroke_path_animation_preprocess_gaps(gtd, rng, &nbr_gaps, &tot_gaps_time);
- }
-
- if (gtd->realtime) {
- time_range = (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */
- }
- else {
- time_range = (float)(gtd->end_frame - gtd->start_frame);
- }
-
- if (G.debug & G_DEBUG) {
- printf("GP Stroke Path Conversion: Starting keying!\n");
- }
-
- gp_stroke_path_animation_add_keyframes(
- depsgraph, reports, ptr, prop, fcu, cu, gtd, rng, time_range,
- nbr_gaps, tot_gaps_time);
-
- BLI_rng_free(rng);
- }
-
- /* As we used INSERTKEY_FAST mode, we need to recompute all curve's handles now */
- calchandles_fcurve(fcu);
-
- if (G.debug & G_DEBUG) {
- printf("%s: \ntot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time);
- for (i = 0; i < gtd->num_points; i++) {
- printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]);
- }
- printf("\n\n");
- }
-
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
-
- /* send updates */
- DEG_id_tag_update(&cu->id, 0);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ bAction *act;
+ FCurve *fcu;
+ PointerRNA ptr;
+ PropertyRNA *prop = NULL;
+ int nbr_gaps = 0, i;
+
+ if (gtd->mode == GP_STROKECONVERT_TIMING_NONE)
+ return;
+
+ /* gap_duration and gap_randomness are in frames, but we need seconds!!! */
+ gtd->gap_duration = FRA2TIME(gtd->gap_duration);
+ gtd->gap_randomness = FRA2TIME(gtd->gap_randomness);
+
+ /* Enable path! */
+ cu->flag |= CU_PATH;
+ cu->pathlen = gtd->frame_range;
+
+ /* Get RNA pointer to read/write path time values */
+ RNA_id_pointer_create((ID *)cu, &ptr);
+ 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);
+
+ if (G.debug & G_DEBUG) {
+ printf("%s: tot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time);
+ for (i = 0; i < gtd->num_points; i++) {
+ printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]);
+ }
+ }
+
+ if (gtd->mode == GP_STROKECONVERT_TIMING_LINEAR) {
+ float cfra;
+
+ /* Linear extrapolation! */
+ fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
+
+ cu->ctime = 0.0f;
+ cfra = (float)gtd->start_frame;
+ insert_keyframe_direct(
+ depsgraph, reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, NULL, INSERTKEY_FAST);
+
+ cu->ctime = cu->pathlen;
+ if (gtd->realtime) {
+ cfra += (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */
+ }
+ else {
+ cfra = (float)gtd->end_frame;
+ }
+ insert_keyframe_direct(
+ depsgraph, reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, NULL, INSERTKEY_FAST);
+ }
+ else {
+ /* Use actual recorded timing! */
+ RNG *rng = BLI_rng_new(0);
+ float time_range;
+
+ /* CustomGaps specific */
+ float tot_gaps_time = 0.0f;
+
+ /* Pre-process gaps, in case we don't want to keep their original timing */
+ if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
+ gp_stroke_path_animation_preprocess_gaps(gtd, rng, &nbr_gaps, &tot_gaps_time);
+ }
+
+ if (gtd->realtime) {
+ time_range = (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */
+ }
+ else {
+ time_range = (float)(gtd->end_frame - gtd->start_frame);
+ }
+
+ if (G.debug & G_DEBUG) {
+ printf("GP Stroke Path Conversion: Starting keying!\n");
+ }
+
+ gp_stroke_path_animation_add_keyframes(
+ depsgraph, reports, ptr, prop, fcu, cu, gtd, rng, time_range, nbr_gaps, tot_gaps_time);
+
+ BLI_rng_free(rng);
+ }
+
+ /* As we used INSERTKEY_FAST mode, we need to recompute all curve's handles now */
+ calchandles_fcurve(fcu);
+
+ if (G.debug & G_DEBUG) {
+ printf("%s: \ntot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time);
+ for (i = 0; i < gtd->num_points; i++) {
+ printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]);
+ }
+ printf("\n\n");
+ }
+
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+
+ /* send updates */
+ DEG_id_tag_update(&cu->id, 0);
}
#undef MIN_TIME_DELTA
@@ -558,486 +604,559 @@ static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu
/* convert stroke to 3d path */
/* helper */
-static void gp_stroke_to_path_add_point(
- tGpTimingData *gtd, BPoint *bp, const float p[3], const float prev_p[3],
- const bool do_gtd, const double inittime, const float time,
- const float width, const float rad_fac, float minmax_weights[2])
+static void gp_stroke_to_path_add_point(tGpTimingData *gtd,
+ BPoint *bp,
+ const float p[3],
+ const float prev_p[3],
+ const bool do_gtd,
+ const double inittime,
+ const float time,
+ const float width,
+ const float rad_fac,
+ float minmax_weights[2])
{
- copy_v3_v3(bp->vec, p);
- bp->vec[3] = 1.0f;
-
- /* set settings */
- bp->f1 = SELECT;
- bp->radius = width * rad_fac;
- bp->weight = width;
- CLAMP(bp->weight, 0.0f, 1.0f);
- if (bp->weight < minmax_weights[0]) {
- minmax_weights[0] = bp->weight;
- }
- else if (bp->weight > minmax_weights[1]) {
- minmax_weights[1] = bp->weight;
- }
-
- /* Update timing data */
- if (do_gtd) {
- gp_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p));
- }
+ copy_v3_v3(bp->vec, p);
+ bp->vec[3] = 1.0f;
+
+ /* set settings */
+ bp->f1 = SELECT;
+ bp->radius = width * rad_fac;
+ bp->weight = width;
+ CLAMP(bp->weight, 0.0f, 1.0f);
+ if (bp->weight < minmax_weights[0]) {
+ minmax_weights[0] = bp->weight;
+ }
+ else if (bp->weight > minmax_weights[1]) {
+ minmax_weights[1] = bp->weight;
+ }
+
+ /* Update timing data */
+ if (do_gtd) {
+ gp_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p));
+ }
}
-static void gp_stroke_to_path(
- bContext *C, bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu,
- float minmax_weights[2], const float rad_fac, bool stitch, const bool add_start_point,
- const bool add_end_point, tGpTimingData *gtd)
+static void gp_stroke_to_path(bContext *C,
+ bGPdata *gpd,
+ bGPDlayer *gpl,
+ bGPDstroke *gps,
+ Curve *cu,
+ rctf *subrect,
+ Nurb **curnu,
+ float minmax_weights[2],
+ const float rad_fac,
+ bool stitch,
+ const bool add_start_point,
+ const bool add_end_point,
+ tGpTimingData *gtd)
{
- bGPDspoint *pt;
- Nurb *nu = (curnu) ? *curnu : NULL;
- BPoint *bp, *prev_bp = NULL;
- const bool do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE);
- const int add_start_end_points = (add_start_point ? 1 : 0) + (add_end_point ? 1 : 0);
- int i, old_nbp = 0;
-
- /* create new 'nurb' or extend current one within the curve */
- if (nu) {
- old_nbp = nu->pntsu;
-
- /* If stitch, the first point of this stroke is already present in current nu.
- * Else, we have to add two additional points to make the zero-radius link between strokes.
- */
- BKE_nurb_points_add(nu, gps->totpoints + (stitch ? -1 : 2) + add_start_end_points);
- }
- else {
- nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)");
-
- nu->pntsu = gps->totpoints + add_start_end_points;
- nu->pntsv = 1;
- nu->orderu = 2; /* point-to-point! */
- nu->type = CU_NURBS;
- nu->flagu = CU_NURB_ENDPOINT;
- nu->resolu = cu->resolu;
- nu->resolv = cu->resolv;
- nu->knotsu = NULL;
-
- nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * nu->pntsu, "bpoints");
-
- stitch = false; /* Security! */
- }
-
- if (do_gtd) {
- gp_timing_data_set_nbr(gtd, nu->pntsu);
- }
-
- /* If needed, make the link between both strokes with two zero-radius additional points */
- /* About "zero-radius" point interpolations:
- * - If we have at least two points in current curve (most common case), we linearly extrapolate
- * the last segment to get the first point (p1) position and timing.
- * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point
- * with the first point of the current stroke.
- * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated
- * if it exists, else (if the stroke is a single point), linear interpolation with last curve point...
- */
- if (curnu && !stitch && old_nbp) {
- float p1[3], p2[3], p[3], next_p[3];
- float dt1 = 0.0f, dt2 = 0.0f;
-
- BLI_assert(gps->prev != NULL);
-
- prev_bp = NULL;
- if ((old_nbp > 1) && (gps->prev->totpoints > 1)) {
- /* Only use last curve segment if previous stroke was not a single-point one! */
- prev_bp = &nu->bp[old_nbp - 2];
- }
- bp = &nu->bp[old_nbp - 1];
-
- /* First point */
- gp_strokepoint_convertcoords(C, gpd, gpl, gps, gps->points, p, subrect);
- if (prev_bp) {
- interp_v3_v3v3(p1, bp->vec, prev_bp->vec, -GAP_DFAC);
- if (do_gtd) {
- const int idx = gps->prev->totpoints - 1;
- dt1 = interpf(gps->prev->points[idx - 1].time, gps->prev->points[idx].time, -GAP_DFAC);
- }
- }
- else {
- interp_v3_v3v3(p1, bp->vec, p, GAP_DFAC);
- if (do_gtd) {
- dt1 = interpf(gps->inittime - gps->prev->inittime, 0.0f, GAP_DFAC);
- }
- }
- bp++;
- gp_stroke_to_path_add_point(
- gtd, bp, p1, (bp - 1)->vec, do_gtd, gps->prev->inittime, dt1,
- 0.0f, rad_fac, minmax_weights);
-
- /* 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);
- interp_v3_v3v3(p2, p, next_p, -GAP_DFAC);
- if (do_gtd) {
- dt2 = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC);
- }
- }
- else {
- interp_v3_v3v3(p2, p, bp->vec, GAP_DFAC);
- if (do_gtd) {
- dt2 = interpf(gps->prev->inittime - gps->inittime, 0.0f, GAP_DFAC);
- }
- }
- bp++;
- gp_stroke_to_path_add_point(gtd, bp, p2, p1, do_gtd, gps->inittime, dt2, 0.0f, rad_fac, minmax_weights);
-
- old_nbp += 2;
- }
- else if (add_start_point) {
- float p[3], next_p[3];
- float dt = 0.0f;
-
- gp_strokepoint_convertcoords(C, gpd, gpl, gps, gps->points, p, subrect);
- if (gps->totpoints > 1) {
- gp_strokepoint_convertcoords(C, gpd, 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);
- }
- }
- else {
- p[0] -= GAP_DFAC; /* Rather arbitrary... */
- dt = -GAP_DFAC; /* Rather arbitrary too! */
- }
- bp = &nu->bp[old_nbp];
- /* Note we can't give anything else than 0.0 as time here, since a negative one (which would be expected value)
- * would not work (it would be *before* gtd->inittime, which is not supported currently).
- */
- gp_stroke_to_path_add_point(gtd, bp, p, p, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights);
-
- old_nbp++;
- }
-
- if (old_nbp) {
- prev_bp = &nu->bp[old_nbp - 1];
- }
-
- /* add points */
- for (i = (stitch) ? 1 : 0, pt = &gps->points[(stitch) ? 1 : 0], bp = &nu->bp[old_nbp];
- i < gps->totpoints;
- i++, pt++, bp++)
- {
- float p[3];
- 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_stroke_to_path_add_point(
- gtd, bp, p, (prev_bp) ? prev_bp->vec : p, do_gtd, gps->inittime, pt->time,
- width, rad_fac, minmax_weights);
-
- prev_bp = bp;
- }
-
- if (add_end_point) {
- float p[3];
- float dt = 0.0f;
-
- if (gps->totpoints > 1) {
- interp_v3_v3v3(p, prev_bp->vec, (prev_bp - 1)->vec, -GAP_DFAC);
- if (do_gtd) {
- const int idx = gps->totpoints - 1;
- dt = interpf(gps->points[idx - 1].time, gps->points[idx].time, -GAP_DFAC);
- }
- }
- else {
- copy_v3_v3(p, prev_bp->vec);
- p[0] += GAP_DFAC; /* Rather arbitrary... */
- dt = GAP_DFAC; /* Rather arbitrary too! */
- }
- /* Note bp has already been incremented in main loop above, so it points to the right place. */
- gp_stroke_to_path_add_point(gtd, bp, p, prev_bp->vec, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights);
- }
-
- /* add nurb to curve */
- if (!curnu || !*curnu) {
- BLI_addtail(&cu->nurb, nu);
- }
- if (curnu) {
- *curnu = nu;
- }
-
- BKE_nurb_knot_calc_u(nu);
+ bGPDspoint *pt;
+ Nurb *nu = (curnu) ? *curnu : NULL;
+ BPoint *bp, *prev_bp = NULL;
+ const bool do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE);
+ const int add_start_end_points = (add_start_point ? 1 : 0) + (add_end_point ? 1 : 0);
+ int i, old_nbp = 0;
+
+ /* create new 'nurb' or extend current one within the curve */
+ if (nu) {
+ old_nbp = nu->pntsu;
+
+ /* If stitch, the first point of this stroke is already present in current nu.
+ * Else, we have to add two additional points to make the zero-radius link between strokes.
+ */
+ BKE_nurb_points_add(nu, gps->totpoints + (stitch ? -1 : 2) + add_start_end_points);
+ }
+ else {
+ nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)");
+
+ nu->pntsu = gps->totpoints + add_start_end_points;
+ nu->pntsv = 1;
+ nu->orderu = 2; /* point-to-point! */
+ nu->type = CU_NURBS;
+ nu->flagu = CU_NURB_ENDPOINT;
+ nu->resolu = cu->resolu;
+ nu->resolv = cu->resolv;
+ nu->knotsu = NULL;
+
+ nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * nu->pntsu, "bpoints");
+
+ stitch = false; /* Security! */
+ }
+
+ if (do_gtd) {
+ gp_timing_data_set_nbr(gtd, nu->pntsu);
+ }
+
+ /* If needed, make the link between both strokes with two zero-radius additional points */
+ /* About "zero-radius" point interpolations:
+ * - If we have at least two points in current curve (most common case), we linearly extrapolate
+ * the last segment to get the first point (p1) position and timing.
+ * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point
+ * with the first point of the current stroke.
+ * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated
+ * if it exists, else (if the stroke is a single point), linear interpolation with last curve point...
+ */
+ if (curnu && !stitch && old_nbp) {
+ float p1[3], p2[3], p[3], next_p[3];
+ float dt1 = 0.0f, dt2 = 0.0f;
+
+ BLI_assert(gps->prev != NULL);
+
+ prev_bp = NULL;
+ if ((old_nbp > 1) && (gps->prev->totpoints > 1)) {
+ /* Only use last curve segment if previous stroke was not a single-point one! */
+ prev_bp = &nu->bp[old_nbp - 2];
+ }
+ bp = &nu->bp[old_nbp - 1];
+
+ /* First point */
+ gp_strokepoint_convertcoords(C, gpd, gpl, gps, gps->points, p, subrect);
+ if (prev_bp) {
+ interp_v3_v3v3(p1, bp->vec, prev_bp->vec, -GAP_DFAC);
+ if (do_gtd) {
+ const int idx = gps->prev->totpoints - 1;
+ dt1 = interpf(gps->prev->points[idx - 1].time, gps->prev->points[idx].time, -GAP_DFAC);
+ }
+ }
+ else {
+ interp_v3_v3v3(p1, bp->vec, p, GAP_DFAC);
+ if (do_gtd) {
+ dt1 = interpf(gps->inittime - gps->prev->inittime, 0.0f, GAP_DFAC);
+ }
+ }
+ bp++;
+ gp_stroke_to_path_add_point(gtd,
+ bp,
+ p1,
+ (bp - 1)->vec,
+ do_gtd,
+ gps->prev->inittime,
+ dt1,
+ 0.0f,
+ rad_fac,
+ minmax_weights);
+
+ /* 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);
+ interp_v3_v3v3(p2, p, next_p, -GAP_DFAC);
+ if (do_gtd) {
+ dt2 = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC);
+ }
+ }
+ else {
+ interp_v3_v3v3(p2, p, bp->vec, GAP_DFAC);
+ if (do_gtd) {
+ dt2 = interpf(gps->prev->inittime - gps->inittime, 0.0f, GAP_DFAC);
+ }
+ }
+ bp++;
+ gp_stroke_to_path_add_point(
+ gtd, bp, p2, p1, do_gtd, gps->inittime, dt2, 0.0f, rad_fac, minmax_weights);
+
+ old_nbp += 2;
+ }
+ else if (add_start_point) {
+ float p[3], next_p[3];
+ float dt = 0.0f;
+
+ gp_strokepoint_convertcoords(C, gpd, gpl, gps, gps->points, p, subrect);
+ if (gps->totpoints > 1) {
+ gp_strokepoint_convertcoords(C, gpd, 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);
+ }
+ }
+ else {
+ p[0] -= GAP_DFAC; /* Rather arbitrary... */
+ dt = -GAP_DFAC; /* Rather arbitrary too! */
+ }
+ bp = &nu->bp[old_nbp];
+ /* Note we can't give anything else than 0.0 as time here, since a negative one (which would be expected value)
+ * would not work (it would be *before* gtd->inittime, which is not supported currently).
+ */
+ gp_stroke_to_path_add_point(
+ gtd, bp, p, p, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights);
+
+ old_nbp++;
+ }
+
+ if (old_nbp) {
+ prev_bp = &nu->bp[old_nbp - 1];
+ }
+
+ /* add points */
+ for (i = (stitch) ? 1 : 0, pt = &gps->points[(stitch) ? 1 : 0], bp = &nu->bp[old_nbp];
+ i < gps->totpoints;
+ i++, pt++, bp++) {
+ float p[3];
+ 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_stroke_to_path_add_point(gtd,
+ bp,
+ p,
+ (prev_bp) ? prev_bp->vec : p,
+ do_gtd,
+ gps->inittime,
+ pt->time,
+ width,
+ rad_fac,
+ minmax_weights);
+
+ prev_bp = bp;
+ }
+
+ if (add_end_point) {
+ float p[3];
+ float dt = 0.0f;
+
+ if (gps->totpoints > 1) {
+ interp_v3_v3v3(p, prev_bp->vec, (prev_bp - 1)->vec, -GAP_DFAC);
+ if (do_gtd) {
+ const int idx = gps->totpoints - 1;
+ dt = interpf(gps->points[idx - 1].time, gps->points[idx].time, -GAP_DFAC);
+ }
+ }
+ else {
+ copy_v3_v3(p, prev_bp->vec);
+ p[0] += GAP_DFAC; /* Rather arbitrary... */
+ dt = GAP_DFAC; /* Rather arbitrary too! */
+ }
+ /* Note bp has already been incremented in main loop above, so it points to the right place. */
+ gp_stroke_to_path_add_point(
+ gtd, bp, p, prev_bp->vec, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights);
+ }
+
+ /* add nurb to curve */
+ if (!curnu || !*curnu) {
+ BLI_addtail(&cu->nurb, nu);
+ }
+ if (curnu) {
+ *curnu = nu;
+ }
+
+ BKE_nurb_knot_calc_u(nu);
}
/* convert stroke to 3d bezier */
/* helper */
-static void gp_stroke_to_bezier_add_point(
- tGpTimingData *gtd, BezTriple *bezt,
- const float p[3], const float h1[3], const float h2[3], const float prev_p[3],
- const bool do_gtd, const double inittime, const float time,
- const float width, const float rad_fac, float minmax_weights[2])
+static void gp_stroke_to_bezier_add_point(tGpTimingData *gtd,
+ BezTriple *bezt,
+ const float p[3],
+ const float h1[3],
+ const float h2[3],
+ const float prev_p[3],
+ const bool do_gtd,
+ const double inittime,
+ const float time,
+ const float width,
+ const float rad_fac,
+ float minmax_weights[2])
{
- copy_v3_v3(bezt->vec[0], h1);
- copy_v3_v3(bezt->vec[1], p);
- copy_v3_v3(bezt->vec[2], h2);
-
- /* set settings */
- bezt->h1 = bezt->h2 = HD_FREE;
- bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- bezt->radius = width * rad_fac;
- bezt->weight = width;
- CLAMP(bezt->weight, 0.0f, 1.0f);
- if (bezt->weight < minmax_weights[0]) {
- minmax_weights[0] = bezt->weight;
- }
- else if (bezt->weight > minmax_weights[1]) {
- minmax_weights[1] = bezt->weight;
- }
-
- /* Update timing data */
- if (do_gtd) {
- gp_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p));
- }
+ copy_v3_v3(bezt->vec[0], h1);
+ copy_v3_v3(bezt->vec[1], p);
+ copy_v3_v3(bezt->vec[2], h2);
+
+ /* set settings */
+ bezt->h1 = bezt->h2 = HD_FREE;
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ bezt->radius = width * rad_fac;
+ bezt->weight = width;
+ CLAMP(bezt->weight, 0.0f, 1.0f);
+ if (bezt->weight < minmax_weights[0]) {
+ minmax_weights[0] = bezt->weight;
+ }
+ else if (bezt->weight > minmax_weights[1]) {
+ minmax_weights[1] = bezt->weight;
+ }
+
+ /* Update timing data */
+ if (do_gtd) {
+ gp_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p));
+ }
}
-static void gp_stroke_to_bezier(
- bContext *C, bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu,
- float minmax_weights[2], const float rad_fac, bool stitch, const bool add_start_point,
- const bool add_end_point, tGpTimingData *gtd)
+static void gp_stroke_to_bezier(bContext *C,
+ bGPdata *gpd,
+ bGPDlayer *gpl,
+ bGPDstroke *gps,
+ Curve *cu,
+ rctf *subrect,
+ Nurb **curnu,
+ float minmax_weights[2],
+ const float rad_fac,
+ bool stitch,
+ const bool add_start_point,
+ const bool add_end_point,
+ tGpTimingData *gtd)
{
- bGPDspoint *pt;
- Nurb *nu = (curnu) ? *curnu : NULL;
- BezTriple *bezt, *prev_bezt = NULL;
- int i, tot, old_nbezt = 0;
- const int add_start_end_points = (add_start_point ? 1 : 0) + (add_end_point ? 1 : 0);
- float p3d_cur[3], p3d_prev[3], p3d_next[3], h1[3], h2[3];
- const bool do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE);
-
- /* create new 'nurb' or extend current one within the curve */
- if (nu) {
- old_nbezt = nu->pntsu;
- /* If we do stitch, first point of current stroke is assumed the same as last point of previous stroke,
- * so no need to add it.
- * If no stitch, we want to add two additional points to make a "zero-radius" link between both strokes.
- */
- BKE_nurb_bezierPoints_add(nu, gps->totpoints + ((stitch) ? -1 : 2) + add_start_end_points);
- }
- else {
- nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)");
-
- nu->pntsu = gps->totpoints + add_start_end_points;
- nu->resolu = 12;
- nu->resolv = 12;
- nu->type = CU_BEZIER;
- nu->bezt = (BezTriple *)MEM_callocN(sizeof(BezTriple) * nu->pntsu, "bezts");
-
- stitch = false; /* Security! */
- }
-
- if (do_gtd) {
- gp_timing_data_set_nbr(gtd, nu->pntsu);
- }
-
- tot = gps->totpoints;
-
- /* get initial coordinates */
- pt = gps->points;
- if (tot) {
- gp_strokepoint_convertcoords(C, gpd, 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);
- }
- if (stitch && tot > 2) {
- gp_strokepoint_convertcoords(C, gpd, gpl, gps, pt + 2, p3d_next, subrect);
- }
- }
-
- /* If needed, make the link between both strokes with two zero-radius additional points */
- if (curnu && old_nbezt) {
- BLI_assert(gps->prev != NULL);
-
- /* Update last point's second handle */
- if (stitch) {
- bezt = &nu->bezt[old_nbezt - 1];
- interp_v3_v3v3(h2, bezt->vec[1], p3d_cur, BEZT_HANDLE_FAC);
- copy_v3_v3(bezt->vec[2], h2);
- pt++;
- }
-
- /* Create "link points" */
- /* About "zero-radius" point interpolations:
- * - If we have at least two points in current curve (most common case), we linearly extrapolate
- * the last segment to get the first point (p1) position and timing.
- * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point
- * with the first point of the current stroke.
- * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated
- * if it exists, else (if the stroke is a single point), linear interpolation with last curve point...
- */
- else {
- float p1[3], p2[3];
- float dt1 = 0.0f, dt2 = 0.0f;
-
- prev_bezt = NULL;
- if ((old_nbezt > 1) && (gps->prev->totpoints > 1)) {
- /* Only use last curve segment if previous stroke was not a single-point one! */
- prev_bezt = &nu->bezt[old_nbezt - 2];
- }
- bezt = &nu->bezt[old_nbezt - 1];
-
- /* First point */
- if (prev_bezt) {
- interp_v3_v3v3(p1, prev_bezt->vec[1], bezt->vec[1], 1.0f + GAP_DFAC);
- if (do_gtd) {
- const int idx = gps->prev->totpoints - 1;
- dt1 = interpf(gps->prev->points[idx - 1].time, gps->prev->points[idx].time, -GAP_DFAC);
- }
- }
- else {
- interp_v3_v3v3(p1, bezt->vec[1], p3d_cur, GAP_DFAC);
- if (do_gtd) {
- dt1 = interpf(gps->inittime - gps->prev->inittime, 0.0f, GAP_DFAC);
- }
- }
-
- /* Second point */
- /* Note dt2 is always negative, which marks the gap. */
- if (tot > 1) {
- interp_v3_v3v3(p2, p3d_cur, p3d_next, -GAP_DFAC);
- if (do_gtd) {
- dt2 = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC);
- }
- }
- else {
- interp_v3_v3v3(p2, p3d_cur, bezt->vec[1], GAP_DFAC);
- if (do_gtd) {
- dt2 = interpf(gps->prev->inittime - gps->inittime, 0.0f, GAP_DFAC);
- }
- }
-
- /* Second handle of last point of previous stroke. */
- interp_v3_v3v3(h2, bezt->vec[1], p1, BEZT_HANDLE_FAC);
- copy_v3_v3(bezt->vec[2], h2);
-
- /* First point */
- interp_v3_v3v3(h1, p1, bezt->vec[1], BEZT_HANDLE_FAC);
- interp_v3_v3v3(h2, p1, p2, BEZT_HANDLE_FAC);
- bezt++;
- gp_stroke_to_bezier_add_point(
- gtd, bezt, p1, h1, h2, (bezt - 1)->vec[1], do_gtd, gps->prev->inittime, dt1,
- 0.0f, rad_fac, minmax_weights);
-
- /* Second point */
- interp_v3_v3v3(h1, p2, p1, BEZT_HANDLE_FAC);
- interp_v3_v3v3(h2, p2, p3d_cur, BEZT_HANDLE_FAC);
- bezt++;
- gp_stroke_to_bezier_add_point(
- gtd, bezt, p2, h1, h2, p1, do_gtd, gps->inittime, dt2,
- 0.0f, rad_fac, minmax_weights);
-
- old_nbezt += 2;
- copy_v3_v3(p3d_prev, p2);
- }
- }
- else if (add_start_point) {
- float p[3];
- float dt = 0.0f;
-
- if (gps->totpoints > 1) {
- interp_v3_v3v3(p, p3d_cur, p3d_next, -GAP_DFAC);
- if (do_gtd) {
- dt = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC);
- }
- }
- else {
- copy_v3_v3(p, p3d_cur);
- p[0] -= GAP_DFAC; /* Rather arbitrary... */
- dt = -GAP_DFAC; /* Rather arbitrary too! */
- }
- interp_v3_v3v3(h1, p, p3d_cur, -BEZT_HANDLE_FAC);
- interp_v3_v3v3(h2, p, p3d_cur, BEZT_HANDLE_FAC);
- bezt = &nu->bezt[old_nbezt];
- gp_stroke_to_bezier_add_point(
- gtd, bezt, p, h1, h2, p, do_gtd, gps->inittime, dt,
- 0.0f, rad_fac, minmax_weights);
-
- old_nbezt++;
- copy_v3_v3(p3d_prev, p);
- }
-
- if (old_nbezt) {
- prev_bezt = &nu->bezt[old_nbezt - 1];
- }
-
- /* add points */
- for (i = stitch ? 1 : 0, bezt = &nu->bezt[old_nbezt]; i < tot; i++, pt++, bezt++) {
- float width = pt->pressure * (gps->thickness + gpl->line_change) * WIDTH_CORR_FAC;
-
- if (i || old_nbezt) {
- interp_v3_v3v3(h1, p3d_cur, p3d_prev, BEZT_HANDLE_FAC);
- }
- else {
- interp_v3_v3v3(h1, p3d_cur, p3d_next, -BEZT_HANDLE_FAC);
- }
-
- if (i < tot - 1) {
- interp_v3_v3v3(h2, p3d_cur, p3d_next, BEZT_HANDLE_FAC);
- }
- else {
- interp_v3_v3v3(h2, p3d_cur, p3d_prev, -BEZT_HANDLE_FAC);
- }
-
- gp_stroke_to_bezier_add_point(
- gtd, bezt, p3d_cur, h1, h2, prev_bezt ? prev_bezt->vec[1] : p3d_cur,
- do_gtd, gps->inittime, pt->time, width, rad_fac, minmax_weights);
-
- /* shift coord vects */
- copy_v3_v3(p3d_prev, p3d_cur);
- copy_v3_v3(p3d_cur, p3d_next);
-
- if (i + 2 < tot) {
- gp_strokepoint_convertcoords(C, gpd, gpl, gps, pt + 2, p3d_next, subrect);
- }
-
- prev_bezt = bezt;
- }
-
- if (add_end_point) {
- float p[3];
- float dt = 0.0f;
-
- if (gps->totpoints > 1) {
- interp_v3_v3v3(p, prev_bezt->vec[1], (prev_bezt - 1)->vec[1], -GAP_DFAC);
- if (do_gtd) {
- const int idx = gps->totpoints - 1;
- dt = interpf(gps->points[idx - 1].time, gps->points[idx].time, -GAP_DFAC);
- }
- }
- else {
- copy_v3_v3(p, prev_bezt->vec[1]);
- p[0] += GAP_DFAC; /* Rather arbitrary... */
- dt = GAP_DFAC; /* Rather arbitrary too! */
- }
-
- /* Second handle of last point of this stroke. */
- interp_v3_v3v3(h2, prev_bezt->vec[1], p, BEZT_HANDLE_FAC);
- copy_v3_v3(prev_bezt->vec[2], h2);
-
- /* The end point */
- interp_v3_v3v3(h1, p, prev_bezt->vec[1], BEZT_HANDLE_FAC);
- interp_v3_v3v3(h2, p, prev_bezt->vec[1], -BEZT_HANDLE_FAC);
- /* Note bezt has already been incremented in main loop above, so it points to the right place. */
- gp_stroke_to_bezier_add_point(
- gtd, bezt, p, h1, h2, prev_bezt->vec[1], do_gtd, gps->inittime, dt,
- 0.0f, rad_fac, minmax_weights);
- }
-
- /* must calculate handles or else we crash */
- BKE_nurb_handles_calc(nu);
-
- if (!curnu || !*curnu) {
- BLI_addtail(&cu->nurb, nu);
- }
- if (curnu) {
- *curnu = nu;
- }
+ bGPDspoint *pt;
+ Nurb *nu = (curnu) ? *curnu : NULL;
+ BezTriple *bezt, *prev_bezt = NULL;
+ int i, tot, old_nbezt = 0;
+ const int add_start_end_points = (add_start_point ? 1 : 0) + (add_end_point ? 1 : 0);
+ float p3d_cur[3], p3d_prev[3], p3d_next[3], h1[3], h2[3];
+ const bool do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE);
+
+ /* create new 'nurb' or extend current one within the curve */
+ if (nu) {
+ old_nbezt = nu->pntsu;
+ /* If we do stitch, first point of current stroke is assumed the same as last point of previous stroke,
+ * so no need to add it.
+ * If no stitch, we want to add two additional points to make a "zero-radius" link between both strokes.
+ */
+ BKE_nurb_bezierPoints_add(nu, gps->totpoints + ((stitch) ? -1 : 2) + add_start_end_points);
+ }
+ else {
+ nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)");
+
+ nu->pntsu = gps->totpoints + add_start_end_points;
+ nu->resolu = 12;
+ nu->resolv = 12;
+ nu->type = CU_BEZIER;
+ nu->bezt = (BezTriple *)MEM_callocN(sizeof(BezTriple) * nu->pntsu, "bezts");
+
+ stitch = false; /* Security! */
+ }
+
+ if (do_gtd) {
+ gp_timing_data_set_nbr(gtd, nu->pntsu);
+ }
+
+ tot = gps->totpoints;
+
+ /* get initial coordinates */
+ pt = gps->points;
+ if (tot) {
+ gp_strokepoint_convertcoords(C, gpd, 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);
+ }
+ if (stitch && tot > 2) {
+ gp_strokepoint_convertcoords(C, gpd, gpl, gps, pt + 2, p3d_next, subrect);
+ }
+ }
+
+ /* If needed, make the link between both strokes with two zero-radius additional points */
+ if (curnu && old_nbezt) {
+ BLI_assert(gps->prev != NULL);
+
+ /* Update last point's second handle */
+ if (stitch) {
+ bezt = &nu->bezt[old_nbezt - 1];
+ interp_v3_v3v3(h2, bezt->vec[1], p3d_cur, BEZT_HANDLE_FAC);
+ copy_v3_v3(bezt->vec[2], h2);
+ pt++;
+ }
+
+ /* Create "link points" */
+ /* About "zero-radius" point interpolations:
+ * - If we have at least two points in current curve (most common case), we linearly extrapolate
+ * the last segment to get the first point (p1) position and timing.
+ * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point
+ * with the first point of the current stroke.
+ * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated
+ * if it exists, else (if the stroke is a single point), linear interpolation with last curve point...
+ */
+ else {
+ float p1[3], p2[3];
+ float dt1 = 0.0f, dt2 = 0.0f;
+
+ prev_bezt = NULL;
+ if ((old_nbezt > 1) && (gps->prev->totpoints > 1)) {
+ /* Only use last curve segment if previous stroke was not a single-point one! */
+ prev_bezt = &nu->bezt[old_nbezt - 2];
+ }
+ bezt = &nu->bezt[old_nbezt - 1];
+
+ /* First point */
+ if (prev_bezt) {
+ interp_v3_v3v3(p1, prev_bezt->vec[1], bezt->vec[1], 1.0f + GAP_DFAC);
+ if (do_gtd) {
+ const int idx = gps->prev->totpoints - 1;
+ dt1 = interpf(gps->prev->points[idx - 1].time, gps->prev->points[idx].time, -GAP_DFAC);
+ }
+ }
+ else {
+ interp_v3_v3v3(p1, bezt->vec[1], p3d_cur, GAP_DFAC);
+ if (do_gtd) {
+ dt1 = interpf(gps->inittime - gps->prev->inittime, 0.0f, GAP_DFAC);
+ }
+ }
+
+ /* Second point */
+ /* Note dt2 is always negative, which marks the gap. */
+ if (tot > 1) {
+ interp_v3_v3v3(p2, p3d_cur, p3d_next, -GAP_DFAC);
+ if (do_gtd) {
+ dt2 = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC);
+ }
+ }
+ else {
+ interp_v3_v3v3(p2, p3d_cur, bezt->vec[1], GAP_DFAC);
+ if (do_gtd) {
+ dt2 = interpf(gps->prev->inittime - gps->inittime, 0.0f, GAP_DFAC);
+ }
+ }
+
+ /* Second handle of last point of previous stroke. */
+ interp_v3_v3v3(h2, bezt->vec[1], p1, BEZT_HANDLE_FAC);
+ copy_v3_v3(bezt->vec[2], h2);
+
+ /* First point */
+ interp_v3_v3v3(h1, p1, bezt->vec[1], BEZT_HANDLE_FAC);
+ interp_v3_v3v3(h2, p1, p2, BEZT_HANDLE_FAC);
+ bezt++;
+ gp_stroke_to_bezier_add_point(gtd,
+ bezt,
+ p1,
+ h1,
+ h2,
+ (bezt - 1)->vec[1],
+ do_gtd,
+ gps->prev->inittime,
+ dt1,
+ 0.0f,
+ rad_fac,
+ minmax_weights);
+
+ /* Second point */
+ interp_v3_v3v3(h1, p2, p1, BEZT_HANDLE_FAC);
+ interp_v3_v3v3(h2, p2, p3d_cur, BEZT_HANDLE_FAC);
+ bezt++;
+ gp_stroke_to_bezier_add_point(
+ gtd, bezt, p2, h1, h2, p1, do_gtd, gps->inittime, dt2, 0.0f, rad_fac, minmax_weights);
+
+ old_nbezt += 2;
+ copy_v3_v3(p3d_prev, p2);
+ }
+ }
+ else if (add_start_point) {
+ float p[3];
+ float dt = 0.0f;
+
+ if (gps->totpoints > 1) {
+ interp_v3_v3v3(p, p3d_cur, p3d_next, -GAP_DFAC);
+ if (do_gtd) {
+ dt = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC);
+ }
+ }
+ else {
+ copy_v3_v3(p, p3d_cur);
+ p[0] -= GAP_DFAC; /* Rather arbitrary... */
+ dt = -GAP_DFAC; /* Rather arbitrary too! */
+ }
+ interp_v3_v3v3(h1, p, p3d_cur, -BEZT_HANDLE_FAC);
+ interp_v3_v3v3(h2, p, p3d_cur, BEZT_HANDLE_FAC);
+ bezt = &nu->bezt[old_nbezt];
+ gp_stroke_to_bezier_add_point(
+ gtd, bezt, p, h1, h2, p, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights);
+
+ old_nbezt++;
+ copy_v3_v3(p3d_prev, p);
+ }
+
+ if (old_nbezt) {
+ prev_bezt = &nu->bezt[old_nbezt - 1];
+ }
+
+ /* add points */
+ for (i = stitch ? 1 : 0, bezt = &nu->bezt[old_nbezt]; i < tot; i++, pt++, bezt++) {
+ float width = pt->pressure * (gps->thickness + gpl->line_change) * WIDTH_CORR_FAC;
+
+ if (i || old_nbezt) {
+ interp_v3_v3v3(h1, p3d_cur, p3d_prev, BEZT_HANDLE_FAC);
+ }
+ else {
+ interp_v3_v3v3(h1, p3d_cur, p3d_next, -BEZT_HANDLE_FAC);
+ }
+
+ if (i < tot - 1) {
+ interp_v3_v3v3(h2, p3d_cur, p3d_next, BEZT_HANDLE_FAC);
+ }
+ else {
+ interp_v3_v3v3(h2, p3d_cur, p3d_prev, -BEZT_HANDLE_FAC);
+ }
+
+ gp_stroke_to_bezier_add_point(gtd,
+ bezt,
+ p3d_cur,
+ h1,
+ h2,
+ prev_bezt ? prev_bezt->vec[1] : p3d_cur,
+ do_gtd,
+ gps->inittime,
+ pt->time,
+ width,
+ rad_fac,
+ minmax_weights);
+
+ /* shift coord vects */
+ copy_v3_v3(p3d_prev, p3d_cur);
+ copy_v3_v3(p3d_cur, p3d_next);
+
+ if (i + 2 < tot) {
+ gp_strokepoint_convertcoords(C, gpd, gpl, gps, pt + 2, p3d_next, subrect);
+ }
+
+ prev_bezt = bezt;
+ }
+
+ if (add_end_point) {
+ float p[3];
+ float dt = 0.0f;
+
+ if (gps->totpoints > 1) {
+ interp_v3_v3v3(p, prev_bezt->vec[1], (prev_bezt - 1)->vec[1], -GAP_DFAC);
+ if (do_gtd) {
+ const int idx = gps->totpoints - 1;
+ dt = interpf(gps->points[idx - 1].time, gps->points[idx].time, -GAP_DFAC);
+ }
+ }
+ else {
+ copy_v3_v3(p, prev_bezt->vec[1]);
+ p[0] += GAP_DFAC; /* Rather arbitrary... */
+ dt = GAP_DFAC; /* Rather arbitrary too! */
+ }
+
+ /* Second handle of last point of this stroke. */
+ interp_v3_v3v3(h2, prev_bezt->vec[1], p, BEZT_HANDLE_FAC);
+ copy_v3_v3(prev_bezt->vec[2], h2);
+
+ /* The end point */
+ interp_v3_v3v3(h1, p, prev_bezt->vec[1], BEZT_HANDLE_FAC);
+ interp_v3_v3v3(h2, p, prev_bezt->vec[1], -BEZT_HANDLE_FAC);
+ /* Note bezt has already been incremented in main loop above, so it points to the right place. */
+ gp_stroke_to_bezier_add_point(gtd,
+ bezt,
+ p,
+ h1,
+ h2,
+ prev_bezt->vec[1],
+ do_gtd,
+ gps->inittime,
+ dt,
+ 0.0f,
+ rad_fac,
+ minmax_weights);
+ }
+
+ /* must calculate handles or else we crash */
+ BKE_nurb_handles_calc(nu);
+
+ if (!curnu || !*curnu) {
+ BLI_addtail(&cu->nurb, nu);
+ }
+ if (curnu) {
+ *curnu = nu;
+ }
}
#undef GAP_DFAC
@@ -1046,200 +1165,226 @@ static void gp_stroke_to_bezier(
static void gp_stroke_finalize_curve_endpoints(Curve *cu)
{
- /* start */
- Nurb *nu = cu->nurb.first;
- int i = 0;
- if (nu->bezt) {
- BezTriple *bezt = nu->bezt;
- if (bezt) {
- bezt[i].weight = bezt[i].radius = 0.0f;
- }
- }
- else if (nu->bp) {
- BPoint *bp = nu->bp;
- if (bp) {
- bp[i].weight = bp[i].radius = 0.0f;
- }
- }
-
- /* end */
- nu = cu->nurb.last;
- i = nu->pntsu - 1;
- if (nu->bezt) {
- BezTriple *bezt = nu->bezt;
- if (bezt) {
- bezt[i].weight = bezt[i].radius = 0.0f;
- }
- }
- else if (nu->bp) {
- BPoint *bp = nu->bp;
- if (bp) {
- bp[i].weight = bp[i].radius = 0.0f;
- }
- }
+ /* start */
+ Nurb *nu = cu->nurb.first;
+ int i = 0;
+ if (nu->bezt) {
+ BezTriple *bezt = nu->bezt;
+ if (bezt) {
+ bezt[i].weight = bezt[i].radius = 0.0f;
+ }
+ }
+ else if (nu->bp) {
+ BPoint *bp = nu->bp;
+ if (bp) {
+ bp[i].weight = bp[i].radius = 0.0f;
+ }
+ }
+
+ /* end */
+ nu = cu->nurb.last;
+ i = nu->pntsu - 1;
+ if (nu->bezt) {
+ BezTriple *bezt = nu->bezt;
+ if (bezt) {
+ bezt[i].weight = bezt[i].radius = 0.0f;
+ }
+ }
+ else if (nu->bp) {
+ BPoint *bp = nu->bp;
+ if (bp) {
+ bp[i].weight = bp[i].radius = 0.0f;
+ }
+ }
}
static void gp_stroke_norm_curve_weights(Curve *cu, const float minmax_weights[2])
{
- Nurb *nu;
- const float delta = minmax_weights[0];
- float fac;
- int i;
-
- /* when delta == minmax_weights[0] == minmax_weights[1], we get div by zero [#35686] */
- if (IS_EQF(delta, minmax_weights[1]))
- fac = 1.0f;
- else
- fac = 1.0f / (minmax_weights[1] - delta);
-
- for (nu = cu->nurb.first; nu; nu = nu->next) {
- if (nu->bezt) {
- BezTriple *bezt = nu->bezt;
- for (i = 0; i < nu->pntsu; i++, bezt++) {
- bezt->weight = (bezt->weight - delta) * fac;
- }
- }
- else if (nu->bp) {
- BPoint *bp = nu->bp;
- for (i = 0; i < nu->pntsu; i++, bp++) {
- bp->weight = (bp->weight - delta) * fac;
- }
- }
- }
+ Nurb *nu;
+ const float delta = minmax_weights[0];
+ float fac;
+ int i;
+
+ /* when delta == minmax_weights[0] == minmax_weights[1], we get div by zero [#35686] */
+ if (IS_EQF(delta, minmax_weights[1]))
+ fac = 1.0f;
+ else
+ fac = 1.0f / (minmax_weights[1] - delta);
+
+ for (nu = cu->nurb.first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ BezTriple *bezt = nu->bezt;
+ for (i = 0; i < nu->pntsu; i++, bezt++) {
+ bezt->weight = (bezt->weight - delta) * fac;
+ }
+ }
+ else if (nu->bp) {
+ BPoint *bp = nu->bp;
+ for (i = 0; i < nu->pntsu; i++, bp++) {
+ bp->weight = (bp->weight - delta) * fac;
+ }
+ }
+ }
}
static int gp_camera_view_subrect(bContext *C, rctf *subrect)
{
- View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
-
- if (v3d) {
- RegionView3D *rv3d = ar->regiondata;
-
- /* for camera view set the subrect */
- if (rv3d->persp == RV3D_CAMOB) {
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, subrect, true);
- return 1;
- }
- }
-
- return 0;
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ if (v3d) {
+ RegionView3D *rv3d = ar->regiondata;
+
+ /* for camera view set the subrect */
+ if (rv3d->persp == RV3D_CAMOB) {
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, subrect, true);
+ return 1;
+ }
+ }
+
+ return 0;
}
/* convert a given grease-pencil layer to a 3d-curve representation
* (using current view if appropriate) */
-static void gp_layer_to_curve(
- bContext *C, ReportList *reports, bGPdata *gpd, bGPDlayer *gpl, const int mode,
- const bool norm_weights, const float rad_fac, const bool link_strokes, tGpTimingData *gtd)
+static void gp_layer_to_curve(bContext *C,
+ ReportList *reports,
+ bGPdata *gpd,
+ bGPDlayer *gpl,
+ const int mode,
+ const bool norm_weights,
+ const float rad_fac,
+ const bool link_strokes,
+ tGpTimingData *gtd)
{
- struct Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Collection *collection = CTX_data_collection(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
-
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV);
- bGPDstroke *gps, *prev_gps = NULL;
- Object *ob;
- Curve *cu;
- Nurb *nu = NULL;
- Base *base_new = NULL;
- float minmax_weights[2] = {1.0f, 0.0f};
-
- /* camera framing */
- rctf subrect, *subrect_ptr = NULL;
-
- /* error checking */
- if (ELEM(NULL, gpd, gpl, gpf))
- return;
-
- /* only convert if there are any strokes on this layer's frame to convert */
- if (BLI_listbase_is_empty(&gpf->strokes))
- return;
-
- /* initialize camera framing */
- if (gp_camera_view_subrect(C, &subrect)) {
- subrect_ptr = &subrect;
- }
-
- /* init the curve object (remove rotation and get curve data from it)
- * - must clear transforms set on object, as those skew our results
- */
- ob = BKE_object_add_only_object(bmain, OB_CURVE, gpl->info);
- cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVE);
- BKE_collection_object_add(bmain, collection, ob);
- base_new = BKE_view_layer_base_find(view_layer, ob);
- DEG_relations_tag_update(bmain); /* added object */
-
- cu->flag |= CU_3D;
-
- gtd->inittime = ((bGPDstroke *)gpf->strokes.first)->inittime;
-
- /* add points to curve */
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- const bool add_start_point = (link_strokes && !(prev_gps));
- const bool add_end_point = (link_strokes && !(gps->next));
-
- /* Detect new strokes created because of GP_STROKE_BUFFER_MAX reached,
- * and stitch them to previous one. */
- bool stitch = false;
- if (prev_gps) {
- bGPDspoint *pt1 = &prev_gps->points[prev_gps->totpoints - 1];
- bGPDspoint *pt2 = &gps->points[0];
-
- if ((pt1->x == pt2->x) && (pt1->y == pt2->y)) {
- stitch = true;
- }
- }
-
- /* Decide whether we connect this stroke to previous one */
- if (!(stitch || link_strokes)) {
- nu = NULL;
- }
-
- switch (mode) {
- case GP_STROKECONVERT_PATH:
- gp_stroke_to_path(
- C, gpd, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch,
- add_start_point, add_end_point, gtd);
- break;
- case GP_STROKECONVERT_CURVE:
- case GP_STROKECONVERT_POLY: /* convert after */
- gp_stroke_to_bezier(
- C, gpd, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch,
- add_start_point, add_end_point, gtd);
- break;
- default:
- BLI_assert(!"invalid mode");
- break;
- }
- prev_gps = gps;
- }
-
- /* If link_strokes, be sure first and last points have a zero weight/size! */
- if (link_strokes) {
- gp_stroke_finalize_curve_endpoints(cu);
- }
-
- /* Update curve's weights, if needed */
- if (norm_weights && ((minmax_weights[0] > 0.0f) || (minmax_weights[1] < 1.0f))) {
- gp_stroke_norm_curve_weights(cu, minmax_weights);
- }
-
- /* Create the path animation, if needed */
- gp_stroke_path_animation(C, reports, cu, gtd);
-
- if (mode == GP_STROKECONVERT_POLY) {
- for (nu = cu->nurb.first; nu; nu = nu->next) {
- BKE_nurb_type_convert(nu, CU_POLY, false);
- }
- }
-
- /* set the layer and select */
- base_new->flag |= SELECT;
- BKE_scene_object_base_flag_sync_from_base(base_new);
+ struct Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Collection *collection = CTX_data_collection(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV);
+ bGPDstroke *gps, *prev_gps = NULL;
+ Object *ob;
+ Curve *cu;
+ Nurb *nu = NULL;
+ Base *base_new = NULL;
+ float minmax_weights[2] = {1.0f, 0.0f};
+
+ /* camera framing */
+ rctf subrect, *subrect_ptr = NULL;
+
+ /* error checking */
+ if (ELEM(NULL, gpd, gpl, gpf))
+ return;
+
+ /* only convert if there are any strokes on this layer's frame to convert */
+ if (BLI_listbase_is_empty(&gpf->strokes))
+ return;
+
+ /* initialize camera framing */
+ if (gp_camera_view_subrect(C, &subrect)) {
+ subrect_ptr = &subrect;
+ }
+
+ /* init the curve object (remove rotation and get curve data from it)
+ * - must clear transforms set on object, as those skew our results
+ */
+ ob = BKE_object_add_only_object(bmain, OB_CURVE, gpl->info);
+ cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVE);
+ BKE_collection_object_add(bmain, collection, ob);
+ base_new = BKE_view_layer_base_find(view_layer, ob);
+ DEG_relations_tag_update(bmain); /* added object */
+
+ cu->flag |= CU_3D;
+
+ gtd->inittime = ((bGPDstroke *)gpf->strokes.first)->inittime;
+
+ /* add points to curve */
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ const bool add_start_point = (link_strokes && !(prev_gps));
+ const bool add_end_point = (link_strokes && !(gps->next));
+
+ /* Detect new strokes created because of GP_STROKE_BUFFER_MAX reached,
+ * and stitch them to previous one. */
+ bool stitch = false;
+ if (prev_gps) {
+ bGPDspoint *pt1 = &prev_gps->points[prev_gps->totpoints - 1];
+ bGPDspoint *pt2 = &gps->points[0];
+
+ if ((pt1->x == pt2->x) && (pt1->y == pt2->y)) {
+ stitch = true;
+ }
+ }
+
+ /* Decide whether we connect this stroke to previous one */
+ if (!(stitch || link_strokes)) {
+ nu = NULL;
+ }
+
+ switch (mode) {
+ case GP_STROKECONVERT_PATH:
+ gp_stroke_to_path(C,
+ gpd,
+ gpl,
+ gps,
+ cu,
+ subrect_ptr,
+ &nu,
+ minmax_weights,
+ rad_fac,
+ stitch,
+ add_start_point,
+ add_end_point,
+ gtd);
+ break;
+ case GP_STROKECONVERT_CURVE:
+ case GP_STROKECONVERT_POLY: /* convert after */
+ gp_stroke_to_bezier(C,
+ gpd,
+ gpl,
+ gps,
+ cu,
+ subrect_ptr,
+ &nu,
+ minmax_weights,
+ rad_fac,
+ stitch,
+ add_start_point,
+ add_end_point,
+ gtd);
+ break;
+ default:
+ BLI_assert(!"invalid mode");
+ break;
+ }
+ prev_gps = gps;
+ }
+
+ /* If link_strokes, be sure first and last points have a zero weight/size! */
+ if (link_strokes) {
+ gp_stroke_finalize_curve_endpoints(cu);
+ }
+
+ /* Update curve's weights, if needed */
+ if (norm_weights && ((minmax_weights[0] > 0.0f) || (minmax_weights[1] < 1.0f))) {
+ gp_stroke_norm_curve_weights(cu, minmax_weights);
+ }
+
+ /* Create the path animation, if needed */
+ gp_stroke_path_animation(C, reports, cu, gtd);
+
+ if (mode == GP_STROKECONVERT_POLY) {
+ for (nu = cu->nurb.first; nu; nu = nu->next) {
+ BKE_nurb_type_convert(nu, CU_POLY, false);
+ }
+ }
+
+ /* set the layer and select */
+ base_new->flag |= SELECT;
+ BKE_scene_object_base_flag_sync_from_base(base_new);
}
/* --- */
@@ -1249,279 +1394,348 @@ static void gp_layer_to_curve(
*/
static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOperator *op)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
-
- bGPDframe *gpf = NULL;
- bGPDstroke *gps = NULL;
- bGPDspoint *pt;
- double base_time, cur_time, prev_time = -1.0;
- int i;
- bool valid = true;
-
- if (!gpl || !(gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV)) || !(gps = gpf->strokes.first))
- return false;
-
- do {
- base_time = cur_time = gps->inittime;
- if (cur_time <= prev_time) {
- valid = false;
- break;
- }
-
- prev_time = cur_time;
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- cur_time = base_time + (double)pt->time;
- /* First point of a stroke should have the same time as stroke's inittime,
- * so it's the only case where equality is allowed!
- */
- if ((i && cur_time <= prev_time) || (cur_time < prev_time)) {
- valid = false;
- break;
- }
- prev_time = cur_time;
- }
-
- if (!valid) {
- break;
- }
- } while ((gps = gps->next));
-
- if (op) {
- RNA_boolean_set(op->ptr, "use_timing_data", valid);
- }
- return valid;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+ bGPDframe *gpf = NULL;
+ bGPDstroke *gps = NULL;
+ bGPDspoint *pt;
+ double base_time, cur_time, prev_time = -1.0;
+ int i;
+ bool valid = true;
+
+ if (!gpl || !(gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV)) ||
+ !(gps = gpf->strokes.first))
+ return false;
+
+ do {
+ base_time = cur_time = gps->inittime;
+ if (cur_time <= prev_time) {
+ valid = false;
+ break;
+ }
+
+ prev_time = cur_time;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ cur_time = base_time + (double)pt->time;
+ /* First point of a stroke should have the same time as stroke's inittime,
+ * so it's the only case where equality is allowed!
+ */
+ if ((i && cur_time <= prev_time) || (cur_time < prev_time)) {
+ valid = false;
+ break;
+ }
+ prev_time = cur_time;
+ }
+
+ if (!valid) {
+ break;
+ }
+ } while ((gps = gps->next));
+
+ if (op) {
+ RNA_boolean_set(op->ptr, "use_timing_data", valid);
+ }
+ return valid;
}
/* Check end_frame is always > start frame! */
-static void gp_convert_set_end_frame(struct Main *UNUSED(main), struct Scene *UNUSED(scene), struct PointerRNA *ptr)
+static void gp_convert_set_end_frame(struct Main *UNUSED(main),
+ struct Scene *UNUSED(scene),
+ struct PointerRNA *ptr)
{
- int start_frame = RNA_int_get(ptr, "start_frame");
- int end_frame = RNA_int_get(ptr, "end_frame");
+ int start_frame = RNA_int_get(ptr, "start_frame");
+ int end_frame = RNA_int_get(ptr, "end_frame");
- if (end_frame <= start_frame) {
- RNA_int_set(ptr, "end_frame", start_frame + 1);
- }
+ if (end_frame <= start_frame) {
+ RNA_int_set(ptr, "end_frame", start_frame + 1);
+ }
}
static bool gp_convert_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
-
- if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
- return false;
- }
-
- bGPdata *gpd = (bGPdata *)ob->data;
- bGPDlayer *gpl = NULL;
- bGPDframe *gpf = NULL;
- ScrArea *sa = 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_eval, GP_GETFRAME_USE_PREV)) &&
- (gpf->strokes.first) &&
- (!GPENCIL_ANY_EDIT_MODE(gpd)));
+ Object *ob = CTX_data_active_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+ return false;
+ }
+
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bGPDlayer *gpl = NULL;
+ bGPDframe *gpf = NULL;
+ ScrArea *sa = 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_eval, GP_GETFRAME_USE_PREV)) &&
+ (gpf->strokes.first) && (!GPENCIL_ANY_EDIT_MODE(gpd)));
}
static int gp_convert_layer_exec(bContext *C, wmOperator *op)
{
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_timing_data");
- Object *ob = CTX_data_active_object(C);
- bGPdata *gpd = (bGPdata *)ob->data;
-
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(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");
- const float rad_fac = RNA_float_get(op->ptr, "radius_multiplier");
- const bool link_strokes = RNA_boolean_get(op->ptr, "use_link_strokes");
- bool valid_timing;
- tGpTimingData gtd;
-
- /* check if there's data to work with */
- if (gpd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data to work on");
- return OPERATOR_CANCELLED;
- }
-
- if (!RNA_property_is_set(op->ptr, prop) && !gp_convert_check_has_valid_timing(C, gpl, op)) {
- BKE_report(op->reports, RPT_WARNING,
- "Current Grease Pencil strokes have no valid timing data, most timing options will be hidden!");
- }
- valid_timing = RNA_property_boolean_get(op->ptr, prop);
-
- gtd.mode = RNA_enum_get(op->ptr, "timing_mode");
- /* Check for illegal timing mode! */
- if (!valid_timing && !ELEM(gtd.mode, GP_STROKECONVERT_TIMING_NONE, GP_STROKECONVERT_TIMING_LINEAR)) {
- gtd.mode = GP_STROKECONVERT_TIMING_LINEAR;
- RNA_enum_set(op->ptr, "timing_mode", gtd.mode);
- }
- if (!link_strokes) {
- gtd.mode = GP_STROKECONVERT_TIMING_NONE;
- }
-
- /* grab all relevant settings */
- gtd.frame_range = RNA_int_get(op->ptr, "frame_range");
- gtd.start_frame = RNA_int_get(op->ptr, "start_frame");
- gtd.realtime = valid_timing ? RNA_boolean_get(op->ptr, "use_realtime") : false;
- gtd.end_frame = RNA_int_get(op->ptr, "end_frame");
- gtd.gap_duration = RNA_float_get(op->ptr, "gap_duration");
- gtd.gap_randomness = RNA_float_get(op->ptr, "gap_randomness");
- gtd.gap_randomness = min_ff(gtd.gap_randomness, gtd.gap_duration);
- gtd.seed = RNA_int_get(op->ptr, "seed");
- gtd.num_points = gtd.cur_point = 0;
- gtd.dists = gtd.times = NULL;
- gtd.tot_dist = gtd.tot_time = gtd.gap_tot_time = 0.0f;
- gtd.inittime = 0.0;
- gtd.offset_time = 0.0f;
-
- /* perform conversion */
- gp_layer_to_curve(C, op->reports, gpd, gpl, mode, norm_weights, rad_fac, link_strokes, &gtd);
-
- /* free temp memory */
- if (gtd.dists) {
- MEM_freeN(gtd.dists);
- gtd.dists = NULL;
- }
- if (gtd.times) {
- MEM_freeN(gtd.times);
- gtd.times = NULL;
- }
-
- /* notifiers */
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
-
- /* done */
- return OPERATOR_FINISHED;
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_timing_data");
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(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");
+ const float rad_fac = RNA_float_get(op->ptr, "radius_multiplier");
+ const bool link_strokes = RNA_boolean_get(op->ptr, "use_link_strokes");
+ bool valid_timing;
+ tGpTimingData gtd;
+
+ /* check if there's data to work with */
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data to work on");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!RNA_property_is_set(op->ptr, prop) && !gp_convert_check_has_valid_timing(C, gpl, op)) {
+ BKE_report(op->reports,
+ RPT_WARNING,
+ "Current Grease Pencil strokes have no valid timing data, most timing options will "
+ "be hidden!");
+ }
+ valid_timing = RNA_property_boolean_get(op->ptr, prop);
+
+ gtd.mode = RNA_enum_get(op->ptr, "timing_mode");
+ /* Check for illegal timing mode! */
+ if (!valid_timing &&
+ !ELEM(gtd.mode, GP_STROKECONVERT_TIMING_NONE, GP_STROKECONVERT_TIMING_LINEAR)) {
+ gtd.mode = GP_STROKECONVERT_TIMING_LINEAR;
+ RNA_enum_set(op->ptr, "timing_mode", gtd.mode);
+ }
+ if (!link_strokes) {
+ gtd.mode = GP_STROKECONVERT_TIMING_NONE;
+ }
+
+ /* grab all relevant settings */
+ gtd.frame_range = RNA_int_get(op->ptr, "frame_range");
+ gtd.start_frame = RNA_int_get(op->ptr, "start_frame");
+ gtd.realtime = valid_timing ? RNA_boolean_get(op->ptr, "use_realtime") : false;
+ gtd.end_frame = RNA_int_get(op->ptr, "end_frame");
+ gtd.gap_duration = RNA_float_get(op->ptr, "gap_duration");
+ gtd.gap_randomness = RNA_float_get(op->ptr, "gap_randomness");
+ gtd.gap_randomness = min_ff(gtd.gap_randomness, gtd.gap_duration);
+ gtd.seed = RNA_int_get(op->ptr, "seed");
+ gtd.num_points = gtd.cur_point = 0;
+ gtd.dists = gtd.times = NULL;
+ gtd.tot_dist = gtd.tot_time = gtd.gap_tot_time = 0.0f;
+ gtd.inittime = 0.0;
+ gtd.offset_time = 0.0f;
+
+ /* perform conversion */
+ gp_layer_to_curve(C, op->reports, gpd, gpl, mode, norm_weights, rad_fac, link_strokes, &gtd);
+
+ /* free temp memory */
+ if (gtd.dists) {
+ MEM_freeN(gtd.dists);
+ gtd.dists = NULL;
+ }
+ if (gtd.times) {
+ MEM_freeN(gtd.times);
+ gtd.times = NULL;
+ }
+
+ /* notifiers */
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
-static bool gp_convert_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop)
+static bool gp_convert_poll_property(const bContext *UNUSED(C),
+ wmOperator *op,
+ const PropertyRNA *prop)
{
- PointerRNA *ptr = op->ptr;
- const char *prop_id = RNA_property_identifier(prop);
- const bool link_strokes = RNA_boolean_get(ptr, "use_link_strokes");
- int timing_mode = RNA_enum_get(ptr, "timing_mode");
- bool realtime = RNA_boolean_get(ptr, "use_realtime");
- float gap_duration = RNA_float_get(ptr, "gap_duration");
- float gap_randomness = RNA_float_get(ptr, "gap_randomness");
- const bool valid_timing = RNA_boolean_get(ptr, "use_timing_data");
-
- /* Always show those props */
- if (STREQ(prop_id, "type") ||
- STREQ(prop_id, "use_normalize_weights") ||
- STREQ(prop_id, "radius_multiplier") ||
- STREQ(prop_id, "use_link_strokes"))
- {
- return true;
- }
-
- /* Never show this prop */
- if (STREQ(prop_id, "use_timing_data"))
- return false;
-
- if (link_strokes) {
- /* Only show when link_stroke is true */
- if (STREQ(prop_id, "timing_mode"))
- return true;
-
- if (timing_mode != GP_STROKECONVERT_TIMING_NONE) {
- /* Only show when link_stroke is true and stroke timing is enabled */
- if (STREQ(prop_id, "frame_range") ||
- STREQ(prop_id, "start_frame"))
- {
- return true;
- }
-
- /* Only show if we have valid timing data! */
- if (valid_timing && STREQ(prop_id, "use_realtime"))
- return true;
-
- /* Only show if realtime or valid_timing is false! */
- if ((!realtime || !valid_timing) && STREQ(prop_id, "end_frame"))
- return true;
-
- if (valid_timing && timing_mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
- /* Only show for custom gaps! */
- if (STREQ(prop_id, "gap_duration"))
- return true;
-
- /* Only show randomness for non-null custom gaps! */
- if (STREQ(prop_id, "gap_randomness") && (gap_duration > 0.0f))
- return true;
-
- /* Only show seed for randomize action! */
- if (STREQ(prop_id, "seed") && (gap_duration > 0.0f) && (gap_randomness > 0.0f))
- return true;
- }
- }
- }
-
- /* Else, hidden! */
- return false;
+ PointerRNA *ptr = op->ptr;
+ const char *prop_id = RNA_property_identifier(prop);
+ const bool link_strokes = RNA_boolean_get(ptr, "use_link_strokes");
+ int timing_mode = RNA_enum_get(ptr, "timing_mode");
+ bool realtime = RNA_boolean_get(ptr, "use_realtime");
+ float gap_duration = RNA_float_get(ptr, "gap_duration");
+ float gap_randomness = RNA_float_get(ptr, "gap_randomness");
+ const bool valid_timing = RNA_boolean_get(ptr, "use_timing_data");
+
+ /* Always show those props */
+ if (STREQ(prop_id, "type") || STREQ(prop_id, "use_normalize_weights") ||
+ STREQ(prop_id, "radius_multiplier") || STREQ(prop_id, "use_link_strokes")) {
+ return true;
+ }
+
+ /* Never show this prop */
+ if (STREQ(prop_id, "use_timing_data"))
+ return false;
+
+ if (link_strokes) {
+ /* Only show when link_stroke is true */
+ if (STREQ(prop_id, "timing_mode"))
+ return true;
+
+ if (timing_mode != GP_STROKECONVERT_TIMING_NONE) {
+ /* Only show when link_stroke is true and stroke timing is enabled */
+ if (STREQ(prop_id, "frame_range") || STREQ(prop_id, "start_frame")) {
+ return true;
+ }
+
+ /* Only show if we have valid timing data! */
+ if (valid_timing && STREQ(prop_id, "use_realtime"))
+ return true;
+
+ /* Only show if realtime or valid_timing is false! */
+ if ((!realtime || !valid_timing) && STREQ(prop_id, "end_frame"))
+ return true;
+
+ if (valid_timing && timing_mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
+ /* Only show for custom gaps! */
+ if (STREQ(prop_id, "gap_duration"))
+ return true;
+
+ /* Only show randomness for non-null custom gaps! */
+ if (STREQ(prop_id, "gap_randomness") && (gap_duration > 0.0f))
+ return true;
+
+ /* Only show seed for randomize action! */
+ if (STREQ(prop_id, "seed") && (gap_duration > 0.0f) && (gap_randomness > 0.0f))
+ return true;
+ }
+ }
+ }
+
+ /* Else, hidden! */
+ return false;
}
void GPENCIL_OT_convert(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Convert Grease Pencil";
- ot->idname = "GPENCIL_OT_convert";
- ot->description = "Convert the active Grease Pencil layer to a new Curve Object";
-
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = gp_convert_layer_exec;
- ot->poll = gp_convert_poll;
- ot->poll_property = gp_convert_poll_property;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", "Which type of curve to convert to");
-
- RNA_def_boolean(ot->srna, "use_normalize_weights", true, "Normalize Weight",
- "Normalize weight (set from stroke width)");
- RNA_def_float(ot->srna, "radius_multiplier", 1.0f, 0.0f, 1000.0f, "Radius Fac",
- "Multiplier for the points' radii (set from stroke width)", 0.0f, 10.0f);
- RNA_def_boolean(ot->srna, "use_link_strokes", false, "Link Strokes",
- "Whether to link strokes with zero-radius sections of curves");
-
- prop = RNA_def_enum(ot->srna, "timing_mode", prop_gpencil_convert_timingmodes, GP_STROKECONVERT_TIMING_FULL,
- "Timing Mode", "How to use timing data stored in strokes");
- RNA_def_enum_funcs(prop, rna_GPConvert_mode_items);
-
- RNA_def_int(ot->srna, "frame_range", 100, 1, 10000, "Frame Range",
- "The duration of evaluation of the path control curve", 1, 1000);
- RNA_def_int(ot->srna, "start_frame", 1, 1, 100000, "Start Frame",
- "The start frame of the path control curve", 1, 100000);
- RNA_def_boolean(ot->srna, "use_realtime", false, "Realtime",
- "Whether the path control curve reproduces the drawing in realtime, starting from Start Frame");
- prop = RNA_def_int(ot->srna, "end_frame", 250, 1, 100000, "End Frame",
- "The end frame of the path control curve (if Realtime is not set)", 1, 100000);
- RNA_def_property_update_runtime(prop, gp_convert_set_end_frame);
-
- RNA_def_float(ot->srna, "gap_duration", 0.0f, 0.0f, 10000.0f, "Gap Duration",
- "Custom Gap mode: (Average) length of gaps, in frames "
- "(Note: Realtime value, will be scaled if Realtime is not set)", 0.0f, 1000.0f);
- RNA_def_float(ot->srna, "gap_randomness", 0.0f, 0.0f, 10000.0f, "Gap Randomness",
- "Custom Gap mode: Number of frames that gap lengths can vary", 0.0f, 1000.0f);
- RNA_def_int(ot->srna, "seed", 0, 0, 1000, "Random Seed",
- "Custom Gap mode: Random generator seed", 0, 100);
-
- /* Note: Internal use, this one will always be hidden by UI code... */
- prop = RNA_def_boolean(ot->srna, "use_timing_data", false, "Has Valid Timing",
- "Whether the converted Grease Pencil layer has valid timing data (internal use)");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Convert Grease Pencil";
+ ot->idname = "GPENCIL_OT_convert";
+ ot->description = "Convert the active Grease Pencil layer to a new Curve Object";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = gp_convert_layer_exec;
+ ot->poll = gp_convert_poll;
+ ot->poll_property = gp_convert_poll_property;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", "Which type of curve to convert to");
+
+ RNA_def_boolean(ot->srna,
+ "use_normalize_weights",
+ true,
+ "Normalize Weight",
+ "Normalize weight (set from stroke width)");
+ RNA_def_float(ot->srna,
+ "radius_multiplier",
+ 1.0f,
+ 0.0f,
+ 1000.0f,
+ "Radius Fac",
+ "Multiplier for the points' radii (set from stroke width)",
+ 0.0f,
+ 10.0f);
+ RNA_def_boolean(ot->srna,
+ "use_link_strokes",
+ false,
+ "Link Strokes",
+ "Whether to link strokes with zero-radius sections of curves");
+
+ prop = RNA_def_enum(ot->srna,
+ "timing_mode",
+ prop_gpencil_convert_timingmodes,
+ GP_STROKECONVERT_TIMING_FULL,
+ "Timing Mode",
+ "How to use timing data stored in strokes");
+ RNA_def_enum_funcs(prop, rna_GPConvert_mode_items);
+
+ RNA_def_int(ot->srna,
+ "frame_range",
+ 100,
+ 1,
+ 10000,
+ "Frame Range",
+ "The duration of evaluation of the path control curve",
+ 1,
+ 1000);
+ RNA_def_int(ot->srna,
+ "start_frame",
+ 1,
+ 1,
+ 100000,
+ "Start Frame",
+ "The start frame of the path control curve",
+ 1,
+ 100000);
+ RNA_def_boolean(ot->srna,
+ "use_realtime",
+ false,
+ "Realtime",
+ "Whether the path control curve reproduces the drawing in realtime, starting "
+ "from Start Frame");
+ prop = RNA_def_int(ot->srna,
+ "end_frame",
+ 250,
+ 1,
+ 100000,
+ "End Frame",
+ "The end frame of the path control curve (if Realtime is not set)",
+ 1,
+ 100000);
+ RNA_def_property_update_runtime(prop, gp_convert_set_end_frame);
+
+ RNA_def_float(ot->srna,
+ "gap_duration",
+ 0.0f,
+ 0.0f,
+ 10000.0f,
+ "Gap Duration",
+ "Custom Gap mode: (Average) length of gaps, in frames "
+ "(Note: Realtime value, will be scaled if Realtime is not set)",
+ 0.0f,
+ 1000.0f);
+ RNA_def_float(ot->srna,
+ "gap_randomness",
+ 0.0f,
+ 0.0f,
+ 10000.0f,
+ "Gap Randomness",
+ "Custom Gap mode: Number of frames that gap lengths can vary",
+ 0.0f,
+ 1000.0f);
+ RNA_def_int(ot->srna,
+ "seed",
+ 0,
+ 0,
+ 1000,
+ "Random Seed",
+ "Custom Gap mode: Random generator seed",
+ 0,
+ 100);
+
+ /* Note: Internal use, this one will always be hidden by UI code... */
+ prop = RNA_def_boolean(
+ ot->srna,
+ "use_timing_data",
+ false,
+ "Has Valid Timing",
+ "Whether the converted Grease Pencil layer has valid timing data (internal use)");
+ 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 a49f6a0d414..c91c543e746 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -22,7 +22,6 @@
* \ingroup edgpencil
*/
-
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -91,81 +90,81 @@
/* ******************* Add New Data ************************ */
static bool gp_data_add_poll(bContext *C)
{
- Object *obact = CTX_data_active_object(C);
- if (obact && obact->type == OB_GPENCIL) {
- if (obact->mode != OB_MODE_OBJECT) {
- return false;
- }
- }
+ Object *obact = CTX_data_active_object(C);
+ if (obact && obact->type == OB_GPENCIL) {
+ if (obact->mode != OB_MODE_OBJECT) {
+ return false;
+ }
+ }
- /* the base line we have is that we have somewhere to add Grease Pencil data */
- return ED_gpencil_data_get_pointers(C, NULL) != NULL;
+ /* the base line we have is that we have somewhere to add Grease Pencil data */
+ return ED_gpencil_data_get_pointers(C, NULL) != NULL;
}
/* add new datablock - wrapper around API */
static int gp_data_add_exec(bContext *C, wmOperator *op)
{
- PointerRNA gpd_owner = {{NULL}};
- bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, &gpd_owner);
- bool is_annotation = ED_gpencil_data_owner_is_annotation(&gpd_owner);
+ PointerRNA gpd_owner = {{NULL}};
+ bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, &gpd_owner);
+ bool is_annotation = ED_gpencil_data_owner_is_annotation(&gpd_owner);
- if (gpd_ptr == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
- return OPERATOR_CANCELLED;
- }
- else {
- /* decrement user count and add new datablock */
- /* TODO: if a datablock exists,
- * we should make a copy of it instead of starting fresh (as in other areas) */
- Main *bmain = CTX_data_main(C);
+ if (gpd_ptr == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* decrement user count and add new datablock */
+ /* TODO: if a datablock exists,
+ * we should make a copy of it instead of starting fresh (as in other areas) */
+ Main *bmain = CTX_data_main(C);
- /* decrement user count of old GP datablock */
- if (*gpd_ptr) {
- bGPdata *gpd = (*gpd_ptr);
- id_us_min(&gpd->id);
- }
+ /* decrement user count of old GP datablock */
+ if (*gpd_ptr) {
+ bGPdata *gpd = (*gpd_ptr);
+ id_us_min(&gpd->id);
+ }
- /* add new datablock, with a single layer ready to use (so users don't have to perform an extra step) */
- if (is_annotation) {
- bGPdata *gpd = BKE_gpencil_data_addnew(bmain, DATA_("Annotations"));
- *gpd_ptr = gpd;
+ /* add new datablock, with a single layer ready to use (so users don't have to perform an extra step) */
+ if (is_annotation) {
+ bGPdata *gpd = BKE_gpencil_data_addnew(bmain, DATA_("Annotations"));
+ *gpd_ptr = gpd;
- /* tag for annotations */
- gpd->flag |= GP_DATA_ANNOTATIONS;
+ /* tag for annotations */
+ gpd->flag |= GP_DATA_ANNOTATIONS;
- /* add new layer (i.e. a "note") */
- BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("Note"), true);
- }
- else {
- /* GP Object Case - This shouldn't happen! */
- *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
+ /* add new layer (i.e. a "note") */
+ BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("Note"), true);
+ }
+ else {
+ /* GP Object Case - This shouldn't happen! */
+ *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
- /* add default sets of colors and brushes */
- Object *ob = CTX_data_active_object(C);
- ED_gpencil_add_defaults(C, ob);
+ /* add default sets of colors and brushes */
+ Object *ob = CTX_data_active_object(C);
+ ED_gpencil_add_defaults(C, ob);
- /* add new layer */
- BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), true);
- }
- }
+ /* add new layer */
+ BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), true);
+ }
+ }
- /* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_data_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Grease Pencil Add New";
- ot->idname = "GPENCIL_OT_data_add";
- ot->description = "Add new Grease Pencil data-block";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Grease Pencil Add New";
+ ot->idname = "GPENCIL_OT_data_add";
+ ot->description = "Add new Grease Pencil data-block";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* callbacks */
- ot->exec = gp_data_add_exec;
- ot->poll = gp_data_add_poll;
+ /* callbacks */
+ ot->exec = gp_data_add_exec;
+ ot->poll = gp_data_add_poll;
}
/* ******************* Unlink Data ************************ */
@@ -173,57 +172,55 @@ void GPENCIL_OT_data_add(wmOperatorType *ot)
/* poll callback for adding data/layers - special */
static bool gp_data_unlink_poll(bContext *C)
{
- bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
+ bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
- /* only unlink annotation datablocks */
- if ((gpd_ptr != NULL) && (*gpd_ptr != NULL)) {
- bGPdata *gpd = (*gpd_ptr);
- if ((gpd->flag & GP_DATA_ANNOTATIONS) == 0) {
- return false;
- }
- }
- /* if we have access to some active data, make sure there's a datablock before enabling this */
- return (gpd_ptr && *gpd_ptr);
+ /* only unlink annotation datablocks */
+ if ((gpd_ptr != NULL) && (*gpd_ptr != NULL)) {
+ bGPdata *gpd = (*gpd_ptr);
+ if ((gpd->flag & GP_DATA_ANNOTATIONS) == 0) {
+ return false;
+ }
+ }
+ /* if we have access to some active data, make sure there's a datablock before enabling this */
+ return (gpd_ptr && *gpd_ptr);
}
-
/* unlink datablock - wrapper around API */
static int gp_data_unlink_exec(bContext *C, wmOperator *op)
{
- bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
+ bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
- if (gpd_ptr == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
- return OPERATOR_CANCELLED;
- }
- else {
- /* just unlink datablock now, decreasing its user count */
- bGPdata *gpd = (*gpd_ptr);
+ if (gpd_ptr == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* just unlink datablock now, decreasing its user count */
+ bGPdata *gpd = (*gpd_ptr);
- id_us_min(&gpd->id);
- *gpd_ptr = NULL;
- }
+ id_us_min(&gpd->id);
+ *gpd_ptr = NULL;
+ }
- /* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_data_unlink(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Annotation Unlink";
- ot->idname = "GPENCIL_OT_data_unlink";
- ot->description = "Unlink active Annotation data-block";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Annotation Unlink";
+ ot->idname = "GPENCIL_OT_data_unlink";
+ ot->description = "Unlink active Annotation data-block";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* callbacks */
- ot->exec = gp_data_unlink_exec;
- ot->poll = gp_data_unlink_poll;
+ /* callbacks */
+ ot->exec = gp_data_unlink_exec;
+ ot->poll = gp_data_unlink_poll;
}
-
/* ************************************************ */
/* Layer Operators */
@@ -232,618 +229,636 @@ void GPENCIL_OT_data_unlink(wmOperatorType *ot)
/* add new layer - wrapper around API */
static int gp_layer_add_exec(bContext *C, wmOperator *op)
{
- PointerRNA gpd_owner = {{NULL}};
- bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, &gpd_owner);
- bool is_annotation = ED_gpencil_data_owner_is_annotation(&gpd_owner);
-
- /* if there's no existing Grease-Pencil data there, add some */
- if (gpd_ptr == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
- return OPERATOR_CANCELLED;
- }
-
- if (*gpd_ptr == NULL) {
- Main *bmain = CTX_data_main(C);
- if (is_annotation) {
- /* Annotations */
- *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("Annotations"));
-
- /* mark as annotation */
- (*gpd_ptr)->flag |= GP_DATA_ANNOTATIONS;
- }
- else {
- /* GP Object */
- /* NOTE: This shouldn't actually happen in practice */
- *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
-
- /* add default sets of colors and brushes */
- Object *ob = CTX_data_active_object(C);
- ED_gpencil_add_defaults(C, ob);
- }
- }
-
- /* add new layer now */
- if (is_annotation) {
- BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("Note"), true);
- }
- else {
- BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), true);
- }
-
- /* notifiers */
- bGPdata *gpd = *gpd_ptr;
- 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;
+ PointerRNA gpd_owner = {{NULL}};
+ bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, &gpd_owner);
+ bool is_annotation = ED_gpencil_data_owner_is_annotation(&gpd_owner);
+
+ /* if there's no existing Grease-Pencil data there, add some */
+ if (gpd_ptr == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (*gpd_ptr == NULL) {
+ Main *bmain = CTX_data_main(C);
+ if (is_annotation) {
+ /* Annotations */
+ *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("Annotations"));
+
+ /* mark as annotation */
+ (*gpd_ptr)->flag |= GP_DATA_ANNOTATIONS;
+ }
+ else {
+ /* GP Object */
+ /* NOTE: This shouldn't actually happen in practice */
+ *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
+
+ /* add default sets of colors and brushes */
+ Object *ob = CTX_data_active_object(C);
+ ED_gpencil_add_defaults(C, ob);
+ }
+ }
+
+ /* add new layer now */
+ if (is_annotation) {
+ BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("Note"), true);
+ }
+ else {
+ BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), true);
+ }
+
+ /* notifiers */
+ bGPdata *gpd = *gpd_ptr;
+ 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_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add New Layer";
- ot->idname = "GPENCIL_OT_layer_add";
- ot->description = "Add new layer or note for the active data-block";
+ /* identifiers */
+ ot->name = "Add New Layer";
+ ot->idname = "GPENCIL_OT_layer_add";
+ ot->description = "Add new layer or note for the active data-block";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* callbacks */
- ot->exec = gp_layer_add_exec;
- ot->poll = gp_add_poll;
+ /* callbacks */
+ ot->exec = gp_layer_add_exec;
+ ot->poll = gp_add_poll;
}
/* ******************* Remove Active Layer ************************* */
static int gp_layer_remove_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
- /* sanity checks */
- if (ELEM(NULL, gpd, gpl))
- return OPERATOR_CANCELLED;
+ /* sanity checks */
+ if (ELEM(NULL, gpd, gpl))
+ return OPERATOR_CANCELLED;
- if (gpl->flag & GP_LAYER_LOCKED) {
- BKE_report(op->reports, RPT_ERROR, "Cannot delete locked layers");
- return OPERATOR_CANCELLED;
- }
+ if (gpl->flag & GP_LAYER_LOCKED) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot delete locked layers");
+ return OPERATOR_CANCELLED;
+ }
- /* make the layer before this the new active layer
- * - use the one after if this is the first
- * - if this is the only layer, this naturally becomes NULL
- */
- if (gpl->prev)
- BKE_gpencil_layer_setactive(gpd, gpl->prev);
- else
- BKE_gpencil_layer_setactive(gpd, gpl->next);
+ /* make the layer before this the new active layer
+ * - use the one after if this is the first
+ * - if this is the only layer, this naturally becomes NULL
+ */
+ if (gpl->prev)
+ BKE_gpencil_layer_setactive(gpd, gpl->prev);
+ else
+ BKE_gpencil_layer_setactive(gpd, gpl->next);
- /* delete the layer now... */
- BKE_gpencil_layer_delete(gpd, gpl);
+ /* delete the layer now... */
+ BKE_gpencil_layer_delete(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);
+ /* 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;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_layer_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Layer";
- ot->idname = "GPENCIL_OT_layer_remove";
- ot->description = "Remove active Grease Pencil layer";
+ /* identifiers */
+ ot->name = "Remove Layer";
+ ot->idname = "GPENCIL_OT_layer_remove";
+ ot->description = "Remove active Grease Pencil layer";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* callbacks */
- ot->exec = gp_layer_remove_exec;
- ot->poll = gp_active_layer_poll;
+ /* callbacks */
+ ot->exec = gp_layer_remove_exec;
+ ot->poll = gp_active_layer_poll;
}
/* ******************* Move Layer Up/Down ************************** */
enum {
- GP_LAYER_MOVE_UP = -1,
- GP_LAYER_MOVE_DOWN = 1,
+ GP_LAYER_MOVE_UP = -1,
+ GP_LAYER_MOVE_DOWN = 1,
};
static int gp_layer_move_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
- const int direction = RNA_enum_get(op->ptr, "type") * -1;
+ const int direction = RNA_enum_get(op->ptr, "type") * -1;
- /* sanity checks */
- if (ELEM(NULL, gpd, gpl))
- return OPERATOR_CANCELLED;
+ /* sanity checks */
+ if (ELEM(NULL, gpd, gpl))
+ return OPERATOR_CANCELLED;
- BLI_assert(ELEM(direction, -1, 0, 1)); /* we use value below */
- if (BLI_listbase_link_move(&gpd->layers, gpl, direction)) {
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
- }
+ BLI_assert(ELEM(direction, -1, 0, 1)); /* we use value below */
+ if (BLI_listbase_link_move(&gpd->layers, gpl, direction)) {
+ 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;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_layer_move(wmOperatorType *ot)
{
- static const EnumPropertyItem slot_move[] = {
- {GP_LAYER_MOVE_UP, "UP", 0, "Up", ""},
- {GP_LAYER_MOVE_DOWN, "DOWN", 0, "Down", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem slot_move[] = {
+ {GP_LAYER_MOVE_UP, "UP", 0, "Up", ""},
+ {GP_LAYER_MOVE_DOWN, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Move Grease Pencil Layer";
- ot->idname = "GPENCIL_OT_layer_move";
- ot->description = "Move the active Grease Pencil layer up/down in the list";
+ /* identifiers */
+ ot->name = "Move Grease Pencil Layer";
+ ot->idname = "GPENCIL_OT_layer_move";
+ ot->description = "Move the active Grease Pencil layer up/down in the list";
- /* api callbacks */
- ot->exec = gp_layer_move_exec;
- ot->poll = gp_active_layer_poll;
+ /* api callbacks */
+ ot->exec = gp_layer_move_exec;
+ ot->poll = gp_active_layer_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
}
/* ********************* Duplicate Layer ************************** */
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 *new_layer;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *new_layer;
- /* sanity checks */
- if (ELEM(NULL, gpd, gpl))
- return OPERATOR_CANCELLED;
+ /* sanity checks */
+ if (ELEM(NULL, gpd, gpl))
+ return OPERATOR_CANCELLED;
- /* make copy of layer, and add it immediately after the existing layer */
- new_layer = BKE_gpencil_layer_duplicate(gpl);
- BLI_insertlinkafter(&gpd->layers, gpl, new_layer);
+ /* make copy of layer, and add it immediately after the existing layer */
+ new_layer = BKE_gpencil_layer_duplicate(gpl);
+ BLI_insertlinkafter(&gpd->layers, gpl, new_layer);
- /* ensure new layer has a unique name, and is now the active layer */
- BLI_uniquename(&gpd->layers, new_layer, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(new_layer->info));
- BKE_gpencil_layer_setactive(gpd, new_layer);
+ /* ensure new layer has a unique name, and is now the active layer */
+ BLI_uniquename(&gpd->layers,
+ new_layer,
+ DATA_("GP_Layer"),
+ '.',
+ offsetof(bGPDlayer, info),
+ sizeof(new_layer->info));
+ BKE_gpencil_layer_setactive(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);
+ /* 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;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_layer_duplicate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Duplicate Layer";
- ot->idname = "GPENCIL_OT_layer_duplicate";
- ot->description = "Make a copy of the active Grease Pencil layer";
+ /* identifiers */
+ ot->name = "Duplicate Layer";
+ ot->idname = "GPENCIL_OT_layer_duplicate";
+ ot->description = "Make a copy of the active Grease Pencil layer";
- /* callbacks */
- ot->exec = gp_layer_copy_exec;
- ot->poll = gp_active_layer_poll;
+ /* callbacks */
+ ot->exec = gp_layer_copy_exec;
+ ot->poll = gp_active_layer_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************* Duplicate Layer in a new object ************************** */
enum {
- GP_LAYER_COPY_OBJECT_ALL_FRAME = 0,
- GP_LAYER_COPY_OBJECT_ACT_FRAME = 1,
+ GP_LAYER_COPY_OBJECT_ALL_FRAME = 0,
+ GP_LAYER_COPY_OBJECT_ACT_FRAME = 1,
};
static bool gp_layer_duplicate_object_poll(bContext *C)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = CTX_data_active_object(C);
- if ((ob == NULL) || (ob->type != OB_GPENCIL))
- return false;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL))
+ return false;
- bGPdata *gpd = (bGPdata *)ob->data;
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
- if (gpl == NULL)
- return false;
+ if (gpl == NULL)
+ return false;
- /* check there are more grease pencil objects */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if ((base->object != ob) && (base->object->type == OB_GPENCIL))
- return true;
- }
+ /* check there are more grease pencil objects */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if ((base->object != ob) && (base->object->type == OB_GPENCIL))
+ return true;
+ }
- return false;
+ return false;
}
static int gp_layer_duplicate_object_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- char name[MAX_ID_NAME - 2];
- RNA_string_get(op->ptr, "object", name);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ char name[MAX_ID_NAME - 2];
+ RNA_string_get(op->ptr, "object", name);
- if (name[0] == '\0') {
- return OPERATOR_CANCELLED;
- }
+ if (name[0] == '\0') {
+ return OPERATOR_CANCELLED;
+ }
- Object *ob_dst = (Object *)BKE_scene_object_find_by_name(scene, name);
+ Object *ob_dst = (Object *)BKE_scene_object_find_by_name(scene, name);
- int mode = RNA_enum_get(op->ptr, "mode");
+ int mode = RNA_enum_get(op->ptr, "mode");
- Object *ob_src = CTX_data_active_object(C);
- bGPdata *gpd_src = (bGPdata *)ob_src->data;
- bGPDlayer *gpl_src = BKE_gpencil_layer_getactive(gpd_src);
+ Object *ob_src = CTX_data_active_object(C);
+ bGPdata *gpd_src = (bGPdata *)ob_src->data;
+ bGPDlayer *gpl_src = BKE_gpencil_layer_getactive(gpd_src);
- /* sanity checks */
- if (ELEM(NULL, gpd_src, gpl_src, ob_dst)) {
- return OPERATOR_CANCELLED;
- }
- /* cannot copy itself and check destination type */
- if ((ob_src == ob_dst) || (ob_dst->type != OB_GPENCIL)) {
- return OPERATOR_CANCELLED;
- }
+ /* sanity checks */
+ if (ELEM(NULL, gpd_src, gpl_src, ob_dst)) {
+ return OPERATOR_CANCELLED;
+ }
+ /* cannot copy itself and check destination type */
+ if ((ob_src == ob_dst) || (ob_dst->type != OB_GPENCIL)) {
+ return OPERATOR_CANCELLED;
+ }
- bGPdata *gpd_dst = (bGPdata *)ob_dst->data;
+ bGPdata *gpd_dst = (bGPdata *)ob_dst->data;
- /* make copy of layer */
- bGPDlayer *gpl_dst = MEM_dupallocN(gpl_src);
- gpl_dst->prev = gpl_dst->next = NULL;
- BLI_addtail(&gpd_dst->layers, gpl_dst);
- BLI_uniquename(&gpd_dst->layers, gpl_dst, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(gpl_dst->info));
+ /* make copy of layer */
+ bGPDlayer *gpl_dst = MEM_dupallocN(gpl_src);
+ gpl_dst->prev = gpl_dst->next = NULL;
+ BLI_addtail(&gpd_dst->layers, gpl_dst);
+ BLI_uniquename(&gpd_dst->layers,
+ gpl_dst,
+ DATA_("GP_Layer"),
+ '.',
+ offsetof(bGPDlayer, info),
+ sizeof(gpl_dst->info));
- /* copy frames */
- BLI_listbase_clear(&gpl_dst->frames);
- for (bGPDframe *gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) {
+ /* copy frames */
+ BLI_listbase_clear(&gpl_dst->frames);
+ for (bGPDframe *gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) {
- if ((mode == GP_LAYER_COPY_OBJECT_ACT_FRAME) && (gpf_src != gpl_src->actframe)) {
- continue;
- }
+ if ((mode == GP_LAYER_COPY_OBJECT_ACT_FRAME) && (gpf_src != gpl_src->actframe)) {
+ continue;
+ }
- /* make a copy of source frame */
- bGPDframe *gpf_dst = MEM_dupallocN(gpf_src);
- gpf_dst->prev = gpf_dst->next = NULL;
- BLI_addtail(&gpl_dst->frames, gpf_dst);
+ /* make a copy of source frame */
+ bGPDframe *gpf_dst = MEM_dupallocN(gpf_src);
+ gpf_dst->prev = gpf_dst->next = NULL;
+ BLI_addtail(&gpl_dst->frames, gpf_dst);
- /* copy strokes */
- BLI_listbase_clear(&gpf_dst->strokes);
- for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
+ /* copy strokes */
+ BLI_listbase_clear(&gpf_dst->strokes);
+ for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
- /* make copy of source stroke */
- bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
+ /* make copy of source stroke */
+ bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
- /* 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);
- int idx = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src);
+ /* 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);
+ int idx = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src);
- /* reasign the stroke material to the right slot in destination object */
- gps_dst->mat_nr = idx;
+ /* reasign the stroke material to the right slot in destination object */
+ gps_dst->mat_nr = idx;
- /* add new stroke to frame */
- BLI_addtail(&gpf_dst->strokes, gps_dst);
- }
- }
+ /* add new stroke to frame */
+ BLI_addtail(&gpf_dst->strokes, gps_dst);
+ }
+ }
- /* notifiers */
- DEG_id_tag_update(&gpd_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ /* notifiers */
+ DEG_id_tag_update(&gpd_dst->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+ DEG_id_tag_update(&ob_dst->id, ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_layer_duplicate_object(wmOperatorType *ot)
{
- static const EnumPropertyItem copy_mode[] = {
- {GP_LAYER_COPY_OBJECT_ALL_FRAME, "ALL", 0, "All Frames", ""},
- {GP_LAYER_COPY_OBJECT_ACT_FRAME, "ACTIVE", 0, "Active Frame", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem copy_mode[] = {
+ {GP_LAYER_COPY_OBJECT_ALL_FRAME, "ALL", 0, "All Frames", ""},
+ {GP_LAYER_COPY_OBJECT_ACT_FRAME, "ACTIVE", 0, "Active Frame", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Duplicate Layer to new Object";
- ot->idname = "GPENCIL_OT_layer_duplicate_object";
- ot->description = "Make a copy of the active Grease Pencil layer to new object";
+ /* identifiers */
+ ot->name = "Duplicate Layer to new Object";
+ ot->idname = "GPENCIL_OT_layer_duplicate_object";
+ ot->description = "Make a copy of the active Grease Pencil layer to new object";
- /* callbacks */
- ot->exec = gp_layer_duplicate_object_exec;
- ot->poll = gp_layer_duplicate_object_poll;
+ /* callbacks */
+ ot->exec = gp_layer_duplicate_object_exec;
+ ot->poll = gp_layer_duplicate_object_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_string(ot->srna, "object", NULL, MAX_ID_NAME - 2, "Object", "Name of the destination object");
- RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ ot->prop = RNA_def_string(
+ ot->srna, "object", NULL, MAX_ID_NAME - 2, "Object", "Name of the destination object");
+ RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- RNA_def_enum(ot->srna, "mode", copy_mode, GP_LAYER_COPY_OBJECT_ALL_FRAME, "Mode", "");
+ RNA_def_enum(ot->srna, "mode", copy_mode, GP_LAYER_COPY_OBJECT_ALL_FRAME, "Mode", "");
}
/* ********************* Duplicate Frame ************************** */
enum {
- GP_FRAME_DUP_ACTIVE = 0,
- GP_FRAME_DUP_ALL = 1,
+ GP_FRAME_DUP_ACTIVE = 0,
+ GP_FRAME_DUP_ALL = 1,
};
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);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
- int mode = RNA_enum_get(op->ptr, "mode");
+ int mode = RNA_enum_get(op->ptr, "mode");
- /* sanity checks */
- if (ELEM(NULL, gpd, gpl))
- return OPERATOR_CANCELLED;
+ /* sanity checks */
+ if (ELEM(NULL, gpd, gpl))
+ return OPERATOR_CANCELLED;
- if (mode == 0) {
- BKE_gpencil_frame_addcopy(gpl, cfra_eval);
- }
- else {
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if ((gpl->flag & GP_LAYER_LOCKED) == 0) {
- BKE_gpencil_frame_addcopy(gpl, cfra_eval);
- }
- }
+ if (mode == 0) {
+ BKE_gpencil_frame_addcopy(gpl, cfra_eval);
+ }
+ else {
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if ((gpl->flag & GP_LAYER_LOCKED) == 0) {
+ BKE_gpencil_frame_addcopy(gpl, cfra_eval);
+ }
+ }
+ }
+ /* 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);
- }
- /* 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;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_frame_duplicate(wmOperatorType *ot)
{
- static const EnumPropertyItem duplicate_mode[] = {
- {GP_FRAME_DUP_ACTIVE, "ACTIVE", 0, "Active", "Duplicate frame in active layer only"},
- {GP_FRAME_DUP_ALL, "ALL", 0, "All", "Duplicate active frames in all layers"},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem duplicate_mode[] = {
+ {GP_FRAME_DUP_ACTIVE, "ACTIVE", 0, "Active", "Duplicate frame in active layer only"},
+ {GP_FRAME_DUP_ALL, "ALL", 0, "All", "Duplicate active frames in all layers"},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Duplicate Frame";
- ot->idname = "GPENCIL_OT_frame_duplicate";
- ot->description = "Make a copy of the active Grease Pencil Frame";
+ /* identifiers */
+ ot->name = "Duplicate Frame";
+ ot->idname = "GPENCIL_OT_frame_duplicate";
+ ot->description = "Make a copy of the active Grease Pencil Frame";
- /* callbacks */
- ot->exec = gp_frame_duplicate_exec;
- ot->poll = gp_active_layer_poll;
+ /* callbacks */
+ ot->exec = gp_frame_duplicate_exec;
+ ot->poll = gp_active_layer_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "mode", duplicate_mode, GP_FRAME_DUP_ACTIVE, "Mode", "");
+ ot->prop = RNA_def_enum(ot->srna, "mode", duplicate_mode, GP_FRAME_DUP_ACTIVE, "Mode", "");
}
/* ********************* Clean Fill Boundaries on Frame ************************** */
enum {
- GP_FRAME_CLEAN_FILL_ACTIVE = 0,
- GP_FRAME_CLEAN_FILL_ALL = 1,
+ GP_FRAME_CLEAN_FILL_ACTIVE = 0,
+ GP_FRAME_CLEAN_FILL_ALL = 1,
};
static int gp_frame_clean_fill_exec(bContext *C, wmOperator *op)
{
- bool changed = false;
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- int mode = RNA_enum_get(op->ptr, "mode");
-
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- bGPDframe *init_gpf = gpl->actframe;
- if (mode == GP_FRAME_CLEAN_FILL_ALL) {
- init_gpf = gpl->frames.first;
- }
-
- 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;
-
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps) == false)
- continue;
-
- /* free stroke */
- if (gps->flag & GP_STROKE_NOFILL) {
- /* free stroke memory arrays, then stroke itself */
- if (gps->points) {
- MEM_freeN(gps->points);
- }
- if (gps->dvert) {
- BKE_gpencil_free_stroke_weights(gps);
- MEM_freeN(gps->dvert);
- }
- MEM_SAFE_FREE(gps->triangles);
- BLI_freelinkN(&gpf->strokes, gps);
-
- changed = true;
- }
- }
- }
- }
- }
- 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);
- }
-
- return OPERATOR_FINISHED;
+ bool changed = false;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ int mode = RNA_enum_get(op->ptr, "mode");
+
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ bGPDframe *init_gpf = gpl->actframe;
+ if (mode == GP_FRAME_CLEAN_FILL_ALL) {
+ init_gpf = gpl->frames.first;
+ }
+
+ 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;
+
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
+ /* free stroke */
+ if (gps->flag & GP_STROKE_NOFILL) {
+ /* free stroke memory arrays, then stroke itself */
+ if (gps->points) {
+ MEM_freeN(gps->points);
+ }
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
+ MEM_SAFE_FREE(gps->triangles);
+ BLI_freelinkN(&gpf->strokes, gps);
+
+ changed = true;
+ }
+ }
+ }
+ }
+ }
+ 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);
+ }
+
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_frame_clean_fill(wmOperatorType *ot)
{
- static const EnumPropertyItem duplicate_mode[] = {
- {GP_FRAME_CLEAN_FILL_ACTIVE, "ACTIVE", 0, "Active Frame Only", "Clean active frame only"},
- {GP_FRAME_CLEAN_FILL_ALL, "ALL", 0, "All Frames", "Clean all frames in all layers"},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem duplicate_mode[] = {
+ {GP_FRAME_CLEAN_FILL_ACTIVE, "ACTIVE", 0, "Active Frame Only", "Clean active frame only"},
+ {GP_FRAME_CLEAN_FILL_ALL, "ALL", 0, "All Frames", "Clean all frames in all layers"},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Clean Fill Boundaries";
- ot->idname = "GPENCIL_OT_frame_clean_fill";
- ot->description = "Remove 'no fill' boundary strokes";
+ /* identifiers */
+ ot->name = "Clean Fill Boundaries";
+ ot->idname = "GPENCIL_OT_frame_clean_fill";
+ ot->description = "Remove 'no fill' boundary strokes";
- /* callbacks */
- ot->exec = gp_frame_clean_fill_exec;
- ot->poll = gp_active_layer_poll;
+ /* callbacks */
+ ot->exec = gp_frame_clean_fill_exec;
+ ot->poll = gp_active_layer_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "mode", duplicate_mode, GP_FRAME_DUP_ACTIVE, "Mode", "");
+ ot->prop = RNA_def_enum(ot->srna, "mode", duplicate_mode, GP_FRAME_DUP_ACTIVE, "Mode", "");
}
/* ********************* Clean Loose Boundaries on Frame ************************** */
static int gp_frame_clean_loose_exec(bContext *C, wmOperator *op)
{
- bool changed = false;
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- int limit = RNA_int_get(op->ptr, "limit");
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
-
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- bGPDframe *init_gpf = gpl->actframe;
- bGPDstroke *gps = NULL;
- bGPDstroke *gpsn = NULL;
- 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))) {
- if (gpf == NULL)
- continue;
-
- /* simply delete strokes which are no loose */
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
-
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps) == false)
- continue;
-
- /* free stroke */
- if (gps->totpoints <= limit) {
- /* free stroke memory arrays, then stroke itself */
- if (gps->points) {
- MEM_freeN(gps->points);
- }
- if (gps->dvert) {
- BKE_gpencil_free_stroke_weights(gps);
- MEM_freeN(gps->dvert);
- }
- MEM_SAFE_FREE(gps->triangles);
- BLI_freelinkN(&gpf->strokes, gps);
-
- changed = true;
- }
- }
- }
-
- /* if not multiedit, exit loop*/
- if (!is_multiedit) {
- break;
- }
- }
- }
- 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);
- }
-
- return OPERATOR_FINISHED;
+ bool changed = false;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ int limit = RNA_int_get(op->ptr, "limit");
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ bGPDframe *init_gpf = gpl->actframe;
+ bGPDstroke *gps = NULL;
+ bGPDstroke *gpsn = NULL;
+ 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))) {
+ if (gpf == NULL)
+ continue;
+
+ /* simply delete strokes which are no loose */
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
+ /* free stroke */
+ if (gps->totpoints <= limit) {
+ /* free stroke memory arrays, then stroke itself */
+ if (gps->points) {
+ MEM_freeN(gps->points);
+ }
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
+ MEM_SAFE_FREE(gps->triangles);
+ BLI_freelinkN(&gpf->strokes, gps);
+
+ changed = true;
+ }
+ }
+ }
+
+ /* if not multiedit, exit loop*/
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ 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);
+ }
+
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_frame_clean_loose(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clean Loose points";
- ot->idname = "GPENCIL_OT_frame_clean_loose";
- ot->description = "Remove loose points";
+ /* identifiers */
+ ot->name = "Clean Loose points";
+ ot->idname = "GPENCIL_OT_frame_clean_loose";
+ ot->description = "Remove loose points";
- /* callbacks */
- ot->exec = gp_frame_clean_loose_exec;
- ot->poll = gp_active_layer_poll;
+ /* callbacks */
+ ot->exec = gp_frame_clean_loose_exec;
+ ot->poll = gp_active_layer_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_int(ot->srna, "limit", 1, 1, INT_MAX, "Limit", "Number of points to consider stroke as loose", 1, INT_MAX);
+ RNA_def_int(ot->srna,
+ "limit",
+ 1,
+ 1,
+ INT_MAX,
+ "Limit",
+ "Number of points to consider stroke as loose",
+ 1,
+ INT_MAX);
}
/* *********************** Hide Layers ******************************** */
static int gp_hide_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *layer = BKE_gpencil_layer_getactive(gpd);
- bool unselected = RNA_boolean_get(op->ptr, "unselected");
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *layer = BKE_gpencil_layer_getactive(gpd);
+ bool unselected = RNA_boolean_get(op->ptr, "unselected");
- /* sanity checks */
- if (ELEM(NULL, gpd, layer))
- return OPERATOR_CANCELLED;
+ /* sanity checks */
+ if (ELEM(NULL, gpd, layer))
+ return OPERATOR_CANCELLED;
- if (unselected) {
- bGPDlayer *gpl;
+ if (unselected) {
+ bGPDlayer *gpl;
- /* hide unselected */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpl != layer) {
- gpl->flag |= GP_LAYER_HIDE;
- }
- }
- }
- else {
- /* hide selected/active */
- layer->flag |= GP_LAYER_HIDE;
- }
+ /* hide unselected */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpl != layer) {
+ gpl->flag |= GP_LAYER_HIDE;
+ }
+ }
+ }
+ else {
+ /* hide selected/active */
+ layer->flag |= GP_LAYER_HIDE;
+ }
- /* 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);
+ /* 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;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_hide(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Layer(s)";
- ot->idname = "GPENCIL_OT_hide";
- ot->description = "Hide selected/unselected Grease Pencil layers";
+ /* identifiers */
+ ot->name = "Hide Layer(s)";
+ ot->idname = "GPENCIL_OT_hide";
+ ot->description = "Hide selected/unselected Grease Pencil layers";
- /* callbacks */
- ot->exec = gp_hide_exec;
- ot->poll = gp_active_layer_poll; /* NOTE: we need an active layer to play with */
+ /* callbacks */
+ ot->exec = gp_hide_exec;
+ ot->poll = gp_active_layer_poll; /* NOTE: we need an active layer to play with */
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected layers");
+ /* props */
+ RNA_def_boolean(
+ ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected layers");
}
/* ********************** Show All Layers ***************************** */
@@ -851,368 +866,375 @@ void GPENCIL_OT_hide(wmOperatorType *ot)
/* poll callback for showing layers */
static bool gp_reveal_poll(bContext *C)
{
- return ED_gpencil_data_get_active(C) != NULL;
+ return ED_gpencil_data_get_active(C) != NULL;
}
static void gp_reveal_select_frame(bContext *C, bGPDframe *frame, bool select)
{
- bGPDstroke *gps;
- for (gps = frame->strokes.first; gps; gps = gps->next) {
+ bGPDstroke *gps;
+ for (gps = frame->strokes.first; gps; gps = gps->next) {
- /* only deselect strokes that are valid in this view */
- if (ED_gpencil_stroke_can_use(C, gps)) {
+ /* only deselect strokes that are valid in this view */
+ if (ED_gpencil_stroke_can_use(C, gps)) {
- /* (de)select points */
- int i;
- bGPDspoint *pt;
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- SET_FLAG_FROM_TEST(pt->flag, select, GP_SPOINT_SELECT);
- }
+ /* (de)select points */
+ int i;
+ bGPDspoint *pt;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ SET_FLAG_FROM_TEST(pt->flag, select, GP_SPOINT_SELECT);
+ }
- /* (de)select stroke */
- SET_FLAG_FROM_TEST(gps->flag, select, GP_STROKE_SELECT);
- }
- }
+ /* (de)select stroke */
+ SET_FLAG_FROM_TEST(gps->flag, select, GP_STROKE_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 */
- if (gpd == NULL)
- return OPERATOR_CANCELLED;
-
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
-
- if (gpl->flag & GP_LAYER_HIDE) {
- gpl->flag &= ~GP_LAYER_HIDE;
-
- /* select or deselect if requested, only on hidden layers */
- if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
- if (select) {
- /* select all strokes on active frame only (same as select all operator) */
- if (gpl->actframe) {
- gp_reveal_select_frame(C, gpl->actframe, true);
- }
- }
- else {
- /* deselect strokes on all frames (same as deselect all operator) */
- bGPDframe *gpf;
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- gp_reveal_select_frame(C, gpf, false);
- }
- }
- }
- }
- }
-
- /* 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;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl;
+ const bool select = RNA_boolean_get(op->ptr, "select");
+
+ /* sanity checks */
+ if (gpd == NULL)
+ return OPERATOR_CANCELLED;
+
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+
+ if (gpl->flag & GP_LAYER_HIDE) {
+ gpl->flag &= ~GP_LAYER_HIDE;
+
+ /* select or deselect if requested, only on hidden layers */
+ if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
+ if (select) {
+ /* select all strokes on active frame only (same as select all operator) */
+ if (gpl->actframe) {
+ gp_reveal_select_frame(C, gpl->actframe, true);
+ }
+ }
+ else {
+ /* deselect strokes on all frames (same as deselect all operator) */
+ bGPDframe *gpf;
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ gp_reveal_select_frame(C, gpf, false);
+ }
+ }
+ }
+ }
+ }
+
+ /* 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_reveal(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Show All Layers";
- ot->idname = "GPENCIL_OT_reveal";
- ot->description = "Show all Grease Pencil layers";
+ /* identifiers */
+ ot->name = "Show All Layers";
+ ot->idname = "GPENCIL_OT_reveal";
+ ot->description = "Show all Grease Pencil layers";
- /* callbacks */
- ot->exec = gp_reveal_exec;
- ot->poll = gp_reveal_poll;
+ /* callbacks */
+ ot->exec = gp_reveal_exec;
+ ot->poll = gp_reveal_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "select", true, "Select", "");
+ /* props */
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
/* ***************** Lock/Unlock All Layers ************************ */
static int gp_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl;
- /* sanity checks */
- if (gpd == NULL)
- return OPERATOR_CANCELLED;
+ /* sanity checks */
+ if (gpd == NULL)
+ return OPERATOR_CANCELLED;
- /* make all layers non-editable */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- gpl->flag |= GP_LAYER_LOCKED;
- }
+ /* make all layers non-editable */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ gpl->flag |= GP_LAYER_LOCKED;
+ }
- /* 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);
+ /* 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;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_lock_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Lock All Layers";
- ot->idname = "GPENCIL_OT_lock_all";
- ot->description = "Lock all Grease Pencil layers to prevent them from being accidentally modified";
+ /* identifiers */
+ ot->name = "Lock All Layers";
+ ot->idname = "GPENCIL_OT_lock_all";
+ ot->description =
+ "Lock all Grease Pencil layers to prevent them from being accidentally modified";
- /* callbacks */
- ot->exec = gp_lock_all_exec;
- ot->poll = gp_reveal_poll; /* XXX: could use dedicated poll later */
+ /* callbacks */
+ ot->exec = gp_lock_all_exec;
+ ot->poll = gp_reveal_poll; /* XXX: could use dedicated poll later */
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* -------------------------- */
static int gp_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl;
- /* sanity checks */
- if (gpd == NULL)
- return OPERATOR_CANCELLED;
+ /* sanity checks */
+ if (gpd == NULL)
+ return OPERATOR_CANCELLED;
- /* make all layers editable again */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- gpl->flag &= ~GP_LAYER_LOCKED;
- }
+ /* make all layers editable again */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ gpl->flag &= ~GP_LAYER_LOCKED;
+ }
- /* 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);
+ /* 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;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_unlock_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unlock All Layers";
- ot->idname = "GPENCIL_OT_unlock_all";
- ot->description = "Unlock all Grease Pencil layers so that they can be edited";
+ /* identifiers */
+ ot->name = "Unlock All Layers";
+ ot->idname = "GPENCIL_OT_unlock_all";
+ ot->description = "Unlock all Grease Pencil layers so that they can be edited";
- /* callbacks */
- ot->exec = gp_unlock_all_exec;
- ot->poll = gp_reveal_poll; /* XXX: could use dedicated poll later */
+ /* callbacks */
+ ot->exec = gp_unlock_all_exec;
+ ot->poll = gp_reveal_poll; /* XXX: could use dedicated poll later */
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************** Isolate Layer **************************** */
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;
- int flags = GP_LAYER_LOCKED;
- bool isolate = false;
-
- if (RNA_boolean_get(op->ptr, "affect_visibility"))
- flags |= GP_LAYER_HIDE;
-
- if (ELEM(NULL, gpd, layer)) {
- BKE_report(op->reports, RPT_ERROR, "No active layer to isolate");
- return OPERATOR_CANCELLED;
- }
-
- /* Test whether to isolate or clear all flags */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* Skip if this is the active layer */
- if (gpl == layer)
- continue;
-
- /* If the flags aren't set, that means that the layer is
- * not alone, so we have some layers to isolate still
- */
- if ((gpl->flag & flags) == 0) {
- isolate = true;
- break;
- }
- }
-
- /* Set/Clear flags as appropriate */
- /* TODO: Include onionskinning on this list? */
- if (isolate) {
- /* Set flags on all "other" layers */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpl == layer)
- continue;
- else
- gpl->flag |= flags;
- }
- }
- else {
- /* Clear flags - Restore everything else */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- gpl->flag &= ~flags;
- }
- }
-
- /* 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;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *layer = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl;
+ int flags = GP_LAYER_LOCKED;
+ bool isolate = false;
+
+ if (RNA_boolean_get(op->ptr, "affect_visibility"))
+ flags |= GP_LAYER_HIDE;
+
+ if (ELEM(NULL, gpd, layer)) {
+ BKE_report(op->reports, RPT_ERROR, "No active layer to isolate");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Test whether to isolate or clear all flags */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* Skip if this is the active layer */
+ if (gpl == layer)
+ continue;
+
+ /* If the flags aren't set, that means that the layer is
+ * not alone, so we have some layers to isolate still
+ */
+ if ((gpl->flag & flags) == 0) {
+ isolate = true;
+ break;
+ }
+ }
+
+ /* Set/Clear flags as appropriate */
+ /* TODO: Include onionskinning on this list? */
+ if (isolate) {
+ /* Set flags on all "other" layers */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpl == layer)
+ continue;
+ else
+ gpl->flag |= flags;
+ }
+ }
+ else {
+ /* Clear flags - Restore everything else */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ gpl->flag &= ~flags;
+ }
+ }
+
+ /* 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_isolate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Isolate Layer";
- ot->idname = "GPENCIL_OT_layer_isolate";
- ot->description = "Toggle whether the active layer is the only one that can be edited and/or visible";
+ /* identifiers */
+ ot->name = "Isolate Layer";
+ ot->idname = "GPENCIL_OT_layer_isolate";
+ ot->description =
+ "Toggle whether the active layer is the only one that can be edited and/or visible";
- /* callbacks */
- ot->exec = gp_isolate_layer_exec;
- ot->poll = gp_active_layer_poll;
+ /* callbacks */
+ ot->exec = gp_isolate_layer_exec;
+ ot->poll = gp_active_layer_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "affect_visibility", false, "Affect Visibility",
- "In addition to toggling the editability, also affect the visibility");
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "affect_visibility",
+ false,
+ "Affect Visibility",
+ "In addition to toggling the editability, also affect the visibility");
}
/* ********************** Merge Layer with the next layer **************************** */
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_current = gpl_next->prev;
-
- if (ELEM(NULL, gpd, gpl_current, gpl_next)) {
- BKE_report(op->reports, RPT_ERROR, "No layers to merge");
- return OPERATOR_CANCELLED;
- }
-
- /* 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) {
- 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) {
- /* 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(gpl_current, gpf->framenum, GP_GETFRAME_USE_PREV);
- frame = BKE_gpencil_frame_addnew(gpl_current, gpf->framenum);
- /* duplicate strokes of current active frame */
- if (actframe) {
- BKE_gpencil_frame_copy_strokes(actframe, frame);
- }
- }
- /* add to tail all strokes */
- BLI_movelisttolist(&frame->strokes, &gpf->strokes);
- }
-
- /* Now delete next layer */
- BKE_gpencil_layer_delete(gpd, gpl_next);
- BLI_ghash_free(gh_frames_cur, NULL, NULL);
-
- /* 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;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl_next = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl_current = gpl_next->prev;
+
+ if (ELEM(NULL, gpd, gpl_current, gpl_next)) {
+ BKE_report(op->reports, RPT_ERROR, "No layers to merge");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* 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) {
+ 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) {
+ /* 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(
+ gpl_current, gpf->framenum, GP_GETFRAME_USE_PREV);
+ frame = BKE_gpencil_frame_addnew(gpl_current, gpf->framenum);
+ /* duplicate strokes of current active frame */
+ if (actframe) {
+ BKE_gpencil_frame_copy_strokes(actframe, frame);
+ }
+ }
+ /* add to tail all strokes */
+ BLI_movelisttolist(&frame->strokes, &gpf->strokes);
+ }
+
+ /* Now delete next layer */
+ BKE_gpencil_layer_delete(gpd, gpl_next);
+ BLI_ghash_free(gh_frames_cur, NULL, NULL);
+
+ /* 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_merge(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Merge Down";
- ot->idname = "GPENCIL_OT_layer_merge";
- ot->description = "Merge the current layer with the layer below";
+ /* identifiers */
+ ot->name = "Merge Down";
+ ot->idname = "GPENCIL_OT_layer_merge";
+ ot->description = "Merge the current layer with the layer below";
- /* callbacks */
- ot->exec = gp_merge_layer_exec;
- ot->poll = gp_active_layer_poll;
+ /* callbacks */
+ ot->exec = gp_merge_layer_exec;
+ ot->poll = gp_active_layer_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************** Change Layer ***************************** */
static int gp_layer_change_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(evt))
{
- uiPopupMenu *pup;
- uiLayout *layout;
+ uiPopupMenu *pup;
+ uiLayout *layout;
- /* call the menu, which will call this operator again, hence the canceled */
- pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
- layout = UI_popup_menu_layout(pup);
- uiItemsEnumO(layout, "GPENCIL_OT_layer_change", "layer");
- UI_popup_menu_end(C, pup);
+ /* call the menu, which will call this operator again, hence the canceled */
+ pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ uiItemsEnumO(layout, "GPENCIL_OT_layer_change", "layer");
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
static int gp_layer_change_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = CTX_data_gpencil_data(C);
- bGPDlayer *gpl = NULL;
- int layer_num = RNA_enum_get(op->ptr, "layer");
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ bGPDlayer *gpl = NULL;
+ int layer_num = RNA_enum_get(op->ptr, "layer");
- /* Get layer or create new one */
- if (layer_num == -1) {
- /* Create layer */
- gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
- }
- else {
- /* Try to get layer */
- gpl = BLI_findlink(&gpd->layers, layer_num);
+ /* Get layer or create new one */
+ if (layer_num == -1) {
+ /* Create layer */
+ gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
+ }
+ else {
+ /* Try to get layer */
+ 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;
- }
- }
+ 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_setactive(gpd, gpl);
+ /* Set active layer */
+ BKE_gpencil_layer_setactive(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);
+ /* 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);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_layer_change(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Change Layer";
- ot->idname = "GPENCIL_OT_layer_change";
- ot->description = "Change active Grease Pencil layer";
+ /* identifiers */
+ ot->name = "Change Layer";
+ ot->idname = "GPENCIL_OT_layer_change";
+ ot->description = "Change active Grease Pencil layer";
- /* callbacks */
- ot->invoke = gp_layer_change_invoke;
- ot->exec = gp_layer_change_exec;
- ot->poll = gp_active_layer_poll;
+ /* callbacks */
+ ot->invoke = gp_layer_change_invoke;
+ ot->exec = gp_layer_change_exec;
+ ot->poll = gp_active_layer_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* gp layer to use (dynamic enum) */
- ot->prop = RNA_def_enum(ot->srna, "layer", DummyRNA_DEFAULT_items, 0, "Grease Pencil Layer", "");
- RNA_def_enum_funcs(ot->prop, ED_gpencil_layers_with_new_enum_itemf);
+ /* gp layer to use (dynamic enum) */
+ ot->prop = RNA_def_enum(ot->srna, "layer", DummyRNA_DEFAULT_items, 0, "Grease Pencil Layer", "");
+ RNA_def_enum_funcs(ot->prop, ED_gpencil_layers_with_new_enum_itemf);
}
/* ************************************************ */
@@ -1220,309 +1242,305 @@ void GPENCIL_OT_layer_change(wmOperatorType *ot)
/* ******************* Arrange Stroke Up/Down in drawing order ************************** */
enum {
- GP_STROKE_MOVE_UP = -1,
- GP_STROKE_MOVE_DOWN = 1,
- GP_STROKE_MOVE_TOP = 2,
- GP_STROKE_MOVE_BOTTOM = 3,
+ GP_STROKE_MOVE_UP = -1,
+ GP_STROKE_MOVE_DOWN = 1,
+ GP_STROKE_MOVE_TOP = 2,
+ GP_STROKE_MOVE_BOTTOM = 3,
};
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 = BKE_gpencil_layer_getactive(gpd);
- bGPDstroke *gps;
-
- /* sanity checks */
- if (ELEM(NULL, gpd, gpl, gpl->actframe)) {
- return OPERATOR_CANCELLED;
- }
-
- const int direction = RNA_enum_get(op->ptr, "direction");
-
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* temp listbase to store selected strokes by layer */
- ListBase selected = { NULL };
- bGPDframe *gpf = gpl->actframe;
- if (gpl->flag & GP_LAYER_LOCKED) {
- continue;
- }
-
- if (gpf == NULL) {
- continue;
- }
- bool gpf_lock = false;
- /* verify if any selected stroke is in the extreme of the stack and select to move */
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- /* only if selected */
- if (gps->flag & GP_STROKE_SELECT) {
- /* 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;
- }
- /* some stroke is already at front*/
- if ((direction == GP_STROKE_MOVE_TOP) || (direction == GP_STROKE_MOVE_UP)) {
- if (gps == gpf->strokes.last) {
- gpf_lock = true;
- continue;
- }
- }
- /* some stroke is already at botom */
- if ((direction == GP_STROKE_MOVE_BOTTOM) || (direction == GP_STROKE_MOVE_DOWN)) {
- if (gps == gpf->strokes.first) {
- gpf_lock = true;
- continue;
- }
- }
- /* add to list (if not locked) */
- if (!gpf_lock) {
- BLI_addtail(&selected, BLI_genericNodeN(gps));
- }
- }
- }
- /* Now do the movement of the stroke */
- if (!gpf_lock) {
- switch (direction) {
- /* Bring to Front */
- case GP_STROKE_MOVE_TOP:
- for (LinkData *link = selected.first; link; link = link->next) {
- gps = link->data;
- BLI_remlink(&gpf->strokes, gps);
- BLI_addtail(&gpf->strokes, gps);
- }
- break;
- /* Bring Forward */
- case GP_STROKE_MOVE_UP:
- for (LinkData *link = selected.last; link; link = link->prev) {
- gps = link->data;
- BLI_listbase_link_move(&gpf->strokes, gps, 1);
- }
- break;
- /* Send Backward */
- case GP_STROKE_MOVE_DOWN:
- for (LinkData *link = selected.first; link; link = link->next) {
- gps = link->data;
- BLI_listbase_link_move(&gpf->strokes, gps, -1);
- }
- break;
- /* Send to Back */
- case GP_STROKE_MOVE_BOTTOM:
- for (LinkData *link = selected.last; link; link = link->prev) {
- gps = link->data;
- BLI_remlink(&gpf->strokes, gps);
- BLI_addhead(&gpf->strokes, gps);
- }
- break;
- default:
- BLI_assert(0);
- break;
- }
- }
- BLI_freelistN(&selected);
- }
-
- /* 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;
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDstroke *gps;
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd, gpl, gpl->actframe)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ const int direction = RNA_enum_get(op->ptr, "direction");
+
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* temp listbase to store selected strokes by layer */
+ ListBase selected = {NULL};
+ bGPDframe *gpf = gpl->actframe;
+ if (gpl->flag & GP_LAYER_LOCKED) {
+ continue;
+ }
+
+ if (gpf == NULL) {
+ continue;
+ }
+ bool gpf_lock = false;
+ /* verify if any selected stroke is in the extreme of the stack and select to move */
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* only if selected */
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* 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;
+ }
+ /* some stroke is already at front*/
+ if ((direction == GP_STROKE_MOVE_TOP) || (direction == GP_STROKE_MOVE_UP)) {
+ if (gps == gpf->strokes.last) {
+ gpf_lock = true;
+ continue;
+ }
+ }
+ /* some stroke is already at botom */
+ if ((direction == GP_STROKE_MOVE_BOTTOM) || (direction == GP_STROKE_MOVE_DOWN)) {
+ if (gps == gpf->strokes.first) {
+ gpf_lock = true;
+ continue;
+ }
+ }
+ /* add to list (if not locked) */
+ if (!gpf_lock) {
+ BLI_addtail(&selected, BLI_genericNodeN(gps));
+ }
+ }
+ }
+ /* Now do the movement of the stroke */
+ if (!gpf_lock) {
+ switch (direction) {
+ /* Bring to Front */
+ case GP_STROKE_MOVE_TOP:
+ for (LinkData *link = selected.first; link; link = link->next) {
+ gps = link->data;
+ BLI_remlink(&gpf->strokes, gps);
+ BLI_addtail(&gpf->strokes, gps);
+ }
+ break;
+ /* Bring Forward */
+ case GP_STROKE_MOVE_UP:
+ for (LinkData *link = selected.last; link; link = link->prev) {
+ gps = link->data;
+ BLI_listbase_link_move(&gpf->strokes, gps, 1);
+ }
+ break;
+ /* Send Backward */
+ case GP_STROKE_MOVE_DOWN:
+ for (LinkData *link = selected.first; link; link = link->next) {
+ gps = link->data;
+ BLI_listbase_link_move(&gpf->strokes, gps, -1);
+ }
+ break;
+ /* Send to Back */
+ case GP_STROKE_MOVE_BOTTOM:
+ for (LinkData *link = selected.last; link; link = link->prev) {
+ gps = link->data;
+ BLI_remlink(&gpf->strokes, gps);
+ BLI_addhead(&gpf->strokes, gps);
+ }
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+ }
+ BLI_freelistN(&selected);
+ }
+
+ /* 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_stroke_arrange(wmOperatorType *ot)
{
- static const EnumPropertyItem slot_move[] = {
- {GP_STROKE_MOVE_UP, "UP", 0, "Bring Forward", ""},
- {GP_STROKE_MOVE_DOWN, "DOWN", 0, "Send Backward", ""},
- {GP_STROKE_MOVE_TOP, "TOP", 0, "Bring to Front", ""},
- {GP_STROKE_MOVE_BOTTOM, "BOTTOM", 0, "Send to Back", ""},
- {0, NULL, 0, NULL, NULL }
- };
+ static const EnumPropertyItem slot_move[] = {
+ {GP_STROKE_MOVE_UP, "UP", 0, "Bring Forward", ""},
+ {GP_STROKE_MOVE_DOWN, "DOWN", 0, "Send Backward", ""},
+ {GP_STROKE_MOVE_TOP, "TOP", 0, "Bring to Front", ""},
+ {GP_STROKE_MOVE_BOTTOM, "BOTTOM", 0, "Send to Back", ""},
+ {0, NULL, 0, NULL, NULL}};
- /* identifiers */
- ot->name = "Arrange Stroke";
- ot->idname = "GPENCIL_OT_stroke_arrange";
- ot->description = "Arrange selected strokes up/down in the drawing order of the active layer";
+ /* identifiers */
+ ot->name = "Arrange Stroke";
+ ot->idname = "GPENCIL_OT_stroke_arrange";
+ ot->description = "Arrange selected strokes up/down in the drawing order of the active layer";
- /* callbacks */
- ot->exec = gp_stroke_arrange_exec;
- ot->poll = gp_active_layer_poll;
+ /* callbacks */
+ ot->exec = gp_stroke_arrange_exec;
+ ot->poll = gp_active_layer_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "direction", slot_move, GP_STROKE_MOVE_UP, "Direction", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "direction", slot_move, GP_STROKE_MOVE_UP, "Direction", "");
}
/* ******************* Move Stroke to new color ************************** */
static int gp_stroke_change_color_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Material *ma = NULL;
- char name[MAX_ID_NAME - 2];
- RNA_string_get(op->ptr, "material", name);
-
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- Object *ob = CTX_data_active_object(C);
- if (name[0] == '\0') {
- ma = give_current_material(ob, ob->actcol);
- }
- else {
- ma = (Material *)BKE_libblock_find_name(bmain, ID_MA, name);
- if (ma == NULL) {
- return OPERATOR_CANCELLED;
- }
- }
- /* try to find slot */
- int idx = BKE_gpencil_object_material_get_index(ob, ma);
- if (idx < 0) {
- return OPERATOR_CANCELLED;
- }
-
- /* sanity checks */
- if (ELEM(NULL, gpd)) {
- return OPERATOR_CANCELLED;
- }
-
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- if (ELEM(NULL, ma)) {
- return OPERATOR_CANCELLED;
- }
-
- /* loop all strokes */
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- 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))) {
- if (gpf == NULL)
- continue;
-
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- /* only if selected */
- if (gps->flag & GP_STROKE_SELECT) {
- /* 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;
-
- /* assign new color */
- gps->mat_nr = idx;
- }
- }
- }
- /* if not multiedit, exit loop*/
- if (!is_multiedit) {
- break;
- }
-
- }
- }
- CTX_DATA_END;
-
- /* 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;
+ Main *bmain = CTX_data_main(C);
+ Material *ma = NULL;
+ char name[MAX_ID_NAME - 2];
+ RNA_string_get(op->ptr, "material", name);
+
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ Object *ob = CTX_data_active_object(C);
+ if (name[0] == '\0') {
+ ma = give_current_material(ob, ob->actcol);
+ }
+ else {
+ ma = (Material *)BKE_libblock_find_name(bmain, ID_MA, name);
+ if (ma == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+ /* try to find slot */
+ int idx = BKE_gpencil_object_material_get_index(ob, ma);
+ if (idx < 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ if (ELEM(NULL, ma)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* loop all strokes */
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ 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))) {
+ if (gpf == NULL)
+ continue;
+
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* only if selected */
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* 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;
+
+ /* assign new color */
+ gps->mat_nr = idx;
+ }
+ }
+ }
+ /* if not multiedit, exit loop*/
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* 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_stroke_change_color(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Change Stroke Color";
- ot->idname = "GPENCIL_OT_stroke_change_color";
- ot->description = "Move selected strokes to active material";
-
- /* callbacks */
- ot->exec = gp_stroke_change_color_exec;
- ot->poll = gp_active_layer_poll;
+ /* identifiers */
+ ot->name = "Change Stroke Color";
+ ot->idname = "GPENCIL_OT_stroke_change_color";
+ ot->description = "Move selected strokes to active material";
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* callbacks */
+ ot->exec = gp_stroke_change_color_exec;
+ ot->poll = gp_active_layer_poll;
- RNA_def_string(ot->srna, "material", NULL, MAX_ID_NAME - 2, "Material", "Name of the material");
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ RNA_def_string(ot->srna, "material", NULL, MAX_ID_NAME - 2, "Material", "Name of the material");
}
/* ******************* Lock color of non selected Strokes colors ************************** */
static int gp_stroke_lock_color_exec(bContext *C, wmOperator *UNUSED(op))
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- short *totcol = give_totcolp(ob);
+ short *totcol = give_totcolp(ob);
- /* sanity checks */
- if (ELEM(NULL, gpd))
- return OPERATOR_CANCELLED;
+ /* sanity checks */
+ if (ELEM(NULL, gpd))
+ return OPERATOR_CANCELLED;
- /* first lock all colors */
- for (short i = 0; i < *totcol; i++) {
- Material *tmp_ma = give_current_material(ob, i + 1);
- tmp_ma->gp_style->flag |= GP_STYLE_COLOR_LOCKED;
- DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
- }
+ /* first lock all colors */
+ for (short i = 0; i < *totcol; i++) {
+ Material *tmp_ma = give_current_material(ob, i + 1);
+ tmp_ma->gp_style->flag |= GP_STYLE_COLOR_LOCKED;
+ DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
- /* loop all selected strokes and unlock any color */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* only editable and visible layers are considered */
- if (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) {
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps) == false) {
- continue;
- }
- /* unlock color */
- Material *tmp_ma = give_current_material(ob, gps->mat_nr + 1);
+ /* loop all selected strokes and unlock any color */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* only editable and visible layers are considered */
+ if (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) {
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+ /* unlock color */
+ Material *tmp_ma = give_current_material(ob, gps->mat_nr + 1);
- tmp_ma->gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
- DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
- }
- }
- }
- }
- /* updates */
- DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
+ tmp_ma->gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
+ DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ }
+ }
+ }
+ /* 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);
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
- /* 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);
+ /* 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;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_stroke_lock_color(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";
+ /* identifiers */
+ ot->name = "Lock Unused Colors";
+ ot->idname = "GPENCIL_OT_stroke_lock_color";
+ ot->description = "Lock any color not used in any selected stroke";
- /* api callbacks */
- ot->exec = gp_stroke_lock_color_exec;
- ot->poll = gp_active_layer_poll;
+ /* api callbacks */
+ ot->exec = gp_stroke_lock_color_exec;
+ ot->poll = gp_active_layer_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ************************************************ */
@@ -1531,1111 +1549,1111 @@ void GPENCIL_OT_stroke_lock_color(wmOperatorType *ot)
/* ******************* Brush create presets ************************** */
static int gp_brush_presets_create_exec(bContext *C, wmOperator *UNUSED(op))
{
- BKE_brush_gpencil_presets(C);
+ BKE_brush_gpencil_presets(C);
- /* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_brush_presets_create(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";
+ /* identifiers */
+ ot->name = "Create Preset Brushes";
+ ot->idname = "GPENCIL_OT_brush_presets_create";
+ ot->description = "Create a set of predefined Grease Pencil drawing brushes";
- /* api callbacks */
- ot->exec = gp_brush_presets_create_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* api callbacks */
+ ot->exec = gp_brush_presets_create_exec;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/*********************** Vertex Groups ***********************************/
static bool gpencil_vertex_group_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if ((ob) && (ob->type == OB_GPENCIL)) {
- if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && ob->defbase.first) {
- if (ELEM(ob->mode,
- OB_MODE_EDIT_GPENCIL,
- OB_MODE_SCULPT_GPENCIL))
- {
- return true;
- }
- }
- }
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && ob->defbase.first) {
+ if (ELEM(ob->mode, OB_MODE_EDIT_GPENCIL, OB_MODE_SCULPT_GPENCIL)) {
+ return true;
+ }
+ }
+ }
- return false;
+ return false;
}
static bool gpencil_vertex_group_weight_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if ((ob) && (ob->type == OB_GPENCIL)) {
- if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && ob->defbase.first) {
- if (ob->mode == OB_MODE_WEIGHT_GPENCIL) {
- return true;
- }
- }
- }
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && ob->defbase.first) {
+ if (ob->mode == OB_MODE_WEIGHT_GPENCIL) {
+ return true;
+ }
+ }
+ }
- return false;
+ return false;
}
static int gpencil_vertex_group_assign_exec(bContext *C, wmOperator *UNUSED(op))
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- Object *ob = CTX_data_active_object(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = CTX_data_active_object(C);
- /* sanity checks */
- if (ELEM(NULL, ts, ob, ob->data))
- return OPERATOR_CANCELLED;
+ /* sanity checks */
+ if (ELEM(NULL, ts, ob, ob->data))
+ return OPERATOR_CANCELLED;
- ED_gpencil_vgroup_assign(C, ob, ts->vgroup_weight);
+ ED_gpencil_vgroup_assign(C, ob, ts->vgroup_weight);
- /* notifiers */
- bGPdata *gpd = ob->data;
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
+ /* notifiers */
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_vertex_group_assign(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Assign to Vertex Group";
- ot->idname = "GPENCIL_OT_vertex_group_assign";
- ot->description = "Assign the selected vertices to the active vertex group";
+ /* identifiers */
+ ot->name = "Assign to Vertex Group";
+ ot->idname = "GPENCIL_OT_vertex_group_assign";
+ ot->description = "Assign the selected vertices to the active vertex group";
- /* api callbacks */
- ot->poll = gpencil_vertex_group_poll;
- ot->exec = gpencil_vertex_group_assign_exec;
+ /* api callbacks */
+ ot->poll = gpencil_vertex_group_poll;
+ ot->exec = gpencil_vertex_group_assign_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* remove point from vertex group */
static int gpencil_vertex_group_remove_from_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- /* sanity checks */
- if (ELEM(NULL, ob, ob->data))
- return OPERATOR_CANCELLED;
+ /* sanity checks */
+ if (ELEM(NULL, ob, ob->data))
+ return OPERATOR_CANCELLED;
- ED_gpencil_vgroup_remove(C, ob);
+ ED_gpencil_vgroup_remove(C, ob);
- /* notifiers */
- bGPdata *gpd = ob->data;
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
+ /* notifiers */
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_vertex_group_remove_from(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove from Vertex Group";
- ot->idname = "GPENCIL_OT_vertex_group_remove_from";
- ot->description = "Remove the selected vertices from active or all vertex group(s)";
-
- /* api callbacks */
- ot->poll = gpencil_vertex_group_poll;
- ot->exec = gpencil_vertex_group_remove_from_exec;
+ /* identifiers */
+ ot->name = "Remove from Vertex Group";
+ ot->idname = "GPENCIL_OT_vertex_group_remove_from";
+ ot->description = "Remove the selected vertices from active or all vertex group(s)";
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* api callbacks */
+ ot->poll = gpencil_vertex_group_poll;
+ ot->exec = gpencil_vertex_group_remove_from_exec;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int gpencil_vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- /* sanity checks */
- if (ELEM(NULL, ob, ob->data))
- return OPERATOR_CANCELLED;
+ /* sanity checks */
+ if (ELEM(NULL, ob, ob->data))
+ return OPERATOR_CANCELLED;
- ED_gpencil_vgroup_select(C, ob);
+ ED_gpencil_vgroup_select(C, ob);
- /* notifiers */
- bGPdata *gpd = ob->data;
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
+ /* notifiers */
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_vertex_group_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Vertex Group";
- ot->idname = "GPENCIL_OT_vertex_group_select";
- ot->description = "Select all the vertices assigned to the active vertex group";
+ /* identifiers */
+ ot->name = "Select Vertex Group";
+ ot->idname = "GPENCIL_OT_vertex_group_select";
+ ot->description = "Select all the vertices assigned to the active vertex group";
- /* api callbacks */
- ot->poll = gpencil_vertex_group_poll;
- ot->exec = gpencil_vertex_group_select_exec;
+ /* api callbacks */
+ ot->poll = gpencil_vertex_group_poll;
+ ot->exec = gpencil_vertex_group_select_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int gpencil_vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- /* sanity checks */
- if (ELEM(NULL, ob, ob->data))
- return OPERATOR_CANCELLED;
+ /* sanity checks */
+ if (ELEM(NULL, ob, ob->data))
+ return OPERATOR_CANCELLED;
- ED_gpencil_vgroup_deselect(C, ob);
+ ED_gpencil_vgroup_deselect(C, ob);
- /* notifiers */
- bGPdata *gpd = ob->data;
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
+ /* notifiers */
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_vertex_group_deselect(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Deselect Vertex Group";
- ot->idname = "GPENCIL_OT_vertex_group_deselect";
- ot->description = "Deselect all selected vertices assigned to the active vertex group";
+ /* identifiers */
+ ot->name = "Deselect Vertex Group";
+ ot->idname = "GPENCIL_OT_vertex_group_deselect";
+ ot->description = "Deselect all selected vertices assigned to the active vertex group";
- /* api callbacks */
- ot->poll = gpencil_vertex_group_poll;
- ot->exec = gpencil_vertex_group_deselect_exec;
+ /* api callbacks */
+ ot->poll = gpencil_vertex_group_poll;
+ ot->exec = gpencil_vertex_group_deselect_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* invert */
static int gpencil_vertex_group_invert_exec(bContext *C, wmOperator *op)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- Object *ob = CTX_data_active_object(C);
-
- /* sanity checks */
- if (ELEM(NULL, ts, ob, ob->data)) {
- return OPERATOR_CANCELLED;
- }
-
- MDeformVert *dvert;
- const int def_nr = ob->actdef - 1;
- bDeformGroup *defgroup = BLI_findlink(&ob->defbase, def_nr);
- if (defgroup == NULL) {
- return OPERATOR_CANCELLED;
- }
- if (defgroup->flag & DG_LOCK_WEIGHT) {
- BKE_report(op->reports, RPT_ERROR, "Current Vertex Group is locked");
- return OPERATOR_CANCELLED;
- }
-
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- for (int i = 0; i < gps->totpoints; i++) {
- dvert = &gps->dvert[i];
- MDeformWeight *dw = defvert_find_index(dvert, def_nr);
- if (dw == NULL) {
- defvert_add_index_notest(dvert, def_nr, 1.0f);
- }
- else if (dw->weight == 1.0f) {
- defvert_remove_group(dvert, dw);
- }
- else {
- dw->weight = 1.0f - dw->weight;
- }
- }
- }
- CTX_DATA_END;
-
- /* notifiers */
- bGPdata *gpd = ob->data;
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
-
- return OPERATOR_FINISHED;
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = CTX_data_active_object(C);
+
+ /* sanity checks */
+ if (ELEM(NULL, ts, ob, ob->data)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ MDeformVert *dvert;
+ const int def_nr = ob->actdef - 1;
+ bDeformGroup *defgroup = BLI_findlink(&ob->defbase, def_nr);
+ if (defgroup == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ if (defgroup->flag & DG_LOCK_WEIGHT) {
+ BKE_report(op->reports, RPT_ERROR, "Current Vertex Group is locked");
+ return OPERATOR_CANCELLED;
+ }
+
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ for (int i = 0; i < gps->totpoints; i++) {
+ dvert = &gps->dvert[i];
+ MDeformWeight *dw = defvert_find_index(dvert, def_nr);
+ if (dw == NULL) {
+ defvert_add_index_notest(dvert, def_nr, 1.0f);
+ }
+ else if (dw->weight == 1.0f) {
+ defvert_remove_group(dvert, dw);
+ }
+ else {
+ dw->weight = 1.0f - dw->weight;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* notifiers */
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
+
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_vertex_group_invert(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Invert Vertex Group";
- ot->idname = "GPENCIL_OT_vertex_group_invert";
- ot->description = "Invert weights to the active vertex group";
+ /* identifiers */
+ ot->name = "Invert Vertex Group";
+ ot->idname = "GPENCIL_OT_vertex_group_invert";
+ ot->description = "Invert weights to the active vertex group";
- /* api callbacks */
- ot->poll = gpencil_vertex_group_weight_poll;
- ot->exec = gpencil_vertex_group_invert_exec;
+ /* api callbacks */
+ ot->poll = gpencil_vertex_group_weight_poll;
+ ot->exec = gpencil_vertex_group_invert_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* smooth */
static int gpencil_vertex_group_smooth_exec(bContext *C, wmOperator *op)
{
- const float fac = RNA_float_get(op->ptr, "factor");
- const int repeat = RNA_int_get(op->ptr, "repeat");
-
- ToolSettings *ts = CTX_data_tool_settings(C);
- Object *ob = CTX_data_active_object(C);
-
- /* sanity checks */
- if (ELEM(NULL, ts, ob, ob->data)) {
- return OPERATOR_CANCELLED;
- }
-
- const int def_nr = ob->actdef - 1;
- bDeformGroup *defgroup = BLI_findlink(&ob->defbase, def_nr);
- if (defgroup == NULL) {
- return OPERATOR_CANCELLED;
- }
- if (defgroup->flag & DG_LOCK_WEIGHT) {
- BKE_report(op->reports, RPT_ERROR, "Current Vertex Group is locked");
- return OPERATOR_CANCELLED;
- }
-
- bGPDspoint *pta, *ptb, *ptc;
- MDeformVert *dverta, *dvertb;
-
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- if (gps->dvert == NULL) {
- continue;
- }
-
- for (int s = 0; s < repeat; s++) {
- for (int i = 0; i < gps->totpoints; i++) {
- /* previous point */
- if (i > 0) {
- pta = &gps->points[i - 1];
- dverta = &gps->dvert[i - 1];
- }
- else {
- pta = &gps->points[i];
- dverta = &gps->dvert[i];
- }
- /* current */
- ptb = &gps->points[i];
- dvertb = &gps->dvert[i];
- /* next point */
- if (i + 1 < gps->totpoints) {
- ptc = &gps->points[i + 1];
- }
- else {
- ptc = &gps->points[i];
- }
-
- float wa = defvert_find_weight(dverta, def_nr);
- float wb = defvert_find_weight(dvertb, def_nr);
-
- /* the optimal value is the corresponding to the interpolation of the weight
- * at the distance of point b
- */
- 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);
- if (dw) {
- dw->weight = interpf(wb, optimal, fac);
- CLAMP(dw->weight, 0.0, 1.0f);
- }
- }
- }
- }
- CTX_DATA_END;
-
- /* notifiers */
- bGPdata *gpd = ob->data;
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
-
- return OPERATOR_FINISHED;
+ const float fac = RNA_float_get(op->ptr, "factor");
+ const int repeat = RNA_int_get(op->ptr, "repeat");
+
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = CTX_data_active_object(C);
+
+ /* sanity checks */
+ if (ELEM(NULL, ts, ob, ob->data)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ const int def_nr = ob->actdef - 1;
+ bDeformGroup *defgroup = BLI_findlink(&ob->defbase, def_nr);
+ if (defgroup == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ if (defgroup->flag & DG_LOCK_WEIGHT) {
+ BKE_report(op->reports, RPT_ERROR, "Current Vertex Group is locked");
+ return OPERATOR_CANCELLED;
+ }
+
+ bGPDspoint *pta, *ptb, *ptc;
+ MDeformVert *dverta, *dvertb;
+
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ if (gps->dvert == NULL) {
+ continue;
+ }
+
+ for (int s = 0; s < repeat; s++) {
+ for (int i = 0; i < gps->totpoints; i++) {
+ /* previous point */
+ if (i > 0) {
+ pta = &gps->points[i - 1];
+ dverta = &gps->dvert[i - 1];
+ }
+ else {
+ pta = &gps->points[i];
+ dverta = &gps->dvert[i];
+ }
+ /* current */
+ ptb = &gps->points[i];
+ dvertb = &gps->dvert[i];
+ /* next point */
+ if (i + 1 < gps->totpoints) {
+ ptc = &gps->points[i + 1];
+ }
+ else {
+ ptc = &gps->points[i];
+ }
+
+ float wa = defvert_find_weight(dverta, def_nr);
+ float wb = defvert_find_weight(dvertb, def_nr);
+
+ /* the optimal value is the corresponding to the interpolation of the weight
+ * at the distance of point b
+ */
+ 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);
+ if (dw) {
+ dw->weight = interpf(wb, optimal, fac);
+ CLAMP(dw->weight, 0.0, 1.0f);
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* notifiers */
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
+
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_vertex_group_smooth(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Smooth Vertex Group";
- ot->idname = "GPENCIL_OT_vertex_group_smooth";
- ot->description = "Smooth weights to the active vertex group";
+ /* identifiers */
+ ot->name = "Smooth Vertex Group";
+ ot->idname = "GPENCIL_OT_vertex_group_smooth";
+ ot->description = "Smooth weights to the active vertex group";
- /* api callbacks */
- ot->poll = gpencil_vertex_group_weight_poll;
- ot->exec = gpencil_vertex_group_smooth_exec;
+ /* api callbacks */
+ ot->poll = gpencil_vertex_group_weight_poll;
+ ot->exec = gpencil_vertex_group_smooth_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0, "Factor", "", 0.0f, 1.0f);
- RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
+ RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0, "Factor", "", 0.0f, 1.0f);
+ RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
}
/* normalize */
static int gpencil_vertex_group_normalize_exec(bContext *C, wmOperator *op)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- Object *ob = CTX_data_active_object(C);
-
- /* sanity checks */
- if (ELEM(NULL, ts, ob, ob->data)) {
- return OPERATOR_CANCELLED;
- }
-
- MDeformVert *dvert = NULL;
- MDeformWeight *dw = NULL;
- const int def_nr = ob->actdef - 1;
- bDeformGroup *defgroup = BLI_findlink(&ob->defbase, def_nr);
- if (defgroup == NULL) {
- return OPERATOR_CANCELLED;
- }
- if (defgroup->flag & DG_LOCK_WEIGHT) {
- BKE_report(op->reports, RPT_ERROR, "Current Vertex Group is locked");
- return OPERATOR_CANCELLED;
- }
-
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- /* look for max value */
- float maxvalue = 0.0f;
- for (int i = 0; i < gps->totpoints; i++) {
- dvert = &gps->dvert[i];
- dw = defvert_find_index(dvert, def_nr);
- if ((dw != NULL) && (dw->weight > maxvalue)) {
- maxvalue = dw->weight;
- }
- }
-
- /* normalize weights */
- if (maxvalue > 0.0f) {
- for (int i = 0; i < gps->totpoints; i++) {
- dvert = &gps->dvert[i];
- dw = defvert_find_index(dvert, def_nr);
- if (dw != NULL) {
- dw->weight = dw->weight / maxvalue;
- }
- }
- }
- }
- CTX_DATA_END;
-
- /* notifiers */
- bGPdata *gpd = ob->data;
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
-
- return OPERATOR_FINISHED;
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = CTX_data_active_object(C);
+
+ /* sanity checks */
+ if (ELEM(NULL, ts, ob, ob->data)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ MDeformVert *dvert = NULL;
+ MDeformWeight *dw = NULL;
+ const int def_nr = ob->actdef - 1;
+ bDeformGroup *defgroup = BLI_findlink(&ob->defbase, def_nr);
+ if (defgroup == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ if (defgroup->flag & DG_LOCK_WEIGHT) {
+ BKE_report(op->reports, RPT_ERROR, "Current Vertex Group is locked");
+ return OPERATOR_CANCELLED;
+ }
+
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ /* look for max value */
+ float maxvalue = 0.0f;
+ for (int i = 0; i < gps->totpoints; i++) {
+ dvert = &gps->dvert[i];
+ dw = defvert_find_index(dvert, def_nr);
+ if ((dw != NULL) && (dw->weight > maxvalue)) {
+ maxvalue = dw->weight;
+ }
+ }
+
+ /* normalize weights */
+ if (maxvalue > 0.0f) {
+ for (int i = 0; i < gps->totpoints; i++) {
+ dvert = &gps->dvert[i];
+ dw = defvert_find_index(dvert, def_nr);
+ if (dw != NULL) {
+ dw->weight = dw->weight / maxvalue;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* notifiers */
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
+
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_vertex_group_normalize(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Normalize Vertex Group";
- ot->idname = "GPENCIL_OT_vertex_group_normalize";
- ot->description = "Normalize weights to the active vertex group";
+ /* identifiers */
+ ot->name = "Normalize Vertex Group";
+ ot->idname = "GPENCIL_OT_vertex_group_normalize";
+ ot->description = "Normalize weights to the active vertex group";
- /* api callbacks */
- ot->poll = gpencil_vertex_group_weight_poll;
- ot->exec = gpencil_vertex_group_normalize_exec;
+ /* api callbacks */
+ ot->poll = gpencil_vertex_group_weight_poll;
+ ot->exec = gpencil_vertex_group_normalize_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* normalize all */
static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- Object *ob = CTX_data_active_object(C);
- bool lock_active = RNA_boolean_get(op->ptr, "lock_active");
-
- /* sanity checks */
- if (ELEM(NULL, ts, ob, ob->data)) {
- return OPERATOR_CANCELLED;
- }
-
- bDeformGroup *defgroup = NULL;
- MDeformVert *dvert = NULL;
- MDeformWeight *dw = NULL;
- const int def_nr = ob->actdef - 1;
- const int defbase_tot = BLI_listbase_count(&ob->defbase);
- if (defbase_tot == 0) {
- return OPERATOR_CANCELLED;
- }
-
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- /* verify the strokes has something to change */
- if (gps->totpoints == 0) {
- continue;
- }
- /* look for tot value */
- float *tot_values = MEM_callocN(gps->totpoints * sizeof(float), __func__);
-
- for (int i = 0; i < gps->totpoints; i++) {
- dvert = &gps->dvert[i];
- for (int v = 0; v < defbase_tot; v++) {
- defgroup = BLI_findlink(&ob->defbase, v);
- /* skip NULL or locked groups */
- if ((defgroup == NULL) || (defgroup->flag & DG_LOCK_WEIGHT)) {
- continue;
- }
-
- /* skip current */
- if ((lock_active) && (v == def_nr)) {
- continue;
- }
-
- dw = defvert_find_index(dvert, v);
- if (dw != NULL) {
- tot_values[i] += dw->weight;
- }
- }
- }
-
- /* normalize weights */
- for (int i = 0; i < gps->totpoints; i++) {
- if (tot_values[i] == 0.0f) {
- continue;
- }
-
- dvert = &gps->dvert[i];
- for (int v = 0; v < defbase_tot; v++) {
- defgroup = BLI_findlink(&ob->defbase, v);
- /* skip NULL or locked groups */
- if ((defgroup == NULL) || (defgroup->flag & DG_LOCK_WEIGHT)) {
- continue;
- }
-
- /* skip current */
- if ((lock_active) && (v == def_nr)) {
- continue;
- }
-
- dw = defvert_find_index(dvert, v);
- if (dw != NULL) {
- dw->weight = dw->weight / tot_values[i];
- }
- }
- }
-
- /* free temp array */
- MEM_SAFE_FREE(tot_values);
- }
- CTX_DATA_END;
-
- /* notifiers */
- bGPdata *gpd = ob->data;
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
-
- return OPERATOR_FINISHED;
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = CTX_data_active_object(C);
+ bool lock_active = RNA_boolean_get(op->ptr, "lock_active");
+
+ /* sanity checks */
+ if (ELEM(NULL, ts, ob, ob->data)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ bDeformGroup *defgroup = NULL;
+ MDeformVert *dvert = NULL;
+ MDeformWeight *dw = NULL;
+ const int def_nr = ob->actdef - 1;
+ const int defbase_tot = BLI_listbase_count(&ob->defbase);
+ if (defbase_tot == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ /* verify the strokes has something to change */
+ if (gps->totpoints == 0) {
+ continue;
+ }
+ /* look for tot value */
+ float *tot_values = MEM_callocN(gps->totpoints * sizeof(float), __func__);
+
+ for (int i = 0; i < gps->totpoints; i++) {
+ dvert = &gps->dvert[i];
+ for (int v = 0; v < defbase_tot; v++) {
+ defgroup = BLI_findlink(&ob->defbase, v);
+ /* skip NULL or locked groups */
+ if ((defgroup == NULL) || (defgroup->flag & DG_LOCK_WEIGHT)) {
+ continue;
+ }
+
+ /* skip current */
+ if ((lock_active) && (v == def_nr)) {
+ continue;
+ }
+
+ dw = defvert_find_index(dvert, v);
+ if (dw != NULL) {
+ tot_values[i] += dw->weight;
+ }
+ }
+ }
+
+ /* normalize weights */
+ for (int i = 0; i < gps->totpoints; i++) {
+ if (tot_values[i] == 0.0f) {
+ continue;
+ }
+
+ dvert = &gps->dvert[i];
+ for (int v = 0; v < defbase_tot; v++) {
+ defgroup = BLI_findlink(&ob->defbase, v);
+ /* skip NULL or locked groups */
+ if ((defgroup == NULL) || (defgroup->flag & DG_LOCK_WEIGHT)) {
+ continue;
+ }
+
+ /* skip current */
+ if ((lock_active) && (v == def_nr)) {
+ continue;
+ }
+
+ dw = defvert_find_index(dvert, v);
+ if (dw != NULL) {
+ dw->weight = dw->weight / tot_values[i];
+ }
+ }
+ }
+
+ /* free temp array */
+ MEM_SAFE_FREE(tot_values);
+ }
+ CTX_DATA_END;
+
+ /* notifiers */
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
+
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_vertex_group_normalize_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Normalize All Vertex Group";
- ot->idname = "GPENCIL_OT_vertex_group_normalize_all";
- ot->description = "Normalize all weights of all vertex groups, "
- "so that for each vertex, the sum of all weights is 1.0";
+ /* identifiers */
+ ot->name = "Normalize All Vertex Group";
+ ot->idname = "GPENCIL_OT_vertex_group_normalize_all";
+ ot->description =
+ "Normalize all weights of all vertex groups, "
+ "so that for each vertex, the sum of all weights is 1.0";
- /* api callbacks */
- ot->poll = gpencil_vertex_group_weight_poll;
- ot->exec = gpencil_vertex_group_normalize_all_exec;
+ /* api callbacks */
+ ot->poll = gpencil_vertex_group_weight_poll;
+ ot->exec = gpencil_vertex_group_normalize_all_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "lock_active", true, "Lock Active",
- "Keep the values of the active group while normalizing others");
+ /* props */
+ RNA_def_boolean(ot->srna,
+ "lock_active",
+ true,
+ "Lock Active",
+ "Keep the values of the active group while normalizing others");
}
/****************************** Join ***********************************/
/* userdata for joined_gpencil_fix_animdata_cb() */
typedef struct tJoinGPencil_AdtFixData {
- bGPdata *src_gpd;
- bGPdata *tar_gpd;
+ bGPdata *src_gpd;
+ bGPdata *tar_gpd;
- GHash *names_map;
+ GHash *names_map;
} tJoinGPencil_AdtFixData;
/* Callback to pass to BKE_fcurves_main_cb() for RNA Paths attached to each F-Curve used in the AnimData */
static void joined_gpencil_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data)
{
- tJoinGPencil_AdtFixData *afd = (tJoinGPencil_AdtFixData *)user_data;
- ID *src_id = &afd->src_gpd->id;
- ID *dst_id = &afd->tar_gpd->id;
-
- GHashIterator gh_iter;
-
- /* Fix paths - If this is the target datablock, it will have some "dirty" paths */
- if ((id == src_id) && fcu->rna_path && strstr(fcu->rna_path, "layers[")) {
- GHASH_ITER(gh_iter, afd->names_map) {
- const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
- const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
-
- /* only remap if changed;
- * this still means there will be some waste if there aren't many drivers/keys */
- if (!STREQ(old_name, new_name) && strstr(fcu->rna_path, old_name)) {
- fcu->rna_path = BKE_animsys_fix_rna_path_rename(
- id, fcu->rna_path, "layers",
- old_name, new_name, 0, 0, false);
-
- /* we don't want to apply a second remapping on this F-Curve now,
- * so stop trying to fix names names
- */
- break;
- }
- }
- }
-
- /* Fix driver targets */
- if (fcu->driver) {
- /* Fix driver references to invalid ID's */
- for (DriverVar *dvar = fcu->driver->variables.first; dvar; dvar = dvar->next) {
- /* only change the used targets, since the others will need fixing manually anyway */
- DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar)
- {
- /* change the ID's used... */
- if (dtar->id == src_id) {
- dtar->id = dst_id;
-
- /* also check on the subtarget...
- * XXX: We duplicate the logic from drivers_path_rename_fix() here, with our own
- * little twists so that we know that it isn't going to clobber the wrong data
- */
- if (dtar->rna_path && strstr(dtar->rna_path, "layers[")) {
- GHASH_ITER(gh_iter, afd->names_map) {
- const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
- const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
-
- /* only remap if changed */
- if (!STREQ(old_name, new_name)) {
- if ((dtar->rna_path) && strstr(dtar->rna_path, old_name)) {
- /* Fix up path */
- dtar->rna_path = BKE_animsys_fix_rna_path_rename(
- id, dtar->rna_path, "layers",
- old_name, new_name, 0, 0, false);
- break; /* no need to try any more names for layer path */
- }
- }
- }
- }
- }
- }
- DRIVER_TARGETS_LOOPER_END;
- }
- }
+ tJoinGPencil_AdtFixData *afd = (tJoinGPencil_AdtFixData *)user_data;
+ ID *src_id = &afd->src_gpd->id;
+ ID *dst_id = &afd->tar_gpd->id;
+
+ GHashIterator gh_iter;
+
+ /* Fix paths - If this is the target datablock, it will have some "dirty" paths */
+ if ((id == src_id) && fcu->rna_path && strstr(fcu->rna_path, "layers[")) {
+ GHASH_ITER (gh_iter, afd->names_map) {
+ const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
+ const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
+
+ /* only remap if changed;
+ * this still means there will be some waste if there aren't many drivers/keys */
+ if (!STREQ(old_name, new_name) && strstr(fcu->rna_path, old_name)) {
+ fcu->rna_path = BKE_animsys_fix_rna_path_rename(
+ id, fcu->rna_path, "layers", old_name, new_name, 0, 0, false);
+
+ /* we don't want to apply a second remapping on this F-Curve now,
+ * so stop trying to fix names names
+ */
+ break;
+ }
+ }
+ }
+
+ /* Fix driver targets */
+ if (fcu->driver) {
+ /* Fix driver references to invalid ID's */
+ for (DriverVar *dvar = fcu->driver->variables.first; dvar; dvar = dvar->next) {
+ /* only change the used targets, since the others will need fixing manually anyway */
+ DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
+ /* change the ID's used... */
+ if (dtar->id == src_id) {
+ dtar->id = dst_id;
+
+ /* also check on the subtarget...
+ * XXX: We duplicate the logic from drivers_path_rename_fix() here, with our own
+ * little twists so that we know that it isn't going to clobber the wrong data
+ */
+ if (dtar->rna_path && strstr(dtar->rna_path, "layers[")) {
+ GHASH_ITER (gh_iter, afd->names_map) {
+ const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
+ const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
+
+ /* only remap if changed */
+ if (!STREQ(old_name, new_name)) {
+ if ((dtar->rna_path) && strstr(dtar->rna_path, old_name)) {
+ /* Fix up path */
+ dtar->rna_path = BKE_animsys_fix_rna_path_rename(
+ id, dtar->rna_path, "layers", old_name, new_name, 0, 0, false);
+ break; /* no need to try any more names for layer path */
+ }
+ }
+ }
+ }
+ }
+ }
+ DRIVER_TARGETS_LOOPER_END;
+ }
+ }
}
/* join objects called from OBJECT_OT_join */
int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *ob_active = CTX_data_active_object(C);
- bGPdata *gpd_dst = NULL;
- bool ok = false;
-
- /* Ensure we're in right mode and that the active object is correct */
- if (!ob_active || ob_active->type != OB_GPENCIL)
- return OPERATOR_CANCELLED;
-
- bGPdata *gpd = (bGPdata *)ob_active->data;
- if ((!gpd) || GPENCIL_ANY_MODE(gpd)) {
- return OPERATOR_CANCELLED;
- }
-
- /* Ensure all rotations are applied before */
- // XXX: Why don't we apply them here instead of warning?
- CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
- {
- if (ob_iter->type == OB_GPENCIL) {
- if ((ob_iter->rot[0] != 0) ||
- (ob_iter->rot[1] != 0) ||
- (ob_iter->rot[2] != 0))
- {
- BKE_report(op->reports, RPT_ERROR, "Apply all rotations before join objects");
- return OPERATOR_CANCELLED;
- }
- }
- }
- CTX_DATA_END;
-
- CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
- {
- if (ob_iter == ob_active) {
- ok = true;
- break;
- }
- }
- CTX_DATA_END;
-
- /* that way the active object is always selected */
- if (ok == false) {
- BKE_report(op->reports, RPT_WARNING, "Active object is not a selected grease pencil");
- return OPERATOR_CANCELLED;
- }
-
- gpd_dst = ob_active->data;
- Object *ob_dst = ob_active;
-
- /* loop and join all data */
- CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
- {
- if ((ob_iter->type == OB_GPENCIL) && (ob_iter != ob_active)) {
- /* we assume that each datablock is not already used in active object */
- if (ob_active->data != ob_iter->data) {
- Object *ob_src = ob_iter;
- 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);
- if (mti->bakeModifier) {
- mti->bakeModifier(bmain, depsgraph, md, ob_iter);
- }
- }
-
- /* copy vertex groups to the base one's */
- int old_idx = 0;
- for (bDeformGroup *dg = ob_iter->defbase.first; dg; dg = dg->next) {
- bDeformGroup *vgroup = MEM_dupallocN(dg);
- int idx = BLI_listbase_count(&ob_active->defbase);
- 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) {
- MDeformVert *dvert;
- int i;
- for (i = 0, dvert = gps->dvert; i < gps->totpoints; i++, dvert++) {
- if ((dvert->dw) && (dvert->dw->def_nr == old_idx)) {
- dvert->dw->def_nr = idx;
- }
- }
- }
- }
- }
- old_idx++;
- }
- if (ob_active->defbase.first && ob_active->actdef == 0) {
- ob_active->actdef = 1;
- }
-
- /* add missing materials reading source materials and checking in destination object */
- short *totcol = give_totcolp(ob_src);
-
- for (short i = 0; i < *totcol; i++) {
- Material *tmp_ma = give_current_material(ob_src, i + 1);
- BKE_gpencil_object_material_ensure(bmain, ob_dst, tmp_ma);
- }
-
- /* duplicate bGPDlayers */
- tJoinGPencil_AdtFixData afd = {0};
- afd.src_gpd = gpd_src;
- afd.tar_gpd = gpd_dst;
- afd.names_map = BLI_ghash_str_new("joined_gp_layers_map");
-
- float imat[3][3], bmat[3][3];
- float offset_global[3];
- float offset_local[3];
-
- sub_v3_v3v3(offset_global, ob_active->loc, ob_iter->obmat[3]);
- copy_m3_m4(bmat, ob_active->obmat);
- invert_m3_m3(imat, bmat);
- 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) {
- 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);
- 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) {
-
- /* reasign material. Look old material and try to find in dst */
- ma_src = give_current_material(ob_src, gps->mat_nr + 1);
- gps->mat_nr = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src);
-
- bGPDspoint *pt;
- int i;
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- float mpt[3];
- mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
- sub_v3_v3(mpt, offset_local);
- mul_v3_m4v3(&pt->x, diff_mat, mpt);
- }
- }
- }
-
- /* be sure name is unique in new object */
- BLI_uniquename(&gpd_dst->layers, gpl_new, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(gpl_new->info));
- BLI_ghash_insert(afd.names_map, BLI_strdup(gpl_src->info), gpl_new->info);
-
- /* add to destination datablock */
- BLI_addtail(&gpd_dst->layers, gpl_new);
- }
-
- /* Fix all the animation data */
- BKE_fcurves_main_cb(bmain, joined_gpencil_fix_animdata_cb, &afd);
- BLI_ghash_free(afd.names_map, MEM_freeN, NULL);
-
- /* Only copy over animdata now, after all the remapping has been done,
- * so that we don't have to worry about ambiguities re which datablock
- * a layer came from!
- */
- if (ob_iter->adt) {
- if (ob_active->adt == NULL) {
- /* no animdata, so just use a copy of the whole thing */
- ob_active->adt = BKE_animdata_copy(bmain, ob_iter->adt, 0);
- }
- else {
- /* merge in data - we'll fix the drivers manually */
- BKE_animdata_merge_copy(bmain, &ob_active->id, &ob_iter->id, ADT_MERGECOPY_KEEP_DST, false);
- }
- }
-
- if (gpd_src->adt) {
- if (gpd_dst->adt == NULL) {
- /* no animdata, so just use a copy of the whole thing */
- gpd_dst->adt = BKE_animdata_copy(bmain, gpd_src->adt, 0);
- }
- else {
- /* merge in data - we'll fix the drivers manually */
- BKE_animdata_merge_copy(bmain, &gpd_dst->id, &gpd_src->id, ADT_MERGECOPY_KEEP_DST, false);
- }
- }
- DEG_id_tag_update(&gpd_src->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
- }
-
- /* Free the old object */
- ED_object_base_free_and_unlink(bmain, scene, ob_iter);
- }
- }
- CTX_DATA_END;
-
- DEG_id_tag_update(&gpd_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain); /* because we removed object(s) */
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob_active = CTX_data_active_object(C);
+ bGPdata *gpd_dst = NULL;
+ bool ok = false;
+
+ /* Ensure we're in right mode and that the active object is correct */
+ if (!ob_active || ob_active->type != OB_GPENCIL)
+ return OPERATOR_CANCELLED;
+
+ bGPdata *gpd = (bGPdata *)ob_active->data;
+ if ((!gpd) || GPENCIL_ANY_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Ensure all rotations are applied before */
+ // XXX: Why don't we apply them here instead of warning?
+ CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
+ if (ob_iter->type == OB_GPENCIL) {
+ if ((ob_iter->rot[0] != 0) || (ob_iter->rot[1] != 0) || (ob_iter->rot[2] != 0)) {
+ BKE_report(op->reports, RPT_ERROR, "Apply all rotations before join objects");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
+ if (ob_iter == ob_active) {
+ ok = true;
+ break;
+ }
+ }
+ CTX_DATA_END;
+
+ /* that way the active object is always selected */
+ if (ok == false) {
+ BKE_report(op->reports, RPT_WARNING, "Active object is not a selected grease pencil");
+ return OPERATOR_CANCELLED;
+ }
+
+ gpd_dst = ob_active->data;
+ Object *ob_dst = ob_active;
+
+ /* loop and join all data */
+ CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
+ if ((ob_iter->type == OB_GPENCIL) && (ob_iter != ob_active)) {
+ /* we assume that each datablock is not already used in active object */
+ if (ob_active->data != ob_iter->data) {
+ Object *ob_src = ob_iter;
+ 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);
+ if (mti->bakeModifier) {
+ mti->bakeModifier(bmain, depsgraph, md, ob_iter);
+ }
+ }
+
+ /* copy vertex groups to the base one's */
+ int old_idx = 0;
+ for (bDeformGroup *dg = ob_iter->defbase.first; dg; dg = dg->next) {
+ bDeformGroup *vgroup = MEM_dupallocN(dg);
+ int idx = BLI_listbase_count(&ob_active->defbase);
+ 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) {
+ MDeformVert *dvert;
+ int i;
+ for (i = 0, dvert = gps->dvert; i < gps->totpoints; i++, dvert++) {
+ if ((dvert->dw) && (dvert->dw->def_nr == old_idx)) {
+ dvert->dw->def_nr = idx;
+ }
+ }
+ }
+ }
+ }
+ old_idx++;
+ }
+ if (ob_active->defbase.first && ob_active->actdef == 0) {
+ ob_active->actdef = 1;
+ }
+
+ /* add missing materials reading source materials and checking in destination object */
+ short *totcol = give_totcolp(ob_src);
+
+ for (short i = 0; i < *totcol; i++) {
+ Material *tmp_ma = give_current_material(ob_src, i + 1);
+ BKE_gpencil_object_material_ensure(bmain, ob_dst, tmp_ma);
+ }
+
+ /* duplicate bGPDlayers */
+ tJoinGPencil_AdtFixData afd = {0};
+ afd.src_gpd = gpd_src;
+ afd.tar_gpd = gpd_dst;
+ afd.names_map = BLI_ghash_str_new("joined_gp_layers_map");
+
+ float imat[3][3], bmat[3][3];
+ float offset_global[3];
+ float offset_local[3];
+
+ sub_v3_v3v3(offset_global, ob_active->loc, ob_iter->obmat[3]);
+ copy_m3_m4(bmat, ob_active->obmat);
+ invert_m3_m3(imat, bmat);
+ 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) {
+ 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);
+ 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) {
+
+ /* reasign material. Look old material and try to find in dst */
+ ma_src = give_current_material(ob_src, gps->mat_nr + 1);
+ gps->mat_nr = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src);
+
+ bGPDspoint *pt;
+ int i;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ float mpt[3];
+ mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
+ sub_v3_v3(mpt, offset_local);
+ mul_v3_m4v3(&pt->x, diff_mat, mpt);
+ }
+ }
+ }
+
+ /* be sure name is unique in new object */
+ BLI_uniquename(&gpd_dst->layers,
+ gpl_new,
+ DATA_("GP_Layer"),
+ '.',
+ offsetof(bGPDlayer, info),
+ sizeof(gpl_new->info));
+ BLI_ghash_insert(afd.names_map, BLI_strdup(gpl_src->info), gpl_new->info);
+
+ /* add to destination datablock */
+ BLI_addtail(&gpd_dst->layers, gpl_new);
+ }
+
+ /* Fix all the animation data */
+ BKE_fcurves_main_cb(bmain, joined_gpencil_fix_animdata_cb, &afd);
+ BLI_ghash_free(afd.names_map, MEM_freeN, NULL);
+
+ /* Only copy over animdata now, after all the remapping has been done,
+ * so that we don't have to worry about ambiguities re which datablock
+ * a layer came from!
+ */
+ if (ob_iter->adt) {
+ if (ob_active->adt == NULL) {
+ /* no animdata, so just use a copy of the whole thing */
+ ob_active->adt = BKE_animdata_copy(bmain, ob_iter->adt, 0);
+ }
+ else {
+ /* merge in data - we'll fix the drivers manually */
+ BKE_animdata_merge_copy(
+ bmain, &ob_active->id, &ob_iter->id, ADT_MERGECOPY_KEEP_DST, false);
+ }
+ }
+
+ if (gpd_src->adt) {
+ if (gpd_dst->adt == NULL) {
+ /* no animdata, so just use a copy of the whole thing */
+ gpd_dst->adt = BKE_animdata_copy(bmain, gpd_src->adt, 0);
+ }
+ else {
+ /* merge in data - we'll fix the drivers manually */
+ BKE_animdata_merge_copy(
+ bmain, &gpd_dst->id, &gpd_src->id, ADT_MERGECOPY_KEEP_DST, false);
+ }
+ }
+ DEG_id_tag_update(&gpd_src->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+ }
+
+ /* Free the old object */
+ ED_object_base_free_and_unlink(bmain, scene, ob_iter);
+ }
+ }
+ CTX_DATA_END;
+
+ DEG_id_tag_update(&gpd_dst->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain); /* because we removed object(s) */
+
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+
+ return OPERATOR_FINISHED;
}
/* Color Handle operator */
static bool gpencil_active_color_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
- if (ob && ob->data && (ob->type == OB_GPENCIL)) {
- short *totcolp = give_totcolp(ob);
- return *totcolp > 0;
- }
- return false;
+ Object *ob = CTX_data_active_object(C);
+ if (ob && ob->data && (ob->type == OB_GPENCIL)) {
+ short *totcolp = give_totcolp(ob);
+ return *totcolp > 0;
+ }
+ return false;
}
-
/* ******************* 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);
- Object *ob = CTX_data_active_object(C);
- MaterialGPencilStyle *gp_style = NULL;
-
- /* sanity checks */
- if (ELEM(NULL, gpd))
- return OPERATOR_CANCELLED;
-
- /* first lock and hide all colors */
- Material *ma = NULL;
- short *totcol = give_totcolp(ob);
- if (totcol == 0)
- return OPERATOR_CANCELLED;
-
- for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
- gp_style = ma->gp_style;
- gp_style->flag |= GP_STYLE_COLOR_LOCKED;
- gp_style->flag |= GP_STYLE_COLOR_HIDE;
- DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
- }
-
- /* loop all selected strokes and unlock any color used in active layer */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* only editable and visible layers are considered */
- if (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 */
- if (ED_gpencil_stroke_can_use(C, gps) == false)
- continue;
-
- ma = give_current_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;
- }
- }
- }
- }
- /* 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);
-
- /* 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;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ Object *ob = CTX_data_active_object(C);
+ MaterialGPencilStyle *gp_style = NULL;
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd))
+ return OPERATOR_CANCELLED;
+
+ /* first lock and hide all colors */
+ Material *ma = NULL;
+ short *totcol = give_totcolp(ob);
+ if (totcol == 0)
+ return OPERATOR_CANCELLED;
+
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ gp_style = ma->gp_style;
+ gp_style->flag |= GP_STYLE_COLOR_LOCKED;
+ gp_style->flag |= GP_STYLE_COLOR_HIDE;
+ DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
+
+ /* loop all selected strokes and unlock any color used in active layer */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* only editable and visible layers are considered */
+ if (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 */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
+ ma = give_current_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;
+ }
+ }
+ }
+ }
+ /* 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);
+
+ /* 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_lock_layer(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Disable Unused Layer Colors";
- ot->idname = "GPENCIL_OT_lock_layer";
- ot->description = "Lock and hide any color not used in any layer";
+ /* identifiers */
+ ot->name = "Disable Unused Layer Colors";
+ ot->idname = "GPENCIL_OT_lock_layer";
+ ot->description = "Lock and hide any color not used in any layer";
- /* api callbacks */
- ot->exec = gpencil_lock_layer_exec;
- ot->poll = gp_active_layer_poll;
+ /* api callbacks */
+ ot->exec = gpencil_lock_layer_exec;
+ ot->poll = gp_active_layer_poll;
}
/* ********************** Isolate gpencil_ color **************************** */
static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- Object *ob = CTX_data_active_object(C);
- Material *active_ma = give_current_material(ob, ob->actcol);
- MaterialGPencilStyle *active_color = BKE_material_gpencil_settings_get(ob, ob->actcol);
- MaterialGPencilStyle *gp_style;
-
- int flags = GP_STYLE_COLOR_LOCKED;
- bool isolate = false;
-
- if (RNA_boolean_get(op->ptr, "affect_visibility"))
- flags |= GP_STYLE_COLOR_HIDE;
-
- if (ELEM(NULL, gpd, active_color)) {
- BKE_report(op->reports, RPT_ERROR, "No active color to isolate");
- return OPERATOR_CANCELLED;
- }
-
- /* Test whether to isolate or clear all flags */
- Material *ma = NULL;
- short *totcol = give_totcolp(ob);
- for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
- /* Skip if this is the active one */
- if (ma == active_ma)
- continue;
-
- /* If the flags aren't set, that means that the color is
- * not alone, so we have some colors to isolate still
- */
- gp_style = ma->gp_style;
- if ((gp_style->flag & flags) == 0) {
- isolate = true;
- break;
- }
- }
-
- /* Set/Clear flags as appropriate */
- if (isolate) {
- /* Set flags on all "other" colors */
- for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
- gp_style = ma->gp_style;
- if (gp_style == active_color)
- continue;
- else
- gp_style->flag |= flags;
- DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
- }
- }
- else {
- /* Clear flags - Restore everything else */
- for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
- gp_style = ma->gp_style;
- gp_style->flag &= ~flags;
- DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
- }
- }
-
- /* notifiers */
- 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 | ND_DATA | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ Object *ob = CTX_data_active_object(C);
+ Material *active_ma = give_current_material(ob, ob->actcol);
+ MaterialGPencilStyle *active_color = BKE_material_gpencil_settings_get(ob, ob->actcol);
+ MaterialGPencilStyle *gp_style;
+
+ int flags = GP_STYLE_COLOR_LOCKED;
+ bool isolate = false;
+
+ if (RNA_boolean_get(op->ptr, "affect_visibility"))
+ flags |= GP_STYLE_COLOR_HIDE;
+
+ if (ELEM(NULL, gpd, active_color)) {
+ BKE_report(op->reports, RPT_ERROR, "No active color to isolate");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Test whether to isolate or clear all flags */
+ Material *ma = NULL;
+ short *totcol = give_totcolp(ob);
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ /* Skip if this is the active one */
+ if (ma == active_ma)
+ continue;
+
+ /* If the flags aren't set, that means that the color is
+ * not alone, so we have some colors to isolate still
+ */
+ gp_style = ma->gp_style;
+ if ((gp_style->flag & flags) == 0) {
+ isolate = true;
+ break;
+ }
+ }
+
+ /* Set/Clear flags as appropriate */
+ if (isolate) {
+ /* Set flags on all "other" colors */
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ gp_style = ma->gp_style;
+ if (gp_style == active_color)
+ continue;
+ else
+ gp_style->flag |= flags;
+ DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ }
+ else {
+ /* Clear flags - Restore everything else */
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ gp_style = ma->gp_style;
+ gp_style->flag &= ~flags;
+ DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ }
+
+ /* notifiers */
+ 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 | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_color_isolate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Isolate Color";
- ot->idname = "GPENCIL_OT_color_isolate";
- ot->description = "Toggle whether the active color is the only one that is editable and/or visible";
+ /* identifiers */
+ ot->name = "Isolate Color";
+ ot->idname = "GPENCIL_OT_color_isolate";
+ ot->description =
+ "Toggle whether the active color is the only one that is editable and/or visible";
- /* callbacks */
- ot->exec = gpencil_color_isolate_exec;
- ot->poll = gpencil_active_color_poll;
+ /* callbacks */
+ ot->exec = gpencil_color_isolate_exec;
+ ot->poll = gpencil_active_color_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "affect_visibility", false, "Affect Visibility", "In addition to toggling "
- "the editability, also affect the visibility");
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "affect_visibility",
+ false,
+ "Affect Visibility",
+ "In addition to toggling "
+ "the editability, also affect the visibility");
}
/* *********************** Hide colors ******************************** */
static int gpencil_color_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);
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ MaterialGPencilStyle *active_color = BKE_material_gpencil_settings_get(ob, ob->actcol);
- bool unselected = RNA_boolean_get(op->ptr, "unselected");
+ bool unselected = RNA_boolean_get(op->ptr, "unselected");
- Material *ma = NULL;
- short *totcol = give_totcolp(ob);
- if (totcol == 0)
- return OPERATOR_CANCELLED;
+ Material *ma = NULL;
+ short *totcol = give_totcolp(ob);
+ if (totcol == 0)
+ return OPERATOR_CANCELLED;
- if (unselected) {
- /* hide unselected */
- MaterialGPencilStyle *color = NULL;
- for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
- color = ma->gp_style;
- if (active_color != color) {
- color->flag |= GP_STYLE_COLOR_HIDE;
- DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
- }
- }
- }
- else {
- /* hide selected/active */
- active_color->flag |= GP_STYLE_COLOR_HIDE;
- }
+ if (unselected) {
+ /* hide unselected */
+ MaterialGPencilStyle *color = NULL;
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ color = ma->gp_style;
+ if (active_color != color) {
+ color->flag |= GP_STYLE_COLOR_HIDE;
+ DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ }
+ }
+ else {
+ /* hide selected/active */
+ active_color->flag |= GP_STYLE_COLOR_HIDE;
+ }
- /* updates */
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ /* updates */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | 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);
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
- /* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_color_hide(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Color(s)";
- ot->idname = "GPENCIL_OT_color_hide";
- ot->description = "Hide selected/unselected Grease Pencil colors";
+ /* identifiers */
+ ot->name = "Hide Color(s)";
+ ot->idname = "GPENCIL_OT_color_hide";
+ ot->description = "Hide selected/unselected Grease Pencil colors";
- /* callbacks */
- ot->exec = gpencil_color_hide_exec;
- ot->poll = gpencil_active_color_poll; /* NOTE: we need an active color to play with */
+ /* callbacks */
+ ot->exec = gpencil_color_hide_exec;
+ ot->poll = gpencil_active_color_poll; /* NOTE: we need an active color to play with */
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected colors");
+ /* props */
+ RNA_def_boolean(
+ ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected colors");
}
/* ********************** Show All Colors ***************************** */
static int gpencil_color_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);
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ Material *ma = NULL;
+ short *totcol = give_totcolp(ob);
- if (totcol == 0)
- return OPERATOR_CANCELLED;
+ if (totcol == 0)
+ return OPERATOR_CANCELLED;
- /* make all colors visible */
- MaterialGPencilStyle *gp_style = NULL;
+ /* make all colors visible */
+ MaterialGPencilStyle *gp_style = NULL;
- for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
- gp_style = ma->gp_style;
- gp_style->flag &= ~GP_STYLE_COLOR_HIDE;
- DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
- }
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ gp_style = ma->gp_style;
+ gp_style->flag &= ~GP_STYLE_COLOR_HIDE;
+ DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
- /* updates */
- DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
+ /* 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);
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
- /* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_color_reveal(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Show All Colors";
- ot->idname = "GPENCIL_OT_color_reveal";
- ot->description = "Unhide all hidden Grease Pencil colors";
+ /* identifiers */
+ ot->name = "Show All Colors";
+ ot->idname = "GPENCIL_OT_color_reveal";
+ ot->description = "Unhide all hidden Grease Pencil colors";
- /* callbacks */
- ot->exec = gpencil_color_reveal_exec;
- ot->poll = gpencil_active_color_poll;
+ /* callbacks */
+ ot->exec = gpencil_color_reveal_exec;
+ ot->poll = gpencil_active_color_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ***************** Lock/Unlock All colors ************************ */
@@ -2643,189 +2661,187 @@ void GPENCIL_OT_color_reveal(wmOperatorType *ot)
static int gpencil_color_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);
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ Material *ma = NULL;
+ short *totcol = give_totcolp(ob);
- if (totcol == 0)
- return OPERATOR_CANCELLED;
+ if (totcol == 0)
+ return OPERATOR_CANCELLED;
- /* make all layers non-editable */
- MaterialGPencilStyle *gp_style = NULL;
+ /* make all layers non-editable */
+ MaterialGPencilStyle *gp_style = NULL;
- for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
- gp_style = ma->gp_style;
- gp_style->flag |= GP_STYLE_COLOR_LOCKED;
- DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
- }
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ gp_style = ma->gp_style;
+ gp_style->flag |= GP_STYLE_COLOR_LOCKED;
+ DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
- /* updates */
- DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
+ /* 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);
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
- /* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_color_lock_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Lock All Colors";
- ot->idname = "GPENCIL_OT_color_lock_all";
- ot->description = "Lock all Grease Pencil colors to prevent them from being accidentally modified";
+ /* identifiers */
+ ot->name = "Lock All Colors";
+ ot->idname = "GPENCIL_OT_color_lock_all";
+ ot->description =
+ "Lock all Grease Pencil colors to prevent them from being accidentally modified";
- /* callbacks */
- ot->exec = gpencil_color_lock_all_exec;
- ot->poll = gpencil_active_color_poll;
+ /* callbacks */
+ ot->exec = gpencil_color_lock_all_exec;
+ ot->poll = gpencil_active_color_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* -------------------------- */
static int gpencil_color_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);
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ Material *ma = NULL;
+ short *totcol = give_totcolp(ob);
- if (totcol == 0)
- return OPERATOR_CANCELLED;
+ if (totcol == 0)
+ return OPERATOR_CANCELLED;
- /* make all layers editable again*/
- MaterialGPencilStyle *gp_style = NULL;
+ /* make all layers editable again*/
+ MaterialGPencilStyle *gp_style = NULL;
- for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
- gp_style = ma->gp_style;
- gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
- DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
- }
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ gp_style = ma->gp_style;
+ gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
+ DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
- /* updates */
- DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
+ /* 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);
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
- /* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_color_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";
+ /* 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";
- /* callbacks */
- ot->exec = gpencil_color_unlock_all_exec;
- ot->poll = gpencil_active_color_poll;
+ /* callbacks */
+ ot->exec = gpencil_color_unlock_all_exec;
+ ot->poll = gpencil_active_color_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/* ***************** Select all strokes using color ************************ */
static int gpencil_color_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);
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- const bool deselected = RNA_boolean_get(op->ptr, "deselect");
-
- /* sanity checks */
- if (ELEM(NULL, gpd, gp_style))
- return OPERATOR_CANCELLED;
-
- /* read all strokes and select*/
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- 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))) {
-
- /* verify something to do */
- 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;
- /* check if the color is editable */
- if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false)
- continue;
-
- /* select */
- if (ob->actcol == gps->mat_nr + 1) {
- bGPDspoint *pt;
- int i;
-
- if (!deselected) {
- gps->flag |= GP_STROKE_SELECT;
- }
- else {
- gps->flag &= ~GP_STROKE_SELECT;
- }
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (!deselected) {
- pt->flag |= GP_SPOINT_SELECT;
- }
- else {
- pt->flag &= ~GP_SPOINT_SELECT;
- }
- }
- }
- }
- }
- /* if not multiedit, exit loop*/
- if (!is_multiedit) {
- break;
- }
-
- }
- }
- CTX_DATA_END;
-
- /* copy on write tag is needed, or else no refresh happens */
- DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
-
- /* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
+ 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);
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ const bool deselected = RNA_boolean_get(op->ptr, "deselect");
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd, gp_style))
+ return OPERATOR_CANCELLED;
+
+ /* read all strokes and select*/
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ 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))) {
+
+ /* verify something to do */
+ 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;
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false)
+ continue;
+
+ /* select */
+ if (ob->actcol == gps->mat_nr + 1) {
+ bGPDspoint *pt;
+ int i;
+
+ if (!deselected) {
+ gps->flag |= GP_STROKE_SELECT;
+ }
+ else {
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (!deselected) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ else {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ }
+ }
+ }
+ }
+ /* if not multiedit, exit loop*/
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_color_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Color";
- ot->idname = "GPENCIL_OT_color_select";
- ot->description = "Select all Grease Pencil strokes using current color";
+ /* identifiers */
+ ot->name = "Select Color";
+ ot->idname = "GPENCIL_OT_color_select";
+ ot->description = "Select all Grease Pencil strokes using current color";
- /* callbacks */
- ot->exec = gpencil_color_select_exec;
- ot->poll = gpencil_active_color_poll;
+ /* callbacks */
+ ot->exec = gpencil_color_select_exec;
+ ot->poll = gpencil_active_color_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- ot->prop = RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Unselect strokes");
- RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ /* props */
+ ot->prop = RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Unselect strokes");
+ RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index e1eaedd435c..40e1e483f41 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -86,452 +86,455 @@
#include "gpencil_intern.h"
- /* ************************************************ */
- /* Stroke Edit Mode Management */
+/* ************************************************ */
+/* Stroke Edit Mode Management */
/* poll callback for all stroke editing operators */
static bool gp_stroke_edit_poll(bContext *C)
{
- /* edit only supported with grease pencil objects */
- Object *ob = CTX_data_active_object(C);
- if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
- return false;
- }
-
- /* NOTE: this is a bit slower, but is the most accurate... */
- return CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0;
+ /* edit only supported with grease pencil objects */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+ return false;
+ }
+
+ /* NOTE: this is a bit slower, but is the most accurate... */
+ return CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0;
}
/* poll callback to verify edit mode in 3D view only */
static bool gp_strokes_edit3d_poll(bContext *C)
{
- /* edit only supported with grease pencil objects */
- Object *ob = CTX_data_active_object(C);
- if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
- return false;
- }
-
-
- /* 2 Requirements:
- * - 1) Editable GP data
- * - 2) 3D View only
- */
- return (gp_stroke_edit_poll(C) && ED_operator_view3d_active(C));
+ /* edit only supported with grease pencil objects */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+ return false;
+ }
+
+ /* 2 Requirements:
+ * - 1) Editable GP data
+ * - 2) 3D View only
+ */
+ return (gp_stroke_edit_poll(C) && ED_operator_view3d_active(C));
}
static bool gpencil_editmode_toggle_poll(bContext *C)
{
- /* edit only supported with grease pencil objects */
- Object *ob = CTX_data_active_object(C);
- if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
- return false;
- }
-
- /* if using gpencil object, use this gpd */
- if (ob->type == OB_GPENCIL) {
- return ob->data != NULL;
- }
-
- return ED_gpencil_data_get_active(C) != NULL;
+ /* edit only supported with grease pencil objects */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+ return false;
+ }
+
+ /* if using gpencil object, use this gpd */
+ if (ob->type == OB_GPENCIL) {
+ return ob->data != NULL;
+ }
+
+ return ED_gpencil_data_get_active(C) != NULL;
}
static int gpencil_editmode_toggle_exec(bContext *C, wmOperator *op)
{
- const int back = RNA_boolean_get(op->ptr, "back");
-
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- bGPdata *gpd = ED_gpencil_data_get_active(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;
- }
-
- if (gpd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active GP data");
- return OPERATOR_CANCELLED;
- }
-
- /* Just toggle editmode flag... */
- gpd->flag ^= GP_DATA_STROKE_EDITMODE;
- /* recalculate parent matrix */
- if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
- ED_gpencil_reset_layers_parent(depsgraph, ob, gpd);
- }
- /* set mode */
- if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
- mode = OB_MODE_EDIT_GPENCIL;
- }
- else {
- mode = OB_MODE_OBJECT;
- }
-
- if (is_object) {
- /* try to back previous mode */
- if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_EDITMODE) == 0) && (back == 1)) {
- mode = ob->restore_mode;
- }
- ob->restore_mode = ob->mode;
- ob->mode = mode;
- }
-
- /* 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, NULL);
- WM_event_add_notifier(C, NC_GPENCIL | 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;
+ const int back = RNA_boolean_get(op->ptr, "back");
+
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(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;
+ }
+
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active GP data");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Just toggle editmode flag... */
+ gpd->flag ^= GP_DATA_STROKE_EDITMODE;
+ /* recalculate parent matrix */
+ if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
+ ED_gpencil_reset_layers_parent(depsgraph, ob, gpd);
+ }
+ /* set mode */
+ if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
+ mode = OB_MODE_EDIT_GPENCIL;
+ }
+ else {
+ mode = OB_MODE_OBJECT;
+ }
+
+ if (is_object) {
+ /* try to back previous mode */
+ if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_EDITMODE) == 0) && (back == 1)) {
+ mode = ob->restore_mode;
+ }
+ ob->restore_mode = ob->mode;
+ ob->mode = mode;
+ }
+
+ /* 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, NULL);
+ WM_event_add_notifier(C, NC_GPENCIL | 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_editmode_toggle(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Strokes Edit Mode Toggle";
- ot->idname = "GPENCIL_OT_editmode_toggle";
- ot->description = "Enter/Exit edit mode for Grease Pencil strokes";
+ /* identifiers */
+ ot->name = "Strokes Edit Mode Toggle";
+ ot->idname = "GPENCIL_OT_editmode_toggle";
+ ot->description = "Enter/Exit edit mode for Grease Pencil strokes";
- /* callbacks */
- ot->exec = gpencil_editmode_toggle_exec;
- ot->poll = gpencil_editmode_toggle_poll;
+ /* callbacks */
+ ot->exec = gpencil_editmode_toggle_exec;
+ ot->poll = gpencil_editmode_toggle_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+ /* 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);
+ /* 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);
}
/* set select mode */
static int gpencil_selectmode_toggle_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- const int mode = RNA_int_get(op->ptr, "mode");
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ const int mode = RNA_int_get(op->ptr, "mode");
- /* Just set mode */
- ts->gpencil_selectmode = mode;
+ /* Just set mode */
+ ts->gpencil_selectmode = mode;
- WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_selectmode_toggle(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Select Mode Toggle";
- ot->idname = "GPENCIL_OT_selectmode_toggle";
- ot->description = "Set selection mode for Grease Pencil strokes";
+ /* identifiers */
+ ot->name = "Select Mode Toggle";
+ ot->idname = "GPENCIL_OT_selectmode_toggle";
+ ot->description = "Set selection mode for Grease Pencil strokes";
- /* callbacks */
- ot->exec = gpencil_selectmode_toggle_exec;
- ot->poll = gp_strokes_edit3d_poll;
+ /* callbacks */
+ ot->exec = gpencil_selectmode_toggle_exec;
+ ot->poll = gp_strokes_edit3d_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
- /* properties */
- prop = RNA_def_int(ot->srna, "mode", 0, 0, 2, "Select mode", "Select mode", 0, 2);
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ /* properties */
+ prop = RNA_def_int(ot->srna, "mode", 0, 0, 2, "Select mode", "Select mode", 0, 2);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/* Stroke Paint Mode Management */
static bool gpencil_paintmode_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;
+ /* 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_paintmode_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;
- }
-
- if (gpd == NULL)
- return OPERATOR_CANCELLED;
-
- /* Just toggle paintmode flag... */
- gpd->flag ^= GP_DATA_STROKE_PAINTMODE;
- /* set mode */
- if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
- mode = OB_MODE_PAINT_GPENCIL;
- }
- else {
- mode = OB_MODE_OBJECT;
- }
-
- if (is_object) {
- /* try to back previous mode */
- if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0) && (back == 1)) {
- mode = ob->restore_mode;
- }
- ob->restore_mode = ob->mode;
- ob->mode = mode;
- }
-
- if (mode == OB_MODE_PAINT_GPENCIL) {
- /* be sure we have brushes */
- BKE_paint_ensure(ts, (Paint **)&ts->gp_paint);
- Paint *paint = &ts->gp_paint->paint;
- /* if not exist, create a new one */
- if (paint->brush == NULL) {
- BKE_brush_gpencil_presets(C);
- }
- BKE_paint_toolslots_brush_validate(bmain, &ts->gp_paint->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;
+ 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;
+ }
+
+ if (gpd == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* Just toggle paintmode flag... */
+ gpd->flag ^= GP_DATA_STROKE_PAINTMODE;
+ /* set mode */
+ if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
+ mode = OB_MODE_PAINT_GPENCIL;
+ }
+ else {
+ mode = OB_MODE_OBJECT;
+ }
+
+ if (is_object) {
+ /* try to back previous mode */
+ if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0) && (back == 1)) {
+ mode = ob->restore_mode;
+ }
+ ob->restore_mode = ob->mode;
+ ob->mode = mode;
+ }
+
+ if (mode == OB_MODE_PAINT_GPENCIL) {
+ /* be sure we have brushes */
+ BKE_paint_ensure(ts, (Paint **)&ts->gp_paint);
+ Paint *paint = &ts->gp_paint->paint;
+ /* if not exist, create a new one */
+ if (paint->brush == NULL) {
+ BKE_brush_gpencil_presets(C);
+ }
+ BKE_paint_toolslots_brush_validate(bmain, &ts->gp_paint->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_paintmode_toggle(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Strokes Paint Mode Toggle";
- ot->idname = "GPENCIL_OT_paintmode_toggle";
- ot->description = "Enter/Exit paint mode for Grease Pencil strokes";
+ /* identifiers */
+ ot->name = "Strokes Paint Mode Toggle";
+ ot->idname = "GPENCIL_OT_paintmode_toggle";
+ ot->description = "Enter/Exit paint mode for Grease Pencil strokes";
- /* callbacks */
- ot->exec = gpencil_paintmode_toggle_exec;
- ot->poll = gpencil_paintmode_toggle_poll;
+ /* callbacks */
+ ot->exec = gpencil_paintmode_toggle_exec;
+ ot->poll = gpencil_paintmode_toggle_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+ /* 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);
+ /* 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);
}
/* Stroke Sculpt Mode Management */
static bool gpencil_sculptmode_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;
+ /* 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_sculptmode_toggle_exec(bContext *C, wmOperator *op)
{
- const bool back = RNA_boolean_get(op->ptr, "back");
-
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- bGPdata *gpd = ED_gpencil_data_get_active(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;
- }
-
- if (gpd == NULL)
- return OPERATOR_CANCELLED;
-
- /* Just toggle sculptmode flag... */
- gpd->flag ^= GP_DATA_STROKE_SCULPTMODE;
- /* set mode */
- if (gpd->flag & GP_DATA_STROKE_SCULPTMODE) {
- mode = OB_MODE_SCULPT_GPENCIL;
- }
- else {
- mode = OB_MODE_OBJECT;
- }
-
- if (is_object) {
- /* try to back previous mode */
- if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_SCULPTMODE) == 0) && (back == 1)) {
- mode = ob->restore_mode;
- }
- ob->restore_mode = ob->mode;
- ob->mode = mode;
- }
-
- /* 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;
+ const bool back = RNA_boolean_get(op->ptr, "back");
+
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(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;
+ }
+
+ if (gpd == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* Just toggle sculptmode flag... */
+ gpd->flag ^= GP_DATA_STROKE_SCULPTMODE;
+ /* set mode */
+ if (gpd->flag & GP_DATA_STROKE_SCULPTMODE) {
+ mode = OB_MODE_SCULPT_GPENCIL;
+ }
+ else {
+ mode = OB_MODE_OBJECT;
+ }
+
+ if (is_object) {
+ /* try to back previous mode */
+ if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_SCULPTMODE) == 0) && (back == 1)) {
+ mode = ob->restore_mode;
+ }
+ ob->restore_mode = ob->mode;
+ ob->mode = mode;
+ }
+
+ /* 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_sculptmode_toggle(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Strokes Sculpt Mode Toggle";
- ot->idname = "GPENCIL_OT_sculptmode_toggle";
- ot->description = "Enter/Exit sculpt mode for Grease Pencil strokes";
+ /* identifiers */
+ ot->name = "Strokes Sculpt Mode Toggle";
+ ot->idname = "GPENCIL_OT_sculptmode_toggle";
+ ot->description = "Enter/Exit sculpt mode for Grease Pencil strokes";
- /* callbacks */
- ot->exec = gpencil_sculptmode_toggle_exec;
- ot->poll = gpencil_sculptmode_toggle_poll;
+ /* callbacks */
+ ot->exec = gpencil_sculptmode_toggle_exec;
+ ot->poll = gpencil_sculptmode_toggle_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+ /* 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);
+ /* 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);
}
/* Stroke Weight Paint Mode Management */
static bool gpencil_weightmode_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;
+ /* 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_weightmode_toggle_exec(bContext *C, wmOperator *op)
{
- const bool back = RNA_boolean_get(op->ptr, "back");
-
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- bGPdata *gpd = ED_gpencil_data_get_active(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;
- }
-
- if (gpd == NULL)
- return OPERATOR_CANCELLED;
-
- /* Just toggle weightmode flag... */
- gpd->flag ^= GP_DATA_STROKE_WEIGHTMODE;
- /* set mode */
- if (gpd->flag & GP_DATA_STROKE_WEIGHTMODE) {
- mode = OB_MODE_WEIGHT_GPENCIL;
- }
- else {
- mode = OB_MODE_OBJECT;
- }
-
- if (is_object) {
- /* try to back previous mode */
- if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && (back == 1)) {
- mode = ob->restore_mode;
- }
- ob->restore_mode = ob->mode;
- ob->mode = mode;
- }
-
- /* 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;
+ const bool back = RNA_boolean_get(op->ptr, "back");
+
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(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;
+ }
+
+ if (gpd == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* Just toggle weightmode flag... */
+ gpd->flag ^= GP_DATA_STROKE_WEIGHTMODE;
+ /* set mode */
+ if (gpd->flag & GP_DATA_STROKE_WEIGHTMODE) {
+ mode = OB_MODE_WEIGHT_GPENCIL;
+ }
+ else {
+ mode = OB_MODE_OBJECT;
+ }
+
+ if (is_object) {
+ /* try to back previous mode */
+ if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && (back == 1)) {
+ mode = ob->restore_mode;
+ }
+ ob->restore_mode = ob->mode;
+ ob->mode = mode;
+ }
+
+ /* 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_weightmode_toggle(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Strokes Weight Mode Toggle";
- ot->idname = "GPENCIL_OT_weightmode_toggle";
- ot->description = "Enter/Exit weight paint mode for Grease Pencil strokes";
+ /* identifiers */
+ ot->name = "Strokes Weight Mode Toggle";
+ ot->idname = "GPENCIL_OT_weightmode_toggle";
+ ot->description = "Enter/Exit weight paint mode for Grease Pencil strokes";
- /* callbacks */
- ot->exec = gpencil_weightmode_toggle_exec;
- ot->poll = gpencil_weightmode_toggle_poll;
+ /* callbacks */
+ ot->exec = gpencil_weightmode_toggle_exec;
+ ot->poll = gpencil_weightmode_toggle_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+ /* 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);
+ /* 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);
}
/* ************************************************ */
@@ -541,440 +544,437 @@ void GPENCIL_OT_weightmode_toggle(wmOperatorType *ot)
static int gpencil_hideselect_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d == NULL)
- return OPERATOR_CANCELLED;
-
- /* Just toggle alpha... */
- if (v3d->vertex_opacity > 0.0f) {
- v3d->vertex_opacity = 0.0f;
- }
- else {
- v3d->vertex_opacity = 1.0f;
- }
-
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
- WM_event_add_notifier(C, NC_GPENCIL | ND_GPENCIL_EDITMODE, NULL);
- WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
-
- return OPERATOR_FINISHED;
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* Just toggle alpha... */
+ if (v3d->vertex_opacity > 0.0f) {
+ v3d->vertex_opacity = 0.0f;
+ }
+ else {
+ v3d->vertex_opacity = 1.0f;
+ }
+
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_GPENCIL_EDITMODE, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
+
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_selection_opacity_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Selected";
- ot->idname = "GPENCIL_OT_selection_opacity_toggle";
- ot->description = "Hide/Unhide selected points for Grease Pencil strokes setting alpha factor";
+ /* identifiers */
+ ot->name = "Hide Selected";
+ ot->idname = "GPENCIL_OT_selection_opacity_toggle";
+ ot->description = "Hide/Unhide selected points for Grease Pencil strokes setting alpha factor";
- /* callbacks */
- ot->exec = gpencil_hideselect_toggle_exec;
- ot->poll = gp_stroke_edit_poll;
+ /* callbacks */
+ ot->exec = gpencil_hideselect_toggle_exec;
+ ot->poll = gp_stroke_edit_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
}
/* ************** Duplicate Selected Strokes **************** */
/* Make copies of selected point segments in a selected stroke */
-static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes, const char *layername)
+static void gp_duplicate_points(const bGPDstroke *gps,
+ ListBase *new_strokes,
+ const char *layername)
{
- bGPDspoint *pt;
- int i;
-
- int start_idx = -1;
-
-
- /* Step through the original stroke's points:
- * - We accumulate selected points (from start_idx to current index)
- * and then convert that to a new stroke
- */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- /* searching for start, are waiting for end? */
- if (start_idx == -1) {
- /* is this the first selected point for a new island? */
- if (pt->flag & GP_SPOINT_SELECT) {
- start_idx = i;
- }
- }
- else {
- size_t len = 0;
-
- /* is this the end of current island yet?
- * 1) Point i-1 was the last one that was selected
- * 2) Point i is the last in the array
- */
- if ((pt->flag & GP_SPOINT_SELECT) == 0) {
- len = i - start_idx;
- }
- 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);
-
- /* 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");
- 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");
- memcpy(gpsd->dvert, gps->dvert + start_idx, sizeof(MDeformVert) * len);
-
- /* Copy weights */
- int e = start_idx;
- for (int j = 0; j < gpsd->totpoints; j++) {
- MDeformVert *dvert_dst = &gps->dvert[e];
- MDeformVert *dvert_src = &gps->dvert[j];
- dvert_dst->dw = MEM_dupallocN(dvert_src->dw);
- e++;
- }
- }
-
- /* add to temp buffer */
- gpsd->next = gpsd->prev = NULL;
- BLI_addtail(new_strokes, gpsd);
-
- /* cleanup + reset for next */
- start_idx = -1;
- }
- }
- }
+ bGPDspoint *pt;
+ int i;
+
+ int start_idx = -1;
+
+ /* Step through the original stroke's points:
+ * - We accumulate selected points (from start_idx to current index)
+ * and then convert that to a new stroke
+ */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ /* searching for start, are waiting for end? */
+ if (start_idx == -1) {
+ /* is this the first selected point for a new island? */
+ if (pt->flag & GP_SPOINT_SELECT) {
+ start_idx = i;
+ }
+ }
+ else {
+ size_t len = 0;
+
+ /* is this the end of current island yet?
+ * 1) Point i-1 was the last one that was selected
+ * 2) Point i is the last in the array
+ */
+ if ((pt->flag & GP_SPOINT_SELECT) == 0) {
+ len = i - start_idx;
+ }
+ 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);
+
+ /* 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");
+ 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");
+ memcpy(gpsd->dvert, gps->dvert + start_idx, sizeof(MDeformVert) * len);
+
+ /* Copy weights */
+ int e = start_idx;
+ for (int j = 0; j < gpsd->totpoints; j++) {
+ MDeformVert *dvert_dst = &gps->dvert[e];
+ MDeformVert *dvert_src = &gps->dvert[j];
+ dvert_dst->dw = MEM_dupallocN(dvert_src->dw);
+ e++;
+ }
+ }
+
+ /* add to temp buffer */
+ gpsd->next = gpsd->prev = NULL;
+ BLI_addtail(new_strokes, gpsd);
+
+ /* cleanup + reset for next */
+ start_idx = -1;
+ }
+ }
+ }
}
static int gp_duplicate_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
-
- if (gpd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
- return OPERATOR_CANCELLED;
- }
-
- if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
- BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition");
- return OPERATOR_CANCELLED;
- }
-
- /* for each visible (and editable) layer's selected strokes,
- * copy the strokes into a temporary buffer, then append
- * once all done
- */
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- ListBase new_strokes = {NULL, NULL};
- bGPDframe *gpf = gpl->actframe;
- bGPDstroke *gps;
-
- if (gpf == NULL)
- continue;
-
- /* make copies of selected strokes, and deselect these once we're done */
- for (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;
- }
-
- if (gps->flag & GP_STROKE_SELECT) {
- if (gps->totpoints == 1) {
- /* Special Case: If there's just a single point in this stroke... */
- bGPDstroke *gpsd;
-
- /* make direct copies of the stroke and its points */
- gpsd = MEM_dupallocN(gps);
- 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;
-
- /* add to temp buffer */
- gpsd->next = gpsd->prev = NULL;
- BLI_addtail(&new_strokes, gpsd);
- }
- else {
- /* delegate to a helper, as there's too much to fit in here (for copying subsets)... */
- gp_duplicate_points(gps, &new_strokes, gpl->info);
- }
-
- /* deselect original stroke, or else the originals get moved too
- * (when using the copy + move macro)
- */
- gps->flag &= ~GP_STROKE_SELECT;
- }
- }
-
- /* add all new strokes in temp buffer to the frame (preventing double-copies) */
- BLI_movelisttolist(&gpf->strokes, &new_strokes);
- BLI_assert(new_strokes.first == NULL);
- }
- CTX_DATA_END;
-
- /* 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);
-
- return OPERATOR_FINISHED;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
+ BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* for each visible (and editable) layer's selected strokes,
+ * copy the strokes into a temporary buffer, then append
+ * once all done
+ */
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ ListBase new_strokes = {NULL, NULL};
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps;
+
+ if (gpf == NULL)
+ continue;
+
+ /* make copies of selected strokes, and deselect these once we're done */
+ for (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;
+ }
+
+ if (gps->flag & GP_STROKE_SELECT) {
+ if (gps->totpoints == 1) {
+ /* Special Case: If there's just a single point in this stroke... */
+ bGPDstroke *gpsd;
+
+ /* make direct copies of the stroke and its points */
+ gpsd = MEM_dupallocN(gps);
+ 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;
+
+ /* add to temp buffer */
+ gpsd->next = gpsd->prev = NULL;
+ BLI_addtail(&new_strokes, gpsd);
+ }
+ else {
+ /* delegate to a helper, as there's too much to fit in here (for copying subsets)... */
+ gp_duplicate_points(gps, &new_strokes, gpl->info);
+ }
+
+ /* deselect original stroke, or else the originals get moved too
+ * (when using the copy + move macro)
+ */
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ }
+
+ /* add all new strokes in temp buffer to the frame (preventing double-copies) */
+ BLI_movelisttolist(&gpf->strokes, &new_strokes);
+ BLI_assert(new_strokes.first == NULL);
+ }
+ CTX_DATA_END;
+
+ /* 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);
+
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_duplicate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Duplicate Strokes";
- ot->idname = "GPENCIL_OT_duplicate";
- ot->description = "Duplicate the selected Grease Pencil strokes";
+ /* identifiers */
+ ot->name = "Duplicate Strokes";
+ ot->idname = "GPENCIL_OT_duplicate";
+ ot->description = "Duplicate the selected Grease Pencil strokes";
- /* callbacks */
- ot->exec = gp_duplicate_exec;
- ot->poll = gp_stroke_edit_poll;
+ /* callbacks */
+ ot->exec = gp_duplicate_exec;
+ ot->poll = gp_stroke_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ************** Extrude Selected Strokes **************** */
/* helper to copy a point to temp area */
-static void copy_move_point(
- bGPDstroke *gps,
- bGPDspoint *temp_points,
- MDeformVert *temp_dverts,
- int from_idx, int to_idx, const bool copy)
+static void copy_move_point(bGPDstroke *gps,
+ bGPDspoint *temp_points,
+ MDeformVert *temp_dverts,
+ int from_idx,
+ int to_idx,
+ const bool copy)
{
- bGPDspoint *pt = &temp_points[from_idx];
- bGPDspoint *pt_final = &gps->points[to_idx];
-
- copy_v3_v3(&pt_final->x, &pt->x);
- pt_final->pressure = pt->pressure;
- pt_final->strength = pt->strength;
- pt_final->time = pt->time;
- pt_final->flag = pt->flag;
- pt_final->uv_fac = pt->uv_fac;
- pt_final->uv_rot = pt->uv_rot;
-
- if (gps->dvert != NULL) {
- MDeformVert *dvert = &temp_dverts[from_idx];
- MDeformVert *dvert_final = &gps->dvert[to_idx];
-
- dvert_final->totweight = dvert->totweight;
- /* if copy, duplicate memory, otherwise move only the pointer */
- if (copy) {
- dvert_final->dw = MEM_dupallocN(dvert->dw);
- }
- else {
- dvert_final->dw = dvert->dw;
- }
- }
+ bGPDspoint *pt = &temp_points[from_idx];
+ bGPDspoint *pt_final = &gps->points[to_idx];
+
+ copy_v3_v3(&pt_final->x, &pt->x);
+ pt_final->pressure = pt->pressure;
+ pt_final->strength = pt->strength;
+ pt_final->time = pt->time;
+ pt_final->flag = pt->flag;
+ pt_final->uv_fac = pt->uv_fac;
+ pt_final->uv_rot = pt->uv_rot;
+
+ if (gps->dvert != NULL) {
+ MDeformVert *dvert = &temp_dverts[from_idx];
+ MDeformVert *dvert_final = &gps->dvert[to_idx];
+
+ dvert_final->totweight = dvert->totweight;
+ /* if copy, duplicate memory, otherwise move only the pointer */
+ if (copy) {
+ dvert_final->dw = MEM_dupallocN(dvert->dw);
+ }
+ else {
+ dvert_final->dw = dvert->dw;
+ }
+ }
}
static void gpencil_add_move_points(bGPDframe *gpf, bGPDstroke *gps)
{
- bGPDspoint *temp_points = NULL;
- MDeformVert *temp_dverts = NULL;
- bGPDspoint *pt = NULL;
- const bGPDspoint *pt_start = &gps->points[0];
- const bGPDspoint *pt_last = &gps->points[gps->totpoints - 1];
- const bool do_first = (pt_start->flag & GP_SPOINT_SELECT);
- const bool do_last = ((pt_last->flag & GP_SPOINT_SELECT) && (pt_start != pt_last));
- const bool do_stroke = (do_first || do_last);
-
- /* review points in the middle of stroke to create new strokes */
- for (int i = 0; i < gps->totpoints; i++) {
- /* skip first and last point */
- if ((i == 0) || (i == gps->totpoints - 1)) {
- continue;
- }
-
- pt = &gps->points[i];
- if (pt->flag == GP_SPOINT_SELECT) {
- /* duplicate original stroke data */
- bGPDstroke *gps_new = MEM_dupallocN(gps);
- gps_new->prev = gps_new->next = NULL;
-
- /* add new points array */
- gps_new->totpoints = 1;
- gps_new->points = MEM_callocN(sizeof(bGPDspoint), __func__);
- gps_new->dvert = NULL;
-
- if (gps->dvert != NULL) {
- 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);
-
- /* deselect orinal point */
- pt->flag &= ~GP_SPOINT_SELECT;
- }
- }
-
- /* review first and last point to reuse same stroke */
- int i2 = 0;
- int totnewpoints, oldtotpoints;
- /* if first or last, reuse stroke and resize */
- if ((do_first) || (do_last)) {
- totnewpoints = gps->totpoints;
- if (do_first) {
- totnewpoints++;
- }
- if (do_last) {
- totnewpoints++;
- }
-
- /* duplicate points in a temp area */
- temp_points = MEM_dupallocN(gps->points);
- oldtotpoints = gps->totpoints;
- if (gps->dvert != NULL) {
- temp_dverts = MEM_dupallocN(gps->dvert);
- }
-
- /* if first point, need move all one position */
- if (do_first) {
- i2 = 1;
- }
-
- /* resize the points arrays */
- gps->totpoints = totnewpoints;
- gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
- if (gps->dvert != NULL) {
- gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
- }
-
- /* move points to new position */
- for (int i = 0; i < oldtotpoints; i++) {
- 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 begining */
- if (do_first) {
- copy_move_point(gps, temp_points, temp_dverts, 0, 0, true);
- /* deselect old */
- pt = &gps->points[1];
- pt->flag &= ~GP_SPOINT_SELECT;
- /* select new */
- pt = &gps->points[0];
- pt->flag |= GP_SPOINT_SELECT;
- }
-
- /* if last point, add new point at the end */
- if (do_last) {
- copy_move_point(
- gps, temp_points, temp_dverts,
- oldtotpoints - 1, gps->totpoints - 1, true);
-
- /* deselect old */
- pt = &gps->points[gps->totpoints - 2];
- pt->flag &= ~GP_SPOINT_SELECT;
- /* select new */
- pt = &gps->points[gps->totpoints - 1];
- pt->flag |= GP_SPOINT_SELECT;
- }
-
- MEM_SAFE_FREE(temp_points);
- MEM_SAFE_FREE(temp_dverts);
- }
-
- /* if the stroke is not reused, deselect */
- if (!do_stroke) {
- gps->flag &= ~GP_STROKE_SELECT;
- }
+ bGPDspoint *temp_points = NULL;
+ MDeformVert *temp_dverts = NULL;
+ bGPDspoint *pt = NULL;
+ const bGPDspoint *pt_start = &gps->points[0];
+ const bGPDspoint *pt_last = &gps->points[gps->totpoints - 1];
+ const bool do_first = (pt_start->flag & GP_SPOINT_SELECT);
+ const bool do_last = ((pt_last->flag & GP_SPOINT_SELECT) && (pt_start != pt_last));
+ const bool do_stroke = (do_first || do_last);
+
+ /* review points in the middle of stroke to create new strokes */
+ for (int i = 0; i < gps->totpoints; i++) {
+ /* skip first and last point */
+ if ((i == 0) || (i == gps->totpoints - 1)) {
+ continue;
+ }
+
+ pt = &gps->points[i];
+ if (pt->flag == GP_SPOINT_SELECT) {
+ /* duplicate original stroke data */
+ bGPDstroke *gps_new = MEM_dupallocN(gps);
+ gps_new->prev = gps_new->next = NULL;
+
+ /* add new points array */
+ gps_new->totpoints = 1;
+ gps_new->points = MEM_callocN(sizeof(bGPDspoint), __func__);
+ gps_new->dvert = NULL;
+
+ if (gps->dvert != NULL) {
+ 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);
+
+ /* deselect orinal point */
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ }
+
+ /* review first and last point to reuse same stroke */
+ int i2 = 0;
+ int totnewpoints, oldtotpoints;
+ /* if first or last, reuse stroke and resize */
+ if ((do_first) || (do_last)) {
+ totnewpoints = gps->totpoints;
+ if (do_first) {
+ totnewpoints++;
+ }
+ if (do_last) {
+ totnewpoints++;
+ }
+
+ /* duplicate points in a temp area */
+ temp_points = MEM_dupallocN(gps->points);
+ oldtotpoints = gps->totpoints;
+ if (gps->dvert != NULL) {
+ temp_dverts = MEM_dupallocN(gps->dvert);
+ }
+
+ /* if first point, need move all one position */
+ if (do_first) {
+ i2 = 1;
+ }
+
+ /* resize the points arrays */
+ gps->totpoints = totnewpoints;
+ gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
+ if (gps->dvert != NULL) {
+ gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
+ }
+
+ /* move points to new position */
+ for (int i = 0; i < oldtotpoints; i++) {
+ 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 begining */
+ if (do_first) {
+ copy_move_point(gps, temp_points, temp_dverts, 0, 0, true);
+ /* deselect old */
+ pt = &gps->points[1];
+ pt->flag &= ~GP_SPOINT_SELECT;
+ /* select new */
+ pt = &gps->points[0];
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+
+ /* if last point, add new point at the end */
+ if (do_last) {
+ copy_move_point(gps, temp_points, temp_dverts, oldtotpoints - 1, gps->totpoints - 1, true);
+
+ /* deselect old */
+ pt = &gps->points[gps->totpoints - 2];
+ pt->flag &= ~GP_SPOINT_SELECT;
+ /* select new */
+ pt = &gps->points[gps->totpoints - 1];
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+
+ MEM_SAFE_FREE(temp_points);
+ MEM_SAFE_FREE(temp_dverts);
+ }
+
+ /* if the stroke is not reused, deselect */
+ if (!do_stroke) {
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
}
static int gp_extrude_exec(bContext *C, wmOperator *op)
{
- Object *obact = CTX_data_active_object(C);
- bGPdata *gpd = (bGPdata *)obact->data;
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- bGPDstroke *gps = NULL;
-
- if (gpd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
- return OPERATOR_CANCELLED;
- }
-
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- 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))) {
- if (gpf == NULL)
- continue;
-
- for (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;
-
- if (gps->flag & GP_STROKE_SELECT) {
- gpencil_add_move_points(gpf, gps);
- }
- }
- /* if not multiedit, exit loop*/
- if (!is_multiedit) {
- break;
- }
- }
- }
- }
- CTX_DATA_END;
-
- /* updates */
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
- DEG_id_tag_update(&obact->id, ID_RECALC_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
+ Object *obact = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)obact->data;
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ bGPDstroke *gps = NULL;
+
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
+ return OPERATOR_CANCELLED;
+ }
+
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ 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))) {
+ if (gpf == NULL)
+ continue;
+
+ for (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;
+
+ if (gps->flag & GP_STROKE_SELECT) {
+ gpencil_add_move_points(gpf, gps);
+ }
+ }
+ /* if not multiedit, exit loop*/
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* updates */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+ DEG_id_tag_update(&obact->id, ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_extrude(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Extrude Stroke Points";
- ot->idname = "GPENCIL_OT_extrude";
- ot->description = "Extrude the selected Grease Pencil points";
+ /* identifiers */
+ ot->name = "Extrude Stroke Points";
+ ot->idname = "GPENCIL_OT_extrude";
+ ot->description = "Extrude the selected Grease Pencil points";
- /* callbacks */
- ot->exec = gp_extrude_exec;
- ot->poll = gp_stroke_edit_poll;
+ /* callbacks */
+ ot->exec = gp_extrude_exec;
+ ot->poll = gp_stroke_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/* ******************* Copy/Paste Strokes ************************* */
/* Grease Pencil stroke data copy/paste buffer:
* - The copy operation collects all segments of selected strokes,
@@ -984,8 +984,8 @@ void GPENCIL_OT_extrude(wmOperatorType *ot)
* 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 */
+/* list of bGPDstroke instances */
+/* NOTE: is exposed within the editors/gpencil module so that other tools can use it too */
ListBase gp_strokes_copypastebuf = {NULL, NULL};
/* Hash for hanging on to all the colors used by strokes in the buffer
@@ -997,69 +997,69 @@ static GHash *gp_strokes_copypastebuf_colors = NULL;
static GHash *gp_strokes_copypastebuf_colors_material_to_name_create(Main *bmain)
{
- GHash *ma_to_name = BLI_ghash_ptr_new(__func__);
+ GHash *ma_to_name = BLI_ghash_ptr_new(__func__);
- for (Material *ma = bmain->materials.first; ma != NULL; ma = ma->id.next) {
- char *name = BKE_id_to_unique_string_key(&ma->id);
- BLI_ghash_insert(ma_to_name, ma, name);
- }
+ for (Material *ma = bmain->materials.first; ma != NULL; ma = ma->id.next) {
+ char *name = BKE_id_to_unique_string_key(&ma->id);
+ BLI_ghash_insert(ma_to_name, ma, name);
+ }
- return ma_to_name;
+ return ma_to_name;
}
static void gp_strokes_copypastebuf_colors_material_to_name_free(GHash *ma_to_name)
{
- BLI_ghash_free(ma_to_name, NULL, MEM_freeN);
+ BLI_ghash_free(ma_to_name, NULL, MEM_freeN);
}
static GHash *gp_strokes_copypastebuf_colors_name_to_material_create(Main *bmain)
{
- GHash *name_to_ma = BLI_ghash_str_new(__func__);
+ GHash *name_to_ma = BLI_ghash_str_new(__func__);
- for (Material *ma = bmain->materials.first; ma != NULL; ma = ma->id.next) {
- char *name = BKE_id_to_unique_string_key(&ma->id);
- BLI_ghash_insert(name_to_ma, name, ma);
- }
+ for (Material *ma = bmain->materials.first; ma != NULL; ma = ma->id.next) {
+ char *name = BKE_id_to_unique_string_key(&ma->id);
+ BLI_ghash_insert(name_to_ma, name, ma);
+ }
- return name_to_ma;
+ return name_to_ma;
}
static void gp_strokes_copypastebuf_colors_name_to_material_free(GHash *name_to_ma)
{
- BLI_ghash_free(name_to_ma, MEM_freeN, NULL);
+ BLI_ghash_free(name_to_ma, MEM_freeN, NULL);
}
/* Free copy/paste buffer data */
void ED_gpencil_strokes_copybuf_free(void)
{
- bGPDstroke *gps, *gpsn;
-
- /* Free the colors buffer
- * NOTE: This is done before the strokes so that the ptrs are still safe
- */
- if (gp_strokes_copypastebuf_colors) {
- BLI_ghash_free(gp_strokes_copypastebuf_colors, NULL, MEM_freeN);
- gp_strokes_copypastebuf_colors = NULL;
- }
-
- /* Free the stroke buffer */
- for (gps = gp_strokes_copypastebuf.first; gps; gps = gpsn) {
- gpsn = gps->next;
-
- if (gps->points) {
- MEM_freeN(gps->points);
- }
- if (gps->dvert) {
- BKE_gpencil_free_stroke_weights(gps);
- MEM_freeN(gps->dvert);
- }
-
- MEM_SAFE_FREE(gps->triangles);
-
- BLI_freelinkN(&gp_strokes_copypastebuf, gps);
- }
-
- gp_strokes_copypastebuf.first = gp_strokes_copypastebuf.last = NULL;
+ bGPDstroke *gps, *gpsn;
+
+ /* Free the colors buffer
+ * NOTE: This is done before the strokes so that the ptrs are still safe
+ */
+ if (gp_strokes_copypastebuf_colors) {
+ BLI_ghash_free(gp_strokes_copypastebuf_colors, NULL, MEM_freeN);
+ gp_strokes_copypastebuf_colors = NULL;
+ }
+
+ /* Free the stroke buffer */
+ for (gps = gp_strokes_copypastebuf.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ if (gps->points) {
+ MEM_freeN(gps->points);
+ }
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
+
+ MEM_SAFE_FREE(gps->triangles);
+
+ BLI_freelinkN(&gp_strokes_copypastebuf, gps);
+ }
+
+ gp_strokes_copypastebuf.first = gp_strokes_copypastebuf.last = NULL;
}
/* Ensure that destination datablock has all the colours the pasted strokes need
@@ -1067,30 +1067,30 @@ void ED_gpencil_strokes_copybuf_free(void)
*/
GHash *gp_copybuf_validate_colormap(bContext *C)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = CTX_data_active_object(C);
- GHash *new_colors = BLI_ghash_int_new("GPencil Paste Dst Colors");
- GHashIterator gh_iter;
+ Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
+ GHash *new_colors = BLI_ghash_int_new("GPencil Paste Dst Colors");
+ GHashIterator gh_iter;
- /* For each color, check if exist and add if not */
- GHash *name_to_ma = gp_strokes_copypastebuf_colors_name_to_material_create(bmain);
+ /* For each color, check if exist and add if not */
+ GHash *name_to_ma = gp_strokes_copypastebuf_colors_name_to_material_create(bmain);
- GHASH_ITER(gh_iter, gp_strokes_copypastebuf_colors) {
- int *key = BLI_ghashIterator_getKey(&gh_iter);
- char *ma_name = BLI_ghashIterator_getValue(&gh_iter);
- Material *ma = BLI_ghash_lookup(name_to_ma, ma_name);
+ GHASH_ITER (gh_iter, gp_strokes_copypastebuf_colors) {
+ int *key = BLI_ghashIterator_getKey(&gh_iter);
+ char *ma_name = BLI_ghashIterator_getValue(&gh_iter);
+ Material *ma = BLI_ghash_lookup(name_to_ma, ma_name);
- BKE_gpencil_object_material_ensure(bmain, ob, ma);
+ BKE_gpencil_object_material_ensure(bmain, ob, ma);
- /* Store this mapping (for use later when pasting) */
- if (!BLI_ghash_haskey(new_colors, POINTER_FROM_INT(*key))) {
- BLI_ghash_insert(new_colors, POINTER_FROM_INT(*key), ma);
- }
- }
+ /* Store this mapping (for use later when pasting) */
+ if (!BLI_ghash_haskey(new_colors, POINTER_FROM_INT(*key))) {
+ BLI_ghash_insert(new_colors, POINTER_FROM_INT(*key), ma);
+ }
+ }
- gp_strokes_copypastebuf_colors_name_to_material_free(name_to_ma);
+ gp_strokes_copypastebuf_colors_name_to_material_free(name_to_ma);
- return new_colors;
+ return new_colors;
}
/* --------------------- */
@@ -1098,111 +1098,111 @@ GHash *gp_copybuf_validate_colormap(bContext *C)
static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = CTX_data_active_object(C);
- bGPdata *gpd = ED_gpencil_data_get_active(C);
-
- if (gpd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
- return OPERATOR_CANCELLED;
- }
-
- if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
- BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition");
- return OPERATOR_CANCELLED;
- }
-
- /* clear the buffer first */
- ED_gpencil_strokes_copybuf_free();
-
- /* for each visible (and editable) layer's selected strokes,
- * copy the strokes into a temporary buffer, then append
- * once all done
- */
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- bGPDframe *gpf = gpl->actframe;
- bGPDstroke *gps;
-
- if (gpf == NULL)
- continue;
-
- /* make copies of selected strokes, and deselect these once we're done */
- for (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;
-
- if (gps->flag & GP_STROKE_SELECT) {
- if (gps->totpoints == 1) {
- /* Special Case: If there's just a single point in this stroke... */
- bGPDstroke *gpsd;
-
- /* make direct copies of the stroke and its points */
- gpsd = MEM_dupallocN(gps);
- /* saves original layer name */
- 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);
- }
-
- /* triangles cache - will be recalculated on next redraw */
- gpsd->flag |= GP_STROKE_RECALC_GEOMETRY;
- gpsd->tot_triangles = 0;
- gpsd->triangles = NULL;
-
- /* add to temp buffer */
- gpsd->next = gpsd->prev = NULL;
- BLI_addtail(&gp_strokes_copypastebuf, gpsd);
- }
- else {
- /* delegate to a helper, as there's too much to fit in here (for copying subsets)... */
- gp_duplicate_points(gps, &gp_strokes_copypastebuf, gpl->info);
- }
- }
- }
- }
- CTX_DATA_END;
-
- /* Build up hash of material colors used in these strokes */
- 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) {
- if (ED_gpencil_stroke_can_use(C, gps)) {
- char **ma_name_val;
- if (!BLI_ghash_ensure_p(gp_strokes_copypastebuf_colors, &gps->mat_nr, (void ***)&ma_name_val)) {
- Material *ma = give_current_material(ob, gps->mat_nr + 1);
- char *ma_name = BLI_ghash_lookup(ma_to_name, ma);
- *ma_name_val = MEM_dupallocN(ma_name);
- }
- }
- }
- gp_strokes_copypastebuf_colors_material_to_name_free(ma_to_name);
- }
-
- /* updates (to ensure operator buttons are refreshed, when used via hotkeys) */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL); // XXX?
-
- /* done */
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
+ BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* clear the buffer first */
+ ED_gpencil_strokes_copybuf_free();
+
+ /* for each visible (and editable) layer's selected strokes,
+ * copy the strokes into a temporary buffer, then append
+ * once all done
+ */
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps;
+
+ if (gpf == NULL)
+ continue;
+
+ /* make copies of selected strokes, and deselect these once we're done */
+ for (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;
+
+ if (gps->flag & GP_STROKE_SELECT) {
+ if (gps->totpoints == 1) {
+ /* Special Case: If there's just a single point in this stroke... */
+ bGPDstroke *gpsd;
+
+ /* make direct copies of the stroke and its points */
+ gpsd = MEM_dupallocN(gps);
+ /* saves original layer name */
+ 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);
+ }
+
+ /* triangles cache - will be recalculated on next redraw */
+ gpsd->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gpsd->tot_triangles = 0;
+ gpsd->triangles = NULL;
+
+ /* add to temp buffer */
+ gpsd->next = gpsd->prev = NULL;
+ BLI_addtail(&gp_strokes_copypastebuf, gpsd);
+ }
+ else {
+ /* delegate to a helper, as there's too much to fit in here (for copying subsets)... */
+ gp_duplicate_points(gps, &gp_strokes_copypastebuf, gpl->info);
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* Build up hash of material colors used in these strokes */
+ 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) {
+ if (ED_gpencil_stroke_can_use(C, gps)) {
+ char **ma_name_val;
+ if (!BLI_ghash_ensure_p(
+ gp_strokes_copypastebuf_colors, &gps->mat_nr, (void ***)&ma_name_val)) {
+ Material *ma = give_current_material(ob, gps->mat_nr + 1);
+ char *ma_name = BLI_ghash_lookup(ma_to_name, ma);
+ *ma_name_val = MEM_dupallocN(ma_name);
+ }
+ }
+ }
+ gp_strokes_copypastebuf_colors_material_to_name_free(ma_to_name);
+ }
+
+ /* updates (to ensure operator buttons are refreshed, when used via hotkeys) */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL); // XXX?
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Strokes";
- ot->idname = "GPENCIL_OT_copy";
- ot->description = "Copy selected Grease Pencil points and strokes";
+ /* identifiers */
+ ot->name = "Copy Strokes";
+ ot->idname = "GPENCIL_OT_copy";
+ ot->description = "Copy selected Grease Pencil points and strokes";
- /* callbacks */
- ot->exec = gp_strokes_copy_exec;
- ot->poll = gp_stroke_edit_poll;
+ /* callbacks */
+ ot->exec = gp_strokes_copy_exec;
+ ot->poll = gp_stroke_edit_poll;
- /* flags */
- //ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ //ot->flag = OPTYPE_REGISTER;
}
/* --------------------- */
@@ -1210,299 +1210,302 @@ void GPENCIL_OT_copy(wmOperatorType *ot)
static bool gp_strokes_paste_poll(bContext *C)
{
- /* 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, but that should prompt a warning instead
- * 2) Copy buffer must at least have something (though it may be the wrong sort...)
- */
- return (ED_gpencil_data_get_active(C) != NULL) && (!BLI_listbase_is_empty(&gp_strokes_copypastebuf));
+ /* 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, but that should prompt a warning instead
+ * 2) Copy buffer must at least have something (though it may be the wrong sort...)
+ */
+ return (ED_gpencil_data_get_active(C) != NULL) &&
+ (!BLI_listbase_is_empty(&gp_strokes_copypastebuf));
}
typedef enum eGP_PasteMode {
- GP_COPY_ONLY = -1,
- GP_COPY_MERGE = 1,
+ GP_COPY_ONLY = -1,
+ GP_COPY_MERGE = 1,
} 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 */
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
- bGPDframe *gpf;
-
- eGP_PasteMode type = RNA_enum_get(op->ptr, "type");
- 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)) {
- BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition");
- return OPERATOR_CANCELLED;
- }
- else if (BLI_listbase_is_empty(&gp_strokes_copypastebuf)) {
- BKE_report(op->reports, RPT_ERROR, "No strokes to paste, select and copy some points before trying again");
- return OPERATOR_CANCELLED;
- }
- else if (gpl == NULL) {
- /* 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_MERGE)) {
- BKE_report(op->reports, RPT_ERROR, "Can not paste strokes when active layer is hidden or locked");
- return OPERATOR_CANCELLED;
- }
- else {
- /* Check that some of the strokes in the buffer can be used */
- bGPDstroke *gps;
- bool ok = false;
-
- for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
- if (ED_gpencil_stroke_can_use(C, gps)) {
- ok = true;
- break;
- }
- }
-
- 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;
- }
- }
-
- /* Deselect all strokes first */
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- bGPDspoint *pt;
- int i;
-
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- pt->flag &= ~GP_SPOINT_SELECT;
- }
-
- gps->flag &= ~GP_STROKE_SELECT;
- }
- CTX_DATA_END;
-
- /* Ensure that all the necessary colors exist */
- 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) {
- if (ED_gpencil_stroke_can_use(C, gps)) {
- /* Need to verify if layer exists */
- if (type != GP_COPY_MERGE) {
- 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);
- }
- }
-
- /* Ensure we have a frame to draw into
- * NOTE: Since this is an op which creates strokes,
- * we are obliged to add a new frame if one
- * doesn't exist already
- */
- gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_ADD_NEW);
- if (gpf) {
- /* Create new stroke */
- bGPDstroke *new_stroke = MEM_dupallocN(gps);
- new_stroke->runtime.tmp_layerinfo[0] = '\0';
-
- 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;
-
- new_stroke->next = new_stroke->prev = NULL;
- 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);
- BLI_assert(new_stroke->mat_nr >= 0); /* have to add the material first */
- }
- }
- }
-
- /* free temp data */
- BLI_ghash_free(new_colors, NULL, NULL);
-
- /* 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);
-
- return OPERATOR_FINISHED;
+ 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 */
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+ bGPDframe *gpf;
+
+ eGP_PasteMode type = RNA_enum_get(op->ptr, "type");
+ 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)) {
+ BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition");
+ return OPERATOR_CANCELLED;
+ }
+ else if (BLI_listbase_is_empty(&gp_strokes_copypastebuf)) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "No strokes to paste, select and copy some points before trying again");
+ return OPERATOR_CANCELLED;
+ }
+ else if (gpl == NULL) {
+ /* 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_MERGE)) {
+ BKE_report(
+ op->reports, RPT_ERROR, "Can not paste strokes when active layer is hidden or locked");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* Check that some of the strokes in the buffer can be used */
+ bGPDstroke *gps;
+ bool ok = false;
+
+ for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
+ if (ED_gpencil_stroke_can_use(C, gps)) {
+ ok = true;
+ break;
+ }
+ }
+
+ 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;
+ }
+ }
+
+ /* Deselect all strokes first */
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ bGPDspoint *pt;
+ int i;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ CTX_DATA_END;
+
+ /* Ensure that all the necessary colors exist */
+ 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) {
+ if (ED_gpencil_stroke_can_use(C, gps)) {
+ /* Need to verify if layer exists */
+ if (type != GP_COPY_MERGE) {
+ 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);
+ }
+ }
+
+ /* Ensure we have a frame to draw into
+ * NOTE: Since this is an op which creates strokes,
+ * we are obliged to add a new frame if one
+ * doesn't exist already
+ */
+ gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_ADD_NEW);
+ if (gpf) {
+ /* Create new stroke */
+ bGPDstroke *new_stroke = MEM_dupallocN(gps);
+ new_stroke->runtime.tmp_layerinfo[0] = '\0';
+
+ 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;
+
+ new_stroke->next = new_stroke->prev = NULL;
+ 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);
+ BLI_assert(new_stroke->mat_nr >= 0); /* have to add the material first */
+ }
+ }
+ }
+
+ /* free temp data */
+ BLI_ghash_free(new_colors, NULL, NULL);
+
+ /* 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);
+
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_paste(wmOperatorType *ot)
{
- static const EnumPropertyItem copy_type[] = {
- {GP_COPY_ONLY, "COPY", 0, "Copy", ""},
- {GP_COPY_MERGE, "MERGE", 0, "Merge", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Paste Strokes";
- ot->idname = "GPENCIL_OT_paste";
- ot->description = "Paste previously copied strokes or copy and merge in active layer";
-
- /* callbacks */
- ot->exec = gp_strokes_paste_exec;
- ot->poll = gp_strokes_paste_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", copy_type, 0, "Type", "");
+ static const EnumPropertyItem copy_type[] = {
+ {GP_COPY_ONLY, "COPY", 0, "Copy", ""},
+ {GP_COPY_MERGE, "MERGE", 0, "Merge", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Paste Strokes";
+ ot->idname = "GPENCIL_OT_paste";
+ ot->description = "Paste previously copied strokes or copy and merge in active layer";
+
+ /* callbacks */
+ ot->exec = gp_strokes_paste_exec;
+ ot->poll = gp_strokes_paste_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", copy_type, 0, "Type", "");
}
/* ******************* Move To Layer ****************************** */
static int gp_move_to_layer_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(evt))
{
- uiPopupMenu *pup;
- uiLayout *layout;
+ uiPopupMenu *pup;
+ uiLayout *layout;
- /* call the menu, which will call this operator again, hence the canceled */
- pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
- layout = UI_popup_menu_layout(pup);
- uiItemsEnumO(layout, "GPENCIL_OT_move_to_layer", "layer");
- UI_popup_menu_end(C, pup);
+ /* call the menu, which will call this operator again, hence the canceled */
+ pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ uiItemsEnumO(layout, "GPENCIL_OT_move_to_layer", "layer");
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
// FIXME: allow moving partial strokes
static int gp_move_to_layer_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = CTX_data_gpencil_data(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
- bGPDlayer *target_layer = NULL;
- ListBase strokes = {NULL, NULL};
- int layer_num = RNA_enum_get(op->ptr, "layer");
- const bool use_autolock = (bool)(gpd->flag & GP_DATA_AUTOLOCK_LAYERS);
-
- if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
- BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition");
- return OPERATOR_CANCELLED;
- }
-
- /* if autolock enabled, disabled now */
- if (use_autolock) {
- gpd->flag &= ~GP_DATA_AUTOLOCK_LAYERS;
- }
-
- /* Get layer or create new one */
- if (layer_num == -1) {
- /* Create layer */
- target_layer = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
- }
- else {
- /* Try to get layer */
- target_layer = BLI_findlink(&gpd->layers, layer_num);
-
- if (target_layer == NULL) {
- /* back autolock status */
- if (use_autolock) {
- gpd->flag |= GP_DATA_AUTOLOCK_LAYERS;
- }
- BKE_reportf(op->reports, RPT_ERROR, "There is no layer number %d", layer_num);
- return OPERATOR_CANCELLED;
- }
- }
-
- /* Extract all strokes to move to this layer
- * NOTE: We need to do this in a two-pass system to avoid conflicts with strokes
- * getting repeatedly moved
- */
- 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))
- continue;
-
- /* make copies of selected strokes, and deselect these once we're done */
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
-
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, 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);
- BLI_addtail(&strokes, gps);
- }
- }
-
- /* if new layer and autolock, lock old layer */
- if ((layer_num == -1) && (use_autolock)) {
- gpl->flag |= GP_LAYER_LOCKED;
- }
- }
- CTX_DATA_END;
-
- /* Paste them all in one go */
- if (strokes.first) {
- bGPDframe *gpf = BKE_gpencil_layer_getframe(target_layer, cfra_eval, GP_GETFRAME_ADD_NEW);
-
- BLI_movelisttolist(&gpf->strokes, &strokes);
- BLI_assert((strokes.first == strokes.last) && (strokes.first == NULL));
- }
-
- /* back autolock status */
- if (use_autolock) {
- gpd->flag |= GP_DATA_AUTOLOCK_LAYERS;
- }
-
- /* 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);
-
- return OPERATOR_FINISHED;
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+ bGPDlayer *target_layer = NULL;
+ ListBase strokes = {NULL, NULL};
+ int layer_num = RNA_enum_get(op->ptr, "layer");
+ const bool use_autolock = (bool)(gpd->flag & GP_DATA_AUTOLOCK_LAYERS);
+
+ if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
+ BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* if autolock enabled, disabled now */
+ if (use_autolock) {
+ gpd->flag &= ~GP_DATA_AUTOLOCK_LAYERS;
+ }
+
+ /* Get layer or create new one */
+ if (layer_num == -1) {
+ /* Create layer */
+ target_layer = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
+ }
+ else {
+ /* Try to get layer */
+ target_layer = BLI_findlink(&gpd->layers, layer_num);
+
+ if (target_layer == NULL) {
+ /* back autolock status */
+ if (use_autolock) {
+ gpd->flag |= GP_DATA_AUTOLOCK_LAYERS;
+ }
+ BKE_reportf(op->reports, RPT_ERROR, "There is no layer number %d", layer_num);
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ /* Extract all strokes to move to this layer
+ * NOTE: We need to do this in a two-pass system to avoid conflicts with strokes
+ * getting repeatedly moved
+ */
+ 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))
+ continue;
+
+ /* make copies of selected strokes, and deselect these once we're done */
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, 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);
+ BLI_addtail(&strokes, gps);
+ }
+ }
+
+ /* if new layer and autolock, lock old layer */
+ if ((layer_num == -1) && (use_autolock)) {
+ gpl->flag |= GP_LAYER_LOCKED;
+ }
+ }
+ CTX_DATA_END;
+
+ /* Paste them all in one go */
+ if (strokes.first) {
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(target_layer, cfra_eval, GP_GETFRAME_ADD_NEW);
+
+ BLI_movelisttolist(&gpf->strokes, &strokes);
+ BLI_assert((strokes.first == strokes.last) && (strokes.first == NULL));
+ }
+
+ /* back autolock status */
+ if (use_autolock) {
+ gpd->flag |= GP_DATA_AUTOLOCK_LAYERS;
+ }
+
+ /* 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);
+
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_move_to_layer(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move Strokes to Layer";
- ot->idname = "GPENCIL_OT_move_to_layer";
- ot->description = "Move selected strokes to another layer"; // XXX: allow moving individual points too?
-
- /* callbacks */
- ot->invoke = gp_move_to_layer_invoke;
- ot->exec = gp_move_to_layer_exec;
- ot->poll = gp_stroke_edit_poll; // XXX?
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* gp layer to use (dynamic enum) */
- ot->prop = RNA_def_enum(ot->srna, "layer", DummyRNA_DEFAULT_items, 0, "Grease Pencil Layer", "");
- RNA_def_enum_funcs(ot->prop, ED_gpencil_layers_with_new_enum_itemf);
+ /* identifiers */
+ ot->name = "Move Strokes to Layer";
+ ot->idname = "GPENCIL_OT_move_to_layer";
+ ot->description =
+ "Move selected strokes to another layer"; // XXX: allow moving individual points too?
+
+ /* callbacks */
+ ot->invoke = gp_move_to_layer_invoke;
+ ot->exec = gp_move_to_layer_exec;
+ ot->poll = gp_stroke_edit_poll; // XXX?
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* gp layer to use (dynamic enum) */
+ ot->prop = RNA_def_enum(ot->srna, "layer", DummyRNA_DEFAULT_items, 0, "Grease Pencil Layer", "");
+ RNA_def_enum_funcs(ot->prop, ED_gpencil_layers_with_new_enum_itemf);
}
/* ********************* Add Blank Frame *************************** */
@@ -1510,221 +1513,224 @@ void GPENCIL_OT_move_to_layer(wmOperatorType *ot)
/* 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;
+ 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;
}
static int gp_blank_frame_add_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
-
- bGPDlayer *active_gpl = BKE_gpencil_layer_getactive(gpd);
-
- const bool all_layers = RNA_boolean_get(op->ptr, "all_layers");
-
- /* Initialise datablock and an active layer if nothing exists yet */
- if (ELEM(NULL, gpd, active_gpl)) {
- /* let's just be lazy, and call the "Add New Layer" operator, which sets everything up as required */
- WM_operator_name_call(C, "GPENCIL_OT_layer_add", WM_OP_EXEC_DEFAULT, NULL);
- }
-
- /* Go through each layer, adding a frame after the active one
- * and/or shunting all the others out of the way
- */
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- if ((all_layers == false) && (gpl != active_gpl)) {
- continue;
- }
-
- /* 1) Check for an existing frame on the current frame */
- bGPDframe *gpf = BKE_gpencil_layer_find_frame(gpl, cfra_eval);
- if (gpf) {
- /* Shunt all frames after (and including) the existing one later by 1-frame */
- for (; gpf; gpf = gpf->next) {
- gpf->framenum += 1;
- }
- }
-
- /* 2) Now add a new frame, with nothing in it */
- gpl->actframe = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_ADD_NEW);
- }
- CTX_DATA_END;
-
- /* 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;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+ bGPDlayer *active_gpl = BKE_gpencil_layer_getactive(gpd);
+
+ const bool all_layers = RNA_boolean_get(op->ptr, "all_layers");
+
+ /* Initialise datablock and an active layer if nothing exists yet */
+ if (ELEM(NULL, gpd, active_gpl)) {
+ /* let's just be lazy, and call the "Add New Layer" operator, which sets everything up as required */
+ WM_operator_name_call(C, "GPENCIL_OT_layer_add", WM_OP_EXEC_DEFAULT, NULL);
+ }
+
+ /* Go through each layer, adding a frame after the active one
+ * and/or shunting all the others out of the way
+ */
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ if ((all_layers == false) && (gpl != active_gpl)) {
+ continue;
+ }
+
+ /* 1) Check for an existing frame on the current frame */
+ bGPDframe *gpf = BKE_gpencil_layer_find_frame(gpl, cfra_eval);
+ if (gpf) {
+ /* Shunt all frames after (and including) the existing one later by 1-frame */
+ for (; gpf; gpf = gpf->next) {
+ gpf->framenum += 1;
+ }
+ }
+
+ /* 2) Now add a new frame, with nothing in it */
+ gpl->actframe = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_ADD_NEW);
+ }
+ CTX_DATA_END;
+
+ /* 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_blank_frame_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Insert Blank Frame";
- ot->idname = "GPENCIL_OT_blank_frame_add";
- ot->description = "Insert a blank frame on the current frame "
- "(all subsequently existing frames, if any, are shifted right by one frame)";
-
- /* callbacks */
- ot->exec = gp_blank_frame_add_exec;
- ot->poll = gp_add_poll;
-
- /* properties */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "all_layers", false, "All Layers", "Create blank frame in all layers, not only active");
+ /* identifiers */
+ ot->name = "Insert Blank Frame";
+ ot->idname = "GPENCIL_OT_blank_frame_add";
+ ot->description =
+ "Insert a blank frame on the current frame "
+ "(all subsequently existing frames, if any, are shifted right by one frame)";
+
+ /* callbacks */
+ ot->exec = gp_blank_frame_add_exec;
+ ot->poll = gp_add_poll;
+
+ /* properties */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ RNA_def_boolean(ot->srna,
+ "all_layers",
+ false,
+ "All Layers",
+ "Create blank frame in all layers, not only active");
}
/* ******************* Delete Active Frame ************************ */
static bool gp_actframe_delete_poll(bContext *C)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
- /* only if there's an active layer with an active frame */
- return (gpl && gpl->actframe);
+ /* only if there's an active layer with an active frame */
+ return (gpl && gpl->actframe);
}
/* delete active frame - wrapper around API calls */
static int gp_actframe_delete_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV);
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV);
- /* if there's no existing Grease-Pencil data there, add some */
- if (gpd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No grease pencil data");
- return OPERATOR_CANCELLED;
- }
- if (ELEM(NULL, gpl, gpf)) {
- BKE_report(op->reports, RPT_ERROR, "No active frame to delete");
- return OPERATOR_CANCELLED;
- }
+ /* if there's no existing Grease-Pencil data there, add some */
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No grease pencil data");
+ return OPERATOR_CANCELLED;
+ }
+ if (ELEM(NULL, gpl, gpf)) {
+ BKE_report(op->reports, RPT_ERROR, "No active frame to delete");
+ return OPERATOR_CANCELLED;
+ }
- /* delete it... */
- BKE_gpencil_layer_delframe(gpl, gpf);
+ /* delete it... */
+ BKE_gpencil_layer_delframe(gpl, gpf);
- /* 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);
+ /* 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;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_active_frame_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Active Frame";
- ot->idname = "GPENCIL_OT_active_frame_delete";
- ot->description = "Delete the active frame for the active Grease Pencil Layer";
+ /* identifiers */
+ ot->name = "Delete Active Frame";
+ ot->idname = "GPENCIL_OT_active_frame_delete";
+ ot->description = "Delete the active frame for the active Grease Pencil Layer";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* callbacks */
- ot->exec = gp_actframe_delete_exec;
- ot->poll = gp_actframe_delete_poll;
+ /* callbacks */
+ ot->exec = gp_actframe_delete_exec;
+ ot->poll = gp_actframe_delete_poll;
}
/* **************** Delete All Active Frames ****************** */
static bool gp_actframe_delete_all_poll(bContext *C)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
- /* 1) There must be grease pencil data
- * 2) Hopefully some of the layers have stuff we can use
- */
- return (gpd && gpd->layers.first);
+ /* 1) There must be grease pencil data
+ * 2) Hopefully some of the layers have stuff we can use
+ */
+ return (gpd && gpd->layers.first);
}
static int gp_actframe_delete_all_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
-
- bool success = false;
-
- 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_eval, GP_GETFRAME_USE_PREV);
-
- if (gpf == NULL)
- continue;
-
- /* delete it... */
- BKE_gpencil_layer_delframe(gpl, gpf);
-
- /* we successfully modified something */
- success = true;
- }
- CTX_DATA_END;
-
- /* updates */
- if (success) {
- 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;
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "No active frame(s) to delete");
- return OPERATOR_CANCELLED;
- }
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+ bool success = false;
+
+ 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_eval, GP_GETFRAME_USE_PREV);
+
+ if (gpf == NULL)
+ continue;
+
+ /* delete it... */
+ BKE_gpencil_layer_delframe(gpl, gpf);
+
+ /* we successfully modified something */
+ success = true;
+ }
+ CTX_DATA_END;
+
+ /* updates */
+ if (success) {
+ 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;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No active frame(s) to delete");
+ return OPERATOR_CANCELLED;
+ }
}
void GPENCIL_OT_active_frames_delete_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete All Active Frames";
- ot->idname = "GPENCIL_OT_active_frames_delete_all";
- ot->description = "Delete the active frame(s) of all editable Grease Pencil layers";
+ /* identifiers */
+ ot->name = "Delete All Active Frames";
+ ot->idname = "GPENCIL_OT_active_frames_delete_all";
+ ot->description = "Delete the active frame(s) of all editable Grease Pencil layers";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* callbacks */
- ot->exec = gp_actframe_delete_all_exec;
- ot->poll = gp_actframe_delete_all_poll;
+ /* callbacks */
+ ot->exec = gp_actframe_delete_all_exec;
+ ot->poll = gp_actframe_delete_all_poll;
}
/* ******************* Delete Operator ************************ */
typedef enum eGP_DeleteMode {
- /* delete selected stroke points */
- GP_DELETEOP_POINTS = 0,
- /* delete selected strokes */
- GP_DELETEOP_STROKES = 1,
- /* delete active frame */
- GP_DELETEOP_FRAME = 2,
+ /* delete selected stroke points */
+ GP_DELETEOP_POINTS = 0,
+ /* delete selected strokes */
+ GP_DELETEOP_STROKES = 1,
+ /* delete active frame */
+ GP_DELETEOP_FRAME = 2,
} eGP_DeleteMode;
typedef enum eGP_DissolveMode {
- /* dissolve all selected points */
- GP_DISSOLVE_POINTS = 0,
- /* dissolve between selected points */
- GP_DISSOLVE_BETWEEN = 1,
- /* dissolve unselected points */
- GP_DISSOLVE_UNSELECT = 2,
+ /* dissolve all selected points */
+ GP_DISSOLVE_POINTS = 0,
+ /* dissolve between selected points */
+ GP_DISSOLVE_BETWEEN = 1,
+ /* dissolve unselected points */
+ GP_DISSOLVE_UNSELECT = 2,
} eGP_DissolveMode;
/* ----------------------------------- */
@@ -1732,61 +1738,60 @@ typedef enum eGP_DissolveMode {
/* Delete selected strokes */
static int gp_delete_selected_strokes(bContext *C)
{
- bool changed = false;
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
-
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- 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))) {
- bGPDstroke *gps, *gpsn;
-
- if (gpf == NULL)
- continue;
-
- /* simply delete strokes which are selected */
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
-
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps) == false)
- continue;
-
- /* free stroke if selected */
- if (gps->flag & GP_STROKE_SELECT) {
- /* free stroke memory arrays, then stroke itself */
- if (gps->points) {
- MEM_freeN(gps->points);
- }
- if (gps->dvert) {
- BKE_gpencil_free_stroke_weights(gps);
- MEM_freeN(gps->dvert);
- }
- MEM_SAFE_FREE(gps->triangles);
- BLI_freelinkN(&gpf->strokes, gps);
-
- changed = true;
- }
- }
- }
- }
- }
- CTX_DATA_END;
-
- 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;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ bool changed = false;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ 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))) {
+ bGPDstroke *gps, *gpsn;
+
+ if (gpf == NULL)
+ continue;
+
+ /* simply delete strokes which are selected */
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
+ /* free stroke if selected */
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* free stroke memory arrays, then stroke itself */
+ if (gps->points) {
+ MEM_freeN(gps->points);
+ }
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
+ MEM_SAFE_FREE(gps->triangles);
+ BLI_freelinkN(&gpf->strokes, gps);
+
+ changed = true;
+ }
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ 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;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
/* ----------------------------------- */
@@ -1794,242 +1799,242 @@ static int gp_delete_selected_strokes(bContext *C)
/* Delete selected points but keep the stroke */
static int gp_dissolve_selected_points(bContext *C, eGP_DissolveMode mode)
{
- Object *ob = CTX_data_active_object(C);
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- bool changed = false;
- int first = 0;
- int last = 0;
-
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- 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))) {
-
- bGPDstroke *gps, *gpsn;
-
- if (gpf == NULL)
- continue;
-
- /* simply delete points from selected strokes
- * NOTE: we may still have to remove the stroke if it ends up having no points!
- */
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
-
- /* 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;
-
- /* the stroke must have at least one point selected for any operator */
- if (gps->flag & GP_STROKE_SELECT) {
- bGPDspoint *pt;
- MDeformVert *dvert = NULL;
- int i;
-
- int tot = gps->totpoints; /* number of points in new buffer */
-
- /* first pass: count points to remove */
- switch (mode) {
- case GP_DISSOLVE_POINTS:
- /* Count how many points are selected (i.e. how many to remove) */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT) {
- /* selected point - one of the points to remove */
- tot--;
- }
- }
- break;
- case GP_DISSOLVE_BETWEEN:
- /* need to find first and last point selected */
- first = -1;
- last = 0;
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT) {
- if (first < 0) {
- first = i;
- }
- last = i;
- }
- }
- /* count unselected points in the range */
- for (i = first, pt = gps->points + first; i < last; i++, pt++) {
- if ((pt->flag & GP_SPOINT_SELECT) == 0) {
- tot--;
- }
- }
- break;
- case GP_DISSOLVE_UNSELECT:
- /* count number of unselected points */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if ((pt->flag & GP_SPOINT_SELECT) == 0) {
- tot--;
- }
- }
- break;
- default:
- return false;
- break;
- }
-
- /* if no points are left, we simply delete the entire stroke */
- if (tot <= 0) {
- /* remove the entire stroke */
- if (gps->points) {
- MEM_freeN(gps->points);
- }
- if (gps->dvert) {
- BKE_gpencil_free_stroke_weights(gps);
- MEM_freeN(gps->dvert);
- }
- if (gps->triangles) {
- MEM_freeN(gps->triangles);
- }
- BLI_freelinkN(&gpf->strokes, gps);
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- }
- else {
- /* just copy all points to keep into a smaller buffer */
- bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * tot, "new gp stroke points copy");
- bGPDspoint *npt = new_points;
-
- MDeformVert *new_dvert = NULL;
- MDeformVert *ndvert = NULL;
-
- if (gps->dvert != NULL) {
- new_dvert = MEM_callocN(sizeof(MDeformVert) * tot, "new gp stroke weights copy");
- ndvert = new_dvert;
- }
-
- switch (mode) {
- case GP_DISSOLVE_POINTS:
- (gps->dvert != NULL) ? dvert = gps->dvert : NULL;
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if ((pt->flag & GP_SPOINT_SELECT) == 0) {
- *npt = *pt;
- npt++;
-
- if (gps->dvert != NULL) {
- *ndvert = *dvert;
- ndvert->dw = MEM_dupallocN(dvert->dw);
- ndvert++;
- dvert++;
- }
- }
- }
- break;
- case GP_DISSOLVE_BETWEEN:
- /* copy first segment */
- (gps->dvert != NULL) ? dvert = gps->dvert : NULL;
- for (i = 0, pt = gps->points; i < first; i++, pt++) {
- *npt = *pt;
- npt++;
-
- if (gps->dvert != NULL) {
- *ndvert = *dvert;
- ndvert->dw = MEM_dupallocN(dvert->dw);
- ndvert++;
- dvert++;
- }
- }
- /* copy segment (selected points) */
- (gps->dvert != NULL) ? dvert = gps->dvert + first : NULL;
- for (i = first, pt = gps->points + first; i < last; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT) {
- *npt = *pt;
- npt++;
-
- if (gps->dvert != NULL) {
- *ndvert = *dvert;
- ndvert->dw = MEM_dupallocN(dvert->dw);
- ndvert++;
- dvert++;
- }
- }
- }
- /* copy last segment */
- (gps->dvert != NULL) ? dvert = gps->dvert + last : NULL;
- for (i = last, pt = gps->points + last; i < gps->totpoints; i++, pt++) {
- *npt = *pt;
- npt++;
-
- if (gps->dvert != NULL) {
- *ndvert = *dvert;
- ndvert->dw = MEM_dupallocN(dvert->dw);
- ndvert++;
- dvert++;
- }
- }
-
- break;
- case GP_DISSOLVE_UNSELECT:
- /* copy any selected point */
- (gps->dvert != NULL) ? dvert = gps->dvert : NULL;
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT) {
- *npt = *pt;
- npt++;
-
- if (gps->dvert != NULL) {
- *ndvert = *dvert;
- ndvert->dw = MEM_dupallocN(dvert->dw);
- ndvert++;
- dvert++;
- }
- }
- }
- break;
- }
-
- /* free the old buffer */
- if (gps->points) {
- MEM_freeN(gps->points);
- }
- if (gps->dvert) {
- BKE_gpencil_free_stroke_weights(gps);
- MEM_freeN(gps->dvert);
- }
-
- /* save the new buffer */
- gps->points = new_points;
- gps->dvert = new_dvert;
- gps->totpoints = tot;
-
- /* triangles cache needs to be recalculated */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
-
- /* deselect the stroke, since none of its selected points will still be selected */
- gps->flag &= ~GP_STROKE_SELECT;
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- pt->flag &= ~GP_SPOINT_SELECT;
- }
- }
-
- changed = true;
- }
- }
- }
- }
- }
- CTX_DATA_END;
-
- 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;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ bool changed = false;
+ int first = 0;
+ int last = 0;
+
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ 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))) {
+
+ bGPDstroke *gps, *gpsn;
+
+ if (gpf == NULL)
+ continue;
+
+ /* simply delete points from selected strokes
+ * NOTE: we may still have to remove the stroke if it ends up having no points!
+ */
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ /* 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;
+
+ /* the stroke must have at least one point selected for any operator */
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ MDeformVert *dvert = NULL;
+ int i;
+
+ int tot = gps->totpoints; /* number of points in new buffer */
+
+ /* first pass: count points to remove */
+ switch (mode) {
+ case GP_DISSOLVE_POINTS:
+ /* Count how many points are selected (i.e. how many to remove) */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ /* selected point - one of the points to remove */
+ tot--;
+ }
+ }
+ break;
+ case GP_DISSOLVE_BETWEEN:
+ /* need to find first and last point selected */
+ first = -1;
+ last = 0;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ if (first < 0) {
+ first = i;
+ }
+ last = i;
+ }
+ }
+ /* count unselected points in the range */
+ for (i = first, pt = gps->points + first; i < last; i++, pt++) {
+ if ((pt->flag & GP_SPOINT_SELECT) == 0) {
+ tot--;
+ }
+ }
+ break;
+ case GP_DISSOLVE_UNSELECT:
+ /* count number of unselected points */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if ((pt->flag & GP_SPOINT_SELECT) == 0) {
+ tot--;
+ }
+ }
+ break;
+ default:
+ return false;
+ break;
+ }
+
+ /* if no points are left, we simply delete the entire stroke */
+ if (tot <= 0) {
+ /* remove the entire stroke */
+ if (gps->points) {
+ MEM_freeN(gps->points);
+ }
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
+ if (gps->triangles) {
+ MEM_freeN(gps->triangles);
+ }
+ BLI_freelinkN(&gpf->strokes, gps);
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ }
+ else {
+ /* just copy all points to keep into a smaller buffer */
+ bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * tot,
+ "new gp stroke points copy");
+ bGPDspoint *npt = new_points;
+
+ MDeformVert *new_dvert = NULL;
+ MDeformVert *ndvert = NULL;
+
+ if (gps->dvert != NULL) {
+ new_dvert = MEM_callocN(sizeof(MDeformVert) * tot, "new gp stroke weights copy");
+ ndvert = new_dvert;
+ }
+
+ switch (mode) {
+ case GP_DISSOLVE_POINTS:
+ (gps->dvert != NULL) ? dvert = gps->dvert : NULL;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if ((pt->flag & GP_SPOINT_SELECT) == 0) {
+ *npt = *pt;
+ npt++;
+
+ if (gps->dvert != NULL) {
+ *ndvert = *dvert;
+ ndvert->dw = MEM_dupallocN(dvert->dw);
+ ndvert++;
+ dvert++;
+ }
+ }
+ }
+ break;
+ case GP_DISSOLVE_BETWEEN:
+ /* copy first segment */
+ (gps->dvert != NULL) ? dvert = gps->dvert : NULL;
+ for (i = 0, pt = gps->points; i < first; i++, pt++) {
+ *npt = *pt;
+ npt++;
+
+ if (gps->dvert != NULL) {
+ *ndvert = *dvert;
+ ndvert->dw = MEM_dupallocN(dvert->dw);
+ ndvert++;
+ dvert++;
+ }
+ }
+ /* copy segment (selected points) */
+ (gps->dvert != NULL) ? dvert = gps->dvert + first : NULL;
+ for (i = first, pt = gps->points + first; i < last; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ *npt = *pt;
+ npt++;
+
+ if (gps->dvert != NULL) {
+ *ndvert = *dvert;
+ ndvert->dw = MEM_dupallocN(dvert->dw);
+ ndvert++;
+ dvert++;
+ }
+ }
+ }
+ /* copy last segment */
+ (gps->dvert != NULL) ? dvert = gps->dvert + last : NULL;
+ for (i = last, pt = gps->points + last; i < gps->totpoints; i++, pt++) {
+ *npt = *pt;
+ npt++;
+
+ if (gps->dvert != NULL) {
+ *ndvert = *dvert;
+ ndvert->dw = MEM_dupallocN(dvert->dw);
+ ndvert++;
+ dvert++;
+ }
+ }
+
+ break;
+ case GP_DISSOLVE_UNSELECT:
+ /* copy any selected point */
+ (gps->dvert != NULL) ? dvert = gps->dvert : NULL;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ *npt = *pt;
+ npt++;
+
+ if (gps->dvert != NULL) {
+ *ndvert = *dvert;
+ ndvert->dw = MEM_dupallocN(dvert->dw);
+ ndvert++;
+ dvert++;
+ }
+ }
+ }
+ break;
+ }
+
+ /* free the old buffer */
+ if (gps->points) {
+ MEM_freeN(gps->points);
+ }
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
+
+ /* save the new buffer */
+ gps->points = new_points;
+ gps->dvert = new_dvert;
+ gps->totpoints = tot;
+
+ /* triangles cache needs to be recalculated */
+ gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gps->tot_triangles = 0;
+
+ /* deselect the stroke, since none of its selected points will still be selected */
+ gps->flag &= ~GP_STROKE_SELECT;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ }
+
+ changed = true;
+ }
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ 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;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
/* ----------------------------------- */
@@ -2039,94 +2044,93 @@ static int gp_dissolve_selected_points(bContext *C, eGP_DissolveMode mode)
* gp_stroke_delete_tagged_points()
*/
typedef struct tGPDeleteIsland {
- int start_idx;
- int end_idx;
+ int start_idx;
+ int end_idx;
} tGPDeleteIsland;
static void gp_stroke_join_islands(bGPDframe *gpf, bGPDstroke *gps_first, bGPDstroke *gps_last)
{
- bGPDspoint *pt = NULL;
- bGPDspoint *pt_final = NULL;
- const int totpoints = gps_first->totpoints + gps_last->totpoints;
-
- /* create new stroke */
- bGPDstroke *join_stroke = MEM_dupallocN(gps_first);
-
- join_stroke->points = MEM_callocN(sizeof(bGPDspoint) * totpoints, __func__);
- join_stroke->totpoints = totpoints;
- join_stroke->flag &= ~GP_STROKE_CYCLIC;
-
- /* copy points (last before) */
- int e1 = 0;
- int e2 = 0;
- float delta = 0.0f;
-
- for (int i = 0; i < totpoints; i++) {
- pt_final = &join_stroke->points[i];
- if (i < gps_last->totpoints) {
- pt = &gps_last->points[e1];
- e1++;
- }
- else {
- pt = &gps_first->points[e2];
- e2++;
- }
-
- /* copy current point */
- copy_v3_v3(&pt_final->x, &pt->x);
- pt_final->pressure = pt->pressure;
- pt_final->strength = pt->strength;
- pt_final->time = delta;
- pt_final->flag = pt->flag;
-
- /* retiming with fixed time interval (we cannot determine real time) */
- delta += 0.01f;
- }
-
- /* Copy over vertex weight data (if available) */
- if ((gps_first->dvert != NULL) || (gps_last->dvert != NULL)) {
- join_stroke->dvert = MEM_callocN(sizeof(MDeformVert) * totpoints, __func__);
- MDeformVert *dvert_src = NULL;
- MDeformVert *dvert_dst = NULL;
-
- /* Copy weights (last before)*/
- e1 = 0;
- e2 = 0;
- for (int i = 0; i < totpoints; i++) {
- dvert_dst = &join_stroke->dvert[i];
- dvert_src = NULL;
- if (i < gps_last->totpoints) {
- if (gps_last->dvert) {
- dvert_src = &gps_last->dvert[e1];
- e1++;
- }
- }
- else {
- if (gps_first->dvert) {
- dvert_src = &gps_first->dvert[e2];
- e2++;
- }
- }
-
- if ((dvert_src) && (dvert_src->dw)) {
- dvert_dst->dw = MEM_dupallocN(dvert_src->dw);
- }
- }
- }
-
- /* add new stroke at head */
- BLI_addhead(&gpf->strokes, join_stroke);
-
- /* remove first stroke */
- BLI_remlink(&gpf->strokes, gps_first);
- BKE_gpencil_free_stroke(gps_first);
-
- /* remove last stroke */
- BLI_remlink(&gpf->strokes, gps_last);
- BKE_gpencil_free_stroke(gps_last);
+ bGPDspoint *pt = NULL;
+ bGPDspoint *pt_final = NULL;
+ const int totpoints = gps_first->totpoints + gps_last->totpoints;
+
+ /* create new stroke */
+ bGPDstroke *join_stroke = MEM_dupallocN(gps_first);
+
+ join_stroke->points = MEM_callocN(sizeof(bGPDspoint) * totpoints, __func__);
+ join_stroke->totpoints = totpoints;
+ join_stroke->flag &= ~GP_STROKE_CYCLIC;
+
+ /* copy points (last before) */
+ int e1 = 0;
+ int e2 = 0;
+ float delta = 0.0f;
+
+ for (int i = 0; i < totpoints; i++) {
+ pt_final = &join_stroke->points[i];
+ if (i < gps_last->totpoints) {
+ pt = &gps_last->points[e1];
+ e1++;
+ }
+ else {
+ pt = &gps_first->points[e2];
+ e2++;
+ }
+
+ /* copy current point */
+ copy_v3_v3(&pt_final->x, &pt->x);
+ pt_final->pressure = pt->pressure;
+ pt_final->strength = pt->strength;
+ pt_final->time = delta;
+ pt_final->flag = pt->flag;
+
+ /* retiming with fixed time interval (we cannot determine real time) */
+ delta += 0.01f;
+ }
+
+ /* Copy over vertex weight data (if available) */
+ if ((gps_first->dvert != NULL) || (gps_last->dvert != NULL)) {
+ join_stroke->dvert = MEM_callocN(sizeof(MDeformVert) * totpoints, __func__);
+ MDeformVert *dvert_src = NULL;
+ MDeformVert *dvert_dst = NULL;
+
+ /* Copy weights (last before)*/
+ e1 = 0;
+ e2 = 0;
+ for (int i = 0; i < totpoints; i++) {
+ dvert_dst = &join_stroke->dvert[i];
+ dvert_src = NULL;
+ if (i < gps_last->totpoints) {
+ if (gps_last->dvert) {
+ dvert_src = &gps_last->dvert[e1];
+ e1++;
+ }
+ }
+ else {
+ if (gps_first->dvert) {
+ dvert_src = &gps_first->dvert[e2];
+ e2++;
+ }
+ }
+
+ if ((dvert_src) && (dvert_src->dw)) {
+ dvert_dst->dw = MEM_dupallocN(dvert_src->dw);
+ }
+ }
+ }
+
+ /* add new stroke at head */
+ BLI_addhead(&gpf->strokes, join_stroke);
+
+ /* remove first stroke */
+ BLI_remlink(&gpf->strokes, gps_first);
+ BKE_gpencil_free_stroke(gps_first);
+
+ /* remove last stroke */
+ BLI_remlink(&gpf->strokes, gps_last);
+ BKE_gpencil_free_stroke(gps_last);
}
-
/* Split the given stroke into several new strokes, partitioning
* it based on whether the stroke points have a particular flag
* is set (e.g. "GP_SPOINT_SELECT" in most cases, but not always)
@@ -2141,290 +2145,315 @@ static void gp_stroke_join_islands(bGPDframe *gpf, bGPDstroke *gps_first, bGPDst
* 2) Each island gets converted to a new stroke
* If the number of points is <= limit, the stroke is deleted
*/
-void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke *next_stroke,
- int tag_flags, bool select, int limit)
+void gp_stroke_delete_tagged_points(bGPDframe *gpf,
+ bGPDstroke *gps,
+ bGPDstroke *next_stroke,
+ int tag_flags,
+ bool select,
+ int limit)
{
- tGPDeleteIsland *islands = MEM_callocN(sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2, "gp_point_islands");
- bool in_island = false;
- int num_islands = 0;
-
- bGPDstroke *gps_first = NULL;
- const bool is_cyclic = (bool)(gps->flag & GP_STROKE_CYCLIC);
-
- /* First Pass: Identify start/end of islands */
- bGPDspoint *pt = gps->points;
- for (int i = 0; i < gps->totpoints; i++, pt++) {
- if (pt->flag & tag_flags) {
- /* selected - stop accumulating to island */
- in_island = false;
- }
- else {
- /* unselected - start of a new island? */
- int idx;
-
- if (in_island) {
- /* extend existing island */
- idx = num_islands - 1;
- islands[idx].end_idx = i;
- }
- else {
- /* start of new island */
- in_island = true;
- num_islands++;
-
- idx = num_islands - 1;
- islands[idx].start_idx = islands[idx].end_idx = i;
- }
- }
- }
-
- /* Watch out for special case where No islands = All points selected = Delete Stroke only */
- if (num_islands) {
- /* there are islands, so create a series of new strokes, adding them before the "next" stroke */
- int idx;
- bGPDstroke *new_stroke = NULL;
-
- /* Create each new stroke... */
- for (idx = 0; idx < num_islands; idx++) {
- tGPDeleteIsland *island = &islands[idx];
- new_stroke = MEM_dupallocN(gps);
-
- /* 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;
-
- /* Copy over the relevant point data */
- new_stroke->points = MEM_callocN(sizeof(bGPDspoint) * new_stroke->totpoints, "gp delete stroke fragment");
- memcpy(new_stroke->points, gps->points + island->start_idx, sizeof(bGPDspoint) * new_stroke->totpoints);
-
- /* Copy over vertex weight data (if available) */
- if (gps->dvert != NULL) {
- /* Copy over the relevant vertex-weight points */
- new_stroke->dvert = MEM_callocN(sizeof(MDeformVert) * new_stroke->totpoints, "gp delete stroke fragment weight");
- memcpy(new_stroke->dvert, gps->dvert + island->start_idx, sizeof(MDeformVert) * new_stroke->totpoints);
-
- /* Copy weights */
- int e = island->start_idx;
- for (int i = 0; i < new_stroke->totpoints; i++) {
- MDeformVert *dvert_src = &gps->dvert[e];
- MDeformVert *dvert_dst = &new_stroke->dvert[i];
- if (dvert_src->dw) {
- dvert_dst->dw = MEM_dupallocN(dvert_src->dw);
- }
- e++;
- }
- }
- /* Each island corresponds to a new stroke. We must adjust the
- * timings of these new strokes:
- *
- * Each point's timing data is a delta from stroke's inittime, so as we erase some points from
- * the start of the stroke, we have to offset this inittime and all remaining points' delta values.
- * This way we get a new stroke with exactly the same timing as if user had started drawing from
- * the first non-removed point...
- */
- {
- bGPDspoint *pts;
- float delta = gps->points[island->start_idx].time;
- int j;
-
- new_stroke->inittime += (double)delta;
-
- pts = new_stroke->points;
- for (j = 0; j < new_stroke->totpoints; j++, pts++) {
- pts->time -= delta;
- /* set flag for select again later */
- if (select == true) {
- pts->flag &= ~GP_SPOINT_SELECT;
- pts->flag |= GP_SPOINT_TAG;
- }
- }
- }
-
- /* Add new stroke to the frame or delete if below limit */
- if ((limit > 0) && (new_stroke->totpoints <= limit)) {
- BKE_gpencil_free_stroke(new_stroke);
- }
- else {
- if (next_stroke) {
- BLI_insertlinkbefore(&gpf->strokes, next_stroke, new_stroke);
- }
- else {
- BLI_addtail(&gpf->strokes, new_stroke);
- }
- }
- }
- /* if cyclic, need to join last stroke with first stroke */
- if ((is_cyclic) && (gps_first != NULL) && (gps_first != new_stroke)) {
- gp_stroke_join_islands(gpf, gps_first, new_stroke);
- }
-
- }
-
- /* free islands */
- MEM_freeN(islands);
-
- /* Delete the old stroke */
- BLI_remlink(&gpf->strokes, gps);
- BKE_gpencil_free_stroke(gps);
+ tGPDeleteIsland *islands = MEM_callocN(sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2,
+ "gp_point_islands");
+ bool in_island = false;
+ int num_islands = 0;
+
+ bGPDstroke *gps_first = NULL;
+ const bool is_cyclic = (bool)(gps->flag & GP_STROKE_CYCLIC);
+
+ /* First Pass: Identify start/end of islands */
+ bGPDspoint *pt = gps->points;
+ for (int i = 0; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & tag_flags) {
+ /* selected - stop accumulating to island */
+ in_island = false;
+ }
+ else {
+ /* unselected - start of a new island? */
+ int idx;
+
+ if (in_island) {
+ /* extend existing island */
+ idx = num_islands - 1;
+ islands[idx].end_idx = i;
+ }
+ else {
+ /* start of new island */
+ in_island = true;
+ num_islands++;
+
+ idx = num_islands - 1;
+ islands[idx].start_idx = islands[idx].end_idx = i;
+ }
+ }
+ }
+
+ /* Watch out for special case where No islands = All points selected = Delete Stroke only */
+ if (num_islands) {
+ /* there are islands, so create a series of new strokes, adding them before the "next" stroke */
+ int idx;
+ bGPDstroke *new_stroke = NULL;
+
+ /* Create each new stroke... */
+ for (idx = 0; idx < num_islands; idx++) {
+ tGPDeleteIsland *island = &islands[idx];
+ new_stroke = MEM_dupallocN(gps);
+
+ /* 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;
+
+ /* Copy over the relevant point data */
+ new_stroke->points = MEM_callocN(sizeof(bGPDspoint) * new_stroke->totpoints,
+ "gp delete stroke fragment");
+ memcpy(new_stroke->points,
+ gps->points + island->start_idx,
+ sizeof(bGPDspoint) * new_stroke->totpoints);
+
+ /* Copy over vertex weight data (if available) */
+ if (gps->dvert != NULL) {
+ /* Copy over the relevant vertex-weight points */
+ new_stroke->dvert = MEM_callocN(sizeof(MDeformVert) * new_stroke->totpoints,
+ "gp delete stroke fragment weight");
+ memcpy(new_stroke->dvert,
+ gps->dvert + island->start_idx,
+ sizeof(MDeformVert) * new_stroke->totpoints);
+
+ /* Copy weights */
+ int e = island->start_idx;
+ for (int i = 0; i < new_stroke->totpoints; i++) {
+ MDeformVert *dvert_src = &gps->dvert[e];
+ MDeformVert *dvert_dst = &new_stroke->dvert[i];
+ if (dvert_src->dw) {
+ dvert_dst->dw = MEM_dupallocN(dvert_src->dw);
+ }
+ e++;
+ }
+ }
+ /* Each island corresponds to a new stroke. We must adjust the
+ * timings of these new strokes:
+ *
+ * Each point's timing data is a delta from stroke's inittime, so as we erase some points from
+ * the start of the stroke, we have to offset this inittime and all remaining points' delta values.
+ * This way we get a new stroke with exactly the same timing as if user had started drawing from
+ * the first non-removed point...
+ */
+ {
+ bGPDspoint *pts;
+ float delta = gps->points[island->start_idx].time;
+ int j;
+
+ new_stroke->inittime += (double)delta;
+
+ pts = new_stroke->points;
+ for (j = 0; j < new_stroke->totpoints; j++, pts++) {
+ pts->time -= delta;
+ /* set flag for select again later */
+ if (select == true) {
+ pts->flag &= ~GP_SPOINT_SELECT;
+ pts->flag |= GP_SPOINT_TAG;
+ }
+ }
+ }
+
+ /* Add new stroke to the frame or delete if below limit */
+ if ((limit > 0) && (new_stroke->totpoints <= limit)) {
+ BKE_gpencil_free_stroke(new_stroke);
+ }
+ else {
+ if (next_stroke) {
+ BLI_insertlinkbefore(&gpf->strokes, next_stroke, new_stroke);
+ }
+ else {
+ BLI_addtail(&gpf->strokes, new_stroke);
+ }
+ }
+ }
+ /* if cyclic, need to join last stroke with first stroke */
+ if ((is_cyclic) && (gps_first != NULL) && (gps_first != new_stroke)) {
+ gp_stroke_join_islands(gpf, gps_first, new_stroke);
+ }
+ }
+
+ /* free islands */
+ MEM_freeN(islands);
+
+ /* Delete the old stroke */
+ BLI_remlink(&gpf->strokes, gps);
+ BKE_gpencil_free_stroke(gps);
}
/* Split selected strokes into segments, splitting on selected points */
static int gp_delete_selected_points(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- bool changed = false;
-
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- 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))) {
- bGPDstroke *gps, *gpsn;
-
- if (gpf == NULL)
- continue;
-
- /* simply delete strokes which are selected */
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
-
- /* 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;
-
-
- if (gps->flag & GP_STROKE_SELECT) {
- /* deselect old stroke, since it will be used as template for the new strokes */
- 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);
-
- changed = true;
- }
- }
- }
- }
- }
- CTX_DATA_END;
-
- 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;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ 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))) {
+ bGPDstroke *gps, *gpsn;
+
+ if (gpf == NULL)
+ continue;
+
+ /* simply delete strokes which are selected */
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ /* 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;
+
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* deselect old stroke, since it will be used as template for the new strokes */
+ 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);
+
+ changed = true;
+ }
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ 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;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
/* simple wrapper to external call */
int gp_delete_selected_point_wrap(bContext *C)
{
- return gp_delete_selected_points(C);
+ return gp_delete_selected_points(C);
}
/* ----------------------------------- */
static int gp_delete_exec(bContext *C, wmOperator *op)
{
- eGP_DeleteMode mode = RNA_enum_get(op->ptr, "type");
- int result = OPERATOR_CANCELLED;
+ eGP_DeleteMode mode = RNA_enum_get(op->ptr, "type");
+ int result = OPERATOR_CANCELLED;
- switch (mode) {
- case GP_DELETEOP_STROKES: /* selected strokes */
- result = gp_delete_selected_strokes(C);
- break;
+ switch (mode) {
+ case GP_DELETEOP_STROKES: /* selected strokes */
+ result = gp_delete_selected_strokes(C);
+ break;
- case GP_DELETEOP_POINTS: /* selected points (breaks the stroke into segments) */
- result = gp_delete_selected_points(C);
- break;
+ case GP_DELETEOP_POINTS: /* selected points (breaks the stroke into segments) */
+ result = gp_delete_selected_points(C);
+ break;
- case GP_DELETEOP_FRAME: /* active frame */
- result = gp_actframe_delete_exec(C, op);
- break;
- }
+ case GP_DELETEOP_FRAME: /* active frame */
+ result = gp_actframe_delete_exec(C, op);
+ break;
+ }
- return result;
+ return result;
}
void GPENCIL_OT_delete(wmOperatorType *ot)
{
- static const EnumPropertyItem prop_gpencil_delete_types[] = {
- {GP_DELETEOP_POINTS, "POINTS", 0, "Points", "Delete selected points and split strokes into segments"},
- {GP_DELETEOP_STROKES, "STROKES", 0, "Strokes", "Delete selected strokes"},
- {GP_DELETEOP_FRAME, "FRAME", 0, "Frame", "Delete active frame"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Delete";
- ot->idname = "GPENCIL_OT_delete";
- ot->description = "Delete selected Grease Pencil strokes, vertices, or frames";
-
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = gp_delete_exec;
- ot->poll = gp_stroke_edit_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
-
- /* props */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_delete_types, 0, "Type", "Method used for deleting Grease Pencil data");
+ static const EnumPropertyItem prop_gpencil_delete_types[] = {
+ {GP_DELETEOP_POINTS,
+ "POINTS",
+ 0,
+ "Points",
+ "Delete selected points and split strokes into segments"},
+ {GP_DELETEOP_STROKES, "STROKES", 0, "Strokes", "Delete selected strokes"},
+ {GP_DELETEOP_FRAME, "FRAME", 0, "Frame", "Delete active frame"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Delete";
+ ot->idname = "GPENCIL_OT_delete";
+ ot->description = "Delete selected Grease Pencil strokes, vertices, or frames";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = gp_delete_exec;
+ ot->poll = gp_stroke_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+
+ /* props */
+ ot->prop = RNA_def_enum(ot->srna,
+ "type",
+ prop_gpencil_delete_types,
+ 0,
+ "Type",
+ "Method used for deleting Grease Pencil data");
}
static int gp_dissolve_exec(bContext *C, wmOperator *op)
{
- eGP_DissolveMode mode = RNA_enum_get(op->ptr, "type");
+ eGP_DissolveMode mode = RNA_enum_get(op->ptr, "type");
- return gp_dissolve_selected_points(C, mode);
+ return gp_dissolve_selected_points(C, mode);
}
void GPENCIL_OT_dissolve(wmOperatorType *ot)
{
- static EnumPropertyItem prop_gpencil_dissolve_types[] = {
- {GP_DISSOLVE_POINTS, "POINTS", 0, "Dissolve", "Dissolve selected points"},
- {GP_DISSOLVE_BETWEEN, "BETWEEN", 0, "Dissolve Between", "Dissolve points between selected points"},
- {GP_DISSOLVE_UNSELECT, "UNSELECT", 0, "Dissolve Unselect", "Dissolve all unselected points"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Dissolve";
- ot->idname = "GPENCIL_OT_dissolve";
- ot->description = "Delete selected points without splitting strokes";
-
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = gp_dissolve_exec;
- ot->poll = gp_stroke_edit_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
-
- /* props */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_dissolve_types, 0,
- "Type", "Method used for dissolving Stroke points");
+ static EnumPropertyItem prop_gpencil_dissolve_types[] = {
+ {GP_DISSOLVE_POINTS, "POINTS", 0, "Dissolve", "Dissolve selected points"},
+ {GP_DISSOLVE_BETWEEN,
+ "BETWEEN",
+ 0,
+ "Dissolve Between",
+ "Dissolve points between selected points"},
+ {GP_DISSOLVE_UNSELECT, "UNSELECT", 0, "Dissolve Unselect", "Dissolve all unselected points"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Dissolve";
+ ot->idname = "GPENCIL_OT_dissolve";
+ ot->description = "Delete selected points without splitting strokes";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = gp_dissolve_exec;
+ ot->poll = gp_stroke_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+
+ /* props */
+ ot->prop = RNA_def_enum(ot->srna,
+ "type",
+ prop_gpencil_dissolve_types,
+ 0,
+ "Type",
+ "Method used for dissolving Stroke points");
}
/* ****************** Snapping - Strokes <-> Cursor ************************ */
@@ -2435,370 +2464,369 @@ 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);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ ScrArea *sa = CTX_wm_area(C);
- return (gpd != NULL) && ((sa != NULL) && (sa->spacetype == SPACE_VIEW3D));
+ return (gpd != NULL) && ((sa != NULL) && (sa->spacetype == SPACE_VIEW3D));
}
/* --------------------------------- */
static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op))
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- RegionView3D *rv3d = CTX_wm_region_data(C);
- View3D *v3d = CTX_wm_view3d(C);
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- 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) {
- /* only editable and visible layers are considered */
- if (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);
-
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- bGPDspoint *pt;
- int i;
-
- /* 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(obact, gpl, gps) == false)
- continue;
-
- // TODO: if entire stroke is selected, offset entire stroke by same amount?
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- /* only if point is selected */
- if (pt->flag & GP_SPOINT_SELECT) {
- /* apply parent transformations */
- float fpt[3];
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
-
- fpt[0] = gridf * floorf(0.5f + fpt[0] / gridf);
- fpt[1] = gridf * floorf(0.5f + fpt[1] / gridf);
- fpt[2] = gridf * floorf(0.5f + fpt[2] / gridf);
-
- /* return data */
- copy_v3_v3(&pt->x, fpt);
- gp_apply_parent_point(depsgraph, obact, gpd, gpl, pt);
- }
- }
- }
- }
- }
-
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- DEG_id_tag_update(&obact->id, ID_RECALC_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ RegionView3D *rv3d = CTX_wm_region_data(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ 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) {
+ /* only editable and visible layers are considered */
+ if (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);
+
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ bGPDspoint *pt;
+ int i;
+
+ /* 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(obact, gpl, gps) == false)
+ continue;
+
+ // TODO: if entire stroke is selected, offset entire stroke by same amount?
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ /* only if point is selected */
+ if (pt->flag & GP_SPOINT_SELECT) {
+ /* apply parent transformations */
+ float fpt[3];
+ mul_v3_m4v3(fpt, diff_mat, &pt->x);
+
+ fpt[0] = gridf * floorf(0.5f + fpt[0] / gridf);
+ fpt[1] = gridf * floorf(0.5f + fpt[1] / gridf);
+ fpt[2] = gridf * floorf(0.5f + fpt[2] / gridf);
+
+ /* return data */
+ copy_v3_v3(&pt->x, fpt);
+ gp_apply_parent_point(depsgraph, obact, gpd, gpl, pt);
+ }
+ }
+ }
+ }
+ }
+
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(&obact->id, ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_snap_to_grid(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Snap Selection to Grid";
- ot->idname = "GPENCIL_OT_snap_to_grid";
- ot->description = "Snap selected points to the nearest grid points";
+ /* identifiers */
+ ot->name = "Snap Selection to Grid";
+ ot->idname = "GPENCIL_OT_snap_to_grid";
+ ot->description = "Snap selected points to the nearest grid points";
- /* callbacks */
- ot->exec = gp_snap_to_grid;
- ot->poll = gp_snap_poll;
+ /* callbacks */
+ ot->exec = gp_snap_to_grid;
+ ot->poll = gp_snap_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ------------------------------- */
static int gp_snap_to_cursor(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
-
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *obact = CTX_data_active_object(C);
-
- 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) {
- /* only editable and visible layers are considered */
- if (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);
-
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- bGPDspoint *pt;
- int i;
-
- /* 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(obact, gpl, gps) == false)
- continue;
- /* only continue if this stroke is selected (editable doesn't guarantee this)... */
- if ((gps->flag & GP_STROKE_SELECT) == 0)
- continue;
-
- if (use_offset) {
- float offset[3];
-
- /* compute offset from first point of stroke to cursor */
- /* TODO: Allow using midpoint instead? */
- sub_v3_v3v3(offset, cursor_global, &gps->points->x);
-
- /* apply offset to all points in the stroke */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- add_v3_v3(&pt->x, offset);
- }
- }
- else {
- /* affect each selected point */
- 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);
- }
- }
- }
- }
-
- }
- }
-
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- DEG_id_tag_update(&obact->id, ID_RECALC_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *obact = CTX_data_active_object(C);
+
+ 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) {
+ /* only editable and visible layers are considered */
+ if (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);
+
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ bGPDspoint *pt;
+ int i;
+
+ /* 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(obact, gpl, gps) == false)
+ continue;
+ /* only continue if this stroke is selected (editable doesn't guarantee this)... */
+ if ((gps->flag & GP_STROKE_SELECT) == 0)
+ continue;
+
+ if (use_offset) {
+ float offset[3];
+
+ /* compute offset from first point of stroke to cursor */
+ /* TODO: Allow using midpoint instead? */
+ sub_v3_v3v3(offset, cursor_global, &gps->points->x);
+
+ /* apply offset to all points in the stroke */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ add_v3_v3(&pt->x, offset);
+ }
+ }
+ else {
+ /* affect each selected point */
+ 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);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(&obact->id, ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_snap_to_cursor(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Snap Selection to Cursor";
- ot->idname = "GPENCIL_OT_snap_to_cursor";
- ot->description = "Snap selected points/strokes to the cursor";
-
- /* callbacks */
- ot->exec = gp_snap_to_cursor;
- ot->poll = gp_snap_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- ot->prop = RNA_def_boolean(
- ot->srna, "use_offset", true, "With Offset",
- "Offset the entire stroke instead of selected points only");
+ /* identifiers */
+ ot->name = "Snap Selection to Cursor";
+ ot->idname = "GPENCIL_OT_snap_to_cursor";
+ ot->description = "Snap selected points/strokes to the cursor";
+
+ /* callbacks */
+ ot->exec = gp_snap_to_cursor;
+ ot->poll = gp_snap_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ ot->prop = RNA_def_boolean(ot->srna,
+ "use_offset",
+ true,
+ "With Offset",
+ "Offset the entire stroke instead of selected points only");
}
/* ------------------------------- */
static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op))
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
-
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *obact = CTX_data_active_object(C);
-
- float *cursor = scene->cursor.location;
- float centroid[3] = {0.0f};
- float min[3], max[3];
- size_t count = 0;
-
- INIT_MINMAX(min, max);
-
- /* calculate midpoints from selected points */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* only editable and visible layers are considered */
- if (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);
-
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- bGPDspoint *pt;
- int i;
-
- /* 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(obact, gpl, gps) == false)
- continue;
- /* only continue if this stroke is selected (editable doesn't guarantee this)... */
- if ((gps->flag & GP_STROKE_SELECT) == 0)
- continue;
-
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT) {
- /* apply parent transformations */
- float fpt[3];
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
-
- add_v3_v3(centroid, fpt);
- minmax_v3v3_v3(min, max, fpt);
-
- count++;
- }
- }
-
- }
- }
- }
-
- if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEDIAN && count) {
- mul_v3_fl(centroid, 1.0f / (float)count);
- copy_v3_v3(cursor, centroid);
- }
- else {
- mid_v3_v3v3(cursor, min, max);
- }
-
-
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
-
- return OPERATOR_FINISHED;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *obact = CTX_data_active_object(C);
+
+ float *cursor = scene->cursor.location;
+ float centroid[3] = {0.0f};
+ float min[3], max[3];
+ size_t count = 0;
+
+ INIT_MINMAX(min, max);
+
+ /* calculate midpoints from selected points */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* only editable and visible layers are considered */
+ if (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);
+
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ bGPDspoint *pt;
+ int i;
+
+ /* 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(obact, gpl, gps) == false)
+ continue;
+ /* only continue if this stroke is selected (editable doesn't guarantee this)... */
+ if ((gps->flag & GP_STROKE_SELECT) == 0)
+ continue;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ /* apply parent transformations */
+ float fpt[3];
+ mul_v3_m4v3(fpt, diff_mat, &pt->x);
+
+ add_v3_v3(centroid, fpt);
+ minmax_v3v3_v3(min, max, fpt);
+
+ count++;
+ }
+ }
+ }
+ }
+ }
+
+ if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEDIAN && count) {
+ mul_v3_fl(centroid, 1.0f / (float)count);
+ copy_v3_v3(cursor, centroid);
+ }
+ else {
+ mid_v3_v3v3(cursor, min, max);
+ }
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_snap_cursor_to_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Snap Cursor to Selected Points";
- ot->idname = "GPENCIL_OT_snap_cursor_to_selected";
- ot->description = "Snap cursor to center of selected points";
+ /* identifiers */
+ ot->name = "Snap Cursor to Selected Points";
+ ot->idname = "GPENCIL_OT_snap_cursor_to_selected";
+ ot->description = "Snap cursor to center of selected points";
- /* callbacks */
- ot->exec = gp_snap_cursor_to_sel;
- ot->poll = gp_snap_poll;
+ /* callbacks */
+ ot->exec = gp_snap_cursor_to_sel;
+ ot->poll = gp_snap_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************* Apply layer thickness change to strokes ************************** */
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);
-
- /* sanity checks */
- if (ELEM(NULL, gpd, gpl, gpl->frames.first))
- return OPERATOR_CANCELLED;
-
- /* loop all strokes */
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- /* Apply thickness */
- if ((gps->thickness == 0) && (gpl->line_change == 0)) {
- gps->thickness = gpl->thickness;
- }
- else {
- gps->thickness = gps->thickness + gpl->line_change;
- }
- }
- }
- /* clear value */
- gpl->thickness = 0.0f;
- gpl->line_change = 0;
-
- /* 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;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd, gpl, gpl->frames.first))
+ return OPERATOR_CANCELLED;
+
+ /* loop all strokes */
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* Apply thickness */
+ if ((gps->thickness == 0) && (gpl->line_change == 0)) {
+ gps->thickness = gpl->thickness;
+ }
+ else {
+ gps->thickness = gps->thickness + gpl->line_change;
+ }
+ }
+ }
+ /* clear value */
+ gpl->thickness = 0.0f;
+ gpl->line_change = 0;
+
+ /* 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_stroke_apply_thickness(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Apply Stroke Thickness";
- ot->idname = "GPENCIL_OT_stroke_apply_thickness";
- ot->description = "Apply the thickness change of the layer to its strokes";
-
- /* api callbacks */
- ot->exec = gp_stroke_apply_thickness_exec;
- ot->poll = gp_active_layer_poll;
+ /* identifiers */
+ ot->name = "Apply Stroke Thickness";
+ ot->idname = "GPENCIL_OT_stroke_apply_thickness";
+ ot->description = "Apply the thickness change of the layer to its strokes";
+
+ /* api callbacks */
+ ot->exec = gp_stroke_apply_thickness_exec;
+ ot->poll = gp_active_layer_poll;
}
/* ******************* Close Strokes ************************** */
enum {
- GP_STROKE_CYCLIC_CLOSE = 1,
- GP_STROKE_CYCLIC_OPEN = 2,
- GP_STROKE_CYCLIC_TOGGLE = 3,
+ GP_STROKE_CYCLIC_CLOSE = 1,
+ GP_STROKE_CYCLIC_OPEN = 2,
+ GP_STROKE_CYCLIC_TOGGLE = 3,
};
static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- Object *ob = CTX_data_active_object(C);
-
- const int type = RNA_enum_get(op->ptr, "type");
-
- /* sanity checks */
- if (ELEM(NULL, gpd))
- return OPERATOR_CANCELLED;
-
- /* loop all selected strokes */
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- if (gpl->actframe == NULL)
- continue;
-
- for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
- MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
-
- /* skip strokes that are not selected or invalid for current view */
- if (((gps->flag & GP_STROKE_SELECT) == 0) || ED_gpencil_stroke_can_use(C, gps) == false)
- continue;
- /* skip hidden or locked colors */
- if (!gp_style || (gp_style->flag & GP_STYLE_COLOR_HIDE) || (gp_style->flag & GP_STYLE_COLOR_LOCKED))
- continue;
-
- switch (type) {
- case GP_STROKE_CYCLIC_CLOSE:
- /* Close all (enable) */
- gps->flag |= GP_STROKE_CYCLIC;
- break;
- case GP_STROKE_CYCLIC_OPEN:
- /* Open all (disable) */
- gps->flag &= ~GP_STROKE_CYCLIC;
- break;
- case GP_STROKE_CYCLIC_TOGGLE:
- /* Just toggle flag... */
- gps->flag ^= GP_STROKE_CYCLIC;
- break;
- default:
- BLI_assert(0);
- break;
- }
- }
- }
- CTX_DATA_END;
-
- /* 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;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ Object *ob = CTX_data_active_object(C);
+
+ const int type = RNA_enum_get(op->ptr, "type");
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd))
+ return OPERATOR_CANCELLED;
+
+ /* loop all selected strokes */
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ if (gpl->actframe == NULL)
+ continue;
+
+ for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+
+ /* skip strokes that are not selected or invalid for current view */
+ if (((gps->flag & GP_STROKE_SELECT) == 0) || ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+ /* skip hidden or locked colors */
+ if (!gp_style || (gp_style->flag & GP_STYLE_COLOR_HIDE) ||
+ (gp_style->flag & GP_STYLE_COLOR_LOCKED))
+ continue;
+
+ switch (type) {
+ case GP_STROKE_CYCLIC_CLOSE:
+ /* Close all (enable) */
+ gps->flag |= GP_STROKE_CYCLIC;
+ break;
+ case GP_STROKE_CYCLIC_OPEN:
+ /* Open all (disable) */
+ gps->flag &= ~GP_STROKE_CYCLIC;
+ break;
+ case GP_STROKE_CYCLIC_TOGGLE:
+ /* Just toggle flag... */
+ gps->flag ^= GP_STROKE_CYCLIC;
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* 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;
}
/**
@@ -2807,101 +2835,92 @@ static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op)
*/
void GPENCIL_OT_stroke_cyclical_set(wmOperatorType *ot)
{
- static const EnumPropertyItem cyclic_type[] = {
- {GP_STROKE_CYCLIC_CLOSE, "CLOSE", 0, "Close all", ""},
- {GP_STROKE_CYCLIC_OPEN, "OPEN", 0, "Open all", ""},
- {GP_STROKE_CYCLIC_TOGGLE, "TOGGLE", 0, "Toggle", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Set Cyclical State";
- ot->idname = "GPENCIL_OT_stroke_cyclical_set";
- ot->description = "Close or open the selected stroke adding an edge from last to first point";
-
- /* api callbacks */
- ot->exec = gp_stroke_cyclical_set_exec;
- ot->poll = gp_active_layer_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", cyclic_type, GP_STROKE_CYCLIC_TOGGLE, "Type", "");
+ static const EnumPropertyItem cyclic_type[] = {
+ {GP_STROKE_CYCLIC_CLOSE, "CLOSE", 0, "Close all", ""},
+ {GP_STROKE_CYCLIC_OPEN, "OPEN", 0, "Open all", ""},
+ {GP_STROKE_CYCLIC_TOGGLE, "TOGGLE", 0, "Toggle", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Set Cyclical State";
+ ot->idname = "GPENCIL_OT_stroke_cyclical_set";
+ ot->description = "Close or open the selected stroke adding an edge from last to first point";
+
+ /* api callbacks */
+ ot->exec = gp_stroke_cyclical_set_exec;
+ ot->poll = gp_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", cyclic_type, GP_STROKE_CYCLIC_TOGGLE, "Type", "");
}
/* ******************* Flat Stroke Caps ************************** */
enum {
- GP_STROKE_CAPS_TOGGLE_BOTH = 0,
- GP_STROKE_CAPS_TOGGLE_START = 1,
- GP_STROKE_CAPS_TOGGLE_END = 2,
- GP_STROKE_CAPS_TOGGLE_DEFAULT = 3,
+ GP_STROKE_CAPS_TOGGLE_BOTH = 0,
+ GP_STROKE_CAPS_TOGGLE_START = 1,
+ GP_STROKE_CAPS_TOGGLE_END = 2,
+ GP_STROKE_CAPS_TOGGLE_DEFAULT = 3,
};
static int gp_stroke_caps_set_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- Object *ob = CTX_data_active_object(C);
-
- const int type = RNA_enum_get(op->ptr, "type");
-
- /* sanity checks */
- if (ELEM(NULL, gpd))
- return OPERATOR_CANCELLED;
-
- /* loop all selected strokes */
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- if (gpl->actframe == NULL)
- continue;
-
- for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
- MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
-
- /* skip strokes that are not selected or invalid for current view */
- if (((gps->flag & GP_STROKE_SELECT) == 0) ||
- (ED_gpencil_stroke_can_use(C, gps) == false))
- {
- continue;
- }
- /* skip hidden or locked colors */
- if (!gp_style ||
- (gp_style->flag & GP_STYLE_COLOR_HIDE) ||
- (gp_style->flag & GP_STYLE_COLOR_LOCKED))
- {
- continue;
- }
-
- if ((type == GP_STROKE_CAPS_TOGGLE_BOTH) ||
- (type == GP_STROKE_CAPS_TOGGLE_START))
- {
- ++gps->caps[0];
- if (gps->caps[0] >= GP_STROKE_CAP_MAX) {
- gps->caps[0] = GP_STROKE_CAP_ROUND;
- }
- }
- if ((type == GP_STROKE_CAPS_TOGGLE_BOTH) ||
- (type == GP_STROKE_CAPS_TOGGLE_END))
- {
- ++gps->caps[1];
- if (gps->caps[1] >= GP_STROKE_CAP_MAX) {
- gps->caps[1] = GP_STROKE_CAP_ROUND;
- }
- }
- if (type == GP_STROKE_CAPS_TOGGLE_DEFAULT) {
- gps->caps[0] = GP_STROKE_CAP_ROUND;
- gps->caps[1] = GP_STROKE_CAP_ROUND;
- }
- }
- }
- CTX_DATA_END;
-
- /* 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;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ Object *ob = CTX_data_active_object(C);
+
+ const int type = RNA_enum_get(op->ptr, "type");
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd))
+ return OPERATOR_CANCELLED;
+
+ /* loop all selected strokes */
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ if (gpl->actframe == NULL)
+ continue;
+
+ for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+
+ /* skip strokes that are not selected or invalid for current view */
+ if (((gps->flag & GP_STROKE_SELECT) == 0) || (ED_gpencil_stroke_can_use(C, gps) == false)) {
+ continue;
+ }
+ /* skip hidden or locked colors */
+ if (!gp_style || (gp_style->flag & GP_STYLE_COLOR_HIDE) ||
+ (gp_style->flag & GP_STYLE_COLOR_LOCKED)) {
+ continue;
+ }
+
+ if ((type == GP_STROKE_CAPS_TOGGLE_BOTH) || (type == GP_STROKE_CAPS_TOGGLE_START)) {
+ ++gps->caps[0];
+ if (gps->caps[0] >= GP_STROKE_CAP_MAX) {
+ gps->caps[0] = GP_STROKE_CAP_ROUND;
+ }
+ }
+ if ((type == GP_STROKE_CAPS_TOGGLE_BOTH) || (type == GP_STROKE_CAPS_TOGGLE_END)) {
+ ++gps->caps[1];
+ if (gps->caps[1] >= GP_STROKE_CAP_MAX) {
+ gps->caps[1] = GP_STROKE_CAP_ROUND;
+ }
+ }
+ if (type == GP_STROKE_CAPS_TOGGLE_DEFAULT) {
+ gps->caps[0] = GP_STROKE_CAP_ROUND;
+ gps->caps[1] = GP_STROKE_CAP_ROUND;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* 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;
}
/**
@@ -2909,28 +2928,28 @@ static int gp_stroke_caps_set_exec(bContext *C, wmOperator *op)
*/
void GPENCIL_OT_stroke_caps_set(wmOperatorType *ot)
{
- static const EnumPropertyItem toggle_type[] = {
- {GP_STROKE_CAPS_TOGGLE_BOTH, "TOGGLE", 0, "Both", ""},
- {GP_STROKE_CAPS_TOGGLE_START, "START", 0, "Start", ""},
- {GP_STROKE_CAPS_TOGGLE_END, "END", 0, "End", ""},
- {GP_STROKE_CAPS_TOGGLE_DEFAULT, "TOGGLE", 0, "Default", "Set as default rounded"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Set Caps Mode";
- ot->idname = "GPENCIL_OT_stroke_caps_set";
- ot->description = "Change Stroke caps mode (rounded or flat)";
-
- /* api callbacks */
- ot->exec = gp_stroke_caps_set_exec;
- ot->poll = gp_active_layer_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", toggle_type, GP_STROKE_CAPS_TOGGLE_BOTH, "Type", "");
+ static const EnumPropertyItem toggle_type[] = {
+ {GP_STROKE_CAPS_TOGGLE_BOTH, "TOGGLE", 0, "Both", ""},
+ {GP_STROKE_CAPS_TOGGLE_START, "START", 0, "Start", ""},
+ {GP_STROKE_CAPS_TOGGLE_END, "END", 0, "End", ""},
+ {GP_STROKE_CAPS_TOGGLE_DEFAULT, "TOGGLE", 0, "Default", "Set as default rounded"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Set Caps Mode";
+ ot->idname = "GPENCIL_OT_stroke_caps_set";
+ ot->description = "Change Stroke caps mode (rounded or flat)";
+
+ /* api callbacks */
+ ot->exec = gp_stroke_caps_set_exec;
+ ot->poll = gp_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", toggle_type, GP_STROKE_CAPS_TOGGLE_BOTH, "Type", "");
}
/* ******************* Stroke join ************************** */
@@ -2938,1523 +2957,1524 @@ void GPENCIL_OT_stroke_caps_set(wmOperatorType *ot)
/* Helper: flip stroke */
static void gpencil_flip_stroke(bGPDstroke *gps)
{
- int end = gps->totpoints - 1;
-
- for (int i = 0; i < gps->totpoints / 2; i++) {
- bGPDspoint *point, *point2;
- bGPDspoint pt;
-
- /* save first point */
- point = &gps->points[i];
- pt.x = point->x;
- pt.y = point->y;
- pt.z = point->z;
- pt.flag = point->flag;
- pt.pressure = point->pressure;
- pt.strength = point->strength;
- pt.time = point->time;
-
- /* replace first point with last point */
- point2 = &gps->points[end];
- point->x = point2->x;
- point->y = point2->y;
- point->z = point2->z;
- point->flag = point2->flag;
- point->pressure = point2->pressure;
- point->strength = point2->strength;
- point->time = point2->time;
-
- /* replace last point with first saved before */
- point = &gps->points[end];
- point->x = pt.x;
- point->y = pt.y;
- point->z = pt.z;
- point->flag = pt.flag;
- point->pressure = pt.pressure;
- point->strength = pt.strength;
- point->time = pt.time;
-
- end--;
- }
+ int end = gps->totpoints - 1;
+
+ for (int i = 0; i < gps->totpoints / 2; i++) {
+ bGPDspoint *point, *point2;
+ bGPDspoint pt;
+
+ /* save first point */
+ point = &gps->points[i];
+ pt.x = point->x;
+ pt.y = point->y;
+ pt.z = point->z;
+ pt.flag = point->flag;
+ pt.pressure = point->pressure;
+ pt.strength = point->strength;
+ pt.time = point->time;
+
+ /* replace first point with last point */
+ point2 = &gps->points[end];
+ point->x = point2->x;
+ point->y = point2->y;
+ point->z = point2->z;
+ point->flag = point2->flag;
+ point->pressure = point2->pressure;
+ point->strength = point2->strength;
+ point->time = point2->time;
+
+ /* replace last point with first saved before */
+ point = &gps->points[end];
+ point->x = pt.x;
+ point->y = pt.y;
+ point->z = pt.z;
+ point->flag = pt.flag;
+ point->pressure = pt.pressure;
+ point->strength = pt.strength;
+ point->time = pt.time;
+
+ end--;
+ }
}
/* Helper: copy point between strokes */
-static void gpencil_stroke_copy_point(bGPDstroke *gps, bGPDspoint *point, int idx, float delta[3],
- float pressure, float strength, float deltatime)
+static void gpencil_stroke_copy_point(bGPDstroke *gps,
+ bGPDspoint *point,
+ int idx,
+ float delta[3],
+ float pressure,
+ float strength,
+ float deltatime)
{
- bGPDspoint *newpoint;
-
- 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++;
- newpoint = &gps->points[gps->totpoints - 1];
-
- newpoint->x = point->x * delta[0];
- newpoint->y = point->y * delta[1];
- newpoint->z = point->z * delta[2];
- newpoint->flag = point->flag;
- newpoint->pressure = pressure;
- newpoint->strength = strength;
- newpoint->time = point->time + deltatime;
-
- 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);
- }
+ bGPDspoint *newpoint;
+
+ 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++;
+ newpoint = &gps->points[gps->totpoints - 1];
+
+ newpoint->x = point->x * delta[0];
+ newpoint->y = point->y * delta[1];
+ newpoint->z = point->z * delta[2];
+ newpoint->flag = point->flag;
+ newpoint->pressure = pressure;
+ newpoint->strength = strength;
+ newpoint->time = point->time + deltatime;
+
+ 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);
+ }
}
/* Helper: join two strokes using the shortest distance (reorder stroke if necessary ) */
-static void gpencil_stroke_join_strokes(bGPDstroke *gps_a, bGPDstroke *gps_b, const bool leave_gaps)
+static void gpencil_stroke_join_strokes(bGPDstroke *gps_a,
+ bGPDstroke *gps_b,
+ const bool leave_gaps)
{
- bGPDspoint point;
- bGPDspoint *pt;
- int i;
- float delta[3] = {1.0f, 1.0f, 1.0f};
- float deltatime = 0.0f;
-
- /* sanity checks */
- if (ELEM(NULL, gps_a, gps_b))
- return;
-
- if ((gps_a->totpoints == 0) || (gps_b->totpoints == 0))
- return;
-
- /* define start and end points of each stroke */
- float sa[3], sb[3], ea[3], eb[3];
- pt = &gps_a->points[0];
- copy_v3_v3(sa, &pt->x);
-
- pt = &gps_a->points[gps_a->totpoints - 1];
- copy_v3_v3(ea, &pt->x);
-
- pt = &gps_b->points[0];
- copy_v3_v3(sb, &pt->x);
-
- pt = &gps_b->points[gps_b->totpoints - 1];
- copy_v3_v3(eb, &pt->x);
-
- /* review if need flip stroke B */
- float ea_sb = len_squared_v3v3(ea, sb);
- float ea_eb = len_squared_v3v3(ea, eb);
- /* flip if distance to end point is shorter */
- if (ea_eb < ea_sb) {
- gpencil_flip_stroke(gps_b);
- }
-
- /* don't visibly link the first and last points? */
- if (leave_gaps) {
- /* 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);
-
- /* 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);
- }
-
- /* 3rd: add all points */
- for (i = 0, pt = gps_b->points; i < gps_b->totpoints && pt; i++, pt++) {
- /* check if still room in buffer */
- if (gps_a->totpoints <= GP_STROKE_BUFFER_MAX - 2) {
- gpencil_stroke_copy_point(gps_a, pt, i, delta, pt->pressure, pt->strength, deltatime);
- }
- }
+ bGPDspoint point;
+ bGPDspoint *pt;
+ int i;
+ float delta[3] = {1.0f, 1.0f, 1.0f};
+ float deltatime = 0.0f;
+
+ /* sanity checks */
+ if (ELEM(NULL, gps_a, gps_b))
+ return;
+
+ if ((gps_a->totpoints == 0) || (gps_b->totpoints == 0))
+ return;
+
+ /* define start and end points of each stroke */
+ float sa[3], sb[3], ea[3], eb[3];
+ pt = &gps_a->points[0];
+ copy_v3_v3(sa, &pt->x);
+
+ pt = &gps_a->points[gps_a->totpoints - 1];
+ copy_v3_v3(ea, &pt->x);
+
+ pt = &gps_b->points[0];
+ copy_v3_v3(sb, &pt->x);
+
+ pt = &gps_b->points[gps_b->totpoints - 1];
+ copy_v3_v3(eb, &pt->x);
+
+ /* review if need flip stroke B */
+ float ea_sb = len_squared_v3v3(ea, sb);
+ float ea_eb = len_squared_v3v3(ea, eb);
+ /* flip if distance to end point is shorter */
+ if (ea_eb < ea_sb) {
+ gpencil_flip_stroke(gps_b);
+ }
+
+ /* don't visibly link the first and last points? */
+ if (leave_gaps) {
+ /* 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);
+
+ /* 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);
+ }
+
+ /* 3rd: add all points */
+ for (i = 0, pt = gps_b->points; i < gps_b->totpoints && pt; i++, pt++) {
+ /* check if still room in buffer */
+ if (gps_a->totpoints <= GP_STROKE_BUFFER_MAX - 2) {
+ gpencil_stroke_copy_point(gps_a, pt, i, 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;
- Object *ob = CTX_data_active_object(C);
-
- bGPDframe *gpf_a = NULL;
- bGPDstroke *stroke_a = NULL;
- bGPDstroke *stroke_b = NULL;
- bGPDstroke *new_stroke = NULL;
-
- const int type = RNA_enum_get(op->ptr, "type");
- const bool leave_gaps = RNA_boolean_get(op->ptr, "leave_gaps");
-
- /* sanity checks */
- if (ELEM(NULL, gpd))
- return OPERATOR_CANCELLED;
-
- if (activegpl->flag & GP_LAYER_LOCKED)
- return OPERATOR_CANCELLED;
-
- BLI_assert(ELEM(type, GP_STROKE_JOIN, GP_STROKE_JOINCOPY));
-
-
- /* read all selected strokes */
- bool first = false;
- 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;
- if (gps->flag & GP_STROKE_SELECT) {
- /* 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;
- }
-
- /* to join strokes, cyclic must be disabled */
- gps->flag &= ~GP_STROKE_CYCLIC;
-
- /* saves first frame and stroke */
- if (!first) {
- first = true;
- gpf_a = gpf;
- stroke_a = gps;
- }
- else {
- stroke_b = gps;
-
- /* 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;
-
- /* if new, set current color */
- if (type == GP_STROKE_JOINCOPY) {
- new_stroke->mat_nr = stroke_a->mat_nr;
- }
- }
-
- /* join new_stroke and stroke B. New stroke will contain all the previous data */
- gpencil_stroke_join_strokes(new_stroke, stroke_b, leave_gaps);
-
- /* if join only, delete old strokes */
- if (type == GP_STROKE_JOIN) {
- if (stroke_a) {
- BLI_insertlinkbefore(&gpf_a->strokes, stroke_a, new_stroke);
- BLI_remlink(&gpf->strokes, stroke_a);
- BKE_gpencil_free_stroke(stroke_a);
- stroke_a = NULL;
- }
- if (stroke_b) {
- BLI_remlink(&gpf->strokes, stroke_b);
- BKE_gpencil_free_stroke(stroke_b);
- stroke_b = NULL;
- }
- }
- }
- }
- }
- }
- CTX_DATA_END;
-
- /* add new stroke if was not added before */
- if (type == GP_STROKE_JOINCOPY) {
- if (new_stroke) {
- /* Add a new frame if needed */
- if (activegpl->actframe == NULL)
- activegpl->actframe = BKE_gpencil_frame_addnew(activegpl, gpf_a->framenum);
-
- BLI_addtail(&activegpl->actframe->strokes, new_stroke);
- }
- }
-
- /* 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;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *activegpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDstroke *gps, *gpsn;
+ Object *ob = CTX_data_active_object(C);
+
+ bGPDframe *gpf_a = NULL;
+ bGPDstroke *stroke_a = NULL;
+ bGPDstroke *stroke_b = NULL;
+ bGPDstroke *new_stroke = NULL;
+
+ const int type = RNA_enum_get(op->ptr, "type");
+ const bool leave_gaps = RNA_boolean_get(op->ptr, "leave_gaps");
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd))
+ return OPERATOR_CANCELLED;
+
+ if (activegpl->flag & GP_LAYER_LOCKED)
+ return OPERATOR_CANCELLED;
+
+ BLI_assert(ELEM(type, GP_STROKE_JOIN, GP_STROKE_JOINCOPY));
+
+ /* read all selected strokes */
+ bool first = false;
+ 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;
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* 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;
+ }
+
+ /* to join strokes, cyclic must be disabled */
+ gps->flag &= ~GP_STROKE_CYCLIC;
+
+ /* saves first frame and stroke */
+ if (!first) {
+ first = true;
+ gpf_a = gpf;
+ stroke_a = gps;
+ }
+ else {
+ stroke_b = gps;
+
+ /* 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;
+
+ /* if new, set current color */
+ if (type == GP_STROKE_JOINCOPY) {
+ new_stroke->mat_nr = stroke_a->mat_nr;
+ }
+ }
+
+ /* join new_stroke and stroke B. New stroke will contain all the previous data */
+ gpencil_stroke_join_strokes(new_stroke, stroke_b, leave_gaps);
+
+ /* if join only, delete old strokes */
+ if (type == GP_STROKE_JOIN) {
+ if (stroke_a) {
+ BLI_insertlinkbefore(&gpf_a->strokes, stroke_a, new_stroke);
+ BLI_remlink(&gpf->strokes, stroke_a);
+ BKE_gpencil_free_stroke(stroke_a);
+ stroke_a = NULL;
+ }
+ if (stroke_b) {
+ BLI_remlink(&gpf->strokes, stroke_b);
+ BKE_gpencil_free_stroke(stroke_b);
+ stroke_b = NULL;
+ }
+ }
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* add new stroke if was not added before */
+ if (type == GP_STROKE_JOINCOPY) {
+ if (new_stroke) {
+ /* Add a new frame if needed */
+ if (activegpl->actframe == NULL)
+ activegpl->actframe = BKE_gpencil_frame_addnew(activegpl, gpf_a->framenum);
+
+ BLI_addtail(&activegpl->actframe->strokes, new_stroke);
+ }
+ }
+
+ /* 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_stroke_join(wmOperatorType *ot)
{
- static const EnumPropertyItem join_type[] = {
- {GP_STROKE_JOIN, "JOIN", 0, "Join", ""},
- {GP_STROKE_JOINCOPY, "JOINCOPY", 0, "Join and Copy", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Join Strokes";
- ot->idname = "GPENCIL_OT_stroke_join";
- ot->description = "Join selected strokes (optionally as new stroke)";
-
- /* api callbacks */
- ot->exec = gp_stroke_join_exec;
- ot->poll = gp_active_layer_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", join_type, GP_STROKE_JOIN, "Type", "");
- RNA_def_boolean(ot->srna, "leave_gaps", false, "Leave Gaps", "Leave gaps between joined strokes instead of linking them");
+ static const EnumPropertyItem join_type[] = {
+ {GP_STROKE_JOIN, "JOIN", 0, "Join", ""},
+ {GP_STROKE_JOINCOPY, "JOINCOPY", 0, "Join and Copy", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Join Strokes";
+ ot->idname = "GPENCIL_OT_stroke_join";
+ ot->description = "Join selected strokes (optionally as new stroke)";
+
+ /* api callbacks */
+ ot->exec = gp_stroke_join_exec;
+ ot->poll = gp_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", join_type, GP_STROKE_JOIN, "Type", "");
+ RNA_def_boolean(ot->srna,
+ "leave_gaps",
+ false,
+ "Leave Gaps",
+ "Leave gaps between joined strokes instead of linking them");
}
/* ******************* Stroke flip ************************** */
static int gp_stroke_flip_exec(bContext *C, wmOperator *UNUSED(op))
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- Object *ob = CTX_data_active_object(C);
-
- /* sanity checks */
- if (ELEM(NULL, gpd))
- return OPERATOR_CANCELLED;
-
- /* read all selected strokes */
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- bGPDframe *gpf = gpl->actframe;
- if (gpf == NULL)
- continue;
-
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- if (gps->flag & GP_STROKE_SELECT) {
- /* 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;
- }
-
- /* flip stroke */
- gpencil_flip_stroke(gps);
- }
- }
- }
- CTX_DATA_END;
-
- /* 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;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ Object *ob = CTX_data_active_object(C);
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd))
+ return OPERATOR_CANCELLED;
+
+ /* read all selected strokes */
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ bGPDframe *gpf = gpl->actframe;
+ if (gpf == NULL)
+ continue;
+
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* 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;
+ }
+
+ /* flip stroke */
+ gpencil_flip_stroke(gps);
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* 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_stroke_flip(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Flip Stroke";
- ot->idname = "GPENCIL_OT_stroke_flip";
- ot->description = "Change direction of the points of the selected strokes";
+ /* identifiers */
+ ot->name = "Flip Stroke";
+ ot->idname = "GPENCIL_OT_stroke_flip";
+ ot->description = "Change direction of the points of the selected strokes";
- /* api callbacks */
- ot->exec = gp_stroke_flip_exec;
- ot->poll = gp_active_layer_poll;
+ /* api callbacks */
+ ot->exec = gp_stroke_flip_exec;
+ ot->poll = gp_active_layer_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ***************** Reproject Strokes ********************** */
typedef enum eGP_ReprojectModes {
- /* Axis */
- GP_REPROJECT_FRONT = 0,
- GP_REPROJECT_SIDE,
- GP_REPROJECT_TOP,
- /* On same plane, parallel to viewplane */
- GP_REPROJECT_VIEW,
- /* Reprojected on to the scene geometry */
- GP_REPROJECT_SURFACE,
- /* Reprojected on 3D cursor orientation */
- GP_REPROJECT_CURSOR,
+ /* Axis */
+ GP_REPROJECT_FRONT = 0,
+ GP_REPROJECT_SIDE,
+ GP_REPROJECT_TOP,
+ /* On same plane, parallel to viewplane */
+ GP_REPROJECT_VIEW,
+ /* Reprojected on to the scene geometry */
+ GP_REPROJECT_SURFACE,
+ /* Reprojected on 3D cursor orientation */
+ GP_REPROJECT_CURSOR,
} eGP_ReprojectModes;
static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *ob = CTX_data_active_object(C);
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
-
- GP_SpaceConversion gsc = {NULL};
- eGP_ReprojectModes mode = RNA_enum_get(op->ptr, "type");
-
- float origin[3];
-
- /* init space conversion stuff */
- gp_point_conversion_init(C, &gsc);
-
- /* init autodist for geometry projection */
- if (mode == GP_REPROJECT_SURFACE) {
- view3d_region_operator_needs_opengl(CTX_wm_window(C), gsc.ar);
- ED_view3d_autodist_init(depsgraph, gsc.ar, CTX_wm_view3d(C), 0);
- }
-
- // TODO: For deforming geometry workflow, create new frames?
-
- /* Go through each editable + selected stroke, adjusting each of its points one by one... */
- GP_EDITABLE_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
- {
- if (gps->flag & GP_STROKE_SELECT) {
- bGPDspoint *pt;
- int i;
- float inverse_diff_mat[4][4];
-
- /* Compute inverse matrix for unapplying parenting once instead of doing per-point */
- /* TODO: add this bit to the iteration macro? */
- invert_m4_m4(inverse_diff_mat, gpstroke_iter.diff_mat);
-
- /* Adjust each point */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- float xy[2];
-
- /* 3D to Screenspace */
- /* Note: We can't use gp_point_to_xy() here because that uses ints for the screenspace
- * coordinates, resulting in lost precision, which in turn causes stairstepping
- * artifacts in the final points.
- */
- bGPDspoint pt2;
- gp_point_to_parent_space(pt, gpstroke_iter.diff_mat, &pt2);
- gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]);
-
- /* Project stroke in one axis */
- if (ELEM(mode, GP_REPROJECT_FRONT, GP_REPROJECT_SIDE,
- GP_REPROJECT_TOP, GP_REPROJECT_CURSOR))
- {
- if (mode != GP_REPROJECT_CURSOR) {
- ED_gp_get_drawing_reference(
- scene, ob, gpl,
- ts->gpencil_v3d_align, origin);
- }
- else {
- copy_v3_v3(origin, scene->cursor.location);
- }
-
- int axis = 0;
- switch (mode) {
- case GP_REPROJECT_FRONT:
- {
- axis = 1;
- break;
- }
- case GP_REPROJECT_SIDE:
- {
- axis = 0;
- break;
- }
- case GP_REPROJECT_TOP:
- {
- axis = 2;
- break;
- }
- case GP_REPROJECT_CURSOR:
- {
- axis = 3;
- break;
- }
- default:
- {
- axis = 1;
- break;
- }
- }
-
- ED_gp_project_point_to_plane(
- scene, ob, rv3d, origin,
- axis, &pt2);
-
- copy_v3_v3(&pt->x, &pt2.x);
-
- /* apply parent again */
- gp_apply_parent_point(depsgraph, ob, gpd, gpl, pt);
- }
- /* Project screenspace back to 3D space (from current perspective)
- * so that all points have been treated the same way
- */
- else if (mode == GP_REPROJECT_VIEW) {
- /* Planar - All on same plane parallel to the viewplane */
- gp_point_xy_to_3d(&gsc, scene, xy, &pt->x);
- }
- else {
- /* Geometry - Snap to surfaces of visible geometry */
- /* XXX: There will be precision loss (possible stairstep artifacts)
- * from this conversion to satisfy the API's */
- const int screen_co[2] = {(int)xy[0], (int)xy[1]};
-
- int depth_margin = 0; // XXX: 4 for strokes, 0 for normal
- float depth;
-
- /* XXX: The proper procedure computes the depths into an array,
- * to have smooth transitions when all else fails... */
- if (ED_view3d_autodist_depth(gsc.ar, screen_co, depth_margin, &depth)) {
- ED_view3d_autodist_simple(gsc.ar, screen_co, &pt->x, 0, &depth);
- }
- else {
- /* Default to planar */
- gp_point_xy_to_3d(&gsc, scene, xy, &pt->x);
- }
- }
-
- /* Unapply parent corrections */
- if (!ELEM(mode, GP_REPROJECT_FRONT, GP_REPROJECT_SIDE, GP_REPROJECT_TOP)) {
- mul_m4_v3(inverse_diff_mat, &pt->x);
- }
- }
- }
- }
- GP_EDITABLE_STROKES_END(gpstroke_iter);
-
- 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;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob = CTX_data_active_object(C);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ GP_SpaceConversion gsc = {NULL};
+ eGP_ReprojectModes mode = RNA_enum_get(op->ptr, "type");
+
+ float origin[3];
+
+ /* init space conversion stuff */
+ gp_point_conversion_init(C, &gsc);
+
+ /* init autodist for geometry projection */
+ if (mode == GP_REPROJECT_SURFACE) {
+ view3d_region_operator_needs_opengl(CTX_wm_window(C), gsc.ar);
+ ED_view3d_autodist_init(depsgraph, gsc.ar, CTX_wm_view3d(C), 0);
+ }
+
+ // TODO: For deforming geometry workflow, create new frames?
+
+ /* Go through each editable + selected stroke, adjusting each of its points one by one... */
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+ float inverse_diff_mat[4][4];
+
+ /* Compute inverse matrix for unapplying parenting once instead of doing per-point */
+ /* TODO: add this bit to the iteration macro? */
+ invert_m4_m4(inverse_diff_mat, gpstroke_iter.diff_mat);
+
+ /* Adjust each point */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ float xy[2];
+
+ /* 3D to Screenspace */
+ /* Note: We can't use gp_point_to_xy() here because that uses ints for the screenspace
+ * coordinates, resulting in lost precision, which in turn causes stairstepping
+ * artifacts in the final points.
+ */
+ bGPDspoint pt2;
+ gp_point_to_parent_space(pt, gpstroke_iter.diff_mat, &pt2);
+ gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]);
+
+ /* Project stroke in one axis */
+ if (ELEM(mode,
+ GP_REPROJECT_FRONT,
+ GP_REPROJECT_SIDE,
+ GP_REPROJECT_TOP,
+ GP_REPROJECT_CURSOR)) {
+ if (mode != GP_REPROJECT_CURSOR) {
+ ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, origin);
+ }
+ else {
+ copy_v3_v3(origin, scene->cursor.location);
+ }
+
+ int axis = 0;
+ switch (mode) {
+ case GP_REPROJECT_FRONT: {
+ axis = 1;
+ break;
+ }
+ case GP_REPROJECT_SIDE: {
+ axis = 0;
+ break;
+ }
+ case GP_REPROJECT_TOP: {
+ axis = 2;
+ break;
+ }
+ case GP_REPROJECT_CURSOR: {
+ axis = 3;
+ break;
+ }
+ default: {
+ axis = 1;
+ break;
+ }
+ }
+
+ ED_gp_project_point_to_plane(scene, ob, rv3d, origin, axis, &pt2);
+
+ copy_v3_v3(&pt->x, &pt2.x);
+
+ /* apply parent again */
+ gp_apply_parent_point(depsgraph, ob, gpd, gpl, pt);
+ }
+ /* Project screenspace back to 3D space (from current perspective)
+ * so that all points have been treated the same way
+ */
+ else if (mode == GP_REPROJECT_VIEW) {
+ /* Planar - All on same plane parallel to the viewplane */
+ gp_point_xy_to_3d(&gsc, scene, xy, &pt->x);
+ }
+ else {
+ /* Geometry - Snap to surfaces of visible geometry */
+ /* XXX: There will be precision loss (possible stairstep artifacts)
+ * from this conversion to satisfy the API's */
+ const int screen_co[2] = {(int)xy[0], (int)xy[1]};
+
+ int depth_margin = 0; // XXX: 4 for strokes, 0 for normal
+ float depth;
+
+ /* XXX: The proper procedure computes the depths into an array,
+ * to have smooth transitions when all else fails... */
+ if (ED_view3d_autodist_depth(gsc.ar, screen_co, depth_margin, &depth)) {
+ ED_view3d_autodist_simple(gsc.ar, screen_co, &pt->x, 0, &depth);
+ }
+ else {
+ /* Default to planar */
+ gp_point_xy_to_3d(&gsc, scene, xy, &pt->x);
+ }
+ }
+
+ /* Unapply parent corrections */
+ if (!ELEM(mode, GP_REPROJECT_FRONT, GP_REPROJECT_SIDE, GP_REPROJECT_TOP)) {
+ mul_m4_v3(inverse_diff_mat, &pt->x);
+ }
+ }
+ }
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
+
+ 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_reproject(wmOperatorType *ot)
{
- static const EnumPropertyItem reproject_type[] = {
- {GP_REPROJECT_FRONT, "FRONT", 0, "Front",
- "Reproject the strokes using the X-Z plane"},
- {GP_REPROJECT_SIDE, "SIDE", 0, "Side",
- "Reproject the strokes using the Y-Z plane"},
- {GP_REPROJECT_TOP, "TOP", 0, "Top",
- "Reproject the strokes using the X-Y plane"},
- {GP_REPROJECT_VIEW, "VIEW", 0, "View",
- "Reproject the strokes to end up on the same plane, as if drawn from the current viewpoint "
- "using 'Cursor' Stroke Placement"},
- {GP_REPROJECT_SURFACE, "SURFACE", 0, "Surface",
- "Reproject the strokes on to the scene geometry, as if drawn using 'Surface' placement"},
- {GP_REPROJECT_CURSOR, "CURSOR", 0, "Cursor",
- "Reproject the strokes using the orienation of 3D cursor"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Reproject Strokes";
- ot->idname = "GPENCIL_OT_reproject";
- ot->description = "Reproject the selected strokes from the current viewpoint as if they had been newly drawn "
- "(e.g. to fix problems from accidental 3D cursor movement or accidental viewport changes, "
- "or for matching deforming geometry)";
-
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = gp_strokes_reproject_exec;
- ot->poll = gp_strokes_edit3d_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", reproject_type, GP_REPROJECT_VIEW, "Projection Type", "");
+ static const EnumPropertyItem reproject_type[] = {
+ {GP_REPROJECT_FRONT, "FRONT", 0, "Front", "Reproject the strokes using the X-Z plane"},
+ {GP_REPROJECT_SIDE, "SIDE", 0, "Side", "Reproject the strokes using the Y-Z plane"},
+ {GP_REPROJECT_TOP, "TOP", 0, "Top", "Reproject the strokes using the X-Y plane"},
+ {GP_REPROJECT_VIEW,
+ "VIEW",
+ 0,
+ "View",
+ "Reproject the strokes to end up on the same plane, as if drawn from the current viewpoint "
+ "using 'Cursor' Stroke Placement"},
+ {GP_REPROJECT_SURFACE,
+ "SURFACE",
+ 0,
+ "Surface",
+ "Reproject the strokes on to the scene geometry, as if drawn using 'Surface' placement"},
+ {GP_REPROJECT_CURSOR,
+ "CURSOR",
+ 0,
+ "Cursor",
+ "Reproject the strokes using the orienation of 3D cursor"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Reproject Strokes";
+ ot->idname = "GPENCIL_OT_reproject";
+ ot->description =
+ "Reproject the selected strokes from the current viewpoint as if they had been newly drawn "
+ "(e.g. to fix problems from accidental 3D cursor movement or accidental viewport changes, "
+ "or for matching deforming geometry)";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = gp_strokes_reproject_exec;
+ ot->poll = gp_strokes_edit3d_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+
+ /* properties */
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", reproject_type, GP_REPROJECT_VIEW, "Projection Type", "");
}
/* ******************* Stroke subdivide ************************** */
/* helper to smooth */
static void gp_smooth_stroke(bContext *C, wmOperator *op)
{
- const int repeat = RNA_int_get(op->ptr, "repeat");
- float factor = RNA_float_get(op->ptr, "factor");
- const bool only_selected = RNA_boolean_get(op->ptr, "only_selected");
- const bool smooth_position = RNA_boolean_get(op->ptr, "smooth_position");
- const bool smooth_thickness = RNA_boolean_get(op->ptr, "smooth_thickness");
- const bool smooth_strength = RNA_boolean_get(op->ptr, "smooth_strength");
- const bool smooth_uv = RNA_boolean_get(op->ptr, "smooth_uv");
-
- if (factor == 0.0f) {
- return;
- }
-
- GP_EDITABLE_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
- {
- if (gps->flag & GP_STROKE_SELECT) {
- for (int r = 0; r < repeat; r++) {
- for (int i = 0; i < gps->totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
- if ((only_selected) && ((pt->flag & GP_SPOINT_SELECT) == 0)) {
- continue;
- }
-
- /* perform smoothing */
- if (smooth_position) {
- BKE_gpencil_smooth_stroke(gps, i, factor);
- }
- if (smooth_strength) {
- BKE_gpencil_smooth_stroke_strength(gps, i, factor);
- }
- if (smooth_thickness) {
- /* thickness need to repeat process several times */
- for (int r2 = 0; r2 < r * 10; r2++) {
- BKE_gpencil_smooth_stroke_thickness(gps, i, factor);
- }
- }
- if (smooth_uv) {
- BKE_gpencil_smooth_stroke_uv(gps, i, factor);
- }
- }
- }
- }
- }
- GP_EDITABLE_STROKES_END(gpstroke_iter);
+ const int repeat = RNA_int_get(op->ptr, "repeat");
+ float factor = RNA_float_get(op->ptr, "factor");
+ const bool only_selected = RNA_boolean_get(op->ptr, "only_selected");
+ const bool smooth_position = RNA_boolean_get(op->ptr, "smooth_position");
+ const bool smooth_thickness = RNA_boolean_get(op->ptr, "smooth_thickness");
+ const bool smooth_strength = RNA_boolean_get(op->ptr, "smooth_strength");
+ const bool smooth_uv = RNA_boolean_get(op->ptr, "smooth_uv");
+
+ if (factor == 0.0f) {
+ return;
+ }
+
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ for (int r = 0; r < repeat; r++) {
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ if ((only_selected) && ((pt->flag & GP_SPOINT_SELECT) == 0)) {
+ continue;
+ }
+
+ /* perform smoothing */
+ if (smooth_position) {
+ BKE_gpencil_smooth_stroke(gps, i, factor);
+ }
+ if (smooth_strength) {
+ BKE_gpencil_smooth_stroke_strength(gps, i, factor);
+ }
+ if (smooth_thickness) {
+ /* thickness need to repeat process several times */
+ for (int r2 = 0; r2 < r * 10; r2++) {
+ BKE_gpencil_smooth_stroke_thickness(gps, i, factor);
+ }
+ }
+ if (smooth_uv) {
+ BKE_gpencil_smooth_stroke_uv(gps, i, factor);
+ }
+ }
+ }
+ }
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
}
/* helper: Count how many points need to be inserted */
static int gp_count_subdivision_cuts(bGPDstroke *gps)
{
- bGPDspoint *pt;
- int i;
- int totnewpoints = 0;
- for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT) {
- if (i + 1 < gps->totpoints) {
- if (gps->points[i + 1].flag & GP_SPOINT_SELECT) {
- totnewpoints++;
- }
- }
- }
- }
-
- return totnewpoints;
+ bGPDspoint *pt;
+ int i;
+ int totnewpoints = 0;
+ for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ if (i + 1 < gps->totpoints) {
+ if (gps->points[i + 1].flag & GP_SPOINT_SELECT) {
+ totnewpoints++;
+ }
+ }
+ }
+ }
+
+ return totnewpoints;
}
static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDspoint *temp_points;
- const int cuts = RNA_int_get(op->ptr, "number_cuts");
-
- int totnewpoints, oldtotpoints;
- int i2;
-
- /* sanity checks */
- if (ELEM(NULL, gpd))
- return OPERATOR_CANCELLED;
-
- /* Go through each editable + selected stroke */
- GP_EDITABLE_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
- {
- if (gps->flag & GP_STROKE_SELECT) {
- /* loop as many times as cuts */
- for (int s = 0; s < cuts; s++) {
- totnewpoints = gp_count_subdivision_cuts(gps);
- if (totnewpoints == 0) {
- continue;
- }
- /* duplicate points in a temp area */
- temp_points = MEM_dupallocN(gps->points);
- oldtotpoints = gps->totpoints;
-
- MDeformVert *temp_dverts = NULL;
- MDeformVert *dvert_final = NULL;
- MDeformVert *dvert = NULL;
- MDeformVert *dvert_next = NULL;
- if (gps->dvert != NULL) {
- temp_dverts = MEM_dupallocN(gps->dvert);
- }
-
- /* resize the points arrays */
- gps->totpoints += totnewpoints;
- gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
- if (gps->dvert != NULL) {
- gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
- }
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
-
- /* loop and interpolate */
- i2 = 0;
- for (int i = 0; i < oldtotpoints; i++) {
- bGPDspoint *pt = &temp_points[i];
- bGPDspoint *pt_final = &gps->points[i2];
-
- /* copy current point */
- copy_v3_v3(&pt_final->x, &pt->x);
- pt_final->pressure = pt->pressure;
- pt_final->strength = pt->strength;
- pt_final->time = pt->time;
- pt_final->flag = pt->flag;
-
- if (gps->dvert != NULL) {
- dvert = &temp_dverts[i];
- dvert_final = &gps->dvert[i2];
- dvert_final->totweight = dvert->totweight;
- dvert_final->dw = dvert->dw;
- }
- i2++;
-
- /* if next point is selected add a half way point */
- if (pt->flag & GP_SPOINT_SELECT) {
- if (i + 1 < oldtotpoints) {
- if (temp_points[i + 1].flag & GP_SPOINT_SELECT) {
- pt_final = &gps->points[i2];
- if (gps->dvert != NULL) {
- dvert_final = &gps->dvert[i2];
- }
- /* Interpolate all values */
- bGPDspoint *next = &temp_points[i + 1];
- interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
- 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);
- pt_final->time = interpf(pt->time, next->time, 0.5f);
- pt_final->flag |= GP_SPOINT_SELECT;
-
- /* interpolate weights */
- if (gps->dvert != NULL) {
- dvert = &temp_dverts[i];
- dvert_next = &temp_dverts[i + 1];
- dvert_final = &gps->dvert[i2];
-
- dvert_final->totweight = dvert->totweight;
- dvert_final->dw = MEM_dupallocN(dvert->dw);
-
- /* interpolate weight values */
- for (int d = 0; d < dvert->totweight; d++) {
- MDeformWeight *dw_a = &dvert->dw[d];
- if (dvert_next->totweight > d) {
- MDeformWeight *dw_b = &dvert_next->dw[d];
- MDeformWeight *dw_final = &dvert_final->dw[d];
- dw_final->weight = interpf(dw_a->weight, dw_b->weight, 0.5f);
- }
- }
- }
-
- i2++;
- }
- }
- }
- }
- /* free temp memory */
- MEM_SAFE_FREE(temp_points);
- MEM_SAFE_FREE(temp_dverts);
- }
-
- /* triangles cache needs to be recalculated */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
- }
- }
- GP_EDITABLE_STROKES_END(gpstroke_iter);
-
- /* smooth stroke */
- gp_smooth_stroke(C, op);
-
- /* 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;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDspoint *temp_points;
+ const int cuts = RNA_int_get(op->ptr, "number_cuts");
+
+ int totnewpoints, oldtotpoints;
+ int i2;
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd))
+ return OPERATOR_CANCELLED;
+
+ /* Go through each editable + selected stroke */
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* loop as many times as cuts */
+ for (int s = 0; s < cuts; s++) {
+ totnewpoints = gp_count_subdivision_cuts(gps);
+ if (totnewpoints == 0) {
+ continue;
+ }
+ /* duplicate points in a temp area */
+ temp_points = MEM_dupallocN(gps->points);
+ oldtotpoints = gps->totpoints;
+
+ MDeformVert *temp_dverts = NULL;
+ MDeformVert *dvert_final = NULL;
+ MDeformVert *dvert = NULL;
+ MDeformVert *dvert_next = NULL;
+ if (gps->dvert != NULL) {
+ temp_dverts = MEM_dupallocN(gps->dvert);
+ }
+
+ /* resize the points arrays */
+ gps->totpoints += totnewpoints;
+ gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
+ if (gps->dvert != NULL) {
+ gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
+ }
+ gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+
+ /* loop and interpolate */
+ i2 = 0;
+ for (int i = 0; i < oldtotpoints; i++) {
+ bGPDspoint *pt = &temp_points[i];
+ bGPDspoint *pt_final = &gps->points[i2];
+
+ /* copy current point */
+ copy_v3_v3(&pt_final->x, &pt->x);
+ pt_final->pressure = pt->pressure;
+ pt_final->strength = pt->strength;
+ pt_final->time = pt->time;
+ pt_final->flag = pt->flag;
+
+ if (gps->dvert != NULL) {
+ dvert = &temp_dverts[i];
+ dvert_final = &gps->dvert[i2];
+ dvert_final->totweight = dvert->totweight;
+ dvert_final->dw = dvert->dw;
+ }
+ i2++;
+
+ /* if next point is selected add a half way point */
+ if (pt->flag & GP_SPOINT_SELECT) {
+ if (i + 1 < oldtotpoints) {
+ if (temp_points[i + 1].flag & GP_SPOINT_SELECT) {
+ pt_final = &gps->points[i2];
+ if (gps->dvert != NULL) {
+ dvert_final = &gps->dvert[i2];
+ }
+ /* Interpolate all values */
+ bGPDspoint *next = &temp_points[i + 1];
+ interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
+ 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);
+ pt_final->time = interpf(pt->time, next->time, 0.5f);
+ pt_final->flag |= GP_SPOINT_SELECT;
+
+ /* interpolate weights */
+ if (gps->dvert != NULL) {
+ dvert = &temp_dverts[i];
+ dvert_next = &temp_dverts[i + 1];
+ dvert_final = &gps->dvert[i2];
+
+ dvert_final->totweight = dvert->totweight;
+ dvert_final->dw = MEM_dupallocN(dvert->dw);
+
+ /* interpolate weight values */
+ for (int d = 0; d < dvert->totweight; d++) {
+ MDeformWeight *dw_a = &dvert->dw[d];
+ if (dvert_next->totweight > d) {
+ MDeformWeight *dw_b = &dvert_next->dw[d];
+ MDeformWeight *dw_final = &dvert_final->dw[d];
+ dw_final->weight = interpf(dw_a->weight, dw_b->weight, 0.5f);
+ }
+ }
+ }
+
+ i2++;
+ }
+ }
+ }
+ }
+ /* free temp memory */
+ MEM_SAFE_FREE(temp_points);
+ MEM_SAFE_FREE(temp_dverts);
+ }
+
+ /* triangles cache needs to be recalculated */
+ gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gps->tot_triangles = 0;
+ }
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
+
+ /* smooth stroke */
+ gp_smooth_stroke(C, op);
+
+ /* 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_stroke_subdivide(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Subdivide Stroke";
- ot->idname = "GPENCIL_OT_stroke_subdivide";
- ot->description = "Subdivide between continuous selected points of the stroke adding a point half way between them";
-
- /* api callbacks */
- ot->exec = gp_stroke_subdivide_exec;
- ot->poll = gp_active_layer_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 10, "Number of Cuts", "", 1, 5);
- /* avoid re-using last var because it can cause _very_ high value and annoy users */
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- /* Smooth parameters */
- RNA_def_float(ot->srna, "factor", 0.0f, 0.0f, 2.0f, "Smooth", "", 0.0f, 2.0f);
- prop = RNA_def_int(ot->srna, "repeat", 1, 1, 10, "Repeat", "", 1, 5);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- RNA_def_boolean(
- ot->srna, "only_selected", true, "Selected Points",
- "Smooth only selected points in the stroke");
- RNA_def_boolean(ot->srna, "smooth_position", true, "Position", "");
- RNA_def_boolean(ot->srna, "smooth_thickness", true, "Thickness", "");
- RNA_def_boolean(ot->srna, "smooth_strength", false, "Strength", "");
- RNA_def_boolean(ot->srna, "smooth_uv", false, "UV", "");
-
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Subdivide Stroke";
+ ot->idname = "GPENCIL_OT_stroke_subdivide";
+ ot->description =
+ "Subdivide between continuous selected points of the stroke adding a point half way between "
+ "them";
+
+ /* api callbacks */
+ ot->exec = gp_stroke_subdivide_exec;
+ ot->poll = gp_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 10, "Number of Cuts", "", 1, 5);
+ /* avoid re-using last var because it can cause _very_ high value and annoy users */
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ /* Smooth parameters */
+ RNA_def_float(ot->srna, "factor", 0.0f, 0.0f, 2.0f, "Smooth", "", 0.0f, 2.0f);
+ prop = RNA_def_int(ot->srna, "repeat", 1, 1, 10, "Repeat", "", 1, 5);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_boolean(ot->srna,
+ "only_selected",
+ true,
+ "Selected Points",
+ "Smooth only selected points in the stroke");
+ RNA_def_boolean(ot->srna, "smooth_position", true, "Position", "");
+ RNA_def_boolean(ot->srna, "smooth_thickness", true, "Thickness", "");
+ RNA_def_boolean(ot->srna, "smooth_strength", false, "Strength", "");
+ RNA_def_boolean(ot->srna, "smooth_uv", false, "UV", "");
}
/* ** simplify stroke *** */
static int gp_stroke_simplify_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- float factor = RNA_float_get(op->ptr, "factor");
-
- /* sanity checks */
- if (ELEM(NULL, gpd))
- return OPERATOR_CANCELLED;
-
- /* Go through each editable + selected stroke */
- 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);
- }
- }
- GP_EDITABLE_STROKES_END(gpstroke_iter);
-
- /* 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;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ float factor = RNA_float_get(op->ptr, "factor");
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd))
+ return OPERATOR_CANCELLED;
+
+ /* Go through each editable + selected stroke */
+ 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);
+ }
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
+
+ /* 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_stroke_simplify(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Simplify Stroke";
- ot->idname = "GPENCIL_OT_stroke_simplify";
- ot->description = "Simplify selected stroked reducing number of points";
+ /* identifiers */
+ ot->name = "Simplify Stroke";
+ ot->idname = "GPENCIL_OT_stroke_simplify";
+ ot->description = "Simplify selected stroked reducing number of points";
- /* api callbacks */
- ot->exec = gp_stroke_simplify_exec;
- ot->poll = gp_active_layer_poll;
+ /* api callbacks */
+ ot->exec = gp_stroke_simplify_exec;
+ ot->poll = gp_active_layer_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- prop = RNA_def_float(ot->srna, "factor", 0.0f, 0.0f, 100.0f, "Factor", "", 0.0f, 100.0f);
- /* avoid re-using last var */
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ prop = RNA_def_float(ot->srna, "factor", 0.0f, 0.0f, 100.0f, "Factor", "", 0.0f, 100.0f);
+ /* avoid re-using last var */
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ** simplify stroke using fixed algorithm *** */
static int gp_stroke_simplify_fixed_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- int steps = RNA_int_get(op->ptr, "step");
-
- /* sanity checks */
- if (ELEM(NULL, gpd))
- return OPERATOR_CANCELLED;
-
- /* Go through each editable + selected stroke */
- 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);
- }
- }
- }
- GP_EDITABLE_STROKES_END(gpstroke_iter);
-
- /* 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;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ int steps = RNA_int_get(op->ptr, "step");
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd))
+ return OPERATOR_CANCELLED;
+
+ /* Go through each editable + selected stroke */
+ 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);
+ }
+ }
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
+
+ /* 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_stroke_simplify_fixed(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Simplify Fixed Stroke";
- ot->idname = "GPENCIL_OT_stroke_simplify_fixed";
- ot->description = "Simplify selected stroked reducing number of points using fixed algorithm";
+ PropertyRNA *prop;
- /* api callbacks */
- ot->exec = gp_stroke_simplify_fixed_exec;
- ot->poll = gp_active_layer_poll;
+ /* identifiers */
+ ot->name = "Simplify Fixed Stroke";
+ ot->idname = "GPENCIL_OT_stroke_simplify_fixed";
+ ot->description = "Simplify selected stroked reducing number of points using fixed algorithm";
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* api callbacks */
+ ot->exec = gp_stroke_simplify_fixed_exec;
+ ot->poll = gp_active_layer_poll;
- /* properties */
- prop = RNA_def_int(ot->srna, "step", 1, 1, 100, "Steps", "Number of simplify steps", 1, 10);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* avoid re-using last var */
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ prop = RNA_def_int(ot->srna, "step", 1, 1, 100, "Steps", "Number of simplify steps", 1, 10);
+ /* avoid re-using last var */
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ******************* Stroke trim ************************** */
static int gp_stroke_trim_exec(bContext *C, wmOperator *UNUSED(op))
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
-
- /* sanity checks */
- if (ELEM(NULL, gpd))
- return OPERATOR_CANCELLED;
-
- /* Go through each editable + selected stroke */
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
-
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- 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))) {
- bGPDstroke *gps, *gpsn;
-
- if (gpf == NULL)
- continue;
-
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
-
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps) == false)
- continue;
-
- if (gps->flag & GP_STROKE_SELECT) {
- BKE_gpencil_trim_stroke(gps);
- }
- }
- /* if not multiedit, exit loop*/
- if (!is_multiedit) {
- break;
- }
- }
- }
- }
- CTX_DATA_END;
-
- /* 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;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd))
+ return OPERATOR_CANCELLED;
+
+ /* Go through each editable + selected stroke */
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ 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))) {
+ bGPDstroke *gps, *gpsn;
+
+ if (gpf == NULL)
+ continue;
+
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
+ if (gps->flag & GP_STROKE_SELECT) {
+ BKE_gpencil_trim_stroke(gps);
+ }
+ }
+ /* if not multiedit, exit loop*/
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* 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_stroke_trim(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Trim Stroke";
- ot->idname = "GPENCIL_OT_stroke_trim";
- ot->description = "Trim selected stroke to first loop or intersection";
+ /* identifiers */
+ ot->name = "Trim Stroke";
+ ot->idname = "GPENCIL_OT_stroke_trim";
+ ot->description = "Trim selected stroke to first loop or intersection";
- /* api callbacks */
- ot->exec = gp_stroke_trim_exec;
- ot->poll = gp_active_layer_poll;
+ /* api callbacks */
+ ot->exec = gp_stroke_trim_exec;
+ ot->poll = gp_active_layer_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ***************** Separate Strokes ********************** */
typedef enum eGP_SeparateModes {
- /* Points */
- GP_SEPARATE_POINT = 0,
- /* Selected Strokes */
- GP_SEPARATE_STROKE,
- /* Current Layer */
- GP_SEPARATE_LAYER,
+ /* Points */
+ GP_SEPARATE_POINT = 0,
+ /* Selected Strokes */
+ GP_SEPARATE_STROKE,
+ /* Current Layer */
+ GP_SEPARATE_LAYER,
} eGP_SeparateModes;
static int gp_stroke_separate_exec(bContext *C, wmOperator *op)
{
- Base *base_new;
- 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);
- bGPdata *gpd_src = ED_gpencil_data_get_active(C);
- Object *ob = CTX_data_active_object(C);
-
- Object *ob_dst = NULL;
- bGPdata *gpd_dst = NULL;
- bGPDlayer *gpl_dst = NULL;
- bGPDframe *gpf_dst = NULL;
- bGPDspoint *pt;
- Material *ma = NULL;
- int i, idx;
-
- eGP_SeparateModes mode = RNA_enum_get(op->ptr, "mode");
-
- /* sanity checks */
- if (ELEM(NULL, gpd_src)) {
- return OPERATOR_CANCELLED;
- }
-
- if ((mode == GP_SEPARATE_LAYER) && (BLI_listbase_count(&gpd_src->layers) == 1)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot separate an object with one layer only");
- return OPERATOR_CANCELLED;
- }
-
- 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);
- ob_dst = base_new->object;
- ob_dst->mode = OB_MODE_OBJECT;
- /* create new grease pencil datablock */
- gpd_dst = BKE_gpencil_data_addnew(bmain, gpd_src->id.name + 2);
- ob_dst->data = (bGPdata *)gpd_dst;
-
- /* loop old datablock and separate parts */
- if ((mode == GP_SEPARATE_POINT) || (mode == GP_SEPARATE_STROKE)) {
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- gpl_dst = NULL;
- 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))) {
- bGPDstroke *gps, *gpsn;
-
- if (gpf == NULL) {
- continue;
- }
-
- gpf_dst = NULL;
-
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
-
- /* 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;
- }
- /* separate selected strokes */
- if (gps->flag & GP_STROKE_SELECT) {
- /* add layer if not created before */
- if (gpl_dst == NULL) {
- gpl_dst = BKE_gpencil_layer_addnew(gpd_dst, gpl->info, false);
- }
-
- /* add frame if not created before */
- if (gpf_dst == NULL) {
- gpf_dst = BKE_gpencil_layer_getframe(gpl_dst, gpf->framenum, GP_GETFRAME_ADD_NEW);
- }
-
- /* add duplicate materials */
- ma = give_current_material(ob, gps->mat_nr + 1); /* XXX same material can be in multiple slots */
- 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);
-
- /* reasign material */
- gps_dst->mat_nr = idx;
-
- /* link to destination frame */
- BLI_addtail(&gpf_dst->strokes, gps_dst);
-
- /* Invert selection status of all points in destination stroke */
- for (i = 0, pt = gps_dst->points; i < gps_dst->totpoints; i++, pt++) {
- pt->flag ^= GP_SPOINT_SELECT;
- }
-
- /* delete selected points from destination stroke */
- 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);
- }
- /* selected strokes mode */
- else if (mode == GP_SEPARATE_STROKE) {
- /* deselect old stroke */
- gps->flag &= ~GP_STROKE_SELECT;
- /* unlink from source frame */
- BLI_remlink(&gpf->strokes, gps);
- gps->prev = gps->next = NULL;
- /* relink to destination frame */
- BLI_addtail(&gpf_dst->strokes, gps);
- /* reasign material */
- gps->mat_nr = idx;
- }
- }
- }
- }
-
- /* if not multiedit, exit loop*/
- if (!is_multiedit) {
- break;
- }
- }
- }
- CTX_DATA_END;
- }
- else if (mode == GP_SEPARATE_LAYER) {
- bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
- if (gpl) {
- /* try to set a new active layer in source datablock */
- if (gpl->prev) {
- BKE_gpencil_layer_setactive(gpd_src, gpl->prev);
- }
- else if (gpl->next) {
- BKE_gpencil_layer_setactive(gpd_src, gpl->next);
- }
- /* unlink from source datablock */
- BLI_remlink(&gpd_src->layers, gpl);
- gpl->prev = gpl->next = NULL;
- /* relink to destination datablock */
- 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) {
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps) == false) {
- continue;
- }
- ma = give_current_material(ob, gps->mat_nr + 1);
- gps->mat_nr = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma);
- }
- }
- }
- }
-
- 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);
-
- return OPERATOR_FINISHED;
+ Base *base_new;
+ 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);
+ bGPdata *gpd_src = ED_gpencil_data_get_active(C);
+ Object *ob = CTX_data_active_object(C);
+
+ Object *ob_dst = NULL;
+ bGPdata *gpd_dst = NULL;
+ bGPDlayer *gpl_dst = NULL;
+ bGPDframe *gpf_dst = NULL;
+ bGPDspoint *pt;
+ Material *ma = NULL;
+ int i, idx;
+
+ eGP_SeparateModes mode = RNA_enum_get(op->ptr, "mode");
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd_src)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if ((mode == GP_SEPARATE_LAYER) && (BLI_listbase_count(&gpd_src->layers) == 1)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot separate an object with one layer only");
+ return OPERATOR_CANCELLED;
+ }
+
+ 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);
+ ob_dst = base_new->object;
+ ob_dst->mode = OB_MODE_OBJECT;
+ /* create new grease pencil datablock */
+ gpd_dst = BKE_gpencil_data_addnew(bmain, gpd_src->id.name + 2);
+ ob_dst->data = (bGPdata *)gpd_dst;
+
+ /* loop old datablock and separate parts */
+ if ((mode == GP_SEPARATE_POINT) || (mode == GP_SEPARATE_STROKE)) {
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ gpl_dst = NULL;
+ 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))) {
+ bGPDstroke *gps, *gpsn;
+
+ if (gpf == NULL) {
+ continue;
+ }
+
+ gpf_dst = NULL;
+
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ /* 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;
+ }
+ /* separate selected strokes */
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* add layer if not created before */
+ if (gpl_dst == NULL) {
+ gpl_dst = BKE_gpencil_layer_addnew(gpd_dst, gpl->info, false);
+ }
+
+ /* add frame if not created before */
+ if (gpf_dst == NULL) {
+ gpf_dst = BKE_gpencil_layer_getframe(gpl_dst, gpf->framenum, GP_GETFRAME_ADD_NEW);
+ }
+
+ /* add duplicate materials */
+ ma = give_current_material(
+ ob, gps->mat_nr + 1); /* XXX same material can be in multiple slots */
+ 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);
+
+ /* reasign material */
+ gps_dst->mat_nr = idx;
+
+ /* link to destination frame */
+ BLI_addtail(&gpf_dst->strokes, gps_dst);
+
+ /* Invert selection status of all points in destination stroke */
+ for (i = 0, pt = gps_dst->points; i < gps_dst->totpoints; i++, pt++) {
+ pt->flag ^= GP_SPOINT_SELECT;
+ }
+
+ /* delete selected points from destination stroke */
+ 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);
+ }
+ /* selected strokes mode */
+ else if (mode == GP_SEPARATE_STROKE) {
+ /* deselect old stroke */
+ gps->flag &= ~GP_STROKE_SELECT;
+ /* unlink from source frame */
+ BLI_remlink(&gpf->strokes, gps);
+ gps->prev = gps->next = NULL;
+ /* relink to destination frame */
+ BLI_addtail(&gpf_dst->strokes, gps);
+ /* reasign material */
+ gps->mat_nr = idx;
+ }
+ }
+ }
+ }
+
+ /* if not multiedit, exit loop*/
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ CTX_DATA_END;
+ }
+ else if (mode == GP_SEPARATE_LAYER) {
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+ if (gpl) {
+ /* try to set a new active layer in source datablock */
+ if (gpl->prev) {
+ BKE_gpencil_layer_setactive(gpd_src, gpl->prev);
+ }
+ else if (gpl->next) {
+ BKE_gpencil_layer_setactive(gpd_src, gpl->next);
+ }
+ /* unlink from source datablock */
+ BLI_remlink(&gpd_src->layers, gpl);
+ gpl->prev = gpl->next = NULL;
+ /* relink to destination datablock */
+ 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) {
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+ ma = give_current_material(ob, gps->mat_nr + 1);
+ gps->mat_nr = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma);
+ }
+ }
+ }
+ }
+
+ 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);
+
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_stroke_separate(wmOperatorType *ot)
{
- static const EnumPropertyItem separate_type[] = {
- {GP_SEPARATE_POINT, "POINT", 0, "Selected Points", "Separate the selected points"},
- {GP_SEPARATE_STROKE, "STROKE", 0, "Selected Strokes", "Separate the selected strokes"},
- {GP_SEPARATE_LAYER, "LAYER", 0, "Active Layer", "Separate the strokes of the current layer"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Separate Strokes";
- ot->idname = "GPENCIL_OT_stroke_separate";
- ot->description = "Separate the selected strokes or layer in a new grease pencil object";
-
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = gp_stroke_separate_exec;
- ot->poll = gp_strokes_edit3d_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "mode", separate_type, GP_SEPARATE_POINT, "Mode", "");
+ static const EnumPropertyItem separate_type[] = {
+ {GP_SEPARATE_POINT, "POINT", 0, "Selected Points", "Separate the selected points"},
+ {GP_SEPARATE_STROKE, "STROKE", 0, "Selected Strokes", "Separate the selected strokes"},
+ {GP_SEPARATE_LAYER, "LAYER", 0, "Active Layer", "Separate the strokes of the current layer"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Separate Strokes";
+ ot->idname = "GPENCIL_OT_stroke_separate";
+ ot->description = "Separate the selected strokes or layer in a new grease pencil object";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = gp_stroke_separate_exec;
+ ot->poll = gp_strokes_edit3d_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "mode", separate_type, GP_SEPARATE_POINT, "Mode", "");
}
/* ***************** Split Strokes ********************** */
static int gp_stroke_split_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = CTX_data_active_object(C);
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDspoint *pt;
- int i;
-
- /* sanity checks */
- if (ELEM(NULL, gpd)) {
- return OPERATOR_CANCELLED;
- }
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
-
- /* loop strokes and split parts */
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- 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))) {
- bGPDstroke *gps, *gpsn;
-
- if (gpf == NULL) {
- continue;
- }
-
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
-
- /* 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;
- }
- /* split selected strokes */
- if (gps->flag & GP_STROKE_SELECT) {
- /* make copy of source stroke */
- bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps);
-
- /* link to same frame */
- BLI_addtail(&gpf->strokes, gps_dst);
-
- /* invert selection status of all points in destination stroke */
- for (i = 0, pt = gps_dst->points; i < gps_dst->totpoints; i++, pt++) {
- pt->flag ^= GP_SPOINT_SELECT;
- }
-
- /* delete selected points from destination stroke */
- 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);
- }
- }
- /* select again tagged points */
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- bGPDspoint *ptn = gps->points;
- for (int i2 = 0; i2 < gps->totpoints; i2++, ptn++) {
- if (ptn->flag & GP_SPOINT_TAG) {
- ptn->flag |= GP_SPOINT_SELECT;
- ptn->flag &= ~GP_SPOINT_TAG;
- }
- }
- }
- }
-
- /* if not multiedit, exit loop*/
- if (!is_multiedit) {
- break;
- }
- }
- }
- CTX_DATA_END;
-
- 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;
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDspoint *pt;
+ int i;
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+
+ /* loop strokes and split parts */
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ 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))) {
+ bGPDstroke *gps, *gpsn;
+
+ if (gpf == NULL) {
+ continue;
+ }
+
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ /* 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;
+ }
+ /* split selected strokes */
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* make copy of source stroke */
+ bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps);
+
+ /* link to same frame */
+ BLI_addtail(&gpf->strokes, gps_dst);
+
+ /* invert selection status of all points in destination stroke */
+ for (i = 0, pt = gps_dst->points; i < gps_dst->totpoints; i++, pt++) {
+ pt->flag ^= GP_SPOINT_SELECT;
+ }
+
+ /* delete selected points from destination stroke */
+ 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);
+ }
+ }
+ /* select again tagged points */
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ bGPDspoint *ptn = gps->points;
+ for (int i2 = 0; i2 < gps->totpoints; i2++, ptn++) {
+ if (ptn->flag & GP_SPOINT_TAG) {
+ ptn->flag |= GP_SPOINT_SELECT;
+ ptn->flag &= ~GP_SPOINT_TAG;
+ }
+ }
+ }
+ }
+
+ /* if not multiedit, exit loop*/
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ 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_stroke_split(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Split Strokes";
- ot->idname = "GPENCIL_OT_stroke_split";
- ot->description = "Split selected points as new stroke on same frame";
+ /* identifiers */
+ ot->name = "Split Strokes";
+ ot->idname = "GPENCIL_OT_stroke_split";
+ ot->description = "Split selected points as new stroke on same frame";
- /* callbacks */
- ot->exec = gp_stroke_split_exec;
- ot->poll = gp_strokes_edit3d_poll;
+ /* callbacks */
+ ot->exec = gp_stroke_split_exec;
+ ot->poll = gp_strokes_edit3d_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int gp_stroke_smooth_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
- /* sanity checks */
- if (ELEM(NULL, gpd))
- return OPERATOR_CANCELLED;
+ /* sanity checks */
+ if (ELEM(NULL, gpd))
+ return OPERATOR_CANCELLED;
- gp_smooth_stroke(C, op);
+ gp_smooth_stroke(C, op);
- /* 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);
+ /* 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;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_stroke_smooth(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Smooth Stroke";
- ot->idname = "GPENCIL_OT_stroke_smooth";
- ot->description = "Smooth selected strokes";
-
- /* api callbacks */
- ot->exec = gp_stroke_smooth_exec;
- ot->poll = gp_active_layer_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_int(ot->srna, "repeat", 1, 1, 10, "Repeat", "", 1, 5);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 2.0f, "Factor", "", 0.0f, 2.0f);
- RNA_def_boolean(
- ot->srna, "only_selected", true, "Selected Points",
- "Smooth only selected points in the stroke");
- RNA_def_boolean(ot->srna, "smooth_position", true, "Position", "");
- RNA_def_boolean(ot->srna, "smooth_thickness", true, "Thickness", "");
- RNA_def_boolean(ot->srna, "smooth_strength", false, "Strength", "");
- RNA_def_boolean(ot->srna, "smooth_uv", false, "UV", "");
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Smooth Stroke";
+ ot->idname = "GPENCIL_OT_stroke_smooth";
+ ot->description = "Smooth selected strokes";
+
+ /* api callbacks */
+ ot->exec = gp_stroke_smooth_exec;
+ ot->poll = gp_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_int(ot->srna, "repeat", 1, 1, 10, "Repeat", "", 1, 5);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 2.0f, "Factor", "", 0.0f, 2.0f);
+ RNA_def_boolean(ot->srna,
+ "only_selected",
+ true,
+ "Selected Points",
+ "Smooth only selected points in the stroke");
+ RNA_def_boolean(ot->srna, "smooth_position", true, "Position", "");
+ RNA_def_boolean(ot->srna, "smooth_thickness", true, "Thickness", "");
+ RNA_def_boolean(ot->srna, "smooth_strength", false, "Strength", "");
+ RNA_def_boolean(ot->srna, "smooth_uv", false, "UV", "");
}
/* smart stroke cutter for trimming stroke ends */
struct GP_SelectLassoUserData {
- rcti rect;
- const int(*mcords)[2];
- int mcords_len;
+ rcti rect;
+ const int (*mcords)[2];
+ int mcords_len;
};
-static bool gpencil_test_lasso(
- bGPDstroke *gps, bGPDspoint *pt,
- const GP_SpaceConversion *gsc, const float diff_mat[4][4],
- void *user_data)
+static bool gpencil_test_lasso(bGPDstroke *gps,
+ bGPDspoint *pt,
+ const GP_SpaceConversion *gsc,
+ const float diff_mat[4][4],
+ void *user_data)
{
- const struct GP_SelectLassoUserData *data = user_data;
- bGPDspoint pt2;
- int x0, y0;
- gp_point_to_parent_space(pt, diff_mat, &pt2);
- 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));
+ const struct GP_SelectLassoUserData *data = user_data;
+ bGPDspoint pt2;
+ int x0, y0;
+ gp_point_to_parent_space(pt, diff_mat, &pt2);
+ 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));
}
-typedef bool(*GPencilTestFn)(
- bGPDstroke *gps, bGPDspoint *pt,
- const GP_SpaceConversion *gsc, const float diff_mat[4][4], void *user_data);
+typedef bool (*GPencilTestFn)(bGPDstroke *gps,
+ bGPDspoint *pt,
+ const GP_SpaceConversion *gsc,
+ const float diff_mat[4][4],
+ void *user_data);
static void gpencil_cutter_dissolve(bGPDlayer *hit_layer, bGPDstroke *hit_stroke)
{
- bGPDspoint *pt = NULL;
- bGPDspoint *pt1 = NULL;
- int i;
-
- bGPDstroke *gpsn = hit_stroke->next;
-
- int totselect = 0;
- for (i = 0, pt = hit_stroke->points; i < hit_stroke->totpoints; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT) {
- totselect++;
- }
- }
-
- /* if all points selected delete or only 2 points and 1 selected */
- if (((totselect == 1) && (hit_stroke->totpoints == 2)) ||
- (hit_stroke->totpoints == totselect))
- {
- BLI_remlink(&hit_layer->actframe->strokes, hit_stroke);
- BKE_gpencil_free_stroke(hit_stroke);
- hit_stroke = NULL;
- }
-
- /* if very small distance delete */
- if ((hit_stroke) && (hit_stroke->totpoints == 2)) {
- pt = &hit_stroke->points[0];
- pt1 = &hit_stroke->points[1];
- if (len_v3v3(&pt->x, &pt1->x) < 0.001f) {
- BLI_remlink(&hit_layer->actframe->strokes, hit_stroke);
- BKE_gpencil_free_stroke(hit_stroke);
- hit_stroke = NULL;
- }
- }
-
- if (hit_stroke) {
- /* tag and dissolve (untag new points) */
- for (i = 0, pt = hit_stroke->points; i < hit_stroke->totpoints; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT) {
- pt->flag &= ~GP_SPOINT_SELECT;
- pt->flag |= GP_SPOINT_TAG;
- }
- else if (pt->flag & GP_SPOINT_TAG) {
- pt->flag &= ~GP_SPOINT_TAG;
- }
- }
- gp_stroke_delete_tagged_points(
- hit_layer->actframe, hit_stroke, gpsn, GP_SPOINT_TAG, false, 1);
- }
+ bGPDspoint *pt = NULL;
+ bGPDspoint *pt1 = NULL;
+ int i;
+
+ bGPDstroke *gpsn = hit_stroke->next;
+
+ int totselect = 0;
+ for (i = 0, pt = hit_stroke->points; i < hit_stroke->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ totselect++;
+ }
+ }
+
+ /* if all points selected delete or only 2 points and 1 selected */
+ if (((totselect == 1) && (hit_stroke->totpoints == 2)) || (hit_stroke->totpoints == totselect)) {
+ BLI_remlink(&hit_layer->actframe->strokes, hit_stroke);
+ BKE_gpencil_free_stroke(hit_stroke);
+ hit_stroke = NULL;
+ }
+
+ /* if very small distance delete */
+ if ((hit_stroke) && (hit_stroke->totpoints == 2)) {
+ pt = &hit_stroke->points[0];
+ pt1 = &hit_stroke->points[1];
+ if (len_v3v3(&pt->x, &pt1->x) < 0.001f) {
+ BLI_remlink(&hit_layer->actframe->strokes, hit_stroke);
+ BKE_gpencil_free_stroke(hit_stroke);
+ hit_stroke = NULL;
+ }
+ }
+
+ if (hit_stroke) {
+ /* tag and dissolve (untag new points) */
+ for (i = 0, pt = hit_stroke->points; i < hit_stroke->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ pt->flag |= GP_SPOINT_TAG;
+ }
+ else if (pt->flag & GP_SPOINT_TAG) {
+ pt->flag &= ~GP_SPOINT_TAG;
+ }
+ }
+ gp_stroke_delete_tagged_points(hit_layer->actframe, hit_stroke, gpsn, GP_SPOINT_TAG, false, 1);
+ }
}
-static int gpencil_cutter_lasso_select(
- bContext *C, wmOperator *op,
- GPencilTestFn is_inside_fn, void *user_data)
+static int gpencil_cutter_lasso_select(bContext *C,
+ wmOperator *op,
+ GPencilTestFn is_inside_fn,
+ void *user_data)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- ScrArea *sa = CTX_wm_area(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- const float scale = ts->gp_sculpt.isect_threshold;
-
- bGPDspoint *pt;
- int i;
- GP_SpaceConversion gsc = { NULL };
-
- bool changed = false;
-
- /* sanity checks */
- if (sa == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active area");
- return OPERATOR_CANCELLED;
- }
-
- /* init space conversion stuff */
- gp_point_conversion_init(C, &gsc);
-
- /* deselect all strokes first */
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- pt->flag &= ~GP_SPOINT_SELECT;
- }
-
- gps->flag &= ~GP_STROKE_SELECT;
- }
- CTX_DATA_END;
-
- /* select points */
- GP_EDITABLE_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
- {
- int tot_inside = 0;
- const int oldtot = gps->totpoints;
- for (i = 0; i < gps->totpoints; i++) {
- pt = &gps->points[i];
- if ((pt->flag & GP_SPOINT_SELECT) || (pt->flag & GP_SPOINT_TAG)) {
- continue;
- }
- /* convert point coords to screenspace */
- const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data);
- if (is_inside) {
- tot_inside++;
- changed = true;
- pt->flag |= GP_SPOINT_SELECT;
- gps->flag |= GP_STROKE_SELECT;
- float r_hita[3], r_hitb[3];
- if (gps->totpoints > 1) {
- ED_gpencil_select_stroke_segment(
- gpl, gps, pt, true, true, scale, r_hita, r_hitb);
- }
- /* avoid infinite loops */
- if (gps->totpoints > oldtot) {
- break;
- }
- }
- }
- /* if mark all points inside lasso set to remove all stroke */
- if ((tot_inside == oldtot) ||
- ((tot_inside == 1) && (oldtot == 2)))
- {
- for (i = 0; i < gps->totpoints; i++) {
- pt = &gps->points[i];
- pt->flag |= GP_SPOINT_SELECT;
- }
- }
- }
- GP_EDITABLE_STROKES_END(gpstroke_iter);
-
- /* dissolve selected points */
- bGPDstroke *gpsn;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- bGPDframe *gpf = gpl->actframe;
- if (gpf == NULL) {
- continue;
- }
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
- if (gps->flag & GP_STROKE_SELECT) {
- gpencil_cutter_dissolve(gpl, gps);
- }
- }
- }
-
- /* updates */
- if (changed) {
- DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | 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);
- }
-
- return OPERATOR_FINISHED;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ const float scale = ts->gp_sculpt.isect_threshold;
+
+ bGPDspoint *pt;
+ int i;
+ GP_SpaceConversion gsc = {NULL};
+
+ bool changed = false;
+
+ /* sanity checks */
+ if (sa == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active area");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* init space conversion stuff */
+ gp_point_conversion_init(C, &gsc);
+
+ /* deselect all strokes first */
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ CTX_DATA_END;
+
+ /* select points */
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ int tot_inside = 0;
+ const int oldtot = gps->totpoints;
+ for (i = 0; i < gps->totpoints; i++) {
+ pt = &gps->points[i];
+ if ((pt->flag & GP_SPOINT_SELECT) || (pt->flag & GP_SPOINT_TAG)) {
+ continue;
+ }
+ /* convert point coords to screenspace */
+ const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data);
+ if (is_inside) {
+ tot_inside++;
+ changed = true;
+ pt->flag |= GP_SPOINT_SELECT;
+ gps->flag |= GP_STROKE_SELECT;
+ float r_hita[3], r_hitb[3];
+ if (gps->totpoints > 1) {
+ ED_gpencil_select_stroke_segment(gpl, gps, pt, true, true, scale, r_hita, r_hitb);
+ }
+ /* avoid infinite loops */
+ if (gps->totpoints > oldtot) {
+ break;
+ }
+ }
+ }
+ /* if mark all points inside lasso set to remove all stroke */
+ if ((tot_inside == oldtot) || ((tot_inside == 1) && (oldtot == 2))) {
+ for (i = 0; i < gps->totpoints; i++) {
+ pt = &gps->points[i];
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ }
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
+
+ /* dissolve selected points */
+ bGPDstroke *gpsn;
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ bGPDframe *gpf = gpl->actframe;
+ if (gpf == NULL) {
+ continue;
+ }
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+ if (gps->flag & GP_STROKE_SELECT) {
+ gpencil_cutter_dissolve(gpl, gps);
+ }
+ }
+ }
+
+ /* updates */
+ if (changed) {
+ DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | 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);
+ }
+
+ return OPERATOR_FINISHED;
}
static bool gpencil_cutter_poll(bContext *C)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
- if (GPENCIL_PAINT_MODE(gpd)) {
- if (gpd->layers.first)
- return true;
- }
+ if (GPENCIL_PAINT_MODE(gpd)) {
+ if (gpd->layers.first)
+ return true;
+ }
- return false;
+ return false;
}
static int gpencil_cutter_exec(bContext *C, wmOperator *op)
{
- ScrArea *sa = CTX_wm_area(C);
- /* sanity checks */
- if (sa == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active area");
- return OPERATOR_CANCELLED;
- }
+ ScrArea *sa = CTX_wm_area(C);
+ /* sanity checks */
+ if (sa == 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);
+ struct GP_SelectLassoUserData data = {0};
+ data.mcords = WM_gesture_lasso_path_to_array(C, op, &data.mcords_len);
- /* Sanity check. */
- if (data.mcords == NULL) {
- return OPERATOR_PASS_THROUGH;
- }
+ /* Sanity check. */
+ if (data.mcords == NULL) {
+ return OPERATOR_PASS_THROUGH;
+ }
- /* Compute boundbox of lasso (for faster testing later). */
- BLI_lasso_boundbox(&data.rect, data.mcords, data.mcords_len);
+ /* Compute boundbox of lasso (for faster testing later). */
+ BLI_lasso_boundbox(&data.rect, data.mcords, data.mcords_len);
- gpencil_cutter_lasso_select(C, op, gpencil_test_lasso, &data);
+ gpencil_cutter_lasso_select(C, op, gpencil_test_lasso, &data);
- MEM_freeN((void *)data.mcords);
+ MEM_freeN((void *)data.mcords);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_stroke_cutter(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Stroke Cutter";
- ot->description = "Select section and cut";
- ot->idname = "GPENCIL_OT_stroke_cutter";
-
- /* callbacks */
- ot->invoke = WM_gesture_lasso_invoke;
- ot->modal = WM_gesture_lasso_modal;
- ot->exec = gpencil_cutter_exec;
- ot->poll = gpencil_cutter_poll;
- ot->cancel = WM_gesture_lasso_cancel;
-
- /* flag */
- ot->flag = OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
-
- /* properties */
- WM_operator_properties_gesture_lasso(ot);
+ /* identifiers */
+ ot->name = "Stroke Cutter";
+ ot->description = "Select section and cut";
+ ot->idname = "GPENCIL_OT_stroke_cutter";
+
+ /* callbacks */
+ ot->invoke = WM_gesture_lasso_invoke;
+ ot->modal = WM_gesture_lasso_modal;
+ ot->exec = gpencil_cutter_exec;
+ ot->poll = gpencil_cutter_poll;
+ ot->cancel = WM_gesture_lasso_cancel;
+
+ /* flag */
+ ot->flag = OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+
+ /* properties */
+ WM_operator_properties_gesture_lasso(ot);
}
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index 76d15557055..8d3137ed3db 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -79,373 +79,393 @@
#define LEAK_HORZ 0
#define LEAK_VERT 1
-
- /* Temporary fill operation data (op->customdata) */
+/* Temporary fill operation data (op->customdata) */
typedef struct tGPDfill {
- bContext *C;
- struct Main *bmain;
- struct Depsgraph *depsgraph;
- /** window where painting originated */
- struct wmWindow *win;
- /** current scene from context */
- struct Scene *scene;
- /** current active gp object */
- struct Object *ob;
- /** area where painting originated */
- struct ScrArea *sa;
- /** region where painting originated */
- struct RegionView3D *rv3d;
- /** view3 where painting originated */
- struct View3D *v3d;
- /** region where painting originated */
- struct ARegion *ar;
- /** current GP datablock */
- struct bGPdata *gpd;
- /** current material */
- struct Material *mat;
- /** layer */
- struct bGPDlayer *gpl;
- /** frame */
- struct bGPDframe *gpf;
-
- /** flags */
- short flag;
- /** avoid too fast events */
- short oldkey;
- /** send to back stroke */
- bool on_back;
-
- /** mouse fill center position */
- int center[2];
- /** windows width */
- int sizex;
- /** window height */
- int sizey;
- /** lock to viewport axis */
- int lock_axis;
-
- /** number of pixel to consider the leak is too small (x 2) */
- short fill_leak;
- /** factor for transparency */
- float fill_threshold;
- /** number of simplify steps */
- int fill_simplylvl;
- /** boundary limits drawing mode */
- int fill_draw_mode;
- /* scaling factor */
- short fill_factor;
-
- /** number of elements currently in cache */
- short sbuffer_size;
- /** temporary points */
- void *sbuffer;
- /** depth array for reproject */
- float *depth_arr;
-
- /** temp image */
- Image *ima;
- /** temp points data */
- BLI_Stack *stack;
- /** handle for drawing strokes while operator is running 3d stuff */
- void *draw_handle_3d;
-
- /* tmp size x */
- int bwinx;
- /* tmp size y */
- int bwiny;
- rcti brect;
+ bContext *C;
+ struct Main *bmain;
+ struct Depsgraph *depsgraph;
+ /** window where painting originated */
+ struct wmWindow *win;
+ /** current scene from context */
+ struct Scene *scene;
+ /** current active gp object */
+ struct Object *ob;
+ /** area where painting originated */
+ struct ScrArea *sa;
+ /** region where painting originated */
+ struct RegionView3D *rv3d;
+ /** view3 where painting originated */
+ struct View3D *v3d;
+ /** region where painting originated */
+ struct ARegion *ar;
+ /** current GP datablock */
+ struct bGPdata *gpd;
+ /** current material */
+ struct Material *mat;
+ /** layer */
+ struct bGPDlayer *gpl;
+ /** frame */
+ struct bGPDframe *gpf;
+
+ /** flags */
+ short flag;
+ /** avoid too fast events */
+ short oldkey;
+ /** send to back stroke */
+ bool on_back;
+
+ /** mouse fill center position */
+ int center[2];
+ /** windows width */
+ int sizex;
+ /** window height */
+ int sizey;
+ /** lock to viewport axis */
+ int lock_axis;
+
+ /** number of pixel to consider the leak is too small (x 2) */
+ short fill_leak;
+ /** factor for transparency */
+ float fill_threshold;
+ /** number of simplify steps */
+ int fill_simplylvl;
+ /** boundary limits drawing mode */
+ int fill_draw_mode;
+ /* scaling factor */
+ short fill_factor;
+
+ /** number of elements currently in cache */
+ short sbuffer_size;
+ /** temporary points */
+ void *sbuffer;
+ /** depth array for reproject */
+ float *depth_arr;
+
+ /** temp image */
+ Image *ima;
+ /** temp points data */
+ BLI_Stack *stack;
+ /** handle for drawing strokes while operator is running 3d stuff */
+ void *draw_handle_3d;
+
+ /* tmp size x */
+ int bwinx;
+ /* tmp size y */
+ int bwiny;
+ rcti brect;
} tGPDfill;
-
/* draw a given stroke using same thickness and color for all points */
-static void gp_draw_basic_stroke(
- tGPDfill *tgpf, bGPDstroke *gps, const float diff_mat[4][4],
- const bool cyclic, const float ink[4], const int flag, const float thershold)
+static void gp_draw_basic_stroke(tGPDfill *tgpf,
+ bGPDstroke *gps,
+ const float diff_mat[4][4],
+ const bool cyclic,
+ const float ink[4],
+ const int flag,
+ const float thershold)
{
- bGPDspoint *points = gps->points;
-
- Material *ma = tgpf->mat;
- MaterialGPencilStyle *gp_style = ma->gp_style;
-
- int totpoints = gps->totpoints;
- float fpt[3];
- float col[4];
-
- copy_v4_v4(col, ink);
-
- /* if cyclic needs more vertex */
- int cyclic_add = (cyclic) ? 1 : 0;
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
-
- /* draw stroke curve */
- GPU_line_width(1.0f);
- immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints + cyclic_add);
- const bGPDspoint *pt = points;
-
- for (int i = 0; i < totpoints; i++, pt++) {
-
- if (flag & GP_BRUSH_FILL_HIDE) {
- float alpha = gp_style->stroke_rgba[3] * pt->strength;
- CLAMP(alpha, 0.0f, 1.0f);
- col[3] = alpha <= thershold ? 0.0f : 1.0f;
- }
- else {
- col[3] = 1.0f;
- }
- /* set point */
- immAttr4fv(color, col);
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- immVertex3fv(pos, fpt);
- }
-
- if (cyclic && totpoints > 2) {
- /* draw line to first point to complete the cycle */
- immAttr4fv(color, col);
- mul_v3_m4v3(fpt, diff_mat, &points->x);
- immVertex3fv(pos, fpt);
- }
-
- immEnd();
- immUnbindProgram();
+ bGPDspoint *points = gps->points;
+
+ Material *ma = tgpf->mat;
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+
+ int totpoints = gps->totpoints;
+ float fpt[3];
+ float col[4];
+
+ copy_v4_v4(col, ink);
+
+ /* if cyclic needs more vertex */
+ int cyclic_add = (cyclic) ? 1 : 0;
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
+ /* draw stroke curve */
+ GPU_line_width(1.0f);
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints + cyclic_add);
+ const bGPDspoint *pt = points;
+
+ for (int i = 0; i < totpoints; i++, pt++) {
+
+ if (flag & GP_BRUSH_FILL_HIDE) {
+ float alpha = gp_style->stroke_rgba[3] * pt->strength;
+ CLAMP(alpha, 0.0f, 1.0f);
+ col[3] = alpha <= thershold ? 0.0f : 1.0f;
+ }
+ else {
+ col[3] = 1.0f;
+ }
+ /* set point */
+ immAttr4fv(color, col);
+ mul_v3_m4v3(fpt, diff_mat, &pt->x);
+ immVertex3fv(pos, fpt);
+ }
+
+ if (cyclic && totpoints > 2) {
+ /* draw line to first point to complete the cycle */
+ immAttr4fv(color, col);
+ mul_v3_m4v3(fpt, diff_mat, &points->x);
+ immVertex3fv(pos, fpt);
+ }
+
+ immEnd();
+ immUnbindProgram();
}
/* loop all layers */
static void gp_draw_datablock(tGPDfill *tgpf, const float ink[4])
{
- /* duplicated: etempFlags */
- enum {
- GP_DRAWFILLS_NOSTATUS = (1 << 0), /* don't draw status info */
- GP_DRAWFILLS_ONLY3D = (1 << 1), /* only draw 3d-strokes */
- };
-
- Object *ob = tgpf->ob;
- bGPdata *gpd = tgpf->gpd;
- int cfra_eval = (int)DEG_get_ctime(tgpf->depsgraph);
-
- tGPDdraw tgpw;
- tgpw.rv3d = tgpf->rv3d;
- tgpw.depsgraph = tgpf->depsgraph;
- tgpw.ob = ob;
- tgpw.gpd = gpd;
- tgpw.offsx = 0;
- tgpw.offsy = 0;
- tgpw.winx = tgpf->ar->winx;
- tgpw.winy = tgpf->ar->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) {
- /* calculate parent position */
- ED_gpencil_parent_location(tgpw.depsgraph, ob, gpd, gpl, tgpw.diff_mat);
-
- /* do not draw layer if hidden */
- if (gpl->flag & GP_LAYER_HIDE)
- continue;
-
- /* 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);
- }
- }
-
- /* get frame to draw */
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV);
- if (gpf == NULL)
- continue;
-
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- /* 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)) {
- continue;
- }
-
- tgpw.gps = gps;
- tgpw.gpl = gpl;
- tgpw.gpf = gpf;
- tgpw.t_gpf = gpf;
-
- /* reduce thickness to avoid gaps */
- tgpw.is_fill_stroke = (tgpf->fill_draw_mode == GP_FILL_DMODE_CONTROL) ? false : true ;
- tgpw.lthick = gpl->line_change;
- tgpw.opacity = 1.0;
- copy_v4_v4(tgpw.tintcolor, ink);
- 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)
- {
- 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)
- {
- gp_draw_basic_stroke(
- tgpf, gps, tgpw.diff_mat, gps->flag & GP_STROKE_CYCLIC, ink,
- tgpf->flag, tgpf->fill_threshold);
- }
- }
- }
-
- GPU_blend(false);
+ /* duplicated: etempFlags */
+ enum {
+ GP_DRAWFILLS_NOSTATUS = (1 << 0), /* don't draw status info */
+ GP_DRAWFILLS_ONLY3D = (1 << 1), /* only draw 3d-strokes */
+ };
+
+ Object *ob = tgpf->ob;
+ bGPdata *gpd = tgpf->gpd;
+ int cfra_eval = (int)DEG_get_ctime(tgpf->depsgraph);
+
+ tGPDdraw tgpw;
+ tgpw.rv3d = tgpf->rv3d;
+ tgpw.depsgraph = tgpf->depsgraph;
+ tgpw.ob = ob;
+ tgpw.gpd = gpd;
+ tgpw.offsx = 0;
+ tgpw.offsy = 0;
+ tgpw.winx = tgpf->ar->winx;
+ tgpw.winy = tgpf->ar->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) {
+ /* calculate parent position */
+ ED_gpencil_parent_location(tgpw.depsgraph, ob, gpd, gpl, tgpw.diff_mat);
+
+ /* do not draw layer if hidden */
+ if (gpl->flag & GP_LAYER_HIDE)
+ continue;
+
+ /* 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);
+ }
+ }
+
+ /* get frame to draw */
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV);
+ if (gpf == NULL)
+ continue;
+
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* 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)) {
+ continue;
+ }
+
+ tgpw.gps = gps;
+ tgpw.gpl = gpl;
+ tgpw.gpf = gpf;
+ tgpw.t_gpf = gpf;
+
+ /* reduce thickness to avoid gaps */
+ tgpw.is_fill_stroke = (tgpf->fill_draw_mode == GP_FILL_DMODE_CONTROL) ? false : true;
+ tgpw.lthick = gpl->line_change;
+ tgpw.opacity = 1.0;
+ copy_v4_v4(tgpw.tintcolor, ink);
+ 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) {
+ 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) {
+ gp_draw_basic_stroke(tgpf,
+ gps,
+ tgpw.diff_mat,
+ gps->flag & GP_STROKE_CYCLIC,
+ ink,
+ tgpf->flag,
+ tgpf->fill_threshold);
+ }
+ }
+ }
+
+ GPU_blend(false);
}
/* draw strokes in offscreen buffer */
static bool gp_render_offscreen(tGPDfill *tgpf)
{
- bool is_ortho = false;
- float winmat[4][4];
-
- if (!tgpf->gpd) {
- return false;
- }
-
- /* 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);
-
- /* save new size */
- tgpf->sizex = (int)tgpf->ar->winx;
- tgpf->sizey = (int)tgpf->ar->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);
- round_v2i_v2fl(tgpf->center, center);
-
- char err_out[256] = "unknown";
- GPUOffScreen *offscreen = GPU_offscreen_create(tgpf->sizex, tgpf->sizey, 0, true, false, err_out);
- if (offscreen == NULL) {
- printf("GPencil - Fill - Unable to create fill buffer\n");
- return false;
- }
-
- GPU_offscreen_bind(offscreen, true);
- uint flag = IB_rect | IB_rectfloat;
- ImBuf *ibuf = IMB_allocImBuf(tgpf->sizex, tgpf->sizey, 32, flag);
-
- rctf viewplane;
- float clip_start, clip_end;
-
- is_ortho = ED_view3d_viewplane_get(
- tgpf->depsgraph, tgpf->v3d, tgpf->rv3d, tgpf->sizex, tgpf->sizey,
- &viewplane, &clip_start, &clip_end, NULL);
- if (is_ortho) {
- orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clip_end, clip_end);
- }
- else {
- perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clip_start, clip_end);
- }
-
- GPU_matrix_push_projection();
- GPU_matrix_identity_set();
- GPU_matrix_push();
- GPU_matrix_identity_set();
-
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- ED_view3d_update_viewmat(
- tgpf->depsgraph, tgpf->scene, tgpf->v3d, tgpf->ar,
- NULL, winmat, NULL);
- /* set for opengl */
- GPU_matrix_projection_set(tgpf->rv3d->winmat);
- GPU_matrix_set(tgpf->rv3d->viewmat);
-
- /* draw strokes */
- float ink[4] = {1.0f, 0.0f, 0.0f, 1.0f};
- gp_draw_datablock(tgpf, ink);
-
- GPU_matrix_pop_projection();
- GPU_matrix_pop();
-
- /* create a image to see result of template */
- if (ibuf->rect_float) {
- GPU_offscreen_read_pixels(offscreen, GL_FLOAT, ibuf->rect_float);
- }
- else if (ibuf->rect) {
- GPU_offscreen_read_pixels(offscreen, GL_UNSIGNED_BYTE, ibuf->rect);
- }
- if (ibuf->rect_float && ibuf->rect) {
- IMB_rect_from_float(ibuf);
- }
-
- tgpf->ima = BKE_image_add_from_imbuf(tgpf->bmain, ibuf, "GP_fill");
- tgpf->ima->id.tag |= LIB_TAG_DOIT;
-
- BKE_image_release_ibuf(tgpf->ima, ibuf, NULL);
-
- /* switch back to window-system-provided framebuffer */
- GPU_offscreen_unbind(offscreen, true);
- GPU_offscreen_free(offscreen);
-
- return true;
+ bool is_ortho = false;
+ float winmat[4][4];
+
+ if (!tgpf->gpd) {
+ return false;
+ }
+
+ /* 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);
+
+ /* save new size */
+ tgpf->sizex = (int)tgpf->ar->winx;
+ tgpf->sizey = (int)tgpf->ar->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);
+ round_v2i_v2fl(tgpf->center, center);
+
+ char err_out[256] = "unknown";
+ GPUOffScreen *offscreen = GPU_offscreen_create(
+ tgpf->sizex, tgpf->sizey, 0, true, false, err_out);
+ if (offscreen == NULL) {
+ printf("GPencil - Fill - Unable to create fill buffer\n");
+ return false;
+ }
+
+ GPU_offscreen_bind(offscreen, true);
+ uint flag = IB_rect | IB_rectfloat;
+ ImBuf *ibuf = IMB_allocImBuf(tgpf->sizex, tgpf->sizey, 32, flag);
+
+ rctf viewplane;
+ float clip_start, clip_end;
+
+ is_ortho = ED_view3d_viewplane_get(tgpf->depsgraph,
+ tgpf->v3d,
+ tgpf->rv3d,
+ tgpf->sizex,
+ tgpf->sizey,
+ &viewplane,
+ &clip_start,
+ &clip_end,
+ NULL);
+ if (is_ortho) {
+ orthographic_m4(winmat,
+ viewplane.xmin,
+ viewplane.xmax,
+ viewplane.ymin,
+ viewplane.ymax,
+ -clip_end,
+ clip_end);
+ }
+ else {
+ perspective_m4(winmat,
+ viewplane.xmin,
+ viewplane.xmax,
+ viewplane.ymin,
+ viewplane.ymax,
+ clip_start,
+ clip_end);
+ }
+
+ GPU_matrix_push_projection();
+ GPU_matrix_identity_set();
+ GPU_matrix_push();
+ GPU_matrix_identity_set();
+
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ ED_view3d_update_viewmat(tgpf->depsgraph, tgpf->scene, tgpf->v3d, tgpf->ar, NULL, winmat, NULL);
+ /* set for opengl */
+ GPU_matrix_projection_set(tgpf->rv3d->winmat);
+ GPU_matrix_set(tgpf->rv3d->viewmat);
+
+ /* draw strokes */
+ float ink[4] = {1.0f, 0.0f, 0.0f, 1.0f};
+ gp_draw_datablock(tgpf, ink);
+
+ GPU_matrix_pop_projection();
+ GPU_matrix_pop();
+
+ /* create a image to see result of template */
+ if (ibuf->rect_float) {
+ GPU_offscreen_read_pixels(offscreen, GL_FLOAT, ibuf->rect_float);
+ }
+ else if (ibuf->rect) {
+ GPU_offscreen_read_pixels(offscreen, GL_UNSIGNED_BYTE, ibuf->rect);
+ }
+ if (ibuf->rect_float && ibuf->rect) {
+ IMB_rect_from_float(ibuf);
+ }
+
+ tgpf->ima = BKE_image_add_from_imbuf(tgpf->bmain, ibuf, "GP_fill");
+ tgpf->ima->id.tag |= LIB_TAG_DOIT;
+
+ BKE_image_release_ibuf(tgpf->ima, ibuf, NULL);
+
+ /* switch back to window-system-provided framebuffer */
+ GPU_offscreen_unbind(offscreen, true);
+ GPU_offscreen_free(offscreen);
+
+ return true;
}
/* return pixel data (rgba) at index */
static void get_pixel(const ImBuf *ibuf, const int idx, float r_col[4])
{
- if (ibuf->rect_float) {
- const float *frgba = &ibuf->rect_float[idx * 4];
- copy_v4_v4(r_col, frgba);
- }
- else {
- /* XXX: This case probably doesn't happen, as we only write to the float buffer,
- * but we get compiler warnings about uninitialised vars otherwise
- */
- BLI_assert(!"gpencil_fill.c - get_pixel() non-float case is used!");
- zero_v4(r_col);
- }
+ if (ibuf->rect_float) {
+ const float *frgba = &ibuf->rect_float[idx * 4];
+ copy_v4_v4(r_col, frgba);
+ }
+ else {
+ /* XXX: This case probably doesn't happen, as we only write to the float buffer,
+ * but we get compiler warnings about uninitialised vars otherwise
+ */
+ BLI_assert(!"gpencil_fill.c - get_pixel() non-float case is used!");
+ zero_v4(r_col);
+ }
}
/* set pixel data (rgba) at index */
static void set_pixel(ImBuf *ibuf, int idx, const float col[4])
{
- //BLI_assert(idx <= ibuf->x * ibuf->y);
- if (ibuf->rect) {
- uint *rrect = &ibuf->rect[idx];
- uchar ccol[4];
-
- rgba_float_to_uchar(ccol, col);
- *rrect = *((uint *)ccol);
- }
-
- if (ibuf->rect_float) {
- float *rrectf = &ibuf->rect_float[idx * 4];
- copy_v4_v4(rrectf, col);
- }
+ //BLI_assert(idx <= ibuf->x * ibuf->y);
+ if (ibuf->rect) {
+ uint *rrect = &ibuf->rect[idx];
+ uchar ccol[4];
+
+ rgba_float_to_uchar(ccol, col);
+ *rrect = *((uint *)ccol);
+ }
+
+ if (ibuf->rect_float) {
+ float *rrectf = &ibuf->rect_float[idx * 4];
+ copy_v4_v4(rrectf, col);
+ }
}
/* check if the size of the leak is narrow to determine if the stroke is closed
@@ -460,96 +480,96 @@ static void set_pixel(ImBuf *ibuf, int idx, const float col[4])
*/
static bool is_leak_narrow(ImBuf *ibuf, const int maxpixel, int limit, int index, int type)
{
- float rgba[4];
- int i;
- int pt;
- bool t_a = false;
- bool t_b = false;
-
- /* Horizontal leak (check vertical pixels)
- * X
- * X
- * xB7
- * X
- * X
- */
- if (type == LEAK_HORZ) {
- /* pixels on top */
- for (i = 1; i <= limit; i++) {
- pt = index + (ibuf->x * i);
- if (pt <= maxpixel) {
- get_pixel(ibuf, pt, rgba);
- if (rgba[0] == 1.0f) {
- t_a = true;
- break;
- }
- }
- else {
- /* edge of image*/
- t_a = true;
- break;
- }
- }
- /* pixels on bottom */
- for (i = 1; i <= limit; i++) {
- pt = index - (ibuf->x * i);
- if (pt >= 0) {
- get_pixel(ibuf, pt, rgba);
- if (rgba[0] == 1.0f) {
- t_b = true;
- break;
- }
- }
- else {
- /* edge of image*/
- t_b = true;
- break;
- }
- }
- }
-
- /* Vertical leak (check horizontal pixels)
- *
- * XXXxB7XX
- */
- if (type == LEAK_VERT) {
- /* get pixel range of the row */
- int row = index / ibuf->x;
- int lowpix = row * ibuf->x;
- int higpix = lowpix + ibuf->x - 1;
-
- /* pixels to right */
- for (i = 0; i < limit; i++) {
- pt = index - (limit - i);
- if (pt >= lowpix) {
- get_pixel(ibuf, pt, rgba);
- if (rgba[0] == 1.0f) {
- t_a = true;
- break;
- }
- }
- else {
- t_a = true; /* edge of image*/
- break;
- }
- }
- /* pixels to left */
- for (i = 0; i < limit; i++) {
- pt = index + (limit - i);
- if (pt <= higpix) {
- get_pixel(ibuf, pt, rgba);
- if (rgba[0] == 1.0f) {
- t_b = true;
- break;
- }
- }
- else {
- t_b = true; /* edge of image */
- break;
- }
- }
- }
- return (bool)(t_a && t_b);
+ float rgba[4];
+ int i;
+ int pt;
+ bool t_a = false;
+ bool t_b = false;
+
+ /* Horizontal leak (check vertical pixels)
+ * X
+ * X
+ * xB7
+ * X
+ * X
+ */
+ if (type == LEAK_HORZ) {
+ /* pixels on top */
+ for (i = 1; i <= limit; i++) {
+ pt = index + (ibuf->x * i);
+ if (pt <= maxpixel) {
+ get_pixel(ibuf, pt, rgba);
+ if (rgba[0] == 1.0f) {
+ t_a = true;
+ break;
+ }
+ }
+ else {
+ /* edge of image*/
+ t_a = true;
+ break;
+ }
+ }
+ /* pixels on bottom */
+ for (i = 1; i <= limit; i++) {
+ pt = index - (ibuf->x * i);
+ if (pt >= 0) {
+ get_pixel(ibuf, pt, rgba);
+ if (rgba[0] == 1.0f) {
+ t_b = true;
+ break;
+ }
+ }
+ else {
+ /* edge of image*/
+ t_b = true;
+ break;
+ }
+ }
+ }
+
+ /* Vertical leak (check horizontal pixels)
+ *
+ * XXXxB7XX
+ */
+ if (type == LEAK_VERT) {
+ /* get pixel range of the row */
+ int row = index / ibuf->x;
+ int lowpix = row * ibuf->x;
+ int higpix = lowpix + ibuf->x - 1;
+
+ /* pixels to right */
+ for (i = 0; i < limit; i++) {
+ pt = index - (limit - i);
+ if (pt >= lowpix) {
+ get_pixel(ibuf, pt, rgba);
+ if (rgba[0] == 1.0f) {
+ t_a = true;
+ break;
+ }
+ }
+ else {
+ t_a = true; /* edge of image*/
+ break;
+ }
+ }
+ /* pixels to left */
+ for (i = 0; i < limit; i++) {
+ pt = index + (limit - i);
+ if (pt <= higpix) {
+ get_pixel(ibuf, pt, rgba);
+ if (rgba[0] == 1.0f) {
+ t_b = true;
+ break;
+ }
+ }
+ else {
+ t_b = true; /* edge of image */
+ break;
+ }
+ }
+ }
+ return (bool)(t_a && t_b);
}
/* Boundary fill inside strokes
@@ -560,122 +580,122 @@ static bool is_leak_narrow(ImBuf *ibuf, const int maxpixel, int limit, int index
*/
static void gpencil_boundaryfill_area(tGPDfill *tgpf)
{
- ImBuf *ibuf;
- float rgba[4];
- void *lock;
- const float fill_col[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
- ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
- const int maxpixel = (ibuf->x * ibuf->y) - 1;
-
- BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__);
-
- /* calculate index of the seed point using the position of the mouse */
- int index = (tgpf->sizex * tgpf->center[1]) + tgpf->center[0];
- if ((index >= 0) && (index <= maxpixel)) {
- BLI_stack_push(stack, &index);
- }
-
- /* the fill use a stack to save the pixel list instead of the common recursive
- * 4-contact point method.
- * The problem with recursive calls is that for big fill areas, we can get max limit
- * of recursive calls and STACK_OVERFLOW error.
- *
- * The 4-contact point analyze the pixels to the left, right, bottom and top
- * -----------
- * | X |
- * | XoX |
- * | X |
- * -----------
- */
- while (!BLI_stack_is_empty(stack)) {
- int v;
-
- BLI_stack_pop(stack, &v);
-
- 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);
- }
- }
- /* 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 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);
- }
- }
- }
- }
- }
-
- /* release ibuf */
- if (ibuf) {
- BKE_image_release_ibuf(tgpf->ima, ibuf, lock);
- }
-
- tgpf->ima->id.tag |= LIB_TAG_DOIT;
- /* free temp stack data */
- BLI_stack_free(stack);
+ ImBuf *ibuf;
+ float rgba[4];
+ void *lock;
+ const float fill_col[4] = {0.0f, 1.0f, 0.0f, 1.0f};
+ ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
+ const int maxpixel = (ibuf->x * ibuf->y) - 1;
+
+ BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__);
+
+ /* calculate index of the seed point using the position of the mouse */
+ int index = (tgpf->sizex * tgpf->center[1]) + tgpf->center[0];
+ if ((index >= 0) && (index <= maxpixel)) {
+ BLI_stack_push(stack, &index);
+ }
+
+ /* the fill use a stack to save the pixel list instead of the common recursive
+ * 4-contact point method.
+ * The problem with recursive calls is that for big fill areas, we can get max limit
+ * of recursive calls and STACK_OVERFLOW error.
+ *
+ * The 4-contact point analyze the pixels to the left, right, bottom and top
+ * -----------
+ * | X |
+ * | XoX |
+ * | X |
+ * -----------
+ */
+ while (!BLI_stack_is_empty(stack)) {
+ int v;
+
+ BLI_stack_pop(stack, &v);
+
+ 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);
+ }
+ }
+ /* 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 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);
+ }
+ }
+ }
+ }
+ }
+
+ /* release ibuf */
+ if (ibuf) {
+ BKE_image_release_ibuf(tgpf->ima, ibuf, lock);
+ }
+
+ tgpf->ima->id.tag |= LIB_TAG_DOIT;
+ /* free temp stack data */
+ BLI_stack_free(stack);
}
/* clean external border of image to avoid infinite loops */
static void gpencil_clean_borders(tGPDfill *tgpf)
{
- ImBuf *ibuf;
- void *lock;
- const float fill_col[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
- ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
- int idx;
- int pixel = 0;
-
- /* horizontal lines */
- for (idx = 0; idx < ibuf->x; idx++) {
- /* bottom line */
- set_pixel(ibuf, idx, fill_col);
- /* top line */
- pixel = idx + (ibuf->x * (ibuf->y - 1));
- set_pixel(ibuf, pixel, fill_col);
- }
- /* vertical lines */
- for (idx = 0; idx < ibuf->y; idx++) {
- /* left line */
- set_pixel(ibuf, ibuf->x * idx, fill_col);
- /* right line */
- pixel = ibuf->x * idx + (ibuf->x - 1);
- set_pixel(ibuf, pixel, fill_col);
- }
-
- /* release ibuf */
- if (ibuf) {
- BKE_image_release_ibuf(tgpf->ima, ibuf, lock);
- }
-
- tgpf->ima->id.tag |= LIB_TAG_DOIT;
+ ImBuf *ibuf;
+ void *lock;
+ const float fill_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
+ int idx;
+ int pixel = 0;
+
+ /* horizontal lines */
+ for (idx = 0; idx < ibuf->x; idx++) {
+ /* bottom line */
+ set_pixel(ibuf, idx, fill_col);
+ /* top line */
+ pixel = idx + (ibuf->x * (ibuf->y - 1));
+ set_pixel(ibuf, pixel, fill_col);
+ }
+ /* vertical lines */
+ for (idx = 0; idx < ibuf->y; idx++) {
+ /* left line */
+ set_pixel(ibuf, ibuf->x * idx, fill_col);
+ /* right line */
+ pixel = ibuf->x * idx + (ibuf->x - 1);
+ set_pixel(ibuf, pixel, fill_col);
+ }
+
+ /* release ibuf */
+ if (ibuf) {
+ BKE_image_release_ibuf(tgpf->ima, ibuf, lock);
+ }
+
+ tgpf->ima->id.tag |= LIB_TAG_DOIT;
}
/* Naive dilate
@@ -691,96 +711,96 @@ static void gpencil_clean_borders(tGPDfill *tgpf)
*/
static void dilate(ImBuf *ibuf)
{
- BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__);
- const float green[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
- const int maxpixel = (ibuf->x * ibuf->y) - 1;
- /* detect pixels and expand into red areas */
- for (int v = maxpixel; v != 0; v--) {
- float color[4];
- int index;
- int tp = 0;
- int bm = 0;
- int lt = 0;
- int rt = 0;
- get_pixel(ibuf, v, color);
- if (color[1] == 1.0f) {
- /* pixel left */
- if (v - 1 >= 0) {
- index = v - 1;
- get_pixel(ibuf, index, color);
- if (color[0] == 1.0f) {
- BLI_stack_push(stack, &index);
- lt = index;
- }
- }
- /* pixel right */
- if (v + 1 <= maxpixel) {
- index = v + 1;
- get_pixel(ibuf, index, color);
- if (color[0] == 1.0f) {
- BLI_stack_push(stack, &index);
- rt = index;
- }
- }
- /* pixel top */
- if (v + ibuf->x <= maxpixel) {
- index = v + ibuf->x;
- get_pixel(ibuf, index, color);
- if (color[0] == 1.0f) {
- BLI_stack_push(stack, &index);
- tp = index;
- }
- }
- /* pixel bottom */
- if (v - ibuf->x >= 0) {
- index = v - ibuf->x;
- get_pixel(ibuf, index, color);
- if (color[0] == 1.0f) {
- BLI_stack_push(stack, &index);
- bm = index;
- }
- }
- /* pixel top-left */
- if (tp && lt) {
- index = tp - 1;
- get_pixel(ibuf, index, color);
- if (color[0] == 1.0f) {
- BLI_stack_push(stack, &index);
- }
- }
- /* pixel top-right */
- if (tp && rt) {
- index = tp + 1;
- get_pixel(ibuf, index, color);
- if (color[0] == 1.0f) {
- BLI_stack_push(stack, &index);
- }
- }
- /* pixel bottom-left */
- if (bm && lt) {
- index = bm - 1;
- get_pixel(ibuf, index, color);
- if (color[0] == 1.0f) {
- BLI_stack_push(stack, &index);
- }
- }
- /* pixel bottom-right */
- if (bm && rt) {
- index = bm + 1;
- get_pixel(ibuf, index, color);
- if (color[0] == 1.0f) {
- BLI_stack_push(stack, &index);
- }
- }
- }
- }
- /* set dilated pixels */
- while (!BLI_stack_is_empty(stack)) {
- int v;
- BLI_stack_pop(stack, &v);
- set_pixel(ibuf, v, green);
- }
- BLI_stack_free(stack);
+ BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__);
+ const float green[4] = {0.0f, 1.0f, 0.0f, 1.0f};
+ const int maxpixel = (ibuf->x * ibuf->y) - 1;
+ /* detect pixels and expand into red areas */
+ for (int v = maxpixel; v != 0; v--) {
+ float color[4];
+ int index;
+ int tp = 0;
+ int bm = 0;
+ int lt = 0;
+ int rt = 0;
+ get_pixel(ibuf, v, color);
+ if (color[1] == 1.0f) {
+ /* pixel left */
+ if (v - 1 >= 0) {
+ index = v - 1;
+ get_pixel(ibuf, index, color);
+ if (color[0] == 1.0f) {
+ BLI_stack_push(stack, &index);
+ lt = index;
+ }
+ }
+ /* pixel right */
+ if (v + 1 <= maxpixel) {
+ index = v + 1;
+ get_pixel(ibuf, index, color);
+ if (color[0] == 1.0f) {
+ BLI_stack_push(stack, &index);
+ rt = index;
+ }
+ }
+ /* pixel top */
+ if (v + ibuf->x <= maxpixel) {
+ index = v + ibuf->x;
+ get_pixel(ibuf, index, color);
+ if (color[0] == 1.0f) {
+ BLI_stack_push(stack, &index);
+ tp = index;
+ }
+ }
+ /* pixel bottom */
+ if (v - ibuf->x >= 0) {
+ index = v - ibuf->x;
+ get_pixel(ibuf, index, color);
+ if (color[0] == 1.0f) {
+ BLI_stack_push(stack, &index);
+ bm = index;
+ }
+ }
+ /* pixel top-left */
+ if (tp && lt) {
+ index = tp - 1;
+ get_pixel(ibuf, index, color);
+ if (color[0] == 1.0f) {
+ BLI_stack_push(stack, &index);
+ }
+ }
+ /* pixel top-right */
+ if (tp && rt) {
+ index = tp + 1;
+ get_pixel(ibuf, index, color);
+ if (color[0] == 1.0f) {
+ BLI_stack_push(stack, &index);
+ }
+ }
+ /* pixel bottom-left */
+ if (bm && lt) {
+ index = bm - 1;
+ get_pixel(ibuf, index, color);
+ if (color[0] == 1.0f) {
+ BLI_stack_push(stack, &index);
+ }
+ }
+ /* pixel bottom-right */
+ if (bm && rt) {
+ index = bm + 1;
+ get_pixel(ibuf, index, color);
+ if (color[0] == 1.0f) {
+ BLI_stack_push(stack, &index);
+ }
+ }
+ }
+ }
+ /* set dilated pixels */
+ while (!BLI_stack_is_empty(stack)) {
+ int v;
+ BLI_stack_pop(stack, &v);
+ set_pixel(ibuf, v, green);
+ }
+ BLI_stack_free(stack);
}
/* Get the outline points of a shape using Moore Neighborhood algorithm
@@ -790,331 +810,325 @@ static void dilate(ImBuf *ibuf)
*/
static void gpencil_get_outline_points(tGPDfill *tgpf)
{
- ImBuf *ibuf;
- float rgba[4];
- void *lock;
- int v[2];
- int boundary_co[2];
- int start_co[2];
- int backtracked_co[2];
- int current_check_co[2];
- int prev_check_co[2];
- int backtracked_offset[1][2] = {{0, 0}};
- // bool boundary_found = false;
- bool start_found = false;
- const int NEIGHBOR_COUNT = 8;
-
- const int offset[8][2] = {
- {-1, -1},
- {0, -1},
- {1, -1},
- {1, 0},
- {1, 1},
- {0, 1},
- {-1, 1},
- {-1, 0},
- };
-
- tgpf->stack = BLI_stack_new(sizeof(int[2]), __func__);
-
- ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
- int imagesize = ibuf->x * ibuf->y;
-
- /* dilate */
- dilate(ibuf);
-
- /* find the initial point to start outline analysis */
- for (int idx = imagesize - 1; idx != 0; idx--) {
- get_pixel(ibuf, idx, rgba);
- if (rgba[1] == 1.0f) {
- boundary_co[0] = idx % ibuf->x;
- boundary_co[1] = idx / ibuf->x;
- copy_v2_v2_int(start_co, boundary_co);
- backtracked_co[0] = (idx - 1) % ibuf->x;
- backtracked_co[1] = (idx - 1) / ibuf->x;
- backtracked_offset[0][0] = backtracked_co[0] - boundary_co[0];
- backtracked_offset[0][1] = backtracked_co[1] - boundary_co[1];
- copy_v2_v2_int(prev_check_co, start_co);
-
- BLI_stack_push(tgpf->stack, &boundary_co);
- start_found = true;
- break;
- }
- }
-
- while (start_found) {
- int cur_back_offset = -1;
- for (int i = 0; i < NEIGHBOR_COUNT; i++) {
- if (backtracked_offset[0][0] == offset[i][0] &&
- backtracked_offset[0][1] == offset[i][1])
- {
- /* Finding the bracktracked pixel offset index */
- cur_back_offset = i;
- break;
- }
- }
-
- int loop = 0;
- while (loop < (NEIGHBOR_COUNT - 1) && cur_back_offset != -1) {
- int offset_idx = (cur_back_offset + 1) % NEIGHBOR_COUNT;
- current_check_co[0] = boundary_co[0] + offset[offset_idx][0];
- current_check_co[1] = boundary_co[1] + offset[offset_idx][1];
-
- int image_idx = ibuf->x * current_check_co[1] + current_check_co[0];
- get_pixel(ibuf, image_idx, rgba);
-
- /* find next boundary pixel */
- if (rgba[1] == 1.0f) {
- copy_v2_v2_int(boundary_co, current_check_co);
- copy_v2_v2_int(backtracked_co, prev_check_co);
- backtracked_offset[0][0] = backtracked_co[0] - boundary_co[0];
- backtracked_offset[0][1] = backtracked_co[1] - boundary_co[1];
-
- BLI_stack_push(tgpf->stack, &boundary_co);
-
- break;
- }
- copy_v2_v2_int(prev_check_co, current_check_co);
- cur_back_offset++;
- loop++;
- }
- /* current pixel is equal to starting pixel */
- if (boundary_co[0] == start_co[0] &&
- boundary_co[1] == start_co[1])
- {
- BLI_stack_pop(tgpf->stack, &v);
- // boundary_found = true;
- break;
- }
- }
-
- /* release ibuf */
- if (ibuf) {
- BKE_image_release_ibuf(tgpf->ima, ibuf, lock);
- }
+ ImBuf *ibuf;
+ float rgba[4];
+ void *lock;
+ int v[2];
+ int boundary_co[2];
+ int start_co[2];
+ int backtracked_co[2];
+ int current_check_co[2];
+ int prev_check_co[2];
+ int backtracked_offset[1][2] = {{0, 0}};
+ // bool boundary_found = false;
+ bool start_found = false;
+ const int NEIGHBOR_COUNT = 8;
+
+ const int offset[8][2] = {
+ {-1, -1},
+ {0, -1},
+ {1, -1},
+ {1, 0},
+ {1, 1},
+ {0, 1},
+ {-1, 1},
+ {-1, 0},
+ };
+
+ tgpf->stack = BLI_stack_new(sizeof(int[2]), __func__);
+
+ ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
+ int imagesize = ibuf->x * ibuf->y;
+
+ /* dilate */
+ dilate(ibuf);
+
+ /* find the initial point to start outline analysis */
+ for (int idx = imagesize - 1; idx != 0; idx--) {
+ get_pixel(ibuf, idx, rgba);
+ if (rgba[1] == 1.0f) {
+ boundary_co[0] = idx % ibuf->x;
+ boundary_co[1] = idx / ibuf->x;
+ copy_v2_v2_int(start_co, boundary_co);
+ backtracked_co[0] = (idx - 1) % ibuf->x;
+ backtracked_co[1] = (idx - 1) / ibuf->x;
+ backtracked_offset[0][0] = backtracked_co[0] - boundary_co[0];
+ backtracked_offset[0][1] = backtracked_co[1] - boundary_co[1];
+ copy_v2_v2_int(prev_check_co, start_co);
+
+ BLI_stack_push(tgpf->stack, &boundary_co);
+ start_found = true;
+ break;
+ }
+ }
+
+ while (start_found) {
+ int cur_back_offset = -1;
+ for (int i = 0; i < NEIGHBOR_COUNT; i++) {
+ if (backtracked_offset[0][0] == offset[i][0] && backtracked_offset[0][1] == offset[i][1]) {
+ /* Finding the bracktracked pixel offset index */
+ cur_back_offset = i;
+ break;
+ }
+ }
+
+ int loop = 0;
+ while (loop < (NEIGHBOR_COUNT - 1) && cur_back_offset != -1) {
+ int offset_idx = (cur_back_offset + 1) % NEIGHBOR_COUNT;
+ current_check_co[0] = boundary_co[0] + offset[offset_idx][0];
+ current_check_co[1] = boundary_co[1] + offset[offset_idx][1];
+
+ int image_idx = ibuf->x * current_check_co[1] + current_check_co[0];
+ get_pixel(ibuf, image_idx, rgba);
+
+ /* find next boundary pixel */
+ if (rgba[1] == 1.0f) {
+ copy_v2_v2_int(boundary_co, current_check_co);
+ copy_v2_v2_int(backtracked_co, prev_check_co);
+ backtracked_offset[0][0] = backtracked_co[0] - boundary_co[0];
+ backtracked_offset[0][1] = backtracked_co[1] - boundary_co[1];
+
+ BLI_stack_push(tgpf->stack, &boundary_co);
+
+ break;
+ }
+ copy_v2_v2_int(prev_check_co, current_check_co);
+ cur_back_offset++;
+ loop++;
+ }
+ /* current pixel is equal to starting pixel */
+ if (boundary_co[0] == start_co[0] && boundary_co[1] == start_co[1]) {
+ BLI_stack_pop(tgpf->stack, &v);
+ // boundary_found = true;
+ break;
+ }
+ }
+
+ /* release ibuf */
+ if (ibuf) {
+ BKE_image_release_ibuf(tgpf->ima, ibuf, lock);
+ }
}
/* get z-depth array to reproject on surface */
static void gpencil_get_depth_array(tGPDfill *tgpf)
{
- tGPspoint *ptc;
- ToolSettings *ts = tgpf->scene->toolsettings;
- int totpoints = tgpf->sbuffer_size;
- int i = 0;
-
- if (totpoints == 0) {
- return;
- }
-
- /* for surface sketching, need to set the right OpenGL context stuff so that
- * the conversions will project the values correctly...
- */
- 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);
-
- /* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */
- int depth_margin = 0;
-
- /* get an array of depths, far depths are blended */
- int mval_prev[2] = { 0 };
- int interp_depth = 0;
- int found_depth = 0;
-
- tgpf->depth_arr = MEM_mallocN(sizeof(float) * totpoints, "depth_points");
-
- for (i = 0, ptc = tgpf->sbuffer; i < totpoints; i++, ptc++) {
-
- 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)))
- {
- interp_depth = true;
- }
- else {
- found_depth = true;
- }
-
- copy_v2_v2_int(mval_prev, mval_i);
- }
-
- if (found_depth == false) {
- /* eeh... not much we can do.. :/, ignore depth in this case */
- for (i = totpoints - 1; i >= 0; i--)
- tgpf->depth_arr[i] = 0.9999f;
- }
- else {
- if (interp_depth) {
- interp_sparse_array(tgpf->depth_arr, totpoints, FLT_MAX);
- }
- }
- }
+ tGPspoint *ptc;
+ ToolSettings *ts = tgpf->scene->toolsettings;
+ int totpoints = tgpf->sbuffer_size;
+ int i = 0;
+
+ if (totpoints == 0) {
+ return;
+ }
+
+ /* for surface sketching, need to set the right OpenGL context stuff so that
+ * the conversions will project the values correctly...
+ */
+ 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);
+
+ /* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */
+ int depth_margin = 0;
+
+ /* get an array of depths, far depths are blended */
+ int mval_prev[2] = {0};
+ int interp_depth = 0;
+ int found_depth = 0;
+
+ tgpf->depth_arr = MEM_mallocN(sizeof(float) * totpoints, "depth_points");
+
+ for (i = 0, ptc = tgpf->sbuffer; i < totpoints; i++, ptc++) {
+
+ 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))) {
+ interp_depth = true;
+ }
+ else {
+ found_depth = true;
+ }
+
+ copy_v2_v2_int(mval_prev, mval_i);
+ }
+
+ if (found_depth == false) {
+ /* eeh... not much we can do.. :/, ignore depth in this case */
+ for (i = totpoints - 1; i >= 0; i--)
+ tgpf->depth_arr[i] = 0.9999f;
+ }
+ else {
+ if (interp_depth) {
+ interp_sparse_array(tgpf->depth_arr, totpoints, FLT_MAX);
+ }
+ }
+ }
}
/* create array of points using stack as source */
static void gpencil_points_from_stack(tGPDfill *tgpf)
{
- tGPspoint *point2D;
- int totpoints = BLI_stack_count(tgpf->stack);
- if (totpoints == 0) {
- return;
- }
-
- tgpf->sbuffer_size = (short)totpoints;
- tgpf->sbuffer = MEM_callocN(sizeof(tGPspoint) * totpoints, __func__);
-
- point2D = tgpf->sbuffer;
- while (!BLI_stack_is_empty(tgpf->stack)) {
- int v[2];
- BLI_stack_pop(tgpf->stack, &v);
- copy_v2fl_v2i(&point2D->x, v);
- /* shift points to center of pixel */
- add_v2_fl(&point2D->x, 0.5f);
- point2D->pressure = 1.0f;
- point2D->strength = 1.0f;
- point2D->time = 0.0f;
- point2D++;
- }
+ tGPspoint *point2D;
+ int totpoints = BLI_stack_count(tgpf->stack);
+ if (totpoints == 0) {
+ return;
+ }
+
+ tgpf->sbuffer_size = (short)totpoints;
+ tgpf->sbuffer = MEM_callocN(sizeof(tGPspoint) * totpoints, __func__);
+
+ point2D = tgpf->sbuffer;
+ while (!BLI_stack_is_empty(tgpf->stack)) {
+ int v[2];
+ BLI_stack_pop(tgpf->stack, &v);
+ copy_v2fl_v2i(&point2D->x, v);
+ /* shift points to center of pixel */
+ add_v2_fl(&point2D->x, 0.5f);
+ point2D->pressure = 1.0f;
+ point2D->strength = 1.0f;
+ point2D->time = 0.0f;
+ point2D++;
+ }
}
/* 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));
- const bool is_camera = (bool)(ts->gp_sculpt.lock_axis == 0) &&
- (tgpf->rv3d->persp == RV3D_CAMOB) && (!is_depth);
- Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
- if (brush == NULL) {
- return;
- }
-
- bGPDspoint *pt;
- MDeformVert *dvert = NULL;
- tGPspoint *point2D;
-
- if (tgpf->sbuffer_size == 0) {
- return;
- }
-
- /* get frame or create a new one */
- tgpf->gpf = BKE_gpencil_layer_getframe(tgpf->gpl, cfra_eval, GP_GETFRAME_ADD_NEW);
-
- /* 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->inittime = 0.0f;
-
- /* the polygon must be closed, so enabled cyclic */
- gps->flag |= GP_STROKE_CYCLIC;
- gps->flag |= GP_STROKE_3DSPACE;
-
- gps->mat_nr = BKE_gpencil_object_material_ensure(tgpf->bmain, tgpf->ob, tgpf->mat);
-
- /* allocate memory for storage points */
- gps->totpoints = tgpf->sbuffer_size;
- gps->points = MEM_callocN(sizeof(bGPDspoint) * tgpf->sbuffer_size, "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);
- }
- else {
- BLI_addtail(&tgpf->gpf->strokes, gps);
- }
-
- /* add points */
- pt = gps->points;
- point2D = (tGPspoint *)tgpf->sbuffer;
-
- const int def_nr = tgpf->ob->actdef - 1;
- const bool have_weight = (bool)BLI_findlink(&tgpf->ob->defbase, def_nr);
-
- if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
- BKE_gpencil_dvert_ensure(gps);
- dvert = gps->dvert;
- }
-
- for (int i = 0; i < tgpf->sbuffer_size && point2D; i++, point2D++, pt++) {
- /* convert screen-coordinates to 3D coordinates */
- gp_stroke_convertcoords_tpoint(
- tgpf->scene, tgpf->ar, tgpf->ob,
- tgpf->gpl, point2D,
- tgpf->depth_arr ? tgpf->depth_arr + i : NULL,
- &pt->x);
-
- pt->pressure = 1.0f;
- pt->strength = 1.0f;
- pt->time = 0.0f;
-
- if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
- MDeformWeight *dw = defvert_verify_index(dvert, def_nr);
- if (dw) {
- dw->weight = ts->vgroup_weight;
- }
-
- dvert++;
- }
- else {
- if (dvert != NULL) {
- dvert->totweight = 0;
- dvert->dw = NULL;
- dvert++;
- }
- }
- }
-
- /* smooth stroke */
- float reduce = 0.0f;
- 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);
- }
- reduce += 0.25f; // reduce the factor
- }
-
- /* if axis locked, reproject to plane locked */
- 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_gp_project_stroke_to_plane(
- tgpf->scene, tgpf->ob, tgpf->rv3d, gps, origin,
- tgpf->lock_axis - 1);
- }
-
- /* if parented change position relative to parent object */
- for (int a = 0; a < tgpf->sbuffer_size; a++) {
- pt = &gps->points[a];
- gp_apply_parent_point(tgpf->depsgraph, tgpf->ob, tgpf->gpd, tgpf->gpl, pt);
- }
-
- /* if camera view, reproject flat to view to avoid perspective effect */
- if (is_camera) {
- ED_gpencil_project_stroke_to_view(tgpf->C, tgpf->gpl, gps);
- }
-
- /* simplify stroke */
- for (int b = 0; b < tgpf->fill_simplylvl; b++) {
- BKE_gpencil_simplify_fixed(gps);
- }
+ 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));
+ const bool is_camera = (bool)(ts->gp_sculpt.lock_axis == 0) &&
+ (tgpf->rv3d->persp == RV3D_CAMOB) && (!is_depth);
+ Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
+ if (brush == NULL) {
+ return;
+ }
+
+ bGPDspoint *pt;
+ MDeformVert *dvert = NULL;
+ tGPspoint *point2D;
+
+ if (tgpf->sbuffer_size == 0) {
+ return;
+ }
+
+ /* get frame or create a new one */
+ tgpf->gpf = BKE_gpencil_layer_getframe(tgpf->gpl, cfra_eval, GP_GETFRAME_ADD_NEW);
+
+ /* 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->inittime = 0.0f;
+
+ /* the polygon must be closed, so enabled cyclic */
+ gps->flag |= GP_STROKE_CYCLIC;
+ gps->flag |= GP_STROKE_3DSPACE;
+
+ gps->mat_nr = BKE_gpencil_object_material_ensure(tgpf->bmain, tgpf->ob, tgpf->mat);
+
+ /* allocate memory for storage points */
+ gps->totpoints = tgpf->sbuffer_size;
+ gps->points = MEM_callocN(sizeof(bGPDspoint) * tgpf->sbuffer_size, "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);
+ }
+ else {
+ BLI_addtail(&tgpf->gpf->strokes, gps);
+ }
+
+ /* add points */
+ pt = gps->points;
+ point2D = (tGPspoint *)tgpf->sbuffer;
+
+ const int def_nr = tgpf->ob->actdef - 1;
+ const bool have_weight = (bool)BLI_findlink(&tgpf->ob->defbase, def_nr);
+
+ if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
+ BKE_gpencil_dvert_ensure(gps);
+ dvert = gps->dvert;
+ }
+
+ for (int i = 0; i < tgpf->sbuffer_size && point2D; i++, point2D++, pt++) {
+ /* convert screen-coordinates to 3D coordinates */
+ gp_stroke_convertcoords_tpoint(tgpf->scene,
+ tgpf->ar,
+ tgpf->ob,
+ tgpf->gpl,
+ point2D,
+ tgpf->depth_arr ? tgpf->depth_arr + i : NULL,
+ &pt->x);
+
+ pt->pressure = 1.0f;
+ pt->strength = 1.0f;
+ pt->time = 0.0f;
+
+ if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
+ MDeformWeight *dw = defvert_verify_index(dvert, def_nr);
+ if (dw) {
+ dw->weight = ts->vgroup_weight;
+ }
+
+ dvert++;
+ }
+ else {
+ if (dvert != NULL) {
+ dvert->totweight = 0;
+ dvert->dw = NULL;
+ dvert++;
+ }
+ }
+ }
+
+ /* smooth stroke */
+ float reduce = 0.0f;
+ 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);
+ }
+ reduce += 0.25f; // reduce the factor
+ }
+
+ /* if axis locked, reproject to plane locked */
+ 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_gp_project_stroke_to_plane(
+ tgpf->scene, tgpf->ob, tgpf->rv3d, gps, origin, tgpf->lock_axis - 1);
+ }
+
+ /* if parented change position relative to parent object */
+ for (int a = 0; a < tgpf->sbuffer_size; a++) {
+ pt = &gps->points[a];
+ gp_apply_parent_point(tgpf->depsgraph, tgpf->ob, tgpf->gpd, tgpf->gpl, pt);
+ }
+
+ /* if camera view, reproject flat to view to avoid perspective effect */
+ if (is_camera) {
+ ED_gpencil_project_stroke_to_view(tgpf->C, tgpf->gpl, gps);
+ }
+
+ /* simplify stroke */
+ for (int b = 0; b < tgpf->fill_simplylvl; b++) {
+ BKE_gpencil_simplify_fixed(gps);
+ }
}
/* ----------------------- */
@@ -1122,357 +1136,356 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
/* Helper: Draw status message while the user is running the operator */
static void gpencil_fill_status_indicators(bContext *C, tGPDfill *UNUSED(tgpf))
{
- const char *status_str = IFACE_("Fill: ESC/RMB cancel, LMB Fill, Shift Draw on Back");
- ED_workspace_status_text(C, status_str);
+ const char *status_str = IFACE_("Fill: ESC/RMB cancel, LMB Fill, Shift Draw on Back");
+ ED_workspace_status_text(C, status_str);
}
/* draw boundary lines to see fill limits */
static void gpencil_draw_boundary_lines(const bContext *UNUSED(C), tGPDfill *tgpf)
{
- if (!tgpf->gpd) {
- return;
- }
- const float ink[4] = {1.0f, 0.0f, 0.0f, 1.0f};
- gp_draw_datablock(tgpf, ink);
+ if (!tgpf->gpd) {
+ return;
+ }
+ const float ink[4] = {1.0f, 0.0f, 0.0f, 1.0f};
+ gp_draw_datablock(tgpf, ink);
}
/* Drawing callback for modal operator in 3d mode */
static void gpencil_fill_draw_3d(const bContext *C, ARegion *UNUSED(ar), 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) {
- return;
- }
-
- gpencil_draw_boundary_lines(C, tgpf);
+ 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) {
+ return;
+ }
+
+ gpencil_draw_boundary_lines(C, tgpf);
}
/* check if context is suitable for filling */
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) {
- if ((obact == NULL) ||
- (obact->type != OB_GPENCIL) ||
- (obact->mode != OB_MODE_PAINT_GPENCIL))
- {
- return false;
- }
-
- return true;
- }
- else {
- CTX_wm_operator_poll_msg_set(C, "Active region not valid for filling operator");
- return false;
- }
- }
- else {
- CTX_wm_operator_poll_msg_set(C, "Active region not set");
- return false;
- }
+ Object *obact = CTX_data_active_object(C);
+
+ if (ED_operator_regionactive(C)) {
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa->spacetype == SPACE_VIEW3D) {
+ if ((obact == NULL) || (obact->type != OB_GPENCIL) ||
+ (obact->mode != OB_MODE_PAINT_GPENCIL)) {
+ return false;
+ }
+
+ return true;
+ }
+ else {
+ CTX_wm_operator_poll_msg_set(C, "Active region not valid for filling operator");
+ return false;
+ }
+ }
+ else {
+ CTX_wm_operator_poll_msg_set(C, "Active region not set");
+ return false;
+ }
}
/* Allocate memory and initialize values */
static tGPDfill *gp_session_init_fill(bContext *C, wmOperator *UNUSED(op))
{
- tGPDfill *tgpf = MEM_callocN(sizeof(tGPDfill), "GPencil Fill Data");
-
- /* define initial values */
- ToolSettings *ts = CTX_data_tool_settings(C);
- bGPdata *gpd = CTX_data_gpencil_data(C);
- Main *bmain = CTX_data_main(C);
-
- /* set current scene and window info */
- tgpf->C = C;
- 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->depsgraph = CTX_data_depsgraph(C);
- tgpf->win = CTX_wm_window(C);
-
- /* set GP datablock */
- tgpf->gpd = gpd;
- tgpf->gpl = BKE_gpencil_layer_getactive(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;
- tgpf->sbuffer_size = 0;
- tgpf->sbuffer = NULL;
- tgpf->depth_arr = NULL;
-
- /* save filling parameters */
- Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
- tgpf->flag = brush->gpencil_settings->flag;
- tgpf->fill_leak = brush->gpencil_settings->fill_leak;
- tgpf->fill_threshold = brush->gpencil_settings->fill_threshold;
- tgpf->fill_simplylvl = brush->gpencil_settings->fill_simplylvl;
- tgpf->fill_draw_mode = brush->gpencil_settings->fill_draw_mode;
- tgpf->fill_factor = (short)max_ii(1, min_ii((int)brush->gpencil_settings->fill_factor, 8));
-
- int totcol = tgpf->ob->totcol;
-
- /* get color info */
- Material *ma = BKE_gpencil_object_material_ensure_from_active_input_brush(bmain, tgpf->ob, brush);
-
- tgpf->mat = ma;
-
- /* check whether the material was newly added */
- if (totcol != tgpf->ob->totcol) {
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_PROPERTIES, NULL);
- }
-
- /* init undo */
- gpencil_undo_init(tgpf->gpd);
-
- /* return context data for running operator */
- return tgpf;
+ tGPDfill *tgpf = MEM_callocN(sizeof(tGPDfill), "GPencil Fill Data");
+
+ /* define initial values */
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ Main *bmain = CTX_data_main(C);
+
+ /* set current scene and window info */
+ tgpf->C = C;
+ 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->depsgraph = CTX_data_depsgraph(C);
+ tgpf->win = CTX_wm_window(C);
+
+ /* set GP datablock */
+ tgpf->gpd = gpd;
+ tgpf->gpl = BKE_gpencil_layer_getactive(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;
+ tgpf->sbuffer_size = 0;
+ tgpf->sbuffer = NULL;
+ tgpf->depth_arr = NULL;
+
+ /* save filling parameters */
+ Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
+ tgpf->flag = brush->gpencil_settings->flag;
+ tgpf->fill_leak = brush->gpencil_settings->fill_leak;
+ tgpf->fill_threshold = brush->gpencil_settings->fill_threshold;
+ tgpf->fill_simplylvl = brush->gpencil_settings->fill_simplylvl;
+ tgpf->fill_draw_mode = brush->gpencil_settings->fill_draw_mode;
+ tgpf->fill_factor = (short)max_ii(1, min_ii((int)brush->gpencil_settings->fill_factor, 8));
+
+ int totcol = tgpf->ob->totcol;
+
+ /* get color info */
+ Material *ma = BKE_gpencil_object_material_ensure_from_active_input_brush(
+ bmain, tgpf->ob, brush);
+
+ tgpf->mat = ma;
+
+ /* check whether the material was newly added */
+ if (totcol != tgpf->ob->totcol) {
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_PROPERTIES, NULL);
+ }
+
+ /* init undo */
+ gpencil_undo_init(tgpf->gpd);
+
+ /* return context data for running operator */
+ return tgpf;
}
/* end operator */
static void gpencil_fill_exit(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = CTX_data_active_object(C);
-
- /* clear undo stack */
- gpencil_undo_finish();
-
- /* restore cursor to indicate end of fill */
- WM_cursor_modal_restore(CTX_wm_window(C));
-
- tGPDfill *tgpf = op->customdata;
-
- /* don't assume that operator data exists at all */
- if (tgpf) {
- /* clear status message area */
- ED_workspace_status_text(C, NULL);
-
- MEM_SAFE_FREE(tgpf->sbuffer);
- MEM_SAFE_FREE(tgpf->depth_arr);
-
- /* remove drawing handler */
- if (tgpf->draw_handle_3d) {
- ED_region_draw_cb_exit(tgpf->ar->type, tgpf->draw_handle_3d);
- }
-
- /* 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;
- }
- }
- }
-
- /* finally, free memory used by temp data */
- MEM_freeN(tgpf);
- }
-
- /* clear pointer */
- op->customdata = NULL;
-
- /* drawing batch cache is dirty now */
- if ((ob) && (ob->type == OB_GPENCIL) && (ob->data)) {
- bGPdata *gpd2 = ob->data;
- DEG_id_tag_update(&gpd2->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- gpd2->flag |= GP_DATA_CACHE_IS_DIRTY;
- }
-
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+ Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
+
+ /* clear undo stack */
+ gpencil_undo_finish();
+
+ /* restore cursor to indicate end of fill */
+ WM_cursor_modal_restore(CTX_wm_window(C));
+
+ tGPDfill *tgpf = op->customdata;
+
+ /* don't assume that operator data exists at all */
+ if (tgpf) {
+ /* clear status message area */
+ ED_workspace_status_text(C, NULL);
+
+ MEM_SAFE_FREE(tgpf->sbuffer);
+ MEM_SAFE_FREE(tgpf->depth_arr);
+
+ /* remove drawing handler */
+ if (tgpf->draw_handle_3d) {
+ ED_region_draw_cb_exit(tgpf->ar->type, tgpf->draw_handle_3d);
+ }
+
+ /* 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;
+ }
+ }
+ }
+
+ /* finally, free memory used by temp data */
+ MEM_freeN(tgpf);
+ }
+
+ /* clear pointer */
+ op->customdata = NULL;
+
+ /* drawing batch cache is dirty now */
+ if ((ob) && (ob->type == OB_GPENCIL) && (ob->data)) {
+ bGPdata *gpd2 = ob->data;
+ DEG_id_tag_update(&gpd2->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ gpd2->flag |= GP_DATA_CACHE_IS_DIRTY;
+ }
+
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
}
static void gpencil_fill_cancel(bContext *C, wmOperator *op)
{
- /* this is just a wrapper around exit() */
- gpencil_fill_exit(C, op);
+ /* this is just a wrapper around exit() */
+ gpencil_fill_exit(C, op);
}
/* Init: Allocate memory and set init values */
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);
- if ((gpl) && (gpl->flag & GP_LAYER_LOCKED)) {
- return 0;
- }
-
- /* check context */
- tgpf = op->customdata = gp_session_init_fill(C, op);
- if (tgpf == NULL) {
- /* something wasn't set correctly in context */
- gpencil_fill_exit(C, op);
- return 0;
- }
-
- /* everything is now setup ok */
- return 1;
+ tGPDfill *tgpf;
+ /* cannot paint in locked layer */
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ if ((gpl) && (gpl->flag & GP_LAYER_LOCKED)) {
+ return 0;
+ }
+
+ /* check context */
+ tgpf = op->customdata = gp_session_init_fill(C, op);
+ if (tgpf == NULL) {
+ /* something wasn't set correctly in context */
+ gpencil_fill_exit(C, op);
+ return 0;
+ }
+
+ /* everything is now setup ok */
+ return 1;
}
/* start of interactive part of operator */
static int gpencil_fill_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- tGPDfill *tgpf = NULL;
+ tGPDfill *tgpf = NULL;
- /* try to initialize context data needed */
- if (!gpencil_fill_init(C, op)) {
- gpencil_fill_exit(C, op);
- if (op->customdata)
- MEM_freeN(op->customdata);
- return OPERATOR_CANCELLED;
- }
- else {
- tgpf = op->customdata;
- }
+ /* try to initialize context data needed */
+ if (!gpencil_fill_init(C, op)) {
+ gpencil_fill_exit(C, op);
+ if (op->customdata)
+ MEM_freeN(op->customdata);
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ tgpf = op->customdata;
+ }
- /* 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);
- }
+ /* 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);
+ }
- WM_cursor_modal_set(CTX_wm_window(C), BC_PAINTBRUSHCURSOR);
+ WM_cursor_modal_set(CTX_wm_window(C), BC_PAINTBRUSHCURSOR);
- gpencil_fill_status_indicators(C, tgpf);
+ gpencil_fill_status_indicators(C, tgpf);
- DEG_id_tag_update(&tgpf->gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+ DEG_id_tag_update(&tgpf->gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
- /* add a modal handler for this operator*/
- WM_event_add_modal_handler(C, op);
+ /* add a modal handler for this operator*/
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
/* events handling during interactive part of operator */
static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- tGPDfill *tgpf = op->customdata;
-
- int estate = OPERATOR_PASS_THROUGH; /* default exit state - pass through */
-
- switch (event->type) {
- case 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 */
- 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) {
- bool in_bounds = false;
-
- /* Perform bounds check */
- in_bounds = BLI_rcti_isect_pt(&ar->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 */
- tgpf->center[0] = event->mval[0];
- tgpf->center[1] = event->mval[1];
-
- /* render screen to temp image */
- if ( gp_render_offscreen(tgpf) ) {
-
- /* apply boundary fill */
- gpencil_boundaryfill_area(tgpf);
-
- /* clean borders to avoid infinite loops */
- gpencil_clean_borders(tgpf);
-
- /* analyze outline */
- gpencil_get_outline_points(tgpf);
-
- /* create array of points from stack */
- gpencil_points_from_stack(tgpf);
-
- /* create z-depth array for reproject */
- gpencil_get_depth_array(tgpf);
-
- /* create stroke and reproject */
- 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);
- }
-
- /* push undo data */
- gpencil_undo_push(tgpf->gpd);
-
- estate = OPERATOR_FINISHED;
- }
- else {
- estate = OPERATOR_CANCELLED;
- }
- }
- else {
- estate = OPERATOR_CANCELLED;
- }
- }
- tgpf->oldkey = event->type;
- break;
- }
- /* process last operations before exiting */
- switch (estate) {
- case OPERATOR_FINISHED:
- gpencil_fill_exit(C, op);
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
- break;
-
- case OPERATOR_CANCELLED:
- gpencil_fill_exit(C, op);
- break;
-
- case OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH:
- break;
- }
-
- /* return status code */
- return estate;
+ tGPDfill *tgpf = op->customdata;
+
+ int estate = OPERATOR_PASS_THROUGH; /* default exit state - pass through */
+
+ switch (event->type) {
+ case 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 */
+ 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) {
+ bool in_bounds = false;
+
+ /* Perform bounds check */
+ in_bounds = BLI_rcti_isect_pt(&ar->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 */
+ tgpf->center[0] = event->mval[0];
+ tgpf->center[1] = event->mval[1];
+
+ /* render screen to temp image */
+ if (gp_render_offscreen(tgpf)) {
+
+ /* apply boundary fill */
+ gpencil_boundaryfill_area(tgpf);
+
+ /* clean borders to avoid infinite loops */
+ gpencil_clean_borders(tgpf);
+
+ /* analyze outline */
+ gpencil_get_outline_points(tgpf);
+
+ /* create array of points from stack */
+ gpencil_points_from_stack(tgpf);
+
+ /* create z-depth array for reproject */
+ gpencil_get_depth_array(tgpf);
+
+ /* create stroke and reproject */
+ 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);
+ }
+
+ /* push undo data */
+ gpencil_undo_push(tgpf->gpd);
+
+ estate = OPERATOR_FINISHED;
+ }
+ else {
+ estate = OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ estate = OPERATOR_CANCELLED;
+ }
+ }
+ tgpf->oldkey = event->type;
+ break;
+ }
+ /* process last operations before exiting */
+ switch (estate) {
+ case OPERATOR_FINISHED:
+ gpencil_fill_exit(C, op);
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+ break;
+
+ case OPERATOR_CANCELLED:
+ gpencil_fill_exit(C, op);
+ break;
+
+ case OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH:
+ break;
+ }
+
+ /* return status code */
+ return estate;
}
void GPENCIL_OT_fill(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Grease Pencil Fill";
- ot->idname = "GPENCIL_OT_fill";
- ot->description = "Fill with color the shape formed by strokes";
+ /* identifiers */
+ ot->name = "Grease Pencil Fill";
+ ot->idname = "GPENCIL_OT_fill";
+ ot->description = "Fill with color the shape formed by strokes";
- /* api callbacks */
- ot->invoke = gpencil_fill_invoke;
- ot->modal = gpencil_fill_modal;
- ot->poll = gpencil_fill_poll;
- ot->cancel = gpencil_fill_cancel;
+ /* api callbacks */
+ ot->invoke = gpencil_fill_invoke;
+ ot->modal = gpencil_fill_modal;
+ ot->poll = gpencil_fill_poll;
+ ot->cancel = gpencil_fill_cancel;
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
- prop = RNA_def_boolean(ot->srna, "on_back", false, "Draw On Back", "Send new stroke to Back");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "on_back", false, "Draw On Back", "Send new stroke to Back");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 3742ca92551..c8d2547ad51 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -24,12 +24,10 @@
#ifndef __GPENCIL_INTERN_H__
#define __GPENCIL_INTERN_H__
-
#include "DNA_vec_types.h"
#include "ED_numinput.h"
-
/* internal exports only */
struct Material;
struct bGPDspoint;
@@ -53,7 +51,6 @@ struct EnumPropertyItem;
struct PointerRNA;
struct PropertyRNA;
-
/* ***************************************************** */
/* Modal Operator Geometry Preview
*
@@ -73,172 +70,171 @@ struct PropertyRNA;
/* Temporary draw data (no draw manager mode) */
typedef struct tGPDdraw {
- struct RegionView3D *rv3d; /* region to draw */
- struct Depsgraph *depsgraph; /* depsgraph */
- struct Object *ob; /* GP object */
- struct bGPdata *gpd; /* current GP datablock */
- struct bGPDlayer *gpl; /* layer */
- struct bGPDframe *gpf; /* frame */
- struct bGPDframe *t_gpf; /* temporal frame */
- struct bGPDstroke *gps; /* stroke */
- int disable_fill; /* disable fill */
- int offsx; /* windows offset x */
- int offsy; /* windows offset y */
- int winx; /* windows width */
- int winy; /* windows height */
- int dflag; /* flags datablock */
- short lthick; /* layer thickness */
- float opacity; /* opacity */
- float tintcolor[4]; /* tint color */
- bool onion; /* onion flag */
- bool custonion; /* use custom onion colors */
- bool is_fill_stroke; /* use fill tool */
- float diff_mat[4][4]; /* matrix */
+ struct RegionView3D *rv3d; /* region to draw */
+ struct Depsgraph *depsgraph; /* depsgraph */
+ struct Object *ob; /* GP object */
+ struct bGPdata *gpd; /* current GP datablock */
+ struct bGPDlayer *gpl; /* layer */
+ struct bGPDframe *gpf; /* frame */
+ struct bGPDframe *t_gpf; /* temporal frame */
+ struct bGPDstroke *gps; /* stroke */
+ int disable_fill; /* disable fill */
+ int offsx; /* windows offset x */
+ int offsy; /* windows offset y */
+ int winx; /* windows width */
+ int winy; /* windows height */
+ int dflag; /* flags datablock */
+ short lthick; /* layer thickness */
+ float opacity; /* opacity */
+ float tintcolor[4]; /* tint color */
+ bool onion; /* onion flag */
+ bool custonion; /* use custom onion colors */
+ bool is_fill_stroke; /* use fill tool */
+ float diff_mat[4][4]; /* matrix */
} tGPDdraw;
-
/* Temporary interpolate operation data */
typedef struct tGPDinterpolate_layer {
- struct tGPDinterpolate_layer *next, *prev;
-
- /** layer */
- struct bGPDlayer *gpl;
- /** frame before current frame (interpolate-from) */
- struct bGPDframe *prevFrame;
- /** frame after current frame (interpolate-to) */
- struct bGPDframe *nextFrame;
- /** interpolated frame */
- struct bGPDframe *interFrame;
- /** interpolate factor */
- float factor;
+ struct tGPDinterpolate_layer *next, *prev;
+
+ /** layer */
+ struct bGPDlayer *gpl;
+ /** frame before current frame (interpolate-from) */
+ struct bGPDframe *prevFrame;
+ /** frame after current frame (interpolate-to) */
+ struct bGPDframe *nextFrame;
+ /** interpolated frame */
+ struct bGPDframe *interFrame;
+ /** interpolate factor */
+ float factor;
} tGPDinterpolate_layer;
typedef struct tGPDinterpolate {
- /** current scene from context */
- struct Scene *scene;
- /** area where painting originated */
- struct ScrArea *sa;
- /** region where painting originated */
- struct ARegion *ar;
- /** current GP datablock */
- struct bGPdata *gpd;
- /** current material */
- struct Material *mat;
-
- /** current frame number */
- int cframe;
- /** (tGPDinterpolate_layer) layers to be interpolated */
- ListBase ilayers;
- /** value for determining the displacement influence */
- float shift;
- /** initial interpolation factor for active layer */
- float init_factor;
- /** shift low limit (-100%) */
- float low_limit;
- /** shift upper limit (200%) */
- float high_limit;
- /** flag from toolsettings */
- 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;
+ /** current scene from context */
+ struct Scene *scene;
+ /** area where painting originated */
+ struct ScrArea *sa;
+ /** region where painting originated */
+ struct ARegion *ar;
+ /** current GP datablock */
+ struct bGPdata *gpd;
+ /** current material */
+ struct Material *mat;
+
+ /** current frame number */
+ int cframe;
+ /** (tGPDinterpolate_layer) layers to be interpolated */
+ ListBase ilayers;
+ /** value for determining the displacement influence */
+ float shift;
+ /** initial interpolation factor for active layer */
+ float init_factor;
+ /** shift low limit (-100%) */
+ float low_limit;
+ /** shift upper limit (200%) */
+ float high_limit;
+ /** flag from toolsettings */
+ 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 */
typedef struct tGPDprimitive {
- /** main database pointer */
- struct Main *bmain;
- struct Depsgraph *depsgraph;
- /** window where painting originated */
- struct wmWindow *win;
- /** current scene from context */
- struct Scene *scene;
- /** current active gp object */
- struct Object *ob;
- /** area where painting originated */
- struct ScrArea *sa;
- /** region where painting originated */
- struct RegionView3D *rv3d;
- /** view3d where painting originated */
- struct View3D *v3d;
- /** region where painting originated */
- struct ARegion *ar;
- /** current GP datablock */
- struct bGPdata *gpd;
- /** current material */
- struct Material *mat;
- /** current brush */
- struct Brush *brush;
-
- /** current frame number */
- int cframe;
- /** layer */
- struct bGPDlayer *gpl;
- /** frame */
- struct bGPDframe *gpf;
- /** type of primitive */
- int type;
- /** original type of primitive */
- int orign_type;
- /** type of primitive is a curve */
- bool curve;
- /** brush size */
- int brush_size;
- /** brush strength */
- float brush_strength;
- /** flip option */
- short flip;
- /** array of data-points for stroke */
- tGPspoint *points;
- /** number of edges allocated */
- int point_count;
- /** stored number of polygon edges */
- int tot_stored_edges;
- /** number of polygon edges */
- int tot_edges;
- /** move distance */
- float move[2];
- /** initial box corner */
- float origin[2];
- /** first box corner */
- float start[2];
- /** last box corner */
- float end[2];
- /** midpoint box corner */
- float midpoint[2];
- /** first control point */
- float cp1[2];
- /** second control point */
- float cp2[2];
- /** flag to determine control point is selected */
- int sel_cp;
- /** flag to determine operations in progress */
- int flag;
- /** recorded mouse-position */
- float mval[2];
- /** previous recorded mouse-position */
- float mvalo[2];
-
- /** lock to viewport axis */
- int lock_axis;
- struct RNG *rng;
-
- /** numeric input */
- NumInput num;
-
- /** size in pixels for uv calculation */
- float totpixlen;
+ /** main database pointer */
+ struct Main *bmain;
+ struct Depsgraph *depsgraph;
+ /** window where painting originated */
+ struct wmWindow *win;
+ /** current scene from context */
+ struct Scene *scene;
+ /** current active gp object */
+ struct Object *ob;
+ /** area where painting originated */
+ struct ScrArea *sa;
+ /** region where painting originated */
+ struct RegionView3D *rv3d;
+ /** view3d where painting originated */
+ struct View3D *v3d;
+ /** region where painting originated */
+ struct ARegion *ar;
+ /** current GP datablock */
+ struct bGPdata *gpd;
+ /** current material */
+ struct Material *mat;
+ /** current brush */
+ struct Brush *brush;
+
+ /** current frame number */
+ int cframe;
+ /** layer */
+ struct bGPDlayer *gpl;
+ /** frame */
+ struct bGPDframe *gpf;
+ /** type of primitive */
+ int type;
+ /** original type of primitive */
+ int orign_type;
+ /** type of primitive is a curve */
+ bool curve;
+ /** brush size */
+ int brush_size;
+ /** brush strength */
+ float brush_strength;
+ /** flip option */
+ short flip;
+ /** array of data-points for stroke */
+ tGPspoint *points;
+ /** number of edges allocated */
+ int point_count;
+ /** stored number of polygon edges */
+ int tot_stored_edges;
+ /** number of polygon edges */
+ int tot_edges;
+ /** move distance */
+ float move[2];
+ /** initial box corner */
+ float origin[2];
+ /** first box corner */
+ float start[2];
+ /** last box corner */
+ float end[2];
+ /** midpoint box corner */
+ float midpoint[2];
+ /** first control point */
+ float cp1[2];
+ /** second control point */
+ float cp2[2];
+ /** flag to determine control point is selected */
+ int sel_cp;
+ /** flag to determine operations in progress */
+ int flag;
+ /** recorded mouse-position */
+ float mval[2];
+ /** previous recorded mouse-position */
+ float mvalo[2];
+
+ /** lock to viewport axis */
+ int lock_axis;
+ struct RNG *rng;
+
+ /** numeric input */
+ NumInput num;
+
+ /** size in pixels for uv calculation */
+ float totpixlen;
} tGPDprimitive;
-
/* Modal Operator Drawing Callbacks ------------------------ */
-void ED_gp_draw_interpolation(const struct bContext *C, struct tGPDinterpolate *tgpi, const int type);
+void ED_gp_draw_interpolation(const struct bContext *C,
+ struct tGPDinterpolate *tgpi,
+ const int type);
void ED_gp_draw_fill(struct tGPDdraw *tgpw);
/* ***************************************************** */
@@ -248,55 +244,74 @@ void ED_gp_draw_fill(struct tGPDdraw *tgpw);
/* gpencil_utils.c */
typedef struct GP_SpaceConversion {
- struct Scene *scene;
- struct Object *ob;
- struct bGPdata *gpd;
- struct bGPDlayer *gpl;
+ struct Scene *scene;
+ struct Object *ob;
+ struct bGPdata *gpd;
+ struct bGPDlayer *gpl;
- struct ScrArea *sa;
- struct ARegion *ar;
- struct View2D *v2d;
+ struct ScrArea *sa;
+ struct ARegion *ar;
+ struct View2D *v2d;
- rctf *subrect; /* for using the camera rect within the 3d view */
- rctf subrect_data;
+ rctf *subrect; /* for using the camera rect within the 3d view */
+ rctf subrect_data;
- float mat[4][4]; /* transform matrix on the strokes (introduced in [b770964]) */
+ 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);
+ const float mval[2], const float UNUSED(mvalo[2]), int rad, int x0, int y0, int x1, int y1);
void gp_point_conversion_init(struct bContext *C, GP_SpaceConversion *r_gsc);
-void gp_point_to_xy(
- const GP_SpaceConversion *gsc, const struct bGPDstroke *gps, const struct bGPDspoint *pt,
- int *r_x, int *r_y);
+void gp_point_to_xy(const GP_SpaceConversion *gsc,
+ const struct bGPDstroke *gps,
+ const struct bGPDspoint *pt,
+ int *r_x,
+ int *r_y);
-void gp_point_to_xy_fl(
- const GP_SpaceConversion *gsc, const bGPDstroke *gps, const bGPDspoint *pt,
- float *r_x, float *r_y);
+void gp_point_to_xy_fl(const GP_SpaceConversion *gsc,
+ const bGPDstroke *gps,
+ const bGPDspoint *pt,
+ float *r_x,
+ float *r_y);
void gp_point_to_parent_space(const bGPDspoint *pt, const float diff_mat[4][4], bGPDspoint *r_pt);
/**
* Change points position relative to parent object
*/
-void gp_apply_parent(struct Depsgraph *depsgraph, struct Object *obact, bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps);
+void gp_apply_parent(struct Depsgraph *depsgraph,
+ struct Object *obact,
+ bGPdata *gpd,
+ bGPDlayer *gpl,
+ bGPDstroke *gps);
/**
* Change point position relative to parent object
*/
-void gp_apply_parent_point(struct Depsgraph *depsgraph, struct Object *obact, bGPdata *gpd, bGPDlayer *gpl, bGPDspoint *pt);
-
-void gp_point_3d_to_xy(const GP_SpaceConversion *gsc, const short flag, const float pt[3], float xy[2]);
-
-bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc, struct Scene *scene, const float screen_co[2], float r_out[3]);
+void gp_apply_parent_point(struct Depsgraph *depsgraph,
+ struct Object *obact,
+ bGPdata *gpd,
+ bGPDlayer *gpl,
+ bGPDspoint *pt);
+
+void gp_point_3d_to_xy(const GP_SpaceConversion *gsc,
+ const short flag,
+ const float pt[3],
+ float xy[2]);
+
+bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc,
+ struct Scene *scene,
+ const float screen_co[2],
+ float r_out[3]);
/* helper to convert 2d to 3d */
-void gp_stroke_convertcoords_tpoint(
- struct Scene *scene, struct ARegion *ar,
- struct Object *ob,
- bGPDlayer *gpl, const struct tGPspoint *point2D,
- float *depth, float out[3]);
+void gp_stroke_convertcoords_tpoint(struct Scene *scene,
+ struct ARegion *ar,
+ struct Object *ob,
+ bGPDlayer *gpl,
+ const struct tGPspoint *point2D,
+ float *depth,
+ float out[3]);
/* Poll Callbacks ------------------------------------ */
/* gpencil_utils.c */
@@ -316,9 +331,12 @@ struct GHash *gp_copybuf_validate_colormap(struct bContext *C);
/* Stroke Editing ------------------------------------ */
-void gp_stroke_delete_tagged_points(
- bGPDframe *gpf, bGPDstroke *gps, bGPDstroke *next_stroke,
- int tag_flags, bool select, int limit);
+void gp_stroke_delete_tagged_points(bGPDframe *gpf,
+ bGPDstroke *gps,
+ bGPDstroke *next_stroke,
+ int tag_flags,
+ bool select,
+ int limit);
int gp_delete_selected_point_wrap(bContext *C);
void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide);
@@ -326,12 +344,14 @@ void gp_randomize_stroke(bGPDstroke *gps, Brush *brush, struct RNG *rng);
/* Layers Enums -------------------------------------- */
-const struct EnumPropertyItem *ED_gpencil_layers_enum_itemf(
- struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop,
- bool *r_free);
-const struct EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(
- struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop,
- bool *r_free);
+const struct EnumPropertyItem *ED_gpencil_layers_enum_itemf(struct bContext *C,
+ struct PointerRNA *ptr,
+ struct PropertyRNA *prop,
+ bool *r_free);
+const struct EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(struct bContext *C,
+ struct PointerRNA *ptr,
+ struct PropertyRNA *prop,
+ bool *r_free);
/* ***************************************************** */
/* Operator Defines */
@@ -340,7 +360,6 @@ const struct EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(
void GPENCIL_OT_annotate(struct wmOperatorType *ot);
-
/* drawing ---------- */
void GPENCIL_OT_draw(struct wmOperatorType *ot);
@@ -352,15 +371,15 @@ void GPENCIL_OT_guide_rotate(struct wmOperatorType *ot);
/* Paint Modes for operator */
typedef enum eGPencil_PaintModes {
- GP_PAINTMODE_DRAW = 0,
- GP_PAINTMODE_ERASER,
- GP_PAINTMODE_DRAW_STRAIGHT,
- GP_PAINTMODE_DRAW_POLY,
- GP_PAINTMODE_SET_CP,
+ GP_PAINTMODE_DRAW = 0,
+ GP_PAINTMODE_ERASER,
+ GP_PAINTMODE_DRAW_STRAIGHT,
+ GP_PAINTMODE_DRAW_POLY,
+ GP_PAINTMODE_SET_CP,
} eGPencil_PaintModes;
/* maximum sizes of gp-session buffer */
-#define GP_STROKE_BUFFER_MAX 5000
+#define GP_STROKE_BUFFER_MAX 5000
/* stroke editing ----- */
@@ -436,21 +455,21 @@ void GPENCIL_OT_frame_clean_loose(struct wmOperatorType *ot);
void GPENCIL_OT_convert(struct wmOperatorType *ot);
enum {
- GP_STROKE_JOIN = -1,
- GP_STROKE_JOINCOPY = 1,
+ GP_STROKE_JOIN = -1,
+ GP_STROKE_JOINCOPY = 1,
};
enum {
- GP_STROKE_BOX = -1,
- GP_STROKE_LINE = 1,
- GP_STROKE_CIRCLE = 2,
- GP_STROKE_ARC = 3,
- GP_STROKE_CURVE = 4,
+ GP_STROKE_BOX = -1,
+ GP_STROKE_LINE = 1,
+ GP_STROKE_CIRCLE = 2,
+ GP_STROKE_ARC = 3,
+ GP_STROKE_CURVE = 4,
};
enum {
- GP_MERGE_STROKE = -1,
- GP_MERGE_POINT = 1,
+ GP_MERGE_STROKE = -1,
+ GP_MERGE_POINT = 1,
};
void GPENCIL_OT_stroke_arrange(struct wmOperatorType *ot);
@@ -520,20 +539,20 @@ void GPENCIL_OT_generate_weights(struct wmOperatorType *ot);
/* XXX - TODO: replace this with the modern bAnimListElem... */
/* This struct defines a structure used for quick access */
typedef struct bActListElem {
- struct bActListElem *next, *prev;
+ struct bActListElem *next, *prev;
- void *data; /* source data this elem represents */
- int type; /* one of the ACTTYPE_* values */
- int flag; /* copy of elem's flags for quick access */
- int index; /* copy of adrcode where applicable */
+ void *data; /* source data this elem represents */
+ int type; /* one of the ACTTYPE_* values */
+ int flag; /* copy of elem's flags for quick access */
+ int index; /* copy of adrcode where applicable */
- void *key_data; /* motion data - ipo or ipo-curve */
- short datatype; /* type of motion data to expect */
+ void *key_data; /* motion data - ipo or ipo-curve */
+ short datatype; /* type of motion data to expect */
- struct bActionGroup *grp; /* action group that owns the channel */
+ struct bActionGroup *grp; /* action group that owns the channel */
- void *owner; /* will either be an action channel or fake ipo-channel (for keys) */
- short ownertype; /* type of owner */
+ void *owner; /* will either be an action channel or fake ipo-channel (for keys) */
+ short ownertype; /* type of owner */
} bActListElem;
/* ****************************************************** */
@@ -541,29 +560,29 @@ typedef struct bActListElem {
/* filtering flags - under what circumstances should a channel be added */
typedef enum ACTFILTER_FLAGS {
- ACTFILTER_VISIBLE = (1 << 0), /* should channels be visible */
- ACTFILTER_SEL = (1 << 1), /* should channels be selected */
- ACTFILTER_FOREDIT = (1 << 2), /* does editable status matter */
- ACTFILTER_CHANNELS = (1 << 3), /* do we only care that it is a channel */
- ACTFILTER_IPOKEYS = (1 << 4), /* only channels referencing ipo's */
- ACTFILTER_ONLYICU = (1 << 5), /* only reference ipo-curves */
- ACTFILTER_FORDRAWING = (1 << 6), /* make list for interface drawing */
- ACTFILTER_ACTGROUPED = (1 << 7), /* belongs to the active group */
+ ACTFILTER_VISIBLE = (1 << 0), /* should channels be visible */
+ ACTFILTER_SEL = (1 << 1), /* should channels be selected */
+ ACTFILTER_FOREDIT = (1 << 2), /* does editable status matter */
+ ACTFILTER_CHANNELS = (1 << 3), /* do we only care that it is a channel */
+ ACTFILTER_IPOKEYS = (1 << 4), /* only channels referencing ipo's */
+ ACTFILTER_ONLYICU = (1 << 5), /* only reference ipo-curves */
+ ACTFILTER_FORDRAWING = (1 << 6), /* make list for interface drawing */
+ ACTFILTER_ACTGROUPED = (1 << 7), /* belongs to the active group */
} ACTFILTER_FLAGS;
/* Action Editor - Main Data types */
typedef enum ACTCONT_TYPES {
- ACTCONT_NONE = 0,
- ACTCONT_ACTION,
- ACTCONT_SHAPEKEY,
- ACTCONT_GPENCIL,
+ ACTCONT_NONE = 0,
+ ACTCONT_ACTION,
+ ACTCONT_SHAPEKEY,
+ ACTCONT_GPENCIL,
} ACTCONT_TYPES;
/* ****************************************************** */
/* Stroke Iteration Utilities */
struct GP_EditableStrokes_Iter {
- float diff_mat[4][4];
+ float diff_mat[4][4];
};
/**
@@ -576,42 +595,42 @@ struct GP_EditableStrokes_Iter {
* \param gps: The identifier to use for current stroke being processed.
* Choose a suitable value to avoid name clashes.
*/
-#define GP_EDITABLE_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) \
-{ \
- struct GP_EditableStrokes_Iter gpstroke_iter = {{{0}}}; \
- Depsgraph *depsgraph_ = CTX_data_depsgraph(C); \
- Object *obact_ = CTX_data_active_object(C); \
- bGPdata *gpd_ = CTX_data_gpencil_data(C); \
- const bool is_multiedit_ = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_); \
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) \
- { \
- 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); \
- /* loop over strokes */ \
- 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; \
- /* check if the color is editable */ \
- if (ED_gpencil_stroke_color_use(obact_, gpl, gps) == false) \
- continue; \
- /* ... Do Stuff With Strokes ... */
-
-#define GP_EDITABLE_STROKES_END(gpstroke_iter) \
- } \
- } \
- if (!is_multiedit_) { \
- break; \
- } \
- } \
- } \
- CTX_DATA_END; \
-} (void)0
+#define GP_EDITABLE_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) \
+ { \
+ struct GP_EditableStrokes_Iter gpstroke_iter = {{{0}}}; \
+ Depsgraph *depsgraph_ = CTX_data_depsgraph(C); \
+ Object *obact_ = CTX_data_active_object(C); \
+ bGPdata *gpd_ = CTX_data_gpencil_data(C); \
+ const bool is_multiedit_ = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_); \
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { \
+ 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); \
+ /* loop over strokes */ \
+ 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; \
+ /* check if the color is editable */ \
+ if (ED_gpencil_stroke_color_use(obact_, gpl, gps) == false) \
+ continue; \
+ /* ... Do Stuff With Strokes ... */
+
+#define GP_EDITABLE_STROKES_END(gpstroke_iter) \
+ } \
+ } \
+ if (!is_multiedit_) { \
+ break; \
+ } \
+ } \
+ } \
+ CTX_DATA_END; \
+ } \
+ (void)0
/* ****************************************************** */
diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c
index 7be157b5d84..5c9b9416330 100644
--- a/source/blender/editors/gpencil/gpencil_interpolate.c
+++ b/source/blender/editors/gpencil/gpencil_interpolate.c
@@ -22,7 +22,6 @@
* \ingroup edgpencil
*/
-
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -82,46 +81,48 @@
/* Poll callback for interpolation operators */
static bool gpencil_view3d_poll(bContext *C)
{
- bGPdata *gpd = CTX_data_gpencil_data(C);
- bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
- /* only 3D view */
- ScrArea *sa = CTX_wm_area(C);
- if (sa && sa->spacetype != SPACE_VIEW3D) {
- return 0;
- }
+ /* only 3D view */
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa && sa->spacetype != SPACE_VIEW3D) {
+ return 0;
+ }
- /* need data to interpolate */
- if (ELEM(NULL, gpd, gpl)) {
- return 0;
- }
+ /* need data to interpolate */
+ if (ELEM(NULL, gpd, gpl)) {
+ return 0;
+ }
- return 1;
+ return 1;
}
/* Perform interpolation */
-static void gp_interpolate_update_points(
- const bGPDstroke *gps_from, const bGPDstroke *gps_to, bGPDstroke *new_stroke, float factor)
+static void gp_interpolate_update_points(const bGPDstroke *gps_from,
+ const bGPDstroke *gps_to,
+ bGPDstroke *new_stroke,
+ float factor)
{
- /* update points */
- for (int i = 0; i < new_stroke->totpoints; i++) {
- const bGPDspoint *prev = &gps_from->points[i];
- const bGPDspoint *next = &gps_to->points[i];
- bGPDspoint *pt = &new_stroke->points[i];
-
- /* Interpolate all values */
- interp_v3_v3v3(&pt->x, &prev->x, &next->x, factor);
- 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 */
+ /* update points */
+ for (int i = 0; i < new_stroke->totpoints; i++) {
+ const bGPDspoint *prev = &gps_from->points[i];
+ const bGPDspoint *next = &gps_to->points[i];
+ bGPDspoint *pt = &new_stroke->points[i];
+
+ /* Interpolate all values */
+ interp_v3_v3v3(&pt->x, &prev->x, &next->x, factor);
+ 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;
+ MDeformVert *dvert = &new_stroke->dvert[i];
+ dvert->totweight = 0;
+ dvert->dw = NULL;
#endif
- }
+ }
}
/* ****************** Interpolate Interactive *********************** */
@@ -129,212 +130,223 @@ static void gp_interpolate_update_points(
/* 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;
- const float factor = tgpil->factor + shift;
-
- for (new_stroke = tgpil->interFrame->strokes.first; new_stroke; new_stroke = new_stroke->next) {
- bGPDstroke *gps_from, *gps_to;
- int stroke_idx;
-
- if (new_stroke->totpoints == 0) {
- continue;
- }
-
- /* get strokes to interpolate */
- stroke_idx = BLI_findindex(&tgpil->interFrame->strokes, new_stroke);
-
- gps_from = BLI_findlink(&tgpil->prevFrame->strokes, stroke_idx);
- gps_to = BLI_findlink(&tgpil->nextFrame->strokes, stroke_idx);
-
- /* update points position */
- if ((gps_from) && (gps_to)) {
- gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor);
- }
- }
- }
-
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+ bGPdata *gpd = tgpi->gpd;
+ tGPDinterpolate_layer *tgpil;
+ const float shift = tgpi->shift;
+
+ for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
+ bGPDstroke *new_stroke;
+ const float factor = tgpil->factor + shift;
+
+ for (new_stroke = tgpil->interFrame->strokes.first; new_stroke;
+ new_stroke = new_stroke->next) {
+ bGPDstroke *gps_from, *gps_to;
+ int stroke_idx;
+
+ if (new_stroke->totpoints == 0) {
+ continue;
+ }
+
+ /* get strokes to interpolate */
+ stroke_idx = BLI_findindex(&tgpil->interFrame->strokes, new_stroke);
+
+ gps_from = BLI_findlink(&tgpil->prevFrame->strokes, stroke_idx);
+ gps_to = BLI_findlink(&tgpil->nextFrame->strokes, stroke_idx);
+
+ /* update points position */
+ if ((gps_from) && (gps_to)) {
+ gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor);
+ }
+ }
+ }
+
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
}
/* Helper: Verify valid strokes for interpolation */
static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd)
{
- Object *ob = CTX_data_active_object(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- eGP_Interpolate_SettingsFlag flag = ts->gp_interpolate.flag;
-
- /* get layers */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* 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)) {
- continue;
- }
-
- /* read strokes */
- for (bGPDstroke *gps_from = gpl->actframe->strokes.first; gps_from; gps_from = gps_from->next) {
- bGPDstroke *gps_to;
- int fFrame;
-
- /* only selected */
- if ((flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
- continue;
- }
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps_from) == false) {
- continue;
- }
- /* check if the color is editable */
- if (ED_gpencil_stroke_color_use(ob, gpl, gps_from) == false) {
- continue;
- }
-
- /* get final stroke to interpolate */
- fFrame = BLI_findindex(&gpl->actframe->strokes, gps_from);
- gps_to = BLI_findlink(&gpl->actframe->next->strokes, fFrame);
- if (gps_to == NULL) {
- continue;
- }
-
- return true;
- }
- }
- return false;
+ Object *ob = CTX_data_active_object(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ eGP_Interpolate_SettingsFlag flag = ts->gp_interpolate.flag;
+
+ /* get layers */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* 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)) {
+ continue;
+ }
+
+ /* read strokes */
+ for (bGPDstroke *gps_from = gpl->actframe->strokes.first; gps_from;
+ gps_from = gps_from->next) {
+ bGPDstroke *gps_to;
+ int fFrame;
+
+ /* only selected */
+ if ((flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) &&
+ ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
+ continue;
+ }
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps_from) == false) {
+ continue;
+ }
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps_from) == false) {
+ continue;
+ }
+
+ /* get final stroke to interpolate */
+ fFrame = BLI_findindex(&gpl->actframe->strokes, gps_from);
+ gps_to = BLI_findlink(&gpl->actframe->next->strokes, fFrame);
+ if (gps_to == NULL) {
+ continue;
+ }
+
+ return true;
+ }
+ }
+ return false;
}
/* Helper: Create internal strokes interpolated */
static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
{
- bGPdata *gpd = tgpi->gpd;
- bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C);
- bGPDframe *actframe = active_gpl->actframe;
- Object *ob = CTX_data_active_object(C);
-
- /* save initial factor for active layer to define shift limits */
- tgpi->init_factor = (float)(tgpi->cframe - actframe->framenum) / (actframe->next->framenum - actframe->framenum + 1);
-
- /* limits are 100% below 0 and 100% over the 100% */
- tgpi->low_limit = -1.0f - tgpi->init_factor;
- tgpi->high_limit = 2.0f - tgpi->init_factor;
-
- /* set layers */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- tGPDinterpolate_layer *tgpil;
-
- /* all layers or only active */
- if (!(tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS) && (gpl != active_gpl)) {
- continue;
- }
- /* only editable and visible layers are considered */
- if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
- continue;
- }
-
- /* create temp data for each layer */
- tgpil = MEM_callocN(sizeof(tGPDinterpolate_layer), "GPencil Interpolate Layer");
-
- tgpil->gpl = gpl;
- tgpil->prevFrame = gpl->actframe;
- tgpil->nextFrame = gpl->actframe->next;
-
- BLI_addtail(&tgpi->ilayers, tgpil);
-
- /* create a new temporary frame */
- tgpil->interFrame = MEM_callocN(sizeof(bGPDframe), "bGPDframe");
- tgpil->interFrame->framenum = tgpi->cframe;
-
- /* get interpolation factor by layer (usually must be equal for all layers, but not sure) */
- tgpil->factor = (float)(tgpi->cframe - tgpil->prevFrame->framenum) / (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) {
- bGPDstroke *gps_to;
- int fFrame;
-
- bGPDstroke *new_stroke = NULL;
- bool valid = true;
-
-
- /* only selected */
- if ((tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
- valid = false;
- }
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps_from) == false) {
- valid = false;
- }
-
- /* check if the color is editable */
- if (ED_gpencil_stroke_color_use(ob, tgpil->gpl, gps_from) == false) {
- valid = false;
- }
-
- /* get final stroke to interpolate */
- fFrame = BLI_findindex(&tgpil->prevFrame->strokes, gps_from);
- gps_to = BLI_findlink(&tgpil->nextFrame->strokes, fFrame);
- if (gps_to == NULL) {
- valid = false;
- }
-
- /* create new stroke */
- new_stroke = BKE_gpencil_stroke_duplicate(gps_from);
-
- if (valid) {
- /* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
- if (gps_from->totpoints > gps_to->totpoints) {
- new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points) * gps_to->totpoints);
- if (new_stroke->dvert != NULL) {
- 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, tgpil->factor);
- }
- else {
- /* need an empty stroke to keep index correct for lookup, but resize to smallest size */
- new_stroke->totpoints = 0;
- new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points));
- 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;
- }
-
- /* add to strokes */
- BLI_addtail(&tgpil->interFrame->strokes, new_stroke);
- }
- }
+ bGPdata *gpd = tgpi->gpd;
+ bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C);
+ bGPDframe *actframe = active_gpl->actframe;
+ Object *ob = CTX_data_active_object(C);
+
+ /* save initial factor for active layer to define shift limits */
+ tgpi->init_factor = (float)(tgpi->cframe - actframe->framenum) /
+ (actframe->next->framenum - actframe->framenum + 1);
+
+ /* limits are 100% below 0 and 100% over the 100% */
+ tgpi->low_limit = -1.0f - tgpi->init_factor;
+ tgpi->high_limit = 2.0f - tgpi->init_factor;
+
+ /* set layers */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ tGPDinterpolate_layer *tgpil;
+
+ /* all layers or only active */
+ if (!(tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS) && (gpl != active_gpl)) {
+ continue;
+ }
+ /* only editable and visible layers are considered */
+ if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
+ continue;
+ }
+
+ /* create temp data for each layer */
+ tgpil = MEM_callocN(sizeof(tGPDinterpolate_layer), "GPencil Interpolate Layer");
+
+ tgpil->gpl = gpl;
+ tgpil->prevFrame = gpl->actframe;
+ tgpil->nextFrame = gpl->actframe->next;
+
+ BLI_addtail(&tgpi->ilayers, tgpil);
+
+ /* create a new temporary frame */
+ tgpil->interFrame = MEM_callocN(sizeof(bGPDframe), "bGPDframe");
+ tgpil->interFrame->framenum = tgpi->cframe;
+
+ /* get interpolation factor by layer (usually must be equal for all layers, but not sure) */
+ tgpil->factor = (float)(tgpi->cframe - tgpil->prevFrame->framenum) /
+ (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) {
+ bGPDstroke *gps_to;
+ int fFrame;
+
+ bGPDstroke *new_stroke = NULL;
+ bool valid = true;
+
+ /* only selected */
+ if ((tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) &&
+ ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
+ valid = false;
+ }
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps_from) == false) {
+ valid = false;
+ }
+
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(ob, tgpil->gpl, gps_from) == false) {
+ valid = false;
+ }
+
+ /* get final stroke to interpolate */
+ fFrame = BLI_findindex(&tgpil->prevFrame->strokes, gps_from);
+ gps_to = BLI_findlink(&tgpil->nextFrame->strokes, fFrame);
+ if (gps_to == NULL) {
+ valid = false;
+ }
+
+ /* create new stroke */
+ new_stroke = BKE_gpencil_stroke_duplicate(gps_from);
+
+ if (valid) {
+ /* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
+ if (gps_from->totpoints > gps_to->totpoints) {
+ new_stroke->points = MEM_recallocN(new_stroke->points,
+ sizeof(*new_stroke->points) * gps_to->totpoints);
+ if (new_stroke->dvert != NULL) {
+ 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, tgpil->factor);
+ }
+ else {
+ /* need an empty stroke to keep index correct for lookup, but resize to smallest size */
+ new_stroke->totpoints = 0;
+ new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points));
+ 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;
+ }
+
+ /* add to strokes */
+ BLI_addtail(&tgpil->interFrame->strokes, new_stroke);
+ }
+ }
}
/* ----------------------- */
/* 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)
+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);
+ 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);
+ tGPDinterpolate *tgpi = (tGPDinterpolate *)arg;
+ ED_gp_draw_interpolation(C, tgpi, REGION_DRAW_POST_VIEW);
}
/* ----------------------- */
@@ -344,52 +356,57 @@ static void gpencil_interpolate_draw_3d(const bContext *C, ARegion *UNUSED(ar),
*/
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;
-
- if (mpos >= mid) {
- tgpi->shift = ((mpos - mid) * tgpi->high_limit) / mid;
- }
- else {
- tgpi->shift = tgpi->low_limit - ((mpos * tgpi->low_limit) / mid);
- }
-
- CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
- RNA_float_set(op->ptr, "shift", tgpi->shift);
+ float mid = (float)(tgpi->ar->winx - tgpi->ar->winrct.xmin) / 2.0f;
+ float mpos = event->x - tgpi->ar->winrct.xmin;
+
+ if (mpos >= mid) {
+ tgpi->shift = ((mpos - mid) * tgpi->high_limit) / mid;
+ }
+ else {
+ tgpi->shift = tgpi->low_limit - ((mpos * tgpi->low_limit) / mid);
+ }
+
+ CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
+ RNA_float_set(op->ptr, "shift", tgpi->shift);
}
/* Helper: Draw status message while the user is running the operator */
static void gpencil_interpolate_status_indicators(bContext *C, tGPDinterpolate *p)
{
- Scene *scene = p->scene;
- char status_str[UI_MAX_DRAW_STR];
- char msg_str[UI_MAX_DRAW_STR];
-
- BLI_strncpy(msg_str, IFACE_("GPencil Interpolation: "), UI_MAX_DRAW_STR);
-
- if (hasNumInput(&p->num)) {
- char str_offs[NUM_STR_REP_LEN];
-
- outputNumInput(&p->num, str_offs, &scene->unit);
- BLI_snprintf(status_str, sizeof(status_str), "%s%s", msg_str, str_offs);
- }
- else {
- BLI_snprintf(status_str, sizeof(status_str), "%s%d %%", msg_str, (int)((p->init_factor + p->shift) * 100.0f));
- }
-
- ED_area_status_text(p->sa, status_str);
- ED_workspace_status_text(C, IFACE_("ESC/RMB to cancel, Enter/LMB to confirm, WHEEL/MOVE to adjust factor"));
+ Scene *scene = p->scene;
+ char status_str[UI_MAX_DRAW_STR];
+ char msg_str[UI_MAX_DRAW_STR];
+
+ BLI_strncpy(msg_str, IFACE_("GPencil Interpolation: "), UI_MAX_DRAW_STR);
+
+ if (hasNumInput(&p->num)) {
+ char str_offs[NUM_STR_REP_LEN];
+
+ outputNumInput(&p->num, str_offs, &scene->unit);
+ BLI_snprintf(status_str, sizeof(status_str), "%s%s", msg_str, str_offs);
+ }
+ else {
+ BLI_snprintf(status_str,
+ sizeof(status_str),
+ "%s%d %%",
+ msg_str,
+ (int)((p->init_factor + p->shift) * 100.0f));
+ }
+
+ ED_area_status_text(p->sa, status_str);
+ ED_workspace_status_text(
+ C, IFACE_("ESC/RMB to cancel, Enter/LMB to confirm, WHEEL/MOVE to adjust factor"));
}
/* Update screen and stroke */
static void gpencil_interpolate_update(bContext *C, wmOperator *op, tGPDinterpolate *tgpi)
{
- /* update shift indicator in header */
- gpencil_interpolate_status_indicators(C, tgpi);
- /* apply... */
- tgpi->shift = RNA_float_get(op->ptr, "shift");
- /* update points position */
- gp_interpolate_update_strokes(C, tgpi);
+ /* update shift indicator in header */
+ gpencil_interpolate_status_indicators(C, tgpi);
+ /* apply... */
+ tgpi->shift = RNA_float_get(op->ptr, "shift");
+ /* update points position */
+ gp_interpolate_update_strokes(C, tgpi);
}
/* ----------------------- */
@@ -397,93 +414,93 @@ static void gpencil_interpolate_update(bContext *C, wmOperator *op, tGPDinterpol
/* Exit and free memory */
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_workspace_status_text(C, NULL);
-
- /* finally, free memory used by temp data */
- for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
- BKE_gpencil_free_strokes(tgpil->interFrame);
- MEM_freeN(tgpil->interFrame);
- }
-
- BLI_freelistN(&tgpi->ilayers);
- MEM_freeN(tgpi);
- }
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
-
- /* clear pointer */
- op->customdata = NULL;
+ 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_workspace_status_text(C, NULL);
+
+ /* finally, free memory used by temp data */
+ for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
+ BKE_gpencil_free_strokes(tgpil->interFrame);
+ MEM_freeN(tgpil->interFrame);
+ }
+
+ BLI_freelistN(&tgpi->ilayers);
+ MEM_freeN(tgpi);
+ }
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+
+ /* clear pointer */
+ op->customdata = NULL;
}
/* Init new temporary interpolation data */
static bool gp_interpolate_set_init_values(bContext *C, wmOperator *op, tGPDinterpolate *tgpi)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- bGPdata *gpd = CTX_data_gpencil_data(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
- /* set current scene and window */
- tgpi->scene = CTX_data_scene(C);
- tgpi->sa = CTX_wm_area(C);
- tgpi->ar = CTX_wm_region(C);
- tgpi->flag = ts->gp_interpolate.flag;
+ /* set current scene and window */
+ tgpi->scene = CTX_data_scene(C);
+ tgpi->sa = CTX_wm_area(C);
+ tgpi->ar = CTX_wm_region(C);
+ tgpi->flag = ts->gp_interpolate.flag;
- /* set current frame number */
- tgpi->cframe = tgpi->scene->r.cfra;
+ /* set current frame number */
+ tgpi->cframe = tgpi->scene->r.cfra;
- /* set GP datablock */
- tgpi->gpd = gpd;
+ /* set GP datablock */
+ tgpi->gpd = gpd;
- /* set interpolation weight */
- tgpi->shift = RNA_float_get(op->ptr, "shift");
- /* set layers */
- gp_interpolate_set_points(C, tgpi);
+ /* set interpolation weight */
+ tgpi->shift = RNA_float_get(op->ptr, "shift");
+ /* set layers */
+ gp_interpolate_set_points(C, tgpi);
- return 1;
+ return 1;
}
/* Allocate memory and initialize values */
static tGPDinterpolate *gp_session_init_interpolation(bContext *C, wmOperator *op)
{
- tGPDinterpolate *tgpi = MEM_callocN(sizeof(tGPDinterpolate), "GPencil Interpolate Data");
+ tGPDinterpolate *tgpi = MEM_callocN(sizeof(tGPDinterpolate), "GPencil Interpolate Data");
- /* define initial values */
- gp_interpolate_set_init_values(C, op, tgpi);
+ /* define initial values */
+ gp_interpolate_set_init_values(C, op, tgpi);
- /* return context data for running operator */
- return tgpi;
+ /* return context data for running operator */
+ return tgpi;
}
/* Init interpolation: Allocate memory and set init values */
static int gpencil_interpolate_init(bContext *C, wmOperator *op)
{
- tGPDinterpolate *tgpi;
-
- /* check context */
- tgpi = op->customdata = gp_session_init_interpolation(C, op);
- if (tgpi == NULL) {
- /* something wasn't set correctly in context */
- gpencil_interpolate_exit(C, op);
- return 0;
- }
-
- /* everything is now setup ok */
- return 1;
+ tGPDinterpolate *tgpi;
+
+ /* check context */
+ tgpi = op->customdata = gp_session_init_interpolation(C, op);
+ if (tgpi == NULL) {
+ /* something wasn't set correctly in context */
+ gpencil_interpolate_exit(C, op);
+ return 0;
+ }
+
+ /* everything is now setup ok */
+ return 1;
}
/* ----------------------- */
@@ -491,219 +508,230 @@ static int gpencil_interpolate_init(bContext *C, wmOperator *op)
/* Invoke handler: Initialize the operator */
static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- wmWindow *win = CTX_wm_window(C);
- bGPdata *gpd = CTX_data_gpencil_data(C);
- bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
- bGPDframe *actframe = gpl->actframe;
- tGPDinterpolate *tgpi = NULL;
-
- /* cannot interpolate if not between 2 frames */
- if (ELEM(NULL, actframe, actframe->next)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot find a pair of grease pencil frames to interpolate between in active layer");
- return OPERATOR_CANCELLED;
- }
-
- /* cannot interpolate in extremes */
- if (ELEM(cfra_eval, actframe->framenum, actframe->next->framenum)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot interpolate as current frame already has existing grease pencil frames");
- return OPERATOR_CANCELLED;
- }
-
- /* need editable strokes */
- if (!gp_interpolate_check_todo(C, gpd)) {
- BKE_report(op->reports, RPT_ERROR, "Interpolation requires some editable strokes");
- return OPERATOR_CANCELLED;
- }
-
- /* try to initialize context data needed */
- if (!gpencil_interpolate_init(C, op)) {
- if (op->customdata)
- MEM_freeN(op->customdata);
- return OPERATOR_CANCELLED;
- }
- else {
- 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, BC_EW_SCROLLCURSOR);
-
- /* update shift indicator in header */
- gpencil_interpolate_status_indicators(C, tgpi);
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
-
- /* add a modal handler for this operator */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
+ wmWindow *win = CTX_wm_window(C);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+ bGPDframe *actframe = gpl->actframe;
+ tGPDinterpolate *tgpi = NULL;
+
+ /* cannot interpolate if not between 2 frames */
+ if (ELEM(NULL, actframe, actframe->next)) {
+ BKE_report(
+ op->reports,
+ RPT_ERROR,
+ "Cannot find a pair of grease pencil frames to interpolate between in active layer");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* cannot interpolate in extremes */
+ if (ELEM(cfra_eval, actframe->framenum, actframe->next->framenum)) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Cannot interpolate as current frame already has existing grease pencil frames");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* need editable strokes */
+ if (!gp_interpolate_check_todo(C, gpd)) {
+ BKE_report(op->reports, RPT_ERROR, "Interpolation requires some editable strokes");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* try to initialize context data needed */
+ if (!gpencil_interpolate_init(C, op)) {
+ if (op->customdata)
+ MEM_freeN(op->customdata);
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ 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, BC_EW_SCROLLCURSOR);
+
+ /* update shift indicator in header */
+ gpencil_interpolate_status_indicators(C, tgpi);
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+
+ /* add a modal handler for this operator */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
}
/* Modal handler: Events handling during interactive part */
static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- tGPDinterpolate *tgpi = op->customdata;
- wmWindow *win = CTX_wm_window(C);
- bGPDframe *gpf_dst;
- bGPDstroke *gps_src, *gps_dst;
- tGPDinterpolate_layer *tgpil;
- const bool has_numinput = hasNumInput(&tgpi->num);
-
- switch (event->type) {
- case LEFTMOUSE: /* confirm */
- case RETKEY:
- {
- /* return to normal cursor and header status */
- ED_area_status_text(tgpi->sa, 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);
- 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) {
- 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;
- BLI_addtail(&gpf_dst->strokes, gps_dst);
- }
- }
-
- /* clean up temp data */
- gpencil_interpolate_exit(C, op);
-
- /* done! */
- return OPERATOR_FINISHED;
- }
-
- case ESCKEY: /* cancel */
- case RIGHTMOUSE:
- {
- /* return to normal cursor and header status */
- ED_area_status_text(tgpi->sa, NULL);
- ED_workspace_status_text(C, NULL);
- WM_cursor_modal_restore(win);
-
- /* clean up temp data */
- gpencil_interpolate_exit(C, op);
-
- /* canceled! */
- return OPERATOR_CANCELLED;
- }
-
- case WHEELUPMOUSE:
- {
- tgpi->shift = tgpi->shift + 0.01f;
- CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
- RNA_float_set(op->ptr, "shift", tgpi->shift);
-
- /* update screen */
- gpencil_interpolate_update(C, op, tgpi);
- break;
- }
- case WHEELDOWNMOUSE:
- {
- tgpi->shift = tgpi->shift - 0.01f;
- CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
- RNA_float_set(op->ptr, "shift", tgpi->shift);
-
- /* update screen */
- gpencil_interpolate_update(C, op, tgpi);
- break;
- }
- case MOUSEMOVE: /* calculate new position */
- {
- /* only handle mousemove if not doing numinput */
- if (has_numinput == false) {
- /* update shift based on position of mouse */
- gpencil_mouse_update_shift(tgpi, op, event);
-
- /* update screen */
- gpencil_interpolate_update(C, op, tgpi);
- }
- break;
- }
- default:
- {
- if ((event->val == KM_PRESS) && handleNumInput(C, &tgpi->num, event)) {
- const float factor = tgpi->init_factor;
- float value;
-
- /* Grab shift from numeric input, and store this new value (the user see an int) */
- value = (factor + tgpi->shift) * 100.0f;
- applyNumInput(&tgpi->num, &value);
- tgpi->shift = value / 100.0f;
-
- /* recalculate the shift to get the right value in the frame scale */
- tgpi->shift = tgpi->shift - factor;
-
- CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
- RNA_float_set(op->ptr, "shift", tgpi->shift);
-
- /* update screen */
- gpencil_interpolate_update(C, op, tgpi);
-
- break;
- }
- else {
- /* unhandled event - allow to pass through */
- return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH;
- }
- }
- }
-
- /* still running... */
- return OPERATOR_RUNNING_MODAL;
+ tGPDinterpolate *tgpi = op->customdata;
+ wmWindow *win = CTX_wm_window(C);
+ bGPDframe *gpf_dst;
+ bGPDstroke *gps_src, *gps_dst;
+ tGPDinterpolate_layer *tgpil;
+ const bool has_numinput = hasNumInput(&tgpi->num);
+
+ switch (event->type) {
+ case LEFTMOUSE: /* confirm */
+ case RETKEY: {
+ /* return to normal cursor and header status */
+ ED_area_status_text(tgpi->sa, 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);
+ 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) {
+ 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;
+ BLI_addtail(&gpf_dst->strokes, gps_dst);
+ }
+ }
+
+ /* clean up temp data */
+ gpencil_interpolate_exit(C, op);
+
+ /* done! */
+ return OPERATOR_FINISHED;
+ }
+
+ case ESCKEY: /* cancel */
+ case RIGHTMOUSE: {
+ /* return to normal cursor and header status */
+ ED_area_status_text(tgpi->sa, NULL);
+ ED_workspace_status_text(C, NULL);
+ WM_cursor_modal_restore(win);
+
+ /* clean up temp data */
+ gpencil_interpolate_exit(C, op);
+
+ /* canceled! */
+ return OPERATOR_CANCELLED;
+ }
+
+ case WHEELUPMOUSE: {
+ tgpi->shift = tgpi->shift + 0.01f;
+ CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
+ RNA_float_set(op->ptr, "shift", tgpi->shift);
+
+ /* update screen */
+ gpencil_interpolate_update(C, op, tgpi);
+ break;
+ }
+ case WHEELDOWNMOUSE: {
+ tgpi->shift = tgpi->shift - 0.01f;
+ CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
+ RNA_float_set(op->ptr, "shift", tgpi->shift);
+
+ /* update screen */
+ gpencil_interpolate_update(C, op, tgpi);
+ break;
+ }
+ case MOUSEMOVE: /* calculate new position */
+ {
+ /* only handle mousemove if not doing numinput */
+ if (has_numinput == false) {
+ /* update shift based on position of mouse */
+ gpencil_mouse_update_shift(tgpi, op, event);
+
+ /* update screen */
+ gpencil_interpolate_update(C, op, tgpi);
+ }
+ break;
+ }
+ default: {
+ if ((event->val == KM_PRESS) && handleNumInput(C, &tgpi->num, event)) {
+ const float factor = tgpi->init_factor;
+ float value;
+
+ /* Grab shift from numeric input, and store this new value (the user see an int) */
+ value = (factor + tgpi->shift) * 100.0f;
+ applyNumInput(&tgpi->num, &value);
+ tgpi->shift = value / 100.0f;
+
+ /* recalculate the shift to get the right value in the frame scale */
+ tgpi->shift = tgpi->shift - factor;
+
+ CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
+ RNA_float_set(op->ptr, "shift", tgpi->shift);
+
+ /* update screen */
+ gpencil_interpolate_update(C, op, tgpi);
+
+ break;
+ }
+ else {
+ /* unhandled event - allow to pass through */
+ return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH;
+ }
+ }
+ }
+
+ /* still running... */
+ return OPERATOR_RUNNING_MODAL;
}
/* Cancel handler */
static void gpencil_interpolate_cancel(bContext *C, wmOperator *op)
{
- /* this is just a wrapper around exit() */
- gpencil_interpolate_exit(C, op);
+ /* this is just a wrapper around exit() */
+ gpencil_interpolate_exit(C, op);
}
void GPENCIL_OT_interpolate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Grease Pencil Interpolation";
- ot->idname = "GPENCIL_OT_interpolate";
- ot->description = "Interpolate grease pencil strokes between frames";
-
- /* callbacks */
- ot->invoke = gpencil_interpolate_invoke;
- ot->modal = gpencil_interpolate_modal;
- ot->cancel = gpencil_interpolate_cancel;
- ot->poll = gpencil_view3d_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* properties */
- RNA_def_float_percentage(ot->srna, "shift", 0.0f, -1.0f, 1.0f, "Shift", "Bias factor for which frame has more influence on the interpolated strokes", -0.9f, 0.9f);
+ /* identifiers */
+ ot->name = "Grease Pencil Interpolation";
+ ot->idname = "GPENCIL_OT_interpolate";
+ ot->description = "Interpolate grease pencil strokes between frames";
+
+ /* callbacks */
+ ot->invoke = gpencil_interpolate_invoke;
+ ot->modal = gpencil_interpolate_modal;
+ ot->cancel = gpencil_interpolate_cancel;
+ ot->poll = gpencil_view3d_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* properties */
+ RNA_def_float_percentage(
+ ot->srna,
+ "shift",
+ 0.0f,
+ -1.0f,
+ 1.0f,
+ "Shift",
+ "Bias factor for which frame has more influence on the interpolated strokes",
+ -0.9f,
+ 0.9f);
}
/* ****************** Interpolate Sequence *********************** */
@@ -711,464 +739,473 @@ void GPENCIL_OT_interpolate(wmOperatorType *ot)
/* Helper: Perform easing equation calculations for GP interpolation operator */
static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_settings, float time)
{
- const float begin = 0.0f;
- const float change = 1.0f;
- const float duration = 1.0f;
-
- const float back = ipo_settings->back;
- const float amplitude = ipo_settings->amplitude;
- const float period = ipo_settings->period;
-
- eBezTriple_Easing easing = ipo_settings->easing;
- float result = time;
-
- switch (ipo_settings->type) {
- case GP_IPO_BACK:
- switch (easing) {
- case BEZT_IPO_EASE_IN:
- result = BLI_easing_back_ease_in(time, begin, change, duration, back);
- break;
- case BEZT_IPO_EASE_OUT:
- result = BLI_easing_back_ease_out(time, begin, change, duration, back);
- break;
- case BEZT_IPO_EASE_IN_OUT:
- result = BLI_easing_back_ease_in_out(time, begin, change, duration, back);
- break;
-
- default: /* default/auto: same as ease out */
- result = BLI_easing_back_ease_out(time, begin, change, duration, back);
- break;
- }
- break;
-
- case GP_IPO_BOUNCE:
- switch (easing) {
- case BEZT_IPO_EASE_IN:
- result = BLI_easing_bounce_ease_in(time, begin, change, duration);
- break;
- case BEZT_IPO_EASE_OUT:
- result = BLI_easing_bounce_ease_out(time, begin, change, duration);
- break;
- case BEZT_IPO_EASE_IN_OUT:
- result = BLI_easing_bounce_ease_in_out(time, begin, change, duration);
- break;
-
- default: /* default/auto: same as ease out */
- result = BLI_easing_bounce_ease_out(time, begin, change, duration);
- break;
- }
- break;
-
- case GP_IPO_CIRC:
- switch (easing) {
- case BEZT_IPO_EASE_IN:
- result = BLI_easing_circ_ease_in(time, begin, change, duration);
- break;
- case BEZT_IPO_EASE_OUT:
- result = BLI_easing_circ_ease_out(time, begin, change, duration);
- break;
- case BEZT_IPO_EASE_IN_OUT:
- result = BLI_easing_circ_ease_in_out(time, begin, change, duration);
- break;
-
- default: /* default/auto: same as ease in */
- result = BLI_easing_circ_ease_in(time, begin, change, duration);
- break;
- }
- break;
-
- case GP_IPO_CUBIC:
- switch (easing) {
- case BEZT_IPO_EASE_IN:
- result = BLI_easing_cubic_ease_in(time, begin, change, duration);
- break;
- case BEZT_IPO_EASE_OUT:
- result = BLI_easing_cubic_ease_out(time, begin, change, duration);
- break;
- case BEZT_IPO_EASE_IN_OUT:
- result = BLI_easing_cubic_ease_in_out(time, begin, change, duration);
- break;
-
- default: /* default/auto: same as ease in */
- result = BLI_easing_cubic_ease_in(time, begin, change, duration);
- break;
- }
- break;
-
- case GP_IPO_ELASTIC:
- switch (easing) {
- case BEZT_IPO_EASE_IN:
- result = BLI_easing_elastic_ease_in(time, begin, change, duration, amplitude, period);
- break;
- case BEZT_IPO_EASE_OUT:
- result = BLI_easing_elastic_ease_out(time, begin, change, duration, amplitude, period);
- break;
- case BEZT_IPO_EASE_IN_OUT:
- result = BLI_easing_elastic_ease_in_out(time, begin, change, duration, amplitude, period);
- break;
-
- default: /* default/auto: same as ease out */
- result = BLI_easing_elastic_ease_out(time, begin, change, duration, amplitude, period);
- break;
- }
- break;
-
- case GP_IPO_EXPO:
- switch (easing) {
- case BEZT_IPO_EASE_IN:
- result = BLI_easing_expo_ease_in(time, begin, change, duration);
- break;
- case BEZT_IPO_EASE_OUT:
- result = BLI_easing_expo_ease_out(time, begin, change, duration);
- break;
- case BEZT_IPO_EASE_IN_OUT:
- result = BLI_easing_expo_ease_in_out(time, begin, change, duration);
- break;
-
- default: /* default/auto: same as ease in */
- result = BLI_easing_expo_ease_in(time, begin, change, duration);
- break;
- }
- break;
-
- case GP_IPO_QUAD:
- switch (easing) {
- case BEZT_IPO_EASE_IN:
- result = BLI_easing_quad_ease_in(time, begin, change, duration);
- break;
- case BEZT_IPO_EASE_OUT:
- result = BLI_easing_quad_ease_out(time, begin, change, duration);
- break;
- case BEZT_IPO_EASE_IN_OUT:
- result = BLI_easing_quad_ease_in_out(time, begin, change, duration);
- break;
-
- default: /* default/auto: same as ease in */
- result = BLI_easing_quad_ease_in(time, begin, change, duration);
- break;
- }
- break;
-
- case GP_IPO_QUART:
- switch (easing) {
- case BEZT_IPO_EASE_IN:
- result = BLI_easing_quart_ease_in(time, begin, change, duration);
- break;
- case BEZT_IPO_EASE_OUT:
- result = BLI_easing_quart_ease_out(time, begin, change, duration);
- break;
- case BEZT_IPO_EASE_IN_OUT:
- result = BLI_easing_quart_ease_in_out(time, begin, change, duration);
- break;
-
- default: /* default/auto: same as ease in */
- result = BLI_easing_quart_ease_in(time, begin, change, duration);
- break;
- }
- break;
-
- case GP_IPO_QUINT:
- switch (easing) {
- case BEZT_IPO_EASE_IN:
- result = BLI_easing_quint_ease_in(time, begin, change, duration);
- break;
- case BEZT_IPO_EASE_OUT:
- result = BLI_easing_quint_ease_out(time, begin, change, duration);
- break;
- case BEZT_IPO_EASE_IN_OUT:
- result = BLI_easing_quint_ease_in_out(time, begin, change, duration);
- break;
-
- default: /* default/auto: same as ease in */
- result = BLI_easing_quint_ease_in(time, begin, change, duration);
- break;
- }
- break;
-
- case GP_IPO_SINE:
- switch (easing) {
- case BEZT_IPO_EASE_IN:
- result = BLI_easing_sine_ease_in(time, begin, change, duration);
- break;
- case BEZT_IPO_EASE_OUT:
- result = BLI_easing_sine_ease_out(time, begin, change, duration);
- break;
- case BEZT_IPO_EASE_IN_OUT:
- result = BLI_easing_sine_ease_in_out(time, begin, change, duration);
- break;
-
- default: /* default/auto: same as ease in */
- result = BLI_easing_sine_ease_in(time, begin, change, duration);
- break;
- }
- break;
-
- default:
- printf("%s: Unknown interpolation type - %d\n", __func__, ipo_settings->type);
- break;
- }
-
- return result;
+ const float begin = 0.0f;
+ const float change = 1.0f;
+ const float duration = 1.0f;
+
+ const float back = ipo_settings->back;
+ const float amplitude = ipo_settings->amplitude;
+ const float period = ipo_settings->period;
+
+ eBezTriple_Easing easing = ipo_settings->easing;
+ float result = time;
+
+ switch (ipo_settings->type) {
+ case GP_IPO_BACK:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_back_ease_in(time, begin, change, duration, back);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_back_ease_out(time, begin, change, duration, back);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_back_ease_in_out(time, begin, change, duration, back);
+ break;
+
+ default: /* default/auto: same as ease out */
+ result = BLI_easing_back_ease_out(time, begin, change, duration, back);
+ break;
+ }
+ break;
+
+ case GP_IPO_BOUNCE:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_bounce_ease_in(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_bounce_ease_out(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_bounce_ease_in_out(time, begin, change, duration);
+ break;
+
+ default: /* default/auto: same as ease out */
+ result = BLI_easing_bounce_ease_out(time, begin, change, duration);
+ break;
+ }
+ break;
+
+ case GP_IPO_CIRC:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_circ_ease_in(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_circ_ease_out(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_circ_ease_in_out(time, begin, change, duration);
+ break;
+
+ default: /* default/auto: same as ease in */
+ result = BLI_easing_circ_ease_in(time, begin, change, duration);
+ break;
+ }
+ break;
+
+ case GP_IPO_CUBIC:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_cubic_ease_in(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_cubic_ease_out(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_cubic_ease_in_out(time, begin, change, duration);
+ break;
+
+ default: /* default/auto: same as ease in */
+ result = BLI_easing_cubic_ease_in(time, begin, change, duration);
+ break;
+ }
+ break;
+
+ case GP_IPO_ELASTIC:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_elastic_ease_in(time, begin, change, duration, amplitude, period);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_elastic_ease_out(time, begin, change, duration, amplitude, period);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_elastic_ease_in_out(
+ time, begin, change, duration, amplitude, period);
+ break;
+
+ default: /* default/auto: same as ease out */
+ result = BLI_easing_elastic_ease_out(time, begin, change, duration, amplitude, period);
+ break;
+ }
+ break;
+
+ case GP_IPO_EXPO:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_expo_ease_in(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_expo_ease_out(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_expo_ease_in_out(time, begin, change, duration);
+ break;
+
+ default: /* default/auto: same as ease in */
+ result = BLI_easing_expo_ease_in(time, begin, change, duration);
+ break;
+ }
+ break;
+
+ case GP_IPO_QUAD:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_quad_ease_in(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_quad_ease_out(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_quad_ease_in_out(time, begin, change, duration);
+ break;
+
+ default: /* default/auto: same as ease in */
+ result = BLI_easing_quad_ease_in(time, begin, change, duration);
+ break;
+ }
+ break;
+
+ case GP_IPO_QUART:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_quart_ease_in(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_quart_ease_out(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_quart_ease_in_out(time, begin, change, duration);
+ break;
+
+ default: /* default/auto: same as ease in */
+ result = BLI_easing_quart_ease_in(time, begin, change, duration);
+ break;
+ }
+ break;
+
+ case GP_IPO_QUINT:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_quint_ease_in(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_quint_ease_out(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_quint_ease_in_out(time, begin, change, duration);
+ break;
+
+ default: /* default/auto: same as ease in */
+ result = BLI_easing_quint_ease_in(time, begin, change, duration);
+ break;
+ }
+ break;
+
+ case GP_IPO_SINE:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_sine_ease_in(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_sine_ease_out(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_sine_ease_in_out(time, begin, change, duration);
+ break;
+
+ default: /* default/auto: same as ease in */
+ result = BLI_easing_sine_ease_in(time, begin, change, duration);
+ break;
+ }
+ break;
+
+ default:
+ printf("%s: Unknown interpolation type - %d\n", __func__, ipo_settings->type);
+ break;
+ }
+
+ return result;
}
static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = CTX_data_gpencil_data(C);
- bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C);
- bGPDframe *actframe = active_gpl->actframe;
-
- Object *ob = CTX_data_active_object(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
-
- GP_Interpolate_Settings *ipo_settings = &ts->gp_interpolate;
- eGP_Interpolate_SettingsFlag flag = ipo_settings->flag;
-
- /* cannot interpolate if not between 2 frames */
- if (ELEM(NULL, actframe, actframe->next)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot find a pair of grease pencil frames to interpolate between in active layer");
- return OPERATOR_CANCELLED;
- }
- /* cannot interpolate in extremes */
- if (ELEM(cfra_eval, actframe->framenum, actframe->next->framenum)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot interpolate as current frame already has existing grease pencil frames");
- return OPERATOR_CANCELLED;
- }
-
- /* loop all layer to check if need interpolation */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- bGPDframe *prevFrame, *nextFrame;
- bGPDstroke *gps_from, *gps_to;
- int cframe, fFrame;
-
- /* 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)) {
- continue;
- }
-
- /* store extremes */
- prevFrame = gpl->actframe;
- nextFrame = gpl->actframe->next;
-
- /* Loop over intermediary frames and create the interpolation */
- for (cframe = prevFrame->framenum + 1; cframe < nextFrame->framenum; cframe++) {
- bGPDframe *interFrame = NULL;
- float factor;
-
- /* get interpolation factor */
- factor = (float)(cframe - prevFrame->framenum) / (nextFrame->framenum - prevFrame->framenum + 1);
-
- if (ipo_settings->type == GP_IPO_CURVEMAP) {
- /* custom curvemap */
- if (ipo_settings->custom_ipo) {
- factor = curvemapping_evaluateF(ipo_settings->custom_ipo, 0, factor);
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Custom interpolation curve does not exist");
- }
- }
- else if (ipo_settings->type >= GP_IPO_BACK) {
- /* easing equation... */
- factor = gp_interpolate_seq_easing_calc(ipo_settings, factor);
- }
-
- /* 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) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
- continue;
- }
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps_from) == false) {
- continue;
- }
- /* check if the color is editable */
- if (ED_gpencil_stroke_color_use(ob, gpl, gps_from) == false) {
- continue;
- }
-
- /* get final stroke to interpolate */
- fFrame = BLI_findindex(&prevFrame->strokes, gps_from);
- gps_to = BLI_findlink(&nextFrame->strokes, fFrame);
- if (gps_to == NULL) {
- continue;
- }
-
- /* create a new frame if needed */
- if (interFrame == NULL) {
- interFrame = BKE_gpencil_layer_getframe(gpl, cframe, GP_GETFRAME_ADD_NEW);
- interFrame->key_type = BEZT_KEYTYPE_BREAKDOWN;
- }
-
- /* create new stroke */
- new_stroke = BKE_gpencil_stroke_duplicate(gps_from);
-
- /* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
- if (gps_from->totpoints > gps_to->totpoints) {
- /* free weights of removed points */
- if (gps_from->dvert != NULL) {
- BKE_defvert_array_free_elems(gps_from->dvert + gps_to->totpoints, gps_from->totpoints - gps_to->totpoints);
- }
-
- new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points) * gps_to->totpoints);
-
- if (new_stroke->dvert != NULL) {
- 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);
-
- /* add to strokes */
- BLI_addtail(&interFrame->strokes, new_stroke);
- }
- }
- }
-
- /* 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;
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C);
+ bGPDframe *actframe = active_gpl->actframe;
+
+ Object *ob = CTX_data_active_object(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+ GP_Interpolate_Settings *ipo_settings = &ts->gp_interpolate;
+ eGP_Interpolate_SettingsFlag flag = ipo_settings->flag;
+
+ /* cannot interpolate if not between 2 frames */
+ if (ELEM(NULL, actframe, actframe->next)) {
+ BKE_report(
+ op->reports,
+ RPT_ERROR,
+ "Cannot find a pair of grease pencil frames to interpolate between in active layer");
+ return OPERATOR_CANCELLED;
+ }
+ /* cannot interpolate in extremes */
+ if (ELEM(cfra_eval, actframe->framenum, actframe->next->framenum)) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Cannot interpolate as current frame already has existing grease pencil frames");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* loop all layer to check if need interpolation */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ bGPDframe *prevFrame, *nextFrame;
+ bGPDstroke *gps_from, *gps_to;
+ int cframe, fFrame;
+
+ /* 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)) {
+ continue;
+ }
+
+ /* store extremes */
+ prevFrame = gpl->actframe;
+ nextFrame = gpl->actframe->next;
+
+ /* Loop over intermediary frames and create the interpolation */
+ for (cframe = prevFrame->framenum + 1; cframe < nextFrame->framenum; cframe++) {
+ bGPDframe *interFrame = NULL;
+ float factor;
+
+ /* get interpolation factor */
+ factor = (float)(cframe - prevFrame->framenum) /
+ (nextFrame->framenum - prevFrame->framenum + 1);
+
+ if (ipo_settings->type == GP_IPO_CURVEMAP) {
+ /* custom curvemap */
+ if (ipo_settings->custom_ipo) {
+ factor = curvemapping_evaluateF(ipo_settings->custom_ipo, 0, factor);
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Custom interpolation curve does not exist");
+ }
+ }
+ else if (ipo_settings->type >= GP_IPO_BACK) {
+ /* easing equation... */
+ factor = gp_interpolate_seq_easing_calc(ipo_settings, factor);
+ }
+
+ /* 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) &&
+ ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
+ continue;
+ }
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps_from) == false) {
+ continue;
+ }
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps_from) == false) {
+ continue;
+ }
+
+ /* get final stroke to interpolate */
+ fFrame = BLI_findindex(&prevFrame->strokes, gps_from);
+ gps_to = BLI_findlink(&nextFrame->strokes, fFrame);
+ if (gps_to == NULL) {
+ continue;
+ }
+
+ /* create a new frame if needed */
+ if (interFrame == NULL) {
+ interFrame = BKE_gpencil_layer_getframe(gpl, cframe, GP_GETFRAME_ADD_NEW);
+ interFrame->key_type = BEZT_KEYTYPE_BREAKDOWN;
+ }
+
+ /* create new stroke */
+ new_stroke = BKE_gpencil_stroke_duplicate(gps_from);
+
+ /* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
+ if (gps_from->totpoints > gps_to->totpoints) {
+ /* free weights of removed points */
+ if (gps_from->dvert != NULL) {
+ BKE_defvert_array_free_elems(gps_from->dvert + gps_to->totpoints,
+ gps_from->totpoints - gps_to->totpoints);
+ }
+
+ new_stroke->points = MEM_recallocN(new_stroke->points,
+ sizeof(*new_stroke->points) * gps_to->totpoints);
+
+ if (new_stroke->dvert != NULL) {
+ 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);
+
+ /* add to strokes */
+ BLI_addtail(&interFrame->strokes, new_stroke);
+ }
+ }
+ }
+
+ /* 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_interpolate_sequence(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Interpolate Sequence";
- ot->idname = "GPENCIL_OT_interpolate_sequence";
- ot->description = "Generate 'in-betweens' to smoothly interpolate between Grease Pencil frames";
+ /* identifiers */
+ ot->name = "Interpolate Sequence";
+ ot->idname = "GPENCIL_OT_interpolate_sequence";
+ ot->description = "Generate 'in-betweens' to smoothly interpolate between Grease Pencil frames";
- /* api callbacks */
- ot->exec = gpencil_interpolate_seq_exec;
- ot->poll = gpencil_view3d_poll;
+ /* api callbacks */
+ ot->exec = gpencil_interpolate_seq_exec;
+ ot->poll = gpencil_view3d_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Remove Breakdowns ************************ */
static bool gpencil_interpolate_reverse_poll(bContext *C)
{
- if (!gpencil_view3d_poll(C)) {
- return 0;
- }
+ if (!gpencil_view3d_poll(C)) {
+ return 0;
+ }
- bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
- /* need to be on a breakdown frame */
- if ((gpl->actframe == NULL) || (gpl->actframe->key_type != BEZT_KEYTYPE_BREAKDOWN)) {
- CTX_wm_operator_poll_msg_set(C, "Expected current frame to be a breakdown");
- return 0;
- }
+ /* need to be on a breakdown frame */
+ if ((gpl->actframe == NULL) || (gpl->actframe->key_type != BEZT_KEYTYPE_BREAKDOWN)) {
+ CTX_wm_operator_poll_msg_set(C, "Expected current frame to be a breakdown");
+ return 0;
+ }
- return 1;
+ return 1;
}
static int gpencil_interpolate_reverse_exec(bContext *C, wmOperator *UNUSED(op))
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
-
- /* Go through each layer, deleting the breakdowns around the current frame,
- * but only if there is a keyframe nearby to stop at
- */
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- bGPDframe *start_key = NULL;
- bGPDframe *end_key = NULL;
- bGPDframe *gpf, *gpfn;
-
- /* Only continue if we're currently on a breakdown keyframe */
- if ((gpl->actframe == NULL) || (gpl->actframe->key_type != BEZT_KEYTYPE_BREAKDOWN))
- continue;
-
- /* Search left for "start_key" (i.e. the first breakdown to remove) */
- gpf = gpl->actframe;
- while (gpf) {
- if (gpf->key_type == BEZT_KEYTYPE_BREAKDOWN) {
- /* A breakdown... keep going left */
- start_key = gpf;
- gpf = gpf->prev;
- }
- else {
- /* Not a breakdown (may be a key, or an extreme,
- * or something else that wasn't generated)... stop */
- break;
- }
- }
-
- /* Search right for "end_key" (i.e. the last breakdown to remove) */
- gpf = gpl->actframe;
- while (gpf) {
- if (gpf->key_type == BEZT_KEYTYPE_BREAKDOWN) {
- /* A breakdown... keep going right */
- end_key = gpf;
- gpf = gpf->next;
- }
- else {
- /* Not a breakdown... stop */
- break;
- }
- }
-
- /* Did we find anything? */
- /* NOTE: We should only proceed if there's something before/after these extents...
- * Otherwise, there's just an extent of breakdowns with no keys to interpolate between
- */
- if ((start_key && end_key) &&
- ELEM(NULL, start_key->prev, end_key->next) == false)
- {
- /* Set actframe to the key before start_key, since the keys have been removed now */
- gpl->actframe = start_key->prev;
-
- /* Free each frame we're removing (except the last one) */
- for (gpf = start_key; gpf && gpf != end_key; gpf = gpfn) {
- gpfn = gpf->next;
-
- /* free strokes and their associated memory */
- BKE_gpencil_free_strokes(gpf);
- BLI_freelinkN(&gpl->frames, gpf);
- }
-
- /* Now free the last one... */
- BKE_gpencil_free_strokes(end_key);
- BLI_freelinkN(&gpl->frames, end_key);
- }
- }
- CTX_DATA_END;
-
- /* 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;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+ /* Go through each layer, deleting the breakdowns around the current frame,
+ * but only if there is a keyframe nearby to stop at
+ */
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ bGPDframe *start_key = NULL;
+ bGPDframe *end_key = NULL;
+ bGPDframe *gpf, *gpfn;
+
+ /* Only continue if we're currently on a breakdown keyframe */
+ if ((gpl->actframe == NULL) || (gpl->actframe->key_type != BEZT_KEYTYPE_BREAKDOWN))
+ continue;
+
+ /* Search left for "start_key" (i.e. the first breakdown to remove) */
+ gpf = gpl->actframe;
+ while (gpf) {
+ if (gpf->key_type == BEZT_KEYTYPE_BREAKDOWN) {
+ /* A breakdown... keep going left */
+ start_key = gpf;
+ gpf = gpf->prev;
+ }
+ else {
+ /* Not a breakdown (may be a key, or an extreme,
+ * or something else that wasn't generated)... stop */
+ break;
+ }
+ }
+
+ /* Search right for "end_key" (i.e. the last breakdown to remove) */
+ gpf = gpl->actframe;
+ while (gpf) {
+ if (gpf->key_type == BEZT_KEYTYPE_BREAKDOWN) {
+ /* A breakdown... keep going right */
+ end_key = gpf;
+ gpf = gpf->next;
+ }
+ else {
+ /* Not a breakdown... stop */
+ break;
+ }
+ }
+
+ /* Did we find anything? */
+ /* NOTE: We should only proceed if there's something before/after these extents...
+ * Otherwise, there's just an extent of breakdowns with no keys to interpolate between
+ */
+ if ((start_key && end_key) && ELEM(NULL, start_key->prev, end_key->next) == false) {
+ /* Set actframe to the key before start_key, since the keys have been removed now */
+ gpl->actframe = start_key->prev;
+
+ /* Free each frame we're removing (except the last one) */
+ for (gpf = start_key; gpf && gpf != end_key; gpf = gpfn) {
+ gpfn = gpf->next;
+
+ /* free strokes and their associated memory */
+ BKE_gpencil_free_strokes(gpf);
+ BLI_freelinkN(&gpl->frames, gpf);
+ }
+
+ /* Now free the last one... */
+ BKE_gpencil_free_strokes(end_key);
+ BLI_freelinkN(&gpl->frames, end_key);
+ }
+ }
+ CTX_DATA_END;
+
+ /* 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_interpolate_reverse(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Breakdowns";
- ot->idname = "GPENCIL_OT_interpolate_reverse";
- ot->description = "Remove breakdown frames generated by interpolating between two Grease Pencil frames";
-
- /* callbacks */
- ot->exec = gpencil_interpolate_reverse_exec;
- ot->poll = gpencil_interpolate_reverse_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Remove Breakdowns";
+ ot->idname = "GPENCIL_OT_interpolate_reverse";
+ ot->description =
+ "Remove breakdown frames generated by interpolating between two Grease Pencil frames";
+
+ /* callbacks */
+ ot->exec = gpencil_interpolate_reverse_exec;
+ ot->poll = gpencil_interpolate_reverse_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* *************************************************************** */
diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c
index 10bf45a9e2f..48c761919e5 100644
--- a/source/blender/editors/gpencil/gpencil_merge.c
+++ b/source/blender/editors/gpencil/gpencil_merge.c
@@ -54,144 +54,144 @@
#include "gpencil_intern.h"
typedef struct tGPencilPointCache {
- float factor; /* value to sort */
- bGPDstroke *gps;
- float x, y, z;
- float pressure;
- float strength;
+ float factor; /* value to sort */
+ bGPDstroke *gps;
+ float x, y, z;
+ float pressure;
+ float strength;
} tGPencilPointCache;
/* helper function to sort points */
static int gpencil_sort_points(const void *a1, const void *a2)
{
- const tGPencilPointCache *ps1 = a1, *ps2 = a2;
+ const tGPencilPointCache *ps1 = a1, *ps2 = a2;
- if (ps1->factor < ps2->factor) return -1;
- else if (ps1->factor > ps2->factor) return 1;
+ if (ps1->factor < ps2->factor)
+ return -1;
+ else if (ps1->factor > ps2->factor)
+ return 1;
- return 0;
+ return 0;
}
-static void gpencil_insert_points_to_stroke(
- bGPDstroke *gps, tGPencilPointCache *points_array, int totpoints)
+static void gpencil_insert_points_to_stroke(bGPDstroke *gps,
+ tGPencilPointCache *points_array,
+ int totpoints)
{
- tGPencilPointCache *point_elem = NULL;
-
- for (int i = 0; i < totpoints; i++) {
- point_elem = &points_array[i];
- bGPDspoint *pt_dst = &gps->points[i];
-
- copy_v3_v3(&pt_dst->x, &point_elem->x);
- pt_dst->pressure = point_elem->pressure;
- pt_dst->strength = point_elem->strength;
- pt_dst->uv_fac = 1.0f;
- pt_dst->uv_rot = 0;
- pt_dst->flag |= GP_SPOINT_SELECT;
- }
-
+ tGPencilPointCache *point_elem = NULL;
+
+ for (int i = 0; i < totpoints; i++) {
+ point_elem = &points_array[i];
+ bGPDspoint *pt_dst = &gps->points[i];
+
+ copy_v3_v3(&pt_dst->x, &point_elem->x);
+ pt_dst->pressure = point_elem->pressure;
+ pt_dst->strength = point_elem->strength;
+ pt_dst->uv_fac = 1.0f;
+ pt_dst->uv_rot = 0;
+ pt_dst->flag |= GP_SPOINT_SELECT;
+ }
}
static bGPDstroke *gpencil_prepare_stroke(bContext *C, wmOperator *op, int totpoints)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *ob = CTX_data_active_object(C);
- bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
-
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
-
- const bool back = RNA_boolean_get(op->ptr, "back");
- const bool additive = RNA_boolean_get(op->ptr, "additive");
- const bool cyclic = RNA_boolean_get(op->ptr, "cyclic");
-
- Paint *paint = &ts->gp_paint->paint;
- /* if not exist, create a new one */
- if (paint->brush == NULL) {
- /* create new brushes */
- BKE_brush_gpencil_presets(C);
- }
- Brush *brush = paint->brush;
-
- /* frame */
- short add_frame_mode;
- if (additive) {
- add_frame_mode = GP_GETFRAME_ADD_COPY;
- }
- else {
- add_frame_mode = GP_GETFRAME_ADD_NEW;
- }
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, 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);
- 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;
- }
-
- /* add new stroke to frame */
- if (back) {
- BLI_addhead(&gpf->strokes, gps);
- }
- else {
- BLI_addtail(&gpf->strokes, gps);
- }
-
- return gps;
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob = CTX_data_active_object(C);
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+ const bool back = RNA_boolean_get(op->ptr, "back");
+ const bool additive = RNA_boolean_get(op->ptr, "additive");
+ const bool cyclic = RNA_boolean_get(op->ptr, "cyclic");
+
+ Paint *paint = &ts->gp_paint->paint;
+ /* if not exist, create a new one */
+ if (paint->brush == NULL) {
+ /* create new brushes */
+ BKE_brush_gpencil_presets(C);
+ }
+ Brush *brush = paint->brush;
+
+ /* frame */
+ short add_frame_mode;
+ if (additive) {
+ add_frame_mode = GP_GETFRAME_ADD_COPY;
+ }
+ else {
+ add_frame_mode = GP_GETFRAME_ADD_NEW;
+ }
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, 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);
+ 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;
+ }
+
+ /* add new stroke to frame */
+ if (back) {
+ BLI_addhead(&gpf->strokes, gps);
+ }
+ else {
+ BLI_addtail(&gpf->strokes, gps);
+ }
+
+ return gps;
}
static void gpencil_get_elements_len(bContext *C, int *totstrokes, int *totpoints)
{
- bGPDspoint *pt;
- int i;
-
- /* count number of strokes and selected points */
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- if (gps->flag & GP_STROKE_SELECT) {
- *totstrokes += 1;
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT) {
- *totpoints += 1;
- }
- }
- }
- }
- CTX_DATA_END;
+ bGPDspoint *pt;
+ int i;
+
+ /* count number of strokes and selected points */
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ *totstrokes += 1;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ *totpoints += 1;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
}
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);
- }
- }
- CTX_DATA_END;
+ 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);
+ }
+ }
+ CTX_DATA_END;
}
/* Calc a factor of each selected point and fill an array with all the data.
@@ -201,367 +201,368 @@ static void gpencil_dissolve_points(bContext *C)
*
* All the data is saved to be sorted and used later.
*/
-static void gpencil_calc_points_factor(
- bContext *C, const int mode, int totpoints,
- const bool clear_point, const bool clear_stroke,
- tGPencilPointCache *src_array)
+static void gpencil_calc_points_factor(bContext *C,
+ const int mode,
+ int totpoints,
+ const bool clear_point,
+ const bool clear_stroke,
+ tGPencilPointCache *src_array)
{
- bGPDspoint *pt;
- int i;
- int idx = 0;
-
- /* create selected point array an fill it */
- bGPDstroke **gps_array = MEM_callocN(sizeof(bGPDstroke *) * totpoints, __func__);
- bGPDspoint *pt_array = MEM_callocN(sizeof(bGPDspoint) * totpoints, __func__);
-
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- bGPDframe *gpf = gpl->actframe;
- if (gpf == NULL) {
- continue;
- }
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- if (gps->flag & GP_STROKE_SELECT) {
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (clear_stroke) {
- pt->flag |= GP_SPOINT_TAG;
- }
- else {
- pt->flag &= ~GP_SPOINT_TAG;
- }
-
- if (pt->flag & GP_SPOINT_SELECT) {
- bGPDspoint *pt2 = &pt_array[idx];
- copy_v3_v3(&pt2->x, &pt->x);
- pt2->pressure = pt->pressure;
- pt2->strength = pt->strength;
- pt->flag &= ~GP_SPOINT_SELECT;
- if (clear_point) {
- pt->flag |= GP_SPOINT_TAG;
- }
-
- /* save stroke */
- gps_array[idx] = gps;
-
- idx++;
- }
- }
- gps->flag &= ~GP_STROKE_SELECT;
- }
- }
- }
- CTX_DATA_END;
-
- /* project in 2d plane */
- int direction = 0;
- float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * totpoints, "GP Stroke temp 2d points");
- BKE_gpencil_stroke_2d_flat(pt_array, totpoints, points2d, &direction);
-
- /* calc center */
- float center[2] = { 0.0f, 0.0f };
- for (i = 0; i < totpoints; i++) {
- center[0] += points2d[i][0];
- center[1] += points2d[i][1];
- }
- mul_v2_fl(center, 1.0f / totpoints);
-
- /* calc angle and distance to center for each point */
- const float axis[2] = { 1.0f, 0.0f };
- float v1[3];
- for (i = 0; i < totpoints; i++) {
- float ln = len_v2v2(center, points2d[i]);
- sub_v2_v2v2(v1, points2d[i], center);
- float angle = angle_signed_v2v2(axis, v1);
- if (angle < 0.0f) {
- angle = fabsf(angle);
- }
- else {
- angle = (M_PI * 2.0) - angle;
- }
- tGPencilPointCache *sort_pt = &src_array[i];
- bGPDspoint *pt2 = &pt_array[i];
-
- copy_v3_v3(&sort_pt->x, &pt2->x);
- sort_pt->pressure = pt2->pressure;
- sort_pt->strength = pt2->strength;
-
- sort_pt->gps = gps_array[i];
-
- if (mode == GP_MERGE_STROKE) {
- sort_pt->factor = angle;
- }
- else {
- sort_pt->factor = (angle * 100000.0f) + ln;
- }
- }
- MEM_SAFE_FREE(points2d);
- MEM_SAFE_FREE(gps_array);
- MEM_SAFE_FREE(pt_array);
+ bGPDspoint *pt;
+ int i;
+ int idx = 0;
+
+ /* create selected point array an fill it */
+ bGPDstroke **gps_array = MEM_callocN(sizeof(bGPDstroke *) * totpoints, __func__);
+ bGPDspoint *pt_array = MEM_callocN(sizeof(bGPDspoint) * totpoints, __func__);
+
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ bGPDframe *gpf = gpl->actframe;
+ if (gpf == NULL) {
+ continue;
+ }
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (clear_stroke) {
+ pt->flag |= GP_SPOINT_TAG;
+ }
+ else {
+ pt->flag &= ~GP_SPOINT_TAG;
+ }
+
+ if (pt->flag & GP_SPOINT_SELECT) {
+ bGPDspoint *pt2 = &pt_array[idx];
+ copy_v3_v3(&pt2->x, &pt->x);
+ pt2->pressure = pt->pressure;
+ pt2->strength = pt->strength;
+ pt->flag &= ~GP_SPOINT_SELECT;
+ if (clear_point) {
+ pt->flag |= GP_SPOINT_TAG;
+ }
+
+ /* save stroke */
+ gps_array[idx] = gps;
+
+ idx++;
+ }
+ }
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* project in 2d plane */
+ int direction = 0;
+ float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * totpoints, "GP Stroke temp 2d points");
+ BKE_gpencil_stroke_2d_flat(pt_array, totpoints, points2d, &direction);
+
+ /* calc center */
+ float center[2] = {0.0f, 0.0f};
+ for (i = 0; i < totpoints; i++) {
+ center[0] += points2d[i][0];
+ center[1] += points2d[i][1];
+ }
+ mul_v2_fl(center, 1.0f / totpoints);
+
+ /* calc angle and distance to center for each point */
+ const float axis[2] = {1.0f, 0.0f};
+ float v1[3];
+ for (i = 0; i < totpoints; i++) {
+ float ln = len_v2v2(center, points2d[i]);
+ sub_v2_v2v2(v1, points2d[i], center);
+ float angle = angle_signed_v2v2(axis, v1);
+ if (angle < 0.0f) {
+ angle = fabsf(angle);
+ }
+ else {
+ angle = (M_PI * 2.0) - angle;
+ }
+ tGPencilPointCache *sort_pt = &src_array[i];
+ bGPDspoint *pt2 = &pt_array[i];
+
+ copy_v3_v3(&sort_pt->x, &pt2->x);
+ sort_pt->pressure = pt2->pressure;
+ sort_pt->strength = pt2->strength;
+
+ sort_pt->gps = gps_array[i];
+
+ if (mode == GP_MERGE_STROKE) {
+ sort_pt->factor = angle;
+ }
+ else {
+ sort_pt->factor = (angle * 100000.0f) + ln;
+ }
+ }
+ MEM_SAFE_FREE(points2d);
+ MEM_SAFE_FREE(gps_array);
+ MEM_SAFE_FREE(pt_array);
}
/* insert a group of points in destination array */
-static int gpencil_insert_to_array(
- tGPencilPointCache *src_array, tGPencilPointCache *dst_array, int totpoints,
- bGPDstroke *gps_filter, bool reverse, int last)
+static int gpencil_insert_to_array(tGPencilPointCache *src_array,
+ tGPencilPointCache *dst_array,
+ int totpoints,
+ bGPDstroke *gps_filter,
+ bool reverse,
+ int last)
{
- tGPencilPointCache *src_elem = NULL;
- tGPencilPointCache *dst_elem = NULL;
- int idx = 0;
-
- for (int i = 0; i < totpoints; i++) {
- if (!reverse) {
- idx = i;
- }
- else {
- idx = totpoints - i - 1;
- }
- src_elem = &src_array[idx];
- /* check if all points or only a stroke */
- if ((gps_filter != NULL) && (gps_filter != src_elem->gps)) {
- continue;
- }
-
- dst_elem = &dst_array[last];
- last++;
-
- copy_v3_v3(&dst_elem->x, &src_elem->x);
- dst_elem->gps = src_elem->gps;
- dst_elem->pressure = src_elem->pressure;
- dst_elem->strength = src_elem->strength;
- dst_elem->factor = src_elem->factor;
- }
-
- return last;
+ tGPencilPointCache *src_elem = NULL;
+ tGPencilPointCache *dst_elem = NULL;
+ int idx = 0;
+
+ for (int i = 0; i < totpoints; i++) {
+ if (!reverse) {
+ idx = i;
+ }
+ else {
+ idx = totpoints - i - 1;
+ }
+ src_elem = &src_array[idx];
+ /* check if all points or only a stroke */
+ if ((gps_filter != NULL) && (gps_filter != src_elem->gps)) {
+ continue;
+ }
+
+ dst_elem = &dst_array[last];
+ last++;
+
+ copy_v3_v3(&dst_elem->x, &src_elem->x);
+ dst_elem->gps = src_elem->gps;
+ dst_elem->pressure = src_elem->pressure;
+ dst_elem->strength = src_elem->strength;
+ dst_elem->factor = src_elem->factor;
+ }
+
+ return last;
}
/* get first and last point location */
static void gpencil_get_extremes(
- tGPencilPointCache *src_array, int totpoints,
- bGPDstroke *gps_filter, float *start, float *end)
+ tGPencilPointCache *src_array, int totpoints, bGPDstroke *gps_filter, float *start, float *end)
{
- tGPencilPointCache *array_pt = NULL;
- int i;
-
- /* find first point */
- for (i = 0; i < totpoints; i++) {
- array_pt = &src_array[i];
- if (gps_filter == array_pt->gps) {
- copy_v3_v3(start, &array_pt->x);
- break;
- }
- }
- /* find last point */
- for (i = totpoints - 1; i >= 0; i--) {
- array_pt = &src_array[i];
- if (gps_filter == array_pt->gps) {
- copy_v3_v3(end, &array_pt->x);
- break;
- }
- }
+ tGPencilPointCache *array_pt = NULL;
+ int i;
+
+ /* find first point */
+ for (i = 0; i < totpoints; i++) {
+ array_pt = &src_array[i];
+ if (gps_filter == array_pt->gps) {
+ copy_v3_v3(start, &array_pt->x);
+ break;
+ }
+ }
+ /* find last point */
+ for (i = totpoints - 1; i >= 0; i--) {
+ array_pt = &src_array[i];
+ if (gps_filter == array_pt->gps) {
+ copy_v3_v3(end, &array_pt->x);
+ break;
+ }
+ }
}
-static int gpencil_analyze_strokes(
- tGPencilPointCache *src_array, int totstrokes, int totpoints,
- tGPencilPointCache *dst_array)
+static int gpencil_analyze_strokes(tGPencilPointCache *src_array,
+ int totstrokes,
+ int totpoints,
+ tGPencilPointCache *dst_array)
{
- int i;
- int last = 0;
- GHash *all_strokes = BLI_ghash_ptr_new(__func__);
- /* add first stroke to array */
- tGPencilPointCache *sort_pt = &src_array[0];
- bGPDstroke *gps = sort_pt->gps;
- last = gpencil_insert_to_array(src_array, dst_array, totpoints, gps, false, last);
- float start[3];
- float end[3];
- float end_prv[3];
- gpencil_get_extremes(src_array, totpoints, gps, start, end);
- copy_v3_v3(end_prv, end);
- BLI_ghash_insert(all_strokes, sort_pt->gps, sort_pt->gps);
-
- /* look for near stroke */
- bool loop = (bool)(totstrokes > 1);
- while (loop) {
- bGPDstroke *gps_next = NULL;
- GHash *strokes = BLI_ghash_ptr_new(__func__);
- float dist_start = 0.0f;
- float dist_end = 0.0f;
- float dist = FLT_MAX;
- bool reverse = false;
-
- for (i = 0; i < totpoints; i++) {
- sort_pt = &src_array[i];
- /* avoid dups */
- if (BLI_ghash_haskey(all_strokes, sort_pt->gps)) {
- continue;
- }
- if (!BLI_ghash_haskey(strokes, sort_pt->gps)) {
- gpencil_get_extremes(src_array, totpoints, sort_pt->gps, start, end);
- /* distances to previous end */
- dist_start = len_v3v3(end_prv, start);
- dist_end = len_v3v3(end_prv, end);
-
- if (dist > dist_start) {
- gps_next = sort_pt->gps;
- dist = dist_start;
- reverse = false;
- }
- if (dist > dist_end) {
- gps_next = sort_pt->gps;
- dist = dist_end;
- reverse = true;
- }
- BLI_ghash_insert(strokes, sort_pt->gps, sort_pt->gps);
- }
- }
- BLI_ghash_free(strokes, NULL, NULL);
-
- /* add the stroke to array */
- if (gps->next != NULL) {
- BLI_ghash_insert(all_strokes, gps_next, gps_next);
- last = gpencil_insert_to_array(src_array, dst_array, totpoints, gps_next, reverse, last);
- /* replace last end */
- sort_pt = &dst_array[last - 1];
- copy_v3_v3(end_prv, &sort_pt->x);
- }
-
- /* loop exit */
- if (last >= totpoints) {
- loop = false;
- }
- }
-
- BLI_ghash_free(all_strokes, NULL, NULL);
- return last;
+ int i;
+ int last = 0;
+ GHash *all_strokes = BLI_ghash_ptr_new(__func__);
+ /* add first stroke to array */
+ tGPencilPointCache *sort_pt = &src_array[0];
+ bGPDstroke *gps = sort_pt->gps;
+ last = gpencil_insert_to_array(src_array, dst_array, totpoints, gps, false, last);
+ float start[3];
+ float end[3];
+ float end_prv[3];
+ gpencil_get_extremes(src_array, totpoints, gps, start, end);
+ copy_v3_v3(end_prv, end);
+ BLI_ghash_insert(all_strokes, sort_pt->gps, sort_pt->gps);
+
+ /* look for near stroke */
+ bool loop = (bool)(totstrokes > 1);
+ while (loop) {
+ bGPDstroke *gps_next = NULL;
+ GHash *strokes = BLI_ghash_ptr_new(__func__);
+ float dist_start = 0.0f;
+ float dist_end = 0.0f;
+ float dist = FLT_MAX;
+ bool reverse = false;
+
+ for (i = 0; i < totpoints; i++) {
+ sort_pt = &src_array[i];
+ /* avoid dups */
+ if (BLI_ghash_haskey(all_strokes, sort_pt->gps)) {
+ continue;
+ }
+ if (!BLI_ghash_haskey(strokes, sort_pt->gps)) {
+ gpencil_get_extremes(src_array, totpoints, sort_pt->gps, start, end);
+ /* distances to previous end */
+ dist_start = len_v3v3(end_prv, start);
+ dist_end = len_v3v3(end_prv, end);
+
+ if (dist > dist_start) {
+ gps_next = sort_pt->gps;
+ dist = dist_start;
+ reverse = false;
+ }
+ if (dist > dist_end) {
+ gps_next = sort_pt->gps;
+ dist = dist_end;
+ reverse = true;
+ }
+ BLI_ghash_insert(strokes, sort_pt->gps, sort_pt->gps);
+ }
+ }
+ BLI_ghash_free(strokes, NULL, NULL);
+
+ /* add the stroke to array */
+ if (gps->next != NULL) {
+ BLI_ghash_insert(all_strokes, gps_next, gps_next);
+ last = gpencil_insert_to_array(src_array, dst_array, totpoints, gps_next, reverse, last);
+ /* replace last end */
+ sort_pt = &dst_array[last - 1];
+ copy_v3_v3(end_prv, &sort_pt->x);
+ }
+
+ /* loop exit */
+ if (last >= totpoints) {
+ loop = false;
+ }
+ }
+
+ BLI_ghash_free(all_strokes, NULL, NULL);
+ return last;
}
static bool gp_strokes_merge_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;
- }
-
- /* check material */
- Material *ma = NULL;
- ma = give_current_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))
- {
- return false;
- }
-
- /* check layer */
- bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
- if ((gpl == NULL) ||
- (gpl->flag & GP_LAYER_LOCKED) ||
- (gpl->flag & GP_LAYER_HIDE))
- {
- return false;
- }
-
- /* NOTE: this is a bit slower, but is the most accurate... */
- return (CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0) && ED_operator_view3d_active(C);
+ /* only supported with grease pencil objects */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+ return false;
+ }
+
+ /* check material */
+ Material *ma = NULL;
+ ma = give_current_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)) {
+ return false;
+ }
+
+ /* check layer */
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+ if ((gpl == NULL) || (gpl->flag & GP_LAYER_LOCKED) || (gpl->flag & GP_LAYER_HIDE)) {
+ return false;
+ }
+
+ /* NOTE: this is a bit slower, but is the most accurate... */
+ return (CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0) && ED_operator_view3d_active(C);
}
static int gp_stroke_merge_exec(bContext *C, wmOperator *op)
{
- const int mode = RNA_enum_get(op->ptr, "mode");
- const bool clear_point = RNA_boolean_get(op->ptr, "clear_point");
- const bool clear_stroke = RNA_boolean_get(op->ptr, "clear_stroke");
-
- Object *ob = CTX_data_active_object(C);
- /* sanity checks */
- if (!ob || ob->type != OB_GPENCIL) {
- return OPERATOR_CANCELLED;
- }
-
- bGPdata *gpd = (bGPdata *)ob->data;
- bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
- if (gpl == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- int totstrokes = 0;
- int totpoints = 0;
-
- /* count number of strokes and selected points */
- gpencil_get_elements_len(C, &totstrokes, &totpoints);
-
- if (totpoints == 0) {
- return OPERATOR_CANCELLED;
- }
-
- /* calc factor of each point and fill an array with all data */
- tGPencilPointCache *sorted_array = NULL;
- tGPencilPointCache *original_array = MEM_callocN(sizeof(tGPencilPointCache) * totpoints, __func__);
- gpencil_calc_points_factor(C, mode, totpoints, clear_point, clear_stroke, original_array);
-
- /* for strokes analyze strokes and load sorted array */
- if (mode == GP_MERGE_STROKE) {
- sorted_array = MEM_callocN(sizeof(tGPencilPointCache) * totpoints, __func__);
- totpoints = gpencil_analyze_strokes(original_array, totstrokes, totpoints, sorted_array);
- }
- else {
- /* make a copy to sort */
- sorted_array = MEM_dupallocN(original_array);
- /* sort by factor around center */
- qsort(sorted_array, totpoints, sizeof(tGPencilPointCache), gpencil_sort_points);
- }
-
- /* prepare the new stroke */
- bGPDstroke *gps = gpencil_prepare_stroke(C, op, totpoints);
-
- /* copy original points to final stroke */
- gpencil_insert_points_to_stroke(gps, sorted_array, totpoints);
-
- /* dissolve all tagged points */
- if ((clear_point) || (clear_stroke)) {
- gpencil_dissolve_points(C);
- }
-
- /* free memory */
- MEM_SAFE_FREE(original_array);
- MEM_SAFE_FREE(sorted_array);
-
- /* 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;
+ const int mode = RNA_enum_get(op->ptr, "mode");
+ const bool clear_point = RNA_boolean_get(op->ptr, "clear_point");
+ const bool clear_stroke = RNA_boolean_get(op->ptr, "clear_stroke");
+
+ Object *ob = CTX_data_active_object(C);
+ /* sanity checks */
+ if (!ob || ob->type != OB_GPENCIL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+ if (gpl == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ int totstrokes = 0;
+ int totpoints = 0;
+
+ /* count number of strokes and selected points */
+ gpencil_get_elements_len(C, &totstrokes, &totpoints);
+
+ if (totpoints == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* calc factor of each point and fill an array with all data */
+ tGPencilPointCache *sorted_array = NULL;
+ tGPencilPointCache *original_array = MEM_callocN(sizeof(tGPencilPointCache) * totpoints,
+ __func__);
+ gpencil_calc_points_factor(C, mode, totpoints, clear_point, clear_stroke, original_array);
+
+ /* for strokes analyze strokes and load sorted array */
+ if (mode == GP_MERGE_STROKE) {
+ sorted_array = MEM_callocN(sizeof(tGPencilPointCache) * totpoints, __func__);
+ totpoints = gpencil_analyze_strokes(original_array, totstrokes, totpoints, sorted_array);
+ }
+ else {
+ /* make a copy to sort */
+ sorted_array = MEM_dupallocN(original_array);
+ /* sort by factor around center */
+ qsort(sorted_array, totpoints, sizeof(tGPencilPointCache), gpencil_sort_points);
+ }
+
+ /* prepare the new stroke */
+ bGPDstroke *gps = gpencil_prepare_stroke(C, op, totpoints);
+
+ /* copy original points to final stroke */
+ gpencil_insert_points_to_stroke(gps, sorted_array, totpoints);
+
+ /* dissolve all tagged points */
+ if ((clear_point) || (clear_stroke)) {
+ gpencil_dissolve_points(C);
+ }
+
+ /* free memory */
+ MEM_SAFE_FREE(original_array);
+ MEM_SAFE_FREE(sorted_array);
+
+ /* 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_stroke_merge(wmOperatorType *ot)
{
- static const EnumPropertyItem mode_type[] = {
- {GP_MERGE_STROKE, "STROKE", 0, "Stroke", ""},
- {GP_MERGE_POINT, "POINT", 0, "Point", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Merge Strokes";
- ot->idname = "GPENCIL_OT_stroke_merge";
- ot->description = "Create a new stroke with the selected stroke points";
-
- /* api callbacks */
- ot->exec = gp_stroke_merge_exec;
- ot->poll = gp_strokes_merge_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "mode", mode_type, GP_MERGE_STROKE, "Mode", "");
- RNA_def_boolean(ot->srna, "back", 0, "Draw on Back", "Draw new stroke below all previous strokes");
- RNA_def_boolean(ot->srna, "additive", 0, "Additive Drawing", "Add to previous drawing");
- RNA_def_boolean(ot->srna, "cyclic", 0, "Cyclic", "Close new stroke");
- 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");
+ static const EnumPropertyItem mode_type[] = {
+ {GP_MERGE_STROKE, "STROKE", 0, "Stroke", ""},
+ {GP_MERGE_POINT, "POINT", 0, "Point", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Merge Strokes";
+ ot->idname = "GPENCIL_OT_stroke_merge";
+ ot->description = "Create a new stroke with the selected stroke points";
+
+ /* api callbacks */
+ ot->exec = gp_stroke_merge_exec;
+ ot->poll = gp_strokes_merge_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "mode", mode_type, GP_MERGE_STROKE, "Mode", "");
+ RNA_def_boolean(
+ ot->srna, "back", 0, "Draw on Back", "Draw new stroke below all previous strokes");
+ RNA_def_boolean(ot->srna, "additive", 0, "Additive Drawing", "Add to previous drawing");
+ RNA_def_boolean(ot->srna, "cyclic", 0, "Cyclic", "Close new stroke");
+ 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");
}
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 779094c21ea..fce8fa79217 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -21,7 +21,6 @@
* \ingroup edgpencil
*/
-
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
@@ -58,7 +57,7 @@
/* Generic Drawing Keymap - Annotations */
static void ed_keymap_gpencil_general(wmKeyConfig *keyconf)
{
- WM_keymap_ensure(keyconf, "Grease Pencil", 0, 0);
+ WM_keymap_ensure(keyconf, "Grease Pencil", 0, 0);
}
/* ==================== */
@@ -66,317 +65,316 @@ static void ed_keymap_gpencil_general(wmKeyConfig *keyconf)
/* Poll callback for stroke editing mode */
static bool gp_stroke_editmode_poll(bContext *C)
{
- bGPdata *gpd = CTX_data_gpencil_data(C);
- return (gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE));
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ return (gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE));
}
/* Poll callback for stroke painting mode */
static bool gp_stroke_paintmode_poll(bContext *C)
{
- /* TODO: limit this to mode, but review 2D editors */
- bGPdata *gpd = CTX_data_gpencil_data(C);
- return (gpd && (gpd->flag & GP_DATA_STROKE_PAINTMODE));
+ /* TODO: limit this to mode, but review 2D editors */
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ return (gpd && (gpd->flag & GP_DATA_STROKE_PAINTMODE));
}
static bool gp_stroke_paintmode_poll_with_tool(bContext *C, const char gpencil_tool)
{
- /* TODO: limit this to mode, but review 2D editors */
- bGPdata *gpd = CTX_data_gpencil_data(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
- return ((gpd) && (gpd->flag & GP_DATA_STROKE_PAINTMODE) &&
- (brush && brush->gpencil_settings) &&
- WM_toolsystem_active_tool_is_brush(C) &&
- (brush->gpencil_tool == gpencil_tool));
+ /* TODO: limit this to mode, but review 2D editors */
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
+ return ((gpd) && (gpd->flag & GP_DATA_STROKE_PAINTMODE) && (brush && brush->gpencil_settings) &&
+ WM_toolsystem_active_tool_is_brush(C) && (brush->gpencil_tool == gpencil_tool));
}
/* Poll callback for stroke painting (draw brush) */
static bool gp_stroke_paintmode_draw_poll(bContext *C)
{
- return gp_stroke_paintmode_poll_with_tool(C, GPAINT_TOOL_DRAW);
+ return gp_stroke_paintmode_poll_with_tool(C, GPAINT_TOOL_DRAW);
}
/* Poll callback for stroke painting (erase brush) */
static bool gp_stroke_paintmode_erase_poll(bContext *C)
{
- return gp_stroke_paintmode_poll_with_tool(C, GPAINT_TOOL_ERASE);
+ return gp_stroke_paintmode_poll_with_tool(C, GPAINT_TOOL_ERASE);
}
/* Poll callback for stroke painting (fill) */
static bool gp_stroke_paintmode_fill_poll(bContext *C)
{
- return gp_stroke_paintmode_poll_with_tool(C, GPAINT_TOOL_FILL);
+ return gp_stroke_paintmode_poll_with_tool(C, GPAINT_TOOL_FILL);
}
/* 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);
-
- /* if not gpencil object and not view3d, need sculpt keys if edit mode */
- if (sa->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 0;
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ Object *ob = CTX_data_active_object(C);
+ ScrArea *sa = CTX_wm_area(C);
+
+ /* if not gpencil object and not view3d, need sculpt keys if edit mode */
+ if (sa->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 0;
}
/* Poll callback for stroke weight paint mode */
static bool gp_stroke_weightmode_poll(bContext *C)
{
- bGPdata *gpd = CTX_data_gpencil_data(C);
- Object *ob = CTX_data_active_object(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_WEIGHTMODE));
- }
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ return (gpd && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE));
+ }
- return 0;
+ return 0;
}
/* Stroke Editing Keymap - Only when editmode is enabled */
static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
{
- wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Edit Mode", 0, 0);
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Edit Mode", 0, 0);
- /* set poll callback - so that this keymap only gets enabled when stroke editmode is enabled */
- keymap->poll = gp_stroke_editmode_poll;
+ /* set poll callback - so that this keymap only gets enabled when stroke editmode is enabled */
+ keymap->poll = gp_stroke_editmode_poll;
}
/* keys for draw with a drawing brush (no fill) */
static void ed_keymap_gpencil_painting_draw(wmKeyConfig *keyconf)
{
- wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint (Draw brush)", 0, 0);
- keymap->poll = gp_stroke_paintmode_draw_poll;
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint (Draw brush)", 0, 0);
+ keymap->poll = gp_stroke_paintmode_draw_poll;
}
/* keys for draw with a eraser brush (erase) */
static void ed_keymap_gpencil_painting_erase(wmKeyConfig *keyconf)
{
- wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint (Erase)", 0, 0);
- keymap->poll = gp_stroke_paintmode_erase_poll;
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint (Erase)", 0, 0);
+ keymap->poll = gp_stroke_paintmode_erase_poll;
}
/* keys for draw with a fill brush */
static void ed_keymap_gpencil_painting_fill(wmKeyConfig *keyconf)
{
- wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint (Fill)", 0, 0);
- keymap->poll = gp_stroke_paintmode_fill_poll;
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint (Fill)", 0, 0);
+ keymap->poll = gp_stroke_paintmode_fill_poll;
}
/* Stroke Painting Keymap - Only when paintmode is enabled */
static void ed_keymap_gpencil_painting(wmKeyConfig *keyconf)
{
- /* set poll callback - so that this keymap only gets enabled when stroke paintmode is enabled */
- wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint Mode", 0, 0);
- keymap->poll = gp_stroke_paintmode_poll;
+ /* set poll callback - so that this keymap only gets enabled when stroke paintmode is enabled */
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint Mode", 0, 0);
+ keymap->poll = gp_stroke_paintmode_poll;
}
/* Stroke Sculpting Keymap - Only when sculptmode is enabled */
static void ed_keymap_gpencil_sculpting(wmKeyConfig *keyconf)
{
- /* set poll callback - so that this keymap only gets enabled when stroke sculptmode is enabled */
- wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt Mode", 0, 0);
- keymap->poll = gp_stroke_sculptmode_poll;
+ /* set poll callback - so that this keymap only gets enabled when stroke sculptmode is enabled */
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt Mode", 0, 0);
+ keymap->poll = gp_stroke_sculptmode_poll;
}
/* Stroke Weight Paint Keymap - Only when weight is enabled */
static void ed_keymap_gpencil_weightpainting(wmKeyConfig *keyconf)
{
- /* set poll callback - so that this keymap only gets enabled when stroke sculptmode is enabled */
- wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Weight Mode", 0, 0);
- keymap->poll = gp_stroke_weightmode_poll;
+ /* set poll callback - so that this keymap only gets enabled when stroke sculptmode is enabled */
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Weight Mode", 0, 0);
+ keymap->poll = gp_stroke_weightmode_poll;
}
/* ==================== */
void ED_keymap_gpencil(wmKeyConfig *keyconf)
{
- ed_keymap_gpencil_general(keyconf);
- ed_keymap_gpencil_editing(keyconf);
- ed_keymap_gpencil_painting(keyconf);
- ed_keymap_gpencil_painting_draw(keyconf);
- ed_keymap_gpencil_painting_erase(keyconf);
- ed_keymap_gpencil_painting_fill(keyconf);
- ed_keymap_gpencil_sculpting(keyconf);
- ed_keymap_gpencil_weightpainting(keyconf);
+ ed_keymap_gpencil_general(keyconf);
+ ed_keymap_gpencil_editing(keyconf);
+ ed_keymap_gpencil_painting(keyconf);
+ ed_keymap_gpencil_painting_draw(keyconf);
+ ed_keymap_gpencil_painting_erase(keyconf);
+ ed_keymap_gpencil_painting_fill(keyconf);
+ ed_keymap_gpencil_sculpting(keyconf);
+ ed_keymap_gpencil_weightpainting(keyconf);
}
/* ****************************************** */
void ED_operatortypes_gpencil(void)
{
- /* Annotations -------------------- */
-
- WM_operatortype_append(GPENCIL_OT_annotate);
-
- /* Drawing ----------------------- */
-
- WM_operatortype_append(GPENCIL_OT_draw);
- WM_operatortype_append(GPENCIL_OT_fill);
-
- /* Guides ----------------------- */
-
- WM_operatortype_append(GPENCIL_OT_guide_rotate);
-
- /* Editing (Strokes) ------------ */
-
- WM_operatortype_append(GPENCIL_OT_editmode_toggle);
- WM_operatortype_append(GPENCIL_OT_selectmode_toggle);
- 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_selection_opacity_toggle);
-
- WM_operatortype_append(GPENCIL_OT_select);
- WM_operatortype_append(GPENCIL_OT_select_all);
- WM_operatortype_append(GPENCIL_OT_select_circle);
- WM_operatortype_append(GPENCIL_OT_select_box);
- WM_operatortype_append(GPENCIL_OT_select_lasso);
-
- WM_operatortype_append(GPENCIL_OT_select_linked);
- WM_operatortype_append(GPENCIL_OT_select_grouped);
- WM_operatortype_append(GPENCIL_OT_select_more);
- WM_operatortype_append(GPENCIL_OT_select_less);
- 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_duplicate);
- WM_operatortype_append(GPENCIL_OT_delete);
- WM_operatortype_append(GPENCIL_OT_dissolve);
- WM_operatortype_append(GPENCIL_OT_copy);
- WM_operatortype_append(GPENCIL_OT_paste);
- WM_operatortype_append(GPENCIL_OT_extrude);
-
- WM_operatortype_append(GPENCIL_OT_move_to_layer);
- WM_operatortype_append(GPENCIL_OT_layer_change);
-
- WM_operatortype_append(GPENCIL_OT_snap_to_grid);
- WM_operatortype_append(GPENCIL_OT_snap_to_cursor);
- WM_operatortype_append(GPENCIL_OT_snap_cursor_to_selected);
-
- WM_operatortype_append(GPENCIL_OT_reproject);
-
- WM_operatortype_append(GPENCIL_OT_sculpt_paint);
-
- /* Editing (Buttons) ------------ */
-
- WM_operatortype_append(GPENCIL_OT_data_add);
- WM_operatortype_append(GPENCIL_OT_data_unlink);
-
- WM_operatortype_append(GPENCIL_OT_layer_add);
- WM_operatortype_append(GPENCIL_OT_layer_remove);
- WM_operatortype_append(GPENCIL_OT_layer_move);
- WM_operatortype_append(GPENCIL_OT_layer_duplicate);
- WM_operatortype_append(GPENCIL_OT_layer_duplicate_object);
-
- WM_operatortype_append(GPENCIL_OT_hide);
- WM_operatortype_append(GPENCIL_OT_reveal);
- WM_operatortype_append(GPENCIL_OT_lock_all);
- WM_operatortype_append(GPENCIL_OT_unlock_all);
- WM_operatortype_append(GPENCIL_OT_layer_isolate);
- WM_operatortype_append(GPENCIL_OT_layer_merge);
-
- WM_operatortype_append(GPENCIL_OT_blank_frame_add);
-
- WM_operatortype_append(GPENCIL_OT_active_frame_delete);
- WM_operatortype_append(GPENCIL_OT_active_frames_delete_all);
- WM_operatortype_append(GPENCIL_OT_frame_duplicate);
- WM_operatortype_append(GPENCIL_OT_frame_clean_fill);
- WM_operatortype_append(GPENCIL_OT_frame_clean_loose);
-
- WM_operatortype_append(GPENCIL_OT_convert);
-
- 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_stroke_apply_thickness);
- WM_operatortype_append(GPENCIL_OT_stroke_cyclical_set);
- WM_operatortype_append(GPENCIL_OT_stroke_caps_set);
- WM_operatortype_append(GPENCIL_OT_stroke_join);
- WM_operatortype_append(GPENCIL_OT_stroke_flip);
- WM_operatortype_append(GPENCIL_OT_stroke_subdivide);
- WM_operatortype_append(GPENCIL_OT_stroke_simplify);
- WM_operatortype_append(GPENCIL_OT_stroke_simplify_fixed);
- WM_operatortype_append(GPENCIL_OT_stroke_separate);
- WM_operatortype_append(GPENCIL_OT_stroke_split);
- WM_operatortype_append(GPENCIL_OT_stroke_smooth);
- WM_operatortype_append(GPENCIL_OT_stroke_merge);
- WM_operatortype_append(GPENCIL_OT_stroke_cutter);
- WM_operatortype_append(GPENCIL_OT_stroke_trim);
-
- WM_operatortype_append(GPENCIL_OT_brush_presets_create);
-
- /* vertex groups */
- WM_operatortype_append(GPENCIL_OT_vertex_group_assign);
- WM_operatortype_append(GPENCIL_OT_vertex_group_remove_from);
- WM_operatortype_append(GPENCIL_OT_vertex_group_select);
- WM_operatortype_append(GPENCIL_OT_vertex_group_deselect);
- WM_operatortype_append(GPENCIL_OT_vertex_group_invert);
- WM_operatortype_append(GPENCIL_OT_vertex_group_smooth);
- WM_operatortype_append(GPENCIL_OT_vertex_group_normalize);
- WM_operatortype_append(GPENCIL_OT_vertex_group_normalize_all);
-
- /* 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);
-
- /* Editing (Time) --------------- */
-
- /* Interpolation */
- WM_operatortype_append(GPENCIL_OT_interpolate);
- WM_operatortype_append(GPENCIL_OT_interpolate_sequence);
- WM_operatortype_append(GPENCIL_OT_interpolate_reverse);
-
- /* Primitives */
- WM_operatortype_append(GPENCIL_OT_primitive);
-
- /* convert old 2.7 files to 2.8 */
- WM_operatortype_append(GPENCIL_OT_convert_old_files);
-
- /* armatures */
- WM_operatortype_append(GPENCIL_OT_generate_weights);
+ /* Annotations -------------------- */
+
+ WM_operatortype_append(GPENCIL_OT_annotate);
+
+ /* Drawing ----------------------- */
+
+ WM_operatortype_append(GPENCIL_OT_draw);
+ WM_operatortype_append(GPENCIL_OT_fill);
+
+ /* Guides ----------------------- */
+
+ WM_operatortype_append(GPENCIL_OT_guide_rotate);
+
+ /* Editing (Strokes) ------------ */
+
+ WM_operatortype_append(GPENCIL_OT_editmode_toggle);
+ WM_operatortype_append(GPENCIL_OT_selectmode_toggle);
+ 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_selection_opacity_toggle);
+
+ WM_operatortype_append(GPENCIL_OT_select);
+ WM_operatortype_append(GPENCIL_OT_select_all);
+ WM_operatortype_append(GPENCIL_OT_select_circle);
+ WM_operatortype_append(GPENCIL_OT_select_box);
+ WM_operatortype_append(GPENCIL_OT_select_lasso);
+
+ WM_operatortype_append(GPENCIL_OT_select_linked);
+ WM_operatortype_append(GPENCIL_OT_select_grouped);
+ WM_operatortype_append(GPENCIL_OT_select_more);
+ WM_operatortype_append(GPENCIL_OT_select_less);
+ 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_duplicate);
+ WM_operatortype_append(GPENCIL_OT_delete);
+ WM_operatortype_append(GPENCIL_OT_dissolve);
+ WM_operatortype_append(GPENCIL_OT_copy);
+ WM_operatortype_append(GPENCIL_OT_paste);
+ WM_operatortype_append(GPENCIL_OT_extrude);
+
+ WM_operatortype_append(GPENCIL_OT_move_to_layer);
+ WM_operatortype_append(GPENCIL_OT_layer_change);
+
+ WM_operatortype_append(GPENCIL_OT_snap_to_grid);
+ WM_operatortype_append(GPENCIL_OT_snap_to_cursor);
+ WM_operatortype_append(GPENCIL_OT_snap_cursor_to_selected);
+
+ WM_operatortype_append(GPENCIL_OT_reproject);
+
+ WM_operatortype_append(GPENCIL_OT_sculpt_paint);
+
+ /* Editing (Buttons) ------------ */
+
+ WM_operatortype_append(GPENCIL_OT_data_add);
+ WM_operatortype_append(GPENCIL_OT_data_unlink);
+
+ WM_operatortype_append(GPENCIL_OT_layer_add);
+ WM_operatortype_append(GPENCIL_OT_layer_remove);
+ WM_operatortype_append(GPENCIL_OT_layer_move);
+ WM_operatortype_append(GPENCIL_OT_layer_duplicate);
+ WM_operatortype_append(GPENCIL_OT_layer_duplicate_object);
+
+ WM_operatortype_append(GPENCIL_OT_hide);
+ WM_operatortype_append(GPENCIL_OT_reveal);
+ WM_operatortype_append(GPENCIL_OT_lock_all);
+ WM_operatortype_append(GPENCIL_OT_unlock_all);
+ WM_operatortype_append(GPENCIL_OT_layer_isolate);
+ WM_operatortype_append(GPENCIL_OT_layer_merge);
+
+ WM_operatortype_append(GPENCIL_OT_blank_frame_add);
+
+ WM_operatortype_append(GPENCIL_OT_active_frame_delete);
+ WM_operatortype_append(GPENCIL_OT_active_frames_delete_all);
+ WM_operatortype_append(GPENCIL_OT_frame_duplicate);
+ WM_operatortype_append(GPENCIL_OT_frame_clean_fill);
+ WM_operatortype_append(GPENCIL_OT_frame_clean_loose);
+
+ WM_operatortype_append(GPENCIL_OT_convert);
+
+ 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_stroke_apply_thickness);
+ WM_operatortype_append(GPENCIL_OT_stroke_cyclical_set);
+ WM_operatortype_append(GPENCIL_OT_stroke_caps_set);
+ WM_operatortype_append(GPENCIL_OT_stroke_join);
+ WM_operatortype_append(GPENCIL_OT_stroke_flip);
+ WM_operatortype_append(GPENCIL_OT_stroke_subdivide);
+ WM_operatortype_append(GPENCIL_OT_stroke_simplify);
+ WM_operatortype_append(GPENCIL_OT_stroke_simplify_fixed);
+ WM_operatortype_append(GPENCIL_OT_stroke_separate);
+ WM_operatortype_append(GPENCIL_OT_stroke_split);
+ WM_operatortype_append(GPENCIL_OT_stroke_smooth);
+ WM_operatortype_append(GPENCIL_OT_stroke_merge);
+ WM_operatortype_append(GPENCIL_OT_stroke_cutter);
+ WM_operatortype_append(GPENCIL_OT_stroke_trim);
+
+ WM_operatortype_append(GPENCIL_OT_brush_presets_create);
+
+ /* vertex groups */
+ WM_operatortype_append(GPENCIL_OT_vertex_group_assign);
+ WM_operatortype_append(GPENCIL_OT_vertex_group_remove_from);
+ WM_operatortype_append(GPENCIL_OT_vertex_group_select);
+ WM_operatortype_append(GPENCIL_OT_vertex_group_deselect);
+ WM_operatortype_append(GPENCIL_OT_vertex_group_invert);
+ WM_operatortype_append(GPENCIL_OT_vertex_group_smooth);
+ WM_operatortype_append(GPENCIL_OT_vertex_group_normalize);
+ WM_operatortype_append(GPENCIL_OT_vertex_group_normalize_all);
+
+ /* 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);
+
+ /* Editing (Time) --------------- */
+
+ /* Interpolation */
+ WM_operatortype_append(GPENCIL_OT_interpolate);
+ WM_operatortype_append(GPENCIL_OT_interpolate_sequence);
+ WM_operatortype_append(GPENCIL_OT_interpolate_reverse);
+
+ /* Primitives */
+ WM_operatortype_append(GPENCIL_OT_primitive);
+
+ /* convert old 2.7 files to 2.8 */
+ WM_operatortype_append(GPENCIL_OT_convert_old_files);
+
+ /* armatures */
+ WM_operatortype_append(GPENCIL_OT_generate_weights);
}
void ED_operatormacros_gpencil(void)
{
- wmOperatorType *ot;
- wmOperatorTypeMacro *otmacro;
-
- /* Duplicate + Move = Interactively place newly duplicated strokes */
- ot = WM_operatortype_append_macro(
- "GPENCIL_OT_duplicate_move", "Duplicate Strokes",
- "Make copies of the selected Grease Pencil strokes and move them",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "GPENCIL_OT_duplicate");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_boolean_set(otmacro->ptr, "gpencil_strokes", true);
- RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", false);
-
- /* Extrude + Move = Interactively add new points */
- ot = WM_operatortype_append_macro(
- "GPENCIL_OT_extrude_move", "Extrude Stroke Points",
- "Extrude selected points and move them",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "GPENCIL_OT_extrude");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_boolean_set(otmacro->ptr, "gpencil_strokes", true);
- RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", false);
+ wmOperatorType *ot;
+ wmOperatorTypeMacro *otmacro;
+
+ /* Duplicate + Move = Interactively place newly duplicated strokes */
+ ot = WM_operatortype_append_macro(
+ "GPENCIL_OT_duplicate_move",
+ "Duplicate Strokes",
+ "Make copies of the selected Grease Pencil strokes and move them",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "GPENCIL_OT_duplicate");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_boolean_set(otmacro->ptr, "gpencil_strokes", true);
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
+
+ /* Extrude + Move = Interactively add new points */
+ ot = WM_operatortype_append_macro("GPENCIL_OT_extrude_move",
+ "Extrude Stroke Points",
+ "Extrude selected points and move them",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "GPENCIL_OT_extrude");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_boolean_set(otmacro->ptr, "gpencil_strokes", true);
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
}
/* ****************************************** */
diff --git a/source/blender/editors/gpencil/gpencil_ops_versioning.c b/source/blender/editors/gpencil/gpencil_ops_versioning.c
index 9fdb5a9b174..af49587f9ad 100644
--- a/source/blender/editors/gpencil/gpencil_ops_versioning.c
+++ b/source/blender/editors/gpencil/gpencil_ops_versioning.c
@@ -22,7 +22,7 @@
* \ingroup edgpencil
*/
- /* allow to use deprecated functionality */
+/* allow to use deprecated functionality */
#define DNA_DEPRECATED_ALLOW
#include <stdio.h>
@@ -56,162 +56,161 @@
#include "gpencil_intern.h"
- /* Free all of a gp-colors */
+/* Free all of a gp-colors */
static void free_gpencil_colors(bGPDpalette *palette)
{
- /* error checking */
- if (palette == NULL) {
- return;
- }
+ /* error checking */
+ if (palette == NULL) {
+ return;
+ }
- /* free colors */
- BLI_freelistN(&palette->colors);
+ /* free colors */
+ BLI_freelistN(&palette->colors);
}
/* Free all of the gp-palettes and colors */
static void free_palettes(ListBase *list)
{
- bGPDpalette *palette_next;
-
- /* error checking */
- if (list == NULL) {
- return;
- }
-
- /* delete palettes */
- for (bGPDpalette *palette = list->first; palette; palette = palette_next) {
- palette_next = palette->next;
- /* free palette colors */
- free_gpencil_colors(palette);
-
- MEM_freeN(palette);
- }
- BLI_listbase_clear(list);
+ bGPDpalette *palette_next;
+
+ /* error checking */
+ if (list == NULL) {
+ return;
+ }
+
+ /* delete palettes */
+ for (bGPDpalette *palette = list->first; palette; palette = palette_next) {
+ palette_next = palette->next;
+ /* free palette colors */
+ free_gpencil_colors(palette);
+
+ MEM_freeN(palette);
+ }
+ BLI_listbase_clear(list);
}
/* ***************** Convert old 2.7 files to 2.8 ************************ */
static bool gpencil_convert_old_files_poll(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- return (int) (scene->gpd != NULL);
+ return (int)(scene->gpd != NULL);
}
static int gpencil_convert_old_files_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);
- const bool is_annotation = RNA_boolean_get(op->ptr, "annotation");
- bGPdata *gpd = scene->gpd;
-
- /* Convert grease pencil scene datablock to GP object */
- if ((!is_annotation) && (view_layer != NULL)) {
- Object *ob;
- ob = BKE_object_add_for_data(bmain, view_layer, OB_GPENCIL, "GP_Scene", &scene->gpd->id, false);
- zero_v3(ob->loc);
-
- /* 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) {
-
- /* create material slot */
- Material *ma = BKE_gpencil_object_material_new(bmain, ob, palcolor->info, NULL);
-
- /* copy color settings */
- MaterialGPencilStyle *gp_style = ma->gp_style;
- copy_v4_v4(gp_style->stroke_rgba, palcolor->color);
- 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;
-
- /* 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) {
- if ((gps->colorname[0] != '\0') &&
- (STREQ(gps->colorname, palcolor->info)))
- {
- gps->mat_nr = ob->totcol - 1;
- gps->colorname[0] = '\0';
- /* weights array */
- gps->dvert = NULL;
- }
- }
- }
- }
- }
- }
-
- /* free palettes */
- free_palettes(&gpd->palettes);
-
- /* disable all GP modes */
- ED_gpencil_setup_modes(C, gpd, 0);
-
- /* set cache as dirty */
- BKE_gpencil_batch_cache_dirty_tag(ob->data);
-
- scene->gpd = NULL;
- }
-
- if (is_annotation) {
- for (const bGPDpalette *palette = gpd->palettes.first; palette; palette = palette->next) {
- for (bGPDpalettecolor *palcolor = palette->colors.first; palcolor; palcolor = palcolor->next) {
- /* fix layers */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* unlock/unhide layer */
- gpl->flag &= ~GP_LAYER_LOCKED;
- gpl->flag &= ~GP_LAYER_HIDE;
- /* set opacity to 1 */
- 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) {
- if ((gps->colorname[0] != '\0') &&
- (STREQ(gps->colorname, palcolor->info)))
- {
- /* copy color settings */
- copy_v4_v4(gpl->color, palcolor->color);
- }
- }
- }
- }
- }
- }
- }
-
- /* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool is_annotation = RNA_boolean_get(op->ptr, "annotation");
+ bGPdata *gpd = scene->gpd;
+
+ /* Convert grease pencil scene datablock to GP object */
+ if ((!is_annotation) && (view_layer != NULL)) {
+ Object *ob;
+ ob = BKE_object_add_for_data(
+ bmain, view_layer, OB_GPENCIL, "GP_Scene", &scene->gpd->id, false);
+ zero_v3(ob->loc);
+
+ /* 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) {
+
+ /* create material slot */
+ Material *ma = BKE_gpencil_object_material_new(bmain, ob, palcolor->info, NULL);
+
+ /* copy color settings */
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+ copy_v4_v4(gp_style->stroke_rgba, palcolor->color);
+ 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;
+
+ /* 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) {
+ if ((gps->colorname[0] != '\0') && (STREQ(gps->colorname, palcolor->info))) {
+ gps->mat_nr = ob->totcol - 1;
+ gps->colorname[0] = '\0';
+ /* weights array */
+ gps->dvert = NULL;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* free palettes */
+ free_palettes(&gpd->palettes);
+
+ /* disable all GP modes */
+ ED_gpencil_setup_modes(C, gpd, 0);
+
+ /* set cache as dirty */
+ BKE_gpencil_batch_cache_dirty_tag(ob->data);
+
+ scene->gpd = NULL;
+ }
+
+ if (is_annotation) {
+ for (const bGPDpalette *palette = gpd->palettes.first; palette; palette = palette->next) {
+ for (bGPDpalettecolor *palcolor = palette->colors.first; palcolor;
+ palcolor = palcolor->next) {
+ /* fix layers */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* unlock/unhide layer */
+ gpl->flag &= ~GP_LAYER_LOCKED;
+ gpl->flag &= ~GP_LAYER_HIDE;
+ /* set opacity to 1 */
+ 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) {
+ if ((gps->colorname[0] != '\0') && (STREQ(gps->colorname, palcolor->info))) {
+ /* copy color settings */
+ copy_v4_v4(gpl->color, palcolor->color);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_convert_old_files(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Convert Grease Pencil";
- ot->idname = "GPENCIL_OT_convert_old_files";
- ot->description = "Convert 2.7x grease pencil files to 2.80";
+ /* identifiers */
+ ot->name = "Convert Grease Pencil";
+ ot->idname = "GPENCIL_OT_convert_old_files";
+ ot->description = "Convert 2.7x grease pencil files to 2.80";
- /* callbacks */
- ot->exec = gpencil_convert_old_files_exec;
- ot->poll = gpencil_convert_old_files_poll;
+ /* callbacks */
+ ot->exec = gpencil_convert_old_files_exec;
+ ot->poll = gpencil_convert_old_files_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- ot->prop = RNA_def_boolean(ot->srna, "annotation", 0, "Annotation", "Convert to Annotations");
+ /* props */
+ ot->prop = RNA_def_boolean(ot->srna, "annotation", 0, "Annotation", "Convert to Annotations");
}
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 8ac4d602736..bfdfe64ed54 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -69,7 +69,6 @@
#include "ED_view3d.h"
#include "ED_clip.h"
-
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_state.h"
@@ -85,153 +84,153 @@
#include "gpencil_intern.h"
- /* ******************************************* */
- /* 'Globals' and Defines */
+/* ******************************************* */
+/* 'Globals' and Defines */
- /* values for tGPsdata->status */
+/* values for tGPsdata->status */
typedef enum eGPencil_PaintStatus {
- GP_STATUS_IDLING = 0, /* stroke isn't in progress yet */
- GP_STATUS_PAINTING, /* a stroke is in progress */
- GP_STATUS_ERROR, /* something wasn't correctly set up */
- GP_STATUS_DONE, /* painting done */
+ GP_STATUS_IDLING = 0, /* stroke isn't in progress yet */
+ GP_STATUS_PAINTING, /* a stroke is in progress */
+ GP_STATUS_ERROR, /* something wasn't correctly set up */
+ GP_STATUS_DONE, /* painting done */
} eGPencil_PaintStatus;
/* Return flags for adding points to stroke buffer */
typedef enum eGP_StrokeAdd_Result {
- GP_STROKEADD_INVALID = -2, /* error occurred - insufficient info to do so */
- GP_STROKEADD_OVERFLOW = -1, /* error occurred - cannot fit any more points */
- GP_STROKEADD_NORMAL, /* point was successfully added */
- GP_STROKEADD_FULL, /* cannot add any more points to buffer */
+ GP_STROKEADD_INVALID = -2, /* error occurred - insufficient info to do so */
+ GP_STROKEADD_OVERFLOW = -1, /* error occurred - cannot fit any more points */
+ GP_STROKEADD_NORMAL, /* point was successfully added */
+ GP_STROKEADD_FULL, /* cannot add any more points to buffer */
} eGP_StrokeAdd_Result;
/* Runtime flags */
typedef enum eGPencil_PaintFlags {
- GP_PAINTFLAG_FIRSTRUN = (1 << 0), /* operator just started */
- GP_PAINTFLAG_STROKEADDED = (1 << 1),
- GP_PAINTFLAG_SELECTMASK = (1 << 3),
- GP_PAINTFLAG_HARD_ERASER = (1 << 4),
- GP_PAINTFLAG_STROKE_ERASER = (1 << 5),
- GP_PAINTFLAG_REQ_VECTOR = (1 << 6),
+ GP_PAINTFLAG_FIRSTRUN = (1 << 0), /* operator just started */
+ GP_PAINTFLAG_STROKEADDED = (1 << 1),
+ GP_PAINTFLAG_SELECTMASK = (1 << 3),
+ GP_PAINTFLAG_HARD_ERASER = (1 << 4),
+ GP_PAINTFLAG_STROKE_ERASER = (1 << 5),
+ GP_PAINTFLAG_REQ_VECTOR = (1 << 6),
} eGPencil_PaintFlags;
/* Temporary 'Stroke' Operation data
* "p" = op->customdata
*/
typedef struct tGPsdata {
- bContext *C;
-
- /** main database pointer. */
- Main *bmain;
- /** current scene from context. */
- Scene *scene;
- struct Depsgraph *depsgraph;
-
- /** current object. */
- Object *ob;
- /** window where painting originated. */
- wmWindow *win;
- /** area where painting originated. */
- ScrArea *sa;
- /** region where painting originated. */
- ARegion *ar;
- /** needed for GP_STROKE_2DSPACE. */
- View2D *v2d;
- /** for using the camera rect within the 3d view. */
- rctf *subrect;
- rctf subrect_data;
-
- /** settings to pass to gp_points_to_xy(). */
- GP_SpaceConversion gsc;
-
- /** pointer to owner of gp-datablock. */
- PointerRNA ownerPtr;
- /** gp-datablock layer comes from. */
- bGPdata *gpd;
- /** layer we're working on. */
- bGPDlayer *gpl;
- /** frame we're working on. */
- bGPDframe *gpf;
-
- /** projection-mode flags (toolsettings - eGPencil_Placement_Flags) */
- char *align_flag;
-
- /** current status of painting. */
- eGPencil_PaintStatus status;
- /** mode for painting. */
- eGPencil_PaintModes paintmode;
- /** flags that can get set during runtime (eGPencil_PaintFlags) */
- eGPencil_PaintFlags flags;
-
- /** radius of influence for eraser. */
- short radius;
-
- /** current mouse-position. */
- float mval[2];
- /** previous recorded mouse-position. */
- float mvalo[2];
- /** initial recorded mouse-position */
- float mvali[2];
-
- /** current stylus pressure. */
- float pressure;
- /** previous stylus pressure. */
- float opressure;
-
- /* These need to be doubles, as (at least under unix) they are in seconds since epoch,
- * float (and its 7 digits precision) is definitively not enough here!
- * double, with its 15 digits precision, ensures us millisecond precision for a few centuries at least.
- */
- /** Used when converting to path. */
- double inittime;
- /** Used when converting to path. */
- double curtime;
- /** Used when converting to path. */
- double ocurtime;
-
- /** Inverted transformation matrix applying when converting coords from screen-space
- * to region space. */
- float imat[4][4];
- float mat[4][4];
-
- /** custom color - hack for enforcing a particular color for track/mask editing. */
- float custom_color[4];
-
- /** radial cursor data for drawing eraser. */
- void *erasercursor;
-
- /* mat settings are only used for 3D view */
- /** current material */
- Material *material;
- /** current drawing brush */
- Brush *brush;
- /** default eraser brush */
- Brush *eraser;
-
- /** 1: line horizontal, 2: line vertical, other: not defined */
- short straight;
- /** lock drawing to one axis */
- int lock_axis;
- /** the stroke is no fill mode */
- bool disable_fill;
-
- RNG *rng;
-
- /** key used for invoking the operator */
- short keymodifier;
- /** shift modifier flag */
- short shift;
- /** size in pixels for uv calculation */
- float totpixlen;
-
- /* guide */
- /** guide spacing */
- float guide_spacing;
- /** half guide spacing */
- float half_spacing;
- /** origin */
- float origin[2];
-
- ReportList *reports;
+ bContext *C;
+
+ /** main database pointer. */
+ Main *bmain;
+ /** current scene from context. */
+ Scene *scene;
+ struct Depsgraph *depsgraph;
+
+ /** current object. */
+ Object *ob;
+ /** window where painting originated. */
+ wmWindow *win;
+ /** area where painting originated. */
+ ScrArea *sa;
+ /** region where painting originated. */
+ ARegion *ar;
+ /** needed for GP_STROKE_2DSPACE. */
+ View2D *v2d;
+ /** for using the camera rect within the 3d view. */
+ rctf *subrect;
+ rctf subrect_data;
+
+ /** settings to pass to gp_points_to_xy(). */
+ GP_SpaceConversion gsc;
+
+ /** pointer to owner of gp-datablock. */
+ PointerRNA ownerPtr;
+ /** gp-datablock layer comes from. */
+ bGPdata *gpd;
+ /** layer we're working on. */
+ bGPDlayer *gpl;
+ /** frame we're working on. */
+ bGPDframe *gpf;
+
+ /** projection-mode flags (toolsettings - eGPencil_Placement_Flags) */
+ char *align_flag;
+
+ /** current status of painting. */
+ eGPencil_PaintStatus status;
+ /** mode for painting. */
+ eGPencil_PaintModes paintmode;
+ /** flags that can get set during runtime (eGPencil_PaintFlags) */
+ eGPencil_PaintFlags flags;
+
+ /** radius of influence for eraser. */
+ short radius;
+
+ /** current mouse-position. */
+ float mval[2];
+ /** previous recorded mouse-position. */
+ float mvalo[2];
+ /** initial recorded mouse-position */
+ float mvali[2];
+
+ /** current stylus pressure. */
+ float pressure;
+ /** previous stylus pressure. */
+ float opressure;
+
+ /* These need to be doubles, as (at least under unix) they are in seconds since epoch,
+ * float (and its 7 digits precision) is definitively not enough here!
+ * double, with its 15 digits precision, ensures us millisecond precision for a few centuries at least.
+ */
+ /** Used when converting to path. */
+ double inittime;
+ /** Used when converting to path. */
+ double curtime;
+ /** Used when converting to path. */
+ double ocurtime;
+
+ /** Inverted transformation matrix applying when converting coords from screen-space
+ * to region space. */
+ float imat[4][4];
+ float mat[4][4];
+
+ /** custom color - hack for enforcing a particular color for track/mask editing. */
+ float custom_color[4];
+
+ /** radial cursor data for drawing eraser. */
+ void *erasercursor;
+
+ /* mat settings are only used for 3D view */
+ /** current material */
+ Material *material;
+ /** current drawing brush */
+ Brush *brush;
+ /** default eraser brush */
+ Brush *eraser;
+
+ /** 1: line horizontal, 2: line vertical, other: not defined */
+ short straight;
+ /** lock drawing to one axis */
+ int lock_axis;
+ /** the stroke is no fill mode */
+ bool disable_fill;
+
+ RNG *rng;
+
+ /** key used for invoking the operator */
+ short keymodifier;
+ /** shift modifier flag */
+ short shift;
+ /** size in pixels for uv calculation */
+ float totpixlen;
+
+ /* guide */
+ /** guide spacing */
+ float guide_spacing;
+ /** half guide spacing */
+ float half_spacing;
+ /** origin */
+ float origin[2];
+
+ ReportList *reports;
} tGPsdata;
/* ------ */
@@ -241,30 +240,30 @@ typedef struct tGPsdata {
/* Macros for accessing sensitivity thresholds... */
/* minimum number of pixels mouse should move before new point created */
-#define MIN_MANHATTEN_PX (U.gp_manhattendist)
+#define MIN_MANHATTEN_PX (U.gp_manhattendist)
/* minimum length of new segment before new point can be added */
-#define MIN_EUCLIDEAN_PX (U.gp_euclideandist)
+#define MIN_EUCLIDEAN_PX (U.gp_euclideandist)
static void gp_update_cache(bGPdata *gpd)
{
- if (gpd) {
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
- }
+ if (gpd) {
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+ }
}
static bool gp_stroke_added_check(tGPsdata *p)
{
- return (p->gpf && p->gpf->strokes.last && p->flags & GP_PAINTFLAG_STROKEADDED);
+ 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);
- p->flags |= GP_PAINTFLAG_STROKEADDED;
+ BLI_assert(p->gpf->strokes.last != NULL);
+ p->flags |= GP_PAINTFLAG_STROKEADDED;
- /* drawing batch cache is dirty now */
- gp_update_cache(p->gpd);
+ /* drawing batch cache is dirty now */
+ gp_update_cache(p->gpd);
}
/* ------ */
@@ -278,49 +277,50 @@ static void gp_session_validatebuffer(tGPsdata *p);
/* check if context is suitable for drawing */
static bool gpencil_draw_poll(bContext *C)
{
- if (ED_operator_regionactive(C)) {
- ScrArea *sa = CTX_wm_area(C);
- /* 3D Viewport */
- if (sa->spacetype != SPACE_VIEW3D) {
- return false;
- }
-
- /* check if Grease Pencil isn't already running */
- if (ED_gpencil_session_active() != 0) {
- CTX_wm_operator_poll_msg_set(C, "Grease Pencil operator is already active");
- return false;
- }
-
- /* only grease pencil object type */
- Object *ob = CTX_data_active_object(C);
- if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
- return false;
- }
-
- bGPdata *gpd = (bGPdata *)ob->data;
- if (!GPENCIL_PAINT_MODE(gpd)) {
- return false;
- }
-
- ToolSettings *ts = CTX_data_scene(C)->toolsettings;
- if (!ts->gp_paint->paint.brush) {
- CTX_wm_operator_poll_msg_set(C, "Grease Pencil has no active paint tool");
- return false;
- }
-
- return true;
- }
- else {
- CTX_wm_operator_poll_msg_set(C, "Active region not set");
- return false;
- }
+ if (ED_operator_regionactive(C)) {
+ ScrArea *sa = CTX_wm_area(C);
+ /* 3D Viewport */
+ if (sa->spacetype != SPACE_VIEW3D) {
+ return false;
+ }
+
+ /* check if Grease Pencil isn't already running */
+ if (ED_gpencil_session_active() != 0) {
+ CTX_wm_operator_poll_msg_set(C, "Grease Pencil operator is already active");
+ return false;
+ }
+
+ /* only grease pencil object type */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+ return false;
+ }
+
+ bGPdata *gpd = (bGPdata *)ob->data;
+ if (!GPENCIL_PAINT_MODE(gpd)) {
+ return false;
+ }
+
+ ToolSettings *ts = CTX_data_scene(C)->toolsettings;
+ if (!ts->gp_paint->paint.brush) {
+ CTX_wm_operator_poll_msg_set(C, "Grease Pencil has no active paint tool");
+ return false;
+ }
+
+ return true;
+ }
+ else {
+ CTX_wm_operator_poll_msg_set(C, "Active region not set");
+ return false;
+ }
}
/* check if projecting strokes into 3d-geometry in the 3D-View */
static bool gpencil_project_check(tGPsdata *p)
{
- bGPdata *gpd = p->gpd;
- return ((gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) && (*p->align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE)));
+ bGPdata *gpd = p->gpd;
+ return ((gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) &&
+ (*p->align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE)));
}
/* ******************************************* */
@@ -331,220 +331,219 @@ static bool gpencil_project_check(tGPsdata *p)
/* get the reference point for stroke-point conversions */
static void gp_get_3d_reference(tGPsdata *p, float vec[3])
{
- Object *ob = NULL;
- 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);
+ Object *ob = NULL;
+ 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);
}
/* Stroke Editing ---------------------------- */
/* check if the current mouse position is suitable for adding a new point */
static bool gp_stroke_filtermval(tGPsdata *p, const float mval[2], float mvalo[2])
{
- Brush *brush = p->brush;
- int dx = (int)fabsf(mval[0] - mvalo[0]);
- int dy = (int)fabsf(mval[1] - mvalo[1]);
- brush->gpencil_settings->flag &= ~GP_BRUSH_STABILIZE_MOUSE_TEMP;
-
- /* if buffer is empty, just let this go through (i.e. so that dots will work) */
- if (p->gpd->runtime.sbuffer_size == 0) {
- return true;
- }
- /* if lazy mouse, check minimum distance */
- else if (GPENCIL_LAZY_MODE(brush, p->shift)) {
- brush->gpencil_settings->flag |= GP_BRUSH_STABILIZE_MOUSE_TEMP;
- if ((dx * dx + dy * dy) > (brush->smooth_stroke_radius * brush->smooth_stroke_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;
- }
- }
- /* check if mouse moved at least certain distance on both axes (best case)
- * - aims to eliminate some jitter-noise from input when trying to draw straight lines freehand
- */
- else if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX))
- return true;
-
- /* check if the distance since the last point is significant enough
- * - prevents points being added too densely
- * - distance here doesn't use sqrt to prevent slowness... we should still be safe from overflows though
- */
- else if ((dx * dx + dy * dy) > MIN_EUCLIDEAN_PX * MIN_EUCLIDEAN_PX)
- return true;
-
- /* mouse 'didn't move' */
- else
- return false;
+ Brush *brush = p->brush;
+ int dx = (int)fabsf(mval[0] - mvalo[0]);
+ int dy = (int)fabsf(mval[1] - mvalo[1]);
+ brush->gpencil_settings->flag &= ~GP_BRUSH_STABILIZE_MOUSE_TEMP;
+
+ /* if buffer is empty, just let this go through (i.e. so that dots will work) */
+ if (p->gpd->runtime.sbuffer_size == 0) {
+ return true;
+ }
+ /* if lazy mouse, check minimum distance */
+ else if (GPENCIL_LAZY_MODE(brush, p->shift)) {
+ brush->gpencil_settings->flag |= GP_BRUSH_STABILIZE_MOUSE_TEMP;
+ if ((dx * dx + dy * dy) > (brush->smooth_stroke_radius * brush->smooth_stroke_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;
+ }
+ }
+ /* check if mouse moved at least certain distance on both axes (best case)
+ * - aims to eliminate some jitter-noise from input when trying to draw straight lines freehand
+ */
+ else if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX))
+ return true;
+
+ /* check if the distance since the last point is significant enough
+ * - prevents points being added too densely
+ * - distance here doesn't use sqrt to prevent slowness... we should still be safe from overflows though
+ */
+ else if ((dx * dx + dy * dy) > MIN_EUCLIDEAN_PX * MIN_EUCLIDEAN_PX)
+ return true;
+
+ /* mouse 'didn't move' */
+ else
+ return false;
}
/* reproject stroke to plane locked to axis in 3d cursor location */
static void gp_reproject_toplane(tGPsdata *p, bGPDstroke *gps)
{
- bGPdata *gpd = p->gpd;
- Object *obact = (Object *)p->ownerPtr.data;
-
- float origin[3];
- RegionView3D *rv3d = p->ar->regiondata;
-
- /* verify the stroke mode is CURSOR 3d space mode */
- if ((gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) == 0) {
- return;
- }
- if ((*p->align_flag & GP_PROJECT_VIEWSPACE) == 0) {
- return;
- }
- if ((*p->align_flag & GP_PROJECT_DEPTH_VIEW) || (*p->align_flag & GP_PROJECT_DEPTH_STROKE)) {
- return;
- }
-
- /* get drawing origin */
- gp_get_3d_reference(p, origin);
- ED_gp_project_stroke_to_plane(
- p->scene, obact, rv3d, gps,
- origin, p->lock_axis - 1);
+ bGPdata *gpd = p->gpd;
+ Object *obact = (Object *)p->ownerPtr.data;
+
+ float origin[3];
+ RegionView3D *rv3d = p->ar->regiondata;
+
+ /* verify the stroke mode is CURSOR 3d space mode */
+ if ((gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) == 0) {
+ return;
+ }
+ if ((*p->align_flag & GP_PROJECT_VIEWSPACE) == 0) {
+ return;
+ }
+ if ((*p->align_flag & GP_PROJECT_DEPTH_VIEW) || (*p->align_flag & GP_PROJECT_DEPTH_STROKE)) {
+ return;
+ }
+
+ /* get drawing origin */
+ gp_get_3d_reference(p, origin);
+ ED_gp_project_stroke_to_plane(p->scene, obact, rv3d, gps, origin, p->lock_axis - 1);
}
/* convert screen-coordinates to buffer-coordinates */
/* XXX this method needs a total overhaul! */
static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[3], float *depth)
{
- bGPdata *gpd = p->gpd;
-
- /* in 3d-space - pt->x/y/z are 3 side-by-side floats */
- if (gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) {
-
- /* add small offset to keep stroke over the surface */
- if ((depth) &&
- (gpd->zdepth_offset > 0.0f) &&
- (*p->align_flag & GP_PROJECT_DEPTH_VIEW))
- {
- *depth *= (1.0f - gpd->zdepth_offset);
- }
-
- 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))) {
- /* projecting onto 3D-Geometry
- * - nothing more needs to be done here, since view_autodist_simple() has already done it
- */
-
- /* verify valid zdepth, if it's wrong, the default drawing mode is used
- * and the function doesn't return now */
- if ((depth == NULL) || (*depth <= 1.0f)) {
- return;
- }
- }
-
- float mval_prj[2];
- float rvec[3], dvec[3];
- float mval_f[2];
- float zfac;
-
- /* Current method just converts each point in screen-coordinates to
- * 3D-coordinates using the 3D-cursor as reference. In general, this
- * 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);
-
- if (ED_view3d_project_float_global(p->ar, 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);
- sub_v3_v3v3(out, rvec, dvec);
- }
- else {
- zero_v3(out);
- }
- }
+ bGPdata *gpd = p->gpd;
+
+ /* in 3d-space - pt->x/y/z are 3 side-by-side floats */
+ if (gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) {
+
+ /* add small offset to keep stroke over the surface */
+ if ((depth) && (gpd->zdepth_offset > 0.0f) && (*p->align_flag & GP_PROJECT_DEPTH_VIEW)) {
+ *depth *= (1.0f - gpd->zdepth_offset);
+ }
+
+ 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))) {
+ /* projecting onto 3D-Geometry
+ * - nothing more needs to be done here, since view_autodist_simple() has already done it
+ */
+
+ /* verify valid zdepth, if it's wrong, the default drawing mode is used
+ * and the function doesn't return now */
+ if ((depth == NULL) || (*depth <= 1.0f)) {
+ return;
+ }
+ }
+
+ float mval_prj[2];
+ float rvec[3], dvec[3];
+ float mval_f[2];
+ float zfac;
+
+ /* Current method just converts each point in screen-coordinates to
+ * 3D-coordinates using the 3D-cursor as reference. In general, this
+ * 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);
+
+ if (ED_view3d_project_float_global(p->ar, 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);
+ sub_v3_v3v3(out, rvec, dvec);
+ }
+ else {
+ zero_v3(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)
+static void gp_brush_jitter(bGPdata *gpd,
+ Brush *brush,
+ tGPspoint *pt,
+ const float mval[2],
+ const float pressure,
+ float r_mval[2],
+ RNG *rng)
{
- float tmp_pressure = pressure;
- if (brush->gpencil_settings->draw_jitter > 0.0f) {
- float curvef = 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 */
- if (gpd->runtime.sbuffer_size > 1) {
- mvec[0] = (mval[0] - (pt - 1)->x);
- mvec[1] = (mval[1] - (pt - 1)->y);
- 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);
- }
-
- r_mval[0] = mval[0] + svec[0];
- r_mval[1] = mval[1] + svec[1];
-
+ float tmp_pressure = pressure;
+ if (brush->gpencil_settings->draw_jitter > 0.0f) {
+ float curvef = 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 */
+ if (gpd->runtime.sbuffer_size > 1) {
+ mvec[0] = (mval[0] - (pt - 1)->x);
+ mvec[1] = (mval[1] - (pt - 1)->y);
+ 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);
+ }
+
+ r_mval[0] = mval[0] + svec[0];
+ r_mval[1] = mval[1] + svec[1];
}
/* apply pressure change depending of the angle of the stroke to simulate a pen with shape */
static void gp_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const float mval[2])
{
- 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;
- /* angle vector of the brush with full thickness */
- float v0[2] = { cos(angle), sin(angle) };
-
- /* Apply to first point (only if there are 2 points because before no data to do it ) */
- if (gpd->runtime.sbuffer_size == 1) {
- mvec[0] = (mval[0] - (pt - 1)->x);
- mvec[1] = (mval[1] - (pt - 1)->y);
- normalize_v2(mvec);
-
- /* uses > 1.0f to get a smooth transition in first point */
- fac = 1.4f - fabs(dot_v2v2(v0, mvec)); /* 0.0 to 1.0 */
- (pt - 1)->pressure = (pt - 1)->pressure - (sen * fac);
-
- CLAMP((pt - 1)->pressure, GPENCIL_ALPHA_OPACITY_THRESH, 1.0f);
- }
-
- /* apply from second point */
- if (gpd->runtime.sbuffer_size >= 1) {
- mvec[0] = (mval[0] - (pt - 1)->x);
- mvec[1] = (mval[1] - (pt - 1)->y);
- normalize_v2(mvec);
-
- 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;
-
- CLAMP(pt->pressure, GPENCIL_ALPHA_OPACITY_THRESH, 1.0f);
- }
-
+ 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;
+ /* angle vector of the brush with full thickness */
+ float v0[2] = {cos(angle), sin(angle)};
+
+ /* Apply to first point (only if there are 2 points because before no data to do it ) */
+ if (gpd->runtime.sbuffer_size == 1) {
+ mvec[0] = (mval[0] - (pt - 1)->x);
+ mvec[1] = (mval[1] - (pt - 1)->y);
+ normalize_v2(mvec);
+
+ /* uses > 1.0f to get a smooth transition in first point */
+ fac = 1.4f - fabs(dot_v2v2(v0, mvec)); /* 0.0 to 1.0 */
+ (pt - 1)->pressure = (pt - 1)->pressure - (sen * fac);
+
+ CLAMP((pt - 1)->pressure, GPENCIL_ALPHA_OPACITY_THRESH, 1.0f);
+ }
+
+ /* apply from second point */
+ if (gpd->runtime.sbuffer_size >= 1) {
+ mvec[0] = (mval[0] - (pt - 1)->x);
+ mvec[1] = (mval[1] - (pt - 1)->y);
+ normalize_v2(mvec);
+
+ 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;
+
+ CLAMP(pt->pressure, GPENCIL_ALPHA_OPACITY_THRESH, 1.0f);
+ }
}
/* Apply smooth to buffer while drawing
@@ -558,708 +557,712 @@ 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;
- short num_points = gpd->runtime.sbuffer_size;
-
- /* Do nothing if not enough points to smooth out */
- if ((num_points < 3) || (idx < 3) || (inf == 0.0f)) {
- return;
- }
-
- tGPspoint *points = (tGPspoint *)gpd->runtime.sbuffer;
- float steps = 4.0f;
- if (idx < 4) {
- steps--;
- }
-
- tGPspoint *pta = idx >= 4 ? &points[idx - 4] : NULL;
- tGPspoint *ptb = idx >= 3 ? &points[idx - 3] : NULL;
- tGPspoint *ptc = idx >= 2 ? &points[idx - 2] : NULL;
- tGPspoint *ptd = &points[idx - 1];
-
- float sco[2] = { 0.0f };
- float a[2], b[2], c[2], d[2];
- const float average_fac = 1.0f / steps;
-
- /* Compute smoothed coordinate by taking the ones nearby */
- if (pta) {
- copy_v2_v2(a, &pta->x);
- madd_v2_v2fl(sco, a, average_fac);
- }
- if (ptb) {
- copy_v2_v2(b, &ptb->x);
- madd_v2_v2fl(sco, b, average_fac);
- }
- if (ptc) {
- copy_v2_v2(c, &ptc->x);
- madd_v2_v2fl(sco, c, average_fac);
- }
- if (ptd) {
- copy_v2_v2(d, &ptd->x);
- madd_v2_v2fl(sco, d, 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);
+ bGPdata *gpd = p->gpd;
+ short num_points = gpd->runtime.sbuffer_size;
+
+ /* Do nothing if not enough points to smooth out */
+ if ((num_points < 3) || (idx < 3) || (inf == 0.0f)) {
+ return;
+ }
+
+ tGPspoint *points = (tGPspoint *)gpd->runtime.sbuffer;
+ float steps = 4.0f;
+ if (idx < 4) {
+ steps--;
+ }
+
+ tGPspoint *pta = idx >= 4 ? &points[idx - 4] : NULL;
+ tGPspoint *ptb = idx >= 3 ? &points[idx - 3] : NULL;
+ tGPspoint *ptc = idx >= 2 ? &points[idx - 2] : NULL;
+ tGPspoint *ptd = &points[idx - 1];
+
+ float sco[2] = {0.0f};
+ float a[2], b[2], c[2], d[2];
+ const float average_fac = 1.0f / steps;
+
+ /* Compute smoothed coordinate by taking the ones nearby */
+ if (pta) {
+ copy_v2_v2(a, &pta->x);
+ madd_v2_v2fl(sco, a, average_fac);
+ }
+ if (ptb) {
+ copy_v2_v2(b, &ptb->x);
+ madd_v2_v2fl(sco, b, average_fac);
+ }
+ if (ptc) {
+ copy_v2_v2(c, &ptc->x);
+ madd_v2_v2fl(sco, c, average_fac);
+ }
+ if (ptd) {
+ copy_v2_v2(d, &ptd->x);
+ madd_v2_v2fl(sco, d, 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);
}
/* 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)
+static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure, double curtime)
{
- bGPdata *gpd = p->gpd;
- Brush *brush = p->brush;
- 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);
-
- /* check painting mode */
- if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
- /* straight lines only - i.e. only store start and end point in buffer */
- if (gpd->runtime.sbuffer_size == 0) {
- /* first point in buffer (start 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);
-
- /* increment buffer size */
- gpd->runtime.sbuffer_size++;
- }
- else {
- /* just reset the endpoint to the latest value
- * - assume that pointers for this are always valid...
- */
- pt = ((tGPspoint *)(gpd->runtime.sbuffer) + 1);
-
- /* 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);
-
- /* now the buffer has 2 points (and shouldn't be allowed to get any larger) */
- gpd->runtime.sbuffer_size = 2;
- }
-
- /* can keep carrying on this way :) */
- return GP_STROKEADD_NORMAL;
- }
- else if (p->paintmode == GP_PAINTMODE_DRAW) { /* normal drawing */
- /* check if still room in buffer */
- if (gpd->runtime.sbuffer_size >= GP_STROKE_BUFFER_MAX)
- return GP_STROKEADD_OVERFLOW;
-
- /* get pointer to destination point */
- pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_size);
-
- /* store settings */
- /* pressure */
- if (brush->gpencil_settings->flag & GP_BRUSH_USE_PRESSURE) {
- float curvef = curvemapping_evaluateF(brush->gpencil_settings->curve_sensitivity, 0, pressure);
- pt->pressure = curvef * brush->gpencil_settings->draw_sensitivity;
- }
- else {
- pt->pressure = 1.0f;
- }
-
- /* 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 = 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);
- }
-
- /* 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;
- }
- CLAMP(pt->uv_rot, -M_PI_2, M_PI_2);
- }
- else {
- pt->uv_rot = 0.0f;
- }
-
- /* apply angle of stroke to brush size */
- if (brush->gpencil_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 = 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_size > 0)) {
- float pixsize = gp_style->texture_pixsize / 1000000.0f;
- tGPspoint *ptb = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_size - 1;
- bGPDspoint spt, spt2;
-
- /* get origin to reproject point */
- float origin[3];
- gp_get_3d_reference(p, origin);
- /* reproject current */
- ED_gpencil_tpoint_to_point(p->ar, 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_gp_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt2);
- p->totpixlen += len_v3v3(&spt.x, &spt2.x) / pixsize;
- pt->uv_fac = p->totpixlen;
- if ((gp_style) && (gp_style->sima)) {
- pt->uv_fac /= gp_style->sima->gen_x;
- }
- }
- else {
- p->totpixlen = 0.0f;
- pt->uv_fac = 0.0f;
- }
-
- /* increment counters */
- gpd->runtime.sbuffer_size++;
-
- /* 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, brush->gpencil_settings->active_smooth * ((3.0f - s) / 3.0f), gpd->runtime.sbuffer_size - s);
- }
- }
-
- /* check if another operation can still occur */
- if (gpd->runtime.sbuffer_size == GP_STROKE_BUFFER_MAX)
- return GP_STROKEADD_FULL;
- else
- 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_size == 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_size == 0)
- gpd->runtime.sbuffer_size++;
-
- return GP_STROKEADD_NORMAL;
- }
-
- /* return invalid state for now... */
- return GP_STROKEADD_INVALID;
+ bGPdata *gpd = p->gpd;
+ Brush *brush = p->brush;
+ 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);
+
+ /* check painting mode */
+ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
+ /* straight lines only - i.e. only store start and end point in buffer */
+ if (gpd->runtime.sbuffer_size == 0) {
+ /* first point in buffer (start 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);
+
+ /* increment buffer size */
+ gpd->runtime.sbuffer_size++;
+ }
+ else {
+ /* just reset the endpoint to the latest value
+ * - assume that pointers for this are always valid...
+ */
+ pt = ((tGPspoint *)(gpd->runtime.sbuffer) + 1);
+
+ /* 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);
+
+ /* now the buffer has 2 points (and shouldn't be allowed to get any larger) */
+ gpd->runtime.sbuffer_size = 2;
+ }
+
+ /* can keep carrying on this way :) */
+ return GP_STROKEADD_NORMAL;
+ }
+ else if (p->paintmode == GP_PAINTMODE_DRAW) { /* normal drawing */
+ /* check if still room in buffer */
+ if (gpd->runtime.sbuffer_size >= GP_STROKE_BUFFER_MAX)
+ return GP_STROKEADD_OVERFLOW;
+
+ /* get pointer to destination point */
+ pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_size);
+
+ /* store settings */
+ /* pressure */
+ if (brush->gpencil_settings->flag & GP_BRUSH_USE_PRESSURE) {
+ float curvef = curvemapping_evaluateF(
+ brush->gpencil_settings->curve_sensitivity, 0, pressure);
+ pt->pressure = curvef * brush->gpencil_settings->draw_sensitivity;
+ }
+ else {
+ pt->pressure = 1.0f;
+ }
+
+ /* 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 = 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);
+ }
+
+ /* 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;
+ }
+ CLAMP(pt->uv_rot, -M_PI_2, M_PI_2);
+ }
+ else {
+ pt->uv_rot = 0.0f;
+ }
+
+ /* apply angle of stroke to brush size */
+ if (brush->gpencil_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 = 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_size > 0)) {
+ float pixsize = gp_style->texture_pixsize / 1000000.0f;
+ tGPspoint *ptb = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_size - 1;
+ bGPDspoint spt, spt2;
+
+ /* get origin to reproject point */
+ float origin[3];
+ gp_get_3d_reference(p, origin);
+ /* reproject current */
+ ED_gpencil_tpoint_to_point(p->ar, 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_gp_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt2);
+ p->totpixlen += len_v3v3(&spt.x, &spt2.x) / pixsize;
+ pt->uv_fac = p->totpixlen;
+ if ((gp_style) && (gp_style->sima)) {
+ pt->uv_fac /= gp_style->sima->gen_x;
+ }
+ }
+ else {
+ p->totpixlen = 0.0f;
+ pt->uv_fac = 0.0f;
+ }
+
+ /* increment counters */
+ gpd->runtime.sbuffer_size++;
+
+ /* 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,
+ brush->gpencil_settings->active_smooth * ((3.0f - s) / 3.0f),
+ gpd->runtime.sbuffer_size - s);
+ }
+ }
+
+ /* check if another operation can still occur */
+ if (gpd->runtime.sbuffer_size == GP_STROKE_BUFFER_MAX)
+ return GP_STROKEADD_FULL;
+ else
+ 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_size == 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_size == 0)
+ gpd->runtime.sbuffer_size++;
+
+ return GP_STROKEADD_NORMAL;
+ }
+
+ /* return invalid state for now... */
+ return GP_STROKEADD_INVALID;
}
/* make a new stroke from the buffer data */
static void gp_stroke_newfrombuffer(tGPsdata *p)
{
- bGPdata *gpd = p->gpd;
- bGPDlayer *gpl = p->gpl;
- bGPDstroke *gps;
- bGPDspoint *pt;
- tGPspoint *ptc;
- MDeformVert *dvert = NULL;
- Brush *brush = p->brush;
- ToolSettings *ts = p->scene->toolsettings;
- Depsgraph *depsgraph = p->depsgraph;
- Object *obact = (Object *)p->ownerPtr.data;
- RegionView3D *rv3d = p->ar->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;
- const bool is_depth = (bool)(*align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE));
- const bool is_camera = (bool)(ts->gp_sculpt.lock_axis == 0) &&
- (rv3d->persp == RV3D_CAMOB) && (!is_depth);
- int i, totelem;
-
- /* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */
- int depth_margin = (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 4 : 0;
-
- /* get total number of points to allocate space for
- * - drawing straight-lines only requires the endpoints
- */
- if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT)
- totelem = (gpd->runtime.sbuffer_size >= 2) ? 2 : gpd->runtime.sbuffer_size;
- else
- totelem = gpd->runtime.sbuffer_size;
-
- /* exit with error if no valid points from this stroke */
- if (totelem == 0) {
- if (G.debug & G_DEBUG)
- printf("Error: No valid points in stroke buffer to convert (tot=%d)\n", gpd->runtime.sbuffer_size);
- 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->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;
-
- /* 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");
-
- /* initialize triangle memory to dummy data */
- gps->triangles = MEM_callocN(sizeof(bGPDtriangle), "GP Stroke triangulation");
- 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 */
- pt = gps->points + (gps->totpoints - totelem);
- if (gps->dvert != NULL) {
- dvert = gps->dvert + (gps->totpoints - totelem);
- }
-
- /* copy points from the buffer to the stroke */
- if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
- /* straight lines only -> only endpoints */
- {
- /* first point */
- ptc = gpd->runtime.sbuffer;
-
- /* convert screen-coordinates to appropriate coordinates (and store them) */
- gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
- /* copy pressure and time */
- pt->pressure = ptc->pressure;
- pt->strength = ptc->strength;
- CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
- pt->time = ptc->time;
- 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);
- if (dw) {
- dw->weight = ts->vgroup_weight;
- }
- dvert++;
- }
- else {
- if (dvert != NULL) {
- dvert->totweight = 0;
- dvert->dw = NULL;
- dvert++;
- }
- }
- }
-
- if (totelem == 2) {
- /* last point if applicable */
- ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_size - 1);
-
- /* convert screen-coordinates to appropriate coordinates (and store them) */
- gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
- /* 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;
- }
- }
- }
-
- /* reproject to plane (only in 3d space) */
- gp_reproject_toplane(p, gps);
- 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);
- }
-
- /* 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);
- }
- }
- 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;
-
- /* get an array of depths, far depths are blended */
- if (gpencil_project_check(p)) {
- int mval_i[2], mval_prev[2] = { 0 };
- int interp_depth = 0;
- int found_depth = 0;
-
- depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_size, "depth_points");
-
- for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size; 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) &&
- (i && (ED_view3d_autodist_depth_seg(p->ar, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0)))
- {
- interp_depth = true;
- }
- else {
- found_depth = true;
- }
-
- copy_v2_v2_int(mval_prev, mval_i);
- }
-
- if (found_depth == false) {
- /* eeh... not much we can do.. :/, ignore depth in this case, use the 3D cursor */
- for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--)
- depth_arr[i] = 0.9999f;
- }
- else {
- if ((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE_ENDPOINTS) ||
- (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE_FIRST))
- {
- int first_valid = 0;
- int last_valid = 0;
-
- /* find first valid contact point */
- for (i = 0; i < gpd->runtime.sbuffer_size; i++) {
- if (depth_arr[i] != FLT_MAX)
- break;
- }
- first_valid = i;
-
- /* find last valid contact point */
- if (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE_FIRST) {
- last_valid = first_valid;
- }
- else {
- for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--) {
- if (depth_arr[i] != FLT_MAX)
- break;
- }
- last_valid = i;
- }
- /* invalidate any other point, to interpolate between
- * first and last contact in an imaginary line between them */
- for (i = 0; i < gpd->runtime.sbuffer_size; i++) {
- if ((i != first_valid) && (i != last_valid)) {
- depth_arr[i] = FLT_MAX;
- }
- }
- interp_depth = true;
- }
-
- if (interp_depth) {
- interp_sparse_array(depth_arr, gpd->runtime.sbuffer_size, FLT_MAX);
- }
- }
- }
-
- pt = gps->points;
- dvert = gps->dvert;
-
- /* convert all points (normal behavior) */
- for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size && ptc; i++, ptc++, pt++) {
- /* convert screen-coordinates to appropriate coordinates (and store them) */
- gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL);
-
- /* copy pressure and time */
- pt->pressure = ptc->pressure;
- pt->strength = ptc->strength;
- CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
- pt->time = ptc->time;
- pt->uv_fac = ptc->uv_fac;
- pt->uv_rot = ptc->uv_rot;
-
- if (dvert != NULL) {
- dvert->totweight = 0;
- dvert->dw = NULL;
- dvert++;
- }
- }
-
- /* subdivide and smooth the stroke */
- 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 without changing too much
- * the original stroke
- */
- if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_SETTINGS) &&
- (brush->gpencil_settings->draw_smoothfac > 0.0f))
- {
- 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);
- }
- reduce += 0.25f; // reduce the factor
- }
- }
- /* 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);
- }
- }
- }
-
- /* 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);
- /* 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);
- }
-
- if (depth_arr)
- MEM_freeN(depth_arr);
- }
-
- /* Save material index */
- gps->mat_nr = BKE_gpencil_object_material_get_index_from_brush(p->ob, p->brush);
-
- /* 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)) {
- BLI_addhead(&p->gpf->strokes, gps);
- }
- else {
- BLI_addtail(&p->gpf->strokes, gps);
- }
- /* add weights */
- if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
- 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);
- if (dw) {
- dw->weight = ts->vgroup_weight;
- }
- }
- }
-
- /* 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);
- }
-
- gp_stroke_added_enable(p);
+ bGPdata *gpd = p->gpd;
+ bGPDlayer *gpl = p->gpl;
+ bGPDstroke *gps;
+ bGPDspoint *pt;
+ tGPspoint *ptc;
+ MDeformVert *dvert = NULL;
+ Brush *brush = p->brush;
+ ToolSettings *ts = p->scene->toolsettings;
+ Depsgraph *depsgraph = p->depsgraph;
+ Object *obact = (Object *)p->ownerPtr.data;
+ RegionView3D *rv3d = p->ar->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;
+ const bool is_depth = (bool)(*align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE));
+ const bool is_camera = (bool)(ts->gp_sculpt.lock_axis == 0) && (rv3d->persp == RV3D_CAMOB) &&
+ (!is_depth);
+ int i, totelem;
+
+ /* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */
+ int depth_margin = (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 4 : 0;
+
+ /* get total number of points to allocate space for
+ * - drawing straight-lines only requires the endpoints
+ */
+ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT)
+ totelem = (gpd->runtime.sbuffer_size >= 2) ? 2 : gpd->runtime.sbuffer_size;
+ else
+ totelem = gpd->runtime.sbuffer_size;
+
+ /* exit with error if no valid points from this stroke */
+ if (totelem == 0) {
+ if (G.debug & G_DEBUG)
+ printf("Error: No valid points in stroke buffer to convert (tot=%d)\n",
+ gpd->runtime.sbuffer_size);
+ 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->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;
+
+ /* 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");
+
+ /* initialize triangle memory to dummy data */
+ gps->triangles = MEM_callocN(sizeof(bGPDtriangle), "GP Stroke triangulation");
+ 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 */
+ pt = gps->points + (gps->totpoints - totelem);
+ if (gps->dvert != NULL) {
+ dvert = gps->dvert + (gps->totpoints - totelem);
+ }
+
+ /* copy points from the buffer to the stroke */
+ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
+ /* straight lines only -> only endpoints */
+ {
+ /* first point */
+ ptc = gpd->runtime.sbuffer;
+
+ /* convert screen-coordinates to appropriate coordinates (and store them) */
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
+ /* copy pressure and time */
+ pt->pressure = ptc->pressure;
+ pt->strength = ptc->strength;
+ CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
+ pt->time = ptc->time;
+ 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);
+ if (dw) {
+ dw->weight = ts->vgroup_weight;
+ }
+ dvert++;
+ }
+ else {
+ if (dvert != NULL) {
+ dvert->totweight = 0;
+ dvert->dw = NULL;
+ dvert++;
+ }
+ }
+ }
+
+ if (totelem == 2) {
+ /* last point if applicable */
+ ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_size - 1);
+
+ /* convert screen-coordinates to appropriate coordinates (and store them) */
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
+ /* 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;
+ }
+ }
+ }
+
+ /* reproject to plane (only in 3d space) */
+ gp_reproject_toplane(p, gps);
+ 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);
+ }
+
+ /* 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);
+ }
+ }
+ 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;
+
+ /* get an array of depths, far depths are blended */
+ if (gpencil_project_check(p)) {
+ int mval_i[2], mval_prev[2] = {0};
+ int interp_depth = 0;
+ int found_depth = 0;
+
+ depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_size, "depth_points");
+
+ for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size; 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) &&
+ (i && (ED_view3d_autodist_depth_seg(
+ p->ar, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0))) {
+ interp_depth = true;
+ }
+ else {
+ found_depth = true;
+ }
+
+ copy_v2_v2_int(mval_prev, mval_i);
+ }
+
+ if (found_depth == false) {
+ /* eeh... not much we can do.. :/, ignore depth in this case, use the 3D cursor */
+ for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--)
+ depth_arr[i] = 0.9999f;
+ }
+ else {
+ if ((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE_ENDPOINTS) ||
+ (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE_FIRST)) {
+ int first_valid = 0;
+ int last_valid = 0;
+
+ /* find first valid contact point */
+ for (i = 0; i < gpd->runtime.sbuffer_size; i++) {
+ if (depth_arr[i] != FLT_MAX)
+ break;
+ }
+ first_valid = i;
+
+ /* find last valid contact point */
+ if (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE_FIRST) {
+ last_valid = first_valid;
+ }
+ else {
+ for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--) {
+ if (depth_arr[i] != FLT_MAX)
+ break;
+ }
+ last_valid = i;
+ }
+ /* invalidate any other point, to interpolate between
+ * first and last contact in an imaginary line between them */
+ for (i = 0; i < gpd->runtime.sbuffer_size; i++) {
+ if ((i != first_valid) && (i != last_valid)) {
+ depth_arr[i] = FLT_MAX;
+ }
+ }
+ interp_depth = true;
+ }
+
+ if (interp_depth) {
+ interp_sparse_array(depth_arr, gpd->runtime.sbuffer_size, FLT_MAX);
+ }
+ }
+ }
+
+ pt = gps->points;
+ dvert = gps->dvert;
+
+ /* convert all points (normal behavior) */
+ for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size && ptc;
+ i++, ptc++, pt++) {
+ /* convert screen-coordinates to appropriate coordinates (and store them) */
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL);
+
+ /* copy pressure and time */
+ pt->pressure = ptc->pressure;
+ pt->strength = ptc->strength;
+ CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
+ pt->time = ptc->time;
+ pt->uv_fac = ptc->uv_fac;
+ pt->uv_rot = ptc->uv_rot;
+
+ if (dvert != NULL) {
+ dvert->totweight = 0;
+ dvert->dw = NULL;
+ dvert++;
+ }
+ }
+
+ /* subdivide and smooth the stroke */
+ 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 without changing too much
+ * the original stroke
+ */
+ if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_SETTINGS) &&
+ (brush->gpencil_settings->draw_smoothfac > 0.0f)) {
+ 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);
+ }
+ reduce += 0.25f; // reduce the factor
+ }
+ }
+ /* 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);
+ }
+ }
+ }
+
+ /* 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);
+ /* 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);
+ }
+
+ if (depth_arr)
+ MEM_freeN(depth_arr);
+ }
+
+ /* Save material index */
+ gps->mat_nr = BKE_gpencil_object_material_get_index_from_brush(p->ob, p->brush);
+
+ /* 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)) {
+ BLI_addhead(&p->gpf->strokes, gps);
+ }
+ else {
+ BLI_addtail(&p->gpf->strokes, gps);
+ }
+ /* add weights */
+ if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
+ 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);
+ if (dw) {
+ dw->weight = ts->vgroup_weight;
+ }
+ }
+ }
+
+ /* 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);
+ }
+
+ gp_stroke_added_enable(p);
}
/* --- 'Eraser' for 'Paint' Tool ------ */
@@ -1267,97 +1270,102 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
/* which which point is infront (result should only be used for comparison) */
static float view3d_point_depth(const RegionView3D *rv3d, const float co[3])
{
- if (rv3d->is_persp) {
- return ED_view3d_calc_zfac(rv3d, co, NULL);
- }
- else {
- return -dot_v3v3(rv3d->viewinv[2], co);
- }
+ if (rv3d->is_persp) {
+ return ED_view3d_calc_zfac(rv3d, co, NULL);
+ }
+ else {
+ return -dot_v3v3(rv3d->viewinv[2], co);
+ }
}
/* only erase stroke points that are visible */
-static bool gp_stroke_eraser_is_occluded(tGPsdata *p, const bGPDspoint *pt, const int x, const int y)
+static bool gp_stroke_eraser_is_occluded(tGPsdata *p,
+ const bGPDspoint *pt,
+ const int x,
+ const int y)
{
- Object *obact = (Object *)p->ownerPtr.data;
- Brush *brush = p->brush;
- Brush *eraser = p->eraser;
- BrushGpencilSettings *gp_settings = NULL;
-
- if (brush->gpencil_tool == GPAINT_TOOL_ERASE) {
- gp_settings = brush->gpencil_settings;
- }
- else if ((eraser != NULL) & (eraser->gpencil_tool == GPAINT_TOOL_ERASE)) {
- gp_settings = eraser->gpencil_settings;
- }
-
- if ((gp_settings != NULL) && (p->sa->spacetype == SPACE_VIEW3D) &&
- (gp_settings->flag & GP_BRUSH_OCCLUDE_ERASER))
- {
- RegionView3D *rv3d = p->ar->regiondata;
- bGPDlayer *gpl = p->gpl;
-
- const int mval_i[2] = {x, y};
- float mval_3d[3];
- float fpt[3];
-
- float diff_mat[4][4];
- /* calculate difference matrix if parent object */
- ED_gpencil_parent_location(p->depsgraph, obact, p->gpd, gpl, diff_mat);
-
- if (ED_view3d_autodist_simple(p->ar, mval_i, mval_3d, 0, NULL)) {
- const float depth_mval = view3d_point_depth(rv3d, mval_3d);
-
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- const float depth_pt = view3d_point_depth(rv3d, fpt);
-
- if (depth_pt > depth_mval) {
- return true;
- }
- }
- }
- return false;
+ Object *obact = (Object *)p->ownerPtr.data;
+ Brush *brush = p->brush;
+ Brush *eraser = p->eraser;
+ BrushGpencilSettings *gp_settings = NULL;
+
+ if (brush->gpencil_tool == GPAINT_TOOL_ERASE) {
+ gp_settings = brush->gpencil_settings;
+ }
+ else if ((eraser != NULL) & (eraser->gpencil_tool == GPAINT_TOOL_ERASE)) {
+ gp_settings = eraser->gpencil_settings;
+ }
+
+ if ((gp_settings != NULL) && (p->sa->spacetype == SPACE_VIEW3D) &&
+ (gp_settings->flag & GP_BRUSH_OCCLUDE_ERASER)) {
+ RegionView3D *rv3d = p->ar->regiondata;
+ bGPDlayer *gpl = p->gpl;
+
+ const int mval_i[2] = {x, y};
+ float mval_3d[3];
+ float fpt[3];
+
+ float diff_mat[4][4];
+ /* calculate difference matrix if parent object */
+ ED_gpencil_parent_location(p->depsgraph, obact, p->gpd, gpl, diff_mat);
+
+ if (ED_view3d_autodist_simple(p->ar, mval_i, mval_3d, 0, NULL)) {
+ const float depth_mval = view3d_point_depth(rv3d, mval_3d);
+
+ mul_v3_m4v3(fpt, diff_mat, &pt->x);
+ const float depth_pt = view3d_point_depth(rv3d, fpt);
+
+ if (depth_pt > depth_mval) {
+ return true;
+ }
+ }
+ }
+ return false;
}
/* apply a falloff effect to brush strength, based on distance */
-static float gp_stroke_eraser_calc_influence(tGPsdata *p, const float mval[2], const int radius, const int co[2])
+static float gp_stroke_eraser_calc_influence(tGPsdata *p,
+ const float mval[2],
+ const int radius,
+ const int co[2])
{
- Brush *brush = p->brush;
- /* Linear Falloff... */
- int mval_i[2];
- round_v2i_v2fl(mval_i, mval);
- float distance = (float)len_v2v2_int(mval_i, co);
- float fac;
-
- CLAMP(distance, 0.0f, (float)radius);
- fac = 1.0f - (distance / (float)radius);
-
- /* apply strength factor */
- fac *= brush->gpencil_settings->draw_strength;
-
- /* Control this further using pen pressure */
- if (brush->gpencil_settings->flag & GP_BRUSH_USE_PRESSURE) {
- fac *= p->pressure;
- }
- /* Return influence factor computed here */
- return fac;
+ Brush *brush = p->brush;
+ /* Linear Falloff... */
+ int mval_i[2];
+ round_v2i_v2fl(mval_i, mval);
+ float distance = (float)len_v2v2_int(mval_i, co);
+ float fac;
+
+ CLAMP(distance, 0.0f, (float)radius);
+ fac = 1.0f - (distance / (float)radius);
+
+ /* apply strength factor */
+ fac *= brush->gpencil_settings->draw_strength;
+
+ /* Control this further using pen pressure */
+ if (brush->gpencil_settings->flag & GP_BRUSH_USE_PRESSURE) {
+ fac *= p->pressure;
+ }
+ /* Return influence factor computed here */
+ return fac;
}
/* helper to free a stroke */
static void gp_free_stroke(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps)
{
- if (gps->points) {
- MEM_freeN(gps->points);
- }
-
- if (gps->dvert) {
- BKE_gpencil_free_stroke_weights(gps);
- MEM_freeN(gps->dvert);
- }
-
- if (gps->triangles)
- MEM_freeN(gps->triangles);
- BLI_freelinkN(&gpf->strokes, gps);
- gp_update_cache(gpd);
+ if (gps->points) {
+ MEM_freeN(gps->points);
+ }
+
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
+
+ if (gps->triangles)
+ MEM_freeN(gps->triangles);
+ BLI_freelinkN(&gpf->strokes, gps);
+ gp_update_cache(gpd);
}
/**
@@ -1367,322 +1375,324 @@ static void gp_free_stroke(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps)
*/
static void gp_stroke_soft_refine(bGPDstroke *gps)
{
- bGPDspoint *pt = NULL;
- bGPDspoint *pt2 = NULL;
- int i;
-
- /* check if enough points*/
- if (gps->totpoints < 3) {
- return;
- }
-
- /* loop all points to untag any point that next is not tagged */
- pt = gps->points;
- for (i = 1; i < gps->totpoints - 1; i++, pt++) {
- if (pt->flag & GP_SPOINT_TAG) {
- pt2 = &gps->points[i + 1];
- if ((pt2->flag & GP_SPOINT_TAG) == 0) {
- pt->flag &= ~GP_SPOINT_TAG;
- }
- }
- }
-
- /* loop reverse all points to untag any point that previous is not tagged */
- pt = &gps->points[gps->totpoints - 1];
- for (i = gps->totpoints - 1; i > 0; i--, pt--) {
- if (pt->flag & GP_SPOINT_TAG) {
- pt2 = &gps->points[i - 1];
- if ((pt2->flag & GP_SPOINT_TAG) == 0) {
- pt->flag &= ~GP_SPOINT_TAG;
- }
- }
- }
+ bGPDspoint *pt = NULL;
+ bGPDspoint *pt2 = NULL;
+ int i;
+
+ /* check if enough points*/
+ if (gps->totpoints < 3) {
+ return;
+ }
+
+ /* loop all points to untag any point that next is not tagged */
+ pt = gps->points;
+ for (i = 1; i < gps->totpoints - 1; i++, pt++) {
+ if (pt->flag & GP_SPOINT_TAG) {
+ pt2 = &gps->points[i + 1];
+ if ((pt2->flag & GP_SPOINT_TAG) == 0) {
+ pt->flag &= ~GP_SPOINT_TAG;
+ }
+ }
+ }
+
+ /* loop reverse all points to untag any point that previous is not tagged */
+ pt = &gps->points[gps->totpoints - 1];
+ for (i = gps->totpoints - 1; i > 0; i--, pt--) {
+ if (pt->flag & GP_SPOINT_TAG) {
+ pt2 = &gps->points[i - 1];
+ if ((pt2->flag & GP_SPOINT_TAG) == 0) {
+ pt->flag &= ~GP_SPOINT_TAG;
+ }
+ }
+ }
}
/* 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)
+ 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);
- }
- else if (gps->totpoints == 1) {
- /* 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_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])) {
- /* only check if point is inside */
- if (len_v2v2_int(mval_i, pc1) <= radius) {
- /* free stroke */
- gp_free_stroke(p->gpd, gpf, gps);
- }
- }
- }
- }
- else if ((p->flags & GP_PAINTFLAG_STROKE_ERASER) || (eraser->gpencil_settings->eraser_mode == GP_BRUSH_ERASER_STROKE)) {
- for (i = 0; (i + 1) < gps->totpoints; i++) {
-
- /* only process if it hasn't been masked out... */
- if ((p->flags & GP_PAINTFLAG_SELECTMASK) && !(gps->points->flag & GP_SPOINT_SELECT))
- continue;
-
- /* get points to work with */
- pt1 = gps->points + i;
- bGPDspoint npt;
- gp_point_to_parent_space(pt1, diff_mat, &npt);
- gp_point_to_xy(&p->gsc, gps, &npt, &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])) {
- /* only check if point is inside */
- if (len_v2v2_int(mval_i, pc1) <= radius) {
- /* free stroke */
- gp_free_stroke(p->gpd, gpf, gps);
- return;
- }
- }
- }
- }
- else {
- /* Pressure threshold at which stroke should be culled */
- const float cull_thresh = 0.005f;
-
- /* Amount to decrease the pressure of each point with each stroke */
- const float strength = 0.1f;
-
- /* Perform culling? */
- bool do_cull = false;
-
- /* Clear Tags
- *
- * Note: It's better this way, as we are sure that
- * we don't miss anything, though things will be
- * slightly slower as a result
- */
- for (i = 0; i < gps->totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
- pt->flag &= ~GP_SPOINT_TAG;
- }
-
- /* First Pass: Loop over the points in the stroke
- * 1) Thin out parts of the stroke under the brush
- * 2) Tag "too thin" parts for removal (in second pass)
- */
- for (i = 0; (i + 1) < gps->totpoints; i++) {
- /* get points to work with */
- pt0 = i > 0 ? gps->points + i - 1 : NULL;
- pt1 = gps->points + i;
- pt2 = gps->points + i + 1;
-
- /* only process if it hasn't been masked out... */
- if ((p->flags & GP_PAINTFLAG_SELECTMASK) && !(gps->points->flag & GP_SPOINT_SELECT))
- continue;
-
- bGPDspoint npt;
- if (pt0) {
- gp_point_to_parent_space(pt0, diff_mat, &npt);
- gp_point_to_xy(&p->gsc, gps, &npt, &pc0[0], &pc0[1]);
- }
- else {
- /* avoid null values */
- copy_v2_v2_int(pc0, pc1);
- }
-
- gp_point_to_parent_space(pt1, 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_xy(&p->gsc, gps, &npt, &pc2[0], &pc2[1]);
-
- /* Check that point segment of the boundbox of the eraser stroke */
- if (((!ELEM(V2D_IS_CLIPPED, pc0[0], pc0[1])) && BLI_rcti_isect_pt(rect, pc0[0], pc0[1])) ||
- ((!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
- * 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_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))
- {
- /* Point is affected: */
- /* Adjust thickness
- * - Influence of eraser falls off with distance from the middle of the eraser
- * - Second point gets less influence, as it might get hit again in the next segment
- */
-
- /* Adjust strength if the eraser is soft */
- if (eraser->gpencil_settings->eraser_mode == GP_BRUSH_ERASER_SOFT) {
- float f_strength = eraser->gpencil_settings->era_strength_f / 100.0f;
- float f_thickness = eraser->gpencil_settings->era_thickness_f / 100.0f;
- float influence = 0.0f;
-
- if (pt0) {
- influence = gp_stroke_eraser_calc_influence(p, mval, radius, pc0);
- pt0->strength -= influence * strength * f_strength * 0.5f;
- CLAMP_MIN(pt0->strength, 0.0f);
- pt0->pressure -= influence * strength * f_thickness * 0.5f;
- }
-
- influence = gp_stroke_eraser_calc_influence(p, mval, radius, pc1);
- pt1->strength -= influence * strength * f_strength;
- CLAMP_MIN(pt1->strength, 0.0f);
- pt1->pressure -= influence * strength * f_thickness;
-
- influence = gp_stroke_eraser_calc_influence(p, mval, radius, pc2);
- pt2->strength -= influence * strength * f_strength * 0.5f;
- CLAMP_MIN(pt2->strength, 0.0f);
- pt2->pressure -= influence * strength * f_thickness * 0.5f;
-
- /* if invisible, delete point */
- if ((pt0) &&
- ((pt0->strength <= GPENCIL_ALPHA_OPACITY_THRESH) ||
- (pt0->pressure < cull_thresh)))
- {
- pt0->flag |= GP_SPOINT_TAG;
- do_cull = true;
- }
- if ((pt1->strength <= GPENCIL_ALPHA_OPACITY_THRESH) || (pt1->pressure < cull_thresh)) {
- pt1->flag |= GP_SPOINT_TAG;
- do_cull = true;
- }
- if ((pt2->strength <= GPENCIL_ALPHA_OPACITY_THRESH) || (pt2->pressure < cull_thresh)) {
- pt2->flag |= GP_SPOINT_TAG;
- do_cull = true;
- }
- }
- else {
- pt1->pressure -= gp_stroke_eraser_calc_influence(p, mval, radius, pc1) * strength;
- pt2->pressure -= gp_stroke_eraser_calc_influence(p, mval, radius, pc2) * strength * 0.5f;
- }
-
- /* 2) Tag any point with overly low influence for removal in the next pass */
- if ((pt1->pressure < cull_thresh) || (p->flags & GP_PAINTFLAG_HARD_ERASER) ||
- (eraser->gpencil_settings->eraser_mode == GP_BRUSH_ERASER_HARD))
- {
- pt1->flag |= GP_SPOINT_TAG;
- do_cull = true;
- }
- if ((pt2->pressure < cull_thresh) || (p->flags & GP_PAINTFLAG_HARD_ERASER) ||
- (eraser->gpencil_settings->eraser_mode == GP_BRUSH_ERASER_HARD))
- {
- pt2->flag |= GP_SPOINT_TAG;
- do_cull = true;
- }
- }
- }
- }
- }
-
- /* Second Pass: Remove any points that are tagged */
- if (do_cull) {
- /* if soft eraser, must analyze points to be sure the stroke ends
- * don't get rounded */
- if (eraser->gpencil_settings->eraser_mode == GP_BRUSH_ERASER_SOFT) {
- gp_stroke_soft_refine(gps);
- }
-
- gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG, false, 0);
- }
- gp_update_cache(p->gpd);
- }
+ 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);
+ }
+ else if (gps->totpoints == 1) {
+ /* 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_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])) {
+ /* only check if point is inside */
+ if (len_v2v2_int(mval_i, pc1) <= radius) {
+ /* free stroke */
+ gp_free_stroke(p->gpd, gpf, gps);
+ }
+ }
+ }
+ }
+ else if ((p->flags & GP_PAINTFLAG_STROKE_ERASER) ||
+ (eraser->gpencil_settings->eraser_mode == GP_BRUSH_ERASER_STROKE)) {
+ for (i = 0; (i + 1) < gps->totpoints; i++) {
+
+ /* only process if it hasn't been masked out... */
+ if ((p->flags & GP_PAINTFLAG_SELECTMASK) && !(gps->points->flag & GP_SPOINT_SELECT))
+ continue;
+
+ /* get points to work with */
+ pt1 = gps->points + i;
+ bGPDspoint npt;
+ gp_point_to_parent_space(pt1, diff_mat, &npt);
+ gp_point_to_xy(&p->gsc, gps, &npt, &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])) {
+ /* only check if point is inside */
+ if (len_v2v2_int(mval_i, pc1) <= radius) {
+ /* free stroke */
+ gp_free_stroke(p->gpd, gpf, gps);
+ return;
+ }
+ }
+ }
+ }
+ else {
+ /* Pressure threshold at which stroke should be culled */
+ const float cull_thresh = 0.005f;
+
+ /* Amount to decrease the pressure of each point with each stroke */
+ const float strength = 0.1f;
+
+ /* Perform culling? */
+ bool do_cull = false;
+
+ /* Clear Tags
+ *
+ * Note: It's better this way, as we are sure that
+ * we don't miss anything, though things will be
+ * slightly slower as a result
+ */
+ for (i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ pt->flag &= ~GP_SPOINT_TAG;
+ }
+
+ /* First Pass: Loop over the points in the stroke
+ * 1) Thin out parts of the stroke under the brush
+ * 2) Tag "too thin" parts for removal (in second pass)
+ */
+ for (i = 0; (i + 1) < gps->totpoints; i++) {
+ /* get points to work with */
+ pt0 = i > 0 ? gps->points + i - 1 : NULL;
+ pt1 = gps->points + i;
+ pt2 = gps->points + i + 1;
+
+ /* only process if it hasn't been masked out... */
+ if ((p->flags & GP_PAINTFLAG_SELECTMASK) && !(gps->points->flag & GP_SPOINT_SELECT))
+ continue;
+
+ bGPDspoint npt;
+ if (pt0) {
+ gp_point_to_parent_space(pt0, diff_mat, &npt);
+ gp_point_to_xy(&p->gsc, gps, &npt, &pc0[0], &pc0[1]);
+ }
+ else {
+ /* avoid null values */
+ copy_v2_v2_int(pc0, pc1);
+ }
+
+ gp_point_to_parent_space(pt1, 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_xy(&p->gsc, gps, &npt, &pc2[0], &pc2[1]);
+
+ /* Check that point segment of the boundbox of the eraser stroke */
+ if (((!ELEM(V2D_IS_CLIPPED, pc0[0], pc0[1])) && BLI_rcti_isect_pt(rect, pc0[0], pc0[1])) ||
+ ((!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
+ * 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_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)) {
+ /* Point is affected: */
+ /* Adjust thickness
+ * - Influence of eraser falls off with distance from the middle of the eraser
+ * - Second point gets less influence, as it might get hit again in the next segment
+ */
+
+ /* Adjust strength if the eraser is soft */
+ if (eraser->gpencil_settings->eraser_mode == GP_BRUSH_ERASER_SOFT) {
+ float f_strength = eraser->gpencil_settings->era_strength_f / 100.0f;
+ float f_thickness = eraser->gpencil_settings->era_thickness_f / 100.0f;
+ float influence = 0.0f;
+
+ if (pt0) {
+ influence = gp_stroke_eraser_calc_influence(p, mval, radius, pc0);
+ pt0->strength -= influence * strength * f_strength * 0.5f;
+ CLAMP_MIN(pt0->strength, 0.0f);
+ pt0->pressure -= influence * strength * f_thickness * 0.5f;
+ }
+
+ influence = gp_stroke_eraser_calc_influence(p, mval, radius, pc1);
+ pt1->strength -= influence * strength * f_strength;
+ CLAMP_MIN(pt1->strength, 0.0f);
+ pt1->pressure -= influence * strength * f_thickness;
+
+ influence = gp_stroke_eraser_calc_influence(p, mval, radius, pc2);
+ pt2->strength -= influence * strength * f_strength * 0.5f;
+ CLAMP_MIN(pt2->strength, 0.0f);
+ pt2->pressure -= influence * strength * f_thickness * 0.5f;
+
+ /* if invisible, delete point */
+ if ((pt0) && ((pt0->strength <= GPENCIL_ALPHA_OPACITY_THRESH) ||
+ (pt0->pressure < cull_thresh))) {
+ pt0->flag |= GP_SPOINT_TAG;
+ do_cull = true;
+ }
+ if ((pt1->strength <= GPENCIL_ALPHA_OPACITY_THRESH) ||
+ (pt1->pressure < cull_thresh)) {
+ pt1->flag |= GP_SPOINT_TAG;
+ do_cull = true;
+ }
+ if ((pt2->strength <= GPENCIL_ALPHA_OPACITY_THRESH) ||
+ (pt2->pressure < cull_thresh)) {
+ pt2->flag |= GP_SPOINT_TAG;
+ do_cull = true;
+ }
+ }
+ else {
+ pt1->pressure -= gp_stroke_eraser_calc_influence(p, mval, radius, pc1) * strength;
+ pt2->pressure -= gp_stroke_eraser_calc_influence(p, mval, radius, pc2) * strength *
+ 0.5f;
+ }
+
+ /* 2) Tag any point with overly low influence for removal in the next pass */
+ if ((pt1->pressure < cull_thresh) || (p->flags & GP_PAINTFLAG_HARD_ERASER) ||
+ (eraser->gpencil_settings->eraser_mode == GP_BRUSH_ERASER_HARD)) {
+ pt1->flag |= GP_SPOINT_TAG;
+ do_cull = true;
+ }
+ if ((pt2->pressure < cull_thresh) || (p->flags & GP_PAINTFLAG_HARD_ERASER) ||
+ (eraser->gpencil_settings->eraser_mode == GP_BRUSH_ERASER_HARD)) {
+ pt2->flag |= GP_SPOINT_TAG;
+ do_cull = true;
+ }
+ }
+ }
+ }
+ }
+
+ /* Second Pass: Remove any points that are tagged */
+ if (do_cull) {
+ /* if soft eraser, must analyze points to be sure the stroke ends
+ * don't get rounded */
+ if (eraser->gpencil_settings->eraser_mode == GP_BRUSH_ERASER_SOFT) {
+ gp_stroke_soft_refine(gps);
+ }
+
+ gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG, false, 0);
+ }
+ gp_update_cache(p->gpd);
+ }
}
/* 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;
- bool use_pressure = false;
- float press = 1.0f;
- BrushGpencilSettings *gp_settings = NULL;
-
- /* detect if use pressure in eraser */
- if (brush->gpencil_tool == GPAINT_TOOL_ERASE) {
- use_pressure = (bool)(brush->gpencil_settings->flag & GP_BRUSH_USE_PRESSURE);
- gp_settings = brush->gpencil_settings;
- }
- else if ((eraser != NULL) & (eraser->gpencil_tool == GPAINT_TOOL_ERASE)) {
- use_pressure = (bool)(eraser->gpencil_settings->flag & GP_BRUSH_USE_PRESSURE);
- gp_settings = eraser->gpencil_settings;
- }
- if (use_pressure) {
- press = p->pressure;
- CLAMP(press, 0.01f, 1.0f);
- }
- /* rect is rectangle of eraser */
- const int calc_radius = (int)p->radius * press;
- rect.xmin = p->mval[0] - calc_radius;
- rect.ymin = p->mval[1] - calc_radius;
- rect.xmax = p->mval[0] + calc_radius;
- rect.ymax = p->mval[1] + calc_radius;
-
- if (p->sa->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);
- }
- }
-
- /* loop over all layers too, since while it's easy to restrict editing to
- * 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) {
- bGPDframe *gpf = gpl->actframe;
-
- /* only affect layer if it's editable (and visible) */
- if (gpencil_layer_is_editable(gpl) == false) {
- continue;
- }
- else if (gpf == NULL) {
- continue;
- }
-
- /* loop over strokes, checking segments for intersections */
- for (gps = gpf->strokes.first; gps; gps = gpn) {
- gpn = gps->next;
- /* check if the color is editable */
- if (ED_gpencil_stroke_color_use(p->ob, gpl, gps) == false) {
- 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);
- }
- }
- }
+ bGPDlayer *gpl;
+ bGPDstroke *gps, *gpn;
+ rcti rect;
+ Brush *brush = p->brush;
+ Brush *eraser = p->eraser;
+ bool use_pressure = false;
+ float press = 1.0f;
+ BrushGpencilSettings *gp_settings = NULL;
+
+ /* detect if use pressure in eraser */
+ if (brush->gpencil_tool == GPAINT_TOOL_ERASE) {
+ use_pressure = (bool)(brush->gpencil_settings->flag & GP_BRUSH_USE_PRESSURE);
+ gp_settings = brush->gpencil_settings;
+ }
+ else if ((eraser != NULL) & (eraser->gpencil_tool == GPAINT_TOOL_ERASE)) {
+ use_pressure = (bool)(eraser->gpencil_settings->flag & GP_BRUSH_USE_PRESSURE);
+ gp_settings = eraser->gpencil_settings;
+ }
+ if (use_pressure) {
+ press = p->pressure;
+ CLAMP(press, 0.01f, 1.0f);
+ }
+ /* rect is rectangle of eraser */
+ const int calc_radius = (int)p->radius * press;
+ rect.xmin = p->mval[0] - calc_radius;
+ rect.ymin = p->mval[1] - calc_radius;
+ rect.xmax = p->mval[0] + calc_radius;
+ rect.ymax = p->mval[1] + calc_radius;
+
+ if (p->sa->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);
+ }
+ }
+
+ /* loop over all layers too, since while it's easy to restrict editing to
+ * 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) {
+ bGPDframe *gpf = gpl->actframe;
+
+ /* only affect layer if it's editable (and visible) */
+ if (gpencil_layer_is_editable(gpl) == false) {
+ continue;
+ }
+ else if (gpf == NULL) {
+ continue;
+ }
+
+ /* loop over strokes, checking segments for intersections */
+ for (gps = gpf->strokes.first; gps; gps = gpn) {
+ gpn = gps->next;
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(p->ob, gpl, gps) == false) {
+ 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);
+ }
+ }
+ }
}
/* ******************************************* */
@@ -1691,563 +1701,558 @@ static void gp_stroke_doeraser(tGPsdata *p)
/* clear the session buffers (call this before AND after a paint operation) */
static void gp_session_validatebuffer(tGPsdata *p)
{
- bGPdata *gpd = p->gpd;
- Brush *brush = p->brush;
-
- /* clear memory of buffer (or allocate it if starting a new session) */
- if (gpd->runtime.sbuffer) {
- /* printf("\t\tGP - reset sbuffer\n"); */
- memset(gpd->runtime.sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX);
- }
- else {
- /* printf("\t\tGP - allocate sbuffer\n"); */
- gpd->runtime.sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer");
- }
-
- /* reset indices */
- gpd->runtime.sbuffer_size = 0;
-
- /* reset flags */
- gpd->runtime.sbuffer_sflag = 0;
-
- /* reset region */
- gpd->runtime.ar = NULL;
-
- /* reset inittime */
- p->inittime = 0.0;
-
- /* reset lazy */
- if (brush) {
- brush->gpencil_settings->flag &= ~GP_BRUSH_STABILIZE_MOUSE_TEMP;
- }
+ bGPdata *gpd = p->gpd;
+ Brush *brush = p->brush;
+
+ /* clear memory of buffer (or allocate it if starting a new session) */
+ if (gpd->runtime.sbuffer) {
+ /* printf("\t\tGP - reset sbuffer\n"); */
+ memset(gpd->runtime.sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX);
+ }
+ else {
+ /* printf("\t\tGP - allocate sbuffer\n"); */
+ gpd->runtime.sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX,
+ "gp_session_strokebuffer");
+ }
+
+ /* reset indices */
+ gpd->runtime.sbuffer_size = 0;
+
+ /* reset flags */
+ gpd->runtime.sbuffer_sflag = 0;
+
+ /* reset region */
+ gpd->runtime.ar = NULL;
+
+ /* reset inittime */
+ p->inittime = 0.0;
+
+ /* reset lazy */
+ if (brush) {
+ brush->gpencil_settings->flag &= ~GP_BRUSH_STABILIZE_MOUSE_TEMP;
+ }
}
/* helper to get default eraser and create one if no eraser brush */
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;
- for (Brush *brush = bmain->brushes.first; brush; brush = brush->id.next) {
- 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) {
- brush_dft = brush;
- }
- /* found default */
- if (brush->gpencil_settings->flag & GP_BRUSH_DEFAULT_ERASER) {
- return brush;
- }
- }
- }
- /* if no default, but exist eraser brush, return this and set as default */
- if (brush_dft) {
- brush_dft->gpencil_settings->flag |= GP_BRUSH_DEFAULT_ERASER;
- return brush_dft;
- }
- /* create a new soft eraser brush */
- else {
- brush_dft = BKE_brush_add_gpencil(bmain, ts, "Soft Eraser");
- brush_dft->size = 30.0f;
- brush_dft->gpencil_settings->flag |= (GP_BRUSH_ENABLE_CURSOR | 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);
-
- return brush_dft;
- }
+ Brush *brush_dft = NULL;
+ Paint *paint = &ts->gp_paint->paint;
+ Brush *brush_old = paint->brush;
+ for (Brush *brush = bmain->brushes.first; brush; brush = brush->id.next) {
+ 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) {
+ brush_dft = brush;
+ }
+ /* found default */
+ if (brush->gpencil_settings->flag & GP_BRUSH_DEFAULT_ERASER) {
+ return brush;
+ }
+ }
+ }
+ /* if no default, but exist eraser brush, return this and set as default */
+ if (brush_dft) {
+ brush_dft->gpencil_settings->flag |= GP_BRUSH_DEFAULT_ERASER;
+ return brush_dft;
+ }
+ /* create a new soft eraser brush */
+ else {
+ brush_dft = BKE_brush_add_gpencil(bmain, ts, "Soft Eraser");
+ brush_dft->size = 30.0f;
+ brush_dft->gpencil_settings->flag |= (GP_BRUSH_ENABLE_CURSOR | 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);
+
+ return brush_dft;
+ }
}
/* helper to set default eraser and disable others */
static void gp_set_default_eraser(Main *bmain, Brush *brush_dft)
{
- if (brush_dft == NULL) {
- return;
- }
-
- for (Brush *brush = bmain->brushes.first; brush; brush = brush->id.next) {
- if ((brush->gpencil_settings) && (brush->gpencil_tool == GPAINT_TOOL_ERASE)) {
- if (brush == brush_dft) {
- brush->gpencil_settings->flag |= GP_BRUSH_DEFAULT_ERASER;
- }
- else if (brush->gpencil_settings->flag & GP_BRUSH_DEFAULT_ERASER) {
- brush->gpencil_settings->flag &= ~GP_BRUSH_DEFAULT_ERASER;
- }
- }
- }
+ if (brush_dft == NULL) {
+ return;
+ }
+
+ for (Brush *brush = bmain->brushes.first; brush; brush = brush->id.next) {
+ if ((brush->gpencil_settings) && (brush->gpencil_tool == GPAINT_TOOL_ERASE)) {
+ if (brush == brush_dft) {
+ brush->gpencil_settings->flag |= GP_BRUSH_DEFAULT_ERASER;
+ }
+ else if (brush->gpencil_settings->flag & GP_BRUSH_DEFAULT_ERASER) {
+ brush->gpencil_settings->flag &= ~GP_BRUSH_DEFAULT_ERASER;
+ }
+ }
+ }
}
/* initialize a drawing brush */
static void gp_init_drawing_brush(bContext *C, tGPsdata *p)
{
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
-
- Paint *paint = &ts->gp_paint->paint;
- bool changed = false;
- /* if not exist, create a new one */
- if (paint->brush == NULL) {
- /* create new brushes */
- BKE_brush_gpencil_presets(C);
- changed = true;
- }
- /* be sure curves are initializated */
- curvemapping_initialize(paint->brush->gpencil_settings->curve_sensitivity);
- curvemapping_initialize(paint->brush->gpencil_settings->curve_strength);
- curvemapping_initialize(paint->brush->gpencil_settings->curve_jitter);
-
- /* assign to temp tGPsdata */
- p->brush = paint->brush;
- if (paint->brush->gpencil_tool != GPAINT_TOOL_ERASE) {
- p->eraser = gp_get_default_eraser(p->bmain, ts);
- }
- else {
- p->eraser = paint->brush;
- }
- /* set new eraser as default */
- gp_set_default_eraser(p->bmain, p->eraser);
-
- /* 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.
- */
- if (changed) {
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- }
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+
+ Paint *paint = &ts->gp_paint->paint;
+ bool changed = false;
+ /* if not exist, create a new one */
+ if (paint->brush == NULL) {
+ /* create new brushes */
+ BKE_brush_gpencil_presets(C);
+ changed = true;
+ }
+ /* be sure curves are initializated */
+ curvemapping_initialize(paint->brush->gpencil_settings->curve_sensitivity);
+ curvemapping_initialize(paint->brush->gpencil_settings->curve_strength);
+ curvemapping_initialize(paint->brush->gpencil_settings->curve_jitter);
+
+ /* assign to temp tGPsdata */
+ p->brush = paint->brush;
+ if (paint->brush->gpencil_tool != GPAINT_TOOL_ERASE) {
+ p->eraser = gp_get_default_eraser(p->bmain, ts);
+ }
+ else {
+ p->eraser = paint->brush;
+ }
+ /* set new eraser as default */
+ gp_set_default_eraser(p->bmain, p->eraser);
+
+ /* 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.
+ */
+ if (changed) {
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
-
/* initialize a paint brush and a default color if not exist */
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;
- }
+ 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;
+ }
}
/* (re)init new painting data */
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);
- ToolSettings *ts = CTX_data_tool_settings(C);
- Object *obact = CTX_data_active_object(C);
-
- /* make sure the active view (at the starting time) is a 3d-view */
- if (curarea == NULL) {
- p->status = GP_STATUS_ERROR;
- if (G.debug & G_DEBUG)
- printf("Error: No active view for painting\n");
- return 0;
- }
-
- /* pass on current scene and window */
- p->C = C;
- p->bmain = CTX_data_main(C);
- p->scene = CTX_data_scene(C);
- p->depsgraph = CTX_data_depsgraph(C);
- p->win = CTX_wm_window(C);
- p->disable_fill = RNA_boolean_get(op->ptr, "disable_fill");
-
- unit_m4(p->imat);
- unit_m4(p->mat);
-
- 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->align_flag = &ts->gpencil_v3d_align;
-
- if (ar->regiondata == NULL) {
- p->status = GP_STATUS_ERROR;
- if (G.debug & G_DEBUG)
- printf("Error: 3D-View active region doesn't have any region data, so cannot be drawable\n");
- return 0;
- }
-
- if ((!obact) || (obact->type != OB_GPENCIL)) {
- View3D *v3d = p->sa->spacedata.first;
- /* if active object doesn't exist or isn't a GP Object, create one */
- const float *cur = p->scene->cursor.location;
-
- ushort local_view_bits = 0;
- if (v3d->localvd) {
- local_view_bits = v3d->local_view_uuid;
- }
- /* create new default object */
- obact = ED_gpencil_add_object(C, p->scene, cur, local_view_bits);
- }
- /* assign object after all checks to be sure we have one active */
- p->ob = obact;
-
- break;
- }
-
- /* unsupported views */
- default:
- {
- p->status = GP_STATUS_ERROR;
- if (G.debug & G_DEBUG)
- printf("Error: Active view not appropriate for Grease Pencil drawing\n");
- return 0;
- }
- }
-
- /* get gp-data */
- gpd_ptr = ED_gpencil_data_get_pointers(C, &p->ownerPtr);
- if ((gpd_ptr == NULL) || ED_gpencil_data_owner_is_annotation(&p->ownerPtr)) {
- p->status = GP_STATUS_ERROR;
- if (G.debug & G_DEBUG)
- printf("Error: Current context doesn't allow for any Grease Pencil data\n");
- return 0;
- }
- else {
- /* if no existing GPencil block exists, add one */
- if (*gpd_ptr == NULL)
- *gpd_ptr = BKE_gpencil_data_addnew(bmain, "GPencil");
- p->gpd = *gpd_ptr;
- }
-
- /* clear out buffer (stored in gp-data), in case something contaminated it */
- gp_session_validatebuffer(p);
-
- /* set brush and create a new one if null */
- 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);
-
- /* 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);
- }
- }
-
- /* lock axis (in some modes, disable) */
- if (((*p->align_flag & GP_PROJECT_DEPTH_VIEW) == 0) &&
- ((*p->align_flag & GP_PROJECT_DEPTH_STROKE) == 0))
- {
- p->lock_axis = ts->gp_sculpt.lock_axis;
- }
- else {
- p->lock_axis = 0;
- }
-
- return 1;
+ Main *bmain = CTX_data_main(C);
+ bGPdata **gpd_ptr = NULL;
+ ScrArea *curarea = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *obact = CTX_data_active_object(C);
+
+ /* make sure the active view (at the starting time) is a 3d-view */
+ if (curarea == NULL) {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf("Error: No active view for painting\n");
+ return 0;
+ }
+
+ /* pass on current scene and window */
+ p->C = C;
+ p->bmain = CTX_data_main(C);
+ p->scene = CTX_data_scene(C);
+ p->depsgraph = CTX_data_depsgraph(C);
+ p->win = CTX_wm_window(C);
+ p->disable_fill = RNA_boolean_get(op->ptr, "disable_fill");
+
+ unit_m4(p->imat);
+ unit_m4(p->mat);
+
+ 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->align_flag = &ts->gpencil_v3d_align;
+
+ if (ar->regiondata == NULL) {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf(
+ "Error: 3D-View active region doesn't have any region data, so cannot be "
+ "drawable\n");
+ return 0;
+ }
+
+ if ((!obact) || (obact->type != OB_GPENCIL)) {
+ View3D *v3d = p->sa->spacedata.first;
+ /* if active object doesn't exist or isn't a GP Object, create one */
+ const float *cur = p->scene->cursor.location;
+
+ ushort local_view_bits = 0;
+ if (v3d->localvd) {
+ local_view_bits = v3d->local_view_uuid;
+ }
+ /* create new default object */
+ obact = ED_gpencil_add_object(C, p->scene, cur, local_view_bits);
+ }
+ /* assign object after all checks to be sure we have one active */
+ p->ob = obact;
+
+ break;
+ }
+
+ /* unsupported views */
+ default: {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf("Error: Active view not appropriate for Grease Pencil drawing\n");
+ return 0;
+ }
+ }
+
+ /* get gp-data */
+ gpd_ptr = ED_gpencil_data_get_pointers(C, &p->ownerPtr);
+ if ((gpd_ptr == NULL) || ED_gpencil_data_owner_is_annotation(&p->ownerPtr)) {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf("Error: Current context doesn't allow for any Grease Pencil data\n");
+ return 0;
+ }
+ else {
+ /* if no existing GPencil block exists, add one */
+ if (*gpd_ptr == NULL)
+ *gpd_ptr = BKE_gpencil_data_addnew(bmain, "GPencil");
+ p->gpd = *gpd_ptr;
+ }
+
+ /* clear out buffer (stored in gp-data), in case something contaminated it */
+ gp_session_validatebuffer(p);
+
+ /* set brush and create a new one if null */
+ 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);
+
+ /* 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);
+ }
+ }
+
+ /* lock axis (in some modes, disable) */
+ if (((*p->align_flag & GP_PROJECT_DEPTH_VIEW) == 0) &&
+ ((*p->align_flag & GP_PROJECT_DEPTH_STROKE) == 0)) {
+ p->lock_axis = ts->gp_sculpt.lock_axis;
+ }
+ else {
+ p->lock_axis = 0;
+ }
+
+ return 1;
}
/* init new painting session */
static tGPsdata *gp_session_initpaint(bContext *C, wmOperator *op)
{
- tGPsdata *p = NULL;
-
- /* Create new context data */
- p = MEM_callocN(sizeof(tGPsdata), "GPencil Drawing Data");
-
- /* Try to initialize context data
- * WARNING: This may not always succeed (e.g. using GP in an annotation-only context)
- */
- if (gp_session_initdata(C, op, p) == 0) {
- /* Invalid state - Exit
- * NOTE: It should be safe to just free the data, since failing context checks should
- * only happen when no data has been allocated.
- */
- MEM_freeN(p);
- return NULL;
- }
-
- /* Random generator, only init once. */
- uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
- rng_seed ^= POINTER_AS_UINT(p);
- p->rng = BLI_rng_new(rng_seed);
-
- /* return context data for running paint operator */
- return p;
+ tGPsdata *p = NULL;
+
+ /* Create new context data */
+ p = MEM_callocN(sizeof(tGPsdata), "GPencil Drawing Data");
+
+ /* Try to initialize context data
+ * WARNING: This may not always succeed (e.g. using GP in an annotation-only context)
+ */
+ if (gp_session_initdata(C, op, p) == 0) {
+ /* Invalid state - Exit
+ * NOTE: It should be safe to just free the data, since failing context checks should
+ * only happen when no data has been allocated.
+ */
+ MEM_freeN(p);
+ return NULL;
+ }
+
+ /* Random generator, only init once. */
+ uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
+ rng_seed ^= POINTER_AS_UINT(p);
+ p->rng = BLI_rng_new(rng_seed);
+
+ /* return context data for running paint operator */
+ return p;
}
/* cleanup after a painting session */
static void gp_session_cleanup(tGPsdata *p)
{
- bGPdata *gpd = (p) ? p->gpd : NULL;
-
- /* error checking */
- if (gpd == NULL)
- return;
-
- /* free stroke buffer */
- if (gpd->runtime.sbuffer) {
- /* printf("\t\tGP - free sbuffer\n"); */
- MEM_SAFE_FREE(gpd->runtime.sbuffer);
- gpd->runtime.sbuffer = NULL;
- }
-
- /* clear flags */
- gpd->runtime.sbuffer_size = 0;
- gpd->runtime.sbuffer_sflag = 0;
- p->inittime = 0.0;
+ bGPdata *gpd = (p) ? p->gpd : NULL;
+
+ /* error checking */
+ if (gpd == NULL)
+ return;
+
+ /* free stroke buffer */
+ if (gpd->runtime.sbuffer) {
+ /* printf("\t\tGP - free sbuffer\n"); */
+ MEM_SAFE_FREE(gpd->runtime.sbuffer);
+ gpd->runtime.sbuffer = NULL;
+ }
+
+ /* clear flags */
+ gpd->runtime.sbuffer_size = 0;
+ gpd->runtime.sbuffer_sflag = 0;
+ p->inittime = 0.0;
}
static void gp_session_free(tGPsdata *p)
{
- if (p->rng != NULL) {
- BLI_rng_free(p->rng);
- }
+ if (p->rng != NULL) {
+ BLI_rng_free(p->rng);
+ }
- MEM_freeN(p);
+ MEM_freeN(p);
}
/* init new stroke */
static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Depsgraph *depsgraph)
{
- Scene *scene = p->scene;
- ToolSettings *ts = scene->toolsettings;
- int cfra_eval = (int)DEG_get_ctime(p->depsgraph);
-
- /* get active layer (or add a new one if non-existent) */
- p->gpl = BKE_gpencil_layer_getactive(p->gpd);
- if (p->gpl == NULL) {
- p->gpl = BKE_gpencil_layer_addnew(p->gpd, DATA_("GP_Layer"), true);
-
- if (p->custom_color[3]) {
- copy_v3_v3(p->gpl->color, p->custom_color);
- }
- }
- if ((paintmode != GP_PAINTMODE_ERASER) &&
- (p->gpl->flag & GP_LAYER_LOCKED))
- {
- p->status = GP_STATUS_ERROR;
- if (G.debug & G_DEBUG)
- printf("Error: Cannot paint on locked layer\n");
- return;
- }
-
- /* get active frame (add a new one if not matching frame) */
- 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) {
- /* Skip if layer not editable */
- if (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_eval, GP_GETFRAME_ADD_COPY);
- has_layer_to_erase = true;
- }
-
- /* 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;
-
- /* Restrict eraser to only affecting selected strokes, if the "selection mask" is on
- * (though this is only available in editmode)
- */
- if (p->gpd->flag & GP_DATA_STROKE_EDITMODE) {
- if (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_SELECT_MASK) {
- p->flags |= GP_PAINTFLAG_SELECTMASK;
- }
- }
-
- if (has_layer_to_erase == false) {
- p->status = GP_STATUS_ERROR;
- return;
- }
- }
- else {
- /* Drawing Modes - Add a new frame if needed on the active layer */
- short add_frame_mode;
-
- if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST)
- add_frame_mode = GP_GETFRAME_ADD_COPY;
- else
- add_frame_mode = GP_GETFRAME_ADD_NEW;
-
- p->gpf = BKE_gpencil_layer_getframe(p->gpl, cfra_eval, add_frame_mode);
-
- if (p->gpf == NULL) {
- p->status = GP_STATUS_ERROR;
- if (G.debug & G_DEBUG)
- printf("Error: No frame created (gpencil_paint_init)\n");
- return;
- }
- else {
- p->gpf->flag |= GP_FRAME_PAINT;
- }
- }
-
- /* set 'eraser' for this stroke if using eraser */
- p->paintmode = paintmode;
- if (p->paintmode == GP_PAINTMODE_ERASER) {
- p->gpd->runtime.sbuffer_sflag |= GP_STROKE_ERASER;
- }
- else {
- /* disable eraser flags - so that we can switch modes during a session */
- p->gpd->runtime.sbuffer_sflag &= ~GP_STROKE_ERASER;
- }
-
- /* 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 */
- p->flags |= GP_PAINTFLAG_FIRSTRUN;
-
- /* 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;
-
- /* 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->subrect = &p->subrect_data;
- }
- }
- }
-
- /* init stroke point space-conversion settings... */
- p->gsc.gpd = p->gpd;
- p->gsc.gpl = p->gpl;
-
- p->gsc.sa = p->sa;
- p->gsc.ar = p->ar;
- p->gsc.v2d = p->v2d;
-
- p->gsc.subrect_data = p->subrect_data;
- p->gsc.subrect = p->subrect;
-
- copy_m4_m4(p->gsc.mat, p->mat);
-
-
- /* check if points will need to be made in view-aligned space */
- if (*p->align_flag & GP_PROJECT_VIEWSPACE) {
- switch (p->sa->spacetype) {
- case SPACE_VIEW3D:
- {
- p->gpd->runtime.sbuffer_sflag |= GP_STROKE_3DSPACE;
- break;
- }
- }
- }
+ Scene *scene = p->scene;
+ ToolSettings *ts = scene->toolsettings;
+ int cfra_eval = (int)DEG_get_ctime(p->depsgraph);
+
+ /* get active layer (or add a new one if non-existent) */
+ p->gpl = BKE_gpencil_layer_getactive(p->gpd);
+ if (p->gpl == NULL) {
+ p->gpl = BKE_gpencil_layer_addnew(p->gpd, DATA_("GP_Layer"), true);
+
+ if (p->custom_color[3]) {
+ copy_v3_v3(p->gpl->color, p->custom_color);
+ }
+ }
+ if ((paintmode != GP_PAINTMODE_ERASER) && (p->gpl->flag & GP_LAYER_LOCKED)) {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf("Error: Cannot paint on locked layer\n");
+ return;
+ }
+
+ /* get active frame (add a new one if not matching frame) */
+ 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) {
+ /* Skip if layer not editable */
+ if (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_eval, GP_GETFRAME_ADD_COPY);
+ has_layer_to_erase = true;
+ }
+
+ /* 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;
+
+ /* Restrict eraser to only affecting selected strokes, if the "selection mask" is on
+ * (though this is only available in editmode)
+ */
+ if (p->gpd->flag & GP_DATA_STROKE_EDITMODE) {
+ if (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_SELECT_MASK) {
+ p->flags |= GP_PAINTFLAG_SELECTMASK;
+ }
+ }
+
+ if (has_layer_to_erase == false) {
+ p->status = GP_STATUS_ERROR;
+ return;
+ }
+ }
+ else {
+ /* Drawing Modes - Add a new frame if needed on the active layer */
+ short add_frame_mode;
+
+ if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST)
+ add_frame_mode = GP_GETFRAME_ADD_COPY;
+ else
+ add_frame_mode = GP_GETFRAME_ADD_NEW;
+
+ p->gpf = BKE_gpencil_layer_getframe(p->gpl, cfra_eval, add_frame_mode);
+
+ if (p->gpf == NULL) {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf("Error: No frame created (gpencil_paint_init)\n");
+ return;
+ }
+ else {
+ p->gpf->flag |= GP_FRAME_PAINT;
+ }
+ }
+
+ /* set 'eraser' for this stroke if using eraser */
+ p->paintmode = paintmode;
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ p->gpd->runtime.sbuffer_sflag |= GP_STROKE_ERASER;
+ }
+ else {
+ /* disable eraser flags - so that we can switch modes during a session */
+ p->gpd->runtime.sbuffer_sflag &= ~GP_STROKE_ERASER;
+ }
+
+ /* 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 */
+ p->flags |= GP_PAINTFLAG_FIRSTRUN;
+
+ /* 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;
+
+ /* 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->subrect = &p->subrect_data;
+ }
+ }
+ }
+
+ /* init stroke point space-conversion settings... */
+ p->gsc.gpd = p->gpd;
+ p->gsc.gpl = p->gpl;
+
+ p->gsc.sa = p->sa;
+ p->gsc.ar = p->ar;
+ p->gsc.v2d = p->v2d;
+
+ p->gsc.subrect_data = p->subrect_data;
+ p->gsc.subrect = p->subrect;
+
+ copy_m4_m4(p->gsc.mat, p->mat);
+
+ /* check if points will need to be made in view-aligned space */
+ if (*p->align_flag & GP_PROJECT_VIEWSPACE) {
+ switch (p->sa->spacetype) {
+ case SPACE_VIEW3D: {
+ p->gpd->runtime.sbuffer_sflag |= GP_STROKE_3DSPACE;
+ break;
+ }
+ }
+ }
}
/* finish off a stroke (clears buffer, but doesn't finish the paint operation) */
static void gp_paint_strokeend(tGPsdata *p)
{
- ToolSettings *ts = p->scene->toolsettings;
- /* for surface sketching, need to set the right OpenGL context stuff so that
- * the conversions will project the values correctly...
- */
- if (gpencil_project_check(p)) {
- View3D *v3d = p->sa->spacedata.first;
-
- /* need to restore the original projection settings before packing up */
- 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);
- }
-
- /* check if doing eraser or not */
- if ((p->gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) {
- /* transfer stroke to frame */
- gp_stroke_newfrombuffer(p);
- }
-
- /* clean up buffer now */
- gp_session_validatebuffer(p);
+ ToolSettings *ts = p->scene->toolsettings;
+ /* for surface sketching, need to set the right OpenGL context stuff so that
+ * the conversions will project the values correctly...
+ */
+ if (gpencil_project_check(p)) {
+ View3D *v3d = p->sa->spacedata.first;
+
+ /* need to restore the original projection settings before packing up */
+ 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);
+ }
+
+ /* check if doing eraser or not */
+ if ((p->gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) {
+ /* transfer stroke to frame */
+ gp_stroke_newfrombuffer(p);
+ }
+
+ /* clean up buffer now */
+ gp_session_validatebuffer(p);
}
/* finish off stroke painting operation */
static void gp_paint_cleanup(tGPsdata *p)
{
- /* p->gpd==NULL happens when stroke failed to initialize,
- * for example when GP is hidden in current space (sergey)
- */
- if (p->gpd) {
- /* finish off a stroke */
- gp_paint_strokeend(p);
- }
-
- /* "unlock" frame */
- if (p->gpf)
- p->gpf->flag &= ~GP_FRAME_PAINT;
+ /* p->gpd==NULL happens when stroke failed to initialize,
+ * for example when GP is hidden in current space (sergey)
+ */
+ if (p->gpd) {
+ /* finish off a stroke */
+ gp_paint_strokeend(p);
+ }
+
+ /* "unlock" frame */
+ if (p->gpf)
+ p->gpf->flag &= ~GP_FRAME_PAINT;
}
/* ------------------------------- */
@@ -2255,265 +2260,271 @@ static void gp_paint_cleanup(tGPsdata *p)
/* Helper callback for drawing the cursor itself */
static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
{
- tGPsdata *p = (tGPsdata *)p_ptr;
+ tGPsdata *p = (tGPsdata *)p_ptr;
- if (p->paintmode == GP_PAINTMODE_ERASER) {
- GPUVertFormat *format = immVertexFormat();
- const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ GPUVertFormat *format = immVertexFormat();
+ const uint shdr_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_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_line_smooth(true);
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- immUniformColor4ub(255, 100, 100, 20);
- imm_draw_circle_fill_2d(shdr_pos, x, y, p->radius, 40);
+ immUniformColor4ub(255, 100, 100, 20);
+ imm_draw_circle_fill_2d(shdr_pos, x, y, p->radius, 40);
- immUnbindProgram();
+ immUnbindProgram();
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
- immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f);
- immUniform1i("colors_len", 0); /* "simple" mode */
- immUniform1f("dash_width", 12.0f);
- immUniform1f("dash_factor", 0.5f);
+ immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f);
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniform1f("dash_width", 12.0f);
+ immUniform1f("dash_factor", 0.5f);
- imm_draw_circle_wire_2d(
- shdr_pos, x, y, p->radius,
- /* XXX Dashed shader gives bad results with sets of small segments currently,
- * temp hack around the issue. :( */
- max_ii(8, p->radius / 2)); /* was fixed 40 */
+ imm_draw_circle_wire_2d(
+ shdr_pos,
+ x,
+ y,
+ p->radius,
+ /* XXX Dashed shader gives bad results with sets of small segments currently,
+ * temp hack around the issue. :( */
+ max_ii(8, p->radius / 2)); /* was fixed 40 */
- immUnbindProgram();
+ immUnbindProgram();
- GPU_blend(false);
- GPU_line_smooth(false);
- }
+ GPU_blend(false);
+ GPU_line_smooth(false);
+ }
}
/* Turn brush cursor in 3D view on/off */
static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short enable)
{
- if (p->erasercursor && !enable) {
- /* clear cursor */
- WM_paint_cursor_end(CTX_wm_manager(C), p->erasercursor);
- p->erasercursor = NULL;
- }
- else if (enable && !p->erasercursor) {
- ED_gpencil_toggle_brush_cursor(p->C, false, NULL);
- /* enable cursor */
- p->erasercursor = WM_paint_cursor_activate(
- CTX_wm_manager(C),
- SPACE_TYPE_ANY, RGN_TYPE_ANY,
- NULL, /* XXX */
- gpencil_draw_eraser, p);
- }
+ if (p->erasercursor && !enable) {
+ /* clear cursor */
+ WM_paint_cursor_end(CTX_wm_manager(C), p->erasercursor);
+ p->erasercursor = NULL;
+ }
+ else if (enable && !p->erasercursor) {
+ ED_gpencil_toggle_brush_cursor(p->C, false, NULL);
+ /* enable cursor */
+ p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C),
+ SPACE_TYPE_ANY,
+ RGN_TYPE_ANY,
+ NULL, /* XXX */
+ gpencil_draw_eraser,
+ p);
+ }
}
/* Check if tablet eraser is being used (when processing events) */
static bool gpencil_is_tablet_eraser_active(const wmEvent *event)
{
- if (event->tablet_data) {
- const wmTabletData *wmtab = event->tablet_data;
- return (wmtab->Active == EVT_TABLET_ERASER);
- }
+ if (event->tablet_data) {
+ const wmTabletData *wmtab = event->tablet_data;
+ return (wmtab->Active == EVT_TABLET_ERASER);
+ }
- return false;
+ return false;
}
/* ------------------------------- */
static void gpencil_draw_exit(bContext *C, wmOperator *op)
{
- tGPsdata *p = op->customdata;
-
- /* don't assume that operator data exists at all */
- if (p) {
- /* check size of buffer before cleanup, to determine if anything happened here */
- if (p->paintmode == GP_PAINTMODE_ERASER) {
- /* turn off radial brush cursor */
- gpencil_draw_toggle_eraser_cursor(C, p, false);
- }
-
- /* always store the new eraser size to be used again next time
- * NOTE: Do this even when not in eraser mode, as eraser may
- * have been toggled at some point.
- */
- if (p->eraser) {
- p->eraser->size = p->radius;
- }
-
- /* restore cursor to indicate end of drawing */
- if (p->sa->spacetype != SPACE_VIEW3D) {
- WM_cursor_modal_restore(CTX_wm_window(C));
- }
- else {
- /* or restore paint if 3D view */
- if ((p) && (p->paintmode == GP_PAINTMODE_ERASER)) {
- WM_cursor_modal_set(p->win, CURSOR_STD);
- }
-
- /* 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);
- }
- }
-
- /* clear undo stack */
- gpencil_undo_finish();
-
- /* cleanup */
- WM_cursor_modal_set(p->win, CURSOR_STD);
-
- gp_paint_cleanup(p);
- gp_session_cleanup(p);
- ED_gpencil_toggle_brush_cursor(C, true, NULL);
-
- /* finally, free the temp data */
- gp_session_free(p);
- p = NULL;
- }
-
- op->customdata = NULL;
+ tGPsdata *p = op->customdata;
+
+ /* don't assume that operator data exists at all */
+ if (p) {
+ /* check size of buffer before cleanup, to determine if anything happened here */
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ /* turn off radial brush cursor */
+ gpencil_draw_toggle_eraser_cursor(C, p, false);
+ }
+
+ /* always store the new eraser size to be used again next time
+ * NOTE: Do this even when not in eraser mode, as eraser may
+ * have been toggled at some point.
+ */
+ if (p->eraser) {
+ p->eraser->size = p->radius;
+ }
+
+ /* restore cursor to indicate end of drawing */
+ if (p->sa->spacetype != SPACE_VIEW3D) {
+ WM_cursor_modal_restore(CTX_wm_window(C));
+ }
+ else {
+ /* or restore paint if 3D view */
+ if ((p) && (p->paintmode == GP_PAINTMODE_ERASER)) {
+ WM_cursor_modal_set(p->win, CURSOR_STD);
+ }
+
+ /* 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);
+ }
+ }
+
+ /* clear undo stack */
+ gpencil_undo_finish();
+
+ /* cleanup */
+ WM_cursor_modal_set(p->win, CURSOR_STD);
+
+ gp_paint_cleanup(p);
+ gp_session_cleanup(p);
+ ED_gpencil_toggle_brush_cursor(C, true, NULL);
+
+ /* finally, free the temp data */
+ gp_session_free(p);
+ p = NULL;
+ }
+
+ op->customdata = NULL;
}
static void gpencil_draw_cancel(bContext *C, wmOperator *op)
{
- /* this is just a wrapper around exit() */
- gpencil_draw_exit(C, op);
+ /* this is just a wrapper around exit() */
+ gpencil_draw_exit(C, op);
}
/* ------------------------------- */
-
static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event)
{
- tGPsdata *p;
- eGPencil_PaintModes paintmode = RNA_enum_get(op->ptr, "mode");
- ToolSettings *ts = CTX_data_tool_settings(C);
- Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
-
- /* if mode is draw and the brush is eraser, cancel */
- if (paintmode != GP_PAINTMODE_ERASER) {
- if ((brush) && (brush->gpencil_tool == GPAINT_TOOL_ERASE)) {
- return 0;
- }
- }
-
- /* check context */
- p = op->customdata = gp_session_initpaint(C, op);
- if ((p == NULL) || (p->status == GP_STATUS_ERROR)) {
- /* something wasn't set correctly in context */
- gpencil_draw_exit(C, op);
- return 0;
- }
-
- /* init painting data */
- gp_paint_initstroke(p, paintmode, CTX_data_depsgraph(C));
- if (p->status == GP_STATUS_ERROR) {
- gpencil_draw_exit(C, op);
- return 0;
- }
-
- if (event != NULL) {
- p->keymodifier = event->keymodifier;
- }
- else {
- p->keymodifier = -1;
- }
-
- p->reports = op->reports;
-
- /* everything is now setup ok */
- return 1;
+ tGPsdata *p;
+ eGPencil_PaintModes paintmode = RNA_enum_get(op->ptr, "mode");
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
+
+ /* if mode is draw and the brush is eraser, cancel */
+ if (paintmode != GP_PAINTMODE_ERASER) {
+ if ((brush) && (brush->gpencil_tool == GPAINT_TOOL_ERASE)) {
+ return 0;
+ }
+ }
+
+ /* check context */
+ p = op->customdata = gp_session_initpaint(C, op);
+ if ((p == NULL) || (p->status == GP_STATUS_ERROR)) {
+ /* something wasn't set correctly in context */
+ gpencil_draw_exit(C, op);
+ return 0;
+ }
+
+ /* init painting data */
+ gp_paint_initstroke(p, paintmode, CTX_data_depsgraph(C));
+ if (p->status == GP_STATUS_ERROR) {
+ gpencil_draw_exit(C, op);
+ return 0;
+ }
+
+ if (event != NULL) {
+ p->keymodifier = event->keymodifier;
+ }
+ else {
+ p->keymodifier = -1;
+ }
+
+ p->reports = op->reports;
+
+ /* everything is now setup ok */
+ return 1;
}
-
/* ------------------------------- */
/* ensure that the correct cursor icon is set */
static void gpencil_draw_cursor_set(tGPsdata *p)
{
- Brush *brush = p->brush;
- if ((p->paintmode == GP_PAINTMODE_ERASER) ||
- (brush->gpencil_tool == GPAINT_TOOL_ERASE))
- {
- WM_cursor_modal_set(p->win, BC_CROSSCURSOR); /* XXX need a better cursor */
- }
- else {
- WM_cursor_modal_set(p->win, CURSOR_NONE);
- }
+ Brush *brush = p->brush;
+ if ((p->paintmode == GP_PAINTMODE_ERASER) || (brush->gpencil_tool == GPAINT_TOOL_ERASE)) {
+ WM_cursor_modal_set(p->win, BC_CROSSCURSOR); /* XXX need a better cursor */
+ }
+ else {
+ WM_cursor_modal_set(p->win, CURSOR_NONE);
+ }
}
/* update UI indicators of status, including cursor and header prints */
static void gpencil_draw_status_indicators(bContext *C, tGPsdata *p)
{
- /* header prints */
- switch (p->status) {
- case GP_STATUS_IDLING:
- {
- /* print status info */
- switch (p->paintmode) {
- case GP_PAINTMODE_ERASER:
- {
- ED_workspace_status_text(C, IFACE_("Grease Pencil Erase Session: Hold and drag LMB or RMB to erase | "
- "ESC/Enter to end (or click outside this area)"));
- break;
- }
- case GP_PAINTMODE_DRAW_STRAIGHT:
- {
- ED_workspace_status_text(C, IFACE_("Grease Pencil Line Session: Hold and drag LMB to draw | "
- "ESC/Enter to end (or click outside this area)"));
- break;
- }
- case GP_PAINTMODE_SET_CP:
- {
- ED_workspace_status_text(C, IFACE_("Grease Pencil Guides: LMB click and release to place reference point | "
- "Esc/RMB to cancel"));
- break;
- }
- case GP_PAINTMODE_DRAW:
- {
- GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide;
- if (guide->use_guide) {
- ED_workspace_status_text(C, IFACE_("Grease Pencil Freehand Session: Hold and drag LMB to draw | "
- "M key to flip guide | O key to move reference point"));
- }
- else {
- ED_workspace_status_text(C, IFACE_("Grease Pencil Freehand Session: Hold and drag LMB to draw"));
- }
- break;
- }
- case GP_PAINTMODE_DRAW_POLY:
- {
- ED_workspace_status_text(C, IFACE_("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(C, IFACE_("Grease Pencil Session: ESC/Enter to end (or click outside this area)"));
- break;
- }
- }
- break;
- }
- case GP_STATUS_ERROR:
- case GP_STATUS_DONE:
- {
- /* clear status string */
- ED_workspace_status_text(C, NULL);
- break;
- }
- case GP_STATUS_PAINTING:
- break;
- }
+ /* header prints */
+ switch (p->status) {
+ case GP_STATUS_IDLING: {
+ /* print status info */
+ switch (p->paintmode) {
+ case GP_PAINTMODE_ERASER: {
+ ED_workspace_status_text(
+ C,
+ IFACE_("Grease Pencil Erase Session: Hold and drag LMB or RMB to erase | "
+ "ESC/Enter to end (or click outside this area)"));
+ break;
+ }
+ case GP_PAINTMODE_DRAW_STRAIGHT: {
+ ED_workspace_status_text(
+ C,
+ IFACE_("Grease Pencil Line Session: Hold and drag LMB to draw | "
+ "ESC/Enter to end (or click outside this area)"));
+ break;
+ }
+ case GP_PAINTMODE_SET_CP: {
+ ED_workspace_status_text(
+ C,
+ IFACE_("Grease Pencil Guides: LMB click and release to place reference point | "
+ "Esc/RMB to cancel"));
+ break;
+ }
+ case GP_PAINTMODE_DRAW: {
+ GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide;
+ if (guide->use_guide) {
+ ED_workspace_status_text(
+ C,
+ IFACE_("Grease Pencil Freehand Session: Hold and drag LMB to draw | "
+ "M key to flip guide | O key to move reference point"));
+ }
+ else {
+ ED_workspace_status_text(
+ C, IFACE_("Grease Pencil Freehand Session: Hold and drag LMB to draw"));
+ }
+ break;
+ }
+ case GP_PAINTMODE_DRAW_POLY: {
+ ED_workspace_status_text(
+ C,
+ IFACE_("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(
+ C, IFACE_("Grease Pencil Session: ESC/Enter to end (or click outside this area)"));
+ break;
+ }
+ }
+ break;
+ }
+ case GP_STATUS_ERROR:
+ case GP_STATUS_DONE: {
+ /* clear status string */
+ ED_workspace_status_text(C, NULL);
+ break;
+ }
+ case GP_STATUS_PAINTING:
+ break;
+ }
}
/* ------------------------------- */
@@ -2521,401 +2532,399 @@ 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)
{
- 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);
-
- /* 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_size - 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_size > 0))
- {
- pt = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_size - 1;
- if (p->paintmode != GP_PAINTMODE_ERASER) {
- ED_gpencil_toggle_brush_cursor(C, true, &pt->x);
- }
- }
+ 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);
+
+ /* 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_size - 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_size > 0)) {
+ pt = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_size - 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], const float origin[2], const float angle)
+static void gp_rotate_v2_v2v2fl(float v[2],
+ const float p[2],
+ const float origin[2],
+ const float angle)
{
- float pt[2];
- float r[2];
- sub_v2_v2v2(pt, p, origin);
- rotate_v2_v2fl(r, pt, angle);
- add_v2_v2v2(v, r, origin);
+ float pt[2];
+ float r[2];
+ sub_v2_v2v2(pt, p, origin);
+ rotate_v2_v2fl(r, pt, angle);
+ add_v2_v2v2(v, r, origin);
}
/* Helper to snap value to grid */
static float gp_snap_to_grid_fl(float v, const float offset, const float spacing)
{
- if (spacing > 0.0f) {
- return roundf(v / spacing) * spacing + fmodf(offset, spacing);
- }
- else {
- return v;
- }
+ if (spacing > 0.0f) {
+ return roundf(v / spacing) * spacing + fmodf(offset, spacing);
+ }
+ else {
+ return v;
+ }
}
-static void UNUSED_FUNCTION(gp_snap_to_grid_v2)(float v[2], const float offset[2], const float spacing)
+static void UNUSED_FUNCTION(gp_snap_to_grid_v2)(float v[2],
+ const float offset[2],
+ const float spacing)
{
- v[0] = gp_snap_to_grid_fl(v[0], offset[0], spacing);
- v[1] = gp_snap_to_grid_fl(v[1], offset[1], spacing);
+ v[0] = gp_snap_to_grid_fl(v[0], offset[0], spacing);
+ v[1] = gp_snap_to_grid_fl(v[1], offset[1], spacing);
}
/* get reference point - screen coords to buffer coords */
static void gp_origin_set(wmOperator *op, const int mval[2])
{
- tGPsdata *p = op->customdata;
- GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide;
- float origin[2];
- float point[3];
- copy_v2fl_v2i(origin, mval);
- gp_stroke_convertcoords(p, origin, point, NULL);
- if (guide->reference_point == GP_GUIDE_REF_CUSTOM) {
- copy_v3_v3(guide->location, point);
- }
- else if (guide->reference_point == GP_GUIDE_REF_CURSOR) {
- copy_v3_v3(p->scene->cursor.location, point);
- }
+ tGPsdata *p = op->customdata;
+ GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide;
+ float origin[2];
+ float point[3];
+ copy_v2fl_v2i(origin, mval);
+ gp_stroke_convertcoords(p, origin, point, NULL);
+ if (guide->reference_point == GP_GUIDE_REF_CUSTOM) {
+ copy_v3_v3(guide->location, point);
+ }
+ else if (guide->reference_point == GP_GUIDE_REF_CURSOR) {
+ copy_v3_v3(p->scene->cursor.location, point);
+ }
}
/* get reference point - buffer coords to screen coords */
static void gp_origin_get(tGPsdata *p, float origin[2])
{
- GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide;
- float location[3];
- if (guide->reference_point == GP_GUIDE_REF_CUSTOM) {
- copy_v3_v3(location, guide->location);
- }
- else if (guide->reference_point == GP_GUIDE_REF_OBJECT &&
- guide->reference_object != NULL)
- {
- copy_v3_v3(location, guide->reference_object->loc);
- }
- else {
- copy_v3_v3(location, p->scene->cursor.location);
- }
- GP_SpaceConversion *gsc = &p->gsc;
- gp_point_3d_to_xy(gsc, p->gpd->runtime.sbuffer_sflag, location, origin);
+ GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide;
+ float location[3];
+ if (guide->reference_point == GP_GUIDE_REF_CUSTOM) {
+ copy_v3_v3(location, guide->location);
+ }
+ else if (guide->reference_point == GP_GUIDE_REF_OBJECT && guide->reference_object != NULL) {
+ copy_v3_v3(location, guide->reference_object->loc);
+ }
+ else {
+ copy_v3_v3(location, p->scene->cursor.location);
+ }
+ GP_SpaceConversion *gsc = &p->gsc;
+ gp_point_3d_to_xy(gsc, p->gpd->runtime.sbuffer_sflag, location, origin);
}
/* handle draw event */
-static void gpencil_draw_apply_event(bContext *C, wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y)
+static void gpencil_draw_apply_event(
+ bContext *C, wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y)
{
- tGPsdata *p = op->customdata;
- GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide;
- PointerRNA itemptr;
- float mousef[2];
- int tablet = 0;
-
- /* convert from window-space to area-space mouse coordinates
- * add any x,y override position for fake events
- */
- p->mval[0] = (float)event->mval[0] - x;
- p->mval[1] = (float)event->mval[1] - y;
- p->shift = event->shift;
-
- /* verify direction for straight lines */
- if ((guide->use_guide) || ((event->alt > 0) && (RNA_boolean_get(op->ptr, "disable_straight") == false))) {
- if (p->straight == 0) {
- int dx = (int)fabsf(p->mval[0] - p->mvali[0]);
- int dy = (int)fabsf(p->mval[1] - p->mvali[1]);
- if ((dx > 0) || (dy > 0)) {
- /* store mouse direction */
- if (dx > dy) {
- p->straight = STROKE_HORIZONTAL;
- }
- else if (dx < dy) {
- p->straight = STROKE_VERTICAL;
- }
- }
- }
- }
-
- p->curtime = PIL_check_seconds_timer();
-
- /* handle pressure sensitivity (which is supplied by tablets) */
- if (event->tablet_data) {
- const wmTabletData *wmtab = event->tablet_data;
-
- tablet = (wmtab->Active != EVT_TABLET_NONE);
- p->pressure = wmtab->Pressure;
-
- /* Hack for pressure sensitive eraser on D+RMB when using a tablet:
- * The pen has to float over the tablet surface, resulting in
- * zero pressure (T47101). Ignore pressure values if floating
- * (i.e. "effectively zero" pressure), and only when the "active"
- * end is the stylus (i.e. the default when not eraser)
- */
- if (p->paintmode == GP_PAINTMODE_ERASER) {
- if ((wmtab->Active != EVT_TABLET_ERASER) && (p->pressure < 0.001f)) {
- p->pressure = 1.0f;
- }
- }
- }
- else {
- /* No tablet data -> No pressure info is available */
- p->pressure = 1.0f;
- }
-
- /* special eraser modes */
- if (p->paintmode == GP_PAINTMODE_ERASER) {
- if (event->shift > 0) {
- p->flags |= GP_PAINTFLAG_HARD_ERASER;
- }
- else {
- p->flags &= ~GP_PAINTFLAG_HARD_ERASER;
- }
- if (event->alt > 0) {
- p->flags |= GP_PAINTFLAG_STROKE_ERASER;
- }
- else {
- p->flags &= ~GP_PAINTFLAG_STROKE_ERASER;
- }
- }
-
- /* special exception for start of strokes (i.e. maybe for just a dot) */
- if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
- 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->mvali, p->mval);
-
- /* calculate once and store snapping distance and origin */
- RegionView3D * rv3d = p->ar->regiondata;
- float scale = 1.0f;
- if (rv3d->is_persp) {
- float vec[3];
- gp_get_3d_reference(p, vec);
- mul_m4_v3(rv3d->persmat, vec);
- scale = vec[2] * rv3d->pixsize;
- }
- else {
- scale = rv3d->pixsize;
- }
- p->guide_spacing = guide->spacing / scale;
- p->half_spacing = p->guide_spacing * 0.5f;
- gp_origin_get(p, p->origin);
-
- /* special exception here for too high pressure values on first touch in
- * windows for some tablets, then we just skip first touch...
- */
- if (tablet && (p->pressure >= 0.99f)) {
- return;
- }
-
- /* special exception for grid snapping
- * it requires direction which needs at least two points
- */
- if (!ELEM(p->paintmode, GP_PAINTMODE_ERASER, GP_PAINTMODE_SET_CP) &&
- guide->use_guide &&
- guide->use_snapping &&
- (guide->type == GP_GUIDE_GRID))
- {
- p->flags |= GP_PAINTFLAG_REQ_VECTOR;
- }
- }
-
- /* wait for vector then add initial point */
- if (p->flags & GP_PAINTFLAG_REQ_VECTOR) {
- if (p->straight == 0) {
- return;
- }
-
- p->flags &= ~GP_PAINTFLAG_REQ_VECTOR;
-
- /* create fake events */
- float tmp[2];
- float pt[2];
- copy_v2_v2(tmp, p->mval);
- sub_v2_v2v2(pt, p->mval, p->mvali);
- gpencil_draw_apply_event(C, op, event, CTX_data_depsgraph(C), pt[0], pt[1]);
- if (len_v2v2(p->mval, p->mvalo)) {
- sub_v2_v2v2(pt, p->mval, p->mvalo);
- gpencil_draw_apply_event(C, op, event, CTX_data_depsgraph(C), pt[0], pt[1]);
- }
- copy_v2_v2(p->mval, tmp);
- }
-
- /* check if stroke is straight or guided */
- if ((p->paintmode != GP_PAINTMODE_ERASER) &&
- ((p->straight) || (guide->use_guide)))
- {
- /* guided stroke */
- if (guide->use_guide) {
- switch (guide->type) {
- default:
- case GP_GUIDE_CIRCULAR:
- {
- float distance;
- distance = len_v2v2(p->mvali, p->origin);
-
- if (guide->use_snapping && (guide->spacing > 0.0f)) {
- distance = gp_snap_to_grid_fl(distance, 0.0f, p->guide_spacing);
- }
-
- dist_ensure_v2_v2fl(p->mval, p->origin, distance);
- break;
- }
- case GP_GUIDE_RADIAL:
- {
- if (guide->use_snapping && (guide->angle_snap > 0.0f)) {
- float point[2];
- float xy[2];
- float angle;
- float half_angle = guide->angle_snap * 0.5f;
- sub_v2_v2v2(xy, p->mvali, p->origin);
- angle = atan2f(xy[1], xy[0]);
- angle += (M_PI * 2.0f);
- angle = fmodf(angle + half_angle, guide->angle_snap);
- angle -= half_angle;
- gp_rotate_v2_v2v2fl(point, p->mvali, p->origin, -angle);
- closest_to_line_v2(p->mval, p->mval, point, p->origin);
- }
- else {
- closest_to_line_v2(p->mval, p->mval, p->mvali, p->origin);
- }
- break;
- }
- case GP_GUIDE_PARALLEL:
- {
- float point[2];
- float unit[2];
- copy_v2_v2(unit, p->mvali);
- unit[0] += 1.0f; /* start from horizontal */
- gp_rotate_v2_v2v2fl(point, unit, p->mvali, guide->angle);
- closest_to_line_v2(p->mval, p->mval, p->mvali, point);
-
- if (guide->use_snapping && (guide->spacing > 0.0f)) {
- gp_rotate_v2_v2v2fl(p->mval, p->mval, p->origin, -guide->angle);
- p->mval[1] = gp_snap_to_grid_fl(p->mval[1] - p->half_spacing, p->origin[1], p->guide_spacing);
- gp_rotate_v2_v2v2fl(p->mval, p->mval, p->origin, guide->angle);
- }
- break;
- }
- case GP_GUIDE_GRID:
- {
- if (guide->use_snapping && (guide->spacing > 0.0f)) {
- float point[2];
- float unit[2];
- float angle;
- copy_v2_v2(unit, p->mvali);
- unit[0] += 1.0f; /* start from horizontal */
- angle = (p->straight == STROKE_VERTICAL) ? M_PI_2 : 0.0f;
- gp_rotate_v2_v2v2fl(point, unit, p->mvali, angle);
- closest_to_line_v2(p->mval, p->mval, p->mvali, point);
-
- if (p->straight == STROKE_HORIZONTAL) {
- p->mval[1] = gp_snap_to_grid_fl(p->mval[1] - p->half_spacing, p->origin[1], p->guide_spacing);
- }
- else {
- p->mval[0] = gp_snap_to_grid_fl(p->mval[0] - p->half_spacing, p->origin[0], p->guide_spacing);
- }
- }
- else if (p->straight == STROKE_HORIZONTAL) {
- p->mval[1] = p->mvali[1]; /* replace y */
- }
- else {
- p->mval[0] = p->mvali[0]; /* replace x */
- }
- break;
- }
- }
- }
- else if (p->straight == STROKE_HORIZONTAL) {
- p->mval[1] = p->mvali[1]; /* replace y */
- }
- else {
- p->mval[0] = p->mvali[0]; /* replace x */
- }
- }
-
- /* fill in stroke data (not actually used directly by gpencil_draw_apply) */
- RNA_collection_add(op->ptr, "stroke", &itemptr);
-
- mousef[0] = p->mval[0];
- mousef[1] = p->mval[1];
- RNA_float_set_array(&itemptr, "mouse", mousef);
- RNA_float_set(&itemptr, "pressure", p->pressure);
- RNA_boolean_set(&itemptr, "is_start", (p->flags & GP_PAINTFLAG_FIRSTRUN) != 0);
-
- RNA_float_set(&itemptr, "time", p->curtime - p->inittime);
-
- /* apply the current latest drawing point */
- 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);
+ tGPsdata *p = op->customdata;
+ GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide;
+ PointerRNA itemptr;
+ float mousef[2];
+ int tablet = 0;
+
+ /* convert from window-space to area-space mouse coordinates
+ * add any x,y override position for fake events
+ */
+ p->mval[0] = (float)event->mval[0] - x;
+ p->mval[1] = (float)event->mval[1] - y;
+ p->shift = event->shift;
+
+ /* verify direction for straight lines */
+ if ((guide->use_guide) ||
+ ((event->alt > 0) && (RNA_boolean_get(op->ptr, "disable_straight") == false))) {
+ if (p->straight == 0) {
+ int dx = (int)fabsf(p->mval[0] - p->mvali[0]);
+ int dy = (int)fabsf(p->mval[1] - p->mvali[1]);
+ if ((dx > 0) || (dy > 0)) {
+ /* store mouse direction */
+ if (dx > dy) {
+ p->straight = STROKE_HORIZONTAL;
+ }
+ else if (dx < dy) {
+ p->straight = STROKE_VERTICAL;
+ }
+ }
+ }
+ }
+
+ p->curtime = PIL_check_seconds_timer();
+
+ /* handle pressure sensitivity (which is supplied by tablets) */
+ if (event->tablet_data) {
+ const wmTabletData *wmtab = event->tablet_data;
+
+ tablet = (wmtab->Active != EVT_TABLET_NONE);
+ p->pressure = wmtab->Pressure;
+
+ /* Hack for pressure sensitive eraser on D+RMB when using a tablet:
+ * The pen has to float over the tablet surface, resulting in
+ * zero pressure (T47101). Ignore pressure values if floating
+ * (i.e. "effectively zero" pressure), and only when the "active"
+ * end is the stylus (i.e. the default when not eraser)
+ */
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ if ((wmtab->Active != EVT_TABLET_ERASER) && (p->pressure < 0.001f)) {
+ p->pressure = 1.0f;
+ }
+ }
+ }
+ else {
+ /* No tablet data -> No pressure info is available */
+ p->pressure = 1.0f;
+ }
+
+ /* special eraser modes */
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ if (event->shift > 0) {
+ p->flags |= GP_PAINTFLAG_HARD_ERASER;
+ }
+ else {
+ p->flags &= ~GP_PAINTFLAG_HARD_ERASER;
+ }
+ if (event->alt > 0) {
+ p->flags |= GP_PAINTFLAG_STROKE_ERASER;
+ }
+ else {
+ p->flags &= ~GP_PAINTFLAG_STROKE_ERASER;
+ }
+ }
+
+ /* special exception for start of strokes (i.e. maybe for just a dot) */
+ if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
+ 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->mvali, p->mval);
+
+ /* calculate once and store snapping distance and origin */
+ RegionView3D *rv3d = p->ar->regiondata;
+ float scale = 1.0f;
+ if (rv3d->is_persp) {
+ float vec[3];
+ gp_get_3d_reference(p, vec);
+ mul_m4_v3(rv3d->persmat, vec);
+ scale = vec[2] * rv3d->pixsize;
+ }
+ else {
+ scale = rv3d->pixsize;
+ }
+ p->guide_spacing = guide->spacing / scale;
+ p->half_spacing = p->guide_spacing * 0.5f;
+ gp_origin_get(p, p->origin);
+
+ /* special exception here for too high pressure values on first touch in
+ * windows for some tablets, then we just skip first touch...
+ */
+ if (tablet && (p->pressure >= 0.99f)) {
+ return;
+ }
+
+ /* special exception for grid snapping
+ * it requires direction which needs at least two points
+ */
+ if (!ELEM(p->paintmode, GP_PAINTMODE_ERASER, GP_PAINTMODE_SET_CP) && guide->use_guide &&
+ guide->use_snapping && (guide->type == GP_GUIDE_GRID)) {
+ p->flags |= GP_PAINTFLAG_REQ_VECTOR;
+ }
+ }
+
+ /* wait for vector then add initial point */
+ if (p->flags & GP_PAINTFLAG_REQ_VECTOR) {
+ if (p->straight == 0) {
+ return;
+ }
+
+ p->flags &= ~GP_PAINTFLAG_REQ_VECTOR;
+
+ /* create fake events */
+ float tmp[2];
+ float pt[2];
+ copy_v2_v2(tmp, p->mval);
+ sub_v2_v2v2(pt, p->mval, p->mvali);
+ gpencil_draw_apply_event(C, op, event, CTX_data_depsgraph(C), pt[0], pt[1]);
+ if (len_v2v2(p->mval, p->mvalo)) {
+ sub_v2_v2v2(pt, p->mval, p->mvalo);
+ gpencil_draw_apply_event(C, op, event, CTX_data_depsgraph(C), pt[0], pt[1]);
+ }
+ copy_v2_v2(p->mval, tmp);
+ }
+
+ /* check if stroke is straight or guided */
+ if ((p->paintmode != GP_PAINTMODE_ERASER) && ((p->straight) || (guide->use_guide))) {
+ /* guided stroke */
+ if (guide->use_guide) {
+ switch (guide->type) {
+ default:
+ case GP_GUIDE_CIRCULAR: {
+ float distance;
+ distance = len_v2v2(p->mvali, p->origin);
+
+ if (guide->use_snapping && (guide->spacing > 0.0f)) {
+ distance = gp_snap_to_grid_fl(distance, 0.0f, p->guide_spacing);
+ }
+
+ dist_ensure_v2_v2fl(p->mval, p->origin, distance);
+ break;
+ }
+ case GP_GUIDE_RADIAL: {
+ if (guide->use_snapping && (guide->angle_snap > 0.0f)) {
+ float point[2];
+ float xy[2];
+ float angle;
+ float half_angle = guide->angle_snap * 0.5f;
+ sub_v2_v2v2(xy, p->mvali, p->origin);
+ angle = atan2f(xy[1], xy[0]);
+ angle += (M_PI * 2.0f);
+ angle = fmodf(angle + half_angle, guide->angle_snap);
+ angle -= half_angle;
+ gp_rotate_v2_v2v2fl(point, p->mvali, p->origin, -angle);
+ closest_to_line_v2(p->mval, p->mval, point, p->origin);
+ }
+ else {
+ closest_to_line_v2(p->mval, p->mval, p->mvali, p->origin);
+ }
+ break;
+ }
+ case GP_GUIDE_PARALLEL: {
+ float point[2];
+ float unit[2];
+ copy_v2_v2(unit, p->mvali);
+ unit[0] += 1.0f; /* start from horizontal */
+ gp_rotate_v2_v2v2fl(point, unit, p->mvali, guide->angle);
+ closest_to_line_v2(p->mval, p->mval, p->mvali, point);
+
+ if (guide->use_snapping && (guide->spacing > 0.0f)) {
+ gp_rotate_v2_v2v2fl(p->mval, p->mval, p->origin, -guide->angle);
+ p->mval[1] = gp_snap_to_grid_fl(
+ p->mval[1] - p->half_spacing, p->origin[1], p->guide_spacing);
+ gp_rotate_v2_v2v2fl(p->mval, p->mval, p->origin, guide->angle);
+ }
+ break;
+ }
+ case GP_GUIDE_GRID: {
+ if (guide->use_snapping && (guide->spacing > 0.0f)) {
+ float point[2];
+ float unit[2];
+ float angle;
+ copy_v2_v2(unit, p->mvali);
+ unit[0] += 1.0f; /* start from horizontal */
+ angle = (p->straight == STROKE_VERTICAL) ? M_PI_2 : 0.0f;
+ gp_rotate_v2_v2v2fl(point, unit, p->mvali, angle);
+ closest_to_line_v2(p->mval, p->mval, p->mvali, point);
+
+ if (p->straight == STROKE_HORIZONTAL) {
+ p->mval[1] = gp_snap_to_grid_fl(
+ p->mval[1] - p->half_spacing, p->origin[1], p->guide_spacing);
+ }
+ else {
+ p->mval[0] = gp_snap_to_grid_fl(
+ p->mval[0] - p->half_spacing, p->origin[0], p->guide_spacing);
+ }
+ }
+ else if (p->straight == STROKE_HORIZONTAL) {
+ p->mval[1] = p->mvali[1]; /* replace y */
+ }
+ else {
+ p->mval[0] = p->mvali[0]; /* replace x */
+ }
+ break;
+ }
+ }
+ }
+ else if (p->straight == STROKE_HORIZONTAL) {
+ p->mval[1] = p->mvali[1]; /* replace y */
+ }
+ else {
+ p->mval[0] = p->mvali[0]; /* replace x */
+ }
+ }
+
+ /* fill in stroke data (not actually used directly by gpencil_draw_apply) */
+ RNA_collection_add(op->ptr, "stroke", &itemptr);
+
+ mousef[0] = p->mval[0];
+ mousef[1] = p->mval[1];
+ RNA_float_set_array(&itemptr, "mouse", mousef);
+ RNA_float_set(&itemptr, "pressure", p->pressure);
+ RNA_boolean_set(&itemptr, "is_start", (p->flags & GP_PAINTFLAG_FIRSTRUN) != 0);
+
+ RNA_float_set(&itemptr, "time", p->curtime - p->inittime);
+
+ /* apply the current latest drawing point */
+ 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);
}
/* ------------------------------- */
@@ -2923,910 +2932,945 @@ static void gpencil_draw_apply_event(bContext *C, wmOperator *op, const wmEvent
/* operator 'redo' (i.e. after changing some properties, but also for repeat last) */
static int gpencil_draw_exec(bContext *C, wmOperator *op)
{
- tGPsdata *p = NULL;
- Depsgraph *depsgraph = CTX_data_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];
- p->mval[1] = mousef[1];
- p->pressure = RNA_float_get(&itemptr, "pressure");
- p->curtime = (double)RNA_float_get(&itemptr, "time") + p->inittime;
-
- if (RNA_boolean_get(&itemptr, "is_start")) {
- /* if first-run flag isn't set already (i.e. not true first stroke),
- * then we must terminate the previous one first before continuing
- */
- if ((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) {
- /* TODO: both of these ops can set error-status, but we probably don't need to worry */
- gp_paint_strokeend(p);
- gp_paint_initstroke(p, p->paintmode, depsgraph);
- }
- }
-
- /* if first run, set previous data too */
- if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
- p->flags &= ~GP_PAINTFLAG_FIRSTRUN;
-
- p->mvalo[0] = p->mval[0];
- p->mvalo[1] = p->mval[1];
- p->opressure = p->pressure;
- p->ocurtime = p->curtime;
- }
-
- /* apply this data as necessary now (as per usual) */
- gpencil_draw_apply(C, op, p, depsgraph);
- }
- RNA_END;
-
- /* printf("\tGP - done\n"); */
-
- /* cleanup */
- gpencil_draw_exit(C, op);
-
- /* refreshes */
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
+ tGPsdata *p = NULL;
+ Depsgraph *depsgraph = CTX_data_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];
+ p->mval[1] = mousef[1];
+ p->pressure = RNA_float_get(&itemptr, "pressure");
+ p->curtime = (double)RNA_float_get(&itemptr, "time") + p->inittime;
+
+ if (RNA_boolean_get(&itemptr, "is_start")) {
+ /* if first-run flag isn't set already (i.e. not true first stroke),
+ * then we must terminate the previous one first before continuing
+ */
+ if ((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) {
+ /* TODO: both of these ops can set error-status, but we probably don't need to worry */
+ gp_paint_strokeend(p);
+ gp_paint_initstroke(p, p->paintmode, depsgraph);
+ }
+ }
+
+ /* if first run, set previous data too */
+ if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
+ p->flags &= ~GP_PAINTFLAG_FIRSTRUN;
+
+ p->mvalo[0] = p->mval[0];
+ p->mvalo[1] = p->mval[1];
+ p->opressure = p->pressure;
+ p->ocurtime = p->curtime;
+ }
+
+ /* apply this data as necessary now (as per usual) */
+ gpencil_draw_apply(C, op, p, depsgraph);
+ }
+ RNA_END;
+
+ /* printf("\tGP - done\n"); */
+
+ /* cleanup */
+ gpencil_draw_exit(C, op);
+
+ /* refreshes */
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
/* ------------------------------- */
/* handle events for guides */
-static void gpencil_guide_event_handling(bContext *C, wmOperator *op, const wmEvent *event, tGPsdata *p)
+static void gpencil_guide_event_handling(bContext *C,
+ wmOperator *op,
+ const wmEvent *event,
+ tGPsdata *p)
{
- bool add_notifier = false;
- 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 (p->paintmode == GP_PAINTMODE_DRAW && guide->reference_point != GP_GUIDE_REF_OBJECT) {
- add_notifier = true;
- p->paintmode = GP_PAINTMODE_SET_CP;
- ED_gpencil_toggle_brush_cursor(C, false, NULL);
- }
- }
- /* Freehand mode, turn off speed guide */
- else if ((event->type == 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)) {
- if (guide->type == GP_GUIDE_CIRCULAR) {
- add_notifier = true;
- guide->type = GP_GUIDE_RADIAL;
- }
- else if (guide->type == GP_GUIDE_RADIAL) {
- add_notifier = true;
- guide->type = GP_GUIDE_CIRCULAR;
- }
- else if (guide->type == GP_GUIDE_PARALLEL) {
- add_notifier = true;
- guide->angle += M_PI_2;
- guide->angle = angle_compat_rad(guide->angle, M_PI);
- }
- else {
- add_notifier = false;
- }
- }
- /* Line guides */
- else if ((event->type == LKEY) && (event->val == KM_RELEASE)) {
- add_notifier = true;
- guide->use_guide = true;
- if (event->ctrl) {
- guide->angle = 0.0f;
- guide->type = GP_GUIDE_PARALLEL;
- }
- else if (event->alt) {
- guide->type = GP_GUIDE_PARALLEL;
- guide->angle = RNA_float_get(op->ptr, "guide_last_angle");
- }
- else {
- guide->type = GP_GUIDE_PARALLEL;
- }
- }
- /* Point guide */
- else if ((event->type == CKEY) && (event->val == KM_RELEASE)) {
- add_notifier = true;
- if (!guide->use_guide) {
- guide->use_guide = true;
- guide->type = GP_GUIDE_CIRCULAR;
- }
- else if (guide->type == GP_GUIDE_CIRCULAR) {
- guide->type = GP_GUIDE_RADIAL;
- }
- else if (guide->type == GP_GUIDE_RADIAL) {
- guide->type = GP_GUIDE_CIRCULAR;
- }
- else {
- guide->type = GP_GUIDE_CIRCULAR;
- }
- }
- /* Change line angle */
- else if (ELEM(event->type, JKEY, KKEY) && (event->val == KM_RELEASE)) {
- add_notifier = true;
- float angle = guide->angle;
- float adjust = (float)M_PI / 180.0f;
- if (event->alt)
- adjust *= 45.0f;
- else if (!event->shift)
- adjust *= 15.0f;
- angle += (event->type == JKEY) ? adjust : -adjust;
- angle = angle_compat_rad(angle, M_PI);
- guide->angle = angle;
- }
-
- if (add_notifier) {
- WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS | NC_GPENCIL | NA_EDITED, NULL);
- }
+ bool add_notifier = false;
+ 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 (p->paintmode == GP_PAINTMODE_DRAW && guide->reference_point != GP_GUIDE_REF_OBJECT) {
+ add_notifier = true;
+ p->paintmode = GP_PAINTMODE_SET_CP;
+ ED_gpencil_toggle_brush_cursor(C, false, NULL);
+ }
+ }
+ /* Freehand mode, turn off speed guide */
+ else if ((event->type == 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)) {
+ if (guide->type == GP_GUIDE_CIRCULAR) {
+ add_notifier = true;
+ guide->type = GP_GUIDE_RADIAL;
+ }
+ else if (guide->type == GP_GUIDE_RADIAL) {
+ add_notifier = true;
+ guide->type = GP_GUIDE_CIRCULAR;
+ }
+ else if (guide->type == GP_GUIDE_PARALLEL) {
+ add_notifier = true;
+ guide->angle += M_PI_2;
+ guide->angle = angle_compat_rad(guide->angle, M_PI);
+ }
+ else {
+ add_notifier = false;
+ }
+ }
+ /* Line guides */
+ else if ((event->type == LKEY) && (event->val == KM_RELEASE)) {
+ add_notifier = true;
+ guide->use_guide = true;
+ if (event->ctrl) {
+ guide->angle = 0.0f;
+ guide->type = GP_GUIDE_PARALLEL;
+ }
+ else if (event->alt) {
+ guide->type = GP_GUIDE_PARALLEL;
+ guide->angle = RNA_float_get(op->ptr, "guide_last_angle");
+ }
+ else {
+ guide->type = GP_GUIDE_PARALLEL;
+ }
+ }
+ /* Point guide */
+ else if ((event->type == CKEY) && (event->val == KM_RELEASE)) {
+ add_notifier = true;
+ if (!guide->use_guide) {
+ guide->use_guide = true;
+ guide->type = GP_GUIDE_CIRCULAR;
+ }
+ else if (guide->type == GP_GUIDE_CIRCULAR) {
+ guide->type = GP_GUIDE_RADIAL;
+ }
+ else if (guide->type == GP_GUIDE_RADIAL) {
+ guide->type = GP_GUIDE_CIRCULAR;
+ }
+ else {
+ guide->type = GP_GUIDE_CIRCULAR;
+ }
+ }
+ /* Change line angle */
+ else if (ELEM(event->type, JKEY, KKEY) && (event->val == KM_RELEASE)) {
+ add_notifier = true;
+ float angle = guide->angle;
+ float adjust = (float)M_PI / 180.0f;
+ if (event->alt)
+ adjust *= 45.0f;
+ else if (!event->shift)
+ adjust *= 15.0f;
+ angle += (event->type == JKEY) ? adjust : -adjust;
+ angle = angle_compat_rad(angle, M_PI);
+ guide->angle = angle;
+ }
+
+ if (add_notifier) {
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS | NC_GPENCIL | NA_EDITED, NULL);
+ }
}
/* start of interactive drawing part of operator */
static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- tGPsdata *p = NULL;
- Object *ob = CTX_data_active_object(C);
- bGPdata *gpd = (bGPdata *)ob->data;
-
- if (G.debug & G_DEBUG)
- printf("GPencil - Starting Drawing\n");
-
- /* support for tablets eraser pen */
- if (gpencil_is_tablet_eraser_active(event)) {
- RNA_enum_set(op->ptr, "mode", GP_PAINTMODE_ERASER);
- }
-
- /* do not draw in locked or invisible layers */
- eGPencil_PaintModes paintmode = RNA_enum_get(op->ptr, "mode");
- if (paintmode != GP_PAINTMODE_ERASER) {
- bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
- if ((gpl) && ((gpl->flag & GP_LAYER_LOCKED) || (gpl->flag & GP_LAYER_HIDE))) {
- BKE_report(op->reports, RPT_ERROR, "Active layer is locked or hide");
- return OPERATOR_CANCELLED;
- }
- }
- else {
- /* don't erase empty frames */
- bool has_layer_to_erase = false;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* Skip if layer not editable */
- if (gpencil_layer_is_editable(gpl)) {
- if (gpl->actframe && gpl->actframe->strokes.first) {
- has_layer_to_erase = true;
- break;
- }
- }
- }
- if (!has_layer_to_erase) {
- BKE_report(op->reports, RPT_ERROR, "Nothing to erase or all layers locked");
- return OPERATOR_FINISHED;
- }
- }
-
- /* try to initialize context data needed while drawing */
- if (!gpencil_draw_init(C, op, event)) {
- if (op->customdata)
- MEM_freeN(op->customdata);
- if (G.debug & G_DEBUG)
- printf("\tGP - no valid data\n");
- return OPERATOR_CANCELLED;
- }
- else
- p = op->customdata;
-
- /* 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... */
-
- /* 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_depsgraph(C), 0.0f, 0.0f);
- 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;
- }
-
- /* enable paint mode */
- /* handle speed guide events before drawing inside view3d */
- if (!ELEM(p->paintmode, GP_PAINTMODE_ERASER, GP_PAINTMODE_SET_CP)) {
- gpencil_guide_event_handling(C, op, event, p);
- }
-
- if (ob && (ob->type == OB_GPENCIL) && ((p->gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0)) {
- /* FIXME: use the mode switching operator, this misses notifiers, messages. */
- /* Just set paintmode flag... */
- p->gpd->flag |= GP_DATA_STROKE_PAINTMODE;
- /* disable other GP modes */
- p->gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
- p->gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
- p->gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
- /* set workspace mode */
- ob->restore_mode = ob->mode;
- ob->mode = OB_MODE_PAINT_GPENCIL;
- /* redraw mode on screen */
- WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
- }
-
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
-
- /* add a modal handler for this operator, so that we can then draw continuous strokes */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
+ tGPsdata *p = NULL;
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ if (G.debug & G_DEBUG)
+ printf("GPencil - Starting Drawing\n");
+
+ /* support for tablets eraser pen */
+ if (gpencil_is_tablet_eraser_active(event)) {
+ RNA_enum_set(op->ptr, "mode", GP_PAINTMODE_ERASER);
+ }
+
+ /* do not draw in locked or invisible layers */
+ eGPencil_PaintModes paintmode = RNA_enum_get(op->ptr, "mode");
+ if (paintmode != GP_PAINTMODE_ERASER) {
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+ if ((gpl) && ((gpl->flag & GP_LAYER_LOCKED) || (gpl->flag & GP_LAYER_HIDE))) {
+ BKE_report(op->reports, RPT_ERROR, "Active layer is locked or hide");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ /* don't erase empty frames */
+ bool has_layer_to_erase = false;
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* Skip if layer not editable */
+ if (gpencil_layer_is_editable(gpl)) {
+ if (gpl->actframe && gpl->actframe->strokes.first) {
+ has_layer_to_erase = true;
+ break;
+ }
+ }
+ }
+ if (!has_layer_to_erase) {
+ BKE_report(op->reports, RPT_ERROR, "Nothing to erase or all layers locked");
+ return OPERATOR_FINISHED;
+ }
+ }
+
+ /* try to initialize context data needed while drawing */
+ if (!gpencil_draw_init(C, op, event)) {
+ if (op->customdata)
+ MEM_freeN(op->customdata);
+ if (G.debug & G_DEBUG)
+ printf("\tGP - no valid data\n");
+ return OPERATOR_CANCELLED;
+ }
+ else
+ p = op->customdata;
+
+ /* 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... */
+
+ /* 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_depsgraph(C), 0.0f, 0.0f);
+ 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;
+ }
+
+ /* enable paint mode */
+ /* handle speed guide events before drawing inside view3d */
+ if (!ELEM(p->paintmode, GP_PAINTMODE_ERASER, GP_PAINTMODE_SET_CP)) {
+ gpencil_guide_event_handling(C, op, event, p);
+ }
+
+ if (ob && (ob->type == OB_GPENCIL) && ((p->gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0)) {
+ /* FIXME: use the mode switching operator, this misses notifiers, messages. */
+ /* Just set paintmode flag... */
+ p->gpd->flag |= GP_DATA_STROKE_PAINTMODE;
+ /* disable other GP modes */
+ p->gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
+ p->gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
+ p->gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
+ /* set workspace mode */
+ ob->restore_mode = ob->mode;
+ ob->mode = OB_MODE_PAINT_GPENCIL;
+ /* redraw mode on screen */
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
+ }
+
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+
+ /* add a modal handler for this operator, so that we can then draw continuous strokes */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
}
/* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */
static bool gpencil_area_exists(bContext *C, ScrArea *sa_test)
{
- bScreen *sc = CTX_wm_screen(C);
- return (BLI_findindex(&sc->areabase, sa_test) != -1);
+ bScreen *sc = CTX_wm_screen(C);
+ return (BLI_findindex(&sc->areabase, sa_test) != -1);
}
static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
{
- tGPsdata *p = op->customdata;
+ tGPsdata *p = op->customdata;
- /* 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) {
- printf("\t\t\tGP - wrong area execution abort!\n");
- p->status = GP_STATUS_ERROR;
- }
+ /* 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) {
+ printf("\t\t\tGP - wrong area execution abort!\n");
+ p->status = GP_STATUS_ERROR;
+ }
- /* printf("\t\tGP - start stroke\n"); */
+ /* 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 */
+ /* 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(C));
+ if (gp_session_initdata(C, op, p))
+ gp_paint_initstroke(p, p->paintmode, CTX_data_depsgraph(C));
- if (p->status != GP_STATUS_ERROR) {
- p->status = GP_STATUS_PAINTING;
- op->flag &= ~OP_IS_MODAL_CURSOR_REGION;
- }
+ if (p->status != GP_STATUS_ERROR) {
+ p->status = GP_STATUS_PAINTING;
+ op->flag &= ~OP_IS_MODAL_CURSOR_REGION;
+ }
- return op->customdata;
+ return op->customdata;
}
static void gpencil_stroke_end(wmOperator *op)
{
- tGPsdata *p = op->customdata;
+ tGPsdata *p = op->customdata;
- gp_paint_cleanup(p);
+ gp_paint_cleanup(p);
- gpencil_undo_push(p->gpd);
+ gpencil_undo_push(p->gpd);
- gp_session_cleanup(p);
+ gp_session_cleanup(p);
- p->status = GP_STATUS_IDLING;
- op->flag |= OP_IS_MODAL_CURSOR_REGION;
+ p->status = GP_STATUS_IDLING;
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
- p->gpd = NULL;
- p->gpl = NULL;
- p->gpf = NULL;
+ p->gpd = NULL;
+ p->gpl = NULL;
+ p->gpf = NULL;
}
/* 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);
-
- /* sanity checks */
- if (ELEM(NULL, gpd, gpl, gpl->actframe)) {
- return;
- }
-
- bGPDframe *gpf = gpl->actframe;
- bGPDstroke *gps = gpf->strokes.last;
- if (ELEM(NULL, gps)) {
- return;
- }
-
- BLI_remlink(&gpf->strokes, gps);
- BLI_insertlinkbefore(&gpf->strokes, gpf->strokes.first, gps);
+ /* 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);
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd, gpl, gpl->actframe)) {
+ return;
+ }
+
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps = gpf->strokes.last;
+ if (ELEM(NULL, gps)) {
+ return;
+ }
+
+ BLI_remlink(&gpf->strokes, gps);
+ BLI_insertlinkbefore(&gpf->strokes, gpf->strokes.first, gps);
}
/* add events for missing mouse movements when the artist draw very fast */
-static void gpencil_add_missing_events(bContext *C, wmOperator *op, const wmEvent *event, tGPsdata *p)
+static void gpencil_add_missing_events(bContext *C,
+ wmOperator *op,
+ const wmEvent *event,
+ tGPsdata *p)
{
- Brush *brush = p->brush;
- GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide;
- int input_samples = brush->gpencil_settings->input_samples;
-
- /* ensure sampling when using circular guide */
- if (guide->use_guide && (guide->type == GP_GUIDE_CIRCULAR)) {
- input_samples = GP_MAX_INPUT_SAMPLES;
- }
-
- if (input_samples == 0) {
- 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;
-
- float pt[2], a[2], b[2];
- float vec[3];
- float scale = 1.0f;
-
- /* 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;
- }
-
- /* 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;
- }
- 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;
-
- /* 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, CTX_data_depsgraph(C), pt[0], pt[1]);
- }
- 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, CTX_data_depsgraph(C),
- pt[0], pt[1]);
- }
- }
+ Brush *brush = p->brush;
+ GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide;
+ int input_samples = brush->gpencil_settings->input_samples;
+
+ /* ensure sampling when using circular guide */
+ if (guide->use_guide && (guide->type == GP_GUIDE_CIRCULAR)) {
+ input_samples = GP_MAX_INPUT_SAMPLES;
+ }
+
+ if (input_samples == 0) {
+ 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;
+
+ float pt[2], a[2], b[2];
+ float vec[3];
+ float scale = 1.0f;
+
+ /* 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;
+ }
+
+ /* 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;
+ }
+ 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;
+
+ /* 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, CTX_data_depsgraph(C), pt[0], pt[1]);
+ }
+ 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, CTX_data_depsgraph(C), pt[0], pt[1]);
+ }
+ }
}
/* 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);
- GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide;
- /* default exit state - pass through to support MMB view nav, etc. */
- int estate = OPERATOR_PASS_THROUGH;
-
- /* if (event->type == NDOF_MOTION)
- * return OPERATOR_PASS_THROUGH;
- * -------------------------------
- * [mce] Not quite what I was looking
- * for, but a good start! GP continues to
- * draw on the screen while the 3D mouse
- * moves the viewpoint. Problem is that
- * the stroke is converted to 3D only after
- * it is finished. This approach should work
- * better in tools that immediately apply
- * in 3D space.
- */
-
- if (p->status == GP_STATUS_IDLING) {
- ARegion *ar = CTX_wm_region(C);
- p->ar = ar;
- }
-
- /* special mode for editing control points */
- if (p->paintmode == GP_PAINTMODE_SET_CP) {
- wmWindow *win = p->win;
- WM_cursor_modal_set(win, BC_NSEW_SCROLLCURSOR);
- bool drawmode = false;
-
- switch (event->type) {
- /* cancel */
- case ESCKEY:
- case RIGHTMOUSE:
- {
- if (ELEM(event->val, KM_RELEASE)) {
- drawmode = true;
- }
- break;
- }
- /* set */
- case LEFTMOUSE:
- {
- if (ELEM(event->val, KM_RELEASE)) {
- gp_origin_set(op, event->mval);
- drawmode = true;
- }
- break;
- }
- }
- if (drawmode) {
- p->status = GP_STATUS_IDLING;
- p->paintmode = GP_PAINTMODE_DRAW;
- ED_gpencil_toggle_brush_cursor(C, true, NULL);
- DEG_id_tag_update(&p->scene->id, ID_RECALC_COPY_ON_WRITE);
- }
- else {
- return OPERATOR_RUNNING_MODAL;
- }
- }
-
- /* 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)) {
- /* 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)) {
- /* 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)) {
- /* 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
- */
- WM_operator_name_call(C, "GPENCIL_OT_blank_frame_add", WM_OP_EXEC_DEFAULT, NULL);
- estate = OPERATOR_RUNNING_MODAL;
- }
- else if ((!ELEM(p->paintmode, GP_PAINTMODE_ERASER, GP_PAINTMODE_SET_CP))) {
- gpencil_guide_event_handling(C, op, event, p);
- estate = OPERATOR_RUNNING_MODAL;
- }
- else {
- estate = OPERATOR_RUNNING_MODAL;
- }
- }
-
- //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 [#32647]
- */
- /* 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);
- }
- }
- }
-
- 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)
- * (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;
- }
- }
- else if (event->val == KM_PRESS) {
- bool in_bounds = false;
-
- /* Check if we're outside the bounds of the active region
- * 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)) {
- /* 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);
-
- if (G.debug & G_DEBUG) {
- printf("found alternative region %p (old was %p) - at %d %d (sa: %d %d -> %d %d)\n",
- current_region, p->ar, event->x, event->y,
- p->sa->totrct.xmin, p->sa->totrct.ymin, p->sa->totrct.xmax, p->sa->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;
- in_bounds = true;
- }
- else {
- /* Out of bounds, or invalid in some other way */
- p->status = GP_STATUS_ERROR;
- estate = OPERATOR_CANCELLED;
-
- if (G.debug & G_DEBUG)
- printf("%s: Region under cursor is out of bounds, so cannot be drawn on\n", __func__);
- }
- }
- else if (p->ar) {
- rcti region_rect;
-
- /* Perform bounds check using */
- ED_region_visible_rect(p->ar, &region_rect);
- in_bounds = BLI_rcti_isect_pt_v(&region_rect, event->mval);
- }
- else {
- /* No region */
- p->status = GP_STATUS_ERROR;
- estate = OPERATOR_CANCELLED;
-
- if (G.debug & G_DEBUG)
- printf("%s: No active region found in GP Paint session data\n", __func__);
- }
-
- if (in_bounds) {
- /* Switch paintmode (temporarily if need be) based on which button was used
- * NOTE: This is to make it more convenient to erase strokes when using drawing sessions
- */
- if ((event->type == RIGHTMOUSE) || gpencil_is_tablet_eraser_active(event)) {
- /* turn on eraser */
- p->paintmode = GP_PAINTMODE_ERASER;
- }
- else if (event->type == LEFTMOUSE) {
- /* restore drawmode to default */
- p->paintmode = RNA_enum_get(op->ptr, "mode");
- }
-
- gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER);
-
- /* not painting, so start stroke (this should be mouse-button down) */
- p = gpencil_stroke_begin(C, op);
-
- if (p->status == GP_STATUS_ERROR) {
- estate = OPERATOR_CANCELLED;
- }
- }
- else if (p->status != GP_STATUS_ERROR) {
- /* User clicked outside bounds of window while idling, so exit paintmode
- * 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;
- }
- }
- else if (event->val == KM_RELEASE) {
- p->status = GP_STATUS_IDLING;
- op->flag |= OP_IS_MODAL_CURSOR_REGION;
- ED_region_tag_redraw(p->ar);
- }
- }
-
- /* handle mode-specific events */
- if (p->status == GP_STATUS_PAINTING) {
- /* 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"); */
-
- if (((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) || (guide->use_guide)) {
- gpencil_add_missing_events(C, op, event, p);
- }
-
- gpencil_draw_apply_event(C, op, event, CTX_data_depsgraph(C), 0.0f, 0.0f);
-
- /* finish painting operation if anything went wrong just now */
- if (p->status == GP_STATUS_ERROR) {
- printf("\t\t\t\tGP - add error done!\n");
- estate = OPERATOR_CANCELLED;
- }
- 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"); */
- switch (event->type) {
- case WHEELDOWNMOUSE: /* larger */
- case PADPLUSKEY:
- p->radius += 5;
- break;
-
- case WHEELUPMOUSE: /* smaller */
- case PADMINUS:
- p->radius -= 5;
-
- if (p->radius <= 0)
- p->radius = 1;
- break;
- }
-
- /* force refresh */
- /* just active area for now, since doing whole screen is too slow */
- ED_region_tag_redraw(p->ar);
-
- /* event handled, so just tag as running modal */
- estate = OPERATOR_RUNNING_MODAL;
- }
- /* there shouldn't be any other events, but just in case there are, let's swallow them
- * (i.e. to prevent problems with undo)
- */
- else {
- /* swallow event to save ourselves trouble */
- estate = OPERATOR_RUNNING_MODAL;
- }
- }
-
- /* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */
- if (0 == gpencil_area_exists(C, p->sa))
- 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 */
- switch (estate) {
- case OPERATOR_FINISHED:
- /* store stroke angle for parallel guide */
- if ((p->straight == 0) || (guide->use_guide && (guide->type == GP_GUIDE_CIRCULAR))) {
- float xy[2];
- sub_v2_v2v2(xy, p->mval, p->mvali);
- float angle = atan2f(xy[1], xy[0]);
- RNA_float_set(op->ptr, "guide_last_angle", angle);
- }
- /* one last flush before we're done */
- gpencil_draw_exit(C, op);
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
- break;
-
- case OPERATOR_CANCELLED:
- gpencil_draw_exit(C, op);
- break;
-
- case OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH:
- /* event doesn't need to be handled */
+ tGPsdata *p = op->customdata;
+ 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. */
+ int estate = OPERATOR_PASS_THROUGH;
+
+ /* if (event->type == NDOF_MOTION)
+ * return OPERATOR_PASS_THROUGH;
+ * -------------------------------
+ * [mce] Not quite what I was looking
+ * for, but a good start! GP continues to
+ * draw on the screen while the 3D mouse
+ * moves the viewpoint. Problem is that
+ * the stroke is converted to 3D only after
+ * it is finished. This approach should work
+ * better in tools that immediately apply
+ * in 3D space.
+ */
+
+ if (p->status == GP_STATUS_IDLING) {
+ ARegion *ar = CTX_wm_region(C);
+ p->ar = ar;
+ }
+
+ /* special mode for editing control points */
+ if (p->paintmode == GP_PAINTMODE_SET_CP) {
+ wmWindow *win = p->win;
+ WM_cursor_modal_set(win, BC_NSEW_SCROLLCURSOR);
+ bool drawmode = false;
+
+ switch (event->type) {
+ /* cancel */
+ case ESCKEY:
+ case RIGHTMOUSE: {
+ if (ELEM(event->val, KM_RELEASE)) {
+ drawmode = true;
+ }
+ break;
+ }
+ /* set */
+ case LEFTMOUSE: {
+ if (ELEM(event->val, KM_RELEASE)) {
+ gp_origin_set(op, event->mval);
+ drawmode = true;
+ }
+ break;
+ }
+ }
+ if (drawmode) {
+ p->status = GP_STATUS_IDLING;
+ p->paintmode = GP_PAINTMODE_DRAW;
+ ED_gpencil_toggle_brush_cursor(C, true, NULL);
+ DEG_id_tag_update(&p->scene->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ else {
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+
+ /* 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)) {
+ /* 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)) {
+ /* 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)) {
+ /* 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
+ */
+ WM_operator_name_call(C, "GPENCIL_OT_blank_frame_add", WM_OP_EXEC_DEFAULT, NULL);
+ estate = OPERATOR_RUNNING_MODAL;
+ }
+ else if ((!ELEM(p->paintmode, GP_PAINTMODE_ERASER, GP_PAINTMODE_SET_CP))) {
+ gpencil_guide_event_handling(C, op, event, p);
+ estate = OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ estate = OPERATOR_RUNNING_MODAL;
+ }
+ }
+
+ //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 [#32647]
+ */
+ /* 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);
+ }
+ }
+ }
+
+ 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)
+ * (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;
+ }
+ }
+ else if (event->val == KM_PRESS) {
+ bool in_bounds = false;
+
+ /* Check if we're outside the bounds of the active region
+ * 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)) {
+ /* 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);
+
+ if (G.debug & G_DEBUG) {
+ printf("found alternative region %p (old was %p) - at %d %d (sa: %d %d -> %d %d)\n",
+ current_region,
+ p->ar,
+ event->x,
+ event->y,
+ p->sa->totrct.xmin,
+ p->sa->totrct.ymin,
+ p->sa->totrct.xmax,
+ p->sa->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;
+ in_bounds = true;
+ }
+ else {
+ /* Out of bounds, or invalid in some other way */
+ p->status = GP_STATUS_ERROR;
+ estate = OPERATOR_CANCELLED;
+
+ if (G.debug & G_DEBUG)
+ printf("%s: Region under cursor is out of bounds, so cannot be drawn on\n", __func__);
+ }
+ }
+ else if (p->ar) {
+ rcti region_rect;
+
+ /* Perform bounds check using */
+ ED_region_visible_rect(p->ar, &region_rect);
+ in_bounds = BLI_rcti_isect_pt_v(&region_rect, event->mval);
+ }
+ else {
+ /* No region */
+ p->status = GP_STATUS_ERROR;
+ estate = OPERATOR_CANCELLED;
+
+ if (G.debug & G_DEBUG)
+ printf("%s: No active region found in GP Paint session data\n", __func__);
+ }
+
+ if (in_bounds) {
+ /* Switch paintmode (temporarily if need be) based on which button was used
+ * NOTE: This is to make it more convenient to erase strokes when using drawing sessions
+ */
+ if ((event->type == RIGHTMOUSE) || gpencil_is_tablet_eraser_active(event)) {
+ /* turn on eraser */
+ p->paintmode = GP_PAINTMODE_ERASER;
+ }
+ else if (event->type == LEFTMOUSE) {
+ /* restore drawmode to default */
+ p->paintmode = RNA_enum_get(op->ptr, "mode");
+ }
+
+ gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER);
+
+ /* not painting, so start stroke (this should be mouse-button down) */
+ p = gpencil_stroke_begin(C, op);
+
+ if (p->status == GP_STATUS_ERROR) {
+ estate = OPERATOR_CANCELLED;
+ }
+ }
+ else if (p->status != GP_STATUS_ERROR) {
+ /* User clicked outside bounds of window while idling, so exit paintmode
+ * 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;
+ }
+ }
+ else if (event->val == KM_RELEASE) {
+ p->status = GP_STATUS_IDLING;
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+ ED_region_tag_redraw(p->ar);
+ }
+ }
+
+ /* handle mode-specific events */
+ if (p->status == GP_STATUS_PAINTING) {
+ /* 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"); */
+
+ if (((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) || (guide->use_guide)) {
+ gpencil_add_missing_events(C, op, event, p);
+ }
+
+ gpencil_draw_apply_event(C, op, event, CTX_data_depsgraph(C), 0.0f, 0.0f);
+
+ /* finish painting operation if anything went wrong just now */
+ if (p->status == GP_STATUS_ERROR) {
+ printf("\t\t\t\tGP - add error done!\n");
+ estate = OPERATOR_CANCELLED;
+ }
+ 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"); */
+ switch (event->type) {
+ case WHEELDOWNMOUSE: /* larger */
+ case PADPLUSKEY:
+ p->radius += 5;
+ break;
+
+ case WHEELUPMOUSE: /* smaller */
+ case PADMINUS:
+ p->radius -= 5;
+
+ if (p->radius <= 0)
+ p->radius = 1;
+ break;
+ }
+
+ /* force refresh */
+ /* just active area for now, since doing whole screen is too slow */
+ ED_region_tag_redraw(p->ar);
+
+ /* event handled, so just tag as running modal */
+ estate = OPERATOR_RUNNING_MODAL;
+ }
+ /* there shouldn't be any other events, but just in case there are, let's swallow them
+ * (i.e. to prevent problems with undo)
+ */
+ else {
+ /* swallow event to save ourselves trouble */
+ estate = OPERATOR_RUNNING_MODAL;
+ }
+ }
+
+ /* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */
+ if (0 == gpencil_area_exists(C, p->sa))
+ 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 */
+ switch (estate) {
+ case OPERATOR_FINISHED:
+ /* store stroke angle for parallel guide */
+ if ((p->straight == 0) || (guide->use_guide && (guide->type == GP_GUIDE_CIRCULAR))) {
+ float xy[2];
+ sub_v2_v2v2(xy, p->mval, p->mvali);
+ float angle = atan2f(xy[1], xy[0]);
+ RNA_float_set(op->ptr, "guide_last_angle", angle);
+ }
+ /* one last flush before we're done */
+ gpencil_draw_exit(C, op);
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+ break;
+
+ case OPERATOR_CANCELLED:
+ gpencil_draw_exit(C, op);
+ break;
+
+ 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);
+ printf("unhandled event -> %d (mmb? = %d | mmv? = %d)\n",
+ event->type, event->type == MIDDLEMOUSE, event->type == MOUSEMOVE);
#endif
- break;
- }
+ break;
+ }
- /* return status code */
- return estate;
+ /* return status code */
+ return estate;
}
/* ------------------------------- */
static const EnumPropertyItem prop_gpencil_drawmodes[] = {
- {GP_PAINTMODE_DRAW, "DRAW", 0, "Draw Freehand", "Draw freehand stroke(s)"},
- {GP_PAINTMODE_DRAW_STRAIGHT, "DRAW_STRAIGHT", 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},
+ {GP_PAINTMODE_DRAW, "DRAW", 0, "Draw Freehand", "Draw freehand stroke(s)"},
+ {GP_PAINTMODE_DRAW_STRAIGHT,
+ "DRAW_STRAIGHT",
+ 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},
};
void GPENCIL_OT_draw(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Grease Pencil Draw";
- ot->idname = "GPENCIL_OT_draw";
- ot->description = "Draw a new stroke in the active Grease Pencil Object";
-
- /* api callbacks */
- ot->exec = gpencil_draw_exec;
- ot->invoke = gpencil_draw_invoke;
- ot->modal = gpencil_draw_modal;
- ot->cancel = gpencil_draw_cancel;
- ot->poll = gpencil_draw_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* settings for drawing */
- ot->prop = RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements");
-
- prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
-
- /* NOTE: wait for input is enabled by default,
- * so that all UI code can work properly without needing users to know about this */
- prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "Wait for first click instead of painting immediately");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
-
- prop = RNA_def_boolean(ot->srna, "disable_straight", false, "No Straight lines", "Disable key for straight lines");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- prop = RNA_def_boolean(ot->srna, "disable_fill", false, "No Fill Areas", "Disable fill to use stroke as fill boundary");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- /* guides */
- prop = RNA_def_float(ot->srna, "guide_last_angle", 0.0f, -10000.0f, 10000.0f, "Angle", "Speed guide angle", -10000.0f, 10000.0f);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Grease Pencil Draw";
+ ot->idname = "GPENCIL_OT_draw";
+ ot->description = "Draw a new stroke in the active Grease Pencil Object";
+
+ /* api callbacks */
+ ot->exec = gpencil_draw_exec;
+ ot->invoke = gpencil_draw_invoke;
+ ot->modal = gpencil_draw_modal;
+ ot->cancel = gpencil_draw_cancel;
+ ot->poll = gpencil_draw_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* settings for drawing */
+ ot->prop = RNA_def_enum(
+ ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements");
+
+ prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ /* NOTE: wait for input is enabled by default,
+ * so that all UI code can work properly without needing users to know about this */
+ prop = RNA_def_boolean(ot->srna,
+ "wait_for_input",
+ true,
+ "Wait for Input",
+ "Wait for first click instead of painting immediately");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(
+ ot->srna, "disable_straight", false, "No Straight lines", "Disable key for straight lines");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(ot->srna,
+ "disable_fill",
+ false,
+ "No Fill Areas",
+ "Disable fill to use stroke as fill boundary");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ /* guides */
+ prop = RNA_def_float(ot->srna,
+ "guide_last_angle",
+ 0.0f,
+ -10000.0f,
+ 10000.0f,
+ "Angle",
+ "Speed guide angle",
+ -10000.0f,
+ 10000.0f);
}
/* additional OPs */
static int gpencil_guide_rotate(bContext *C, wmOperator *op)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- GP_Sculpt_Guide *guide = &ts->gp_sculpt.guide;
- float angle = RNA_float_get(op->ptr, "angle");
- bool increment = RNA_boolean_get(op->ptr, "increment");
- if (increment) {
- float oldangle = guide->angle;
- oldangle += angle;
- guide->angle = angle_compat_rad(oldangle, M_PI);
- }
- else {
- guide->angle = angle_compat_rad(angle, M_PI);
- }
-
- return OPERATOR_FINISHED;
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ GP_Sculpt_Guide *guide = &ts->gp_sculpt.guide;
+ float angle = RNA_float_get(op->ptr, "angle");
+ bool increment = RNA_boolean_get(op->ptr, "increment");
+ if (increment) {
+ float oldangle = guide->angle;
+ oldangle += angle;
+ guide->angle = angle_compat_rad(oldangle, M_PI);
+ }
+ else {
+ guide->angle = angle_compat_rad(angle, M_PI);
+ }
+
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_guide_rotate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Rotate Guide Angle";
- ot->idname = "GPENCIL_OT_guide_rotate";
- ot->description = "Rotate guide angle";
+ /* identifiers */
+ ot->name = "Rotate Guide Angle";
+ ot->idname = "GPENCIL_OT_guide_rotate";
+ ot->description = "Rotate guide angle";
- /* api callbacks */
- ot->exec = gpencil_guide_rotate;
+ /* api callbacks */
+ ot->exec = gpencil_guide_rotate;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- PropertyRNA *prop;
+ PropertyRNA *prop;
- prop = RNA_def_boolean(ot->srna, "increment", true, "Increment", "Increment angle");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_float(ot->srna, "angle", 0.0f, -10000.0f, 10000.0f, "Angle", "Guide angle", -10000.0f, 10000.0f);
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_boolean(ot->srna, "increment", true, "Increment", "Increment angle");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_float(
+ ot->srna, "angle", 0.0f, -10000.0f, 10000.0f, "Angle", "Guide angle", -10000.0f, 10000.0f);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index 374dbbf4d9c..f178d232376 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -97,193 +97,201 @@
#define SELECT_CP2 3
#define SELECT_END 4
-#define BIG_SIZE_CTL 15
-#define MID_SIZE_CTL 10
-#define SMALL_SIZE_CTL 8
+#define BIG_SIZE_CTL 15
+#define MID_SIZE_CTL 10
+#define SMALL_SIZE_CTL 8
#define MOVE_NONE 0
#define MOVE_ENDS 1
#define MOVE_CP 2
- /* ************************************************ */
- /* Core/Shared Utilities */
+/* ************************************************ */
+/* Core/Shared Utilities */
/* clear the session buffers (call this before AND after a paint operation) */
static void gp_session_validatebuffer(tGPDprimitive *p)
{
- bGPdata *gpd = p->gpd;
-
- /* clear memory of buffer (or allocate it if starting a new session) */
- if (gpd->runtime.sbuffer) {
- memset(gpd->runtime.sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX);
- }
- else {
- gpd->runtime.sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer");
- }
-
- /* reset indices */
- gpd->runtime.sbuffer_size = 0;
-
- /* reset flags */
- gpd->runtime.sbuffer_sflag = 0;
- gpd->runtime.sbuffer_sflag |= GP_STROKE_3DSPACE;
-
- if (ELEM(p->type, GP_STROKE_BOX, GP_STROKE_CIRCLE))
- gpd->runtime.sbuffer_sflag |= GP_STROKE_CYCLIC;
+ bGPdata *gpd = p->gpd;
+
+ /* clear memory of buffer (or allocate it if starting a new session) */
+ if (gpd->runtime.sbuffer) {
+ memset(gpd->runtime.sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX);
+ }
+ else {
+ gpd->runtime.sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX,
+ "gp_session_strokebuffer");
+ }
+
+ /* reset indices */
+ gpd->runtime.sbuffer_size = 0;
+
+ /* reset flags */
+ gpd->runtime.sbuffer_sflag = 0;
+ gpd->runtime.sbuffer_sflag |= GP_STROKE_3DSPACE;
+
+ if (ELEM(p->type, GP_STROKE_BOX, GP_STROKE_CIRCLE))
+ gpd->runtime.sbuffer_sflag |= GP_STROKE_CYCLIC;
}
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);
-
- /* 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;
- }
+ 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);
+
+ /* 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;
+ }
}
/* Helper to square a primitive */
static void gpencil_primitive_to_square(tGPDprimitive *tgpi, const float x, const float y)
{
- float w = fabsf(x);
- float h = fabsf(y);
- if ((x > 0 && y > 0) || (x < 0 && y < 0)) {
- if (w > h)
- tgpi->end[1] = tgpi->origin[1] + x;
- else
- tgpi->end[0] = tgpi->origin[0] + y;
- }
- else {
- if (w > h)
- tgpi->end[1] = tgpi->origin[1] - x;
- else
- tgpi->end[0] = tgpi->origin[0] - y;
- }
+ float w = fabsf(x);
+ float h = fabsf(y);
+ if ((x > 0 && y > 0) || (x < 0 && y < 0)) {
+ if (w > h)
+ tgpi->end[1] = tgpi->origin[1] + x;
+ else
+ tgpi->end[0] = tgpi->origin[0] + y;
+ }
+ else {
+ if (w > h)
+ tgpi->end[1] = tgpi->origin[1] - x;
+ else
+ tgpi->end[0] = tgpi->origin[0] - y;
+ }
}
/* Helper to rotate point around origin */
-static void gp_rotate_v2_v2v2fl(float v[2], const float p[2], const float origin[2], const float angle)
+static void gp_rotate_v2_v2v2fl(float v[2],
+ const float p[2],
+ const float origin[2],
+ const float angle)
{
- float pt[2];
- float r[2];
- sub_v2_v2v2(pt, p, origin);
- rotate_v2_v2fl(r, pt, angle);
- add_v2_v2v2(v, r, origin);
+ float pt[2];
+ float r[2];
+ sub_v2_v2v2(pt, p, origin);
+ rotate_v2_v2fl(r, pt, angle);
+ add_v2_v2v2(v, r, origin);
}
/* Helper to rotate line around line centre */
-static void gp_primitive_rotate_line(float va[2], float vb[2], const float a[2], const float b[2], const float angle)
+static void gp_primitive_rotate_line(
+ float va[2], float vb[2], const float a[2], const float b[2], const float angle)
{
- float midpoint[2];
- mid_v2_v2v2(midpoint, a, b);
- gp_rotate_v2_v2v2fl(va, a, midpoint, angle);
- gp_rotate_v2_v2v2fl(vb, b, midpoint, angle);
+ float midpoint[2];
+ mid_v2_v2v2(midpoint, a, b);
+ gp_rotate_v2_v2v2fl(va, a, midpoint, angle);
+ gp_rotate_v2_v2v2fl(vb, b, midpoint, angle);
}
/* Helper to update cps */
static void gp_primitive_update_cps(tGPDprimitive *tgpi)
{
- if (!tgpi->curve) {
- mid_v2_v2v2(tgpi->midpoint, tgpi->start, tgpi->end);
- copy_v2_v2(tgpi->cp1, tgpi->midpoint);
- copy_v2_v2(tgpi->cp2, tgpi->cp1);
- }
- else if (tgpi->type == GP_STROKE_CURVE) {
- mid_v2_v2v2(tgpi->midpoint, tgpi->start, tgpi->end);
- copy_v2_v2(tgpi->cp1, tgpi->midpoint);
- copy_v2_v2(tgpi->cp2, tgpi->cp1);
- }
- else if (tgpi->type == GP_STROKE_ARC) {
- if (tgpi->flip) {
- gp_primitive_rotate_line(tgpi->cp1, tgpi->cp2, tgpi->start, tgpi->end, M_PI_2);
- }
- else {
- gp_primitive_rotate_line(tgpi->cp1, tgpi->cp2, tgpi->end, tgpi->start, M_PI_2);
- }
- }
+ if (!tgpi->curve) {
+ mid_v2_v2v2(tgpi->midpoint, tgpi->start, tgpi->end);
+ copy_v2_v2(tgpi->cp1, tgpi->midpoint);
+ copy_v2_v2(tgpi->cp2, tgpi->cp1);
+ }
+ else if (tgpi->type == GP_STROKE_CURVE) {
+ mid_v2_v2v2(tgpi->midpoint, tgpi->start, tgpi->end);
+ copy_v2_v2(tgpi->cp1, tgpi->midpoint);
+ copy_v2_v2(tgpi->cp2, tgpi->cp1);
+ }
+ else if (tgpi->type == GP_STROKE_ARC) {
+ if (tgpi->flip) {
+ gp_primitive_rotate_line(tgpi->cp1, tgpi->cp2, tgpi->start, tgpi->end, M_PI_2);
+ }
+ else {
+ gp_primitive_rotate_line(tgpi->cp1, tgpi->cp2, tgpi->end, tgpi->start, M_PI_2);
+ }
+ }
}
/* 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])
+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]);
+ 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 */
+/* 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) {
- return 0;
- }
-
- /* need data to create primitive */
- bGPdata *gpd = CTX_data_gpencil_data(C);
- if (gpd == NULL) {
- return 0;
- }
-
- /* only in edit and paint modes
- * - paint as it's the "drawing/creation mode"
- * - edit as this is more of an atomic editing operation
- * (similar to copy/paste), and also for consistency
- */
- if ((gpd->flag & (GP_DATA_STROKE_PAINTMODE | GP_DATA_STROKE_EDITMODE)) == 0) {
- CTX_wm_operator_poll_msg_set(C, "Primitives can only be added in Draw or Edit modes");
- return 0;
- }
-
- /* 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);
- 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");
- return 0;
- }
-
- return 1;
+ /* only 3D view */
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa && sa->spacetype != SPACE_VIEW3D) {
+ return 0;
+ }
+
+ /* need data to create primitive */
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ if (gpd == NULL) {
+ return 0;
+ }
+
+ /* only in edit and paint modes
+ * - paint as it's the "drawing/creation mode"
+ * - edit as this is more of an atomic editing operation
+ * (similar to copy/paste), and also for consistency
+ */
+ if ((gpd->flag & (GP_DATA_STROKE_PAINTMODE | GP_DATA_STROKE_EDITMODE)) == 0) {
+ CTX_wm_operator_poll_msg_set(C, "Primitives can only be added in Draw or Edit modes");
+ return 0;
+ }
+
+ /* 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);
+ 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");
+ return 0;
+ }
+
+ return 1;
}
/* Allocate memory to stroke, adds MAX_EDGES on every call */
static void gpencil_primitive_allocate_memory(tGPDprimitive *tgpi)
{
- tgpi->point_count += (tgpi->type == GP_STROKE_BOX) ? (MAX_EDGES * 4 + 1) : (MAX_EDGES + 1);
- bGPDstroke *gpsf = tgpi->gpf->strokes.first;
- gpsf->points = MEM_reallocN(gpsf->points, sizeof(bGPDspoint) * tgpi->point_count);
- if (gpsf->dvert != NULL)
- gpsf->dvert = MEM_reallocN(gpsf->dvert, sizeof(MDeformVert) * tgpi->point_count);
- tgpi->points = MEM_reallocN(tgpi->points, sizeof(tGPspoint) * tgpi->point_count);
+ tgpi->point_count += (tgpi->type == GP_STROKE_BOX) ? (MAX_EDGES * 4 + 1) : (MAX_EDGES + 1);
+ bGPDstroke *gpsf = tgpi->gpf->strokes.first;
+ gpsf->points = MEM_reallocN(gpsf->points, sizeof(bGPDspoint) * tgpi->point_count);
+ if (gpsf->dvert != NULL)
+ gpsf->dvert = MEM_reallocN(gpsf->dvert, sizeof(MDeformVert) * tgpi->point_count);
+ tgpi->points = MEM_reallocN(tgpi->points, sizeof(tGPspoint) * tgpi->point_count);
}
/* ****************** Primitive Interactive *********************** */
@@ -291,1510 +299,1511 @@ static void gpencil_primitive_allocate_memory(tGPDprimitive *tgpi)
/* Helper: Create internal strokes primitives data */
static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
-
- bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
-
- /* if brush doesn't exist, create a new one */
- Paint *paint = &ts->gp_paint->paint;
- /* if not exist, create a new one */
- if (paint->brush == NULL) {
- /* create new brushes */
- BKE_brush_gpencil_presets(C);
- }
- tgpi->brush = paint->brush;
-
- /* if layer doesn't exist, create a new one */
- if (gpl == NULL) {
- gpl = BKE_gpencil_layer_addnew(tgpi->gpd, DATA_("Primitives"), true);
- }
- tgpi->gpl = gpl;
-
- /* create a new temporary frame */
- tgpi->gpf = MEM_callocN(sizeof(bGPDframe), "Temp bGPDframe");
- tgpi->gpf->framenum = tgpi->cframe = cfra_eval;
-
- /* 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->inittime = 0.0f;
-
- /* enable recalculation flag by default */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->flag &= ~GP_STROKE_SELECT;
- /* the polygon must be closed, so enabled cyclic */
- if (ELEM(tgpi->type, GP_STROKE_BOX, GP_STROKE_CIRCLE)) {
- gps->flag |= GP_STROKE_CYCLIC;
- }
-
- gps->flag |= GP_STROKE_3DSPACE;
-
- gps->mat_nr = BKE_gpencil_object_material_get_index(tgpi->ob, tgpi->mat);
-
- /* allocate memory for storage points, but keep empty */
- gps->totpoints = 0;
- gps->points = MEM_callocN(sizeof(bGPDspoint), "gp_stroke_points");
- /* 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);
-
- /* allocate memory for storage points */
- gpencil_primitive_allocate_memory(tgpi);
-
- /* Random generator, only init once. */
- uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
- tgpi->rng = BLI_rng_new(rng_seed);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+
+ /* if brush doesn't exist, create a new one */
+ Paint *paint = &ts->gp_paint->paint;
+ /* if not exist, create a new one */
+ if (paint->brush == NULL) {
+ /* create new brushes */
+ BKE_brush_gpencil_presets(C);
+ }
+ tgpi->brush = paint->brush;
+
+ /* if layer doesn't exist, create a new one */
+ if (gpl == NULL) {
+ gpl = BKE_gpencil_layer_addnew(tgpi->gpd, DATA_("Primitives"), true);
+ }
+ tgpi->gpl = gpl;
+
+ /* create a new temporary frame */
+ tgpi->gpf = MEM_callocN(sizeof(bGPDframe), "Temp bGPDframe");
+ tgpi->gpf->framenum = tgpi->cframe = cfra_eval;
+
+ /* 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->inittime = 0.0f;
+
+ /* enable recalculation flag by default */
+ gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gps->flag &= ~GP_STROKE_SELECT;
+ /* the polygon must be closed, so enabled cyclic */
+ if (ELEM(tgpi->type, GP_STROKE_BOX, GP_STROKE_CIRCLE)) {
+ gps->flag |= GP_STROKE_CYCLIC;
+ }
+
+ gps->flag |= GP_STROKE_3DSPACE;
+
+ gps->mat_nr = BKE_gpencil_object_material_get_index(tgpi->ob, tgpi->mat);
+
+ /* allocate memory for storage points, but keep empty */
+ gps->totpoints = 0;
+ gps->points = MEM_callocN(sizeof(bGPDspoint), "gp_stroke_points");
+ /* 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);
+
+ /* allocate memory for storage points */
+ gpencil_primitive_allocate_memory(tgpi);
+
+ /* Random generator, only init once. */
+ uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
+ tgpi->rng = BLI_rng_new(rng_seed);
}
/* add new segment to curve */
static void gpencil_primitive_add_segment(tGPDprimitive *tgpi)
{
- if (tgpi->tot_stored_edges > 0) {
- tgpi->tot_stored_edges += (tgpi->tot_edges - 1);
- }
- else {
- tgpi->tot_stored_edges += tgpi->tot_edges;
- }
- gpencil_primitive_allocate_memory(tgpi);
+ if (tgpi->tot_stored_edges > 0) {
+ tgpi->tot_stored_edges += (tgpi->tot_edges - 1);
+ }
+ else {
+ tgpi->tot_stored_edges += tgpi->tot_edges;
+ }
+ gpencil_primitive_allocate_memory(tgpi);
}
/* Helper: set control point */
static void gp_primitive_set_cp(tGPDprimitive *tgpi, float p[2], float color[4], int size)
{
- if (tgpi->flag == IN_PROGRESS) {
- return;
- }
-
- bGPDcontrolpoint *cp_points = tgpi->gpd->runtime.cp_points;
-
- if (tgpi->gpd->runtime.tot_cp_points < MAX_CP) {
- CLAMP(size, 5, 20);
- bGPDcontrolpoint *cp = &cp_points[tgpi->gpd->runtime.tot_cp_points];
- copy_v2_v2(&cp->x, p);
- copy_v4_v4(cp->color, color);
- color[3] = 0.8f;
- cp->size = size;
- tgpi->gpd->runtime.tot_cp_points += 1;
- }
+ if (tgpi->flag == IN_PROGRESS) {
+ return;
+ }
+
+ bGPDcontrolpoint *cp_points = tgpi->gpd->runtime.cp_points;
+
+ if (tgpi->gpd->runtime.tot_cp_points < MAX_CP) {
+ CLAMP(size, 5, 20);
+ bGPDcontrolpoint *cp = &cp_points[tgpi->gpd->runtime.tot_cp_points];
+ copy_v2_v2(&cp->x, p);
+ copy_v4_v4(cp->color, color);
+ color[3] = 0.8f;
+ cp->size = size;
+ tgpi->gpd->runtime.tot_cp_points += 1;
+ }
}
/* Helper: Draw status message while the user is running the operator */
static void gpencil_primitive_status_indicators(bContext *C, tGPDprimitive *tgpi)
{
- Scene *scene = tgpi->scene;
- char status_str[UI_MAX_DRAW_STR];
- char msg_str[UI_MAX_DRAW_STR];
-
- if (tgpi->type == GP_STROKE_LINE) {
- BLI_strncpy(
- msg_str,
- IFACE_("Line: ESC to cancel, LMB set origin, Enter/MMB to confirm, WHEEL/+- to adjust subdivision number, Shift to align, Alt to center, E: extrude"),
- UI_MAX_DRAW_STR);
- }
- else if (tgpi->type == GP_STROKE_BOX) {
- BLI_strncpy(
- msg_str,
- IFACE_("Rectangle: ESC to cancel, LMB set origin, Enter/MMB to confirm, WHEEL/+- to adjust subdivision number, Shift to square, Alt to center"),
- UI_MAX_DRAW_STR);
- }
- else if (tgpi->type == GP_STROKE_CIRCLE) {
- BLI_strncpy(
- msg_str,
- IFACE_("Circle: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust edge number, Shift to square, Alt to center"),
- UI_MAX_DRAW_STR);
- }
- else if (tgpi->type == GP_STROKE_ARC) {
- BLI_strncpy(
- msg_str,
- IFACE_("Arc: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust edge number, Shift to square, Alt to center, M: Flip, E: extrude"),
- UI_MAX_DRAW_STR);
- }
- else if (tgpi->type == GP_STROKE_CURVE) {
- BLI_strncpy(
- msg_str,
- IFACE_("Curve: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust edge number, Shift to square, Alt to center, E: extrude"),
- UI_MAX_DRAW_STR);
- }
-
- if (ELEM(tgpi->type, GP_STROKE_CIRCLE, GP_STROKE_ARC, GP_STROKE_LINE, GP_STROKE_BOX)) {
- if (hasNumInput(&tgpi->num)) {
- char str_offs[NUM_STR_REP_LEN];
-
- outputNumInput(&tgpi->num, str_offs, &scene->unit);
- BLI_snprintf(status_str, sizeof(status_str), "%s: %s", msg_str, str_offs);
- }
- else {
- if (tgpi->flag == IN_PROGRESS) {
- BLI_snprintf(
- status_str, sizeof(status_str), "%s: %d (%d, %d) (%d, %d)", msg_str, tgpi->tot_edges,
- (int)tgpi->start[0], (int)tgpi->start[1], (int)tgpi->end[0], (int)tgpi->end[1]);
- }
- else {
- BLI_snprintf(
- status_str, sizeof(status_str), "%s: %d (%d, %d)", msg_str, tgpi->tot_edges,
- (int)tgpi->end[0], (int)tgpi->end[1]);
- }
- }
- }
- else {
- if (tgpi->flag == IN_PROGRESS) {
- BLI_snprintf(
- status_str, sizeof(status_str), "%s: %d (%d, %d) (%d, %d)", msg_str, tgpi->tot_edges,
- (int)tgpi->start[0], (int)tgpi->start[1], (int)tgpi->end[0], (int)tgpi->end[1]);
- }
- else {
- BLI_snprintf(
- status_str, sizeof(status_str), "%s: (%d, %d)", msg_str,
- (int)tgpi->end[0], (int)tgpi->end[1]);
- }
- }
- ED_workspace_status_text(C, status_str);
+ Scene *scene = tgpi->scene;
+ char status_str[UI_MAX_DRAW_STR];
+ char msg_str[UI_MAX_DRAW_STR];
+
+ if (tgpi->type == GP_STROKE_LINE) {
+ BLI_strncpy(msg_str,
+ IFACE_("Line: ESC to cancel, LMB set origin, Enter/MMB to confirm, WHEEL/+- to "
+ "adjust subdivision number, Shift to align, Alt to center, E: extrude"),
+ UI_MAX_DRAW_STR);
+ }
+ else if (tgpi->type == GP_STROKE_BOX) {
+ BLI_strncpy(msg_str,
+ IFACE_("Rectangle: ESC to cancel, LMB set origin, Enter/MMB to confirm, WHEEL/+- "
+ "to adjust subdivision number, Shift to square, Alt to center"),
+ UI_MAX_DRAW_STR);
+ }
+ else if (tgpi->type == GP_STROKE_CIRCLE) {
+ BLI_strncpy(msg_str,
+ IFACE_("Circle: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust edge "
+ "number, Shift to square, Alt to center"),
+ UI_MAX_DRAW_STR);
+ }
+ else if (tgpi->type == GP_STROKE_ARC) {
+ BLI_strncpy(msg_str,
+ IFACE_("Arc: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust edge number, "
+ "Shift to square, Alt to center, M: Flip, E: extrude"),
+ UI_MAX_DRAW_STR);
+ }
+ else if (tgpi->type == GP_STROKE_CURVE) {
+ BLI_strncpy(msg_str,
+ IFACE_("Curve: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust edge "
+ "number, Shift to square, Alt to center, E: extrude"),
+ UI_MAX_DRAW_STR);
+ }
+
+ if (ELEM(tgpi->type, GP_STROKE_CIRCLE, GP_STROKE_ARC, GP_STROKE_LINE, GP_STROKE_BOX)) {
+ if (hasNumInput(&tgpi->num)) {
+ char str_offs[NUM_STR_REP_LEN];
+
+ outputNumInput(&tgpi->num, str_offs, &scene->unit);
+ BLI_snprintf(status_str, sizeof(status_str), "%s: %s", msg_str, str_offs);
+ }
+ else {
+ if (tgpi->flag == IN_PROGRESS) {
+ BLI_snprintf(status_str,
+ sizeof(status_str),
+ "%s: %d (%d, %d) (%d, %d)",
+ msg_str,
+ tgpi->tot_edges,
+ (int)tgpi->start[0],
+ (int)tgpi->start[1],
+ (int)tgpi->end[0],
+ (int)tgpi->end[1]);
+ }
+ else {
+ BLI_snprintf(status_str,
+ sizeof(status_str),
+ "%s: %d (%d, %d)",
+ msg_str,
+ tgpi->tot_edges,
+ (int)tgpi->end[0],
+ (int)tgpi->end[1]);
+ }
+ }
+ }
+ else {
+ if (tgpi->flag == IN_PROGRESS) {
+ BLI_snprintf(status_str,
+ sizeof(status_str),
+ "%s: %d (%d, %d) (%d, %d)",
+ msg_str,
+ tgpi->tot_edges,
+ (int)tgpi->start[0],
+ (int)tgpi->start[1],
+ (int)tgpi->end[0],
+ (int)tgpi->end[1]);
+ }
+ else {
+ BLI_snprintf(status_str,
+ sizeof(status_str),
+ "%s: (%d, %d)",
+ msg_str,
+ (int)tgpi->end[0],
+ (int)tgpi->end[1]);
+ }
+ }
+ ED_workspace_status_text(C, status_str);
}
/* create a rectangle */
static void gp_primitive_rectangle(tGPDprimitive *tgpi, tGPspoint *points2D)
{
- float coords[5][2];
-
- coords[0][0] = tgpi->start[0];
- coords[0][1] = tgpi->start[1];
- coords[1][0] = tgpi->end[0];
- coords[1][1] = tgpi->start[1];
- coords[2][0] = tgpi->end[0];
- coords[2][1] = tgpi->end[1];
- coords[3][0] = tgpi->start[0];
- coords[3][1] = tgpi->end[1];
- coords[4][0] = tgpi->start[0];
- coords[4][1] = tgpi->start[1];
-
- const float step = 1.0f / (float)(tgpi->tot_edges);
- int i = tgpi->tot_stored_edges;
-
- for (int j = 0; j < 4; j++) {
- float a = 0.0f;
- for (int k = 0; k < tgpi->tot_edges; k++) {
- tGPspoint *p2d = &points2D[i];
- interp_v2_v2v2(&p2d->x, coords[j], coords[j + 1], a);
- a += step;
- i++;
- }
- }
-
- mid_v2_v2v2(tgpi->midpoint, tgpi->start, tgpi->end);
- float color[4];
- UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color);
- gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL);
- if (tgpi->tot_stored_edges) {
- UI_GetThemeColor4fv(TH_REDALERT, color);
- gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL);
- }
- else {
- gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL);
- }
- UI_GetThemeColor4fv(TH_REDALERT, color);
- gp_primitive_set_cp(tgpi, tgpi->midpoint, color, SMALL_SIZE_CTL);
+ float coords[5][2];
+
+ coords[0][0] = tgpi->start[0];
+ coords[0][1] = tgpi->start[1];
+ coords[1][0] = tgpi->end[0];
+ coords[1][1] = tgpi->start[1];
+ coords[2][0] = tgpi->end[0];
+ coords[2][1] = tgpi->end[1];
+ coords[3][0] = tgpi->start[0];
+ coords[3][1] = tgpi->end[1];
+ coords[4][0] = tgpi->start[0];
+ coords[4][1] = tgpi->start[1];
+
+ const float step = 1.0f / (float)(tgpi->tot_edges);
+ int i = tgpi->tot_stored_edges;
+
+ for (int j = 0; j < 4; j++) {
+ float a = 0.0f;
+ for (int k = 0; k < tgpi->tot_edges; k++) {
+ tGPspoint *p2d = &points2D[i];
+ interp_v2_v2v2(&p2d->x, coords[j], coords[j + 1], a);
+ a += step;
+ i++;
+ }
+ }
+
+ mid_v2_v2v2(tgpi->midpoint, tgpi->start, tgpi->end);
+ float color[4];
+ UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color);
+ gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL);
+ if (tgpi->tot_stored_edges) {
+ UI_GetThemeColor4fv(TH_REDALERT, color);
+ gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL);
+ }
+ else {
+ gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL);
+ }
+ UI_GetThemeColor4fv(TH_REDALERT, color);
+ gp_primitive_set_cp(tgpi, tgpi->midpoint, color, SMALL_SIZE_CTL);
}
/* create a line */
static void gp_primitive_line(tGPDprimitive *tgpi, tGPspoint *points2D)
{
- const int totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges);
- const float step = 1.0f / (float)(tgpi->tot_edges - 1);
- float a = tgpi->tot_stored_edges ? step : 0.0f;
-
- for (int i = tgpi->tot_stored_edges; i < totpoints; i++) {
- tGPspoint *p2d = &points2D[i];
- interp_v2_v2v2(&p2d->x, tgpi->start, tgpi->end, a);
- a += step;
- }
-
- float color[4];
- UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color);
- gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL);
- if (tgpi->tot_stored_edges) {
- UI_GetThemeColor4fv(TH_REDALERT, color);
- gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL);
- }
- else {
- gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL);
- }
+ const int totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges);
+ const float step = 1.0f / (float)(tgpi->tot_edges - 1);
+ float a = tgpi->tot_stored_edges ? step : 0.0f;
+
+ for (int i = tgpi->tot_stored_edges; i < totpoints; i++) {
+ tGPspoint *p2d = &points2D[i];
+ interp_v2_v2v2(&p2d->x, tgpi->start, tgpi->end, a);
+ a += step;
+ }
+
+ float color[4];
+ UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color);
+ gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL);
+ if (tgpi->tot_stored_edges) {
+ UI_GetThemeColor4fv(TH_REDALERT, color);
+ gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL);
+ }
+ else {
+ gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL);
+ }
}
/* create an arc */
static void gp_primitive_arc(tGPDprimitive *tgpi, tGPspoint *points2D)
{
- const int totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges);
- const float step = M_PI_2 / (float)(tgpi->tot_edges - 1);
- float start[2];
- float end[2];
- float cp1[2];
- float corner[2];
- float midpoint[2];
- float a = tgpi->tot_stored_edges ? step : 0.0f;
-
- mid_v2_v2v2(tgpi->midpoint, tgpi->start, tgpi->end);
- copy_v2_v2(start, tgpi->start);
- copy_v2_v2(end, tgpi->end);
- copy_v2_v2(cp1, tgpi->cp1);
- copy_v2_v2(midpoint, tgpi->midpoint);
-
- corner[0] = midpoint[0] - (cp1[0] - midpoint[0]);
- corner[1] = midpoint[1] - (cp1[1] - midpoint[1]);
-
- for (int i = tgpi->tot_stored_edges; i < totpoints; i++) {
- tGPspoint *p2d = &points2D[i];
- p2d->x = corner[0] + (end[0] - corner[0]) * sinf(a) + (start[0] - corner[0]) * cosf(a);
- p2d->y = corner[1] + (end[1] - corner[1]) * sinf(a) + (start[1] - corner[1]) * cosf(a);
- a += step;
- }
- float color[4];
- UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color);
- gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL);
- if (tgpi->tot_stored_edges) {
- UI_GetThemeColor4fv(TH_REDALERT, color);
- gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL);
- }
- else {
- gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL);
- }
- UI_GetThemeColor4fv(TH_GIZMO_SECONDARY, color);
- gp_primitive_set_cp(tgpi, tgpi->cp1, color, BIG_SIZE_CTL * 0.9f);
+ const int totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges);
+ const float step = M_PI_2 / (float)(tgpi->tot_edges - 1);
+ float start[2];
+ float end[2];
+ float cp1[2];
+ float corner[2];
+ float midpoint[2];
+ float a = tgpi->tot_stored_edges ? step : 0.0f;
+
+ mid_v2_v2v2(tgpi->midpoint, tgpi->start, tgpi->end);
+ copy_v2_v2(start, tgpi->start);
+ copy_v2_v2(end, tgpi->end);
+ copy_v2_v2(cp1, tgpi->cp1);
+ copy_v2_v2(midpoint, tgpi->midpoint);
+
+ corner[0] = midpoint[0] - (cp1[0] - midpoint[0]);
+ corner[1] = midpoint[1] - (cp1[1] - midpoint[1]);
+
+ for (int i = tgpi->tot_stored_edges; i < totpoints; i++) {
+ tGPspoint *p2d = &points2D[i];
+ p2d->x = corner[0] + (end[0] - corner[0]) * sinf(a) + (start[0] - corner[0]) * cosf(a);
+ p2d->y = corner[1] + (end[1] - corner[1]) * sinf(a) + (start[1] - corner[1]) * cosf(a);
+ a += step;
+ }
+ float color[4];
+ UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color);
+ gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL);
+ if (tgpi->tot_stored_edges) {
+ UI_GetThemeColor4fv(TH_REDALERT, color);
+ gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL);
+ }
+ else {
+ gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL);
+ }
+ UI_GetThemeColor4fv(TH_GIZMO_SECONDARY, color);
+ gp_primitive_set_cp(tgpi, tgpi->cp1, color, BIG_SIZE_CTL * 0.9f);
}
/* create a bezier */
static void gp_primitive_bezier(tGPDprimitive *tgpi, tGPspoint *points2D)
{
- const int totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges);
- const float step = 1.0f / (float)(tgpi->tot_edges - 1);
- float bcp1[2];
- float bcp2[2];
- float bcp3[2];
- float bcp4[2];
- float a = tgpi->tot_stored_edges ? step : 0.0f;
-
- copy_v2_v2(bcp1, tgpi->start);
- copy_v2_v2(bcp2, tgpi->cp1);
- copy_v2_v2(bcp3, tgpi->cp2);
- copy_v2_v2(bcp4, tgpi->end);
-
- for (int i = tgpi->tot_stored_edges; i < totpoints; i++) {
- tGPspoint *p2d = &points2D[i];
- interp_v2_v2v2v2v2_cubic(&p2d->x, bcp1, bcp2, bcp3, bcp4, a);
- a += step;
- }
- float color[4];
- UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color);
- gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL);
- if (tgpi->tot_stored_edges) {
- UI_GetThemeColor4fv(TH_REDALERT, color);
- gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL);
- }
- else {
- gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL);
- }
- UI_GetThemeColor4fv(TH_GIZMO_SECONDARY, color);
- gp_primitive_set_cp(tgpi, tgpi->cp1, color, BIG_SIZE_CTL * 0.9f);
- gp_primitive_set_cp(tgpi, tgpi->cp2, color, BIG_SIZE_CTL * 0.9f);
+ const int totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges);
+ const float step = 1.0f / (float)(tgpi->tot_edges - 1);
+ float bcp1[2];
+ float bcp2[2];
+ float bcp3[2];
+ float bcp4[2];
+ float a = tgpi->tot_stored_edges ? step : 0.0f;
+
+ copy_v2_v2(bcp1, tgpi->start);
+ copy_v2_v2(bcp2, tgpi->cp1);
+ copy_v2_v2(bcp3, tgpi->cp2);
+ copy_v2_v2(bcp4, tgpi->end);
+
+ for (int i = tgpi->tot_stored_edges; i < totpoints; i++) {
+ tGPspoint *p2d = &points2D[i];
+ interp_v2_v2v2v2v2_cubic(&p2d->x, bcp1, bcp2, bcp3, bcp4, a);
+ a += step;
+ }
+ float color[4];
+ UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color);
+ gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL);
+ if (tgpi->tot_stored_edges) {
+ UI_GetThemeColor4fv(TH_REDALERT, color);
+ gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL);
+ }
+ else {
+ gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL);
+ }
+ UI_GetThemeColor4fv(TH_GIZMO_SECONDARY, color);
+ gp_primitive_set_cp(tgpi, tgpi->cp1, color, BIG_SIZE_CTL * 0.9f);
+ gp_primitive_set_cp(tgpi, tgpi->cp2, color, BIG_SIZE_CTL * 0.9f);
}
/* create a circle */
static void gp_primitive_circle(tGPDprimitive *tgpi, tGPspoint *points2D)
{
- const int totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges);
- const float step = (2.0f * M_PI) / (float)(tgpi->tot_edges);
- float center[2];
- float radius[2];
- float a = 0.0f;
-
- center[0] = tgpi->start[0] + ((tgpi->end[0] - tgpi->start[0]) / 2.0f);
- center[1] = tgpi->start[1] + ((tgpi->end[1] - tgpi->start[1]) / 2.0f);
- radius[0] = fabsf(((tgpi->end[0] - tgpi->start[0]) / 2.0f));
- radius[1] = fabsf(((tgpi->end[1] - tgpi->start[1]) / 2.0f));
-
- for (int i = tgpi->tot_stored_edges; i < totpoints; i++) {
- tGPspoint *p2d = &points2D[i];
- p2d->x = (center[0] + cosf(a) * radius[0]);
- p2d->y = (center[1] + sinf(a) * radius[1]);
- a += step;
- }
- float color[4];
- UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color);
- gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL);
- gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL);
- UI_GetThemeColor4fv(TH_REDALERT, color);
- gp_primitive_set_cp(tgpi, center, color, SMALL_SIZE_CTL);
+ const int totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges);
+ const float step = (2.0f * M_PI) / (float)(tgpi->tot_edges);
+ float center[2];
+ float radius[2];
+ float a = 0.0f;
+
+ center[0] = tgpi->start[0] + ((tgpi->end[0] - tgpi->start[0]) / 2.0f);
+ center[1] = tgpi->start[1] + ((tgpi->end[1] - tgpi->start[1]) / 2.0f);
+ radius[0] = fabsf(((tgpi->end[0] - tgpi->start[0]) / 2.0f));
+ radius[1] = fabsf(((tgpi->end[1] - tgpi->start[1]) / 2.0f));
+
+ for (int i = tgpi->tot_stored_edges; i < totpoints; i++) {
+ tGPspoint *p2d = &points2D[i];
+ p2d->x = (center[0] + cosf(a) * radius[0]);
+ p2d->y = (center[1] + sinf(a) * radius[1]);
+ a += step;
+ }
+ float color[4];
+ UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color);
+ gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL);
+ gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL);
+ UI_GetThemeColor4fv(TH_REDALERT, color);
+ gp_primitive_set_cp(tgpi, center, color, SMALL_SIZE_CTL);
}
/* Helper: Update shape of the stroke */
static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
{
- ToolSettings *ts = tgpi->scene->toolsettings;
- bGPdata *gpd = tgpi->gpd;
- Brush *brush = tgpi->brush;
- 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;
- const char *align_flag = &ts->gpencil_v3d_align;
- bool is_depth = (bool)(*align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE));
- const bool is_camera = (bool)(ts->gp_sculpt.lock_axis == 0) &&
- (tgpi->rv3d->persp == RV3D_CAMOB) && (!is_depth);
-
- if (tgpi->type == GP_STROKE_BOX)
- gps->totpoints = (tgpi->tot_edges * 4 + tgpi->tot_stored_edges);
- else
- gps->totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges);
-
- if (tgpi->tot_stored_edges)
- gps->totpoints--;
-
- tgpi->gpd->runtime.tot_cp_points = 0;
-
- /* compute screen-space coordinates for points */
- tGPspoint *points2D = tgpi->points;
-
- if (tgpi->tot_edges > 1) {
- switch (tgpi->type) {
- case GP_STROKE_BOX:
- gp_primitive_rectangle(tgpi, points2D);
- break;
- case GP_STROKE_LINE:
- gp_primitive_line(tgpi, points2D);
- break;
- case GP_STROKE_CIRCLE:
- gp_primitive_circle(tgpi, points2D);
- break;
- case GP_STROKE_ARC:
- gp_primitive_arc(tgpi, points2D);
- break;
- case GP_STROKE_CURVE:
- gp_primitive_bezier(tgpi, points2D);
- default:
- break;
- }
- }
-
- /* convert screen-coordinates to 3D coordinates */
- gp_session_validatebuffer(tgpi);
- gp_init_colors(tgpi);
- if (gset->flag & GP_SCULPT_SETT_FLAG_PRIMITIVE_CURVE) {
- curvemapping_initialize(ts->gp_sculpt.cur_primitive);
- }
- if (tgpi->brush->gpencil_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) {
- curvemapping_initialize(tgpi->brush->gpencil_settings->curve_jitter);
- }
- if (tgpi->brush->gpencil_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) {
- curvemapping_initialize(tgpi->brush->gpencil_settings->curve_strength);
- }
-
- /* get an array of depths, far depths are blended */
- float *depth_arr = NULL;
- if (is_depth) {
- int i;
- int mval_i[2], mval_prev[2] = { 0 };
- bool interp_depth = false;
- bool found_depth = false;
-
- /* need to restore the original projection settings before packing up */
- view3d_region_operator_needs_opengl(tgpi->win, tgpi->ar);
- ED_view3d_autodist_init(
- tgpi->depsgraph, tgpi->ar, tgpi->v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
-
- depth_arr = MEM_mallocN(sizeof(float) * gps->totpoints, "depth_points");
- 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) &&
- (i && (ED_view3d_autodist_depth_seg(
- tgpi->ar, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0)))
- {
- interp_depth = true;
- }
- else {
- found_depth = true;
- }
- copy_v2_v2_int(mval_prev, mval_i);
- }
-
- if (!found_depth) {
- for (i = 0; i < gps->totpoints; i++) {
- depth_arr[i] = 0.9999f;
- }
- }
- else {
- /* if all depth are too high disable */
- bool valid_depth = false;
- for (i = 0; i < gps->totpoints; i++) {
- if (depth_arr[i] < 0.9999f) {
- valid_depth = true;
- break;
- }
- }
- if (!valid_depth) {
- MEM_SAFE_FREE(depth_arr);
- is_depth = false;
- }
- else {
- if ((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE_ENDPOINTS) ||
- (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE_FIRST))
- {
- int first_valid = 0;
- int last_valid = 0;
-
- /* find first valid contact point */
- for (i = 0; i < gps->totpoints; i++) {
- if (depth_arr[i] != FLT_MAX)
- break;
- }
- first_valid = i;
-
- /* find last valid contact point */
- if (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE_FIRST) {
- last_valid = first_valid;
- }
- else {
- for (i = gps->totpoints - 1; i >= 0; i--) {
- if (depth_arr[i] != FLT_MAX)
- break;
- }
- last_valid = i;
- }
-
- /* invalidate any other point, to interpolate between
- * first and last contact in an imaginary line between them */
- for (i = 0; i < gps->totpoints; i++) {
- if ((i != first_valid) && (i != last_valid)) {
- depth_arr[i] = FLT_MAX;
- }
- }
- interp_depth = true;
- }
-
- if (interp_depth) {
- interp_sparse_array(depth_arr, gps->totpoints, FLT_MAX);
- }
- }
- }
- }
-
- /* load stroke points and sbuffer */
- for (int i = 0; i < gps->totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
- tGPspoint *p2d = &points2D[i];
-
- /* set rnd value for reuse */
- if ((brush->gpencil_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;
- }
-
- /* Copy points to buffer */
- tGPspoint *tpt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_size);
-
- /* Store original points */
- float tmp_xyp[2];
- copy_v2_v2(tmp_xyp, &p2d->x);
-
- /* calc pressure */
- float curve_pressure = 1.0;
- float pressure = 1.0;
- float strength = brush->gpencil_settings->draw_strength;
-
- /* normalize value to evaluate curve */
- if (gset->flag & GP_SCULPT_SETT_FLAG_PRIMITIVE_CURVE) {
- float value = (float)i / (gps->totpoints - 1);
- curve_pressure = curvemapping_evaluateF(gset->cur_primitive, 0, value);
- pressure = curve_pressure;
- }
-
- /* apply jitter to position */
- if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) &&
- (brush->gpencil_settings->draw_jitter > 0.0f))
- {
- float jitter;
-
- if (brush->gpencil_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) {
- jitter = curvemapping_evaluateF(brush->gpencil_settings->curve_jitter, 0, curve_pressure);
- jitter *= brush->gpencil_settings->draw_sensitivity;
- }
- else {
- jitter = brush->gpencil_settings->draw_jitter;
- }
-
- /* exponential value */
- const float exfactor = SQUARE(brush->gpencil_settings->draw_jitter + 2.0f);
- const float fac = p2d->rnd[0] * exfactor * jitter;
-
- /* vector */
- float mvec[2], svec[2];
- if (i > 0) {
- mvec[0] = (p2d->x - (p2d - 1)->x);
- mvec[1] = (p2d->y - (p2d - 1)->y);
- normalize_v2(mvec);
- }
- else {
- zero_v2(mvec);
- }
- svec[0] = -mvec[1];
- svec[1] = mvec[0];
-
- if (p2d->rnd[1] > 0.5f) {
- mul_v2_fl(svec, -fac);
- }
- else {
- mul_v2_fl(svec, fac);
- }
- 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 = curvemapping_evaluateF(brush->gpencil_settings->curve_strength, 0, curve_pressure);
- strength *= curvef * brush->gpencil_settings->draw_sensitivity;
- strength *= brush->gpencil_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];
- }
- else {
- strength += strength * brush->gpencil_settings->draw_random_strength * p2d->rnd[1];
- }
- 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;
-
- /* point uv */
- if (gpd->runtime.sbuffer_size > 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_size - 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);
- /* reproject current */
- ED_gpencil_tpoint_to_point(tgpi->ar, 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_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;
- tpt->uv_fac = tgpi->totpixlen;
- if ((gp_style) && (gp_style->sima)) {
- tpt->uv_fac /= gp_style->sima->gen_x;
- }
- }
- else {
- tgpi->totpixlen = 0.0f;
- tpt->uv_fac = 0.0f;
- }
-
- tpt->uv_rot = p2d->uv_rot;
-
- gpd->runtime.sbuffer_size++;
-
- /* add small offset to keep stroke over the surface */
- if ((depth_arr) && (gpd->zdepth_offset > 0.0f)) {
- depth_arr[i] *= (1.0f - gpd->zdepth_offset);
- }
-
- /* 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);
-
- pt->pressure = pressure;
- pt->strength = strength;
- pt->time = 0.0f;
- pt->flag = 0;
- pt->uv_fac = tpt->uv_fac;
-
- if (gps->dvert != NULL) {
- MDeformVert *dvert = &gps->dvert[i];
- dvert->totweight = 0;
- dvert->dw = NULL;
- }
-
- /* Restore original points */
- copy_v2_v2(&p2d->x, tmp_xyp);
- }
-
- /* store cps and convert coords */
- if (tgpi->gpd->runtime.tot_cp_points > 0) {
- bGPDcontrolpoint *cps = tgpi->gpd->runtime.cp_points;
- 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);
- }
- }
-
- /* 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_gp_project_stroke_to_plane(
- tgpi->scene, tgpi->ob, tgpi->rv3d, gps,
- origin, ts->gp_sculpt.lock_axis - 1);
- }
-
- /* 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);
- }
-
- /* if camera view, reproject flat to view to avoid perspective effect */
- if (is_camera) {
- ED_gpencil_project_stroke_to_view(C, tgpi->gpl, gps);
- }
-
- /* force fill recalc */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
-
- MEM_SAFE_FREE(depth_arr);
-
- DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+ ToolSettings *ts = tgpi->scene->toolsettings;
+ bGPdata *gpd = tgpi->gpd;
+ Brush *brush = tgpi->brush;
+ 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;
+ const char *align_flag = &ts->gpencil_v3d_align;
+ bool is_depth = (bool)(*align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE));
+ const bool is_camera = (bool)(ts->gp_sculpt.lock_axis == 0) &&
+ (tgpi->rv3d->persp == RV3D_CAMOB) && (!is_depth);
+
+ if (tgpi->type == GP_STROKE_BOX)
+ gps->totpoints = (tgpi->tot_edges * 4 + tgpi->tot_stored_edges);
+ else
+ gps->totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges);
+
+ if (tgpi->tot_stored_edges)
+ gps->totpoints--;
+
+ tgpi->gpd->runtime.tot_cp_points = 0;
+
+ /* compute screen-space coordinates for points */
+ tGPspoint *points2D = tgpi->points;
+
+ if (tgpi->tot_edges > 1) {
+ switch (tgpi->type) {
+ case GP_STROKE_BOX:
+ gp_primitive_rectangle(tgpi, points2D);
+ break;
+ case GP_STROKE_LINE:
+ gp_primitive_line(tgpi, points2D);
+ break;
+ case GP_STROKE_CIRCLE:
+ gp_primitive_circle(tgpi, points2D);
+ break;
+ case GP_STROKE_ARC:
+ gp_primitive_arc(tgpi, points2D);
+ break;
+ case GP_STROKE_CURVE:
+ gp_primitive_bezier(tgpi, points2D);
+ default:
+ break;
+ }
+ }
+
+ /* convert screen-coordinates to 3D coordinates */
+ gp_session_validatebuffer(tgpi);
+ gp_init_colors(tgpi);
+ if (gset->flag & GP_SCULPT_SETT_FLAG_PRIMITIVE_CURVE) {
+ curvemapping_initialize(ts->gp_sculpt.cur_primitive);
+ }
+ if (tgpi->brush->gpencil_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) {
+ curvemapping_initialize(tgpi->brush->gpencil_settings->curve_jitter);
+ }
+ if (tgpi->brush->gpencil_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) {
+ curvemapping_initialize(tgpi->brush->gpencil_settings->curve_strength);
+ }
+
+ /* get an array of depths, far depths are blended */
+ float *depth_arr = NULL;
+ if (is_depth) {
+ int i;
+ int mval_i[2], mval_prev[2] = {0};
+ bool interp_depth = false;
+ bool found_depth = false;
+
+ /* need to restore the original projection settings before packing up */
+ view3d_region_operator_needs_opengl(tgpi->win, tgpi->ar);
+ ED_view3d_autodist_init(tgpi->depsgraph,
+ tgpi->ar,
+ tgpi->v3d,
+ (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
+
+ depth_arr = MEM_mallocN(sizeof(float) * gps->totpoints, "depth_points");
+ 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) &&
+ (i && (ED_view3d_autodist_depth_seg(
+ tgpi->ar, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0))) {
+ interp_depth = true;
+ }
+ else {
+ found_depth = true;
+ }
+ copy_v2_v2_int(mval_prev, mval_i);
+ }
+
+ if (!found_depth) {
+ for (i = 0; i < gps->totpoints; i++) {
+ depth_arr[i] = 0.9999f;
+ }
+ }
+ else {
+ /* if all depth are too high disable */
+ bool valid_depth = false;
+ for (i = 0; i < gps->totpoints; i++) {
+ if (depth_arr[i] < 0.9999f) {
+ valid_depth = true;
+ break;
+ }
+ }
+ if (!valid_depth) {
+ MEM_SAFE_FREE(depth_arr);
+ is_depth = false;
+ }
+ else {
+ if ((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE_ENDPOINTS) ||
+ (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE_FIRST)) {
+ int first_valid = 0;
+ int last_valid = 0;
+
+ /* find first valid contact point */
+ for (i = 0; i < gps->totpoints; i++) {
+ if (depth_arr[i] != FLT_MAX)
+ break;
+ }
+ first_valid = i;
+
+ /* find last valid contact point */
+ if (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE_FIRST) {
+ last_valid = first_valid;
+ }
+ else {
+ for (i = gps->totpoints - 1; i >= 0; i--) {
+ if (depth_arr[i] != FLT_MAX)
+ break;
+ }
+ last_valid = i;
+ }
+
+ /* invalidate any other point, to interpolate between
+ * first and last contact in an imaginary line between them */
+ for (i = 0; i < gps->totpoints; i++) {
+ if ((i != first_valid) && (i != last_valid)) {
+ depth_arr[i] = FLT_MAX;
+ }
+ }
+ interp_depth = true;
+ }
+
+ if (interp_depth) {
+ interp_sparse_array(depth_arr, gps->totpoints, FLT_MAX);
+ }
+ }
+ }
+ }
+
+ /* load stroke points and sbuffer */
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ tGPspoint *p2d = &points2D[i];
+
+ /* set rnd value for reuse */
+ if ((brush->gpencil_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;
+ }
+
+ /* Copy points to buffer */
+ tGPspoint *tpt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_size);
+
+ /* Store original points */
+ float tmp_xyp[2];
+ copy_v2_v2(tmp_xyp, &p2d->x);
+
+ /* calc pressure */
+ float curve_pressure = 1.0;
+ float pressure = 1.0;
+ float strength = brush->gpencil_settings->draw_strength;
+
+ /* normalize value to evaluate curve */
+ if (gset->flag & GP_SCULPT_SETT_FLAG_PRIMITIVE_CURVE) {
+ float value = (float)i / (gps->totpoints - 1);
+ curve_pressure = curvemapping_evaluateF(gset->cur_primitive, 0, value);
+ pressure = curve_pressure;
+ }
+
+ /* apply jitter to position */
+ if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) &&
+ (brush->gpencil_settings->draw_jitter > 0.0f)) {
+ float jitter;
+
+ if (brush->gpencil_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) {
+ jitter = curvemapping_evaluateF(brush->gpencil_settings->curve_jitter, 0, curve_pressure);
+ jitter *= brush->gpencil_settings->draw_sensitivity;
+ }
+ else {
+ jitter = brush->gpencil_settings->draw_jitter;
+ }
+
+ /* exponential value */
+ const float exfactor = SQUARE(brush->gpencil_settings->draw_jitter + 2.0f);
+ const float fac = p2d->rnd[0] * exfactor * jitter;
+
+ /* vector */
+ float mvec[2], svec[2];
+ if (i > 0) {
+ mvec[0] = (p2d->x - (p2d - 1)->x);
+ mvec[1] = (p2d->y - (p2d - 1)->y);
+ normalize_v2(mvec);
+ }
+ else {
+ zero_v2(mvec);
+ }
+ svec[0] = -mvec[1];
+ svec[1] = mvec[0];
+
+ if (p2d->rnd[1] > 0.5f) {
+ mul_v2_fl(svec, -fac);
+ }
+ else {
+ mul_v2_fl(svec, fac);
+ }
+ 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 = curvemapping_evaluateF(
+ brush->gpencil_settings->curve_strength, 0, curve_pressure);
+ strength *= curvef * brush->gpencil_settings->draw_sensitivity;
+ strength *= brush->gpencil_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];
+ }
+ else {
+ strength += strength * brush->gpencil_settings->draw_random_strength * p2d->rnd[1];
+ }
+ 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;
+
+ /* point uv */
+ if (gpd->runtime.sbuffer_size > 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_size - 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);
+ /* reproject current */
+ ED_gpencil_tpoint_to_point(tgpi->ar, 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_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;
+ tpt->uv_fac = tgpi->totpixlen;
+ if ((gp_style) && (gp_style->sima)) {
+ tpt->uv_fac /= gp_style->sima->gen_x;
+ }
+ }
+ else {
+ tgpi->totpixlen = 0.0f;
+ tpt->uv_fac = 0.0f;
+ }
+
+ tpt->uv_rot = p2d->uv_rot;
+
+ gpd->runtime.sbuffer_size++;
+
+ /* add small offset to keep stroke over the surface */
+ if ((depth_arr) && (gpd->zdepth_offset > 0.0f)) {
+ depth_arr[i] *= (1.0f - gpd->zdepth_offset);
+ }
+
+ /* 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);
+
+ pt->pressure = pressure;
+ pt->strength = strength;
+ pt->time = 0.0f;
+ pt->flag = 0;
+ pt->uv_fac = tpt->uv_fac;
+
+ if (gps->dvert != NULL) {
+ MDeformVert *dvert = &gps->dvert[i];
+ dvert->totweight = 0;
+ dvert->dw = NULL;
+ }
+
+ /* Restore original points */
+ copy_v2_v2(&p2d->x, tmp_xyp);
+ }
+
+ /* store cps and convert coords */
+ if (tgpi->gpd->runtime.tot_cp_points > 0) {
+ bGPDcontrolpoint *cps = tgpi->gpd->runtime.cp_points;
+ 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);
+ }
+ }
+
+ /* 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_gp_project_stroke_to_plane(
+ tgpi->scene, tgpi->ob, tgpi->rv3d, gps, origin, ts->gp_sculpt.lock_axis - 1);
+ }
+
+ /* 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);
+ }
+
+ /* if camera view, reproject flat to view to avoid perspective effect */
+ if (is_camera) {
+ ED_gpencil_project_stroke_to_view(C, tgpi->gpl, gps);
+ }
+
+ /* force fill recalc */
+ gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+
+ MEM_SAFE_FREE(depth_arr);
+
+ DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
}
/* Update screen and stroke */
static void gpencil_primitive_update(bContext *C, wmOperator *op, tGPDprimitive *tgpi)
{
- /* update indicator in header */
- gpencil_primitive_status_indicators(C, tgpi);
- /* apply... */
- tgpi->type = RNA_enum_get(op->ptr, "type");
- tgpi->tot_edges = RNA_int_get(op->ptr, "edges");
- /* update points position */
- gp_primitive_update_strokes(C, tgpi);
+ /* update indicator in header */
+ gpencil_primitive_status_indicators(C, tgpi);
+ /* apply... */
+ tgpi->type = RNA_enum_get(op->ptr, "type");
+ tgpi->tot_edges = RNA_int_get(op->ptr, "edges");
+ /* update points position */
+ gp_primitive_update_strokes(C, tgpi);
}
static void gpencil_primitive_interaction_begin(tGPDprimitive *tgpi, const wmEvent *event)
{
- copy_v2fl_v2i(tgpi->mval, event->mval);
- copy_v2_v2(tgpi->origin, tgpi->mval);
- copy_v2_v2(tgpi->start, tgpi->mval);
- copy_v2_v2(tgpi->end, tgpi->mval);
- copy_v2_v2(tgpi->cp1, tgpi->mval);
- copy_v2_v2(tgpi->cp2, tgpi->mval);
+ copy_v2fl_v2i(tgpi->mval, event->mval);
+ copy_v2_v2(tgpi->origin, tgpi->mval);
+ copy_v2_v2(tgpi->start, tgpi->mval);
+ copy_v2_v2(tgpi->end, tgpi->mval);
+ copy_v2_v2(tgpi->cp1, tgpi->mval);
+ copy_v2_v2(tgpi->cp2, tgpi->mval);
}
/* Exit and free memory */
static void gpencil_primitive_exit(bContext *C, wmOperator *op)
{
- tGPDprimitive *tgpi = op->customdata;
- bGPdata *gpd = tgpi->gpd;
-
- /* don't assume that operator data exists at all */
- if (tgpi) {
- /* clear status message area */
- ED_workspace_status_text(C, NULL);
-
- MEM_SAFE_FREE(tgpi->points);
- tgpi->gpd->runtime.tot_cp_points = 0;
- MEM_SAFE_FREE(tgpi->gpd->runtime.cp_points);
- /* finally, free memory used by temp data */
- BKE_gpencil_free_strokes(tgpi->gpf);
- MEM_SAFE_FREE(tgpi->gpf);
-
- /* free random seed */
- if (tgpi->rng != NULL) {
- BLI_rng_free(tgpi->rng);
- }
-
- MEM_freeN(tgpi);
- }
-
- /* free stroke buffer */
- if ((gpd != NULL) && (gpd->runtime.sbuffer)) {
- MEM_SAFE_FREE(gpd->runtime.sbuffer);
- gpd->runtime.sbuffer = NULL;
-
- /* clear flags */
- gpd->runtime.sbuffer_size = 0;
- gpd->runtime.sbuffer_sflag = 0;
- }
-
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
-
- /* clear pointer */
- op->customdata = NULL;
+ tGPDprimitive *tgpi = op->customdata;
+ bGPdata *gpd = tgpi->gpd;
+
+ /* don't assume that operator data exists at all */
+ if (tgpi) {
+ /* clear status message area */
+ ED_workspace_status_text(C, NULL);
+
+ MEM_SAFE_FREE(tgpi->points);
+ tgpi->gpd->runtime.tot_cp_points = 0;
+ MEM_SAFE_FREE(tgpi->gpd->runtime.cp_points);
+ /* finally, free memory used by temp data */
+ BKE_gpencil_free_strokes(tgpi->gpf);
+ MEM_SAFE_FREE(tgpi->gpf);
+
+ /* free random seed */
+ if (tgpi->rng != NULL) {
+ BLI_rng_free(tgpi->rng);
+ }
+
+ MEM_freeN(tgpi);
+ }
+
+ /* free stroke buffer */
+ if ((gpd != NULL) && (gpd->runtime.sbuffer)) {
+ MEM_SAFE_FREE(gpd->runtime.sbuffer);
+ gpd->runtime.sbuffer = NULL;
+
+ /* clear flags */
+ gpd->runtime.sbuffer_size = 0;
+ gpd->runtime.sbuffer_sflag = 0;
+ }
+
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+
+ /* clear pointer */
+ op->customdata = NULL;
}
/* Init new temporary primitive data */
static void gpencil_primitive_init(bContext *C, wmOperator *op)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- bGPdata *gpd = CTX_data_gpencil_data(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
-
- /* create temporary operator data */
- tGPDprimitive *tgpi = MEM_callocN(sizeof(tGPDprimitive), "GPencil Primitive Data");
- op->customdata = tgpi;
-
- tgpi->points = MEM_callocN(sizeof(tGPspoint), "gp primitive points2D");
-
- /* set current scene and window info */
- tgpi->bmain = CTX_data_main(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_depsgraph(C);
- tgpi->win = CTX_wm_window(C);
-
- /* save original type */
- tgpi->orign_type = RNA_enum_get(op->ptr, "type");
-
- /* set current frame number */
- tgpi->cframe = cfra_eval;
-
- /* set GP datablock */
- tgpi->gpd = gpd;
- /* region where paint was originated */
- tgpi->gpd->runtime.ar = tgpi->ar;
-
- /* control points */
- tgpi->gpd->runtime.cp_points = MEM_callocN(sizeof(bGPDcontrolpoint) * MAX_CP, "gp primitive cpoint");
- tgpi->gpd->runtime.tot_cp_points = 0;
-
- /* getcolor info */
- tgpi->mat = BKE_gpencil_object_material_ensure_from_active_input_toolsettings(bmain, tgpi->ob, ts);
-
- /* set parameters */
- tgpi->type = RNA_enum_get(op->ptr, "type");
-
- if (ELEM(tgpi->type, GP_STROKE_ARC, GP_STROKE_CURVE)) {
- tgpi->curve = true;
- }
- else {
- tgpi->curve = false;
- }
-
- /* set default edge count */
- switch (tgpi->type) {
- case GP_STROKE_LINE:
- {
- RNA_int_set(op->ptr, "edges", 8);
- break;
- }
- case GP_STROKE_BOX:
- {
- RNA_int_set(op->ptr, "edges", 8);
- break;
- }
- case GP_STROKE_CIRCLE:
- {
- RNA_int_set(op->ptr, "edges", 96);
- break;
- }
- default:
- {
- RNA_int_set(op->ptr, "edges", 64);
- break;
- }
- }
-
- tgpi->tot_stored_edges = 0;
- tgpi->tot_edges = RNA_int_get(op->ptr, "edges");
- tgpi->flag = IDLE;
- tgpi->lock_axis = ts->gp_sculpt.lock_axis;
-
- /* set temp layer, frame and stroke */
- gp_primitive_set_initdata(C, tgpi);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+ /* create temporary operator data */
+ tGPDprimitive *tgpi = MEM_callocN(sizeof(tGPDprimitive), "GPencil Primitive Data");
+ op->customdata = tgpi;
+
+ tgpi->points = MEM_callocN(sizeof(tGPspoint), "gp primitive points2D");
+
+ /* set current scene and window info */
+ tgpi->bmain = CTX_data_main(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_depsgraph(C);
+ tgpi->win = CTX_wm_window(C);
+
+ /* save original type */
+ tgpi->orign_type = RNA_enum_get(op->ptr, "type");
+
+ /* set current frame number */
+ tgpi->cframe = cfra_eval;
+
+ /* set GP datablock */
+ tgpi->gpd = gpd;
+ /* region where paint was originated */
+ tgpi->gpd->runtime.ar = tgpi->ar;
+
+ /* control points */
+ tgpi->gpd->runtime.cp_points = MEM_callocN(sizeof(bGPDcontrolpoint) * MAX_CP,
+ "gp primitive cpoint");
+ tgpi->gpd->runtime.tot_cp_points = 0;
+
+ /* getcolor info */
+ tgpi->mat = BKE_gpencil_object_material_ensure_from_active_input_toolsettings(
+ bmain, tgpi->ob, ts);
+
+ /* set parameters */
+ tgpi->type = RNA_enum_get(op->ptr, "type");
+
+ if (ELEM(tgpi->type, GP_STROKE_ARC, GP_STROKE_CURVE)) {
+ tgpi->curve = true;
+ }
+ else {
+ tgpi->curve = false;
+ }
+
+ /* set default edge count */
+ switch (tgpi->type) {
+ case GP_STROKE_LINE: {
+ RNA_int_set(op->ptr, "edges", 8);
+ break;
+ }
+ case GP_STROKE_BOX: {
+ RNA_int_set(op->ptr, "edges", 8);
+ break;
+ }
+ case GP_STROKE_CIRCLE: {
+ RNA_int_set(op->ptr, "edges", 96);
+ break;
+ }
+ default: {
+ RNA_int_set(op->ptr, "edges", 64);
+ break;
+ }
+ }
+
+ tgpi->tot_stored_edges = 0;
+ tgpi->tot_edges = RNA_int_get(op->ptr, "edges");
+ tgpi->flag = IDLE;
+ tgpi->lock_axis = ts->gp_sculpt.lock_axis;
+
+ /* set temp layer, frame and stroke */
+ gp_primitive_set_initdata(C, tgpi);
}
/* Invoke handler: Initialize the operator */
static int gpencil_primitive_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- wmWindow *win = CTX_wm_window(C);
- bGPdata *gpd = CTX_data_gpencil_data(C);
- tGPDprimitive *tgpi = NULL;
+ wmWindow *win = CTX_wm_window(C);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ tGPDprimitive *tgpi = NULL;
- /* initialize operator runtime data */
- gpencil_primitive_init(C, op);
- tgpi = op->customdata;
+ /* initialize operator runtime data */
+ gpencil_primitive_init(C, op);
+ tgpi = op->customdata;
- const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input");
- if (!is_modal) {
- tgpi->flag = IN_PROGRESS;
- gpencil_primitive_interaction_begin(tgpi, event);
- }
+ const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input");
+ if (!is_modal) {
+ tgpi->flag = IN_PROGRESS;
+ gpencil_primitive_interaction_begin(tgpi, event);
+ }
- /* if in tools region, wait till we get to the main (3d-space)
- * region before allowing drawing to take place.
- */
- op->flag |= OP_IS_MODAL_CURSOR_REGION;
+ /* if in tools region, wait till we get to the main (3d-space)
+ * region before allowing drawing to take place.
+ */
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
- /* set cursor to indicate modal */
- WM_cursor_modal_set(win, BC_CROSSCURSOR);
+ /* set cursor to indicate modal */
+ WM_cursor_modal_set(win, BC_CROSSCURSOR);
- /* update sindicator in header */
- gpencil_primitive_status_indicators(C, tgpi);
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+ /* update sindicator in header */
+ gpencil_primitive_status_indicators(C, tgpi);
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
- /* add a modal handler for this operator */
- WM_event_add_modal_handler(C, op);
+ /* add a modal handler for this operator */
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
/* Helper to complete a primitive */
-static void gpencil_primitive_interaction_end(bContext *C, wmOperator *op, wmWindow *win, tGPDprimitive *tgpi)
+static void gpencil_primitive_interaction_end(bContext *C,
+ wmOperator *op,
+ wmWindow *win,
+ tGPDprimitive *tgpi)
{
- bGPDframe *gpf;
- bGPDstroke *gps;
-
- ToolSettings *ts = tgpi->scene->toolsettings;
- Brush *brush = tgpi->brush;
-
- const int def_nr = tgpi->ob->actdef - 1;
- const bool have_weight = (bool)BLI_findlink(&tgpi->ob->defbase, def_nr);
-
- /* return to normal cursor and header status */
- ED_workspace_status_text(C, NULL);
- WM_cursor_modal_restore(win);
-
- /* insert keyframes as required... */
- short add_frame_mode;
- if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) {
- add_frame_mode = GP_GETFRAME_ADD_COPY;
- }
- else {
- add_frame_mode = GP_GETFRAME_ADD_NEW;
- }
-
- gpf = BKE_gpencil_layer_getframe(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;
-
- /* calculate UVs along the stroke */
- ED_gpencil_calc_stroke_uv(tgpi->ob, gps);
- }
-
- /* transfer stroke from temporary buffer to the actual frame */
- if (ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK) {
- BLI_movelisttolist_reverse(&gpf->strokes, &tgpi->gpf->strokes);
- }
- else {
- BLI_movelisttolist(&gpf->strokes, &tgpi->gpf->strokes);
- }
- BLI_assert(BLI_listbase_is_empty(&tgpi->gpf->strokes));
-
- /* add weights if required */
- if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
- 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);
- if (dw) {
- dw->weight = ts->vgroup_weight;
- }
- }
- }
-
- DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_COPY_ON_WRITE);
- DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
-
- /* clean up temp data */
- gpencil_primitive_exit(C, op);
+ bGPDframe *gpf;
+ bGPDstroke *gps;
+
+ ToolSettings *ts = tgpi->scene->toolsettings;
+ Brush *brush = tgpi->brush;
+
+ const int def_nr = tgpi->ob->actdef - 1;
+ const bool have_weight = (bool)BLI_findlink(&tgpi->ob->defbase, def_nr);
+
+ /* return to normal cursor and header status */
+ ED_workspace_status_text(C, NULL);
+ WM_cursor_modal_restore(win);
+
+ /* insert keyframes as required... */
+ short add_frame_mode;
+ if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) {
+ add_frame_mode = GP_GETFRAME_ADD_COPY;
+ }
+ else {
+ add_frame_mode = GP_GETFRAME_ADD_NEW;
+ }
+
+ gpf = BKE_gpencil_layer_getframe(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;
+
+ /* calculate UVs along the stroke */
+ ED_gpencil_calc_stroke_uv(tgpi->ob, gps);
+ }
+
+ /* transfer stroke from temporary buffer to the actual frame */
+ if (ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK) {
+ BLI_movelisttolist_reverse(&gpf->strokes, &tgpi->gpf->strokes);
+ }
+ else {
+ BLI_movelisttolist(&gpf->strokes, &tgpi->gpf->strokes);
+ }
+ BLI_assert(BLI_listbase_is_empty(&tgpi->gpf->strokes));
+
+ /* add weights if required */
+ if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
+ 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);
+ if (dw) {
+ dw->weight = ts->vgroup_weight;
+ }
+ }
+ }
+
+ DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ /* clean up temp data */
+ gpencil_primitive_exit(C, op);
}
/* edit event handling */
-static void gpencil_primitive_edit_event_handling(bContext *C, wmOperator *op, wmWindow *win, const wmEvent *event, tGPDprimitive *tgpi)
+static void gpencil_primitive_edit_event_handling(
+ bContext *C, wmOperator *op, wmWindow *win, const wmEvent *event, tGPDprimitive *tgpi)
{
- /* calculate nearest point then set cursor */
- int move = MOVE_NONE;
- float a = len_v2v2(tgpi->mval, tgpi->start);
- float b = len_v2v2(tgpi->mval, tgpi->end);
-
- float c = len_v2v2(tgpi->mval, tgpi->cp1);
- float d = len_v2v2(tgpi->mval, tgpi->cp2);
-
- if (tgpi->flag == IN_CURVE_EDIT) {
- if ((a < BIG_SIZE_CTL && tgpi->tot_stored_edges == 0) || b < BIG_SIZE_CTL) {
- move = MOVE_ENDS;
- WM_cursor_modal_set(win, BC_NSEW_SCROLLCURSOR);
- }
- else if (tgpi->curve) {
- move = MOVE_CP;
- WM_cursor_modal_set(win, BC_HANDCURSOR);
- }
- else {
- WM_cursor_modal_set(win, BC_CROSSCURSOR);
- }
- }
- else if (tgpi->flag == IN_PROGRESS) {
- WM_cursor_modal_set(win, BC_NSEW_SCROLLCURSOR);
- }
-
- switch (event->type) {
- case MOUSEMOVE:
- {
- if ((event->val == KM_PRESS) && tgpi->sel_cp != SELECT_NONE) {
- if (tgpi->sel_cp == SELECT_START && tgpi->tot_stored_edges == 0) {
- copy_v2_v2(tgpi->start, tgpi->mval);
- }
- else if (tgpi->sel_cp == SELECT_END) {
- copy_v2_v2(tgpi->end, tgpi->mval);
- }
- else if (tgpi->sel_cp == SELECT_CP1 || (tgpi->sel_cp == SELECT_CP2 && tgpi->type != GP_STROKE_CURVE)) {
- float dx = (tgpi->mval[0] - tgpi->mvalo[0]);
- float dy = (tgpi->mval[1] - tgpi->mvalo[1]);
- tgpi->cp1[0] += dx;
- tgpi->cp1[1] += dy;
- if (event->shift)
- copy_v2_v2(tgpi->cp2, tgpi->cp1);
- }
- else if (tgpi->sel_cp == SELECT_CP2) {
- float dx = (tgpi->mval[0] - tgpi->mvalo[0]);
- float dy = (tgpi->mval[1] - tgpi->mvalo[1]);
- tgpi->cp2[0] += dx;
- tgpi->cp2[1] += dy;
- if (event->shift)
- copy_v2_v2(tgpi->cp1, tgpi->cp2);
- }
- /* update screen */
- gpencil_primitive_update(C, op, tgpi);
- }
- break;
- }
- case LEFTMOUSE:
- {
- if ((event->val == KM_PRESS)) {
- /* find nearest cp based on stroke end points */
- if (move == MOVE_ENDS)
- tgpi->sel_cp = (a < b) ? SELECT_START : SELECT_END;
- else if (move == MOVE_CP)
- tgpi->sel_cp = (c < d) ? SELECT_CP1 : SELECT_CP2;
- else
- tgpi->sel_cp = SELECT_NONE;
- break;
- }
- else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS)) {
- /* set control points and enter edit mode */
- tgpi->flag = IN_CURVE_EDIT;
- gp_primitive_update_cps(tgpi);
- gpencil_primitive_update(C, op, tgpi);
- }
- else {
- tgpi->sel_cp = SELECT_NONE;
- }
- break;
- }
- case MKEY:
- {
- if ((event->val == KM_PRESS) &&
- (tgpi->curve) &&
- (ELEM(tgpi->orign_type, GP_STROKE_ARC) ))
- {
- tgpi->flip ^= 1;
- gp_primitive_update_cps(tgpi);
- gpencil_primitive_update(C, op, tgpi);
- }
- break;
- }
- case 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, BC_NSEW_SCROLLCURSOR);
- gpencil_primitive_add_segment(tgpi);
- copy_v2_v2(tgpi->start, tgpi->end);
- copy_v2_v2(tgpi->origin, tgpi->start);
- gp_primitive_update_cps(tgpi);
- }
- break;
- }
- }
+ /* calculate nearest point then set cursor */
+ int move = MOVE_NONE;
+ float a = len_v2v2(tgpi->mval, tgpi->start);
+ float b = len_v2v2(tgpi->mval, tgpi->end);
+
+ float c = len_v2v2(tgpi->mval, tgpi->cp1);
+ float d = len_v2v2(tgpi->mval, tgpi->cp2);
+
+ if (tgpi->flag == IN_CURVE_EDIT) {
+ if ((a < BIG_SIZE_CTL && tgpi->tot_stored_edges == 0) || b < BIG_SIZE_CTL) {
+ move = MOVE_ENDS;
+ WM_cursor_modal_set(win, BC_NSEW_SCROLLCURSOR);
+ }
+ else if (tgpi->curve) {
+ move = MOVE_CP;
+ WM_cursor_modal_set(win, BC_HANDCURSOR);
+ }
+ else {
+ WM_cursor_modal_set(win, BC_CROSSCURSOR);
+ }
+ }
+ else if (tgpi->flag == IN_PROGRESS) {
+ WM_cursor_modal_set(win, BC_NSEW_SCROLLCURSOR);
+ }
+
+ switch (event->type) {
+ case MOUSEMOVE: {
+ if ((event->val == KM_PRESS) && tgpi->sel_cp != SELECT_NONE) {
+ if (tgpi->sel_cp == SELECT_START && tgpi->tot_stored_edges == 0) {
+ copy_v2_v2(tgpi->start, tgpi->mval);
+ }
+ else if (tgpi->sel_cp == SELECT_END) {
+ copy_v2_v2(tgpi->end, tgpi->mval);
+ }
+ else if (tgpi->sel_cp == SELECT_CP1 ||
+ (tgpi->sel_cp == SELECT_CP2 && tgpi->type != GP_STROKE_CURVE)) {
+ float dx = (tgpi->mval[0] - tgpi->mvalo[0]);
+ float dy = (tgpi->mval[1] - tgpi->mvalo[1]);
+ tgpi->cp1[0] += dx;
+ tgpi->cp1[1] += dy;
+ if (event->shift)
+ copy_v2_v2(tgpi->cp2, tgpi->cp1);
+ }
+ else if (tgpi->sel_cp == SELECT_CP2) {
+ float dx = (tgpi->mval[0] - tgpi->mvalo[0]);
+ float dy = (tgpi->mval[1] - tgpi->mvalo[1]);
+ tgpi->cp2[0] += dx;
+ tgpi->cp2[1] += dy;
+ if (event->shift)
+ copy_v2_v2(tgpi->cp1, tgpi->cp2);
+ }
+ /* update screen */
+ gpencil_primitive_update(C, op, tgpi);
+ }
+ break;
+ }
+ case LEFTMOUSE: {
+ if ((event->val == KM_PRESS)) {
+ /* find nearest cp based on stroke end points */
+ if (move == MOVE_ENDS)
+ tgpi->sel_cp = (a < b) ? SELECT_START : SELECT_END;
+ else if (move == MOVE_CP)
+ tgpi->sel_cp = (c < d) ? SELECT_CP1 : SELECT_CP2;
+ else
+ tgpi->sel_cp = SELECT_NONE;
+ break;
+ }
+ else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS)) {
+ /* set control points and enter edit mode */
+ tgpi->flag = IN_CURVE_EDIT;
+ gp_primitive_update_cps(tgpi);
+ gpencil_primitive_update(C, op, tgpi);
+ }
+ else {
+ tgpi->sel_cp = SELECT_NONE;
+ }
+ break;
+ }
+ case MKEY: {
+ if ((event->val == KM_PRESS) && (tgpi->curve) && (ELEM(tgpi->orign_type, GP_STROKE_ARC))) {
+ tgpi->flip ^= 1;
+ gp_primitive_update_cps(tgpi);
+ gpencil_primitive_update(C, op, tgpi);
+ }
+ break;
+ }
+ case 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, BC_NSEW_SCROLLCURSOR);
+ gpencil_primitive_add_segment(tgpi);
+ copy_v2_v2(tgpi->start, tgpi->end);
+ copy_v2_v2(tgpi->origin, tgpi->start);
+ gp_primitive_update_cps(tgpi);
+ }
+ break;
+ }
+ }
}
/* brush strength */
static void gpencil_primitive_strength(tGPDprimitive *tgpi, bool reset)
{
- Brush *brush = tgpi->brush;
- if (brush) {
- if (reset) {
- brush->gpencil_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;
- }
- 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));
- }
-
- /* limit low limit because below 0.2f the stroke is invisible */
- CLAMP(brush->gpencil_settings->draw_strength, 0.2f, 1.0f);
- }
+ Brush *brush = tgpi->brush;
+ if (brush) {
+ if (reset) {
+ brush->gpencil_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;
+ }
+ 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));
+ }
+
+ /* limit low limit because below 0.2f the stroke is invisible */
+ CLAMP(brush->gpencil_settings->draw_strength, 0.2f, 1.0f);
+ }
}
/* brush size */
static void gpencil_primitive_size(tGPDprimitive *tgpi, bool reset)
{
- Brush *brush = tgpi->brush;
- if (brush) {
- if (reset) {
- brush->size = tgpi->brush_size;
- tgpi->brush_size = 0;
- }
- else {
- if (tgpi->brush_size == 0) {
- tgpi->brush_size = brush->size;
- }
- float move[2];
- sub_v2_v2v2(move, tgpi->mval, tgpi->mvalo);
- int adjust = (move[1] > 0.0f) ? 1 : -1;
- brush->size += adjust * (int)fabsf(len_manhattan_v2(move));
- }
- CLAMP_MIN(brush->size, 1);
- }
+ Brush *brush = tgpi->brush;
+ if (brush) {
+ if (reset) {
+ brush->size = tgpi->brush_size;
+ tgpi->brush_size = 0;
+ }
+ else {
+ if (tgpi->brush_size == 0) {
+ tgpi->brush_size = brush->size;
+ }
+ float move[2];
+ sub_v2_v2v2(move, tgpi->mval, tgpi->mvalo);
+ int adjust = (move[1] > 0.0f) ? 1 : -1;
+ brush->size += adjust * (int)fabsf(len_manhattan_v2(move));
+ }
+ CLAMP_MIN(brush->size, 1);
+ }
}
/* move */
static void gpencil_primitive_move(tGPDprimitive *tgpi, bool reset)
{
- float move[2];
- zero_v2(move);
-
- if (reset) {
- sub_v2_v2(move, tgpi->move);
- zero_v2(tgpi->move);
- }
- else {
- sub_v2_v2v2(move, tgpi->mval, tgpi->mvalo);
- add_v2_v2(tgpi->move, move);
- }
-
- bGPDstroke *gps = tgpi->gpf->strokes.first;
- tGPspoint *points2D = tgpi->points;
-
- for (int i = 0; i < gps->totpoints; i++) {
- tGPspoint *p2d = &points2D[i];
- add_v2_v2(&p2d->x, move);
- }
-
- add_v2_v2(tgpi->start, move);
- add_v2_v2(tgpi->end, move);
- add_v2_v2(tgpi->cp1, move);
- add_v2_v2(tgpi->cp2, move);
- add_v2_v2(tgpi->origin, move);
+ float move[2];
+ zero_v2(move);
+
+ if (reset) {
+ sub_v2_v2(move, tgpi->move);
+ zero_v2(tgpi->move);
+ }
+ else {
+ sub_v2_v2v2(move, tgpi->mval, tgpi->mvalo);
+ add_v2_v2(tgpi->move, move);
+ }
+
+ bGPDstroke *gps = tgpi->gpf->strokes.first;
+ tGPspoint *points2D = tgpi->points;
+
+ for (int i = 0; i < gps->totpoints; i++) {
+ tGPspoint *p2d = &points2D[i];
+ add_v2_v2(&p2d->x, move);
+ }
+
+ add_v2_v2(tgpi->start, move);
+ add_v2_v2(tgpi->end, move);
+ add_v2_v2(tgpi->cp1, move);
+ add_v2_v2(tgpi->cp2, move);
+ add_v2_v2(tgpi->origin, move);
}
/* Modal handler: Events handling during interactive part */
static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- tGPDprimitive *tgpi = op->customdata;
- wmWindow *win = CTX_wm_window(C);
- const bool has_numinput = hasNumInput(&tgpi->num);
-
- copy_v2fl_v2i(tgpi->mval, event->mval);
-
- if (tgpi->flag == IN_MOVE) {
-
- switch (event->type) {
- case MOUSEMOVE:
- {
- gpencil_primitive_move(tgpi, false);
- gpencil_primitive_update(C, op, tgpi);
- break;
- }
- case ESCKEY:
- case LEFTMOUSE:
- {
- zero_v2(tgpi->move);
- tgpi->flag = IN_CURVE_EDIT;
- break;
- }
- case RIGHTMOUSE:
- {
- if (event->val == KM_RELEASE) {
- tgpi->flag = IN_CURVE_EDIT;
- gpencil_primitive_move(tgpi, true);
- gpencil_primitive_update(C, op, tgpi);
- }
- break;
- }
- }
- copy_v2_v2(tgpi->mvalo, tgpi->mval);
- return OPERATOR_RUNNING_MODAL;
- }
- else if (tgpi->flag == IN_BRUSH_SIZE) {
- switch (event->type) {
- case MOUSEMOVE:
- gpencil_primitive_size(tgpi, false);
- gpencil_primitive_update(C, op, tgpi);
- break;
- case ESCKEY:
- case MIDDLEMOUSE:
- case LEFTMOUSE:
- tgpi->brush_size = 0;
- tgpi->flag = IN_CURVE_EDIT;
- break;
- case RIGHTMOUSE:
- if (event->val == KM_RELEASE) {
- tgpi->flag = IN_CURVE_EDIT;
- gpencil_primitive_size(tgpi, true);
- gpencil_primitive_update(C, op, tgpi);
- }
- break;
- }
- copy_v2_v2(tgpi->mvalo, tgpi->mval);
- return OPERATOR_RUNNING_MODAL;
- }
- else if (tgpi->flag == IN_BRUSH_STRENGTH) {
- switch (event->type) {
- case MOUSEMOVE:
- gpencil_primitive_strength(tgpi, false);
- gpencil_primitive_update(C, op, tgpi);
- break;
- case ESCKEY:
- case MIDDLEMOUSE:
- case LEFTMOUSE:
- tgpi->brush_strength = 0.0f;
- tgpi->flag = IN_CURVE_EDIT;
- break;
- case RIGHTMOUSE:
- if (event->val == KM_RELEASE) {
- tgpi->flag = IN_CURVE_EDIT;
- gpencil_primitive_strength(tgpi, true);
- gpencil_primitive_update(C, op, tgpi);
- }
- break;
- }
- copy_v2_v2(tgpi->mvalo, tgpi->mval);
- return OPERATOR_RUNNING_MODAL;
- }
- else if (tgpi->flag != IDLE) {
- gpencil_primitive_edit_event_handling(C, op, win, event, tgpi);
- }
-
- switch (event->type) {
- case LEFTMOUSE:
- {
- if ((event->val == KM_PRESS) && (tgpi->flag == IDLE)) {
- /* start drawing primitive */
- /* TODO: Ignore if not in main region yet */
- tgpi->flag = IN_PROGRESS;
- gpencil_primitive_interaction_begin(tgpi, event);
- }
- else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_MOVE)) {
- tgpi->flag = IN_CURVE_EDIT;
- }
- else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS)) {
- /* set control points and enter edit mode */
- tgpi->flag = IN_CURVE_EDIT;
- gp_primitive_update_cps(tgpi);
- gpencil_primitive_update(C, op, tgpi);
- }
- else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS) && (tgpi->type != GP_STROKE_CURVE)) {
- /* stop drawing primitive */
- tgpi->flag = IDLE;
- gpencil_primitive_interaction_end(C, op, win, tgpi);
- /* done! */
- return OPERATOR_FINISHED;
- }
- else {
- if (G.debug & G_DEBUG) {
- printf("GP Add Primitive Modal: LEFTMOUSE %d, Status = %d\n", event->val, tgpi->flag);
- }
- }
- break;
- }
- case SPACEKEY: /* confirm */
- case MIDDLEMOUSE:
- case RETKEY:
- {
- tgpi->flag = IDLE;
- gpencil_primitive_interaction_end(C, op, win, tgpi);
- /* done! */
- return OPERATOR_FINISHED;
- }
- case RIGHTMOUSE:
- {
- /* exception to cancel current stroke when we have previous strokes in buffer */
- if (tgpi->tot_stored_edges > 0) {
- tgpi->flag = IDLE;
- tgpi->tot_edges = 0;
- gp_primitive_update_strokes(C, tgpi);
- gpencil_primitive_interaction_end(C, op, win, tgpi);
- /* done! */
- return OPERATOR_FINISHED;
- }
- ATTR_FALLTHROUGH;
- }
- case ESCKEY:
- {
- /* return to normal cursor and header status */
- ED_workspace_status_text(C, NULL);
- WM_cursor_modal_restore(win);
-
- /* clean up temp data */
- gpencil_primitive_exit(C, op);
-
- /* canceled! */
- return OPERATOR_CANCELLED;
- }
- case PADPLUSKEY:
- case WHEELUPMOUSE:
- {
- if ((event->val != KM_RELEASE)) {
- tgpi->tot_edges = tgpi->tot_edges + 1;
- CLAMP(tgpi->tot_edges, MIN_EDGES, MAX_EDGES);
- RNA_int_set(op->ptr, "edges", tgpi->tot_edges);
-
- /* update screen */
- gpencil_primitive_update(C, op, tgpi);
- }
- break;
- }
- case PADMINUS:
- case WHEELDOWNMOUSE:
- {
- if ((event->val != KM_RELEASE)) {
- tgpi->tot_edges = tgpi->tot_edges - 1;
- CLAMP(tgpi->tot_edges, MIN_EDGES, MAX_EDGES);
- RNA_int_set(op->ptr, "edges", tgpi->tot_edges);
-
- /* update screen */
- gpencil_primitive_update(C, op, tgpi);
- }
- break;
- }
- case GKEY: /* grab mode */
- {
- if ((event->val == KM_PRESS)) {
- tgpi->flag = IN_MOVE;
- WM_cursor_modal_set(win, BC_NSEW_SCROLLCURSOR);
- }
- break;
- }
- case FKEY: /* brush thickness/ brush strength */
- {
- if ((event->val == KM_PRESS)) {
- if (event->shift) {
- tgpi->flag = IN_BRUSH_STRENGTH;
- }
- else {
- tgpi->flag = IN_BRUSH_SIZE;
- }
- WM_cursor_modal_set(win, BC_NS_SCROLLCURSOR);
- }
- break;
- }
- case CKEY: /* curve mode */
- {
- if ((event->val == KM_PRESS) &&
- (tgpi->orign_type == GP_STROKE_CURVE))
- {
- switch (tgpi->type) {
- case GP_STROKE_CURVE:
- tgpi->type = GP_STROKE_ARC;
- break;
- default:
- case GP_STROKE_ARC:
- tgpi->type = GP_STROKE_CURVE;
- break;
- }
-
- RNA_enum_set(op->ptr, "type", tgpi->type);
- gp_primitive_update_cps(tgpi);
- gpencil_primitive_update(C, op, tgpi);
- }
- break;
- }
- case TABKEY:
- {
- if (tgpi->flag == IN_CURVE_EDIT) {
- tgpi->flag = IN_PROGRESS;
- WM_cursor_modal_set(win, BC_NSEW_SCROLLCURSOR);
- gp_primitive_update_cps(tgpi);
- gpencil_primitive_update(C, op, tgpi);
- }
- break;
- }
- case MOUSEMOVE: /* calculate new position */
- {
- if (tgpi->flag == IN_CURVE_EDIT) {
- break;
- }
- /* only handle mousemove if not doing numinput */
- if (has_numinput == false) {
- /* update position of mouse */
- copy_v2_v2(tgpi->end, tgpi->mval);
- copy_v2_v2(tgpi->start, tgpi->origin);
- if (tgpi->flag == IDLE) {
- copy_v2_v2(tgpi->origin, tgpi->mval);
- }
- /* Keep square if shift key */
- if (event->shift) {
- float x = tgpi->end[0] - tgpi->origin[0];
- float y = tgpi->end[1] - tgpi->origin[1];
- if (tgpi->type == GP_STROKE_LINE || tgpi->curve) {
- float angle = fabsf(atan2f(y, x));
- if (angle < 0.4f || angle > (M_PI - 0.4f)) {
- tgpi->end[1] = tgpi->origin[1];
- }
- else if (angle > (M_PI_2 - 0.4f) && angle < (M_PI_2 + 0.4f)) {
- tgpi->end[0] = tgpi->origin[0];
- }
- else {
- gpencil_primitive_to_square(tgpi, x, y);
- }
- }
- else {
- gpencil_primitive_to_square(tgpi, x, y);
- }
- }
- /* Center primitive if alt key */
- if (event->alt) {
- tgpi->start[0] = tgpi->origin[0] - (tgpi->end[0] - tgpi->origin[0]);
- tgpi->start[1] = tgpi->origin[1] - (tgpi->end[1] - tgpi->origin[1]);
- }
- gp_primitive_update_cps(tgpi);
- /* update screen */
- gpencil_primitive_update(C, op, tgpi);
- }
- break;
- }
- default:
- {
- if (tgpi->flag != IN_CURVE_EDIT && (event->val == KM_PRESS) && handleNumInput(C, &tgpi->num, event)) {
- float value;
-
- /* Grab data from numeric input, and store this new value (the user see an int) */
- value = tgpi->tot_edges;
- applyNumInput(&tgpi->num, &value);
- tgpi->tot_edges = value;
-
- CLAMP(tgpi->tot_edges, MIN_EDGES, MAX_EDGES);
- RNA_int_set(op->ptr, "edges", tgpi->tot_edges);
-
- /* update screen */
- gpencil_primitive_update(C, op, tgpi);
-
- break;
- }
- else {
- /* unhandled event - allow to pass through */
- return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH;
- }
- }
- }
-
- copy_v2_v2(tgpi->mvalo, tgpi->mval);
- /* still running... */
- return OPERATOR_RUNNING_MODAL;
+ tGPDprimitive *tgpi = op->customdata;
+ wmWindow *win = CTX_wm_window(C);
+ const bool has_numinput = hasNumInput(&tgpi->num);
+
+ copy_v2fl_v2i(tgpi->mval, event->mval);
+
+ if (tgpi->flag == IN_MOVE) {
+
+ switch (event->type) {
+ case MOUSEMOVE: {
+ gpencil_primitive_move(tgpi, false);
+ gpencil_primitive_update(C, op, tgpi);
+ break;
+ }
+ case ESCKEY:
+ case LEFTMOUSE: {
+ zero_v2(tgpi->move);
+ tgpi->flag = IN_CURVE_EDIT;
+ break;
+ }
+ case RIGHTMOUSE: {
+ if (event->val == KM_RELEASE) {
+ tgpi->flag = IN_CURVE_EDIT;
+ gpencil_primitive_move(tgpi, true);
+ gpencil_primitive_update(C, op, tgpi);
+ }
+ break;
+ }
+ }
+ copy_v2_v2(tgpi->mvalo, tgpi->mval);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else if (tgpi->flag == IN_BRUSH_SIZE) {
+ switch (event->type) {
+ case MOUSEMOVE:
+ gpencil_primitive_size(tgpi, false);
+ gpencil_primitive_update(C, op, tgpi);
+ break;
+ case ESCKEY:
+ case MIDDLEMOUSE:
+ case LEFTMOUSE:
+ tgpi->brush_size = 0;
+ tgpi->flag = IN_CURVE_EDIT;
+ break;
+ case RIGHTMOUSE:
+ if (event->val == KM_RELEASE) {
+ tgpi->flag = IN_CURVE_EDIT;
+ gpencil_primitive_size(tgpi, true);
+ gpencil_primitive_update(C, op, tgpi);
+ }
+ break;
+ }
+ copy_v2_v2(tgpi->mvalo, tgpi->mval);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else if (tgpi->flag == IN_BRUSH_STRENGTH) {
+ switch (event->type) {
+ case MOUSEMOVE:
+ gpencil_primitive_strength(tgpi, false);
+ gpencil_primitive_update(C, op, tgpi);
+ break;
+ case ESCKEY:
+ case MIDDLEMOUSE:
+ case LEFTMOUSE:
+ tgpi->brush_strength = 0.0f;
+ tgpi->flag = IN_CURVE_EDIT;
+ break;
+ case RIGHTMOUSE:
+ if (event->val == KM_RELEASE) {
+ tgpi->flag = IN_CURVE_EDIT;
+ gpencil_primitive_strength(tgpi, true);
+ gpencil_primitive_update(C, op, tgpi);
+ }
+ break;
+ }
+ copy_v2_v2(tgpi->mvalo, tgpi->mval);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else if (tgpi->flag != IDLE) {
+ gpencil_primitive_edit_event_handling(C, op, win, event, tgpi);
+ }
+
+ switch (event->type) {
+ case LEFTMOUSE: {
+ if ((event->val == KM_PRESS) && (tgpi->flag == IDLE)) {
+ /* start drawing primitive */
+ /* TODO: Ignore if not in main region yet */
+ tgpi->flag = IN_PROGRESS;
+ gpencil_primitive_interaction_begin(tgpi, event);
+ }
+ else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_MOVE)) {
+ tgpi->flag = IN_CURVE_EDIT;
+ }
+ else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS)) {
+ /* set control points and enter edit mode */
+ tgpi->flag = IN_CURVE_EDIT;
+ gp_primitive_update_cps(tgpi);
+ gpencil_primitive_update(C, op, tgpi);
+ }
+ else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS) &&
+ (tgpi->type != GP_STROKE_CURVE)) {
+ /* stop drawing primitive */
+ tgpi->flag = IDLE;
+ gpencil_primitive_interaction_end(C, op, win, tgpi);
+ /* done! */
+ return OPERATOR_FINISHED;
+ }
+ else {
+ if (G.debug & G_DEBUG) {
+ printf("GP Add Primitive Modal: LEFTMOUSE %d, Status = %d\n", event->val, tgpi->flag);
+ }
+ }
+ break;
+ }
+ case SPACEKEY: /* confirm */
+ case MIDDLEMOUSE:
+ case RETKEY: {
+ tgpi->flag = IDLE;
+ gpencil_primitive_interaction_end(C, op, win, tgpi);
+ /* done! */
+ return OPERATOR_FINISHED;
+ }
+ case RIGHTMOUSE: {
+ /* exception to cancel current stroke when we have previous strokes in buffer */
+ if (tgpi->tot_stored_edges > 0) {
+ tgpi->flag = IDLE;
+ tgpi->tot_edges = 0;
+ gp_primitive_update_strokes(C, tgpi);
+ gpencil_primitive_interaction_end(C, op, win, tgpi);
+ /* done! */
+ return OPERATOR_FINISHED;
+ }
+ ATTR_FALLTHROUGH;
+ }
+ case ESCKEY: {
+ /* return to normal cursor and header status */
+ ED_workspace_status_text(C, NULL);
+ WM_cursor_modal_restore(win);
+
+ /* clean up temp data */
+ gpencil_primitive_exit(C, op);
+
+ /* canceled! */
+ return OPERATOR_CANCELLED;
+ }
+ case PADPLUSKEY:
+ case WHEELUPMOUSE: {
+ if ((event->val != KM_RELEASE)) {
+ tgpi->tot_edges = tgpi->tot_edges + 1;
+ CLAMP(tgpi->tot_edges, MIN_EDGES, MAX_EDGES);
+ RNA_int_set(op->ptr, "edges", tgpi->tot_edges);
+
+ /* update screen */
+ gpencil_primitive_update(C, op, tgpi);
+ }
+ break;
+ }
+ case PADMINUS:
+ case WHEELDOWNMOUSE: {
+ if ((event->val != KM_RELEASE)) {
+ tgpi->tot_edges = tgpi->tot_edges - 1;
+ CLAMP(tgpi->tot_edges, MIN_EDGES, MAX_EDGES);
+ RNA_int_set(op->ptr, "edges", tgpi->tot_edges);
+
+ /* update screen */
+ gpencil_primitive_update(C, op, tgpi);
+ }
+ break;
+ }
+ case GKEY: /* grab mode */
+ {
+ if ((event->val == KM_PRESS)) {
+ tgpi->flag = IN_MOVE;
+ WM_cursor_modal_set(win, BC_NSEW_SCROLLCURSOR);
+ }
+ break;
+ }
+ case FKEY: /* brush thickness/ brush strength */
+ {
+ if ((event->val == KM_PRESS)) {
+ if (event->shift) {
+ tgpi->flag = IN_BRUSH_STRENGTH;
+ }
+ else {
+ tgpi->flag = IN_BRUSH_SIZE;
+ }
+ WM_cursor_modal_set(win, BC_NS_SCROLLCURSOR);
+ }
+ break;
+ }
+ case CKEY: /* curve mode */
+ {
+ if ((event->val == KM_PRESS) && (tgpi->orign_type == GP_STROKE_CURVE)) {
+ switch (tgpi->type) {
+ case GP_STROKE_CURVE:
+ tgpi->type = GP_STROKE_ARC;
+ break;
+ default:
+ case GP_STROKE_ARC:
+ tgpi->type = GP_STROKE_CURVE;
+ break;
+ }
+
+ RNA_enum_set(op->ptr, "type", tgpi->type);
+ gp_primitive_update_cps(tgpi);
+ gpencil_primitive_update(C, op, tgpi);
+ }
+ break;
+ }
+ case TABKEY: {
+ if (tgpi->flag == IN_CURVE_EDIT) {
+ tgpi->flag = IN_PROGRESS;
+ WM_cursor_modal_set(win, BC_NSEW_SCROLLCURSOR);
+ gp_primitive_update_cps(tgpi);
+ gpencil_primitive_update(C, op, tgpi);
+ }
+ break;
+ }
+ case MOUSEMOVE: /* calculate new position */
+ {
+ if (tgpi->flag == IN_CURVE_EDIT) {
+ break;
+ }
+ /* only handle mousemove if not doing numinput */
+ if (has_numinput == false) {
+ /* update position of mouse */
+ copy_v2_v2(tgpi->end, tgpi->mval);
+ copy_v2_v2(tgpi->start, tgpi->origin);
+ if (tgpi->flag == IDLE) {
+ copy_v2_v2(tgpi->origin, tgpi->mval);
+ }
+ /* Keep square if shift key */
+ if (event->shift) {
+ float x = tgpi->end[0] - tgpi->origin[0];
+ float y = tgpi->end[1] - tgpi->origin[1];
+ if (tgpi->type == GP_STROKE_LINE || tgpi->curve) {
+ float angle = fabsf(atan2f(y, x));
+ if (angle < 0.4f || angle > (M_PI - 0.4f)) {
+ tgpi->end[1] = tgpi->origin[1];
+ }
+ else if (angle > (M_PI_2 - 0.4f) && angle < (M_PI_2 + 0.4f)) {
+ tgpi->end[0] = tgpi->origin[0];
+ }
+ else {
+ gpencil_primitive_to_square(tgpi, x, y);
+ }
+ }
+ else {
+ gpencil_primitive_to_square(tgpi, x, y);
+ }
+ }
+ /* Center primitive if alt key */
+ if (event->alt) {
+ tgpi->start[0] = tgpi->origin[0] - (tgpi->end[0] - tgpi->origin[0]);
+ tgpi->start[1] = tgpi->origin[1] - (tgpi->end[1] - tgpi->origin[1]);
+ }
+ gp_primitive_update_cps(tgpi);
+ /* update screen */
+ gpencil_primitive_update(C, op, tgpi);
+ }
+ break;
+ }
+ default: {
+ if (tgpi->flag != IN_CURVE_EDIT && (event->val == KM_PRESS) &&
+ handleNumInput(C, &tgpi->num, event)) {
+ float value;
+
+ /* Grab data from numeric input, and store this new value (the user see an int) */
+ value = tgpi->tot_edges;
+ applyNumInput(&tgpi->num, &value);
+ tgpi->tot_edges = value;
+
+ CLAMP(tgpi->tot_edges, MIN_EDGES, MAX_EDGES);
+ RNA_int_set(op->ptr, "edges", tgpi->tot_edges);
+
+ /* update screen */
+ gpencil_primitive_update(C, op, tgpi);
+
+ break;
+ }
+ else {
+ /* unhandled event - allow to pass through */
+ return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH;
+ }
+ }
+ }
+
+ copy_v2_v2(tgpi->mvalo, tgpi->mval);
+ /* still running... */
+ return OPERATOR_RUNNING_MODAL;
}
/* Cancel handler */
static void gpencil_primitive_cancel(bContext *C, wmOperator *op)
{
- /* this is just a wrapper around exit() */
- gpencil_primitive_exit(C, op);
+ /* this is just a wrapper around exit() */
+ gpencil_primitive_exit(C, op);
}
void GPENCIL_OT_primitive(wmOperatorType *ot)
{
- static EnumPropertyItem primitive_type[] = {
- {GP_STROKE_BOX, "BOX", 0, "Box", ""},
- {GP_STROKE_LINE, "LINE", 0, "Line", ""},
- {GP_STROKE_CIRCLE, "CIRCLE", 0, "Circle", ""},
- {GP_STROKE_ARC, "ARC", 0, "Arc", ""},
- {GP_STROKE_CURVE, "CURVE", 0, "Curve", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Grease Pencil Shapes";
- ot->idname = "GPENCIL_OT_primitive";
- ot->description = "Create predefined grease pencil stroke shapes";
-
- /* callbacks */
- ot->invoke = gpencil_primitive_invoke;
- ot->modal = gpencil_primitive_modal;
- ot->cancel = gpencil_primitive_cancel;
- ot->poll = gpencil_primitive_add_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* properties */
- PropertyRNA *prop;
-
- prop = RNA_def_int(ot->srna, "edges", 4, MIN_EDGES, MAX_EDGES, "Edges", "Number of polygon edges", MIN_EDGES, MAX_EDGES);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- RNA_def_enum(ot->srna, "type", primitive_type, GP_STROKE_BOX, "Type", "Type of shape");
-
- prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ static EnumPropertyItem primitive_type[] = {
+ {GP_STROKE_BOX, "BOX", 0, "Box", ""},
+ {GP_STROKE_LINE, "LINE", 0, "Line", ""},
+ {GP_STROKE_CIRCLE, "CIRCLE", 0, "Circle", ""},
+ {GP_STROKE_ARC, "ARC", 0, "Arc", ""},
+ {GP_STROKE_CURVE, "CURVE", 0, "Curve", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Grease Pencil Shapes";
+ ot->idname = "GPENCIL_OT_primitive";
+ ot->description = "Create predefined grease pencil stroke shapes";
+
+ /* callbacks */
+ ot->invoke = gpencil_primitive_invoke;
+ ot->modal = gpencil_primitive_modal;
+ ot->cancel = gpencil_primitive_cancel;
+ ot->poll = gpencil_primitive_add_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* properties */
+ PropertyRNA *prop;
+
+ prop = RNA_def_int(ot->srna,
+ "edges",
+ 4,
+ MIN_EDGES,
+ MAX_EDGES,
+ "Edges",
+ "Number of polygon edges",
+ MIN_EDGES,
+ MAX_EDGES);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ RNA_def_enum(ot->srna, "type", primitive_type, GP_STROKE_BOX, "Type", "Type of shape");
+
+ 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_select.c b/source/blender/editors/gpencil/gpencil_select.c
index 99bbf10cdc1..ef7a198111b 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -69,16 +69,16 @@
static bool gpencil_select_poll(bContext *C)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
- /* 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? */
- if (gpd->layers.first)
- return true;
- }
+ /* 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? */
+ if (gpd->layers.first)
+ return true;
+ }
- return false;
+ return false;
}
/** \} */
@@ -89,47 +89,47 @@ static bool gpencil_select_poll(bContext *C)
static int gpencil_select_all_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- int action = RNA_enum_get(op->ptr, "action");
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ int action = RNA_enum_get(op->ptr, "action");
- if (gpd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
- return OPERATOR_CANCELLED;
- }
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
+ return OPERATOR_CANCELLED;
+ }
- /* if not edit/sculpt mode, the event is catched but not processed */
- if (GPENCIL_NONE_EDIT_MODE(gpd)) {
- return OPERATOR_CANCELLED;
- }
+ /* if not edit/sculpt mode, the event is catched but not processed */
+ if (GPENCIL_NONE_EDIT_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
- ED_gpencil_select_toggle_all(C, action);
+ ED_gpencil_select_toggle_all(C, action);
- /* updates */
- DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
+ /* 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);
+ /* 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);
- return OPERATOR_FINISHED;
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All Strokes";
- ot->idname = "GPENCIL_OT_select_all";
- ot->description = "Change selection of all Grease Pencil strokes currently visible";
+ /* identifiers */
+ ot->name = "(De)select All Strokes";
+ ot->idname = "GPENCIL_OT_select_all";
+ ot->description = "Change selection of all Grease Pencil strokes currently visible";
- /* callbacks */
- ot->exec = gpencil_select_all_exec;
- ot->poll = gpencil_select_poll;
+ /* callbacks */
+ ot->exec = gpencil_select_all_exec;
+ ot->poll = gpencil_select_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_select_all(ot);
+ WM_operator_properties_select_all(ot);
}
/** \} */
@@ -140,56 +140,55 @@ void GPENCIL_OT_select_all(wmOperatorType *ot)
static int gpencil_select_linked_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
-
- if (gpd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
- return OPERATOR_CANCELLED;
- }
-
- /* if not edit/sculpt mode, the event is catched but not processed */
- if (GPENCIL_NONE_EDIT_MODE(gpd)) {
- return OPERATOR_CANCELLED;
- }
-
- /* select all points in selected strokes */
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- if (gps->flag & GP_STROKE_SELECT) {
- bGPDspoint *pt;
- int i;
-
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- pt->flag |= GP_SPOINT_SELECT;
- }
- }
- }
- CTX_DATA_END;
-
- /* 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);
- return OPERATOR_FINISHED;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* if not edit/sculpt mode, the event is catched but not processed */
+ if (GPENCIL_NONE_EDIT_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* select all points in selected strokes */
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* 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);
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_select_linked(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Linked";
- ot->idname = "GPENCIL_OT_select_linked";
- ot->description = "Select all points in same strokes as already selected points";
+ /* identifiers */
+ ot->name = "Select Linked";
+ ot->idname = "GPENCIL_OT_select_linked";
+ ot->description = "Select all points in same strokes as already selected points";
- /* callbacks */
- ot->exec = gpencil_select_linked_exec;
- ot->poll = gpencil_select_poll;
+ /* callbacks */
+ ot->exec = gpencil_select_linked_exec;
+ ot->poll = gpencil_select_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -200,80 +199,83 @@ void GPENCIL_OT_select_linked(wmOperatorType *ot)
static int gpencil_select_alternate_exec(bContext *C, wmOperator *op)
{
- const bool unselect_ends = RNA_boolean_get(op->ptr, "unselect_ends");
- bGPdata *gpd = ED_gpencil_data_get_active(C);
-
- if (gpd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
- return OPERATOR_CANCELLED;
- }
-
- /* if not edit/sculpt mode, the event is catched but not processed */
- if (GPENCIL_NONE_EDIT_MODE(gpd)) {
- return OPERATOR_CANCELLED;
- }
-
- /* select all points in selected strokes */
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- if ((gps->flag & GP_STROKE_SELECT) && (gps->totpoints > 1)) {
- bGPDspoint *pt;
- int row = 0;
- int start = 0;
- if (unselect_ends) {
- start = 1;
- }
-
- for (int i = start; i < gps->totpoints; i++) {
- pt = &gps->points[i];
- if ((row % 2) == 0) {
- pt->flag |= GP_SPOINT_SELECT;
- }
- else {
- pt->flag &= ~GP_SPOINT_SELECT;
- }
- row++;
- }
-
- /* unselect start and end points */
- if (unselect_ends) {
- pt = &gps->points[0];
- pt->flag &= ~GP_SPOINT_SELECT;
-
- pt = &gps->points[gps->totpoints - 1];
- pt->flag &= ~GP_SPOINT_SELECT;
- }
- }
- }
- CTX_DATA_END;
-
- /* 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);
- return OPERATOR_FINISHED;
+ const bool unselect_ends = RNA_boolean_get(op->ptr, "unselect_ends");
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* if not edit/sculpt mode, the event is catched but not processed */
+ if (GPENCIL_NONE_EDIT_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* select all points in selected strokes */
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ if ((gps->flag & GP_STROKE_SELECT) && (gps->totpoints > 1)) {
+ bGPDspoint *pt;
+ int row = 0;
+ int start = 0;
+ if (unselect_ends) {
+ start = 1;
+ }
+
+ for (int i = start; i < gps->totpoints; i++) {
+ pt = &gps->points[i];
+ if ((row % 2) == 0) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ else {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ row++;
+ }
+
+ /* unselect start and end points */
+ if (unselect_ends) {
+ pt = &gps->points[0];
+ pt->flag &= ~GP_SPOINT_SELECT;
+
+ pt = &gps->points[gps->totpoints - 1];
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* 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);
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_select_alternate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Alternated";
- ot->idname = "GPENCIL_OT_select_alternate";
- ot->description = "Select alternative points in same strokes as already selected points";
-
- /* callbacks */
- ot->exec = gpencil_select_alternate_exec;
- ot->poll = gpencil_select_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "unselect_ends", true, "Unselect Ends", "Do not select the first and last point of the stroke");
+ /* identifiers */
+ ot->name = "Alternated";
+ ot->idname = "GPENCIL_OT_select_alternate";
+ ot->description = "Select alternative points in same strokes as already selected points";
+
+ /* callbacks */
+ ot->exec = gpencil_select_alternate_exec;
+ ot->poll = gpencil_select_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "unselect_ends",
+ true,
+ "Unselect Ends",
+ "Do not select the first and last point of the stroke");
}
/** \} */
@@ -283,14 +285,14 @@ void GPENCIL_OT_select_alternate(wmOperatorType *ot)
* \{ */
typedef enum eGP_SelectGrouped {
- /* Select strokes in the same layer */
- GP_SEL_SAME_LAYER = 0,
+ /* Select strokes in the same layer */
+ GP_SEL_SAME_LAYER = 0,
- /* Select strokes with the same color */
- GP_SEL_SAME_MATERIAL = 1,
+ /* Select strokes with the same color */
+ GP_SEL_SAME_MATERIAL = 1,
- /* TODO: All with same prefix - Useful for isolating all layers for a particular character for instance */
- /* TODO: All with same appearance - colour/opacity/volumetric/fills ? */
+ /* TODO: All with same prefix - Useful for isolating all layers for a particular character for instance */
+ /* TODO: All with same appearance - colour/opacity/volumetric/fills ? */
} eGP_SelectGrouped;
/* ----------------------------------- */
@@ -298,146 +300,143 @@ typedef enum eGP_SelectGrouped {
/* On each visible layer, check for selected strokes - if found, select all others */
static void gp_select_same_layer(bContext *C)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
-
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV);
- bGPDstroke *gps;
- bool found = false;
-
- if (gpf == NULL)
- continue;
-
- /* Search for a selected stroke */
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- if (ED_gpencil_stroke_can_use(C, gps)) {
- if (gps->flag & GP_STROKE_SELECT) {
- found = true;
- break;
- }
- }
- }
-
- /* Select all if found */
- if (found) {
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- if (ED_gpencil_stroke_can_use(C, gps)) {
- bGPDspoint *pt;
- int i;
-
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- pt->flag |= GP_SPOINT_SELECT;
- }
-
- gps->flag |= GP_STROKE_SELECT;
- }
- }
- }
- }
- CTX_DATA_END;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV);
+ bGPDstroke *gps;
+ bool found = false;
+
+ if (gpf == NULL)
+ continue;
+
+ /* Search for a selected stroke */
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ if (ED_gpencil_stroke_can_use(C, gps)) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ /* Select all if found */
+ if (found) {
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ if (ED_gpencil_stroke_can_use(C, gps)) {
+ bGPDspoint *pt;
+ int i;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+
+ gps->flag |= GP_STROKE_SELECT;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
}
/* Select all strokes with same colors as selected ones */
static void gp_select_same_material(bContext *C)
{
- /* First, build set containing all the colors of selected strokes */
- GSet *selected_colors = BLI_gset_str_new("GP Selected Colors");
-
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- if (gps->flag & GP_STROKE_SELECT) {
- /* add instead of insert here, otherwise the uniqueness check gets skipped,
- * and we get many duplicate entries...
- */
- BLI_gset_add(selected_colors, &gps->mat_nr);
- }
- }
- CTX_DATA_END;
-
- /* Second, select any visible stroke that uses these colors */
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- if (BLI_gset_haskey(selected_colors, &gps->mat_nr)) {
- /* select this stroke */
- bGPDspoint *pt;
- int i;
-
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- pt->flag |= GP_SPOINT_SELECT;
- }
-
- gps->flag |= GP_STROKE_SELECT;
- }
- }
- CTX_DATA_END;
-
- /* free memomy */
- if (selected_colors != NULL) {
- BLI_gset_free(selected_colors, NULL);
- }
+ /* First, build set containing all the colors of selected strokes */
+ GSet *selected_colors = BLI_gset_str_new("GP Selected Colors");
+
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* add instead of insert here, otherwise the uniqueness check gets skipped,
+ * and we get many duplicate entries...
+ */
+ BLI_gset_add(selected_colors, &gps->mat_nr);
+ }
+ }
+ CTX_DATA_END;
+
+ /* Second, select any visible stroke that uses these colors */
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ if (BLI_gset_haskey(selected_colors, &gps->mat_nr)) {
+ /* select this stroke */
+ bGPDspoint *pt;
+ int i;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+
+ gps->flag |= GP_STROKE_SELECT;
+ }
+ }
+ CTX_DATA_END;
+
+ /* free memomy */
+ if (selected_colors != NULL) {
+ BLI_gset_free(selected_colors, NULL);
+ }
}
-
/* ----------------------------------- */
static int gpencil_select_grouped_exec(bContext *C, wmOperator *op)
{
- eGP_SelectGrouped mode = RNA_enum_get(op->ptr, "type");
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- /* if not edit/sculpt mode, the event is catched but not processed */
- if (GPENCIL_NONE_EDIT_MODE(gpd)) {
- return OPERATOR_CANCELLED;
- }
-
- switch (mode) {
- case GP_SEL_SAME_LAYER:
- gp_select_same_layer(C);
- break;
- case GP_SEL_SAME_MATERIAL:
- gp_select_same_material(C);
- break;
-
- default:
- BLI_assert(!"unhandled select grouped gpencil mode");
- break;
- }
-
- /* 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);
- return OPERATOR_FINISHED;
+ eGP_SelectGrouped mode = RNA_enum_get(op->ptr, "type");
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ /* if not edit/sculpt mode, the event is catched but not processed */
+ if (GPENCIL_NONE_EDIT_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (mode) {
+ case GP_SEL_SAME_LAYER:
+ gp_select_same_layer(C);
+ break;
+ case GP_SEL_SAME_MATERIAL:
+ gp_select_same_material(C);
+ break;
+
+ default:
+ BLI_assert(!"unhandled select grouped gpencil mode");
+ break;
+ }
+
+ /* 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);
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_select_grouped(wmOperatorType *ot)
{
- static const EnumPropertyItem prop_select_grouped_types[] = {
- {GP_SEL_SAME_LAYER, "LAYER", 0, "Layer", "Shared layers"},
- {GP_SEL_SAME_MATERIAL, "MATERIAL", 0, "Material", "Shared materials"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Select Grouped";
- ot->idname = "GPENCIL_OT_select_grouped";
- ot->description = "Select all strokes with similar characteristics";
-
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = gpencil_select_grouped_exec;
- ot->poll = gpencil_select_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, GP_SEL_SAME_LAYER, "Type", "");
+ static const EnumPropertyItem prop_select_grouped_types[] = {
+ {GP_SEL_SAME_LAYER, "LAYER", 0, "Layer", "Shared layers"},
+ {GP_SEL_SAME_MATERIAL, "MATERIAL", 0, "Material", "Shared materials"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Select Grouped";
+ ot->idname = "GPENCIL_OT_select_grouped";
+ ot->description = "Select all strokes with similar characteristics";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = gpencil_select_grouped_exec;
+ ot->poll = gpencil_select_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", prop_select_grouped_types, GP_SEL_SAME_LAYER, "Type", "");
}
/** \} */
@@ -448,71 +447,77 @@ void GPENCIL_OT_select_grouped(wmOperatorType *ot)
static int gpencil_select_first_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- /* if not edit/sculpt mode, the event is catched but not processed */
- if (GPENCIL_NONE_EDIT_MODE(gpd)) {
- return OPERATOR_CANCELLED;
- }
-
- const bool only_selected = RNA_boolean_get(op->ptr, "only_selected_strokes");
- const bool extend = RNA_boolean_get(op->ptr, "extend");
-
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- /* skip stroke if we're only manipulating selected strokes */
- if (only_selected && !(gps->flag & GP_STROKE_SELECT)) {
- continue;
- }
-
- /* select first point */
- BLI_assert(gps->totpoints >= 1);
-
- gps->points->flag |= GP_SPOINT_SELECT;
- gps->flag |= GP_STROKE_SELECT;
-
- /* deselect rest? */
- if ((extend == false) && (gps->totpoints > 1)) {
- /* start from index 1, to skip the first point that we'd just selected... */
- bGPDspoint *pt = &gps->points[1];
- int i = 1;
-
- for (; i < gps->totpoints; i++, pt++) {
- pt->flag &= ~GP_SPOINT_SELECT;
- }
- }
- }
- CTX_DATA_END;
-
- /* 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);
- return OPERATOR_FINISHED;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ /* if not edit/sculpt mode, the event is catched but not processed */
+ if (GPENCIL_NONE_EDIT_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ const bool only_selected = RNA_boolean_get(op->ptr, "only_selected_strokes");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ /* skip stroke if we're only manipulating selected strokes */
+ if (only_selected && !(gps->flag & GP_STROKE_SELECT)) {
+ continue;
+ }
+
+ /* select first point */
+ BLI_assert(gps->totpoints >= 1);
+
+ gps->points->flag |= GP_SPOINT_SELECT;
+ gps->flag |= GP_STROKE_SELECT;
+
+ /* deselect rest? */
+ if ((extend == false) && (gps->totpoints > 1)) {
+ /* start from index 1, to skip the first point that we'd just selected... */
+ bGPDspoint *pt = &gps->points[1];
+ int i = 1;
+
+ for (; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* 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);
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_select_first(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select First";
- ot->idname = "GPENCIL_OT_select_first";
- ot->description = "Select first point in Grease Pencil strokes";
-
- /* callbacks */
- ot->exec = gpencil_select_first_exec;
- ot->poll = gpencil_select_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "only_selected_strokes", false, "Selected Strokes Only",
- "Only select the first point of strokes that already have points selected");
-
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting all other selected points");
+ /* identifiers */
+ ot->name = "Select First";
+ ot->idname = "GPENCIL_OT_select_first";
+ ot->description = "Select first point in Grease Pencil strokes";
+
+ /* callbacks */
+ ot->exec = gpencil_select_first_exec;
+ ot->poll = gpencil_select_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "only_selected_strokes",
+ false,
+ "Selected Strokes Only",
+ "Only select the first point of strokes that already have points selected");
+
+ RNA_def_boolean(ot->srna,
+ "extend",
+ false,
+ "Extend",
+ "Extend selection instead of deselecting all other selected points");
}
/** \} */
@@ -523,71 +528,77 @@ void GPENCIL_OT_select_first(wmOperatorType *ot)
static int gpencil_select_last_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- /* if not edit/sculpt mode, the event is catched but not processed */
- if (GPENCIL_NONE_EDIT_MODE(gpd)) {
- return OPERATOR_CANCELLED;
- }
-
- const bool only_selected = RNA_boolean_get(op->ptr, "only_selected_strokes");
- const bool extend = RNA_boolean_get(op->ptr, "extend");
-
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- /* skip stroke if we're only manipulating selected strokes */
- if (only_selected && !(gps->flag & GP_STROKE_SELECT)) {
- continue;
- }
-
- /* select last point */
- BLI_assert(gps->totpoints >= 1);
-
- gps->points[gps->totpoints - 1].flag |= GP_SPOINT_SELECT;
- gps->flag |= GP_STROKE_SELECT;
-
- /* deselect rest? */
- if ((extend == false) && (gps->totpoints > 1)) {
- /* don't include the last point... */
- bGPDspoint *pt = gps->points;
- int i = 1;
-
- for (; i < gps->totpoints - 1; i++, pt++) {
- pt->flag &= ~GP_SPOINT_SELECT;
- }
- }
- }
- CTX_DATA_END;
-
- /* 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);
- return OPERATOR_FINISHED;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ /* if not edit/sculpt mode, the event is catched but not processed */
+ if (GPENCIL_NONE_EDIT_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ const bool only_selected = RNA_boolean_get(op->ptr, "only_selected_strokes");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ /* skip stroke if we're only manipulating selected strokes */
+ if (only_selected && !(gps->flag & GP_STROKE_SELECT)) {
+ continue;
+ }
+
+ /* select last point */
+ BLI_assert(gps->totpoints >= 1);
+
+ gps->points[gps->totpoints - 1].flag |= GP_SPOINT_SELECT;
+ gps->flag |= GP_STROKE_SELECT;
+
+ /* deselect rest? */
+ if ((extend == false) && (gps->totpoints > 1)) {
+ /* don't include the last point... */
+ bGPDspoint *pt = gps->points;
+ int i = 1;
+
+ for (; i < gps->totpoints - 1; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* 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);
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_select_last(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Last";
- ot->idname = "GPENCIL_OT_select_last";
- ot->description = "Select last point in Grease Pencil strokes";
-
- /* callbacks */
- ot->exec = gpencil_select_last_exec;
- ot->poll = gpencil_select_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "only_selected_strokes", false, "Selected Strokes Only",
- "Only select the last point of strokes that already have points selected");
-
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting all other selected points");
+ /* identifiers */
+ ot->name = "Select Last";
+ ot->idname = "GPENCIL_OT_select_last";
+ ot->description = "Select last point in Grease Pencil strokes";
+
+ /* callbacks */
+ ot->exec = gpencil_select_last_exec;
+ ot->poll = gpencil_select_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "only_selected_strokes",
+ false,
+ "Selected Strokes Only",
+ "Only select the last point of strokes that already have points selected");
+
+ RNA_def_boolean(ot->srna,
+ "extend",
+ false,
+ "Extend",
+ "Extend selection instead of deselecting all other selected points");
}
/** \} */
@@ -598,81 +609,80 @@ void GPENCIL_OT_select_last(wmOperatorType *ot)
static int gpencil_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- /* if not edit/sculpt mode, the event is catched but not processed */
- if (GPENCIL_NONE_EDIT_MODE(gpd)) {
- return OPERATOR_CANCELLED;
- }
-
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- if (gps->flag & GP_STROKE_SELECT) {
- bGPDspoint *pt;
- int i;
- bool prev_sel;
-
- /* First Pass: Go in forward order, expanding selection if previous was selected (pre changes)...
- * - This pass covers the "after" edges of selection islands
- */
- prev_sel = false;
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT) {
- /* selected point - just set flag for next point */
- prev_sel = true;
- }
- else {
- /* unselected point - expand selection if previous was selected... */
- if (prev_sel) {
- pt->flag |= GP_SPOINT_SELECT;
- }
- prev_sel = false;
- }
- }
-
- /* Second Pass: Go in reverse order, doing the same as before (except in opposite order)
- * - This pass covers the "before" edges of selection islands
- */
- prev_sel = false;
- for (pt -= 1; i > 0; i--, pt--) {
- if (pt->flag & GP_SPOINT_SELECT) {
- prev_sel = true;
- }
- else {
- /* unselected point - expand selection if previous was selected... */
- if (prev_sel) {
- pt->flag |= GP_SPOINT_SELECT;
- }
- prev_sel = false;
- }
- }
- }
- }
- CTX_DATA_END;
-
- /* 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);
- return OPERATOR_FINISHED;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ /* if not edit/sculpt mode, the event is catched but not processed */
+ if (GPENCIL_NONE_EDIT_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+ bool prev_sel;
+
+ /* First Pass: Go in forward order, expanding selection if previous was selected (pre changes)...
+ * - This pass covers the "after" edges of selection islands
+ */
+ prev_sel = false;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ /* selected point - just set flag for next point */
+ prev_sel = true;
+ }
+ else {
+ /* unselected point - expand selection if previous was selected... */
+ if (prev_sel) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ prev_sel = false;
+ }
+ }
+
+ /* Second Pass: Go in reverse order, doing the same as before (except in opposite order)
+ * - This pass covers the "before" edges of selection islands
+ */
+ prev_sel = false;
+ for (pt -= 1; i > 0; i--, pt--) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ prev_sel = true;
+ }
+ else {
+ /* unselected point - expand selection if previous was selected... */
+ if (prev_sel) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ prev_sel = false;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* 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);
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_select_more(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select More";
- ot->idname = "GPENCIL_OT_select_more";
- ot->description = "Grow sets of selected Grease Pencil points";
+ /* identifiers */
+ ot->name = "Select More";
+ ot->idname = "GPENCIL_OT_select_more";
+ ot->description = "Grow sets of selected Grease Pencil points";
- /* callbacks */
- ot->exec = gpencil_select_more_exec;
- ot->poll = gpencil_select_poll;
+ /* callbacks */
+ ot->exec = gpencil_select_more_exec;
+ ot->poll = gpencil_select_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -683,82 +693,81 @@ void GPENCIL_OT_select_more(wmOperatorType *ot)
static int gpencil_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- /* if not edit/sculpt mode, the event is catched but not processed */
- if (GPENCIL_NONE_EDIT_MODE(gpd)) {
- return OPERATOR_CANCELLED;
- }
-
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- if (gps->flag & GP_STROKE_SELECT) {
- bGPDspoint *pt;
- int i;
- bool prev_sel;
-
- /* First Pass: Go in forward order, shrinking selection if previous was not selected (pre changes)...
- * - This pass covers the "after" edges of selection islands
- */
- prev_sel = false;
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT) {
- /* shrink if previous wasn't selected */
- if (prev_sel == false) {
- pt->flag &= ~GP_SPOINT_SELECT;
- }
- prev_sel = true;
- }
- else {
- /* mark previous as being unselected - and hence, is trigger for shrinking */
- prev_sel = false;
- }
- }
-
- /* Second Pass: Go in reverse order, doing the same as before (except in opposite order)
- * - This pass covers the "before" edges of selection islands
- */
- prev_sel = false;
- for (pt -= 1; i > 0; i--, pt--) {
- if (pt->flag & GP_SPOINT_SELECT) {
- /* shrink if previous wasn't selected */
- if (prev_sel == false) {
- pt->flag &= ~GP_SPOINT_SELECT;
- }
- prev_sel = true;
- }
- else {
- /* mark previous as being unselected - and hence, is trigger for shrinking */
- prev_sel = false;
- }
- }
- }
- }
- CTX_DATA_END;
-
- /* 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);
- return OPERATOR_FINISHED;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ /* if not edit/sculpt mode, the event is catched but not processed */
+ if (GPENCIL_NONE_EDIT_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+ bool prev_sel;
+
+ /* First Pass: Go in forward order, shrinking selection if previous was not selected (pre changes)...
+ * - This pass covers the "after" edges of selection islands
+ */
+ prev_sel = false;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ /* shrink if previous wasn't selected */
+ if (prev_sel == false) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ prev_sel = true;
+ }
+ else {
+ /* mark previous as being unselected - and hence, is trigger for shrinking */
+ prev_sel = false;
+ }
+ }
+
+ /* Second Pass: Go in reverse order, doing the same as before (except in opposite order)
+ * - This pass covers the "before" edges of selection islands
+ */
+ prev_sel = false;
+ for (pt -= 1; i > 0; i--, pt--) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ /* shrink if previous wasn't selected */
+ if (prev_sel == false) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ prev_sel = true;
+ }
+ else {
+ /* mark previous as being unselected - and hence, is trigger for shrinking */
+ prev_sel = false;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* 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);
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_select_less(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Less";
- ot->idname = "GPENCIL_OT_select_less";
- ot->description = "Shrink sets of selected Grease Pencil points";
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->idname = "GPENCIL_OT_select_less";
+ ot->description = "Shrink sets of selected Grease Pencil points";
- /* callbacks */
- ot->exec = gpencil_select_less_exec;
- ot->poll = gpencil_select_poll;
+ /* callbacks */
+ ot->exec = gpencil_select_less_exec;
+ ot->poll = gpencil_select_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -771,216 +780,213 @@ void GPENCIL_OT_select_less(wmOperatorType *ot)
/* NOTE: Code here is adapted (i.e. copied directly) 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(
- bGPDlayer *gpl,
- bGPDstroke *gps, GP_SpaceConversion *gsc,
- const int mx, const int my, const int radius,
- const bool select, rcti *rect, float diff_mat[4][4], const int selectmode,
- const float scale)
+static bool gp_stroke_do_circle_sel(bGPDlayer *gpl,
+ bGPDstroke *gps,
+ GP_SpaceConversion *gsc,
+ const int mx,
+ const int my,
+ const int radius,
+ const bool select,
+ rcti *rect,
+ float diff_mat[4][4],
+ const int selectmode,
+ const float scale)
{
- bGPDspoint *pt1 = NULL;
- bGPDspoint *pt2 = NULL;
- int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
- int i;
- bool changed = false;
-
- if (gps->totpoints == 1) {
- bGPDspoint pt_temp;
- gp_point_to_parent_space(gps->points, diff_mat, &pt_temp);
- gp_point_to_xy(gsc, gps, &pt_temp, &x0, &y0);
-
- /* do boundbox check first */
- if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) {
- /* only check if point is inside */
- if (((x0 - mx) * (x0 - mx) + (y0 - my) * (y0 - my)) <= radius * radius) {
- /* change selection */
- if (select) {
- gps->points->flag |= GP_SPOINT_SELECT;
- gps->flag |= GP_STROKE_SELECT;
- }
- else {
- gps->points->flag &= ~GP_SPOINT_SELECT;
- gps->flag &= ~GP_STROKE_SELECT;
- }
-
- return true;
- }
- }
- }
- else {
- /* Loop over the points in the stroke, checking for intersections
- * - an intersection means that we touched the stroke
- */
- bool hit = false;
- for (i = 0; (i + 1) < gps->totpoints; i++) {
- /* get points to work with */
- pt1 = gps->points + i;
- pt2 = gps->points + i + 1;
- bGPDspoint npt;
- gp_point_to_parent_space(pt1, diff_mat, &npt);
- gp_point_to_xy(gsc, gps, &npt, &x0, &y0);
-
- gp_point_to_parent_space(pt2, diff_mat, &npt);
- gp_point_to_xy(gsc, gps, &npt, &x1, &y1);
-
- /* check that point segment of the boundbox of the selection stroke */
- 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)) {
- /* 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) {
- pt1->flag |= GP_SPOINT_SELECT;
- pt2->flag |= GP_SPOINT_SELECT;
-
- changed = true;
- }
- else {
- pt1->flag &= ~GP_SPOINT_SELECT;
- pt2->flag &= ~GP_SPOINT_SELECT;
-
- changed = true;
- }
- }
- }
- /* if stroke mode, don't check more points */
- if ((hit) && (selectmode == GP_SELECTMODE_STROKE)) {
- break;
- }
- }
-
- /* if stroke mode expand selection */
- if ((hit) && (selectmode == GP_SELECTMODE_STROKE)) {
- for (i = 0, pt1 = gps->points; i < gps->totpoints; i++, pt1++) {
- if (select) {
- pt1->flag |= GP_SPOINT_SELECT;
- }
- else {
- pt1->flag &= ~GP_SPOINT_SELECT;
- }
- }
- }
-
- /* expand selection to segment */
- if ((hit) && (selectmode == GP_SELECTMODE_SEGMENT) && (select)) {
- float r_hita[3], r_hitb[3];
- bool hit_select = (bool)(pt1->flag & GP_SPOINT_SELECT);
- ED_gpencil_select_stroke_segment(
- gpl, gps, pt1, hit_select, false, scale, r_hita, r_hitb);
- }
-
- /* Ensure that stroke selection is in sync with its points */
- BKE_gpencil_stroke_sync_selection(gps);
- }
-
- return changed;
+ bGPDspoint *pt1 = NULL;
+ bGPDspoint *pt2 = NULL;
+ int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
+ int i;
+ bool changed = false;
+
+ if (gps->totpoints == 1) {
+ bGPDspoint pt_temp;
+ gp_point_to_parent_space(gps->points, diff_mat, &pt_temp);
+ gp_point_to_xy(gsc, gps, &pt_temp, &x0, &y0);
+
+ /* do boundbox check first */
+ if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) {
+ /* only check if point is inside */
+ if (((x0 - mx) * (x0 - mx) + (y0 - my) * (y0 - my)) <= radius * radius) {
+ /* change selection */
+ if (select) {
+ gps->points->flag |= GP_SPOINT_SELECT;
+ gps->flag |= GP_STROKE_SELECT;
+ }
+ else {
+ gps->points->flag &= ~GP_SPOINT_SELECT;
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+
+ return true;
+ }
+ }
+ }
+ else {
+ /* Loop over the points in the stroke, checking for intersections
+ * - an intersection means that we touched the stroke
+ */
+ bool hit = false;
+ for (i = 0; (i + 1) < gps->totpoints; i++) {
+ /* get points to work with */
+ pt1 = gps->points + i;
+ pt2 = gps->points + i + 1;
+ bGPDspoint npt;
+ gp_point_to_parent_space(pt1, diff_mat, &npt);
+ gp_point_to_xy(gsc, gps, &npt, &x0, &y0);
+
+ gp_point_to_parent_space(pt2, diff_mat, &npt);
+ gp_point_to_xy(gsc, gps, &npt, &x1, &y1);
+
+ /* check that point segment of the boundbox of the selection stroke */
+ 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)) {
+ /* 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) {
+ pt1->flag |= GP_SPOINT_SELECT;
+ pt2->flag |= GP_SPOINT_SELECT;
+
+ changed = true;
+ }
+ else {
+ pt1->flag &= ~GP_SPOINT_SELECT;
+ pt2->flag &= ~GP_SPOINT_SELECT;
+
+ changed = true;
+ }
+ }
+ }
+ /* if stroke mode, don't check more points */
+ if ((hit) && (selectmode == GP_SELECTMODE_STROKE)) {
+ break;
+ }
+ }
+
+ /* if stroke mode expand selection */
+ if ((hit) && (selectmode == GP_SELECTMODE_STROKE)) {
+ for (i = 0, pt1 = gps->points; i < gps->totpoints; i++, pt1++) {
+ if (select) {
+ pt1->flag |= GP_SPOINT_SELECT;
+ }
+ else {
+ pt1->flag &= ~GP_SPOINT_SELECT;
+ }
+ }
+ }
+
+ /* expand selection to segment */
+ if ((hit) && (selectmode == GP_SELECTMODE_SEGMENT) && (select)) {
+ float r_hita[3], r_hitb[3];
+ bool hit_select = (bool)(pt1->flag & GP_SPOINT_SELECT);
+ ED_gpencil_select_stroke_segment(gpl, gps, pt1, hit_select, false, scale, r_hita, r_hitb);
+ }
+
+ /* Ensure that stroke selection is in sync with its points */
+ BKE_gpencil_stroke_sync_selection(gps);
+ }
+
+ return changed;
}
-
static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- const int selectmode = ts->gpencil_selectmode;
- const float scale = ts->gp_sculpt.isect_threshold;
-
- /* if not edit/sculpt mode, the event is catched but not processed */
- if (GPENCIL_NONE_EDIT_MODE(gpd)) {
- return OPERATOR_CANCELLED;
- }
-
- ScrArea *sa = CTX_wm_area(C);
-
- const int mx = RNA_int_get(op->ptr, "x");
- const int my = RNA_int_get(op->ptr, "y");
- const int radius = RNA_int_get(op->ptr, "radius");
-
- GP_SpaceConversion gsc = {NULL};
- /* for bounding rect around circle (for quicky intersection testing) */
- rcti rect = {0};
-
- bool changed = false;
-
-
- /* sanity checks */
- if (sa == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active area");
- return OPERATOR_CANCELLED;
- }
-
- 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);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- ED_gpencil_select_toggle_all(C, SEL_DESELECT);
- changed = true;
- }
-
- /* init space conversion stuff */
- gp_point_conversion_init(C, &gsc);
-
-
- /* rect is rectangle of selection circle */
- rect.xmin = mx - radius;
- rect.ymin = my - radius;
- rect.xmax = mx + radius;
- rect.ymax = my + radius;
-
-
- /* find visible strokes, and select if hit */
- GP_EDITABLE_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
- {
- changed |= gp_stroke_do_circle_sel(
- gpl, gps, &gsc, mx, my, radius, select, &rect,
- gpstroke_iter.diff_mat, selectmode, scale);
- }
- GP_EDITABLE_STROKES_END(gpstroke_iter);
-
- /* updates */
- if (changed) {
- 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);
- }
-
- return OPERATOR_FINISHED;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ const int selectmode = ts->gpencil_selectmode;
+ const float scale = ts->gp_sculpt.isect_threshold;
+
+ /* if not edit/sculpt mode, the event is catched but not processed */
+ if (GPENCIL_NONE_EDIT_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ ScrArea *sa = CTX_wm_area(C);
+
+ const int mx = RNA_int_get(op->ptr, "x");
+ const int my = RNA_int_get(op->ptr, "y");
+ const int radius = RNA_int_get(op->ptr, "radius");
+
+ GP_SpaceConversion gsc = {NULL};
+ /* for bounding rect around circle (for quicky intersection testing) */
+ rcti rect = {0};
+
+ bool changed = false;
+
+ /* sanity checks */
+ if (sa == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active area");
+ return OPERATOR_CANCELLED;
+ }
+
+ 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);
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ ED_gpencil_select_toggle_all(C, SEL_DESELECT);
+ changed = true;
+ }
+
+ /* init space conversion stuff */
+ gp_point_conversion_init(C, &gsc);
+
+ /* rect is rectangle of selection circle */
+ rect.xmin = mx - radius;
+ rect.ymin = my - radius;
+ rect.xmax = mx + radius;
+ rect.ymax = my + radius;
+
+ /* find visible strokes, and select if hit */
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ changed |= gp_stroke_do_circle_sel(
+ gpl, gps, &gsc, mx, my, radius, select, &rect, gpstroke_iter.diff_mat, selectmode, scale);
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
+
+ /* updates */
+ if (changed) {
+ 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);
+ }
+
+ return OPERATOR_FINISHED;
}
void GPENCIL_OT_select_circle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Circle Select";
- ot->description = "Select Grease Pencil strokes using brush selection";
- ot->idname = "GPENCIL_OT_select_circle";
-
- /* callbacks */
- ot->invoke = WM_gesture_circle_invoke;
- ot->modal = WM_gesture_circle_modal;
- ot->exec = gpencil_circle_select_exec;
- ot->poll = gpencil_select_poll;
- ot->cancel = WM_gesture_circle_cancel;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
-
- /* properties */
- WM_operator_properties_gesture_circle(ot);
- WM_operator_properties_select_operation_simple(ot);
+ /* identifiers */
+ ot->name = "Circle Select";
+ ot->description = "Select Grease Pencil strokes using brush selection";
+ ot->idname = "GPENCIL_OT_select_circle";
+
+ /* callbacks */
+ ot->invoke = WM_gesture_circle_invoke;
+ ot->modal = WM_gesture_circle_modal;
+ ot->exec = gpencil_circle_select_exec;
+ ot->poll = gpencil_select_poll;
+ ot->cancel = WM_gesture_circle_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+
+ /* properties */
+ WM_operator_properties_gesture_circle(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
/** \} */
@@ -992,135 +998,132 @@ void GPENCIL_OT_select_circle(wmOperatorType *ot)
*
* \{ */
-typedef bool (*GPencilTestFn)(
- bGPDstroke *gps, bGPDspoint *pt,
- const GP_SpaceConversion *gsc, const float diff_mat[4][4], void *user_data);
+typedef bool (*GPencilTestFn)(bGPDstroke *gps,
+ bGPDspoint *pt,
+ const GP_SpaceConversion *gsc,
+ const float diff_mat[4][4],
+ void *user_data);
-static int gpencil_generic_select_exec(
- bContext *C, wmOperator *op,
- GPencilTestFn is_inside_fn, void *user_data)
+static int gpencil_generic_select_exec(bContext *C,
+ wmOperator *op,
+ GPencilTestFn is_inside_fn,
+ void *user_data)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- ScrArea *sa = CTX_wm_area(C);
- const bool strokemode = (
- (ts->gpencil_selectmode == GP_SELECTMODE_STROKE) &&
- ((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0));
- const bool segmentmode = (
- (ts->gpencil_selectmode == GP_SELECTMODE_SEGMENT) &&
- ((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0));
- const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
- const float scale = ts->gp_sculpt.isect_threshold;
-
-
- GP_SpaceConversion gsc = {NULL};
-
- bool changed = false;
-
- /* sanity checks */
- if (sa == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active area");
- return OPERATOR_CANCELLED;
- }
-
- /* init space conversion stuff */
- gp_point_conversion_init(C, &gsc);
-
- /* deselect all strokes first? */
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
-
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- bGPDspoint *pt;
- int i;
-
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- pt->flag &= ~GP_SPOINT_SELECT;
- }
-
- gps->flag &= ~GP_STROKE_SELECT;
- }
- CTX_DATA_END;
- }
-
- /* select/deselect points */
- GP_EDITABLE_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
- {
-
- bGPDspoint *pt;
- int i;
- bool hit = false;
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- /* convert point coords to screenspace */
- const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data);
-
- if (strokemode == false) {
- const bool is_select = (pt->flag & GP_SPOINT_SELECT) != 0;
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(pt->flag, sel_op_result, GP_SPOINT_SELECT);
- changed = true;
-
- /* expand selection to segment */
- if ((sel_op_result != -1) && (segmentmode)) {
- bool hit_select = (bool)(pt->flag & GP_SPOINT_SELECT);
- float r_hita[3], r_hitb[3];
- ED_gpencil_select_stroke_segment(
- gpl, gps, pt, hit_select, false, scale, r_hita, r_hitb);
- }
-
- }
- }
- else {
- if (is_inside) {
- hit = true;
- break;
- }
- }
- }
-
- /* if stroke mode expand selection */
- if (strokemode) {
- const bool is_select = BKE_gpencil_stroke_select_check(gps);
- const bool is_inside = hit;
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (sel_op_result) {
- pt->flag |= GP_SPOINT_SELECT;
- }
- else {
- pt->flag &= ~GP_SPOINT_SELECT;
- }
- }
- changed = true;
- }
- }
-
- /* Ensure that stroke selection is in sync with its points */
- BKE_gpencil_stroke_sync_selection(gps);
- }
- GP_EDITABLE_STROKES_END(gpstroke_iter);
-
- /* if paint mode,delete selected points */
- if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
- gp_delete_selected_point_wrap(C);
- changed = true;
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- }
-
- /* updates */
- if (changed) {
- 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);
- }
-
- return OPERATOR_FINISHED;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ ScrArea *sa = CTX_wm_area(C);
+ const bool strokemode = ((ts->gpencil_selectmode == GP_SELECTMODE_STROKE) &&
+ ((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0));
+ const bool segmentmode = ((ts->gpencil_selectmode == GP_SELECTMODE_SEGMENT) &&
+ ((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0));
+ const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
+ const float scale = ts->gp_sculpt.isect_threshold;
+
+ GP_SpaceConversion gsc = {NULL};
+
+ bool changed = false;
+
+ /* sanity checks */
+ if (sa == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active area");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* init space conversion stuff */
+ gp_point_conversion_init(C, &gsc);
+
+ /* deselect all strokes first? */
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ bGPDspoint *pt;
+ int i;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ CTX_DATA_END;
+ }
+
+ /* select/deselect points */
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+
+ bGPDspoint *pt;
+ int i;
+ bool hit = false;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ /* convert point coords to screenspace */
+ const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data);
+
+ if (strokemode == false) {
+ const bool is_select = (pt->flag & GP_SPOINT_SELECT) != 0;
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ SET_FLAG_FROM_TEST(pt->flag, sel_op_result, GP_SPOINT_SELECT);
+ changed = true;
+
+ /* expand selection to segment */
+ if ((sel_op_result != -1) && (segmentmode)) {
+ bool hit_select = (bool)(pt->flag & GP_SPOINT_SELECT);
+ float r_hita[3], r_hitb[3];
+ ED_gpencil_select_stroke_segment(
+ gpl, gps, pt, hit_select, false, scale, r_hita, r_hitb);
+ }
+ }
+ }
+ else {
+ if (is_inside) {
+ hit = true;
+ break;
+ }
+ }
+ }
+
+ /* if stroke mode expand selection */
+ if (strokemode) {
+ const bool is_select = BKE_gpencil_stroke_select_check(gps);
+ const bool is_inside = hit;
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (sel_op_result) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ else {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ }
+ changed = true;
+ }
+ }
+
+ /* Ensure that stroke selection is in sync with its points */
+ BKE_gpencil_stroke_sync_selection(gps);
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
+
+ /* if paint mode,delete selected points */
+ if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
+ gp_delete_selected_point_wrap(C);
+ changed = true;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ }
+
+ /* updates */
+ if (changed) {
+ 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);
+ }
+
+ return OPERATOR_FINISHED;
}
/** \} */
@@ -1130,52 +1133,51 @@ static int gpencil_generic_select_exec(
* \{ */
struct GP_SelectBoxUserData {
- rcti rect;
+ rcti rect;
};
-static bool gpencil_test_box(
- bGPDstroke *gps, bGPDspoint *pt,
- const GP_SpaceConversion *gsc, const float diff_mat[4][4], void *user_data)
+static bool gpencil_test_box(bGPDstroke *gps,
+ bGPDspoint *pt,
+ const GP_SpaceConversion *gsc,
+ const float diff_mat[4][4],
+ void *user_data)
{
- const struct GP_SelectBoxUserData *data = user_data;
- bGPDspoint pt2;
- int x0, y0;
- gp_point_to_parent_space(pt, diff_mat, &pt2);
- gp_point_to_xy(gsc, gps, &pt2, &x0, &y0);
- return ((!ELEM(V2D_IS_CLIPPED, x0, y0)) &&
- BLI_rcti_isect_pt(&data->rect, x0, y0));
+ const struct GP_SelectBoxUserData *data = user_data;
+ bGPDspoint pt2;
+ int x0, y0;
+ gp_point_to_parent_space(pt, diff_mat, &pt2);
+ gp_point_to_xy(gsc, gps, &pt2, &x0, &y0);
+ return ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&data->rect, x0, y0));
}
static int gpencil_box_select_exec(bContext *C, wmOperator *op)
{
- struct GP_SelectBoxUserData data = {0};
- WM_operator_properties_border_to_rcti(op, &data.rect);
- return gpencil_generic_select_exec(
- C, op,
- gpencil_test_box, &data);
+ struct GP_SelectBoxUserData data = {0};
+ WM_operator_properties_border_to_rcti(op, &data.rect);
+ return gpencil_generic_select_exec(C, op, gpencil_test_box, &data);
}
void GPENCIL_OT_select_box(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Box Select";
- ot->description = "Select Grease Pencil strokes within a rectangular region";
- ot->idname = "GPENCIL_OT_select_box";
+ /* identifiers */
+ ot->name = "Box Select";
+ ot->description = "Select Grease Pencil strokes within a rectangular region";
+ ot->idname = "GPENCIL_OT_select_box";
- /* callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = gpencil_box_select_exec;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
+ /* callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = gpencil_box_select_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
- ot->poll = gpencil_select_poll;
+ ot->poll = gpencil_select_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
- /* properties */
- WM_operator_properties_gesture_box(ot);
- WM_operator_properties_select_operation(ot);
+ /* properties */
+ WM_operator_properties_gesture_box(ot);
+ WM_operator_properties_select_operation(ot);
}
/** \} */
@@ -1185,67 +1187,65 @@ void GPENCIL_OT_select_box(wmOperatorType *ot)
* \{ */
struct GP_SelectLassoUserData {
- rcti rect;
- const int (*mcords)[2];
- int mcords_len;
+ rcti rect;
+ const int (*mcords)[2];
+ int mcords_len;
};
-static bool gpencil_test_lasso(
- bGPDstroke *gps, bGPDspoint *pt,
- const GP_SpaceConversion *gsc, const float diff_mat[4][4],
- void *user_data)
+static bool gpencil_test_lasso(bGPDstroke *gps,
+ bGPDspoint *pt,
+ const GP_SpaceConversion *gsc,
+ const float diff_mat[4][4],
+ void *user_data)
{
- const struct GP_SelectLassoUserData *data = user_data;
- bGPDspoint pt2;
- int x0, y0;
- gp_point_to_parent_space(pt, diff_mat, &pt2);
- 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));
+ const struct GP_SelectLassoUserData *data = user_data;
+ bGPDspoint pt2;
+ int x0, y0;
+ gp_point_to_parent_space(pt, diff_mat, &pt2);
+ 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));
}
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);
+ struct GP_SelectLassoUserData data = {0};
+ data.mcords = WM_gesture_lasso_path_to_array(C, op, &data.mcords_len);
- /* Sanity check. */
- if (data.mcords == NULL) {
- return OPERATOR_PASS_THROUGH;
- }
+ /* Sanity check. */
+ if (data.mcords == NULL) {
+ return OPERATOR_PASS_THROUGH;
+ }
- /* Compute boundbox of lasso (for faster testing later). */
- BLI_lasso_boundbox(&data.rect, data.mcords, data.mcords_len);
+ /* Compute boundbox of lasso (for faster testing later). */
+ BLI_lasso_boundbox(&data.rect, data.mcords, data.mcords_len);
- int ret = gpencil_generic_select_exec(
- C, op,
- gpencil_test_lasso, &data);
+ int ret = gpencil_generic_select_exec(C, op, gpencil_test_lasso, &data);
- MEM_freeN((void *)data.mcords);
+ MEM_freeN((void *)data.mcords);
- return ret;
+ return ret;
}
void GPENCIL_OT_select_lasso(wmOperatorType *ot)
{
- ot->name = "Lasso Select Strokes";
- ot->description = "Select Grease Pencil strokes using lasso selection";
- ot->idname = "GPENCIL_OT_select_lasso";
-
- ot->invoke = WM_gesture_lasso_invoke;
- ot->modal = WM_gesture_lasso_modal;
- ot->exec = gpencil_lasso_select_exec;
- ot->poll = gpencil_select_poll;
- ot->cancel = WM_gesture_lasso_cancel;
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
-
- /* properties */
- WM_operator_properties_select_operation(ot);
- WM_operator_properties_gesture_lasso(ot);
+ ot->name = "Lasso Select Strokes";
+ ot->description = "Select Grease Pencil strokes using lasso selection";
+ ot->idname = "GPENCIL_OT_select_lasso";
+
+ ot->invoke = WM_gesture_lasso_invoke;
+ ot->modal = WM_gesture_lasso_modal;
+ ot->exec = gpencil_lasso_select_exec;
+ ot->poll = gpencil_select_poll;
+ ot->cancel = WM_gesture_lasso_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+
+ /* properties */
+ WM_operator_properties_select_operation(ot);
+ WM_operator_properties_gesture_lasso(ot);
}
/** \} */
@@ -1257,215 +1257,225 @@ void GPENCIL_OT_select_lasso(wmOperatorType *ot)
/* helper to deselect all selected strokes/points */
static void deselect_all_selected(bContext *C)
{
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- /* deselect stroke and its points if selected */
- if (gps->flag & GP_STROKE_SELECT) {
- bGPDspoint *pt;
- int i;
-
- /* deselect points */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- pt->flag &= ~GP_SPOINT_SELECT;
- }
-
- /* deselect stroke itself too */
- gps->flag &= ~GP_STROKE_SELECT;
- }
- }
- CTX_DATA_END;
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ /* deselect stroke and its points if selected */
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ /* deselect points */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ /* deselect stroke itself too */
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ }
+ CTX_DATA_END;
}
static int gpencil_select_exec(bContext *C, wmOperator *op)
{
- ScrArea *sa = CTX_wm_area(C);
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- const float scale = ts->gp_sculpt.isect_threshold;
-
- /* "radius" is simply a threshold (screen space) to make it easier to test with a tolerance */
- const float radius = 0.50f * U.widget_unit;
- const int radius_squared = (int)(radius * radius);
-
- bool extend = RNA_boolean_get(op->ptr, "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");
-
- int mval[2] = {0};
-
- GP_SpaceConversion gsc = {NULL};
-
- bGPDlayer *hit_layer = NULL;
- bGPDstroke *hit_stroke = NULL;
- bGPDspoint *hit_point = NULL;
- int hit_distance = radius_squared;
-
- /* sanity checks */
- if (sa == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active area");
- return OPERATOR_CANCELLED;
- }
-
- /* if select mode is stroke, use whole stroke */
- if (ts->gpencil_selectmode == GP_SELECTMODE_STROKE) {
- whole = true;
- }
-
- /* init space conversion stuff */
- gp_point_conversion_init(C, &gsc);
-
- /* get mouse location */
- RNA_int_get_array(op->ptr, "location", mval);
-
- /* First Pass: Find stroke point which gets hit */
- /* XXX: maybe we should go from the top of the stack down instead... */
- GP_EDITABLE_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
- {
- bGPDspoint *pt;
- int i;
-
- /* firstly, check for hit-point */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- int xy[2];
-
- bGPDspoint pt2;
- gp_point_to_parent_space(pt, gpstroke_iter.diff_mat, &pt2);
- gp_point_to_xy(&gsc, gps, &pt2, &xy[0], &xy[1]);
-
- /* do boundbox check first */
- if (!ELEM(V2D_IS_CLIPPED, xy[0], xy[1])) {
- const int pt_distance = len_manhattan_v2v2_int(mval, xy);
-
- /* check if point is inside */
- if (pt_distance <= radius_squared) {
- /* only use this point if it is a better match than the current hit - T44685 */
- if (pt_distance < hit_distance) {
- hit_layer = gpl;
- hit_stroke = gps;
- hit_point = pt;
- hit_distance = pt_distance;
- }
- }
- }
- }
- }
- GP_EDITABLE_STROKES_END(gpstroke_iter);
-
- /* Abort if nothing hit... */
- if (ELEM(NULL, hit_stroke, hit_point)) {
-
- /* since left mouse select change, deselect all if click outside any hit */
- deselect_all_selected(C);
-
- /* copy on write tag is needed, or else no refresh happens */
- DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
- 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);
-
- return OPERATOR_CANCELLED;
- }
-
- /* adjust selection behavior - for toggle option */
- if (toggle) {
- deselect = (hit_point->flag & GP_SPOINT_SELECT) != 0;
- }
-
- /* If not extending selection, deselect everything else */
- if (extend == false) {
- deselect_all_selected(C);
- }
-
- /* Perform selection operations... */
- if (whole) {
- bGPDspoint *pt;
- int i;
-
- /* entire stroke's points */
- for (i = 0, pt = hit_stroke->points; i < hit_stroke->totpoints; i++, pt++) {
- if (deselect == false)
- pt->flag |= GP_SPOINT_SELECT;
- else
- pt->flag &= ~GP_SPOINT_SELECT;
- }
-
- /* stroke too... */
- if (deselect == false)
- hit_stroke->flag |= GP_STROKE_SELECT;
- else
- hit_stroke->flag &= ~GP_STROKE_SELECT;
- }
- else {
- /* just the point (and the stroke) */
- if (deselect == false) {
- /* we're adding selection, so selection must be true */
- hit_point->flag |= GP_SPOINT_SELECT;
- hit_stroke->flag |= GP_STROKE_SELECT;
-
- /* expand selection to segment */
- if (ts->gpencil_selectmode == GP_SELECTMODE_SEGMENT) {
- float r_hita[3], r_hitb[3];
- bool hit_select = (bool)(hit_point->flag & GP_SPOINT_SELECT);
- ED_gpencil_select_stroke_segment(
- hit_layer, hit_stroke, hit_point, hit_select,
- false, scale, r_hita, r_hitb);
- }
- }
- else {
- /* deselect point */
- hit_point->flag &= ~GP_SPOINT_SELECT;
-
- /* ensure that stroke is selected correctly */
- BKE_gpencil_stroke_sync_selection(hit_stroke);
- }
- }
-
- /* updates */
- if (hit_point != NULL) {
- 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);
- }
-
- return OPERATOR_FINISHED;
+ ScrArea *sa = CTX_wm_area(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ const float scale = ts->gp_sculpt.isect_threshold;
+
+ /* "radius" is simply a threshold (screen space) to make it easier to test with a tolerance */
+ const float radius = 0.50f * U.widget_unit;
+ const int radius_squared = (int)(radius * radius);
+
+ bool extend = RNA_boolean_get(op->ptr, "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");
+
+ int mval[2] = {0};
+
+ GP_SpaceConversion gsc = {NULL};
+
+ bGPDlayer *hit_layer = NULL;
+ bGPDstroke *hit_stroke = NULL;
+ bGPDspoint *hit_point = NULL;
+ int hit_distance = radius_squared;
+
+ /* sanity checks */
+ if (sa == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active area");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* if select mode is stroke, use whole stroke */
+ if (ts->gpencil_selectmode == GP_SELECTMODE_STROKE) {
+ whole = true;
+ }
+
+ /* init space conversion stuff */
+ gp_point_conversion_init(C, &gsc);
+
+ /* get mouse location */
+ RNA_int_get_array(op->ptr, "location", mval);
+
+ /* First Pass: Find stroke point which gets hit */
+ /* XXX: maybe we should go from the top of the stack down instead... */
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ bGPDspoint *pt;
+ int i;
+
+ /* firstly, check for hit-point */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ int xy[2];
+
+ bGPDspoint pt2;
+ gp_point_to_parent_space(pt, gpstroke_iter.diff_mat, &pt2);
+ gp_point_to_xy(&gsc, gps, &pt2, &xy[0], &xy[1]);
+
+ /* do boundbox check first */
+ if (!ELEM(V2D_IS_CLIPPED, xy[0], xy[1])) {
+ const int pt_distance = len_manhattan_v2v2_int(mval, xy);
+
+ /* check if point is inside */
+ if (pt_distance <= radius_squared) {
+ /* only use this point if it is a better match than the current hit - T44685 */
+ if (pt_distance < hit_distance) {
+ hit_layer = gpl;
+ hit_stroke = gps;
+ hit_point = pt;
+ hit_distance = pt_distance;
+ }
+ }
+ }
+ }
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
+
+ /* Abort if nothing hit... */
+ if (ELEM(NULL, hit_stroke, hit_point)) {
+
+ /* since left mouse select change, deselect all if click outside any hit */
+ deselect_all_selected(C);
+
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
+ 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);
+
+ return OPERATOR_CANCELLED;
+ }
+
+ /* adjust selection behavior - for toggle option */
+ if (toggle) {
+ deselect = (hit_point->flag & GP_SPOINT_SELECT) != 0;
+ }
+
+ /* If not extending selection, deselect everything else */
+ if (extend == false) {
+ deselect_all_selected(C);
+ }
+
+ /* Perform selection operations... */
+ if (whole) {
+ bGPDspoint *pt;
+ int i;
+
+ /* entire stroke's points */
+ for (i = 0, pt = hit_stroke->points; i < hit_stroke->totpoints; i++, pt++) {
+ if (deselect == false)
+ pt->flag |= GP_SPOINT_SELECT;
+ else
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ /* stroke too... */
+ if (deselect == false)
+ hit_stroke->flag |= GP_STROKE_SELECT;
+ else
+ hit_stroke->flag &= ~GP_STROKE_SELECT;
+ }
+ else {
+ /* just the point (and the stroke) */
+ if (deselect == false) {
+ /* we're adding selection, so selection must be true */
+ hit_point->flag |= GP_SPOINT_SELECT;
+ hit_stroke->flag |= GP_STROKE_SELECT;
+
+ /* expand selection to segment */
+ if (ts->gpencil_selectmode == GP_SELECTMODE_SEGMENT) {
+ float r_hita[3], r_hitb[3];
+ bool hit_select = (bool)(hit_point->flag & GP_SPOINT_SELECT);
+ ED_gpencil_select_stroke_segment(
+ hit_layer, hit_stroke, hit_point, hit_select, false, scale, r_hita, r_hitb);
+ }
+ }
+ else {
+ /* deselect point */
+ hit_point->flag &= ~GP_SPOINT_SELECT;
+
+ /* ensure that stroke is selected correctly */
+ BKE_gpencil_stroke_sync_selection(hit_stroke);
+ }
+ }
+
+ /* updates */
+ if (hit_point != NULL) {
+ 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);
+ }
+
+ return OPERATOR_FINISHED;
}
static int gpencil_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- RNA_int_set_array(op->ptr, "location", event->mval);
- return gpencil_select_exec(C, op);
+ RNA_int_set_array(op->ptr, "location", event->mval);
+ return gpencil_select_exec(C, op);
}
void GPENCIL_OT_select(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Select";
- ot->description = "Select Grease Pencil strokes and/or stroke points";
- ot->idname = "GPENCIL_OT_select";
-
- /* callbacks */
- ot->invoke = gpencil_select_invoke;
- ot->exec = gpencil_select_exec;
- ot->poll = gpencil_select_poll;
-
- /* flag */
- ot->flag = OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
-
- /* properties */
- WM_operator_properties_mouse_select(ot);
-
- prop = RNA_def_boolean(ot->srna, "entire_strokes", false, "Entire Strokes", "Select entire strokes instead of just the nearest stroke vertex");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- prop = RNA_def_int_vector(ot->srna, "location", 2, NULL, INT_MIN, INT_MAX, "Location", "Mouse location", INT_MIN, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select";
+ ot->description = "Select Grease Pencil strokes and/or stroke points";
+ ot->idname = "GPENCIL_OT_select";
+
+ /* callbacks */
+ ot->invoke = gpencil_select_invoke;
+ ot->exec = gpencil_select_exec;
+ ot->poll = gpencil_select_poll;
+
+ /* flag */
+ ot->flag = OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+
+ /* properties */
+ WM_operator_properties_mouse_select(ot);
+
+ prop = RNA_def_boolean(ot->srna,
+ "entire_strokes",
+ false,
+ "Entire Strokes",
+ "Select entire strokes instead of just the nearest stroke vertex");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_int_vector(ot->srna,
+ "location",
+ 2,
+ NULL,
+ INT_MIN,
+ INT_MAX,
+ "Location",
+ "Mouse location",
+ INT_MIN,
+ INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/** \} */
diff --git a/source/blender/editors/gpencil/gpencil_undo.c b/source/blender/editors/gpencil/gpencil_undo.c
index 7ed794a0a32..d91977bc0da 100644
--- a/source/blender/editors/gpencil/gpencil_undo.c
+++ b/source/blender/editors/gpencil/gpencil_undo.c
@@ -21,7 +21,6 @@
* \ingroup edgpencil
*/
-
#include <stdlib.h>
#include <string.h>
@@ -48,10 +47,10 @@
#include "gpencil_intern.h"
typedef struct bGPundonode {
- struct bGPundonode *next, *prev;
+ struct bGPundonode *next, *prev;
- char name[BKE_UNDO_STR_MAX];
- struct bGPdata *gpd;
+ char name[BKE_UNDO_STR_MAX];
+ struct bGPdata *gpd;
} bGPundonode;
static ListBase undo_nodes = {NULL, NULL};
@@ -59,140 +58,140 @@ static bGPundonode *cur_node = NULL;
int ED_gpencil_session_active(void)
{
- return (BLI_listbase_is_empty(&undo_nodes) == false);
+ return (BLI_listbase_is_empty(&undo_nodes) == false);
}
int ED_undo_gpencil_step(bContext *C, int step, const char *name)
{
- bGPdata **gpd_ptr = NULL, *new_gpd = NULL;
-
- gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
-
- if (step == 1) { /* undo */
- //printf("\t\tGP - undo step\n");
- if (cur_node->prev) {
- if (!name || STREQ(cur_node->name, name)) {
- cur_node = cur_node->prev;
- new_gpd = cur_node->gpd;
- }
- }
- }
- else if (step == -1) {
- //printf("\t\tGP - redo step\n");
- if (cur_node->next) {
- if (!name || STREQ(cur_node->name, name)) {
- cur_node = cur_node->next;
- new_gpd = cur_node->gpd;
- }
- }
- }
-
- if (new_gpd) {
- if (gpd_ptr) {
- if (*gpd_ptr) {
- bGPdata *gpd = *gpd_ptr;
- bGPDlayer *gpl, *gpld;
-
- BKE_gpencil_free_layers(&gpd->layers);
-
- /* copy layers */
- BLI_listbase_clear(&gpd->layers);
-
- for (gpl = new_gpd->layers.first; gpl; gpl = gpl->next) {
- /* make a copy of source layer and its data */
- gpld = BKE_gpencil_layer_duplicate(gpl);
- BLI_addtail(&gpd->layers, gpld);
- }
- }
- }
- /* drawing batch cache is dirty now */
- DEG_id_tag_update(&new_gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- new_gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
- }
-
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
+ bGPdata **gpd_ptr = NULL, *new_gpd = NULL;
+
+ gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
+
+ if (step == 1) { /* undo */
+ //printf("\t\tGP - undo step\n");
+ if (cur_node->prev) {
+ if (!name || STREQ(cur_node->name, name)) {
+ cur_node = cur_node->prev;
+ new_gpd = cur_node->gpd;
+ }
+ }
+ }
+ else if (step == -1) {
+ //printf("\t\tGP - redo step\n");
+ if (cur_node->next) {
+ if (!name || STREQ(cur_node->name, name)) {
+ cur_node = cur_node->next;
+ new_gpd = cur_node->gpd;
+ }
+ }
+ }
+
+ if (new_gpd) {
+ if (gpd_ptr) {
+ if (*gpd_ptr) {
+ bGPdata *gpd = *gpd_ptr;
+ bGPDlayer *gpl, *gpld;
+
+ BKE_gpencil_free_layers(&gpd->layers);
+
+ /* copy layers */
+ BLI_listbase_clear(&gpd->layers);
+
+ for (gpl = new_gpd->layers.first; gpl; gpl = gpl->next) {
+ /* make a copy of source layer and its data */
+ gpld = BKE_gpencil_layer_duplicate(gpl);
+ BLI_addtail(&gpd->layers, gpld);
+ }
+ }
+ }
+ /* drawing batch cache is dirty now */
+ DEG_id_tag_update(&new_gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ new_gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+ }
+
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
}
void gpencil_undo_init(bGPdata *gpd)
{
- gpencil_undo_push(gpd);
+ gpencil_undo_push(gpd);
}
static void gpencil_undo_free_node(bGPundonode *undo_node)
{
- /* HACK: animdata wasn't duplicated, so it shouldn't be freed here,
- * or else the real copy will segfault when accessed
- */
- undo_node->gpd->adt = NULL;
+ /* HACK: animdata wasn't duplicated, so it shouldn't be freed here,
+ * or else the real copy will segfault when accessed
+ */
+ undo_node->gpd->adt = NULL;
- BKE_gpencil_free(undo_node->gpd, false);
- MEM_freeN(undo_node->gpd);
+ BKE_gpencil_free(undo_node->gpd, false);
+ MEM_freeN(undo_node->gpd);
}
void gpencil_undo_push(bGPdata *gpd)
{
- bGPundonode *undo_node;
+ bGPundonode *undo_node;
- //printf("\t\tGP - undo push\n");
+ //printf("\t\tGP - undo push\n");
- if (cur_node) {
- /* remove all un-done nodes from stack */
- undo_node = cur_node->next;
+ if (cur_node) {
+ /* remove all un-done nodes from stack */
+ undo_node = cur_node->next;
- while (undo_node) {
- bGPundonode *next_node = undo_node->next;
+ while (undo_node) {
+ bGPundonode *next_node = undo_node->next;
- gpencil_undo_free_node(undo_node);
- BLI_freelinkN(&undo_nodes, undo_node);
+ gpencil_undo_free_node(undo_node);
+ BLI_freelinkN(&undo_nodes, undo_node);
- undo_node = next_node;
- }
- }
+ undo_node = next_node;
+ }
+ }
- /* limit number of undo steps to the maximum undo steps
- * - to prevent running out of memory during **really**
- * long drawing sessions (triggering swapping)
- */
- /* TODO: Undo-memory constraint is not respected yet, but can be added if we have any need for it */
- if (U.undosteps && !BLI_listbase_is_empty(&undo_nodes)) {
- /* remove anything older than n-steps before cur_node */
- int steps = 0;
+ /* limit number of undo steps to the maximum undo steps
+ * - to prevent running out of memory during **really**
+ * long drawing sessions (triggering swapping)
+ */
+ /* TODO: Undo-memory constraint is not respected yet, but can be added if we have any need for it */
+ if (U.undosteps && !BLI_listbase_is_empty(&undo_nodes)) {
+ /* remove anything older than n-steps before cur_node */
+ int steps = 0;
- undo_node = (cur_node) ? cur_node : undo_nodes.last;
- while (undo_node) {
- bGPundonode *prev_node = undo_node->prev;
+ undo_node = (cur_node) ? cur_node : undo_nodes.last;
+ while (undo_node) {
+ bGPundonode *prev_node = undo_node->prev;
- if (steps >= U.undosteps) {
- gpencil_undo_free_node(undo_node);
- BLI_freelinkN(&undo_nodes, undo_node);
- }
+ if (steps >= U.undosteps) {
+ gpencil_undo_free_node(undo_node);
+ BLI_freelinkN(&undo_nodes, undo_node);
+ }
- steps++;
- undo_node = prev_node;
- }
- }
+ steps++;
+ undo_node = prev_node;
+ }
+ }
- /* create new undo node */
- undo_node = MEM_callocN(sizeof(bGPundonode), "gpencil undo node");
- undo_node->gpd = BKE_gpencil_data_duplicate(NULL, gpd, true);
+ /* create new undo node */
+ undo_node = MEM_callocN(sizeof(bGPundonode), "gpencil undo node");
+ undo_node->gpd = BKE_gpencil_data_duplicate(NULL, gpd, true);
- cur_node = undo_node;
+ cur_node = undo_node;
- BLI_addtail(&undo_nodes, undo_node);
+ BLI_addtail(&undo_nodes, undo_node);
}
void gpencil_undo_finish(void)
{
- bGPundonode *undo_node = undo_nodes.first;
+ bGPundonode *undo_node = undo_nodes.first;
- while (undo_node) {
- gpencil_undo_free_node(undo_node);
- undo_node = undo_node->next;
- }
+ while (undo_node) {
+ gpencil_undo_free_node(undo_node);
+ undo_node = undo_node->next;
+ }
- BLI_freelistN(&undo_nodes);
+ BLI_freelistN(&undo_nodes);
- cur_node = NULL;
+ cur_node = NULL;
}
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index f582b52713d..858415061b1 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -88,120 +88,129 @@
/* Get pointer to active Grease Pencil datablock, and an RNA-pointer to trace back to whatever owns it,
* when context info is not available.
*/
-bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, ScrArea *sa, Scene *scene, Object *ob, PointerRNA *r_ptr)
+bGPdata **ED_gpencil_data_get_pointers_direct(
+ ID *screen_id, ScrArea *sa, Scene *scene, 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) {
- SpaceLink *sl = sa->spacedata.first;
-
- switch (sa->spacetype) {
- /* XXX: Should we reduce reliance on context.gpencil_data for these cases? */
- case SPACE_PROPERTIES: /* properties */
- case SPACE_INFO: /* header info (needed after workspaces merge) */
- {
- if (ob && (ob->type == OB_GPENCIL)) {
- /* GP Object */
- if (r_ptr) RNA_id_pointer_create(&ob->id, r_ptr);
- return (bGPdata **)&ob->data;
- }
- else {
- return NULL;
- }
-
- break;
- }
-
- case SPACE_TOPBAR: /* Topbar (needed after topbar merge) */
- case SPACE_VIEW3D: /* 3D-View */
- {
- if (ob && (ob->type == OB_GPENCIL)) {
- /* GP Object */
- if (r_ptr) RNA_id_pointer_create(&ob->id, r_ptr);
- return (bGPdata **)&ob->data;
- }
- else {
- /* Annotations */
- /* XXX: */
- if (r_ptr) RNA_id_pointer_create(&scene->id, r_ptr);
- return &scene->gpd;
- }
-
- break;
- }
- case SPACE_NODE: /* Nodes Editor */
- {
- SpaceNode *snode = (SpaceNode *)sl;
-
- /* return the GP data for the active node block/node */
- if (snode && snode->nodetree) {
- /* for now, as long as there's an active node tree,
- * default to using that in the Nodes Editor */
- if (r_ptr) RNA_id_pointer_create(&snode->nodetree->id, r_ptr);
- return &snode->nodetree->gpd;
- }
-
- /* even when there is no node-tree, don't allow this to flow to scene */
- return NULL;
- }
- case SPACE_SEQ: /* Sequencer */
- {
- SpaceSeq *sseq = (SpaceSeq *)sl;
-
- /* for now, Grease Pencil data is associated with the space (actually preview region only) */
- /* XXX our convention for everything else is to link to data though... */
- if (r_ptr) RNA_pointer_create(screen_id, &RNA_SpaceSequenceEditor, sseq, r_ptr);
- return &sseq->gpd;
- }
- case SPACE_IMAGE: /* Image/UV Editor */
- {
- SpaceImage *sima = (SpaceImage *)sl;
-
- /* for now, Grease Pencil data is associated with the space... */
- /* XXX our convention for everything else is to link to data though... */
- if (r_ptr) RNA_pointer_create(screen_id, &RNA_SpaceImageEditor, sima, r_ptr);
- return &sima->gpd;
- }
- case SPACE_CLIP: /* Nodes Editor */
- {
- SpaceClip *sc = (SpaceClip *)sl;
- MovieClip *clip = ED_space_clip_get_clip(sc);
-
- if (clip) {
- if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
- MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking);
-
- if (!track)
- return NULL;
-
- if (r_ptr) RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, r_ptr);
- return &track->gpd;
- }
- else {
- if (r_ptr) RNA_id_pointer_create(&clip->id, r_ptr);
- return &clip->gpd;
- }
- }
- break;
- }
- default: /* unsupported space */
- return NULL;
- }
- }
-
- return NULL;
+ /* 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;
+
+ switch (sa->spacetype) {
+ /* XXX: Should we reduce reliance on context.gpencil_data for these cases? */
+ case SPACE_PROPERTIES: /* properties */
+ case SPACE_INFO: /* header info (needed after workspaces merge) */
+ {
+ if (ob && (ob->type == OB_GPENCIL)) {
+ /* GP Object */
+ if (r_ptr)
+ RNA_id_pointer_create(&ob->id, r_ptr);
+ return (bGPdata **)&ob->data;
+ }
+ else {
+ return NULL;
+ }
+
+ break;
+ }
+
+ case SPACE_TOPBAR: /* Topbar (needed after topbar merge) */
+ case SPACE_VIEW3D: /* 3D-View */
+ {
+ if (ob && (ob->type == OB_GPENCIL)) {
+ /* GP Object */
+ if (r_ptr)
+ RNA_id_pointer_create(&ob->id, r_ptr);
+ return (bGPdata **)&ob->data;
+ }
+ else {
+ /* Annotations */
+ /* XXX: */
+ if (r_ptr)
+ RNA_id_pointer_create(&scene->id, r_ptr);
+ return &scene->gpd;
+ }
+
+ break;
+ }
+ case SPACE_NODE: /* Nodes Editor */
+ {
+ SpaceNode *snode = (SpaceNode *)sl;
+
+ /* return the GP data for the active node block/node */
+ if (snode && snode->nodetree) {
+ /* for now, as long as there's an active node tree,
+ * default to using that in the Nodes Editor */
+ if (r_ptr)
+ RNA_id_pointer_create(&snode->nodetree->id, r_ptr);
+ return &snode->nodetree->gpd;
+ }
+
+ /* even when there is no node-tree, don't allow this to flow to scene */
+ return NULL;
+ }
+ case SPACE_SEQ: /* Sequencer */
+ {
+ SpaceSeq *sseq = (SpaceSeq *)sl;
+
+ /* for now, Grease Pencil data is associated with the space (actually preview region only) */
+ /* XXX our convention for everything else is to link to data though... */
+ if (r_ptr)
+ RNA_pointer_create(screen_id, &RNA_SpaceSequenceEditor, sseq, r_ptr);
+ return &sseq->gpd;
+ }
+ case SPACE_IMAGE: /* Image/UV Editor */
+ {
+ SpaceImage *sima = (SpaceImage *)sl;
+
+ /* for now, Grease Pencil data is associated with the space... */
+ /* XXX our convention for everything else is to link to data though... */
+ if (r_ptr)
+ RNA_pointer_create(screen_id, &RNA_SpaceImageEditor, sima, r_ptr);
+ return &sima->gpd;
+ }
+ case SPACE_CLIP: /* Nodes Editor */
+ {
+ SpaceClip *sc = (SpaceClip *)sl;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+
+ if (clip) {
+ if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
+ MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking);
+
+ if (!track)
+ return NULL;
+
+ if (r_ptr)
+ RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, r_ptr);
+ return &track->gpd;
+ }
+ else {
+ if (r_ptr)
+ RNA_id_pointer_create(&clip->id, r_ptr);
+ return &clip->gpd;
+ }
+ }
+ break;
+ }
+ default: /* unsupported space */
+ return NULL;
+ }
+ }
+
+ return NULL;
}
/* Get pointer to active Grease Pencil datablock, and an RNA-pointer to trace back to whatever owns it */
bGPdata **ED_gpencil_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);
- Object *ob = CTX_data_active_object(C);
+ ID *screen_id = (ID *)CTX_wm_screen(C);
+ Scene *scene = CTX_data_scene(C);
+ ScrArea *sa = CTX_wm_area(C);
+ Object *ob = CTX_data_active_object(C);
- return ED_gpencil_data_get_pointers_direct(screen_id, sa, scene, ob, r_ptr);
+ return ED_gpencil_data_get_pointers_direct(screen_id, sa, scene, ob, r_ptr);
}
/* -------------------------------------------------------- */
@@ -209,8 +218,8 @@ bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *r_ptr)
/* Get the active Grease Pencil datablock, when context is not available */
bGPdata *ED_gpencil_data_get_active_direct(ID *screen_id, ScrArea *sa, Scene *scene, Object *ob)
{
- bGPdata **gpd_ptr = ED_gpencil_data_get_pointers_direct(screen_id, sa, scene, ob, NULL);
- return (gpd_ptr) ? *(gpd_ptr) : NULL;
+ bGPdata **gpd_ptr = ED_gpencil_data_get_pointers_direct(screen_id, sa, scene, ob, NULL);
+ return (gpd_ptr) ? *(gpd_ptr) : NULL;
}
/**
@@ -220,8 +229,8 @@ bGPdata *ED_gpencil_data_get_active_direct(ID *screen_id, ScrArea *sa, Scene *sc
*/
bGPdata *ED_gpencil_data_get_active(const bContext *C)
{
- bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
- return (gpd_ptr) ? *(gpd_ptr) : NULL;
+ bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
+ return (gpd_ptr) ? *(gpd_ptr) : NULL;
}
/**
@@ -234,16 +243,16 @@ bGPdata *ED_gpencil_data_get_active(const bContext *C)
*/
bGPdata *ED_gpencil_data_get_active_evaluated(const bContext *C)
{
- ID *screen_id = (ID *)CTX_wm_screen(C);
- ScrArea *sa = CTX_wm_area(C);
+ ID *screen_id = (ID *)CTX_wm_screen(C);
+ ScrArea *sa = CTX_wm_area(C);
- const Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *ob = CTX_data_active_object(C);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob = CTX_data_active_object(C);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- /* if (ob && ob->type == OB_GPENCIL) BLI_assert(ob_eval->data == DEG_get_evaluated_id(ob->data)); */
- return ED_gpencil_data_get_active_direct(screen_id, sa, scene_eval, ob_eval);
+ /* if (ob && ob->type == OB_GPENCIL) BLI_assert(ob_eval->data == DEG_get_evaluated_id(ob->data)); */
+ return ED_gpencil_data_get_active_direct(screen_id, sa, scene_eval, ob_eval);
}
/* -------------------------------------------------------- */
@@ -254,10 +263,10 @@ bGPdata *ED_gpencil_data_get_active_evaluated(const bContext *C)
*/
bool ED_gpencil_data_owner_is_annotation(PointerRNA *owner_ptr)
{
- /* Key Assumption: If the pointer is an object, we're dealing with a GP Object's data.
- * Otherwise, the GP datablock is being used for annotations (i.e. everywhere else)
- */
- return ((owner_ptr) && (owner_ptr->type != &RNA_Object));
+ /* Key Assumption: If the pointer is an object, we're dealing with a GP Object's data.
+ * Otherwise, the GP datablock is being used for annotations (i.e. everywhere else)
+ */
+ return ((owner_ptr) && (owner_ptr->type != &RNA_Object));
}
/* ******************************************************** */
@@ -266,21 +275,21 @@ bool ED_gpencil_data_owner_is_annotation(PointerRNA *owner_ptr)
/* Check whether there's an active GP keyframe on the current frame */
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);
- if (gpl) {
- if (gpl->actframe) {
- // XXX: assumes that frame has been fetched already
- return (gpl->actframe->framenum == cfra);
- }
- else {
- /* XXX: disabled as could be too much of a penalty */
- /* return BKE_gpencil_layer_find_frame(gpl, cfra); */
- }
- }
- }
-
- return false;
+ if (ob && ob->data && (ob->type == OB_GPENCIL)) {
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(ob->data);
+ if (gpl) {
+ if (gpl->actframe) {
+ // XXX: assumes that frame has been fetched already
+ return (gpl->actframe->framenum == cfra);
+ }
+ else {
+ /* XXX: disabled as could be too much of a penalty */
+ /* return BKE_gpencil_layer_find_frame(gpl, cfra); */
+ }
+ }
+ }
+
+ return false;
}
/* ******************************************************** */
@@ -289,30 +298,30 @@ bool ED_gpencil_has_keyframe_v3d(Scene *UNUSED(scene), Object *ob, int cfra)
/* poll callback for adding data/layers - special */
bool gp_add_poll(bContext *C)
{
- /* the base line we have is that we have somewhere to add Grease Pencil data */
- return ED_gpencil_data_get_pointers(C, NULL) != NULL;
+ /* the base line we have is that we have somewhere to add Grease Pencil data */
+ return ED_gpencil_data_get_pointers(C, NULL) != NULL;
}
/* poll callback for checking if there is an active layer */
bool gp_active_layer_poll(bContext *C)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
- return (gpl != NULL);
+ return (gpl != NULL);
}
/* poll callback for checking if there is an active brush */
bool gp_active_brush_poll(bContext *C)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- Paint *paint = &ts->gp_paint->paint;
- if (paint) {
- return (paint->brush != NULL);
- }
- else {
- return false;
- }
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Paint *paint = &ts->gp_paint->paint;
+ if (paint) {
+ return (paint->brush != NULL);
+ }
+ else {
+ return false;
+ }
}
/* ******************************************************** */
@@ -320,88 +329,91 @@ bool gp_active_brush_poll(bContext *C)
/* NOTE: These include an option to create a new layer and use that... */
/* Just existing layers */
-const EnumPropertyItem *ED_gpencil_layers_enum_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+const EnumPropertyItem *ED_gpencil_layers_enum_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- bGPdata *gpd = CTX_data_gpencil_data(C);
- bGPDlayer *gpl;
- EnumPropertyItem *item = NULL, item_tmp = {0};
- int totitem = 0;
- int i = 0;
-
- if (ELEM(NULL, C, gpd)) {
- return DummyRNA_DEFAULT_items;
- }
-
- /* Existing layers */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next, i++) {
- item_tmp.identifier = gpl->info;
- item_tmp.name = gpl->info;
- item_tmp.value = i;
-
- if (gpl->flag & GP_LAYER_ACTIVE)
- item_tmp.icon = ICON_GREASEPENCIL;
- else
- item_tmp.icon = ICON_NONE;
-
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ bGPDlayer *gpl;
+ EnumPropertyItem *item = NULL, item_tmp = {0};
+ int totitem = 0;
+ int i = 0;
+
+ if (ELEM(NULL, C, gpd)) {
+ return DummyRNA_DEFAULT_items;
+ }
+
+ /* Existing layers */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next, i++) {
+ item_tmp.identifier = gpl->info;
+ item_tmp.name = gpl->info;
+ item_tmp.value = i;
+
+ if (gpl->flag & GP_LAYER_ACTIVE)
+ item_tmp.icon = ICON_GREASEPENCIL;
+ else
+ item_tmp.icon = ICON_NONE;
+
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
/* Existing + Option to add/use new layer */
-const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- bGPdata *gpd = CTX_data_gpencil_data(C);
- bGPDlayer *gpl;
- EnumPropertyItem *item = NULL, item_tmp = {0};
- int totitem = 0;
- int i = 0;
-
- if (ELEM(NULL, C, gpd)) {
- return DummyRNA_DEFAULT_items;
- }
-
- /* Create new layer */
- /* TODO: have some way of specifying that we don't want this? */
- {
- /* "New Layer" entry */
- item_tmp.identifier = "__CREATE__";
- item_tmp.name = "New Layer";
- item_tmp.value = -1;
- item_tmp.icon = ICON_ADD;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
-
- /* separator */
- RNA_enum_item_add_separator(&item, &totitem);
- }
- const int tot = BLI_listbase_count(&gpd->layers);
- /* Existing layers */
- for (gpl = gpd->layers.last, i = 0; gpl; gpl = gpl->prev, i++) {
- item_tmp.identifier = gpl->info;
- item_tmp.name = gpl->info;
- item_tmp.value = tot - i - 1;
-
- if (gpl->flag & GP_LAYER_ACTIVE)
- item_tmp.icon = ICON_GREASEPENCIL;
- else
- item_tmp.icon = ICON_NONE;
-
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ bGPDlayer *gpl;
+ EnumPropertyItem *item = NULL, item_tmp = {0};
+ int totitem = 0;
+ int i = 0;
+
+ if (ELEM(NULL, C, gpd)) {
+ return DummyRNA_DEFAULT_items;
+ }
+
+ /* Create new layer */
+ /* TODO: have some way of specifying that we don't want this? */
+ {
+ /* "New Layer" entry */
+ item_tmp.identifier = "__CREATE__";
+ item_tmp.name = "New Layer";
+ item_tmp.value = -1;
+ item_tmp.icon = ICON_ADD;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+
+ /* separator */
+ RNA_enum_item_add_separator(&item, &totitem);
+ }
+ const int tot = BLI_listbase_count(&gpd->layers);
+ /* Existing layers */
+ for (gpl = gpd->layers.last, i = 0; gpl; gpl = gpl->prev, i++) {
+ item_tmp.identifier = gpl->info;
+ item_tmp.name = gpl->info;
+ item_tmp.value = tot - i - 1;
+
+ if (gpl->flag & GP_LAYER_ACTIVE)
+ item_tmp.icon = ICON_GREASEPENCIL;
+ else
+ item_tmp.icon = ICON_NONE;
+
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
-
/* ******************************************************** */
/* Brush Tool Core */
@@ -416,19 +428,18 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(
* \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)
+ const float mval[2], const float UNUSED(mvalo[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};
- const float screen_co_b[2] = {x1, y1};
+ /* simple within-radius check for now */
+ const float screen_co_a[2] = {x0, y0};
+ const float screen_co_b[2] = {x1, y1};
- if (edge_inside_circle(mval, rad, screen_co_a, screen_co_b)) {
- return true;
- }
+ if (edge_inside_circle(mval, rad, screen_co_a, screen_co_b)) {
+ return true;
+ }
- /* not inside */
- return false;
+ /* not inside */
+ return false;
}
/* ******************************************************** */
@@ -438,50 +449,50 @@ bool gp_stroke_inside_circle(
/* TODO: do we need additional flags for screenspace vs dataspace? */
bool ED_gpencil_stroke_can_use_direct(const ScrArea *sa, const bGPDstroke *gps)
{
- /* sanity check */
- if (ELEM(NULL, sa, 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));
- }
- else if (gps->flag & GP_STROKE_2DIMAGE) {
- /* Special "image" strokes - only in Image Editor */
- return (sa->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);
- }
- else {
- /* view aligned - anything goes */
- return true;
- }
+ /* sanity check */
+ if (ELEM(NULL, sa, 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));
+ }
+ else if (gps->flag & GP_STROKE_2DIMAGE) {
+ /* Special "image" strokes - only in Image Editor */
+ return (sa->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);
+ }
+ else {
+ /* view aligned - anything goes */
+ return true;
+ }
}
/* 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 *sa = CTX_wm_area(C);
+ return ED_gpencil_stroke_can_use_direct(sa, 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);
+ /* check if the color is editable */
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
- if (gp_style != NULL) {
- if (gp_style->flag & GP_STYLE_COLOR_HIDE)
- return false;
- if (((gpl->flag & GP_LAYER_UNLOCK_COLOR) == 0) && (gp_style->flag & GP_STYLE_COLOR_LOCKED))
- return false;
- }
+ if (gp_style != NULL) {
+ if (gp_style->flag & GP_STYLE_COLOR_HIDE)
+ return false;
+ if (((gpl->flag & GP_LAYER_UNLOCK_COLOR) == 0) && (gp_style->flag & GP_STYLE_COLOR_LOCKED))
+ return false;
+ }
- return true;
+ return true;
}
/* ******************************************************** */
@@ -494,41 +505,42 @@ 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);
-
- /* zero out the storage (just in case) */
- memset(r_gsc, 0, sizeof(GP_SpaceConversion));
- unit_m4(r_gsc->mat);
-
- /* store settings */
- 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;
-
- /* init region-specific stuff */
- if (sa->spacetype == SPACE_VIEW3D) {
- wmWindow *win = CTX_wm_window(C);
- Scene *scene = CTX_data_scene(C);
- struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
- View3D *v3d = (View3D *)CTX_wm_space_data(C);
- RegionView3D *rv3d = ar->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);
-
- /* for camera view set the subrect */
- if (rv3d->persp == RV3D_CAMOB) {
- ED_view3d_calc_camera_border(scene, CTX_data_depsgraph(C), ar, v3d, rv3d, &r_gsc->subrect_data, true);
- r_gsc->subrect = &r_gsc->subrect_data;
- }
- }
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ /* zero out the storage (just in case) */
+ memset(r_gsc, 0, sizeof(GP_SpaceConversion));
+ unit_m4(r_gsc->mat);
+
+ /* store settings */
+ 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;
+
+ /* init region-specific stuff */
+ if (sa->spacetype == SPACE_VIEW3D) {
+ wmWindow *win = CTX_wm_window(C);
+ Scene *scene = CTX_data_scene(C);
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ View3D *v3d = (View3D *)CTX_wm_space_data(C);
+ RegionView3D *rv3d = ar->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);
+
+ /* for camera view set the subrect */
+ if (rv3d->persp == RV3D_CAMOB) {
+ ED_view3d_calc_camera_border(
+ scene, CTX_data_depsgraph(C), ar, v3d, rv3d, &r_gsc->subrect_data, true);
+ r_gsc->subrect = &r_gsc->subrect_data;
+ }
+ }
}
/**
@@ -540,50 +552,52 @@ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
*/
void gp_point_to_parent_space(const bGPDspoint *pt, const float diff_mat[4][4], bGPDspoint *r_pt)
{
- float fpt[3];
+ float fpt[3];
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- copy_v3_v3(&r_pt->x, fpt);
+ mul_v3_m4v3(fpt, diff_mat, &pt->x);
+ copy_v3_v3(&r_pt->x, fpt);
}
/**
* 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, bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps)
{
- bGPDspoint *pt;
- int i;
-
- /* 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);
- invert_m4_m4(inverse_diff_mat, diff_mat);
-
- for (i = 0; i < gps->totpoints; i++) {
- pt = &gps->points[i];
- mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x);
- copy_v3_v3(&pt->x, fpt);
- }
+ bGPDspoint *pt;
+ int i;
+
+ /* 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);
+ invert_m4_m4(inverse_diff_mat, diff_mat);
+
+ for (i = 0; i < gps->totpoints; i++) {
+ pt = &gps->points[i];
+ mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x);
+ copy_v3_v3(&pt->x, fpt);
+ }
}
/**
* 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, bGPdata *gpd, bGPDlayer *gpl, bGPDspoint *pt)
{
- /* undo matrix */
- float diff_mat[4][4];
- float inverse_diff_mat[4][4];
- float fpt[3];
+ /* 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);
- invert_m4_m4(inverse_diff_mat, diff_mat);
+ ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ invert_m4_m4(inverse_diff_mat, diff_mat);
- mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x);
- copy_v3_v3(&pt->x, fpt);
+ mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x);
+ copy_v3_v3(&pt->x, fpt);
}
/**
@@ -595,46 +609,44 @@ void gp_apply_parent_point(Depsgraph *depsgraph, Object *obact, bGPdata *gpd, bG
* \warning This assumes that the caller has already checked whether the stroke in question can be drawn.
*/
void gp_point_to_xy(
- const GP_SpaceConversion *gsc, const bGPDstroke *gps, const bGPDspoint *pt,
- int *r_x, int *r_y)
+ const GP_SpaceConversion *gsc, const bGPDstroke *gps, const bGPDspoint *pt, int *r_x, int *r_y)
{
- const ARegion *ar = gsc->ar;
- 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));
-
-
- if (gps->flag & GP_STROKE_3DSPACE) {
- if (ED_view3d_project_int_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- *r_x = xyval[0];
- *r_y = xyval[1];
- }
- else {
- *r_x = V2D_IS_CLIPPED;
- *r_y = V2D_IS_CLIPPED;
- }
- }
- else if (gps->flag & GP_STROKE_2DSPACE) {
- float vec[3] = {pt->x, pt->y, 0.0f};
- mul_m4_v3(gsc->mat, vec);
- UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], r_x, r_y);
- }
- 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);
- }
- else {
- /* camera view, use subrect */
- *r_x = (int)((pt->x / 100) * BLI_rctf_size_x(subrect)) + subrect->xmin;
- *r_y = (int)((pt->y / 100) * BLI_rctf_size_y(subrect)) + subrect->ymin;
- }
- }
+ const ARegion *ar = gsc->ar;
+ 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));
+
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ if (ED_view3d_project_int_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ *r_x = xyval[0];
+ *r_y = xyval[1];
+ }
+ else {
+ *r_x = V2D_IS_CLIPPED;
+ *r_y = V2D_IS_CLIPPED;
+ }
+ }
+ else if (gps->flag & GP_STROKE_2DSPACE) {
+ float vec[3] = {pt->x, pt->y, 0.0f};
+ mul_m4_v3(gsc->mat, vec);
+ UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], r_x, r_y);
+ }
+ 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);
+ }
+ else {
+ /* camera view, use subrect */
+ *r_x = (int)((pt->x / 100) * BLI_rctf_size_x(subrect)) + subrect->xmin;
+ *r_y = (int)((pt->y / 100) * BLI_rctf_size_y(subrect)) + subrect->ymin;
+ }
+ }
}
/**
@@ -648,117 +660,119 @@ void gp_point_to_xy(
*
* \warning This assumes that the caller has already checked whether the stroke in question can be drawn.
*/
-void gp_point_to_xy_fl(
- const GP_SpaceConversion *gsc, const bGPDstroke *gps, const bGPDspoint *pt,
- float *r_x, float *r_y)
+void gp_point_to_xy_fl(const GP_SpaceConversion *gsc,
+ const bGPDstroke *gps,
+ const bGPDspoint *pt,
+ float *r_x,
+ float *r_y)
{
- const ARegion *ar = gsc->ar;
- 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));
-
-
- if (gps->flag & GP_STROKE_3DSPACE) {
- if (ED_view3d_project_float_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- *r_x = xyval[0];
- *r_y = xyval[1];
- }
- else {
- *r_x = 0.0f;
- *r_y = 0.0f;
- }
- }
- else if (gps->flag & GP_STROKE_2DSPACE) {
- float vec[3] = {pt->x, pt->y, 0.0f};
- int t_x, t_y;
-
- mul_m4_v3(gsc->mat, vec);
- UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], &t_x, &t_y);
-
- if ((t_x == t_y) && (t_x == V2D_IS_CLIPPED)) {
- /* XXX: Or should we just always use the values as-is? */
- *r_x = 0.0f;
- *r_y = 0.0f;
- }
- else {
- *r_x = (float)t_x;
- *r_y = (float)t_y;
- }
- }
- 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);
- }
- else {
- /* camera view, use subrect */
- *r_x = ((pt->x / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin;
- *r_y = ((pt->y / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin;
- }
- }
+ const ARegion *ar = gsc->ar;
+ 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));
+
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ if (ED_view3d_project_float_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ *r_x = xyval[0];
+ *r_y = xyval[1];
+ }
+ else {
+ *r_x = 0.0f;
+ *r_y = 0.0f;
+ }
+ }
+ else if (gps->flag & GP_STROKE_2DSPACE) {
+ float vec[3] = {pt->x, pt->y, 0.0f};
+ int t_x, t_y;
+
+ mul_m4_v3(gsc->mat, vec);
+ UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], &t_x, &t_y);
+
+ if ((t_x == t_y) && (t_x == V2D_IS_CLIPPED)) {
+ /* XXX: Or should we just always use the values as-is? */
+ *r_x = 0.0f;
+ *r_y = 0.0f;
+ }
+ else {
+ *r_x = (float)t_x;
+ *r_y = (float)t_y;
+ }
+ }
+ 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);
+ }
+ else {
+ /* camera view, use subrect */
+ *r_x = ((pt->x / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin;
+ *r_y = ((pt->y / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin;
+ }
+ }
}
-
/**
* generic based on gp_point_to_xy_fl
*/
-void gp_point_3d_to_xy(const GP_SpaceConversion *gsc, const short flag, const float pt[3], float xy[2])
+void gp_point_3d_to_xy(const GP_SpaceConversion *gsc,
+ const short flag,
+ const float pt[3],
+ float xy[2])
{
- const ARegion *ar = gsc->ar;
- const View2D *v2d = gsc->v2d;
- const rctf *subrect = gsc->subrect;
- float xyval[2];
-
- /* sanity checks */
- BLI_assert((gsc->sa->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) {
- xy[0] = xyval[0];
- xy[1] = xyval[1];
- }
- else {
- xy[0] = 0.0f;
- xy[1] = 0.0f;
- }
- }
- else if (flag & GP_STROKE_2DSPACE) {
- float vec[3] = { pt[0], pt[1], 0.0f };
- int t_x, t_y;
-
- mul_m4_v3(gsc->mat, vec);
- UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], &t_x, &t_y);
-
- if ((t_x == t_y) && (t_x == V2D_IS_CLIPPED)) {
- /* XXX: Or should we just always use the values as-is? */
- xy[0] = 0.0f;
- xy[1] = 0.0f;
- }
- else {
- xy[0] = (float)t_x;
- xy[1] = (float)t_y;
- }
- }
- 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);
- }
- else {
- /* camera view, use subrect */
- xy[0] = ((pt[0] / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin;
- xy[1] = ((pt[1] / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin;
- }
- }
+ const ARegion *ar = gsc->ar;
+ const View2D *v2d = gsc->v2d;
+ const rctf *subrect = gsc->subrect;
+ float xyval[2];
+
+ /* sanity checks */
+ BLI_assert((gsc->sa->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) {
+ xy[0] = xyval[0];
+ xy[1] = xyval[1];
+ }
+ else {
+ xy[0] = 0.0f;
+ xy[1] = 0.0f;
+ }
+ }
+ else if (flag & GP_STROKE_2DSPACE) {
+ float vec[3] = {pt[0], pt[1], 0.0f};
+ int t_x, t_y;
+
+ mul_m4_v3(gsc->mat, vec);
+ UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], &t_x, &t_y);
+
+ if ((t_x == t_y) && (t_x == V2D_IS_CLIPPED)) {
+ /* XXX: Or should we just always use the values as-is? */
+ xy[0] = 0.0f;
+ xy[1] = 0.0f;
+ }
+ else {
+ xy[0] = (float)t_x;
+ xy[1] = (float)t_y;
+ }
+ }
+ 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);
+ }
+ else {
+ /* camera view, use subrect */
+ xy[0] = ((pt[0] / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin;
+ xy[1] = ((pt[1] / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin;
+ }
+ }
}
-
/**
* Project screenspace coordinates to 3D-space
*
@@ -774,34 +788,37 @@ void gp_point_3d_to_xy(const GP_SpaceConversion *gsc, const short flag, const fl
*
* \warning Assumes that it is getting called in a 3D view only.
*/
-bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc, Scene *scene, const float screen_co[2], float r_out[3])
+bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc,
+ Scene *scene,
+ const float screen_co[2],
+ float r_out[3])
{
- const RegionView3D *rv3d = gsc->ar->regiondata;
- float rvec[3];
+ const RegionView3D *rv3d = gsc->ar->regiondata;
+ float rvec[3];
- ED_gp_get_drawing_reference(
- scene, gsc->ob, gsc->gpl,
- scene->toolsettings->gpencil_v3d_align, rvec);
+ ED_gp_get_drawing_reference(
+ scene, gsc->ob, gsc->gpl, scene->toolsettings->gpencil_v3d_align, rvec);
- float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
+ float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
- float mval_f[2], mval_prj[2];
- float dvec[3];
+ float mval_f[2], mval_prj[2];
+ float dvec[3];
- copy_v2_v2(mval_f, screen_co);
+ copy_v2_v2(mval_f, screen_co);
- if (ED_view3d_project_float_global(gsc->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(gsc->ar, mval_f, dvec, zfac);
- sub_v3_v3v3(r_out, rvec, dvec);
+ if (ED_view3d_project_float_global(gsc->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(gsc->ar, mval_f, dvec, zfac);
+ sub_v3_v3v3(r_out, rvec, dvec);
- return true;
- }
- else {
- zero_v3(r_out);
+ return true;
+ }
+ else {
+ zero_v3(r_out);
- return false;
- }
+ return false;
+ }
}
/**
@@ -812,43 +829,45 @@ bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc, Scene *scene, const float
* \param depth: Depth array (via #ED_view3d_autodist_depth()).
* \param[out] r_out: The resulting 2D point data.
*/
-void gp_stroke_convertcoords_tpoint(
- Scene *scene, ARegion *ar,
- Object *ob, bGPDlayer *gpl,
- const tGPspoint *point2D, float *depth,
- float r_out[3])
+void gp_stroke_convertcoords_tpoint(Scene *scene,
+ ARegion *ar,
+ Object *ob,
+ bGPDlayer *gpl,
+ const tGPspoint *point2D,
+ float *depth,
+ float r_out[3])
{
- ToolSettings *ts = scene->toolsettings;
-
- 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))) {
- /* projecting onto 3D-Geometry
- * - nothing more needs to be done here, since view_autodist_simple() has already done it
- */
- }
- else {
- float mval_f[2] = {point2D->x, point2D->y};
- float mval_prj[2];
- float rvec[3], dvec[3];
- float zfac;
-
- /* 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);
-
- if (ED_view3d_project_float_global(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(ar, mval_f, dvec, zfac);
- sub_v3_v3v3(r_out, rvec, dvec);
- }
- else {
- zero_v3(r_out);
- }
- }
+ ToolSettings *ts = scene->toolsettings;
+
+ 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))) {
+ /* projecting onto 3D-Geometry
+ * - nothing more needs to be done here, since view_autodist_simple() has already done it
+ */
+ }
+ else {
+ float mval_f[2] = {point2D->x, point2D->y};
+ float mval_prj[2];
+ float rvec[3], dvec[3];
+ float zfac;
+
+ /* 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);
+
+ if (ED_view3d_project_float_global(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(ar, mval_f, dvec, zfac);
+ sub_v3_v3v3(r_out, rvec, dvec);
+ }
+ else {
+ zero_v3(r_out);
+ }
+ }
}
/**
@@ -856,209 +875,206 @@ void gp_stroke_convertcoords_tpoint(
* \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])
+ const Scene *scene, const Object *ob, bGPDlayer *UNUSED(gpl), char align_flag, float r_vec[3])
{
- const float *fp = scene->cursor.location;
-
- /* if using a gpencil object at cursor mode, can use the location of the object */
- if (align_flag & GP_PROJECT_VIEWSPACE) {
- if (ob && (ob->type == OB_GPENCIL)) {
- /* fallback (no strokes) - use cursor or object location */
- if (align_flag & GP_PROJECT_CURSOR) {
- /* use 3D-cursor */
- copy_v3_v3(r_vec, fp);
- }
- else {
- /* use object location */
- copy_v3_v3(r_vec, ob->obmat[3]);
- }
- }
- }
- else {
- /* use 3D-cursor */
- copy_v3_v3(r_vec, fp);
- }
+ const float *fp = scene->cursor.location;
+
+ /* if using a gpencil object at cursor mode, can use the location of the object */
+ if (align_flag & GP_PROJECT_VIEWSPACE) {
+ if (ob && (ob->type == OB_GPENCIL)) {
+ /* fallback (no strokes) - use cursor or object location */
+ if (align_flag & GP_PROJECT_CURSOR) {
+ /* use 3D-cursor */
+ copy_v3_v3(r_vec, fp);
+ }
+ else {
+ /* use object location */
+ copy_v3_v3(r_vec, ob->obmat[3]);
+ }
+ }
+ }
+ else {
+ /* use 3D-cursor */
+ copy_v3_v3(r_vec, fp);
+ }
}
void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke *gps)
{
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *ob = CTX_data_active_object(C);
- bGPdata *gpd = (bGPdata *)ob->data;
- GP_SpaceConversion gsc = { NULL };
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ GP_SpaceConversion gsc = {NULL};
- bGPDspoint *pt;
- int i;
- float diff_mat[4][4];
- float inverse_diff_mat[4][4];
+ bGPDspoint *pt;
+ int i;
+ float diff_mat[4][4];
+ float inverse_diff_mat[4][4];
- /* init space conversion stuff */
- gp_point_conversion_init(C, &gsc);
+ /* init space conversion stuff */
+ gp_point_conversion_init(C, &gsc);
- ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat);
- invert_m4_m4(inverse_diff_mat, diff_mat);
+ ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat);
+ invert_m4_m4(inverse_diff_mat, diff_mat);
- /* Adjust each point */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- float xy[2];
+ /* Adjust each point */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ float xy[2];
- bGPDspoint pt2;
- gp_point_to_parent_space(pt, diff_mat, &pt2);
- gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]);
+ bGPDspoint pt2;
+ gp_point_to_parent_space(pt, diff_mat, &pt2);
+ gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]);
- /* Planar - All on same plane parallel to the viewplane */
- gp_point_xy_to_3d(&gsc, scene, xy, &pt->x);
+ /* Planar - All on same plane parallel to the viewplane */
+ gp_point_xy_to_3d(&gsc, scene, xy, &pt->x);
- /* Unapply parent corrections */
- mul_m4_v3(inverse_diff_mat, &pt->x);
- }
+ /* Unapply parent corrections */
+ mul_m4_v3(inverse_diff_mat, &pt->x);
+ }
}
/**
* Reproject all points of the stroke to a plane locked to axis to avoid stroke offset
*/
-void ED_gp_project_stroke_to_plane(
- const Scene *scene, const Object *ob,
- const RegionView3D *rv3d, bGPDstroke *gps,
- const float origin[3], const int axis)
+void ED_gp_project_stroke_to_plane(const Scene *scene,
+ const Object *ob,
+ const RegionView3D *rv3d,
+ bGPDstroke *gps,
+ const float origin[3],
+ const int axis)
{
- const ToolSettings *ts = scene->toolsettings;
- const View3DCursor *cursor = &scene->cursor;
- float plane_normal[3];
- float vn[3];
-
- float ray[3];
- float rpoint[3];
-
- /* normal vector for a plane locked to axis */
- zero_v3(plane_normal);
- if (axis < 0) {
- /* if the axis is not locked, need a vector to the view direction
- * in order to get the right size of the stroke.
- */
- ED_view3d_global_to_vector(rv3d, origin, plane_normal);
- }
- else if (axis < 3) {
- plane_normal[axis] = 1.0f;
- /* if object, apply object rotation */
- if (ob && (ob->type == OB_GPENCIL)) {
- float mat[4][4];
- copy_m4_m4(mat, ob->obmat);
-
- /* move origin to cursor */
- if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) {
- copy_v3_v3(mat[3], cursor->location);
- }
-
- mul_mat3_m4_v3(mat, plane_normal);
- }
- }
- else {
- float scale[3] = { 1.0f, 1.0f, 1.0f };
- plane_normal[2] = 1.0f;
- float mat[4][4];
- loc_eul_size_to_mat4(mat,
- cursor->location,
- cursor->rotation_euler,
- scale);
-
- /* move origin to object */
- if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) {
- copy_v3_v3(mat[3], ob->obmat[3]);
- }
-
- mul_mat3_m4_v3(mat, plane_normal);
- }
-
- /* Reproject the points in the plane */
- for (int i = 0; i < gps->totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
-
- /* get a vector from the point with the current view direction of the viewport */
- ED_view3d_global_to_vector(rv3d, &pt->x, vn);
-
- /* calculate line extreme point to create a ray that cross the plane */
- mul_v3_fl(vn, -50.0f);
- add_v3_v3v3(ray, &pt->x, vn);
-
- /* if the line never intersect, the point is not changed */
- if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) {
- copy_v3_v3(&pt->x, rpoint);
- }
- }
+ const ToolSettings *ts = scene->toolsettings;
+ const View3DCursor *cursor = &scene->cursor;
+ float plane_normal[3];
+ float vn[3];
+
+ float ray[3];
+ float rpoint[3];
+
+ /* normal vector for a plane locked to axis */
+ zero_v3(plane_normal);
+ if (axis < 0) {
+ /* if the axis is not locked, need a vector to the view direction
+ * in order to get the right size of the stroke.
+ */
+ ED_view3d_global_to_vector(rv3d, origin, plane_normal);
+ }
+ else if (axis < 3) {
+ plane_normal[axis] = 1.0f;
+ /* if object, apply object rotation */
+ if (ob && (ob->type == OB_GPENCIL)) {
+ float mat[4][4];
+ copy_m4_m4(mat, ob->obmat);
+
+ /* move origin to cursor */
+ if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) {
+ copy_v3_v3(mat[3], cursor->location);
+ }
+
+ mul_mat3_m4_v3(mat, plane_normal);
+ }
+ }
+ else {
+ float scale[3] = {1.0f, 1.0f, 1.0f};
+ plane_normal[2] = 1.0f;
+ float mat[4][4];
+ loc_eul_size_to_mat4(mat, cursor->location, cursor->rotation_euler, scale);
+
+ /* move origin to object */
+ if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) {
+ copy_v3_v3(mat[3], ob->obmat[3]);
+ }
+
+ mul_mat3_m4_v3(mat, plane_normal);
+ }
+
+ /* Reproject the points in the plane */
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+
+ /* get a vector from the point with the current view direction of the viewport */
+ ED_view3d_global_to_vector(rv3d, &pt->x, vn);
+
+ /* calculate line extreme point to create a ray that cross the plane */
+ mul_v3_fl(vn, -50.0f);
+ add_v3_v3v3(ray, &pt->x, vn);
+
+ /* if the line never intersect, the point is not changed */
+ if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) {
+ copy_v3_v3(&pt->x, rpoint);
+ }
+ }
}
/**
* Reproject given point to a plane locked to axis to avoid stroke offset
* \param[in,out] pt: Point to affect
*/
-void ED_gp_project_point_to_plane(
- const Scene *scene, const Object *ob,
- const RegionView3D *rv3d, const float origin[3],
- const int axis, bGPDspoint *pt)
+void ED_gp_project_point_to_plane(const Scene *scene,
+ const Object *ob,
+ const RegionView3D *rv3d,
+ const float origin[3],
+ const int axis,
+ bGPDspoint *pt)
{
- const ToolSettings *ts = scene->toolsettings;
- const View3DCursor *cursor = &scene->cursor;
- float plane_normal[3];
- float vn[3];
-
- float ray[3];
- float rpoint[3];
-
- /* normal vector for a plane locked to axis */
- zero_v3(plane_normal);
- if (axis < 0) {
- /* if the axis is not locked, need a vector to the view direction
- * in order to get the right size of the stroke.
- */
- ED_view3d_global_to_vector(rv3d, origin, plane_normal);
- }
- else if (axis < 3) {
- plane_normal[axis] = 1.0f;
- /* if object, apply object rotation */
- if (ob && (ob->type == OB_GPENCIL)) {
- float mat[4][4];
- copy_m4_m4(mat, ob->obmat);
-
- /* move origin to cursor */
- if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) {
- copy_v3_v3(mat[3], cursor->location);
- }
-
- mul_mat3_m4_v3(mat, plane_normal);
- }
- }
- else {
- float scale[3] = { 1.0f, 1.0f, 1.0f };
- plane_normal[2] = 1.0f;
- float mat[4][4];
- loc_eul_size_to_mat4(mat,
- cursor->location,
- cursor->rotation_euler,
- scale);
-
- /* move origin to object */
- if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) {
- copy_v3_v3(mat[3], ob->obmat[3]);
- }
-
- mul_mat3_m4_v3(mat, plane_normal);
- }
-
- /* Reproject the points in the plane */
- /* get a vector from the point with the current view direction of the viewport */
- ED_view3d_global_to_vector(rv3d, &pt->x, vn);
-
- /* calculate line extrem point to create a ray that cross the plane */
- mul_v3_fl(vn, -50.0f);
- add_v3_v3v3(ray, &pt->x, vn);
-
- /* if the line never intersect, the point is not changed */
- if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) {
- copy_v3_v3(&pt->x, rpoint);
- }
+ const ToolSettings *ts = scene->toolsettings;
+ const View3DCursor *cursor = &scene->cursor;
+ float plane_normal[3];
+ float vn[3];
+
+ float ray[3];
+ float rpoint[3];
+
+ /* normal vector for a plane locked to axis */
+ zero_v3(plane_normal);
+ if (axis < 0) {
+ /* if the axis is not locked, need a vector to the view direction
+ * in order to get the right size of the stroke.
+ */
+ ED_view3d_global_to_vector(rv3d, origin, plane_normal);
+ }
+ else if (axis < 3) {
+ plane_normal[axis] = 1.0f;
+ /* if object, apply object rotation */
+ if (ob && (ob->type == OB_GPENCIL)) {
+ float mat[4][4];
+ copy_m4_m4(mat, ob->obmat);
+
+ /* move origin to cursor */
+ if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) {
+ copy_v3_v3(mat[3], cursor->location);
+ }
+
+ mul_mat3_m4_v3(mat, plane_normal);
+ }
+ }
+ else {
+ float scale[3] = {1.0f, 1.0f, 1.0f};
+ plane_normal[2] = 1.0f;
+ float mat[4][4];
+ loc_eul_size_to_mat4(mat, cursor->location, cursor->rotation_euler, scale);
+
+ /* move origin to object */
+ if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) {
+ copy_v3_v3(mat[3], ob->obmat[3]);
+ }
+
+ mul_mat3_m4_v3(mat, plane_normal);
+ }
+
+ /* Reproject the points in the plane */
+ /* get a vector from the point with the current view direction of the viewport */
+ ED_view3d_global_to_vector(rv3d, &pt->x, vn);
+
+ /* calculate line extrem point to create a ray that cross the plane */
+ mul_v3_fl(vn, -50.0f);
+ add_v3_v3v3(ray, &pt->x, vn);
+
+ /* if the line never intersect, the point is not changed */
+ if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) {
+ copy_v3_v3(&pt->x, rpoint);
+ }
}
/* ******************************************************** */
@@ -1072,92 +1088,92 @@ void ED_gp_project_point_to_plane(
*/
void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide)
{
- bGPDspoint *temp_points;
- int totnewpoints, oldtotpoints;
- int i2;
-
- /* loop as many times as levels */
- for (int s = 0; s < subdivide; s++) {
- totnewpoints = gps->totpoints - 1;
- /* duplicate points in a temp area */
- temp_points = MEM_dupallocN(gps->points);
- oldtotpoints = gps->totpoints;
-
- /* resize the points arrays */
- gps->totpoints += totnewpoints;
- gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
- if (gps->dvert != NULL) {
- gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
- }
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
-
- /* move points from last to first to new place */
- i2 = gps->totpoints - 1;
- for (int i = oldtotpoints - 1; i > 0; i--) {
- bGPDspoint *pt = &temp_points[i];
- bGPDspoint *pt_final = &gps->points[i2];
-
- copy_v3_v3(&pt_final->x, &pt->x);
- pt_final->pressure = pt->pressure;
- pt_final->strength = pt->strength;
- pt_final->time = pt->time;
- pt_final->flag = pt->flag;
- pt_final->uv_fac = pt->uv_fac;
- pt_final->uv_rot = pt->uv_rot;
-
- if (gps->dvert != NULL) {
- MDeformVert *dvert = &gps->dvert[i];
- MDeformVert *dvert_final = &gps->dvert[i2];
-
- dvert_final->totweight = dvert->totweight;
- dvert_final->dw = dvert->dw;
- }
-
- i2 -= 2;
- }
- /* interpolate mid points */
- i2 = 1;
- for (int i = 0; i < oldtotpoints - 1; i++) {
- bGPDspoint *pt = &temp_points[i];
- bGPDspoint *next = &temp_points[i + 1];
- bGPDspoint *pt_final = &gps->points[i2];
-
- /* add a half way point */
- interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
- 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);
- 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);
-
- if (gps->dvert != NULL) {
- MDeformVert *dvert_final = &gps->dvert[i2];
- dvert_final->totweight = 0;
- dvert_final->dw = NULL;
- }
-
- i2 += 2;
- }
-
- MEM_SAFE_FREE(temp_points);
-
- /* move points to smooth stroke */
- /* duplicate points in a temp area with the new subdivide data */
- temp_points = MEM_dupallocN(gps->points);
-
- /* extreme points are not changed */
- for (int i = 0; i < gps->totpoints - 2; i++) {
- bGPDspoint *pt = &temp_points[i];
- bGPDspoint *next = &temp_points[i + 1];
- bGPDspoint *pt_final = &gps->points[i + 1];
-
- /* move point */
- interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
- }
- /* free temp memory */
- MEM_SAFE_FREE(temp_points);
- }
+ bGPDspoint *temp_points;
+ int totnewpoints, oldtotpoints;
+ int i2;
+
+ /* loop as many times as levels */
+ for (int s = 0; s < subdivide; s++) {
+ totnewpoints = gps->totpoints - 1;
+ /* duplicate points in a temp area */
+ temp_points = MEM_dupallocN(gps->points);
+ oldtotpoints = gps->totpoints;
+
+ /* resize the points arrays */
+ gps->totpoints += totnewpoints;
+ gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
+ if (gps->dvert != NULL) {
+ gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
+ }
+ gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+
+ /* move points from last to first to new place */
+ i2 = gps->totpoints - 1;
+ for (int i = oldtotpoints - 1; i > 0; i--) {
+ bGPDspoint *pt = &temp_points[i];
+ bGPDspoint *pt_final = &gps->points[i2];
+
+ copy_v3_v3(&pt_final->x, &pt->x);
+ pt_final->pressure = pt->pressure;
+ pt_final->strength = pt->strength;
+ pt_final->time = pt->time;
+ pt_final->flag = pt->flag;
+ pt_final->uv_fac = pt->uv_fac;
+ pt_final->uv_rot = pt->uv_rot;
+
+ if (gps->dvert != NULL) {
+ MDeformVert *dvert = &gps->dvert[i];
+ MDeformVert *dvert_final = &gps->dvert[i2];
+
+ dvert_final->totweight = dvert->totweight;
+ dvert_final->dw = dvert->dw;
+ }
+
+ i2 -= 2;
+ }
+ /* interpolate mid points */
+ i2 = 1;
+ for (int i = 0; i < oldtotpoints - 1; i++) {
+ bGPDspoint *pt = &temp_points[i];
+ bGPDspoint *next = &temp_points[i + 1];
+ bGPDspoint *pt_final = &gps->points[i2];
+
+ /* add a half way point */
+ interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
+ 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);
+ 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);
+
+ if (gps->dvert != NULL) {
+ MDeformVert *dvert_final = &gps->dvert[i2];
+ dvert_final->totweight = 0;
+ dvert_final->dw = NULL;
+ }
+
+ i2 += 2;
+ }
+
+ MEM_SAFE_FREE(temp_points);
+
+ /* move points to smooth stroke */
+ /* duplicate points in a temp area with the new subdivide data */
+ temp_points = MEM_dupallocN(gps->points);
+
+ /* extreme points are not changed */
+ for (int i = 0; i < gps->totpoints - 2; i++) {
+ bGPDspoint *pt = &temp_points[i];
+ bGPDspoint *next = &temp_points[i + 1];
+ bGPDspoint *pt_final = &gps->points[i + 1];
+
+ /* move point */
+ interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
+ }
+ /* free temp memory */
+ MEM_SAFE_FREE(temp_points);
+ }
}
/**
@@ -1167,184 +1183,189 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide)
*/
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);
- }
+ 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])
+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);
- 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);
- }
- else {
- /* if bone not found use object (armature) */
- mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
- }
- return;
- }
- else {
- unit_m4(diff_mat); /* not defined type */
- }
- }
+ 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);
+ 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);
+ }
+ else {
+ /* if bone not found use object (armature) */
+ mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
+ }
+ return;
+ }
+ else {
+ unit_m4(diff_mat); /* not defined type */
+ }
+ }
}
/* reset parent matrix for all layers */
void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata *gpd)
{
- bGPDspoint *pt;
- int i;
- float diff_mat[4][4];
- float cur_mat[4][4];
-
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpl->parent != NULL) {
- /* calculate new matrix */
- if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
- invert_m4_m4(cur_mat, gpl->parent->obmat);
- }
- else if (gpl->partype == PARBONE) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(gpl->parent->pose, gpl->parsubstr);
- if (pchan) {
- float tmp_mat[4][4];
- mul_m4_m4m4(tmp_mat, gpl->parent->obmat, pchan->pose_mat);
- invert_m4_m4(cur_mat, tmp_mat);
- }
- }
-
- /* 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);
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- mul_m4_v3(diff_mat, &pt->x);
- }
- }
- }
- /* set new parent matrix */
- copy_m4_m4(gpl->inverse, cur_mat);
- }
- }
- }
+ bGPDspoint *pt;
+ int i;
+ float diff_mat[4][4];
+ float cur_mat[4][4];
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpl->parent != NULL) {
+ /* calculate new matrix */
+ if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
+ invert_m4_m4(cur_mat, gpl->parent->obmat);
+ }
+ else if (gpl->partype == PARBONE) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(gpl->parent->pose, gpl->parsubstr);
+ if (pchan) {
+ float tmp_mat[4][4];
+ mul_m4_m4m4(tmp_mat, gpl->parent->obmat, pchan->pose_mat);
+ invert_m4_m4(cur_mat, tmp_mat);
+ }
+ }
+
+ /* 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);
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ mul_m4_v3(diff_mat, &pt->x);
+ }
+ }
+ }
+ /* set new parent matrix */
+ copy_m4_m4(gpl->inverse, cur_mat);
+ }
+ }
+ }
}
/* ******************************************************** */
/* 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,
+ Scene *UNUSED(scene),
+ const float loc[3],
+ ushort local_view_bits)
{
- float rot[3] = {0.0f};
+ float rot[3] = {0.0f};
- Object *ob = ED_object_add_type(C, OB_GPENCIL, NULL, loc, rot, false, local_view_bits);
+ Object *ob = ED_object_add_type(C, OB_GPENCIL, NULL, loc, rot, false, local_view_bits);
- /* create default brushes and colors */
- ED_gpencil_add_defaults(C, ob);
+ /* create default brushes and colors */
+ ED_gpencil_add_defaults(C, ob);
- return ob;
+ return ob;
}
/* Helper function to create default colors and drawing brushes */
void ED_gpencil_add_defaults(bContext *C, Object *ob)
{
- Main *bmain = CTX_data_main(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
-
- BKE_paint_ensure(ts, (Paint **)&ts->gp_paint);
- Paint *paint = &ts->gp_paint->paint;
- /* if not exist, create a new one */
- if (paint->brush == NULL) {
- /* create new brushes */
- BKE_brush_gpencil_presets(C);
- }
-
- /* ensure a color exists and is assigned to object */
- BKE_gpencil_object_material_ensure_from_active_input_toolsettings(bmain, ob, ts);
-
- /* ensure multiframe falloff curve */
- if (ts->gp_sculpt.cur_falloff == NULL) {
- ts->gp_sculpt.cur_falloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
- CurveMapping *gp_falloff_curve = ts->gp_sculpt.cur_falloff;
- curvemapping_initialize(gp_falloff_curve);
- curvemap_reset(
- gp_falloff_curve->cm,
- &gp_falloff_curve->clipr,
- CURVE_PRESET_GAUSS,
- CURVEMAP_SLOPE_POSITIVE);
- }
+ Main *bmain = CTX_data_main(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+
+ BKE_paint_ensure(ts, (Paint **)&ts->gp_paint);
+ Paint *paint = &ts->gp_paint->paint;
+ /* if not exist, create a new one */
+ if (paint->brush == NULL) {
+ /* create new brushes */
+ BKE_brush_gpencil_presets(C);
+ }
+
+ /* ensure a color exists and is assigned to object */
+ BKE_gpencil_object_material_ensure_from_active_input_toolsettings(bmain, ob, ts);
+
+ /* ensure multiframe falloff curve */
+ if (ts->gp_sculpt.cur_falloff == NULL) {
+ ts->gp_sculpt.cur_falloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ CurveMapping *gp_falloff_curve = ts->gp_sculpt.cur_falloff;
+ curvemapping_initialize(gp_falloff_curve);
+ curvemap_reset(gp_falloff_curve->cm,
+ &gp_falloff_curve->clipr,
+ CURVE_PRESET_GAUSS,
+ CURVEMAP_SLOPE_POSITIVE);
+ }
}
/* ******************************************************** */
@@ -1353,213 +1374,209 @@ void ED_gpencil_add_defaults(bContext *C, Object *ob)
/* assign points to vertex group */
void ED_gpencil_vgroup_assign(bContext *C, Object *ob, float weight)
{
- bGPdata *gpd = (bGPdata *)ob->data;
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- const int def_nr = ob->actdef - 1;
- if (!BLI_findlink(&ob->defbase, def_nr))
- return;
-
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- bGPDframe *init_gpf = gpl->actframe;
- bGPDstroke *gps = NULL;
- 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))) {
- if (gpf == NULL)
- continue;
-
- for (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;
-
- if (gps->flag & GP_STROKE_SELECT) {
- /* verify the weight array is created */
- BKE_gpencil_dvert_ensure(gps);
-
- for (int i = 0; i < gps->totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
- MDeformVert *dvert = &gps->dvert[i];
- if (pt->flag & GP_SPOINT_SELECT) {
- MDeformWeight *dw = defvert_verify_index(dvert, def_nr);
- if (dw) {
- dw->weight = weight;
- }
- }
- }
- }
- }
- }
-
- /* if not multiedit, exit loop*/
- if (!is_multiedit) {
- break;
- }
- }
- }
- CTX_DATA_END;
+ bGPdata *gpd = (bGPdata *)ob->data;
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ const int def_nr = ob->actdef - 1;
+ if (!BLI_findlink(&ob->defbase, def_nr))
+ return;
+
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ bGPDframe *init_gpf = gpl->actframe;
+ bGPDstroke *gps = NULL;
+ 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))) {
+ if (gpf == NULL)
+ continue;
+
+ for (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;
+
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* verify the weight array is created */
+ BKE_gpencil_dvert_ensure(gps);
+
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = &gps->dvert[i];
+ if (pt->flag & GP_SPOINT_SELECT) {
+ MDeformWeight *dw = defvert_verify_index(dvert, def_nr);
+ if (dw) {
+ dw->weight = weight;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* if not multiedit, exit loop*/
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ CTX_DATA_END;
}
/* remove points from vertex group */
void ED_gpencil_vgroup_remove(bContext *C, Object *ob)
{
- bGPdata *gpd = (bGPdata *)ob->data;
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- const int def_nr = ob->actdef - 1;
- if (!BLI_findlink(&ob->defbase, def_nr))
- return;
-
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- bGPDframe *init_gpf = gpl->actframe;
- bGPDstroke *gps = NULL;
- 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))) {
- if (gpf == NULL)
- continue;
-
- for (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;
-
- for (int i = 0; i < gps->totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
- if (gps->dvert == NULL) {
- continue;
- }
- MDeformVert *dvert = &gps->dvert[i];
-
- if ((pt->flag & GP_SPOINT_SELECT) && (dvert->totweight > 0)) {
- MDeformWeight *dw = defvert_find_index(dvert, def_nr);
- if (dw != NULL) {
- defvert_remove_group(dvert, dw);
- }
- }
- }
- }
- }
-
- /* if not multiedit, exit loop*/
- if (!is_multiedit) {
- break;
- }
- }
- }
- CTX_DATA_END;
+ bGPdata *gpd = (bGPdata *)ob->data;
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ const int def_nr = ob->actdef - 1;
+ if (!BLI_findlink(&ob->defbase, def_nr))
+ return;
+
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ bGPDframe *init_gpf = gpl->actframe;
+ bGPDstroke *gps = NULL;
+ 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))) {
+ if (gpf == NULL)
+ continue;
+
+ for (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;
+
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ if (gps->dvert == NULL) {
+ continue;
+ }
+ MDeformVert *dvert = &gps->dvert[i];
+
+ if ((pt->flag & GP_SPOINT_SELECT) && (dvert->totweight > 0)) {
+ MDeformWeight *dw = defvert_find_index(dvert, def_nr);
+ if (dw != NULL) {
+ defvert_remove_group(dvert, dw);
+ }
+ }
+ }
+ }
+ }
+
+ /* if not multiedit, exit loop*/
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ CTX_DATA_END;
}
/* select points of vertex group */
void ED_gpencil_vgroup_select(bContext *C, Object *ob)
{
- bGPdata *gpd = (bGPdata *)ob->data;
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- const int def_nr = ob->actdef - 1;
- if (!BLI_findlink(&ob->defbase, def_nr))
- return;
-
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- bGPDframe *init_gpf = gpl->actframe;
- bGPDstroke *gps = NULL;
- 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))) {
- if (gpf == NULL)
- continue;
-
- for (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;
-
- for (int i = 0; i < gps->totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
- if (gps->dvert == NULL) {
- continue;
- }
- MDeformVert *dvert = &gps->dvert[i];
-
- if (defvert_find_index(dvert, def_nr) != NULL) {
- pt->flag |= GP_SPOINT_SELECT;
- gps->flag |= GP_STROKE_SELECT;
- }
- }
- }
- }
-
- /* if not multiedit, exit loop*/
- if (!is_multiedit) {
- break;
- }
- }
- }
- CTX_DATA_END;
+ bGPdata *gpd = (bGPdata *)ob->data;
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ const int def_nr = ob->actdef - 1;
+ if (!BLI_findlink(&ob->defbase, def_nr))
+ return;
+
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ bGPDframe *init_gpf = gpl->actframe;
+ bGPDstroke *gps = NULL;
+ 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))) {
+ if (gpf == NULL)
+ continue;
+
+ for (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;
+
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ if (gps->dvert == NULL) {
+ continue;
+ }
+ MDeformVert *dvert = &gps->dvert[i];
+
+ if (defvert_find_index(dvert, def_nr) != NULL) {
+ pt->flag |= GP_SPOINT_SELECT;
+ gps->flag |= GP_STROKE_SELECT;
+ }
+ }
+ }
+ }
+
+ /* if not multiedit, exit loop*/
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ CTX_DATA_END;
}
/* unselect points of vertex group */
void ED_gpencil_vgroup_deselect(bContext *C, Object *ob)
{
- bGPdata *gpd = (bGPdata *)ob->data;
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- const int def_nr = ob->actdef - 1;
- if (!BLI_findlink(&ob->defbase, def_nr))
- return;
-
- CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
- {
- bGPDframe *init_gpf = gpl->actframe;
- bGPDstroke *gps = NULL;
- 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))) {
- if (gpf == NULL)
- continue;
-
- for (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;
-
- for (int i = 0; i < gps->totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
- if (gps->dvert == NULL) {
- continue;
- }
- MDeformVert *dvert = &gps->dvert[i];
-
- if (defvert_find_index(dvert, def_nr) != NULL) {
- pt->flag &= ~GP_SPOINT_SELECT;
- }
- }
- }
- }
-
- /* if not multiedit, exit loop*/
- if (!is_multiedit) {
- break;
- }
- }
- }
- CTX_DATA_END;
+ bGPdata *gpd = (bGPdata *)ob->data;
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ const int def_nr = ob->actdef - 1;
+ if (!BLI_findlink(&ob->defbase, def_nr))
+ return;
+
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ bGPDframe *init_gpf = gpl->actframe;
+ bGPDstroke *gps = NULL;
+ 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))) {
+ if (gpf == NULL)
+ continue;
+
+ for (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;
+
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ if (gps->dvert == NULL) {
+ continue;
+ }
+ MDeformVert *dvert = &gps->dvert[i];
+
+ if (defvert_find_index(dvert, def_nr) != NULL) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ }
+ }
+ }
+
+ /* if not multiedit, exit loop*/
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ CTX_DATA_END;
}
/* ******************************************************** */
@@ -1568,903 +1585,902 @@ 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);
- 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)))
- {
- return false;
- }
-
- /* TODO: add more spacetypes */
- if (!ELEM(sa->spacetype, SPACE_VIEW3D)) {
- return false;
- }
- if ((ar) && (ar->regiontype != RGN_TYPE_WINDOW)) {
- return false;
- }
- else if (ar) {
- return BLI_rcti_isect_pt_v(&ar->winrct, mval_i);
- }
- else {
- return false;
- }
+ ARegion *ar = CTX_wm_region(C);
+ ScrArea *sa = 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))) {
+ return false;
+ }
+
+ /* TODO: add more spacetypes */
+ if (!ELEM(sa->spacetype, SPACE_VIEW3D)) {
+ return false;
+ }
+ if ((ar) && (ar->regiontype != RGN_TYPE_WINDOW)) {
+ return false;
+ }
+ else if (ar) {
+ return BLI_rcti_isect_pt_v(&ar->winrct, mval_i);
+ }
+ else {
+ return false;
+ }
}
/* draw eraser cursor */
void ED_gpencil_brush_draw_eraser(Brush *brush, int x, int y)
{
- short radius = (short)brush->size;
+ short radius = (short)brush->size;
- GPUVertFormat *format = immVertexFormat();
- const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ GPUVertFormat *format = immVertexFormat();
+ const uint shdr_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);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_line_smooth(true);
+ GPU_blend(true);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- immUniformColor4ub(255, 100, 100, 20);
- imm_draw_circle_fill_2d(shdr_pos, x, y, radius, 40);
+ immUniformColor4ub(255, 100, 100, 20);
+ imm_draw_circle_fill_2d(shdr_pos, x, y, radius, 40);
- immUnbindProgram();
+ immUnbindProgram();
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- glGetFloatv(GL_VIEWPORT, viewport_size);
- immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
- immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f);
- immUniform1i("colors_len", 0); /* "simple" mode */
- immUniform1f("dash_width", 12.0f);
- immUniform1f("dash_factor", 0.5f);
+ immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f);
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniform1f("dash_width", 12.0f);
+ immUniform1f("dash_factor", 0.5f);
- imm_draw_circle_wire_2d(
- shdr_pos, x, y, radius,
- /* XXX Dashed shader gives bad results with sets of small segments currently,
- * temp hack around the issue. :( */
- max_ii(8, radius / 2)); /* was fixed 40 */
+ imm_draw_circle_wire_2d(
+ shdr_pos,
+ x,
+ y,
+ radius,
+ /* XXX Dashed shader gives bad results with sets of small segments currently,
+ * temp hack around the issue. :( */
+ max_ii(8, radius / 2)); /* was fixed 40 */
- immUnbindProgram();
+ immUnbindProgram();
- GPU_blend(false);
- GPU_line_smooth(false);
+ GPU_blend(false);
+ GPU_line_smooth(false);
}
static bool gp_brush_cursor_poll(bContext *C)
{
- if (WM_toolsystem_active_tool_is_brush(C)) {
- return true;
- }
- return false;
+ if (WM_toolsystem_active_tool_is_brush(C)) {
+ return true;
+ }
+ return false;
}
/* Helper callback for drawing the cursor itself */
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);
-
- 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];
- float radius = 3.0f;
-
- int mval_i[2] = {x, y};
- /* check if cursor is in drawing region and has valid datablock */
- if ((!gp_check_cursor_region(C, mval_i)) || (gpd == NULL)) {
- return;
- }
-
- /* for paint use paint brush size and color */
- if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
- brush = scene->toolsettings->gp_paint->paint.brush;
- if ((brush == NULL) || (brush->gpencil_settings == NULL)) {
- return;
- }
-
- /* while drawing hide */
- if ((gpd->runtime.sbuffer_size > 0) &&
- ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
- ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0))
- {
- return;
- }
-
- if ((brush->gpencil_settings->flag & GP_BRUSH_ENABLE_CURSOR) == 0) {
- return;
- }
-
- /* eraser has special shape and use a different shader program */
- if (brush->gpencil_tool == GPAINT_TOOL_ERASE) {
- ED_gpencil_brush_draw_eraser(brush, x, y);
- return;
- }
-
- /* get current drawing color */
- ma = BKE_gpencil_object_material_get_from_brush(ob, brush);
-
- if (ma) {
- gp_style = ma->gp_style;
-
- /* after some testing, display the size of the brush is not practical because
- * is too disruptive and the size of cursor does not change with zoom factor.
- * The decision was to use a fix size, instead of brush->thickness value.
- */
- if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) &&
- ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
- ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) &&
- (brush->gpencil_tool == GPAINT_TOOL_DRAW))
- {
- radius = 2.0f;
- copy_v3_v3(color, gp_style->stroke_rgba);
- }
- 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;
- }
-
- 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);
- }
- }
- }
-
- /* draw icon */
- 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);
-
- /* Inner Ring: Color from UI panel */
- immUniformColor4f(color[0], color[1], color[2], 0.8f);
- if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) &&
- ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
- ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) &&
- (brush->gpencil_tool == GPAINT_TOOL_DRAW))
- {
- imm_draw_circle_fill_2d(pos, x, y, radius, 40);
- }
- else {
- 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);
-
- GPU_blend(false);
- GPU_line_smooth(false);
-
- /* Draw line for lazy mouse */
- if ((last_mouse_position) &&
- (brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP))
- {
- GPU_line_smooth(true);
- GPU_blend(true);
-
- copy_v3_v3(color, brush->add_col);
- immUniformColor4f(color[0], color[1], color[2], 0.8f);
-
- 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);
- immEnd();
-
- GPU_blend(false);
- GPU_line_smooth(false);
- }
-
- immUnbindProgram();
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ ARegion *ar = CTX_wm_region(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];
+ float radius = 3.0f;
+
+ int mval_i[2] = {x, y};
+ /* check if cursor is in drawing region and has valid datablock */
+ if ((!gp_check_cursor_region(C, mval_i)) || (gpd == NULL)) {
+ return;
+ }
+
+ /* for paint use paint brush size and color */
+ if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
+ brush = scene->toolsettings->gp_paint->paint.brush;
+ if ((brush == NULL) || (brush->gpencil_settings == NULL)) {
+ return;
+ }
+
+ /* while drawing hide */
+ if ((gpd->runtime.sbuffer_size > 0) &&
+ ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
+ ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0)) {
+ return;
+ }
+
+ if ((brush->gpencil_settings->flag & GP_BRUSH_ENABLE_CURSOR) == 0) {
+ return;
+ }
+
+ /* eraser has special shape and use a different shader program */
+ if (brush->gpencil_tool == GPAINT_TOOL_ERASE) {
+ ED_gpencil_brush_draw_eraser(brush, x, y);
+ return;
+ }
+
+ /* get current drawing color */
+ ma = BKE_gpencil_object_material_get_from_brush(ob, brush);
+
+ if (ma) {
+ gp_style = ma->gp_style;
+
+ /* after some testing, display the size of the brush is not practical because
+ * is too disruptive and the size of cursor does not change with zoom factor.
+ * The decision was to use a fix size, instead of brush->thickness value.
+ */
+ if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) &&
+ ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
+ ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) &&
+ (brush->gpencil_tool == GPAINT_TOOL_DRAW)) {
+ radius = 2.0f;
+ copy_v3_v3(color, gp_style->stroke_rgba);
+ }
+ 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;
+ }
+
+ 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);
+ }
+ }
+ }
+
+ /* draw icon */
+ 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);
+
+ /* Inner Ring: Color from UI panel */
+ immUniformColor4f(color[0], color[1], color[2], 0.8f);
+ if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) &&
+ ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
+ ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) &&
+ (brush->gpencil_tool == GPAINT_TOOL_DRAW)) {
+ imm_draw_circle_fill_2d(pos, x, y, radius, 40);
+ }
+ else {
+ 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);
+
+ GPU_blend(false);
+ GPU_line_smooth(false);
+
+ /* Draw line for lazy mouse */
+ if ((last_mouse_position) && (brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP)) {
+ GPU_line_smooth(true);
+ GPU_blend(true);
+
+ copy_v3_v3(color, brush->add_col);
+ immUniformColor4f(color[0], color[1], color[2], 0.8f);
+
+ 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);
+ immEnd();
+
+ GPU_blend(false);
+ GPU_line_smooth(false);
+ }
+
+ immUnbindProgram();
}
/* Turn brush cursor in on/off */
void ED_gpencil_toggle_brush_cursor(bContext *C, bool enable, void *customdata)
{
- Scene *scene = CTX_data_scene(C);
- GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
- float *lastpost = customdata;
-
- if (gset->paintcursor && !enable) {
- /* clear cursor */
- WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor);
- gset->paintcursor = NULL;
- }
- else if (enable) {
- /* in some situations cursor could be duplicated, so it is better disable first if exist */
- if (gset->paintcursor) {
- /* clear cursor */
- WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor);
- gset->paintcursor = NULL;
- }
- /* enable cursor */
- gset->paintcursor = WM_paint_cursor_activate(
- CTX_wm_manager(C),
- SPACE_TYPE_ANY, RGN_TYPE_ANY,
- gp_brush_cursor_poll,
- gp_brush_cursor_draw,
- (lastpost) ? customdata : NULL);
- }
+ Scene *scene = CTX_data_scene(C);
+ GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
+ float *lastpost = customdata;
+
+ if (gset->paintcursor && !enable) {
+ /* clear cursor */
+ WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor);
+ gset->paintcursor = NULL;
+ }
+ else if (enable) {
+ /* in some situations cursor could be duplicated, so it is better disable first if exist */
+ if (gset->paintcursor) {
+ /* clear cursor */
+ WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor);
+ gset->paintcursor = NULL;
+ }
+ /* enable cursor */
+ gset->paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C),
+ SPACE_TYPE_ANY,
+ RGN_TYPE_ANY,
+ gp_brush_cursor_poll,
+ gp_brush_cursor_draw,
+ (lastpost) ? customdata : NULL);
+ }
}
/* 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;
- }
+ 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)
{
- if (!gpd) {
- return;
- }
-
- switch (newmode) {
- case OB_MODE_EDIT_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;
- ED_gpencil_toggle_brush_cursor(C, false, NULL);
- break;
- case OB_MODE_PAINT_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;
- ED_gpencil_toggle_brush_cursor(C, true, NULL);
- break;
- case OB_MODE_SCULPT_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;
- gpencil_verify_brush_type(C, OB_MODE_SCULPT_GPENCIL);
- ED_gpencil_toggle_brush_cursor(C, true, NULL);
- break;
- case OB_MODE_WEIGHT_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;
- gpencil_verify_brush_type(C, OB_MODE_WEIGHT_GPENCIL);
- ED_gpencil_toggle_brush_cursor(C, true, NULL);
- break;
- default:
- gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
- gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
- gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
- gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
- ED_gpencil_toggle_brush_cursor(C, false, NULL);
- break;
- }
+ if (!gpd) {
+ return;
+ }
+
+ switch (newmode) {
+ case OB_MODE_EDIT_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;
+ ED_gpencil_toggle_brush_cursor(C, false, NULL);
+ break;
+ case OB_MODE_PAINT_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;
+ ED_gpencil_toggle_brush_cursor(C, true, NULL);
+ break;
+ case OB_MODE_SCULPT_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;
+ gpencil_verify_brush_type(C, OB_MODE_SCULPT_GPENCIL);
+ ED_gpencil_toggle_brush_cursor(C, true, NULL);
+ break;
+ case OB_MODE_WEIGHT_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;
+ gpencil_verify_brush_type(C, OB_MODE_WEIGHT_GPENCIL);
+ ED_gpencil_toggle_brush_cursor(C, true, NULL);
+ break;
+ default:
+ gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
+ gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
+ gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
+ gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
+ 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, const tGPspoint *point2D, float origin[3], float out[3])
+static void gpencil_stroke_convertcoords(ARegion *ar,
+ const tGPspoint *point2D,
+ float origin[3],
+ float out[3])
{
- float mval_f[2] = { (float)point2D->x, (float)point2D->y };
- float mval_prj[2];
- float rvec[3], dvec[3];
- float zfac;
-
- copy_v3_v3(rvec, origin);
-
- zfac = ED_view3d_calc_zfac(ar->regiondata, rvec, NULL);
-
- if (ED_view3d_project_float_global(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(ar, mval_f, dvec, zfac);
- sub_v3_v3v3(out, rvec, dvec);
- }
- else {
- zero_v3(out);
- }
+ float mval_f[2] = {(float)point2D->x, (float)point2D->y};
+ float mval_prj[2];
+ float rvec[3], dvec[3];
+ float zfac;
+
+ copy_v3_v3(rvec, origin);
+
+ zfac = ED_view3d_calc_zfac(ar->regiondata, rvec, NULL);
+
+ if (ED_view3d_project_float_global(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(ar, mval_f, dvec, zfac);
+ sub_v3_v3v3(out, rvec, dvec);
+ }
+ else {
+ zero_v3(out);
+ }
}
/* convert 2d tGPspoint to 3d bGPDspoint */
void ED_gpencil_tpoint_to_point(ARegion *ar, float origin[3], const tGPspoint *tpt, bGPDspoint *pt)
{
- float p3d[3];
- /* conversion to 3d format */
- gpencil_stroke_convertcoords(ar, tpt, origin, p3d);
- copy_v3_v3(&pt->x, p3d);
-
- pt->pressure = tpt->pressure;
- pt->strength = tpt->strength;
- pt->uv_fac = tpt->uv_fac;
- pt->uv_rot = tpt->uv_rot;
+ float p3d[3];
+ /* conversion to 3d format */
+ gpencil_stroke_convertcoords(ar, tpt, origin, p3d);
+ copy_v3_v3(&pt->x, p3d);
+
+ pt->pressure = tpt->pressure;
+ pt->strength = tpt->strength;
+ pt->uv_fac = tpt->uv_fac;
+ 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;
- }
+ 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)
{
- Material *gps_ma = NULL;
- /* read all strokes */
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- if (ob->type == OB_GPENCIL) {
- bGPdata *gpd = ob->data;
- if (gpd == NULL) {
- continue;
- }
-
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* 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) {
- /* check if it is editable */
- if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
- continue;
- }
- gps_ma = give_current_material(ob, gps->mat_nr + 1);
- /* update */
- if ((gps_ma) && (gps_ma == mat)) {
- ED_gpencil_calc_stroke_uv(ob, gps);
- }
- }
- }
- }
- }
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- }
- }
+ Material *gps_ma = NULL;
+ /* read all strokes */
+ for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
+ if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = ob->data;
+ if (gpd == NULL) {
+ continue;
+ }
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* 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) {
+ /* check if it is editable */
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
+ continue;
+ }
+ gps_ma = give_current_material(ob, gps->mat_nr + 1);
+ /* update */
+ if ((gps_ma) && (gps_ma == mat)) {
+ ED_gpencil_calc_stroke_uv(ob, gps);
+ }
+ }
+ }
+ }
+ }
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ }
+ }
}
-static bool gpencil_check_collision(
- bGPDstroke *gps, bGPDstroke **gps_array, GHash *all_2d,
- int totstrokes, float p2d_a1[2], float p2d_a2[2], float r_hit[2])
+static bool gpencil_check_collision(bGPDstroke *gps,
+ bGPDstroke **gps_array,
+ GHash *all_2d,
+ int totstrokes,
+ float p2d_a1[2],
+ float p2d_a2[2],
+ float r_hit[2])
{
- bool hit = false;
- /* check segment with all segments of all strokes */
- for (int s = 0; s < totstrokes; s++) {
- bGPDstroke *gps_iter = gps_array[s];
- if (gps_iter->totpoints < 2) {
- continue;
- }
- /* get stroke 2d version */
- float(*points2d)[2] = BLI_ghash_lookup(all_2d, gps_iter);
-
- for (int i2 = 0; i2 < gps_iter->totpoints - 1; i2++) {
- float p2d_b1[2], p2d_b2[2];
- copy_v2_v2(p2d_b1, points2d[i2]);
- copy_v2_v2(p2d_b2, points2d[i2 + 1]);
-
- /* don't self check */
- if (gps == gps_iter) {
- if (equals_v2v2(p2d_a1, p2d_b1) || equals_v2v2(p2d_a1, p2d_b2)) {
- continue;
- }
- if (equals_v2v2(p2d_a2, p2d_b1) || equals_v2v2(p2d_a2, p2d_b2)) {
- continue;
- }
- }
- /* check collision */
- int check = isect_seg_seg_v2_point(p2d_a1, p2d_a2, p2d_b1, p2d_b2, r_hit);
- if (check > 0) {
- hit = true;
- break;
- }
- }
-
- if (hit) {
- break;
- }
- }
-
- if (!hit) {
- zero_v2(r_hit);
- }
-
- return hit;
+ bool hit = false;
+ /* check segment with all segments of all strokes */
+ for (int s = 0; s < totstrokes; s++) {
+ bGPDstroke *gps_iter = gps_array[s];
+ if (gps_iter->totpoints < 2) {
+ continue;
+ }
+ /* get stroke 2d version */
+ float(*points2d)[2] = BLI_ghash_lookup(all_2d, gps_iter);
+
+ for (int i2 = 0; i2 < gps_iter->totpoints - 1; i2++) {
+ float p2d_b1[2], p2d_b2[2];
+ copy_v2_v2(p2d_b1, points2d[i2]);
+ copy_v2_v2(p2d_b2, points2d[i2 + 1]);
+
+ /* don't self check */
+ if (gps == gps_iter) {
+ if (equals_v2v2(p2d_a1, p2d_b1) || equals_v2v2(p2d_a1, p2d_b2)) {
+ continue;
+ }
+ if (equals_v2v2(p2d_a2, p2d_b1) || equals_v2v2(p2d_a2, p2d_b2)) {
+ continue;
+ }
+ }
+ /* check collision */
+ int check = isect_seg_seg_v2_point(p2d_a1, p2d_a2, p2d_b1, p2d_b2, r_hit);
+ if (check > 0) {
+ hit = true;
+ break;
+ }
+ }
+
+ if (hit) {
+ break;
+ }
+ }
+
+ if (!hit) {
+ zero_v2(r_hit);
+ }
+
+ return hit;
}
-static void gp_copy_points(
- bGPDstroke *gps, bGPDspoint *pt, bGPDspoint *pt_final, int i, int i2)
+static void gp_copy_points(bGPDstroke *gps, bGPDspoint *pt, bGPDspoint *pt_final, int i, int i2)
{
- /* don't copy same point */
- if (i == i2) {
- return;
- }
-
- copy_v3_v3(&pt_final->x, &pt->x);
- pt_final->pressure = pt->pressure;
- pt_final->strength = pt->strength;
- pt_final->time = pt->time;
- pt_final->flag = pt->flag;
- pt_final->uv_fac = pt->uv_fac;
- pt_final->uv_rot = pt->uv_rot;
-
- if (gps->dvert != NULL) {
- MDeformVert *dvert = &gps->dvert[i];
- MDeformVert *dvert_final = &gps->dvert[i2];
- MEM_SAFE_FREE(dvert_final->dw);
-
- dvert_final->totweight = dvert->totweight;
- if (dvert->dw == NULL) {
- dvert_final->dw = NULL;
- dvert_final->totweight = 0;
- }
- else {
- dvert_final->dw = MEM_dupallocN(dvert->dw);
- }
- }
-
+ /* don't copy same point */
+ if (i == i2) {
+ return;
+ }
+
+ copy_v3_v3(&pt_final->x, &pt->x);
+ pt_final->pressure = pt->pressure;
+ pt_final->strength = pt->strength;
+ pt_final->time = pt->time;
+ pt_final->flag = pt->flag;
+ pt_final->uv_fac = pt->uv_fac;
+ pt_final->uv_rot = pt->uv_rot;
+
+ if (gps->dvert != NULL) {
+ MDeformVert *dvert = &gps->dvert[i];
+ MDeformVert *dvert_final = &gps->dvert[i2];
+ MEM_SAFE_FREE(dvert_final->dw);
+
+ dvert_final->totweight = dvert->totweight;
+ if (dvert->dw == NULL) {
+ dvert_final->dw = NULL;
+ dvert_final->totweight = 0;
+ }
+ else {
+ dvert_final->dw = MEM_dupallocN(dvert->dw);
+ }
+ }
}
static void gp_insert_point(
- bGPDstroke *gps,
- bGPDspoint *a_pt, bGPDspoint *b_pt,
- float co_a[3], float co_b[3])
+ bGPDstroke *gps, bGPDspoint *a_pt, bGPDspoint *b_pt, float co_a[3], float co_b[3])
{
- bGPDspoint *temp_points;
- int totnewpoints, oldtotpoints;
-
- totnewpoints = gps->totpoints;
- if (a_pt) {
- totnewpoints++;
- }
- if (b_pt) {
- totnewpoints++;
- }
-
- /* duplicate points in a temp area */
- temp_points = MEM_dupallocN(gps->points);
- oldtotpoints = gps->totpoints;
-
- /* look index of base points because memory is changed when resize points array */
- int a_idx = -1;
- int b_idx = -1;
- for (int i = 0; i < oldtotpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
- if (pt == a_pt) {
- a_idx = i;
- }
- if (pt == b_pt) {
- b_idx = i;
- }
- }
-
- /* resize the points arrays */
- gps->totpoints = totnewpoints;
- gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
- if (gps->dvert != NULL) {
- gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
- }
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
-
- /* copy all points */
- int i2 = 0;
- for (int i = 0; i < oldtotpoints; i++) {
- bGPDspoint *pt = &temp_points[i];
- bGPDspoint *pt_final = &gps->points[i2];
- gp_copy_points(gps, pt, pt_final, i, i2);
-
- /* create new point duplicating point and copy location */
- if ((i == a_idx) || (i == b_idx)) {
- i2++;
- pt_final = &gps->points[i2];
- gp_copy_points(gps, pt, pt_final, i, i2);
- copy_v3_v3(&pt_final->x, (i == a_idx) ? co_a : co_b);
-
- /* unselect */
- pt_final->flag &= ~GP_SPOINT_SELECT;
- /* tag to avoid more checking with this point */
- pt_final->flag |= GP_SPOINT_TAG;
- }
-
- i2++;
- }
-
- MEM_SAFE_FREE(temp_points);
+ bGPDspoint *temp_points;
+ int totnewpoints, oldtotpoints;
+
+ totnewpoints = gps->totpoints;
+ if (a_pt) {
+ totnewpoints++;
+ }
+ if (b_pt) {
+ totnewpoints++;
+ }
+
+ /* duplicate points in a temp area */
+ temp_points = MEM_dupallocN(gps->points);
+ oldtotpoints = gps->totpoints;
+
+ /* look index of base points because memory is changed when resize points array */
+ int a_idx = -1;
+ int b_idx = -1;
+ for (int i = 0; i < oldtotpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ if (pt == a_pt) {
+ a_idx = i;
+ }
+ if (pt == b_pt) {
+ b_idx = i;
+ }
+ }
+
+ /* resize the points arrays */
+ gps->totpoints = totnewpoints;
+ gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
+ if (gps->dvert != NULL) {
+ gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
+ }
+ gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+
+ /* copy all points */
+ int i2 = 0;
+ for (int i = 0; i < oldtotpoints; i++) {
+ bGPDspoint *pt = &temp_points[i];
+ bGPDspoint *pt_final = &gps->points[i2];
+ gp_copy_points(gps, pt, pt_final, i, i2);
+
+ /* create new point duplicating point and copy location */
+ if ((i == a_idx) || (i == b_idx)) {
+ i2++;
+ pt_final = &gps->points[i2];
+ gp_copy_points(gps, pt, pt_final, i, i2);
+ copy_v3_v3(&pt_final->x, (i == a_idx) ? co_a : co_b);
+
+ /* unselect */
+ pt_final->flag &= ~GP_SPOINT_SELECT;
+ /* tag to avoid more checking with this point */
+ pt_final->flag |= GP_SPOINT_TAG;
+ }
+
+ i2++;
+ }
+
+ MEM_SAFE_FREE(temp_points);
}
static float gp_calc_factor(float p2d_a1[2], float p2d_a2[2], float r_hit2d[2])
{
- float dist1 = len_squared_v2v2(p2d_a1, p2d_a2);
- float dist2 = len_squared_v2v2(p2d_a1, r_hit2d);
- float f = dist1 > 0.0f ? dist2 / dist1 : 0.0f;
-
- /* apply a correction factor */
- float v1[2];
- interp_v2_v2v2(v1, p2d_a1, p2d_a2, f);
- float dist3 = len_squared_v2v2(p2d_a1, v1);
- float f1 = dist1 > 0.0f ? dist3 / dist1 : 0.0f;
- f = f + (f - f1);
-
- return f;
+ float dist1 = len_squared_v2v2(p2d_a1, p2d_a2);
+ float dist2 = len_squared_v2v2(p2d_a1, r_hit2d);
+ float f = dist1 > 0.0f ? dist2 / dist1 : 0.0f;
+
+ /* apply a correction factor */
+ float v1[2];
+ interp_v2_v2v2(v1, p2d_a1, p2d_a2, f);
+ float dist3 = len_squared_v2v2(p2d_a1, v1);
+ float f1 = dist1 > 0.0f ? dist3 / dist1 : 0.0f;
+ f = f + (f - f1);
+
+ return f;
}
/* extend selection to stroke intersections */
-int ED_gpencil_select_stroke_segment(
- bGPDlayer *gpl, bGPDstroke *gps, bGPDspoint *pt,
- bool select, bool insert, const float scale,
- float r_hita[3], float r_hitb[3])
+int ED_gpencil_select_stroke_segment(bGPDlayer *gpl,
+ bGPDstroke *gps,
+ bGPDspoint *pt,
+ bool select,
+ bool insert,
+ const float scale,
+ float r_hita[3],
+ float r_hitb[3])
{
- const float min_factor = 0.0015f;
- bGPDspoint *pta1 = NULL;
- bGPDspoint *pta2 = NULL;
- float f = 0.0f;
- int i2 = 0;
-
- bGPDframe *gpf = gpl->actframe;
- if (gpf == NULL) {
- return 0;
- }
-
- int memsize = BLI_listbase_count(&gpf->strokes);
- bGPDstroke **gps_array = MEM_callocN(sizeof(bGPDstroke *) * memsize, __func__);
-
- /* save points */
- bGPDspoint *oldpoints = MEM_dupallocN(gps->points);
-
- /* Save list of strokes to check */
- int totstrokes = 0;
- for (bGPDstroke *gps_iter = gpf->strokes.first; gps_iter; gps_iter = gps_iter->next) {
- if (gps_iter->totpoints < 2) {
- continue;
- }
- gps_array[totstrokes] = gps_iter;
- totstrokes++;
- }
-
- if (totstrokes == 0) {
- return 0;
- }
-
- /* look for index of the current point */
- int cur_idx = -1;
- for (int i = 0; i < gps->totpoints; i++) {
- pta1 = &gps->points[i];
- if (pta1 == pt) {
- cur_idx = i;
- break;
- }
- }
- if (cur_idx < 0) {
- return 0;
- }
-
- /* convert all gps points to 2d and save in a hash to avoid recalculation */
- int direction = 0;
- float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points");
- BKE_gpencil_stroke_2d_flat_ref(
- gps->points, gps->totpoints,
- gps->points, gps->totpoints, points2d, scale, &direction);
-
- GHash *all_2d = BLI_ghash_ptr_new(__func__);
-
- for (int s = 0; s < totstrokes; s++) {
- bGPDstroke *gps_iter = gps_array[s];
- float(*points2d_iter)[2] = MEM_mallocN(sizeof(*points2d_iter) * gps_iter->totpoints, __func__);
-
- /* the extremes of the stroke are scaled to improve collision detection
- * for near lines */
- BKE_gpencil_stroke_2d_flat_ref(
- gps->points, gps->totpoints,
- gps_iter->points, gps_iter->totpoints, points2d_iter,
- scale, &direction);
- BLI_ghash_insert(all_2d, gps_iter, points2d_iter);
- }
-
- bool hit_a = false;
- bool hit_b = false;
- float p2d_a1[2] = {0.0f, 0.0f};
- float p2d_a2[2] = {0.0f, 0.0f};
- float r_hit2d[2];
- bGPDspoint *hit_pointa = NULL;
- bGPDspoint *hit_pointb = NULL;
-
- /* analyze points before current */
- if (cur_idx > 0) {
- for (int i = cur_idx; i >= 0; i--) {
- pta1 = &gps->points[i];
- copy_v2_v2(p2d_a1, points2d[i]);
-
- i2 = i - 1;
- CLAMP_MIN(i2, 0);
- pta2 = &gps->points[i2];
- copy_v2_v2(p2d_a2, points2d[i2]);
-
- hit_a = gpencil_check_collision(
- gps, gps_array, all_2d, totstrokes, p2d_a1, p2d_a2, r_hit2d);
-
- if (select) {
- pta1->flag |= GP_SPOINT_SELECT;
- }
- else {
- pta1->flag &= ~GP_SPOINT_SELECT;
- }
-
- if (hit_a) {
- f = gp_calc_factor(p2d_a1, p2d_a2, r_hit2d);
- interp_v3_v3v3(r_hita, &pta1->x, &pta2->x, f);
- if (f > min_factor) {
- hit_pointa = pta2; /* first point is second (inverted loop) */
- }
- else {
- pta1->flag &= ~GP_SPOINT_SELECT;
- }
- break;
- }
- }
- }
-
- /* analyze points after current */
- for (int i = cur_idx; i < gps->totpoints; i++) {
- pta1 = &gps->points[i];
- copy_v2_v2(p2d_a1, points2d[i]);
-
- i2 = i + 1;
- CLAMP_MAX(i2, gps->totpoints - 1);
- pta2 = &gps->points[i2];
- copy_v2_v2(p2d_a2, points2d[i2]);
-
- hit_b = gpencil_check_collision(
- gps, gps_array, all_2d, totstrokes, p2d_a1, p2d_a2, r_hit2d);
-
- if (select) {
- pta1->flag |= GP_SPOINT_SELECT;
- }
- else {
- pta1->flag &= ~GP_SPOINT_SELECT;
- }
-
- if (hit_b) {
- f = gp_calc_factor(p2d_a1, p2d_a2, r_hit2d);
- interp_v3_v3v3(r_hitb, &pta1->x, &pta2->x, f);
- if (f > min_factor) {
- hit_pointb = pta1;
- }
- else {
- pta1->flag &= ~GP_SPOINT_SELECT;
- }
- break;
- }
- }
-
- /* insert new point in the collision points */
- if (insert) {
- gp_insert_point(gps, hit_pointa, hit_pointb, r_hita, r_hitb);
- }
-
- /* free memory */
- if (all_2d) {
- GHashIterator gh_iter;
- GHASH_ITER(gh_iter, all_2d) {
- float(*p2d)[2] = BLI_ghashIterator_getValue(&gh_iter);
- MEM_SAFE_FREE(p2d);
- }
- BLI_ghash_free(all_2d, NULL, NULL);
- }
-
- /* if no hit, reset selection flag */
- if ((!hit_a) && (!hit_b)) {
- for (int i = 0; i < gps->totpoints; i++) {
- pta1 = &gps->points[i];
- pta2 = &oldpoints[i];
- pta1->flag = pta2->flag;
- }
- }
-
- MEM_SAFE_FREE(points2d);
- MEM_SAFE_FREE(gps_array);
- MEM_SAFE_FREE(oldpoints);
-
- /* return type of hit */
- if ((hit_a) && (hit_b)) {
- return 3;
- }
- else if (hit_a) {
- return 1;
- }
- else if (hit_b) {
- return 2;
- }
- else {
- return 0;
- }
+ const float min_factor = 0.0015f;
+ bGPDspoint *pta1 = NULL;
+ bGPDspoint *pta2 = NULL;
+ float f = 0.0f;
+ int i2 = 0;
+
+ bGPDframe *gpf = gpl->actframe;
+ if (gpf == NULL) {
+ return 0;
+ }
+
+ int memsize = BLI_listbase_count(&gpf->strokes);
+ bGPDstroke **gps_array = MEM_callocN(sizeof(bGPDstroke *) * memsize, __func__);
+
+ /* save points */
+ bGPDspoint *oldpoints = MEM_dupallocN(gps->points);
+
+ /* Save list of strokes to check */
+ int totstrokes = 0;
+ for (bGPDstroke *gps_iter = gpf->strokes.first; gps_iter; gps_iter = gps_iter->next) {
+ if (gps_iter->totpoints < 2) {
+ continue;
+ }
+ gps_array[totstrokes] = gps_iter;
+ totstrokes++;
+ }
+
+ if (totstrokes == 0) {
+ return 0;
+ }
+
+ /* look for index of the current point */
+ int cur_idx = -1;
+ for (int i = 0; i < gps->totpoints; i++) {
+ pta1 = &gps->points[i];
+ if (pta1 == pt) {
+ cur_idx = i;
+ break;
+ }
+ }
+ if (cur_idx < 0) {
+ return 0;
+ }
+
+ /* convert all gps points to 2d and save in a hash to avoid recalculation */
+ int direction = 0;
+ float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints,
+ "GP Stroke temp 2d points");
+ BKE_gpencil_stroke_2d_flat_ref(
+ gps->points, gps->totpoints, gps->points, gps->totpoints, points2d, scale, &direction);
+
+ GHash *all_2d = BLI_ghash_ptr_new(__func__);
+
+ for (int s = 0; s < totstrokes; s++) {
+ bGPDstroke *gps_iter = gps_array[s];
+ float(*points2d_iter)[2] = MEM_mallocN(sizeof(*points2d_iter) * gps_iter->totpoints, __func__);
+
+ /* the extremes of the stroke are scaled to improve collision detection
+ * for near lines */
+ BKE_gpencil_stroke_2d_flat_ref(gps->points,
+ gps->totpoints,
+ gps_iter->points,
+ gps_iter->totpoints,
+ points2d_iter,
+ scale,
+ &direction);
+ BLI_ghash_insert(all_2d, gps_iter, points2d_iter);
+ }
+
+ bool hit_a = false;
+ bool hit_b = false;
+ float p2d_a1[2] = {0.0f, 0.0f};
+ float p2d_a2[2] = {0.0f, 0.0f};
+ float r_hit2d[2];
+ bGPDspoint *hit_pointa = NULL;
+ bGPDspoint *hit_pointb = NULL;
+
+ /* analyze points before current */
+ if (cur_idx > 0) {
+ for (int i = cur_idx; i >= 0; i--) {
+ pta1 = &gps->points[i];
+ copy_v2_v2(p2d_a1, points2d[i]);
+
+ i2 = i - 1;
+ CLAMP_MIN(i2, 0);
+ pta2 = &gps->points[i2];
+ copy_v2_v2(p2d_a2, points2d[i2]);
+
+ hit_a = gpencil_check_collision(gps, gps_array, all_2d, totstrokes, p2d_a1, p2d_a2, r_hit2d);
+
+ if (select) {
+ pta1->flag |= GP_SPOINT_SELECT;
+ }
+ else {
+ pta1->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ if (hit_a) {
+ f = gp_calc_factor(p2d_a1, p2d_a2, r_hit2d);
+ interp_v3_v3v3(r_hita, &pta1->x, &pta2->x, f);
+ if (f > min_factor) {
+ hit_pointa = pta2; /* first point is second (inverted loop) */
+ }
+ else {
+ pta1->flag &= ~GP_SPOINT_SELECT;
+ }
+ break;
+ }
+ }
+ }
+
+ /* analyze points after current */
+ for (int i = cur_idx; i < gps->totpoints; i++) {
+ pta1 = &gps->points[i];
+ copy_v2_v2(p2d_a1, points2d[i]);
+
+ i2 = i + 1;
+ CLAMP_MAX(i2, gps->totpoints - 1);
+ pta2 = &gps->points[i2];
+ copy_v2_v2(p2d_a2, points2d[i2]);
+
+ hit_b = gpencil_check_collision(gps, gps_array, all_2d, totstrokes, p2d_a1, p2d_a2, r_hit2d);
+
+ if (select) {
+ pta1->flag |= GP_SPOINT_SELECT;
+ }
+ else {
+ pta1->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ if (hit_b) {
+ f = gp_calc_factor(p2d_a1, p2d_a2, r_hit2d);
+ interp_v3_v3v3(r_hitb, &pta1->x, &pta2->x, f);
+ if (f > min_factor) {
+ hit_pointb = pta1;
+ }
+ else {
+ pta1->flag &= ~GP_SPOINT_SELECT;
+ }
+ break;
+ }
+ }
+
+ /* insert new point in the collision points */
+ if (insert) {
+ gp_insert_point(gps, hit_pointa, hit_pointb, r_hita, r_hitb);
+ }
+
+ /* free memory */
+ if (all_2d) {
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, all_2d) {
+ float(*p2d)[2] = BLI_ghashIterator_getValue(&gh_iter);
+ MEM_SAFE_FREE(p2d);
+ }
+ BLI_ghash_free(all_2d, NULL, NULL);
+ }
+
+ /* if no hit, reset selection flag */
+ if ((!hit_a) && (!hit_b)) {
+ for (int i = 0; i < gps->totpoints; i++) {
+ pta1 = &gps->points[i];
+ pta2 = &oldpoints[i];
+ pta1->flag = pta2->flag;
+ }
+ }
+
+ MEM_SAFE_FREE(points2d);
+ MEM_SAFE_FREE(gps_array);
+ MEM_SAFE_FREE(oldpoints);
+
+ /* return type of hit */
+ if ((hit_a) && (hit_b)) {
+ return 3;
+ }
+ else if (hit_a) {
+ return 1;
+ }
+ else if (hit_b) {
+ return 2;
+ }
+ else {
+ return 0;
+ }
}
void ED_gpencil_select_toggle_all(bContext *C, int action)
{
- /* for "toggle", test for existing selected strokes */
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
-
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- if (gps->flag & GP_STROKE_SELECT) {
- action = SEL_DESELECT;
- break; // XXX: this only gets out of the inner loop...
- }
- }
- CTX_DATA_END;
- }
-
- /* if deselecting, we need to deselect strokes across all frames
- * - Currently, an exception is only given for deselection
- * Selecting and toggling should only affect what's visible,
- * while deselecting helps clean up unintended/forgotten
- * stuff on other frames
- */
- if (action == SEL_DESELECT) {
- /* deselect strokes across editable layers
- * NOTE: we limit ourselves to editable layers, since once a layer is "locked/hidden
- * 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) {
- bGPDstroke *gps;
-
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- bGPDspoint *pt;
- int i;
-
- /* only edit strokes that are valid in this view... */
- if (ED_gpencil_stroke_can_use(C, gps)) {
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- pt->flag &= ~GP_SPOINT_SELECT;
- }
-
- gps->flag &= ~GP_STROKE_SELECT;
- }
- }
- }
- }
- CTX_DATA_END;
- }
- else {
- /* select or deselect all strokes */
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- bGPDspoint *pt;
- int i;
- bool selected = false;
-
- /* Change selection status of all points, then make the stroke match */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- switch (action) {
- case SEL_SELECT:
- pt->flag |= GP_SPOINT_SELECT;
- break;
- //case SEL_DESELECT:
- // pt->flag &= ~GP_SPOINT_SELECT;
- // break;
- case SEL_INVERT:
- pt->flag ^= GP_SPOINT_SELECT;
- break;
- }
-
- if (pt->flag & GP_SPOINT_SELECT)
- selected = true;
- }
-
- /* Change status of stroke */
- if (selected)
- gps->flag |= GP_STROKE_SELECT;
- else
- gps->flag &= ~GP_STROKE_SELECT;
- }
- CTX_DATA_END;
- }
+ /* for "toggle", test for existing selected strokes */
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ action = SEL_DESELECT;
+ break; // XXX: this only gets out of the inner loop...
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ /* if deselecting, we need to deselect strokes across all frames
+ * - Currently, an exception is only given for deselection
+ * Selecting and toggling should only affect what's visible,
+ * while deselecting helps clean up unintended/forgotten
+ * stuff on other frames
+ */
+ if (action == SEL_DESELECT) {
+ /* deselect strokes across editable layers
+ * NOTE: we limit ourselves to editable layers, since once a layer is "locked/hidden
+ * 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) {
+ bGPDstroke *gps;
+
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ bGPDspoint *pt;
+ int i;
+
+ /* only edit strokes that are valid in this view... */
+ if (ED_gpencil_stroke_can_use(C, gps)) {
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+ }
+ else {
+ /* select or deselect all strokes */
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ bGPDspoint *pt;
+ int i;
+ bool selected = false;
+
+ /* Change selection status of all points, then make the stroke match */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ switch (action) {
+ case SEL_SELECT:
+ pt->flag |= GP_SPOINT_SELECT;
+ break;
+ //case SEL_DESELECT:
+ // pt->flag &= ~GP_SPOINT_SELECT;
+ // break;
+ case SEL_INVERT:
+ pt->flag ^= GP_SPOINT_SELECT;
+ break;
+ }
+
+ if (pt->flag & GP_SPOINT_SELECT)
+ selected = true;
+ }
+
+ /* Change status of stroke */
+ if (selected)
+ gps->flag |= GP_STROKE_SELECT;
+ else
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ CTX_DATA_END;
+ }
}
diff --git a/source/blender/editors/include/BIF_gl.h b/source/blender/editors/include/BIF_gl.h
index 4a1cdce2ead..84820c3c564 100644
--- a/source/blender/editors/include/BIF_gl.h
+++ b/source/blender/editors/include/BIF_gl.h
@@ -30,12 +30,14 @@
/* hacking pointsize and linewidth */
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
-# define glPointSize(f) glPointSize(U.pixelsize * _Generic((f), double: (float)(f), default: (f)))
-# define glLineWidth(f) glLineWidth(U.pixelsize * _Generic((f), double: (float)(f), default: (f)))
+# define glPointSize(f) \
+ glPointSize(U.pixelsize *_Generic((f), double : (float)(f), default : (f)))
+# define glLineWidth(f) \
+ glLineWidth(U.pixelsize *_Generic((f), double : (float)(f), default : (f)))
#else
-# define glPointSize(f) glPointSize(U.pixelsize * (f))
-# define glLineWidth(f) glLineWidth(U.pixelsize * (f))
-#endif /* C11 */
+# define glPointSize(f) glPointSize(U.pixelsize *(f))
+# define glLineWidth(f) glLineWidth(U.pixelsize *(f))
+#endif /* C11 */
#define GLA_PIXEL_OFS 0.375f
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
index 9cb308d5145..a2e8d6afd4b 100644
--- a/source/blender/editors/include/BIF_glutil.h
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -62,10 +62,10 @@ int glaGetOneInt(int param);
void glaRasterPosSafe2f(float x, float y, float known_good_x, float known_good_y);
typedef struct IMMDrawPixelsTexState {
- struct GPUShader *shader;
- unsigned int pos;
- unsigned int texco;
- bool do_shader_unbind;
+ struct GPUShader *shader;
+ unsigned int pos;
+ unsigned int texco;
+ bool do_shader_unbind;
} IMMDrawPixelsTexState;
/* To be used before calling immDrawPixelsTex
@@ -88,19 +88,65 @@ IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin);
* 1-to-1 mapping to screen space.
*/
void immDrawPixelsTex(IMMDrawPixelsTexState *state,
- float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect,
- float xzoom, float yzoom, float color[4]);
+ float x,
+ float y,
+ int img_w,
+ int img_h,
+ int format,
+ int type,
+ int zoomfilter,
+ void *rect,
+ float xzoom,
+ float yzoom,
+ float color[4]);
void immDrawPixelsTex_clipping(IMMDrawPixelsTexState *state,
- float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect,
- float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y,
- float xzoom, float yzoom, float color[4]);
+ float x,
+ float y,
+ int img_w,
+ int img_h,
+ int format,
+ int type,
+ int zoomfilter,
+ void *rect,
+ float clip_min_x,
+ float clip_min_y,
+ float clip_max_x,
+ float clip_max_y,
+ float xzoom,
+ float yzoom,
+ float color[4]);
void immDrawPixelsTexScaled(IMMDrawPixelsTexState *state,
- float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY,
- float xzoom, float yzoom, float color[4]);
+ float x,
+ float y,
+ int img_w,
+ int img_h,
+ int format,
+ int type,
+ int zoomfilter,
+ void *rect,
+ float scaleX,
+ float scaleY,
+ float xzoom,
+ float yzoom,
+ float color[4]);
void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state,
- float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY,
- float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y,
- float xzoom, float yzoom, float color[4]);
+ float x,
+ float y,
+ int img_w,
+ int img_h,
+ int format,
+ int type,
+ int zoomfilter,
+ void *rect,
+ float scaleX,
+ float scaleY,
+ float clip_min_x,
+ float clip_min_y,
+ float clip_max_x,
+ float clip_max_y,
+ float xzoom,
+ float yzoom,
+ float color[4]);
void set_inverted_drawing(int enable);
@@ -111,28 +157,46 @@ void bglPolygonOffset(float viewdist, float dist);
/* **** Color management helper functions for GLSL display/transform ***** */
/* Draw imbuf on a screen, preferably using GLSL display transform */
-void glaDrawImBuf_glsl(struct ImBuf *ibuf, float x, float y, int zoomfilter,
+void glaDrawImBuf_glsl(struct ImBuf *ibuf,
+ float x,
+ float y,
+ int zoomfilter,
struct ColorManagedViewSettings *view_settings,
struct ColorManagedDisplaySettings *display_settings,
- float zoom_x, float zoom_y);
-void glaDrawImBuf_glsl_clipping(struct ImBuf *ibuf, float x, float y, int zoomfilter,
+ float zoom_x,
+ float zoom_y);
+void glaDrawImBuf_glsl_clipping(struct ImBuf *ibuf,
+ float x,
+ float y,
+ int zoomfilter,
struct ColorManagedViewSettings *view_settings,
struct ColorManagedDisplaySettings *display_settings,
- float clip_min_x, float clip_min_y,
- float clip_max_x, float clip_max_y,
- float zoom_x, float zoom_y);
-
+ float clip_min_x,
+ float clip_min_y,
+ float clip_max_x,
+ float clip_max_y,
+ float zoom_x,
+ float zoom_y);
/* Draw imbuf on a screen, preferably using GLSL display transform */
-void glaDrawImBuf_glsl_ctx(const struct bContext *C, struct ImBuf *ibuf, float x, float y, int zoomfilter,
- float zoom_x, float zoom_y);
+void glaDrawImBuf_glsl_ctx(const struct bContext *C,
+ struct ImBuf *ibuf,
+ float x,
+ float y,
+ int zoomfilter,
+ float zoom_x,
+ float zoom_y);
void glaDrawImBuf_glsl_ctx_clipping(const struct bContext *C,
struct ImBuf *ibuf,
- float x, float y,
+ float x,
+ float y,
int zoomfilter,
- float clip_min_x, float clip_min_y,
- float clip_max_x, float clip_max_y,
- float zoom_x, float zoom_y);
+ float clip_min_x,
+ float clip_min_y,
+ float clip_max_x,
+ float clip_max_y,
+ float zoom_x,
+ float zoom_y);
void immDrawBorderCorners(unsigned int pos, const struct rcti *border, float zoomx, float zoomy);
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index dc5ffb4794d..3a9539ee52c 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -62,61 +62,61 @@ struct PropertyRNA;
* 'context' information
*/
typedef struct bAnimContext {
- /** data to be filtered for use in animation editor */
- void *data;
- /** type of data eAnimCont_Types */
- short datatype;
-
- /** editor->mode */
- short mode;
- /** sa->spacetype */
- short spacetype;
- /** active region -> type (channels or main) */
- short regiontype;
-
- /** editor host */
- struct ScrArea *sa;
- /** editor data */
- struct SpaceLink *sl;
- /** region within editor */
- struct ARegion *ar;
-
- /** dopesheet data for editor (or which is being used) */
- struct bDopeSheet *ads;
-
- /** active dependency graph */
- struct Depsgraph *depsgraph;
- /** Current Main */
- struct Main *bmain;
- /** active scene */
- struct Scene *scene;
- /** active scene layer */
- struct ViewLayer *view_layer;
- /** active object */
- struct Object *obact;
- /** active set of markers */
- ListBase *markers;
-
- /** pointer to current reports list */
- struct ReportList *reports;
-
- /** Scale factor for height of channels (i.e. based on the size of keyframes). */
- float yscale_fac;
+ /** data to be filtered for use in animation editor */
+ void *data;
+ /** type of data eAnimCont_Types */
+ short datatype;
+
+ /** editor->mode */
+ short mode;
+ /** sa->spacetype */
+ short spacetype;
+ /** active region -> type (channels or main) */
+ short regiontype;
+
+ /** editor host */
+ struct ScrArea *sa;
+ /** editor data */
+ struct SpaceLink *sl;
+ /** region within editor */
+ struct ARegion *ar;
+
+ /** dopesheet data for editor (or which is being used) */
+ struct bDopeSheet *ads;
+
+ /** active dependency graph */
+ struct Depsgraph *depsgraph;
+ /** Current Main */
+ struct Main *bmain;
+ /** active scene */
+ struct Scene *scene;
+ /** active scene layer */
+ struct ViewLayer *view_layer;
+ /** active object */
+ struct Object *obact;
+ /** active set of markers */
+ ListBase *markers;
+
+ /** pointer to current reports list */
+ struct ReportList *reports;
+
+ /** Scale factor for height of channels (i.e. based on the size of keyframes). */
+ float yscale_fac;
} bAnimContext;
/* Main Data container types */
typedef enum eAnimCont_Types {
- ANIMCONT_NONE = 0, /* invalid or no data */
- ANIMCONT_ACTION = 1, /* action (bAction) */
- ANIMCONT_SHAPEKEY = 2, /* shapekey (Key) */
- ANIMCONT_GPENCIL = 3, /* grease pencil (screen) */
- ANIMCONT_DOPESHEET = 4, /* dopesheet (bDopesheet) */
- ANIMCONT_FCURVES = 5, /* animation F-Curves (bDopesheet) */
- ANIMCONT_DRIVERS = 6, /* drivers (bDopesheet) */
- ANIMCONT_NLA = 7, /* nla (bDopesheet) */
- ANIMCONT_CHANNEL = 8, /* animation channel (bAnimListElem) */
- ANIMCONT_MASK = 9, /* mask dopesheet */
- ANIMCONT_TIMELINE = 10, /* "timeline" editor (bDopeSheet) */
+ ANIMCONT_NONE = 0, /* invalid or no data */
+ ANIMCONT_ACTION = 1, /* action (bAction) */
+ ANIMCONT_SHAPEKEY = 2, /* shapekey (Key) */
+ ANIMCONT_GPENCIL = 3, /* grease pencil (screen) */
+ ANIMCONT_DOPESHEET = 4, /* dopesheet (bDopesheet) */
+ ANIMCONT_FCURVES = 5, /* animation F-Curves (bDopesheet) */
+ ANIMCONT_DRIVERS = 6, /* drivers (bDopesheet) */
+ ANIMCONT_NLA = 7, /* nla (bDopesheet) */
+ ANIMCONT_CHANNEL = 8, /* animation channel (bAnimListElem) */
+ ANIMCONT_MASK = 9, /* mask dopesheet */
+ ANIMCONT_TIMELINE = 10, /* "timeline" editor (bDopeSheet) */
} eAnimCont_Types;
/* --------------- Channels -------------------- */
@@ -125,64 +125,62 @@ typedef enum eAnimCont_Types {
* channels of animation data
*/
typedef struct bAnimListElem {
- struct bAnimListElem *next, *prev;
-
- /** source data this elem represents */
- void *data;
- /** (eAnim_ChannelType) one of the ANIMTYPE_* values */
- int type;
- /** copy of elem's flags for quick access */
- int flag;
- /** for un-named data, the index of the data in its collection */
- int index;
-
- /** (eAnim_Update_Flags) tag the element for updating */
- char update;
- /** tag the included data. Temporary always */
- char tag;
-
- /** (eAnim_KeyType) type of motion data to expect */
- short datatype;
- /** motion data - mostly F-Curves, but can be other types too */
- void *key_data;
-
-
- /**
- * \note
- * id here is the "IdAdtTemplate"-style datablock (e.g. Object, Material, Texture, NodeTree)
- * from which evaluation of the RNA-paths takes place. It's used to figure out how deep
- * channels should be nested (e.g. for Textures/NodeTrees) in the tree, and allows property
- * lookups (e.g. for sliders and for inserting keyframes) to work. If we had instead used
- * bAction or something similar, none of this would be possible: although it's trivial
- * to use an IdAdtTemplate type to find the source action a channel (e.g. F-Curve) comes from
- * (i.e. in the AnimEditors, it *must* be the active action, as only that can be edited),
- * it's impossible to go the other way (i.e. one action may be used in multiple places).
- */
- /** ID block that channel is attached to */
- struct ID *id;
- /** source of the animation data attached to ID block (for convenience) */
- struct AnimData *adt;
-
- /**
- * For list element which corresponds to a f-curve, this is an ID which
- * owns the f-curve.
- *
- * For example, if the f-curve is coming from Action, this id will be set to
- * action's ID. But if this is a f-curve which is a driver, then the owner
- * is set to, for example, object.
- *
- * Note, that this is different from id above. The id above will be set to
- * an object if the f-curve is coming from action associated with that
- * object. */
- struct ID *fcurve_owner_id;
-
- /**
- * for per-element F-Curves
- * (e.g. NLA Control Curves), the element that this represents (e.g. NlaStrip) */
- void *owner;
+ struct bAnimListElem *next, *prev;
+
+ /** source data this elem represents */
+ void *data;
+ /** (eAnim_ChannelType) one of the ANIMTYPE_* values */
+ int type;
+ /** copy of elem's flags for quick access */
+ int flag;
+ /** for un-named data, the index of the data in its collection */
+ int index;
+
+ /** (eAnim_Update_Flags) tag the element for updating */
+ char update;
+ /** tag the included data. Temporary always */
+ char tag;
+
+ /** (eAnim_KeyType) type of motion data to expect */
+ short datatype;
+ /** motion data - mostly F-Curves, but can be other types too */
+ void *key_data;
+
+ /**
+ * \note
+ * id here is the "IdAdtTemplate"-style datablock (e.g. Object, Material, Texture, NodeTree)
+ * from which evaluation of the RNA-paths takes place. It's used to figure out how deep
+ * channels should be nested (e.g. for Textures/NodeTrees) in the tree, and allows property
+ * lookups (e.g. for sliders and for inserting keyframes) to work. If we had instead used
+ * bAction or something similar, none of this would be possible: although it's trivial
+ * to use an IdAdtTemplate type to find the source action a channel (e.g. F-Curve) comes from
+ * (i.e. in the AnimEditors, it *must* be the active action, as only that can be edited),
+ * it's impossible to go the other way (i.e. one action may be used in multiple places).
+ */
+ /** ID block that channel is attached to */
+ struct ID *id;
+ /** source of the animation data attached to ID block (for convenience) */
+ struct AnimData *adt;
+
+ /**
+ * For list element which corresponds to a f-curve, this is an ID which
+ * owns the f-curve.
+ *
+ * For example, if the f-curve is coming from Action, this id will be set to
+ * action's ID. But if this is a f-curve which is a driver, then the owner
+ * is set to, for example, object.
+ *
+ * Note, that this is different from id above. The id above will be set to
+ * an object if the f-curve is coming from action associated with that
+ * object. */
+ struct ID *fcurve_owner_id;
+
+ /**
+ * for per-element F-Curves
+ * (e.g. NLA Control Curves), the element that this represents (e.g. NlaStrip) */
+ void *owner;
} bAnimListElem;
-
/**
* Some types for easier type-testing
*
@@ -190,72 +188,72 @@ typedef struct bAnimListElem {
* which is used for drawing and handling channel lists for.
*/
typedef enum eAnim_ChannelType {
- ANIMTYPE_NONE = 0,
- ANIMTYPE_ANIMDATA,
- ANIMTYPE_SPECIALDATA,
-
- ANIMTYPE_SUMMARY,
-
- ANIMTYPE_SCENE,
- ANIMTYPE_OBJECT,
- ANIMTYPE_GROUP,
- ANIMTYPE_FCURVE,
-
- ANIMTYPE_NLACONTROLS,
- ANIMTYPE_NLACURVE,
-
- ANIMTYPE_FILLACTD,
- ANIMTYPE_FILLDRIVERS,
-
- ANIMTYPE_DSMAT,
- ANIMTYPE_DSLAM,
- ANIMTYPE_DSCAM,
- ANIMTYPE_DSCACHEFILE,
- ANIMTYPE_DSCUR,
- ANIMTYPE_DSSKEY,
- ANIMTYPE_DSWOR,
- ANIMTYPE_DSNTREE,
- ANIMTYPE_DSPART,
- ANIMTYPE_DSMBALL,
- ANIMTYPE_DSARM,
- ANIMTYPE_DSMESH,
- ANIMTYPE_DSTEX,
- ANIMTYPE_DSLAT,
- ANIMTYPE_DSLINESTYLE,
- ANIMTYPE_DSSPK,
- ANIMTYPE_DSGPENCIL,
- ANIMTYPE_DSMCLIP,
-
- ANIMTYPE_SHAPEKEY,
-
- ANIMTYPE_GPDATABLOCK,
- ANIMTYPE_GPLAYER,
-
- ANIMTYPE_MASKDATABLOCK,
- ANIMTYPE_MASKLAYER,
-
- ANIMTYPE_NLATRACK,
- ANIMTYPE_NLAACTION,
-
- ANIMTYPE_PALETTE,
-
- /* always as last item, the total number of channel types... */
- ANIMTYPE_NUM_TYPES,
+ ANIMTYPE_NONE = 0,
+ ANIMTYPE_ANIMDATA,
+ ANIMTYPE_SPECIALDATA,
+
+ ANIMTYPE_SUMMARY,
+
+ ANIMTYPE_SCENE,
+ ANIMTYPE_OBJECT,
+ ANIMTYPE_GROUP,
+ ANIMTYPE_FCURVE,
+
+ ANIMTYPE_NLACONTROLS,
+ ANIMTYPE_NLACURVE,
+
+ ANIMTYPE_FILLACTD,
+ ANIMTYPE_FILLDRIVERS,
+
+ ANIMTYPE_DSMAT,
+ ANIMTYPE_DSLAM,
+ ANIMTYPE_DSCAM,
+ ANIMTYPE_DSCACHEFILE,
+ ANIMTYPE_DSCUR,
+ ANIMTYPE_DSSKEY,
+ ANIMTYPE_DSWOR,
+ ANIMTYPE_DSNTREE,
+ ANIMTYPE_DSPART,
+ ANIMTYPE_DSMBALL,
+ ANIMTYPE_DSARM,
+ ANIMTYPE_DSMESH,
+ ANIMTYPE_DSTEX,
+ ANIMTYPE_DSLAT,
+ ANIMTYPE_DSLINESTYLE,
+ ANIMTYPE_DSSPK,
+ ANIMTYPE_DSGPENCIL,
+ ANIMTYPE_DSMCLIP,
+
+ ANIMTYPE_SHAPEKEY,
+
+ ANIMTYPE_GPDATABLOCK,
+ ANIMTYPE_GPLAYER,
+
+ ANIMTYPE_MASKDATABLOCK,
+ ANIMTYPE_MASKLAYER,
+
+ ANIMTYPE_NLATRACK,
+ ANIMTYPE_NLAACTION,
+
+ ANIMTYPE_PALETTE,
+
+ /* always as last item, the total number of channel types... */
+ ANIMTYPE_NUM_TYPES,
} eAnim_ChannelType;
/* types of keyframe data in bAnimListElem */
typedef enum eAnim_KeyType {
- ALE_NONE = 0, /* no keyframe data */
- ALE_FCURVE, /* F-Curve */
- ALE_GPFRAME, /* Grease Pencil Frames */
- ALE_MASKLAY, /* Mask */
- ALE_NLASTRIP, /* NLA Strips */
-
- ALE_ALL, /* All channels summary */
- ALE_SCE, /* Scene summary */
- ALE_OB, /* Object summary */
- ALE_ACT, /* Action summary */
- ALE_GROUP, /* Action Group summary */
+ ALE_NONE = 0, /* no keyframe data */
+ ALE_FCURVE, /* F-Curve */
+ ALE_GPFRAME, /* Grease Pencil Frames */
+ ALE_MASKLAY, /* Mask */
+ ALE_NLASTRIP, /* NLA Strips */
+
+ ALE_ALL, /* All channels summary */
+ ALE_SCE, /* Scene summary */
+ ALE_OB, /* Object summary */
+ ALE_ACT, /* Action summary */
+ ALE_GROUP, /* Action Group summary */
} eAnim_KeyType;
/* Flags for specifying the types of updates (i.e. recalculation/refreshing) that
@@ -263,9 +261,9 @@ typedef enum eAnim_KeyType {
* For use with ANIM_animdata_update()
*/
typedef enum eAnim_Update_Flags {
- ANIM_UPDATE_DEPS = (1 << 0), /* referenced data and dependencies get refreshed */
- ANIM_UPDATE_ORDER = (1 << 1), /* keyframes need to be sorted */
- ANIM_UPDATE_HANDLES = (1 << 2), /* recalculate handles */
+ ANIM_UPDATE_DEPS = (1 << 0), /* referenced data and dependencies get refreshed */
+ ANIM_UPDATE_ORDER = (1 << 1), /* keyframes need to be sorted */
+ ANIM_UPDATE_HANDLES = (1 << 2), /* recalculate handles */
} eAnim_Update_Flags;
/* used for most tools which change keyframes (flushed by ANIM_animdata_update) */
@@ -276,47 +274,47 @@ typedef enum eAnim_Update_Flags {
/* filtering flags - under what circumstances should a channel be returned */
typedef enum eAnimFilter_Flags {
- /** data which channel represents is fits the dopesheet filters
- * (i.e. scene visibility criteria) */
- // XXX: it's hard to think of any examples where this *ISN'T* the case... perhaps becomes implicit?
- ANIMFILTER_DATA_VISIBLE = (1 << 0),
- /** channel is visible within the channel-list hierarchy
- * (i.e. F-Curves within Groups in ActEdit) */
- ANIMFILTER_LIST_VISIBLE = (1 << 1),
- /** channel has specifically been tagged as visible in Graph Editor (* Graph Editor Only) */
- ANIMFILTER_CURVE_VISIBLE = (1 << 2),
-
- /** include summary channels and "expanders" (for drawing/mouse-selection in channel list) */
- ANIMFILTER_LIST_CHANNELS = (1 << 3),
-
- /** for its type, channel should be "active" one */
- ANIMFILTER_ACTIVE = (1 << 4),
- /** channel is a child of the active group (* Actions speciality) */
- ANIMFILTER_ACTGROUPED = (1 << 5),
-
- /** channel must be selected/not-selected, but both must not be set together */
- ANIMFILTER_SEL = (1 << 6),
- ANIMFILTER_UNSEL = (1 << 7),
-
- /** editability status - must be editable to be included */
- ANIMFILTER_FOREDIT = (1 << 8),
- /** only selected animchannels should be considerable as editable - mainly
- * for Graph Editor's option for keys on select curves only */
- ANIMFILTER_SELEDIT = (1 << 9),
-
- /** flags used to enforce certain data types
- * \node the ones for curves and NLA tracks were redundant and have been removed for now...
- */
- ANIMFILTER_ANIMDATA = (1 << 10),
-
- /** duplicate entries for animation data attached to multi-user blocks must not occur */
- ANIMFILTER_NODUPLIS = (1 << 11),
-
- /** for checking if we should keep some collapsed channel around (internal use only!) */
- ANIMFILTER_TMP_PEEK = (1 << 30),
-
- /** ignore ONLYSEL flag from filterflag, (internal use only!) */
- ANIMFILTER_TMP_IGNORE_ONLYSEL = (1u << 31),
+ /** data which channel represents is fits the dopesheet filters
+ * (i.e. scene visibility criteria) */
+ // XXX: it's hard to think of any examples where this *ISN'T* the case... perhaps becomes implicit?
+ ANIMFILTER_DATA_VISIBLE = (1 << 0),
+ /** channel is visible within the channel-list hierarchy
+ * (i.e. F-Curves within Groups in ActEdit) */
+ ANIMFILTER_LIST_VISIBLE = (1 << 1),
+ /** channel has specifically been tagged as visible in Graph Editor (* Graph Editor Only) */
+ ANIMFILTER_CURVE_VISIBLE = (1 << 2),
+
+ /** include summary channels and "expanders" (for drawing/mouse-selection in channel list) */
+ ANIMFILTER_LIST_CHANNELS = (1 << 3),
+
+ /** for its type, channel should be "active" one */
+ ANIMFILTER_ACTIVE = (1 << 4),
+ /** channel is a child of the active group (* Actions speciality) */
+ ANIMFILTER_ACTGROUPED = (1 << 5),
+
+ /** channel must be selected/not-selected, but both must not be set together */
+ ANIMFILTER_SEL = (1 << 6),
+ ANIMFILTER_UNSEL = (1 << 7),
+
+ /** editability status - must be editable to be included */
+ ANIMFILTER_FOREDIT = (1 << 8),
+ /** only selected animchannels should be considerable as editable - mainly
+ * for Graph Editor's option for keys on select curves only */
+ ANIMFILTER_SELEDIT = (1 << 9),
+
+ /** flags used to enforce certain data types
+ * \node the ones for curves and NLA tracks were redundant and have been removed for now...
+ */
+ ANIMFILTER_ANIMDATA = (1 << 10),
+
+ /** duplicate entries for animation data attached to multi-user blocks must not occur */
+ ANIMFILTER_NODUPLIS = (1 << 11),
+
+ /** for checking if we should keep some collapsed channel around (internal use only!) */
+ ANIMFILTER_TMP_PEEK = (1 << 30),
+
+ /** ignore ONLYSEL flag from filterflag, (internal use only!) */
+ ANIMFILTER_TMP_IGNORE_ONLYSEL = (1u << 31),
} eAnimFilter_Flags;
/* ---------- Flag Checking Macros ------------ */
@@ -330,24 +328,28 @@ typedef enum eAnimFilter_Flags {
#define FILTER_WOR_SCED(wo) (CHECK_TYPE_INLINE(wo, World *), (wo->flag & WO_DS_EXPAND))
#define FILTER_LS_SCED(linestyle) ((linestyle->flag & LS_DS_EXPAND))
/* '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))
+#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))
/* '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)))
-#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)))
-#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_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)))
+#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)))
+#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_SPK_OBJD(spk) (CHECK_TYPE_INLINE(spk, Speaker *), ((spk->flag & SPK_DS_EXPAND)))
/* Variable use expanders */
-#define FILTER_NTREE_DATA(ntree) (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)))
+#define FILTER_NTREE_DATA(ntree) \
+ (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) */
#define SEL_ACTC(actc) ((actc->flag & ACT_SELECTED))
@@ -355,13 +357,12 @@ typedef enum eAnimFilter_Flags {
/* 'Sub-AnimData' channels */
#define EXPANDED_DRVD(adt) ((adt->flag & ADT_DRIVERS_COLLAPSED) == 0)
-
/* Actions (also used for Dopesheet) */
/* Action Channel Group */
#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)) )
+ (((!(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)
@@ -385,7 +386,6 @@ typedef enum eAnimFilter_Flags {
#define EDITABLE_MASK(masklay) ((masklay->flag & MASK_LAYERFLAG_LOCKED) == 0)
#define SEL_MASKLAY(masklay) (masklay->flag & SELECT)
-
/* NLA only */
#define SEL_NLT(nlt) (nlt->flag & NLATRACK_SELECTED)
#define EDITABLE_NLT(nlt) ((nlt->flag & NLATRACK_PROTECTED) == 0)
@@ -402,40 +402,45 @@ typedef enum eAnimFilter_Flags {
/* -------------- Channel Defines -------------- */
/* channel heights */
-#define ACHANNEL_FIRST(ac) (-0.8f * (ac)->yscale_fac * U.widget_unit)
-#define ACHANNEL_HEIGHT(ac) (0.8f * (ac)->yscale_fac * U.widget_unit)
-#define ACHANNEL_HEIGHT_HALF(ac) (0.4f * (ac)->yscale_fac * U.widget_unit)
-#define ACHANNEL_SKIP (0.1f * U.widget_unit)
-#define ACHANNEL_STEP(ac) (ACHANNEL_HEIGHT(ac) + ACHANNEL_SKIP)
+#define ACHANNEL_FIRST(ac) (-0.8f * (ac)->yscale_fac * U.widget_unit)
+#define ACHANNEL_HEIGHT(ac) (0.8f * (ac)->yscale_fac * U.widget_unit)
+#define ACHANNEL_HEIGHT_HALF(ac) (0.4f * (ac)->yscale_fac * U.widget_unit)
+#define ACHANNEL_SKIP (0.1f * U.widget_unit)
+#define ACHANNEL_STEP(ac) (ACHANNEL_HEIGHT(ac) + ACHANNEL_SKIP)
/* channel widths */
-#define ACHANNEL_NAMEWIDTH (10 * U.widget_unit)
+#define ACHANNEL_NAMEWIDTH (10 * U.widget_unit)
/* channel toggle-buttons */
-#define ACHANNEL_BUTTON_WIDTH (0.8f * U.widget_unit)
-
+#define ACHANNEL_BUTTON_WIDTH (0.8f * U.widget_unit)
/* -------------- NLA Channel Defines -------------- */
/* NLA channel heights */
-#define NLACHANNEL_FIRST (-0.8f * U.widget_unit)
-#define NLACHANNEL_HEIGHT(snla) ((snla && (snla->flag & SNLA_NOSTRIPCURVES)) ? (0.8f * U.widget_unit) : (1.2f * U.widget_unit))
-#define NLACHANNEL_HEIGHT_HALF(snla) ((snla && (snla->flag & SNLA_NOSTRIPCURVES)) ? (0.4f * U.widget_unit) : (0.6f * U.widget_unit))
-#define NLACHANNEL_SKIP (0.1f * U.widget_unit)
-#define NLACHANNEL_STEP(snla) (NLACHANNEL_HEIGHT(snla) + NLACHANNEL_SKIP)
+#define NLACHANNEL_FIRST (-0.8f * U.widget_unit)
+#define NLACHANNEL_HEIGHT(snla) \
+ ((snla && (snla->flag & SNLA_NOSTRIPCURVES)) ? (0.8f * U.widget_unit) : (1.2f * U.widget_unit))
+#define NLACHANNEL_HEIGHT_HALF(snla) \
+ ((snla && (snla->flag & SNLA_NOSTRIPCURVES)) ? (0.4f * U.widget_unit) : (0.6f * U.widget_unit))
+#define NLACHANNEL_SKIP (0.1f * U.widget_unit)
+#define NLACHANNEL_STEP(snla) (NLACHANNEL_HEIGHT(snla) + NLACHANNEL_SKIP)
/* channel widths */
-#define NLACHANNEL_NAMEWIDTH (10 * U.widget_unit)
+#define NLACHANNEL_NAMEWIDTH (10 * U.widget_unit)
/* channel toggle-buttons */
-#define NLACHANNEL_BUTTON_WIDTH (0.8f * U.widget_unit)
+#define NLACHANNEL_BUTTON_WIDTH (0.8f * U.widget_unit)
/* ---------------- API -------------------- */
/* Obtain list of filtered Animation channels to operate on.
* Returns the number of channels in the list
*/
-size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_Flags filter_mode, void *data, eAnimCont_Types datatype);
+size_t ANIM_animdata_filter(bAnimContext *ac,
+ ListBase *anim_data,
+ eAnimFilter_Flags filter_mode,
+ void *data,
+ eAnimCont_Types datatype);
/* Obtain current anim-data context from Blender Context info.
* Returns whether the operation was successful.
@@ -461,80 +466,79 @@ void ANIM_animdata_freelist(ListBase *anim_data);
/* role or level of animchannel in the hierarchy */
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,
- /** data channel - a channel representing one of the actual building blocks of channels */
- ACHANNEL_ROLE_CHANNEL = 1,
+ /** datablock expander - a "composite" channel type */
+ ACHANNEL_ROLE_EXPANDER = -1,
+ /** special purposes - not generally for hierarchy processing */
+ ACHANNEL_ROLE_SPECIAL = 0,
+ /** data channel - a channel representing one of the actual building blocks of channels */
+ ACHANNEL_ROLE_CHANNEL = 1,
} eAnimChannel_Role;
/* flag-setting behavior */
typedef enum eAnimChannels_SetFlag {
- /** turn off */
- ACHANNEL_SETFLAG_CLEAR = 0,
- /** turn on */
- ACHANNEL_SETFLAG_ADD = 1,
- /** on->off, off->on */
- ACHANNEL_SETFLAG_INVERT = 2,
- /** some on -> all off // all on */
- ACHANNEL_SETFLAG_TOGGLE = 3,
+ /** turn off */
+ ACHANNEL_SETFLAG_CLEAR = 0,
+ /** turn on */
+ ACHANNEL_SETFLAG_ADD = 1,
+ /** on->off, off->on */
+ ACHANNEL_SETFLAG_INVERT = 2,
+ /** some on -> all off // all on */
+ ACHANNEL_SETFLAG_TOGGLE = 3,
} eAnimChannels_SetFlag;
/* types of settings for AnimChannels */
typedef enum eAnimChannel_Settings {
- ACHANNEL_SETTING_SELECT = 0,
- /** warning: for drawing UI's, need to check if this is off (maybe inverse this later) */
- ACHANNEL_SETTING_PROTECT = 1,
- ACHANNEL_SETTING_MUTE = 2,
- ACHANNEL_SETTING_EXPAND = 3,
- /** only for Graph Editor */
- ACHANNEL_SETTING_VISIBLE = 4,
- /** only for NLA Tracks */
- ACHANNEL_SETTING_SOLO = 5,
- /** only for NLA Actions */
- ACHANNEL_SETTING_PINNED = 6,
- ACHANNEL_SETTING_MOD_OFF = 7,
- /** channel is pinned and always visible */
- ACHANNEL_SETTING_ALWAYS_VISIBLE = 8,
+ ACHANNEL_SETTING_SELECT = 0,
+ /** warning: for drawing UI's, need to check if this is off (maybe inverse this later) */
+ ACHANNEL_SETTING_PROTECT = 1,
+ ACHANNEL_SETTING_MUTE = 2,
+ ACHANNEL_SETTING_EXPAND = 3,
+ /** only for Graph Editor */
+ ACHANNEL_SETTING_VISIBLE = 4,
+ /** only for NLA Tracks */
+ ACHANNEL_SETTING_SOLO = 5,
+ /** only for NLA Actions */
+ ACHANNEL_SETTING_PINNED = 6,
+ ACHANNEL_SETTING_MOD_OFF = 7,
+ /** channel is pinned and always visible */
+ ACHANNEL_SETTING_ALWAYS_VISIBLE = 8,
} eAnimChannel_Settings;
-
/* Drawing, mouse handling, and flag setting behavior... */
typedef struct bAnimChannelType {
- /* -- Type data -- */
- /* name of the channel type, for debugging */
- const char *channel_type_name;
- /* "level" or role in hierarchy - for finding the active channel */
- eAnimChannel_Role channel_role;
-
- /* -- Drawing -- */
- /* get RGB color that is used to draw the majority of the backdrop */
- void (*get_backdrop_color)(bAnimContext *ac, bAnimListElem *ale, float r_color[3]);
- /* draw backdrop strip for channel */
- void (*draw_backdrop)(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc);
- /* get depth of indention (relative to the depth channel is nested at) */
- short (*get_indent_level)(bAnimContext *ac, bAnimListElem *ale);
- /* get offset in pixels for the start of the channel (in addition to the indent depth) */
- short (*get_offset)(bAnimContext *ac, bAnimListElem *ale);
-
- /* get name (for channel lists) */
- void (*name)(bAnimListElem *ale, char *name);
- /* get RNA property+pointer for editing the name */
- bool (*name_prop)(bAnimListElem *ale, struct PointerRNA *ptr, struct PropertyRNA **prop);
- /* get icon (for channel lists) */
- int (*icon)(bAnimListElem *ale);
-
- /* -- Settings -- */
- /* check if the given setting is valid in the current context */
- bool (*has_setting)(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting);
- /* get the flag used for this setting */
- int (*setting_flag)(bAnimContext *ac, eAnimChannel_Settings setting, bool *neg);
- /* get the pointer to int/short where data is stored,
- * with type being sizeof(ptr_data) which should be fine for runtime use...
- * - assume that setting has been checked to be valid for current context
- */
- void *(*setting_ptr)(bAnimListElem *ale, eAnimChannel_Settings setting, short *type);
+ /* -- Type data -- */
+ /* name of the channel type, for debugging */
+ const char *channel_type_name;
+ /* "level" or role in hierarchy - for finding the active channel */
+ eAnimChannel_Role channel_role;
+
+ /* -- Drawing -- */
+ /* get RGB color that is used to draw the majority of the backdrop */
+ void (*get_backdrop_color)(bAnimContext *ac, bAnimListElem *ale, float r_color[3]);
+ /* draw backdrop strip for channel */
+ void (*draw_backdrop)(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc);
+ /* get depth of indention (relative to the depth channel is nested at) */
+ short (*get_indent_level)(bAnimContext *ac, bAnimListElem *ale);
+ /* get offset in pixels for the start of the channel (in addition to the indent depth) */
+ short (*get_offset)(bAnimContext *ac, bAnimListElem *ale);
+
+ /* get name (for channel lists) */
+ void (*name)(bAnimListElem *ale, char *name);
+ /* get RNA property+pointer for editing the name */
+ bool (*name_prop)(bAnimListElem *ale, struct PointerRNA *ptr, struct PropertyRNA **prop);
+ /* get icon (for channel lists) */
+ int (*icon)(bAnimListElem *ale);
+
+ /* -- Settings -- */
+ /* check if the given setting is valid in the current context */
+ bool (*has_setting)(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting);
+ /* get the flag used for this setting */
+ int (*setting_flag)(bAnimContext *ac, eAnimChannel_Settings setting, bool *neg);
+ /* get the pointer to int/short where data is stored,
+ * with type being sizeof(ptr_data) which should be fine for runtime use...
+ * - assume that setting has been checked to be valid for current context
+ */
+ void *(*setting_ptr)(bAnimListElem *ale, eAnimChannel_Settings setting, short *type);
} bAnimChannelType;
/* ------------------------ Drawing API -------------------------- */
@@ -546,16 +550,15 @@ const bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale);
void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level);
/* Draw the given channel */
-void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc, size_t channel_index);
+void ANIM_channel_draw(
+ bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc, size_t channel_index);
/* Draw the widgets for the given channel */
-void ANIM_channel_draw_widgets(
- const struct bContext *C,
- bAnimContext *ac,
- bAnimListElem *ale,
- struct uiBlock *block,
- rctf *rect,
- size_t channel_index);
-
+void ANIM_channel_draw_widgets(const struct bContext *C,
+ bAnimContext *ac,
+ bAnimListElem *ale,
+ struct uiBlock *block,
+ rctf *rect,
+ size_t channel_index);
/* ------------------------ Editing API -------------------------- */
@@ -564,14 +567,18 @@ void ANIM_channel_draw_widgets(
*
* - setting: eAnimChannel_Settings
*/
-short ANIM_channel_setting_get(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting);
+short ANIM_channel_setting_get(bAnimContext *ac,
+ bAnimListElem *ale,
+ eAnimChannel_Settings setting);
/* Change value of some setting for a channel
* - setting: eAnimChannel_Settings
* - mode: eAnimChannels_SetFlag
*/
-void ANIM_channel_setting_set(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting, eAnimChannels_SetFlag mode);
-
+void ANIM_channel_setting_set(bAnimContext *ac,
+ bAnimListElem *ale,
+ eAnimChannel_Settings setting,
+ eAnimChannels_SetFlag mode);
/* Flush visibility (for Graph Editor) changes up/down hierarchy for changes in the given setting
* - anim_data: list of the all the anim channels that can be chosen
@@ -582,15 +589,23 @@ void ANIM_channel_setting_set(bAnimContext *ac, bAnimListElem *ale, eAnimChannel
* - setting: type of setting to set
* - on: whether the visibility setting has been enabled or disabled
*/
-void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAnimListElem *ale_setting, eAnimChannel_Settings setting, eAnimChannels_SetFlag mode);
-
+void ANIM_flush_setting_anim_channels(bAnimContext *ac,
+ ListBase *anim_data,
+ bAnimListElem *ale_setting,
+ eAnimChannel_Settings setting,
+ eAnimChannels_SetFlag mode);
/* Deselect all animation channels */
-void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types datatype, bool test, eAnimChannels_SetFlag sel);
+void ANIM_deselect_anim_channels(
+ bAnimContext *ac, void *data, eAnimCont_Types datatype, bool test, eAnimChannels_SetFlag sel);
/* Set the 'active' channel of type channel_type, in the given action */
-void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datatype, eAnimFilter_Flags filter, void *channel_data, eAnim_ChannelType channel_type);
-
+void ANIM_set_active_channel(bAnimContext *ac,
+ void *data,
+ eAnimCont_Types datatype,
+ eAnimFilter_Flags filter,
+ void *channel_data,
+ eAnim_ChannelType channel_type);
/* Delete the F-Curve from the given AnimData block (if possible),
* as appropriate according to animation context */
@@ -604,12 +619,12 @@ void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, struct AnimData *adt, st
/* flags for Current Frame Drawing */
enum eAnimEditDraw_CurrentFrame {
- /* plain time indicator with no special indicators */
- DRAWCFRA_PLAIN = 0,
- /* time indication in seconds or frames */
- DRAWCFRA_UNIT_SECONDS = (1 << 0),
- /* draw indicator extra wide (for timeline) */
- DRAWCFRA_WIDE = (1 << 1),
+ /* plain time indicator with no special indicators */
+ DRAWCFRA_PLAIN = 0,
+ /* time indication in seconds or frames */
+ DRAWCFRA_UNIT_SECONDS = (1 << 0),
+ /* draw indicator extra wide (for timeline) */
+ DRAWCFRA_WIDE = (1 << 1),
};
/* main call to draw current-frame indicator in an Animation Editor */
@@ -623,7 +638,6 @@ void ANIM_draw_cfra_number(const struct bContext *C, struct View2D *v2d, short f
/* main call to draw preview range curtains */
void ANIM_draw_previewrange(const struct bContext *C, struct View2D *v2d, int end_frame_width);
-
/* -------------- Frame Range Drawing --------------- */
/* main call to draw normal frame range indicators */
@@ -635,12 +649,13 @@ void ANIM_draw_framerange(struct Scene *scene, struct View2D *v2d);
/* ------------- UI Panel Drawing -------------- */
/* draw a given F-Modifier for some layout/UI-Block */
-void ANIM_uiTemplate_fmodifier_draw(struct uiLayout *layout, struct ID *fcurve_owner_id,
- ListBase *modifiers, struct FModifier *fcm);
+void ANIM_uiTemplate_fmodifier_draw(struct uiLayout *layout,
+ struct ID *fcurve_owner_id,
+ ListBase *modifiers,
+ struct FModifier *fcm);
/* ------------- Copy/Paste Buffer -------------- */
-
/* free the copy/paste buffer */
void ANIM_fmodifiers_copybuf_free(void);
@@ -682,7 +697,10 @@ void nla_action_get_color(struct AnimData *adt, struct bAction *act, float color
struct AnimData *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale);
/* Apply/Unapply NLA mapping to all keyframes in the nominated F-Curve */
-void ANIM_nla_mapping_apply_fcurve(struct AnimData *adt, struct FCurve *fcu, bool restore, bool only_keys);
+void ANIM_nla_mapping_apply_fcurve(struct AnimData *adt,
+ struct FCurve *fcu,
+ bool restore,
+ bool only_keys);
/* ..... */
@@ -695,28 +713,29 @@ void ED_nla_postop_refresh(bAnimContext *ac);
/* flags for conversion mapping */
typedef enum eAnimUnitConv_Flags {
- /* restore to original internal values */
- ANIM_UNITCONV_RESTORE = (1 << 0),
- /* ignore handles (i.e. only touch main keyframes) */
- ANIM_UNITCONV_ONLYKEYS = (1 << 1),
- /* only touch selected BezTriples */
- ANIM_UNITCONV_ONLYSEL = (1 << 2),
- /* only touch selected vertices */
- ANIM_UNITCONV_SELVERTS = (1 << 3),
- ANIM_UNITCONV_SKIPKNOTS = (1 << 4),
- /* 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,
- * prevents curves from jumping all over the place when tweaking them.
- */
- ANIM_UNITCONV_NORMALIZE_FREEZE = (1 << 6),
+ /* restore to original internal values */
+ ANIM_UNITCONV_RESTORE = (1 << 0),
+ /* ignore handles (i.e. only touch main keyframes) */
+ ANIM_UNITCONV_ONLYKEYS = (1 << 1),
+ /* only touch selected BezTriples */
+ ANIM_UNITCONV_ONLYSEL = (1 << 2),
+ /* only touch selected vertices */
+ ANIM_UNITCONV_SELVERTS = (1 << 3),
+ ANIM_UNITCONV_SKIPKNOTS = (1 << 4),
+ /* 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,
+ * prevents curves from jumping all over the place when tweaking them.
+ */
+ ANIM_UNITCONV_NORMALIZE_FREEZE = (1 << 6),
} eAnimUnitConv_Flags;
/* Normalization flags from Space Graph passing to ANIM_unit_mapping_get_factor */
short ANIM_get_normalization_flags(bAnimContext *ac);
/* Get unit conversion factor for given ID + F-Curve */
-float ANIM_unit_mapping_get_factor(struct Scene *scene, struct ID *id, struct FCurve *fcu, short flag, float *r_offset);
+float ANIM_unit_mapping_get_factor(
+ struct Scene *scene, struct ID *id, struct FCurve *fcu, short flag, float *r_offset);
/* ------------- Utility macros ----------------------- */
@@ -731,11 +750,15 @@ float ANIM_unit_mapping_get_factor(struct Scene *scene, struct ID *id, struct FC
* - sflag - bitflag to set
*/
#define ACHANNEL_SET_FLAG(channel, smode, sflag) \
- { \
- if (smode == ACHANNEL_SETFLAG_INVERT) (channel)->flag ^= (sflag); \
- else if (smode == ACHANNEL_SETFLAG_ADD) (channel)->flag |= (sflag); \
- else (channel)->flag &= ~(sflag); \
- } ((void)0)
+ { \
+ if (smode == ACHANNEL_SETFLAG_INVERT) \
+ (channel)->flag ^= (sflag); \
+ else if (smode == ACHANNEL_SETFLAG_ADD) \
+ (channel)->flag |= (sflag); \
+ else \
+ (channel)->flag &= ~(sflag); \
+ } \
+ ((void)0)
/* set/clear/toggle macro, where the flag is negative
* - channel - channel with a 'flag' member that we're setting
@@ -743,12 +766,15 @@ float ANIM_unit_mapping_get_factor(struct Scene *scene, struct ID *id, struct FC
* - sflag - bitflag to set
*/
#define ACHANNEL_SET_FLAG_NEG(channel, smode, sflag) \
- { \
- if (smode == ACHANNEL_SETFLAG_INVERT) (channel)->flag ^= (sflag); \
- else if (smode == ACHANNEL_SETFLAG_ADD) (channel)->flag &= ~(sflag); \
- else (channel)->flag |= (sflag); \
- } ((void)0)
-
+ { \
+ if (smode == ACHANNEL_SETFLAG_INVERT) \
+ (channel)->flag ^= (sflag); \
+ else if (smode == ACHANNEL_SETFLAG_ADD) \
+ (channel)->flag &= ~(sflag); \
+ else \
+ (channel)->flag |= (sflag); \
+ } \
+ ((void)0)
/* --------- anim_deps.c, animation updates -------- */
@@ -782,10 +808,12 @@ void ED_operatormacros_action(void);
/* Action Editor - Action Management */
struct AnimData *ED_actedit_animdata_from_context(struct bContext *C);
-void ED_animedit_unlink_action(struct bContext *C, struct ID *id,
- struct AnimData *adt, struct bAction *act,
- struct ReportList *reports, bool force_delete);
-
+void ED_animedit_unlink_action(struct bContext *C,
+ struct ID *id,
+ struct AnimData *adt,
+ struct bAction *act,
+ struct ReportList *reports,
+ bool force_delete);
/* Drivers Editor - Utility to set up UI correctly */
void ED_drivers_editor_init(struct bContext *C, struct ScrArea *sa);
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index d469c0ea8a0..9fb8f1b1b04 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -51,98 +51,97 @@ struct wmKeyConfig;
struct wmOperator;
typedef struct EditBone {
- struct EditBone *next, *prev;
- /** User-Defined Properties on this Bone */
- struct IDProperty *prop;
- /** Editbones have a one-way link (i.e. children refer
- * to parents. This is converted to a two-way link for
- * normal bones when leaving editmode. */
- struct EditBone *parent;
- /** (64 == MAXBONENAME) */
- char name[64];
- /** Roll along axis. We'll ultimately use the axis/angle method
- * for determining the transformation matrix of the bone. The axis
- * is tail-head while roll provides the angle. Refer to Graphics
- * Gems 1 p. 466 (section IX.6) if it's not already in here somewhere*/
- float roll;
-
- /** Orientation and length is implicit during editing */
- float head[3];
- float tail[3];
- /** All joints are considered to have zero rotation with respect to
- * their parents. Therefore any rotations specified during the
- * animation are automatically relative to the bones' rest positions*/
- int flag;
- int layer;
-
- float dist, weight;
- /** put them in order! transform uses this as scale */
- float xwidth, length, zwidth;
- float rad_head, rad_tail;
-
- /* Bendy-Bone parameters */
- float roll1, roll2;
- float curveOutX, curveOutY;
- float curveInX, curveInY;
- float ease1, ease2;
- float scaleIn, scaleOut;
-
- /** for envelope scaling */
- float oldlength;
-
- short segments;
-
- /** Type of next/prev bone handles */
- char bbone_prev_type;
- char bbone_next_type;
- /** Next/prev bones to use as handle references when calculating bbones (optional) */
- struct EditBone *bbone_prev;
- struct EditBone *bbone_next;
-
- /* Used for display */
- /** in Armature space, rest pos matrix */
- float disp_mat[4][4];
- /** in Armature space, rest pos matrix */
- float disp_tail_mat[4][4];
- /** in Armature space, rest pos matrix (32 == MAX_BBONE_SUBDIV) */
- float disp_bbone_mat[32][4][4];
-
- /** connected child temporary during drawing */
- struct EditBone *bbone_child;
-
- /* Used to store temporary data */
- union {
- struct EditBone *ebone;
- struct Bone *bone;
- void *p;
- int i;
- } temp;
+ struct EditBone *next, *prev;
+ /** User-Defined Properties on this Bone */
+ struct IDProperty *prop;
+ /** Editbones have a one-way link (i.e. children refer
+ * to parents. This is converted to a two-way link for
+ * normal bones when leaving editmode. */
+ struct EditBone *parent;
+ /** (64 == MAXBONENAME) */
+ char name[64];
+ /** Roll along axis. We'll ultimately use the axis/angle method
+ * for determining the transformation matrix of the bone. The axis
+ * is tail-head while roll provides the angle. Refer to Graphics
+ * Gems 1 p. 466 (section IX.6) if it's not already in here somewhere*/
+ float roll;
+
+ /** Orientation and length is implicit during editing */
+ float head[3];
+ float tail[3];
+ /** All joints are considered to have zero rotation with respect to
+ * their parents. Therefore any rotations specified during the
+ * animation are automatically relative to the bones' rest positions*/
+ int flag;
+ int layer;
+
+ float dist, weight;
+ /** put them in order! transform uses this as scale */
+ float xwidth, length, zwidth;
+ float rad_head, rad_tail;
+
+ /* Bendy-Bone parameters */
+ float roll1, roll2;
+ float curveOutX, curveOutY;
+ float curveInX, curveInY;
+ float ease1, ease2;
+ float scaleIn, scaleOut;
+
+ /** for envelope scaling */
+ float oldlength;
+
+ short segments;
+
+ /** Type of next/prev bone handles */
+ char bbone_prev_type;
+ char bbone_next_type;
+ /** Next/prev bones to use as handle references when calculating bbones (optional) */
+ struct EditBone *bbone_prev;
+ struct EditBone *bbone_next;
+
+ /* Used for display */
+ /** in Armature space, rest pos matrix */
+ float disp_mat[4][4];
+ /** in Armature space, rest pos matrix */
+ float disp_tail_mat[4][4];
+ /** in Armature space, rest pos matrix (32 == MAX_BBONE_SUBDIV) */
+ float disp_bbone_mat[32][4][4];
+
+ /** connected child temporary during drawing */
+ struct EditBone *bbone_child;
+
+ /* Used to store temporary data */
+ union {
+ struct EditBone *ebone;
+ struct Bone *bone;
+ void *p;
+ int i;
+ } temp;
} EditBone;
-#define BONESEL_ROOT (1 << 28)
-#define BONESEL_TIP (1 << 29)
-#define BONESEL_BONE (1 << 30)
-#define BONESEL_ANY (BONESEL_TIP | BONESEL_ROOT | BONESEL_BONE)
+#define BONESEL_ROOT (1 << 28)
+#define BONESEL_TIP (1 << 29)
+#define BONESEL_BONE (1 << 30)
+#define BONESEL_ANY (BONESEL_TIP | BONESEL_ROOT | BONESEL_BONE)
-#define BONESEL_NOSEL (1u << 31u)
+#define BONESEL_NOSEL (1u << 31u)
/* useful macros */
-#define EBONE_VISIBLE(arm, ebone) ( \
- CHECK_TYPE_INLINE(arm, bArmature *), \
- CHECK_TYPE_INLINE(ebone, EditBone *), \
- (((arm)->layer & (ebone)->layer) && !((ebone)->flag & BONE_HIDDEN_A)) \
- )
+#define EBONE_VISIBLE(arm, ebone) \
+ (CHECK_TYPE_INLINE(arm, bArmature *), \
+ CHECK_TYPE_INLINE(ebone, EditBone *), \
+ (((arm)->layer & (ebone)->layer) && !((ebone)->flag & BONE_HIDDEN_A)))
-#define EBONE_SELECTABLE(arm, ebone) (EBONE_VISIBLE(arm, ebone) && !(ebone->flag & BONE_UNSELECTABLE))
+#define EBONE_SELECTABLE(arm, ebone) \
+ (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)) \
- )
+#define EBONE_EDITABLE(ebone) \
+ (CHECK_TYPE_INLINE(ebone, EditBone *), \
+ (((ebone)->flag & BONE_SELECTED) && !((ebone)->flag & BONE_EDITMODE_LOCKED)))
/* used in armature_select_hierarchy_exec() */
-#define BONE_SELECT_PARENT 0
-#define BONE_SELECT_CHILD 1
+#define BONE_SELECT_PARENT 0
+#define BONE_SELECT_CHILD 1
/* armature_ops.c */
void ED_operatortypes_armature(void);
@@ -161,38 +160,54 @@ 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);
+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);
bool ED_armature_edit_select_pick(
- struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
+ 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);
+bool ED_armature_edit_select_op_from_tagged(struct bArmature *arm, const int sel_op);
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);
+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);
-struct Base *ED_armature_base_and_ebone_from_select_buffer(
- struct Base **bases, uint bases_len, int hit, struct EditBone **r_ebone);
-struct Object *ED_armature_object_and_ebone_from_select_buffer(
- struct Object **objects, uint objects_len, int hit, struct EditBone **r_ebone);
-
-struct Base *ED_armature_base_and_bone_from_select_buffer(
- struct Base **bases, uint bases_len, int hit, struct Bone **r_bone);
-
-EditBone *ED_armature_ebone_add_primitive(struct Object *obedit_arm, float length, bool view_aligned);
+struct Base *ED_armature_base_and_ebone_from_select_buffer(struct Base **bases,
+ uint bases_len,
+ int hit,
+ struct EditBone **r_ebone);
+struct Object *ED_armature_object_and_ebone_from_select_buffer(struct Object **objects,
+ uint objects_len,
+ int hit,
+ struct EditBone **r_ebone);
+
+struct Base *ED_armature_base_and_bone_from_select_buffer(struct Base **bases,
+ uint bases_len,
+ int hit,
+ struct Bone **r_bone);
+
+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);
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);
+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]);
@@ -201,27 +216,44 @@ void ED_armature_ebone_from_mat3(EditBone *ebone, float mat[3][3]);
void ED_armature_ebone_from_mat4(EditBone *ebone, float mat[4][4]);
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_origin_set(
+ struct Main *bmain, struct Object *ob, const float cursor[3], int centermode, int around);
void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4], const bool do_props);
-void ED_armature_transform_apply(struct Main *bmain, struct Object *ob, float mat[4][4], const bool do_props);
-void ED_armature_transform(struct Main *bmain, struct bArmature *arm, float mat[4][4], const bool do_props);
-
-#define ARM_GROUPS_NAME 1
+void ED_armature_transform_apply(struct Main *bmain,
+ struct Object *ob,
+ float mat[4][4],
+ const bool do_props);
+void ED_armature_transform(struct Main *bmain,
+ struct bArmature *arm,
+ float mat[4][4],
+ const bool do_props);
+
+#define ARM_GROUPS_NAME 1
#define ARM_GROUPS_ENVELOPE 2
-#define ARM_GROUPS_AUTO 3
+#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);
+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_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);
/* low level selection functions which handle */
-int ED_armature_ebone_selectflag_get(const EditBone *ebone);
+int ED_armature_ebone_selectflag_get(const EditBone *ebone);
void ED_armature_ebone_selectflag_set(EditBone *ebone, int flag);
void ED_armature_ebone_select_set(EditBone *ebone, bool select);
void ED_armature_ebone_selectflag_enable(EditBone *ebone, int flag);
@@ -240,19 +272,26 @@ 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_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);
-void ED_pose_recalculate_paths(struct bContext *C, struct Scene *scene, struct Object *ob, bool current_frame_only);
+void ED_pose_recalculate_paths(struct bContext *C,
+ struct Scene *scene,
+ struct Object *ob,
+ bool current_frame_only);
struct Object *ED_pose_object_from_context(struct bContext *C);
/* meshlaplacian.c */
-void ED_mesh_deform_bind_callback(
- struct MeshDeformModifierData *mmd,
- struct Mesh *cagemesh,
- float *vertexcos, int totvert, float cagemat[4][4]);
+void ED_mesh_deform_bind_callback(struct MeshDeformModifierData *mmd,
+ struct Mesh *cagemesh,
+ float *vertexcos,
+ int totvert,
+ float cagemat[4][4]);
#ifdef __cplusplus
}
diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h
index a146bbeb0af..1d9e99eeaf9 100644
--- a/source/blender/editors/include/ED_clip.h
+++ b/source/blender/editors/include/ED_clip.h
@@ -54,9 +54,15 @@ void ED_space_clip_get_aspect_dimension_aware(struct SpaceClip *sc, float *aspx,
int ED_space_clip_get_clip_frame_number(struct SpaceClip *sc);
struct ImBuf *ED_space_clip_get_buffer(struct SpaceClip *sc);
-struct ImBuf *ED_space_clip_get_stable_buffer(struct SpaceClip *sc, float loc[2], float *scale, float *angle);
+struct ImBuf *ED_space_clip_get_stable_buffer(struct SpaceClip *sc,
+ float loc[2],
+ float *scale,
+ float *angle);
-bool ED_space_clip_color_sample(struct SpaceClip *sc, struct ARegion *ar, int mval[2], float r_col[3]);
+bool ED_space_clip_color_sample(struct SpaceClip *sc,
+ struct ARegion *ar,
+ 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);
@@ -64,15 +70,22 @@ bool ED_clip_view_selection(const struct bContext *C, struct ARegion *ar, bool f
void ED_clip_select_all(struct SpaceClip *sc, int action, bool *r_has_selection);
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);
-void ED_clip_point_stable_pos__reverse(struct SpaceClip *sc, struct ARegion *ar, 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);
+void ED_clip_point_stable_pos__reverse(struct SpaceClip *sc,
+ struct ARegion *ar,
+ 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]);
bool ED_space_clip_check_show_trackedit(struct SpaceClip *sc);
bool ED_space_clip_check_show_maskedit(struct SpaceClip *sc);
struct MovieClip *ED_space_clip_get_clip(struct SpaceClip *sc);
-void ED_space_clip_set_clip(struct bContext *C, struct bScreen *screen, struct SpaceClip *sc, struct MovieClip *clip);
+void ED_space_clip_set_clip(struct bContext *C,
+ struct bScreen *screen,
+ struct SpaceClip *sc,
+ struct MovieClip *clip);
struct Mask *ED_space_clip_get_mask(struct SpaceClip *sc);
void ED_space_clip_set_mask(struct bContext *C, struct SpaceClip *sc, struct Mask *mask);
diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h
index 3e8821efbd0..d6d5ae299b7 100644
--- a/source/blender/editors/include/ED_curve.h
+++ b/source/blender/editors/include/ED_curve.h
@@ -40,27 +40,29 @@ struct wmKeyConfig;
struct wmOperator;
/* curve_ops.c */
-void ED_operatortypes_curve(void);
-void ED_operatormacros_curve(void);
-void ED_keymap_curve(struct wmKeyConfig *keyconf);
+void ED_operatortypes_curve(void);
+void ED_operatormacros_curve(void);
+void ED_keymap_curve(struct wmKeyConfig *keyconf);
/* editcurve.c */
struct ListBase *object_editcurve_get(struct Object *ob);
-void ED_curve_editnurb_load(struct Main *bmain, struct Object *obedit);
-void ED_curve_editnurb_make(struct Object *obedit);
-void ED_curve_editnurb_free(struct Object *obedit);
+void ED_curve_editnurb_load(struct Main *bmain, struct Object *obedit);
+void ED_curve_editnurb_make(struct Object *obedit);
+void ED_curve_editnurb_free(struct Object *obedit);
-bool ED_curve_editnurb_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
+bool ED_curve_editnurb_select_pick(
+ struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
-struct Nurb *ED_curve_add_nurbs_primitive(struct bContext *C, struct Object *obedit, float mat[4][4], int type, int newob);
+struct Nurb *ED_curve_add_nurbs_primitive(
+ struct bContext *C, struct Object *obedit, float mat[4][4], int type, int newob);
-bool ED_curve_nurb_select_check(struct View3D *v3d, struct Nurb *nu);
-int ED_curve_nurb_select_count(struct View3D *v3d, struct Nurb *nu);
-bool ED_curve_nurb_select_all(const struct Nurb *nu);
-bool ED_curve_nurb_deselect_all(const struct Nurb *nu);
+bool ED_curve_nurb_select_check(struct View3D *v3d, struct Nurb *nu);
+int ED_curve_nurb_select_count(struct View3D *v3d, struct Nurb *nu);
+bool ED_curve_nurb_select_all(const struct Nurb *nu);
+bool ED_curve_nurb_deselect_all(const struct Nurb *nu);
-int join_curve_exec(struct bContext *C, struct wmOperator *op);
+int join_curve_exec(struct bContext *C, struct wmOperator *op);
/* editcurve_select.c */
bool ED_curve_select_check(struct View3D *v3d, struct EditNurb *editnurb);
@@ -75,25 +77,28 @@ int ED_curve_select_count(struct View3D *v3d, struct EditNurb *editnurb);
void ED_curve_undosys_type(struct UndoType *ut);
/* editfont.c */
-void ED_curve_editfont_load(struct Object *obedit);
-void ED_curve_editfont_make(struct Object *obedit);
-void ED_curve_editfont_free(struct Object *obedit);
+void ED_curve_editfont_load(struct Object *obedit);
+void ED_curve_editfont_make(struct Object *obedit);
+void ED_curve_editfont_free(struct Object *obedit);
-void ED_text_to_object(struct bContext *C, struct Text *text, const bool split_lines);
+void ED_text_to_object(struct bContext *C, struct Text *text, const bool split_lines);
-void ED_curve_beztcpy(struct EditNurb *editnurb, struct BezTriple *dst, struct BezTriple *src, int count);
+void ED_curve_beztcpy(struct EditNurb *editnurb,
+ struct BezTriple *dst,
+ struct BezTriple *src,
+ int count);
void ED_curve_bpcpy(struct EditNurb *editnurb, struct BPoint *dst, struct BPoint *src, int count);
int ED_curve_updateAnimPaths(struct Main *bmain, struct Curve *cu);
bool ED_curve_active_center(struct Curve *cu, float center[3]);
-bool ED_curve_editfont_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
+bool ED_curve_editfont_select_pick(
+ struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
/* editfont_undo.c */
void ED_font_undosys_type(struct UndoType *ut);
-
#if 0
/* debug only */
void printknots(struct Object *obedit);
diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h
index 48c38396e98..7273f857a41 100644
--- a/source/blender/editors/include/ED_fileselect.h
+++ b/source/blender/editors/include/ED_fileselect.h
@@ -37,38 +37,38 @@ struct wmWindowManager;
#define MAX_FILE_COLUMN 4
typedef enum FileListColumns {
- COLUMN_NAME = 0,
- COLUMN_DATE,
- COLUMN_TIME,
- COLUMN_SIZE,
+ COLUMN_NAME = 0,
+ COLUMN_DATE,
+ COLUMN_TIME,
+ COLUMN_SIZE,
} FileListColumns;
typedef struct FileLayout {
- /* view settings - XXX - move into own struct */
- int prv_w;
- int prv_h;
- int tile_w;
- int tile_h;
- int tile_border_x;
- int tile_border_y;
- int prv_border_x;
- int prv_border_y;
- int rows;
- int columns;
- int width;
- int height;
- int flag;
- int dirty;
- int textheight;
- float column_widths[MAX_FILE_COLUMN];
-
- /* When we change display size, we may have to update static strings like size of files... */
- short curr_size;
+ /* view settings - XXX - move into own struct */
+ int prv_w;
+ int prv_h;
+ int tile_w;
+ int tile_h;
+ int tile_border_x;
+ int tile_border_y;
+ int prv_border_x;
+ int prv_border_y;
+ int rows;
+ int columns;
+ int width;
+ int height;
+ int flag;
+ int dirty;
+ int textheight;
+ float column_widths[MAX_FILE_COLUMN];
+
+ /* When we change display size, we may have to update static strings like size of files... */
+ short curr_size;
} FileLayout;
typedef struct FileSelection {
- int first;
- int last;
+ int first;
+ int last;
} FileSelection;
struct rcti;
@@ -79,10 +79,8 @@ short ED_fileselect_set_params(struct SpaceFile *sfile);
void ED_fileselect_reset_params(struct SpaceFile *sfile);
-
void ED_fileselect_init_layout(struct SpaceFile *sfile, struct ARegion *ar);
-
FileLayout *ED_fileselect_get_layout(struct SpaceFile *sfile, struct ARegion *ar);
int ED_fileselect_layout_numfiles(FileLayout *layout, struct ARegion *ar);
@@ -108,29 +106,29 @@ void ED_file_change_dir(struct bContext *C);
/* FSMenuEntry's without paths indicate separators */
typedef struct FSMenuEntry {
- struct FSMenuEntry *next;
+ struct FSMenuEntry *next;
- char *path;
- char name[256]; /* FILE_MAXFILE */
- short save;
- short valid;
- short pad[2];
+ char *path;
+ char name[256]; /* FILE_MAXFILE */
+ short save;
+ short valid;
+ short pad[2];
} FSMenuEntry;
typedef enum FSMenuCategory {
- FS_CATEGORY_SYSTEM,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- FS_CATEGORY_BOOKMARKS,
- FS_CATEGORY_RECENT,
+ FS_CATEGORY_SYSTEM,
+ FS_CATEGORY_SYSTEM_BOOKMARKS,
+ FS_CATEGORY_BOOKMARKS,
+ FS_CATEGORY_RECENT,
} FSMenuCategory;
typedef enum FSMenuInsert {
- FS_INSERT_SORTED = (1 << 0),
- FS_INSERT_SAVE = (1 << 1),
- /** moves the item to the front of the list when its not already there */
- FS_INSERT_FIRST = (1 << 2),
- /** just append to preseve delivered order */
- FS_INSERT_LAST = (1 << 3),
+ FS_INSERT_SORTED = (1 << 0),
+ FS_INSERT_SAVE = (1 << 1),
+ /** moves the item to the front of the list when its not already there */
+ FS_INSERT_FIRST = (1 << 2),
+ /** just append to preseve delivered order */
+ FS_INSERT_LAST = (1 << 3),
} FSMenuInsert;
struct FSMenu;
@@ -138,7 +136,9 @@ struct FSMenuEntry;
struct FSMenu *ED_fsmenu_get(void);
struct FSMenuEntry *ED_fsmenu_get_category(struct FSMenu *fsmenu, FSMenuCategory category);
-void ED_fsmenu_set_category(struct FSMenu *fsmenu, FSMenuCategory category, struct FSMenuEntry *fsm_head);
+void ED_fsmenu_set_category(struct FSMenu *fsmenu,
+ FSMenuCategory category,
+ struct FSMenuEntry *fsm_head);
int ED_fsmenu_get_nentries(struct FSMenu *fsmenu, FSMenuCategory category);
diff --git a/source/blender/editors/include/ED_gizmo_library.h b/source/blender/editors/include/ED_gizmo_library.h
index 48effda37ef..f14648bc026 100644
--- a/source/blender/editors/include/ED_gizmo_library.h
+++ b/source/blender/editors/include/ED_gizmo_library.h
@@ -22,7 +22,6 @@
* This is exposes pre-defined gizmos for re-use.
*/
-
#ifndef __ED_GIZMO_LIBRARY_H__
#define __ED_GIZMO_LIBRARY_H__
@@ -49,7 +48,6 @@ struct bContext;
struct wmGizmo;
struct wmGizmoGroup;
-
/* -------------------------------------------------------------------- */
/* Shape Presets
*
@@ -57,39 +55,43 @@ struct wmGizmoGroup;
*/
/* gizmo_library_presets.c */
-void ED_gizmo_draw_preset_box(
- const struct wmGizmo *gz, float mat[4][4], int select_id);
-void ED_gizmo_draw_preset_arrow(
- const struct wmGizmo *gz, float mat[4][4], int axis, int select_id);
-void ED_gizmo_draw_preset_circle(
- const struct wmGizmo *gz, float mat[4][4], int axis, int select_id);
-void ED_gizmo_draw_preset_facemap(
- const struct bContext *C, const struct wmGizmo *gz,
- struct Object *ob, const int facemap, int select_id);
-
+void ED_gizmo_draw_preset_box(const struct wmGizmo *gz, float mat[4][4], int select_id);
+void ED_gizmo_draw_preset_arrow(const struct wmGizmo *gz,
+ float mat[4][4],
+ int axis,
+ int select_id);
+void ED_gizmo_draw_preset_circle(const struct wmGizmo *gz,
+ float mat[4][4],
+ int axis,
+ int select_id);
+void ED_gizmo_draw_preset_facemap(const struct bContext *C,
+ const struct wmGizmo *gz,
+ struct Object *ob,
+ const int facemap,
+ int select_id);
/* -------------------------------------------------------------------- */
/* 3D Arrow Gizmo */
enum {
- ED_GIZMO_ARROW_STYLE_NORMAL = 0,
- ED_GIZMO_ARROW_STYLE_CROSS = 1,
- ED_GIZMO_ARROW_STYLE_BOX = 2,
- ED_GIZMO_ARROW_STYLE_CONE = 3,
+ ED_GIZMO_ARROW_STYLE_NORMAL = 0,
+ ED_GIZMO_ARROW_STYLE_CROSS = 1,
+ ED_GIZMO_ARROW_STYLE_BOX = 2,
+ ED_GIZMO_ARROW_STYLE_CONE = 3,
};
/* transform */
enum {
- /* inverted offset during interaction - if set it also sets constrained below */
- ED_GIZMO_ARROW_XFORM_FLAG_INVERTED = (1 << 3),
- /* clamp arrow interaction to property width */
- ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED = (1 << 4),
+ /* inverted offset during interaction - if set it also sets constrained below */
+ ED_GIZMO_ARROW_XFORM_FLAG_INVERTED = (1 << 3),
+ /* clamp arrow interaction to property width */
+ ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED = (1 << 4),
};
/* draw_options */
enum {
- /* Show arrow stem. */
- ED_GIZMO_ARROW_DRAW_FLAG_STEM = (1 << 0),
+ /* Show arrow stem. */
+ ED_GIZMO_ARROW_DRAW_FLAG_STEM = (1 << 0),
};
void ED_gizmo_arrow3d_set_ui_range(struct wmGizmo *gz, const float min, const float max);
@@ -104,76 +106,76 @@ void ED_gizmo_arrow3d_set_range_fac(struct wmGizmo *gz, const float range_fac);
/* Cage Gizmo */
enum {
- ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE = (1 << 0), /* Translates */
- ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE = (1 << 1), /* Rotates */
- ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE = (1 << 2), /* Scales */
- ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM = (1 << 3), /* Scales uniformly */
- ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_SIGNED = (1 << 4), /* Negative scale allowed */
+ ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE = (1 << 0), /* Translates */
+ ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE = (1 << 1), /* Rotates */
+ ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE = (1 << 2), /* Scales */
+ ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM = (1 << 3), /* Scales uniformly */
+ ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_SIGNED = (1 << 4), /* Negative scale allowed */
};
/* draw_style */
enum {
- ED_GIZMO_CAGE2D_STYLE_BOX = 0,
- ED_GIZMO_CAGE2D_STYLE_CIRCLE = 1,
+ ED_GIZMO_CAGE2D_STYLE_BOX = 0,
+ ED_GIZMO_CAGE2D_STYLE_CIRCLE = 1,
};
/* draw_options */
enum {
- /** Draw a central handle (instead of having the entire area selectable)
- * Needed for large rectangles that we don't want to swallow all events. */
- ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE = (1 << 0),
+ /** Draw a central handle (instead of having the entire area selectable)
+ * Needed for large rectangles that we don't want to swallow all events. */
+ ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE = (1 << 0),
};
/** #wmGizmo.highlight_part */
enum {
- ED_GIZMO_CAGE2D_PART_TRANSLATE = 0,
- ED_GIZMO_CAGE2D_PART_SCALE_MIN_X = 1,
- ED_GIZMO_CAGE2D_PART_SCALE_MAX_X = 2,
- ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y = 3,
- ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y = 4,
- /* Corners */
- ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y = 5,
- ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y = 6,
- ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y = 7,
- ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y = 8,
-
- ED_GIZMO_CAGE2D_PART_ROTATE = 9,
+ ED_GIZMO_CAGE2D_PART_TRANSLATE = 0,
+ ED_GIZMO_CAGE2D_PART_SCALE_MIN_X = 1,
+ ED_GIZMO_CAGE2D_PART_SCALE_MAX_X = 2,
+ ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y = 3,
+ ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y = 4,
+ /* Corners */
+ ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y = 5,
+ ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y = 6,
+ ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y = 7,
+ ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y = 8,
+
+ ED_GIZMO_CAGE2D_PART_ROTATE = 9,
};
/** #wmGizmo.highlight_part */
enum {
- /* ordered min/mid/max so we can loop over values (MIN/MID/MAX) on each axis. */
- ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z = 0,
- ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MID_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MAX_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MID_Y_MIN_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MID_Y_MID_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MID_Y_MAX_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MAX_Y_MIN_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MAX_Y_MID_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MAX_Y_MAX_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MIN_Y_MIN_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MIN_Y_MID_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MIN_Y_MAX_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MID_Y_MIN_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MID_Y_MID_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MID_Y_MAX_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MAX_Y_MIN_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MAX_Y_MID_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MAX_Y_MAX_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MIN_Y_MIN_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MIN_Y_MID_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MIN_Y_MAX_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MID_Y_MIN_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MID_Y_MID_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MID_Y_MAX_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MIN_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MID_Z,
- ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z,
-
- ED_GIZMO_CAGE3D_PART_TRANSLATE,
-
- ED_GIZMO_CAGE3D_PART_ROTATE,
+ /* ordered min/mid/max so we can loop over values (MIN/MID/MAX) on each axis. */
+ ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z = 0,
+ ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MID_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MAX_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MID_Y_MIN_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MID_Y_MID_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MID_Y_MAX_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MAX_Y_MIN_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MAX_Y_MID_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MAX_Y_MAX_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MIN_Y_MIN_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MIN_Y_MID_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MIN_Y_MAX_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MID_Y_MIN_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MID_Y_MID_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MID_Y_MAX_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MAX_Y_MIN_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MAX_Y_MID_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MAX_Y_MAX_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MIN_Y_MIN_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MIN_Y_MID_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MIN_Y_MAX_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MID_Y_MIN_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MID_Y_MID_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MID_Y_MAX_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MIN_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MID_Z,
+ ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z,
+
+ ED_GIZMO_CAGE3D_PART_TRANSLATE,
+
+ ED_GIZMO_CAGE3D_PART_ROTATE,
};
/* -------------------------------------------------------------------- */
@@ -181,14 +183,14 @@ enum {
/* draw_options */
enum {
- ED_GIZMO_DIAL_DRAW_FLAG_NOP = 0,
- ED_GIZMO_DIAL_DRAW_FLAG_CLIP = (1 << 0),
- ED_GIZMO_DIAL_DRAW_FLAG_FILL = (1 << 1),
- ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT = (1 << 2),
- ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR = (1 << 3),
- ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y = (1 << 4),
- /* Always show the angle value as an arc in the dial. */
- ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE = (1 << 5),
+ ED_GIZMO_DIAL_DRAW_FLAG_NOP = 0,
+ ED_GIZMO_DIAL_DRAW_FLAG_CLIP = (1 << 0),
+ ED_GIZMO_DIAL_DRAW_FLAG_FILL = (1 << 1),
+ ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT = (1 << 2),
+ ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR = (1 << 3),
+ ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y = (1 << 4),
+ /* Always show the angle value as an arc in the dial. */
+ ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE = (1 << 5),
};
/* -------------------------------------------------------------------- */
@@ -196,58 +198,55 @@ enum {
/* draw_options */
enum {
- ED_GIZMO_MOVE_DRAW_FLAG_NOP = 0,
- /* only for solid shapes */
- ED_GIZMO_MOVE_DRAW_FLAG_FILL = (1 << 0),
- ED_GIZMO_MOVE_DRAW_FLAG_FILL_SELECT = (1 << 1),
- ED_GIZMO_MOVE_DRAW_FLAG_ALIGN_VIEW = (1 << 2),
+ ED_GIZMO_MOVE_DRAW_FLAG_NOP = 0,
+ /* only for solid shapes */
+ ED_GIZMO_MOVE_DRAW_FLAG_FILL = (1 << 0),
+ ED_GIZMO_MOVE_DRAW_FLAG_FILL_SELECT = (1 << 1),
+ ED_GIZMO_MOVE_DRAW_FLAG_ALIGN_VIEW = (1 << 2),
};
enum {
- ED_GIZMO_MOVE_STYLE_RING_2D = 0,
- ED_GIZMO_MOVE_STYLE_CROSS_2D = 1,
+ ED_GIZMO_MOVE_STYLE_RING_2D = 0,
+ ED_GIZMO_MOVE_STYLE_CROSS_2D = 1,
};
/* -------------------------------------------------------------------- */
/* Button Gizmo */
enum {
- ED_GIZMO_BUTTON_SHOW_OUTLINE = (1 << 0),
- ED_GIZMO_BUTTON_SHOW_BACKDROP = (1 << 1),
- /**
- * Draw a line from the origin to the offset (similar to an arrow)
- * sometimes needed to show what the button edits.
- */
- ED_GIZMO_BUTTON_SHOW_HELPLINE = (1 << 2),
+ ED_GIZMO_BUTTON_SHOW_OUTLINE = (1 << 0),
+ ED_GIZMO_BUTTON_SHOW_BACKDROP = (1 << 1),
+ /**
+ * Draw a line from the origin to the offset (similar to an arrow)
+ * sometimes needed to show what the button edits.
+ */
+ ED_GIZMO_BUTTON_SHOW_HELPLINE = (1 << 2),
};
-
/* -------------------------------------------------------------------- */
/* Primitive Gizmo */
enum {
- ED_GIZMO_PRIMITIVE_STYLE_PLANE = 0,
+ ED_GIZMO_PRIMITIVE_STYLE_PLANE = 0,
};
-
/* -------------------------------------------------------------------- */
/* Gizmo Drawing Functions */
struct Dial3dParams {
- int draw_options;
- float angle_ofs;
- float angle_delta;
- float angle_increment;
- float arc_partial_angle;
- float arc_inner_factor;
- float *clip_plane;
+ int draw_options;
+ float angle_ofs;
+ float angle_delta;
+ float angle_increment;
+ float arc_partial_angle;
+ float arc_inner_factor;
+ float *clip_plane;
};
-void ED_gizmotypes_dial_3d_draw_util(
- const float matrix_basis[4][4],
- const float matrix_final[4][4],
- const float line_width,
- const float color[4],
- const bool select,
- struct Dial3dParams *params);
-
-#endif /* __ED_GIZMO_LIBRARY_H__ */
+void ED_gizmotypes_dial_3d_draw_util(const float matrix_basis[4][4],
+ const float matrix_final[4][4],
+ const float line_width,
+ const float color[4],
+ const bool select,
+ struct Dial3dParams *params);
+
+#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 e81dcb34cd2..8c494bdf18c 100644
--- a/source/blender/editors/include/ED_gizmo_utils.h
+++ b/source/blender/editors/include/ED_gizmo_utils.h
@@ -27,16 +27,16 @@ struct bContext;
struct wmGizmoGroupType;
/** Wrapper function (operator name can't be guessed). */
-bool ED_gizmo_poll_or_unlink_delayed_from_operator(
- const struct bContext *C, struct wmGizmoGroupType *gzgt,
- const char *idname);
+bool ED_gizmo_poll_or_unlink_delayed_from_operator(const struct bContext *C,
+ struct wmGizmoGroupType *gzgt,
+ const char *idname);
-bool ED_gizmo_poll_or_unlink_delayed_from_tool_ex(
- const struct bContext *C, struct wmGizmoGroupType *gzgt,
- const char *gzgt_idname);
+bool ED_gizmo_poll_or_unlink_delayed_from_tool_ex(const struct bContext *C,
+ struct wmGizmoGroupType *gzgt,
+ const char *gzgt_idname);
/** Use this as poll function directly for: #wmGizmoGroupType.poll */
-bool ED_gizmo_poll_or_unlink_delayed_from_tool(
- const struct bContext *C, struct wmGizmoGroupType *gzgt);
+bool ED_gizmo_poll_or_unlink_delayed_from_tool(const struct bContext *C,
+ struct wmGizmoGroupType *gzgt);
-#endif /* __ED_GIZMO_UTILS_H__ */
+#endif /* __ED_GIZMO_UTILS_H__ */
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index 1f86a8c7f46..ac998cbcb71 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -67,22 +67,22 @@ struct wmWindowManager;
* 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 */
+ 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 */
} tGPspoint;
/* 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;
+ struct Base *base;
+ float zdepth;
} tGPencilSort;
/* ----------- Grease Pencil Tools/Context ------------- */
@@ -90,26 +90,24 @@ typedef struct tGPencilSort {
/* Context-dependent */
struct bGPdata **ED_gpencil_data_get_pointers(const struct bContext *C, struct PointerRNA *r_ptr);
-struct bGPdata *ED_gpencil_data_get_active(const struct bContext *C);
-struct bGPdata *ED_gpencil_data_get_active_evaluated(const struct bContext *C);
+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 ID *screen_id,
- struct ScrArea *sa,
- struct Scene *scene,
- struct Object *ob,
- struct PointerRNA *r_ptr);
-struct bGPdata *ED_gpencil_data_get_active_direct(
- struct ID *screen_id,
- struct ScrArea *sa,
- struct Scene *scene,
- struct Object *ob);
+struct bGPdata **ED_gpencil_data_get_pointers_direct(struct ID *screen_id,
+ struct ScrArea *sa,
+ struct Scene *scene,
+ struct Object *ob,
+ struct PointerRNA *r_ptr);
+struct bGPdata *ED_gpencil_data_get_active_direct(struct ID *screen_id,
+ struct ScrArea *sa,
+ struct Scene *scene,
+ struct Object *ob);
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);
+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);
@@ -117,7 +115,9 @@ bool ED_gpencil_has_keyframe_v3d(struct Scene *scene, struct Object *ob, int cfr
bool ED_gpencil_stroke_can_use_direct(const struct ScrArea *sa, 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, const struct bGPDstroke *gps);
+bool ED_gpencil_stroke_color_use(struct Object *ob,
+ const struct bGPDlayer *gpl,
+ const struct bGPDstroke *gps);
/* ----------- Grease Pencil Operators ----------------- */
@@ -131,67 +131,78 @@ void ED_operatormacros_gpencil(void);
/* Strokes copybuf */
void ED_gpencil_strokes_copybuf_free(void);
-
/* ------------ Grease-Pencil Drawing API ------------------ */
/* drawgpencil.c */
void ED_annotation_draw_2dimage(const struct bContext *C);
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,
- bool only3d);
-void ED_annotation_draw_ex(
- struct Scene *scene,
- struct bGPdata *gpd, int winx, int winy,
- const int cfra, const char spacetype);
+void ED_annotation_draw_view3d(struct Scene *scene,
+ struct Depsgraph *depsgraph,
+ struct View3D *v3d,
+ struct ARegion *ar,
+ bool only3d);
+void ED_annotation_draw_ex(struct Scene *scene,
+ struct bGPdata *gpd,
+ int winx,
+ int winy,
+ const int cfra,
+ const char spacetype);
/* ----------- Grease-Pencil AnimEdit API ------------------ */
-bool ED_gplayer_frames_looper(struct bGPDlayer *gpl, struct Scene *scene,
- short (*gpf_cb)(struct bGPDframe *, struct Scene *));
+bool ED_gplayer_frames_looper(struct bGPDlayer *gpl,
+ struct Scene *scene,
+ short (*gpf_cb)(struct bGPDframe *, struct Scene *));
void ED_gplayer_make_cfra_list(struct bGPDlayer *gpl, ListBase *elems, bool onlysel);
-bool ED_gplayer_frame_select_check(struct bGPDlayer *gpl);
-void ED_gplayer_frame_select_set(struct bGPDlayer *gpl, short mode);
-void ED_gplayer_frames_select_box(struct bGPDlayer *gpl, float min, float max, short select_mode);
-void ED_gplayer_frames_select_region(struct KeyframeEditData *ked, struct bGPDlayer *gpl, short tool, short select_mode);
-void ED_gpencil_select_frames(struct bGPDlayer *gpl, short select_mode);
-void ED_gpencil_select_frame(struct bGPDlayer *gpl, int selx, short select_mode);
+bool ED_gplayer_frame_select_check(struct bGPDlayer *gpl);
+void ED_gplayer_frame_select_set(struct bGPDlayer *gpl, short mode);
+void ED_gplayer_frames_select_box(struct bGPDlayer *gpl, float min, float max, short select_mode);
+void ED_gplayer_frames_select_region(struct KeyframeEditData *ked,
+ struct bGPDlayer *gpl,
+ short tool,
+ short select_mode);
+void ED_gpencil_select_frames(struct bGPDlayer *gpl, short select_mode);
+void ED_gpencil_select_frame(struct bGPDlayer *gpl, int selx, short select_mode);
-bool ED_gplayer_frames_delete(struct bGPDlayer *gpl);
-void ED_gplayer_frames_duplicate(struct bGPDlayer *gpl);
+bool ED_gplayer_frames_delete(struct bGPDlayer *gpl);
+void ED_gplayer_frames_duplicate(struct bGPDlayer *gpl);
void ED_gplayer_frames_keytype_set(struct bGPDlayer *gpl, short type);
-void ED_gplayer_snap_frames(struct bGPDlayer *gpl, struct Scene *scene, short mode);
-void ED_gplayer_mirror_frames(struct bGPDlayer *gpl, struct Scene *scene, short mode);
+void ED_gplayer_snap_frames(struct bGPDlayer *gpl, struct Scene *scene, short mode);
+void ED_gplayer_mirror_frames(struct bGPDlayer *gpl, struct Scene *scene, short mode);
void ED_gpencil_anim_copybuf_free(void);
bool ED_gpencil_anim_copybuf_copy(struct bAnimContext *ac);
bool ED_gpencil_anim_copybuf_paste(struct bAnimContext *ac, const short copy_mode);
-
/* ------------ Grease-Pencil Undo System ------------------ */
int ED_gpencil_session_active(void);
int ED_undo_gpencil_step(struct bContext *C, int step, const char *name);
/* ------------ Grease-Pencil Armature weights ------------------ */
-bool ED_gpencil_add_armature_weights(
- const struct bContext *C, struct ReportList *reports,
- struct Object *ob, struct Object *ob_arm, int mode);
+bool ED_gpencil_add_armature_weights(const struct bContext *C,
+ struct ReportList *reports,
+ struct Object *ob,
+ struct Object *ob_arm,
+ int mode);
/* keep this aligned with gpencil_armature enum */
-#define GP_PAR_ARMATURE_NAME 0
-#define GP_PAR_ARMATURE_AUTO 1
+#define GP_PAR_ARMATURE_NAME 0
+#define GP_PAR_ARMATURE_AUTO 1
/* ------------ 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]);
+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, struct bGPdata *gpd);
+void ED_gpencil_reset_layers_parent(struct Depsgraph *depsgraph,
+ struct Object *obact,
+ struct bGPdata *gpd);
/* cursor utilities */
void ED_gpencil_brush_draw_eraser(struct Brush *brush, int x, int y);
@@ -202,25 +213,34 @@ void ED_gpencil_create_monkey(struct bContext *C, struct Object *ob, float mat[4
void ED_gpencil_create_stroke(struct bContext *C, struct Object *ob, float mat[4][4]);
/* ------------ Object Utilities ------------ */
-struct Object *ED_gpencil_add_object(
- struct bContext *C, struct Scene *scene, const float loc[3], unsigned short local_view_bits);
+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);
/* set object modes */
void ED_gpencil_setup_modes(struct bContext *C, struct bGPdata *gpd, int newmode);
-void ED_gp_project_stroke_to_plane(
- const struct Scene *scene,
- const struct Object *ob, const struct RegionView3D *rv3d,
- struct bGPDstroke *gps, const float origin[3], const int axis);
-void ED_gp_project_point_to_plane(
- const struct Scene *scene,
- const struct Object *ob, const struct RegionView3D *rv3d,
- 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_project_stroke_to_view(
- struct bContext *C, struct bGPDlayer *gpl, struct bGPDstroke *gps);
+void ED_gp_project_stroke_to_plane(const struct Scene *scene,
+ const struct Object *ob,
+ const struct RegionView3D *rv3d,
+ struct bGPDstroke *gps,
+ const float origin[3],
+ const int axis);
+void ED_gp_project_point_to_plane(const struct Scene *scene,
+ const struct Object *ob,
+ const struct RegionView3D *rv3d,
+ 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_project_stroke_to_view(struct bContext *C,
+ struct bGPDlayer *gpl,
+ struct bGPDstroke *gps);
/* set sculpt cursor */
void ED_gpencil_toggle_brush_cursor(struct bContext *C, bool enable, void *customdata);
@@ -235,7 +255,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, float origin[3], const struct tGPspoint *tpt, struct bGPDspoint *pt);
+void ED_gpencil_tpoint_to_point(struct ARegion *ar,
+ 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);
@@ -246,11 +269,14 @@ void ED_gpencil_update_color_uv(struct Main *bmain, struct Material *mat);
* 2 - Hit in point B
* 3 - Hit in point A and B
*/
-int ED_gpencil_select_stroke_segment(
- struct bGPDlayer *gpl,
- struct bGPDstroke *gps, struct bGPDspoint *pt,
- bool select, bool insert, const float scale,
- float r_hita[3], float r_hitb[3]);
+int ED_gpencil_select_stroke_segment(struct bGPDlayer *gpl,
+ struct bGPDstroke *gps,
+ struct bGPDspoint *pt,
+ bool select,
+ bool insert,
+ const float scale,
+ float r_hita[3],
+ float r_hitb[3]);
void ED_gpencil_select_toggle_all(struct bContext *C, int action);
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index bc5e21e4e08..ba5a6a8a339 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -37,12 +37,19 @@ struct wmWindowManager;
/* image_edit.c, exported for transform */
struct Image *ED_space_image(struct SpaceImage *sima);
-void ED_space_image_set(struct Main *bmain, struct SpaceImage *sima, struct Object *obedit, struct Image *ima, bool automatic);
-void ED_space_image_auto_set(const struct bContext *C, struct SpaceImage *sima);
-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);
+void ED_space_image_set(struct Main *bmain,
+ struct SpaceImage *sima,
+ struct Object *obedit,
+ struct Image *ima,
+ bool automatic);
+void ED_space_image_auto_set(const struct bContext *C, struct SpaceImage *sima);
+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, int mval[2], float r_col[3]);
+bool ED_space_image_color_sample(struct SpaceImage *sima,
+ struct ARegion *ar,
+ int mval[2],
+ float r_col[3]);
struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **r_lock);
void ED_space_image_release_buffer(struct SpaceImage *sima, struct ImBuf *ibuf, void *lock);
bool ED_space_image_has_buffer(struct SpaceImage *sima);
@@ -50,18 +57,35 @@ 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_zoom(struct SpaceImage *sima, struct ARegion *ar, float *zoomx, float *zoomy);
+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);
-void ED_space_image_scopes_update(const struct bContext *C, struct SpaceImage *sima, struct ImBuf *ibuf, bool use_view_settings);
+void ED_space_image_scopes_update(const struct bContext *C,
+ struct SpaceImage *sima,
+ struct ImBuf *ibuf,
+ bool use_view_settings);
-void ED_space_image_paint_update(struct Main *bmain, struct wmWindowManager *wm, struct Scene *scene);
-void ED_space_image_uv_sculpt_update(struct Main *bmain, struct wmWindowManager *wm, struct Scene *scene);
+void ED_space_image_paint_update(struct Main *bmain,
+ struct wmWindowManager *wm,
+ struct Scene *scene);
+void ED_space_image_uv_sculpt_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_mouse_pos(struct SpaceImage *sima, struct ARegion *ar, const int mval[2], float co[2]);
-void ED_image_point_pos(struct SpaceImage *sima, struct ARegion *ar, float x, float y, float *xr, float *yr);
-void ED_image_point_pos__reverse(struct SpaceImage *sima, struct ARegion *ar, const float co[2], float r_co[2]);
+void ED_image_mouse_pos(struct SpaceImage *sima,
+ struct ARegion *ar,
+ const int mval[2],
+ float co[2]);
+void ED_image_point_pos(
+ struct SpaceImage *sima, struct ARegion *ar, float x, float y, float *xr, float *yr);
+void ED_image_point_pos__reverse(struct SpaceImage *sima,
+ struct ARegion *ar,
+ const float co[2],
+ float r_co[2]);
bool ED_image_slot_cycle(struct Image *image, int direction);
bool ED_space_image_show_render(struct SpaceImage *sima);
@@ -74,8 +98,18 @@ bool ED_space_image_check_show_maskedit(struct SpaceImage *sima, struct ViewLaye
bool ED_space_image_maskedit_poll(struct bContext *C);
bool ED_space_image_maskedit_mask_poll(struct bContext *C);
-void ED_image_draw_info(struct Scene *scene, struct ARegion *ar, bool color_manage, bool use_default_view, int channels, int x, int y,
- const unsigned char cp[4], const float fp[4], const float linearcol[4], int *zp, float *zpf);
+void ED_image_draw_info(struct Scene *scene,
+ struct ARegion *ar,
+ bool color_manage,
+ bool use_default_view,
+ int channels,
+ int x,
+ int y,
+ const unsigned char cp[4],
+ const float fp[4],
+ const float linearcol[4],
+ int *zp,
+ float *zpf);
bool ED_space_image_show_cache(struct SpaceImage *sima);
diff --git a/source/blender/editors/include/ED_info.h b/source/blender/editors/include/ED_info.h
index 118295a80e0..8a84d3646f8 100644
--- a/source/blender/editors/include/ED_info.h
+++ b/source/blender/editors/include/ED_info.h
@@ -27,6 +27,8 @@ 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_stats_string(struct Main *bmain,
+ struct Scene *scene,
+ struct ViewLayer *view_layer);
#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 5c97dc835d1..9fa8996c384 100644
--- a/source/blender/editors/include/ED_keyframes_draw.h
+++ b/source/blender/editors/include/ED_keyframes_draw.h
@@ -44,143 +44,218 @@ struct bGPDlayer;
/* Information about the stretch of time from current to the next column */
typedef struct ActKeyBlockInfo {
- /* Combination of flags from all curves. */
- short flag;
- /* Mask of flags that differ between curves. */
- short conflict;
+ /* Combination of flags from all curves. */
+ short flag;
+ /* Mask of flags that differ between curves. */
+ short conflict;
- /* Selection flag. */
- char sel;
+ /* Selection flag. */
+ char sel;
} ActKeyBlockInfo;
/* Keyframe Column Struct */
typedef struct ActKeyColumn {
- /* ListBase linkage */
- struct ActKeyColumn *next, *prev;
-
- /* sorting-tree linkage */
- /** 'children' of this node, less than and greater than it (respectively) */
- struct ActKeyColumn *left, *right;
- /** parent of this node in the tree */
- struct ActKeyColumn *parent;
- /** DLRB_BLACK or DLRB_RED */
- char tree_col;
-
- /* keyframe info */
- /** eBezTripe_KeyframeType */
- char key_type;
- /** eKeyframeHandleDrawOpts */
- char handle_type;
- /** eKeyframeExtremeDrawOpts */
- char extreme_type;
- short sel;
- float cfra;
-
- /* key-block info */
- ActKeyBlockInfo block;
-
- /* number of curves and keys in this column */
- short totcurve, totkey, totblock;
+ /* ListBase linkage */
+ struct ActKeyColumn *next, *prev;
+
+ /* sorting-tree linkage */
+ /** 'children' of this node, less than and greater than it (respectively) */
+ struct ActKeyColumn *left, *right;
+ /** parent of this node in the tree */
+ struct ActKeyColumn *parent;
+ /** DLRB_BLACK or DLRB_RED */
+ char tree_col;
+
+ /* keyframe info */
+ /** eBezTripe_KeyframeType */
+ char key_type;
+ /** eKeyframeHandleDrawOpts */
+ char handle_type;
+ /** eKeyframeExtremeDrawOpts */
+ char extreme_type;
+ short sel;
+ float cfra;
+
+ /* key-block info */
+ ActKeyBlockInfo block;
+
+ /* number of curves and keys in this column */
+ short totcurve, totkey, totblock;
} ActKeyColumn;
/* ActKeyBlockInfo - Flag */
typedef enum eActKeyBlock_Hold {
- /* Key block represents a moving hold */
- ACTKEYBLOCK_FLAG_MOVING_HOLD = (1 << 0),
- /* Key block represents a static hold */
- ACTKEYBLOCK_FLAG_STATIC_HOLD = (1 << 1),
- /* Key block represents any kind of hold */
- ACTKEYBLOCK_FLAG_ANY_HOLD = (1 << 2),
- /* The curve segment uses non-bezier interpolation */
- ACTKEYBLOCK_FLAG_NON_BEZIER = (1 << 3),
+ /* Key block represents a moving hold */
+ ACTKEYBLOCK_FLAG_MOVING_HOLD = (1 << 0),
+ /* Key block represents a static hold */
+ ACTKEYBLOCK_FLAG_STATIC_HOLD = (1 << 1),
+ /* Key block represents any kind of hold */
+ ACTKEYBLOCK_FLAG_ANY_HOLD = (1 << 2),
+ /* The curve segment uses non-bezier interpolation */
+ ACTKEYBLOCK_FLAG_NON_BEZIER = (1 << 3),
} eActKeyBlock_Flag;
/* *********************** Keyframe Drawing ****************************** */
/* options for keyframe shape drawing */
typedef enum eKeyframeShapeDrawOpts {
- /* only the border */
- KEYFRAME_SHAPE_FRAME = 0,
- /* only the inside filling */
- KEYFRAME_SHAPE_INSIDE,
- /* the whole thing */
- KEYFRAME_SHAPE_BOTH,
+ /* only the border */
+ KEYFRAME_SHAPE_FRAME = 0,
+ /* only the inside filling */
+ KEYFRAME_SHAPE_INSIDE,
+ /* the whole thing */
+ KEYFRAME_SHAPE_BOTH,
} eKeyframeShapeDrawOpts;
/* Handle type. */
typedef enum eKeyframeHandleDrawOpts {
- /* Don't draw */
- KEYFRAME_HANDLE_NONE = 0,
- /* Various marks in order of increasing display priority. */
- KEYFRAME_HANDLE_AUTO_CLAMP,
- KEYFRAME_HANDLE_AUTO,
- KEYFRAME_HANDLE_VECTOR,
- KEYFRAME_HANDLE_ALIGNED,
- KEYFRAME_HANDLE_FREE,
+ /* Don't draw */
+ KEYFRAME_HANDLE_NONE = 0,
+ /* Various marks in order of increasing display priority. */
+ KEYFRAME_HANDLE_AUTO_CLAMP,
+ KEYFRAME_HANDLE_AUTO,
+ KEYFRAME_HANDLE_VECTOR,
+ KEYFRAME_HANDLE_ALIGNED,
+ KEYFRAME_HANDLE_FREE,
} eKeyframeHandleDrawOpts;
/* Extreme type. */
typedef enum eKeyframeExtremeDrawOpts {
- KEYFRAME_EXTREME_NONE = 0,
- /* Minimum/maximum present. */
- KEYFRAME_EXTREME_MIN = (1 << 0),
- KEYFRAME_EXTREME_MAX = (1 << 1),
- /* Grouped keys have different states. */
- KEYFRAME_EXTREME_MIXED = (1 << 2),
- /* Both neigbors are equal to this key. */
- KEYFRAME_EXTREME_FLAT = (1 << 3),
+ KEYFRAME_EXTREME_NONE = 0,
+ /* Minimum/maximum present. */
+ KEYFRAME_EXTREME_MIN = (1 << 0),
+ KEYFRAME_EXTREME_MAX = (1 << 1),
+ /* Grouped keys have different states. */
+ KEYFRAME_EXTREME_MIXED = (1 << 2),
+ /* Both neigbors are equal to this key. */
+ KEYFRAME_EXTREME_FLAT = (1 << 3),
} eKeyframeExtremeDrawOpts;
/* draw simple diamond-shape keyframe */
/* caller should set up vertex format, bind GPU_SHADER_KEYFRAME_DIAMOND,
* immBegin(GPU_PRIM_POINTS, n), then call this n times */
-void draw_keyframe_shape(float x, float y, float size, bool sel, 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 linemask_id, short ipo_type, short extreme_type);
+void draw_keyframe_shape(float x,
+ float y,
+ float size,
+ bool sel,
+ 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 linemask_id,
+ short ipo_type,
+ short extreme_type);
/* ******************************* Methods ****************************** */
/* Channel Drawing ------------------ */
/* F-Curve */
-void draw_fcurve_channel(struct View2D *v2d, struct AnimData *adt, struct FCurve *fcu, float ypos, float yscale_fac, int saction_flag);
+void draw_fcurve_channel(struct View2D *v2d,
+ struct AnimData *adt,
+ struct FCurve *fcu,
+ float ypos,
+ float yscale_fac,
+ int saction_flag);
/* Action Group Summary */
-void draw_agroup_channel(struct View2D *v2d, struct AnimData *adt, struct bActionGroup *agrp, float ypos, float yscale_fac, int saction_flag);
+void draw_agroup_channel(struct View2D *v2d,
+ struct AnimData *adt,
+ struct bActionGroup *agrp,
+ float ypos,
+ float yscale_fac,
+ int saction_flag);
/* Action Summary */
-void draw_action_channel(struct View2D *v2d, struct AnimData *adt, struct bAction *act, float ypos, float yscale_fac, int saction_flag);
+void draw_action_channel(struct View2D *v2d,
+ struct AnimData *adt,
+ struct bAction *act,
+ float ypos,
+ float yscale_fac,
+ int saction_flag);
/* Object Summary */
-void draw_object_channel(struct View2D *v2d, struct bDopeSheet *ads, struct Object *ob, float ypos, float yscale_fac, int saction_flag);
+void draw_object_channel(struct View2D *v2d,
+ struct bDopeSheet *ads,
+ struct Object *ob,
+ float ypos,
+ float yscale_fac,
+ int saction_flag);
/* Scene Summary */
-void draw_scene_channel(struct View2D *v2d, struct bDopeSheet *ads, struct Scene *sce, float ypos, float yscale_fac, int saction_flag);
+void draw_scene_channel(struct View2D *v2d,
+ struct bDopeSheet *ads,
+ struct Scene *sce,
+ float ypos,
+ float yscale_fac,
+ int saction_flag);
/* DopeSheet Summary */
-void draw_summary_channel(struct View2D *v2d, struct bAnimContext *ac, float ypos, float yscale_fac, int saction_flag);
+void draw_summary_channel(
+ struct View2D *v2d, struct bAnimContext *ac, float ypos, float yscale_fac, int saction_flag);
/* Grease Pencil datablock summary */
-void draw_gpencil_channel(struct View2D *v2d, struct bDopeSheet *ads, struct bGPdata *gpd, float ypos, float yscale_fac, int saction_flag);
+void draw_gpencil_channel(struct View2D *v2d,
+ struct bDopeSheet *ads,
+ struct bGPdata *gpd,
+ float ypos,
+ float yscale_fac,
+ int saction_flag);
/* Grease Pencil Layer */
-void draw_gpl_channel(struct View2D *v2d, struct bDopeSheet *ads, struct bGPDlayer *gpl, float ypos, float yscale_fac, int saction_flag);
+void draw_gpl_channel(struct View2D *v2d,
+ struct bDopeSheet *ads,
+ struct bGPDlayer *gpl,
+ float ypos,
+ float yscale_fac,
+ int saction_flag);
/* Mask Layer */
-void draw_masklay_channel(struct View2D *v2d, struct bDopeSheet *ads, struct MaskLayer *masklay, float ypos, float yscale_fac, int saction_flag);
+void draw_masklay_channel(struct View2D *v2d,
+ struct bDopeSheet *ads,
+ struct MaskLayer *masklay,
+ float ypos,
+ float yscale_fac,
+ int saction_flag);
/* Keydata Generation --------------- */
/* F-Curve */
-void fcurve_to_keylist(struct AnimData *adt, struct FCurve *fcu, struct DLRBT_Tree *keys, int saction_flag);
+void fcurve_to_keylist(struct AnimData *adt,
+ struct FCurve *fcu,
+ struct DLRBT_Tree *keys,
+ int saction_flag);
/* Action Group */
-void agroup_to_keylist(struct AnimData *adt, struct bActionGroup *agrp, struct DLRBT_Tree *keys, int saction_flag);
+void agroup_to_keylist(struct AnimData *adt,
+ struct bActionGroup *agrp,
+ struct DLRBT_Tree *keys,
+ int saction_flag);
/* Action */
-void action_to_keylist(struct AnimData *adt, struct bAction *act, struct DLRBT_Tree *keys, int saction_flag);
+void action_to_keylist(struct AnimData *adt,
+ struct bAction *act,
+ struct DLRBT_Tree *keys,
+ int saction_flag);
/* Object */
-void ob_to_keylist(struct bDopeSheet *ads, struct Object *ob, struct DLRBT_Tree *keys, int saction_flag);
+void ob_to_keylist(struct bDopeSheet *ads,
+ struct Object *ob,
+ struct DLRBT_Tree *keys,
+ int saction_flag);
/* Cache File */
-void cachefile_to_keylist(struct bDopeSheet *ads, struct CacheFile *cache_file, struct DLRBT_Tree *keys, int saction_flag);
+void cachefile_to_keylist(struct bDopeSheet *ads,
+ struct CacheFile *cache_file,
+ struct DLRBT_Tree *keys,
+ int saction_flag);
/* Scene */
-void scene_to_keylist(struct bDopeSheet *ads, struct Scene *sce, struct DLRBT_Tree *keys, int saction_flag);
+void scene_to_keylist(struct bDopeSheet *ads,
+ struct Scene *sce,
+ struct DLRBT_Tree *keys,
+ int saction_flag);
/* DopeSheet Summary */
void summary_to_keylist(struct bAnimContext *ac, struct DLRBT_Tree *keys, int saction_flag);
/* Grease Pencil datablock summary */
-void gpencil_to_keylist(struct bDopeSheet *ads, struct bGPdata *gpd, struct DLRBT_Tree *keys, const bool active);
+void gpencil_to_keylist(struct bDopeSheet *ads,
+ struct bGPdata *gpd,
+ struct DLRBT_Tree *keys,
+ const bool active);
/* Grease Pencil Layer */
void gpl_to_keylist(struct bDopeSheet *ads, struct bGPDlayer *gpl, struct DLRBT_Tree *keys);
/* Mask */
-void mask_to_keylist(struct bDopeSheet *UNUSED(ads), struct MaskLayer *masklay, struct DLRBT_Tree *keys);
+void mask_to_keylist(struct bDopeSheet *UNUSED(ads),
+ struct MaskLayer *masklay,
+ struct DLRBT_Tree *keys);
/* ActKeyColumn API ---------------- */
/* Comparator callback used for ActKeyColumns and cframe float-value pointer */
@@ -192,4 +267,4 @@ 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);
-#endif /* __ED_KEYFRAMES_DRAW_H__ */
+#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 266eb3850b3..99a13dc6a87 100644
--- a/source/blender/editors/include/ED_keyframes_edit.h
+++ b/source/blender/editors/include/ED_keyframes_edit.h
@@ -38,81 +38,80 @@ struct bDopeSheet;
/* bezt validation */
typedef enum eEditKeyframes_Validate {
- /* Frame range */
- BEZT_OK_FRAME = 1,
- BEZT_OK_FRAMERANGE,
- /* Selection status */
- BEZT_OK_SELECTED,
- /* Values (y-val) only */
- BEZT_OK_VALUE,
- BEZT_OK_VALUERANGE,
- /* For graph editor keyframes (2D tests) */
- BEZT_OK_REGION,
- BEZT_OK_REGION_LASSO,
- BEZT_OK_REGION_CIRCLE,
- /* Only for keyframes a certain Dopesheet channel */
- BEZT_OK_CHANNEL_LASSO,
- BEZT_OK_CHANNEL_CIRCLE,
+ /* Frame range */
+ BEZT_OK_FRAME = 1,
+ BEZT_OK_FRAMERANGE,
+ /* Selection status */
+ BEZT_OK_SELECTED,
+ /* Values (y-val) only */
+ BEZT_OK_VALUE,
+ BEZT_OK_VALUERANGE,
+ /* For graph editor keyframes (2D tests) */
+ BEZT_OK_REGION,
+ BEZT_OK_REGION_LASSO,
+ BEZT_OK_REGION_CIRCLE,
+ /* Only for keyframes a certain Dopesheet channel */
+ BEZT_OK_CHANNEL_LASSO,
+ BEZT_OK_CHANNEL_CIRCLE,
} eEditKeyframes_Validate;
/* ------------ */
/* select modes */
typedef enum eEditKeyframes_Select {
- /* SELECT_SUBTRACT for all, followed by SELECT_ADD for some */
- SELECT_REPLACE = (1 << 0),
- /* add ok keyframes to selection */
- SELECT_ADD = (1 << 1),
- /* remove ok keyframes from selection */
- SELECT_SUBTRACT = (1 << 2),
- /* flip ok status of keyframes based on key status */
- SELECT_INVERT = (1 << 3),
+ /* SELECT_SUBTRACT for all, followed by SELECT_ADD for some */
+ SELECT_REPLACE = (1 << 0),
+ /* add ok keyframes to selection */
+ SELECT_ADD = (1 << 1),
+ /* remove ok keyframes from selection */
+ SELECT_SUBTRACT = (1 << 2),
+ /* flip ok status of keyframes based on key status */
+ SELECT_INVERT = (1 << 3),
} eEditKeyframes_Select;
/* "selection map" building modes */
typedef enum eEditKeyframes_SelMap {
- SELMAP_MORE = 0,
- SELMAP_LESS,
+ SELMAP_MORE = 0,
+ SELMAP_LESS,
} eEditKeyframes_SelMap;
/* snapping tools */
typedef enum eEditKeyframes_Snap {
- SNAP_KEYS_CURFRAME = 1,
- SNAP_KEYS_NEARFRAME,
- SNAP_KEYS_NEARSEC,
- SNAP_KEYS_NEARMARKER,
- SNAP_KEYS_HORIZONTAL,
- SNAP_KEYS_VALUE,
- SNAP_KEYS_TIME,
+ SNAP_KEYS_CURFRAME = 1,
+ SNAP_KEYS_NEARFRAME,
+ SNAP_KEYS_NEARSEC,
+ SNAP_KEYS_NEARMARKER,
+ SNAP_KEYS_HORIZONTAL,
+ SNAP_KEYS_VALUE,
+ SNAP_KEYS_TIME,
} eEditKeyframes_Snap;
/* mirroring tools */
typedef enum eEditKeyframes_Mirror {
- MIRROR_KEYS_CURFRAME = 1,
- MIRROR_KEYS_YAXIS,
- MIRROR_KEYS_XAXIS,
- MIRROR_KEYS_MARKER,
- MIRROR_KEYS_VALUE,
- MIRROR_KEYS_TIME,
+ MIRROR_KEYS_CURFRAME = 1,
+ MIRROR_KEYS_YAXIS,
+ MIRROR_KEYS_XAXIS,
+ MIRROR_KEYS_MARKER,
+ MIRROR_KEYS_VALUE,
+ MIRROR_KEYS_TIME,
} eEditKeyframes_Mirror;
/* use with BEZT_OK_REGION_LASSO */
typedef struct KeyframeEdit_LassoData {
- rctf *rectf_scaled;
- const rctf *rectf_view;
- const int (*mcords)[2];
- int mcords_tot;
+ rctf *rectf_scaled;
+ const rctf *rectf_view;
+ const int (*mcords)[2];
+ int mcords_tot;
} KeyframeEdit_LassoData;
/* use with BEZT_OK_REGION_CIRCLE */
typedef struct KeyframeEdit_CircleData {
- rctf *rectf_scaled;
- const rctf *rectf_view;
- float mval[2];
- float radius_squared;
+ rctf *rectf_scaled;
+ const rctf *rectf_view;
+ float mval[2];
+ float radius_squared;
} KeyframeEdit_CircleData;
-
/* ************************************************ */
/* Non-Destuctive Editing API (keyframes_edit.c) */
@@ -120,58 +119,58 @@ typedef struct KeyframeEdit_CircleData {
/* which verts of a keyframe is active (after polling) */
typedef enum eKeyframeVertOk {
- /* 'key' itself is ok */
- KEYFRAME_OK_KEY = (1 << 0),
- /* 'handle 1' is ok */
- KEYFRAME_OK_H1 = (1 << 1),
- /* 'handle 2' is ok */
- KEYFRAME_OK_H2 = (1 << 2),
- /* all flags */
- KEYFRAME_OK_ALL = (KEYFRAME_OK_KEY | KEYFRAME_OK_H1 | KEYFRAME_OK_H2),
+ /* 'key' itself is ok */
+ KEYFRAME_OK_KEY = (1 << 0),
+ /* 'handle 1' is ok */
+ KEYFRAME_OK_H1 = (1 << 1),
+ /* 'handle 2' is ok */
+ KEYFRAME_OK_H2 = (1 << 2),
+ /* all flags */
+ KEYFRAME_OK_ALL = (KEYFRAME_OK_KEY | KEYFRAME_OK_H1 | KEYFRAME_OK_H2),
} eKeyframeVertOk;
/* Flags for use during iteration */
typedef enum eKeyframeIterFlags {
- /* consider handles in addition to key itself */
- KEYFRAME_ITER_INCL_HANDLES = (1 << 0),
+ /* consider handles in addition to key itself */
+ KEYFRAME_ITER_INCL_HANDLES = (1 << 0),
- /* Perform NLA time remapping (global -> strip) for the "f1" parameter
- * (e.g. used for selection tools on summary tracks)
- */
- KED_F1_NLA_UNMAP = (1 << 1),
+ /* Perform NLA time remapping (global -> strip) for the "f1" parameter
+ * (e.g. used for selection tools on summary tracks)
+ */
+ KED_F1_NLA_UNMAP = (1 << 1),
- /* Perform NLA time remapping (global -> strip) for the "f2" parameter */
- KED_F2_NLA_UNMAP = (1 << 2),
+ /* Perform NLA time remapping (global -> strip) for the "f2" parameter */
+ KED_F2_NLA_UNMAP = (1 << 2),
} eKeyframeIterFlags;
/* --- Generic Properties for Keyframe Edit Tools ----- */
typedef struct KeyframeEditData {
- /* generic properties/data access */
- /** temp list for storing custom list of data to check */
- ListBase list;
- /** pointer to current scene - many tools need access to cfra/etc. */
- struct Scene *scene;
- /** pointer to custom data - usually 'Object' but also 'rectf', but could be other types too */
- void *data;
- /** storage of times/values as 'decimals' */
- float f1, f2;
- /** storage of times/values/flags as 'whole' numbers */
- int i1, i2;
-
- /* current iteration data */
- /** F-Curve that is being iterated over */
- struct FCurve *fcu;
- /** index of current keyframe being iterated over */
- int curIndex;
- /** y-position of midpoint of the channel (for the dopesheet) */
- float channel_y;
-
- /* flags */
- /** current flags for the keyframe we're reached in the iteration process */
- eKeyframeVertOk curflags;
- /** settings for iteration process */
- eKeyframeIterFlags iterflags;
+ /* generic properties/data access */
+ /** temp list for storing custom list of data to check */
+ ListBase list;
+ /** pointer to current scene - many tools need access to cfra/etc. */
+ struct Scene *scene;
+ /** pointer to custom data - usually 'Object' but also 'rectf', but could be other types too */
+ void *data;
+ /** storage of times/values as 'decimals' */
+ float f1, f2;
+ /** storage of times/values/flags as 'whole' numbers */
+ int i1, i2;
+
+ /* current iteration data */
+ /** F-Curve that is being iterated over */
+ struct FCurve *fcu;
+ /** index of current keyframe being iterated over */
+ int curIndex;
+ /** y-position of midpoint of the channel (for the dopesheet) */
+ float channel_y;
+
+ /* flags */
+ /** current flags for the keyframe we're reached in the iteration process */
+ eKeyframeVertOk curflags;
+ /** settings for iteration process */
+ eKeyframeIterFlags iterflags;
} KeyframeEditData;
/* ------- Function Pointer Typedefs ---------------- */
@@ -181,36 +180,35 @@ typedef void (*FcuEditFunc)(struct FCurve *fcu);
/* callback function that operates on the given BezTriple */
typedef short (*KeyframeEditFunc)(KeyframeEditData *ked, struct BezTriple *bezt);
-
/* ------- Custom Data Type Defines ------------------ */
/* Custom data for remapping one range to another in a fixed way */
typedef struct KeyframeEditCD_Remap {
- float oldMin, oldMax; /* old range */
- float newMin, newMax; /* new range */
+ float oldMin, oldMax; /* old range */
+ float newMin, newMax; /* new range */
} KeyframeEditCD_Remap;
/* Paste options */
typedef enum eKeyPasteOffset {
- /* paste keys starting at current frame */
- KEYFRAME_PASTE_OFFSET_CFRA_START,
- /* paste keys ending at current frame */
- KEYFRAME_PASTE_OFFSET_CFRA_END,
- /* paste keys relative to the current frame when copying */
- KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE,
- /* paste keys from original time */
- KEYFRAME_PASTE_OFFSET_NONE,
+ /* paste keys starting at current frame */
+ KEYFRAME_PASTE_OFFSET_CFRA_START,
+ /* paste keys ending at current frame */
+ KEYFRAME_PASTE_OFFSET_CFRA_END,
+ /* paste keys relative to the current frame when copying */
+ KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE,
+ /* paste keys from original time */
+ KEYFRAME_PASTE_OFFSET_NONE,
} eKeyPasteOffset;
typedef enum eKeyMergeMode {
- /* overlay existing with new keys */
- KEYFRAME_PASTE_MERGE_MIX,
- /* replace entire fcurve */
- KEYFRAME_PASTE_MERGE_OVER,
- /* overwrite keys in pasted range */
- KEYFRAME_PASTE_MERGE_OVER_RANGE,
- /* overwrite keys in pasted range (use all keyframe start & end for range) */
- KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL,
+ /* overlay existing with new keys */
+ KEYFRAME_PASTE_MERGE_MIX,
+ /* replace entire fcurve */
+ KEYFRAME_PASTE_MERGE_OVER,
+ /* overwrite keys in pasted range */
+ KEYFRAME_PASTE_MERGE_OVER_RANGE,
+ /* overwrite keys in pasted range (use all keyframe start & end for range) */
+ KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL,
} eKeyMergeMode;
/* ---------------- Looping API --------------------- */
@@ -218,15 +216,30 @@ typedef enum eKeyMergeMode {
/* functions for looping over keyframes */
/* function for working with F-Curve data only
* (i.e. when filters have been chosen to explicitly use this) */
-short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked, struct FCurve *fcu, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb);
+short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked,
+ struct FCurve *fcu,
+ KeyframeEditFunc key_ok,
+ KeyframeEditFunc key_cb,
+ FcuEditFunc fcu_cb);
/* function for working with any type (i.e. one of the known types) of animation channel
* - filterflag is bDopeSheet->flag (DOPESHEET_FILTERFLAG)
*/
-short ANIM_animchannel_keyframes_loop(KeyframeEditData *ked, struct bDopeSheet *ads, struct bAnimListElem *ale, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb);
+short ANIM_animchannel_keyframes_loop(KeyframeEditData *ked,
+ struct bDopeSheet *ads,
+ struct bAnimListElem *ale,
+ KeyframeEditFunc key_ok,
+ KeyframeEditFunc key_cb,
+ FcuEditFunc fcu_cb);
/* same as above, except bAnimListElem wrapper is not needed...
* - keytype is eAnim_KeyType
*/
-short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked, struct bDopeSheet *ads, void *data, int keytype, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb);
+short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked,
+ struct bDopeSheet *ads,
+ void *data,
+ int keytype,
+ KeyframeEditFunc key_ok,
+ KeyframeEditFunc key_cb,
+ FcuEditFunc fcu_cb);
/* functions for making sure all keyframes are in good order */
void ANIM_editkeyframes_refresh(struct bAnimContext *ac);
@@ -274,14 +287,9 @@ void bezt_remap_times(KeyframeEditData *ked, struct BezTriple *bezt);
/* XXX: These are temporary,
* until we can unify GP/Mask Keyframe handling and standard FCurve Keyframe handling */
-bool keyframe_region_lasso_test(
- const KeyframeEdit_LassoData *data_lasso,
- const float xy[2]);
-
-bool keyframe_region_circle_test(
- const KeyframeEdit_CircleData *data_circle,
- const float xy[2]);
+bool keyframe_region_lasso_test(const KeyframeEdit_LassoData *data_lasso, const float xy[2]);
+bool keyframe_region_circle_test(const KeyframeEdit_CircleData *data_circle, const float xy[2]);
/* ************************************************ */
/* Destructive Editing API (keyframes_general.c) */
@@ -291,7 +299,10 @@ bool delete_fcurve_keys(struct FCurve *fcu);
void clear_fcurve_keys(struct FCurve *fcu);
void duplicate_fcurve_keys(struct FCurve *fcu);
-void clean_fcurve(struct bAnimContext *ac, struct bAnimListElem *ale, float thresh, bool cleardefault);
+void clean_fcurve(struct bAnimContext *ac,
+ struct bAnimListElem *ale,
+ float thresh,
+ bool cleardefault);
void smooth_fcurve(struct FCurve *fcu);
void sample_fcurve(struct FCurve *fcu);
@@ -299,8 +310,11 @@ void sample_fcurve(struct FCurve *fcu);
void ANIM_fcurves_copybuf_free(void);
short copy_animedit_keys(struct bAnimContext *ac, ListBase *anim_data);
-short paste_animedit_keys(struct bAnimContext *ac, ListBase *anim_data,
- const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip);
+short paste_animedit_keys(struct bAnimContext *ac,
+ ListBase *anim_data,
+ const eKeyPasteOffset offset_mode,
+ const eKeyMergeMode merge_mode,
+ bool flip);
/* ************************************************ */
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index 5191978c529..54570938de1 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -72,8 +72,13 @@ struct bAction *verify_adt_action(struct Main *bmain, struct ID *id, short add);
/* 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 *verify_fcurve(struct Main *bmain,
+ struct bAction *act,
+ const char group[],
+ struct PointerRNA *ptr,
+ const char rna_path[],
+ const int array_index,
+ short add);
/* -------- */
@@ -81,7 +86,9 @@ struct FCurve *verify_fcurve(struct Main *bmain, struct bAction *act, const char
* Update integer/discrete flags of the FCurve (used when creating/inserting keyframes,
* but also through RNA when editing an ID prop, see T37103).
*/
-void update_autoflags_fcurve(struct FCurve *fcu, struct bContext *C, struct ReportList *reports,
+void update_autoflags_fcurve(struct FCurve *fcu,
+ struct bContext *C,
+ struct ReportList *reports,
struct PointerRNA *ptr);
/* -------- */
@@ -97,7 +104,8 @@ int insert_bezt_fcurve(struct FCurve *fcu, const struct BezTriple *bezt, eInsert
* already exists. It will insert a keyframe using the current value being keyframed.
* Returns the index at which a keyframe was added (or -1 if failed)
*/
-int insert_vert_fcurve(struct FCurve *fcu, float x, float y, eBezTriple_KeyframeType keytype, eInsertKeyFlags flag);
+int insert_vert_fcurve(
+ struct FCurve *fcu, float x, float y, eBezTriple_KeyframeType keytype, eInsertKeyFlags flag);
/* -------- */
@@ -105,7 +113,15 @@ int insert_vert_fcurve(struct FCurve *fcu, float x, float y, eBezTriple_Keyframe
* Use this to insert a keyframe using the current value being keyframed, in the
* nominated F-Curve (no creation of animation data performed). Returns success.
*/
-bool insert_keyframe_direct(struct Depsgraph *depsgraph, struct ReportList *reports, struct PointerRNA ptr, struct PropertyRNA *prop, struct FCurve *fcu, float cfra, eBezTriple_KeyframeType keytype, struct NlaKeyframingContext *nla, eInsertKeyFlags flag);
+bool insert_keyframe_direct(struct Depsgraph *depsgraph,
+ struct ReportList *reports,
+ struct PointerRNA ptr,
+ struct PropertyRNA *prop,
+ struct FCurve *fcu,
+ float cfra,
+ eBezTriple_KeyframeType keytype,
+ struct NlaKeyframingContext *nla,
+ eInsertKeyFlags flag);
/* -------- */
@@ -113,16 +129,31 @@ bool insert_keyframe_direct(struct Depsgraph *depsgraph, struct ReportList *repo
* 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 Depsgraph *depsgraph, 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);
+short insert_keyframe(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ 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);
+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);
/* ************ Keying Sets ********************** */
@@ -133,60 +164,66 @@ struct KeyingSetInfo;
/* Polling Callback for KeyingSets */
typedef bool (*cbKeyingSet_Poll)(struct KeyingSetInfo *ksi, struct bContext *C);
/* Context Iterator Callback for KeyingSets */
-typedef void (*cbKeyingSet_Iterator)(struct KeyingSetInfo *ksi, struct bContext *C, struct KeyingSet *ks);
+typedef void (*cbKeyingSet_Iterator)(struct KeyingSetInfo *ksi,
+ struct bContext *C,
+ struct KeyingSet *ks);
/* Property Specifier Callback for KeyingSets (called from iterators) */
-typedef void (*cbKeyingSet_Generate)(struct KeyingSetInfo *ksi, struct bContext *C, struct KeyingSet *ks, struct PointerRNA *ptr);
-
+typedef void (*cbKeyingSet_Generate)(struct KeyingSetInfo *ksi,
+ struct bContext *C,
+ struct KeyingSet *ks,
+ struct PointerRNA *ptr);
/* Callback info for 'Procedural' KeyingSets to use */
typedef struct KeyingSetInfo {
- struct KeyingSetInfo *next, *prev;
-
- /* info */
- /* identifier used for class name, which KeyingSet instances reference as "Typeinfo Name" */
- char idname[64];
- /* identifier so that user can hook this up to a KeyingSet (used as label). */
- char name[64];
- /* short help/description. */
- char description[240]; /* RNA_DYN_DESCR_MAX */
- /* keying settings */
- short keyingflag;
-
- /* polling callbacks */
- /* callback for polling the context for whether the right data is available */
- cbKeyingSet_Poll poll;
-
- /* generate callbacks */
- /* iterator to use to go through collections of data in context
- * - this callback is separate from the 'adding' stage, allowing
- * BuiltIn KeyingSets to be manually specified to use
- */
- cbKeyingSet_Iterator iter;
- /* generator to use to add properties based on the data found by iterator */
- cbKeyingSet_Generate generate;
-
- /* RNA integration */
- struct ExtensionRNA ext;
+ struct KeyingSetInfo *next, *prev;
+
+ /* info */
+ /* identifier used for class name, which KeyingSet instances reference as "Typeinfo Name" */
+ char idname[64];
+ /* identifier so that user can hook this up to a KeyingSet (used as label). */
+ char name[64];
+ /* short help/description. */
+ char description[240]; /* RNA_DYN_DESCR_MAX */
+ /* keying settings */
+ short keyingflag;
+
+ /* polling callbacks */
+ /* callback for polling the context for whether the right data is available */
+ cbKeyingSet_Poll poll;
+
+ /* generate callbacks */
+ /* iterator to use to go through collections of data in context
+ * - this callback is separate from the 'adding' stage, allowing
+ * BuiltIn KeyingSets to be manually specified to use
+ */
+ cbKeyingSet_Iterator iter;
+ /* generator to use to add properties based on the data found by iterator */
+ cbKeyingSet_Generate generate;
+
+ /* RNA integration */
+ struct ExtensionRNA ext;
} KeyingSetInfo;
/* -------- */
/* Add another data source for Relative Keying Sets to be evaluated with */
-void ANIM_relative_keyingset_add_source(ListBase *dsources, struct ID *id, struct StructRNA *srna, void *data);
-
+void ANIM_relative_keyingset_add_source(ListBase *dsources,
+ struct ID *id,
+ struct StructRNA *srna,
+ void *data);
/* mode for modify_keyframes */
typedef enum eModifyKey_Modes {
- MODIFYKEY_MODE_INSERT = 0,
- MODIFYKEY_MODE_DELETE,
+ MODIFYKEY_MODE_INSERT = 0,
+ MODIFYKEY_MODE_DELETE,
} eModifyKey_Modes;
/* return codes for errors (with Relative KeyingSets) */
typedef enum eModifyKey_Returns {
- /* context info was invalid for using the Keying Set */
- MODIFYKEY_INVALID_CONTEXT = -1,
- /* there isn't any typeinfo for generating paths from context */
- MODIFYKEY_MISSING_TYPEINFO = -2,
+ /* context info was invalid for using the Keying Set */
+ MODIFYKEY_INVALID_CONTEXT = -1,
+ /* there isn't any typeinfo for generating paths from context */
+ MODIFYKEY_MISSING_TYPEINFO = -2,
} eModifyKey_Returns;
/* poll the current KeyingSet, updating it's set of paths
@@ -194,7 +231,12 @@ typedef enum eModifyKey_Returns {
short 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, ListBase *dsources, struct bAction *act, struct KeyingSet *ks, short mode, float cfra);
+int ANIM_apply_keyingset(struct bContext *C,
+ ListBase *dsources,
+ struct bAction *act,
+ struct KeyingSet *ks,
+ short mode,
+ float cfra);
/* -------- */
@@ -224,10 +266,14 @@ struct KeyingSet *ANIM_scene_get_active_keyingset(struct Scene *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, const char *tranformKSName);
+struct KeyingSet *ANIM_get_keyingset_for_autokeying(struct Scene *scene,
+ const char *tranformKSName);
/* Dynamically populate an enum of Keying Sets */
-const struct EnumPropertyItem *ANIM_keying_sets_enum_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
+const struct EnumPropertyItem *ANIM_keying_sets_enum_itemf(struct bContext *C,
+ struct PointerRNA *ptr,
+ struct PropertyRNA *prop,
+ bool *r_free);
/* Use to get the keying set from the int value used by enums. */
KeyingSet *ANIM_keyingset_get_from_enum_type(struct Scene *scene, int type);
@@ -240,27 +286,27 @@ bool ANIM_keyingset_context_ok_poll(struct bContext *C, struct KeyingSet *ks);
/* Flags for use by driver creation calls */
typedef enum eCreateDriverFlags {
- /** create drivers with a default variable for nicer UI */
- CREATEDRIVER_WITH_DEFAULT_DVAR = (1 << 0),
- /** create drivers with Generator FModifier (for backwards compat) */
- CREATEDRIVER_WITH_FMODIFIER = (1 << 1),
+ /** create drivers with a default variable for nicer UI */
+ CREATEDRIVER_WITH_DEFAULT_DVAR = (1 << 0),
+ /** create drivers with Generator FModifier (for backwards compat) */
+ CREATEDRIVER_WITH_FMODIFIER = (1 << 1),
} eCreateDriverFlags;
/* Heuristic to use for connecting target properties to driven ones */
typedef enum eCreateDriver_MappingTypes {
- /** 1 to Many - Use the specified index, and drive all elements with it */
- CREATEDRIVER_MAPPING_1_N = 0,
- /** 1 to 1 - Only for the specified index on each side */
- CREATEDRIVER_MAPPING_1_1 = 1,
- /** Many to Many - Match up the indices one by one (only for drivers on vectors/arrays) */
- CREATEDRIVER_MAPPING_N_N = 2,
-
- /** None (Single Prop):
- * Do not create driver with any targets; these will get added later instead */
- CREATEDRIVER_MAPPING_NONE = 3,
- /** None (All Properties):
- * Do not create driver with any targets; these will get added later instead */
- CREATEDRIVER_MAPPING_NONE_ALL = 4,
+ /** 1 to Many - Use the specified index, and drive all elements with it */
+ CREATEDRIVER_MAPPING_1_N = 0,
+ /** 1 to 1 - Only for the specified index on each side */
+ CREATEDRIVER_MAPPING_1_1 = 1,
+ /** Many to Many - Match up the indices one by one (only for drivers on vectors/arrays) */
+ CREATEDRIVER_MAPPING_N_N = 2,
+
+ /** None (Single Prop):
+ * Do not create driver with any targets; these will get added later instead */
+ CREATEDRIVER_MAPPING_NONE = 3,
+ /** None (All Properties):
+ * Do not create driver with any targets; these will get added later instead */
+ CREATEDRIVER_MAPPING_NONE_ALL = 4,
} eCreateDriver_MappingTypes;
/* RNA Enum of eCreateDriver_MappingTypes, for use by the appropriate operators */
@@ -271,7 +317,10 @@ extern EnumPropertyItem prop_driver_create_mapping_types[];
/* Low-level call to add a new driver F-Curve. This shouldn't be used directly for most tools,
* although there are special cases where this approach is preferable.
*/
-struct FCurve *verify_driver_fcurve(struct ID *id, const char rna_path[], const int array_index, short add);
+struct FCurve *verify_driver_fcurve(struct ID *id,
+ const char rna_path[],
+ const int array_index,
+ short add);
/* -------- */
@@ -286,23 +335,34 @@ struct FCurve *verify_driver_fcurve(struct ID *id, const char rna_path[], const
* - driver_type: eDriver_Types
* - mapping_type: eCreateDriver_MappingTypes
*/
-int ANIM_add_driver_with_target(
- struct ReportList *reports,
- struct ID *dst_id, const char dst_path[], int dst_index,
- struct ID *src_id, const char src_path[], int src_index,
- short flag, int driver_type, short mapping_type);
+int ANIM_add_driver_with_target(struct ReportList *reports,
+ struct ID *dst_id,
+ const char dst_path[],
+ int dst_index,
+ struct ID *src_id,
+ const char src_path[],
+ int src_index,
+ short flag,
+ int driver_type,
+ short mapping_type);
/* -------- */
/* Main Driver Management API calls:
* Add a new driver for the specified property on the given ID block
*/
-int ANIM_add_driver(struct ReportList *reports, struct ID *id, const char rna_path[], int array_index, short flag, int type);
+int ANIM_add_driver(struct ReportList *reports,
+ struct ID *id,
+ const char rna_path[],
+ int array_index,
+ short flag,
+ int type);
/* Main Driver Management API calls:
* Remove the driver for the specified property on the given ID block (if available)
*/
-bool ANIM_remove_driver(struct ReportList *reports, struct ID *id, const char rna_path[], int array_index, short flag);
+bool ANIM_remove_driver(
+ struct ReportList *reports, struct ID *id, const char rna_path[], int array_index, short flag);
/* -------- */
@@ -320,13 +380,15 @@ bool ANIM_driver_can_paste(void);
/* Main Driver Management API calls:
* Make a copy of the driver for the specified property on the given ID block
*/
-bool ANIM_copy_driver(struct ReportList *reports, struct ID *id, const char rna_path[], int array_index, short flag);
+bool ANIM_copy_driver(
+ struct ReportList *reports, struct ID *id, const char rna_path[], int array_index, short flag);
/* Main Driver Management API calls:
* Add a new driver for the specified property on the given ID block or replace an existing one
* with the driver + driver-curve data from the buffer
*/
-bool ANIM_paste_driver(struct ReportList *reports, struct ID *id, const char rna_path[], int array_index, short flag);
+bool ANIM_paste_driver(
+ struct ReportList *reports, struct ID *id, const char rna_path[], int array_index, short flag);
/* -------- */
@@ -351,15 +413,17 @@ bool ANIM_driver_vars_paste(struct ReportList *reports, struct FCurve *fcu, bool
/* 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))
+#define IS_AUTOKEY_ON(scene) \
+ ((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) : (U.autokey_mode == AUTOKEY_MODE_##mode))
+#define IS_AUTOKEY_MODE(scene, 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) || (U.autokey_flag & AUTOKEY_FLAG_##flag)) \
- : \
- (U.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);
@@ -375,7 +439,10 @@ bool fcurve_frame_has_keyframe(struct FCurve *fcu, float frame, short filter);
* - Returns whether the current value of a given property differs from the interpolated value.
* - Used for button drawing.
*/
-bool fcurve_is_changed(struct PointerRNA ptr, struct PropertyRNA *prop, struct FCurve *fcu, float frame);
+bool fcurve_is_changed(struct PointerRNA ptr,
+ struct PropertyRNA *prop,
+ struct FCurve *fcu,
+ float frame);
/**
* Main Keyframe Checking API call:
@@ -392,29 +459,36 @@ bool id_frame_has_keyframe(struct ID *id, float frame, short filter);
* (for v3d->keyflags)
*/
typedef enum eAnimFilterFlags {
- /* general */
- ANIMFILTER_KEYS_LOCAL = (1 << 0), /* only include locally available anim data */
- ANIMFILTER_KEYS_MUTED = (1 << 1), /* include muted elements */
- ANIMFILTER_KEYS_ACTIVE = (1 << 2), /* only include active-subelements */
-
- /* object specific */
- ANIMFILTER_KEYS_NOMAT = (1 << 9), /* don't include material keyframes */
- ANIMFILTER_KEYS_NOSKEY = (1 << 10), /* don't include shape keys (for geometry) */
+ /* general */
+ ANIMFILTER_KEYS_LOCAL = (1 << 0), /* only include locally available anim data */
+ ANIMFILTER_KEYS_MUTED = (1 << 1), /* include muted elements */
+ ANIMFILTER_KEYS_ACTIVE = (1 << 2), /* only include active-subelements */
+
+ /* object specific */
+ ANIMFILTER_KEYS_NOMAT = (1 << 9), /* don't include material keyframes */
+ ANIMFILTER_KEYS_NOSKEY = (1 << 10), /* don't include shape keys (for geometry) */
} eAnimFilterFlags;
/* utility funcs for auto keyframe */
-bool ED_autokeyframe_object(struct bContext *C, struct Scene *scene, struct Object *ob, struct KeyingSet *ks);
-bool ED_autokeyframe_pchan(struct bContext *C, struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, struct KeyingSet *ks);
+bool ED_autokeyframe_object(struct bContext *C,
+ struct Scene *scene,
+ struct Object *ob,
+ struct KeyingSet *ks);
+bool ED_autokeyframe_pchan(struct bContext *C,
+ struct Scene *scene,
+ struct Object *ob,
+ struct bPoseChannel *pchan,
+ struct KeyingSet *ks);
/* Names for builtin keying sets so we don't confuse these with labels/text,
* defined in python script: keyingsets_builtins.py */
-#define ANIM_KS_LOCATION_ID "Location"
-#define ANIM_KS_ROTATION_ID "Rotation"
-#define ANIM_KS_SCALING_ID "Scaling"
-#define ANIM_KS_LOC_ROT_SCALE_ID "LocRotScale"
-#define ANIM_KS_AVAILABLE_ID "Available"
-#define ANIM_KS_WHOLE_CHARACTER_ID "WholeCharacter"
-#define ANIM_KS_WHOLE_CHARACTER_SELECTED_ID "WholeCharacterSelected"
+#define ANIM_KS_LOCATION_ID "Location"
+#define ANIM_KS_ROTATION_ID "Rotation"
+#define ANIM_KS_SCALING_ID "Scaling"
+#define ANIM_KS_LOC_ROT_SCALE_ID "LocRotScale"
+#define ANIM_KS_AVAILABLE_ID "Available"
+#define ANIM_KS_WHOLE_CHARACTER_ID "WholeCharacter"
+#define ANIM_KS_WHOLE_CHARACTER_SELECTED_ID "WholeCharacterSelected"
#ifdef __cplusplus
}
diff --git a/source/blender/editors/include/ED_lattice.h b/source/blender/editors/include/ED_lattice.h
index f65f47c40ad..5c3c3555d56 100644
--- a/source/blender/editors/include/ED_lattice.h
+++ b/source/blender/editors/include/ED_lattice.h
@@ -35,7 +35,8 @@ void ED_keymap_lattice(struct wmKeyConfig *keyconf);
/* editlattice_select.c */
bool ED_lattice_flags_set(struct Object *obedit, int flag);
-bool ED_lattice_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
+bool ED_lattice_select_pick(
+ struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
bool ED_lattice_deselect_all_multi_ex(struct Base **bases, const uint bases_len);
bool ED_lattice_deselect_all_multi(struct bContext *C);
@@ -43,4 +44,4 @@ bool ED_lattice_deselect_all_multi(struct bContext *C);
/* editlattice_undo.c */
void ED_lattice_undosys_type(struct UndoType *ut);
-#endif /* __ED_LATTICE_H__ */
+#endif /* __ED_LATTICE_H__ */
diff --git a/source/blender/editors/include/ED_markers.h b/source/blender/editors/include/ED_markers.h
index f3ca7135e40..a883187327f 100644
--- a/source/blender/editors/include/ED_markers.h
+++ b/source/blender/editors/include/ED_markers.h
@@ -35,9 +35,9 @@ struct wmKeyMap;
/* flags for drawing markers */
enum {
- DRAW_MARKERS_LINES = (1 << 0),
- DRAW_MARKERS_LOCAL = (1 << 1),
- DRAW_MARKERS_MARGIN = (1 << 2),
+ DRAW_MARKERS_LINES = (1 << 0),
+ DRAW_MARKERS_LOCAL = (1 << 1),
+ DRAW_MARKERS_MARGIN = (1 << 2),
};
void ED_markers_draw(const struct bContext *C, int flag);
@@ -47,7 +47,8 @@ void ED_markers_draw(const struct bContext *C, int flag);
ListBase *ED_context_get_markers(const struct bContext *C);
ListBase *ED_animcontext_get_markers(const struct bAnimContext *ac);
-int ED_markers_post_apply_transform(ListBase *markers, struct Scene *scene, int mode, float value, char side);
+int ED_markers_post_apply_transform(
+ ListBase *markers, struct Scene *scene, int mode, float value, char side);
struct TimeMarker *ED_markers_find_nearest_marker(ListBase *markers, float x);
int ED_markers_find_nearest_marker_time(ListBase *markers, float x);
diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h
index d555a17c0b1..c3883de0722 100644
--- a/source/blender/editors/include/ED_mask.h
+++ b/source/blender/editors/include/ED_mask.h
@@ -35,12 +35,16 @@ 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_pixelspace_factor(struct ScrArea *sa, struct ARegion *ar, float *scalex, float *scaley);
+void ED_mask_pixelspace_factor(struct ScrArea *sa,
+ struct ARegion *ar,
+ 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_point_pos(struct ScrArea *sa, struct ARegion *ar, 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);
+void ED_mask_point_pos(
+ struct ScrArea *sa, struct ARegion *ar, 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);
void ED_mask_cursor_location_get(struct ScrArea *sa, float cursor[2]);
bool ED_mask_selected_minmax(const struct bContext *C, float min[2], float max[2]);
@@ -51,15 +55,22 @@ void ED_operatormacros_mask(void);
/* mask_draw.c */
void ED_mask_draw(const struct bContext *C, const char draw_flag, const char draw_type);
-void ED_mask_draw_region(struct Mask *mask, struct ARegion *ar,
- const char draw_flag, const char draw_type, const char overlay_mode,
- const int width_i, const int height_i,
- const float aspx, const float aspy,
- const bool do_scale_applied, const bool do_draw_cb,
+void ED_mask_draw_region(struct Mask *mask,
+ struct ARegion *ar,
+ const char draw_flag,
+ const char draw_type,
+ const char overlay_mode,
+ const int width_i,
+ const int height_i,
+ const float aspx,
+ const float aspy,
+ const bool do_scale_applied,
+ const bool do_draw_cb,
float stabmat[4][4],
const struct bContext *C);
-void ED_mask_draw_frames(struct Mask *mask, struct ARegion *ar, const int cfra, const int sfra, const int efra);
+void ED_mask_draw_frames(
+ struct Mask *mask, struct ARegion *ar, const int cfra, const int sfra, const int efra);
/* mask_shapekey.c */
void ED_mask_layer_shape_auto_key(struct MaskLayer *masklay, const int frame);
@@ -67,16 +78,24 @@ bool ED_mask_layer_shape_auto_key_all(struct Mask *mask, const int frame);
bool ED_mask_layer_shape_auto_key_select(struct Mask *mask, const int frame);
/* ----------- Mask AnimEdit API ------------------ */
-bool ED_masklayer_frames_looper(struct MaskLayer *masklay, struct Scene *scene,
- short (*masklay_shape_cb)(struct MaskLayerShape *, struct Scene *));
+bool ED_masklayer_frames_looper(struct MaskLayer *masklay,
+ struct Scene *scene,
+ short (*masklay_shape_cb)(struct MaskLayerShape *,
+ struct Scene *));
void ED_masklayer_make_cfra_list(struct MaskLayer *masklay, ListBase *elems, bool onlysel);
-bool ED_masklayer_frame_select_check(struct MaskLayer *masklay);
-void ED_masklayer_frame_select_set(struct MaskLayer *masklay, short mode);
-void ED_masklayer_frames_select_box(struct MaskLayer *masklay, float min, float max, short select_mode);
-void ED_masklayer_frames_select_region(struct KeyframeEditData *ked, struct MaskLayer *masklay, short tool, short select_mode);
-void ED_mask_select_frames(struct MaskLayer *masklay, short select_mode);
-void ED_mask_select_frame(struct MaskLayer *masklay, int selx, short select_mode);
+bool ED_masklayer_frame_select_check(struct MaskLayer *masklay);
+void ED_masklayer_frame_select_set(struct MaskLayer *masklay, short mode);
+void ED_masklayer_frames_select_box(struct MaskLayer *masklay,
+ float min,
+ float max,
+ short select_mode);
+void ED_masklayer_frames_select_region(struct KeyframeEditData *ked,
+ struct MaskLayer *masklay,
+ short tool,
+ short select_mode);
+void ED_mask_select_frames(struct MaskLayer *masklay, short select_mode);
+void ED_mask_select_frame(struct MaskLayer *masklay, int selx, short select_mode);
bool ED_masklayer_frames_delete(struct MaskLayer *masklay);
void ED_masklayer_frames_duplicate(struct MaskLayer *masklay);
diff --git a/source/blender/editors/include/ED_mball.h b/source/blender/editors/include/ED_mball.h
index 2683631e85f..8ffae0f2b66 100644
--- a/source/blender/editors/include/ED_mball.h
+++ b/source/blender/editors/include/ED_mball.h
@@ -34,9 +34,11 @@ void ED_operatortypes_metaball(void);
void ED_operatormacros_metaball(void);
void ED_keymap_metaball(struct wmKeyConfig *keyconf);
-struct MetaElem *ED_mball_add_primitive(struct bContext *C, struct Object *obedit, float mat[4][4], float dia, int type);
+struct MetaElem *ED_mball_add_primitive(
+ struct bContext *C, struct Object *obedit, float mat[4][4], float dia, int type);
-bool ED_mball_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
+bool ED_mball_select_pick(
+ struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
bool ED_mball_deselect_all_multi_ex(struct Base **bases, uint bases_len);
bool ED_mball_deselect_all_multi(struct bContext *C);
@@ -48,11 +50,10 @@ void ED_mball_editmball_load(struct Object *obedit);
/* editmball_undo.c */
void ED_mball_undosys_type(struct UndoType *ut);
+#define MBALLSEL_STIFF (1 << 29)
+#define MBALLSEL_RADIUS (1 << 30)
+#define MBALLSEL_ANY (MBALLSEL_STIFF | MBALLSEL_RADIUS)
-#define MBALLSEL_STIFF (1 << 29)
-#define MBALLSEL_RADIUS (1 << 30)
-#define MBALLSEL_ANY (MBALLSEL_STIFF | MBALLSEL_RADIUS)
+#define MBALL_NOSEL (1u << 31u)
-#define MBALL_NOSEL (1u << 31u)
-
-#endif /* __ED_MBALL_H__ */
+#endif /* __ED_MBALL_H__ */
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 9e68c4a03ae..dcac5301da5 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -60,17 +60,24 @@ struct wmKeyConfig;
struct wmOperator;
/* editmesh_utils.c */
-void EDBM_verts_mirror_cache_begin_ex(struct BMEditMesh *em, const int axis,
- const bool use_self, const bool use_select,
- const bool use_topology, float maxdist, int *r_index);
-void EDBM_verts_mirror_cache_begin(struct BMEditMesh *em, const int axis,
- const bool use_self, const bool use_select, const bool use_toplogy);
-void EDBM_verts_mirror_apply(struct BMEditMesh *em, const int sel_from, const int sel_to);
+void EDBM_verts_mirror_cache_begin_ex(struct BMEditMesh *em,
+ const int axis,
+ const bool use_self,
+ const bool use_select,
+ const bool use_topology,
+ float maxdist,
+ int *r_index);
+void EDBM_verts_mirror_cache_begin(struct BMEditMesh *em,
+ const int axis,
+ const bool use_self,
+ const bool use_select,
+ const bool use_toplogy);
+void EDBM_verts_mirror_apply(struct BMEditMesh *em, const int sel_from, const int sel_to);
struct BMVert *EDBM_verts_mirror_get(struct BMEditMesh *em, struct BMVert *v);
struct BMEdge *EDBM_verts_mirror_get_edge(struct BMEditMesh *em, struct BMEdge *e);
struct BMFace *EDBM_verts_mirror_get_face(struct BMEditMesh *em, struct BMFace *f);
-void EDBM_verts_mirror_cache_clear(struct BMEditMesh *em, struct BMVert *v);
-void EDBM_verts_mirror_cache_end(struct BMEditMesh *em);
+void EDBM_verts_mirror_cache_clear(struct BMEditMesh *em, struct BMVert *v);
+void EDBM_verts_mirror_cache_end(struct BMEditMesh *em);
void EDBM_mesh_normals_update(struct BMEditMesh *em);
void EDBM_mesh_clear(struct BMEditMesh *em);
@@ -100,98 +107,115 @@ bool EDBM_mesh_reveal(struct BMEditMesh *em, bool select);
void EDBM_update_generic(struct BMEditMesh *em, const bool do_tessface, const bool is_destructive);
-struct UvElementMap *BM_uv_element_map_create(
- struct BMesh *bm,
- const bool selected, const bool use_winding, const bool do_islands);
-void BM_uv_element_map_free(struct UvElementMap *vmap);
-struct UvElement *BM_uv_element_get(struct UvElementMap *map, struct BMFace *efa, struct BMLoop *l);
-
-bool EDBM_uv_check(struct BMEditMesh *em);
-struct BMFace *EDBM_uv_active_face_get(
- struct BMEditMesh *em, const bool sloppy, const bool selected);
-
-void BM_uv_vert_map_free(struct UvVertMap *vmap);
+struct UvElementMap *BM_uv_element_map_create(struct BMesh *bm,
+ const bool selected,
+ const bool use_winding,
+ const bool do_islands);
+void BM_uv_element_map_free(struct UvElementMap *vmap);
+struct UvElement *BM_uv_element_get(struct UvElementMap *map,
+ struct BMFace *efa,
+ struct BMLoop *l);
+
+bool EDBM_uv_check(struct BMEditMesh *em);
+struct BMFace *EDBM_uv_active_face_get(struct BMEditMesh *em,
+ const bool sloppy,
+ const bool selected);
+
+void BM_uv_vert_map_free(struct UvVertMap *vmap);
struct UvMapVert *BM_uv_vert_map_at_index(struct UvVertMap *vmap, unsigned int v);
-struct UvVertMap *BM_uv_vert_map_create(
- struct BMesh *bm,
- const float limit[2], const bool use_select, const bool use_winding);
+struct UvVertMap *BM_uv_vert_map_create(struct BMesh *bm,
+ const float limit[2],
+ const bool use_select,
+ const bool use_winding);
void EDBM_flag_enable_all(struct BMEditMesh *em, const char hflag);
void EDBM_flag_disable_all(struct BMEditMesh *em, const char hflag);
-bool BMBVH_EdgeVisible(struct BMBVHTree *tree, struct BMEdge *e,
+bool BMBVH_EdgeVisible(struct BMBVHTree *tree,
+ struct BMEdge *e,
struct Depsgraph *depsgraph,
- struct ARegion *ar, struct View3D *v3d, struct Object *obedit);
+ struct ARegion *ar,
+ struct View3D *v3d,
+ struct Object *obedit);
/* editmesh_undo.c */
void ED_mesh_undosys_type(struct UndoType *ut);
/* editmesh_select.c */
void EDBM_select_mirrored(
- struct BMEditMesh *em, const int axis, const bool extend,
- int *r_totmirr, int *r_totfail);
+ struct BMEditMesh *em, const int axis, const bool extend, int *r_totmirr, int *r_totfail);
void EDBM_automerge(struct Scene *scene, struct Object *ob, bool update, const char hflag);
-bool EDBM_backbuf_border_init(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
+bool EDBM_backbuf_border_init(
+ struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
bool EDBM_backbuf_check(unsigned int index);
void EDBM_backbuf_free(void);
-bool EDBM_backbuf_border_mask_init(
- struct ViewContext *vc, const int mcords[][2], short tot,
- short xmin, short ymin, short xmax, short ymax);
+bool EDBM_backbuf_border_mask_init(struct ViewContext *vc,
+ const int mcords[][2],
+ short tot,
+ short xmin,
+ short ymin,
+ short xmax,
+ short ymax);
bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads);
-struct BMVert *EDBM_vert_find_nearest_ex(
- struct ViewContext *vc, float *r_dist,
- const bool use_select_bias, bool use_cycle);
-struct BMVert *EDBM_vert_find_nearest(
- struct ViewContext *vc, float *r_dist);
-
-struct BMEdge *EDBM_edge_find_nearest_ex(
- struct ViewContext *vc, float *r_dist,
- float *r_dist_center,
- const bool use_select_bias, const bool use_cycle,
- struct BMEdge **r_eed_zbuf);
-struct BMEdge *EDBM_edge_find_nearest(
- struct ViewContext *vc, float *r_dist);
-
-struct BMFace *EDBM_face_find_nearest_ex(
- struct ViewContext *vc, float *r_dist,
- float *r_dist_center,
- const bool use_select_bias, const bool use_cycle,
- struct BMFace **r_efa_zbuf);
-struct BMFace *EDBM_face_find_nearest(
- struct ViewContext *vc, float *r_dist);
-
-bool EDBM_unified_findnearest(
- struct ViewContext *vc,
- struct Base **bases,
- const uint bases_len,
- int *r_base_index,
- struct BMVert **r_eve,
- struct BMEdge **r_eed,
- struct BMFace **r_efa);
-
-bool EDBM_unified_findnearest_from_raycast(
- struct ViewContext *vc,
- struct Base **bases,
- const uint bases_len,
- bool use_boundary,
- int *r_base_index,
- struct BMVert **r_eve,
- struct BMEdge **r_eed,
- struct BMFace **r_efa);
-
-bool EDBM_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
+struct BMVert *EDBM_vert_find_nearest_ex(struct ViewContext *vc,
+ float *r_dist,
+ const bool use_select_bias,
+ bool use_cycle);
+struct BMVert *EDBM_vert_find_nearest(struct ViewContext *vc, float *r_dist);
+
+struct BMEdge *EDBM_edge_find_nearest_ex(struct ViewContext *vc,
+ float *r_dist,
+ float *r_dist_center,
+ const bool use_select_bias,
+ const bool use_cycle,
+ struct BMEdge **r_eed_zbuf);
+struct BMEdge *EDBM_edge_find_nearest(struct ViewContext *vc, float *r_dist);
+
+struct BMFace *EDBM_face_find_nearest_ex(struct ViewContext *vc,
+ float *r_dist,
+ float *r_dist_center,
+ const bool use_select_bias,
+ const bool use_cycle,
+ struct BMFace **r_efa_zbuf);
+struct BMFace *EDBM_face_find_nearest(struct ViewContext *vc, float *r_dist);
+
+bool EDBM_unified_findnearest(struct ViewContext *vc,
+ struct Base **bases,
+ const uint bases_len,
+ int *r_base_index,
+ struct BMVert **r_eve,
+ struct BMEdge **r_eed,
+ struct BMFace **r_efa);
+
+bool EDBM_unified_findnearest_from_raycast(struct ViewContext *vc,
+ struct Base **bases,
+ const uint bases_len,
+ bool use_boundary,
+ int *r_base_index,
+ struct BMVert **r_eve,
+ struct BMEdge **r_eed,
+ struct BMFace **r_efa);
+
+bool EDBM_select_pick(
+ struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
void EDBM_selectmode_set(struct BMEditMesh *em);
-void EDBM_selectmode_convert(struct BMEditMesh *em, const short selectmode_old, const short selectmode_new);
+void EDBM_selectmode_convert(struct BMEditMesh *em,
+ const short selectmode_old,
+ const short selectmode_new);
/* user access this */
-bool EDBM_selectmode_toggle(struct bContext *C, const short selectmode_new,
- const int action, const bool use_extend, const bool use_expand);
-
-bool EDBM_selectmode_disable(struct Scene *scene, struct BMEditMesh *em,
+bool EDBM_selectmode_toggle(struct bContext *C,
+ const short selectmode_new,
+ const int action,
+ const bool use_extend,
+ const bool use_expand);
+
+bool EDBM_selectmode_disable(struct Scene *scene,
+ struct BMEditMesh *em,
const short selectmode_disable,
const short selectmode_fallback);
@@ -201,7 +225,7 @@ void EDBM_select_toggle_all(struct BMEditMesh *em);
void EDBM_select_swap(struct BMEditMesh *em); /* exported for UV */
bool EDBM_select_interior_faces(struct BMEditMesh *em);
-void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc); /* rename? */
+void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc); /* rename? */
bool EDBM_mesh_deselect_all_multi_ex(struct Base **bases, const uint bases_len);
bool EDBM_mesh_deselect_all_multi(struct bContext *C);
@@ -214,9 +238,11 @@ struct EditMesh_PreSelEdgeRing *EDBM_preselect_edgering_create(void);
void EDBM_preselect_edgering_destroy(struct EditMesh_PreSelEdgeRing *psel);
void EDBM_preselect_edgering_clear(struct EditMesh_PreSelEdgeRing *psel);
void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const float matrix[4][4]);
-void EDBM_preselect_edgering_update_from_edge(
- struct EditMesh_PreSelEdgeRing *psel,
- struct BMesh *bm, struct BMEdge *eed_start, int previewlines, const float (*coords)[3]);
+void EDBM_preselect_edgering_update_from_edge(struct EditMesh_PreSelEdgeRing *psel,
+ struct BMesh *bm,
+ struct BMEdge *eed_start,
+ int previewlines,
+ const float (*coords)[3]);
/* editmesh_preselect_elem.c */
struct EditMesh_PreSelElem;
@@ -224,25 +250,36 @@ struct EditMesh_PreSelElem *EDBM_preselect_elem_create(void);
void EDBM_preselect_elem_destroy(struct EditMesh_PreSelElem *psel);
void EDBM_preselect_elem_clear(struct EditMesh_PreSelElem *psel);
void EDBM_preselect_elem_draw(struct EditMesh_PreSelElem *psel, const float matrix[4][4]);
-void EDBM_preselect_elem_update_from_single(
- struct EditMesh_PreSelElem *psel,
- struct BMesh *bm, struct BMElem *ele, const float (*coords)[3]);
+void EDBM_preselect_elem_update_from_single(struct EditMesh_PreSelElem *psel,
+ struct BMesh *bm,
+ struct BMElem *ele,
+ const float (*coords)[3]);
/* mesh_ops.c */
-void ED_operatortypes_mesh(void);
-void ED_operatormacros_mesh(void);
-void ED_keymap_mesh(struct wmKeyConfig *keyconf);
+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 ARegion *ar, struct BMEditMesh *em);
-
/* editface.c */
void paintface_flush_flags(struct bContext *C, struct Object *ob, short flag);
-bool paintface_mouse_select(struct bContext *C, struct Object *ob, const int mval[2], bool extend, bool deselect, bool toggle);
+bool paintface_mouse_select(struct bContext *C,
+ struct Object *ob,
+ const int mval[2],
+ bool extend,
+ bool deselect,
+ bool toggle);
bool do_paintface_box_select(struct ViewContext *vc, const struct rcti *rect, int sel_op);
-bool paintface_deselect_all_visible(struct bContext *C, struct Object *ob, int action, bool flush_flags);
-void paintface_select_linked(struct bContext *C, struct Object *ob, const int mval[2], const bool select);
+bool paintface_deselect_all_visible(struct bContext *C,
+ struct Object *ob,
+ int action,
+ bool flush_flags);
+void paintface_select_linked(struct bContext *C,
+ struct Object *ob,
+ const int mval[2],
+ const bool select);
bool paintface_minmax(struct Object *ob, float r_min[3], float r_max[3]);
void paintface_hide(struct bContext *C, struct Object *ob, const bool unselected);
@@ -255,53 +292,70 @@ void paintvert_tag_select_update(struct bContext *C, struct Object *ob);
/* mirrtopo */
typedef struct MirrTopoStore_t {
- intptr_t *index_lookup;
- int prev_vert_tot;
- int prev_edge_tot;
- bool prev_is_editmode;
+ intptr_t *index_lookup;
+ int prev_vert_tot;
+ int prev_edge_tot;
+ bool prev_is_editmode;
} MirrTopoStore_t;
-bool ED_mesh_mirrtopo_recalc_check(
- struct Mesh *me, struct Mesh *me_eval, MirrTopoStore_t *mesh_topo_store);
-void ED_mesh_mirrtopo_init(
- struct Mesh *me, struct Mesh *me_eval, MirrTopoStore_t *mesh_topo_store,
- const bool skip_em_vert_array_init);
+bool ED_mesh_mirrtopo_recalc_check(struct Mesh *me,
+ struct Mesh *me_eval,
+ MirrTopoStore_t *mesh_topo_store);
+void ED_mesh_mirrtopo_init(struct Mesh *me,
+ struct Mesh *me_eval,
+ MirrTopoStore_t *mesh_topo_store,
+ const bool skip_em_vert_array_init);
void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store);
-
/* object_vgroup.c */
#define WEIGHT_REPLACE 1
#define WEIGHT_ADD 2
#define WEIGHT_SUBTRACT 3
-bool ED_vgroup_sync_from_pose(struct Object *ob);
-void ED_vgroup_select_by_name(struct Object *ob, const char *name);
-void ED_vgroup_data_clamp_range(struct ID *id, const int total);
-bool ED_vgroup_array_copy(struct Object *ob, struct Object *ob_from);
-bool ED_vgroup_parray_alloc(struct ID *id, struct MDeformVert ***dvert_arr, int *dvert_tot,
- const bool use_vert_sel);
-void ED_vgroup_parray_mirror_sync(struct Object *ob,
- struct MDeformVert **dvert_array, const int dvert_tot,
- const bool *vgroup_validmap, const int vgroup_tot);
-void ED_vgroup_parray_mirror_assign(struct Object *ob,
- struct MDeformVert **dvert_array, const int dvert_tot);
-void ED_vgroup_parray_remove_zero(struct MDeformVert **dvert_array, const int dvert_tot,
- const bool *vgroup_validmap, const int vgroup_tot,
- const float epsilon, const bool keep_single);
-void ED_vgroup_parray_to_weight_array(const struct MDeformVert **dvert_array, const int dvert_tot,
- float *dvert_weights, const int def_nr);
-void ED_vgroup_parray_from_weight_array(struct MDeformVert **dvert_array, const int dvert_tot,
- const float *dvert_weights, const int def_nr,
- const bool remove_zero);
-void ED_vgroup_mirror(struct Object *ob,
- const bool mirror_weights, const bool flip_vgroups,
- const bool all_vgroups, const bool use_topology,
- int *r_totmirr, int *r_totfail);
-
-void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode);
-void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGroup *dg, int vertnum);
-float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vertnum);
-void ED_vgroup_vert_active_mirror(struct Object *ob, int def_nr);
+bool ED_vgroup_sync_from_pose(struct Object *ob);
+void ED_vgroup_select_by_name(struct Object *ob, const char *name);
+void ED_vgroup_data_clamp_range(struct ID *id, const int total);
+bool ED_vgroup_array_copy(struct Object *ob, struct Object *ob_from);
+bool ED_vgroup_parray_alloc(struct ID *id,
+ struct MDeformVert ***dvert_arr,
+ int *dvert_tot,
+ const bool use_vert_sel);
+void ED_vgroup_parray_mirror_sync(struct Object *ob,
+ struct MDeformVert **dvert_array,
+ const int dvert_tot,
+ const bool *vgroup_validmap,
+ const int vgroup_tot);
+void ED_vgroup_parray_mirror_assign(struct Object *ob,
+ struct MDeformVert **dvert_array,
+ const int dvert_tot);
+void ED_vgroup_parray_remove_zero(struct MDeformVert **dvert_array,
+ const int dvert_tot,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const float epsilon,
+ const bool keep_single);
+void ED_vgroup_parray_to_weight_array(const struct MDeformVert **dvert_array,
+ const int dvert_tot,
+ float *dvert_weights,
+ const int def_nr);
+void ED_vgroup_parray_from_weight_array(struct MDeformVert **dvert_array,
+ const int dvert_tot,
+ const float *dvert_weights,
+ const int def_nr,
+ const bool remove_zero);
+void ED_vgroup_mirror(struct Object *ob,
+ const bool mirror_weights,
+ const bool flip_vgroups,
+ const bool all_vgroups,
+ const bool use_topology,
+ int *r_totmirr,
+ int *r_totfail);
+
+void ED_vgroup_vert_add(
+ struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode);
+void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGroup *dg, int vertnum);
+float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vertnum);
+void ED_vgroup_vert_active_mirror(struct Object *ob, int def_nr);
/* mesh_data.c */
// void ED_mesh_geometry_add(struct Mesh *mesh, struct ReportList *reports, int verts, int edges, int faces);
@@ -316,28 +370,37 @@ void ED_mesh_edges_remove(struct Mesh *mesh, struct ReportList *reports, int cou
void ED_mesh_vertices_remove(struct Mesh *mesh, struct ReportList *reports, int count);
void ED_mesh_calc_tessface(struct Mesh *mesh, bool free_mpoly);
-void ED_mesh_update(struct Mesh *mesh, struct bContext *C, bool calc_edges, bool calc_edges_loose, bool calc_tessface);
+void ED_mesh_update(struct Mesh *mesh,
+ struct bContext *C,
+ bool calc_edges,
+ bool calc_edges_loose,
+ bool calc_tessface);
void ED_mesh_uv_texture_ensure(struct Mesh *me, const char *name);
-int ED_mesh_uv_texture_add(struct Mesh *me, const char *name, const bool active_set, const bool do_init);
+int ED_mesh_uv_texture_add(struct Mesh *me,
+ const char *name,
+ const bool active_set,
+ const bool do_init);
bool ED_mesh_uv_texture_remove_index(struct Mesh *me, const int n);
bool ED_mesh_uv_texture_remove_active(struct Mesh *me);
bool ED_mesh_uv_texture_remove_named(struct Mesh *me, const char *name);
void ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me);
void ED_mesh_uv_loop_reset_ex(struct Mesh *me, const int layernum);
bool ED_mesh_color_ensure(struct Mesh *me, const char *name);
-int ED_mesh_color_add(struct Mesh *me, const char *name, const bool active_set, const bool do_init);
+int ED_mesh_color_add(struct Mesh *me,
+ const char *name,
+ const bool active_set,
+ const bool do_init);
bool ED_mesh_color_remove_index(struct Mesh *me, const int n);
bool ED_mesh_color_remove_active(struct Mesh *me);
bool ED_mesh_color_remove_named(struct Mesh *me, const char *name);
void ED_mesh_report_mirror(struct wmOperator *op, int totmirr, int totfail);
-void ED_mesh_report_mirror_ex(struct wmOperator *op, int totmirr, int totfail,
- char selectmode);
+void ED_mesh_report_mirror_ex(struct wmOperator *op, int totmirr, int totfail, char selectmode);
/* mesh backup */
typedef struct BMBackup {
- struct BMesh *bmcopy;
+ struct BMesh *bmcopy;
} BMBackup;
/* save a copy of the bmesh for restoring later */
@@ -347,44 +410,54 @@ void EDBM_redo_state_restore(struct BMBackup, struct BMEditMesh *em, int recalct
/* delete the backup, optionally flushing it to an editmesh */
void EDBM_redo_state_free(struct BMBackup *, struct BMEditMesh *em, int recalctess);
-
/* *** meshtools.c *** */
-int join_mesh_exec(struct bContext *C, struct wmOperator *op);
-int join_mesh_shapes_exec(struct bContext *C, struct wmOperator *op);
+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);
+ 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);
/* retrieves mirrored cache vert, or NULL if there isn't one.
* note: calling this without ensuring the mirror cache state
* is bad.*/
-int mesh_get_x_mirror_vert(struct Object *ob, struct Mesh *me_eval, int index, const bool use_topology);
-struct BMVert *editbmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh *em,
- struct BMVert *eve, const float co[3],
- int index, const bool use_topology);
+int mesh_get_x_mirror_vert(struct Object *ob,
+ struct Mesh *me_eval,
+ int index,
+ const bool use_topology);
+struct BMVert *editbmesh_get_x_mirror_vert(struct Object *ob,
+ struct BMEditMesh *em,
+ struct BMVert *eve,
+ const float co[3],
+ int index,
+ const bool use_topology);
int *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em, struct Mesh *me_eval);
int ED_mesh_mirror_get_vert(struct Object *ob, int index);
-bool ED_mesh_pick_vert(
- struct bContext *C, struct Object *ob, const int mval[2], uint dist_px, bool use_zbuf,
- uint *r_index);
+bool ED_mesh_pick_vert(struct bContext *C,
+ struct Object *ob,
+ const int mval[2],
+ uint dist_px,
+ bool use_zbuf,
+ uint *r_index);
bool ED_mesh_pick_face(
- struct bContext *C, struct Object *ob, const int mval[2], uint dist_px,
- uint *r_index);
+ struct bContext *C, struct Object *ob, const int mval[2], uint dist_px, uint *r_index);
bool ED_mesh_pick_face_vert(
- struct bContext *C, struct Object *ob, const int mval[2], uint dist_px,
- uint *r_index);
-
+ struct bContext *C, struct Object *ob, const int mval[2], uint dist_px, uint *r_index);
struct MDeformVert *ED_mesh_active_dvert_get_em(struct Object *ob, struct BMVert **r_eve);
struct MDeformVert *ED_mesh_active_dvert_get_ob(struct Object *ob, int *r_index);
struct MDeformVert *ED_mesh_active_dvert_get_only(struct Object *ob);
-void EDBM_mesh_stats_multi(struct Object **objects, const uint objects_len, int totelem[3], int totelem_sel[3]);
-void EDBM_mesh_elem_index_ensure_multi(struct Object **objects, const uint objects_len, const char htype);
+void EDBM_mesh_stats_multi(struct Object **objects,
+ const uint objects_len,
+ int totelem[3],
+ int totelem_sel[3]);
+void EDBM_mesh_elem_index_ensure_multi(struct Object **objects,
+ const uint objects_len,
+ const char htype);
#define ED_MESH_PICK_DEFAULT_VERT_DIST 25
#define ED_MESH_PICK_DEFAULT_FACE_DIST 1
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index 09449687e6e..d2d8972c245 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -40,20 +40,23 @@ struct bNodeTreeType;
struct bNodeType;
typedef enum {
- NODE_TOP = 1,
- NODE_BOTTOM = 2,
- NODE_LEFT = 4,
- NODE_RIGHT = 8,
+ NODE_TOP = 1,
+ NODE_BOTTOM = 2,
+ NODE_LEFT = 4,
+ NODE_RIGHT = 8,
} NodeBorder;
-#define NODE_GRID_STEPS 5
+#define NODE_GRID_STEPS 5
/* space_node.c */
int ED_node_tree_path_length(struct SpaceNode *snode);
void ED_node_tree_path_get(struct SpaceNode *snode, char *value);
void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length);
-void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, struct ID *id, struct ID *from);
+void ED_node_tree_start(struct SpaceNode *snode,
+ struct bNodeTree *ntree,
+ struct ID *id,
+ struct ID *from);
void ED_node_tree_push(struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *gnode);
void ED_node_tree_pop(struct SpaceNode *snode);
int ED_node_tree_depth(struct SpaceNode *snode);
@@ -68,7 +71,8 @@ void ED_init_custom_node_socket_type(struct bNodeSocketType *stype);
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);
+void ED_node_draw_snap(
+ struct View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned pos);
/* node_draw.c */
void ED_node_tree_update(const struct bContext *C);
@@ -95,12 +99,15 @@ void ED_node_select_all(ListBase *lb, int action);
void ED_node_post_apply_transform(struct bContext *C, struct bNodeTree *ntree);
void ED_node_set_active(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node);
-void ED_node_composite_job(const struct bContext *C, struct bNodeTree *nodetree, struct Scene *scene_owner);
+void ED_node_composite_job(const struct bContext *C,
+ struct bNodeTree *nodetree,
+ struct Scene *scene_owner);
/* node_ops.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 *ar, int mval[2], float r_col[3]);
#endif /* __ED_NODE_H__ */
diff --git a/source/blender/editors/include/ED_numinput.h b/source/blender/editors/include/ED_numinput.h
index d4cb2110c2c..697a236341f 100644
--- a/source/blender/editors/include/ED_numinput.h
+++ b/source/blender/editors/include/ED_numinput.h
@@ -27,47 +27,47 @@
struct wmEvent;
typedef struct NumInput {
- /** idx_max < NUM_MAX_ELEMENTS */
- short idx_max;
- int unit_sys;
- /** Each value can have a different type */
- int unit_type[NUM_MAX_ELEMENTS];
- bool unit_use_radians;
-
- /** Flags affecting all values' behavior */
- short flag;
- /** Per-value flags */
- short val_flag[NUM_MAX_ELEMENTS];
- /** Direct value of the input */
- float val[NUM_MAX_ELEMENTS];
- /** Original value of the input, for reset */
- float val_org[NUM_MAX_ELEMENTS];
- /** Increment steps */
- float val_inc[NUM_MAX_ELEMENTS];
-
- /** Active element/value */
- short idx;
- /** String as typed by user for edited value (we assume ASCII world!) */
- char str[NUM_STR_REP_LEN];
- /** Current position of cursor in edited value str
- * (first byte of "current" letter, so 0 for an empty str) */
- int str_cur;
+ /** idx_max < NUM_MAX_ELEMENTS */
+ short idx_max;
+ int unit_sys;
+ /** Each value can have a different type */
+ int unit_type[NUM_MAX_ELEMENTS];
+ bool unit_use_radians;
+
+ /** Flags affecting all values' behavior */
+ short flag;
+ /** Per-value flags */
+ short val_flag[NUM_MAX_ELEMENTS];
+ /** Direct value of the input */
+ float val[NUM_MAX_ELEMENTS];
+ /** Original value of the input, for reset */
+ float val_org[NUM_MAX_ELEMENTS];
+ /** Increment steps */
+ float val_inc[NUM_MAX_ELEMENTS];
+
+ /** Active element/value */
+ short idx;
+ /** String as typed by user for edited value (we assume ASCII world!) */
+ char str[NUM_STR_REP_LEN];
+ /** Current position of cursor in edited value str
+ * (first byte of "current" letter, so 0 for an empty str) */
+ int str_cur;
} NumInput;
/* NumInput.flag */
enum {
- NUM_AFFECT_ALL = (1 << 0),
- /* (1 << 9) and above are reserved for internal flags! */
+ NUM_AFFECT_ALL = (1 << 0),
+ /* (1 << 9) and above are reserved for internal flags! */
};
/* NumInput.val_flag[] */
enum {
- /* Public! */
- NUM_NULL_ONE = (1 << 0),
- NUM_NO_NEGATIVE = (1 << 1),
- NUM_NO_ZERO = (1 << 2),
- NUM_NO_FRACTION = (1 << 3),
- /* (1 << 9) and above are reserved for internal flags! */
+ /* Public! */
+ NUM_NULL_ONE = (1 << 0),
+ NUM_NO_NEGATIVE = (1 << 1),
+ NUM_NO_ZERO = (1 << 2),
+ NUM_NO_FRACTION = (1 << 3),
+ /* (1 << 9) and above are reserved for internal flags! */
};
struct UnitSettings;
@@ -92,11 +92,12 @@ bool hasNumInput(const NumInput *n);
bool applyNumInput(NumInput *n, float *vec);
bool handleNumInput(struct bContext *C, NumInput *n, const struct wmEvent *event);
-#define NUM_MODAL_INCREMENT_UP 18
+#define NUM_MODAL_INCREMENT_UP 18
#define NUM_MODAL_INCREMENT_DOWN 19
-bool user_string_to_number(bContext *C, const char *str, const struct UnitSettings *unit, int type, double *r_value);
+bool user_string_to_number(
+ bContext *C, const char *str, const struct UnitSettings *unit, int type, double *r_value);
/** \} */
-#endif /* __ED_NUMINPUT_H__ */
+#endif /* __ED_NUMINPUT_H__ */
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index cb0a390cbc2..ed0298cce1f 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -67,12 +67,13 @@ struct Object *ED_object_active_context(struct bContext *C);
void ED_collection_hide_menu_draw(const struct bContext *C, struct uiLayout *layout);
/* object_utils.c */
-bool ED_object_calc_active_center_for_editmode(
- struct Object *obedit, const bool select_only, float r_center[3]);
-bool ED_object_calc_active_center_for_posemode(
- struct Object *ob, const bool select_only, float r_center[3]);
-bool ED_object_calc_active_center(
- struct Object *ob, const bool select_only, float r_center[3]);
+bool ED_object_calc_active_center_for_editmode(struct Object *obedit,
+ const bool select_only,
+ float r_center[3]);
+bool ED_object_calc_active_center_for_posemode(struct Object *ob,
+ const bool select_only,
+ float r_center[3]);
+bool ED_object_calc_active_center(struct Object *ob, const bool select_only, float r_center[3]);
/* object_ops.c */
void ED_operatortypes_object(void);
@@ -81,25 +82,25 @@ void ED_keymap_object(struct wmKeyConfig *keyconf);
/* object_relations.c */
typedef enum eParentType {
- PAR_OBJECT,
- PAR_ARMATURE,
- PAR_ARMATURE_NAME,
- PAR_ARMATURE_ENVELOPE,
- PAR_ARMATURE_AUTO,
- PAR_BONE,
- PAR_BONE_RELATIVE,
- PAR_CURVE,
- PAR_FOLLOW,
- PAR_PATH_CONST,
- PAR_LATTICE,
- PAR_VERTEX,
- PAR_VERTEX_TRI,
+ PAR_OBJECT,
+ PAR_ARMATURE,
+ PAR_ARMATURE_NAME,
+ PAR_ARMATURE_ENVELOPE,
+ PAR_ARMATURE_AUTO,
+ PAR_BONE,
+ PAR_BONE_RELATIVE,
+ PAR_CURVE,
+ PAR_FOLLOW,
+ PAR_PATH_CONST,
+ PAR_LATTICE,
+ PAR_VERTEX,
+ PAR_VERTEX_TRI,
} eParentType;
typedef enum eObjectSelect_Mode {
- BA_DESELECT = 0,
- BA_SELECT = 1,
- BA_INVERT = 2,
+ BA_DESELECT = 0,
+ BA_SELECT = 1,
+ BA_INVERT = 2,
} eObjectSelect_Mode;
#ifdef __RNA_TYPES_H__
@@ -107,42 +108,67 @@ extern struct EnumPropertyItem prop_clear_parent_types[];
extern struct EnumPropertyItem prop_make_parent_types[];
#endif
-bool ED_object_parent_set(struct ReportList *reports, const struct bContext *C, struct Scene *scene, struct Object *ob,
- struct Object *par, int partype, const bool xmirror, const bool keep_transform,
+bool ED_object_parent_set(struct ReportList *reports,
+ const struct bContext *C,
+ struct Scene *scene,
+ struct Object *ob,
+ struct Object *par,
+ int partype,
+ const bool xmirror,
+ const bool keep_transform,
const int vert_par[3]);
void ED_object_parent_clear(struct Object *ob, const int type);
void ED_object_base_select(struct Base *base, eObjectSelect_Mode mode);
void ED_object_base_activate(struct bContext *C, struct Base *base);
void ED_object_base_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Object *ob);
-bool ED_object_base_deselect_all_ex(struct ViewLayer *view_layer, struct View3D *v3d, int action, bool *r_any_visible);
+bool ED_object_base_deselect_all_ex(struct ViewLayer *view_layer,
+ struct View3D *v3d,
+ int action,
+ bool *r_any_visible);
bool ED_object_base_deselect_all(struct ViewLayer *view_layer, struct View3D *v3d, int action);
/* single object duplicate, if (dupflag == 0), fully linked, else it uses the flags given */
-struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct Base *base, int dupflag);
+struct Base *ED_object_add_duplicate(struct Main *bmain,
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ struct Base *base,
+ int dupflag);
-void ED_object_parent(struct Object *ob, struct Object *parent, const int type, const char *substr);
+void ED_object_parent(struct Object *ob,
+ struct Object *parent,
+ const int type,
+ const char *substr);
/* bitflags for enter/exit editmode */
enum {
- EM_FREEDATA = (1 << 0),
- EM_NO_CONTEXT = (1 << 1),
+ EM_FREEDATA = (1 << 0),
+ EM_NO_CONTEXT = (1 << 1),
};
-bool ED_object_editmode_exit_ex(
- struct Main *bmain, struct Scene *scene, struct Object *obedit, int flag);
+bool ED_object_editmode_exit_ex(struct Main *bmain,
+ struct Scene *scene,
+ struct Object *obedit,
+ int flag);
bool ED_object_editmode_exit(struct bContext *C, int flag);
-bool ED_object_editmode_enter_ex(struct Main *bmain, struct Scene *scene, struct Object *ob, int flag);
+bool ED_object_editmode_enter_ex(struct Main *bmain,
+ struct Scene *scene,
+ struct Object *ob,
+ int flag);
bool ED_object_editmode_enter(struct bContext *C, int flag);
bool ED_object_editmode_load(struct Main *bmain, struct Object *obedit);
-void ED_object_vpaintmode_enter_ex(
- struct Main *bmain, struct Depsgraph *depsgraph, struct wmWindowManager *wm,
- struct Scene *scene, struct Object *ob);
+void ED_object_vpaintmode_enter_ex(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ struct wmWindowManager *wm,
+ struct Scene *scene,
+ struct Object *ob);
void ED_object_vpaintmode_enter(struct bContext *C);
-void ED_object_wpaintmode_enter_ex(
- struct Main *bmain, struct Depsgraph *depsgraph, struct wmWindowManager *wm,
- struct Scene *scene, struct Object *ob);
+void ED_object_wpaintmode_enter_ex(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ struct wmWindowManager *wm,
+ struct Scene *scene,
+ struct Object *ob);
void ED_object_wpaintmode_enter(struct bContext *C);
void ED_object_vpaintmode_exit_ex(struct Object *ob);
@@ -150,24 +176,30 @@ void ED_object_vpaintmode_exit(struct bContext *C);
void ED_object_wpaintmode_exit_ex(struct Object *ob);
void ED_object_wpaintmode_exit(struct bContext *C);
-void ED_object_sculptmode_enter_ex(
- struct Main *bmain, struct Depsgraph *depsgraph,
- struct Scene *scene, struct Object *ob, const bool force_dyntopo,
- struct ReportList *reports);
+void ED_object_sculptmode_enter_ex(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob,
+ const bool force_dyntopo,
+ struct ReportList *reports);
void ED_object_sculptmode_enter(struct bContext *C, struct ReportList *reports);
-void ED_object_sculptmode_exit_ex(
- struct Depsgraph *depsgraph,
- struct Scene *scene, struct Object *ob);
+void ED_object_sculptmode_exit_ex(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob);
void ED_object_sculptmode_exit(struct bContext *C);
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(struct bContext *C, struct Base *base, const float loc[3], const float rot[3]);
-float ED_object_new_primitive_matrix(
- struct bContext *C, struct Object *editob,
- const float loc[3], const float rot[3], float primmat[4][4]);
-
+void ED_object_base_init_transform(struct bContext *C,
+ struct Base *base,
+ const float loc[3],
+ const float rot[3]);
+float ED_object_new_primitive_matrix(struct bContext *C,
+ struct Object *editob,
+ const float loc[3],
+ const float rot[3],
+ float primmat[4][4]);
/* Avoid allowing too much insane values even by typing
* (typos can hang/crash Blender otherwise). */
@@ -177,27 +209,41 @@ void ED_object_add_unit_props_size(struct wmOperatorType *ot);
void ED_object_add_unit_props_radius(struct wmOperatorType *ot);
void ED_object_add_generic_props(struct wmOperatorType *ot, bool do_editmode);
void ED_object_add_mesh_props(struct wmOperatorType *ot);
-bool ED_object_add_generic_get_opts(
- struct bContext *C, struct wmOperator *op, const char view_align_axis,
- float loc[3], float rot[3],
- bool *enter_editmode, unsigned short *local_view_bits, bool *is_view_aligned);
-
-struct Object *ED_object_add_type(
- struct bContext *C,
- int type, const char *name, const float loc[3], const float rot[3],
- bool enter_editmode, unsigned short local_view_bits)
- ATTR_NONNULL(1) ATTR_RETURNS_NONNULL;
-
-void ED_object_single_users(struct Main *bmain, struct Scene *scene, const bool full, const bool copy_groups);
+bool ED_object_add_generic_get_opts(struct bContext *C,
+ struct wmOperator *op,
+ const char view_align_axis,
+ float loc[3],
+ float rot[3],
+ bool *enter_editmode,
+ unsigned short *local_view_bits,
+ bool *is_view_aligned);
+
+struct Object *ED_object_add_type(struct bContext *C,
+ int type,
+ const char *name,
+ const float loc[3],
+ const float rot[3],
+ bool enter_editmode,
+ unsigned short local_view_bits)
+ ATTR_NONNULL(1) ATTR_RETURNS_NONNULL;
+
+void ED_object_single_users(struct Main *bmain,
+ struct Scene *scene,
+ const bool full,
+ const bool copy_groups);
void ED_object_single_user(struct Main *bmain, struct Scene *scene, struct Object *ob);
/* object motion paths */
void ED_objects_clear_paths(struct bContext *C, bool only_selected);
-void ED_objects_recalculate_paths(struct bContext *C, struct Scene *scene, bool current_frame_only);
+void ED_objects_recalculate_paths(struct bContext *C,
+ struct Scene *scene,
+ bool current_frame_only);
/* constraints */
struct ListBase *get_active_constraints(struct Object *ob);
-struct ListBase *get_constraint_lb(struct Object *ob, struct bConstraint *con, struct bPoseChannel **r_pchan);
+struct ListBase *get_constraint_lb(struct Object *ob,
+ struct bConstraint *con,
+ struct bPoseChannel **r_pchan);
struct bConstraint *get_active_constraint(struct Object *ob);
void object_test_constraints(struct Main *bmain, struct Object *ob);
@@ -206,111 +252,147 @@ void ED_object_constraint_set_active(struct Object *ob, struct bConstraint *con)
void ED_object_constraint_update(struct Main *bmain, struct Object *ob);
void ED_object_constraint_dependency_update(struct Main *bmain, struct Object *ob);
-void ED_object_constraint_tag_update(struct Main *bmain, struct Object *ob, struct bConstraint *con);
-void ED_object_constraint_dependency_tag_update(struct Main *bmain, struct Object *ob, struct bConstraint *con);
+void ED_object_constraint_tag_update(struct Main *bmain,
+ struct Object *ob,
+ struct bConstraint *con);
+void ED_object_constraint_dependency_tag_update(struct Main *bmain,
+ struct Object *ob,
+ struct bConstraint *con);
/* object_modes.c */
bool ED_object_mode_compat_test(const struct Object *ob, eObjectMode mode);
-bool ED_object_mode_compat_set(struct bContext *C, struct Object *ob, eObjectMode mode, struct ReportList *reports);
+bool ED_object_mode_compat_set(struct bContext *C,
+ struct Object *ob,
+ eObjectMode mode,
+ struct ReportList *reports);
void ED_object_mode_toggle(struct bContext *C, eObjectMode mode);
void ED_object_mode_set(struct bContext *C, eObjectMode mode);
void ED_object_mode_exit(struct bContext *C);
-bool ED_object_mode_generic_enter(
- struct bContext *C,
- eObjectMode object_mode);
-void ED_object_mode_generic_exit(
- struct Main *bmain,
- struct Depsgraph *depsgraph,
- struct Scene *scene, struct Object *ob);
-bool ED_object_mode_generic_has_data(
- struct Depsgraph *depsgraph,
- struct Object *ob);
+bool ED_object_mode_generic_enter(struct bContext *C, eObjectMode object_mode);
+void ED_object_mode_generic_exit(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob);
+bool ED_object_mode_generic_has_data(struct Depsgraph *depsgraph, struct Object *ob);
/* object_modifier.c */
enum {
- MODIFIER_APPLY_DATA = 1,
- MODIFIER_APPLY_SHAPE,
+ MODIFIER_APPLY_DATA = 1,
+ MODIFIER_APPLY_SHAPE,
};
-struct ModifierData *ED_object_modifier_add(
- struct ReportList *reports, struct Main *bmain, struct Scene *scene,
- struct Object *ob, const char *name, int type);
-bool ED_object_modifier_remove(struct ReportList *reports, struct Main *bmain,
- struct Object *ob, struct ModifierData *md);
+struct ModifierData *ED_object_modifier_add(struct ReportList *reports,
+ struct Main *bmain,
+ struct Scene *scene,
+ struct Object *ob,
+ const char *name,
+ int type);
+bool ED_object_modifier_remove(struct ReportList *reports,
+ struct Main *bmain,
+ struct Object *ob,
+ struct ModifierData *md);
void ED_object_modifier_clear(struct Main *bmain, struct Object *ob);
-int ED_object_modifier_move_down(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
-int ED_object_modifier_move_up(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
-int ED_object_modifier_convert(
- struct ReportList *reports, struct Main *bmain, struct Depsgraph *depsgraph, struct Scene *scene,
- 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);
-int ED_object_modifier_copy(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
-
-bool ED_object_iter_other(
- struct Main *bmain, struct Object *orig_ob, const bool include_orig,
- bool (*callback)(struct Object *ob, void *callback_data),
- void *callback_data);
+int ED_object_modifier_move_down(struct ReportList *reports,
+ struct Object *ob,
+ struct ModifierData *md);
+int ED_object_modifier_move_up(struct ReportList *reports,
+ struct Object *ob,
+ struct ModifierData *md);
+int ED_object_modifier_convert(struct ReportList *reports,
+ struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ 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);
+int ED_object_modifier_copy(struct ReportList *reports,
+ struct Object *ob,
+ struct ModifierData *md);
+
+bool ED_object_iter_other(struct Main *bmain,
+ struct Object *orig_ob,
+ const bool include_orig,
+ bool (*callback)(struct Object *ob, void *callback_data),
+ void *callback_data);
bool ED_object_multires_update_totlevels_cb(struct Object *ob, void *totlevel_v);
-
/* object_greasepencil_modifier.c */
-struct GpencilModifierData *ED_object_gpencil_modifier_add(
- struct ReportList *reports, struct Main *bmain, struct Scene *scene,
- struct Object *ob, const char *name, int type);
-bool ED_object_gpencil_modifier_remove(
- struct ReportList *reports, struct Main *bmain,
- struct Object *ob, struct GpencilModifierData *md);
-void ED_object_gpencil_modifier_clear(
- struct Main *bmain, struct Object *ob);
-int ED_object_gpencil_modifier_move_down(
- struct ReportList *reports, struct Object *ob, struct GpencilModifierData *md);
-int ED_object_gpencil_modifier_move_up(
- struct ReportList *reports, struct Object *ob, struct GpencilModifierData *md);
-int ED_object_gpencil_modifier_apply(
- struct Main *bmain, struct ReportList *reports, struct Depsgraph *depsgraph,
- struct Object *ob, struct GpencilModifierData *md, int mode);
-int ED_object_gpencil_modifier_copy(
- struct ReportList *reports, struct Object *ob, struct GpencilModifierData *md);
+struct GpencilModifierData *ED_object_gpencil_modifier_add(struct ReportList *reports,
+ struct Main *bmain,
+ struct Scene *scene,
+ struct Object *ob,
+ const char *name,
+ int type);
+bool ED_object_gpencil_modifier_remove(struct ReportList *reports,
+ struct Main *bmain,
+ struct Object *ob,
+ struct GpencilModifierData *md);
+void ED_object_gpencil_modifier_clear(struct Main *bmain, struct Object *ob);
+int ED_object_gpencil_modifier_move_down(struct ReportList *reports,
+ struct Object *ob,
+ struct GpencilModifierData *md);
+int ED_object_gpencil_modifier_move_up(struct ReportList *reports,
+ struct Object *ob,
+ struct GpencilModifierData *md);
+int ED_object_gpencil_modifier_apply(struct Main *bmain,
+ struct ReportList *reports,
+ struct Depsgraph *depsgraph,
+ struct Object *ob,
+ struct GpencilModifierData *md,
+ int mode);
+int ED_object_gpencil_modifier_copy(struct ReportList *reports,
+ struct Object *ob,
+ struct GpencilModifierData *md);
/* object_shader_fx.c */
-struct ShaderFxData *ED_object_shaderfx_add(
- struct ReportList *reports, struct Main *bmain, struct Scene *scene,
- struct Object *ob, const char *name, int type);
-bool ED_object_shaderfx_remove(
- struct ReportList *reports, struct Main *bmain,
- struct Object *ob, struct ShaderFxData *fx);
-void ED_object_shaderfx_clear(
- struct Main *bmain, struct Object *ob);
-int ED_object_shaderfx_move_down(
- struct ReportList *reports, struct Object *ob, struct ShaderFxData *fx);
-int ED_object_shaderfx_move_up(
- struct ReportList *reports, struct Object *ob, struct ShaderFxData *fx);
+struct ShaderFxData *ED_object_shaderfx_add(struct ReportList *reports,
+ struct Main *bmain,
+ struct Scene *scene,
+ struct Object *ob,
+ const char *name,
+ int type);
+bool ED_object_shaderfx_remove(struct ReportList *reports,
+ struct Main *bmain,
+ struct Object *ob,
+ struct ShaderFxData *fx);
+void ED_object_shaderfx_clear(struct Main *bmain, struct Object *ob);
+int ED_object_shaderfx_move_down(struct ReportList *reports,
+ struct Object *ob,
+ struct ShaderFxData *fx);
+int ED_object_shaderfx_move_up(struct ReportList *reports,
+ struct Object *ob,
+ struct ShaderFxData *fx);
/* object_select.c */
void ED_object_select_linked_by_id(struct bContext *C, struct ID *id);
const struct EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(
- const struct bContext *C,
- struct PointerRNA *ptr,
- struct PropertyRNA *prop,
- bool *r_free,
- const unsigned int selection_mask);
+ const struct bContext *C,
+ struct PointerRNA *ptr,
+ struct PropertyRNA *prop,
+ bool *r_free,
+ const unsigned int selection_mask);
-void ED_object_check_force_modifiers(
- struct Main *bmain, struct Scene *scene, struct Object *object);
+void ED_object_check_force_modifiers(struct Main *bmain,
+ struct Scene *scene,
+ struct Object *object);
struct Base *ED_object_find_first_by_data_id(struct ViewLayer *view_layer, struct ID *id);
-bool ED_object_jump_to_object(
- struct bContext *C, struct Object *ob,
- const bool reveal_hidden);
-bool ED_object_jump_to_bone(
- struct bContext *C, struct Object *ob, const char *bone_name,
- const bool reveal_hidden);
+bool ED_object_jump_to_object(struct bContext *C, struct Object *ob, const bool reveal_hidden);
+bool ED_object_jump_to_bone(struct bContext *C,
+ struct Object *ob,
+ const char *bone_name,
+ const bool reveal_hidden);
/* object_facemap_ops.c */
void ED_object_facemap_face_add(struct Object *ob, struct bFaceMap *fmap, int facenum);
diff --git a/source/blender/editors/include/ED_paint.h b/source/blender/editors/include/ED_paint.h
index c59f1b9e927..88cc8a85897 100644
--- a/source/blender/editors/include/ED_paint.h
+++ b/source/blender/editors/include/ED_paint.h
@@ -36,7 +36,8 @@ void ED_keymap_paint(struct wmKeyConfig *keyconf);
/* paint_image.c */
void ED_imapaint_clear_partial_redraw(void);
-void ED_imapaint_dirty_region(struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h, bool find_old);
+void ED_imapaint_dirty_region(
+ struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h, bool find_old);
void ED_imapaint_bucket_fill(struct bContext *C, float color[3], struct wmOperator *op);
/* paint_image_undo.c */
diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h
index 9cb0eb870ab..3ef3c0ba937 100644
--- a/source/blender/editors/include/ED_particle.h
+++ b/source/blender/editors/include/ED_particle.h
@@ -41,22 +41,29 @@ int PE_start_edit(struct PTCacheEdit *edit);
/* access */
struct PTCacheEdit *PE_get_current_from_psys(struct ParticleSystem *psys);
struct PTCacheEdit *PE_get_current(struct Scene *scene, struct Object *ob);
-struct PTCacheEdit *PE_create_current(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob);
+struct PTCacheEdit *PE_create_current(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob);
void PE_current_changed(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob);
int PE_minmax(struct Scene *scene, struct ViewLayer *view_layer, float min[3], float max[3]);
struct ParticleEditSettings *PE_settings(struct Scene *scene);
/* update calls */
void PE_hide_keys_time(struct Scene *scene, struct PTCacheEdit *edit, float cfra);
-void PE_update_object(
- struct Depsgraph *depsgraph, struct Scene *scene,
- struct Object *ob, int useflag);
+void PE_update_object(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob,
+ int useflag);
/* selection tools */
-bool PE_mouse_particles(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
+bool PE_mouse_particles(
+ struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
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 sel_op);
+int PE_lasso_select(struct bContext *C,
+ const int mcords[][2],
+ const short moves,
+ const int sel_op);
bool PE_deselect_all_visible_ex(struct PTCacheEdit *edit);
bool PE_deselect_all_visible(struct bContext *C);
diff --git a/source/blender/editors/include/ED_physics.h b/source/blender/editors/include/ED_physics.h
index f37a5eeb666..1006a9d4f47 100644
--- a/source/blender/editors/include/ED_physics.h
+++ b/source/blender/editors/include/ED_physics.h
@@ -37,11 +37,19 @@ bool PE_hair_poll(struct bContext *C);
bool PE_poll_view3d(struct bContext *C);
/* rigidbody_object.c */
-bool ED_rigidbody_object_add(struct Main *bmain, struct Scene *scene, struct Object *ob, int type, struct ReportList *reports);
+bool ED_rigidbody_object_add(struct Main *bmain,
+ struct Scene *scene,
+ struct Object *ob,
+ int type,
+ struct ReportList *reports);
void ED_rigidbody_object_remove(struct Main *bmain, struct Scene *scene, struct Object *ob);
/* rigidbody_constraint.c */
-bool ED_rigidbody_constraint_add(struct Main *bmain, struct Scene *scene, struct Object *ob, int type, struct ReportList *reports);
+bool ED_rigidbody_constraint_add(struct Main *bmain,
+ struct Scene *scene,
+ struct Object *ob,
+ int type,
+ struct ReportList *reports);
void ED_rigidbody_constraint_remove(struct Main *bmain, struct Scene *scene, struct Object *ob);
/* operators */
diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h
index fd6818d6717..7689a9f97cd 100644
--- a/source/blender/editors/include/ED_render.h
+++ b/source/blender/editors/include/ED_render.h
@@ -65,18 +65,35 @@ struct Scene *ED_render_job_get_current_scene(const struct bContext *C);
*/
enum {
- PR_BUTS_RENDER = 0,
- PR_ICON_RENDER = 1,
- PR_NODE_RENDER = 2,
- PR_ICON_DEFERRED = 3,
+ PR_BUTS_RENDER = 0,
+ PR_ICON_RENDER = 1,
+ PR_NODE_RENDER = 2,
+ PR_ICON_DEFERRED = 3,
};
void ED_preview_ensure_dbase(void);
void ED_preview_free_dbase(void);
-void ED_preview_shader_job(const struct bContext *C, void *owner, struct ID *id, struct ID *parent, struct MTex *slot, int sizex, int sizey, int method);
-void ED_preview_icon_render(struct Main *bmain, struct Scene *scene, struct ID *id, unsigned int *rect, int sizex, int sizey);
-void ED_preview_icon_job(const struct bContext *C, void *owner, struct ID *id, unsigned int *rect, int sizex, int sizey);
+void ED_preview_shader_job(const struct bContext *C,
+ void *owner,
+ struct ID *id,
+ struct ID *parent,
+ struct MTex *slot,
+ int sizex,
+ int sizey,
+ int method);
+void ED_preview_icon_render(struct Main *bmain,
+ struct Scene *scene,
+ struct ID *id,
+ unsigned int *rect,
+ int sizex,
+ int sizey);
+void ED_preview_icon_job(const struct bContext *C,
+ void *owner,
+ struct ID *id,
+ unsigned int *rect,
+ int sizex,
+ int sizey);
void ED_preview_kill_jobs(struct wmWindowManager *wm, struct Main *bmain);
void ED_preview_draw(const struct bContext *C, void *idp, void *parentp, void *slot, rcti *rect);
diff --git a/source/blender/editors/include/ED_scene.h b/source/blender/editors/include/ED_scene.h
index 08ead58fce6..99a9693ad19 100644
--- a/source/blender/editors/include/ED_scene.h
+++ b/source/blender/editors/include/ED_scene.h
@@ -25,12 +25,20 @@
enum eSceneCopyMethod;
-struct Scene *ED_scene_add(struct Main *bmain, struct bContext *C, struct wmWindow *win, enum eSceneCopyMethod method) ATTR_NONNULL();
-bool ED_scene_delete(struct bContext *C, struct Main *bmain, struct wmWindow *win, struct Scene *scene) ATTR_NONNULL();
-void ED_scene_change_update(struct Main *bmain, struct Scene *scene, struct ViewLayer *layer) ATTR_NONNULL();
-bool ED_scene_view_layer_delete(
- struct Main *bmain, struct Scene *scene, struct ViewLayer *layer,
- struct ReportList *reports) ATTR_NONNULL(1, 2, 3);
+struct Scene *ED_scene_add(struct Main *bmain,
+ struct bContext *C,
+ struct wmWindow *win,
+ enum eSceneCopyMethod method) ATTR_NONNULL();
+bool ED_scene_delete(struct bContext *C,
+ struct Main *bmain,
+ struct wmWindow *win,
+ struct Scene *scene) ATTR_NONNULL();
+void ED_scene_change_update(struct Main *bmain, struct Scene *scene, struct ViewLayer *layer)
+ ATTR_NONNULL();
+bool ED_scene_view_layer_delete(struct Main *bmain,
+ struct Scene *scene,
+ struct ViewLayer *layer,
+ struct ReportList *reports) ATTR_NONNULL(1, 2, 3);
void ED_operatortypes_scene(void);
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 10a1eab265a..bcf9cb3fcc0 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -61,101 +61,117 @@ struct wmWindow;
struct wmWindowManager;
/* regions */
-void ED_region_do_listen(
- struct wmWindow *win, struct ScrArea *sa, struct ARegion *ar,
- 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_pixelspace(struct ARegion *ar);
-void ED_region_update_rect(struct ARegion *ar);
-void ED_region_init(struct ARegion *ar);
-void ED_region_tag_redraw(struct ARegion *ar);
-void ED_region_tag_redraw_partial(struct ARegion *ar, const struct rcti *rct);
-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_do_listen(struct wmWindow *win,
+ struct ScrArea *sa,
+ struct ARegion *ar,
+ 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_pixelspace(struct ARegion *ar);
+void ED_region_update_rect(struct ARegion *ar);
+void ED_region_init(struct ARegion *ar);
+void ED_region_tag_redraw(struct ARegion *ar);
+void ED_region_tag_redraw_partial(struct ARegion *ar, const struct rcti *rct);
+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_panels_ex(
- const struct bContext *C, struct ARegion *ar,
- const char *contexts[], int contextnr, const bool vertical);
-void ED_region_panels(
- const struct bContext *C, struct ARegion *ar);
-void ED_region_panels_layout_ex(
- const struct bContext *C, struct ARegion *ar,
- const char *contexts[], int contextnr, const bool vertical);
-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_ex(const struct bContext *C,
+ struct ARegion *ar,
+ const char *contexts[],
+ int contextnr,
+ const bool vertical);
+void ED_region_panels(const struct bContext *C, struct ARegion *ar);
+void ED_region_panels_layout_ex(const struct bContext *C,
+ struct ARegion *ar,
+ const char *contexts[],
+ int contextnr,
+ const bool vertical);
+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_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_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_visibility_change_update(struct bContext *C, struct ARegion *ar);
-void ED_region_info_draw(struct ARegion *ar, const char *text, float fill_color[4], const bool full_redraw);
-void ED_region_info_draw_multiline(ARegion *ar, 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 ED_region_blend_alpha(struct ARegion *ar);
-void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect);
-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);
+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_visibility_change_update(struct bContext *C, struct ARegion *ar);
+void ED_region_info_draw(struct ARegion *ar,
+ const char *text,
+ float fill_color[4],
+ const bool full_redraw);
+void ED_region_info_draw_multiline(ARegion *ar,
+ 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 ED_region_blend_alpha(struct ARegion *ar);
+void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect);
+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);
/* message_bus callbacks */
-void ED_region_do_msg_notify_tag_redraw(
- struct bContext *C, struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val);
-void ED_area_do_msg_notify_tag_refresh(
- struct bContext *C, struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val);
+void ED_region_do_msg_notify_tag_redraw(struct bContext *C,
+ struct wmMsgSubscribeKey *msg_key,
+ struct wmMsgSubscribeValue *msg_val);
+void ED_area_do_msg_notify_tag_refresh(struct bContext *C,
+ struct wmMsgSubscribeKey *msg_key,
+ struct wmMsgSubscribeValue *msg_val);
/* message bus */
-void ED_region_message_subscribe(
- struct bContext *C,
- struct WorkSpace *workspace, struct Scene *scene,
- struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar,
- struct wmMsgBus *mbus);
+void ED_region_message_subscribe(struct bContext *C,
+ struct WorkSpace *workspace,
+ struct Scene *scene,
+ struct bScreen *screen,
+ struct ScrArea *sa,
+ struct ARegion *ar,
+ struct wmMsgBus *mbus);
/* spaces */
-void ED_spacetypes_keymap(struct wmKeyConfig *keyconf);
-int ED_area_header_switchbutton(const struct bContext *C, struct uiBlock *block, int yco);
+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);
-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);
+void ED_area_initialize(struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *sa);
+void ED_area_exit(struct bContext *C, struct ScrArea *sa);
+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_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);
-int ED_area_header_alignment(const ScrArea *area);
-int ED_area_footersize(void);
-int ED_area_footer_alignment_or_fallback(const ScrArea *area, int fallback);
-int ED_area_footer_alignment(const ScrArea *area);
-int ED_area_global_size_y(const ScrArea *area);
-int ED_area_global_min_size_y(const ScrArea *area);
-int ED_area_global_max_size_y(const ScrArea *area);
-bool ED_area_is_global(const ScrArea *area);
-int ED_region_global_size_y(void);
-void ED_area_update_region_sizes(struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *area);
+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_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);
+int ED_area_header_alignment(const ScrArea *area);
+int ED_area_footersize(void);
+int ED_area_footer_alignment_or_fallback(const ScrArea *area, int fallback);
+int ED_area_footer_alignment(const ScrArea *area);
+int ED_area_global_size_y(const ScrArea *area);
+int ED_area_global_min_size_y(const ScrArea *area);
+int ED_area_global_max_size_y(const ScrArea *area);
+bool ED_area_is_global(const ScrArea *area);
+int ED_region_global_size_y(void);
+void ED_area_update_region_sizes(struct wmWindowManager *wm,
+ struct wmWindow *win,
+ struct ScrArea *area);
ScrArea *ED_screen_areas_iter_first(const struct wmWindow *win, const bScreen *screen);
ScrArea *ED_screen_areas_iter_next(const bScreen *screen, const ScrArea *area);
@@ -164,94 +180,105 @@ ScrArea *ED_screen_areas_iter_next(const bScreen *screen, const ScrArea *area);
* visible in the window, not just bScreen).
* \note Skips global areas with flag GLOBAL_AREA_IS_HIDDEN.
*/
-#define ED_screen_areas_iter(win, screen, area_name) \
- for (ScrArea *area_name = ED_screen_areas_iter_first(win, screen); \
- area_name != NULL; \
- area_name = ED_screen_areas_iter_next(screen, area_name))
-#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; \
- vert_name != NULL; \
- vert_name = (vert_name == (win)->global_areas.vertbase.last) ? (screen)->vertbase.first : vert_name->next)
+#define ED_screen_areas_iter(win, screen, area_name) \
+ for (ScrArea *area_name = ED_screen_areas_iter_first(win, screen); area_name != NULL; \
+ area_name = ED_screen_areas_iter_next(screen, area_name))
+#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; \
+ vert_name != NULL; \
+ vert_name = (vert_name == (win)->global_areas.vertbase.last) ? (screen)->vertbase.first : \
+ vert_name->next)
/* screens */
-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_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);
-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);
+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_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);
+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);
-struct ScrArea *ED_screen_state_toggle(struct bContext *C, struct wmWindow *win, struct ScrArea *sa, const short state);
-void ED_screens_header_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
-void ED_screens_footer_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
-void ED_screens_navigation_bar_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
-bool ED_screen_stereo3d_required(const struct bScreen *screen, const struct Scene *scene);
-Scene *ED_screen_scene_find(const struct bScreen *screen, const struct wmWindowManager *wm);
-Scene *ED_screen_scene_find_with_window(const struct bScreen *screen, const struct wmWindowManager *wm, struct wmWindow **r_window);
-ScrArea *ED_screen_area_find_with_spacedata(const bScreen *screen, const struct SpaceLink *sl, const bool only_visible);
-struct wmWindow *ED_screen_window_find(const struct bScreen *screen, const struct wmWindowManager *wm);
-void ED_screen_preview_render(const struct bScreen *screen, int size_x, int size_y, unsigned int *r_rect) ATTR_NONNULL();
+void ED_screen_full_prevspace(struct bContext *C, ScrArea *sa);
+void ED_screen_full_restore(struct bContext *C, ScrArea *sa);
+struct ScrArea *ED_screen_state_toggle(struct bContext *C,
+ struct wmWindow *win,
+ struct ScrArea *sa,
+ const short state);
+void ED_screens_header_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
+void ED_screens_footer_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
+void ED_screens_navigation_bar_tools_menu_create(struct bContext *C,
+ struct uiLayout *layout,
+ void *arg);
+bool ED_screen_stereo3d_required(const struct bScreen *screen, const struct Scene *scene);
+Scene *ED_screen_scene_find(const struct bScreen *screen, const struct wmWindowManager *wm);
+Scene *ED_screen_scene_find_with_window(const struct bScreen *screen,
+ const struct wmWindowManager *wm,
+ struct wmWindow **r_window);
+ScrArea *ED_screen_area_find_with_spacedata(const bScreen *screen,
+ const struct SpaceLink *sl,
+ const bool only_visible);
+struct wmWindow *ED_screen_window_find(const struct bScreen *screen,
+ const struct wmWindowManager *wm);
+void ED_screen_preview_render(const struct bScreen *screen,
+ int size_x,
+ int size_y,
+ unsigned int *r_rect) ATTR_NONNULL();
/* workspaces */
-struct WorkSpace *ED_workspace_add(
- struct Main *bmain,
- const char *name) ATTR_NONNULL();
-bool ED_workspace_change(
- struct WorkSpace *workspace_new,
- struct bContext *C,
- struct wmWindowManager *wm, struct wmWindow *win) ATTR_NONNULL();
-struct WorkSpace *ED_workspace_duplicate(
- struct WorkSpace *workspace_old,
- struct Main *bmain, struct wmWindow *win);
-bool ED_workspace_delete(
- struct WorkSpace *workspace,
- struct Main *bmain, struct bContext *C,
- struct wmWindowManager *wm) ATTR_NONNULL();
-void ED_workspace_scene_data_sync(
- struct WorkSpaceInstanceHook *hook, Scene *scene) ATTR_NONNULL();
-struct WorkSpaceLayout *ED_workspace_layout_add(
- struct Main *bmain,
- struct WorkSpace *workspace,
- struct wmWindow *win,
- const char *name) ATTR_NONNULL();
-struct WorkSpaceLayout *ED_workspace_layout_duplicate(
- struct Main *bmain,
- struct WorkSpace *workspace, const struct WorkSpaceLayout *layout_old,
- struct wmWindow *win) ATTR_NONNULL();
-bool ED_workspace_layout_delete(
- struct WorkSpace *workspace, struct WorkSpaceLayout *layout_old,
- struct bContext *C) ATTR_NONNULL();
-bool ED_workspace_layout_cycle(
- struct WorkSpace *workspace, const short direction,
- struct bContext *C) ATTR_NONNULL();
-
-void ED_workspace_status_text(struct bContext *C, const char *str);
+struct WorkSpace *ED_workspace_add(struct Main *bmain, const char *name) ATTR_NONNULL();
+bool ED_workspace_change(struct WorkSpace *workspace_new,
+ struct bContext *C,
+ struct wmWindowManager *wm,
+ struct wmWindow *win) ATTR_NONNULL();
+struct WorkSpace *ED_workspace_duplicate(struct WorkSpace *workspace_old,
+ struct Main *bmain,
+ struct wmWindow *win);
+bool ED_workspace_delete(struct WorkSpace *workspace,
+ struct Main *bmain,
+ struct bContext *C,
+ struct wmWindowManager *wm) ATTR_NONNULL();
+void ED_workspace_scene_data_sync(struct WorkSpaceInstanceHook *hook, Scene *scene) ATTR_NONNULL();
+struct WorkSpaceLayout *ED_workspace_layout_add(struct Main *bmain,
+ struct WorkSpace *workspace,
+ struct wmWindow *win,
+ const char *name) ATTR_NONNULL();
+struct WorkSpaceLayout *ED_workspace_layout_duplicate(struct Main *bmain,
+ struct WorkSpace *workspace,
+ const struct WorkSpaceLayout *layout_old,
+ struct wmWindow *win) ATTR_NONNULL();
+bool ED_workspace_layout_delete(struct WorkSpace *workspace,
+ struct WorkSpaceLayout *layout_old,
+ struct bContext *C) ATTR_NONNULL();
+bool ED_workspace_layout_cycle(struct WorkSpace *workspace,
+ const short direction,
+ struct bContext *C) ATTR_NONNULL();
+
+void ED_workspace_status_text(struct bContext *C, const char *str);
/* anim */
-void ED_update_for_newframe(struct Main *bmain, struct Depsgraph *depsgraph);
+void ED_update_for_newframe(struct Main *bmain, struct Depsgraph *depsgraph);
-void ED_refresh_viewport_fps(struct bContext *C);
-int ED_screen_animation_play(struct bContext *C, int sync, int mode);
-bScreen *ED_screen_animation_playing(const struct wmWindowManager *wm);
+void ED_refresh_viewport_fps(struct bContext *C);
+int ED_screen_animation_play(struct bContext *C, int sync, int mode);
+bScreen *ED_screen_animation_playing(const struct wmWindowManager *wm);
bScreen *ED_screen_animation_no_scrub(const struct wmWindowManager *wm);
/* screen keymaps */
-void ED_operatortypes_screen(void);
-void ED_keymap_screen(struct wmKeyConfig *keyconf);
+void ED_operatortypes_screen(void);
+void ED_keymap_screen(struct wmKeyConfig *keyconf);
/* workspace keymaps */
-void ED_operatortypes_workspace(void);
+void ED_operatortypes_workspace(void);
/* operators; context poll callbacks */
bool ED_operator_screenactive(struct bContext *C);
@@ -281,7 +308,6 @@ bool ED_operator_nla_active(struct bContext *C);
bool ED_operator_info_active(struct bContext *C);
bool ED_operator_console_active(struct bContext *C);
-
bool ED_operator_object_active(struct bContext *C);
bool ED_operator_object_active_editable(struct bContext *C);
bool ED_operator_object_active_editable_mesh(struct bContext *C);
@@ -314,43 +340,52 @@ bool ED_operator_camera(struct bContext *C);
bUserMenu **ED_screen_user_menus_find(const struct bContext *C, uint *r_len);
struct bUserMenu *ED_screen_user_menu_ensure(struct bContext *C);
-
-struct bUserMenuItem_Op *ED_screen_user_menu_item_find_operator(
- struct ListBase *lb,
- const struct wmOperatorType *ot, struct IDProperty *prop, short opcontext);
-struct bUserMenuItem_Menu *ED_screen_user_menu_item_find_menu(
- struct ListBase *lb,
- const struct MenuType *mt);
-struct bUserMenuItem_Prop *ED_screen_user_menu_item_find_prop(
- struct ListBase *lb,
- const char *context_data_path, const char *prop_id, int prop_index);
-
-void ED_screen_user_menu_item_add_operator(
- struct ListBase *lb, const char *ui_name,
- const struct wmOperatorType *ot, const struct IDProperty *prop, short opcontext);
-void ED_screen_user_menu_item_add_menu(
- struct ListBase *lb, const char *ui_name,
- const struct MenuType *mt);
-void ED_screen_user_menu_item_add_prop(
- ListBase *lb, const char *ui_name,
- const char *context_data_path, const char *prop_id, int prop_index);
-
-void ED_screen_user_menu_item_remove(
- struct ListBase *lb, struct bUserMenuItem *umi);
+struct bUserMenuItem_Op *ED_screen_user_menu_item_find_operator(struct ListBase *lb,
+ const struct wmOperatorType *ot,
+ struct IDProperty *prop,
+ short opcontext);
+struct bUserMenuItem_Menu *ED_screen_user_menu_item_find_menu(struct ListBase *lb,
+ const struct MenuType *mt);
+struct bUserMenuItem_Prop *ED_screen_user_menu_item_find_prop(struct ListBase *lb,
+ const char *context_data_path,
+ const char *prop_id,
+ int prop_index);
+
+void ED_screen_user_menu_item_add_operator(struct ListBase *lb,
+ const char *ui_name,
+ const struct wmOperatorType *ot,
+ const struct IDProperty *prop,
+ short opcontext);
+void ED_screen_user_menu_item_add_menu(struct ListBase *lb,
+ const char *ui_name,
+ const struct MenuType *mt);
+void ED_screen_user_menu_item_add_prop(ListBase *lb,
+ const char *ui_name,
+ const char *context_data_path,
+ const char *prop_id,
+ int prop_index);
+
+void ED_screen_user_menu_item_remove(struct ListBase *lb, struct bUserMenuItem *umi);
void ED_screen_user_menu_register(void);
/* Cache display helpers */
void ED_region_cache_draw_background(const struct ARegion *ar);
void ED_region_cache_draw_curfra_label(const int framenr, const float x, const float y);
-void ED_region_cache_draw_cached_segments(const struct ARegion *ar, const int num_segments, const int *points, const int sfra, const int efra);
+void ED_region_cache_draw_cached_segments(const struct ARegion *ar,
+ 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 wmMsgBus *mbus);
+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 wmMsgBus *mbus);
int ED_region_generic_tools_region_snap_size(const struct ARegion *ar, int size, int axis);
/* interface_region_hud.c */
@@ -360,22 +395,22 @@ void ED_area_type_hud_ensure(struct bContext *C, struct ScrArea *sa);
/* default keymaps, bitflags (matches order of evaluation). */
enum {
- ED_KEYMAP_UI = (1 << 1),
- 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),
- ED_KEYMAP_GPENCIL = (1 << 9),
- ED_KEYMAP_FOOTER = (1 << 10),
+ ED_KEYMAP_UI = (1 << 1),
+ 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),
+ ED_KEYMAP_GPENCIL = (1 << 9),
+ ED_KEYMAP_FOOTER = (1 << 10),
};
/* SCREEN_OT_space_context_cycle direction */
enum {
- SPACE_CONTEXT_CYCLE_PREV,
- SPACE_CONTEXT_CYCLE_NEXT,
+ SPACE_CONTEXT_CYCLE_PREV,
+ SPACE_CONTEXT_CYCLE_NEXT,
};
#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 46b8a9b34de..3cbeab247ef 100644
--- a/source/blender/editors/include/ED_screen_types.h
+++ b/source/blender/editors/include/ED_screen_types.h
@@ -28,28 +28,28 @@
/* for animplayer */
typedef struct ScreenAnimData {
- ARegion *ar; /* 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 */
+ ARegion *ar; /* 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 */
} ScreenAnimData;
/* for animplayer */
enum {
- /* user-setting - frame range is played backwards */
- ANIMPLAY_FLAG_REVERSE = (1 << 0),
- /* temporary - playback just jumped to the start/end */
- ANIMPLAY_FLAG_JUMPED = (1 << 1),
- /* drop frames as needed to maintain framerate */
- ANIMPLAY_FLAG_SYNC = (1 << 2),
- /* don't drop frames (and ignore SCE_FRAME_DROP flag) */
- ANIMPLAY_FLAG_NO_SYNC = (1 << 3),
- /* use nextfra at next timer update */
- ANIMPLAY_FLAG_USE_NEXT_FRAME = (1 << 4),
+ /* user-setting - frame range is played backwards */
+ ANIMPLAY_FLAG_REVERSE = (1 << 0),
+ /* temporary - playback just jumped to the start/end */
+ ANIMPLAY_FLAG_JUMPED = (1 << 1),
+ /* drop frames as needed to maintain framerate */
+ ANIMPLAY_FLAG_SYNC = (1 << 2),
+ /* don't drop frames (and ignore SCE_FRAME_DROP flag) */
+ ANIMPLAY_FLAG_NO_SYNC = (1 << 3),
+ /* use nextfra at next timer update */
+ ANIMPLAY_FLAG_USE_NEXT_FRAME = (1 << 4),
};
/* ----------------------------------------------------- */
@@ -60,64 +60,64 @@ enum {
* stored during runtime as scene->fps_info
*/
typedef struct ScreenFrameRateInfo {
- double redrawtime;
- double lredrawtime;
- float redrawtimes_fps[REDRAW_FRAME_AVERAGE];
- short redrawtime_index;
+ double redrawtime;
+ double lredrawtime;
+ float redrawtimes_fps[REDRAW_FRAME_AVERAGE];
+ short redrawtime_index;
} ScreenFrameRateInfo;
/* ----------------------------------------------------- */
/* Enum for Action Zone Edges. Which edge of area is action zone. */
typedef enum {
- /** Region located on the left, _right_ edge is action zone.
- * Region minimized to the top left */
- AE_RIGHT_TO_TOPLEFT,
- /** Region located on the right, _left_ edge is action zone.
- * Region minimized to the top right */
- AE_LEFT_TO_TOPRIGHT,
- /** Region located at the bottom, _top_ edge is action zone.
- * Region minimized to the bottom right */
- AE_TOP_TO_BOTTOMRIGHT,
- /** Region located at the top, _bottom_ edge is action zone.
- * Region minimized to the top left */
- AE_BOTTOM_TO_TOPLEFT,
+ /** Region located on the left, _right_ edge is action zone.
+ * Region minimized to the top left */
+ AE_RIGHT_TO_TOPLEFT,
+ /** Region located on the right, _left_ edge is action zone.
+ * Region minimized to the top right */
+ AE_LEFT_TO_TOPRIGHT,
+ /** Region located at the bottom, _top_ edge is action zone.
+ * Region minimized to the bottom right */
+ AE_TOP_TO_BOTTOMRIGHT,
+ /** Region located at the top, _bottom_ edge is action zone.
+ * Region minimized to the top left */
+ AE_BOTTOM_TO_TOPLEFT,
} AZEdge;
typedef enum {
- AZ_SCROLL_VERT,
- AZ_SCROLL_HOR,
+ AZ_SCROLL_VERT,
+ AZ_SCROLL_HOR,
} AZScrollDirection;
/* for editing areas/regions */
typedef struct AZone {
- struct AZone *next, *prev;
- ARegion *ar;
- int type;
+ struct AZone *next, *prev;
+ ARegion *ar;
+ int type;
- union {
- /* region-azone, which of the edges (only for AZONE_REGION) */
- AZEdge edge;
- AZScrollDirection direction;
- };
- /* for draw */
- short x1, y1, x2, y2;
- /* for clip */
- rcti rect;
- /* for fade in/out */
- float alpha;
+ union {
+ /* region-azone, which of the edges (only for AZONE_REGION) */
+ AZEdge edge;
+ AZScrollDirection direction;
+ };
+ /* for draw */
+ short x1, y1, x2, y2;
+ /* for clip */
+ rcti rect;
+ /* for fade in/out */
+ float alpha;
} AZone;
/* actionzone type */
enum {
- /* corner widgets for splitting areas */
- AZONE_AREA = 1,
- /* when a region is collapsed, draw a handle to expose */
- AZONE_REGION,
- /* when in editor fullscreen draw a corner to go to normal mode */
- AZONE_FULLSCREEN,
- /* Hotspot azone around scrollbars to show/hide them. */
- AZONE_REGION_SCROLL,
+ /* corner widgets for splitting areas */
+ AZONE_AREA = 1,
+ /* when a region is collapsed, draw a handle to expose */
+ AZONE_REGION,
+ /* when in editor fullscreen draw a corner to go to normal mode */
+ AZONE_FULLSCREEN,
+ /* Hotspot azone around scrollbars to show/hide them. */
+ AZONE_REGION_SCROLL,
};
#endif /* __ED_SCREEN_TYPES_H__ */
diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h
index 31b642165cd..86e108a26c6 100644
--- a/source/blender/editors/include/ED_sculpt.h
+++ b/source/blender/editors/include/ED_sculpt.h
@@ -37,7 +37,10 @@ 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);
-bool ED_sculpt_mask_box_select(struct bContext *C, struct ViewContext *vc, const struct rcti *rect, bool select);
+bool ED_sculpt_mask_box_select(struct bContext *C,
+ struct ViewContext *vc,
+ const struct rcti *rect,
+ bool select);
/* sculpt_undo.c */
void ED_sculpt_undosys_type(struct UndoType *ut);
diff --git a/source/blender/editors/include/ED_select_utils.h b/source/blender/editors/include/ED_select_utils.h
index 04ea1769c09..954e4335608 100644
--- a/source/blender/editors/include/ED_select_utils.h
+++ b/source/blender/editors/include/ED_select_utils.h
@@ -24,26 +24,26 @@
struct KDTree_1d;
enum {
- SEL_TOGGLE = 0,
- SEL_SELECT = 1,
- SEL_DESELECT = 2,
- SEL_INVERT = 3,
+ SEL_TOGGLE = 0,
+ SEL_SELECT = 1,
+ SEL_DESELECT = 2,
+ SEL_INVERT = 3,
};
/** See #WM_operator_properties_select_operation */
typedef enum {
- SEL_OP_ADD = 1,
- SEL_OP_SUB,
- SEL_OP_SET,
- SEL_OP_AND,
- SEL_OP_XOR,
+ SEL_OP_ADD = 1,
+ SEL_OP_SUB,
+ SEL_OP_SET,
+ SEL_OP_AND,
+ SEL_OP_XOR,
} eSelectOp;
/* Select Similar */
enum {
- SIM_CMP_EQ = 0,
- SIM_CMP_GT,
- SIM_CMP_LT,
+ SIM_CMP_EQ = 0,
+ SIM_CMP_GT,
+ SIM_CMP_LT,
};
#define SEL_OP_USE_OUTSIDE(sel_op) (ELEM(sel_op, SEL_OP_AND))
@@ -52,11 +52,16 @@ enum {
/* Use when we've de-selected all first for 'SEL_OP_SET' */
int ED_select_op_action(const eSelectOp sel_op, const bool is_select, const bool is_inside);
-int ED_select_op_action_deselected(const eSelectOp sel_op, const bool is_select, const bool is_inside);
+int ED_select_op_action_deselected(const eSelectOp sel_op,
+ const bool is_select,
+ const bool is_inside);
int ED_select_similar_compare_float(const float delta, const float thresh, const int compare);
-bool ED_select_similar_compare_float_tree(const struct KDTree_1d *tree, const float length, const float thresh, const int compare);
+bool ED_select_similar_compare_float_tree(const struct KDTree_1d *tree,
+ const float length,
+ const float thresh,
+ const int compare);
eSelectOp ED_select_op_modal(const eSelectOp sel_op, const bool is_first);
-#endif /* __ED_SELECT_UTILS_H__ */
+#endif /* __ED_SELECT_UTILS_H__ */
diff --git a/source/blender/editors/include/ED_sequencer.h b/source/blender/editors/include/ED_sequencer.h
index 38f07e83572..2e89af4bb3f 100644
--- a/source/blender/editors/include/ED_sequencer.h
+++ b/source/blender/editors/include/ED_sequencer.h
@@ -28,7 +28,9 @@ struct Sequence;
struct SpaceSeq;
struct bContext;
-void ED_sequencer_select_sequence_single(struct Scene *scene, struct Sequence *seq, bool deselect_all);
+void ED_sequencer_select_sequence_single(struct Scene *scene,
+ struct Sequence *seq,
+ bool deselect_all);
void ED_sequencer_deselect_all(struct Scene *scene);
bool ED_space_sequencer_maskedit_mask_poll(struct bContext *C);
@@ -41,7 +43,7 @@ bool ED_space_sequencer_check_show_strip(struct SpaceSeq *sseq);
void ED_operatormacros_sequencer(void);
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);
+void ED_sequencer_special_preview_set(struct bContext *C, const int mval[2]);
+void ED_sequencer_special_preview_clear(void);
#endif /* __ED_SEQUENCER_H__ */
diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h
index 8495af9b36a..01de5fd8441 100644
--- a/source/blender/editors/include/ED_space_api.h
+++ b/source/blender/editors/include/ED_space_api.h
@@ -59,13 +59,14 @@ void ED_spacetype_topbar(void);
void ED_file_init(void);
void ED_file_exit(void);
-#define REGION_DRAW_POST_VIEW 0
-#define REGION_DRAW_POST_PIXEL 1
-#define REGION_DRAW_PRE_VIEW 2
+#define REGION_DRAW_POST_VIEW 0
+#define REGION_DRAW_POST_PIXEL 1
+#define REGION_DRAW_PRE_VIEW 2
void *ED_region_draw_cb_activate(struct ARegionType *,
void (*draw)(const struct bContext *, struct ARegion *, void *),
- void *custumdata, int type);
+ void *custumdata,
+ int type);
void ED_region_draw_cb_draw(const struct bContext *, struct ARegion *, int);
void ED_region_draw_cb_exit(struct ARegionType *, void *);
/* generic callbacks */
diff --git a/source/blender/editors/include/ED_text.h b/source/blender/editors/include/ED_text.h
index 1260c531f54..7638249d49a 100644
--- a/source/blender/editors/include/ED_text.h
+++ b/source/blender/editors/include/ED_text.h
@@ -29,7 +29,10 @@ struct SpaceText;
struct TextUndoBuf;
struct UndoType;
-bool ED_text_region_location_from_cursor(struct SpaceText *st, struct ARegion *ar, const int cursor_co[2], int r_pixel_co[2]);
+bool ED_text_region_location_from_cursor(struct SpaceText *st,
+ struct ARegion *ar,
+ const int cursor_co[2],
+ int r_pixel_co[2]);
/* text_undo.c */
void ED_text_undosys_type(struct UndoType *ut);
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index 18573e92926..3605a245187 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -47,62 +47,65 @@ void transform_operatortypes(void);
/* MODE AND NUMINPUT FLAGS */
enum TfmMode {
- TFM_INIT = -1,
- TFM_DUMMY,
- TFM_TRANSLATION,
- TFM_ROTATION,
- TFM_RESIZE,
- TFM_SKIN_RESIZE,
- TFM_TOSPHERE,
- TFM_SHEAR,
- TFM_BEND,
- TFM_SHRINKFATTEN,
- TFM_TILT,
- TFM_TRACKBALL,
- TFM_PUSHPULL,
- TFM_CREASE,
- TFM_MIRROR,
- TFM_BONESIZE,
- TFM_BONE_ENVELOPE,
- TFM_CURVE_SHRINKFATTEN,
- TFM_MASK_SHRINKFATTEN,
- TFM_GPENCIL_SHRINKFATTEN,
- TFM_BONE_ROLL,
- TFM_TIME_TRANSLATE,
- TFM_TIME_SLIDE,
- TFM_TIME_SCALE,
- TFM_TIME_EXTEND,
- TFM_TIME_DUPLICATE,
- TFM_BAKE_TIME,
- TFM_DEPRECATED, /* was BEVEL */
- TFM_BWEIGHT,
- TFM_ALIGN,
- TFM_EDGE_SLIDE,
- TFM_VERT_SLIDE,
- TFM_SEQ_SLIDE,
- TFM_BONE_ENVELOPE_DIST,
- TFM_NORMAL_ROTATION,
- TFM_GPENCIL_OPACITY,
+ TFM_INIT = -1,
+ TFM_DUMMY,
+ TFM_TRANSLATION,
+ TFM_ROTATION,
+ TFM_RESIZE,
+ TFM_SKIN_RESIZE,
+ TFM_TOSPHERE,
+ TFM_SHEAR,
+ TFM_BEND,
+ TFM_SHRINKFATTEN,
+ TFM_TILT,
+ TFM_TRACKBALL,
+ TFM_PUSHPULL,
+ TFM_CREASE,
+ TFM_MIRROR,
+ TFM_BONESIZE,
+ TFM_BONE_ENVELOPE,
+ TFM_CURVE_SHRINKFATTEN,
+ TFM_MASK_SHRINKFATTEN,
+ TFM_GPENCIL_SHRINKFATTEN,
+ TFM_BONE_ROLL,
+ TFM_TIME_TRANSLATE,
+ TFM_TIME_SLIDE,
+ TFM_TIME_SCALE,
+ TFM_TIME_EXTEND,
+ TFM_TIME_DUPLICATE,
+ TFM_BAKE_TIME,
+ TFM_DEPRECATED, /* was BEVEL */
+ TFM_BWEIGHT,
+ TFM_ALIGN,
+ TFM_EDGE_SLIDE,
+ TFM_VERT_SLIDE,
+ TFM_SEQ_SLIDE,
+ TFM_BONE_ENVELOPE_DIST,
+ TFM_NORMAL_ROTATION,
+ TFM_GPENCIL_OPACITY,
};
/* TRANSFORM CONTEXTS */
-#define CTX_NONE 0
-#define CTX_TEXTURE (1 << 0)
-#define CTX_EDGE (1 << 1)
-#define CTX_NO_PET (1 << 2)
-#define CTX_NO_MIRROR (1 << 3)
-#define CTX_AUTOCONFIRM (1 << 4)
-#define CTX_MOVIECLIP (1 << 6)
-#define CTX_MASK (1 << 7)
-#define CTX_PAINT_CURVE (1 << 8)
+#define CTX_NONE 0
+#define CTX_TEXTURE (1 << 0)
+#define CTX_EDGE (1 << 1)
+#define CTX_NO_PET (1 << 2)
+#define CTX_NO_MIRROR (1 << 3)
+#define CTX_AUTOCONFIRM (1 << 4)
+#define CTX_MOVIECLIP (1 << 6)
+#define CTX_MASK (1 << 7)
+#define CTX_PAINT_CURVE (1 << 8)
#define CTX_GPENCIL_STROKES (1 << 9)
-#define CTX_CURSOR (1 << 10)
+#define CTX_CURSOR (1 << 10)
/* Standalone call to get the transformation center corresponding to the current situation
* returns 1 if successful, 0 otherwise (usually means there's no selection)
* (if 0 is returns, *vec is unmodified)
* */
-bool calculateTransformCenter(struct bContext *C, int centerMode, float cent3d[3], float cent2d[2]);
+bool calculateTransformCenter(struct bContext *C,
+ int centerMode,
+ float cent3d[3],
+ float cent2d[2]);
struct Object;
struct Scene;
@@ -121,34 +124,39 @@ 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, struct ReportList *reports,
- const char *name, const bool use_view,
- const bool activate, const bool overwrite);
+void BIF_createTransformOrientation(struct bContext *C,
+ struct ReportList *reports,
+ const char *name,
+ const bool use_view,
+ const bool activate,
+ const bool overwrite);
void BIF_selectTransformOrientation(struct bContext *C, struct TransformOrientation *ts);
-void ED_getTransformOrientationMatrix(const struct bContext *C, float orientation_mat[3][3], const short around);
+void ED_getTransformOrientationMatrix(const struct bContext *C,
+ float orientation_mat[3][3],
+ const short around);
int BIF_countTransformOrientation(const struct bContext *C);
/* to be able to add operator properties to other operators */
-#define P_MIRROR (1 << 0)
-#define P_MIRROR_DUMMY (P_MIRROR | (1 << 9))
-#define P_PROPORTIONAL (1 << 1)
+#define P_MIRROR (1 << 0)
+#define P_MIRROR_DUMMY (P_MIRROR | (1 << 9))
+#define P_PROPORTIONAL (1 << 1)
#define P_ORIENT_AXIS (1 << 2)
#define P_ORIENT_AXIS_ORTHO (1 << 16)
#define P_ORIENT_MATRIX (1 << 17)
-#define P_SNAP (1 << 3)
-#define P_GEO_SNAP (P_SNAP | (1 << 4))
-#define P_ALIGN_SNAP (P_GEO_SNAP | (1 << 5))
-#define P_CONSTRAINT (1 << 6)
-#define P_OPTIONS (1 << 7)
-#define P_CORRECT_UV (1 << 8)
-#define P_NO_DEFAULTS (1 << 10)
-#define P_NO_TEXSPACE (1 << 11)
-#define P_CENTER (1 << 12)
-#define P_GPENCIL_EDIT (1 << 13)
-#define P_CURSOR_EDIT (1 << 14)
+#define P_SNAP (1 << 3)
+#define P_GEO_SNAP (P_SNAP | (1 << 4))
+#define P_ALIGN_SNAP (P_GEO_SNAP | (1 << 5))
+#define P_CONSTRAINT (1 << 6)
+#define P_OPTIONS (1 << 7)
+#define P_CORRECT_UV (1 << 8)
+#define P_NO_DEFAULTS (1 << 10)
+#define P_NO_TEXSPACE (1 << 11)
+#define P_CENTER (1 << 12)
+#define P_GPENCIL_EDIT (1 << 13)
+#define P_CURSOR_EDIT (1 << 14)
#define P_CLNOR_INVALIDATE (1 << 15)
void Transform_Properties(struct wmOperatorType *ot, int flags);
@@ -168,64 +176,70 @@ void ED_widgetgroup_gizmo2d_setup(const struct bContext *C, struct wmGizmoGroup
void ED_widgetgroup_gizmo2d_refresh(const struct bContext *C, struct wmGizmoGroup *gzgroup);
void ED_widgetgroup_gizmo2d_draw_prepare(const struct bContext *C, struct wmGizmoGroup *gzgroup);
-
/* Snapping */
#define SNAP_MIN_DISTANCE 30
#define SNAP_INCREMENTAL_ANGLE DEG2RAD(5.0)
-bool peelObjectsTransform(
- struct TransInfo *t,
- const float mval[2],
- const bool use_peel_object,
- /* return args */
- 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);
-
-bool snapObjectsTransform(
- struct TransInfo *t, const float mval[2],
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3]);
-bool snapNodesTransform(
- struct TransInfo *t, const int mval[2],
- /* return args */
- float r_loc[2], float *r_dist_px, char *r_node_border);
-
-void ED_transform_calc_orientation_from_type(
- const struct bContext *C, float r_mat[3][3]);
- void ED_transform_calc_orientation_from_type_ex(
- const struct bContext *C, float r_mat[3][3],
- /* extra args */
- struct Scene *scene, struct RegionView3D *rv3d, struct Object *ob, struct Object *obedit,
- const short orientation_type, int orientation_index_custom,
- const int pivot_point);
+bool peelObjectsTransform(struct TransInfo *t,
+ const float mval[2],
+ const bool use_peel_object,
+ /* return args */
+ 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);
+
+bool snapObjectsTransform(struct TransInfo *t,
+ const float mval[2],
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3]);
+bool snapNodesTransform(struct TransInfo *t,
+ const int mval[2],
+ /* return args */
+ float r_loc[2],
+ float *r_dist_px,
+ char *r_node_border);
+
+void ED_transform_calc_orientation_from_type(const struct bContext *C, float r_mat[3][3]);
+void ED_transform_calc_orientation_from_type_ex(const struct bContext *C,
+ float r_mat[3][3],
+ /* extra args */
+ struct Scene *scene,
+ struct RegionView3D *rv3d,
+ struct Object *ob,
+ struct Object *obedit,
+ const short orientation_type,
+ int orientation_index_custom,
+ const int pivot_point);
struct TransformBounds {
- float center[3]; /* Center for transform widget. */
- float min[3], max[3]; /* Boundbox of selection for transform widget. */
+ float center[3]; /* Center for transform widget. */
+ float min[3], max[3]; /* Boundbox of selection for transform widget. */
- /* Normalized axis */
- float axis[3][3];
- float axis_min[3], axis_max[3];
+ /* Normalized axis */
+ float axis[3][3];
+ float axis_min[3], axis_max[3];
};
struct TransformCalcParams {
- uint use_only_center : 1;
- uint use_local_axis : 1;
- /* Use 'Scene.orientation_type' when zero, otherwise subtract one and use. */
- ushort orientation_type;
- ushort orientation_index_custom;
+ uint use_only_center : 1;
+ uint use_local_axis : 1;
+ /* Use 'Scene.orientation_type' when zero, otherwise subtract one and use. */
+ ushort orientation_type;
+ ushort orientation_index_custom;
};
-int ED_transform_calc_gizmo_stats(
- const struct bContext *C,
- const struct TransformCalcParams *params,
- struct TransformBounds *tbounds);
+int ED_transform_calc_gizmo_stats(const struct bContext *C,
+ const struct TransformCalcParams *params,
+ struct TransformBounds *tbounds);
-#endif /* __ED_TRANSFORM_H__ */
+#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 688d01f7846..75564ddd947 100644
--- a/source/blender/editors/include/ED_transform_snap_object_context.h
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -40,95 +40,111 @@ struct bContext;
/* ED_transform_snap_object_*** API */
typedef enum eSnapSelect {
- SNAP_ALL = 0,
- SNAP_NOT_SELECTED = 1,
- SNAP_NOT_ACTIVE = 2,
+ SNAP_ALL = 0,
+ SNAP_NOT_SELECTED = 1,
+ SNAP_NOT_ACTIVE = 2,
} eSnapSelect;
/** used for storing multiple hits */
struct SnapObjectHitDepth {
- struct SnapObjectHitDepth *next, *prev;
+ struct SnapObjectHitDepth *next, *prev;
- float depth;
- float co[3];
- float no[3];
- int index;
+ float depth;
+ float co[3];
+ float no[3];
+ int index;
- struct Object *ob;
- float obmat[4][4];
+ struct Object *ob;
+ float obmat[4][4];
- /* needed to tell which ray-cast this was part of,
- * the same object may be part of many ray-casts when dupli's are used. */
- unsigned int ob_uuid;
+ /* needed to tell which ray-cast this was part of,
+ * the same object may be part of many ray-casts when dupli's are used. */
+ unsigned int ob_uuid;
};
/** parameters that define which objects will be used to snap. */
struct SnapObjectParams {
- /* special context sensitive handling for the active or selected object */
- char snap_select;
- /* use editmode cage */
- unsigned int use_object_edit_cage : 1;
- /* snap to the closest element, use when using more than one snap type */
- unsigned int use_occlusion_test : 1;
+ /* special context sensitive handling for the active or selected object */
+ char snap_select;
+ /* use editmode cage */
+ unsigned int use_object_edit_cage : 1;
+ /* snap to the closest element, use when using more than one snap type */
+ unsigned int use_occlusion_test : 1;
};
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 View3D *v3d);
+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 View3D *v3d);
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx);
/* callbacks to filter how snap works */
void ED_transform_snap_object_context_set_editmesh_callbacks(
- SnapObjectContext *sctx,
- bool (*test_vert_fn)(struct BMVert *, void *user_data),
- bool (*test_edge_fn)(struct BMEdge *, void *user_data),
- bool (*test_face_fn)(struct BMFace *, void *user_data),
- void *user_data);
-
-bool ED_transform_snap_object_project_ray_ex(
- struct SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_start[3], const float ray_normal[3], float *ray_depth,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- struct Object **r_ob, float r_obmat[4][4]);
-bool ED_transform_snap_object_project_ray(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_origin[3], const float ray_direction[3], float *ray_depth,
- float r_co[3], float r_no[3]);
-
-bool ED_transform_snap_object_project_ray_all(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_start[3], const float ray_normal[3],
- float ray_depth, bool sort,
- struct ListBase *r_hit_list);
-
-bool ED_transform_snap_object_project_view3d_ex(
- struct SnapObjectContext *sctx,
- const unsigned short snap_to,
- const struct SnapObjectParams *params,
- const float mval[2], float *dist_px,
- float r_loc[3], float r_no[3], int *r_index,
- struct Object **r_ob, float r_obmat[4][4]);
-bool ED_transform_snap_object_project_view3d(
- struct SnapObjectContext *sctx,
- const unsigned short snap_to,
- const struct SnapObjectParams *params,
- const float mval[2], float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3]);
-
-bool ED_transform_snap_object_project_all_view3d_ex(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float mval[2],
- float ray_depth, bool sort,
- ListBase *r_hit_list);
-
-#endif /* __ED_TRANSFORM_SNAP_OBJECT_CONTEXT_H__ */
+ SnapObjectContext *sctx,
+ bool (*test_vert_fn)(struct BMVert *, void *user_data),
+ bool (*test_edge_fn)(struct BMEdge *, void *user_data),
+ bool (*test_face_fn)(struct BMFace *, void *user_data),
+ void *user_data);
+
+bool ED_transform_snap_object_project_ray_ex(struct SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_start[3],
+ const float ray_normal[3],
+ float *ray_depth,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ struct Object **r_ob,
+ float r_obmat[4][4]);
+bool ED_transform_snap_object_project_ray(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_origin[3],
+ const float ray_direction[3],
+ float *ray_depth,
+ float r_co[3],
+ float r_no[3]);
+
+bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_start[3],
+ const float ray_normal[3],
+ float ray_depth,
+ bool sort,
+ struct ListBase *r_hit_list);
+
+bool ED_transform_snap_object_project_view3d_ex(struct SnapObjectContext *sctx,
+ const unsigned short snap_to,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float *dist_px,
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ struct Object **r_ob,
+ float r_obmat[4][4]);
+bool ED_transform_snap_object_project_view3d(struct SnapObjectContext *sctx,
+ const unsigned short snap_to,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3]);
+
+bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float ray_depth,
+ bool sort,
+ ListBase *r_hit_list);
+
+#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 d03cd0151a6..3460aae32c0 100644
--- a/source/blender/editors/include/ED_transverts.h
+++ b/source/blender/editors/include/ED_transverts.h
@@ -27,16 +27,16 @@
struct Object;
typedef struct TransVert {
- float *loc;
- float oldloc[3], maploc[3];
- float normal[3];
- int flag;
+ float *loc;
+ float oldloc[3], maploc[3];
+ float normal[3];
+ int flag;
} TransVert;
typedef struct TransVertStore {
- struct TransVert *transverts;
- int transverts_tot;
- int mode;
+ struct TransVert *transverts;
+ int transverts_tot;
+ int mode;
} TransVertStore;
void ED_transverts_create_from_obedit(TransVertStore *tvs, struct Object *obedit, const int mode);
@@ -47,25 +47,25 @@ bool ED_transverts_poll(struct bContext *C);
/* currently only used for bmesh index values */
enum {
- TM_INDEX_ON = 1, /* tag to make trans verts */
- TM_INDEX_OFF = 0, /* don't make verts */
- TM_INDEX_SKIP = -1, /* dont make verts (when the index values point to trans-verts) */
+ TM_INDEX_ON = 1, /* tag to make trans verts */
+ TM_INDEX_OFF = 0, /* don't make verts */
+ TM_INDEX_SKIP = -1, /* dont make verts (when the index values point to trans-verts) */
};
/* mode flags: */
enum {
- /** all joints (for bones only) */
- TM_ALL_JOINTS = (1 << 0),
- /** skip handles when control point is selected (for curves only) */
- TM_SKIP_HANDLES = (1 << 1),
- /** fill in normals when available */
- TM_CALC_NORMALS = (1 << 2),
+ /** all joints (for bones only) */
+ TM_ALL_JOINTS = (1 << 0),
+ /** skip handles when control point is selected (for curves only) */
+ TM_SKIP_HANDLES = (1 << 1),
+ /** fill in normals when available */
+ TM_CALC_NORMALS = (1 << 2),
};
enum {
- /* SELECT == (1 << 0) */
- TX_VERT_USE_MAPLOC = (1 << 1),
- TX_VERT_USE_NORMAL = (1 << 2), /* avoid nonzero check */
+ /* SELECT == (1 << 0) */
+ TX_VERT_USE_MAPLOC = (1 << 1),
+ TX_VERT_USE_NORMAL = (1 << 2), /* avoid nonzero check */
};
-#endif /* __ED_TRANSVERTS_H__ */
+#endif /* __ED_TRANSVERTS_H__ */
diff --git a/source/blender/editors/include/ED_types.h b/source/blender/editors/include/ED_types.h
index 7040a2ef6c1..4b18bb699a9 100644
--- a/source/blender/editors/include/ED_types.h
+++ b/source/blender/editors/include/ED_types.h
@@ -28,13 +28,11 @@
/* old blender defines... should be deprecated? */
#define DESELECT 0
-#define SELECT 1
-#define ACTIVE 2
+#define SELECT 1
+#define ACTIVE 2
/* proposal = put scene pointers on function calls? */
// #define BASACT (scene->basact)
// #define OBACT (BASACT ? BASACT->object : NULL)
-
-
#endif /* __ED_TYPES_H__ */
diff --git a/source/blender/editors/include/ED_undo.h b/source/blender/editors/include/ED_undo.h
index 12839e36a12..ebc50e186a2 100644
--- a/source/blender/editors/include/ED_undo.h
+++ b/source/blender/editors/include/ED_undo.h
@@ -32,37 +32,40 @@ struct wmOperator;
struct wmOperatorType;
/* undo.c */
-void ED_undo_push(struct bContext *C, const char *str);
-void ED_undo_push_op(struct bContext *C, struct wmOperator *op);
-void ED_undo_grouped_push(struct bContext *C, const char *str);
-void ED_undo_grouped_push_op(struct bContext *C, struct wmOperator *op);
-void ED_undo_pop_op(struct bContext *C, struct wmOperator *op);
-void ED_undo_pop(struct bContext *C);
-void ED_undo_redo(struct bContext *C);
-void ED_OT_undo(struct wmOperatorType *ot);
-void ED_OT_undo_push(struct wmOperatorType *ot);
-void ED_OT_redo(struct wmOperatorType *ot);
-void ED_OT_undo_redo(struct wmOperatorType *ot);
-void ED_OT_undo_history(struct wmOperatorType *ot);
+void ED_undo_push(struct bContext *C, const char *str);
+void ED_undo_push_op(struct bContext *C, struct wmOperator *op);
+void ED_undo_grouped_push(struct bContext *C, const char *str);
+void ED_undo_grouped_push_op(struct bContext *C, struct wmOperator *op);
+void ED_undo_pop_op(struct bContext *C, struct wmOperator *op);
+void ED_undo_pop(struct bContext *C);
+void ED_undo_redo(struct bContext *C);
+void ED_OT_undo(struct wmOperatorType *ot);
+void ED_OT_undo_push(struct wmOperatorType *ot);
+void ED_OT_redo(struct wmOperatorType *ot);
+void ED_OT_undo_redo(struct wmOperatorType *ot);
+void ED_OT_undo_history(struct wmOperatorType *ot);
-int ED_undo_operator_repeat(struct bContext *C, struct wmOperator *op);
+int ED_undo_operator_repeat(struct bContext *C, struct wmOperator *op);
/* convenience since UI callbacks use this mostly*/
-void ED_undo_operator_repeat_cb(struct bContext *C, void *arg_op, void *arg_unused);
-void ED_undo_operator_repeat_cb_evt(struct bContext *C, void *arg_op, int arg_unused);
+void ED_undo_operator_repeat_cb(struct bContext *C, void *arg_op, void *arg_unused);
+void ED_undo_operator_repeat_cb_evt(struct bContext *C, void *arg_op, int arg_unused);
-bool ED_undo_is_valid(const struct bContext *C, const char *undoname);
+bool ED_undo_is_valid(const struct bContext *C, const char *undoname);
-bool ED_undo_is_memfile_compatible(const struct bContext *C);
+bool ED_undo_is_memfile_compatible(const struct bContext *C);
-void ED_undo_object_editmode_restore_helper(
- struct bContext *C,
- struct Object **object_array, uint object_array_len, uint object_array_stride);
+void ED_undo_object_editmode_restore_helper(struct bContext *C,
+ struct Object **object_array,
+ uint object_array_len,
+ uint object_array_stride);
struct UndoStack *ED_undo_stack_get(void);
/* helpers */
-void ED_undo_object_set_active_or_warn(
- struct ViewLayer *view_layer, struct Object *ob, const char *info, struct CLG_LogRef *log);
+void ED_undo_object_set_active_or_warn(struct ViewLayer *view_layer,
+ struct Object *ob,
+ const char *info,
+ struct CLG_LogRef *log);
/* undo_system_types.c */
void ED_undosys_type_init(void);
diff --git a/source/blender/editors/include/ED_userpref.h b/source/blender/editors/include/ED_userpref.h
index 29470608933..686b8a689f0 100644
--- a/source/blender/editors/include/ED_userpref.h
+++ b/source/blender/editors/include/ED_userpref.h
@@ -23,4 +23,4 @@
void ED_operatortypes_userpref(void);
-#endif /* __ED_USERPREF_H__ */
+#endif /* __ED_USERPREF_H__ */
diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h
index b275b776ddd..87f57b4e144 100644
--- a/source/blender/editors/include/ED_util.h
+++ b/source/blender/editors/include/ED_util.h
@@ -36,15 +36,24 @@ void ED_editors_init(struct bContext *C);
void ED_editors_exit(struct Main *bmain, bool do_undo_system);
bool ED_editors_flush_edits(struct Main *bmain, bool for_render);
-void ED_spacedata_id_remap(struct ScrArea *sa, struct SpaceLink *sl, struct ID *old_id, struct ID *new_id);
+void ED_spacedata_id_remap(struct ScrArea *sa,
+ struct SpaceLink *sl,
+ struct ID *old_id,
+ struct ID *new_id);
void ED_OT_flush_edits(struct wmOperatorType *ot);
/* ************** XXX OLD CRUFT WARNING ************* */
-void apply_keyb_grid(int shift, int ctrl, float *val, float fac1, float fac2, float fac3, int invert);
+void apply_keyb_grid(
+ int shift, int ctrl, float *val, float fac1, float fac2, float fac3, int invert);
/* where else to go ? */
-void unpack_menu(struct bContext *C, const char *opname, const char *id_name, const char *abs_name, const char *folder, struct PackedFile *pf);
+void unpack_menu(struct bContext *C,
+ const char *opname,
+ const char *id_name,
+ const char *abs_name,
+ const char *folder,
+ struct PackedFile *pf);
#endif /* __ED_UTIL_H__ */
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index b0d1f7a014a..9259afd1d5f 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -46,90 +46,126 @@ struct wmKeyConfig;
void ED_operatortypes_uvedit(void);
void ED_keymap_uvedit(struct wmKeyConfig *keyconf);
-bool ED_uvedit_minmax(struct Scene *scene, struct Image *ima, struct Object *obedit, float min[2], float max[2]);
+bool ED_uvedit_minmax(
+ struct Scene *scene, struct Image *ima, struct Object *obedit, float min[2], float max[2]);
bool ED_uvedit_center(Scene *scene, Image *ima, struct Object *obedit, float cent[2], char mode);
void ED_uvedit_select_all(struct BMesh *bm);
-bool ED_uvedit_minmax_multi(
- struct Scene *scene, struct Image *ima, struct Object **objects_edit, uint objects_len, float r_min[2], float r_max[2]);
-bool ED_uvedit_center_multi(
- Scene *scene, Image *ima, struct Object **objects_edit, uint objects_len, float r_cent[2], char mode);
-
-bool ED_object_get_active_image(
- struct Object *ob, int mat_nr,
- struct Image **r_ima, struct ImageUser **r_iuser, struct bNode **r_node, struct bNodeTree **r_ntree);
-void ED_object_assign_active_image(struct Main *bmain, struct Object *ob, int mat_nr, struct Image *ima);
+bool ED_uvedit_minmax_multi(struct Scene *scene,
+ struct Image *ima,
+ struct Object **objects_edit,
+ uint objects_len,
+ float r_min[2],
+ float r_max[2]);
+bool ED_uvedit_center_multi(Scene *scene,
+ Image *ima,
+ struct Object **objects_edit,
+ uint objects_len,
+ float r_cent[2],
+ char mode);
+
+bool ED_object_get_active_image(struct Object *ob,
+ int mat_nr,
+ struct Image **r_ima,
+ struct ImageUser **r_iuser,
+ struct bNode **r_node,
+ struct bNodeTree **r_ntree);
+void ED_object_assign_active_image(struct Main *bmain,
+ struct Object *ob,
+ int mat_nr,
+ struct Image *ima);
bool ED_uvedit_test(struct Object *obedit);
/* visibility and selection */
-bool uvedit_face_visible_nolocal_ex(
- const struct ToolSettings *ts, struct BMFace *efa);
-bool uvedit_face_visible_test_ex(
- const struct ToolSettings *ts, struct Object *obedit, struct Image *ima, struct BMFace *efa);
-bool uvedit_face_select_test_ex(
- const struct ToolSettings *ts, struct BMFace *efa,
- const int cd_loop_uv_offset);
-bool uvedit_edge_select_test_ex(
- const struct ToolSettings *ts, struct BMLoop *l,
- const int cd_loop_uv_offset);
-bool uvedit_uv_select_test_ex(
- const struct ToolSettings *ts, struct BMLoop *l,
- const int cd_loop_uv_offset);
-
-bool uvedit_face_visible_nolocal(
- struct Scene *scene, struct BMFace *efa);
-bool uvedit_face_visible_test(
- struct Scene *scene, struct Object *obedit, struct Image *ima, struct BMFace *efa);
-bool uvedit_face_select_test(
- struct Scene *scene, struct BMFace *efa,
- const int cd_loop_uv_offset);
-bool uvedit_edge_select_test(
- struct Scene *scene, struct BMLoop *l,
- const int cd_loop_uv_offset);
-bool uvedit_uv_select_test(
- struct Scene *scene, struct BMLoop *l,
- const int cd_loop_uv_offset);
+bool uvedit_face_visible_nolocal_ex(const struct ToolSettings *ts, struct BMFace *efa);
+bool uvedit_face_visible_test_ex(const struct ToolSettings *ts,
+ struct Object *obedit,
+ struct Image *ima,
+ struct BMFace *efa);
+bool uvedit_face_select_test_ex(const struct ToolSettings *ts,
+ struct BMFace *efa,
+ const int cd_loop_uv_offset);
+bool uvedit_edge_select_test_ex(const struct ToolSettings *ts,
+ struct BMLoop *l,
+ const int cd_loop_uv_offset);
+bool uvedit_uv_select_test_ex(const struct ToolSettings *ts,
+ struct BMLoop *l,
+ const int cd_loop_uv_offset);
+
+bool uvedit_face_visible_nolocal(struct Scene *scene, struct BMFace *efa);
+bool uvedit_face_visible_test(struct Scene *scene,
+ struct Object *obedit,
+ struct Image *ima,
+ struct BMFace *efa);
+bool uvedit_face_select_test(struct Scene *scene, struct BMFace *efa, const int cd_loop_uv_offset);
+bool uvedit_edge_select_test(struct Scene *scene, struct BMLoop *l, const int cd_loop_uv_offset);
+bool uvedit_uv_select_test(struct Scene *scene, struct BMLoop *l, const int cd_loop_uv_offset);
/* uv face */
-bool uvedit_face_select_set(
- struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa, const bool select,
- const bool do_history, const int cd_loop_uv_offset);
-bool uvedit_face_select_enable(
- struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa,
- const bool do_history, const int cd_loop_uv_offset);
-bool uvedit_face_select_disable(
- struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa,
- const int cd_loop_uv_offset);
+bool uvedit_face_select_set(struct Scene *scene,
+ struct BMEditMesh *em,
+ struct BMFace *efa,
+ const bool select,
+ const bool do_history,
+ const int cd_loop_uv_offset);
+bool uvedit_face_select_enable(struct Scene *scene,
+ struct BMEditMesh *em,
+ struct BMFace *efa,
+ const bool do_history,
+ const int cd_loop_uv_offset);
+bool uvedit_face_select_disable(struct Scene *scene,
+ struct BMEditMesh *em,
+ struct BMFace *efa,
+ const int cd_loop_uv_offset);
/* uv edge */
-void uvedit_edge_select_set(
- struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l, const bool select,
- const bool do_history, const int cd_loop_uv_offset);
-void uvedit_edge_select_enable(
- struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l,
- const bool do_history, const int cd_loop_uv_offset);
-void uvedit_edge_select_disable(
- struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l,
- const int cd_loop_uv_offset);
+void uvedit_edge_select_set(struct BMEditMesh *em,
+ struct Scene *scene,
+ struct BMLoop *l,
+ const bool select,
+ const bool do_history,
+ const int cd_loop_uv_offset);
+void uvedit_edge_select_enable(struct BMEditMesh *em,
+ struct Scene *scene,
+ struct BMLoop *l,
+ const bool do_history,
+ const int cd_loop_uv_offset);
+void uvedit_edge_select_disable(struct BMEditMesh *em,
+ struct Scene *scene,
+ struct BMLoop *l,
+ const int cd_loop_uv_offset);
/* uv vert */
-void uvedit_uv_select_set(
- struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l, const bool select,
- const bool do_history, const int cd_loop_uv_offset);
-void uvedit_uv_select_enable(
- struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l,
- const bool do_history, const int cd_loop_uv_offset);
-void uvedit_uv_select_disable(
- struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l,
- const int cd_loop_uv_offset);
-
-bool ED_uvedit_nearest_uv(
- struct Scene *scene, struct Object *obedit, struct Image *ima, const float co[2],
- float *dist_sq, float r_uv[2]);
-bool ED_uvedit_nearest_uv_multi(
- struct Scene *scene, struct Image *ima,
- struct Object **objects, const uint objects_len, const float co[2],
- float *dist_sq, float r_uv[2]);
-
-void ED_uvedit_get_aspect(struct Scene *scene, struct Object *ob, struct BMesh *em, float *aspx, float *aspy);
+void uvedit_uv_select_set(struct BMEditMesh *em,
+ struct Scene *scene,
+ struct BMLoop *l,
+ const bool select,
+ const bool do_history,
+ const int cd_loop_uv_offset);
+void uvedit_uv_select_enable(struct BMEditMesh *em,
+ struct Scene *scene,
+ struct BMLoop *l,
+ const bool do_history,
+ const int cd_loop_uv_offset);
+void uvedit_uv_select_disable(struct BMEditMesh *em,
+ struct Scene *scene,
+ struct BMLoop *l,
+ const int cd_loop_uv_offset);
+
+bool ED_uvedit_nearest_uv(struct Scene *scene,
+ struct Object *obedit,
+ struct Image *ima,
+ const float co[2],
+ float *dist_sq,
+ float r_uv[2]);
+bool ED_uvedit_nearest_uv_multi(struct Scene *scene,
+ struct Image *ima,
+ struct Object **objects,
+ const uint objects_len,
+ const float co[2],
+ float *dist_sq,
+ float r_uv[2]);
+
+void ED_uvedit_get_aspect(
+ struct Scene *scene, struct Object *ob, struct BMesh *em, float *aspx, float *aspy);
/* uvedit_unwrap_ops.c */
void ED_uvedit_live_unwrap_begin(struct Scene *scene, struct Object *obedit);
@@ -139,14 +175,15 @@ void ED_uvedit_live_unwrap_end(short cancel);
void ED_uvedit_live_unwrap(struct Scene *scene, struct Object **objects, int objects_len);
void ED_uvedit_add_simple_uvs(struct Main *bmain, struct Scene *scene, struct Object *ob);
-
/* uvedit_draw.c */
-void ED_image_draw_cursor(
- struct ARegion *ar, const float cursor[2]);
-void ED_uvedit_draw_main(
- struct SpaceImage *sima,
- struct ARegion *ar, struct Scene *scene, struct ViewLayer *view_layer,
- struct Object *obedit, struct Object *obact, struct Depsgraph *depsgraph);
+void ED_image_draw_cursor(struct ARegion *ar, const float cursor[2]);
+void ED_uvedit_draw_main(struct SpaceImage *sima,
+ struct ARegion *ar,
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ struct Object *obedit,
+ struct Object *obact,
+ struct Depsgraph *depsgraph);
/* uvedit_buttons.c */
void ED_uvedit_buttons_register(struct ARegionType *art);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 4c03be3bd5a..e747dda95d4 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -72,53 +72,57 @@ enum eGPUFXFlags;
/* for derivedmesh drawing callbacks, for view3d_select, .... */
typedef struct ViewContext {
- struct bContext *C;
- struct Main *bmain;
- struct Depsgraph *depsgraph;
- struct Scene *scene;
- struct ViewLayer *view_layer;
- struct Object *obact;
- struct Object *obedit;
- struct ARegion *ar;
- struct View3D *v3d;
- struct wmWindow *win;
- struct RegionView3D *rv3d;
- struct BMEditMesh *em;
- int mval[2];
+ struct bContext *C;
+ struct Main *bmain;
+ struct Depsgraph *depsgraph;
+ struct Scene *scene;
+ struct ViewLayer *view_layer;
+ struct Object *obact;
+ struct Object *obedit;
+ struct ARegion *ar;
+ struct View3D *v3d;
+ struct wmWindow *win;
+ struct RegionView3D *rv3d;
+ struct BMEditMesh *em;
+ int mval[2];
} ViewContext;
typedef struct ViewDepths {
- unsigned short w, h;
- short x, y; /* only for temp use for sub-rects, added to ar->winx/y */
- float *depths;
- double depth_range[2];
+ unsigned short w, h;
+ short x, y; /* only for temp use for sub-rects, added to ar->winx/y */
+ float *depths;
+ double depth_range[2];
- bool damaged;
+ bool damaged;
} ViewDepths;
-
/* Rotate 3D cursor on placement. */
enum eV3DCursorOrient {
- V3D_CURSOR_ORIENT_NONE = 0,
- V3D_CURSOR_ORIENT_VIEW,
- V3D_CURSOR_ORIENT_XFORM,
- V3D_CURSOR_ORIENT_GEOM,
+ V3D_CURSOR_ORIENT_NONE = 0,
+ V3D_CURSOR_ORIENT_VIEW,
+ V3D_CURSOR_ORIENT_XFORM,
+ V3D_CURSOR_ORIENT_GEOM,
};
-void ED_view3d_background_color_get(const struct Scene *scene, const struct View3D *v3d, float r_color[3]);
+void ED_view3d_background_color_get(const struct Scene *scene,
+ const struct View3D *v3d,
+ float r_color[3]);
void ED_view3d_cursor3d_calc_mat3(const struct Scene *scene, float mat[3][3]);
void ED_view3d_cursor3d_calc_mat4(const struct Scene *scene, float mat[4][4]);
-void ED_view3d_cursor3d_position(
- struct bContext *C, const int mval[2],
- const bool use_depth,
- float cursor_co[3]);
-void ED_view3d_cursor3d_position_rotation(
- struct bContext *C, const int mval[2],
- const bool use_depth, enum eV3DCursorOrient orientation,
- float cursor_co[3], float cursor_quat[4]);
-void ED_view3d_cursor3d_update(
- struct bContext *C, const int mval[2],
- const bool use_depth, enum eV3DCursorOrient orientation);
+void ED_view3d_cursor3d_position(struct bContext *C,
+ const int mval[2],
+ const bool use_depth,
+ float cursor_co[3]);
+void ED_view3d_cursor3d_position_rotation(struct bContext *C,
+ const int mval[2],
+ const bool use_depth,
+ enum eV3DCursorOrient orientation,
+ float cursor_co[3],
+ float cursor_quat[4]);
+void ED_view3d_cursor3d_update(struct bContext *C,
+ const int mval[2],
+ const bool use_depth,
+ enum eV3DCursorOrient orientation);
struct Camera *ED_view3d_camera_data_get(struct View3D *v3d, struct RegionView3D *rv3d);
@@ -126,289 +130,393 @@ void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], c
void ED_view3d_from_m4(const float mat[4][4], float ofs[3], float quat[4], float *dist);
void ED_view3d_from_object(
- const struct Object *ob,
- float ofs[3], float quat[4], float *dist, float *lens);
-void ED_view3d_to_object(
- const struct Depsgraph *depsgraph, struct Object *ob,
- const float ofs[3], const float quat[4], const float dist);
+ const struct Object *ob, float ofs[3], float quat[4], float *dist, float *lens);
+void ED_view3d_to_object(const struct Depsgraph *depsgraph,
+ struct Object *ob,
+ const float ofs[3],
+ const float quat[4],
+ const float dist);
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 *ar);
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,
- const int mval[2], const double depth,
- float r_location_world[3]);
-void ED_view3d_depth_tag_update(struct RegionView3D *rv3d);
+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,
+ const int mval[2],
+ const double depth,
+ float r_location_world[3]);
+void ED_view3d_depth_tag_update(struct RegionView3D *rv3d);
/* Projection */
-#define IS_CLIPPED 12000
+#define IS_CLIPPED 12000
/* return values for ED_view3d_project_...() */
typedef enum {
- V3D_PROJ_RET_OK = 0,
- /** can't avoid this when in perspective mode, (can't avoid) */
- V3D_PROJ_RET_CLIP_NEAR = 1,
- /** so close to zero we can't apply a perspective matrix usefully */
- V3D_PROJ_RET_CLIP_ZERO = 2,
- /** bounding box clip - RV3D_CLIPPING */
- V3D_PROJ_RET_CLIP_BB = 3,
- /** outside window bounds */
- V3D_PROJ_RET_CLIP_WIN = 4,
- /** outside range (mainly for short), (can't avoid) */
- V3D_PROJ_RET_OVERFLOW = 5,
+ V3D_PROJ_RET_OK = 0,
+ /** can't avoid this when in perspective mode, (can't avoid) */
+ V3D_PROJ_RET_CLIP_NEAR = 1,
+ /** so close to zero we can't apply a perspective matrix usefully */
+ V3D_PROJ_RET_CLIP_ZERO = 2,
+ /** bounding box clip - RV3D_CLIPPING */
+ V3D_PROJ_RET_CLIP_BB = 3,
+ /** outside window bounds */
+ V3D_PROJ_RET_CLIP_WIN = 4,
+ /** outside range (mainly for short), (can't avoid) */
+ V3D_PROJ_RET_OVERFLOW = 5,
} eV3DProjStatus;
/* some clipping tests are optional */
typedef enum {
- V3D_PROJ_TEST_NOP = 0,
- V3D_PROJ_TEST_CLIP_BB = (1 << 0),
- V3D_PROJ_TEST_CLIP_WIN = (1 << 1),
- V3D_PROJ_TEST_CLIP_NEAR = (1 << 2),
- V3D_PROJ_TEST_CLIP_ZERO = (1 << 3),
+ V3D_PROJ_TEST_NOP = 0,
+ V3D_PROJ_TEST_CLIP_BB = (1 << 0),
+ V3D_PROJ_TEST_CLIP_WIN = (1 << 1),
+ V3D_PROJ_TEST_CLIP_NEAR = (1 << 2),
+ V3D_PROJ_TEST_CLIP_ZERO = (1 << 3),
} eV3DProjTest;
#define V3D_PROJ_TEST_CLIP_DEFAULT \
- (V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR)
+ (V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR)
#define V3D_PROJ_TEST_ALL \
- (V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_ZERO)
-
+ (V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR | \
+ V3D_PROJ_TEST_CLIP_ZERO)
/* view3d_iterators.c */
/* foreach iterators */
void meshobject_foreachScreenVert(
- struct ViewContext *vc,
- void (*func)(void *userData, struct MVert *eve, const float screen_co[2], int index),
- void *userData, const eV3DProjTest clip_flag);
+ struct ViewContext *vc,
+ void (*func)(void *userData, struct MVert *eve, const float screen_co[2], int index),
+ void *userData,
+ const eV3DProjTest clip_flag);
void mesh_foreachScreenVert(
- struct ViewContext *vc,
- void (*func)(void *userData, struct BMVert *eve, const float screen_co[2], int index),
- void *userData, const eV3DProjTest clip_flag);
-void mesh_foreachScreenEdge(
- struct ViewContext *vc,
- void (*func)(void *userData, struct BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2],
- int index),
- void *userData, const eV3DProjTest clip_flag);
+ struct ViewContext *vc,
+ void (*func)(void *userData, struct BMVert *eve, const float screen_co[2], int index),
+ void *userData,
+ const eV3DProjTest clip_flag);
+void mesh_foreachScreenEdge(struct ViewContext *vc,
+ void (*func)(void *userData,
+ struct BMEdge *eed,
+ const float screen_co_a[2],
+ const float screen_co_b[2],
+ int index),
+ void *userData,
+ const eV3DProjTest clip_flag);
void mesh_foreachScreenFace(
- struct ViewContext *vc,
- void (*func)(void *userData, struct BMFace *efa, const float screen_co[2], int index),
- void *userData, const eV3DProjTest clip_flag);
-void nurbs_foreachScreenVert(
- struct ViewContext *vc,
- void (*func)(void *userData, struct Nurb *nu, struct BPoint *bp, struct BezTriple *bezt,
- int beztindex, const float screen_co[2]),
- void *userData, const eV3DProjTest clip_flag);
-void mball_foreachScreenElem(
- struct ViewContext *vc,
- void (*func)(void *userData, struct MetaElem *ml, const float screen_co[2]),
- void *userData, const eV3DProjTest clip_flag);
-void lattice_foreachScreenVert(
- struct ViewContext *vc,
- void (*func)(void *userData, struct BPoint *bp,
- const float screen_co[2]),
- void *userData, const eV3DProjTest clip_flag);
-void armature_foreachScreenBone(
- struct ViewContext *vc,
- void (*func)(void *userData, struct EditBone *ebone,
- const float screen_co_a[2], const float screen_co_b[2]),
- void *userData, const eV3DProjTest clip_flag);
-void pose_foreachScreenBone(
- struct ViewContext *vc,
- void (*func)(void *userData, struct bPoseChannel *pchan,
- const float screen_co_a[2], const float screen_co_b[2]),
- void *userData, const eV3DProjTest clip_flag);
+ struct ViewContext *vc,
+ void (*func)(void *userData, struct BMFace *efa, const float screen_co[2], int index),
+ void *userData,
+ const eV3DProjTest clip_flag);
+void nurbs_foreachScreenVert(struct ViewContext *vc,
+ void (*func)(void *userData,
+ struct Nurb *nu,
+ struct BPoint *bp,
+ struct BezTriple *bezt,
+ int beztindex,
+ const float screen_co[2]),
+ void *userData,
+ const eV3DProjTest clip_flag);
+void mball_foreachScreenElem(struct ViewContext *vc,
+ void (*func)(void *userData,
+ struct MetaElem *ml,
+ const float screen_co[2]),
+ void *userData,
+ const eV3DProjTest clip_flag);
+void lattice_foreachScreenVert(struct ViewContext *vc,
+ void (*func)(void *userData,
+ struct BPoint *bp,
+ const float screen_co[2]),
+ void *userData,
+ const eV3DProjTest clip_flag);
+void armature_foreachScreenBone(struct ViewContext *vc,
+ void (*func)(void *userData,
+ struct EditBone *ebone,
+ const float screen_co_a[2],
+ const float screen_co_b[2]),
+ void *userData,
+ const eV3DProjTest clip_flag);
+void pose_foreachScreenBone(struct ViewContext *vc,
+ void (*func)(void *userData,
+ struct bPoseChannel *pchan,
+ const float screen_co_a[2],
+ const float screen_co_b[2]),
+ void *userData,
+ const eV3DProjTest clip_flag);
/* *** end iterators *** */
-
/* view3d_project.c */
-void ED_view3d_project_float_v2_m4(const struct ARegion *ar, const float co[3], float r_co[2], float mat[4][4]);
-void ED_view3d_project_float_v3_m4(const struct ARegion *ar, const float co[3], float r_co[3], float mat[4][4]);
+void ED_view3d_project_float_v2_m4(const struct ARegion *ar,
+ const float co[3],
+ float r_co[2],
+ float mat[4][4]);
+void ED_view3d_project_float_v3_m4(const struct ARegion *ar,
+ const float co[3],
+ float r_co[3],
+ float mat[4][4]);
eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct Base *base);
/* *** short *** */
-eV3DProjStatus ED_view3d_project_short_ex(const struct ARegion *ar, 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, const float co[3], short r_co[2], const eV3DProjTest flag);
-eV3DProjStatus ED_view3d_project_short_object(const struct ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag);
+eV3DProjStatus ED_view3d_project_short_ex(const struct ARegion *ar,
+ 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,
+ const float co[3],
+ short r_co[2],
+ const eV3DProjTest flag);
+eV3DProjStatus ED_view3d_project_short_object(const struct ARegion *ar,
+ const float co[3],
+ short r_co[2],
+ const eV3DProjTest flag);
/* *** int *** */
-eV3DProjStatus ED_view3d_project_int_ex(const struct ARegion *ar, 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, const float co[3], int r_co[2], const eV3DProjTest flag);
-eV3DProjStatus ED_view3d_project_int_object(const struct ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag);
+eV3DProjStatus ED_view3d_project_int_ex(const struct ARegion *ar,
+ 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,
+ const float co[3],
+ int r_co[2],
+ const eV3DProjTest flag);
+eV3DProjStatus ED_view3d_project_int_object(const struct ARegion *ar,
+ const float co[3],
+ int r_co[2],
+ const eV3DProjTest flag);
/* *** float *** */
-eV3DProjStatus ED_view3d_project_float_ex(const struct ARegion *ar, 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, const float co[3], float r_co[2], const eV3DProjTest flag);
-eV3DProjStatus ED_view3d_project_float_object(const struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag);
+eV3DProjStatus ED_view3d_project_float_ex(const struct ARegion *ar,
+ 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,
+ const float co[3],
+ float r_co[2],
+ const eV3DProjTest flag);
+eV3DProjStatus ED_view3d_project_float_object(const struct ARegion *ar,
+ const float co[3],
+ float r_co[2],
+ const eV3DProjTest flag);
float ED_view3d_pixel_size(const struct RegionView3D *rv3d, const float co[3]);
float ED_view3d_pixel_size_no_ui_scale(const struct RegionView3D *rv3d, const float co[3]);
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 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 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, const float mval[2],
- float r_ray_start[3], float r_ray_normal[3]);
-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 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 float depth_pt[3], const int mval[2],
- float r_out[3]);
-bool ED_view3d_win_to_3d_on_plane(
- const struct ARegion *ar,
- 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,
- 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, const float mval[2], float out[3], const float zfac);
+bool ED_view3d_win_to_ray_clipped(struct Depsgraph *depsgraph,
+ const struct ARegion *ar,
+ 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 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,
+ const float mval[2],
+ float r_ray_start[3],
+ float r_ray_normal[3]);
+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 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 float depth_pt[3],
+ const int mval[2],
+ float r_out[3]);
+bool ED_view3d_win_to_3d_on_plane(const struct ARegion *ar,
+ 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,
+ 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,
+ 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]);
-bool ED_view3d_win_to_segment_clipped(
- struct Depsgraph *depsgraph,
- const struct ARegion *ar, struct View3D *v3d, const float mval[2],
- float r_ray_start[3], float r_ray_end[3], const bool do_clip);
-void ED_view3d_ob_project_mat_get(const struct RegionView3D *v3d, struct Object *ob, float pmat[4][4]);
-void ED_view3d_ob_project_mat_get_from_obmat(const struct RegionView3D *rv3d, float obmat[4][4], float pmat[4][4]);
+bool ED_view3d_win_to_segment_clipped(struct Depsgraph *depsgraph,
+ const struct ARegion *ar,
+ struct View3D *v3d,
+ const float mval[2],
+ float r_ray_start[3],
+ float r_ray_end[3],
+ const bool do_clip);
+void ED_view3d_ob_project_mat_get(const struct RegionView3D *v3d,
+ struct Object *ob,
+ float pmat[4][4]);
+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]);
-bool ED_view3d_unproject(const struct ARegion *ar, float regionx, float regiony, float regionz, float world[3]);
+bool ED_view3d_unproject(
+ const struct ARegion *ar, float regionx, float regiony, float regionz, float world[3]);
/* end */
-
-void ED_view3d_dist_range_get(
- const struct View3D *v3d,
- float r_dist_range[2]);
-bool ED_view3d_clip_range_get(
- struct Depsgraph *depsgraph,
- const struct View3D *v3d, const struct RegionView3D *rv3d,
- float *r_clipsta, float *r_clipend, const bool use_ortho_factor);
-bool ED_view3d_viewplane_get(
- struct Depsgraph *depsgraph,
- const struct View3D *v3d, const struct RegionView3D *rv3d, int winxi, int winyi,
- struct rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize);
+void ED_view3d_dist_range_get(const struct View3D *v3d, float r_dist_range[2]);
+bool ED_view3d_clip_range_get(struct Depsgraph *depsgraph,
+ const struct View3D *v3d,
+ const struct RegionView3D *rv3d,
+ float *r_clipsta,
+ float *r_clipend,
+ const bool use_ortho_factor);
+bool ED_view3d_viewplane_get(struct Depsgraph *depsgraph,
+ const struct View3D *v3d,
+ const struct RegionView3D *rv3d,
+ int winxi,
+ int winyi,
+ struct rctf *r_viewplane,
+ float *r_clipsta,
+ float *r_clipend,
+ float *r_pixsize);
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 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 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 rcti *rect);
-
-void ED_view3d_clipping_calc_from_boundbox(float clip[6][4], const struct BoundBox *clipbb, const bool is_flip);
-void ED_view3d_clipping_calc(struct BoundBox *bb, float planes[4][4],
- const struct ARegion *ar, const struct Object *ob, const struct rcti *rect);
+void ED_view3d_calc_camera_border(const struct Scene *scene,
+ struct Depsgraph *depsgraph,
+ const struct ARegion *ar,
+ 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 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 rcti *rect);
+
+void ED_view3d_clipping_calc_from_boundbox(float clip[6][4],
+ const struct BoundBox *clipbb,
+ const bool is_flip);
+void ED_view3d_clipping_calc(struct BoundBox *bb,
+ float planes[4][4],
+ const struct ARegion *ar,
+ const struct Object *ob,
+ const struct rcti *rect);
void ED_view3d_clipping_local(struct RegionView3D *rv3d, float mat[4][4]);
-bool ED_view3d_clipping_test(const struct RegionView3D *rv3d, const float co[3], const bool is_local);
+bool ED_view3d_clipping_test(const struct RegionView3D *rv3d,
+ const float co[3],
+ const bool is_local);
void ED_view3d_clipping_set(struct RegionView3D *rv3d);
void ED_view3d_clipping_enable(void);
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 Depsgraph *depsgraph,
- const char persp, const bool use_aspect,
- const float radius);
+float ED_view3d_radius_to_dist(const struct View3D *v3d,
+ const struct ARegion *ar,
+ 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);
/* 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);
+void ED_view3d_backbuf_depth_validate(struct ViewContext *vc);
+int ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist);
-void ED_view3d_select_id_validate(struct ViewContext *vc);
-void ED_view3d_select_id_validate_with_select_mode(
- struct ViewContext *vc, short select_mode);
+void ED_view3d_select_id_validate(struct ViewContext *vc);
+void ED_view3d_select_id_validate_with_select_mode(struct ViewContext *vc, short select_mode);
-uint ED_view3d_select_id_sample(
- struct ViewContext *vc, int x, int y);
+uint ED_view3d_select_id_sample(struct ViewContext *vc, int x, int y);
uint *ED_view3d_select_id_read(
- struct ViewContext *vc,
- int xmin, int ymin, int xmax, int ymax,
- uint *r_buf_len);
-uint *ED_view3d_select_id_read_rect(
- struct ViewContext *vc, const struct rcti *rect, uint *r_buf_len);
+ struct ViewContext *vc, int xmin, int ymin, int xmax, int ymax, uint *r_buf_len);
+uint *ED_view3d_select_id_read_rect(struct ViewContext *vc,
+ const struct rcti *rect,
+ uint *r_buf_len);
uint ED_view3d_select_id_read_nearest(
- struct ViewContext *vc, const int mval[2],
- const uint min, const uint max, uint *r_dist);
+ struct ViewContext *vc, const int mval[2], const uint min, const uint max, uint *r_dist);
-bool ED_view3d_autodist(
- struct Depsgraph *depsgraph, struct ARegion *ar, struct View3D *v3d,
- const int mval[2], float mouse_worldloc[3],
- const bool alphaoverride, const float fallback_depth_pt[3]);
+bool ED_view3d_autodist(struct Depsgraph *depsgraph,
+ struct ARegion *ar,
+ struct View3D *v3d,
+ const int mval[2],
+ float mouse_worldloc[3],
+ const bool alphaoverride,
+ const float fallback_depth_pt[3]);
/* 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 View3D *v3d, int mode);
-bool ED_view3d_autodist_simple(struct ARegion *ar, const int mval[2], float mouse_worldloc[3], int margin, float *force_depth);
+void ED_view3d_autodist_init(struct Depsgraph *depsgraph,
+ struct ARegion *ar,
+ struct View3D *v3d,
+ int mode);
+bool ED_view3d_autodist_simple(struct ARegion *ar,
+ 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_seg(
+ struct ARegion *ar, const int mval_sta[2], const int mval_end[2], int margin, float *depth);
/* select */
-#define MAXPICKELEMS 2500
-#define MAXPICKBUF (4 * MAXPICKELEMS)
+#define MAXPICKELEMS 2500
+#define MAXPICKBUF (4 * MAXPICKELEMS)
typedef enum {
- /* all elements in the region, ignore depth */
- VIEW3D_SELECT_ALL = 0,
- /* pick also depth sorts (only for small regions!) */
- VIEW3D_SELECT_PICK_ALL = 1,
- /* sorts and only returns visible objects (only for small regions!) */
- VIEW3D_SELECT_PICK_NEAREST = 2,
+ /* all elements in the region, ignore depth */
+ VIEW3D_SELECT_ALL = 0,
+ /* pick also depth sorts (only for small regions!) */
+ VIEW3D_SELECT_PICK_ALL = 1,
+ /* sorts and only returns visible objects (only for small regions!) */
+ VIEW3D_SELECT_PICK_NEAREST = 2,
} eV3DSelectMode;
typedef enum {
- /** Don't exclude anything. */
- VIEW3D_SELECT_FILTER_NOP = 0,
- /** Don't select objects outside the current mode. */
- VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK = 1,
- /** A version of #VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK that allows pose-bone selection. */
- VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK = 2,
+ /** Don't exclude anything. */
+ VIEW3D_SELECT_FILTER_NOP = 0,
+ /** Don't select objects outside the current mode. */
+ VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK = 1,
+ /** A version of #VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK that allows pose-bone selection. */
+ VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK = 2,
} eV3DSelectObjectFilter;
-eV3DSelectObjectFilter ED_view3d_select_filter_from_mode(const struct Scene *scene, const struct Object *obact);
+eV3DSelectObjectFilter ED_view3d_select_filter_from_mode(const struct Scene *scene,
+ const struct Object *obact);
void view3d_opengl_select_cache_begin(void);
void view3d_opengl_select_cache_end(void);
-int view3d_opengl_select(
- struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const struct rcti *input,
- eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter);
+int view3d_opengl_select(struct ViewContext *vc,
+ unsigned int *buffer,
+ unsigned int bufsize,
+ const struct rcti *input,
+ eV3DSelectMode select_mode,
+ eV3DSelectObjectFilter select_filter);
/* view3d_select.c */
float ED_view3d_select_dist_px(void);
@@ -416,14 +524,20 @@ void ED_view3d_viewcontext_init(struct bContext *C, struct ViewContext *vc);
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_opengl_read_pixels(struct ARegion *ar, int x, int y, int w, int h, int format, int type, void *data);
+void view3d_opengl_read_pixels(
+ struct ARegion *ar, int x, int y, int w, int h, int format, int type, void *data);
/* XXX should move to BLI_math */
-bool edge_inside_circle(const float cent[2], float radius, const float screen_co_a[2], const float screen_co_b[2]);
+bool edge_inside_circle(const float cent[2],
+ float radius,
+ const float screen_co_a[2],
+ const float screen_co_b[2]);
/* get 3d region from context, also if mouse is in header or toolbar */
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);
+bool ED_view3d_context_user_region(struct bContext *C,
+ struct View3D **r_v3d,
+ struct ARegion **r_ar);
bool ED_operator_rv3d_user_region_poll(struct bContext *C);
void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d);
@@ -437,97 +551,139 @@ void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d);
#endif
struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d);
-void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat);
+void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat);
-void ED_draw_object_facemap(
- struct Depsgraph *depsgraph, struct Object *ob, const float col[4], const int facemap);
+void ED_draw_object_facemap(struct Depsgraph *depsgraph,
+ struct Object *ob,
+ const float col[4],
+ const int facemap);
struct RenderEngineType *ED_view3d_engine_type(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,
- struct GPUFXSettings *fx_settings, const bool do_color_managment,
- struct GPUOffScreen *ofs, struct GPUViewport *viewport);
-void ED_view3d_draw_setup_view(
- struct wmWindow *win, struct Depsgraph *depsgraph, struct Scene *scene, struct ARegion *ar, struct View3D *v3d,
- float viewmat[4][4], float winmat[4][4], const struct rcti *rect);
+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,
+ struct GPUFXSettings *fx_settings,
+ const bool do_color_managment,
+ struct GPUOffScreen *ofs,
+ struct GPUViewport *viewport);
+void ED_view3d_draw_setup_view(struct wmWindow *win,
+ struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct ARegion *ar,
+ struct View3D *v3d,
+ float viewmat[4][4],
+ float winmat[4][4],
+ const struct rcti *rect);
enum {
- V3D_OFSDRAW_NONE = (0),
+ V3D_OFSDRAW_NONE = (0),
- V3D_OFSDRAW_USE_FULL_SAMPLE = (1 << 0),
+ V3D_OFSDRAW_USE_FULL_SAMPLE = (1 << 0),
- /* Only works with ED_view3d_draw_offscreen_imbuf_simple(). */
- V3D_OFSDRAW_USE_GPENCIL = (1 << 1),
- V3D_OFSDRAW_USE_CAMERA_DOF = (1 << 2),
+ /* Only works with ED_view3d_draw_offscreen_imbuf_simple(). */
+ V3D_OFSDRAW_USE_GPENCIL = (1 << 1),
+ V3D_OFSDRAW_USE_CAMERA_DOF = (1 << 2),
};
-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, unsigned int draw_flags,
- int alpha_mode, int samples, const char *viewname,
- struct GPUOffScreen *ofs, char err_out[256]);
-struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
- struct Depsgraph *depsgraph, struct Scene *scene,
- int drawtype,
- struct Object *camera, int width, int height,
- unsigned int flag, unsigned int draw_flags, int alpha_mode,
- int samples, const char *viewname,
- struct GPUOffScreen *ofs, char err_out[256]);
+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,
+ unsigned int draw_flags,
+ int alpha_mode,
+ int samples,
+ const char *viewname,
+ struct GPUOffScreen *ofs,
+ char err_out[256]);
+struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ int drawtype,
+ struct Object *camera,
+ int width,
+ int height,
+ unsigned int flag,
+ unsigned int draw_flags,
+ int alpha_mode,
+ int samples,
+ 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_update_viewmat(
- struct Depsgraph *depsgraph, struct Scene *scene, struct View3D *v3d, struct ARegion *ar,
- float viewmat[4][4], float winmat[4][4], const struct rcti *rect);
+void ED_view3d_update_viewmat(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct View3D *v3d,
+ struct ARegion *ar,
+ float viewmat[4][4],
+ float winmat[4][4],
+ const struct rcti *rect);
bool ED_view3d_quat_from_axis_view(const char view, float quat[4]);
char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon);
char ED_view3d_lock_view_from_index(int index);
char ED_view3d_axis_view_opposite(char view);
bool ED_view3d_lock(struct RegionView3D *rv3d);
-void ED_view3d_datamask(
- const struct bContext *C, const struct Scene *scene, const struct View3D *v3d,
- struct CustomData_MeshMasks *r_cddata_masks);
-void ED_view3d_screen_datamask(
- const struct bContext *C, const struct Scene *scene, const struct bScreen *screen,
- struct CustomData_MeshMasks *r_cddata_masks);
+void ED_view3d_datamask(const struct bContext *C,
+ const struct Scene *scene,
+ const struct View3D *v3d,
+ struct CustomData_MeshMasks *r_cddata_masks);
+void ED_view3d_screen_datamask(const struct bContext *C,
+ const struct Scene *scene,
+ const struct bScreen *screen,
+ struct CustomData_MeshMasks *r_cddata_masks);
bool ED_view3d_offset_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d);
-void ED_view3d_persp_switch_from_camera(
- const struct Depsgraph *depsgraph,
- struct View3D *v3d, struct RegionView3D *rv3d, const char persp);
-bool ED_view3d_persp_ensure(
- const struct Depsgraph *depsgraph,
- struct View3D *v3d, struct ARegion *ar);
-
+void ED_view3d_persp_switch_from_camera(const struct Depsgraph *depsgraph,
+ struct View3D *v3d,
+ struct RegionView3D *rv3d,
+ const char persp);
+bool ED_view3d_persp_ensure(const struct Depsgraph *depsgraph,
+ struct View3D *v3d,
+ struct ARegion *ar);
/* camera lock functions */
bool ED_view3d_camera_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d);
/* copy the camera to the view before starting a view transformation */
-void ED_view3d_camera_lock_init_ex(
- const struct Depsgraph *depsgraph,
- struct View3D *v3d, struct RegionView3D *rv3d, const bool calc_dist);
-void ED_view3d_camera_lock_init(const struct Depsgraph *depsgraph, struct View3D *v3d, struct RegionView3D *rv3d);
+void ED_view3d_camera_lock_init_ex(const struct Depsgraph *depsgraph,
+ struct View3D *v3d,
+ struct RegionView3D *rv3d,
+ const bool calc_dist);
+void ED_view3d_camera_lock_init(const struct Depsgraph *depsgraph,
+ struct View3D *v3d,
+ struct RegionView3D *rv3d);
/* copy the view to the camera, return true if */
-bool ED_view3d_camera_lock_sync(
- const struct Depsgraph *depsgraph,
- struct View3D *v3d, struct RegionView3D *rv3d);
-
-bool ED_view3d_camera_autokey(
- struct Scene *scene, struct ID *id_key,
- struct bContext *C, const bool do_rotate, const bool do_translate);
-bool ED_view3d_camera_lock_autokey(
- struct View3D *v3d, struct RegionView3D *rv3d,
- struct bContext *C, const bool do_rotate, const bool do_translate);
+bool ED_view3d_camera_lock_sync(const struct Depsgraph *depsgraph,
+ struct View3D *v3d,
+ struct RegionView3D *rv3d);
+
+bool ED_view3d_camera_autokey(struct Scene *scene,
+ struct ID *id_key,
+ struct bContext *C,
+ const bool do_rotate,
+ const bool do_translate);
+bool ED_view3d_camera_lock_autokey(struct View3D *v3d,
+ struct RegionView3D *rv3d,
+ struct bContext *C,
+ const bool do_rotate,
+ const bool do_translate);
void ED_view3d_lock_clear(struct View3D *v3d);
@@ -535,12 +691,14 @@ void ED_view3d_lock_clear(struct View3D *v3d);
#define VIEW3D_DIST_FALLBACK 1.0f
float ED_view3d_offset_distance(float mat[4][4], const float ofs[3], const float dist_fallback);
-void ED_view3d_distance_set(struct RegionView3D *rv3d, const float dist);
+void ED_view3d_distance_set(struct RegionView3D *rv3d, const float dist);
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);
-float ED_view3d_grid_view_scale(
- struct Scene *scene, struct View3D *v3d, struct RegionView3D *rv3d, const char **grid_unit);
+float ED_view3d_grid_view_scale(struct Scene *scene,
+ struct View3D *v3d,
+ struct RegionView3D *rv3d,
+ const char **grid_unit);
void ED_scene_draw_fps(struct Scene *scene, int xoffset, int *yoffset);
@@ -556,22 +714,27 @@ void ED_view3d_operator_properties_viewmat_get(struct wmOperator *op, int *winx,
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);
-#define XRAY_ALPHA(v3d) (((v3d)->shading.type == OB_WIRE) ? (v3d)->shading.xray_alpha_wire : (v3d)->shading.xray_alpha)
-#define XRAY_FLAG(v3d) (((v3d)->shading.type == OB_WIRE) ? V3D_SHADING_XRAY_BONE : V3D_SHADING_XRAY)
+#define XRAY_ALPHA(v3d) \
+ (((v3d)->shading.type == OB_WIRE) ? (v3d)->shading.xray_alpha_wire : (v3d)->shading.xray_alpha)
+#define XRAY_FLAG(v3d) \
+ (((v3d)->shading.type == OB_WIRE) ? V3D_SHADING_XRAY_BONE : V3D_SHADING_XRAY)
#define XRAY_FLAG_ENABLED(v3d) (((v3d)->shading.flag & XRAY_FLAG(v3d)) != 0)
-#define XRAY_ENABLED(v3d) (XRAY_FLAG_ENABLED(v3d) && (XRAY_ALPHA(v3d) < 1.0f))
-#define XRAY_ACTIVE(v3d) (XRAY_ENABLED(v3d) && ((v3d)->shading.type < OB_MATERIAL))
+#define XRAY_ENABLED(v3d) (XRAY_FLAG_ENABLED(v3d) && (XRAY_ALPHA(v3d) < 1.0f))
+#define XRAY_ACTIVE(v3d) (XRAY_ENABLED(v3d) && ((v3d)->shading.type < OB_MATERIAL))
/* view3d_draw_legacy.c */
/* Try avoid using these more move out of legacy. */
-void ED_view3d_draw_bgpic_test(
- struct Scene *scene, struct Depsgraph *depsgraph,
- struct ARegion *ar, struct View3D *v3d,
- const bool do_foreground, const bool do_camera_frame);
+void ED_view3d_draw_bgpic_test(struct Scene *scene,
+ struct Depsgraph *depsgraph,
+ struct ARegion *ar,
+ struct View3D *v3d,
+ const bool do_foreground,
+ const bool do_camera_frame);
/* view3d_gizmo_preselect_type.c */
-void ED_view3d_gizmo_mesh_preselect_get_active(
- struct bContext *C, struct wmGizmo *gz,
- struct Base **r_base, struct BMElem **r_ele);
+void ED_view3d_gizmo_mesh_preselect_get_active(struct bContext *C,
+ struct wmGizmo *gz,
+ struct Base **r_base,
+ struct BMElem **r_ele);
#endif /* __ED_VIEW3D_H__ */
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 419fe961cec..2f624007c98 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -71,7 +71,7 @@ DEF_ICON_BLANK(77)
DEF_ICON(NODE)
DEF_ICON(NODE_SEL)
- /* ui */
+/* ui */
DEF_ICON(WINDOW)
DEF_ICON(WORKSPACE)
DEF_ICON(RIGHTARROW_THIN)
@@ -85,7 +85,7 @@ DEF_ICON(EYEDROPPER)
DEF_ICON_BLANK(92)
DEF_ICON(AUTO)
DEF_ICON(CHECKBOX_DEHLT) /* de-Hilight - Checkbox OFF */
-DEF_ICON(CHECKBOX_HLT) /* Hilight - Checkbox ON */
+DEF_ICON(CHECKBOX_HLT) /* Hilight - Checkbox ON */
DEF_ICON(UNLOCKED)
DEF_ICON(LOCKED)
DEF_ICON(UNPINNED)
@@ -99,10 +99,10 @@ DEF_ICON_BLANK(105)
DEF_ICON_BLANK(106)
DEF_ICON(PLUGIN)
- /* various ui */
+/* various ui */
DEF_ICON(HELP)
DEF_ICON(GHOST_ENABLED)
-DEF_ICON(COLOR) /* see COLOR_RED/GREEN/BLUE */
+DEF_ICON(COLOR) /* see COLOR_RED/GREEN/BLUE */
DEF_ICON(UNLINKED)
DEF_ICON(LINKED)
DEF_ICON(HAND)
@@ -127,7 +127,7 @@ DEF_ICON(FULLSCREEN_ENTER)
DEF_ICON(FULLSCREEN_EXIT)
DEF_ICON_BLANK(135)
- /* BUTTONS */
+/* BUTTONS */
DEF_ICON_SHADING(LIGHT)
DEF_ICON_SHADING(MATERIAL)
DEF_ICON_SHADING(TEXTURE)
@@ -151,10 +151,10 @@ DEF_ICON_BLANK(157)
DEF_ICON_BLANK(158)
DEF_ICON_BLANK(159)
DEF_ICON_BLANK(160)
-DEF_ICON(BLANK1) // Not actually blank - this is used all over the place
+DEF_ICON(BLANK1) // Not actually blank - this is used all over the place
DEF_ICON(FAKE_USER_OFF)
DEF_ICON(FAKE_USER_ON)
- /* EDITORS */
+/* EDITORS */
DEF_ICON(VIEW3D)
DEF_ICON(GRAPH)
DEF_ICON(OUTLINER)
@@ -182,8 +182,8 @@ DEF_ICON(NODE_MATERIAL)
DEF_ICON(UV)
DEF_ICON_BLANK(190)
- /* MODES */
-DEF_ICON(OBJECT_DATAMODE) // XXX fix this up
+/* MODES */
+DEF_ICON(OBJECT_DATAMODE) // XXX fix this up
DEF_ICON(EDITMODE_HLT)
DEF_ICON(UV_DATA)
DEF_ICON(VPAINT_HLT)
@@ -210,7 +210,7 @@ DEF_ICON(TRACKING_REFINE_BACKWARDS)
DEF_ICON(TRACKING_REFINE_FORWARDS)
DEF_ICON_BLANK(77b)
- /* DATA */
+/* DATA */
DEF_ICON(SCENE_DATA)
DEF_ICON(RENDERLAYERS)
DEF_ICON_SHADING(WORLD_DATA)
@@ -238,7 +238,7 @@ DEF_ICON(PACKAGE)
DEF_ICON(UGLYPACKAGE)
DEF_ICON(EXPERIMENTAL)
- /* DATA */
+/* DATA */
DEF_ICON_SHADING(BRUSH_DATA)
DEF_ICON_SHADING(IMAGE_DATA)
DEF_ICON(FILE)
@@ -266,7 +266,7 @@ DEF_ICON_BLANK(272)
DEF_ICON(RNA)
DEF_ICON(RNA_ADD)
- /* INPUT + DECORATOR */
+/* INPUT + DECORATOR */
DEF_ICON(MOUSE_LMB)
DEF_ICON(MOUSE_MMB)
DEF_ICON(MOUSE_RMB)
@@ -294,7 +294,7 @@ DEF_ICON(USER)
DEF_ICON(SYSTEM)
DEF_ICON(SETTINGS)
- /* OUTLINER */
+/* OUTLINER */
DEF_ICON_OBJECT(OUTLINER_OB_EMPTY)
DEF_ICON_OBJECT(OUTLINER_OB_MESH)
DEF_ICON_OBJECT(OUTLINER_OB_CURVE)
@@ -322,7 +322,7 @@ DEF_ICON(RESTRICT_RENDER_ON)
DEF_ICON(RESTRICT_RENDER_OFF)
DEF_ICON_BLANK(330)
- /* OUTLINER */
+/* OUTLINER */
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_EMPTY)
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_MESH)
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_CURVE)
@@ -350,7 +350,7 @@ DEF_ICON(RESTRICT_VIEW_ON)
DEF_ICON(RESTRICT_VIEW_OFF)
DEF_ICON_BLANK(353)
- /* PRIMITIVES */
+/* PRIMITIVES */
DEF_ICON(MESH_PLANE)
DEF_ICON(MESH_CUBE)
DEF_ICON(MESH_CIRCLE)
@@ -378,7 +378,7 @@ DEF_ICON(META_ELLIPSOID)
DEF_ICON(META_CAPSULE)
DEF_ICON_BLANK(625)
- /* PRIMITIVES */
+/* PRIMITIVES */
DEF_ICON(SURFACE_NCURVE)
DEF_ICON(SURFACE_NCIRCLE)
DEF_ICON(SURFACE_NSURFACE)
@@ -406,7 +406,7 @@ DEF_ICON(TRIA_DOWN_BAR)
DEF_ICON(TRIA_LEFT_BAR)
DEF_ICON(TRIA_UP_BAR)
- /* EMPTY */
+/* EMPTY */
DEF_ICON(FORCE_FORCE)
DEF_ICON(FORCE_WIND)
DEF_ICON(FORCE_VORTEX)
@@ -434,7 +434,7 @@ DEF_ICON(IMAGE_PLANE)
DEF_ICON(IMAGE_BACKGROUND)
DEF_ICON(IMAGE_REFERENCE)
- /* EMPTY */
+/* EMPTY */
DEF_ICON_BLANK(445)
DEF_ICON_BLANK(446)
DEF_ICON_BLANK(447)
@@ -462,7 +462,7 @@ DEF_ICON_BLANK(713)
DEF_ICON_BLANK(714)
DEF_ICON_BLANK(715)
- /* EMPTY */
+/* EMPTY */
DEF_ICON(ALIGN_LEFT)
DEF_ICON(ALIGN_CENTER)
DEF_ICON(ALIGN_RIGHT)
@@ -490,7 +490,7 @@ DEF_ICON_BLANK(753)
DEF_ICON_BLANK(754)
DEF_ICON_BLANK(755)
- /* EMPTY */
+/* EMPTY */
DEF_ICON_BLANK(501)
DEF_ICON_BLANK(502)
DEF_ICON_BLANK(503)
@@ -518,7 +518,7 @@ DEF_ICON_BLANK(524)
DEF_ICON_BLANK(525)
DEF_ICON_BLANK(526)
- /* MODIFIERS */
+/* MODIFIERS */
DEF_ICON_MODIFIER(MODIFIER_DATA)
DEF_ICON_MODIFIER(MOD_WAVE)
DEF_ICON_MODIFIER(MOD_BUILD)
@@ -546,7 +546,7 @@ DEF_ICON_MODIFIER(MOD_SMOOTH)
DEF_ICON_MODIFIER(MOD_SIMPLEDEFORM)
DEF_ICON_MODIFIER(MOD_MASK)
- /* MODIFIERS */
+/* MODIFIERS */
DEF_ICON_MODIFIER(MOD_CLOTH)
DEF_ICON_MODIFIER(MOD_EXPLODE)
DEF_ICON_MODIFIER(MOD_FLUIDSIM)
@@ -574,7 +574,7 @@ DEF_ICON_MODIFIER(MOD_INSTANCE)
DEF_ICON_MODIFIER(MOD_TIME)
DEF_ICON_MODIFIER(MOD_OPACITY)
- /* ANIMATION */
+/* ANIMATION */
DEF_ICON(REC)
DEF_ICON(PLAY)
DEF_ICON(FF)
@@ -602,7 +602,7 @@ DEF_ICON(VISIBLE_IPO_OFF)
DEF_ICON(VISIBLE_IPO_ON)
DEF_ICON(DRIVER)
- /* ANIMATION */
+/* ANIMATION */
DEF_ICON(SOLO_OFF)
DEF_ICON(SOLO_ON)
DEF_ICON(FRAME_PREV)
@@ -630,7 +630,7 @@ DEF_ICON_BLANK(636)
DEF_ICON_BLANK(637)
DEF_ICON_BLANK(638)
- /* EDITING */
+/* EDITING */
DEF_ICON(VERTEXSEL)
DEF_ICON(EDGESEL)
DEF_ICON(FACESEL)
@@ -658,7 +658,7 @@ DEF_ICON(PARTICLE_POINT)
DEF_ICON(PARTICLE_TIP)
DEF_ICON(PARTICLE_PATH)
- /* EDITING */
+/* EDITING */
DEF_ICON_BLANK(669)
DEF_ICON_BLANK(670)
DEF_ICON_BLANK(671)
@@ -686,7 +686,7 @@ DEF_ICON(ORIENTATION_LOCAL)
DEF_ICON(ORIENTATION_NORMAL)
DEF_ICON(ORIENTATION_VIEW)
- /* EDITING */
+/* EDITING */
DEF_ICON(COPYDOWN)
DEF_ICON(PASTEDOWN)
DEF_ICON(PASTEFLIPUP)
@@ -714,7 +714,7 @@ DEF_ICON(NORMALS_VERTEX)
DEF_ICON(NORMALS_FACE)
DEF_ICON(NORMALS_VERTEX_FACE)
- /* 3D VIEW */
+/* 3D VIEW */
DEF_ICON(SHADING_BBOX)
DEF_ICON(SHADING_WIRE)
DEF_ICON(SHADING_SOLID)
@@ -736,7 +736,7 @@ DEF_ICON(NDOF_FLY)
DEF_ICON(NDOF_TRANS)
DEF_ICON(LAYER_USED)
DEF_ICON(LAYER_ACTIVE)
- /* available */
+/* available */
DEF_ICON_BLANK(254)
DEF_ICON_BLANK(255)
DEF_ICON_BLANK(256)
@@ -769,7 +769,7 @@ DEF_ICON_BLANK(775)
DEF_ICON_BLANK(776)
DEF_ICON_BLANK(777)
- /* FILE SELECT */
+/* FILE SELECT */
DEF_ICON(SORTALPHA)
DEF_ICON(SORTBYEXT)
DEF_ICON(SORTTIME)
@@ -797,7 +797,7 @@ DEF_ICON(FILE_SOUND)
DEF_ICON(FILE_FONT)
DEF_ICON(FILE_TEXT)
- /* FILE SELECT */
+/* FILE SELECT */
DEF_ICON(SORT_DESC)
DEF_ICON(SORT_ASC)
DEF_ICON(LINK_BLEND)
@@ -825,7 +825,7 @@ DEF_ICON(FILE_HIDDEN)
DEF_ICON(FILE_BACKUP)
DEF_ICON(DISK_DRIVE)
- /* SHADING / TEXT */
+/* SHADING / TEXT */
DEF_ICON(MATPLANE)
DEF_ICON(MATSPHERE)
DEF_ICON(MATCUBE)
@@ -853,7 +853,7 @@ DEF_ICON_BLANK(859)
DEF_ICON_BLANK(860)
DEF_ICON_BLANK(861)
- /* SEQUENCE / IMAGE EDITOR */
+/* SEQUENCE / IMAGE EDITOR */
DEF_ICON(SEQ_SEQUENCER)
DEF_ICON(SEQ_PREVIEW)
DEF_ICON(SEQ_LUMA_WAVEFORM)
@@ -863,7 +863,7 @@ DEF_ICON(SEQ_SPLITVIEW)
DEF_ICON_BLANK(870)
DEF_ICON_BLANK(871)
DEF_ICON_BLANK(872)
-DEF_ICON(IMAGE_RGB) // XXX CHANGE TO STRAIGHT ALPHA, Z ETC
+DEF_ICON(IMAGE_RGB) // XXX CHANGE TO STRAIGHT ALPHA, Z ETC
DEF_ICON(IMAGE_RGB_ALPHA)
DEF_ICON(IMAGE_ALPHA)
DEF_ICON(IMAGE_ZDEPTH)
@@ -881,7 +881,7 @@ DEF_ICON(VIEW_CAMERA)
DEF_ICON(VIEW_PAN)
DEF_ICON(VIEW_ZOOM)
- /* brush icons */
+/* brush icons */
DEF_ICON_COLOR(BRUSH_BLOB)
DEF_ICON_COLOR(BRUSH_BLUR)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index b862f36337c..d3cce4a5dde 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -78,7 +78,7 @@ typedef struct uiPopupBlockHandle uiPopupBlockHandle;
/* Defines */
/* char for splitting strings, aligning shortcuts in menus, users never see */
-#define UI_SEP_CHAR '|'
+#define UI_SEP_CHAR '|'
#define UI_SEP_CHAR_S "|"
/* names */
@@ -91,135 +91,135 @@ typedef struct uiPopupBlockHandle uiPopupBlockHandle;
/* uiBlock->dt and uiBut->dt */
enum {
- UI_EMBOSS = 0, /* use widget style for drawing */
- UI_EMBOSS_NONE = 1, /* Nothing, only icon and/or text */
- UI_EMBOSS_PULLDOWN = 2, /* Pulldown menu style */
- UI_EMBOSS_RADIAL = 3, /* Pie Menu */
+ UI_EMBOSS = 0, /* use widget style for drawing */
+ UI_EMBOSS_NONE = 1, /* Nothing, only icon and/or text */
+ UI_EMBOSS_PULLDOWN = 2, /* Pulldown menu style */
+ UI_EMBOSS_RADIAL = 3, /* Pie Menu */
- UI_EMBOSS_UNDEFINED = 255, /* For layout engine, use emboss from block. */
+ UI_EMBOSS_UNDEFINED = 255, /* For layout engine, use emboss from block. */
};
/* uiBlock->direction */
enum {
- UI_DIR_UP = 1 << 0,
- UI_DIR_DOWN = 1 << 1,
- UI_DIR_LEFT = 1 << 2,
- UI_DIR_RIGHT = 1 << 3,
- UI_DIR_CENTER_X = 1 << 4,
- UI_DIR_CENTER_Y = 1 << 5,
-
- UI_DIR_ALL = UI_DIR_UP | UI_DIR_DOWN | UI_DIR_LEFT | UI_DIR_RIGHT,
+ UI_DIR_UP = 1 << 0,
+ UI_DIR_DOWN = 1 << 1,
+ UI_DIR_LEFT = 1 << 2,
+ UI_DIR_RIGHT = 1 << 3,
+ UI_DIR_CENTER_X = 1 << 4,
+ UI_DIR_CENTER_Y = 1 << 5,
+
+ UI_DIR_ALL = UI_DIR_UP | UI_DIR_DOWN | UI_DIR_LEFT | UI_DIR_RIGHT,
};
#if 0
/* uiBlock->autofill (not yet used) */
-#define UI_BLOCK_COLLUMNS 1
-#define UI_BLOCK_ROWS 2
+# define UI_BLOCK_COLLUMNS 1
+# define UI_BLOCK_ROWS 2
#endif
/** #uiBlock.flag (controls) */
enum {
- UI_BLOCK_LOOP = 1 << 0,
- UI_BLOCK_IS_FLIP = 1 << 1,
- UI_BLOCK_NO_FLIP = 1 << 2,
- UI_BLOCK_NUMSELECT = 1 << 3,
- /** Don't apply window clipping. */
- UI_BLOCK_NO_WIN_CLIP = 1 << 4,
- UI_BLOCK_CLIPBOTTOM = 1 << 5,
- UI_BLOCK_CLIPTOP = 1 << 6,
- UI_BLOCK_MOVEMOUSE_QUIT = 1 << 7,
- UI_BLOCK_KEEP_OPEN = 1 << 8,
- UI_BLOCK_POPUP = 1 << 9,
- UI_BLOCK_OUT_1 = 1 << 10,
- UI_BLOCK_SEARCH_MENU = 1 << 11,
- UI_BLOCK_POPUP_MEMORY = 1 << 12,
- /* Stop handling mouse events. */
- UI_BLOCK_CLIP_EVENTS = 1 << 13,
-
- /* block->flag bits 14-17 are identical to but->drawflag bits */
-
- UI_BLOCK_POPUP_HOLD = 1 << 18,
- UI_BLOCK_LIST_ITEM = 1 << 19,
- UI_BLOCK_RADIAL = 1 << 20,
- UI_BLOCK_POPOVER = 1 << 21,
- UI_BLOCK_POPOVER_ONCE = 1 << 22,
- /** Always show keymaps, even for non-menus. */
- UI_BLOCK_SHOW_SHORTCUT_ALWAYS = 1 << 23,
+ UI_BLOCK_LOOP = 1 << 0,
+ UI_BLOCK_IS_FLIP = 1 << 1,
+ UI_BLOCK_NO_FLIP = 1 << 2,
+ UI_BLOCK_NUMSELECT = 1 << 3,
+ /** Don't apply window clipping. */
+ UI_BLOCK_NO_WIN_CLIP = 1 << 4,
+ UI_BLOCK_CLIPBOTTOM = 1 << 5,
+ UI_BLOCK_CLIPTOP = 1 << 6,
+ UI_BLOCK_MOVEMOUSE_QUIT = 1 << 7,
+ UI_BLOCK_KEEP_OPEN = 1 << 8,
+ UI_BLOCK_POPUP = 1 << 9,
+ UI_BLOCK_OUT_1 = 1 << 10,
+ UI_BLOCK_SEARCH_MENU = 1 << 11,
+ UI_BLOCK_POPUP_MEMORY = 1 << 12,
+ /* Stop handling mouse events. */
+ UI_BLOCK_CLIP_EVENTS = 1 << 13,
+
+ /* block->flag bits 14-17 are identical to but->drawflag bits */
+
+ UI_BLOCK_POPUP_HOLD = 1 << 18,
+ UI_BLOCK_LIST_ITEM = 1 << 19,
+ UI_BLOCK_RADIAL = 1 << 20,
+ UI_BLOCK_POPOVER = 1 << 21,
+ UI_BLOCK_POPOVER_ONCE = 1 << 22,
+ /** Always show keymaps, even for non-menus. */
+ UI_BLOCK_SHOW_SHORTCUT_ALWAYS = 1 << 23,
};
/** #uiPopupBlockHandle.menuretval */
enum {
- /** Cancel all menus cascading. */
- UI_RETURN_CANCEL = 1 << 0,
- /** Choice made. */
- UI_RETURN_OK = 1 << 1,
- /** Left the menu. */
- UI_RETURN_OUT = 1 << 2,
- /** Let the parent handle this event. */
- UI_RETURN_OUT_PARENT = 1 << 3,
- /** Update the button that opened. */
- UI_RETURN_UPDATE = 1 << 4,
- /** Popup is ok to be handled. */
- UI_RETURN_POPUP_OK = 1 << 5,
+ /** Cancel all menus cascading. */
+ UI_RETURN_CANCEL = 1 << 0,
+ /** Choice made. */
+ UI_RETURN_OK = 1 << 1,
+ /** Left the menu. */
+ UI_RETURN_OUT = 1 << 2,
+ /** Let the parent handle this event. */
+ UI_RETURN_OUT_PARENT = 1 << 3,
+ /** Update the button that opened. */
+ UI_RETURN_UPDATE = 1 << 4,
+ /** Popup is ok to be handled. */
+ UI_RETURN_POPUP_OK = 1 << 5,
};
/* panel controls */
enum {
- UI_PNL_SOLID = 1 << 1,
- UI_PNL_CLOSE = 1 << 5,
- UI_PNL_SCALE = 1 << 9,
+ UI_PNL_SOLID = 1 << 1,
+ UI_PNL_CLOSE = 1 << 5,
+ UI_PNL_SCALE = 1 << 9,
};
/* but->flag - general state flags. */
enum {
- /** Warning, the first 6 flags are internal. */
- UI_BUT_ICON_SUBMENU = 1 << 6,
- UI_BUT_ICON_PREVIEW = 1 << 7,
-
- UI_BUT_NODE_LINK = 1 << 8,
- UI_BUT_NODE_ACTIVE = 1 << 9,
- UI_BUT_DRAG_LOCK = 1 << 10,
- /** Grayed out and un-editable. */
- UI_BUT_DISABLED = 1 << 11,
-
- UI_BUT_ANIMATED = 1 << 13,
- UI_BUT_ANIMATED_KEY = 1 << 14,
- UI_BUT_DRIVEN = 1 << 15,
- UI_BUT_REDALERT = 1 << 16,
- /** Grayed out but still editable. */
- UI_BUT_INACTIVE = 1 << 17,
- UI_BUT_LAST_ACTIVE = 1 << 18,
- UI_BUT_UNDO = 1 << 19,
- UI_BUT_IMMEDIATE = 1 << 20,
- UI_BUT_NO_UTF8 = 1 << 21,
-
- /** For popups, pressing return activates this button, overriding the highlighted button.
- * For non-popups this is just used as a display hint for the user to let them
- * know the action which is activated when pressing return (file selector for eg). */
- UI_BUT_ACTIVE_DEFAULT = 1 << 23,
-
- /** This but is "inside" a list item (currently used to change theme colors). */
- UI_BUT_LIST_ITEM = 1 << 24,
- /** edit this button as well as the active button (not just dragging) */
- UI_BUT_DRAG_MULTI = 1 << 25,
- /** Use for popups to start editing the button on initialization. */
- UI_BUT_ACTIVATE_ON_INIT = 1 << 26,
-
- /** #uiBut.str contains #UI_SEP_CHAR, used for key shortcuts */
- UI_BUT_HAS_SEP_CHAR = 1 << 27,
- /** Don't run updates while dragging (needed in rare cases). */
- UI_BUT_UPDATE_DELAY = 1 << 28,
- /** When widget is in textedit mode, update value on each char stroke */
- UI_BUT_TEXTEDIT_UPDATE = 1 << 29,
- /** Show 'x' icon to clear/unlink value of text or search button. */
- UI_BUT_VALUE_CLEAR = 1 << 30,
-
- /** RNA property of the button is overridden from linked reference data. */
- UI_BUT_OVERRIDEN = 1u << 31u,
+ /** Warning, the first 6 flags are internal. */
+ UI_BUT_ICON_SUBMENU = 1 << 6,
+ UI_BUT_ICON_PREVIEW = 1 << 7,
+
+ UI_BUT_NODE_LINK = 1 << 8,
+ UI_BUT_NODE_ACTIVE = 1 << 9,
+ UI_BUT_DRAG_LOCK = 1 << 10,
+ /** Grayed out and un-editable. */
+ UI_BUT_DISABLED = 1 << 11,
+
+ UI_BUT_ANIMATED = 1 << 13,
+ UI_BUT_ANIMATED_KEY = 1 << 14,
+ UI_BUT_DRIVEN = 1 << 15,
+ UI_BUT_REDALERT = 1 << 16,
+ /** Grayed out but still editable. */
+ UI_BUT_INACTIVE = 1 << 17,
+ UI_BUT_LAST_ACTIVE = 1 << 18,
+ UI_BUT_UNDO = 1 << 19,
+ UI_BUT_IMMEDIATE = 1 << 20,
+ UI_BUT_NO_UTF8 = 1 << 21,
+
+ /** For popups, pressing return activates this button, overriding the highlighted button.
+ * For non-popups this is just used as a display hint for the user to let them
+ * know the action which is activated when pressing return (file selector for eg). */
+ UI_BUT_ACTIVE_DEFAULT = 1 << 23,
+
+ /** This but is "inside" a list item (currently used to change theme colors). */
+ UI_BUT_LIST_ITEM = 1 << 24,
+ /** edit this button as well as the active button (not just dragging) */
+ UI_BUT_DRAG_MULTI = 1 << 25,
+ /** Use for popups to start editing the button on initialization. */
+ UI_BUT_ACTIVATE_ON_INIT = 1 << 26,
+
+ /** #uiBut.str contains #UI_SEP_CHAR, used for key shortcuts */
+ UI_BUT_HAS_SEP_CHAR = 1 << 27,
+ /** Don't run updates while dragging (needed in rare cases). */
+ UI_BUT_UPDATE_DELAY = 1 << 28,
+ /** When widget is in textedit mode, update value on each char stroke */
+ UI_BUT_TEXTEDIT_UPDATE = 1 << 29,
+ /** Show 'x' icon to clear/unlink value of text or search button. */
+ UI_BUT_VALUE_CLEAR = 1 << 30,
+
+ /** RNA property of the button is overridden from linked reference data. */
+ UI_BUT_OVERRIDEN = 1u << 31u,
};
-#define UI_PANEL_WIDTH 340
-#define UI_COMPACT_PANEL_WIDTH 160
+#define UI_PANEL_WIDTH 340
+#define UI_COMPACT_PANEL_WIDTH 160
#define UI_NAVIGATION_REGION_WIDTH UI_COMPACT_PANEL_WIDTH
#define UI_NARROW_NAVIGATION_REGION_WIDTH 100
@@ -230,48 +230,48 @@ enum {
* (except for the 'align' ones)!
*/
enum {
- /** Text and icon alignment (by default, they are centered). */
- UI_BUT_TEXT_LEFT = 1 << 1,
- UI_BUT_ICON_LEFT = 1 << 2,
- UI_BUT_TEXT_RIGHT = 1 << 3,
- /** Prevent the button to show any tooltip. */
- UI_BUT_NO_TOOLTIP = 1 << 4,
-
- /* Button align flag, for drawing groups together.
- * Used in 'uiBlock.flag', take care! */
- UI_BUT_ALIGN_TOP = 1 << 14,
- UI_BUT_ALIGN_LEFT = 1 << 15,
- UI_BUT_ALIGN_RIGHT = 1 << 16,
- UI_BUT_ALIGN_DOWN = 1 << 17,
- UI_BUT_ALIGN = UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_LEFT | UI_BUT_ALIGN_RIGHT | UI_BUT_ALIGN_DOWN,
- /* end bits shared with 'uiBlock.flag' */
-
- /**
- * Warning - HACK!
- * Needed for buttons which are not TOP/LEFT aligned,
- * but have some top/left corner stitched to some other TOP/LEFT-aligned button,
- * because of 'corrective' hack in widget_roundbox_set()... */
- UI_BUT_ALIGN_STITCH_TOP = 1 << 18,
- UI_BUT_ALIGN_STITCH_LEFT = 1 << 19,
- UI_BUT_ALIGN_ALL = UI_BUT_ALIGN | UI_BUT_ALIGN_STITCH_TOP | UI_BUT_ALIGN_STITCH_LEFT,
-
- /** This but is "inside" a box item (currently used to change theme colors). */
- UI_BUT_BOX_ITEM = 1 << 20,
-
- /** Active left part of number button */
- UI_BUT_ACTIVE_LEFT = 1 << 21,
- /** Active right part of number button */
- UI_BUT_ACTIVE_RIGHT = 1 << 22,
-
- /* (also used by search buttons to enforce shortcut display for their items). */
- /** Button has shortcut text. */
- UI_BUT_HAS_SHORTCUT = 1 << 23,
-
- /** Reverse order of consecutive off/on icons */
- UI_BUT_ICON_REVERSE = 1 << 24,
-
- /** Value is animated, but the current value differs from the animated one. */
- UI_BUT_ANIMATED_CHANGED = 1 << 25,
+ /** Text and icon alignment (by default, they are centered). */
+ UI_BUT_TEXT_LEFT = 1 << 1,
+ UI_BUT_ICON_LEFT = 1 << 2,
+ UI_BUT_TEXT_RIGHT = 1 << 3,
+ /** Prevent the button to show any tooltip. */
+ UI_BUT_NO_TOOLTIP = 1 << 4,
+
+ /* Button align flag, for drawing groups together.
+ * Used in 'uiBlock.flag', take care! */
+ UI_BUT_ALIGN_TOP = 1 << 14,
+ UI_BUT_ALIGN_LEFT = 1 << 15,
+ UI_BUT_ALIGN_RIGHT = 1 << 16,
+ UI_BUT_ALIGN_DOWN = 1 << 17,
+ UI_BUT_ALIGN = UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_LEFT | UI_BUT_ALIGN_RIGHT | UI_BUT_ALIGN_DOWN,
+ /* end bits shared with 'uiBlock.flag' */
+
+ /**
+ * Warning - HACK!
+ * Needed for buttons which are not TOP/LEFT aligned,
+ * but have some top/left corner stitched to some other TOP/LEFT-aligned button,
+ * because of 'corrective' hack in widget_roundbox_set()... */
+ UI_BUT_ALIGN_STITCH_TOP = 1 << 18,
+ UI_BUT_ALIGN_STITCH_LEFT = 1 << 19,
+ UI_BUT_ALIGN_ALL = UI_BUT_ALIGN | UI_BUT_ALIGN_STITCH_TOP | UI_BUT_ALIGN_STITCH_LEFT,
+
+ /** This but is "inside" a box item (currently used to change theme colors). */
+ UI_BUT_BOX_ITEM = 1 << 20,
+
+ /** Active left part of number button */
+ UI_BUT_ACTIVE_LEFT = 1 << 21,
+ /** Active right part of number button */
+ UI_BUT_ACTIVE_RIGHT = 1 << 22,
+
+ /* (also used by search buttons to enforce shortcut display for their items). */
+ /** Button has shortcut text. */
+ UI_BUT_HAS_SHORTCUT = 1 << 23,
+
+ /** Reverse order of consecutive off/on icons */
+ UI_BUT_ICON_REVERSE = 1 << 24,
+
+ /** Value is animated, but the current value differs from the animated one. */
+ UI_BUT_ANIMATED_CHANGED = 1 << 25,
};
/* scale fixed button widths by this to account for DPI */
@@ -287,12 +287,12 @@ enum {
* - bit 9-15: button type (now 6 bits, 64 types)
* */
typedef enum {
- UI_BUT_POIN_CHAR = 32,
- UI_BUT_POIN_SHORT = 64,
- UI_BUT_POIN_INT = 96,
- UI_BUT_POIN_FLOAT = 128,
-/* UI_BUT_POIN_FUNCTION = 192, */ /*UNUSED*/
- UI_BUT_POIN_BIT = 256, /* OR'd with a bit index*/
+ UI_BUT_POIN_CHAR = 32,
+ UI_BUT_POIN_SHORT = 64,
+ UI_BUT_POIN_INT = 96,
+ UI_BUT_POIN_FLOAT = 128,
+ /* UI_BUT_POIN_FUNCTION = 192, */ /*UNUSED*/
+ UI_BUT_POIN_BIT = 256, /* OR'd with a bit index*/
} eButPointerType;
/* requires (but->poin != NULL) */
@@ -300,77 +300,77 @@ typedef enum {
/* assigned to but->type, OR'd with the flags above when passing args */
typedef enum {
- UI_BTYPE_BUT = 1 << 9,
- UI_BTYPE_ROW = 2 << 9,
- UI_BTYPE_TEXT = 3 << 9,
- /** dropdown list */
- UI_BTYPE_MENU = 4 << 9,
- UI_BTYPE_BUT_MENU = 5 << 9,
- /** number button */
- UI_BTYPE_NUM = 6 << 9,
- /** number slider */
- UI_BTYPE_NUM_SLIDER = 7 << 9,
- UI_BTYPE_TOGGLE = 8 << 9,
- UI_BTYPE_TOGGLE_N = 9 << 9,
- UI_BTYPE_ICON_TOGGLE = 10 << 9,
- UI_BTYPE_ICON_TOGGLE_N = 11 << 9,
- /** same as regular toggle, but no on/off state displayed */
- UI_BTYPE_BUT_TOGGLE = 12 << 9,
- /** similar to toggle, display a 'tick' */
- UI_BTYPE_CHECKBOX = 13 << 9,
- UI_BTYPE_CHECKBOX_N = 14 << 9,
- UI_BTYPE_COLOR = 15 << 9,
- UI_BTYPE_TAB = 16 << 9,
- UI_BTYPE_POPOVER = 17 << 9,
- UI_BTYPE_SCROLL = 18 << 9,
- UI_BTYPE_BLOCK = 19 << 9,
- UI_BTYPE_LABEL = 20 << 9,
- UI_BTYPE_KEY_EVENT = 24 << 9,
- UI_BTYPE_HSVCUBE = 26 << 9,
- /** menu (often used in headers), **_MENU /w different draw-type */
- UI_BTYPE_PULLDOWN = 27 << 9,
- UI_BTYPE_ROUNDBOX = 28 << 9,
- UI_BTYPE_COLORBAND = 30 << 9,
- /** sphere widget (used to input a unit-vector, aka normal) */
- UI_BTYPE_UNITVEC = 31 << 9,
- UI_BTYPE_CURVE = 32 << 9,
- UI_BTYPE_LISTBOX = 36 << 9,
- UI_BTYPE_LISTROW = 37 << 9,
- UI_BTYPE_HSVCIRCLE = 38 << 9,
- UI_BTYPE_TRACK_PREVIEW = 40 << 9,
-
- /** Buttons with value >= #UI_BTYPE_SEARCH_MENU don't get undo pushes. */
- UI_BTYPE_SEARCH_MENU = 41 << 9,
- UI_BTYPE_EXTRA = 42 << 9,
- UI_BTYPE_HOTKEY_EVENT = 46 << 9,
- /** Non-interactive image, used for splash screen */
- UI_BTYPE_IMAGE = 47 << 9,
- UI_BTYPE_HISTOGRAM = 48 << 9,
- UI_BTYPE_WAVEFORM = 49 << 9,
- UI_BTYPE_VECTORSCOPE = 50 << 9,
- UI_BTYPE_PROGRESS_BAR = 51 << 9,
- UI_BTYPE_NODE_SOCKET = 53 << 9,
- UI_BTYPE_SEPR = 54 << 9,
- UI_BTYPE_SEPR_LINE = 55 << 9,
- /** Dynamically fill available space. */
- UI_BTYPE_SEPR_SPACER = 56 << 9,
- /** Resize handle (resize uilist). */
- UI_BTYPE_GRIP = 57 << 9,
+ UI_BTYPE_BUT = 1 << 9,
+ UI_BTYPE_ROW = 2 << 9,
+ UI_BTYPE_TEXT = 3 << 9,
+ /** dropdown list */
+ UI_BTYPE_MENU = 4 << 9,
+ UI_BTYPE_BUT_MENU = 5 << 9,
+ /** number button */
+ UI_BTYPE_NUM = 6 << 9,
+ /** number slider */
+ UI_BTYPE_NUM_SLIDER = 7 << 9,
+ UI_BTYPE_TOGGLE = 8 << 9,
+ UI_BTYPE_TOGGLE_N = 9 << 9,
+ UI_BTYPE_ICON_TOGGLE = 10 << 9,
+ UI_BTYPE_ICON_TOGGLE_N = 11 << 9,
+ /** same as regular toggle, but no on/off state displayed */
+ UI_BTYPE_BUT_TOGGLE = 12 << 9,
+ /** similar to toggle, display a 'tick' */
+ UI_BTYPE_CHECKBOX = 13 << 9,
+ UI_BTYPE_CHECKBOX_N = 14 << 9,
+ UI_BTYPE_COLOR = 15 << 9,
+ UI_BTYPE_TAB = 16 << 9,
+ UI_BTYPE_POPOVER = 17 << 9,
+ UI_BTYPE_SCROLL = 18 << 9,
+ UI_BTYPE_BLOCK = 19 << 9,
+ UI_BTYPE_LABEL = 20 << 9,
+ UI_BTYPE_KEY_EVENT = 24 << 9,
+ UI_BTYPE_HSVCUBE = 26 << 9,
+ /** menu (often used in headers), **_MENU /w different draw-type */
+ UI_BTYPE_PULLDOWN = 27 << 9,
+ UI_BTYPE_ROUNDBOX = 28 << 9,
+ UI_BTYPE_COLORBAND = 30 << 9,
+ /** sphere widget (used to input a unit-vector, aka normal) */
+ UI_BTYPE_UNITVEC = 31 << 9,
+ UI_BTYPE_CURVE = 32 << 9,
+ UI_BTYPE_LISTBOX = 36 << 9,
+ UI_BTYPE_LISTROW = 37 << 9,
+ UI_BTYPE_HSVCIRCLE = 38 << 9,
+ UI_BTYPE_TRACK_PREVIEW = 40 << 9,
+
+ /** Buttons with value >= #UI_BTYPE_SEARCH_MENU don't get undo pushes. */
+ UI_BTYPE_SEARCH_MENU = 41 << 9,
+ UI_BTYPE_EXTRA = 42 << 9,
+ UI_BTYPE_HOTKEY_EVENT = 46 << 9,
+ /** Non-interactive image, used for splash screen */
+ UI_BTYPE_IMAGE = 47 << 9,
+ UI_BTYPE_HISTOGRAM = 48 << 9,
+ UI_BTYPE_WAVEFORM = 49 << 9,
+ UI_BTYPE_VECTORSCOPE = 50 << 9,
+ UI_BTYPE_PROGRESS_BAR = 51 << 9,
+ UI_BTYPE_NODE_SOCKET = 53 << 9,
+ UI_BTYPE_SEPR = 54 << 9,
+ UI_BTYPE_SEPR_LINE = 55 << 9,
+ /** Dynamically fill available space. */
+ UI_BTYPE_SEPR_SPACER = 56 << 9,
+ /** Resize handle (resize uilist). */
+ UI_BTYPE_GRIP = 57 << 9,
} eButType;
-#define BUTTYPE (63 << 9)
+#define BUTTYPE (63 << 9)
/** Gradient types, for color picker #UI_BTYPE_HSVCUBE etc. */
enum {
- UI_GRAD_SV = 0,
- UI_GRAD_HV = 1,
- UI_GRAD_HS = 2,
- UI_GRAD_H = 3,
- UI_GRAD_S = 4,
- UI_GRAD_V = 5,
-
- UI_GRAD_V_ALT = 9,
- UI_GRAD_L_ALT = 10,
+ UI_GRAD_SV = 0,
+ UI_GRAD_HV = 1,
+ UI_GRAD_HS = 2,
+ UI_GRAD_H = 3,
+ UI_GRAD_S = 4,
+ UI_GRAD_V = 5,
+
+ UI_GRAD_V_ALT = 9,
+ UI_GRAD_L_ALT = 10,
};
#define UI_PALETTE_COLOR 20
@@ -380,15 +380,40 @@ enum {
* Functions to draw various shapes, taking theme settings into account.
* Used for code that draws its own UI style elements. */
-void UI_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3, const float color[4]);
+void UI_draw_anti_tria(
+ float x1, float y1, float x2, float y2, float x3, float y3, const float color[4]);
void UI_draw_anti_fan(float tri_array[][2], unsigned int length, const float color[4]);
void UI_draw_roundbox_corner_set(int type);
-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_shade_x(bool filled, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown, const float col[4]);
+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_shade_x(bool filled,
+ float minx,
+ float miny,
+ float maxx,
+ float maxy,
+ float rad,
+ float shadetop,
+ float shadedown,
+ const float col[4]);
#if 0 /* unused */
int UI_draw_roundbox_corner_get(void);
@@ -398,21 +423,32 @@ void UI_draw_roundbox_shade_y(bool filled, float minx, float miny, float maxx, f
void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy);
void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const float color[4]);
-void UI_draw_safe_areas(uint pos, float x1, float x2, float y1, float y2,
- const float title_aspect[2], const float action_aspect[2]);
+void UI_draw_safe_areas(uint pos,
+ float x1,
+ float x2,
+ float y1,
+ float y2,
+ const float title_aspect[2],
+ const float action_aspect[2]);
/** State for scrolldrawing. */
enum {
- UI_SCROLL_PRESSED = 1 << 0,
- UI_SCROLL_ARROWS = 1 << 1,
- UI_SCROLL_NO_OUTLINE = 1 << 2,
+ UI_SCROLL_PRESSED = 1 << 0,
+ UI_SCROLL_ARROWS = 1 << 1,
+ UI_SCROLL_NO_OUTLINE = 1 << 2,
};
-void UI_draw_widget_scroll(struct uiWidgetColors *wcol, const struct rcti *rect, const struct rcti *slider, int state);
+void UI_draw_widget_scroll(struct uiWidgetColors *wcol,
+ const struct rcti *rect,
+ const struct rcti *slider,
+ int state);
/* Shortening string helper. */
-float UI_text_clip_middle_ex(
- const struct uiFontStyle *fstyle, char *str, float okwidth, const float minwidth,
- const size_t max_len, const char rpart_sep);
+float UI_text_clip_middle_ex(const struct uiFontStyle *fstyle,
+ char *str,
+ float okwidth,
+ const float minwidth,
+ const size_t max_len,
+ const char rpart_sep);
/**
* Callbacks
@@ -437,8 +473,13 @@ 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);
+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);
/* Must return allocated string. */
typedef char *(*uiButToolTipFunc)(struct bContext *C, void *argN, const char *tip);
typedef int (*uiButPushedStateFunc)(struct bContext *C, void *arg);
@@ -457,16 +498,13 @@ typedef void (*uiMenuHandleFunc)(struct bContext *C, void *arg, int event);
*/
typedef bool (*uiMenuStepFunc)(struct bContext *C, int direction, void *arg1);
-
/* interface_query.c */
bool UI_but_has_tooltip_label(const uiBut *but);
bool UI_but_is_tool(const uiBut *but);
-#define UI_but_is_decorator(but) \
- ((but)->func == ui_but_anim_decorate_cb)
+#define UI_but_is_decorator(but) ((but)->func == ui_but_anim_decorate_cb)
bool UI_block_is_empty(const uiBlock *block);
-
/* interface_region_menu_popup.c */
/**
* Popup Menus
@@ -478,17 +516,18 @@ bool UI_block_is_empty(const uiBlock *block);
*/
typedef struct uiPopupMenu uiPopupMenu;
-uiPopupMenu *UI_popup_menu_begin(
- struct bContext *C, const char *title, int icon) ATTR_NONNULL();
-uiPopupMenu *UI_popup_menu_begin_ex(
- struct bContext *C, const char *title, const char *block_name,
- int icon) ATTR_NONNULL();
+uiPopupMenu *UI_popup_menu_begin(struct bContext *C, const char *title, int icon) ATTR_NONNULL();
+uiPopupMenu *UI_popup_menu_begin_ex(struct bContext *C,
+ const char *title,
+ const char *block_name,
+ int icon) ATTR_NONNULL();
void UI_popup_menu_end(struct bContext *C, struct uiPopupMenu *head);
bool UI_popup_menu_end_or_cancel(struct bContext *C, struct uiPopupMenu *head);
struct uiLayout *UI_popup_menu_layout(uiPopupMenu *head);
void UI_popup_menu_reports(struct bContext *C, struct ReportList *reports) ATTR_NONNULL();
-int UI_popup_menu_invoke(struct bContext *C, const char *idname, struct ReportList *reports) ATTR_NONNULL(1, 2);
+int UI_popup_menu_invoke(struct bContext *C, const char *idname, struct ReportList *reports)
+ ATTR_NONNULL(1, 2);
void UI_popup_menu_retval_set(const uiBlock *block, const int retval, const bool enable);
void UI_popup_menu_but_set(uiPopupMenu *pup, struct ARegion *butregion, uiBut *but);
@@ -497,9 +536,10 @@ void UI_popup_menu_but_set(uiPopupMenu *pup, struct ARegion *butregion, uiBut *b
typedef struct uiPopover uiPopover;
-int UI_popover_panel_invoke(
- struct bContext *C, const char *idname,
- bool keep_open, struct ReportList *reports);
+int UI_popover_panel_invoke(struct bContext *C,
+ const char *idname,
+ bool keep_open,
+ struct ReportList *reports);
uiPopover *UI_popover_begin(struct bContext *C, int menu_width) ATTR_NONNULL(1);
void UI_popover_end(struct bContext *C, struct uiPopover *head, struct wmKeyMap *keymap);
@@ -511,16 +551,20 @@ void UI_popover_once_clear(uiPopover *pup);
typedef struct uiPieMenu uiPieMenu;
int UI_pie_menu_invoke(struct bContext *C, const char *idname, const struct wmEvent *event);
-int UI_pie_menu_invoke_from_operator_enum(
- struct bContext *C, const char *title, const char *opname,
- const char *propname, const struct wmEvent *event);
-int UI_pie_menu_invoke_from_rna_enum(
- struct bContext *C, const char *title,
- const char *path, const struct wmEvent *event);
-
-struct uiPieMenu *UI_pie_menu_begin(
- struct bContext *C, const char *title, int icon,
- const struct wmEvent *event) ATTR_NONNULL();
+int UI_pie_menu_invoke_from_operator_enum(struct bContext *C,
+ const char *title,
+ const char *opname,
+ const char *propname,
+ const struct wmEvent *event);
+int UI_pie_menu_invoke_from_rna_enum(struct bContext *C,
+ const char *title,
+ const char *path,
+ const struct wmEvent *event);
+
+struct uiPieMenu *UI_pie_menu_begin(struct bContext *C,
+ const char *title,
+ int icon,
+ const struct wmEvent *event) ATTR_NONNULL();
void UI_pie_menu_end(struct bContext *C, uiPieMenu *pie);
struct uiLayout *UI_pie_menu_layout(struct uiPieMenu *pie);
@@ -530,13 +574,19 @@ 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 *ar, void *arg1);
typedef void (*uiBlockCancelFunc)(struct bContext *C, void *arg1);
void UI_popup_block_invoke(struct bContext *C, uiBlockCreateFunc func, void *arg);
-void UI_popup_block_invoke_ex(struct bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext);
-void UI_popup_block_ex(struct bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg, struct wmOperator *op);
-#if 0 /* UNUSED */
+void UI_popup_block_invoke_ex(
+ struct bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext);
+void UI_popup_block_ex(struct bContext *C,
+ uiBlockCreateFunc func,
+ uiBlockHandleFunc popup_func,
+ uiBlockCancelFunc cancel_func,
+ void *arg,
+ struct wmOperator *op);
+#if 0 /* UNUSED */
void uiPupBlockOperator(struct bContext *C, uiBlockCreateFunc func, struct wmOperator *op, int opcontext);
#endif
@@ -555,7 +605,10 @@ bool UI_popup_block_name_exists(struct bContext *C, const char *name);
*
* */
-uiBlock *UI_block_begin(const struct bContext *C, struct ARegion *region, const char *name, short dt);
+uiBlock *UI_block_begin(const struct bContext *C,
+ struct ARegion *region,
+ const char *name,
+ short dt);
void UI_block_end_ex(const struct bContext *C, uiBlock *block, const int xy[2], int r_xy[2]);
void UI_block_end(const struct bContext *C, uiBlock *block);
void UI_block_draw(const struct bContext *C, struct uiBlock *block);
@@ -564,8 +617,8 @@ void UI_blocklist_draw(const struct bContext *C, const struct ListBase *lb);
void UI_block_update_from_old(const struct bContext *C, struct uiBlock *block);
enum {
- UI_BLOCK_THEME_STYLE_REGULAR = 0,
- UI_BLOCK_THEME_STYLE_POPUP = 1,
+ UI_BLOCK_THEME_STYLE_REGULAR = 0,
+ UI_BLOCK_THEME_STYLE_POPUP = 1,
};
void UI_block_theme_style_set(uiBlock *block, char theme_style);
void UI_block_emboss_set(uiBlock *block, char dt);
@@ -586,13 +639,13 @@ void UI_block_align_end(uiBlock *block);
/* block bounds/position calculation */
typedef enum {
- UI_BLOCK_BOUNDS_NONE = 0,
- UI_BLOCK_BOUNDS = 1,
- UI_BLOCK_BOUNDS_TEXT,
- UI_BLOCK_BOUNDS_POPUP_MOUSE,
- UI_BLOCK_BOUNDS_POPUP_MENU,
- UI_BLOCK_BOUNDS_POPUP_CENTER,
- UI_BLOCK_BOUNDS_PIE_CENTER,
+ UI_BLOCK_BOUNDS_NONE = 0,
+ UI_BLOCK_BOUNDS = 1,
+ UI_BLOCK_BOUNDS_TEXT,
+ UI_BLOCK_BOUNDS_POPUP_MOUSE,
+ UI_BLOCK_BOUNDS_POPUP_MENU,
+ UI_BLOCK_BOUNDS_POPUP_CENTER,
+ UI_BLOCK_BOUNDS_PIE_CENTER,
} eBlockBoundsCalc;
void UI_block_bounds_set_normal(struct uiBlock *block, int addval);
@@ -602,50 +655,50 @@ void UI_block_bounds_set_menu(uiBlock *block, int addval, const int bounds_offse
void UI_block_bounds_set_centered(uiBlock *block, int addval);
void UI_block_bounds_set_explicit(uiBlock *block, int minx, int miny, int maxx, int maxy);
-int UI_blocklist_min_y_get(struct ListBase *lb);
+int UI_blocklist_min_y_get(struct ListBase *lb);
-void UI_block_direction_set(uiBlock *block, char direction);
-void UI_block_order_flip(uiBlock *block);
-void UI_block_flag_enable(uiBlock *block, int flag);
-void UI_block_flag_disable(uiBlock *block, int flag);
-void UI_block_translate(uiBlock *block, int x, int y);
+void UI_block_direction_set(uiBlock *block, char direction);
+void UI_block_order_flip(uiBlock *block);
+void UI_block_flag_enable(uiBlock *block, int flag);
+void UI_block_flag_disable(uiBlock *block, int flag);
+void UI_block_translate(uiBlock *block, int x, int y);
-int UI_but_return_value_get(uiBut *but);
+int UI_but_return_value_get(uiBut *but);
-void UI_but_drag_set_id(uiBut *but, struct ID *id);
-void UI_but_drag_set_rna(uiBut *but, struct PointerRNA *ptr);
-void UI_but_drag_set_path(uiBut *but, const char *path, const bool use_free);
-void UI_but_drag_set_name(uiBut *but, const char *name);
-void UI_but_drag_set_value(uiBut *but);
-void UI_but_drag_set_image(
- uiBut *but, const char *path, int icon, struct ImBuf *ima, float scale, const bool use_free);
+void UI_but_drag_set_id(uiBut *but, struct ID *id);
+void UI_but_drag_set_rna(uiBut *but, struct PointerRNA *ptr);
+void UI_but_drag_set_path(uiBut *but, const char *path, const bool use_free);
+void UI_but_drag_set_name(uiBut *but, const char *name);
+void UI_but_drag_set_value(uiBut *but);
+void UI_but_drag_set_image(
+ uiBut *but, const char *path, int icon, struct ImBuf *ima, float scale, const bool use_free);
-bool UI_but_active_drop_name(struct bContext *C);
-bool UI_but_active_drop_color(struct bContext *C);
+bool UI_but_active_drop_name(struct bContext *C);
+bool UI_but_active_drop_color(struct bContext *C);
-void UI_but_flag_enable(uiBut *but, int flag);
-void UI_but_flag_disable(uiBut *but, int flag);
-bool UI_but_flag_is_set(uiBut *but, int flag);
+void UI_but_flag_enable(uiBut *but, int flag);
+void UI_but_flag_disable(uiBut *but, int flag);
+bool UI_but_flag_is_set(uiBut *but, int flag);
-void UI_but_drawflag_enable(uiBut *but, int flag);
-void UI_but_drawflag_disable(uiBut *but, int flag);
+void UI_but_drawflag_enable(uiBut *but, int flag);
+void UI_but_drawflag_disable(uiBut *but, int flag);
-void UI_but_type_set_menu_from_pulldown(uiBut *but);
+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_block_active_only_flagged_buttons(const struct bContext *C, struct ARegion *ar, struct uiBlock *block);
+bool UI_but_active_only(const struct bContext *C, struct ARegion *ar, uiBlock *block, uiBut *but);
+bool UI_block_active_only_flagged_buttons(const struct bContext *C,
+ struct ARegion *ar,
+ struct uiBlock *block);
-void UI_but_execute(const struct bContext *C, uiBut *but);
+void UI_but_execute(const struct bContext *C, uiBut *but);
-bool UI_but_online_manual_id(
- const uiBut *but,
- char *r_str, size_t maxlength)
- ATTR_WARN_UNUSED_RESULT;
-bool UI_but_online_manual_id_from_active(
- const struct bContext *C,
- char *r_str, size_t maxlength)
- ATTR_WARN_UNUSED_RESULT;
+bool UI_but_online_manual_id(const uiBut *but,
+ char *r_str,
+ size_t maxlength) ATTR_WARN_UNUSED_RESULT;
+bool UI_but_online_manual_id_from_active(const struct bContext *C,
+ char *r_str,
+ size_t maxlength) ATTR_WARN_UNUSED_RESULT;
/* Buttons
*
@@ -657,68 +710,567 @@ bool UI_but_online_manual_id_from_active(
* - R: RNA
* - O: operator */
-uiBut *uiDefBut(
- uiBlock *block,
- int type, int retval, const char *str,
- int x1, int y1,
- short x2, short y2,
- void *poin,
- float min, float max,
- float a1, float a2, const char *tip);
-uiBut *uiDefButF(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefButBitF(uiBlock *block, int type, int bit, int retval, const char *str, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefButI(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefButBitI(uiBlock *block, int type, int bit, int retval, const char *str, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefButS(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefButBitS(uiBlock *block, int type, int bit, int retval, const char *str, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefButC(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefButBitC(uiBlock *block, int type, int bit, int retval, const char *str, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefButR(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, struct PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefButR_prop(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefButO(uiBlock *block, int type, const char *opname, int opcontext, const char *str, int x, int y, short width, short height, const char *tip);
-uiBut *uiDefButO_ptr(uiBlock *block, int type, struct wmOperatorType *ot, int opcontext, const char *str, int x, int y, short width, short height, const char *tip);
-
-uiBut *uiDefIconBut(
- uiBlock *block,
- int type, int retval, int icon,
- int x1, int y1,
- short x2, short y2,
- void *poin,
- float min, float max,
- float a1, float a2, const char *tip);
-uiBut *uiDefIconButF(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconButBitF(uiBlock *block, int type, int bit, int retval, int icon, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconButI(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconButBitI(uiBlock *block, int type, int bit, int retval, int icon, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconButS(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconButBitS(uiBlock *block, int type, int bit, int retval, int icon, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconButC(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconButBitC(uiBlock *block, int type, int bit, int retval, int icon, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconButR(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, struct PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconButR_prop(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, struct PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, int x, int y, short width, short height, const char *tip);
-uiBut *uiDefIconButO_ptr(uiBlock *block, int type, struct wmOperatorType *ot, int opcontext, int icon, int x, int y, short width, short height, const char *tip);
-
-uiBut *uiDefIconTextBut(
- uiBlock *block,
- int type, int retval, int icon, const char *str,
- int x1, int y1,
- short x2, short y2,
- void *poin,
- float min, float max,
- float a1, float a2, const char *tip);
-uiBut *uiDefIconTextButF(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconTextButBitF(uiBlock *block, int type, int bit, int retval, int icon, const char *str, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconTextButI(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconTextButBitI(uiBlock *block, int type, int bit, int retval, int icon, const char *str, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconTextButS(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconTextButBitS(uiBlock *block, int type, int bit, int retval, int icon, const char *str, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconTextButC(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconTextButBitC(uiBlock *block, int type, int bit, int retval, int icon, const char *str, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconTextButR(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, struct PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconTextButR_prop(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip);
-uiBut *uiDefIconTextButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, const char *str, int x, int y, short width, short height, const char *tip);
-uiBut *uiDefIconTextButO_ptr(uiBlock *block, int type, struct wmOperatorType *ot, int opcontext, int icon, const char *str, int x, int y, short width, short height, const char *tip);
+uiBut *uiDefBut(uiBlock *block,
+ int type,
+ int retval,
+ const char *str,
+ int x1,
+ int y1,
+ short x2,
+ short y2,
+ void *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefButF(uiBlock *block,
+ int type,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ float *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefButBitF(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ float *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefButI(uiBlock *block,
+ int type,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ int *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefButBitI(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ int *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefButS(uiBlock *block,
+ int type,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ short *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefButBitS(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ short *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefButC(uiBlock *block,
+ int type,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ char *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefButBitC(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ char *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefButR(uiBlock *block,
+ int type,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ struct PointerRNA *ptr,
+ const char *propname,
+ int index,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefButR_prop(uiBlock *block,
+ int type,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ struct PointerRNA *ptr,
+ struct PropertyRNA *prop,
+ int index,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefButO(uiBlock *block,
+ int type,
+ const char *opname,
+ int opcontext,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip);
+uiBut *uiDefButO_ptr(uiBlock *block,
+ int type,
+ struct wmOperatorType *ot,
+ int opcontext,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip);
+
+uiBut *uiDefIconBut(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ int x1,
+ int y1,
+ short x2,
+ short y2,
+ void *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconButF(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ float *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconButBitF(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ float *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconButI(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ int *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconButBitI(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ int *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconButS(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ short *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconButBitS(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ short *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconButC(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ char *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconButBitC(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ char *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconButR(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ struct PointerRNA *ptr,
+ const char *propname,
+ int index,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconButR_prop(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ struct PointerRNA *ptr,
+ PropertyRNA *prop,
+ int index,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconButO(uiBlock *block,
+ int type,
+ const char *opname,
+ int opcontext,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip);
+uiBut *uiDefIconButO_ptr(uiBlock *block,
+ int type,
+ struct wmOperatorType *ot,
+ int opcontext,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip);
+
+uiBut *uiDefIconTextBut(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ const char *str,
+ int x1,
+ int y1,
+ short x2,
+ short y2,
+ void *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconTextButF(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ float *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconTextButBitF(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ float *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconTextButI(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ int *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconTextButBitI(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ int *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconTextButS(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ short *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconTextButBitS(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ short *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconTextButC(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ char *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconTextButBitC(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ char *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconTextButR(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ struct PointerRNA *ptr,
+ const char *propname,
+ int index,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconTextButR_prop(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ struct PointerRNA *ptr,
+ struct PropertyRNA *prop,
+ int index,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefIconTextButO(uiBlock *block,
+ int type,
+ const char *opname,
+ int opcontext,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip);
+uiBut *uiDefIconTextButO_ptr(uiBlock *block,
+ int type,
+ struct wmOperatorType *ot,
+ int opcontext,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip);
/* for passing inputs to ButO buttons */
struct PointerRNA *UI_but_operator_ptr_get(uiBut *but);
@@ -727,23 +1279,23 @@ void UI_but_unit_type_set(uiBut *but, const int unit_type);
int UI_but_unit_type_get(const uiBut *but);
enum {
- BUT_GET_RNAPROP_IDENTIFIER = 1,
- BUT_GET_RNASTRUCT_IDENTIFIER,
- BUT_GET_RNAENUM_IDENTIFIER,
- BUT_GET_LABEL,
- BUT_GET_RNA_LABEL,
- BUT_GET_RNAENUM_LABEL,
- BUT_GET_RNA_LABEL_CONTEXT, /* Context specified in CTX_XXX_ macros are just unreachable! */
- BUT_GET_TIP,
- BUT_GET_RNA_TIP,
- BUT_GET_RNAENUM_TIP,
- BUT_GET_OP_KEYMAP,
- BUT_GET_PROP_KEYMAP,
+ BUT_GET_RNAPROP_IDENTIFIER = 1,
+ BUT_GET_RNASTRUCT_IDENTIFIER,
+ BUT_GET_RNAENUM_IDENTIFIER,
+ BUT_GET_LABEL,
+ BUT_GET_RNA_LABEL,
+ BUT_GET_RNAENUM_LABEL,
+ BUT_GET_RNA_LABEL_CONTEXT, /* Context specified in CTX_XXX_ macros are just unreachable! */
+ BUT_GET_TIP,
+ BUT_GET_RNA_TIP,
+ BUT_GET_RNAENUM_TIP,
+ BUT_GET_OP_KEYMAP,
+ BUT_GET_PROP_KEYMAP,
};
typedef struct uiStringInfo {
- int type;
- char *strinfo;
+ int type;
+ char *strinfo;
} uiStringInfo;
/* Note: Expects pointers to uiStringInfo structs as parameters.
@@ -767,19 +1319,20 @@ void UI_but_string_info_get(struct bContext *C, uiBut *but, ...) ATTR_SENTINEL(0
* - AutoButR: RNA property button with type automatically defined.
*/
enum {
- UI_ID_RENAME = 1 << 0,
- UI_ID_BROWSE = 1 << 1,
- UI_ID_ADD_NEW = 1 << 2,
- UI_ID_ALONE = 1 << 4,
- UI_ID_OPEN = 1 << 3,
- UI_ID_DELETE = 1 << 5,
- UI_ID_LOCAL = 1 << 6,
- UI_ID_AUTO_NAME = 1 << 7,
- UI_ID_FAKE_USER = 1 << 8,
- UI_ID_PIN = 1 << 9,
- UI_ID_PREVIEWS = 1 << 10,
- UI_ID_OVERRIDE = 1 << 11,
- UI_ID_FULL = UI_ID_RENAME | UI_ID_BROWSE | UI_ID_ADD_NEW | UI_ID_OPEN | UI_ID_ALONE | UI_ID_DELETE | UI_ID_LOCAL,
+ UI_ID_RENAME = 1 << 0,
+ UI_ID_BROWSE = 1 << 1,
+ UI_ID_ADD_NEW = 1 << 2,
+ UI_ID_ALONE = 1 << 4,
+ UI_ID_OPEN = 1 << 3,
+ UI_ID_DELETE = 1 << 5,
+ UI_ID_LOCAL = 1 << 6,
+ UI_ID_AUTO_NAME = 1 << 7,
+ UI_ID_FAKE_USER = 1 << 8,
+ UI_ID_PIN = 1 << 9,
+ UI_ID_PREVIEWS = 1 << 10,
+ UI_ID_OVERRIDE = 1 << 11,
+ UI_ID_FULL = UI_ID_RENAME | UI_ID_BROWSE | UI_ID_ADD_NEW | UI_ID_OPEN | UI_ID_ALONE |
+ UI_ID_DELETE | UI_ID_LOCAL,
};
/**
@@ -787,8 +1340,8 @@ enum {
* \note We may want to add LOCAL, LIBRARY ... as needed.
*/
enum {
- UI_TEMPLATE_ID_FILTER_ALL = 0,
- UI_TEMPLATE_ID_FILTER_AVAILABLE = 1,
+ UI_TEMPLATE_ID_FILTER_ALL = 0,
+ UI_TEMPLATE_ID_FILTER_AVAILABLE = 1,
};
int UI_icon_from_id(struct ID *id);
@@ -797,89 +1350,212 @@ int UI_icon_from_report_type(int type);
int UI_icon_from_event_type(short event_type, short event_value);
int UI_icon_from_keymap_item(const struct wmKeyMapItem *kmi, int r_icon_mod[4]);
-uiBut *uiDefPulldownBut(uiBlock *block, uiBlockCreateFunc func, void *arg, const char *str, int x, int y, short width, short height, const char *tip);
-uiBut *uiDefMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, const char *str, int x, int y, short width, short height, const char *tip);
-uiBut *uiDefIconTextMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int icon, const char *str, int x, int y, short width, short height, const char *tip);
-uiBut *uiDefIconMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int icon, int x, int y, short width, short height, const char *tip);
-
-uiBut *uiDefBlockBut(uiBlock *block, uiBlockCreateFunc func, void *func_arg1, const char *str, int x, int y, short width, short height, const char *tip);
-uiBut *uiDefBlockButN(uiBlock *block, uiBlockCreateFunc func, void *argN, const char *str, int x, int y, short width, short height, const char *tip);
-
-uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int retval, int icon, int x, int y, short width, short height, const char *tip);
-uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int icon, const char *str, int x, int y, short width, short height, const char *tip);
-
-uiBut *uiDefKeyevtButS(uiBlock *block, int retval, const char *str, int x, int y, short width, short height, short *spoin, const char *tip);
-uiBut *uiDefHotKeyevtButS(uiBlock *block, int retval, const char *str, int x, int y, short width, short height, short *keypoin, short *modkeypoin, const char *tip);
-
-uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxlen, int x, int y, short width, short height, float a1, float a2, const char *tip);
-uiBut *uiDefSearchButO_ptr(
- uiBlock *block, struct wmOperatorType *ot, struct IDProperty *properties,
- void *arg, int retval, int icon, int maxlen, int x, int y,
- short width, short height, float a1, float a2, const char *tip);
-
+uiBut *uiDefPulldownBut(uiBlock *block,
+ uiBlockCreateFunc func,
+ void *arg,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip);
+uiBut *uiDefMenuBut(uiBlock *block,
+ uiMenuCreateFunc func,
+ void *arg,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip);
+uiBut *uiDefIconTextMenuBut(uiBlock *block,
+ uiMenuCreateFunc func,
+ void *arg,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip);
+uiBut *uiDefIconMenuBut(uiBlock *block,
+ uiMenuCreateFunc func,
+ void *arg,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip);
+
+uiBut *uiDefBlockBut(uiBlock *block,
+ uiBlockCreateFunc func,
+ void *func_arg1,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip);
+uiBut *uiDefBlockButN(uiBlock *block,
+ uiBlockCreateFunc func,
+ void *argN,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip);
+
+uiBut *uiDefIconBlockBut(uiBlock *block,
+ uiBlockCreateFunc func,
+ void *arg,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip);
+uiBut *uiDefIconTextBlockBut(uiBlock *block,
+ uiBlockCreateFunc func,
+ void *arg,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip);
+
+uiBut *uiDefKeyevtButS(uiBlock *block,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ short *spoin,
+ const char *tip);
+uiBut *uiDefHotKeyevtButS(uiBlock *block,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ short *keypoin,
+ short *modkeypoin,
+ const char *tip);
+
+uiBut *uiDefSearchBut(uiBlock *block,
+ void *arg,
+ int retval,
+ int icon,
+ int maxlen,
+ int x,
+ int y,
+ short width,
+ short height,
+ float a1,
+ float a2,
+ const char *tip);
+uiBut *uiDefSearchButO_ptr(uiBlock *block,
+ struct wmOperatorType *ot,
+ struct IDProperty *properties,
+ void *arg,
+ int retval,
+ int icon,
+ int maxlen,
+ int x,
+ int y,
+ short width,
+ short height,
+ float a1,
+ float a2,
+ const char *tip);
/* For uiDefAutoButsRNA */
typedef enum {
- /* Keep current layout for aligning label with property button. */
- UI_BUT_LABEL_ALIGN_NONE,
- /* Align label and property button vertically. */
- UI_BUT_LABEL_ALIGN_COLUMN,
- /* Split layout into a column for the label and one for property button. */
- UI_BUT_LABEL_ALIGN_SPLIT_COLUMN,
+ /* Keep current layout for aligning label with property button. */
+ UI_BUT_LABEL_ALIGN_NONE,
+ /* Align label and property button vertically. */
+ UI_BUT_LABEL_ALIGN_COLUMN,
+ /* Split layout into a column for the label and one for property button. */
+ UI_BUT_LABEL_ALIGN_SPLIT_COLUMN,
} eButLabelAlign;
/* Return info for uiDefAutoButsRNA */
typedef enum {
- /* Returns when no buttons were added */
- UI_PROP_BUTS_NONE_ADDED = 1 << 0,
- /* Returned when any property failed the custom check callback (check_prop) */
- UI_PROP_BUTS_ANY_FAILED_CHECK = 1 << 1,
+ /* Returns when no buttons were added */
+ UI_PROP_BUTS_NONE_ADDED = 1 << 0,
+ /* Returned when any property failed the custom check callback (check_prop) */
+ UI_PROP_BUTS_ANY_FAILED_CHECK = 1 << 1,
} eAutoPropButsReturn;
-uiBut *uiDefAutoButR(uiBlock *block, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, const char *name, int icon, int x1, int y1, int x2, int y2);
-eAutoPropButsReturn uiDefAutoButsRNA(
- uiLayout *layout, struct PointerRNA *ptr,
- bool (*check_prop)(struct PointerRNA *ptr, struct PropertyRNA *prop, void *user_data), void *user_data,
- struct PropertyRNA *prop_activate_init,
- eButLabelAlign label_align, const bool compact);
+uiBut *uiDefAutoButR(uiBlock *block,
+ struct PointerRNA *ptr,
+ struct PropertyRNA *prop,
+ int index,
+ const char *name,
+ int icon,
+ int x1,
+ int y1,
+ int x2,
+ int y2);
+eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout,
+ struct PointerRNA *ptr,
+ bool (*check_prop)(struct PointerRNA *ptr,
+ struct PropertyRNA *prop,
+ void *user_data),
+ void *user_data,
+ struct PropertyRNA *prop_activate_init,
+ eButLabelAlign label_align,
+ const bool compact);
/* use inside searchfunc to add items */
-bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int iconid);
+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 */
-void UI_but_func_search_set(
- uiBut *but, uiButSearchCreateFunc cfunc, uiButSearchFunc sfunc,
- void *arg, bool free_arg, uiButHandleFunc bfunc, void *active);
+void UI_but_func_search_set(uiBut *but,
+ uiButSearchCreateFunc cfunc,
+ uiButSearchFunc sfunc,
+ void *arg,
+ bool free_arg,
+ uiButHandleFunc bfunc,
+ void *active);
/* height in pixels, it's using hardcoded values still */
-int UI_searchbox_size_y(void);
-int UI_searchbox_size_x(void);
+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);
+int UI_search_items_find_index(uiSearchItems *items, const char *name);
-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);
-void UI_block_funcN_set(uiBlock *block, uiButHandleNFunc funcN, void *argN, void *arg2);
+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);
+void UI_block_funcN_set(uiBlock *block, uiButHandleNFunc funcN, void *argN, void *arg2);
-void UI_but_func_rename_set(uiBut *but, uiButHandleRenameFunc func, void *arg1);
-void UI_but_func_set(uiBut *but, uiButHandleFunc func, void *arg1, void *arg2);
-void UI_but_funcN_set(uiBut *but, uiButHandleNFunc funcN, void *argN, void *arg2);
+void UI_but_func_rename_set(uiBut *but, uiButHandleRenameFunc func, void *arg1);
+void UI_but_func_set(uiBut *but, uiButHandleFunc func, void *arg1, void *arg2);
+void UI_but_funcN_set(uiBut *but, uiButHandleNFunc funcN, void *argN, void *arg2);
-void UI_but_func_complete_set(uiBut *but, uiButCompleteFunc func, void *arg);
+void UI_but_func_complete_set(uiBut *but, uiButCompleteFunc func, void *arg);
-void UI_but_func_drawextra_set(
- uiBlock *block,
- void (*func)(const struct bContext *C, void *, void *, void *, struct rcti *rect),
- void *arg1, void *arg2);
+void UI_but_func_drawextra_set(
+ uiBlock *block,
+ void (*func)(const struct bContext *C, void *, void *, void *, struct rcti *rect),
+ void *arg1,
+ void *arg2);
-void UI_but_func_menu_step_set(uiBut *but, uiMenuStepFunc func);
+void UI_but_func_menu_step_set(uiBut *but, uiMenuStepFunc func);
-void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *argN);
-void UI_but_tooltip_refresh(struct bContext *C, uiBut *but);
-void UI_but_tooltip_timer_remove(struct bContext *C, uiBut *but);
+void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *argN);
+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,
- const void *rna_poin_data, const char *rna_prop_id);
+bool UI_textbutton_activate_rna(const struct bContext *C,
+ struct ARegion *ar,
+ const void *rna_poin_data,
+ const char *rna_prop_id);
bool UI_textbutton_activate_but(const struct bContext *C, uiBut *but);
void UI_but_focus_on_enter_event(struct wmWindow *win, uiBut *but);
@@ -915,25 +1591,31 @@ void UI_panels_end(const struct bContext *C, struct ARegion *ar, int *r_x, int *
void UI_panels_draw(const struct bContext *C, struct ARegion *ar);
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 ListBase *lb,
- uiBlock *block, struct PanelType *pt, struct Panel *pa,
- bool *r_open);
+struct Panel *UI_panel_begin(struct ScrArea *sa,
+ struct ARegion *ar,
+ struct ListBase *lb,
+ uiBlock *block,
+ struct PanelType *pt,
+ struct Panel *pa,
+ bool *r_open);
void UI_panel_end(uiBlock *block, int width, int height);
void UI_panels_scale(struct ARegion *ar, float new_width);
void UI_panel_label_offset(struct uiBlock *block, int *r_x, int *r_y);
int UI_panel_size_y(const struct Panel *pa);
-bool UI_panel_category_is_visible(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);
+bool UI_panel_category_is_visible(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);
-struct PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(struct ARegion *ar, const int x, const int y);
-struct PanelCategoryDyn *UI_panel_category_find_mouse_over(struct ARegion *ar, 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);
+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);
+struct PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(struct ARegion *ar,
+ const int x,
+ const int y);
+struct PanelCategoryDyn *UI_panel_category_find_mouse_over(struct ARegion *ar,
+ 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);
struct PanelType *UI_paneltype_find(int space_id, int region_id, const char *idname);
@@ -944,7 +1626,10 @@ struct PanelType *UI_paneltype_find(int space_id, int region_id, const char *idn
* as screen/ if ED_KEYMAP_UI is set, or internally in popup functions. */
void UI_region_handlers_add(struct ListBase *handlers);
-void UI_popup_handlers_add(struct bContext *C, struct ListBase *handlers, uiPopupBlockHandle *popup, const char flag);
+void UI_popup_handlers_add(struct bContext *C,
+ struct ListBase *handlers,
+ uiPopupBlockHandle *popup,
+ const char flag);
void UI_popup_handlers_remove(struct ListBase *handlers, uiPopupBlockHandle *popup);
void UI_popup_handlers_remove_all(struct bContext *C, struct ListBase *handlers);
@@ -970,51 +1655,51 @@ void UI_exit(void);
/* layout */
enum {
- UI_LAYOUT_HORIZONTAL = 0,
- UI_LAYOUT_VERTICAL = 1,
+ UI_LAYOUT_HORIZONTAL = 0,
+ UI_LAYOUT_VERTICAL = 1,
};
enum {
- UI_LAYOUT_PANEL = 0,
- UI_LAYOUT_HEADER = 1,
- UI_LAYOUT_MENU = 2,
- UI_LAYOUT_TOOLBAR = 3,
- UI_LAYOUT_PIEMENU = 4,
- UI_LAYOUT_VERT_BAR = 5,
+ UI_LAYOUT_PANEL = 0,
+ UI_LAYOUT_HEADER = 1,
+ UI_LAYOUT_MENU = 2,
+ UI_LAYOUT_TOOLBAR = 3,
+ UI_LAYOUT_PIEMENU = 4,
+ UI_LAYOUT_VERT_BAR = 5,
};
-#define UI_UNIT_X ((void)0, U.widget_unit)
-#define UI_UNIT_Y ((void)0, U.widget_unit)
+#define UI_UNIT_X ((void)0, U.widget_unit)
+#define UI_UNIT_Y ((void)0, U.widget_unit)
enum {
- UI_LAYOUT_ALIGN_EXPAND = 0,
- UI_LAYOUT_ALIGN_LEFT = 1,
- UI_LAYOUT_ALIGN_CENTER = 2,
- UI_LAYOUT_ALIGN_RIGHT = 3,
+ UI_LAYOUT_ALIGN_EXPAND = 0,
+ UI_LAYOUT_ALIGN_LEFT = 1,
+ UI_LAYOUT_ALIGN_CENTER = 2,
+ UI_LAYOUT_ALIGN_RIGHT = 3,
};
enum {
- UI_ITEM_O_RETURN_PROPS = 1 << 0,
- UI_ITEM_R_EXPAND = 1 << 1,
- UI_ITEM_R_SLIDER = 1 << 2,
- UI_ITEM_R_TOGGLE = 1 << 3,
- UI_ITEM_R_ICON_ONLY = 1 << 4,
- UI_ITEM_R_EVENT = 1 << 5,
- UI_ITEM_R_FULL_EVENT = 1 << 6,
- UI_ITEM_R_NO_BG = 1 << 7,
- UI_ITEM_R_IMMEDIATE = 1 << 8,
- UI_ITEM_O_DEPRESS = 1 << 9,
- UI_ITEM_R_COMPACT = 1 << 10,
+ UI_ITEM_O_RETURN_PROPS = 1 << 0,
+ UI_ITEM_R_EXPAND = 1 << 1,
+ UI_ITEM_R_SLIDER = 1 << 2,
+ UI_ITEM_R_TOGGLE = 1 << 3,
+ UI_ITEM_R_ICON_ONLY = 1 << 4,
+ UI_ITEM_R_EVENT = 1 << 5,
+ UI_ITEM_R_FULL_EVENT = 1 << 6,
+ UI_ITEM_R_NO_BG = 1 << 7,
+ UI_ITEM_R_IMMEDIATE = 1 << 8,
+ UI_ITEM_O_DEPRESS = 1 << 9,
+ UI_ITEM_R_COMPACT = 1 << 10,
};
#define UI_HEADER_OFFSET ((void)0, 0.4f * UI_UNIT_X)
/* uiLayoutOperatorButs flags */
enum {
- UI_TEMPLATE_OP_PROPS_SHOW_TITLE = 1 << 0,
- UI_TEMPLATE_OP_PROPS_SHOW_EMPTY = 1 << 1,
- UI_TEMPLATE_OP_PROPS_COMPACT = 1 << 2,
- UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED = 1 << 3,
+ UI_TEMPLATE_OP_PROPS_SHOW_TITLE = 1 << 0,
+ UI_TEMPLATE_OP_PROPS_SHOW_EMPTY = 1 << 1,
+ UI_TEMPLATE_OP_PROPS_COMPACT = 1 << 2,
+ UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED = 1 << 3,
};
/* used for transp checkers */
@@ -1028,16 +1713,24 @@ enum {
* 8------4 */
enum {
- UI_CNR_TOP_LEFT = 1 << 0,
- UI_CNR_TOP_RIGHT = 1 << 1,
- UI_CNR_BOTTOM_RIGHT = 1 << 2,
- UI_CNR_BOTTOM_LEFT = 1 << 3,
- /* just for convenience */
- UI_CNR_NONE = 0,
- UI_CNR_ALL = (UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT),
+ UI_CNR_TOP_LEFT = 1 << 0,
+ UI_CNR_TOP_RIGHT = 1 << 1,
+ UI_CNR_BOTTOM_RIGHT = 1 << 2,
+ UI_CNR_BOTTOM_LEFT = 1 << 3,
+ /* just for convenience */
+ UI_CNR_NONE = 0,
+ UI_CNR_ALL = (UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT),
};
-uiLayout *UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, struct uiStyle *style);
+uiLayout *UI_block_layout(uiBlock *block,
+ int dir,
+ int type,
+ int x,
+ int y,
+ int size,
+ int em,
+ int padding,
+ 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);
@@ -1094,12 +1787,19 @@ bool uiLayoutGetPropDecorate(uiLayout *layout);
uiLayout *uiLayoutRow(uiLayout *layout, bool align);
uiLayout *uiLayoutColumn(uiLayout *layout, bool align);
uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, bool align);
-uiLayout *uiLayoutGridFlow(
- uiLayout *layout, bool row_major, int columns_len, bool even_columns, bool even_rows, bool align);
+uiLayout *uiLayoutGridFlow(uiLayout *layout,
+ bool row_major,
+ int columns_len,
+ bool even_columns,
+ bool even_rows,
+ bool align);
uiLayout *uiLayoutBox(uiLayout *layout);
-uiLayout *uiLayoutListBox(
- uiLayout *layout, struct uiList *ui_list, struct PointerRNA *ptr, struct PropertyRNA *prop,
- struct PointerRNA *actptr, struct PropertyRNA *actprop);
+uiLayout *uiLayoutListBox(uiLayout *layout,
+ struct uiList *ui_list,
+ struct PointerRNA *ptr,
+ struct PropertyRNA *prop,
+ struct PointerRNA *actptr,
+ struct PropertyRNA *actprop);
uiLayout *uiLayoutAbsolute(uiLayout *layout, bool align);
uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, bool align);
uiLayout *uiLayoutOverlap(uiLayout *layout);
@@ -1108,169 +1808,397 @@ uiLayout *uiLayoutRadial(uiLayout *layout);
/* templates */
void uiTemplateHeader(uiLayout *layout, struct bContext *C);
-void uiTemplateID(
- uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname,
- const char *newop, const char *openop, const char *unlinkop,
- int filter, const bool live_icon);
-void uiTemplateIDBrowse(
- uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname,
- const char *newop, const char *openop, const char *unlinkop, int filter);
-void uiTemplateIDPreview(
- uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname,
- const char *newop, const char *openop, const char *unlinkop, int rows, int cols,
- int filter, const bool hide_buttons);
-void uiTemplateIDTabs(
- uiLayout *layout, struct bContext *C,
- PointerRNA *ptr, const char *propname,
- const char *newop, const char *menu,
- int filter);
-void uiTemplateAnyID(
- uiLayout *layout, struct PointerRNA *ptr, const char *propname,
- const char *proptypename, const char *text);
-void uiTemplateSearch(
- uiLayout *layout, struct bContext *C,
- struct PointerRNA *ptr, const char *propname,
- struct PointerRNA *searchptr, const char *searchpropname,
- const char *newop, const char *unlinkop);
-void uiTemplateSearchPreview(
- uiLayout *layout, struct bContext *C,
- struct PointerRNA *ptr, const char *propname,
- struct PointerRNA *searchptr, const char *searchpropname,
- const char *newop, const char *unlinkop,
- const int rows, const int cols);
-void uiTemplatePathBuilder(
- uiLayout *layout, struct PointerRNA *ptr, const char *propname,
- struct PointerRNA *root_ptr, const char *text);
+void uiTemplateID(uiLayout *layout,
+ struct bContext *C,
+ struct PointerRNA *ptr,
+ const char *propname,
+ const char *newop,
+ const char *openop,
+ const char *unlinkop,
+ int filter,
+ const bool live_icon);
+void uiTemplateIDBrowse(uiLayout *layout,
+ struct bContext *C,
+ struct PointerRNA *ptr,
+ const char *propname,
+ const char *newop,
+ const char *openop,
+ const char *unlinkop,
+ int filter);
+void uiTemplateIDPreview(uiLayout *layout,
+ struct bContext *C,
+ struct PointerRNA *ptr,
+ const char *propname,
+ const char *newop,
+ const char *openop,
+ const char *unlinkop,
+ int rows,
+ int cols,
+ int filter,
+ const bool hide_buttons);
+void uiTemplateIDTabs(uiLayout *layout,
+ struct bContext *C,
+ PointerRNA *ptr,
+ const char *propname,
+ const char *newop,
+ const char *menu,
+ int filter);
+void uiTemplateAnyID(uiLayout *layout,
+ struct PointerRNA *ptr,
+ const char *propname,
+ const char *proptypename,
+ const char *text);
+void uiTemplateSearch(uiLayout *layout,
+ struct bContext *C,
+ struct PointerRNA *ptr,
+ const char *propname,
+ struct PointerRNA *searchptr,
+ const char *searchpropname,
+ const char *newop,
+ const char *unlinkop);
+void uiTemplateSearchPreview(uiLayout *layout,
+ struct bContext *C,
+ struct PointerRNA *ptr,
+ const char *propname,
+ struct PointerRNA *searchptr,
+ const char *searchpropname,
+ const char *newop,
+ const char *unlinkop,
+ const int rows,
+ const int cols);
+void uiTemplatePathBuilder(uiLayout *layout,
+ struct PointerRNA *ptr,
+ const char *propname,
+ struct PointerRNA *root_ptr,
+ const char *text);
uiLayout *uiTemplateModifier(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr);
uiLayout *uiTemplateGpencilModifier(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr);
-void uiTemplateGpencilColorPreview(
- uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname,
- int rows, int cols, float scale, int filter);
+void uiTemplateGpencilColorPreview(uiLayout *layout,
+ struct bContext *C,
+ struct PointerRNA *ptr,
+ const char *propname,
+ int rows,
+ int cols,
+ float scale,
+ int filter);
uiLayout *uiTemplateShaderFx(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr);
void uiTemplateOperatorRedoProperties(uiLayout *layout, const struct bContext *C);
uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr);
-void uiTemplatePreview(
- uiLayout *layout, struct bContext *C, struct ID *id, bool show_buttons, struct ID *parent,
- struct MTex *slot, const char *preview_id);
-void uiTemplateColorRamp(uiLayout *layout, struct PointerRNA *ptr, const char *propname, bool expand);
+void uiTemplatePreview(uiLayout *layout,
+ struct bContext *C,
+ struct ID *id,
+ bool show_buttons,
+ struct ID *parent,
+ struct MTex *slot,
+ const char *preview_id);
+void uiTemplateColorRamp(uiLayout *layout,
+ struct PointerRNA *ptr,
+ const char *propname,
+ bool expand);
void uiTemplateIcon(uiLayout *layout, int icon_value, float icon_scale);
-void uiTemplateIconView(
- uiLayout *layout, struct PointerRNA *ptr, const char *propname, bool show_labels,
- float icon_scale, float icon_scale_popup);
+void uiTemplateIconView(uiLayout *layout,
+ struct PointerRNA *ptr,
+ const char *propname,
+ bool show_labels,
+ float icon_scale,
+ float icon_scale_popup);
void uiTemplateHistogram(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
void uiTemplateWaveform(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
void uiTemplateVectorscope(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
-void uiTemplateCurveMapping(
- uiLayout *layout, struct PointerRNA *ptr, const char *propname, int type,
- bool levels, bool brush, bool neg_slope, bool tone);
-void uiTemplateColorPicker(uiLayout *layout, struct PointerRNA *ptr, const char *propname, bool value_slider, bool lock, bool lock_luminosity, bool cubic);
+void uiTemplateCurveMapping(uiLayout *layout,
+ struct PointerRNA *ptr,
+ const char *propname,
+ int type,
+ bool levels,
+ bool brush,
+ bool neg_slope,
+ bool tone);
+void uiTemplateColorPicker(uiLayout *layout,
+ struct PointerRNA *ptr,
+ const char *propname,
+ bool value_slider,
+ bool lock,
+ bool lock_luminosity,
+ bool cubic);
void uiTemplatePalette(uiLayout *layout, struct PointerRNA *ptr, const char *propname, bool color);
void uiTemplateCryptoPicker(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
-void uiTemplateLayers(
- uiLayout *layout, struct PointerRNA *ptr, const char *propname,
- PointerRNA *used_ptr, const char *used_propname, int active_layer);
-void uiTemplateImage(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, struct PointerRNA *userptr, bool compact, bool multiview);
+void uiTemplateLayers(uiLayout *layout,
+ struct PointerRNA *ptr,
+ const char *propname,
+ PointerRNA *used_ptr,
+ const char *used_propname,
+ int active_layer);
+void uiTemplateImage(uiLayout *layout,
+ struct bContext *C,
+ struct PointerRNA *ptr,
+ const char *propname,
+ struct PointerRNA *userptr,
+ bool compact,
+ bool multiview);
void uiTemplateImageSettings(uiLayout *layout, struct PointerRNA *imfptr, bool color_management);
void uiTemplateImageStereo3d(uiLayout *layout, struct PointerRNA *stereo3d_format_ptr);
void uiTemplateImageViews(uiLayout *layout, struct PointerRNA *imaptr);
void uiTemplateImageFormatViews(uiLayout *layout, PointerRNA *imfptr, PointerRNA *ptr);
-void uiTemplateImageLayers(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser);
-void uiTemplateImageInfo(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser);
+void uiTemplateImageLayers(uiLayout *layout,
+ struct bContext *C,
+ struct Image *ima,
+ struct ImageUser *iuser);
+void uiTemplateImageInfo(uiLayout *layout,
+ struct bContext *C,
+ struct Image *ima,
+ struct ImageUser *iuser);
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);
+eAutoPropButsReturn uiTemplateOperatorPropertyButs(const struct bContext *C,
+ uiLayout *layout,
+ struct wmOperator *op,
+ const eButLabelAlign label_align,
+ const 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);
void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr);
-void uiTemplateComponentMenu(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name);
+void uiTemplateComponentMenu(uiLayout *layout,
+ struct PointerRNA *ptr,
+ const char *propname,
+ const char *name);
void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color);
-void uiTemplateCacheFile(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname);
+void uiTemplateCacheFile(uiLayout *layout,
+ struct bContext *C,
+ 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, struct bContext *C, const char *listtype_name, const char *list_id,
- struct PointerRNA *dataptr, const char *propname, struct PointerRNA *active_dataptr,
- const char *active_propname, const char *item_dyntip_propname,
- int rows, int maxrows, int layout_type, int columns, bool sort_reverse, bool sort_lock);
-void uiTemplateNodeLink(uiLayout *layout, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input);
-void uiTemplateNodeView(uiLayout *layout, struct bContext *C, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input);
+void uiTemplateList(uiLayout *layout,
+ struct bContext *C,
+ const char *listtype_name,
+ const char *list_id,
+ struct PointerRNA *dataptr,
+ const char *propname,
+ struct PointerRNA *active_dataptr,
+ const char *active_propname,
+ const char *item_dyntip_propname,
+ int rows,
+ int maxrows,
+ int layout_type,
+ int columns,
+ bool sort_reverse,
+ bool sort_lock);
+void uiTemplateNodeLink(uiLayout *layout,
+ struct bNodeTree *ntree,
+ struct bNode *node,
+ struct bNodeSocket *input);
+void uiTemplateNodeView(uiLayout *layout,
+ struct bContext *C,
+ struct bNodeTree *ntree,
+ struct bNode *node,
+ struct bNodeSocket *input);
void uiTemplateTextureUser(uiLayout *layout, struct bContext *C);
-void uiTemplateTextureShow(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop);
-
-void uiTemplateMovieClip(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, bool compact);
+void uiTemplateTextureShow(uiLayout *layout,
+ struct bContext *C,
+ struct PointerRNA *ptr,
+ struct PropertyRNA *prop);
+
+void uiTemplateMovieClip(struct uiLayout *layout,
+ struct bContext *C,
+ struct PointerRNA *ptr,
+ const char *propname,
+ bool compact);
void uiTemplateTrack(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname);
-void uiTemplateMarker(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, PointerRNA *userptr, PointerRNA *trackptr, bool compact);
-void uiTemplateMovieclipInformation(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, struct PointerRNA *userptr);
-
-void uiTemplateColorspaceSettings(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname);
-void uiTemplateColormanagedViewSettings(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname);
+void uiTemplateMarker(struct uiLayout *layout,
+ struct PointerRNA *ptr,
+ const char *propname,
+ PointerRNA *userptr,
+ PointerRNA *trackptr,
+ bool compact);
+void uiTemplateMovieclipInformation(struct uiLayout *layout,
+ struct PointerRNA *ptr,
+ const char *propname,
+ struct PointerRNA *userptr);
+
+void uiTemplateColorspaceSettings(struct uiLayout *layout,
+ struct PointerRNA *ptr,
+ const char *propname);
+void uiTemplateColormanagedViewSettings(struct uiLayout *layout,
+ struct bContext *C,
+ struct PointerRNA *ptr,
+ const char *propname);
int uiTemplateRecentFiles(struct uiLayout *layout, int rows);
/* items */
void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname);
-void uiItemEnumO_ptr(uiLayout *layout, struct wmOperatorType *ot, const char *name, int icon, const char *propname, int value);
-void uiItemEnumO(uiLayout *layout, const char *opname, const char *name, int icon, const char *propname, int value);
-void uiItemEnumO_value(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, int value);
-void uiItemEnumO_string(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, const char *value);
+void uiItemEnumO_ptr(uiLayout *layout,
+ struct wmOperatorType *ot,
+ const char *name,
+ int icon,
+ const char *propname,
+ int value);
+void uiItemEnumO(uiLayout *layout,
+ const char *opname,
+ const char *name,
+ int icon,
+ const char *propname,
+ int value);
+void uiItemEnumO_value(uiLayout *layout,
+ const char *name,
+ int icon,
+ const char *opname,
+ const char *propname,
+ int value);
+void uiItemEnumO_string(uiLayout *layout,
+ const char *name,
+ int icon,
+ const char *opname,
+ const char *propname,
+ const char *value);
void uiItemsEnumO(uiLayout *layout, const char *opname, const char *propname);
-void uiItemBooleanO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, int value);
-void uiItemIntO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, int value);
-void uiItemFloatO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, float value);
-void uiItemStringO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, const char *value);
-
-void uiItemFullO_ptr(
- uiLayout *layout, struct wmOperatorType *ot, const char *name, int icon,
- struct IDProperty *properties, int context, int flag,
- PointerRNA *r_opptr);
-void uiItemFullO(
- uiLayout *layout, const char *idname, const char *name, int icon,
- struct IDProperty *properties, int context, int flag,
- PointerRNA *r_opptr);
-void uiItemFullOMenuHold_ptr(
- uiLayout *layout, struct wmOperatorType *ot, const char *name, int icon,
- struct IDProperty *properties, int context, int flag,
- const char *menu_id, /* extra menu arg. */
- PointerRNA *r_opptr);
-
-void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon);
-void uiItemFullR(
- uiLayout *layout, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, int value, int flag,
- const char *name, int icon);
-void uiItemFullR_with_popover(
- uiLayout *layout, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, int value, int flag,
- const char *name, int icon,
- const char *panel_type);
-void uiItemFullR_with_menu(
- uiLayout *layout, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, int value, int flag,
- const char *name, int icon,
- const char *menu_type);
-void uiItemEnumR_prop(uiLayout *layout, const char *name, int icon, struct PointerRNA *ptr, PropertyRNA *prop, int value);
-void uiItemEnumR(uiLayout *layout, const char *name, int icon, struct PointerRNA *ptr, const char *propname, int value);
-void uiItemEnumR_string_prop(uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, const char *value, const char *name, int icon);
-void uiItemEnumR_string(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *value, const char *name, int icon);
+void uiItemBooleanO(uiLayout *layout,
+ const char *name,
+ int icon,
+ const char *opname,
+ const char *propname,
+ int value);
+void uiItemIntO(uiLayout *layout,
+ const char *name,
+ int icon,
+ const char *opname,
+ const char *propname,
+ int value);
+void uiItemFloatO(uiLayout *layout,
+ const char *name,
+ int icon,
+ const char *opname,
+ const char *propname,
+ float value);
+void uiItemStringO(uiLayout *layout,
+ const char *name,
+ int icon,
+ const char *opname,
+ const char *propname,
+ const char *value);
+
+void uiItemFullO_ptr(uiLayout *layout,
+ struct wmOperatorType *ot,
+ const char *name,
+ int icon,
+ struct IDProperty *properties,
+ int context,
+ int flag,
+ PointerRNA *r_opptr);
+void uiItemFullO(uiLayout *layout,
+ const char *idname,
+ const char *name,
+ int icon,
+ struct IDProperty *properties,
+ int context,
+ int flag,
+ PointerRNA *r_opptr);
+void uiItemFullOMenuHold_ptr(uiLayout *layout,
+ struct wmOperatorType *ot,
+ const char *name,
+ int icon,
+ struct IDProperty *properties,
+ int context,
+ int flag,
+ const char *menu_id, /* extra menu arg. */
+ PointerRNA *r_opptr);
+
+void uiItemR(uiLayout *layout,
+ struct PointerRNA *ptr,
+ const char *propname,
+ int flag,
+ const char *name,
+ int icon);
+void uiItemFullR(uiLayout *layout,
+ struct PointerRNA *ptr,
+ struct PropertyRNA *prop,
+ int index,
+ int value,
+ int flag,
+ const char *name,
+ int icon);
+void uiItemFullR_with_popover(uiLayout *layout,
+ struct PointerRNA *ptr,
+ struct PropertyRNA *prop,
+ int index,
+ int value,
+ int flag,
+ const char *name,
+ int icon,
+ const char *panel_type);
+void uiItemFullR_with_menu(uiLayout *layout,
+ struct PointerRNA *ptr,
+ struct PropertyRNA *prop,
+ int index,
+ int value,
+ int flag,
+ const char *name,
+ int icon,
+ const char *menu_type);
+void uiItemEnumR_prop(uiLayout *layout,
+ const char *name,
+ int icon,
+ struct PointerRNA *ptr,
+ PropertyRNA *prop,
+ int value);
+void uiItemEnumR(uiLayout *layout,
+ const char *name,
+ int icon,
+ struct PointerRNA *ptr,
+ const char *propname,
+ int value);
+void uiItemEnumR_string_prop(uiLayout *layout,
+ struct PointerRNA *ptr,
+ PropertyRNA *prop,
+ const char *value,
+ const char *name,
+ int icon);
+void uiItemEnumR_string(uiLayout *layout,
+ struct PointerRNA *ptr,
+ const char *propname,
+ const char *value,
+ const char *name,
+ int icon);
void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
-void uiItemPointerR_prop(uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, struct PointerRNA *searchptr, PropertyRNA *searchprop, const char *name, int icon);
-void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, struct PointerRNA *searchptr, const char *searchpropname, const char *name, int icon);
-void uiItemsFullEnumO(
- uiLayout *layout, const char *opname, const char *propname,
- struct IDProperty *properties, int context, int flag);
-void uiItemsFullEnumO_items(
- uiLayout *layout, struct wmOperatorType *ot, PointerRNA ptr, PropertyRNA *prop,
- struct IDProperty *properties, int context, int flag,
- const EnumPropertyItem *item_array, int totitem);
+void uiItemPointerR_prop(uiLayout *layout,
+ struct PointerRNA *ptr,
+ PropertyRNA *prop,
+ struct PointerRNA *searchptr,
+ PropertyRNA *searchprop,
+ const char *name,
+ int icon);
+void uiItemPointerR(uiLayout *layout,
+ struct PointerRNA *ptr,
+ const char *propname,
+ struct PointerRNA *searchptr,
+ const char *searchpropname,
+ const char *name,
+ int icon);
+void uiItemsFullEnumO(uiLayout *layout,
+ const char *opname,
+ const char *propname,
+ struct IDProperty *properties,
+ int context,
+ int flag);
+void uiItemsFullEnumO_items(uiLayout *layout,
+ struct wmOperatorType *ot,
+ PointerRNA ptr,
+ PropertyRNA *prop,
+ struct IDProperty *properties,
+ int context,
+ int flag,
+ const EnumPropertyItem *item_array,
+ int totitem);
void uiItemL(uiLayout *layout, const char *name, int icon); /* label */
/* label icon for dragging */
@@ -1288,98 +2216,129 @@ void uiItemS_ex(uiLayout *layout, float factor);
void uiItemSpacer(uiLayout *layout);
void uiItemPopoverPanel_ptr(
- uiLayout *layout, struct bContext *C,
- struct PanelType *pt,
- const char *name, int icon);
+ uiLayout *layout, struct bContext *C, struct PanelType *pt, const char *name, int icon);
void uiItemPopoverPanel(
- uiLayout *layout, struct bContext *C,
- const char *panelname,
- const char *name, int icon);
-void uiItemPopoverPanelFromGroup(
- uiLayout *layout, struct bContext *C,
- int space_id, int region_id,
- const char *context, const char *category);
+ uiLayout *layout, struct bContext *C, const char *panelname, const char *name, int icon);
+void uiItemPopoverPanelFromGroup(uiLayout *layout,
+ struct bContext *C,
+ int space_id,
+ int region_id,
+ const char *context,
+ const char *category);
void uiItemMenuF(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg);
void uiItemMenuFN(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *argN);
-void uiItemMenuEnumO_ptr(uiLayout *layout, struct bContext *C, struct wmOperatorType *ot, const char *propname, const char *name, int icon);
-void uiItemMenuEnumO(uiLayout *layout, struct bContext *C, const char *opname, const char *propname, const char *name, int icon);
-void uiItemMenuEnumR_prop(uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, const char *name, int icon);
-void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon);
-void uiItemTabsEnumR_prop(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, PropertyRNA *prop, bool icon_only);
+void uiItemMenuEnumO_ptr(uiLayout *layout,
+ struct bContext *C,
+ struct wmOperatorType *ot,
+ const char *propname,
+ const char *name,
+ int icon);
+void uiItemMenuEnumO(uiLayout *layout,
+ struct bContext *C,
+ const char *opname,
+ const char *propname,
+ const char *name,
+ int icon);
+void uiItemMenuEnumR_prop(
+ uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, const char *name, int icon);
+void uiItemMenuEnumR(
+ uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon);
+void uiItemTabsEnumR_prop(uiLayout *layout,
+ struct bContext *C,
+ struct PointerRNA *ptr,
+ PropertyRNA *prop,
+ bool icon_only);
/* UI Operators */
typedef struct uiDragColorHandle {
- float color[3];
- bool gamma_corrected;
+ float color[3];
+ bool gamma_corrected;
} uiDragColorHandle;
void ED_operatortypes_ui(void);
void ED_keymap_ui(struct wmKeyConfig *keyconf);
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);
-
-bool UI_context_copy_to_selected_list(
- struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop,
- struct ListBase *r_lb, bool *r_use_path_from_id, char **r_path);
+bool UI_drop_color_poll(struct bContext *C,
+ struct wmDrag *drag,
+ const struct wmEvent *event,
+ const char **tooltip);
+
+bool UI_context_copy_to_selected_list(struct bContext *C,
+ struct PointerRNA *ptr,
+ struct PropertyRNA *prop,
+ struct ListBase *r_lb,
+ bool *r_use_path_from_id,
+ char **r_path);
/* Helpers for Operators */
uiBut *UI_context_active_but_get(const struct bContext *C);
-uiBut *UI_context_active_but_prop_get(
- const struct bContext *C,
- struct PointerRNA *r_ptr, struct PropertyRNA **r_prop, int *r_index);
+uiBut *UI_context_active_but_prop_get(const struct bContext *C,
+ struct PointerRNA *r_ptr,
+ struct PropertyRNA **r_prop,
+ int *r_index);
void UI_context_active_but_prop_handle(struct bContext *C);
struct wmOperator *UI_context_active_operator_get(const struct bContext *C);
void UI_context_update_anim_flag(const struct bContext *C);
-void UI_context_active_but_prop_get_filebrowser(
- const struct bContext *C,
- struct PointerRNA *r_ptr, struct PropertyRNA **r_prop, bool *r_is_undo);
-void UI_context_active_but_prop_get_templateID(
- struct bContext *C,
- struct PointerRNA *r_ptr, struct PropertyRNA **r_prop);
+void UI_context_active_but_prop_get_filebrowser(const struct bContext *C,
+ struct PointerRNA *r_ptr,
+ struct PropertyRNA **r_prop,
+ bool *r_is_undo);
+void UI_context_active_but_prop_get_templateID(struct bContext *C,
+ struct PointerRNA *r_ptr,
+ 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);
/* uiFontStyle.align */
typedef enum eFontStyle_Align {
- UI_STYLE_TEXT_LEFT = 0,
- UI_STYLE_TEXT_CENTER = 1,
- UI_STYLE_TEXT_RIGHT = 2,
+ UI_STYLE_TEXT_LEFT = 0,
+ UI_STYLE_TEXT_CENTER = 1,
+ UI_STYLE_TEXT_RIGHT = 2,
} eFontStyle_Align;
struct uiFontStyleDraw_Params {
- eFontStyle_Align align;
- uint word_wrap : 1;
+ eFontStyle_Align align;
+ uint word_wrap : 1;
};
/* Styled text draw */
void UI_fontstyle_set(const struct uiFontStyle *fs);
-void UI_fontstyle_draw_ex(
- const struct uiFontStyle *fs, const struct rcti *rect, const char *str,
- const uchar col[4], const struct uiFontStyleDraw_Params *fs_params,
- size_t len, float *r_xofs, float *r_yofs);
-void UI_fontstyle_draw(
- const struct uiFontStyle *fs, const struct rcti *rect, const char *str,
- const uchar col[4], const struct uiFontStyleDraw_Params *fs_params);
-void UI_fontstyle_draw_rotated(
- const struct uiFontStyle *fs, const struct rcti *rect, const char *str,
- const uchar col[4]);
+void UI_fontstyle_draw_ex(const struct uiFontStyle *fs,
+ const struct rcti *rect,
+ const char *str,
+ const uchar col[4],
+ const struct uiFontStyleDraw_Params *fs_params,
+ size_t len,
+ float *r_xofs,
+ float *r_yofs);
+void UI_fontstyle_draw(const struct uiFontStyle *fs,
+ const struct rcti *rect,
+ const char *str,
+ const uchar col[4],
+ const struct uiFontStyleDraw_Params *fs_params);
+void UI_fontstyle_draw_rotated(const struct uiFontStyle *fs,
+ const struct rcti *rect,
+ const char *str,
+ const uchar col[4]);
void UI_fontstyle_draw_simple(
- const struct uiFontStyle *fs, float x, float y, const char *str,
- const uchar col[4]);
-void UI_fontstyle_draw_simple_backdrop(
- const struct uiFontStyle *fs, float x, float y, const char *str,
- const float col_fg[4], const float col_bg[4]);
+ const struct uiFontStyle *fs, float x, float y, const char *str, const uchar col[4]);
+void UI_fontstyle_draw_simple_backdrop(const struct uiFontStyle *fs,
+ float x,
+ float y,
+ const char *str,
+ const float col_fg[4],
+ const float col_bg[4]);
int UI_fontstyle_string_width(const struct uiFontStyle *fs, const char *str);
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 */
+struct uiStyle *UI_style_get(void); /* use for fonts etc */
+struct uiStyle *UI_style_get_dpi(void); /* DPI scaled settings for drawing */
/* linker workaround ack! */
void UI_template_fix_linking(void);
@@ -1403,7 +2362,10 @@ bool UI_butstore_register_update(uiBlock *block, uiBut *but_dst, const uiBut *bu
void UI_butstore_unregister(uiButStore *bs_handle, uiBut **but_p);
/* ui_interface_region_tooltip.c */
-struct ARegion *UI_tooltip_create_from_button(struct bContext *C, struct ARegion *butregion, uiBut *but, bool is_label);
+struct ARegion *UI_tooltip_create_from_button(struct bContext *C,
+ struct ARegion *butregion,
+ 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);
@@ -1436,4 +2398,4 @@ void UI_style_init_default(void);
/* Support click-drag motion which presses the button and closes a popover (like a menu). */
#define USE_UI_POPOVER_ONCE
-#endif /* __UI_INTERFACE_H__ */
+#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 bd1f04ebcff..5666421c27f 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -33,18 +33,18 @@ struct bContext;
enum eIconSizes;
typedef struct IconFile {
- struct IconFile *next, *prev;
- char filename[256]; /* FILE_MAXFILE size */
- int index;
+ struct IconFile *next, *prev;
+ char filename[256]; /* FILE_MAXFILE size */
+ int index;
} IconFile;
#define ICON_DEFAULT_HEIGHT 16
-#define ICON_DEFAULT_WIDTH 16
+#define ICON_DEFAULT_WIDTH 16
#define ICON_DEFAULT_HEIGHT_TOOLBAR 32
#define ICON_DEFAULT_HEIGHT_SCALE ((int)(UI_UNIT_Y * 0.8f))
-#define ICON_DEFAULT_WIDTH_SCALE ((int)(UI_UNIT_X * 0.8f))
+#define ICON_DEFAULT_WIDTH_SCALE ((int)(UI_UNIT_X * 0.8f))
#define PREVIEW_DEFAULT_HEIGHT 128
@@ -55,20 +55,32 @@ void UI_icons_init(void);
int UI_icon_get_width(int icon_id);
int UI_icon_get_height(int icon_id);
-void UI_id_icon_render(
- const struct bContext *C, struct Scene *scene, struct ID *id, const bool big, const bool use_job);
+void UI_id_icon_render(const struct bContext *C,
+ struct Scene *scene,
+ struct ID *id,
+ const bool big,
+ const bool use_job);
int UI_preview_render_size(enum eIconSizes size);
void UI_icon_draw(float x, float y, int icon_id);
void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha);
void UI_icon_draw_preview(float x, float y, int icon_id);
void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect);
-void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspect, float alpha, int size);
+void UI_icon_draw_preview_aspect_size(
+ float x, float y, int icon_id, float aspect, float alpha, int size);
-void UI_icon_draw_aspect(float x, float y, int icon_id, float aspect, float alpha, const char mono_color[4]);
-void UI_icon_draw_aspect_color(float x, float y, int icon_id, float aspect, const float rgb[3], const char mono_color[4]);
+void UI_icon_draw_aspect(
+ float x, float y, int icon_id, float aspect, float alpha, const char mono_color[4]);
+void UI_icon_draw_aspect_color(
+ float x, float y, int icon_id, float aspect, const float rgb[3], const char mono_color[4]);
void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha);
-void UI_icon_draw_desaturate(float x, float y, int icon_id, float aspect, float alpha, float desaturate, const char mono_color[4]);
+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);
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 61fc09b751b..1fc1fba4b4a 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -33,284 +33,284 @@
#define DEF_ICON_BLANK(name) ICON_BLANK_##name,
typedef enum {
- /* ui */
+/* ui */
#include "UI_icons.h"
- BIFICONID_LAST,
+ BIFICONID_LAST,
} BIFIconID;
-#define BIFICONID_FIRST (ICON_NONE)
+#define BIFICONID_FIRST (ICON_NONE)
/* use to denote intentionally unset theme color */
#define TH_UNDEFINED -1
typedef enum ThemeColorID {
- TH_REDALERT,
-
- TH_THEMEUI,
-// common colors among spaces
-
- TH_BACK,
- /** Use when 'TH_SHOW_BACK_GRAD' is set (the lower, darker color). */
- TH_BACK_GRAD,
- TH_TEXT,
- TH_TEXT_HI,
- TH_TITLE,
- TH_TAB_ACTIVE,
- TH_TAB_INACTIVE,
- TH_TAB_BACK,
- TH_TAB_OUTLINE,
-
- TH_HEADER,
- TH_HEADERDESEL,
- TH_HEADER_TEXT,
- TH_HEADER_TEXT_HI,
-
- /* panels */
- TH_PANEL_HEADER,
- TH_PANEL_BACK,
- TH_PANEL_SUB_BACK,
-
- TH_BUTBACK,
- TH_BUTBACK_TEXT,
- TH_BUTBACK_TEXT_HI,
-
- TH_SHADE1,
- TH_SHADE2,
- TH_HILITE,
-
- TH_GRID,
- TH_WIRE,
- TH_WIRE_INNER,
- TH_WIRE_EDIT,
- TH_SELECT,
- TH_ACTIVE,
- TH_GROUP,
- TH_GROUP_ACTIVE,
- TH_TRANSFORM,
- TH_VERTEX,
- TH_VERTEX_SELECT,
- TH_VERTEX_UNREFERENCED,
- TH_VERTEX_SIZE,
- TH_OUTLINE_WIDTH,
- TH_EDGE,
- TH_EDGE_SELECT,
- TH_EDGE_SEAM,
- TH_EDGE_FACESEL,
- TH_FACE,
- TH_FACE_SELECT,
- TH_NORMAL,
- TH_VNORMAL,
- TH_LNORMAL,
- TH_FACE_DOT,
- TH_FACEDOT_SIZE,
- TH_CFRAME,
- TH_TIME_KEYFRAME,
- TH_TIME_GP_KEYFRAME,
- TH_NURB_ULINE,
- TH_NURB_VLINE,
- TH_NURB_SEL_ULINE,
- TH_NURB_SEL_VLINE,
-
- /* this eight colors should be in one block */
- TH_HANDLE_FREE,
- TH_HANDLE_AUTO,
- TH_HANDLE_VECT,
- TH_HANDLE_ALIGN,
- TH_HANDLE_AUTOCLAMP,
- TH_HANDLE_SEL_FREE,
- TH_HANDLE_SEL_AUTO,
- TH_HANDLE_SEL_VECT,
- TH_HANDLE_SEL_ALIGN,
- TH_HANDLE_SEL_AUTOCLAMP,
-
- TH_ACTIVE_SPLINE,
- TH_ACTIVE_VERT, /* equivalent of TH_EDITMESH_ACTIVE for splines */
-
- TH_SYNTAX_B,
- TH_SYNTAX_V,
- TH_SYNTAX_R,
- TH_SYNTAX_C,
- TH_SYNTAX_L,
- TH_SYNTAX_D,
- TH_SYNTAX_N,
- TH_SYNTAX_S,
-
- TH_BONE_SOLID,
- TH_BONE_POSE,
- TH_BONE_POSE_ACTIVE,
-
- TH_STRIP,
- TH_STRIP_SELECT,
-
- TH_KEYTYPE_KEYFRAME, /* KEYTYPES */
- TH_KEYTYPE_KEYFRAME_SELECT,
- TH_KEYTYPE_EXTREME,
- TH_KEYTYPE_EXTREME_SELECT,
- TH_KEYTYPE_BREAKDOWN,
- TH_KEYTYPE_BREAKDOWN_SELECT,
- TH_KEYTYPE_JITTER,
- TH_KEYTYPE_JITTER_SELECT,
- TH_KEYTYPE_MOVEHOLD,
- TH_KEYTYPE_MOVEHOLD_SELECT,
-
- TH_KEYBORDER,
- TH_KEYBORDER_SELECT,
-
- TH_LIGHT,
- TH_SPEAKER,
- TH_CAMERA,
- TH_EMPTY,
-
- TH_NODE,
- TH_NODE_INPUT,
- TH_NODE_OUTPUT,
- TH_NODE_COLOR,
- TH_NODE_FILTER,
- TH_NODE_VECTOR,
- TH_NODE_TEXTURE,
- TH_NODE_PATTERN,
- TH_NODE_SCRIPT,
- TH_NODE_LAYOUT,
- TH_NODE_SHADER,
- TH_NODE_INTERFACE,
- TH_NODE_CONVERTOR,
- TH_NODE_GROUP,
- TH_NODE_FRAME,
- TH_NODE_MATTE,
- TH_NODE_DISTORT,
-
- TH_CONSOLE_OUTPUT,
- TH_CONSOLE_INPUT,
- TH_CONSOLE_INFO,
- TH_CONSOLE_ERROR,
- TH_CONSOLE_CURSOR,
- TH_CONSOLE_SELECT,
-
- TH_SEQ_MOVIE,
- TH_SEQ_MOVIECLIP,
- TH_SEQ_MASK,
- TH_SEQ_IMAGE,
- TH_SEQ_SCENE,
- TH_SEQ_AUDIO,
- TH_SEQ_EFFECT,
- TH_SEQ_TRANSITION,
- TH_SEQ_META,
- TH_SEQ_TEXT,
- TH_SEQ_PREVIEW,
-
- TH_EDGE_SHARP,
- TH_EDITMESH_ACTIVE,
-
- TH_HANDLE_VERTEX,
- TH_HANDLE_VERTEX_SELECT,
- TH_HANDLE_VERTEX_SIZE,
-
- TH_GP_VERTEX,
- TH_GP_VERTEX_SELECT,
- TH_GP_VERTEX_SIZE,
-
- TH_DOPESHEET_CHANNELOB,
- TH_DOPESHEET_CHANNELSUBOB,
- TH_DOPESHEET_IPOLINE,
-
- TH_PREVIEW_BACK,
-
- TH_EDGE_CREASE,
-
- TH_DRAWEXTRA_EDGELEN,
- TH_DRAWEXTRA_EDGEANG,
- TH_DRAWEXTRA_FACEAREA,
- TH_DRAWEXTRA_FACEANG,
-
- TH_NODE_CURVING,
-
- TH_MARKER_OUTLINE,
- TH_MARKER,
- TH_ACT_MARKER,
- TH_SEL_MARKER,
- TH_BUNDLE_SOLID,
- TH_DIS_MARKER,
- TH_PATH_BEFORE,
- TH_PATH_AFTER,
- TH_CAMERA_PATH,
- TH_LOCK_MARKER,
-
- TH_STITCH_PREVIEW_FACE,
- TH_STITCH_PREVIEW_EDGE,
- TH_STITCH_PREVIEW_VERT,
- TH_STITCH_PREVIEW_STITCHABLE,
- TH_STITCH_PREVIEW_UNSTITCHABLE,
- TH_STITCH_PREVIEW_ACTIVE,
-
- TH_PAINT_CURVE_HANDLE,
- TH_PAINT_CURVE_PIVOT,
-
- TH_UV_SHADOW,
- TH_UV_OTHERS,
-
- TH_FREESTYLE_EDGE_MARK,
- TH_FREESTYLE_FACE_MARK,
-
- TH_MATCH, /* highlight color for search matches */
- TH_SELECT_HIGHLIGHT, /* highlight color for selected outliner item */
-
- TH_SKIN_ROOT,
-
- TH_ANIM_ACTIVE, /* active action */
- TH_ANIM_INACTIVE, /* no active action */
- TH_ANIM_PREVIEW_RANGE,/* preview range overlay */
-
- TH_ICON_COLLECTION,
- TH_ICON_OBJECT,
- TH_ICON_OBJECT_DATA,
- TH_ICON_MODIFIER,
- TH_ICON_SHADING,
-
- TH_NLA_TWEAK, /* 'tweaking' track in NLA */
- TH_NLA_TWEAK_DUPLI, /* error/warning flag for other strips referencing dupli strip */
-
- TH_NLA_TRANSITION,
- TH_NLA_TRANSITION_SEL,
- TH_NLA_META,
- TH_NLA_META_SEL,
- TH_NLA_SOUND,
- TH_NLA_SOUND_SEL,
-
- TH_WIDGET_EMBOSS,
-
- TH_EDITOR_OUTLINE,
-
- TH_AXIS_X, /* X/Y/Z Axis */
- TH_AXIS_Y,
- TH_AXIS_Z,
-
- TH_GIZMO_HI,
- TH_GIZMO_PRIMARY,
- TH_GIZMO_SECONDARY,
- TH_GIZMO_A,
- TH_GIZMO_B,
-
- TH_SHOW_BACK_GRAD,
-
- TH_INFO_SELECTED,
- TH_INFO_SELECTED_TEXT,
- TH_INFO_ERROR,
- TH_INFO_ERROR_TEXT,
- TH_INFO_WARNING,
- TH_INFO_WARNING_TEXT,
- TH_INFO_INFO,
- TH_INFO_INFO_TEXT,
- TH_INFO_DEBUG,
- TH_INFO_DEBUG_TEXT,
- TH_VIEW_OVERLAY,
-
- TH_V3D_CLIPPING_BORDER,
-
- TH_METADATA_BG,
- TH_METADATA_TEXT,
+ TH_REDALERT,
+
+ TH_THEMEUI,
+ // common colors among spaces
+
+ TH_BACK,
+ /** Use when 'TH_SHOW_BACK_GRAD' is set (the lower, darker color). */
+ TH_BACK_GRAD,
+ TH_TEXT,
+ TH_TEXT_HI,
+ TH_TITLE,
+ TH_TAB_ACTIVE,
+ TH_TAB_INACTIVE,
+ TH_TAB_BACK,
+ TH_TAB_OUTLINE,
+
+ TH_HEADER,
+ TH_HEADERDESEL,
+ TH_HEADER_TEXT,
+ TH_HEADER_TEXT_HI,
+
+ /* panels */
+ TH_PANEL_HEADER,
+ TH_PANEL_BACK,
+ TH_PANEL_SUB_BACK,
+
+ TH_BUTBACK,
+ TH_BUTBACK_TEXT,
+ TH_BUTBACK_TEXT_HI,
+
+ TH_SHADE1,
+ TH_SHADE2,
+ TH_HILITE,
+
+ TH_GRID,
+ TH_WIRE,
+ TH_WIRE_INNER,
+ TH_WIRE_EDIT,
+ TH_SELECT,
+ TH_ACTIVE,
+ TH_GROUP,
+ TH_GROUP_ACTIVE,
+ TH_TRANSFORM,
+ TH_VERTEX,
+ TH_VERTEX_SELECT,
+ TH_VERTEX_UNREFERENCED,
+ TH_VERTEX_SIZE,
+ TH_OUTLINE_WIDTH,
+ TH_EDGE,
+ TH_EDGE_SELECT,
+ TH_EDGE_SEAM,
+ TH_EDGE_FACESEL,
+ TH_FACE,
+ TH_FACE_SELECT,
+ TH_NORMAL,
+ TH_VNORMAL,
+ TH_LNORMAL,
+ TH_FACE_DOT,
+ TH_FACEDOT_SIZE,
+ TH_CFRAME,
+ TH_TIME_KEYFRAME,
+ TH_TIME_GP_KEYFRAME,
+ TH_NURB_ULINE,
+ TH_NURB_VLINE,
+ TH_NURB_SEL_ULINE,
+ TH_NURB_SEL_VLINE,
+
+ /* this eight colors should be in one block */
+ TH_HANDLE_FREE,
+ TH_HANDLE_AUTO,
+ TH_HANDLE_VECT,
+ TH_HANDLE_ALIGN,
+ TH_HANDLE_AUTOCLAMP,
+ TH_HANDLE_SEL_FREE,
+ TH_HANDLE_SEL_AUTO,
+ TH_HANDLE_SEL_VECT,
+ TH_HANDLE_SEL_ALIGN,
+ TH_HANDLE_SEL_AUTOCLAMP,
+
+ TH_ACTIVE_SPLINE,
+ TH_ACTIVE_VERT, /* equivalent of TH_EDITMESH_ACTIVE for splines */
+
+ TH_SYNTAX_B,
+ TH_SYNTAX_V,
+ TH_SYNTAX_R,
+ TH_SYNTAX_C,
+ TH_SYNTAX_L,
+ TH_SYNTAX_D,
+ TH_SYNTAX_N,
+ TH_SYNTAX_S,
+
+ TH_BONE_SOLID,
+ TH_BONE_POSE,
+ TH_BONE_POSE_ACTIVE,
+
+ TH_STRIP,
+ TH_STRIP_SELECT,
+
+ TH_KEYTYPE_KEYFRAME, /* KEYTYPES */
+ TH_KEYTYPE_KEYFRAME_SELECT,
+ TH_KEYTYPE_EXTREME,
+ TH_KEYTYPE_EXTREME_SELECT,
+ TH_KEYTYPE_BREAKDOWN,
+ TH_KEYTYPE_BREAKDOWN_SELECT,
+ TH_KEYTYPE_JITTER,
+ TH_KEYTYPE_JITTER_SELECT,
+ TH_KEYTYPE_MOVEHOLD,
+ TH_KEYTYPE_MOVEHOLD_SELECT,
+
+ TH_KEYBORDER,
+ TH_KEYBORDER_SELECT,
+
+ TH_LIGHT,
+ TH_SPEAKER,
+ TH_CAMERA,
+ TH_EMPTY,
+
+ TH_NODE,
+ TH_NODE_INPUT,
+ TH_NODE_OUTPUT,
+ TH_NODE_COLOR,
+ TH_NODE_FILTER,
+ TH_NODE_VECTOR,
+ TH_NODE_TEXTURE,
+ TH_NODE_PATTERN,
+ TH_NODE_SCRIPT,
+ TH_NODE_LAYOUT,
+ TH_NODE_SHADER,
+ TH_NODE_INTERFACE,
+ TH_NODE_CONVERTOR,
+ TH_NODE_GROUP,
+ TH_NODE_FRAME,
+ TH_NODE_MATTE,
+ TH_NODE_DISTORT,
+
+ TH_CONSOLE_OUTPUT,
+ TH_CONSOLE_INPUT,
+ TH_CONSOLE_INFO,
+ TH_CONSOLE_ERROR,
+ TH_CONSOLE_CURSOR,
+ TH_CONSOLE_SELECT,
+
+ TH_SEQ_MOVIE,
+ TH_SEQ_MOVIECLIP,
+ TH_SEQ_MASK,
+ TH_SEQ_IMAGE,
+ TH_SEQ_SCENE,
+ TH_SEQ_AUDIO,
+ TH_SEQ_EFFECT,
+ TH_SEQ_TRANSITION,
+ TH_SEQ_META,
+ TH_SEQ_TEXT,
+ TH_SEQ_PREVIEW,
+
+ TH_EDGE_SHARP,
+ TH_EDITMESH_ACTIVE,
+
+ TH_HANDLE_VERTEX,
+ TH_HANDLE_VERTEX_SELECT,
+ TH_HANDLE_VERTEX_SIZE,
+
+ TH_GP_VERTEX,
+ TH_GP_VERTEX_SELECT,
+ TH_GP_VERTEX_SIZE,
+
+ TH_DOPESHEET_CHANNELOB,
+ TH_DOPESHEET_CHANNELSUBOB,
+ TH_DOPESHEET_IPOLINE,
+
+ TH_PREVIEW_BACK,
+
+ TH_EDGE_CREASE,
+
+ TH_DRAWEXTRA_EDGELEN,
+ TH_DRAWEXTRA_EDGEANG,
+ TH_DRAWEXTRA_FACEAREA,
+ TH_DRAWEXTRA_FACEANG,
+
+ TH_NODE_CURVING,
+
+ TH_MARKER_OUTLINE,
+ TH_MARKER,
+ TH_ACT_MARKER,
+ TH_SEL_MARKER,
+ TH_BUNDLE_SOLID,
+ TH_DIS_MARKER,
+ TH_PATH_BEFORE,
+ TH_PATH_AFTER,
+ TH_CAMERA_PATH,
+ TH_LOCK_MARKER,
+
+ TH_STITCH_PREVIEW_FACE,
+ TH_STITCH_PREVIEW_EDGE,
+ TH_STITCH_PREVIEW_VERT,
+ TH_STITCH_PREVIEW_STITCHABLE,
+ TH_STITCH_PREVIEW_UNSTITCHABLE,
+ TH_STITCH_PREVIEW_ACTIVE,
+
+ TH_PAINT_CURVE_HANDLE,
+ TH_PAINT_CURVE_PIVOT,
+
+ TH_UV_SHADOW,
+ TH_UV_OTHERS,
+
+ TH_FREESTYLE_EDGE_MARK,
+ TH_FREESTYLE_FACE_MARK,
+
+ TH_MATCH, /* highlight color for search matches */
+ TH_SELECT_HIGHLIGHT, /* highlight color for selected outliner item */
+
+ TH_SKIN_ROOT,
+
+ TH_ANIM_ACTIVE, /* active action */
+ TH_ANIM_INACTIVE, /* no active action */
+ TH_ANIM_PREVIEW_RANGE, /* preview range overlay */
+
+ TH_ICON_COLLECTION,
+ TH_ICON_OBJECT,
+ TH_ICON_OBJECT_DATA,
+ TH_ICON_MODIFIER,
+ TH_ICON_SHADING,
+
+ TH_NLA_TWEAK, /* 'tweaking' track in NLA */
+ TH_NLA_TWEAK_DUPLI, /* error/warning flag for other strips referencing dupli strip */
+
+ TH_NLA_TRANSITION,
+ TH_NLA_TRANSITION_SEL,
+ TH_NLA_META,
+ TH_NLA_META_SEL,
+ TH_NLA_SOUND,
+ TH_NLA_SOUND_SEL,
+
+ TH_WIDGET_EMBOSS,
+
+ TH_EDITOR_OUTLINE,
+
+ TH_AXIS_X, /* X/Y/Z Axis */
+ TH_AXIS_Y,
+ TH_AXIS_Z,
+
+ TH_GIZMO_HI,
+ TH_GIZMO_PRIMARY,
+ TH_GIZMO_SECONDARY,
+ TH_GIZMO_A,
+ TH_GIZMO_B,
+
+ TH_SHOW_BACK_GRAD,
+
+ TH_INFO_SELECTED,
+ TH_INFO_SELECTED_TEXT,
+ TH_INFO_ERROR,
+ TH_INFO_ERROR_TEXT,
+ TH_INFO_WARNING,
+ TH_INFO_WARNING_TEXT,
+ TH_INFO_INFO,
+ TH_INFO_INFO_TEXT,
+ TH_INFO_DEBUG,
+ TH_INFO_DEBUG_TEXT,
+ TH_VIEW_OVERLAY,
+
+ TH_V3D_CLIPPING_BORDER,
+
+ TH_METADATA_BG,
+ TH_METADATA_TEXT,
- TH_EDGE_BEVEL,
- TH_VERTEX_BEVEL,
+ TH_EDGE_BEVEL,
+ TH_VERTEX_BEVEL,
} ThemeColorID;
/* specific defines per space should have higher define values */
@@ -318,48 +318,54 @@ typedef enum ThemeColorID {
struct bTheme;
struct bThemeState {
- struct bTheme *theme;
- int spacetype, regionid;
+ struct bTheme *theme;
+ int spacetype, regionid;
};
// THE CODERS API FOR THEMES:
// returns one value, not scaled
-float UI_GetThemeValuef(int colorid);
-int UI_GetThemeValue(int colorid);
+float UI_GetThemeValuef(int colorid);
+int UI_GetThemeValue(int colorid);
-float UI_GetThemeValueTypef(int colorid, int spacetype);
-int UI_GetThemeValueType(int colorid, int spacetype);
+float UI_GetThemeValueTypef(int colorid, int spacetype);
+int UI_GetThemeValueType(int colorid, int spacetype);
// get three color values, scaled to 0.0-1.0 range
-void UI_GetThemeColor3fv(int colorid, float col[3]);
-void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigned char col[3]);
-void UI_GetThemeColorBlend3f(int colorid1, int colorid2, float fac, float r_col[3]);
-void UI_GetThemeColorBlend4f(int colorid1, int colorid2, float fac, float r_col[4]);
+void UI_GetThemeColor3fv(int colorid, float col[3]);
+void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigned char col[3]);
+void UI_GetThemeColorBlend3f(int colorid1, int colorid2, float fac, float r_col[3]);
+void UI_GetThemeColorBlend4f(int colorid1, int colorid2, float fac, float r_col[4]);
// get the color, range 0.0-1.0, complete with shading offset
-void UI_GetThemeColorShade3fv(int colorid, int offset, float col[3]);
-void UI_GetThemeColorShade3ubv(int colorid, int offset, unsigned char col[3]);
-void UI_GetThemeColorShade4ubv(int colorid, int offset, unsigned char col[4]);
+void UI_GetThemeColorShade3fv(int colorid, int offset, float col[3]);
+void UI_GetThemeColorShade3ubv(int colorid, int offset, unsigned char col[3]);
+void UI_GetThemeColorShade4ubv(int colorid, int offset, unsigned char col[4]);
// get three color values, range 0-255, complete with shading offset for the RGB components and blending
-void UI_GetThemeColorBlendShade3ubv(int colorid1, int colorid2, float fac, int offset, unsigned char col[3]);
+void UI_GetThemeColorBlendShade3ubv(
+ int colorid1, int colorid2, float fac, int offset, unsigned char col[3]);
// get four color values, scaled to 0.0-1.0 range
-void UI_GetThemeColor4fv(int colorid, float col[4]);
+void UI_GetThemeColor4fv(int colorid, float col[4]);
/* get four color values from specified space type, scaled to 0.0-1.0 range */
-void UI_GetThemeColorType4fv(int colorid, int spacetype, float col[4]);
+void UI_GetThemeColorType4fv(int colorid, int spacetype, float col[4]);
// get four color values, range 0.0-1.0, complete with shading offset for the RGB components
-void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4]);
-void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4]);
+void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4]);
+void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4]);
// get four colour values ranged between 0 and 255; includes the alpha channel
-void UI_GetThemeColorShadeAlpha4ubv(int colorid, int coloffset, int alphaoffset, unsigned char col[4]);
+void UI_GetThemeColorShadeAlpha4ubv(int colorid,
+ int coloffset,
+ int alphaoffset,
+ unsigned char col[4]);
// get four color values, range 0.0-1.0, complete with shading offset for the RGB components and blending
-void UI_GetThemeColorBlendShade3fv(int colorid1, int colorid2, float fac, int offset, float col[3]);
-void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int offset, float col[4]);
+void UI_GetThemeColorBlendShade3fv(
+ int colorid1, int colorid2, float fac, int offset, float col[3]);
+void UI_GetThemeColorBlendShade4fv(
+ int colorid1, int colorid2, float fac, int offset, float col[4]);
// get the 3 or 4 byte values
void UI_GetThemeColor3ubv(int colorid, unsigned char col[3]);
@@ -371,26 +377,30 @@ void UI_GetThemeColorType3ubv(int colorid, int spacetype, unsigned char col[3]);
void UI_GetThemeColorType4ubv(int colorid, int spacetype, unsigned char col[4]);
// get theme color for coloring monochrome icons
-bool UI_GetIconThemeColor4fv(int colorid, float col[4]);
+bool UI_GetIconThemeColor4fv(int colorid, float col[4]);
// shade a 3 byte color (same as UI_GetColorPtrBlendShade3ubv with 0.0 factor)
-void UI_GetColorPtrShade3ubv(const unsigned char cp1[3], unsigned char col[3], int offset);
+void UI_GetColorPtrShade3ubv(const unsigned char cp1[3], unsigned char col[3], int offset);
// get a 3 byte color, blended and shaded between two other char color pointers
-void UI_GetColorPtrBlendShade3ubv(const unsigned char cp1[3], const unsigned char cp2[3], unsigned char col[3], float fac, int offset);
+void UI_GetColorPtrBlendShade3ubv(const unsigned char cp1[3],
+ const unsigned char cp2[3],
+ unsigned char col[3],
+ float fac,
+ int offset);
// sets the font color
// (for anything fancy use UI_GetThemeColor[Fancy] then BLF_color)
void UI_FontThemeColor(int fontid, int colorid);
// clear the openGL ClearColor using the input colorid
-void UI_ThemeClearColor(int colorid);
+void UI_ThemeClearColor(int colorid);
// clear the openGL ClearColor using the input colorid using optional transparency
-void UI_ThemeClearColorAlpha(int colorid, float alpha);
+void UI_ThemeClearColorAlpha(int colorid, float alpha);
// internal (blender) usage only, for init and set active
-void UI_SetTheme(int spacetype, int regionid);
+void UI_SetTheme(int spacetype, int regionid);
// get current theme
struct bTheme *UI_GetTheme(void);
@@ -406,4 +416,4 @@ 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);
-#endif /* __UI_RESOURCES_H__ */
+#endif /* __UI_RESOURCES_H__ */
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 6efbcf09e97..fde865d4bba 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -34,7 +34,7 @@
/* ---- General Defines ---- */
/* generic value to use when coordinate lies out of view when converting */
-#define V2D_IS_CLIPPED 12000
+#define V2D_IS_CLIPPED 12000
/* Common View2D view types
* NOTE: only define a type here if it completely sets all (+/- a few) of the relevant flags
@@ -42,80 +42,80 @@
* than one specific place
*/
enum eView2D_CommonViewTypes {
- /* custom view type (region has defined all necessary flags already) */
- V2D_COMMONVIEW_CUSTOM = -1,
- /* standard (only use this when setting up a new view, as a sensible base for most settings) */
- V2D_COMMONVIEW_STANDARD,
- /* listview (i.e. Outliner) */
- V2D_COMMONVIEW_LIST,
- /* stackview (this is basically a list where new items are added at the top) */
- V2D_COMMONVIEW_STACK,
- /* headers (this is basically the same as listview, but no y-panning) */
- V2D_COMMONVIEW_HEADER,
- /* ui region containing panels */
- V2D_COMMONVIEW_PANELS_UI,
+ /* custom view type (region has defined all necessary flags already) */
+ V2D_COMMONVIEW_CUSTOM = -1,
+ /* standard (only use this when setting up a new view, as a sensible base for most settings) */
+ V2D_COMMONVIEW_STANDARD,
+ /* listview (i.e. Outliner) */
+ V2D_COMMONVIEW_LIST,
+ /* stackview (this is basically a list where new items are added at the top) */
+ V2D_COMMONVIEW_STACK,
+ /* headers (this is basically the same as listview, but no y-panning) */
+ V2D_COMMONVIEW_HEADER,
+ /* ui region containing panels */
+ V2D_COMMONVIEW_PANELS_UI,
};
/* ---- Defines for Scroller/Grid Arguments ----- */
/* 'dummy' argument to pass when argument is irrelevant */
-#define V2D_ARG_DUMMY -1
+#define V2D_ARG_DUMMY -1
/* Grid units */
enum eView2D_Units {
- /* for drawing time */
- V2D_UNIT_SECONDS = 0,
- V2D_UNIT_FRAMES,
- V2D_UNIT_FRAMESCALE,
+ /* for drawing time */
+ V2D_UNIT_SECONDS = 0,
+ V2D_UNIT_FRAMES,
+ V2D_UNIT_FRAMESCALE,
- /* for drawing values */
- V2D_UNIT_VALUES,
+ /* for drawing values */
+ V2D_UNIT_VALUES,
};
/* clamping of grid values to whole numbers */
enum eView2D_Clamp {
- V2D_GRID_NOCLAMP = 0,
- V2D_GRID_CLAMP,
+ V2D_GRID_NOCLAMP = 0,
+ V2D_GRID_CLAMP,
};
/* flags for grid-lines to draw */
enum eView2D_Gridlines {
- V2D_HORIZONTAL_LINES = (1 << 0),
- V2D_VERTICAL_LINES = (1 << 1),
- V2D_HORIZONTAL_AXIS = (1 << 2),
- V2D_VERTICAL_AXIS = (1 << 3),
- V2D_HORIZONTAL_FINELINES = (1 << 4),
-
- V2D_GRIDLINES_MAJOR = (V2D_VERTICAL_LINES | V2D_VERTICAL_AXIS | V2D_HORIZONTAL_LINES | V2D_HORIZONTAL_AXIS),
- V2D_GRIDLINES_ALL = (V2D_GRIDLINES_MAJOR | V2D_HORIZONTAL_FINELINES),
+ V2D_HORIZONTAL_LINES = (1 << 0),
+ V2D_VERTICAL_LINES = (1 << 1),
+ V2D_HORIZONTAL_AXIS = (1 << 2),
+ V2D_VERTICAL_AXIS = (1 << 3),
+ V2D_HORIZONTAL_FINELINES = (1 << 4),
+
+ V2D_GRIDLINES_MAJOR = (V2D_VERTICAL_LINES | V2D_VERTICAL_AXIS | V2D_HORIZONTAL_LINES |
+ V2D_HORIZONTAL_AXIS),
+ V2D_GRIDLINES_ALL = (V2D_GRIDLINES_MAJOR | V2D_HORIZONTAL_FINELINES),
};
/* ------ Defines for Scrollers ----- */
/* scroller area */
-#define V2D_SCROLL_HEIGHT (0.45f * U.widget_unit)
-#define V2D_SCROLL_WIDTH (0.45f * U.widget_unit)
+#define V2D_SCROLL_HEIGHT (0.45f * U.widget_unit)
+#define V2D_SCROLL_WIDTH (0.45f * U.widget_unit)
/* For scrollers with scale markings (text written onto them) */
#define V2D_SCROLL_HEIGHT_TEXT (0.79f * U.widget_unit)
-#define V2D_SCROLL_WIDTH_TEXT (0.79f * U.widget_unit)
+#define V2D_SCROLL_WIDTH_TEXT (0.79f * U.widget_unit)
/* scroller 'handles' hotspot radius for mouse */
-#define V2D_SCROLLER_HANDLE_SIZE (0.6f * U.widget_unit)
+#define V2D_SCROLLER_HANDLE_SIZE (0.6f * U.widget_unit)
/* ------ Define for UI_view2d_sync ----- */
/* means copy it from another v2d */
-#define V2D_LOCK_SET 0
+#define V2D_LOCK_SET 0
/* means copy it to the other v2ds */
-#define V2D_LOCK_COPY 1
-
+#define V2D_LOCK_COPY 1
/* ------------------------------------------ */
/* Macros: */
/* test if mouse in a scrollbar (assume that scroller availability has been tested) */
-#define IN_2D_VERT_SCROLL(v2d, co) (BLI_rcti_isect_pt_v(&v2d->vert, co))
-#define IN_2D_HORIZ_SCROLL(v2d, co) (BLI_rcti_isect_pt_v(&v2d->hor, co))
+#define IN_2D_VERT_SCROLL(v2d, co) (BLI_rcti_isect_pt_v(&v2d->vert, co))
+#define IN_2D_HORIZ_SCROLL(v2d, co) (BLI_rcti_isect_pt_v(&v2d->hor, co))
/* ------------------------------------------ */
/* Type definitions: */
@@ -161,53 +161,99 @@ void UI_view2d_view_orthoSpecial(struct ARegion *ar, struct View2D *v2d, const b
void UI_view2d_view_restore(const struct bContext *C);
/* grid drawing */
-View2DGrid *UI_view2d_grid_calc(struct Scene *scene, struct View2D *v2d,
- short xunits, short xclamp, short yunits, short yclamp, int winx, int winy);
+View2DGrid *UI_view2d_grid_calc(struct Scene *scene,
+ struct View2D *v2d,
+ short xunits,
+ short xclamp,
+ short yunits,
+ short yclamp,
+ int winx,
+ int winy);
void UI_view2d_grid_draw(struct View2D *v2d, View2DGrid *grid, int flag);
void UI_view2d_constant_grid_draw(struct View2D *v2d, float step);
-void UI_view2d_multi_grid_draw(struct View2D *v2d, int colorid, float step, int level_size, int totlevels);
+void UI_view2d_multi_grid_draw(
+ struct View2D *v2d, int colorid, float step, int level_size, int totlevels);
void UI_view2d_grid_size(View2DGrid *grid, float *r_dx, float *r_dy);
-void UI_view2d_grid_draw_numbers_horizontal(const struct Scene *scene, const struct View2D *v2d,
- const View2DGrid *grid, const struct rcti *rect,
- int unit, bool whole_numbers_only);
-void UI_view2d_grid_draw_numbers_vertical(const struct Scene *scene, const struct View2D *v2d,
- const View2DGrid *grid, const struct rcti *rect,
- int unit, float text_offset);
+void UI_view2d_grid_draw_numbers_horizontal(const struct Scene *scene,
+ const struct View2D *v2d,
+ const View2DGrid *grid,
+ const struct rcti *rect,
+ int unit,
+ bool whole_numbers_only);
+void UI_view2d_grid_draw_numbers_vertical(const struct Scene *scene,
+ const struct View2D *v2d,
+ const View2DGrid *grid,
+ const struct rcti *rect,
+ int unit,
+ float text_offset);
void UI_view2d_grid_free(View2DGrid *grid);
/* scrollbar drawing */
-View2DScrollers *UI_view2d_scrollers_calc(
- const struct bContext *C, struct View2D *v2d, const struct rcti *mask_custom,
- short xunits, short xclamp, short yunits, short yclamp);
-void UI_view2d_scrollers_draw(const struct bContext *C, struct View2D *v2d, View2DScrollers *scrollers);
+View2DScrollers *UI_view2d_scrollers_calc(const struct bContext *C,
+ struct View2D *v2d,
+ const struct rcti *mask_custom,
+ short xunits,
+ short xclamp,
+ short yunits,
+ short yclamp);
+void UI_view2d_scrollers_draw(const struct bContext *C,
+ struct View2D *v2d,
+ View2DScrollers *scrollers);
void UI_view2d_scrollers_free(View2DScrollers *scrollers);
/* list view tools */
-void UI_view2d_listview_cell_to_view(struct View2D *v2d, float columnwidth, float rowheight,
- float startx, float starty, int column, int row,
+void UI_view2d_listview_cell_to_view(struct View2D *v2d,
+ float columnwidth,
+ float rowheight,
+ float startx,
+ float starty,
+ int column,
+ int row,
struct rctf *rect);
-void UI_view2d_listview_view_to_cell(struct View2D *v2d, float columnwidth, float rowheight,
- float startx, float starty, float viewx, float viewy,
- int *column, int *row);
-void UI_view2d_listview_visible_cells(struct View2D *v2d, float columnwidth, float rowheight,
- float startx, float starty, int *column_min, int *column_max,
- int *row_min, int *row_max);
+void UI_view2d_listview_view_to_cell(struct View2D *v2d,
+ float columnwidth,
+ float rowheight,
+ float startx,
+ float starty,
+ float viewx,
+ float viewy,
+ int *column,
+ int *row);
+void UI_view2d_listview_visible_cells(struct View2D *v2d,
+ float columnwidth,
+ float rowheight,
+ float startx,
+ float starty,
+ int *column_min,
+ int *column_max,
+ int *row_min,
+ int *row_max);
/* coordinate conversion */
float UI_view2d_region_to_view_x(const struct View2D *v2d, float x);
float UI_view2d_region_to_view_y(const struct View2D *v2d, float y);
-void UI_view2d_region_to_view(const struct View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL();
-void UI_view2d_region_to_view_rctf(const struct View2D *v2d, const struct rctf *rect_src, struct rctf *rect_dst) ATTR_NONNULL();
+void UI_view2d_region_to_view(
+ const struct View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL();
+void UI_view2d_region_to_view_rctf(const struct View2D *v2d,
+ const struct rctf *rect_src,
+ struct rctf *rect_dst) ATTR_NONNULL();
float UI_view2d_view_to_region_x(const struct View2D *v2d, float x);
float UI_view2d_view_to_region_y(const struct View2D *v2d, float y);
-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 rctf *rect_src, struct rcti *rect_dst) ATTR_NONNULL();
-bool UI_view2d_view_to_region_rcti_clip(struct View2D *v2d, const struct rctf *rect_src, struct rcti *rect_dst) ATTR_NONNULL();
+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 rctf *rect_src,
+ struct rcti *rect_dst) ATTR_NONNULL();
+bool UI_view2d_view_to_region_rcti_clip(struct View2D *v2d,
+ const struct rctf *rect_src,
+ struct rcti *rect_dst) ATTR_NONNULL();
/* utilities */
struct View2D *UI_view2d_fromcontext(const struct bContext *C);
@@ -224,24 +270,30 @@ 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 View2D *v2d, int x, int y);
+ 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 View2D *v2d,
+ int x,
+ int y);
/* 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_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_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_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);
/* operators */
void ED_operatortypes_view2d(void);
void ED_keymap_view2d(struct wmKeyConfig *keyconf);
-void UI_view2d_smooth_view(struct bContext *C, struct ARegion *ar,
- const struct rctf *cur, const int smooth_viewtx);
+void UI_view2d_smooth_view(struct bContext *C,
+ struct ARegion *ar,
+ const struct rctf *cur,
+ const int smooth_viewtx);
#define UI_MARKER_MARGIN_Y (42 * UI_DPI_FAC)
#endif /* __UI_VIEW2D_H__ */
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index fd6b0e4a0c5..622f89b1f87 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -16,95 +16,95 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenfont
- ../../blenkernel
- ../../blenlib
- ../../blenloader
- ../../blentranslation
- ../../depsgraph
- ../../draw
- ../../gpu
- ../../imbuf
- ../../makesdna
- ../../makesrna
- ../../python
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenfont
+ ../../blenkernel
+ ../../blenlib
+ ../../blenloader
+ ../../blentranslation
+ ../../depsgraph
+ ../../draw
+ ../../gpu
+ ../../imbuf
+ ../../makesdna
+ ../../makesrna
+ ../../python
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- interface.c
- interface_align.c
- interface_anim.c
- interface_context_menu.c
- interface_draw.c
- interface_eyedropper.c
- interface_eyedropper_color.c
- interface_eyedropper_colorband.c
- interface_eyedropper_datablock.c
- interface_eyedropper_depth.c
- interface_eyedropper_driver.c
- interface_handlers.c
- interface_icons.c
- interface_icons_event.c
- interface_layout.c
- interface_ops.c
- interface_panel.c
- interface_query.c
- interface_region_color_picker.c
- interface_region_hud.c
- interface_region_menu_pie.c
- interface_region_menu_popup.c
- interface_region_popover.c
- interface_region_popup.c
- interface_region_search.c
- interface_region_tooltip.c
- interface_regions.c
- interface_style.c
- interface_templates.c
- interface_utils.c
- interface_widgets.c
- resources.c
- view2d.c
- view2d_ops.c
+ interface.c
+ interface_align.c
+ interface_anim.c
+ interface_context_menu.c
+ interface_draw.c
+ interface_eyedropper.c
+ interface_eyedropper_color.c
+ interface_eyedropper_colorband.c
+ interface_eyedropper_datablock.c
+ interface_eyedropper_depth.c
+ interface_eyedropper_driver.c
+ interface_handlers.c
+ interface_icons.c
+ interface_icons_event.c
+ interface_layout.c
+ interface_ops.c
+ interface_panel.c
+ interface_query.c
+ interface_region_color_picker.c
+ interface_region_hud.c
+ interface_region_menu_pie.c
+ interface_region_menu_popup.c
+ interface_region_popover.c
+ interface_region_popup.c
+ interface_region_search.c
+ interface_region_tooltip.c
+ interface_regions.c
+ interface_style.c
+ interface_templates.c
+ interface_utils.c
+ interface_widgets.c
+ resources.c
+ view2d.c
+ view2d_ops.c
- interface_eyedropper_intern.h
- interface_intern.h
- interface_regions_intern.h
+ interface_eyedropper_intern.h
+ interface_intern.h
+ interface_regions_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
- bf_editor_datafiles
+ bf_blenkernel
+ bf_blenlib
+ bf_editor_datafiles
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
if(WITH_HEADLESS)
- add_definitions(-DWITH_HEADLESS)
+ add_definitions(-DWITH_HEADLESS)
endif()
if(WITH_CYCLES)
- add_definitions(-DWITH_CYCLES)
+ add_definitions(-DWITH_CYCLES)
endif()
if(WITH_PYTHON)
- add_definitions(-DWITH_PYTHON)
+ add_definitions(-DWITH_PYTHON)
endif()
if(WIN32)
- if(WITH_INPUT_IME)
- add_definitions(-DWITH_INPUT_IME)
- endif()
+ if(WITH_INPUT_IME)
+ add_definitions(-DWITH_INPUT_IME)
+ endif()
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index b76be4cf4d8..06b0634f6fb 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -21,13 +21,12 @@
* \ingroup edinterface
*/
-
#include <float.h>
#include <limits.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
-#include <stddef.h> /* offsetof() */
+#include <stddef.h> /* offsetof() */
#include "MEM_guardedalloc.h"
@@ -83,7 +82,10 @@
#include "interface_intern.h"
/* prototypes. */
-static void ui_but_to_pixelrect(struct rcti *rect, const struct ARegion *ar, struct uiBlock *block, struct uiBut *but);
+static void ui_but_to_pixelrect(struct rcti *rect,
+ const struct ARegion *ar,
+ struct uiBlock *block,
+ struct uiBut *but);
static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *but_p);
static void ui_def_but_rna__panel_type(bContext *UNUSED(C), uiLayout *layout, void *but_p);
static void ui_def_but_rna__menu_type(bContext *UNUSED(C), uiLayout *layout, void *but_p);
@@ -91,222 +93,225 @@ static void ui_def_but_rna__menu_type(bContext *UNUSED(C), uiLayout *layout, voi
/* avoid unneeded calls to ui_but_value_get */
#define UI_BUT_VALUE_UNSET DBL_MAX
#define UI_GET_BUT_VALUE_INIT(_but, _value) \
- if (_value == DBL_MAX) { \
- (_value) = ui_but_value_get(_but); \
- } ((void)0)
+ if (_value == DBL_MAX) { \
+ (_value) = ui_but_value_get(_but); \
+ } \
+ ((void)0)
#define B_NOP -1
/**
* a full doc with API notes can be found in 'blender/doc/guides/interface_API.txt'
*
- * `uiBlahBlah()` external function.
- * `ui_blah_blah()` internal function.
+ * `uiBlahBlah()` external function.
+ * `ui_blah_blah()` internal function.
*/
static void ui_but_free(const bContext *C, uiBut *but);
static bool ui_but_is_unit_radians_ex(UnitSettings *unit, const int unit_type)
{
- return (unit->system_rotation == USER_UNIT_ROT_RADIANS && unit_type == PROP_UNIT_ROTATION);
+ return (unit->system_rotation == USER_UNIT_ROT_RADIANS && unit_type == PROP_UNIT_ROTATION);
}
static bool ui_but_is_unit_radians(const uiBut *but)
{
- UnitSettings *unit = but->block->unit;
- const int unit_type = UI_but_unit_type_get(but);
+ UnitSettings *unit = but->block->unit;
+ const int unit_type = UI_but_unit_type_get(but);
- return ui_but_is_unit_radians_ex(unit, unit_type);
+ return ui_but_is_unit_radians_ex(unit, unit_type);
}
/* ************* window matrix ************** */
void ui_block_to_window_fl(const ARegion *ar, uiBlock *block, float *x, float *y)
{
- float gx, gy;
- int sx, sy, getsizex, getsizey;
+ 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(&ar->winrct) + 1;
+ getsizey = BLI_rcti_size_y(&ar->winrct) + 1;
+ sx = ar->winrct.xmin;
+ sy = ar->winrct.ymin;
- gx = *x;
- gy = *y;
+ gx = *x;
+ gy = *y;
- if (block->panel) {
- gx += block->panel->ofsx;
- gy += block->panel->ofsy;
- }
+ if (block->panel) {
+ gx += block->panel->ofsx;
+ gy += block->panel->ofsy;
+ }
- *x = ((float)sx) + ((float)getsizex) * (0.5f + 0.5f * (gx * block->winmat[0][0] + gy * block->winmat[1][0] + block->winmat[3][0]));
- *y = ((float)sy) + ((float)getsizey) * (0.5f + 0.5f * (gx * block->winmat[0][1] + gy * block->winmat[1][1] + block->winmat[3][1]));
+ *x = ((float)sx) +
+ ((float)getsizex) * (0.5f + 0.5f * (gx * block->winmat[0][0] + gy * block->winmat[1][0] +
+ block->winmat[3][0]));
+ *y = ((float)sy) +
+ ((float)getsizey) * (0.5f + 0.5f * (gx * block->winmat[0][1] + gy * block->winmat[1][1] +
+ block->winmat[3][1]));
}
void ui_block_to_window(const ARegion *ar, uiBlock *block, int *x, int *y)
{
- float fx, fy;
+ float fx, fy;
- fx = *x;
- fy = *y;
+ fx = *x;
+ fy = *y;
- ui_block_to_window_fl(ar, block, &fx, &fy);
+ ui_block_to_window_fl(ar, block, &fx, &fy);
- *x = (int)(fx + 0.5f);
- *y = (int)(fy + 0.5f);
+ *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)
{
- *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);
+ *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);
}
float ui_block_to_window_scale(const ARegion *ar, 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);
- dummy_x = 0.0f;
- ui_block_to_window_fl(ar, block, &dummy_x, &max_y);
- return max_y - min_y;
+ /* 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);
+ dummy_x = 0.0f;
+ ui_block_to_window_fl(ar, 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)
{
- float a, b, c, d, e, f, px, py;
- int sx, sy, getsizex, getsizey;
+ 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(&ar->winrct) + 1;
+ getsizey = BLI_rcti_size_y(&ar->winrct) + 1;
+ sx = ar->winrct.xmin;
+ sy = ar->winrct.ymin;
- a = 0.5f * ((float)getsizex) * block->winmat[0][0];
- b = 0.5f * ((float)getsizex) * block->winmat[1][0];
- c = 0.5f * ((float)getsizex) * (1.0f + block->winmat[3][0]);
+ a = 0.5f * ((float)getsizex) * block->winmat[0][0];
+ b = 0.5f * ((float)getsizex) * block->winmat[1][0];
+ c = 0.5f * ((float)getsizex) * (1.0f + block->winmat[3][0]);
- d = 0.5f * ((float)getsizey) * block->winmat[0][1];
- e = 0.5f * ((float)getsizey) * block->winmat[1][1];
- f = 0.5f * ((float)getsizey) * (1.0f + block->winmat[3][1]);
+ d = 0.5f * ((float)getsizey) * block->winmat[0][1];
+ e = 0.5f * ((float)getsizey) * block->winmat[1][1];
+ f = 0.5f * ((float)getsizey) * (1.0f + block->winmat[3][1]);
- px = *x - sx;
- py = *y - sy;
+ px = *x - sx;
+ py = *y - sy;
- *y = (a * (py - f) + d * (c - px)) / (a * e - d * b);
- *x = (px - b * (*y) - c) / a;
+ *y = (a * (py - f) + d * (c - px)) / (a * e - d * b);
+ *x = (px - b * (*y) - c) / a;
- if (block->panel) {
- *x -= block->panel->ofsx;
- *y -= block->panel->ofsy;
- }
+ if (block->panel) {
+ *x -= block->panel->ofsx;
+ *y -= block->panel->ofsy;
+ }
}
void ui_window_to_block(const ARegion *ar, uiBlock *block, int *x, int *y)
{
- float fx, fy;
+ float fx, fy;
- fx = *x;
- fy = *y;
+ fx = *x;
+ fy = *y;
- ui_window_to_block_fl(ar, block, &fx, &fy);
+ ui_window_to_block_fl(ar, block, &fx, &fy);
- *x = (int)(fx + 0.5f);
- *y = (int)(fy + 0.5f);
+ *x = (int)(fx + 0.5f);
+ *y = (int)(fy + 0.5f);
}
void ui_window_to_region(const ARegion *ar, int *x, int *y)
{
- *x -= ar->winrct.xmin;
- *y -= ar->winrct.ymin;
+ *x -= ar->winrct.xmin;
+ *y -= ar->winrct.ymin;
}
void ui_region_to_window(const ARegion *ar, int *x, int *y)
{
- *x += ar->winrct.xmin;
- *y += ar->winrct.ymin;
+ *x += ar->winrct.xmin;
+ *y += ar->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) {
- if (but->type == UI_BTYPE_SEPR_SPACER) {
- sepr_flex_len++;
- }
- }
-
- if (sepr_flex_len == 0) {
- return;
- }
-
- rcti rect;
- ui_but_to_pixelrect(&rect, region, block, block->buttons.last);
- const float buttons_width = (float)rect.xmax + UI_HEADER_OFFSET;
- const float region_width = (float)region->sizex * U.dpi_fac;
-
- if (region_width <= buttons_width) {
- return;
- }
-
- /* 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) {
- if (but->type == UI_BTYPE_SEPR_SPACER) {
- ui_but_to_pixelrect(&rect, region, block, but);
- spacers_pos[i] = rect.xmax + UI_HEADER_OFFSET;
- i++;
- }
- }
-
- 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) {
- BLI_rctf_translate(&but->rect, offset, 0);
- if (but->type == UI_BTYPE_SEPR_SPACER) {
- /* How much the next block overlap with the current segment */
- int overlap = (
- (i == sepr_flex_len - 1) ?
- buttons_width - spacers_pos[i] :
- (spacers_pos[i + 1] - spacers_pos[i]) / 2);
- int segment_end = segment_width * (i + 1);
- int spacer_end = segment_end - overlap;
- int spacer_sta = spacers_pos[i] + offset;
- if (spacer_end > spacer_sta) {
- float step = min_ff(remaining_space, spacer_end - spacer_sta);
- remaining_space -= step;
- offset += step;
- }
- i++;
- }
- }
- ui_block_bounds_calc(block);
+ int sepr_flex_len = 0;
+ for (uiBut *but = block->buttons.first; but; but = but->next) {
+ if (but->type == UI_BTYPE_SEPR_SPACER) {
+ sepr_flex_len++;
+ }
+ }
+
+ if (sepr_flex_len == 0) {
+ return;
+ }
+
+ rcti rect;
+ ui_but_to_pixelrect(&rect, region, block, block->buttons.last);
+ const float buttons_width = (float)rect.xmax + UI_HEADER_OFFSET;
+ const float region_width = (float)region->sizex * U.dpi_fac;
+
+ if (region_width <= buttons_width) {
+ return;
+ }
+
+ /* 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) {
+ if (but->type == UI_BTYPE_SEPR_SPACER) {
+ ui_but_to_pixelrect(&rect, region, block, but);
+ spacers_pos[i] = rect.xmax + UI_HEADER_OFFSET;
+ i++;
+ }
+ }
+
+ 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) {
+ BLI_rctf_translate(&but->rect, offset, 0);
+ if (but->type == UI_BTYPE_SEPR_SPACER) {
+ /* How much the next block overlap with the current segment */
+ int overlap = ((i == sepr_flex_len - 1) ? buttons_width - spacers_pos[i] :
+ (spacers_pos[i + 1] - spacers_pos[i]) / 2);
+ int segment_end = segment_width * (i + 1);
+ int spacer_end = segment_end - overlap;
+ int spacer_sta = spacers_pos[i] + offset;
+ if (spacer_end > spacer_sta) {
+ float step = min_ff(remaining_space, spacer_end - spacer_sta);
+ remaining_space -= step;
+ offset += step;
+ }
+ i++;
+ }
+ }
+ ui_block_bounds_calc(block);
}
static void ui_update_window_matrix(const wmWindow *window, const ARegion *region, uiBlock *block)
{
- /* window matrix and aspect */
- if (region && region->visible) {
- /* Get projection matrix which includes View2D translation and zoom. */
- GPU_matrix_projection_get(block->winmat);
- block->aspect = 2.0f / fabsf(region->winx * block->winmat[0][0]);
- }
- else {
- /* No subwindow created yet, for menus for example, so we use the main
- * window instead, since buttons are created there anyway. */
- int width = WM_window_pixels_x(window);
- int height = WM_window_pixels_y(window);
- rcti winrct = {0, width - 1, 0, height - 1};
+ /* window matrix and aspect */
+ if (region && region->visible) {
+ /* Get projection matrix which includes View2D translation and zoom. */
+ GPU_matrix_projection_get(block->winmat);
+ block->aspect = 2.0f / fabsf(region->winx * block->winmat[0][0]);
+ }
+ else {
+ /* No subwindow created yet, for menus for example, so we use the main
+ * window instead, since buttons are created there anyway. */
+ int width = WM_window_pixels_x(window);
+ int height = WM_window_pixels_y(window);
+ rcti winrct = {0, width - 1, 0, height - 1};
- wmGetProjectionMatrix(block->winmat, &winrct);
- block->aspect = 2.0f / fabsf(width * block->winmat[0][0]);
- }
+ wmGetProjectionMatrix(block->winmat, &winrct);
+ block->aspect = 2.0f / fabsf(width * block->winmat[0][0]);
+ }
}
/**
@@ -315,303 +320,303 @@ static void ui_update_window_matrix(const wmWindow *window, const ARegion *regio
*/
void ui_region_winrct_get_no_margin(const struct ARegion *ar, struct rcti *r_rect)
{
- uiBlock *block = ar->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);
- }
- else {
- *r_rect = ar->winrct;
- }
+ uiBlock *block = ar->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);
+ }
+ else {
+ *r_rect = ar->winrct;
+ }
}
/* ******************* block calc ************************* */
void UI_block_translate(uiBlock *block, int x, int y)
{
- uiBut *but;
+ uiBut *but;
- for (but = block->buttons.first; but; but = but->next) {
- BLI_rctf_translate(&but->rect, x, y);
- }
+ for (but = block->buttons.first; but; but = but->next) {
+ BLI_rctf_translate(&but->rect, x, y);
+ }
- BLI_rctf_translate(&block->rect, x, y);
+ BLI_rctf_translate(&block->rect, x, y);
}
static void ui_block_bounds_calc_text(uiBlock *block, float offset)
{
- uiStyle *style = UI_style_get();
- uiBut *bt, *init_col_bt, *col_bt;
- int i = 0, j, x1addval = offset;
+ uiStyle *style = UI_style_get();
+ uiBut *bt, *init_col_bt, *col_bt;
+ int i = 0, j, x1addval = offset;
- UI_fontstyle_set(&style->widget);
+ UI_fontstyle_set(&style->widget);
- for (init_col_bt = bt = block->buttons.first; bt; bt = bt->next) {
- if (!ELEM(bt->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_SEPR_SPACER)) {
- j = BLF_width(style->widget.uifont_id, bt->drawstr, sizeof(bt->drawstr));
+ for (init_col_bt = bt = block->buttons.first; bt; bt = bt->next) {
+ if (!ELEM(bt->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_SEPR_SPACER)) {
+ j = BLF_width(style->widget.uifont_id, bt->drawstr, sizeof(bt->drawstr));
- if (j > i) {
- i = j;
- }
- }
+ if (j > i) {
+ i = j;
+ }
+ }
- if (bt->next && bt->rect.xmin < bt->next->rect.xmin) {
- /* End of this column, and it's not the last one. */
- for (col_bt = init_col_bt; col_bt->prev != bt; col_bt = col_bt->next) {
- col_bt->rect.xmin = x1addval;
- col_bt->rect.xmax = x1addval + i + block->bounds;
+ if (bt->next && bt->rect.xmin < bt->next->rect.xmin) {
+ /* End of this column, and it's not the last one. */
+ for (col_bt = init_col_bt; col_bt->prev != bt; col_bt = col_bt->next) {
+ col_bt->rect.xmin = x1addval;
+ col_bt->rect.xmax = x1addval + i + block->bounds;
- ui_but_update(col_bt); /* clips text again */
- }
+ ui_but_update(col_bt); /* clips text again */
+ }
- /* And we prepare next column. */
- x1addval += i + block->bounds;
- i = 0;
- init_col_bt = col_bt;
- }
- }
+ /* And we prepare next column. */
+ x1addval += i + block->bounds;
+ i = 0;
+ init_col_bt = col_bt;
+ }
+ }
- /* Last column. */
- for (col_bt = init_col_bt; col_bt; col_bt = col_bt->next) {
- col_bt->rect.xmin = x1addval;
- col_bt->rect.xmax = max_ff(x1addval + i + block->bounds, offset + block->minbounds);
+ /* Last column. */
+ for (col_bt = init_col_bt; col_bt; col_bt = col_bt->next) {
+ col_bt->rect.xmin = x1addval;
+ col_bt->rect.xmax = max_ff(x1addval + i + block->bounds, offset + block->minbounds);
- ui_but_update(col_bt); /* clips text again */
- }
+ ui_but_update(col_bt); /* clips text again */
+ }
}
void ui_block_bounds_calc(uiBlock *block)
{
- uiBut *bt;
- int xof;
+ uiBut *bt;
+ int xof;
- if (BLI_listbase_is_empty(&block->buttons)) {
- if (block->panel) {
- block->rect.xmin = 0.0; block->rect.xmax = block->panel->sizex;
- block->rect.ymin = 0.0; block->rect.ymax = block->panel->sizey;
- }
- }
- else {
+ if (BLI_listbase_is_empty(&block->buttons)) {
+ if (block->panel) {
+ block->rect.xmin = 0.0;
+ block->rect.xmax = block->panel->sizex;
+ block->rect.ymin = 0.0;
+ block->rect.ymax = block->panel->sizey;
+ }
+ }
+ else {
- BLI_rctf_init_minmax(&block->rect);
+ BLI_rctf_init_minmax(&block->rect);
- for (bt = block->buttons.first; bt; bt = bt->next) {
- BLI_rctf_union(&block->rect, &bt->rect);
- }
+ for (bt = block->buttons.first; bt; bt = bt->next) {
+ BLI_rctf_union(&block->rect, &bt->rect);
+ }
- block->rect.xmin -= block->bounds;
- block->rect.ymin -= block->bounds;
- block->rect.xmax += block->bounds;
- block->rect.ymax += block->bounds;
- }
+ block->rect.xmin -= block->bounds;
+ block->rect.ymin -= block->bounds;
+ block->rect.xmax += block->bounds;
+ block->rect.ymax += block->bounds;
+ }
- block->rect.xmax = block->rect.xmin + max_ff(BLI_rctf_size_x(&block->rect), block->minbounds);
+ block->rect.xmax = block->rect.xmin + max_ff(BLI_rctf_size_x(&block->rect), block->minbounds);
- /* hardcoded exception... but that one is annoying with larger safety */
- bt = block->buttons.first;
- if (bt && STREQLEN(bt->str, "ERROR", 5)) {
- xof = 10;
- }
- else {
- xof = 40;
- }
+ /* hardcoded exception... but that one is annoying with larger safety */
+ bt = block->buttons.first;
+ if (bt && STREQLEN(bt->str, "ERROR", 5)) {
+ xof = 10;
+ }
+ else {
+ xof = 40;
+ }
- block->safety.xmin = block->rect.xmin - xof;
- block->safety.ymin = block->rect.ymin - xof;
- block->safety.xmax = block->rect.xmax + xof;
- block->safety.ymax = block->rect.ymax + xof;
+ block->safety.xmin = block->rect.xmin - xof;
+ block->safety.ymin = block->rect.ymin - xof;
+ block->safety.xmax = block->rect.xmax + xof;
+ block->safety.ymax = block->rect.ymax + xof;
}
static void ui_block_bounds_calc_centered(wmWindow *window, uiBlock *block)
{
- int xmax, ymax;
- int startx, starty;
- int width, height;
-
- /* note: this is used for the splash where window bounds event has not been
- * updated by ghost, get the window bounds from ghost directly */
+ int xmax, ymax;
+ int startx, starty;
+ int width, height;
- xmax = WM_window_pixels_x(window);
- ymax = WM_window_pixels_y(window);
+ /* note: this is used for the splash where window bounds event has not been
+ * updated by ghost, get the window bounds from ghost directly */
- ui_block_bounds_calc(block);
+ xmax = WM_window_pixels_x(window);
+ ymax = WM_window_pixels_y(window);
- width = BLI_rctf_size_x(&block->rect);
- height = BLI_rctf_size_y(&block->rect);
+ ui_block_bounds_calc(block);
- startx = (xmax * 0.5f) - (width * 0.5f);
- starty = (ymax * 0.5f) - (height * 0.5f);
+ width = BLI_rctf_size_x(&block->rect);
+ height = BLI_rctf_size_y(&block->rect);
- UI_block_translate(block, startx - block->rect.xmin, starty - block->rect.ymin);
+ startx = (xmax * 0.5f) - (width * 0.5f);
+ starty = (ymax * 0.5f) - (height * 0.5f);
- /* now recompute bounds and safety */
- ui_block_bounds_calc(block);
+ UI_block_translate(block, startx - block->rect.xmin, starty - block->rect.ymin);
+ /* now recompute bounds and safety */
+ ui_block_bounds_calc(block);
}
static void ui_block_bounds_calc_centered_pie(uiBlock *block)
{
- const int xy[2] = {
- block->pie_data.pie_center_spawned[0],
- block->pie_data.pie_center_spawned[1],
- };
+ const int xy[2] = {
+ block->pie_data.pie_center_spawned[0],
+ block->pie_data.pie_center_spawned[1],
+ };
- UI_block_translate(block, xy[0], xy[1]);
+ UI_block_translate(block, xy[0], xy[1]);
- /* now recompute bounds and safety */
- ui_block_bounds_calc(block);
+ /* now recompute bounds and safety */
+ ui_block_bounds_calc(block);
}
static void ui_block_bounds_calc_popup(
- wmWindow *window, uiBlock *block,
- eBlockBoundsCalc bounds_calc, const int xy[2], int r_xy[2])
+ wmWindow *window, uiBlock *block, eBlockBoundsCalc bounds_calc, const int xy[2], int r_xy[2])
{
- int width, height, oldwidth, oldheight;
- int oldbounds, xmax, ymax, raw_x, raw_y;
- const int margin = UI_SCREEN_MARGIN;
- rcti rect, rect_bounds;
- int ofs_dummy[2];
+ int width, height, oldwidth, oldheight;
+ int oldbounds, xmax, ymax, raw_x, raw_y;
+ const int margin = UI_SCREEN_MARGIN;
+ rcti rect, rect_bounds;
+ int ofs_dummy[2];
- oldbounds = block->bounds;
+ oldbounds = block->bounds;
- /* compute mouse position with user defined offset */
- ui_block_bounds_calc(block);
+ /* compute mouse position with user defined offset */
+ ui_block_bounds_calc(block);
- xmax = WM_window_pixels_x(window);
- ymax = WM_window_pixels_y(window);
+ xmax = WM_window_pixels_x(window);
+ ymax = WM_window_pixels_y(window);
- oldwidth = BLI_rctf_size_x(&block->rect);
- oldheight = BLI_rctf_size_y(&block->rect);
+ oldwidth = BLI_rctf_size_x(&block->rect);
+ oldheight = BLI_rctf_size_y(&block->rect);
- /* first we ensure wide enough text bounds */
- if (bounds_calc == UI_BLOCK_BOUNDS_POPUP_MENU) {
- if (block->flag & UI_BLOCK_LOOP) {
- block->bounds = 2.5f * UI_UNIT_X;
- ui_block_bounds_calc_text(block, block->rect.xmin);
- }
- }
+ /* first we ensure wide enough text bounds */
+ if (bounds_calc == UI_BLOCK_BOUNDS_POPUP_MENU) {
+ if (block->flag & UI_BLOCK_LOOP) {
+ block->bounds = 2.5f * UI_UNIT_X;
+ ui_block_bounds_calc_text(block, block->rect.xmin);
+ }
+ }
- /* next we recompute bounds */
- block->bounds = oldbounds;
- ui_block_bounds_calc(block);
+ /* next we recompute bounds */
+ block->bounds = oldbounds;
+ ui_block_bounds_calc(block);
- /* and we adjust the position to fit within window */
- width = BLI_rctf_size_x(&block->rect);
- height = BLI_rctf_size_y(&block->rect);
+ /* and we adjust the position to fit within window */
+ width = BLI_rctf_size_x(&block->rect);
+ height = BLI_rctf_size_y(&block->rect);
- /* avoid divide by zero below, caused by calling with no UI, but better not crash */
- oldwidth = oldwidth > 0 ? oldwidth : MAX2(1, width);
- oldheight = oldheight > 0 ? oldheight : MAX2(1, height);
+ /* avoid divide by zero below, caused by calling with no UI, but better not crash */
+ oldwidth = oldwidth > 0 ? oldwidth : MAX2(1, width);
+ oldheight = oldheight > 0 ? oldheight : MAX2(1, height);
- /* offset block based on mouse position, user offset is scaled
- * along in case we resized the block in ui_block_bounds_calc_text */
- raw_x = rect.xmin = xy[0] + block->rect.xmin + (block->bounds_offset[0] * width) / oldwidth;
- raw_y = rect.ymin = xy[1] + block->rect.ymin + (block->bounds_offset[1] * height) / oldheight;
- rect.xmax = rect.xmin + width;
- rect.ymax = rect.ymin + height;
+ /* offset block based on mouse position, user offset is scaled
+ * along in case we resized the block in ui_block_bounds_calc_text */
+ raw_x = rect.xmin = xy[0] + block->rect.xmin + (block->bounds_offset[0] * width) / oldwidth;
+ raw_y = rect.ymin = xy[1] + block->rect.ymin + (block->bounds_offset[1] * height) / oldheight;
+ rect.xmax = rect.xmin + width;
+ rect.ymax = rect.ymin + height;
- rect_bounds.xmin = margin;
- rect_bounds.ymin = margin;
- rect_bounds.xmax = xmax - margin;
- rect_bounds.ymax = ymax - UI_POPUP_MENU_TOP;
+ rect_bounds.xmin = margin;
+ rect_bounds.ymin = margin;
+ rect_bounds.xmax = xmax - margin;
+ rect_bounds.ymax = ymax - UI_POPUP_MENU_TOP;
- BLI_rcti_clamp(&rect, &rect_bounds, ofs_dummy);
- UI_block_translate(block, rect.xmin - block->rect.xmin, rect.ymin - block->rect.ymin);
+ BLI_rcti_clamp(&rect, &rect_bounds, ofs_dummy);
+ UI_block_translate(block, rect.xmin - block->rect.xmin, rect.ymin - block->rect.ymin);
- /* now recompute bounds and safety */
- ui_block_bounds_calc(block);
+ /* now recompute bounds and safety */
+ ui_block_bounds_calc(block);
- /* If given, adjust input coordinates such that they would generate real final popup position.
- * Needed to handle correctly floating panels once they have been dragged around,
- * see T52999. */
- if (r_xy) {
- r_xy[0] = xy[0] + block->rect.xmin - raw_x;
- r_xy[1] = xy[1] + block->rect.ymin - raw_y;
- }
+ /* If given, adjust input coordinates such that they would generate real final popup position.
+ * Needed to handle correctly floating panels once they have been dragged around,
+ * see T52999. */
+ if (r_xy) {
+ r_xy[0] = xy[0] + block->rect.xmin - raw_x;
+ r_xy[1] = xy[1] + block->rect.ymin - raw_y;
+ }
}
/* used for various cases */
void UI_block_bounds_set_normal(uiBlock *block, int addval)
{
- if (block == NULL) {
- return;
- }
+ if (block == NULL) {
+ return;
+ }
- block->bounds = addval;
- block->bounds_type = UI_BLOCK_BOUNDS;
+ block->bounds = addval;
+ block->bounds_type = UI_BLOCK_BOUNDS;
}
/* used for pulldowns */
void UI_block_bounds_set_text(uiBlock *block, int addval)
{
- block->bounds = addval;
- block->bounds_type = UI_BLOCK_BOUNDS_TEXT;
+ block->bounds = addval;
+ block->bounds_type = UI_BLOCK_BOUNDS_TEXT;
}
/* used for block popups */
void UI_block_bounds_set_popup(uiBlock *block, int addval, const int bounds_offset[2])
{
- block->bounds = addval;
- block->bounds_type = UI_BLOCK_BOUNDS_POPUP_MOUSE;
- if (bounds_offset != NULL) {
- block->bounds_offset[0] = bounds_offset[0];
- block->bounds_offset[1] = bounds_offset[1];
- }
- else {
- block->bounds_offset[0] = 0;
- block->bounds_offset[1] = 0;
- }
+ block->bounds = addval;
+ block->bounds_type = UI_BLOCK_BOUNDS_POPUP_MOUSE;
+ if (bounds_offset != NULL) {
+ block->bounds_offset[0] = bounds_offset[0];
+ block->bounds_offset[1] = bounds_offset[1];
+ }
+ else {
+ block->bounds_offset[0] = 0;
+ block->bounds_offset[1] = 0;
+ }
}
/* used for menu popups */
void UI_block_bounds_set_menu(uiBlock *block, int addval, const int bounds_offset[2])
{
- block->bounds = addval;
- block->bounds_type = UI_BLOCK_BOUNDS_POPUP_MENU;
- if (bounds_offset != NULL) {
- block->bounds_offset[0] = bounds_offset[0];
- block->bounds_offset[1] = bounds_offset[1];
- }
- else {
- block->bounds_offset[0] = 0;
- block->bounds_offset[1] = 0;
- }
+ block->bounds = addval;
+ block->bounds_type = UI_BLOCK_BOUNDS_POPUP_MENU;
+ if (bounds_offset != NULL) {
+ block->bounds_offset[0] = bounds_offset[0];
+ block->bounds_offset[1] = bounds_offset[1];
+ }
+ else {
+ block->bounds_offset[0] = 0;
+ block->bounds_offset[1] = 0;
+ }
}
/* used for centered popups, i.e. splash */
void UI_block_bounds_set_centered(uiBlock *block, int addval)
{
- block->bounds = addval;
- block->bounds_type = UI_BLOCK_BOUNDS_POPUP_CENTER;
+ block->bounds = addval;
+ block->bounds_type = UI_BLOCK_BOUNDS_POPUP_CENTER;
}
void UI_block_bounds_set_explicit(uiBlock *block, int minx, int miny, int maxx, int maxy)
{
- block->rect.xmin = minx;
- block->rect.ymin = miny;
- block->rect.xmax = maxx;
- block->rect.ymax = maxy;
- block->bounds_type = UI_BLOCK_BOUNDS_NONE;
+ block->rect.xmin = minx;
+ block->rect.ymin = miny;
+ block->rect.xmax = maxx;
+ block->rect.ymax = maxy;
+ block->bounds_type = UI_BLOCK_BOUNDS_NONE;
}
static int ui_but_calc_float_precision(uiBut *but, double value)
{
- int prec = (int)but->a2;
+ int prec = (int)but->a2;
- /* first check for various special cases:
- * * If button is radians, we want additional precision (see T39861).
- * * If prec is not set, we fallback to a simple default */
- if (ui_but_is_unit_radians(but) && prec < 5) {
- prec = 5;
- }
- else if (prec == -1) {
- prec = (but->hardmax < 10.001f) ? 3 : 2;
- }
- else {
- CLAMP(prec, 0, UI_PRECISION_FLOAT_MAX);
- }
+ /* first check for various special cases:
+ * * If button is radians, we want additional precision (see T39861).
+ * * If prec is not set, we fallback to a simple default */
+ if (ui_but_is_unit_radians(but) && prec < 5) {
+ prec = 5;
+ }
+ else if (prec == -1) {
+ prec = (but->hardmax < 10.001f) ? 3 : 2;
+ }
+ else {
+ CLAMP(prec, 0, UI_PRECISION_FLOAT_MAX);
+ }
- return UI_calc_float_precision(prec, value);
+ return UI_calc_float_precision(prec, value);
}
/* ************** BLOCK ENDING FUNCTION ************* */
@@ -619,187 +624,206 @@ static int ui_but_calc_float_precision(uiBut *but, double value)
/* NOTE: if but->poin is allocated memory for every defbut, things fail... */
static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut)
{
- /* various properties are being compared here, hopefully sufficient
- * to catch all cases, but it is simple to add more checks later */
- 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) { return false; }
- if (but->func != oldbut->func) { return false; }
- if (but->funcN != oldbut->funcN) { return false; }
- if (oldbut->func_arg1 != oldbut && but->func_arg1 != oldbut->func_arg1) { return false; }
- if (oldbut->func_arg2 != oldbut && but->func_arg2 != oldbut->func_arg2) { return false; }
- if (!but->funcN && ((but->poin != oldbut->poin && (uiBut *)oldbut->poin != oldbut) ||
- (but->pointype != oldbut->pointype))) { return false; }
- if (but->optype != oldbut->optype) { return false; }
-
- return true;
+ /* various properties are being compared here, hopefully sufficient
+ * to catch all cases, but it is simple to add more checks later */
+ 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) {
+ return false;
+ }
+ if (but->func != oldbut->func) {
+ return false;
+ }
+ if (but->funcN != oldbut->funcN) {
+ return false;
+ }
+ if (oldbut->func_arg1 != oldbut && but->func_arg1 != oldbut->func_arg1) {
+ return false;
+ }
+ if (oldbut->func_arg2 != oldbut && but->func_arg2 != oldbut->func_arg2) {
+ return false;
+ }
+ if (!but->funcN && ((but->poin != oldbut->poin && (uiBut *)oldbut->poin != oldbut) ||
+ (but->pointype != oldbut->pointype))) {
+ return false;
+ }
+ if (but->optype != oldbut->optype) {
+ return false;
+ }
+
+ return true;
}
uiBut *ui_but_find_old(uiBlock *block_old, const uiBut *but_new)
{
- uiBut *but_old;
- for (but_old = block_old->buttons.first; but_old; but_old = but_old->next) {
- if (ui_but_equals_old(but_new, but_old)) {
- break;
- }
- }
- return but_old;
+ uiBut *but_old;
+ for (but_old = block_old->buttons.first; but_old; but_old = but_old->next) {
+ if (ui_but_equals_old(but_new, but_old)) {
+ break;
+ }
+ }
+ return but_old;
}
uiBut *ui_but_find_new(uiBlock *block_new, const uiBut *but_old)
{
- uiBut *but_new;
- for (but_new = block_new->buttons.first; but_new; but_new = but_new->next) {
- if (ui_but_equals_old(but_new, but_old)) {
- break;
- }
- }
- return but_new;
+ uiBut *but_new;
+ for (but_new = block_new->buttons.first; but_new; but_new = but_new->next) {
+ if (ui_but_equals_old(but_new, but_old)) {
+ break;
+ }
+ }
+ return but_new;
}
/**
* \return true when \a but_p is set (only done for active buttons).
*/
-static bool ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut **but_p, uiBut **but_old_p)
+static bool ui_but_update_from_old_block(const bContext *C,
+ uiBlock *block,
+ uiBut **but_p,
+ uiBut **but_old_p)
{
- const int drawflag_copy = 0; /* None currently. */
-
- uiBlock *oldblock = block->oldblock;
- uiBut *oldbut = NULL, *but = *but_p;
- bool found_active = false;
+ const int drawflag_copy = 0; /* None currently. */
+ uiBlock *oldblock = block->oldblock;
+ uiBut *oldbut = NULL, *but = *but_p;
+ bool found_active = false;
#if 0
- /* simple/stupid - search every time */
- oldbut = ui_but_find_old(oldblock, but);
- (void)but_old_p;
+ /* simple/stupid - search every time */
+ oldbut = ui_but_find_old(oldblock, but);
+ (void)but_old_p;
#else
- BLI_assert(*but_old_p == NULL || BLI_findindex(&oldblock->buttons, *but_old_p) != -1);
-
- /* fastpath - avoid loop-in-loop, calling 'ui_but_find_old'
- * as long as old/new buttons are aligned */
- if (LIKELY(*but_old_p && ui_but_equals_old(but, *but_old_p))) {
- oldbut = *but_old_p;
- }
- else {
- /* fallback to block search */
- oldbut = ui_but_find_old(oldblock, but);
- }
- (*but_old_p) = oldbut ? oldbut->next : NULL;
+ BLI_assert(*but_old_p == NULL || BLI_findindex(&oldblock->buttons, *but_old_p) != -1);
+
+ /* fastpath - avoid loop-in-loop, calling 'ui_but_find_old'
+ * as long as old/new buttons are aligned */
+ if (LIKELY(*but_old_p && ui_but_equals_old(but, *but_old_p))) {
+ oldbut = *but_old_p;
+ }
+ else {
+ /* fallback to block search */
+ oldbut = ui_but_find_old(oldblock, but);
+ }
+ (*but_old_p) = oldbut ? oldbut->next : NULL;
#endif
+ if (!oldbut) {
+ return found_active;
+ }
- if (!oldbut) {
- return found_active;
- }
-
- if (oldbut->active) {
- /* flags from the buttons we want to refresh, may want to add more here... */
- const int flag_copy = UI_BUT_REDALERT | UI_HAS_ICON;
+ if (oldbut->active) {
+ /* flags from the buttons we want to refresh, may want to add more here... */
+ const int flag_copy = UI_BUT_REDALERT | UI_HAS_ICON;
- found_active = true;
+ found_active = true;
#if 0
- but->flag = oldbut->flag;
- but->active = oldbut->active;
- but->pos = oldbut->pos;
- but->ofs = oldbut->ofs;
- but->editstr = oldbut->editstr;
- but->editval = oldbut->editval;
- but->editvec = oldbut->editvec;
- but->editcoba = oldbut->editcoba;
- but->editcumap = oldbut->editcumap;
- but->selsta = oldbut->selsta;
- but->selend = oldbut->selend;
- but->softmin = oldbut->softmin;
- but->softmax = oldbut->softmax;
- oldbut->active = NULL;
+ but->flag = oldbut->flag;
+ but->active = oldbut->active;
+ but->pos = oldbut->pos;
+ but->ofs = oldbut->ofs;
+ but->editstr = oldbut->editstr;
+ but->editval = oldbut->editval;
+ but->editvec = oldbut->editvec;
+ but->editcoba = oldbut->editcoba;
+ but->editcumap = oldbut->editcumap;
+ but->selsta = oldbut->selsta;
+ but->selend = oldbut->selend;
+ but->softmin = oldbut->softmin;
+ but->softmax = oldbut->softmax;
+ oldbut->active = NULL;
#endif
- /* move button over from oldblock to new block */
- BLI_remlink(&oldblock->buttons, oldbut);
- BLI_insertlinkafter(&block->buttons, but, oldbut);
- oldbut->block = block;
- *but_p = oldbut;
-
- /* still stuff needs to be copied */
- oldbut->rect = but->rect;
- oldbut->context = but->context; /* set by Layout */
-
- /* drawing */
- oldbut->icon = but->icon;
- oldbut->iconadd = but->iconadd;
- oldbut->alignnr = but->alignnr;
-
- /* typically the same pointers, but not on undo/redo */
- /* XXX some menu buttons store button itself in but->poin. Ugly */
- if (oldbut->poin != (char *)oldbut) {
- SWAP(char *, oldbut->poin, but->poin);
- SWAP(void *, oldbut->func_argN, but->func_argN);
- }
-
- /* Move tooltip from new to old. */
- SWAP(uiButToolTipFunc, oldbut->tip_func, but->tip_func);
- SWAP(void *, oldbut->tip_argN, but->tip_argN);
-
- oldbut->flag = (oldbut->flag & ~flag_copy) | (but->flag & flag_copy);
- oldbut->drawflag = (oldbut->drawflag & ~drawflag_copy) | (but->drawflag & drawflag_copy);
-
- /* 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)) {
- oldbut->hardmax = but->hardmax;
- }
-
- /* Selectively copy a1, a2 since their use differs across all button types
- * (and we'll probably split these out later) */
- if (ELEM(oldbut->type, UI_BTYPE_PROGRESS_BAR)) {
- oldbut->a1 = but->a1;
- }
-
- if (!BLI_listbase_is_empty(&block->butstore)) {
- UI_butstore_register_update(block, oldbut, but);
- }
-
- /* move/copy string from the new button to the old */
- /* needed for alt+mouse wheel over enums */
- if (but->str != but->strdata) {
- if (oldbut->str != oldbut->strdata) {
- SWAP(char *, but->str, oldbut->str);
- }
- else {
- oldbut->str = but->str;
- but->str = but->strdata;
- }
- }
- else {
- if (oldbut->str != oldbut->strdata) {
- MEM_freeN(oldbut->str);
- oldbut->str = oldbut->strdata;
- }
- BLI_strncpy(oldbut->strdata, but->strdata, sizeof(oldbut->strdata));
- }
-
- if (but->dragpoin && (but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
- SWAP(void *, but->dragpoin, oldbut->dragpoin);
- }
-
- BLI_remlink(&block->buttons, but);
- ui_but_free(C, but);
-
- /* note: if layout hasn't been applied yet, it uses old button pointers... */
- }
- else {
- const int flag_copy = UI_BUT_DRAG_MULTI;
-
- but->flag = (but->flag & ~flag_copy) | (oldbut->flag & flag_copy);
-
- /* ensures one button can get activated, and in case the buttons
- * draw are the same this gives O(1) lookup for each button */
- BLI_remlink(&oldblock->buttons, oldbut);
- ui_but_free(C, oldbut);
- }
-
- return found_active;
+ /* move button over from oldblock to new block */
+ BLI_remlink(&oldblock->buttons, oldbut);
+ BLI_insertlinkafter(&block->buttons, but, oldbut);
+ oldbut->block = block;
+ *but_p = oldbut;
+
+ /* still stuff needs to be copied */
+ oldbut->rect = but->rect;
+ oldbut->context = but->context; /* set by Layout */
+
+ /* drawing */
+ oldbut->icon = but->icon;
+ oldbut->iconadd = but->iconadd;
+ oldbut->alignnr = but->alignnr;
+
+ /* typically the same pointers, but not on undo/redo */
+ /* XXX some menu buttons store button itself in but->poin. Ugly */
+ if (oldbut->poin != (char *)oldbut) {
+ SWAP(char *, oldbut->poin, but->poin);
+ SWAP(void *, oldbut->func_argN, but->func_argN);
+ }
+
+ /* Move tooltip from new to old. */
+ SWAP(uiButToolTipFunc, oldbut->tip_func, but->tip_func);
+ SWAP(void *, oldbut->tip_argN, but->tip_argN);
+
+ oldbut->flag = (oldbut->flag & ~flag_copy) | (but->flag & flag_copy);
+ oldbut->drawflag = (oldbut->drawflag & ~drawflag_copy) | (but->drawflag & drawflag_copy);
+
+ /* 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)) {
+ oldbut->hardmax = but->hardmax;
+ }
+
+ /* Selectively copy a1, a2 since their use differs across all button types
+ * (and we'll probably split these out later) */
+ if (ELEM(oldbut->type, UI_BTYPE_PROGRESS_BAR)) {
+ oldbut->a1 = but->a1;
+ }
+
+ if (!BLI_listbase_is_empty(&block->butstore)) {
+ UI_butstore_register_update(block, oldbut, but);
+ }
+
+ /* move/copy string from the new button to the old */
+ /* needed for alt+mouse wheel over enums */
+ if (but->str != but->strdata) {
+ if (oldbut->str != oldbut->strdata) {
+ SWAP(char *, but->str, oldbut->str);
+ }
+ else {
+ oldbut->str = but->str;
+ but->str = but->strdata;
+ }
+ }
+ else {
+ if (oldbut->str != oldbut->strdata) {
+ MEM_freeN(oldbut->str);
+ oldbut->str = oldbut->strdata;
+ }
+ BLI_strncpy(oldbut->strdata, but->strdata, sizeof(oldbut->strdata));
+ }
+
+ if (but->dragpoin && (but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
+ SWAP(void *, but->dragpoin, oldbut->dragpoin);
+ }
+
+ BLI_remlink(&block->buttons, but);
+ ui_but_free(C, but);
+
+ /* note: if layout hasn't been applied yet, it uses old button pointers... */
+ }
+ else {
+ const int flag_copy = UI_BUT_DRAG_MULTI;
+
+ but->flag = (but->flag & ~flag_copy) | (oldbut->flag & flag_copy);
+
+ /* ensures one button can get activated, and in case the buttons
+ * draw are the same this gives O(1) lookup for each button */
+ BLI_remlink(&oldblock->buttons, oldbut);
+ ui_but_free(C, oldbut);
+ }
+
+ return found_active;
}
/* needed for temporarily rename buttons, such as in outliner or file-select,
@@ -807,165 +831,163 @@ static bool ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBu
/* returns 0 when button removed */
bool UI_but_active_only(const bContext *C, ARegion *ar, uiBlock *block, uiBut *but)
{
- uiBlock *oldblock;
- uiBut *oldbut;
- bool activate = false, found = false, isactive = false;
-
- oldblock = block->oldblock;
- if (!oldblock) {
- activate = true;
- }
- else {
- oldbut = ui_but_find_old(oldblock, but);
- if (oldbut) {
- found = true;
-
- if (oldbut->active) {
- isactive = true;
- }
- }
- }
- if ((activate == true) || (found == false)) {
- ui_but_activate_event((bContext *)C, ar, but);
- }
- else if ((found == true) && (isactive == false)) {
- BLI_remlink(&block->buttons, but);
- ui_but_free(C, but);
- return false;
- }
-
- return true;
+ uiBlock *oldblock;
+ uiBut *oldbut;
+ bool activate = false, found = false, isactive = false;
+
+ oldblock = block->oldblock;
+ if (!oldblock) {
+ activate = true;
+ }
+ else {
+ oldbut = ui_but_find_old(oldblock, but);
+ if (oldbut) {
+ found = true;
+
+ if (oldbut->active) {
+ isactive = true;
+ }
+ }
+ }
+ if ((activate == true) || (found == false)) {
+ ui_but_activate_event((bContext *)C, ar, but);
+ }
+ else if ((found == true) && (isactive == false)) {
+ 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 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)) {
- done = true;
- }
- }
- }
- but->flag &= ~UI_BUT_ACTIVATE_ON_INIT;
- }
- return done;
+ 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)) {
+ done = true;
+ }
+ }
+ }
+ but->flag &= ~UI_BUT_ACTIVATE_ON_INIT;
+ }
+ return done;
}
-
-
/* simulate button click */
void UI_but_execute(const bContext *C, uiBut *but)
{
- ARegion *ar = CTX_wm_region(C);
- void *active_back;
- ui_but_execute_begin((bContext *)C, ar, but, &active_back);
- /* Value is applied in begin. No further action required. */
- ui_but_execute_end((bContext *)C, ar, but, active_back);
+ ARegion *ar = CTX_wm_region(C);
+ void *active_back;
+ ui_but_execute_begin((bContext *)C, ar, but, &active_back);
+ /* Value is applied in begin. No further action required. */
+ ui_but_execute_end((bContext *)C, ar, but, active_back);
}
/* use to check if we need to disable undo, but don't make any changes
* returns false if undo needs to be disabled. */
static bool ui_but_is_rna_undo(const uiBut *but)
{
- if (but->rnapoin.id.data) {
- /* avoid undo push for buttons who's ID are screen or wm level
- * we could disable undo for buttons with no ID too but may have
- * unforeseen consequences, so best check for ID's we _know_ are not
- * handled by undo - campbell */
- ID *id = but->rnapoin.id.data;
- if (ID_CHECK_UNDO(id) == false) {
- return false;
- }
- else {
- return true;
- }
- }
- else if (but->rnapoin.type && !RNA_struct_undo_check(but->rnapoin.type)) {
- return false;
- }
-
- return true;
+ if (but->rnapoin.id.data) {
+ /* avoid undo push for buttons who's ID are screen or wm level
+ * we could disable undo for buttons with no ID too but may have
+ * unforeseen consequences, so best check for ID's we _know_ are not
+ * handled by undo - campbell */
+ ID *id = but->rnapoin.id.data;
+ if (ID_CHECK_UNDO(id) == false) {
+ return false;
+ }
+ else {
+ return true;
+ }
+ }
+ else if (but->rnapoin.type && !RNA_struct_undo_check(but->rnapoin.type)) {
+ return false;
+ }
+
+ return true;
}
/* assigns automatic keybindings to menu items for fast access
* (underline key in menu) */
static void ui_menu_block_set_keyaccels(uiBlock *block)
{
- uiBut *but;
-
- uint menu_key_mask = 0;
- uchar menu_key;
- const char *str_pt;
- int pass;
- int tot_missing = 0;
-
- /* only do it before bounding */
- if (block->rect.xmin != block->rect.xmax) {
- return;
- }
-
- for (pass = 0; pass < 2; pass++) {
- /* 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 (but = block->buttons.first; but; but = but->next) {
- if (!ELEM(but->type,
- UI_BTYPE_BUT,
- UI_BTYPE_BUT_MENU,
- UI_BTYPE_MENU, UI_BTYPE_BLOCK,
- UI_BTYPE_PULLDOWN) ||
- (but->flag & UI_HIDDEN))
- {
- /* pass */
- }
- else if (but->menu_key == '\0') {
- if (but->str) {
- for (str_pt = but->str; *str_pt; ) {
- menu_key = tolower(*str_pt);
- if ((menu_key >= 'a' && menu_key <= 'z') && !(menu_key_mask & 1 << (menu_key - 'a'))) {
- menu_key_mask |= 1 << (menu_key - 'a');
- break;
- }
-
- if (pass == 0) {
- /* Skip to next delimiter on first pass (be picky) */
- while (isalpha(*str_pt)) {
- str_pt++;
- }
-
- if (*str_pt) {
- str_pt++;
- }
- }
- else {
- /* just step over every char second pass and find first usable key */
- str_pt++;
- }
- }
-
- if (*str_pt) {
- but->menu_key = menu_key;
- }
- else {
- /* run second pass */
- tot_missing++;
- }
-
- /* if all keys have been used just exit, unlikely */
- if (menu_key_mask == (1 << 26) - 1) {
- return;
- }
- }
- }
- }
-
- /* check if second pass is needed */
- if (!tot_missing) {
- break;
- }
- }
+ uiBut *but;
+
+ uint menu_key_mask = 0;
+ uchar menu_key;
+ const char *str_pt;
+ int pass;
+ int tot_missing = 0;
+
+ /* only do it before bounding */
+ if (block->rect.xmin != block->rect.xmax) {
+ return;
+ }
+
+ for (pass = 0; pass < 2; pass++) {
+ /* 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 (but = block->buttons.first; but; but = but->next) {
+ if (!ELEM(but->type,
+ UI_BTYPE_BUT,
+ UI_BTYPE_BUT_MENU,
+ UI_BTYPE_MENU,
+ UI_BTYPE_BLOCK,
+ UI_BTYPE_PULLDOWN) ||
+ (but->flag & UI_HIDDEN)) {
+ /* pass */
+ }
+ else if (but->menu_key == '\0') {
+ if (but->str) {
+ for (str_pt = but->str; *str_pt;) {
+ menu_key = tolower(*str_pt);
+ if ((menu_key >= 'a' && menu_key <= 'z') && !(menu_key_mask & 1 << (menu_key - 'a'))) {
+ menu_key_mask |= 1 << (menu_key - 'a');
+ break;
+ }
+
+ if (pass == 0) {
+ /* Skip to next delimiter on first pass (be picky) */
+ while (isalpha(*str_pt)) {
+ str_pt++;
+ }
+
+ if (*str_pt) {
+ str_pt++;
+ }
+ }
+ else {
+ /* just step over every char second pass and find first usable key */
+ str_pt++;
+ }
+ }
+
+ if (*str_pt) {
+ but->menu_key = menu_key;
+ }
+ else {
+ /* run second pass */
+ tot_missing++;
+ }
+
+ /* if all keys have been used just exit, unlikely */
+ if (menu_key_mask == (1 << 26) - 1) {
+ return;
+ }
+ }
+ }
+ }
+
+ /* check if second pass is needed */
+ if (!tot_missing) {
+ break;
+ }
+ }
}
/* XXX, this code will shorten any allocated string to 'UI_MAX_NAME_STR'
@@ -973,35 +995,32 @@ static void ui_menu_block_set_keyaccels(uiBlock *block)
* but this could be supported */
void ui_but_add_shortcut(uiBut *but, const char *shortcut_str, const bool do_strip)
{
- if (do_strip && (but->flag & UI_BUT_HAS_SEP_CHAR)) {
- char *cpoin = strrchr(but->str, UI_SEP_CHAR);
- if (cpoin) {
- *cpoin = '\0';
- }
- but->flag &= ~UI_BUT_HAS_SEP_CHAR;
- }
-
- /* without this, just allow stripping of the shortcut */
- if (shortcut_str) {
- char *butstr_orig;
-
- if (but->str != but->strdata) {
- butstr_orig = but->str; /* free after using as source buffer */
- }
- else {
- butstr_orig = BLI_strdup(but->str);
- }
- BLI_snprintf(
- but->strdata,
- sizeof(but->strdata),
- "%s" UI_SEP_CHAR_S "%s",
- butstr_orig, shortcut_str);
- MEM_freeN(butstr_orig);
- but->str = but->strdata;
- but->flag |= UI_BUT_HAS_SEP_CHAR;
- but->drawflag |= UI_BUT_HAS_SHORTCUT;
- ui_but_update(but);
- }
+ if (do_strip && (but->flag & UI_BUT_HAS_SEP_CHAR)) {
+ char *cpoin = strrchr(but->str, UI_SEP_CHAR);
+ if (cpoin) {
+ *cpoin = '\0';
+ }
+ but->flag &= ~UI_BUT_HAS_SEP_CHAR;
+ }
+
+ /* without this, just allow stripping of the shortcut */
+ if (shortcut_str) {
+ char *butstr_orig;
+
+ if (but->str != but->strdata) {
+ butstr_orig = but->str; /* free after using as source buffer */
+ }
+ else {
+ butstr_orig = BLI_strdup(but->str);
+ }
+ BLI_snprintf(
+ but->strdata, sizeof(but->strdata), "%s" UI_SEP_CHAR_S "%s", butstr_orig, shortcut_str);
+ MEM_freeN(butstr_orig);
+ but->str = but->strdata;
+ but->flag |= UI_BUT_HAS_SEP_CHAR;
+ but->drawflag |= UI_BUT_HAS_SHORTCUT;
+ ui_but_update(but);
+ }
}
/* -------------------------------------------------------------------- */
@@ -1011,308 +1030,321 @@ void ui_but_add_shortcut(uiBut *but, const char *shortcut_str, const bool do_str
* - #ui_but_event_property_operator_string
* \{ */
-static bool ui_but_event_operator_string_from_operator(
- const bContext *C, uiBut *but,
- char *buf, const size_t buf_len)
-{
- BLI_assert(but->optype != NULL);
- bool found = false;
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
-
- if (WM_key_event_operator_string(
- C, but->optype->idname, but->opcontext, prop, true,
- buf, buf_len))
- {
- found = true;
- }
- return found;
-}
-
-static bool ui_but_event_operator_string_from_menu(
- const bContext *C, uiBut *but,
- char *buf, const size_t buf_len)
-{
- MenuType *mt = UI_but_menutype_get(but);
- BLI_assert(mt != NULL);
-
- bool found = false;
- IDProperty *prop_menu;
-
- /* annoying, create a property */
- IDPropertyTemplate val = {0};
- prop_menu = IDP_New(IDP_GROUP, &val, __func__); /* dummy, name is unimportant */
- IDP_AddToGroup(prop_menu, IDP_NewString(mt->idname, "name", sizeof(mt->idname)));
-
- if (WM_key_event_operator_string(
- C, "WM_OT_call_menu", WM_OP_INVOKE_REGION_WIN, prop_menu, true,
- buf, buf_len))
- {
- found = true;
- }
-
- IDP_FreeProperty(prop_menu);
- MEM_freeN(prop_menu);
- return found;
-}
-
-static bool ui_but_event_operator_string_from_panel(
- const bContext *C, uiBut *but,
- char *buf, const size_t buf_len)
-{
- /** Nearly exact copy of #ui_but_event_operator_string_from_menu */
- PanelType *pt = UI_but_paneltype_get(but);
- BLI_assert(pt != NULL);
-
- bool found = false;
- IDProperty *prop_panel;
-
- /* annoying, create a property */
- IDPropertyTemplate val = {0};
- prop_panel = IDP_New(IDP_GROUP, &val, __func__); /* dummy, name is unimportant */
- IDP_AddToGroup(prop_panel, IDP_NewString(pt->idname, "name", sizeof(pt->idname)));
- IDP_AddToGroup(prop_panel, IDP_New(IDP_INT, &(IDPropertyTemplate){ .i = pt->space_type, }, "space_type"));
- IDP_AddToGroup(prop_panel, IDP_New(IDP_INT, &(IDPropertyTemplate){ .i = pt->region_type, }, "region_type"));
-
- for (int i = 0; i < 2; i++) {
- /* FIXME(campbell): We can't reasonably search all configurations - long term. */
- IDP_ReplaceInGroup(prop_panel, IDP_New(IDP_INT, &(IDPropertyTemplate){ .i = i, }, "keep_open"));
- if (WM_key_event_operator_string(
- C, "WM_OT_call_panel", WM_OP_INVOKE_REGION_WIN, prop_panel, true,
- buf, buf_len))
- {
- found = true;
- break;
- }
- }
-
- IDP_FreeProperty(prop_panel);
- MEM_freeN(prop_panel);
- return found;
-}
-
-static bool ui_but_event_operator_string(
- const bContext *C, uiBut *but,
- char *buf, const size_t buf_len)
-{
- bool found = false;
-
- if (but->optype != NULL) {
- found = ui_but_event_operator_string_from_operator(C, but, buf, buf_len);
- }
- else if (UI_but_menutype_get(but) != NULL) {
- found = ui_but_event_operator_string_from_menu(C, but, buf, buf_len);
- }
- else if (UI_but_paneltype_get(but) != NULL) {
- found = ui_but_event_operator_string_from_panel(C, but, buf, buf_len);
- }
-
- return found;
-}
-
-static bool ui_but_event_property_operator_string(
- const bContext *C, uiBut *but,
- char *buf, const size_t buf_len)
-{
- /* context toggle operator names to check... */
-
- /* This function could use a refactor to generalize button type to operator relationship
- * as well as which operators use properties.
- * - Campbell
- * */
- const char *ctx_toggle_opnames[] = {
- "WM_OT_context_toggle",
- "WM_OT_context_toggle_enum",
- "WM_OT_context_cycle_int",
- "WM_OT_context_cycle_enum",
- "WM_OT_context_cycle_array",
- "WM_OT_context_menu_enum",
- NULL,
- };
-
- const char *ctx_enum_opnames[] = {
- "WM_OT_context_set_enum",
- NULL,
- };
-
- const char *ctx_enum_opnames_for_Area_ui_type[] = {
- "SCREEN_OT_space_type_set_or_cycle",
- NULL,
- };
-
- const char **opnames = ctx_toggle_opnames;
- int opnames_len = ARRAY_SIZE(ctx_toggle_opnames);
-
-
- int prop_enum_value = -1;
- bool prop_enum_value_ok = false;
- bool prop_enum_value_is_int = false;
- const char *prop_enum_value_id = "value";
- PointerRNA *ptr = &but->rnapoin;
- PropertyRNA *prop = but->rnaprop;
- if ((but->type == UI_BTYPE_BUT_MENU) && (but->block->handle != NULL)) {
- uiBut *but_parent = but->block->handle->popup_create_vars.but;
- if ((but->type == UI_BTYPE_BUT_MENU) &&
- (but_parent && but_parent->rnaprop) &&
- (RNA_property_type(but_parent->rnaprop) == PROP_ENUM) &&
- ELEM(but_parent->menu_create_func,
- ui_def_but_rna__menu,
- ui_def_but_rna__panel_type,
- ui_def_but_rna__menu_type))
- {
- prop_enum_value = (int)but->hardmin;
- ptr = &but_parent->rnapoin;
- prop = but_parent->rnaprop;
- prop_enum_value_ok = true;
-
- opnames = ctx_enum_opnames;
- opnames_len = ARRAY_SIZE(ctx_enum_opnames);
- }
- }
-
- bool found = false;
-
- /* Don't use the button again. */
- but = NULL;
-
- /* this version is only for finding hotkeys for properties
- * (which get set via context using operators) */
- if (prop) {
- /* to avoid massive slowdowns on property panels, for now, we only check the
- * hotkeys for Editor / Scene settings...
- *
- * TODO: userpref settings?
- */
- char *data_path = NULL;
-
- if (ptr->id.data) {
- ID *id = ptr->id.data;
-
- if (GS(id->name) == ID_SCR) {
- /* screen/editor property
- * NOTE: in most cases, there is actually no info for backwards tracing
- * how to get back to ID from the editor data we may be dealing with
- */
- if (RNA_struct_is_a(ptr->type, &RNA_Space)) {
- /* data should be directly on here... */
- data_path = BLI_sprintfN("space_data.%s", RNA_property_identifier(prop));
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_Area)) {
- /* data should be directly on here... */
- const char *prop_id = RNA_property_identifier(prop);
- /* Hack since keys access 'type', UI shows 'ui_type'. */
- if (STREQ(prop_id, "ui_type")) {
- prop_id = "type";
- prop_enum_value >>= 16;
- prop = RNA_struct_find_property(ptr, prop_id);
-
- opnames = ctx_enum_opnames_for_Area_ui_type;
- opnames_len = ARRAY_SIZE(ctx_enum_opnames_for_Area_ui_type);
- prop_enum_value_id = "space_type";
- prop_enum_value_is_int = true;
- }
- else {
- data_path = BLI_sprintfN("area.%s", prop_id);
- }
- }
- else {
- /* special exceptions for common nested data in editors... */
- if (RNA_struct_is_a(ptr->type, &RNA_DopeSheet)) {
- /* dopesheet filtering options... */
- data_path = BLI_sprintfN("space_data.dopesheet.%s", RNA_property_identifier(prop));
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_FileSelectParams)) {
- /* Filebrowser options... */
- data_path = BLI_sprintfN("space_data.params.%s", RNA_property_identifier(prop));
- }
- }
- }
- 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)
- */
- data_path = RNA_path_from_ID_to_property(ptr, prop);
- }
- else {
- /* scene property */
- char *path = RNA_path_from_ID_to_property(ptr, prop);
-
- if (path) {
- data_path = BLI_sprintfN("scene.%s", path);
- MEM_freeN(path);
- }
+static bool ui_but_event_operator_string_from_operator(const bContext *C,
+ uiBut *but,
+ char *buf,
+ const size_t buf_len)
+{
+ BLI_assert(but->optype != NULL);
+ bool found = false;
+ IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
+
+ if (WM_key_event_operator_string(
+ C, but->optype->idname, but->opcontext, prop, true, buf, buf_len)) {
+ found = true;
+ }
+ return found;
+}
+
+static bool ui_but_event_operator_string_from_menu(const bContext *C,
+ uiBut *but,
+ char *buf,
+ const size_t buf_len)
+{
+ MenuType *mt = UI_but_menutype_get(but);
+ BLI_assert(mt != NULL);
+
+ bool found = false;
+ IDProperty *prop_menu;
+
+ /* annoying, create a property */
+ IDPropertyTemplate val = {0};
+ prop_menu = IDP_New(IDP_GROUP, &val, __func__); /* dummy, name is unimportant */
+ IDP_AddToGroup(prop_menu, IDP_NewString(mt->idname, "name", sizeof(mt->idname)));
+
+ if (WM_key_event_operator_string(
+ C, "WM_OT_call_menu", WM_OP_INVOKE_REGION_WIN, prop_menu, true, buf, buf_len)) {
+ found = true;
+ }
+
+ IDP_FreeProperty(prop_menu);
+ MEM_freeN(prop_menu);
+ return found;
+}
+
+static bool ui_but_event_operator_string_from_panel(const bContext *C,
+ uiBut *but,
+ char *buf,
+ const size_t buf_len)
+{
+ /** Nearly exact copy of #ui_but_event_operator_string_from_menu */
+ PanelType *pt = UI_but_paneltype_get(but);
+ BLI_assert(pt != NULL);
+
+ bool found = false;
+ IDProperty *prop_panel;
+
+ /* annoying, create a property */
+ IDPropertyTemplate val = {0};
+ prop_panel = IDP_New(IDP_GROUP, &val, __func__); /* dummy, name is unimportant */
+ IDP_AddToGroup(prop_panel, IDP_NewString(pt->idname, "name", sizeof(pt->idname)));
+ IDP_AddToGroup(prop_panel,
+ IDP_New(IDP_INT,
+ &(IDPropertyTemplate){
+ .i = pt->space_type,
+ },
+ "space_type"));
+ IDP_AddToGroup(prop_panel,
+ IDP_New(IDP_INT,
+ &(IDPropertyTemplate){
+ .i = pt->region_type,
+ },
+ "region_type"));
+
+ for (int i = 0; i < 2; i++) {
+ /* FIXME(campbell): We can't reasonably search all configurations - long term. */
+ IDP_ReplaceInGroup(prop_panel,
+ IDP_New(IDP_INT,
+ &(IDPropertyTemplate){
+ .i = i,
+ },
+ "keep_open"));
+ if (WM_key_event_operator_string(
+ C, "WM_OT_call_panel", WM_OP_INVOKE_REGION_WIN, prop_panel, true, buf, buf_len)) {
+ found = true;
+ break;
+ }
+ }
+
+ IDP_FreeProperty(prop_panel);
+ MEM_freeN(prop_panel);
+ return found;
+}
+
+static bool ui_but_event_operator_string(const bContext *C,
+ uiBut *but,
+ char *buf,
+ const size_t buf_len)
+{
+ bool found = false;
+
+ if (but->optype != NULL) {
+ found = ui_but_event_operator_string_from_operator(C, but, buf, buf_len);
+ }
+ else if (UI_but_menutype_get(but) != NULL) {
+ found = ui_but_event_operator_string_from_menu(C, but, buf, buf_len);
+ }
+ else if (UI_but_paneltype_get(but) != NULL) {
+ found = ui_but_event_operator_string_from_panel(C, but, buf, buf_len);
+ }
+
+ return found;
+}
+
+static bool ui_but_event_property_operator_string(const bContext *C,
+ uiBut *but,
+ char *buf,
+ const size_t buf_len)
+{
+ /* context toggle operator names to check... */
+
+ /* This function could use a refactor to generalize button type to operator relationship
+ * as well as which operators use properties.
+ * - Campbell
+ * */
+ const char *ctx_toggle_opnames[] = {
+ "WM_OT_context_toggle",
+ "WM_OT_context_toggle_enum",
+ "WM_OT_context_cycle_int",
+ "WM_OT_context_cycle_enum",
+ "WM_OT_context_cycle_array",
+ "WM_OT_context_menu_enum",
+ NULL,
+ };
+
+ const char *ctx_enum_opnames[] = {
+ "WM_OT_context_set_enum",
+ NULL,
+ };
+
+ const char *ctx_enum_opnames_for_Area_ui_type[] = {
+ "SCREEN_OT_space_type_set_or_cycle",
+ NULL,
+ };
+
+ const char **opnames = ctx_toggle_opnames;
+ int opnames_len = ARRAY_SIZE(ctx_toggle_opnames);
+
+ int prop_enum_value = -1;
+ bool prop_enum_value_ok = false;
+ bool prop_enum_value_is_int = false;
+ const char *prop_enum_value_id = "value";
+ PointerRNA *ptr = &but->rnapoin;
+ PropertyRNA *prop = but->rnaprop;
+ if ((but->type == UI_BTYPE_BUT_MENU) && (but->block->handle != NULL)) {
+ uiBut *but_parent = but->block->handle->popup_create_vars.but;
+ if ((but->type == UI_BTYPE_BUT_MENU) && (but_parent && but_parent->rnaprop) &&
+ (RNA_property_type(but_parent->rnaprop) == PROP_ENUM) &&
+ ELEM(but_parent->menu_create_func,
+ ui_def_but_rna__menu,
+ ui_def_but_rna__panel_type,
+ ui_def_but_rna__menu_type)) {
+ prop_enum_value = (int)but->hardmin;
+ ptr = &but_parent->rnapoin;
+ prop = but_parent->rnaprop;
+ prop_enum_value_ok = true;
+
+ opnames = ctx_enum_opnames;
+ opnames_len = ARRAY_SIZE(ctx_enum_opnames);
+ }
+ }
+
+ bool found = false;
+
+ /* Don't use the button again. */
+ but = NULL;
+
+ /* this version is only for finding hotkeys for properties
+ * (which get set via context using operators) */
+ if (prop) {
+ /* to avoid massive slowdowns on property panels, for now, we only check the
+ * hotkeys for Editor / Scene settings...
+ *
+ * TODO: userpref settings?
+ */
+ char *data_path = NULL;
+
+ if (ptr->id.data) {
+ ID *id = ptr->id.data;
+
+ if (GS(id->name) == ID_SCR) {
+ /* screen/editor property
+ * NOTE: in most cases, there is actually no info for backwards tracing
+ * how to get back to ID from the editor data we may be dealing with
+ */
+ if (RNA_struct_is_a(ptr->type, &RNA_Space)) {
+ /* data should be directly on here... */
+ data_path = BLI_sprintfN("space_data.%s", RNA_property_identifier(prop));
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Area)) {
+ /* data should be directly on here... */
+ const char *prop_id = RNA_property_identifier(prop);
+ /* Hack since keys access 'type', UI shows 'ui_type'. */
+ if (STREQ(prop_id, "ui_type")) {
+ prop_id = "type";
+ prop_enum_value >>= 16;
+ prop = RNA_struct_find_property(ptr, prop_id);
+
+ opnames = ctx_enum_opnames_for_Area_ui_type;
+ opnames_len = ARRAY_SIZE(ctx_enum_opnames_for_Area_ui_type);
+ prop_enum_value_id = "space_type";
+ prop_enum_value_is_int = true;
+ }
+ else {
+ data_path = BLI_sprintfN("area.%s", prop_id);
+ }
+ }
+ else {
+ /* special exceptions for common nested data in editors... */
+ if (RNA_struct_is_a(ptr->type, &RNA_DopeSheet)) {
+ /* dopesheet filtering options... */
+ data_path = BLI_sprintfN("space_data.dopesheet.%s", RNA_property_identifier(prop));
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_FileSelectParams)) {
+ /* Filebrowser options... */
+ data_path = BLI_sprintfN("space_data.params.%s", RNA_property_identifier(prop));
+ }
+ }
+ }
+ 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)
+ */
+ data_path = RNA_path_from_ID_to_property(ptr, prop);
+ }
+ else {
+ /* scene property */
+ char *path = RNA_path_from_ID_to_property(ptr, prop);
+
+ if (path) {
+ data_path = BLI_sprintfN("scene.%s", path);
+ MEM_freeN(path);
+ }
#if 0
- else {
- printf("ERROR in %s(): Couldn't get path for scene property - %s\n",
- __func__, RNA_property_identifier(prop));
- }
+ else {
+ printf("ERROR in %s(): Couldn't get path for scene property - %s\n",
+ __func__, RNA_property_identifier(prop));
+ }
#endif
- }
- }
- else {
- //puts("other id");
- }
-
- //printf("prop shortcut: '%s' (%s)\n", RNA_property_identifier(prop), data_path);
- }
-
- /* we have a datapath! */
- if (data_path || (prop_enum_value_ok && prop_enum_value_id)) {
- /* create a property to host the "datapath" property we're sending to the operators */
- IDProperty *prop_path;
-
- IDPropertyTemplate val = {0};
- prop_path = IDP_New(IDP_GROUP, &val, __func__);
- if (data_path) {
- IDP_AddToGroup(prop_path, IDP_NewString(data_path, "data_path", strlen(data_path) + 1));
- }
- if (prop_enum_value_ok) {
- const EnumPropertyItem *item;
- bool free;
- RNA_property_enum_items((bContext *)C, ptr, prop, &item, NULL, &free);
- int index = RNA_enum_from_value(item, prop_enum_value);
- if (index != -1) {
- IDProperty *prop_value;
- if (prop_enum_value_is_int) {
- int value = item[index].value;
- prop_value = IDP_New(IDP_INT, &(IDPropertyTemplate){ .i = value, }, prop_enum_value_id);
- }
- else {
- const char *id = item[index].identifier;
- prop_value = IDP_NewString(id, prop_enum_value_id, strlen(id) + 1);
- }
- IDP_AddToGroup(prop_path, prop_value);
- }
- else {
- opnames_len = 0; /* Do nothing. */
- }
- if (free) {
- MEM_freeN((void *)item);
- }
- }
-
- /* check each until one works... */
-
- for (int i = 0; (i < opnames_len) && (opnames[i]); i++) {
- if (WM_key_event_operator_string(
- C, opnames[i], WM_OP_INVOKE_REGION_WIN, prop_path, false,
- buf, buf_len))
- {
- found = true;
- break;
- }
- }
-
- /* cleanup */
- IDP_FreeProperty(prop_path);
- MEM_freeN(prop_path);
- if (data_path) {
- MEM_freeN(data_path);
- }
- }
- }
-
- return found;
+ }
+ }
+ else {
+ //puts("other id");
+ }
+
+ //printf("prop shortcut: '%s' (%s)\n", RNA_property_identifier(prop), data_path);
+ }
+
+ /* we have a datapath! */
+ if (data_path || (prop_enum_value_ok && prop_enum_value_id)) {
+ /* create a property to host the "datapath" property we're sending to the operators */
+ IDProperty *prop_path;
+
+ IDPropertyTemplate val = {0};
+ prop_path = IDP_New(IDP_GROUP, &val, __func__);
+ if (data_path) {
+ IDP_AddToGroup(prop_path, IDP_NewString(data_path, "data_path", strlen(data_path) + 1));
+ }
+ if (prop_enum_value_ok) {
+ const EnumPropertyItem *item;
+ bool free;
+ RNA_property_enum_items((bContext *)C, ptr, prop, &item, NULL, &free);
+ int index = RNA_enum_from_value(item, prop_enum_value);
+ if (index != -1) {
+ IDProperty *prop_value;
+ if (prop_enum_value_is_int) {
+ int value = item[index].value;
+ prop_value = IDP_New(IDP_INT,
+ &(IDPropertyTemplate){
+ .i = value,
+ },
+ prop_enum_value_id);
+ }
+ else {
+ const char *id = item[index].identifier;
+ prop_value = IDP_NewString(id, prop_enum_value_id, strlen(id) + 1);
+ }
+ IDP_AddToGroup(prop_path, prop_value);
+ }
+ else {
+ opnames_len = 0; /* Do nothing. */
+ }
+ if (free) {
+ MEM_freeN((void *)item);
+ }
+ }
+
+ /* check each until one works... */
+
+ for (int i = 0; (i < opnames_len) && (opnames[i]); i++) {
+ if (WM_key_event_operator_string(
+ C, opnames[i], WM_OP_INVOKE_REGION_WIN, prop_path, false, buf, buf_len)) {
+ found = true;
+ break;
+ }
+ }
+
+ /* cleanup */
+ IDP_FreeProperty(prop_path);
+ MEM_freeN(prop_path);
+ if (data_path) {
+ MEM_freeN(data_path);
+ }
+ }
+ }
+
+ return found;
}
/** \} */
@@ -1342,356 +1374,359 @@ static bool ui_but_event_property_operator_string(
*
* --Matt 07/2006
*/
-const char ui_radial_dir_order[8] = {
- UI_RADIAL_W, UI_RADIAL_E, UI_RADIAL_S, UI_RADIAL_N,
- UI_RADIAL_NW, UI_RADIAL_NE, UI_RADIAL_SW, UI_RADIAL_SE};
-
-const char ui_radial_dir_to_numpad[8] = {8, 9, 6, 3, 2, 1, 4, 7};
-const short ui_radial_dir_to_angle[8] = {90, 45, 0, 315, 270, 225, 180, 135};
+const char ui_radial_dir_order[8] = {UI_RADIAL_W,
+ UI_RADIAL_E,
+ UI_RADIAL_S,
+ UI_RADIAL_N,
+ UI_RADIAL_NW,
+ UI_RADIAL_NE,
+ UI_RADIAL_SW,
+ UI_RADIAL_SE};
+
+const char ui_radial_dir_to_numpad[8] = {8, 9, 6, 3, 2, 1, 4, 7};
+const short ui_radial_dir_to_angle[8] = {90, 45, 0, 315, 270, 225, 180, 135};
static void ui_but_pie_direction_string(uiBut *but, char *buf, int size)
{
- BLI_assert(but->pie_dir < ARRAY_SIZE(ui_radial_dir_to_numpad));
- BLI_snprintf(buf, size, "%d", ui_radial_dir_to_numpad[but->pie_dir]);
+ BLI_assert(but->pie_dir < ARRAY_SIZE(ui_radial_dir_to_numpad));
+ BLI_snprintf(buf, size, "%d", ui_radial_dir_to_numpad[but->pie_dir]);
}
static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
{
- uiBut *but;
- char buf[128];
-
- BLI_assert(block->flag & (UI_BLOCK_LOOP | UI_BLOCK_SHOW_SHORTCUT_ALWAYS));
-
- /* only do it before bounding */
- if (block->rect.xmin != block->rect.xmax) {
- return;
- }
- if (STREQ(block->name, "splash")) {
- return;
- }
-
- if (block->flag & UI_BLOCK_RADIAL) {
- for (but = block->buttons.first; but; but = but->next) {
- if (but->pie_dir != UI_RADIAL_NONE) {
- ui_but_pie_direction_string(but, buf, sizeof(buf));
- ui_but_add_shortcut(but, buf, false);
- }
- }
- }
- else {
- for (but = block->buttons.first; but; but = but->next) {
- if (block->flag & UI_BLOCK_SHOW_SHORTCUT_ALWAYS) {
- /* Skip icon-only buttons (as used in the toolbar). */
- if (but->drawstr[0] == '\0') {
- continue;
- }
- else if (((block->flag & UI_BLOCK_POPOVER) == 0) && UI_but_is_tool(but)) {
- /* For non-popovers, shown in shortcut only
- * (has special shortcut handling code). */
- continue;
- }
- }
- else if (but->dt != UI_EMBOSS_PULLDOWN) {
- continue;
- }
-
- if (ui_but_event_operator_string(C, but, buf, sizeof(buf))) {
- ui_but_add_shortcut(but, buf, false);
- }
- else if (ui_but_event_property_operator_string(C, but, buf, sizeof(buf))) {
- ui_but_add_shortcut(but, buf, false);
- }
- }
- }
+ uiBut *but;
+ char buf[128];
+
+ BLI_assert(block->flag & (UI_BLOCK_LOOP | UI_BLOCK_SHOW_SHORTCUT_ALWAYS));
+
+ /* only do it before bounding */
+ if (block->rect.xmin != block->rect.xmax) {
+ return;
+ }
+ if (STREQ(block->name, "splash")) {
+ return;
+ }
+
+ if (block->flag & UI_BLOCK_RADIAL) {
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->pie_dir != UI_RADIAL_NONE) {
+ ui_but_pie_direction_string(but, buf, sizeof(buf));
+ ui_but_add_shortcut(but, buf, false);
+ }
+ }
+ }
+ else {
+ for (but = block->buttons.first; but; but = but->next) {
+ if (block->flag & UI_BLOCK_SHOW_SHORTCUT_ALWAYS) {
+ /* Skip icon-only buttons (as used in the toolbar). */
+ if (but->drawstr[0] == '\0') {
+ continue;
+ }
+ else if (((block->flag & UI_BLOCK_POPOVER) == 0) && UI_but_is_tool(but)) {
+ /* For non-popovers, shown in shortcut only
+ * (has special shortcut handling code). */
+ continue;
+ }
+ }
+ else if (but->dt != UI_EMBOSS_PULLDOWN) {
+ continue;
+ }
+
+ if (ui_but_event_operator_string(C, but, buf, sizeof(buf))) {
+ ui_but_add_shortcut(but, buf, false);
+ }
+ else if (ui_but_event_property_operator_string(C, but, buf, sizeof(buf))) {
+ ui_but_add_shortcut(but, buf, false);
+ }
+ }
+ }
}
void ui_but_override_flag(uiBut *but)
{
- const int override_status = RNA_property_static_override_status(&but->rnapoin, but->rnaprop, but->rnaindex);
+ const int override_status = RNA_property_static_override_status(
+ &but->rnapoin, but->rnaprop, but->rnaindex);
- if (override_status & RNA_OVERRIDE_STATUS_OVERRIDDEN) {
- but->flag |= UI_BUT_OVERRIDEN;
- }
- else {
- but->flag &= ~UI_BUT_OVERRIDEN;
- }
+ if (override_status & RNA_OVERRIDE_STATUS_OVERRIDDEN) {
+ but->flag |= UI_BUT_OVERRIDEN;
+ }
+ else {
+ but->flag &= ~UI_BUT_OVERRIDEN;
+ }
}
void UI_block_update_from_old(const bContext *C, uiBlock *block)
{
- uiBut *but_old;
- uiBut *but;
+ uiBut *but_old;
+ uiBut *but;
- if (!block->oldblock) {
- return;
- }
+ if (!block->oldblock) {
+ return;
+ }
- but_old = block->oldblock->buttons.first;
+ but_old = block->oldblock->buttons.first;
- if (BLI_listbase_is_empty(&block->oldblock->butstore) == false) {
- UI_butstore_update(block);
- }
+ if (BLI_listbase_is_empty(&block->oldblock->butstore) == false) {
+ UI_butstore_update(block);
+ }
- for (but = block->buttons.first; but; but = but->next) {
- if (ui_but_update_from_old_block(C, block, &but, &but_old)) {
- ui_but_update(but);
+ for (but = block->buttons.first; but; but = but->next) {
+ if (ui_but_update_from_old_block(C, block, &but, &but_old)) {
+ ui_but_update(but);
- /* redraw dynamic tooltip if we have one open */
- if (but->tip_func) {
- UI_but_tooltip_refresh((bContext *)C, but);
- }
- }
- }
+ /* redraw dynamic tooltip if we have one open */
+ if (but->tip_func) {
+ UI_but_tooltip_refresh((bContext *)C, but);
+ }
+ }
+ }
- block->auto_open = block->oldblock->auto_open;
- block->auto_open_last = block->oldblock->auto_open_last;
- block->tooltipdisabled = block->oldblock->tooltipdisabled;
- BLI_movelisttolist(&block->color_pickers.list, &block->oldblock->color_pickers.list);
+ block->auto_open = block->oldblock->auto_open;
+ block->auto_open_last = block->oldblock->auto_open_last;
+ block->tooltipdisabled = block->oldblock->tooltipdisabled;
+ BLI_movelisttolist(&block->color_pickers.list, &block->oldblock->color_pickers.list);
- block->oldblock = NULL;
+ block->oldblock = NULL;
}
void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_xy[2])
{
- wmWindow *window = CTX_wm_window(C);
- Scene *scene = CTX_data_scene(C);
- ARegion *region = CTX_wm_region(C);
- uiBut *but;
-
- BLI_assert(block->active);
-
- UI_block_update_from_old(C, block);
-
- /* inherit flags from 'old' buttons that was drawn here previous, based
- * on matching buttons, we need this to make button event handling non
- * blocking, while still allowing buttons to be remade each redraw as it
- * is expected by blender code */
- for (but = block->buttons.first; but; but = but->next) {
- /* temp? Proper check for graying out */
- if (but->optype) {
- wmOperatorType *ot = but->optype;
-
- if (but->context) {
- CTX_store_set((bContext *)C, but->context);
- }
-
- if (ot == NULL || WM_operator_poll_context((bContext *)C, ot, but->opcontext) == 0) {
- but->flag |= UI_BUT_DISABLED;
- }
-
- if (but->context) {
- CTX_store_set((bContext *)C, NULL);
- }
- }
-
- ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f);
- ui_but_override_flag(but);
- if (UI_but_is_decorator(but)) {
- ui_but_anim_decorate_update_from_flag(but);
- }
- }
-
-
-
- /* handle pending stuff */
- if (block->layouts.first) {
- UI_block_layout_resolve(block, NULL, NULL);
- }
- ui_block_align_calc(block, CTX_wm_region(C));
- if ((block->flag & UI_BLOCK_LOOP) && (block->flag & UI_BLOCK_NUMSELECT)) {
- ui_menu_block_set_keyaccels(block); /* could use a different flag to check */
- }
-
- if (block->flag & (UI_BLOCK_LOOP | UI_BLOCK_SHOW_SHORTCUT_ALWAYS)) {
- ui_menu_block_set_keymaps(C, block);
- }
-
- /* after keymaps! */
- switch (block->bounds_type) {
- case UI_BLOCK_BOUNDS_NONE:
- break;
- case UI_BLOCK_BOUNDS:
- ui_block_bounds_calc(block);
- break;
- case UI_BLOCK_BOUNDS_TEXT:
- ui_block_bounds_calc_text(block, 0.0f);
- break;
- case UI_BLOCK_BOUNDS_POPUP_CENTER:
- ui_block_bounds_calc_centered(window, block);
- break;
- case UI_BLOCK_BOUNDS_PIE_CENTER:
- ui_block_bounds_calc_centered_pie(block);
- break;
-
- /* fallback */
- case UI_BLOCK_BOUNDS_POPUP_MOUSE:
- case UI_BLOCK_BOUNDS_POPUP_MENU:
- ui_block_bounds_calc_popup(window, block, block->bounds_type, xy, r_xy);
- break;
- }
-
- if (block->rect.xmin == 0.0f && block->rect.xmax == 0.0f) {
- UI_block_bounds_set_normal(block, 0);
- }
- if (block->flag & UI_BUT_ALIGN) {
- UI_block_align_end(block);
- }
-
- ui_update_flexible_spacing(region, block);
-
- block->endblock = 1;
+ wmWindow *window = CTX_wm_window(C);
+ Scene *scene = CTX_data_scene(C);
+ ARegion *region = CTX_wm_region(C);
+ uiBut *but;
+
+ BLI_assert(block->active);
+
+ UI_block_update_from_old(C, block);
+
+ /* inherit flags from 'old' buttons that was drawn here previous, based
+ * on matching buttons, we need this to make button event handling non
+ * blocking, while still allowing buttons to be remade each redraw as it
+ * is expected by blender code */
+ for (but = block->buttons.first; but; but = but->next) {
+ /* temp? Proper check for graying out */
+ if (but->optype) {
+ wmOperatorType *ot = but->optype;
+
+ if (but->context) {
+ CTX_store_set((bContext *)C, but->context);
+ }
+
+ if (ot == NULL || WM_operator_poll_context((bContext *)C, ot, but->opcontext) == 0) {
+ but->flag |= UI_BUT_DISABLED;
+ }
+
+ if (but->context) {
+ CTX_store_set((bContext *)C, NULL);
+ }
+ }
+
+ ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f);
+ ui_but_override_flag(but);
+ if (UI_but_is_decorator(but)) {
+ ui_but_anim_decorate_update_from_flag(but);
+ }
+ }
+
+ /* handle pending stuff */
+ if (block->layouts.first) {
+ UI_block_layout_resolve(block, NULL, NULL);
+ }
+ ui_block_align_calc(block, CTX_wm_region(C));
+ if ((block->flag & UI_BLOCK_LOOP) && (block->flag & UI_BLOCK_NUMSELECT)) {
+ ui_menu_block_set_keyaccels(block); /* could use a different flag to check */
+ }
+
+ if (block->flag & (UI_BLOCK_LOOP | UI_BLOCK_SHOW_SHORTCUT_ALWAYS)) {
+ ui_menu_block_set_keymaps(C, block);
+ }
+
+ /* after keymaps! */
+ switch (block->bounds_type) {
+ case UI_BLOCK_BOUNDS_NONE:
+ break;
+ case UI_BLOCK_BOUNDS:
+ ui_block_bounds_calc(block);
+ break;
+ case UI_BLOCK_BOUNDS_TEXT:
+ ui_block_bounds_calc_text(block, 0.0f);
+ break;
+ case UI_BLOCK_BOUNDS_POPUP_CENTER:
+ ui_block_bounds_calc_centered(window, block);
+ break;
+ case UI_BLOCK_BOUNDS_PIE_CENTER:
+ ui_block_bounds_calc_centered_pie(block);
+ break;
+
+ /* fallback */
+ case UI_BLOCK_BOUNDS_POPUP_MOUSE:
+ case UI_BLOCK_BOUNDS_POPUP_MENU:
+ ui_block_bounds_calc_popup(window, block, block->bounds_type, xy, r_xy);
+ break;
+ }
+
+ if (block->rect.xmin == 0.0f && block->rect.xmax == 0.0f) {
+ UI_block_bounds_set_normal(block, 0);
+ }
+ if (block->flag & UI_BUT_ALIGN) {
+ UI_block_align_end(block);
+ }
+
+ ui_update_flexible_spacing(region, block);
+
+ block->endblock = 1;
}
void UI_block_end(const bContext *C, uiBlock *block)
{
- wmWindow *window = CTX_wm_window(C);
+ wmWindow *window = CTX_wm_window(C);
- UI_block_end_ex(C, block, &window->eventstate->x, NULL);
+ UI_block_end_ex(C, block, &window->eventstate->x, NULL);
}
/* ************** BLOCK DRAWING FUNCTION ************* */
void ui_fontscale(short *points, float aspect)
{
- if (aspect < 0.9f || aspect > 1.1f) {
- float pointsf = *points;
+ if (aspect < 0.9f || aspect > 1.1f) {
+ float pointsf = *points;
- /* for some reason scaling fonts goes too fast compared to widget size */
- /* XXX not true anymore? (ton) */
- //aspect = sqrt(aspect);
- pointsf /= aspect;
+ /* for some reason scaling fonts goes too fast compared to widget size */
+ /* XXX not true anymore? (ton) */
+ //aspect = sqrt(aspect);
+ pointsf /= aspect;
- if (aspect > 1.0f) {
- *points = ceilf(pointsf);
- }
- else {
- *points = floorf(pointsf);
- }
- }
+ if (aspect > 1.0f) {
+ *points = ceilf(pointsf);
+ }
+ else {
+ *points = floorf(pointsf);
+ }
+ }
}
/* 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)
{
- rctf rectf;
+ rctf rectf;
- ui_block_to_window_rctf(ar, block, &rectf, (but) ? &but->rect : &block->rect);
- BLI_rcti_rctf_copy_round(rect, &rectf);
- BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->winrct.ymin);
+ ui_block_to_window_rctf(ar, block, &rectf, (but) ? &but->rect : &block->rect);
+ BLI_rcti_rctf_copy_round(rect, &rectf);
+ BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->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;
- uiBut *but;
- rcti rect;
-
- /* get menu region or area region */
- ar = CTX_wm_menu(C);
- if (!ar) {
- ar = CTX_wm_region(C);
- }
-
- if (!block->endblock) {
- UI_block_end(C, block);
- }
-
- /* we set this only once */
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- /* scale fonts */
- ui_fontscale(&style.paneltitle.points, block->aspect);
- ui_fontscale(&style.grouplabel.points, block->aspect);
- ui_fontscale(&style.widgetlabel.points, block->aspect);
- ui_fontscale(&style.widget.points, block->aspect);
-
- /* scale block min/max to rect */
- ui_but_to_pixelrect(&rect, ar, block, NULL);
-
- /* pixel space for AA widgets */
- GPU_matrix_push_projection();
- GPU_matrix_push();
- GPU_matrix_identity_set();
-
- wmOrtho2_region_pixelspace(ar);
-
- /* 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);
- }
- 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;
- ui_draw_aligned_panel(
- &style, block, &rect,
- UI_panel_category_is_visible(ar), show_background);
- }
-
- BLF_batch_draw_begin();
- UI_icon_draw_cache_begin();
- UI_widgetbase_draw_cache_begin();
-
- /* 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);
-
- /* 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_widgetbase_draw_cache_end();
- UI_icon_draw_cache_end();
- BLF_batch_draw_end();
-
- /* restore matrix */
- GPU_matrix_pop_projection();
- GPU_matrix_pop();
+ uiStyle style = *UI_style_get_dpi(); /* XXX pass on as arg */
+ ARegion *ar;
+ uiBut *but;
+ rcti rect;
+
+ /* get menu region or area region */
+ ar = CTX_wm_menu(C);
+ if (!ar) {
+ ar = CTX_wm_region(C);
+ }
+
+ if (!block->endblock) {
+ UI_block_end(C, block);
+ }
+
+ /* we set this only once */
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ /* scale fonts */
+ ui_fontscale(&style.paneltitle.points, block->aspect);
+ ui_fontscale(&style.grouplabel.points, block->aspect);
+ ui_fontscale(&style.widgetlabel.points, block->aspect);
+ ui_fontscale(&style.widget.points, block->aspect);
+
+ /* scale block min/max to rect */
+ ui_but_to_pixelrect(&rect, ar, block, NULL);
+
+ /* pixel space for AA widgets */
+ GPU_matrix_push_projection();
+ GPU_matrix_push();
+ GPU_matrix_identity_set();
+
+ wmOrtho2_region_pixelspace(ar);
+
+ /* 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);
+ }
+ 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;
+ ui_draw_aligned_panel(&style, block, &rect, UI_panel_category_is_visible(ar), show_background);
+ }
+
+ BLF_batch_draw_begin();
+ UI_icon_draw_cache_begin();
+ UI_widgetbase_draw_cache_begin();
+
+ /* 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);
+
+ /* 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_widgetbase_draw_cache_end();
+ UI_icon_draw_cache_end();
+ BLF_batch_draw_end();
+
+ /* restore matrix */
+ GPU_matrix_pop_projection();
+ GPU_matrix_pop();
}
static void ui_block_message_subscribe(ARegion *ar, 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) {
- 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) &&
- (but_prev->rnapoin.type == but->rnapoin.type) &&
- (but_prev->rnapoin.data == but->rnapoin.data) &&
- (but_prev->rnapoin.id.data == but->rnapoin.id.data)) == false)
- {
- /* TODO: could make this into utility function. */
- WM_msg_subscribe_rna(
- mbus, &but->rnapoin, but->rnaprop,
- &(const wmMsgSubscribeValue){
- .owner = ar,
- .user_data = ar,
- .notify = ED_region_do_msg_notify_tag_redraw,
- }, __func__);
- but_prev = but;
- }
- }
- }
+ 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) {
+ 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) &&
+ (but_prev->rnapoin.type == but->rnapoin.type) &&
+ (but_prev->rnapoin.data == but->rnapoin.data) &&
+ (but_prev->rnapoin.id.data == but->rnapoin.id.data)) == false) {
+ /* TODO: could make this into utility function. */
+ WM_msg_subscribe_rna(mbus,
+ &but->rnapoin,
+ but->rnaprop,
+ &(const wmMsgSubscribeValue){
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ },
+ __func__);
+ but_prev = but;
+ }
+ }
+ }
}
void UI_region_message_subscribe(ARegion *ar, struct wmMsgBus *mbus)
{
- for (uiBlock *block = ar->uiblocks.first; block; block = block->next) {
- ui_block_message_subscribe(ar, mbus, block);
- }
+ for (uiBlock *block = ar->uiblocks.first; block; block = block->next) {
+ ui_block_message_subscribe(ar, mbus, block);
+ }
}
/* ************* EVENTS ************* */
@@ -1703,116 +1738,117 @@ void UI_region_message_subscribe(ARegion *ar, struct wmMsgBus *mbus)
*/
int ui_but_is_pushed_ex(uiBut *but, double *value)
{
- int is_push = 0;
-
- if (but->bit) {
- const bool state = !ELEM(but->type, UI_BTYPE_TOGGLE_N, UI_BTYPE_ICON_TOGGLE_N, UI_BTYPE_CHECKBOX_N);
- int lvalue;
- UI_GET_BUT_VALUE_INIT(but, *value);
- lvalue = (int)*value;
- if (UI_BITBUT_TEST(lvalue, (but->bitnr))) {
- is_push = state;
- }
- else {
- is_push = !state;
- }
- }
- else {
- switch (but->type) {
- case UI_BTYPE_BUT:
- case UI_BTYPE_HOTKEY_EVENT:
- case UI_BTYPE_KEY_EVENT:
- case UI_BTYPE_COLOR:
- is_push = -1;
- break;
- case UI_BTYPE_BUT_TOGGLE:
- case UI_BTYPE_TOGGLE:
- case UI_BTYPE_ICON_TOGGLE:
- case UI_BTYPE_CHECKBOX:
- UI_GET_BUT_VALUE_INIT(but, *value);
- if (*value != (double)but->hardmin) {
- is_push = true;
- }
- break;
- case UI_BTYPE_ICON_TOGGLE_N:
- case UI_BTYPE_TOGGLE_N:
- case UI_BTYPE_CHECKBOX_N:
- UI_GET_BUT_VALUE_INIT(but, *value);
- if (*value == 0.0) {
- is_push = true;
- }
- break;
- case UI_BTYPE_ROW:
- case UI_BTYPE_LISTROW:
- case UI_BTYPE_TAB:
- if ((but->type == UI_BTYPE_TAB) && but->rnaprop && but->custom_data) {
- /* uiBut.custom_data points to data this tab represents (e.g. workspace).
- * uiBut.rnapoin/prop store an active value (e.g. active workspace). */
- if (RNA_property_type(but->rnaprop) == PROP_POINTER) {
- PointerRNA active_ptr = RNA_property_pointer_get(&but->rnapoin, but->rnaprop);
- if (active_ptr.data == but->custom_data) {
- is_push = true;
- }
- }
- break;
- }
- else if (but->optype) {
- break;
- }
-
- UI_GET_BUT_VALUE_INIT(but, *value);
- /* support for rna enum buts */
- if (but->rnaprop && (RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG)) {
- if ((int)*value & (int)but->hardmax) {
- is_push = true;
- }
- }
- else {
- if (*value == (double)but->hardmax) {
- is_push = true;
- }
- }
- break;
- default:
- is_push = -1;
- break;
- }
- }
-
- return is_push;
+ int is_push = 0;
+
+ if (but->bit) {
+ const bool state = !ELEM(
+ but->type, UI_BTYPE_TOGGLE_N, UI_BTYPE_ICON_TOGGLE_N, UI_BTYPE_CHECKBOX_N);
+ int lvalue;
+ UI_GET_BUT_VALUE_INIT(but, *value);
+ lvalue = (int)*value;
+ if (UI_BITBUT_TEST(lvalue, (but->bitnr))) {
+ is_push = state;
+ }
+ else {
+ is_push = !state;
+ }
+ }
+ else {
+ switch (but->type) {
+ case UI_BTYPE_BUT:
+ case UI_BTYPE_HOTKEY_EVENT:
+ case UI_BTYPE_KEY_EVENT:
+ case UI_BTYPE_COLOR:
+ is_push = -1;
+ break;
+ case UI_BTYPE_BUT_TOGGLE:
+ case UI_BTYPE_TOGGLE:
+ case UI_BTYPE_ICON_TOGGLE:
+ case UI_BTYPE_CHECKBOX:
+ UI_GET_BUT_VALUE_INIT(but, *value);
+ if (*value != (double)but->hardmin) {
+ is_push = true;
+ }
+ break;
+ case UI_BTYPE_ICON_TOGGLE_N:
+ case UI_BTYPE_TOGGLE_N:
+ case UI_BTYPE_CHECKBOX_N:
+ UI_GET_BUT_VALUE_INIT(but, *value);
+ if (*value == 0.0) {
+ is_push = true;
+ }
+ break;
+ case UI_BTYPE_ROW:
+ case UI_BTYPE_LISTROW:
+ case UI_BTYPE_TAB:
+ if ((but->type == UI_BTYPE_TAB) && but->rnaprop && but->custom_data) {
+ /* uiBut.custom_data points to data this tab represents (e.g. workspace).
+ * uiBut.rnapoin/prop store an active value (e.g. active workspace). */
+ if (RNA_property_type(but->rnaprop) == PROP_POINTER) {
+ PointerRNA active_ptr = RNA_property_pointer_get(&but->rnapoin, but->rnaprop);
+ if (active_ptr.data == but->custom_data) {
+ is_push = true;
+ }
+ }
+ break;
+ }
+ else if (but->optype) {
+ break;
+ }
+
+ UI_GET_BUT_VALUE_INIT(but, *value);
+ /* support for rna enum buts */
+ if (but->rnaprop && (RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG)) {
+ if ((int)*value & (int)but->hardmax) {
+ is_push = true;
+ }
+ }
+ else {
+ if (*value == (double)but->hardmax) {
+ is_push = true;
+ }
+ }
+ break;
+ default:
+ is_push = -1;
+ break;
+ }
+ }
+
+ return is_push;
}
int ui_but_is_pushed(uiBut *but)
{
- double value = UI_BUT_VALUE_UNSET;
- return ui_but_is_pushed_ex(but, &value);
+ double value = UI_BUT_VALUE_UNSET;
+ return ui_but_is_pushed_ex(but, &value);
}
static void ui_but_update_select_flag(uiBut *but, double *value)
{
- switch (ui_but_is_pushed_ex(but, value)) {
- case true:
- but->flag |= UI_SELECT;
- break;
- case false:
- but->flag &= ~UI_SELECT;
- break;
- }
+ switch (ui_but_is_pushed_ex(but, value)) {
+ case true:
+ but->flag |= UI_SELECT;
+ break;
+ case false:
+ but->flag &= ~UI_SELECT;
+ break;
+ }
}
/* ************************************************ */
void UI_block_lock_set(uiBlock *block, bool val, const char *lockstr)
{
- if (val) {
- block->lock = val;
- block->lockstr = lockstr;
- }
+ if (val) {
+ block->lock = val;
+ block->lockstr = lockstr;
+ }
}
void UI_block_lock_clear(uiBlock *block)
{
- block->lock = false;
- block->lockstr = NULL;
+ block->lock = false;
+ block->lockstr = NULL;
}
/* *********************** data get/set ***********************
@@ -1822,154 +1858,159 @@ void UI_block_lock_clear(uiBlock *block)
/* for buttons pointing to color for example */
void ui_but_v3_get(uiBut *but, float vec[3])
{
- PropertyRNA *prop;
- int a;
-
- if (but->editvec) {
- copy_v3_v3(vec, but->editvec);
- }
-
- if (but->rnaprop) {
- prop = but->rnaprop;
-
- zero_v3(vec);
-
- if (RNA_property_type(prop) == PROP_FLOAT) {
- int tot = RNA_property_array_length(&but->rnapoin, prop);
- BLI_assert(tot > 0);
- if (tot == 3) {
- RNA_property_float_get_array(&but->rnapoin, prop, vec);
- }
- else {
- tot = min_ii(tot, 3);
- for (a = 0; a < tot; a++) {
- vec[a] = RNA_property_float_get_index(&but->rnapoin, prop, a);
- }
- }
- }
- }
- else if (but->pointype == UI_BUT_POIN_CHAR) {
- const char *cp = (char *)but->poin;
-
- vec[0] = ((float)cp[0]) / 255.0f;
- vec[1] = ((float)cp[1]) / 255.0f;
- vec[2] = ((float)cp[2]) / 255.0f;
- }
- else if (but->pointype == UI_BUT_POIN_FLOAT) {
- const float *fp = (float *)but->poin;
- copy_v3_v3(vec, fp);
- }
- else {
- if (but->editvec == NULL) {
- fprintf(stderr, "%s: can't get color, should never happen\n", __func__);
- zero_v3(vec);
- }
- }
-
- if (but->type == UI_BTYPE_UNITVEC) {
- normalize_v3(vec);
- }
+ PropertyRNA *prop;
+ int a;
+
+ if (but->editvec) {
+ copy_v3_v3(vec, but->editvec);
+ }
+
+ if (but->rnaprop) {
+ prop = but->rnaprop;
+
+ zero_v3(vec);
+
+ if (RNA_property_type(prop) == PROP_FLOAT) {
+ int tot = RNA_property_array_length(&but->rnapoin, prop);
+ BLI_assert(tot > 0);
+ if (tot == 3) {
+ RNA_property_float_get_array(&but->rnapoin, prop, vec);
+ }
+ else {
+ tot = min_ii(tot, 3);
+ for (a = 0; a < tot; a++) {
+ vec[a] = RNA_property_float_get_index(&but->rnapoin, prop, a);
+ }
+ }
+ }
+ }
+ else if (but->pointype == UI_BUT_POIN_CHAR) {
+ const char *cp = (char *)but->poin;
+
+ vec[0] = ((float)cp[0]) / 255.0f;
+ vec[1] = ((float)cp[1]) / 255.0f;
+ vec[2] = ((float)cp[2]) / 255.0f;
+ }
+ else if (but->pointype == UI_BUT_POIN_FLOAT) {
+ const float *fp = (float *)but->poin;
+ copy_v3_v3(vec, fp);
+ }
+ else {
+ if (but->editvec == NULL) {
+ fprintf(stderr, "%s: can't get color, should never happen\n", __func__);
+ zero_v3(vec);
+ }
+ }
+
+ if (but->type == UI_BTYPE_UNITVEC) {
+ normalize_v3(vec);
+ }
}
/* for buttons pointing to color for example */
void ui_but_v3_set(uiBut *but, const float vec[3])
{
- PropertyRNA *prop;
-
- if (but->editvec) {
- copy_v3_v3(but->editvec, vec);
- }
-
- if (but->rnaprop) {
- prop = but->rnaprop;
-
- if (RNA_property_type(prop) == PROP_FLOAT) {
- int tot;
- int a;
-
- tot = RNA_property_array_length(&but->rnapoin, prop);
- BLI_assert(tot > 0);
- if (tot == 3) {
- RNA_property_float_set_array(&but->rnapoin, prop, vec);
- }
- else {
- tot = min_ii(tot, 3);
- for (a = 0; a < tot; a++) {
- RNA_property_float_set_index(&but->rnapoin, prop, a, vec[a]);
- }
- }
- }
- }
- else if (but->pointype == UI_BUT_POIN_CHAR) {
- char *cp = (char *)but->poin;
- cp[0] = (char)(0.5f + vec[0] * 255.0f);
- cp[1] = (char)(0.5f + vec[1] * 255.0f);
- cp[2] = (char)(0.5f + vec[2] * 255.0f);
- }
- else if (but->pointype == UI_BUT_POIN_FLOAT) {
- float *fp = (float *)but->poin;
- copy_v3_v3(fp, vec);
- }
+ PropertyRNA *prop;
+
+ if (but->editvec) {
+ copy_v3_v3(but->editvec, vec);
+ }
+
+ if (but->rnaprop) {
+ prop = but->rnaprop;
+
+ if (RNA_property_type(prop) == PROP_FLOAT) {
+ int tot;
+ int a;
+
+ tot = RNA_property_array_length(&but->rnapoin, prop);
+ BLI_assert(tot > 0);
+ if (tot == 3) {
+ RNA_property_float_set_array(&but->rnapoin, prop, vec);
+ }
+ else {
+ tot = min_ii(tot, 3);
+ for (a = 0; a < tot; a++) {
+ RNA_property_float_set_index(&but->rnapoin, prop, a, vec[a]);
+ }
+ }
+ }
+ }
+ else if (but->pointype == UI_BUT_POIN_CHAR) {
+ char *cp = (char *)but->poin;
+ cp[0] = (char)(0.5f + vec[0] * 255.0f);
+ cp[1] = (char)(0.5f + vec[1] * 255.0f);
+ cp[2] = (char)(0.5f + vec[2] * 255.0f);
+ }
+ else if (but->pointype == UI_BUT_POIN_FLOAT) {
+ float *fp = (float *)but->poin;
+ copy_v3_v3(fp, vec);
+ }
}
bool ui_but_is_float(const uiBut *but)
{
- if (but->pointype == UI_BUT_POIN_FLOAT && but->poin) {
- return true;
- }
+ if (but->pointype == UI_BUT_POIN_FLOAT && but->poin) {
+ return true;
+ }
- if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_FLOAT) {
- return true;
- }
+ if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_FLOAT) {
+ return true;
+ }
- return false;
+ return false;
}
bool ui_but_is_bool(const uiBut *but)
{
- if (ELEM(but->type, UI_BTYPE_TOGGLE, UI_BTYPE_TOGGLE_N, UI_BTYPE_ICON_TOGGLE, UI_BTYPE_ICON_TOGGLE_N, UI_BTYPE_TAB)) {
- return true;
- }
+ if (ELEM(but->type,
+ UI_BTYPE_TOGGLE,
+ UI_BTYPE_TOGGLE_N,
+ UI_BTYPE_ICON_TOGGLE,
+ UI_BTYPE_ICON_TOGGLE_N,
+ UI_BTYPE_TAB)) {
+ return true;
+ }
- if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_BOOLEAN) {
- return true;
- }
+ if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_BOOLEAN) {
+ return true;
+ }
- if ((but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) && (but->type == UI_BTYPE_ROW)) {
- return true;
- }
+ if ((but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) &&
+ (but->type == UI_BTYPE_ROW)) {
+ return true;
+ }
- return false;
+ return false;
}
-
bool ui_but_is_unit(const uiBut *but)
{
- UnitSettings *unit = but->block->unit;
- const int unit_type = UI_but_unit_type_get(but);
+ UnitSettings *unit = but->block->unit;
+ const int unit_type = UI_but_unit_type_get(but);
- if (unit_type == PROP_UNIT_NONE) {
- return false;
- }
+ if (unit_type == PROP_UNIT_NONE) {
+ return false;
+ }
#if 1 /* removed so angle buttons get correct snapping */
- if (ui_but_is_unit_radians_ex(unit, unit_type)) {
- return false;
- }
+ if (ui_but_is_unit_radians_ex(unit, unit_type)) {
+ return false;
+ }
#endif
- /* for now disable time unit conversion */
- if (unit_type == PROP_UNIT_TIME) {
- return false;
- }
+ /* for now disable time unit conversion */
+ if (unit_type == PROP_UNIT_TIME) {
+ return false;
+ }
- if (unit->system == USER_UNIT_NONE) {
- if (unit_type != PROP_UNIT_ROTATION) {
- return false;
- }
- }
+ if (unit->system == USER_UNIT_NONE) {
+ if (unit_type != PROP_UNIT_ROTATION) {
+ return false;
+ }
+ }
- return true;
+ return true;
}
/**
@@ -1977,39 +2018,39 @@ bool ui_but_is_unit(const uiBut *but)
*/
bool ui_but_is_compatible(const uiBut *but_a, const uiBut *but_b)
{
- if (but_a->type != but_b->type) {
- return false;
- }
- if (but_a->pointype != but_b->pointype) {
- return false;
- }
-
- if (but_a->rnaprop) {
- /* skip 'rnapoin.data', 'rnapoin.id.data'
- * allow different data to have the same props edited at once */
- if (but_a->rnapoin.type != but_b->rnapoin.type) {
- return false;
- }
- if (RNA_property_type(but_a->rnaprop) != RNA_property_type(but_b->rnaprop)) {
- return false;
- }
- if (RNA_property_subtype(but_a->rnaprop) != RNA_property_subtype(but_b->rnaprop)) {
- return false;
- }
- }
-
- return true;
+ if (but_a->type != but_b->type) {
+ return false;
+ }
+ if (but_a->pointype != but_b->pointype) {
+ return false;
+ }
+
+ if (but_a->rnaprop) {
+ /* skip 'rnapoin.data', 'rnapoin.id.data'
+ * allow different data to have the same props edited at once */
+ if (but_a->rnapoin.type != but_b->rnapoin.type) {
+ return false;
+ }
+ if (RNA_property_type(but_a->rnaprop) != RNA_property_type(but_b->rnaprop)) {
+ return false;
+ }
+ if (RNA_property_subtype(but_a->rnaprop) != RNA_property_subtype(but_b->rnaprop)) {
+ return false;
+ }
+ }
+
+ return true;
}
bool ui_but_is_rna_valid(uiBut *but)
{
- if (but->rnaprop == NULL || RNA_struct_contains_property(&but->rnapoin, but->rnaprop)) {
- return true;
- }
- else {
- printf("property removed %s: %p\n", but->drawstr, but->rnaprop);
- return false;
- }
+ if (but->rnaprop == NULL || RNA_struct_contains_property(&but->rnapoin, but->rnaprop)) {
+ return true;
+ }
+ else {
+ printf("property removed %s: %p\n", but->drawstr, but->rnaprop);
+ return false;
+ }
}
/**
@@ -2017,199 +2058,198 @@ bool ui_but_is_rna_valid(uiBut *but)
*/
bool ui_but_supports_cycling(const uiBut *but)
{
- return ((ELEM(but->type, UI_BTYPE_ROW, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, UI_BTYPE_LISTBOX)) ||
- (but->type == UI_BTYPE_MENU && ui_but_menu_step_poll(but)) ||
- (but->type == UI_BTYPE_COLOR && but->a1 != -1) ||
- (but->menu_step_func != NULL));
+ return ((ELEM(but->type, UI_BTYPE_ROW, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, UI_BTYPE_LISTBOX)) ||
+ (but->type == UI_BTYPE_MENU && ui_but_menu_step_poll(but)) ||
+ (but->type == UI_BTYPE_COLOR && but->a1 != -1) || (but->menu_step_func != NULL));
}
double ui_but_value_get(uiBut *but)
{
- PropertyRNA *prop;
- double value = 0.0;
-
- if (but->editval) {
- return *(but->editval);
- }
- if (but->poin == NULL && but->rnapoin.data == NULL) {
- return 0.0;
- }
-
- if (but->rnaprop) {
- prop = but->rnaprop;
-
- BLI_assert(but->rnaindex != -1);
-
- switch (RNA_property_type(prop)) {
- case PROP_BOOLEAN:
- if (RNA_property_array_check(prop)) {
- value = RNA_property_boolean_get_index(&but->rnapoin, prop, but->rnaindex);
- }
- else {
- value = RNA_property_boolean_get(&but->rnapoin, prop);
- }
- break;
- case PROP_INT:
- if (RNA_property_array_check(prop)) {
- value = RNA_property_int_get_index(&but->rnapoin, prop, but->rnaindex);
- }
- else {
- value = RNA_property_int_get(&but->rnapoin, prop);
- }
- break;
- case PROP_FLOAT:
- if (RNA_property_array_check(prop)) {
- value = RNA_property_float_get_index(&but->rnapoin, prop, but->rnaindex);
- }
- else {
- value = RNA_property_float_get(&but->rnapoin, prop);
- }
- break;
- case PROP_ENUM:
- value = RNA_property_enum_get(&but->rnapoin, prop);
- break;
- default:
- value = 0.0;
- break;
- }
- }
- else if (but->pointype == UI_BUT_POIN_CHAR) {
- value = *(char *)but->poin;
- }
- else if (but->pointype == UI_BUT_POIN_SHORT) {
- value = *(short *)but->poin;
- }
- else if (but->pointype == UI_BUT_POIN_INT) {
- value = *(int *)but->poin;
- }
- else if (but->pointype == UI_BUT_POIN_FLOAT) {
- value = *(float *)but->poin;
- }
-
- return value;
+ PropertyRNA *prop;
+ double value = 0.0;
+
+ if (but->editval) {
+ return *(but->editval);
+ }
+ if (but->poin == NULL && but->rnapoin.data == NULL) {
+ return 0.0;
+ }
+
+ if (but->rnaprop) {
+ prop = but->rnaprop;
+
+ BLI_assert(but->rnaindex != -1);
+
+ switch (RNA_property_type(prop)) {
+ case PROP_BOOLEAN:
+ if (RNA_property_array_check(prop)) {
+ value = RNA_property_boolean_get_index(&but->rnapoin, prop, but->rnaindex);
+ }
+ else {
+ value = RNA_property_boolean_get(&but->rnapoin, prop);
+ }
+ break;
+ case PROP_INT:
+ if (RNA_property_array_check(prop)) {
+ value = RNA_property_int_get_index(&but->rnapoin, prop, but->rnaindex);
+ }
+ else {
+ value = RNA_property_int_get(&but->rnapoin, prop);
+ }
+ break;
+ case PROP_FLOAT:
+ if (RNA_property_array_check(prop)) {
+ value = RNA_property_float_get_index(&but->rnapoin, prop, but->rnaindex);
+ }
+ else {
+ value = RNA_property_float_get(&but->rnapoin, prop);
+ }
+ break;
+ case PROP_ENUM:
+ value = RNA_property_enum_get(&but->rnapoin, prop);
+ break;
+ default:
+ value = 0.0;
+ break;
+ }
+ }
+ else if (but->pointype == UI_BUT_POIN_CHAR) {
+ value = *(char *)but->poin;
+ }
+ else if (but->pointype == UI_BUT_POIN_SHORT) {
+ value = *(short *)but->poin;
+ }
+ else if (but->pointype == UI_BUT_POIN_INT) {
+ value = *(int *)but->poin;
+ }
+ else if (but->pointype == UI_BUT_POIN_FLOAT) {
+ value = *(float *)but->poin;
+ }
+
+ return value;
}
void ui_but_value_set(uiBut *but, double value)
{
- PropertyRNA *prop;
-
- /* value is a hsv value: convert to rgb */
- if (but->rnaprop) {
- prop = but->rnaprop;
-
- if (RNA_property_editable(&but->rnapoin, prop)) {
- switch (RNA_property_type(prop)) {
- case PROP_BOOLEAN:
- if (RNA_property_array_check(prop)) {
- RNA_property_boolean_set_index(&but->rnapoin, prop, but->rnaindex, value);
- }
- else {
- RNA_property_boolean_set(&but->rnapoin, prop, value);
- }
- break;
- case PROP_INT:
- if (RNA_property_array_check(prop)) {
- RNA_property_int_set_index(&but->rnapoin, prop, but->rnaindex, (int)value);
- }
- else {
- RNA_property_int_set(&but->rnapoin, prop, (int)value);
- }
- break;
- case PROP_FLOAT:
- if (RNA_property_array_check(prop)) {
- RNA_property_float_set_index(&but->rnapoin, prop, but->rnaindex, value);
- }
- else {
- RNA_property_float_set(&but->rnapoin, prop, value);
- }
- break;
- case PROP_ENUM:
- if (RNA_property_flag(prop) & PROP_ENUM_FLAG) {
- int ivalue = (int)value;
- /* toggle for enum/flag buttons */
- ivalue ^= RNA_property_enum_get(&but->rnapoin, prop);
- RNA_property_enum_set(&but->rnapoin, prop, ivalue);
- }
- else {
- RNA_property_enum_set(&but->rnapoin, prop, value);
- }
- break;
- default:
- break;
- }
- }
-
- /* we can't be sure what RNA set functions actually do,
- * so leave this unset */
- value = UI_BUT_VALUE_UNSET;
- }
- else if (but->pointype == 0) {
- /* pass */
- }
- else {
- /* first do rounding */
- if (but->pointype == UI_BUT_POIN_CHAR) {
- value = round_db_to_uchar_clamp(value);
- }
- else if (but->pointype == UI_BUT_POIN_SHORT) {
- value = round_db_to_short_clamp(value);
- }
- else if (but->pointype == UI_BUT_POIN_INT) {
- value = round_db_to_int_clamp(value);
- }
- else if (but->pointype == UI_BUT_POIN_FLOAT) {
- float fval = (float)value;
- if (fval >= -0.00001f && fval <= 0.00001f) {
- /* prevent negative zero */
- fval = 0.0f;
- }
- value = fval;
- }
-
- /* then set value with possible edit override */
- if (but->editval) {
- value = *but->editval = value;
- }
- else if (but->pointype == UI_BUT_POIN_CHAR) {
- value = *((char *)but->poin) = (char)value;
- }
- else if (but->pointype == UI_BUT_POIN_SHORT) {
- value = *((short *)but->poin) = (short)value;
- }
- else if (but->pointype == UI_BUT_POIN_INT) {
- value = *((int *)but->poin) = (int)value;
- }
- else if (but->pointype == UI_BUT_POIN_FLOAT) {
- value = *((float *)but->poin) = (float)value;
- }
- }
-
- ui_but_update_select_flag(but, &value);
+ PropertyRNA *prop;
+
+ /* value is a hsv value: convert to rgb */
+ if (but->rnaprop) {
+ prop = but->rnaprop;
+
+ if (RNA_property_editable(&but->rnapoin, prop)) {
+ switch (RNA_property_type(prop)) {
+ case PROP_BOOLEAN:
+ if (RNA_property_array_check(prop)) {
+ RNA_property_boolean_set_index(&but->rnapoin, prop, but->rnaindex, value);
+ }
+ else {
+ RNA_property_boolean_set(&but->rnapoin, prop, value);
+ }
+ break;
+ case PROP_INT:
+ if (RNA_property_array_check(prop)) {
+ RNA_property_int_set_index(&but->rnapoin, prop, but->rnaindex, (int)value);
+ }
+ else {
+ RNA_property_int_set(&but->rnapoin, prop, (int)value);
+ }
+ break;
+ case PROP_FLOAT:
+ if (RNA_property_array_check(prop)) {
+ RNA_property_float_set_index(&but->rnapoin, prop, but->rnaindex, value);
+ }
+ else {
+ RNA_property_float_set(&but->rnapoin, prop, value);
+ }
+ break;
+ case PROP_ENUM:
+ if (RNA_property_flag(prop) & PROP_ENUM_FLAG) {
+ int ivalue = (int)value;
+ /* toggle for enum/flag buttons */
+ ivalue ^= RNA_property_enum_get(&but->rnapoin, prop);
+ RNA_property_enum_set(&but->rnapoin, prop, ivalue);
+ }
+ else {
+ RNA_property_enum_set(&but->rnapoin, prop, value);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* we can't be sure what RNA set functions actually do,
+ * so leave this unset */
+ value = UI_BUT_VALUE_UNSET;
+ }
+ else if (but->pointype == 0) {
+ /* pass */
+ }
+ else {
+ /* first do rounding */
+ if (but->pointype == UI_BUT_POIN_CHAR) {
+ value = round_db_to_uchar_clamp(value);
+ }
+ else if (but->pointype == UI_BUT_POIN_SHORT) {
+ value = round_db_to_short_clamp(value);
+ }
+ else if (but->pointype == UI_BUT_POIN_INT) {
+ value = round_db_to_int_clamp(value);
+ }
+ else if (but->pointype == UI_BUT_POIN_FLOAT) {
+ float fval = (float)value;
+ if (fval >= -0.00001f && fval <= 0.00001f) {
+ /* prevent negative zero */
+ fval = 0.0f;
+ }
+ value = fval;
+ }
+
+ /* then set value with possible edit override */
+ if (but->editval) {
+ value = *but->editval = value;
+ }
+ else if (but->pointype == UI_BUT_POIN_CHAR) {
+ value = *((char *)but->poin) = (char)value;
+ }
+ else if (but->pointype == UI_BUT_POIN_SHORT) {
+ value = *((short *)but->poin) = (short)value;
+ }
+ else if (but->pointype == UI_BUT_POIN_INT) {
+ value = *((int *)but->poin) = (int)value;
+ }
+ else if (but->pointype == UI_BUT_POIN_FLOAT) {
+ value = *((float *)but->poin) = (float)value;
+ }
+ }
+
+ ui_but_update_select_flag(but, &value);
}
int ui_but_string_get_max_length(uiBut *but)
{
- if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
- return but->hardmax;
- }
- else {
- return UI_MAX_DRAW_STR;
- }
+ if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
+ return but->hardmax;
+ }
+ else {
+ return UI_MAX_DRAW_STR;
+ }
}
uiBut *ui_but_drag_multi_edit_get(uiBut *but)
{
- uiBut *but_iter;
+ uiBut *but_iter;
- BLI_assert(but->flag & UI_BUT_DRAG_MULTI);
+ BLI_assert(but->flag & UI_BUT_DRAG_MULTI);
- for (but_iter = but->block->buttons.first; but_iter; but_iter = but_iter->next) {
- if (but_iter->editstr) {
- break;
- }
- }
+ for (but_iter = but->block->buttons.first; but_iter; but_iter = but_iter->next) {
+ if (but_iter->editstr) {
+ break;
+ }
+ }
- return but_iter;
+ return but_iter;
}
/** \name Check to show extra icons
@@ -2220,293 +2260,299 @@ uiBut *ui_but_drag_multi_edit_get(uiBut *but)
static bool ui_but_icon_extra_is_visible_text_clear(const uiBut *but)
{
- BLI_assert(but->type == UI_BTYPE_TEXT);
- return ((but->flag & UI_BUT_VALUE_CLEAR) && but->drawstr[0]);
+ BLI_assert(but->type == UI_BTYPE_TEXT);
+ return ((but->flag & UI_BUT_VALUE_CLEAR) && but->drawstr[0]);
}
static bool ui_but_icon_extra_is_visible_search_unlink(const uiBut *but)
{
- BLI_assert(ELEM(but->type, UI_BTYPE_SEARCH_MENU));
- return ((but->editstr == NULL) &&
- (but->drawstr[0] != '\0') &&
- (but->flag & UI_BUT_VALUE_CLEAR));
+ BLI_assert(ELEM(but->type, UI_BTYPE_SEARCH_MENU));
+ return ((but->editstr == NULL) && (but->drawstr[0] != '\0') && (but->flag & UI_BUT_VALUE_CLEAR));
}
static bool ui_but_icon_extra_is_visible_search_eyedropper(uiBut *but)
{
- StructRNA *type;
- short idcode;
+ StructRNA *type;
+ short idcode;
- BLI_assert(but->type == UI_BTYPE_SEARCH_MENU && (but->flag & UI_BUT_VALUE_CLEAR));
+ BLI_assert(but->type == UI_BTYPE_SEARCH_MENU && (but->flag & UI_BUT_VALUE_CLEAR));
- if (but->rnaprop == NULL) {
- return false;
- }
+ if (but->rnaprop == NULL) {
+ return false;
+ }
- type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
- idcode = RNA_type_to_ID_code(type);
+ type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
+ idcode = RNA_type_to_ID_code(type);
- return ((but->editstr == NULL) &&
- (idcode == ID_OB || OB_DATA_SUPPORT_ID(idcode)));
+ return ((but->editstr == NULL) && (idcode == ID_OB || OB_DATA_SUPPORT_ID(idcode)));
}
uiButExtraIconType ui_but_icon_extra_get(uiBut *but)
{
- switch (but->type) {
- case UI_BTYPE_TEXT:
- if (ui_but_icon_extra_is_visible_text_clear(but)) {
- return UI_BUT_ICONEXTRA_CLEAR;
- }
- break;
- case UI_BTYPE_SEARCH_MENU:
- if ((but->flag & UI_BUT_VALUE_CLEAR) == 0) {
- /* pass */
- }
- else if (ui_but_icon_extra_is_visible_search_unlink(but)) {
- return UI_BUT_ICONEXTRA_CLEAR;
- }
- else if (ui_but_icon_extra_is_visible_search_eyedropper(but)) {
- return UI_BUT_ICONEXTRA_EYEDROPPER;
- }
- break;
- default:
- break;
- }
-
- return UI_BUT_ICONEXTRA_NONE;
+ switch (but->type) {
+ case UI_BTYPE_TEXT:
+ if (ui_but_icon_extra_is_visible_text_clear(but)) {
+ return UI_BUT_ICONEXTRA_CLEAR;
+ }
+ break;
+ case UI_BTYPE_SEARCH_MENU:
+ if ((but->flag & UI_BUT_VALUE_CLEAR) == 0) {
+ /* pass */
+ }
+ else if (ui_but_icon_extra_is_visible_search_unlink(but)) {
+ return UI_BUT_ICONEXTRA_CLEAR;
+ }
+ else if (ui_but_icon_extra_is_visible_search_eyedropper(but)) {
+ return UI_BUT_ICONEXTRA_EYEDROPPER;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return UI_BUT_ICONEXTRA_NONE;
}
/** \} */
-
static double ui_get_but_scale_unit(uiBut *but, double value)
{
- UnitSettings *unit = but->block->unit;
- int unit_type = UI_but_unit_type_get(but);
+ UnitSettings *unit = but->block->unit;
+ int unit_type = UI_but_unit_type_get(but);
- /* Time unit is a bit special, not handled by BKE_scene_unit_scale() for now. */
- if (unit_type == PROP_UNIT_TIME) { /* WARNING - using evil_C :| */
- Scene *scene = CTX_data_scene(but->block->evil_C);
- return FRA2TIME(value);
- }
- else {
- return BKE_scene_unit_scale(unit, RNA_SUBTYPE_UNIT_VALUE(unit_type), value);
- }
+ /* Time unit is a bit special, not handled by BKE_scene_unit_scale() for now. */
+ if (unit_type == PROP_UNIT_TIME) { /* WARNING - using evil_C :| */
+ Scene *scene = CTX_data_scene(but->block->evil_C);
+ return FRA2TIME(value);
+ }
+ else {
+ return BKE_scene_unit_scale(unit, RNA_SUBTYPE_UNIT_VALUE(unit_type), value);
+ }
}
/* str will be overwritten */
void ui_but_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen)
{
- if (ui_but_is_unit(but)) {
- UnitSettings *unit = but->block->unit;
- int unit_type = UI_but_unit_type_get(but);
- char *orig_str;
+ if (ui_but_is_unit(but)) {
+ UnitSettings *unit = but->block->unit;
+ int unit_type = UI_but_unit_type_get(but);
+ char *orig_str;
- orig_str = BLI_strdup(str);
+ orig_str = BLI_strdup(str);
- bUnit_ToUnitAltName(str, maxlen, orig_str, unit->system, RNA_SUBTYPE_UNIT_VALUE(unit_type));
+ bUnit_ToUnitAltName(str, maxlen, orig_str, unit->system, RNA_SUBTYPE_UNIT_VALUE(unit_type));
- MEM_freeN(orig_str);
- }
+ MEM_freeN(orig_str);
+ }
}
/**
* \param float_precision: Override the button precision.
*/
-static void ui_get_but_string_unit(uiBut *but, char *str, int len_max, double value, bool pad, int float_precision)
-{
- UnitSettings *unit = but->block->unit;
- int unit_type = UI_but_unit_type_get(but);
- int precision;
-
- if (unit->scale_length < 0.0001f) {
- unit->scale_length = 1.0f; // XXX do_versions
- }
-
- /* Use precision override? */
- if (float_precision == -1) {
- /* Sanity checks */
- precision = (int)but->a2;
- if (precision > UI_PRECISION_FLOAT_MAX) {
- precision = UI_PRECISION_FLOAT_MAX;
- }
- else if (precision == -1) {
- precision = 2;
- }
- }
- else {
- precision = float_precision;
- }
-
- bUnit_AsString2(
- str, len_max, ui_get_but_scale_unit(but, value), precision,
- RNA_SUBTYPE_UNIT_VALUE(unit_type), unit, pad);
+static void ui_get_but_string_unit(
+ uiBut *but, char *str, int len_max, double value, bool pad, int float_precision)
+{
+ UnitSettings *unit = but->block->unit;
+ int unit_type = UI_but_unit_type_get(but);
+ int precision;
+
+ if (unit->scale_length < 0.0001f) {
+ unit->scale_length = 1.0f; // XXX do_versions
+ }
+
+ /* Use precision override? */
+ if (float_precision == -1) {
+ /* Sanity checks */
+ precision = (int)but->a2;
+ if (precision > UI_PRECISION_FLOAT_MAX) {
+ precision = UI_PRECISION_FLOAT_MAX;
+ }
+ else if (precision == -1) {
+ precision = 2;
+ }
+ }
+ else {
+ precision = float_precision;
+ }
+
+ bUnit_AsString2(str,
+ len_max,
+ ui_get_but_scale_unit(but, value),
+ precision,
+ RNA_SUBTYPE_UNIT_VALUE(unit_type),
+ unit,
+ pad);
}
static float ui_get_but_step_unit(uiBut *but, float step_default)
{
- int unit_type = RNA_SUBTYPE_UNIT_VALUE(UI_but_unit_type_get(but));
- const double step_orig = step_default * UI_PRECISION_FLOAT_SCALE;
- /* Scaling up 'step_origg ' here is a bit arbitrary,
- * its just giving better scales from user POV */
- const double scale_step = ui_get_but_scale_unit(but, step_orig * 10);
- const double step = bUnit_ClosestScalar(scale_step, but->block->unit->system, unit_type);
+ int unit_type = RNA_SUBTYPE_UNIT_VALUE(UI_but_unit_type_get(but));
+ const double step_orig = step_default * UI_PRECISION_FLOAT_SCALE;
+ /* Scaling up 'step_origg ' here is a bit arbitrary,
+ * its just giving better scales from user POV */
+ const double scale_step = ui_get_but_scale_unit(but, step_orig * 10);
+ const double step = bUnit_ClosestScalar(scale_step, but->block->unit->system, unit_type);
- /* -1 is an error value */
- if (step != -1.0) {
- const double scale_unit = ui_get_but_scale_unit(but, 1.0);
- const double step_unit = bUnit_ClosestScalar(scale_unit, but->block->unit->system, unit_type);
- double step_final;
+ /* -1 is an error value */
+ if (step != -1.0) {
+ const double scale_unit = ui_get_but_scale_unit(but, 1.0);
+ const double step_unit = bUnit_ClosestScalar(scale_unit, but->block->unit->system, unit_type);
+ double step_final;
- BLI_assert(step > 0.0);
+ BLI_assert(step > 0.0);
- step_final = (step / scale_unit) / (double)UI_PRECISION_FLOAT_SCALE;
+ step_final = (step / scale_unit) / (double)UI_PRECISION_FLOAT_SCALE;
- if (step == step_unit) {
- /* Logic here is to scale by the original 'step_orig'
- * only when the unit step matches the scaled step.
- *
- * This is needed for units that don't have a wide range of scales (degrees for eg.).
- * Without this we can't select between a single degree, or a 10th of a degree.
- */
- step_final *= step_orig;
- }
+ if (step == step_unit) {
+ /* Logic here is to scale by the original 'step_orig'
+ * only when the unit step matches the scaled step.
+ *
+ * This is needed for units that don't have a wide range of scales (degrees for eg.).
+ * Without this we can't select between a single degree, or a 10th of a degree.
+ */
+ step_final *= step_orig;
+ }
- return (float)step_final;
- }
- else {
- return step_default;
- }
+ return (float)step_final;
+ }
+ else {
+ return step_default;
+ }
}
/**
* \param float_precision: For number buttons the precision to use or -1 to fallback to the button default.
* \param use_exp_float: Use exponent representation of floats when out of reasonable range (outside of 1e3/1e-3).
*/
-void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision, const bool use_exp_float, bool *r_use_exp_float)
-{
- if (r_use_exp_float) {
- *r_use_exp_float = false;
- }
-
- if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_TAB)) {
- PropertyType type;
- const char *buf = NULL;
- int buf_len;
-
- type = RNA_property_type(but->rnaprop);
-
- if ((but->type == UI_BTYPE_TAB) && (but->custom_data)) {
- StructRNA *ptr_type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
- PointerRNA ptr;
-
- /* uiBut.custom_data points to data this tab represents (e.g. workspace).
- * uiBut.rnapoin/prop store an active value (e.g. active workspace). */
- RNA_pointer_create(but->rnapoin.id.data, ptr_type, but->custom_data, &ptr);
- buf = RNA_struct_name_get_alloc(&ptr, str, maxlen, &buf_len);
- }
- else if (type == PROP_STRING) {
- /* RNA string */
- buf = RNA_property_string_get_alloc(&but->rnapoin, but->rnaprop, str, maxlen, &buf_len);
- }
- else if (type == PROP_ENUM) {
- /* RNA enum */
- int value = RNA_property_enum_get(&but->rnapoin, but->rnaprop);
- if (RNA_property_enum_name(but->block->evil_C, &but->rnapoin, but->rnaprop, value, &buf)) {
- BLI_strncpy(str, buf, maxlen);
- buf = str;
- }
- }
- else if (type == PROP_POINTER) {
- /* RNA pointer */
- PointerRNA ptr = RNA_property_pointer_get(&but->rnapoin, but->rnaprop);
- buf = RNA_struct_name_get_alloc(&ptr, str, maxlen, &buf_len);
- }
- else {
- BLI_assert(0);
- }
-
- if (!buf) {
- str[0] = '\0';
- }
- else if (buf && buf != str) {
- BLI_assert(maxlen <= buf_len + 1);
- /* string was too long, we have to truncate */
- if (ui_but_is_utf8(but)) {
- BLI_strncpy_utf8(str, buf, maxlen);
- }
- else {
- BLI_strncpy(str, buf, maxlen);
- }
- MEM_freeN((void *)buf);
- }
- }
- else if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
- /* string */
- BLI_strncpy(str, but->poin, maxlen);
- return;
- }
- else if (ui_but_anim_expression_get(but, str, maxlen)) {
- /* driver expression */
- }
- else {
- /* number editing */
- double value;
-
- value = ui_but_value_get(but);
-
- PropertySubType subtype = PROP_NONE;
- if (but->rnaprop) {
- subtype = RNA_property_subtype(but->rnaprop);
- }
-
- if (ui_but_is_float(but)) {
- int prec = (float_precision == -1) ? ui_but_calc_float_precision(but, value) : float_precision;
-
- if (ui_but_is_unit(but)) {
- ui_get_but_string_unit(but, str, maxlen, value, false, prec);
- }
- else if (subtype == PROP_FACTOR) {
- if (U.factor_display_type == USER_FACTOR_AS_FACTOR) {
- BLI_snprintf(str, maxlen, "%.*f", prec, value);
- }
- else {
- BLI_snprintf(str, maxlen, "%.*f", MAX2(0, prec - 2), value * 100);
- }
-
- }
- else {
- if (use_exp_float) {
- const int int_digits_num = integer_digits_f(value);
- if (int_digits_num < -6 || int_digits_num > 12) {
- BLI_snprintf(str, maxlen, "%.*g", prec, value);
- if (r_use_exp_float) {
- *r_use_exp_float = true;
- }
- }
- else {
- prec -= int_digits_num;
- CLAMP(prec, 0, UI_PRECISION_FLOAT_MAX);
- BLI_snprintf(str, maxlen, "%.*f", prec, value);
- }
- }
- else {
-#if 0 /* TODO, but will likely break some stuff, so better after 2.79 release. */
- prec -= int_digits_num;
- CLAMP(prec, 0, UI_PRECISION_FLOAT_MAX);
+void ui_but_string_get_ex(uiBut *but,
+ char *str,
+ const size_t maxlen,
+ const int float_precision,
+ const bool use_exp_float,
+ bool *r_use_exp_float)
+{
+ if (r_use_exp_float) {
+ *r_use_exp_float = false;
+ }
+
+ if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_TAB)) {
+ PropertyType type;
+ const char *buf = NULL;
+ int buf_len;
+
+ type = RNA_property_type(but->rnaprop);
+
+ if ((but->type == UI_BTYPE_TAB) && (but->custom_data)) {
+ StructRNA *ptr_type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
+ PointerRNA ptr;
+
+ /* uiBut.custom_data points to data this tab represents (e.g. workspace).
+ * uiBut.rnapoin/prop store an active value (e.g. active workspace). */
+ RNA_pointer_create(but->rnapoin.id.data, ptr_type, but->custom_data, &ptr);
+ buf = RNA_struct_name_get_alloc(&ptr, str, maxlen, &buf_len);
+ }
+ else if (type == PROP_STRING) {
+ /* RNA string */
+ buf = RNA_property_string_get_alloc(&but->rnapoin, but->rnaprop, str, maxlen, &buf_len);
+ }
+ else if (type == PROP_ENUM) {
+ /* RNA enum */
+ int value = RNA_property_enum_get(&but->rnapoin, but->rnaprop);
+ if (RNA_property_enum_name(but->block->evil_C, &but->rnapoin, but->rnaprop, value, &buf)) {
+ BLI_strncpy(str, buf, maxlen);
+ buf = str;
+ }
+ }
+ else if (type == PROP_POINTER) {
+ /* RNA pointer */
+ PointerRNA ptr = RNA_property_pointer_get(&but->rnapoin, but->rnaprop);
+ buf = RNA_struct_name_get_alloc(&ptr, str, maxlen, &buf_len);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ if (!buf) {
+ str[0] = '\0';
+ }
+ else if (buf && buf != str) {
+ BLI_assert(maxlen <= buf_len + 1);
+ /* string was too long, we have to truncate */
+ if (ui_but_is_utf8(but)) {
+ BLI_strncpy_utf8(str, buf, maxlen);
+ }
+ else {
+ BLI_strncpy(str, buf, maxlen);
+ }
+ MEM_freeN((void *)buf);
+ }
+ }
+ else if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
+ /* string */
+ BLI_strncpy(str, but->poin, maxlen);
+ return;
+ }
+ else if (ui_but_anim_expression_get(but, str, maxlen)) {
+ /* driver expression */
+ }
+ else {
+ /* number editing */
+ double value;
+
+ value = ui_but_value_get(but);
+
+ PropertySubType subtype = PROP_NONE;
+ if (but->rnaprop) {
+ subtype = RNA_property_subtype(but->rnaprop);
+ }
+
+ if (ui_but_is_float(but)) {
+ int prec = (float_precision == -1) ? ui_but_calc_float_precision(but, value) :
+ float_precision;
+
+ if (ui_but_is_unit(but)) {
+ ui_get_but_string_unit(but, str, maxlen, value, false, prec);
+ }
+ else if (subtype == PROP_FACTOR) {
+ if (U.factor_display_type == USER_FACTOR_AS_FACTOR) {
+ BLI_snprintf(str, maxlen, "%.*f", prec, value);
+ }
+ else {
+ BLI_snprintf(str, maxlen, "%.*f", MAX2(0, prec - 2), value * 100);
+ }
+ }
+ else {
+ if (use_exp_float) {
+ const int int_digits_num = integer_digits_f(value);
+ if (int_digits_num < -6 || int_digits_num > 12) {
+ BLI_snprintf(str, maxlen, "%.*g", prec, value);
+ if (r_use_exp_float) {
+ *r_use_exp_float = true;
+ }
+ }
+ else {
+ prec -= int_digits_num;
+ CLAMP(prec, 0, UI_PRECISION_FLOAT_MAX);
+ BLI_snprintf(str, maxlen, "%.*f", prec, value);
+ }
+ }
+ else {
+#if 0 /* TODO, but will likely break some stuff, so better after 2.79 release. */
+ prec -= int_digits_num;
+ CLAMP(prec, 0, UI_PRECISION_FLOAT_MAX);
#endif
- BLI_snprintf(str, maxlen, "%.*f", prec, value);
- }
- }
- }
- else {
- BLI_snprintf(str, maxlen, "%d", (int)value);
- }
- }
+ BLI_snprintf(str, maxlen, "%.*f", prec, value);
+ }
+ }
+ }
+ else {
+ BLI_snprintf(str, maxlen, "%d", (int)value);
+ }
+ }
}
void ui_but_string_get(uiBut *but, char *str, const size_t maxlen)
{
- ui_but_string_get_ex(but, str, maxlen, -1, false, NULL);
+ ui_but_string_get_ex(but, str, maxlen, -1, false, NULL);
}
/**
@@ -2517,438 +2563,449 @@ void ui_but_string_get(uiBut *but, char *str, const size_t maxlen)
*/
char *ui_but_string_get_dynamic(uiBut *but, int *r_str_size)
{
- char *str = NULL;
- *r_str_size = 1;
-
- if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
- PropertyType type;
-
- type = RNA_property_type(but->rnaprop);
-
- if (type == PROP_STRING) {
- /* RNA string */
- str = RNA_property_string_get_alloc(&but->rnapoin, but->rnaprop, NULL, 0, r_str_size);
- (*r_str_size) += 1;
- }
- else if (type == PROP_ENUM) {
- /* RNA enum */
- int value = RNA_property_enum_get(&but->rnapoin, but->rnaprop);
- const char *value_id;
- if (!RNA_property_enum_name(but->block->evil_C, &but->rnapoin, but->rnaprop, value, &value_id)) {
- value_id = "";
- }
-
- *r_str_size = strlen(value_id) + 1;
- str = BLI_strdupn(value_id, *r_str_size);
- }
- else if (type == PROP_POINTER) {
- /* RNA pointer */
- PointerRNA ptr = RNA_property_pointer_get(&but->rnapoin, but->rnaprop);
- str = RNA_struct_name_get_alloc(&ptr, NULL, 0, r_str_size);
- (*r_str_size) += 1;
- }
- else {
- BLI_assert(0);
- }
- }
- else {
- BLI_assert(0);
- }
-
- if (UNLIKELY(str == NULL)) {
- /* should never happen, paranoid check */
- *r_str_size = 1;
- str = BLI_strdup("");
- BLI_assert(0);
-
- }
-
- return str;
-}
-
-static bool ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char *str, double *r_value)
-{
- const UnitSettings *unit = but->block->unit;
- int type = RNA_SUBTYPE_UNIT_VALUE(UI_but_unit_type_get(but));
- return user_string_to_number(C, str, unit, type, r_value);
+ char *str = NULL;
+ *r_str_size = 1;
+
+ if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
+ PropertyType type;
+
+ type = RNA_property_type(but->rnaprop);
+
+ if (type == PROP_STRING) {
+ /* RNA string */
+ str = RNA_property_string_get_alloc(&but->rnapoin, but->rnaprop, NULL, 0, r_str_size);
+ (*r_str_size) += 1;
+ }
+ else if (type == PROP_ENUM) {
+ /* RNA enum */
+ int value = RNA_property_enum_get(&but->rnapoin, but->rnaprop);
+ const char *value_id;
+ if (!RNA_property_enum_name(
+ but->block->evil_C, &but->rnapoin, but->rnaprop, value, &value_id)) {
+ value_id = "";
+ }
+
+ *r_str_size = strlen(value_id) + 1;
+ str = BLI_strdupn(value_id, *r_str_size);
+ }
+ else if (type == PROP_POINTER) {
+ /* RNA pointer */
+ PointerRNA ptr = RNA_property_pointer_get(&but->rnapoin, but->rnaprop);
+ str = RNA_struct_name_get_alloc(&ptr, NULL, 0, r_str_size);
+ (*r_str_size) += 1;
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ if (UNLIKELY(str == NULL)) {
+ /* should never happen, paranoid check */
+ *r_str_size = 1;
+ str = BLI_strdup("");
+ BLI_assert(0);
+ }
+
+ return str;
+}
+
+static bool ui_set_but_string_eval_num_unit(bContext *C,
+ uiBut *but,
+ const char *str,
+ double *r_value)
+{
+ const UnitSettings *unit = but->block->unit;
+ int type = RNA_SUBTYPE_UNIT_VALUE(UI_but_unit_type_get(but));
+ return user_string_to_number(C, str, unit, type, r_value);
}
static bool ui_number_from_string(bContext *C, const char *str, double *r_value)
{
#ifdef WITH_PYTHON
- return BPY_execute_string_as_number(C, NULL, str, true, r_value);
+ return BPY_execute_string_as_number(C, NULL, str, true, r_value);
#else
- *r_value = atof(str);
- return true;
+ *r_value = atof(str);
+ return true;
#endif
}
static bool ui_number_from_string_factor(bContext *C, const char *str, double *r_value)
{
- int len = strlen(str);
- if (BLI_strn_endswith(str, "%", len)) {
- char *str_new = BLI_strdupn(str, len - 1);
- bool success = ui_number_from_string(C, str_new, r_value);
- MEM_freeN(str_new);
- *r_value /= 100.0;
- return success;
- }
- else {
- if (!ui_number_from_string(C, str, r_value)) {
- return false;
- }
- if (U.factor_display_type == USER_FACTOR_AS_PERCENTAGE) {
- *r_value /= 100.0;
- }
- return true;
- }
+ int len = strlen(str);
+ if (BLI_strn_endswith(str, "%", len)) {
+ char *str_new = BLI_strdupn(str, len - 1);
+ bool success = ui_number_from_string(C, str_new, r_value);
+ MEM_freeN(str_new);
+ *r_value /= 100.0;
+ return success;
+ }
+ else {
+ if (!ui_number_from_string(C, str, r_value)) {
+ return false;
+ }
+ if (U.factor_display_type == USER_FACTOR_AS_PERCENTAGE) {
+ *r_value /= 100.0;
+ }
+ return true;
+ }
}
static bool ui_number_from_string_percentage(bContext *C, const char *str, double *r_value)
{
- int len = strlen(str);
- if (BLI_strn_endswith(str, "%", len)) {
- char *str_new = BLI_strdupn(str, len - 1);
- bool success = ui_number_from_string(C, str_new, r_value);
- MEM_freeN(str_new);
- return success;
- }
- else {
- return ui_number_from_string(C, str, r_value);
- }
+ int len = strlen(str);
+ if (BLI_strn_endswith(str, "%", len)) {
+ char *str_new = BLI_strdupn(str, len - 1);
+ bool success = ui_number_from_string(C, str_new, r_value);
+ MEM_freeN(str_new);
+ return success;
+ }
+ else {
+ return ui_number_from_string(C, str, r_value);
+ }
}
bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double *r_value)
{
- if (str[0] == '\0') {
- *r_value = 0.0;
- return true;
- }
-
- PropertySubType subtype = PROP_NONE;
- if (but->rnaprop) {
- subtype = RNA_property_subtype(but->rnaprop);
- }
-
- if (ui_but_is_float(but)) {
- if (ui_but_is_unit(but)) {
- return ui_set_but_string_eval_num_unit(C, but, str, r_value);
- }
- else if (subtype == PROP_FACTOR) {
- return ui_number_from_string_factor(C, str, r_value);
- }
- else if (subtype == PROP_PERCENTAGE) {
- return ui_number_from_string_percentage(C, str, r_value);
- }
- else {
- return ui_number_from_string(C, str, r_value);
- }
- }
- else {
- return ui_number_from_string(C, str, r_value);
- }
+ if (str[0] == '\0') {
+ *r_value = 0.0;
+ return true;
+ }
+
+ PropertySubType subtype = PROP_NONE;
+ if (but->rnaprop) {
+ subtype = RNA_property_subtype(but->rnaprop);
+ }
+
+ if (ui_but_is_float(but)) {
+ if (ui_but_is_unit(but)) {
+ return ui_set_but_string_eval_num_unit(C, but, str, r_value);
+ }
+ else if (subtype == PROP_FACTOR) {
+ return ui_number_from_string_factor(C, str, r_value);
+ }
+ else if (subtype == PROP_PERCENTAGE) {
+ return ui_number_from_string_percentage(C, str, r_value);
+ }
+ else {
+ return ui_number_from_string(C, str, r_value);
+ }
+ }
+ else {
+ return ui_number_from_string(C, str, r_value);
+ }
}
/* just the assignment/free part */
static void ui_but_string_set_internal(uiBut *but, const char *str, size_t str_len)
{
- BLI_assert(str_len == strlen(str));
- BLI_assert(but->str == NULL);
- str_len += 1;
+ BLI_assert(str_len == strlen(str));
+ BLI_assert(but->str == NULL);
+ str_len += 1;
- if (str_len > UI_MAX_NAME_STR) {
- but->str = MEM_mallocN(str_len, "ui_def_but str");
- }
- else {
- but->str = but->strdata;
- }
- memcpy(but->str, str, str_len);
+ if (str_len > UI_MAX_NAME_STR) {
+ but->str = MEM_mallocN(str_len, "ui_def_but str");
+ }
+ else {
+ but->str = but->strdata;
+ }
+ memcpy(but->str, str, str_len);
}
static void ui_but_string_free_internal(uiBut *but)
{
- if (but->str) {
- if (but->str != but->strdata) {
- MEM_freeN(but->str);
- }
- /* must call 'ui_but_string_set_internal' after */
- but->str = NULL;
- }
+ if (but->str) {
+ if (but->str != but->strdata) {
+ MEM_freeN(but->str);
+ }
+ /* must call 'ui_but_string_set_internal' after */
+ but->str = NULL;
+ }
}
bool ui_but_string_set(bContext *C, uiBut *but, const char *str)
{
- if (but->rnaprop && but->rnapoin.data && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
- if (RNA_property_editable(&but->rnapoin, but->rnaprop)) {
- PropertyType type;
-
- type = RNA_property_type(but->rnaprop);
-
- if (type == PROP_STRING) {
- /* RNA string */
- RNA_property_string_set(&but->rnapoin, but->rnaprop, str);
- return true;
- }
- else if (type == PROP_POINTER) {
- if (str[0] == '\0') {
- RNA_property_pointer_set(&but->rnapoin, but->rnaprop, PointerRNA_NULL);
- return true;
- }
- else {
- /* RNA pointer */
- PointerRNA rptr;
- PointerRNA ptr = but->rnasearchpoin;
- PropertyRNA *prop = but->rnasearchprop;
-
- /* This is kind of hackish, in theory think we could only ever use the second member of
- * this if/else, since ui_searchbox_apply() is supposed to always set that pointer when
- * we are storing pointers... But keeping str search first for now, to try to break as little as
- * possible existing code. All this is band-aids anyway.
- * Fact remains, using editstr as main 'reference' over whole search button thingy is utterly weak
- * and should be redesigned imho, but that's not a simple task. */
- if (prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr)) {
- RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr);
- }
- else if (but->func_arg2 != NULL) {
- RNA_pointer_create(NULL, RNA_property_pointer_type(&but->rnapoin, but->rnaprop), but->func_arg2, &rptr);
- RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr);
- }
-
- return true;
- }
-
- return false;
- }
- else if (type == PROP_ENUM) {
- int value;
- if (RNA_property_enum_value(but->block->evil_C, &but->rnapoin, but->rnaprop, str, &value)) {
- RNA_property_enum_set(&but->rnapoin, but->rnaprop, value);
- return true;
- }
- return false;
- }
- else {
- BLI_assert(0);
- }
- }
- }
- else if (but->type == UI_BTYPE_TAB) {
- if (but->rnaprop && but->custom_data) {
- StructRNA *ptr_type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
- PointerRNA ptr;
- PropertyRNA *prop;
-
- /* uiBut.custom_data points to data this tab represents (e.g. workspace).
- * uiBut.rnapoin/prop store an active value (e.g. active workspace). */
- RNA_pointer_create(but->rnapoin.id.data, ptr_type, but->custom_data, &ptr);
- prop = RNA_struct_name_property(ptr_type);
- if (RNA_property_editable(&ptr, prop)) {
- RNA_property_string_set(&ptr, prop, str);
- }
- }
- }
- else if (but->type == UI_BTYPE_TEXT) {
- /* string */
- if (!but->poin) {
- str = "";
- }
- else if (ui_but_is_utf8(but)) {
- BLI_strncpy_utf8(but->poin, str, but->hardmax);
- }
- else {
- BLI_strncpy(but->poin, str, but->hardmax);
- }
-
- return true;
- }
- else if (but->type == UI_BTYPE_SEARCH_MENU) {
- /* string */
- BLI_strncpy(but->poin, str, but->hardmax);
- return true;
- }
- else if (ui_but_anim_expression_set(but, str)) {
- /* driver expression */
- return true;
- }
- else if (str[0] == '#') {
- /* shortcut to create new driver expression (versus immediate Py-execution) */
- return ui_but_anim_expression_create(but, str + 1);
- }
- else {
- /* number editing */
- double value;
-
- if (ui_but_string_set_eval_num(C, but, str, &value) == false) {
- WM_report_banner_show();
- return false;
- }
-
- if (!ui_but_is_float(but)) {
- value = floor(value + 0.5);
- }
-
- /* not that we use hard limits here */
- if (value < (double)but->hardmin) { value = but->hardmin; }
- if (value > (double)but->hardmax) { value = but->hardmax; }
-
- ui_but_value_set(but, value);
- return true;
- }
-
- return false;
+ if (but->rnaprop && but->rnapoin.data && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
+ if (RNA_property_editable(&but->rnapoin, but->rnaprop)) {
+ PropertyType type;
+
+ type = RNA_property_type(but->rnaprop);
+
+ if (type == PROP_STRING) {
+ /* RNA string */
+ RNA_property_string_set(&but->rnapoin, but->rnaprop, str);
+ return true;
+ }
+ else if (type == PROP_POINTER) {
+ if (str[0] == '\0') {
+ RNA_property_pointer_set(&but->rnapoin, but->rnaprop, PointerRNA_NULL);
+ return true;
+ }
+ else {
+ /* RNA pointer */
+ PointerRNA rptr;
+ PointerRNA ptr = but->rnasearchpoin;
+ PropertyRNA *prop = but->rnasearchprop;
+
+ /* This is kind of hackish, in theory think we could only ever use the second member of
+ * this if/else, since ui_searchbox_apply() is supposed to always set that pointer when
+ * we are storing pointers... But keeping str search first for now, to try to break as little as
+ * possible existing code. All this is band-aids anyway.
+ * Fact remains, using editstr as main 'reference' over whole search button thingy is utterly weak
+ * and should be redesigned imho, but that's not a simple task. */
+ if (prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr)) {
+ RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr);
+ }
+ else if (but->func_arg2 != NULL) {
+ RNA_pointer_create(NULL,
+ RNA_property_pointer_type(&but->rnapoin, but->rnaprop),
+ but->func_arg2,
+ &rptr);
+ RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr);
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+ else if (type == PROP_ENUM) {
+ int value;
+ if (RNA_property_enum_value(
+ but->block->evil_C, &but->rnapoin, but->rnaprop, str, &value)) {
+ RNA_property_enum_set(&but->rnapoin, but->rnaprop, value);
+ return true;
+ }
+ return false;
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ }
+ else if (but->type == UI_BTYPE_TAB) {
+ if (but->rnaprop && but->custom_data) {
+ StructRNA *ptr_type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ /* uiBut.custom_data points to data this tab represents (e.g. workspace).
+ * uiBut.rnapoin/prop store an active value (e.g. active workspace). */
+ RNA_pointer_create(but->rnapoin.id.data, ptr_type, but->custom_data, &ptr);
+ prop = RNA_struct_name_property(ptr_type);
+ if (RNA_property_editable(&ptr, prop)) {
+ RNA_property_string_set(&ptr, prop, str);
+ }
+ }
+ }
+ else if (but->type == UI_BTYPE_TEXT) {
+ /* string */
+ if (!but->poin) {
+ str = "";
+ }
+ else if (ui_but_is_utf8(but)) {
+ BLI_strncpy_utf8(but->poin, str, but->hardmax);
+ }
+ else {
+ BLI_strncpy(but->poin, str, but->hardmax);
+ }
+
+ return true;
+ }
+ else if (but->type == UI_BTYPE_SEARCH_MENU) {
+ /* string */
+ BLI_strncpy(but->poin, str, but->hardmax);
+ return true;
+ }
+ else if (ui_but_anim_expression_set(but, str)) {
+ /* driver expression */
+ return true;
+ }
+ else if (str[0] == '#') {
+ /* shortcut to create new driver expression (versus immediate Py-execution) */
+ return ui_but_anim_expression_create(but, str + 1);
+ }
+ else {
+ /* number editing */
+ double value;
+
+ if (ui_but_string_set_eval_num(C, but, str, &value) == false) {
+ WM_report_banner_show();
+ return false;
+ }
+
+ if (!ui_but_is_float(but)) {
+ value = floor(value + 0.5);
+ }
+
+ /* not that we use hard limits here */
+ if (value < (double)but->hardmin) {
+ value = but->hardmin;
+ }
+ if (value > (double)but->hardmax) {
+ value = but->hardmax;
+ }
+
+ ui_but_value_set(but, value);
+ return true;
+ }
+
+ return false;
}
void ui_but_default_set(bContext *C, const bool all, const bool use_afterfunc)
{
- wmOperatorType *ot = WM_operatortype_find("UI_OT_reset_default_button", true);
+ wmOperatorType *ot = WM_operatortype_find("UI_OT_reset_default_button", true);
- if (use_afterfunc) {
- PointerRNA *ptr;
- ptr = ui_handle_afterfunc_add_operator(ot, WM_OP_EXEC_DEFAULT, true);
- RNA_boolean_set(ptr, "all", all);
- }
- else {
- PointerRNA ptr;
- WM_operator_properties_create_ptr(&ptr, ot);
- RNA_boolean_set(&ptr, "all", all);
- WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &ptr);
- WM_operator_properties_free(&ptr);
- }
+ if (use_afterfunc) {
+ PointerRNA *ptr;
+ ptr = ui_handle_afterfunc_add_operator(ot, WM_OP_EXEC_DEFAULT, true);
+ RNA_boolean_set(ptr, "all", all);
+ }
+ else {
+ PointerRNA ptr;
+ WM_operator_properties_create_ptr(&ptr, ot);
+ RNA_boolean_set(&ptr, "all", all);
+ WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &ptr);
+ WM_operator_properties_free(&ptr);
+ }
}
static double soft_range_round_up(double value, double max)
{
- /* round up to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, ..
- * checking for 0.0 prevents floating point exceptions */
- double newmax = (value != 0.0) ? pow(10.0, ceil(log(value) / M_LN10)) : 0.0;
+ /* round up to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, ..
+ * checking for 0.0 prevents floating point exceptions */
+ double newmax = (value != 0.0) ? pow(10.0, ceil(log(value) / M_LN10)) : 0.0;
- if (newmax * 0.2 >= max && newmax * 0.2 >= value) {
- return newmax * 0.2;
- }
- else if (newmax * 0.5 >= max && newmax * 0.5 >= value) {
- return newmax * 0.5;
- }
- else {
- return newmax;
- }
+ if (newmax * 0.2 >= max && newmax * 0.2 >= value) {
+ return newmax * 0.2;
+ }
+ else if (newmax * 0.5 >= max && newmax * 0.5 >= value) {
+ return newmax * 0.5;
+ }
+ else {
+ return newmax;
+ }
}
static double soft_range_round_down(double value, double max)
{
- /* round down to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, ..
- * checking for 0.0 prevents floating point exceptions */
- double newmax = (value != 0.0) ? pow(10.0, floor(log(value) / M_LN10)) : 0.0;
+ /* round down to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, ..
+ * checking for 0.0 prevents floating point exceptions */
+ double newmax = (value != 0.0) ? pow(10.0, floor(log(value) / M_LN10)) : 0.0;
- if (newmax * 5.0 <= max && newmax * 5.0 <= value) {
- return newmax * 5.0;
- }
- else if (newmax * 2.0 <= max && newmax * 2.0 <= value) {
- return newmax * 2.0;
- }
- else {
- return newmax;
- }
+ if (newmax * 5.0 <= max && newmax * 5.0 <= value) {
+ return newmax * 5.0;
+ }
+ else if (newmax * 2.0 <= max && newmax * 2.0 <= value) {
+ return newmax * 2.0;
+ }
+ else {
+ return newmax;
+ }
}
/* note: this could be split up into functions which handle arrays and not */
static void ui_set_but_soft_range(uiBut *but)
{
- /* ideally we would not limit this but practically, its more than
- * enough worst case is very long vectors wont use a smart soft-range
- * which isn't so bad. */
-
- if (but->rnaprop) {
- const PropertyType type = RNA_property_type(but->rnaprop);
- double softmin, softmax /*, step, precision*/;
- double value_min;
- double value_max;
-
- /* clamp button range to something reasonable in case
- * we get -inf/inf from RNA properties */
- if (type == PROP_INT) {
- const bool is_array = RNA_property_array_check(but->rnaprop);
- int imin, imax, istep;
-
- RNA_property_int_ui_range(&but->rnapoin, but->rnaprop, &imin, &imax, &istep);
- softmin = (imin == INT_MIN) ? -1e4 : imin;
- softmax = (imin == INT_MAX) ? 1e4 : imax;
- /*step = istep;*/ /*UNUSED*/
- /*precision = 1;*/ /*UNUSED*/
-
- if (is_array) {
- int value_range[2];
- RNA_property_int_get_array_range(&but->rnapoin, but->rnaprop, value_range);
- value_min = (double)value_range[0];
- value_max = (double)value_range[1];
- }
- else {
- value_min = value_max = (double)RNA_property_int_get(&but->rnapoin, but->rnaprop);
- }
- }
- else if (type == PROP_FLOAT) {
- const bool is_array = RNA_property_array_check(but->rnaprop);
- float fmin, fmax, fstep, fprecision;
-
- RNA_property_float_ui_range(&but->rnapoin, but->rnaprop, &fmin, &fmax, &fstep, &fprecision);
- softmin = (fmin == -FLT_MAX) ? (float)-1e4 : fmin;
- softmax = (fmax == FLT_MAX) ? (float)1e4 : fmax;
- /*step = fstep;*/ /*UNUSED*/
- /*precision = fprecision;*/ /*UNUSED*/
-
- if (is_array) {
- float value_range[2];
- RNA_property_float_get_array_range(&but->rnapoin, but->rnaprop, value_range);
- value_min = (double)value_range[0];
- value_max = (double)value_range[1];
- }
- else {
- value_min = value_max = (double)RNA_property_float_get(&but->rnapoin, but->rnaprop);
- }
- }
- else {
- return;
- }
-
- /* if the value goes out of the soft/max range, adapt the range */
- if (value_min + 1e-10 < softmin) {
- if (value_min < 0.0) {
- softmin = -soft_range_round_up(-value_min, -softmin);
- }
- else {
- softmin = soft_range_round_down(value_min, softmin);
- }
-
- if (softmin < (double)but->hardmin) {
- softmin = (double)but->hardmin;
- }
- }
- if (value_max - 1e-10 > softmax) {
- if (value_max < 0.0) {
- softmax = -soft_range_round_down(-value_max, -softmax);
- }
- else {
- softmax = soft_range_round_up(value_max, softmax);
- }
-
- if (softmax > (double)but->hardmax) {
- softmax = but->hardmax;
- }
- }
-
- but->softmin = softmin;
- but->softmax = softmax;
- }
- else if (but->poin && (but->pointype & UI_BUT_POIN_TYPES)) {
- float value = ui_but_value_get(but);
- if (isfinite(value)) {
- CLAMP(value, but->hardmin, but->hardmax);
- but->softmin = min_ff(but->softmin, value);
- but->softmax = max_ff(but->softmax, value);
- }
- }
- else {
- BLI_assert(0);
- }
+ /* ideally we would not limit this but practically, its more than
+ * enough worst case is very long vectors wont use a smart soft-range
+ * which isn't so bad. */
+
+ if (but->rnaprop) {
+ const PropertyType type = RNA_property_type(but->rnaprop);
+ double softmin, softmax /*, step, precision*/;
+ double value_min;
+ double value_max;
+
+ /* clamp button range to something reasonable in case
+ * we get -inf/inf from RNA properties */
+ if (type == PROP_INT) {
+ const bool is_array = RNA_property_array_check(but->rnaprop);
+ int imin, imax, istep;
+
+ RNA_property_int_ui_range(&but->rnapoin, but->rnaprop, &imin, &imax, &istep);
+ softmin = (imin == INT_MIN) ? -1e4 : imin;
+ softmax = (imin == INT_MAX) ? 1e4 : imax;
+ /*step = istep;*/ /*UNUSED*/
+ /*precision = 1;*/ /*UNUSED*/
+
+ if (is_array) {
+ int value_range[2];
+ RNA_property_int_get_array_range(&but->rnapoin, but->rnaprop, value_range);
+ value_min = (double)value_range[0];
+ value_max = (double)value_range[1];
+ }
+ else {
+ value_min = value_max = (double)RNA_property_int_get(&but->rnapoin, but->rnaprop);
+ }
+ }
+ else if (type == PROP_FLOAT) {
+ const bool is_array = RNA_property_array_check(but->rnaprop);
+ float fmin, fmax, fstep, fprecision;
+
+ RNA_property_float_ui_range(&but->rnapoin, but->rnaprop, &fmin, &fmax, &fstep, &fprecision);
+ softmin = (fmin == -FLT_MAX) ? (float)-1e4 : fmin;
+ softmax = (fmax == FLT_MAX) ? (float)1e4 : fmax;
+ /*step = fstep;*/ /*UNUSED*/
+ /*precision = fprecision;*/ /*UNUSED*/
+
+ if (is_array) {
+ float value_range[2];
+ RNA_property_float_get_array_range(&but->rnapoin, but->rnaprop, value_range);
+ value_min = (double)value_range[0];
+ value_max = (double)value_range[1];
+ }
+ else {
+ value_min = value_max = (double)RNA_property_float_get(&but->rnapoin, but->rnaprop);
+ }
+ }
+ else {
+ return;
+ }
+
+ /* if the value goes out of the soft/max range, adapt the range */
+ if (value_min + 1e-10 < softmin) {
+ if (value_min < 0.0) {
+ softmin = -soft_range_round_up(-value_min, -softmin);
+ }
+ else {
+ softmin = soft_range_round_down(value_min, softmin);
+ }
+
+ if (softmin < (double)but->hardmin) {
+ softmin = (double)but->hardmin;
+ }
+ }
+ if (value_max - 1e-10 > softmax) {
+ if (value_max < 0.0) {
+ softmax = -soft_range_round_down(-value_max, -softmax);
+ }
+ else {
+ softmax = soft_range_round_up(value_max, softmax);
+ }
+
+ if (softmax > (double)but->hardmax) {
+ softmax = but->hardmax;
+ }
+ }
+
+ but->softmin = softmin;
+ but->softmax = softmax;
+ }
+ else if (but->poin && (but->pointype & UI_BUT_POIN_TYPES)) {
+ float value = ui_but_value_get(but);
+ if (isfinite(value)) {
+ CLAMP(value, but->hardmin, but->hardmax);
+ but->softmin = min_ff(but->softmin, value);
+ but->softmax = max_ff(but->softmax, value);
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
}
/* ******************* Free ********************/
@@ -2956,278 +3013,278 @@ static void ui_set_but_soft_range(uiBut *but)
/* can be called with C==NULL */
static void ui_but_free(const bContext *C, uiBut *but)
{
- if (but->opptr) {
- WM_operator_properties_free(but->opptr);
- MEM_freeN(but->opptr);
- }
-
- if (but->func_argN) {
- MEM_freeN(but->func_argN);
- }
-
- if (but->tip_argN) {
- MEM_freeN(but->tip_argN);
- }
-
- if (but->hold_argN) {
- MEM_freeN(but->hold_argN);
- }
-
- if (but->free_search_arg) {
- MEM_SAFE_FREE(but->search_arg);
- }
-
- if (but->active) {
- /* XXX solve later, buttons should be free-able without context ideally,
- * however they may have open tooltips or popup windows, which need to
- * be closed using a context pointer */
- if (C) {
- ui_but_active_free(C, but);
- }
- else {
- if (but->active) {
- MEM_freeN(but->active);
- }
- }
- }
- if (but->str && but->str != but->strdata) {
- MEM_freeN(but->str);
- }
-
- if ((but->type == UI_BTYPE_IMAGE) && but->poin) {
- IMB_freeImBuf((struct ImBuf *)but->poin);
- }
-
- if (but->dragpoin && (but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
- MEM_freeN(but->dragpoin);
- }
-
- BLI_assert(UI_butstore_is_registered(but->block, but) == false);
-
- MEM_freeN(but);
+ if (but->opptr) {
+ WM_operator_properties_free(but->opptr);
+ MEM_freeN(but->opptr);
+ }
+
+ if (but->func_argN) {
+ MEM_freeN(but->func_argN);
+ }
+
+ if (but->tip_argN) {
+ MEM_freeN(but->tip_argN);
+ }
+
+ if (but->hold_argN) {
+ MEM_freeN(but->hold_argN);
+ }
+
+ if (but->free_search_arg) {
+ MEM_SAFE_FREE(but->search_arg);
+ }
+
+ if (but->active) {
+ /* XXX solve later, buttons should be free-able without context ideally,
+ * however they may have open tooltips or popup windows, which need to
+ * be closed using a context pointer */
+ if (C) {
+ ui_but_active_free(C, but);
+ }
+ else {
+ if (but->active) {
+ MEM_freeN(but->active);
+ }
+ }
+ }
+ if (but->str && but->str != but->strdata) {
+ MEM_freeN(but->str);
+ }
+
+ if ((but->type == UI_BTYPE_IMAGE) && but->poin) {
+ IMB_freeImBuf((struct ImBuf *)but->poin);
+ }
+
+ if (but->dragpoin && (but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
+ MEM_freeN(but->dragpoin);
+ }
+
+ BLI_assert(UI_butstore_is_registered(but->block, but) == false);
+
+ MEM_freeN(but);
}
/* can be called with C==NULL */
void UI_block_free(const bContext *C, uiBlock *block)
{
- uiBut *but;
+ uiBut *but;
- UI_butstore_clear(block);
+ UI_butstore_clear(block);
- while ((but = BLI_pophead(&block->buttons))) {
- ui_but_free(C, but);
- }
+ while ((but = BLI_pophead(&block->buttons))) {
+ ui_but_free(C, but);
+ }
- if (block->unit) {
- MEM_freeN(block->unit);
- }
+ if (block->unit) {
+ MEM_freeN(block->unit);
+ }
- if (block->func_argN) {
- MEM_freeN(block->func_argN);
- }
+ if (block->func_argN) {
+ MEM_freeN(block->func_argN);
+ }
- CTX_store_free_list(&block->contexts);
+ CTX_store_free_list(&block->contexts);
- BLI_freelistN(&block->saferct);
- BLI_freelistN(&block->color_pickers.list);
+ BLI_freelistN(&block->saferct);
+ BLI_freelistN(&block->color_pickers.list);
- MEM_freeN(block);
+ MEM_freeN(block);
}
void UI_blocklist_update_window_matrix(const bContext *C, const ListBase *lb)
{
- ARegion *region = CTX_wm_region(C);
- wmWindow *window = CTX_wm_window(C);
+ ARegion *region = CTX_wm_region(C);
+ wmWindow *window = CTX_wm_window(C);
- for (uiBlock *block = lb->first; block; block = block->next) {
- if (block->active) {
- ui_update_window_matrix(window, region, block);
- }
- }
+ for (uiBlock *block = lb->first; block; block = block->next) {
+ if (block->active) {
+ ui_update_window_matrix(window, region, block);
+ }
+ }
}
void UI_blocklist_draw(const bContext *C, const ListBase *lb)
{
- for (uiBlock *block = lb->first; block; block = block->next) {
- if (block->active) {
- UI_block_draw(C, block);
- }
- }
+ for (uiBlock *block = lb->first; block; block = block->next) {
+ if (block->active) {
+ UI_block_draw(C, block);
+ }
+ }
}
/* can be called with C==NULL */
void UI_blocklist_free(const bContext *C, ListBase *lb)
{
- uiBlock *block;
+ uiBlock *block;
- while ((block = BLI_pophead(lb))) {
- UI_block_free(C, block);
- }
+ while ((block = BLI_pophead(lb))) {
+ UI_block_free(C, block);
+ }
}
void UI_blocklist_free_inactive(const bContext *C, ListBase *lb)
{
- uiBlock *block, *nextblock;
+ uiBlock *block, *nextblock;
- for (block = lb->first; block; block = nextblock) {
- nextblock = block->next;
+ for (block = lb->first; block; block = nextblock) {
+ nextblock = block->next;
- if (!block->handle) {
- if (!block->active) {
- BLI_remlink(lb, block);
- UI_block_free(C, block);
- }
- else {
- block->active = 0;
- }
- }
- }
+ if (!block->handle) {
+ if (!block->active) {
+ BLI_remlink(lb, block);
+ UI_block_free(C, block);
+ }
+ else {
+ block->active = 0;
+ }
+ }
+ }
}
void UI_block_region_set(uiBlock *block, ARegion *region)
{
- ListBase *lb = &region->uiblocks;
- uiBlock *oldblock = NULL;
+ ListBase *lb = &region->uiblocks;
+ uiBlock *oldblock = NULL;
- /* each listbase only has one block with this name, free block
- * if is already there so it can be rebuilt from scratch */
- if (lb) {
- oldblock = BLI_findstring(lb, block->name, offsetof(uiBlock, name));
+ /* each listbase only has one block with this name, free block
+ * if is already there so it can be rebuilt from scratch */
+ if (lb) {
+ oldblock = BLI_findstring(lb, block->name, offsetof(uiBlock, name));
- if (oldblock) {
- oldblock->active = 0;
- oldblock->panel = NULL;
- oldblock->handle = NULL;
- }
+ if (oldblock) {
+ oldblock->active = 0;
+ oldblock->panel = NULL;
+ oldblock->handle = NULL;
+ }
- /* at the beginning of the list! for dynamical menus/blocks */
- BLI_addhead(lb, block);
- }
+ /* at the beginning of the list! for dynamical menus/blocks */
+ BLI_addhead(lb, block);
+ }
- block->oldblock = oldblock;
+ block->oldblock = oldblock;
}
uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, short dt)
{
- uiBlock *block;
- wmWindow *window;
- Scene *scn;
+ uiBlock *block;
+ wmWindow *window;
+ Scene *scn;
- window = CTX_wm_window(C);
- scn = CTX_data_scene(C);
+ window = CTX_wm_window(C);
+ scn = CTX_data_scene(C);
- block = MEM_callocN(sizeof(uiBlock), "uiBlock");
- block->active = 1;
- block->dt = dt;
- block->evil_C = (void *)C; /* XXX */
+ block = MEM_callocN(sizeof(uiBlock), "uiBlock");
+ block->active = 1;
+ block->dt = dt;
+ block->evil_C = (void *)C; /* XXX */
- if (scn) {
- /* store display device name, don't lookup for transformations yet
- * block could be used for non-color displays where looking up for transformation
- * would slow down redraw, so only lookup for actual transform when it's indeed
- * needed
- */
- STRNCPY(block->display_device, scn->display_settings.display_device);
+ if (scn) {
+ /* store display device name, don't lookup for transformations yet
+ * block could be used for non-color displays where looking up for transformation
+ * would slow down redraw, so only lookup for actual transform when it's indeed
+ * needed
+ */
+ STRNCPY(block->display_device, scn->display_settings.display_device);
- /* copy to avoid crash when scene gets deleted with ui still open */
- block->unit = MEM_mallocN(sizeof(scn->unit), "UI UnitSettings");
- memcpy(block->unit, &scn->unit, sizeof(scn->unit));
- }
- else {
- STRNCPY(block->display_device, IMB_colormanagement_display_get_default_name());
- }
+ /* copy to avoid crash when scene gets deleted with ui still open */
+ block->unit = MEM_mallocN(sizeof(scn->unit), "UI UnitSettings");
+ memcpy(block->unit, &scn->unit, sizeof(scn->unit));
+ }
+ else {
+ STRNCPY(block->display_device, IMB_colormanagement_display_get_default_name());
+ }
- BLI_strncpy(block->name, name, sizeof(block->name));
+ BLI_strncpy(block->name, name, sizeof(block->name));
- if (region) {
- UI_block_region_set(block, region);
- }
+ if (region) {
+ UI_block_region_set(block, region);
+ }
- /* Set window matrix and aspect for region and OpenGL state. */
- ui_update_window_matrix(window, region, block);
+ /* Set window matrix and aspect for region and OpenGL state. */
+ ui_update_window_matrix(window, region, block);
- /* Tag as popup menu if not created within a region. */
- if (!(region && region->visible)) {
- block->auto_open = true;
- block->flag |= UI_BLOCK_LOOP;
- }
+ /* Tag as popup menu if not created within a region. */
+ if (!(region && region->visible)) {
+ block->auto_open = true;
+ block->flag |= UI_BLOCK_LOOP;
+ }
- return block;
+ return block;
}
void UI_block_emboss_set(uiBlock *block, char dt)
{
- block->dt = dt;
+ block->dt = dt;
}
void UI_block_theme_style_set(uiBlock *block, char theme_style)
{
- block->theme_style = theme_style;
+ block->theme_style = theme_style;
}
static void ui_but_build_drawstr_float(uiBut *but, double value)
{
- size_t slen = 0;
- STR_CONCAT(but->drawstr, slen, but->str);
-
- PropertySubType subtype = PROP_NONE;
- if (but->rnaprop) {
- subtype = RNA_property_subtype(but->rnaprop);
- }
-
- if (value == (double)FLT_MAX) {
- STR_CONCAT(but->drawstr, slen, "inf");
- }
- else if (value == (double)-FLT_MIN) {
- STR_CONCAT(but->drawstr, slen, "-inf");
- }
- else if (subtype == PROP_PERCENTAGE) {
- int prec = ui_but_calc_float_precision(but, value);
- STR_CONCATF(but->drawstr, slen, "%.*f %%", prec, value);
- }
- else if (subtype == PROP_PIXEL) {
- int prec = ui_but_calc_float_precision(but, value);
- STR_CONCATF(but->drawstr, slen, "%.*f px", prec, value);
- }
- else if (subtype == PROP_FACTOR) {
- int precision = ui_but_calc_float_precision(but, value);
-
- if (U.factor_display_type == USER_FACTOR_AS_FACTOR) {
- STR_CONCATF(but->drawstr, slen, "%.*f", precision, value);
- }
- else {
- STR_CONCATF(but->drawstr, slen, "%.*f %%", MAX2(0, precision - 2), value * 100);
- }
- }
- else if (ui_but_is_unit(but)) {
- char new_str[sizeof(but->drawstr)];
- ui_get_but_string_unit(but, new_str, sizeof(new_str), value, true, -1);
- STR_CONCAT(but->drawstr, slen, new_str);
- }
- else {
- int prec = ui_but_calc_float_precision(but, value);
- STR_CONCATF(but->drawstr, slen, "%.*f", prec, value);
- }
+ size_t slen = 0;
+ STR_CONCAT(but->drawstr, slen, but->str);
+
+ PropertySubType subtype = PROP_NONE;
+ if (but->rnaprop) {
+ subtype = RNA_property_subtype(but->rnaprop);
+ }
+
+ if (value == (double)FLT_MAX) {
+ STR_CONCAT(but->drawstr, slen, "inf");
+ }
+ else if (value == (double)-FLT_MIN) {
+ STR_CONCAT(but->drawstr, slen, "-inf");
+ }
+ else if (subtype == PROP_PERCENTAGE) {
+ int prec = ui_but_calc_float_precision(but, value);
+ STR_CONCATF(but->drawstr, slen, "%.*f %%", prec, value);
+ }
+ else if (subtype == PROP_PIXEL) {
+ int prec = ui_but_calc_float_precision(but, value);
+ STR_CONCATF(but->drawstr, slen, "%.*f px", prec, value);
+ }
+ else if (subtype == PROP_FACTOR) {
+ int precision = ui_but_calc_float_precision(but, value);
+
+ if (U.factor_display_type == USER_FACTOR_AS_FACTOR) {
+ STR_CONCATF(but->drawstr, slen, "%.*f", precision, value);
+ }
+ else {
+ STR_CONCATF(but->drawstr, slen, "%.*f %%", MAX2(0, precision - 2), value * 100);
+ }
+ }
+ else if (ui_but_is_unit(but)) {
+ char new_str[sizeof(but->drawstr)];
+ ui_get_but_string_unit(but, new_str, sizeof(new_str), value, true, -1);
+ STR_CONCAT(but->drawstr, slen, new_str);
+ }
+ else {
+ int prec = ui_but_calc_float_precision(but, value);
+ STR_CONCATF(but->drawstr, slen, "%.*f", prec, value);
+ }
}
static void ui_but_build_drawstr_int(uiBut *but, int value)
{
- size_t slen = 0;
- STR_CONCAT(but->drawstr, slen, but->str);
+ size_t slen = 0;
+ STR_CONCAT(but->drawstr, slen, but->str);
- PropertySubType subtype = PROP_NONE;
- if (but->rnaprop) {
- subtype = RNA_property_subtype(but->rnaprop);
- }
+ PropertySubType subtype = PROP_NONE;
+ if (but->rnaprop) {
+ subtype = RNA_property_subtype(but->rnaprop);
+ }
- STR_CONCATF(but->drawstr, slen, "%d", value);
+ STR_CONCATF(but->drawstr, slen, "%d", value);
- if (subtype == PROP_PERCENTAGE) {
- STR_CONCAT(but->drawstr, slen, "%");
- }
- else if (subtype == PROP_PIXEL) {
- STR_CONCAT(but->drawstr, slen, " px");
- }
+ if (subtype == PROP_PERCENTAGE) {
+ STR_CONCAT(but->drawstr, slen, "%");
+ }
+ else if (subtype == PROP_PIXEL) {
+ STR_CONCAT(but->drawstr, slen, " px");
+ }
}
/**
@@ -3237,233 +3294,225 @@ static void ui_but_build_drawstr_int(uiBut *but, int value)
*/
static void ui_but_update_ex(uiBut *but, const bool validate)
{
- /* if something changed in the button */
- double value = UI_BUT_VALUE_UNSET;
-
- ui_but_update_select_flag(but, &value);
-
- /* only update soft range while not editing */
- if (!ui_but_is_editing(but)) {
- if ((but->rnaprop != NULL) ||
- (but->poin && (but->pointype & UI_BUT_POIN_TYPES)))
- {
- ui_set_but_soft_range(but);
- }
- }
-
- /* test for min and max, icon sliders, etc */
- switch (but->type) {
- case UI_BTYPE_NUM:
- case UI_BTYPE_SCROLL:
- case UI_BTYPE_NUM_SLIDER:
- if (validate) {
- UI_GET_BUT_VALUE_INIT(but, value);
- if (value < (double)but->hardmin) {
- ui_but_value_set(but, but->hardmin);
- }
- else if (value > (double)but->hardmax) {
- ui_but_value_set(but, but->hardmax);
- }
-
- /* max must never be smaller than min! Both being equal is allowed though */
- BLI_assert(but->softmin <= but->softmax &&
- but->hardmin <= but->hardmax);
- }
- break;
-
- case UI_BTYPE_ICON_TOGGLE:
- case UI_BTYPE_ICON_TOGGLE_N:
- if ((but->rnaprop == NULL) || (RNA_property_flag(but->rnaprop) & PROP_ICONS_CONSECUTIVE)) {
- if (but->rnaprop && RNA_property_flag(but->rnaprop) & PROP_ICONS_REVERSE) {
- but->drawflag |= UI_BUT_ICON_REVERSE;
- }
-
- but->iconadd = (but->flag & UI_SELECT) ? 1 : 0;
- }
- break;
-
- /* quiet warnings for unhandled types */
- default:
- break;
- }
-
-
- /* safety is 4 to enable small number buttons (like 'users') */
- // okwidth = -4 + (BLI_rcti_size_x(&but->rect)); // UNUSED
-
- /* name: */
- switch (but->type) {
-
- case UI_BTYPE_MENU:
- if (BLI_rctf_size_x(&but->rect) >= (UI_UNIT_X * 2)) {
- /* only needed for menus in popup blocks that don't recreate buttons on redraw */
- if (but->block->flag & UI_BLOCK_LOOP) {
- if (but->rnaprop && (RNA_property_type(but->rnaprop) == PROP_ENUM)) {
- int value_enum = RNA_property_enum_get(&but->rnapoin, but->rnaprop);
-
- EnumPropertyItem item;
- if (RNA_property_enum_item_from_value_gettexted(
- but->block->evil_C,
- &but->rnapoin, but->rnaprop, value_enum, &item))
- {
- size_t slen = strlen(item.name);
- ui_but_string_free_internal(but);
- ui_but_string_set_internal(but, item.name, slen);
- but->icon = item.icon;
- }
- }
- }
- BLI_strncpy(but->drawstr, but->str, sizeof(but->drawstr));
- }
- break;
-
- case UI_BTYPE_NUM:
- case UI_BTYPE_NUM_SLIDER:
- if (but->editstr) {
- break;
- }
- UI_GET_BUT_VALUE_INIT(but, value);
- if (ui_but_is_float(but)) {
- ui_but_build_drawstr_float(but, value);
- }
- else {
- ui_but_build_drawstr_int(but, (int)value);
- }
- break;
-
- case UI_BTYPE_LABEL:
- if (ui_but_is_float(but)) {
- int prec;
- UI_GET_BUT_VALUE_INIT(but, value);
- prec = ui_but_calc_float_precision(but, value);
- BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%.*f", but->str, prec, value);
- }
- else {
- BLI_strncpy(but->drawstr, but->str, UI_MAX_DRAW_STR);
- }
-
- break;
-
- case UI_BTYPE_TEXT:
- case UI_BTYPE_SEARCH_MENU:
- if (!but->editstr) {
- char str[UI_MAX_DRAW_STR];
-
- ui_but_string_get(but, str, UI_MAX_DRAW_STR);
- BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%s", but->str, str);
- }
- break;
-
- case UI_BTYPE_KEY_EVENT:
- {
- const char *str;
- if (but->flag & UI_SELECT) {
- str = "Press a key";
- }
- else {
- UI_GET_BUT_VALUE_INIT(but, value);
- str = WM_key_event_string((short)value, false);
- }
- BLI_snprintf(but->drawstr, UI_MAX_DRAW_STR, "%s%s", but->str, str);
- break;
- }
- case UI_BTYPE_HOTKEY_EVENT:
- if (but->flag & UI_SELECT) {
-
- if (but->modifier_key) {
- char *str = but->drawstr;
- but->drawstr[0] = '\0';
-
- if (but->modifier_key & KM_SHIFT) {
- str += BLI_strcpy_rlen(str, "Shift ");
- }
- if (but->modifier_key & KM_CTRL) {
- str += BLI_strcpy_rlen(str, "Ctrl ");
- }
- if (but->modifier_key & KM_ALT) {
- str += BLI_strcpy_rlen(str, "Alt ");
- }
- if (but->modifier_key & KM_OSKEY) {
- str += BLI_strcpy_rlen(str, "Cmd ");
- }
-
- (void)str; /* UNUSED */
- }
- else {
- BLI_strncpy(but->drawstr, "Press a key", UI_MAX_DRAW_STR);
- }
- }
- else {
- BLI_strncpy(but->drawstr, but->str, UI_MAX_DRAW_STR);
- }
-
- break;
-
- case UI_BTYPE_HSVCUBE:
- case UI_BTYPE_HSVCIRCLE:
- break;
- default:
- BLI_strncpy(but->drawstr, but->str, UI_MAX_DRAW_STR);
- break;
-
- }
-
- /* if we are doing text editing, this will override the drawstr */
- if (but->editstr) {
- but->drawstr[0] = '\0';
- }
-
- /* text clipping moved to widget drawing code itself */
+ /* if something changed in the button */
+ double value = UI_BUT_VALUE_UNSET;
+
+ ui_but_update_select_flag(but, &value);
+
+ /* only update soft range while not editing */
+ if (!ui_but_is_editing(but)) {
+ if ((but->rnaprop != NULL) || (but->poin && (but->pointype & UI_BUT_POIN_TYPES))) {
+ ui_set_but_soft_range(but);
+ }
+ }
+
+ /* test for min and max, icon sliders, etc */
+ switch (but->type) {
+ case UI_BTYPE_NUM:
+ case UI_BTYPE_SCROLL:
+ case UI_BTYPE_NUM_SLIDER:
+ if (validate) {
+ UI_GET_BUT_VALUE_INIT(but, value);
+ if (value < (double)but->hardmin) {
+ ui_but_value_set(but, but->hardmin);
+ }
+ else if (value > (double)but->hardmax) {
+ ui_but_value_set(but, but->hardmax);
+ }
+
+ /* max must never be smaller than min! Both being equal is allowed though */
+ BLI_assert(but->softmin <= but->softmax && but->hardmin <= but->hardmax);
+ }
+ break;
+
+ case UI_BTYPE_ICON_TOGGLE:
+ case UI_BTYPE_ICON_TOGGLE_N:
+ if ((but->rnaprop == NULL) || (RNA_property_flag(but->rnaprop) & PROP_ICONS_CONSECUTIVE)) {
+ if (but->rnaprop && RNA_property_flag(but->rnaprop) & PROP_ICONS_REVERSE) {
+ but->drawflag |= UI_BUT_ICON_REVERSE;
+ }
+
+ but->iconadd = (but->flag & UI_SELECT) ? 1 : 0;
+ }
+ break;
+
+ /* quiet warnings for unhandled types */
+ default:
+ break;
+ }
+
+ /* safety is 4 to enable small number buttons (like 'users') */
+ // okwidth = -4 + (BLI_rcti_size_x(&but->rect)); // UNUSED
+
+ /* name: */
+ switch (but->type) {
+
+ case UI_BTYPE_MENU:
+ if (BLI_rctf_size_x(&but->rect) >= (UI_UNIT_X * 2)) {
+ /* only needed for menus in popup blocks that don't recreate buttons on redraw */
+ if (but->block->flag & UI_BLOCK_LOOP) {
+ if (but->rnaprop && (RNA_property_type(but->rnaprop) == PROP_ENUM)) {
+ int value_enum = RNA_property_enum_get(&but->rnapoin, but->rnaprop);
+
+ EnumPropertyItem item;
+ if (RNA_property_enum_item_from_value_gettexted(
+ but->block->evil_C, &but->rnapoin, but->rnaprop, value_enum, &item)) {
+ size_t slen = strlen(item.name);
+ ui_but_string_free_internal(but);
+ ui_but_string_set_internal(but, item.name, slen);
+ but->icon = item.icon;
+ }
+ }
+ }
+ BLI_strncpy(but->drawstr, but->str, sizeof(but->drawstr));
+ }
+ break;
+
+ case UI_BTYPE_NUM:
+ case UI_BTYPE_NUM_SLIDER:
+ if (but->editstr) {
+ break;
+ }
+ UI_GET_BUT_VALUE_INIT(but, value);
+ if (ui_but_is_float(but)) {
+ ui_but_build_drawstr_float(but, value);
+ }
+ else {
+ ui_but_build_drawstr_int(but, (int)value);
+ }
+ break;
+
+ case UI_BTYPE_LABEL:
+ if (ui_but_is_float(but)) {
+ int prec;
+ UI_GET_BUT_VALUE_INIT(but, value);
+ prec = ui_but_calc_float_precision(but, value);
+ BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%.*f", but->str, prec, value);
+ }
+ else {
+ BLI_strncpy(but->drawstr, but->str, UI_MAX_DRAW_STR);
+ }
+
+ break;
+
+ case UI_BTYPE_TEXT:
+ case UI_BTYPE_SEARCH_MENU:
+ if (!but->editstr) {
+ char str[UI_MAX_DRAW_STR];
+
+ ui_but_string_get(but, str, UI_MAX_DRAW_STR);
+ BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%s", but->str, str);
+ }
+ break;
+
+ case UI_BTYPE_KEY_EVENT: {
+ const char *str;
+ if (but->flag & UI_SELECT) {
+ str = "Press a key";
+ }
+ else {
+ UI_GET_BUT_VALUE_INIT(but, value);
+ str = WM_key_event_string((short)value, false);
+ }
+ BLI_snprintf(but->drawstr, UI_MAX_DRAW_STR, "%s%s", but->str, str);
+ break;
+ }
+ case UI_BTYPE_HOTKEY_EVENT:
+ if (but->flag & UI_SELECT) {
+
+ if (but->modifier_key) {
+ char *str = but->drawstr;
+ but->drawstr[0] = '\0';
+
+ if (but->modifier_key & KM_SHIFT) {
+ str += BLI_strcpy_rlen(str, "Shift ");
+ }
+ if (but->modifier_key & KM_CTRL) {
+ str += BLI_strcpy_rlen(str, "Ctrl ");
+ }
+ if (but->modifier_key & KM_ALT) {
+ str += BLI_strcpy_rlen(str, "Alt ");
+ }
+ if (but->modifier_key & KM_OSKEY) {
+ str += BLI_strcpy_rlen(str, "Cmd ");
+ }
+
+ (void)str; /* UNUSED */
+ }
+ else {
+ BLI_strncpy(but->drawstr, "Press a key", UI_MAX_DRAW_STR);
+ }
+ }
+ else {
+ BLI_strncpy(but->drawstr, but->str, UI_MAX_DRAW_STR);
+ }
+
+ break;
+
+ case UI_BTYPE_HSVCUBE:
+ case UI_BTYPE_HSVCIRCLE:
+ break;
+ default:
+ BLI_strncpy(but->drawstr, but->str, UI_MAX_DRAW_STR);
+ break;
+ }
+
+ /* if we are doing text editing, this will override the drawstr */
+ if (but->editstr) {
+ but->drawstr[0] = '\0';
+ }
+
+ /* text clipping moved to widget drawing code itself */
}
void ui_but_update(uiBut *but)
{
- ui_but_update_ex(but, false);
+ ui_but_update_ex(but, false);
}
void ui_but_update_edited(uiBut *but)
{
- ui_but_update_ex(but, true);
+ ui_but_update_ex(but, true);
}
void UI_block_align_begin(uiBlock *block)
{
- /* if other align was active, end it */
- if (block->flag & UI_BUT_ALIGN) {
- UI_block_align_end(block);
- }
+ /* if other align was active, end it */
+ if (block->flag & UI_BUT_ALIGN) {
+ UI_block_align_end(block);
+ }
- block->flag |= UI_BUT_ALIGN_DOWN;
- block->alignnr++;
+ block->flag |= UI_BUT_ALIGN_DOWN;
+ block->alignnr++;
- /* buttons declared after this call will get this align nr */ // XXX flag?
+ /* buttons declared after this call will get this align nr */ // XXX flag?
}
void UI_block_align_end(uiBlock *block)
{
- block->flag &= ~UI_BUT_ALIGN; /* all 4 flags */
+ block->flag &= ~UI_BUT_ALIGN; /* all 4 flags */
}
struct ColorManagedDisplay *ui_block_cm_display_get(uiBlock *block)
{
- return IMB_colormanagement_display_get_named(block->display_device);
+ return IMB_colormanagement_display_get_named(block->display_device);
}
void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3])
{
- struct ColorManagedDisplay *display = ui_block_cm_display_get(block);
+ struct ColorManagedDisplay *display = ui_block_cm_display_get(block);
- IMB_colormanagement_scene_linear_to_display_v3(pixel, display);
+ IMB_colormanagement_scene_linear_to_display_v3(pixel, display);
}
static uiBut *ui_but_alloc(const eButType type)
{
- switch (type) {
- case UI_BTYPE_TAB:
- return MEM_callocN(sizeof(uiButTab), "uiButTab");
- default:
- return MEM_callocN(sizeof(uiBut), "uiBut");
- }
+ switch (type) {
+ case UI_BTYPE_TAB:
+ return MEM_callocN(sizeof(uiButTab), "uiButTab");
+ default:
+ return MEM_callocN(sizeof(uiBut), "uiBut");
+ }
}
/**
@@ -3477,353 +3526,434 @@ static uiBut *ui_but_alloc(const eButType type)
* \param a2: Number of decimal point values to display. 0 defaults to 3 (0.000)
* 1,2,3, and a maximum of 4, all greater values will be clamped to 4.
*/
-static uiBut *ui_def_but(
- uiBlock *block, int type, int retval, const char *str,
- int x, int y, short width, short height,
- void *poin, float min, float max, float a1, float a2, const char *tip)
-{
- uiBut *but;
- int slen;
-
- BLI_assert(width >= 0 && height >= 0);
-
- /* we could do some more error checks here */
- if ((type & BUTTYPE) == UI_BTYPE_LABEL) {
- BLI_assert((poin != NULL || min != 0.0f || max != 0.0f || (a1 == 0.0f && a2 != 0.0f) || (a1 != 0.0f && a1 != 1.0f)) == false);
- }
-
- if (type & UI_BUT_POIN_TYPES) { /* a pointer is required */
- if (poin == NULL) {
- BLI_assert(0);
- return NULL;
- }
- }
-
- but = ui_but_alloc(type & BUTTYPE);
-
- but->type = type & BUTTYPE;
- but->pointype = type & UI_BUT_POIN_TYPES;
- but->bit = type & UI_BUT_POIN_BIT;
- but->bitnr = type & 31;
- but->icon = ICON_NONE;
- but->iconadd = 0;
-
- but->retval = retval;
-
- slen = strlen(str);
- ui_but_string_set_internal(but, str, slen);
-
- but->rect.xmin = x;
- but->rect.ymin = y;
- but->rect.xmax = but->rect.xmin + width;
- but->rect.ymax = but->rect.ymin + height;
-
- but->poin = poin;
- but->hardmin = but->softmin = min;
- but->hardmax = but->softmax = max;
- but->a1 = a1;
- but->a2 = a2;
- but->tip = tip;
-
- but->disabled_info = block->lockstr;
- but->dt = block->dt;
- but->pie_dir = UI_RADIAL_NONE;
-
- but->block = block; /* pointer back, used for frontbuffer status, and picker */
-
- if ((block->flag & UI_BUT_ALIGN) && ui_but_can_align(but)) {
- but->alignnr = block->alignnr;
- }
-
- but->func = block->func;
- but->func_arg1 = block->func_arg1;
- but->func_arg2 = block->func_arg2;
-
- but->funcN = block->funcN;
- if (block->func_argN) {
- but->func_argN = MEM_dupallocN(block->func_argN);
- }
-
- but->pos = -1; /* cursor invisible */
-
- if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) { /* add a space to name */
- /* slen remains unchanged from previous assignment, ensure this stays true */
- if (slen > 0 && slen < UI_MAX_NAME_STR - 2) {
- if (but->str[slen - 1] != ' ') {
- but->str[slen] = ' ';
- but->str[slen + 1] = 0;
- }
- }
- }
-
- if (block->flag & UI_BLOCK_RADIAL) {
- but->drawflag |= UI_BUT_TEXT_LEFT;
- if (but->str && but->str[0]) {
- but->drawflag |= UI_BUT_ICON_LEFT;
- }
- }
- else if (((block->flag & UI_BLOCK_LOOP) && !ui_block_is_popover(block)) ||
- ELEM(but->type,
- UI_BTYPE_MENU, UI_BTYPE_TEXT, UI_BTYPE_LABEL,
- UI_BTYPE_BLOCK, UI_BTYPE_BUT_MENU, UI_BTYPE_SEARCH_MENU,
- UI_BTYPE_PROGRESS_BAR, UI_BTYPE_POPOVER))
- {
- but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT);
- }
+static uiBut *ui_def_but(uiBlock *block,
+ int type,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ void *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ uiBut *but;
+ int slen;
+
+ BLI_assert(width >= 0 && height >= 0);
+
+ /* we could do some more error checks here */
+ if ((type & BUTTYPE) == UI_BTYPE_LABEL) {
+ BLI_assert((poin != NULL || min != 0.0f || max != 0.0f || (a1 == 0.0f && a2 != 0.0f) ||
+ (a1 != 0.0f && a1 != 1.0f)) == false);
+ }
+
+ if (type & UI_BUT_POIN_TYPES) { /* a pointer is required */
+ if (poin == NULL) {
+ BLI_assert(0);
+ return NULL;
+ }
+ }
+
+ but = ui_but_alloc(type & BUTTYPE);
+
+ but->type = type & BUTTYPE;
+ but->pointype = type & UI_BUT_POIN_TYPES;
+ but->bit = type & UI_BUT_POIN_BIT;
+ but->bitnr = type & 31;
+ but->icon = ICON_NONE;
+ but->iconadd = 0;
+
+ but->retval = retval;
+
+ slen = strlen(str);
+ ui_but_string_set_internal(but, str, slen);
+
+ but->rect.xmin = x;
+ but->rect.ymin = y;
+ but->rect.xmax = but->rect.xmin + width;
+ but->rect.ymax = but->rect.ymin + height;
+
+ but->poin = poin;
+ but->hardmin = but->softmin = min;
+ but->hardmax = but->softmax = max;
+ but->a1 = a1;
+ but->a2 = a2;
+ but->tip = tip;
+
+ but->disabled_info = block->lockstr;
+ but->dt = block->dt;
+ but->pie_dir = UI_RADIAL_NONE;
+
+ but->block = block; /* pointer back, used for frontbuffer status, and picker */
+
+ if ((block->flag & UI_BUT_ALIGN) && ui_but_can_align(but)) {
+ but->alignnr = block->alignnr;
+ }
+
+ but->func = block->func;
+ but->func_arg1 = block->func_arg1;
+ but->func_arg2 = block->func_arg2;
+
+ but->funcN = block->funcN;
+ if (block->func_argN) {
+ but->func_argN = MEM_dupallocN(block->func_argN);
+ }
+
+ but->pos = -1; /* cursor invisible */
+
+ if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) { /* add a space to name */
+ /* slen remains unchanged from previous assignment, ensure this stays true */
+ if (slen > 0 && slen < UI_MAX_NAME_STR - 2) {
+ if (but->str[slen - 1] != ' ') {
+ but->str[slen] = ' ';
+ but->str[slen + 1] = 0;
+ }
+ }
+ }
+
+ if (block->flag & UI_BLOCK_RADIAL) {
+ but->drawflag |= UI_BUT_TEXT_LEFT;
+ if (but->str && but->str[0]) {
+ but->drawflag |= UI_BUT_ICON_LEFT;
+ }
+ }
+ else if (((block->flag & UI_BLOCK_LOOP) && !ui_block_is_popover(block)) ||
+ ELEM(but->type,
+ UI_BTYPE_MENU,
+ UI_BTYPE_TEXT,
+ UI_BTYPE_LABEL,
+ UI_BTYPE_BLOCK,
+ UI_BTYPE_BUT_MENU,
+ UI_BTYPE_SEARCH_MENU,
+ UI_BTYPE_PROGRESS_BAR,
+ UI_BTYPE_POPOVER)) {
+ but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT);
+ }
#ifdef USE_NUMBUTS_LR_ALIGN
- else if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) {
- if (slen != 0) {
- but->drawflag |= UI_BUT_TEXT_LEFT;
- }
- }
+ else if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) {
+ if (slen != 0) {
+ but->drawflag |= UI_BUT_TEXT_LEFT;
+ }
+ }
#endif
- but->drawflag |= (block->flag & UI_BUT_ALIGN);
-
- if (block->lock == true) {
- but->flag |= UI_BUT_DISABLED;
- }
-
- /* keep track of UI_interface.h */
- if (ELEM(but->type,
- UI_BTYPE_BLOCK, UI_BTYPE_BUT, UI_BTYPE_LABEL,
- UI_BTYPE_PULLDOWN, UI_BTYPE_ROUNDBOX, UI_BTYPE_LISTBOX,
- UI_BTYPE_BUT_MENU, UI_BTYPE_SCROLL, UI_BTYPE_GRIP,
- UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE,
- UI_BTYPE_SEPR_SPACER) ||
- (but->type >= UI_BTYPE_SEARCH_MENU))
- {
- /* pass */
- }
- else {
- but->flag |= UI_BUT_UNDO;
- }
-
- BLI_addtail(&block->buttons, but);
-
- if (block->curlayout) {
- ui_layout_add_but(block->curlayout, but);
- }
+ but->drawflag |= (block->flag & UI_BUT_ALIGN);
+
+ if (block->lock == true) {
+ but->flag |= UI_BUT_DISABLED;
+ }
+
+ /* keep track of UI_interface.h */
+ if (ELEM(but->type,
+ UI_BTYPE_BLOCK,
+ UI_BTYPE_BUT,
+ UI_BTYPE_LABEL,
+ UI_BTYPE_PULLDOWN,
+ UI_BTYPE_ROUNDBOX,
+ UI_BTYPE_LISTBOX,
+ UI_BTYPE_BUT_MENU,
+ UI_BTYPE_SCROLL,
+ UI_BTYPE_GRIP,
+ UI_BTYPE_SEPR,
+ UI_BTYPE_SEPR_LINE,
+ UI_BTYPE_SEPR_SPACER) ||
+ (but->type >= UI_BTYPE_SEARCH_MENU)) {
+ /* pass */
+ }
+ else {
+ but->flag |= UI_BUT_UNDO;
+ }
+
+ BLI_addtail(&block->buttons, but);
+
+ if (block->curlayout) {
+ ui_layout_add_but(block->curlayout, but);
+ }
#ifdef WITH_PYTHON
- /* if the 'UI_OT_editsource' is running, extract the source info from the button */
- if (UI_editsource_enable_check()) {
- UI_editsource_active_but_test(but);
- }
+ /* if the 'UI_OT_editsource' is running, extract the source info from the button */
+ if (UI_editsource_enable_check()) {
+ UI_editsource_active_but_test(but);
+ }
#endif
- return but;
+ return but;
}
void ui_def_but_icon(uiBut *but, const int icon, const int flag)
{
- if (icon) {
- ui_icon_ensure_deferred(but->block->evil_C, icon, (flag & UI_BUT_ICON_PREVIEW) != 0);
- }
- but->icon = (BIFIconID)icon;
- but->flag |= flag;
+ if (icon) {
+ ui_icon_ensure_deferred(but->block->evil_C, icon, (flag & UI_BUT_ICON_PREVIEW) != 0);
+ }
+ but->icon = (BIFIconID)icon;
+ but->flag |= flag;
- if (but->str && but->str[0]) {
- but->drawflag |= UI_BUT_ICON_LEFT;
- }
+ if (but->str && but->str[0]) {
+ but->drawflag |= UI_BUT_ICON_LEFT;
+ }
}
static void ui_def_but_rna__disable(uiBut *but, const char *info)
{
- but->flag |= UI_BUT_DISABLED;
- but->disabled_info = info;
+ but->flag |= UI_BUT_DISABLED;
+ but->disabled_info = info;
}
static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *but_p)
{
- uiBlock *block = uiLayoutGetBlock(layout);
- uiPopupBlockHandle *handle = block->handle;
- uiBut *but = (uiBut *)but_p;
-
- /* see comment in ui_item_enum_expand, re: uiname */
- const EnumPropertyItem *item, *item_array;
- bool free;
-
- uiLayout *split, *column = NULL;
-
- int totitems = 0;
- int columns, rows, a, b;
- int column_end = 0;
- int nbr_entries_nosepr = 0;
-
- UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT);
-
- RNA_property_enum_items_gettexted(block->evil_C, &but->rnapoin, but->rnaprop, &item_array, NULL, &free);
-
-
- /* we dont want nested rows, cols in menus */
- UI_block_layout_set_current(block, layout);
-
- for (item = item_array; item->identifier; item++, totitems++) {
- if (!item->identifier[0]) {
- /* inconsistent, but menus with categories do not look good flipped */
- if (item->name) {
- block->flag |= UI_BLOCK_NO_FLIP;
- nbr_entries_nosepr++;
- }
- /* We do not want simple separators in nbr_entries_nosepr count */
- continue;
- }
- nbr_entries_nosepr++;
- }
-
- /* Columns and row estimation. Ignore simple separators here. */
- columns = (nbr_entries_nosepr + 20) / 20;
- if (columns < 1) {
- columns = 1;
- }
- if (columns > 8) {
- columns = (nbr_entries_nosepr + 25) / 25;
- }
-
- rows = totitems / columns;
- if (rows < 1) {
- rows = 1;
- }
- while (rows * columns < totitems) {
- rows++;
- }
-
- if (block->flag & UI_BLOCK_NO_FLIP) {
- /* Title at the top for menus with categories. */
- uiDefBut(block, UI_BTYPE_LABEL, 0, RNA_property_ui_name(but->rnaprop),
- 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- uiItemS(layout);
- }
-
- /* note, item_array[...] is reversed on access */
-
- /* create items */
- split = uiLayoutSplit(layout, 0.0f, false);
-
- for (a = 0; a < totitems; a++) {
- if (a == column_end) {
- /* start new column, and find out where it ends in advance, so we
- * can flip the order of items properly per column */
- column_end = totitems;
-
- for (b = a + 1; b < totitems; b++) {
- item = &item_array[b];
-
- /* new column on N rows or on separation label */
- if (((b - a) % rows == 0) || (!item->identifier[0] && item->name)) {
- column_end = b;
- break;
- }
- }
-
- column = uiLayoutColumn(split, false);
- }
-
- item = &item_array[a];
-
- if (!item->identifier[0]) {
- if (item->name) {
- if (item->icon) {
- uiItemL(column, item->name, item->icon);
- }
- else {
- /* Do not use uiItemL here, as our root layout is a menu one,
- * it will add a fake blank icon! */
- uiDefBut(block, UI_BTYPE_LABEL, 0, item->name, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- }
- }
- else {
- uiItemS(column);
- }
- }
- else {
- if (item->icon) {
- uiDefIconTextButI(
- block, UI_BTYPE_BUT_MENU, B_NOP, item->icon, item->name, 0, 0,
- UI_UNIT_X * 5, UI_UNIT_Y, &handle->retvalue, item->value, 0.0, 0, -1, item->description);
- }
- else {
- uiDefButI(
- block, UI_BTYPE_BUT_MENU, B_NOP, item->name, 0, 0,
- UI_UNIT_X * 5, UI_UNIT_X, &handle->retvalue, item->value, 0.0, 0, -1, item->description);
- }
- }
- }
-
- if (!(block->flag & UI_BLOCK_NO_FLIP)) {
- /* Title at the bottom for menus without categories. */
- uiItemS(layout);
- uiDefBut(block, UI_BTYPE_LABEL, 0, RNA_property_ui_name(but->rnaprop),
- 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- }
-
- UI_block_layout_set_current(block, layout);
-
- if (free) {
- MEM_freeN((void *)item_array);
- }
- BLI_assert((block->flag & UI_BLOCK_IS_FLIP) == 0);
- block->flag |= UI_BLOCK_IS_FLIP;
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiPopupBlockHandle *handle = block->handle;
+ uiBut *but = (uiBut *)but_p;
+
+ /* see comment in ui_item_enum_expand, re: uiname */
+ const EnumPropertyItem *item, *item_array;
+ bool free;
+
+ uiLayout *split, *column = NULL;
+
+ int totitems = 0;
+ int columns, rows, a, b;
+ int column_end = 0;
+ int nbr_entries_nosepr = 0;
+
+ UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT);
+
+ RNA_property_enum_items_gettexted(
+ block->evil_C, &but->rnapoin, but->rnaprop, &item_array, NULL, &free);
+
+ /* we dont want nested rows, cols in menus */
+ UI_block_layout_set_current(block, layout);
+
+ for (item = item_array; item->identifier; item++, totitems++) {
+ if (!item->identifier[0]) {
+ /* inconsistent, but menus with categories do not look good flipped */
+ if (item->name) {
+ block->flag |= UI_BLOCK_NO_FLIP;
+ nbr_entries_nosepr++;
+ }
+ /* We do not want simple separators in nbr_entries_nosepr count */
+ continue;
+ }
+ nbr_entries_nosepr++;
+ }
+
+ /* Columns and row estimation. Ignore simple separators here. */
+ columns = (nbr_entries_nosepr + 20) / 20;
+ if (columns < 1) {
+ columns = 1;
+ }
+ if (columns > 8) {
+ columns = (nbr_entries_nosepr + 25) / 25;
+ }
+
+ rows = totitems / columns;
+ if (rows < 1) {
+ rows = 1;
+ }
+ while (rows * columns < totitems) {
+ rows++;
+ }
+
+ if (block->flag & UI_BLOCK_NO_FLIP) {
+ /* Title at the top for menus with categories. */
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ RNA_property_ui_name(but->rnaprop),
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ uiItemS(layout);
+ }
+
+ /* note, item_array[...] is reversed on access */
+
+ /* create items */
+ split = uiLayoutSplit(layout, 0.0f, false);
+
+ for (a = 0; a < totitems; a++) {
+ if (a == column_end) {
+ /* start new column, and find out where it ends in advance, so we
+ * can flip the order of items properly per column */
+ column_end = totitems;
+
+ for (b = a + 1; b < totitems; b++) {
+ item = &item_array[b];
+
+ /* new column on N rows or on separation label */
+ if (((b - a) % rows == 0) || (!item->identifier[0] && item->name)) {
+ column_end = b;
+ break;
+ }
+ }
+
+ column = uiLayoutColumn(split, false);
+ }
+
+ item = &item_array[a];
+
+ if (!item->identifier[0]) {
+ if (item->name) {
+ if (item->icon) {
+ uiItemL(column, item->name, item->icon);
+ }
+ else {
+ /* Do not use uiItemL here, as our root layout is a menu one,
+ * it will add a fake blank icon! */
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ item->name,
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ }
+ }
+ else {
+ uiItemS(column);
+ }
+ }
+ else {
+ if (item->icon) {
+ uiDefIconTextButI(block,
+ UI_BTYPE_BUT_MENU,
+ B_NOP,
+ item->icon,
+ item->name,
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_Y,
+ &handle->retvalue,
+ item->value,
+ 0.0,
+ 0,
+ -1,
+ item->description);
+ }
+ else {
+ uiDefButI(block,
+ UI_BTYPE_BUT_MENU,
+ B_NOP,
+ item->name,
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_X,
+ &handle->retvalue,
+ item->value,
+ 0.0,
+ 0,
+ -1,
+ item->description);
+ }
+ }
+ }
+
+ if (!(block->flag & UI_BLOCK_NO_FLIP)) {
+ /* Title at the bottom for menus without categories. */
+ uiItemS(layout);
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ RNA_property_ui_name(but->rnaprop),
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ }
+
+ UI_block_layout_set_current(block, layout);
+
+ if (free) {
+ MEM_freeN((void *)item_array);
+ }
+ BLI_assert((block->flag & UI_BLOCK_IS_FLIP) == 0);
+ block->flag |= UI_BLOCK_IS_FLIP;
}
static void ui_def_but_rna__panel_type(bContext *C, uiLayout *layout, void *but_p)
{
- uiBut *but = but_p;
- const char *panel_type = but->func_argN;
- PanelType *pt = WM_paneltype_find(panel_type, true);
- if (pt) {
- ui_item_paneltype_func(C, layout, pt);
- }
- else {
- char msg[256];
- SNPRINTF(msg, "Missing Panel: %s", panel_type);
- uiItemL(layout, msg, ICON_NONE);
- }
+ uiBut *but = but_p;
+ const char *panel_type = but->func_argN;
+ PanelType *pt = WM_paneltype_find(panel_type, true);
+ if (pt) {
+ ui_item_paneltype_func(C, layout, pt);
+ }
+ else {
+ char msg[256];
+ SNPRINTF(msg, "Missing Panel: %s", panel_type);
+ uiItemL(layout, msg, ICON_NONE);
+ }
}
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);
- but->menu_create_func = ui_def_but_rna__panel_type;
- but->func_argN = BLI_strdup(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);
+ but->menu_create_func = ui_def_but_rna__panel_type;
+ but->func_argN = BLI_strdup(panel_type);
}
bool ui_but_menu_draw_as_popover(const uiBut *but)
{
- return (but->menu_create_func == ui_def_but_rna__panel_type);
+ return (but->menu_create_func == ui_def_but_rna__panel_type);
}
static void ui_def_but_rna__menu_type(bContext *C, uiLayout *layout, void *but_p)
{
- uiBut *but = but_p;
- const char *menu_type = but->func_argN;
- MenuType *mt = WM_menutype_find(menu_type, true);
- if (mt) {
- ui_item_menutype_func(C, layout, mt);
- }
- else {
- char msg[256];
- SNPRINTF(msg, "Missing Menu: %s", menu_type);
- uiItemL(layout, msg, ICON_NONE);
- }
+ uiBut *but = but_p;
+ const char *menu_type = but->func_argN;
+ MenuType *mt = WM_menutype_find(menu_type, true);
+ if (mt) {
+ ui_item_menutype_func(C, layout, mt);
+ }
+ else {
+ char msg[256];
+ SNPRINTF(msg, "Missing Menu: %s", menu_type);
+ uiItemL(layout, msg, ICON_NONE);
+ }
}
void ui_but_rna_menu_convert_to_menu_type(uiBut *but, const char *menu_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);
- but->menu_create_func = ui_def_but_rna__menu_type;
- but->func_argN = BLI_strdup(menu_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);
+ but->menu_create_func = ui_def_but_rna__menu_type;
+ but->func_argN = BLI_strdup(menu_type);
}
static void ui_but_submenu_enable(uiBlock *block, uiBut *but)
{
- but->flag |= UI_BUT_ICON_SUBMENU;
- block->content_hints |= UI_BLOCK_CONTAINS_SUBMENU_BUT;
+ but->flag |= UI_BUT_ICON_SUBMENU;
+ block->content_hints |= UI_BLOCK_CONTAINS_SUBMENU_BUT;
}
/**
@@ -3834,227 +3964,278 @@ static void ui_but_submenu_enable(uiBlock *block, uiBut *but)
* When this kind of change won't disrupt branches, best look into making more
* of our UI functions take prop rather then propname.
*/
-static uiBut *ui_def_but_rna(
- uiBlock *block, int type, int retval, const char *str,
- int x, int y, short width, short height,
- PointerRNA *ptr, PropertyRNA *prop, int index,
- float min, float max, float a1, float a2, const char *tip)
-{
- const PropertyType proptype = RNA_property_type(prop);
- uiBut *but;
- int icon = 0;
- uiMenuCreateFunc func = NULL;
-
- if (ELEM(type, UI_BTYPE_COLOR, UI_BTYPE_HSVCIRCLE, UI_BTYPE_HSVCUBE)) {
- BLI_assert(index == -1);
- }
-
- /* use rna values if parameters are not specified */
- if ((proptype == PROP_ENUM) && ELEM(type, UI_BTYPE_MENU, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) {
- /* UI_BTYPE_MENU is handled a little differently here */
- const EnumPropertyItem *item;
- int value;
- bool free;
- int i;
-
- RNA_property_enum_items(block->evil_C, ptr, prop, &item, NULL, &free);
-
- if (type == UI_BTYPE_MENU) {
- value = RNA_property_enum_get(ptr, prop);
- }
- else {
- value = (int)max;
- }
-
- i = RNA_enum_from_value(item, value);
- if (i != -1) {
-
- if (!str) {
- str = item[i].name;
+static uiBut *ui_def_but_rna(uiBlock *block,
+ int type,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ int index,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ const PropertyType proptype = RNA_property_type(prop);
+ uiBut *but;
+ int icon = 0;
+ uiMenuCreateFunc func = NULL;
+
+ if (ELEM(type, UI_BTYPE_COLOR, UI_BTYPE_HSVCIRCLE, UI_BTYPE_HSVCUBE)) {
+ BLI_assert(index == -1);
+ }
+
+ /* use rna values if parameters are not specified */
+ if ((proptype == PROP_ENUM) && ELEM(type, UI_BTYPE_MENU, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) {
+ /* UI_BTYPE_MENU is handled a little differently here */
+ const EnumPropertyItem *item;
+ int value;
+ bool free;
+ int i;
+
+ RNA_property_enum_items(block->evil_C, ptr, prop, &item, NULL, &free);
+
+ if (type == UI_BTYPE_MENU) {
+ value = RNA_property_enum_get(ptr, prop);
+ }
+ else {
+ value = (int)max;
+ }
+
+ i = RNA_enum_from_value(item, value);
+ if (i != -1) {
+
+ if (!str) {
+ str = item[i].name;
#ifdef WITH_INTERNATIONAL
- str = CTX_IFACE_(RNA_property_translation_context(prop), str);
+ str = CTX_IFACE_(RNA_property_translation_context(prop), str);
#endif
- }
-
- icon = item[i].icon;
- }
- else {
- if (!str) {
- if (type == UI_BTYPE_MENU) {
- str = "";
- }
- else {
- str = RNA_property_ui_name(prop);
- }
- }
- }
-
- if (type == UI_BTYPE_MENU) {
- func = ui_def_but_rna__menu;
- }
-
- if (free) {
- MEM_freeN((void *)item);
- }
- }
- else {
- if (!str) {
- str = RNA_property_ui_name(prop);
- }
- icon = RNA_property_ui_icon(prop);
- }
-
- if (!tip && proptype != PROP_ENUM) {
- tip = RNA_property_ui_description(prop);
- }
-
- if (min == max || a1 == -1 || a2 == -1) {
- if (proptype == PROP_INT) {
- int hardmin, hardmax, softmin, softmax, step;
-
- RNA_property_int_range(ptr, prop, &hardmin, &hardmax);
- RNA_property_int_ui_range(ptr, prop, &softmin, &softmax, &step);
-
- if (!ELEM(type, UI_BTYPE_ROW, UI_BTYPE_LISTROW) && min == max) {
- min = hardmin;
- max = hardmax;
- }
- if (a1 == -1) {
- a1 = step;
- }
- if (a2 == -1) {
- a2 = 0;
- }
- }
- else if (proptype == PROP_FLOAT) {
- float hardmin, hardmax, softmin, softmax, step, precision;
-
- RNA_property_float_range(ptr, prop, &hardmin, &hardmax);
- RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
-
- if (!ELEM(type, UI_BTYPE_ROW, UI_BTYPE_LISTROW) && min == max) {
- min = hardmin;
- max = hardmax;
- }
- if (a1 == -1) {
- a1 = step;
- }
- if (a2 == -1) {
- a2 = precision;
- }
- }
- else if (proptype == PROP_STRING) {
- min = 0;
- max = RNA_property_string_maxlength(prop);
- /* note, 'max' may be zero (code for dynamically resized array) */
- }
- }
-
- /* now create button */
- but = ui_def_but(block, type, retval, str, x, y, width, height, NULL, min, max, a1, a2, tip);
-
- but->rnapoin = *ptr;
- but->rnaprop = prop;
-
- if (RNA_property_array_check(but->rnaprop)) {
- but->rnaindex = index;
- }
- else {
- but->rnaindex = 0;
- }
-
- if (icon) {
- ui_def_but_icon(but, icon, UI_HAS_ICON);
- }
-
- if (type == UI_BTYPE_MENU) {
- if (but->dt == UI_EMBOSS_PULLDOWN) {
- ui_but_submenu_enable(block, but);
- }
- }
- else if (type == UI_BTYPE_SEARCH_MENU) {
- if (proptype == PROP_POINTER) {
- /* Search buttons normally don't get undo, see: T54580. */
- but->flag |= UI_BUT_UNDO;
- }
- }
-
- const char *info;
- if (but->rnapoin.data && !RNA_property_editable_info(&but->rnapoin, prop, &info)) {
- ui_def_but_rna__disable(but, info);
- }
-
- if (but->flag & UI_BUT_UNDO && (ui_but_is_rna_undo(but) == false)) {
- but->flag &= ~UI_BUT_UNDO;
- }
-
- /* If this button uses units, calculate the step from this */
- if ((proptype == PROP_FLOAT) && ui_but_is_unit(but)) {
- but->a1 = ui_get_but_step_unit(but, but->a1);
- }
-
- if (func) {
- but->menu_create_func = func;
- but->poin = (char *)but;
- }
-
- return but;
-}
-
-static uiBut *ui_def_but_rna_propname(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip)
-{
- PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
- uiBut *but;
-
- if (prop) {
- but = ui_def_but_rna(block, type, retval, str, x, y, width, height, ptr, prop, index, min, max, a1, a2, tip);
- }
- else {
- but = ui_def_but(block, type, retval, propname, x, y, width, height, NULL, min, max, a1, a2, tip);
-
- ui_def_but_rna__disable(but, "Unknown Property.");
- }
-
- return but;
-}
-
-static uiBut *ui_def_but_operator_ptr(uiBlock *block, int type, wmOperatorType *ot, int opcontext, const char *str, int x, int y, short width, short height, const char *tip)
-{
- uiBut *but;
-
- if (!str) {
- if (ot && ot->srna) {
- str = RNA_struct_ui_name(ot->srna);
- }
- else {
- str = "";
- }
- }
-
- if ((!tip || tip[0] == '\0') && ot && ot->srna) {
- tip = RNA_struct_ui_description(ot->srna);
- }
-
- but = ui_def_but(block, type, -1, str, x, y, width, height, NULL, 0, 0, 0, 0, tip);
- but->optype = ot;
- but->opcontext = opcontext;
- but->flag &= ~UI_BUT_UNDO; /* no need for ui_but_is_rna_undo(), we never need undo here */
-
- if (!ot) {
- but->flag |= UI_BUT_DISABLED;
- but->disabled_info = "";
- }
-
- return but;
-}
-
-uiBut *uiDefBut(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
-{
- uiBut *but = ui_def_but(block, type, retval, str, x, y, width, height, poin, min, max, a1, a2, tip);
-
- ui_but_update(but);
-
- return but;
+ }
+
+ icon = item[i].icon;
+ }
+ else {
+ if (!str) {
+ if (type == UI_BTYPE_MENU) {
+ str = "";
+ }
+ else {
+ str = RNA_property_ui_name(prop);
+ }
+ }
+ }
+
+ if (type == UI_BTYPE_MENU) {
+ func = ui_def_but_rna__menu;
+ }
+
+ if (free) {
+ MEM_freeN((void *)item);
+ }
+ }
+ else {
+ if (!str) {
+ str = RNA_property_ui_name(prop);
+ }
+ icon = RNA_property_ui_icon(prop);
+ }
+
+ if (!tip && proptype != PROP_ENUM) {
+ tip = RNA_property_ui_description(prop);
+ }
+
+ if (min == max || a1 == -1 || a2 == -1) {
+ if (proptype == PROP_INT) {
+ int hardmin, hardmax, softmin, softmax, step;
+
+ RNA_property_int_range(ptr, prop, &hardmin, &hardmax);
+ RNA_property_int_ui_range(ptr, prop, &softmin, &softmax, &step);
+
+ if (!ELEM(type, UI_BTYPE_ROW, UI_BTYPE_LISTROW) && min == max) {
+ min = hardmin;
+ max = hardmax;
+ }
+ if (a1 == -1) {
+ a1 = step;
+ }
+ if (a2 == -1) {
+ a2 = 0;
+ }
+ }
+ else if (proptype == PROP_FLOAT) {
+ float hardmin, hardmax, softmin, softmax, step, precision;
+
+ RNA_property_float_range(ptr, prop, &hardmin, &hardmax);
+ RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
+
+ if (!ELEM(type, UI_BTYPE_ROW, UI_BTYPE_LISTROW) && min == max) {
+ min = hardmin;
+ max = hardmax;
+ }
+ if (a1 == -1) {
+ a1 = step;
+ }
+ if (a2 == -1) {
+ a2 = precision;
+ }
+ }
+ else if (proptype == PROP_STRING) {
+ min = 0;
+ max = RNA_property_string_maxlength(prop);
+ /* note, 'max' may be zero (code for dynamically resized array) */
+ }
+ }
+
+ /* now create button */
+ but = ui_def_but(block, type, retval, str, x, y, width, height, NULL, min, max, a1, a2, tip);
+
+ but->rnapoin = *ptr;
+ but->rnaprop = prop;
+
+ if (RNA_property_array_check(but->rnaprop)) {
+ but->rnaindex = index;
+ }
+ else {
+ but->rnaindex = 0;
+ }
+
+ if (icon) {
+ ui_def_but_icon(but, icon, UI_HAS_ICON);
+ }
+
+ if (type == UI_BTYPE_MENU) {
+ if (but->dt == UI_EMBOSS_PULLDOWN) {
+ ui_but_submenu_enable(block, but);
+ }
+ }
+ else if (type == UI_BTYPE_SEARCH_MENU) {
+ if (proptype == PROP_POINTER) {
+ /* Search buttons normally don't get undo, see: T54580. */
+ but->flag |= UI_BUT_UNDO;
+ }
+ }
+
+ const char *info;
+ if (but->rnapoin.data && !RNA_property_editable_info(&but->rnapoin, prop, &info)) {
+ ui_def_but_rna__disable(but, info);
+ }
+
+ if (but->flag & UI_BUT_UNDO && (ui_but_is_rna_undo(but) == false)) {
+ but->flag &= ~UI_BUT_UNDO;
+ }
+
+ /* If this button uses units, calculate the step from this */
+ if ((proptype == PROP_FLOAT) && ui_but_is_unit(but)) {
+ but->a1 = ui_get_but_step_unit(but, but->a1);
+ }
+
+ if (func) {
+ but->menu_create_func = func;
+ but->poin = (char *)but;
+ }
+
+ return but;
+}
+
+static uiBut *ui_def_but_rna_propname(uiBlock *block,
+ int type,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ PointerRNA *ptr,
+ const char *propname,
+ int index,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ uiBut *but;
+
+ if (prop) {
+ but = ui_def_but_rna(
+ block, type, retval, str, x, y, width, height, ptr, prop, index, min, max, a1, a2, tip);
+ }
+ else {
+ but = ui_def_but(
+ block, type, retval, propname, x, y, width, height, NULL, min, max, a1, a2, tip);
+
+ ui_def_but_rna__disable(but, "Unknown Property.");
+ }
+
+ return but;
+}
+
+static uiBut *ui_def_but_operator_ptr(uiBlock *block,
+ int type,
+ wmOperatorType *ot,
+ int opcontext,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip)
+{
+ uiBut *but;
+
+ if (!str) {
+ if (ot && ot->srna) {
+ str = RNA_struct_ui_name(ot->srna);
+ }
+ else {
+ str = "";
+ }
+ }
+
+ if ((!tip || tip[0] == '\0') && ot && ot->srna) {
+ tip = RNA_struct_ui_description(ot->srna);
+ }
+
+ but = ui_def_but(block, type, -1, str, x, y, width, height, NULL, 0, 0, 0, 0, tip);
+ but->optype = ot;
+ but->opcontext = opcontext;
+ but->flag &= ~UI_BUT_UNDO; /* no need for ui_but_is_rna_undo(), we never need undo here */
+
+ if (!ot) {
+ but->flag |= UI_BUT_DISABLED;
+ but->disabled_info = "";
+ }
+
+ return but;
+}
+
+uiBut *uiDefBut(uiBlock *block,
+ int type,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ void *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ uiBut *but = ui_def_but(
+ block, type, retval, str, x, y, width, height, poin, min, max, a1, a2, tip);
+
+ ui_but_update(but);
+
+ return but;
}
/**
@@ -4068,341 +4249,1285 @@ uiBut *uiDefBut(uiBlock *block, int type, int retval, const char *str, int x, in
*/
static int findBitIndex(uint x)
{
- if (!x || !is_power_of_2_i(x)) { /* is_power_of_2_i(x) strips lowest bit */
- return -1;
- }
- else {
- int idx = 0;
-
- if (x & 0xFFFF0000) { idx += 16; x >>= 16; }
- if (x & 0xFF00) { idx += 8; x >>= 8; }
- if (x & 0xF0) { idx += 4; x >>= 4; }
- if (x & 0xC) { idx += 2; x >>= 2; }
- if (x & 0x2) { idx += 1; }
-
- return idx;
- }
+ if (!x || !is_power_of_2_i(x)) { /* is_power_of_2_i(x) strips lowest bit */
+ return -1;
+ }
+ else {
+ int idx = 0;
+
+ if (x & 0xFFFF0000) {
+ idx += 16;
+ x >>= 16;
+ }
+ if (x & 0xFF00) {
+ idx += 8;
+ x >>= 8;
+ }
+ if (x & 0xF0) {
+ idx += 4;
+ x >>= 4;
+ }
+ if (x & 0xC) {
+ idx += 2;
+ x >>= 2;
+ }
+ if (x & 0x2) {
+ idx += 1;
+ }
+
+ return idx;
+ }
}
/* autocomplete helper functions */
struct AutoComplete {
- size_t maxlen;
- int matches;
- char *truncate;
- const char *startname;
+ size_t maxlen;
+ int matches;
+ char *truncate;
+ const char *startname;
};
AutoComplete *UI_autocomplete_begin(const char *startname, size_t maxlen)
{
- AutoComplete *autocpl;
+ AutoComplete *autocpl;
- autocpl = MEM_callocN(sizeof(AutoComplete), "AutoComplete");
- autocpl->maxlen = maxlen;
- autocpl->matches = 0;
- autocpl->truncate = MEM_callocN(sizeof(char) * maxlen, "AutoCompleteTruncate");
- autocpl->startname = startname;
+ autocpl = MEM_callocN(sizeof(AutoComplete), "AutoComplete");
+ autocpl->maxlen = maxlen;
+ autocpl->matches = 0;
+ autocpl->truncate = MEM_callocN(sizeof(char) * maxlen, "AutoCompleteTruncate");
+ autocpl->startname = startname;
- return autocpl;
+ return autocpl;
}
void UI_autocomplete_update_name(AutoComplete *autocpl, const char *name)
{
- char *truncate = autocpl->truncate;
- const char *startname = autocpl->startname;
- int a;
-
- for (a = 0; a < autocpl->maxlen - 1; a++) {
- if (startname[a] == 0 || startname[a] != name[a]) {
- break;
- }
- }
- /* found a match */
- if (startname[a] == 0) {
- autocpl->matches++;
- /* first match */
- if (truncate[0] == 0) {
- BLI_strncpy(truncate, name, autocpl->maxlen);
- }
- else {
- /* remove from truncate what is not in bone->name */
- for (a = 0; a < autocpl->maxlen - 1; a++) {
- if (name[a] == 0) {
- truncate[a] = 0;
- break;
- }
- else if (truncate[a] != name[a]) {
- truncate[a] = 0;
- }
- }
- }
- }
+ char *truncate = autocpl->truncate;
+ const char *startname = autocpl->startname;
+ int a;
+
+ for (a = 0; a < autocpl->maxlen - 1; a++) {
+ if (startname[a] == 0 || startname[a] != name[a]) {
+ break;
+ }
+ }
+ /* found a match */
+ if (startname[a] == 0) {
+ autocpl->matches++;
+ /* first match */
+ if (truncate[0] == 0) {
+ BLI_strncpy(truncate, name, autocpl->maxlen);
+ }
+ else {
+ /* remove from truncate what is not in bone->name */
+ for (a = 0; a < autocpl->maxlen - 1; a++) {
+ if (name[a] == 0) {
+ truncate[a] = 0;
+ break;
+ }
+ else if (truncate[a] != name[a]) {
+ truncate[a] = 0;
+ }
+ }
+ }
+ }
}
int UI_autocomplete_end(AutoComplete *autocpl, char *autoname)
{
- int match = AUTOCOMPLETE_NO_MATCH;
- if (autocpl->truncate[0]) {
- if (autocpl->matches == 1) {
- match = AUTOCOMPLETE_FULL_MATCH;
- }
- else {
- match = AUTOCOMPLETE_PARTIAL_MATCH;
- }
- BLI_strncpy(autoname, autocpl->truncate, autocpl->maxlen);
- }
- else {
- if (autoname != autocpl->startname) { /* don't copy a string over its self */
- BLI_strncpy(autoname, autocpl->startname, autocpl->maxlen);
- }
- }
-
- MEM_freeN(autocpl->truncate);
- MEM_freeN(autocpl);
- return match;
+ int match = AUTOCOMPLETE_NO_MATCH;
+ if (autocpl->truncate[0]) {
+ if (autocpl->matches == 1) {
+ match = AUTOCOMPLETE_FULL_MATCH;
+ }
+ else {
+ match = AUTOCOMPLETE_PARTIAL_MATCH;
+ }
+ BLI_strncpy(autoname, autocpl->truncate, autocpl->maxlen);
+ }
+ else {
+ if (autoname != autocpl->startname) { /* don't copy a string over its self */
+ BLI_strncpy(autoname, autocpl->startname, autocpl->maxlen);
+ }
+ }
+
+ MEM_freeN(autocpl->truncate);
+ MEM_freeN(autocpl);
+ return match;
}
static void ui_but_update_and_icon_set(uiBut *but, int icon)
{
- if (icon) {
- ui_def_but_icon(but, icon, UI_HAS_ICON);
- }
-
- ui_but_update(but);
-}
-
-static uiBut *uiDefButBit(uiBlock *block, int type, int bit, int retval, const char *str, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
-{
- int bitIdx = findBitIndex(bit);
- if (bitIdx == -1) {
- return NULL;
- }
- else {
- return uiDefBut(block, type | UI_BUT_POIN_BIT | bitIdx, retval, str, x, y, width, height, poin, min, max, a1, a2, tip);
- }
-}
-uiBut *uiDefButF(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefBut(block, type | UI_BUT_POIN_FLOAT, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefButBitF(uiBlock *block, int type, int bit, int retval, const char *str, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefButBit(block, type | UI_BUT_POIN_FLOAT, bit, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefButI(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefBut(block, type | UI_BUT_POIN_INT, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefButBitI(uiBlock *block, int type, int bit, int retval, const char *str, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefButBit(block, type | UI_BUT_POIN_INT, bit, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefButS(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefBut(block, type | UI_BUT_POIN_SHORT, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefButBitS(uiBlock *block, int type, int bit, int retval, const char *str, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefButBit(block, type | UI_BUT_POIN_SHORT, bit, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefButC(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefBut(block, type | UI_BUT_POIN_CHAR, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefButBitC(uiBlock *block, int type, int bit, int retval, const char *str, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefButBit(block, type | UI_BUT_POIN_CHAR, bit, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefButR(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip)
-{
- uiBut *but;
- but = ui_def_but_rna_propname(block, type, retval, str, x, y, width, height, ptr, propname, index, min, max, a1, a2, tip);
- ui_but_update(but);
- return but;
-}
-uiBut *uiDefButR_prop(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip)
-{
- uiBut *but;
- but = ui_def_but_rna(block, type, retval, str, x, y, width, height, ptr, prop, index, min, max, a1, a2, tip);
- ui_but_update(but);
- return but;
-}
-
-uiBut *uiDefButO_ptr(uiBlock *block, int type, wmOperatorType *ot, int opcontext, const char *str, int x, int y, short width, short height, const char *tip)
-{
- uiBut *but;
- but = ui_def_but_operator_ptr(block, type, ot, opcontext, str, x, y, width, height, tip);
- ui_but_update(but);
- return but;
-}
-uiBut *uiDefButO(uiBlock *block, int type, const char *opname, int opcontext, const char *str, int x, int y, short width, short height, const char *tip)
-{
- wmOperatorType *ot = WM_operatortype_find(opname, 0);
- if (str == NULL && ot == NULL) {
- str = opname;
- }
- return uiDefButO_ptr(block, type, ot, opcontext, str, x, y, width, height, tip);
+ if (icon) {
+ ui_def_but_icon(but, icon, UI_HAS_ICON);
+ }
+
+ ui_but_update(but);
+}
+
+static uiBut *uiDefButBit(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ void *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ int bitIdx = findBitIndex(bit);
+ if (bitIdx == -1) {
+ return NULL;
+ }
+ else {
+ return uiDefBut(block,
+ type | UI_BUT_POIN_BIT | bitIdx,
+ retval,
+ str,
+ x,
+ y,
+ width,
+ height,
+ poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+ }
+}
+uiBut *uiDefButF(uiBlock *block,
+ int type,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ float *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefBut(block,
+ type | UI_BUT_POIN_FLOAT,
+ retval,
+ str,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefButBitF(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ float *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefButBit(block,
+ type | UI_BUT_POIN_FLOAT,
+ bit,
+ retval,
+ str,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefButI(uiBlock *block,
+ int type,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ int *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefBut(block,
+ type | UI_BUT_POIN_INT,
+ retval,
+ str,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefButBitI(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ int *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefButBit(block,
+ type | UI_BUT_POIN_INT,
+ bit,
+ retval,
+ str,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefButS(uiBlock *block,
+ int type,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ short *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefBut(block,
+ type | UI_BUT_POIN_SHORT,
+ retval,
+ str,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefButBitS(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ short *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefButBit(block,
+ type | UI_BUT_POIN_SHORT,
+ bit,
+ retval,
+ str,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefButC(uiBlock *block,
+ int type,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ char *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefBut(block,
+ type | UI_BUT_POIN_CHAR,
+ retval,
+ str,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefButBitC(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ char *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefButBit(block,
+ type | UI_BUT_POIN_CHAR,
+ bit,
+ retval,
+ str,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefButR(uiBlock *block,
+ int type,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ PointerRNA *ptr,
+ const char *propname,
+ int index,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ uiBut *but;
+ but = ui_def_but_rna_propname(
+ block, type, retval, str, x, y, width, height, ptr, propname, index, min, max, a1, a2, tip);
+ ui_but_update(but);
+ return but;
+}
+uiBut *uiDefButR_prop(uiBlock *block,
+ int type,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ int index,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ uiBut *but;
+ but = ui_def_but_rna(
+ block, type, retval, str, x, y, width, height, ptr, prop, index, min, max, a1, a2, tip);
+ ui_but_update(but);
+ return but;
+}
+
+uiBut *uiDefButO_ptr(uiBlock *block,
+ int type,
+ wmOperatorType *ot,
+ int opcontext,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip)
+{
+ uiBut *but;
+ but = ui_def_but_operator_ptr(block, type, ot, opcontext, str, x, y, width, height, tip);
+ ui_but_update(but);
+ return but;
+}
+uiBut *uiDefButO(uiBlock *block,
+ int type,
+ const char *opname,
+ int opcontext,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip)
+{
+ wmOperatorType *ot = WM_operatortype_find(opname, 0);
+ if (str == NULL && ot == NULL) {
+ str = opname;
+ }
+ return uiDefButO_ptr(block, type, ot, opcontext, str, x, y, width, height, tip);
}
/* if a1==1.0 then a2 is an extra icon blending factor (alpha 0.0 - 1.0) */
-uiBut *uiDefIconBut(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
-{
- uiBut *but = ui_def_but(block, type, retval, "", x, y, width, height, poin, min, max, a1, a2, tip);
- ui_but_update_and_icon_set(but, icon);
- return but;
-}
-static uiBut *uiDefIconButBit(uiBlock *block, int type, int bit, int retval, int icon, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
-{
- int bitIdx = findBitIndex(bit);
- if (bitIdx == -1) {
- return NULL;
- }
- else {
- return uiDefIconBut(block, type | UI_BUT_POIN_BIT | bitIdx, retval, icon, x, y, width, height, poin, min, max, a1, a2, tip);
- }
-}
-
-uiBut *uiDefIconButF(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefIconBut(block, type | UI_BUT_POIN_FLOAT, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefIconButBitF(uiBlock *block, int type, int bit, int retval, int icon, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefIconButBit(block, type | UI_BUT_POIN_FLOAT, bit, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefIconButI(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefIconBut(block, type | UI_BUT_POIN_INT, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefIconButBitI(uiBlock *block, int type, int bit, int retval, int icon, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefIconButBit(block, type | UI_BUT_POIN_INT, bit, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefIconButS(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefIconBut(block, type | UI_BUT_POIN_SHORT, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefIconButBitS(uiBlock *block, int type, int bit, int retval, int icon, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefIconButBit(block, type | UI_BUT_POIN_SHORT, bit, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefIconButC(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefIconBut(block, type | UI_BUT_POIN_CHAR, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefIconButBitC(uiBlock *block, int type, int bit, int retval, int icon, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefIconButBit(block, type | UI_BUT_POIN_CHAR, bit, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefIconButR(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip)
-{
- uiBut *but;
- but = ui_def_but_rna_propname(block, type, retval, "", x, y, width, height, ptr, propname, index, min, max, a1, a2, tip);
- ui_but_update_and_icon_set(but, icon);
- return but;
-}
-uiBut *uiDefIconButR_prop(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip)
-{
- uiBut *but;
- but = ui_def_but_rna(block, type, retval, "", x, y, width, height, ptr, prop, index, min, max, a1, a2, tip);
- ui_but_update_and_icon_set(but, icon);
- return but;
-}
-
-uiBut *uiDefIconButO_ptr(uiBlock *block, int type, wmOperatorType *ot, int opcontext, int icon, int x, int y, short width, short height, const char *tip)
-{
- uiBut *but;
- but = ui_def_but_operator_ptr(block, type, ot, opcontext, "", x, y, width, height, tip);
- ui_but_update_and_icon_set(but, icon);
- return but;
-}
-uiBut *uiDefIconButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, int x, int y, short width, short height, const char *tip)
-{
- wmOperatorType *ot = WM_operatortype_find(opname, 0);
- return uiDefIconButO_ptr(block, type, ot, opcontext, icon, x, y, width, height, tip);
+uiBut *uiDefIconBut(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ void *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ uiBut *but = ui_def_but(
+ block, type, retval, "", x, y, width, height, poin, min, max, a1, a2, tip);
+ ui_but_update_and_icon_set(but, icon);
+ return but;
+}
+static uiBut *uiDefIconButBit(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ void *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ int bitIdx = findBitIndex(bit);
+ if (bitIdx == -1) {
+ return NULL;
+ }
+ else {
+ return uiDefIconBut(block,
+ type | UI_BUT_POIN_BIT | bitIdx,
+ retval,
+ icon,
+ x,
+ y,
+ width,
+ height,
+ poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+ }
+}
+
+uiBut *uiDefIconButF(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ float *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefIconBut(block,
+ type | UI_BUT_POIN_FLOAT,
+ retval,
+ icon,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefIconButBitF(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ float *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefIconButBit(block,
+ type | UI_BUT_POIN_FLOAT,
+ bit,
+ retval,
+ icon,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefIconButI(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ int *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefIconBut(block,
+ type | UI_BUT_POIN_INT,
+ retval,
+ icon,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefIconButBitI(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ int *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefIconButBit(block,
+ type | UI_BUT_POIN_INT,
+ bit,
+ retval,
+ icon,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefIconButS(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ short *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefIconBut(block,
+ type | UI_BUT_POIN_SHORT,
+ retval,
+ icon,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefIconButBitS(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ short *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefIconButBit(block,
+ type | UI_BUT_POIN_SHORT,
+ bit,
+ retval,
+ icon,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefIconButC(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ char *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefIconBut(block,
+ type | UI_BUT_POIN_CHAR,
+ retval,
+ icon,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefIconButBitC(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ char *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefIconButBit(block,
+ type | UI_BUT_POIN_CHAR,
+ bit,
+ retval,
+ icon,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefIconButR(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ PointerRNA *ptr,
+ const char *propname,
+ int index,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ uiBut *but;
+ but = ui_def_but_rna_propname(
+ block, type, retval, "", x, y, width, height, ptr, propname, index, min, max, a1, a2, tip);
+ ui_but_update_and_icon_set(but, icon);
+ return but;
+}
+uiBut *uiDefIconButR_prop(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ int index,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ uiBut *but;
+ but = ui_def_but_rna(
+ block, type, retval, "", x, y, width, height, ptr, prop, index, min, max, a1, a2, tip);
+ ui_but_update_and_icon_set(but, icon);
+ return but;
+}
+
+uiBut *uiDefIconButO_ptr(uiBlock *block,
+ int type,
+ wmOperatorType *ot,
+ int opcontext,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip)
+{
+ uiBut *but;
+ but = ui_def_but_operator_ptr(block, type, ot, opcontext, "", x, y, width, height, tip);
+ ui_but_update_and_icon_set(but, icon);
+ return but;
+}
+uiBut *uiDefIconButO(uiBlock *block,
+ int type,
+ const char *opname,
+ int opcontext,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip)
+{
+ wmOperatorType *ot = WM_operatortype_find(opname, 0);
+ return uiDefIconButO_ptr(block, type, ot, opcontext, icon, x, y, width, height, tip);
}
/* Button containing both string label and icon */
-uiBut *uiDefIconTextBut(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
-{
- uiBut *but = ui_def_but(block, type, retval, str, x, y, width, height, poin, min, max, a1, a2, tip);
- ui_but_update_and_icon_set(but, icon);
- but->drawflag |= UI_BUT_ICON_LEFT;
- return but;
-}
-static uiBut *uiDefIconTextButBit(uiBlock *block, int type, int bit, int retval, int icon, const char *str, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
-{
- int bitIdx = findBitIndex(bit);
- if (bitIdx == -1) {
- return NULL;
- }
- else {
- return uiDefIconTextBut(block, type | UI_BUT_POIN_BIT | bitIdx, retval, icon, str, x, y, width, height, poin, min, max, a1, a2, tip);
- }
-}
-
-uiBut *uiDefIconTextButF(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefIconTextBut(block, type | UI_BUT_POIN_FLOAT, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefIconTextButBitF(uiBlock *block, int type, int bit, int retval, int icon, const char *str, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefIconTextButBit(block, type | UI_BUT_POIN_FLOAT, bit, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefIconTextButI(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefIconTextBut(block, type | UI_BUT_POIN_INT, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefIconTextButBitI(uiBlock *block, int type, int bit, int retval, int icon, const char *str, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefIconTextButBit(block, type | UI_BUT_POIN_INT, bit, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefIconTextButS(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefIconTextBut(block, type | UI_BUT_POIN_SHORT, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefIconTextButBitS(uiBlock *block, int type, int bit, int retval, int icon, const char *str, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefIconTextButBit(block, type | UI_BUT_POIN_SHORT, bit, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefIconTextButC(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefIconTextBut(block, type | UI_BUT_POIN_CHAR, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefIconTextButBitC(uiBlock *block, int type, int bit, int retval, int icon, const char *str, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip)
-{
- return uiDefIconTextButBit(block, type | UI_BUT_POIN_CHAR, bit, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip);
-}
-uiBut *uiDefIconTextButR(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip)
-{
- uiBut *but;
- but = ui_def_but_rna_propname(block, type, retval, str, x, y, width, height, ptr, propname, index, min, max, a1, a2, tip);
- ui_but_update_and_icon_set(but, icon);
- but->drawflag |= UI_BUT_ICON_LEFT;
- return but;
-}
-uiBut *uiDefIconTextButR_prop(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip)
-{
- uiBut *but;
- but = ui_def_but_rna(block, type, retval, str, x, y, width, height, ptr, prop, index, min, max, a1, a2, tip);
- ui_but_update_and_icon_set(but, icon);
- but->drawflag |= UI_BUT_ICON_LEFT;
- return but;
-}
-uiBut *uiDefIconTextButO_ptr(uiBlock *block, int type, wmOperatorType *ot, int opcontext, int icon, const char *str, int x, int y, short width, short height, const char *tip)
-{
- uiBut *but;
- but = ui_def_but_operator_ptr(block, type, ot, opcontext, str, x, y, width, height, tip);
- ui_but_update_and_icon_set(but, icon);
- but->drawflag |= UI_BUT_ICON_LEFT;
- return but;
-}
-uiBut *uiDefIconTextButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, const char *str, int x, int y, short width, short height, const char *tip)
-{
- wmOperatorType *ot = WM_operatortype_find(opname, 0);
- if (str && str[0] == '\0') {
- return uiDefIconButO_ptr(block, type, ot, opcontext, icon, x, y, width, height, tip);
- }
- return uiDefIconTextButO_ptr(block, type, ot, opcontext, icon, str, x, y, width, height, tip);
+uiBut *uiDefIconTextBut(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ void *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ uiBut *but = ui_def_but(
+ block, type, retval, str, x, y, width, height, poin, min, max, a1, a2, tip);
+ ui_but_update_and_icon_set(but, icon);
+ but->drawflag |= UI_BUT_ICON_LEFT;
+ return but;
+}
+static uiBut *uiDefIconTextButBit(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ void *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ int bitIdx = findBitIndex(bit);
+ if (bitIdx == -1) {
+ return NULL;
+ }
+ else {
+ return uiDefIconTextBut(block,
+ type | UI_BUT_POIN_BIT | bitIdx,
+ retval,
+ icon,
+ str,
+ x,
+ y,
+ width,
+ height,
+ poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+ }
+}
+
+uiBut *uiDefIconTextButF(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ float *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefIconTextBut(block,
+ type | UI_BUT_POIN_FLOAT,
+ retval,
+ icon,
+ str,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefIconTextButBitF(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ float *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefIconTextButBit(block,
+ type | UI_BUT_POIN_FLOAT,
+ bit,
+ retval,
+ icon,
+ str,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefIconTextButI(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ int *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefIconTextBut(block,
+ type | UI_BUT_POIN_INT,
+ retval,
+ icon,
+ str,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefIconTextButBitI(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ int *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefIconTextButBit(block,
+ type | UI_BUT_POIN_INT,
+ bit,
+ retval,
+ icon,
+ str,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefIconTextButS(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ short *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefIconTextBut(block,
+ type | UI_BUT_POIN_SHORT,
+ retval,
+ icon,
+ str,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefIconTextButBitS(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ short *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefIconTextButBit(block,
+ type | UI_BUT_POIN_SHORT,
+ bit,
+ retval,
+ icon,
+ str,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefIconTextButC(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ char *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefIconTextBut(block,
+ type | UI_BUT_POIN_CHAR,
+ retval,
+ icon,
+ str,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefIconTextButBitC(uiBlock *block,
+ int type,
+ int bit,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ char *poin,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ return uiDefIconTextButBit(block,
+ type | UI_BUT_POIN_CHAR,
+ bit,
+ retval,
+ icon,
+ str,
+ x,
+ y,
+ width,
+ height,
+ (void *)poin,
+ min,
+ max,
+ a1,
+ a2,
+ tip);
+}
+uiBut *uiDefIconTextButR(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ PointerRNA *ptr,
+ const char *propname,
+ int index,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ uiBut *but;
+ but = ui_def_but_rna_propname(
+ block, type, retval, str, x, y, width, height, ptr, propname, index, min, max, a1, a2, tip);
+ ui_but_update_and_icon_set(but, icon);
+ but->drawflag |= UI_BUT_ICON_LEFT;
+ return but;
+}
+uiBut *uiDefIconTextButR_prop(uiBlock *block,
+ int type,
+ int retval,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ int index,
+ float min,
+ float max,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ uiBut *but;
+ but = ui_def_but_rna(
+ block, type, retval, str, x, y, width, height, ptr, prop, index, min, max, a1, a2, tip);
+ ui_but_update_and_icon_set(but, icon);
+ but->drawflag |= UI_BUT_ICON_LEFT;
+ return but;
+}
+uiBut *uiDefIconTextButO_ptr(uiBlock *block,
+ int type,
+ wmOperatorType *ot,
+ int opcontext,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip)
+{
+ uiBut *but;
+ but = ui_def_but_operator_ptr(block, type, ot, opcontext, str, x, y, width, height, tip);
+ ui_but_update_and_icon_set(but, icon);
+ but->drawflag |= UI_BUT_ICON_LEFT;
+ return but;
+}
+uiBut *uiDefIconTextButO(uiBlock *block,
+ int type,
+ const char *opname,
+ int opcontext,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip)
+{
+ wmOperatorType *ot = WM_operatortype_find(opname, 0);
+ if (str && str[0] == '\0') {
+ return uiDefIconButO_ptr(block, type, ot, opcontext, icon, x, y, width, height, tip);
+ }
+ return uiDefIconTextButO_ptr(block, type, ot, opcontext, icon, str, x, y, width, height, tip);
}
/* END Button containing both string label and icon */
@@ -4411,550 +5536,703 @@ uiBut *uiDefIconTextButO(uiBlock *block, int type, const char *opname, int opcon
int UI_blocklist_min_y_get(ListBase *lb)
{
- uiBlock *block;
- int min = 0;
+ uiBlock *block;
+ int min = 0;
- for (block = lb->first; block; block = block->next) {
- if (block == lb->first || block->rect.ymin < min) {
- min = block->rect.ymin;
- }
- }
+ for (block = lb->first; block; block = block->next) {
+ if (block == lb->first || block->rect.ymin < min) {
+ min = block->rect.ymin;
+ }
+ }
- return min;
+ return min;
}
void UI_block_direction_set(uiBlock *block, char direction)
{
- block->direction = direction;
+ block->direction = direction;
}
/* this call escapes if there's alignment flags */
void UI_block_order_flip(uiBlock *block)
{
- uiBut *but;
- float centy, miny = 10000, maxy = -10000;
-
- if (U.uiflag & USER_MENUFIXEDORDER) {
- return;
- }
- else if (block->flag & UI_BLOCK_NO_FLIP) {
- return;
- }
-
- for (but = block->buttons.first; but; but = but->next) {
- if (but->drawflag & UI_BUT_ALIGN) {
- return;
- }
- if (but->rect.ymin < miny) {
- miny = but->rect.ymin;
- }
- if (but->rect.ymax > maxy) {
- maxy = but->rect.ymax;
- }
- }
- /* mirror trick */
- centy = (miny + maxy) / 2.0f;
- for (but = block->buttons.first; but; but = but->next) {
- but->rect.ymin = centy - (but->rect.ymin - centy);
- but->rect.ymax = centy - (but->rect.ymax - centy);
- SWAP(float, but->rect.ymin, but->rect.ymax);
- }
-
- block->flag ^= UI_BLOCK_IS_FLIP;
+ uiBut *but;
+ float centy, miny = 10000, maxy = -10000;
+
+ if (U.uiflag & USER_MENUFIXEDORDER) {
+ return;
+ }
+ else if (block->flag & UI_BLOCK_NO_FLIP) {
+ return;
+ }
+
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->drawflag & UI_BUT_ALIGN) {
+ return;
+ }
+ if (but->rect.ymin < miny) {
+ miny = but->rect.ymin;
+ }
+ if (but->rect.ymax > maxy) {
+ maxy = but->rect.ymax;
+ }
+ }
+ /* mirror trick */
+ centy = (miny + maxy) / 2.0f;
+ for (but = block->buttons.first; but; but = but->next) {
+ but->rect.ymin = centy - (but->rect.ymin - centy);
+ but->rect.ymax = centy - (but->rect.ymax - centy);
+ SWAP(float, but->rect.ymin, but->rect.ymax);
+ }
+
+ block->flag ^= UI_BLOCK_IS_FLIP;
}
-
void UI_block_flag_enable(uiBlock *block, int flag)
{
- block->flag |= flag;
+ block->flag |= flag;
}
void UI_block_flag_disable(uiBlock *block, int flag)
{
- block->flag &= ~flag;
+ block->flag &= ~flag;
}
void UI_but_flag_enable(uiBut *but, int flag)
{
- but->flag |= flag;
+ but->flag |= flag;
}
void UI_but_flag_disable(uiBut *but, int flag)
{
- but->flag &= ~flag;
+ but->flag &= ~flag;
}
bool UI_but_flag_is_set(uiBut *but, int flag)
{
- return (but->flag & flag) != 0;
+ return (but->flag & flag) != 0;
}
void UI_but_drawflag_enable(uiBut *but, int flag)
{
- but->drawflag |= flag;
+ but->drawflag |= flag;
}
void UI_but_drawflag_disable(uiBut *but, int flag)
{
- but->drawflag &= ~flag;
+ but->drawflag &= ~flag;
}
void UI_but_type_set_menu_from_pulldown(uiBut *but)
{
- BLI_assert(but->type == UI_BTYPE_PULLDOWN);
- but->type = UI_BTYPE_MENU;
- UI_but_drawflag_disable(but, UI_BUT_TEXT_RIGHT);
- UI_but_drawflag_enable(but, UI_BUT_TEXT_LEFT);
+ BLI_assert(but->type == UI_BTYPE_PULLDOWN);
+ but->type = UI_BTYPE_MENU;
+ UI_but_drawflag_disable(but, UI_BUT_TEXT_RIGHT);
+ UI_but_drawflag_enable(but, UI_BUT_TEXT_LEFT);
}
int UI_but_return_value_get(uiBut *but)
{
- return but->retval;
+ return but->retval;
}
void UI_but_drag_set_id(uiBut *but, ID *id)
{
- but->dragtype = WM_DRAG_ID;
- if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
- MEM_SAFE_FREE(but->dragpoin);
- but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
- }
- but->dragpoin = (void *)id;
+ but->dragtype = WM_DRAG_ID;
+ if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
+ MEM_SAFE_FREE(but->dragpoin);
+ but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
+ }
+ but->dragpoin = (void *)id;
}
void UI_but_drag_set_rna(uiBut *but, PointerRNA *ptr)
{
- but->dragtype = WM_DRAG_RNA;
- if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
- MEM_SAFE_FREE(but->dragpoin);
- but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
- }
- but->dragpoin = (void *)ptr;
+ but->dragtype = WM_DRAG_RNA;
+ if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
+ MEM_SAFE_FREE(but->dragpoin);
+ but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
+ }
+ but->dragpoin = (void *)ptr;
}
void UI_but_drag_set_path(uiBut *but, const char *path, const bool use_free)
{
- but->dragtype = WM_DRAG_PATH;
- if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
- MEM_SAFE_FREE(but->dragpoin);
- but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
- }
- but->dragpoin = (void *)path;
- if (use_free) {
- but->dragflag |= UI_BUT_DRAGPOIN_FREE;
- }
+ but->dragtype = WM_DRAG_PATH;
+ if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
+ MEM_SAFE_FREE(but->dragpoin);
+ but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
+ }
+ but->dragpoin = (void *)path;
+ if (use_free) {
+ but->dragflag |= UI_BUT_DRAGPOIN_FREE;
+ }
}
void UI_but_drag_set_name(uiBut *but, const char *name)
{
- but->dragtype = WM_DRAG_NAME;
- if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
- MEM_SAFE_FREE(but->dragpoin);
- but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
- }
- but->dragpoin = (void *)name;
+ but->dragtype = WM_DRAG_NAME;
+ if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
+ MEM_SAFE_FREE(but->dragpoin);
+ but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
+ }
+ but->dragpoin = (void *)name;
}
/* value from button itself */
void UI_but_drag_set_value(uiBut *but)
{
- but->dragtype = WM_DRAG_VALUE;
+ but->dragtype = WM_DRAG_VALUE;
}
-void UI_but_drag_set_image(uiBut *but, const char *path, int icon, struct ImBuf *imb, float scale, const bool use_free)
+void UI_but_drag_set_image(
+ uiBut *but, const char *path, int icon, struct ImBuf *imb, float scale, const bool use_free)
{
- but->dragtype = WM_DRAG_PATH;
- ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */
- if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
- MEM_SAFE_FREE(but->dragpoin);
- but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
- }
- but->dragpoin = (void *)path;
- if (use_free) {
- but->dragflag |= UI_BUT_DRAGPOIN_FREE;
- }
- but->imb = imb;
- but->imb_scale = scale;
+ but->dragtype = WM_DRAG_PATH;
+ ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */
+ if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
+ MEM_SAFE_FREE(but->dragpoin);
+ but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
+ }
+ but->dragpoin = (void *)path;
+ if (use_free) {
+ but->dragflag |= UI_BUT_DRAGPOIN_FREE;
+ }
+ but->imb = imb;
+ but->imb_scale = scale;
}
PointerRNA *UI_but_operator_ptr_get(uiBut *but)
{
- if (but->optype && !but->opptr) {
- but->opptr = MEM_callocN(sizeof(PointerRNA), "uiButOpPtr");
- WM_operator_properties_create_ptr(but->opptr, but->optype);
- }
+ if (but->optype && !but->opptr) {
+ but->opptr = MEM_callocN(sizeof(PointerRNA), "uiButOpPtr");
+ WM_operator_properties_create_ptr(but->opptr, but->optype);
+ }
- return but->opptr;
+ return but->opptr;
}
void UI_but_unit_type_set(uiBut *but, const int unit_type)
{
- but->unit_type = (uchar)(RNA_SUBTYPE_UNIT_VALUE(unit_type));
+ but->unit_type = (uchar)(RNA_SUBTYPE_UNIT_VALUE(unit_type));
}
int UI_but_unit_type_get(const uiBut *but)
{
- int ownUnit = (int)but->unit_type;
+ int ownUnit = (int)but->unit_type;
- /* own unit define always takes precedence over RNA provided, allowing for overriding
- * default value provided in RNA in a few special cases (i.e. Active Keyframe in Graph Edit)
- */
- /* XXX: this doesn't allow clearing unit completely, though the same could be said for icons */
- if ((ownUnit != 0) || (but->rnaprop == NULL)) {
- return ownUnit << 16;
- }
- else {
- return RNA_SUBTYPE_UNIT(RNA_property_subtype(but->rnaprop));
- }
+ /* own unit define always takes precedence over RNA provided, allowing for overriding
+ * default value provided in RNA in a few special cases (i.e. Active Keyframe in Graph Edit)
+ */
+ /* XXX: this doesn't allow clearing unit completely, though the same could be said for icons */
+ if ((ownUnit != 0) || (but->rnaprop == NULL)) {
+ return ownUnit << 16;
+ }
+ else {
+ return RNA_SUBTYPE_UNIT(RNA_property_subtype(but->rnaprop));
+ }
}
void UI_block_func_handle_set(uiBlock *block, uiBlockHandleFunc func, void *arg)
{
- block->handle_func = func;
- block->handle_func_arg = arg;
+ block->handle_func = func;
+ block->handle_func_arg = arg;
}
void UI_block_func_butmenu_set(uiBlock *block, uiMenuHandleFunc func, void *arg)
{
- block->butm_func = func;
- block->butm_func_arg = arg;
+ block->butm_func = func;
+ block->butm_func_arg = arg;
}
void UI_block_func_set(uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2)
{
- block->func = func;
- block->func_arg1 = arg1;
- block->func_arg2 = arg2;
+ block->func = func;
+ block->func_arg1 = arg1;
+ block->func_arg2 = arg2;
}
void UI_block_funcN_set(uiBlock *block, uiButHandleNFunc funcN, void *argN, void *arg2)
{
- if (block->func_argN) {
- MEM_freeN(block->func_argN);
- }
+ if (block->func_argN) {
+ MEM_freeN(block->func_argN);
+ }
- block->funcN = funcN;
- block->func_argN = argN;
- block->func_arg2 = arg2;
+ block->funcN = funcN;
+ block->func_argN = argN;
+ block->func_arg2 = arg2;
}
void UI_but_func_rename_set(uiBut *but, uiButHandleRenameFunc func, void *arg1)
{
- but->rename_func = func;
- but->rename_arg1 = arg1;
+ but->rename_func = func;
+ but->rename_arg1 = arg1;
}
-void UI_but_func_drawextra_set(uiBlock *block, void (*func)(const bContext *C, void *idv, void *arg1, void *arg2, rcti *rect), void *arg1, void *arg2)
+void UI_but_func_drawextra_set(
+ uiBlock *block,
+ void (*func)(const bContext *C, void *idv, void *arg1, void *arg2, rcti *rect),
+ void *arg1,
+ void *arg2)
{
- block->drawextra = func;
- block->drawextra_arg1 = arg1;
- block->drawextra_arg2 = arg2;
+ block->drawextra = func;
+ block->drawextra_arg1 = arg1;
+ block->drawextra_arg2 = arg2;
}
void UI_but_func_set(uiBut *but, uiButHandleFunc func, void *arg1, void *arg2)
{
- but->func = func;
- but->func_arg1 = arg1;
- but->func_arg2 = arg2;
+ but->func = func;
+ but->func_arg1 = arg1;
+ but->func_arg2 = arg2;
}
void UI_but_funcN_set(uiBut *but, uiButHandleNFunc funcN, void *argN, void *arg2)
{
- if (but->func_argN) {
- MEM_freeN(but->func_argN);
- }
+ if (but->func_argN) {
+ MEM_freeN(but->func_argN);
+ }
- but->funcN = funcN;
- but->func_argN = argN;
- but->func_arg2 = arg2;
+ but->funcN = funcN;
+ but->func_argN = argN;
+ but->func_arg2 = arg2;
}
void UI_but_func_complete_set(uiBut *but, uiButCompleteFunc func, void *arg)
{
- but->autocomplete_func = func;
- but->autofunc_arg = arg;
+ but->autocomplete_func = func;
+ but->autofunc_arg = arg;
}
void UI_but_func_menu_step_set(uiBut *but, uiMenuStepFunc func)
{
- but->menu_step_func = func;
+ but->menu_step_func = func;
}
void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *argN)
{
- but->tip_func = func;
- if (but->tip_argN) {
- MEM_freeN(but->tip_argN);
- }
- but->tip_argN = argN;
+ but->tip_func = func;
+ if (but->tip_argN) {
+ MEM_freeN(but->tip_argN);
+ }
+ but->tip_argN = argN;
}
void UI_but_func_pushed_state_set(uiBut *but, uiButPushedStateFunc func, void *arg)
{
- but->pushed_state_func = func;
- but->pushed_state_arg = arg;
-}
-
-uiBut *uiDefBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, const char *str, int x, int y, short width, short height, const char *tip)
-{
- uiBut *but = ui_def_but(block, UI_BTYPE_BLOCK, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
- but->block_create_func = func;
- ui_but_update(but);
- return but;
-}
-
-uiBut *uiDefBlockButN(uiBlock *block, uiBlockCreateFunc func, void *argN, const char *str, int x, int y, short width, short height, const char *tip)
-{
- uiBut *but = ui_def_but(block, UI_BTYPE_BLOCK, 0, str, x, y, width, height, NULL, 0.0, 0.0, 0.0, 0.0, tip);
- but->block_create_func = func;
- if (but->func_argN) {
- MEM_freeN(but->func_argN);
- }
- but->func_argN = argN;
- ui_but_update(but);
- return but;
-}
-
-
-uiBut *uiDefPulldownBut(uiBlock *block, uiBlockCreateFunc func, void *arg, const char *str, int x, int y, short width, short height, const char *tip)
-{
- uiBut *but = ui_def_but(block, UI_BTYPE_PULLDOWN, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
- but->block_create_func = func;
- ui_but_update(but);
- return but;
-}
-
-uiBut *uiDefMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, const char *str, int x, int y, short width, short height, const char *tip)
-{
- uiBut *but = ui_def_but(block, UI_BTYPE_PULLDOWN, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
- but->menu_create_func = func;
- ui_but_update(but);
- return but;
-}
-
-uiBut *uiDefIconTextMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int icon, const char *str, int x, int y, short width, short height, const char *tip)
-{
- uiBut *but = ui_def_but(block, UI_BTYPE_PULLDOWN, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
-
- ui_def_but_icon(but, icon, UI_HAS_ICON);
-
- but->drawflag |= UI_BUT_ICON_LEFT;
- ui_but_submenu_enable(block, but);
-
- but->menu_create_func = func;
- ui_but_update(but);
-
- return but;
-}
-
-uiBut *uiDefIconMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int icon, int x, int y, short width, short height, const char *tip)
-{
- uiBut *but = ui_def_but(block, UI_BTYPE_PULLDOWN, 0, "", x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
-
- ui_def_but_icon(but, icon, UI_HAS_ICON);
- but->drawflag &= ~UI_BUT_ICON_LEFT;
-
- but->menu_create_func = func;
- ui_but_update(but);
-
- return but;
+ but->pushed_state_func = func;
+ but->pushed_state_arg = arg;
+}
+
+uiBut *uiDefBlockBut(uiBlock *block,
+ uiBlockCreateFunc func,
+ void *arg,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip)
+{
+ uiBut *but = ui_def_but(
+ block, UI_BTYPE_BLOCK, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
+ but->block_create_func = func;
+ ui_but_update(but);
+ return but;
+}
+
+uiBut *uiDefBlockButN(uiBlock *block,
+ uiBlockCreateFunc func,
+ void *argN,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip)
+{
+ uiBut *but = ui_def_but(
+ block, UI_BTYPE_BLOCK, 0, str, x, y, width, height, NULL, 0.0, 0.0, 0.0, 0.0, tip);
+ but->block_create_func = func;
+ if (but->func_argN) {
+ MEM_freeN(but->func_argN);
+ }
+ but->func_argN = argN;
+ ui_but_update(but);
+ return but;
+}
+
+uiBut *uiDefPulldownBut(uiBlock *block,
+ uiBlockCreateFunc func,
+ void *arg,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip)
+{
+ uiBut *but = ui_def_but(
+ block, UI_BTYPE_PULLDOWN, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
+ but->block_create_func = func;
+ ui_but_update(but);
+ return but;
+}
+
+uiBut *uiDefMenuBut(uiBlock *block,
+ uiMenuCreateFunc func,
+ void *arg,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip)
+{
+ uiBut *but = ui_def_but(
+ block, UI_BTYPE_PULLDOWN, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
+ but->menu_create_func = func;
+ ui_but_update(but);
+ return but;
+}
+
+uiBut *uiDefIconTextMenuBut(uiBlock *block,
+ uiMenuCreateFunc func,
+ void *arg,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip)
+{
+ uiBut *but = ui_def_but(
+ block, UI_BTYPE_PULLDOWN, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
+
+ ui_def_but_icon(but, icon, UI_HAS_ICON);
+
+ but->drawflag |= UI_BUT_ICON_LEFT;
+ ui_but_submenu_enable(block, but);
+
+ but->menu_create_func = func;
+ ui_but_update(but);
+
+ return but;
+}
+
+uiBut *uiDefIconMenuBut(uiBlock *block,
+ uiMenuCreateFunc func,
+ void *arg,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip)
+{
+ uiBut *but = ui_def_but(
+ block, UI_BTYPE_PULLDOWN, 0, "", x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
+
+ ui_def_but_icon(but, icon, UI_HAS_ICON);
+ but->drawflag &= ~UI_BUT_ICON_LEFT;
+
+ but->menu_create_func = func;
+ ui_but_update(but);
+
+ return but;
}
/* Block button containing both string label and icon */
-uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int icon, const char *str, int x, int y, short width, short height, const char *tip)
-{
- uiBut *but = ui_def_but(block, UI_BTYPE_BLOCK, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
-
- /* XXX temp, old menu calls pass on icon arrow, which is now UI_BUT_ICON_SUBMENU flag */
- if (icon != ICON_RIGHTARROW_THIN) {
- ui_def_but_icon(but, icon, 0);
- but->drawflag |= UI_BUT_ICON_LEFT;
- }
- but->flag |= UI_HAS_ICON;
- ui_but_submenu_enable(block, but);
-
- but->block_create_func = func;
- ui_but_update(but);
-
- return but;
+uiBut *uiDefIconTextBlockBut(uiBlock *block,
+ uiBlockCreateFunc func,
+ void *arg,
+ int icon,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip)
+{
+ uiBut *but = ui_def_but(
+ block, UI_BTYPE_BLOCK, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
+
+ /* XXX temp, old menu calls pass on icon arrow, which is now UI_BUT_ICON_SUBMENU flag */
+ if (icon != ICON_RIGHTARROW_THIN) {
+ ui_def_but_icon(but, icon, 0);
+ but->drawflag |= UI_BUT_ICON_LEFT;
+ }
+ but->flag |= UI_HAS_ICON;
+ ui_but_submenu_enable(block, but);
+
+ but->block_create_func = func;
+ ui_but_update(but);
+
+ return but;
}
/* Block button containing icon */
-uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int retval, int icon, int x, int y, short width, short height, const char *tip)
-{
- uiBut *but = ui_def_but(block, UI_BTYPE_BLOCK, retval, "", x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
-
- ui_def_but_icon(but, icon, UI_HAS_ICON);
-
- but->drawflag |= UI_BUT_ICON_LEFT;
-
- but->block_create_func = func;
- ui_but_update(but);
-
- return but;
-}
-
-uiBut *uiDefKeyevtButS(uiBlock *block, int retval, const char *str, int x, int y, short width, short height, short *spoin, const char *tip)
-{
- uiBut *but = ui_def_but(block, UI_BTYPE_KEY_EVENT | UI_BUT_POIN_SHORT, retval, str, x, y, width, height, spoin, 0.0, 0.0, 0.0, 0.0, tip);
- ui_but_update(but);
- return but;
+uiBut *uiDefIconBlockBut(uiBlock *block,
+ uiBlockCreateFunc func,
+ void *arg,
+ int retval,
+ int icon,
+ int x,
+ int y,
+ short width,
+ short height,
+ const char *tip)
+{
+ uiBut *but = ui_def_but(
+ block, UI_BTYPE_BLOCK, retval, "", x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
+
+ ui_def_but_icon(but, icon, UI_HAS_ICON);
+
+ but->drawflag |= UI_BUT_ICON_LEFT;
+
+ but->block_create_func = func;
+ ui_but_update(but);
+
+ return but;
+}
+
+uiBut *uiDefKeyevtButS(uiBlock *block,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ short *spoin,
+ const char *tip)
+{
+ uiBut *but = ui_def_but(block,
+ UI_BTYPE_KEY_EVENT | UI_BUT_POIN_SHORT,
+ retval,
+ str,
+ x,
+ y,
+ width,
+ height,
+ spoin,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ tip);
+ ui_but_update(but);
+ return but;
}
/* short pointers hardcoded */
/* modkeypoin will be set to KM_SHIFT, KM_ALT, KM_CTRL, KM_OSKEY bits */
-uiBut *uiDefHotKeyevtButS(uiBlock *block, int retval, const char *str, int x, int y, short width, short height, short *keypoin, short *modkeypoin, const char *tip)
-{
- uiBut *but = ui_def_but(block, UI_BTYPE_HOTKEY_EVENT | UI_BUT_POIN_SHORT, retval, str, x, y, width, height, keypoin, 0.0, 0.0, 0.0, 0.0, tip);
- but->modifier_key = *modkeypoin;
- ui_but_update(but);
- return but;
+uiBut *uiDefHotKeyevtButS(uiBlock *block,
+ int retval,
+ const char *str,
+ int x,
+ int y,
+ short width,
+ short height,
+ short *keypoin,
+ short *modkeypoin,
+ const char *tip)
+{
+ uiBut *but = ui_def_but(block,
+ UI_BTYPE_HOTKEY_EVENT | UI_BUT_POIN_SHORT,
+ retval,
+ str,
+ x,
+ y,
+ width,
+ height,
+ keypoin,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ tip);
+ but->modifier_key = *modkeypoin;
+ ui_but_update(but);
+ return but;
}
-
/* arg is pointer to string/name, use UI_but_func_search_set() below to make this work */
/* here a1 and a2, if set, control thumbnail preview rows/cols */
-uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxlen, int x, int y, short width, short height, float a1, float a2, const char *tip)
+uiBut *uiDefSearchBut(uiBlock *block,
+ void *arg,
+ int retval,
+ int icon,
+ int maxlen,
+ int x,
+ int y,
+ short width,
+ short height,
+ float a1,
+ float a2,
+ const char *tip)
{
- uiBut *but = ui_def_but(block, UI_BTYPE_SEARCH_MENU, retval, "", x, y, width, height, arg, 0.0, maxlen, a1, a2, tip);
+ uiBut *but = ui_def_but(
+ block, UI_BTYPE_SEARCH_MENU, retval, "", x, y, width, height, arg, 0.0, maxlen, a1, a2, tip);
- ui_def_but_icon(but, icon, UI_HAS_ICON);
+ ui_def_but_icon(but, icon, UI_HAS_ICON);
- but->drawflag |= UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT;
+ but->drawflag |= UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT;
- ui_but_update(but);
+ ui_but_update(but);
- return but;
+ return but;
}
-
/**
* \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.
*/
-void UI_but_func_search_set(
- uiBut *but,
- uiButSearchCreateFunc search_create_func,
- uiButSearchFunc search_func, void *arg, bool free_arg,
- uiButHandleFunc bfunc, 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 (but->free_search_arg) {
- MEM_SAFE_FREE(but->search_arg);
- }
-
- but->search_create_func = search_create_func;
- but->search_func = search_func;
- but->search_arg = arg;
- but->free_search_arg = free_arg;
-
- if (bfunc) {
+void UI_but_func_search_set(uiBut *but,
+ uiButSearchCreateFunc search_create_func,
+ uiButSearchFunc search_func,
+ void *arg,
+ bool free_arg,
+ uiButHandleFunc bfunc,
+ 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 (but->free_search_arg) {
+ MEM_SAFE_FREE(but->search_arg);
+ }
+
+ but->search_create_func = search_create_func;
+ but->search_func = search_func;
+ but->search_arg = arg;
+ but->free_search_arg = free_arg;
+
+ if (bfunc) {
#ifdef DEBUG
- if (but->func) {
- /* watch this, can be cause of much confusion, see: T47691 */
- printf("%s: warning, overwriting button callback with search function callback!\n", __func__);
- }
+ if (but->func) {
+ /* watch this, can be cause of much confusion, see: T47691 */
+ printf("%s: warning, overwriting button callback with search function callback!\n",
+ __func__);
+ }
#endif
- UI_but_func_set(but, bfunc, arg, active);
- }
+ UI_but_func_set(but, bfunc, arg, active);
+ }
- /* search buttons show red-alert if item doesn't exist, not for menus */
- if (0 == (but->block->flag & UI_BLOCK_LOOP)) {
- /* skip empty buttons, not all buttons need input, we only show invalid */
- if (but->drawstr[0]) {
- ui_but_search_refresh(but);
- }
- }
+ /* search buttons show red-alert if item doesn't exist, not for menus */
+ if (0 == (but->block->flag & UI_BLOCK_LOOP)) {
+ /* skip empty buttons, not all buttons need input, we only show invalid */
+ if (but->drawstr[0]) {
+ ui_but_search_refresh(but);
+ }
+ }
}
/* Callbacks for operator search button. */
-static void operator_enum_search_cb(const struct bContext *C, void *but, const char *str, uiSearchItems *items)
-{
- wmOperatorType *ot = ((uiBut *)but)->optype;
- PropertyRNA *prop = ot->prop;
-
- if (prop == NULL) {
- printf("%s: %s has no enum property set\n",
- __func__, ot->idname);
- }
- else if (RNA_property_type(prop) != PROP_ENUM) {
- printf("%s: %s \"%s\" is not an enum property\n",
- __func__, ot->idname, RNA_property_identifier(prop));
- }
- else {
- PointerRNA *ptr = UI_but_operator_ptr_get(but); /* Will create it if needed! */
- const EnumPropertyItem *item, *item_array;
- bool do_free;
-
- RNA_property_enum_items_gettexted((bContext *)C, ptr, prop, &item_array, NULL, &do_free);
-
- for (item = item_array; item->identifier; item++) {
- /* 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)) {
- break;
- }
- }
- }
-
- if (do_free) {
- MEM_freeN((void *)item_array);
- }
- }
+static void operator_enum_search_cb(const struct bContext *C,
+ void *but,
+ const char *str,
+ uiSearchItems *items)
+{
+ wmOperatorType *ot = ((uiBut *)but)->optype;
+ PropertyRNA *prop = ot->prop;
+
+ if (prop == NULL) {
+ printf("%s: %s has no enum property set\n", __func__, ot->idname);
+ }
+ else if (RNA_property_type(prop) != PROP_ENUM) {
+ printf("%s: %s \"%s\" is not an enum property\n",
+ __func__,
+ ot->idname,
+ RNA_property_identifier(prop));
+ }
+ else {
+ PointerRNA *ptr = UI_but_operator_ptr_get(but); /* Will create it if needed! */
+ const EnumPropertyItem *item, *item_array;
+ bool do_free;
+
+ RNA_property_enum_items_gettexted((bContext *)C, ptr, prop, &item_array, NULL, &do_free);
+
+ for (item = item_array; item->identifier; item++) {
+ /* 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)) {
+ break;
+ }
+ }
+ }
+
+ if (do_free) {
+ MEM_freeN((void *)item_array);
+ }
+ }
}
static void operator_enum_call_cb(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! */
+ wmOperatorType *ot = ((uiBut *)but)->optype;
+ PointerRNA *opptr = UI_but_operator_ptr_get(but); /* Will create it if needed! */
- if (ot) {
- if (ot->prop) {
- RNA_property_enum_set(opptr, ot->prop, POINTER_AS_INT(arg2));
- /* We do not call op from here, will be called by button code.
- * ui_apply_but_funcs_after() (in interface_handlers.c) called this func before checking operators,
- * because one of its parameters is the button itself!
- */
- }
- else {
- printf("%s: op->prop for '%s' is NULL\n", __func__, ot->idname);
- }
- }
+ if (ot) {
+ if (ot->prop) {
+ RNA_property_enum_set(opptr, ot->prop, POINTER_AS_INT(arg2));
+ /* We do not call op from here, will be called by button code.
+ * ui_apply_but_funcs_after() (in interface_handlers.c) called this func before checking operators,
+ * because one of its parameters is the button itself!
+ */
+ }
+ else {
+ printf("%s: op->prop for '%s' is NULL\n", __func__, ot->idname);
+ }
+ }
}
/**
* Same parameters as for uiDefSearchBut, with additional operator type and properties, used by callback
* to call again the right op with the right options (properties values).
*/
-uiBut *uiDefSearchButO_ptr(
- uiBlock *block, wmOperatorType *ot, IDProperty *properties,
- void *arg, int retval, int icon, int maxlen, int x, int y,
- short width, short height, float a1, float a2, const char *tip)
-{
- uiBut *but;
-
- 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,
- but, false, operator_enum_call_cb, NULL);
-
- but->optype = ot;
- but->opcontext = WM_OP_EXEC_DEFAULT;
-
- if (properties) {
- PointerRNA *ptr = UI_but_operator_ptr_get(but);
- /* Copy idproperties. */
- ptr->data = IDP_CopyProperty(properties);
- }
-
- return but;
+uiBut *uiDefSearchButO_ptr(uiBlock *block,
+ wmOperatorType *ot,
+ IDProperty *properties,
+ void *arg,
+ int retval,
+ int icon,
+ int maxlen,
+ int x,
+ int y,
+ short width,
+ short height,
+ float a1,
+ float a2,
+ const char *tip)
+{
+ uiBut *but;
+
+ 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,
+ but,
+ false,
+ operator_enum_call_cb,
+ NULL);
+
+ but->optype = ot;
+ but->opcontext = WM_OP_EXEC_DEFAULT;
+
+ if (properties) {
+ PointerRNA *ptr = UI_but_operator_ptr_get(but);
+ /* Copy idproperties. */
+ ptr->data = IDP_CopyProperty(properties);
+ }
+
+ return but;
}
/**
@@ -4963,260 +6241,259 @@ uiBut *uiDefSearchButO_ptr(
*/
void UI_but_focus_on_enter_event(wmWindow *win, uiBut *but)
{
- wmEvent event;
+ wmEvent event;
- wm_event_init_from_window(win, &event);
+ wm_event_init_from_window(win, &event);
- event.type = EVT_BUT_OPEN;
- event.val = KM_PRESS;
- event.customdata = but;
- event.customdatafree = false;
+ event.type = EVT_BUT_OPEN;
+ event.val = KM_PRESS;
+ event.customdata = but;
+ event.customdatafree = false;
- wm_event_add(win, &event);
+ wm_event_add(win, &event);
}
void UI_but_func_hold_set(uiBut *but, uiButHandleHoldFunc func, void *argN)
{
- but->hold_func = func;
- but->hold_argN = argN;
+ but->hold_func = func;
+ but->hold_argN = argN;
}
void UI_but_string_info_get(bContext *C, uiBut *but, ...)
{
- va_list args;
- uiStringInfo *si;
-
- const EnumPropertyItem *items = NULL, *item = NULL;
- int totitems;
- bool free_items = false;
-
- va_start(args, but);
- while ((si = (uiStringInfo *) va_arg(args, void *))) {
- int type = si->type;
- char *tmp = NULL;
-
- if (type == BUT_GET_LABEL) {
- if (but->str) {
- const char *str_sep;
- size_t str_len;
-
- if ((but->flag & UI_BUT_HAS_SEP_CHAR) &&
- (str_sep = strrchr(but->str, UI_SEP_CHAR)))
- {
- str_len = (str_sep - but->str);
- }
- else {
- str_len = strlen(but->str);
- }
-
- tmp = BLI_strdupn(but->str, str_len);
- }
- else {
- type = BUT_GET_RNA_LABEL; /* Fail-safe solution... */
- }
- }
- else if (type == BUT_GET_TIP) {
- if (but->tip_func) {
- tmp = but->tip_func(C, but->tip_argN, but->tip);
- }
- else if (but->tip && but->tip[0]) {
- tmp = BLI_strdup(but->tip);
- }
- else {
- type = BUT_GET_RNA_TIP; /* Fail-safe solution... */
- }
- }
-
- if (type == BUT_GET_RNAPROP_IDENTIFIER) {
- if (but->rnaprop) {
- tmp = BLI_strdup(RNA_property_identifier(but->rnaprop));
- }
- }
- else if (type == BUT_GET_RNASTRUCT_IDENTIFIER) {
- if (but->rnaprop && but->rnapoin.data) {
- tmp = BLI_strdup(RNA_struct_identifier(but->rnapoin.type));
- }
- else if (but->optype) {
- tmp = BLI_strdup(but->optype->idname);
- }
- else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN)) {
- MenuType *mt = UI_but_menutype_get(but);
- if (mt) {
- tmp = BLI_strdup(mt->idname);
- }
- }
- else if (but->type == UI_BTYPE_POPOVER) {
- PanelType *pt = UI_but_paneltype_get(but);
- if (pt) {
- tmp = BLI_strdup(pt->idname);
- }
- }
- }
- else if (ELEM(type, BUT_GET_RNA_LABEL, BUT_GET_RNA_TIP)) {
- if (but->rnaprop) {
- if (type == BUT_GET_RNA_LABEL) {
- tmp = BLI_strdup(RNA_property_ui_name(but->rnaprop));
- }
- else {
- const char *t = RNA_property_ui_description(but->rnaprop);
- if (t && t[0]) {
- tmp = BLI_strdup(t);
- }
- }
- }
- else if (but->optype) {
- if (type == BUT_GET_RNA_LABEL) {
- tmp = BLI_strdup(RNA_struct_ui_name(but->optype->srna));
- }
- else {
- const char *t = RNA_struct_ui_description(but->optype->srna);
- if (t && t[0]) {
- tmp = BLI_strdup(t);
- }
- }
- }
- else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN)) {
- MenuType *mt = UI_but_menutype_get(but);
- if (mt) {
- /* not all menus are from python */
- if (mt->ext.srna) {
- if (type == BUT_GET_RNA_LABEL) {
- tmp = BLI_strdup(RNA_struct_ui_name(mt->ext.srna));
- }
- else {
- const char *t = RNA_struct_ui_description(mt->ext.srna);
- if (t && t[0]) {
- tmp = BLI_strdup(t);
- }
- }
- }
- }
- }
- }
- else if (type == BUT_GET_RNA_LABEL_CONTEXT) {
- const char *_tmp = BLT_I18NCONTEXT_DEFAULT;
- if (but->rnaprop) {
- _tmp = RNA_property_translation_context(but->rnaprop);
- }
- else if (but->optype) {
- _tmp = RNA_struct_translation_context(but->optype->srna);
- }
- 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);
- }
- }
- if (BLT_is_default_context(_tmp)) {
- _tmp = BLT_I18NCONTEXT_DEFAULT_BPYRNA;
- }
- tmp = BLI_strdup(_tmp);
- }
- else if (ELEM(type, BUT_GET_RNAENUM_IDENTIFIER, BUT_GET_RNAENUM_LABEL, BUT_GET_RNAENUM_TIP)) {
- PointerRNA *ptr = NULL;
- PropertyRNA *prop = NULL;
- int value = 0;
-
- /* get the enum property... */
- if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) {
- /* enum property */
- ptr = &but->rnapoin;
- prop = but->rnaprop;
- value = (ELEM(but->type, UI_BTYPE_ROW, UI_BTYPE_TAB)) ? (int)but->hardmax : (int)ui_but_value_get(but);
- }
- else if (but->optype) {
- PointerRNA *opptr = UI_but_operator_ptr_get(but);
- wmOperatorType *ot = but->optype;
-
- /* so the context is passed to itemf functions */
- WM_operator_properties_sanitize(opptr, false);
-
- /* if the default property of the operator is enum and it is set,
- * fetch the tooltip of the selected value so that "Snap" and "Mirror"
- * operator menus in the Anim Editors will show tooltips for the different
- * operations instead of the meaningless generic operator tooltip
- */
- if (ot->prop && RNA_property_type(ot->prop) == PROP_ENUM) {
- if (RNA_struct_contains_property(opptr, ot->prop)) {
- ptr = opptr;
- prop = ot->prop;
- value = RNA_property_enum_get(opptr, ot->prop);
- }
- }
- }
-
- /* get strings from matching enum item */
- if (ptr && prop) {
- if (!item) {
- int i;
-
- RNA_property_enum_items_gettexted(C, ptr, prop, &items, &totitems, &free_items);
- for (i = 0, item = items; i < totitems; i++, item++) {
- if (item->identifier[0] && item->value == value) {
- break;
- }
- }
- }
- if (item && item->identifier) {
- if (type == BUT_GET_RNAENUM_IDENTIFIER) {
- tmp = BLI_strdup(item->identifier);
- }
- else if (type == BUT_GET_RNAENUM_LABEL) {
- tmp = BLI_strdup(item->name);
- }
- else if (item->description && item->description[0]) {
- tmp = BLI_strdup(item->description);
- }
- }
- }
- }
- else if (type == BUT_GET_OP_KEYMAP) {
- if (!ui_block_is_menu(but->block)) {
- char buf[128];
- if (ui_but_event_operator_string(C, but, buf, sizeof(buf))) {
- tmp = BLI_strdup(buf);
- }
- }
- }
- else if (type == BUT_GET_PROP_KEYMAP) {
- /* for properties that are bound to one of the context cycle, etc. keys... */
- char buf[128];
- if (ui_but_event_property_operator_string(C, but, buf, sizeof(buf))) {
- tmp = BLI_strdup(buf);
- }
- }
-
- si->strinfo = tmp;
- }
- va_end(args);
-
- if (free_items && items) {
- MEM_freeN((void *)items);
- }
+ va_list args;
+ uiStringInfo *si;
+
+ const EnumPropertyItem *items = NULL, *item = NULL;
+ int totitems;
+ bool free_items = false;
+
+ va_start(args, but);
+ while ((si = (uiStringInfo *)va_arg(args, void *))) {
+ int type = si->type;
+ char *tmp = NULL;
+
+ if (type == BUT_GET_LABEL) {
+ if (but->str) {
+ const char *str_sep;
+ size_t str_len;
+
+ if ((but->flag & UI_BUT_HAS_SEP_CHAR) && (str_sep = strrchr(but->str, UI_SEP_CHAR))) {
+ str_len = (str_sep - but->str);
+ }
+ else {
+ str_len = strlen(but->str);
+ }
+
+ tmp = BLI_strdupn(but->str, str_len);
+ }
+ else {
+ type = BUT_GET_RNA_LABEL; /* Fail-safe solution... */
+ }
+ }
+ else if (type == BUT_GET_TIP) {
+ if (but->tip_func) {
+ tmp = but->tip_func(C, but->tip_argN, but->tip);
+ }
+ else if (but->tip && but->tip[0]) {
+ tmp = BLI_strdup(but->tip);
+ }
+ else {
+ type = BUT_GET_RNA_TIP; /* Fail-safe solution... */
+ }
+ }
+
+ if (type == BUT_GET_RNAPROP_IDENTIFIER) {
+ if (but->rnaprop) {
+ tmp = BLI_strdup(RNA_property_identifier(but->rnaprop));
+ }
+ }
+ else if (type == BUT_GET_RNASTRUCT_IDENTIFIER) {
+ if (but->rnaprop && but->rnapoin.data) {
+ tmp = BLI_strdup(RNA_struct_identifier(but->rnapoin.type));
+ }
+ else if (but->optype) {
+ tmp = BLI_strdup(but->optype->idname);
+ }
+ else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN)) {
+ MenuType *mt = UI_but_menutype_get(but);
+ if (mt) {
+ tmp = BLI_strdup(mt->idname);
+ }
+ }
+ else if (but->type == UI_BTYPE_POPOVER) {
+ PanelType *pt = UI_but_paneltype_get(but);
+ if (pt) {
+ tmp = BLI_strdup(pt->idname);
+ }
+ }
+ }
+ else if (ELEM(type, BUT_GET_RNA_LABEL, BUT_GET_RNA_TIP)) {
+ if (but->rnaprop) {
+ if (type == BUT_GET_RNA_LABEL) {
+ tmp = BLI_strdup(RNA_property_ui_name(but->rnaprop));
+ }
+ else {
+ const char *t = RNA_property_ui_description(but->rnaprop);
+ if (t && t[0]) {
+ tmp = BLI_strdup(t);
+ }
+ }
+ }
+ else if (but->optype) {
+ if (type == BUT_GET_RNA_LABEL) {
+ tmp = BLI_strdup(RNA_struct_ui_name(but->optype->srna));
+ }
+ else {
+ const char *t = RNA_struct_ui_description(but->optype->srna);
+ if (t && t[0]) {
+ tmp = BLI_strdup(t);
+ }
+ }
+ }
+ else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN)) {
+ MenuType *mt = UI_but_menutype_get(but);
+ if (mt) {
+ /* not all menus are from python */
+ if (mt->ext.srna) {
+ if (type == BUT_GET_RNA_LABEL) {
+ tmp = BLI_strdup(RNA_struct_ui_name(mt->ext.srna));
+ }
+ else {
+ const char *t = RNA_struct_ui_description(mt->ext.srna);
+ if (t && t[0]) {
+ tmp = BLI_strdup(t);
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (type == BUT_GET_RNA_LABEL_CONTEXT) {
+ const char *_tmp = BLT_I18NCONTEXT_DEFAULT;
+ if (but->rnaprop) {
+ _tmp = RNA_property_translation_context(but->rnaprop);
+ }
+ else if (but->optype) {
+ _tmp = RNA_struct_translation_context(but->optype->srna);
+ }
+ 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);
+ }
+ }
+ if (BLT_is_default_context(_tmp)) {
+ _tmp = BLT_I18NCONTEXT_DEFAULT_BPYRNA;
+ }
+ tmp = BLI_strdup(_tmp);
+ }
+ else if (ELEM(type, BUT_GET_RNAENUM_IDENTIFIER, BUT_GET_RNAENUM_LABEL, BUT_GET_RNAENUM_TIP)) {
+ PointerRNA *ptr = NULL;
+ PropertyRNA *prop = NULL;
+ int value = 0;
+
+ /* get the enum property... */
+ if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) {
+ /* enum property */
+ ptr = &but->rnapoin;
+ prop = but->rnaprop;
+ value = (ELEM(but->type, UI_BTYPE_ROW, UI_BTYPE_TAB)) ? (int)but->hardmax :
+ (int)ui_but_value_get(but);
+ }
+ else if (but->optype) {
+ PointerRNA *opptr = UI_but_operator_ptr_get(but);
+ wmOperatorType *ot = but->optype;
+
+ /* so the context is passed to itemf functions */
+ WM_operator_properties_sanitize(opptr, false);
+
+ /* if the default property of the operator is enum and it is set,
+ * fetch the tooltip of the selected value so that "Snap" and "Mirror"
+ * operator menus in the Anim Editors will show tooltips for the different
+ * operations instead of the meaningless generic operator tooltip
+ */
+ if (ot->prop && RNA_property_type(ot->prop) == PROP_ENUM) {
+ if (RNA_struct_contains_property(opptr, ot->prop)) {
+ ptr = opptr;
+ prop = ot->prop;
+ value = RNA_property_enum_get(opptr, ot->prop);
+ }
+ }
+ }
+
+ /* get strings from matching enum item */
+ if (ptr && prop) {
+ if (!item) {
+ int i;
+
+ RNA_property_enum_items_gettexted(C, ptr, prop, &items, &totitems, &free_items);
+ for (i = 0, item = items; i < totitems; i++, item++) {
+ if (item->identifier[0] && item->value == value) {
+ break;
+ }
+ }
+ }
+ if (item && item->identifier) {
+ if (type == BUT_GET_RNAENUM_IDENTIFIER) {
+ tmp = BLI_strdup(item->identifier);
+ }
+ else if (type == BUT_GET_RNAENUM_LABEL) {
+ tmp = BLI_strdup(item->name);
+ }
+ else if (item->description && item->description[0]) {
+ tmp = BLI_strdup(item->description);
+ }
+ }
+ }
+ }
+ else if (type == BUT_GET_OP_KEYMAP) {
+ if (!ui_block_is_menu(but->block)) {
+ char buf[128];
+ if (ui_but_event_operator_string(C, but, buf, sizeof(buf))) {
+ tmp = BLI_strdup(buf);
+ }
+ }
+ }
+ else if (type == BUT_GET_PROP_KEYMAP) {
+ /* for properties that are bound to one of the context cycle, etc. keys... */
+ char buf[128];
+ if (ui_but_event_property_operator_string(C, but, buf, sizeof(buf))) {
+ tmp = BLI_strdup(buf);
+ }
+ }
+
+ si->strinfo = tmp;
+ }
+ va_end(args);
+
+ if (free_items && items) {
+ MEM_freeN((void *)items);
+ }
}
/* Program Init/Exit */
void UI_init(void)
{
- ui_resources_init();
+ ui_resources_init();
}
/* after reading userdef file */
void UI_init_userdef(Main *bmain)
{
- /* fix saved themes */
- init_userdef_do_versions(bmain);
- uiStyleInit();
+ /* fix saved themes */
+ init_userdef_do_versions(bmain);
+ uiStyleInit();
}
void UI_reinit_font(void)
{
- uiStyleInit();
+ uiStyleInit();
}
void UI_exit(void)
{
- ui_resources_free();
- ui_but_clipboard_free();
+ ui_resources_free();
+ ui_but_clipboard_free();
}
diff --git a/source/blender/editors/interface/interface_align.c b/source/blender/editors/interface/interface_align.c
index 9e1563e6511..61f9005ce44 100644
--- a/source/blender/editors/interface/interface_align.c
+++ b/source/blender/editors/interface/interface_align.c
@@ -55,77 +55,87 @@
* but not sure we want to support such exotic cases anyway.
*/
typedef struct ButAlign {
- uiBut *but;
+ uiBut *but;
- /* Neighbor buttons */
- struct ButAlign *neighbors[4];
+ /* Neighbor buttons */
+ struct ButAlign *neighbors[4];
- /* Pointers to coordinates (rctf values) of the button. */
- float *borders[4];
+ /* Pointers to coordinates (rctf values) of the button. */
+ float *borders[4];
- /* Distances to the neighbors. */
- float dists[4];
+ /* Distances to the neighbors. */
+ float dists[4];
- /* Flags, used to mark whether we should 'stitch'
- * the corners of this button with its neighbors' ones. */
- char flags[4];
+ /* Flags, used to mark whether we should 'stitch'
+ * the corners of this button with its neighbors' ones. */
+ char flags[4];
} ButAlign;
/* Side-related enums and flags. */
enum {
- /* Sides (used as indices, order is **crucial**,
- * this allows us to factorize code in a loop over the four sides). */
- LEFT = 0,
- TOP = 1,
- RIGHT = 2,
- DOWN = 3,
- TOTSIDES = 4,
-
- /* Stitch flags, built from sides values. */
- STITCH_LEFT = 1 << LEFT,
- STITCH_TOP = 1 << TOP,
- STITCH_RIGHT = 1 << RIGHT,
- STITCH_DOWN = 1 << DOWN,
+ /* Sides (used as indices, order is **crucial**,
+ * this allows us to factorize code in a loop over the four sides). */
+ LEFT = 0,
+ TOP = 1,
+ RIGHT = 2,
+ DOWN = 3,
+ TOTSIDES = 4,
+
+ /* Stitch flags, built from sides values. */
+ STITCH_LEFT = 1 << LEFT,
+ STITCH_TOP = 1 << TOP,
+ STITCH_RIGHT = 1 << RIGHT,
+ STITCH_DOWN = 1 << DOWN,
};
/* Mapping between 'our' sides and 'public' UI_BUT_ALIGN flags, order must match enum above. */
-#define SIDE_TO_UI_BUT_ALIGN {UI_BUT_ALIGN_LEFT, UI_BUT_ALIGN_TOP, UI_BUT_ALIGN_RIGHT, UI_BUT_ALIGN_DOWN}
+# define SIDE_TO_UI_BUT_ALIGN \
+ { \
+ UI_BUT_ALIGN_LEFT, UI_BUT_ALIGN_TOP, UI_BUT_ALIGN_RIGHT, UI_BUT_ALIGN_DOWN \
+ }
/* Given one side, compute the three other ones */
-#define SIDE1(_s) (((_s) + 1) % TOTSIDES)
-#define OPPOSITE(_s) (((_s) + 2) % TOTSIDES)
-#define SIDE2(_s) (((_s) + 3) % TOTSIDES)
+# define SIDE1(_s) (((_s) + 1) % TOTSIDES)
+# define OPPOSITE(_s) (((_s) + 2) % TOTSIDES)
+# define SIDE2(_s) (((_s) + 3) % TOTSIDES)
/* 0: LEFT/RIGHT sides; 1 = TOP/DOWN sides. */
-#define IS_COLUMN(_s) ((_s) % 2)
+# define IS_COLUMN(_s) ((_s) % 2)
/* Stitch flag from side value. */
-#define STITCH(_s) (1 << (_s))
+# define STITCH(_s) (1 << (_s))
/* Max distance between to buttons for them to be 'mergeable'. */
-#define MAX_DELTA 0.45f * max_ii(UI_UNIT_Y, UI_UNIT_X)
+# define MAX_DELTA 0.45f * max_ii(UI_UNIT_Y, UI_UNIT_X)
bool ui_but_can_align(const uiBut *but)
{
- const bool btype_can_align = !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N,
- UI_BTYPE_TAB, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_SEPR_SPACER);
- return (btype_can_align && (BLI_rctf_size_x(&but->rect) > 0.0f) && (BLI_rctf_size_y(&but->rect) > 0.0f));
+ const bool btype_can_align = !ELEM(but->type,
+ UI_BTYPE_LABEL,
+ UI_BTYPE_CHECKBOX,
+ UI_BTYPE_CHECKBOX_N,
+ UI_BTYPE_TAB,
+ UI_BTYPE_SEPR,
+ UI_BTYPE_SEPR_LINE,
+ UI_BTYPE_SEPR_SPACER);
+ return (btype_can_align && (BLI_rctf_size_x(&but->rect) > 0.0f) &&
+ (BLI_rctf_size_y(&but->rect) > 0.0f));
}
int ui_but_align_opposite_to_area_align_get(const ARegion *ar)
{
- switch (ar->alignment) {
- case RGN_ALIGN_TOP:
- return UI_BUT_ALIGN_DOWN;
- case RGN_ALIGN_BOTTOM:
- return UI_BUT_ALIGN_TOP;
- case RGN_ALIGN_LEFT:
- return UI_BUT_ALIGN_RIGHT;
- case RGN_ALIGN_RIGHT:
- return UI_BUT_ALIGN_LEFT;
- }
-
- return 0;
+ switch (ar->alignment) {
+ case RGN_ALIGN_TOP:
+ return UI_BUT_ALIGN_DOWN;
+ case RGN_ALIGN_BOTTOM:
+ return UI_BUT_ALIGN_TOP;
+ case RGN_ALIGN_LEFT:
+ return UI_BUT_ALIGN_RIGHT;
+ case RGN_ALIGN_RIGHT:
+ return UI_BUT_ALIGN_LEFT;
+ }
+
+ return 0;
}
/**
@@ -136,114 +146,115 @@ int ui_but_align_opposite_to_area_align_get(const ARegion *ar)
*/
static void block_align_proximity_compute(ButAlign *butal, ButAlign *butal_other)
{
- /* That's the biggest gap between two borders to consider them 'alignable'. */
- const float max_delta = MAX_DELTA;
- float delta, delta_side_opp;
- int side, side_opp;
-
- const bool butal_can_align = ui_but_can_align(butal->but);
- const bool butal_other_can_align = ui_but_can_align(butal_other->but);
-
- const bool buts_share[2] = {
- /* Sharing same line? */
- !((*butal->borders[DOWN] >= *butal_other->borders[TOP]) ||
- (*butal->borders[TOP] <= *butal_other->borders[DOWN])),
- /* Sharing same column? */
- !((*butal->borders[LEFT] >= *butal_other->borders[RIGHT]) ||
- (*butal->borders[RIGHT] <= *butal_other->borders[LEFT])),
- };
-
- /* Early out in case buttons share no column or line, or if none can align... */
- if (!(buts_share[0] || buts_share[1]) || !(butal_can_align || butal_other_can_align)) {
- return;
- }
-
- for (side = 0; side < RIGHT; side++) {
- /* We are only interested in buttons which share a same line
- * (LEFT/RIGHT sides) or column (TOP/DOWN sides). */
- if (buts_share[IS_COLUMN(side)]) {
- side_opp = OPPOSITE(side);
-
- /* We check both opposite sides at once, because with very small buttons,
- * delta could be below max_delta for the wrong side
- * (that is, in horizontal case, the total width of two buttons can be below max_delta).
- * We rely on exact zero value here as an 'already processed' flag,
- * so ensure we never actually set a zero value at this stage.
- * FLT_MIN is zero-enough for UI position computing. ;) */
- delta = max_ff(fabsf(*butal->borders[side] - *butal_other->borders[side_opp]), FLT_MIN);
- delta_side_opp = max_ff(fabsf(*butal->borders[side_opp] - *butal_other->borders[side]), FLT_MIN);
- if (delta_side_opp < delta) {
- SWAP(int, side, side_opp);
- delta = delta_side_opp;
- }
-
- if (delta < max_delta) {
- /* We are only interested in neighbors that are
- * at least as close as already found ones. */
- if (delta <= butal->dists[side]) {
- {
- /* We found an as close or closer neighbor.
- * If both buttons are alignable, we set them as each other neighbors.
- * Else, we have an unalignable one, we need to reset the others matching
- * neighbor to NULL if its 'proximity distance'
- * is really lower with current one.
- *
- * NOTE: We cannot only execute that piece of code in case we found a
- * **closer** neighbor, due to the limited way we represent neighbors
- * (buttons only know **one** neighbor on each side, when they can
- * actually have several ones), it would prevent some buttons to be
- * properly 'neighborly-initialized'. */
- if (butal_can_align && butal_other_can_align) {
- butal->neighbors[side] = butal_other;
- butal_other->neighbors[side_opp] = butal;
- }
- else if (butal_can_align && (delta < butal->dists[side])) {
- butal->neighbors[side] = NULL;
- }
- else if (butal_other_can_align && (delta < butal_other->dists[side_opp])) {
- butal_other->neighbors[side_opp] = NULL;
- }
- butal->dists[side] = butal_other->dists[side_opp] = delta;
- }
-
- if (butal_can_align && butal_other_can_align) {
- const int side_s1 = SIDE1(side);
- const int side_s2 = SIDE2(side);
-
- const int stitch = STITCH(side);
- const int stitch_opp = STITCH(side_opp);
-
- if (butal->neighbors[side] == NULL) {
- butal->neighbors[side] = butal_other;
- }
- if (butal_other->neighbors[side_opp] == NULL) {
- butal_other->neighbors[side_opp] = butal;
- }
-
- /* We have a pair of neighbors, we have to check whether we
- * can stitch their matching corners.
- * E.g. if butal_other is on the left of butal (that is, side == LEFT),
- * if both TOP (side_s1) coordinates of buttons are close enough,
- * we can stitch their upper matching corners,
- * and same for DOWN (side_s2) side. */
- delta = fabsf(*butal->borders[side_s1] - *butal_other->borders[side_s1]);
- if (delta < max_delta) {
- butal->flags[side_s1] |= stitch;
- butal_other->flags[side_s1] |= stitch_opp;
- }
- delta = fabsf(*butal->borders[side_s2] - *butal_other->borders[side_s2]);
- if (delta < max_delta) {
- butal->flags[side_s2] |= stitch;
- butal_other->flags[side_s2] |= stitch_opp;
- }
- }
- }
- /* We assume two buttons can only share one side at most - for until
- * we have sperical UI... */
- return;
- }
- }
- }
+ /* That's the biggest gap between two borders to consider them 'alignable'. */
+ const float max_delta = MAX_DELTA;
+ float delta, delta_side_opp;
+ int side, side_opp;
+
+ const bool butal_can_align = ui_but_can_align(butal->but);
+ const bool butal_other_can_align = ui_but_can_align(butal_other->but);
+
+ const bool buts_share[2] = {
+ /* Sharing same line? */
+ !((*butal->borders[DOWN] >= *butal_other->borders[TOP]) ||
+ (*butal->borders[TOP] <= *butal_other->borders[DOWN])),
+ /* Sharing same column? */
+ !((*butal->borders[LEFT] >= *butal_other->borders[RIGHT]) ||
+ (*butal->borders[RIGHT] <= *butal_other->borders[LEFT])),
+ };
+
+ /* Early out in case buttons share no column or line, or if none can align... */
+ if (!(buts_share[0] || buts_share[1]) || !(butal_can_align || butal_other_can_align)) {
+ return;
+ }
+
+ for (side = 0; side < RIGHT; side++) {
+ /* We are only interested in buttons which share a same line
+ * (LEFT/RIGHT sides) or column (TOP/DOWN sides). */
+ if (buts_share[IS_COLUMN(side)]) {
+ side_opp = OPPOSITE(side);
+
+ /* We check both opposite sides at once, because with very small buttons,
+ * delta could be below max_delta for the wrong side
+ * (that is, in horizontal case, the total width of two buttons can be below max_delta).
+ * We rely on exact zero value here as an 'already processed' flag,
+ * so ensure we never actually set a zero value at this stage.
+ * FLT_MIN is zero-enough for UI position computing. ;) */
+ delta = max_ff(fabsf(*butal->borders[side] - *butal_other->borders[side_opp]), FLT_MIN);
+ delta_side_opp = max_ff(fabsf(*butal->borders[side_opp] - *butal_other->borders[side]),
+ FLT_MIN);
+ if (delta_side_opp < delta) {
+ SWAP(int, side, side_opp);
+ delta = delta_side_opp;
+ }
+
+ if (delta < max_delta) {
+ /* We are only interested in neighbors that are
+ * at least as close as already found ones. */
+ if (delta <= butal->dists[side]) {
+ {
+ /* We found an as close or closer neighbor.
+ * If both buttons are alignable, we set them as each other neighbors.
+ * Else, we have an unalignable one, we need to reset the others matching
+ * neighbor to NULL if its 'proximity distance'
+ * is really lower with current one.
+ *
+ * NOTE: We cannot only execute that piece of code in case we found a
+ * **closer** neighbor, due to the limited way we represent neighbors
+ * (buttons only know **one** neighbor on each side, when they can
+ * actually have several ones), it would prevent some buttons to be
+ * properly 'neighborly-initialized'. */
+ if (butal_can_align && butal_other_can_align) {
+ butal->neighbors[side] = butal_other;
+ butal_other->neighbors[side_opp] = butal;
+ }
+ else if (butal_can_align && (delta < butal->dists[side])) {
+ butal->neighbors[side] = NULL;
+ }
+ else if (butal_other_can_align && (delta < butal_other->dists[side_opp])) {
+ butal_other->neighbors[side_opp] = NULL;
+ }
+ butal->dists[side] = butal_other->dists[side_opp] = delta;
+ }
+
+ if (butal_can_align && butal_other_can_align) {
+ const int side_s1 = SIDE1(side);
+ const int side_s2 = SIDE2(side);
+
+ const int stitch = STITCH(side);
+ const int stitch_opp = STITCH(side_opp);
+
+ if (butal->neighbors[side] == NULL) {
+ butal->neighbors[side] = butal_other;
+ }
+ if (butal_other->neighbors[side_opp] == NULL) {
+ butal_other->neighbors[side_opp] = butal;
+ }
+
+ /* We have a pair of neighbors, we have to check whether we
+ * can stitch their matching corners.
+ * E.g. if butal_other is on the left of butal (that is, side == LEFT),
+ * if both TOP (side_s1) coordinates of buttons are close enough,
+ * we can stitch their upper matching corners,
+ * and same for DOWN (side_s2) side. */
+ delta = fabsf(*butal->borders[side_s1] - *butal_other->borders[side_s1]);
+ if (delta < max_delta) {
+ butal->flags[side_s1] |= stitch;
+ butal_other->flags[side_s1] |= stitch_opp;
+ }
+ delta = fabsf(*butal->borders[side_s2] - *butal_other->borders[side_s2]);
+ if (delta < max_delta) {
+ butal->flags[side_s2] |= stitch;
+ butal_other->flags[side_s2] |= stitch_opp;
+ }
+ }
+ }
+ /* We assume two buttons can only share one side at most - for until
+ * we have sperical UI... */
+ return;
+ }
+ }
+ }
}
/**
@@ -265,47 +276,49 @@ static void block_align_proximity_compute(ButAlign *butal, ButAlign *butal_other
* \note To avoid doing this twice, some stitching flags are cleared to break the 'stitching connection'
* between neighbors.
*/
-static void block_align_stitch_neighbors(
- ButAlign *butal,
- const int side, const int side_opp, const int side_s1, const int side_s2,
- const int align, const int align_opp, const float co)
+static void block_align_stitch_neighbors(ButAlign *butal,
+ const int side,
+ const int side_opp,
+ const int side_s1,
+ const int side_s2,
+ const int align,
+ const int align_opp,
+ const float co)
{
- ButAlign *butal_neighbor;
-
- const int stitch_s1 = STITCH(side_s1);
- const int stitch_s2 = STITCH(side_s2);
-
- /* We have to check stitching flags on both sides of the stitching, since we only clear one of them flags to break
- * any future loop on same 'columns/side' case.
- * Also, if butal is spanning over several rows or columns of neighbors, it may have both of its stitching flags
- * set, but would not be the case of its immediate neighbor! */
- while ((butal->flags[side] & stitch_s1) &&
- (butal = butal->neighbors[side_s1]) &&
- (butal->flags[side] & stitch_s2))
- {
- butal_neighbor = butal->neighbors[side];
-
- /* If we actually do have a neighbor, we directly set its values accordingly, and clear its matching 'dist'
- * to prevent it being set again later... */
- if (butal_neighbor) {
- butal->but->drawflag |= align;
- butal_neighbor->but->drawflag |= align_opp;
- *butal_neighbor->borders[side_opp] = co;
- butal_neighbor->dists[side_opp] = 0.0f;
- }
- /* See definition of UI_BUT_ALIGN_STITCH_LEFT/TOP for reason of this... */
- else if (side == LEFT) {
- butal->but->drawflag |= UI_BUT_ALIGN_STITCH_LEFT;
- }
- else if (side == TOP) {
- butal->but->drawflag |= UI_BUT_ALIGN_STITCH_TOP;
- }
- *butal->borders[side] = co;
- butal->dists[side] = 0.0f;
- /* Clearing one of the 'flags pair' here is enough to prevent this loop running on
- * the same column, side and direction again. */
- butal->flags[side] &= ~stitch_s2;
- }
+ ButAlign *butal_neighbor;
+
+ const int stitch_s1 = STITCH(side_s1);
+ const int stitch_s2 = STITCH(side_s2);
+
+ /* We have to check stitching flags on both sides of the stitching, since we only clear one of them flags to break
+ * any future loop on same 'columns/side' case.
+ * Also, if butal is spanning over several rows or columns of neighbors, it may have both of its stitching flags
+ * set, but would not be the case of its immediate neighbor! */
+ while ((butal->flags[side] & stitch_s1) && (butal = butal->neighbors[side_s1]) &&
+ (butal->flags[side] & stitch_s2)) {
+ butal_neighbor = butal->neighbors[side];
+
+ /* If we actually do have a neighbor, we directly set its values accordingly, and clear its matching 'dist'
+ * to prevent it being set again later... */
+ if (butal_neighbor) {
+ butal->but->drawflag |= align;
+ butal_neighbor->but->drawflag |= align_opp;
+ *butal_neighbor->borders[side_opp] = co;
+ butal_neighbor->dists[side_opp] = 0.0f;
+ }
+ /* See definition of UI_BUT_ALIGN_STITCH_LEFT/TOP for reason of this... */
+ else if (side == LEFT) {
+ butal->but->drawflag |= UI_BUT_ALIGN_STITCH_LEFT;
+ }
+ else if (side == TOP) {
+ butal->but->drawflag |= UI_BUT_ALIGN_STITCH_TOP;
+ }
+ *butal->borders[side] = co;
+ butal->dists[side] = 0.0f;
+ /* Clearing one of the 'flags pair' here is enough to prevent this loop running on
+ * the same column, side and direction again. */
+ butal->flags[side] &= ~stitch_s2;
+ }
}
/**
@@ -316,61 +329,61 @@ static void block_align_stitch_neighbors(
*/
static int ui_block_align_butal_cmp(const void *a, const void *b)
{
- const ButAlign *butal = a;
- const ButAlign *butal_other = b;
-
- /* Sort by align group. */
- if (butal->but->alignnr != butal_other->but->alignnr) {
- return butal->but->alignnr - butal_other->but->alignnr;
- }
-
- /* Sort vertically.
- * Note that Y of buttons is decreasing (first buttons have higher Y value than later ones). */
- if (*butal->borders[TOP] != *butal_other->borders[TOP]) {
- return (*butal_other->borders[TOP] > *butal->borders[TOP]) ? 1 : -1;
- }
-
- /* Sort horizontally. */
- if (*butal->borders[LEFT] != *butal_other->borders[LEFT]) {
- return (*butal->borders[LEFT] > *butal_other->borders[LEFT]) ? 1 : -1;
- }
-
- /* XXX We cannot actually assert here, since in some very compressed space cases,
- * stupid UI code produces widgets which have the same TOP and LEFT positions...
- * We do not care really,
- * because this happens when UI is way too small to be usable anyway. */
- /* BLI_assert(0); */
- return 0;
+ const ButAlign *butal = a;
+ const ButAlign *butal_other = b;
+
+ /* Sort by align group. */
+ if (butal->but->alignnr != butal_other->but->alignnr) {
+ return butal->but->alignnr - butal_other->but->alignnr;
+ }
+
+ /* Sort vertically.
+ * Note that Y of buttons is decreasing (first buttons have higher Y value than later ones). */
+ if (*butal->borders[TOP] != *butal_other->borders[TOP]) {
+ return (*butal_other->borders[TOP] > *butal->borders[TOP]) ? 1 : -1;
+ }
+
+ /* Sort horizontally. */
+ if (*butal->borders[LEFT] != *butal_other->borders[LEFT]) {
+ return (*butal->borders[LEFT] > *butal_other->borders[LEFT]) ? 1 : -1;
+ }
+
+ /* XXX We cannot actually assert here, since in some very compressed space cases,
+ * stupid UI code produces widgets which have the same TOP and LEFT positions...
+ * We do not care really,
+ * because this happens when UI is way too small to be usable anyway. */
+ /* BLI_assert(0); */
+ return 0;
}
static void ui_block_align_but_to_region(uiBut *but, const ARegion *region)
{
- rctf *rect = &but->rect;
- const float but_width = BLI_rctf_size_x(rect);
- const float but_height = BLI_rctf_size_y(rect);
- const float outline_px = U.pixelsize; /* This may have to be made more variable. */
-
- switch (but->drawflag & UI_BUT_ALIGN) {
- case UI_BUT_ALIGN_TOP:
- rect->ymax = region->winy + outline_px;
- rect->ymin = but->rect.ymax - but_height;
- break;
- case UI_BUT_ALIGN_DOWN:
- rect->ymin = -outline_px;
- rect->ymax = rect->ymin + but_height;
- break;
- case UI_BUT_ALIGN_LEFT:
- rect->xmin = -outline_px;
- rect->xmax = rect->xmin + but_width;
- break;
- case UI_BUT_ALIGN_RIGHT:
- rect->xmax = region->winx + outline_px;
- rect->xmin = rect->xmax - but_width;
- break;
- default:
- BLI_assert(0);
- break;
- }
+ rctf *rect = &but->rect;
+ const float but_width = BLI_rctf_size_x(rect);
+ const float but_height = BLI_rctf_size_y(rect);
+ const float outline_px = U.pixelsize; /* This may have to be made more variable. */
+
+ switch (but->drawflag & UI_BUT_ALIGN) {
+ case UI_BUT_ALIGN_TOP:
+ rect->ymax = region->winy + outline_px;
+ rect->ymin = but->rect.ymax - but_height;
+ break;
+ case UI_BUT_ALIGN_DOWN:
+ rect->ymin = -outline_px;
+ rect->ymax = rect->ymin + but_height;
+ break;
+ case UI_BUT_ALIGN_LEFT:
+ rect->xmin = -outline_px;
+ rect->xmax = rect->xmin + but_width;
+ break;
+ case UI_BUT_ALIGN_RIGHT:
+ rect->xmax = region->winx + outline_px;
+ rect->xmin = rect->xmax - but_width;
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
}
/**
@@ -381,350 +394,355 @@ static void ui_block_align_but_to_region(uiBut *but, const ARegion *region)
*/
void ui_block_align_calc(uiBlock *block, const ARegion *region)
{
- uiBut *but;
- int num_buttons = 0;
-
- const int sides_to_ui_but_align_flags[4] = SIDE_TO_UI_BUT_ALIGN;
-
- ButAlign *butal_array;
- ButAlign *butal, *butal_other;
- int side;
- int i, j;
-
- /* First loop: we count number of buttons belonging to an align group, and clear their align flag.
- * Tabs get some special treatment here, they get aligned to region border. */
- for (but = block->buttons.first; but; but = but->next) {
- /* special case: tabs need to be aligned to a region border, drawflag tells which one */
- if (but->type == UI_BTYPE_TAB) {
- ui_block_align_but_to_region(but, region);
- }
- else {
- /* Clear old align flags. */
- but->drawflag &= ~UI_BUT_ALIGN_ALL;
- }
-
- if (but->alignnr != 0) {
- num_buttons++;
- }
- }
-
- if (num_buttons < 2) {
- /* No need to go further if we have nothing to align... */
- return;
- }
-
- butal_array = alloca(sizeof(*butal_array) * (size_t)num_buttons);
- memset(butal_array, 0, sizeof(*butal_array) * (size_t)num_buttons);
-
- /* Second loop: we initialize our ButAlign data for each button. */
- for (but = block->buttons.first, butal = butal_array; but; but = but->next) {
- if (but->alignnr != 0) {
- butal->but = but;
- butal->borders[LEFT] = &but->rect.xmin;
- butal->borders[RIGHT] = &but->rect.xmax;
- butal->borders[DOWN] = &but->rect.ymin;
- butal->borders[TOP] = &but->rect.ymax;
- copy_v4_fl(butal->dists, FLT_MAX);
- butal++;
- }
- }
-
- /* This will give us ButAlign items regrouped by align group, vertical and horizontal location.
- * Note that, given how buttons are defined in UI code,
- * butal_array shall already be "nearly sorted"... */
- qsort(butal_array, (size_t)num_buttons, sizeof(*butal_array), ui_block_align_butal_cmp);
-
- /* Third loop: for each pair of buttons in the same align group,
- * we compute their potential proximity. Note that each pair is checked only once, and that we
- * break early in case we know all remaining pairs will always be too far away. */
- for (i = 0, butal = butal_array; i < num_buttons; i++, butal++) {
- const short alignnr = butal->but->alignnr;
-
- for (j = i + 1, butal_other = &butal_array[i + 1]; j < num_buttons; j++, butal_other++) {
- const float max_delta = MAX_DELTA;
-
- /* Since they are sorted, buttons after current butal can only be of same or higher
- * group, and once they are not of same group, we know we can break this sub-loop and
- * start checking with next butal. */
- if (butal_other->but->alignnr != alignnr) {
- break;
- }
-
- /* Since they are sorted vertically first, buttons after current butal can only be at
- * same or lower height, and once they are lower than a given threshold, we know we can
- * break this sub-loop and start checking with next butal. */
- if ((*butal->borders[DOWN] - *butal_other->borders[TOP]) > max_delta) {
- break;
- }
-
- block_align_proximity_compute(butal, butal_other);
- }
- }
-
- /* Fourth loop: we have all our 'aligned' buttons as a 'map' in butal_array. We need to:
- * - update their relevant coordinates to stitch them.
- * - assign them valid flags.
- */
- for (i = 0; i < num_buttons; i++) {
- butal = &butal_array[i];
-
- for (side = 0; side < TOTSIDES; side++) {
- butal_other = butal->neighbors[side];
-
- if (butal_other) {
- const int side_opp = OPPOSITE(side);
- const int side_s1 = SIDE1(side);
- const int side_s2 = SIDE2(side);
-
- const int align = sides_to_ui_but_align_flags[side];
- const int align_opp = sides_to_ui_but_align_flags[side_opp];
-
- float co;
-
- butal->but->drawflag |= align;
- butal_other->but->drawflag |= align_opp;
- if (butal->dists[side]) {
- float *delta = &butal->dists[side];
-
- if (*butal->borders[side] < *butal_other->borders[side_opp]) {
- *delta *= 0.5f;
- }
- else {
- *delta *= -0.5f;
- }
- co = (*butal->borders[side] += *delta);
-
- if (butal_other->dists[side_opp]) {
- BLI_assert(butal_other->dists[side_opp] * 0.5f == fabsf(*delta));
- *butal_other->borders[side_opp] = co;
- butal_other->dists[side_opp] = 0.0f;
- }
- *delta = 0.0f;
- }
- else {
- co = *butal->borders[side];
- }
-
- block_align_stitch_neighbors(butal, side, side_opp, side_s1, side_s2, align, align_opp, co);
- block_align_stitch_neighbors(butal, side, side_opp, side_s2, side_s1, align, align_opp, co);
- }
- }
- }
+ uiBut *but;
+ int num_buttons = 0;
+
+ const int sides_to_ui_but_align_flags[4] = SIDE_TO_UI_BUT_ALIGN;
+
+ ButAlign *butal_array;
+ ButAlign *butal, *butal_other;
+ int side;
+ int i, j;
+
+ /* First loop: we count number of buttons belonging to an align group, and clear their align flag.
+ * Tabs get some special treatment here, they get aligned to region border. */
+ for (but = block->buttons.first; but; but = but->next) {
+ /* special case: tabs need to be aligned to a region border, drawflag tells which one */
+ if (but->type == UI_BTYPE_TAB) {
+ ui_block_align_but_to_region(but, region);
+ }
+ else {
+ /* Clear old align flags. */
+ but->drawflag &= ~UI_BUT_ALIGN_ALL;
+ }
+
+ if (but->alignnr != 0) {
+ num_buttons++;
+ }
+ }
+
+ if (num_buttons < 2) {
+ /* No need to go further if we have nothing to align... */
+ return;
+ }
+
+ butal_array = alloca(sizeof(*butal_array) * (size_t)num_buttons);
+ memset(butal_array, 0, sizeof(*butal_array) * (size_t)num_buttons);
+
+ /* Second loop: we initialize our ButAlign data for each button. */
+ for (but = block->buttons.first, butal = butal_array; but; but = but->next) {
+ if (but->alignnr != 0) {
+ butal->but = but;
+ butal->borders[LEFT] = &but->rect.xmin;
+ butal->borders[RIGHT] = &but->rect.xmax;
+ butal->borders[DOWN] = &but->rect.ymin;
+ butal->borders[TOP] = &but->rect.ymax;
+ copy_v4_fl(butal->dists, FLT_MAX);
+ butal++;
+ }
+ }
+
+ /* This will give us ButAlign items regrouped by align group, vertical and horizontal location.
+ * Note that, given how buttons are defined in UI code,
+ * butal_array shall already be "nearly sorted"... */
+ qsort(butal_array, (size_t)num_buttons, sizeof(*butal_array), ui_block_align_butal_cmp);
+
+ /* Third loop: for each pair of buttons in the same align group,
+ * we compute their potential proximity. Note that each pair is checked only once, and that we
+ * break early in case we know all remaining pairs will always be too far away. */
+ for (i = 0, butal = butal_array; i < num_buttons; i++, butal++) {
+ const short alignnr = butal->but->alignnr;
+
+ for (j = i + 1, butal_other = &butal_array[i + 1]; j < num_buttons; j++, butal_other++) {
+ const float max_delta = MAX_DELTA;
+
+ /* Since they are sorted, buttons after current butal can only be of same or higher
+ * group, and once they are not of same group, we know we can break this sub-loop and
+ * start checking with next butal. */
+ if (butal_other->but->alignnr != alignnr) {
+ break;
+ }
+
+ /* Since they are sorted vertically first, buttons after current butal can only be at
+ * same or lower height, and once they are lower than a given threshold, we know we can
+ * break this sub-loop and start checking with next butal. */
+ if ((*butal->borders[DOWN] - *butal_other->borders[TOP]) > max_delta) {
+ break;
+ }
+
+ block_align_proximity_compute(butal, butal_other);
+ }
+ }
+
+ /* Fourth loop: we have all our 'aligned' buttons as a 'map' in butal_array. We need to:
+ * - update their relevant coordinates to stitch them.
+ * - assign them valid flags.
+ */
+ for (i = 0; i < num_buttons; i++) {
+ butal = &butal_array[i];
+
+ for (side = 0; side < TOTSIDES; side++) {
+ butal_other = butal->neighbors[side];
+
+ if (butal_other) {
+ const int side_opp = OPPOSITE(side);
+ const int side_s1 = SIDE1(side);
+ const int side_s2 = SIDE2(side);
+
+ const int align = sides_to_ui_but_align_flags[side];
+ const int align_opp = sides_to_ui_but_align_flags[side_opp];
+
+ float co;
+
+ butal->but->drawflag |= align;
+ butal_other->but->drawflag |= align_opp;
+ if (butal->dists[side]) {
+ float *delta = &butal->dists[side];
+
+ if (*butal->borders[side] < *butal_other->borders[side_opp]) {
+ *delta *= 0.5f;
+ }
+ else {
+ *delta *= -0.5f;
+ }
+ co = (*butal->borders[side] += *delta);
+
+ if (butal_other->dists[side_opp]) {
+ BLI_assert(butal_other->dists[side_opp] * 0.5f == fabsf(*delta));
+ *butal_other->borders[side_opp] = co;
+ butal_other->dists[side_opp] = 0.0f;
+ }
+ *delta = 0.0f;
+ }
+ else {
+ co = *butal->borders[side];
+ }
+
+ block_align_stitch_neighbors(
+ butal, side, side_opp, side_s1, side_s2, align, align_opp, co);
+ block_align_stitch_neighbors(
+ butal, side, side_opp, side_s2, side_s1, align, align_opp, co);
+ }
+ }
+ }
}
-#undef SIDE_TO_UI_BUT_ALIGN
-#undef SIDE1
-#undef OPPOSITE
-#undef SIDE2
-#undef IS_COLUMN
-#undef STITCH
-#undef MAX_DELTA
+# undef SIDE_TO_UI_BUT_ALIGN
+# undef SIDE1
+# undef OPPOSITE
+# undef SIDE2
+# undef IS_COLUMN
+# undef STITCH
+# undef MAX_DELTA
#else
bool ui_but_can_align(uiBut *but)
{
- return !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N,
- UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_SEPR_SPACER);
+ return !ELEM(but->type,
+ UI_BTYPE_LABEL,
+ UI_BTYPE_CHECKBOX,
+ UI_BTYPE_CHECKBOX_N,
+ UI_BTYPE_SEPR,
+ UI_BTYPE_SEPR_LINE,
+ UI_BTYPE_SEPR_SPACER);
}
static bool buts_are_horiz(uiBut *but1, uiBut *but2)
{
- float dx, dy;
+ float dx, dy;
- /* simple case which can fail if buttons shift apart
- * with proportional layouts, see: [#38602] */
- if ((but1->rect.ymin == but2->rect.ymin) &&
- (but1->rect.xmin != but2->rect.xmin))
- {
- return true;
- }
+ /* simple case which can fail if buttons shift apart
+ * with proportional layouts, see: [#38602] */
+ if ((but1->rect.ymin == but2->rect.ymin) && (but1->rect.xmin != but2->rect.xmin)) {
+ return true;
+ }
- dx = fabsf(but1->rect.xmax - but2->rect.xmin);
- dy = fabsf(but1->rect.ymin - but2->rect.ymax);
+ dx = fabsf(but1->rect.xmax - but2->rect.xmin);
+ dy = fabsf(but1->rect.ymin - but2->rect.ymax);
- return (dx <= dy);
+ return (dx <= dy);
}
static void ui_block_align_calc_but(uiBut *first, short nr)
{
- uiBut *prev, *but = NULL, *next;
- int flag = 0, cols = 0, rows = 0;
-
- /* auto align */
-
- for (but = first; but && but->alignnr == nr; but = but->next) {
- if (but->next && but->next->alignnr == nr) {
- if (buts_are_horiz(but, but->next)) {
- cols++;
- }
- else {
- rows++;
- }
- }
- }
-
- /* rows == 0: 1 row, cols == 0: 1 column */
-
- /* note; how it uses 'flag' in loop below (either set it, or OR it) is confusing */
- for (but = first, prev = NULL; but && but->alignnr == nr; prev = but, but = but->next) {
- next = but->next;
- if (next && next->alignnr != nr) {
- next = NULL;
- }
-
- /* clear old flag */
- but->drawflag &= ~UI_BUT_ALIGN;
-
- if (flag == 0) { /* first case */
- if (next) {
- if (buts_are_horiz(but, next)) {
- if (rows == 0) {
- flag = UI_BUT_ALIGN_RIGHT;
- }
- else {
- flag = UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_RIGHT;
- }
- }
- else {
- flag = UI_BUT_ALIGN_DOWN;
- }
- }
- }
- else if (next == NULL) { /* last case */
- if (prev) {
- if (buts_are_horiz(prev, but)) {
- if (rows == 0) {
- flag = UI_BUT_ALIGN_LEFT;
- }
- else {
- flag = UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_LEFT;
- }
- }
- else {
- flag = UI_BUT_ALIGN_TOP;
- }
- }
- }
- else if (buts_are_horiz(but, next)) {
- /* check if this is already second row */
- if (prev && buts_are_horiz(prev, but) == 0) {
- flag &= ~UI_BUT_ALIGN_LEFT;
- flag |= UI_BUT_ALIGN_TOP;
- /* exception case: bottom row */
- if (rows > 0) {
- uiBut *bt = but;
- while (bt && bt->alignnr == nr) {
- if (bt->next && bt->next->alignnr == nr && buts_are_horiz(bt, bt->next) == 0) {
- break;
- }
- bt = bt->next;
- }
- if (bt == NULL || bt->alignnr != nr) {
- flag = UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_RIGHT;
- }
- }
- }
- else {
- flag |= UI_BUT_ALIGN_LEFT;
- }
- }
- else {
- if (cols == 0) {
- flag |= UI_BUT_ALIGN_TOP;
- }
- else { /* next button switches to new row */
-
- if (prev && buts_are_horiz(prev, but)) {
- flag |= UI_BUT_ALIGN_LEFT;
- }
- else {
- flag &= ~UI_BUT_ALIGN_LEFT;
- flag |= UI_BUT_ALIGN_TOP;
- }
-
- if ((flag & UI_BUT_ALIGN_TOP) == 0) { /* still top row */
- if (prev) {
- if (next && buts_are_horiz(but, next)) {
- flag = UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_LEFT | UI_BUT_ALIGN_RIGHT;
- }
- else {
- /* last button in top row */
- flag = UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_LEFT;
- }
- }
- else {
- flag |= UI_BUT_ALIGN_DOWN;
- }
- }
- else {
- flag |= UI_BUT_ALIGN_TOP;
- }
- }
- }
-
- but->drawflag |= flag;
-
- /* merge coordinates */
- if (prev) {
- /* simple cases */
- if (rows == 0) {
- but->rect.xmin = (prev->rect.xmax + but->rect.xmin) / 2.0f;
- prev->rect.xmax = but->rect.xmin;
- }
- else if (cols == 0) {
- but->rect.ymax = (prev->rect.ymin + but->rect.ymax) / 2.0f;
- prev->rect.ymin = but->rect.ymax;
- }
- else {
- if (buts_are_horiz(prev, but)) {
- but->rect.xmin = (prev->rect.xmax + but->rect.xmin) / 2.0f;
- prev->rect.xmax = but->rect.xmin;
- /* copy height too */
- but->rect.ymax = prev->rect.ymax;
- }
- else if (prev->prev && buts_are_horiz(prev->prev, prev) == 0) {
- /* the previous button is a single one in its row */
- but->rect.ymax = (prev->rect.ymin + but->rect.ymax) / 2.0f;
- prev->rect.ymin = but->rect.ymax;
-
- but->rect.xmin = prev->rect.xmin;
- if (next && buts_are_horiz(but, next) == 0) {
- but->rect.xmax = prev->rect.xmax;
- }
- }
- else {
- /* the previous button is not a single one in its row */
- but->rect.ymax = prev->rect.ymin;
- }
- }
- }
- }
+ uiBut *prev, *but = NULL, *next;
+ int flag = 0, cols = 0, rows = 0;
+
+ /* auto align */
+
+ for (but = first; but && but->alignnr == nr; but = but->next) {
+ if (but->next && but->next->alignnr == nr) {
+ if (buts_are_horiz(but, but->next)) {
+ cols++;
+ }
+ else {
+ rows++;
+ }
+ }
+ }
+
+ /* rows == 0: 1 row, cols == 0: 1 column */
+
+ /* note; how it uses 'flag' in loop below (either set it, or OR it) is confusing */
+ for (but = first, prev = NULL; but && but->alignnr == nr; prev = but, but = but->next) {
+ next = but->next;
+ if (next && next->alignnr != nr) {
+ next = NULL;
+ }
+
+ /* clear old flag */
+ but->drawflag &= ~UI_BUT_ALIGN;
+
+ if (flag == 0) { /* first case */
+ if (next) {
+ if (buts_are_horiz(but, next)) {
+ if (rows == 0) {
+ flag = UI_BUT_ALIGN_RIGHT;
+ }
+ else {
+ flag = UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_RIGHT;
+ }
+ }
+ else {
+ flag = UI_BUT_ALIGN_DOWN;
+ }
+ }
+ }
+ else if (next == NULL) { /* last case */
+ if (prev) {
+ if (buts_are_horiz(prev, but)) {
+ if (rows == 0) {
+ flag = UI_BUT_ALIGN_LEFT;
+ }
+ else {
+ flag = UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_LEFT;
+ }
+ }
+ else {
+ flag = UI_BUT_ALIGN_TOP;
+ }
+ }
+ }
+ else if (buts_are_horiz(but, next)) {
+ /* check if this is already second row */
+ if (prev && buts_are_horiz(prev, but) == 0) {
+ flag &= ~UI_BUT_ALIGN_LEFT;
+ flag |= UI_BUT_ALIGN_TOP;
+ /* exception case: bottom row */
+ if (rows > 0) {
+ uiBut *bt = but;
+ while (bt && bt->alignnr == nr) {
+ if (bt->next && bt->next->alignnr == nr && buts_are_horiz(bt, bt->next) == 0) {
+ break;
+ }
+ bt = bt->next;
+ }
+ if (bt == NULL || bt->alignnr != nr) {
+ flag = UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_RIGHT;
+ }
+ }
+ }
+ else {
+ flag |= UI_BUT_ALIGN_LEFT;
+ }
+ }
+ else {
+ if (cols == 0) {
+ flag |= UI_BUT_ALIGN_TOP;
+ }
+ else { /* next button switches to new row */
+
+ if (prev && buts_are_horiz(prev, but)) {
+ flag |= UI_BUT_ALIGN_LEFT;
+ }
+ else {
+ flag &= ~UI_BUT_ALIGN_LEFT;
+ flag |= UI_BUT_ALIGN_TOP;
+ }
+
+ if ((flag & UI_BUT_ALIGN_TOP) == 0) { /* still top row */
+ if (prev) {
+ if (next && buts_are_horiz(but, next)) {
+ flag = UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_LEFT | UI_BUT_ALIGN_RIGHT;
+ }
+ else {
+ /* last button in top row */
+ flag = UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_LEFT;
+ }
+ }
+ else {
+ flag |= UI_BUT_ALIGN_DOWN;
+ }
+ }
+ else {
+ flag |= UI_BUT_ALIGN_TOP;
+ }
+ }
+ }
+
+ but->drawflag |= flag;
+
+ /* merge coordinates */
+ if (prev) {
+ /* simple cases */
+ if (rows == 0) {
+ but->rect.xmin = (prev->rect.xmax + but->rect.xmin) / 2.0f;
+ prev->rect.xmax = but->rect.xmin;
+ }
+ else if (cols == 0) {
+ but->rect.ymax = (prev->rect.ymin + but->rect.ymax) / 2.0f;
+ prev->rect.ymin = but->rect.ymax;
+ }
+ else {
+ if (buts_are_horiz(prev, but)) {
+ but->rect.xmin = (prev->rect.xmax + but->rect.xmin) / 2.0f;
+ prev->rect.xmax = but->rect.xmin;
+ /* copy height too */
+ but->rect.ymax = prev->rect.ymax;
+ }
+ else if (prev->prev && buts_are_horiz(prev->prev, prev) == 0) {
+ /* the previous button is a single one in its row */
+ but->rect.ymax = (prev->rect.ymin + but->rect.ymax) / 2.0f;
+ prev->rect.ymin = but->rect.ymax;
+
+ but->rect.xmin = prev->rect.xmin;
+ if (next && buts_are_horiz(but, next) == 0) {
+ but->rect.xmax = prev->rect.xmax;
+ }
+ }
+ else {
+ /* the previous button is not a single one in its row */
+ but->rect.ymax = prev->rect.ymin;
+ }
+ }
+ }
+ }
}
void ui_block_align_calc(uiBlock *block)
{
- uiBut *but;
- short nr;
-
- /* align buttons with same align nr */
- for (but = block->buttons.first; but; ) {
- if (but->alignnr) {
- nr = but->alignnr;
- ui_block_align_calc_but(but, nr);
-
- /* skip with same number */
- for (; but && but->alignnr == nr; but = but->next) {
- /* pass */
- }
-
- if (!but) {
- break;
- }
- }
- else {
- but = but->next;
- }
- }
+ uiBut *but;
+ short nr;
+
+ /* align buttons with same align nr */
+ for (but = block->buttons.first; but;) {
+ if (but->alignnr) {
+ nr = but->alignnr;
+ ui_block_align_calc_but(but, nr);
+
+ /* skip with same number */
+ for (; but && but->alignnr == nr; but = but->next) {
+ /* pass */
+ }
+
+ if (!but) {
+ break;
+ }
+ }
+ else {
+ but = but->next;
+ }
+ }
}
#endif
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index a4476b4d2f1..b9de504f3b2 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -52,83 +52,85 @@
#include "interface_intern.h"
-static FCurve *ui_but_get_fcurve(uiBut *but, AnimData **adt, bAction **action, bool *r_driven, bool *r_special)
+static FCurve *ui_but_get_fcurve(
+ uiBut *but, AnimData **adt, bAction **action, bool *r_driven, bool *r_special)
{
- /* for entire array buttons we check the first component, it's not perfect
- * but works well enough in typical cases */
- int rnaindex = (but->rnaindex == -1) ? 0 : but->rnaindex;
+ /* for entire array buttons we check the first component, it's not perfect
+ * but works well enough in typical cases */
+ int rnaindex = (but->rnaindex == -1) ? 0 : but->rnaindex;
- return rna_get_fcurve_context_ui(but->block->evil_C, &but->rnapoin, but->rnaprop, rnaindex, adt, action, r_driven, r_special);
+ return rna_get_fcurve_context_ui(
+ but->block->evil_C, &but->rnapoin, but->rnaprop, rnaindex, adt, action, r_driven, r_special);
}
void ui_but_anim_flag(uiBut *but, float cfra)
{
- AnimData *adt;
- bAction *act;
- FCurve *fcu;
- bool driven;
- bool special;
-
- but->flag &= ~(UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN);
- but->drawflag &= ~UI_BUT_ANIMATED_CHANGED;
-
- /* NOTE: "special" is reserved for special F-Curves stored on the animation data
- * itself (which are used to animate properties of the animation data).
- * We count those as "animated" too for now
- */
- fcu = ui_but_get_fcurve(but, &adt, &act, &driven, &special);
-
- if (fcu) {
- if (!driven) {
- but->flag |= UI_BUT_ANIMATED;
-
- /* T41525 - When the active action is a NLA strip being edited,
- * we need to correct the frame number to "look inside" the
- * remapped action
- */
- if (adt) {
- cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
- }
-
- if (fcurve_frame_has_keyframe(fcu, cfra, 0)) {
- but->flag |= UI_BUT_ANIMATED_KEY;
- }
-
- /* XXX: this feature is totally broken and useless with NLA */
- if (adt == NULL || adt->nla_tracks.first == NULL) {
- if (fcurve_is_changed(but->rnapoin, but->rnaprop, fcu, cfra)) {
- but->drawflag |= UI_BUT_ANIMATED_CHANGED;
- }
- }
- }
- else {
- but->flag |= UI_BUT_DRIVEN;
- }
- }
+ AnimData *adt;
+ bAction *act;
+ FCurve *fcu;
+ bool driven;
+ bool special;
+
+ but->flag &= ~(UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN);
+ but->drawflag &= ~UI_BUT_ANIMATED_CHANGED;
+
+ /* NOTE: "special" is reserved for special F-Curves stored on the animation data
+ * itself (which are used to animate properties of the animation data).
+ * We count those as "animated" too for now
+ */
+ fcu = ui_but_get_fcurve(but, &adt, &act, &driven, &special);
+
+ if (fcu) {
+ if (!driven) {
+ but->flag |= UI_BUT_ANIMATED;
+
+ /* T41525 - When the active action is a NLA strip being edited,
+ * we need to correct the frame number to "look inside" the
+ * remapped action
+ */
+ if (adt) {
+ cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
+ }
+
+ if (fcurve_frame_has_keyframe(fcu, cfra, 0)) {
+ but->flag |= UI_BUT_ANIMATED_KEY;
+ }
+
+ /* XXX: this feature is totally broken and useless with NLA */
+ if (adt == NULL || adt->nla_tracks.first == NULL) {
+ if (fcurve_is_changed(but->rnapoin, but->rnaprop, fcu, cfra)) {
+ but->drawflag |= UI_BUT_ANIMATED_CHANGED;
+ }
+ }
+ }
+ else {
+ but->flag |= UI_BUT_DRIVEN;
+ }
+ }
}
void ui_but_anim_decorate_update_from_flag(uiBut *but)
{
- BLI_assert(UI_but_is_decorator(but) && but->prev);
- int flag = but->prev->flag;
- if (flag & UI_BUT_DRIVEN) {
- but->icon = ICON_DECORATE_DRIVER;
- }
- else if (flag & UI_BUT_ANIMATED_KEY) {
- but->icon = ICON_DECORATE_KEYFRAME;
- }
- else if (flag & UI_BUT_ANIMATED) {
- but->icon = ICON_DECORATE_ANIMATE;
- }
- else if (flag & UI_BUT_OVERRIDEN) {
- but->icon = ICON_DECORATE_OVERRIDE;
- }
- else {
- but->icon = ICON_DECORATE;
- }
-
- const int flag_copy = (UI_BUT_DISABLED | UI_BUT_INACTIVE);
- but->flag = (but->flag & ~flag_copy) | (flag & flag_copy);
+ BLI_assert(UI_but_is_decorator(but) && but->prev);
+ int flag = but->prev->flag;
+ if (flag & UI_BUT_DRIVEN) {
+ but->icon = ICON_DECORATE_DRIVER;
+ }
+ else if (flag & UI_BUT_ANIMATED_KEY) {
+ but->icon = ICON_DECORATE_KEYFRAME;
+ }
+ else if (flag & UI_BUT_ANIMATED) {
+ but->icon = ICON_DECORATE_ANIMATE;
+ }
+ else if (flag & UI_BUT_OVERRIDEN) {
+ but->icon = ICON_DECORATE_OVERRIDE;
+ }
+ else {
+ but->icon = ICON_DECORATE;
+ }
+
+ const int flag_copy = (UI_BUT_DISABLED | UI_BUT_INACTIVE);
+ but->flag = (but->flag & ~flag_copy) | (flag & flag_copy);
}
/**
@@ -137,233 +139,251 @@ void ui_but_anim_decorate_update_from_flag(uiBut *but)
*/
bool ui_but_anim_expression_get(uiBut *but, char *str, size_t maxlen)
{
- FCurve *fcu;
- ChannelDriver *driver;
- bool driven, special;
+ FCurve *fcu;
+ ChannelDriver *driver;
+ bool driven, special;
- fcu = ui_but_get_fcurve(but, NULL, NULL, &driven, &special);
+ fcu = ui_but_get_fcurve(but, NULL, NULL, &driven, &special);
- if (fcu && driven) {
- driver = fcu->driver;
+ if (fcu && driven) {
+ driver = fcu->driver;
- if (driver && driver->type == DRIVER_TYPE_PYTHON) {
- if (str) {
- BLI_strncpy(str, driver->expression, maxlen);
- }
- return true;
- }
- }
+ if (driver && driver->type == DRIVER_TYPE_PYTHON) {
+ if (str) {
+ BLI_strncpy(str, driver->expression, maxlen);
+ }
+ return true;
+ }
+ }
- return false;
+ return false;
}
bool ui_but_anim_expression_set(uiBut *but, const char *str)
{
- FCurve *fcu;
- ChannelDriver *driver;
- bool driven, special;
+ FCurve *fcu;
+ ChannelDriver *driver;
+ bool driven, special;
- fcu = ui_but_get_fcurve(but, NULL, NULL, &driven, &special);
+ fcu = ui_but_get_fcurve(but, NULL, NULL, &driven, &special);
- if (fcu && driven) {
- driver = fcu->driver;
+ if (fcu && driven) {
+ driver = fcu->driver;
- if (driver && (driver->type == DRIVER_TYPE_PYTHON)) {
- BLI_strncpy_utf8(driver->expression, str, sizeof(driver->expression));
+ if (driver && (driver->type == DRIVER_TYPE_PYTHON)) {
+ BLI_strncpy_utf8(driver->expression, str, sizeof(driver->expression));
- /* tag driver as needing to be recompiled */
- BKE_driver_invalidate_expression(driver, true, false);
+ /* tag driver as needing to be recompiled */
+ BKE_driver_invalidate_expression(driver, true, false);
- /* clear invalid flags which may prevent this from working */
- driver->flag &= ~DRIVER_FLAG_INVALID;
- fcu->flag &= ~FCURVE_DISABLED;
+ /* clear invalid flags which may prevent this from working */
+ driver->flag &= ~DRIVER_FLAG_INVALID;
+ fcu->flag &= ~FCURVE_DISABLED;
- /* this notifier should update the Graph Editor and trigger depsgraph refresh? */
- WM_event_add_notifier(but->block->evil_C, NC_ANIMATION | ND_KEYFRAME, NULL);
+ /* this notifier should update the Graph Editor and trigger depsgraph refresh? */
+ WM_event_add_notifier(but->block->evil_C, NC_ANIMATION | ND_KEYFRAME, NULL);
- return true;
- }
- }
+ return true;
+ }
+ }
- return false;
+ return false;
}
/* create new expression for button (i.e. a "scripted driver"), if it can be created... */
bool ui_but_anim_expression_create(uiBut *but, const char *str)
{
- bContext *C = but->block->evil_C;
- ID *id;
- FCurve *fcu;
- char *path;
- bool ok = false;
-
- /* button must have RNA-pointer to a numeric-capable property */
- if (ELEM(NULL, but->rnapoin.data, but->rnaprop)) {
- if (G.debug & G_DEBUG) {
- printf("ERROR: create expression failed - button has no RNA info attached\n");
- }
- return false;
- }
-
- if (RNA_property_array_check(but->rnaprop) != 0) {
- if (but->rnaindex == -1) {
- if (G.debug & G_DEBUG) {
- printf("ERROR: create expression failed - can't create expression for entire array\n");
- }
- return false;
- }
- }
-
- /* make sure we have animdata for this */
- /* FIXME: until materials can be handled by depsgraph,
- * don't allow drivers to be created for them */
- id = (ID *)but->rnapoin.id.data;
- if ((id == NULL) || (GS(id->name) == ID_MA) || (GS(id->name) == ID_TE)) {
- if (G.debug & G_DEBUG) {
- printf("ERROR: create expression failed - invalid data-block for adding drivers (%p)\n", id);
- }
- return false;
- }
-
- /* get path */
- path = RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop);
- if (path == NULL) {
- return false;
- }
-
- /* create driver */
- fcu = verify_driver_fcurve(id, path, but->rnaindex, 1);
- if (fcu) {
- ChannelDriver *driver = fcu->driver;
-
- if (driver) {
- /* set type of driver */
- driver->type = DRIVER_TYPE_PYTHON;
-
- /* set the expression */
- /* TODO: need some way of identifying variables used */
- BLI_strncpy_utf8(driver->expression, str, sizeof(driver->expression));
-
- /* updates */
- BKE_driver_invalidate_expression(driver, true, false);
- DEG_relations_tag_update(CTX_data_main(C));
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME, NULL);
- ok = true;
- }
- }
-
- MEM_freeN(path);
-
- return ok;
+ bContext *C = but->block->evil_C;
+ ID *id;
+ FCurve *fcu;
+ char *path;
+ bool ok = false;
+
+ /* button must have RNA-pointer to a numeric-capable property */
+ if (ELEM(NULL, but->rnapoin.data, but->rnaprop)) {
+ if (G.debug & G_DEBUG) {
+ printf("ERROR: create expression failed - button has no RNA info attached\n");
+ }
+ return false;
+ }
+
+ if (RNA_property_array_check(but->rnaprop) != 0) {
+ if (but->rnaindex == -1) {
+ if (G.debug & G_DEBUG) {
+ printf("ERROR: create expression failed - can't create expression for entire array\n");
+ }
+ return false;
+ }
+ }
+
+ /* make sure we have animdata for this */
+ /* FIXME: until materials can be handled by depsgraph,
+ * don't allow drivers to be created for them */
+ id = (ID *)but->rnapoin.id.data;
+ if ((id == NULL) || (GS(id->name) == ID_MA) || (GS(id->name) == ID_TE)) {
+ if (G.debug & G_DEBUG) {
+ printf("ERROR: create expression failed - invalid data-block for adding drivers (%p)\n", id);
+ }
+ return false;
+ }
+
+ /* get path */
+ path = RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop);
+ if (path == NULL) {
+ return false;
+ }
+
+ /* create driver */
+ fcu = verify_driver_fcurve(id, path, but->rnaindex, 1);
+ if (fcu) {
+ ChannelDriver *driver = fcu->driver;
+
+ if (driver) {
+ /* set type of driver */
+ driver->type = DRIVER_TYPE_PYTHON;
+
+ /* set the expression */
+ /* TODO: need some way of identifying variables used */
+ BLI_strncpy_utf8(driver->expression, str, sizeof(driver->expression));
+
+ /* updates */
+ BKE_driver_invalidate_expression(driver, true, false);
+ DEG_relations_tag_update(CTX_data_main(C));
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME, NULL);
+ ok = true;
+ }
+ }
+
+ MEM_freeN(path);
+
+ return ok;
}
void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
{
- Main *bmain = CTX_data_main(C);
- ID *id;
- bAction *action;
- FCurve *fcu;
- bool driven;
- bool special;
-
- fcu = ui_but_get_fcurve(but, NULL, &action, &driven, &special);
-
- if (fcu == NULL) {
- return;
- }
-
- if (special) {
- /* NLA Strip property */
- if (IS_AUTOKEY_ON(scene)) {
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ReportList *reports = CTX_wm_reports(C);
- ToolSettings *ts = scene->toolsettings;
-
- insert_keyframe_direct(depsgraph, reports, but->rnapoin, but->rnaprop, fcu, cfra, ts->keyframe_type, NULL, 0);
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- }
- }
- else if (driven) {
- /* Driver - Try to insert keyframe using the driver's input as the frame,
- * making it easier to set up corrective drivers
- */
- if (IS_AUTOKEY_ON(scene)) {
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ReportList *reports = CTX_wm_reports(C);
- ToolSettings *ts = scene->toolsettings;
-
- insert_keyframe_direct(depsgraph, reports, but->rnapoin, but->rnaprop, fcu, cfra, ts->keyframe_type, NULL, INSERTKEY_DRIVER);
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- }
- }
- else {
- id = but->rnapoin.id.data;
-
- /* TODO: this should probably respect the keyingset only option for anim */
- if (autokeyframe_cfra_can_key(scene, id)) {
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ReportList *reports = CTX_wm_reports(C);
- ToolSettings *ts = scene->toolsettings;
- short flag = ANIM_get_keyframing_flags(scene, 1);
-
- fcu->flag &= ~FCURVE_SELECTED;
-
- /* Note: We use but->rnaindex instead of fcu->array_index,
- * because a button may control all items of an array at once.
- * E.g., color wheels (see T42567). */
- BLI_assert((fcu->array_index == but->rnaindex) || (but->rnaindex == -1));
- insert_keyframe(bmain, depsgraph, reports, id, action,
- ((fcu->grp) ? (fcu->grp->name) : (NULL)),
- fcu->rna_path, but->rnaindex, cfra, ts->keyframe_type, NULL, flag);
-
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- }
- }
+ Main *bmain = CTX_data_main(C);
+ ID *id;
+ bAction *action;
+ FCurve *fcu;
+ bool driven;
+ bool special;
+
+ fcu = ui_but_get_fcurve(but, NULL, &action, &driven, &special);
+
+ if (fcu == NULL) {
+ return;
+ }
+
+ if (special) {
+ /* NLA Strip property */
+ if (IS_AUTOKEY_ON(scene)) {
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ReportList *reports = CTX_wm_reports(C);
+ ToolSettings *ts = scene->toolsettings;
+
+ insert_keyframe_direct(
+ depsgraph, reports, but->rnapoin, but->rnaprop, fcu, cfra, ts->keyframe_type, NULL, 0);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ }
+ }
+ else if (driven) {
+ /* Driver - Try to insert keyframe using the driver's input as the frame,
+ * making it easier to set up corrective drivers
+ */
+ if (IS_AUTOKEY_ON(scene)) {
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ReportList *reports = CTX_wm_reports(C);
+ ToolSettings *ts = scene->toolsettings;
+
+ insert_keyframe_direct(depsgraph,
+ reports,
+ but->rnapoin,
+ but->rnaprop,
+ fcu,
+ cfra,
+ ts->keyframe_type,
+ NULL,
+ INSERTKEY_DRIVER);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ }
+ }
+ else {
+ id = but->rnapoin.id.data;
+
+ /* TODO: this should probably respect the keyingset only option for anim */
+ if (autokeyframe_cfra_can_key(scene, id)) {
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ReportList *reports = CTX_wm_reports(C);
+ ToolSettings *ts = scene->toolsettings;
+ short flag = ANIM_get_keyframing_flags(scene, 1);
+
+ fcu->flag &= ~FCURVE_SELECTED;
+
+ /* Note: We use but->rnaindex instead of fcu->array_index,
+ * because a button may control all items of an array at once.
+ * E.g., color wheels (see T42567). */
+ BLI_assert((fcu->array_index == but->rnaindex) || (but->rnaindex == -1));
+ insert_keyframe(bmain,
+ depsgraph,
+ reports,
+ id,
+ action,
+ ((fcu->grp) ? (fcu->grp->name) : (NULL)),
+ fcu->rna_path,
+ but->rnaindex,
+ cfra,
+ ts->keyframe_type,
+ NULL,
+ flag);
+
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ }
+ }
}
void ui_but_anim_copy_driver(bContext *C)
{
- /* this operator calls UI_context_active_but_prop_get */
- WM_operator_name_call(C, "ANIM_OT_copy_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
+ /* this operator calls UI_context_active_but_prop_get */
+ WM_operator_name_call(C, "ANIM_OT_copy_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
}
void ui_but_anim_paste_driver(bContext *C)
{
- /* this operator calls UI_context_active_but_prop_get */
- WM_operator_name_call(C, "ANIM_OT_paste_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
+ /* this operator calls UI_context_active_but_prop_get */
+ WM_operator_name_call(C, "ANIM_OT_paste_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
}
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;
-
- /* FIXME(campbell), swapping active pointer is weak. */
- SWAP(struct uiHandleButtonData *, but->active, but->next->active);
- wm->op_undo_depth++;
-
- if (but->flag & UI_BUT_DRIVEN) {
- /* pass */
- /* TODO: report? */
- }
- else if (but->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);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
- WM_operator_properties_free(&props_ptr);
- }
- else {
- 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);
- 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);
- wm->op_undo_depth--;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ uiBut *but = arg_but;
+ but = but->prev;
+
+ /* FIXME(campbell), swapping active pointer is weak. */
+ SWAP(struct uiHandleButtonData *, but->active, but->next->active);
+ wm->op_undo_depth++;
+
+ if (but->flag & UI_BUT_DRIVEN) {
+ /* pass */
+ /* TODO: report? */
+ }
+ else if (but->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);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+ WM_operator_properties_free(&props_ptr);
+ }
+ else {
+ 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);
+ 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);
+ 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 4ca92fbb386..afa1b5c87e1 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -60,59 +60,65 @@
static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event))
{
- uiBut *but = (uiBut *)arg1;
-
- if (but->optype) {
- char shortcut_str[128];
-
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
-
- /* complex code to change name of button */
- if (WM_key_event_operator_string(
- C, but->optype->idname, but->opcontext, prop, true,
- shortcut_str, sizeof(shortcut_str)))
- {
- ui_but_add_shortcut(but, shortcut_str, true);
- }
- else {
- /* simply strip the shortcut */
- ui_but_add_shortcut(but, NULL, true);
- }
- }
+ uiBut *but = (uiBut *)arg1;
+
+ if (but->optype) {
+ char shortcut_str[128];
+
+ IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
+
+ /* complex code to change name of button */
+ if (WM_key_event_operator_string(C,
+ but->optype->idname,
+ but->opcontext,
+ prop,
+ true,
+ shortcut_str,
+ sizeof(shortcut_str))) {
+ ui_but_add_shortcut(but, shortcut_str, true);
+ }
+ else {
+ /* simply strip the shortcut */
+ ui_but_add_shortcut(but, NULL, true);
+ }
+ }
}
static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- uiBlock *block;
- uiBut *but = (uiBut *)arg;
- wmKeyMap *km;
- wmKeyMapItem *kmi;
- PointerRNA ptr;
- uiLayout *layout;
- uiStyle *style = UI_style_get_dpi();
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
-
- kmi = WM_key_event_operator(
- C, but->optype->idname, but->opcontext, prop,
- EVT_TYPE_MASK_HOTKEY_INCLUDE, EVT_TYPE_MASK_HOTKEY_EXCLUDE,
- &km);
- BLI_assert(kmi != NULL);
-
- RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr);
-
- block = UI_block_begin(C, ar, "_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);
-
- layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style);
-
- uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE);
-
- UI_block_bounds_set_popup(block, 6, (const int[2]){-50, 26});
-
- return block;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ uiBlock *block;
+ uiBut *but = (uiBut *)arg;
+ wmKeyMap *km;
+ wmKeyMapItem *kmi;
+ PointerRNA ptr;
+ uiLayout *layout;
+ uiStyle *style = UI_style_get_dpi();
+ IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
+
+ kmi = WM_key_event_operator(C,
+ but->optype->idname,
+ but->opcontext,
+ prop,
+ EVT_TYPE_MASK_HOTKEY_INCLUDE,
+ EVT_TYPE_MASK_HOTKEY_EXCLUDE,
+ &km);
+ BLI_assert(kmi != NULL);
+
+ RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr);
+
+ block = UI_block_begin(C, ar, "_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);
+
+ layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style);
+
+ uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE);
+
+ UI_block_bounds_set_popup(block, 6, (const int[2]){-50, 26});
+
+ return block;
}
#ifdef USE_KEYMAP_ADD_HACK
@@ -121,743 +127,944 @@ static int g_kmi_id_hack;
static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- uiBlock *block;
- uiBut *but = (uiBut *)arg;
- wmKeyMap *km;
- wmKeyMapItem *kmi;
- PointerRNA ptr;
- uiLayout *layout;
- uiStyle *style = UI_style_get_dpi();
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
- int kmi_id;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ uiBlock *block;
+ uiBut *but = (uiBut *)arg;
+ wmKeyMap *km;
+ wmKeyMapItem *kmi;
+ PointerRNA ptr;
+ uiLayout *layout;
+ uiStyle *style = UI_style_get_dpi();
+ IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
+ int kmi_id;
- /* XXX this guess_opname can potentially return a different keymap
- * than being found on adding later... */
- km = WM_keymap_guess_opname(C, but->optype->idname);
- kmi = WM_keymap_add_item(km, but->optype->idname, AKEY, KM_PRESS, 0, 0);
- kmi_id = kmi->id;
+ /* XXX this guess_opname can potentially return a different keymap
+ * than being found on adding later... */
+ km = WM_keymap_guess_opname(C, but->optype->idname);
+ kmi = WM_keymap_add_item(km, but->optype->idname, AKEY, KM_PRESS, 0, 0);
+ kmi_id = kmi->id;
- /* copy properties, prop can be NULL for reset */
- if (prop) {
- prop = IDP_CopyProperty(prop);
- }
- WM_keymap_properties_reset(kmi, prop);
+ /* copy properties, prop can be NULL for reset */
+ if (prop) {
+ prop = IDP_CopyProperty(prop);
+ }
+ WM_keymap_properties_reset(kmi, prop);
- /* update and get pointers again */
- WM_keyconfig_update(wm);
+ /* update and get pointers again */
+ WM_keyconfig_update(wm);
- km = WM_keymap_guess_opname(C, but->optype->idname);
- kmi = WM_keymap_item_find_id(km, kmi_id);
+ km = WM_keymap_guess_opname(C, but->optype->idname);
+ kmi = WM_keymap_item_find_id(km, kmi_id);
- RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr);
+ RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr);
- block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
- UI_block_func_handle_set(block, but_shortcut_name_func, but);
- UI_block_direction_set(block, UI_DIR_CENTER_Y);
+ block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
+ UI_block_func_handle_set(block, but_shortcut_name_func, but);
+ UI_block_direction_set(block, UI_DIR_CENTER_Y);
- layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style);
+ layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style);
- uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE);
+ uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE);
- UI_block_bounds_set_popup(block, 6, (const int[2]){-50, 26});
+ UI_block_bounds_set_popup(block, 6, (const int[2]){-50, 26});
#ifdef USE_KEYMAP_ADD_HACK
- g_kmi_id_hack = kmi_id;
+ g_kmi_id_hack = kmi_id;
#endif
- return block;
+ return block;
}
static void menu_add_shortcut_cancel(struct bContext *C, void *arg1)
{
- uiBut *but = (uiBut *)arg1;
- wmKeyMap *km;
- wmKeyMapItem *kmi;
+ uiBut *but = (uiBut *)arg1;
+ wmKeyMap *km;
+ wmKeyMapItem *kmi;
#ifndef USE_KEYMAP_ADD_HACK
- IDProperty *prop;
+ IDProperty *prop;
#endif
- int kmi_id;
+ int kmi_id;
#ifdef USE_KEYMAP_ADD_HACK
- km = WM_keymap_guess_opname(C, but->optype->idname);
- kmi_id = g_kmi_id_hack;
- UNUSED_VARS(but);
+ km = WM_keymap_guess_opname(C, but->optype->idname);
+ kmi_id = g_kmi_id_hack;
+ UNUSED_VARS(but);
#else
- prop = (but->opptr) ? but->opptr->data : NULL;
- kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km);
+ prop = (but->opptr) ? but->opptr->data : NULL;
+ kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km);
#endif
- kmi = WM_keymap_item_find_id(km, kmi_id);
- WM_keymap_remove_item(km, kmi);
+ kmi = WM_keymap_item_find_id(km, kmi_id);
+ WM_keymap_remove_item(km, kmi);
}
static void popup_change_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
{
- uiBut *but = (uiBut *)arg1;
- UI_popup_block_invoke(C, menu_change_shortcut, but);
+ uiBut *but = (uiBut *)arg1;
+ UI_popup_block_invoke(C, menu_change_shortcut, but);
}
static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
{
- uiBut *but = (uiBut *)arg1;
- wmKeyMap *km;
- wmKeyMapItem *kmi;
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
-
- kmi = WM_key_event_operator(
- C, but->optype->idname, but->opcontext, prop,
- EVT_TYPE_MASK_HOTKEY_INCLUDE, EVT_TYPE_MASK_HOTKEY_EXCLUDE,
- &km);
- BLI_assert(kmi != NULL);
-
- WM_keymap_remove_item(km, kmi);
-
- but_shortcut_name_func(C, but, 0);
+ uiBut *but = (uiBut *)arg1;
+ wmKeyMap *km;
+ wmKeyMapItem *kmi;
+ IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
+
+ kmi = WM_key_event_operator(C,
+ but->optype->idname,
+ but->opcontext,
+ prop,
+ EVT_TYPE_MASK_HOTKEY_INCLUDE,
+ EVT_TYPE_MASK_HOTKEY_EXCLUDE,
+ &km);
+ BLI_assert(kmi != NULL);
+
+ WM_keymap_remove_item(km, kmi);
+
+ but_shortcut_name_func(C, but, 0);
}
static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
{
- uiBut *but = (uiBut *)arg1;
- UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but, NULL);
+ uiBut *but = (uiBut *)arg1;
+ UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but, NULL);
}
static bool ui_but_is_user_menu_compatible(bContext *C, uiBut *but)
{
- return (but->optype ||
- (but->rnaprop &&
- (RNA_property_type(but->rnaprop) == PROP_BOOLEAN) &&
- (WM_context_member_from_ptr(C, &but->rnapoin) != NULL)) ||
- UI_but_menutype_get(but));
+ return (but->optype ||
+ (but->rnaprop && (RNA_property_type(but->rnaprop) == PROP_BOOLEAN) &&
+ (WM_context_member_from_ptr(C, &but->rnapoin) != NULL)) ||
+ UI_but_menutype_get(but));
}
static bUserMenuItem *ui_but_user_menu_find(bContext *C, uiBut *but, bUserMenu *um)
{
- MenuType *mt = NULL;
- if (but->optype) {
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
- return (bUserMenuItem *)ED_screen_user_menu_item_find_operator(
- &um->items, but->optype, prop, but->opcontext);
- }
- else if (but->rnaprop) {
- const char *member_id = WM_context_member_from_ptr(C, &but->rnapoin);
- const char *data_path = RNA_path_from_ID_to_struct(&but->rnapoin);
- const char *member_id_data_path = member_id;
- if (data_path) {
- member_id_data_path = BLI_sprintfN("%s.%s", member_id, data_path);
- }
- const char *prop_id = RNA_property_identifier(but->rnaprop);
- bUserMenuItem *umi = (bUserMenuItem *)ED_screen_user_menu_item_find_prop(
- &um->items, member_id_data_path, prop_id, but->rnaindex);
- if (data_path) {
- MEM_freeN((void *)data_path);
- }
- if (member_id != member_id_data_path) {
- MEM_freeN((void *)member_id_data_path);
- }
- return umi;
- }
- else if ((mt = UI_but_menutype_get(but))) {
- return (bUserMenuItem *)ED_screen_user_menu_item_find_menu(
- &um->items, mt);
- }
- else {
- return NULL;
- }
+ MenuType *mt = NULL;
+ if (but->optype) {
+ IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
+ return (bUserMenuItem *)ED_screen_user_menu_item_find_operator(
+ &um->items, but->optype, prop, but->opcontext);
+ }
+ else if (but->rnaprop) {
+ const char *member_id = WM_context_member_from_ptr(C, &but->rnapoin);
+ const char *data_path = RNA_path_from_ID_to_struct(&but->rnapoin);
+ const char *member_id_data_path = member_id;
+ if (data_path) {
+ member_id_data_path = BLI_sprintfN("%s.%s", member_id, data_path);
+ }
+ const char *prop_id = RNA_property_identifier(but->rnaprop);
+ bUserMenuItem *umi = (bUserMenuItem *)ED_screen_user_menu_item_find_prop(
+ &um->items, member_id_data_path, prop_id, but->rnaindex);
+ if (data_path) {
+ MEM_freeN((void *)data_path);
+ }
+ if (member_id != member_id_data_path) {
+ MEM_freeN((void *)member_id_data_path);
+ }
+ return umi;
+ }
+ else if ((mt = UI_but_menutype_get(but))) {
+ return (bUserMenuItem *)ED_screen_user_menu_item_find_menu(&um->items, mt);
+ }
+ else {
+ return NULL;
+ }
}
static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um)
{
- BLI_assert(ui_but_is_user_menu_compatible(C, but));
-
- char drawstr[sizeof(but->drawstr)];
- STRNCPY(drawstr, but->drawstr);
- if (but->flag & UI_BUT_HAS_SEP_CHAR) {
- char *sep = strrchr(drawstr, UI_SEP_CHAR);
- if (sep) {
- *sep = '\0';
- }
- }
-
- MenuType *mt = NULL;
- if (but->optype) {
- if (drawstr[0] == '\0') {
- /* Hard code overrides for generic operators. */
- if (UI_but_is_tool(but)) {
- RNA_string_get(but->opptr, "name", drawstr);
- }
- }
- ED_screen_user_menu_item_add_operator(
- &um->items, drawstr,
- but->optype, but->opptr ? but->opptr->data : NULL, but->opcontext);
- }
- else if (but->rnaprop) {
- /* Note: 'member_id' may be a path. */
- const char *member_id = WM_context_member_from_ptr(C, &but->rnapoin);
- const char *data_path = RNA_path_from_ID_to_struct(&but->rnapoin);
- const char *member_id_data_path = member_id;
- if (data_path) {
- member_id_data_path = BLI_sprintfN("%s.%s", member_id, data_path);
- }
- const char *prop_id = RNA_property_identifier(but->rnaprop);
- /* Note, ignore 'drawstr', use property idname always. */
- ED_screen_user_menu_item_add_prop(
- &um->items, "",
- member_id_data_path, prop_id, but->rnaindex);
- if (data_path) {
- MEM_freeN((void *)data_path);
- }
- if (member_id != member_id_data_path) {
- MEM_freeN((void *)member_id_data_path);
- }
- }
- else if ((mt = UI_but_menutype_get(but))) {
- ED_screen_user_menu_item_add_menu(
- &um->items, drawstr,
- mt);
- }
+ BLI_assert(ui_but_is_user_menu_compatible(C, but));
+
+ char drawstr[sizeof(but->drawstr)];
+ STRNCPY(drawstr, but->drawstr);
+ if (but->flag & UI_BUT_HAS_SEP_CHAR) {
+ char *sep = strrchr(drawstr, UI_SEP_CHAR);
+ if (sep) {
+ *sep = '\0';
+ }
+ }
+
+ MenuType *mt = NULL;
+ if (but->optype) {
+ if (drawstr[0] == '\0') {
+ /* Hard code overrides for generic operators. */
+ if (UI_but_is_tool(but)) {
+ RNA_string_get(but->opptr, "name", drawstr);
+ }
+ }
+ ED_screen_user_menu_item_add_operator(
+ &um->items, drawstr, but->optype, but->opptr ? but->opptr->data : NULL, but->opcontext);
+ }
+ else if (but->rnaprop) {
+ /* Note: 'member_id' may be a path. */
+ const char *member_id = WM_context_member_from_ptr(C, &but->rnapoin);
+ const char *data_path = RNA_path_from_ID_to_struct(&but->rnapoin);
+ const char *member_id_data_path = member_id;
+ if (data_path) {
+ member_id_data_path = BLI_sprintfN("%s.%s", member_id, data_path);
+ }
+ const char *prop_id = RNA_property_identifier(but->rnaprop);
+ /* Note, ignore 'drawstr', use property idname always. */
+ ED_screen_user_menu_item_add_prop(&um->items, "", member_id_data_path, prop_id, but->rnaindex);
+ if (data_path) {
+ MEM_freeN((void *)data_path);
+ }
+ if (member_id != member_id_data_path) {
+ MEM_freeN((void *)member_id_data_path);
+ }
+ }
+ else if ((mt = UI_but_menutype_get(but))) {
+ ED_screen_user_menu_item_add_menu(&um->items, drawstr, mt);
+ }
}
static void popup_user_menu_add_or_replace_func(bContext *C, void *arg1, void *UNUSED(arg2))
{
- uiBut *but = arg1;
- bUserMenu *um = ED_screen_user_menu_ensure(C);
- ui_but_user_menu_add(C, but, um);
+ uiBut *but = arg1;
+ bUserMenu *um = ED_screen_user_menu_ensure(C);
+ ui_but_user_menu_add(C, but, um);
}
static void popup_user_menu_remove_func(bContext *UNUSED(C), void *arg1, void *arg2)
{
- bUserMenu *um = arg1;
- bUserMenuItem *umi = arg2;
- ED_screen_user_menu_item_remove(&um->items, umi);
+ bUserMenu *um = arg1;
+ bUserMenuItem *umi = arg2;
+ ED_screen_user_menu_item_remove(&um->items, umi);
}
static void ui_but_menu_add_path_operators(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop)
{
- const PropertySubType subtype = RNA_property_subtype(prop);
- wmOperatorType *ot = WM_operatortype_find("WM_OT_path_open", true);
- char filepath[FILE_MAX];
- char dir[FILE_MAXDIR];
- char file[FILE_MAXFILE];
- PointerRNA props_ptr;
-
- BLI_assert(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH));
- UNUSED_VARS_NDEBUG(subtype);
-
- RNA_property_string_get(ptr, prop, filepath);
- BLI_split_dirfile(filepath, dir, file, sizeof(dir), sizeof(file));
-
- if (file[0]) {
- BLI_assert(subtype == PROP_FILEPATH);
- uiItemFullO_ptr(
- layout, ot, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open File Externally"),
- ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &props_ptr);
- RNA_string_set(&props_ptr, "filepath", filepath);
- }
-
- uiItemFullO_ptr(
- layout, ot, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Location Externally"),
- ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &props_ptr);
- RNA_string_set(&props_ptr, "filepath", dir);
+ const PropertySubType subtype = RNA_property_subtype(prop);
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_path_open", true);
+ char filepath[FILE_MAX];
+ char dir[FILE_MAXDIR];
+ char file[FILE_MAXFILE];
+ PointerRNA props_ptr;
+
+ BLI_assert(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH));
+ UNUSED_VARS_NDEBUG(subtype);
+
+ RNA_property_string_get(ptr, prop, filepath);
+ BLI_split_dirfile(filepath, dir, file, sizeof(dir), sizeof(file));
+
+ if (file[0]) {
+ BLI_assert(subtype == PROP_FILEPATH);
+ uiItemFullO_ptr(layout,
+ ot,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open File Externally"),
+ ICON_NONE,
+ NULL,
+ WM_OP_INVOKE_DEFAULT,
+ 0,
+ &props_ptr);
+ RNA_string_set(&props_ptr, "filepath", filepath);
+ }
+
+ uiItemFullO_ptr(layout,
+ ot,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Location Externally"),
+ ICON_NONE,
+ NULL,
+ WM_OP_INVOKE_DEFAULT,
+ 0,
+ &props_ptr);
+ RNA_string_set(&props_ptr, "filepath", dir);
}
bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
{
- /* having this menu for some buttons makes no sense */
- if (but->type == UI_BTYPE_IMAGE) {
- return false;
- }
-
- uiPopupMenu *pup;
- uiLayout *layout;
-
- {
- uiStringInfo label = {BUT_GET_LABEL, NULL};
-
- /* highly unlikely getting the label ever fails */
- UI_but_string_info_get(C, but, &label, NULL);
-
- pup = UI_popup_menu_begin(C, label.strinfo ? label.strinfo : "", ICON_NONE);
- layout = UI_popup_menu_layout(pup);
- if (label.strinfo) {
- MEM_freeN(label.strinfo);
- }
- uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
- }
-
- const bool is_disabled = but->flag & UI_BUT_DISABLED;
-
- if (is_disabled) {
- /* Suppress editing commands. */
- }
- else if (but->type == UI_BTYPE_TAB) {
- uiButTab *tab = (uiButTab *)but;
- if (tab->menu) {
- UI_menutype_draw(C, tab->menu, layout);
- uiItemS(layout);
- }
- }
- else if (but->rnapoin.data && but->rnaprop) {
- PointerRNA *ptr = &but->rnapoin;
- PropertyRNA *prop = but->rnaprop;
- const PropertyType type = RNA_property_type(prop);
- const PropertySubType subtype = RNA_property_subtype(prop);
- bool is_anim = RNA_property_animateable(ptr, prop);
- bool is_editable = RNA_property_editable(ptr, prop);
- bool is_idprop = RNA_property_is_idprop(prop);
- bool is_set = RNA_property_is_set(ptr, prop);
-
- /* second slower test,
- * saved people finding keyframe items in menus when its not possible */
- if (is_anim) {
- is_anim = RNA_property_path_from_ID_check(&but->rnapoin, but->rnaprop);
- }
-
- /* determine if we can key a single component of an array */
- const bool is_array = RNA_property_array_length(&but->rnapoin, but->rnaprop) != 0;
- const bool is_array_component = (is_array && but->rnaindex != -1);
-
- const int override_status = RNA_property_static_override_status(ptr, prop, -1);
- const bool is_overridable = (override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE) != 0;
-
- /* Set the (button_pointer, button_prop)
- * and pointer data for Python access to the hovered ui element. */
- uiLayoutSetContextFromBut(layout, but);
-
- /* Keyframes */
- if (but->flag & UI_BUT_ANIMATED_KEY) {
- /* replace/delete keyfraemes */
- if (is_array_component) {
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframes"),
- ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1);
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Single Keyframe"),
- ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0);
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframes"),
- ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 1);
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Keyframe"),
- ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 0);
- }
- else {
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframe"),
- ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1);
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframe"),
- ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 1);
- }
-
- /* keyframe settings */
- uiItemS(layout);
-
-
- }
- else if (but->flag & UI_BUT_DRIVEN) {
- /* pass */
- }
- else if (is_anim) {
- if (is_array_component) {
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframes"),
- ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1);
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Single Keyframe"),
- ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0);
- }
- else {
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframe"),
- ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1);
- }
- }
-
- if ((but->flag & UI_BUT_ANIMATED) && (but->rnapoin.type != &RNA_NlaStrip)) {
- if (is_array_component) {
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"),
- ICON_KEY_DEHLT, "ANIM_OT_keyframe_clear_button", "all", 1);
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Single Keyframes"),
- ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 0);
- }
- else {
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"),
- ICON_KEY_DEHLT, "ANIM_OT_keyframe_clear_button", "all", 1);
- }
- }
-
- /* Drivers */
- if (but->flag & UI_BUT_DRIVEN) {
- uiItemS(layout);
-
- if (is_array_component) {
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Drivers"),
- ICON_X, "ANIM_OT_driver_button_remove", "all", 1);
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Driver"),
- ICON_NONE, "ANIM_OT_driver_button_remove", "all", 0);
- }
- else {
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Driver"),
- ICON_X, "ANIM_OT_driver_button_remove", "all", 1);
- }
-
- uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Driver"),
- ICON_NONE, "ANIM_OT_copy_driver_button");
- if (ANIM_driver_can_paste()) {
- uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"),
- ICON_NONE, "ANIM_OT_paste_driver_button");
- }
-
- uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Edit Driver"),
- ICON_DRIVER, "ANIM_OT_driver_button_edit");
-
- uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Drivers Editor"),
- ICON_NONE, "SCREEN_OT_drivers_editor_show");
- }
- else if (but->flag & (UI_BUT_ANIMATED_KEY | UI_BUT_ANIMATED)) {
- /* pass */
- }
- else if (is_anim) {
- uiItemS(layout);
-
- uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"),
- ICON_DRIVER, "ANIM_OT_driver_button_add");
-
- if (ANIM_driver_can_paste()) {
- uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"),
- ICON_NONE, "ANIM_OT_paste_driver_button");
- }
-
- uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Drivers Editor"),
- ICON_NONE, "SCREEN_OT_drivers_editor_show");
- }
-
- /* Keying Sets */
- /* TODO: check on modifyability of Keying Set when doing this */
- if (is_anim) {
- uiItemS(layout);
-
- if (is_array_component) {
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add All to Keying Set"),
- ICON_KEYINGSET, "ANIM_OT_keyingset_button_add", "all", 1);
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Single to Keying Set"),
- ICON_NONE, "ANIM_OT_keyingset_button_add", "all", 0);
- uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"),
- ICON_NONE, "ANIM_OT_keyingset_button_remove");
- }
- else {
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add to Keying Set"),
- ICON_KEYINGSET, "ANIM_OT_keyingset_button_add", "all", 1);
- uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"),
- ICON_NONE, "ANIM_OT_keyingset_button_remove");
- }
- }
-
- if (is_overridable) {
- wmOperatorType *ot;
- PointerRNA op_ptr;
- /* Override Operators */
- uiItemS(layout);
-
- if (but->flag & UI_BUT_OVERRIDEN) {
- if (is_array_component) {
-#if 0 /* Disabled for now. */
- ot = WM_operatortype_find("UI_OT_override_type_set_button", false);
- uiItemFullO_ptr(
- layout, ot, "Overrides Type", ICON_NONE,
- NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
- RNA_boolean_set(&op_ptr, "all", true);
- uiItemFullO_ptr(
- layout, ot, "Single Override Type", ICON_NONE,
- NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
- RNA_boolean_set(&op_ptr, "all", false);
+ /* having this menu for some buttons makes no sense */
+ if (but->type == UI_BTYPE_IMAGE) {
+ return false;
+ }
+
+ uiPopupMenu *pup;
+ uiLayout *layout;
+
+ {
+ uiStringInfo label = {BUT_GET_LABEL, NULL};
+
+ /* highly unlikely getting the label ever fails */
+ UI_but_string_info_get(C, but, &label, NULL);
+
+ pup = UI_popup_menu_begin(C, label.strinfo ? label.strinfo : "", ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ if (label.strinfo) {
+ MEM_freeN(label.strinfo);
+ }
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
+ }
+
+ const bool is_disabled = but->flag & UI_BUT_DISABLED;
+
+ if (is_disabled) {
+ /* Suppress editing commands. */
+ }
+ else if (but->type == UI_BTYPE_TAB) {
+ uiButTab *tab = (uiButTab *)but;
+ if (tab->menu) {
+ UI_menutype_draw(C, tab->menu, layout);
+ uiItemS(layout);
+ }
+ }
+ else if (but->rnapoin.data && but->rnaprop) {
+ PointerRNA *ptr = &but->rnapoin;
+ PropertyRNA *prop = but->rnaprop;
+ const PropertyType type = RNA_property_type(prop);
+ const PropertySubType subtype = RNA_property_subtype(prop);
+ bool is_anim = RNA_property_animateable(ptr, prop);
+ bool is_editable = RNA_property_editable(ptr, prop);
+ bool is_idprop = RNA_property_is_idprop(prop);
+ bool is_set = RNA_property_is_set(ptr, prop);
+
+ /* second slower test,
+ * saved people finding keyframe items in menus when its not possible */
+ if (is_anim) {
+ is_anim = RNA_property_path_from_ID_check(&but->rnapoin, but->rnaprop);
+ }
+
+ /* determine if we can key a single component of an array */
+ const bool is_array = RNA_property_array_length(&but->rnapoin, but->rnaprop) != 0;
+ const bool is_array_component = (is_array && but->rnaindex != -1);
+
+ const int override_status = RNA_property_static_override_status(ptr, prop, -1);
+ const bool is_overridable = (override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE) != 0;
+
+ /* Set the (button_pointer, button_prop)
+ * and pointer data for Python access to the hovered ui element. */
+ uiLayoutSetContextFromBut(layout, but);
+
+ /* Keyframes */
+ if (but->flag & UI_BUT_ANIMATED_KEY) {
+ /* replace/delete keyfraemes */
+ if (is_array_component) {
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframes"),
+ ICON_KEY_HLT,
+ "ANIM_OT_keyframe_insert_button",
+ "all",
+ 1);
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Single Keyframe"),
+ ICON_NONE,
+ "ANIM_OT_keyframe_insert_button",
+ "all",
+ 0);
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframes"),
+ ICON_NONE,
+ "ANIM_OT_keyframe_delete_button",
+ "all",
+ 1);
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Keyframe"),
+ ICON_NONE,
+ "ANIM_OT_keyframe_delete_button",
+ "all",
+ 0);
+ }
+ else {
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframe"),
+ ICON_KEY_HLT,
+ "ANIM_OT_keyframe_insert_button",
+ "all",
+ 1);
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframe"),
+ ICON_NONE,
+ "ANIM_OT_keyframe_delete_button",
+ "all",
+ 1);
+ }
+
+ /* keyframe settings */
+ uiItemS(layout);
+ }
+ else if (but->flag & UI_BUT_DRIVEN) {
+ /* pass */
+ }
+ else if (is_anim) {
+ if (is_array_component) {
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframes"),
+ ICON_KEY_HLT,
+ "ANIM_OT_keyframe_insert_button",
+ "all",
+ 1);
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Single Keyframe"),
+ ICON_NONE,
+ "ANIM_OT_keyframe_insert_button",
+ "all",
+ 0);
+ }
+ else {
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframe"),
+ ICON_KEY_HLT,
+ "ANIM_OT_keyframe_insert_button",
+ "all",
+ 1);
+ }
+ }
+
+ if ((but->flag & UI_BUT_ANIMATED) && (but->rnapoin.type != &RNA_NlaStrip)) {
+ if (is_array_component) {
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"),
+ ICON_KEY_DEHLT,
+ "ANIM_OT_keyframe_clear_button",
+ "all",
+ 1);
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Single Keyframes"),
+ ICON_NONE,
+ "ANIM_OT_keyframe_clear_button",
+ "all",
+ 0);
+ }
+ else {
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"),
+ ICON_KEY_DEHLT,
+ "ANIM_OT_keyframe_clear_button",
+ "all",
+ 1);
+ }
+ }
+
+ /* Drivers */
+ if (but->flag & UI_BUT_DRIVEN) {
+ uiItemS(layout);
+
+ if (is_array_component) {
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Drivers"),
+ ICON_X,
+ "ANIM_OT_driver_button_remove",
+ "all",
+ 1);
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Driver"),
+ ICON_NONE,
+ "ANIM_OT_driver_button_remove",
+ "all",
+ 0);
+ }
+ else {
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Driver"),
+ ICON_X,
+ "ANIM_OT_driver_button_remove",
+ "all",
+ 1);
+ }
+
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Driver"),
+ ICON_NONE,
+ "ANIM_OT_copy_driver_button");
+ if (ANIM_driver_can_paste()) {
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"),
+ ICON_NONE,
+ "ANIM_OT_paste_driver_button");
+ }
+
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Edit Driver"),
+ ICON_DRIVER,
+ "ANIM_OT_driver_button_edit");
+
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Drivers Editor"),
+ ICON_NONE,
+ "SCREEN_OT_drivers_editor_show");
+ }
+ else if (but->flag & (UI_BUT_ANIMATED_KEY | UI_BUT_ANIMATED)) {
+ /* pass */
+ }
+ else if (is_anim) {
+ uiItemS(layout);
+
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"),
+ ICON_DRIVER,
+ "ANIM_OT_driver_button_add");
+
+ if (ANIM_driver_can_paste()) {
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"),
+ ICON_NONE,
+ "ANIM_OT_paste_driver_button");
+ }
+
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Drivers Editor"),
+ ICON_NONE,
+ "SCREEN_OT_drivers_editor_show");
+ }
+
+ /* Keying Sets */
+ /* TODO: check on modifyability of Keying Set when doing this */
+ if (is_anim) {
+ uiItemS(layout);
+
+ if (is_array_component) {
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add All to Keying Set"),
+ ICON_KEYINGSET,
+ "ANIM_OT_keyingset_button_add",
+ "all",
+ 1);
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Single to Keying Set"),
+ ICON_NONE,
+ "ANIM_OT_keyingset_button_add",
+ "all",
+ 0);
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"),
+ ICON_NONE,
+ "ANIM_OT_keyingset_button_remove");
+ }
+ else {
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add to Keying Set"),
+ ICON_KEYINGSET,
+ "ANIM_OT_keyingset_button_add",
+ "all",
+ 1);
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"),
+ ICON_NONE,
+ "ANIM_OT_keyingset_button_remove");
+ }
+ }
+
+ if (is_overridable) {
+ wmOperatorType *ot;
+ PointerRNA op_ptr;
+ /* Override Operators */
+ uiItemS(layout);
+
+ if (but->flag & UI_BUT_OVERRIDEN) {
+ if (is_array_component) {
+#if 0 /* Disabled for now. */
+ ot = WM_operatortype_find("UI_OT_override_type_set_button", false);
+ uiItemFullO_ptr(
+ layout, ot, "Overrides Type", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", true);
+ uiItemFullO_ptr(
+ layout, ot, "Single Override Type", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", false);
#endif
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Overrides"),
- ICON_X, "UI_OT_override_remove_button", "all", true);
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Single Override"),
- ICON_X, "UI_OT_override_remove_button", "all", false);
- }
- else {
-#if 0 /* Disabled for now. */
- uiItemFullO(
- layout, "UI_OT_override_type_set_button", "Override Type", ICON_NONE,
- NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
- RNA_boolean_set(&op_ptr, "all", false);
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Overrides"),
+ ICON_X,
+ "UI_OT_override_remove_button",
+ "all",
+ true);
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Single Override"),
+ ICON_X,
+ "UI_OT_override_remove_button",
+ "all",
+ false);
+ }
+ else {
+#if 0 /* Disabled for now. */
+ uiItemFullO(
+ layout, "UI_OT_override_type_set_button", "Override Type", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", false);
#endif
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Override"),
- ICON_X, "UI_OT_override_remove_button", "all", true);
- }
- }
- else {
- if (is_array_component) {
- ot = WM_operatortype_find("UI_OT_override_type_set_button", false);
- uiItemFullO_ptr(
- layout, ot, "Define Overrides", ICON_NONE,
- NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
- RNA_boolean_set(&op_ptr, "all", true);
- uiItemFullO_ptr(
- layout, ot, "Define Single Override", ICON_NONE,
- NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
- RNA_boolean_set(&op_ptr, "all", false);
- }
- else {
- uiItemFullO(
- layout, "UI_OT_override_type_set_button", "Define Override", ICON_NONE,
- NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
- RNA_boolean_set(&op_ptr, "all", false);
- }
- }
- }
-
- uiItemS(layout);
-
- /* Property Operators */
-
- /* Copy Property Value
- * Paste Property Value */
-
- if (is_array_component) {
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset All to Default Values"),
- ICON_LOOP_BACK, "UI_OT_reset_default_button", "all", 1);
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset Single to Default Value"),
- ICON_NONE, "UI_OT_reset_default_button", "all", 0);
- }
- else {
- uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset to Default Value"),
- ICON_LOOP_BACK, "UI_OT_reset_default_button", "all", 1);
- }
- if (is_editable /*&& is_idprop*/ && is_set) {
- uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Unset"),
- ICON_NONE, "UI_OT_unset_property_button");
- }
-
- if (is_idprop && !is_array_component && ELEM(type, PROP_INT, PROP_FLOAT)) {
- uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Assign Value as Default"),
- ICON_NONE, "UI_OT_assign_default_button");
-
- uiItemS(layout);
- }
-
- if (is_array_component) {
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy All To Selected"),
- ICON_NONE, "UI_OT_copy_to_selected_button", "all", true);
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Single To Selected"),
- ICON_NONE, "UI_OT_copy_to_selected_button", "all", false);
- }
- else {
- uiItemBooleanO(
- layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy To Selected"),
- ICON_NONE, "UI_OT_copy_to_selected_button", "all", true);
- }
-
- uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Data Path"),
- ICON_NONE, "UI_OT_copy_data_path_button");
-
- uiItemS(layout);
-
- if (type == PROP_STRING && ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH)) {
- ui_but_menu_add_path_operators(layout, ptr, prop);
- uiItemS(layout);
- }
- }
-
- /* Pointer properties and string properties with
- * prop_search support jumping to target object/bone. */
- if (but->rnapoin.data && but->rnaprop) {
- 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)) &&
- ui_jump_to_target_button_poll(C))
- {
- uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Jump To Target"),
- ICON_NONE, "UI_OT_jump_to_target_button");
- uiItemS(layout);
- }
- }
-
- /* Favorites Menu */
- if (ui_but_is_user_menu_compatible(C, but)) {
- uiBlock *block = uiLayoutGetBlock(layout);
- const int w = uiLayoutGetWidth(layout);
- uiBut *but2;
- bool item_found = false;
-
- uint um_array_len;
- bUserMenu **um_array = ED_screen_user_menus_find(C, &um_array_len);
- for (int um_index = 0; um_index < um_array_len; um_index++) {
- bUserMenu *um = um_array[um_index];
- if (um == NULL) {
- continue;
- }
- bUserMenuItem *umi = ui_but_user_menu_find(C, but, um);
- if (umi != NULL) {
- but2 = uiDefIconTextBut(
- block, UI_BTYPE_BUT, 0, ICON_MENU_PANEL,
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Quick Favorites"),
- 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- UI_but_func_set(but2, popup_user_menu_remove_func, um, umi);
- item_found = true;
- }
- }
- if (um_array) {
- MEM_freeN(um_array);
- }
-
- if (!item_found) {
- but2 = uiDefIconTextBut(
- block, UI_BTYPE_BUT, 0, ICON_MENU_PANEL,
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add to Quick Favorites"),
- 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0,
- "Add to a user defined context menu (stored in the user preferences)");
- UI_but_func_set(but2, popup_user_menu_add_or_replace_func, but, NULL);
- }
-
- uiItemS(layout);
- }
-
- /* Operator buttons */
- if (but->optype) {
- uiBlock *block = uiLayoutGetBlock(layout);
- uiBut *but2;
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
- int w = uiLayoutGetWidth(layout);
- wmKeyMap *km;
- /* We want to know if this op has a shortcut, be it hotkey or not. */
- wmKeyMapItem *kmi = WM_key_event_operator(
- C, but->optype->idname, but->opcontext, prop,
- EVT_TYPE_MASK_ALL, 0,
- &km);
-
- /* We do have a shortcut, but only keyboard ones are editable that way... */
- if (kmi) {
- if (ISKEYBOARD(kmi->type)) {
-#if 0 /* would rather use a block but, but gets weirdly positioned... */
- uiDefBlockBut(
- block, menu_change_shortcut, but, "Change Shortcut",
- 0, 0, uiLayoutGetWidth(layout), UI_UNIT_Y, "");
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Override"),
+ ICON_X,
+ "UI_OT_override_remove_button",
+ "all",
+ true);
+ }
+ }
+ else {
+ if (is_array_component) {
+ ot = WM_operatortype_find("UI_OT_override_type_set_button", false);
+ uiItemFullO_ptr(
+ layout, ot, "Define Overrides", ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", true);
+ uiItemFullO_ptr(layout,
+ ot,
+ "Define Single Override",
+ ICON_NONE,
+ NULL,
+ WM_OP_INVOKE_DEFAULT,
+ 0,
+ &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", false);
+ }
+ else {
+ uiItemFullO(layout,
+ "UI_OT_override_type_set_button",
+ "Define Override",
+ ICON_NONE,
+ NULL,
+ WM_OP_INVOKE_DEFAULT,
+ 0,
+ &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", false);
+ }
+ }
+ }
+
+ uiItemS(layout);
+
+ /* Property Operators */
+
+ /* Copy Property Value
+ * Paste Property Value */
+
+ if (is_array_component) {
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset All to Default Values"),
+ ICON_LOOP_BACK,
+ "UI_OT_reset_default_button",
+ "all",
+ 1);
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset Single to Default Value"),
+ ICON_NONE,
+ "UI_OT_reset_default_button",
+ "all",
+ 0);
+ }
+ else {
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset to Default Value"),
+ ICON_LOOP_BACK,
+ "UI_OT_reset_default_button",
+ "all",
+ 1);
+ }
+ if (is_editable /*&& is_idprop*/ && is_set) {
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Unset"),
+ ICON_NONE,
+ "UI_OT_unset_property_button");
+ }
+
+ if (is_idprop && !is_array_component && ELEM(type, PROP_INT, PROP_FLOAT)) {
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Assign Value as Default"),
+ ICON_NONE,
+ "UI_OT_assign_default_button");
+
+ uiItemS(layout);
+ }
+
+ if (is_array_component) {
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy All To Selected"),
+ ICON_NONE,
+ "UI_OT_copy_to_selected_button",
+ "all",
+ true);
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Single To Selected"),
+ ICON_NONE,
+ "UI_OT_copy_to_selected_button",
+ "all",
+ false);
+ }
+ else {
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy To Selected"),
+ ICON_NONE,
+ "UI_OT_copy_to_selected_button",
+ "all",
+ true);
+ }
+
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Data Path"),
+ ICON_NONE,
+ "UI_OT_copy_data_path_button");
+
+ uiItemS(layout);
+
+ if (type == PROP_STRING && ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH)) {
+ ui_but_menu_add_path_operators(layout, ptr, prop);
+ uiItemS(layout);
+ }
+ }
+
+ /* Pointer properties and string properties with
+ * prop_search support jumping to target object/bone. */
+ if (but->rnapoin.data && but->rnaprop) {
+ 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)) &&
+ ui_jump_to_target_button_poll(C)) {
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Jump To Target"),
+ ICON_NONE,
+ "UI_OT_jump_to_target_button");
+ uiItemS(layout);
+ }
+ }
+
+ /* Favorites Menu */
+ if (ui_but_is_user_menu_compatible(C, but)) {
+ uiBlock *block = uiLayoutGetBlock(layout);
+ const int w = uiLayoutGetWidth(layout);
+ uiBut *but2;
+ bool item_found = false;
+
+ uint um_array_len;
+ bUserMenu **um_array = ED_screen_user_menus_find(C, &um_array_len);
+ for (int um_index = 0; um_index < um_array_len; um_index++) {
+ bUserMenu *um = um_array[um_index];
+ if (um == NULL) {
+ continue;
+ }
+ bUserMenuItem *umi = ui_but_user_menu_find(C, but, um);
+ if (umi != NULL) {
+ but2 = uiDefIconTextBut(
+ block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_MENU_PANEL,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Quick Favorites"),
+ 0,
+ 0,
+ w,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ UI_but_func_set(but2, popup_user_menu_remove_func, um, umi);
+ item_found = true;
+ }
+ }
+ if (um_array) {
+ MEM_freeN(um_array);
+ }
+
+ if (!item_found) {
+ but2 = uiDefIconTextBut(
+ block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_MENU_PANEL,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add to Quick Favorites"),
+ 0,
+ 0,
+ w,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "Add to a user defined context menu (stored in the user preferences)");
+ UI_but_func_set(but2, popup_user_menu_add_or_replace_func, but, NULL);
+ }
+
+ uiItemS(layout);
+ }
+
+ /* Operator buttons */
+ if (but->optype) {
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiBut *but2;
+ IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
+ int w = uiLayoutGetWidth(layout);
+ wmKeyMap *km;
+ /* We want to know if this op has a shortcut, be it hotkey or not. */
+ wmKeyMapItem *kmi = WM_key_event_operator(
+ C, but->optype->idname, but->opcontext, prop, EVT_TYPE_MASK_ALL, 0, &km);
+
+ /* We do have a shortcut, but only keyboard ones are editable that way... */
+ if (kmi) {
+ if (ISKEYBOARD(kmi->type)) {
+#if 0 /* would rather use a block but, but gets weirdly positioned... */
+ uiDefBlockBut(
+ block, menu_change_shortcut, but, "Change Shortcut",
+ 0, 0, uiLayoutGetWidth(layout), UI_UNIT_Y, "");
#endif
- but2 = uiDefIconTextBut(
- block, UI_BTYPE_BUT, 0, ICON_HAND,
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"),
- 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- UI_but_func_set(but2, popup_change_shortcut_func, but, NULL);
-
- but2 = uiDefIconTextBut(
- block, UI_BTYPE_BUT, 0, ICON_BLANK1,
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"),
- 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- UI_but_func_set(but2, remove_shortcut_func, but, NULL);
- }
- else {
- but2 = uiDefIconTextBut(
- block, UI_BTYPE_BUT, 0, ICON_HAND, IFACE_("Non-Keyboard Shortcut"),
- 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0,
- TIP_("Only keyboard shortcuts can be edited that way, "
- "please use User Preferences otherwise"));
- UI_but_flag_enable(but2, UI_BUT_DISABLED);
- }
- }
- /* only show 'assign' if there's a suitable key map for it to go in */
- else if (WM_keymap_guess_opname(C, but->optype->idname)) {
- but2 = uiDefIconTextBut(
- block, UI_BTYPE_BUT, 0, ICON_HAND,
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Assign Shortcut"),
- 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- UI_but_func_set(but2, popup_add_shortcut_func, but, NULL);
- }
-
- /* Set the operator pointer for python access */
- uiLayoutSetContextFromBut(layout, but);
-
- uiItemS(layout);
- }
-
- { /* Docs */
- char buf[512];
-
- if (UI_but_online_manual_id(but, buf, sizeof(buf))) {
- PointerRNA ptr_props;
- uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"),
- ICON_URL, "WM_OT_doc_view_manual_ui_context");
-
- if (U.flag & USER_DEVELOPER_UI) {
- uiItemFullO(
- layout, "WM_OT_doc_view",
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"),
- ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr_props);
- RNA_string_set(&ptr_props, "doc_id", buf);
- }
-
- /* XXX inactive option, not for public! */
+ but2 = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_HAND,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"),
+ 0,
+ 0,
+ w,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ UI_but_func_set(but2, popup_change_shortcut_func, but, NULL);
+
+ but2 = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_BLANK1,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"),
+ 0,
+ 0,
+ w,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ UI_but_func_set(but2, remove_shortcut_func, but, NULL);
+ }
+ else {
+ but2 = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_HAND,
+ IFACE_("Non-Keyboard Shortcut"),
+ 0,
+ 0,
+ w,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Only keyboard shortcuts can be edited that way, "
+ "please use User Preferences otherwise"));
+ UI_but_flag_enable(but2, UI_BUT_DISABLED);
+ }
+ }
+ /* only show 'assign' if there's a suitable key map for it to go in */
+ else if (WM_keymap_guess_opname(C, but->optype->idname)) {
+ but2 = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_HAND,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Assign Shortcut"),
+ 0,
+ 0,
+ w,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ UI_but_func_set(but2, popup_add_shortcut_func, but, NULL);
+ }
+
+ /* Set the operator pointer for python access */
+ uiLayoutSetContextFromBut(layout, but);
+
+ uiItemS(layout);
+ }
+
+ { /* Docs */
+ char buf[512];
+
+ if (UI_but_online_manual_id(but, buf, sizeof(buf))) {
+ PointerRNA ptr_props;
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"),
+ ICON_URL,
+ "WM_OT_doc_view_manual_ui_context");
+
+ if (U.flag & USER_DEVELOPER_UI) {
+ uiItemFullO(layout,
+ "WM_OT_doc_view",
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"),
+ ICON_NONE,
+ NULL,
+ WM_OP_EXEC_DEFAULT,
+ 0,
+ &ptr_props);
+ RNA_string_set(&ptr_props, "doc_id", buf);
+ }
+
+ /* XXX inactive option, not for public! */
#if 0
- uiItemFullO(
- layout, "WM_OT_doc_edit", "Submit Description", ICON_NONE,
- NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr_props);
- RNA_string_set(&ptr_props, "doc_id", buf);
- RNA_string_set(&ptr_props, "doc_new", RNA_property_description(but->rnaprop));
+ uiItemFullO(
+ layout, "WM_OT_doc_edit", "Submit Description", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr_props);
+ RNA_string_set(&ptr_props, "doc_id", buf);
+ RNA_string_set(&ptr_props, "doc_new", RNA_property_description(but->rnaprop));
#endif
- }
- }
-
- if (but->optype && U.flag & USER_DEVELOPER_UI) {
- uiItemO(layout, NULL,
- ICON_NONE, "UI_OT_copy_python_command_button");
- }
-
- /* perhaps we should move this into (G.debug & G_DEBUG) - campbell */
- if (U.flag & USER_DEVELOPER_UI) {
- if (ui_block_is_menu(but->block) == false) {
- uiItemFullO(layout, "UI_OT_editsource", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL);
- }
- }
-
- if (BKE_addon_find(&U.addons, "ui_translate")) {
- uiItemFullO(layout, "UI_OT_edittranslation_init", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL);
- }
-
- /* Show header tools for header buttons. */
- if (ui_block_is_popup_any(but->block) == false) {
- const ARegion *ar = CTX_wm_region(C);
-
- if (!ar) {
- /* skip */
- }
- else if (ar->regiontype == RGN_TYPE_HEADER) {
- uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL);
- }
- else if (ar->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) {
- uiItemMenuF(layout, IFACE_("Footer"), ICON_NONE, ED_screens_footer_tools_menu_create, NULL);
- }
- }
-
- MenuType *mt = WM_menutype_find("WM_MT_button_context", true);
- if (mt) {
- UI_menutype_draw(C, mt, uiLayoutColumn(layout, false));
- }
-
- return UI_popup_menu_end_or_cancel(C, pup);
+ }
+ }
+
+ if (but->optype && U.flag & USER_DEVELOPER_UI) {
+ uiItemO(layout, NULL, ICON_NONE, "UI_OT_copy_python_command_button");
+ }
+
+ /* perhaps we should move this into (G.debug & G_DEBUG) - campbell */
+ if (U.flag & USER_DEVELOPER_UI) {
+ if (ui_block_is_menu(but->block) == false) {
+ uiItemFullO(
+ layout, "UI_OT_editsource", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL);
+ }
+ }
+
+ if (BKE_addon_find(&U.addons, "ui_translate")) {
+ uiItemFullO(layout,
+ "UI_OT_edittranslation_init",
+ NULL,
+ ICON_NONE,
+ NULL,
+ WM_OP_INVOKE_DEFAULT,
+ 0,
+ NULL);
+ }
+
+ /* Show header tools for header buttons. */
+ if (ui_block_is_popup_any(but->block) == false) {
+ const ARegion *ar = CTX_wm_region(C);
+
+ if (!ar) {
+ /* skip */
+ }
+ else if (ar->regiontype == RGN_TYPE_HEADER) {
+ uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL);
+ }
+ else if (ar->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) {
+ uiItemMenuF(layout, IFACE_("Footer"), ICON_NONE, ED_screens_footer_tools_menu_create, NULL);
+ }
+ }
+
+ MenuType *mt = WM_menutype_find("WM_MT_button_context", true);
+ if (mt) {
+ UI_menutype_draw(C, mt, uiLayoutColumn(layout, false));
+ }
+
+ return UI_popup_menu_end_or_cancel(C, pup);
}
/** \} */
@@ -871,35 +1078,39 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
*/
void ui_popup_context_menu_for_panel(bContext *C, ARegion *ar, Panel *pa)
{
- bScreen *sc = CTX_wm_screen(C);
- const bool has_panel_category = UI_panel_category_is_visible(ar);
- const bool any_item_visible = has_panel_category;
- PointerRNA ptr;
- uiPopupMenu *pup;
- uiLayout *layout;
-
- if (!any_item_visible) {
- return;
- }
-
- RNA_pointer_create(&sc->id, &RNA_Panel, pa, &ptr);
-
- pup = UI_popup_menu_begin(C, IFACE_("Panel"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
-
- if (has_panel_category) {
- char tmpstr[80];
- BLI_snprintf(tmpstr, sizeof(tmpstr), "%s" UI_SEP_CHAR_S "%s", IFACE_("Pin"), IFACE_("Shift+Left Mouse"));
- uiItemR(layout, &ptr, "use_pin", 0, tmpstr, ICON_NONE);
-
- /* evil, force shortcut flag */
- {
- uiBlock *block = uiLayoutGetBlock(layout);
- uiBut *but = block->buttons.last;
- but->flag |= UI_BUT_HAS_SEP_CHAR;
- }
- }
- UI_popup_menu_end(C, pup);
+ bScreen *sc = CTX_wm_screen(C);
+ const bool has_panel_category = UI_panel_category_is_visible(ar);
+ const bool any_item_visible = has_panel_category;
+ PointerRNA ptr;
+ uiPopupMenu *pup;
+ uiLayout *layout;
+
+ if (!any_item_visible) {
+ return;
+ }
+
+ RNA_pointer_create(&sc->id, &RNA_Panel, pa, &ptr);
+
+ pup = UI_popup_menu_begin(C, IFACE_("Panel"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+
+ if (has_panel_category) {
+ char tmpstr[80];
+ BLI_snprintf(tmpstr,
+ sizeof(tmpstr),
+ "%s" UI_SEP_CHAR_S "%s",
+ IFACE_("Pin"),
+ IFACE_("Shift+Left Mouse"));
+ uiItemR(layout, &ptr, "use_pin", 0, tmpstr, ICON_NONE);
+
+ /* evil, force shortcut flag */
+ {
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiBut *but = block->buttons.last;
+ but->flag |= UI_BUT_HAS_SEP_CHAR;
+ }
+ }
+ UI_popup_menu_end(C, pup);
}
/** \} */
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 4185339cc92..0517278a149 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -21,7 +21,6 @@
* \ingroup edinterface
*/
-
#include <math.h>
#include <string.h>
@@ -39,7 +38,6 @@
#include "BKE_node.h"
#include "BKE_tracking.h"
-
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_colormanagement.h"
@@ -60,619 +58,668 @@
/* own include */
#include "interface_intern.h"
-
static int roundboxtype = UI_CNR_ALL;
void UI_draw_roundbox_corner_set(int type)
{
- /* Not sure the roundbox function is the best place to change this
- * if this is undone, it's not that big a deal, only makes curves edges
- * square for the */
- roundboxtype = type;
+ /* Not sure the roundbox function is the best place to change this
+ * if this is undone, it's not that big a deal, only makes curves edges
+ * square for the */
+ roundboxtype = type;
}
#if 0 /* unused */
int UI_draw_roundbox_corner_get(void)
{
- return roundboxtype;
+ return roundboxtype;
}
#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_3ubAlpha(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;
- colv[1] = ((float)col[1]) / 255;
- colv[2] = ((float)col[2]) / 255;
- colv[3] = ((float)alpha) / 255;
- UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv);
+ float colv[4];
+ colv[0] = ((float)col[0]) / 255;
+ colv[1] = ((float)col[1]) / 255;
+ colv[2] = ((float)col[2]) / 255;
+ colv[3] = ((float)alpha) / 255;
+ 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_3fvAlpha(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];
- colv[1] = col[1];
- colv[2] = col[2];
- colv[3] = alpha;
- UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv);
+ float colv[4];
+ colv[0] = col[0];
+ colv[1] = col[1];
+ colv[2] = col[2];
+ colv[3] = alpha;
+ UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv);
}
-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_aa(
+ bool filled, float minx, float miny, float maxx, float maxy, float rad, const float color[4])
{
- uiWidgetBaseParameters widget_params = {
- .recti.xmin = minx, .recti.ymin = miny,
- .recti.xmax = maxx, .recti.ymax = maxy,
- .radi = rad,
- .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
- .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
- .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
- .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
- .color_inner1[0] = color[0], .color_inner2[0] = color[0],
- .color_inner1[1] = color[1], .color_inner2[1] = color[1],
- .color_inner1[2] = color[2], .color_inner2[2] = color[2],
- .color_inner1[3] = color[3], .color_inner2[3] = color[3],
- .alpha_discard = 1.0f,
- };
-
- GPU_blend(true);
-
- if (filled) {
- /* plain antialiased filled box */
- widget_params.color_inner1[3] *= 0.125f;
- widget_params.color_inner2[3] *= 0.125f;
-
- /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space.
- * If it has been scaled, then it's no longer valid. */
- GPUBatch *batch = ui_batch_roundbox_get(filled, true);
- GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
- GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
- GPU_batch_draw(batch);
- }
- else {
- /* plain antialiased unfilled box */
- GPU_line_smooth(true);
-
- GPUBatch *batch = ui_batch_roundbox_get(filled, false);
- GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
- GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
- GPU_batch_draw(batch);
-
- GPU_line_smooth(false);
- }
-
- GPU_blend(false);
+ uiWidgetBaseParameters widget_params = {
+ .recti.xmin = minx,
+ .recti.ymin = miny,
+ .recti.xmax = maxx,
+ .recti.ymax = maxy,
+ .radi = rad,
+ .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
+ .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
+ .color_inner1[0] = color[0],
+ .color_inner2[0] = color[0],
+ .color_inner1[1] = color[1],
+ .color_inner2[1] = color[1],
+ .color_inner1[2] = color[2],
+ .color_inner2[2] = color[2],
+ .color_inner1[3] = color[3],
+ .color_inner2[3] = color[3],
+ .alpha_discard = 1.0f,
+ };
+
+ GPU_blend(true);
+
+ if (filled) {
+ /* plain antialiased filled box */
+ widget_params.color_inner1[3] *= 0.125f;
+ widget_params.color_inner2[3] *= 0.125f;
+
+ /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space.
+ * If it has been scaled, then it's no longer valid. */
+ GPUBatch *batch = ui_batch_roundbox_get(filled, true);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
+ GPU_batch_draw(batch);
+ }
+ else {
+ /* plain antialiased unfilled box */
+ GPU_line_smooth(true);
+
+ GPUBatch *batch = ui_batch_roundbox_get(filled, false);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
+ GPU_batch_draw(batch);
+
+ GPU_line_smooth(false);
+ }
+
+ GPU_blend(false);
}
-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_4fv(
+ bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[4])
{
#if 0
- float vec[7][2] = {
- {0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
- {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805},
- };
- int a;
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- /* mult */
- for (a = 0; a < 7; a++) {
- mul_v2_fl(vec[a], rad);
- }
-
- uint vert_len = 0;
- vert_len += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1;
- vert_len += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1;
- vert_len += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
- vert_len += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4fv(col);
-
- immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, vert_len);
- /* start with corner right-bottom */
- if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
- immVertex2f(pos, maxx - rad, miny);
- for (a = 0; a < 7; a++) {
- immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
- }
- immVertex2f(pos, maxx, miny + rad);
- }
- else {
- immVertex2f(pos, maxx, miny);
- }
-
- /* corner right-top */
- if (roundboxtype & UI_CNR_TOP_RIGHT) {
- immVertex2f(pos, maxx, maxy - rad);
- for (a = 0; a < 7; a++) {
- immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
- }
- immVertex2f(pos, maxx - rad, maxy);
- }
- else {
- immVertex2f(pos, maxx, maxy);
- }
-
- /* corner left-top */
- if (roundboxtype & UI_CNR_TOP_LEFT) {
- immVertex2f(pos, minx + rad, maxy);
- for (a = 0; a < 7; a++) {
- immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
- }
- immVertex2f(pos, minx, maxy - rad);
- }
- else {
- immVertex2f(pos, minx, maxy);
- }
-
- /* corner left-bottom */
- if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
- immVertex2f(pos, minx, miny + rad);
- for (a = 0; a < 7; a++) {
- immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
- }
- immVertex2f(pos, minx + rad, miny);
- }
- else {
- immVertex2f(pos, minx, miny);
- }
-
- immEnd();
- immUnbindProgram();
+ float vec[7][2] = {
+ {0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
+ {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805},
+ };
+ int a;
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ /* mult */
+ for (a = 0; a < 7; a++) {
+ mul_v2_fl(vec[a], rad);
+ }
+
+ uint vert_len = 0;
+ vert_len += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1;
+ vert_len += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1;
+ vert_len += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
+ vert_len += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(col);
+
+ immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, vert_len);
+ /* start with corner right-bottom */
+ if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
+ immVertex2f(pos, maxx - rad, miny);
+ for (a = 0; a < 7; a++) {
+ immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
+ }
+ immVertex2f(pos, maxx, miny + rad);
+ }
+ else {
+ immVertex2f(pos, maxx, miny);
+ }
+
+ /* corner right-top */
+ if (roundboxtype & UI_CNR_TOP_RIGHT) {
+ immVertex2f(pos, maxx, maxy - rad);
+ for (a = 0; a < 7; a++) {
+ immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
+ }
+ immVertex2f(pos, maxx - rad, maxy);
+ }
+ else {
+ immVertex2f(pos, maxx, maxy);
+ }
+
+ /* corner left-top */
+ if (roundboxtype & UI_CNR_TOP_LEFT) {
+ immVertex2f(pos, minx + rad, maxy);
+ for (a = 0; a < 7; a++) {
+ immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
+ }
+ immVertex2f(pos, minx, maxy - rad);
+ }
+ else {
+ immVertex2f(pos, minx, maxy);
+ }
+
+ /* corner left-bottom */
+ if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
+ immVertex2f(pos, minx, miny + rad);
+ for (a = 0; a < 7; a++) {
+ immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
+ }
+ immVertex2f(pos, minx + rad, miny);
+ }
+ else {
+ immVertex2f(pos, minx, miny);
+ }
+
+ immEnd();
+ immUnbindProgram();
#endif
- uiWidgetBaseParameters widget_params = {
- .recti.xmin = minx, .recti.ymin = miny,
- .recti.xmax = maxx, .recti.ymax = maxy,
- .radi = rad,
- .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
- .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
- .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
- .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
- .color_inner1[0] = col[0], .color_inner2[0] = col[0],
- .color_inner1[1] = col[1], .color_inner2[1] = col[1],
- .color_inner1[2] = col[2], .color_inner2[2] = col[2],
- .color_inner1[3] = col[3], .color_inner2[3] = col[3],
- .alpha_discard = 1.0f,
- };
-
- GPUBatch *batch = ui_batch_roundbox_get(filled, false);
- GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
- GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
- GPU_batch_draw(batch);
+ uiWidgetBaseParameters widget_params = {
+ .recti.xmin = minx,
+ .recti.ymin = miny,
+ .recti.xmax = maxx,
+ .recti.ymax = maxy,
+ .radi = rad,
+ .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
+ .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
+ .color_inner1[0] = col[0],
+ .color_inner2[0] = col[0],
+ .color_inner1[1] = col[1],
+ .color_inner2[1] = col[1],
+ .color_inner1[2] = col[2],
+ .color_inner2[2] = col[2],
+ .color_inner1[3] = col[3],
+ .color_inner2[3] = col[3],
+ .alpha_discard = 1.0f,
+ };
+
+ GPUBatch *batch = ui_batch_roundbox_get(filled, false);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
+ GPU_batch_draw(batch);
}
#if 0
static void round_box_shade_col(uint attr, const float col1[3], float const col2[3], const float fac)
{
- float col[4] = {
- fac * col1[0] + (1.0f - fac) * col2[0],
- fac * col1[1] + (1.0f - fac) * col2[1],
- fac * col1[2] + (1.0f - fac) * col2[2],
- 1.0f,
- };
- immAttr4fv(attr, col);
+ float col[4] = {
+ fac * col1[0] + (1.0f - fac) * col2[0],
+ fac * col1[1] + (1.0f - fac) * col2[1],
+ fac * col1[2] + (1.0f - fac) * col2[2],
+ 1.0f,
+ };
+ immAttr4fv(attr, col);
}
#endif
/* linear horizontal shade within button or in outline */
/* view2d scrollers use it */
-void UI_draw_roundbox_shade_x(
- bool filled, float minx, float miny, float maxx, float maxy,
- float rad, float shadetop, float shadedown, const float col[4])
+void UI_draw_roundbox_shade_x(bool filled,
+ float minx,
+ float miny,
+ float maxx,
+ float maxy,
+ float rad,
+ float shadetop,
+ float shadedown,
+ const float col[4])
{
#if 0
- float vec[7][2] = {
- {0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
- {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805},
- };
- const float div = maxy - miny;
- const float idiv = 1.0f / div;
- float coltop[3], coldown[3];
- int vert_count = 0;
- int a;
-
- GPUVertFormat *format = immVertexFormat();
- 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, 4, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
-
- /* mult */
- for (a = 0; a < 7; a++) {
- mul_v2_fl(vec[a], rad);
- }
-
- /* 'shade' defines strength of shading */
- coltop[0] = min_ff(1.0f, col[0] + shadetop);
- coltop[1] = min_ff(1.0f, col[1] + shadetop);
- coltop[2] = min_ff(1.0f, col[2] + shadetop);
- coldown[0] = max_ff(0.0f, col[0] + shadedown);
- coldown[1] = max_ff(0.0f, col[1] + shadedown);
- coldown[2] = max_ff(0.0f, col[2] + shadedown);
-
- vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1;
- vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1;
- vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
- vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
-
- immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, vert_count);
-
- /* start with corner right-bottom */
- if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
-
- round_box_shade_col(color, coltop, coldown, 0.0);
- immVertex2f(pos, maxx - rad, miny);
-
- for (a = 0; a < 7; a++) {
- round_box_shade_col(color, coltop, coldown, vec[a][1] * idiv);
- immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
- }
-
- round_box_shade_col(color, coltop, coldown, rad * idiv);
- immVertex2f(pos, maxx, miny + rad);
- }
- else {
- round_box_shade_col(color, coltop, coldown, 0.0);
- immVertex2f(pos, maxx, miny);
- }
-
- /* corner right-top */
- if (roundboxtype & UI_CNR_TOP_RIGHT) {
-
- round_box_shade_col(color, coltop, coldown, (div - rad) * idiv);
- immVertex2f(pos, maxx, maxy - rad);
-
- for (a = 0; a < 7; a++) {
- round_box_shade_col(color, coltop, coldown, (div - rad + vec[a][1]) * idiv);
- immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
- }
- round_box_shade_col(color, coltop, coldown, 1.0);
- immVertex2f(pos, maxx - rad, maxy);
- }
- else {
- round_box_shade_col(color, coltop, coldown, 1.0);
- immVertex2f(pos, maxx, maxy);
- }
-
- /* corner left-top */
- if (roundboxtype & UI_CNR_TOP_LEFT) {
-
- round_box_shade_col(color, coltop, coldown, 1.0);
- immVertex2f(pos, minx + rad, maxy);
-
- for (a = 0; a < 7; a++) {
- round_box_shade_col(color, coltop, coldown, (div - vec[a][1]) * idiv);
- immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
- }
-
- round_box_shade_col(color, coltop, coldown, (div - rad) * idiv);
- immVertex2f(pos, minx, maxy - rad);
- }
- else {
- round_box_shade_col(color, coltop, coldown, 1.0);
- immVertex2f(pos, minx, maxy);
- }
-
- /* corner left-bottom */
- if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
-
- round_box_shade_col(color, coltop, coldown, rad * idiv);
- immVertex2f(pos, minx, miny + rad);
-
- for (a = 0; a < 7; a++) {
- round_box_shade_col(color, coltop, coldown, (rad - vec[a][1]) * idiv);
- immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
- }
-
- round_box_shade_col(color, coltop, coldown, 0.0);
- immVertex2f(pos, minx + rad, miny);
- }
- else {
- round_box_shade_col(color, coltop, coldown, 0.0);
- immVertex2f(pos, minx, miny);
- }
-
- immEnd();
- immUnbindProgram();
+ float vec[7][2] = {
+ {0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
+ {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805},
+ };
+ const float div = maxy - miny;
+ const float idiv = 1.0f / div;
+ float coltop[3], coldown[3];
+ int vert_count = 0;
+ int a;
+
+ GPUVertFormat *format = immVertexFormat();
+ 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, 4, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ /* mult */
+ for (a = 0; a < 7; a++) {
+ mul_v2_fl(vec[a], rad);
+ }
+
+ /* 'shade' defines strength of shading */
+ coltop[0] = min_ff(1.0f, col[0] + shadetop);
+ coltop[1] = min_ff(1.0f, col[1] + shadetop);
+ coltop[2] = min_ff(1.0f, col[2] + shadetop);
+ coldown[0] = max_ff(0.0f, col[0] + shadedown);
+ coldown[1] = max_ff(0.0f, col[1] + shadedown);
+ coldown[2] = max_ff(0.0f, col[2] + shadedown);
+
+ vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1;
+ vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1;
+ vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
+ vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
+
+ immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, vert_count);
+
+ /* start with corner right-bottom */
+ if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
+
+ round_box_shade_col(color, coltop, coldown, 0.0);
+ immVertex2f(pos, maxx - rad, miny);
+
+ for (a = 0; a < 7; a++) {
+ round_box_shade_col(color, coltop, coldown, vec[a][1] * idiv);
+ immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
+ }
+
+ round_box_shade_col(color, coltop, coldown, rad * idiv);
+ immVertex2f(pos, maxx, miny + rad);
+ }
+ else {
+ round_box_shade_col(color, coltop, coldown, 0.0);
+ immVertex2f(pos, maxx, miny);
+ }
+
+ /* corner right-top */
+ if (roundboxtype & UI_CNR_TOP_RIGHT) {
+
+ round_box_shade_col(color, coltop, coldown, (div - rad) * idiv);
+ immVertex2f(pos, maxx, maxy - rad);
+
+ for (a = 0; a < 7; a++) {
+ round_box_shade_col(color, coltop, coldown, (div - rad + vec[a][1]) * idiv);
+ immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
+ }
+ round_box_shade_col(color, coltop, coldown, 1.0);
+ immVertex2f(pos, maxx - rad, maxy);
+ }
+ else {
+ round_box_shade_col(color, coltop, coldown, 1.0);
+ immVertex2f(pos, maxx, maxy);
+ }
+
+ /* corner left-top */
+ if (roundboxtype & UI_CNR_TOP_LEFT) {
+
+ round_box_shade_col(color, coltop, coldown, 1.0);
+ immVertex2f(pos, minx + rad, maxy);
+
+ for (a = 0; a < 7; a++) {
+ round_box_shade_col(color, coltop, coldown, (div - vec[a][1]) * idiv);
+ immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
+ }
+
+ round_box_shade_col(color, coltop, coldown, (div - rad) * idiv);
+ immVertex2f(pos, minx, maxy - rad);
+ }
+ else {
+ round_box_shade_col(color, coltop, coldown, 1.0);
+ immVertex2f(pos, minx, maxy);
+ }
+
+ /* corner left-bottom */
+ if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
+
+ round_box_shade_col(color, coltop, coldown, rad * idiv);
+ immVertex2f(pos, minx, miny + rad);
+
+ for (a = 0; a < 7; a++) {
+ round_box_shade_col(color, coltop, coldown, (rad - vec[a][1]) * idiv);
+ immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
+ }
+
+ round_box_shade_col(color, coltop, coldown, 0.0);
+ immVertex2f(pos, minx + rad, miny);
+ }
+ else {
+ round_box_shade_col(color, coltop, coldown, 0.0);
+ immVertex2f(pos, minx, miny);
+ }
+
+ immEnd();
+ immUnbindProgram();
#endif
- uiWidgetBaseParameters widget_params = {
- .recti.xmin = minx, .recti.ymin = miny,
- .recti.xmax = maxx, .recti.ymax = maxy,
- .radi = rad,
- .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
- .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
- .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
- .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
- .color_inner1[0] = min_ff(1.0f, col[0] + shadetop),
- .color_inner2[0] = max_ff(0.0f, col[0] + shadedown),
- .color_inner1[1] = min_ff(1.0f, col[1] + shadetop),
- .color_inner2[1] = max_ff(0.0f, col[1] + shadedown),
- .color_inner1[2] = min_ff(1.0f, col[2] + shadetop),
- .color_inner2[2] = max_ff(0.0f, col[2] + shadedown),
- .color_inner1[3] = 1.0f,
- .color_inner2[3] = 1.0f,
- .alpha_discard = 1.0f,
- };
-
- GPUBatch *batch = ui_batch_roundbox_get(filled, false);
- GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
- GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
- GPU_batch_draw(batch);
+ uiWidgetBaseParameters widget_params = {
+ .recti.xmin = minx,
+ .recti.ymin = miny,
+ .recti.xmax = maxx,
+ .recti.ymax = maxy,
+ .radi = rad,
+ .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
+ .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
+ .color_inner1[0] = min_ff(1.0f, col[0] + shadetop),
+ .color_inner2[0] = max_ff(0.0f, col[0] + shadedown),
+ .color_inner1[1] = min_ff(1.0f, col[1] + shadetop),
+ .color_inner2[1] = max_ff(0.0f, col[1] + shadedown),
+ .color_inner1[2] = min_ff(1.0f, col[2] + shadetop),
+ .color_inner2[2] = max_ff(0.0f, col[2] + shadedown),
+ .color_inner1[3] = 1.0f,
+ .color_inner2[3] = 1.0f,
+ .alpha_discard = 1.0f,
+ };
+
+ GPUBatch *batch = ui_batch_roundbox_get(filled, false);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
+ GPU_batch_draw(batch);
}
-#if 0 /* unused */
+#if 0 /* unused */
/* linear vertical shade within button or in outline */
/* view2d scrollers use it */
void UI_draw_roundbox_shade_y(
bool filled, float minx, float miny, float maxx, float maxy,
float rad, float shadeleft, float shaderight, const float col[4])
{
- float vec[7][2] = {
- {0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
- {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805},
- };
- const float div = maxx - minx;
- const float idiv = 1.0f / div;
- float colLeft[3], colRight[3];
- int vert_count = 0;
- int a;
-
- /* mult */
- for (a = 0; a < 7; a++) {
- mul_v2_fl(vec[a], rad);
- }
-
- GPUVertFormat *format = immVertexFormat();
- 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, 4, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
-
- /* 'shade' defines strength of shading */
- colLeft[0] = min_ff(1.0f, col[0] + shadeleft);
- colLeft[1] = min_ff(1.0f, col[1] + shadeleft);
- colLeft[2] = min_ff(1.0f, col[2] + shadeleft);
- colRight[0] = max_ff(0.0f, col[0] + shaderight);
- colRight[1] = max_ff(0.0f, col[1] + shaderight);
- colRight[2] = max_ff(0.0f, col[2] + shaderight);
-
-
- vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1;
- vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1;
- vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
- vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
-
- immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, vert_count);
-
- /* start with corner right-bottom */
- if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
- round_box_shade_col(color, colLeft, colRight, 0.0);
- immVertex2f(pos, maxx - rad, miny);
-
- for (a = 0; a < 7; a++) {
- round_box_shade_col(color, colLeft, colRight, vec[a][0] * idiv);
- immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
- }
-
- round_box_shade_col(color, colLeft, colRight, rad * idiv);
- immVertex2f(pos, maxx, miny + rad);
- }
- else {
- round_box_shade_col(color, colLeft, colRight, 0.0);
- immVertex2f(pos, maxx, miny);
- }
-
- /* corner right-top */
- if (roundboxtype & UI_CNR_TOP_RIGHT) {
- round_box_shade_col(color, colLeft, colRight, 0.0);
- immVertex2f(pos, maxx, maxy - rad);
-
- for (a = 0; a < 7; a++) {
-
- round_box_shade_col(color, colLeft, colRight, (div - rad - vec[a][0]) * idiv);
- immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
- }
- round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv);
- immVertex2f(pos, maxx - rad, maxy);
- }
- else {
- round_box_shade_col(color, colLeft, colRight, 0.0);
- immVertex2f(pos, maxx, maxy);
- }
-
- /* corner left-top */
- if (roundboxtype & UI_CNR_TOP_LEFT) {
- round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv);
- immVertex2f(pos, minx + rad, maxy);
-
- for (a = 0; a < 7; a++) {
- round_box_shade_col(color, colLeft, colRight, (div - rad + vec[a][0]) * idiv);
- immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
- }
-
- round_box_shade_col(color, colLeft, colRight, 1.0);
- immVertex2f(pos, minx, maxy - rad);
- }
- else {
- round_box_shade_col(color, colLeft, colRight, 1.0);
- immVertex2f(pos, minx, maxy);
- }
-
- /* corner left-bottom */
- if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
- round_box_shade_col(color, colLeft, colRight, 1.0);
- immVertex2f(pos, minx, miny + rad);
-
- for (a = 0; a < 7; a++) {
- round_box_shade_col(color, colLeft, colRight, (vec[a][0]) * idiv);
- immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
- }
-
- round_box_shade_col(color, colLeft, colRight, 1.0);
- immVertex2f(pos, minx + rad, miny);
- }
- else {
- round_box_shade_col(color, colLeft, colRight, 1.0);
- immVertex2f(pos, minx, miny);
- }
-
- immEnd();
- immUnbindProgram();
+ float vec[7][2] = {
+ {0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
+ {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805},
+ };
+ const float div = maxx - minx;
+ const float idiv = 1.0f / div;
+ float colLeft[3], colRight[3];
+ int vert_count = 0;
+ int a;
+
+ /* mult */
+ for (a = 0; a < 7; a++) {
+ mul_v2_fl(vec[a], rad);
+ }
+
+ GPUVertFormat *format = immVertexFormat();
+ 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, 4, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ /* 'shade' defines strength of shading */
+ colLeft[0] = min_ff(1.0f, col[0] + shadeleft);
+ colLeft[1] = min_ff(1.0f, col[1] + shadeleft);
+ colLeft[2] = min_ff(1.0f, col[2] + shadeleft);
+ colRight[0] = max_ff(0.0f, col[0] + shaderight);
+ colRight[1] = max_ff(0.0f, col[1] + shaderight);
+ colRight[2] = max_ff(0.0f, col[2] + shaderight);
+
+
+ vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1;
+ vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1;
+ vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
+ vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
+
+ immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, vert_count);
+
+ /* start with corner right-bottom */
+ if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
+ round_box_shade_col(color, colLeft, colRight, 0.0);
+ immVertex2f(pos, maxx - rad, miny);
+
+ for (a = 0; a < 7; a++) {
+ round_box_shade_col(color, colLeft, colRight, vec[a][0] * idiv);
+ immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
+ }
+
+ round_box_shade_col(color, colLeft, colRight, rad * idiv);
+ immVertex2f(pos, maxx, miny + rad);
+ }
+ else {
+ round_box_shade_col(color, colLeft, colRight, 0.0);
+ immVertex2f(pos, maxx, miny);
+ }
+
+ /* corner right-top */
+ if (roundboxtype & UI_CNR_TOP_RIGHT) {
+ round_box_shade_col(color, colLeft, colRight, 0.0);
+ immVertex2f(pos, maxx, maxy - rad);
+
+ for (a = 0; a < 7; a++) {
+
+ round_box_shade_col(color, colLeft, colRight, (div - rad - vec[a][0]) * idiv);
+ immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
+ }
+ round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv);
+ immVertex2f(pos, maxx - rad, maxy);
+ }
+ else {
+ round_box_shade_col(color, colLeft, colRight, 0.0);
+ immVertex2f(pos, maxx, maxy);
+ }
+
+ /* corner left-top */
+ if (roundboxtype & UI_CNR_TOP_LEFT) {
+ round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv);
+ immVertex2f(pos, minx + rad, maxy);
+
+ for (a = 0; a < 7; a++) {
+ round_box_shade_col(color, colLeft, colRight, (div - rad + vec[a][0]) * idiv);
+ immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
+ }
+
+ round_box_shade_col(color, colLeft, colRight, 1.0);
+ immVertex2f(pos, minx, maxy - rad);
+ }
+ else {
+ round_box_shade_col(color, colLeft, colRight, 1.0);
+ immVertex2f(pos, minx, maxy);
+ }
+
+ /* corner left-bottom */
+ if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
+ round_box_shade_col(color, colLeft, colRight, 1.0);
+ immVertex2f(pos, minx, miny + rad);
+
+ for (a = 0; a < 7; a++) {
+ round_box_shade_col(color, colLeft, colRight, (vec[a][0]) * idiv);
+ immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
+ }
+
+ round_box_shade_col(color, colLeft, colRight, 1.0);
+ immVertex2f(pos, minx + rad, miny);
+ }
+ else {
+ round_box_shade_col(color, colLeft, colRight, 1.0);
+ immVertex2f(pos, minx, miny);
+ }
+
+ immEnd();
+ immUnbindProgram();
}
#endif /* unused */
void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const float color[4])
{
- int ofs_y = 4 * U.pixelsize;
+ int ofs_y = 4 * U.pixelsize;
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4fv(color);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
- immRecti(pos, pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize));
- immUnbindProgram();
+ immRecti(pos, pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize));
+ immUnbindProgram();
}
/* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */
/* based on UI_draw_roundbox_gl_mode,
* check on making a version which allows us to skip some sides */
-void ui_draw_but_TAB_outline(const rcti *rect, float rad, uchar highlight[3], uchar highlight_fade[3])
+void ui_draw_but_TAB_outline(const rcti *rect,
+ float rad,
+ uchar highlight[3],
+ uchar highlight_fade[3])
{
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
- /* add a 1px offset, looks nicer */
- const int minx = rect->xmin + U.pixelsize, maxx = rect->xmax - U.pixelsize;
- const int miny = rect->ymin + U.pixelsize, maxy = rect->ymax - U.pixelsize;
- int a;
- float vec[4][2] = {
- {0.195, 0.02},
- {0.55, 0.169},
- {0.831, 0.45},
- {0.98, 0.805},
- };
-
-
- /* mult */
- for (a = 0; a < 4; a++) {
- mul_v2_fl(vec[a], rad);
- }
-
- immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
- immBeginAtMost(GPU_PRIM_LINE_STRIP, 25);
-
- immAttr3ubv(col, highlight);
-
- /* start with corner left-top */
- if (roundboxtype & UI_CNR_TOP_LEFT) {
- immVertex2f(pos, minx, maxy - rad);
- for (a = 0; a < 4; a++) {
- immVertex2f(pos, minx + vec[a][1], maxy - rad + vec[a][0]);
- }
- immVertex2f(pos, minx + rad, maxy);
- }
- else {
- immVertex2f(pos, minx, maxy);
- }
-
- /* corner right-top */
- if (roundboxtype & UI_CNR_TOP_RIGHT) {
- immVertex2f(pos, maxx - rad, maxy);
- for (a = 0; a < 4; a++) {
- immVertex2f(pos, maxx - rad + vec[a][0], maxy - vec[a][1]);
- }
- immVertex2f(pos, maxx, maxy - rad);
- }
- else {
- immVertex2f(pos, maxx, maxy);
- }
-
- immAttr3ubv(col, highlight_fade);
-
- /* corner right-bottom */
- if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
- immVertex2f(pos, maxx, miny + rad);
- for (a = 0; a < 4; a++) {
- immVertex2f(pos, maxx - vec[a][1], miny + rad - vec[a][0]);
- }
- immVertex2f(pos, maxx - rad, miny);
- }
- else {
- immVertex2f(pos, maxx, miny);
- }
-
- /* corner left-bottom */
- if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
- immVertex2f(pos, minx + rad, miny);
- for (a = 0; a < 4; a++) {
- immVertex2f(pos, minx + rad - vec[a][0], miny + vec[a][1]);
- }
- immVertex2f(pos, minx, miny + rad);
- }
- else {
- immVertex2f(pos, minx, miny);
- }
-
- immAttr3ubv(col, highlight);
-
- /* back to corner left-top */
- immVertex2f(pos, minx, (roundboxtype & UI_CNR_TOP_LEFT) ? (maxy - rad) : maxy);
-
- immEnd();
- immUnbindProgram();
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ /* add a 1px offset, looks nicer */
+ const int minx = rect->xmin + U.pixelsize, maxx = rect->xmax - U.pixelsize;
+ const int miny = rect->ymin + U.pixelsize, maxy = rect->ymax - U.pixelsize;
+ int a;
+ float vec[4][2] = {
+ {0.195, 0.02},
+ {0.55, 0.169},
+ {0.831, 0.45},
+ {0.98, 0.805},
+ };
+
+ /* mult */
+ for (a = 0; a < 4; a++) {
+ mul_v2_fl(vec[a], rad);
+ }
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, 25);
+
+ immAttr3ubv(col, highlight);
+
+ /* start with corner left-top */
+ if (roundboxtype & UI_CNR_TOP_LEFT) {
+ immVertex2f(pos, minx, maxy - rad);
+ for (a = 0; a < 4; a++) {
+ immVertex2f(pos, minx + vec[a][1], maxy - rad + vec[a][0]);
+ }
+ immVertex2f(pos, minx + rad, maxy);
+ }
+ else {
+ immVertex2f(pos, minx, maxy);
+ }
+
+ /* corner right-top */
+ if (roundboxtype & UI_CNR_TOP_RIGHT) {
+ immVertex2f(pos, maxx - rad, maxy);
+ for (a = 0; a < 4; a++) {
+ immVertex2f(pos, maxx - rad + vec[a][0], maxy - vec[a][1]);
+ }
+ immVertex2f(pos, maxx, maxy - rad);
+ }
+ else {
+ immVertex2f(pos, maxx, maxy);
+ }
+
+ immAttr3ubv(col, highlight_fade);
+
+ /* corner right-bottom */
+ if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
+ immVertex2f(pos, maxx, miny + rad);
+ for (a = 0; a < 4; a++) {
+ immVertex2f(pos, maxx - vec[a][1], miny + rad - vec[a][0]);
+ }
+ immVertex2f(pos, maxx - rad, miny);
+ }
+ else {
+ immVertex2f(pos, maxx, miny);
+ }
+
+ /* corner left-bottom */
+ if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
+ immVertex2f(pos, minx + rad, miny);
+ for (a = 0; a < 4; a++) {
+ immVertex2f(pos, minx + rad - vec[a][0], miny + vec[a][1]);
+ }
+ immVertex2f(pos, minx, miny + rad);
+ }
+ else {
+ immVertex2f(pos, minx, miny);
+ }
+
+ immAttr3ubv(col, highlight);
+
+ /* back to corner left-top */
+ immVertex2f(pos, minx, (roundboxtype & UI_CNR_TOP_LEFT) ? (maxy - rad) : maxy);
+
+ immEnd();
+ immUnbindProgram();
}
-void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, const uiWidgetColors *UNUSED(wcol), const rcti *rect)
+void ui_draw_but_IMAGE(ARegion *UNUSED(ar),
+ uiBut *but,
+ const uiWidgetColors *UNUSED(wcol),
+ const rcti *rect)
{
#ifdef WITH_HEADLESS
- (void)rect;
- (void)but;
+ (void)rect;
+ (void)but;
#else
- ImBuf *ibuf = (ImBuf *)but->poin;
-
- if (!ibuf) {
- return;
- }
-
- float facx = 1.0f;
- float facy = 1.0f;
-
- int w = BLI_rcti_size_x(rect);
- int h = BLI_rcti_size_y(rect);
-
- /* scissor doesn't seem to be doing the right thing...? */
-#if 0
- /* prevent drawing outside widget area */
- int scissor[4];
- GPU_scissor_get_i(scissor);
- GPU_scissor(rect->xmin, rect->ymin, w, h);
-#endif
-
- GPU_blend(true);
-
- if (w != ibuf->x || h != ibuf->y) {
- facx = (float)w / (float)ibuf->x;
- facy = (float)h / (float)ibuf->y;
- }
-
- IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
- immDrawPixelsTex(
- &state, (float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect,
- facx, facy, NULL);
-
- GPU_blend(false);
-
-#if 0
- // restore scissortest
- GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
-#endif
+ ImBuf *ibuf = (ImBuf *)but->poin;
+
+ if (!ibuf) {
+ return;
+ }
+
+ float facx = 1.0f;
+ float facy = 1.0f;
+
+ int w = BLI_rcti_size_x(rect);
+ int h = BLI_rcti_size_y(rect);
+
+ /* scissor doesn't seem to be doing the right thing...? */
+# if 0
+ /* prevent drawing outside widget area */
+ int scissor[4];
+ GPU_scissor_get_i(scissor);
+ GPU_scissor(rect->xmin, rect->ymin, w, h);
+# endif
+
+ GPU_blend(true);
+
+ if (w != ibuf->x || h != ibuf->y) {
+ facx = (float)w / (float)ibuf->x;
+ facy = (float)h / (float)ibuf->y;
+ }
+
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(&state,
+ (float)rect->xmin,
+ (float)rect->ymin,
+ ibuf->x,
+ ibuf->y,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ GL_NEAREST,
+ ibuf->rect,
+ facx,
+ facy,
+ NULL);
+
+ GPU_blend(false);
+
+# if 0
+ // restore scissortest
+ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+# endif
#endif
}
@@ -687,1468 +734,1599 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, const uiWidgetColors *UN
*
* The next 4 parameters are the offsets for the view, not the zones.
*/
-void UI_draw_safe_areas(
- uint pos, float x1, float x2, float y1, float y2,
- const float title_aspect[2], const float action_aspect[2])
+void UI_draw_safe_areas(uint pos,
+ float x1,
+ float x2,
+ float y1,
+ float y2,
+ const float title_aspect[2],
+ const float action_aspect[2])
{
- const float size_x_half = (x2 - x1) * 0.5f;
- const float size_y_half = (y2 - y1) * 0.5f;
+ const float size_x_half = (x2 - x1) * 0.5f;
+ const float size_y_half = (y2 - y1) * 0.5f;
- const float *safe_areas[] = {title_aspect, action_aspect};
- const int safe_len = ARRAY_SIZE(safe_areas);
+ const float *safe_areas[] = {title_aspect, action_aspect};
+ const int safe_len = ARRAY_SIZE(safe_areas);
- for (int i = 0; i < safe_len; i++) {
- if (safe_areas[i][0] || safe_areas[i][1]) {
- float margin_x = safe_areas[i][0] * size_x_half;
- float margin_y = safe_areas[i][1] * size_y_half;
+ for (int i = 0; i < safe_len; i++) {
+ if (safe_areas[i][0] || safe_areas[i][1]) {
+ float margin_x = safe_areas[i][0] * size_x_half;
+ float margin_y = safe_areas[i][1] * size_y_half;
- float minx = x1 + margin_x;
- float miny = y1 + margin_y;
- float maxx = x2 - margin_x;
- float maxy = y2 - margin_y;
+ float minx = x1 + margin_x;
+ float miny = y1 + margin_y;
+ float maxx = x2 - margin_x;
+ float maxy = y2 - margin_y;
- imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy);
- }
- }
+ imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy);
+ }
+ }
}
-
static void draw_scope_end(const rctf *rect, GLint *scissor)
{
- /* restore scissortest */
- GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+ /* restore scissortest */
+ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- /* outline */
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- float color[4] = {0.0f, 0.0f, 0.0f, 0.5f};
- UI_draw_roundbox_4fv(false, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f, color);
+ /* outline */
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.5f};
+ UI_draw_roundbox_4fv(
+ false, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f, color);
}
-static void histogram_draw_one(
- float r, float g, float b, float alpha,
- float x, float y, float w, float h, const float *data, int res, const bool is_line,
- uint pos_attr)
+static void histogram_draw_one(float r,
+ float g,
+ float b,
+ float alpha,
+ float x,
+ float y,
+ float w,
+ float h,
+ const float *data,
+ int res,
+ const bool is_line,
+ uint pos_attr)
{
- float color[4] = {r, g, b, alpha};
-
- /* that can happen */
- if (res == 0) {
- return;
- }
-
- GPU_line_smooth(true);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE);
-
- immUniformColor4fv(color);
-
- if (is_line) {
- /* curve outline */
- GPU_line_width(1.5);
-
- immBegin(GPU_PRIM_LINE_STRIP, res);
- for (int i = 0; i < res; i++) {
- float x2 = x + i * (w / (float)res);
- immVertex2f(pos_attr, x2, y + (data[i] * h));
- }
- immEnd();
- }
- else {
- /* under the curve */
- immBegin(GPU_PRIM_TRI_STRIP, res * 2);
- immVertex2f(pos_attr, x, y);
- immVertex2f(pos_attr, x, y + (data[0] * h));
- for (int i = 1; i < res; i++) {
- float x2 = x + i * (w / (float)res);
- immVertex2f(pos_attr, x2, y + (data[i] * h));
- immVertex2f(pos_attr, x2, y);
- }
- immEnd();
-
- /* curve outline */
- immUniformColor4f(0.0f, 0.0f, 0.0f, 0.25f);
-
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- immBegin(GPU_PRIM_LINE_STRIP, res);
- for (int i = 0; i < res; i++) {
- float x2 = x + i * (w / (float)res);
- immVertex2f(pos_attr, x2, y + (data[i] * h));
- }
- immEnd();
- }
-
- GPU_line_smooth(false);
+ float color[4] = {r, g, b, alpha};
+
+ /* that can happen */
+ if (res == 0) {
+ return;
+ }
+
+ GPU_line_smooth(true);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE);
+
+ immUniformColor4fv(color);
+
+ if (is_line) {
+ /* curve outline */
+ GPU_line_width(1.5);
+
+ immBegin(GPU_PRIM_LINE_STRIP, res);
+ for (int i = 0; i < res; i++) {
+ float x2 = x + i * (w / (float)res);
+ immVertex2f(pos_attr, x2, y + (data[i] * h));
+ }
+ immEnd();
+ }
+ else {
+ /* under the curve */
+ immBegin(GPU_PRIM_TRI_STRIP, res * 2);
+ immVertex2f(pos_attr, x, y);
+ immVertex2f(pos_attr, x, y + (data[0] * h));
+ for (int i = 1; i < res; i++) {
+ float x2 = x + i * (w / (float)res);
+ immVertex2f(pos_attr, x2, y + (data[i] * h));
+ immVertex2f(pos_attr, x2, y);
+ }
+ immEnd();
+
+ /* curve outline */
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.25f);
+
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ immBegin(GPU_PRIM_LINE_STRIP, res);
+ for (int i = 0; i < res; i++) {
+ float x2 = x + i * (w / (float)res);
+ immVertex2f(pos_attr, x2, y + (data[i] * h));
+ }
+ immEnd();
+ }
+
+ GPU_line_smooth(false);
}
#define HISTOGRAM_TOT_GRID_LINES 4
-void ui_draw_but_HISTOGRAM(ARegion *UNUSED(ar), uiBut *but, const uiWidgetColors *UNUSED(wcol), const rcti *recti)
+void ui_draw_but_HISTOGRAM(ARegion *UNUSED(ar),
+ uiBut *but,
+ const uiWidgetColors *UNUSED(wcol),
+ const rcti *recti)
{
- Histogram *hist = (Histogram *)but->poin;
- int res = hist->x_resolution;
- const bool is_line = (hist->flag & HISTO_FLAG_LINE) != 0;
-
- rctf rect = {
- .xmin = (float)recti->xmin + 1,
- .xmax = (float)recti->xmax - 1,
- .ymin = (float)recti->ymin + 1,
- .ymax = (float)recti->ymax - 1,
- };
-
- float w = BLI_rctf_size_x(&rect);
- float h = BLI_rctf_size_y(&rect) * hist->ymax;
-
- 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];
- UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
-
- /* need scissor test, histogram can draw outside of boundary */
- int scissor[4];
- GPU_scissor_get_i(scissor);
- GPU_scissor(
- (rect.xmin - 1),
- (rect.ymin - 1),
- (rect.xmax + 1) - (rect.xmin - 1),
- (rect.ymax + 1) - (rect.ymin - 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);
-
- immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
- /* draw grid lines here */
- for (int i = 1; i <= HISTOGRAM_TOT_GRID_LINES; i++) {
- const float fac = (float)i / (float)HISTOGRAM_TOT_GRID_LINES;
-
- /* so we can tell the 1.0 color point */
- if (i == HISTOGRAM_TOT_GRID_LINES) {
- immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
- }
-
- immBegin(GPU_PRIM_LINES, 4);
-
- immVertex2f(pos, rect.xmin, rect.ymin + fac * h);
- immVertex2f(pos, rect.xmax, rect.ymin + fac * h);
-
- immVertex2f(pos, rect.xmin + fac * w, rect.ymin);
- immVertex2f(pos, rect.xmin + fac * w, rect.ymax);
-
- immEnd();
- }
-
- if (hist->mode == HISTO_MODE_LUMA) {
- histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res, is_line, pos);
- }
- else if (hist->mode == HISTO_MODE_ALPHA) {
- histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_a, res, is_line, pos);
- }
- else {
- if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_R) {
- histogram_draw_one(1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res, is_line, pos);
- }
- if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_G) {
- histogram_draw_one(0.0, 1.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_g, res, is_line, pos);
- }
- if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_B) {
- histogram_draw_one(0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res, is_line, pos);
- }
- }
-
- immUnbindProgram();
-
- /* outline */
- draw_scope_end(&rect, scissor);
+ Histogram *hist = (Histogram *)but->poin;
+ int res = hist->x_resolution;
+ const bool is_line = (hist->flag & HISTO_FLAG_LINE) != 0;
+
+ rctf rect = {
+ .xmin = (float)recti->xmin + 1,
+ .xmax = (float)recti->xmax - 1,
+ .ymin = (float)recti->ymin + 1,
+ .ymax = (float)recti->ymax - 1,
+ };
+
+ float w = BLI_rctf_size_x(&rect);
+ float h = BLI_rctf_size_y(&rect) * hist->ymax;
+
+ 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];
+ UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_4fv(
+ true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
+
+ /* need scissor test, histogram can draw outside of boundary */
+ int scissor[4];
+ GPU_scissor_get_i(scissor);
+ GPU_scissor((rect.xmin - 1),
+ (rect.ymin - 1),
+ (rect.xmax + 1) - (rect.xmin - 1),
+ (rect.ymax + 1) - (rect.ymin - 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);
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
+ /* draw grid lines here */
+ for (int i = 1; i <= HISTOGRAM_TOT_GRID_LINES; i++) {
+ const float fac = (float)i / (float)HISTOGRAM_TOT_GRID_LINES;
+
+ /* so we can tell the 1.0 color point */
+ if (i == HISTOGRAM_TOT_GRID_LINES) {
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
+ }
+
+ immBegin(GPU_PRIM_LINES, 4);
+
+ immVertex2f(pos, rect.xmin, rect.ymin + fac * h);
+ immVertex2f(pos, rect.xmax, rect.ymin + fac * h);
+
+ immVertex2f(pos, rect.xmin + fac * w, rect.ymin);
+ immVertex2f(pos, rect.xmin + fac * w, rect.ymax);
+
+ immEnd();
+ }
+
+ if (hist->mode == HISTO_MODE_LUMA) {
+ histogram_draw_one(
+ 1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res, is_line, pos);
+ }
+ else if (hist->mode == HISTO_MODE_ALPHA) {
+ histogram_draw_one(
+ 1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_a, res, is_line, pos);
+ }
+ else {
+ if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_R) {
+ histogram_draw_one(
+ 1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res, is_line, pos);
+ }
+ if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_G) {
+ histogram_draw_one(
+ 0.0, 1.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_g, res, is_line, pos);
+ }
+ if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_B) {
+ histogram_draw_one(
+ 0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res, is_line, pos);
+ }
+ }
+
+ immUnbindProgram();
+
+ /* outline */
+ draw_scope_end(&rect, scissor);
}
#undef HISTOGRAM_TOT_GRID_LINES
static void waveform_draw_one(float *waveform, int nbr, const float col[3])
{
- GPUVertFormat format = {0};
- uint pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPUVertFormat format = {0};
+ uint pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, nbr);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, nbr);
- GPU_vertbuf_attr_fill(vbo, pos_id, waveform);
+ GPU_vertbuf_attr_fill(vbo, pos_id, waveform);
- /* TODO store the GPUBatch inside the scope */
- GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
- GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR);
- GPU_batch_uniform_4f(batch, "color", col[0], col[1], col[2], 1.0f);
- GPU_batch_draw(batch);
+ /* TODO store the GPUBatch inside the scope */
+ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR);
+ GPU_batch_uniform_4f(batch, "color", col[0], col[1], col[2], 1.0f);
+ GPU_batch_draw(batch);
- GPU_batch_discard(batch);
+ GPU_batch_discard(batch);
}
-void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, const uiWidgetColors *UNUSED(wcol), const rcti *recti)
+void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar),
+ uiBut *but,
+ const uiWidgetColors *UNUSED(wcol),
+ const rcti *recti)
{
- Scopes *scopes = (Scopes *)but->poin;
- int scissor[4];
- float colors[3][3];
- float colorsycc[3][3] = {{1, 0, 1}, {1, 1, 0}, {0, 1, 1}};
- /* colors pre multiplied by alpha for speed up */
- float colors_alpha[3][3], colorsycc_alpha[3][3];
- float min, max;
-
- if (scopes == NULL) {
- return;
- }
-
- rctf rect = {
- .xmin = (float)recti->xmin + 1,
- .xmax = (float)recti->xmax - 1,
- .ymin = (float)recti->ymin + 1,
- .ymax = (float)recti->ymax - 1,
- };
-
- if (scopes->wavefrm_yfac < 0.5f) {
- scopes->wavefrm_yfac = 0.98f;
- }
- float w = BLI_rctf_size_x(&rect) - 7;
- float h = BLI_rctf_size_y(&rect) * scopes->wavefrm_yfac;
- float yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) * 0.5f;
- float w3 = w / 3.0f;
-
- /* log scale for alpha */
- float alpha = scopes->wavefrm_alpha * scopes->wavefrm_alpha;
-
- unit_m3(colors);
-
- for (int c = 0; c < 3; c++) {
- for (int i = 0; i < 3; i++) {
- colors_alpha[c][i] = colors[c][i] * alpha;
- colorsycc_alpha[c][i] = colorsycc[c][i] * alpha;
- }
- }
-
- /* Flush text cache before changing scissors. */
- BLF_batch_draw_flush();
-
- 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];
- UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
-
- /* need scissor test, waveform can draw outside of boundary */
- GPU_scissor_get_i(scissor);
- GPU_scissor(
- (rect.xmin - 1),
- (rect.ymin - 1),
- (rect.xmax + 1) - (rect.xmin - 1),
- (rect.ymax + 1) - (rect.ymin - 1));
-
- /* draw scale numbers first before binding any shader */
- for (int i = 0; i < 6; i++) {
- char str[4];
- BLI_snprintf(str, sizeof(str), "%-3d", i * 20);
- str[3] = '\0';
- BLF_color4f(BLF_default(), 1.0f, 1.0f, 1.0f, 0.08f);
- BLF_draw_default(rect.xmin + 1, yofs - 5 + (i * 0.2f) * h, 0, str, sizeof(str) - 1);
- }
-
- /* Flush text cache before drawing things on top. */
- BLF_batch_draw_flush();
-
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
-
- /* draw grid lines here */
- immBegin(GPU_PRIM_LINES, 12);
-
- for (int i = 0; i < 6; i++) {
- immVertex2f(pos, rect.xmin + 22, yofs + (i * 0.2f) * h);
- immVertex2f(pos, rect.xmax + 1, yofs + (i * 0.2f) * h);
- }
-
- immEnd();
-
- /* 3 vertical separation */
- if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA) {
- immBegin(GPU_PRIM_LINES, 4);
-
- for (int i = 1; i < 3; i++) {
- immVertex2f(pos, rect.xmin + i * w3, rect.ymin);
- immVertex2f(pos, rect.xmin + i * w3, rect.ymax);
- }
-
- immEnd();
- }
-
- /* separate min max zone on the right */
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, rect.xmin + w, rect.ymin);
- immVertex2f(pos, rect.xmin + w, rect.ymax);
- immEnd();
-
- /* 16-235-240 level in case of ITU-R BT601/709 */
- immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f);
- if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_YCC_601, SCOPES_WAVEFRM_YCC_709)) {
- immBegin(GPU_PRIM_LINES, 8);
-
- immVertex2f(pos, rect.xmin + 22, yofs + h * 16.0f / 255.0f);
- immVertex2f(pos, rect.xmax + 1, yofs + h * 16.0f / 255.0f);
-
- immVertex2f(pos, rect.xmin + 22, yofs + h * 235.0f / 255.0f);
- immVertex2f(pos, rect.xmin + w3, yofs + h * 235.0f / 255.0f);
-
- immVertex2f(pos, rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f);
- immVertex2f(pos, rect.xmax + 1, yofs + h * 235.0f / 255.0f);
-
- immVertex2f(pos, rect.xmin + w3, yofs + h * 240.0f / 255.0f);
- immVertex2f(pos, rect.xmax + 1, yofs + h * 240.0f / 255.0f);
-
- immEnd();
- }
- /* 7.5 IRE black point level for NTSC */
- if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) {
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, rect.xmin, yofs + h * 0.075f);
- immVertex2f(pos, rect.xmax + 1, yofs + h * 0.075f);
- immEnd();
- }
-
- if (scopes->ok && scopes->waveform_1 != NULL) {
- glBlendFunc(GL_ONE, GL_ONE);
- GPU_point_size(1.0);
-
- /* LUMA (1 channel) */
- if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) {
- float col[3] = {alpha, alpha, alpha};
-
- GPU_matrix_push();
- GPU_matrix_translate_2f(rect.xmin, yofs);
- GPU_matrix_scale_2f(w, h);
-
- waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, col);
-
- GPU_matrix_pop();
-
- /* min max */
- immUniformColor3f(0.5f, 0.5f, 0.5f);
- min = yofs + scopes->minmax[0][0] * h;
- max = yofs + scopes->minmax[0][1] * h;
- CLAMP(min, rect.ymin, rect.ymax);
- CLAMP(max, rect.ymin, rect.ymax);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, rect.xmax - 3, min);
- immVertex2f(pos, rect.xmax - 3, max);
- immEnd();
- }
- /* RGB (3 channel) */
- else if (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB) {
- GPU_matrix_push();
- GPU_matrix_translate_2f(rect.xmin, yofs);
- GPU_matrix_scale_2f(w, h);
-
- waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, colors_alpha[0]);
- waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, colors_alpha[1]);
- waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, colors_alpha[2]);
-
- GPU_matrix_pop();
- }
- /* PARADE / YCC (3 channels) */
- else if (ELEM(scopes->wavefrm_mode,
- SCOPES_WAVEFRM_RGB_PARADE,
- SCOPES_WAVEFRM_YCC_601,
- SCOPES_WAVEFRM_YCC_709,
- SCOPES_WAVEFRM_YCC_JPEG
- ))
- {
- int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB_PARADE);
-
- GPU_matrix_push();
- GPU_matrix_translate_2f(rect.xmin, yofs);
- GPU_matrix_scale_2f(w3, h);
-
- waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, (rgb) ? colors_alpha[0] : colorsycc_alpha[0]);
-
- GPU_matrix_translate_2f(1.0f, 0.0f);
- waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, (rgb) ? colors_alpha[1] : colorsycc_alpha[1]);
-
- GPU_matrix_translate_2f(1.0f, 0.0f);
- waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, (rgb) ? colors_alpha[2] : colorsycc_alpha[2]);
-
- GPU_matrix_pop();
- }
-
- /* min max */
- if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA ) {
- for (int c = 0; c < 3; c++) {
- if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_RGB_PARADE, SCOPES_WAVEFRM_RGB)) {
- immUniformColor3f(colors[c][0] * 0.75f, colors[c][1] * 0.75f, colors[c][2] * 0.75f);
- }
- else {
- immUniformColor3f(colorsycc[c][0] * 0.75f, colorsycc[c][1] * 0.75f, colorsycc[c][2] * 0.75f);
- }
- min = yofs + scopes->minmax[c][0] * h;
- max = yofs + scopes->minmax[c][1] * h;
- CLAMP(min, rect.ymin, rect.ymax);
- CLAMP(max, rect.ymin, rect.ymax);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, rect.xmin + w + 2 + c * 2, min);
- immVertex2f(pos, rect.xmin + w + 2 + c * 2, max);
- immEnd();
- }
- }
- }
-
- immUnbindProgram();
-
- /* outline */
- draw_scope_end(&rect, scissor);
-
- GPU_blend(false);
+ Scopes *scopes = (Scopes *)but->poin;
+ int scissor[4];
+ float colors[3][3];
+ float colorsycc[3][3] = {{1, 0, 1}, {1, 1, 0}, {0, 1, 1}};
+ /* colors pre multiplied by alpha for speed up */
+ float colors_alpha[3][3], colorsycc_alpha[3][3];
+ float min, max;
+
+ if (scopes == NULL) {
+ return;
+ }
+
+ rctf rect = {
+ .xmin = (float)recti->xmin + 1,
+ .xmax = (float)recti->xmax - 1,
+ .ymin = (float)recti->ymin + 1,
+ .ymax = (float)recti->ymax - 1,
+ };
+
+ if (scopes->wavefrm_yfac < 0.5f) {
+ scopes->wavefrm_yfac = 0.98f;
+ }
+ float w = BLI_rctf_size_x(&rect) - 7;
+ float h = BLI_rctf_size_y(&rect) * scopes->wavefrm_yfac;
+ float yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) * 0.5f;
+ float w3 = w / 3.0f;
+
+ /* log scale for alpha */
+ float alpha = scopes->wavefrm_alpha * scopes->wavefrm_alpha;
+
+ unit_m3(colors);
+
+ for (int c = 0; c < 3; c++) {
+ for (int i = 0; i < 3; i++) {
+ colors_alpha[c][i] = colors[c][i] * alpha;
+ colorsycc_alpha[c][i] = colorsycc[c][i] * alpha;
+ }
+ }
+
+ /* Flush text cache before changing scissors. */
+ BLF_batch_draw_flush();
+
+ 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];
+ UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_4fv(
+ true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
+
+ /* need scissor test, waveform can draw outside of boundary */
+ GPU_scissor_get_i(scissor);
+ GPU_scissor((rect.xmin - 1),
+ (rect.ymin - 1),
+ (rect.xmax + 1) - (rect.xmin - 1),
+ (rect.ymax + 1) - (rect.ymin - 1));
+
+ /* draw scale numbers first before binding any shader */
+ for (int i = 0; i < 6; i++) {
+ char str[4];
+ BLI_snprintf(str, sizeof(str), "%-3d", i * 20);
+ str[3] = '\0';
+ BLF_color4f(BLF_default(), 1.0f, 1.0f, 1.0f, 0.08f);
+ BLF_draw_default(rect.xmin + 1, yofs - 5 + (i * 0.2f) * h, 0, str, sizeof(str) - 1);
+ }
+
+ /* Flush text cache before drawing things on top. */
+ BLF_batch_draw_flush();
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
+
+ /* draw grid lines here */
+ immBegin(GPU_PRIM_LINES, 12);
+
+ for (int i = 0; i < 6; i++) {
+ immVertex2f(pos, rect.xmin + 22, yofs + (i * 0.2f) * h);
+ immVertex2f(pos, rect.xmax + 1, yofs + (i * 0.2f) * h);
+ }
+
+ immEnd();
+
+ /* 3 vertical separation */
+ if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA) {
+ immBegin(GPU_PRIM_LINES, 4);
+
+ for (int i = 1; i < 3; i++) {
+ immVertex2f(pos, rect.xmin + i * w3, rect.ymin);
+ immVertex2f(pos, rect.xmin + i * w3, rect.ymax);
+ }
+
+ immEnd();
+ }
+
+ /* separate min max zone on the right */
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, rect.xmin + w, rect.ymin);
+ immVertex2f(pos, rect.xmin + w, rect.ymax);
+ immEnd();
+
+ /* 16-235-240 level in case of ITU-R BT601/709 */
+ immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f);
+ if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_YCC_601, SCOPES_WAVEFRM_YCC_709)) {
+ immBegin(GPU_PRIM_LINES, 8);
+
+ immVertex2f(pos, rect.xmin + 22, yofs + h * 16.0f / 255.0f);
+ immVertex2f(pos, rect.xmax + 1, yofs + h * 16.0f / 255.0f);
+
+ immVertex2f(pos, rect.xmin + 22, yofs + h * 235.0f / 255.0f);
+ immVertex2f(pos, rect.xmin + w3, yofs + h * 235.0f / 255.0f);
+
+ immVertex2f(pos, rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f);
+ immVertex2f(pos, rect.xmax + 1, yofs + h * 235.0f / 255.0f);
+
+ immVertex2f(pos, rect.xmin + w3, yofs + h * 240.0f / 255.0f);
+ immVertex2f(pos, rect.xmax + 1, yofs + h * 240.0f / 255.0f);
+
+ immEnd();
+ }
+ /* 7.5 IRE black point level for NTSC */
+ if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) {
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, rect.xmin, yofs + h * 0.075f);
+ immVertex2f(pos, rect.xmax + 1, yofs + h * 0.075f);
+ immEnd();
+ }
+
+ if (scopes->ok && scopes->waveform_1 != NULL) {
+ glBlendFunc(GL_ONE, GL_ONE);
+ GPU_point_size(1.0);
+
+ /* LUMA (1 channel) */
+ if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) {
+ float col[3] = {alpha, alpha, alpha};
+
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(rect.xmin, yofs);
+ GPU_matrix_scale_2f(w, h);
+
+ waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, col);
+
+ GPU_matrix_pop();
+
+ /* min max */
+ immUniformColor3f(0.5f, 0.5f, 0.5f);
+ min = yofs + scopes->minmax[0][0] * h;
+ max = yofs + scopes->minmax[0][1] * h;
+ CLAMP(min, rect.ymin, rect.ymax);
+ CLAMP(max, rect.ymin, rect.ymax);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, rect.xmax - 3, min);
+ immVertex2f(pos, rect.xmax - 3, max);
+ immEnd();
+ }
+ /* RGB (3 channel) */
+ else if (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB) {
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(rect.xmin, yofs);
+ GPU_matrix_scale_2f(w, h);
+
+ waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, colors_alpha[0]);
+ waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, colors_alpha[1]);
+ waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, colors_alpha[2]);
+
+ GPU_matrix_pop();
+ }
+ /* PARADE / YCC (3 channels) */
+ else if (ELEM(scopes->wavefrm_mode,
+ SCOPES_WAVEFRM_RGB_PARADE,
+ SCOPES_WAVEFRM_YCC_601,
+ SCOPES_WAVEFRM_YCC_709,
+ SCOPES_WAVEFRM_YCC_JPEG)) {
+ int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB_PARADE);
+
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(rect.xmin, yofs);
+ GPU_matrix_scale_2f(w3, h);
+
+ waveform_draw_one(
+ scopes->waveform_1, scopes->waveform_tot, (rgb) ? colors_alpha[0] : colorsycc_alpha[0]);
+
+ GPU_matrix_translate_2f(1.0f, 0.0f);
+ waveform_draw_one(
+ scopes->waveform_2, scopes->waveform_tot, (rgb) ? colors_alpha[1] : colorsycc_alpha[1]);
+
+ GPU_matrix_translate_2f(1.0f, 0.0f);
+ waveform_draw_one(
+ scopes->waveform_3, scopes->waveform_tot, (rgb) ? colors_alpha[2] : colorsycc_alpha[2]);
+
+ GPU_matrix_pop();
+ }
+
+ /* min max */
+ if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA) {
+ for (int c = 0; c < 3; c++) {
+ if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_RGB_PARADE, SCOPES_WAVEFRM_RGB)) {
+ immUniformColor3f(colors[c][0] * 0.75f, colors[c][1] * 0.75f, colors[c][2] * 0.75f);
+ }
+ else {
+ immUniformColor3f(
+ colorsycc[c][0] * 0.75f, colorsycc[c][1] * 0.75f, colorsycc[c][2] * 0.75f);
+ }
+ min = yofs + scopes->minmax[c][0] * h;
+ max = yofs + scopes->minmax[c][1] * h;
+ CLAMP(min, rect.ymin, rect.ymax);
+ CLAMP(max, rect.ymin, rect.ymax);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, rect.xmin + w + 2 + c * 2, min);
+ immVertex2f(pos, rect.xmin + w + 2 + c * 2, max);
+ immEnd();
+ }
+ }
+ }
+
+ immUnbindProgram();
+
+ /* outline */
+ draw_scope_end(&rect, scissor);
+
+ GPU_blend(false);
}
static float polar_to_x(float center, float diam, float ampli, float angle)
{
- return center + diam * ampli * cosf(angle);
+ return center + diam * ampli * cosf(angle);
}
static float polar_to_y(float center, float diam, float ampli, float angle)
{
- return center + diam * ampli * sinf(angle);
+ return center + diam * ampli * sinf(angle);
}
-static void vectorscope_draw_target(uint pos, float centerx, float centery, float diam, const float colf[3])
+static void vectorscope_draw_target(
+ uint pos, float centerx, float centery, float diam, const float colf[3])
{
- float y, u, v;
- float tangle = 0.0f, tampli;
- float dangle, dampli, dangle2, dampli2;
-
- rgb_to_yuv(colf[0], colf[1], colf[2], &y, &u, &v, BLI_YUV_ITU_BT709);
-
- if (u > 0 && v >= 0) {
- tangle = atanf(v / u);
- }
- else if (u > 0 && v < 0) {
- tangle = atanf(v / u) + 2.0f * (float)M_PI;
- }
- else if (u < 0) {
- tangle = atanf(v / u) + (float)M_PI;
- }
- else if (u == 0 && v > 0.0f) {
- tangle = M_PI_2;
- }
- else if (u == 0 && v < 0.0f) {
- tangle = -M_PI_2;
- }
- tampli = sqrtf(u * u + v * v);
-
- /* small target vary by 2.5 degree and 2.5 IRE unit */
- immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f);
- dangle = DEG2RADF(2.5f);
- dampli = 2.5f / 200.0f;
- immBegin(GPU_PRIM_LINE_LOOP, 4);
- immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
- immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
- immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
- immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
- immEnd();
- /* big target vary by 10 degree and 20% amplitude */
- immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f);
- dangle = DEG2RADF(10.0f);
- dampli = 0.2f * tampli;
- dangle2 = DEG2RADF(5.0f);
- dampli2 = 0.5f * dampli;
- immBegin(GPU_PRIM_LINE_STRIP, 3);
- immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle + dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle + dangle));
- immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
- immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli + dampli, tangle + dangle - dangle2));
- immEnd();
- immBegin(GPU_PRIM_LINE_STRIP, 3);
- immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle + dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle + dangle));
- immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
- immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli - dampli, tangle + dangle - dangle2));
- immEnd();
- immBegin(GPU_PRIM_LINE_STRIP, 3);
- immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle - dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle - dangle));
- immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
- immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli - dampli, tangle - dangle + dangle2));
- immEnd();
- immBegin(GPU_PRIM_LINE_STRIP, 3);
- immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle - dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle - dangle));
- immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
- immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli + dampli, tangle - dangle + dangle2));
- immEnd();
+ float y, u, v;
+ float tangle = 0.0f, tampli;
+ float dangle, dampli, dangle2, dampli2;
+
+ rgb_to_yuv(colf[0], colf[1], colf[2], &y, &u, &v, BLI_YUV_ITU_BT709);
+
+ if (u > 0 && v >= 0) {
+ tangle = atanf(v / u);
+ }
+ else if (u > 0 && v < 0) {
+ tangle = atanf(v / u) + 2.0f * (float)M_PI;
+ }
+ else if (u < 0) {
+ tangle = atanf(v / u) + (float)M_PI;
+ }
+ else if (u == 0 && v > 0.0f) {
+ tangle = M_PI_2;
+ }
+ else if (u == 0 && v < 0.0f) {
+ tangle = -M_PI_2;
+ }
+ tampli = sqrtf(u * u + v * v);
+
+ /* small target vary by 2.5 degree and 2.5 IRE unit */
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f);
+ dangle = DEG2RADF(2.5f);
+ dampli = 2.5f / 200.0f;
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
+ immVertex2f(pos,
+ polar_to_x(centerx, diam, tampli + dampli, tangle + dangle),
+ polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
+ immVertex2f(pos,
+ polar_to_x(centerx, diam, tampli - dampli, tangle + dangle),
+ polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
+ immVertex2f(pos,
+ polar_to_x(centerx, diam, tampli - dampli, tangle - dangle),
+ polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
+ immVertex2f(pos,
+ polar_to_x(centerx, diam, tampli + dampli, tangle - dangle),
+ polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
+ immEnd();
+ /* big target vary by 10 degree and 20% amplitude */
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f);
+ dangle = DEG2RADF(10.0f);
+ dampli = 0.2f * tampli;
+ dangle2 = DEG2RADF(5.0f);
+ dampli2 = 0.5f * dampli;
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
+ immVertex2f(pos,
+ polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle + dangle),
+ polar_to_y(centery, diam, tampli + dampli - dampli2, tangle + dangle));
+ immVertex2f(pos,
+ polar_to_x(centerx, diam, tampli + dampli, tangle + dangle),
+ polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
+ immVertex2f(pos,
+ polar_to_x(centerx, diam, tampli + dampli, tangle + dangle - dangle2),
+ polar_to_y(centery, diam, tampli + dampli, tangle + dangle - dangle2));
+ immEnd();
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
+ immVertex2f(pos,
+ polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle + dangle),
+ polar_to_y(centery, diam, tampli - dampli + dampli2, tangle + dangle));
+ immVertex2f(pos,
+ polar_to_x(centerx, diam, tampli - dampli, tangle + dangle),
+ polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
+ immVertex2f(pos,
+ polar_to_x(centerx, diam, tampli - dampli, tangle + dangle - dangle2),
+ polar_to_y(centery, diam, tampli - dampli, tangle + dangle - dangle2));
+ immEnd();
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
+ immVertex2f(pos,
+ polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle - dangle),
+ polar_to_y(centery, diam, tampli - dampli + dampli2, tangle - dangle));
+ immVertex2f(pos,
+ polar_to_x(centerx, diam, tampli - dampli, tangle - dangle),
+ polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
+ immVertex2f(pos,
+ polar_to_x(centerx, diam, tampli - dampli, tangle - dangle + dangle2),
+ polar_to_y(centery, diam, tampli - dampli, tangle - dangle + dangle2));
+ immEnd();
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
+ immVertex2f(pos,
+ polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle - dangle),
+ polar_to_y(centery, diam, tampli + dampli - dampli2, tangle - dangle));
+ immVertex2f(pos,
+ polar_to_x(centerx, diam, tampli + dampli, tangle - dangle),
+ polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
+ immVertex2f(pos,
+ polar_to_x(centerx, diam, tampli + dampli, tangle - dangle + dangle2),
+ polar_to_y(centery, diam, tampli + dampli, tangle - dangle + dangle2));
+ immEnd();
}
-void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(ar), uiBut *but, const uiWidgetColors *UNUSED(wcol), const rcti *recti)
+void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(ar),
+ uiBut *but,
+ const uiWidgetColors *UNUSED(wcol),
+ const rcti *recti)
{
- const float skin_rad = DEG2RADF(123.0f); /* angle in radians of the skin tone line */
- Scopes *scopes = (Scopes *)but->poin;
-
- const float colors[6][3] = {
- {0.75, 0.0, 0.0}, {0.75, 0.75, 0.0}, {0.0, 0.75, 0.0},
- {0.0, 0.75, 0.75}, {0.0, 0.0, 0.75}, {0.75, 0.0, 0.75}};
-
- rctf rect = {
- .xmin = (float)recti->xmin + 1,
- .xmax = (float)recti->xmax - 1,
- .ymin = (float)recti->ymin + 1,
- .ymax = (float)recti->ymax - 1,
- };
-
- float w = BLI_rctf_size_x(&rect);
- float h = BLI_rctf_size_y(&rect);
- float centerx = rect.xmin + w * 0.5f;
- float centery = rect.ymin + h * 0.5f;
- float diam = (w < h) ? w : h;
-
- float alpha = scopes->vecscope_alpha * scopes->vecscope_alpha * scopes->vecscope_alpha;
-
- 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];
- UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
-
- /* need scissor test, hvectorscope can draw outside of boundary */
- int scissor[4];
- GPU_scissor_get_i(scissor);
- GPU_scissor(
- (rect.xmin - 1),
- (rect.ymin - 1),
- (rect.xmax + 1) - (rect.xmin - 1),
- (rect.ymax + 1) - (rect.ymin - 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);
-
- immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
- /* draw grid elements */
- /* cross */
- immBegin(GPU_PRIM_LINES, 4);
-
- immVertex2f(pos, centerx - (diam * 0.5f) - 5, centery);
- immVertex2f(pos, centerx + (diam * 0.5f) + 5, centery);
-
- immVertex2f(pos, centerx, centery - (diam * 0.5f) - 5);
- immVertex2f(pos, centerx, centery + (diam * 0.5f) + 5);
-
- immEnd();
-
- /* circles */
- for (int j = 0; j < 5; j++) {
- const int increment = 15;
- immBegin(GPU_PRIM_LINE_LOOP, (int)(360 / increment));
- for (int i = 0; i <= 360 - increment; i += increment) {
- const float a = DEG2RADF((float)i);
- const float r = (j + 1) * 0.1f;
- immVertex2f(pos, polar_to_x(centerx, diam, r, a), polar_to_y(centery, diam, r, a));
- }
- immEnd();
- }
- /* skin tone line */
- immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, polar_to_x(centerx, diam, 0.5f, skin_rad), polar_to_y(centery, diam, 0.5f, skin_rad));
- immVertex2f(pos, polar_to_x(centerx, diam, 0.1f, skin_rad), polar_to_y(centery, diam, 0.1f, skin_rad));
- immEnd();
-
- /* saturation points */
- for (int i = 0; i < 6; i++) {
- vectorscope_draw_target(pos, centerx, centery, diam, colors[i]);
- }
-
- if (scopes->ok && scopes->vecscope != NULL) {
- /* pixel point cloud */
- float col[3] = {alpha, alpha, alpha};
-
- glBlendFunc(GL_ONE, GL_ONE);
- GPU_point_size(1.0);
-
- GPU_matrix_push();
- GPU_matrix_translate_2f(centerx, centery);
- GPU_matrix_scale_1f(diam);
-
- waveform_draw_one(scopes->vecscope, scopes->waveform_tot, col);
-
- GPU_matrix_pop();
- }
-
- immUnbindProgram();
-
- /* outline */
- draw_scope_end(&rect, scissor);
-
- GPU_blend(false);
+ const float skin_rad = DEG2RADF(123.0f); /* angle in radians of the skin tone line */
+ Scopes *scopes = (Scopes *)but->poin;
+
+ const float colors[6][3] = {{0.75, 0.0, 0.0},
+ {0.75, 0.75, 0.0},
+ {0.0, 0.75, 0.0},
+ {0.0, 0.75, 0.75},
+ {0.0, 0.0, 0.75},
+ {0.75, 0.0, 0.75}};
+
+ rctf rect = {
+ .xmin = (float)recti->xmin + 1,
+ .xmax = (float)recti->xmax - 1,
+ .ymin = (float)recti->ymin + 1,
+ .ymax = (float)recti->ymax - 1,
+ };
+
+ float w = BLI_rctf_size_x(&rect);
+ float h = BLI_rctf_size_y(&rect);
+ float centerx = rect.xmin + w * 0.5f;
+ float centery = rect.ymin + h * 0.5f;
+ float diam = (w < h) ? w : h;
+
+ float alpha = scopes->vecscope_alpha * scopes->vecscope_alpha * scopes->vecscope_alpha;
+
+ 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];
+ UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_4fv(
+ true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
+
+ /* need scissor test, hvectorscope can draw outside of boundary */
+ int scissor[4];
+ GPU_scissor_get_i(scissor);
+ GPU_scissor((rect.xmin - 1),
+ (rect.ymin - 1),
+ (rect.xmax + 1) - (rect.xmin - 1),
+ (rect.ymax + 1) - (rect.ymin - 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);
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
+ /* draw grid elements */
+ /* cross */
+ immBegin(GPU_PRIM_LINES, 4);
+
+ immVertex2f(pos, centerx - (diam * 0.5f) - 5, centery);
+ immVertex2f(pos, centerx + (diam * 0.5f) + 5, centery);
+
+ immVertex2f(pos, centerx, centery - (diam * 0.5f) - 5);
+ immVertex2f(pos, centerx, centery + (diam * 0.5f) + 5);
+
+ immEnd();
+
+ /* circles */
+ for (int j = 0; j < 5; j++) {
+ const int increment = 15;
+ immBegin(GPU_PRIM_LINE_LOOP, (int)(360 / increment));
+ for (int i = 0; i <= 360 - increment; i += increment) {
+ const float a = DEG2RADF((float)i);
+ const float r = (j + 1) * 0.1f;
+ immVertex2f(pos, polar_to_x(centerx, diam, r, a), polar_to_y(centery, diam, r, a));
+ }
+ immEnd();
+ }
+ /* skin tone line */
+ immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(
+ pos, polar_to_x(centerx, diam, 0.5f, skin_rad), polar_to_y(centery, diam, 0.5f, skin_rad));
+ immVertex2f(
+ pos, polar_to_x(centerx, diam, 0.1f, skin_rad), polar_to_y(centery, diam, 0.1f, skin_rad));
+ immEnd();
+
+ /* saturation points */
+ for (int i = 0; i < 6; i++) {
+ vectorscope_draw_target(pos, centerx, centery, diam, colors[i]);
+ }
+
+ if (scopes->ok && scopes->vecscope != NULL) {
+ /* pixel point cloud */
+ float col[3] = {alpha, alpha, alpha};
+
+ glBlendFunc(GL_ONE, GL_ONE);
+ GPU_point_size(1.0);
+
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(centerx, centery);
+ GPU_matrix_scale_1f(diam);
+
+ waveform_draw_one(scopes->vecscope, scopes->waveform_tot, col);
+
+ GPU_matrix_pop();
+ }
+
+ immUnbindProgram();
+
+ /* outline */
+ draw_scope_end(&rect, scissor);
+
+ GPU_blend(false);
}
-static void ui_draw_colorband_handle_tri_hlight(uint pos, float x1, float y1, float halfwidth, float height)
+static void ui_draw_colorband_handle_tri_hlight(
+ uint pos, float x1, float y1, float halfwidth, float height)
{
- GPU_line_smooth(true);
+ GPU_line_smooth(true);
- immBegin(GPU_PRIM_LINE_STRIP, 3);
- immVertex2f(pos, x1 + halfwidth, y1);
- immVertex2f(pos, x1, y1 + height);
- immVertex2f(pos, x1 - halfwidth, y1);
- immEnd();
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
+ immVertex2f(pos, x1 + halfwidth, y1);
+ immVertex2f(pos, x1, y1 + height);
+ immVertex2f(pos, x1 - halfwidth, y1);
+ immEnd();
- GPU_line_smooth(false);
+ GPU_line_smooth(false);
}
-static void ui_draw_colorband_handle_tri(uint pos, float x1, float y1, float halfwidth, float height, bool fill)
+static void ui_draw_colorband_handle_tri(
+ uint pos, float x1, float y1, float halfwidth, float height, bool fill)
{
- if (fill) {
- GPU_polygon_smooth(true);
- }
- else {
- GPU_line_smooth(true);
- }
-
- immBegin(fill ? GPU_PRIM_TRIS : GPU_PRIM_LINE_LOOP, 3);
- immVertex2f(pos, x1 + halfwidth, y1);
- immVertex2f(pos, x1, y1 + height);
- immVertex2f(pos, x1 - halfwidth, y1);
- immEnd();
-
- if (fill) {
- GPU_polygon_smooth(false);
- }
- else {
- GPU_line_smooth(false);
- }
+ if (fill) {
+ GPU_polygon_smooth(true);
+ }
+ else {
+ GPU_line_smooth(true);
+ }
+
+ immBegin(fill ? GPU_PRIM_TRIS : GPU_PRIM_LINE_LOOP, 3);
+ immVertex2f(pos, x1 + halfwidth, y1);
+ immVertex2f(pos, x1, y1 + height);
+ immVertex2f(pos, x1 - halfwidth, y1);
+ immEnd();
+
+ if (fill) {
+ GPU_polygon_smooth(false);
+ }
+ else {
+ GPU_line_smooth(false);
+ }
}
-static void ui_draw_colorband_handle_box(uint pos, float x1, float y1, float x2, float y2, bool fill)
+static void ui_draw_colorband_handle_box(
+ uint pos, float x1, float y1, float x2, float y2, bool fill)
{
- immBegin(fill ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, 4);
- immVertex2f(pos, x1, y1);
- immVertex2f(pos, x1, y2);
- immVertex2f(pos, x2, y2);
- immVertex2f(pos, x2, y1);
- immEnd();
+ immBegin(fill ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, 4);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x2, y1);
+ immEnd();
}
-static void ui_draw_colorband_handle(
- uint shdr_pos, const rcti *rect, float x,
- const float rgb[3], struct ColorManagedDisplay *display,
- bool active)
+static void ui_draw_colorband_handle(uint shdr_pos,
+ const rcti *rect,
+ float x,
+ const float rgb[3],
+ struct ColorManagedDisplay *display,
+ bool active)
{
- const float sizey = BLI_rcti_size_y(rect);
- const float min_width = 3.0f;
- float colf[3] = {UNPACK3(rgb)};
+ const float sizey = BLI_rcti_size_y(rect);
+ const float min_width = 3.0f;
+ float colf[3] = {UNPACK3(rgb)};
- float half_width = floorf(sizey / 3.5f);
- float height = half_width * 1.4f;
+ float half_width = floorf(sizey / 3.5f);
+ float height = half_width * 1.4f;
- float y1 = rect->ymin + (sizey * 0.16f);
- float y2 = rect->ymax;
+ float y1 = rect->ymin + (sizey * 0.16f);
+ float y2 = rect->ymax;
- /* align to pixels */
- x = floorf(x + 0.5f);
- y1 = floorf(y1 + 0.5f);
+ /* align to pixels */
+ x = floorf(x + 0.5f);
+ y1 = floorf(y1 + 0.5f);
- if (active || half_width < min_width) {
- immUnbindProgram();
+ if (active || half_width < min_width) {
+ immUnbindProgram();
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
- immUniform1i("colors_len", 2); /* "advanced" mode */
- immUniformArray4fv("colors", (float *)(float[][4]){{0.8f, 0.8f, 0.8f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2);
- immUniform1f("dash_width", active ? 4.0f : 2.0f);
+ immUniform1i("colors_len", 2); /* "advanced" mode */
+ immUniformArray4fv(
+ "colors", (float *)(float[][4]){{0.8f, 0.8f, 0.8f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2);
+ immUniform1f("dash_width", active ? 4.0f : 2.0f);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(shdr_pos, x, y1);
- immVertex2f(shdr_pos, x, y2);
- immEnd();
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(shdr_pos, x, y1);
+ immVertex2f(shdr_pos, x, y2);
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- /* hide handles when zoomed out too far */
- if (half_width < min_width) {
- return;
- }
- }
+ /* hide handles when zoomed out too far */
+ if (half_width < min_width) {
+ return;
+ }
+ }
- /* shift handle down */
- y1 -= half_width;
+ /* shift handle down */
+ y1 -= half_width;
- immUniformColor3ub(0, 0, 0);
- ui_draw_colorband_handle_box(shdr_pos, x - half_width, y1 - 1, x + half_width, y1 + height, false);
+ immUniformColor3ub(0, 0, 0);
+ ui_draw_colorband_handle_box(
+ shdr_pos, x - half_width, y1 - 1, x + half_width, y1 + height, false);
- /* draw all triangles blended */
- GPU_blend(true);
+ /* draw all triangles blended */
+ GPU_blend(true);
- ui_draw_colorband_handle_tri(shdr_pos, x, y1 + height, half_width, half_width, true);
+ ui_draw_colorband_handle_tri(shdr_pos, x, y1 + height, half_width, half_width, true);
- if (active) {
- immUniformColor3ub(196, 196, 196);
- }
- else {
- immUniformColor3ub(96, 96, 96);
- }
- ui_draw_colorband_handle_tri(shdr_pos, x, y1 + height, half_width, half_width, true);
+ if (active) {
+ immUniformColor3ub(196, 196, 196);
+ }
+ else {
+ immUniformColor3ub(96, 96, 96);
+ }
+ ui_draw_colorband_handle_tri(shdr_pos, x, y1 + height, half_width, half_width, true);
- if (active) {
- immUniformColor3ub(255, 255, 255);
- }
- else {
- immUniformColor3ub(128, 128, 128);
- }
- ui_draw_colorband_handle_tri_hlight(shdr_pos, x, y1 + height - 1, (half_width - 1), (half_width - 1));
+ if (active) {
+ immUniformColor3ub(255, 255, 255);
+ }
+ else {
+ immUniformColor3ub(128, 128, 128);
+ }
+ ui_draw_colorband_handle_tri_hlight(
+ shdr_pos, x, y1 + height - 1, (half_width - 1), (half_width - 1));
- immUniformColor3ub(0, 0, 0);
- ui_draw_colorband_handle_tri_hlight(shdr_pos, x, y1 + height, half_width, half_width);
+ immUniformColor3ub(0, 0, 0);
+ ui_draw_colorband_handle_tri_hlight(shdr_pos, x, y1 + height, half_width, half_width);
- GPU_blend(false);
+ GPU_blend(false);
- immUniformColor3ub(128, 128, 128);
- ui_draw_colorband_handle_box(shdr_pos, x - (half_width - 1), y1, x + (half_width - 1), y1 + height, true);
+ immUniformColor3ub(128, 128, 128);
+ ui_draw_colorband_handle_box(
+ shdr_pos, x - (half_width - 1), y1, x + (half_width - 1), y1 + height, true);
- if (display) {
- IMB_colormanagement_scene_linear_to_display_v3(colf, display);
- }
+ if (display) {
+ IMB_colormanagement_scene_linear_to_display_v3(colf, display);
+ }
- immUniformColor3fv(colf);
- ui_draw_colorband_handle_box(shdr_pos, x - (half_width - 2), y1 + 1, x + (half_width - 2), y1 + height - 2, true);
+ immUniformColor3fv(colf);
+ ui_draw_colorband_handle_box(
+ shdr_pos, x - (half_width - 2), y1 + 1, x + (half_width - 2), y1 + height - 2, true);
}
void ui_draw_but_COLORBAND(uiBut *but, const uiWidgetColors *UNUSED(wcol), const rcti *rect)
{
- struct ColorManagedDisplay *display = ui_block_cm_display_get(but->block);
- uint pos_id, col_id;
-
- ColorBand *coba = (ColorBand *)(but->editcoba ? but->editcoba : but->poin);
- if (coba == NULL) {
- return;
- }
-
- float x1 = rect->xmin;
- float sizex = rect->xmax - x1;
- float sizey = BLI_rcti_size_y(rect);
- float sizey_solid = sizey * 0.25f;
- float y1 = rect->ymin;
-
- GPUVertFormat *format = immVertexFormat();
- pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_CHECKER);
-
- /* Drawing the checkerboard. */
- immUniform4f("color1", UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, 1.0f);
- immUniform4f("color2", UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 1.0f);
- immUniform1i("size", 8);
- immRectf(pos_id, x1, y1, x1 + sizex, rect->ymax);
- immUnbindProgram();
-
- /* New format */
- format = immVertexFormat();
- pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
-
- /* layer: color ramp */
- GPU_blend(true);
-
- CBData *cbd = coba->data;
-
- float v1[2], v2[2];
- float colf[4] = {0, 0, 0, 0}; /* initialize in case the colorband isn't valid */
-
- v1[1] = y1 + sizey_solid;
- v2[1] = rect->ymax;
-
- immBegin(GPU_PRIM_TRI_STRIP, (sizex + 1) * 2);
- for (int a = 0; a <= sizex; a++) {
- float pos = ((float)a) / sizex;
- BKE_colorband_evaluate(coba, pos, colf);
- if (display) {
- IMB_colormanagement_scene_linear_to_display_v3(colf, display);
- }
-
- v1[0] = v2[0] = x1 + a;
-
- immAttr4fv(col_id, colf);
- immVertex2fv(pos_id, v1);
- immVertex2fv(pos_id, v2);
- }
- immEnd();
-
- /* layer: color ramp without alpha for reference when manipulating ramp properties */
- v1[1] = y1;
- v2[1] = y1 + sizey_solid;
-
- immBegin(GPU_PRIM_TRI_STRIP, (sizex + 1) * 2);
- for (int a = 0; a <= sizex; a++) {
- float pos = ((float)a) / sizex;
- BKE_colorband_evaluate(coba, pos, colf);
- if (display) {
- IMB_colormanagement_scene_linear_to_display_v3(colf, display);
- }
-
- v1[0] = v2[0] = x1 + a;
-
- immAttr4f(col_id, colf[0], colf[1], colf[2], 1.0f);
- immVertex2fv(pos_id, v1);
- immVertex2fv(pos_id, v2);
- }
- immEnd();
-
- immUnbindProgram();
-
- GPU_blend(false);
-
- /* New format */
- format = immVertexFormat();
- pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* layer: box outline */
- immUniformColor4f(0.0f, 0.0f, 0.0f, 1.0f);
- imm_draw_box_wire_2d(pos_id, x1, y1, x1 + sizex, rect->ymax);
-
- /* layer: box outline */
- GPU_blend(true);
- immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos_id, x1, y1);
- immVertex2f(pos_id, x1 + sizex, y1);
- immEnd();
-
- immUniformColor4f(1.0f, 1.0f, 1.0f, 0.25f);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos_id, x1, y1 - 1);
- immVertex2f(pos_id, x1 + sizex, y1 - 1);
- immEnd();
-
- GPU_blend(false);
-
- /* layer: draw handles */
- for (int a = 0; a < coba->tot; a++, cbd++) {
- if (a != coba->cur) {
- float pos = x1 + cbd->pos * (sizex - 1) + 1;
- ui_draw_colorband_handle(pos_id, rect, pos, &cbd->r, display, false);
- }
- }
-
- /* layer: active handle */
- if (coba->tot != 0) {
- cbd = &coba->data[coba->cur];
- float pos = x1 + cbd->pos * (sizex - 1) + 1;
- ui_draw_colorband_handle(pos_id, rect, pos, &cbd->r, display, true);
- }
-
- immUnbindProgram();
+ struct ColorManagedDisplay *display = ui_block_cm_display_get(but->block);
+ uint pos_id, col_id;
+
+ ColorBand *coba = (ColorBand *)(but->editcoba ? but->editcoba : but->poin);
+ if (coba == NULL) {
+ return;
+ }
+
+ float x1 = rect->xmin;
+ float sizex = rect->xmax - x1;
+ float sizey = BLI_rcti_size_y(rect);
+ float sizey_solid = sizey * 0.25f;
+ float y1 = rect->ymin;
+
+ GPUVertFormat *format = immVertexFormat();
+ pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_CHECKER);
+
+ /* Drawing the checkerboard. */
+ immUniform4f("color1",
+ UI_ALPHA_CHECKER_DARK / 255.0f,
+ UI_ALPHA_CHECKER_DARK / 255.0f,
+ UI_ALPHA_CHECKER_DARK / 255.0f,
+ 1.0f);
+ immUniform4f("color2",
+ UI_ALPHA_CHECKER_LIGHT / 255.0f,
+ UI_ALPHA_CHECKER_LIGHT / 255.0f,
+ UI_ALPHA_CHECKER_LIGHT / 255.0f,
+ 1.0f);
+ immUniform1i("size", 8);
+ immRectf(pos_id, x1, y1, x1 + sizex, rect->ymax);
+ immUnbindProgram();
+
+ /* New format */
+ format = immVertexFormat();
+ pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ /* layer: color ramp */
+ GPU_blend(true);
+
+ CBData *cbd = coba->data;
+
+ float v1[2], v2[2];
+ float colf[4] = {0, 0, 0, 0}; /* initialize in case the colorband isn't valid */
+
+ v1[1] = y1 + sizey_solid;
+ v2[1] = rect->ymax;
+
+ immBegin(GPU_PRIM_TRI_STRIP, (sizex + 1) * 2);
+ for (int a = 0; a <= sizex; a++) {
+ float pos = ((float)a) / sizex;
+ BKE_colorband_evaluate(coba, pos, colf);
+ if (display) {
+ IMB_colormanagement_scene_linear_to_display_v3(colf, display);
+ }
+
+ v1[0] = v2[0] = x1 + a;
+
+ immAttr4fv(col_id, colf);
+ immVertex2fv(pos_id, v1);
+ immVertex2fv(pos_id, v2);
+ }
+ immEnd();
+
+ /* layer: color ramp without alpha for reference when manipulating ramp properties */
+ v1[1] = y1;
+ v2[1] = y1 + sizey_solid;
+
+ immBegin(GPU_PRIM_TRI_STRIP, (sizex + 1) * 2);
+ for (int a = 0; a <= sizex; a++) {
+ float pos = ((float)a) / sizex;
+ BKE_colorband_evaluate(coba, pos, colf);
+ if (display) {
+ IMB_colormanagement_scene_linear_to_display_v3(colf, display);
+ }
+
+ v1[0] = v2[0] = x1 + a;
+
+ immAttr4f(col_id, colf[0], colf[1], colf[2], 1.0f);
+ immVertex2fv(pos_id, v1);
+ immVertex2fv(pos_id, v2);
+ }
+ immEnd();
+
+ immUnbindProgram();
+
+ GPU_blend(false);
+
+ /* New format */
+ format = immVertexFormat();
+ pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* layer: box outline */
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+ imm_draw_box_wire_2d(pos_id, x1, y1, x1 + sizex, rect->ymax);
+
+ /* layer: box outline */
+ GPU_blend(true);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos_id, x1, y1);
+ immVertex2f(pos_id, x1 + sizex, y1);
+ immEnd();
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.25f);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos_id, x1, y1 - 1);
+ immVertex2f(pos_id, x1 + sizex, y1 - 1);
+ immEnd();
+
+ GPU_blend(false);
+
+ /* layer: draw handles */
+ for (int a = 0; a < coba->tot; a++, cbd++) {
+ if (a != coba->cur) {
+ float pos = x1 + cbd->pos * (sizex - 1) + 1;
+ ui_draw_colorband_handle(pos_id, rect, pos, &cbd->r, display, false);
+ }
+ }
+
+ /* layer: active handle */
+ if (coba->tot != 0) {
+ cbd = &coba->data[coba->cur];
+ float pos = x1 + cbd->pos * (sizex - 1) + 1;
+ ui_draw_colorband_handle(pos_id, rect, pos, &cbd->r, display, true);
+ }
+
+ immUnbindProgram();
}
void ui_draw_but_UNITVEC(uiBut *but, const uiWidgetColors *wcol, const rcti *rect)
{
- /* sphere color */
- float diffuse[3] = {1.0f, 1.0f, 1.0f};
- float light[3];
- float size;
-
- /* backdrop */
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_3ubAlpha(true, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f, (uchar *)wcol->inner, 255);
-
- glCullFace(GL_BACK);
- glEnable(GL_CULL_FACE);
-
- /* setup lights */
- ui_but_v3_get(but, light);
-
- /* 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);
- }
-
- GPU_matrix_translate_2f(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect));
- GPU_matrix_scale_1f(size);
-
- GPUBatch *sphere = GPU_batch_preset_sphere(2);
- GPU_batch_program_set_builtin(sphere, GPU_SHADER_SIMPLE_LIGHTING);
- GPU_batch_uniform_4f(sphere, "color", diffuse[0], diffuse[1], diffuse[2], 1.0f);
- GPU_batch_uniform_3fv(sphere, "light", light);
- GPU_batch_draw(sphere);
-
- /* restore */
- glDisable(GL_CULL_FACE);
-
- /* AA circle */
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3ubv((uchar *)wcol->inner);
-
- GPU_blend(true);
- GPU_line_smooth(true);
- imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, 1.0f, 32);
- GPU_blend(false);
- GPU_line_smooth(false);
-
- /* matrix after circle */
- GPU_matrix_pop();
-
- immUnbindProgram();
+ /* sphere color */
+ float diffuse[3] = {1.0f, 1.0f, 1.0f};
+ float light[3];
+ float size;
+
+ /* backdrop */
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_3ubAlpha(
+ true, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f, (uchar *)wcol->inner, 255);
+
+ glCullFace(GL_BACK);
+ glEnable(GL_CULL_FACE);
+
+ /* setup lights */
+ ui_but_v3_get(but, light);
+
+ /* 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);
+ }
+
+ GPU_matrix_translate_2f(rect->xmin + 0.5f * BLI_rcti_size_x(rect),
+ rect->ymin + 0.5f * BLI_rcti_size_y(rect));
+ GPU_matrix_scale_1f(size);
+
+ GPUBatch *sphere = GPU_batch_preset_sphere(2);
+ GPU_batch_program_set_builtin(sphere, GPU_SHADER_SIMPLE_LIGHTING);
+ GPU_batch_uniform_4f(sphere, "color", diffuse[0], diffuse[1], diffuse[2], 1.0f);
+ GPU_batch_uniform_3fv(sphere, "light", light);
+ GPU_batch_draw(sphere);
+
+ /* restore */
+ glDisable(GL_CULL_FACE);
+
+ /* AA circle */
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3ubv((uchar *)wcol->inner);
+
+ GPU_blend(true);
+ GPU_line_smooth(true);
+ imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, 1.0f, 32);
+ GPU_blend(false);
+ GPU_line_smooth(false);
+
+ /* matrix after circle */
+ GPU_matrix_pop();
+
+ immUnbindProgram();
}
-static void ui_draw_but_curve_grid(uint pos, const rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step)
+static void ui_draw_but_curve_grid(
+ uint pos, const rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step)
{
- float dx = step * zoomx;
- float fx = rect->xmin + zoomx * (-offsx);
- if (fx > rect->xmin) {
- fx -= dx * (floorf(fx - rect->xmin));
- }
-
- float dy = step * zoomy;
- float fy = rect->ymin + zoomy * (-offsy);
- if (fy > rect->ymin) {
- fy -= dy * (floorf(fy - rect->ymin));
- }
-
- float line_count = (
- floorf((rect->xmax - fx) / dx) + 1.0f +
- floorf((rect->ymax - fy) / dy) + 1.0f);
-
- immBegin(GPU_PRIM_LINES, (int)line_count * 2);
- while (fx < rect->xmax) {
- immVertex2f(pos, fx, rect->ymin);
- immVertex2f(pos, fx, rect->ymax);
- fx += dx;
- }
- while (fy < rect->ymax) {
- immVertex2f(pos, rect->xmin, fy);
- immVertex2f(pos, rect->xmax, fy);
- fy += dy;
- }
- immEnd();
-
+ float dx = step * zoomx;
+ float fx = rect->xmin + zoomx * (-offsx);
+ if (fx > rect->xmin) {
+ fx -= dx * (floorf(fx - rect->xmin));
+ }
+
+ float dy = step * zoomy;
+ float fy = rect->ymin + zoomy * (-offsy);
+ if (fy > rect->ymin) {
+ fy -= dy * (floorf(fy - rect->ymin));
+ }
+
+ float line_count = (floorf((rect->xmax - fx) / dx) + 1.0f + floorf((rect->ymax - fy) / dy) +
+ 1.0f);
+
+ immBegin(GPU_PRIM_LINES, (int)line_count * 2);
+ while (fx < rect->xmax) {
+ immVertex2f(pos, fx, rect->ymin);
+ immVertex2f(pos, fx, rect->ymax);
+ fx += dx;
+ }
+ while (fy < rect->ymax) {
+ immVertex2f(pos, rect->xmin, fy);
+ immVertex2f(pos, rect->xmax, fy);
+ fy += dy;
+ }
+ immEnd();
}
-
static void gl_shaded_color_get(const uchar color[3], int shade, uchar r_color[3])
{
- r_color[0] = color[0] - shade > 0 ? color[0] - shade : 0;
- r_color[1] = color[1] - shade > 0 ? color[1] - shade : 0;
- r_color[2] = color[2] - shade > 0 ? color[2] - shade : 0;
+ r_color[0] = color[0] - shade > 0 ? color[0] - shade : 0;
+ r_color[1] = color[1] - shade > 0 ? color[1] - shade : 0;
+ r_color[2] = color[2] - shade > 0 ? color[2] - shade : 0;
}
static void gl_shaded_color_get_fl(const uchar *color, int shade, float r_color[3])
{
- uchar color_shaded[3];
- gl_shaded_color_get(color, shade, color_shaded);
- rgb_uchar_to_float(r_color, color_shaded);
+ uchar color_shaded[3];
+ gl_shaded_color_get(color, shade, color_shaded);
+ rgb_uchar_to_float(r_color, color_shaded);
}
static void gl_shaded_color(uchar *color, int shade)
{
- uchar color_shaded[3];
- gl_shaded_color_get(color, shade, color_shaded);
- immUniformColor3ubv(color_shaded);
+ uchar color_shaded[3];
+ gl_shaded_color_get(color, shade, color_shaded);
+ immUniformColor3ubv(color_shaded);
}
void ui_draw_but_CURVE(ARegion *ar, uiBut *but, const uiWidgetColors *wcol, const rcti *rect)
{
- CurveMapping *cumap;
-
- if (but->editcumap) {
- cumap = but->editcumap;
- }
- else {
- cumap = (CurveMapping *)but->poin;
- }
-
- CurveMap *cuma = &cumap->cm[cumap->cur];
-
- /* need scissor test, curve can draw outside of boundary */
- int scissor[4];
- GPU_scissor_get_i(scissor);
- rcti scissor_new = {
- .xmin = rect->xmin,
- .ymin = rect->ymin,
- .xmax = rect->xmax,
- .ymax = rect->ymax,
- };
- rcti scissor_region = {0, ar->winx, 0, ar->winy};
- BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new);
- GPU_scissor(
- scissor_new.xmin,
- scissor_new.ymin,
- BLI_rcti_size_x(&scissor_new),
- BLI_rcti_size_y(&scissor_new));
-
- /* calculate offset and zoom */
- float zoomx = (BLI_rcti_size_x(rect) - 2.0f) / BLI_rctf_size_x(&cumap->curr);
- float zoomy = (BLI_rcti_size_y(rect) - 2.0f) / BLI_rctf_size_y(&cumap->curr);
- float offsx = cumap->curr.xmin - (1.0f / zoomx);
- float offsy = cumap->curr.ymin - (1.0f / zoomy);
-
- /* Do this first to not mess imm context */
- if (but->a1 == UI_GRAD_H) {
- /* magic trigger for curve backgrounds */
- float col[3] = {0.0f, 0.0f, 0.0f}; /* dummy arg */
-
- rcti grid = {
- .xmin = rect->xmin + zoomx * (-offsx),
- .xmax = grid.xmin + zoomx,
- .ymin = rect->ymin + zoomy * (-offsy),
- .ymax = grid.ymin + zoomy,
- };
-
- ui_draw_gradient(&grid, col, UI_GRAD_H, 1.0f);
- }
-
- GPU_line_width(1.0f);
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* backdrop */
- float color_backdrop[4] = {0, 0, 0, 1};
-
- if (but->a1 == UI_GRAD_H) {
- /* grid, hsv uses different grid */
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- ARRAY_SET_ITEMS(color_backdrop, 0, 0, 0, 48.0 / 255.0);
- immUniformColor4fv(color_backdrop);
- ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.1666666f);
- GPU_blend(false);
- }
- else {
- if (cumap->flag & CUMA_DO_CLIP) {
- gl_shaded_color_get_fl((uchar *)wcol->inner, -20, color_backdrop);
- immUniformColor3fv(color_backdrop);
- immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
- immUniformColor3ubv((uchar *)wcol->inner);
- immRectf(pos,
- rect->xmin + zoomx * (cumap->clipr.xmin - offsx),
- rect->ymin + zoomy * (cumap->clipr.ymin - offsy),
- rect->xmin + zoomx * (cumap->clipr.xmax - offsx),
- rect->ymin + zoomy * (cumap->clipr.ymax - offsy));
- }
- else {
- rgb_uchar_to_float(color_backdrop, (const uchar *)wcol->inner);
- immUniformColor3fv(color_backdrop);
- immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
- }
-
- /* grid, every 0.25 step */
- gl_shaded_color((uchar *)wcol->inner, -16);
- ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.25f);
- /* grid, every 1.0 step */
- gl_shaded_color((uchar *)wcol->inner, -24);
- ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 1.0f);
- /* axes */
- gl_shaded_color((uchar *)wcol->inner, -50);
- immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, rect->xmin, rect->ymin + zoomy * (-offsy));
- immVertex2f(pos, rect->xmax, rect->ymin + zoomy * (-offsy));
- immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymin);
- immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymax);
- immEnd();
- }
-
- /* cfra option */
- /* XXX 2.48 */
+ CurveMapping *cumap;
+
+ if (but->editcumap) {
+ cumap = but->editcumap;
+ }
+ else {
+ cumap = (CurveMapping *)but->poin;
+ }
+
+ CurveMap *cuma = &cumap->cm[cumap->cur];
+
+ /* need scissor test, curve can draw outside of boundary */
+ int scissor[4];
+ GPU_scissor_get_i(scissor);
+ rcti scissor_new = {
+ .xmin = rect->xmin,
+ .ymin = rect->ymin,
+ .xmax = rect->xmax,
+ .ymax = rect->ymax,
+ };
+ rcti scissor_region = {0, ar->winx, 0, ar->winy};
+ BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new);
+ GPU_scissor(scissor_new.xmin,
+ scissor_new.ymin,
+ BLI_rcti_size_x(&scissor_new),
+ BLI_rcti_size_y(&scissor_new));
+
+ /* calculate offset and zoom */
+ float zoomx = (BLI_rcti_size_x(rect) - 2.0f) / BLI_rctf_size_x(&cumap->curr);
+ float zoomy = (BLI_rcti_size_y(rect) - 2.0f) / BLI_rctf_size_y(&cumap->curr);
+ float offsx = cumap->curr.xmin - (1.0f / zoomx);
+ float offsy = cumap->curr.ymin - (1.0f / zoomy);
+
+ /* Do this first to not mess imm context */
+ if (but->a1 == UI_GRAD_H) {
+ /* magic trigger for curve backgrounds */
+ float col[3] = {0.0f, 0.0f, 0.0f}; /* dummy arg */
+
+ rcti grid = {
+ .xmin = rect->xmin + zoomx * (-offsx),
+ .xmax = grid.xmin + zoomx,
+ .ymin = rect->ymin + zoomy * (-offsy),
+ .ymax = grid.ymin + zoomy,
+ };
+
+ ui_draw_gradient(&grid, col, UI_GRAD_H, 1.0f);
+ }
+
+ GPU_line_width(1.0f);
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* backdrop */
+ float color_backdrop[4] = {0, 0, 0, 1};
+
+ if (but->a1 == UI_GRAD_H) {
+ /* grid, hsv uses different grid */
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ ARRAY_SET_ITEMS(color_backdrop, 0, 0, 0, 48.0 / 255.0);
+ immUniformColor4fv(color_backdrop);
+ ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.1666666f);
+ GPU_blend(false);
+ }
+ else {
+ if (cumap->flag & CUMA_DO_CLIP) {
+ gl_shaded_color_get_fl((uchar *)wcol->inner, -20, color_backdrop);
+ immUniformColor3fv(color_backdrop);
+ immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ immUniformColor3ubv((uchar *)wcol->inner);
+ immRectf(pos,
+ rect->xmin + zoomx * (cumap->clipr.xmin - offsx),
+ rect->ymin + zoomy * (cumap->clipr.ymin - offsy),
+ rect->xmin + zoomx * (cumap->clipr.xmax - offsx),
+ rect->ymin + zoomy * (cumap->clipr.ymax - offsy));
+ }
+ else {
+ rgb_uchar_to_float(color_backdrop, (const uchar *)wcol->inner);
+ immUniformColor3fv(color_backdrop);
+ immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ }
+
+ /* grid, every 0.25 step */
+ gl_shaded_color((uchar *)wcol->inner, -16);
+ ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.25f);
+ /* grid, every 1.0 step */
+ gl_shaded_color((uchar *)wcol->inner, -24);
+ ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 1.0f);
+ /* axes */
+ gl_shaded_color((uchar *)wcol->inner, -50);
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex2f(pos, rect->xmin, rect->ymin + zoomy * (-offsy));
+ immVertex2f(pos, rect->xmax, rect->ymin + zoomy * (-offsy));
+ immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymin);
+ immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymax);
+ immEnd();
+ }
+
+ /* cfra option */
+ /* XXX 2.48 */
#if 0
- if (cumap->flag & CUMA_DRAW_CFRA) {
- immUniformColor3ub(0x60, 0xc0, 0x40);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymin);
- immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymax);
- immEnd();
- }
+ if (cumap->flag & CUMA_DRAW_CFRA) {
+ immUniformColor3ub(0x60, 0xc0, 0x40);
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymin);
+ immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymax);
+ immEnd();
+ }
#endif
- /* sample option */
-
- if (cumap->flag & CUMA_DRAW_SAMPLE) {
- immBegin(GPU_PRIM_LINES, 2); /* will draw one of the following 3 lines */
- if (but->a1 == UI_GRAD_H) {
- float tsample[3];
- float hsv[3];
- linearrgb_to_srgb_v3_v3(tsample, cumap->sample);
- rgb_to_hsv_v(tsample, hsv);
- immUniformColor3ub(240, 240, 240);
-
- immVertex2f(pos, rect->xmin + zoomx * (hsv[0] - offsx), rect->ymin);
- immVertex2f(pos, rect->xmin + zoomx * (hsv[0] - offsx), rect->ymax);
- }
- else if (cumap->cur == 3) {
- float lum = IMB_colormanagement_get_luminance(cumap->sample);
- immUniformColor3ub(240, 240, 240);
-
- immVertex2f(pos, rect->xmin + zoomx * (lum - offsx), rect->ymin);
- immVertex2f(pos, rect->xmin + zoomx * (lum - offsx), rect->ymax);
- }
- else {
- if (cumap->cur == 0) {
- immUniformColor3ub(240, 100, 100);
- }
- else if (cumap->cur == 1) {
- immUniformColor3ub(100, 240, 100);
- }
- else {
- immUniformColor3ub(100, 100, 240);
- }
-
- immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymin);
- immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymax);
- }
- immEnd();
- }
- immUnbindProgram();
-
-
-
- if (cuma->table == NULL) {
- curvemapping_changed(cumap, false);
- }
-
- CurveMapPoint *cmp = cuma->table;
- rctf line_range;
-
- /* First curve point. */
- if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
- line_range.xmin = rect->xmin;
- line_range.ymin = rect->ymin + zoomy * (cmp[0].y - offsy);
- }
- else {
- line_range.xmin = rect->xmin + zoomx * (cmp[0].x - offsx + cuma->ext_in[0]);
- line_range.ymin = rect->ymin + zoomy * (cmp[0].y - offsy + cuma->ext_in[1]);
- }
- /* Last curve point. */
- if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
- line_range.xmax = rect->xmax;
- line_range.ymax = rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy);
- }
- else {
- line_range.xmax = rect->xmin + zoomx * (cmp[CM_TABLE].x - offsx - cuma->ext_out[0]);
- line_range.ymax = rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy - cuma->ext_out[1]);
- }
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- GPU_blend(true);
-
- /* Curve filled. */
- immUniformColor3ubvAlpha((uchar *)wcol->item, 128);
- GPU_polygon_smooth(true);
- immBegin(GPU_PRIM_TRI_STRIP, (CM_TABLE * 2 + 2) + 4);
- immVertex2f(pos, line_range.xmin, rect->ymin);
- immVertex2f(pos, line_range.xmin, line_range.ymin);
- for (int a = 0; a <= CM_TABLE; a++) {
- float fx = rect->xmin + zoomx * (cmp[a].x - offsx);
- float fy = rect->ymin + zoomy * (cmp[a].y - offsy);
- immVertex2f(pos, fx, rect->ymin);
- immVertex2f(pos, fx, fy);
- }
- immVertex2f(pos, line_range.xmax, rect->ymin);
- immVertex2f(pos, line_range.xmax, line_range.ymax);
- immEnd();
- GPU_polygon_smooth(false);
-
- /* Curve line. */
- GPU_line_width(1.0f);
- immUniformColor3ubvAlpha((uchar *)wcol->item, 255);
- GPU_line_smooth(true);
- immBegin(GPU_PRIM_LINE_STRIP, (CM_TABLE + 1) + 2);
- immVertex2f(pos, line_range.xmin, line_range.ymin);
- for (int a = 0; a <= CM_TABLE; a++) {
- float fx = rect->xmin + zoomx * (cmp[a].x - offsx);
- float fy = rect->ymin + zoomy * (cmp[a].y - offsy);
- immVertex2f(pos, fx, fy);
- }
- immVertex2f(pos, line_range.xmax, line_range.ymax);
- immEnd();
-
- /* Reset state for fill & line. */
- GPU_line_smooth(false);
- GPU_blend(false);
- immUnbindProgram();
-
- /* The points, use aspect to make them visible on edges. */
- format = immVertexFormat();
- pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
-
- /* Calculate vertex colors based on text theme. */
- float color_vert[4], color_vert_select[4];
- UI_GetThemeColor4fv(TH_TEXT_HI, color_vert);
- UI_GetThemeColor4fv(TH_TEXT, color_vert_select);
- if (len_squared_v3v3(color_vert, color_vert_select) < 0.1f) {
- interp_v3_v3v3(color_vert, color_vert_select, color_backdrop, 0.75f);
- }
- if (len_squared_v3(color_vert) > len_squared_v3(color_vert_select)) {
- /* Ensure brightest text color is used for selection. */
- swap_v3_v3(color_vert, color_vert_select);
- }
-
- cmp = cuma->curve;
- GPU_point_size(max_ff(1.0f, min_ff(UI_DPI_FAC / but->block->aspect * 4.0f, 4.0f)));
- immBegin(GPU_PRIM_POINTS, cuma->totpoint);
- for (int a = 0; a < cuma->totpoint; a++) {
- float fx = rect->xmin + zoomx * (cmp[a].x - offsx);
- float fy = rect->ymin + zoomy * (cmp[a].y - offsy);
- immAttr4fv(col, (cmp[a].flag & CUMA_SELECT) ? color_vert_select : color_vert);
- immVertex2f(pos, fx, fy);
- }
- immEnd();
- immUnbindProgram();
-
- /* restore scissortest */
- GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
-
- /* outline */
- format = immVertexFormat();
- pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- immUniformColor3ubv((uchar *)wcol->outline);
- imm_draw_box_wire_2d(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
-
- immUnbindProgram();
+ /* sample option */
+
+ if (cumap->flag & CUMA_DRAW_SAMPLE) {
+ immBegin(GPU_PRIM_LINES, 2); /* will draw one of the following 3 lines */
+ if (but->a1 == UI_GRAD_H) {
+ float tsample[3];
+ float hsv[3];
+ linearrgb_to_srgb_v3_v3(tsample, cumap->sample);
+ rgb_to_hsv_v(tsample, hsv);
+ immUniformColor3ub(240, 240, 240);
+
+ immVertex2f(pos, rect->xmin + zoomx * (hsv[0] - offsx), rect->ymin);
+ immVertex2f(pos, rect->xmin + zoomx * (hsv[0] - offsx), rect->ymax);
+ }
+ else if (cumap->cur == 3) {
+ float lum = IMB_colormanagement_get_luminance(cumap->sample);
+ immUniformColor3ub(240, 240, 240);
+
+ immVertex2f(pos, rect->xmin + zoomx * (lum - offsx), rect->ymin);
+ immVertex2f(pos, rect->xmin + zoomx * (lum - offsx), rect->ymax);
+ }
+ else {
+ if (cumap->cur == 0) {
+ immUniformColor3ub(240, 100, 100);
+ }
+ else if (cumap->cur == 1) {
+ immUniformColor3ub(100, 240, 100);
+ }
+ else {
+ immUniformColor3ub(100, 100, 240);
+ }
+
+ immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymin);
+ immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymax);
+ }
+ immEnd();
+ }
+ immUnbindProgram();
+
+ if (cuma->table == NULL) {
+ curvemapping_changed(cumap, false);
+ }
+
+ CurveMapPoint *cmp = cuma->table;
+ rctf line_range;
+
+ /* First curve point. */
+ if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
+ line_range.xmin = rect->xmin;
+ line_range.ymin = rect->ymin + zoomy * (cmp[0].y - offsy);
+ }
+ else {
+ line_range.xmin = rect->xmin + zoomx * (cmp[0].x - offsx + cuma->ext_in[0]);
+ line_range.ymin = rect->ymin + zoomy * (cmp[0].y - offsy + cuma->ext_in[1]);
+ }
+ /* Last curve point. */
+ if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
+ line_range.xmax = rect->xmax;
+ line_range.ymax = rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy);
+ }
+ else {
+ line_range.xmax = rect->xmin + zoomx * (cmp[CM_TABLE].x - offsx - cuma->ext_out[0]);
+ line_range.ymax = rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy - cuma->ext_out[1]);
+ }
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ GPU_blend(true);
+
+ /* Curve filled. */
+ immUniformColor3ubvAlpha((uchar *)wcol->item, 128);
+ GPU_polygon_smooth(true);
+ immBegin(GPU_PRIM_TRI_STRIP, (CM_TABLE * 2 + 2) + 4);
+ immVertex2f(pos, line_range.xmin, rect->ymin);
+ immVertex2f(pos, line_range.xmin, line_range.ymin);
+ for (int a = 0; a <= CM_TABLE; a++) {
+ float fx = rect->xmin + zoomx * (cmp[a].x - offsx);
+ float fy = rect->ymin + zoomy * (cmp[a].y - offsy);
+ immVertex2f(pos, fx, rect->ymin);
+ immVertex2f(pos, fx, fy);
+ }
+ immVertex2f(pos, line_range.xmax, rect->ymin);
+ immVertex2f(pos, line_range.xmax, line_range.ymax);
+ immEnd();
+ GPU_polygon_smooth(false);
+
+ /* Curve line. */
+ GPU_line_width(1.0f);
+ immUniformColor3ubvAlpha((uchar *)wcol->item, 255);
+ GPU_line_smooth(true);
+ immBegin(GPU_PRIM_LINE_STRIP, (CM_TABLE + 1) + 2);
+ immVertex2f(pos, line_range.xmin, line_range.ymin);
+ for (int a = 0; a <= CM_TABLE; a++) {
+ float fx = rect->xmin + zoomx * (cmp[a].x - offsx);
+ float fy = rect->ymin + zoomy * (cmp[a].y - offsy);
+ immVertex2f(pos, fx, fy);
+ }
+ immVertex2f(pos, line_range.xmax, line_range.ymax);
+ immEnd();
+
+ /* Reset state for fill & line. */
+ GPU_line_smooth(false);
+ GPU_blend(false);
+ immUnbindProgram();
+
+ /* The points, use aspect to make them visible on edges. */
+ format = immVertexFormat();
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
+ /* Calculate vertex colors based on text theme. */
+ float color_vert[4], color_vert_select[4];
+ UI_GetThemeColor4fv(TH_TEXT_HI, color_vert);
+ UI_GetThemeColor4fv(TH_TEXT, color_vert_select);
+ if (len_squared_v3v3(color_vert, color_vert_select) < 0.1f) {
+ interp_v3_v3v3(color_vert, color_vert_select, color_backdrop, 0.75f);
+ }
+ if (len_squared_v3(color_vert) > len_squared_v3(color_vert_select)) {
+ /* Ensure brightest text color is used for selection. */
+ swap_v3_v3(color_vert, color_vert_select);
+ }
+
+ cmp = cuma->curve;
+ GPU_point_size(max_ff(1.0f, min_ff(UI_DPI_FAC / but->block->aspect * 4.0f, 4.0f)));
+ immBegin(GPU_PRIM_POINTS, cuma->totpoint);
+ for (int a = 0; a < cuma->totpoint; a++) {
+ float fx = rect->xmin + zoomx * (cmp[a].x - offsx);
+ float fy = rect->ymin + zoomy * (cmp[a].y - offsy);
+ immAttr4fv(col, (cmp[a].flag & CUMA_SELECT) ? color_vert_select : color_vert);
+ immVertex2f(pos, fx, fy);
+ }
+ immEnd();
+ immUnbindProgram();
+
+ /* restore scissortest */
+ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+
+ /* outline */
+ format = immVertexFormat();
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3ubv((uchar *)wcol->outline);
+ imm_draw_box_wire_2d(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+
+ immUnbindProgram();
}
-void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(ar), uiBut *but, const uiWidgetColors *UNUSED(wcol), const rcti *recti)
+void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(ar),
+ uiBut *but,
+ const uiWidgetColors *UNUSED(wcol),
+ const rcti *recti)
{
- bool ok = false;
- MovieClipScopes *scopes = (MovieClipScopes *)but->poin;
-
- rctf rect = {
- .xmin = (float)recti->xmin + 1,
- .xmax = (float)recti->xmax - 1,
- .ymin = (float)recti->ymin + 1,
- .ymax = (float)recti->ymax - 1,
- };
-
- int width = BLI_rctf_size_x(&rect) + 1;
- int height = BLI_rctf_size_y(&rect);
-
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- /* need scissor test, preview image can draw outside of boundary */
- int scissor[4];
- GPU_scissor_get_i(scissor);
- GPU_scissor(
- (rect.xmin - 1),
- (rect.ymin - 1),
- (rect.xmax + 1) - (rect.xmin - 1),
- (rect.ymax + 1) - (rect.ymin - 1));
-
- if (scopes->track_disabled) {
- float color[4] = {0.7f, 0.3f, 0.3f, 0.3f};
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
-
- ok = true;
- }
- else if ((scopes->track_search) &&
- ((!scopes->track_preview) ||
- (scopes->track_preview->x != width || scopes->track_preview->y != height)))
- {
- if (scopes->track_preview) {
- IMB_freeImBuf(scopes->track_preview);
- }
-
- ImBuf *tmpibuf = BKE_tracking_sample_pattern(
- scopes->frame_width, scopes->frame_height,
- scopes->track_search, scopes->track,
- &scopes->undist_marker, true, scopes->use_track_mask,
- width, height, scopes->track_pos);
- if (tmpibuf) {
- if (tmpibuf->rect_float) {
- IMB_rect_from_float(tmpibuf);
- }
-
- if (tmpibuf->rect) {
- scopes->track_preview = tmpibuf;
- }
- else {
- IMB_freeImBuf(tmpibuf);
- }
- }
- }
-
- if (!ok && scopes->track_preview) {
- GPU_matrix_push();
-
- /* draw content of pattern area */
- GPU_scissor(rect.xmin, rect.ymin, scissor[2], scissor[3]);
-
- if (width > 0 && height > 0) {
- ImBuf *drawibuf = scopes->track_preview;
- float col_sel[4], col_outline[4];
-
- if (scopes->use_track_mask) {
- float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
- }
-
- IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
- immDrawPixelsTex(&state, rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, drawibuf->rect, 1.0f, 1.0f, NULL);
-
- /* draw cross for pixel position */
- GPU_matrix_translate_2f(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1]);
- GPU_scissor(
- rect.xmin,
- rect.ymin,
- BLI_rctf_size_x(&rect),
- BLI_rctf_size_y(&rect));
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
-
- UI_GetThemeColor4fv(TH_SEL_MARKER, col_sel);
- UI_GetThemeColor4fv(TH_MARKER_OUTLINE, col_outline);
-
- /* Do stipple cross with geometry */
- immBegin(GPU_PRIM_LINES, 7 * 2 * 2);
- float pos_sel[8] = {-10.0f, -7.0f, -4.0f, -1.0f, 2.0f, 5.0f, 8.0f, 11.0f};
- for (int axe = 0; axe < 2; ++axe) {
- for (int i = 0; i < 7; ++i) {
- float x1 = pos_sel[i] * (1 - axe);
- float y1 = pos_sel[i] * axe;
- float x2 = pos_sel[i + 1] * (1 - axe);
- float y2 = pos_sel[i + 1] * axe;
-
- if (i % 2 == 1) {
- immAttr4fv(col, col_sel);
- }
- else {
- immAttr4fv(col, col_outline);
- }
-
- immVertex2f(pos, x1, y1);
- immVertex2f(pos, x2, y2);
- }
- }
- immEnd();
-
- immUnbindProgram();
- }
-
- GPU_matrix_pop();
-
- ok = true;
- }
-
- if (!ok) {
- float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
- }
-
- /* outline */
- draw_scope_end(&rect, scissor);
-
- GPU_blend(false);
+ bool ok = false;
+ MovieClipScopes *scopes = (MovieClipScopes *)but->poin;
+
+ rctf rect = {
+ .xmin = (float)recti->xmin + 1,
+ .xmax = (float)recti->xmax - 1,
+ .ymin = (float)recti->ymin + 1,
+ .ymax = (float)recti->ymax - 1,
+ };
+
+ int width = BLI_rctf_size_x(&rect) + 1;
+ int height = BLI_rctf_size_y(&rect);
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ /* need scissor test, preview image can draw outside of boundary */
+ int scissor[4];
+ GPU_scissor_get_i(scissor);
+ GPU_scissor((rect.xmin - 1),
+ (rect.ymin - 1),
+ (rect.xmax + 1) - (rect.xmin - 1),
+ (rect.ymax + 1) - (rect.ymin - 1));
+
+ if (scopes->track_disabled) {
+ float color[4] = {0.7f, 0.3f, 0.3f, 0.3f};
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_4fv(
+ true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
+
+ ok = true;
+ }
+ else if ((scopes->track_search) &&
+ ((!scopes->track_preview) ||
+ (scopes->track_preview->x != width || scopes->track_preview->y != height))) {
+ if (scopes->track_preview) {
+ IMB_freeImBuf(scopes->track_preview);
+ }
+
+ ImBuf *tmpibuf = BKE_tracking_sample_pattern(scopes->frame_width,
+ scopes->frame_height,
+ scopes->track_search,
+ scopes->track,
+ &scopes->undist_marker,
+ true,
+ scopes->use_track_mask,
+ width,
+ height,
+ scopes->track_pos);
+ if (tmpibuf) {
+ if (tmpibuf->rect_float) {
+ IMB_rect_from_float(tmpibuf);
+ }
+
+ if (tmpibuf->rect) {
+ scopes->track_preview = tmpibuf;
+ }
+ else {
+ IMB_freeImBuf(tmpibuf);
+ }
+ }
+ }
+
+ if (!ok && scopes->track_preview) {
+ GPU_matrix_push();
+
+ /* draw content of pattern area */
+ GPU_scissor(rect.xmin, rect.ymin, scissor[2], scissor[3]);
+
+ if (width > 0 && height > 0) {
+ ImBuf *drawibuf = scopes->track_preview;
+ float col_sel[4], col_outline[4];
+
+ if (scopes->use_track_mask) {
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_4fv(
+ true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
+ }
+
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(&state,
+ rect.xmin,
+ rect.ymin + 1,
+ drawibuf->x,
+ drawibuf->y,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ GL_LINEAR,
+ drawibuf->rect,
+ 1.0f,
+ 1.0f,
+ NULL);
+
+ /* draw cross for pixel position */
+ GPU_matrix_translate_2f(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1]);
+ GPU_scissor(rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), BLI_rctf_size_y(&rect));
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
+ UI_GetThemeColor4fv(TH_SEL_MARKER, col_sel);
+ UI_GetThemeColor4fv(TH_MARKER_OUTLINE, col_outline);
+
+ /* Do stipple cross with geometry */
+ immBegin(GPU_PRIM_LINES, 7 * 2 * 2);
+ float pos_sel[8] = {-10.0f, -7.0f, -4.0f, -1.0f, 2.0f, 5.0f, 8.0f, 11.0f};
+ for (int axe = 0; axe < 2; ++axe) {
+ for (int i = 0; i < 7; ++i) {
+ float x1 = pos_sel[i] * (1 - axe);
+ float y1 = pos_sel[i] * axe;
+ float x2 = pos_sel[i + 1] * (1 - axe);
+ float y2 = pos_sel[i + 1] * axe;
+
+ if (i % 2 == 1) {
+ immAttr4fv(col, col_sel);
+ }
+ else {
+ immAttr4fv(col, col_outline);
+ }
+
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y2);
+ }
+ }
+ immEnd();
+
+ immUnbindProgram();
+ }
+
+ GPU_matrix_pop();
+
+ ok = true;
+ }
+
+ if (!ok) {
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_4fv(
+ true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
+ }
+
+ /* outline */
+ draw_scope_end(&rect, scissor);
+
+ GPU_blend(false);
}
-void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, const uiWidgetColors *UNUSED(wcol), const rcti *recti)
+void ui_draw_but_NODESOCKET(ARegion *ar,
+ uiBut *but,
+ const uiWidgetColors *UNUSED(wcol),
+ const rcti *recti)
{
- static const float size = 5.0f;
-
- /* 16 values of sin function */
- const float si[16] = {
- 0.00000000f, 0.39435585f, 0.72479278f, 0.93775213f,
- 0.99871650f, 0.89780453f, 0.65137248f, 0.29936312f,
- -0.10116832f, -0.48530196f, -0.79077573f, -0.96807711f,
- -0.98846832f, -0.84864425f, -0.57126821f, -0.20129852f,
- };
- /* 16 values of cos function */
- const float co[16] = {
- 1.00000000f, 0.91895781f, 0.68896691f, 0.34730525f,
- -0.05064916f, -0.44039415f, -0.75875812f, -0.95413925f,
- -0.99486932f, -0.87434661f, -0.61210598f, -0.25065253f,
- 0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f,
- };
-
- int scissor[4];
-
- /* need scissor test, can draw outside of boundary */
- GPU_scissor_get_i(scissor);
-
- rcti scissor_new = {
- .xmin = recti->xmin,
- .ymin = recti->ymin,
- .xmax = recti->xmax,
- .ymax = recti->ymax,
- };
-
- rcti scissor_region = {0, ar->winx, 0, ar->winy};
-
- BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new);
- GPU_scissor(
- scissor_new.xmin,
- scissor_new.ymin,
- BLI_rcti_size_x(&scissor_new),
- BLI_rcti_size_y(&scissor_new));
-
- float x = 0.5f * (recti->xmin + recti->xmax);
- float y = 0.5f * (recti->ymin + recti->ymax);
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4ubv(but->col);
-
- GPU_blend(true);
- immBegin(GPU_PRIM_TRI_FAN, 16);
- for (int a = 0; a < 16; a++) {
- immVertex2f(pos, x + size * si[a], y + size * co[a]);
- }
- immEnd();
-
- immUniformColor4ub(0, 0, 0, 150);
- GPU_line_width(1);
- GPU_line_smooth(true);
- immBegin(GPU_PRIM_LINE_LOOP, 16);
- for (int a = 0; a < 16; a++) {
- immVertex2f(pos, x + size * si[a], y + size * co[a]);
- }
- immEnd();
- GPU_line_smooth(false);
- GPU_blend(false);
-
- immUnbindProgram();
-
- /* restore scissortest */
- GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+ static const float size = 5.0f;
+
+ /* 16 values of sin function */
+ const float si[16] = {
+ 0.00000000f,
+ 0.39435585f,
+ 0.72479278f,
+ 0.93775213f,
+ 0.99871650f,
+ 0.89780453f,
+ 0.65137248f,
+ 0.29936312f,
+ -0.10116832f,
+ -0.48530196f,
+ -0.79077573f,
+ -0.96807711f,
+ -0.98846832f,
+ -0.84864425f,
+ -0.57126821f,
+ -0.20129852f,
+ };
+ /* 16 values of cos function */
+ const float co[16] = {
+ 1.00000000f,
+ 0.91895781f,
+ 0.68896691f,
+ 0.34730525f,
+ -0.05064916f,
+ -0.44039415f,
+ -0.75875812f,
+ -0.95413925f,
+ -0.99486932f,
+ -0.87434661f,
+ -0.61210598f,
+ -0.25065253f,
+ 0.15142777f,
+ 0.52896401f,
+ 0.82076344f,
+ 0.97952994f,
+ };
+
+ int scissor[4];
+
+ /* need scissor test, can draw outside of boundary */
+ GPU_scissor_get_i(scissor);
+
+ rcti scissor_new = {
+ .xmin = recti->xmin,
+ .ymin = recti->ymin,
+ .xmax = recti->xmax,
+ .ymax = recti->ymax,
+ };
+
+ rcti scissor_region = {0, ar->winx, 0, ar->winy};
+
+ BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new);
+ GPU_scissor(scissor_new.xmin,
+ scissor_new.ymin,
+ BLI_rcti_size_x(&scissor_new),
+ BLI_rcti_size_y(&scissor_new));
+
+ float x = 0.5f * (recti->xmin + recti->xmax);
+ float y = 0.5f * (recti->ymin + recti->ymax);
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv(but->col);
+
+ GPU_blend(true);
+ immBegin(GPU_PRIM_TRI_FAN, 16);
+ for (int a = 0; a < 16; a++) {
+ immVertex2f(pos, x + size * si[a], y + size * co[a]);
+ }
+ immEnd();
+
+ immUniformColor4ub(0, 0, 0, 150);
+ GPU_line_width(1);
+ GPU_line_smooth(true);
+ immBegin(GPU_PRIM_LINE_LOOP, 16);
+ for (int a = 0; a < 16; a++) {
+ immVertex2f(pos, x + size * si[a], y + size * co[a]);
+ }
+ immEnd();
+ GPU_line_smooth(false);
+ GPU_blend(false);
+
+ immUnbindProgram();
+
+ /* restore scissortest */
+ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
}
/* ****************************************************** */
@@ -2157,157 +2335,175 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, const uiWidgetColors *UNUSE
* would replace / modify the following 3 functions - merwin
*/
-static void ui_shadowbox(uint pos, uint color, float minx, float miny, float maxx, float maxy, float shadsize, uchar alpha)
+static void ui_shadowbox(uint pos,
+ uint color,
+ float minx,
+ float miny,
+ float maxx,
+ float maxy,
+ float shadsize,
+ uchar alpha)
{
- /**
- * <pre>
- * v1-_
- * | -_v2
- * | |
- * | |
- * | |
- * v7_______v3____v4
- * \ | /
- * \ | _v5
- * v8______v6_-
- * </pre>
- */
- const float v1[2] = {maxx, maxy - 0.3f * shadsize};
- const float v2[2] = {maxx + shadsize, maxy - 0.75f * shadsize};
- const float v3[2] = {maxx, miny};
- const float v4[2] = {maxx + shadsize, miny};
-
- const float v5[2] = {maxx + 0.7f * shadsize, miny - 0.7f * shadsize};
-
- const float v6[2] = {maxx, miny - shadsize};
- const float v7[2] = {minx + 0.3f * shadsize, miny};
- const float v8[2] = {minx + 0.5f * shadsize, miny - shadsize};
-
- /* right quad */
- immAttr4ub(color, 0, 0, 0, alpha);
- immVertex2fv(pos, v3);
- immVertex2fv(pos, v1);
- immAttr4ub(color, 0, 0, 0, 0);
- immVertex2fv(pos, v2);
-
- immVertex2fv(pos, v2);
- immVertex2fv(pos, v4);
- immAttr4ub(color, 0, 0, 0, alpha);
- immVertex2fv(pos, v3);
-
- /* corner shape */
- /* immAttr4ub(color, 0, 0, 0, alpha); */ /* Not needed, done above in previous tri */
- immVertex2fv(pos, v3);
- immAttr4ub(color, 0, 0, 0, 0);
- immVertex2fv(pos, v4);
- immVertex2fv(pos, v5);
-
- immVertex2fv(pos, v5);
- immVertex2fv(pos, v6);
- immAttr4ub(color, 0, 0, 0, alpha);
- immVertex2fv(pos, v3);
-
- /* bottom quad */
- /* immAttr4ub(color, 0, 0, 0, alpha); */ /* Not needed, done above in previous tri */
- immVertex2fv(pos, v3);
- immAttr4ub(color, 0, 0, 0, 0);
- immVertex2fv(pos, v6);
- immVertex2fv(pos, v8);
-
- immVertex2fv(pos, v8);
- immAttr4ub(color, 0, 0, 0, alpha);
- immVertex2fv(pos, v7);
- immVertex2fv(pos, v3);
+ /**
+ * <pre>
+ * v1-_
+ * | -_v2
+ * | |
+ * | |
+ * | |
+ * v7_______v3____v4
+ * \ | /
+ * \ | _v5
+ * v8______v6_-
+ * </pre>
+ */
+ const float v1[2] = {maxx, maxy - 0.3f * shadsize};
+ const float v2[2] = {maxx + shadsize, maxy - 0.75f * shadsize};
+ const float v3[2] = {maxx, miny};
+ const float v4[2] = {maxx + shadsize, miny};
+
+ const float v5[2] = {maxx + 0.7f * shadsize, miny - 0.7f * shadsize};
+
+ const float v6[2] = {maxx, miny - shadsize};
+ const float v7[2] = {minx + 0.3f * shadsize, miny};
+ const float v8[2] = {minx + 0.5f * shadsize, miny - shadsize};
+
+ /* right quad */
+ immAttr4ub(color, 0, 0, 0, alpha);
+ immVertex2fv(pos, v3);
+ immVertex2fv(pos, v1);
+ immAttr4ub(color, 0, 0, 0, 0);
+ immVertex2fv(pos, v2);
+
+ immVertex2fv(pos, v2);
+ immVertex2fv(pos, v4);
+ immAttr4ub(color, 0, 0, 0, alpha);
+ immVertex2fv(pos, v3);
+
+ /* corner shape */
+ /* immAttr4ub(color, 0, 0, 0, alpha); */ /* Not needed, done above in previous tri */
+ immVertex2fv(pos, v3);
+ immAttr4ub(color, 0, 0, 0, 0);
+ immVertex2fv(pos, v4);
+ immVertex2fv(pos, v5);
+
+ immVertex2fv(pos, v5);
+ immVertex2fv(pos, v6);
+ immAttr4ub(color, 0, 0, 0, alpha);
+ immVertex2fv(pos, v3);
+
+ /* bottom quad */
+ /* immAttr4ub(color, 0, 0, 0, alpha); */ /* Not needed, done above in previous tri */
+ immVertex2fv(pos, v3);
+ immAttr4ub(color, 0, 0, 0, 0);
+ immVertex2fv(pos, v6);
+ immVertex2fv(pos, v8);
+
+ immVertex2fv(pos, v8);
+ immAttr4ub(color, 0, 0, 0, alpha);
+ immVertex2fv(pos, v7);
+ immVertex2fv(pos, v3);
}
void UI_draw_box_shadow(uchar alpha, float minx, float miny, float maxx, float maxy)
{
- GPU_blend(true);
+ GPU_blend(true);
- GPUVertFormat *format = immVertexFormat();
- 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_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ 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_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
- immBegin(GPU_PRIM_TRIS, 54);
+ immBegin(GPU_PRIM_TRIS, 54);
- /* accumulated outline boxes to make shade not linear, is more pleasant */
- ui_shadowbox(pos, color, minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8);
- ui_shadowbox(pos, color, minx, miny, maxx, maxy, 7.0, (40 * alpha) >> 8);
- ui_shadowbox(pos, color, minx, miny, maxx, maxy, 5.0, (80 * alpha) >> 8);
+ /* accumulated outline boxes to make shade not linear, is more pleasant */
+ ui_shadowbox(pos, color, minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8);
+ ui_shadowbox(pos, color, minx, miny, maxx, maxy, 7.0, (40 * alpha) >> 8);
+ ui_shadowbox(pos, color, minx, miny, maxx, maxy, 5.0, (80 * alpha) >> 8);
- immEnd();
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
- GPU_blend(false);
+ GPU_blend(false);
}
-
-void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int UNUSED(select))
+void ui_draw_dropshadow(
+ const rctf *rct, float radius, float aspect, float alpha, int UNUSED(select))
{
- float rad;
+ float rad;
- if (radius > (BLI_rctf_size_y(rct) - 10.0f) * 0.5f) {
- rad = (BLI_rctf_size_y(rct) - 10.0f) * 0.5f;
- }
- else {
- rad = radius;
- }
+ if (radius > (BLI_rctf_size_y(rct) - 10.0f) * 0.5f) {
+ rad = (BLI_rctf_size_y(rct) - 10.0f) * 0.5f;
+ }
+ else {
+ rad = radius;
+ }
- int a, i = 12;
+ int a, i = 12;
#if 0
- if (select) {
- a = i * aspect; /* same as below */
- }
- else
+ if (select) {
+ a = i * aspect; /* same as below */
+ }
+ else
#endif
- {
- a = i * aspect;
- }
-
- GPU_blend(true);
- const float dalpha = alpha * 2.0f / 255.0f;
- float calpha = dalpha;
- float visibility = 1.0f;
- for (; i--;) {
- /* alpha ranges from 2 to 20 or so */
+ {
+ a = i * aspect;
+ }
+
+ GPU_blend(true);
+ const float dalpha = alpha * 2.0f / 255.0f;
+ float calpha = dalpha;
+ float visibility = 1.0f;
+ for (; i--;) {
+ /* alpha ranges from 2 to 20 or so */
#if 0 /* Old Method (pre 2.8) */
- float color[4] = {0.0f, 0.0f, 0.0f, calpha};
- UI_draw_roundbox_4fv(true, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a, color);
+ float color[4] = {0.0f, 0.0f, 0.0f, calpha};
+ UI_draw_roundbox_4fv(true, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a, color);
#endif
- /* Compute final visibility to match old method result. */
- /* TODO we could just find a better fit function inside the shader instead of this. */
- visibility = visibility * (1.0f - calpha);
- calpha += dalpha;
- }
-
- uiWidgetBaseParameters widget_params = {
- .recti.xmin = rct->xmin, .recti.ymin = rct->ymin,
- .recti.xmax = rct->xmax, .recti.ymax = rct->ymax - 10.0f,
- .rect.xmin = rct->xmin - a, .rect.ymin = rct->ymin - a,
- .rect.xmax = rct->xmax + a, .rect.ymax = rct->ymax - 10.0f + a,
- .radi = rad,
- .rad = rad + a,
- .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
- .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
- .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
- .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
- .alpha_discard = 1.0f,
- };
-
- GPUBatch *batch = ui_batch_roundbox_shadow_get();
- GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_SHADOW);
- GPU_batch_uniform_4fv_array(batch, "parameters", 4, (float *)&widget_params);
- GPU_batch_uniform_1f(batch, "alpha", 1.0f - visibility);
- GPU_batch_draw(batch);
-
- /* outline emphasis */
- GPU_line_smooth(true);
- float color[4] = {0.0f, 0.0f, 0.0f, 0.4f};
- UI_draw_roundbox_4fv(false, rct->xmin - 0.5f, rct->ymin - 0.5f, rct->xmax + 0.5f, rct->ymax + 0.5f, radius + 0.5f, color);
- GPU_line_smooth(false);
-
- GPU_blend(false);
+ /* Compute final visibility to match old method result. */
+ /* TODO we could just find a better fit function inside the shader instead of this. */
+ visibility = visibility * (1.0f - calpha);
+ calpha += dalpha;
+ }
+
+ uiWidgetBaseParameters widget_params = {
+ .recti.xmin = rct->xmin,
+ .recti.ymin = rct->ymin,
+ .recti.xmax = rct->xmax,
+ .recti.ymax = rct->ymax - 10.0f,
+ .rect.xmin = rct->xmin - a,
+ .rect.ymin = rct->ymin - a,
+ .rect.xmax = rct->xmax + a,
+ .rect.ymax = rct->ymax - 10.0f + a,
+ .radi = rad,
+ .rad = rad + a,
+ .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
+ .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
+ .alpha_discard = 1.0f,
+ };
+
+ GPUBatch *batch = ui_batch_roundbox_shadow_get();
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_SHADOW);
+ GPU_batch_uniform_4fv_array(batch, "parameters", 4, (float *)&widget_params);
+ GPU_batch_uniform_1f(batch, "alpha", 1.0f - visibility);
+ GPU_batch_draw(batch);
+
+ /* outline emphasis */
+ GPU_line_smooth(true);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.4f};
+ UI_draw_roundbox_4fv(false,
+ rct->xmin - 0.5f,
+ rct->ymin - 0.5f,
+ rct->xmax + 0.5f,
+ rct->ymax + 0.5f,
+ radius + 0.5f,
+ color);
+ GPU_line_smooth(false);
+
+ GPU_blend(false);
}
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index 0f0d2c355e8..3c26c37b610 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -36,7 +36,7 @@
#include "interface_intern.h"
-#include "interface_eyedropper_intern.h" /* own include */
+#include "interface_eyedropper_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/* Keymap
@@ -44,62 +44,61 @@
/** \name Modal Keymap
* \{ */
-
wmKeyMap *eyedropper_modal_keymap(wmKeyConfig *keyconf)
{
- static const EnumPropertyItem modal_items[] = {
- {EYE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
- {EYE_MODAL_SAMPLE_CONFIRM, "SAMPLE_CONFIRM", 0, "Confirm Sampling", ""},
- {EYE_MODAL_SAMPLE_BEGIN, "SAMPLE_BEGIN", 0, "Start Sampling", ""},
- {EYE_MODAL_SAMPLE_RESET, "SAMPLE_RESET", 0, "Reset Sampling", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- wmKeyMap *keymap = WM_modalkeymap_get(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);
-
- /* assign to operators */
- WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_colorramp");
- WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_color");
- WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_id");
- WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_depth");
- WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_driver");
-
- return keymap;
+ static const EnumPropertyItem modal_items[] = {
+ {EYE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
+ {EYE_MODAL_SAMPLE_CONFIRM, "SAMPLE_CONFIRM", 0, "Confirm Sampling", ""},
+ {EYE_MODAL_SAMPLE_BEGIN, "SAMPLE_BEGIN", 0, "Start Sampling", ""},
+ {EYE_MODAL_SAMPLE_RESET, "SAMPLE_RESET", 0, "Reset Sampling", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ wmKeyMap *keymap = WM_modalkeymap_get(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);
+
+ /* assign to operators */
+ WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_colorramp");
+ WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_color");
+ WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_id");
+ WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_depth");
+ WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_driver");
+
+ return keymap;
}
wmKeyMap *eyedropper_colorband_modal_keymap(wmKeyConfig *keyconf)
{
- static const EnumPropertyItem modal_items_point[] = {
- {EYE_MODAL_POINT_CANCEL, "CANCEL", 0, "Cancel", ""},
- {EYE_MODAL_POINT_SAMPLE, "SAMPLE_SAMPLE", 0, "Sample a point", ""},
- {EYE_MODAL_POINT_CONFIRM, "SAMPLE_CONFIRM", 0, "Confirm Sampling", ""},
- {EYE_MODAL_POINT_RESET, "SAMPLE_RESET", 0, "Reset Sampling", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Eyedropper ColorRamp PointSampling Map");
- if (keymap && keymap->modal_items) {
- return keymap;
- }
-
- keymap = WM_modalkeymap_add(keyconf, "Eyedropper ColorRamp PointSampling Map", modal_items_point);
-
- /* assign to operators */
- WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_colorramp_point");
-
- return keymap;
+ static const EnumPropertyItem modal_items_point[] = {
+ {EYE_MODAL_POINT_CANCEL, "CANCEL", 0, "Cancel", ""},
+ {EYE_MODAL_POINT_SAMPLE, "SAMPLE_SAMPLE", 0, "Sample a point", ""},
+ {EYE_MODAL_POINT_CONFIRM, "SAMPLE_CONFIRM", 0, "Confirm Sampling", ""},
+ {EYE_MODAL_POINT_RESET, "SAMPLE_RESET", 0, "Reset Sampling", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Eyedropper ColorRamp PointSampling Map");
+ if (keymap && keymap->modal_items) {
+ return keymap;
+ }
+
+ keymap = WM_modalkeymap_add(
+ keyconf, "Eyedropper ColorRamp PointSampling Map", modal_items_point);
+
+ /* assign to operators */
+ WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_colorramp_point");
+
+ return keymap;
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Utility Functions
*/
@@ -108,29 +107,25 @@ wmKeyMap *eyedropper_colorband_modal_keymap(wmKeyConfig *keyconf)
void eyedropper_draw_cursor_text(const struct bContext *C, const ARegion *ar, const char *name)
{
- const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- wmWindow *win = CTX_wm_window(C);
- int x = win->eventstate->x;
- int y = win->eventstate->y;
- 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};
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ wmWindow *win = CTX_wm_window(C);
+ int x = win->eventstate->x;
+ int y = win->eventstate->y;
+ 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)) {
+ return;
+ }
- if ((name[0] == '\0') ||
- (BLI_rcti_isect_pt(&ar->winrct, x, y) == false))
- {
- return;
- }
+ x = x - ar->winrct.xmin;
+ y = y - ar->winrct.ymin;
- x = x - ar->winrct.xmin;
- y = y - ar->winrct.ymin;
+ y += U.widget_unit;
- y += U.widget_unit;
-
- UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, col_fg, col_bg);
+ UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, col_fg, col_bg);
}
-
/**
* Utility to retrieve a button representing a RNA property that is currently under the cursor.
*
@@ -142,18 +137,18 @@ 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);
-
- uiBut *but = ui_but_find_mouse_over(ar, event);
-
- if (ELEM(NULL, but, but->rnapoin.data, but->rnaprop)) {
- return NULL;
- }
- else {
- return but;
- }
+ 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);
+
+ uiBut *but = ui_but_find_mouse_over(ar, event);
+
+ if (ELEM(NULL, but, but->rnapoin.data, but->rnaprop)) {
+ return NULL;
+ }
+ else {
+ return but;
+ }
}
/** \} */
diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c
index e2f85c4d7cc..68c12fe7652 100644
--- a/source/blender/editors/interface/interface_eyedropper_color.c
+++ b/source/blender/editors/interface/interface_eyedropper_color.c
@@ -59,70 +59,68 @@
#include "interface_eyedropper_intern.h"
typedef struct Eyedropper {
- struct ColorManagedDisplay *display;
+ struct ColorManagedDisplay *display;
- PointerRNA ptr;
- PropertyRNA *prop;
- int index;
- bool is_undo;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+ bool is_undo;
- bool is_set;
- float init_col[3]; /* for resetting on cancel */
+ bool is_set;
+ float init_col[3]; /* for resetting on cancel */
- bool accum_start; /* has mouse been pressed */
- float accum_col[3];
- int accum_tot;
+ bool accum_start; /* has mouse been pressed */
+ float accum_col[3];
+ int accum_tot;
- bool use_accum;
+ bool use_accum;
} Eyedropper;
static bool eyedropper_init(bContext *C, wmOperator *op)
{
- Eyedropper *eye = MEM_callocN(sizeof(Eyedropper), __func__);
- eye->use_accum = RNA_boolean_get(op->ptr, "use_accumulate");
-
- uiBut *but = UI_context_active_but_prop_get(C, &eye->ptr, &eye->prop, &eye->index);
-
- if ((eye->ptr.data == NULL) ||
- (eye->prop == NULL) ||
- (RNA_property_editable(&eye->ptr, eye->prop) == false) ||
- (RNA_property_array_length(&eye->ptr, eye->prop) < 3) ||
- (RNA_property_type(eye->prop) != PROP_FLOAT))
- {
- MEM_freeN(eye);
- return false;
- }
- op->customdata = eye;
-
- eye->is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
-
- float col[4];
- RNA_property_float_get_array(&eye->ptr, eye->prop, col);
- if (RNA_property_subtype(eye->prop) != PROP_COLOR) {
- Scene *scene = CTX_data_scene(C);
- const char *display_device;
-
- display_device = scene->display_settings.display_device;
- eye->display = IMB_colormanagement_display_get_named(display_device);
-
- /* store initial color */
- if (eye->display) {
- IMB_colormanagement_display_to_scene_linear_v3(col, eye->display);
- }
- }
- copy_v3_v3(eye->init_col, col);
-
- return true;
+ Eyedropper *eye = MEM_callocN(sizeof(Eyedropper), __func__);
+ eye->use_accum = RNA_boolean_get(op->ptr, "use_accumulate");
+
+ uiBut *but = UI_context_active_but_prop_get(C, &eye->ptr, &eye->prop, &eye->index);
+
+ if ((eye->ptr.data == NULL) || (eye->prop == NULL) ||
+ (RNA_property_editable(&eye->ptr, eye->prop) == false) ||
+ (RNA_property_array_length(&eye->ptr, eye->prop) < 3) ||
+ (RNA_property_type(eye->prop) != PROP_FLOAT)) {
+ MEM_freeN(eye);
+ return false;
+ }
+ op->customdata = eye;
+
+ eye->is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
+
+ float col[4];
+ RNA_property_float_get_array(&eye->ptr, eye->prop, col);
+ if (RNA_property_subtype(eye->prop) != PROP_COLOR) {
+ Scene *scene = CTX_data_scene(C);
+ const char *display_device;
+
+ display_device = scene->display_settings.display_device;
+ eye->display = IMB_colormanagement_display_get_named(display_device);
+
+ /* store initial color */
+ if (eye->display) {
+ IMB_colormanagement_display_to_scene_linear_v3(col, eye->display);
+ }
+ }
+ copy_v3_v3(eye->init_col, col);
+
+ return true;
}
static void eyedropper_exit(bContext *C, wmOperator *op)
{
- WM_cursor_modal_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
- if (op->customdata) {
- MEM_freeN(op->customdata);
- op->customdata = NULL;
- }
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+ }
}
/* *** eyedropper_color_ helper functions *** */
@@ -136,224 +134,220 @@ static void eyedropper_exit(bContext *C, wmOperator *op)
*/
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);
- 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 (ED_space_image_color_sample(sima, ar, 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};
-
- if (ED_space_node_color_sample(bmain, snode, ar, 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};
-
- if (ED_space_clip_color_sample(sc, ar, mval, r_col)) {
- return;
- }
- }
- }
- }
-
- /* fallback to simple opengl picker */
- glReadBuffer(GL_FRONT);
- glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, r_col);
- glReadBuffer(GL_BACK);
-
- IMB_colormanagement_display_to_scene_linear_v3(r_col, display);
+ /* 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);
+ 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 (ED_space_image_color_sample(sima, ar, 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};
+
+ if (ED_space_node_color_sample(bmain, snode, ar, 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};
+
+ if (ED_space_clip_color_sample(sc, ar, mval, r_col)) {
+ return;
+ }
+ }
+ }
+ }
+
+ /* fallback to simple opengl picker */
+ glReadBuffer(GL_FRONT);
+ glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, r_col);
+ glReadBuffer(GL_BACK);
+
+ IMB_colormanagement_display_to_scene_linear_v3(r_col, display);
}
/* sets the sample color RGB, maintaining A */
static void eyedropper_color_set(bContext *C, Eyedropper *eye, const float col[3])
{
- float col_conv[4];
+ float col_conv[4];
- /* to maintain alpha */
- RNA_property_float_get_array(&eye->ptr, eye->prop, col_conv);
+ /* to maintain alpha */
+ RNA_property_float_get_array(&eye->ptr, eye->prop, col_conv);
- /* convert from linear rgb space to display space */
- if (eye->display) {
- copy_v3_v3(col_conv, col);
- IMB_colormanagement_scene_linear_to_display_v3(col_conv, eye->display);
- }
- else {
- copy_v3_v3(col_conv, col);
- }
+ /* convert from linear rgb space to display space */
+ if (eye->display) {
+ copy_v3_v3(col_conv, col);
+ IMB_colormanagement_scene_linear_to_display_v3(col_conv, eye->display);
+ }
+ else {
+ copy_v3_v3(col_conv, col);
+ }
- RNA_property_float_set_array(&eye->ptr, eye->prop, col_conv);
- eye->is_set = true;
+ RNA_property_float_set_array(&eye->ptr, eye->prop, col_conv);
+ eye->is_set = true;
- RNA_property_update(C, &eye->ptr, eye->prop);
+ RNA_property_update(C, &eye->ptr, eye->prop);
}
static void eyedropper_color_sample(bContext *C, Eyedropper *eye, int mx, int my)
{
- /* Accumulate color. */
- float col[3];
- eyedropper_color_sample_fl(C, mx, my, col);
-
- if (eye->use_accum) {
- add_v3_v3(eye->accum_col, col);
- eye->accum_tot++;
- }
- else {
- copy_v3_v3(eye->accum_col, col);
- eye->accum_tot = 1;
- }
-
- /* Apply to property. */
- float accum_col[3];
- if (eye->accum_tot > 1) {
- mul_v3_v3fl(accum_col, eye->accum_col, 1.0f / (float)eye->accum_tot);
- }
- else {
- copy_v3_v3(accum_col, eye->accum_col);
- }
- eyedropper_color_set(C, eye, accum_col);
+ /* Accumulate color. */
+ float col[3];
+ eyedropper_color_sample_fl(C, mx, my, col);
+
+ if (eye->use_accum) {
+ add_v3_v3(eye->accum_col, col);
+ eye->accum_tot++;
+ }
+ else {
+ copy_v3_v3(eye->accum_col, col);
+ eye->accum_tot = 1;
+ }
+
+ /* Apply to property. */
+ float accum_col[3];
+ if (eye->accum_tot > 1) {
+ mul_v3_v3fl(accum_col, eye->accum_col, 1.0f / (float)eye->accum_tot);
+ }
+ else {
+ copy_v3_v3(accum_col, eye->accum_col);
+ }
+ eyedropper_color_set(C, eye, accum_col);
}
static void eyedropper_cancel(bContext *C, wmOperator *op)
{
- Eyedropper *eye = op->customdata;
- if (eye->is_set) {
- eyedropper_color_set(C, eye, eye->init_col);
- }
- eyedropper_exit(C, op);
+ Eyedropper *eye = op->customdata;
+ if (eye->is_set) {
+ eyedropper_color_set(C, eye, eye->init_col);
+ }
+ eyedropper_exit(C, op);
}
/* main modal status check */
static int eyedropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- Eyedropper *eye = (Eyedropper *)op->customdata;
-
- /* handle modal keymap */
- if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case EYE_MODAL_CANCEL:
- eyedropper_cancel(C, op);
- return OPERATOR_CANCELLED;
- case EYE_MODAL_SAMPLE_CONFIRM:
- {
- const bool is_undo = eye->is_undo;
- if (eye->accum_tot == 0) {
- eyedropper_color_sample(C, eye, event->x, event->y);
- }
- eyedropper_exit(C, op);
- /* Could support finished & undo-skip. */
- return is_undo ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
- }
- case EYE_MODAL_SAMPLE_BEGIN:
- /* enable accum and make first sample */
- eye->accum_start = true;
- eyedropper_color_sample(C, eye, event->x, event->y);
- break;
- case EYE_MODAL_SAMPLE_RESET:
- eye->accum_tot = 0;
- zero_v3(eye->accum_col);
- eyedropper_color_sample(C, eye, event->x, event->y);
- break;
- }
- }
- else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
- if (eye->accum_start) {
- /* button is pressed so keep sampling */
- eyedropper_color_sample(C, eye, event->x, event->y);
- }
- }
-
- return OPERATOR_RUNNING_MODAL;
+ Eyedropper *eye = (Eyedropper *)op->customdata;
+
+ /* handle modal keymap */
+ if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case EYE_MODAL_CANCEL:
+ eyedropper_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ case EYE_MODAL_SAMPLE_CONFIRM: {
+ const bool is_undo = eye->is_undo;
+ if (eye->accum_tot == 0) {
+ eyedropper_color_sample(C, eye, event->x, event->y);
+ }
+ eyedropper_exit(C, op);
+ /* Could support finished & undo-skip. */
+ return is_undo ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ }
+ case EYE_MODAL_SAMPLE_BEGIN:
+ /* enable accum and make first sample */
+ eye->accum_start = true;
+ eyedropper_color_sample(C, eye, event->x, event->y);
+ break;
+ case EYE_MODAL_SAMPLE_RESET:
+ eye->accum_tot = 0;
+ zero_v3(eye->accum_col);
+ eyedropper_color_sample(C, eye, event->x, event->y);
+ break;
+ }
+ }
+ else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+ if (eye->accum_start) {
+ /* button is pressed so keep sampling */
+ eyedropper_color_sample(C, eye, event->x, event->y);
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
/* Modal Operator init */
static int eyedropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- /* init */
- if (eyedropper_init(C, op)) {
- WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
-
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
- }
- else {
- return OPERATOR_PASS_THROUGH;
- }
+ /* init */
+ if (eyedropper_init(C, op)) {
+ WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ return OPERATOR_PASS_THROUGH;
+ }
}
/* Repeat operator */
static int eyedropper_exec(bContext *C, wmOperator *op)
{
- /* init */
- if (eyedropper_init(C, op)) {
+ /* init */
+ if (eyedropper_init(C, op)) {
- /* do something */
+ /* do something */
- /* cleanup */
- eyedropper_exit(C, op);
+ /* cleanup */
+ eyedropper_exit(C, op);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_PASS_THROUGH;
- }
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_PASS_THROUGH;
+ }
}
static bool eyedropper_poll(bContext *C)
{
- /* Actual test for active button happens later, since we don't
- * know which one is active until mouse over. */
- return (CTX_wm_window(C) != NULL);
+ /* Actual test for active button happens later, since we don't
+ * know which one is active until mouse over. */
+ return (CTX_wm_window(C) != NULL);
}
void UI_OT_eyedropper_color(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Eyedropper";
- ot->idname = "UI_OT_eyedropper_color";
- ot->description = "Sample a color from the Blender Window to store in a property";
-
- /* api callbacks */
- ot->invoke = eyedropper_invoke;
- ot->modal = eyedropper_modal;
- ot->cancel = eyedropper_cancel;
- ot->exec = eyedropper_exec;
- ot->poll = eyedropper_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_INTERNAL;
-
- /* properties */
- PropertyRNA *prop;
-
- /* Needed for color picking with crypto-matte. */
- prop = RNA_def_boolean(ot->srna, "use_accumulate", true, "Accumulate", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ /* identifiers */
+ ot->name = "Eyedropper";
+ ot->idname = "UI_OT_eyedropper_color";
+ ot->description = "Sample a color from the Blender Window to store in a property";
+
+ /* api callbacks */
+ ot->invoke = eyedropper_invoke;
+ ot->modal = eyedropper_modal;
+ ot->cancel = eyedropper_cancel;
+ ot->exec = eyedropper_exec;
+ ot->poll = eyedropper_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_INTERNAL;
+
+ /* properties */
+ PropertyRNA *prop;
+
+ /* Needed for color picking with crypto-matte. */
+ prop = RNA_def_boolean(ot->srna, "use_accumulate", true, "Accumulate", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/interface/interface_eyedropper_colorband.c b/source/blender/editors/interface/interface_eyedropper_colorband.c
index 6c60640b428..67e5a6c806c 100644
--- a/source/blender/editors/interface/interface_eyedropper_colorband.c
+++ b/source/blender/editors/interface/interface_eyedropper_colorband.c
@@ -53,307 +53,312 @@
#include "interface_eyedropper_intern.h"
typedef struct Colorband_RNAUpdateCb {
- PointerRNA ptr;
- PropertyRNA *prop;
+ PointerRNA ptr;
+ PropertyRNA *prop;
} Colorband_RNAUpdateCb;
typedef struct EyedropperColorband {
- int last_x, last_y;
- /* Alpha is currently fixed at 1.0, may support in future. */
- float (*color_buffer)[4];
- int color_buffer_alloc;
- int color_buffer_len;
- bool sample_start;
- ColorBand init_color_band;
- ColorBand *color_band;
- PointerRNA ptr;
- PropertyRNA *prop;
- bool is_undo;
- bool is_set;
+ int last_x, last_y;
+ /* Alpha is currently fixed at 1.0, may support in future. */
+ float (*color_buffer)[4];
+ int color_buffer_alloc;
+ int color_buffer_len;
+ bool sample_start;
+ ColorBand init_color_band;
+ ColorBand *color_band;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ bool is_undo;
+ bool is_set;
} EyedropperColorband;
/* For user-data only. */
struct EyedropperColorband_Context {
- bContext *context;
- EyedropperColorband *eye;
+ bContext *context;
+ EyedropperColorband *eye;
};
static bool eyedropper_colorband_init(bContext *C, wmOperator *op)
{
- ColorBand *band = NULL;
-
- uiBut *but = UI_context_active_but_get(C);
-
- if (but == NULL) {
- /* pass */
- }
- else if (but->type == UI_BTYPE_COLORBAND) {
- /* When invoked with a hotkey, we can find the band in 'but->poin'. */
- band = (ColorBand *)but->poin;
- }
- else {
- /* When invoked from a button it's in custom_data field. */
- band = (ColorBand *)but->custom_data;
- }
-
- if (!band) {
- PointerRNA ptr = CTX_data_pointer_get_type(C, "color_ramp", &RNA_ColorRamp);
- if (ptr.data != NULL) {
- band = ptr.data;
- }
- }
-
- if (!band) {
- return false;
- }
-
- EyedropperColorband *eye = MEM_callocN(sizeof(EyedropperColorband), __func__);
- eye->color_buffer_alloc = 16;
- eye->color_buffer = MEM_mallocN(sizeof(*eye->color_buffer) * eye->color_buffer_alloc, __func__);
- eye->color_buffer_len = 0;
- eye->color_band = band;
- eye->init_color_band = *eye->color_band;
- eye->ptr = ((Colorband_RNAUpdateCb *)but->func_argN)->ptr;
- eye->prop = ((Colorband_RNAUpdateCb *)but->func_argN)->prop;
- eye->is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
-
- op->customdata = eye;
-
- return true;
+ ColorBand *band = NULL;
+
+ uiBut *but = UI_context_active_but_get(C);
+
+ if (but == NULL) {
+ /* pass */
+ }
+ else if (but->type == UI_BTYPE_COLORBAND) {
+ /* When invoked with a hotkey, we can find the band in 'but->poin'. */
+ band = (ColorBand *)but->poin;
+ }
+ else {
+ /* When invoked from a button it's in custom_data field. */
+ band = (ColorBand *)but->custom_data;
+ }
+
+ if (!band) {
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "color_ramp", &RNA_ColorRamp);
+ if (ptr.data != NULL) {
+ band = ptr.data;
+ }
+ }
+
+ if (!band) {
+ return false;
+ }
+
+ EyedropperColorband *eye = MEM_callocN(sizeof(EyedropperColorband), __func__);
+ eye->color_buffer_alloc = 16;
+ eye->color_buffer = MEM_mallocN(sizeof(*eye->color_buffer) * eye->color_buffer_alloc, __func__);
+ eye->color_buffer_len = 0;
+ eye->color_band = band;
+ eye->init_color_band = *eye->color_band;
+ eye->ptr = ((Colorband_RNAUpdateCb *)but->func_argN)->ptr;
+ eye->prop = ((Colorband_RNAUpdateCb *)but->func_argN)->prop;
+ eye->is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
+
+ op->customdata = eye;
+
+ return true;
}
-static void eyedropper_colorband_sample_point(bContext *C, EyedropperColorband *eye, int mx, int my)
+static void eyedropper_colorband_sample_point(bContext *C,
+ EyedropperColorband *eye,
+ int mx,
+ int my)
{
- if (eye->last_x != mx || eye->last_y != my) {
- float col[4];
- col[3] = 1.0f; /* TODO: sample alpha */
- eyedropper_color_sample_fl(C, mx, my, col);
- if (eye->color_buffer_len + 1 == eye->color_buffer_alloc) {
- eye->color_buffer_alloc *= 2;
- eye->color_buffer = MEM_reallocN(eye->color_buffer, sizeof(*eye->color_buffer) * eye->color_buffer_alloc);
- }
- copy_v4_v4(eye->color_buffer[eye->color_buffer_len], col);
- eye->color_buffer_len += 1;
- eye->last_x = mx;
- eye->last_y = my;
- eye->is_set = true;
- }
+ if (eye->last_x != mx || eye->last_y != my) {
+ float col[4];
+ col[3] = 1.0f; /* TODO: sample alpha */
+ eyedropper_color_sample_fl(C, mx, my, col);
+ if (eye->color_buffer_len + 1 == eye->color_buffer_alloc) {
+ eye->color_buffer_alloc *= 2;
+ eye->color_buffer = MEM_reallocN(eye->color_buffer,
+ sizeof(*eye->color_buffer) * eye->color_buffer_alloc);
+ }
+ copy_v4_v4(eye->color_buffer[eye->color_buffer_len], col);
+ eye->color_buffer_len += 1;
+ eye->last_x = mx;
+ eye->last_y = my;
+ eye->is_set = true;
+ }
}
static bool eyedropper_colorband_sample_callback(int mx, int my, void *userdata)
{
- struct EyedropperColorband_Context *data = userdata;
- bContext *C = data->context;
- EyedropperColorband *eye = data->eye;
- eyedropper_colorband_sample_point(C, eye, mx, my);
- return true;
+ struct EyedropperColorband_Context *data = userdata;
+ bContext *C = data->context;
+ EyedropperColorband *eye = data->eye;
+ eyedropper_colorband_sample_point(C, eye, mx, my);
+ return true;
}
-static void eyedropper_colorband_sample_segment(bContext *C, EyedropperColorband *eye, int mx, int my)
+static void eyedropper_colorband_sample_segment(bContext *C,
+ EyedropperColorband *eye,
+ int mx,
+ int my)
{
- /* Since the mouse tends to move rather rapidly we use #BLI_bitmap_draw_2d_line_v2v2i
- * to interpolate between the reported coordinates */
- struct EyedropperColorband_Context userdata = {C, eye};
- int p1[2] = {eye->last_x, eye->last_y};
- int p2[2] = {mx, my};
- BLI_bitmap_draw_2d_line_v2v2i(p1, p2, eyedropper_colorband_sample_callback, &userdata);
+ /* Since the mouse tends to move rather rapidly we use #BLI_bitmap_draw_2d_line_v2v2i
+ * to interpolate between the reported coordinates */
+ struct EyedropperColorband_Context userdata = {C, eye};
+ int p1[2] = {eye->last_x, eye->last_y};
+ int p2[2] = {mx, my};
+ BLI_bitmap_draw_2d_line_v2v2i(p1, p2, eyedropper_colorband_sample_callback, &userdata);
}
static void eyedropper_colorband_exit(bContext *C, wmOperator *op)
{
- WM_cursor_modal_restore(CTX_wm_window(C));
-
- if (op->customdata) {
- EyedropperColorband *eye = op->customdata;
- MEM_freeN(eye->color_buffer);
- MEM_freeN(eye);
- op->customdata = NULL;
- }
+ WM_cursor_modal_restore(CTX_wm_window(C));
+
+ if (op->customdata) {
+ EyedropperColorband *eye = op->customdata;
+ MEM_freeN(eye->color_buffer);
+ MEM_freeN(eye);
+ op->customdata = NULL;
+ }
}
static void eyedropper_colorband_apply(bContext *C, wmOperator *op)
{
- EyedropperColorband *eye = op->customdata;
- /* Always filter, avoids noise in resulting color-band. */
- bool filter_samples = true;
- BKE_colorband_init_from_table_rgba(eye->color_band, eye->color_buffer, eye->color_buffer_len, filter_samples);
- eye->is_set = true;
- RNA_property_update(C, &eye->ptr, eye->prop);
+ EyedropperColorband *eye = op->customdata;
+ /* Always filter, avoids noise in resulting color-band. */
+ bool filter_samples = true;
+ BKE_colorband_init_from_table_rgba(
+ eye->color_band, eye->color_buffer, eye->color_buffer_len, filter_samples);
+ eye->is_set = true;
+ RNA_property_update(C, &eye->ptr, eye->prop);
}
static void eyedropper_colorband_cancel(bContext *C, wmOperator *op)
{
- EyedropperColorband *eye = op->customdata;
- if (eye->is_set) {
- *eye->color_band = eye->init_color_band;
- RNA_property_update(C, &eye->ptr, eye->prop);
- }
- eyedropper_colorband_exit(C, op);
+ EyedropperColorband *eye = op->customdata;
+ if (eye->is_set) {
+ *eye->color_band = eye->init_color_band;
+ RNA_property_update(C, &eye->ptr, eye->prop);
+ }
+ eyedropper_colorband_exit(C, op);
}
/* main modal status check */
static int eyedropper_colorband_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- EyedropperColorband *eye = op->customdata;
- /* handle modal keymap */
- if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case EYE_MODAL_CANCEL:
- eyedropper_colorband_cancel(C, op);
- return OPERATOR_CANCELLED;
- case EYE_MODAL_SAMPLE_CONFIRM:
- {
- const bool is_undo = eye->is_undo;
- eyedropper_colorband_sample_segment(C, eye, event->x, event->y);
- eyedropper_colorband_apply(C, op);
- eyedropper_colorband_exit(C, op);
- /* Could support finished & undo-skip. */
- return is_undo ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
- }
- case EYE_MODAL_SAMPLE_BEGIN:
- /* enable accum and make first sample */
- eye->sample_start = true;
- eyedropper_colorband_sample_point(C, eye, event->x, event->y);
- eyedropper_colorband_apply(C, op);
- eye->last_x = event->x;
- eye->last_y = event->y;
- break;
- case EYE_MODAL_SAMPLE_RESET:
- break;
- }
- }
- else if (event->type == MOUSEMOVE) {
- if (eye->sample_start) {
- eyedropper_colorband_sample_segment(C, eye, event->x, event->y);
- eyedropper_colorband_apply(C, op);
- }
- }
- return OPERATOR_RUNNING_MODAL;
+ EyedropperColorband *eye = op->customdata;
+ /* handle modal keymap */
+ if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case EYE_MODAL_CANCEL:
+ eyedropper_colorband_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ case EYE_MODAL_SAMPLE_CONFIRM: {
+ const bool is_undo = eye->is_undo;
+ eyedropper_colorband_sample_segment(C, eye, event->x, event->y);
+ eyedropper_colorband_apply(C, op);
+ eyedropper_colorband_exit(C, op);
+ /* Could support finished & undo-skip. */
+ return is_undo ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ }
+ case EYE_MODAL_SAMPLE_BEGIN:
+ /* enable accum and make first sample */
+ eye->sample_start = true;
+ eyedropper_colorband_sample_point(C, eye, event->x, event->y);
+ eyedropper_colorband_apply(C, op);
+ eye->last_x = event->x;
+ eye->last_y = event->y;
+ break;
+ case EYE_MODAL_SAMPLE_RESET:
+ break;
+ }
+ }
+ else if (event->type == MOUSEMOVE) {
+ if (eye->sample_start) {
+ eyedropper_colorband_sample_segment(C, eye, event->x, event->y);
+ eyedropper_colorband_apply(C, op);
+ }
+ }
+ return OPERATOR_RUNNING_MODAL;
}
static int eyedropper_colorband_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- EyedropperColorband *eye = op->customdata;
- /* handle modal keymap */
- if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case EYE_MODAL_POINT_CANCEL:
- eyedropper_colorband_cancel(C, op);
- return OPERATOR_CANCELLED;
- case EYE_MODAL_POINT_CONFIRM:
- eyedropper_colorband_apply(C, op);
- eyedropper_colorband_exit(C, op);
- return OPERATOR_FINISHED;
- case EYE_MODAL_POINT_REMOVE_LAST:
- if (eye->color_buffer_len > 0) {
- eye->color_buffer_len -= 1;
- eyedropper_colorband_apply(C, op);
- }
- break;
- case EYE_MODAL_POINT_SAMPLE:
- eyedropper_colorband_sample_point(C, eye, event->x, event->y);
- eyedropper_colorband_apply(C, op);
- if (eye->color_buffer_len == MAXCOLORBAND ) {
- eyedropper_colorband_exit(C, op);
- return OPERATOR_FINISHED;
- }
- break;
- case EYE_MODAL_SAMPLE_RESET:
- *eye->color_band = eye->init_color_band;
- RNA_property_update(C, &eye->ptr, eye->prop);
- eye->color_buffer_len = 0;
- break;
- }
- }
- return OPERATOR_RUNNING_MODAL;
+ EyedropperColorband *eye = op->customdata;
+ /* handle modal keymap */
+ if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case EYE_MODAL_POINT_CANCEL:
+ eyedropper_colorband_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ case EYE_MODAL_POINT_CONFIRM:
+ eyedropper_colorband_apply(C, op);
+ eyedropper_colorband_exit(C, op);
+ return OPERATOR_FINISHED;
+ case EYE_MODAL_POINT_REMOVE_LAST:
+ if (eye->color_buffer_len > 0) {
+ eye->color_buffer_len -= 1;
+ eyedropper_colorband_apply(C, op);
+ }
+ break;
+ case EYE_MODAL_POINT_SAMPLE:
+ eyedropper_colorband_sample_point(C, eye, event->x, event->y);
+ eyedropper_colorband_apply(C, op);
+ if (eye->color_buffer_len == MAXCOLORBAND) {
+ eyedropper_colorband_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ break;
+ case EYE_MODAL_SAMPLE_RESET:
+ *eye->color_band = eye->init_color_band;
+ RNA_property_update(C, &eye->ptr, eye->prop);
+ eye->color_buffer_len = 0;
+ break;
+ }
+ }
+ return OPERATOR_RUNNING_MODAL;
}
-
/* Modal Operator init */
static int eyedropper_colorband_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- /* init */
- if (eyedropper_colorband_init(C, op)) {
- WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
-
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ /* init */
+ if (eyedropper_colorband_init(C, op)) {
+ WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
/* Repeat operator */
static int eyedropper_colorband_exec(bContext *C, wmOperator *op)
{
- /* init */
- if (eyedropper_colorband_init(C, op)) {
+ /* init */
+ if (eyedropper_colorband_init(C, op)) {
- /* do something */
+ /* do something */
- /* cleanup */
- eyedropper_colorband_exit(C, op);
+ /* cleanup */
+ eyedropper_colorband_exit(C, op);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static bool eyedropper_colorband_poll(bContext *C)
{
- uiBut *but = UI_context_active_but_get(C);
- if (but && but->type == UI_BTYPE_COLORBAND) {
- return true;
- }
- PointerRNA ptr = CTX_data_pointer_get_type(C, "color_ramp", &RNA_ColorRamp);
- if (ptr.data != NULL) {
- return true;
- }
- return false;
+ uiBut *but = UI_context_active_but_get(C);
+ if (but && but->type == UI_BTYPE_COLORBAND) {
+ return true;
+ }
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "color_ramp", &RNA_ColorRamp);
+ if (ptr.data != NULL) {
+ return true;
+ }
+ return false;
}
-
void UI_OT_eyedropper_colorramp(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Eyedropper colorband";
- ot->idname = "UI_OT_eyedropper_colorramp";
- ot->description = "Sample a color band";
-
- /* api callbacks */
- ot->invoke = eyedropper_colorband_invoke;
- ot->modal = eyedropper_colorband_modal;
- ot->cancel = eyedropper_colorband_cancel;
- ot->exec = eyedropper_colorband_exec;
- ot->poll = eyedropper_colorband_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_INTERNAL;
-
- /* properties */
+ /* identifiers */
+ ot->name = "Eyedropper colorband";
+ ot->idname = "UI_OT_eyedropper_colorramp";
+ ot->description = "Sample a color band";
+
+ /* api callbacks */
+ ot->invoke = eyedropper_colorband_invoke;
+ ot->modal = eyedropper_colorband_modal;
+ ot->cancel = eyedropper_colorband_cancel;
+ ot->exec = eyedropper_colorband_exec;
+ ot->poll = eyedropper_colorband_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_INTERNAL;
+
+ /* properties */
}
void UI_OT_eyedropper_colorramp_point(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Eyedropper colorband (points)";
- ot->idname = "UI_OT_eyedropper_colorramp_point";
- ot->description = "Point-sample a color band";
-
- /* api callbacks */
- ot->invoke = eyedropper_colorband_invoke;
- ot->modal = eyedropper_colorband_point_modal;
- ot->cancel = eyedropper_colorband_cancel;
- ot->exec = eyedropper_colorband_exec;
- ot->poll = eyedropper_colorband_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_INTERNAL;
-
- /* properties */
+ /* identifiers */
+ ot->name = "Eyedropper colorband (points)";
+ ot->idname = "UI_OT_eyedropper_colorramp_point";
+ ot->description = "Point-sample a color band";
+
+ /* api callbacks */
+ ot->invoke = eyedropper_colorband_invoke;
+ ot->modal = eyedropper_colorband_point_modal;
+ ot->cancel = eyedropper_colorband_cancel;
+ ot->exec = eyedropper_colorband_exec;
+ ot->poll = eyedropper_colorband_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_INTERNAL;
+
+ /* properties */
}
diff --git a/source/blender/editors/interface/interface_eyedropper_datablock.c b/source/blender/editors/interface/interface_eyedropper_datablock.c
index ffd8f672622..1d90139eade 100644
--- a/source/blender/editors/interface/interface_eyedropper_datablock.c
+++ b/source/blender/editors/interface/interface_eyedropper_datablock.c
@@ -59,87 +59,84 @@
* \note #DataDropper is only internal name to avoid confusion with other kinds of eye-droppers.
*/
typedef struct DataDropper {
- PointerRNA ptr;
- PropertyRNA *prop;
- short idcode;
- const char *idcode_name;
- bool is_undo;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ short idcode;
+ const char *idcode_name;
+ bool is_undo;
- ID *init_id; /* for resetting on cancel */
+ ID *init_id; /* for resetting on cancel */
- ARegionType *art;
- void *draw_handle_pixel;
- char name[200];
+ ARegionType *art;
+ void *draw_handle_pixel;
+ char name[200];
} DataDropper;
-
static void datadropper_draw_cb(const struct bContext *C, ARegion *ar, void *arg)
{
- DataDropper *ddr = arg;
- eyedropper_draw_cursor_text(C, ar, ddr->name);
+ DataDropper *ddr = arg;
+ eyedropper_draw_cursor_text(C, ar, ddr->name);
}
-
static int datadropper_init(bContext *C, wmOperator *op)
{
- int index_dummy;
- StructRNA *type;
+ int index_dummy;
+ StructRNA *type;
- SpaceType *st;
- ARegionType *art;
+ SpaceType *st;
+ ARegionType *art;
- st = BKE_spacetype_from_id(SPACE_VIEW3D);
- art = BKE_regiontype_from_id(st, RGN_TYPE_WINDOW);
+ st = BKE_spacetype_from_id(SPACE_VIEW3D);
+ art = BKE_regiontype_from_id(st, RGN_TYPE_WINDOW);
- DataDropper *ddr = MEM_callocN(sizeof(DataDropper), __func__);
+ DataDropper *ddr = MEM_callocN(sizeof(DataDropper), __func__);
- uiBut *but = UI_context_active_but_prop_get(C, &ddr->ptr, &ddr->prop, &index_dummy);
+ uiBut *but = UI_context_active_but_prop_get(C, &ddr->ptr, &ddr->prop, &index_dummy);
- if ((ddr->ptr.data == NULL) ||
- (ddr->prop == NULL) ||
- (RNA_property_editable(&ddr->ptr, ddr->prop) == false) ||
- (RNA_property_type(ddr->prop) != PROP_POINTER))
- {
- MEM_freeN(ddr);
- return false;
- }
- op->customdata = ddr;
+ if ((ddr->ptr.data == NULL) || (ddr->prop == NULL) ||
+ (RNA_property_editable(&ddr->ptr, ddr->prop) == false) ||
+ (RNA_property_type(ddr->prop) != PROP_POINTER)) {
+ MEM_freeN(ddr);
+ return false;
+ }
+ op->customdata = ddr;
- ddr->is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
+ ddr->is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
- ddr->art = art;
- ddr->draw_handle_pixel = ED_region_draw_cb_activate(art, datadropper_draw_cb, ddr, REGION_DRAW_POST_PIXEL);
+ ddr->art = art;
+ ddr->draw_handle_pixel = ED_region_draw_cb_activate(
+ art, datadropper_draw_cb, ddr, REGION_DRAW_POST_PIXEL);
- type = RNA_property_pointer_type(&ddr->ptr, ddr->prop);
- ddr->idcode = RNA_type_to_ID_code(type);
- 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));
+ type = RNA_property_pointer_type(&ddr->ptr, ddr->prop);
+ ddr->idcode = RNA_type_to_ID_code(type);
+ 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));
- PointerRNA ptr = RNA_property_pointer_get(&ddr->ptr, ddr->prop);
- ddr->init_id = ptr.id.data;
+ PointerRNA ptr = RNA_property_pointer_get(&ddr->ptr, ddr->prop);
+ ddr->init_id = ptr.id.data;
- return true;
+ return true;
}
static void datadropper_exit(bContext *C, wmOperator *op)
{
- WM_cursor_modal_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
- if (op->customdata) {
- DataDropper *ddr = (DataDropper *)op->customdata;
+ if (op->customdata) {
+ DataDropper *ddr = (DataDropper *)op->customdata;
- if (ddr->art) {
- ED_region_draw_cb_exit(ddr->art, ddr->draw_handle_pixel);
- }
+ if (ddr->art) {
+ ED_region_draw_cb_exit(ddr->art, ddr->draw_handle_pixel);
+ }
- MEM_freeN(op->customdata);
+ MEM_freeN(op->customdata);
- op->customdata = NULL;
- }
+ op->customdata = NULL;
+ }
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(C);
}
/* *** datadropper id helper functions *** */
@@ -148,204 +145,198 @@ static void datadropper_exit(bContext *C, wmOperator *op)
*/
static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int my, ID **r_id)
{
- /* we could use some clever */
- bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = BKE_screen_find_area_xy(screen, -1, mx, my);
-
- ScrArea *area_prev = CTX_wm_area(C);
- ARegion *ar_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) {
- const int mval[2] = {
- mx - ar->winrct.xmin,
- my - ar->winrct.ymin};
- Base *base;
-
- CTX_wm_area_set(C, sa);
- CTX_wm_region_set(C, ar);
-
- /* grr, always draw else we leave stale text */
- ED_region_tag_redraw(ar);
-
- base = ED_view3d_give_base_under_cursor(C, mval);
- if (base) {
- Object *ob = base->object;
- ID *id = NULL;
- if (ddr->idcode == ID_OB) {
- id = (ID *)ob;
- }
- else if (ob->data) {
- if (GS(((ID *)ob->data)->name) == ddr->idcode) {
- id = (ID *)ob->data;
- }
- else {
- BLI_snprintf(ddr->name, sizeof(ddr->name), "Incompatible, expected a %s",
- ddr->idcode_name);
- }
- }
-
- PointerRNA idptr;
- RNA_id_pointer_create(id, &idptr);
-
- if (id && RNA_property_pointer_poll(&ddr->ptr, ddr->prop, &idptr)) {
- BLI_snprintf(ddr->name, sizeof(ddr->name), "%s: %s",
- ddr->idcode_name, id->name + 2);
- *r_id = id;
- }
- }
- }
- }
- }
-
- CTX_wm_area_set(C, area_prev);
- CTX_wm_region_set(C, ar_prev);
+ /* we could use some clever */
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = BKE_screen_find_area_xy(screen, -1, mx, my);
+
+ ScrArea *area_prev = CTX_wm_area(C);
+ ARegion *ar_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) {
+ const int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin};
+ Base *base;
+
+ CTX_wm_area_set(C, sa);
+ CTX_wm_region_set(C, ar);
+
+ /* grr, always draw else we leave stale text */
+ ED_region_tag_redraw(ar);
+
+ base = ED_view3d_give_base_under_cursor(C, mval);
+ if (base) {
+ Object *ob = base->object;
+ ID *id = NULL;
+ if (ddr->idcode == ID_OB) {
+ id = (ID *)ob;
+ }
+ else if (ob->data) {
+ if (GS(((ID *)ob->data)->name) == ddr->idcode) {
+ id = (ID *)ob->data;
+ }
+ else {
+ BLI_snprintf(
+ ddr->name, sizeof(ddr->name), "Incompatible, expected a %s", ddr->idcode_name);
+ }
+ }
+
+ PointerRNA idptr;
+ RNA_id_pointer_create(id, &idptr);
+
+ if (id && RNA_property_pointer_poll(&ddr->ptr, ddr->prop, &idptr)) {
+ BLI_snprintf(ddr->name, sizeof(ddr->name), "%s: %s", ddr->idcode_name, id->name + 2);
+ *r_id = id;
+ }
+ }
+ }
+ }
+ }
+
+ CTX_wm_area_set(C, area_prev);
+ CTX_wm_region_set(C, ar_prev);
}
/* sets the ID, returns success */
static bool datadropper_id_set(bContext *C, DataDropper *ddr, ID *id)
{
- PointerRNA ptr_value;
+ PointerRNA ptr_value;
- RNA_id_pointer_create(id, &ptr_value);
+ RNA_id_pointer_create(id, &ptr_value);
- RNA_property_pointer_set(&ddr->ptr, ddr->prop, ptr_value);
+ RNA_property_pointer_set(&ddr->ptr, ddr->prop, ptr_value);
- RNA_property_update(C, &ddr->ptr, ddr->prop);
+ RNA_property_update(C, &ddr->ptr, ddr->prop);
- ptr_value = RNA_property_pointer_get(&ddr->ptr, ddr->prop);
+ ptr_value = RNA_property_pointer_get(&ddr->ptr, ddr->prop);
- return (ptr_value.id.data == id);
+ return (ptr_value.id.data == id);
}
/* single point sample & set */
static bool datadropper_id_sample(bContext *C, DataDropper *ddr, int mx, int my)
{
- ID *id = NULL;
+ ID *id = NULL;
- datadropper_id_sample_pt(C, ddr, mx, my, &id);
- return datadropper_id_set(C, ddr, id);
+ datadropper_id_sample_pt(C, ddr, mx, my, &id);
+ return datadropper_id_set(C, ddr, id);
}
static void datadropper_cancel(bContext *C, wmOperator *op)
{
- DataDropper *ddr = op->customdata;
- datadropper_id_set(C, ddr, ddr->init_id);
- datadropper_exit(C, op);
+ DataDropper *ddr = op->customdata;
+ datadropper_id_set(C, ddr, ddr->init_id);
+ datadropper_exit(C, op);
}
/* main modal status check */
static int datadropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- DataDropper *ddr = (DataDropper *)op->customdata;
-
- /* handle modal keymap */
- if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case EYE_MODAL_CANCEL:
- datadropper_cancel(C, op);
- return OPERATOR_CANCELLED;
- case EYE_MODAL_SAMPLE_CONFIRM:
- {
- const bool is_undo = ddr->is_undo;
- const bool success = datadropper_id_sample(C, ddr, event->x, event->y);
- datadropper_exit(C, op);
- if (success) {
- /* Could support finished & undo-skip. */
- return is_undo ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
- }
- else {
- BKE_report(op->reports, RPT_WARNING, "Failed to set value");
- return OPERATOR_CANCELLED;
- }
- }
- }
- }
- else if (event->type == MOUSEMOVE) {
- ID *id = NULL;
- datadropper_id_sample_pt(C, ddr, event->x, event->y, &id);
- }
-
- return OPERATOR_RUNNING_MODAL;
+ DataDropper *ddr = (DataDropper *)op->customdata;
+
+ /* handle modal keymap */
+ if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case EYE_MODAL_CANCEL:
+ datadropper_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ case EYE_MODAL_SAMPLE_CONFIRM: {
+ const bool is_undo = ddr->is_undo;
+ const bool success = datadropper_id_sample(C, ddr, event->x, event->y);
+ datadropper_exit(C, op);
+ if (success) {
+ /* Could support finished & undo-skip. */
+ return is_undo ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ }
+ else {
+ BKE_report(op->reports, RPT_WARNING, "Failed to set value");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ }
+ }
+ else if (event->type == MOUSEMOVE) {
+ ID *id = NULL;
+ datadropper_id_sample_pt(C, ddr, event->x, event->y, &id);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
/* Modal Operator init */
static int datadropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- /* init */
- if (datadropper_init(C, op)) {
- WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
-
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ /* init */
+ if (datadropper_init(C, op)) {
+ WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
/* Repeat operator */
static int datadropper_exec(bContext *C, wmOperator *op)
{
- /* init */
- if (datadropper_init(C, op)) {
- /* cleanup */
- datadropper_exit(C, op);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ /* init */
+ if (datadropper_init(C, op)) {
+ /* cleanup */
+ datadropper_exit(C, op);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static bool datadropper_poll(bContext *C)
{
- PointerRNA ptr;
- PropertyRNA *prop;
- int index_dummy;
- uiBut *but;
-
- /* data dropper only supports object data */
- if ((CTX_wm_window(C) != NULL) &&
- (but = UI_context_active_but_prop_get(C, &ptr, &prop, &index_dummy)) &&
- (but->type == UI_BTYPE_SEARCH_MENU) &&
- (but->flag & UI_BUT_VALUE_CLEAR))
- {
- if (prop && RNA_property_type(prop) == PROP_POINTER) {
- StructRNA *type = RNA_property_pointer_type(&ptr, prop);
- const short idcode = RNA_type_to_ID_code(type);
- if ((idcode == ID_OB) || OB_DATA_SUPPORT_ID(idcode)) {
- return 1;
- }
- }
- }
-
- return 0;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index_dummy;
+ uiBut *but;
+
+ /* data dropper only supports object data */
+ if ((CTX_wm_window(C) != NULL) &&
+ (but = UI_context_active_but_prop_get(C, &ptr, &prop, &index_dummy)) &&
+ (but->type == UI_BTYPE_SEARCH_MENU) && (but->flag & UI_BUT_VALUE_CLEAR)) {
+ if (prop && RNA_property_type(prop) == PROP_POINTER) {
+ StructRNA *type = RNA_property_pointer_type(&ptr, prop);
+ const short idcode = RNA_type_to_ID_code(type);
+ if ((idcode == ID_OB) || OB_DATA_SUPPORT_ID(idcode)) {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
}
void UI_OT_eyedropper_id(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Eyedropper Data-Block";
- ot->idname = "UI_OT_eyedropper_id";
- ot->description = "Sample a data-block from the 3D View to store in a property";
-
- /* api callbacks */
- ot->invoke = datadropper_invoke;
- ot->modal = datadropper_modal;
- ot->cancel = datadropper_cancel;
- ot->exec = datadropper_exec;
- ot->poll = datadropper_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_INTERNAL;
-
- /* properties */
+ /* identifiers */
+ ot->name = "Eyedropper Data-Block";
+ ot->idname = "UI_OT_eyedropper_id";
+ ot->description = "Sample a data-block from the 3D View to store in a property";
+
+ /* api callbacks */
+ ot->invoke = datadropper_invoke;
+ ot->modal = datadropper_modal;
+ ot->cancel = datadropper_cancel;
+ ot->exec = datadropper_exec;
+ ot->poll = datadropper_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_INTERNAL;
+
+ /* properties */
}
diff --git a/source/blender/editors/interface/interface_eyedropper_depth.c b/source/blender/editors/interface/interface_eyedropper_depth.c
index 9e559f65335..adb317f488c 100644
--- a/source/blender/editors/interface/interface_eyedropper_depth.c
+++ b/source/blender/editors/interface/interface_eyedropper_depth.c
@@ -60,334 +60,328 @@
* \note #DepthDropper is only internal name to avoid confusion with other kinds of eye-droppers.
*/
typedef struct DepthDropper {
- PointerRNA ptr;
- PropertyRNA *prop;
- bool is_undo;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ bool is_undo;
- bool is_set;
- float init_depth; /* for resetting on cancel */
+ bool is_set;
+ float init_depth; /* for resetting on cancel */
- bool accum_start; /* has mouse been presed */
- float accum_depth;
- int accum_tot;
+ bool accum_start; /* has mouse been presed */
+ float accum_depth;
+ int accum_tot;
- ARegionType *art;
- void *draw_handle_pixel;
- char name[200];
+ ARegionType *art;
+ void *draw_handle_pixel;
+ char name[200];
} DepthDropper;
-
static void depthdropper_draw_cb(const struct bContext *C, ARegion *ar, void *arg)
{
- DepthDropper *ddr = arg;
- eyedropper_draw_cursor_text(C, ar, ddr->name);
+ DepthDropper *ddr = arg;
+ eyedropper_draw_cursor_text(C, ar, ddr->name);
}
-
static int depthdropper_init(bContext *C, wmOperator *op)
{
- int index_dummy;
-
- SpaceType *st;
- ARegionType *art;
-
- st = BKE_spacetype_from_id(SPACE_VIEW3D);
- art = BKE_regiontype_from_id(st, RGN_TYPE_WINDOW);
-
- DepthDropper *ddr = MEM_callocN(sizeof(DepthDropper), __func__);
-
- uiBut *but = UI_context_active_but_prop_get(C, &ddr->ptr, &ddr->prop, &index_dummy);
-
- /* fallback to the active camera's dof */
- if (ddr->prop == NULL) {
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- if (rv3d && rv3d->persp == RV3D_CAMOB) {
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d->camera && v3d->camera->data && !ID_IS_LINKED(v3d->camera->data)) {
- RNA_id_pointer_create(v3d->camera->data, &ddr->ptr);
- ddr->prop = RNA_struct_find_property(&ddr->ptr, "dof_distance");
- ddr->is_undo = true;
- }
- }
- }
- else {
- ddr->is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
- }
-
- if ((ddr->ptr.data == NULL) ||
- (ddr->prop == NULL) ||
- (RNA_property_editable(&ddr->ptr, ddr->prop) == false) ||
- (RNA_property_type(ddr->prop) != PROP_FLOAT))
- {
- MEM_freeN(ddr);
- return false;
- }
- op->customdata = ddr;
-
- ddr->art = art;
- ddr->draw_handle_pixel = ED_region_draw_cb_activate(art, depthdropper_draw_cb, ddr, REGION_DRAW_POST_PIXEL);
- ddr->init_depth = RNA_property_float_get(&ddr->ptr, ddr->prop);
-
- return true;
+ int index_dummy;
+
+ SpaceType *st;
+ ARegionType *art;
+
+ st = BKE_spacetype_from_id(SPACE_VIEW3D);
+ art = BKE_regiontype_from_id(st, RGN_TYPE_WINDOW);
+
+ DepthDropper *ddr = MEM_callocN(sizeof(DepthDropper), __func__);
+
+ uiBut *but = UI_context_active_but_prop_get(C, &ddr->ptr, &ddr->prop, &index_dummy);
+
+ /* fallback to the active camera's dof */
+ if (ddr->prop == NULL) {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if (rv3d && rv3d->persp == RV3D_CAMOB) {
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->camera && v3d->camera->data && !ID_IS_LINKED(v3d->camera->data)) {
+ RNA_id_pointer_create(v3d->camera->data, &ddr->ptr);
+ ddr->prop = RNA_struct_find_property(&ddr->ptr, "dof_distance");
+ ddr->is_undo = true;
+ }
+ }
+ }
+ else {
+ ddr->is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
+ }
+
+ if ((ddr->ptr.data == NULL) || (ddr->prop == NULL) ||
+ (RNA_property_editable(&ddr->ptr, ddr->prop) == false) ||
+ (RNA_property_type(ddr->prop) != PROP_FLOAT)) {
+ MEM_freeN(ddr);
+ return false;
+ }
+ op->customdata = ddr;
+
+ ddr->art = art;
+ ddr->draw_handle_pixel = ED_region_draw_cb_activate(
+ art, depthdropper_draw_cb, ddr, REGION_DRAW_POST_PIXEL);
+ ddr->init_depth = RNA_property_float_get(&ddr->ptr, ddr->prop);
+
+ return true;
}
static void depthdropper_exit(bContext *C, wmOperator *op)
{
- WM_cursor_modal_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
- if (op->customdata) {
- DepthDropper *ddr = (DepthDropper *)op->customdata;
+ if (op->customdata) {
+ DepthDropper *ddr = (DepthDropper *)op->customdata;
- if (ddr->art) {
- ED_region_draw_cb_exit(ddr->art, ddr->draw_handle_pixel);
- }
+ if (ddr->art) {
+ ED_region_draw_cb_exit(ddr->art, ddr->draw_handle_pixel);
+ }
- MEM_freeN(op->customdata);
+ MEM_freeN(op->customdata);
- op->customdata = NULL;
- }
+ op->customdata = NULL;
+ }
}
/* *** depthdropper id helper functions *** */
/**
* \brief get the ID from the screen.
*/
-static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, int my, float *r_depth)
+static void depthdropper_depth_sample_pt(
+ bContext *C, DepthDropper *ddr, int mx, int my, float *r_depth)
{
- /* we could use some clever */
- bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = 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);
-
- 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) {
- struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
- View3D *v3d = sa->spacedata.first;
- RegionView3D *rv3d = ar->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};
- float co[3];
-
- CTX_wm_area_set(C, sa);
- CTX_wm_region_set(C, ar);
-
- /* grr, always draw else we leave stale text */
- ED_region_tag_redraw(ar);
-
- 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};
- 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);
-
- *r_depth = len_v3v3(view_co, co_align);
-
- bUnit_AsString2(
- ddr->name, sizeof(ddr->name), (double)*r_depth,
- 4, B_UNIT_LENGTH, &scene->unit, false);
- }
- else {
- BLI_strncpy(ddr->name, "Nothing under cursor", sizeof(ddr->name));
- }
- }
- }
- }
-
- CTX_wm_area_set(C, area_prev);
- CTX_wm_region_set(C, ar_prev);
+ /* we could use some clever */
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = 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);
+
+ 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) {
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ View3D *v3d = sa->spacedata.first;
+ RegionView3D *rv3d = ar->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};
+ float co[3];
+
+ CTX_wm_area_set(C, sa);
+ CTX_wm_region_set(C, ar);
+
+ /* grr, always draw else we leave stale text */
+ ED_region_tag_redraw(ar);
+
+ 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};
+ 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);
+
+ *r_depth = len_v3v3(view_co, co_align);
+
+ bUnit_AsString2(ddr->name,
+ sizeof(ddr->name),
+ (double)*r_depth,
+ 4,
+ B_UNIT_LENGTH,
+ &scene->unit,
+ false);
+ }
+ else {
+ BLI_strncpy(ddr->name, "Nothing under cursor", sizeof(ddr->name));
+ }
+ }
+ }
+ }
+
+ CTX_wm_area_set(C, area_prev);
+ CTX_wm_region_set(C, ar_prev);
}
/* sets the sample depth RGB, maintaining A */
static void depthdropper_depth_set(bContext *C, DepthDropper *ddr, const float depth)
{
- RNA_property_float_set(&ddr->ptr, ddr->prop, depth);
- ddr->is_set = true;
- RNA_property_update(C, &ddr->ptr, ddr->prop);
+ RNA_property_float_set(&ddr->ptr, ddr->prop, depth);
+ ddr->is_set = true;
+ RNA_property_update(C, &ddr->ptr, ddr->prop);
}
/* set sample from accumulated values */
static void depthdropper_depth_set_accum(bContext *C, DepthDropper *ddr)
{
- float depth = ddr->accum_depth;
- if (ddr->accum_tot) {
- depth /= (float)ddr->accum_tot;
- }
- depthdropper_depth_set(C, ddr, depth);
+ float depth = ddr->accum_depth;
+ if (ddr->accum_tot) {
+ depth /= (float)ddr->accum_tot;
+ }
+ depthdropper_depth_set(C, ddr, depth);
}
/* single point sample & set */
static void depthdropper_depth_sample(bContext *C, DepthDropper *ddr, int mx, int my)
{
- float depth = -1.0f;
- if (depth != -1.0f) {
- depthdropper_depth_sample_pt(C, ddr, mx, my, &depth);
- depthdropper_depth_set(C, ddr, depth);
- }
+ float depth = -1.0f;
+ if (depth != -1.0f) {
+ depthdropper_depth_sample_pt(C, ddr, mx, my, &depth);
+ depthdropper_depth_set(C, ddr, depth);
+ }
}
static void depthdropper_depth_sample_accum(bContext *C, DepthDropper *ddr, int mx, int my)
{
- float depth = -1.0f;
- depthdropper_depth_sample_pt(C, ddr, mx, my, &depth);
- if (depth != -1.0f) {
- ddr->accum_depth += depth;
- ddr->accum_tot++;
- }
+ float depth = -1.0f;
+ depthdropper_depth_sample_pt(C, ddr, mx, my, &depth);
+ if (depth != -1.0f) {
+ ddr->accum_depth += depth;
+ ddr->accum_tot++;
+ }
}
static void depthdropper_cancel(bContext *C, wmOperator *op)
{
- DepthDropper *ddr = op->customdata;
- if (ddr->is_set) {
- depthdropper_depth_set(C, ddr, ddr->init_depth);
- }
- depthdropper_exit(C, op);
+ DepthDropper *ddr = op->customdata;
+ if (ddr->is_set) {
+ depthdropper_depth_set(C, ddr, ddr->init_depth);
+ }
+ depthdropper_exit(C, op);
}
/* main modal status check */
static int depthdropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- DepthDropper *ddr = (DepthDropper *)op->customdata;
-
- /* handle modal keymap */
- if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case EYE_MODAL_CANCEL:
- depthdropper_cancel(C, op);
- return OPERATOR_CANCELLED;
- case EYE_MODAL_SAMPLE_CONFIRM:
- {
- const bool is_undo = ddr->is_undo;
- if (ddr->accum_tot == 0) {
- depthdropper_depth_sample(C, ddr, event->x, event->y);
- }
- else {
- depthdropper_depth_set_accum(C, ddr);
- }
- depthdropper_exit(C, op);
- /* Could support finished & undo-skip. */
- return is_undo ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
- }
- case EYE_MODAL_SAMPLE_BEGIN:
- /* enable accum and make first sample */
- ddr->accum_start = true;
- depthdropper_depth_sample_accum(C, ddr, event->x, event->y);
- break;
- case EYE_MODAL_SAMPLE_RESET:
- ddr->accum_tot = 0;
- ddr->accum_depth = 0.0f;
- depthdropper_depth_sample_accum(C, ddr, event->x, event->y);
- depthdropper_depth_set_accum(C, ddr);
- break;
- }
- }
- else if (event->type == MOUSEMOVE) {
- if (ddr->accum_start) {
- /* button is pressed so keep sampling */
- depthdropper_depth_sample_accum(C, ddr, event->x, event->y);
- depthdropper_depth_set_accum(C, ddr);
- }
- }
-
- return OPERATOR_RUNNING_MODAL;
+ DepthDropper *ddr = (DepthDropper *)op->customdata;
+
+ /* handle modal keymap */
+ if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case EYE_MODAL_CANCEL:
+ depthdropper_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ case EYE_MODAL_SAMPLE_CONFIRM: {
+ const bool is_undo = ddr->is_undo;
+ if (ddr->accum_tot == 0) {
+ depthdropper_depth_sample(C, ddr, event->x, event->y);
+ }
+ else {
+ depthdropper_depth_set_accum(C, ddr);
+ }
+ depthdropper_exit(C, op);
+ /* Could support finished & undo-skip. */
+ return is_undo ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ }
+ case EYE_MODAL_SAMPLE_BEGIN:
+ /* enable accum and make first sample */
+ ddr->accum_start = true;
+ depthdropper_depth_sample_accum(C, ddr, event->x, event->y);
+ break;
+ case EYE_MODAL_SAMPLE_RESET:
+ ddr->accum_tot = 0;
+ ddr->accum_depth = 0.0f;
+ depthdropper_depth_sample_accum(C, ddr, event->x, event->y);
+ depthdropper_depth_set_accum(C, ddr);
+ break;
+ }
+ }
+ else if (event->type == MOUSEMOVE) {
+ if (ddr->accum_start) {
+ /* button is pressed so keep sampling */
+ depthdropper_depth_sample_accum(C, ddr, event->x, event->y);
+ depthdropper_depth_set_accum(C, ddr);
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
/* Modal Operator init */
static int depthdropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- /* init */
- if (depthdropper_init(C, op)) {
- WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
-
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ /* init */
+ if (depthdropper_init(C, op)) {
+ WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
/* Repeat operator */
static int depthdropper_exec(bContext *C, wmOperator *op)
{
- /* init */
- if (depthdropper_init(C, op)) {
- /* cleanup */
- depthdropper_exit(C, op);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ /* init */
+ if (depthdropper_init(C, op)) {
+ /* cleanup */
+ depthdropper_exit(C, op);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static bool depthdropper_poll(bContext *C)
{
- PointerRNA ptr;
- PropertyRNA *prop;
- int index_dummy;
- uiBut *but;
-
- /* check if there's an active button taking depth value */
- if ((CTX_wm_window(C) != NULL) &&
- (but = UI_context_active_but_prop_get(C, &ptr, &prop, &index_dummy)) &&
- (but->type == UI_BTYPE_NUM) &&
- (prop != NULL))
- {
- if ((RNA_property_type(prop) == PROP_FLOAT) &&
- (RNA_property_subtype(prop) & PROP_UNIT_LENGTH) &&
- (RNA_property_array_check(prop) == false))
- {
- return 1;
- }
- }
- else {
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- if (rv3d && rv3d->persp == RV3D_CAMOB) {
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d->camera && v3d->camera->data && !ID_IS_LINKED(v3d->camera->data)) {
- return 1;
- }
- }
- }
-
- return 0;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index_dummy;
+ uiBut *but;
+
+ /* check if there's an active button taking depth value */
+ if ((CTX_wm_window(C) != NULL) &&
+ (but = UI_context_active_but_prop_get(C, &ptr, &prop, &index_dummy)) &&
+ (but->type == UI_BTYPE_NUM) && (prop != NULL)) {
+ if ((RNA_property_type(prop) == PROP_FLOAT) &&
+ (RNA_property_subtype(prop) & PROP_UNIT_LENGTH) &&
+ (RNA_property_array_check(prop) == false)) {
+ return 1;
+ }
+ }
+ else {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if (rv3d && rv3d->persp == RV3D_CAMOB) {
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->camera && v3d->camera->data && !ID_IS_LINKED(v3d->camera->data)) {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
}
void UI_OT_eyedropper_depth(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Eyedropper Depth";
- ot->idname = "UI_OT_eyedropper_depth";
- ot->description = "Sample depth from the 3D view";
-
- /* api callbacks */
- ot->invoke = depthdropper_invoke;
- ot->modal = depthdropper_modal;
- ot->cancel = depthdropper_cancel;
- ot->exec = depthdropper_exec;
- ot->poll = depthdropper_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_INTERNAL;
-
- /* properties */
+ /* identifiers */
+ ot->name = "Eyedropper Depth";
+ ot->idname = "UI_OT_eyedropper_depth";
+ ot->description = "Sample depth from the 3D view";
+
+ /* api callbacks */
+ ot->invoke = depthdropper_invoke;
+ ot->modal = depthdropper_modal;
+ ot->cancel = depthdropper_cancel;
+ ot->exec = depthdropper_exec;
+ ot->poll = depthdropper_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_INTERNAL;
+
+ /* properties */
}
diff --git a/source/blender/editors/interface/interface_eyedropper_driver.c b/source/blender/editors/interface/interface_eyedropper_driver.c
index dd2656e7fa1..c1aee190cd3 100644
--- a/source/blender/editors/interface/interface_eyedropper_driver.c
+++ b/source/blender/editors/interface/interface_eyedropper_driver.c
@@ -32,7 +32,6 @@
#include "DNA_screen_types.h"
#include "DNA_object_types.h"
-
#include "BKE_context.h"
#include "BKE_animsys.h"
@@ -53,188 +52,193 @@
#include "interface_eyedropper_intern.h"
typedef struct DriverDropper {
- /* Destination property (i.e. where we'll add a driver) */
- PointerRNA ptr;
- PropertyRNA *prop;
- int index;
- bool is_undo;
+ /* Destination property (i.e. where we'll add a driver) */
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+ bool is_undo;
- // TODO: new target?
+ // TODO: new target?
} DriverDropper;
static bool driverdropper_init(bContext *C, wmOperator *op)
{
- DriverDropper *ddr = MEM_callocN(sizeof(DriverDropper), __func__);
+ DriverDropper *ddr = MEM_callocN(sizeof(DriverDropper), __func__);
- uiBut *but = UI_context_active_but_prop_get(C, &ddr->ptr, &ddr->prop, &ddr->index);
+ uiBut *but = UI_context_active_but_prop_get(C, &ddr->ptr, &ddr->prop, &ddr->index);
- if ((ddr->ptr.data == NULL) ||
- (ddr->prop == NULL) ||
- (RNA_property_editable(&ddr->ptr, ddr->prop) == false) ||
- (RNA_property_animateable(&ddr->ptr, ddr->prop) == false) ||
- (but->flag & UI_BUT_DRIVEN))
- {
- MEM_freeN(ddr);
- return false;
- }
- op->customdata = ddr;
+ if ((ddr->ptr.data == NULL) || (ddr->prop == NULL) ||
+ (RNA_property_editable(&ddr->ptr, ddr->prop) == false) ||
+ (RNA_property_animateable(&ddr->ptr, ddr->prop) == false) || (but->flag & UI_BUT_DRIVEN)) {
+ MEM_freeN(ddr);
+ return false;
+ }
+ op->customdata = ddr;
- ddr->is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
+ ddr->is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
- return true;
+ return true;
}
static void driverdropper_exit(bContext *C, wmOperator *op)
{
- WM_cursor_modal_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
- if (op->customdata) {
- MEM_freeN(op->customdata);
- op->customdata = NULL;
- }
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+ }
}
static void driverdropper_sample(bContext *C, wmOperator *op, const wmEvent *event)
{
- DriverDropper *ddr = (DriverDropper *)op->customdata;
- uiBut *but = eyedropper_get_property_button_under_mouse(C, event);
-
- short mapping_type = RNA_enum_get(op->ptr, "mapping_type");
- short flag = 0;
-
- /* we can only add a driver if we know what RNA property it corresponds to */
- if (but == NULL) {
- return;
- }
- else {
- /* Get paths for src... */
- PointerRNA *target_ptr = &but->rnapoin;
- PropertyRNA *target_prop = but->rnaprop;
- int target_index = but->rnaindex;
-
- char *target_path = RNA_path_from_ID_to_property(target_ptr, target_prop);
-
- /* ... and destination */
- char *dst_path = BKE_animdata_driver_path_hack(C, &ddr->ptr, ddr->prop, NULL);
-
- /* Now create driver(s) */
- if (target_path && dst_path) {
- int success = ANIM_add_driver_with_target(op->reports,
- ddr->ptr.id.data, dst_path, ddr->index,
- target_ptr->id.data, target_path, target_index,
- flag, DRIVER_TYPE_PYTHON, mapping_type);
-
- if (success) {
- /* send updates */
- UI_context_update_anim_flag(C);
- DEG_relations_tag_update(CTX_data_main(C));
- DEG_id_tag_update(ddr->ptr.id.data, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX
- }
- }
-
- /* cleanup */
- if (target_path) {
- MEM_freeN(target_path);
- }
- if (dst_path) {
- MEM_freeN(dst_path);
- }
- }
+ DriverDropper *ddr = (DriverDropper *)op->customdata;
+ uiBut *but = eyedropper_get_property_button_under_mouse(C, event);
+
+ short mapping_type = RNA_enum_get(op->ptr, "mapping_type");
+ short flag = 0;
+
+ /* we can only add a driver if we know what RNA property it corresponds to */
+ if (but == NULL) {
+ return;
+ }
+ else {
+ /* Get paths for src... */
+ PointerRNA *target_ptr = &but->rnapoin;
+ PropertyRNA *target_prop = but->rnaprop;
+ int target_index = but->rnaindex;
+
+ char *target_path = RNA_path_from_ID_to_property(target_ptr, target_prop);
+
+ /* ... and destination */
+ char *dst_path = BKE_animdata_driver_path_hack(C, &ddr->ptr, ddr->prop, NULL);
+
+ /* Now create driver(s) */
+ if (target_path && dst_path) {
+ int success = ANIM_add_driver_with_target(op->reports,
+ ddr->ptr.id.data,
+ dst_path,
+ ddr->index,
+ target_ptr->id.data,
+ target_path,
+ target_index,
+ flag,
+ DRIVER_TYPE_PYTHON,
+ mapping_type);
+
+ if (success) {
+ /* send updates */
+ UI_context_update_anim_flag(C);
+ DEG_relations_tag_update(CTX_data_main(C));
+ DEG_id_tag_update(ddr->ptr.id.data, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX
+ }
+ }
+
+ /* cleanup */
+ if (target_path) {
+ MEM_freeN(target_path);
+ }
+ if (dst_path) {
+ MEM_freeN(dst_path);
+ }
+ }
}
static void driverdropper_cancel(bContext *C, wmOperator *op)
{
- driverdropper_exit(C, op);
+ driverdropper_exit(C, op);
}
/* main modal status check */
static int driverdropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- DriverDropper *ddr = op->customdata;
-
- /* handle modal keymap */
- if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case EYE_MODAL_CANCEL:
- {
- driverdropper_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- case EYE_MODAL_SAMPLE_CONFIRM:
- {
- const bool is_undo = ddr->is_undo;
- driverdropper_sample(C, op, event);
- driverdropper_exit(C, op);
- /* Could support finished & undo-skip. */
- return is_undo ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
- }
- }
- }
-
- return OPERATOR_RUNNING_MODAL;
+ DriverDropper *ddr = op->customdata;
+
+ /* handle modal keymap */
+ if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case EYE_MODAL_CANCEL: {
+ driverdropper_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ case EYE_MODAL_SAMPLE_CONFIRM: {
+ const bool is_undo = ddr->is_undo;
+ driverdropper_sample(C, op, event);
+ driverdropper_exit(C, op);
+ /* Could support finished & undo-skip. */
+ return is_undo ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ }
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
/* Modal Operator init */
static int driverdropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- /* init */
- if (driverdropper_init(C, op)) {
- WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
-
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ /* init */
+ if (driverdropper_init(C, op)) {
+ WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
/* Repeat operator */
static int driverdropper_exec(bContext *C, wmOperator *op)
{
- /* init */
- if (driverdropper_init(C, op)) {
- /* cleanup */
- driverdropper_exit(C, op);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ /* init */
+ if (driverdropper_init(C, op)) {
+ /* cleanup */
+ driverdropper_exit(C, op);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static bool driverdropper_poll(bContext *C)
{
- if (!CTX_wm_window(C)) {
- return 0;
- }
- else {
- return 1;
- }
+ if (!CTX_wm_window(C)) {
+ return 0;
+ }
+ else {
+ return 1;
+ }
}
void UI_OT_eyedropper_driver(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Eyedropper Driver";
- ot->idname = "UI_OT_eyedropper_driver";
- ot->description = "Pick a property to use as a driver target";
-
- /* api callbacks */
- ot->invoke = driverdropper_invoke;
- ot->modal = driverdropper_modal;
- ot->cancel = driverdropper_cancel;
- ot->exec = driverdropper_exec;
- ot->poll = driverdropper_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_INTERNAL;
-
- /* properties */
- RNA_def_enum(ot->srna, "mapping_type", prop_driver_create_mapping_types, 0,
- "Mapping Type", "Method used to match target and driven properties");
+ /* identifiers */
+ ot->name = "Eyedropper Driver";
+ ot->idname = "UI_OT_eyedropper_driver";
+ ot->description = "Pick a property to use as a driver target";
+
+ /* api callbacks */
+ ot->invoke = driverdropper_invoke;
+ ot->modal = driverdropper_modal;
+ ot->cancel = driverdropper_cancel;
+ ot->exec = driverdropper_exec;
+ ot->poll = driverdropper_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_INTERNAL;
+
+ /* properties */
+ RNA_def_enum(ot->srna,
+ "mapping_type",
+ prop_driver_create_mapping_types,
+ 0,
+ "Mapping Type",
+ "Method used to match target and driven properties");
}
diff --git a/source/blender/editors/interface/interface_eyedropper_intern.h b/source/blender/editors/interface/interface_eyedropper_intern.h
index 1ce0cb6d3e1..d9ec0657bfe 100644
--- a/source/blender/editors/interface/interface_eyedropper_intern.h
+++ b/source/blender/editors/interface/interface_eyedropper_intern.h
@@ -24,7 +24,9 @@
#define __INTERFACE_EYEDROPPER_INTERN_H__
/* interface_eyedropper.c */
-void eyedropper_draw_cursor_text(const struct bContext *C, const struct ARegion *ar, const char *name);
+void eyedropper_draw_cursor_text(const struct bContext *C,
+ const struct ARegion *ar,
+ const char *name);
uiBut *eyedropper_get_property_button_under_mouse(bContext *C, const wmEvent *event);
/* interface_eyedropper_color.c (expose for color-band picker) */
@@ -32,19 +34,19 @@ void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3]);
/* Used for most eye-dropper operators. */
enum {
- EYE_MODAL_CANCEL = 1,
- EYE_MODAL_SAMPLE_CONFIRM,
- EYE_MODAL_SAMPLE_BEGIN,
- EYE_MODAL_SAMPLE_RESET,
+ EYE_MODAL_CANCEL = 1,
+ EYE_MODAL_SAMPLE_CONFIRM,
+ EYE_MODAL_SAMPLE_BEGIN,
+ EYE_MODAL_SAMPLE_RESET,
};
/* Color-band point sample. */
enum {
- EYE_MODAL_POINT_CANCEL = 1,
- EYE_MODAL_POINT_SAMPLE,
- EYE_MODAL_POINT_CONFIRM,
- EYE_MODAL_POINT_RESET,
- EYE_MODAL_POINT_REMOVE_LAST,
+ EYE_MODAL_POINT_CANCEL = 1,
+ EYE_MODAL_POINT_SAMPLE,
+ EYE_MODAL_POINT_CONFIRM,
+ EYE_MODAL_POINT_RESET,
+ EYE_MODAL_POINT_REMOVE_LAST,
};
-#endif /* __INTERFACE_EYEDROPPER_INTERN_H__ */
+#endif /* __INTERFACE_EYEDROPPER_INTERN_H__ */
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 86a225bf3bd..0fe12b21636 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -102,7 +102,10 @@
#define UI_MAX_PASSWORD_STR 128
/* proto */
-static int ui_do_but_EXIT(bContext *C, uiBut *but, struct uiHandleButtonData *data, const wmEvent *event);
+static int ui_do_but_EXIT(bContext *C,
+ uiBut *but,
+ struct uiHandleButtonData *data,
+ const wmEvent *event);
static bool ui_but_find_select_in_enum__cmp(const uiBut *but_a, const uiBut *but_b);
static void ui_textedit_string_set(uiBut *but, struct uiHandleButtonData *data, const char *str);
@@ -115,289 +118,289 @@ static bool ui_mouse_motion_keynav_test(struct uiKeyNavLock *keynav, const wmEve
/** \name Structs & Defines
* \{ */
-#define BUTTON_FLASH_DELAY 0.020
-#define MENU_SCROLL_INTERVAL 0.1
-#define PIE_MENU_INTERVAL 0.01
-#define BUTTON_AUTO_OPEN_THRESH 0.2
+#define BUTTON_FLASH_DELAY 0.020
+#define MENU_SCROLL_INTERVAL 0.1
+#define PIE_MENU_INTERVAL 0.01
+#define BUTTON_AUTO_OPEN_THRESH 0.2
#define BUTTON_MOUSE_TOWARDS_THRESH 1.0
/* pixels to move the cursor to get out of keyboard navigation */
-#define BUTTON_KEYNAV_PX_LIMIT 8
+#define BUTTON_KEYNAV_PX_LIMIT 8
-#define MENU_TOWARDS_MARGIN 20 /* margin in pixels */
-#define MENU_TOWARDS_WIGGLE_ROOM 64 /* tolerance in pixels */
+#define MENU_TOWARDS_MARGIN 20 /* margin in pixels */
+#define MENU_TOWARDS_WIGGLE_ROOM 64 /* tolerance in pixels */
/* drag-lock distance threshold in pixels */
-#define BUTTON_DRAGLOCK_THRESH 3
+#define BUTTON_DRAGLOCK_THRESH 3
typedef enum uiButtonActivateType {
- BUTTON_ACTIVATE_OVER,
- BUTTON_ACTIVATE,
- BUTTON_ACTIVATE_APPLY,
- BUTTON_ACTIVATE_TEXT_EDITING,
- BUTTON_ACTIVATE_OPEN,
+ BUTTON_ACTIVATE_OVER,
+ BUTTON_ACTIVATE,
+ BUTTON_ACTIVATE_APPLY,
+ BUTTON_ACTIVATE_TEXT_EDITING,
+ BUTTON_ACTIVATE_OPEN,
} uiButtonActivateType;
typedef enum uiHandleButtonState {
- BUTTON_STATE_INIT,
- BUTTON_STATE_HIGHLIGHT,
- BUTTON_STATE_WAIT_FLASH,
- BUTTON_STATE_WAIT_RELEASE,
- BUTTON_STATE_WAIT_KEY_EVENT,
- BUTTON_STATE_NUM_EDITING,
- BUTTON_STATE_TEXT_EDITING,
- BUTTON_STATE_TEXT_SELECTING,
- BUTTON_STATE_MENU_OPEN,
- BUTTON_STATE_WAIT_DRAG,
- BUTTON_STATE_EXIT,
+ BUTTON_STATE_INIT,
+ BUTTON_STATE_HIGHLIGHT,
+ BUTTON_STATE_WAIT_FLASH,
+ BUTTON_STATE_WAIT_RELEASE,
+ BUTTON_STATE_WAIT_KEY_EVENT,
+ BUTTON_STATE_NUM_EDITING,
+ BUTTON_STATE_TEXT_EDITING,
+ BUTTON_STATE_TEXT_SELECTING,
+ BUTTON_STATE_MENU_OPEN,
+ BUTTON_STATE_WAIT_DRAG,
+ BUTTON_STATE_EXIT,
} uiHandleButtonState;
-
#ifdef USE_ALLSELECT
/* Unfortunately there's no good way handle more generally:
* (propagate single clicks on layer buttons to other objects) */
-#define USE_ALLSELECT_LAYER_HACK
+# define USE_ALLSELECT_LAYER_HACK
typedef struct uiSelectContextElem {
- PointerRNA ptr;
- union {
- bool val_b;
- int val_i;
- float val_f;
- };
+ PointerRNA ptr;
+ union {
+ bool val_b;
+ int val_i;
+ float val_f;
+ };
} uiSelectContextElem;
typedef struct uiSelectContextStore {
- uiSelectContextElem *elems;
- int elems_len;
- bool do_free;
- bool is_enabled;
- /* When set, simply copy values (don't apply difference).
- * Rules are:
- * - dragging numbers uses delta.
- * - typing in values will assign to all. */
- bool is_copy;
+ uiSelectContextElem *elems;
+ int elems_len;
+ bool do_free;
+ bool is_enabled;
+ /* When set, simply copy values (don't apply difference).
+ * Rules are:
+ * - dragging numbers uses delta.
+ * - typing in values will assign to all. */
+ bool is_copy;
} uiSelectContextStore;
-static bool ui_selectcontext_begin(
- bContext *C, uiBut *but, struct uiSelectContextStore *selctx_data);
-static void ui_selectcontext_end(
- uiBut *but, uiSelectContextStore *selctx_data);
-static void ui_selectcontext_apply(
- bContext *C, uiBut *but, struct uiSelectContextStore *selctx_data,
- const double value, const double value_orig);
+static bool ui_selectcontext_begin(bContext *C,
+ uiBut *but,
+ struct uiSelectContextStore *selctx_data);
+static void ui_selectcontext_end(uiBut *but, uiSelectContextStore *selctx_data);
+static void ui_selectcontext_apply(bContext *C,
+ uiBut *but,
+ struct uiSelectContextStore *selctx_data,
+ const double value,
+ const double value_orig);
-#define IS_ALLSELECT_EVENT(event) ((event)->alt != 0)
+# define IS_ALLSELECT_EVENT(event) ((event)->alt != 0)
/** just show a tinted color so users know its activated */
-#define UI_BUT_IS_SELECT_CONTEXT UI_BUT_NODE_ACTIVE
-
-#endif /* USE_ALLSELECT */
+# define UI_BUT_IS_SELECT_CONTEXT UI_BUT_NODE_ACTIVE
+#endif /* USE_ALLSELECT */
#ifdef USE_DRAG_MULTINUM
/**
* how far to drag before we check for gesture direction (in pixels),
* note: half the height of a button is about right... */
-#define DRAG_MULTINUM_THRESHOLD_DRAG_X (UI_UNIT_Y / 4)
+# define DRAG_MULTINUM_THRESHOLD_DRAG_X (UI_UNIT_Y / 4)
/**
* how far to drag horizontally before we stop checking which buttons the gesture spans (in pixels),
* locking down the buttons so we can drag freely without worrying about vertical movement. */
-#define DRAG_MULTINUM_THRESHOLD_DRAG_Y (UI_UNIT_Y / 4)
+# define DRAG_MULTINUM_THRESHOLD_DRAG_Y (UI_UNIT_Y / 4)
/**
* how strict to be when detecting a vertical gesture, [0.5 == sloppy], [0.9 == strict], (unsigned dot-product)
* note: we should be quite strict here, since doing a vertical gesture by accident should be avoided,
* however with some care a user should be able to do a vertical movement without *missing*. */
-#define DRAG_MULTINUM_THRESHOLD_VERTICAL (0.75f)
-
+# define DRAG_MULTINUM_THRESHOLD_VERTICAL (0.75f)
/* a simple version of uiHandleButtonData when accessing multiple buttons */
typedef struct uiButMultiState {
- double origvalue;
- uiBut *but;
+ double origvalue;
+ uiBut *but;
-#ifdef USE_ALLSELECT
- uiSelectContextStore select_others;
-#endif
+# ifdef USE_ALLSELECT
+ uiSelectContextStore select_others;
+# endif
} uiButMultiState;
typedef struct uiHandleButtonMulti {
- enum {
- /** gesture direction unknown, wait until mouse has moved enough... */
- BUTTON_MULTI_INIT_UNSET = 0,
- /** vertical gesture detected, flag buttons interactively (UI_BUT_DRAG_MULTI) */
- BUTTON_MULTI_INIT_SETUP,
- /** flag buttons finished, apply horizontal motion to active and flagged */
- BUTTON_MULTI_INIT_ENABLE,
- /** vertical gesture _not_ detected, take no further action */
- BUTTON_MULTI_INIT_DISABLE,
- } init;
-
- bool has_mbuts; /* any buttons flagged UI_BUT_DRAG_MULTI */
- LinkNode *mbuts;
- uiButStore *bs_mbuts;
-
- bool is_proportional;
-
- /* In some cases we directly apply the changes to multiple buttons,
- * so we don't want to do it twice. */
- bool skip;
-
- /* before activating, we need to check gesture direction accumulate signed cursor movement
- * here so we can tell if this is a vertical motion or not. */
- float drag_dir[2];
-
- /* values copied direct from event->x,y
- * used to detect buttons between the current and initial mouse position */
- int drag_start[2];
-
- /* store x location once BUTTON_MULTI_INIT_SETUP is set,
- * moving outside this sets BUTTON_MULTI_INIT_ENABLE */
- int drag_lock_x;
+ enum {
+ /** gesture direction unknown, wait until mouse has moved enough... */
+ BUTTON_MULTI_INIT_UNSET = 0,
+ /** vertical gesture detected, flag buttons interactively (UI_BUT_DRAG_MULTI) */
+ BUTTON_MULTI_INIT_SETUP,
+ /** flag buttons finished, apply horizontal motion to active and flagged */
+ BUTTON_MULTI_INIT_ENABLE,
+ /** vertical gesture _not_ detected, take no further action */
+ BUTTON_MULTI_INIT_DISABLE,
+ } init;
+
+ bool has_mbuts; /* any buttons flagged UI_BUT_DRAG_MULTI */
+ LinkNode *mbuts;
+ uiButStore *bs_mbuts;
+
+ bool is_proportional;
+
+ /* In some cases we directly apply the changes to multiple buttons,
+ * so we don't want to do it twice. */
+ bool skip;
+
+ /* before activating, we need to check gesture direction accumulate signed cursor movement
+ * here so we can tell if this is a vertical motion or not. */
+ float drag_dir[2];
+
+ /* values copied direct from event->x,y
+ * used to detect buttons between the current and initial mouse position */
+ int drag_start[2];
+
+ /* store x location once BUTTON_MULTI_INIT_SETUP is set,
+ * moving outside this sets BUTTON_MULTI_INIT_ENABLE */
+ int drag_lock_x;
} uiHandleButtonMulti;
-#endif /* USE_DRAG_MULTINUM */
+#endif /* USE_DRAG_MULTINUM */
typedef struct uiHandleButtonData {
- wmWindowManager *wm;
- wmWindow *window;
- ARegion *region;
-
- bool interactive;
-
- /* overall state */
- uiHandleButtonState state;
- int retval;
- /* booleans (could be made into flags) */
- bool cancel, escapecancel;
- bool applied, applied_interactive;
- bool changed_cursor;
- wmTimer *flashtimer;
-
- /* edited value */
- /* use 'ui_textedit_string_set' to assign new strings */
- char *str;
- char *origstr;
- double value, origvalue, startvalue;
- float vec[3], origvec[3];
-#if 0 /* UNUSED */
- int togdual, togonly;
+ wmWindowManager *wm;
+ wmWindow *window;
+ ARegion *region;
+
+ bool interactive;
+
+ /* overall state */
+ uiHandleButtonState state;
+ int retval;
+ /* booleans (could be made into flags) */
+ bool cancel, escapecancel;
+ bool applied, applied_interactive;
+ bool changed_cursor;
+ wmTimer *flashtimer;
+
+ /* edited value */
+ /* use 'ui_textedit_string_set' to assign new strings */
+ char *str;
+ char *origstr;
+ double value, origvalue, startvalue;
+ float vec[3], origvec[3];
+#if 0 /* UNUSED */
+ int togdual, togonly;
#endif
- ColorBand *coba;
-
- /* tooltip */
- uint tooltip_force : 1;
-
- /* auto open */
- bool used_mouse;
- wmTimer *autoopentimer;
-
- /* auto open (hold) */
- wmTimer *hold_action_timer;
-
- /* text selection/editing */
- /* size of 'str' (including terminator) */
- 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;
- /* allow to realloc str/editstr and use 'maxlen' to track alloc size (maxlen + 1) */
- bool is_str_dynamic;
-
- /* number editing / dragging */
- /* coords are Window/uiBlock relative (depends on the button) */
- int draglastx, draglasty;
- int dragstartx, dragstarty;
- int draglastvalue;
- int dragstartvalue;
- bool dragchange, draglock;
- int dragsel;
- float dragf, dragfstart;
- CBData *dragcbd;
+ ColorBand *coba;
+
+ /* tooltip */
+ uint tooltip_force : 1;
+
+ /* auto open */
+ bool used_mouse;
+ wmTimer *autoopentimer;
+
+ /* auto open (hold) */
+ wmTimer *hold_action_timer;
+
+ /* text selection/editing */
+ /* size of 'str' (including terminator) */
+ 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;
+ /* allow to realloc str/editstr and use 'maxlen' to track alloc size (maxlen + 1) */
+ bool is_str_dynamic;
+
+ /* number editing / dragging */
+ /* coords are Window/uiBlock relative (depends on the button) */
+ int draglastx, draglasty;
+ int dragstartx, dragstarty;
+ int draglastvalue;
+ int dragstartvalue;
+ bool dragchange, draglock;
+ int dragsel;
+ float dragf, dragfstart;
+ CBData *dragcbd;
#ifdef USE_CONT_MOUSE_CORRECT
- /* when ungrabbing buttons which are #ui_but_is_cursor_warp(),
- * we may want to position them.
- * FLT_MAX signifies do-nothing, use #ui_block_to_window_fl()
- * to get this into a usable space. */
- float ungrab_mval[2];
+ /* when ungrabbing buttons which are #ui_but_is_cursor_warp(),
+ * we may want to position them.
+ * FLT_MAX signifies do-nothing, use #ui_block_to_window_fl()
+ * to get this into a usable space. */
+ float ungrab_mval[2];
#endif
- /* menu open (watch UI_screen_free_active_but) */
- uiPopupBlockHandle *menu;
- int menuretval;
+ /* menu open (watch UI_screen_free_active_but) */
+ uiPopupBlockHandle *menu;
+ int menuretval;
- /* search box (watch UI_screen_free_active_but) */
- ARegion *searchbox;
+ /* search box (watch UI_screen_free_active_but) */
+ ARegion *searchbox;
#ifdef USE_KEYNAV_LIMIT
- struct uiKeyNavLock searchbox_keynav_state;
+ struct uiKeyNavLock searchbox_keynav_state;
#endif
#ifdef USE_DRAG_MULTINUM
- /* Multi-buttons will be updated in unison with the active button. */
- uiHandleButtonMulti multi_data;
+ /* Multi-buttons will be updated in unison with the active button. */
+ uiHandleButtonMulti multi_data;
#endif
#ifdef USE_ALLSELECT
- uiSelectContextStore select_others;
+ uiSelectContextStore select_others;
#endif
- /* post activate */
- uiButtonActivateType posttype;
- uiBut *postbut;
+ /* post activate */
+ uiButtonActivateType posttype;
+ uiBut *postbut;
} uiHandleButtonData;
typedef struct uiAfterFunc {
- struct uiAfterFunc *next, *prev;
+ struct uiAfterFunc *next, *prev;
- uiButHandleFunc func;
- void *func_arg1;
- void *func_arg2;
+ uiButHandleFunc func;
+ void *func_arg1;
+ void *func_arg2;
- uiButHandleNFunc funcN;
- void *func_argN;
+ uiButHandleNFunc funcN;
+ void *func_argN;
- uiButHandleRenameFunc rename_func;
- void *rename_arg1;
- void *rename_orig;
+ uiButHandleRenameFunc rename_func;
+ void *rename_arg1;
+ void *rename_orig;
- uiBlockHandleFunc handle_func;
- void *handle_func_arg;
- int retval;
+ uiBlockHandleFunc handle_func;
+ void *handle_func_arg;
+ int retval;
- uiMenuHandleFunc butm_func;
- void *butm_func_arg;
- int a2;
+ uiMenuHandleFunc butm_func;
+ void *butm_func_arg;
+ int a2;
- wmOperator *popup_op;
- wmOperatorType *optype;
- int opcontext;
- PointerRNA *opptr;
+ wmOperator *popup_op;
+ wmOperatorType *optype;
+ int opcontext;
+ PointerRNA *opptr;
- PointerRNA rnapoin;
- PropertyRNA *rnaprop;
+ PointerRNA rnapoin;
+ PropertyRNA *rnaprop;
- bContextStore *context;
+ bContextStore *context;
- char undostr[BKE_UNDO_STR_MAX];
+ char undostr[BKE_UNDO_STR_MAX];
} uiAfterFunc;
-
static void button_activate_init(bContext *C, ARegion *ar, 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);
+ 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, uiBut *but, uiButtonActivateType type);
+static void ui_handle_button_activate(bContext *C,
+ ARegion *ar,
+ uiBut *but,
+ uiButtonActivateType type);
#ifdef USE_DRAG_MULTINUM
static void ui_multibut_restore(bContext *C, uiHandleButtonData *data, uiBlock *block);
@@ -411,60 +414,57 @@ static bool but_copypaste_curve_alive = false;
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name UI Queries
* \{ */
bool ui_but_is_editing(const uiBut *but)
{
- uiHandleButtonData *data = but->active;
- return (data && ELEM(data->state, BUTTON_STATE_TEXT_EDITING, BUTTON_STATE_NUM_EDITING));
+ uiHandleButtonData *data = but->active;
+ return (data && ELEM(data->state, BUTTON_STATE_TEXT_EDITING, BUTTON_STATE_NUM_EDITING));
}
/* assumes event type is MOUSEPAN */
void ui_pan_to_scroll(const wmEvent *event, int *type, int *val)
{
- static int lastdy = 0;
- int dy = event->prevy - event->y;
+ static int lastdy = 0;
+ int dy = event->prevy - event->y;
- /* This event should be originally from event->type,
- * converting wrong event into wheel is bad, see [#33803] */
- BLI_assert(*type == MOUSEPAN);
+ /* This event should be originally from event->type,
+ * converting wrong event into wheel is bad, see [#33803] */
+ BLI_assert(*type == MOUSEPAN);
- /* sign differs, reset */
- if ((dy > 0 && lastdy < 0) || (dy < 0 && lastdy > 0)) {
- lastdy = dy;
- }
- else {
- lastdy += dy;
+ /* sign differs, reset */
+ if ((dy > 0 && lastdy < 0) || (dy < 0 && lastdy > 0)) {
+ lastdy = dy;
+ }
+ else {
+ lastdy += dy;
- if (ABS(lastdy) > (int)UI_UNIT_Y) {
- if (U.uiflag2 & USER_TRACKPAD_NATURAL) {
- dy = -dy;
- }
+ if (ABS(lastdy) > (int)UI_UNIT_Y) {
+ if (U.uiflag2 & USER_TRACKPAD_NATURAL) {
+ dy = -dy;
+ }
- *val = KM_PRESS;
+ *val = KM_PRESS;
- if (dy > 0) {
- *type = WHEELUPMOUSE;
- }
- else {
- *type = WHEELDOWNMOUSE;
- }
+ if (dy > 0) {
+ *type = WHEELUPMOUSE;
+ }
+ else {
+ *type = WHEELDOWNMOUSE;
+ }
- lastdy = 0;
- }
- }
+ lastdy = 0;
+ }
+ }
}
static bool ui_but_find_select_in_enum__cmp(const uiBut *but_a, const uiBut *but_b)
{
- return ((but_a->type == but_b->type) &&
- (but_a->alignnr == but_b->alignnr) &&
- (but_a->poin == but_b->poin) &&
- (but_a->rnapoin.type == but_b->rnapoin.type) &&
- (but_a->rnaprop == but_b->rnaprop));
+ return ((but_a->type == but_b->type) && (but_a->alignnr == but_b->alignnr) &&
+ (but_a->poin == but_b->poin) && (but_a->rnapoin.type == but_b->rnapoin.type) &&
+ (but_a->rnaprop == but_b->rnaprop));
}
/**
@@ -474,43 +474,44 @@ static bool ui_but_find_select_in_enum__cmp(const uiBut *but_a, const uiBut *but
*/
uiBut *ui_but_find_select_in_enum(uiBut *but, int direction)
{
- uiBut *but_iter = but;
- uiBut *but_found = NULL;
- BLI_assert(ELEM(direction, -1, 1));
+ uiBut *but_iter = but;
+ uiBut *but_found = NULL;
+ BLI_assert(ELEM(direction, -1, 1));
- while ((but_iter->prev) &&
- ui_but_find_select_in_enum__cmp(but_iter->prev, but))
- {
- but_iter = but_iter->prev;
- }
+ while ((but_iter->prev) && ui_but_find_select_in_enum__cmp(but_iter->prev, but)) {
+ but_iter = but_iter->prev;
+ }
- while (but_iter && ui_but_find_select_in_enum__cmp(but_iter, but)) {
- if (but_iter->flag & UI_SELECT) {
- but_found = but_iter;
- if (direction == 1) {
- break;
- }
- }
- but_iter = but_iter->next;
- }
+ while (but_iter && ui_but_find_select_in_enum__cmp(but_iter, but)) {
+ if (but_iter->flag & UI_SELECT) {
+ but_found = but_iter;
+ if (direction == 1) {
+ break;
+ }
+ }
+ but_iter = but_iter->next;
+ }
- return but_found;
+ return but_found;
}
static float ui_mouse_scale_warp_factor(const bool shift)
{
- return shift ? 0.05f : 1.0f;
+ return shift ? 0.05f : 1.0f;
}
-static void ui_mouse_scale_warp(
- uiHandleButtonData *data, const float mx, const float my,
- float *r_mx, float *r_my, const bool shift)
+static void ui_mouse_scale_warp(uiHandleButtonData *data,
+ const float mx,
+ const float my,
+ float *r_mx,
+ float *r_my,
+ const bool shift)
{
- const float fac = ui_mouse_scale_warp_factor(shift);
+ const float fac = ui_mouse_scale_warp_factor(shift);
- /* slow down the mouse, this is fairly picky */
- *r_mx = (data->dragstartx * (1.0f - fac) + mx * fac);
- *r_my = (data->dragstarty * (1.0f - fac) + my * fac);
+ /* slow down the mouse, this is fairly picky */
+ *r_mx = (data->dragstartx * (1.0f - fac) + mx * fac);
+ *r_my = (data->dragstarty * (1.0f - fac) + my * fac);
}
/** \} */
@@ -524,24 +525,24 @@ static void ui_mouse_scale_warp(
*/
static bool ui_but_dragedit_update_mval(uiHandleButtonData *data, int mx)
{
- if (mx == data->draglastx) {
- return false;
- }
+ if (mx == data->draglastx) {
+ return false;
+ }
- if (data->draglock) {
- if (ABS(mx - data->dragstartx) <= BUTTON_DRAGLOCK_THRESH) {
- return false;
- }
+ if (data->draglock) {
+ if (ABS(mx - data->dragstartx) <= BUTTON_DRAGLOCK_THRESH) {
+ return false;
+ }
#ifdef USE_DRAG_MULTINUM
- if (ELEM(data->multi_data.init, BUTTON_MULTI_INIT_UNSET, BUTTON_MULTI_INIT_SETUP)) {
- return false;
- }
+ if (ELEM(data->multi_data.init, BUTTON_MULTI_INIT_UNSET, BUTTON_MULTI_INIT_SETUP)) {
+ return false;
+ }
#endif
- data->draglock = false;
- data->dragstartx = mx; /* ignore mouse movement within drag-lock */
- }
+ data->draglock = false;
+ data->dragstartx = mx; /* ignore mouse movement within drag-lock */
+ }
- return true;
+ return true;
}
/** \} */
@@ -552,27 +553,27 @@ static bool ui_but_dragedit_update_mval(uiHandleButtonData *data, int mx)
* \{ */
enum eSnapType {
- SNAP_OFF = 0,
- SNAP_ON,
- SNAP_ON_SMALL,
+ SNAP_OFF = 0,
+ SNAP_ON,
+ SNAP_ON_SMALL,
};
static enum eSnapType ui_event_to_snap(const wmEvent *event)
{
- return (event->ctrl) ? (event->shift) ? SNAP_ON_SMALL : SNAP_ON : SNAP_OFF;
+ return (event->ctrl) ? (event->shift) ? SNAP_ON_SMALL : SNAP_ON : SNAP_OFF;
}
static bool ui_event_is_snap(const wmEvent *event)
{
- return (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY) ||
- ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY));
+ return (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY) ||
+ ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY));
}
static void ui_color_snap_hue(const enum eSnapType snap, float *r_hue)
{
- const float snap_increment = (snap == SNAP_ON_SMALL) ? 24 : 12;
- BLI_assert(snap != SNAP_OFF);
- *r_hue = roundf((*r_hue) * snap_increment) / snap_increment;
+ const float snap_increment = (snap == SNAP_ON_SMALL) ? 24 : 12;
+ BLI_assert(snap != SNAP_OFF);
+ *r_hue = roundf((*r_hue) * snap_increment) / snap_increment;
}
/** \} */
@@ -585,13 +586,13 @@ static ListBase UIAfterFuncs = {NULL, NULL};
static uiAfterFunc *ui_afterfunc_new(void)
{
- uiAfterFunc *after;
+ uiAfterFunc *after;
- after = MEM_callocN(sizeof(uiAfterFunc), "uiAfterFunc");
+ after = MEM_callocN(sizeof(uiAfterFunc), "uiAfterFunc");
- BLI_addtail(&UIAfterFuncs, after);
+ BLI_addtail(&UIAfterFuncs, after);
- return after;
+ return after;
}
/**
@@ -602,26 +603,26 @@ static uiAfterFunc *ui_afterfunc_new(void)
*/
PointerRNA *ui_handle_afterfunc_add_operator(wmOperatorType *ot, int opcontext, bool create_props)
{
- PointerRNA *ptr = NULL;
- uiAfterFunc *after = ui_afterfunc_new();
+ PointerRNA *ptr = NULL;
+ uiAfterFunc *after = ui_afterfunc_new();
- after->optype = ot;
- after->opcontext = opcontext;
+ after->optype = ot;
+ after->opcontext = opcontext;
- if (create_props) {
- ptr = MEM_callocN(sizeof(PointerRNA), __func__);
- WM_operator_properties_create_ptr(ptr, ot);
- after->opptr = ptr;
- }
+ if (create_props) {
+ ptr = MEM_callocN(sizeof(PointerRNA), __func__);
+ WM_operator_properties_create_ptr(ptr, ot);
+ after->opptr = ptr;
+ }
- return ptr;
+ return ptr;
}
static void popup_check(bContext *C, wmOperator *op)
{
- if (op && op->type->check) {
- op->type->check(C, op);
- }
+ if (op && op->type->check) {
+ op->type->check(C, op);
+ }
}
/**
@@ -629,362 +630,362 @@ static void popup_check(bContext *C, wmOperator *op)
*/
static bool ui_afterfunc_check(const uiBlock *block, const uiBut *but)
{
- return (but->func || but->funcN || but->rename_func || but->optype || but->rnaprop || block->handle_func ||
- (but->type == UI_BTYPE_BUT_MENU && block->butm_func) ||
- (block->handle && block->handle->popup_op));
+ return (but->func || but->funcN || but->rename_func || but->optype || but->rnaprop ||
+ block->handle_func || (but->type == UI_BTYPE_BUT_MENU && block->butm_func) ||
+ (block->handle && block->handle->popup_op));
}
static void ui_apply_but_func(bContext *C, uiBut *but)
{
- uiAfterFunc *after;
- uiBlock *block = but->block;
+ uiAfterFunc *after;
+ uiBlock *block = but->block;
- /* these functions are postponed and only executed after all other
- * handling is done, i.e. menus are closed, in order to avoid conflicts
- * with these functions removing the buttons we are working with */
+ /* these functions are postponed and only executed after all other
+ * handling is done, i.e. menus are closed, in order to avoid conflicts
+ * with these functions removing the buttons we are working with */
- if (ui_afterfunc_check(block, but)) {
- after = ui_afterfunc_new();
+ if (ui_afterfunc_check(block, but)) {
+ after = ui_afterfunc_new();
- if (but->func && ELEM(but, but->func_arg1, but->func_arg2)) {
- /* exception, this will crash due to removed button otherwise */
- but->func(C, but->func_arg1, but->func_arg2);
- }
- else {
- after->func = but->func;
- }
+ if (but->func && ELEM(but, but->func_arg1, but->func_arg2)) {
+ /* exception, this will crash due to removed button otherwise */
+ but->func(C, but->func_arg1, but->func_arg2);
+ }
+ else {
+ after->func = but->func;
+ }
- after->func_arg1 = but->func_arg1;
- after->func_arg2 = but->func_arg2;
+ after->func_arg1 = but->func_arg1;
+ after->func_arg2 = but->func_arg2;
- after->funcN = but->funcN;
- after->func_argN = (but->func_argN) ? MEM_dupallocN(but->func_argN) : NULL;
+ after->funcN = but->funcN;
+ after->func_argN = (but->func_argN) ? MEM_dupallocN(but->func_argN) : NULL;
- after->rename_func = but->rename_func;
- after->rename_arg1 = but->rename_arg1;
- after->rename_orig = but->rename_orig; /* needs free! */
+ after->rename_func = but->rename_func;
+ after->rename_arg1 = but->rename_arg1;
+ after->rename_orig = but->rename_orig; /* needs free! */
- after->handle_func = block->handle_func;
- after->handle_func_arg = block->handle_func_arg;
- after->retval = but->retval;
+ after->handle_func = block->handle_func;
+ after->handle_func_arg = block->handle_func_arg;
+ after->retval = but->retval;
- if (but->type == UI_BTYPE_BUT_MENU) {
- after->butm_func = block->butm_func;
- after->butm_func_arg = block->butm_func_arg;
- after->a2 = but->a2;
- }
+ if (but->type == UI_BTYPE_BUT_MENU) {
+ after->butm_func = block->butm_func;
+ after->butm_func_arg = block->butm_func_arg;
+ after->a2 = but->a2;
+ }
- if (block->handle) {
- after->popup_op = block->handle->popup_op;
- }
+ if (block->handle) {
+ after->popup_op = block->handle->popup_op;
+ }
- after->optype = but->optype;
- after->opcontext = but->opcontext;
- after->opptr = but->opptr;
+ after->optype = but->optype;
+ after->opcontext = but->opcontext;
+ after->opptr = but->opptr;
- after->rnapoin = but->rnapoin;
- after->rnaprop = but->rnaprop;
+ after->rnapoin = but->rnapoin;
+ after->rnaprop = but->rnaprop;
- if (but->context) {
- after->context = CTX_store_copy(but->context);
- }
+ if (but->context) {
+ after->context = CTX_store_copy(but->context);
+ }
- but->optype = NULL;
- but->opcontext = 0;
- but->opptr = NULL;
- }
+ but->optype = NULL;
+ but->opcontext = 0;
+ but->opptr = NULL;
+ }
}
/* typically call ui_apply_but_undo(), ui_apply_but_autokey() */
static void ui_apply_but_undo(uiBut *but)
{
- uiAfterFunc *after;
+ uiAfterFunc *after;
- if (but->flag & UI_BUT_UNDO) {
- const char *str = NULL;
+ if (but->flag & UI_BUT_UNDO) {
+ const char *str = NULL;
- /* define which string to use for undo */
- if (but->type == UI_BTYPE_MENU) {
- str = but->drawstr;
- }
- else if (but->drawstr[0]) {
- str = but->drawstr;
- }
- else {
- str = but->tip;
- }
+ /* define which string to use for undo */
+ if (but->type == UI_BTYPE_MENU) {
+ str = but->drawstr;
+ }
+ else if (but->drawstr[0]) {
+ str = but->drawstr;
+ }
+ else {
+ str = but->tip;
+ }
- /* fallback, else we don't get an undo! */
- if (str == NULL || str[0] == '\0') {
- str = "Unknown Action";
- }
+ /* fallback, else we don't get an undo! */
+ if (str == NULL || str[0] == '\0') {
+ str = "Unknown Action";
+ }
- /* delayed, after all other funcs run, popups are closed, etc */
- after = ui_afterfunc_new();
- BLI_strncpy(after->undostr, str, sizeof(after->undostr));
- }
+ /* delayed, after all other funcs run, popups are closed, etc */
+ after = ui_afterfunc_new();
+ BLI_strncpy(after->undostr, str, sizeof(after->undostr));
+ }
}
static void ui_apply_but_autokey(bContext *C, uiBut *but)
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- /* try autokey */
- ui_but_anim_autokey(C, but, scene, scene->r.cfra);
+ /* try autokey */
+ ui_but_anim_autokey(C, but, scene, scene->r.cfra);
- /* make a little report about what we've done! */
- if (but->rnaprop) {
- char *buf;
+ /* make a little report about what we've done! */
+ if (but->rnaprop) {
+ char *buf;
- if (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD) {
- return;
- }
+ if (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD) {
+ return;
+ }
- buf = WM_prop_pystring_assign(C, &but->rnapoin, but->rnaprop, but->rnaindex);
- if (buf) {
- BKE_report(CTX_wm_reports(C), RPT_PROPERTY, buf);
- MEM_freeN(buf);
+ buf = WM_prop_pystring_assign(C, &but->rnapoin, but->rnaprop, but->rnaindex);
+ if (buf) {
+ BKE_report(CTX_wm_reports(C), RPT_PROPERTY, buf);
+ MEM_freeN(buf);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO_REPORT, NULL);
- }
- }
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO_REPORT, NULL);
+ }
+ }
}
static void ui_apply_but_funcs_after(bContext *C)
{
- uiAfterFunc *afterf, after;
- PointerRNA opptr;
- ListBase funcs;
-
- /* copy to avoid recursive calls */
- funcs = UIAfterFuncs;
- BLI_listbase_clear(&UIAfterFuncs);
-
- for (afterf = funcs.first; afterf; afterf = after.next) {
- after = *afterf; /* copy to avoid memleak on exit() */
- BLI_freelinkN(&funcs, afterf);
-
- if (after.context) {
- CTX_store_set(C, after.context);
- }
-
- if (after.popup_op) {
- popup_check(C, after.popup_op);
- }
-
- if (after.opptr) {
- /* free in advance to avoid leak on exit */
- opptr = *after.opptr;
- MEM_freeN(after.opptr);
- }
-
- if (after.optype) {
- WM_operator_name_call_ptr(C, after.optype, after.opcontext, (after.opptr) ? &opptr : NULL);
- }
-
- if (after.opptr) {
- WM_operator_properties_free(&opptr);
- }
-
- if (after.rnapoin.data) {
- RNA_property_update(C, &after.rnapoin, after.rnaprop);
- }
-
- if (after.context) {
- CTX_store_set(C, NULL);
- CTX_store_free(after.context);
- }
-
- if (after.func) {
- after.func(C, after.func_arg1, after.func_arg2);
- }
- if (after.funcN) {
- after.funcN(C, after.func_argN, after.func_arg2);
- }
- if (after.func_argN) {
- MEM_freeN(after.func_argN);
- }
-
- if (after.handle_func) {
- after.handle_func(C, after.handle_func_arg, after.retval);
- }
- if (after.butm_func) {
- after.butm_func(C, after.butm_func_arg, after.a2);
- }
-
- if (after.rename_func) {
- after.rename_func(C, after.rename_arg1, after.rename_orig);
- }
- if (after.rename_orig) {
- MEM_freeN(after.rename_orig);
- }
-
- if (after.undostr[0]) {
- ED_undo_push(C, after.undostr);
- }
- }
+ uiAfterFunc *afterf, after;
+ PointerRNA opptr;
+ ListBase funcs;
+
+ /* copy to avoid recursive calls */
+ funcs = UIAfterFuncs;
+ BLI_listbase_clear(&UIAfterFuncs);
+
+ for (afterf = funcs.first; afterf; afterf = after.next) {
+ after = *afterf; /* copy to avoid memleak on exit() */
+ BLI_freelinkN(&funcs, afterf);
+
+ if (after.context) {
+ CTX_store_set(C, after.context);
+ }
+
+ if (after.popup_op) {
+ popup_check(C, after.popup_op);
+ }
+
+ if (after.opptr) {
+ /* free in advance to avoid leak on exit */
+ opptr = *after.opptr;
+ MEM_freeN(after.opptr);
+ }
+
+ if (after.optype) {
+ WM_operator_name_call_ptr(C, after.optype, after.opcontext, (after.opptr) ? &opptr : NULL);
+ }
+
+ if (after.opptr) {
+ WM_operator_properties_free(&opptr);
+ }
+
+ if (after.rnapoin.data) {
+ RNA_property_update(C, &after.rnapoin, after.rnaprop);
+ }
+
+ if (after.context) {
+ CTX_store_set(C, NULL);
+ CTX_store_free(after.context);
+ }
+
+ if (after.func) {
+ after.func(C, after.func_arg1, after.func_arg2);
+ }
+ if (after.funcN) {
+ after.funcN(C, after.func_argN, after.func_arg2);
+ }
+ if (after.func_argN) {
+ MEM_freeN(after.func_argN);
+ }
+
+ if (after.handle_func) {
+ after.handle_func(C, after.handle_func_arg, after.retval);
+ }
+ if (after.butm_func) {
+ after.butm_func(C, after.butm_func_arg, after.a2);
+ }
+
+ if (after.rename_func) {
+ after.rename_func(C, after.rename_arg1, after.rename_orig);
+ }
+ if (after.rename_orig) {
+ MEM_freeN(after.rename_orig);
+ }
+
+ if (after.undostr[0]) {
+ ED_undo_push(C, after.undostr);
+ }
+ }
}
static void ui_apply_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- ui_apply_but_func(C, but);
+ ui_apply_but_func(C, but);
- data->retval = but->retval;
- data->applied = true;
+ data->retval = but->retval;
+ data->applied = true;
}
static void ui_apply_but_BUTM(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- ui_but_value_set(but, but->hardmin);
- ui_apply_but_func(C, but);
+ ui_but_value_set(but, but->hardmin);
+ ui_apply_but_func(C, but);
- data->retval = but->retval;
- data->applied = true;
+ data->retval = but->retval;
+ data->applied = true;
}
static void ui_apply_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- if (but->type == UI_BTYPE_MENU) {
- ui_but_value_set(but, data->value);
- }
+ if (but->type == UI_BTYPE_MENU) {
+ ui_but_value_set(but, data->value);
+ }
- ui_but_update_edited(but);
- ui_apply_but_func(C, but);
- data->retval = but->retval;
- data->applied = true;
+ ui_but_update_edited(but);
+ ui_apply_but_func(C, but);
+ data->retval = but->retval;
+ data->applied = true;
}
static void ui_apply_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- const double value = ui_but_value_get(but);
- int value_toggle;
- if (but->bit) {
- value_toggle = UI_BITBUT_VALUE_TOGGLED((int)value, but->bitnr);
- }
- else {
- value_toggle = (value == 0.0);
- if (ELEM(but->type, UI_BTYPE_TOGGLE_N, UI_BTYPE_ICON_TOGGLE_N, UI_BTYPE_CHECKBOX_N)) {
- value_toggle = !value_toggle;
- }
- }
+ const double value = ui_but_value_get(but);
+ int value_toggle;
+ if (but->bit) {
+ value_toggle = UI_BITBUT_VALUE_TOGGLED((int)value, but->bitnr);
+ }
+ else {
+ value_toggle = (value == 0.0);
+ if (ELEM(but->type, UI_BTYPE_TOGGLE_N, UI_BTYPE_ICON_TOGGLE_N, UI_BTYPE_CHECKBOX_N)) {
+ value_toggle = !value_toggle;
+ }
+ }
- ui_but_value_set(but, (double)value_toggle);
- if (but->type == UI_BTYPE_ICON_TOGGLE || but->type == UI_BTYPE_ICON_TOGGLE_N) {
- ui_but_update_edited(but);
- }
+ ui_but_value_set(but, (double)value_toggle);
+ if (but->type == UI_BTYPE_ICON_TOGGLE || but->type == UI_BTYPE_ICON_TOGGLE_N) {
+ ui_but_update_edited(but);
+ }
- ui_apply_but_func(C, but);
+ ui_apply_but_func(C, but);
- data->retval = but->retval;
- data->applied = true;
+ data->retval = but->retval;
+ data->applied = true;
}
static void ui_apply_but_ROW(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data)
{
- uiBut *bt;
+ uiBut *bt;
- ui_but_value_set(but, but->hardmax);
+ ui_but_value_set(but, but->hardmax);
- ui_apply_but_func(C, but);
+ ui_apply_but_func(C, but);
- /* states of other row buttons */
- for (bt = block->buttons.first; bt; bt = bt->next) {
- if (bt != but && bt->poin == but->poin && ELEM(bt->type, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) {
- ui_but_update_edited(bt);
- }
- }
+ /* states of other row buttons */
+ for (bt = block->buttons.first; bt; bt = bt->next) {
+ if (bt != but && bt->poin == but->poin && ELEM(bt->type, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) {
+ ui_but_update_edited(bt);
+ }
+ }
- data->retval = but->retval;
- data->applied = true;
+ data->retval = but->retval;
+ data->applied = true;
}
static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- if (!data->str) {
- return;
- }
+ if (!data->str) {
+ return;
+ }
- ui_but_string_set(C, but, data->str);
- ui_but_update_edited(but);
+ ui_but_string_set(C, but, data->str);
+ ui_but_update_edited(but);
- /* give butfunc a copy of the original text too.
- * feature used for bone renaming, channels, etc.
- * afterfunc frees rename_orig */
- if (data->origstr && (but->flag & UI_BUT_TEXTEDIT_UPDATE)) {
- /* In this case, we need to keep origstr available, to restore real org string in case we cancel after
- * having typed something already. */
- but->rename_orig = BLI_strdup(data->origstr);
- }
- /* only if there are afterfuncs, otherwise 'renam_orig' isn't freed */
- else if (ui_afterfunc_check(but->block, but)) {
- but->rename_orig = data->origstr;
- data->origstr = NULL;
- }
- ui_apply_but_func(C, but);
+ /* give butfunc a copy of the original text too.
+ * feature used for bone renaming, channels, etc.
+ * afterfunc frees rename_orig */
+ if (data->origstr && (but->flag & UI_BUT_TEXTEDIT_UPDATE)) {
+ /* In this case, we need to keep origstr available, to restore real org string in case we cancel after
+ * having typed something already. */
+ but->rename_orig = BLI_strdup(data->origstr);
+ }
+ /* only if there are afterfuncs, otherwise 'renam_orig' isn't freed */
+ else if (ui_afterfunc_check(but->block, but)) {
+ but->rename_orig = data->origstr;
+ data->origstr = NULL;
+ }
+ ui_apply_but_func(C, but);
- data->retval = but->retval;
- data->applied = true;
+ data->retval = but->retval;
+ data->applied = true;
}
static void ui_apply_but_TAB(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- if (data->str) {
- ui_but_string_set(C, but, data->str);
- ui_but_update_edited(but);
- }
- else {
- ui_but_value_set(but, but->hardmax);
- ui_apply_but_func(C, but);
- }
+ if (data->str) {
+ ui_but_string_set(C, but, data->str);
+ ui_but_update_edited(but);
+ }
+ else {
+ ui_but_value_set(but, but->hardmax);
+ ui_apply_but_func(C, but);
+ }
- data->retval = but->retval;
- data->applied = true;
+ data->retval = but->retval;
+ data->applied = true;
}
static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- if (data->str) {
- if (ui_but_string_set(C, but, data->str)) {
- data->value = ui_but_value_get(but);
- }
- else {
- data->cancel = true;
- return;
- }
- }
- else {
- ui_but_value_set(but, data->value);
- }
+ if (data->str) {
+ if (ui_but_string_set(C, but, data->str)) {
+ data->value = ui_but_value_get(but);
+ }
+ else {
+ data->cancel = true;
+ return;
+ }
+ }
+ else {
+ ui_but_value_set(but, data->value);
+ }
- ui_but_update_edited(but);
- ui_apply_but_func(C, but);
+ ui_but_update_edited(but);
+ ui_apply_but_func(C, but);
- data->retval = but->retval;
- data->applied = true;
+ data->retval = but->retval;
+ data->applied = true;
}
static void ui_apply_but_VEC(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- ui_but_v3_set(but, data->vec);
- ui_but_update_edited(but);
- ui_apply_but_func(C, but);
+ ui_but_v3_set(but, data->vec);
+ ui_but_update_edited(but);
+ ui_apply_but_func(C, but);
- data->retval = but->retval;
- data->applied = true;
+ data->retval = but->retval;
+ data->applied = true;
}
static void ui_apply_but_COLORBAND(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- ui_apply_but_func(C, but);
- data->retval = but->retval;
- data->applied = true;
+ ui_apply_but_func(C, but);
+ data->retval = but->retval;
+ data->applied = true;
}
static void ui_apply_but_CURVE(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- ui_apply_but_func(C, but);
- data->retval = but->retval;
- data->applied = true;
+ ui_apply_but_func(C, but);
+ data->retval = but->retval;
+ data->applied = true;
}
/** \} */
@@ -998,245 +999,240 @@ static void ui_apply_but_CURVE(bContext *C, uiBut *but, uiHandleButtonData *data
/* small multi-but api */
static void ui_multibut_add(uiHandleButtonData *data, uiBut *but)
{
- uiButMultiState *mbut_state;
+ uiButMultiState *mbut_state;
- BLI_assert(but->flag & UI_BUT_DRAG_MULTI);
- BLI_assert(data->multi_data.has_mbuts);
+ BLI_assert(but->flag & UI_BUT_DRAG_MULTI);
+ BLI_assert(data->multi_data.has_mbuts);
+ mbut_state = MEM_callocN(sizeof(*mbut_state), __func__);
+ mbut_state->but = but;
+ mbut_state->origvalue = ui_but_value_get(but);
- mbut_state = MEM_callocN(sizeof(*mbut_state), __func__);
- mbut_state->but = but;
- mbut_state->origvalue = ui_but_value_get(but);
+ BLI_linklist_prepend(&data->multi_data.mbuts, mbut_state);
- BLI_linklist_prepend(&data->multi_data.mbuts, mbut_state);
-
- UI_butstore_register(data->multi_data.bs_mbuts, &mbut_state->but);
+ UI_butstore_register(data->multi_data.bs_mbuts, &mbut_state->but);
}
static uiButMultiState *ui_multibut_lookup(uiHandleButtonData *data, const uiBut *but)
{
- LinkNode *l;
+ LinkNode *l;
- for (l = data->multi_data.mbuts; l; l = l->next) {
- uiButMultiState *mbut_state;
+ for (l = data->multi_data.mbuts; l; l = l->next) {
+ uiButMultiState *mbut_state;
- mbut_state = l->link;
+ mbut_state = l->link;
- if (mbut_state->but == but) {
- return mbut_state;
- }
- }
+ if (mbut_state->but == but) {
+ return mbut_state;
+ }
+ }
- return NULL;
+ return NULL;
}
static void ui_multibut_restore(bContext *C, uiHandleButtonData *data, uiBlock *block)
{
- uiBut *but;
-
- for (but = block->buttons.first; but; but = but->next) {
- if (but->flag & UI_BUT_DRAG_MULTI) {
- uiButMultiState *mbut_state = ui_multibut_lookup(data, but);
- if (mbut_state) {
- ui_but_value_set(but, mbut_state->origvalue);
-
-#ifdef USE_ALLSELECT
- if (mbut_state->select_others.elems_len > 0) {
- ui_selectcontext_apply(
- C, but, &mbut_state->select_others,
- mbut_state->origvalue, mbut_state->origvalue);
- }
-#else
- UNUSED_VARS(C);
-#endif
- }
- }
- }
+ uiBut *but;
+
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->flag & UI_BUT_DRAG_MULTI) {
+ uiButMultiState *mbut_state = ui_multibut_lookup(data, but);
+ if (mbut_state) {
+ ui_but_value_set(but, mbut_state->origvalue);
+
+# ifdef USE_ALLSELECT
+ if (mbut_state->select_others.elems_len > 0) {
+ ui_selectcontext_apply(
+ C, but, &mbut_state->select_others, mbut_state->origvalue, mbut_state->origvalue);
+ }
+# else
+ UNUSED_VARS(C);
+# endif
+ }
+ }
+ }
}
static void ui_multibut_free(uiHandleButtonData *data, uiBlock *block)
{
-#ifdef USE_ALLSELECT
- if (data->multi_data.mbuts) {
- LinkNode *list = data->multi_data.mbuts;
- while (list) {
- LinkNode *next = list->next;
- uiButMultiState *mbut_state = list->link;
-
- if (mbut_state->select_others.elems) {
- MEM_freeN(mbut_state->select_others.elems);
- }
-
- MEM_freeN(list->link);
- MEM_freeN(list);
- list = next;
- }
- }
-#else
- BLI_linklist_freeN(data->multi_data.mbuts);
-#endif
+# ifdef USE_ALLSELECT
+ if (data->multi_data.mbuts) {
+ LinkNode *list = data->multi_data.mbuts;
+ while (list) {
+ LinkNode *next = list->next;
+ uiButMultiState *mbut_state = list->link;
+
+ if (mbut_state->select_others.elems) {
+ MEM_freeN(mbut_state->select_others.elems);
+ }
+
+ MEM_freeN(list->link);
+ MEM_freeN(list);
+ list = next;
+ }
+ }
+# else
+ BLI_linklist_freeN(data->multi_data.mbuts);
+# endif
- data->multi_data.mbuts = NULL;
+ data->multi_data.mbuts = NULL;
- if (data->multi_data.bs_mbuts) {
- UI_butstore_free(block, data->multi_data.bs_mbuts);
- data->multi_data.bs_mbuts = NULL;
- }
+ if (data->multi_data.bs_mbuts) {
+ UI_butstore_free(block, data->multi_data.bs_mbuts);
+ data->multi_data.bs_mbuts = NULL;
+ }
}
-static bool ui_multibut_states_tag(
- uiBut *but_active,
- uiHandleButtonData *data, const wmEvent *event)
+static bool ui_multibut_states_tag(uiBut *but_active,
+ uiHandleButtonData *data,
+ const wmEvent *event)
{
- uiBut *but;
- float seg[2][2];
- bool changed = false;
+ uiBut *but;
+ float seg[2][2];
+ bool changed = false;
- seg[0][0] = data->multi_data.drag_start[0];
- seg[0][1] = data->multi_data.drag_start[1];
+ seg[0][0] = data->multi_data.drag_start[0];
+ seg[0][1] = data->multi_data.drag_start[1];
- seg[1][0] = event->x;
- seg[1][1] = event->y;
+ seg[1][0] = event->x;
+ seg[1][1] = event->y;
- BLI_assert(data->multi_data.init == BUTTON_MULTI_INIT_SETUP);
+ BLI_assert(data->multi_data.init == BUTTON_MULTI_INIT_SETUP);
- ui_window_to_block_fl(data->region, but_active->block, &seg[0][0], &seg[0][1]);
- ui_window_to_block_fl(data->region, but_active->block, &seg[1][0], &seg[1][1]);
+ ui_window_to_block_fl(data->region, but_active->block, &seg[0][0], &seg[0][1]);
+ ui_window_to_block_fl(data->region, but_active->block, &seg[1][0], &seg[1][1]);
- data->multi_data.has_mbuts = false;
+ data->multi_data.has_mbuts = false;
- /* follow ui_but_find_mouse_over_ex logic */
- for (but = but_active->block->buttons.first; but; but = but->next) {
- bool drag_prev = false;
- bool drag_curr = false;
+ /* follow ui_but_find_mouse_over_ex logic */
+ for (but = but_active->block->buttons.first; but; but = but->next) {
+ bool drag_prev = false;
+ bool drag_curr = false;
- /* re-set each time */
- if (but->flag & UI_BUT_DRAG_MULTI) {
- but->flag &= ~UI_BUT_DRAG_MULTI;
- drag_prev = true;
- }
+ /* re-set each time */
+ if (but->flag & UI_BUT_DRAG_MULTI) {
+ but->flag &= ~UI_BUT_DRAG_MULTI;
+ drag_prev = true;
+ }
- if (ui_but_is_interactive(but, false)) {
+ if (ui_but_is_interactive(but, false)) {
- /* drag checks */
- if (but_active != but) {
- if (ui_but_is_compatible(but_active, but)) {
+ /* drag checks */
+ if (but_active != but) {
+ if (ui_but_is_compatible(but_active, but)) {
- BLI_assert(but->active == NULL);
+ BLI_assert(but->active == NULL);
- /* finally check for overlap */
- if (BLI_rctf_isect_segment(&but->rect, seg[0], seg[1])) {
+ /* finally check for overlap */
+ if (BLI_rctf_isect_segment(&but->rect, seg[0], seg[1])) {
- but->flag |= UI_BUT_DRAG_MULTI;
- data->multi_data.has_mbuts = true;
- drag_curr = true;
- }
- }
- }
- }
+ but->flag |= UI_BUT_DRAG_MULTI;
+ data->multi_data.has_mbuts = true;
+ drag_curr = true;
+ }
+ }
+ }
+ }
- changed |= (drag_prev != drag_curr);
- }
+ changed |= (drag_prev != drag_curr);
+ }
- return changed;
+ return changed;
}
static void ui_multibut_states_create(uiBut *but_active, uiHandleButtonData *data)
{
- BLI_assert(data->multi_data.init == BUTTON_MULTI_INIT_SETUP);
- BLI_assert(data->multi_data.has_mbuts);
-
- data->multi_data.bs_mbuts = UI_butstore_create(but_active->block);
+ BLI_assert(data->multi_data.init == BUTTON_MULTI_INIT_SETUP);
+ BLI_assert(data->multi_data.has_mbuts);
- for (uiBut *but = but_active->block->buttons.first; but; but = but->next) {
- if (but->flag & UI_BUT_DRAG_MULTI) {
- ui_multibut_add(data, but);
- }
- }
+ data->multi_data.bs_mbuts = UI_butstore_create(but_active->block);
- /* edit buttons proportionally to eachother
- * 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))
- {
- if (data->origvalue != 0.0) {
- data->multi_data.is_proportional = true;
- }
- }
+ for (uiBut *but = but_active->block->buttons.first; but; but = but->next) {
+ if (but->flag & UI_BUT_DRAG_MULTI) {
+ ui_multibut_add(data, but);
+ }
+ }
+ /* edit buttons proportionally to eachother
+ * 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)) {
+ if (data->origvalue != 0.0) {
+ data->multi_data.is_proportional = true;
+ }
+ }
}
static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBlock *block)
{
- ARegion *ar = 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;
- uiBut *but;
-
- BLI_assert(data->multi_data.init == BUTTON_MULTI_INIT_ENABLE);
- BLI_assert(data->multi_data.skip == false);
-
- for (but = block->buttons.first; but; but = but->next) {
- if (but->flag & UI_BUT_DRAG_MULTI) {
- /* mbut_states for delta */
- uiButMultiState *mbut_state = ui_multibut_lookup(data, but);
-
- if (mbut_state) {
- void *active_back;
-
- ui_but_execute_begin(C, ar, but, &active_back);
-
-#ifdef USE_ALLSELECT
- if (data->select_others.is_enabled) {
- /* init once! */
- if (mbut_state->select_others.elems_len == 0) {
- ui_selectcontext_begin(C, but, &mbut_state->select_others);
- }
- if (mbut_state->select_others.elems_len == 0) {
- mbut_state->select_others.elems_len = -1;
- }
- }
-
- /* needed so we apply the right deltas */
- but->active->origvalue = mbut_state->origvalue;
- but->active->select_others = mbut_state->select_others;
- but->active->select_others.do_free = false;
-#endif
-
- BLI_assert(active_back == NULL);
- /* no need to check 'data->state' here */
- if (data->str) {
- /* entering text (set all) */
- but->active->value = data->value;
- ui_but_string_set(C, but, data->str);
- }
- else {
- /* dragging (use delta) */
- if (data->multi_data.is_proportional) {
- but->active->value = mbut_state->origvalue * value_scale;
- }
- else {
- but->active->value = mbut_state->origvalue + value_delta;
- }
-
- /* 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);
- }
- else {
- /* highly unlikely */
- printf("%s: cant find button\n", __func__);
- }
- /* end */
-
- }
- }
-}
-
-#endif /* USE_DRAG_MULTINUM */
+ ARegion *ar = 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;
+ uiBut *but;
+
+ BLI_assert(data->multi_data.init == BUTTON_MULTI_INIT_ENABLE);
+ BLI_assert(data->multi_data.skip == false);
+
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->flag & UI_BUT_DRAG_MULTI) {
+ /* mbut_states for delta */
+ uiButMultiState *mbut_state = ui_multibut_lookup(data, but);
+
+ if (mbut_state) {
+ void *active_back;
+
+ ui_but_execute_begin(C, ar, but, &active_back);
+
+# ifdef USE_ALLSELECT
+ if (data->select_others.is_enabled) {
+ /* init once! */
+ if (mbut_state->select_others.elems_len == 0) {
+ ui_selectcontext_begin(C, but, &mbut_state->select_others);
+ }
+ if (mbut_state->select_others.elems_len == 0) {
+ mbut_state->select_others.elems_len = -1;
+ }
+ }
+
+ /* needed so we apply the right deltas */
+ but->active->origvalue = mbut_state->origvalue;
+ but->active->select_others = mbut_state->select_others;
+ but->active->select_others.do_free = false;
+# endif
+ BLI_assert(active_back == NULL);
+ /* no need to check 'data->state' here */
+ if (data->str) {
+ /* entering text (set all) */
+ but->active->value = data->value;
+ ui_but_string_set(C, but, data->str);
+ }
+ else {
+ /* dragging (use delta) */
+ if (data->multi_data.is_proportional) {
+ but->active->value = mbut_state->origvalue * value_scale;
+ }
+ else {
+ but->active->value = mbut_state->origvalue + value_delta;
+ }
+
+ /* 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);
+ }
+ else {
+ /* highly unlikely */
+ printf("%s: cant find button\n", __func__);
+ }
+ /* end */
+ }
+ }
+}
+
+#endif /* USE_DRAG_MULTINUM */
/** \} */
@@ -1250,488 +1246,478 @@ static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBl
static bool ui_drag_toggle_but_is_supported(const uiBut *but)
{
- if (ui_but_is_bool(but)) {
- return true;
- }
- else if (UI_but_is_decorator(but)) {
- return ELEM(but->icon, ICON_DECORATE, ICON_DECORATE_KEYFRAME, ICON_DECORATE_ANIMATE, ICON_DECORATE_OVERRIDE);
- }
- else {
- return false;
- }
+ if (ui_but_is_bool(but)) {
+ return true;
+ }
+ else if (UI_but_is_decorator(but)) {
+ return ELEM(but->icon,
+ ICON_DECORATE,
+ ICON_DECORATE_KEYFRAME,
+ ICON_DECORATE_ANIMATE,
+ ICON_DECORATE_OVERRIDE);
+ }
+ else {
+ return false;
+ }
}
/* Button pushed state to compare if other buttons match. Can be more
* then just true or false for toggle buttons with more than 2 states. */
static int ui_drag_toggle_but_pushed_state(bContext *C, uiBut *but)
{
- if (but->rnapoin.data == NULL && but->poin == NULL && but->icon) {
- if (but->pushed_state_func) {
- return but->pushed_state_func(C, but->pushed_state_arg);
- }
- else {
- /* Assume icon identifies a unique state, for buttons that
- * work though functions callbacks and don't have an boolean
- * value that indicates the state. */
- return but->icon + but->iconadd;
- }
- }
- else if (ui_but_is_bool(but)) {
- return ui_but_is_pushed(but);
- }
- else {
- return 0;
- }
+ if (but->rnapoin.data == NULL && but->poin == NULL && but->icon) {
+ if (but->pushed_state_func) {
+ return but->pushed_state_func(C, but->pushed_state_arg);
+ }
+ else {
+ /* Assume icon identifies a unique state, for buttons that
+ * work though functions callbacks and don't have an boolean
+ * value that indicates the state. */
+ return but->icon + but->iconadd;
+ }
+ }
+ else if (ui_but_is_bool(but)) {
+ return ui_but_is_pushed(but);
+ }
+ else {
+ return 0;
+ }
}
typedef struct uiDragToggleHandle {
- /* init */
- int pushed_state;
- float but_cent_start[2];
+ /* init */
+ int pushed_state;
+ float but_cent_start[2];
- bool is_xy_lock_init;
- bool xy_lock[2];
+ bool is_xy_lock_init;
+ bool xy_lock[2];
- int xy_init[2];
- int xy_last[2];
+ int xy_init[2];
+ int xy_last[2];
} 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])
-{
- /* popups such as layers won't re-evaluate on redraw */
- const bool do_check = (ar->regiontype == RGN_TYPE_TEMPORARY);
- bool changed = false;
- uiBlock *block;
-
- for (block = ar->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]);
-
- for (but = block->buttons.first; but; but = but->next) {
- /* Note: ctrl is always true here because (at least for now) we always want to consider text control
- * in this case, even when not embossed. */
- if (ui_but_is_interactive(but, true)) {
- if (BLI_rctf_isect_segment(&but->rect, xy_a_block, xy_b_block)) {
-
- /* execute the button */
- if (ui_drag_toggle_but_is_supported(but)) {
- /* is it pressed? */
- int pushed_state_but = ui_drag_toggle_but_pushed_state(C, but);
- if (pushed_state_but != pushed_state) {
- UI_but_execute(C, but);
- if (do_check) {
- ui_but_update_edited(but);
- }
- changed = true;
- }
- }
- /* done */
-
- }
- }
- }
- }
- if (changed) {
- /* apply now, not on release (or if handlers are canceled for whatever reason) */
- ui_apply_but_funcs_after(C);
- }
-
- return changed;
+ bContext *C, ARegion *ar, 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);
+ bool changed = false;
+ uiBlock *block;
+
+ for (block = ar->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]);
+
+ for (but = block->buttons.first; but; but = but->next) {
+ /* Note: ctrl is always true here because (at least for now) we always want to consider text control
+ * in this case, even when not embossed. */
+ if (ui_but_is_interactive(but, true)) {
+ if (BLI_rctf_isect_segment(&but->rect, xy_a_block, xy_b_block)) {
+
+ /* execute the button */
+ if (ui_drag_toggle_but_is_supported(but)) {
+ /* is it pressed? */
+ int pushed_state_but = ui_drag_toggle_but_pushed_state(C, but);
+ if (pushed_state_but != pushed_state) {
+ UI_but_execute(C, but);
+ if (do_check) {
+ ui_but_update_edited(but);
+ }
+ changed = true;
+ }
+ }
+ /* done */
+ }
+ }
+ }
+ }
+ if (changed) {
+ /* apply now, not on release (or if handlers are canceled for whatever reason) */
+ ui_apply_but_funcs_after(C);
+ }
+
+ return changed;
}
static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const int xy_input[2])
{
- ARegion *ar = CTX_wm_region(C);
- bool do_draw = false;
- int xy[2];
-
- /**
- * Initialize Locking:
- *
- * Check if we need to initialize the lock axis by finding if the first
- * button we mouse over is X or Y aligned, then lock the mouse to that axis after.
- */
- 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);
-
- if (but) {
- if (but->flag & UI_BUT_DRAG_LOCK) {
- const float but_cent_new[2] = {
- BLI_rctf_cent_x(&but->rect),
- BLI_rctf_cent_y(&but->rect),
- };
-
- /* check if this is a different button,
- * chances are high the button wont move about :) */
- if (len_manhattan_v2v2(drag_info->but_cent_start, but_cent_new) > 1.0f) {
- if (fabsf(drag_info->but_cent_start[0] - but_cent_new[0]) <
- fabsf(drag_info->but_cent_start[1] - but_cent_new[1]))
- {
- drag_info->xy_lock[0] = true;
- }
- else {
- drag_info->xy_lock[1] = true;
- }
- drag_info->is_xy_lock_init = true;
- }
- }
- else {
- drag_info->is_xy_lock_init = true;
- }
- }
- }
- /* done with axis locking */
-
-
- xy[0] = (drag_info->xy_lock[0] == false) ? xy_input[0] : drag_info->xy_last[0];
- 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);
-
- if (do_draw) {
- ED_region_tag_redraw(ar);
- }
-
- copy_v2_v2_int(drag_info->xy_last, xy);
+ ARegion *ar = CTX_wm_region(C);
+ bool do_draw = false;
+ int xy[2];
+
+ /**
+ * Initialize Locking:
+ *
+ * Check if we need to initialize the lock axis by finding if the first
+ * button we mouse over is X or Y aligned, then lock the mouse to that axis after.
+ */
+ 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);
+
+ if (but) {
+ if (but->flag & UI_BUT_DRAG_LOCK) {
+ const float but_cent_new[2] = {
+ BLI_rctf_cent_x(&but->rect),
+ BLI_rctf_cent_y(&but->rect),
+ };
+
+ /* check if this is a different button,
+ * chances are high the button wont move about :) */
+ if (len_manhattan_v2v2(drag_info->but_cent_start, but_cent_new) > 1.0f) {
+ if (fabsf(drag_info->but_cent_start[0] - but_cent_new[0]) <
+ fabsf(drag_info->but_cent_start[1] - but_cent_new[1])) {
+ drag_info->xy_lock[0] = true;
+ }
+ else {
+ drag_info->xy_lock[1] = true;
+ }
+ drag_info->is_xy_lock_init = true;
+ }
+ }
+ else {
+ drag_info->is_xy_lock_init = true;
+ }
+ }
+ }
+ /* done with axis locking */
+
+ xy[0] = (drag_info->xy_lock[0] == false) ? xy_input[0] : drag_info->xy_last[0];
+ 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);
+
+ if (do_draw) {
+ ED_region_tag_redraw(ar);
+ }
+
+ copy_v2_v2_int(drag_info->xy_last, xy);
}
static void ui_handler_region_drag_toggle_remove(bContext *UNUSED(C), void *userdata)
{
- uiDragToggleHandle *drag_info = userdata;
- MEM_freeN(drag_info);
+ uiDragToggleHandle *drag_info = userdata;
+ MEM_freeN(drag_info);
}
static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void *userdata)
{
- uiDragToggleHandle *drag_info = userdata;
- bool done = false;
-
- switch (event->type) {
- case LEFTMOUSE:
- {
- if (event->val == KM_RELEASE) {
- done = true;
- }
- break;
- }
- case MOUSEMOVE:
- {
- ui_drag_toggle_set(C, drag_info, &event->x);
- break;
- }
- }
-
- 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);
-
- if (but) {
- ui_apply_but_undo(but);
- }
-
- WM_event_remove_ui_handler(
- &win->modalhandlers,
- ui_handler_region_drag_toggle,
- ui_handler_region_drag_toggle_remove,
- drag_info, false);
- ui_handler_region_drag_toggle_remove(C, drag_info);
-
- WM_event_add_mousemove(C);
- return WM_UI_HANDLER_BREAK;
- }
- else {
- return WM_UI_HANDLER_CONTINUE;
- }
+ uiDragToggleHandle *drag_info = userdata;
+ bool done = false;
+
+ switch (event->type) {
+ case LEFTMOUSE: {
+ if (event->val == KM_RELEASE) {
+ done = true;
+ }
+ break;
+ }
+ case MOUSEMOVE: {
+ ui_drag_toggle_set(C, drag_info, &event->x);
+ break;
+ }
+ }
+
+ 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);
+
+ if (but) {
+ ui_apply_but_undo(but);
+ }
+
+ WM_event_remove_ui_handler(&win->modalhandlers,
+ ui_handler_region_drag_toggle,
+ ui_handler_region_drag_toggle_remove,
+ drag_info,
+ false);
+ ui_handler_region_drag_toggle_remove(C, drag_info);
+
+ WM_event_add_mousemove(C);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else {
+ return WM_UI_HANDLER_CONTINUE;
+ }
}
static bool ui_but_is_drag_toggle(const uiBut *but)
{
- return ((ui_drag_toggle_but_is_supported(but) == true) &&
- /* menu check is importnt so the button dragged over isn't removed instantly */
- (ui_block_is_menu(but->block) == false));
+ return ((ui_drag_toggle_but_is_supported(but) == true) &&
+ /* menu check is importnt so the button dragged over isn't removed instantly */
+ (ui_block_is_menu(but->block) == false));
}
-#endif /* USE_DRAG_TOGGLE */
-
+#endif /* USE_DRAG_TOGGLE */
#ifdef USE_ALLSELECT
-static bool ui_selectcontext_begin(
- bContext *C, uiBut *but, uiSelectContextStore *selctx_data)
-{
- PointerRNA ptr, lptr, idptr;
- PropertyRNA *prop, *lprop;
- bool success = false;
- int index;
-
- char *path = NULL;
- ListBase lb = {NULL};
-
- ptr = but->rnapoin;
- prop = but->rnaprop;
- index = but->rnaindex;
-
- /* for now don't support whole colors */
- if (index == -1) {
- return false;
- }
-
- /* if there is a valid property that is editable... */
- if (ptr.data && prop) {
- CollectionPointerLink *link;
- bool use_path_from_id;
- int i;
-
- /* some facts we want to know */
- const bool is_array = RNA_property_array_check(prop);
- const int rna_type = RNA_property_type(prop);
-
- if (UI_context_copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path) &&
- !BLI_listbase_is_empty(&lb))
- {
- selctx_data->elems_len = BLI_listbase_count(&lb);
- selctx_data->elems = MEM_mallocN(sizeof(uiSelectContextElem) * selctx_data->elems_len, __func__);
-
- for (i = 0, link = lb.first; i < selctx_data->elems_len; i++, link = link->next) {
- uiSelectContextElem *other = &selctx_data->elems[i];
- /* TODO,. de-duplicate copy_to_selected_button */
- if (link->ptr.data != ptr.data) {
- if (use_path_from_id) {
- /* Path relative to ID. */
- lprop = NULL;
- RNA_id_pointer_create(link->ptr.id.data, &idptr);
- RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
- }
- else if (path) {
- /* Path relative to elements from list. */
- lprop = NULL;
- RNA_path_resolve_property(&link->ptr, path, &lptr, &lprop);
- }
- else {
- lptr = link->ptr;
- lprop = prop;
- }
-
- /* lptr might not be the same as link->ptr! */
- if ((lptr.data != ptr.data) &&
- (lprop == prop) &&
- RNA_property_editable(&lptr, lprop))
- {
- other->ptr = lptr;
- if (is_array) {
- if (rna_type == PROP_FLOAT) {
- other->val_f = RNA_property_float_get_index(&lptr, lprop, index);
- }
- else if (rna_type == PROP_INT) {
- other->val_i = RNA_property_int_get_index(&lptr, lprop, index);
- }
- /* ignored for now */
-#if 0
- else if (rna_type == PROP_BOOLEAN) {
- other->val_b = RNA_property_boolean_get_index(&lptr, lprop, index);
- }
-#endif
- }
- else {
- if (rna_type == PROP_FLOAT) {
- other->val_f = RNA_property_float_get(&lptr, lprop);
- }
- else if (rna_type == PROP_INT) {
- other->val_i = RNA_property_int_get(&lptr, lprop);
- }
- /* ignored for now */
-#if 0
- else if (rna_type == PROP_BOOLEAN) {
- other->val_b = RNA_property_boolean_get(&lptr, lprop);
- }
- else if (rna_type == PROP_ENUM) {
- other->val_i = RNA_property_enum_get(&lptr, lprop);
- }
-#endif
- }
-
- continue;
- }
- }
-
- selctx_data->elems_len -= 1;
- i -= 1;
- }
-
- success = (selctx_data->elems_len != 0);
- }
- }
-
- if (selctx_data->elems_len == 0) {
- MEM_SAFE_FREE(selctx_data->elems);
- }
-
- MEM_SAFE_FREE(path);
- BLI_freelistN(&lb);
-
- /* caller can clear */
- selctx_data->do_free = true;
-
- if (success) {
- but->flag |= UI_BUT_IS_SELECT_CONTEXT;
- }
-
- return success;
-}
-
-static void ui_selectcontext_end(
- uiBut *but, uiSelectContextStore *selctx_data)
-{
- if (selctx_data->do_free) {
- if (selctx_data->elems) {
- MEM_freeN(selctx_data->elems);
- }
- }
-
- but->flag &= ~UI_BUT_IS_SELECT_CONTEXT;
-}
-
-static void ui_selectcontext_apply(
- bContext *C, uiBut *but, uiSelectContextStore *selctx_data,
- const double value, const double value_orig)
-{
- if (selctx_data->elems) {
- PropertyRNA *prop = but->rnaprop;
- PropertyRNA *lprop = but->rnaprop;
- int index = but->rnaindex;
- int i;
- const bool use_delta = (selctx_data->is_copy == false);
-
- union {
- bool b;
- int i;
- float f;
- PointerRNA p;
- } delta, min, max;
-
- const bool is_array = RNA_property_array_check(prop);
- const int rna_type = RNA_property_type(prop);
-
- if (rna_type == PROP_FLOAT) {
- delta.f = use_delta ? (value - value_orig) : value;
- RNA_property_float_range(&but->rnapoin, prop, &min.f, &max.f);
- }
- else if (rna_type == PROP_INT) {
- delta.i = use_delta ? ((int)value - (int)value_orig) : (int)value;
- RNA_property_int_range(&but->rnapoin, prop, &min.i, &max.i);
- }
- else if (rna_type == PROP_ENUM) {
- /* not a delta infact */
- delta.i = RNA_property_enum_get(&but->rnapoin, prop);
- }
- else if (rna_type == PROP_BOOLEAN) {
- if (is_array) {
- /* not a delta infact */
- delta.b = RNA_property_boolean_get_index(&but->rnapoin, prop, index);
- }
- else {
- /* not a delta infact */
- delta.b = RNA_property_boolean_get(&but->rnapoin, prop);
- }
- }
- else if (rna_type == PROP_POINTER) {
- /* not a delta infact */
- delta.p = RNA_property_pointer_get(&but->rnapoin, prop);
- }
-
-#ifdef USE_ALLSELECT_LAYER_HACK
- /* make up for not having 'handle_layer_buttons' */
- {
- PropertySubType subtype = RNA_property_subtype(prop);
-
- if ((rna_type == PROP_BOOLEAN) &&
- ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER) &&
- is_array &&
- /* could check for 'handle_layer_buttons' */
- but->func)
- {
- wmWindow *win = CTX_wm_window(C);
- if (!win->eventstate->shift) {
- const int len = RNA_property_array_length(&but->rnapoin, prop);
- bool *tmparray = MEM_callocN(sizeof(bool) * len, __func__);
-
- tmparray[index] = true;
-
- for (i = 0; i < selctx_data->elems_len; i++) {
- uiSelectContextElem *other = &selctx_data->elems[i];
- PointerRNA lptr = other->ptr;
- RNA_property_boolean_set_array(&lptr, lprop, tmparray);
- RNA_property_update(C, &lptr, lprop);
- }
-
- MEM_freeN(tmparray);
-
- return;
- }
- }
- }
-#endif
+static bool ui_selectcontext_begin(bContext *C, uiBut *but, uiSelectContextStore *selctx_data)
+{
+ PointerRNA ptr, lptr, idptr;
+ PropertyRNA *prop, *lprop;
+ bool success = false;
+ int index;
+
+ char *path = NULL;
+ ListBase lb = {NULL};
+
+ ptr = but->rnapoin;
+ prop = but->rnaprop;
+ index = but->rnaindex;
+
+ /* for now don't support whole colors */
+ if (index == -1) {
+ return false;
+ }
+
+ /* if there is a valid property that is editable... */
+ if (ptr.data && prop) {
+ CollectionPointerLink *link;
+ bool use_path_from_id;
+ int i;
+
+ /* some facts we want to know */
+ const bool is_array = RNA_property_array_check(prop);
+ const int rna_type = RNA_property_type(prop);
+
+ if (UI_context_copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path) &&
+ !BLI_listbase_is_empty(&lb)) {
+ selctx_data->elems_len = BLI_listbase_count(&lb);
+ selctx_data->elems = MEM_mallocN(sizeof(uiSelectContextElem) * selctx_data->elems_len,
+ __func__);
+
+ for (i = 0, link = lb.first; i < selctx_data->elems_len; i++, link = link->next) {
+ uiSelectContextElem *other = &selctx_data->elems[i];
+ /* TODO,. de-duplicate copy_to_selected_button */
+ if (link->ptr.data != ptr.data) {
+ if (use_path_from_id) {
+ /* Path relative to ID. */
+ lprop = NULL;
+ RNA_id_pointer_create(link->ptr.id.data, &idptr);
+ RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
+ }
+ else if (path) {
+ /* Path relative to elements from list. */
+ lprop = NULL;
+ RNA_path_resolve_property(&link->ptr, path, &lptr, &lprop);
+ }
+ else {
+ lptr = link->ptr;
+ lprop = prop;
+ }
+
+ /* lptr might not be the same as link->ptr! */
+ if ((lptr.data != ptr.data) && (lprop == prop) && RNA_property_editable(&lptr, lprop)) {
+ other->ptr = lptr;
+ if (is_array) {
+ if (rna_type == PROP_FLOAT) {
+ other->val_f = RNA_property_float_get_index(&lptr, lprop, index);
+ }
+ else if (rna_type == PROP_INT) {
+ other->val_i = RNA_property_int_get_index(&lptr, lprop, index);
+ }
+ /* ignored for now */
+# if 0
+ else if (rna_type == PROP_BOOLEAN) {
+ other->val_b = RNA_property_boolean_get_index(&lptr, lprop, index);
+ }
+# endif
+ }
+ else {
+ if (rna_type == PROP_FLOAT) {
+ other->val_f = RNA_property_float_get(&lptr, lprop);
+ }
+ else if (rna_type == PROP_INT) {
+ other->val_i = RNA_property_int_get(&lptr, lprop);
+ }
+ /* ignored for now */
+# if 0
+ else if (rna_type == PROP_BOOLEAN) {
+ other->val_b = RNA_property_boolean_get(&lptr, lprop);
+ }
+ else if (rna_type == PROP_ENUM) {
+ other->val_i = RNA_property_enum_get(&lptr, lprop);
+ }
+# endif
+ }
+
+ continue;
+ }
+ }
+
+ selctx_data->elems_len -= 1;
+ i -= 1;
+ }
+
+ success = (selctx_data->elems_len != 0);
+ }
+ }
+
+ if (selctx_data->elems_len == 0) {
+ MEM_SAFE_FREE(selctx_data->elems);
+ }
+
+ MEM_SAFE_FREE(path);
+ BLI_freelistN(&lb);
+
+ /* caller can clear */
+ selctx_data->do_free = true;
+
+ if (success) {
+ but->flag |= UI_BUT_IS_SELECT_CONTEXT;
+ }
+
+ return success;
+}
+
+static void ui_selectcontext_end(uiBut *but, uiSelectContextStore *selctx_data)
+{
+ if (selctx_data->do_free) {
+ if (selctx_data->elems) {
+ MEM_freeN(selctx_data->elems);
+ }
+ }
+
+ but->flag &= ~UI_BUT_IS_SELECT_CONTEXT;
+}
+
+static void ui_selectcontext_apply(bContext *C,
+ uiBut *but,
+ uiSelectContextStore *selctx_data,
+ const double value,
+ const double value_orig)
+{
+ if (selctx_data->elems) {
+ PropertyRNA *prop = but->rnaprop;
+ PropertyRNA *lprop = but->rnaprop;
+ int index = but->rnaindex;
+ int i;
+ const bool use_delta = (selctx_data->is_copy == false);
+
+ union {
+ bool b;
+ int i;
+ float f;
+ PointerRNA p;
+ } delta, min, max;
+
+ const bool is_array = RNA_property_array_check(prop);
+ const int rna_type = RNA_property_type(prop);
+
+ if (rna_type == PROP_FLOAT) {
+ delta.f = use_delta ? (value - value_orig) : value;
+ RNA_property_float_range(&but->rnapoin, prop, &min.f, &max.f);
+ }
+ else if (rna_type == PROP_INT) {
+ delta.i = use_delta ? ((int)value - (int)value_orig) : (int)value;
+ RNA_property_int_range(&but->rnapoin, prop, &min.i, &max.i);
+ }
+ else if (rna_type == PROP_ENUM) {
+ /* not a delta infact */
+ delta.i = RNA_property_enum_get(&but->rnapoin, prop);
+ }
+ else if (rna_type == PROP_BOOLEAN) {
+ if (is_array) {
+ /* not a delta infact */
+ delta.b = RNA_property_boolean_get_index(&but->rnapoin, prop, index);
+ }
+ else {
+ /* not a delta infact */
+ delta.b = RNA_property_boolean_get(&but->rnapoin, prop);
+ }
+ }
+ else if (rna_type == PROP_POINTER) {
+ /* not a delta infact */
+ delta.p = RNA_property_pointer_get(&but->rnapoin, prop);
+ }
+
+# ifdef USE_ALLSELECT_LAYER_HACK
+ /* make up for not having 'handle_layer_buttons' */
+ {
+ PropertySubType subtype = RNA_property_subtype(prop);
+
+ if ((rna_type == PROP_BOOLEAN) && ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER) && is_array &&
+ /* could check for 'handle_layer_buttons' */
+ but->func) {
+ wmWindow *win = CTX_wm_window(C);
+ if (!win->eventstate->shift) {
+ const int len = RNA_property_array_length(&but->rnapoin, prop);
+ bool *tmparray = MEM_callocN(sizeof(bool) * len, __func__);
+
+ tmparray[index] = true;
+
+ for (i = 0; i < selctx_data->elems_len; i++) {
+ uiSelectContextElem *other = &selctx_data->elems[i];
+ PointerRNA lptr = other->ptr;
+ RNA_property_boolean_set_array(&lptr, lprop, tmparray);
+ RNA_property_update(C, &lptr, lprop);
+ }
+
+ MEM_freeN(tmparray);
+
+ return;
+ }
+ }
+ }
+# endif
- for (i = 0; i < selctx_data->elems_len; i++) {
- uiSelectContextElem *other = &selctx_data->elems[i];
- PointerRNA lptr = other->ptr;
-
- if (rna_type == PROP_FLOAT) {
- float other_value = use_delta ? (other->val_f + delta.f) : delta.f;
- CLAMP(other_value, min.f, max.f);
- if (is_array) {
- RNA_property_float_set_index(&lptr, lprop, index, other_value);
- }
- else {
- RNA_property_float_set(&lptr, lprop, other_value);
- }
- }
- else if (rna_type == PROP_INT) {
- int other_value = use_delta ? (other->val_i + delta.i) : delta.i;
- CLAMP(other_value, min.i, max.i);
- if (is_array) {
- RNA_property_int_set_index(&lptr, lprop, index, other_value);
- }
- else {
- RNA_property_int_set(&lptr, lprop, other_value);
- }
- }
- else if (rna_type == PROP_BOOLEAN) {
- const bool other_value = delta.b;
- if (is_array) {
- RNA_property_boolean_set_index(&lptr, lprop, index, other_value);
- }
- else {
- RNA_property_boolean_set(&lptr, lprop, delta.b);
- }
- }
- else if (rna_type == PROP_ENUM) {
- const int other_value = delta.i;
- BLI_assert(!is_array);
- RNA_property_enum_set(&lptr, lprop, other_value);
- }
- else if (rna_type == PROP_POINTER) {
- const PointerRNA other_value = delta.p;
- RNA_property_pointer_set(&lptr, lprop, other_value);
- }
-
- RNA_property_update(C, &lptr, prop);
- }
- }
-}
-
-#endif /* USE_ALLSELECT */
+ for (i = 0; i < selctx_data->elems_len; i++) {
+ uiSelectContextElem *other = &selctx_data->elems[i];
+ PointerRNA lptr = other->ptr;
+
+ if (rna_type == PROP_FLOAT) {
+ float other_value = use_delta ? (other->val_f + delta.f) : delta.f;
+ CLAMP(other_value, min.f, max.f);
+ if (is_array) {
+ RNA_property_float_set_index(&lptr, lprop, index, other_value);
+ }
+ else {
+ RNA_property_float_set(&lptr, lprop, other_value);
+ }
+ }
+ else if (rna_type == PROP_INT) {
+ int other_value = use_delta ? (other->val_i + delta.i) : delta.i;
+ CLAMP(other_value, min.i, max.i);
+ if (is_array) {
+ RNA_property_int_set_index(&lptr, lprop, index, other_value);
+ }
+ else {
+ RNA_property_int_set(&lptr, lprop, other_value);
+ }
+ }
+ else if (rna_type == PROP_BOOLEAN) {
+ const bool other_value = delta.b;
+ if (is_array) {
+ RNA_property_boolean_set_index(&lptr, lprop, index, other_value);
+ }
+ else {
+ RNA_property_boolean_set(&lptr, lprop, delta.b);
+ }
+ }
+ else if (rna_type == PROP_ENUM) {
+ const int other_value = delta.i;
+ BLI_assert(!is_array);
+ RNA_property_enum_set(&lptr, lprop, other_value);
+ }
+ else if (rna_type == PROP_POINTER) {
+ const PointerRNA other_value = delta.p;
+ RNA_property_pointer_set(&lptr, lprop, other_value);
+ }
+
+ RNA_property_update(C, &lptr, prop);
+ }
+ }
+}
+
+#endif /* USE_ALLSELECT */
/** \} */
@@ -1739,112 +1725,114 @@ static void ui_selectcontext_apply(
/** \name Button Drag
* \{ */
-static bool ui_but_drag_init(
- bContext *C, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
+static bool ui_but_drag_init(bContext *C,
+ uiBut *but,
+ uiHandleButtonData *data,
+ const wmEvent *event)
{
- /* prevent other WM gestures to start while we try to drag */
- WM_gestures_remove(C);
+ /* prevent other WM gestures to start while we try to drag */
+ WM_gestures_remove(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. */
- const int drag_threshold = min_ii(
- U.tweak_threshold * U.dpi_fac,
- (int)((UI_UNIT_Y / 2) * ui_block_to_window_scale(data->region, but->block)));
+ /* 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. */
+ const int drag_threshold = min_ii(
+ U.tweak_threshold * U.dpi_fac,
+ (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) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- data->cancel = true;
+ 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;
-
- /* call here because regular mouse-up event wont run,
- * typically 'button_activate_exit()' handles this */
- ui_apply_but_autokey(C, but);
-
- drag_info->pushed_state = ui_drag_toggle_but_pushed_state(C, but);
- drag_info->but_cent_start[0] = BLI_rctf_cent_x(&but->rect);
- drag_info->but_cent_start[1] = BLI_rctf_cent_y(&but->rect);
- copy_v2_v2_int(drag_info->xy_init, &event->x);
- copy_v2_v2_int(drag_info->xy_last, &event->x);
-
- /* needed for toggle drag on popups */
- ar_prev = CTX_wm_region(C);
- CTX_wm_region_set(C, data->region);
-
- WM_event_add_ui_handler(
- C, &data->window->modalhandlers,
- ui_handler_region_drag_toggle,
- ui_handler_region_drag_toggle_remove,
- drag_info, WM_HANDLER_BLOCKING);
-
- CTX_wm_region_set(C, ar_prev);
-
- /* Initialize alignment for single row/column regions,
- * otherwise we use the relative position of the first other button dragged over. */
- if (ELEM(data->region->regiontype, RGN_TYPE_NAV_BAR, RGN_TYPE_HEADER, RGN_TYPE_FOOTER)) {
- int lock_axis = -1;
- if (ELEM(data->region->alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
- lock_axis = 0;
- }
- else if (ELEM(data->region->alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
- lock_axis = 1;
- }
- if (lock_axis != -1) {
- drag_info->xy_lock[lock_axis] = true;
- drag_info->is_xy_lock_init = true;
- }
- }
- }
- else
+ if (ui_drag_toggle_but_is_supported(but)) {
+ uiDragToggleHandle *drag_info = MEM_callocN(sizeof(*drag_info), __func__);
+ ARegion *ar_prev;
+
+ /* call here because regular mouse-up event wont run,
+ * typically 'button_activate_exit()' handles this */
+ ui_apply_but_autokey(C, but);
+
+ drag_info->pushed_state = ui_drag_toggle_but_pushed_state(C, but);
+ drag_info->but_cent_start[0] = BLI_rctf_cent_x(&but->rect);
+ drag_info->but_cent_start[1] = BLI_rctf_cent_y(&but->rect);
+ copy_v2_v2_int(drag_info->xy_init, &event->x);
+ copy_v2_v2_int(drag_info->xy_last, &event->x);
+
+ /* needed for toggle drag on popups */
+ ar_prev = CTX_wm_region(C);
+ CTX_wm_region_set(C, data->region);
+
+ WM_event_add_ui_handler(C,
+ &data->window->modalhandlers,
+ ui_handler_region_drag_toggle,
+ ui_handler_region_drag_toggle_remove,
+ drag_info,
+ WM_HANDLER_BLOCKING);
+
+ CTX_wm_region_set(C, ar_prev);
+
+ /* Initialize alignment for single row/column regions,
+ * otherwise we use the relative position of the first other button dragged over. */
+ if (ELEM(data->region->regiontype, RGN_TYPE_NAV_BAR, RGN_TYPE_HEADER, RGN_TYPE_FOOTER)) {
+ int lock_axis = -1;
+ if (ELEM(data->region->alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
+ lock_axis = 0;
+ }
+ else if (ELEM(data->region->alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
+ lock_axis = 1;
+ }
+ if (lock_axis != -1) {
+ drag_info->xy_lock[lock_axis] = true;
+ drag_info->is_xy_lock_init = true;
+ }
+ }
+ }
+ else
#endif
- if (but->type == UI_BTYPE_COLOR) {
- bool valid = false;
- uiDragColorHandle *drag_info = MEM_callocN(sizeof(*drag_info), __func__);
-
- /* TODO support more button pointer types */
- if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
- ui_but_v3_get(but, drag_info->color);
- drag_info->gamma_corrected = true;
- valid = true;
- }
- else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
- ui_but_v3_get(but, drag_info->color);
- drag_info->gamma_corrected = false;
- valid = true;
- }
- else if (ELEM(but->pointype, UI_BUT_POIN_FLOAT, UI_BUT_POIN_CHAR)) {
- ui_but_v3_get(but, drag_info->color);
- copy_v3_v3(drag_info->color, (float *)but->poin);
- valid = true;
- }
-
- if (valid) {
- WM_event_start_drag(C, ICON_COLOR, WM_DRAG_COLOR, drag_info, 0.0, WM_DRAG_FREE_DATA);
- }
- else {
- MEM_freeN(drag_info);
- return false;
- }
- }
- else {
- wmDrag *drag = WM_event_start_drag(
- C, but->icon, but->dragtype, but->dragpoin,
- ui_but_value_get(but), WM_DRAG_NOP);
-
- if (but->imb) {
- WM_event_drag_image(
- drag, but->imb, but->imb_scale,
- BLI_rctf_size_x(&but->rect),
- BLI_rctf_size_y(&but->rect));
- }
- }
- return true;
- }
-
- return false;
+ if (but->type == UI_BTYPE_COLOR) {
+ bool valid = false;
+ uiDragColorHandle *drag_info = MEM_callocN(sizeof(*drag_info), __func__);
+
+ /* TODO support more button pointer types */
+ if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
+ ui_but_v3_get(but, drag_info->color);
+ drag_info->gamma_corrected = true;
+ valid = true;
+ }
+ else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
+ ui_but_v3_get(but, drag_info->color);
+ drag_info->gamma_corrected = false;
+ valid = true;
+ }
+ else if (ELEM(but->pointype, UI_BUT_POIN_FLOAT, UI_BUT_POIN_CHAR)) {
+ ui_but_v3_get(but, drag_info->color);
+ copy_v3_v3(drag_info->color, (float *)but->poin);
+ valid = true;
+ }
+
+ if (valid) {
+ WM_event_start_drag(C, ICON_COLOR, WM_DRAG_COLOR, drag_info, 0.0, WM_DRAG_FREE_DATA);
+ }
+ else {
+ MEM_freeN(drag_info);
+ return false;
+ }
+ }
+ else {
+ wmDrag *drag = WM_event_start_drag(
+ C, but->icon, but->dragtype, but->dragpoin, ui_but_value_get(but), WM_DRAG_NOP);
+
+ if (but->imb) {
+ WM_event_drag_image(drag,
+ but->imb,
+ but->imb_scale,
+ BLI_rctf_size_x(&but->rect),
+ BLI_rctf_size_y(&but->rect));
+ }
+ }
+ return true;
+ }
+
+ return false;
}
/** \} */
@@ -1855,210 +1843,208 @@ static bool ui_but_drag_init(
static void ui_apply_but_IMAGE(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- ui_apply_but_func(C, but);
- data->retval = but->retval;
- data->applied = true;
+ ui_apply_but_func(C, but);
+ data->retval = but->retval;
+ data->applied = true;
}
static void ui_apply_but_HISTOGRAM(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- ui_apply_but_func(C, but);
- data->retval = but->retval;
- data->applied = true;
+ ui_apply_but_func(C, but);
+ data->retval = but->retval;
+ data->applied = true;
}
static void ui_apply_but_WAVEFORM(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- ui_apply_but_func(C, but);
- data->retval = but->retval;
- data->applied = true;
+ ui_apply_but_func(C, but);
+ data->retval = but->retval;
+ data->applied = true;
}
static void ui_apply_but_TRACKPREVIEW(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- ui_apply_but_func(C, but);
- data->retval = but->retval;
- data->applied = true;
-}
-
-
-static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const bool interactive)
-{
- char *editstr;
- double *editval;
- float *editvec;
- ColorBand *editcoba;
- CurveMapping *editcumap;
-
- data->retval = 0;
-
- /* if we cancel and have not applied yet, there is nothing to do,
- * otherwise we have to restore the original value again */
- if (data->cancel) {
- if (!data->applied) {
- return;
- }
-
- if (data->str) {
- MEM_freeN(data->str);
- }
- data->str = data->origstr;
- data->origstr = NULL;
- data->value = data->origvalue;
- copy_v3_v3(data->vec, data->origvec);
- /* postpone clearing origdata */
- }
- else {
- /* we avoid applying interactive edits a second time
- * at the end with the appliedinteractive flag */
- if (interactive) {
- data->applied_interactive = true;
- }
- else if (data->applied_interactive) {
- return;
- }
+ ui_apply_but_func(C, but);
+ data->retval = but->retval;
+ data->applied = true;
+}
+
+static void ui_apply_but(
+ bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const bool interactive)
+{
+ char *editstr;
+ double *editval;
+ float *editvec;
+ ColorBand *editcoba;
+ CurveMapping *editcumap;
+
+ data->retval = 0;
+
+ /* if we cancel and have not applied yet, there is nothing to do,
+ * otherwise we have to restore the original value again */
+ if (data->cancel) {
+ if (!data->applied) {
+ return;
+ }
+
+ if (data->str) {
+ MEM_freeN(data->str);
+ }
+ data->str = data->origstr;
+ data->origstr = NULL;
+ data->value = data->origvalue;
+ copy_v3_v3(data->vec, data->origvec);
+ /* postpone clearing origdata */
+ }
+ else {
+ /* we avoid applying interactive edits a second time
+ * at the end with the appliedinteractive flag */
+ if (interactive) {
+ data->applied_interactive = true;
+ }
+ else if (data->applied_interactive) {
+ return;
+ }
#ifdef USE_ALLSELECT
# ifdef USE_DRAG_MULTINUM
- if (but->flag & UI_BUT_DRAG_MULTI) {
- /* pass */
- }
- else
+ if (but->flag & UI_BUT_DRAG_MULTI) {
+ /* pass */
+ }
+ else
# endif
- if (data->select_others.elems_len == 0) {
- wmWindow *win = CTX_wm_window(C);
- /* may have been enabled before activating */
- if (data->select_others.is_enabled || IS_ALLSELECT_EVENT(win->eventstate)) {
- ui_selectcontext_begin(C, but, &data->select_others);
- data->select_others.is_enabled = true;
- }
- }
- if (data->select_others.elems_len == 0) {
- /* dont check again */
- data->select_others.elems_len = -1;
- }
+ if (data->select_others.elems_len == 0) {
+ wmWindow *win = CTX_wm_window(C);
+ /* may have been enabled before activating */
+ if (data->select_others.is_enabled || IS_ALLSELECT_EVENT(win->eventstate)) {
+ ui_selectcontext_begin(C, but, &data->select_others);
+ data->select_others.is_enabled = true;
+ }
+ }
+ if (data->select_others.elems_len == 0) {
+ /* dont check again */
+ data->select_others.elems_len = -1;
+ }
#endif
- }
-
- /* ensures we are writing actual values */
- editstr = but->editstr;
- editval = but->editval;
- editvec = but->editvec;
- editcoba = but->editcoba;
- editcumap = but->editcumap;
- but->editstr = NULL;
- but->editval = NULL;
- but->editvec = NULL;
- but->editcoba = NULL;
- but->editcumap = NULL;
-
- /* handle different types */
- switch (but->type) {
- case UI_BTYPE_BUT:
- ui_apply_but_BUT(C, but, data);
- break;
- case UI_BTYPE_TEXT:
- case UI_BTYPE_SEARCH_MENU:
- ui_apply_but_TEX(C, but, data);
- break;
- case UI_BTYPE_BUT_TOGGLE:
- case UI_BTYPE_TOGGLE:
- case UI_BTYPE_TOGGLE_N:
- case UI_BTYPE_ICON_TOGGLE:
- case UI_BTYPE_ICON_TOGGLE_N:
- case UI_BTYPE_CHECKBOX:
- case UI_BTYPE_CHECKBOX_N:
- ui_apply_but_TOG(C, but, data);
- break;
- case UI_BTYPE_ROW:
- case UI_BTYPE_LISTROW:
- ui_apply_but_ROW(C, block, but, data);
- break;
- case UI_BTYPE_TAB:
- ui_apply_but_TAB(C, but, data);
- break;
- case UI_BTYPE_SCROLL:
- case UI_BTYPE_GRIP:
- case UI_BTYPE_NUM:
- case UI_BTYPE_NUM_SLIDER:
- ui_apply_but_NUM(C, but, data);
- break;
- case UI_BTYPE_MENU:
- case UI_BTYPE_BLOCK:
- case UI_BTYPE_PULLDOWN:
- ui_apply_but_BLOCK(C, but, data);
- break;
- case UI_BTYPE_COLOR:
- if (data->cancel) {
- ui_apply_but_VEC(C, but, data);
- }
- else {
- ui_apply_but_BLOCK(C, but, data);
- }
- break;
- case UI_BTYPE_BUT_MENU:
- ui_apply_but_BUTM(C, but, data);
- break;
- case UI_BTYPE_UNITVEC:
- case UI_BTYPE_HSVCUBE:
- case UI_BTYPE_HSVCIRCLE:
- ui_apply_but_VEC(C, but, data);
- break;
- case UI_BTYPE_COLORBAND:
- ui_apply_but_COLORBAND(C, but, data);
- break;
- case UI_BTYPE_CURVE:
- ui_apply_but_CURVE(C, but, data);
- break;
- case UI_BTYPE_KEY_EVENT:
- case UI_BTYPE_HOTKEY_EVENT:
- ui_apply_but_BUT(C, but, data);
- break;
- case UI_BTYPE_IMAGE:
- ui_apply_but_IMAGE(C, but, data);
- break;
- case UI_BTYPE_HISTOGRAM:
- ui_apply_but_HISTOGRAM(C, but, data);
- break;
- case UI_BTYPE_WAVEFORM:
- ui_apply_but_WAVEFORM(C, but, data);
- break;
- case UI_BTYPE_TRACK_PREVIEW:
- ui_apply_but_TRACKPREVIEW(C, but, data);
- break;
- default:
- break;
- }
+ }
+
+ /* ensures we are writing actual values */
+ editstr = but->editstr;
+ editval = but->editval;
+ editvec = but->editvec;
+ editcoba = but->editcoba;
+ editcumap = but->editcumap;
+ but->editstr = NULL;
+ but->editval = NULL;
+ but->editvec = NULL;
+ but->editcoba = NULL;
+ but->editcumap = NULL;
+
+ /* handle different types */
+ switch (but->type) {
+ case UI_BTYPE_BUT:
+ ui_apply_but_BUT(C, but, data);
+ break;
+ case UI_BTYPE_TEXT:
+ case UI_BTYPE_SEARCH_MENU:
+ ui_apply_but_TEX(C, but, data);
+ break;
+ case UI_BTYPE_BUT_TOGGLE:
+ case UI_BTYPE_TOGGLE:
+ case UI_BTYPE_TOGGLE_N:
+ case UI_BTYPE_ICON_TOGGLE:
+ case UI_BTYPE_ICON_TOGGLE_N:
+ case UI_BTYPE_CHECKBOX:
+ case UI_BTYPE_CHECKBOX_N:
+ ui_apply_but_TOG(C, but, data);
+ break;
+ case UI_BTYPE_ROW:
+ case UI_BTYPE_LISTROW:
+ ui_apply_but_ROW(C, block, but, data);
+ break;
+ case UI_BTYPE_TAB:
+ ui_apply_but_TAB(C, but, data);
+ break;
+ case UI_BTYPE_SCROLL:
+ case UI_BTYPE_GRIP:
+ case UI_BTYPE_NUM:
+ case UI_BTYPE_NUM_SLIDER:
+ ui_apply_but_NUM(C, but, data);
+ break;
+ case UI_BTYPE_MENU:
+ case UI_BTYPE_BLOCK:
+ case UI_BTYPE_PULLDOWN:
+ ui_apply_but_BLOCK(C, but, data);
+ break;
+ case UI_BTYPE_COLOR:
+ if (data->cancel) {
+ ui_apply_but_VEC(C, but, data);
+ }
+ else {
+ ui_apply_but_BLOCK(C, but, data);
+ }
+ break;
+ case UI_BTYPE_BUT_MENU:
+ ui_apply_but_BUTM(C, but, data);
+ break;
+ case UI_BTYPE_UNITVEC:
+ case UI_BTYPE_HSVCUBE:
+ case UI_BTYPE_HSVCIRCLE:
+ ui_apply_but_VEC(C, but, data);
+ break;
+ case UI_BTYPE_COLORBAND:
+ ui_apply_but_COLORBAND(C, but, data);
+ break;
+ case UI_BTYPE_CURVE:
+ ui_apply_but_CURVE(C, but, data);
+ break;
+ case UI_BTYPE_KEY_EVENT:
+ case UI_BTYPE_HOTKEY_EVENT:
+ ui_apply_but_BUT(C, but, data);
+ break;
+ case UI_BTYPE_IMAGE:
+ ui_apply_but_IMAGE(C, but, data);
+ break;
+ case UI_BTYPE_HISTOGRAM:
+ ui_apply_but_HISTOGRAM(C, but, data);
+ break;
+ case UI_BTYPE_WAVEFORM:
+ ui_apply_but_WAVEFORM(C, but, data);
+ break;
+ case UI_BTYPE_TRACK_PREVIEW:
+ ui_apply_but_TRACKPREVIEW(C, but, data);
+ break;
+ default:
+ break;
+ }
#ifdef USE_DRAG_MULTINUM
- if (data->multi_data.has_mbuts) {
- if ((data->multi_data.init == BUTTON_MULTI_INIT_ENABLE) &&
- (data->multi_data.skip == false))
- {
- if (data->cancel) {
- ui_multibut_restore(C, data, block);
- }
- else {
- ui_multibut_states_apply(C, data, block);
- }
- }
- }
+ if (data->multi_data.has_mbuts) {
+ if ((data->multi_data.init == BUTTON_MULTI_INIT_ENABLE) && (data->multi_data.skip == false)) {
+ if (data->cancel) {
+ ui_multibut_restore(C, data, block);
+ }
+ else {
+ ui_multibut_states_apply(C, data, block);
+ }
+ }
+ }
#endif
#ifdef USE_ALLSELECT
- ui_selectcontext_apply(C, but, &data->select_others, data->value, data->origvalue);
+ ui_selectcontext_apply(C, but, &data->select_others, data->value, data->origvalue);
#endif
- if (data->cancel) {
- data->origvalue = 0.0;
- zero_v3(data->origvec);
- }
+ if (data->cancel) {
+ data->origvalue = 0.0;
+ zero_v3(data->origvec);
+ }
- but->editstr = editstr;
- but->editval = editval;
- but->editvec = editvec;
- but->editcoba = editcoba;
- but->editcumap = editcumap;
+ but->editstr = editstr;
+ but->editval = editval;
+ but->editvec = editvec;
+ but->editcoba = editcoba;
+ but->editcumap = editcumap;
}
/** \} */
@@ -2070,28 +2056,28 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
/* only call if event type is EVT_DROP */
static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleButtonData *data)
{
- wmDrag *wmd;
- ListBase *drags = event->customdata; /* drop event type has listbase customdata by default */
+ wmDrag *wmd;
+ ListBase *drags = event->customdata; /* drop event type has listbase customdata by default */
- for (wmd = drags->first; wmd; wmd = wmd->next) {
- if (wmd->type == WM_DRAG_ID) {
- /* align these types with UI_but_active_drop_name */
- if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
- ID *id = WM_drag_ID(wmd, 0);
+ for (wmd = drags->first; wmd; wmd = wmd->next) {
+ if (wmd->type == WM_DRAG_ID) {
+ /* align these types with UI_but_active_drop_name */
+ if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
+ ID *id = WM_drag_ID(wmd, 0);
- button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
- ui_textedit_string_set(but, data, id->name + 2);
+ ui_textedit_string_set(but, data, id->name + 2);
- if (ELEM(but->type, UI_BTYPE_SEARCH_MENU)) {
- but->changed = true;
- ui_searchbox_update(C, data->searchbox, but, true);
- }
+ if (ELEM(but->type, UI_BTYPE_SEARCH_MENU)) {
+ but->changed = true;
+ ui_searchbox_update(C, data->searchbox, but, true);
+ }
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- }
- }
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+ }
}
/** \} */
@@ -2102,435 +2088,446 @@ static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleB
static void ui_but_get_pasted_text_from_clipboard(char **buf_paste, int *buf_len)
{
- char *text;
- int length;
- /* get only first line even if the clipboard contains multiple lines */
- text = WM_clipboard_text_get_firstline(false, &length);
+ char *text;
+ int length;
+ /* get only first line even if the clipboard contains multiple lines */
+ text = WM_clipboard_text_get_firstline(false, &length);
- if (text) {
- *buf_paste = text;
- *buf_len = length;
- }
- else {
- *buf_paste = MEM_callocN(sizeof(char), __func__);
- *buf_len = 0;
- }
+ if (text) {
+ *buf_paste = text;
+ *buf_len = length;
+ }
+ else {
+ *buf_paste = MEM_callocN(sizeof(char), __func__);
+ *buf_len = 0;
+ }
}
static int get_but_property_array_length(uiBut *but)
{
- return RNA_property_array_length(&but->rnapoin, but->rnaprop);
+ return RNA_property_array_length(&but->rnapoin, but->rnaprop);
}
-static void ui_but_set_float_array(bContext *C, uiBut *but, uiHandleButtonData *data, float *values, int array_length)
+static void ui_but_set_float_array(
+ bContext *C, uiBut *but, uiHandleButtonData *data, float *values, int array_length)
{
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- for (int i = 0; i < array_length; i++) {
- RNA_property_float_set_index(&but->rnapoin, but->rnaprop, i, values[i]);
- }
- if (data) {
- data->value = values[but->rnaindex];
- }
+ for (int i = 0; i < array_length; i++) {
+ RNA_property_float_set_index(&but->rnapoin, but->rnaprop, i, values[i]);
+ }
+ if (data) {
+ data->value = values[but->rnaindex];
+ }
- button_activate_state(C, but, BUTTON_STATE_EXIT);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
}
-static void float_array_to_string(float *values, int array_length, char *output, int output_len_max)
+static void float_array_to_string(float *values,
+ int array_length,
+ char *output,
+ int output_len_max)
{
- /* to avoid buffer overflow attacks; numbers are quite arbitrary */
- BLI_assert(output_len_max > 15);
- output_len_max -= 10;
+ /* to avoid buffer overflow attacks; numbers are quite arbitrary */
+ BLI_assert(output_len_max > 15);
+ output_len_max -= 10;
- int current_index = 0;
- output[current_index] = '[';
- current_index++;
+ int current_index = 0;
+ output[current_index] = '[';
+ current_index++;
- for (int i = 0; i < array_length; i++) {
- int length = BLI_snprintf(output + current_index, output_len_max - current_index, "%f", values[i]);
- current_index += length;
+ for (int i = 0; i < array_length; i++) {
+ int length = BLI_snprintf(
+ output + current_index, output_len_max - current_index, "%f", values[i]);
+ current_index += length;
- if (i < array_length - 1) {
- if (current_index < output_len_max) {
- output[current_index + 0] = ',';
- output[current_index + 1] = ' ';
- current_index += 2;
- }
- }
- }
+ if (i < array_length - 1) {
+ if (current_index < output_len_max) {
+ output[current_index + 0] = ',';
+ output[current_index + 1] = ' ';
+ current_index += 2;
+ }
+ }
+ }
- output[current_index + 0] = ']';
- output[current_index + 1] = '\0';
+ output[current_index + 0] = ']';
+ output[current_index + 1] = '\0';
}
static void ui_but_copy_numeric_array(uiBut *but, char *output, int output_len_max)
{
- int array_length = get_but_property_array_length(but);
- float *values = alloca(array_length * sizeof(float));
- RNA_property_float_get_array(&but->rnapoin, but->rnaprop, values);
- float_array_to_string(values, array_length, output, output_len_max);
+ int array_length = get_but_property_array_length(but);
+ float *values = alloca(array_length * sizeof(float));
+ RNA_property_float_get_array(&but->rnapoin, but->rnaprop, values);
+ float_array_to_string(values, array_length, output, output_len_max);
}
static bool parse_float_array(char *text, float *values, int expected_length)
{
- /* can parse max 4 floats for now */
- BLI_assert(0 <= expected_length && expected_length <= 4);
+ /* can parse max 4 floats for now */
+ BLI_assert(0 <= expected_length && expected_length <= 4);
- float v[5];
- int actual_length = sscanf(text, "[%f, %f, %f, %f, %f]", &v[0], &v[1], &v[2], &v[3], &v[4]);
+ float v[5];
+ int actual_length = sscanf(text, "[%f, %f, %f, %f, %f]", &v[0], &v[1], &v[2], &v[3], &v[4]);
- if (actual_length == expected_length) {
- memcpy(values, v, sizeof(float) * expected_length);
- return true;
- }
- else {
- return false;
- }
+ if (actual_length == expected_length) {
+ memcpy(values, v, sizeof(float) * expected_length);
+ return true;
+ }
+ else {
+ return false;
+ }
}
-static void ui_but_paste_numeric_array(bContext *C, uiBut *but, uiHandleButtonData *data, char *buf_paste)
+static void ui_but_paste_numeric_array(bContext *C,
+ uiBut *but,
+ uiHandleButtonData *data,
+ char *buf_paste)
{
- int array_length = get_but_property_array_length(but);
- if (array_length > 4) {
- // not supported for now
- return;
- }
+ int array_length = get_but_property_array_length(but);
+ if (array_length > 4) {
+ // not supported for now
+ return;
+ }
- float *values = alloca(sizeof(float) * array_length);
+ float *values = alloca(sizeof(float) * array_length);
- if (parse_float_array(buf_paste, values, array_length)) {
- ui_but_set_float_array(C, but, data, values, array_length);
- }
- else {
- WM_report(RPT_ERROR, "Expected an array of numbers: [n, n, ...]");
- }
+ if (parse_float_array(buf_paste, values, array_length)) {
+ ui_but_set_float_array(C, but, data, values, array_length);
+ }
+ else {
+ WM_report(RPT_ERROR, "Expected an array of numbers: [n, n, ...]");
+ }
}
static void ui_but_copy_numeric_value(uiBut *but, char *output, int output_len_max)
{
- /* Get many decimal places, then strip trailing zeros.
- * note: too high values start to give strange results */
- ui_but_string_get_ex(but, output, output_len_max, UI_PRECISION_FLOAT_MAX, false, NULL);
- BLI_str_rstrip_float_zero(output, '\0');
+ /* Get many decimal places, then strip trailing zeros.
+ * note: too high values start to give strange results */
+ ui_but_string_get_ex(but, output, output_len_max, UI_PRECISION_FLOAT_MAX, false, NULL);
+ BLI_str_rstrip_float_zero(output, '\0');
}
-static void ui_but_paste_numeric_value(bContext *C, uiBut *but, uiHandleButtonData *data, char *buf_paste)
+static void ui_but_paste_numeric_value(bContext *C,
+ uiBut *but,
+ uiHandleButtonData *data,
+ char *buf_paste)
{
- double value;
+ double value;
- if (ui_but_string_set_eval_num(C, but, buf_paste, &value)) {
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- data->value = value;
- ui_but_string_set(C, but, buf_paste);
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- else {
- WM_report(RPT_ERROR, "Expected a number");
- }
+ if (ui_but_string_set_eval_num(C, but, buf_paste, &value)) {
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+ data->value = value;
+ ui_but_string_set(C, but, buf_paste);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else {
+ WM_report(RPT_ERROR, "Expected a number");
+ }
}
static void ui_but_paste_normalized_vector(bContext *C, uiBut *but, char *buf_paste)
{
- float xyz[3];
- if (parse_float_array(buf_paste, xyz, 3)) {
- if (normalize_v3(xyz) == 0.0f) {
- /* better set Z up then have a zero vector */
- xyz[2] = 1.0;
- }
- ui_but_set_float_array(C, but, NULL, xyz, 3);
- }
- else {
- WM_report(RPT_ERROR, "Paste expected 3 numbers, formatted: '[n, n, n]'");
- }
+ float xyz[3];
+ if (parse_float_array(buf_paste, xyz, 3)) {
+ if (normalize_v3(xyz) == 0.0f) {
+ /* better set Z up then have a zero vector */
+ xyz[2] = 1.0;
+ }
+ ui_but_set_float_array(C, but, NULL, xyz, 3);
+ }
+ else {
+ WM_report(RPT_ERROR, "Paste expected 3 numbers, formatted: '[n, n, n]'");
+ }
}
static void ui_but_copy_color(uiBut *but, char *output, int output_len_max)
{
- float rgba[4];
+ float rgba[4];
- if (but->rnaprop && get_but_property_array_length(but) == 4) {
- rgba[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
- }
- else {
- rgba[3] = 1.0f;
- }
+ if (but->rnaprop && get_but_property_array_length(but) == 4) {
+ rgba[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
+ }
+ else {
+ rgba[3] = 1.0f;
+ }
- ui_but_v3_get(but, rgba);
+ ui_but_v3_get(but, rgba);
- /* convert to linear color to do compatible copy between gamma and non-gamma */
- if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
- srgb_to_linearrgb_v3_v3(rgba, rgba);
- }
+ /* convert to linear color to do compatible copy between gamma and non-gamma */
+ if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
+ srgb_to_linearrgb_v3_v3(rgba, rgba);
+ }
- float_array_to_string(rgba, 4, output, output_len_max);
+ float_array_to_string(rgba, 4, output, output_len_max);
}
static void ui_but_paste_color(bContext *C, uiBut *but, char *buf_paste)
{
- float rgba[4];
- if (parse_float_array(buf_paste, rgba, 4)) {
- if (but->rnaprop) {
- /* Assume linear colors in buffer. */
- if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
- linearrgb_to_srgb_v3_v3(rgba, rgba);
- }
-
- /* Some color properties are RGB, not RGBA. */
- int array_len = get_but_property_array_length(but);
- BLI_assert(ELEM(array_len, 3, 4));
- ui_but_set_float_array(C, but, NULL, rgba, array_len);
- }
- }
- else {
- WM_report(RPT_ERROR, "Paste expected 4 numbers, formatted: '[n, n, n, n]'");
- }
+ float rgba[4];
+ if (parse_float_array(buf_paste, rgba, 4)) {
+ if (but->rnaprop) {
+ /* Assume linear colors in buffer. */
+ if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
+ linearrgb_to_srgb_v3_v3(rgba, rgba);
+ }
+
+ /* Some color properties are RGB, not RGBA. */
+ int array_len = get_but_property_array_length(but);
+ BLI_assert(ELEM(array_len, 3, 4));
+ ui_but_set_float_array(C, but, NULL, rgba, array_len);
+ }
+ }
+ else {
+ WM_report(RPT_ERROR, "Paste expected 4 numbers, formatted: '[n, n, n, n]'");
+ }
}
static void ui_but_copy_text(uiBut *but, char *output, int output_len_max)
{
- ui_but_string_get(but, output, output_len_max);
+ ui_but_string_get(but, output, output_len_max);
}
static void ui_but_paste_text(bContext *C, uiBut *but, uiHandleButtonData *data, char *buf_paste)
{
- button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
- ui_textedit_string_set(but, but->active, buf_paste);
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ ui_textedit_string_set(but, but->active, buf_paste);
- if (but->type == UI_BTYPE_SEARCH_MENU) {
- but->changed = true;
- ui_searchbox_update(C, data->searchbox, but, true);
- }
+ if (but->type == UI_BTYPE_SEARCH_MENU) {
+ but->changed = true;
+ ui_searchbox_update(C, data->searchbox, but, true);
+ }
- button_activate_state(C, but, BUTTON_STATE_EXIT);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
}
static void ui_but_copy_colorband(uiBut *but)
{
- if (but->poin != NULL) {
- memcpy(&but_copypaste_coba, but->poin, sizeof(ColorBand));
- }
+ if (but->poin != NULL) {
+ memcpy(&but_copypaste_coba, but->poin, sizeof(ColorBand));
+ }
}
static void ui_but_paste_colorband(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- if (but_copypaste_coba.tot != 0) {
- if (!but->poin) {
- but->poin = MEM_callocN(sizeof(ColorBand), "colorband");
- }
+ if (but_copypaste_coba.tot != 0) {
+ if (!but->poin) {
+ but->poin = MEM_callocN(sizeof(ColorBand), "colorband");
+ }
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- memcpy(data->coba, &but_copypaste_coba, sizeof(ColorBand));
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+ memcpy(data->coba, &but_copypaste_coba, sizeof(ColorBand));
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
}
static void ui_but_copy_curvemapping(uiBut *but)
{
- if (but->poin != NULL) {
- but_copypaste_curve_alive = true;
- curvemapping_free_data(&but_copypaste_curve);
- curvemapping_copy_data(&but_copypaste_curve, (CurveMapping *) but->poin);
- }
+ if (but->poin != NULL) {
+ but_copypaste_curve_alive = true;
+ curvemapping_free_data(&but_copypaste_curve);
+ curvemapping_copy_data(&but_copypaste_curve, (CurveMapping *)but->poin);
+ }
}
static void ui_but_paste_curvemapping(bContext *C, uiBut *but)
{
- if (but_copypaste_curve_alive) {
- if (!but->poin) {
- but->poin = MEM_callocN(sizeof(CurveMapping), "curvemapping");
- }
+ if (but_copypaste_curve_alive) {
+ if (!but->poin) {
+ but->poin = MEM_callocN(sizeof(CurveMapping), "curvemapping");
+ }
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- curvemapping_free_data((CurveMapping *) but->poin);
- curvemapping_copy_data((CurveMapping *) but->poin, &but_copypaste_curve);
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+ curvemapping_free_data((CurveMapping *)but->poin);
+ curvemapping_copy_data((CurveMapping *)but->poin, &but_copypaste_curve);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
}
static void ui_but_copy_operator(bContext *C, uiBut *but, char *output, int output_len_max)
{
- PointerRNA *opptr;
- opptr = UI_but_operator_ptr_get(but);
+ PointerRNA *opptr;
+ opptr = UI_but_operator_ptr_get(but);
- char *str;
- str = WM_operator_pystring_ex(C, NULL, false, true, but->optype, opptr);
- BLI_strncpy(output, str, output_len_max);
- MEM_freeN(str);
+ char *str;
+ str = WM_operator_pystring_ex(C, NULL, false, true, but->optype, opptr);
+ BLI_strncpy(output, str, output_len_max);
+ MEM_freeN(str);
}
static bool ui_but_copy_menu(uiBut *but, char *output, int output_len_max)
{
- MenuType *mt = UI_but_menutype_get(but);
- if (mt) {
- BLI_snprintf(output, output_len_max, "bpy.ops.wm.call_menu(name=\"%s\")", mt->idname);
- return true;
- }
- return false;
+ MenuType *mt = UI_but_menutype_get(but);
+ if (mt) {
+ BLI_snprintf(output, output_len_max, "bpy.ops.wm.call_menu(name=\"%s\")", mt->idname);
+ return true;
+ }
+ return false;
}
static bool ui_but_copy_popover(uiBut *but, char *output, int output_len_max)
{
- PanelType *pt = UI_but_paneltype_get(but);
- if (pt) {
- BLI_snprintf(output, output_len_max, "bpy.ops.wm.call_panel(name=\"%s\")", pt->idname);
- return true;
- }
- return false;
+ PanelType *pt = UI_but_paneltype_get(but);
+ if (pt) {
+ BLI_snprintf(output, output_len_max, "bpy.ops.wm.call_panel(name=\"%s\")", pt->idname);
+ return true;
+ }
+ return false;
}
static void ui_but_copy(bContext *C, uiBut *but, const bool copy_array)
{
- if (ui_but_contains_password(but)) {
- return;
- }
-
- /* Arbitrary large value (allow for paths: 'PATH_MAX') */
- char buf[4096] = {0};
- const int buf_max_len = sizeof(buf);
-
- /* Left false for copying internal data (color-band for eg). */
- bool is_buf_set = false;
-
- bool has_required_data = !(but->poin == NULL && but->rnapoin.data == NULL);
-
- switch (but->type) {
- case UI_BTYPE_NUM:
- case UI_BTYPE_NUM_SLIDER:
- if (!has_required_data) {
- break;
- }
- if (copy_array && ui_but_has_array_value(but)) {
- ui_but_copy_numeric_array(but, buf, buf_max_len);
- }
- else {
- ui_but_copy_numeric_value(but, buf, buf_max_len);
- }
- is_buf_set = true;
- break;
-
- case UI_BTYPE_UNITVEC:
- if (!has_required_data) {
- break;
- }
- ui_but_copy_numeric_array(but, buf, buf_max_len);
- is_buf_set = true;
- break;
-
- case UI_BTYPE_COLOR:
- if (!has_required_data) {
- break;
- }
- ui_but_copy_color(but, buf, buf_max_len);
- is_buf_set = true;
- break;
-
- case UI_BTYPE_TEXT:
- case UI_BTYPE_SEARCH_MENU:
- if (!has_required_data) {
- break;
- }
- ui_but_copy_text(but, buf, buf_max_len);
- is_buf_set = true;
- break;
-
- case UI_BTYPE_COLORBAND:
- ui_but_copy_colorband(but);
- break;
-
- case UI_BTYPE_CURVE:
- ui_but_copy_curvemapping(but);
- break;
-
- case UI_BTYPE_BUT:
- ui_but_copy_operator(C, but, buf, buf_max_len);
- is_buf_set = true;
- break;
-
- case UI_BTYPE_MENU:
- case UI_BTYPE_PULLDOWN:
- if (ui_but_copy_menu(but, buf, buf_max_len)) {
- is_buf_set = true;
- }
- break;
- case UI_BTYPE_POPOVER:
- if (ui_but_copy_popover(but, buf, buf_max_len)) {
- is_buf_set = true;
- }
- break;
-
- default:
- break;
- }
-
- if (is_buf_set) {
- WM_clipboard_text_set(buf, 0);
- }
+ if (ui_but_contains_password(but)) {
+ return;
+ }
+
+ /* Arbitrary large value (allow for paths: 'PATH_MAX') */
+ char buf[4096] = {0};
+ const int buf_max_len = sizeof(buf);
+
+ /* Left false for copying internal data (color-band for eg). */
+ bool is_buf_set = false;
+
+ bool has_required_data = !(but->poin == NULL && but->rnapoin.data == NULL);
+
+ switch (but->type) {
+ case UI_BTYPE_NUM:
+ case UI_BTYPE_NUM_SLIDER:
+ if (!has_required_data) {
+ break;
+ }
+ if (copy_array && ui_but_has_array_value(but)) {
+ ui_but_copy_numeric_array(but, buf, buf_max_len);
+ }
+ else {
+ ui_but_copy_numeric_value(but, buf, buf_max_len);
+ }
+ is_buf_set = true;
+ break;
+
+ case UI_BTYPE_UNITVEC:
+ if (!has_required_data) {
+ break;
+ }
+ ui_but_copy_numeric_array(but, buf, buf_max_len);
+ is_buf_set = true;
+ break;
+
+ case UI_BTYPE_COLOR:
+ if (!has_required_data) {
+ break;
+ }
+ ui_but_copy_color(but, buf, buf_max_len);
+ is_buf_set = true;
+ break;
+
+ case UI_BTYPE_TEXT:
+ case UI_BTYPE_SEARCH_MENU:
+ if (!has_required_data) {
+ break;
+ }
+ ui_but_copy_text(but, buf, buf_max_len);
+ is_buf_set = true;
+ break;
+
+ case UI_BTYPE_COLORBAND:
+ ui_but_copy_colorband(but);
+ break;
+
+ case UI_BTYPE_CURVE:
+ ui_but_copy_curvemapping(but);
+ break;
+
+ case UI_BTYPE_BUT:
+ ui_but_copy_operator(C, but, buf, buf_max_len);
+ is_buf_set = true;
+ break;
+
+ case UI_BTYPE_MENU:
+ case UI_BTYPE_PULLDOWN:
+ if (ui_but_copy_menu(but, buf, buf_max_len)) {
+ is_buf_set = true;
+ }
+ break;
+ case UI_BTYPE_POPOVER:
+ if (ui_but_copy_popover(but, buf, buf_max_len)) {
+ is_buf_set = true;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (is_buf_set) {
+ WM_clipboard_text_set(buf, 0);
+ }
}
static void ui_but_paste(bContext *C, uiBut *but, uiHandleButtonData *data, const bool paste_array)
{
- BLI_assert((but->flag & UI_BUT_DISABLED) == 0); /* caller should check */
-
- int buf_paste_len = 0;
- char *buf_paste;
- ui_but_get_pasted_text_from_clipboard(&buf_paste, &buf_paste_len);
-
- bool has_required_data = !(but->poin == NULL && but->rnapoin.data == NULL);
-
- switch (but->type) {
- case UI_BTYPE_NUM:
- case UI_BTYPE_NUM_SLIDER:
- if (!has_required_data) {
- break;
- }
- if (paste_array && ui_but_has_array_value(but)) {
- ui_but_paste_numeric_array(C, but, data, buf_paste);
- }
- else {
- ui_but_paste_numeric_value(C, but, data, buf_paste);
- }
- break;
-
- case UI_BTYPE_UNITVEC:
- if (!has_required_data) {
- break;
- }
- ui_but_paste_normalized_vector(C, but, buf_paste);
- break;
-
- case UI_BTYPE_COLOR:
- if (!has_required_data) {
- break;
- }
- ui_but_paste_color(C, but, buf_paste);
- break;
-
- case UI_BTYPE_TEXT:
- case UI_BTYPE_SEARCH_MENU:
- if (!has_required_data) {
- break;
- }
- ui_but_paste_text(C, but, data, buf_paste);
- break;
-
- case UI_BTYPE_COLORBAND:
- ui_but_paste_colorband(C, but, data);
- break;
-
- case UI_BTYPE_CURVE:
- ui_but_paste_curvemapping(C, but);
- break;
-
- default:
- break;
- }
-
- MEM_freeN((void *)buf_paste);
+ BLI_assert((but->flag & UI_BUT_DISABLED) == 0); /* caller should check */
+
+ int buf_paste_len = 0;
+ char *buf_paste;
+ ui_but_get_pasted_text_from_clipboard(&buf_paste, &buf_paste_len);
+
+ bool has_required_data = !(but->poin == NULL && but->rnapoin.data == NULL);
+
+ switch (but->type) {
+ case UI_BTYPE_NUM:
+ case UI_BTYPE_NUM_SLIDER:
+ if (!has_required_data) {
+ break;
+ }
+ if (paste_array && ui_but_has_array_value(but)) {
+ ui_but_paste_numeric_array(C, but, data, buf_paste);
+ }
+ else {
+ ui_but_paste_numeric_value(C, but, data, buf_paste);
+ }
+ break;
+
+ case UI_BTYPE_UNITVEC:
+ if (!has_required_data) {
+ break;
+ }
+ ui_but_paste_normalized_vector(C, but, buf_paste);
+ break;
+
+ case UI_BTYPE_COLOR:
+ if (!has_required_data) {
+ break;
+ }
+ ui_but_paste_color(C, but, buf_paste);
+ break;
+
+ case UI_BTYPE_TEXT:
+ case UI_BTYPE_SEARCH_MENU:
+ if (!has_required_data) {
+ break;
+ }
+ ui_but_paste_text(C, but, data, buf_paste);
+ break;
+
+ case UI_BTYPE_COLORBAND:
+ ui_but_paste_colorband(C, but, data);
+ break;
+
+ case UI_BTYPE_CURVE:
+ ui_but_paste_curvemapping(C, but);
+ break;
+
+ default:
+ break;
+ }
+
+ MEM_freeN((void *)buf_paste);
}
void ui_but_clipboard_free(void)
{
- curvemapping_free_data(&but_copypaste_curve);
+ curvemapping_free_data(&but_copypaste_curve);
}
/** \} */
@@ -2550,61 +2547,63 @@ void ui_but_clipboard_free(void)
static int ui_text_position_from_hidden(uiBut *but, int pos)
{
- const char *strpos, *butstr;
- int i;
+ const char *strpos, *butstr;
+ int i;
- butstr = (but->editstr) ? but->editstr : but->drawstr;
+ butstr = (but->editstr) ? but->editstr : but->drawstr;
- for (i = 0, strpos = butstr; i < pos; i++) {
- strpos = BLI_str_find_next_char_utf8(strpos, NULL);
- }
+ for (i = 0, strpos = butstr; i < pos; i++) {
+ strpos = BLI_str_find_next_char_utf8(strpos, NULL);
+ }
- return (strpos - butstr);
+ return (strpos - butstr);
}
static int ui_text_position_to_hidden(uiBut *but, int pos)
{
- const char *butstr = (but->editstr) ? but->editstr : but->drawstr;
- return BLI_strnlen_utf8(butstr, pos);
+ const char *butstr = (but->editstr) ? but->editstr : but->drawstr;
+ return BLI_strnlen_utf8(butstr, pos);
}
-void ui_but_text_password_hide(char password_str[UI_MAX_PASSWORD_STR], uiBut *but, const bool restore)
+void ui_but_text_password_hide(char password_str[UI_MAX_PASSWORD_STR],
+ uiBut *but,
+ const bool restore)
{
- char *butstr;
+ char *butstr;
- if (!(but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_PASSWORD)) {
- return;
- }
+ if (!(but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_PASSWORD)) {
+ return;
+ }
- butstr = (but->editstr) ? but->editstr : but->drawstr;
+ butstr = (but->editstr) ? but->editstr : but->drawstr;
- if (restore) {
- /* restore original string */
- BLI_strncpy(butstr, password_str, UI_MAX_PASSWORD_STR);
+ if (restore) {
+ /* restore original string */
+ BLI_strncpy(butstr, password_str, UI_MAX_PASSWORD_STR);
- /* remap cursor positions */
- if (but->pos >= 0) {
- but->pos = ui_text_position_from_hidden(but, but->pos);
- but->selsta = ui_text_position_from_hidden(but, but->selsta);
- but->selend = ui_text_position_from_hidden(but, but->selend);
- }
- }
- else {
- /* convert text to hidden text using asterisks (e.g. pass -> ****) */
- const size_t len = BLI_strlen_utf8(butstr);
+ /* remap cursor positions */
+ if (but->pos >= 0) {
+ but->pos = ui_text_position_from_hidden(but, but->pos);
+ but->selsta = ui_text_position_from_hidden(but, but->selsta);
+ but->selend = ui_text_position_from_hidden(but, but->selend);
+ }
+ }
+ else {
+ /* convert text to hidden text using asterisks (e.g. pass -> ****) */
+ const size_t len = BLI_strlen_utf8(butstr);
- /* remap cursor positions */
- if (but->pos >= 0) {
- but->pos = ui_text_position_to_hidden(but, but->pos);
- but->selsta = ui_text_position_to_hidden(but, but->selsta);
- but->selend = ui_text_position_to_hidden(but, but->selend);
- }
+ /* remap cursor positions */
+ if (but->pos >= 0) {
+ but->pos = ui_text_position_to_hidden(but, but->pos);
+ but->selsta = ui_text_position_to_hidden(but, but->selsta);
+ but->selend = ui_text_position_to_hidden(but, but->selend);
+ }
- /* save original string */
- BLI_strncpy(password_str, butstr, UI_MAX_PASSWORD_STR);
- memset(butstr, '*', len);
- butstr[len] = '\0';
- }
+ /* save original string */
+ BLI_strncpy(password_str, butstr, UI_MAX_PASSWORD_STR);
+ memset(butstr, '*', len);
+ butstr[len] = '\0';
+ }
}
/** \} */
@@ -2615,54 +2614,53 @@ void ui_but_text_password_hide(char password_str[UI_MAX_PASSWORD_STR], uiBut *bu
static void ui_textedit_string_clear_and_exit(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- /* most likely NULL, but let's check, and give it temp zero string */
- if (!data->str) {
- data->str = MEM_callocN(1, "temp str");
- }
- data->str[0] = 0;
+ /* most likely NULL, but let's check, and give it temp zero string */
+ if (!data->str) {
+ data->str = MEM_callocN(1, "temp str");
+ }
+ data->str[0] = 0;
- ui_apply_but_TEX(C, but, data);
- button_activate_state(C, but, BUTTON_STATE_EXIT);
+ ui_apply_but_TEX(C, but, data);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
}
static void ui_textedit_string_ensure_max_length(uiBut *but, uiHandleButtonData *data, int maxlen)
{
- BLI_assert(data->is_str_dynamic);
- BLI_assert(data->str == but->editstr);
+ BLI_assert(data->is_str_dynamic);
+ BLI_assert(data->str == but->editstr);
- if (maxlen > data->maxlen) {
- data->str = but->editstr = MEM_reallocN(data->str, sizeof(char) * maxlen);
- data->maxlen = maxlen;
- }
+ if (maxlen > data->maxlen) {
+ data->str = but->editstr = MEM_reallocN(data->str, sizeof(char) * maxlen);
+ data->maxlen = maxlen;
+ }
}
static void ui_textedit_string_set(uiBut *but, uiHandleButtonData *data, const char *str)
{
- if (data->is_str_dynamic) {
- ui_textedit_string_ensure_max_length(but, data, strlen(str) + 1);
- }
+ if (data->is_str_dynamic) {
+ ui_textedit_string_ensure_max_length(but, data, strlen(str) + 1);
+ }
- if (ui_but_is_utf8(but)) {
- BLI_strncpy_utf8(data->str, str, data->maxlen);
- }
- else {
- BLI_strncpy(data->str, str, data->maxlen);
- }
+ if (ui_but_is_utf8(but)) {
+ BLI_strncpy_utf8(data->str, str, data->maxlen);
+ }
+ else {
+ BLI_strncpy(data->str, str, data->maxlen);
+ }
}
-
static bool ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data)
{
- char *str = data->str;
- const int len = strlen(str);
- bool changed = false;
- if (but->selsta != but->selend && len) {
- memmove(str + but->selsta, str + but->selend, (len - but->selend) + 1);
- changed = true;
- }
+ char *str = data->str;
+ const int len = strlen(str);
+ bool changed = false;
+ if (but->selsta != but->selend && len) {
+ memmove(str + but->selsta, str + but->selend, (len - but->selend) + 1);
+ changed = true;
+ }
- but->pos = but->selend = but->selsta;
- return changed;
+ but->pos = but->selend = but->selsta;
+ return changed;
}
/**
@@ -2672,123 +2670,131 @@ 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;
- const float aspect = but->block->aspect;
- const short fstyle_points_prev = fstyle->points;
-
- float startx = but->rect.xmin;
- float starty_dummy = 0.0f;
- char password_str[UI_MAX_PASSWORD_STR];
- /* treat 'str_last' as null terminator for str, no need to modify in-place */
- const char *str = but->editstr, *str_last;
-
- ui_block_to_window_fl(data->region, but->block, &startx, &starty_dummy);
-
- ui_fontscale(&fstyle->points, aspect);
-
- UI_fontstyle_set(fstyle);
-
- if (fstyle->kerning == 1) {
- /* for BLF_width */
- BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- }
-
- ui_but_text_password_hide(password_str, but, false);
-
- if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
- if (but->flag & UI_HAS_ICON) {
- startx += UI_DPI_ICON_SIZE / aspect;
- }
- }
- /* but this extra .05 makes clicks inbetween characters feel nicer */
- startx += ((UI_TEXT_MARGIN_X + 0.05f) * U.widget_unit) / aspect;
-
- /* mouse dragged outside the widget to the left */
- if (x < startx) {
- int i = but->ofs;
-
- str_last = &str[but->ofs];
-
- 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) {
- break;
- }
- }
- else {
- break; /* unlikely but possible */
- }
- }
- but->ofs = i;
- 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;
- }
- }
-
- 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;
+ uiStyle *style = UI_style_get(); // XXX pass on as arg
+ uiFontStyle *fstyle = &style->widget;
+ const float aspect = but->block->aspect;
+ const short fstyle_points_prev = fstyle->points;
+
+ float startx = but->rect.xmin;
+ float starty_dummy = 0.0f;
+ char password_str[UI_MAX_PASSWORD_STR];
+ /* treat 'str_last' as null terminator for str, no need to modify in-place */
+ const char *str = but->editstr, *str_last;
+
+ ui_block_to_window_fl(data->region, but->block, &startx, &starty_dummy);
+
+ ui_fontscale(&fstyle->points, aspect);
+
+ UI_fontstyle_set(fstyle);
+
+ if (fstyle->kerning == 1) {
+ /* for BLF_width */
+ BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
+
+ ui_but_text_password_hide(password_str, but, false);
+
+ if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
+ if (but->flag & UI_HAS_ICON) {
+ startx += UI_DPI_ICON_SIZE / aspect;
+ }
+ }
+ /* but this extra .05 makes clicks inbetween characters feel nicer */
+ startx += ((UI_TEXT_MARGIN_X + 0.05f) * U.widget_unit) / aspect;
+
+ /* mouse dragged outside the widget to the left */
+ if (x < startx) {
+ int i = but->ofs;
+
+ str_last = &str[but->ofs];
+
+ 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) {
+ break;
+ }
+ }
+ else {
+ break; /* unlikely but possible */
+ }
+ }
+ but->ofs = i;
+ 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;
+ }
+ }
+
+ 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; }
+ 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);
+ 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; }
+ if (data->selextend == EXTEND_RIGHT) {
+ but->selend = but->pos;
+ }
+ else if (data->selextend == EXTEND_LEFT) {
+ but->selsta = but->pos;
+ }
- ui_but_update(but);
+ ui_but_update(but);
}
/**
@@ -2796,841 +2802,839 @@ static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data,
*
* For unicode buttons, \a buf is treated as unicode.
*/
-static bool ui_textedit_insert_buf(
- uiBut *but, uiHandleButtonData *data,
- const char *buf, int buf_len)
-{
- int len = strlen(data->str);
- int len_new = len - (but->selend - but->selsta) + 1;
- bool changed = false;
-
- if (data->is_str_dynamic) {
- ui_textedit_string_ensure_max_length(but, data, len_new + buf_len);
- }
-
- if (len_new <= data->maxlen) {
- char *str = data->str;
- size_t step = buf_len;
-
- /* type over the current selection */
- if ((but->selend - but->selsta) > 0) {
- changed = ui_textedit_delete_selection(but, data);
- len = strlen(str);
- }
-
- if ((len + step >= data->maxlen) && (data->maxlen - (len + 1) > 0)) {
- if (ui_but_is_utf8(but)) {
- /* shorten 'step' to a utf8 aligned size that fits */
- BLI_strnlen_utf8_ex(buf, data->maxlen - (len + 1), &step);
- }
- else {
- step = data->maxlen - (len + 1);
- }
- }
-
- if (step && (len + step < data->maxlen)) {
- memmove(&str[but->pos + step], &str[but->pos], (len + 1) - but->pos);
- memcpy(&str[but->pos], buf, step * sizeof(char));
- but->pos += step;
- changed = true;
- }
- }
-
- return changed;
+static bool ui_textedit_insert_buf(uiBut *but,
+ uiHandleButtonData *data,
+ const char *buf,
+ int buf_len)
+{
+ int len = strlen(data->str);
+ int len_new = len - (but->selend - but->selsta) + 1;
+ bool changed = false;
+
+ if (data->is_str_dynamic) {
+ ui_textedit_string_ensure_max_length(but, data, len_new + buf_len);
+ }
+
+ if (len_new <= data->maxlen) {
+ char *str = data->str;
+ size_t step = buf_len;
+
+ /* type over the current selection */
+ if ((but->selend - but->selsta) > 0) {
+ changed = ui_textedit_delete_selection(but, data);
+ len = strlen(str);
+ }
+
+ if ((len + step >= data->maxlen) && (data->maxlen - (len + 1) > 0)) {
+ if (ui_but_is_utf8(but)) {
+ /* shorten 'step' to a utf8 aligned size that fits */
+ BLI_strnlen_utf8_ex(buf, data->maxlen - (len + 1), &step);
+ }
+ else {
+ step = data->maxlen - (len + 1);
+ }
+ }
+
+ if (step && (len + step < data->maxlen)) {
+ memmove(&str[but->pos + step], &str[but->pos], (len + 1) - but->pos);
+ memcpy(&str[but->pos], buf, step * sizeof(char));
+ but->pos += step;
+ changed = true;
+ }
+ }
+
+ return changed;
}
static bool ui_textedit_insert_ascii(uiBut *but, uiHandleButtonData *data, char ascii)
{
- char buf[2] = {ascii, '\0'};
-
- if (ui_but_is_utf8(but) && (BLI_str_utf8_size(buf) == -1)) {
- printf("%s: entering invalid ascii char into an ascii key (%d)\n",
- __func__, (int)(uchar)ascii);
-
- return false;
- }
-
- /* in some cases we want to allow invalid utf8 chars */
- return ui_textedit_insert_buf(but, data, buf, 1);
-}
-
-static void ui_textedit_move(
- uiBut *but, uiHandleButtonData *data, eStrCursorJumpDirection direction,
- const bool select, eStrCursorJumpType jump)
-{
- const char *str = data->str;
- const int len = strlen(str);
- const int pos_prev = but->pos;
- const bool has_sel = (but->selend - but->selsta) > 0;
-
- ui_but_update(but);
-
- /* special case, quit selection and set cursor */
- if (has_sel && !select) {
- if (jump == STRCUR_JUMP_ALL) {
- but->selsta = but->selend = but->pos = direction ? len : 0;
- }
- else {
- if (direction) {
- but->selsta = but->pos = but->selend;
- }
- else {
- but->pos = but->selend = but->selsta;
- }
- }
- data->selextend = EXTEND_NONE;
- }
- else {
- int pos_i = but->pos;
- BLI_str_cursor_step_utf8(str, len, &pos_i, direction, jump, true);
- 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;
- }
- }
- }
- }
-}
-
-static bool ui_textedit_delete(uiBut *but, uiHandleButtonData *data, int direction, eStrCursorJumpType jump)
-{
- char *str = data->str;
- const int len = strlen(str);
-
- bool changed = false;
-
- if (jump == STRCUR_JUMP_ALL) {
- if (len) {
- changed = true;
- }
- str[0] = '\0';
- but->pos = 0;
- }
- else if (direction) { /* delete */
- if ((but->selend - but->selsta) > 0) {
- changed = ui_textedit_delete_selection(but, data);
- }
- else if (but->pos >= 0 && but->pos < len) {
- int pos = but->pos;
- int step;
- BLI_str_cursor_step_utf8(str, len, &pos, direction, jump, true);
- step = pos - but->pos;
- memmove(&str[but->pos], &str[but->pos + step], (len + 1) - (but->pos + step));
- changed = true;
- }
- }
- else { /* backspace */
- if (len != 0) {
- if ((but->selend - but->selsta) > 0) {
- changed = ui_textedit_delete_selection(but, data);
- }
- else if (but->pos > 0) {
- int pos = but->pos;
- int step;
-
- BLI_str_cursor_step_utf8(str, len, &pos, direction, jump, true);
- step = but->pos - pos;
- memmove(&str[but->pos - step], &str[but->pos], (len + 1) - but->pos);
- but->pos -= step;
- changed = true;
- }
- }
- }
-
- return changed;
+ char buf[2] = {ascii, '\0'};
+
+ if (ui_but_is_utf8(but) && (BLI_str_utf8_size(buf) == -1)) {
+ printf(
+ "%s: entering invalid ascii char into an ascii key (%d)\n", __func__, (int)(uchar)ascii);
+
+ return false;
+ }
+
+ /* in some cases we want to allow invalid utf8 chars */
+ return ui_textedit_insert_buf(but, data, buf, 1);
+}
+
+static void ui_textedit_move(uiBut *but,
+ uiHandleButtonData *data,
+ eStrCursorJumpDirection direction,
+ const bool select,
+ eStrCursorJumpType jump)
+{
+ const char *str = data->str;
+ const int len = strlen(str);
+ const int pos_prev = but->pos;
+ const bool has_sel = (but->selend - but->selsta) > 0;
+
+ ui_but_update(but);
+
+ /* special case, quit selection and set cursor */
+ if (has_sel && !select) {
+ if (jump == STRCUR_JUMP_ALL) {
+ but->selsta = but->selend = but->pos = direction ? len : 0;
+ }
+ else {
+ if (direction) {
+ but->selsta = but->pos = but->selend;
+ }
+ else {
+ but->pos = but->selend = but->selsta;
+ }
+ }
+ data->selextend = EXTEND_NONE;
+ }
+ else {
+ int pos_i = but->pos;
+ BLI_str_cursor_step_utf8(str, len, &pos_i, direction, jump, true);
+ 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;
+ }
+ }
+ }
+ }
+}
+
+static bool ui_textedit_delete(uiBut *but,
+ uiHandleButtonData *data,
+ int direction,
+ eStrCursorJumpType jump)
+{
+ char *str = data->str;
+ const int len = strlen(str);
+
+ bool changed = false;
+
+ if (jump == STRCUR_JUMP_ALL) {
+ if (len) {
+ changed = true;
+ }
+ str[0] = '\0';
+ but->pos = 0;
+ }
+ else if (direction) { /* delete */
+ if ((but->selend - but->selsta) > 0) {
+ changed = ui_textedit_delete_selection(but, data);
+ }
+ else if (but->pos >= 0 && but->pos < len) {
+ int pos = but->pos;
+ int step;
+ BLI_str_cursor_step_utf8(str, len, &pos, direction, jump, true);
+ step = pos - but->pos;
+ memmove(&str[but->pos], &str[but->pos + step], (len + 1) - (but->pos + step));
+ changed = true;
+ }
+ }
+ else { /* backspace */
+ if (len != 0) {
+ if ((but->selend - but->selsta) > 0) {
+ changed = ui_textedit_delete_selection(but, data);
+ }
+ else if (but->pos > 0) {
+ int pos = but->pos;
+ int step;
+
+ BLI_str_cursor_step_utf8(str, len, &pos, direction, jump, true);
+ step = but->pos - pos;
+ memmove(&str[but->pos - step], &str[but->pos], (len + 1) - but->pos);
+ but->pos -= step;
+ changed = true;
+ }
+ }
+ }
+
+ return changed;
}
static int ui_textedit_autocomplete(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- char *str;
- int changed;
+ char *str;
+ int changed;
- str = data->str;
+ str = data->str;
- if (data->searchbox) {
- changed = ui_searchbox_autocomplete(C, data->searchbox, but, data->str);
- }
- else {
- changed = but->autocomplete_func(C, str, but->autofunc_arg);
- }
+ if (data->searchbox) {
+ changed = ui_searchbox_autocomplete(C, data->searchbox, but, data->str);
+ }
+ else {
+ changed = but->autocomplete_func(C, str, but->autofunc_arg);
+ }
- but->pos = strlen(str);
- but->selsta = but->selend = but->pos;
+ but->pos = strlen(str);
+ but->selsta = but->selend = but->pos;
- return changed;
+ return changed;
}
/* mode for ui_textedit_copypaste() */
enum {
- UI_TEXTEDIT_PASTE = 1,
- UI_TEXTEDIT_COPY,
- UI_TEXTEDIT_CUT,
+ UI_TEXTEDIT_PASTE = 1,
+ UI_TEXTEDIT_COPY,
+ UI_TEXTEDIT_CUT,
};
static bool ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, const int mode)
{
- char *pbuf;
- bool changed = false;
- int buf_len;
+ char *pbuf;
+ bool changed = false;
+ int buf_len;
- /* paste */
- if (mode == UI_TEXTEDIT_PASTE) {
- /* extract the first line from the clipboard */
- pbuf = WM_clipboard_text_get_firstline(false, &buf_len);
+ /* paste */
+ if (mode == UI_TEXTEDIT_PASTE) {
+ /* extract the first line from the clipboard */
+ pbuf = WM_clipboard_text_get_firstline(false, &buf_len);
- if (pbuf) {
- if (ui_but_is_utf8(but)) {
- buf_len -= BLI_utf8_invalid_strip(pbuf, (size_t)buf_len);
- }
+ if (pbuf) {
+ if (ui_but_is_utf8(but)) {
+ buf_len -= BLI_utf8_invalid_strip(pbuf, (size_t)buf_len);
+ }
- ui_textedit_insert_buf(but, data, pbuf, buf_len);
+ ui_textedit_insert_buf(but, data, pbuf, buf_len);
- changed = true;
+ changed = true;
- MEM_freeN(pbuf);
- }
- }
- /* cut & copy */
- else if (ELEM(mode, UI_TEXTEDIT_COPY, UI_TEXTEDIT_CUT)) {
- /* copy the contents to the copypaste buffer */
- int sellen = but->selend - but->selsta;
- char *buf = MEM_mallocN(sizeof(char) * (sellen + 1), "ui_textedit_copypaste");
+ MEM_freeN(pbuf);
+ }
+ }
+ /* cut & copy */
+ else if (ELEM(mode, UI_TEXTEDIT_COPY, UI_TEXTEDIT_CUT)) {
+ /* copy the contents to the copypaste buffer */
+ int sellen = but->selend - but->selsta;
+ char *buf = MEM_mallocN(sizeof(char) * (sellen + 1), "ui_textedit_copypaste");
- BLI_strncpy(buf, data->str + but->selsta, sellen + 1);
- WM_clipboard_text_set(buf, 0);
- MEM_freeN(buf);
+ BLI_strncpy(buf, data->str + but->selsta, sellen + 1);
+ WM_clipboard_text_set(buf, 0);
+ MEM_freeN(buf);
- /* for cut only, delete the selection afterwards */
- if (mode == UI_TEXTEDIT_CUT) {
- if ((but->selend - but->selsta) > 0) {
- changed = ui_textedit_delete_selection(but, data);
- }
- }
- }
+ /* for cut only, delete the selection afterwards */
+ if (mode == UI_TEXTEDIT_CUT) {
+ if ((but->selend - but->selsta) > 0) {
+ changed = ui_textedit_delete_selection(but, data);
+ }
+ }
+ }
- return changed;
+ return changed;
}
#ifdef WITH_INPUT_IME
/* enable ime, and set up uibut ime data */
static void ui_textedit_ime_begin(wmWindow *win, uiBut *UNUSED(but))
{
- /* XXX Is this really needed? */
- int x, y;
+ /* XXX Is this really needed? */
+ int x, y;
- BLI_assert(win->ime_data == NULL);
+ BLI_assert(win->ime_data == NULL);
- /* enable IME and position to cursor, it's a trick */
- x = win->eventstate->x;
- /* flip y and move down a bit, prevent the IME panel cover the edit button */
- y = win->eventstate->y - 12;
+ /* enable IME and position to cursor, it's a trick */
+ x = win->eventstate->x;
+ /* flip y and move down a bit, prevent the IME panel cover the edit button */
+ y = win->eventstate->y - 12;
- wm_window_IME_begin(win, x, y, 0, 0, true);
+ wm_window_IME_begin(win, x, y, 0, 0, true);
}
/* disable ime, and clear uibut ime data */
static void ui_textedit_ime_end(wmWindow *win, uiBut *UNUSED(but))
{
- wm_window_IME_end(win);
+ wm_window_IME_end(win);
}
void ui_but_ime_reposition(uiBut *but, int x, int y, bool complete)
{
- BLI_assert(but->active);
+ BLI_assert(but->active);
- ui_region_to_window(but->active->region, &x, &y);
- wm_window_IME_begin(but->active->window, x, y - 4, 0, 0, complete);
+ ui_region_to_window(but->active->region, &x, &y);
+ wm_window_IME_begin(but->active->window, x, y - 4, 0, 0, complete);
}
wmIMEData *ui_but_ime_data_get(uiBut *but)
{
- if (but->active && but->active->window) {
- return but->active->window->ime_data;
- }
- else {
- return NULL;
- }
+ if (but->active && but->active->window) {
+ return but->active->window->ime_data;
+ }
+ else {
+ return NULL;
+ }
}
-#endif /* WITH_INPUT_IME */
+#endif /* WITH_INPUT_IME */
static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- wmWindow *win = CTX_wm_window(C);
- int len;
- const bool is_num_but = ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER);
- bool no_zero_strip = false;
+ wmWindow *win = CTX_wm_window(C);
+ int len;
+ const bool is_num_but = ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER);
+ bool no_zero_strip = false;
- if (data->str) {
- MEM_freeN(data->str);
- data->str = NULL;
- }
+ if (data->str) {
+ MEM_freeN(data->str);
+ data->str = NULL;
+ }
#ifdef USE_DRAG_MULTINUM
- /* this can happen from multi-drag */
- if (data->applied_interactive) {
- /* remove any small changes so canceling edit doesn't restore invalid value: T40538 */
- data->cancel = true;
- ui_apply_but(C, but->block, but, data, true);
- data->cancel = false;
-
- data->applied_interactive = false;
- }
+ /* this can happen from multi-drag */
+ if (data->applied_interactive) {
+ /* remove any small changes so canceling edit doesn't restore invalid value: T40538 */
+ data->cancel = true;
+ ui_apply_but(C, but->block, but, data, true);
+ data->cancel = false;
+
+ data->applied_interactive = false;
+ }
#endif
#ifdef USE_ALLSELECT
- if (is_num_but) {
- if (IS_ALLSELECT_EVENT(win->eventstate)) {
- data->select_others.is_enabled = true;
- data->select_others.is_copy = true;
-
- }
- }
+ if (is_num_but) {
+ if (IS_ALLSELECT_EVENT(win->eventstate)) {
+ data->select_others.is_enabled = true;
+ data->select_others.is_copy = true;
+ }
+ }
#endif
- /* retrieve string */
- data->maxlen = ui_but_string_get_max_length(but);
- if (data->maxlen != 0) {
- data->str = MEM_callocN(sizeof(char) * data->maxlen, "textedit str");
- /* We do not want to truncate precision to default here, it's nice to show value,
- * not to edit it - way too much precision is lost then. */
- ui_but_string_get_ex(but, data->str, data->maxlen, UI_PRECISION_FLOAT_MAX, true, &no_zero_strip);
- }
- else {
- data->is_str_dynamic = true;
- data->str = ui_but_string_get_dynamic(but, &data->maxlen);
- }
-
- if (ui_but_is_float(but) && !ui_but_is_unit(but) && !ui_but_anim_expression_get(but, NULL, 0) && !no_zero_strip) {
- BLI_str_rstrip_float_zero(data->str, '\0');
- }
-
- if (is_num_but) {
- BLI_assert(data->is_str_dynamic == false);
- ui_but_convert_to_unit_alt_name(but, data->str, data->maxlen);
- }
-
- /* won't change from now on */
- len = strlen(data->str);
-
- data->origstr = BLI_strdupn(data->str, len);
- data->selextend = EXTEND_NONE;
- data->selstartx = 0.0f;
-
- /* set cursor pos to the end of the text */
- but->editstr = data->str;
- but->pos = len;
- but->selsta = 0;
- but->selend = len;
-
- /* optional searchbox */
- if (but->type == UI_BTYPE_SEARCH_MENU) {
- data->searchbox = but->search_create_func(C, data->region, but);
- ui_searchbox_update(C, data->searchbox, but, true); /* true = reset */
- }
-
- /* reset alert flag (avoid confusion, will refresh on exit) */
- but->flag &= ~UI_BUT_REDALERT;
-
- ui_but_update(but);
-
- WM_cursor_modal_set(win, BC_TEXTEDITCURSOR);
+ /* retrieve string */
+ data->maxlen = ui_but_string_get_max_length(but);
+ if (data->maxlen != 0) {
+ data->str = MEM_callocN(sizeof(char) * data->maxlen, "textedit str");
+ /* We do not want to truncate precision to default here, it's nice to show value,
+ * not to edit it - way too much precision is lost then. */
+ ui_but_string_get_ex(
+ but, data->str, data->maxlen, UI_PRECISION_FLOAT_MAX, true, &no_zero_strip);
+ }
+ else {
+ data->is_str_dynamic = true;
+ data->str = ui_but_string_get_dynamic(but, &data->maxlen);
+ }
+
+ if (ui_but_is_float(but) && !ui_but_is_unit(but) && !ui_but_anim_expression_get(but, NULL, 0) &&
+ !no_zero_strip) {
+ BLI_str_rstrip_float_zero(data->str, '\0');
+ }
+
+ if (is_num_but) {
+ BLI_assert(data->is_str_dynamic == false);
+ ui_but_convert_to_unit_alt_name(but, data->str, data->maxlen);
+ }
+
+ /* won't change from now on */
+ len = strlen(data->str);
+
+ data->origstr = BLI_strdupn(data->str, len);
+ data->selextend = EXTEND_NONE;
+ data->selstartx = 0.0f;
+
+ /* set cursor pos to the end of the text */
+ but->editstr = data->str;
+ but->pos = len;
+ but->selsta = 0;
+ but->selend = len;
+
+ /* optional searchbox */
+ if (but->type == UI_BTYPE_SEARCH_MENU) {
+ data->searchbox = but->search_create_func(C, data->region, but);
+ ui_searchbox_update(C, data->searchbox, but, true); /* true = reset */
+ }
+
+ /* reset alert flag (avoid confusion, will refresh on exit) */
+ but->flag &= ~UI_BUT_REDALERT;
+
+ ui_but_update(but);
+
+ WM_cursor_modal_set(win, BC_TEXTEDITCURSOR);
#ifdef WITH_INPUT_IME
- if (is_num_but == false && BLT_lang_is_ime_supported()) {
- ui_textedit_ime_begin(win, but);
- }
+ if (is_num_but == false && BLT_lang_is_ime_supported()) {
+ ui_textedit_ime_begin(win, but);
+ }
#endif
}
static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- wmWindow *win = CTX_wm_window(C);
+ wmWindow *win = CTX_wm_window(C);
- if (but) {
- if (ui_but_is_utf8(but)) {
- int strip = BLI_utf8_invalid_strip(but->editstr, strlen(but->editstr));
- /* not a file?, strip non utf-8 chars */
- if (strip) {
- /* wont happen often so isn't that annoying to keep it here for a while */
- printf("%s: invalid utf8 - stripped chars %d\n", __func__, strip);
- }
- }
+ if (but) {
+ if (ui_but_is_utf8(but)) {
+ int strip = BLI_utf8_invalid_strip(but->editstr, strlen(but->editstr));
+ /* not a file?, strip non utf-8 chars */
+ if (strip) {
+ /* wont happen often so isn't that annoying to keep it here for a while */
+ printf("%s: invalid utf8 - stripped chars %d\n", __func__, strip);
+ }
+ }
- if (data->searchbox) {
- if (data->cancel == false) {
- if ((ui_searchbox_apply(but, data->searchbox) == false) &&
- (ui_searchbox_find_index(data->searchbox, but->editstr) == -1))
- {
- data->cancel = true;
+ if (data->searchbox) {
+ if (data->cancel == false) {
+ if ((ui_searchbox_apply(but, data->searchbox) == false) &&
+ (ui_searchbox_find_index(data->searchbox, but->editstr) == -1)) {
+ data->cancel = true;
- /* ensure menu (popup) too is closed! */
- data->escapecancel = true;
- }
- }
+ /* ensure menu (popup) too is closed! */
+ data->escapecancel = true;
+ }
+ }
- ui_searchbox_free(C, data->searchbox);
- data->searchbox = NULL;
- }
+ ui_searchbox_free(C, data->searchbox);
+ data->searchbox = NULL;
+ }
- but->editstr = NULL;
- but->pos = -1;
- }
+ but->editstr = NULL;
+ but->pos = -1;
+ }
- WM_cursor_modal_restore(win);
+ WM_cursor_modal_restore(win);
#ifdef WITH_INPUT_IME
- if (win->ime_data) {
- ui_textedit_ime_end(win, but);
- }
+ if (win->ime_data) {
+ ui_textedit_ime_end(win, but);
+ }
#endif
}
static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonData *data)
{
- uiBut *but;
-
- /* label and roundbox can overlap real buttons (backdrops...) */
- if (ELEM(actbut->type, UI_BTYPE_LABEL, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_ROUNDBOX, UI_BTYPE_LISTBOX)) {
- return;
- }
-
- for (but = actbut->next; but; but = but->next) {
- if (ui_but_is_editable_as_text(but)) {
- if (!(but->flag & UI_BUT_DISABLED)) {
- data->postbut = but;
- data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
- return;
- }
- }
- }
- for (but = block->buttons.first; but != actbut; but = but->next) {
- if (ui_but_is_editable_as_text(but)) {
- if (!(but->flag & UI_BUT_DISABLED)) {
- data->postbut = but;
- data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
- return;
- }
- }
- }
+ uiBut *but;
+
+ /* label and roundbox can overlap real buttons (backdrops...) */
+ if (ELEM(actbut->type,
+ UI_BTYPE_LABEL,
+ UI_BTYPE_SEPR,
+ UI_BTYPE_SEPR_LINE,
+ UI_BTYPE_ROUNDBOX,
+ UI_BTYPE_LISTBOX)) {
+ return;
+ }
+
+ for (but = actbut->next; but; but = but->next) {
+ if (ui_but_is_editable_as_text(but)) {
+ if (!(but->flag & UI_BUT_DISABLED)) {
+ data->postbut = but;
+ data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
+ return;
+ }
+ }
+ }
+ for (but = block->buttons.first; but != actbut; but = but->next) {
+ if (ui_but_is_editable_as_text(but)) {
+ if (!(but->flag & UI_BUT_DISABLED)) {
+ data->postbut = but;
+ data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
+ return;
+ }
+ }
+ }
}
static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonData *data)
{
- uiBut *but;
-
- /* label and roundbox can overlap real buttons (backdrops...) */
- if (ELEM(actbut->type, UI_BTYPE_LABEL, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_ROUNDBOX, UI_BTYPE_LISTBOX)) {
- return;
- }
-
- for (but = actbut->prev; but; but = but->prev) {
- if (ui_but_is_editable_as_text(but)) {
- if (!(but->flag & UI_BUT_DISABLED)) {
- data->postbut = but;
- data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
- return;
- }
- }
- }
- for (but = block->buttons.last; but != actbut; but = but->prev) {
- if (ui_but_is_editable_as_text(but)) {
- if (!(but->flag & UI_BUT_DISABLED)) {
- data->postbut = but;
- data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
- return;
- }
- }
- }
+ uiBut *but;
+
+ /* label and roundbox can overlap real buttons (backdrops...) */
+ if (ELEM(actbut->type,
+ UI_BTYPE_LABEL,
+ UI_BTYPE_SEPR,
+ UI_BTYPE_SEPR_LINE,
+ UI_BTYPE_ROUNDBOX,
+ UI_BTYPE_LISTBOX)) {
+ return;
+ }
+
+ for (but = actbut->prev; but; but = but->prev) {
+ if (ui_but_is_editable_as_text(but)) {
+ if (!(but->flag & UI_BUT_DISABLED)) {
+ data->postbut = but;
+ data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
+ return;
+ }
+ }
+ }
+ for (but = block->buttons.last; but != actbut; but = but->prev) {
+ if (ui_but_is_editable_as_text(but)) {
+ if (!(but->flag & UI_BUT_DISABLED)) {
+ data->postbut = but;
+ data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
+ return;
+ }
+ }
+ }
}
-
static void ui_do_but_textedit(
- bContext *C, uiBlock *block, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
+ bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
- int retval = WM_UI_HANDLER_CONTINUE;
- bool changed = false, inbox = false, update = false;
+ int retval = WM_UI_HANDLER_CONTINUE;
+ bool changed = false, inbox = false, update = false;
#ifdef WITH_INPUT_IME
- wmWindow *win = CTX_wm_window(C);
- wmIMEData *ime_data = win->ime_data;
- bool is_ime_composing = ime_data && ime_data->is_ime_composing;
+ wmWindow *win = CTX_wm_window(C);
+ wmIMEData *ime_data = win->ime_data;
+ bool is_ime_composing = ime_data && ime_data->is_ime_composing;
#else
- bool is_ime_composing = false;
+ bool is_ime_composing = false;
#endif
- switch (event->type) {
- case MOUSEMOVE:
- case MOUSEPAN:
- if (data->searchbox) {
+ switch (event->type) {
+ case MOUSEMOVE:
+ case MOUSEPAN:
+ if (data->searchbox) {
#ifdef USE_KEYNAV_LIMIT
- if ((event->type == MOUSEMOVE) && ui_mouse_motion_keynav_test(&data->searchbox_keynav_state, event)) {
- /* pass */
- }
- else {
- ui_searchbox_event(C, data->searchbox, but, event);
- }
+ if ((event->type == MOUSEMOVE) &&
+ ui_mouse_motion_keynav_test(&data->searchbox_keynav_state, event)) {
+ /* pass */
+ }
+ else {
+ ui_searchbox_event(C, data->searchbox, but, event);
+ }
#else
- ui_searchbox_event(C, data->searchbox, but, event);
+ ui_searchbox_event(C, data->searchbox, but, event);
#endif
- }
+ }
- break;
- case RIGHTMOUSE:
- case ESCKEY:
- if (event->val == KM_PRESS) {
+ break;
+ case RIGHTMOUSE:
+ case ESCKEY:
+ if (event->val == KM_PRESS) {
#ifdef WITH_INPUT_IME
- /* skips button handling since it is not wanted */
- if (is_ime_composing) {
- break;
- }
+ /* skips button handling since it is not wanted */
+ if (is_ime_composing) {
+ break;
+ }
#endif
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- retval = WM_UI_HANDLER_BREAK;
- }
- break;
- case LEFTMOUSE:
- {
- bool had_selection = but->selsta != but->selend;
-
- /* exit on LMB only on RELEASE for searchbox, to mimic other popups,
- * and allow multiple menu levels */
- if (data->searchbox) {
- inbox = ui_searchbox_inside(data->searchbox, event->x, event->y);
- }
-
- /* for double click: we do a press again for when you first click on button
- * (selects all text, no cursor pos) */
- if (event->val == KM_PRESS || event->val == KM_DBL_CLICK) {
- float mx, my;
-
- mx = event->x;
- my = event->y;
- ui_window_to_block_fl(data->region, block, &mx, &my);
-
- 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;
-
- button_activate_state(C, but, BUTTON_STATE_TEXT_SELECTING);
- retval = WM_UI_HANDLER_BREAK;
- }
- else if (inbox == false) {
- /* if searchbox, click outside will cancel */
- if (data->searchbox) {
- data->cancel = data->escapecancel = true;
- }
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- retval = WM_UI_HANDLER_BREAK;
- }
- }
-
- /* only select a word in button if there was no selection before */
- if (event->val == KM_DBL_CLICK && had_selection == false) {
- ui_textedit_move(but, data, STRCUR_DIR_PREV, false, STRCUR_JUMP_DELIM);
- ui_textedit_move(but, data, STRCUR_DIR_NEXT, true, STRCUR_JUMP_DELIM);
- retval = WM_UI_HANDLER_BREAK;
- changed = true;
- }
- else if (inbox) {
- /* if we allow activation on key press,
- * it gives problems launching operators T35713. */
- if (event->val == KM_RELEASE) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- retval = WM_UI_HANDLER_BREAK;
- }
- }
- break;
- }
- }
-
- if (event->val == KM_PRESS && !is_ime_composing) {
- switch (event->type) {
- case VKEY:
- case XKEY:
- case CKEY:
- if (IS_EVENT_MOD(event, ctrl, oskey)) {
- if (event->type == VKEY) {
- changed = ui_textedit_copypaste(but, data, UI_TEXTEDIT_PASTE);
- }
- else if (event->type == CKEY) {
- changed = ui_textedit_copypaste(but, data, UI_TEXTEDIT_COPY);
- }
- else if (event->type == XKEY) {
- changed = ui_textedit_copypaste(but, data, UI_TEXTEDIT_CUT);
- }
-
- retval = WM_UI_HANDLER_BREAK;
- }
- break;
- case RIGHTARROWKEY:
- ui_textedit_move(
- but, data, STRCUR_DIR_NEXT,
- event->shift != 0, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
- retval = WM_UI_HANDLER_BREAK;
- break;
- case LEFTARROWKEY:
- ui_textedit_move(
- but, data, STRCUR_DIR_PREV,
- event->shift != 0, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
- retval = WM_UI_HANDLER_BREAK;
- break;
- case WHEELDOWNMOUSE:
- case DOWNARROWKEY:
- if (data->searchbox) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ break;
+ case LEFTMOUSE: {
+ bool had_selection = but->selsta != but->selend;
+
+ /* exit on LMB only on RELEASE for searchbox, to mimic other popups,
+ * and allow multiple menu levels */
+ if (data->searchbox) {
+ inbox = ui_searchbox_inside(data->searchbox, event->x, event->y);
+ }
+
+ /* for double click: we do a press again for when you first click on button
+ * (selects all text, no cursor pos) */
+ if (event->val == KM_PRESS || event->val == KM_DBL_CLICK) {
+ float mx, my;
+
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block_fl(data->region, block, &mx, &my);
+
+ 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;
+
+ button_activate_state(C, but, BUTTON_STATE_TEXT_SELECTING);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (inbox == false) {
+ /* if searchbox, click outside will cancel */
+ if (data->searchbox) {
+ data->cancel = data->escapecancel = true;
+ }
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ /* only select a word in button if there was no selection before */
+ if (event->val == KM_DBL_CLICK && had_selection == false) {
+ ui_textedit_move(but, data, STRCUR_DIR_PREV, false, STRCUR_JUMP_DELIM);
+ ui_textedit_move(but, data, STRCUR_DIR_NEXT, true, STRCUR_JUMP_DELIM);
+ retval = WM_UI_HANDLER_BREAK;
+ changed = true;
+ }
+ else if (inbox) {
+ /* if we allow activation on key press,
+ * it gives problems launching operators T35713. */
+ if (event->val == KM_RELEASE) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
+ break;
+ }
+ }
+
+ if (event->val == KM_PRESS && !is_ime_composing) {
+ switch (event->type) {
+ case VKEY:
+ case XKEY:
+ case CKEY:
+ if (IS_EVENT_MOD(event, ctrl, oskey)) {
+ if (event->type == VKEY) {
+ changed = ui_textedit_copypaste(but, data, UI_TEXTEDIT_PASTE);
+ }
+ else if (event->type == CKEY) {
+ changed = ui_textedit_copypaste(but, data, UI_TEXTEDIT_COPY);
+ }
+ else if (event->type == XKEY) {
+ changed = ui_textedit_copypaste(but, data, UI_TEXTEDIT_CUT);
+ }
+
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ break;
+ case RIGHTARROWKEY:
+ ui_textedit_move(but,
+ data,
+ STRCUR_DIR_NEXT,
+ event->shift != 0,
+ event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
+ retval = WM_UI_HANDLER_BREAK;
+ break;
+ case LEFTARROWKEY:
+ ui_textedit_move(but,
+ data,
+ STRCUR_DIR_PREV,
+ event->shift != 0,
+ event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
+ retval = WM_UI_HANDLER_BREAK;
+ break;
+ case WHEELDOWNMOUSE:
+ case DOWNARROWKEY:
+ if (data->searchbox) {
#ifdef USE_KEYNAV_LIMIT
- ui_mouse_motion_keynav_init(&data->searchbox_keynav_state, event);
+ ui_mouse_motion_keynav_init(&data->searchbox_keynav_state, event);
#endif
- ui_searchbox_event(C, data->searchbox, but, event);
- break;
- }
- if (event->type == WHEELDOWNMOUSE) {
- break;
- }
- ATTR_FALLTHROUGH;
- case 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:
- if (data->searchbox) {
+ ui_searchbox_event(C, data->searchbox, but, event);
+ break;
+ }
+ if (event->type == WHEELDOWNMOUSE) {
+ break;
+ }
+ ATTR_FALLTHROUGH;
+ case 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:
+ if (data->searchbox) {
#ifdef USE_KEYNAV_LIMIT
- ui_mouse_motion_keynav_init(&data->searchbox_keynav_state, event);
+ ui_mouse_motion_keynav_init(&data->searchbox_keynav_state, event);
#endif
- ui_searchbox_event(C, data->searchbox, but, event);
- break;
- }
- if (event->type == WHEELUPMOUSE) {
- break;
- }
- ATTR_FALLTHROUGH;
- case 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:
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- retval = WM_UI_HANDLER_BREAK;
- break;
- case DELKEY:
- changed = ui_textedit_delete(
- but, data, 1,
- event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
- retval = WM_UI_HANDLER_BREAK;
- break;
-
- case BACKSPACEKEY:
- changed = ui_textedit_delete(
- but, data, 0,
- event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
- retval = WM_UI_HANDLER_BREAK;
- break;
-
- case AKEY:
-
- /* Ctrl + A: Select all */
+ ui_searchbox_event(C, data->searchbox, but, event);
+ break;
+ }
+ if (event->type == WHEELUPMOUSE) {
+ break;
+ }
+ ATTR_FALLTHROUGH;
+ case 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:
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ retval = WM_UI_HANDLER_BREAK;
+ break;
+ case DELKEY:
+ changed = ui_textedit_delete(
+ but, data, 1, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
+ retval = WM_UI_HANDLER_BREAK;
+ break;
+
+ case BACKSPACEKEY:
+ changed = ui_textedit_delete(
+ but, data, 0, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
+ retval = WM_UI_HANDLER_BREAK;
+ break;
+
+ case AKEY:
+
+ /* Ctrl + A: Select all */
#if defined(__APPLE__)
- /* OSX uses cmd-a systemwide, so add it */
- if ((event->oskey && !IS_EVENT_MOD(event, shift, alt, ctrl)) ||
- (event->ctrl && !IS_EVENT_MOD(event, shift, alt, oskey)))
+ /* OSX uses cmd-a systemwide, so add it */
+ if ((event->oskey && !IS_EVENT_MOD(event, shift, alt, ctrl)) ||
+ (event->ctrl && !IS_EVENT_MOD(event, shift, alt, oskey)))
#else
- if (event->ctrl && !IS_EVENT_MOD(event, shift, alt, oskey))
+ if (event->ctrl && !IS_EVENT_MOD(event, shift, alt, oskey))
#endif
- {
- ui_textedit_move(
- but, data, STRCUR_DIR_PREV,
- false, STRCUR_JUMP_ALL);
- ui_textedit_move(
- but, data, STRCUR_DIR_NEXT,
- true, STRCUR_JUMP_ALL);
- retval = WM_UI_HANDLER_BREAK;
- }
- break;
-
- case 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);
- changed = autocomplete != AUTOCOMPLETE_NO_MATCH;
-
- if (autocomplete == AUTOCOMPLETE_FULL_MATCH) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- }
- /* the hotkey here is not well defined, was G.qual so we check all */
- else if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) {
- ui_textedit_prev_but(block, but, data);
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- else {
- ui_textedit_next_but(block, but, data);
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- retval = WM_UI_HANDLER_BREAK;
- break;
- }
-
- if ((event->ascii || event->utf8_buf[0]) &&
- (retval == WM_UI_HANDLER_CONTINUE)
+ {
+ ui_textedit_move(but, data, STRCUR_DIR_PREV, false, STRCUR_JUMP_ALL);
+ ui_textedit_move(but, data, STRCUR_DIR_NEXT, true, STRCUR_JUMP_ALL);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ break;
+
+ case 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);
+ changed = autocomplete != AUTOCOMPLETE_NO_MATCH;
+
+ if (autocomplete == AUTOCOMPLETE_FULL_MATCH) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+ /* the hotkey here is not well defined, was G.qual so we check all */
+ else if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) {
+ ui_textedit_prev_but(block, but, data);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else {
+ ui_textedit_next_but(block, but, data);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ retval = WM_UI_HANDLER_BREAK;
+ break;
+ }
+
+ if ((event->ascii || event->utf8_buf[0]) && (retval == WM_UI_HANDLER_CONTINUE)
#ifdef WITH_INPUT_IME
- &&
- !is_ime_composing &&
- (!WM_event_is_ime_switch(event) || !BLT_lang_is_ime_supported())
+ && !is_ime_composing && (!WM_event_is_ime_switch(event) || !BLT_lang_is_ime_supported())
#endif
- )
- {
- char ascii = event->ascii;
- const char *utf8_buf = event->utf8_buf;
-
- /* 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 == ',') {
- ascii = '.';
- utf8_buf = NULL; /* force ascii fallback */
- }
- }
-
- 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");
- changed = ui_textedit_insert_buf(but, data, event->utf8_buf, utf8_buf_len);
- }
- else {
- changed = ui_textedit_insert_ascii(but, data, ascii);
- }
-
- retval = WM_UI_HANDLER_BREAK;
-
- }
- /* textbutton with this flag: do live update (e.g. for search buttons) */
- if (but->flag & UI_BUT_TEXTEDIT_UPDATE) {
- update = true;
- }
- }
+ ) {
+ char ascii = event->ascii;
+ const char *utf8_buf = event->utf8_buf;
+
+ /* 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 == ',') {
+ ascii = '.';
+ utf8_buf = NULL; /* force ascii fallback */
+ }
+ }
+
+ 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");
+ changed = ui_textedit_insert_buf(but, data, event->utf8_buf, utf8_buf_len);
+ }
+ else {
+ changed = ui_textedit_insert_ascii(but, data, ascii);
+ }
+
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ /* textbutton with this flag: do live update (e.g. for search buttons) */
+ if (but->flag & UI_BUT_TEXTEDIT_UPDATE) {
+ update = true;
+ }
+ }
#ifdef WITH_INPUT_IME
- if (event->type == WM_IME_COMPOSITE_START || event->type == WM_IME_COMPOSITE_EVENT) {
- changed = true;
-
- if (event->type == WM_IME_COMPOSITE_START && but->selend > but->selsta) {
- ui_textedit_delete_selection(but, data);
- }
- if (event->type == WM_IME_COMPOSITE_EVENT && ime_data->result_len) {
- ui_textedit_insert_buf(
- but, data,
- ime_data->str_result,
- ime_data->result_len);
- }
- }
- else if (event->type == WM_IME_COMPOSITE_END) {
- changed = true;
- }
+ if (event->type == WM_IME_COMPOSITE_START || event->type == WM_IME_COMPOSITE_EVENT) {
+ changed = true;
+
+ if (event->type == WM_IME_COMPOSITE_START && but->selend > but->selsta) {
+ ui_textedit_delete_selection(but, data);
+ }
+ if (event->type == WM_IME_COMPOSITE_EVENT && ime_data->result_len) {
+ ui_textedit_insert_buf(but, data, ime_data->str_result, ime_data->result_len);
+ }
+ }
+ else if (event->type == WM_IME_COMPOSITE_END) {
+ changed = true;
+ }
#endif
- if (changed) {
- /* 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);
- }
- else {
- ui_but_update_edited(but);
- }
- but->changed = true;
+ if (changed) {
+ /* 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);
+ }
+ else {
+ ui_but_update_edited(but);
+ }
+ but->changed = true;
- if (data->searchbox) {
- ui_searchbox_update(C, data->searchbox, but, true); /* true = reset */
- }
- }
+ if (data->searchbox) {
+ ui_searchbox_update(C, data->searchbox, but, true); /* true = reset */
+ }
+ }
- if (changed || (retval == WM_UI_HANDLER_BREAK)) {
- ED_region_tag_redraw(data->region);
- }
+ if (changed || (retval == WM_UI_HANDLER_BREAK)) {
+ ED_region_tag_redraw(data->region);
+ }
}
static void ui_do_but_textedit_select(
- bContext *C, uiBlock *block, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
- int mx, my, retval = WM_UI_HANDLER_CONTINUE;
-
- switch (event->type) {
- case MOUSEMOVE:
- {
- mx = event->x;
- my = event->y;
- ui_window_to_block(data->region, block, &mx, &my);
-
- ui_textedit_set_cursor_select(but, data, event->x);
- retval = WM_UI_HANDLER_BREAK;
- break;
- }
- case LEFTMOUSE:
- if (event->val == KM_RELEASE) {
- button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
- }
- retval = WM_UI_HANDLER_BREAK;
- break;
- }
-
- if (retval == WM_UI_HANDLER_BREAK) {
- ui_but_update(but);
- ED_region_tag_redraw(data->region);
- }
+ bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ int mx, my, retval = WM_UI_HANDLER_CONTINUE;
+
+ switch (event->type) {
+ case MOUSEMOVE: {
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ ui_textedit_set_cursor_select(but, data, event->x);
+ retval = WM_UI_HANDLER_BREAK;
+ break;
+ }
+ case LEFTMOUSE:
+ if (event->val == KM_RELEASE) {
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ }
+ retval = WM_UI_HANDLER_BREAK;
+ break;
+ }
+
+ if (retval == WM_UI_HANDLER_BREAK) {
+ ui_but_update(but);
+ ED_region_tag_redraw(data->region);
+ }
}
/** \} */
@@ -3641,62 +3645,66 @@ static void ui_do_but_textedit_select(
static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data)
{
- if (but->type == UI_BTYPE_CURVE) {
- but->editcumap = (CurveMapping *)but->poin;
- }
- else if (but->type == UI_BTYPE_COLORBAND) {
- data->coba = (ColorBand *)but->poin;
- but->editcoba = data->coba;
- }
- else if (ELEM(but->type, UI_BTYPE_UNITVEC, UI_BTYPE_HSVCUBE, UI_BTYPE_HSVCIRCLE, UI_BTYPE_COLOR)) {
- ui_but_v3_get(but, data->origvec);
- copy_v3_v3(data->vec, data->origvec);
- but->editvec = data->vec;
- }
- else {
- float softrange, softmin, softmax;
-
- data->startvalue = ui_but_value_get(but);
- data->origvalue = data->startvalue;
- data->value = data->origvalue;
- but->editval = &data->value;
-
- softmin = but->softmin;
- softmax = but->softmax;
- softrange = softmax - softmin;
-
- data->dragfstart = (softrange == 0.0f) ? 0.0f : ((float)data->value - softmin) / softrange;
- data->dragf = data->dragfstart;
- }
-
- data->dragchange = false;
- data->draglock = true;
+ if (but->type == UI_BTYPE_CURVE) {
+ but->editcumap = (CurveMapping *)but->poin;
+ }
+ else if (but->type == UI_BTYPE_COLORBAND) {
+ data->coba = (ColorBand *)but->poin;
+ but->editcoba = data->coba;
+ }
+ else if (ELEM(but->type,
+ UI_BTYPE_UNITVEC,
+ UI_BTYPE_HSVCUBE,
+ UI_BTYPE_HSVCIRCLE,
+ UI_BTYPE_COLOR)) {
+ ui_but_v3_get(but, data->origvec);
+ copy_v3_v3(data->vec, data->origvec);
+ but->editvec = data->vec;
+ }
+ else {
+ float softrange, softmin, softmax;
+
+ data->startvalue = ui_but_value_get(but);
+ data->origvalue = data->startvalue;
+ data->value = data->origvalue;
+ but->editval = &data->value;
+
+ softmin = but->softmin;
+ softmax = but->softmax;
+ softrange = softmax - softmin;
+
+ data->dragfstart = (softrange == 0.0f) ? 0.0f : ((float)data->value - softmin) / softrange;
+ data->dragf = data->dragfstart;
+ }
+
+ data->dragchange = false;
+ data->draglock = true;
}
static void ui_numedit_end(uiBut *but, uiHandleButtonData *data)
{
- but->editval = NULL;
- but->editvec = NULL;
- but->editcoba = NULL;
- but->editcumap = NULL;
+ but->editval = NULL;
+ but->editvec = NULL;
+ but->editcoba = NULL;
+ but->editcumap = NULL;
- data->dragstartx = 0;
- data->draglastx = 0;
- data->dragchange = false;
- data->dragcbd = NULL;
- data->dragsel = 0;
+ data->dragstartx = 0;
+ data->draglastx = 0;
+ data->dragchange = false;
+ data->dragcbd = NULL;
+ data->dragsel = 0;
}
static void ui_numedit_apply(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data)
{
- if (data->interactive) {
- ui_apply_but(C, block, but, data, true);
- }
- else {
- ui_but_update(but);
- }
+ if (data->interactive) {
+ ui_apply_but(C, block, but, data, true);
+ }
+ else {
+ ui_but_update(but);
+ }
- ED_region_tag_redraw(data->region);
+ ED_region_tag_redraw(data->region);
}
/** \} */
@@ -3707,131 +3715,133 @@ static void ui_numedit_apply(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- uiBlockCreateFunc func = NULL;
- uiBlockHandleCreateFunc handlefunc = NULL;
- uiMenuCreateFunc menufunc = NULL;
- uiMenuCreateFunc popoverfunc = NULL;
- void *arg = NULL;
-
- switch (but->type) {
- case UI_BTYPE_BLOCK:
- case UI_BTYPE_PULLDOWN:
- if (but->menu_create_func) {
- menufunc = but->menu_create_func;
- arg = but->poin;
- }
- else {
- func = but->block_create_func;
- arg = but->poin ? but->poin : but->func_argN;
- }
- break;
- case UI_BTYPE_MENU:
- case UI_BTYPE_POPOVER:
- BLI_assert(but->menu_create_func);
- if ((but->type == UI_BTYPE_POPOVER) || ui_but_menu_draw_as_popover(but)) {
- popoverfunc = but->menu_create_func;
- }
- else {
- menufunc = but->menu_create_func;
- }
- arg = but->poin;
- break;
- case UI_BTYPE_COLOR:
- ui_but_v3_get(but, data->origvec);
- copy_v3_v3(data->vec, data->origvec);
- but->editvec = data->vec;
-
- handlefunc = ui_block_func_COLOR;
- arg = but;
- break;
-
- /* quiet warnings for unhandled types */
- default:
- break;
- }
-
- if (func || handlefunc) {
- data->menu = ui_popup_block_create(C, data->region, but, func, handlefunc, arg);
- if (but->block->handle) {
- data->menu->popup = but->block->handle->popup;
- }
- }
- else if (menufunc) {
- data->menu = ui_popup_menu_create(C, data->region, but, menufunc, arg);
- if (but->block->handle) {
- data->menu->popup = but->block->handle->popup;
- }
- }
- else if (popoverfunc) {
- data->menu = ui_popover_panel_create(C, data->region, but, popoverfunc, arg);
- if (but->block->handle) {
- data->menu->popup = but->block->handle->popup;
- }
- }
+ uiBlockCreateFunc func = NULL;
+ uiBlockHandleCreateFunc handlefunc = NULL;
+ uiMenuCreateFunc menufunc = NULL;
+ uiMenuCreateFunc popoverfunc = NULL;
+ void *arg = NULL;
+
+ switch (but->type) {
+ case UI_BTYPE_BLOCK:
+ case UI_BTYPE_PULLDOWN:
+ if (but->menu_create_func) {
+ menufunc = but->menu_create_func;
+ arg = but->poin;
+ }
+ else {
+ func = but->block_create_func;
+ arg = but->poin ? but->poin : but->func_argN;
+ }
+ break;
+ case UI_BTYPE_MENU:
+ case UI_BTYPE_POPOVER:
+ BLI_assert(but->menu_create_func);
+ if ((but->type == UI_BTYPE_POPOVER) || ui_but_menu_draw_as_popover(but)) {
+ popoverfunc = but->menu_create_func;
+ }
+ else {
+ menufunc = but->menu_create_func;
+ }
+ arg = but->poin;
+ break;
+ case UI_BTYPE_COLOR:
+ ui_but_v3_get(but, data->origvec);
+ copy_v3_v3(data->vec, data->origvec);
+ but->editvec = data->vec;
+
+ handlefunc = ui_block_func_COLOR;
+ arg = but;
+ break;
+
+ /* quiet warnings for unhandled types */
+ default:
+ break;
+ }
+
+ if (func || handlefunc) {
+ data->menu = ui_popup_block_create(C, data->region, but, func, handlefunc, arg);
+ if (but->block->handle) {
+ data->menu->popup = but->block->handle->popup;
+ }
+ }
+ else if (menufunc) {
+ data->menu = ui_popup_menu_create(C, data->region, but, menufunc, arg);
+ if (but->block->handle) {
+ data->menu->popup = but->block->handle->popup;
+ }
+ }
+ else if (popoverfunc) {
+ data->menu = ui_popover_panel_create(C, data->region, but, popoverfunc, arg);
+ if (but->block->handle) {
+ data->menu->popup = but->block->handle->popup;
+ }
+ }
#ifdef USE_ALLSELECT
- {
- wmWindow *win = CTX_wm_window(C);
- if (IS_ALLSELECT_EVENT(win->eventstate)) {
- data->select_others.is_enabled = true;
- }
- }
+ {
+ wmWindow *win = CTX_wm_window(C);
+ if (IS_ALLSELECT_EVENT(win->eventstate)) {
+ data->select_others.is_enabled = true;
+ }
+ }
#endif
- /* this makes adjacent blocks auto open from now on */
- //if (but->block->auto_open == 0) {
- // but->block->auto_open = 1;
- //}
+ /* this makes adjacent blocks auto open from now on */
+ //if (but->block->auto_open == 0) {
+ // but->block->auto_open = 1;
+ //}
}
static void ui_block_open_end(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- if (but) {
- but->editval = NULL;
- but->editvec = NULL;
+ if (but) {
+ but->editval = NULL;
+ but->editvec = NULL;
- but->block->auto_open_last = PIL_check_seconds_timer();
- }
+ but->block->auto_open_last = PIL_check_seconds_timer();
+ }
- if (data->menu) {
- ui_popup_block_free(C, data->menu);
- data->menu = NULL;
- }
+ if (data->menu) {
+ ui_popup_block_free(C, data->menu);
+ data->menu = NULL;
+ }
}
int ui_but_menu_direction(uiBut *but)
{
- uiHandleButtonData *data = but->active;
+ uiHandleButtonData *data = but->active;
- if (data && data->menu) {
- return data->menu->direction;
- }
+ if (data && data->menu) {
+ return data->menu->direction;
+ }
- return 0;
+ return 0;
}
/**
* 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, uiHandleButtonData *data, const wmEvent *event,
- uiButtonActivateType activate_type)
+static uiBut *ui_but_list_row_text_activate(bContext *C,
+ uiBut *but,
+ uiHandleButtonData *data,
+ 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 *ar = CTX_wm_region(C);
+ uiBut *labelbut = ui_but_find_mouse_over_ex(ar, event->x, event->y, true);
- if (labelbut && labelbut->type == UI_BTYPE_TEXT && !(labelbut->flag & UI_BUT_DISABLED)) {
- /* exit listrow */
- data->cancel = true;
- button_activate_exit(C, but, data, false, false);
+ if (labelbut && labelbut->type == UI_BTYPE_TEXT && !(labelbut->flag & UI_BUT_DISABLED)) {
+ /* exit listrow */
+ data->cancel = true;
+ button_activate_exit(C, but, data, false, false);
- /* Activate the text button. */
- button_activate_init(C, ar, labelbut, activate_type);
+ /* Activate the text button. */
+ button_activate_init(C, ar, labelbut, activate_type);
- return labelbut;
- }
- return NULL;
+ return labelbut;
+ }
+ return NULL;
}
/** \} */
@@ -3843,3247 +3853,3256 @@ static uiBut *ui_but_list_row_text_activate(
#ifdef USE_DRAG_TOGGLE
/* Shared by any button that supports drag-toggle. */
static bool ui_do_but_ANY_drag_toggle(
- bContext *C, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event,
- int *r_retval)
-{
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (event->type == LEFTMOUSE && event->val == KM_PRESS && ui_but_is_drag_toggle(but)) {
-#if 0 /* UNUSED */
- data->togdual = event->ctrl;
- data->togonly = !event->shift;
-#endif
- ui_apply_but(C, but->block, but, data, true);
- button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
- data->dragstartx = event->x;
- data->dragstarty = event->y;
- *r_retval = WM_UI_HANDLER_BREAK;
- return true;
- }
- }
- else if (data->state == BUTTON_STATE_WAIT_DRAG) {
- /* note: the 'BUTTON_STATE_WAIT_DRAG' part of 'ui_do_but_EXIT' could be refactored into
- * its own function */
- data->applied = false;
- *r_retval = ui_do_but_EXIT(C, but, data, event);
- return true;
- }
- return false;
-}
-#endif /* USE_DRAG_TOGGLE */
-
-static int ui_do_but_BUT(
- bContext *C, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
+ bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event, int *r_retval)
+{
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS && ui_but_is_drag_toggle(but)) {
+# if 0 /* UNUSED */
+ data->togdual = event->ctrl;
+ data->togonly = !event->shift;
+# endif
+ ui_apply_but(C, but->block, but, data, true);
+ button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ *r_retval = WM_UI_HANDLER_BREAK;
+ return true;
+ }
+ }
+ else if (data->state == BUTTON_STATE_WAIT_DRAG) {
+ /* note: the 'BUTTON_STATE_WAIT_DRAG' part of 'ui_do_but_EXIT' could be refactored into
+ * its own function */
+ data->applied = false;
+ *r_retval = ui_do_but_EXIT(C, but, data, event);
+ return true;
+ }
+ return false;
+}
+#endif /* USE_DRAG_TOGGLE */
+
+static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
#ifdef USE_DRAG_TOGGLE
- {
- int retval;
- if (ui_do_but_ANY_drag_toggle(C, but, data, event, &retval)) {
- return retval;
- }
- }
+ {
+ int retval;
+ if (ui_do_but_ANY_drag_toggle(C, but, data, event, &retval)) {
+ return retval;
+ }
+ }
#endif
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
- button_activate_state(C, but, BUTTON_STATE_WAIT_RELEASE);
- return WM_UI_HANDLER_BREAK;
- }
- else if (event->type == LEFTMOUSE && event->val == KM_RELEASE && but->block->handle) {
- /* regular buttons will be 'UI_SELECT', menu items 'UI_ACTIVE' */
- if (!(but->flag & (UI_SELECT | UI_ACTIVE))) {
- data->cancel = true;
- }
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- return WM_UI_HANDLER_BREAK;
- }
- else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS) {
- button_activate_state(C, but, BUTTON_STATE_WAIT_FLASH);
- return WM_UI_HANDLER_BREAK;
- }
- }
- else if (data->state == BUTTON_STATE_WAIT_RELEASE) {
- if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- if (!(but->flag & UI_SELECT)) {
- data->cancel = true;
- }
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- return WM_UI_HANDLER_BREAK;
- }
- }
-
- return WM_UI_HANDLER_CONTINUE;
-}
-
-static int ui_do_but_HOTKEYEVT(
- bContext *C, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
- but->drawstr[0] = 0;
- but->modifier_key = 0;
- button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
- return WM_UI_HANDLER_BREAK;
- }
- }
- else if (data->state == BUTTON_STATE_WAIT_KEY_EVENT) {
- if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
- return WM_UI_HANDLER_CONTINUE;
- }
-
- if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
- /* only cancel if click outside the button */
- if (ui_but_contains_point_px(but, but->active->region, event->x, event->y) == 0) {
- /* data->cancel doesn't work, this button opens immediate */
- if (but->flag & UI_BUT_IMMEDIATE) {
- ui_but_value_set(but, 0);
- }
- else {
- data->cancel = true;
- }
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- return WM_UI_HANDLER_BREAK;
- }
- }
-
- /* always set */
- but->modifier_key = 0;
- if (event->shift) {
- but->modifier_key |= KM_SHIFT;
- }
- if (event->alt) {
- but->modifier_key |= KM_ALT;
- }
- if (event->ctrl) {
- but->modifier_key |= KM_CTRL;
- }
- if (event->oskey) {
- but->modifier_key |= KM_OSKEY;
- }
-
- ui_but_update(but);
- ED_region_tag_redraw(data->region);
-
- if (event->val == KM_PRESS) {
- if (ISHOTKEY(event->type) && (event->type != ESCKEY)) {
- if (WM_key_event_string(event->type, false)[0]) {
- ui_but_value_set(but, event->type);
- }
- else {
- data->cancel = true;
- }
-
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- return WM_UI_HANDLER_BREAK;
- }
- else if (event->type == ESCKEY) {
- if (event->val == KM_PRESS) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- }
-
- }
- }
-
- return WM_UI_HANDLER_CONTINUE;
-}
-
-static int ui_do_but_KEYEVT(
- bContext *C, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
- button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
- return WM_UI_HANDLER_BREAK;
- }
- }
- else if (data->state == BUTTON_STATE_WAIT_KEY_EVENT) {
- if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
- return WM_UI_HANDLER_CONTINUE;
- }
-
- if (event->val == KM_PRESS) {
- if (WM_key_event_string(event->type, false)[0]) {
- ui_but_value_set(but, event->type);
- }
- else {
- data->cancel = true;
- }
-
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- }
-
- return WM_UI_HANDLER_CONTINUE;
-}
-
-static bool ui_but_is_mouse_over_icon_extra(const ARegion *region, uiBut *but, const int mouse_xy[2])
-{
- int x = mouse_xy[0], y = mouse_xy[1];
- rcti icon_rect;
-
- BLI_assert(ui_but_icon_extra_get(but) != UI_BUT_ICONEXTRA_NONE);
-
- ui_window_to_block(region, but->block, &x, &y);
-
- BLI_rcti_rctf_copy(&icon_rect, &but->rect);
- icon_rect.xmin = icon_rect.xmax - (BLI_rcti_size_y(&icon_rect));
-
- return BLI_rcti_isect_pt(&icon_rect, x, y);
-}
-
-static int ui_do_but_TAB(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
-{
- const bool is_property = (but->rnaprop != NULL);
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_RELEASE);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE && but->block->handle) {
+ /* regular buttons will be 'UI_SELECT', menu items 'UI_ACTIVE' */
+ if (!(but->flag & (UI_SELECT | UI_ACTIVE))) {
+ data->cancel = true;
+ }
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_FLASH);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if (data->state == BUTTON_STATE_WAIT_RELEASE) {
+ if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ if (!(but->flag & UI_SELECT)) {
+ data->cancel = true;
+ }
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
+static int ui_do_but_HOTKEYEVT(bContext *C,
+ uiBut *but,
+ uiHandleButtonData *data,
+ const wmEvent *event)
+{
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ but->drawstr[0] = 0;
+ but->modifier_key = 0;
+ button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if (data->state == BUTTON_STATE_WAIT_KEY_EVENT) {
+ if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+ return WM_UI_HANDLER_CONTINUE;
+ }
+
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
+ /* only cancel if click outside the button */
+ if (ui_but_contains_point_px(but, but->active->region, event->x, event->y) == 0) {
+ /* data->cancel doesn't work, this button opens immediate */
+ if (but->flag & UI_BUT_IMMEDIATE) {
+ ui_but_value_set(but, 0);
+ }
+ else {
+ data->cancel = true;
+ }
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ /* always set */
+ but->modifier_key = 0;
+ if (event->shift) {
+ but->modifier_key |= KM_SHIFT;
+ }
+ if (event->alt) {
+ but->modifier_key |= KM_ALT;
+ }
+ if (event->ctrl) {
+ but->modifier_key |= KM_CTRL;
+ }
+ if (event->oskey) {
+ but->modifier_key |= KM_OSKEY;
+ }
+
+ ui_but_update(but);
+ ED_region_tag_redraw(data->region);
+
+ if (event->val == KM_PRESS) {
+ if (ISHOTKEY(event->type) && (event->type != ESCKEY)) {
+ if (WM_key_event_string(event->type, false)[0]) {
+ ui_but_value_set(but, event->type);
+ }
+ else {
+ data->cancel = true;
+ }
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if (event->type == ESCKEY) {
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+ }
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
+static int ui_do_but_KEYEVT(bContext *C,
+ uiBut *but,
+ uiHandleButtonData *data,
+ const wmEvent *event)
+{
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if (data->state == BUTTON_STATE_WAIT_KEY_EVENT) {
+ if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+ return WM_UI_HANDLER_CONTINUE;
+ }
+
+ if (event->val == KM_PRESS) {
+ if (WM_key_event_string(event->type, false)[0]) {
+ ui_but_value_set(but, event->type);
+ }
+ else {
+ data->cancel = true;
+ }
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
+static bool ui_but_is_mouse_over_icon_extra(const ARegion *region,
+ uiBut *but,
+ const int mouse_xy[2])
+{
+ int x = mouse_xy[0], y = mouse_xy[1];
+ rcti icon_rect;
+
+ BLI_assert(ui_but_icon_extra_get(but) != UI_BUT_ICONEXTRA_NONE);
+
+ ui_window_to_block(region, but->block, &x, &y);
+
+ BLI_rcti_rctf_copy(&icon_rect, &but->rect);
+ icon_rect.xmin = icon_rect.xmax - (BLI_rcti_size_y(&icon_rect));
+
+ return BLI_rcti_isect_pt(&icon_rect, x, y);
+}
+
+static int ui_do_but_TAB(
+ bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ const bool is_property = (but->rnaprop != NULL);
#ifdef USE_DRAG_TOGGLE
- if (is_property) {
- int retval;
- if (ui_do_but_ANY_drag_toggle(C, but, data, event, &retval)) {
- return retval;
- }
- }
+ if (is_property) {
+ int retval;
+ if (ui_do_but_ANY_drag_toggle(C, but, data, event, &retval)) {
+ return retval;
+ }
+ }
#endif
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- const int rna_type = but->rnaprop ? RNA_property_type(but->rnaprop) : 0;
-
- if (is_property &&
- ELEM(rna_type, PROP_POINTER, PROP_STRING) &&
- (but->custom_data != NULL) &&
- (event->type == LEFTMOUSE) &&
- ((event->val == KM_DBL_CLICK) || event->ctrl))
- {
- button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
- return WM_UI_HANDLER_BREAK;
- }
- else if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY)) {
- int event_val = (is_property) ? KM_PRESS : KM_CLICK;
- if (event->val == event_val) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- return WM_UI_HANDLER_BREAK;
- }
- }
- }
- else if (data->state == BUTTON_STATE_TEXT_EDITING) {
- ui_do_but_textedit(C, block, but, data, event);
- return WM_UI_HANDLER_BREAK;
- }
- else if (data->state == BUTTON_STATE_TEXT_SELECTING) {
- ui_do_but_textedit_select(C, block, but, data, event);
- return WM_UI_HANDLER_BREAK;
- }
-
- return WM_UI_HANDLER_CONTINUE;
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ const int rna_type = but->rnaprop ? RNA_property_type(but->rnaprop) : 0;
+
+ if (is_property && ELEM(rna_type, PROP_POINTER, PROP_STRING) && (but->custom_data != NULL) &&
+ (event->type == LEFTMOUSE) && ((event->val == KM_DBL_CLICK) || event->ctrl)) {
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY)) {
+ int event_val = (is_property) ? KM_PRESS : KM_CLICK;
+ if (event->val == event_val) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ }
+ else if (data->state == BUTTON_STATE_TEXT_EDITING) {
+ ui_do_but_textedit(C, block, but, data, event);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if (data->state == BUTTON_STATE_TEXT_SELECTING) {
+ ui_do_but_textedit_select(C, block, but, data, event);
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
}
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))) {
- /* pass - allow filesel, enter to execute */
- }
- else if (but->dt == UI_EMBOSS_NONE && !event->ctrl) {
- /* pass */
- }
- else {
- const bool has_icon_extra = ui_but_icon_extra_get(but) == UI_BUT_ICONEXTRA_CLEAR;
-
- if (has_icon_extra && ui_but_is_mouse_over_icon_extra(data->region, but, &event->x)) {
- ui_textedit_string_clear_and_exit(C, but, data);
- }
- else {
- button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
- }
- return WM_UI_HANDLER_BREAK;
- }
- }
- }
- else if (data->state == BUTTON_STATE_TEXT_EDITING) {
- ui_do_but_textedit(C, block, but, data, event);
- return WM_UI_HANDLER_BREAK;
- }
- else if (data->state == BUTTON_STATE_TEXT_SELECTING) {
- ui_do_but_textedit_select(C, block, but, data, event);
- return WM_UI_HANDLER_BREAK;
- }
-
- return WM_UI_HANDLER_CONTINUE;
+ 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))) {
+ /* pass - allow filesel, enter to execute */
+ }
+ else if (but->dt == UI_EMBOSS_NONE && !event->ctrl) {
+ /* pass */
+ }
+ else {
+ const bool has_icon_extra = ui_but_icon_extra_get(but) == UI_BUT_ICONEXTRA_CLEAR;
+
+ if (has_icon_extra && ui_but_is_mouse_over_icon_extra(data->region, but, &event->x)) {
+ ui_textedit_string_clear_and_exit(C, but, data);
+ }
+ else {
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ }
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ }
+ else if (data->state == BUTTON_STATE_TEXT_EDITING) {
+ ui_do_but_textedit(C, block, but, data, event);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if (data->state == BUTTON_STATE_TEXT_SELECTING) {
+ ui_do_but_textedit_select(C, block, but, data, event);
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
}
static int ui_do_but_SEARCH_UNLINK(
- bContext *C, uiBlock *block, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
- const uiButExtraIconType extra_icon_type = ui_but_icon_extra_get(but);
- const bool has_icon_extra = (extra_icon_type != UI_BUT_ICONEXTRA_NONE);
-
- /* unlink icon is on right */
- if ((ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY)) &&
- (has_icon_extra == true) &&
- (ui_but_is_mouse_over_icon_extra(data->region, but, &event->x) == true))
- {
- /* doing this on KM_PRESS calls eyedropper after clicking unlink icon */
- if (event->val == KM_RELEASE) {
- /* unlink */
- if (extra_icon_type == UI_BUT_ICONEXTRA_CLEAR) {
- ui_textedit_string_clear_and_exit(C, but, data);
- }
- /* eyedropper */
- else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
- WM_operator_name_call(C, "UI_OT_eyedropper_id", WM_OP_INVOKE_DEFAULT, NULL);
- }
- else {
- BLI_assert(0);
- }
- }
- return WM_UI_HANDLER_BREAK;
- }
- return ui_do_but_TEX(C, block, but, data, event);
-}
-
-static int ui_do_but_TOG(
- bContext *C, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
+ bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ const uiButExtraIconType extra_icon_type = ui_but_icon_extra_get(but);
+ const bool has_icon_extra = (extra_icon_type != UI_BUT_ICONEXTRA_NONE);
+
+ /* unlink icon is on right */
+ if ((ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY)) && (has_icon_extra == true) &&
+ (ui_but_is_mouse_over_icon_extra(data->region, but, &event->x) == true)) {
+ /* doing this on KM_PRESS calls eyedropper after clicking unlink icon */
+ if (event->val == KM_RELEASE) {
+ /* unlink */
+ if (extra_icon_type == UI_BUT_ICONEXTRA_CLEAR) {
+ ui_textedit_string_clear_and_exit(C, but, data);
+ }
+ /* eyedropper */
+ else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
+ WM_operator_name_call(C, "UI_OT_eyedropper_id", WM_OP_INVOKE_DEFAULT, NULL);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ return WM_UI_HANDLER_BREAK;
+ }
+ return ui_do_but_TEX(C, block, but, data, event);
+}
+
+static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
#ifdef USE_DRAG_TOGGLE
- {
- int retval;
- if (ui_do_but_ANY_drag_toggle(C, but, data, event, &retval)) {
- return retval;
- }
- }
+ {
+ int retval;
+ if (ui_do_but_ANY_drag_toggle(C, but, data, event, &retval)) {
+ return retval;
+ }
+ }
#endif
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- bool do_activate = false;
- if (ELEM(event->type, PADENTER, RETKEY)) {
- if (event->val == KM_PRESS) {
- do_activate = true;
- }
- }
- else if (event->type == LEFTMOUSE) {
- if (ui_block_is_menu(but->block)) {
- /* Behave like other menu items. */
- do_activate = (event->val == KM_RELEASE);
- }
- else {
- do_activate = (event->val == KM_PRESS);
- }
- }
-
- if (do_activate) {
-#if 0 /* UNUSED */
- data->togdual = event->ctrl;
- data->togonly = !event->shift;
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ bool do_activate = false;
+ if (ELEM(event->type, PADENTER, RETKEY)) {
+ if (event->val == KM_PRESS) {
+ do_activate = true;
+ }
+ }
+ else if (event->type == LEFTMOUSE) {
+ if (ui_block_is_menu(but->block)) {
+ /* Behave like other menu items. */
+ do_activate = (event->val == KM_RELEASE);
+ }
+ else {
+ do_activate = (event->val == KM_PRESS);
+ }
+ }
+
+ if (do_activate) {
+#if 0 /* UNUSED */
+ data->togdual = event->ctrl;
+ data->togonly = !event->shift;
#endif
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- return WM_UI_HANDLER_BREAK;
- }
- else if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) {
- /* Support alt+wheel on expanded enum rows */
- if (but->type == UI_BTYPE_ROW) {
- const int direction = (event->type == WHEELDOWNMOUSE) ? -1 : 1;
- uiBut *but_select = ui_but_find_select_in_enum(but, direction);
- 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;
-
- 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);
- 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);
- }
- else {
- /* shouldn't happen */
- BLI_assert(0);
- }
- }
- }
- return WM_UI_HANDLER_BREAK;
- }
- }
- }
- return WM_UI_HANDLER_CONTINUE;
-}
-
-static int ui_do_but_EXIT(
- bContext *C, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
-
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
-
- /* first handle click on icondrag type button */
- if (event->type == LEFTMOUSE && but->dragpoin) {
- if (ui_but_contains_point_px_icon(but, data->region, event)) {
-
- /* tell the button to wait and keep checking further events to
- * see if it should start dragging */
- button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
- data->dragstartx = event->x;
- data->dragstarty = event->y;
- return WM_UI_HANDLER_CONTINUE;
- }
- }
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) {
+ /* Support alt+wheel on expanded enum rows */
+ if (but->type == UI_BTYPE_ROW) {
+ const int direction = (event->type == WHEELDOWNMOUSE) ? -1 : 1;
+ uiBut *but_select = ui_but_find_select_in_enum(but, direction);
+ 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;
+
+ 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);
+ 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);
+ }
+ else {
+ /* shouldn't happen */
+ BLI_assert(0);
+ }
+ }
+ }
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ }
+ return WM_UI_HANDLER_CONTINUE;
+}
+
+static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+
+ /* first handle click on icondrag type button */
+ if (event->type == LEFTMOUSE && but->dragpoin) {
+ if (ui_but_contains_point_px_icon(but, data->region, event)) {
+
+ /* tell the button to wait and keep checking further events to
+ * see if it should start dragging */
+ button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ return WM_UI_HANDLER_CONTINUE;
+ }
+ }
#ifdef USE_DRAG_TOGGLE
- if (event->type == LEFTMOUSE && ui_but_is_drag_toggle(but)) {
- button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
- data->dragstartx = event->x;
- data->dragstarty = event->y;
- return WM_UI_HANDLER_CONTINUE;
- }
+ if (event->type == LEFTMOUSE && ui_but_is_drag_toggle(but)) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ return WM_UI_HANDLER_CONTINUE;
+ }
#endif
- if (ELEM(event->type, LEFTMOUSE, PADENTER, 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)) {
- ret = WM_UI_HANDLER_CONTINUE;
- }
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- return ret;
- }
- }
- else if (data->state == BUTTON_STATE_WAIT_DRAG) {
-
- /* this function also ends state */
- if (ui_but_drag_init(C, but, data, event)) {
- return WM_UI_HANDLER_BREAK;
- }
-
- /* If the mouse has been pressed and released, getting to
- * this point without triggering a drag, then clear the
- * drag state for this button and continue to pass on the event */
- if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- return WM_UI_HANDLER_CONTINUE;
- }
-
- /* while waiting for a drag to be triggered, always block
- * other events from getting handled */
- return WM_UI_HANDLER_BREAK;
- }
-
- return WM_UI_HANDLER_CONTINUE;
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, 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)) {
+ ret = WM_UI_HANDLER_CONTINUE;
+ }
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return ret;
+ }
+ }
+ else if (data->state == BUTTON_STATE_WAIT_DRAG) {
+
+ /* this function also ends state */
+ if (ui_but_drag_init(C, but, data, event)) {
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ /* If the mouse has been pressed and released, getting to
+ * this point without triggering a drag, then clear the
+ * drag state for this button and continue to pass on the event */
+ if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_CONTINUE;
+ }
+
+ /* while waiting for a drag to be triggered, always block
+ * other events from getting handled */
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
}
/* var names match ui_numedit_but_NUM */
-static float ui_numedit_apply_snapf(
- uiBut *but, float tempf, float softmin, float softmax, float softrange,
- const enum eSnapType snap)
-{
- if (tempf == softmin || tempf == softmax || snap == SNAP_OFF) {
- /* pass */
- }
- else {
- float fac = 1.0f;
-
- if (ui_but_is_unit(but)) {
- UnitSettings *unit = but->block->unit;
- int unit_type = RNA_SUBTYPE_UNIT_VALUE(UI_but_unit_type_get(but));
-
- if (bUnit_IsValid(unit->system, unit_type)) {
- fac = (float)bUnit_BaseScalar(unit->system, unit_type);
- if (ELEM(unit_type, B_UNIT_LENGTH, B_UNIT_AREA, B_UNIT_VOLUME)) {
- fac /= unit->scale_length;
- }
- }
- }
-
- if (fac != 1.0f) {
- /* snap in unit-space */
- tempf /= fac;
- /* softmin /= fac; */ /* UNUSED */
- /* softmax /= fac; */ /* UNUSED */
- softrange /= fac;
- }
-
- /* workaround, too high snapping values */
- /* snapping by 10's for float buttons is quite annoying (location, scale...),
- * but allow for rotations */
- if (softrange >= 21.0f) {
- UnitSettings *unit = but->block->unit;
- int unit_type = UI_but_unit_type_get(but);
- if ((unit_type == PROP_UNIT_ROTATION) && (unit->system_rotation != USER_UNIT_ROT_RADIANS)) {
- /* pass (degrees)*/
- }
- else {
- softrange = 20.0f;
- }
- }
-
- if (snap == SNAP_ON) {
- if (softrange < 2.10f) { tempf = roundf(tempf * 10.0f) * 0.1f; }
- else if (softrange < 21.0f) { tempf = roundf(tempf); }
- else { tempf = roundf(tempf * 0.1f) * 10.0f; }
- }
- else if (snap == SNAP_ON_SMALL) {
- if (softrange < 2.10f) { tempf = roundf(tempf * 100.0f) * 0.01f; }
- else if (softrange < 21.0f) { tempf = roundf(tempf * 10.0f) * 0.1f; }
- else { tempf = roundf(tempf); }
- }
- else {
- BLI_assert(0);
- }
-
- if (fac != 1.0f) {
- tempf *= fac;
- }
- }
-
- return tempf;
-}
-
-static float ui_numedit_apply_snap(
- int temp, float softmin, float softmax,
- const enum eSnapType snap)
-{
- if (temp == softmin || temp == softmax) {
- return temp;
- }
-
- switch (snap) {
- case SNAP_OFF:
- break;
- case SNAP_ON:
- temp = 10 * (temp / 10);
- break;
- case SNAP_ON_SMALL:
- temp = 100 * (temp / 100);
- break;
- }
-
- return temp;
-}
-
-static bool ui_numedit_but_NUM(
- uiBut *but, uiHandleButtonData *data,
- int mx, const bool is_motion,
- const enum eSnapType snap, float fac)
-{
- float deler, tempf, softmin, softmax, softrange;
- int lvalue, temp;
- bool changed = false;
- const bool is_float = ui_but_is_float(but);
-
- /* prevent unwanted drag adjustments, test motion so modifier keys refresh. */
- if ((is_motion || data->draglock) &&
- (ui_but_dragedit_update_mval(data, mx) == false))
- {
- return changed;
- }
-
- softmin = but->softmin;
- softmax = but->softmax;
- softrange = softmax - softmin;
-
- if (ui_but_is_cursor_warp(but)) {
- /* Mouse location isn't screen clamped to the screen so use a linear mapping
- * 2px == 1-int, or 1px == 1-ClickStep */
- if (is_float) {
- fac *= 0.01f * but->a1;
- tempf = (float)data->startvalue + ((float)(mx - data->dragstartx) * fac);
- tempf = ui_numedit_apply_snapf(but, tempf, softmin, softmax, softrange, snap);
-
-#if 1 /* fake moving the click start, nicer for dragging back after passing the limit */
- if (tempf < softmin) {
- data->dragstartx -= (softmin - tempf) / fac;
- tempf = softmin;
- }
- else if (tempf > softmax) {
- data->dragstartx += (tempf - softmax) / fac;
- tempf = softmax;
- }
+static float ui_numedit_apply_snapf(uiBut *but,
+ float tempf,
+ float softmin,
+ float softmax,
+ float softrange,
+ const enum eSnapType snap)
+{
+ if (tempf == softmin || tempf == softmax || snap == SNAP_OFF) {
+ /* pass */
+ }
+ else {
+ float fac = 1.0f;
+
+ if (ui_but_is_unit(but)) {
+ UnitSettings *unit = but->block->unit;
+ int unit_type = RNA_SUBTYPE_UNIT_VALUE(UI_but_unit_type_get(but));
+
+ if (bUnit_IsValid(unit->system, unit_type)) {
+ fac = (float)bUnit_BaseScalar(unit->system, unit_type);
+ if (ELEM(unit_type, B_UNIT_LENGTH, B_UNIT_AREA, B_UNIT_VOLUME)) {
+ fac /= unit->scale_length;
+ }
+ }
+ }
+
+ if (fac != 1.0f) {
+ /* snap in unit-space */
+ tempf /= fac;
+ /* softmin /= fac; */ /* UNUSED */
+ /* softmax /= fac; */ /* UNUSED */
+ softrange /= fac;
+ }
+
+ /* workaround, too high snapping values */
+ /* snapping by 10's for float buttons is quite annoying (location, scale...),
+ * but allow for rotations */
+ if (softrange >= 21.0f) {
+ UnitSettings *unit = but->block->unit;
+ int unit_type = UI_but_unit_type_get(but);
+ if ((unit_type == PROP_UNIT_ROTATION) && (unit->system_rotation != USER_UNIT_ROT_RADIANS)) {
+ /* pass (degrees)*/
+ }
+ else {
+ softrange = 20.0f;
+ }
+ }
+
+ if (snap == SNAP_ON) {
+ if (softrange < 2.10f) {
+ tempf = roundf(tempf * 10.0f) * 0.1f;
+ }
+ else if (softrange < 21.0f) {
+ tempf = roundf(tempf);
+ }
+ else {
+ tempf = roundf(tempf * 0.1f) * 10.0f;
+ }
+ }
+ else if (snap == SNAP_ON_SMALL) {
+ if (softrange < 2.10f) {
+ tempf = roundf(tempf * 100.0f) * 0.01f;
+ }
+ else if (softrange < 21.0f) {
+ tempf = roundf(tempf * 10.0f) * 0.1f;
+ }
+ else {
+ tempf = roundf(tempf);
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ if (fac != 1.0f) {
+ tempf *= fac;
+ }
+ }
+
+ return tempf;
+}
+
+static float ui_numedit_apply_snap(int temp,
+ float softmin,
+ float softmax,
+ const enum eSnapType snap)
+{
+ if (temp == softmin || temp == softmax) {
+ return temp;
+ }
+
+ switch (snap) {
+ case SNAP_OFF:
+ break;
+ case SNAP_ON:
+ temp = 10 * (temp / 10);
+ break;
+ case SNAP_ON_SMALL:
+ temp = 100 * (temp / 100);
+ break;
+ }
+
+ return temp;
+}
+
+static bool ui_numedit_but_NUM(uiBut *but,
+ uiHandleButtonData *data,
+ int mx,
+ const bool is_motion,
+ const enum eSnapType snap,
+ float fac)
+{
+ float deler, tempf, softmin, softmax, softrange;
+ int lvalue, temp;
+ bool changed = false;
+ const bool is_float = ui_but_is_float(but);
+
+ /* prevent unwanted drag adjustments, test motion so modifier keys refresh. */
+ if ((is_motion || data->draglock) && (ui_but_dragedit_update_mval(data, mx) == false)) {
+ return changed;
+ }
+
+ softmin = but->softmin;
+ softmax = but->softmax;
+ softrange = softmax - softmin;
+
+ if (ui_but_is_cursor_warp(but)) {
+ /* Mouse location isn't screen clamped to the screen so use a linear mapping
+ * 2px == 1-int, or 1px == 1-ClickStep */
+ if (is_float) {
+ fac *= 0.01f * but->a1;
+ tempf = (float)data->startvalue + ((float)(mx - data->dragstartx) * fac);
+ tempf = ui_numedit_apply_snapf(but, tempf, softmin, softmax, softrange, snap);
+
+#if 1 /* fake moving the click start, nicer for dragging back after passing the limit */
+ if (tempf < softmin) {
+ data->dragstartx -= (softmin - tempf) / fac;
+ tempf = softmin;
+ }
+ else if (tempf > softmax) {
+ data->dragstartx += (tempf - softmax) / fac;
+ tempf = softmax;
+ }
#else
- CLAMP(tempf, softmin, softmax);
+ CLAMP(tempf, softmin, softmax);
#endif
- if (tempf != (float)data->value) {
- data->dragchange = true;
- data->value = tempf;
- changed = true;
- }
- }
- else {
- if (softrange > 256) { fac = 1.0; } /* 1px == 1 */
- else if (softrange > 32) { fac = 1.0 / 2.0; } /* 2px == 1 */
- else { fac = 1.0 / 16.0; } /* 16px == 1? */
-
- temp = data->startvalue + (((double)mx - data->dragstartx) * (double)fac);
- temp = ui_numedit_apply_snap(temp, softmin, softmax, snap);
-
-#if 1 /* fake moving the click start, nicer for dragging back after passing the limit */
- if (temp < softmin) {
- data->dragstartx -= (softmin - temp) / fac;
- temp = softmin;
- }
- else if (temp > softmax) {
- data->dragstartx += (temp - softmax) / fac;
- temp = softmax;
- }
+ if (tempf != (float)data->value) {
+ data->dragchange = true;
+ data->value = tempf;
+ changed = true;
+ }
+ }
+ else {
+ if (softrange > 256) {
+ fac = 1.0;
+ } /* 1px == 1 */
+ else if (softrange > 32) {
+ fac = 1.0 / 2.0;
+ } /* 2px == 1 */
+ else {
+ fac = 1.0 / 16.0;
+ } /* 16px == 1? */
+
+ temp = data->startvalue + (((double)mx - data->dragstartx) * (double)fac);
+ temp = ui_numedit_apply_snap(temp, softmin, softmax, snap);
+
+#if 1 /* fake moving the click start, nicer for dragging back after passing the limit */
+ if (temp < softmin) {
+ data->dragstartx -= (softmin - temp) / fac;
+ temp = softmin;
+ }
+ else if (temp > softmax) {
+ data->dragstartx += (temp - softmax) / fac;
+ temp = softmax;
+ }
#else
- CLAMP(temp, softmin, softmax);
+ CLAMP(temp, softmin, softmax);
#endif
- if (temp != data->value) {
- data->dragchange = true;
- data->value = temp;
- changed = true;
- }
- }
-
- data->draglastx = mx;
- }
- else {
- float non_linear_range_limit;
- float non_linear_pixel_map;
- float non_linear_scale;
-
- /* Use a non-linear mapping of the mouse drag especially for large floats
- * (normal behavior) */
- deler = 500;
- if (is_float) {
- /* not needed for smaller float buttons */
- non_linear_range_limit = 11.0f;
- non_linear_pixel_map = 500.0f;
- }
- else {
- /* only scale large int buttons */
- non_linear_range_limit = 129.0f;
- /* larger for ints, we dont need to fine tune them */
- non_linear_pixel_map = 250.0f;
-
- /* prevent large ranges from getting too out of control */
- if (softrange > 600) { deler = powf(softrange, 0.75f); }
- else if (softrange < 25) { deler = 50.0; }
- else if (softrange < 100) { deler = 100.0; }
- }
- deler /= fac;
-
- if (softrange > non_linear_range_limit) {
- non_linear_scale = (float)abs(mx - data->dragstartx) / non_linear_pixel_map;
- }
- else {
- non_linear_scale = 1.0f;
- }
-
- if (is_float == false) {
- /* at minimum, moving cursor 2 pixels should change an int button. */
- CLAMP_MIN(non_linear_scale, 0.5f * U.pixelsize);
- }
-
- data->dragf += (((float)(mx - data->draglastx)) / deler) * non_linear_scale;
-
- CLAMP(data->dragf, 0.0f, 1.0f);
- data->draglastx = mx;
- tempf = (softmin + data->dragf * softrange);
-
-
- if (!is_float) {
- temp = round_fl_to_int(tempf);
-
- temp = ui_numedit_apply_snap(temp, softmin, softmax, snap);
-
- CLAMP(temp, softmin, softmax);
- lvalue = (int)data->value;
-
- if (temp != lvalue) {
- data->dragchange = true;
- data->value = (double)temp;
- changed = true;
- }
- }
- else {
- temp = 0;
- tempf = ui_numedit_apply_snapf(but, tempf, softmin, softmax, softrange, snap);
-
- CLAMP(tempf, softmin, softmax);
-
- if (tempf != (float)data->value) {
- data->dragchange = true;
- data->value = tempf;
- changed = true;
- }
- }
- }
-
-
- return changed;
+ if (temp != data->value) {
+ data->dragchange = true;
+ data->value = temp;
+ changed = true;
+ }
+ }
+
+ data->draglastx = mx;
+ }
+ else {
+ float non_linear_range_limit;
+ float non_linear_pixel_map;
+ float non_linear_scale;
+
+ /* Use a non-linear mapping of the mouse drag especially for large floats
+ * (normal behavior) */
+ deler = 500;
+ if (is_float) {
+ /* not needed for smaller float buttons */
+ non_linear_range_limit = 11.0f;
+ non_linear_pixel_map = 500.0f;
+ }
+ else {
+ /* only scale large int buttons */
+ non_linear_range_limit = 129.0f;
+ /* larger for ints, we dont need to fine tune them */
+ non_linear_pixel_map = 250.0f;
+
+ /* prevent large ranges from getting too out of control */
+ if (softrange > 600) {
+ deler = powf(softrange, 0.75f);
+ }
+ else if (softrange < 25) {
+ deler = 50.0;
+ }
+ else if (softrange < 100) {
+ deler = 100.0;
+ }
+ }
+ deler /= fac;
+
+ if (softrange > non_linear_range_limit) {
+ non_linear_scale = (float)abs(mx - data->dragstartx) / non_linear_pixel_map;
+ }
+ else {
+ non_linear_scale = 1.0f;
+ }
+
+ if (is_float == false) {
+ /* at minimum, moving cursor 2 pixels should change an int button. */
+ CLAMP_MIN(non_linear_scale, 0.5f * U.pixelsize);
+ }
+
+ data->dragf += (((float)(mx - data->draglastx)) / deler) * non_linear_scale;
+
+ CLAMP(data->dragf, 0.0f, 1.0f);
+ data->draglastx = mx;
+ tempf = (softmin + data->dragf * softrange);
+
+ if (!is_float) {
+ temp = round_fl_to_int(tempf);
+
+ temp = ui_numedit_apply_snap(temp, softmin, softmax, snap);
+
+ CLAMP(temp, softmin, softmax);
+ lvalue = (int)data->value;
+
+ if (temp != lvalue) {
+ data->dragchange = true;
+ data->value = (double)temp;
+ changed = true;
+ }
+ }
+ else {
+ temp = 0;
+ tempf = ui_numedit_apply_snapf(but, tempf, softmin, softmax, softrange, snap);
+
+ CLAMP(tempf, softmin, softmax);
+
+ if (tempf != (float)data->value) {
+ data->dragchange = true;
+ data->value = tempf;
+ changed = true;
+ }
+ }
+ }
+
+ return changed;
}
static void ui_numedit_set_active(uiBut *but)
{
- int oldflag = but->drawflag;
- but->drawflag &= ~(UI_BUT_ACTIVE_LEFT | UI_BUT_ACTIVE_RIGHT);
-
- uiHandleButtonData *data = but->active;
- if (!data) {
- return;
- }
-
- /* Ignore once we start dragging. */
- if (data->dragchange == false) {
- const float handle_width = min_ff(BLI_rctf_size_x(&but->rect) / 3, BLI_rctf_size_y(&but->rect) * 0.7f);
- /* we can click on the side arrows to increment/decrement,
- * or click inside to edit the value directly */
- int mx = data->window->eventstate->x;
- int my = data->window->eventstate->y;
- ui_window_to_block(data->region, but->block, &mx, &my);
-
- if (mx < (but->rect.xmin + handle_width)) {
- but->drawflag |= UI_BUT_ACTIVE_LEFT;
- }
- else if (mx > (but->rect.xmax - handle_width)) {
- but->drawflag |= UI_BUT_ACTIVE_RIGHT;
- }
- }
-
- /* Don't change the cursor once pressed. */
- if ((but->flag & UI_SELECT) == 0) {
- if ((but->drawflag & (UI_BUT_ACTIVE_LEFT)) || (but->drawflag & (UI_BUT_ACTIVE_RIGHT))) {
- if (data->changed_cursor) {
- WM_cursor_modal_restore(data->window);
- data->changed_cursor = false;
- }
- }
- else {
- if (data->changed_cursor == false) {
- WM_cursor_modal_set(data->window, CURSOR_X_MOVE);
- data->changed_cursor = true;
- }
- }
- }
-
- if (but->drawflag != oldflag) {
- ED_region_tag_redraw(data->region);
- }
+ int oldflag = but->drawflag;
+ but->drawflag &= ~(UI_BUT_ACTIVE_LEFT | UI_BUT_ACTIVE_RIGHT);
+
+ uiHandleButtonData *data = but->active;
+ if (!data) {
+ return;
+ }
+
+ /* Ignore once we start dragging. */
+ if (data->dragchange == false) {
+ const float handle_width = min_ff(BLI_rctf_size_x(&but->rect) / 3,
+ BLI_rctf_size_y(&but->rect) * 0.7f);
+ /* we can click on the side arrows to increment/decrement,
+ * or click inside to edit the value directly */
+ int mx = data->window->eventstate->x;
+ int my = data->window->eventstate->y;
+ ui_window_to_block(data->region, but->block, &mx, &my);
+
+ if (mx < (but->rect.xmin + handle_width)) {
+ but->drawflag |= UI_BUT_ACTIVE_LEFT;
+ }
+ else if (mx > (but->rect.xmax - handle_width)) {
+ but->drawflag |= UI_BUT_ACTIVE_RIGHT;
+ }
+ }
+
+ /* Don't change the cursor once pressed. */
+ if ((but->flag & UI_SELECT) == 0) {
+ if ((but->drawflag & (UI_BUT_ACTIVE_LEFT)) || (but->drawflag & (UI_BUT_ACTIVE_RIGHT))) {
+ if (data->changed_cursor) {
+ WM_cursor_modal_restore(data->window);
+ data->changed_cursor = false;
+ }
+ }
+ else {
+ if (data->changed_cursor == false) {
+ WM_cursor_modal_set(data->window, CURSOR_X_MOVE);
+ data->changed_cursor = true;
+ }
+ }
+ }
+
+ if (but->drawflag != oldflag) {
+ ED_region_tag_redraw(data->region);
+ }
}
static int ui_do_but_NUM(
- bContext *C, uiBlock *block, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
- int mx, my; /* mouse location scaled to fit the UI */
- int screen_mx, screen_my; /* mouse location kept at screen pixel coords */
- int click = 0;
- int retval = WM_UI_HANDLER_CONTINUE;
-
- mx = screen_mx = event->x;
- my = screen_my = event->y;
-
- ui_window_to_block(data->region, block, &mx, &my);
- ui_numedit_set_active(but);
-
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- int type = event->type, val = event->val;
-
- if (type == MOUSEPAN) {
- ui_pan_to_scroll(event, &type, &val);
- }
-
- /* XXX hardcoded keymap check.... */
- if (type == MOUSEPAN && event->alt) {
- /* allow accumulating values, otherwise scrolling gets preference */
- retval = WM_UI_HANDLER_BREAK;
- }
- else if (type == WHEELDOWNMOUSE && event->ctrl) {
- mx = but->rect.xmin;
- but->drawflag &= ~UI_BUT_ACTIVE_RIGHT;
- but->drawflag |= UI_BUT_ACTIVE_LEFT;
- click = 1;
- }
- else if (type == WHEELUPMOUSE && event->ctrl) {
- mx = but->rect.xmax;
- but->drawflag &= ~UI_BUT_ACTIVE_LEFT;
- but->drawflag |= UI_BUT_ACTIVE_RIGHT;
- click = 1;
- }
- else if (event->val == KM_PRESS) {
- if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->ctrl) {
- button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
- retval = WM_UI_HANDLER_BREAK;
- }
- else if (event->type == LEFTMOUSE) {
- data->dragstartx = data->draglastx = ui_but_is_cursor_warp(but) ? screen_mx : mx;
- 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) {
- click = 1;
- }
- else if (event->type == 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);
- retval = WM_UI_HANDLER_BREAK;
- }
+ bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ int mx, my; /* mouse location scaled to fit the UI */
+ int screen_mx, screen_my; /* mouse location kept at screen pixel coords */
+ int click = 0;
+ int retval = WM_UI_HANDLER_CONTINUE;
+
+ mx = screen_mx = event->x;
+ my = screen_my = event->y;
+
+ ui_window_to_block(data->region, block, &mx, &my);
+ ui_numedit_set_active(but);
+
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ int type = event->type, val = event->val;
+
+ if (type == MOUSEPAN) {
+ ui_pan_to_scroll(event, &type, &val);
+ }
+
+ /* XXX hardcoded keymap check.... */
+ if (type == MOUSEPAN && event->alt) {
+ /* allow accumulating values, otherwise scrolling gets preference */
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (type == WHEELDOWNMOUSE && event->ctrl) {
+ mx = but->rect.xmin;
+ but->drawflag &= ~UI_BUT_ACTIVE_RIGHT;
+ but->drawflag |= UI_BUT_ACTIVE_LEFT;
+ click = 1;
+ }
+ else if (type == WHEELUPMOUSE && event->ctrl) {
+ mx = but->rect.xmax;
+ but->drawflag &= ~UI_BUT_ACTIVE_LEFT;
+ but->drawflag |= UI_BUT_ACTIVE_RIGHT;
+ click = 1;
+ }
+ else if (event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->ctrl) {
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (event->type == LEFTMOUSE) {
+ data->dragstartx = data->draglastx = ui_but_is_cursor_warp(but) ? screen_mx : mx;
+ 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) {
+ click = 1;
+ }
+ else if (event->type == 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);
+ retval = WM_UI_HANDLER_BREAK;
+ }
#ifdef USE_DRAG_MULTINUM
- copy_v2_v2_int(data->multi_data.drag_start, &event->x);
+ copy_v2_v2_int(data->multi_data.drag_start, &event->x);
#endif
- }
-
- }
- else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
- if (event->val == KM_PRESS) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- }
- else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- if (data->dragchange) {
+ }
+ }
+ else if (data->state == BUTTON_STATE_NUM_EDITING) {
+ if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ if (data->dragchange) {
#ifdef USE_DRAG_MULTINUM
- /* if we started multibutton but didn't drag, then edit */
- if (data->multi_data.init == BUTTON_MULTI_INIT_SETUP) {
- click = 1;
- }
- else
+ /* if we started multibutton but didn't drag, then edit */
+ if (data->multi_data.init == BUTTON_MULTI_INIT_SETUP) {
+ click = 1;
+ }
+ else
#endif
- {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- }
- else {
- click = 1;
- }
- }
- else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
- const bool is_motion = (event->type == MOUSEMOVE);
- const enum eSnapType snap = ui_event_to_snap(event);
- float fac;
+ {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+ else {
+ click = 1;
+ }
+ }
+ else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
+ const bool is_motion = (event->type == MOUSEMOVE);
+ const enum eSnapType snap = ui_event_to_snap(event);
+ float fac;
#ifdef USE_DRAG_MULTINUM
- data->multi_data.drag_dir[0] += abs(data->draglastx - mx);
- data->multi_data.drag_dir[1] += abs(data->draglasty - my);
+ data->multi_data.drag_dir[0] += abs(data->draglastx - mx);
+ data->multi_data.drag_dir[1] += abs(data->draglasty - my);
#endif
- fac = 1.0f;
- if (event->shift) {
- fac /= 10.0f;
- }
+ fac = 1.0f;
+ if (event->shift) {
+ fac /= 10.0f;
+ }
- if (ui_numedit_but_NUM(but, data, (ui_but_is_cursor_warp(but) ? screen_mx : mx), is_motion, snap, fac)) {
- ui_numedit_apply(C, block, but, data);
- }
+ if (ui_numedit_but_NUM(
+ but, data, (ui_but_is_cursor_warp(but) ? screen_mx : mx), is_motion, snap, fac)) {
+ ui_numedit_apply(C, block, but, data);
+ }
#ifdef USE_DRAG_MULTINUM
- else if (data->multi_data.has_mbuts) {
- if (data->multi_data.init == BUTTON_MULTI_INIT_ENABLE) {
- ui_multibut_states_apply(C, data, block);
- }
- }
+ else if (data->multi_data.has_mbuts) {
+ if (data->multi_data.init == BUTTON_MULTI_INIT_ENABLE) {
+ ui_multibut_states_apply(C, data, block);
+ }
+ }
#endif
- }
- retval = WM_UI_HANDLER_BREAK;
- }
- else if (data->state == BUTTON_STATE_TEXT_EDITING) {
- ui_do_but_textedit(C, block, but, data, event);
- retval = WM_UI_HANDLER_BREAK;
- }
- else if (data->state == BUTTON_STATE_TEXT_SELECTING) {
- ui_do_but_textedit_select(C, block, but, data, event);
- retval = WM_UI_HANDLER_BREAK;
- }
-
- if (click) {
- /* we can click on the side arrows to increment/decrement,
- * or click inside to edit the value directly */
- float tempf, softmin, softmax;
- int temp;
-
- softmin = but->softmin;
- softmax = but->softmax;
-
- if (!ui_but_is_float(but)) {
- if (but->drawflag & UI_BUT_ACTIVE_LEFT) {
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
-
- temp = (int)data->value - 1;
- if (temp >= softmin && temp <= softmax) {
- data->value = (double)temp;
- }
- else {
- data->cancel = true;
- }
-
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- else if (but->drawflag & UI_BUT_ACTIVE_RIGHT) {
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
-
- temp = (int)data->value + 1;
- if (temp >= softmin && temp <= softmax) {
- data->value = (double)temp;
- }
- else {
- data->cancel = true;
- }
-
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- else {
- button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
- }
- }
- else {
- if (but->drawflag & UI_BUT_ACTIVE_LEFT) {
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
-
- tempf = (float)data->value - (UI_PRECISION_FLOAT_SCALE * but->a1);
- if (tempf < softmin) {
- tempf = softmin;
- }
- data->value = tempf;
-
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- else if (but->drawflag & UI_BUT_ACTIVE_RIGHT) {
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
-
- tempf = (float)data->value + (UI_PRECISION_FLOAT_SCALE * but->a1);
- if (tempf > softmax) {
- tempf = softmax;
- }
- data->value = tempf;
-
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- else {
- button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
- }
- }
-
- retval = WM_UI_HANDLER_BREAK;
- }
-
- data->draglastx = mx;
- data->draglasty = my;
-
- return retval;
-}
-
-static bool ui_numedit_but_SLI(
- uiBut *but, uiHandleButtonData *data,
- int mx, const bool is_horizontal, const bool is_motion,
- const bool snap, const bool shift)
-{
- float cursor_x_range, f, tempf, softmin, softmax, softrange;
- int temp, lvalue;
- bool changed = false;
- float mx_fl, my_fl;
-
- /* prevent unwanted drag adjustments, test motion so modifier keys refresh. */
- if ((but->type != UI_BTYPE_SCROLL) &&
- (is_motion || data->draglock) &&
- (ui_but_dragedit_update_mval(data, mx) == false))
- {
- return changed;
- }
-
- softmin = but->softmin;
- softmax = but->softmax;
- softrange = softmax - softmin;
-
- /* yes, 'mx' as both x/y is intentional */
- ui_mouse_scale_warp(data, mx, mx, &mx_fl, &my_fl, shift);
-
- if (but->type == UI_BTYPE_NUM_SLIDER) {
- cursor_x_range = BLI_rctf_size_x(&but->rect);
- }
- else if (but->type == UI_BTYPE_SCROLL) {
- const float size = (is_horizontal) ? BLI_rctf_size_x(&but->rect) : -BLI_rctf_size_y(&but->rect);
- cursor_x_range = size * (but->softmax - but->softmin) / (but->softmax - but->softmin + but->a1);
- }
- else {
- float offs = (BLI_rctf_size_y(&but->rect) / 2.0f);
- cursor_x_range = (BLI_rctf_size_x(&but->rect) - offs);
- }
-
- f = (mx_fl - data->dragstartx) / cursor_x_range + data->dragfstart;
- CLAMP(f, 0.0f, 1.0f);
-
-
- /* deal with mouse correction */
+ }
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (data->state == BUTTON_STATE_TEXT_EDITING) {
+ ui_do_but_textedit(C, block, but, data, event);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (data->state == BUTTON_STATE_TEXT_SELECTING) {
+ ui_do_but_textedit_select(C, block, but, data, event);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+
+ if (click) {
+ /* we can click on the side arrows to increment/decrement,
+ * or click inside to edit the value directly */
+ float tempf, softmin, softmax;
+ int temp;
+
+ softmin = but->softmin;
+ softmax = but->softmax;
+
+ if (!ui_but_is_float(but)) {
+ if (but->drawflag & UI_BUT_ACTIVE_LEFT) {
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ temp = (int)data->value - 1;
+ if (temp >= softmin && temp <= softmax) {
+ data->value = (double)temp;
+ }
+ else {
+ data->cancel = true;
+ }
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else if (but->drawflag & UI_BUT_ACTIVE_RIGHT) {
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ temp = (int)data->value + 1;
+ if (temp >= softmin && temp <= softmax) {
+ data->value = (double)temp;
+ }
+ else {
+ data->cancel = true;
+ }
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else {
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ }
+ }
+ else {
+ if (but->drawflag & UI_BUT_ACTIVE_LEFT) {
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ tempf = (float)data->value - (UI_PRECISION_FLOAT_SCALE * but->a1);
+ if (tempf < softmin) {
+ tempf = softmin;
+ }
+ data->value = tempf;
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else if (but->drawflag & UI_BUT_ACTIVE_RIGHT) {
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ tempf = (float)data->value + (UI_PRECISION_FLOAT_SCALE * but->a1);
+ if (tempf > softmax) {
+ tempf = softmax;
+ }
+ data->value = tempf;
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else {
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ }
+ }
+
+ retval = WM_UI_HANDLER_BREAK;
+ }
+
+ data->draglastx = mx;
+ data->draglasty = my;
+
+ return retval;
+}
+
+static bool ui_numedit_but_SLI(uiBut *but,
+ uiHandleButtonData *data,
+ int mx,
+ const bool is_horizontal,
+ const bool is_motion,
+ const bool snap,
+ const bool shift)
+{
+ float cursor_x_range, f, tempf, softmin, softmax, softrange;
+ int temp, lvalue;
+ bool changed = false;
+ float mx_fl, my_fl;
+
+ /* prevent unwanted drag adjustments, test motion so modifier keys refresh. */
+ if ((but->type != UI_BTYPE_SCROLL) && (is_motion || data->draglock) &&
+ (ui_but_dragedit_update_mval(data, mx) == false)) {
+ return changed;
+ }
+
+ softmin = but->softmin;
+ softmax = but->softmax;
+ softrange = softmax - softmin;
+
+ /* yes, 'mx' as both x/y is intentional */
+ ui_mouse_scale_warp(data, mx, mx, &mx_fl, &my_fl, shift);
+
+ if (but->type == UI_BTYPE_NUM_SLIDER) {
+ cursor_x_range = BLI_rctf_size_x(&but->rect);
+ }
+ else if (but->type == UI_BTYPE_SCROLL) {
+ const float size = (is_horizontal) ? BLI_rctf_size_x(&but->rect) :
+ -BLI_rctf_size_y(&but->rect);
+ cursor_x_range = size * (but->softmax - but->softmin) /
+ (but->softmax - but->softmin + but->a1);
+ }
+ else {
+ float offs = (BLI_rctf_size_y(&but->rect) / 2.0f);
+ cursor_x_range = (BLI_rctf_size_x(&but->rect) - offs);
+ }
+
+ f = (mx_fl - data->dragstartx) / cursor_x_range + data->dragfstart;
+ CLAMP(f, 0.0f, 1.0f);
+
+ /* deal with mouse correction */
#ifdef USE_CONT_MOUSE_CORRECT
- if (ui_but_is_cursor_warp(but)) {
- /* OK but can go outside bounds */
- if (is_horizontal) {
- data->ungrab_mval[0] = but->rect.xmin + (f * cursor_x_range);
- data->ungrab_mval[1] = BLI_rctf_cent_y(&but->rect);
- }
- else {
- data->ungrab_mval[1] = but->rect.ymin + (f * cursor_x_range);
- data->ungrab_mval[0] = BLI_rctf_cent_x(&but->rect);
- }
- BLI_rctf_clamp_pt_v(&but->rect, data->ungrab_mval);
- }
+ if (ui_but_is_cursor_warp(but)) {
+ /* OK but can go outside bounds */
+ if (is_horizontal) {
+ data->ungrab_mval[0] = but->rect.xmin + (f * cursor_x_range);
+ data->ungrab_mval[1] = BLI_rctf_cent_y(&but->rect);
+ }
+ else {
+ data->ungrab_mval[1] = but->rect.ymin + (f * cursor_x_range);
+ data->ungrab_mval[0] = BLI_rctf_cent_x(&but->rect);
+ }
+ BLI_rctf_clamp_pt_v(&but->rect, data->ungrab_mval);
+ }
#endif
- /* done correcting mouse */
-
-
- tempf = softmin + f * softrange;
- temp = round_fl_to_int(tempf);
-
- if (snap) {
- if (tempf == softmin || tempf == softmax) {
- /* pass */
- }
- else if (ui_but_is_float(but)) {
-
- if (shift) {
- if (tempf == softmin || tempf == softmax) {}
- else if (softrange < 2.10f) { tempf = roundf(tempf * 100.0f) * 0.01f; }
- else if (softrange < 21.0f) { tempf = roundf(tempf * 10.0f) * 0.1f; }
- else { tempf = roundf(tempf); }
- }
- else {
- if (softrange < 2.10f) { tempf = roundf(tempf * 10.0f) * 0.1f; }
- else if (softrange < 21.0f) { tempf = roundf(tempf); }
- else { tempf = roundf(tempf * 0.1f) * 10.0f; }
- }
- }
- else {
- temp = 10 * (temp / 10);
- tempf = temp;
- }
- }
-
- if (!ui_but_is_float(but)) {
- lvalue = round(data->value);
-
- CLAMP(temp, softmin, softmax);
-
- if (temp != lvalue) {
- data->value = temp;
- data->dragchange = true;
- changed = true;
- }
- }
- else {
- CLAMP(tempf, softmin, softmax);
-
- if (tempf != (float)data->value) {
- data->value = tempf;
- data->dragchange = true;
- changed = true;
- }
- }
-
- return changed;
+ /* done correcting mouse */
+
+ tempf = softmin + f * softrange;
+ temp = round_fl_to_int(tempf);
+
+ if (snap) {
+ if (tempf == softmin || tempf == softmax) {
+ /* pass */
+ }
+ else if (ui_but_is_float(but)) {
+
+ if (shift) {
+ if (tempf == softmin || tempf == softmax) {
+ }
+ else if (softrange < 2.10f) {
+ tempf = roundf(tempf * 100.0f) * 0.01f;
+ }
+ else if (softrange < 21.0f) {
+ tempf = roundf(tempf * 10.0f) * 0.1f;
+ }
+ else {
+ tempf = roundf(tempf);
+ }
+ }
+ else {
+ if (softrange < 2.10f) {
+ tempf = roundf(tempf * 10.0f) * 0.1f;
+ }
+ else if (softrange < 21.0f) {
+ tempf = roundf(tempf);
+ }
+ else {
+ tempf = roundf(tempf * 0.1f) * 10.0f;
+ }
+ }
+ }
+ else {
+ temp = 10 * (temp / 10);
+ tempf = temp;
+ }
+ }
+
+ if (!ui_but_is_float(but)) {
+ lvalue = round(data->value);
+
+ CLAMP(temp, softmin, softmax);
+
+ if (temp != lvalue) {
+ data->value = temp;
+ data->dragchange = true;
+ changed = true;
+ }
+ }
+ else {
+ CLAMP(tempf, softmin, softmax);
+
+ if (tempf != (float)data->value) {
+ data->value = tempf;
+ data->dragchange = true;
+ changed = true;
+ }
+ }
+
+ return changed;
}
static int ui_do_but_SLI(
- bContext *C, uiBlock *block, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
- int mx, my, click = 0;
- int retval = WM_UI_HANDLER_CONTINUE;
-
- mx = event->x;
- my = event->y;
- ui_window_to_block(data->region, block, &mx, &my);
-
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- int type = event->type, val = event->val;
-
- if (type == MOUSEPAN) {
- ui_pan_to_scroll(event, &type, &val);
- }
-
- /* XXX hardcoded keymap check.... */
- if (type == MOUSEPAN && event->alt) {
- /* allow accumulating values, otherwise scrolling gets preference */
- retval = WM_UI_HANDLER_BREAK;
- }
- else if (type == WHEELDOWNMOUSE && event->ctrl) {
- mx = but->rect.xmin;
- click = 2;
- }
- else if (type == WHEELUPMOUSE && event->ctrl) {
- mx = but->rect.xmax;
- click = 2;
- }
- else if (event->val == KM_PRESS) {
- if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->ctrl) {
- button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
- retval = WM_UI_HANDLER_BREAK;
- }
+ bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ int mx, my, click = 0;
+ int retval = WM_UI_HANDLER_CONTINUE;
+
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ int type = event->type, val = event->val;
+
+ if (type == MOUSEPAN) {
+ ui_pan_to_scroll(event, &type, &val);
+ }
+
+ /* XXX hardcoded keymap check.... */
+ if (type == MOUSEPAN && event->alt) {
+ /* allow accumulating values, otherwise scrolling gets preference */
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (type == WHEELDOWNMOUSE && event->ctrl) {
+ mx = but->rect.xmin;
+ click = 2;
+ }
+ else if (type == WHEELUPMOUSE && event->ctrl) {
+ mx = but->rect.xmax;
+ click = 2;
+ }
+ else if (event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->ctrl) {
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ retval = WM_UI_HANDLER_BREAK;
+ }
#ifndef USE_ALLSELECT
- /* alt-click on sides to get "arrows" like in UI_BTYPE_NUM buttons,
- * and match wheel usage above */
- else if (event->type == LEFTMOUSE && event->alt) {
- int halfpos = BLI_rctf_cent_x(&but->rect);
- click = 2;
- if (mx < halfpos) {
- mx = but->rect.xmin;
- }
- else {
- mx = but->rect.xmax;
- }
- }
+ /* alt-click on sides to get "arrows" like in UI_BTYPE_NUM buttons,
+ * and match wheel usage above */
+ else if (event->type == LEFTMOUSE && event->alt) {
+ int halfpos = BLI_rctf_cent_x(&but->rect);
+ click = 2;
+ if (mx < halfpos) {
+ mx = but->rect.xmin;
+ }
+ else {
+ mx = but->rect.xmax;
+ }
+ }
#endif
- else if (event->type == LEFTMOUSE) {
- data->dragstartx = mx;
- data->draglastx = mx;
- 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) {
- click = 1;
- }
- else if (event->type == 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);
- retval = WM_UI_HANDLER_BREAK;
- }
- }
+ else if (event->type == LEFTMOUSE) {
+ data->dragstartx = mx;
+ data->draglastx = mx;
+ 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) {
+ click = 1;
+ }
+ else if (event->type == 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);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
#ifdef USE_DRAG_MULTINUM
- copy_v2_v2_int(data->multi_data.drag_start, &event->x);
+ copy_v2_v2_int(data->multi_data.drag_start, &event->x);
#endif
- }
- else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
- if (event->val == KM_PRESS) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- }
- else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- if (data->dragchange) {
+ }
+ else if (data->state == BUTTON_STATE_NUM_EDITING) {
+ if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ if (data->dragchange) {
#ifdef USE_DRAG_MULTINUM
- /* if we started multibutton but didn't drag, then edit */
- if (data->multi_data.init == BUTTON_MULTI_INIT_SETUP) {
- click = 1;
- }
- else
+ /* if we started multibutton but didn't drag, then edit */
+ if (data->multi_data.init == BUTTON_MULTI_INIT_SETUP) {
+ click = 1;
+ }
+ else
#endif
- {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- }
- else {
+ {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+ else {
#ifdef USE_CONT_MOUSE_CORRECT
- /* reset! */
- copy_v2_fl(data->ungrab_mval, FLT_MAX);
+ /* reset! */
+ copy_v2_fl(data->ungrab_mval, FLT_MAX);
#endif
- click = 1;
- }
- }
- else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
- const bool is_motion = (event->type == MOUSEMOVE);
+ click = 1;
+ }
+ }
+ else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
+ const bool is_motion = (event->type == MOUSEMOVE);
#ifdef USE_DRAG_MULTINUM
- data->multi_data.drag_dir[0] += abs(data->draglastx - mx);
- data->multi_data.drag_dir[1] += abs(data->draglasty - my);
+ data->multi_data.drag_dir[0] += abs(data->draglastx - mx);
+ data->multi_data.drag_dir[1] += abs(data->draglasty - my);
#endif
- if (ui_numedit_but_SLI(but, data, mx, true, is_motion, event->ctrl != 0, event->shift != 0)) {
- ui_numedit_apply(C, block, but, data);
- }
+ if (ui_numedit_but_SLI(
+ but, data, mx, true, is_motion, event->ctrl != 0, event->shift != 0)) {
+ ui_numedit_apply(C, block, but, data);
+ }
#ifdef USE_DRAG_MULTINUM
- else if (data->multi_data.has_mbuts) {
- if (data->multi_data.init == BUTTON_MULTI_INIT_ENABLE) {
- ui_multibut_states_apply(C, data, block);
- }
- }
+ else if (data->multi_data.has_mbuts) {
+ if (data->multi_data.init == BUTTON_MULTI_INIT_ENABLE) {
+ ui_multibut_states_apply(C, data, block);
+ }
+ }
#endif
- }
- retval = WM_UI_HANDLER_BREAK;
- }
- else if (data->state == BUTTON_STATE_TEXT_EDITING) {
- ui_do_but_textedit(C, block, but, data, event);
- retval = WM_UI_HANDLER_BREAK;
- }
- else if (data->state == BUTTON_STATE_TEXT_SELECTING) {
- ui_do_but_textedit_select(C, block, but, data, event);
- retval = WM_UI_HANDLER_BREAK;
- }
-
- if (click) {
- if (click == 2) {
- /* nudge slider to the left or right */
- float f, tempf, softmin, softmax, softrange;
- int temp;
-
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
-
- softmin = but->softmin;
- softmax = but->softmax;
- softrange = softmax - softmin;
-
- tempf = data->value;
- temp = (int)data->value;
+ }
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (data->state == BUTTON_STATE_TEXT_EDITING) {
+ ui_do_but_textedit(C, block, but, data, event);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (data->state == BUTTON_STATE_TEXT_SELECTING) {
+ ui_do_but_textedit_select(C, block, but, data, event);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+
+ if (click) {
+ if (click == 2) {
+ /* nudge slider to the left or right */
+ float f, tempf, softmin, softmax, softrange;
+ int temp;
+
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ softmin = but->softmin;
+ softmax = but->softmax;
+ softrange = softmax - softmin;
+
+ tempf = data->value;
+ temp = (int)data->value;
#if 0
- if (but->type == SLI) {
- /* same as below */
- f = (float)(mx - but->rect.xmin) / (BLI_rctf_size_x(&but->rect));
- }
- else
+ if (but->type == SLI) {
+ /* same as below */
+ f = (float)(mx - but->rect.xmin) / (BLI_rctf_size_x(&but->rect));
+ }
+ else
#endif
- {
- f = (float)(mx - but->rect.xmin) / (BLI_rctf_size_x(&but->rect));
- }
-
- f = softmin + f * softrange;
-
- if (!ui_but_is_float(but)) {
- if (f < temp) {
- temp--;
- }
- else {
- temp++;
- }
-
- if (temp >= softmin && temp <= softmax) {
- data->value = temp;
- }
- else {
- data->cancel = true;
- }
- }
- else {
- if (f < tempf) {
- tempf -= 0.01f;
- }
- else {
- tempf += 0.01f;
- }
-
- if (tempf >= softmin && tempf <= softmax) {
- data->value = tempf;
- }
- else {
- data->cancel = true;
- }
- }
-
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- retval = WM_UI_HANDLER_BREAK;
- }
- else {
- /* edit the value directly */
- button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
- retval = WM_UI_HANDLER_BREAK;
- }
- }
-
- data->draglastx = mx;
- data->draglasty = my;
-
- return retval;
+ {
+ f = (float)(mx - but->rect.xmin) / (BLI_rctf_size_x(&but->rect));
+ }
+
+ f = softmin + f * softrange;
+
+ if (!ui_but_is_float(but)) {
+ if (f < temp) {
+ temp--;
+ }
+ else {
+ temp++;
+ }
+
+ if (temp >= softmin && temp <= softmax) {
+ data->value = temp;
+ }
+ else {
+ data->cancel = true;
+ }
+ }
+ else {
+ if (f < tempf) {
+ tempf -= 0.01f;
+ }
+ else {
+ tempf += 0.01f;
+ }
+
+ if (tempf >= softmin && tempf <= softmax) {
+ data->value = tempf;
+ }
+ else {
+ data->cancel = true;
+ }
+ }
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else {
+ /* edit the value directly */
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ data->draglastx = mx;
+ data->draglasty = my;
+
+ return retval;
}
static int ui_do_but_SCROLL(
- bContext *C, uiBlock *block, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
- int mx, my /*, click = 0 */;
- int retval = WM_UI_HANDLER_CONTINUE;
- bool horizontal = (BLI_rctf_size_x(&but->rect) > BLI_rctf_size_y(&but->rect));
-
- mx = event->x;
- my = event->y;
- ui_window_to_block(data->region, block, &mx, &my);
-
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (event->val == KM_PRESS) {
- if (event->type == LEFTMOUSE) {
- if (horizontal) {
- data->dragstartx = mx;
- data->draglastx = mx;
- }
- else {
- data->dragstartx = my;
- data->draglastx = my;
- }
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- retval = WM_UI_HANDLER_BREAK;
- }
- /* UNUSED - otherwise code is ok, add back if needed */
+ bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ int mx, my /*, click = 0 */;
+ int retval = WM_UI_HANDLER_CONTINUE;
+ bool horizontal = (BLI_rctf_size_x(&but->rect) > BLI_rctf_size_y(&but->rect));
+
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (event->val == KM_PRESS) {
+ if (event->type == LEFTMOUSE) {
+ if (horizontal) {
+ data->dragstartx = mx;
+ data->draglastx = mx;
+ }
+ else {
+ data->dragstartx = my;
+ data->draglastx = my;
+ }
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ /* UNUSED - otherwise code is ok, add back if needed */
#if 0
- else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS) {
- click = 1;
- }
+ else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ click = 1;
+ }
#endif
- }
- }
- else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == ESCKEY) {
- if (event->val == KM_PRESS) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- }
- else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- else if (event->type == MOUSEMOVE) {
- const bool is_motion = (event->type == MOUSEMOVE);
- if (ui_numedit_but_SLI(but, data, (horizontal) ? mx : my, horizontal, is_motion, false, false)) {
- ui_numedit_apply(C, block, but, data);
- }
- }
-
- retval = WM_UI_HANDLER_BREAK;
- }
-
- return retval;
+ }
+ }
+ else if (data->state == BUTTON_STATE_NUM_EDITING) {
+ if (event->type == ESCKEY) {
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else if (event->type == MOUSEMOVE) {
+ const bool is_motion = (event->type == MOUSEMOVE);
+ if (ui_numedit_but_SLI(
+ but, data, (horizontal) ? mx : my, horizontal, is_motion, false, false)) {
+ ui_numedit_apply(C, block, but, data);
+ }
+ }
+
+ retval = WM_UI_HANDLER_BREAK;
+ }
+
+ return retval;
}
static int ui_do_but_GRIP(
- bContext *C, uiBlock *block, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
- int mx, my;
- int retval = WM_UI_HANDLER_CONTINUE;
- const bool horizontal = (BLI_rctf_size_x(&but->rect) < BLI_rctf_size_y(&but->rect));
-
- /* Note: Having to store org point in window space and recompute it to block "space" each time
- * is not ideal, but this is a way to hack around behavior of ui_window_to_block(), which
- * returns different results when the block is inside a panel or not...
- * See T37739.
- */
-
- mx = event->x;
- my = event->y;
- ui_window_to_block(data->region, block, &mx, &my);
-
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (event->val == KM_PRESS) {
- if (event->type == LEFTMOUSE) {
- data->dragstartx = event->x;
- data->dragstarty = event->y;
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- retval = WM_UI_HANDLER_BREAK;
- }
- }
- }
- else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == ESCKEY) {
- if (event->val == KM_PRESS) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- }
- else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- else if (event->type == MOUSEMOVE) {
- int dragstartx = data->dragstartx;
- int dragstarty = data->dragstarty;
- ui_window_to_block(data->region, block, &dragstartx, &dragstarty);
- data->value = data->origvalue + (horizontal ? mx - dragstartx : dragstarty - my);
- ui_numedit_apply(C, block, but, data);
- }
-
- retval = WM_UI_HANDLER_BREAK;
- }
-
- return retval;
-}
-
-static int ui_do_but_LISTROW(
- bContext *C, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- /* 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 && event->ctrl) ||
- (event->type == LEFTMOUSE && event->val == KM_DBL_CLICK))
- {
- uiBut *labelbut = ui_but_list_row_text_activate(C, but, data, event, BUTTON_ACTIVATE_TEXT_EDITING);
- if (labelbut) {
- /* Nothing else to do. */
- return WM_UI_HANDLER_BREAK;
- }
- }
- }
-
- return ui_do_but_EXIT(C, but, data, event);
-}
-
-static int ui_do_but_BLOCK(
- bContext *C, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
-
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
-
- /* first handle click on icondrag type button */
- if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) {
- if (ui_but_contains_point_px_icon(but, data->region, event)) {
- button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
- data->dragstartx = event->x;
- data->dragstarty = event->y;
- return WM_UI_HANDLER_BREAK;
- }
- }
+ bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ int mx, my;
+ int retval = WM_UI_HANDLER_CONTINUE;
+ const bool horizontal = (BLI_rctf_size_x(&but->rect) < BLI_rctf_size_y(&but->rect));
+
+ /* Note: Having to store org point in window space and recompute it to block "space" each time
+ * is not ideal, but this is a way to hack around behavior of ui_window_to_block(), which
+ * returns different results when the block is inside a panel or not...
+ * See T37739.
+ */
+
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (event->val == KM_PRESS) {
+ if (event->type == LEFTMOUSE) {
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
+ }
+ else if (data->state == BUTTON_STATE_NUM_EDITING) {
+ if (event->type == ESCKEY) {
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else if (event->type == MOUSEMOVE) {
+ int dragstartx = data->dragstartx;
+ int dragstarty = data->dragstarty;
+ ui_window_to_block(data->region, block, &dragstartx, &dragstarty);
+ data->value = data->origvalue + (horizontal ? mx - dragstartx : dragstarty - my);
+ ui_numedit_apply(C, block, but, data);
+ }
+
+ retval = WM_UI_HANDLER_BREAK;
+ }
+
+ return retval;
+}
+
+static int ui_do_but_LISTROW(bContext *C,
+ uiBut *but,
+ uiHandleButtonData *data,
+ const wmEvent *event)
+{
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ /* 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 &&
+ event->ctrl) ||
+ (event->type == LEFTMOUSE && event->val == KM_DBL_CLICK)) {
+ uiBut *labelbut = ui_but_list_row_text_activate(
+ C, but, data, event, BUTTON_ACTIVATE_TEXT_EDITING);
+ if (labelbut) {
+ /* Nothing else to do. */
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ }
+
+ return ui_do_but_EXIT(C, but, data, event);
+}
+
+static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+
+ /* first handle click on icondrag type button */
+ if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) {
+ if (ui_but_contains_point_px_icon(but, data->region, event)) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
#ifdef USE_DRAG_TOGGLE
- if (event->type == LEFTMOUSE && event->val == KM_PRESS && (ui_but_is_drag_toggle(but))) {
- button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
- data->dragstartx = event->x;
- data->dragstarty = event->y;
- return WM_UI_HANDLER_BREAK;
- }
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS && (ui_but_is_drag_toggle(but))) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ return WM_UI_HANDLER_BREAK;
+ }
#endif
- /* regular open menu */
- if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
- button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
- return WM_UI_HANDLER_BREAK;
- }
- else if (but->type == UI_BTYPE_MENU) {
- if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) {
- const int direction = (event->type == WHEELDOWNMOUSE) ? -1 : 1;
-
- data->value = ui_but_menu_step(but, direction);
-
- 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)
- */
- data->postbut = but;
- data->posttype = BUTTON_ACTIVATE_OVER;
-
- /* without this, a new interface that draws as result of the menu change
- * won't register that the mouse is over it, eg:
- * Alt+MouseWheel over the render slots, without this,
- * the slot menu fails to switch a second time.
- *
- * The active state of the button could be maintained some other way
- * and remove this mousemove event.
- */
- WM_event_add_mousemove(C);
-
- return WM_UI_HANDLER_BREAK;
- }
- }
- }
- else if (data->state == BUTTON_STATE_WAIT_DRAG) {
-
- /* this function also ends state */
- if (ui_but_drag_init(C, but, data, event)) {
- return WM_UI_HANDLER_BREAK;
- }
-
- /* outside icon quit, not needed if drag activated */
- if (0 == ui_but_contains_point_px_icon(but, data->region, event)) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- data->cancel = true;
- return WM_UI_HANDLER_BREAK;
- }
-
- if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
- return WM_UI_HANDLER_BREAK;
- }
-
- }
-
- return WM_UI_HANDLER_CONTINUE;
+ /* regular open menu */
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if (but->type == UI_BTYPE_MENU) {
+ if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) {
+ const int direction = (event->type == WHEELDOWNMOUSE) ? -1 : 1;
+
+ data->value = ui_but_menu_step(but, direction);
+
+ 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)
+ */
+ data->postbut = but;
+ data->posttype = BUTTON_ACTIVATE_OVER;
+
+ /* without this, a new interface that draws as result of the menu change
+ * won't register that the mouse is over it, eg:
+ * Alt+MouseWheel over the render slots, without this,
+ * the slot menu fails to switch a second time.
+ *
+ * The active state of the button could be maintained some other way
+ * and remove this mousemove event.
+ */
+ WM_event_add_mousemove(C);
+
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ }
+ else if (data->state == BUTTON_STATE_WAIT_DRAG) {
+
+ /* this function also ends state */
+ if (ui_but_drag_init(C, but, data, event)) {
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ /* outside icon quit, not needed if drag activated */
+ if (0 == ui_but_contains_point_px_icon(but, data->region, event)) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ data->cancel = true;
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
}
static bool ui_numedit_but_UNITVEC(
- uiBut *but, uiHandleButtonData *data,
- int mx, int my,
- const enum eSnapType snap)
-{
- float dx, dy, rad, radsq, mrad, *fp;
- int mdx, mdy;
- bool changed = true;
-
- /* button is presumed square */
- /* if mouse moves outside of sphere, it does negative normal */
-
- /* note that both data->vec and data->origvec should be normalized
- * else we'll get a harmless but annoying jump when first clicking */
-
- fp = data->origvec;
- rad = BLI_rctf_size_x(&but->rect);
- radsq = rad * rad;
-
- if (fp[2] > 0.0f) {
- mdx = (rad * fp[0]);
- mdy = (rad * fp[1]);
- }
- else if (fp[2] > -1.0f) {
- mrad = rad / sqrtf(fp[0] * fp[0] + fp[1] * fp[1]);
-
- mdx = 2.0f * mrad * fp[0] - (rad * fp[0]);
- mdy = 2.0f * mrad * fp[1] - (rad * fp[1]);
- }
- else {
- mdx = mdy = 0;
- }
-
- dx = (float)(mx + mdx - data->dragstartx);
- dy = (float)(my + mdy - data->dragstarty);
-
- fp = data->vec;
- mrad = dx * dx + dy * dy;
- if (mrad < radsq) { /* inner circle */
- fp[0] = dx;
- fp[1] = dy;
- fp[2] = sqrtf(radsq - dx * dx - dy * dy);
- }
- else { /* outer circle */
-
- mrad = rad / sqrtf(mrad); // veclen
-
- dx *= (2.0f * mrad - 1.0f);
- dy *= (2.0f * mrad - 1.0f);
-
- mrad = dx * dx + dy * dy;
- if (mrad < radsq) {
- fp[0] = dx;
- fp[1] = dy;
- fp[2] = -sqrtf(radsq - dx * dx - dy * dy);
- }
- }
- normalize_v3(fp);
-
- if (snap != SNAP_OFF) {
- const int snap_steps = (snap == SNAP_ON) ? 4 : 12; /* 45 or 15 degree increments */
- const float snap_steps_angle = M_PI / snap_steps;
- float angle, angle_snap;
- int i;
-
- /* round each axis of 'fp' to the next increment
- * do this in "angle" space - this gives increments of same size */
- for (i = 0; i < 3; i++) {
- angle = asinf(fp[i]);
- angle_snap = roundf((angle / snap_steps_angle)) * snap_steps_angle;
- fp[i] = sinf(angle_snap);
- }
- normalize_v3(fp);
- changed = !compare_v3v3(fp, data->origvec, FLT_EPSILON);
- }
-
- data->draglastx = mx;
- data->draglasty = my;
-
- return changed;
+ uiBut *but, uiHandleButtonData *data, int mx, int my, const enum eSnapType snap)
+{
+ float dx, dy, rad, radsq, mrad, *fp;
+ int mdx, mdy;
+ bool changed = true;
+
+ /* button is presumed square */
+ /* if mouse moves outside of sphere, it does negative normal */
+
+ /* note that both data->vec and data->origvec should be normalized
+ * else we'll get a harmless but annoying jump when first clicking */
+
+ fp = data->origvec;
+ rad = BLI_rctf_size_x(&but->rect);
+ radsq = rad * rad;
+
+ if (fp[2] > 0.0f) {
+ mdx = (rad * fp[0]);
+ mdy = (rad * fp[1]);
+ }
+ else if (fp[2] > -1.0f) {
+ mrad = rad / sqrtf(fp[0] * fp[0] + fp[1] * fp[1]);
+
+ mdx = 2.0f * mrad * fp[0] - (rad * fp[0]);
+ mdy = 2.0f * mrad * fp[1] - (rad * fp[1]);
+ }
+ else {
+ mdx = mdy = 0;
+ }
+
+ dx = (float)(mx + mdx - data->dragstartx);
+ dy = (float)(my + mdy - data->dragstarty);
+
+ fp = data->vec;
+ mrad = dx * dx + dy * dy;
+ if (mrad < radsq) { /* inner circle */
+ fp[0] = dx;
+ fp[1] = dy;
+ fp[2] = sqrtf(radsq - dx * dx - dy * dy);
+ }
+ else { /* outer circle */
+
+ mrad = rad / sqrtf(mrad); // veclen
+
+ dx *= (2.0f * mrad - 1.0f);
+ dy *= (2.0f * mrad - 1.0f);
+
+ mrad = dx * dx + dy * dy;
+ if (mrad < radsq) {
+ fp[0] = dx;
+ fp[1] = dy;
+ fp[2] = -sqrtf(radsq - dx * dx - dy * dy);
+ }
+ }
+ normalize_v3(fp);
+
+ if (snap != SNAP_OFF) {
+ const int snap_steps = (snap == SNAP_ON) ? 4 : 12; /* 45 or 15 degree increments */
+ const float snap_steps_angle = M_PI / snap_steps;
+ float angle, angle_snap;
+ int i;
+
+ /* round each axis of 'fp' to the next increment
+ * do this in "angle" space - this gives increments of same size */
+ for (i = 0; i < 3; i++) {
+ angle = asinf(fp[i]);
+ angle_snap = roundf((angle / snap_steps_angle)) * snap_steps_angle;
+ fp[i] = sinf(angle_snap);
+ }
+ normalize_v3(fp);
+ changed = !compare_v3v3(fp, data->origvec, FLT_EPSILON);
+ }
+
+ data->draglastx = mx;
+ data->draglasty = my;
+
+ return changed;
}
static void ui_palette_set_active(uiBut *but)
{
- if ((int)(but->a1) == UI_PALETTE_COLOR) {
- Palette *palette = but->rnapoin.id.data;
- PaletteColor *color = but->rnapoin.data;
- palette->active_color = BLI_findindex(&palette->colors, color);
- }
-}
-
-static int ui_do_but_COLOR(
- bContext *C, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- /* first handle click on icondrag type button */
- if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) {
- ui_palette_set_active(but);
- if (ui_but_contains_point_px_icon(but, data->region, event)) {
- button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
- data->dragstartx = event->x;
- data->dragstarty = event->y;
- return WM_UI_HANDLER_BREAK;
- }
- }
+ if ((int)(but->a1) == UI_PALETTE_COLOR) {
+ Palette *palette = but->rnapoin.id.data;
+ PaletteColor *color = but->rnapoin.data;
+ palette->active_color = BLI_findindex(&palette->colors, color);
+ }
+}
+
+static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ /* first handle click on icondrag type button */
+ if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) {
+ ui_palette_set_active(but);
+ if (ui_but_contains_point_px_icon(but, data->region, event)) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
#ifdef USE_DRAG_TOGGLE
- if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
- ui_palette_set_active(but);
- button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
- data->dragstartx = event->x;
- data->dragstarty = event->y;
- return WM_UI_HANDLER_BREAK;
- }
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
+ ui_palette_set_active(but);
+ button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ return WM_UI_HANDLER_BREAK;
+ }
#endif
- /* regular open menu */
- if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
- ui_palette_set_active(but);
- button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
- return WM_UI_HANDLER_BREAK;
- }
- else if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) {
- ColorPicker *cpicker = but->custom_data;
- float hsv_static[3] = {0.0f};
- float *hsv = cpicker ? cpicker->color_data : hsv_static;
- float col[3];
-
- ui_but_v3_get(but, col);
- rgb_to_hsv_compat_v(col, hsv);
-
- if (event->type == WHEELDOWNMOUSE) {
- hsv[2] = clamp_f(hsv[2] - 0.05f, 0.0f, 1.0f);
- }
- else if (event->type == WHEELUPMOUSE) {
- hsv[2] = clamp_f(hsv[2] + 0.05f, 0.0f, 1.0f);
- }
- else {
- float fac = 0.005 * (event->y - event->prevy);
- hsv[2] = clamp_f(hsv[2] + fac, 0.0f, 1.0f);
- }
-
- hsv_to_rgb_v(hsv, data->vec);
- ui_but_v3_set(but, data->vec);
-
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- 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 && event->val == KM_PRESS)
- {
- Palette *palette = but->rnapoin.id.data;
- PaletteColor *color = but->rnapoin.data;
-
- BKE_palette_color_remove(palette, color);
-
- button_activate_state(C, but, BUTTON_STATE_EXIT);
-
- /* this is risky. it works OK for now,
- * but if it gives trouble we should delay execution */
- but->rnapoin = PointerRNA_NULL;
- but->rnaprop = NULL;
-
- return WM_UI_HANDLER_BREAK;
- }
- }
- else if (data->state == BUTTON_STATE_WAIT_DRAG) {
-
- /* this function also ends state */
- if (ui_but_drag_init(C, but, data, event)) {
- return WM_UI_HANDLER_BREAK;
- }
-
- /* outside icon quit, not needed if drag activated */
- if (0 == ui_but_contains_point_px_icon(but, data->region, event)) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- data->cancel = true;
- return WM_UI_HANDLER_BREAK;
- }
-
- if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- if ((int)(but->a1) == UI_PALETTE_COLOR) {
- if (!event->ctrl) {
- float color[3];
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Paint *paint = BKE_paint_get_active(scene, view_layer);
- Brush *brush = BKE_paint_brush(paint);
-
- if (brush->flag & BRUSH_USE_GRADIENT) {
- float *target = &brush->gradient->data[brush->gradient->cur].r;
-
- if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
- RNA_property_float_get_array(&but->rnapoin, but->rnaprop, target);
- IMB_colormanagement_srgb_to_scene_linear_v3(target);
- }
- else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
- RNA_property_float_get_array(&but->rnapoin, but->rnaprop, target);
- }
- }
- else {
- 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);
- }
- 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);
- }
- }
-
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- else {
- button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
- }
- }
- else {
- button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
- }
- return WM_UI_HANDLER_BREAK;
- }
-
- }
-
- return WM_UI_HANDLER_CONTINUE;
+ /* regular open menu */
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ ui_palette_set_active(but);
+ button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) {
+ ColorPicker *cpicker = but->custom_data;
+ float hsv_static[3] = {0.0f};
+ float *hsv = cpicker ? cpicker->color_data : hsv_static;
+ float col[3];
+
+ ui_but_v3_get(but, col);
+ rgb_to_hsv_compat_v(col, hsv);
+
+ if (event->type == WHEELDOWNMOUSE) {
+ hsv[2] = clamp_f(hsv[2] - 0.05f, 0.0f, 1.0f);
+ }
+ else if (event->type == WHEELUPMOUSE) {
+ hsv[2] = clamp_f(hsv[2] + 0.05f, 0.0f, 1.0f);
+ }
+ else {
+ float fac = 0.005 * (event->y - event->prevy);
+ hsv[2] = clamp_f(hsv[2] + fac, 0.0f, 1.0f);
+ }
+
+ hsv_to_rgb_v(hsv, data->vec);
+ ui_but_v3_set(but, data->vec);
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ 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 &&
+ event->val == KM_PRESS) {
+ Palette *palette = but->rnapoin.id.data;
+ PaletteColor *color = but->rnapoin.data;
+
+ BKE_palette_color_remove(palette, color);
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+
+ /* this is risky. it works OK for now,
+ * but if it gives trouble we should delay execution */
+ but->rnapoin = PointerRNA_NULL;
+ but->rnaprop = NULL;
+
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if (data->state == BUTTON_STATE_WAIT_DRAG) {
+
+ /* this function also ends state */
+ if (ui_but_drag_init(C, but, data, event)) {
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ /* outside icon quit, not needed if drag activated */
+ if (0 == ui_but_contains_point_px_icon(but, data->region, event)) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ data->cancel = true;
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ if ((int)(but->a1) == UI_PALETTE_COLOR) {
+ if (!event->ctrl) {
+ float color[3];
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Paint *paint = BKE_paint_get_active(scene, view_layer);
+ Brush *brush = BKE_paint_brush(paint);
+
+ if (brush->flag & BRUSH_USE_GRADIENT) {
+ float *target = &brush->gradient->data[brush->gradient->cur].r;
+
+ if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
+ RNA_property_float_get_array(&but->rnapoin, but->rnaprop, target);
+ IMB_colormanagement_srgb_to_scene_linear_v3(target);
+ }
+ else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
+ RNA_property_float_get_array(&but->rnapoin, but->rnaprop, target);
+ }
+ }
+ else {
+ 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);
+ }
+ 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);
+ }
+ }
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else {
+ button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
+ }
+ }
+ else {
+ button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
+ }
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
}
static int ui_do_but_UNITVEC(
- bContext *C, uiBlock *block, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
- int mx, my;
-
- mx = event->x;
- my = event->y;
- ui_window_to_block(data->region, block, &mx, &my);
-
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
- const enum eSnapType snap = ui_event_to_snap(event);
- data->dragstartx = mx;
- data->dragstarty = my;
- data->draglastx = mx;
- data->draglasty = my;
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
-
- /* also do drag the first time */
- if (ui_numedit_but_UNITVEC(but, data, mx, my, snap)) {
- ui_numedit_apply(C, block, but, data);
- }
-
- return WM_UI_HANDLER_BREAK;
- }
- }
- else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
- if (mx != data->draglastx || my != data->draglasty || event->type != MOUSEMOVE) {
- const enum eSnapType snap = ui_event_to_snap(event);
- if (ui_numedit_but_UNITVEC(but, data, mx, my, snap)) {
- ui_numedit_apply(C, block, but, data);
- }
- }
- }
- else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
-
- return WM_UI_HANDLER_BREAK;
- }
-
- return WM_UI_HANDLER_CONTINUE;
+ bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ int mx, my;
+
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
+ const enum eSnapType snap = ui_event_to_snap(event);
+ data->dragstartx = mx;
+ data->dragstarty = my;
+ data->draglastx = mx;
+ data->draglasty = my;
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ /* also do drag the first time */
+ if (ui_numedit_but_UNITVEC(but, data, mx, my, snap)) {
+ ui_numedit_apply(C, block, but, data);
+ }
+
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if (data->state == BUTTON_STATE_NUM_EDITING) {
+ if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
+ if (mx != data->draglastx || my != data->draglasty || event->type != MOUSEMOVE) {
+ const enum eSnapType snap = ui_event_to_snap(event);
+ if (ui_numedit_but_UNITVEC(but, data, mx, my, snap)) {
+ ui_numedit_apply(C, block, but, data);
+ }
+ }
+ }
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
}
/* scales a vector so no axis exceeds max
* (could become BLI_math func) */
static void clamp_axis_max_v3(float v[3], const float max)
{
- const float v_max = max_fff(v[0], v[1], v[2]);
- if (v_max > max) {
- mul_v3_fl(v, max / v_max);
- if (v[0] > max) {
- v[0] = max;
- }
- if (v[1] > max) {
- v[1] = max;
- }
- if (v[2] > max) {
- v[2] = max;
- }
- }
+ const float v_max = max_fff(v[0], v[1], v[2]);
+ if (v_max > max) {
+ mul_v3_fl(v, max / v_max);
+ if (v[0] > max) {
+ v[0] = max;
+ }
+ if (v[1] > max) {
+ v[1] = max;
+ }
+ if (v[2] > max) {
+ v[2] = max;
+ }
+ }
}
static void ui_rgb_to_color_picker_HSVCUBE_compat_v(uiBut *but, const float rgb[3], float hsv[3])
{
- if (but->a1 == UI_GRAD_L_ALT) {
- rgb_to_hsl_compat_v(rgb, hsv);
- }
- else {
- rgb_to_hsv_compat_v(rgb, hsv);
- }
+ if (but->a1 == UI_GRAD_L_ALT) {
+ rgb_to_hsl_compat_v(rgb, hsv);
+ }
+ else {
+ rgb_to_hsv_compat_v(rgb, hsv);
+ }
}
static void ui_rgb_to_color_picker_HSVCUBE_v(uiBut *but, const float rgb[3], float hsv[3])
{
- if (but->a1 == UI_GRAD_L_ALT) {
- rgb_to_hsl_v(rgb, hsv);
- }
- else {
- rgb_to_hsv_v(rgb, hsv);
- }
+ if (but->a1 == UI_GRAD_L_ALT) {
+ rgb_to_hsl_v(rgb, hsv);
+ }
+ else {
+ rgb_to_hsv_v(rgb, hsv);
+ }
}
static void ui_color_picker_to_rgb_HSVCUBE_v(uiBut *but, const float hsv[3], float rgb[3])
{
- if (but->a1 == UI_GRAD_L_ALT) {
- hsl_to_rgb_v(hsv, rgb);
- }
- else {
- hsv_to_rgb_v(hsv, rgb);
- }
+ if (but->a1 == UI_GRAD_L_ALT) {
+ hsl_to_rgb_v(hsv, rgb);
+ }
+ else {
+ hsv_to_rgb_v(hsv, rgb);
+ }
}
-static bool ui_numedit_but_HSVCUBE(
- uiBut *but, uiHandleButtonData *data,
- int mx, int my,
- const enum eSnapType snap, const bool shift)
+static bool ui_numedit_but_HSVCUBE(uiBut *but,
+ uiHandleButtonData *data,
+ int mx,
+ int my,
+ const enum eSnapType snap,
+ const bool shift)
{
- ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
- float rgb[3];
- float x, y;
- float mx_fl, my_fl;
- bool changed = true;
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
+ float rgb[3];
+ float x, y;
+ float mx_fl, my_fl;
+ bool changed = true;
- ui_mouse_scale_warp(data, mx, my, &mx_fl, &my_fl, shift);
+ ui_mouse_scale_warp(data, mx, my, &mx_fl, &my_fl, shift);
#ifdef USE_CONT_MOUSE_CORRECT
- if (ui_but_is_cursor_warp(but)) {
- /* OK but can go outside bounds */
- data->ungrab_mval[0] = mx_fl;
- data->ungrab_mval[1] = my_fl;
- BLI_rctf_clamp_pt_v(&but->rect, data->ungrab_mval);
- }
+ if (ui_but_is_cursor_warp(but)) {
+ /* OK but can go outside bounds */
+ data->ungrab_mval[0] = mx_fl;
+ data->ungrab_mval[1] = my_fl;
+ BLI_rctf_clamp_pt_v(&but->rect, data->ungrab_mval);
+ }
#endif
- ui_but_v3_get(but, rgb);
- ui_scene_linear_to_color_picker_space(but, rgb);
-
- ui_rgb_to_color_picker_HSVCUBE_compat_v(but, rgb, hsv);
-
- /* only apply the delta motion, not absolute */
- if (shift) {
- rcti rect_i;
- float xpos, ypos, hsvo[3];
-
- BLI_rcti_rctf_copy(&rect_i, &but->rect);
-
- /* calculate original hsv again */
- copy_v3_v3(rgb, data->origvec);
- ui_scene_linear_to_color_picker_space(but, rgb);
-
- copy_v3_v3(hsvo, hsv);
-
- ui_rgb_to_color_picker_HSVCUBE_compat_v(but, rgb, hsvo);
-
- /* and original position */
- ui_hsvcube_pos_from_vals(but, &rect_i, hsvo, &xpos, &ypos);
-
- mx_fl = xpos - (data->dragstartx - mx_fl);
- my_fl = ypos - (data->dragstarty - my_fl);
- }
-
- /* relative position within box */
- x = ((float)mx_fl - but->rect.xmin) / BLI_rctf_size_x(&but->rect);
- y = ((float)my_fl - but->rect.ymin) / BLI_rctf_size_y(&but->rect);
- CLAMP(x, 0.0f, 1.0f);
- CLAMP(y, 0.0f, 1.0f);
-
- switch ((int)but->a1) {
- case UI_GRAD_SV:
- hsv[1] = x;
- hsv[2] = y;
- break;
- case UI_GRAD_HV:
- hsv[0] = x;
- hsv[2] = y;
- break;
- case UI_GRAD_HS:
- hsv[0] = x;
- hsv[1] = y;
- break;
- case UI_GRAD_H:
- hsv[0] = x;
- break;
- case UI_GRAD_S:
- hsv[1] = x;
- break;
- case UI_GRAD_V:
- hsv[2] = x;
- break;
- case UI_GRAD_L_ALT:
- hsv[2] = y;
- break;
- case UI_GRAD_V_ALT:
- {
- /* vertical 'value' strip */
- float min = but->softmin, max = but->softmax;
- /* exception only for value strip - use the range set in but->min/max */
- hsv[2] = y * (max - min) + min;
- break;
- }
- default:
- BLI_assert(0);
- break;
- }
-
- if (snap != SNAP_OFF) {
- if (ELEM((int)but->a1, UI_GRAD_HV, UI_GRAD_HS, UI_GRAD_H)) {
- ui_color_snap_hue(snap, &hsv[0]);
- }
- }
-
- ui_color_picker_to_rgb_HSVCUBE_v(but, hsv, rgb);
- ui_color_picker_to_scene_linear_space(but, rgb);
-
- /* clamp because with color conversion we can exceed range [#34295] */
- if (but->a1 == UI_GRAD_V_ALT) {
- clamp_axis_max_v3(rgb, but->softmax);
- }
-
- copy_v3_v3(data->vec, rgb);
-
- data->draglastx = mx;
- data->draglasty = my;
-
- return changed;
+ ui_but_v3_get(but, rgb);
+ ui_scene_linear_to_color_picker_space(but, rgb);
+
+ ui_rgb_to_color_picker_HSVCUBE_compat_v(but, rgb, hsv);
+
+ /* only apply the delta motion, not absolute */
+ if (shift) {
+ rcti rect_i;
+ float xpos, ypos, hsvo[3];
+
+ BLI_rcti_rctf_copy(&rect_i, &but->rect);
+
+ /* calculate original hsv again */
+ copy_v3_v3(rgb, data->origvec);
+ ui_scene_linear_to_color_picker_space(but, rgb);
+
+ copy_v3_v3(hsvo, hsv);
+
+ ui_rgb_to_color_picker_HSVCUBE_compat_v(but, rgb, hsvo);
+
+ /* and original position */
+ ui_hsvcube_pos_from_vals(but, &rect_i, hsvo, &xpos, &ypos);
+
+ mx_fl = xpos - (data->dragstartx - mx_fl);
+ my_fl = ypos - (data->dragstarty - my_fl);
+ }
+
+ /* relative position within box */
+ x = ((float)mx_fl - but->rect.xmin) / BLI_rctf_size_x(&but->rect);
+ y = ((float)my_fl - but->rect.ymin) / BLI_rctf_size_y(&but->rect);
+ CLAMP(x, 0.0f, 1.0f);
+ CLAMP(y, 0.0f, 1.0f);
+
+ switch ((int)but->a1) {
+ case UI_GRAD_SV:
+ hsv[1] = x;
+ hsv[2] = y;
+ break;
+ case UI_GRAD_HV:
+ hsv[0] = x;
+ hsv[2] = y;
+ break;
+ case UI_GRAD_HS:
+ hsv[0] = x;
+ hsv[1] = y;
+ break;
+ case UI_GRAD_H:
+ hsv[0] = x;
+ break;
+ case UI_GRAD_S:
+ hsv[1] = x;
+ break;
+ case UI_GRAD_V:
+ hsv[2] = x;
+ break;
+ case UI_GRAD_L_ALT:
+ hsv[2] = y;
+ break;
+ case UI_GRAD_V_ALT: {
+ /* vertical 'value' strip */
+ float min = but->softmin, max = but->softmax;
+ /* exception only for value strip - use the range set in but->min/max */
+ hsv[2] = y * (max - min) + min;
+ break;
+ }
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ if (snap != SNAP_OFF) {
+ if (ELEM((int)but->a1, UI_GRAD_HV, UI_GRAD_HS, UI_GRAD_H)) {
+ ui_color_snap_hue(snap, &hsv[0]);
+ }
+ }
+
+ ui_color_picker_to_rgb_HSVCUBE_v(but, hsv, rgb);
+ ui_color_picker_to_scene_linear_space(but, rgb);
+
+ /* clamp because with color conversion we can exceed range [#34295] */
+ if (but->a1 == UI_GRAD_V_ALT) {
+ clamp_axis_max_v3(rgb, but->softmax);
+ }
+
+ copy_v3_v3(data->vec, rgb);
+
+ data->draglastx = mx;
+ data->draglasty = my;
+
+ return changed;
}
#ifdef WITH_INPUT_NDOF
-static void ui_ndofedit_but_HSVCUBE(
- uiBut *but, uiHandleButtonData *data,
- const wmNDOFMotionData *ndof,
- const enum eSnapType snap, const bool shift)
-{
- ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
- const float hsv_v_max = max_ff(hsv[2], but->softmax);
- float rgb[3];
- float sensitivity = (shift ? 0.15f : 0.3f) * ndof->dt;
-
- ui_but_v3_get(but, rgb);
- ui_scene_linear_to_color_picker_space(but, rgb);
- ui_rgb_to_color_picker_HSVCUBE_compat_v(but, rgb, hsv);
-
- switch ((int)but->a1) {
- case UI_GRAD_SV:
- hsv[1] += ndof->rvec[2] * sensitivity;
- hsv[2] += ndof->rvec[0] * sensitivity;
- break;
- case UI_GRAD_HV:
- hsv[0] += ndof->rvec[2] * sensitivity;
- hsv[2] += ndof->rvec[0] * sensitivity;
- break;
- case UI_GRAD_HS:
- hsv[0] += ndof->rvec[2] * sensitivity;
- hsv[1] += ndof->rvec[0] * sensitivity;
- break;
- case UI_GRAD_H:
- hsv[0] += ndof->rvec[2] * sensitivity;
- break;
- case UI_GRAD_S:
- hsv[1] += ndof->rvec[2] * sensitivity;
- break;
- case UI_GRAD_V:
- hsv[2] += ndof->rvec[2] * sensitivity;
- break;
- case UI_GRAD_V_ALT:
- case UI_GRAD_L_ALT:
- /* vertical 'value' strip */
-
- /* exception only for value strip - use the range set in but->min/max */
- hsv[2] += ndof->rvec[0] * sensitivity;
-
- CLAMP(hsv[2], but->softmin, but->softmax);
- break;
- default:
- assert(!"invalid hsv type");
- break;
- }
-
- if (snap != SNAP_OFF) {
- if (ELEM((int)but->a1, UI_GRAD_HV, UI_GRAD_HS, UI_GRAD_H)) {
- ui_color_snap_hue(snap, &hsv[0]);
- }
- }
-
- /* ndof specific: the changes above aren't clamping */
- hsv_clamp_v(hsv, hsv_v_max);
-
- ui_color_picker_to_rgb_HSVCUBE_v(but, hsv, rgb);
- ui_color_picker_to_scene_linear_space(but, rgb);
-
- copy_v3_v3(data->vec, rgb);
- ui_but_v3_set(but, data->vec);
+static void ui_ndofedit_but_HSVCUBE(uiBut *but,
+ uiHandleButtonData *data,
+ const wmNDOFMotionData *ndof,
+ const enum eSnapType snap,
+ const bool shift)
+{
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
+ const float hsv_v_max = max_ff(hsv[2], but->softmax);
+ float rgb[3];
+ float sensitivity = (shift ? 0.15f : 0.3f) * ndof->dt;
+
+ ui_but_v3_get(but, rgb);
+ ui_scene_linear_to_color_picker_space(but, rgb);
+ ui_rgb_to_color_picker_HSVCUBE_compat_v(but, rgb, hsv);
+
+ switch ((int)but->a1) {
+ case UI_GRAD_SV:
+ hsv[1] += ndof->rvec[2] * sensitivity;
+ hsv[2] += ndof->rvec[0] * sensitivity;
+ break;
+ case UI_GRAD_HV:
+ hsv[0] += ndof->rvec[2] * sensitivity;
+ hsv[2] += ndof->rvec[0] * sensitivity;
+ break;
+ case UI_GRAD_HS:
+ hsv[0] += ndof->rvec[2] * sensitivity;
+ hsv[1] += ndof->rvec[0] * sensitivity;
+ break;
+ case UI_GRAD_H:
+ hsv[0] += ndof->rvec[2] * sensitivity;
+ break;
+ case UI_GRAD_S:
+ hsv[1] += ndof->rvec[2] * sensitivity;
+ break;
+ case UI_GRAD_V:
+ hsv[2] += ndof->rvec[2] * sensitivity;
+ break;
+ case UI_GRAD_V_ALT:
+ case UI_GRAD_L_ALT:
+ /* vertical 'value' strip */
+
+ /* exception only for value strip - use the range set in but->min/max */
+ hsv[2] += ndof->rvec[0] * sensitivity;
+
+ CLAMP(hsv[2], but->softmin, but->softmax);
+ break;
+ default:
+ assert(!"invalid hsv type");
+ break;
+ }
+
+ if (snap != SNAP_OFF) {
+ if (ELEM((int)but->a1, UI_GRAD_HV, UI_GRAD_HS, UI_GRAD_H)) {
+ ui_color_snap_hue(snap, &hsv[0]);
+ }
+ }
+
+ /* ndof specific: the changes above aren't clamping */
+ hsv_clamp_v(hsv, hsv_v_max);
+
+ ui_color_picker_to_rgb_HSVCUBE_v(but, hsv, rgb);
+ ui_color_picker_to_scene_linear_space(but, rgb);
+
+ copy_v3_v3(data->vec, rgb);
+ ui_but_v3_set(but, data->vec);
}
#endif /* WITH_INPUT_NDOF */
static int ui_do_but_HSVCUBE(
- bContext *C, uiBlock *block, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
+ bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
- int mx, my;
+ int mx, my;
- mx = event->x;
- my = event->y;
- ui_window_to_block(data->region, block, &mx, &my);
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
- const enum eSnapType snap = ui_event_to_snap(event);
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
+ const enum eSnapType snap = ui_event_to_snap(event);
- data->dragstartx = mx;
- data->dragstarty = my;
- data->draglastx = mx;
- data->draglasty = my;
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+ data->dragstartx = mx;
+ data->dragstarty = my;
+ data->draglastx = mx;
+ data->draglasty = my;
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- /* also do drag the first time */
- if (ui_numedit_but_HSVCUBE(but, data, mx, my, snap, event->shift != 0)) {
- ui_numedit_apply(C, block, but, data);
- }
+ /* also do drag the first time */
+ if (ui_numedit_but_HSVCUBE(but, data, mx, my, snap, event->shift != 0)) {
+ ui_numedit_apply(C, block, but, data);
+ }
- return WM_UI_HANDLER_BREAK;
- }
+ return WM_UI_HANDLER_BREAK;
+ }
#ifdef WITH_INPUT_NDOF
- else if (event->type == NDOF_MOTION) {
- const wmNDOFMotionData *ndof = event->customdata;
- const enum eSnapType snap = ui_event_to_snap(event);
+ else if (event->type == NDOF_MOTION) {
+ const wmNDOFMotionData *ndof = event->customdata;
+ const enum eSnapType snap = ui_event_to_snap(event);
- ui_ndofedit_but_HSVCUBE(but, data, ndof, snap, event->shift != 0);
+ ui_ndofedit_but_HSVCUBE(but, data, ndof, snap, event->shift != 0);
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- ui_apply_but(C, but->block, but, data, true);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ ui_apply_but(C, but->block, but, data, true);
- return WM_UI_HANDLER_BREAK;
- }
+ return WM_UI_HANDLER_BREAK;
+ }
#endif /* WITH_INPUT_NDOF */
- /* XXX hardcoded keymap check.... */
- else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) {
- if (ELEM(but->a1, UI_GRAD_V_ALT, UI_GRAD_L_ALT)) {
- int len;
-
- /* reset only value */
-
- len = RNA_property_array_length(&but->rnapoin, but->rnaprop);
- if (ELEM(len, 3, 4)) {
- float rgb[3], def_hsv[3];
- float def[4];
- ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
-
- RNA_property_float_get_default_array(&but->rnapoin, but->rnaprop, def);
- ui_rgb_to_color_picker_HSVCUBE_v(but, def, def_hsv);
-
- ui_but_v3_get(but, rgb);
- ui_rgb_to_color_picker_HSVCUBE_compat_v(but, rgb, hsv);
-
- def_hsv[0] = hsv[0];
- def_hsv[1] = hsv[1];
-
- ui_color_picker_to_rgb_HSVCUBE_v(but, def_hsv, rgb);
- ui_but_v3_set(but, rgb);
-
- RNA_property_update(C, &but->rnapoin, but->rnaprop);
- return WM_UI_HANDLER_BREAK;
- }
- }
- }
- }
- else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
- if (event->val == KM_PRESS) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- }
- else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
- if (mx != data->draglastx || my != data->draglasty || event->type != MOUSEMOVE) {
- const enum eSnapType snap = ui_event_to_snap(event);
-
- if (ui_numedit_but_HSVCUBE(but, data, mx, my, snap, event->shift != 0)) {
- ui_numedit_apply(C, block, but, data);
- }
- }
- }
- else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
-
- return WM_UI_HANDLER_BREAK;
- }
-
- return WM_UI_HANDLER_CONTINUE;
-}
-
-static bool ui_numedit_but_HSVCIRCLE(
- uiBut *but, uiHandleButtonData *data,
- float mx, float my,
- const enum eSnapType snap, const bool shift)
-{
- rcti rect;
- bool changed = true;
- float mx_fl, my_fl;
- float rgb[3];
- ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
-
- ui_mouse_scale_warp(data, mx, my, &mx_fl, &my_fl, shift);
+ /* XXX hardcoded keymap check.... */
+ else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) {
+ if (ELEM(but->a1, UI_GRAD_V_ALT, UI_GRAD_L_ALT)) {
+ int len;
+
+ /* reset only value */
+
+ len = RNA_property_array_length(&but->rnapoin, but->rnaprop);
+ if (ELEM(len, 3, 4)) {
+ float rgb[3], def_hsv[3];
+ float def[4];
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
+
+ RNA_property_float_get_default_array(&but->rnapoin, but->rnaprop, def);
+ ui_rgb_to_color_picker_HSVCUBE_v(but, def, def_hsv);
+
+ ui_but_v3_get(but, rgb);
+ ui_rgb_to_color_picker_HSVCUBE_compat_v(but, rgb, hsv);
+
+ def_hsv[0] = hsv[0];
+ def_hsv[1] = hsv[1];
+
+ ui_color_picker_to_rgb_HSVCUBE_v(but, def_hsv, rgb);
+ ui_but_v3_set(but, rgb);
+
+ RNA_property_update(C, &but->rnapoin, but->rnaprop);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ }
+ }
+ else if (data->state == BUTTON_STATE_NUM_EDITING) {
+ if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+ else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
+ if (mx != data->draglastx || my != data->draglasty || event->type != MOUSEMOVE) {
+ const enum eSnapType snap = ui_event_to_snap(event);
+
+ if (ui_numedit_but_HSVCUBE(but, data, mx, my, snap, event->shift != 0)) {
+ ui_numedit_apply(C, block, but, data);
+ }
+ }
+ }
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
+static bool ui_numedit_but_HSVCIRCLE(uiBut *but,
+ uiHandleButtonData *data,
+ float mx,
+ float my,
+ const enum eSnapType snap,
+ const bool shift)
+{
+ rcti rect;
+ bool changed = true;
+ float mx_fl, my_fl;
+ float rgb[3];
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
+
+ ui_mouse_scale_warp(data, mx, my, &mx_fl, &my_fl, shift);
#ifdef USE_CONT_MOUSE_CORRECT
- if (ui_but_is_cursor_warp(but)) {
- /* OK but can go outside bounds */
- data->ungrab_mval[0] = mx_fl;
- data->ungrab_mval[1] = my_fl;
- { /* clamp */
- const float radius = min_ff(BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect)) / 2.0f;
- const float cent[2] = {BLI_rctf_cent_x(&but->rect), BLI_rctf_cent_y(&but->rect)};
- const float len = len_v2v2(cent, data->ungrab_mval);
- if (len > radius) {
- dist_ensure_v2_v2fl(data->ungrab_mval, cent, radius);
- }
- }
- }
+ if (ui_but_is_cursor_warp(but)) {
+ /* OK but can go outside bounds */
+ data->ungrab_mval[0] = mx_fl;
+ data->ungrab_mval[1] = my_fl;
+ { /* clamp */
+ const float radius = min_ff(BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect)) / 2.0f;
+ const float cent[2] = {BLI_rctf_cent_x(&but->rect), BLI_rctf_cent_y(&but->rect)};
+ const float len = len_v2v2(cent, data->ungrab_mval);
+ if (len > radius) {
+ dist_ensure_v2_v2fl(data->ungrab_mval, cent, radius);
+ }
+ }
+ }
#endif
- BLI_rcti_rctf_copy(&rect, &but->rect);
-
- ui_but_v3_get(but, rgb);
- ui_scene_linear_to_color_picker_space(but, rgb);
- ui_rgb_to_color_picker_compat_v(rgb, hsv);
+ BLI_rcti_rctf_copy(&rect, &but->rect);
- /* exception, when using color wheel in 'locked' value state:
- * allow choosing a hue for black values, by giving a tiny increment */
- if (cpicker->use_color_lock) {
- if (U.color_picker_type == USER_CP_CIRCLE_HSV) { // lock
- if (hsv[2] == 0.f) {
- hsv[2] = 0.0001f;
- }
- }
- else {
- if (hsv[2] == 0.0f) {
- hsv[2] = 0.0001f;
- }
- if (hsv[2] >= 0.9999f) {
- hsv[2] = 0.9999f;
- }
- }
- }
+ ui_but_v3_get(but, rgb);
+ ui_scene_linear_to_color_picker_space(but, rgb);
+ ui_rgb_to_color_picker_compat_v(rgb, hsv);
- /* only apply the delta motion, not absolute */
- if (shift) {
- float xpos, ypos, hsvo[3], rgbo[3];
+ /* exception, when using color wheel in 'locked' value state:
+ * allow choosing a hue for black values, by giving a tiny increment */
+ if (cpicker->use_color_lock) {
+ if (U.color_picker_type == USER_CP_CIRCLE_HSV) { // lock
+ if (hsv[2] == 0.f) {
+ hsv[2] = 0.0001f;
+ }
+ }
+ else {
+ if (hsv[2] == 0.0f) {
+ hsv[2] = 0.0001f;
+ }
+ if (hsv[2] >= 0.9999f) {
+ hsv[2] = 0.9999f;
+ }
+ }
+ }
- /* calculate original hsv again */
- copy_v3_v3(hsvo, hsv);
- copy_v3_v3(rgbo, data->origvec);
- ui_scene_linear_to_color_picker_space(but, rgbo);
- ui_rgb_to_color_picker_compat_v(rgbo, hsvo);
+ /* only apply the delta motion, not absolute */
+ if (shift) {
+ float xpos, ypos, hsvo[3], rgbo[3];
- /* and original position */
- ui_hsvcircle_pos_from_vals(cpicker, &rect, hsvo, &xpos, &ypos);
+ /* calculate original hsv again */
+ copy_v3_v3(hsvo, hsv);
+ copy_v3_v3(rgbo, data->origvec);
+ ui_scene_linear_to_color_picker_space(but, rgbo);
+ ui_rgb_to_color_picker_compat_v(rgbo, hsvo);
- mx_fl = xpos - (data->dragstartx - mx_fl);
- my_fl = ypos - (data->dragstarty - my_fl);
+ /* and original position */
+ ui_hsvcircle_pos_from_vals(cpicker, &rect, hsvo, &xpos, &ypos);
- }
+ mx_fl = xpos - (data->dragstartx - mx_fl);
+ my_fl = ypos - (data->dragstarty - my_fl);
+ }
- ui_hsvcircle_vals_from_pos(&rect, mx_fl, my_fl, hsv, hsv + 1);
+ ui_hsvcircle_vals_from_pos(&rect, mx_fl, my_fl, hsv, hsv + 1);
- if ((cpicker->use_color_cubic) && (U.color_picker_type == USER_CP_CIRCLE_HSV)) {
- hsv[1] = 1.0f - sqrt3f(1.0f - hsv[1]);
- }
+ if ((cpicker->use_color_cubic) && (U.color_picker_type == USER_CP_CIRCLE_HSV)) {
+ hsv[1] = 1.0f - sqrt3f(1.0f - hsv[1]);
+ }
- if (snap != SNAP_OFF) {
- ui_color_snap_hue(snap, &hsv[0]);
- }
+ if (snap != SNAP_OFF) {
+ ui_color_snap_hue(snap, &hsv[0]);
+ }
- ui_color_picker_to_rgb_v(hsv, rgb);
+ ui_color_picker_to_rgb_v(hsv, rgb);
- if ((cpicker->use_luminosity_lock)) {
- if (!is_zero_v3(rgb)) {
- normalize_v3_length(rgb, cpicker->luminosity_lock_value);
- }
- }
+ if ((cpicker->use_luminosity_lock)) {
+ if (!is_zero_v3(rgb)) {
+ normalize_v3_length(rgb, cpicker->luminosity_lock_value);
+ }
+ }
- ui_color_picker_to_scene_linear_space(but, rgb);
- ui_but_v3_set(but, rgb);
+ ui_color_picker_to_scene_linear_space(but, rgb);
+ ui_but_v3_set(but, rgb);
- data->draglastx = mx;
- data->draglasty = my;
+ data->draglastx = mx;
+ data->draglasty = my;
- return changed;
+ return changed;
}
#ifdef WITH_INPUT_NDOF
-static void ui_ndofedit_but_HSVCIRCLE(
- uiBut *but, uiHandleButtonData *data,
- const wmNDOFMotionData *ndof,
- const enum eSnapType snap, const bool shift)
-{
- ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
- float rgb[3];
- float phi, r /*, sqr */ /* UNUSED */, v[2];
- float sensitivity = (shift ? 0.06f : 0.3f) * ndof->dt;
-
- ui_but_v3_get(but, rgb);
- ui_scene_linear_to_color_picker_space(but, rgb);
- ui_rgb_to_color_picker_compat_v(rgb, hsv);
-
- /* Convert current color on hue/sat disc to circular coordinates phi, r */
- phi = fmodf(hsv[0] + 0.25f, 1.0f) * -2.0f * (float)M_PI;
- r = hsv[1];
- /* sqr = r > 0.0f ? sqrtf(r) : 1; */ /* UNUSED */
-
- /* Convert to 2d vectors */
- v[0] = r * cosf(phi);
- v[1] = r * sinf(phi);
-
- /* Use ndof device y and x rotation to move the vector in 2d space */
- v[0] += ndof->rvec[2] * sensitivity;
- v[1] += ndof->rvec[0] * sensitivity;
-
- /* convert back to polar coords on circle */
- phi = atan2f(v[0], v[1]) / (2.0f * (float)M_PI) + 0.5f;
-
- /* use ndof Y rotation to additionally rotate hue */
- phi += ndof->rvec[1] * sensitivity * 0.5f;
- r = len_v2(v);
-
- /* convert back to hsv values, in range [0,1] */
- hsv[0] = phi;
- hsv[1] = r;
-
- /* exception, when using color wheel in 'locked' value state:
- * allow choosing a hue for black values, by giving a tiny increment */
- if (cpicker->use_color_lock) {
- if (U.color_picker_type == USER_CP_CIRCLE_HSV) { // lock
- if (hsv[2] == 0.f) {
- hsv[2] = 0.0001f;
- }
- }
- else {
- if (hsv[2] == 0.f) {
- hsv[2] = 0.0001f;
- }
- if (hsv[2] == 1.f) {
- hsv[2] = 0.9999f;
- }
- }
- }
-
- if (snap != SNAP_OFF) {
- ui_color_snap_hue(snap, &hsv[0]);
- }
-
- hsv_clamp_v(hsv, FLT_MAX);
-
- ui_color_picker_to_rgb_v(hsv, data->vec);
-
- if (cpicker->use_luminosity_lock) {
- if (!is_zero_v3(data->vec)) {
- normalize_v3_length(data->vec, cpicker->luminosity_lock_value);
- }
- }
-
- ui_color_picker_to_scene_linear_space(but, data->vec);
- ui_but_v3_set(but, data->vec);
+static void ui_ndofedit_but_HSVCIRCLE(uiBut *but,
+ uiHandleButtonData *data,
+ const wmNDOFMotionData *ndof,
+ const enum eSnapType snap,
+ const bool shift)
+{
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
+ float rgb[3];
+ float phi, r /*, sqr */ /* UNUSED */, v[2];
+ float sensitivity = (shift ? 0.06f : 0.3f) * ndof->dt;
+
+ ui_but_v3_get(but, rgb);
+ ui_scene_linear_to_color_picker_space(but, rgb);
+ ui_rgb_to_color_picker_compat_v(rgb, hsv);
+
+ /* Convert current color on hue/sat disc to circular coordinates phi, r */
+ phi = fmodf(hsv[0] + 0.25f, 1.0f) * -2.0f * (float)M_PI;
+ r = hsv[1];
+ /* sqr = r > 0.0f ? sqrtf(r) : 1; */ /* UNUSED */
+
+ /* Convert to 2d vectors */
+ v[0] = r * cosf(phi);
+ v[1] = r * sinf(phi);
+
+ /* Use ndof device y and x rotation to move the vector in 2d space */
+ v[0] += ndof->rvec[2] * sensitivity;
+ v[1] += ndof->rvec[0] * sensitivity;
+
+ /* convert back to polar coords on circle */
+ phi = atan2f(v[0], v[1]) / (2.0f * (float)M_PI) + 0.5f;
+
+ /* use ndof Y rotation to additionally rotate hue */
+ phi += ndof->rvec[1] * sensitivity * 0.5f;
+ r = len_v2(v);
+
+ /* convert back to hsv values, in range [0,1] */
+ hsv[0] = phi;
+ hsv[1] = r;
+
+ /* exception, when using color wheel in 'locked' value state:
+ * allow choosing a hue for black values, by giving a tiny increment */
+ if (cpicker->use_color_lock) {
+ if (U.color_picker_type == USER_CP_CIRCLE_HSV) { // lock
+ if (hsv[2] == 0.f) {
+ hsv[2] = 0.0001f;
+ }
+ }
+ else {
+ if (hsv[2] == 0.f) {
+ hsv[2] = 0.0001f;
+ }
+ if (hsv[2] == 1.f) {
+ hsv[2] = 0.9999f;
+ }
+ }
+ }
+
+ if (snap != SNAP_OFF) {
+ ui_color_snap_hue(snap, &hsv[0]);
+ }
+
+ hsv_clamp_v(hsv, FLT_MAX);
+
+ ui_color_picker_to_rgb_v(hsv, data->vec);
+
+ if (cpicker->use_luminosity_lock) {
+ if (!is_zero_v3(data->vec)) {
+ normalize_v3_length(data->vec, cpicker->luminosity_lock_value);
+ }
+ }
+
+ ui_color_picker_to_scene_linear_space(but, data->vec);
+ ui_but_v3_set(but, data->vec);
}
#endif /* WITH_INPUT_NDOF */
static int ui_do_but_HSVCIRCLE(
- bContext *C, uiBlock *block, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
- ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
- int mx, my;
- mx = event->x;
- my = event->y;
- ui_window_to_block(data->region, block, &mx, &my);
-
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
- const enum eSnapType snap = ui_event_to_snap(event);
- data->dragstartx = mx;
- data->dragstarty = my;
- data->draglastx = mx;
- data->draglasty = my;
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
-
- /* also do drag the first time */
- if (ui_numedit_but_HSVCIRCLE(but, data, mx, my, snap, event->shift != 0)) {
- ui_numedit_apply(C, block, but, data);
- }
-
- return WM_UI_HANDLER_BREAK;
- }
+ bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
+ int mx, my;
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
+ const enum eSnapType snap = ui_event_to_snap(event);
+ data->dragstartx = mx;
+ data->dragstarty = my;
+ data->draglastx = mx;
+ data->draglasty = my;
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ /* also do drag the first time */
+ if (ui_numedit_but_HSVCIRCLE(but, data, mx, my, snap, event->shift != 0)) {
+ ui_numedit_apply(C, block, but, data);
+ }
+
+ return WM_UI_HANDLER_BREAK;
+ }
#ifdef WITH_INPUT_NDOF
- else if (event->type == NDOF_MOTION) {
- const enum eSnapType snap = ui_event_to_snap(event);
- const wmNDOFMotionData *ndof = event->customdata;
+ else if (event->type == NDOF_MOTION) {
+ const enum eSnapType snap = ui_event_to_snap(event);
+ const wmNDOFMotionData *ndof = event->customdata;
- ui_ndofedit_but_HSVCIRCLE(but, data, ndof, snap, event->shift != 0);
+ ui_ndofedit_but_HSVCIRCLE(but, data, ndof, snap, event->shift != 0);
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- ui_apply_but(C, but->block, but, data, true);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ ui_apply_but(C, but->block, but, data, true);
- return WM_UI_HANDLER_BREAK;
- }
+ return WM_UI_HANDLER_BREAK;
+ }
#endif /* WITH_INPUT_NDOF */
- /* XXX hardcoded keymap check.... */
- else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) {
- int len;
-
- /* reset only saturation */
-
- len = RNA_property_array_length(&but->rnapoin, but->rnaprop);
- if (len >= 3) {
- float rgb[3], def_hsv[3];
- float *def;
- def = MEM_callocN(sizeof(float) * len, "reset_defaults - float");
-
- RNA_property_float_get_default_array(&but->rnapoin, but->rnaprop, def);
- ui_color_picker_to_rgb_v(def, def_hsv);
-
- ui_but_v3_get(but, rgb);
- ui_rgb_to_color_picker_compat_v(rgb, hsv);
-
- def_hsv[0] = hsv[0];
- def_hsv[2] = hsv[2];
-
- hsv_to_rgb_v(def_hsv, rgb);
- ui_but_v3_set(but, rgb);
-
- RNA_property_update(C, &but->rnapoin, but->rnaprop);
-
- MEM_freeN(def);
- }
- return WM_UI_HANDLER_BREAK;
- }
- }
- else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
- if (event->val == KM_PRESS) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- }
- /* XXX hardcoded keymap check.... */
- else if (event->type == WHEELDOWNMOUSE) {
- hsv[2] = clamp_f(hsv[2] - 0.05f, 0.0f, 1.0f);
- ui_but_hsv_set(but); /* converts to rgb */
- ui_numedit_apply(C, block, but, data);
- }
- else if (event->type == WHEELUPMOUSE) {
- hsv[2] = clamp_f(hsv[2] + 0.05f, 0.0f, 1.0f);
- ui_but_hsv_set(but); /* converts to rgb */
- ui_numedit_apply(C, block, but, data);
- }
- else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
- if (mx != data->draglastx || my != data->draglasty || event->type != MOUSEMOVE) {
- const enum eSnapType snap = ui_event_to_snap(event);
-
- if (ui_numedit_but_HSVCIRCLE(but, data, mx, my, snap, event->shift != 0)) {
- ui_numedit_apply(C, block, but, data);
- }
- }
- }
- else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- return WM_UI_HANDLER_BREAK;
- }
-
- return WM_UI_HANDLER_CONTINUE;
+ /* XXX hardcoded keymap check.... */
+ else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) {
+ int len;
+
+ /* reset only saturation */
+
+ len = RNA_property_array_length(&but->rnapoin, but->rnaprop);
+ if (len >= 3) {
+ float rgb[3], def_hsv[3];
+ float *def;
+ def = MEM_callocN(sizeof(float) * len, "reset_defaults - float");
+
+ RNA_property_float_get_default_array(&but->rnapoin, but->rnaprop, def);
+ ui_color_picker_to_rgb_v(def, def_hsv);
+
+ ui_but_v3_get(but, rgb);
+ ui_rgb_to_color_picker_compat_v(rgb, hsv);
+
+ def_hsv[0] = hsv[0];
+ def_hsv[2] = hsv[2];
+
+ hsv_to_rgb_v(def_hsv, rgb);
+ ui_but_v3_set(but, rgb);
+
+ RNA_property_update(C, &but->rnapoin, but->rnaprop);
+
+ MEM_freeN(def);
+ }
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if (data->state == BUTTON_STATE_NUM_EDITING) {
+ if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+ /* XXX hardcoded keymap check.... */
+ else if (event->type == WHEELDOWNMOUSE) {
+ hsv[2] = clamp_f(hsv[2] - 0.05f, 0.0f, 1.0f);
+ ui_but_hsv_set(but); /* converts to rgb */
+ ui_numedit_apply(C, block, but, data);
+ }
+ else if (event->type == WHEELUPMOUSE) {
+ hsv[2] = clamp_f(hsv[2] + 0.05f, 0.0f, 1.0f);
+ ui_but_hsv_set(but); /* converts to rgb */
+ ui_numedit_apply(C, block, but, data);
+ }
+ else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
+ if (mx != data->draglastx || my != data->draglasty || event->type != MOUSEMOVE) {
+ const enum eSnapType snap = ui_event_to_snap(event);
+
+ if (ui_numedit_but_HSVCIRCLE(but, data, mx, my, snap, event->shift != 0)) {
+ ui_numedit_apply(C, block, but, data);
+ }
+ }
+ }
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
}
-
static bool ui_numedit_but_COLORBAND(uiBut *but, uiHandleButtonData *data, int mx)
{
- float dx;
- bool changed = false;
+ float dx;
+ bool changed = false;
- if (data->draglastx == mx) {
- return changed;
- }
+ if (data->draglastx == mx) {
+ return changed;
+ }
- if (data->coba->tot == 0) {
- return changed;
- }
+ if (data->coba->tot == 0) {
+ return changed;
+ }
- dx = ((float)(mx - data->draglastx)) / BLI_rctf_size_x(&but->rect);
- data->dragcbd->pos += dx;
- CLAMP(data->dragcbd->pos, 0.0f, 1.0f);
+ dx = ((float)(mx - data->draglastx)) / BLI_rctf_size_x(&but->rect);
+ data->dragcbd->pos += dx;
+ CLAMP(data->dragcbd->pos, 0.0f, 1.0f);
- BKE_colorband_update_sort(data->coba);
- data->dragcbd = data->coba->data + data->coba->cur; /* because qsort */
+ BKE_colorband_update_sort(data->coba);
+ data->dragcbd = data->coba->data + data->coba->cur; /* because qsort */
- data->draglastx = mx;
- changed = true;
+ data->draglastx = mx;
+ changed = true;
- return changed;
+ return changed;
}
static int ui_do_but_COLORBAND(
- bContext *C, uiBlock *block, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
- ColorBand *coba;
- CBData *cbd;
- /* ignore zoom-level for mindist */
- int mindist = (50 * UI_DPI_FAC) * block->aspect;
- int mx, my, a, xco;
-
- mx = event->x;
- my = event->y;
- ui_window_to_block(data->region, block, &mx, &my);
-
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
- coba = (ColorBand *)but->poin;
-
- if (event->ctrl) {
- /* insert new key on mouse location */
- float pos = ((float)(mx - but->rect.xmin)) / BLI_rctf_size_x(&but->rect);
- BKE_colorband_element_add(coba, pos);
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- else {
- data->dragstartx = mx;
- data->dragstarty = my;
- data->draglastx = mx;
- data->draglasty = my;
-
- /* 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);
- if (a == coba->cur) {
- /* Selected one disadvantage. */
- xco += 5;
- }
- if (xco < mindist) {
- coba->cur = a;
- mindist = xco;
- }
- }
-
- data->dragcbd = coba->data + coba->cur;
- data->dragfstart = data->dragcbd->pos;
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- }
-
- return WM_UI_HANDLER_BREAK;
- }
- }
- else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == MOUSEMOVE) {
- if (mx != data->draglastx || my != data->draglasty) {
- if (ui_numedit_but_COLORBAND(but, data, mx)) {
- ui_numedit_apply(C, block, but, data);
- }
- }
- }
- else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- else if (ELEM(event->type, ESCKEY, RIGHTMOUSE)) {
- if (event->val == KM_PRESS) {
- data->dragcbd->pos = data->dragfstart;
- BKE_colorband_update_sort(data->coba);
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- }
- return WM_UI_HANDLER_BREAK;
- }
-
- return WM_UI_HANDLER_CONTINUE;
-}
-
-static bool ui_numedit_but_CURVE(
- uiBlock *block, uiBut *but, uiHandleButtonData *data,
- int evtx, int evty,
- bool snap, const bool shift)
-{
- CurveMapping *cumap = (CurveMapping *)but->poin;
- CurveMap *cuma = cumap->cm + cumap->cur;
- CurveMapPoint *cmp = cuma->curve;
- float fx, fy, zoomx, zoomy;
- int mx, my, dragx, dragy;
- int a;
- bool changed = false;
-
- /* evtx evty and drag coords are absolute mousecoords,
- * prevents errors when editing when layout changes */
- mx = evtx;
- my = evty;
- ui_window_to_block(data->region, block, &mx, &my);
- dragx = data->draglastx;
- dragy = data->draglasty;
- ui_window_to_block(data->region, block, &dragx, &dragy);
-
- zoomx = BLI_rctf_size_x(&but->rect) / BLI_rctf_size_x(&cumap->curr);
- zoomy = BLI_rctf_size_y(&but->rect) / BLI_rctf_size_y(&cumap->curr);
-
- if (snap) {
- float d[2];
-
- d[0] = mx - data->dragstartx;
- d[1] = my - data->dragstarty;
-
- if (len_squared_v2(d) < (3.0f * 3.0f)) {
- snap = false;
- }
- }
-
- if (data->dragsel != -1) {
- CurveMapPoint *cmp_last = NULL;
- const float mval_factor = ui_mouse_scale_warp_factor(shift);
- bool moved_point = false; /* for ctrl grid, can't use orig coords because of sorting */
-
- fx = (mx - dragx) / zoomx;
- fy = (my - dragy) / zoomy;
-
- fx *= mval_factor;
- fy *= mval_factor;
-
- for (a = 0; a < cuma->totpoint; a++) {
- if (cmp[a].flag & CUMA_SELECT) {
- float origx = cmp[a].x, origy = cmp[a].y;
- cmp[a].x += fx;
- cmp[a].y += fy;
- if (snap) {
- cmp[a].x = 0.125f * roundf(8.0f * cmp[a].x);
- cmp[a].y = 0.125f * roundf(8.0f * cmp[a].y);
- }
- if (cmp[a].x != origx || cmp[a].y != origy) {
- moved_point = true;
- }
-
- cmp_last = &cmp[a];
- }
- }
-
- curvemapping_changed(cumap, false);
-
- if (moved_point) {
- data->draglastx = evtx;
- data->draglasty = evty;
- changed = true;
+ bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ ColorBand *coba;
+ CBData *cbd;
+ /* ignore zoom-level for mindist */
+ int mindist = (50 * UI_DPI_FAC) * block->aspect;
+ int mx, my, a, xco;
+
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
+ coba = (ColorBand *)but->poin;
+
+ if (event->ctrl) {
+ /* insert new key on mouse location */
+ float pos = ((float)(mx - but->rect.xmin)) / BLI_rctf_size_x(&but->rect);
+ BKE_colorband_element_add(coba, pos);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else {
+ data->dragstartx = mx;
+ data->dragstarty = my;
+ data->draglastx = mx;
+ data->draglasty = my;
+
+ /* 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);
+ if (a == coba->cur) {
+ /* Selected one disadvantage. */
+ xco += 5;
+ }
+ if (xco < mindist) {
+ coba->cur = a;
+ mindist = xco;
+ }
+ }
+
+ data->dragcbd = coba->data + coba->cur;
+ data->dragfstart = data->dragcbd->pos;
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+ }
+
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if (data->state == BUTTON_STATE_NUM_EDITING) {
+ if (event->type == MOUSEMOVE) {
+ if (mx != data->draglastx || my != data->draglasty) {
+ if (ui_numedit_but_COLORBAND(but, data, mx)) {
+ ui_numedit_apply(C, block, but, data);
+ }
+ }
+ }
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else if (ELEM(event->type, ESCKEY, RIGHTMOUSE)) {
+ if (event->val == KM_PRESS) {
+ data->dragcbd->pos = data->dragfstart;
+ BKE_colorband_update_sort(data->coba);
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
+static bool ui_numedit_but_CURVE(uiBlock *block,
+ uiBut *but,
+ uiHandleButtonData *data,
+ int evtx,
+ int evty,
+ bool snap,
+ const bool shift)
+{
+ CurveMapping *cumap = (CurveMapping *)but->poin;
+ CurveMap *cuma = cumap->cm + cumap->cur;
+ CurveMapPoint *cmp = cuma->curve;
+ float fx, fy, zoomx, zoomy;
+ int mx, my, dragx, dragy;
+ int a;
+ bool changed = false;
+
+ /* evtx evty and drag coords are absolute mousecoords,
+ * prevents errors when editing when layout changes */
+ mx = evtx;
+ my = evty;
+ ui_window_to_block(data->region, block, &mx, &my);
+ dragx = data->draglastx;
+ dragy = data->draglasty;
+ ui_window_to_block(data->region, block, &dragx, &dragy);
+
+ zoomx = BLI_rctf_size_x(&but->rect) / BLI_rctf_size_x(&cumap->curr);
+ zoomy = BLI_rctf_size_y(&but->rect) / BLI_rctf_size_y(&cumap->curr);
+
+ if (snap) {
+ float d[2];
+
+ d[0] = mx - data->dragstartx;
+ d[1] = my - data->dragstarty;
+
+ if (len_squared_v2(d) < (3.0f * 3.0f)) {
+ snap = false;
+ }
+ }
+
+ if (data->dragsel != -1) {
+ CurveMapPoint *cmp_last = NULL;
+ const float mval_factor = ui_mouse_scale_warp_factor(shift);
+ bool moved_point = false; /* for ctrl grid, can't use orig coords because of sorting */
+
+ fx = (mx - dragx) / zoomx;
+ fy = (my - dragy) / zoomy;
+
+ fx *= mval_factor;
+ fy *= mval_factor;
+
+ for (a = 0; a < cuma->totpoint; a++) {
+ if (cmp[a].flag & CUMA_SELECT) {
+ float origx = cmp[a].x, origy = cmp[a].y;
+ cmp[a].x += fx;
+ cmp[a].y += fy;
+ if (snap) {
+ cmp[a].x = 0.125f * roundf(8.0f * cmp[a].x);
+ cmp[a].y = 0.125f * roundf(8.0f * cmp[a].y);
+ }
+ if (cmp[a].x != origx || cmp[a].y != origy) {
+ moved_point = true;
+ }
+
+ cmp_last = &cmp[a];
+ }
+ }
+
+ curvemapping_changed(cumap, false);
+
+ if (moved_point) {
+ data->draglastx = evtx;
+ data->draglasty = evty;
+ changed = true;
#ifdef USE_CONT_MOUSE_CORRECT
- /* note: using 'cmp_last' is weak since there may be multiple points selected,
- * but in practice this isnt really an issue */
- if (ui_but_is_cursor_warp(but)) {
- /* OK but can go outside bounds */
- data->ungrab_mval[0] = but->rect.xmin + ((cmp_last->x - cumap->curr.xmin) * zoomx);
- data->ungrab_mval[1] = but->rect.ymin + ((cmp_last->y - cumap->curr.ymin) * zoomy);
- BLI_rctf_clamp_pt_v(&but->rect, data->ungrab_mval);
- }
+ /* note: using 'cmp_last' is weak since there may be multiple points selected,
+ * but in practice this isnt really an issue */
+ if (ui_but_is_cursor_warp(but)) {
+ /* OK but can go outside bounds */
+ data->ungrab_mval[0] = but->rect.xmin + ((cmp_last->x - cumap->curr.xmin) * zoomx);
+ data->ungrab_mval[1] = but->rect.ymin + ((cmp_last->y - cumap->curr.ymin) * zoomy);
+ BLI_rctf_clamp_pt_v(&but->rect, data->ungrab_mval);
+ }
#endif
-
- }
-
- data->dragchange = true; /* mark for selection */
- }
- else {
- fx = (mx - dragx) / zoomx;
- fy = (my - dragy) / zoomy;
-
- /* clamp for clip */
- if (cumap->flag & CUMA_DO_CLIP) {
- if (cumap->curr.xmin - fx < cumap->clipr.xmin) {
- fx = cumap->curr.xmin - cumap->clipr.xmin;
- }
- else if (cumap->curr.xmax - fx > cumap->clipr.xmax) {
- fx = cumap->curr.xmax - cumap->clipr.xmax;
- }
- if (cumap->curr.ymin - fy < cumap->clipr.ymin) {
- fy = cumap->curr.ymin - cumap->clipr.ymin;
- }
- else if (cumap->curr.ymax - fy > cumap->clipr.ymax) {
- fy = cumap->curr.ymax - cumap->clipr.ymax;
- }
- }
-
- cumap->curr.xmin -= fx;
- cumap->curr.ymin -= fy;
- cumap->curr.xmax -= fx;
- cumap->curr.ymax -= fy;
-
- data->draglastx = evtx;
- data->draglasty = evty;
-
- changed = true;
- }
-
- return changed;
+ }
+
+ data->dragchange = true; /* mark for selection */
+ }
+ else {
+ fx = (mx - dragx) / zoomx;
+ fy = (my - dragy) / zoomy;
+
+ /* clamp for clip */
+ if (cumap->flag & CUMA_DO_CLIP) {
+ if (cumap->curr.xmin - fx < cumap->clipr.xmin) {
+ fx = cumap->curr.xmin - cumap->clipr.xmin;
+ }
+ else if (cumap->curr.xmax - fx > cumap->clipr.xmax) {
+ fx = cumap->curr.xmax - cumap->clipr.xmax;
+ }
+ if (cumap->curr.ymin - fy < cumap->clipr.ymin) {
+ fy = cumap->curr.ymin - cumap->clipr.ymin;
+ }
+ else if (cumap->curr.ymax - fy > cumap->clipr.ymax) {
+ fy = cumap->curr.ymax - cumap->clipr.ymax;
+ }
+ }
+
+ cumap->curr.xmin -= fx;
+ cumap->curr.ymin -= fy;
+ cumap->curr.xmax -= fx;
+ cumap->curr.ymax -= fy;
+
+ data->draglastx = evtx;
+ data->draglasty = evty;
+
+ changed = true;
+ }
+
+ return changed;
}
static int ui_do_but_CURVE(
- bContext *C, uiBlock *block, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
- int mx, my, a;
- bool changed = false;
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- mx = event->x;
- my = event->y;
- ui_window_to_block(data->region, block, &mx, &my);
-
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
- CurveMapping *cumap = (CurveMapping *)but->poin;
- CurveMap *cuma = cumap->cm + cumap->cur;
- CurveMapPoint *cmp;
- const float m_xy[2] = {mx, my};
- float dist_min_sq = SQUARE(14.0f); /* 14 pixels radius */
- int sel = -1;
-
- if (event->ctrl) {
- float f_xy[2];
- BLI_rctf_transform_pt_v(&cumap->curr, &but->rect, f_xy, m_xy);
-
- curvemap_insert(cuma, f_xy[0], f_xy[1]);
- curvemapping_changed(cumap, false);
- changed = true;
- }
-
- /* check for selecting of a point */
- cmp = cuma->curve; /* ctrl adds point, new malloc */
- for (a = 0; a < cuma->totpoint; a++) {
- float f_xy[2];
- BLI_rctf_transform_pt_v(&but->rect, &cumap->curr, f_xy, &cmp[a].x);
- const float dist_sq = len_squared_v2v2(m_xy, f_xy);
- if (dist_sq < dist_min_sq) {
- sel = a;
- dist_min_sq = dist_sq;
- }
- }
-
- if (sel == -1) {
- int i;
- float f_xy[2], f_xy_prev[2];
-
- /* if the click didn't select anything, check if it's clicked on the
- * curve itself, and if so, add a point */
- cmp = cuma->table;
-
- BLI_rctf_transform_pt_v(&but->rect, &cumap->curr, f_xy, &cmp[0].x);
-
- /* with 160px height 8px should translate to the old 0.05 coefficient at no zoom */
- dist_min_sq = SQUARE(8.0f);
-
- /* loop through the curve segment table and find what's near the mouse. */
- for (i = 1; i <= CM_TABLE; i++) {
- copy_v2_v2(f_xy_prev, f_xy);
- BLI_rctf_transform_pt_v(&but->rect, &cumap->curr, f_xy, &cmp[i].x);
-
- if (dist_squared_to_line_segment_v2(m_xy, f_xy_prev, f_xy) < dist_min_sq) {
- BLI_rctf_transform_pt_v(&cumap->curr, &but->rect, f_xy, m_xy);
-
- curvemap_insert(cuma, f_xy[0], f_xy[1]);
- curvemapping_changed(cumap, false);
-
- changed = true;
-
- /* reset cmp back to the curve points again,
- * rather than drawing segments */
- cmp = cuma->curve;
-
- /* find newly added point and make it 'sel' */
- for (a = 0; a < cuma->totpoint; a++) {
- if (cmp[a].x == f_xy[0]) {
- sel = a;
- }
- }
- break;
- }
- }
- }
-
- if (sel != -1) {
- /* ok, we move a point */
- /* deselect all if this one is deselect. except if we hold shift */
- if (!event->shift) {
- for (a = 0; a < cuma->totpoint; a++) {
- cmp[a].flag &= ~CUMA_SELECT;
- }
- cmp[sel].flag |= CUMA_SELECT;
- }
- else {
- cmp[sel].flag ^= CUMA_SELECT;
- }
- }
- else {
- /* move the view */
- data->cancel = true;
- }
-
- data->dragsel = sel;
-
- data->dragstartx = event->x;
- data->dragstarty = event->y;
- data->draglastx = event->x;
- data->draglasty = event->y;
-
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- return WM_UI_HANDLER_BREAK;
- }
- }
- else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == MOUSEMOVE) {
- if (event->x != data->draglastx || event->y != data->draglasty) {
-
- if (ui_numedit_but_CURVE(block, but, data, event->x, event->y, event->ctrl != 0, event->shift != 0)) {
- ui_numedit_apply(C, block, but, data);
- }
- }
- }
- else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- if (data->dragsel != -1) {
- CurveMapping *cumap = (CurveMapping *)but->poin;
- CurveMap *cuma = cumap->cm + cumap->cur;
- CurveMapPoint *cmp = cuma->curve;
-
- if (data->dragchange == false) {
- /* deselect all, select one */
- if (!event->shift) {
- for (a = 0; a < cuma->totpoint; a++) {
- cmp[a].flag &= ~CUMA_SELECT;
- }
- cmp[data->dragsel].flag |= CUMA_SELECT;
- }
- }
- else {
- curvemapping_changed(cumap, true); /* remove doubles */
- BKE_paint_invalidate_cursor_overlay(scene, view_layer, cumap);
- }
- }
-
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
-
- return WM_UI_HANDLER_BREAK;
- }
-
- /* UNUSED but keep for now */
- (void)changed;
-
- return WM_UI_HANDLER_CONTINUE;
+ bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ int mx, my, a;
+ bool changed = false;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
+ CurveMapping *cumap = (CurveMapping *)but->poin;
+ CurveMap *cuma = cumap->cm + cumap->cur;
+ CurveMapPoint *cmp;
+ const float m_xy[2] = {mx, my};
+ float dist_min_sq = SQUARE(14.0f); /* 14 pixels radius */
+ int sel = -1;
+
+ if (event->ctrl) {
+ float f_xy[2];
+ BLI_rctf_transform_pt_v(&cumap->curr, &but->rect, f_xy, m_xy);
+
+ curvemap_insert(cuma, f_xy[0], f_xy[1]);
+ curvemapping_changed(cumap, false);
+ changed = true;
+ }
+
+ /* check for selecting of a point */
+ cmp = cuma->curve; /* ctrl adds point, new malloc */
+ for (a = 0; a < cuma->totpoint; a++) {
+ float f_xy[2];
+ BLI_rctf_transform_pt_v(&but->rect, &cumap->curr, f_xy, &cmp[a].x);
+ const float dist_sq = len_squared_v2v2(m_xy, f_xy);
+ if (dist_sq < dist_min_sq) {
+ sel = a;
+ dist_min_sq = dist_sq;
+ }
+ }
+
+ if (sel == -1) {
+ int i;
+ float f_xy[2], f_xy_prev[2];
+
+ /* if the click didn't select anything, check if it's clicked on the
+ * curve itself, and if so, add a point */
+ cmp = cuma->table;
+
+ BLI_rctf_transform_pt_v(&but->rect, &cumap->curr, f_xy, &cmp[0].x);
+
+ /* with 160px height 8px should translate to the old 0.05 coefficient at no zoom */
+ dist_min_sq = SQUARE(8.0f);
+
+ /* loop through the curve segment table and find what's near the mouse. */
+ for (i = 1; i <= CM_TABLE; i++) {
+ copy_v2_v2(f_xy_prev, f_xy);
+ BLI_rctf_transform_pt_v(&but->rect, &cumap->curr, f_xy, &cmp[i].x);
+
+ if (dist_squared_to_line_segment_v2(m_xy, f_xy_prev, f_xy) < dist_min_sq) {
+ BLI_rctf_transform_pt_v(&cumap->curr, &but->rect, f_xy, m_xy);
+
+ curvemap_insert(cuma, f_xy[0], f_xy[1]);
+ curvemapping_changed(cumap, false);
+
+ changed = true;
+
+ /* reset cmp back to the curve points again,
+ * rather than drawing segments */
+ cmp = cuma->curve;
+
+ /* find newly added point and make it 'sel' */
+ for (a = 0; a < cuma->totpoint; a++) {
+ if (cmp[a].x == f_xy[0]) {
+ sel = a;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ if (sel != -1) {
+ /* ok, we move a point */
+ /* deselect all if this one is deselect. except if we hold shift */
+ if (!event->shift) {
+ for (a = 0; a < cuma->totpoint; a++) {
+ cmp[a].flag &= ~CUMA_SELECT;
+ }
+ cmp[sel].flag |= CUMA_SELECT;
+ }
+ else {
+ cmp[sel].flag ^= CUMA_SELECT;
+ }
+ }
+ else {
+ /* move the view */
+ data->cancel = true;
+ }
+
+ data->dragsel = sel;
+
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ data->draglastx = event->x;
+ data->draglasty = event->y;
+
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if (data->state == BUTTON_STATE_NUM_EDITING) {
+ if (event->type == MOUSEMOVE) {
+ if (event->x != data->draglastx || event->y != data->draglasty) {
+
+ if (ui_numedit_but_CURVE(
+ block, but, data, event->x, event->y, event->ctrl != 0, event->shift != 0)) {
+ ui_numedit_apply(C, block, but, data);
+ }
+ }
+ }
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ if (data->dragsel != -1) {
+ CurveMapping *cumap = (CurveMapping *)but->poin;
+ CurveMap *cuma = cumap->cm + cumap->cur;
+ CurveMapPoint *cmp = cuma->curve;
+
+ if (data->dragchange == false) {
+ /* deselect all, select one */
+ if (!event->shift) {
+ for (a = 0; a < cuma->totpoint; a++) {
+ cmp[a].flag &= ~CUMA_SELECT;
+ }
+ cmp[data->dragsel].flag |= CUMA_SELECT;
+ }
+ }
+ else {
+ curvemapping_changed(cumap, true); /* remove doubles */
+ BKE_paint_invalidate_cursor_overlay(scene, view_layer, cumap);
+ }
+ }
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ /* UNUSED but keep for now */
+ (void)changed;
+
+ return WM_UI_HANDLER_CONTINUE;
}
static bool ui_numedit_but_HISTOGRAM(uiBut *but, uiHandleButtonData *data, int mx, int my)
{
- Histogram *hist = (Histogram *)but->poin;
- bool changed = true;
- float dy = my - data->draglasty;
+ Histogram *hist = (Histogram *)but->poin;
+ bool changed = true;
+ float dy = my - data->draglasty;
- /* scale histogram values (dy / 10 for better control) */
- const float yfac = min_ff(pow2f(hist->ymax), 1.0f) * 0.5f;
- hist->ymax += (dy * 0.1f) * yfac;
+ /* scale histogram values (dy / 10 for better control) */
+ const float yfac = min_ff(pow2f(hist->ymax), 1.0f) * 0.5f;
+ hist->ymax += (dy * 0.1f) * yfac;
- /* 0.1 allows us to see HDR colors up to 10 */
- CLAMP(hist->ymax, 0.1f, 100.f);
+ /* 0.1 allows us to see HDR colors up to 10 */
+ CLAMP(hist->ymax, 0.1f, 100.f);
- data->draglastx = mx;
- data->draglasty = my;
+ data->draglastx = mx;
+ data->draglasty = my;
- return changed;
+ return changed;
}
static int ui_do_but_HISTOGRAM(
- bContext *C, uiBlock *block, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
- int mx, my;
-
- mx = event->x;
- my = event->y;
- ui_window_to_block(data->region, block, &mx, &my);
-
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
- data->dragstartx = mx;
- data->dragstarty = my;
- data->draglastx = mx;
- data->draglasty = my;
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
-
- /* also do drag the first time */
- if (ui_numedit_but_HISTOGRAM(but, data, mx, my)) {
- ui_numedit_apply(C, block, but, data);
- }
-
- return WM_UI_HANDLER_BREAK;
- }
- /* XXX hardcoded keymap check.... */
- else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) {
- Histogram *hist = (Histogram *)but->poin;
- hist->ymax = 1.f;
-
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- return WM_UI_HANDLER_BREAK;
- }
- }
- else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == ESCKEY) {
- if (event->val == KM_PRESS) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- }
- else if (event->type == MOUSEMOVE) {
- if (mx != data->draglastx || my != data->draglasty) {
- if (ui_numedit_but_HISTOGRAM(but, data, mx, my)) {
- ui_numedit_apply(C, block, but, data);
- }
- }
- }
- else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- return WM_UI_HANDLER_BREAK;
- }
-
- return WM_UI_HANDLER_CONTINUE;
+ bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ int mx, my;
+
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
+ data->dragstartx = mx;
+ data->dragstarty = my;
+ data->draglastx = mx;
+ data->draglasty = my;
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ /* also do drag the first time */
+ if (ui_numedit_but_HISTOGRAM(but, data, mx, my)) {
+ ui_numedit_apply(C, block, but, data);
+ }
+
+ return WM_UI_HANDLER_BREAK;
+ }
+ /* XXX hardcoded keymap check.... */
+ else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) {
+ Histogram *hist = (Histogram *)but->poin;
+ hist->ymax = 1.f;
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if (data->state == BUTTON_STATE_NUM_EDITING) {
+ if (event->type == ESCKEY) {
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+ else if (event->type == MOUSEMOVE) {
+ if (mx != data->draglastx || my != data->draglasty) {
+ if (ui_numedit_but_HISTOGRAM(but, data, mx, my)) {
+ ui_numedit_apply(C, block, but, data);
+ }
+ }
+ }
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
}
static bool ui_numedit_but_WAVEFORM(uiBut *but, uiHandleButtonData *data, int mx, int my)
{
- Scopes *scopes = (Scopes *)but->poin;
- bool changed = true;
- float dy;
+ Scopes *scopes = (Scopes *)but->poin;
+ bool changed = true;
+ float dy;
- dy = my - data->draglasty;
+ dy = my - data->draglasty;
- /* scale waveform values */
- scopes->wavefrm_yfac += dy / 200.0f;
+ /* scale waveform values */
+ scopes->wavefrm_yfac += dy / 200.0f;
- CLAMP(scopes->wavefrm_yfac, 0.5f, 2.0f);
+ CLAMP(scopes->wavefrm_yfac, 0.5f, 2.0f);
- data->draglastx = mx;
- data->draglasty = my;
+ data->draglastx = mx;
+ data->draglasty = my;
- return changed;
+ return changed;
}
static int ui_do_but_WAVEFORM(
- bContext *C, uiBlock *block, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
- int mx, my;
-
- mx = event->x;
- my = event->y;
- ui_window_to_block(data->region, block, &mx, &my);
-
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
- data->dragstartx = mx;
- data->dragstarty = my;
- data->draglastx = mx;
- data->draglasty = my;
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
-
- /* also do drag the first time */
- if (ui_numedit_but_WAVEFORM(but, data, mx, my)) {
- ui_numedit_apply(C, block, but, data);
- }
-
- return WM_UI_HANDLER_BREAK;
- }
- /* XXX hardcoded keymap check.... */
- else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) {
- Scopes *scopes = (Scopes *)but->poin;
- scopes->wavefrm_yfac = 1.f;
-
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- return WM_UI_HANDLER_BREAK;
- }
- }
- else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == ESCKEY) {
- if (event->val == KM_PRESS) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- }
- else if (event->type == MOUSEMOVE) {
- if (mx != data->draglastx || my != data->draglasty) {
- if (ui_numedit_but_WAVEFORM(but, data, mx, my)) {
- ui_numedit_apply(C, block, but, data);
- }
- }
- }
- else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- return WM_UI_HANDLER_BREAK;
- }
-
- return WM_UI_HANDLER_CONTINUE;
+ bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ int mx, my;
+
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
+ data->dragstartx = mx;
+ data->dragstarty = my;
+ data->draglastx = mx;
+ data->draglasty = my;
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ /* also do drag the first time */
+ if (ui_numedit_but_WAVEFORM(but, data, mx, my)) {
+ ui_numedit_apply(C, block, but, data);
+ }
+
+ return WM_UI_HANDLER_BREAK;
+ }
+ /* XXX hardcoded keymap check.... */
+ else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) {
+ Scopes *scopes = (Scopes *)but->poin;
+ scopes->wavefrm_yfac = 1.f;
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if (data->state == BUTTON_STATE_NUM_EDITING) {
+ if (event->type == ESCKEY) {
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+ else if (event->type == MOUSEMOVE) {
+ if (mx != data->draglastx || my != data->draglasty) {
+ if (ui_numedit_but_WAVEFORM(but, data, mx, my)) {
+ ui_numedit_apply(C, block, but, data);
+ }
+ }
+ }
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
}
static bool ui_numedit_but_TRACKPREVIEW(
- bContext *C, uiBut *but, uiHandleButtonData *data,
- int mx, int my,
- const bool shift)
+ bContext *C, uiBut *but, uiHandleButtonData *data, int mx, int my, const bool shift)
{
- MovieClipScopes *scopes = (MovieClipScopes *)but->poin;
- bool changed = true;
- float dx, dy;
+ MovieClipScopes *scopes = (MovieClipScopes *)but->poin;
+ bool changed = true;
+ float dx, dy;
- dx = mx - data->draglastx;
- dy = my - data->draglasty;
+ dx = mx - data->draglastx;
+ dy = my - data->draglasty;
- if (shift) {
- dx /= 5.0f;
- dy /= 5.0f;
- }
+ if (shift) {
+ dx /= 5.0f;
+ dy /= 5.0f;
+ }
- if (!scopes->track_locked) {
- if (scopes->marker->framenr != scopes->framenr) {
- scopes->marker = BKE_tracking_marker_ensure(scopes->track, scopes->framenr);
- }
+ if (!scopes->track_locked) {
+ if (scopes->marker->framenr != scopes->framenr) {
+ scopes->marker = BKE_tracking_marker_ensure(scopes->track, scopes->framenr);
+ }
- scopes->marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED);
- scopes->marker->pos[0] += -dx * scopes->slide_scale[0] / BLI_rctf_size_x(&but->block->rect);
- scopes->marker->pos[1] += -dy * scopes->slide_scale[1] / BLI_rctf_size_y(&but->block->rect);
+ scopes->marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED);
+ scopes->marker->pos[0] += -dx * scopes->slide_scale[0] / BLI_rctf_size_x(&but->block->rect);
+ scopes->marker->pos[1] += -dy * scopes->slide_scale[1] / BLI_rctf_size_y(&but->block->rect);
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
- }
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
+ }
- scopes->ok = 0;
+ scopes->ok = 0;
- data->draglastx = mx;
- data->draglasty = my;
+ data->draglastx = mx;
+ data->draglasty = my;
- return changed;
+ return changed;
}
static int ui_do_but_TRACKPREVIEW(
- bContext *C, uiBlock *block, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
- int mx, my;
-
- mx = event->x;
- my = event->y;
- ui_window_to_block(data->region, block, &mx, &my);
-
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
- data->dragstartx = mx;
- data->dragstarty = my;
- data->draglastx = mx;
- data->draglasty = my;
- button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
-
- /* also do drag the first time */
- if (ui_numedit_but_TRACKPREVIEW(C, but, data, mx, my, event->shift != 0)) {
- ui_numedit_apply(C, block, but, data);
- }
-
- return WM_UI_HANDLER_BREAK;
- }
- }
- else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == ESCKEY) {
- if (event->val == KM_PRESS) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- }
- else if (event->type == MOUSEMOVE) {
- if (mx != data->draglastx || my != data->draglasty) {
- if (ui_numedit_but_TRACKPREVIEW(C, but, data, mx, my, event->shift != 0)) {
- ui_numedit_apply(C, block, but, data);
- }
- }
- }
- else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- return WM_UI_HANDLER_BREAK;
- }
-
- return WM_UI_HANDLER_CONTINUE;
+ bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ int mx, my;
+
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
+ data->dragstartx = mx;
+ data->dragstarty = my;
+ data->draglastx = mx;
+ data->draglasty = my;
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ /* also do drag the first time */
+ if (ui_numedit_but_TRACKPREVIEW(C, but, data, mx, my, event->shift != 0)) {
+ ui_numedit_apply(C, block, but, data);
+ }
+
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if (data->state == BUTTON_STATE_NUM_EDITING) {
+ if (event->type == ESCKEY) {
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
+ else if (event->type == MOUSEMOVE) {
+ if (mx != data->draglastx || my != data->draglasty) {
+ if (ui_numedit_but_TRACKPREVIEW(C, but, data, mx, my, event->shift != 0)) {
+ ui_numedit_apply(C, block, but, data);
+ }
+ }
+ }
+ else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
}
static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *event)
{
- uiHandleButtonData *data;
- int retval;
-
- data = but->active;
- retval = WM_UI_HANDLER_CONTINUE;
-
- bool is_disabled = but->flag & UI_BUT_DISABLED;
-
- /* if but->pointype is set, but->poin should be too */
- BLI_assert(!but->pointype || but->poin);
-
- /* Only hard-coded stuff here, button interactions with configurable
- * keymaps are handled using operators (see #ED_keymap_ui). */
-
- if ((data->state == BUTTON_STATE_HIGHLIGHT) || (event->type == EVT_DROP)) {
-
- /* 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;
-
- /* Specific handling for listrows, we try to find their overlapping tex button. */
- if ((do_copy || do_paste) && but->type == UI_BTYPE_LISTROW) {
- uiBut *labelbut = ui_but_list_row_text_activate(C, but, data, event, BUTTON_ACTIVATE_OVER);
- if (labelbut) {
- but = labelbut;
- data = but->active;
- }
- }
-
- /* do copy first, because it is the only allowed operator when disabled */
- if (do_copy) {
- ui_but_copy(C, but, event->alt);
- return WM_UI_HANDLER_BREAK;
- }
-
- /* handle menu */
- if ((event->type == RIGHTMOUSE) &&
- !IS_EVENT_MOD(event, shift, ctrl, alt, oskey) &&
- (event->val == KM_PRESS))
- {
- /* RMB has two options now */
- if (ui_popup_context_menu_for_button(C, but)) {
- return WM_UI_HANDLER_BREAK;
- }
- }
-
- if (is_disabled) {
- return WM_UI_HANDLER_CONTINUE;
- }
-
- if (do_paste) {
- ui_but_paste(C, but, data, event->alt);
- return WM_UI_HANDLER_BREAK;
- }
-
- /* handle drop */
- if (event->type == EVT_DROP) {
- ui_but_drop(C, event, but, data);
- }
- }
-
- if (but->flag & UI_BUT_DISABLED) {
- return WM_UI_HANDLER_CONTINUE;
- }
-
- switch (but->type) {
- case UI_BTYPE_BUT:
- retval = ui_do_but_BUT(C, but, data, event);
- break;
- case UI_BTYPE_KEY_EVENT:
- retval = ui_do_but_KEYEVT(C, but, data, event);
- break;
- case UI_BTYPE_HOTKEY_EVENT:
- retval = ui_do_but_HOTKEYEVT(C, but, data, event);
- break;
- case UI_BTYPE_TAB:
- retval = ui_do_but_TAB(C, block, but, data, event);
- break;
- case UI_BTYPE_BUT_TOGGLE:
- case UI_BTYPE_TOGGLE:
- case UI_BTYPE_ICON_TOGGLE:
- case UI_BTYPE_ICON_TOGGLE_N:
- case UI_BTYPE_TOGGLE_N:
- case UI_BTYPE_CHECKBOX:
- case UI_BTYPE_CHECKBOX_N:
- case UI_BTYPE_ROW:
- retval = ui_do_but_TOG(C, but, data, event);
- break;
- case UI_BTYPE_SCROLL:
- retval = ui_do_but_SCROLL(C, block, but, data, event);
- break;
- case UI_BTYPE_GRIP:
- retval = ui_do_but_GRIP(C, block, but, data, event);
- break;
- case UI_BTYPE_NUM:
- retval = ui_do_but_NUM(C, block, but, data, event);
- break;
- case UI_BTYPE_NUM_SLIDER:
- retval = ui_do_but_SLI(C, block, but, data, event);
- break;
- case UI_BTYPE_LISTBOX:
- /* Nothing to do! */
- break;
- case UI_BTYPE_LISTROW:
- retval = ui_do_but_LISTROW(C, but, data, event);
- break;
- case UI_BTYPE_ROUNDBOX:
- case UI_BTYPE_LABEL:
- case UI_BTYPE_IMAGE:
- case UI_BTYPE_PROGRESS_BAR:
- case UI_BTYPE_NODE_SOCKET:
- retval = ui_do_but_EXIT(C, but, data, event);
- break;
- case UI_BTYPE_HISTOGRAM:
- retval = ui_do_but_HISTOGRAM(C, block, but, data, event);
- break;
- case UI_BTYPE_WAVEFORM:
- retval = ui_do_but_WAVEFORM(C, block, but, data, event);
- break;
- case UI_BTYPE_VECTORSCOPE:
- /* Nothing to do! */
- break;
- case UI_BTYPE_TEXT:
- case UI_BTYPE_SEARCH_MENU:
- if ((but->type == UI_BTYPE_SEARCH_MENU) &&
- (but->flag & UI_BUT_VALUE_CLEAR))
- {
- retval = ui_do_but_SEARCH_UNLINK(C, block, but, data, event);
- if (retval & WM_UI_HANDLER_BREAK) {
- break;
- }
- }
- retval = ui_do_but_TEX(C, block, but, data, event);
- break;
- case UI_BTYPE_MENU:
- case UI_BTYPE_POPOVER:
- case UI_BTYPE_BLOCK:
- case UI_BTYPE_PULLDOWN:
- retval = ui_do_but_BLOCK(C, but, data, event);
- break;
- case UI_BTYPE_BUT_MENU:
- retval = ui_do_but_BUT(C, but, data, event);
- break;
- case UI_BTYPE_COLOR:
- if (but->a1 == -1) {
- /* signal to prevent calling up color picker */
- retval = ui_do_but_EXIT(C, but, data, event);
- }
- else {
- retval = ui_do_but_COLOR(C, but, data, event);
- }
- break;
- case UI_BTYPE_UNITVEC:
- retval = ui_do_but_UNITVEC(C, block, but, data, event);
- break;
- case UI_BTYPE_COLORBAND:
- retval = ui_do_but_COLORBAND(C, block, but, data, event);
- break;
- case UI_BTYPE_CURVE:
- retval = ui_do_but_CURVE(C, block, but, data, event);
- break;
- case UI_BTYPE_HSVCUBE:
- retval = ui_do_but_HSVCUBE(C, block, but, data, event);
- break;
- case UI_BTYPE_HSVCIRCLE:
- retval = ui_do_but_HSVCIRCLE(C, block, but, data, event);
- break;
- case UI_BTYPE_TRACK_PREVIEW:
- retval = ui_do_but_TRACKPREVIEW(C, block, but, data, event);
- break;
-
- /* quiet warnings for unhandled types */
- case UI_BTYPE_SEPR:
- case UI_BTYPE_SEPR_LINE:
- case UI_BTYPE_SEPR_SPACER:
- case UI_BTYPE_EXTRA:
- break;
- }
-
-
- /* reset to default (generic function, only use if not handled by switch above) */
- /* XXX hardcoded keymap check.... */
- data = but->active;
- if (data && data->state == BUTTON_STATE_HIGHLIGHT) {
- if ((retval == WM_UI_HANDLER_CONTINUE) &&
- (event->type == 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);
- retval = WM_UI_HANDLER_BREAK;
- }
- }
+ uiHandleButtonData *data;
+ int retval;
+
+ data = but->active;
+ retval = WM_UI_HANDLER_CONTINUE;
+
+ bool is_disabled = but->flag & UI_BUT_DISABLED;
+
+ /* if but->pointype is set, but->poin should be too */
+ BLI_assert(!but->pointype || but->poin);
+
+ /* Only hard-coded stuff here, button interactions with configurable
+ * keymaps are handled using operators (see #ED_keymap_ui). */
+
+ if ((data->state == BUTTON_STATE_HIGHLIGHT) || (event->type == EVT_DROP)) {
+
+ /* 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;
+
+ /* Specific handling for listrows, we try to find their overlapping tex button. */
+ if ((do_copy || do_paste) && but->type == UI_BTYPE_LISTROW) {
+ uiBut *labelbut = ui_but_list_row_text_activate(C, but, data, event, BUTTON_ACTIVATE_OVER);
+ if (labelbut) {
+ but = labelbut;
+ data = but->active;
+ }
+ }
+
+ /* do copy first, because it is the only allowed operator when disabled */
+ if (do_copy) {
+ ui_but_copy(C, but, event->alt);
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ /* handle menu */
+ if ((event->type == RIGHTMOUSE) && !IS_EVENT_MOD(event, shift, ctrl, alt, oskey) &&
+ (event->val == KM_PRESS)) {
+ /* RMB has two options now */
+ if (ui_popup_context_menu_for_button(C, but)) {
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ if (is_disabled) {
+ return WM_UI_HANDLER_CONTINUE;
+ }
+
+ if (do_paste) {
+ ui_but_paste(C, but, data, event->alt);
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ /* handle drop */
+ if (event->type == EVT_DROP) {
+ ui_but_drop(C, event, but, data);
+ }
+ }
+
+ if (but->flag & UI_BUT_DISABLED) {
+ return WM_UI_HANDLER_CONTINUE;
+ }
+
+ switch (but->type) {
+ case UI_BTYPE_BUT:
+ retval = ui_do_but_BUT(C, but, data, event);
+ break;
+ case UI_BTYPE_KEY_EVENT:
+ retval = ui_do_but_KEYEVT(C, but, data, event);
+ break;
+ case UI_BTYPE_HOTKEY_EVENT:
+ retval = ui_do_but_HOTKEYEVT(C, but, data, event);
+ break;
+ case UI_BTYPE_TAB:
+ retval = ui_do_but_TAB(C, block, but, data, event);
+ break;
+ case UI_BTYPE_BUT_TOGGLE:
+ case UI_BTYPE_TOGGLE:
+ case UI_BTYPE_ICON_TOGGLE:
+ case UI_BTYPE_ICON_TOGGLE_N:
+ case UI_BTYPE_TOGGLE_N:
+ case UI_BTYPE_CHECKBOX:
+ case UI_BTYPE_CHECKBOX_N:
+ case UI_BTYPE_ROW:
+ retval = ui_do_but_TOG(C, but, data, event);
+ break;
+ case UI_BTYPE_SCROLL:
+ retval = ui_do_but_SCROLL(C, block, but, data, event);
+ break;
+ case UI_BTYPE_GRIP:
+ retval = ui_do_but_GRIP(C, block, but, data, event);
+ break;
+ case UI_BTYPE_NUM:
+ retval = ui_do_but_NUM(C, block, but, data, event);
+ break;
+ case UI_BTYPE_NUM_SLIDER:
+ retval = ui_do_but_SLI(C, block, but, data, event);
+ break;
+ case UI_BTYPE_LISTBOX:
+ /* Nothing to do! */
+ break;
+ case UI_BTYPE_LISTROW:
+ retval = ui_do_but_LISTROW(C, but, data, event);
+ break;
+ case UI_BTYPE_ROUNDBOX:
+ case UI_BTYPE_LABEL:
+ case UI_BTYPE_IMAGE:
+ case UI_BTYPE_PROGRESS_BAR:
+ case UI_BTYPE_NODE_SOCKET:
+ retval = ui_do_but_EXIT(C, but, data, event);
+ break;
+ case UI_BTYPE_HISTOGRAM:
+ retval = ui_do_but_HISTOGRAM(C, block, but, data, event);
+ break;
+ case UI_BTYPE_WAVEFORM:
+ retval = ui_do_but_WAVEFORM(C, block, but, data, event);
+ break;
+ case UI_BTYPE_VECTORSCOPE:
+ /* Nothing to do! */
+ break;
+ case UI_BTYPE_TEXT:
+ case UI_BTYPE_SEARCH_MENU:
+ if ((but->type == UI_BTYPE_SEARCH_MENU) && (but->flag & UI_BUT_VALUE_CLEAR)) {
+ retval = ui_do_but_SEARCH_UNLINK(C, block, but, data, event);
+ if (retval & WM_UI_HANDLER_BREAK) {
+ break;
+ }
+ }
+ retval = ui_do_but_TEX(C, block, but, data, event);
+ break;
+ case UI_BTYPE_MENU:
+ case UI_BTYPE_POPOVER:
+ case UI_BTYPE_BLOCK:
+ case UI_BTYPE_PULLDOWN:
+ retval = ui_do_but_BLOCK(C, but, data, event);
+ break;
+ case UI_BTYPE_BUT_MENU:
+ retval = ui_do_but_BUT(C, but, data, event);
+ break;
+ case UI_BTYPE_COLOR:
+ if (but->a1 == -1) {
+ /* signal to prevent calling up color picker */
+ retval = ui_do_but_EXIT(C, but, data, event);
+ }
+ else {
+ retval = ui_do_but_COLOR(C, but, data, event);
+ }
+ break;
+ case UI_BTYPE_UNITVEC:
+ retval = ui_do_but_UNITVEC(C, block, but, data, event);
+ break;
+ case UI_BTYPE_COLORBAND:
+ retval = ui_do_but_COLORBAND(C, block, but, data, event);
+ break;
+ case UI_BTYPE_CURVE:
+ retval = ui_do_but_CURVE(C, block, but, data, event);
+ break;
+ case UI_BTYPE_HSVCUBE:
+ retval = ui_do_but_HSVCUBE(C, block, but, data, event);
+ break;
+ case UI_BTYPE_HSVCIRCLE:
+ retval = ui_do_but_HSVCIRCLE(C, block, but, data, event);
+ break;
+ case UI_BTYPE_TRACK_PREVIEW:
+ retval = ui_do_but_TRACKPREVIEW(C, block, but, data, event);
+ break;
+
+ /* quiet warnings for unhandled types */
+ case UI_BTYPE_SEPR:
+ case UI_BTYPE_SEPR_LINE:
+ case UI_BTYPE_SEPR_SPACER:
+ case UI_BTYPE_EXTRA:
+ break;
+ }
+
+ /* reset to default (generic function, only use if not handled by switch above) */
+ /* XXX hardcoded keymap check.... */
+ data = but->active;
+ if (data && data->state == BUTTON_STATE_HIGHLIGHT) {
+ if ((retval == WM_UI_HANDLER_CONTINUE) &&
+ (event->type == 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);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
#ifdef USE_DRAG_MULTINUM
- if (data) {
- if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) ||
- /* if we started dragging, progress on any event */
- (data->multi_data.init == BUTTON_MULTI_INIT_SETUP))
- {
- if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) &&
- ELEM(data->state, BUTTON_STATE_TEXT_EDITING, BUTTON_STATE_NUM_EDITING))
- {
- /* initialize! */
- if (data->multi_data.init == BUTTON_MULTI_INIT_UNSET) {
- /* --> (BUTTON_MULTI_INIT_SETUP | BUTTON_MULTI_INIT_DISABLE) */
-
- const float margin_y = DRAG_MULTINUM_THRESHOLD_DRAG_Y / sqrtf(block->aspect);
-
- /* check if we have a vertical gesture */
- if (len_squared_v2(data->multi_data.drag_dir) > (margin_y * margin_y)) {
- const float dir_nor_y[2] = {0.0, 1.0f};
- float dir_nor_drag[2];
-
- normalize_v2_v2(dir_nor_drag, data->multi_data.drag_dir);
-
- if (fabsf(dot_v2v2(dir_nor_drag, dir_nor_y)) > DRAG_MULTINUM_THRESHOLD_VERTICAL) {
- data->multi_data.init = BUTTON_MULTI_INIT_SETUP;
- data->multi_data.drag_lock_x = event->x;
- }
- else {
- data->multi_data.init = BUTTON_MULTI_INIT_DISABLE;
- }
- }
- }
- else if (data->multi_data.init == BUTTON_MULTI_INIT_SETUP) {
- /* --> (BUTTON_MULTI_INIT_ENABLE) */
- const float margin_x = DRAG_MULTINUM_THRESHOLD_DRAG_X / sqrtf(block->aspect);
- /* check if we're dont setting buttons */
- if ((data->str && ELEM(data->state, BUTTON_STATE_TEXT_EDITING, BUTTON_STATE_NUM_EDITING)) ||
- ((abs(data->multi_data.drag_lock_x - event->x) > margin_x) &&
- /* just to be sure, check we're dragging more hoz then virt */
- abs(event->prevx - event->x) > abs(event->prevy - event->y)))
- {
- if (data->multi_data.has_mbuts) {
- ui_multibut_states_create(but, data);
- data->multi_data.init = BUTTON_MULTI_INIT_ENABLE;
- }
- else {
- data->multi_data.init = BUTTON_MULTI_INIT_DISABLE;
- }
- }
- }
-
- if (data->multi_data.init == BUTTON_MULTI_INIT_SETUP) {
- if (ui_multibut_states_tag(but, data, event)) {
- ED_region_tag_redraw(data->region);
- }
- }
- }
- }
- }
-#endif /* USE_DRAG_MULTINUM */
-
- return retval;
+ if (data) {
+ if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) ||
+ /* if we started dragging, progress on any event */
+ (data->multi_data.init == BUTTON_MULTI_INIT_SETUP)) {
+ if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) &&
+ ELEM(data->state, BUTTON_STATE_TEXT_EDITING, BUTTON_STATE_NUM_EDITING)) {
+ /* initialize! */
+ if (data->multi_data.init == BUTTON_MULTI_INIT_UNSET) {
+ /* --> (BUTTON_MULTI_INIT_SETUP | BUTTON_MULTI_INIT_DISABLE) */
+
+ const float margin_y = DRAG_MULTINUM_THRESHOLD_DRAG_Y / sqrtf(block->aspect);
+
+ /* check if we have a vertical gesture */
+ if (len_squared_v2(data->multi_data.drag_dir) > (margin_y * margin_y)) {
+ const float dir_nor_y[2] = {0.0, 1.0f};
+ float dir_nor_drag[2];
+
+ normalize_v2_v2(dir_nor_drag, data->multi_data.drag_dir);
+
+ if (fabsf(dot_v2v2(dir_nor_drag, dir_nor_y)) > DRAG_MULTINUM_THRESHOLD_VERTICAL) {
+ data->multi_data.init = BUTTON_MULTI_INIT_SETUP;
+ data->multi_data.drag_lock_x = event->x;
+ }
+ else {
+ data->multi_data.init = BUTTON_MULTI_INIT_DISABLE;
+ }
+ }
+ }
+ else if (data->multi_data.init == BUTTON_MULTI_INIT_SETUP) {
+ /* --> (BUTTON_MULTI_INIT_ENABLE) */
+ const float margin_x = DRAG_MULTINUM_THRESHOLD_DRAG_X / sqrtf(block->aspect);
+ /* check if we're dont setting buttons */
+ if ((data->str &&
+ ELEM(data->state, BUTTON_STATE_TEXT_EDITING, BUTTON_STATE_NUM_EDITING)) ||
+ ((abs(data->multi_data.drag_lock_x - event->x) > margin_x) &&
+ /* just to be sure, check we're dragging more hoz then virt */
+ abs(event->prevx - event->x) > abs(event->prevy - event->y))) {
+ if (data->multi_data.has_mbuts) {
+ ui_multibut_states_create(but, data);
+ data->multi_data.init = BUTTON_MULTI_INIT_ENABLE;
+ }
+ else {
+ data->multi_data.init = BUTTON_MULTI_INIT_DISABLE;
+ }
+ }
+ }
+
+ if (data->multi_data.init == BUTTON_MULTI_INIT_SETUP) {
+ if (ui_multibut_states_tag(but, data, event)) {
+ ED_region_tag_redraw(data->region);
+ }
+ }
+ }
+ }
+ }
+#endif /* USE_DRAG_MULTINUM */
+
+ return retval;
}
/** \} */
@@ -7094,17 +7113,17 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
static void ui_blocks_set_tooltips(ARegion *ar, const bool enable)
{
- uiBlock *block;
+ uiBlock *block;
- if (!ar) {
- return;
- }
+ if (!ar) {
+ 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) {
- block->tooltipdisabled = !enable;
- }
+ /* 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) {
+ block->tooltipdisabled = !enable;
+ }
}
/**
@@ -7112,75 +7131,74 @@ static void ui_blocks_set_tooltips(ARegion *ar, const bool enable)
*/
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) {
- WM_tooltip_refresh(C, data->window);
- }
- }
+ uiHandleButtonData *data = but->active;
+ if (data) {
+ bScreen *sc = WM_window_get_active_screen(data->window);
+ if (sc->tool_tip && sc->tool_tip->region) {
+ WM_tooltip_refresh(C, data->window);
+ }
+ }
}
/* removes tooltip timer from active but
* (meaning tooltip is disabled until it's reenabled again) */
void UI_but_tooltip_timer_remove(bContext *C, uiBut *but)
{
- uiHandleButtonData *data;
+ uiHandleButtonData *data;
- data = but->active;
- if (data) {
- if (data->autoopentimer) {
- WM_event_remove_timer(data->wm, data->window, data->autoopentimer);
- data->autoopentimer = NULL;
- }
+ data = but->active;
+ if (data) {
+ if (data->autoopentimer) {
+ WM_event_remove_timer(data->wm, data->window, data->autoopentimer);
+ data->autoopentimer = NULL;
+ }
- if (data->window) {
- WM_tooltip_clear(C, data->window);
- }
- }
+ if (data->window) {
+ WM_tooltip_clear(C, data->window);
+ }
+ }
}
static ARegion *ui_but_tooltip_init(
- bContext *C, ARegion *ar,
- int *pass, double *r_pass_delay, bool *r_exit_on_event)
+ bContext *C, ARegion *ar, int *pass, double *r_pass_delay, bool *r_exit_on_event)
{
- bool is_label = false;
- if (*pass == 1) {
- is_label = true;
- (*pass)--;
- (*r_pass_delay) = UI_TOOLTIP_DELAY - UI_TOOLTIP_DELAY_LABEL;
- }
+ bool is_label = false;
+ if (*pass == 1) {
+ is_label = true;
+ (*pass)--;
+ (*r_pass_delay) = UI_TOOLTIP_DELAY - UI_TOOLTIP_DELAY_LABEL;
+ }
- uiBut *but = UI_region_active_but_get(ar);
- *r_exit_on_event = false;
- if (but) {
- return UI_tooltip_create_from_button(C, ar, but, is_label);
- }
- return NULL;
+ uiBut *but = UI_region_active_but_get(ar);
+ *r_exit_on_event = false;
+ if (but) {
+ return UI_tooltip_create_from_button(C, ar, but, is_label);
+ }
+ return NULL;
}
static void button_tooltip_timer_reset(bContext *C, uiBut *but)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- uiHandleButtonData *data = but->active;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ uiHandleButtonData *data = but->active;
- WM_tooltip_timer_clear(C, data->window);
+ WM_tooltip_timer_clear(C, data->window);
- if ((U.flag & USER_TOOLTIPS) || (data->tooltip_force)) {
- if (!but->block->tooltipdisabled) {
- if (!wm->drags.first) {
- bool is_label = UI_but_has_tooltip_label(but);
- double delay = is_label ? UI_TOOLTIP_DELAY_LABEL : UI_TOOLTIP_DELAY;
- WM_tooltip_timer_init_ex(C, data->window, 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;
- }
- }
- }
- }
- }
+ if ((U.flag & USER_TOOLTIPS) || (data->tooltip_force)) {
+ if (!but->block->tooltipdisabled) {
+ if (!wm->drags.first) {
+ bool is_label = UI_but_has_tooltip_label(but);
+ double delay = is_label ? UI_TOOLTIP_DELAY_LABEL : UI_TOOLTIP_DELAY;
+ WM_tooltip_timer_init_ex(C, data->window, 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;
+ }
+ }
+ }
+ }
+ }
}
/** \} */
@@ -7191,473 +7209,475 @@ static void button_tooltip_timer_reset(bContext *C, uiBut *but)
static bool button_modal_state(uiHandleButtonState state)
{
- return ELEM(state,
- BUTTON_STATE_WAIT_RELEASE,
- BUTTON_STATE_WAIT_KEY_EVENT,
- BUTTON_STATE_NUM_EDITING,
- BUTTON_STATE_TEXT_EDITING,
- BUTTON_STATE_TEXT_SELECTING,
- BUTTON_STATE_MENU_OPEN);
+ return ELEM(state,
+ BUTTON_STATE_WAIT_RELEASE,
+ BUTTON_STATE_WAIT_KEY_EVENT,
+ BUTTON_STATE_NUM_EDITING,
+ BUTTON_STATE_TEXT_EDITING,
+ BUTTON_STATE_TEXT_SELECTING,
+ BUTTON_STATE_MENU_OPEN);
}
static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state)
{
- uiHandleButtonData *data;
-
- data = but->active;
- if (data->state == state) {
- return;
- }
-
- /* highlight has timers for tooltips and auto open */
- if (state == BUTTON_STATE_HIGHLIGHT) {
- but->flag &= ~UI_SELECT;
-
- button_tooltip_timer_reset(C, but);
-
- /* automatic open pulldown block timer */
- if (ELEM(but->type, UI_BTYPE_BLOCK, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) {
- if (data->used_mouse && !data->autoopentimer) {
- int time;
-
- if (but->block->auto_open == true) { /* test for toolbox */
- time = 1;
- }
- else if ((but->block->flag & UI_BLOCK_LOOP && but->type != UI_BTYPE_BLOCK) ||
- (but->block->auto_open == true))
- {
- time = 5 * U.menuthreshold2;
- }
- else if (U.uiflag & USER_MENUOPENAUTO) {
- time = 5 * U.menuthreshold1;
- }
- else {
- time = -1; /* do nothing */
- }
-
- if (time >= 0) {
- data->autoopentimer = WM_event_add_timer(data->wm, data->window, TIMER, 0.02 * (double)time);
- }
- }
- }
- }
- else {
- but->flag |= UI_SELECT;
- UI_but_tooltip_timer_remove(C, but);
- }
-
- /* text editing */
- if (state == BUTTON_STATE_TEXT_EDITING && data->state != BUTTON_STATE_TEXT_SELECTING) {
- ui_textedit_begin(C, but, data);
- }
- else if (data->state == BUTTON_STATE_TEXT_EDITING && state != BUTTON_STATE_TEXT_SELECTING) {
- ui_textedit_end(C, but, data);
- }
- else if (data->state == BUTTON_STATE_TEXT_SELECTING && state != BUTTON_STATE_TEXT_EDITING) {
- ui_textedit_end(C, but, data);
- }
-
- /* number editing */
- if (state == BUTTON_STATE_NUM_EDITING) {
- if (ui_but_is_cursor_warp(but)) {
- WM_cursor_grab_enable(CTX_wm_window(C), true, true, NULL);
- }
- ui_numedit_begin(but, data);
- }
- else if (data->state == BUTTON_STATE_NUM_EDITING) {
- ui_numedit_end(but, data);
-
- if (but->flag & UI_BUT_DRIVEN) {
- /* Only warn when editing stepping/dragging the value.
- * No warnings should show for editing driver expressions though!
- */
- if (state != BUTTON_STATE_TEXT_EDITING) {
- WM_report(RPT_INFO, "Can't edit driven number value, see graph editor for the driver setup.");
- }
- }
-
- if (ui_but_is_cursor_warp(but)) {
+ uiHandleButtonData *data;
+
+ data = but->active;
+ if (data->state == state) {
+ return;
+ }
+
+ /* highlight has timers for tooltips and auto open */
+ if (state == BUTTON_STATE_HIGHLIGHT) {
+ but->flag &= ~UI_SELECT;
+
+ button_tooltip_timer_reset(C, but);
+
+ /* automatic open pulldown block timer */
+ if (ELEM(but->type, UI_BTYPE_BLOCK, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) {
+ if (data->used_mouse && !data->autoopentimer) {
+ int time;
+
+ if (but->block->auto_open == true) { /* test for toolbox */
+ time = 1;
+ }
+ else if ((but->block->flag & UI_BLOCK_LOOP && but->type != UI_BTYPE_BLOCK) ||
+ (but->block->auto_open == true)) {
+ time = 5 * U.menuthreshold2;
+ }
+ else if (U.uiflag & USER_MENUOPENAUTO) {
+ time = 5 * U.menuthreshold1;
+ }
+ else {
+ time = -1; /* do nothing */
+ }
+
+ if (time >= 0) {
+ data->autoopentimer = WM_event_add_timer(
+ data->wm, data->window, TIMER, 0.02 * (double)time);
+ }
+ }
+ }
+ }
+ else {
+ but->flag |= UI_SELECT;
+ UI_but_tooltip_timer_remove(C, but);
+ }
+
+ /* text editing */
+ if (state == BUTTON_STATE_TEXT_EDITING && data->state != BUTTON_STATE_TEXT_SELECTING) {
+ ui_textedit_begin(C, but, data);
+ }
+ else if (data->state == BUTTON_STATE_TEXT_EDITING && state != BUTTON_STATE_TEXT_SELECTING) {
+ ui_textedit_end(C, but, data);
+ }
+ else if (data->state == BUTTON_STATE_TEXT_SELECTING && state != BUTTON_STATE_TEXT_EDITING) {
+ ui_textedit_end(C, but, data);
+ }
+
+ /* number editing */
+ if (state == BUTTON_STATE_NUM_EDITING) {
+ if (ui_but_is_cursor_warp(but)) {
+ WM_cursor_grab_enable(CTX_wm_window(C), true, true, NULL);
+ }
+ ui_numedit_begin(but, data);
+ }
+ else if (data->state == BUTTON_STATE_NUM_EDITING) {
+ ui_numedit_end(but, data);
+
+ if (but->flag & UI_BUT_DRIVEN) {
+ /* Only warn when editing stepping/dragging the value.
+ * No warnings should show for editing driver expressions though!
+ */
+ if (state != BUTTON_STATE_TEXT_EDITING) {
+ WM_report(RPT_INFO,
+ "Can't edit driven number value, see graph editor for the driver setup.");
+ }
+ }
+
+ if (ui_but_is_cursor_warp(but)) {
#ifdef USE_CONT_MOUSE_CORRECT
- /* stereo3d has issues with changing cursor location so rather avoid */
- if (data->ungrab_mval[0] != FLT_MAX && !WM_stereo3d_enabled(data->window, false)) {
- int mouse_ungrab_xy[2];
- ui_block_to_window_fl(data->region, but->block, &data->ungrab_mval[0], &data->ungrab_mval[1]);
- mouse_ungrab_xy[0] = data->ungrab_mval[0];
- mouse_ungrab_xy[1] = data->ungrab_mval[1];
-
- WM_cursor_grab_disable(data->window, mouse_ungrab_xy);
- }
- else {
- WM_cursor_grab_disable(data->window, NULL);
- }
+ /* stereo3d has issues with changing cursor location so rather avoid */
+ if (data->ungrab_mval[0] != FLT_MAX && !WM_stereo3d_enabled(data->window, false)) {
+ int mouse_ungrab_xy[2];
+ ui_block_to_window_fl(
+ data->region, but->block, &data->ungrab_mval[0], &data->ungrab_mval[1]);
+ mouse_ungrab_xy[0] = data->ungrab_mval[0];
+ mouse_ungrab_xy[1] = data->ungrab_mval[1];
+
+ WM_cursor_grab_disable(data->window, mouse_ungrab_xy);
+ }
+ else {
+ WM_cursor_grab_disable(data->window, NULL);
+ }
#else
- WM_cursor_grab_disable(data->window, NULL);
+ WM_cursor_grab_disable(data->window, NULL);
#endif
- }
- }
- /* menu open */
- if (state == BUTTON_STATE_MENU_OPEN) {
- ui_block_open_begin(C, but, data);
- }
- else if (data->state == BUTTON_STATE_MENU_OPEN) {
- ui_block_open_end(C, but, data);
- }
-
- /* add a short delay before exiting, to ensure there is some feedback */
- if (state == BUTTON_STATE_WAIT_FLASH) {
- data->flashtimer = WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_FLASH_DELAY);
- }
- else if (data->flashtimer) {
- WM_event_remove_timer(data->wm, data->window, data->flashtimer);
- data->flashtimer = NULL;
- }
-
- /* add hold timer if it's used */
- if (state == BUTTON_STATE_WAIT_RELEASE && (but->hold_func != NULL)) {
- data->hold_action_timer = WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_AUTO_OPEN_THRESH);
- }
- else if (data->hold_action_timer) {
- WM_event_remove_timer(data->wm, data->window, data->hold_action_timer);
- data->hold_action_timer = NULL;
- }
-
- /* add a blocking ui handler at the window handler for blocking, modal states
- * but not for popups, because we already have a window level handler*/
- if (!(but->block->handle && but->block->handle->popup)) {
- if (button_modal_state(state)) {
- if (!button_modal_state(data->state)) {
- WM_event_add_ui_handler(C, &data->window->modalhandlers, ui_handler_region_menu, NULL, data, 0);
- }
- }
- else {
- if (button_modal_state(data->state)) {
- /* true = postpone free */
- WM_event_remove_ui_handler(&data->window->modalhandlers, ui_handler_region_menu, NULL, data, true);
- }
- }
- }
-
- /* wait for mousemove to enable drag */
- if (state == BUTTON_STATE_WAIT_DRAG) {
- but->flag &= ~UI_SELECT;
- }
-
- data->state = state;
-
- if (state != BUTTON_STATE_EXIT) {
- /* When objects for eg. are removed, running ui_but_update() can access
- * the removed data - so disable update on exit. Also in case of
- * highlight when not in a popup menu, we remove because data used in
- * button below popup might have been removed by action of popup. Needs
- * a more reliable solution... */
- if (state != BUTTON_STATE_HIGHLIGHT || (but->block->flag & UI_BLOCK_LOOP)) {
- ui_but_update(but);
- }
- }
-
- /* redraw */
- ED_region_tag_redraw(data->region);
+ }
+ }
+ /* menu open */
+ if (state == BUTTON_STATE_MENU_OPEN) {
+ ui_block_open_begin(C, but, data);
+ }
+ else if (data->state == BUTTON_STATE_MENU_OPEN) {
+ ui_block_open_end(C, but, data);
+ }
+
+ /* add a short delay before exiting, to ensure there is some feedback */
+ if (state == BUTTON_STATE_WAIT_FLASH) {
+ data->flashtimer = WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_FLASH_DELAY);
+ }
+ else if (data->flashtimer) {
+ WM_event_remove_timer(data->wm, data->window, data->flashtimer);
+ data->flashtimer = NULL;
+ }
+
+ /* add hold timer if it's used */
+ if (state == BUTTON_STATE_WAIT_RELEASE && (but->hold_func != NULL)) {
+ data->hold_action_timer = WM_event_add_timer(
+ data->wm, data->window, TIMER, BUTTON_AUTO_OPEN_THRESH);
+ }
+ else if (data->hold_action_timer) {
+ WM_event_remove_timer(data->wm, data->window, data->hold_action_timer);
+ data->hold_action_timer = NULL;
+ }
+
+ /* add a blocking ui handler at the window handler for blocking, modal states
+ * but not for popups, because we already have a window level handler*/
+ if (!(but->block->handle && but->block->handle->popup)) {
+ if (button_modal_state(state)) {
+ if (!button_modal_state(data->state)) {
+ WM_event_add_ui_handler(
+ C, &data->window->modalhandlers, ui_handler_region_menu, NULL, data, 0);
+ }
+ }
+ else {
+ if (button_modal_state(data->state)) {
+ /* true = postpone free */
+ WM_event_remove_ui_handler(
+ &data->window->modalhandlers, ui_handler_region_menu, NULL, data, true);
+ }
+ }
+ }
+
+ /* wait for mousemove to enable drag */
+ if (state == BUTTON_STATE_WAIT_DRAG) {
+ but->flag &= ~UI_SELECT;
+ }
+
+ data->state = state;
+
+ if (state != BUTTON_STATE_EXIT) {
+ /* When objects for eg. are removed, running ui_but_update() can access
+ * the removed data - so disable update on exit. Also in case of
+ * highlight when not in a popup menu, we remove because data used in
+ * button below popup might have been removed by action of popup. Needs
+ * a more reliable solution... */
+ if (state != BUTTON_STATE_HIGHLIGHT || (but->block->flag & UI_BLOCK_LOOP)) {
+ ui_but_update(but);
+ }
+ }
+
+ /* redraw */
+ ED_region_tag_redraw(data->region);
}
static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type)
{
- uiHandleButtonData *data;
+ uiHandleButtonData *data;
- /* setup struct */
- data = MEM_callocN(sizeof(uiHandleButtonData), "uiHandleButtonData");
- data->wm = CTX_wm_manager(C);
- data->window = CTX_wm_window(C);
- data->region = ar;
+ /* setup struct */
+ data = MEM_callocN(sizeof(uiHandleButtonData), "uiHandleButtonData");
+ data->wm = CTX_wm_manager(C);
+ data->window = CTX_wm_window(C);
+ data->region = ar;
#ifdef USE_CONT_MOUSE_CORRECT
- copy_v2_fl(data->ungrab_mval, FLT_MAX);
+ copy_v2_fl(data->ungrab_mval, FLT_MAX);
#endif
- if (ELEM(but->type, UI_BTYPE_CURVE, UI_BTYPE_SEARCH_MENU)) {
- /* XXX curve is temp */
- }
- else {
- if ((but->flag & UI_BUT_UPDATE_DELAY) == 0) {
- data->interactive = true;
- }
- }
-
- data->state = BUTTON_STATE_INIT;
-
- /* activate button */
- but->flag |= UI_ACTIVE;
-
- but->active = data;
-
- /* we disable auto_open in the block after a threshold, because we still
- * want to allow auto opening adjacent menus even if no button is activated
- * in between going over to the other button, but only for a short while */
- if (type == BUTTON_ACTIVATE_OVER && but->block->auto_open == true) {
- if (but->block->auto_open_last + BUTTON_AUTO_OPEN_THRESH < PIL_check_seconds_timer()) {
- but->block->auto_open = false;
- }
- }
-
- if (type == BUTTON_ACTIVATE_OVER) {
- data->used_mouse = true;
- }
- button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
-
- /* activate right away */
- if (but->flag & UI_BUT_IMMEDIATE) {
- if (but->type == UI_BTYPE_HOTKEY_EVENT) {
- button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
- }
- /* .. more to be added here */
- }
-
- if (type == BUTTON_ACTIVATE_OPEN) {
- button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
-
- /* activate first button in submenu */
- if (data->menu && data->menu->region) {
- ARegion *subar = data->menu->region;
- uiBlock *subblock = subar->uiblocks.first;
- uiBut *subbut;
-
- if (subblock) {
- subbut = ui_but_first(subblock);
-
- if (subbut) {
- ui_handle_button_activate(C, subar, subbut, BUTTON_ACTIVATE);
- }
- }
- }
- }
- else if (type == BUTTON_ACTIVATE_TEXT_EDITING) {
- button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
- }
- else if (type == BUTTON_ACTIVATE_APPLY) {
- button_activate_state(C, but, BUTTON_STATE_WAIT_FLASH);
- }
-
- if (but->type == UI_BTYPE_GRIP) {
- const bool horizontal = (BLI_rctf_size_x(&but->rect) < BLI_rctf_size_y(&but->rect));
- WM_cursor_modal_set(data->window, horizontal ? CURSOR_X_MOVE : CURSOR_Y_MOVE);
- }
- else if (but->type == UI_BTYPE_NUM) {
- ui_numedit_set_active(but);
- }
-
- if (UI_but_has_tooltip_label(but)) {
- /* Show a label for this button. */
- bScreen *sc = 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), ar,
- ui_but_tooltip_init);
- if (sc->tool_tip) {
- sc->tool_tip->pass = 1;
- }
- }
- }
+ if (ELEM(but->type, UI_BTYPE_CURVE, UI_BTYPE_SEARCH_MENU)) {
+ /* XXX curve is temp */
+ }
+ else {
+ if ((but->flag & UI_BUT_UPDATE_DELAY) == 0) {
+ data->interactive = true;
+ }
+ }
+
+ data->state = BUTTON_STATE_INIT;
+
+ /* activate button */
+ but->flag |= UI_ACTIVE;
+
+ but->active = data;
+
+ /* we disable auto_open in the block after a threshold, because we still
+ * want to allow auto opening adjacent menus even if no button is activated
+ * in between going over to the other button, but only for a short while */
+ if (type == BUTTON_ACTIVATE_OVER && but->block->auto_open == true) {
+ if (but->block->auto_open_last + BUTTON_AUTO_OPEN_THRESH < PIL_check_seconds_timer()) {
+ but->block->auto_open = false;
+ }
+ }
+
+ if (type == BUTTON_ACTIVATE_OVER) {
+ data->used_mouse = true;
+ }
+ button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
+
+ /* activate right away */
+ if (but->flag & UI_BUT_IMMEDIATE) {
+ if (but->type == UI_BTYPE_HOTKEY_EVENT) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
+ }
+ /* .. more to be added here */
+ }
+
+ if (type == BUTTON_ACTIVATE_OPEN) {
+ button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
+
+ /* activate first button in submenu */
+ if (data->menu && data->menu->region) {
+ ARegion *subar = data->menu->region;
+ uiBlock *subblock = subar->uiblocks.first;
+ uiBut *subbut;
+
+ if (subblock) {
+ subbut = ui_but_first(subblock);
+
+ if (subbut) {
+ ui_handle_button_activate(C, subar, subbut, BUTTON_ACTIVATE);
+ }
+ }
+ }
+ }
+ else if (type == BUTTON_ACTIVATE_TEXT_EDITING) {
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ }
+ else if (type == BUTTON_ACTIVATE_APPLY) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_FLASH);
+ }
+
+ if (but->type == UI_BTYPE_GRIP) {
+ const bool horizontal = (BLI_rctf_size_x(&but->rect) < BLI_rctf_size_y(&but->rect));
+ WM_cursor_modal_set(data->window, horizontal ? CURSOR_X_MOVE : CURSOR_Y_MOVE);
+ }
+ else if (but->type == UI_BTYPE_NUM) {
+ ui_numedit_set_active(but);
+ }
+
+ if (UI_but_has_tooltip_label(but)) {
+ /* Show a label for this button. */
+ bScreen *sc = 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), ar, ui_but_tooltip_init);
+ if (sc->tool_tip) {
+ sc->tool_tip->pass = 1;
+ }
+ }
+ }
}
static void button_activate_exit(
- bContext *C, uiBut *but, uiHandleButtonData *data,
- const bool mousemove, const bool onfree)
+ bContext *C, uiBut *but, uiHandleButtonData *data, const bool mousemove, const bool onfree)
{
- uiBlock *block = but->block;
- uiBut *bt;
+ uiBlock *block = but->block;
+ uiBut *bt;
- if (but->type == UI_BTYPE_GRIP) {
- WM_cursor_modal_restore(data->window);
- }
+ if (but->type == UI_BTYPE_GRIP) {
+ WM_cursor_modal_restore(data->window);
+ }
- /* ensure we are in the exit state */
- if (data->state != BUTTON_STATE_EXIT) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
+ /* ensure we are in the exit state */
+ if (data->state != BUTTON_STATE_EXIT) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
- /* apply the button action or value */
- if (!onfree) {
- ui_apply_but(C, block, but, data, false);
- }
+ /* apply the button action or value */
+ if (!onfree) {
+ ui_apply_but(C, block, but, data, false);
+ }
#ifdef USE_DRAG_MULTINUM
- if (data->multi_data.has_mbuts) {
- for (bt = block->buttons.first; bt; bt = bt->next) {
- if (bt->flag & UI_BUT_DRAG_MULTI) {
- bt->flag &= ~UI_BUT_DRAG_MULTI;
-
- if (!data->cancel) {
- ui_apply_but_autokey(C, bt);
- }
- }
- }
-
- ui_multibut_free(data, block);
- }
+ if (data->multi_data.has_mbuts) {
+ for (bt = block->buttons.first; bt; bt = bt->next) {
+ if (bt->flag & UI_BUT_DRAG_MULTI) {
+ bt->flag &= ~UI_BUT_DRAG_MULTI;
+
+ if (!data->cancel) {
+ ui_apply_but_autokey(C, bt);
+ }
+ }
+ }
+
+ ui_multibut_free(data, block);
+ }
#endif
- /* if this button is in a menu, this will set the button return
- * value to the button value and the menu return value to ok, the
- * menu return value will be picked up and the menu will close */
- if (block->handle && !(block->flag & UI_BLOCK_KEEP_OPEN)) {
- if (!data->cancel || data->escapecancel) {
- uiPopupBlockHandle *menu;
+ /* if this button is in a menu, this will set the button return
+ * value to the button value and the menu return value to ok, the
+ * menu return value will be picked up and the menu will close */
+ if (block->handle && !(block->flag & UI_BLOCK_KEEP_OPEN)) {
+ if (!data->cancel || data->escapecancel) {
+ uiPopupBlockHandle *menu;
- menu = block->handle;
- menu->butretval = data->retval;
- menu->menuretval = (data->cancel) ? UI_RETURN_CANCEL : UI_RETURN_OK;
- }
- }
+ menu = block->handle;
+ menu->butretval = data->retval;
+ menu->menuretval = (data->cancel) ? UI_RETURN_CANCEL : UI_RETURN_OK;
+ }
+ }
- if (!onfree && !data->cancel) {
- /* autokey & undo push */
- ui_apply_but_undo(but);
- ui_apply_but_autokey(C, but);
+ if (!onfree && !data->cancel) {
+ /* autokey & undo push */
+ ui_apply_but_undo(but);
+ ui_apply_but_autokey(C, but);
#ifdef USE_ALLSELECT
- {
- /* only RNA from this button is used */
- uiBut but_temp = *but;
- uiSelectContextStore *selctx_data = &data->select_others;
- for (int i = 0; i < selctx_data->elems_len; i++) {
- uiSelectContextElem *other = &selctx_data->elems[i];
- but_temp.rnapoin = other->ptr;
- ui_apply_but_autokey(C, &but_temp);
- }
- }
+ {
+ /* only RNA from this button is used */
+ uiBut but_temp = *but;
+ uiSelectContextStore *selctx_data = &data->select_others;
+ for (int i = 0; i < selctx_data->elems_len; i++) {
+ uiSelectContextElem *other = &selctx_data->elems[i];
+ but_temp.rnapoin = other->ptr;
+ ui_apply_but_autokey(C, &but_temp);
+ }
+ }
#endif
- /* popup menu memory */
- if (block->flag & UI_BLOCK_POPUP_MEMORY) {
- ui_popup_menu_memory_set(block, but);
- }
- }
+ /* popup menu memory */
+ if (block->flag & UI_BLOCK_POPUP_MEMORY) {
+ ui_popup_menu_memory_set(block, but);
+ }
+ }
- /* disable tooltips until mousemove + last active flag */
- for (block = data->region->uiblocks.first; block; block = block->next) {
- for (bt = block->buttons.first; bt; bt = bt->next) {
- bt->flag &= ~UI_BUT_LAST_ACTIVE;
- }
+ /* disable tooltips until mousemove + last active flag */
+ for (block = data->region->uiblocks.first; block; block = block->next) {
+ for (bt = block->buttons.first; bt; bt = bt->next) {
+ bt->flag &= ~UI_BUT_LAST_ACTIVE;
+ }
- block->tooltipdisabled = 1;
- }
+ block->tooltipdisabled = 1;
+ }
- ui_blocks_set_tooltips(data->region, false);
+ ui_blocks_set_tooltips(data->region, false);
- /* clean up */
- if (data->str) {
- MEM_freeN(data->str);
- }
- if (data->origstr) {
- MEM_freeN(data->origstr);
- }
+ /* clean up */
+ if (data->str) {
+ MEM_freeN(data->str);
+ }
+ if (data->origstr) {
+ MEM_freeN(data->origstr);
+ }
#ifdef USE_ALLSELECT
- ui_selectcontext_end(but, &data->select_others);
+ ui_selectcontext_end(but, &data->select_others);
#endif
- if (data->changed_cursor) {
- WM_cursor_modal_restore(data->window);
- }
+ if (data->changed_cursor) {
+ WM_cursor_modal_restore(data->window);
+ }
- /* redraw and refresh (for popups) */
- ED_region_tag_redraw(data->region);
- ED_region_tag_refresh_ui(data->region);
+ /* redraw and refresh (for popups) */
+ ED_region_tag_redraw(data->region);
+ ED_region_tag_refresh_ui(data->region);
- /* clean up button */
- if (but->active) {
- MEM_freeN(but->active);
- but->active = NULL;
- }
+ /* clean up button */
+ if (but->active) {
+ MEM_freeN(but->active);
+ but->active = NULL;
+ }
- but->flag &= ~(UI_ACTIVE | UI_SELECT);
- but->flag |= UI_BUT_LAST_ACTIVE;
- if (!onfree) {
- ui_but_update(but);
- }
+ but->flag &= ~(UI_ACTIVE | UI_SELECT);
+ but->flag |= UI_BUT_LAST_ACTIVE;
+ if (!onfree) {
+ ui_but_update(but);
+ }
- /* adds empty mousemove in queue for re-init handler, in case mouse is
- * 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);
- }
+ /* adds empty mousemove in queue for re-init handler, in case mouse is
+ * 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);
+ }
}
void ui_but_active_free(const bContext *C, uiBut *but)
{
- uiHandleButtonData *data;
+ uiHandleButtonData *data;
- /* this gets called when the button somehow disappears while it is still
- * active, this is bad for user interaction, but we need to handle this
- * case cleanly anyway in case it happens */
- if (but->active) {
- data = but->active;
- data->cancel = true;
- button_activate_exit((bContext *)C, but, data, false, true);
- }
+ /* this gets called when the button somehow disappears while it is still
+ * active, this is bad for user interaction, but we need to handle this
+ * case cleanly anyway in case it happens */
+ if (but->active) {
+ data = but->active;
+ data->cancel = true;
+ button_activate_exit((bContext *)C, but, data, false, true);
+ }
}
/* returns the active button with an optional checking function */
static uiBut *ui_context_button_active(ARegion *ar, bool (*but_check_cb)(uiBut *))
{
- uiBut *but_found = NULL;
-
- while (ar) {
- uiBlock *block;
- uiBut *but, *activebut = NULL;
-
- /* find active button */
- for (block = ar->uiblocks.first; block; block = block->next) {
- for (but = block->buttons.first; but; but = but->next) {
- if (but->active) {
- activebut = but;
- }
- else if (!activebut && (but->flag & UI_BUT_LAST_ACTIVE)) {
- activebut = but;
- }
- }
- }
-
- if (activebut && (but_check_cb == NULL || but_check_cb(activebut))) {
- uiHandleButtonData *data = activebut->active;
-
- but_found = activebut;
-
- /* recurse into opened menu, like colorpicker case */
- if (data && data->menu && (ar != data->menu->region)) {
- ar = data->menu->region;
- }
- else {
- return but_found;
- }
- }
- else {
- /* no active button */
- return but_found;
- }
- }
-
- return but_found;
+ uiBut *but_found = NULL;
+
+ while (ar) {
+ uiBlock *block;
+ uiBut *but, *activebut = NULL;
+
+ /* find active button */
+ for (block = ar->uiblocks.first; block; block = block->next) {
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->active) {
+ activebut = but;
+ }
+ else if (!activebut && (but->flag & UI_BUT_LAST_ACTIVE)) {
+ activebut = but;
+ }
+ }
+ }
+
+ if (activebut && (but_check_cb == NULL || but_check_cb(activebut))) {
+ uiHandleButtonData *data = activebut->active;
+
+ but_found = activebut;
+
+ /* recurse into opened menu, like colorpicker case */
+ if (data && data->menu && (ar != data->menu->region)) {
+ ar = data->menu->region;
+ }
+ else {
+ return but_found;
+ }
+ }
+ else {
+ /* no active button */
+ return but_found;
+ }
+ }
+
+ return but_found;
}
static bool ui_context_rna_button_active_test(uiBut *but)
{
- return (but->rnapoin.data != NULL);
+ return (but->rnapoin.data != NULL);
}
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);
+ 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)
{
- return ui_context_button_active(CTX_wm_region(C), NULL);
+ return ui_context_button_active(CTX_wm_region(C), NULL);
}
uiBut *UI_region_active_but_get(ARegion *ar)
{
- return ui_context_button_active(ar, NULL);
+ return ui_context_button_active(ar, NULL);
}
/**
@@ -7666,123 +7686,124 @@ uiBut *UI_region_active_but_get(ARegion *ar)
*
* \return active button, NULL if none found or if it doesn't contain valid RNA data.
*/
-uiBut *UI_context_active_but_prop_get(
- const bContext *C,
- struct PointerRNA *r_ptr, struct PropertyRNA **r_prop, int *r_index)
+uiBut *UI_context_active_but_prop_get(const bContext *C,
+ struct PointerRNA *r_ptr,
+ struct PropertyRNA **r_prop,
+ int *r_index)
{
- uiBut *activebut = ui_context_rna_button_active(C);
+ uiBut *activebut = ui_context_rna_button_active(C);
- if (activebut && activebut->rnapoin.data) {
- *r_ptr = activebut->rnapoin;
- *r_prop = activebut->rnaprop;
- *r_index = activebut->rnaindex;
- }
- else {
- memset(r_ptr, 0, sizeof(*r_ptr));
- *r_prop = NULL;
- *r_index = 0;
- }
+ if (activebut && activebut->rnapoin.data) {
+ *r_ptr = activebut->rnapoin;
+ *r_prop = activebut->rnaprop;
+ *r_index = activebut->rnaindex;
+ }
+ else {
+ memset(r_ptr, 0, sizeof(*r_ptr));
+ *r_prop = NULL;
+ *r_index = 0;
+ }
- return activebut;
+ return activebut;
}
void UI_context_active_but_prop_handle(bContext *C)
{
- uiBut *activebut = ui_context_rna_button_active(C);
- if (activebut) {
- /* TODO, look into a better way to handle the button change
- * currently this is mainly so reset defaults works for the
- * operator redo panel - campbell */
- uiBlock *block = activebut->block;
- if (block->handle_func) {
- block->handle_func(C, block->handle_func_arg, activebut->retval);
- }
- }
+ uiBut *activebut = ui_context_rna_button_active(C);
+ if (activebut) {
+ /* TODO, look into a better way to handle the button change
+ * currently this is mainly so reset defaults works for the
+ * operator redo panel - campbell */
+ uiBlock *block = activebut->block;
+ if (block->handle_func) {
+ block->handle_func(C, block->handle_func_arg, activebut->retval);
+ }
+ }
}
wmOperator *UI_context_active_operator_get(const struct bContext *C)
{
- ARegion *ar_ctx = CTX_wm_region(C);
- uiBlock *block;
-
- /* background mode */
- if (ar_ctx == NULL) {
- return NULL;
- }
-
- /* scan active regions ui */
- for (block = ar_ctx->uiblocks.first; block; block = block->next) {
- if (block->ui_operator) {
- return block->ui_operator;
- }
- }
-
- /* scan popups */
- {
- bScreen *sc = CTX_wm_screen(C);
- ARegion *ar;
-
- for (ar = sc->regionbase.first; ar; ar = ar->next) {
- if (ar == ar_ctx) {
- continue;
- }
- for (block = ar->uiblocks.first; block; block = block->next) {
- if (block->ui_operator) {
- return block->ui_operator;
- }
- }
- }
- }
-
- return NULL;
+ ARegion *ar_ctx = CTX_wm_region(C);
+ uiBlock *block;
+
+ /* background mode */
+ if (ar_ctx == NULL) {
+ return NULL;
+ }
+
+ /* scan active regions ui */
+ for (block = ar_ctx->uiblocks.first; block; block = block->next) {
+ if (block->ui_operator) {
+ return block->ui_operator;
+ }
+ }
+
+ /* scan popups */
+ {
+ bScreen *sc = CTX_wm_screen(C);
+ ARegion *ar;
+
+ for (ar = sc->regionbase.first; ar; ar = ar->next) {
+ if (ar == ar_ctx) {
+ continue;
+ }
+ for (block = ar->uiblocks.first; block; block = block->next) {
+ if (block->ui_operator) {
+ return block->ui_operator;
+ }
+ }
+ }
+ }
+
+ return NULL;
}
/* helper function for insert keyframe, reset to default, etc operators */
void UI_context_update_anim_flag(const bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
- uiBlock *block;
- uiBut *but, *activebut;
-
- while (ar) {
- /* find active button */
- activebut = NULL;
-
- for (block = ar->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);
- if (UI_but_is_decorator(but)) {
- ui_but_anim_decorate_update_from_flag(but);
- }
-
- ED_region_tag_redraw(ar);
-
- if (but->active) {
- activebut = but;
- }
- else if (!activebut && (but->flag & UI_BUT_LAST_ACTIVE)) {
- activebut = but;
- }
- }
- }
-
- if (activebut) {
- /* always recurse into opened menu, so all buttons update (like colorpicker) */
- uiHandleButtonData *data = activebut->active;
- if (data && data->menu) {
- ar = data->menu->region;
- }
- else {
- return;
- }
- }
- else {
- /* no active button */
- return;
- }
- }
+ Scene *scene = CTX_data_scene(C);
+ ARegion *ar = CTX_wm_region(C);
+ uiBlock *block;
+ uiBut *but, *activebut;
+
+ while (ar) {
+ /* find active button */
+ activebut = NULL;
+
+ for (block = ar->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);
+ if (UI_but_is_decorator(but)) {
+ ui_but_anim_decorate_update_from_flag(but);
+ }
+
+ ED_region_tag_redraw(ar);
+
+ if (but->active) {
+ activebut = but;
+ }
+ else if (!activebut && (but->flag & UI_BUT_LAST_ACTIVE)) {
+ activebut = but;
+ }
+ }
+ }
+
+ if (activebut) {
+ /* always recurse into opened menu, so all buttons update (like colorpicker) */
+ uiHandleButtonData *data = activebut->active;
+ if (data && data->menu) {
+ ar = data->menu->region;
+ }
+ else {
+ return;
+ }
+ }
+ else {
+ /* no active button */
+ return;
+ }
+ }
}
/** \} */
@@ -7793,60 +7814,60 @@ void UI_context_update_anim_flag(const bContext *C)
static uiBut *ui_but_find_open_event(ARegion *ar, const wmEvent *event)
{
- uiBlock *block;
- uiBut *but;
+ uiBlock *block;
+ uiBut *but;
- for (block = ar->uiblocks.first; block; block = block->next) {
- for (but = block->buttons.first; but; but = but->next) {
- if (but == event->customdata) {
- return but;
- }
- }
- }
- return NULL;
+ for (block = ar->uiblocks.first; block; block = block->next) {
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but == event->customdata) {
+ return but;
+ }
+ }
+ }
+ return NULL;
}
static int ui_handle_button_over(bContext *C, const wmEvent *event, ARegion *ar)
{
- uiBut *but;
+ uiBut *but;
- if (event->type == MOUSEMOVE) {
- but = ui_but_find_mouse_over(ar, event);
- if (but) {
- button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+ if (event->type == MOUSEMOVE) {
+ but = ui_but_find_mouse_over(ar, event);
+ if (but) {
+ button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
- if (event->alt && but->active) {
- /* display tooltips if holding alt on mouseover when tooltips are off in prefs */
- but->active->tooltip_force = true;
- }
- }
- }
- else if (event->type == EVT_BUT_OPEN) {
- but = ui_but_find_open_event(ar, event);
- if (but) {
- button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
- ui_do_button(C, but->block, but, event);
- }
- }
+ if (event->alt && but->active) {
+ /* display tooltips if holding alt on mouseover when tooltips are off in prefs */
+ but->active->tooltip_force = true;
+ }
+ }
+ }
+ else if (event->type == EVT_BUT_OPEN) {
+ but = ui_but_find_open_event(ar, event);
+ if (but) {
+ button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+ ui_do_button(C, but->block, but, event);
+ }
+ }
- return WM_UI_HANDLER_CONTINUE;
+ return WM_UI_HANDLER_CONTINUE;
}
/* exported to interface.c: UI_but_active_only() */
void ui_but_activate_event(bContext *C, ARegion *ar, uiBut *but)
{
- wmWindow *win = CTX_wm_window(C);
- wmEvent event;
+ wmWindow *win = CTX_wm_window(C);
+ wmEvent event;
- button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+ button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
- wm_event_init_from_window(win, &event);
- event.type = EVT_BUT_OPEN;
- event.val = KM_PRESS;
- event.customdata = but;
- event.customdatafree = false;
+ wm_event_init_from_window(win, &event);
+ event.type = EVT_BUT_OPEN;
+ event.val = KM_PRESS;
+ event.customdata = but;
+ event.customdatafree = false;
- ui_do_button(C, but->block, but, &event);
+ ui_do_button(C, but->block, but, &event);
}
/**
@@ -7857,45 +7878,54 @@ void ui_but_activate_event(bContext *C, ARegion *ar, uiBut *but)
*/
void ui_but_activate_over(bContext *C, ARegion *ar, uiBut *but)
{
- button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+ button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
}
-void ui_but_execute_begin(struct bContext *UNUSED(C), struct ARegion *ar, uiBut *but, void **active_back)
+void ui_but_execute_begin(struct bContext *UNUSED(C),
+ struct ARegion *ar,
+ uiBut *but,
+ void **active_back)
{
- /* 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;
- data->region = ar;
+ /* 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;
+ data->region = ar;
}
-void ui_but_execute_end(struct bContext *C, struct ARegion *UNUSED(ar), uiBut *but, void *active_back)
+void ui_but_execute_end(struct bContext *C,
+ struct ARegion *UNUSED(ar),
+ uiBut *but,
+ void *active_back)
{
- ui_apply_but(C, but->block, but, but->active, true);
+ ui_apply_but(C, but->block, but, but->active, true);
- if ((but->flag & UI_BUT_DRAG_MULTI) == 0) {
- ui_apply_but_autokey(C, but);
- }
- /* use onfree event so undo is handled by caller and apply is already done above */
- button_activate_exit((bContext *)C, but, but->active, false, true);
- but->active = active_back;
+ if ((but->flag & UI_BUT_DRAG_MULTI) == 0) {
+ ui_apply_but_autokey(C, but);
+ }
+ /* use onfree event so undo is handled by caller and apply is already done above */
+ button_activate_exit((bContext *)C, but, but->active, false, true);
+ but->active = active_back;
}
-static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type)
+static void ui_handle_button_activate(bContext *C,
+ ARegion *ar,
+ uiBut *but,
+ uiButtonActivateType type)
{
- uiBut *oldbut;
- uiHandleButtonData *data;
+ uiBut *oldbut;
+ uiHandleButtonData *data;
- oldbut = ui_region_find_active_but(ar);
- if (oldbut) {
- data = oldbut->active;
- data->cancel = true;
- button_activate_exit(C, oldbut, data, false, false);
- }
+ oldbut = ui_region_find_active_but(ar);
+ 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, ar, but, type);
}
/**
@@ -7903,25 +7933,25 @@ static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiBu
*/
static bool ui_handle_button_activate_by_type(bContext *C, ARegion *ar, uiBut *but)
{
- if (but->type == UI_BTYPE_BUT_MENU) {
- /* mainly for operator buttons */
- ui_handle_button_activate(C, ar, 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);
- }
- else if (but->type == UI_BTYPE_MENU) {
- /* activate menu items */
- ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE);
- }
- else {
+ if (but->type == UI_BTYPE_BUT_MENU) {
+ /* mainly for operator buttons */
+ ui_handle_button_activate(C, ar, 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);
+ }
+ else if (but->type == UI_BTYPE_MENU) {
+ /* activate menu items */
+ ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE);
+ }
+ else {
#ifdef DEBUG
- printf("%s: error, unhandled type: %u\n", __func__, but->type);
+ printf("%s: error, unhandled type: %u\n", __func__, but->type);
#endif
- return false;
- }
- return true;
+ return false;
+ }
+ return true;
}
/** \} */
@@ -7932,502 +7962,494 @@ static bool ui_handle_button_activate_by_type(bContext *C, ARegion *ar, uiBut *b
static bool ui_button_value_default(uiBut *but, double *r_value)
{
- if (but->rnaprop != NULL && ui_but_is_rna_valid(but)) {
- int type = RNA_property_type(but->rnaprop);
- if (ELEM(type, PROP_FLOAT, PROP_INT)) {
- double default_value;
- switch (type) {
- case PROP_INT:
- if (RNA_property_array_check(but->rnaprop)) {
- default_value = (double)RNA_property_int_get_default_index(&but->rnapoin, but->rnaprop, but->rnaindex);
- }
- else {
- default_value = (double)RNA_property_int_get_default(&but->rnapoin, but->rnaprop);
- }
- break;
- case PROP_FLOAT:
- if (RNA_property_array_check(but->rnaprop)) {
- default_value = (double)RNA_property_float_get_default_index(&but->rnapoin, but->rnaprop, but->rnaindex);
- }
- else {
- default_value = (double)RNA_property_float_get_default(&but->rnapoin, but->rnaprop);
- }
- break;
- }
- *r_value = default_value;
- return true;
- }
- }
- return false;
+ if (but->rnaprop != NULL && ui_but_is_rna_valid(but)) {
+ int type = RNA_property_type(but->rnaprop);
+ if (ELEM(type, PROP_FLOAT, PROP_INT)) {
+ double default_value;
+ switch (type) {
+ case PROP_INT:
+ if (RNA_property_array_check(but->rnaprop)) {
+ default_value = (double)RNA_property_int_get_default_index(
+ &but->rnapoin, but->rnaprop, but->rnaindex);
+ }
+ else {
+ default_value = (double)RNA_property_int_get_default(&but->rnapoin, but->rnaprop);
+ }
+ break;
+ case PROP_FLOAT:
+ if (RNA_property_array_check(but->rnaprop)) {
+ default_value = (double)RNA_property_float_get_default_index(
+ &but->rnapoin, but->rnaprop, but->rnaindex);
+ }
+ else {
+ default_value = (double)RNA_property_float_get_default(&but->rnapoin, but->rnaprop);
+ }
+ break;
+ }
+ *r_value = default_value;
+ return true;
+ }
+ }
+ return false;
}
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;
- int retval;
+ uiHandleButtonData *data = but->active;
+ const uiHandleButtonState state_orig = data->state;
+ uiBlock *block;
+ ARegion *ar;
+ int retval;
- block = but->block;
- ar = data->region;
+ block = but->block;
+ ar = data->region;
- retval = WM_UI_HANDLER_CONTINUE;
+ retval = WM_UI_HANDLER_CONTINUE;
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- switch (event->type) {
- case WINDEACTIVATE:
- case EVT_BUT_CANCEL:
- data->cancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- break;
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ switch (event->type) {
+ case WINDEACTIVATE:
+ case EVT_BUT_CANCEL:
+ data->cancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ break;
#ifdef USE_UI_POPOVER_ONCE
- case LEFTMOUSE:
- {
- if (event->val == KM_RELEASE) {
- if (block->flag & UI_BLOCK_POPOVER_ONCE) {
- if (!(but->flag & UI_BUT_DISABLED)) {
- if (ui_but_is_popover_once_compat(but)) {
- data->cancel = false;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- retval = WM_UI_HANDLER_BREAK;
- /* Cancel because this `but` handles all events and we don't want
- * the parent button's update function to do anything.
- *
- * Causes issues with buttons defined by #uiItemFullR_with_popover. */
- 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);
- retval = WM_UI_HANDLER_BREAK;
- }
- }
- }
- }
- break;
- }
+ case LEFTMOUSE: {
+ if (event->val == KM_RELEASE) {
+ if (block->flag & UI_BLOCK_POPOVER_ONCE) {
+ if (!(but->flag & UI_BUT_DISABLED)) {
+ if (ui_but_is_popover_once_compat(but)) {
+ data->cancel = false;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ retval = WM_UI_HANDLER_BREAK;
+ /* Cancel because this `but` handles all events and we don't want
+ * the parent button's update function to do anything.
+ *
+ * Causes issues with buttons defined by #uiItemFullR_with_popover. */
+ 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);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
+ }
+ }
+ break;
+ }
#endif
- case MOUSEMOVE:
- {
- uiBut *but_other = ui_but_find_mouse_over(ar, 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))
- {
- exit = true;
- }
- else if (but_other && ui_but_is_editable(but_other) && (but_other != but)) {
- exit = true;
- }
-
- if (exit) {
- data->cancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- else if (event->x != event->prevx || event->y != event->prevy) {
- /* re-enable tooltip on mouse move */
- ui_blocks_set_tooltips(ar, true);
- button_tooltip_timer_reset(C, but);
- }
-
- break;
- }
- case TIMER:
- {
- /* Handle menu auto open timer. */
- if (event->customdata == data->autoopentimer) {
- 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) {
- button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
- }
- }
-
- break;
- }
- /* XXX hardcoded keymap check... but anyway,
- * while view changes, tooltips should be removed */
- case WHEELUPMOUSE:
- case WHEELDOWNMOUSE:
- case MIDDLEMOUSE:
- case MOUSEPAN:
- UI_but_tooltip_timer_remove(C, but);
- ATTR_FALLTHROUGH;
- default:
- break;
- }
-
- /* handle button type specific events */
- retval = ui_do_button(C, block, but, event);
- }
- else if (data->state == BUTTON_STATE_WAIT_RELEASE) {
- switch (event->type) {
- case WINDEACTIVATE:
- data->cancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- break;
-
- case TIMER:
- {
- if (event->customdata == data->hold_action_timer) {
- if (true) {
- data->cancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- else {
- /* Do this so we can still mouse-up, closing the menu and running the button.
- * This is nice to support but there are times when the button gets left pressed.
- * Keep disavled for now. */
- WM_event_remove_timer(data->wm, data->window, data->hold_action_timer);
- data->hold_action_timer = NULL;
- }
- retval = WM_UI_HANDLER_CONTINUE;
- but->hold_func(C, data->region, but);
- }
- break;
- }
- 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)) {
-
- /* Drag on a hold button (used in the toolbar) now opens it immediately. */
- if (data->hold_action_timer) {
- if (but->flag & UI_SELECT) {
- if (len_manhattan_v2v2_int(&event->x, &event->prevx) <= WM_EVENT_CURSOR_MOTION_THRESHOLD) {
- /* pass */
- }
- else {
- WM_event_remove_timer(data->wm, data->window, data->hold_action_timer);
- data->hold_action_timer = WM_event_add_timer(data->wm, data->window, TIMER, 0.0f);
- }
- }
- }
-
- if (!(but->flag & UI_SELECT)) {
- but->flag |= (UI_SELECT | UI_ACTIVE);
- data->cancel = false;
- ED_region_tag_redraw(data->region);
- }
- }
- else {
- if (but->flag & UI_SELECT) {
- but->flag &= ~(UI_SELECT | UI_ACTIVE);
- data->cancel = true;
- ED_region_tag_redraw(data->region);
- }
- }
- break;
- }
- default:
- /* otherwise catch mouse release event */
- ui_do_button(C, block, but, event);
- break;
- }
-
- retval = WM_UI_HANDLER_BREAK;
- }
- else if (data->state == BUTTON_STATE_WAIT_FLASH) {
- switch (event->type) {
- case TIMER:
- {
- if (event->customdata == data->flashtimer) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- break;
- }
- }
-
- retval = WM_UI_HANDLER_CONTINUE;
- }
- else if (data->state == BUTTON_STATE_MENU_OPEN) {
- /* check for exit because of mouse-over another button */
- switch (event->type) {
- case MOUSEMOVE:
- {
- uiBut *bt;
-
- if (data->menu && data->menu->region) {
- if (ui_region_contains_point_px(data->menu->region, event->x, event->y)) {
- break;
- }
- }
-
- bt = ui_but_find_mouse_over(ar, event);
-
- if (bt && bt->active != data) {
- if (but->type != UI_BTYPE_COLOR) { /* exception */
- data->cancel = true;
- }
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- break;
- }
- case RIGHTMOUSE:
- {
- if (event->val == KM_PRESS) {
- uiBut *bt = ui_but_find_mouse_over(ar, event);
- if (bt && bt->active == data) {
- button_activate_state(C, bt, BUTTON_STATE_HIGHLIGHT);
- }
- }
- break;
- }
-
- }
-
- ui_do_button(C, block, but, event);
- retval = WM_UI_HANDLER_CONTINUE;
- }
- else {
- retval = ui_do_button(C, block, but, event);
- // retval = WM_UI_HANDLER_BREAK; XXX why ?
- }
-
- /* may have been re-allocated above (eyedropper for eg) */
- data = but->active;
- if (data && data->state == BUTTON_STATE_EXIT) {
- uiBut *post_but = data->postbut;
- uiButtonActivateType post_type = data->posttype;
-
- /* Reset the button value when empty text is typed. */
- if ((data->cancel == false) && (data->str != NULL) && (data->str[0] == '\0') &&
- (but->rnaprop && ELEM(RNA_property_type(but->rnaprop), PROP_FLOAT, PROP_INT)))
- {
- MEM_SAFE_FREE(data->str);
- ui_button_value_default(but, &data->value);
+ case MOUSEMOVE: {
+ uiBut *but_other = ui_but_find_mouse_over(ar, 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)) {
+ exit = true;
+ }
+ else if (but_other && ui_but_is_editable(but_other) && (but_other != but)) {
+ exit = true;
+ }
+
+ if (exit) {
+ data->cancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else if (event->x != event->prevx || event->y != event->prevy) {
+ /* re-enable tooltip on mouse move */
+ ui_blocks_set_tooltips(ar, true);
+ button_tooltip_timer_reset(C, but);
+ }
+
+ break;
+ }
+ case TIMER: {
+ /* Handle menu auto open timer. */
+ if (event->customdata == data->autoopentimer) {
+ 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) {
+ button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
+ }
+ }
+
+ break;
+ }
+ /* XXX hardcoded keymap check... but anyway,
+ * while view changes, tooltips should be removed */
+ case WHEELUPMOUSE:
+ case WHEELDOWNMOUSE:
+ case MIDDLEMOUSE:
+ case MOUSEPAN:
+ UI_but_tooltip_timer_remove(C, but);
+ ATTR_FALLTHROUGH;
+ default:
+ break;
+ }
+
+ /* handle button type specific events */
+ retval = ui_do_button(C, block, but, event);
+ }
+ else if (data->state == BUTTON_STATE_WAIT_RELEASE) {
+ switch (event->type) {
+ case WINDEACTIVATE:
+ data->cancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ break;
+
+ case TIMER: {
+ if (event->customdata == data->hold_action_timer) {
+ if (true) {
+ data->cancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else {
+ /* Do this so we can still mouse-up, closing the menu and running the button.
+ * This is nice to support but there are times when the button gets left pressed.
+ * Keep disavled for now. */
+ WM_event_remove_timer(data->wm, data->window, data->hold_action_timer);
+ data->hold_action_timer = NULL;
+ }
+ retval = WM_UI_HANDLER_CONTINUE;
+ but->hold_func(C, data->region, but);
+ }
+ break;
+ }
+ 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)) {
+
+ /* Drag on a hold button (used in the toolbar) now opens it immediately. */
+ if (data->hold_action_timer) {
+ if (but->flag & UI_SELECT) {
+ if (len_manhattan_v2v2_int(&event->x, &event->prevx) <=
+ WM_EVENT_CURSOR_MOTION_THRESHOLD) {
+ /* pass */
+ }
+ else {
+ WM_event_remove_timer(data->wm, data->window, data->hold_action_timer);
+ data->hold_action_timer = WM_event_add_timer(data->wm, data->window, TIMER, 0.0f);
+ }
+ }
+ }
+
+ if (!(but->flag & UI_SELECT)) {
+ but->flag |= (UI_SELECT | UI_ACTIVE);
+ data->cancel = false;
+ ED_region_tag_redraw(data->region);
+ }
+ }
+ else {
+ if (but->flag & UI_SELECT) {
+ but->flag &= ~(UI_SELECT | UI_ACTIVE);
+ data->cancel = true;
+ ED_region_tag_redraw(data->region);
+ }
+ }
+ break;
+ }
+ default:
+ /* otherwise catch mouse release event */
+ ui_do_button(C, block, but, event);
+ break;
+ }
+
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (data->state == BUTTON_STATE_WAIT_FLASH) {
+ switch (event->type) {
+ case TIMER: {
+ if (event->customdata == data->flashtimer) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ break;
+ }
+ }
+
+ retval = WM_UI_HANDLER_CONTINUE;
+ }
+ else if (data->state == BUTTON_STATE_MENU_OPEN) {
+ /* check for exit because of mouse-over another button */
+ switch (event->type) {
+ case MOUSEMOVE: {
+ uiBut *bt;
+
+ if (data->menu && data->menu->region) {
+ if (ui_region_contains_point_px(data->menu->region, event->x, event->y)) {
+ break;
+ }
+ }
+
+ bt = ui_but_find_mouse_over(ar, event);
+
+ if (bt && bt->active != data) {
+ if (but->type != UI_BTYPE_COLOR) { /* exception */
+ data->cancel = true;
+ }
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ break;
+ }
+ case RIGHTMOUSE: {
+ if (event->val == KM_PRESS) {
+ uiBut *bt = ui_but_find_mouse_over(ar, event);
+ if (bt && bt->active == data) {
+ button_activate_state(C, bt, BUTTON_STATE_HIGHLIGHT);
+ }
+ }
+ break;
+ }
+ }
+
+ ui_do_button(C, block, but, event);
+ retval = WM_UI_HANDLER_CONTINUE;
+ }
+ else {
+ retval = ui_do_button(C, block, but, event);
+ // retval = WM_UI_HANDLER_BREAK; XXX why ?
+ }
+
+ /* may have been re-allocated above (eyedropper for eg) */
+ data = but->active;
+ if (data && data->state == BUTTON_STATE_EXIT) {
+ uiBut *post_but = data->postbut;
+ uiButtonActivateType post_type = data->posttype;
+
+ /* Reset the button value when empty text is typed. */
+ if ((data->cancel == false) && (data->str != NULL) && (data->str[0] == '\0') &&
+ (but->rnaprop && ELEM(RNA_property_type(but->rnaprop), PROP_FLOAT, PROP_INT))) {
+ MEM_SAFE_FREE(data->str);
+ ui_button_value_default(but, &data->value);
#ifdef USE_DRAG_MULTINUM
- if (data->multi_data.mbuts) {
- for (LinkNode *l = data->multi_data.mbuts; l; l = l->next) {
- uiButMultiState *state = l->link;
- uiBut *but_iter = state->but;
- double default_value;
-
- if (ui_button_value_default(but_iter, &default_value)) {
- ui_but_value_set(but_iter, default_value);
- }
- }
- }
- data->multi_data.skip = true;
+ if (data->multi_data.mbuts) {
+ for (LinkNode *l = data->multi_data.mbuts; l; l = l->next) {
+ uiButMultiState *state = l->link;
+ uiBut *but_iter = state->but;
+ double default_value;
+
+ if (ui_button_value_default(but_iter, &default_value)) {
+ ui_but_value_set(but_iter, default_value);
+ }
+ }
+ }
+ data->multi_data.skip = true;
#endif
- }
-
- button_activate_exit(C, but, data, (post_but == NULL), false);
-
- /* for jumping to the next button with tab while text editing */
- if (post_but) {
- button_activate_init(C, ar, post_but, post_type);
- }
- else {
- /* XXX issue is because WM_event_add_mousemove(C) 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);
- }
- }
- }
- }
-
- return retval;
+ }
+
+ button_activate_exit(C, but, data, (post_but == NULL), false);
+
+ /* for jumping to the next button with tab while text editing */
+ if (post_but) {
+ button_activate_init(C, ar, post_but, post_type);
+ }
+ else {
+ /* XXX issue is because WM_event_add_mousemove(C) 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);
+ }
+ }
+ }
+ }
+
+ return retval;
}
static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar, uiBut *listbox)
{
- uiList *ui_list;
- uiListDyn *dyn_data;
- int retval = WM_UI_HANDLER_CONTINUE;
- int type = event->type, val = event->val;
- bool redraw = false;
- int mx, my;
-
- ui_list = listbox->custom_data;
- if (!ui_list || !ui_list->dyn_data) {
- return retval;
- }
- dyn_data = ui_list->dyn_data;
-
- mx = event->x;
- my = event->y;
- ui_window_to_block(ar, listbox->block, &mx, &my);
-
- /* convert pan to scrollwheel */
- if (type == MOUSEPAN) {
- ui_pan_to_scroll(event, &type, &val);
-
- /* if type still is mousepan, we call it handled, since delta-y accumulate */
- /* also see wm_event_system.c do_wheel_ui hack */
- if (type == MOUSEPAN) {
- retval = WM_UI_HANDLER_BREAK;
- }
- }
-
- if (val == KM_PRESS) {
- if ((ELEM(type, UPARROWKEY, 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);
- int value, min, max, inc;
-
- /* 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;
- }
- else {
- inc = ELEM(type, UPARROWKEY, WHEELUPMOUSE) ? -1 : 1;
- }
-
- if (dyn_data->items_filter_neworder || dyn_data->items_filter_flags) {
- /* If we have a display order different from
- * collection order, we have some work! */
- int *org_order = MEM_mallocN(dyn_data->items_shown * sizeof(int), __func__);
- const int *new_order = dyn_data->items_filter_neworder;
- int i, org_idx = -1, len = dyn_data->items_len;
- int current_idx = -1;
- int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE;
-
- for (i = 0; i < len; i++) {
- if (!dyn_data->items_filter_flags ||
- ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude))
- {
- org_order[new_order ? new_order[++org_idx] : ++org_idx] = i;
- if (i == value) {
- current_idx = new_order ? new_order[org_idx] : org_idx;
- }
- }
- else if (i == value && org_idx >= 0) {
- current_idx = -(new_order ? new_order[org_idx] : org_idx) - 1;
- }
- }
- /* Now, org_order maps displayed indices to real indices,
- * and current_idx either contains the displayed index of active value (positive),
- * or its more-nearest one (negated).
- */
- if (current_idx < 0) {
- current_idx = (current_idx * -1) + (inc < 0 ? inc : inc - 1);
- }
- else {
- current_idx += inc;
- }
- CLAMP(current_idx, 0, dyn_data->items_shown - 1);
- value = org_order[current_idx];
- MEM_freeN(org_order);
- }
- else {
- value += inc;
- }
-
- CLAMP(value, 0, dyn_data->items_len - 1);
-
- RNA_property_int_range(&listbox->rnapoin, listbox->rnaprop, &min, &max);
- CLAMP(value, min, max);
-
- if (value != value_orig) {
- RNA_property_int_set(&listbox->rnapoin, listbox->rnaprop, value);
- RNA_property_update(C, &listbox->rnapoin, listbox->rnaprop);
-
- ui_apply_but_undo(listbox);
-
- ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
- redraw = true;
- }
- retval = WM_UI_HANDLER_BREAK;
- }
- else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
- /* We now have proper grip, but keep this anyway! */
- if (ui_list->list_grip < (dyn_data->visual_height_min - UI_LIST_AUTO_SIZE_THRESHOLD)) {
- ui_list->list_grip = dyn_data->visual_height;
- }
- ui_list->list_grip += (type == WHEELUPMOUSE) ? -1 : 1;
-
- ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
-
- redraw = true;
- retval = WM_UI_HANDLER_BREAK;
- }
- else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
- if (dyn_data->height > dyn_data->visual_height) {
- /* list template will clamp */
- ui_list->list_scroll += (type == WHEELUPMOUSE) ? -1 : 1;
-
- redraw = true;
- retval = WM_UI_HANDLER_BREAK;
- }
- }
- }
-
- if (redraw) {
- ED_region_tag_redraw(ar);
- ED_region_tag_refresh_ui(ar);
- }
-
- return retval;
+ uiList *ui_list;
+ uiListDyn *dyn_data;
+ int retval = WM_UI_HANDLER_CONTINUE;
+ int type = event->type, val = event->val;
+ bool redraw = false;
+ int mx, my;
+
+ ui_list = listbox->custom_data;
+ if (!ui_list || !ui_list->dyn_data) {
+ return retval;
+ }
+ dyn_data = ui_list->dyn_data;
+
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(ar, listbox->block, &mx, &my);
+
+ /* convert pan to scrollwheel */
+ if (type == MOUSEPAN) {
+ ui_pan_to_scroll(event, &type, &val);
+
+ /* if type still is mousepan, we call it handled, since delta-y accumulate */
+ /* also see wm_event_system.c do_wheel_ui hack */
+ if (type == MOUSEPAN) {
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ if (val == KM_PRESS) {
+ if ((ELEM(type, UPARROWKEY, 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);
+ int value, min, max, inc;
+
+ /* 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;
+ }
+ else {
+ inc = ELEM(type, UPARROWKEY, WHEELUPMOUSE) ? -1 : 1;
+ }
+
+ if (dyn_data->items_filter_neworder || dyn_data->items_filter_flags) {
+ /* If we have a display order different from
+ * collection order, we have some work! */
+ int *org_order = MEM_mallocN(dyn_data->items_shown * sizeof(int), __func__);
+ const int *new_order = dyn_data->items_filter_neworder;
+ int i, org_idx = -1, len = dyn_data->items_len;
+ int current_idx = -1;
+ int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE;
+
+ for (i = 0; i < len; i++) {
+ if (!dyn_data->items_filter_flags ||
+ ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude)) {
+ org_order[new_order ? new_order[++org_idx] : ++org_idx] = i;
+ if (i == value) {
+ current_idx = new_order ? new_order[org_idx] : org_idx;
+ }
+ }
+ else if (i == value && org_idx >= 0) {
+ current_idx = -(new_order ? new_order[org_idx] : org_idx) - 1;
+ }
+ }
+ /* Now, org_order maps displayed indices to real indices,
+ * and current_idx either contains the displayed index of active value (positive),
+ * or its more-nearest one (negated).
+ */
+ if (current_idx < 0) {
+ current_idx = (current_idx * -1) + (inc < 0 ? inc : inc - 1);
+ }
+ else {
+ current_idx += inc;
+ }
+ CLAMP(current_idx, 0, dyn_data->items_shown - 1);
+ value = org_order[current_idx];
+ MEM_freeN(org_order);
+ }
+ else {
+ value += inc;
+ }
+
+ CLAMP(value, 0, dyn_data->items_len - 1);
+
+ RNA_property_int_range(&listbox->rnapoin, listbox->rnaprop, &min, &max);
+ CLAMP(value, min, max);
+
+ if (value != value_orig) {
+ RNA_property_int_set(&listbox->rnapoin, listbox->rnaprop, value);
+ RNA_property_update(C, &listbox->rnapoin, listbox->rnaprop);
+
+ ui_apply_but_undo(listbox);
+
+ ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
+ redraw = true;
+ }
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
+ /* We now have proper grip, but keep this anyway! */
+ if (ui_list->list_grip < (dyn_data->visual_height_min - UI_LIST_AUTO_SIZE_THRESHOLD)) {
+ ui_list->list_grip = dyn_data->visual_height;
+ }
+ ui_list->list_grip += (type == WHEELUPMOUSE) ? -1 : 1;
+
+ ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
+
+ redraw = true;
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
+ if (dyn_data->height > dyn_data->visual_height) {
+ /* list template will clamp */
+ ui_list->list_scroll += (type == WHEELUPMOUSE) ? -1 : 1;
+
+ redraw = true;
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
+ }
+
+ if (redraw) {
+ ED_region_tag_redraw(ar);
+ ED_region_tag_refresh_ui(ar);
+ }
+
+ return retval;
}
static void ui_handle_button_return_submenu(bContext *C, const wmEvent *event, uiBut *but)
{
- uiHandleButtonData *data;
- uiPopupBlockHandle *menu;
-
- data = but->active;
- menu = data->menu;
-
- /* copy over return values from the closing menu */
- if ((menu->menuretval & UI_RETURN_OK) || (menu->menuretval & UI_RETURN_UPDATE)) {
- if (but->type == UI_BTYPE_COLOR) {
- copy_v3_v3(data->vec, menu->retvec);
- }
- else if (but->type == UI_BTYPE_MENU) {
- data->value = menu->retvalue;
- }
- }
-
- if (menu->menuretval & UI_RETURN_UPDATE) {
- if (data->interactive) {
- ui_apply_but(C, but->block, but, data, true);
- }
- else {
- ui_but_update(but);
- }
-
- menu->menuretval = 0;
- }
-
- /* now change button state or exit, which will close the submenu */
- if ((menu->menuretval & UI_RETURN_OK) || (menu->menuretval & UI_RETURN_CANCEL)) {
- if (menu->menuretval != UI_RETURN_OK) {
- data->cancel = true;
- }
-
- button_activate_exit(C, but, data, true, false);
- }
- else if (menu->menuretval & UI_RETURN_OUT) {
- if (event->type == MOUSEMOVE && ui_but_contains_point_px(but, data->region, event->x, event->y)) {
- button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
- }
- else {
- if (ISKEYBOARD(event->type)) {
- /* keyboard menu hierarchy navigation, going back to previous level */
- but->active->used_mouse = false;
- button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
- }
- else {
- data->cancel = true;
- button_activate_exit(C, but, data, true, false);
- }
- }
- }
+ uiHandleButtonData *data;
+ uiPopupBlockHandle *menu;
+
+ data = but->active;
+ menu = data->menu;
+
+ /* copy over return values from the closing menu */
+ if ((menu->menuretval & UI_RETURN_OK) || (menu->menuretval & UI_RETURN_UPDATE)) {
+ if (but->type == UI_BTYPE_COLOR) {
+ copy_v3_v3(data->vec, menu->retvec);
+ }
+ else if (but->type == UI_BTYPE_MENU) {
+ data->value = menu->retvalue;
+ }
+ }
+
+ if (menu->menuretval & UI_RETURN_UPDATE) {
+ if (data->interactive) {
+ ui_apply_but(C, but->block, but, data, true);
+ }
+ else {
+ ui_but_update(but);
+ }
+
+ menu->menuretval = 0;
+ }
+
+ /* now change button state or exit, which will close the submenu */
+ if ((menu->menuretval & UI_RETURN_OK) || (menu->menuretval & UI_RETURN_CANCEL)) {
+ if (menu->menuretval != UI_RETURN_OK) {
+ data->cancel = true;
+ }
+
+ button_activate_exit(C, but, data, true, false);
+ }
+ else if (menu->menuretval & UI_RETURN_OUT) {
+ if (event->type == MOUSEMOVE &&
+ ui_but_contains_point_px(but, data->region, event->x, event->y)) {
+ button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
+ }
+ else {
+ if (ISKEYBOARD(event->type)) {
+ /* keyboard menu hierarchy navigation, going back to previous level */
+ but->active->used_mouse = false;
+ button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
+ }
+ else {
+ data->cancel = true;
+ button_activate_exit(C, but, data, true, false);
+ }
+ }
+ }
}
/** \} */
@@ -8446,124 +8468,122 @@ static void ui_handle_button_return_submenu(bContext *C, const wmEvent *event, u
* - only for 1 second.
*/
-static void ui_mouse_motion_towards_init_ex(uiPopupBlockHandle *menu, const int xy[2], const bool force)
+static void ui_mouse_motion_towards_init_ex(uiPopupBlockHandle *menu,
+ const int xy[2],
+ const bool force)
{
- BLI_assert(((uiBlock *)menu->region->uiblocks.first)->flag & (UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_POPOVER));
+ BLI_assert(((uiBlock *)menu->region->uiblocks.first)->flag &
+ (UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_POPOVER));
- if (!menu->dotowards || force) {
- menu->dotowards = true;
- menu->towards_xy[0] = xy[0];
- menu->towards_xy[1] = xy[1];
+ if (!menu->dotowards || force) {
+ menu->dotowards = true;
+ menu->towards_xy[0] = xy[0];
+ menu->towards_xy[1] = xy[1];
- if (force) {
- menu->towardstime = DBL_MAX; /* unlimited time */
- }
- else {
- menu->towardstime = PIL_check_seconds_timer();
- }
- }
+ if (force) {
+ menu->towardstime = DBL_MAX; /* unlimited time */
+ }
+ else {
+ menu->towardstime = PIL_check_seconds_timer();
+ }
+ }
}
static void ui_mouse_motion_towards_init(uiPopupBlockHandle *menu, const int xy[2])
{
- ui_mouse_motion_towards_init_ex(menu, xy, false);
+ ui_mouse_motion_towards_init_ex(menu, xy, false);
}
static void ui_mouse_motion_towards_reinit(uiPopupBlockHandle *menu, const int xy[2])
{
- ui_mouse_motion_towards_init_ex(menu, xy, true);
+ ui_mouse_motion_towards_init_ex(menu, xy, true);
}
-static bool ui_mouse_motion_towards_check(
- uiBlock *block, uiPopupBlockHandle *menu, const int xy[2],
- const bool use_wiggle_room)
+static bool ui_mouse_motion_towards_check(uiBlock *block,
+ uiPopupBlockHandle *menu,
+ const int xy[2],
+ const bool use_wiggle_room)
{
- float p1[2], p2[2], p3[2], p4[2];
- float oldp[2] = {menu->towards_xy[0], menu->towards_xy[1]};
- const float newp[2] = {xy[0], xy[1]};
- bool closer;
- const float margin = MENU_TOWARDS_MARGIN;
- rctf rect_px;
-
- BLI_assert(block->flag & (UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_POPOVER));
-
+ float p1[2], p2[2], p3[2], p4[2];
+ float oldp[2] = {menu->towards_xy[0], menu->towards_xy[1]};
+ const float newp[2] = {xy[0], xy[1]};
+ bool closer;
+ const float margin = MENU_TOWARDS_MARGIN;
+ rctf rect_px;
- /* annoying fix for [#36269], this is a bit odd but in fact works quite well
- * don't mouse-out of a menu if another menu has been created after it.
- * 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;
- do {
- uiBlock *block_iter = ar->uiblocks.first;
- if (block_iter && ui_block_is_menu(block_iter)) {
- return true;
- }
- } while ((ar = ar->next));
- }
- /* annoying fix end! */
+ BLI_assert(block->flag & (UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_POPOVER));
+ /* annoying fix for [#36269], this is a bit odd but in fact works quite well
+ * don't mouse-out of a menu if another menu has been created after it.
+ * 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;
+ do {
+ uiBlock *block_iter = ar->uiblocks.first;
+ if (block_iter && ui_block_is_menu(block_iter)) {
+ return true;
+ }
+ } while ((ar = ar->next));
+ }
+ /* annoying fix end! */
- if (!menu->dotowards) {
- return false;
- }
+ if (!menu->dotowards) {
+ return false;
+ }
- if (len_squared_v2v2(oldp, newp) < (4.0f * 4.0f)) {
- return menu->dotowards;
- }
+ if (len_squared_v2v2(oldp, newp) < (4.0f * 4.0f)) {
+ return menu->dotowards;
+ }
- /* verify that we are moving towards one of the edges of the
- * menu block, in other words, in the triangle formed by the
- * initial mouse location and two edge points. */
- ui_block_to_window_rctf(menu->region, block, &rect_px, &block->rect);
+ /* verify that we are moving towards one of the edges of the
+ * menu block, in other words, in the triangle formed by the
+ * initial mouse location and two edge points. */
+ ui_block_to_window_rctf(menu->region, block, &rect_px, &block->rect);
- p1[0] = rect_px.xmin - margin;
- p1[1] = rect_px.ymin - margin;
+ p1[0] = rect_px.xmin - margin;
+ p1[1] = rect_px.ymin - margin;
- p2[0] = rect_px.xmax + margin;
- p2[1] = rect_px.ymin - margin;
+ p2[0] = rect_px.xmax + margin;
+ p2[1] = rect_px.ymin - margin;
- p3[0] = rect_px.xmax + margin;
- p3[1] = rect_px.ymax + margin;
+ p3[0] = rect_px.xmax + margin;
+ p3[1] = rect_px.ymax + margin;
- p4[0] = rect_px.xmin - margin;
- p4[1] = rect_px.ymax + margin;
+ p4[0] = rect_px.xmin - margin;
+ p4[1] = rect_px.ymax + margin;
- /* allow for some wiggle room, if the user moves a few pixels away,
- * don't immediately quit (only for top level menus) */
- if (use_wiggle_room) {
- const float cent[2] = {
- BLI_rctf_cent_x(&rect_px),
- BLI_rctf_cent_y(&rect_px)};
- float delta[2];
+ /* allow for some wiggle room, if the user moves a few pixels away,
+ * don't immediately quit (only for top level menus) */
+ if (use_wiggle_room) {
+ const float cent[2] = {BLI_rctf_cent_x(&rect_px), BLI_rctf_cent_y(&rect_px)};
+ float delta[2];
- sub_v2_v2v2(delta, oldp, cent);
- normalize_v2_length(delta, MENU_TOWARDS_WIGGLE_ROOM);
- add_v2_v2(oldp, delta);
- }
+ sub_v2_v2v2(delta, oldp, cent);
+ normalize_v2_length(delta, MENU_TOWARDS_WIGGLE_ROOM);
+ add_v2_v2(oldp, delta);
+ }
- closer = (isect_point_tri_v2(newp, oldp, p1, p2) ||
- isect_point_tri_v2(newp, oldp, p2, p3) ||
- isect_point_tri_v2(newp, oldp, p3, p4) ||
- isect_point_tri_v2(newp, oldp, p4, p1));
+ closer = (isect_point_tri_v2(newp, oldp, p1, p2) || isect_point_tri_v2(newp, oldp, p2, p3) ||
+ isect_point_tri_v2(newp, oldp, p3, p4) || isect_point_tri_v2(newp, oldp, p4, p1));
- if (!closer) {
- menu->dotowards = false;
- }
+ if (!closer) {
+ menu->dotowards = false;
+ }
- /* 1 second timer */
- if (PIL_check_seconds_timer() - menu->towardstime > BUTTON_MOUSE_TOWARDS_THRESH) {
- menu->dotowards = false;
- }
+ /* 1 second timer */
+ if (PIL_check_seconds_timer() - menu->towardstime > BUTTON_MOUSE_TOWARDS_THRESH) {
+ menu->dotowards = false;
+ }
- return menu->dotowards;
+ return menu->dotowards;
}
#ifdef USE_KEYNAV_LIMIT
static void ui_mouse_motion_keynav_init(struct uiKeyNavLock *keynav, const wmEvent *event)
{
- keynav->is_keynav = true;
- copy_v2_v2_int(keynav->event_xy, &event->x);
+ keynav->is_keynav = true;
+ copy_v2_v2_int(keynav->event_xy, &event->x);
}
/**
* Return true if keyinput isn't blocking mouse-motion,
@@ -8571,13 +8591,14 @@ static void ui_mouse_motion_keynav_init(struct uiKeyNavLock *keynav, const wmEve
*/
static bool ui_mouse_motion_keynav_test(struct uiKeyNavLock *keynav, const wmEvent *event)
{
- if (keynav->is_keynav && (len_manhattan_v2v2_int(keynav->event_xy, &event->x) > BUTTON_KEYNAV_PX_LIMIT)) {
- keynav->is_keynav = false;
- }
+ if (keynav->is_keynav &&
+ (len_manhattan_v2v2_int(keynav->event_xy, &event->x) > BUTTON_KEYNAV_PX_LIMIT)) {
+ keynav->is_keynav = false;
+ }
- return keynav->is_keynav;
+ return keynav->is_keynav;
}
-#endif /* USE_KEYNAV_LIMIT */
+#endif /* USE_KEYNAV_LIMIT */
/** \} */
@@ -8587,120 +8608,120 @@ static bool ui_mouse_motion_keynav_test(struct uiKeyNavLock *keynav, const wmEve
static char ui_menu_scroll_test(uiBlock *block, int my)
{
- if (block->flag & (UI_BLOCK_CLIPTOP | UI_BLOCK_CLIPBOTTOM)) {
- if (block->flag & UI_BLOCK_CLIPTOP) {
- if (my > block->rect.ymax - UI_MENU_SCROLL_MOUSE) {
- return 't';
- }
- }
- if (block->flag & UI_BLOCK_CLIPBOTTOM) {
- if (my < block->rect.ymin + UI_MENU_SCROLL_MOUSE) {
- return 'b';
- }
- }
- }
- return 0;
+ if (block->flag & (UI_BLOCK_CLIPTOP | UI_BLOCK_CLIPBOTTOM)) {
+ if (block->flag & UI_BLOCK_CLIPTOP) {
+ if (my > block->rect.ymax - UI_MENU_SCROLL_MOUSE) {
+ return 't';
+ }
+ }
+ if (block->flag & UI_BLOCK_CLIPBOTTOM) {
+ if (my < block->rect.ymin + UI_MENU_SCROLL_MOUSE) {
+ return 'b';
+ }
+ }
+ }
+ return 0;
}
static void ui_menu_scroll_apply_offset_y(ARegion *ar, 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 (ymin + dy + UI_UNIT_Y * 0.5f > block->rect.ymin + UI_MENU_SCROLL_PAD) {
- dy = block->rect.ymin - ymin + UI_MENU_SCROLL_PAD;
- }
- }
-
- /* remember scroll offset for refreshes */
- block->handle->scrolloffset += dy;
-
- /* apply scroll offset */
- for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
- bt->rect.ymin += dy;
- bt->rect.ymax += dy;
- }
-
- /* set flags again */
- ui_popup_block_scrolltest(block);
-
- ED_region_tag_redraw(ar);
+ 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 (ymin + dy + UI_UNIT_Y * 0.5f > block->rect.ymin + UI_MENU_SCROLL_PAD) {
+ dy = block->rect.ymin - ymin + UI_MENU_SCROLL_PAD;
+ }
+ }
+
+ /* remember scroll offset for refreshes */
+ block->handle->scrolloffset += dy;
+
+ /* apply scroll offset */
+ for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
+ bt->rect.ymin += dy;
+ bt->rect.ymax += dy;
+ }
+
+ /* set flags again */
+ ui_popup_block_scrolltest(block);
+
+ ED_region_tag_redraw(ar);
}
/** Scroll to activated button. */
static bool ui_menu_scroll_to_but(ARegion *ar, uiBlock *block, uiBut *but_target)
{
- float dy = 0.0;
- if (block->flag & UI_BLOCK_CLIPTOP) {
- if (but_target->rect.ymax > block->rect.ymax - UI_MENU_SCROLL_ARROW) {
- dy = block->rect.ymax - but_target->rect.ymax - UI_MENU_SCROLL_ARROW;
- }
- }
- if (block->flag & UI_BLOCK_CLIPBOTTOM) {
- if (but_target->rect.ymin < block->rect.ymin + UI_MENU_SCROLL_ARROW) {
- dy = block->rect.ymin - but_target->rect.ymin + UI_MENU_SCROLL_ARROW;
- }
- }
- if (dy != 0.0f) {
- ui_menu_scroll_apply_offset_y(ar, block, dy);
- return true;
- }
- return false;
+ float dy = 0.0;
+ if (block->flag & UI_BLOCK_CLIPTOP) {
+ if (but_target->rect.ymax > block->rect.ymax - UI_MENU_SCROLL_ARROW) {
+ dy = block->rect.ymax - but_target->rect.ymax - UI_MENU_SCROLL_ARROW;
+ }
+ }
+ if (block->flag & UI_BLOCK_CLIPBOTTOM) {
+ if (but_target->rect.ymin < block->rect.ymin + UI_MENU_SCROLL_ARROW) {
+ dy = block->rect.ymin - but_target->rect.ymin + UI_MENU_SCROLL_ARROW;
+ }
+ }
+ if (dy != 0.0f) {
+ ui_menu_scroll_apply_offset_y(ar, 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)
{
- const char test = ui_menu_scroll_test(block, y);
- float dy = 0.0f;
- if (test == 't') {
- dy = -UI_UNIT_Y; /* scroll to the top */
- }
- else if (test == 'b') {
- dy = UI_UNIT_Y; /* scroll to the bottom */
- }
- if (dy != 0.0f) {
- ui_menu_scroll_apply_offset_y(ar, block, dy);
- return true;
- }
- return false;
+ const char test = ui_menu_scroll_test(block, y);
+ float dy = 0.0f;
+ if (test == 't') {
+ dy = -UI_UNIT_Y; /* scroll to the top */
+ }
+ else if (test == 'b') {
+ dy = UI_UNIT_Y; /* scroll to the bottom */
+ }
+ if (dy != 0.0f) {
+ ui_menu_scroll_apply_offset_y(ar, block, dy);
+ return true;
+ }
+ return false;
}
static bool ui_menu_scroll_step(ARegion *ar, uiBlock *block, const int scroll_dir)
{
- int my;
- if (scroll_dir == 1) {
- if ((block->flag & UI_BLOCK_CLIPTOP) == 0) {
- return false;
- }
- my = block->rect.ymax + UI_UNIT_Y;
- }
- else if (scroll_dir == -1) {
- if ((block->flag & UI_BLOCK_CLIPBOTTOM) == 0) {
- return false;
- }
- my = block->rect.ymin - UI_UNIT_Y;
- }
- else {
- BLI_assert(0);
- return false;
- }
-
- return ui_menu_scroll_to_y(ar, block, my);
+ int my;
+ if (scroll_dir == 1) {
+ if ((block->flag & UI_BLOCK_CLIPTOP) == 0) {
+ return false;
+ }
+ my = block->rect.ymax + UI_UNIT_Y;
+ }
+ else if (scroll_dir == -1) {
+ if ((block->flag & UI_BLOCK_CLIPBOTTOM) == 0) {
+ return false;
+ }
+ my = block->rect.ymin - UI_UNIT_Y;
+ }
+ else {
+ BLI_assert(0);
+ return false;
+ }
+
+ return ui_menu_scroll_to_y(ar, block, my);
}
/** \} */
@@ -8718,1144 +8739,1169 @@ static bool ui_menu_scroll_step(ARegion *ar, uiBlock *block, const int scroll_di
*
* Without this keyboard navigation from menu's wont work.
*/
-static bool ui_menu_pass_event_to_parent_if_nonactive(
- uiPopupBlockHandle *menu, const uiBut *but,
- const int level, const int retval)
-{
- if ((level != 0) && (but == NULL)) {
- menu->menuretval = UI_RETURN_OUT | UI_RETURN_OUT_PARENT;
- (void) retval; /* so release builds with strict flags are happy as well */
- BLI_assert(retval == WM_UI_HANDLER_CONTINUE);
- return true;
- }
- else {
- return false;
- }
+static bool ui_menu_pass_event_to_parent_if_nonactive(uiPopupBlockHandle *menu,
+ const uiBut *but,
+ const int level,
+ const int retval)
+{
+ if ((level != 0) && (but == NULL)) {
+ menu->menuretval = UI_RETURN_OUT | UI_RETURN_OUT_PARENT;
+ (void)retval; /* so release builds with strict flags are happy as well */
+ BLI_assert(retval == WM_UI_HANDLER_CONTINUE);
+ return true;
+ }
+ else {
+ return false;
+ }
}
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);
- int retval;
-
- if (but) {
- /* Its possible there is an active menu item NOT under the mouse,
- * in this case ignore mouse clicks outside the button (but Enter etc is accepted) */
- if (event->val == KM_RELEASE) {
- /* pass, needed so we can exit active menu-items when click-dragging out of them */
- }
- else if (!ui_block_is_menu(but->block) || ui_block_is_pie_menu(but->block)) {
- /* pass, skip for dialogs */
- }
- else if (!ui_region_contains_point_px(but->active->region, event->x, event->y)) {
- /* pass, needed to click-exit outside of non-flaoting menus */
- }
- else if ((!ELEM(event->type, MOUSEMOVE, WHEELUPMOUSE, WHEELDOWNMOUSE, MOUSEPAN)) && ISMOUSE(event->type)) {
- if (!ui_but_contains_point_px(but, but->active->region, event->x, event->y)) {
- but = NULL;
- }
- }
- }
-
- if (but) {
- ScrArea *ctx_area = CTX_wm_area(C);
- ARegion *ctx_region = CTX_wm_region(C);
-
- if (menu->ctx_area) {
- CTX_wm_area_set(C, menu->ctx_area);
- }
- if (menu->ctx_region) {
- CTX_wm_region_set(C, menu->ctx_region);
- }
-
- retval = ui_handle_button_event(C, event, but);
-
- if (menu->ctx_area) {
- CTX_wm_area_set(C, ctx_area);
- }
- if (menu->ctx_region) {
- CTX_wm_region_set(C, ctx_region);
- }
- }
- else {
- retval = ui_handle_button_over(C, event, ar);
- }
-
- return retval;
+ ARegion *ar = menu->region;
+ uiBut *but = ui_region_find_active_but(ar);
+ int retval;
+
+ if (but) {
+ /* Its possible there is an active menu item NOT under the mouse,
+ * in this case ignore mouse clicks outside the button (but Enter etc is accepted) */
+ if (event->val == KM_RELEASE) {
+ /* pass, needed so we can exit active menu-items when click-dragging out of them */
+ }
+ else if (!ui_block_is_menu(but->block) || ui_block_is_pie_menu(but->block)) {
+ /* pass, skip for dialogs */
+ }
+ else if (!ui_region_contains_point_px(but->active->region, event->x, event->y)) {
+ /* pass, needed to click-exit outside of non-flaoting menus */
+ }
+ else if ((!ELEM(event->type, MOUSEMOVE, WHEELUPMOUSE, WHEELDOWNMOUSE, MOUSEPAN)) &&
+ ISMOUSE(event->type)) {
+ if (!ui_but_contains_point_px(but, but->active->region, event->x, event->y)) {
+ but = NULL;
+ }
+ }
+ }
+
+ if (but) {
+ ScrArea *ctx_area = CTX_wm_area(C);
+ ARegion *ctx_region = CTX_wm_region(C);
+
+ if (menu->ctx_area) {
+ CTX_wm_area_set(C, menu->ctx_area);
+ }
+ if (menu->ctx_region) {
+ CTX_wm_region_set(C, menu->ctx_region);
+ }
+
+ retval = ui_handle_button_event(C, event, but);
+
+ if (menu->ctx_area) {
+ CTX_wm_area_set(C, ctx_area);
+ }
+ if (menu->ctx_region) {
+ CTX_wm_region_set(C, ctx_region);
+ }
+ }
+ else {
+ retval = ui_handle_button_over(C, event, ar);
+ }
+
+ return retval;
}
float ui_block_calc_pie_segment(uiBlock *block, const float event_xy[2])
{
- float seg1[2];
- float seg2[2];
- float len;
+ float seg1[2];
+ float seg2[2];
+ float len;
- if (block->pie_data.flags & UI_PIE_INITIAL_DIRECTION) {
- copy_v2_v2(seg1, block->pie_data.pie_center_init);
- }
- else {
- copy_v2_v2(seg1, block->pie_data.pie_center_spawned);
- }
+ if (block->pie_data.flags & UI_PIE_INITIAL_DIRECTION) {
+ copy_v2_v2(seg1, block->pie_data.pie_center_init);
+ }
+ else {
+ copy_v2_v2(seg1, block->pie_data.pie_center_spawned);
+ }
- sub_v2_v2v2(seg2, event_xy, seg1);
+ sub_v2_v2v2(seg2, event_xy, seg1);
- len = normalize_v2_v2(block->pie_data.pie_dir, seg2);
+ len = normalize_v2_v2(block->pie_data.pie_dir, seg2);
- if (len < U.pie_menu_threshold * U.dpi_fac) {
- block->pie_data.flags |= UI_PIE_INVALID_DIR;
- }
- else {
- block->pie_data.flags &= ~UI_PIE_INVALID_DIR;
- }
+ if (len < U.pie_menu_threshold * U.dpi_fac) {
+ block->pie_data.flags |= UI_PIE_INVALID_DIR;
+ }
+ else {
+ block->pie_data.flags &= ~UI_PIE_INVALID_DIR;
+ }
- return len;
+ return len;
}
-static int ui_handle_menu_event(
- bContext *C, const wmEvent *event, uiPopupBlockHandle *menu,
- int level, const bool is_parent_inside, const bool is_parent_menu, const bool is_floating)
+static int ui_handle_menu_event(bContext *C,
+ const wmEvent *event,
+ uiPopupBlockHandle *menu,
+ int level,
+ const bool is_parent_inside,
+ const bool is_parent_menu,
+ const bool is_floating)
{
- ARegion *ar;
- uiBlock *block;
- uiBut *but;
- int mx, my, retval;
- bool inside;
- bool inside_title; /* check for title dragging */
+ ARegion *ar;
+ uiBlock *block;
+ uiBut *but;
+ int mx, my, retval;
+ bool inside;
+ bool inside_title; /* check for title dragging */
- ar = menu->region;
- block = ar->uiblocks.first;
+ ar = menu->region;
+ block = ar->uiblocks.first;
- retval = WM_UI_HANDLER_CONTINUE;
+ retval = WM_UI_HANDLER_CONTINUE;
- mx = event->x;
- my = event->y;
- ui_window_to_block(ar, block, &mx, &my);
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(ar, 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);
+ /* 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);
+ /* if there's an active modal button, don't check events or outside, except for search menu */
+ but = ui_region_find_active_but(ar);
#ifdef USE_DRAG_POPUP
- if (menu->is_grab) {
- if (event->type == LEFTMOUSE) {
- menu->is_grab = false;
- retval = WM_UI_HANDLER_BREAK;
- }
- else {
- if (event->type == MOUSEMOVE) {
- int mdiff[2];
-
- sub_v2_v2v2_int(mdiff, &event->x, menu->grab_xy_prev);
- copy_v2_v2_int(menu->grab_xy_prev, &event->x);
-
- add_v2_v2v2_int(menu->popup_create_vars.event_xy, menu->popup_create_vars.event_xy, mdiff);
-
- ui_popup_translate(ar, mdiff);
- }
-
- return retval;
- }
- }
+ if (menu->is_grab) {
+ if (event->type == LEFTMOUSE) {
+ menu->is_grab = false;
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else {
+ if (event->type == MOUSEMOVE) {
+ int mdiff[2];
+
+ sub_v2_v2v2_int(mdiff, &event->x, menu->grab_xy_prev);
+ copy_v2_v2_int(menu->grab_xy_prev, &event->x);
+
+ add_v2_v2v2_int(menu->popup_create_vars.event_xy, menu->popup_create_vars.event_xy, mdiff);
+
+ ui_popup_translate(ar, mdiff);
+ }
+
+ return retval;
+ }
+ }
#endif
- if (but && button_modal_state(but->active->state)) {
- if (block->flag & (UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_POPOVER)) {
- /* if a button is activated modal, always reset the start mouse
- * position of the towards mechanism to avoid losing focus,
- * and don't handle events */
- ui_mouse_motion_towards_reinit(menu, &event->x);
- }
- }
- else if (event->type == TIMER) {
- if (event->customdata == menu->scrolltimer) {
- ui_menu_scroll_to_y(ar, block, my);
- }
- }
- else {
- /* for ui_mouse_motion_towards_block */
- if (event->type == MOUSEMOVE) {
- if (block->flag & (UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_POPOVER)) {
- ui_mouse_motion_towards_init(menu, &event->x);
- }
-
- /* add menu scroll timer, if needed */
- if (ui_menu_scroll_test(block, my)) {
- if (menu->scrolltimer == NULL) {
- menu->scrolltimer =
- WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, MENU_SCROLL_INTERVAL);
- }
- }
- }
-
- /* first block own event func */
- if (block->block_event_func && block->block_event_func(C, block, event)) {
- /* pass */
- } /* events not for active search menu button */
- else {
- int act = 0;
-
- switch (event->type) {
-
- /* 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. */
- case RIGHTMOUSE:
- if (inside == false) {
- if (event->val == KM_PRESS && (block->flag & UI_BLOCK_LOOP)) {
- if (block->saferct.first) {
- /* Currently right clicking on a top level pull-down (typically in the header)
- * just closes the menu and doesn't support immediately handling the RMB event.
- *
- * To support we would need UI_RETURN_OUT_PARENT to be handled by
- * top-level buttons, not just menus. Note that this isn't very important
- * since it's easy to manually close these menus by clicking on them. */
- menu->menuretval = (level > 0) ? UI_RETURN_OUT_PARENT : UI_RETURN_OUT;
-
- }
- }
- retval = WM_UI_HANDLER_BREAK;
- }
- break;
-
- /* Closing sub-levels of pull-downs. */
- case LEFTARROWKEY:
- if (event->val == KM_PRESS && (block->flag & UI_BLOCK_LOOP)) {
- if (block->saferct.first) {
- menu->menuretval = UI_RETURN_OUT;
- }
- }
-
- retval = WM_UI_HANDLER_BREAK;
- break;
-
- /* Opening sub-levels of pull-downs. */
- case 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);
-
- if (!but) {
- /* no item active, we make first active */
- if (block->direction & UI_DIR_UP) {
- but = ui_but_last(block);
- }
- else {
- but = ui_but_first(block);
- }
- }
-
- if (but && ELEM(but->type, UI_BTYPE_BLOCK, UI_BTYPE_PULLDOWN)) {
- ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_OPEN);
- }
- }
-
- retval = WM_UI_HANDLER_BREAK;
- break;
-
- case WHEELUPMOUSE:
- case WHEELDOWNMOUSE:
- {
- if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) {
- /* pass */
- }
- else if (!ui_block_is_menu(block)) {
- const int scroll_dir = (event->type == WHEELUPMOUSE) ? 1 : -1;
- if (ui_menu_scroll_step(ar, block, scroll_dir)) {
- if (but) {
- but->active->cancel = true;
- button_activate_exit(C, but, but->active, false, false);
- }
- WM_event_add_mousemove(C);
- }
- break;
- }
- ATTR_FALLTHROUGH;
- }
- case UPARROWKEY:
- case DOWNARROWKEY:
- case MOUSEPAN:
- /* arrowkeys: only handle for block_loop blocks */
- if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) {
- /* pass */
- }
- else if (inside || (block->flag & UI_BLOCK_LOOP)) {
- int type = event->type;
- int val = event->val;
-
- /* convert pan to scrollwheel */
- if (type == MOUSEPAN) {
- ui_pan_to_scroll(event, &type, &val);
- }
-
- if (val == KM_PRESS) {
- const bool is_next =
- (ELEM(type, DOWNARROWKEY, WHEELDOWNMOUSE) ==
- ((block->flag & UI_BLOCK_IS_FLIP) != 0));
-
- if (ui_menu_pass_event_to_parent_if_nonactive(menu, but, level, retval)) {
- break;
- }
+ if (but && button_modal_state(but->active->state)) {
+ if (block->flag & (UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_POPOVER)) {
+ /* if a button is activated modal, always reset the start mouse
+ * position of the towards mechanism to avoid losing focus,
+ * and don't handle events */
+ ui_mouse_motion_towards_reinit(menu, &event->x);
+ }
+ }
+ else if (event->type == TIMER) {
+ if (event->customdata == menu->scrolltimer) {
+ ui_menu_scroll_to_y(ar, block, my);
+ }
+ }
+ else {
+ /* for ui_mouse_motion_towards_block */
+ if (event->type == MOUSEMOVE) {
+ if (block->flag & (UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_POPOVER)) {
+ ui_mouse_motion_towards_init(menu, &event->x);
+ }
+
+ /* add menu scroll timer, if needed */
+ if (ui_menu_scroll_test(block, my)) {
+ if (menu->scrolltimer == NULL) {
+ menu->scrolltimer = WM_event_add_timer(
+ CTX_wm_manager(C), CTX_wm_window(C), TIMER, MENU_SCROLL_INTERVAL);
+ }
+ }
+ }
+
+ /* first block own event func */
+ if (block->block_event_func && block->block_event_func(C, block, event)) {
+ /* pass */
+ } /* events not for active search menu button */
+ else {
+ int act = 0;
+
+ switch (event->type) {
+
+ /* 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. */
+ case RIGHTMOUSE:
+ if (inside == false) {
+ if (event->val == KM_PRESS && (block->flag & UI_BLOCK_LOOP)) {
+ if (block->saferct.first) {
+ /* Currently right clicking on a top level pull-down (typically in the header)
+ * just closes the menu and doesn't support immediately handling the RMB event.
+ *
+ * To support we would need UI_RETURN_OUT_PARENT to be handled by
+ * top-level buttons, not just menus. Note that this isn't very important
+ * since it's easy to manually close these menus by clicking on them. */
+ menu->menuretval = (level > 0) ? UI_RETURN_OUT_PARENT : UI_RETURN_OUT;
+ }
+ }
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ break;
+
+ /* Closing sub-levels of pull-downs. */
+ case LEFTARROWKEY:
+ if (event->val == KM_PRESS && (block->flag & UI_BLOCK_LOOP)) {
+ if (block->saferct.first) {
+ menu->menuretval = UI_RETURN_OUT;
+ }
+ }
+
+ retval = WM_UI_HANDLER_BREAK;
+ break;
+
+ /* Opening sub-levels of pull-downs. */
+ case 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);
+
+ if (!but) {
+ /* no item active, we make first active */
+ if (block->direction & UI_DIR_UP) {
+ but = ui_but_last(block);
+ }
+ else {
+ but = ui_but_first(block);
+ }
+ }
+
+ if (but && ELEM(but->type, UI_BTYPE_BLOCK, UI_BTYPE_PULLDOWN)) {
+ ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_OPEN);
+ }
+ }
+
+ retval = WM_UI_HANDLER_BREAK;
+ break;
+
+ case WHEELUPMOUSE:
+ case WHEELDOWNMOUSE: {
+ if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) {
+ /* pass */
+ }
+ else if (!ui_block_is_menu(block)) {
+ const int scroll_dir = (event->type == WHEELUPMOUSE) ? 1 : -1;
+ if (ui_menu_scroll_step(ar, block, scroll_dir)) {
+ if (but) {
+ but->active->cancel = true;
+ button_activate_exit(C, but, but->active, false, false);
+ }
+ WM_event_add_mousemove(C);
+ }
+ break;
+ }
+ ATTR_FALLTHROUGH;
+ }
+ case UPARROWKEY:
+ case DOWNARROWKEY:
+ case MOUSEPAN:
+ /* arrowkeys: only handle for block_loop blocks */
+ if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) {
+ /* pass */
+ }
+ else if (inside || (block->flag & UI_BLOCK_LOOP)) {
+ int type = event->type;
+ int val = event->val;
+
+ /* convert pan to scrollwheel */
+ if (type == MOUSEPAN) {
+ ui_pan_to_scroll(event, &type, &val);
+ }
+
+ if (val == KM_PRESS) {
+ const bool is_next = (ELEM(type, DOWNARROWKEY, WHEELDOWNMOUSE) ==
+ ((block->flag & UI_BLOCK_IS_FLIP) != 0));
+
+ if (ui_menu_pass_event_to_parent_if_nonactive(menu, but, level, retval)) {
+ break;
+ }
#ifdef USE_KEYNAV_LIMIT
- ui_mouse_motion_keynav_init(&menu->keynav_state, event);
+ ui_mouse_motion_keynav_init(&menu->keynav_state, event);
#endif
- but = ui_region_find_active_but(ar);
- if (but) {
- /* next button */
- but = is_next ? ui_but_next(but) : ui_but_prev(but);
- }
-
- if (!but) {
- /* wrap button */
- uiBut *but_wrap;
- but_wrap = is_next ? ui_but_first(block) : ui_but_last(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);
- }
- }
-
- retval = WM_UI_HANDLER_BREAK;
- }
-
- break;
-
- case ONEKEY: case PAD1:
- act = 1;
- ATTR_FALLTHROUGH;
- case TWOKEY: case PAD2:
- if (act == 0) {
- act = 2;
- }
- ATTR_FALLTHROUGH;
- case THREEKEY: case PAD3:
- if (act == 0) {
- act = 3;
- }
- ATTR_FALLTHROUGH;
- case FOURKEY: case PAD4:
- if (act == 0) {
- act = 4;
- }
- ATTR_FALLTHROUGH;
- case FIVEKEY: case PAD5:
- if (act == 0) {
- act = 5;
- }
- ATTR_FALLTHROUGH;
- case SIXKEY: case PAD6:
- if (act == 0) {
- act = 6;
- }
- ATTR_FALLTHROUGH;
- case SEVENKEY: case PAD7:
- if (act == 0) {
- act = 7;
- }
- ATTR_FALLTHROUGH;
- case EIGHTKEY: case PAD8:
- if (act == 0) {
- act = 8;
- }
- ATTR_FALLTHROUGH;
- case NINEKEY: case PAD9:
- if (act == 0) {
- act = 9;
- }
- ATTR_FALLTHROUGH;
- case ZEROKEY: case PAD0:
- if (act == 0) {
- act = 10;
- }
-
- if ((block->flag & UI_BLOCK_NUMSELECT) && event->val == KM_PRESS) {
- int count;
-
- if (ui_menu_pass_event_to_parent_if_nonactive(menu, but, level, retval)) {
- break;
- }
-
- if (event->alt) {
- act += 10;
- }
-
- count = 0;
- 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)) {
- count++;
- }
-
- /* exception for rna layer buts */
- if (but->rnapoin.data && but->rnaprop &&
- ELEM(RNA_property_subtype(but->rnaprop), PROP_LAYER, PROP_LAYER_MEMBER))
- {
- if (but->rnaindex == act - 1) {
- doit = true;
- }
- }
- else if (ELEM(but->type,
- UI_BTYPE_BUT,
- UI_BTYPE_BUT_MENU,
- UI_BTYPE_MENU, UI_BTYPE_BLOCK,
- UI_BTYPE_PULLDOWN) &&
- count == act)
- {
- doit = true;
- }
-
- if (!(but->flag & UI_BUT_DISABLED) && doit) {
- /* activate buttons but open menu's */
- uiButtonActivateType activate;
- if (but->type == UI_BTYPE_PULLDOWN) {
- activate = BUTTON_ACTIVATE_OPEN;
- }
- else {
- activate = BUTTON_ACTIVATE_APPLY;
- }
-
- ui_handle_button_activate(C, ar, but, activate);
- break;
- }
- }
-
- retval = WM_UI_HANDLER_BREAK;
- }
- 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:
- {
- 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)) {
- break;
- }
-
- for (but = block->buttons.first; but; but = but->next) {
- if (!(but->flag & UI_BUT_DISABLED) && but->menu_key == event->type) {
- if (but->type == UI_BTYPE_BUT) {
- UI_but_execute(C, but);
- }
- else {
- ui_handle_button_activate_by_type(C, ar, but);
- }
- break;
- }
- }
-
- retval = WM_UI_HANDLER_BREAK;
- }
- break;
- }
- }
- }
-
- /* here we check return conditions for menus */
- if (block->flag & UI_BLOCK_LOOP) {
- /* If we click outside the block, verify if we clicked on the
- * button that opened us, otherwise we need to close,
- *
- * note that there is an exception for root level menus and
- * popups which you can click again to close.
- *
- * Events handled above may have already set the return value,
- * don't overwrite them, see: T61015.
- */
- if ((inside == 0) && (menu->menuretval == 0)) {
- uiSafetyRct *saferct = block->saferct.first;
-
- if (ELEM(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE)) {
- if (ELEM(event->val, KM_PRESS, KM_DBL_CLICK)) {
- if ((is_parent_menu == false) && (U.uiflag & USER_MENUOPENAUTO) == 0) {
- /* for root menus, allow clicking to close */
- if (block->flag & (UI_BLOCK_OUT_1)) {
- menu->menuretval = UI_RETURN_OK;
- }
- else {
- menu->menuretval = UI_RETURN_OUT;
- }
- }
- else if (saferct && !BLI_rctf_isect_pt(&saferct->parent, event->x, event->y)) {
- if (block->flag & (UI_BLOCK_OUT_1)) {
- menu->menuretval = UI_RETURN_OK;
- }
- else {
- menu->menuretval = UI_RETURN_OUT;
- }
- }
- }
- else if (ELEM(event->val, KM_RELEASE, KM_CLICK)) {
- /* For buttons that use a hold function,
- * exit when mouse-up outside the menu. */
- if (block->flag & UI_BLOCK_POPUP_HOLD) {
- /* Note, we could check the cursor is over the parent button. */
- menu->menuretval = UI_RETURN_CANCEL;
- retval = WM_UI_HANDLER_CONTINUE;
- }
- }
- }
- }
-
- if (menu->menuretval) {
- /* pass */
- }
+ but = ui_region_find_active_but(ar);
+ if (but) {
+ /* next button */
+ but = is_next ? ui_but_next(but) : ui_but_prev(but);
+ }
+
+ if (!but) {
+ /* wrap button */
+ uiBut *but_wrap;
+ but_wrap = is_next ? ui_but_first(block) : ui_but_last(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);
+ }
+ }
+
+ retval = WM_UI_HANDLER_BREAK;
+ }
+
+ break;
+
+ case ONEKEY:
+ case PAD1:
+ act = 1;
+ ATTR_FALLTHROUGH;
+ case TWOKEY:
+ case PAD2:
+ if (act == 0) {
+ act = 2;
+ }
+ ATTR_FALLTHROUGH;
+ case THREEKEY:
+ case PAD3:
+ if (act == 0) {
+ act = 3;
+ }
+ ATTR_FALLTHROUGH;
+ case FOURKEY:
+ case PAD4:
+ if (act == 0) {
+ act = 4;
+ }
+ ATTR_FALLTHROUGH;
+ case FIVEKEY:
+ case PAD5:
+ if (act == 0) {
+ act = 5;
+ }
+ ATTR_FALLTHROUGH;
+ case SIXKEY:
+ case PAD6:
+ if (act == 0) {
+ act = 6;
+ }
+ ATTR_FALLTHROUGH;
+ case SEVENKEY:
+ case PAD7:
+ if (act == 0) {
+ act = 7;
+ }
+ ATTR_FALLTHROUGH;
+ case EIGHTKEY:
+ case PAD8:
+ if (act == 0) {
+ act = 8;
+ }
+ ATTR_FALLTHROUGH;
+ case NINEKEY:
+ case PAD9:
+ if (act == 0) {
+ act = 9;
+ }
+ ATTR_FALLTHROUGH;
+ case ZEROKEY:
+ case PAD0:
+ if (act == 0) {
+ act = 10;
+ }
+
+ if ((block->flag & UI_BLOCK_NUMSELECT) && event->val == KM_PRESS) {
+ int count;
+
+ if (ui_menu_pass_event_to_parent_if_nonactive(menu, but, level, retval)) {
+ break;
+ }
+
+ if (event->alt) {
+ act += 10;
+ }
+
+ count = 0;
+ 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)) {
+ count++;
+ }
+
+ /* exception for rna layer buts */
+ if (but->rnapoin.data && but->rnaprop &&
+ ELEM(RNA_property_subtype(but->rnaprop), PROP_LAYER, PROP_LAYER_MEMBER)) {
+ if (but->rnaindex == act - 1) {
+ doit = true;
+ }
+ }
+ else if (ELEM(but->type,
+ UI_BTYPE_BUT,
+ UI_BTYPE_BUT_MENU,
+ UI_BTYPE_MENU,
+ UI_BTYPE_BLOCK,
+ UI_BTYPE_PULLDOWN) &&
+ count == act) {
+ doit = true;
+ }
+
+ if (!(but->flag & UI_BUT_DISABLED) && doit) {
+ /* activate buttons but open menu's */
+ uiButtonActivateType activate;
+ if (but->type == UI_BTYPE_PULLDOWN) {
+ activate = BUTTON_ACTIVATE_OPEN;
+ }
+ else {
+ activate = BUTTON_ACTIVATE_APPLY;
+ }
+
+ ui_handle_button_activate(C, ar, but, activate);
+ break;
+ }
+ }
+
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ 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: {
+ 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)) {
+ break;
+ }
+
+ for (but = block->buttons.first; but; but = but->next) {
+ if (!(but->flag & UI_BUT_DISABLED) && but->menu_key == event->type) {
+ if (but->type == UI_BTYPE_BUT) {
+ UI_but_execute(C, but);
+ }
+ else {
+ ui_handle_button_activate_by_type(C, ar, but);
+ }
+ break;
+ }
+ }
+
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ break;
+ }
+ }
+ }
+
+ /* here we check return conditions for menus */
+ if (block->flag & UI_BLOCK_LOOP) {
+ /* If we click outside the block, verify if we clicked on the
+ * button that opened us, otherwise we need to close,
+ *
+ * note that there is an exception for root level menus and
+ * popups which you can click again to close.
+ *
+ * Events handled above may have already set the return value,
+ * don't overwrite them, see: T61015.
+ */
+ if ((inside == 0) && (menu->menuretval == 0)) {
+ uiSafetyRct *saferct = block->saferct.first;
+
+ if (ELEM(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE)) {
+ if (ELEM(event->val, KM_PRESS, KM_DBL_CLICK)) {
+ if ((is_parent_menu == false) && (U.uiflag & USER_MENUOPENAUTO) == 0) {
+ /* for root menus, allow clicking to close */
+ if (block->flag & (UI_BLOCK_OUT_1)) {
+ menu->menuretval = UI_RETURN_OK;
+ }
+ else {
+ menu->menuretval = UI_RETURN_OUT;
+ }
+ }
+ else if (saferct && !BLI_rctf_isect_pt(&saferct->parent, event->x, event->y)) {
+ if (block->flag & (UI_BLOCK_OUT_1)) {
+ menu->menuretval = UI_RETURN_OK;
+ }
+ else {
+ menu->menuretval = UI_RETURN_OUT;
+ }
+ }
+ }
+ else if (ELEM(event->val, KM_RELEASE, KM_CLICK)) {
+ /* For buttons that use a hold function,
+ * exit when mouse-up outside the menu. */
+ if (block->flag & UI_BLOCK_POPUP_HOLD) {
+ /* Note, we could check the cursor is over the parent button. */
+ menu->menuretval = UI_RETURN_CANCEL;
+ retval = WM_UI_HANDLER_CONTINUE;
+ }
+ }
+ }
+ }
+
+ if (menu->menuretval) {
+ /* pass */
+ }
#ifdef USE_KEYNAV_LIMIT
- else if ((event->type == MOUSEMOVE) && ui_mouse_motion_keynav_test(&menu->keynav_state, event)) {
- /* Don't handle the mouse-move if we're using key-navigation. */
- retval = WM_UI_HANDLER_BREAK;
- }
+ else if ((event->type == MOUSEMOVE) &&
+ ui_mouse_motion_keynav_test(&menu->keynav_state, event)) {
+ /* Don't handle the mouse-move if we're using key-navigation. */
+ retval = WM_UI_HANDLER_BREAK;
+ }
#endif
- else if (event->type == 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) {
- uiBut *but_default = ui_region_find_first_but_test_flag(ar, UI_BUT_ACTIVE_DEFAULT, UI_HIDDEN);
- if ((but_default != NULL) && (but_default->active == NULL)) {
- if (but_default->type == UI_BTYPE_BUT) {
- UI_but_execute(C, but_default);
- }
- else {
- ui_handle_button_activate_by_type(C, ar, but_default);
- }
- }
- else {
- uiBut *but_active = ui_region_find_active_but(ar);
-
- /* enter will always close this block, we let the event
- * get handled by the button if it is activated, otherwise we cancel */
- if (but_active == NULL) {
- menu->menuretval = UI_RETURN_CANCEL | UI_RETURN_POPUP_OK;
- }
- }
- }
+ else if (event->type == 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) {
+ uiBut *but_default = ui_region_find_first_but_test_flag(
+ ar, UI_BUT_ACTIVE_DEFAULT, UI_HIDDEN);
+ if ((but_default != NULL) && (but_default->active == NULL)) {
+ if (but_default->type == UI_BTYPE_BUT) {
+ UI_but_execute(C, but_default);
+ }
+ else {
+ ui_handle_button_activate_by_type(C, ar, but_default);
+ }
+ }
+ else {
+ uiBut *but_active = ui_region_find_active_but(ar);
+
+ /* enter will always close this block, we let the event
+ * get handled by the button if it is activated, otherwise we cancel */
+ if (but_active == NULL) {
+ menu->menuretval = UI_RETURN_CANCEL | UI_RETURN_POPUP_OK;
+ }
+ }
+ }
#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_tooltip_timer_remove(C, but);
- }
-
- menu->is_grab = true;
- copy_v2_v2_int(menu->grab_xy_prev, &event->x);
- retval = WM_UI_HANDLER_BREAK;
- }
- }
+ 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_tooltip_timer_remove(C, but);
+ }
+
+ menu->is_grab = true;
+ copy_v2_v2_int(menu->grab_xy_prev, &event->x);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
#endif
- else {
-
- /* check mouse moving outside of the menu */
- if (inside == 0 && (block->flag & (UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_POPOVER))) {
- uiSafetyRct *saferct;
-
- ui_mouse_motion_towards_check(block, menu, &event->x, is_parent_inside == false);
-
- /* check for all parent rects, enables arrowkeys to be used */
- for (saferct = block->saferct.first; saferct; saferct = saferct->next) {
- /* for mouse move we only check our own rect, for other
- * events we check all preceding block rects too to make
- * arrow keys navigation work */
- if (event->type != MOUSEMOVE || saferct == block->saferct.first) {
- if (BLI_rctf_isect_pt(&saferct->parent, (float)event->x, (float)event->y)) {
- break;
- }
- if (BLI_rctf_isect_pt(&saferct->safety, (float)event->x, (float)event->y)) {
- break;
- }
- }
- }
-
- /* strict check, and include the parent rect */
- if (!menu->dotowards && !saferct) {
- if (block->flag & (UI_BLOCK_OUT_1)) {
- menu->menuretval = UI_RETURN_OK;
- }
- else {
- menu->menuretval = UI_RETURN_OUT;
- }
- }
- else if (menu->dotowards && event->type == MOUSEMOVE) {
- retval = WM_UI_HANDLER_BREAK;
- }
- }
- }
-
- /* end switch */
- }
- }
-
- /* if we are didn't handle the event yet, lets pass it on to
- * buttons inside this region. disabled inside check .. not sure
- * anymore why it was there? but it meant enter didn't work
- * for example when mouse was not over submenu */
- if ((event->type == TIMER) ||
- (/*inside &&*/ (!menu->menuretval || (menu->menuretval & UI_RETURN_UPDATE)) && retval == WM_UI_HANDLER_CONTINUE))
- {
- retval = ui_handle_menu_button(C, event, menu);
- }
+ else {
+
+ /* check mouse moving outside of the menu */
+ if (inside == 0 && (block->flag & (UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_POPOVER))) {
+ uiSafetyRct *saferct;
+
+ ui_mouse_motion_towards_check(block, menu, &event->x, is_parent_inside == false);
+
+ /* check for all parent rects, enables arrowkeys to be used */
+ for (saferct = block->saferct.first; saferct; saferct = saferct->next) {
+ /* for mouse move we only check our own rect, for other
+ * events we check all preceding block rects too to make
+ * arrow keys navigation work */
+ if (event->type != MOUSEMOVE || saferct == block->saferct.first) {
+ if (BLI_rctf_isect_pt(&saferct->parent, (float)event->x, (float)event->y)) {
+ break;
+ }
+ if (BLI_rctf_isect_pt(&saferct->safety, (float)event->x, (float)event->y)) {
+ break;
+ }
+ }
+ }
+
+ /* strict check, and include the parent rect */
+ if (!menu->dotowards && !saferct) {
+ if (block->flag & (UI_BLOCK_OUT_1)) {
+ menu->menuretval = UI_RETURN_OK;
+ }
+ else {
+ menu->menuretval = UI_RETURN_OUT;
+ }
+ }
+ else if (menu->dotowards && event->type == MOUSEMOVE) {
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
+ }
+
+ /* end switch */
+ }
+ }
+
+ /* if we are didn't handle the event yet, lets pass it on to
+ * buttons inside this region. disabled inside check .. not sure
+ * anymore why it was there? but it meant enter didn't work
+ * for example when mouse was not over submenu */
+ if ((event->type == TIMER) ||
+ (/*inside &&*/ (!menu->menuretval || (menu->menuretval & UI_RETURN_UPDATE)) &&
+ retval == WM_UI_HANDLER_CONTINUE)) {
+ retval = ui_handle_menu_button(C, event, menu);
+ }
#ifdef USE_UI_POPOVER_ONCE
- if (block->flag & UI_BLOCK_POPOVER_ONCE) {
- if ((event->type == LEFTMOUSE) && (event->val == KM_RELEASE)) {
- UI_popover_once_clear(menu->popup_create_vars.arg);
- block->flag &= ~UI_BLOCK_POPOVER_ONCE;
- }
- }
+ if (block->flag & UI_BLOCK_POPOVER_ONCE) {
+ if ((event->type == LEFTMOUSE) && (event->val == KM_RELEASE)) {
+ UI_popover_once_clear(menu->popup_create_vars.arg);
+ block->flag &= ~UI_BLOCK_POPOVER_ONCE;
+ }
+ }
#endif
- /* Don't handle double click events, rehandle as regular press/release. */
- if (retval == WM_UI_HANDLER_CONTINUE && event->val == KM_DBL_CLICK) {
- return retval;
- }
-
- /* if we set a menu return value, ensure we continue passing this on to
- * lower menus and buttons, so always set continue then, and if we are
- * inside the region otherwise, ensure we swallow the event */
- if (menu->menuretval) {
- return WM_UI_HANDLER_CONTINUE;
- }
- else if (inside) {
- return WM_UI_HANDLER_BREAK;
- }
- else {
- return retval;
- }
-}
-
-static int ui_handle_menu_return_submenu(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu)
-{
- ARegion *ar;
- uiBut *but;
- uiBlock *block;
- uiHandleButtonData *data;
- uiPopupBlockHandle *submenu;
-
- ar = menu->region;
- block = ar->uiblocks.first;
-
- but = ui_region_find_active_but(ar);
-
- BLI_assert(but);
-
- data = but->active;
- submenu = data->menu;
-
- if (submenu->menuretval) {
- bool update;
-
- /* first decide if we want to close our own menu cascading, if
- * so pass on the sub menu return value to our own menu handle */
- if ((submenu->menuretval & UI_RETURN_OK) || (submenu->menuretval & UI_RETURN_CANCEL)) {
- if (!(block->flag & UI_BLOCK_KEEP_OPEN)) {
- menu->menuretval = submenu->menuretval;
- menu->butretval = data->retval;
- }
- }
-
- update = (submenu->menuretval & UI_RETURN_UPDATE) != 0;
-
- /* now let activated button in this menu exit, which
- * will actually close the submenu too */
- ui_handle_button_return_submenu(C, event, but);
-
- if (update) {
- submenu->menuretval = 0;
- }
- }
-
- if (block->flag & (UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_POPOVER)) {
- /* for cases where close does not cascade, allow the user to
- * move the mouse back towards the menu without closing */
- ui_mouse_motion_towards_reinit(menu, &event->x);
- }
-
- if (menu->menuretval) {
- return WM_UI_HANDLER_CONTINUE;
- }
- else {
- return WM_UI_HANDLER_BREAK;
- }
+ /* Don't handle double click events, rehandle as regular press/release. */
+ if (retval == WM_UI_HANDLER_CONTINUE && event->val == KM_DBL_CLICK) {
+ return retval;
+ }
+
+ /* if we set a menu return value, ensure we continue passing this on to
+ * lower menus and buttons, so always set continue then, and if we are
+ * inside the region otherwise, ensure we swallow the event */
+ if (menu->menuretval) {
+ return WM_UI_HANDLER_CONTINUE;
+ }
+ else if (inside) {
+ return WM_UI_HANDLER_BREAK;
+ }
+ else {
+ return retval;
+ }
+}
+
+static int ui_handle_menu_return_submenu(bContext *C,
+ const wmEvent *event,
+ uiPopupBlockHandle *menu)
+{
+ ARegion *ar;
+ uiBut *but;
+ uiBlock *block;
+ uiHandleButtonData *data;
+ uiPopupBlockHandle *submenu;
+
+ ar = menu->region;
+ block = ar->uiblocks.first;
+
+ but = ui_region_find_active_but(ar);
+
+ BLI_assert(but);
+
+ data = but->active;
+ submenu = data->menu;
+
+ if (submenu->menuretval) {
+ bool update;
+
+ /* first decide if we want to close our own menu cascading, if
+ * so pass on the sub menu return value to our own menu handle */
+ if ((submenu->menuretval & UI_RETURN_OK) || (submenu->menuretval & UI_RETURN_CANCEL)) {
+ if (!(block->flag & UI_BLOCK_KEEP_OPEN)) {
+ menu->menuretval = submenu->menuretval;
+ menu->butretval = data->retval;
+ }
+ }
+
+ update = (submenu->menuretval & UI_RETURN_UPDATE) != 0;
+
+ /* now let activated button in this menu exit, which
+ * will actually close the submenu too */
+ ui_handle_button_return_submenu(C, event, but);
+
+ if (update) {
+ submenu->menuretval = 0;
+ }
+ }
+
+ if (block->flag & (UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_POPOVER)) {
+ /* for cases where close does not cascade, allow the user to
+ * move the mouse back towards the menu without closing */
+ ui_mouse_motion_towards_reinit(menu, &event->x);
+ }
+
+ if (menu->menuretval) {
+ return WM_UI_HANDLER_CONTINUE;
+ }
+ else {
+ return WM_UI_HANDLER_BREAK;
+ }
}
static bool ui_but_pie_menu_supported_apply(uiBut *but)
{
- return (!ELEM(but->type, UI_BTYPE_NUM_SLIDER, UI_BTYPE_NUM));
+ return (!ELEM(but->type, UI_BTYPE_NUM_SLIDER, UI_BTYPE_NUM));
}
-static int ui_but_pie_menu_apply(bContext *C, uiPopupBlockHandle *menu, uiBut *but, bool force_close)
+static int ui_but_pie_menu_apply(bContext *C,
+ uiPopupBlockHandle *menu,
+ uiBut *but,
+ bool force_close)
{
- int retval = WM_UI_HANDLER_BREAK;
+ int retval = WM_UI_HANDLER_BREAK;
- if (but && ui_but_pie_menu_supported_apply(but)) {
- if (but->type == UI_BTYPE_MENU) {
- /* forcing the pie menu to close will not handle menus */
- if (!force_close) {
- uiBut *active_but = ui_region_find_active_but(menu->region);
+ if (but && ui_but_pie_menu_supported_apply(but)) {
+ if (but->type == UI_BTYPE_MENU) {
+ /* forcing the pie menu to close will not handle menus */
+ if (!force_close) {
+ uiBut *active_but = ui_region_find_active_but(menu->region);
- if (active_but) {
- button_activate_exit(C, active_but, active_but->active, false, false);
- }
+ if (active_but) {
+ button_activate_exit(C, active_but, active_but->active, false, false);
+ }
- button_activate_init(C, menu->region, but, BUTTON_ACTIVATE_OPEN);
- return retval;
- }
- else {
- menu->menuretval = UI_RETURN_CANCEL;
- }
- }
- else {
- ui_apply_but(C, but->block, but, but->active, false);
- button_activate_exit((bContext *)C, but, but->active, false, true);
+ button_activate_init(C, menu->region, but, BUTTON_ACTIVATE_OPEN);
+ return retval;
+ }
+ else {
+ menu->menuretval = UI_RETURN_CANCEL;
+ }
+ }
+ else {
+ ui_apply_but(C, but->block, but, but->active, false);
+ button_activate_exit((bContext *)C, but, but->active, false, true);
- menu->menuretval = UI_RETURN_OK;
- }
- }
- else {
- menu->menuretval = UI_RETURN_CANCEL;
+ menu->menuretval = UI_RETURN_OK;
+ }
+ }
+ else {
+ menu->menuretval = UI_RETURN_CANCEL;
- ED_region_tag_redraw(menu->region);
- }
+ ED_region_tag_redraw(menu->region);
+ }
- return retval;
+ return retval;
}
static uiBut *ui_block_pie_dir_activate(uiBlock *block, const wmEvent *event, RadialDirection dir)
{
- uiBut *but;
+ uiBut *but;
- if ((block->flag & UI_BLOCK_NUMSELECT) && event->val == KM_PRESS) {
- for (but = block->buttons.first; but; but = but->next) {
- if (but->pie_dir == dir && !ELEM(but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE)) {
- return but;
- }
- }
- }
+ if ((block->flag & UI_BLOCK_NUMSELECT) && event->val == KM_PRESS) {
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->pie_dir == dir && !ELEM(but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE)) {
+ return but;
+ }
+ }
+ }
- return NULL;
+ return NULL;
}
static int ui_but_pie_button_activate(bContext *C, uiBut *but, uiPopupBlockHandle *menu)
{
- uiBut *active_but;
+ uiBut *active_but;
- if (but == NULL) {
- return WM_UI_HANDLER_BREAK;
- }
+ if (but == NULL) {
+ return WM_UI_HANDLER_BREAK;
+ }
- active_but = ui_region_find_active_but(menu->region);
+ active_but = ui_region_find_active_but(menu->region);
- if (active_but) {
- button_activate_exit(C, active_but, active_but->active, false, false);
- }
+ if (active_but) {
+ button_activate_exit(C, active_but, active_but->active, false, false);
+ }
- button_activate_init(C, menu->region, but, BUTTON_ACTIVATE_OVER);
- return ui_but_pie_menu_apply(C, menu, but, false);
+ button_activate_init(C, menu->region, but, BUTTON_ACTIVATE_OVER);
+ return ui_but_pie_menu_apply(C, menu, but, false);
}
static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu)
{
- ARegion *ar;
- uiBlock *block;
- uiBut *but;
- float event_xy[2];
- double duration;
- bool is_click_style;
- float dist;
-
- /* we block all events, this is modal interaction,
- * except for drop events which is described below */
- int retval = WM_UI_HANDLER_BREAK;
-
- if (event->type == EVT_DROP) {
- /* may want to leave this here for later if we support pie ovens */
-
- retval = WM_UI_HANDLER_CONTINUE;
- }
-
- ar = menu->region;
- block = ar->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);
-
- if (menu->scrolltimer == NULL) {
- menu->scrolltimer =
- WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, PIE_MENU_INTERVAL);
- menu->scrolltimer->duration = 0.0;
- }
-
- duration = menu->scrolltimer->duration;
-
- event_xy[0] = event->x;
- event_xy[1] = event->y;
-
- ui_window_to_block_fl(ar, block, &event_xy[0], &event_xy[1]);
-
- /* Distance from initial point. */
- dist = ui_block_calc_pie_segment(block, event_xy);
-
- if (but && button_modal_state(but->active->state)) {
- retval = ui_handle_menu_button(C, event, menu);
- }
- else {
- if (event->type == TIMER) {
- if (event->customdata == menu->scrolltimer) {
- /* deactivate initial direction after a while */
- if (duration > 0.01 * U.pie_initial_timeout) {
- block->pie_data.flags &= ~UI_PIE_INITIAL_DIRECTION;
- }
-
- /* handle animation */
- if (!(block->pie_data.flags & UI_PIE_ANIMATION_FINISHED)) {
- double final_time = 0.01 * U.pie_animation_timeout;
- float fac = duration / final_time;
- float pie_radius = U.pie_menu_radius * UI_DPI_FAC;
-
- if (fac > 1.0f) {
- fac = 1.0f;
- block->pie_data.flags |= UI_PIE_ANIMATION_FINISHED;
- }
-
- for (but = block->buttons.first; but; but = but->next) {
- if (but->pie_dir != UI_RADIAL_NONE) {
- float vec[2];
- float center[2];
-
- ui_but_pie_dir(but->pie_dir, vec);
-
- center[0] = (vec[0] > 0.01f) ? 0.5f : ((vec[0] < -0.01f) ? -0.5f : 0.0f);
- center[1] = (vec[1] > 0.99f) ? 0.5f : ((vec[1] < -0.99f) ? -0.5f : 0.0f);
-
- center[0] *= BLI_rctf_size_x(&but->rect);
- center[1] *= BLI_rctf_size_y(&but->rect);
-
- mul_v2_fl(vec, pie_radius);
- add_v2_v2(vec, center);
- mul_v2_fl(vec, fac);
- add_v2_v2(vec, block->pie_data.pie_center_spawned);
-
- BLI_rctf_recenter(&but->rect, vec[0], vec[1]);
- }
- }
- block->pie_data.alphafac = fac;
-
- ED_region_tag_redraw(ar);
- }
- }
-
- /* check pie velociy here if gesture has ended */
- if (block->pie_data.flags & UI_PIE_GESTURE_END_WAIT) {
- float len_sq = 10;
-
- /* use a time threshold to ensure we leave time to the mouse to move */
- if (duration - block->pie_data.duration_gesture > 0.02) {
- len_sq = len_squared_v2v2(event_xy, block->pie_data.last_pos);
- copy_v2_v2(block->pie_data.last_pos, event_xy);
- block->pie_data.duration_gesture = duration;
- }
-
- if (len_sq < 1.0f) {
- but = ui_region_find_active_but(menu->region);
-
- if (but) {
- return ui_but_pie_menu_apply(C, menu, but, true);
- }
- }
- }
- }
-
- if (event->type == block->pie_data.event && !is_click_style) {
- if (event->val != KM_RELEASE) {
- ui_handle_menu_button(C, event, menu);
-
- if (len_squared_v2v2(event_xy, block->pie_data.pie_center_init) > PIE_CLICK_THRESHOLD_SQ) {
- block->pie_data.flags |= UI_PIE_DRAG_STYLE;
- }
- /* 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);
- }
- else {
- if ((duration < 0.01 * U.pie_tap_timeout) &&
- !(block->pie_data.flags & UI_PIE_DRAG_STYLE))
- {
- block->pie_data.flags |= UI_PIE_CLICK_STYLE;
- }
- else {
- but = ui_region_find_active_but(menu->region);
-
- if (but && (U.pie_menu_confirm > 0) &&
- (dist >= U.dpi_fac * (U.pie_menu_threshold + U.pie_menu_confirm)))
- {
- if (but) {
- return ui_but_pie_menu_apply(C, menu, but, true);
- }
- }
-
- retval = ui_but_pie_menu_apply(C, menu, but, true);
-
- }
- }
- }
- else {
- /* direction from numpad */
- RadialDirection num_dir = UI_RADIAL_NONE;
-
- switch (event->type) {
- case MOUSEMOVE:
- if (!is_click_style) {
- float len_sq = len_squared_v2v2(event_xy, block->pie_data.pie_center_init);
-
- /* here we use the initial position explicitly */
- if (len_sq > PIE_CLICK_THRESHOLD_SQ) {
- block->pie_data.flags |= UI_PIE_DRAG_STYLE;
- }
-
- /* here instead, we use the offset location to account for the initial
- * direction timeout */
- if ((U.pie_menu_confirm > 0) &&
- (dist >= U.dpi_fac * (U.pie_menu_threshold + U.pie_menu_confirm)))
- {
- block->pie_data.flags |= UI_PIE_GESTURE_END_WAIT;
- copy_v2_v2(block->pie_data.last_pos, event_xy);
- block->pie_data.duration_gesture = duration;
- }
- }
-
- ui_handle_menu_button(C, event, menu);
-
- /* mouse move should always refresh the area for pie menus */
- ED_region_tag_redraw(ar);
- break;
-
- case LEFTMOUSE:
- if (is_click_style) {
- if (block->pie_data.flags & UI_PIE_INVALID_DIR) {
- menu->menuretval = UI_RETURN_CANCEL;
- }
- else {
- retval = ui_handle_menu_button(C, event, menu);
- }
- }
- break;
-
- case 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:
- {
- 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) {
- if (but->menu_key == event->type) {
- ui_but_pie_button_activate(C, but, menu);
- }
- }
- }
- break;
- }
+ ARegion *ar;
+ uiBlock *block;
+ uiBut *but;
+ float event_xy[2];
+ double duration;
+ bool is_click_style;
+ float dist;
+
+ /* we block all events, this is modal interaction,
+ * except for drop events which is described below */
+ int retval = WM_UI_HANDLER_BREAK;
+
+ if (event->type == EVT_DROP) {
+ /* may want to leave this here for later if we support pie ovens */
+
+ retval = WM_UI_HANDLER_CONTINUE;
+ }
+
+ ar = menu->region;
+ block = ar->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);
+
+ if (menu->scrolltimer == NULL) {
+ menu->scrolltimer = WM_event_add_timer(
+ CTX_wm_manager(C), CTX_wm_window(C), TIMER, PIE_MENU_INTERVAL);
+ menu->scrolltimer->duration = 0.0;
+ }
+
+ duration = menu->scrolltimer->duration;
+
+ event_xy[0] = event->x;
+ event_xy[1] = event->y;
+
+ ui_window_to_block_fl(ar, block, &event_xy[0], &event_xy[1]);
+
+ /* Distance from initial point. */
+ dist = ui_block_calc_pie_segment(block, event_xy);
+
+ if (but && button_modal_state(but->active->state)) {
+ retval = ui_handle_menu_button(C, event, menu);
+ }
+ else {
+ if (event->type == TIMER) {
+ if (event->customdata == menu->scrolltimer) {
+ /* deactivate initial direction after a while */
+ if (duration > 0.01 * U.pie_initial_timeout) {
+ block->pie_data.flags &= ~UI_PIE_INITIAL_DIRECTION;
+ }
+
+ /* handle animation */
+ if (!(block->pie_data.flags & UI_PIE_ANIMATION_FINISHED)) {
+ double final_time = 0.01 * U.pie_animation_timeout;
+ float fac = duration / final_time;
+ float pie_radius = U.pie_menu_radius * UI_DPI_FAC;
+
+ if (fac > 1.0f) {
+ fac = 1.0f;
+ block->pie_data.flags |= UI_PIE_ANIMATION_FINISHED;
+ }
+
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->pie_dir != UI_RADIAL_NONE) {
+ float vec[2];
+ float center[2];
+
+ ui_but_pie_dir(but->pie_dir, vec);
+
+ center[0] = (vec[0] > 0.01f) ? 0.5f : ((vec[0] < -0.01f) ? -0.5f : 0.0f);
+ center[1] = (vec[1] > 0.99f) ? 0.5f : ((vec[1] < -0.99f) ? -0.5f : 0.0f);
+
+ center[0] *= BLI_rctf_size_x(&but->rect);
+ center[1] *= BLI_rctf_size_y(&but->rect);
+
+ mul_v2_fl(vec, pie_radius);
+ add_v2_v2(vec, center);
+ mul_v2_fl(vec, fac);
+ add_v2_v2(vec, block->pie_data.pie_center_spawned);
+
+ BLI_rctf_recenter(&but->rect, vec[0], vec[1]);
+ }
+ }
+ block->pie_data.alphafac = fac;
+
+ ED_region_tag_redraw(ar);
+ }
+ }
+
+ /* check pie velociy here if gesture has ended */
+ if (block->pie_data.flags & UI_PIE_GESTURE_END_WAIT) {
+ float len_sq = 10;
+
+ /* use a time threshold to ensure we leave time to the mouse to move */
+ if (duration - block->pie_data.duration_gesture > 0.02) {
+ len_sq = len_squared_v2v2(event_xy, block->pie_data.last_pos);
+ copy_v2_v2(block->pie_data.last_pos, event_xy);
+ block->pie_data.duration_gesture = duration;
+ }
+
+ if (len_sq < 1.0f) {
+ but = ui_region_find_active_but(menu->region);
+
+ if (but) {
+ return ui_but_pie_menu_apply(C, menu, but, true);
+ }
+ }
+ }
+ }
+
+ if (event->type == block->pie_data.event && !is_click_style) {
+ if (event->val != KM_RELEASE) {
+ ui_handle_menu_button(C, event, menu);
+
+ if (len_squared_v2v2(event_xy, block->pie_data.pie_center_init) > PIE_CLICK_THRESHOLD_SQ) {
+ block->pie_data.flags |= UI_PIE_DRAG_STYLE;
+ }
+ /* 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);
+ }
+ else {
+ if ((duration < 0.01 * U.pie_tap_timeout) &&
+ !(block->pie_data.flags & UI_PIE_DRAG_STYLE)) {
+ block->pie_data.flags |= UI_PIE_CLICK_STYLE;
+ }
+ else {
+ but = ui_region_find_active_but(menu->region);
+
+ if (but && (U.pie_menu_confirm > 0) &&
+ (dist >= U.dpi_fac * (U.pie_menu_threshold + U.pie_menu_confirm))) {
+ if (but) {
+ return ui_but_pie_menu_apply(C, menu, but, true);
+ }
+ }
+
+ retval = ui_but_pie_menu_apply(C, menu, but, true);
+ }
+ }
+ }
+ else {
+ /* direction from numpad */
+ RadialDirection num_dir = UI_RADIAL_NONE;
+
+ switch (event->type) {
+ case MOUSEMOVE:
+ if (!is_click_style) {
+ float len_sq = len_squared_v2v2(event_xy, block->pie_data.pie_center_init);
+
+ /* here we use the initial position explicitly */
+ if (len_sq > PIE_CLICK_THRESHOLD_SQ) {
+ block->pie_data.flags |= UI_PIE_DRAG_STYLE;
+ }
+
+ /* here instead, we use the offset location to account for the initial
+ * direction timeout */
+ if ((U.pie_menu_confirm > 0) &&
+ (dist >= U.dpi_fac * (U.pie_menu_threshold + U.pie_menu_confirm))) {
+ block->pie_data.flags |= UI_PIE_GESTURE_END_WAIT;
+ copy_v2_v2(block->pie_data.last_pos, event_xy);
+ block->pie_data.duration_gesture = duration;
+ }
+ }
+
+ ui_handle_menu_button(C, event, menu);
+
+ /* mouse move should always refresh the area for pie menus */
+ ED_region_tag_redraw(ar);
+ break;
+
+ case LEFTMOUSE:
+ if (is_click_style) {
+ if (block->pie_data.flags & UI_PIE_INVALID_DIR) {
+ menu->menuretval = UI_RETURN_CANCEL;
+ }
+ else {
+ retval = ui_handle_menu_button(C, event, menu);
+ }
+ }
+ break;
+
+ case 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: {
+ 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) {
+ if (but->menu_key == event->type) {
+ ui_but_pie_button_activate(C, but, menu);
+ }
+ }
+ }
+ break;
+ }
#define CASE_NUM_TO_DIR(n, d) \
- case (ZEROKEY + n): case (PAD0 + n): \
- { if (num_dir == UI_RADIAL_NONE) num_dir = d; } (void)0
-
- CASE_NUM_TO_DIR(1, UI_RADIAL_SW); ATTR_FALLTHROUGH;
- CASE_NUM_TO_DIR(2, UI_RADIAL_S); ATTR_FALLTHROUGH;
- CASE_NUM_TO_DIR(3, UI_RADIAL_SE); ATTR_FALLTHROUGH;
- CASE_NUM_TO_DIR(4, UI_RADIAL_W); ATTR_FALLTHROUGH;
- CASE_NUM_TO_DIR(6, UI_RADIAL_E); ATTR_FALLTHROUGH;
- CASE_NUM_TO_DIR(7, UI_RADIAL_NW); ATTR_FALLTHROUGH;
- CASE_NUM_TO_DIR(8, UI_RADIAL_N); ATTR_FALLTHROUGH;
- CASE_NUM_TO_DIR(9, UI_RADIAL_NE);
- {
- but = ui_block_pie_dir_activate(block, event, num_dir);
- retval = ui_but_pie_button_activate(C, but, menu);
- break;
- }
+ case (ZEROKEY + n): \
+ case (PAD0 + n): { \
+ if (num_dir == UI_RADIAL_NONE) \
+ num_dir = d; \
+ } \
+ (void)0
+
+ CASE_NUM_TO_DIR(1, UI_RADIAL_SW);
+ ATTR_FALLTHROUGH;
+ CASE_NUM_TO_DIR(2, UI_RADIAL_S);
+ ATTR_FALLTHROUGH;
+ CASE_NUM_TO_DIR(3, UI_RADIAL_SE);
+ ATTR_FALLTHROUGH;
+ CASE_NUM_TO_DIR(4, UI_RADIAL_W);
+ ATTR_FALLTHROUGH;
+ CASE_NUM_TO_DIR(6, UI_RADIAL_E);
+ ATTR_FALLTHROUGH;
+ CASE_NUM_TO_DIR(7, UI_RADIAL_NW);
+ ATTR_FALLTHROUGH;
+ CASE_NUM_TO_DIR(8, UI_RADIAL_N);
+ ATTR_FALLTHROUGH;
+ CASE_NUM_TO_DIR(9, UI_RADIAL_NE);
+ {
+ but = ui_block_pie_dir_activate(block, event, num_dir);
+ retval = ui_but_pie_button_activate(C, but, menu);
+ break;
+ }
#undef CASE_NUM_TO_DIR
- default:
- retval = ui_handle_menu_button(C, event, menu);
- break;
- }
- }
- }
-
- return retval;
-}
-
-static int ui_handle_menus_recursive(
- bContext *C, const wmEvent *event, uiPopupBlockHandle *menu,
- int level, const bool is_parent_inside, const bool is_parent_menu, const bool is_floating)
-{
- uiBut *but;
- uiHandleButtonData *data;
- uiPopupBlockHandle *submenu;
- int retval = WM_UI_HANDLER_CONTINUE;
- bool do_towards_reinit = false;
-
- /* check if we have a submenu, and handle events for it first */
- but = ui_region_find_active_but(menu->region);
- data = (but) ? but->active : NULL;
- submenu = (data) ? data->menu : NULL;
-
- if (submenu) {
- uiBlock *block = menu->region->uiblocks.first;
- const bool is_menu = ui_block_is_menu(block);
- bool inside = false;
- /* root pie menus accept the key that spawned
- * them as double click to improve responsiveness */
- bool do_recursion = (!(block->flag & UI_BLOCK_RADIAL) || event->type != block->pie_data.event);
-
- if (do_recursion) {
- if (is_parent_inside == false) {
- int mx, my;
-
- mx = event->x;
- my = event->y;
- ui_window_to_block(menu->region, block, &mx, &my);
- inside = BLI_rctf_isect_pt(&block->rect, mx, my);
- }
-
- retval = ui_handle_menus_recursive(C, event, submenu, level + 1, is_parent_inside || inside, is_menu, false);
- }
- }
-
- /* now handle events for our own menu */
- if (retval == WM_UI_HANDLER_CONTINUE || event->type == TIMER) {
- const bool do_but_search = (but && (but->type == UI_BTYPE_SEARCH_MENU));
- if (submenu && submenu->menuretval) {
- const bool do_ret_out_parent = (submenu->menuretval & UI_RETURN_OUT_PARENT) != 0;
- retval = ui_handle_menu_return_submenu(C, event, menu);
- submenu = NULL; /* hint not to use this, it may be freed by call above */
- (void)submenu;
- /* we may want to quit the submenu and handle the even in this menu,
- * if its important to use it, check 'data->menu' first */
- if (((retval == WM_UI_HANDLER_BREAK) && do_ret_out_parent) == 0) {
- /* skip applying the event */
- return retval;
- }
- }
-
- if (do_but_search) {
- uiBlock *block = menu->region->uiblocks.first;
-
- retval = ui_handle_menu_button(C, event, menu);
-
- if (block->flag & (UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_POPOVER)) {
- /* when there is a active search button and we close it,
- * we need to reinit the mouse coords [#35346] */
- if (ui_region_find_active_but(menu->region) != but) {
- do_towards_reinit = true;
- }
- }
- }
- else {
- uiBlock *block = menu->region->uiblocks.first;
- uiBut *listbox = ui_list_find_mouse_over(menu->region, event);
-
- if (block->flag & UI_BLOCK_RADIAL) {
- retval = ui_pie_handler(C, event, menu);
- }
- else if (event->type == LEFTMOUSE || event->val != KM_DBL_CLICK) {
- bool handled = false;
-
- if (listbox) {
- int retval_test = ui_handle_list_event(C, event, menu->region, listbox);
- if (retval_test != WM_UI_HANDLER_CONTINUE) {
- retval = retval_test;
- handled = true;
- }
- }
-
- if (handled == false) {
- retval = ui_handle_menu_event(
- C, event, menu, level,
- is_parent_inside, is_parent_menu, is_floating);
- }
- }
- }
- }
-
- if (do_towards_reinit) {
- ui_mouse_motion_towards_reinit(menu, &event->x);
- }
-
- return retval;
+ default:
+ retval = ui_handle_menu_button(C, event, menu);
+ break;
+ }
+ }
+ }
+
+ return retval;
+}
+
+static int ui_handle_menus_recursive(bContext *C,
+ const wmEvent *event,
+ uiPopupBlockHandle *menu,
+ int level,
+ const bool is_parent_inside,
+ const bool is_parent_menu,
+ const bool is_floating)
+{
+ uiBut *but;
+ uiHandleButtonData *data;
+ uiPopupBlockHandle *submenu;
+ int retval = WM_UI_HANDLER_CONTINUE;
+ bool do_towards_reinit = false;
+
+ /* check if we have a submenu, and handle events for it first */
+ but = ui_region_find_active_but(menu->region);
+ data = (but) ? but->active : NULL;
+ submenu = (data) ? data->menu : NULL;
+
+ if (submenu) {
+ uiBlock *block = menu->region->uiblocks.first;
+ const bool is_menu = ui_block_is_menu(block);
+ bool inside = false;
+ /* root pie menus accept the key that spawned
+ * them as double click to improve responsiveness */
+ bool do_recursion = (!(block->flag & UI_BLOCK_RADIAL) || event->type != block->pie_data.event);
+
+ if (do_recursion) {
+ if (is_parent_inside == false) {
+ int mx, my;
+
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(menu->region, block, &mx, &my);
+ inside = BLI_rctf_isect_pt(&block->rect, mx, my);
+ }
+
+ retval = ui_handle_menus_recursive(
+ C, event, submenu, level + 1, is_parent_inside || inside, is_menu, false);
+ }
+ }
+
+ /* now handle events for our own menu */
+ if (retval == WM_UI_HANDLER_CONTINUE || event->type == TIMER) {
+ const bool do_but_search = (but && (but->type == UI_BTYPE_SEARCH_MENU));
+ if (submenu && submenu->menuretval) {
+ const bool do_ret_out_parent = (submenu->menuretval & UI_RETURN_OUT_PARENT) != 0;
+ retval = ui_handle_menu_return_submenu(C, event, menu);
+ submenu = NULL; /* hint not to use this, it may be freed by call above */
+ (void)submenu;
+ /* we may want to quit the submenu and handle the even in this menu,
+ * if its important to use it, check 'data->menu' first */
+ if (((retval == WM_UI_HANDLER_BREAK) && do_ret_out_parent) == 0) {
+ /* skip applying the event */
+ return retval;
+ }
+ }
+
+ if (do_but_search) {
+ uiBlock *block = menu->region->uiblocks.first;
+
+ retval = ui_handle_menu_button(C, event, menu);
+
+ if (block->flag & (UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_POPOVER)) {
+ /* when there is a active search button and we close it,
+ * we need to reinit the mouse coords [#35346] */
+ if (ui_region_find_active_but(menu->region) != but) {
+ do_towards_reinit = true;
+ }
+ }
+ }
+ else {
+ uiBlock *block = menu->region->uiblocks.first;
+ uiBut *listbox = ui_list_find_mouse_over(menu->region, event);
+
+ if (block->flag & UI_BLOCK_RADIAL) {
+ retval = ui_pie_handler(C, event, menu);
+ }
+ else if (event->type == LEFTMOUSE || event->val != KM_DBL_CLICK) {
+ bool handled = false;
+
+ if (listbox) {
+ int retval_test = ui_handle_list_event(C, event, menu->region, listbox);
+ if (retval_test != WM_UI_HANDLER_CONTINUE) {
+ retval = retval_test;
+ handled = true;
+ }
+ }
+
+ if (handled == false) {
+ retval = ui_handle_menu_event(
+ C, event, menu, level, is_parent_inside, is_parent_menu, is_floating);
+ }
+ }
+ }
+ }
+
+ if (do_towards_reinit) {
+ ui_mouse_motion_towards_reinit(menu, &event->x);
+ }
+
+ return retval;
}
/**
@@ -9863,10 +9909,10 @@ static int ui_handle_menus_recursive(
*/
void UI_popup_menu_retval_set(const uiBlock *block, const int retval, const bool enable)
{
- uiPopupBlockHandle *menu = block->handle;
- if (menu) {
- menu->menuretval = enable ? (menu->menuretval | retval) : (menu->menuretval & retval);
- }
+ uiPopupBlockHandle *menu = block->handle;
+ if (menu) {
+ menu->menuretval = enable ? (menu->menuretval | retval) : (menu->menuretval & retval);
+ }
}
/** \} */
@@ -9877,391 +9923,387 @@ 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;
- uiBut *but, *listbox;
- int retval;
+ ARegion *ar;
+ uiBut *but, *listbox;
+ int retval;
- /* here we handle buttons at the region level, non-modal */
- ar = CTX_wm_region(C);
- retval = WM_UI_HANDLER_CONTINUE;
+ /* here we handle buttons at the region level, non-modal */
+ ar = CTX_wm_region(C);
+ retval = WM_UI_HANDLER_CONTINUE;
- if (ar == NULL || BLI_listbase_is_empty(&ar->uiblocks)) {
- return retval;
- }
+ if (ar == NULL || BLI_listbase_is_empty(&ar->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);
+ /* 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);
- retval = ui_handler_panel_region(C, event, ar, listbox ? listbox : but);
+ retval = ui_handler_panel_region(C, event, ar, listbox ? listbox : but);
- if (retval == WM_UI_HANDLER_CONTINUE && listbox) {
- retval = ui_handle_list_event(C, event, ar, listbox);
+ if (retval == WM_UI_HANDLER_CONTINUE && listbox) {
+ retval = ui_handle_list_event(C, event, ar, listbox);
- /* interactions with the listbox should disable tips */
- if (retval == WM_UI_HANDLER_BREAK) {
- if (but) {
- UI_but_tooltip_timer_remove(C, but);
- }
- }
- }
+ /* interactions with the listbox should disable tips */
+ if (retval == WM_UI_HANDLER_BREAK) {
+ if (but) {
+ UI_but_tooltip_timer_remove(C, but);
+ }
+ }
+ }
- if (retval == WM_UI_HANDLER_CONTINUE) {
- if (but) {
- retval = ui_handle_button_event(C, event, but);
- }
- else {
- retval = ui_handle_button_over(C, event, ar);
- }
- }
+ if (retval == WM_UI_HANDLER_CONTINUE) {
+ if (but) {
+ retval = ui_handle_button_event(C, event, but);
+ }
+ else {
+ retval = ui_handle_button_over(C, event, ar);
+ }
+ }
- /* re-enable tooltips */
- if (event->type == MOUSEMOVE && (event->x != event->prevx || event->y != event->prevy)) {
- ui_blocks_set_tooltips(ar, true);
- }
+ /* re-enable tooltips */
+ if (event->type == MOUSEMOVE && (event->x != event->prevx || event->y != event->prevy)) {
+ ui_blocks_set_tooltips(ar, true);
+ }
- /* delayed apply callbacks */
- ui_apply_but_funcs_after(C);
+ /* delayed apply callbacks */
+ ui_apply_but_funcs_after(C);
- return retval;
+ return retval;
}
static void ui_region_handler_remove(bContext *C, void *UNUSED(userdata))
{
- bScreen *sc;
- ARegion *ar;
+ bScreen *sc;
+ ARegion *ar;
- ar = CTX_wm_region(C);
- if (ar == NULL) {
- return;
- }
+ ar = CTX_wm_region(C);
+ if (ar == NULL) {
+ return;
+ }
- UI_blocklist_free(C, &ar->uiblocks);
+ UI_blocklist_free(C, &ar->uiblocks);
- sc = CTX_wm_screen(C);
- if (sc == NULL) {
- return;
- }
+ sc = CTX_wm_screen(C);
+ if (sc == 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) {
- ui_apply_but_funcs_after(C);
- }
+ /* 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) {
+ ui_apply_but_funcs_after(C);
+ }
}
/* handle buttons at the window level, modal, for example while
* number sliding, text editing, or when a menu block is open */
static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSED(userdata))
{
- ARegion *ar;
- uiBut *but;
- int retval = WM_UI_HANDLER_CONTINUE;
-
- ar = CTX_wm_menu(C);
- if (!ar) {
- ar = CTX_wm_region(C);
- }
-
- but = ui_region_find_active_but(ar);
-
- if (but) {
- bScreen *screen = CTX_wm_screen(C);
- ARegion *ar_temp;
- uiBut *but_other;
- uiHandleButtonData *data;
- bool is_inside_menu = false;
-
- /* look for a popup menu containing the mouse */
- for (ar_temp = screen->regionbase.first; ar_temp; ar_temp = ar_temp->next) {
- rcti winrct;
-
- ui_region_winrct_get_no_margin(ar_temp, &winrct);
-
- if (BLI_rcti_isect_pt_v(&winrct, &event->x)) {
- BLI_assert(ar_temp->type->regionid == RGN_TYPE_TEMPORARY);
-
- is_inside_menu = true;
- break;
- }
- }
-
- /* handle activated button events */
- data = but->active;
-
- if ((data->state == BUTTON_STATE_MENU_OPEN) &&
- /* make sure mouse isn't inside another menu (see T43247) */
- (is_inside_menu == false) &&
- (ELEM(but->type, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) &&
- (but_other = ui_but_find_mouse_over(ar, event)) &&
- (but != but_other) &&
- (ELEM(but_other->type, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)))
- {
- /* 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);
- button_activate_state(C, but_other, BUTTON_STATE_MENU_OPEN);
- retval = WM_UI_HANDLER_BREAK;
- }
- }
- else if (data->state == BUTTON_STATE_MENU_OPEN) {
- /* handle events for menus and their buttons recursively,
- * this will handle events from the top to the bottom menu */
- if (data->menu) {
- retval = ui_handle_menus_recursive(C, event, data->menu, 0, false, false, false);
- }
-
- /* handle events for the activated button */
- if ((data->menu && (retval == WM_UI_HANDLER_CONTINUE)) ||
- (event->type == TIMER))
- {
- if (data->menu && data->menu->menuretval) {
- ui_handle_button_return_submenu(C, event, but);
- retval = WM_UI_HANDLER_BREAK;
- }
- else {
- retval = ui_handle_button_event(C, event, but);
- }
- }
- }
- else {
- /* handle events for the activated button */
- retval = ui_handle_button_event(C, event, but);
- }
- }
-
- /* re-enable tooltips */
- if (event->type == MOUSEMOVE && (event->x != event->prevx || event->y != event->prevy)) {
- ui_blocks_set_tooltips(ar, true);
- }
-
- /* delayed apply callbacks */
- ui_apply_but_funcs_after(C);
-
- /* Don't handle double-click events,
- * these will be converted into regular clicks which we handle. */
- if (retval == WM_UI_HANDLER_CONTINUE) {
- if (event->val == KM_DBL_CLICK) {
- return WM_UI_HANDLER_CONTINUE;
- }
- }
-
- /* we block all events, this is modal interaction */
- return WM_UI_HANDLER_BREAK;
+ ARegion *ar;
+ uiBut *but;
+ int retval = WM_UI_HANDLER_CONTINUE;
+
+ ar = CTX_wm_menu(C);
+ if (!ar) {
+ ar = CTX_wm_region(C);
+ }
+
+ but = ui_region_find_active_but(ar);
+
+ if (but) {
+ bScreen *screen = CTX_wm_screen(C);
+ ARegion *ar_temp;
+ uiBut *but_other;
+ uiHandleButtonData *data;
+ bool is_inside_menu = false;
+
+ /* look for a popup menu containing the mouse */
+ for (ar_temp = screen->regionbase.first; ar_temp; ar_temp = ar_temp->next) {
+ rcti winrct;
+
+ ui_region_winrct_get_no_margin(ar_temp, &winrct);
+
+ if (BLI_rcti_isect_pt_v(&winrct, &event->x)) {
+ BLI_assert(ar_temp->type->regionid == RGN_TYPE_TEMPORARY);
+
+ is_inside_menu = true;
+ break;
+ }
+ }
+
+ /* handle activated button events */
+ data = but->active;
+
+ if ((data->state == BUTTON_STATE_MENU_OPEN) &&
+ /* make sure mouse isn't inside another menu (see T43247) */
+ (is_inside_menu == false) && (ELEM(but->type, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) &&
+ (but_other = ui_but_find_mouse_over(ar, event)) && (but != but_other) &&
+ (ELEM(but_other->type, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER))) {
+ /* 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);
+ button_activate_state(C, but_other, BUTTON_STATE_MENU_OPEN);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if (data->state == BUTTON_STATE_MENU_OPEN) {
+ /* handle events for menus and their buttons recursively,
+ * this will handle events from the top to the bottom menu */
+ if (data->menu) {
+ retval = ui_handle_menus_recursive(C, event, data->menu, 0, false, false, false);
+ }
+
+ /* handle events for the activated button */
+ if ((data->menu && (retval == WM_UI_HANDLER_CONTINUE)) || (event->type == TIMER)) {
+ if (data->menu && data->menu->menuretval) {
+ ui_handle_button_return_submenu(C, event, but);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else {
+ retval = ui_handle_button_event(C, event, but);
+ }
+ }
+ }
+ else {
+ /* handle events for the activated button */
+ retval = ui_handle_button_event(C, event, but);
+ }
+ }
+
+ /* re-enable tooltips */
+ if (event->type == MOUSEMOVE && (event->x != event->prevx || event->y != event->prevy)) {
+ ui_blocks_set_tooltips(ar, true);
+ }
+
+ /* delayed apply callbacks */
+ ui_apply_but_funcs_after(C);
+
+ /* Don't handle double-click events,
+ * these will be converted into regular clicks which we handle. */
+ if (retval == WM_UI_HANDLER_CONTINUE) {
+ if (event->val == KM_DBL_CLICK) {
+ return WM_UI_HANDLER_CONTINUE;
+ }
+ }
+
+ /* we block all events, this is modal interaction */
+ return WM_UI_HANDLER_BREAK;
}
/* two types of popups, one with operator + enum, other with regular callbacks */
static int ui_popup_handler(bContext *C, const wmEvent *event, void *userdata)
{
- uiPopupBlockHandle *menu = userdata;
- struct ARegion *menu_region;
- /* we block all events, this is modal interaction,
- * except for drop events which is described below */
- int retval = WM_UI_HANDLER_BREAK;
- bool reset_pie = false;
-
- menu_region = CTX_wm_menu(C);
- CTX_wm_menu_set(C, menu->region);
-
- if (event->type == EVT_DROP || event->val == KM_DBL_CLICK) {
- /* EVT_DROP:
- * If we're handling drop event we'll want it to be handled by popup callee as well,
- * so it'll be possible to perform such operations as opening .blend files by dropping
- * them into blender, even if there's opened popup like splash screen (sergey).
- * KM_DBL_CLICK:
- * Continue in case of double click so wm_handlers_do calls handler again with KM_PRESS
- * event. This is needed to ensure correct button handling for fast clicking (T47532).
- */
-
- retval = WM_UI_HANDLER_CONTINUE;
- }
-
- ui_handle_menus_recursive(C, event, menu, 0, false, false, true);
-
- /* free if done, does not free handle itself */
- if (menu->menuretval) {
- wmWindow *win = CTX_wm_window(C);
- /* copy values, we have to free first (closes region) */
- uiPopupBlockHandle temp = *menu;
- uiBlock *block = menu->region->uiblocks.first;
-
- /* set last pie event to allow chained pie spawning */
- if (block->flag & UI_BLOCK_RADIAL) {
- win->last_pie_event = block->pie_data.event;
- reset_pie = true;
- }
-
- ui_popup_block_free(C, menu);
- UI_popup_handlers_remove(&win->modalhandlers, menu);
- CTX_wm_menu_set(C, NULL);
+ uiPopupBlockHandle *menu = userdata;
+ struct ARegion *menu_region;
+ /* we block all events, this is modal interaction,
+ * except for drop events which is described below */
+ int retval = WM_UI_HANDLER_BREAK;
+ bool reset_pie = false;
+
+ menu_region = CTX_wm_menu(C);
+ CTX_wm_menu_set(C, menu->region);
+
+ if (event->type == EVT_DROP || event->val == KM_DBL_CLICK) {
+ /* EVT_DROP:
+ * If we're handling drop event we'll want it to be handled by popup callee as well,
+ * so it'll be possible to perform such operations as opening .blend files by dropping
+ * them into blender, even if there's opened popup like splash screen (sergey).
+ * KM_DBL_CLICK:
+ * Continue in case of double click so wm_handlers_do calls handler again with KM_PRESS
+ * event. This is needed to ensure correct button handling for fast clicking (T47532).
+ */
+
+ retval = WM_UI_HANDLER_CONTINUE;
+ }
+
+ ui_handle_menus_recursive(C, event, menu, 0, false, false, true);
+
+ /* free if done, does not free handle itself */
+ if (menu->menuretval) {
+ wmWindow *win = CTX_wm_window(C);
+ /* copy values, we have to free first (closes region) */
+ uiPopupBlockHandle temp = *menu;
+ uiBlock *block = menu->region->uiblocks.first;
+
+ /* set last pie event to allow chained pie spawning */
+ if (block->flag & UI_BLOCK_RADIAL) {
+ win->last_pie_event = block->pie_data.event;
+ reset_pie = true;
+ }
+
+ ui_popup_block_free(C, menu);
+ UI_popup_handlers_remove(&win->modalhandlers, menu);
+ CTX_wm_menu_set(C, NULL);
#ifdef USE_DRAG_TOGGLE
- {
- WM_event_free_ui_handler_all(
- C, &win->modalhandlers,
- ui_handler_region_drag_toggle, ui_handler_region_drag_toggle_remove);
- }
+ {
+ WM_event_free_ui_handler_all(C,
+ &win->modalhandlers,
+ ui_handler_region_drag_toggle,
+ ui_handler_region_drag_toggle_remove);
+ }
#endif
- if ((temp.menuretval & UI_RETURN_OK) || (temp.menuretval & UI_RETURN_POPUP_OK)) {
- 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);
- }
+ if ((temp.menuretval & UI_RETURN_OK) || (temp.menuretval & UI_RETURN_POPUP_OK)) {
+ 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);
- }
- else {
- /* re-enable tooltips */
- if (event->type == MOUSEMOVE && (event->x != event->prevx || event->y != event->prevy)) {
- ui_blocks_set_tooltips(menu->region, true);
- }
- }
+ WM_event_add_mousemove(C);
+ }
+ else {
+ /* re-enable tooltips */
+ if (event->type == MOUSEMOVE && (event->x != event->prevx || event->y != event->prevy)) {
+ ui_blocks_set_tooltips(menu->region, true);
+ }
+ }
- /* delayed apply callbacks */
- ui_apply_but_funcs_after(C);
+ /* delayed apply callbacks */
+ ui_apply_but_funcs_after(C);
- if (reset_pie) {
- /* reaqcuire window in case pie invalidates it somehow */
- wmWindow *win = CTX_wm_window(C);
+ if (reset_pie) {
+ /* reaqcuire window in case pie invalidates it somehow */
+ wmWindow *win = CTX_wm_window(C);
- if (win) {
- win->last_pie_event = EVENT_NONE;
- }
- }
+ if (win) {
+ win->last_pie_event = EVENT_NONE;
+ }
+ }
- CTX_wm_region_set(C, menu_region);
+ CTX_wm_region_set(C, menu_region);
- return retval;
+ return retval;
}
static void ui_popup_handler_remove(bContext *C, void *userdata)
{
- uiPopupBlockHandle *menu = userdata;
+ uiPopupBlockHandle *menu = userdata;
- /* More correct would be to expect UI_RETURN_CANCEL here, but not wanting to
- * cancel when removing handlers because of file exit is a rare exception.
- * So instead of setting cancel flag for all menus before removing handlers,
- * just explicitly flag menu with UI_RETURN_OK to avoid cancelling it. */
- if ((menu->menuretval & UI_RETURN_OK) == 0 && menu->cancel_func) {
- menu->cancel_func(C, menu->popup_arg);
- }
+ /* More correct would be to expect UI_RETURN_CANCEL here, but not wanting to
+ * cancel when removing handlers because of file exit is a rare exception.
+ * So instead of setting cancel flag for all menus before removing handlers,
+ * just explicitly flag menu with UI_RETURN_OK to avoid cancelling it. */
+ if ((menu->menuretval & UI_RETURN_OK) == 0 && menu->cancel_func) {
+ menu->cancel_func(C, menu->popup_arg);
+ }
- /* free menu block if window is closed for some reason */
- ui_popup_block_free(C, menu);
+ /* free menu block if window is closed for some reason */
+ ui_popup_block_free(C, menu);
- /* delayed apply callbacks */
- ui_apply_but_funcs_after(C);
+ /* delayed apply callbacks */
+ ui_apply_but_funcs_after(C);
}
void UI_region_handlers_add(ListBase *handlers)
{
- WM_event_remove_ui_handler(handlers, ui_region_handler, ui_region_handler_remove, NULL, false);
- WM_event_add_ui_handler(NULL, handlers, ui_region_handler, ui_region_handler_remove, NULL, 0);
+ WM_event_remove_ui_handler(handlers, ui_region_handler, ui_region_handler_remove, NULL, false);
+ WM_event_add_ui_handler(NULL, handlers, ui_region_handler, ui_region_handler_remove, NULL, 0);
}
-void UI_popup_handlers_add(bContext *C, ListBase *handlers, uiPopupBlockHandle *popup, const char flag)
+void UI_popup_handlers_add(bContext *C,
+ ListBase *handlers,
+ uiPopupBlockHandle *popup,
+ const char flag)
{
- WM_event_add_ui_handler(C, handlers, ui_popup_handler, ui_popup_handler_remove, popup, flag);
+ WM_event_add_ui_handler(C, handlers, ui_popup_handler, ui_popup_handler_remove, popup, flag);
}
void UI_popup_handlers_remove(ListBase *handlers, uiPopupBlockHandle *popup)
{
- LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) {
- if (handler_base->type == WM_HANDLER_TYPE_UI) {
- wmEventHandler_UI *handler = (wmEventHandler_UI *)handler_base;
-
- if (handler->handle_fn == ui_popup_handler &&
- handler->remove_fn == ui_popup_handler_remove &&
- handler->user_data == popup)
- {
- /* tag refresh parent popup */
- wmEventHandler_UI *handler_next = (wmEventHandler_UI *)handler->head.next;
- if (handler_next &&
- handler_next->head.type == WM_HANDLER_TYPE_UI &&
- handler_next->handle_fn == ui_popup_handler &&
- handler_next->remove_fn == ui_popup_handler_remove)
- {
- uiPopupBlockHandle *parent_popup = handler_next->user_data;
- ED_region_tag_refresh_ui(parent_popup->region);
- }
- break;
- }
- }
- }
-
- WM_event_remove_ui_handler(handlers, ui_popup_handler, ui_popup_handler_remove, popup, false);
-}
+ LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) {
+ if (handler_base->type == WM_HANDLER_TYPE_UI) {
+ wmEventHandler_UI *handler = (wmEventHandler_UI *)handler_base;
-void UI_popup_handlers_remove_all(bContext *C, ListBase *handlers)
-{
- WM_event_free_ui_handler_all(C, handlers, ui_popup_handler, ui_popup_handler_remove);
+ if (handler->handle_fn == ui_popup_handler &&
+ handler->remove_fn == ui_popup_handler_remove && handler->user_data == popup) {
+ /* tag refresh parent popup */
+ wmEventHandler_UI *handler_next = (wmEventHandler_UI *)handler->head.next;
+ if (handler_next && handler_next->head.type == WM_HANDLER_TYPE_UI &&
+ handler_next->handle_fn == ui_popup_handler &&
+ handler_next->remove_fn == ui_popup_handler_remove) {
+ uiPopupBlockHandle *parent_popup = handler_next->user_data;
+ ED_region_tag_refresh_ui(parent_popup->region);
+ }
+ break;
+ }
+ }
+ }
+
+ WM_event_remove_ui_handler(handlers, ui_popup_handler, ui_popup_handler_remove, popup, false);
}
-bool UI_textbutton_activate_rna(
- const bContext *C, ARegion *ar,
- const void *rna_poin_data, const char *rna_prop_id)
+void UI_popup_handlers_remove_all(bContext *C, ListBase *handlers)
{
- uiBlock *block;
- uiBut *but = NULL;
-
- for (block = ar->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) {
- if (STREQ(RNA_property_identifier(but->rnaprop), rna_prop_id)) {
- break;
- }
- }
- }
- }
- if (but) {
- break;
- }
- }
-
- if (but) {
- UI_but_active_only(C, ar, block, but);
- return true;
- }
- else {
- return false;
- }
+ WM_event_free_ui_handler_all(C, handlers, ui_popup_handler, ui_popup_handler_remove);
+}
+
+bool UI_textbutton_activate_rna(const bContext *C,
+ ARegion *ar,
+ 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 (but = block->buttons.first; but; but = but->next) {
+ if (but->type == UI_BTYPE_TEXT) {
+ if (but->rnaprop && but->rnapoin.data == rna_poin_data) {
+ if (STREQ(RNA_property_identifier(but->rnaprop), rna_prop_id)) {
+ break;
+ }
+ }
+ }
+ }
+ if (but) {
+ break;
+ }
+ }
+
+ if (but) {
+ UI_but_active_only(C, ar, block, but);
+ return true;
+ }
+ else {
+ return false;
+ }
}
bool UI_textbutton_activate_but(const bContext *C, uiBut *actbut)
{
- ARegion *ar = CTX_wm_region(C);
- uiBlock *block;
- uiBut *but = NULL;
+ ARegion *ar = CTX_wm_region(C);
+ uiBlock *block;
+ uiBut *but = NULL;
- for (block = ar->uiblocks.first; block; block = block->next) {
- for (but = block->buttons.first; but; but = but->next) {
- if (but == actbut && but->type == UI_BTYPE_TEXT) {
- break;
- }
- }
+ for (block = ar->uiblocks.first; block; block = block->next) {
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but == actbut && but->type == UI_BTYPE_TEXT) {
+ break;
+ }
+ }
- if (but) {
- break;
- }
- }
+ if (but) {
+ break;
+ }
+ }
- if (but) {
- UI_but_active_only(C, ar, block, but);
- return true;
- }
- else {
- return false;
- }
+ if (but) {
+ UI_but_active_only(C, ar, block, but);
+ return true;
+ }
+ else {
+ return false;
+ }
}
/** \} */
@@ -10273,54 +10315,54 @@ bool UI_textbutton_activate_but(const bContext *C, uiBut *actbut)
/* is called by notifier */
void UI_screen_free_active_but(const bContext *C, bScreen *screen)
{
- wmWindow *win = CTX_wm_window(C);
+ wmWindow *win = CTX_wm_window(C);
- ED_screen_areas_iter(win, screen, area) {
- for (ARegion *region = area->regionbase.first; region; region = region->next) {
- uiBut *but = ui_region_find_active_but(region);
- if (but) {
- uiHandleButtonData *data = but->active;
+ ED_screen_areas_iter(win, screen, area)
+ {
+ for (ARegion *region = area->regionbase.first; region; region = region->next) {
+ uiBut *but = ui_region_find_active_but(region);
+ if (but) {
+ uiHandleButtonData *data = but->active;
- if (data->menu == NULL && data->searchbox == NULL) {
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- ui_but_active_free(C, but);
- }
- }
- }
- }
- }
+ if (data->menu == NULL && data->searchbox == NULL) {
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ ui_but_active_free(C, but);
+ }
+ }
+ }
+ }
+ }
}
-
/* returns true if highlighted button allows drop of names */
/* 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 *ar = CTX_wm_region(C);
+ uiBut *but = ui_region_find_active_but(ar);
- if (but) {
- if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
- return 1;
- }
- }
+ if (but) {
+ if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
+ return 1;
+ }
+ }
- return 0;
+ return 0;
}
bool UI_but_active_drop_color(bContext *C)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *ar = CTX_wm_region(C);
- if (ar) {
- uiBut *but = ui_region_find_active_but(ar);
+ if (ar) {
+ uiBut *but = ui_region_find_active_but(ar);
- if (but && but->type == UI_BTYPE_COLOR) {
- return true;
- }
- }
+ if (but && but->type == UI_BTYPE_COLOR) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
/** \} */
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index dcfeaf64699..e2a75abebd7 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -80,74 +80,74 @@
#include "interface_intern.h"
#ifndef WITH_HEADLESS
-#define ICON_GRID_COLS 26
-#define ICON_GRID_ROWS 30
+# define ICON_GRID_COLS 26
+# define ICON_GRID_ROWS 30
-#define ICON_GRID_MARGIN 10
-#define ICON_GRID_W 32
-#define ICON_GRID_H 32
-#endif /* WITH_HEADLESS */
+# define ICON_GRID_MARGIN 10
+# define ICON_GRID_W 32
+# define ICON_GRID_H 32
+#endif /* WITH_HEADLESS */
typedef struct IconImage {
- int w;
- int h;
- uint *rect;
- const uchar *datatoc_rect;
- int datatoc_size;
+ int w;
+ int h;
+ uint *rect;
+ const uchar *datatoc_rect;
+ int datatoc_size;
} IconImage;
typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
-#define ICON_TYPE_PREVIEW 0
-#define ICON_TYPE_COLOR_TEXTURE 1
-#define ICON_TYPE_MONO_TEXTURE 2
-#define ICON_TYPE_BUFFER 3
-#define ICON_TYPE_VECTOR 4
-#define ICON_TYPE_GEOM 5
-#define ICON_TYPE_EVENT 6 /* draw keymap entries using custom renderer. */
-#define ICON_TYPE_GPLAYER 7
-#define ICON_TYPE_BLANK 8
+#define ICON_TYPE_PREVIEW 0
+#define ICON_TYPE_COLOR_TEXTURE 1
+#define ICON_TYPE_MONO_TEXTURE 2
+#define ICON_TYPE_BUFFER 3
+#define ICON_TYPE_VECTOR 4
+#define ICON_TYPE_GEOM 5
+#define ICON_TYPE_EVENT 6 /* draw keymap entries using custom renderer. */
+#define ICON_TYPE_GPLAYER 7
+#define ICON_TYPE_BLANK 8
typedef struct DrawInfo {
- int type;
-
- union {
- /* type specific data */
- struct {
- VectorDrawFunc func;
- } vector;
- struct {
- ImBuf *image_cache;
- } geom;
- struct {
- IconImage *image;
- } buffer;
- struct {
- int x, y, w, h;
- int theme_color;
- } texture;
- struct {
- /* Can be packed into a single int. */
- short event_type;
- short event_value;
- int icon;
- /* Allow lookups. */
- struct DrawInfo *next;
- } input;
- } data;
+ int type;
+
+ union {
+ /* type specific data */
+ struct {
+ VectorDrawFunc func;
+ } vector;
+ struct {
+ ImBuf *image_cache;
+ } geom;
+ struct {
+ IconImage *image;
+ } buffer;
+ struct {
+ int x, y, w, h;
+ int theme_color;
+ } texture;
+ struct {
+ /* Can be packed into a single int. */
+ short event_type;
+ short event_value;
+ int icon;
+ /* Allow lookups. */
+ struct DrawInfo *next;
+ } input;
+ } data;
} DrawInfo;
typedef struct IconTexture {
- GLuint id;
- int w;
- int h;
- float invw;
- float invh;
+ GLuint id;
+ int w;
+ int h;
+ float invw;
+ float invh;
} IconTexture;
typedef struct IconType {
- int type;
- int theme_color;
+ int type;
+ int theme_color;
} IconType;
/* ******************* STATIC LOCAL VARS ******************* */
@@ -159,93 +159,95 @@ static IconTexture icongltex = {0, 0, 0, 0.0f, 0.0f};
#ifndef WITH_HEADLESS
static const IconType icontypes[] = {
-#define DEF_ICON(name) {ICON_TYPE_MONO_TEXTURE, 0},
-#define DEF_ICON_COLLECTION(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_COLLECTION},
-#define DEF_ICON_OBJECT(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_OBJECT},
-#define DEF_ICON_OBJECT_DATA(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_OBJECT_DATA},
-#define DEF_ICON_MODIFIER(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_MODIFIER},
-#define DEF_ICON_SHADING(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_SHADING},
-#define DEF_ICON_VECTOR(name) {ICON_TYPE_VECTOR, 0},
-#define DEF_ICON_COLOR(name) {ICON_TYPE_COLOR_TEXTURE, 0},
-#define DEF_ICON_BLANK(name) {ICON_TYPE_BLANK, 0},
-#include "UI_icons.h"
+# define DEF_ICON(name) {ICON_TYPE_MONO_TEXTURE, 0},
+# define DEF_ICON_COLLECTION(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_COLLECTION},
+# define DEF_ICON_OBJECT(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_OBJECT},
+# define DEF_ICON_OBJECT_DATA(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_OBJECT_DATA},
+# define DEF_ICON_MODIFIER(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_MODIFIER},
+# define DEF_ICON_SHADING(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_SHADING},
+# define DEF_ICON_VECTOR(name) {ICON_TYPE_VECTOR, 0},
+# define DEF_ICON_COLOR(name) {ICON_TYPE_COLOR_TEXTURE, 0},
+# define DEF_ICON_BLANK(name) {ICON_TYPE_BLANK, 0},
+# include "UI_icons.h"
};
/* **************************************************** */
-static DrawInfo *def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int size, int type, int theme_color)
+static DrawInfo *def_internal_icon(
+ ImBuf *bbuf, int icon_id, int xofs, int yofs, int size, int type, int theme_color)
{
- Icon *new_icon = NULL;
- IconImage *iimg = NULL;
- DrawInfo *di;
+ Icon *new_icon = NULL;
+ IconImage *iimg = NULL;
+ DrawInfo *di;
- new_icon = MEM_callocN(sizeof(Icon), "texicon");
+ new_icon = MEM_callocN(sizeof(Icon), "texicon");
- new_icon->obj = NULL; /* icon is not for library object */
- new_icon->id_type = 0;
+ new_icon->obj = NULL; /* icon is not for library object */
+ new_icon->id_type = 0;
- di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
- di->type = type;
+ di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
+ di->type = type;
- if (ELEM(type, ICON_TYPE_COLOR_TEXTURE, ICON_TYPE_MONO_TEXTURE)) {
- di->data.texture.theme_color = theme_color;
- di->data.texture.x = xofs;
- di->data.texture.y = yofs;
- di->data.texture.w = size;
- di->data.texture.h = size;
- }
- else if (type == ICON_TYPE_BUFFER) {
- iimg = MEM_callocN(sizeof(IconImage), "icon_img");
- iimg->w = size;
- iimg->h = size;
+ if (ELEM(type, ICON_TYPE_COLOR_TEXTURE, ICON_TYPE_MONO_TEXTURE)) {
+ di->data.texture.theme_color = theme_color;
+ di->data.texture.x = xofs;
+ di->data.texture.y = yofs;
+ di->data.texture.w = size;
+ di->data.texture.h = size;
+ }
+ else if (type == ICON_TYPE_BUFFER) {
+ iimg = MEM_callocN(sizeof(IconImage), "icon_img");
+ iimg->w = size;
+ iimg->h = size;
- /* icon buffers can get initialized runtime now, via datatoc */
- if (bbuf) {
- int y, imgsize;
+ /* icon buffers can get initialized runtime now, via datatoc */
+ if (bbuf) {
+ int y, imgsize;
- iimg->rect = MEM_mallocN(size * size * sizeof(uint), "icon_rect");
+ iimg->rect = MEM_mallocN(size * size * sizeof(uint), "icon_rect");
- /* Here we store the rect in the icon - same as before */
- if (size == bbuf->x && size == bbuf->y && xofs == 0 && yofs == 0) {
- memcpy(iimg->rect, bbuf->rect, size * size * sizeof(int));
- }
- else {
- /* this code assumes square images */
- imgsize = bbuf->x;
- for (y = 0; y < size; y++) {
- memcpy(&iimg->rect[y * size], &bbuf->rect[(y + yofs) * imgsize + xofs], size * sizeof(int));
- }
- }
- }
- di->data.buffer.image = iimg;
- }
+ /* Here we store the rect in the icon - same as before */
+ if (size == bbuf->x && size == bbuf->y && xofs == 0 && yofs == 0) {
+ memcpy(iimg->rect, bbuf->rect, size * size * sizeof(int));
+ }
+ else {
+ /* this code assumes square images */
+ imgsize = bbuf->x;
+ for (y = 0; y < size; y++) {
+ memcpy(
+ &iimg->rect[y * size], &bbuf->rect[(y + yofs) * imgsize + xofs], size * sizeof(int));
+ }
+ }
+ }
+ di->data.buffer.image = iimg;
+ }
- new_icon->drawinfo_free = UI_icons_free_drawinfo;
- new_icon->drawinfo = di;
+ new_icon->drawinfo_free = UI_icons_free_drawinfo;
+ new_icon->drawinfo = di;
- BKE_icon_set(icon_id, new_icon);
+ BKE_icon_set(icon_id, new_icon);
- return di;
+ return di;
}
static void def_internal_vicon(int icon_id, VectorDrawFunc drawFunc)
{
- Icon *new_icon = NULL;
- DrawInfo *di;
+ Icon *new_icon = NULL;
+ DrawInfo *di;
- new_icon = MEM_callocN(sizeof(Icon), "texicon");
+ new_icon = MEM_callocN(sizeof(Icon), "texicon");
- new_icon->obj = NULL; /* icon is not for library object */
- new_icon->id_type = 0;
+ new_icon->obj = NULL; /* icon is not for library object */
+ new_icon->id_type = 0;
- di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
- di->type = ICON_TYPE_VECTOR;
- di->data.vector.func = drawFunc;
+ di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
+ di->type = ICON_TYPE_VECTOR;
+ di->data.vector.func = drawFunc;
- new_icon->drawinfo_free = NULL;
- new_icon->drawinfo = di;
+ new_icon->drawinfo_free = NULL;
+ new_icon->drawinfo = di;
- BKE_icon_set(icon_id, new_icon);
+ BKE_icon_set(icon_id, new_icon);
}
/* Vector Icon Drawing Routines */
@@ -254,168 +256,184 @@ static void def_internal_vicon(int icon_id, VectorDrawFunc drawFunc)
static void viconutil_set_point(GLint pt[2], int x, int y)
{
- pt[0] = x;
- pt[1] = y;
+ pt[0] = x;
+ pt[1] = y;
}
static void vicon_small_tri_right_draw(int x, int y, int w, int UNUSED(h), float alpha)
{
- GLint pts[3][2];
- int cx = x + w / 2 - 4;
- int cy = y + w / 2;
- int d = w / 5, d2 = w / 7;
-
- viconutil_set_point(pts[0], cx - d2, cy + d);
- viconutil_set_point(pts[1], cx - d2, cy - d);
- viconutil_set_point(pts[2], cx + d2, cy);
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4f(0.2f, 0.2f, 0.2f, alpha);
-
- immBegin(GPU_PRIM_TRIS, 3);
- immVertex2iv(pos, pts[0]);
- immVertex2iv(pos, pts[1]);
- immVertex2iv(pos, pts[2]);
- immEnd();
-
- immUnbindProgram();
-}
-
-static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha, short key_type, short handle_type)
-{
- /* init dummy theme state for Action Editor - where these colors are defined
- * (since we're doing this offscreen, free from any particular space_id)
- */
- struct bThemeState theme_state;
-
- UI_Theme_Store(&theme_state);
- UI_SetTheme(SPACE_ACTION, RGN_TYPE_WINDOW);
-
- /* the "x" and "y" given are the bottom-left coordinates of the icon,
- * while the draw_keyframe_shape() function needs the midpoint for
- * the keyframe
- */
- float xco = x + w / 2 + 0.5f;
- float yco = y + h / 2 + 0.5f;
-
- GPUVertFormat *format = immVertexFormat();
- uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- uint outline_color_id = GPU_vertformat_attr_add(format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
-
- immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
- GPU_enable_program_point_size();
- immUniform2f("ViewportSize", -1.0f, -1.0f);
- immBegin(GPU_PRIM_POINTS, 1);
-
- /* draw keyframe
- * - size: (default icon size == 16, default dopesheet icon size == 10)
- * - sel: true unless in handletype icons (so that "keyframe" state shows the iconic yellow icon)
- */
- bool sel = (handle_type == KEYFRAME_HANDLE_NONE);
-
- draw_keyframe_shape(xco, yco, (10.0f / 16.0f) * h, sel, key_type, KEYFRAME_SHAPE_BOTH, alpha,
- pos_id, size_id, color_id, outline_color_id,
- flags_id, handle_type, KEYFRAME_EXTREME_NONE);
-
- immEnd();
- GPU_disable_program_point_size();
- immUnbindProgram();
-
- UI_Theme_Restore(&theme_state);
+ GLint pts[3][2];
+ int cx = x + w / 2 - 4;
+ int cy = y + w / 2;
+ int d = w / 5, d2 = w / 7;
+
+ viconutil_set_point(pts[0], cx - d2, cy + d);
+ viconutil_set_point(pts[1], cx - d2, cy - d);
+ viconutil_set_point(pts[2], cx + d2, cy);
+
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4f(0.2f, 0.2f, 0.2f, alpha);
+
+ immBegin(GPU_PRIM_TRIS, 3);
+ immVertex2iv(pos, pts[0]);
+ immVertex2iv(pos, pts[1]);
+ immVertex2iv(pos, pts[2]);
+ immEnd();
+
+ immUnbindProgram();
+}
+
+static void vicon_keytype_draw_wrapper(
+ int x, int y, int w, int h, float alpha, short key_type, short handle_type)
+{
+ /* init dummy theme state for Action Editor - where these colors are defined
+ * (since we're doing this offscreen, free from any particular space_id)
+ */
+ struct bThemeState theme_state;
+
+ UI_Theme_Store(&theme_state);
+ UI_SetTheme(SPACE_ACTION, RGN_TYPE_WINDOW);
+
+ /* the "x" and "y" given are the bottom-left coordinates of the icon,
+ * while the draw_keyframe_shape() function needs the midpoint for
+ * the keyframe
+ */
+ float xco = x + w / 2 + 0.5f;
+ float yco = y + h / 2 + 0.5f;
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uint color_id = GPU_vertformat_attr_add(
+ format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ uint outline_color_id = GPU_vertformat_attr_add(
+ format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
+
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ GPU_enable_program_point_size();
+ immUniform2f("ViewportSize", -1.0f, -1.0f);
+ immBegin(GPU_PRIM_POINTS, 1);
+
+ /* draw keyframe
+ * - size: (default icon size == 16, default dopesheet icon size == 10)
+ * - sel: true unless in handletype icons (so that "keyframe" state shows the iconic yellow icon)
+ */
+ bool sel = (handle_type == KEYFRAME_HANDLE_NONE);
+
+ draw_keyframe_shape(xco,
+ yco,
+ (10.0f / 16.0f) * h,
+ sel,
+ key_type,
+ KEYFRAME_SHAPE_BOTH,
+ alpha,
+ pos_id,
+ size_id,
+ color_id,
+ outline_color_id,
+ flags_id,
+ handle_type,
+ KEYFRAME_EXTREME_NONE);
+
+ immEnd();
+ GPU_disable_program_point_size();
+ immUnbindProgram();
+
+ UI_Theme_Restore(&theme_state);
}
static void vicon_keytype_keyframe_draw(int x, int y, int w, int h, float alpha)
{
- vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_KEYFRAME, KEYFRAME_HANDLE_NONE);
+ vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_KEYFRAME, KEYFRAME_HANDLE_NONE);
}
static void vicon_keytype_breakdown_draw(int x, int y, int w, int h, float alpha)
{
- vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_BREAKDOWN, KEYFRAME_HANDLE_NONE);
+ vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_BREAKDOWN, KEYFRAME_HANDLE_NONE);
}
static void vicon_keytype_extreme_draw(int x, int y, int w, int h, float alpha)
{
- vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_EXTREME, KEYFRAME_HANDLE_NONE);
+ vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_EXTREME, KEYFRAME_HANDLE_NONE);
}
static void vicon_keytype_jitter_draw(int x, int y, int w, int h, float alpha)
{
- vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_JITTER, KEYFRAME_HANDLE_NONE);
+ vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_JITTER, KEYFRAME_HANDLE_NONE);
}
static void vicon_keytype_moving_hold_draw(int x, int y, int w, int h, float alpha)
{
- vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_MOVEHOLD, KEYFRAME_HANDLE_NONE);
+ vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_MOVEHOLD, KEYFRAME_HANDLE_NONE);
}
static void vicon_handletype_free_draw(int x, int y, int w, int h, float alpha)
{
- vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_KEYFRAME, KEYFRAME_HANDLE_FREE);
+ vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_KEYFRAME, KEYFRAME_HANDLE_FREE);
}
static void vicon_handletype_aligned_draw(int x, int y, int w, int h, float alpha)
{
- vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_KEYFRAME, KEYFRAME_HANDLE_ALIGNED);
+ vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_KEYFRAME, KEYFRAME_HANDLE_ALIGNED);
}
static void vicon_handletype_vector_draw(int x, int y, int w, int h, float alpha)
{
- vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_KEYFRAME, KEYFRAME_HANDLE_VECTOR);
+ vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_KEYFRAME, KEYFRAME_HANDLE_VECTOR);
}
static void vicon_handletype_auto_draw(int x, int y, int w, int h, float alpha)
{
- vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_KEYFRAME, KEYFRAME_HANDLE_AUTO);
+ vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_KEYFRAME, KEYFRAME_HANDLE_AUTO);
}
static void vicon_handletype_auto_clamp_draw(int x, int y, int w, int h, float alpha)
{
- vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_KEYFRAME, KEYFRAME_HANDLE_AUTO_CLAMP);
+ vicon_keytype_draw_wrapper(x, y, w, h, alpha, BEZT_KEYTYPE_KEYFRAME, KEYFRAME_HANDLE_AUTO_CLAMP);
}
static void vicon_colorset_draw(int index, int x, int y, int w, int h, float UNUSED(alpha))
{
- bTheme *btheme = UI_GetTheme();
- ThemeWireColor *cs = &btheme->tarm[index];
+ bTheme *btheme = UI_GetTheme();
+ ThemeWireColor *cs = &btheme->tarm[index];
- /* Draw three bands of color: One per color
- * x-----a-----b-----c
- * | N | S | A |
- * x-----a-----b-----c
- */
- const int a = x + w / 3;
- const int b = x + w / 3 * 2;
- const int c = x + w;
+ /* Draw three bands of color: One per color
+ * x-----a-----b-----c
+ * | N | S | A |
+ * x-----a-----b-----c
+ */
+ const int a = x + w / 3;
+ const int b = x + w / 3 * 2;
+ const int c = x + w;
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- /* XXX: Include alpha into this... */
- /* normal */
- immUniformColor3ubv((uchar *)cs->solid);
- immRecti(pos, x, y, a, y + h);
+ /* XXX: Include alpha into this... */
+ /* normal */
+ immUniformColor3ubv((uchar *)cs->solid);
+ immRecti(pos, x, y, a, y + h);
- /* selected */
- immUniformColor3ubv((uchar *)cs->select);
- immRecti(pos, a, y, b, y + h);
+ /* selected */
+ immUniformColor3ubv((uchar *)cs->select);
+ immRecti(pos, a, y, b, y + h);
- /* active */
- immUniformColor3ubv((uchar *)cs->active);
- immRecti(pos, b, y, c, y + h);
+ /* active */
+ immUniformColor3ubv((uchar *)cs->active);
+ immRecti(pos, b, y, c, y + h);
- immUnbindProgram();
+ immUnbindProgram();
}
-#define DEF_ICON_VECTOR_COLORSET_DRAW_NTH(prefix, index) \
- static void vicon_colorset_draw_##prefix(int x, int y, int w, int h, float alpha) \
- { \
- vicon_colorset_draw(index, x, y, w, h, alpha); \
- }
+# define DEF_ICON_VECTOR_COLORSET_DRAW_NTH(prefix, index) \
+ static void vicon_colorset_draw_##prefix(int x, int y, int w, int h, float alpha) \
+ { \
+ vicon_colorset_draw(index, x, y, w, h, alpha); \
+ }
DEF_ICON_VECTOR_COLORSET_DRAW_NTH(01, 0)
DEF_ICON_VECTOR_COLORSET_DRAW_NTH(02, 1)
@@ -438,7 +456,7 @@ DEF_ICON_VECTOR_COLORSET_DRAW_NTH(18, 17)
DEF_ICON_VECTOR_COLORSET_DRAW_NTH(19, 18)
DEF_ICON_VECTOR_COLORSET_DRAW_NTH(20, 19)
-#undef DEF_ICON_VECTOR_COLORSET_DRAW_NTH
+# undef DEF_ICON_VECTOR_COLORSET_DRAW_NTH
/* Dynamically render icon instead of rendering a plain color to a texture/buffer
* This is mot strictly a "vicon", as it needs access to icon->obj to get the color info,
@@ -446,526 +464,559 @@ DEF_ICON_VECTOR_COLORSET_DRAW_NTH(20, 19)
*/
static void vicon_gplayer_color_draw(Icon *icon, int x, int y, int w, int h)
{
- bGPDlayer *gpl = (bGPDlayer *)icon->obj;
+ bGPDlayer *gpl = (bGPDlayer *)icon->obj;
- /* Just draw a colored rect - Like for vicon_colorset_draw() */
- /* TODO: Make this have rounded corners, and maybe be a bit smaller.
- * However, UI_draw_roundbox_aa() draws the colors too dark, so can't be used.
- */
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ /* Just draw a colored rect - Like for vicon_colorset_draw() */
+ /* TODO: Make this have rounded corners, and maybe be a bit smaller.
+ * However, UI_draw_roundbox_aa() draws the colors too dark, so can't be used.
+ */
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3fv(gpl->color);
- immRecti(pos, x, y, x + w - 1, y + h - 1);
+ immUniformColor3fv(gpl->color);
+ immRecti(pos, x, y, x + w - 1, y + h - 1);
- immUnbindProgram();
+ immUnbindProgram();
}
-
-#ifndef WITH_HEADLESS
+# ifndef WITH_HEADLESS
static void init_brush_icons(void)
{
-#define INIT_BRUSH_ICON(icon_id, name) \
- { \
- uchar *rect = (uchar *)datatoc_ ##name## _png; \
- int size = datatoc_ ##name## _png_size; \
- DrawInfo *di; \
- \
- di = def_internal_icon(NULL, icon_id, 0, 0, w, ICON_TYPE_BUFFER, 0); \
- di->data.buffer.image->datatoc_rect = rect; \
- di->data.buffer.image->datatoc_size = size; \
- } ((void)0)
- /* end INIT_BRUSH_ICON */
-
- const int w = 96; /* warning, brush size hardcoded in C, but it gets scaled */
-
- INIT_BRUSH_ICON(ICON_BRUSH_BLOB, blob);
- INIT_BRUSH_ICON(ICON_BRUSH_BLUR, blur);
- INIT_BRUSH_ICON(ICON_BRUSH_CLAY, clay);
- INIT_BRUSH_ICON(ICON_BRUSH_CLAY_STRIPS, claystrips);
- INIT_BRUSH_ICON(ICON_BRUSH_CLONE, clone);
- INIT_BRUSH_ICON(ICON_BRUSH_CREASE, crease);
- INIT_BRUSH_ICON(ICON_BRUSH_SCULPT_DRAW, draw);
- INIT_BRUSH_ICON(ICON_BRUSH_FILL, fill);
- INIT_BRUSH_ICON(ICON_BRUSH_FLATTEN, flatten);
- INIT_BRUSH_ICON(ICON_BRUSH_GRAB, grab);
- INIT_BRUSH_ICON(ICON_BRUSH_INFLATE, inflate);
- INIT_BRUSH_ICON(ICON_BRUSH_LAYER, layer);
- INIT_BRUSH_ICON(ICON_BRUSH_MASK, mask);
- INIT_BRUSH_ICON(ICON_BRUSH_MIX, mix);
- INIT_BRUSH_ICON(ICON_BRUSH_NUDGE, nudge);
- INIT_BRUSH_ICON(ICON_BRUSH_PINCH, pinch);
- INIT_BRUSH_ICON(ICON_BRUSH_SCRAPE, scrape);
- INIT_BRUSH_ICON(ICON_BRUSH_SMEAR, smear);
- INIT_BRUSH_ICON(ICON_BRUSH_SMOOTH, smooth);
- INIT_BRUSH_ICON(ICON_BRUSH_SNAKE_HOOK, snake_hook);
- INIT_BRUSH_ICON(ICON_BRUSH_SOFTEN, soften);
- INIT_BRUSH_ICON(ICON_BRUSH_TEXDRAW, texdraw);
- INIT_BRUSH_ICON(ICON_BRUSH_TEXFILL, texfill);
- INIT_BRUSH_ICON(ICON_BRUSH_TEXMASK, texmask);
- INIT_BRUSH_ICON(ICON_BRUSH_THUMB, thumb);
- INIT_BRUSH_ICON(ICON_BRUSH_ROTATE, twist);
-
- /* grease pencil sculpt */
- INIT_BRUSH_ICON(ICON_GPBRUSH_SMOOTH, gp_brush_smooth);
- INIT_BRUSH_ICON(ICON_GPBRUSH_THICKNESS, gp_brush_thickness);
- INIT_BRUSH_ICON(ICON_GPBRUSH_STRENGTH, gp_brush_strength);
- INIT_BRUSH_ICON(ICON_GPBRUSH_GRAB, gp_brush_grab);
- INIT_BRUSH_ICON(ICON_GPBRUSH_PUSH, gp_brush_push);
- INIT_BRUSH_ICON(ICON_GPBRUSH_TWIST, gp_brush_twist);
- INIT_BRUSH_ICON(ICON_GPBRUSH_PINCH, gp_brush_pinch);
- INIT_BRUSH_ICON(ICON_GPBRUSH_RANDOMIZE, gp_brush_randomize);
- INIT_BRUSH_ICON(ICON_GPBRUSH_CLONE, gp_brush_clone);
- INIT_BRUSH_ICON(ICON_GPBRUSH_WEIGHT, gp_brush_weight);
-
- /* grease pencil drawing brushes */
- INIT_BRUSH_ICON(ICON_GPBRUSH_PENCIL, gp_brush_pencil);
- INIT_BRUSH_ICON(ICON_GPBRUSH_PEN, gp_brush_pen);
- INIT_BRUSH_ICON(ICON_GPBRUSH_INK, gp_brush_ink);
- INIT_BRUSH_ICON(ICON_GPBRUSH_INKNOISE, gp_brush_inknoise);
- INIT_BRUSH_ICON(ICON_GPBRUSH_BLOCK, gp_brush_block);
- INIT_BRUSH_ICON(ICON_GPBRUSH_MARKER, gp_brush_marker);
- INIT_BRUSH_ICON(ICON_GPBRUSH_FILL, gp_brush_fill);
- INIT_BRUSH_ICON(ICON_GPBRUSH_ERASE_SOFT, gp_brush_erase_soft);
- INIT_BRUSH_ICON(ICON_GPBRUSH_ERASE_HARD, gp_brush_erase_hard);
- INIT_BRUSH_ICON(ICON_GPBRUSH_ERASE_STROKE, gp_brush_erase_stroke);
-
-#undef INIT_BRUSH_ICON
+# define INIT_BRUSH_ICON(icon_id, name) \
+ { \
+ uchar *rect = (uchar *)datatoc_##name##_png; \
+ int size = datatoc_##name##_png_size; \
+ DrawInfo *di; \
+\
+ di = def_internal_icon(NULL, icon_id, 0, 0, w, ICON_TYPE_BUFFER, 0); \
+ di->data.buffer.image->datatoc_rect = rect; \
+ di->data.buffer.image->datatoc_size = size; \
+ } \
+ ((void)0)
+ /* end INIT_BRUSH_ICON */
+
+ const int w = 96; /* warning, brush size hardcoded in C, but it gets scaled */
+
+ INIT_BRUSH_ICON(ICON_BRUSH_BLOB, blob);
+ INIT_BRUSH_ICON(ICON_BRUSH_BLUR, blur);
+ INIT_BRUSH_ICON(ICON_BRUSH_CLAY, clay);
+ INIT_BRUSH_ICON(ICON_BRUSH_CLAY_STRIPS, claystrips);
+ INIT_BRUSH_ICON(ICON_BRUSH_CLONE, clone);
+ INIT_BRUSH_ICON(ICON_BRUSH_CREASE, crease);
+ INIT_BRUSH_ICON(ICON_BRUSH_SCULPT_DRAW, draw);
+ INIT_BRUSH_ICON(ICON_BRUSH_FILL, fill);
+ INIT_BRUSH_ICON(ICON_BRUSH_FLATTEN, flatten);
+ INIT_BRUSH_ICON(ICON_BRUSH_GRAB, grab);
+ INIT_BRUSH_ICON(ICON_BRUSH_INFLATE, inflate);
+ INIT_BRUSH_ICON(ICON_BRUSH_LAYER, layer);
+ INIT_BRUSH_ICON(ICON_BRUSH_MASK, mask);
+ INIT_BRUSH_ICON(ICON_BRUSH_MIX, mix);
+ INIT_BRUSH_ICON(ICON_BRUSH_NUDGE, nudge);
+ INIT_BRUSH_ICON(ICON_BRUSH_PINCH, pinch);
+ INIT_BRUSH_ICON(ICON_BRUSH_SCRAPE, scrape);
+ INIT_BRUSH_ICON(ICON_BRUSH_SMEAR, smear);
+ INIT_BRUSH_ICON(ICON_BRUSH_SMOOTH, smooth);
+ INIT_BRUSH_ICON(ICON_BRUSH_SNAKE_HOOK, snake_hook);
+ INIT_BRUSH_ICON(ICON_BRUSH_SOFTEN, soften);
+ INIT_BRUSH_ICON(ICON_BRUSH_TEXDRAW, texdraw);
+ INIT_BRUSH_ICON(ICON_BRUSH_TEXFILL, texfill);
+ INIT_BRUSH_ICON(ICON_BRUSH_TEXMASK, texmask);
+ INIT_BRUSH_ICON(ICON_BRUSH_THUMB, thumb);
+ INIT_BRUSH_ICON(ICON_BRUSH_ROTATE, twist);
+
+ /* grease pencil sculpt */
+ INIT_BRUSH_ICON(ICON_GPBRUSH_SMOOTH, gp_brush_smooth);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_THICKNESS, gp_brush_thickness);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_STRENGTH, gp_brush_strength);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_GRAB, gp_brush_grab);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_PUSH, gp_brush_push);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_TWIST, gp_brush_twist);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_PINCH, gp_brush_pinch);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_RANDOMIZE, gp_brush_randomize);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_CLONE, gp_brush_clone);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_WEIGHT, gp_brush_weight);
+
+ /* grease pencil drawing brushes */
+ INIT_BRUSH_ICON(ICON_GPBRUSH_PENCIL, gp_brush_pencil);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_PEN, gp_brush_pen);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_INK, gp_brush_ink);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_INKNOISE, gp_brush_inknoise);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_BLOCK, gp_brush_block);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_MARKER, gp_brush_marker);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_FILL, gp_brush_fill);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_ERASE_SOFT, gp_brush_erase_soft);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_ERASE_HARD, gp_brush_erase_hard);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_ERASE_STROKE, gp_brush_erase_stroke);
+
+# undef INIT_BRUSH_ICON
}
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;
- }
- else if (event_type == RIGHTCTRLKEY) {
- event_type = LEFTCTRLKEY;
- }
- else if (event_type == RIGHTALTKEY) {
- event_type = LEFTALTKEY;
- }
- else if (event_type == EVT_TWEAK_L) {
- event_type = LEFTMOUSE;
- event_value = KM_CLICK_DRAG;
- }
- else if (event_type == EVT_TWEAK_M) {
- event_type = MIDDLEMOUSE;
- event_value = KM_CLICK_DRAG;
- }
- else if (event_type == EVT_TWEAK_R) {
- event_type = RIGHTMOUSE;
- event_value = KM_CLICK_DRAG;
- }
-
- DrawInfo *di = g_di_event_list;
- do {
- if (di->data.input.event_type == event_type) {
- return di->data.input.icon;
- }
- } while ((di = di->data.input.next));
-
- if (event_type == LEFTMOUSE) {
- return ELEM(event_value, KM_CLICK, KM_PRESS) ? ICON_MOUSE_LMB : ICON_MOUSE_LMB_DRAG;
- }
- else if (event_type == MIDDLEMOUSE) {
- return ELEM(event_value, KM_CLICK, KM_PRESS) ? ICON_MOUSE_MMB : ICON_MOUSE_MMB_DRAG;
- }
- else if (event_type == RIGHTMOUSE) {
- return ELEM(event_value, KM_CLICK, KM_PRESS) ? ICON_MOUSE_RMB : ICON_MOUSE_RMB_DRAG;
- }
-
- return ICON_NONE;
+ if (event_type == RIGHTSHIFTKEY) {
+ event_type = LEFTSHIFTKEY;
+ }
+ else if (event_type == RIGHTCTRLKEY) {
+ event_type = LEFTCTRLKEY;
+ }
+ else if (event_type == RIGHTALTKEY) {
+ event_type = LEFTALTKEY;
+ }
+ else if (event_type == EVT_TWEAK_L) {
+ event_type = LEFTMOUSE;
+ event_value = KM_CLICK_DRAG;
+ }
+ else if (event_type == EVT_TWEAK_M) {
+ event_type = MIDDLEMOUSE;
+ event_value = KM_CLICK_DRAG;
+ }
+ else if (event_type == EVT_TWEAK_R) {
+ event_type = RIGHTMOUSE;
+ event_value = KM_CLICK_DRAG;
+ }
+
+ DrawInfo *di = g_di_event_list;
+ do {
+ if (di->data.input.event_type == event_type) {
+ return di->data.input.icon;
+ }
+ } while ((di = di->data.input.next));
+
+ if (event_type == LEFTMOUSE) {
+ return ELEM(event_value, KM_CLICK, KM_PRESS) ? ICON_MOUSE_LMB : ICON_MOUSE_LMB_DRAG;
+ }
+ else if (event_type == MIDDLEMOUSE) {
+ return ELEM(event_value, KM_CLICK, KM_PRESS) ? ICON_MOUSE_MMB : ICON_MOUSE_MMB_DRAG;
+ }
+ else if (event_type == RIGHTMOUSE) {
+ return ELEM(event_value, KM_CLICK, KM_PRESS) ? ICON_MOUSE_RMB : ICON_MOUSE_RMB_DRAG;
+ }
+
+ return ICON_NONE;
}
int UI_icon_from_keymap_item(const wmKeyMapItem *kmi, int r_icon_mod[4])
{
- if (r_icon_mod) {
- memset(r_icon_mod, 0x0, sizeof(int[4]));
- int i = 0;
- if (!ELEM(kmi->ctrl, KM_NOTHING, KM_ANY)) {
- r_icon_mod[i++] = ICON_EVENT_CTRL;
- }
- if (!ELEM(kmi->alt, KM_NOTHING, KM_ANY)) {
- r_icon_mod[i++] = ICON_EVENT_ALT;
- }
- if (!ELEM(kmi->shift, KM_NOTHING, KM_ANY)) {
- r_icon_mod[i++] = ICON_EVENT_SHIFT;
- }
- if (!ELEM(kmi->oskey, KM_NOTHING, KM_ANY)) {
- r_icon_mod[i++] = ICON_EVENT_OS;
- }
- }
- return UI_icon_from_event_type(kmi->type, kmi->val);
+ if (r_icon_mod) {
+ memset(r_icon_mod, 0x0, sizeof(int[4]));
+ int i = 0;
+ if (!ELEM(kmi->ctrl, KM_NOTHING, KM_ANY)) {
+ r_icon_mod[i++] = ICON_EVENT_CTRL;
+ }
+ if (!ELEM(kmi->alt, KM_NOTHING, KM_ANY)) {
+ r_icon_mod[i++] = ICON_EVENT_ALT;
+ }
+ if (!ELEM(kmi->shift, KM_NOTHING, KM_ANY)) {
+ r_icon_mod[i++] = ICON_EVENT_SHIFT;
+ }
+ if (!ELEM(kmi->oskey, KM_NOTHING, KM_ANY)) {
+ r_icon_mod[i++] = ICON_EVENT_OS;
+ }
+ }
+ return UI_icon_from_event_type(kmi->type, kmi->val);
}
static void init_event_icons(void)
{
- DrawInfo *di_next = NULL;
-
-#define INIT_EVENT_ICON(icon_id, type, value) \
- { \
- DrawInfo *di = def_internal_icon(NULL, icon_id, 0, 0, w, ICON_TYPE_EVENT, 0); \
- di->data.input.event_type = type; \
- di->data.input.event_value = value; \
- di->data.input.icon = icon_id; \
- di->data.input.next = di_next; \
- di_next = di; \
- } ((void)0)
- /* end INIT_EVENT_ICON */
-
- 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);
-
- g_di_event_list = di_next;
-
-#undef INIT_EVENT_ICON
+ DrawInfo *di_next = NULL;
+
+# define INIT_EVENT_ICON(icon_id, type, value) \
+ { \
+ DrawInfo *di = def_internal_icon(NULL, icon_id, 0, 0, w, ICON_TYPE_EVENT, 0); \
+ di->data.input.event_type = type; \
+ di->data.input.event_value = value; \
+ di->data.input.icon = icon_id; \
+ di->data.input.next = di_next; \
+ di_next = di; \
+ } \
+ ((void)0)
+ /* end INIT_EVENT_ICON */
+
+ 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);
+
+ g_di_event_list = di_next;
+
+# undef INIT_EVENT_ICON
}
static void icon_verify_datatoc(IconImage *iimg)
{
- /* if it has own rect, things are all OK */
- if (iimg->rect) {
- return;
- }
+ /* if it has own rect, things are all OK */
+ if (iimg->rect) {
+ return;
+ }
- if (iimg->datatoc_rect) {
- ImBuf *bbuf = IMB_ibImageFromMemory(iimg->datatoc_rect,
- iimg->datatoc_size, IB_rect, NULL, "<matcap icon>");
- /* w and h were set on initialize */
- if (bbuf->x != iimg->h && bbuf->y != iimg->w) {
- IMB_scaleImBuf(bbuf, iimg->w, iimg->h);
- }
+ if (iimg->datatoc_rect) {
+ ImBuf *bbuf = IMB_ibImageFromMemory(
+ iimg->datatoc_rect, iimg->datatoc_size, IB_rect, NULL, "<matcap icon>");
+ /* w and h were set on initialize */
+ if (bbuf->x != iimg->h && bbuf->y != iimg->w) {
+ IMB_scaleImBuf(bbuf, iimg->w, iimg->h);
+ }
- iimg->rect = bbuf->rect;
- bbuf->rect = NULL;
- IMB_freeImBuf(bbuf);
- }
+ iimg->rect = bbuf->rect;
+ bbuf->rect = NULL;
+ IMB_freeImBuf(bbuf);
+ }
}
static void init_internal_icons(void)
{
-// bTheme *btheme = UI_GetTheme();
- ImBuf *b16buf = NULL, *b32buf = NULL;
- int x, y;
-
-#if 0 // temp disabled
- if ((btheme != NULL) && btheme->tui.iconfile[0]) {
- char *icondir = BKE_appdir_folder_id(BLENDER_DATAFILES, "icons");
- char iconfilestr[FILE_MAX];
-
- if (icondir) {
- BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile);
-
- /* if the image is missing bbuf will just be NULL */
- bbuf = IMB_loadiffname(iconfilestr, IB_rect, NULL);
-
- if (bbuf && (bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H)) {
- printf("\n***WARNING***\nIcons file %s too small.\nUsing built-in Icons instead\n", iconfilestr);
- IMB_freeImBuf(bbuf);
- bbuf = NULL;
- }
- }
- else {
- printf("%s: 'icons' data path not found, continuing\n", __func__);
- }
- }
-#endif
- if (b16buf == NULL) {
- b16buf = IMB_ibImageFromMemory((const uchar *)datatoc_blender_icons16_png,
- datatoc_blender_icons16_png_size, IB_rect, NULL, "<blender icons>");
- }
- if (b16buf) {
- IMB_premultiply_alpha(b16buf);
- }
-
- if (b32buf == NULL) {
- b32buf = IMB_ibImageFromMemory((const uchar *)datatoc_blender_icons32_png,
- datatoc_blender_icons32_png_size, IB_rect, NULL, "<blender icons>");
- }
- if (b32buf) {
- IMB_premultiply_alpha(b32buf);
- }
-
- if (b16buf && b32buf) {
- /* Free existing texture if any. */
- if (icongltex.id) {
- glDeleteTextures(1, &icongltex.id);
- icongltex.id = 0;
- }
-
- /* Allocate OpenGL texture. */
- glGenTextures(1, &icongltex.id);
-
- if (icongltex.id) {
- int level = 2;
-
- icongltex.w = b32buf->x;
- icongltex.h = b32buf->y;
- icongltex.invw = 1.0f / b32buf->x;
- icongltex.invh = 1.0f / b32buf->y;
-
- glBindTexture(GL_TEXTURE_2D, icongltex.id);
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, b32buf->x, b32buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b32buf->rect);
- glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, b16buf->x, b16buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b16buf->rect);
-
- while (b16buf->x > 1) {
- ImBuf *nbuf = IMB_onehalf(b16buf);
- glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, nbuf->x, nbuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nbuf->rect);
- level++;
- IMB_freeImBuf(b16buf);
- b16buf = nbuf;
- }
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
- glBindTexture(GL_TEXTURE_2D, 0);
- }
-
- /* Define icons. */
- for (y = 0; y < ICON_GRID_ROWS; y++) {
- /* Row W has monochrome icons. */
- for (x = 0; x < ICON_GRID_COLS; x++) {
- IconType icontype = icontypes[y * ICON_GRID_COLS + x];
- if (!ELEM(icontype.type, ICON_TYPE_COLOR_TEXTURE, ICON_TYPE_MONO_TEXTURE)) {
- continue;
- }
-
- def_internal_icon(b32buf, BIFICONID_FIRST + y * ICON_GRID_COLS + x,
- x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
- y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN, ICON_GRID_W,
- icontype.type, icontype.theme_color);
- }
- }
- }
-
- def_internal_vicon(ICON_SMALL_TRI_RIGHT_VEC, vicon_small_tri_right_draw);
-
- def_internal_vicon(ICON_KEYTYPE_KEYFRAME_VEC, vicon_keytype_keyframe_draw);
- def_internal_vicon(ICON_KEYTYPE_BREAKDOWN_VEC, vicon_keytype_breakdown_draw);
- def_internal_vicon(ICON_KEYTYPE_EXTREME_VEC, vicon_keytype_extreme_draw);
- def_internal_vicon(ICON_KEYTYPE_JITTER_VEC, vicon_keytype_jitter_draw);
- def_internal_vicon(ICON_KEYTYPE_MOVING_HOLD_VEC, vicon_keytype_moving_hold_draw);
-
- def_internal_vicon(ICON_HANDLETYPE_FREE_VEC, vicon_handletype_free_draw);
- def_internal_vicon(ICON_HANDLETYPE_ALIGNED_VEC, vicon_handletype_aligned_draw);
- def_internal_vicon(ICON_HANDLETYPE_VECTOR_VEC, vicon_handletype_vector_draw);
- def_internal_vicon(ICON_HANDLETYPE_AUTO_VEC, vicon_handletype_auto_draw);
- def_internal_vicon(ICON_HANDLETYPE_AUTO_CLAMP_VEC, vicon_handletype_auto_clamp_draw);
-
- def_internal_vicon(ICON_COLORSET_01_VEC, vicon_colorset_draw_01);
- def_internal_vicon(ICON_COLORSET_02_VEC, vicon_colorset_draw_02);
- def_internal_vicon(ICON_COLORSET_03_VEC, vicon_colorset_draw_03);
- def_internal_vicon(ICON_COLORSET_04_VEC, vicon_colorset_draw_04);
- def_internal_vicon(ICON_COLORSET_05_VEC, vicon_colorset_draw_05);
- def_internal_vicon(ICON_COLORSET_06_VEC, vicon_colorset_draw_06);
- def_internal_vicon(ICON_COLORSET_07_VEC, vicon_colorset_draw_07);
- def_internal_vicon(ICON_COLORSET_08_VEC, vicon_colorset_draw_08);
- def_internal_vicon(ICON_COLORSET_09_VEC, vicon_colorset_draw_09);
- def_internal_vicon(ICON_COLORSET_10_VEC, vicon_colorset_draw_10);
- def_internal_vicon(ICON_COLORSET_11_VEC, vicon_colorset_draw_11);
- def_internal_vicon(ICON_COLORSET_12_VEC, vicon_colorset_draw_12);
- def_internal_vicon(ICON_COLORSET_13_VEC, vicon_colorset_draw_13);
- def_internal_vicon(ICON_COLORSET_14_VEC, vicon_colorset_draw_14);
- def_internal_vicon(ICON_COLORSET_15_VEC, vicon_colorset_draw_15);
- def_internal_vicon(ICON_COLORSET_16_VEC, vicon_colorset_draw_16);
- def_internal_vicon(ICON_COLORSET_17_VEC, vicon_colorset_draw_17);
- def_internal_vicon(ICON_COLORSET_18_VEC, vicon_colorset_draw_18);
- def_internal_vicon(ICON_COLORSET_19_VEC, vicon_colorset_draw_19);
- def_internal_vicon(ICON_COLORSET_20_VEC, vicon_colorset_draw_20);
-
- IMB_freeImBuf(b16buf);
- IMB_freeImBuf(b32buf);
-
-}
-#endif /* WITH_HEADLESS */
+ // bTheme *btheme = UI_GetTheme();
+ ImBuf *b16buf = NULL, *b32buf = NULL;
+ int x, y;
+
+# if 0 // temp disabled
+ if ((btheme != NULL) && btheme->tui.iconfile[0]) {
+ char *icondir = BKE_appdir_folder_id(BLENDER_DATAFILES, "icons");
+ char iconfilestr[FILE_MAX];
+
+ if (icondir) {
+ BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile);
+
+ /* if the image is missing bbuf will just be NULL */
+ bbuf = IMB_loadiffname(iconfilestr, IB_rect, NULL);
+
+ if (bbuf && (bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H)) {
+ printf("\n***WARNING***\nIcons file %s too small.\nUsing built-in Icons instead\n", iconfilestr);
+ IMB_freeImBuf(bbuf);
+ bbuf = NULL;
+ }
+ }
+ else {
+ printf("%s: 'icons' data path not found, continuing\n", __func__);
+ }
+ }
+# endif
+ if (b16buf == NULL) {
+ b16buf = IMB_ibImageFromMemory((const uchar *)datatoc_blender_icons16_png,
+ datatoc_blender_icons16_png_size,
+ IB_rect,
+ NULL,
+ "<blender icons>");
+ }
+ if (b16buf) {
+ IMB_premultiply_alpha(b16buf);
+ }
+
+ if (b32buf == NULL) {
+ b32buf = IMB_ibImageFromMemory((const uchar *)datatoc_blender_icons32_png,
+ datatoc_blender_icons32_png_size,
+ IB_rect,
+ NULL,
+ "<blender icons>");
+ }
+ if (b32buf) {
+ IMB_premultiply_alpha(b32buf);
+ }
+
+ if (b16buf && b32buf) {
+ /* Free existing texture if any. */
+ if (icongltex.id) {
+ glDeleteTextures(1, &icongltex.id);
+ icongltex.id = 0;
+ }
+
+ /* Allocate OpenGL texture. */
+ glGenTextures(1, &icongltex.id);
+
+ if (icongltex.id) {
+ int level = 2;
+
+ icongltex.w = b32buf->x;
+ icongltex.h = b32buf->y;
+ icongltex.invw = 1.0f / b32buf->x;
+ icongltex.invh = 1.0f / b32buf->y;
+
+ glBindTexture(GL_TEXTURE_2D, icongltex.id);
+
+ glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ GL_RGBA8,
+ b32buf->x,
+ b32buf->y,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ b32buf->rect);
+ glTexImage2D(GL_TEXTURE_2D,
+ 1,
+ GL_RGBA8,
+ b16buf->x,
+ b16buf->y,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ b16buf->rect);
+
+ while (b16buf->x > 1) {
+ ImBuf *nbuf = IMB_onehalf(b16buf);
+ glTexImage2D(GL_TEXTURE_2D,
+ level,
+ GL_RGBA8,
+ nbuf->x,
+ nbuf->y,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ nbuf->rect);
+ level++;
+ IMB_freeImBuf(b16buf);
+ b16buf = nbuf;
+ }
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+
+ /* Define icons. */
+ for (y = 0; y < ICON_GRID_ROWS; y++) {
+ /* Row W has monochrome icons. */
+ for (x = 0; x < ICON_GRID_COLS; x++) {
+ IconType icontype = icontypes[y * ICON_GRID_COLS + x];
+ if (!ELEM(icontype.type, ICON_TYPE_COLOR_TEXTURE, ICON_TYPE_MONO_TEXTURE)) {
+ continue;
+ }
+
+ def_internal_icon(b32buf,
+ BIFICONID_FIRST + y * ICON_GRID_COLS + x,
+ x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
+ y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
+ ICON_GRID_W,
+ icontype.type,
+ icontype.theme_color);
+ }
+ }
+ }
+
+ def_internal_vicon(ICON_SMALL_TRI_RIGHT_VEC, vicon_small_tri_right_draw);
+
+ def_internal_vicon(ICON_KEYTYPE_KEYFRAME_VEC, vicon_keytype_keyframe_draw);
+ def_internal_vicon(ICON_KEYTYPE_BREAKDOWN_VEC, vicon_keytype_breakdown_draw);
+ def_internal_vicon(ICON_KEYTYPE_EXTREME_VEC, vicon_keytype_extreme_draw);
+ def_internal_vicon(ICON_KEYTYPE_JITTER_VEC, vicon_keytype_jitter_draw);
+ def_internal_vicon(ICON_KEYTYPE_MOVING_HOLD_VEC, vicon_keytype_moving_hold_draw);
+
+ def_internal_vicon(ICON_HANDLETYPE_FREE_VEC, vicon_handletype_free_draw);
+ def_internal_vicon(ICON_HANDLETYPE_ALIGNED_VEC, vicon_handletype_aligned_draw);
+ def_internal_vicon(ICON_HANDLETYPE_VECTOR_VEC, vicon_handletype_vector_draw);
+ def_internal_vicon(ICON_HANDLETYPE_AUTO_VEC, vicon_handletype_auto_draw);
+ def_internal_vicon(ICON_HANDLETYPE_AUTO_CLAMP_VEC, vicon_handletype_auto_clamp_draw);
+
+ def_internal_vicon(ICON_COLORSET_01_VEC, vicon_colorset_draw_01);
+ def_internal_vicon(ICON_COLORSET_02_VEC, vicon_colorset_draw_02);
+ def_internal_vicon(ICON_COLORSET_03_VEC, vicon_colorset_draw_03);
+ def_internal_vicon(ICON_COLORSET_04_VEC, vicon_colorset_draw_04);
+ def_internal_vicon(ICON_COLORSET_05_VEC, vicon_colorset_draw_05);
+ def_internal_vicon(ICON_COLORSET_06_VEC, vicon_colorset_draw_06);
+ def_internal_vicon(ICON_COLORSET_07_VEC, vicon_colorset_draw_07);
+ def_internal_vicon(ICON_COLORSET_08_VEC, vicon_colorset_draw_08);
+ def_internal_vicon(ICON_COLORSET_09_VEC, vicon_colorset_draw_09);
+ def_internal_vicon(ICON_COLORSET_10_VEC, vicon_colorset_draw_10);
+ def_internal_vicon(ICON_COLORSET_11_VEC, vicon_colorset_draw_11);
+ def_internal_vicon(ICON_COLORSET_12_VEC, vicon_colorset_draw_12);
+ def_internal_vicon(ICON_COLORSET_13_VEC, vicon_colorset_draw_13);
+ def_internal_vicon(ICON_COLORSET_14_VEC, vicon_colorset_draw_14);
+ def_internal_vicon(ICON_COLORSET_15_VEC, vicon_colorset_draw_15);
+ def_internal_vicon(ICON_COLORSET_16_VEC, vicon_colorset_draw_16);
+ def_internal_vicon(ICON_COLORSET_17_VEC, vicon_colorset_draw_17);
+ def_internal_vicon(ICON_COLORSET_18_VEC, vicon_colorset_draw_18);
+ def_internal_vicon(ICON_COLORSET_19_VEC, vicon_colorset_draw_19);
+ def_internal_vicon(ICON_COLORSET_20_VEC, vicon_colorset_draw_20);
+
+ IMB_freeImBuf(b16buf);
+ IMB_freeImBuf(b32buf);
+}
+# endif /* WITH_HEADLESS */
static void init_iconfile_list(struct ListBase *list)
{
- IconFile *ifile;
- struct direntry *dir;
- int totfile, i, index = 1;
- const char *icondir;
-
- BLI_listbase_clear(list);
- icondir = BKE_appdir_folder_id(BLENDER_DATAFILES, "icons");
-
- if (icondir == NULL) {
- return;
- }
-
- totfile = BLI_filelist_dir_contents(icondir, &dir);
-
- for (i = 0; i < totfile; i++) {
- if ((dir[i].type & S_IFREG)) {
- const char *filename = dir[i].relname;
-
- if (BLI_path_extension_check(filename, ".png")) {
- /* loading all icons on file start is overkill & slows startup
- * its possible they change size after blender load anyway. */
-#if 0
- int ifilex, ifiley;
- char iconfilestr[FILE_MAX + 16]; /* allow 256 chars for file+dir */
- ImBuf *bbuf = NULL;
- /* check to see if the image is the right size, continue if not */
- /* copying strings here should go ok, assuming that we never get back
- * a complete path to file longer than 256 chars */
- BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, filename);
- bbuf = IMB_loadiffname(iconfilestr, IB_rect);
-
- if (bbuf) {
- ifilex = bbuf->x;
- ifiley = bbuf->y;
- IMB_freeImBuf(bbuf);
- }
- else {
- ifilex = ifiley = 0;
- }
-
- /* bad size or failed to load */
- if ((ifilex != ICON_IMAGE_W) || (ifiley != ICON_IMAGE_H)) {
- printf("icon '%s' is wrong size %dx%d\n", iconfilestr, ifilex, ifiley);
- continue;
- }
-#endif /* removed */
-
- /* found a potential icon file, so make an entry for it in the cache list */
- ifile = MEM_callocN(sizeof(IconFile), "IconFile");
-
- BLI_strncpy(ifile->filename, filename, sizeof(ifile->filename));
- ifile->index = index;
-
- BLI_addtail(list, ifile);
-
- index++;
- }
- }
- }
-
- BLI_filelist_free(dir, totfile);
- dir = NULL;
+ IconFile *ifile;
+ struct direntry *dir;
+ int totfile, i, index = 1;
+ const char *icondir;
+
+ BLI_listbase_clear(list);
+ icondir = BKE_appdir_folder_id(BLENDER_DATAFILES, "icons");
+
+ if (icondir == NULL) {
+ return;
+ }
+
+ totfile = BLI_filelist_dir_contents(icondir, &dir);
+
+ for (i = 0; i < totfile; i++) {
+ if ((dir[i].type & S_IFREG)) {
+ const char *filename = dir[i].relname;
+
+ if (BLI_path_extension_check(filename, ".png")) {
+ /* loading all icons on file start is overkill & slows startup
+ * its possible they change size after blender load anyway. */
+# if 0
+ int ifilex, ifiley;
+ char iconfilestr[FILE_MAX + 16]; /* allow 256 chars for file+dir */
+ ImBuf *bbuf = NULL;
+ /* check to see if the image is the right size, continue if not */
+ /* copying strings here should go ok, assuming that we never get back
+ * a complete path to file longer than 256 chars */
+ BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, filename);
+ bbuf = IMB_loadiffname(iconfilestr, IB_rect);
+
+ if (bbuf) {
+ ifilex = bbuf->x;
+ ifiley = bbuf->y;
+ IMB_freeImBuf(bbuf);
+ }
+ else {
+ ifilex = ifiley = 0;
+ }
+
+ /* bad size or failed to load */
+ if ((ifilex != ICON_IMAGE_W) || (ifiley != ICON_IMAGE_H)) {
+ printf("icon '%s' is wrong size %dx%d\n", iconfilestr, ifilex, ifiley);
+ continue;
+ }
+# endif /* removed */
+
+ /* found a potential icon file, so make an entry for it in the cache list */
+ ifile = MEM_callocN(sizeof(IconFile), "IconFile");
+
+ BLI_strncpy(ifile->filename, filename, sizeof(ifile->filename));
+ ifile->index = index;
+
+ BLI_addtail(list, ifile);
+
+ index++;
+ }
+ }
+ }
+
+ BLI_filelist_free(dir, totfile);
+ dir = NULL;
}
static void free_iconfile_list(struct ListBase *list)
{
- IconFile *ifile = NULL, *next_ifile = NULL;
+ IconFile *ifile = NULL, *next_ifile = NULL;
- for (ifile = list->first; ifile; ifile = next_ifile) {
- next_ifile = ifile->next;
- BLI_freelinkN(list, ifile);
- }
+ for (ifile = list->first; ifile; ifile = next_ifile) {
+ next_ifile = ifile->next;
+ BLI_freelinkN(list, ifile);
+ }
}
-#endif /* WITH_HEADLESS */
+#endif /* WITH_HEADLESS */
int UI_iconfile_get_index(const char *filename)
{
- IconFile *ifile;
- ListBase *list = &(iconfilelist);
+ IconFile *ifile;
+ ListBase *list = &(iconfilelist);
- for (ifile = list->first; ifile; ifile = ifile->next) {
- if (BLI_path_cmp(filename, ifile->filename) == 0) {
- return ifile->index;
- }
- }
+ for (ifile = list->first; ifile; ifile = ifile->next) {
+ if (BLI_path_cmp(filename, ifile->filename) == 0) {
+ return ifile->index;
+ }
+ }
- return 0;
+ return 0;
}
ListBase *UI_iconfile_list(void)
{
- ListBase *list = &(iconfilelist);
+ ListBase *list = &(iconfilelist);
- return list;
+ return list;
}
-
void UI_icons_free(void)
{
#ifndef WITH_HEADLESS
- if (icongltex.id) {
- glDeleteTextures(1, &icongltex.id);
- icongltex.id = 0;
- }
+ if (icongltex.id) {
+ glDeleteTextures(1, &icongltex.id);
+ icongltex.id = 0;
+ }
- free_iconfile_list(&iconfilelist);
- BKE_icons_free();
+ free_iconfile_list(&iconfilelist);
+ BKE_icons_free();
#endif
}
void UI_icons_free_drawinfo(void *drawinfo)
{
- DrawInfo *di = drawinfo;
+ DrawInfo *di = drawinfo;
- if (di) {
- if (di->type == ICON_TYPE_BUFFER) {
- if (di->data.buffer.image) {
- if (di->data.buffer.image->rect) {
- MEM_freeN(di->data.buffer.image->rect);
- }
- MEM_freeN(di->data.buffer.image);
- }
- }
- else if (di->type == ICON_TYPE_GEOM) {
- if (di->data.geom.image_cache) {
- IMB_freeImBuf(di->data.geom.image_cache);
- }
- }
+ if (di) {
+ if (di->type == ICON_TYPE_BUFFER) {
+ if (di->data.buffer.image) {
+ if (di->data.buffer.image->rect) {
+ MEM_freeN(di->data.buffer.image->rect);
+ }
+ MEM_freeN(di->data.buffer.image);
+ }
+ }
+ else if (di->type == ICON_TYPE_GEOM) {
+ if (di->data.geom.image_cache) {
+ IMB_freeImBuf(di->data.geom.image_cache);
+ }
+ }
- MEM_freeN(di);
- }
+ MEM_freeN(di);
+ }
}
/**
@@ -973,89 +1024,89 @@ void UI_icons_free_drawinfo(void *drawinfo)
*/
static DrawInfo *icon_create_drawinfo(Icon *icon)
{
- int icon_data_type = icon->obj_type;
- DrawInfo *di = NULL;
+ int icon_data_type = icon->obj_type;
+ DrawInfo *di = NULL;
- di = MEM_callocN(sizeof(DrawInfo), "di_icon");
+ di = MEM_callocN(sizeof(DrawInfo), "di_icon");
- if (ELEM(icon_data_type, ICON_DATA_ID, ICON_DATA_PREVIEW)) {
- di->type = ICON_TYPE_PREVIEW;
- }
- else if (icon_data_type == ICON_DATA_GEOM) {
- di->type = ICON_TYPE_GEOM;
- }
- else if (icon_data_type == ICON_DATA_STUDIOLIGHT) {
- di->type = ICON_TYPE_BUFFER;
- }
- else if (icon_data_type == ICON_DATA_GPLAYER) {
- di->type = ICON_TYPE_GPLAYER;
- }
- else {
- BLI_assert(0);
- }
+ if (ELEM(icon_data_type, ICON_DATA_ID, ICON_DATA_PREVIEW)) {
+ di->type = ICON_TYPE_PREVIEW;
+ }
+ else if (icon_data_type == ICON_DATA_GEOM) {
+ di->type = ICON_TYPE_GEOM;
+ }
+ else if (icon_data_type == ICON_DATA_STUDIOLIGHT) {
+ di->type = ICON_TYPE_BUFFER;
+ }
+ else if (icon_data_type == ICON_DATA_GPLAYER) {
+ di->type = ICON_TYPE_GPLAYER;
+ }
+ else {
+ BLI_assert(0);
+ }
- return di;
+ return di;
}
static DrawInfo *icon_ensure_drawinfo(Icon *icon)
{
- if (icon->drawinfo) {
- return icon->drawinfo;
- }
- DrawInfo *di = icon_create_drawinfo(icon);
- icon->drawinfo = di;
- icon->drawinfo_free = UI_icons_free_drawinfo;
- return di;
+ if (icon->drawinfo) {
+ return icon->drawinfo;
+ }
+ DrawInfo *di = icon_create_drawinfo(icon);
+ icon->drawinfo = di;
+ icon->drawinfo_free = UI_icons_free_drawinfo;
+ return di;
}
/* note!, returns unscaled by DPI */
int UI_icon_get_width(int icon_id)
{
- Icon *icon = NULL;
- DrawInfo *di = NULL;
+ Icon *icon = NULL;
+ DrawInfo *di = NULL;
- icon = BKE_icon_get(icon_id);
+ icon = BKE_icon_get(icon_id);
- if (icon == NULL) {
- if (G.debug & G_DEBUG) {
- printf("%s: Internal error, no icon for icon ID: %d\n", __func__, icon_id);
- }
- return 0;
- }
+ if (icon == NULL) {
+ if (G.debug & G_DEBUG) {
+ printf("%s: Internal error, no icon for icon ID: %d\n", __func__, icon_id);
+ }
+ return 0;
+ }
- di = icon_ensure_drawinfo(icon);
- if (di) {
- return ICON_DEFAULT_WIDTH;
- }
+ di = icon_ensure_drawinfo(icon);
+ if (di) {
+ return ICON_DEFAULT_WIDTH;
+ }
- return 0;
+ return 0;
}
int UI_icon_get_height(int icon_id)
{
- Icon *icon = BKE_icon_get(icon_id);
- if (icon == NULL) {
- if (G.debug & G_DEBUG) {
- printf("%s: Internal error, no icon for icon ID: %d\n", __func__, icon_id);
- }
- return 0;
- }
+ Icon *icon = BKE_icon_get(icon_id);
+ if (icon == NULL) {
+ if (G.debug & G_DEBUG) {
+ printf("%s: Internal error, no icon for icon ID: %d\n", __func__, icon_id);
+ }
+ return 0;
+ }
- DrawInfo *di = icon_ensure_drawinfo(icon);
- if (di) {
- return ICON_DEFAULT_HEIGHT;
- }
+ DrawInfo *di = icon_ensure_drawinfo(icon);
+ if (di) {
+ return ICON_DEFAULT_HEIGHT;
+ }
- return 0;
+ return 0;
}
void UI_icons_init()
{
#ifndef WITH_HEADLESS
- init_iconfile_list(&iconfilelist);
- init_internal_icons();
- init_brush_icons();
- init_event_icons();
+ init_iconfile_list(&iconfilelist);
+ init_internal_icons();
+ init_brush_icons();
+ init_event_icons();
#endif
}
@@ -1063,281 +1114,312 @@ void UI_icons_init()
*/
int UI_preview_render_size(enum eIconSizes size)
{
- switch (size) {
- case ICON_SIZE_ICON:
- return ICON_RENDER_DEFAULT_HEIGHT;
- case ICON_SIZE_PREVIEW:
- return PREVIEW_RENDER_DEFAULT_HEIGHT;
- default:
- return 0;
- }
+ switch (size) {
+ case ICON_SIZE_ICON:
+ return ICON_RENDER_DEFAULT_HEIGHT;
+ case ICON_SIZE_PREVIEW:
+ return PREVIEW_RENDER_DEFAULT_HEIGHT;
+ default:
+ return 0;
+ }
}
/* Create rect for the icon
*/
static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size)
{
- uint render_size = UI_preview_render_size(size);
+ uint render_size = UI_preview_render_size(size);
- if (!prv_img) {
- if (G.debug & G_DEBUG) {
- printf("%s, error: requested preview image does not exist", __func__);
- }
- }
- else if (!prv_img->rect[size]) {
- prv_img->w[size] = render_size;
- prv_img->h[size] = render_size;
- prv_img->flag[size] |= PRV_CHANGED;
- prv_img->changed_timestamp[size] = 0;
- prv_img->rect[size] = MEM_callocN(render_size * render_size * sizeof(uint), "prv_rect");
- }
+ if (!prv_img) {
+ if (G.debug & G_DEBUG) {
+ printf("%s, error: requested preview image does not exist", __func__);
+ }
+ }
+ else if (!prv_img->rect[size]) {
+ prv_img->w[size] = render_size;
+ prv_img->h[size] = render_size;
+ prv_img->flag[size] |= PRV_CHANGED;
+ prv_img->changed_timestamp[size] = 0;
+ prv_img->rect[size] = MEM_callocN(render_size * render_size * sizeof(uint), "prv_rect");
+ }
}
static void ui_id_preview_image_render_size(
- const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job);
+ const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job);
-static void ui_studiolight_icon_job_exec(void *customdata, short *UNUSED(stop), short *UNUSED(do_update), float *UNUSED(progress))
+static void ui_studiolight_icon_job_exec(void *customdata,
+ short *UNUSED(stop),
+ short *UNUSED(do_update),
+ float *UNUSED(progress))
{
- Icon **tmp = (Icon **)customdata;
- Icon *icon = *tmp;
- DrawInfo *di = icon_ensure_drawinfo(icon);
- StudioLight *sl = icon->obj;
- BKE_studiolight_preview(di->data.buffer.image->rect, sl, icon->id_type);
+ Icon **tmp = (Icon **)customdata;
+ Icon *icon = *tmp;
+ DrawInfo *di = icon_ensure_drawinfo(icon);
+ StudioLight *sl = icon->obj;
+ BKE_studiolight_preview(di->data.buffer.image->rect, sl, icon->id_type);
}
static void ui_studiolight_kill_icon_preview_job(wmWindowManager *wm, int icon_id)
{
- Icon *icon = BKE_icon_get(icon_id);
- WM_jobs_kill_type(wm, icon, WM_JOB_TYPE_STUDIOLIGHT);
- icon->obj = NULL;
+ Icon *icon = BKE_icon_get(icon_id);
+ WM_jobs_kill_type(wm, icon, WM_JOB_TYPE_STUDIOLIGHT);
+ icon->obj = NULL;
}
static void ui_studiolight_free_function(StudioLight *sl, void *data)
{
- wmWindowManager *wm = data;
+ wmWindowManager *wm = data;
- /* Happens if job was canceled or already finished. */
- if (wm == NULL) {
- return;
- }
+ /* Happens if job was canceled or already finished. */
+ if (wm == NULL) {
+ return;
+ }
- // get icons_id, get icons and kill wm jobs
- if (sl->icon_id_radiance) {
- ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_radiance);
- }
- if (sl->icon_id_irradiance) {
- ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_irradiance);
- }
- if (sl->icon_id_matcap) {
- ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_matcap);
- }
- if (sl->icon_id_matcap_flipped) {
- ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_matcap_flipped);
- }
+ // get icons_id, get icons and kill wm jobs
+ if (sl->icon_id_radiance) {
+ ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_radiance);
+ }
+ if (sl->icon_id_irradiance) {
+ ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_irradiance);
+ }
+ if (sl->icon_id_matcap) {
+ ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_matcap);
+ }
+ if (sl->icon_id_matcap_flipped) {
+ ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_matcap_flipped);
+ }
}
static void ui_studiolight_icon_job_end(void *customdata)
{
- Icon **tmp = (Icon **)customdata;
- Icon *icon = *tmp;
- StudioLight *sl = icon->obj;
- BKE_studiolight_set_free_function(sl, &ui_studiolight_free_function, NULL);
+ Icon **tmp = (Icon **)customdata;
+ Icon *icon = *tmp;
+ StudioLight *sl = icon->obj;
+ BKE_studiolight_set_free_function(sl, &ui_studiolight_free_function, NULL);
}
void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool big)
{
- Icon *icon = BKE_icon_get(icon_id);
-
- if (icon) {
- DrawInfo *di = icon_ensure_drawinfo(icon);
-
- if (di) {
- switch (di->type) {
- case ICON_TYPE_PREVIEW:
- {
- ID *id = (icon->id_type != 0) ? icon->obj : NULL;
- PreviewImage *prv = id ? BKE_previewimg_id_ensure(id) : icon->obj;
- /* Using jobs for screen previews crashes due to offscreen rendering.
- * XXX would be nicer if PreviewImage could store if it supports jobs */
- const bool use_jobs = !id || (GS(id->name) != ID_SCR);
-
- if (prv) {
- const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON;
-
- if (id || (prv->tag & PRV_TAG_DEFFERED) != 0) {
- ui_id_preview_image_render_size(C, NULL, id, prv, size, use_jobs);
- }
- }
- break;
- }
- case ICON_TYPE_BUFFER:
- {
- if (icon->obj_type == ICON_DATA_STUDIOLIGHT) {
- if (di->data.buffer.image == NULL) {
- wmWindowManager *wm = CTX_wm_manager(C);
- StudioLight *sl = icon->obj;
- BKE_studiolight_set_free_function(sl, &ui_studiolight_free_function, wm);
- IconImage *img = MEM_mallocN(sizeof(IconImage), __func__);
-
- img->w = STUDIOLIGHT_ICON_SIZE;
- img->h = STUDIOLIGHT_ICON_SIZE;
- size_t size = STUDIOLIGHT_ICON_SIZE * STUDIOLIGHT_ICON_SIZE * sizeof(uint);
- img->rect = MEM_mallocN(size, __func__);
- memset(img->rect, 0, size);
- di->data.buffer.image = img;
-
- wmJob *wm_job = WM_jobs_get(wm, CTX_wm_window(C), icon, "StudioLight Icon", 0, WM_JOB_TYPE_STUDIOLIGHT);
- Icon **tmp = MEM_callocN(sizeof(Icon *), __func__);
- *tmp = icon;
- WM_jobs_customdata_set(wm_job, tmp, MEM_freeN);
- WM_jobs_timer(wm_job, 0.01, 0, NC_WINDOW);
- WM_jobs_callbacks(wm_job, ui_studiolight_icon_job_exec, NULL, NULL, ui_studiolight_icon_job_end);
- WM_jobs_start(CTX_wm_manager(C), wm_job);
- }
- }
- break;
- }
- }
- }
- }
+ Icon *icon = BKE_icon_get(icon_id);
+
+ if (icon) {
+ DrawInfo *di = icon_ensure_drawinfo(icon);
+
+ if (di) {
+ switch (di->type) {
+ case ICON_TYPE_PREVIEW: {
+ ID *id = (icon->id_type != 0) ? icon->obj : NULL;
+ PreviewImage *prv = id ? BKE_previewimg_id_ensure(id) : icon->obj;
+ /* Using jobs for screen previews crashes due to offscreen rendering.
+ * XXX would be nicer if PreviewImage could store if it supports jobs */
+ const bool use_jobs = !id || (GS(id->name) != ID_SCR);
+
+ if (prv) {
+ const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON;
+
+ if (id || (prv->tag & PRV_TAG_DEFFERED) != 0) {
+ ui_id_preview_image_render_size(C, NULL, id, prv, size, use_jobs);
+ }
+ }
+ break;
+ }
+ case ICON_TYPE_BUFFER: {
+ if (icon->obj_type == ICON_DATA_STUDIOLIGHT) {
+ if (di->data.buffer.image == NULL) {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ StudioLight *sl = icon->obj;
+ BKE_studiolight_set_free_function(sl, &ui_studiolight_free_function, wm);
+ IconImage *img = MEM_mallocN(sizeof(IconImage), __func__);
+
+ img->w = STUDIOLIGHT_ICON_SIZE;
+ img->h = STUDIOLIGHT_ICON_SIZE;
+ size_t size = STUDIOLIGHT_ICON_SIZE * STUDIOLIGHT_ICON_SIZE * sizeof(uint);
+ img->rect = MEM_mallocN(size, __func__);
+ memset(img->rect, 0, size);
+ di->data.buffer.image = img;
+
+ wmJob *wm_job = WM_jobs_get(
+ wm, CTX_wm_window(C), icon, "StudioLight Icon", 0, WM_JOB_TYPE_STUDIOLIGHT);
+ Icon **tmp = MEM_callocN(sizeof(Icon *), __func__);
+ *tmp = icon;
+ WM_jobs_customdata_set(wm_job, tmp, MEM_freeN);
+ WM_jobs_timer(wm_job, 0.01, 0, NC_WINDOW);
+ WM_jobs_callbacks(
+ wm_job, ui_studiolight_icon_job_exec, NULL, NULL, ui_studiolight_icon_job_end);
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
}
/* only called when icon has changed */
/* only call with valid pointer from UI_icon_draw */
-static void icon_set_image(
- const bContext *C, Scene *scene, ID *id, PreviewImage *prv_img, enum eIconSizes size, const bool use_job)
-{
- if (!prv_img) {
- if (G.debug & G_DEBUG) {
- printf("%s: no preview image for this ID: %s\n", __func__, id->name);
- }
- return;
- }
-
- if (prv_img->flag[size] & PRV_USER_EDITED) {
- /* user-edited preview, do not auto-update! */
- return;
- }
-
- icon_create_rect(prv_img, size);
-
- if (use_job) {
- /* Job (background) version */
- ED_preview_icon_job(C, prv_img, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]);
- }
- else {
- if (!scene) {
- scene = CTX_data_scene(C);
- }
- /* Immediate version */
- ED_preview_icon_render(CTX_data_main(C), scene, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]);
- }
+static void icon_set_image(const bContext *C,
+ Scene *scene,
+ ID *id,
+ PreviewImage *prv_img,
+ enum eIconSizes size,
+ const bool use_job)
+{
+ if (!prv_img) {
+ if (G.debug & G_DEBUG) {
+ printf("%s: no preview image for this ID: %s\n", __func__, id->name);
+ }
+ return;
+ }
+
+ if (prv_img->flag[size] & PRV_USER_EDITED) {
+ /* user-edited preview, do not auto-update! */
+ return;
+ }
+
+ icon_create_rect(prv_img, size);
+
+ if (use_job) {
+ /* Job (background) version */
+ ED_preview_icon_job(C, prv_img, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]);
+ }
+ else {
+ if (!scene) {
+ scene = CTX_data_scene(C);
+ }
+ /* Immediate version */
+ ED_preview_icon_render(
+ CTX_data_main(C), scene, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]);
+ }
}
PreviewImage *UI_icon_to_preview(int icon_id)
{
- Icon *icon = BKE_icon_get(icon_id);
-
- if (icon) {
- DrawInfo *di = (DrawInfo *)icon->drawinfo;
- if (di) {
- if (di->type == ICON_TYPE_PREVIEW) {
- PreviewImage *prv = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj;
-
- if (prv) {
- return BKE_previewimg_copy(prv);
- }
- }
- else if (di->data.buffer.image) {
- ImBuf *bbuf;
-
- bbuf = IMB_ibImageFromMemory(di->data.buffer.image->datatoc_rect, di->data.buffer.image->datatoc_size,
- IB_rect, NULL, __func__);
- if (bbuf) {
- PreviewImage *prv = BKE_previewimg_create();
-
- prv->rect[0] = bbuf->rect;
-
- prv->w[0] = bbuf->x;
- prv->h[0] = bbuf->y;
-
- bbuf->rect = NULL;
- IMB_freeImBuf(bbuf);
-
- return prv;
- }
- }
- }
- }
- return NULL;
-}
-
-static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), int rw, int rh,
- uint *rect, float alpha, const float rgb[3], const float desaturate)
-{
- ImBuf *ima = NULL;
- int draw_w = w;
- int draw_h = h;
- int draw_x = x;
- int draw_y = y;
-
- /* sanity check */
- if (w <= 0 || h <= 0 || w > 2000 || h > 2000) {
- printf("%s: icons are %i x %i pixels?\n", __func__, w, h);
- BLI_assert(!"invalid icon size");
- return;
- }
- /* modulate color */
- float col[4] = {1.0f, 1.0f, 1.0f, alpha};
-
- if (rgb) {
- col[0] = rgb[0];
- col[1] = rgb[1];
- col[2] = rgb[2];
- }
-
- /* rect contains image in 'rendersize', we only scale if needed */
- if (rw != w || rh != h) {
- /* preserve aspect ratio and center */
- if (rw > rh) {
- draw_w = w;
- draw_h = (int)(((float)rh / (float)rw) * (float)w);
- draw_y += (h - draw_h) / 2;
- }
- else if (rw < rh) {
- draw_w = (int)(((float)rw / (float)rh) * (float)h);
- draw_h = h;
- draw_x += (w - draw_w) / 2;
- }
- /* if the image is squared, the draw_ initialization values are good */
-
- /* first allocate imbuf for scaling and copy preview into it */
- ima = IMB_allocImBuf(rw, rh, 32, IB_rect);
- memcpy(ima->rect, rect, rw * rh * sizeof(uint));
- IMB_scaleImBuf(ima, draw_w, draw_h); /* scale it */
- rect = ima->rect;
- }
-
- /* draw */
- eGPUBuiltinShader shader;
- if (desaturate != 0.0f) {
- shader = GPU_SHADER_2D_IMAGE_DESATURATE_COLOR;
- }
- else {
- shader = GPU_SHADER_2D_IMAGE_COLOR;
- }
- IMMDrawPixelsTexState state = immDrawPixelsTexSetup(shader);
-
- if (shader == GPU_SHADER_2D_IMAGE_DESATURATE_COLOR) {
- immUniform1f("factor", desaturate);
- }
-
- immDrawPixelsTex(&state, draw_x, draw_y, draw_w, draw_h, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect,
- 1.0f, 1.0f, col);
-
- if (ima) {
- IMB_freeImBuf(ima);
- }
+ Icon *icon = BKE_icon_get(icon_id);
+
+ if (icon) {
+ DrawInfo *di = (DrawInfo *)icon->drawinfo;
+ if (di) {
+ if (di->type == ICON_TYPE_PREVIEW) {
+ PreviewImage *prv = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) :
+ icon->obj;
+
+ if (prv) {
+ return BKE_previewimg_copy(prv);
+ }
+ }
+ else if (di->data.buffer.image) {
+ ImBuf *bbuf;
+
+ bbuf = IMB_ibImageFromMemory(di->data.buffer.image->datatoc_rect,
+ di->data.buffer.image->datatoc_size,
+ IB_rect,
+ NULL,
+ __func__);
+ if (bbuf) {
+ PreviewImage *prv = BKE_previewimg_create();
+
+ prv->rect[0] = bbuf->rect;
+
+ prv->w[0] = bbuf->x;
+ prv->h[0] = bbuf->y;
+
+ bbuf->rect = NULL;
+ IMB_freeImBuf(bbuf);
+
+ return prv;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+static void icon_draw_rect(float x,
+ float y,
+ int w,
+ int h,
+ float UNUSED(aspect),
+ int rw,
+ int rh,
+ uint *rect,
+ float alpha,
+ const float rgb[3],
+ const float desaturate)
+{
+ ImBuf *ima = NULL;
+ int draw_w = w;
+ int draw_h = h;
+ int draw_x = x;
+ int draw_y = y;
+
+ /* sanity check */
+ if (w <= 0 || h <= 0 || w > 2000 || h > 2000) {
+ printf("%s: icons are %i x %i pixels?\n", __func__, w, h);
+ BLI_assert(!"invalid icon size");
+ return;
+ }
+ /* modulate color */
+ float col[4] = {1.0f, 1.0f, 1.0f, alpha};
+
+ if (rgb) {
+ col[0] = rgb[0];
+ col[1] = rgb[1];
+ col[2] = rgb[2];
+ }
+
+ /* rect contains image in 'rendersize', we only scale if needed */
+ if (rw != w || rh != h) {
+ /* preserve aspect ratio and center */
+ if (rw > rh) {
+ draw_w = w;
+ draw_h = (int)(((float)rh / (float)rw) * (float)w);
+ draw_y += (h - draw_h) / 2;
+ }
+ else if (rw < rh) {
+ draw_w = (int)(((float)rw / (float)rh) * (float)h);
+ draw_h = h;
+ draw_x += (w - draw_w) / 2;
+ }
+ /* if the image is squared, the draw_ initialization values are good */
+
+ /* first allocate imbuf for scaling and copy preview into it */
+ ima = IMB_allocImBuf(rw, rh, 32, IB_rect);
+ memcpy(ima->rect, rect, rw * rh * sizeof(uint));
+ IMB_scaleImBuf(ima, draw_w, draw_h); /* scale it */
+ rect = ima->rect;
+ }
+
+ /* draw */
+ eGPUBuiltinShader shader;
+ if (desaturate != 0.0f) {
+ shader = GPU_SHADER_2D_IMAGE_DESATURATE_COLOR;
+ }
+ else {
+ shader = GPU_SHADER_2D_IMAGE_COLOR;
+ }
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(shader);
+
+ if (shader == GPU_SHADER_2D_IMAGE_DESATURATE_COLOR) {
+ immUniform1f("factor", desaturate);
+ }
+
+ immDrawPixelsTex(&state,
+ draw_x,
+ draw_y,
+ draw_w,
+ draw_h,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ GL_NEAREST,
+ rect,
+ 1.0f,
+ 1.0f,
+ col);
+
+ if (ima) {
+ IMB_freeImBuf(ima);
+ }
}
/* High enough to make a difference, low enough so that
@@ -1348,669 +1430,721 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect),
#define ICON_DRAW_CACHE_SIZE 16
typedef struct IconDrawCall {
- rctf pos;
- rctf tex;
- float color[4];
+ rctf pos;
+ rctf tex;
+ float color[4];
} IconDrawCall;
static struct {
- IconDrawCall drawcall_cache[ICON_DRAW_CACHE_SIZE];
- int calls; /* Number of calls batched together */
- bool enabled;
- float mat[4][4];
+ IconDrawCall drawcall_cache[ICON_DRAW_CACHE_SIZE];
+ int calls; /* Number of calls batched together */
+ bool enabled;
+ float mat[4][4];
} g_icon_draw_cache = {{{{0}}}};
void UI_icon_draw_cache_begin(void)
{
- BLI_assert(g_icon_draw_cache.enabled == false);
- g_icon_draw_cache.enabled = true;
+ BLI_assert(g_icon_draw_cache.enabled == false);
+ g_icon_draw_cache.enabled = true;
}
static void icon_draw_cache_flush_ex(void)
{
- if (g_icon_draw_cache.calls == 0) {
- return;
- }
+ if (g_icon_draw_cache.calls == 0) {
+ return;
+ }
- /* We need to flush widget base first to ensure correct ordering. */
- UI_widgetbase_draw_cache_flush();
+ /* We need to flush widget base first to ensure correct ordering. */
+ UI_widgetbase_draw_cache_flush();
- GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, icongltex.id);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, icongltex.id);
- GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR);
- GPU_shader_bind(shader);
+ GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR);
+ GPU_shader_bind(shader);
- int img_loc = GPU_shader_get_uniform_ensure(shader, "image");
- int data_loc = GPU_shader_get_uniform_ensure(shader, "calls_data[0]");
+ int img_loc = GPU_shader_get_uniform_ensure(shader, "image");
+ int data_loc = GPU_shader_get_uniform_ensure(shader, "calls_data[0]");
- glUniform1i(img_loc, 0);
- glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)g_icon_draw_cache.drawcall_cache);
+ glUniform1i(img_loc, 0);
+ glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)g_icon_draw_cache.drawcall_cache);
- GPU_draw_primitive(GPU_PRIM_TRIS, 6 * g_icon_draw_cache.calls);
+ GPU_draw_primitive(GPU_PRIM_TRIS, 6 * g_icon_draw_cache.calls);
- glBindTexture(GL_TEXTURE_2D, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
- g_icon_draw_cache.calls = 0;
+ g_icon_draw_cache.calls = 0;
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
}
void UI_icon_draw_cache_end(void)
{
- BLI_assert(g_icon_draw_cache.enabled == true);
- g_icon_draw_cache.enabled = false;
-
- /* Don't change blend state if it's not needed. */
- if (g_icon_draw_cache.calls == 0) {
- return;
- }
+ BLI_assert(g_icon_draw_cache.enabled == true);
+ g_icon_draw_cache.enabled = false;
+
+ /* Don't change blend state if it's not needed. */
+ if (g_icon_draw_cache.calls == 0) {
+ return;
+ }
- GPU_blend(true);
- icon_draw_cache_flush_ex();
- GPU_blend(false);
+ GPU_blend(true);
+ icon_draw_cache_flush_ex();
+ GPU_blend(false);
}
-static void icon_draw_texture_cached(
- float x, float y, float w, float h, int ix, int iy,
- int UNUSED(iw), int ih, float alpha, const float rgb[3])
+static void icon_draw_texture_cached(float x,
+ float y,
+ float w,
+ float h,
+ int ix,
+ int iy,
+ int UNUSED(iw),
+ int ih,
+ float alpha,
+ const float rgb[3])
{
- float mvp[4][4];
- GPU_matrix_model_view_projection_get(mvp);
+ float mvp[4][4];
+ GPU_matrix_model_view_projection_get(mvp);
- IconDrawCall *call = &g_icon_draw_cache.drawcall_cache[g_icon_draw_cache.calls];
- g_icon_draw_cache.calls++;
+ IconDrawCall *call = &g_icon_draw_cache.drawcall_cache[g_icon_draw_cache.calls];
+ g_icon_draw_cache.calls++;
- /* Manual mat4*vec2 */
- call->pos.xmin = x * mvp[0][0] + y * mvp[1][0] + mvp[3][0];
- call->pos.ymin = x * mvp[0][1] + y * mvp[1][1] + mvp[3][1];
- call->pos.xmax = call->pos.xmin + w * mvp[0][0] + h * mvp[1][0];
- call->pos.ymax = call->pos.ymin + w * mvp[0][1] + h * mvp[1][1];
+ /* Manual mat4*vec2 */
+ call->pos.xmin = x * mvp[0][0] + y * mvp[1][0] + mvp[3][0];
+ call->pos.ymin = x * mvp[0][1] + y * mvp[1][1] + mvp[3][1];
+ call->pos.xmax = call->pos.xmin + w * mvp[0][0] + h * mvp[1][0];
+ call->pos.ymax = call->pos.ymin + w * mvp[0][1] + h * mvp[1][1];
- call->tex.xmin = ix * icongltex.invw;
- call->tex.xmax = (ix + ih) * icongltex.invw;
- call->tex.ymin = iy * icongltex.invh;
- call->tex.ymax = (iy + ih) * icongltex.invh;
+ call->tex.xmin = ix * icongltex.invw;
+ call->tex.xmax = (ix + ih) * icongltex.invw;
+ call->tex.ymin = iy * icongltex.invh;
+ call->tex.ymax = (iy + ih) * icongltex.invh;
- if (rgb) {
- copy_v4_fl4(call->color, rgb[0], rgb[1], rgb[2], alpha);
- }
- else {
- copy_v4_fl(call->color, alpha);
- }
+ if (rgb) {
+ copy_v4_fl4(call->color, rgb[0], rgb[1], rgb[2], alpha);
+ }
+ else {
+ copy_v4_fl(call->color, alpha);
+ }
- if (g_icon_draw_cache.calls == ICON_DRAW_CACHE_SIZE) {
- icon_draw_cache_flush_ex();
- }
+ if (g_icon_draw_cache.calls == ICON_DRAW_CACHE_SIZE) {
+ icon_draw_cache_flush_ex();
+ }
}
-static void icon_draw_texture(
- float x, float y, float w, float h, int ix, int iy,
- int iw, int ih, float alpha, const float rgb[3])
+static void icon_draw_texture(float x,
+ float y,
+ float w,
+ float h,
+ int ix,
+ int iy,
+ int iw,
+ int ih,
+ float alpha,
+ const float rgb[3])
{
- if (g_icon_draw_cache.enabled) {
- icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb);
- return;
- }
+ if (g_icon_draw_cache.enabled) {
+ icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb);
+ return;
+ }
- /* We need to flush widget base first to ensure correct ordering. */
- UI_widgetbase_draw_cache_flush();
+ /* We need to flush widget base first to ensure correct ordering. */
+ UI_widgetbase_draw_cache_flush();
- GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- float x1, x2, y1, y2;
+ float x1, x2, y1, y2;
- x1 = ix * icongltex.invw;
- x2 = (ix + ih) * icongltex.invw;
- y1 = iy * icongltex.invh;
- y2 = (iy + ih) * icongltex.invh;
+ x1 = ix * icongltex.invw;
+ x2 = (ix + ih) * icongltex.invw;
+ y1 = iy * icongltex.invh;
+ y2 = (iy + ih) * icongltex.invh;
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, icongltex.id);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, icongltex.id);
- GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
- GPU_shader_bind(shader);
+ GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
+ GPU_shader_bind(shader);
- if (rgb) {
- glUniform4f(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), rgb[0], rgb[1], rgb[2], alpha);
- }
- else {
- glUniform4f(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), alpha, alpha, alpha, alpha);
- }
+ if (rgb) {
+ glUniform4f(
+ GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), rgb[0], rgb[1], rgb[2], alpha);
+ }
+ else {
+ glUniform4f(
+ GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), alpha, alpha, alpha, alpha);
+ }
- glUniform1i(GPU_shader_get_uniform_ensure(shader, "image"), 0);
- glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_icon"), x1, y1, x2, y2);
- glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_geom"), x, y, x + w, y + h);
+ glUniform1i(GPU_shader_get_uniform_ensure(shader, "image"), 0);
+ glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_icon"), x1, y1, x2, y2);
+ glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_geom"), x, y, x + w, y + h);
- GPU_draw_primitive(GPU_PRIM_TRI_STRIP, 4);
+ GPU_draw_primitive(GPU_PRIM_TRI_STRIP, 4);
- glBindTexture(GL_TEXTURE_2D, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
}
/* Drawing size for preview images */
static int get_draw_size(enum eIconSizes size)
{
- switch (size) {
- case ICON_SIZE_ICON:
- return ICON_DEFAULT_HEIGHT;
- case ICON_SIZE_PREVIEW:
- return PREVIEW_DEFAULT_HEIGHT;
- default:
- return 0;
- }
-}
-
-
-
-static void icon_draw_size(
- float x, float y, int icon_id, float aspect, float alpha, const float rgb[3],
- enum eIconSizes size, int draw_size, const float desaturate, const char mono_rgba[4])
-{
- bTheme *btheme = UI_GetTheme();
- Icon *icon = NULL;
- IconImage *iimg;
- const float fdraw_size = (float)draw_size;
- int w, h;
-
- icon = BKE_icon_get(icon_id);
- alpha *= btheme->tui.icon_alpha;
-
- if (icon == NULL) {
- if (G.debug & G_DEBUG) {
- printf("%s: Internal error, no icon for icon ID: %d\n", __func__, icon_id);
- }
- return;
- }
-
- /* scale width and height according to aspect */
- w = (int)(fdraw_size / aspect + 0.5f);
- h = (int)(fdraw_size / aspect + 0.5f);
-
- DrawInfo *di = icon_ensure_drawinfo(icon);
-
- /* We need to flush widget base first to ensure correct ordering. */
- UI_widgetbase_draw_cache_flush();
-
- if (di->type == ICON_TYPE_VECTOR) {
- /* vector icons use the uiBlock transformation, they are not drawn
- * with untransformed coordinates like the other icons */
- di->data.vector.func((int)x, (int)y, w, h, 1.0f);
- }
- else if (di->type == ICON_TYPE_GEOM) {
+ switch (size) {
+ case ICON_SIZE_ICON:
+ return ICON_DEFAULT_HEIGHT;
+ case ICON_SIZE_PREVIEW:
+ return PREVIEW_DEFAULT_HEIGHT;
+ default:
+ return 0;
+ }
+}
+
+static void icon_draw_size(float x,
+ float y,
+ int icon_id,
+ float aspect,
+ float alpha,
+ const float rgb[3],
+ enum eIconSizes size,
+ int draw_size,
+ const float desaturate,
+ const char mono_rgba[4])
+{
+ bTheme *btheme = UI_GetTheme();
+ Icon *icon = NULL;
+ IconImage *iimg;
+ const float fdraw_size = (float)draw_size;
+ int w, h;
+
+ icon = BKE_icon_get(icon_id);
+ alpha *= btheme->tui.icon_alpha;
+
+ if (icon == NULL) {
+ if (G.debug & G_DEBUG) {
+ printf("%s: Internal error, no icon for icon ID: %d\n", __func__, icon_id);
+ }
+ return;
+ }
+
+ /* scale width and height according to aspect */
+ w = (int)(fdraw_size / aspect + 0.5f);
+ h = (int)(fdraw_size / aspect + 0.5f);
+
+ DrawInfo *di = icon_ensure_drawinfo(icon);
+
+ /* We need to flush widget base first to ensure correct ordering. */
+ UI_widgetbase_draw_cache_flush();
+
+ if (di->type == ICON_TYPE_VECTOR) {
+ /* vector icons use the uiBlock transformation, they are not drawn
+ * with untransformed coordinates like the other icons */
+ di->data.vector.func((int)x, (int)y, w, h, 1.0f);
+ }
+ else if (di->type == ICON_TYPE_GEOM) {
#ifdef USE_UI_TOOLBAR_HACK
- /* TODO(campbell): scale icons up for toolbar,
- * we need a way to detect larger buttons and do this automatic. */
- {
- float scale = (float)ICON_DEFAULT_HEIGHT_TOOLBAR / (float)ICON_DEFAULT_HEIGHT;
- y = (y + (h / 2)) - ((h * scale) / 2);
- w *= scale;
- h *= scale;
- }
+ /* TODO(campbell): scale icons up for toolbar,
+ * we need a way to detect larger buttons and do this automatic. */
+ {
+ float scale = (float)ICON_DEFAULT_HEIGHT_TOOLBAR / (float)ICON_DEFAULT_HEIGHT;
+ y = (y + (h / 2)) - ((h * scale) / 2);
+ w *= scale;
+ h *= scale;
+ }
#endif
- /* 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) {
- IMB_freeImBuf(ibuf);
- }
- ibuf = BKE_icon_geom_rasterize(icon->obj, w, h);
- di->data.geom.image_cache = ibuf;
- }
-
- GPU_blend_set_func_separate(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- icon_draw_rect(x, y, w, h, aspect, w, h, ibuf->rect, alpha, rgb, desaturate);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- }
- else if (di->type == ICON_TYPE_EVENT) {
- const short event_type = di->data.input.event_type;
- const short event_value = di->data.input.event_value;
- icon_draw_rect_input(x, y, w, h, alpha, event_type, event_value);
- }
- else if (di->type == ICON_TYPE_COLOR_TEXTURE) {
- /* texture image use premul alpha for correct scaling */
- icon_draw_texture(x, y, (float)w, (float)h, di->data.texture.x, di->data.texture.y,
- di->data.texture.w, di->data.texture.h, alpha, rgb);
- }
- else if (di->type == ICON_TYPE_MONO_TEXTURE) {
- /* icon that matches text color, assumed to be white */
- float color[4];
- if (!UI_GetIconThemeColor4fv(di->data.texture.theme_color, color)) {
- if (mono_rgba) {
- rgba_uchar_to_float(color, (const uchar *)mono_rgba);
- }
- else {
- UI_GetThemeColor4fv(TH_TEXT, color);
- }
- }
-
- if (rgb) {
- mul_v3_v3(color, rgb);
- }
-
- mul_v4_fl(color, alpha);
-
- icon_draw_texture(x, y, (float)w, (float)h, di->data.texture.x, di->data.texture.y,
- di->data.texture.w, di->data.texture.h, color[3], color);
- }
-
- else if (di->type == ICON_TYPE_BUFFER) {
- /* it is a builtin icon */
- iimg = di->data.buffer.image;
+ /* 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) {
+ IMB_freeImBuf(ibuf);
+ }
+ ibuf = BKE_icon_geom_rasterize(icon->obj, w, h);
+ di->data.geom.image_cache = ibuf;
+ }
+
+ GPU_blend_set_func_separate(
+ GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ icon_draw_rect(x, y, w, h, aspect, w, h, ibuf->rect, alpha, rgb, desaturate);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ }
+ else if (di->type == ICON_TYPE_EVENT) {
+ const short event_type = di->data.input.event_type;
+ const short event_value = di->data.input.event_value;
+ icon_draw_rect_input(x, y, w, h, alpha, event_type, event_value);
+ }
+ else if (di->type == ICON_TYPE_COLOR_TEXTURE) {
+ /* texture image use premul alpha for correct scaling */
+ icon_draw_texture(x,
+ y,
+ (float)w,
+ (float)h,
+ di->data.texture.x,
+ di->data.texture.y,
+ di->data.texture.w,
+ di->data.texture.h,
+ alpha,
+ rgb);
+ }
+ else if (di->type == ICON_TYPE_MONO_TEXTURE) {
+ /* icon that matches text color, assumed to be white */
+ float color[4];
+ if (!UI_GetIconThemeColor4fv(di->data.texture.theme_color, color)) {
+ if (mono_rgba) {
+ rgba_uchar_to_float(color, (const uchar *)mono_rgba);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_TEXT, color);
+ }
+ }
+
+ if (rgb) {
+ mul_v3_v3(color, rgb);
+ }
+
+ mul_v4_fl(color, alpha);
+
+ icon_draw_texture(x,
+ y,
+ (float)w,
+ (float)h,
+ di->data.texture.x,
+ di->data.texture.y,
+ di->data.texture.w,
+ di->data.texture.h,
+ color[3],
+ color);
+ }
+
+ else if (di->type == ICON_TYPE_BUFFER) {
+ /* it is a builtin icon */
+ iimg = di->data.buffer.image;
#ifndef WITH_HEADLESS
- icon_verify_datatoc(iimg);
+ icon_verify_datatoc(iimg);
#endif
- if (!iimg->rect) {
- /* something has gone wrong! */
- return;
- }
-
- icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, rgb, desaturate);
- }
- else if (di->type == ICON_TYPE_PREVIEW) {
- PreviewImage *pi = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj;
-
- if (pi) {
- /* no create icon on this level in code */
- if (!pi->rect[size]) {
- /* Something has gone wrong! */
- return;
- }
-
- /* Preview images use premultiplied alpha. */
- GPU_blend_set_func_separate(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- icon_draw_rect(x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], alpha, rgb, desaturate);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- }
- }
- else if (di->type == ICON_TYPE_GPLAYER) {
- BLI_assert(icon->obj != NULL);
-
- /* Just draw a colored rect - Like for vicon_colorset_draw() */
+ if (!iimg->rect) {
+ /* something has gone wrong! */
+ return;
+ }
+
+ icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, rgb, desaturate);
+ }
+ else if (di->type == ICON_TYPE_PREVIEW) {
+ PreviewImage *pi = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) :
+ icon->obj;
+
+ if (pi) {
+ /* no create icon on this level in code */
+ if (!pi->rect[size]) {
+ /* Something has gone wrong! */
+ return;
+ }
+
+ /* Preview images use premultiplied alpha. */
+ GPU_blend_set_func_separate(
+ GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ icon_draw_rect(
+ x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], alpha, rgb, desaturate);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ }
+ }
+ else if (di->type == ICON_TYPE_GPLAYER) {
+ BLI_assert(icon->obj != NULL);
+
+ /* Just draw a colored rect - Like for vicon_colorset_draw() */
#ifndef WITH_HEADLESS
- vicon_gplayer_color_draw(icon, (int)x, (int)y, w, h);
+ vicon_gplayer_color_draw(icon, (int)x, (int)y, w, h);
#endif
- }
+ }
}
static void ui_id_preview_image_render_size(
- const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job)
+ const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job)
{
- /* changed only ever set by dynamic icons */
- if (((pi->flag[size] & PRV_CHANGED) || !pi->rect[size])) {
- /* create the rect if necessary */
- icon_set_image(C, scene, id, pi, size, use_job);
+ /* changed only ever set by dynamic icons */
+ if (((pi->flag[size] & PRV_CHANGED) || !pi->rect[size])) {
+ /* create the rect if necessary */
+ icon_set_image(C, scene, id, pi, size, use_job);
- pi->flag[size] &= ~PRV_CHANGED;
- }
+ pi->flag[size] &= ~PRV_CHANGED;
+ }
}
void UI_id_icon_render(const bContext *C, Scene *scene, ID *id, const bool big, const bool use_job)
{
- PreviewImage *pi = BKE_previewimg_id_ensure(id);
+ PreviewImage *pi = BKE_previewimg_id_ensure(id);
- if (pi) {
- if (big) {
- /* bigger preview size */
- ui_id_preview_image_render_size(C, scene, id, pi, ICON_SIZE_PREVIEW, use_job);
- }
- else {
- /* icon size */
- ui_id_preview_image_render_size(C, scene, id, pi, ICON_SIZE_ICON, use_job);
- }
- }
+ if (pi) {
+ if (big) {
+ /* bigger preview size */
+ ui_id_preview_image_render_size(C, scene, id, pi, ICON_SIZE_PREVIEW, use_job);
+ }
+ else {
+ /* icon size */
+ ui_id_preview_image_render_size(C, scene, id, pi, ICON_SIZE_ICON, use_job);
+ }
+ }
}
static void ui_id_icon_render(const bContext *C, ID *id, bool use_jobs)
{
- PreviewImage *pi = BKE_previewimg_id_ensure(id);
- enum eIconSizes i;
+ PreviewImage *pi = BKE_previewimg_id_ensure(id);
+ enum eIconSizes i;
- if (!pi) {
- return;
- }
+ if (!pi) {
+ return;
+ }
- for (i = 0; i < NUM_ICON_SIZES; i++) {
- /* check if rect needs to be created; changed
- * only set by dynamic icons */
- if (((pi->flag[i] & PRV_CHANGED) || !pi->rect[i])) {
- icon_set_image(C, NULL, id, pi, i, use_jobs);
- pi->flag[i] &= ~PRV_CHANGED;
- }
- }
+ for (i = 0; i < NUM_ICON_SIZES; i++) {
+ /* check if rect needs to be created; changed
+ * only set by dynamic icons */
+ if (((pi->flag[i] & PRV_CHANGED) || !pi->rect[i])) {
+ icon_set_image(C, NULL, id, pi, i, use_jobs);
+ pi->flag[i] &= ~PRV_CHANGED;
+ }
+ }
}
-
static int ui_id_brush_get_icon(const bContext *C, ID *id)
{
- Brush *br = (Brush *)id;
-
- if (br->flag & BRUSH_CUSTOM_ICON) {
- BKE_icon_id_ensure(id);
- ui_id_icon_render(C, id, true);
- }
- else {
- WorkSpace *workspace = CTX_wm_workspace(C);
- 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;
- /* When in an unsupported space. */
- if (!ELEM(space_type, SPACE_VIEW3D, SPACE_IMAGE)) {
- space_type = workspace->tools_space_type;
- }
-
- /* XXX: this is not nice, should probably make brushes
- * be strictly in one paint mode only to avoid
- * checking various context stuff here */
-
- if ((space_type == SPACE_VIEW3D) && ob) {
- if (ob->mode & OB_MODE_SCULPT) {
- paint_mode = PAINT_MODE_SCULPT;
- }
- else if (ob->mode & OB_MODE_VERTEX_PAINT) {
- paint_mode = PAINT_MODE_VERTEX;
- }
- else if (ob->mode & OB_MODE_WEIGHT_PAINT) {
- paint_mode = PAINT_MODE_WEIGHT;
- }
- else if (ob->mode & OB_MODE_TEXTURE_PAINT) {
- paint_mode = PAINT_MODE_TEXTURE_3D;
- }
- }
- else if (space_type == SPACE_IMAGE) {
- int sima_mode;
- if (sa->spacetype == space_type) {
- SpaceImage *sima = sa->spacedata.first;
- sima_mode = sima->mode;
- }
- else {
- sima_mode = workspace->tools_mode;
- }
-
- if (sima_mode == SI_MODE_PAINT) {
- paint_mode = PAINT_MODE_TEXTURE_2D;
- }
- }
-
- /* reset the icon */
- if ((ob != NULL) &&
- (ob->mode & OB_MODE_PAINT_GPENCIL) &&
- (br->gpencil_settings != NULL))
- {
- switch (br->gpencil_settings->icon_id) {
- case GP_BRUSH_ICON_PENCIL:
- br->id.icon_id = ICON_GPBRUSH_PENCIL;
- break;
- case GP_BRUSH_ICON_PEN:
- br->id.icon_id = ICON_GPBRUSH_PEN;
- break;
- case GP_BRUSH_ICON_INK:
- br->id.icon_id = ICON_GPBRUSH_INK;
- break;
- case GP_BRUSH_ICON_INKNOISE:
- br->id.icon_id = ICON_GPBRUSH_INKNOISE;
- break;
- case GP_BRUSH_ICON_BLOCK:
- br->id.icon_id = ICON_GPBRUSH_BLOCK;
- break;
- case GP_BRUSH_ICON_MARKER:
- br->id.icon_id = ICON_GPBRUSH_MARKER;
- break;
- case GP_BRUSH_ICON_FILL:
- br->id.icon_id = ICON_GPBRUSH_FILL;
- break;
- case GP_BRUSH_ICON_ERASE_SOFT:
- br->id.icon_id = ICON_GPBRUSH_ERASE_SOFT;
- break;
- case GP_BRUSH_ICON_ERASE_HARD:
- br->id.icon_id = ICON_GPBRUSH_ERASE_HARD;
- break;
- case GP_BRUSH_ICON_ERASE_STROKE:
- br->id.icon_id = ICON_GPBRUSH_ERASE_STROKE;
- break;
- default:
- br->id.icon_id = ICON_GPBRUSH_PEN;
- break;
- }
- return id->icon_id;
- }
- else if (paint_mode != PAINT_MODE_INVALID) {
- items = BKE_paint_get_tool_enum_from_paintmode(paint_mode);
- const uint tool_offset = BKE_paint_get_brush_tool_offset_from_paintmode(paint_mode);
- const int tool_type = *(char *)POINTER_OFFSET(br, tool_offset);
- if (!items || !RNA_enum_icon_from_value(items, tool_type, &id->icon_id)) {
- id->icon_id = 0;
- }
- }
- else {
- id->icon_id = 0;
- }
- }
-
- return id->icon_id;
+ Brush *br = (Brush *)id;
+
+ if (br->flag & BRUSH_CUSTOM_ICON) {
+ BKE_icon_id_ensure(id);
+ ui_id_icon_render(C, id, true);
+ }
+ else {
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ 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;
+ /* When in an unsupported space. */
+ if (!ELEM(space_type, SPACE_VIEW3D, SPACE_IMAGE)) {
+ space_type = workspace->tools_space_type;
+ }
+
+ /* XXX: this is not nice, should probably make brushes
+ * be strictly in one paint mode only to avoid
+ * checking various context stuff here */
+
+ if ((space_type == SPACE_VIEW3D) && ob) {
+ if (ob->mode & OB_MODE_SCULPT) {
+ paint_mode = PAINT_MODE_SCULPT;
+ }
+ else if (ob->mode & OB_MODE_VERTEX_PAINT) {
+ paint_mode = PAINT_MODE_VERTEX;
+ }
+ else if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ paint_mode = PAINT_MODE_WEIGHT;
+ }
+ else if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ paint_mode = PAINT_MODE_TEXTURE_3D;
+ }
+ }
+ else if (space_type == SPACE_IMAGE) {
+ int sima_mode;
+ if (sa->spacetype == space_type) {
+ SpaceImage *sima = sa->spacedata.first;
+ sima_mode = sima->mode;
+ }
+ else {
+ sima_mode = workspace->tools_mode;
+ }
+
+ if (sima_mode == SI_MODE_PAINT) {
+ paint_mode = PAINT_MODE_TEXTURE_2D;
+ }
+ }
+
+ /* reset the icon */
+ if ((ob != NULL) && (ob->mode & OB_MODE_PAINT_GPENCIL) && (br->gpencil_settings != NULL)) {
+ switch (br->gpencil_settings->icon_id) {
+ case GP_BRUSH_ICON_PENCIL:
+ br->id.icon_id = ICON_GPBRUSH_PENCIL;
+ break;
+ case GP_BRUSH_ICON_PEN:
+ br->id.icon_id = ICON_GPBRUSH_PEN;
+ break;
+ case GP_BRUSH_ICON_INK:
+ br->id.icon_id = ICON_GPBRUSH_INK;
+ break;
+ case GP_BRUSH_ICON_INKNOISE:
+ br->id.icon_id = ICON_GPBRUSH_INKNOISE;
+ break;
+ case GP_BRUSH_ICON_BLOCK:
+ br->id.icon_id = ICON_GPBRUSH_BLOCK;
+ break;
+ case GP_BRUSH_ICON_MARKER:
+ br->id.icon_id = ICON_GPBRUSH_MARKER;
+ break;
+ case GP_BRUSH_ICON_FILL:
+ br->id.icon_id = ICON_GPBRUSH_FILL;
+ break;
+ case GP_BRUSH_ICON_ERASE_SOFT:
+ br->id.icon_id = ICON_GPBRUSH_ERASE_SOFT;
+ break;
+ case GP_BRUSH_ICON_ERASE_HARD:
+ br->id.icon_id = ICON_GPBRUSH_ERASE_HARD;
+ break;
+ case GP_BRUSH_ICON_ERASE_STROKE:
+ br->id.icon_id = ICON_GPBRUSH_ERASE_STROKE;
+ break;
+ default:
+ br->id.icon_id = ICON_GPBRUSH_PEN;
+ break;
+ }
+ return id->icon_id;
+ }
+ else if (paint_mode != PAINT_MODE_INVALID) {
+ items = BKE_paint_get_tool_enum_from_paintmode(paint_mode);
+ const uint tool_offset = BKE_paint_get_brush_tool_offset_from_paintmode(paint_mode);
+ const int tool_type = *(char *)POINTER_OFFSET(br, tool_offset);
+ if (!items || !RNA_enum_icon_from_value(items, tool_type, &id->icon_id)) {
+ id->icon_id = 0;
+ }
+ }
+ else {
+ id->icon_id = 0;
+ }
+ }
+
+ return id->icon_id;
}
static int ui_id_screen_get_icon(const bContext *C, ID *id)
{
- BKE_icon_id_ensure(id);
- /* Don't use jobs here, offscreen rendering doesn't like this and crashes. */
- ui_id_icon_render(C, id, false);
+ BKE_icon_id_ensure(id);
+ /* Don't use jobs here, offscreen rendering doesn't like this and crashes. */
+ ui_id_icon_render(C, id, false);
- return id->icon_id;
+ return id->icon_id;
}
int ui_id_icon_get(const bContext *C, ID *id, const bool big)
{
- int iconid = 0;
-
- /* icon */
- switch (GS(id->name)) {
- case ID_BR:
- iconid = ui_id_brush_get_icon(C, id);
- break;
- case ID_MA: /* fall through */
- case ID_TE: /* fall through */
- case ID_IM: /* fall through */
- case ID_WO: /* fall through */
- case ID_LA: /* fall through */
- iconid = BKE_icon_id_ensure(id);
- /* checks if not exists, or changed */
- UI_id_icon_render(C, NULL, id, big, true);
- break;
- case ID_SCR:
- iconid = ui_id_screen_get_icon(C, id);
- break;
- default:
- break;
- }
-
- return iconid;
+ int iconid = 0;
+
+ /* icon */
+ switch (GS(id->name)) {
+ case ID_BR:
+ iconid = ui_id_brush_get_icon(C, id);
+ break;
+ case ID_MA: /* fall through */
+ case ID_TE: /* fall through */
+ case ID_IM: /* fall through */
+ case ID_WO: /* fall through */
+ case ID_LA: /* fall through */
+ iconid = BKE_icon_id_ensure(id);
+ /* checks if not exists, or changed */
+ UI_id_icon_render(C, NULL, id, big, true);
+ break;
+ case ID_SCR:
+ iconid = ui_id_screen_get_icon(C, id);
+ break;
+ default:
+ break;
+ }
+
+ return iconid;
}
int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big)
{
- ID *id = NULL;
-
- if (!ptr->data) {
- return rnaicon;
- }
-
- /* try ID, material, texture or dynapaint slot */
- if (RNA_struct_is_ID(ptr->type)) {
- id = ptr->id.data;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_MaterialSlot)) {
- id = RNA_pointer_get(ptr, "material").data;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_TextureSlot)) {
- id = RNA_pointer_get(ptr, "texture").data;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_DynamicPaintSurface)) {
- DynamicPaintSurface *surface = ptr->data;
-
- if (surface->format == MOD_DPAINT_SURFACE_F_PTEX) {
- return ICON_SHADING_TEXTURE;
- }
- else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
- return ICON_OUTLINER_DATA_MESH;
- }
- else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
- return ICON_FILE_IMAGE;
- }
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_StudioLight)) {
- StudioLight *sl = ptr->data;
- switch (sl->flag & STUDIOLIGHT_FLAG_ORIENTATIONS) {
- case STUDIOLIGHT_TYPE_STUDIO:
- return sl->icon_id_irradiance;
- case STUDIOLIGHT_TYPE_WORLD:
- default:
- return sl->icon_id_radiance;
- case STUDIOLIGHT_TYPE_MATCAP:
- return sl->icon_id_matcap;
- }
- }
-
- /* get icon from ID */
- if (id) {
- int icon = ui_id_icon_get(C, id, big);
-
- return icon ? icon : rnaicon;
- }
-
- return rnaicon;
+ ID *id = NULL;
+
+ if (!ptr->data) {
+ return rnaicon;
+ }
+
+ /* try ID, material, texture or dynapaint slot */
+ if (RNA_struct_is_ID(ptr->type)) {
+ id = ptr->id.data;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_MaterialSlot)) {
+ id = RNA_pointer_get(ptr, "material").data;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_TextureSlot)) {
+ id = RNA_pointer_get(ptr, "texture").data;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_DynamicPaintSurface)) {
+ DynamicPaintSurface *surface = ptr->data;
+
+ if (surface->format == MOD_DPAINT_SURFACE_F_PTEX) {
+ return ICON_SHADING_TEXTURE;
+ }
+ else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
+ return ICON_OUTLINER_DATA_MESH;
+ }
+ else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
+ return ICON_FILE_IMAGE;
+ }
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_StudioLight)) {
+ StudioLight *sl = ptr->data;
+ switch (sl->flag & STUDIOLIGHT_FLAG_ORIENTATIONS) {
+ case STUDIOLIGHT_TYPE_STUDIO:
+ return sl->icon_id_irradiance;
+ case STUDIOLIGHT_TYPE_WORLD:
+ default:
+ return sl->icon_id_radiance;
+ case STUDIOLIGHT_TYPE_MATCAP:
+ return sl->icon_id_matcap;
+ }
+ }
+
+ /* get icon from ID */
+ if (id) {
+ int icon = ui_id_icon_get(C, id, big);
+
+ return icon ? icon : rnaicon;
+ }
+
+ return rnaicon;
}
int UI_idcode_icon_get(const int idcode)
{
- switch (idcode) {
- case ID_AC:
- return ICON_ACTION;
- case ID_AR:
- return ICON_ARMATURE_DATA;
- case ID_BR:
- return ICON_BRUSH_DATA;
- case ID_CA:
- return ICON_CAMERA_DATA;
- case ID_CF:
- return ICON_FILE;
- case ID_CU:
- return ICON_CURVE_DATA;
- case ID_GD:
- return ICON_GREASEPENCIL;
- case ID_GR:
- return ICON_GROUP;
- case ID_IM:
- return ICON_IMAGE_DATA;
- case ID_LA:
- return ICON_LIGHT_DATA;
- case ID_LS:
- return ICON_LINE_DATA;
- case ID_LT:
- return ICON_LATTICE_DATA;
- case ID_MA:
- return ICON_MATERIAL_DATA;
- case ID_MB:
- return ICON_META_DATA;
- case ID_MC:
- return ICON_TRACKER;
- case ID_ME:
- return ICON_MESH_DATA;
- case ID_MSK:
- return ICON_MOD_MASK; /* TODO! this would need its own icon! */
- case ID_NT:
- return ICON_NODETREE;
- case ID_OB:
- return ICON_OBJECT_DATA;
- case ID_PA:
- return ICON_PARTICLE_DATA;
- case ID_PAL:
- return ICON_COLOR; /* TODO! this would need its own icon! */
- case ID_PC:
- return ICON_CURVE_BEZCURVE; /* TODO! this would need its own icon! */
- case ID_LP:
- return ICON_LIGHTPROBE_CUBEMAP;
- case ID_SCE:
- return ICON_SCENE_DATA;
- case ID_SPK:
- return ICON_SPEAKER;
- case ID_SO:
- return ICON_SOUND;
- case ID_TE:
- return ICON_TEXTURE_DATA;
- case ID_TXT:
- return ICON_TEXT;
- case ID_VF:
- return ICON_FONT_DATA;
- case ID_WO:
- return ICON_WORLD_DATA;
- default:
- return ICON_NONE;
- }
-}
-
-static void icon_draw_at_size(
- float x, float y, int icon_id, float aspect, float alpha,
- enum eIconSizes size, const float desaturate, const char mono_color[4])
-{
- int draw_size = get_draw_size(size);
- icon_draw_size(x, y, icon_id, aspect, alpha, NULL, size, draw_size, desaturate, mono_color);
-}
-
-void UI_icon_draw_aspect(float x, float y, int icon_id, float aspect, float alpha, const char mono_color[4])
-{
- icon_draw_at_size(x, y, icon_id, aspect, alpha, ICON_SIZE_ICON, 0.0f, mono_color);
-}
-
-void UI_icon_draw_aspect_color(float x, float y, int icon_id, float aspect, const float rgb[3], const char mono_color[4])
-{
- int draw_size = get_draw_size(ICON_SIZE_ICON);
- icon_draw_size(x, y, icon_id, aspect, 1.0f, rgb, ICON_SIZE_ICON, draw_size, false, mono_color);
-}
-
-void UI_icon_draw_desaturate(float x, float y, int icon_id, float aspect, float alpha, float desaturate, const char mono_color[4])
-{
- icon_draw_at_size(x, y, icon_id, aspect, alpha, ICON_SIZE_ICON, desaturate, mono_color);
+ switch (idcode) {
+ case ID_AC:
+ return ICON_ACTION;
+ case ID_AR:
+ return ICON_ARMATURE_DATA;
+ case ID_BR:
+ return ICON_BRUSH_DATA;
+ case ID_CA:
+ return ICON_CAMERA_DATA;
+ case ID_CF:
+ return ICON_FILE;
+ case ID_CU:
+ return ICON_CURVE_DATA;
+ case ID_GD:
+ return ICON_GREASEPENCIL;
+ case ID_GR:
+ return ICON_GROUP;
+ case ID_IM:
+ return ICON_IMAGE_DATA;
+ case ID_LA:
+ return ICON_LIGHT_DATA;
+ case ID_LS:
+ return ICON_LINE_DATA;
+ case ID_LT:
+ return ICON_LATTICE_DATA;
+ case ID_MA:
+ return ICON_MATERIAL_DATA;
+ case ID_MB:
+ return ICON_META_DATA;
+ case ID_MC:
+ return ICON_TRACKER;
+ case ID_ME:
+ return ICON_MESH_DATA;
+ case ID_MSK:
+ return ICON_MOD_MASK; /* TODO! this would need its own icon! */
+ case ID_NT:
+ return ICON_NODETREE;
+ case ID_OB:
+ return ICON_OBJECT_DATA;
+ case ID_PA:
+ return ICON_PARTICLE_DATA;
+ case ID_PAL:
+ return ICON_COLOR; /* TODO! this would need its own icon! */
+ case ID_PC:
+ return ICON_CURVE_BEZCURVE; /* TODO! this would need its own icon! */
+ case ID_LP:
+ return ICON_LIGHTPROBE_CUBEMAP;
+ case ID_SCE:
+ return ICON_SCENE_DATA;
+ case ID_SPK:
+ return ICON_SPEAKER;
+ case ID_SO:
+ return ICON_SOUND;
+ case ID_TE:
+ return ICON_TEXTURE_DATA;
+ case ID_TXT:
+ return ICON_TEXT;
+ case ID_VF:
+ return ICON_FONT_DATA;
+ case ID_WO:
+ return ICON_WORLD_DATA;
+ default:
+ return ICON_NONE;
+ }
+}
+
+static void icon_draw_at_size(float x,
+ float y,
+ int icon_id,
+ float aspect,
+ float alpha,
+ enum eIconSizes size,
+ const float desaturate,
+ const char mono_color[4])
+{
+ int draw_size = get_draw_size(size);
+ icon_draw_size(x, y, icon_id, aspect, alpha, NULL, size, draw_size, desaturate, mono_color);
+}
+
+void UI_icon_draw_aspect(
+ float x, float y, int icon_id, float aspect, float alpha, const char mono_color[4])
+{
+ icon_draw_at_size(x, y, icon_id, aspect, alpha, ICON_SIZE_ICON, 0.0f, mono_color);
+}
+
+void UI_icon_draw_aspect_color(
+ float x, float y, int icon_id, float aspect, const float rgb[3], const char mono_color[4])
+{
+ int draw_size = get_draw_size(ICON_SIZE_ICON);
+ icon_draw_size(x, y, icon_id, aspect, 1.0f, rgb, ICON_SIZE_ICON, draw_size, false, mono_color);
+}
+
+void UI_icon_draw_desaturate(float x,
+ float y,
+ int icon_id,
+ float aspect,
+ float alpha,
+ float desaturate,
+ const char mono_color[4])
+{
+ icon_draw_at_size(x, y, icon_id, aspect, alpha, ICON_SIZE_ICON, desaturate, mono_color);
}
/* draws icon with dpi scale factor */
void UI_icon_draw(float x, float y, int icon_id)
{
- UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, 1.0f, NULL);
+ UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, 1.0f, NULL);
}
void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha)
{
- UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, alpha, NULL);
+ UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, alpha, NULL);
}
void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha)
{
- icon_draw_size(x, y, icon_id, 1.0f, alpha, NULL, ICON_SIZE_ICON, size, false, NULL);
+ icon_draw_size(x, y, icon_id, 1.0f, alpha, NULL, ICON_SIZE_ICON, size, false, NULL);
}
void UI_icon_draw_preview(float x, float y, int icon_id)
{
- icon_draw_at_size(x, y, icon_id, 1.0f, 1.0f, ICON_SIZE_PREVIEW, false, NULL);
+ icon_draw_at_size(x, y, icon_id, 1.0f, 1.0f, ICON_SIZE_PREVIEW, false, NULL);
}
void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect)
{
- icon_draw_at_size(x, y, icon_id, aspect, 1.0f, ICON_SIZE_PREVIEW, false, NULL);
+ icon_draw_at_size(x, y, icon_id, aspect, 1.0f, ICON_SIZE_PREVIEW, false, NULL);
}
-void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspect, float alpha, int size)
+void UI_icon_draw_preview_aspect_size(
+ float x, float y, int icon_id, float aspect, float alpha, int size)
{
- icon_draw_size(x, y, icon_id, aspect, alpha, NULL, ICON_SIZE_PREVIEW, size, false, NULL);
+ icon_draw_size(x, y, icon_id, aspect, alpha, NULL, ICON_SIZE_PREVIEW, size, false, NULL);
}
diff --git a/source/blender/editors/interface/interface_icons_event.c b/source/blender/editors/interface/interface_icons_event.c
index 2af9bbf9e88..0992ee95fd7 100644
--- a/source/blender/editors/interface/interface_icons_event.c
+++ b/source/blender/editors/interface/interface_icons_event.c
@@ -77,212 +77,218 @@
#include "interface_intern.h"
static void icon_draw_rect_input_small_text_ex(
- const rctf *rect, const float color[4], const float margin[2], const char *str,
- int font_size)
+ const rctf *rect, const float color[4], const float margin[2], const char *str, int font_size)
{
- BLF_batch_draw_flush();
- const int font_id = BLF_default();
- BLF_color4fv(font_id, color);
- BLF_size(font_id, font_size * U.pixelsize, U.dpi);
- BLF_position(font_id, rect->xmin + margin[0] * 2, rect->ymin + margin[1] * 5, 0.0f);
- BLF_draw(font_id, str, BLF_DRAW_STR_DUMMY_MAX);
- BLF_batch_draw_flush();
+ BLF_batch_draw_flush();
+ const int font_id = BLF_default();
+ BLF_color4fv(font_id, color);
+ BLF_size(font_id, font_size * U.pixelsize, U.dpi);
+ BLF_position(font_id, rect->xmin + margin[0] * 2, rect->ymin + margin[1] * 5, 0.0f);
+ BLF_draw(font_id, str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_batch_draw_flush();
}
-static void icon_draw_rect_input_small_text(
- const rctf *rect, const float color[4], const float margin[2], const char *str)
+static void icon_draw_rect_input_small_text(const rctf *rect,
+ const float color[4],
+ const float margin[2],
+ const char *str)
{
- icon_draw_rect_input_small_text_ex(rect, color, margin, str, 8);
+ icon_draw_rect_input_small_text_ex(rect, color, margin, str, 8);
}
-static void icon_draw_rect_input_default_text(
- const rctf *rect,
- const float color[4], const float margin[2], const char *str)
+static void icon_draw_rect_input_default_text(const rctf *rect,
+ const float color[4],
+ const float margin[2],
+ const char *str)
{
- BLF_batch_draw_flush();
- const int font_id = BLF_default();
- BLF_color4fv(font_id, color);
- BLF_position(font_id, (int)(rect->xmin + margin[0] * 5), (int)(rect->ymin + margin[1] * 5), 0.0f);
- BLF_draw(font_id, str, BLF_DRAW_STR_DUMMY_MAX);
- BLF_batch_draw_flush();
+ BLF_batch_draw_flush();
+ const int font_id = BLF_default();
+ BLF_color4fv(font_id, color);
+ BLF_position(
+ font_id, (int)(rect->xmin + margin[0] * 5), (int)(rect->ymin + margin[1] * 5), 0.0f);
+ BLF_draw(font_id, str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_batch_draw_flush();
}
-static void icon_draw_rect_input_mono_text(
- const rctf *rect,
- const float color[4], const float margin[2], const char *str)
+static void icon_draw_rect_input_mono_text(const rctf *rect,
+ const float color[4],
+ const float margin[2],
+ const char *str)
{
- BLF_batch_draw_flush();
- const int font_id = blf_mono_font;
- BLF_color4fv(font_id, color);
- BLF_size(font_id, 20 * U.pixelsize, U.dpi);
- BLF_position(font_id, (int)(rect->xmin + margin[0] * 5), (int)(rect->ymin + margin[1] * 5), 0.0f);
- BLF_draw(font_id, str, BLF_DRAW_STR_DUMMY_MAX);
- BLF_batch_draw_flush();
+ BLF_batch_draw_flush();
+ const int font_id = blf_mono_font;
+ BLF_color4fv(font_id, color);
+ BLF_size(font_id, 20 * U.pixelsize, U.dpi);
+ BLF_position(
+ font_id, (int)(rect->xmin + margin[0] * 5), (int)(rect->ymin + margin[1] * 5), 0.0f);
+ BLF_draw(font_id, str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_batch_draw_flush();
}
static void icon_draw_rect_input_line_prim(
- const rctf *rect,
- const float color[4],
- const int prim,
- const char lines[][2], int lines_len)
+ const rctf *rect, const float color[4], const int prim, const char lines[][2], int lines_len)
{
- GPU_line_smooth(true);
- GPU_blend(true);
- BLI_assert(ELEM(prim, GPU_PRIM_LINE_LOOP, GPU_PRIM_LINE_STRIP));
- const uint pos_id = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4fv(color);
- immBegin(prim, lines_len);
- float w_inv = BLI_rctf_size_x(rect) / 255.0f;
- float h_inv = BLI_rctf_size_y(rect) / 255.0f;
- for (int i = 0; i < lines_len; i++) {
- immVertex2f(
- pos_id,
- round_fl_to_int(rect->xmin + ((float)lines[i][0] * w_inv)),
- round_fl_to_int(rect->ymin + ((float)lines[i][1] * h_inv))
- );
- }
- immEnd();
- immUnbindProgram();
- GPU_line_smooth(false);
- GPU_blend(false);
+ GPU_line_smooth(true);
+ GPU_blend(true);
+ BLI_assert(ELEM(prim, GPU_PRIM_LINE_LOOP, GPU_PRIM_LINE_STRIP));
+ const uint pos_id = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
+ immBegin(prim, lines_len);
+ float w_inv = BLI_rctf_size_x(rect) / 255.0f;
+ float h_inv = BLI_rctf_size_y(rect) / 255.0f;
+ for (int i = 0; i < lines_len; i++) {
+ immVertex2f(pos_id,
+ round_fl_to_int(rect->xmin + ((float)lines[i][0] * w_inv)),
+ round_fl_to_int(rect->ymin + ((float)lines[i][1] * h_inv)));
+ }
+ immEnd();
+ immUnbindProgram();
+ GPU_line_smooth(false);
+ GPU_blend(false);
}
-void icon_draw_rect_input(
- float x, float y, int w, int h, float UNUSED(alpha),
- short event_type, short UNUSED(event_value))
+void icon_draw_rect_input(float x,
+ float y,
+ int w,
+ int h,
+ float UNUSED(alpha),
+ short event_type,
+ short UNUSED(event_value))
{
- float color[4];
- const float margin[2] = {w / 20.0f, h / 20.0f};
- GPU_line_width(1.0f);
- UI_GetThemeColor4fv(TH_TEXT, color);
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_aa(
- false,
- (int)x,
- (int)y,
- (int)(x + w),
- (int)(y + h), 4.0f, color
- );
+ float color[4];
+ const float margin[2] = {w / 20.0f, h / 20.0f};
+ GPU_line_width(1.0f);
+ UI_GetThemeColor4fv(TH_TEXT, color);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_aa(false, (int)x, (int)y, (int)(x + w), (int)(y + h), 4.0f, color);
- const rctf rect = {
- .xmin = x,
- .ymin = y,
- .xmax = x + w,
- .ymax = y + h,
- };
+ const rctf rect = {
+ .xmin = x,
+ .ymin = y,
+ .xmax = x + w,
+ .ymax = y + h,
+ };
- const bool simple_text = false;
+ const bool simple_text = false;
- if ((event_type >= AKEY) || (ZKEY <= event_type)) {
- char str[2] = {'A' + (event_type - AKEY), '\0'};
- icon_draw_rect_input_default_text(&rect, color, margin, str);
- }
- if ((event_type >= F1KEY) || (F12KEY <= event_type)) {
- char str[3] = {'F', '1' + (event_type - F1KEY), '\0'};
- icon_draw_rect_input_default_text(&rect, color, margin, str);
- }
- else if (event_type == LEFTSHIFTKEY) {
- if (simple_text) {
- icon_draw_rect_input_small_text(&rect, color, margin, "Shift");
- }
- else {
- rctf rect_ofs = rect;
- BLI_rctf_translate(&rect_ofs, (w / -14.0f), (w / -14.0f));
- icon_draw_rect_input_mono_text(&rect_ofs, color, margin, (const char[]){0xe2, 0x87, 0xa7, 0x0});
- }
- }
- else if (event_type == LEFTCTRLKEY) {
- if (simple_text) {
- icon_draw_rect_input_small_text(&rect, color, margin, "Ctrl");
- }
- else {
- rctf rect_ofs = rect;
- BLI_rctf_translate(&rect_ofs, (w / -16.0f), 0.0f);
- icon_draw_rect_input_default_text(&rect_ofs, color, margin, "^");
- }
- }
- else if (event_type == LEFTALTKEY) {
- if (simple_text) {
- icon_draw_rect_input_small_text(&rect, color, margin, "Alt");
- }
- else {
- rctf rect_ofs = rect;
- BLI_rctf_translate(&rect_ofs, (w / -8.0f), 0.0f);
- icon_draw_rect_input_default_text(&rect_ofs, color, margin, (const char[]){0xe2, 0x8c, 0xa5, 0x0});
- }
- }
- else if (event_type == OSKEY) {
- icon_draw_rect_input_small_text(&rect, color, margin, "OS");
- }
- else if (event_type == DELKEY) {
- icon_draw_rect_input_small_text(&rect, color, margin, "Del");
- }
- else if (event_type == TABKEY) {
- if (simple_text) {
- icon_draw_rect_input_small_text(&rect, color, margin, "Tab");
- }
- else {
- rctf rect_ofs = rect;
- BLI_rctf_translate(&rect_ofs, (w / -12.0f), (w / -12.0f));
- icon_draw_rect_input_mono_text(&rect_ofs, color, margin, (const char[]){0xe2, 0x86, 0xb9, 0x0});
- }
- }
- else if (event_type == HOMEKEY) {
- if (simple_text) {
- icon_draw_rect_input_small_text(&rect, color, margin, "Home");
- }
- else {
- rctf rect_ofs = rect;
- BLI_rctf_translate(&rect_ofs, (w / -12.0f), (w / -12.0f));
- icon_draw_rect_input_mono_text(&rect_ofs, color, margin, (const char[]){0xe2, 0x87, 0xa4, 0x0});
- }
- }
- else if (event_type == ENDKEY) {
- if (simple_text) {
- icon_draw_rect_input_small_text(&rect, color, margin, "End");
- }
- else {
- rctf rect_ofs = rect;
- BLI_rctf_translate(&rect_ofs, (w / -12.0f), (w / -12.0f));
- icon_draw_rect_input_mono_text(&rect_ofs, color, margin, (const char[]){0xe2, 0x87, 0xa5, 0x0});
- }
- }
- else if (event_type == RETKEY) {
- if (simple_text) {
- icon_draw_rect_input_small_text(&rect, color, margin, "Ret");
- }
- else {
- rctf rect_ofs = rect;
- BLI_rctf_translate(&rect_ofs, (w / -8.0f), (w / -6.0f));
- icon_draw_rect_input_mono_text(&rect_ofs, color, margin, (const char[]){0xe2, 0x8f, 0x8e, 0x0});
- }
- }
- else if (event_type == ESCKEY) {
- icon_draw_rect_input_small_text(&rect, color, margin, "Esc");
- }
- else if (event_type == PAGEUPKEY) {
- icon_draw_rect_input_small_text_ex(&rect, color, margin, (const char[]){'P', 0xe2, 0x86, 0x91, 0x0}, 10);
- }
- else if (event_type == PAGEDOWNKEY) {
- icon_draw_rect_input_small_text_ex(&rect, color, margin, (const char[]){'P', 0xe2, 0x86, 0x93, 0x0}, 10);
- }
- else if (event_type == LEFTARROWKEY) {
- icon_draw_rect_input_default_text(&rect, color, margin, (const char[]){0xe2, 0x86, 0x90, 0x0});
- }
- else if (event_type == UPARROWKEY) {
- icon_draw_rect_input_default_text(&rect, color, margin, (const char[]){0xe2, 0x86, 0x91, 0x0});
- }
- else if (event_type == RIGHTARROWKEY) {
- icon_draw_rect_input_default_text(&rect, color, margin, (const char[]){0xe2, 0x86, 0x92, 0x0});
- }
- else if (event_type == DOWNARROWKEY) {
- icon_draw_rect_input_default_text(&rect, color, margin, (const char[]){0xe2, 0x86, 0x93, 0x0});
- }
- else if (event_type == SPACEKEY) {
- const uchar lines[] = {60, 118, 60, 60, 195, 60, 195, 118};
- icon_draw_rect_input_line_prim(
- &rect, color, GPU_PRIM_LINE_STRIP,
- (const void *)lines, ARRAY_SIZE(lines) / 2);
- }
+ if ((event_type >= AKEY) || (ZKEY <= event_type)) {
+ char str[2] = {'A' + (event_type - AKEY), '\0'};
+ icon_draw_rect_input_default_text(&rect, color, margin, str);
+ }
+ if ((event_type >= F1KEY) || (F12KEY <= event_type)) {
+ char str[3] = {'F', '1' + (event_type - F1KEY), '\0'};
+ icon_draw_rect_input_default_text(&rect, color, margin, str);
+ }
+ else if (event_type == LEFTSHIFTKEY) {
+ if (simple_text) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "Shift");
+ }
+ else {
+ rctf rect_ofs = rect;
+ BLI_rctf_translate(&rect_ofs, (w / -14.0f), (w / -14.0f));
+ icon_draw_rect_input_mono_text(
+ &rect_ofs, color, margin, (const char[]){0xe2, 0x87, 0xa7, 0x0});
+ }
+ }
+ else if (event_type == LEFTCTRLKEY) {
+ if (simple_text) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "Ctrl");
+ }
+ else {
+ rctf rect_ofs = rect;
+ BLI_rctf_translate(&rect_ofs, (w / -16.0f), 0.0f);
+ icon_draw_rect_input_default_text(&rect_ofs, color, margin, "^");
+ }
+ }
+ else if (event_type == LEFTALTKEY) {
+ if (simple_text) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "Alt");
+ }
+ else {
+ rctf rect_ofs = rect;
+ BLI_rctf_translate(&rect_ofs, (w / -8.0f), 0.0f);
+ icon_draw_rect_input_default_text(
+ &rect_ofs, color, margin, (const char[]){0xe2, 0x8c, 0xa5, 0x0});
+ }
+ }
+ else if (event_type == OSKEY) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "OS");
+ }
+ else if (event_type == DELKEY) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "Del");
+ }
+ else if (event_type == TABKEY) {
+ if (simple_text) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "Tab");
+ }
+ else {
+ rctf rect_ofs = rect;
+ BLI_rctf_translate(&rect_ofs, (w / -12.0f), (w / -12.0f));
+ icon_draw_rect_input_mono_text(
+ &rect_ofs, color, margin, (const char[]){0xe2, 0x86, 0xb9, 0x0});
+ }
+ }
+ else if (event_type == HOMEKEY) {
+ if (simple_text) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "Home");
+ }
+ else {
+ rctf rect_ofs = rect;
+ BLI_rctf_translate(&rect_ofs, (w / -12.0f), (w / -12.0f));
+ icon_draw_rect_input_mono_text(
+ &rect_ofs, color, margin, (const char[]){0xe2, 0x87, 0xa4, 0x0});
+ }
+ }
+ else if (event_type == ENDKEY) {
+ if (simple_text) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "End");
+ }
+ else {
+ rctf rect_ofs = rect;
+ BLI_rctf_translate(&rect_ofs, (w / -12.0f), (w / -12.0f));
+ icon_draw_rect_input_mono_text(
+ &rect_ofs, color, margin, (const char[]){0xe2, 0x87, 0xa5, 0x0});
+ }
+ }
+ else if (event_type == RETKEY) {
+ if (simple_text) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "Ret");
+ }
+ else {
+ rctf rect_ofs = rect;
+ BLI_rctf_translate(&rect_ofs, (w / -8.0f), (w / -6.0f));
+ icon_draw_rect_input_mono_text(
+ &rect_ofs, color, margin, (const char[]){0xe2, 0x8f, 0x8e, 0x0});
+ }
+ }
+ else if (event_type == ESCKEY) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "Esc");
+ }
+ else if (event_type == PAGEUPKEY) {
+ icon_draw_rect_input_small_text_ex(
+ &rect, color, margin, (const char[]){'P', 0xe2, 0x86, 0x91, 0x0}, 10);
+ }
+ else if (event_type == PAGEDOWNKEY) {
+ icon_draw_rect_input_small_text_ex(
+ &rect, color, margin, (const char[]){'P', 0xe2, 0x86, 0x93, 0x0}, 10);
+ }
+ else if (event_type == LEFTARROWKEY) {
+ icon_draw_rect_input_default_text(&rect, color, margin, (const char[]){0xe2, 0x86, 0x90, 0x0});
+ }
+ else if (event_type == UPARROWKEY) {
+ icon_draw_rect_input_default_text(&rect, color, margin, (const char[]){0xe2, 0x86, 0x91, 0x0});
+ }
+ else if (event_type == RIGHTARROWKEY) {
+ icon_draw_rect_input_default_text(&rect, color, margin, (const char[]){0xe2, 0x86, 0x92, 0x0});
+ }
+ else if (event_type == DOWNARROWKEY) {
+ icon_draw_rect_input_default_text(&rect, color, margin, (const char[]){0xe2, 0x86, 0x93, 0x0});
+ }
+ else if (event_type == SPACEKEY) {
+ const uchar lines[] = {60, 118, 60, 60, 195, 60, 195, 118};
+ icon_draw_rect_input_line_prim(
+ &rect, color, GPU_PRIM_LINE_STRIP, (const void *)lines, ARRAY_SIZE(lines) / 2);
+ }
}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 3580b2ff3a5..86ca2241881 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -21,7 +21,6 @@
* \ingroup edinterface
*/
-
#ifndef __INTERFACE_INTERN_H__
#define __INTERFACE_INTERN_H__
@@ -47,81 +46,82 @@ struct wmTimer;
/* ****************** general defines ************** */
-#define RNA_NO_INDEX -1
-#define RNA_ENUM_VALUE -2
+#define RNA_NO_INDEX -1
+#define RNA_ENUM_VALUE -2
#define UI_MENU_PADDING (int)(0.2f * UI_UNIT_Y)
-#define UI_MENU_WIDTH_MIN (UI_UNIT_Y * 9)
+#define UI_MENU_WIDTH_MIN (UI_UNIT_Y * 9)
/* some extra padding added to menus containing submenu icons */
#define UI_MENU_SUBMENU_PADDING (6 * UI_DPI_FAC)
/* menu scrolling */
-#define UI_MENU_SCROLL_ARROW 12
-#define UI_MENU_SCROLL_MOUSE (UI_MENU_SCROLL_ARROW + 2)
-#define UI_MENU_SCROLL_PAD 4
+#define UI_MENU_SCROLL_ARROW 12
+#define UI_MENU_SCROLL_MOUSE (UI_MENU_SCROLL_ARROW + 2)
+#define UI_MENU_SCROLL_PAD 4
/* panel limits */
-#define UI_PANEL_MINX 100
-#define UI_PANEL_MINY 70
+#define UI_PANEL_MINX 100
+#define UI_PANEL_MINY 70
/* popover width (multiplied by 'U.widget_unit') */
#define UI_POPOVER_WIDTH_UNITS 10
/* uiBut->flag */
enum {
- UI_SELECT = (1 << 0), /* use when the button is pressed */
- UI_SCROLLED = (1 << 1), /* temp hidden, scrolled away */
- UI_ACTIVE = (1 << 2),
- UI_HAS_ICON = (1 << 3),
- UI_HIDDEN = (1 << 4),
- UI_SELECT_DRAW = (1 << 5), /* Display selected, doesn't impact interaction. */
- /* warn: rest of uiBut->flag in UI_interface.h */
+ UI_SELECT = (1 << 0), /* use when the button is pressed */
+ UI_SCROLLED = (1 << 1), /* temp hidden, scrolled away */
+ UI_ACTIVE = (1 << 2),
+ UI_HAS_ICON = (1 << 3),
+ UI_HIDDEN = (1 << 4),
+ UI_SELECT_DRAW = (1 << 5), /* Display selected, doesn't impact interaction. */
+ /* warn: rest of uiBut->flag in UI_interface.h */
};
/* some buttons display icons only under special conditions
* (e.g. 'x' icon in search menu) - used with ui_but_icon_extra_get */
typedef enum uiButExtraIconType {
- UI_BUT_ICONEXTRA_NONE = 1,
- UI_BUT_ICONEXTRA_CLEAR,
- UI_BUT_ICONEXTRA_EYEDROPPER,
+ UI_BUT_ICONEXTRA_NONE = 1,
+ UI_BUT_ICONEXTRA_CLEAR,
+ UI_BUT_ICONEXTRA_EYEDROPPER,
} uiButExtraIconType;
/* uiBut->dragflag */
enum {
- UI_BUT_DRAGPOIN_FREE = (1 << 0),
+ UI_BUT_DRAGPOIN_FREE = (1 << 0),
};
/* but->pie_dir */
typedef enum RadialDirection {
- UI_RADIAL_NONE = -1,
- UI_RADIAL_N = 0,
- UI_RADIAL_NE = 1,
- UI_RADIAL_E = 2,
- UI_RADIAL_SE = 3,
- UI_RADIAL_S = 4,
- UI_RADIAL_SW = 5,
- UI_RADIAL_W = 6,
- UI_RADIAL_NW = 7,
+ UI_RADIAL_NONE = -1,
+ UI_RADIAL_N = 0,
+ UI_RADIAL_NE = 1,
+ UI_RADIAL_E = 2,
+ UI_RADIAL_SE = 3,
+ UI_RADIAL_S = 4,
+ UI_RADIAL_SW = 5,
+ UI_RADIAL_W = 6,
+ UI_RADIAL_NW = 7,
} RadialDirection;
-extern const char ui_radial_dir_order[8];
-extern const char ui_radial_dir_to_numpad[8];
+extern const char ui_radial_dir_order[8];
+extern const char ui_radial_dir_to_numpad[8];
extern const short ui_radial_dir_to_angle[8];
/* internal panel drawing defines */
-#define PNL_GRID (UI_UNIT_Y / 5) /* 4 default */
-#define PNL_HEADER (UI_UNIT_Y * 1.2) /* 24 default */
+#define PNL_GRID (UI_UNIT_Y / 5) /* 4 default */
+#define PNL_HEADER (UI_UNIT_Y * 1.2) /* 24 default */
/* bit button defines */
/* Bit operations */
-#define UI_BITBUT_TEST(a, b) (((a) & (1 << (b))) != 0)
-#define UI_BITBUT_VALUE_TOGGLED(a, b) ((a) ^ (1 << (b)))
-#define UI_BITBUT_VALUE_ENABLED(a, b) ((a) | (1 << (b)))
-#define UI_BITBUT_VALUE_DISABLED(a, b) ((a) & ~(1 << (b)))
+#define UI_BITBUT_TEST(a, b) (((a) & (1 << (b))) != 0)
+#define UI_BITBUT_VALUE_TOGGLED(a, b) ((a) ^ (1 << (b)))
+#define UI_BITBUT_VALUE_ENABLED(a, b) ((a) | (1 << (b)))
+#define UI_BITBUT_VALUE_DISABLED(a, b) ((a) & ~(1 << (b)))
/* bit-row */
-#define UI_BITBUT_ROW(min, max) (((max) >= 31 ? 0xFFFFFFFF : (1 << ((max) + 1)) - 1) - ((min) ? ((1 << (min)) - 1) : 0) )
+#define UI_BITBUT_ROW(min, max) \
+ (((max) >= 31 ? 0xFFFFFFFF : (1 << ((max) + 1)) - 1) - ((min) ? ((1 << (min)) - 1) : 0))
/* split numbuts by ':' and align l/r */
#define USE_NUMBUTS_LR_ALIGN
@@ -131,20 +131,20 @@ extern const short ui_radial_dir_to_angle[8];
/* PieMenuData->flags */
enum {
- /** pie menu item collision is detected at 90 degrees */
- UI_PIE_DEGREES_RANGE_LARGE = (1 << 0),
- /** use initial center of pie menu to calculate direction */
- UI_PIE_INITIAL_DIRECTION = (1 << 1),
- /** pie menu is drag style */
- UI_PIE_DRAG_STYLE = (1 << 2),
- /** mouse not far enough from center position */
- UI_PIE_INVALID_DIR = (1 << 3),
- /** pie menu changed to click style, click to confirm */
- UI_PIE_CLICK_STYLE = (1 << 4),
- /** pie animation finished, do not calculate any more motion */
- UI_PIE_ANIMATION_FINISHED = (1 << 5),
- /** pie gesture selection has been done, now wait for mouse motion to end */
- UI_PIE_GESTURE_END_WAIT = (1 << 6),
+ /** pie menu item collision is detected at 90 degrees */
+ UI_PIE_DEGREES_RANGE_LARGE = (1 << 0),
+ /** use initial center of pie menu to calculate direction */
+ UI_PIE_INITIAL_DIRECTION = (1 << 1),
+ /** pie menu is drag style */
+ UI_PIE_DRAG_STYLE = (1 << 2),
+ /** mouse not far enough from center position */
+ UI_PIE_INVALID_DIR = (1 << 3),
+ /** pie menu changed to click style, click to confirm */
+ UI_PIE_CLICK_STYLE = (1 << 4),
+ /** pie animation finished, do not calculate any more motion */
+ UI_PIE_ANIMATION_FINISHED = (1 << 5),
+ /** pie gesture selection has been done, now wait for mouse motion to end */
+ UI_PIE_GESTURE_END_WAIT = (1 << 6),
};
#define PIE_CLICK_THRESHOLD_SQ 50.0f
@@ -153,294 +153,294 @@ enum {
#define PIE_MAX_ITEMS 8
struct uiBut {
- struct uiBut *next, *prev;
- int flag, drawflag;
- eButType type;
- eButPointerType pointype;
- short bit, bitnr, retval, strwidth, alignnr;
- short ofs, pos, selsta, selend;
-
- char *str;
- char strdata[UI_MAX_NAME_STR];
- char drawstr[UI_MAX_DRAW_STR];
-
- rctf rect; /* block relative coords */
-
- char *poin;
- float hardmin, hardmax, softmin, softmax;
-
- /* both these values use depends on the button type
- * (polymorphic struct or union would be nicer for this stuff) */
-
- /* (type == UI_BTYPE_HSVCUBE), Use UI_GRAD_* values.
- * (type == UI_BTYPE_NUM), Use to store RNA 'step' value, for dragging and click-step.
- * (type == UI_BTYPE_LABEL), Use (a1 == 1.0f) to use a2 as a blending factor (wow, this is imaginative!).
- * (type == UI_BTYPE_SCROLL) Use as scroll size.
- * (type == UI_BTYPE_SEARCH_MENU) Use as number or rows.
- * (type == UI_BTYPE_COLOR) Use as indication of color palette
- * (type == UI_BTYPE_PROGRESS_BAR) Use to store progress (0..1).
- */
- float a1;
-
- /* (type == UI_BTYPE_HSVCIRCLE ), Use to store the luminosity.
- * (type == UI_BTYPE_NUM), Use to store RNA 'precision' value, for dragging and click-step.
- * (type == UI_BTYPE_LABEL), If (a1 == 1.0f) use a2 as a blending factor.
- * (type == UI_BTYPE_SEARCH_MENU) Use as number or columns.
- * (type == UI_BTYPE_COLOR) Use as index in palette (not so good, needs refactor)
- */
- float a2;
-
- uchar col[4];
-
- uiButHandleFunc func;
- void *func_arg1;
- void *func_arg2;
-
- uiButHandleNFunc funcN;
- void *func_argN;
-
- struct bContextStore *context;
-
- uiButCompleteFunc autocomplete_func;
- void *autofunc_arg;
-
- uiButSearchCreateFunc search_create_func;
- uiButSearchFunc search_func;
- bool free_search_arg;
- void *search_arg;
-
- uiButHandleRenameFunc rename_func;
- void *rename_arg1;
- void *rename_orig;
-
- /** Run an action when holding the button down. */
- uiButHandleHoldFunc hold_func;
- void *hold_argN;
-
- const char *tip;
- uiButToolTipFunc tip_func;
- void *tip_argN;
-
- /** info on why button is disabled, displayed in tooltip */
- const char *disabled_info;
-
- BIFIconID icon;
- /** drawtype: UI_EMBOSS, UI_EMBOSS_NONE ... etc, copied from the block */
- char dt;
- /** direction in a pie menu, used for collision detection (RadialDirection) */
- signed char pie_dir;
- /** could be made into a single flag */
- bool changed;
- /** so buttons can support unit systems which are not RNA */
- uchar unit_type;
- short modifier_key;
- short iconadd;
-
- /* UI_BTYPE_BLOCK data */
- uiBlockCreateFunc block_create_func;
-
- /* UI_BTYPE_PULLDOWN/UI_BTYPE_MENU data */
- uiMenuCreateFunc menu_create_func;
-
- uiMenuStepFunc menu_step_func;
-
- /* RNA data */
- struct PointerRNA rnapoin;
- struct PropertyRNA *rnaprop;
- int rnaindex;
-
- struct PointerRNA rnasearchpoin;
- struct PropertyRNA *rnasearchprop;
-
- /* Operator data */
- struct wmOperatorType *optype;
- struct PointerRNA *opptr;
- short opcontext;
- uchar menu_key; /* 'a'-'z', always lower case */
-
- /* Draggable data, type is WM_DRAG_... */
- char dragtype;
- short dragflag;
- void *dragpoin;
- struct ImBuf *imb;
- float imb_scale;
-
- /* active button data */
- struct uiHandleButtonData *active;
-
- /* Custom button data. */
- void *custom_data;
-
- char *editstr;
- double *editval;
- float *editvec;
- void *editcoba;
- void *editcumap;
-
- uiButPushedStateFunc pushed_state_func;
- void *pushed_state_arg;
-
- /* pointer back */
- uiBlock *block;
+ struct uiBut *next, *prev;
+ int flag, drawflag;
+ eButType type;
+ eButPointerType pointype;
+ short bit, bitnr, retval, strwidth, alignnr;
+ short ofs, pos, selsta, selend;
+
+ char *str;
+ char strdata[UI_MAX_NAME_STR];
+ char drawstr[UI_MAX_DRAW_STR];
+
+ rctf rect; /* block relative coords */
+
+ char *poin;
+ float hardmin, hardmax, softmin, softmax;
+
+ /* both these values use depends on the button type
+ * (polymorphic struct or union would be nicer for this stuff) */
+
+ /* (type == UI_BTYPE_HSVCUBE), Use UI_GRAD_* values.
+ * (type == UI_BTYPE_NUM), Use to store RNA 'step' value, for dragging and click-step.
+ * (type == UI_BTYPE_LABEL), Use (a1 == 1.0f) to use a2 as a blending factor (wow, this is imaginative!).
+ * (type == UI_BTYPE_SCROLL) Use as scroll size.
+ * (type == UI_BTYPE_SEARCH_MENU) Use as number or rows.
+ * (type == UI_BTYPE_COLOR) Use as indication of color palette
+ * (type == UI_BTYPE_PROGRESS_BAR) Use to store progress (0..1).
+ */
+ float a1;
+
+ /* (type == UI_BTYPE_HSVCIRCLE ), Use to store the luminosity.
+ * (type == UI_BTYPE_NUM), Use to store RNA 'precision' value, for dragging and click-step.
+ * (type == UI_BTYPE_LABEL), If (a1 == 1.0f) use a2 as a blending factor.
+ * (type == UI_BTYPE_SEARCH_MENU) Use as number or columns.
+ * (type == UI_BTYPE_COLOR) Use as index in palette (not so good, needs refactor)
+ */
+ float a2;
+
+ uchar col[4];
+
+ uiButHandleFunc func;
+ void *func_arg1;
+ void *func_arg2;
+
+ uiButHandleNFunc funcN;
+ void *func_argN;
+
+ struct bContextStore *context;
+
+ uiButCompleteFunc autocomplete_func;
+ void *autofunc_arg;
+
+ uiButSearchCreateFunc search_create_func;
+ uiButSearchFunc search_func;
+ bool free_search_arg;
+ void *search_arg;
+
+ uiButHandleRenameFunc rename_func;
+ void *rename_arg1;
+ void *rename_orig;
+
+ /** Run an action when holding the button down. */
+ uiButHandleHoldFunc hold_func;
+ void *hold_argN;
+
+ const char *tip;
+ uiButToolTipFunc tip_func;
+ void *tip_argN;
+
+ /** info on why button is disabled, displayed in tooltip */
+ const char *disabled_info;
+
+ BIFIconID icon;
+ /** drawtype: UI_EMBOSS, UI_EMBOSS_NONE ... etc, copied from the block */
+ char dt;
+ /** direction in a pie menu, used for collision detection (RadialDirection) */
+ signed char pie_dir;
+ /** could be made into a single flag */
+ bool changed;
+ /** so buttons can support unit systems which are not RNA */
+ uchar unit_type;
+ short modifier_key;
+ short iconadd;
+
+ /* UI_BTYPE_BLOCK data */
+ uiBlockCreateFunc block_create_func;
+
+ /* UI_BTYPE_PULLDOWN/UI_BTYPE_MENU data */
+ uiMenuCreateFunc menu_create_func;
+
+ uiMenuStepFunc menu_step_func;
+
+ /* RNA data */
+ struct PointerRNA rnapoin;
+ struct PropertyRNA *rnaprop;
+ int rnaindex;
+
+ struct PointerRNA rnasearchpoin;
+ struct PropertyRNA *rnasearchprop;
+
+ /* Operator data */
+ struct wmOperatorType *optype;
+ struct PointerRNA *opptr;
+ short opcontext;
+ uchar menu_key; /* 'a'-'z', always lower case */
+
+ /* Draggable data, type is WM_DRAG_... */
+ char dragtype;
+ short dragflag;
+ void *dragpoin;
+ struct ImBuf *imb;
+ float imb_scale;
+
+ /* active button data */
+ struct uiHandleButtonData *active;
+
+ /* Custom button data. */
+ void *custom_data;
+
+ char *editstr;
+ double *editval;
+ float *editvec;
+ void *editcoba;
+ void *editcumap;
+
+ uiButPushedStateFunc pushed_state_func;
+ void *pushed_state_arg;
+
+ /* pointer back */
+ uiBlock *block;
};
typedef struct uiButTab {
- uiBut but;
- struct MenuType *menu;
+ uiBut but;
+ struct MenuType *menu;
} uiButTab;
typedef struct ColorPicker {
- struct ColorPicker *next, *prev;
- /** Color data, may be HSV or HSL. */
- float color_data[3];
- /** Initial color data (detect changes). */
- float color_data_init[3];
- bool is_init;
- /** Cubic saturation for the color wheel. */
- bool use_color_cubic;
- bool use_color_lock;
- bool use_luminosity_lock;
- float luminosity_lock_value;
+ struct ColorPicker *next, *prev;
+ /** Color data, may be HSV or HSL. */
+ float color_data[3];
+ /** Initial color data (detect changes). */
+ float color_data_init[3];
+ bool is_init;
+ /** Cubic saturation for the color wheel. */
+ bool use_color_cubic;
+ bool use_color_lock;
+ bool use_luminosity_lock;
+ float luminosity_lock_value;
} ColorPicker;
typedef struct ColorPickerData {
- ListBase list;
+ ListBase list;
} ColorPickerData;
struct PieMenuData {
- /** store title and icon to allow access when pie levels are created */
- const char *title;
- int icon;
-
- float pie_dir[2];
- float pie_center_init[2];
- float pie_center_spawned[2];
- float last_pos[2];
- double duration_gesture;
- int flags;
- /** initial event used to fire the pie menu, store here so we can query for release */
- int event;
- float alphafac;
+ /** store title and icon to allow access when pie levels are created */
+ const char *title;
+ int icon;
+
+ float pie_dir[2];
+ float pie_center_init[2];
+ float pie_center_spawned[2];
+ float last_pos[2];
+ double duration_gesture;
+ int flags;
+ /** initial event used to fire the pie menu, store here so we can query for release */
+ int event;
+ float alphafac;
};
/* uiBlock.content_hints */
enum eBlockContentHints {
- /** In a menu block, if there is a single sub-menu button, we add some
- * padding to the right to put nicely aligned triangle icons there. */
- UI_BLOCK_CONTAINS_SUBMENU_BUT = (1 << 0),
+ /** In a menu block, if there is a single sub-menu button, we add some
+ * padding to the right to put nicely aligned triangle icons there. */
+ UI_BLOCK_CONTAINS_SUBMENU_BUT = (1 << 0),
};
struct uiBlock {
- uiBlock *next, *prev;
+ uiBlock *next, *prev;
- ListBase buttons;
- Panel *panel;
- uiBlock *oldblock;
+ ListBase buttons;
+ Panel *panel;
+ uiBlock *oldblock;
- ListBase butstore; /* UI_butstore_* runtime function */
+ ListBase butstore; /* UI_butstore_* runtime function */
- ListBase layouts;
- struct uiLayout *curlayout;
+ ListBase layouts;
+ struct uiLayout *curlayout;
- ListBase contexts;
+ ListBase contexts;
- char name[UI_MAX_NAME_STR];
+ char name[UI_MAX_NAME_STR];
- float winmat[4][4];
+ float winmat[4][4];
- rctf rect;
- float aspect;
+ rctf rect;
+ float aspect;
- uint puphash; /* popup menu hash for memory */
+ uint puphash; /* popup menu hash for memory */
- uiButHandleFunc func;
- void *func_arg1;
- void *func_arg2;
+ uiButHandleFunc func;
+ void *func_arg1;
+ void *func_arg2;
- uiButHandleNFunc funcN;
- void *func_argN;
+ uiButHandleNFunc funcN;
+ void *func_argN;
- uiMenuHandleFunc butm_func;
- void *butm_func_arg;
+ uiMenuHandleFunc butm_func;
+ void *butm_func_arg;
- uiBlockHandleFunc handle_func;
- void *handle_func_arg;
+ uiBlockHandleFunc handle_func;
+ void *handle_func_arg;
- /* custom extra handling */
- int (*block_event_func)(const struct bContext *C, struct uiBlock *, const struct wmEvent *);
+ /* custom extra handling */
+ int (*block_event_func)(const struct bContext *C, struct uiBlock *, const struct wmEvent *);
- /* extra draw function for custom blocks */
- void (*drawextra)(const struct bContext *C, void *idv, void *arg1, void *arg2, rcti *rect);
- void *drawextra_arg1;
- void *drawextra_arg2;
+ /* extra draw function for custom blocks */
+ void (*drawextra)(const struct bContext *C, void *idv, void *arg1, void *arg2, rcti *rect);
+ void *drawextra_arg1;
+ void *drawextra_arg2;
- int flag;
- short alignnr;
- /** Hints about the buttons of this block. Used to avoid iterating over
- * buttons to find out if some criteria is met by any. Instead, check this
- * criteria when adding the button and set a flag here if it's met. */
- short content_hints; /* eBlockContentHints */
+ int flag;
+ short alignnr;
+ /** Hints about the buttons of this block. Used to avoid iterating over
+ * buttons to find out if some criteria is met by any. Instead, check this
+ * criteria when adding the button and set a flag here if it's met. */
+ short content_hints; /* eBlockContentHints */
- char direction;
- /** UI_BLOCK_THEME_STYLE_* */
- char theme_style;
- /** drawtype: UI_EMBOSS, UI_EMBOSS_NONE ... etc, copied to buttons */
- char dt;
- bool auto_open;
- char _pad[5];
- double auto_open_last;
+ char direction;
+ /** UI_BLOCK_THEME_STYLE_* */
+ char theme_style;
+ /** drawtype: UI_EMBOSS, UI_EMBOSS_NONE ... etc, copied to buttons */
+ char dt;
+ bool auto_open;
+ char _pad[5];
+ double auto_open_last;
- const char *lockstr;
+ const char *lockstr;
- char lock;
- /** to keep blocks while drawing and free them afterwards */
- char active;
- /** to avoid tooltip after click */
- char tooltipdisabled;
- /** UI_block_end done? */
- char endblock;
+ char lock;
+ /** to keep blocks while drawing and free them afterwards */
+ char active;
+ /** to avoid tooltip after click */
+ char tooltipdisabled;
+ /** UI_block_end done? */
+ char endblock;
- /** for doing delayed */
- eBlockBoundsCalc bounds_type;
- /** Offset to use when calculating bounds (in pixels). */
- int bounds_offset[2];
- /** for doing delayed */
- int bounds, minbounds;
+ /** for doing delayed */
+ eBlockBoundsCalc bounds_type;
+ /** Offset to use when calculating bounds (in pixels). */
+ int bounds_offset[2];
+ /** for doing delayed */
+ int bounds, minbounds;
- /** pulldowns, to detect outside, can differ per case how it is created */
- rctf safety;
- /** uiSafetyRct list */
- ListBase saferct;
+ /** pulldowns, to detect outside, can differ per case how it is created */
+ rctf safety;
+ /** uiSafetyRct list */
+ ListBase saferct;
- uiPopupBlockHandle *handle; /* handle */
+ uiPopupBlockHandle *handle; /* handle */
- /** use so presets can find the operator,
- * across menus and from nested popups which fail for operator context. */
- struct wmOperator *ui_operator;
+ /** use so presets can find the operator,
+ * across menus and from nested popups which fail for operator context. */
+ struct wmOperator *ui_operator;
- /** XXX hack for dynamic operator enums */
- void *evil_C;
+ /** XXX hack for dynamic operator enums */
+ void *evil_C;
- /** unit system, used a lot for numeric buttons so include here
- * rather then fetching through the scene every time. */
- struct UnitSettings *unit;
- /** \note only accessed by color picker templates. */
- ColorPickerData color_pickers;
+ /** unit system, used a lot for numeric buttons so include here
+ * rather then fetching through the scene every time. */
+ struct UnitSettings *unit;
+ /** \note only accessed by color picker templates. */
+ ColorPickerData color_pickers;
- bool is_color_gamma_picker; /* Block for color picker with gamma baked in. */
+ bool is_color_gamma_picker; /* Block for color picker with gamma baked in. */
- /** display device name used to display this block,
- * used by color widgets to transform colors from/to scene linear
- */
- char display_device[64];
+ /** display device name used to display this block,
+ * used by color widgets to transform colors from/to scene linear
+ */
+ char display_device[64];
- struct PieMenuData pie_data;
+ struct PieMenuData pie_data;
};
typedef struct uiSafetyRct {
- struct uiSafetyRct *next, *prev;
- rctf parent;
- rctf safety;
+ struct uiSafetyRct *next, *prev;
+ rctf parent;
+ rctf safety;
} uiSafetyRct;
/* interface.c */
@@ -449,7 +449,10 @@ 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, uiBlock *block, rctf *rct_dst, const rctf *rct_src);
+extern void ui_block_to_window_rctf(const struct ARegion *ar,
+ 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);
@@ -464,20 +467,27 @@ extern void ui_but_v3_get(uiBut *but, float vec[3]);
extern void ui_but_v3_set(uiBut *but, const float vec[3]);
extern void ui_hsvcircle_vals_from_pos(
- const rcti *rect, const float mx, const float my,
- float *r_val_rad, float *r_val_dist);
-extern void ui_hsvcircle_pos_from_vals(const ColorPicker *cpicker, const rcti *rect, const float *hsv, float *xpos, float *ypos);
-extern void ui_hsvcube_pos_from_vals(const struct uiBut *but, const rcti *rect, const float *hsv, float *xp, float *yp);
-
-extern void ui_but_string_get_ex(
- uiBut *but, char *str, const size_t maxlen,
- const int float_precision, const bool use_exp_float, bool *r_use_exp_float) ATTR_NONNULL(1, 2);
+ const rcti *rect, const float mx, const float my, float *r_val_rad, float *r_val_dist);
+extern void ui_hsvcircle_pos_from_vals(
+ const ColorPicker *cpicker, const rcti *rect, const float *hsv, float *xpos, float *ypos);
+extern void ui_hsvcube_pos_from_vals(
+ const struct uiBut *but, const rcti *rect, const float *hsv, float *xp, float *yp);
+
+extern void ui_but_string_get_ex(uiBut *but,
+ char *str,
+ const size_t maxlen,
+ const int float_precision,
+ const bool use_exp_float,
+ bool *r_use_exp_float) ATTR_NONNULL(1, 2);
extern void ui_but_string_get(uiBut *but, char *str, const size_t maxlen) ATTR_NONNULL();
extern char *ui_but_string_get_dynamic(uiBut *but, int *r_str_size);
extern void ui_but_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen) ATTR_NONNULL();
extern bool ui_but_string_set(struct bContext *C, uiBut *but, const char *str) ATTR_NONNULL();
-extern bool ui_but_string_set_eval_num(struct bContext *C, uiBut *but, const char *str, double *value) ATTR_NONNULL();
-extern int ui_but_string_get_max_length(uiBut *but);
+extern bool ui_but_string_set_eval_num(struct bContext *C,
+ uiBut *but,
+ const char *str,
+ double *value) ATTR_NONNULL();
+extern int ui_but_string_get_max_length(uiBut *but);
extern uiBut *ui_but_drag_multi_edit_get(uiBut *but);
void ui_def_but_icon(uiBut *but, const int icon, const int flag);
@@ -498,8 +508,8 @@ extern bool ui_but_is_compatible(const uiBut *but_a, const uiBut *but_b) ATTR_WA
extern bool ui_but_is_rna_valid(uiBut *but) ATTR_WARN_UNUSED_RESULT;
extern bool ui_but_supports_cycling(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
-extern int ui_but_is_pushed_ex(uiBut *but, double *value) ATTR_WARN_UNUSED_RESULT;
-extern int ui_but_is_pushed(uiBut *but) ATTR_WARN_UNUSED_RESULT;
+extern int ui_but_is_pushed_ex(uiBut *but, double *value) ATTR_WARN_UNUSED_RESULT;
+extern int ui_but_is_pushed(uiBut *but) ATTR_WARN_UNUSED_RESULT;
void ui_but_override_flag(uiBut *but);
@@ -511,82 +521,84 @@ void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3]);
/* interface_regions.c */
struct uiKeyNavLock {
- /* set when we're using keyinput */
- bool is_keynav;
- /* only used to check if we've moved the cursor */
- int event_xy[2];
+ /* set when we're using keyinput */
+ bool is_keynav;
+ /* only used to check if we've moved the cursor */
+ int event_xy[2];
};
-typedef uiBlock * (*uiBlockHandleCreateFunc)(struct bContext *C, struct uiPopupBlockHandle *handle, void *arg1);
+typedef uiBlock *(*uiBlockHandleCreateFunc)(struct bContext *C,
+ struct uiPopupBlockHandle *handle,
+ void *arg1);
typedef void (*uiBlockHandleFreeFunc)(struct uiPopupBlockHandle *handle, void *arg1);
struct uiPopupBlockCreate {
- uiBlockCreateFunc create_func;
- uiBlockHandleCreateFunc handle_create_func;
- uiBlockHandleFreeFunc free_func;
- void *arg;
+ uiBlockCreateFunc create_func;
+ uiBlockHandleCreateFunc handle_create_func;
+ uiBlockHandleFreeFunc free_func;
+ void *arg;
- int event_xy[2];
+ int event_xy[2];
- /* when popup is initialized from a button */
- ARegion *butregion;
- uiBut *but;
+ /* when popup is initialized from a button */
+ ARegion *butregion;
+ uiBut *but;
};
struct uiPopupBlockHandle {
- /* internal */
- struct ARegion *region;
-
- /* use only for 'UI_BLOCK_MOVEMOUSE_QUIT' popups */
- float towards_xy[2];
- double towardstime;
- bool dotowards;
-
- bool popup;
- void (*popup_func)(struct bContext *C, void *arg, int event);
- void (*cancel_func)(struct bContext *C, void *arg);
- void *popup_arg;
-
- /* store data for refreshing popups */
- struct uiPopupBlockCreate popup_create_vars;
- /* true if we can re-create the popup using 'popup_create_vars' */
- bool can_refresh;
- bool refresh;
-
- struct wmTimer *scrolltimer;
- float scrolloffset;
-
- struct uiKeyNavLock keynav_state;
-
- /* for operator popups */
- struct wmOperator *popup_op;
- struct wmOperatorType *optype;
- ScrArea *ctx_area;
- ARegion *ctx_region;
- int opcontext;
-
- /* return values */
- int butretval;
- int menuretval;
- int retvalue;
- float retvec[4];
-
- /* menu direction */
- int direction;
-
- /* Previous values so we don't resize or reposition on refresh. */
- rctf prev_block_rect;
- rctf prev_butrct;
- short prev_dir1, prev_dir2;
- int prev_bounds_offset[2];
-
- /* Maximum estimated size to avoid having to reposition on refresh. */
- float max_size_x, max_size_y;
-
-/* #ifdef USE_DRAG_POPUP */
- bool is_grab;
- int grab_xy_prev[2];
-/* #endif */
+ /* internal */
+ struct ARegion *region;
+
+ /* use only for 'UI_BLOCK_MOVEMOUSE_QUIT' popups */
+ float towards_xy[2];
+ double towardstime;
+ bool dotowards;
+
+ bool popup;
+ void (*popup_func)(struct bContext *C, void *arg, int event);
+ void (*cancel_func)(struct bContext *C, void *arg);
+ void *popup_arg;
+
+ /* store data for refreshing popups */
+ struct uiPopupBlockCreate popup_create_vars;
+ /* true if we can re-create the popup using 'popup_create_vars' */
+ bool can_refresh;
+ bool refresh;
+
+ struct wmTimer *scrolltimer;
+ float scrolloffset;
+
+ struct uiKeyNavLock keynav_state;
+
+ /* for operator popups */
+ struct wmOperator *popup_op;
+ struct wmOperatorType *optype;
+ ScrArea *ctx_area;
+ ARegion *ctx_region;
+ int opcontext;
+
+ /* return values */
+ int butretval;
+ int menuretval;
+ int retvalue;
+ float retvec[4];
+
+ /* menu direction */
+ int direction;
+
+ /* Previous values so we don't resize or reposition on refresh. */
+ rctf prev_block_rect;
+ rctf prev_butrct;
+ short prev_dir1, prev_dir2;
+ int prev_bounds_offset[2];
+
+ /* Maximum estimated size to avoid having to reposition on refresh. */
+ float max_size_x, max_size_y;
+
+ /* #ifdef USE_DRAG_POPUP */
+ bool is_grab;
+ int grab_xy_prev[2];
+ /* #endif */
};
/* -------------------------------------------------------------------- */
@@ -614,41 +626,56 @@ ColorPicker *ui_block_colorpicker_create(struct uiBlock *block);
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);
+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, uiBut *but, const struct wmEvent *event);
+void ui_searchbox_event(struct bContext *C,
+ struct ARegion *ar,
+ uiBut *but,
+ const struct wmEvent *event);
bool ui_searchbox_apply(uiBut *but, struct ARegion *ar);
void ui_searchbox_free(struct bContext *C, struct ARegion *ar);
void ui_but_search_refresh(uiBut *but);
/* interface_region_menu_popup.c */
-int ui_but_menu_step(uiBut *but, int step);
-bool ui_but_menu_step_poll(const uiBut *but);
+int ui_but_menu_step(uiBut *but, int step);
+bool ui_but_menu_step_poll(const uiBut *but);
uiBut *ui_popup_menu_memory_get(struct uiBlock *block);
-void ui_popup_menu_memory_set(uiBlock *block, struct uiBut *but);
-
-uiBlock *ui_popup_block_refresh(
- struct bContext *C, uiPopupBlockHandle *handle,
- ARegion *butregion, uiBut *but);
-
-uiPopupBlockHandle *ui_popup_block_create(
- struct bContext *C, struct ARegion *butregion, uiBut *but,
- uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func,
- void *arg);
-uiPopupBlockHandle *ui_popup_menu_create(
- struct bContext *C, struct ARegion *butregion, uiBut *but,
- uiMenuCreateFunc create_func, void *arg);
+void ui_popup_menu_memory_set(uiBlock *block, struct uiBut *but);
+
+uiBlock *ui_popup_block_refresh(struct bContext *C,
+ uiPopupBlockHandle *handle,
+ ARegion *butregion,
+ uiBut *but);
+
+uiPopupBlockHandle *ui_popup_block_create(struct bContext *C,
+ struct ARegion *butregion,
+ uiBut *but,
+ uiBlockCreateFunc create_func,
+ uiBlockHandleCreateFunc handle_create_func,
+ void *arg);
+uiPopupBlockHandle *ui_popup_menu_create(struct bContext *C,
+ struct ARegion *butregion,
+ uiBut *but,
+ uiMenuCreateFunc create_func,
+ void *arg);
/* interface_region_popover.c */
-uiPopupBlockHandle *ui_popover_panel_create(
- struct bContext *C, struct ARegion *butregion, uiBut *but,
- uiMenuCreateFunc create_func, void *arg);
+uiPopupBlockHandle *ui_popover_panel_create(struct bContext *C,
+ struct ARegion *butregion,
+ uiBut *but,
+ uiMenuCreateFunc create_func,
+ void *arg);
/* interface_region_menu_pie.c */
-void ui_pie_menu_level_create(
- uiBlock *block, struct wmOperatorType *ot, const char *propname, IDProperty *properties,
- const EnumPropertyItem *items, int totitem, int context, int flag);
+void ui_pie_menu_level_create(uiBlock *block,
+ struct wmOperatorType *ot,
+ const char *propname,
+ 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]);
@@ -657,42 +684,78 @@ void ui_popup_block_scrolltest(struct uiBlock *block);
/* end interface_region_*.c */
-
/* interface_panel.c */
-extern int ui_handler_panel_region(
- struct bContext *C, const struct wmEvent *event,
- struct ARegion *ar, const uiBut *active_but);
-extern void ui_draw_aligned_panel(
- struct uiStyle *style, uiBlock *block, const rcti *rect,
- const bool show_pin, const bool show_background);
+extern int ui_handler_panel_region(struct bContext *C,
+ const struct wmEvent *event,
+ struct ARegion *ar,
+ const uiBut *active_but);
+extern void ui_draw_aligned_panel(struct uiStyle *style,
+ uiBlock *block,
+ const rcti *rect,
+ const bool show_pin,
+ const bool show_background);
/* interface_draw.c */
-extern void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select);
+extern void ui_draw_dropshadow(
+ const rctf *rct, float radius, float aspect, float alpha, int select);
void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, const float alpha);
-
-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, uiBut *but, const struct uiWidgetColors *wcol, const rcti *rect);
-void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, const struct uiWidgetColors *wcol, const rcti *rect);
-void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, const struct uiWidgetColors *wcol, const rcti *rect);
+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,
+ uiBut *but,
+ const struct uiWidgetColors *wcol,
+ const rcti *rect);
+void ui_draw_but_WAVEFORM(ARegion *ar,
+ uiBut *but,
+ const struct uiWidgetColors *wcol,
+ const rcti *rect);
+void ui_draw_but_VECTORSCOPE(ARegion *ar,
+ 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, uiBut *but, const struct uiWidgetColors *wcol, const rcti *rect);
-void ui_draw_but_IMAGE(ARegion *ar, uiBut *but, const struct uiWidgetColors *wcol, const rcti *rect);
-void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, const struct uiWidgetColors *wcol, const rcti *rect);
-void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, const struct uiWidgetColors *wcol, const rcti *rect);
+void ui_draw_but_CURVE(ARegion *ar,
+ uiBut *but,
+ const struct uiWidgetColors *wcol,
+ const rcti *rect);
+void ui_draw_but_IMAGE(ARegion *ar,
+ uiBut *but,
+ const struct uiWidgetColors *wcol,
+ const rcti *rect);
+void ui_draw_but_TRACKPREVIEW(ARegion *ar,
+ uiBut *but,
+ const struct uiWidgetColors *wcol,
+ const rcti *rect);
+void ui_draw_but_NODESOCKET(ARegion *ar,
+ uiBut *but,
+ const struct uiWidgetColors *wcol,
+ const rcti *rect);
/* interface_handlers.c */
-PointerRNA *ui_handle_afterfunc_add_operator(struct wmOperatorType *ot, int opcontext, bool create_props);
+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_execute_begin(struct bContext *C, struct ARegion *ar, uiBut *but, void **active_back);
-extern void ui_but_execute_end(struct bContext *C, struct ARegion *ar, uiBut *but, void *active_back);
+extern void ui_but_execute_begin(struct bContext *C,
+ struct ARegion *ar,
+ uiBut *but,
+ void **active_back);
+extern void ui_but_execute_end(struct bContext *C,
+ struct ARegion *ar,
+ uiBut *but,
+ void *active_back);
extern void ui_but_active_free(const struct bContext *C, uiBut *but);
extern int ui_but_menu_direction(uiBut *but);
-extern void ui_but_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, const bool restore);
+extern void ui_but_text_password_hide(char password_str[UI_MAX_DRAW_STR],
+ uiBut *but,
+ const bool restore);
extern uiBut *ui_but_find_select_in_enum(uiBut *but, int direction);
bool ui_but_is_editing(const uiBut *but);
float ui_block_calc_pie_segment(struct uiBlock *block, const float event_xy[2]);
@@ -711,32 +774,32 @@ struct wmIMEData *ui_but_ime_data_get(uiBut *but);
/* Widget shader parameters, must match the shader layout. */
typedef struct uiWidgetBaseParameters {
- rctf recti, rect;
- float radi, rad;
- float facxi, facyi;
- float round_corners[4];
- float color_inner1[4], color_inner2[4];
- float color_outline[4], color_emboss[4];
- float color_tria[4];
- float tria1_center[2], tria2_center[2];
- float tria1_size, tria2_size;
- float shade_dir;
- /* We pack alpha check and discard factor in alpha_discard.
- * If the value is negative then we do alpha check.
- * The absolute value itself is the discard factor.
- * Initialize value to 1.0.f if you don't want discard */
- float alpha_discard;
+ rctf recti, rect;
+ float radi, rad;
+ float facxi, facyi;
+ float round_corners[4];
+ float color_inner1[4], color_inner2[4];
+ float color_outline[4], color_emboss[4];
+ float color_tria[4];
+ float tria1_center[2], tria2_center[2];
+ float tria1_size, tria2_size;
+ float shade_dir;
+ /* We pack alpha check and discard factor in alpha_discard.
+ * If the value is negative then we do alpha check.
+ * The absolute value itself is the discard factor.
+ * Initialize value to 1.0.f if you don't want discard */
+ float alpha_discard;
} uiWidgetBaseParameters;
enum {
- ROUNDBOX_TRIA_NONE = 0,
- ROUNDBOX_TRIA_ARROWS,
- ROUNDBOX_TRIA_SCROLL,
- ROUNDBOX_TRIA_MENU,
- ROUNDBOX_TRIA_CHECK,
- ROUNDBOX_TRIA_HOLD_ACTION_ARROW,
-
- ROUNDBOX_TRIA_MAX, /* don't use */
+ ROUNDBOX_TRIA_NONE = 0,
+ ROUNDBOX_TRIA_ARROWS,
+ ROUNDBOX_TRIA_SCROLL,
+ ROUNDBOX_TRIA_MENU,
+ ROUNDBOX_TRIA_CHECK,
+ ROUNDBOX_TRIA_HOLD_ACTION_ARROW,
+
+ ROUNDBOX_TRIA_MAX, /* don't use */
};
struct GPUBatch *ui_batch_roundbox_get(bool filled, bool antialiased);
@@ -753,10 +816,17 @@ void ui_draw_widget_menu_back_color(const rcti *rect, bool use_shadow, const flo
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);
-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, ARegion *ar, 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);
-void ui_draw_preview_item(const struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state);
+void ui_draw_menu_item(const struct uiFontStyle *fstyle,
+ rcti *rect,
+ const char *name,
+ int iconid,
+ int state,
+ bool use_sep);
+void ui_draw_preview_item(
+ const struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state);
#define UI_TEXT_MARGIN_X 0.4f
#define UI_POPUP_MARGIN (UI_DPI_FAC * 12)
@@ -775,8 +845,7 @@ int ui_id_icon_get(const struct bContext *C, struct ID *id, const bool big);
/* interface_icons_event.c */
void icon_draw_rect_input(
- float x, float y, int w, int h, float alpha,
- short event_type, short event_value);
+ float x, float y, int w, int h, float alpha, short event_type, short event_value);
/* resources.c */
void init_userdef_do_versions(struct Main *bmain);
@@ -785,7 +854,11 @@ void ui_resources_free(void);
/* interface_layout.c */
void ui_layout_add_but(uiLayout *layout, uiBut *but);
-void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop);
+void ui_but_add_search(uiBut *but,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ PointerRNA *searchptr,
+ PropertyRNA *searchprop);
void ui_layout_list_set_labels_active(uiLayout *layout);
/* menu callback */
void ui_item_menutype_func(struct bContext *C, struct uiLayout *layout, void *arg_mt);
@@ -793,7 +866,7 @@ 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;
+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);
/* interface_anim.c */
@@ -820,17 +893,22 @@ void ui_but_pie_dir(RadialDirection dir, float vec[2]);
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_point_px_icon(
- const uiBut *but, struct ARegion *ar, 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) ATTR_WARN_UNUSED_RESULT;
+bool ui_but_contains_pt(const uiBut *but, float mx, float my) ATTR_WARN_UNUSED_RESULT;
+bool ui_but_contains_point_px_icon(const uiBut *but,
+ struct ARegion *ar,
+ 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)
+ ATTR_WARN_UNUSED_RESULT;
-uiBut *ui_list_find_mouse_over(struct ARegion *ar, const struct wmEvent *event) ATTR_WARN_UNUSED_RESULT;
+uiBut *ui_list_find_mouse_over(struct ARegion *ar,
+ const struct wmEvent *event) ATTR_WARN_UNUSED_RESULT;
-uiBut *ui_but_find_mouse_over_ex(struct ARegion *ar, const int x, const int y, const bool labeledit) ATTR_WARN_UNUSED_RESULT;
-uiBut *ui_but_find_mouse_over(struct ARegion *ar, const struct wmEvent *event) ATTR_WARN_UNUSED_RESULT;
+uiBut *ui_but_find_mouse_over_ex(struct ARegion *ar,
+ const int x,
+ const int y,
+ const bool labeledit) ATTR_WARN_UNUSED_RESULT;
+uiBut *ui_but_find_mouse_over(struct ARegion *ar,
+ const struct wmEvent *event) ATTR_WARN_UNUSED_RESULT;
uiBut *ui_list_find_mouse_over_ex(struct ARegion *ar, int x, int y) ATTR_WARN_UNUSED_RESULT;
@@ -848,8 +926,7 @@ 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_point_px(const struct ARegion *ar, int x, int y) ATTR_WARN_UNUSED_RESULT;
/* interface_context_menu.c */
bool ui_popup_context_menu_for_button(struct bContext *C, uiBut *but);
@@ -881,18 +958,20 @@ void UI_OT_eyedropper_driver(struct wmOperatorType *ot);
* For use with #ui_rna_collection_search_cb.
*/
typedef struct uiRNACollectionSearch {
- PointerRNA target_ptr;
- PropertyRNA *target_prop;
+ PointerRNA target_ptr;
+ PropertyRNA *target_prop;
- PointerRNA search_ptr;
- PropertyRNA *search_prop;
+ PointerRNA search_ptr;
+ PropertyRNA *search_prop;
- bool *but_changed; /* pointer to uiBut.changed */
+ bool *but_changed; /* pointer to uiBut.changed */
} uiRNACollectionSearch;
-void ui_rna_collection_search_cb(const struct bContext *C, void *arg, const char *str, uiSearchItems *items);
+void ui_rna_collection_search_cb(const struct bContext *C,
+ void *arg,
+ const char *str,
+ uiSearchItems *items);
/* interface_ops.c */
bool ui_jump_to_target_button_poll(struct bContext *C);
-
-#endif /* __INTERFACE_INTERN_H__ */
+#endif /* __INTERFACE_INTERN_H__ */
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index fbfa2d11e45..8e463bf8447 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -18,7 +18,6 @@
* \ingroup edinterface
*/
-
#include <limits.h>
#include <math.h>
#include <stdlib.h>
@@ -52,7 +51,6 @@
#include "ED_armature.h"
-
#include "WM_api.h"
#include "WM_types.h"
@@ -67,762 +65,834 @@
/************************ Structs and Defines *************************/
-#define UI_OPERATOR_ERROR_RET(_ot, _opname, return_statement) \
- if (ot == NULL) { \
- ui_item_disabled(layout, _opname); \
- RNA_warning("'%s' unknown operator", _opname); \
- return_statement; \
- } (void)0 \
+#define UI_OPERATOR_ERROR_RET(_ot, _opname, return_statement) \
+ if (ot == NULL) { \
+ ui_item_disabled(layout, _opname); \
+ RNA_warning("'%s' unknown operator", _opname); \
+ return_statement; \
+ } \
+ (void)0
#define UI_ITEM_PROP_SEP_DIVIDE 0.5f
/* uiLayoutRoot */
typedef struct uiLayoutRoot {
- struct uiLayoutRoot *next, *prev;
+ struct uiLayoutRoot *next, *prev;
- int type;
- int opcontext;
+ int type;
+ int opcontext;
- int emw, emh;
- int padding;
+ int emw, emh;
+ int padding;
- uiMenuHandleFunc handlefunc;
- void *argv;
+ uiMenuHandleFunc handlefunc;
+ void *argv;
- uiStyle *style;
- uiBlock *block;
- uiLayout *layout;
+ uiStyle *style;
+ uiBlock *block;
+ uiLayout *layout;
} uiLayoutRoot;
/* Item */
typedef enum uiItemType {
- ITEM_BUTTON,
-
- ITEM_LAYOUT_ROW,
- ITEM_LAYOUT_COLUMN,
- ITEM_LAYOUT_COLUMN_FLOW,
- ITEM_LAYOUT_ROW_FLOW,
- ITEM_LAYOUT_GRID_FLOW,
- ITEM_LAYOUT_BOX,
- ITEM_LAYOUT_ABSOLUTE,
- ITEM_LAYOUT_SPLIT,
- ITEM_LAYOUT_OVERLAP,
- ITEM_LAYOUT_RADIAL,
-
- ITEM_LAYOUT_ROOT
+ ITEM_BUTTON,
+
+ ITEM_LAYOUT_ROW,
+ ITEM_LAYOUT_COLUMN,
+ ITEM_LAYOUT_COLUMN_FLOW,
+ ITEM_LAYOUT_ROW_FLOW,
+ ITEM_LAYOUT_GRID_FLOW,
+ ITEM_LAYOUT_BOX,
+ ITEM_LAYOUT_ABSOLUTE,
+ ITEM_LAYOUT_SPLIT,
+ ITEM_LAYOUT_OVERLAP,
+ ITEM_LAYOUT_RADIAL,
+
+ ITEM_LAYOUT_ROOT
#if 0
- TEMPLATE_COLUMN_FLOW,
- TEMPLATE_SPLIT,
- TEMPLATE_BOX,
+ TEMPLATE_COLUMN_FLOW,
+ TEMPLATE_SPLIT,
+ TEMPLATE_BOX,
- TEMPLATE_HEADER,
- TEMPLATE_HEADER_ID,
+ TEMPLATE_HEADER,
+ TEMPLATE_HEADER_ID,
#endif
} uiItemType;
typedef struct uiItem {
- void *next, *prev;
- uiItemType type;
- int flag;
+ void *next, *prev;
+ uiItemType type;
+ int flag;
} uiItem;
enum {
- UI_ITEM_FIXED = 1 << 0,
- UI_ITEM_MIN = 1 << 1,
-
- UI_ITEM_BOX_ITEM = 1 << 2, /* The item is "inside" a box item */
- UI_ITEM_PROP_SEP = 1 << 3,
- /* 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_FIXED = 1 << 0,
+ UI_ITEM_MIN = 1 << 1,
+
+ UI_ITEM_BOX_ITEM = 1 << 2, /* The item is "inside" a box item */
+ UI_ITEM_PROP_SEP = 1 << 3,
+ /* 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,
};
typedef struct uiButtonItem {
- uiItem item;
- uiBut *but;
+ uiItem item;
+ uiBut *but;
} uiButtonItem;
struct uiLayout {
- uiItem item;
-
- uiLayoutRoot *root;
- bContextStore *context;
- ListBase items;
-
- /** Sub layout to add child items, if not the layout itself. */
- uiLayout *child_items_layout;
-
- int x, y, w, h;
- float scale[2];
- short space;
- bool align;
- bool active;
- bool active_default;
- bool activate_init;
- bool enabled;
- bool redalert;
- bool keepaspect;
- /** For layouts inside gridflow, they and their items shall never have a fixed maximal size. */
- bool variable_size;
- char alignment;
- char emboss;
- /** for fixed width or height to avoid UI size changes */
- float units[2];
+ uiItem item;
+
+ uiLayoutRoot *root;
+ bContextStore *context;
+ ListBase items;
+
+ /** Sub layout to add child items, if not the layout itself. */
+ uiLayout *child_items_layout;
+
+ int x, y, w, h;
+ float scale[2];
+ short space;
+ bool align;
+ bool active;
+ bool active_default;
+ bool activate_init;
+ bool enabled;
+ bool redalert;
+ bool keepaspect;
+ /** For layouts inside gridflow, they and their items shall never have a fixed maximal size. */
+ bool variable_size;
+ char alignment;
+ char emboss;
+ /** for fixed width or height to avoid UI size changes */
+ float units[2];
};
typedef struct uiLayoutItemFlow {
- uiLayout litem;
- int number;
- int totcol;
+ uiLayout litem;
+ int number;
+ int totcol;
} uiLayoutItemFlow;
typedef struct uiLayoutItemGridFlow {
- uiLayout litem;
-
- /* Extra parameters */
- bool row_major; /* Fill first row first, instead of filling first column first. */
- bool even_columns; /* Same width for all columns. */
- bool even_rows; /* Same height for all rows. */
- /**
- * - If positive, absolute fixed number of columns.
- * - If 0, fully automatic (based on available width).
- * - If negative, automatic but only generates number of columns/rows
- * multiple of given (absolute) value.
- */
- int columns_len;
-
- /* Pure internal runtime storage. */
- int tot_items, tot_columns, tot_rows;
+ uiLayout litem;
+
+ /* Extra parameters */
+ bool row_major; /* Fill first row first, instead of filling first column first. */
+ bool even_columns; /* Same width for all columns. */
+ bool even_rows; /* Same height for all rows. */
+ /**
+ * - If positive, absolute fixed number of columns.
+ * - If 0, fully automatic (based on available width).
+ * - If negative, automatic but only generates number of columns/rows
+ * multiple of given (absolute) value.
+ */
+ int columns_len;
+
+ /* Pure internal runtime storage. */
+ int tot_items, tot_columns, tot_rows;
} uiLayoutItemGridFlow;
typedef struct uiLayoutItemBx {
- uiLayout litem;
- uiBut *roundbox;
+ uiLayout litem;
+ uiBut *roundbox;
} uiLayoutItemBx;
typedef struct uiLayoutItemSplit {
- uiLayout litem;
- float percentage;
+ uiLayout litem;
+ float percentage;
} uiLayoutItemSplit;
typedef struct uiLayoutItemRoot {
- uiLayout litem;
+ uiLayout litem;
} uiLayoutItemRoot;
/************************** Item ***************************/
static const char *ui_item_name_add_colon(const char *name, char namestr[UI_MAX_NAME_STR])
{
- int len = strlen(name);
-
- if (len != 0 && len + 1 < UI_MAX_NAME_STR) {
- memcpy(namestr, name, len);
- namestr[len] = ':';
- namestr[len + 1] = '\0';
- return namestr;
- }
-
- return name;
-}
-
-static int ui_item_fit(int item, int pos, int all, int available, bool is_last, int alignment, float *extra_pixel)
-{
- /* available == 0 is unlimited */
- if (ELEM(0, available, all)) {
- return item;
- }
-
- if (all > available) {
- /* contents is bigger than available space */
- if (is_last) {
- return available - pos;
- }
- else {
- float width = *extra_pixel + (item * available) / (float)all;
- *extra_pixel = width - (int)width;
- return (int)width;
- }
- }
- else {
- /* contents is smaller or equal to available space */
- if (alignment == UI_LAYOUT_ALIGN_EXPAND) {
- if (is_last) {
- return available - pos;
- }
- else {
- float width = *extra_pixel + (item * available) / (float)all;
- *extra_pixel = width - (int)width;
- return (int)width;
- }
- }
- else {
- return item;
- }
- }
+ int len = strlen(name);
+
+ if (len != 0 && len + 1 < UI_MAX_NAME_STR) {
+ memcpy(namestr, name, len);
+ namestr[len] = ':';
+ namestr[len + 1] = '\0';
+ return namestr;
+ }
+
+ return name;
+}
+
+static int ui_item_fit(
+ int item, int pos, int all, int available, bool is_last, int alignment, float *extra_pixel)
+{
+ /* available == 0 is unlimited */
+ if (ELEM(0, available, all)) {
+ return item;
+ }
+
+ if (all > available) {
+ /* contents is bigger than available space */
+ if (is_last) {
+ return available - pos;
+ }
+ else {
+ float width = *extra_pixel + (item * available) / (float)all;
+ *extra_pixel = width - (int)width;
+ return (int)width;
+ }
+ }
+ else {
+ /* contents is smaller or equal to available space */
+ if (alignment == UI_LAYOUT_ALIGN_EXPAND) {
+ if (is_last) {
+ return available - pos;
+ }
+ else {
+ float width = *extra_pixel + (item * available) / (float)all;
+ *extra_pixel = width - (int)width;
+ return (int)width;
+ }
+ }
+ else {
+ return item;
+ }
+ }
}
/* variable button size in which direction? */
-#define UI_ITEM_VARY_X 1
-#define UI_ITEM_VARY_Y 2
+#define UI_ITEM_VARY_X 1
+#define UI_ITEM_VARY_Y 2
static int ui_layout_vary_direction(uiLayout *layout)
{
- return ((ELEM(layout->root->type, UI_LAYOUT_HEADER, UI_LAYOUT_PIEMENU) ||
- (layout->alignment != UI_LAYOUT_ALIGN_EXPAND)) ?
- UI_ITEM_VARY_X : UI_ITEM_VARY_Y);
+ return ((ELEM(layout->root->type, UI_LAYOUT_HEADER, UI_LAYOUT_PIEMENU) ||
+ (layout->alignment != UI_LAYOUT_ALIGN_EXPAND)) ?
+ UI_ITEM_VARY_X :
+ UI_ITEM_VARY_Y);
}
static bool ui_layout_variable_size(uiLayout *layout)
{
- /* Note that this code is probably a bit flacky, we'd probably want to know whether it's
- * variable in X and/or Y, etc. But for now it mimics previous one,
- * with addition of variable flag set for children of gridflow layouts. */
- return ui_layout_vary_direction(layout) == UI_ITEM_VARY_X || layout->variable_size;
+ /* Note that this code is probably a bit flacky, we'd probably want to know whether it's
+ * variable in X and/or Y, etc. But for now it mimics previous one,
+ * with addition of variable flag set for children of gridflow layouts. */
+ return ui_layout_vary_direction(layout) == UI_ITEM_VARY_X || layout->variable_size;
}
/* estimated size of text + icon */
static int ui_text_icon_width(uiLayout *layout, const char *name, int icon, bool compact)
{
- bool variable;
- const int unit_x = UI_UNIT_X * (layout->scale[0] ? layout->scale[0] : 1.0f);
-
- if (icon && !name[0]) {
- return unit_x; /* icon only */
- }
-
- variable = ui_layout_variable_size(layout);
-
- if (variable) {
- if (!icon && !name[0]) {
- return unit_x; /* No icon or name. */
- }
- if (layout->alignment != UI_LAYOUT_ALIGN_EXPAND) {
- layout->item.flag |= UI_ITEM_MIN;
- }
- const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- /* it may seem odd that the icon only adds (unit_x / 4)
- * but taking margins into account its fine */
- return (UI_fontstyle_string_width(fstyle, name) +
- (unit_x * ((compact ? 1.25f : 1.50f) +
- (icon ? 0.25f : 0.0f))));
- }
- else {
- return unit_x * 10;
- }
+ bool variable;
+ const int unit_x = UI_UNIT_X * (layout->scale[0] ? layout->scale[0] : 1.0f);
+
+ if (icon && !name[0]) {
+ return unit_x; /* icon only */
+ }
+
+ variable = ui_layout_variable_size(layout);
+
+ if (variable) {
+ if (!icon && !name[0]) {
+ return unit_x; /* No icon or name. */
+ }
+ if (layout->alignment != UI_LAYOUT_ALIGN_EXPAND) {
+ layout->item.flag |= UI_ITEM_MIN;
+ }
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ /* it may seem odd that the icon only adds (unit_x / 4)
+ * but taking margins into account its fine */
+ return (UI_fontstyle_string_width(fstyle, name) +
+ (unit_x * ((compact ? 1.25f : 1.50f) + (icon ? 0.25f : 0.0f))));
+ }
+ else {
+ return unit_x * 10;
+ }
}
static void ui_item_size(uiItem *item, int *r_w, int *r_h)
{
- if (item->type == ITEM_BUTTON) {
- uiButtonItem *bitem = (uiButtonItem *)item;
+ if (item->type == ITEM_BUTTON) {
+ uiButtonItem *bitem = (uiButtonItem *)item;
- if (r_w) {
- *r_w = BLI_rctf_size_x(&bitem->but->rect);
- }
- if (r_h) {
- *r_h = BLI_rctf_size_y(&bitem->but->rect);
- }
- }
- else {
- uiLayout *litem = (uiLayout *)item;
+ if (r_w) {
+ *r_w = BLI_rctf_size_x(&bitem->but->rect);
+ }
+ if (r_h) {
+ *r_h = BLI_rctf_size_y(&bitem->but->rect);
+ }
+ }
+ else {
+ uiLayout *litem = (uiLayout *)item;
- if (r_w) {
- *r_w = litem->w;
- }
- if (r_h) {
- *r_h = litem->h;
- }
- }
+ if (r_w) {
+ *r_w = litem->w;
+ }
+ if (r_h) {
+ *r_h = litem->h;
+ }
+ }
}
static void ui_item_offset(uiItem *item, int *r_x, int *r_y)
{
- if (item->type == ITEM_BUTTON) {
- uiButtonItem *bitem = (uiButtonItem *)item;
-
- if (r_x) {
- *r_x = bitem->but->rect.xmin;
- }
- if (r_y) {
- *r_y = bitem->but->rect.ymin;
- }
- }
- else {
- if (r_x) {
- *r_x = 0;
- }
- if (r_y) {
- *r_y = 0;
- }
- }
+ if (item->type == ITEM_BUTTON) {
+ uiButtonItem *bitem = (uiButtonItem *)item;
+
+ if (r_x) {
+ *r_x = bitem->but->rect.xmin;
+ }
+ if (r_y) {
+ *r_y = bitem->but->rect.ymin;
+ }
+ }
+ else {
+ if (r_x) {
+ *r_x = 0;
+ }
+ if (r_y) {
+ *r_y = 0;
+ }
+ }
}
static void ui_item_position(uiItem *item, int x, int y, int w, int h)
{
- if (item->type == ITEM_BUTTON) {
- uiButtonItem *bitem = (uiButtonItem *)item;
+ if (item->type == ITEM_BUTTON) {
+ uiButtonItem *bitem = (uiButtonItem *)item;
- bitem->but->rect.xmin = x;
- bitem->but->rect.ymin = y;
- bitem->but->rect.xmax = x + w;
- bitem->but->rect.ymax = y + h;
+ bitem->but->rect.xmin = x;
+ bitem->but->rect.ymin = y;
+ bitem->but->rect.xmax = x + w;
+ bitem->but->rect.ymax = y + h;
- ui_but_update(bitem->but); /* for strlen */
- }
- else {
- uiLayout *litem = (uiLayout *)item;
+ ui_but_update(bitem->but); /* for strlen */
+ }
+ else {
+ uiLayout *litem = (uiLayout *)item;
- litem->x = x;
- litem->y = y + h;
- litem->w = w;
- litem->h = h;
- }
+ litem->x = x;
+ litem->y = y + h;
+ litem->w = w;
+ litem->h = h;
+ }
}
static void ui_item_move(uiItem *item, int delta_xmin, int delta_xmax)
{
- if (item->type == ITEM_BUTTON) {
- uiButtonItem *bitem = (uiButtonItem *)item;
+ if (item->type == ITEM_BUTTON) {
+ uiButtonItem *bitem = (uiButtonItem *)item;
- bitem->but->rect.xmin += delta_xmin;
- bitem->but->rect.xmax += delta_xmax;
+ bitem->but->rect.xmin += delta_xmin;
+ bitem->but->rect.xmax += delta_xmax;
- ui_but_update(bitem->but); /* for strlen */
- }
- else {
- uiLayout *litem = (uiLayout *)item;
+ ui_but_update(bitem->but); /* for strlen */
+ }
+ else {
+ uiLayout *litem = (uiLayout *)item;
- if (delta_xmin > 0) {
- litem->x += delta_xmin;
- }
- else {
- litem->w += delta_xmax;
- }
- }
+ if (delta_xmin > 0) {
+ litem->x += delta_xmin;
+ }
+ else {
+ litem->w += delta_xmax;
+ }
+ }
}
/******************** Special RNA Items *********************/
int uiLayoutGetLocalDir(const uiLayout *layout)
{
- switch (layout->item.type) {
- case ITEM_LAYOUT_ROW:
- case ITEM_LAYOUT_ROOT:
- case ITEM_LAYOUT_OVERLAP:
- return UI_LAYOUT_HORIZONTAL;
- case ITEM_LAYOUT_COLUMN:
- case ITEM_LAYOUT_COLUMN_FLOW:
- case ITEM_LAYOUT_GRID_FLOW:
- case ITEM_LAYOUT_SPLIT:
- case ITEM_LAYOUT_ABSOLUTE:
- case ITEM_LAYOUT_BOX:
- default:
- return UI_LAYOUT_VERTICAL;
- }
+ switch (layout->item.type) {
+ case ITEM_LAYOUT_ROW:
+ case ITEM_LAYOUT_ROOT:
+ case ITEM_LAYOUT_OVERLAP:
+ return UI_LAYOUT_HORIZONTAL;
+ case ITEM_LAYOUT_COLUMN:
+ case ITEM_LAYOUT_COLUMN_FLOW:
+ case ITEM_LAYOUT_GRID_FLOW:
+ case ITEM_LAYOUT_SPLIT:
+ case ITEM_LAYOUT_ABSOLUTE:
+ case ITEM_LAYOUT_BOX:
+ default:
+ return UI_LAYOUT_VERTICAL;
+ }
}
static uiLayout *ui_item_local_sublayout(uiLayout *test, uiLayout *layout, bool align)
{
- uiLayout *sub;
+ uiLayout *sub;
- if (uiLayoutGetLocalDir(test) == UI_LAYOUT_HORIZONTAL) {
- sub = uiLayoutRow(layout, align);
- }
- else {
- sub = uiLayoutColumn(layout, align);
- }
+ if (uiLayoutGetLocalDir(test) == UI_LAYOUT_HORIZONTAL) {
+ sub = uiLayoutRow(layout, align);
+ }
+ else {
+ sub = uiLayoutColumn(layout, align);
+ }
- sub->space = 0;
- return sub;
+ sub->space = 0;
+ return sub;
}
static void ui_layer_but_cb(bContext *C, void *arg_but, void *arg_index)
{
- wmWindow *win = CTX_wm_window(C);
- uiBut *but = arg_but, *cbut;
- PointerRNA *ptr = &but->rnapoin;
- PropertyRNA *prop = but->rnaprop;
- int i, index = POINTER_AS_INT(arg_index);
- int shift = win->eventstate->shift;
- int len = RNA_property_array_length(ptr, prop);
+ wmWindow *win = CTX_wm_window(C);
+ uiBut *but = arg_but, *cbut;
+ PointerRNA *ptr = &but->rnapoin;
+ PropertyRNA *prop = but->rnaprop;
+ int i, index = POINTER_AS_INT(arg_index);
+ int shift = win->eventstate->shift;
+ int len = RNA_property_array_length(ptr, prop);
- if (!shift) {
- RNA_property_boolean_set_index(ptr, prop, index, true);
+ if (!shift) {
+ RNA_property_boolean_set_index(ptr, prop, index, true);
- for (i = 0; i < len; i++) {
- if (i != index) {
- RNA_property_boolean_set_index(ptr, prop, i, 0);
- }
- }
+ for (i = 0; i < len; i++) {
+ if (i != index) {
+ RNA_property_boolean_set_index(ptr, prop, i, 0);
+ }
+ }
- RNA_property_update(C, ptr, prop);
+ RNA_property_update(C, ptr, prop);
- for (cbut = but->block->buttons.first; cbut; cbut = cbut->next) {
- ui_but_update(cbut);
- }
- }
+ for (cbut = but->block->buttons.first; cbut; cbut = cbut->next) {
+ ui_but_update(cbut);
+ }
+ }
}
/* create buttons for an item with an RNA array */
-static void ui_item_array(
- uiLayout *layout, uiBlock *block, const char *name, int icon,
- PointerRNA *ptr, PropertyRNA *prop, int len, int x, int y, int w, int UNUSED(h),
- bool expand, bool slider, bool toggle, bool icon_only, bool compact, bool show_text)
-{
- uiStyle *style = layout->root->style;
- uiBut *but;
- PropertyType type;
- PropertySubType subtype;
- uiLayout *sub;
- uint a, b;
-
- /* retrieve type and subtype */
- type = RNA_property_type(prop);
- subtype = RNA_property_subtype(prop);
-
- sub = ui_item_local_sublayout(layout, layout, 1);
- UI_block_layout_set_current(block, sub);
-
- /* create label */
- if (name[0] && show_text) {
- uiDefBut(block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- }
-
- /* create buttons */
- if (type == PROP_BOOLEAN && ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER)) {
- /* special check for layer layout */
- int butw, buth, unit;
- int cols = (len >= 20) ? 2 : 1;
- const uint colbuts = len / (2 * cols);
- uint layer_used = 0;
- uint layer_active = 0;
-
- UI_block_layout_set_current(block, uiLayoutAbsolute(layout, false));
-
- unit = UI_UNIT_X * 0.75;
- butw = unit;
- buth = unit;
-
- if (ptr->type == &RNA_Armature) {
- bArmature *arm = (bArmature *)ptr->data;
-
- layer_used = arm->layer_used;
-
- if (arm->edbo) {
- if (arm->act_edbone) {
- layer_active |= arm->act_edbone->layer;
- }
- }
- else {
- if (arm->act_bone) {
- layer_active |= arm->act_bone->layer;
- }
- }
- }
-
- for (b = 0; b < cols; b++) {
- UI_block_align_begin(block);
-
- for (a = 0; a < colbuts; a++) {
- const int layer_num = a + b * colbuts;
- const uint layer_flag = (1u << layer_num);
-
- if (layer_used & layer_flag) {
- if (layer_active & layer_flag) {
- icon = ICON_LAYER_ACTIVE;
- }
- else {
- icon = ICON_LAYER_USED;
- }
- }
- else {
- icon = ICON_BLANK1;
- }
-
- but = uiDefAutoButR(block, ptr, prop, layer_num, "", icon, x + butw * a, y + buth, butw, buth);
- if (subtype == PROP_LAYER_MEMBER) {
- UI_but_func_set(but, ui_layer_but_cb, but, POINTER_FROM_INT(layer_num));
- }
- }
- for (a = 0; a < colbuts; a++) {
- const int layer_num = a + len / 2 + b * colbuts;
- const uint layer_flag = (1u << layer_num);
-
- if (layer_used & layer_flag) {
- if (layer_active & layer_flag) {
- icon = ICON_LAYER_ACTIVE;
- }
- else {
- icon = ICON_LAYER_USED;
- }
- }
- else {
- icon = ICON_BLANK1;
- }
-
- but = uiDefAutoButR(block, ptr, prop, layer_num, "", icon, x + butw * a, y, butw, buth);
- if (subtype == PROP_LAYER_MEMBER) {
- UI_but_func_set(but, ui_layer_but_cb, but, POINTER_FROM_INT(layer_num));
- }
- }
- UI_block_align_end(block);
-
- x += colbuts * butw + style->buttonspacex;
- }
- }
- else if (subtype == PROP_MATRIX) {
- int totdim, dim_size[3]; /* 3 == RNA_MAX_ARRAY_DIMENSION */
- int row, col;
-
- UI_block_layout_set_current(block, uiLayoutAbsolute(layout, true));
-
- totdim = RNA_property_array_dimension(ptr, prop, dim_size);
- if (totdim != 2) {
- /* Only 2D matrices supported in UI so far. */
- return;
- }
-
- w /= dim_size[0];
- /* h /= dim_size[1]; */ /* UNUSED */
-
- for (a = 0; a < len; a++) {
- col = a % dim_size[0];
- row = a / dim_size[0];
-
- but = uiDefAutoButR(block, ptr, prop, a, "", ICON_NONE, x + w * col, y + (dim_size[1] * UI_UNIT_Y) - (row * UI_UNIT_Y), w, UI_UNIT_Y);
- if (slider && but->type == UI_BTYPE_NUM) {
- but->type = UI_BTYPE_NUM_SLIDER;
- }
- }
- }
- else if (subtype == PROP_DIRECTION && !expand) {
- uiDefButR_prop(block, UI_BTYPE_UNITVEC, 0, name, x, y, UI_UNIT_X * 3, UI_UNIT_Y * 3, ptr, prop, -1, 0, 0, -1, -1, NULL);
- }
- else {
- /* note, this block of code is a bit arbitrary and has just been made
- * to work with common cases, but may need to be re-worked */
-
- /* special case, boolean array in a menu, this could be used in a more generic way too */
- if (ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA) && !expand) {
- uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, 0, 0, w, UI_UNIT_Y);
- }
- else {
- bool *boolarr = NULL;
-
- /* even if 'expand' is fale, expanding anyway */
-
- /* layout for known array subtypes */
- char str[3] = {'\0'};
-
- if (!icon_only && show_text) {
- if (type != PROP_BOOLEAN) {
- str[1] = ':';
- }
- }
-
- /* show checkboxes for rna on a non-emboss block (menu for eg) */
- if (type == PROP_BOOLEAN && ELEM(layout->root->block->dt, UI_EMBOSS_NONE, UI_EMBOSS_PULLDOWN)) {
- boolarr = MEM_callocN(sizeof(bool) * len, __func__);
- RNA_property_boolean_get_array(ptr, prop, boolarr);
- }
-
- const char *str_buf = show_text ? str: "";
- for (a = 0; a < len; a++) {
- int width_item;
-
- if (!icon_only && show_text) {
- str[0] = RNA_property_array_item_char(prop, a);
- }
- if (boolarr) {
- icon = boolarr[a] ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
- }
-
- width_item = (
- (compact && type == PROP_BOOLEAN) ?
- min_ii(w, ui_text_icon_width(layout, str_buf, icon, false)) : w);
-
- but = uiDefAutoButR(block, ptr, prop, a, str_buf, icon, 0, 0, width_item, UI_UNIT_Y);
- if (slider && but->type == UI_BTYPE_NUM) {
- but->type = UI_BTYPE_NUM_SLIDER;
- }
- if (toggle && but->type == UI_BTYPE_CHECKBOX) {
- but->type = UI_BTYPE_TOGGLE;
- }
- if ((a == 0) && (subtype == PROP_AXISANGLE)) {
- UI_but_unit_type_set(but, PROP_UNIT_ROTATION);
- }
- }
-
- if (boolarr) {
- MEM_freeN(boolarr);
- }
- }
- }
-
- UI_block_layout_set_current(block, layout);
+static void ui_item_array(uiLayout *layout,
+ uiBlock *block,
+ const char *name,
+ int icon,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ int len,
+ int x,
+ int y,
+ int w,
+ int UNUSED(h),
+ bool expand,
+ bool slider,
+ bool toggle,
+ bool icon_only,
+ bool compact,
+ bool show_text)
+{
+ uiStyle *style = layout->root->style;
+ uiBut *but;
+ PropertyType type;
+ PropertySubType subtype;
+ uiLayout *sub;
+ uint a, b;
+
+ /* retrieve type and subtype */
+ type = RNA_property_type(prop);
+ subtype = RNA_property_subtype(prop);
+
+ sub = ui_item_local_sublayout(layout, layout, 1);
+ UI_block_layout_set_current(block, sub);
+
+ /* create label */
+ if (name[0] && show_text) {
+ uiDefBut(block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ }
+
+ /* create buttons */
+ if (type == PROP_BOOLEAN && ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER)) {
+ /* special check for layer layout */
+ int butw, buth, unit;
+ int cols = (len >= 20) ? 2 : 1;
+ const uint colbuts = len / (2 * cols);
+ uint layer_used = 0;
+ uint layer_active = 0;
+
+ UI_block_layout_set_current(block, uiLayoutAbsolute(layout, false));
+
+ unit = UI_UNIT_X * 0.75;
+ butw = unit;
+ buth = unit;
+
+ if (ptr->type == &RNA_Armature) {
+ bArmature *arm = (bArmature *)ptr->data;
+
+ layer_used = arm->layer_used;
+
+ if (arm->edbo) {
+ if (arm->act_edbone) {
+ layer_active |= arm->act_edbone->layer;
+ }
+ }
+ else {
+ if (arm->act_bone) {
+ layer_active |= arm->act_bone->layer;
+ }
+ }
+ }
+
+ for (b = 0; b < cols; b++) {
+ UI_block_align_begin(block);
+
+ for (a = 0; a < colbuts; a++) {
+ const int layer_num = a + b * colbuts;
+ const uint layer_flag = (1u << layer_num);
+
+ if (layer_used & layer_flag) {
+ if (layer_active & layer_flag) {
+ icon = ICON_LAYER_ACTIVE;
+ }
+ else {
+ icon = ICON_LAYER_USED;
+ }
+ }
+ else {
+ icon = ICON_BLANK1;
+ }
+
+ but = uiDefAutoButR(
+ block, ptr, prop, layer_num, "", icon, x + butw * a, y + buth, butw, buth);
+ if (subtype == PROP_LAYER_MEMBER) {
+ UI_but_func_set(but, ui_layer_but_cb, but, POINTER_FROM_INT(layer_num));
+ }
+ }
+ for (a = 0; a < colbuts; a++) {
+ const int layer_num = a + len / 2 + b * colbuts;
+ const uint layer_flag = (1u << layer_num);
+
+ if (layer_used & layer_flag) {
+ if (layer_active & layer_flag) {
+ icon = ICON_LAYER_ACTIVE;
+ }
+ else {
+ icon = ICON_LAYER_USED;
+ }
+ }
+ else {
+ icon = ICON_BLANK1;
+ }
+
+ but = uiDefAutoButR(block, ptr, prop, layer_num, "", icon, x + butw * a, y, butw, buth);
+ if (subtype == PROP_LAYER_MEMBER) {
+ UI_but_func_set(but, ui_layer_but_cb, but, POINTER_FROM_INT(layer_num));
+ }
+ }
+ UI_block_align_end(block);
+
+ x += colbuts * butw + style->buttonspacex;
+ }
+ }
+ else if (subtype == PROP_MATRIX) {
+ int totdim, dim_size[3]; /* 3 == RNA_MAX_ARRAY_DIMENSION */
+ int row, col;
+
+ UI_block_layout_set_current(block, uiLayoutAbsolute(layout, true));
+
+ totdim = RNA_property_array_dimension(ptr, prop, dim_size);
+ if (totdim != 2) {
+ /* Only 2D matrices supported in UI so far. */
+ return;
+ }
+
+ w /= dim_size[0];
+ /* h /= dim_size[1]; */ /* UNUSED */
+
+ for (a = 0; a < len; a++) {
+ col = a % dim_size[0];
+ row = a / dim_size[0];
+
+ but = uiDefAutoButR(block,
+ ptr,
+ prop,
+ a,
+ "",
+ ICON_NONE,
+ x + w * col,
+ y + (dim_size[1] * UI_UNIT_Y) - (row * UI_UNIT_Y),
+ w,
+ UI_UNIT_Y);
+ if (slider && but->type == UI_BTYPE_NUM) {
+ but->type = UI_BTYPE_NUM_SLIDER;
+ }
+ }
+ }
+ else if (subtype == PROP_DIRECTION && !expand) {
+ uiDefButR_prop(block,
+ UI_BTYPE_UNITVEC,
+ 0,
+ name,
+ x,
+ y,
+ UI_UNIT_X * 3,
+ UI_UNIT_Y * 3,
+ ptr,
+ prop,
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ }
+ else {
+ /* note, this block of code is a bit arbitrary and has just been made
+ * to work with common cases, but may need to be re-worked */
+
+ /* special case, boolean array in a menu, this could be used in a more generic way too */
+ if (ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA) && !expand) {
+ uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, 0, 0, w, UI_UNIT_Y);
+ }
+ else {
+ bool *boolarr = NULL;
+
+ /* even if 'expand' is fale, expanding anyway */
+
+ /* layout for known array subtypes */
+ char str[3] = {'\0'};
+
+ if (!icon_only && show_text) {
+ if (type != PROP_BOOLEAN) {
+ str[1] = ':';
+ }
+ }
+
+ /* show checkboxes for rna on a non-emboss block (menu for eg) */
+ if (type == PROP_BOOLEAN &&
+ ELEM(layout->root->block->dt, UI_EMBOSS_NONE, UI_EMBOSS_PULLDOWN)) {
+ boolarr = MEM_callocN(sizeof(bool) * len, __func__);
+ RNA_property_boolean_get_array(ptr, prop, boolarr);
+ }
+
+ const char *str_buf = show_text ? str : "";
+ for (a = 0; a < len; a++) {
+ int width_item;
+
+ if (!icon_only && show_text) {
+ str[0] = RNA_property_array_item_char(prop, a);
+ }
+ if (boolarr) {
+ icon = boolarr[a] ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
+ }
+
+ width_item = ((compact && type == PROP_BOOLEAN) ?
+ min_ii(w, ui_text_icon_width(layout, str_buf, icon, false)) :
+ w);
+
+ but = uiDefAutoButR(block, ptr, prop, a, str_buf, icon, 0, 0, width_item, UI_UNIT_Y);
+ if (slider && but->type == UI_BTYPE_NUM) {
+ but->type = UI_BTYPE_NUM_SLIDER;
+ }
+ if (toggle && but->type == UI_BTYPE_CHECKBOX) {
+ but->type = UI_BTYPE_TOGGLE;
+ }
+ if ((a == 0) && (subtype == PROP_AXISANGLE)) {
+ UI_but_unit_type_set(but, PROP_UNIT_ROTATION);
+ }
+ }
+
+ if (boolarr) {
+ MEM_freeN(boolarr);
+ }
+ }
+ }
+
+ UI_block_layout_set_current(block, layout);
}
static void ui_item_enum_expand_handle(bContext *C, void *arg1, void *arg2)
{
- wmWindow *win = CTX_wm_window(C);
-
- if (!win->eventstate->shift) {
- uiBut *but = (uiBut *)arg1;
- int enum_value = POINTER_AS_INT(arg2);
-
- int current_value = RNA_property_enum_get(&but->rnapoin, but->rnaprop);
- if (!(current_value & enum_value)) {
- current_value = enum_value;
- }
- else {
- current_value &= enum_value;
- }
- RNA_property_enum_set(&but->rnapoin, but->rnaprop, current_value);
- }
-}
-static void ui_item_enum_expand_exec(
- uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop,
- const char *uiname, int h, int but_type, bool icon_only)
-{
- /* XXX The way this function currently handles uiname parameter is insane and inconsistent with general UI API:
- * * uiname is the *enum property* label.
- * * when it is NULL or empty, we do not draw *enum items* labels, this doubles the icon_only parameter.
- * * we *never* draw (i.e. really use) the enum label uiname, it is just used as a mere flag!
- * Unfortunately, fixing this implies an API "soft break", so better to defer it for later... :/
- * --mont29
- */
-
- uiBut *but;
- uiLayout *layout_radial = NULL;
- const EnumPropertyItem *item, *item_array;
- const char *name;
- int itemw, icon, value;
- bool free;
- bool radial = (layout->root->type == UI_LAYOUT_PIEMENU);
-
- BLI_assert(RNA_property_type(prop) == PROP_ENUM);
-
- if (radial) {
- RNA_property_enum_items_gettexted_all(block->evil_C, ptr, prop, &item_array, NULL, &free);
- }
- else {
- RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item_array, NULL, &free);
- }
-
- /* we dont want nested rows, cols in menus */
- if (radial) {
- if (layout->root->layout == layout) {
- layout_radial = uiLayoutRadial(layout);
- UI_block_layout_set_current(block, layout_radial);
- }
- else {
- if (layout->item.type == ITEM_LAYOUT_RADIAL) {
- layout_radial = layout;
- }
- UI_block_layout_set_current(block, layout);
- }
- }
- else if (layout->root->type != UI_LAYOUT_MENU) {
- UI_block_layout_set_current(block, ui_item_local_sublayout(layout, layout, 1));
- }
- else {
- UI_block_layout_set_current(block, layout);
- }
-
- for (item = item_array; item->identifier; item++) {
- const bool is_first = item == item_array;
-
- if (!item->identifier[0]) {
- const EnumPropertyItem *next_item = item + 1;
-
- /* Separate items, potentially with a label. */
- if (next_item->identifier) {
- /* Item without identifier but with name:
- * Add group label for the following items. */
- if (item->name) {
- if (!is_first) {
- uiItemS(block->curlayout);
- }
- uiItemL(block->curlayout, item->name, item->icon);
- }
- else if (radial && layout_radial) {
- uiItemS(layout_radial);
- }
- else {
- uiItemS(block->curlayout);
- }
- }
- continue;
- }
-
- name = (!uiname || uiname[0]) ? item->name : "";
- icon = item->icon;
- value = item->value;
- itemw = ui_text_icon_width(block->curlayout, icon_only ? "" : name, icon, 0);
-
- if (icon && name[0] && !icon_only) {
- but = uiDefIconTextButR_prop(block, but_type, 0, icon, name, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL);
- }
- else if (icon) {
- but = uiDefIconButR_prop(block, but_type, 0, icon, 0, 0, (is_first) ? itemw : ceilf(itemw - U.pixelsize), h, ptr, prop, -1, 0, value, -1, -1, NULL);
- }
- else {
- but = uiDefButR_prop(block, but_type, 0, name, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL);
- }
-
- if (RNA_property_flag(prop) & PROP_ENUM_FLAG) {
- /* If this is set, assert since we're clobbering someone elses callback. */
- BLI_assert(but->func == NULL);
- UI_but_func_set(but, ui_item_enum_expand_handle, but, POINTER_FROM_INT(value));
- }
-
- if (uiLayoutGetLocalDir(layout) != UI_LAYOUT_HORIZONTAL) {
- but->drawflag |= UI_BUT_TEXT_LEFT;
- }
-
- /* Allow quick, inaccurate swipe motions to switch tabs
- * (no need to keep cursor over them). */
- if (but_type == UI_BTYPE_TAB) {
- but->flag |= UI_BUT_DRAG_LOCK;
- }
- }
- UI_block_layout_set_current(block, layout);
-
- if (free) {
- MEM_freeN((void *)item_array);
- }
-}
-static void ui_item_enum_expand(
- uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop,
- const char *uiname, int h, bool icon_only)
-{
- ui_item_enum_expand_exec(layout, block, ptr, prop, uiname, h, UI_BTYPE_ROW, icon_only);
-}
-static void ui_item_enum_expand_tabs(
- uiLayout *layout, bContext *C, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop,
- const char *uiname, int h, bool icon_only)
-{
- uiBut *last = block->buttons.last;
-
- ui_item_enum_expand_exec(layout, block, ptr, prop, uiname, h, UI_BTYPE_TAB, icon_only);
- BLI_assert(last != block->buttons.last);
- for (uiBut *tab = last ? last->next : block->buttons.first; tab; tab = tab->next) {
- UI_but_drawflag_enable(tab, ui_but_align_opposite_to_area_align_get(CTX_wm_region(C)));
- }
+ wmWindow *win = CTX_wm_window(C);
+
+ if (!win->eventstate->shift) {
+ uiBut *but = (uiBut *)arg1;
+ int enum_value = POINTER_AS_INT(arg2);
+
+ int current_value = RNA_property_enum_get(&but->rnapoin, but->rnaprop);
+ if (!(current_value & enum_value)) {
+ current_value = enum_value;
+ }
+ else {
+ current_value &= enum_value;
+ }
+ RNA_property_enum_set(&but->rnapoin, but->rnaprop, current_value);
+ }
+}
+static void ui_item_enum_expand_exec(uiLayout *layout,
+ uiBlock *block,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ const char *uiname,
+ int h,
+ int but_type,
+ bool icon_only)
+{
+ /* XXX The way this function currently handles uiname parameter is insane and inconsistent with general UI API:
+ * * uiname is the *enum property* label.
+ * * when it is NULL or empty, we do not draw *enum items* labels, this doubles the icon_only parameter.
+ * * we *never* draw (i.e. really use) the enum label uiname, it is just used as a mere flag!
+ * Unfortunately, fixing this implies an API "soft break", so better to defer it for later... :/
+ * --mont29
+ */
+
+ uiBut *but;
+ uiLayout *layout_radial = NULL;
+ const EnumPropertyItem *item, *item_array;
+ const char *name;
+ int itemw, icon, value;
+ bool free;
+ bool radial = (layout->root->type == UI_LAYOUT_PIEMENU);
+
+ BLI_assert(RNA_property_type(prop) == PROP_ENUM);
+
+ if (radial) {
+ RNA_property_enum_items_gettexted_all(block->evil_C, ptr, prop, &item_array, NULL, &free);
+ }
+ else {
+ RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item_array, NULL, &free);
+ }
+
+ /* we dont want nested rows, cols in menus */
+ if (radial) {
+ if (layout->root->layout == layout) {
+ layout_radial = uiLayoutRadial(layout);
+ UI_block_layout_set_current(block, layout_radial);
+ }
+ else {
+ if (layout->item.type == ITEM_LAYOUT_RADIAL) {
+ layout_radial = layout;
+ }
+ UI_block_layout_set_current(block, layout);
+ }
+ }
+ else if (layout->root->type != UI_LAYOUT_MENU) {
+ UI_block_layout_set_current(block, ui_item_local_sublayout(layout, layout, 1));
+ }
+ else {
+ UI_block_layout_set_current(block, layout);
+ }
+
+ for (item = item_array; item->identifier; item++) {
+ const bool is_first = item == item_array;
+
+ if (!item->identifier[0]) {
+ const EnumPropertyItem *next_item = item + 1;
+
+ /* Separate items, potentially with a label. */
+ if (next_item->identifier) {
+ /* Item without identifier but with name:
+ * Add group label for the following items. */
+ if (item->name) {
+ if (!is_first) {
+ uiItemS(block->curlayout);
+ }
+ uiItemL(block->curlayout, item->name, item->icon);
+ }
+ else if (radial && layout_radial) {
+ uiItemS(layout_radial);
+ }
+ else {
+ uiItemS(block->curlayout);
+ }
+ }
+ continue;
+ }
+
+ name = (!uiname || uiname[0]) ? item->name : "";
+ icon = item->icon;
+ value = item->value;
+ itemw = ui_text_icon_width(block->curlayout, icon_only ? "" : name, icon, 0);
+
+ if (icon && name[0] && !icon_only) {
+ but = uiDefIconTextButR_prop(
+ block, but_type, 0, icon, name, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL);
+ }
+ else if (icon) {
+ but = uiDefIconButR_prop(block,
+ but_type,
+ 0,
+ icon,
+ 0,
+ 0,
+ (is_first) ? itemw : ceilf(itemw - U.pixelsize),
+ h,
+ ptr,
+ prop,
+ -1,
+ 0,
+ value,
+ -1,
+ -1,
+ NULL);
+ }
+ else {
+ but = uiDefButR_prop(
+ block, but_type, 0, name, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL);
+ }
+
+ if (RNA_property_flag(prop) & PROP_ENUM_FLAG) {
+ /* If this is set, assert since we're clobbering someone elses callback. */
+ BLI_assert(but->func == NULL);
+ UI_but_func_set(but, ui_item_enum_expand_handle, but, POINTER_FROM_INT(value));
+ }
+
+ if (uiLayoutGetLocalDir(layout) != UI_LAYOUT_HORIZONTAL) {
+ but->drawflag |= UI_BUT_TEXT_LEFT;
+ }
+
+ /* Allow quick, inaccurate swipe motions to switch tabs
+ * (no need to keep cursor over them). */
+ if (but_type == UI_BTYPE_TAB) {
+ but->flag |= UI_BUT_DRAG_LOCK;
+ }
+ }
+ UI_block_layout_set_current(block, layout);
+
+ if (free) {
+ MEM_freeN((void *)item_array);
+ }
+}
+static void ui_item_enum_expand(uiLayout *layout,
+ uiBlock *block,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ const char *uiname,
+ int h,
+ bool icon_only)
+{
+ ui_item_enum_expand_exec(layout, block, ptr, prop, uiname, h, UI_BTYPE_ROW, icon_only);
+}
+static void ui_item_enum_expand_tabs(uiLayout *layout,
+ bContext *C,
+ uiBlock *block,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ const char *uiname,
+ int h,
+ bool icon_only)
+{
+ uiBut *last = block->buttons.last;
+
+ ui_item_enum_expand_exec(layout, block, ptr, prop, uiname, h, UI_BTYPE_TAB, icon_only);
+ BLI_assert(last != block->buttons.last);
+ for (uiBut *tab = last ? last->next : block->buttons.first; tab; tab = tab->next) {
+ UI_but_drawflag_enable(tab, ui_but_align_opposite_to_area_align_get(CTX_wm_region(C)));
+ }
}
/* callback for keymap item change button */
static void ui_keymap_but_cb(bContext *UNUSED(C), void *but_v, void *UNUSED(key_v))
{
- uiBut *but = but_v;
+ uiBut *but = but_v;
- RNA_boolean_set(&but->rnapoin, "shift", (but->modifier_key & KM_SHIFT) != 0);
- RNA_boolean_set(&but->rnapoin, "ctrl", (but->modifier_key & KM_CTRL) != 0);
- RNA_boolean_set(&but->rnapoin, "alt", (but->modifier_key & KM_ALT) != 0);
- RNA_boolean_set(&but->rnapoin, "oskey", (but->modifier_key & KM_OSKEY) != 0);
+ RNA_boolean_set(&but->rnapoin, "shift", (but->modifier_key & KM_SHIFT) != 0);
+ RNA_boolean_set(&but->rnapoin, "ctrl", (but->modifier_key & KM_CTRL) != 0);
+ RNA_boolean_set(&but->rnapoin, "alt", (but->modifier_key & KM_ALT) != 0);
+ RNA_boolean_set(&but->rnapoin, "oskey", (but->modifier_key & KM_OSKEY) != 0);
}
/**
@@ -831,130 +901,175 @@ static void ui_keymap_but_cb(bContext *UNUSED(C), void *but_v, void *UNUSED(key_
* \param w_hint: For varying width layout, this becomes the label width.
* Otherwise it's used to fit both items into it.
*/
-static uiBut *ui_item_with_label(
- uiLayout *layout, uiBlock *block, const char *name, int icon,
- PointerRNA *ptr, PropertyRNA *prop, int index,
- int x, int y, int w_hint, int h, int flag)
-{
- uiLayout *sub;
- uiBut *but = NULL;
- PropertyType type;
- PropertySubType subtype;
- int prop_but_width = w_hint;
- const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
-
- /* 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);
-
- if (name[0]) {
- int w_label;
-
- if (use_prop_sep) {
- w_label = (int)((w_hint * 2) * UI_ITEM_PROP_SEP_DIVIDE);
- }
- else {
- if (ui_layout_variable_size(layout)) {
- /* w_hint is width for label in this case.
- * Use a default width for property button(s) */
- prop_but_width = UI_UNIT_X * 5;
- w_label = w_hint;
- }
- 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;
- }
- }
-
- type = RNA_property_type(prop);
- subtype = RNA_property_subtype(prop);
-
- if (subtype == PROP_FILEPATH || subtype == PROP_DIRPATH) {
- UI_block_layout_set_current(block, uiLayoutRow(sub, true));
- but = uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, prop_but_width - UI_UNIT_X, h);
-
- /* BUTTONS_OT_file_browse calls UI_context_active_but_prop_get_filebrowser */
- uiDefIconButO(
- block, UI_BTYPE_BUT, subtype == PROP_DIRPATH ? "BUTTONS_OT_directory_browse" : "BUTTONS_OT_file_browse",
- WM_OP_INVOKE_DEFAULT, ICON_FILEBROWSER, x, y, UI_UNIT_X, h, NULL);
- }
- else if (flag & UI_ITEM_R_EVENT) {
- but = uiDefButR_prop(block, UI_BTYPE_KEY_EVENT, 0, name, x, y, prop_but_width, h, ptr, prop, index, 0, 0, -1, -1, NULL);
- }
- else if (flag & UI_ITEM_R_FULL_EVENT) {
- if (RNA_struct_is_a(ptr->type, &RNA_KeyMapItem)) {
- char buf[128];
-
- WM_keymap_item_to_string(ptr->data, false, buf, sizeof(buf));
-
- but = uiDefButR_prop(block, UI_BTYPE_HOTKEY_EVENT, 0, buf, x, y, prop_but_width, h, ptr, prop, 0, 0, 0, -1, -1, NULL);
- UI_but_func_set(but, ui_keymap_but_cb, but, NULL);
- if (flag & UI_ITEM_R_IMMEDIATE) {
- UI_but_flag_enable(but, UI_BUT_IMMEDIATE);
- }
- }
- }
- else {
- const char *str = (type == PROP_ENUM && !(flag & UI_ITEM_R_ICON_ONLY)) ? NULL : "";
- but = uiDefAutoButR(
- block, ptr, prop, index, str, icon,
- x, y, prop_but_width, h);
- }
+static uiBut *ui_item_with_label(uiLayout *layout,
+ uiBlock *block,
+ const char *name,
+ int icon,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ int index,
+ int x,
+ int y,
+ int w_hint,
+ int h,
+ int flag)
+{
+ uiLayout *sub;
+ uiBut *but = NULL;
+ PropertyType type;
+ PropertySubType subtype;
+ int prop_but_width = w_hint;
+ const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
+
+ /* 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);
+
+ if (name[0]) {
+ int w_label;
+
+ if (use_prop_sep) {
+ w_label = (int)((w_hint * 2) * UI_ITEM_PROP_SEP_DIVIDE);
+ }
+ else {
+ if (ui_layout_variable_size(layout)) {
+ /* w_hint is width for label in this case.
+ * Use a default width for property button(s) */
+ prop_but_width = UI_UNIT_X * 5;
+ w_label = w_hint;
+ }
+ 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;
+ }
+ }
+
+ type = RNA_property_type(prop);
+ subtype = RNA_property_subtype(prop);
+
+ if (subtype == PROP_FILEPATH || subtype == PROP_DIRPATH) {
+ UI_block_layout_set_current(block, uiLayoutRow(sub, true));
+ but = uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, prop_but_width - UI_UNIT_X, h);
+
+ /* BUTTONS_OT_file_browse calls UI_context_active_but_prop_get_filebrowser */
+ uiDefIconButO(block,
+ UI_BTYPE_BUT,
+ subtype == PROP_DIRPATH ? "BUTTONS_OT_directory_browse" :
+ "BUTTONS_OT_file_browse",
+ WM_OP_INVOKE_DEFAULT,
+ ICON_FILEBROWSER,
+ x,
+ y,
+ UI_UNIT_X,
+ h,
+ NULL);
+ }
+ else if (flag & UI_ITEM_R_EVENT) {
+ but = uiDefButR_prop(block,
+ UI_BTYPE_KEY_EVENT,
+ 0,
+ name,
+ x,
+ y,
+ prop_but_width,
+ h,
+ ptr,
+ prop,
+ index,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ }
+ else if (flag & UI_ITEM_R_FULL_EVENT) {
+ if (RNA_struct_is_a(ptr->type, &RNA_KeyMapItem)) {
+ char buf[128];
+
+ WM_keymap_item_to_string(ptr->data, false, buf, sizeof(buf));
+
+ but = uiDefButR_prop(block,
+ UI_BTYPE_HOTKEY_EVENT,
+ 0,
+ buf,
+ x,
+ y,
+ prop_but_width,
+ h,
+ ptr,
+ prop,
+ 0,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ UI_but_func_set(but, ui_keymap_but_cb, but, NULL);
+ if (flag & UI_ITEM_R_IMMEDIATE) {
+ UI_but_flag_enable(but, UI_BUT_IMMEDIATE);
+ }
+ }
+ }
+ else {
+ const char *str = (type == PROP_ENUM && !(flag & UI_ITEM_R_ICON_ONLY)) ? NULL : "";
+ but = uiDefAutoButR(block, ptr, prop, index, str, icon, x, y, prop_but_width, h);
+ }
#ifdef UI_PROP_DECORATE
- /* Only for alignment. */
- 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);
- }
- }
-#endif /* UI_PROP_DECORATE */
-
- UI_block_layout_set_current(block, layout);
- return but;
-}
-
-void UI_context_active_but_prop_get_filebrowser(
- const bContext *C,
- PointerRNA *r_ptr, PropertyRNA **r_prop, bool *r_is_undo)
-{
- ARegion *ar = CTX_wm_region(C);
- uiBlock *block;
- uiBut *but, *prevbut = NULL;
-
- memset(r_ptr, 0, sizeof(*r_ptr));
- *r_prop = NULL;
- *r_is_undo = false;
-
- if (!ar) {
- return;
- }
-
- for (block = ar->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) {
- prevbut = but;
- }
- }
-
- /* find the button before the active one */
- if ((but->flag & UI_BUT_LAST_ACTIVE) && prevbut) {
- *r_ptr = prevbut->rnapoin;
- *r_prop = prevbut->rnaprop;
- *r_is_undo = (prevbut->flag & UI_BUT_UNDO) != 0;
- return;
- }
- }
- }
+ /* Only for alignment. */
+ 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);
+ }
+ }
+#endif /* UI_PROP_DECORATE */
+
+ UI_block_layout_set_current(block, layout);
+ return but;
+}
+
+void UI_context_active_but_prop_get_filebrowser(const bContext *C,
+ PointerRNA *r_ptr,
+ PropertyRNA **r_prop,
+ bool *r_is_undo)
+{
+ ARegion *ar = CTX_wm_region(C);
+ uiBlock *block;
+ uiBut *but, *prevbut = NULL;
+
+ memset(r_ptr, 0, sizeof(*r_ptr));
+ *r_prop = NULL;
+ *r_is_undo = false;
+
+ if (!ar) {
+ return;
+ }
+
+ for (block = ar->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) {
+ prevbut = but;
+ }
+ }
+
+ /* find the button before the active one */
+ if ((but->flag & UI_BUT_LAST_ACTIVE) && prevbut) {
+ *r_ptr = prevbut->rnapoin;
+ *r_prop = prevbut->rnaprop;
+ *r_is_undo = (prevbut->flag & UI_BUT_UNDO) != 0;
+ return;
+ }
+ }
+ }
}
/********************* Button Items *************************/
@@ -964,31 +1079,31 @@ void UI_context_active_but_prop_get_filebrowser(
*/
static void ui_but_tip_from_enum_item(uiBut *but, const EnumPropertyItem *item)
{
- if (but->tip == NULL || but->tip[0] == '\0') {
- if (item->description && item->description[0]) {
- but->tip = item->description;
- }
- }
+ if (but->tip == NULL || but->tip[0] == '\0') {
+ if (item->description && item->description[0]) {
+ but->tip = item->description;
+ }
+ }
}
/* disabled item */
static void ui_item_disabled(uiLayout *layout, const char *name)
{
- uiBlock *block = layout->root->block;
- uiBut *but;
- int w;
+ uiBlock *block = layout->root->block;
+ uiBut *but;
+ int w;
- UI_block_layout_set_current(block, layout);
+ UI_block_layout_set_current(block, layout);
- if (!name) {
- name = "";
- }
+ if (!name) {
+ name = "";
+ }
- w = ui_text_icon_width(layout, name, 0, 0);
+ w = ui_text_icon_width(layout, name, 0, 0);
- but = uiDefBut(block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- but->flag |= UI_BUT_DISABLED;
- but->disabled_info = "";
+ but = uiDefBut(block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ but->flag |= UI_BUT_DISABLED;
+ but->disabled_info = "";
}
/**
@@ -996,231 +1111,259 @@ static void ui_item_disabled(uiLayout *layout, const char *name)
* \param r_opptr: Optional, initialize with operator properties when not NULL.
* Will always be written to even in the case of errors.
*/
-static uiBut *uiItemFullO_ptr_ex(
- uiLayout *layout, wmOperatorType *ot,
- const char *name, int icon, IDProperty *properties, int context, int flag,
- PointerRNA *r_opptr)
-{
- /* Take care to fill 'r_opptr' whatever happens. */
- uiBlock *block = layout->root->block;
- uiBut *but;
- int w;
-
- if (!name) {
- if (ot && ot->srna && (flag & UI_ITEM_R_ICON_ONLY) == 0) {
- name = RNA_struct_ui_name(ot->srna);
- }
- else {
- name = "";
- }
- }
-
- if (layout->root->type == UI_LAYOUT_MENU && !icon) {
- icon = ICON_BLANK1;
- }
-
- /* create button */
- UI_block_layout_set_current(block, layout);
-
- w = ui_text_icon_width(layout, name, icon, 0);
-
- int prev_emboss = layout->emboss;
- if (flag & UI_ITEM_R_NO_BG) {
- layout->emboss = UI_EMBOSS_NONE;
- }
-
- /* create the button */
- if (icon) {
- if (name[0]) {
- but = uiDefIconTextButO_ptr(block, UI_BTYPE_BUT, ot, context, icon, name, 0, 0, w, UI_UNIT_Y, NULL);
- }
- else {
- but = uiDefIconButO_ptr(block, UI_BTYPE_BUT, ot, context, icon, 0, 0, w, UI_UNIT_Y, NULL);
- }
- }
- else {
- but = uiDefButO_ptr(block, UI_BTYPE_BUT, ot, context, name, 0, 0, w, UI_UNIT_Y, NULL);
- }
-
- assert(but->optype != NULL);
-
- /* text alignment for toolbar buttons */
- if ((layout->root->type == UI_LAYOUT_TOOLBAR) && !icon) {
- but->drawflag |= UI_BUT_TEXT_LEFT;
- }
-
- if (flag & UI_ITEM_R_NO_BG) {
- layout->emboss = prev_emboss;
- }
-
- if (flag & UI_ITEM_O_DEPRESS) {
- but->flag |= UI_SELECT_DRAW;
- }
-
- if (layout->redalert) {
- UI_but_flag_enable(but, UI_BUT_REDALERT);
- }
-
- if (layout->active_default) {
- UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT);
- }
-
- /* assign properties */
- if (properties || r_opptr) {
- PointerRNA *opptr = UI_but_operator_ptr_get(but);
- if (properties) {
- opptr->data = properties;
- }
- else {
- IDPropertyTemplate val = {0};
- opptr->data = IDP_New(IDP_GROUP, &val, "wmOperatorProperties");
- }
- if (r_opptr) {
- *r_opptr = *opptr;
- }
- }
-
- return but;
+static uiBut *uiItemFullO_ptr_ex(uiLayout *layout,
+ wmOperatorType *ot,
+ const char *name,
+ int icon,
+ IDProperty *properties,
+ int context,
+ int flag,
+ PointerRNA *r_opptr)
+{
+ /* Take care to fill 'r_opptr' whatever happens. */
+ uiBlock *block = layout->root->block;
+ uiBut *but;
+ int w;
+
+ if (!name) {
+ if (ot && ot->srna && (flag & UI_ITEM_R_ICON_ONLY) == 0) {
+ name = RNA_struct_ui_name(ot->srna);
+ }
+ else {
+ name = "";
+ }
+ }
+
+ if (layout->root->type == UI_LAYOUT_MENU && !icon) {
+ icon = ICON_BLANK1;
+ }
+
+ /* create button */
+ UI_block_layout_set_current(block, layout);
+
+ w = ui_text_icon_width(layout, name, icon, 0);
+
+ int prev_emboss = layout->emboss;
+ if (flag & UI_ITEM_R_NO_BG) {
+ layout->emboss = UI_EMBOSS_NONE;
+ }
+
+ /* create the button */
+ if (icon) {
+ if (name[0]) {
+ but = uiDefIconTextButO_ptr(
+ block, UI_BTYPE_BUT, ot, context, icon, name, 0, 0, w, UI_UNIT_Y, NULL);
+ }
+ else {
+ but = uiDefIconButO_ptr(block, UI_BTYPE_BUT, ot, context, icon, 0, 0, w, UI_UNIT_Y, NULL);
+ }
+ }
+ else {
+ but = uiDefButO_ptr(block, UI_BTYPE_BUT, ot, context, name, 0, 0, w, UI_UNIT_Y, NULL);
+ }
+
+ assert(but->optype != NULL);
+
+ /* text alignment for toolbar buttons */
+ if ((layout->root->type == UI_LAYOUT_TOOLBAR) && !icon) {
+ but->drawflag |= UI_BUT_TEXT_LEFT;
+ }
+
+ if (flag & UI_ITEM_R_NO_BG) {
+ layout->emboss = prev_emboss;
+ }
+
+ if (flag & UI_ITEM_O_DEPRESS) {
+ but->flag |= UI_SELECT_DRAW;
+ }
+
+ if (layout->redalert) {
+ UI_but_flag_enable(but, UI_BUT_REDALERT);
+ }
+
+ if (layout->active_default) {
+ UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT);
+ }
+
+ /* assign properties */
+ if (properties || r_opptr) {
+ PointerRNA *opptr = UI_but_operator_ptr_get(but);
+ if (properties) {
+ opptr->data = properties;
+ }
+ else {
+ IDPropertyTemplate val = {0};
+ opptr->data = IDP_New(IDP_GROUP, &val, "wmOperatorProperties");
+ }
+ if (r_opptr) {
+ *r_opptr = *opptr;
+ }
+ }
+
+ return but;
}
static void ui_item_menu_hold(struct bContext *C, ARegion *butregion, uiBut *but)
{
- uiPopupMenu *pup = UI_popup_menu_begin(C, "", ICON_NONE);
- uiLayout *layout = UI_popup_menu_layout(pup);
- uiBlock *block = layout->root->block;
- UI_popup_menu_but_set(pup, butregion, but);
-
- block->flag |= UI_BLOCK_POPUP_HOLD;
- block->flag |= UI_BLOCK_IS_FLIP;
-
- char direction = UI_DIR_DOWN;
- if (!but->drawstr[0]) {
- if (butregion->alignment == RGN_ALIGN_LEFT) {
- direction = UI_DIR_RIGHT;
- }
- else if (butregion->alignment == RGN_ALIGN_RIGHT) {
- direction = UI_DIR_LEFT;
- }
- else if (butregion->alignment == RGN_ALIGN_BOTTOM) {
- direction = UI_DIR_UP;
- }
- else {
- direction = UI_DIR_DOWN;
- }
- }
- UI_block_direction_set(block, direction);
-
- const char *menu_id = but->hold_argN;
- MenuType *mt = WM_menutype_find(menu_id, true);
- if (mt) {
- uiLayoutSetContextFromBut(layout, but);
- UI_menutype_draw(C, mt, layout);
- }
- else {
- uiItemL(layout, "Menu Missing:", ICON_NONE);
- uiItemL(layout, menu_id, ICON_NONE);
- }
- UI_popup_menu_end(C, pup);
-}
-
-void uiItemFullO_ptr(
- uiLayout *layout, wmOperatorType *ot,
- const char *name, int icon, IDProperty *properties, int context, int flag,
- PointerRNA *r_opptr)
-{
- uiItemFullO_ptr_ex(layout, ot, name, icon, properties, context, flag, r_opptr);
-}
-
-void uiItemFullOMenuHold_ptr(
- uiLayout *layout, wmOperatorType *ot,
- const char *name, int icon, IDProperty *properties, int context, int flag,
- const char *menu_id,
- PointerRNA *r_opptr)
-{
- uiBut *but = uiItemFullO_ptr_ex(layout, ot, name, icon, properties, context, flag, r_opptr);
- UI_but_func_hold_set(but, ui_item_menu_hold, BLI_strdup(menu_id));
-}
-
-void uiItemFullO(
- uiLayout *layout, const char *opname,
- const char *name, int icon, IDProperty *properties, int context, int flag,
- PointerRNA *r_opptr)
-{
- wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
-
- UI_OPERATOR_ERROR_RET(
- ot, opname, {
- if (r_opptr) {
- *r_opptr = PointerRNA_NULL;
- }
- return;
- });
+ uiPopupMenu *pup = UI_popup_menu_begin(C, "", ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+ uiBlock *block = layout->root->block;
+ UI_popup_menu_but_set(pup, butregion, but);
+
+ block->flag |= UI_BLOCK_POPUP_HOLD;
+ block->flag |= UI_BLOCK_IS_FLIP;
+
+ char direction = UI_DIR_DOWN;
+ if (!but->drawstr[0]) {
+ if (butregion->alignment == RGN_ALIGN_LEFT) {
+ direction = UI_DIR_RIGHT;
+ }
+ else if (butregion->alignment == RGN_ALIGN_RIGHT) {
+ direction = UI_DIR_LEFT;
+ }
+ else if (butregion->alignment == RGN_ALIGN_BOTTOM) {
+ direction = UI_DIR_UP;
+ }
+ else {
+ direction = UI_DIR_DOWN;
+ }
+ }
+ UI_block_direction_set(block, direction);
+
+ const char *menu_id = but->hold_argN;
+ MenuType *mt = WM_menutype_find(menu_id, true);
+ if (mt) {
+ uiLayoutSetContextFromBut(layout, but);
+ UI_menutype_draw(C, mt, layout);
+ }
+ else {
+ uiItemL(layout, "Menu Missing:", ICON_NONE);
+ uiItemL(layout, menu_id, ICON_NONE);
+ }
+ UI_popup_menu_end(C, pup);
+}
+
+void uiItemFullO_ptr(uiLayout *layout,
+ wmOperatorType *ot,
+ const char *name,
+ int icon,
+ IDProperty *properties,
+ int context,
+ int flag,
+ PointerRNA *r_opptr)
+{
+ uiItemFullO_ptr_ex(layout, ot, name, icon, properties, context, flag, r_opptr);
+}
+
+void uiItemFullOMenuHold_ptr(uiLayout *layout,
+ wmOperatorType *ot,
+ const char *name,
+ int icon,
+ IDProperty *properties,
+ int context,
+ int flag,
+ const char *menu_id,
+ PointerRNA *r_opptr)
+{
+ uiBut *but = uiItemFullO_ptr_ex(layout, ot, name, icon, properties, context, flag, r_opptr);
+ UI_but_func_hold_set(but, ui_item_menu_hold, BLI_strdup(menu_id));
+}
+
+void uiItemFullO(uiLayout *layout,
+ const char *opname,
+ const char *name,
+ int icon,
+ IDProperty *properties,
+ int context,
+ int flag,
+ PointerRNA *r_opptr)
+{
+ wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
+
+ UI_OPERATOR_ERROR_RET(ot, opname, {
+ if (r_opptr) {
+ *r_opptr = PointerRNA_NULL;
+ }
+ return;
+ });
+
+ uiItemFullO_ptr(layout, ot, name, icon, properties, context, flag, r_opptr);
+}
+
+static const char *ui_menu_enumpropname(uiLayout *layout,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ int retval)
+{
+ const EnumPropertyItem *item;
+ bool free;
+ const char *name;
+
+ RNA_property_enum_items(layout->root->block->evil_C, ptr, prop, &item, NULL, &free);
+ if (RNA_enum_name(item, retval, &name)) {
+ name = CTX_IFACE_(RNA_property_translation_context(prop), name);
+ }
+ else {
+ name = "";
+ }
+
+ if (free) {
+ MEM_freeN((void *)item);
+ }
+
+ return name;
+}
+
+void uiItemEnumO_ptr(uiLayout *layout,
+ wmOperatorType *ot,
+ const char *name,
+ int icon,
+ const char *propname,
+ int value)
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ WM_operator_properties_create_ptr(&ptr, ot);
+
+ if ((prop = RNA_struct_find_property(&ptr, propname))) {
+ /* pass */
+ }
+ else {
+ RNA_warning("%s.%s not found", RNA_struct_identifier(ptr.type), propname);
+ return;
+ }
+
+ RNA_property_enum_set(&ptr, prop, value);
+
+ if (!name) {
+ name = ui_menu_enumpropname(layout, &ptr, prop, value);
+ }
- uiItemFullO_ptr(layout, ot, name, icon, properties, context, flag, r_opptr);
+ uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
}
-
-static const char *ui_menu_enumpropname(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int retval)
+void uiItemEnumO(uiLayout *layout,
+ const char *opname,
+ const char *name,
+ int icon,
+ const char *propname,
+ int value)
{
- const EnumPropertyItem *item;
- bool free;
- const char *name;
-
- RNA_property_enum_items(layout->root->block->evil_C, ptr, prop, &item, NULL, &free);
- if (RNA_enum_name(item, retval, &name)) {
- name = CTX_IFACE_(RNA_property_translation_context(prop), name);
- }
- else {
- name = "";
- }
-
- if (free) {
- MEM_freeN((void *)item);
- }
-
- return name;
-}
-
-void uiItemEnumO_ptr(uiLayout *layout, wmOperatorType *ot, const char *name, int icon, const char *propname, int value)
-{
- PointerRNA ptr;
- PropertyRNA *prop;
-
- WM_operator_properties_create_ptr(&ptr, ot);
-
- if ((prop = RNA_struct_find_property(&ptr, propname))) {
- /* pass */
- }
- else {
- RNA_warning("%s.%s not found", RNA_struct_identifier(ptr.type), propname);
- return;
- }
-
- RNA_property_enum_set(&ptr, prop, value);
-
- if (!name) {
- name = ui_menu_enumpropname(layout, &ptr, prop, value);
- }
-
- uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
-}
-void uiItemEnumO(uiLayout *layout, const char *opname, const char *name, int icon, const char *propname, int value)
-{
- wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
-
- if (ot) {
- uiItemEnumO_ptr(layout, ot, name, icon, propname, value);
- }
- else {
- ui_item_disabled(layout, opname);
- RNA_warning("unknown operator '%s'", opname);
- }
+ wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
+ if (ot) {
+ uiItemEnumO_ptr(layout, ot, name, icon, propname, value);
+ }
+ else {
+ ui_item_disabled(layout, opname);
+ RNA_warning("unknown operator '%s'", opname);
+ }
}
BLI_INLINE bool ui_layout_is_radial(const uiLayout *layout)
{
- return (layout->item.type == ITEM_LAYOUT_RADIAL) ||
- ((layout->item.type == ITEM_LAYOUT_ROOT) && (layout->root->type == UI_LAYOUT_PIEMENU));
+ return (layout->item.type == ITEM_LAYOUT_RADIAL) ||
+ ((layout->item.type == ITEM_LAYOUT_ROOT) && (layout->root->type == UI_LAYOUT_PIEMENU));
}
/**
@@ -1228,1454 +1371,1657 @@ BLI_INLINE bool ui_layout_is_radial(const uiLayout *layout)
*
* A version of #uiItemsFullEnumO that takes pre-calculated item array.
*/
-void uiItemsFullEnumO_items(
- uiLayout *layout, wmOperatorType *ot, PointerRNA ptr, PropertyRNA *prop, IDProperty *properties,
- int context, int flag,
- const EnumPropertyItem *item_array, int totitem)
-{
- const char *propname = RNA_property_identifier(prop);
- if (RNA_property_type(prop) != PROP_ENUM) {
- RNA_warning("%s.%s, not an enum type", RNA_struct_identifier(ptr.type), propname);
- return;
- }
-
- uiLayout *target, *split = NULL;
- const EnumPropertyItem *item;
- uiBlock *block = layout->root->block;
- const bool radial = ui_layout_is_radial(layout);
-
- if (radial) {
- target = uiLayoutRadial(layout);
- }
- else {
- split = uiLayoutSplit(layout, 0.0f, false);
- target = uiLayoutColumn(split, layout->align);
- }
-
-
- int i;
- bool last_iter = false;
-
- for (i = 1, item = item_array; item->identifier && !last_iter; i++, item++) {
- /* handle oversized pies */
- if (radial && (totitem > PIE_MAX_ITEMS) && (i >= PIE_MAX_ITEMS)) {
- if (item->name) { /* only visible items */
- const EnumPropertyItem *tmp;
-
- /* Check if there are more visible items for the next level. If not, we don't
- * add a new level and add the remaining item instead of the 'more' button. */
- for (tmp = item + 1; tmp->identifier; tmp++) {
- if (tmp->name) {
- break;
- }
- }
-
- if (tmp->identifier) { /* only true if loop above found item and did early-exit */
- ui_pie_menu_level_create(block, ot, propname, properties, item_array, totitem, context, flag);
- /* break since rest of items is handled in new pie level */
- break;
- }
- else {
- last_iter = true;
- }
- }
- else {
- continue;
- }
- }
-
- if (item->identifier[0]) {
- PointerRNA tptr;
-
- WM_operator_properties_create_ptr(&tptr, ot);
- if (properties) {
- if (tptr.data) {
- IDP_FreeProperty(tptr.data);
- MEM_freeN(tptr.data);
- }
- tptr.data = IDP_CopyProperty(properties);
- }
- RNA_property_enum_set(&tptr, prop, item->value);
-
- uiItemFullO_ptr(target, ot, item->name, item->icon, tptr.data, context, flag, NULL);
-
- ui_but_tip_from_enum_item(block->buttons.last, item);
- }
- else {
- if (item->name) {
- uiBut *but;
-
- if (item != item_array && !radial) {
- target = uiLayoutColumn(split, layout->align);
-
- /* inconsistent, but menus with labels do not look good flipped */
- block->flag |= UI_BLOCK_NO_FLIP;
- }
-
- if (item->icon || radial) {
- uiItemL(target, item->name, item->icon);
-
- but = block->buttons.last;
- }
- else {
- /* Do not use uiItemL here, as our root layout is a menu one,
- * it will add a fake blank icon! */
- but = uiDefBut(
- block, UI_BTYPE_LABEL, 0, item->name, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL,
- 0.0, 0.0, 0, 0, "");
- }
- ui_but_tip_from_enum_item(but, item);
- }
- else {
- if (radial) {
- /* invisible dummy button to ensure all items are
- * always at the same position */
- uiItemS(target);
- }
- else {
- /* XXX bug here, columns draw bottom item badly */
- uiItemS(target);
- }
- }
- }
- }
-}
-
-void uiItemsFullEnumO(
- uiLayout *layout, const char *opname, const char *propname, IDProperty *properties,
- int context, int flag)
-{
- wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
-
- PointerRNA ptr;
- PropertyRNA *prop;
- uiBlock *block = layout->root->block;
-
- if (!ot || !ot->srna) {
- ui_item_disabled(layout, opname);
- RNA_warning("%s '%s'", ot ? "unknown operator" : "operator missing srna", opname);
- return;
- }
-
- WM_operator_properties_create_ptr(&ptr, ot);
- /* so the context is passed to itemf functions (some need it) */
- WM_operator_properties_sanitize(&ptr, false);
- prop = RNA_struct_find_property(&ptr, propname);
-
- /* don't let bad properties slip through */
- BLI_assert((prop == NULL) || (RNA_property_type(prop) == PROP_ENUM));
-
- if (prop && RNA_property_type(prop) == PROP_ENUM) {
- const EnumPropertyItem *item_array = NULL;
- int totitem;
- bool free;
-
- if (ui_layout_is_radial(layout)) {
- /* XXX: While "_all()" guarantees spatial stability, it's bad when an enum has > 8 items total,
- * but only a small subset will ever be shown at once (e.g. Mode Switch menu, after the
- * introduction of GP editing modes)
- */
+void uiItemsFullEnumO_items(uiLayout *layout,
+ wmOperatorType *ot,
+ PointerRNA ptr,
+ PropertyRNA *prop,
+ IDProperty *properties,
+ int context,
+ int flag,
+ const EnumPropertyItem *item_array,
+ int totitem)
+{
+ const char *propname = RNA_property_identifier(prop);
+ if (RNA_property_type(prop) != PROP_ENUM) {
+ RNA_warning("%s.%s, not an enum type", RNA_struct_identifier(ptr.type), propname);
+ return;
+ }
+
+ uiLayout *target, *split = NULL;
+ const EnumPropertyItem *item;
+ uiBlock *block = layout->root->block;
+ const bool radial = ui_layout_is_radial(layout);
+
+ if (radial) {
+ target = uiLayoutRadial(layout);
+ }
+ else {
+ split = uiLayoutSplit(layout, 0.0f, false);
+ target = uiLayoutColumn(split, layout->align);
+ }
+
+ int i;
+ bool last_iter = false;
+
+ for (i = 1, item = item_array; item->identifier && !last_iter; i++, item++) {
+ /* handle oversized pies */
+ if (radial && (totitem > PIE_MAX_ITEMS) && (i >= PIE_MAX_ITEMS)) {
+ if (item->name) { /* only visible items */
+ const EnumPropertyItem *tmp;
+
+ /* Check if there are more visible items for the next level. If not, we don't
+ * add a new level and add the remaining item instead of the 'more' button. */
+ for (tmp = item + 1; tmp->identifier; tmp++) {
+ if (tmp->name) {
+ break;
+ }
+ }
+
+ if (tmp->identifier) { /* only true if loop above found item and did early-exit */
+ ui_pie_menu_level_create(
+ block, ot, propname, properties, item_array, totitem, context, flag);
+ /* break since rest of items is handled in new pie level */
+ break;
+ }
+ else {
+ last_iter = true;
+ }
+ }
+ else {
+ continue;
+ }
+ }
+
+ if (item->identifier[0]) {
+ PointerRNA tptr;
+
+ WM_operator_properties_create_ptr(&tptr, ot);
+ if (properties) {
+ if (tptr.data) {
+ IDP_FreeProperty(tptr.data);
+ MEM_freeN(tptr.data);
+ }
+ tptr.data = IDP_CopyProperty(properties);
+ }
+ RNA_property_enum_set(&tptr, prop, item->value);
+
+ uiItemFullO_ptr(target, ot, item->name, item->icon, tptr.data, context, flag, NULL);
+
+ ui_but_tip_from_enum_item(block->buttons.last, item);
+ }
+ else {
+ if (item->name) {
+ uiBut *but;
+
+ if (item != item_array && !radial) {
+ target = uiLayoutColumn(split, layout->align);
+
+ /* inconsistent, but menus with labels do not look good flipped */
+ block->flag |= UI_BLOCK_NO_FLIP;
+ }
+
+ if (item->icon || radial) {
+ uiItemL(target, item->name, item->icon);
+
+ but = block->buttons.last;
+ }
+ else {
+ /* Do not use uiItemL here, as our root layout is a menu one,
+ * it will add a fake blank icon! */
+ but = uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ item->name,
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ }
+ ui_but_tip_from_enum_item(but, item);
+ }
+ else {
+ if (radial) {
+ /* invisible dummy button to ensure all items are
+ * always at the same position */
+ uiItemS(target);
+ }
+ else {
+ /* XXX bug here, columns draw bottom item badly */
+ uiItemS(target);
+ }
+ }
+ }
+ }
+}
+
+void uiItemsFullEnumO(uiLayout *layout,
+ const char *opname,
+ const char *propname,
+ IDProperty *properties,
+ int context,
+ int flag)
+{
+ wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
+
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ uiBlock *block = layout->root->block;
+
+ if (!ot || !ot->srna) {
+ ui_item_disabled(layout, opname);
+ RNA_warning("%s '%s'", ot ? "unknown operator" : "operator missing srna", opname);
+ return;
+ }
+
+ WM_operator_properties_create_ptr(&ptr, ot);
+ /* so the context is passed to itemf functions (some need it) */
+ WM_operator_properties_sanitize(&ptr, false);
+ prop = RNA_struct_find_property(&ptr, propname);
+
+ /* don't let bad properties slip through */
+ BLI_assert((prop == NULL) || (RNA_property_type(prop) == PROP_ENUM));
+
+ if (prop && RNA_property_type(prop) == PROP_ENUM) {
+ const EnumPropertyItem *item_array = NULL;
+ int totitem;
+ bool free;
+
+ if (ui_layout_is_radial(layout)) {
+ /* XXX: While "_all()" guarantees spatial stability, it's bad when an enum has > 8 items total,
+ * but only a small subset will ever be shown at once (e.g. Mode Switch menu, after the
+ * introduction of GP editing modes)
+ */
#if 0
- RNA_property_enum_items_gettexted_all(block->evil_C, &ptr, prop, &item_array, &totitem, &free);
+ RNA_property_enum_items_gettexted_all(block->evil_C, &ptr, prop, &item_array, &totitem, &free);
#else
- RNA_property_enum_items_gettexted(block->evil_C, &ptr, prop, &item_array, &totitem, &free);
+ RNA_property_enum_items_gettexted(block->evil_C, &ptr, prop, &item_array, &totitem, &free);
#endif
- }
- else {
- RNA_property_enum_items_gettexted(block->evil_C, &ptr, prop, &item_array, &totitem, &free);
- }
-
- /* add items */
- uiItemsFullEnumO_items(
- layout, ot, ptr, prop, properties, context, flag,
- item_array, totitem);
-
- if (free) {
- MEM_freeN((void *)item_array);
- }
-
- /* intentionally don't touch UI_BLOCK_IS_FLIP here,
- * we don't know the context this is called in */
- }
- else if (prop && RNA_property_type(prop) != PROP_ENUM) {
- RNA_warning("%s.%s, not an enum type", RNA_struct_identifier(ptr.type), propname);
- return;
- }
- else {
- RNA_warning("%s.%s not found", RNA_struct_identifier(ptr.type), propname);
- return;
- }
+ }
+ else {
+ RNA_property_enum_items_gettexted(block->evil_C, &ptr, prop, &item_array, &totitem, &free);
+ }
+
+ /* add items */
+ uiItemsFullEnumO_items(layout, ot, ptr, prop, properties, context, flag, item_array, totitem);
+
+ if (free) {
+ MEM_freeN((void *)item_array);
+ }
+
+ /* intentionally don't touch UI_BLOCK_IS_FLIP here,
+ * we don't know the context this is called in */
+ }
+ else if (prop && RNA_property_type(prop) != PROP_ENUM) {
+ RNA_warning("%s.%s, not an enum type", RNA_struct_identifier(ptr.type), propname);
+ return;
+ }
+ else {
+ RNA_warning("%s.%s not found", RNA_struct_identifier(ptr.type), propname);
+ return;
+ }
}
void uiItemsEnumO(uiLayout *layout, const char *opname, const char *propname)
{
- uiItemsFullEnumO(layout, opname, propname, NULL, layout->root->opcontext, 0);
+ uiItemsFullEnumO(layout, opname, propname, NULL, layout->root->opcontext, 0);
}
/* for use in cases where we have */
-void uiItemEnumO_value(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, int value)
+void uiItemEnumO_value(uiLayout *layout,
+ const char *name,
+ int icon,
+ const char *opname,
+ const char *propname,
+ int value)
{
- wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
- PointerRNA ptr;
- PropertyRNA *prop;
+ wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
+ PointerRNA ptr;
+ PropertyRNA *prop;
- UI_OPERATOR_ERROR_RET(ot, opname, return);
+ UI_OPERATOR_ERROR_RET(ot, opname, return );
- WM_operator_properties_create_ptr(&ptr, ot);
+ WM_operator_properties_create_ptr(&ptr, ot);
- /* enum lookup */
- if ((prop = RNA_struct_find_property(&ptr, propname))) {
- /* pass */
- }
- else {
- RNA_warning("%s.%s not found", RNA_struct_identifier(ptr.type), propname);
- return;
- }
+ /* enum lookup */
+ if ((prop = RNA_struct_find_property(&ptr, propname))) {
+ /* pass */
+ }
+ else {
+ RNA_warning("%s.%s not found", RNA_struct_identifier(ptr.type), propname);
+ return;
+ }
- RNA_property_enum_set(&ptr, prop, value);
+ RNA_property_enum_set(&ptr, prop, value);
- /* same as uiItemEnumO */
- if (!name) {
- name = ui_menu_enumpropname(layout, &ptr, prop, value);
- }
+ /* same as uiItemEnumO */
+ if (!name) {
+ name = ui_menu_enumpropname(layout, &ptr, prop, value);
+ }
- uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
+ uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
}
-void uiItemEnumO_string(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, const char *value_str)
+void uiItemEnumO_string(uiLayout *layout,
+ const char *name,
+ int icon,
+ const char *opname,
+ const char *propname,
+ const char *value_str)
{
- wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
- PointerRNA ptr;
- PropertyRNA *prop;
+ wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
+ PointerRNA ptr;
+ PropertyRNA *prop;
- const EnumPropertyItem *item;
- int value;
- bool free;
+ const EnumPropertyItem *item;
+ int value;
+ bool free;
- UI_OPERATOR_ERROR_RET(ot, opname, return);
+ UI_OPERATOR_ERROR_RET(ot, opname, return );
- WM_operator_properties_create_ptr(&ptr, ot);
+ WM_operator_properties_create_ptr(&ptr, ot);
- /* enum lookup */
- if ((prop = RNA_struct_find_property(&ptr, propname))) {
- /* no need for translations here */
- RNA_property_enum_items(layout->root->block->evil_C, &ptr, prop, &item, NULL, &free);
- if (item == NULL || RNA_enum_value_from_id(item, value_str, &value) == 0) {
- if (free) {
- MEM_freeN((void *)item);
- }
- RNA_warning("%s.%s, enum %s not found", RNA_struct_identifier(ptr.type), propname, value_str);
- return;
- }
+ /* enum lookup */
+ if ((prop = RNA_struct_find_property(&ptr, propname))) {
+ /* no need for translations here */
+ RNA_property_enum_items(layout->root->block->evil_C, &ptr, prop, &item, NULL, &free);
+ if (item == NULL || RNA_enum_value_from_id(item, value_str, &value) == 0) {
+ if (free) {
+ MEM_freeN((void *)item);
+ }
+ RNA_warning(
+ "%s.%s, enum %s not found", RNA_struct_identifier(ptr.type), propname, value_str);
+ return;
+ }
- if (free) {
- MEM_freeN((void *)item);
- }
- }
- else {
- RNA_warning("%s.%s not found", RNA_struct_identifier(ptr.type), propname);
- return;
- }
+ if (free) {
+ MEM_freeN((void *)item);
+ }
+ }
+ else {
+ RNA_warning("%s.%s not found", RNA_struct_identifier(ptr.type), propname);
+ return;
+ }
- RNA_property_enum_set(&ptr, prop, value);
+ RNA_property_enum_set(&ptr, prop, value);
- /* same as uiItemEnumO */
- if (!name) {
- name = ui_menu_enumpropname(layout, &ptr, prop, value);
- }
+ /* same as uiItemEnumO */
+ if (!name) {
+ name = ui_menu_enumpropname(layout, &ptr, prop, value);
+ }
- uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
+ uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
}
-void uiItemBooleanO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, int value)
+void uiItemBooleanO(uiLayout *layout,
+ const char *name,
+ int icon,
+ const char *opname,
+ const char *propname,
+ int value)
{
- wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
- PointerRNA ptr;
+ wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
+ PointerRNA ptr;
- UI_OPERATOR_ERROR_RET(ot, opname, return);
+ UI_OPERATOR_ERROR_RET(ot, opname, return );
- WM_operator_properties_create_ptr(&ptr, ot);
- RNA_boolean_set(&ptr, propname, value);
+ WM_operator_properties_create_ptr(&ptr, ot);
+ RNA_boolean_set(&ptr, propname, value);
- uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
+ uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
}
-void uiItemIntO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, int value)
+void uiItemIntO(uiLayout *layout,
+ const char *name,
+ int icon,
+ const char *opname,
+ const char *propname,
+ int value)
{
- wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
- PointerRNA ptr;
+ wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
+ PointerRNA ptr;
- UI_OPERATOR_ERROR_RET(ot, opname, return);
+ UI_OPERATOR_ERROR_RET(ot, opname, return );
- WM_operator_properties_create_ptr(&ptr, ot);
- RNA_int_set(&ptr, propname, value);
+ WM_operator_properties_create_ptr(&ptr, ot);
+ RNA_int_set(&ptr, propname, value);
- uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
+ uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
}
-void uiItemFloatO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, float value)
+void uiItemFloatO(uiLayout *layout,
+ const char *name,
+ int icon,
+ const char *opname,
+ const char *propname,
+ float value)
{
- wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
- PointerRNA ptr;
+ wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
+ PointerRNA ptr;
- UI_OPERATOR_ERROR_RET(ot, opname, return);
+ UI_OPERATOR_ERROR_RET(ot, opname, return );
- WM_operator_properties_create_ptr(&ptr, ot);
- RNA_float_set(&ptr, propname, value);
+ WM_operator_properties_create_ptr(&ptr, ot);
+ RNA_float_set(&ptr, propname, value);
- uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
+ uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
}
-void uiItemStringO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, const char *value)
+void uiItemStringO(uiLayout *layout,
+ const char *name,
+ int icon,
+ const char *opname,
+ const char *propname,
+ const char *value)
{
- wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
- PointerRNA ptr;
+ wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
+ PointerRNA ptr;
- UI_OPERATOR_ERROR_RET(ot, opname, return);
+ UI_OPERATOR_ERROR_RET(ot, opname, return );
- WM_operator_properties_create_ptr(&ptr, ot);
- RNA_string_set(&ptr, propname, value);
+ WM_operator_properties_create_ptr(&ptr, ot);
+ RNA_string_set(&ptr, propname, value);
- uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
+ uiItemFullO_ptr(layout, ot, name, icon, ptr.data, layout->root->opcontext, 0, NULL);
}
void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname)
{
- uiItemFullO(layout, opname, name, icon, NULL, layout->root->opcontext, 0, NULL);
+ uiItemFullO(layout, opname, name, icon, NULL, layout->root->opcontext, 0, NULL);
}
/* RNA property items */
-static void ui_item_rna_size(
- uiLayout *layout, const char *name, int icon,
- PointerRNA *ptr, PropertyRNA *prop,
- int index, bool icon_only, bool compact,
- int *r_w, int *r_h)
-{
- PropertyType type;
- PropertySubType subtype;
- int len, w = 0, h;
-
- /* arbitrary extended width by type */
- type = RNA_property_type(prop);
- subtype = RNA_property_subtype(prop);
- len = RNA_property_array_length(ptr, prop);
-
- if (!name[0] && !icon_only) {
- if (ELEM(type, PROP_STRING, PROP_POINTER)) {
- name = "non-empty text";
- }
- else if (type == PROP_BOOLEAN) {
- icon = ICON_DOT;
- }
- else if (type == PROP_ENUM) {
- /* Find the longest enum item name, instead of using a dummy text! */
- const EnumPropertyItem *item, *item_array;
- bool free;
-
- RNA_property_enum_items_gettexted(layout->root->block->evil_C, ptr, prop, &item_array, NULL, &free);
- for (item = item_array; item->identifier; item++) {
- if (item->identifier[0]) {
- w = max_ii(w, ui_text_icon_width(layout, item->name, item->icon, compact));
- }
- }
- if (free) {
- MEM_freeN((void *)item_array);
- }
- }
- }
-
- if (!w) {
- if (type == PROP_ENUM && icon_only) {
- w = ui_text_icon_width(layout, "", ICON_BLANK1, compact);
- if (index != RNA_ENUM_VALUE) {
- w += 0.6f * UI_UNIT_X;
- }
- }
- else {
- /* not compact for float/int buttons, looks too squashed */
- w = ui_text_icon_width(layout, name, icon, ELEM(type, PROP_FLOAT, PROP_INT) ? false : compact);
- }
- }
- h = UI_UNIT_Y;
-
- /* increase height for arrays */
- if (index == RNA_NO_INDEX && len > 0) {
- if (!name[0] && icon == ICON_NONE) {
- h = 0;
- }
- if (layout->item.flag & UI_ITEM_PROP_SEP) {
- h = 0;
- }
- if (ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER)) {
- h += 2 * UI_UNIT_Y;
- }
- else if (subtype == PROP_MATRIX) {
- h += ceilf(sqrtf(len)) * UI_UNIT_Y;
- }
- else {
- h += len * UI_UNIT_Y;
- }
- }
- else if (ui_layout_variable_size(layout)) {
- if (type == PROP_BOOLEAN && name[0]) {
- w += UI_UNIT_X / 5;
- }
- else if (type == PROP_ENUM && !icon_only) {
- w += UI_UNIT_X / 4;
- }
- else if (type == PROP_FLOAT || type == PROP_INT) {
- w += UI_UNIT_X * 3;
- }
- }
-
- *r_w = w;
- *r_h = h;
-}
-
-void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index, int value, int flag, const char *name, int icon)
-{
- uiBlock *block = layout->root->block;
- uiBut *but = NULL;
- PropertyType type;
- char namestr[UI_MAX_NAME_STR];
- int len, w, h;
- bool slider, toggle, expand, icon_only, no_bg, compact;
- bool is_array;
- const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
-
- /* By default 'use_prop_sep' uses a separate column for labels.
- * This is an exception for check-boxes otherwise only the small checkbox region is clickable.
- *
- * 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;
+static void ui_item_rna_size(uiLayout *layout,
+ const char *name,
+ int icon,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ int index,
+ bool icon_only,
+ bool compact,
+ int *r_w,
+ int *r_h)
+{
+ PropertyType type;
+ PropertySubType subtype;
+ int len, w = 0, h;
+
+ /* arbitrary extended width by type */
+ type = RNA_property_type(prop);
+ subtype = RNA_property_subtype(prop);
+ len = RNA_property_array_length(ptr, prop);
+
+ if (!name[0] && !icon_only) {
+ if (ELEM(type, PROP_STRING, PROP_POINTER)) {
+ name = "non-empty text";
+ }
+ else if (type == PROP_BOOLEAN) {
+ icon = ICON_DOT;
+ }
+ else if (type == PROP_ENUM) {
+ /* Find the longest enum item name, instead of using a dummy text! */
+ const EnumPropertyItem *item, *item_array;
+ bool free;
+
+ RNA_property_enum_items_gettexted(
+ layout->root->block->evil_C, ptr, prop, &item_array, NULL, &free);
+ for (item = item_array; item->identifier; item++) {
+ if (item->identifier[0]) {
+ w = max_ii(w, ui_text_icon_width(layout, item->name, item->icon, compact));
+ }
+ }
+ if (free) {
+ MEM_freeN((void *)item_array);
+ }
+ }
+ }
+
+ if (!w) {
+ if (type == PROP_ENUM && icon_only) {
+ w = ui_text_icon_width(layout, "", ICON_BLANK1, compact);
+ if (index != RNA_ENUM_VALUE) {
+ w += 0.6f * UI_UNIT_X;
+ }
+ }
+ else {
+ /* not compact for float/int buttons, looks too squashed */
+ w = ui_text_icon_width(
+ layout, name, icon, ELEM(type, PROP_FLOAT, PROP_INT) ? false : compact);
+ }
+ }
+ h = UI_UNIT_Y;
+
+ /* increase height for arrays */
+ if (index == RNA_NO_INDEX && len > 0) {
+ if (!name[0] && icon == ICON_NONE) {
+ h = 0;
+ }
+ if (layout->item.flag & UI_ITEM_PROP_SEP) {
+ h = 0;
+ }
+ if (ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER)) {
+ h += 2 * UI_UNIT_Y;
+ }
+ else if (subtype == PROP_MATRIX) {
+ h += ceilf(sqrtf(len)) * UI_UNIT_Y;
+ }
+ else {
+ h += len * UI_UNIT_Y;
+ }
+ }
+ else if (ui_layout_variable_size(layout)) {
+ if (type == PROP_BOOLEAN && name[0]) {
+ w += UI_UNIT_X / 5;
+ }
+ else if (type == PROP_ENUM && !icon_only) {
+ w += UI_UNIT_X / 4;
+ }
+ else if (type == PROP_FLOAT || type == PROP_INT) {
+ w += UI_UNIT_X * 3;
+ }
+ }
+
+ *r_w = w;
+ *r_h = h;
+}
+
+void uiItemFullR(uiLayout *layout,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ int index,
+ int value,
+ int flag,
+ const char *name,
+ int icon)
+{
+ uiBlock *block = layout->root->block;
+ uiBut *but = NULL;
+ PropertyType type;
+ char namestr[UI_MAX_NAME_STR];
+ int len, w, h;
+ bool slider, toggle, expand, icon_only, no_bg, compact;
+ bool is_array;
+ const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
+
+ /* By default 'use_prop_sep' uses a separate column for labels.
+ * This is an exception for check-boxes otherwise only the small checkbox region is clickable.
+ *
+ * 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;
#ifdef UI_PROP_DECORATE
- struct {
- bool use_prop_decorate;
- int len;
- uiLayout *layout;
- uiBut *but;
- } ui_decorate = {
- .use_prop_decorate = (
- ((layout->item.flag & UI_ITEM_PROP_DECORATE) != 0) &&
- (use_prop_sep && ptr->id.data && id_can_have_animdata(ptr->id.data))),
- };
-#endif /* UI_PROP_DECORATE */
-
- UI_block_layout_set_current(block, layout);
-
- /* retrieve info */
- type = RNA_property_type(prop);
- is_array = RNA_property_array_check(prop);
- len = (is_array) ? RNA_property_array_length(ptr, prop) : 0;
-
- icon_only = (flag & UI_ITEM_R_ICON_ONLY) != 0;
-
- /* set name and icon */
- if (!name) {
- if (!icon_only) {
- name = RNA_property_ui_name(prop);
- }
- else {
- name = "";
- }
- }
-
- if (icon == ICON_NONE) {
- icon = RNA_property_ui_icon(prop);
- }
-
- if (flag & UI_ITEM_R_ICON_ONLY) {
- /* pass */
- }
- else if (ELEM(type, PROP_INT, PROP_FLOAT, PROP_STRING, PROP_POINTER)) {
- if (use_prop_sep == false) {
- name = ui_item_name_add_colon(name, namestr);
- }
- }
- else if (type == PROP_BOOLEAN && is_array && index == RNA_NO_INDEX) {
- if (use_prop_sep == false) {
- name = ui_item_name_add_colon(name, namestr);
- }
- }
- else if (type == PROP_ENUM && index != RNA_ENUM_VALUE) {
- if (flag & UI_ITEM_R_COMPACT) {
- name = "";
- }
- else {
- if (use_prop_sep == false) {
- name = ui_item_name_add_colon(name, namestr);
- }
- }
- }
+ struct {
+ bool use_prop_decorate;
+ int len;
+ uiLayout *layout;
+ uiBut *but;
+ } ui_decorate = {
+ .use_prop_decorate = (((layout->item.flag & UI_ITEM_PROP_DECORATE) != 0) &&
+ (use_prop_sep && ptr->id.data && id_can_have_animdata(ptr->id.data))),
+ };
+#endif /* UI_PROP_DECORATE */
+
+ UI_block_layout_set_current(block, layout);
+
+ /* retrieve info */
+ type = RNA_property_type(prop);
+ is_array = RNA_property_array_check(prop);
+ len = (is_array) ? RNA_property_array_length(ptr, prop) : 0;
+
+ icon_only = (flag & UI_ITEM_R_ICON_ONLY) != 0;
+
+ /* set name and icon */
+ if (!name) {
+ if (!icon_only) {
+ name = RNA_property_ui_name(prop);
+ }
+ else {
+ name = "";
+ }
+ }
+
+ if (icon == ICON_NONE) {
+ icon = RNA_property_ui_icon(prop);
+ }
+
+ if (flag & UI_ITEM_R_ICON_ONLY) {
+ /* pass */
+ }
+ else if (ELEM(type, PROP_INT, PROP_FLOAT, PROP_STRING, PROP_POINTER)) {
+ if (use_prop_sep == false) {
+ name = ui_item_name_add_colon(name, namestr);
+ }
+ }
+ else if (type == PROP_BOOLEAN && is_array && index == RNA_NO_INDEX) {
+ if (use_prop_sep == false) {
+ name = ui_item_name_add_colon(name, namestr);
+ }
+ }
+ else if (type == PROP_ENUM && index != RNA_ENUM_VALUE) {
+ if (flag & UI_ITEM_R_COMPACT) {
+ name = "";
+ }
+ else {
+ if (use_prop_sep == false) {
+ name = ui_item_name_add_colon(name, namestr);
+ }
+ }
+ }
#ifdef UI_PROP_SEP_ICON_WIDTH_EXCEPTION
- if (use_prop_sep) {
- if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) {
- use_prop_sep_split_label = false;
- }
- }
+ if (use_prop_sep) {
+ if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) {
+ use_prop_sep_split_label = false;
+ }
+ }
#endif
- /* menus and pie-menus don't show checkbox without this */
- if ((layout->root->type == UI_LAYOUT_MENU) ||
- /* use checkboxes only as a fallback in pie-menu's, when no icon is defined */
- ((layout->root->type == UI_LAYOUT_PIEMENU) && (icon == ICON_NONE)))
- {
- int prop_flag = RNA_property_flag(prop);
- if (type == PROP_BOOLEAN && ((is_array == false) || (index != RNA_NO_INDEX))) {
- if (prop_flag & PROP_ICONS_CONSECUTIVE) {
- icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */
- }
- else if (is_array) {
- icon = (RNA_property_boolean_get_index(ptr, prop, index)) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
- }
- else {
- icon = (RNA_property_boolean_get(ptr, prop)) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
- }
- }
- else if (type == PROP_ENUM && index == RNA_ENUM_VALUE) {
- int enum_value = RNA_property_enum_get(ptr, prop);
- if (prop_flag & PROP_ICONS_CONSECUTIVE) {
- icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */
- }
- else if (prop_flag & PROP_ENUM_FLAG) {
- icon = (enum_value & value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
- }
- else {
- icon = (enum_value == value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
- }
- }
- }
-
- if ((type == PROP_ENUM) && (RNA_property_flag(prop) & PROP_ENUM_FLAG)) {
- flag |= UI_ITEM_R_EXPAND;
- }
-
- slider = (flag & UI_ITEM_R_SLIDER) != 0;
- toggle = (flag & UI_ITEM_R_TOGGLE) != 0;
- expand = (flag & UI_ITEM_R_EXPAND) != 0;
- no_bg = (flag & UI_ITEM_R_NO_BG) != 0;
- compact = (flag & UI_ITEM_R_COMPACT) != 0;
-
- /* get size */
- ui_item_rna_size(layout, name, icon, ptr, prop, index, icon_only, compact, &w, &h);
-
- int prev_emboss = layout->emboss;
- if (no_bg) {
- layout->emboss = UI_EMBOSS_NONE;
- }
-
- /* Split the label / property. */
- uiLayout *layout_parent = layout;
- if (use_prop_sep) {
- uiLayout *layout_row = NULL;
+ /* menus and pie-menus don't show checkbox without this */
+ if ((layout->root->type == UI_LAYOUT_MENU) ||
+ /* use checkboxes only as a fallback in pie-menu's, when no icon is defined */
+ ((layout->root->type == UI_LAYOUT_PIEMENU) && (icon == ICON_NONE))) {
+ int prop_flag = RNA_property_flag(prop);
+ if (type == PROP_BOOLEAN && ((is_array == false) || (index != RNA_NO_INDEX))) {
+ if (prop_flag & PROP_ICONS_CONSECUTIVE) {
+ icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */
+ }
+ else if (is_array) {
+ icon = (RNA_property_boolean_get_index(ptr, prop, index)) ? ICON_CHECKBOX_HLT :
+ ICON_CHECKBOX_DEHLT;
+ }
+ else {
+ icon = (RNA_property_boolean_get(ptr, prop)) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
+ }
+ }
+ else if (type == PROP_ENUM && index == RNA_ENUM_VALUE) {
+ int enum_value = RNA_property_enum_get(ptr, prop);
+ if (prop_flag & PROP_ICONS_CONSECUTIVE) {
+ icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */
+ }
+ else if (prop_flag & PROP_ENUM_FLAG) {
+ icon = (enum_value & value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
+ }
+ else {
+ icon = (enum_value == value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
+ }
+ }
+ }
+
+ if ((type == PROP_ENUM) && (RNA_property_flag(prop) & PROP_ENUM_FLAG)) {
+ flag |= UI_ITEM_R_EXPAND;
+ }
+
+ slider = (flag & UI_ITEM_R_SLIDER) != 0;
+ toggle = (flag & UI_ITEM_R_TOGGLE) != 0;
+ expand = (flag & UI_ITEM_R_EXPAND) != 0;
+ no_bg = (flag & UI_ITEM_R_NO_BG) != 0;
+ compact = (flag & UI_ITEM_R_COMPACT) != 0;
+
+ /* get size */
+ ui_item_rna_size(layout, name, icon, ptr, prop, index, icon_only, compact, &w, &h);
+
+ int prev_emboss = layout->emboss;
+ if (no_bg) {
+ layout->emboss = UI_EMBOSS_NONE;
+ }
+
+ /* Split the label / property. */
+ uiLayout *layout_parent = layout;
+ if (use_prop_sep) {
+ uiLayout *layout_row = NULL;
#ifdef UI_PROP_DECORATE
- if (ui_decorate.use_prop_decorate) {
- layout_row = uiLayoutRow(layout, true);
- layout_row->space = 0;
- ui_decorate.len = max_ii(1, len);
- }
-#endif /* UI_PROP_DECORATE */
-
- if ((name[0] == '\0') || (use_prop_sep_split_label == false)) {
- /* Ensure we get a column when text is not set. */
- layout = uiLayoutColumn(layout_row ? layout_row : layout, true);
- layout->space = 0;
- }
- else {
- const PropertySubType subtype = RNA_property_subtype(prop);
- uiLayout *layout_split = uiLayoutSplit(
- layout_row ? layout_row : layout,
- UI_ITEM_PROP_SEP_DIVIDE, true);
- 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))
- {
- char name_with_suffix[UI_MAX_DRAW_STR + 2];
- char str[2] = {'\0'};
- for (int a = 0; a < len; a++) {
- str[0] = RNA_property_array_item_char(prop, a);
- const bool use_prefix = (a == 0 && name && name[0]);
- if (use_prefix) {
- char *s = name_with_suffix;
- s += STRNCPY_RLEN(name_with_suffix, name);
- *s++ = ' ';
- *s++ = str[0];
- *s++ = '\0';
- }
- but = uiDefBut(
- block, UI_BTYPE_LABEL, 0, use_prefix ? name_with_suffix : str,
- 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;
- }
- }
- else {
- if (name) {
- but = uiDefBut(
- 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;
- }
- }
-
- /* 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;
- }
-
- /* 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. */
-
- /* Often expanded enum's are better arranged into a row,
- * so check the existing layout. */
- if (uiLayoutGetLocalDir(layout) == UI_LAYOUT_HORIZONTAL) {
- layout = uiLayoutRow(layout_split, true);
- }
- else {
- layout = uiLayoutColumn(layout_split, true);
- }
- }
- else {
- name = "";
- layout = uiLayoutColumn(layout_split, true);
- }
- layout->space = 0;
- }
+ if (ui_decorate.use_prop_decorate) {
+ layout_row = uiLayoutRow(layout, true);
+ layout_row->space = 0;
+ ui_decorate.len = max_ii(1, len);
+ }
+#endif /* UI_PROP_DECORATE */
+
+ if ((name[0] == '\0') || (use_prop_sep_split_label == false)) {
+ /* Ensure we get a column when text is not set. */
+ layout = uiLayoutColumn(layout_row ? layout_row : layout, true);
+ layout->space = 0;
+ }
+ else {
+ const PropertySubType subtype = RNA_property_subtype(prop);
+ uiLayout *layout_split = uiLayoutSplit(
+ layout_row ? layout_row : layout, UI_ITEM_PROP_SEP_DIVIDE, true);
+ 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)) {
+ char name_with_suffix[UI_MAX_DRAW_STR + 2];
+ char str[2] = {'\0'};
+ for (int a = 0; a < len; a++) {
+ str[0] = RNA_property_array_item_char(prop, a);
+ const bool use_prefix = (a == 0 && name && name[0]);
+ if (use_prefix) {
+ char *s = name_with_suffix;
+ s += STRNCPY_RLEN(name_with_suffix, name);
+ *s++ = ' ';
+ *s++ = str[0];
+ *s++ = '\0';
+ }
+ but = uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ use_prefix ? name_with_suffix : str,
+ 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;
+ }
+ }
+ else {
+ if (name) {
+ but = uiDefBut(
+ 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;
+ }
+ }
+
+ /* 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;
+ }
+
+ /* 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. */
+
+ /* Often expanded enum's are better arranged into a row,
+ * so check the existing layout. */
+ if (uiLayoutGetLocalDir(layout) == UI_LAYOUT_HORIZONTAL) {
+ layout = uiLayoutRow(layout_split, true);
+ }
+ else {
+ layout = uiLayoutColumn(layout_split, true);
+ }
+ }
+ else {
+ name = "";
+ layout = uiLayoutColumn(layout_split, true);
+ }
+ layout->space = 0;
+ }
#ifdef UI_PROP_DECORATE
- if (ui_decorate.use_prop_decorate) {
- ui_decorate.layout = uiLayoutColumn(layout_row, true);
- ui_decorate.layout->space = 0;
- UI_block_layout_set_current(block, layout);
- ui_decorate.but = block->buttons.last;
-
- /* Clear after. */
- layout->item.flag |= UI_ITEM_PROP_DECORATE_NO_PAD;
- }
-#endif /* UI_PROP_DECORATE */
- }
- /* End split. */
-
- /* array property */
- if (index == RNA_NO_INDEX && is_array) {
- ui_item_array(
- layout, block, name, icon, ptr, prop, len, 0, 0, w, h,
- expand, slider, toggle, icon_only, compact, !use_prop_sep_split_label);
- }
- /* enum item */
- else if (type == PROP_ENUM && index == RNA_ENUM_VALUE) {
- if (icon && name[0] && !icon_only) {
- uiDefIconTextButR_prop(block, UI_BTYPE_ROW, 0, icon, name, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
- }
- else if (icon) {
- uiDefIconButR_prop(block, UI_BTYPE_ROW, 0, icon, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
- }
- else {
- uiDefButR_prop(block, UI_BTYPE_ROW, 0, name, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
- }
- }
- /* expanded enum */
- else if (type == PROP_ENUM && expand) {
- ui_item_enum_expand(layout, block, ptr, prop, name, h, icon_only);
- }
- /* property with separate label */
- else if (type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER) {
- but = ui_item_with_label(layout, block, name, icon, ptr, prop, index, 0, 0, w, h, flag);
- ui_but_add_search(but, ptr, prop, NULL, NULL);
-
- if (layout->redalert) {
- UI_but_flag_enable(but, UI_BUT_REDALERT);
- }
-
- if (layout->activate_init) {
- UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
- }
- }
- /* single button */
- else {
- but = uiDefAutoButR(block, ptr, prop, index, name, icon, 0, 0, w, h);
-
- if (slider && but->type == UI_BTYPE_NUM) {
- but->type = UI_BTYPE_NUM_SLIDER;
- }
-
- if (toggle && but->type == UI_BTYPE_CHECKBOX) {
- but->type = UI_BTYPE_TOGGLE;
- }
-
- if (layout->redalert) {
- UI_but_flag_enable(but, UI_BUT_REDALERT);
- }
-
- 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;
- }
-
- }
-
- /* Mark non-embossed textfields inside a listbox. */
- if (but && (block->flag & UI_BLOCK_LIST_ITEM) && (but->type == UI_BTYPE_TEXT) && (but->dt & UI_EMBOSS_NONE)) {
- UI_but_flag_enable(but, UI_BUT_LIST_ITEM);
- }
+ if (ui_decorate.use_prop_decorate) {
+ ui_decorate.layout = uiLayoutColumn(layout_row, true);
+ ui_decorate.layout->space = 0;
+ UI_block_layout_set_current(block, layout);
+ ui_decorate.but = block->buttons.last;
+
+ /* Clear after. */
+ layout->item.flag |= UI_ITEM_PROP_DECORATE_NO_PAD;
+ }
+#endif /* UI_PROP_DECORATE */
+ }
+ /* End split. */
+
+ /* array property */
+ if (index == RNA_NO_INDEX && is_array) {
+ ui_item_array(layout,
+ block,
+ name,
+ icon,
+ ptr,
+ prop,
+ len,
+ 0,
+ 0,
+ w,
+ h,
+ expand,
+ slider,
+ toggle,
+ icon_only,
+ compact,
+ !use_prop_sep_split_label);
+ }
+ /* enum item */
+ else if (type == PROP_ENUM && index == RNA_ENUM_VALUE) {
+ if (icon && name[0] && !icon_only) {
+ uiDefIconTextButR_prop(
+ block, UI_BTYPE_ROW, 0, icon, name, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
+ }
+ else if (icon) {
+ uiDefIconButR_prop(
+ block, UI_BTYPE_ROW, 0, icon, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
+ }
+ else {
+ uiDefButR_prop(
+ block, UI_BTYPE_ROW, 0, name, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
+ }
+ }
+ /* expanded enum */
+ else if (type == PROP_ENUM && expand) {
+ ui_item_enum_expand(layout, block, ptr, prop, name, h, icon_only);
+ }
+ /* property with separate label */
+ else if (type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER) {
+ but = ui_item_with_label(layout, block, name, icon, ptr, prop, index, 0, 0, w, h, flag);
+ ui_but_add_search(but, ptr, prop, NULL, NULL);
+
+ if (layout->redalert) {
+ UI_but_flag_enable(but, UI_BUT_REDALERT);
+ }
+
+ if (layout->activate_init) {
+ UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
+ }
+ }
+ /* single button */
+ else {
+ but = uiDefAutoButR(block, ptr, prop, index, name, icon, 0, 0, w, h);
+
+ if (slider && but->type == UI_BTYPE_NUM) {
+ but->type = UI_BTYPE_NUM_SLIDER;
+ }
+
+ if (toggle && but->type == UI_BTYPE_CHECKBOX) {
+ but->type = UI_BTYPE_TOGGLE;
+ }
+
+ if (layout->redalert) {
+ UI_but_flag_enable(but, UI_BUT_REDALERT);
+ }
+
+ 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;
+ }
+ }
+
+ /* Mark non-embossed textfields inside a listbox. */
+ if (but && (block->flag & UI_BLOCK_LIST_ITEM) && (but->type == UI_BTYPE_TEXT) &&
+ (but->dt & UI_EMBOSS_NONE)) {
+ UI_but_flag_enable(but, UI_BUT_LIST_ITEM);
+ }
#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;
- 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++) {
- /* 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;
- }
- /* Order the decorator after the button we decorate, this is used so we can always
- * do a quick lookup. */
- BLI_remlink(&block->buttons, but);
- BLI_insertlinkafter(&block->buttons, but_decorate, but);
- but_decorate = but->next;
- }
- BLI_assert(ELEM(i, 1, ui_decorate.len));
-
- layout->item.flag &= ~UI_ITEM_PROP_DECORATE_NO_PAD;
- }
-#endif /* UI_PROP_DECORATE */
-
- if (no_bg) {
- layout->emboss = prev_emboss;
- }
-
- /* ensure text isn't added to icon_only buttons */
- if (but && icon_only) {
- BLI_assert(but->str[0] == '\0');
- }
-
-}
-
-void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
-{
- PropertyRNA *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;
- }
-
- uiItemFullR(layout, ptr, prop, RNA_NO_INDEX, 0, flag, name, icon);
+ 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;
+ 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++) {
+ /* 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;
+ }
+ /* Order the decorator after the button we decorate, this is used so we can always
+ * do a quick lookup. */
+ BLI_remlink(&block->buttons, but);
+ BLI_insertlinkafter(&block->buttons, but_decorate, but);
+ but_decorate = but->next;
+ }
+ BLI_assert(ELEM(i, 1, ui_decorate.len));
+
+ layout->item.flag &= ~UI_ITEM_PROP_DECORATE_NO_PAD;
+ }
+#endif /* UI_PROP_DECORATE */
+
+ if (no_bg) {
+ layout->emboss = prev_emboss;
+ }
+
+ /* ensure text isn't added to icon_only buttons */
+ if (but && icon_only) {
+ BLI_assert(but->str[0] == '\0');
+ }
+}
+
+void uiItemR(
+ uiLayout *layout, PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
+{
+ PropertyRNA *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;
+ }
+
+ uiItemFullR(layout, ptr, prop, RNA_NO_INDEX, 0, flag, name, icon);
}
/**
* Use a wrapper function since re-implementing all the logic in this function would be messy.
*/
-void uiItemFullR_with_popover(
- uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index, int value, int flag, const char *name, int icon,
- const char *panel_type)
-{
- uiBlock *block = layout->root->block;
- uiBut *but = block->buttons.last;
- uiItemFullR(layout, ptr, prop, index, value, flag, name, icon);
- but = but->next;
- while (but) {
- if (but->rnaprop == prop && but->type == UI_BTYPE_MENU) {
- ui_but_rna_menu_convert_to_panel_type(but, panel_type);
- break;
- }
- but = but->next;
- }
- if (but == NULL) {
- const char *propname = RNA_property_identifier(prop);
- ui_item_disabled(layout, panel_type);
- RNA_warning(
- "property could not use a popover: %s.%s (%s)",
- RNA_struct_identifier(ptr->type), propname, panel_type);
- }
-}
-
-void uiItemFullR_with_menu(
- uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index, int value, int flag, const char *name, int icon,
- const char *menu_type)
-{
- uiBlock *block = layout->root->block;
- uiBut *but = block->buttons.last;
- uiItemFullR(layout, ptr, prop, index, value, flag, name, icon);
- but = but->next;
- while (but) {
- if (but->rnaprop == prop && but->type == UI_BTYPE_MENU) {
- ui_but_rna_menu_convert_to_menu_type(but, menu_type);
- break;
- }
- but = but->next;
- }
- if (but == NULL) {
- const char *propname = RNA_property_identifier(prop);
- ui_item_disabled(layout, menu_type);
- RNA_warning(
- "property could not use a menu: %s.%s (%s)",
- RNA_struct_identifier(ptr->type), propname, menu_type);
- }
-}
-
-void uiItemEnumR_prop(uiLayout *layout, const char *name, int icon, struct PointerRNA *ptr, PropertyRNA *prop, int value)
-{
- if (RNA_property_type(prop) != PROP_ENUM) {
- const char *propname = RNA_property_identifier(prop);
- ui_item_disabled(layout, propname);
- RNA_warning("property not an enum: %s.%s", RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- uiItemFullR(layout, ptr, prop, RNA_ENUM_VALUE, value, 0, name, icon);
-}
-
-void uiItemEnumR(uiLayout *layout, const char *name, int icon, struct PointerRNA *ptr, const char *propname, int value)
-{
- PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
-
- if (prop == NULL) {
- ui_item_disabled(layout, propname);
- RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- uiItemFullR(layout, ptr, prop, RNA_ENUM_VALUE, value, 0, name, icon);
-}
-
-
-void uiItemEnumR_string_prop(
- uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop,
- const char *value, const char *name, int icon)
-{
- const EnumPropertyItem *item;
- int ivalue, a;
- bool free;
-
- if (UNLIKELY(RNA_property_type(prop) != PROP_ENUM)) {
- const char *propname = RNA_property_identifier(prop);
- ui_item_disabled(layout, propname);
- RNA_warning("not an enum property: %s.%s", RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- RNA_property_enum_items(layout->root->block->evil_C, ptr, prop, &item, NULL, &free);
-
- if (!RNA_enum_value_from_id(item, value, &ivalue)) {
- const char *propname = RNA_property_identifier(prop);
- if (free) {
- MEM_freeN((void *)item);
- }
- ui_item_disabled(layout, propname);
- RNA_warning("enum property value not found: %s", value);
- return;
- }
-
- for (a = 0; item[a].identifier; a++) {
- if (item[a].value == ivalue) {
- const char *item_name = name ? name : CTX_IFACE_(RNA_property_translation_context(prop), item[a].name);
- const int flag = item_name[0] ? 0 : UI_ITEM_R_ICON_ONLY;
-
- uiItemFullR(layout, ptr, prop, RNA_ENUM_VALUE, ivalue, flag, item_name, icon ? icon : item[a].icon);
- break;
- }
- }
-
- if (free) {
- MEM_freeN((void *)item);
- }
-}
-
-void uiItemEnumR_string(
- uiLayout *layout, struct PointerRNA *ptr, const char *propname,
- const char *value, const char *name, int icon)
-{
- PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
- if (UNLIKELY(prop == NULL)) {
- ui_item_disabled(layout, propname);
- RNA_warning("enum property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
- return;
- }
- uiItemEnumR_string_prop(layout, ptr, prop, value, name, icon);
+void uiItemFullR_with_popover(uiLayout *layout,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ int index,
+ int value,
+ int flag,
+ const char *name,
+ int icon,
+ const char *panel_type)
+{
+ uiBlock *block = layout->root->block;
+ uiBut *but = block->buttons.last;
+ uiItemFullR(layout, ptr, prop, index, value, flag, name, icon);
+ but = but->next;
+ while (but) {
+ if (but->rnaprop == prop && but->type == UI_BTYPE_MENU) {
+ ui_but_rna_menu_convert_to_panel_type(but, panel_type);
+ break;
+ }
+ but = but->next;
+ }
+ if (but == NULL) {
+ const char *propname = RNA_property_identifier(prop);
+ ui_item_disabled(layout, panel_type);
+ RNA_warning("property could not use a popover: %s.%s (%s)",
+ RNA_struct_identifier(ptr->type),
+ propname,
+ panel_type);
+ }
+}
+
+void uiItemFullR_with_menu(uiLayout *layout,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ int index,
+ int value,
+ int flag,
+ const char *name,
+ int icon,
+ const char *menu_type)
+{
+ uiBlock *block = layout->root->block;
+ uiBut *but = block->buttons.last;
+ uiItemFullR(layout, ptr, prop, index, value, flag, name, icon);
+ but = but->next;
+ while (but) {
+ if (but->rnaprop == prop && but->type == UI_BTYPE_MENU) {
+ ui_but_rna_menu_convert_to_menu_type(but, menu_type);
+ break;
+ }
+ but = but->next;
+ }
+ if (but == NULL) {
+ const char *propname = RNA_property_identifier(prop);
+ ui_item_disabled(layout, menu_type);
+ RNA_warning("property could not use a menu: %s.%s (%s)",
+ RNA_struct_identifier(ptr->type),
+ propname,
+ menu_type);
+ }
+}
+
+void uiItemEnumR_prop(uiLayout *layout,
+ const char *name,
+ int icon,
+ struct PointerRNA *ptr,
+ PropertyRNA *prop,
+ int value)
+{
+ if (RNA_property_type(prop) != PROP_ENUM) {
+ const char *propname = RNA_property_identifier(prop);
+ ui_item_disabled(layout, propname);
+ RNA_warning("property not an enum: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ uiItemFullR(layout, ptr, prop, RNA_ENUM_VALUE, value, 0, name, icon);
+}
+
+void uiItemEnumR(uiLayout *layout,
+ const char *name,
+ int icon,
+ struct PointerRNA *ptr,
+ const char *propname,
+ int value)
+{
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+
+ if (prop == NULL) {
+ ui_item_disabled(layout, propname);
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ uiItemFullR(layout, ptr, prop, RNA_ENUM_VALUE, value, 0, name, icon);
+}
+
+void uiItemEnumR_string_prop(uiLayout *layout,
+ struct PointerRNA *ptr,
+ PropertyRNA *prop,
+ const char *value,
+ const char *name,
+ int icon)
+{
+ const EnumPropertyItem *item;
+ int ivalue, a;
+ bool free;
+
+ if (UNLIKELY(RNA_property_type(prop) != PROP_ENUM)) {
+ const char *propname = RNA_property_identifier(prop);
+ ui_item_disabled(layout, propname);
+ RNA_warning("not an enum property: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ RNA_property_enum_items(layout->root->block->evil_C, ptr, prop, &item, NULL, &free);
+
+ if (!RNA_enum_value_from_id(item, value, &ivalue)) {
+ const char *propname = RNA_property_identifier(prop);
+ if (free) {
+ MEM_freeN((void *)item);
+ }
+ ui_item_disabled(layout, propname);
+ RNA_warning("enum property value not found: %s", value);
+ return;
+ }
+
+ for (a = 0; item[a].identifier; a++) {
+ if (item[a].value == ivalue) {
+ const char *item_name = name ?
+ name :
+ CTX_IFACE_(RNA_property_translation_context(prop), item[a].name);
+ const int flag = item_name[0] ? 0 : UI_ITEM_R_ICON_ONLY;
+
+ uiItemFullR(
+ layout, ptr, prop, RNA_ENUM_VALUE, ivalue, flag, item_name, icon ? icon : item[a].icon);
+ break;
+ }
+ }
+
+ if (free) {
+ MEM_freeN((void *)item);
+ }
+}
+
+void uiItemEnumR_string(uiLayout *layout,
+ struct PointerRNA *ptr,
+ const char *propname,
+ const char *value,
+ const char *name,
+ int icon)
+{
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ if (UNLIKELY(prop == NULL)) {
+ ui_item_disabled(layout, propname);
+ RNA_warning("enum property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+ uiItemEnumR_string_prop(layout, ptr, prop, value, name, icon);
}
void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname)
{
- PropertyRNA *prop;
- uiBlock *block = layout->root->block;
- uiBut *bt;
-
- prop = RNA_struct_find_property(ptr, propname);
-
- if (!prop) {
- ui_item_disabled(layout, propname);
- RNA_warning("enum property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- if (RNA_property_type(prop) != PROP_ENUM) {
- RNA_warning("not an enum property: %s.%s", RNA_struct_identifier(ptr->type), propname);
- return;
- }
- else {
- const EnumPropertyItem *item;
- int totitem, i;
- bool free;
- uiLayout *split = uiLayoutSplit(layout, 0.0f, false);
- uiLayout *column = uiLayoutColumn(split, false);
-
- RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item, &totitem, &free);
-
- for (i = 0; i < totitem; i++) {
- if (item[i].identifier[0]) {
- uiItemEnumR_prop(column, item[i].name, item[i].icon, ptr, prop, item[i].value);
- ui_but_tip_from_enum_item(block->buttons.last, &item[i]);
- }
- else {
- if (item[i].name) {
- if (i != 0) {
- column = uiLayoutColumn(split, false);
- /* inconsistent, but menus with labels do not look good flipped */
- block->flag |= UI_BLOCK_NO_FLIP;
- }
-
- uiItemL(column, item[i].name, ICON_NONE);
- bt = block->buttons.last;
- bt->drawflag = UI_BUT_TEXT_LEFT;
-
- ui_but_tip_from_enum_item(bt, &item[i]);
- }
- else {
- uiItemS(column);
- }
- }
- }
-
- if (free) {
- MEM_freeN((void *)item);
- }
- }
-
- /* intentionally don't touch UI_BLOCK_IS_FLIP here,
- * we don't know the context this is called in */
+ PropertyRNA *prop;
+ uiBlock *block = layout->root->block;
+ uiBut *bt;
+
+ prop = RNA_struct_find_property(ptr, propname);
+
+ if (!prop) {
+ ui_item_disabled(layout, propname);
+ RNA_warning("enum property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ if (RNA_property_type(prop) != PROP_ENUM) {
+ RNA_warning("not an enum property: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+ else {
+ const EnumPropertyItem *item;
+ int totitem, i;
+ bool free;
+ uiLayout *split = uiLayoutSplit(layout, 0.0f, false);
+ uiLayout *column = uiLayoutColumn(split, false);
+
+ RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item, &totitem, &free);
+
+ for (i = 0; i < totitem; i++) {
+ if (item[i].identifier[0]) {
+ uiItemEnumR_prop(column, item[i].name, item[i].icon, ptr, prop, item[i].value);
+ ui_but_tip_from_enum_item(block->buttons.last, &item[i]);
+ }
+ else {
+ if (item[i].name) {
+ if (i != 0) {
+ column = uiLayoutColumn(split, false);
+ /* inconsistent, but menus with labels do not look good flipped */
+ block->flag |= UI_BLOCK_NO_FLIP;
+ }
+
+ uiItemL(column, item[i].name, ICON_NONE);
+ bt = block->buttons.last;
+ bt->drawflag = UI_BUT_TEXT_LEFT;
+
+ ui_but_tip_from_enum_item(bt, &item[i]);
+ }
+ else {
+ uiItemS(column);
+ }
+ }
+ }
+
+ if (free) {
+ MEM_freeN((void *)item);
+ }
+ }
+
+ /* intentionally don't touch UI_BLOCK_IS_FLIP here,
+ * we don't know the context this is called in */
}
/* Pointer RNA button with search */
-
static void search_id_collection(StructRNA *ptype, PointerRNA *r_ptr, PropertyRNA **r_prop)
{
- StructRNA *srna;
-
- /* look for collection property in Main */
- /* Note: using global Main is OK-ish here, UI shall not access other Mains anyay... */
- RNA_main_pointer_create(G_MAIN, r_ptr);
-
- *r_prop = NULL;
-
- RNA_STRUCT_BEGIN (r_ptr, iprop)
- {
- /* if it's a collection and has same pointer type, we've got it */
- if (RNA_property_type(iprop) == PROP_COLLECTION) {
- srna = RNA_property_pointer_type(r_ptr, iprop);
-
- if (ptype == srna) {
- *r_prop = iprop;
- break;
- }
- }
- }
- RNA_STRUCT_END;
-}
-
-void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop)
-{
- StructRNA *ptype;
- PointerRNA sptr;
-
- /* for ID's we do automatic lookup */
- if (!searchprop) {
- if (RNA_property_type(prop) == PROP_POINTER) {
- ptype = RNA_property_pointer_type(ptr, prop);
- search_id_collection(ptype, &sptr, &searchprop);
- searchptr = &sptr;
- }
- }
-
- /* turn button into search button */
- if (searchprop) {
- uiRNACollectionSearch *coll_search = MEM_mallocN(sizeof(*coll_search), __func__);
-
- but->type = UI_BTYPE_SEARCH_MENU;
- but->hardmax = MAX2(but->hardmax, 256.0f);
- but->rnasearchpoin = *searchptr;
- but->rnasearchprop = searchprop;
- but->drawflag |= UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT;
- if (RNA_property_is_unlink(prop)) {
- but->flag |= UI_BUT_VALUE_CLEAR;
- }
-
- coll_search->target_ptr = *ptr;
- coll_search->target_prop = prop;
- coll_search->search_ptr = *searchptr;
- coll_search->search_prop = searchprop;
- coll_search->but_changed = &but->changed;
-
- if (RNA_property_type(prop) == PROP_ENUM) {
- /* XXX, this will have a menu string,
- * but in this case we just want the text */
- but->str[0] = 0;
- }
-
- UI_but_func_search_set(
- but, ui_searchbox_create_generic, ui_rna_collection_search_cb,
- coll_search, true, NULL, NULL);
- }
- else if (but->type == UI_BTYPE_SEARCH_MENU) {
- /* In case we fail to find proper searchprop,
- * so other code might have already set but->type to search menu... */
- but->flag |= UI_BUT_DISABLED;
- }
-}
-
-void uiItemPointerR_prop(
- uiLayout *layout,
- PointerRNA *ptr, PropertyRNA *prop,
- PointerRNA *searchptr, PropertyRNA *searchprop,
- const char *name, int icon)
-{
- PropertyType type;
- uiBut *but;
- uiBlock *block;
- StructRNA *icontype;
- int w, h;
- char namestr[UI_MAX_NAME_STR];
- const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
-
- type = RNA_property_type(prop);
- if (!ELEM(type, PROP_POINTER, PROP_STRING, PROP_ENUM)) {
- RNA_warning("Property %s.%s must be a pointer, string or enum",
- RNA_struct_identifier(ptr->type), RNA_property_identifier(prop));
- return;
- }
- if (RNA_property_type(searchprop) != PROP_COLLECTION) {
- RNA_warning("search collection property is not a collection type: %s.%s",
- RNA_struct_identifier(searchptr->type), RNA_property_identifier(searchprop));
- return;
- }
-
- /* get icon & name */
- if (icon == ICON_NONE) {
- if (type == PROP_POINTER) {
- icontype = RNA_property_pointer_type(ptr, prop);
- }
- else {
- icontype = RNA_property_pointer_type(searchptr, searchprop);
- }
-
- icon = RNA_struct_ui_icon(icontype);
- }
- if (!name) {
- name = RNA_property_ui_name(prop);
- }
-
- if (use_prop_sep == false) {
- name = ui_item_name_add_colon(name, namestr);
- }
-
- /* create button */
- block = uiLayoutGetBlock(layout);
-
- ui_item_rna_size(layout, name, icon, ptr, prop, 0, 0, false, &w, &h);
- w += UI_UNIT_X; /* X icon needs more space */
- but = ui_item_with_label(layout, block, name, icon, ptr, prop, 0, 0, 0, w, h, 0);
-
- ui_but_add_search(but, ptr, prop, searchptr, searchprop);
-}
-
-void uiItemPointerR(
- uiLayout *layout,
- PointerRNA *ptr, const char *propname,
- PointerRNA *searchptr, const char *searchpropname,
- const char *name, int icon)
-{
- PropertyRNA *prop, *searchprop;
-
- /* validate arguments */
- prop = RNA_struct_find_property(ptr, propname);
- if (!prop) {
- RNA_warning("property not found: %s.%s",
- RNA_struct_identifier(ptr->type), propname);
- return;
- }
- searchprop = RNA_struct_find_property(searchptr, searchpropname);
- if (!searchprop) {
- RNA_warning("search collection property not found: %s.%s",
- RNA_struct_identifier(searchptr->type), searchpropname);
- return;
- }
-
- uiItemPointerR_prop(layout, ptr, prop, searchptr, searchprop, name, icon);
+ StructRNA *srna;
+
+ /* look for collection property in Main */
+ /* Note: using global Main is OK-ish here, UI shall not access other Mains anyay... */
+ RNA_main_pointer_create(G_MAIN, r_ptr);
+
+ *r_prop = NULL;
+
+ RNA_STRUCT_BEGIN (r_ptr, iprop) {
+ /* if it's a collection and has same pointer type, we've got it */
+ if (RNA_property_type(iprop) == PROP_COLLECTION) {
+ srna = RNA_property_pointer_type(r_ptr, iprop);
+
+ if (ptype == srna) {
+ *r_prop = iprop;
+ break;
+ }
+ }
+ }
+ RNA_STRUCT_END;
+}
+
+void ui_but_add_search(
+ uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop)
+{
+ StructRNA *ptype;
+ PointerRNA sptr;
+
+ /* for ID's we do automatic lookup */
+ if (!searchprop) {
+ if (RNA_property_type(prop) == PROP_POINTER) {
+ ptype = RNA_property_pointer_type(ptr, prop);
+ search_id_collection(ptype, &sptr, &searchprop);
+ searchptr = &sptr;
+ }
+ }
+
+ /* turn button into search button */
+ if (searchprop) {
+ uiRNACollectionSearch *coll_search = MEM_mallocN(sizeof(*coll_search), __func__);
+
+ but->type = UI_BTYPE_SEARCH_MENU;
+ but->hardmax = MAX2(but->hardmax, 256.0f);
+ but->rnasearchpoin = *searchptr;
+ but->rnasearchprop = searchprop;
+ but->drawflag |= UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT;
+ if (RNA_property_is_unlink(prop)) {
+ but->flag |= UI_BUT_VALUE_CLEAR;
+ }
+
+ coll_search->target_ptr = *ptr;
+ coll_search->target_prop = prop;
+ coll_search->search_ptr = *searchptr;
+ coll_search->search_prop = searchprop;
+ coll_search->but_changed = &but->changed;
+
+ if (RNA_property_type(prop) == PROP_ENUM) {
+ /* XXX, this will have a menu string,
+ * but in this case we just want the text */
+ but->str[0] = 0;
+ }
+
+ UI_but_func_search_set(but,
+ ui_searchbox_create_generic,
+ ui_rna_collection_search_cb,
+ coll_search,
+ true,
+ NULL,
+ NULL);
+ }
+ else if (but->type == UI_BTYPE_SEARCH_MENU) {
+ /* In case we fail to find proper searchprop,
+ * so other code might have already set but->type to search menu... */
+ but->flag |= UI_BUT_DISABLED;
+ }
+}
+
+void uiItemPointerR_prop(uiLayout *layout,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ PointerRNA *searchptr,
+ PropertyRNA *searchprop,
+ const char *name,
+ int icon)
+{
+ PropertyType type;
+ uiBut *but;
+ uiBlock *block;
+ StructRNA *icontype;
+ int w, h;
+ char namestr[UI_MAX_NAME_STR];
+ const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
+
+ type = RNA_property_type(prop);
+ if (!ELEM(type, PROP_POINTER, PROP_STRING, PROP_ENUM)) {
+ RNA_warning("Property %s.%s must be a pointer, string or enum",
+ RNA_struct_identifier(ptr->type),
+ RNA_property_identifier(prop));
+ return;
+ }
+ if (RNA_property_type(searchprop) != PROP_COLLECTION) {
+ RNA_warning("search collection property is not a collection type: %s.%s",
+ RNA_struct_identifier(searchptr->type),
+ RNA_property_identifier(searchprop));
+ return;
+ }
+
+ /* get icon & name */
+ if (icon == ICON_NONE) {
+ if (type == PROP_POINTER) {
+ icontype = RNA_property_pointer_type(ptr, prop);
+ }
+ else {
+ icontype = RNA_property_pointer_type(searchptr, searchprop);
+ }
+
+ icon = RNA_struct_ui_icon(icontype);
+ }
+ if (!name) {
+ name = RNA_property_ui_name(prop);
+ }
+
+ if (use_prop_sep == false) {
+ name = ui_item_name_add_colon(name, namestr);
+ }
+
+ /* create button */
+ block = uiLayoutGetBlock(layout);
+
+ ui_item_rna_size(layout, name, icon, ptr, prop, 0, 0, false, &w, &h);
+ w += UI_UNIT_X; /* X icon needs more space */
+ but = ui_item_with_label(layout, block, name, icon, ptr, prop, 0, 0, 0, w, h, 0);
+
+ ui_but_add_search(but, ptr, prop, searchptr, searchprop);
+}
+
+void uiItemPointerR(uiLayout *layout,
+ PointerRNA *ptr,
+ const char *propname,
+ PointerRNA *searchptr,
+ const char *searchpropname,
+ const char *name,
+ int icon)
+{
+ PropertyRNA *prop, *searchprop;
+
+ /* validate arguments */
+ prop = RNA_struct_find_property(ptr, propname);
+ if (!prop) {
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+ searchprop = RNA_struct_find_property(searchptr, searchpropname);
+ if (!searchprop) {
+ RNA_warning("search collection property not found: %s.%s",
+ RNA_struct_identifier(searchptr->type),
+ searchpropname);
+ return;
+ }
+
+ uiItemPointerR_prop(layout, ptr, prop, searchptr, searchprop, name, icon);
}
/* menu item */
void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
{
- MenuType *mt = (MenuType *)arg_mt;
+ MenuType *mt = (MenuType *)arg_mt;
- UI_menutype_draw(C, mt, layout);
+ UI_menutype_draw(C, mt, layout);
- /* menus are created flipped (from event handling pov) */
- layout->root->block->flag ^= UI_BLOCK_IS_FLIP;
+ /* menus are created flipped (from event handling pov) */
+ layout->root->block->flag ^= UI_BLOCK_IS_FLIP;
}
void ui_item_paneltype_func(bContext *C, uiLayout *layout, void *arg_pt)
{
- PanelType *pt = (PanelType *)arg_pt;
- UI_paneltype_draw(C, pt, layout);
-
- /* panels are created flipped (from event handling pov) */
- layout->root->block->flag ^= UI_BLOCK_IS_FLIP;
-}
-
-static uiBut *ui_item_menu(
- uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg, void *argN,
- const char *tip, bool force_menu)
-{
- uiBlock *block = layout->root->block;
- uiBut *but;
- int w, h;
-
- UI_block_layout_set_current(block, layout);
-
- if (!name) {
- name = "";
- }
- if (layout->root->type == UI_LAYOUT_MENU && !icon) {
- icon = ICON_BLANK1;
- }
-
- w = ui_text_icon_width(layout, name, icon, 1);
- h = UI_UNIT_Y;
-
- if (layout->root->type == UI_LAYOUT_HEADER) { /* ugly .. */
- if (icon == ICON_NONE && force_menu) {
- /* pass */
- }
- else if (force_menu) {
- w += 0.6f * UI_UNIT_X;
- }
- else {
- if (name[0]) {
- w -= UI_UNIT_X / 2;
- }
- }
- }
-
- 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) {
- UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT);
- }
- }
- else {
- but = uiDefMenuBut(block, func, arg, name, 0, 0, w, h, tip);
- }
-
- if (argN) {
- /* ugly .. */
- if (arg != argN) {
- but->poin = (char *)but;
- }
- but->func_argN = argN;
- }
-
- if (ELEM(layout->root->type, UI_LAYOUT_PANEL, UI_LAYOUT_TOOLBAR) ||
- /* We never want a dropdown in menu! */
- (force_menu && layout->root->type != UI_LAYOUT_MENU))
- {
- UI_but_type_set_menu_from_pulldown(but);
- }
-
- return but;
+ PanelType *pt = (PanelType *)arg_pt;
+ UI_paneltype_draw(C, pt, layout);
+
+ /* panels are created flipped (from event handling pov) */
+ layout->root->block->flag ^= UI_BLOCK_IS_FLIP;
+}
+
+static uiBut *ui_item_menu(uiLayout *layout,
+ const char *name,
+ int icon,
+ uiMenuCreateFunc func,
+ void *arg,
+ void *argN,
+ const char *tip,
+ bool force_menu)
+{
+ uiBlock *block = layout->root->block;
+ uiBut *but;
+ int w, h;
+
+ UI_block_layout_set_current(block, layout);
+
+ if (!name) {
+ name = "";
+ }
+ if (layout->root->type == UI_LAYOUT_MENU && !icon) {
+ icon = ICON_BLANK1;
+ }
+
+ w = ui_text_icon_width(layout, name, icon, 1);
+ h = UI_UNIT_Y;
+
+ if (layout->root->type == UI_LAYOUT_HEADER) { /* ugly .. */
+ if (icon == ICON_NONE && force_menu) {
+ /* pass */
+ }
+ else if (force_menu) {
+ w += 0.6f * UI_UNIT_X;
+ }
+ else {
+ if (name[0]) {
+ w -= UI_UNIT_X / 2;
+ }
+ }
+ }
+
+ 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) {
+ UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT);
+ }
+ }
+ else {
+ but = uiDefMenuBut(block, func, arg, name, 0, 0, w, h, tip);
+ }
+
+ if (argN) {
+ /* ugly .. */
+ if (arg != argN) {
+ but->poin = (char *)but;
+ }
+ but->func_argN = argN;
+ }
+
+ if (ELEM(layout->root->type, UI_LAYOUT_PANEL, UI_LAYOUT_TOOLBAR) ||
+ /* We never want a dropdown in menu! */
+ (force_menu && layout->root->type != UI_LAYOUT_MENU)) {
+ UI_but_type_set_menu_from_pulldown(but);
+ }
+
+ return but;
}
void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon)
{
- MenuType *mt = WM_menutype_find(menuname, false);
- if (mt == NULL) {
- RNA_warning("not found %s", menuname);
- return;
- }
+ MenuType *mt = WM_menutype_find(menuname, false);
+ if (mt == NULL) {
+ RNA_warning("not found %s", menuname);
+ return;
+ }
- if (!name) {
- name = CTX_IFACE_(mt->translation_context, mt->label);
- }
+ if (!name) {
+ name = CTX_IFACE_(mt->translation_context, mt->label);
+ }
- if (layout->root->type == UI_LAYOUT_MENU && !icon) {
- icon = ICON_BLANK1;
- }
+ if (layout->root->type == UI_LAYOUT_MENU && !icon) {
+ icon = ICON_BLANK1;
+ }
- ui_item_menu(
- layout, name, icon, ui_item_menutype_func, mt, NULL,
- mt->description ? TIP_(mt->description) : "", false);
+ ui_item_menu(layout,
+ name,
+ icon,
+ ui_item_menutype_func,
+ mt,
+ NULL,
+ mt->description ? TIP_(mt->description) : "",
+ false);
}
void uiItemMContents(uiLayout *layout, const char *menuname)
{
- MenuType *mt = WM_menutype_find(menuname, false);
- if (mt == NULL) {
- RNA_warning("not found %s", menuname);
- return;
- }
+ MenuType *mt = WM_menutype_find(menuname, false);
+ if (mt == NULL) {
+ RNA_warning("not found %s", menuname);
+ return;
+ }
- uiBlock *block = layout->root->block;
- bContext *C = block->evil_C;
- UI_menutype_draw(C, mt, layout);
+ uiBlock *block = layout->root->block;
+ bContext *C = block->evil_C;
+ UI_menutype_draw(C, mt, layout);
}
/* popover */
-void uiItemPopoverPanel_ptr(uiLayout *layout, bContext *C, PanelType *pt, const char *name, int icon)
-{
- if (!name) {
- name = CTX_IFACE_(pt->translation_context, pt->label);
- }
-
- if (layout->root->type == UI_LAYOUT_MENU && !icon) {
- icon = ICON_BLANK1;
- }
-
- const bool ok = (pt->poll == NULL) || pt->poll(C, pt);
- if (ok && (pt->draw_header != NULL)) {
- layout = uiLayoutRow(layout, true);
- Panel panel = {
- .type = pt,
- .layout = layout,
- .flag = PNL_POPOVER,
- };
- pt->draw_header(C, &panel);
- }
- uiBut *but = ui_item_menu(layout, name, icon, ui_item_paneltype_func, pt, NULL, NULL, true);
- but->type = UI_BTYPE_POPOVER;
- if (!ok) {
- but->flag |= UI_BUT_DISABLED;
- }
+void uiItemPopoverPanel_ptr(
+ uiLayout *layout, bContext *C, PanelType *pt, const char *name, int icon)
+{
+ if (!name) {
+ name = CTX_IFACE_(pt->translation_context, pt->label);
+ }
+
+ if (layout->root->type == UI_LAYOUT_MENU && !icon) {
+ icon = ICON_BLANK1;
+ }
+
+ const bool ok = (pt->poll == NULL) || pt->poll(C, pt);
+ if (ok && (pt->draw_header != NULL)) {
+ layout = uiLayoutRow(layout, true);
+ Panel panel = {
+ .type = pt,
+ .layout = layout,
+ .flag = PNL_POPOVER,
+ };
+ pt->draw_header(C, &panel);
+ }
+ uiBut *but = ui_item_menu(layout, name, icon, ui_item_paneltype_func, pt, NULL, NULL, true);
+ but->type = UI_BTYPE_POPOVER;
+ if (!ok) {
+ but->flag |= UI_BUT_DISABLED;
+ }
}
void uiItemPopoverPanel(
- uiLayout *layout, bContext *C,
- const char *panel_type, const char *name, int icon)
-{
- PanelType *pt = WM_paneltype_find(panel_type, true);
- if (pt == NULL) {
- RNA_warning("Panel type not found '%s'", panel_type);
- return;
- }
- uiItemPopoverPanel_ptr(layout, C, pt, name, icon);
-}
-
-void uiItemPopoverPanelFromGroup(
- uiLayout *layout, bContext *C,
- int space_id, int region_id, const char *context, const char *category)
-{
- SpaceType *st = BKE_spacetype_from_id(space_id);
- if (st == NULL) {
- RNA_warning("space type not found %d", space_id);
- return;
- }
- ARegionType *art = BKE_regiontype_from_id(st, region_id);
- if (art == NULL) {
- RNA_warning("region type not found %d", region_id);
- return;
- }
-
- for (PanelType *pt = art->paneltypes.first; pt; pt = pt->next) {
- /* Causes too many panels, check context. */
- if (pt->parent_id[0] == '\0') {
- if (/* (*context == '\0') || */ STREQ(pt->context, context)) {
- if ((*category == '\0') || STREQ(pt->category, category)) {
- if (pt->poll == NULL || pt->poll(C, pt)) {
- uiItemPopoverPanel_ptr(layout, C, pt, NULL, ICON_NONE);
- }
- }
- }
- }
- }
+ uiLayout *layout, bContext *C, const char *panel_type, const char *name, int icon)
+{
+ PanelType *pt = WM_paneltype_find(panel_type, true);
+ if (pt == NULL) {
+ RNA_warning("Panel type not found '%s'", panel_type);
+ return;
+ }
+ uiItemPopoverPanel_ptr(layout, C, pt, name, icon);
+}
+
+void uiItemPopoverPanelFromGroup(uiLayout *layout,
+ bContext *C,
+ int space_id,
+ int region_id,
+ const char *context,
+ const char *category)
+{
+ SpaceType *st = BKE_spacetype_from_id(space_id);
+ if (st == NULL) {
+ RNA_warning("space type not found %d", space_id);
+ return;
+ }
+ ARegionType *art = BKE_regiontype_from_id(st, region_id);
+ if (art == NULL) {
+ RNA_warning("region type not found %d", region_id);
+ return;
+ }
+
+ for (PanelType *pt = art->paneltypes.first; pt; pt = pt->next) {
+ /* Causes too many panels, check context. */
+ if (pt->parent_id[0] == '\0') {
+ if (/* (*context == '\0') || */ STREQ(pt->context, context)) {
+ if ((*category == '\0') || STREQ(pt->category, category)) {
+ if (pt->poll == NULL || pt->poll(C, pt)) {
+ uiItemPopoverPanel_ptr(layout, C, pt, NULL, ICON_NONE);
+ }
+ }
+ }
+ }
+ }
}
-
/* label item */
static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon)
{
- uiBlock *block = layout->root->block;
- uiBut *but;
- int w;
-
- UI_block_layout_set_current(block, layout);
-
- if (!name) {
- name = "";
- }
- if (layout->root->type == UI_LAYOUT_MENU && !icon) {
- icon = ICON_BLANK1;
- }
-
- w = ui_text_icon_width(layout, name, icon, 0);
-
- if (icon && name[0]) {
- but = uiDefIconTextBut(block, UI_BTYPE_LABEL, 0, icon, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, NULL);
- }
- else if (icon) {
- but = uiDefIconBut(block, UI_BTYPE_LABEL, 0, icon, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, NULL);
- }
- else {
- but = uiDefBut(block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, NULL);
- }
-
- /* to compensate for string size padding in ui_text_icon_width,
- * make text aligned right if the layout is aligned right.
- */
- if (uiLayoutGetAlignment(layout) == UI_LAYOUT_ALIGN_RIGHT) {
- but->drawflag &= ~UI_BUT_TEXT_LEFT; /* default, needs to be unset */
- but->drawflag |= UI_BUT_TEXT_RIGHT;
- }
-
- /* Mark as a label inside a listbox. */
- if (block->flag & UI_BLOCK_LIST_ITEM) {
- but->flag |= UI_BUT_LIST_ITEM;
- }
-
- if (layout->redalert) {
- UI_but_flag_enable(but, UI_BUT_REDALERT);
- }
-
- return but;
+ uiBlock *block = layout->root->block;
+ uiBut *but;
+ int w;
+
+ UI_block_layout_set_current(block, layout);
+
+ if (!name) {
+ name = "";
+ }
+ if (layout->root->type == UI_LAYOUT_MENU && !icon) {
+ icon = ICON_BLANK1;
+ }
+
+ w = ui_text_icon_width(layout, name, icon, 0);
+
+ if (icon && name[0]) {
+ but = uiDefIconTextBut(
+ block, UI_BTYPE_LABEL, 0, icon, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, NULL);
+ }
+ else if (icon) {
+ but = uiDefIconBut(
+ block, UI_BTYPE_LABEL, 0, icon, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, NULL);
+ }
+ else {
+ but = uiDefBut(block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, NULL);
+ }
+
+ /* to compensate for string size padding in ui_text_icon_width,
+ * make text aligned right if the layout is aligned right.
+ */
+ if (uiLayoutGetAlignment(layout) == UI_LAYOUT_ALIGN_RIGHT) {
+ but->drawflag &= ~UI_BUT_TEXT_LEFT; /* default, needs to be unset */
+ but->drawflag |= UI_BUT_TEXT_RIGHT;
+ }
+
+ /* Mark as a label inside a listbox. */
+ if (block->flag & UI_BLOCK_LIST_ITEM) {
+ but->flag |= UI_BUT_LIST_ITEM;
+ }
+
+ if (layout->redalert) {
+ UI_but_flag_enable(but, UI_BUT_REDALERT);
+ }
+
+ return but;
}
void uiItemL(uiLayout *layout, const char *name, int icon)
{
- uiItemL_(layout, name, icon);
+ uiItemL_(layout, name, icon);
}
void uiItemLDrag(uiLayout *layout, PointerRNA *ptr, const char *name, int icon)
{
- uiBut *but = uiItemL_(layout, name, icon);
+ uiBut *but = uiItemL_(layout, name, icon);
- if (ptr && ptr->type) {
- if (RNA_struct_is_ID(ptr->type)) {
- UI_but_drag_set_id(but, ptr->id.data);
- }
- }
+ if (ptr && ptr->type) {
+ if (RNA_struct_is_ID(ptr->type)) {
+ UI_but_drag_set_id(but, ptr->id.data);
+ }
+ }
}
-
/* value item */
void uiItemV(uiLayout *layout, const char *name, int icon, int argval)
{
- /* label */
- uiBlock *block = layout->root->block;
- int *retvalue = (block->handle) ? &block->handle->retvalue : NULL;
- int w;
-
- UI_block_layout_set_current(block, layout);
-
- if (!name) {
- name = "";
- }
- if (layout->root->type == UI_LAYOUT_MENU && !icon) {
- icon = ICON_BLANK1;
- }
-
- w = ui_text_icon_width(layout, name, icon, 0);
-
- if (icon && name[0]) {
- uiDefIconTextButI(block, UI_BTYPE_BUT, argval, icon, name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, -1, "");
- }
- else if (icon) {
- uiDefIconButI(block, UI_BTYPE_BUT, argval, icon, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, -1, "");
- }
- else {
- uiDefButI(block, UI_BTYPE_BUT, argval, name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, -1, "");
- }
+ /* label */
+ uiBlock *block = layout->root->block;
+ int *retvalue = (block->handle) ? &block->handle->retvalue : NULL;
+ int w;
+
+ UI_block_layout_set_current(block, layout);
+
+ if (!name) {
+ name = "";
+ }
+ if (layout->root->type == UI_LAYOUT_MENU && !icon) {
+ icon = ICON_BLANK1;
+ }
+
+ w = ui_text_icon_width(layout, name, icon, 0);
+
+ if (icon && name[0]) {
+ uiDefIconTextButI(block,
+ UI_BTYPE_BUT,
+ argval,
+ icon,
+ name,
+ 0,
+ 0,
+ w,
+ UI_UNIT_Y,
+ retvalue,
+ 0.0,
+ 0.0,
+ 0,
+ -1,
+ "");
+ }
+ else if (icon) {
+ uiDefIconButI(
+ block, UI_BTYPE_BUT, argval, icon, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, -1, "");
+ }
+ else {
+ uiDefButI(
+ block, UI_BTYPE_BUT, argval, name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, -1, "");
+ }
}
/* separator item */
void uiItemS_ex(uiLayout *layout, float factor)
{
- uiBlock *block = layout->root->block;
- bool is_menu = ui_block_is_menu(block);
- int space = (is_menu) ? 0.45f * UI_UNIT_X : 0.3f * UI_UNIT_X;
- space *= factor;
-
- UI_block_layout_set_current(block, layout);
- uiDefBut(block, (is_menu) ? UI_BTYPE_SEPR_LINE : UI_BTYPE_SEPR, 0, "", 0, 0, space, space, NULL, 0.0, 0.0, 0, 0, "");
+ uiBlock *block = layout->root->block;
+ bool is_menu = ui_block_is_menu(block);
+ int space = (is_menu) ? 0.45f * UI_UNIT_X : 0.3f * UI_UNIT_X;
+ space *= factor;
+
+ UI_block_layout_set_current(block, layout);
+ uiDefBut(block,
+ (is_menu) ? UI_BTYPE_SEPR_LINE : UI_BTYPE_SEPR,
+ 0,
+ "",
+ 0,
+ 0,
+ space,
+ space,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
}
/* separator item */
void uiItemS(uiLayout *layout)
{
- uiItemS_ex(layout, 1.0f);
+ uiItemS_ex(layout, 1.0f);
}
/* Flexible spacing. */
void uiItemSpacer(uiLayout *layout)
{
- uiBlock *block = layout->root->block;
- const bool is_popup = ui_block_is_popup_any(block);
-
- if (is_popup) {
- printf("Error: separator_spacer() not supported in popups.\n");
- return;
- }
-
- if (block->direction & UI_DIR_RIGHT) {
- printf("Error: separator_spacer() only supported in horizontal blocks.\n");
- return;
- }
-
- UI_block_layout_set_current(block, layout);
- uiDefBut(block, UI_BTYPE_SEPR_SPACER, 0, "", 0, 0, 0.3f * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiBlock *block = layout->root->block;
+ const bool is_popup = ui_block_is_popup_any(block);
+
+ if (is_popup) {
+ printf("Error: separator_spacer() not supported in popups.\n");
+ return;
+ }
+
+ if (block->direction & UI_DIR_RIGHT) {
+ printf("Error: separator_spacer() only supported in horizontal blocks.\n");
+ return;
+ }
+
+ UI_block_layout_set_current(block, layout);
+ uiDefBut(block,
+ UI_BTYPE_SEPR_SPACER,
+ 0,
+ "",
+ 0,
+ 0,
+ 0.3f * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
}
/* level items */
void uiItemMenuF(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg)
{
- if (!func) {
- return;
- }
+ if (!func) {
+ return;
+ }
- ui_item_menu(layout, name, icon, func, arg, NULL, "", false);
+ ui_item_menu(layout, name, icon, func, arg, NULL, "", false);
}
/**
@@ -2683,142 +3029,159 @@ void uiItemMenuF(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc
*/
void uiItemMenuFN(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *argN)
{
- if (!func) {
- return;
- }
+ if (!func) {
+ return;
+ }
- /* Second 'argN' only ensures it gets freed. */
- ui_item_menu(layout, name, icon, func, argN, argN, "", false);
+ /* Second 'argN' only ensures it gets freed. */
+ ui_item_menu(layout, name, icon, func, argN, argN, "", false);
}
typedef struct MenuItemLevel {
- int opcontext;
- /* don't use pointers to the strings because python can dynamically
- * allocate strings and free before the menu draws, see [#27304] */
- char opname[OP_MAX_TYPENAME];
- char propname[MAX_IDPROP_NAME];
- PointerRNA rnapoin;
+ int opcontext;
+ /* don't use pointers to the strings because python can dynamically
+ * allocate strings and free before the menu draws, see [#27304] */
+ char opname[OP_MAX_TYPENAME];
+ char propname[MAX_IDPROP_NAME];
+ PointerRNA rnapoin;
} MenuItemLevel;
static void menu_item_enum_opname_menu(bContext *UNUSED(C), uiLayout *layout, void *arg)
{
- MenuItemLevel *lvl = (MenuItemLevel *)(((uiBut *)arg)->func_argN);
+ MenuItemLevel *lvl = (MenuItemLevel *)(((uiBut *)arg)->func_argN);
- uiLayoutSetOperatorContext(layout, lvl->opcontext);
- uiItemsEnumO(layout, lvl->opname, lvl->propname);
+ uiLayoutSetOperatorContext(layout, lvl->opcontext);
+ uiItemsEnumO(layout, lvl->opname, lvl->propname);
- layout->root->block->flag |= UI_BLOCK_IS_FLIP;
+ layout->root->block->flag |= UI_BLOCK_IS_FLIP;
- /* override default, needed since this was assumed pre 2.70 */
- UI_block_direction_set(layout->root->block, UI_DIR_DOWN);
+ /* override default, needed since this was assumed pre 2.70 */
+ UI_block_direction_set(layout->root->block, UI_DIR_DOWN);
}
-void uiItemMenuEnumO_ptr(
- uiLayout *layout, bContext *C, wmOperatorType *ot, const char *propname,
- const char *name, int icon)
+void uiItemMenuEnumO_ptr(uiLayout *layout,
+ bContext *C,
+ wmOperatorType *ot,
+ const char *propname,
+ const char *name,
+ int icon)
{
- MenuItemLevel *lvl;
- uiBut *but;
+ MenuItemLevel *lvl;
+ uiBut *but;
- /* Caller must check */
- BLI_assert(ot->srna != NULL);
+ /* Caller must check */
+ BLI_assert(ot->srna != NULL);
- if (name == NULL) {
- name = RNA_struct_ui_name(ot->srna);
- }
+ if (name == NULL) {
+ name = RNA_struct_ui_name(ot->srna);
+ }
- if (layout->root->type == UI_LAYOUT_MENU && !icon) {
- icon = ICON_BLANK1;
- }
+ if (layout->root->type == UI_LAYOUT_MENU && !icon) {
+ icon = ICON_BLANK1;
+ }
- lvl = MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
- BLI_strncpy(lvl->opname, ot->idname, sizeof(lvl->opname));
- BLI_strncpy(lvl->propname, propname, sizeof(lvl->propname));
- lvl->opcontext = layout->root->opcontext;
+ lvl = MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
+ BLI_strncpy(lvl->opname, ot->idname, sizeof(lvl->opname));
+ BLI_strncpy(lvl->propname, propname, sizeof(lvl->propname));
+ lvl->opcontext = layout->root->opcontext;
- but = ui_item_menu(
- layout, name, icon, menu_item_enum_opname_menu, NULL, lvl,
- RNA_struct_ui_description(ot->srna), true);
+ but = ui_item_menu(layout,
+ name,
+ icon,
+ menu_item_enum_opname_menu,
+ NULL,
+ lvl,
+ RNA_struct_ui_description(ot->srna),
+ true);
- /* add hotkey here, lower UI code can't detect it */
- if ((layout->root->block->flag & UI_BLOCK_LOOP) &&
- (ot->prop && ot->invoke))
- {
- char keybuf[128];
- if (WM_key_event_operator_string(
- C, ot->idname, layout->root->opcontext, NULL, false,
- keybuf, sizeof(keybuf)))
- {
- ui_but_add_shortcut(but, keybuf, false);
- }
- }
+ /* add hotkey here, lower UI code can't detect it */
+ if ((layout->root->block->flag & UI_BLOCK_LOOP) && (ot->prop && ot->invoke)) {
+ char keybuf[128];
+ if (WM_key_event_operator_string(
+ C, ot->idname, layout->root->opcontext, NULL, false, keybuf, sizeof(keybuf))) {
+ ui_but_add_shortcut(but, keybuf, false);
+ }
+ }
}
-void uiItemMenuEnumO(
- uiLayout *layout, bContext *C, const char *opname, const char *propname,
- const char *name, int icon)
+void uiItemMenuEnumO(uiLayout *layout,
+ bContext *C,
+ const char *opname,
+ const char *propname,
+ const char *name,
+ int icon)
{
- wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
+ wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
- UI_OPERATOR_ERROR_RET(ot, opname, return);
+ UI_OPERATOR_ERROR_RET(ot, opname, return );
- if (!ot->srna) {
- ui_item_disabled(layout, opname);
- RNA_warning("operator missing srna '%s'", opname);
- return;
- }
+ if (!ot->srna) {
+ ui_item_disabled(layout, opname);
+ RNA_warning("operator missing srna '%s'", opname);
+ return;
+ }
- uiItemMenuEnumO_ptr(layout, C, ot, propname, name, icon);
+ uiItemMenuEnumO_ptr(layout, C, ot, propname, name, icon);
}
static void menu_item_enum_rna_menu(bContext *UNUSED(C), uiLayout *layout, void *arg)
{
- MenuItemLevel *lvl = (MenuItemLevel *)(((uiBut *)arg)->func_argN);
+ MenuItemLevel *lvl = (MenuItemLevel *)(((uiBut *)arg)->func_argN);
- uiLayoutSetOperatorContext(layout, lvl->opcontext);
- uiItemsEnumR(layout, &lvl->rnapoin, lvl->propname);
- layout->root->block->flag |= UI_BLOCK_IS_FLIP;
+ uiLayoutSetOperatorContext(layout, lvl->opcontext);
+ uiItemsEnumR(layout, &lvl->rnapoin, lvl->propname);
+ layout->root->block->flag |= UI_BLOCK_IS_FLIP;
}
-void uiItemMenuEnumR_prop(uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, const char *name, int icon)
+void uiItemMenuEnumR_prop(
+ uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, const char *name, int icon)
{
- MenuItemLevel *lvl;
+ MenuItemLevel *lvl;
- if (!name) {
- name = RNA_property_ui_name(prop);
- }
- if (layout->root->type == UI_LAYOUT_MENU && !icon) {
- icon = ICON_BLANK1;
- }
+ if (!name) {
+ name = RNA_property_ui_name(prop);
+ }
+ if (layout->root->type == UI_LAYOUT_MENU && !icon) {
+ icon = ICON_BLANK1;
+ }
- lvl = MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
- lvl->rnapoin = *ptr;
- BLI_strncpy(lvl->propname, RNA_property_identifier(prop), sizeof(lvl->propname));
- lvl->opcontext = layout->root->opcontext;
+ lvl = MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
+ lvl->rnapoin = *ptr;
+ BLI_strncpy(lvl->propname, RNA_property_identifier(prop), sizeof(lvl->propname));
+ lvl->opcontext = layout->root->opcontext;
- ui_item_menu(layout, name, icon, menu_item_enum_rna_menu, NULL, lvl, RNA_property_description(prop), false);
+ ui_item_menu(layout,
+ name,
+ icon,
+ menu_item_enum_rna_menu,
+ NULL,
+ lvl,
+ RNA_property_description(prop),
+ false);
}
-void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon)
+void uiItemMenuEnumR(
+ uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- 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;
- }
+ 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;
+ }
- uiItemMenuEnumR_prop(layout, ptr, prop, name, icon);
+ uiItemMenuEnumR_prop(layout, ptr, prop, name, icon);
}
-void uiItemTabsEnumR_prop(uiLayout *layout, bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool icon_only)
+void uiItemTabsEnumR_prop(
+ uiLayout *layout, bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool icon_only)
{
- uiBlock *block = layout->root->block;
+ uiBlock *block = layout->root->block;
- UI_block_layout_set_current(block, layout);
- ui_item_enum_expand_tabs(layout, C, block, ptr, prop, NULL, UI_UNIT_Y, icon_only);
+ UI_block_layout_set_current(block, layout);
+ ui_item_enum_expand_tabs(layout, C, block, ptr, prop, NULL, UI_UNIT_Y, icon_only);
}
/**************************** Layout Items ***************************/
@@ -2826,1235 +3189,1248 @@ void uiItemTabsEnumR_prop(uiLayout *layout, bContext *C, PointerRNA *ptr, Proper
/* single-row layout */
static void ui_litem_estimate_row(uiLayout *litem)
{
- uiItem *item;
- int itemw, itemh;
- bool min_size_flag = true;
+ uiItem *item;
+ int itemw, itemh;
+ bool min_size_flag = true;
- litem->w = 0;
- litem->h = 0;
+ litem->w = 0;
+ litem->h = 0;
- for (item = litem->items.first; item; item = item->next) {
- ui_item_size(item, &itemw, &itemh);
+ for (item = litem->items.first; item; item = item->next) {
+ ui_item_size(item, &itemw, &itemh);
- min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN);
+ min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN);
- litem->w += itemw;
- litem->h = MAX2(itemh, litem->h);
+ litem->w += itemw;
+ litem->h = MAX2(itemh, litem->h);
- if (item->next) {
- litem->w += litem->space;
- }
- }
+ if (item->next) {
+ litem->w += litem->space;
+ }
+ }
- if (min_size_flag) {
- litem->item.flag |= UI_ITEM_MIN;
- }
+ if (min_size_flag) {
+ litem->item.flag |= UI_ITEM_MIN;
+ }
}
static int ui_litem_min_width(int itemw)
{
- return MIN2(2 * UI_UNIT_X, itemw);
+ return MIN2(2 * UI_UNIT_X, itemw);
}
static void ui_litem_layout_row(uiLayout *litem)
{
- uiItem *item, *last_free_item = NULL;
- int x, y, w, tot, totw, neww, newtotw, itemw, minw, itemh, offset;
- int fixedw, freew, fixedx, freex, flag = 0, lastw = 0;
- float extra_pixel;
-
- /* x = litem->x; */ /* UNUSED */
- y = litem->y;
- w = litem->w;
- totw = 0;
- tot = 0;
-
- for (item = litem->items.first; item; item = item->next) {
- ui_item_size(item, &itemw, &itemh);
- totw += itemw;
- tot++;
- }
-
- if (totw == 0) {
- return;
- }
-
- if (w != 0) {
- w -= (tot - 1) * litem->space;
- }
- fixedw = 0;
-
- /* keep clamping items to fixed minimum size until all are done */
- do {
- freew = 0;
- x = 0;
- flag = 0;
- newtotw = totw;
- extra_pixel = 0.0f;
-
- for (item = litem->items.first; item; item = item->next) {
- if (item->flag & UI_ITEM_FIXED) {
- continue;
- }
-
- ui_item_size(item, &itemw, &itemh);
- minw = ui_litem_min_width(itemw);
-
- if (w - lastw > 0) {
- neww = ui_item_fit(itemw, x, totw, w - lastw, !item->next, litem->alignment, &extra_pixel);
- }
- else {
- neww = 0; /* no space left, all will need clamping to minimum size */
- }
-
- x += neww;
-
- bool min_flag = item->flag & UI_ITEM_MIN;
- /* ignore min flag for rows with right or center alignment */
- if (item->type != ITEM_BUTTON &&
- ELEM(((uiLayout *)item)->alignment, UI_LAYOUT_ALIGN_RIGHT, UI_LAYOUT_ALIGN_CENTER) &&
- litem->alignment == UI_LAYOUT_ALIGN_EXPAND &&
- ((uiItem *)litem)->flag & UI_ITEM_MIN)
- {
- min_flag = false;
- }
-
- if ((neww < minw || min_flag) && w != 0) {
- /* fixed size */
- item->flag |= UI_ITEM_FIXED;
- if (item->type != ITEM_BUTTON && item->flag & UI_ITEM_MIN) {
- minw = itemw;
- }
- fixedw += minw;
- flag = 1;
- newtotw -= itemw;
- }
- else {
- /* keep free size */
- item->flag &= ~UI_ITEM_FIXED;
- freew += itemw;
- }
- }
-
- totw = newtotw;
- lastw = fixedw;
- } while (flag);
-
- freex = 0;
- fixedx = 0;
- extra_pixel = 0.0f;
- x = litem->x;
-
- for (item = litem->items.first; item; item = item->next) {
- ui_item_size(item, &itemw, &itemh);
- minw = ui_litem_min_width(itemw);
-
- if (item->flag & UI_ITEM_FIXED) {
- /* fixed minimum size items */
- if (item->type != ITEM_BUTTON && item->flag & UI_ITEM_MIN) {
- minw = itemw;
- }
- itemw = ui_item_fit(minw, fixedx, fixedw, min_ii(w, fixedw), !item->next, litem->alignment, &extra_pixel);
- fixedx += itemw;
- }
- else {
- /* free size item */
- itemw = ui_item_fit(itemw, freex, freew, w - fixedw, !item->next, litem->alignment, &extra_pixel);
- freex += itemw;
- last_free_item = item;
- }
-
- /* align right/center */
- offset = 0;
- if (litem->alignment == UI_LAYOUT_ALIGN_RIGHT) {
- if (freew + fixedw > 0 && freew + fixedw < w) {
- offset = w - (fixedw + freew);
- }
- }
- else if (litem->alignment == UI_LAYOUT_ALIGN_CENTER) {
- if (freew + fixedw > 0 && freew + fixedw < w) {
- offset = (w - (fixedw + freew)) / 2;
- }
- }
-
- /* position item */
- ui_item_position(item, x + offset, y - itemh, itemw, itemh);
-
- x += itemw;
- if (item->next) {
- x += litem->space;
- }
- }
-
- /* add extra pixel */
- uiItem *last_item = litem->items.last;
- extra_pixel = litem->w - (x - litem->x);
- if (extra_pixel > 0 && litem->alignment == UI_LAYOUT_ALIGN_EXPAND &&
- last_free_item && last_item && last_item->flag & UI_ITEM_FIXED)
- {
- ui_item_move(last_free_item, 0, extra_pixel);
- for (item = last_free_item->next; item; item = item->next) {
- ui_item_move(item, extra_pixel, extra_pixel);
- }
- }
-
- litem->w = x - litem->x;
- litem->h = litem->y - y;
- litem->x = x;
- litem->y = y;
+ uiItem *item, *last_free_item = NULL;
+ int x, y, w, tot, totw, neww, newtotw, itemw, minw, itemh, offset;
+ int fixedw, freew, fixedx, freex, flag = 0, lastw = 0;
+ float extra_pixel;
+
+ /* x = litem->x; */ /* UNUSED */
+ y = litem->y;
+ w = litem->w;
+ totw = 0;
+ tot = 0;
+
+ for (item = litem->items.first; item; item = item->next) {
+ ui_item_size(item, &itemw, &itemh);
+ totw += itemw;
+ tot++;
+ }
+
+ if (totw == 0) {
+ return;
+ }
+
+ if (w != 0) {
+ w -= (tot - 1) * litem->space;
+ }
+ fixedw = 0;
+
+ /* keep clamping items to fixed minimum size until all are done */
+ do {
+ freew = 0;
+ x = 0;
+ flag = 0;
+ newtotw = totw;
+ extra_pixel = 0.0f;
+
+ for (item = litem->items.first; item; item = item->next) {
+ if (item->flag & UI_ITEM_FIXED) {
+ continue;
+ }
+
+ ui_item_size(item, &itemw, &itemh);
+ minw = ui_litem_min_width(itemw);
+
+ if (w - lastw > 0) {
+ neww = ui_item_fit(itemw, x, totw, w - lastw, !item->next, litem->alignment, &extra_pixel);
+ }
+ else {
+ neww = 0; /* no space left, all will need clamping to minimum size */
+ }
+
+ x += neww;
+
+ bool min_flag = item->flag & UI_ITEM_MIN;
+ /* ignore min flag for rows with right or center alignment */
+ if (item->type != ITEM_BUTTON &&
+ ELEM(((uiLayout *)item)->alignment, UI_LAYOUT_ALIGN_RIGHT, UI_LAYOUT_ALIGN_CENTER) &&
+ litem->alignment == UI_LAYOUT_ALIGN_EXPAND && ((uiItem *)litem)->flag & UI_ITEM_MIN) {
+ min_flag = false;
+ }
+
+ if ((neww < minw || min_flag) && w != 0) {
+ /* fixed size */
+ item->flag |= UI_ITEM_FIXED;
+ if (item->type != ITEM_BUTTON && item->flag & UI_ITEM_MIN) {
+ minw = itemw;
+ }
+ fixedw += minw;
+ flag = 1;
+ newtotw -= itemw;
+ }
+ else {
+ /* keep free size */
+ item->flag &= ~UI_ITEM_FIXED;
+ freew += itemw;
+ }
+ }
+
+ totw = newtotw;
+ lastw = fixedw;
+ } while (flag);
+
+ freex = 0;
+ fixedx = 0;
+ extra_pixel = 0.0f;
+ x = litem->x;
+
+ for (item = litem->items.first; item; item = item->next) {
+ ui_item_size(item, &itemw, &itemh);
+ minw = ui_litem_min_width(itemw);
+
+ if (item->flag & UI_ITEM_FIXED) {
+ /* fixed minimum size items */
+ if (item->type != ITEM_BUTTON && item->flag & UI_ITEM_MIN) {
+ minw = itemw;
+ }
+ itemw = ui_item_fit(
+ minw, fixedx, fixedw, min_ii(w, fixedw), !item->next, litem->alignment, &extra_pixel);
+ fixedx += itemw;
+ }
+ else {
+ /* free size item */
+ itemw = ui_item_fit(
+ itemw, freex, freew, w - fixedw, !item->next, litem->alignment, &extra_pixel);
+ freex += itemw;
+ last_free_item = item;
+ }
+
+ /* align right/center */
+ offset = 0;
+ if (litem->alignment == UI_LAYOUT_ALIGN_RIGHT) {
+ if (freew + fixedw > 0 && freew + fixedw < w) {
+ offset = w - (fixedw + freew);
+ }
+ }
+ else if (litem->alignment == UI_LAYOUT_ALIGN_CENTER) {
+ if (freew + fixedw > 0 && freew + fixedw < w) {
+ offset = (w - (fixedw + freew)) / 2;
+ }
+ }
+
+ /* position item */
+ ui_item_position(item, x + offset, y - itemh, itemw, itemh);
+
+ x += itemw;
+ if (item->next) {
+ x += litem->space;
+ }
+ }
+
+ /* add extra pixel */
+ uiItem *last_item = litem->items.last;
+ extra_pixel = litem->w - (x - litem->x);
+ if (extra_pixel > 0 && litem->alignment == UI_LAYOUT_ALIGN_EXPAND && last_free_item &&
+ last_item && last_item->flag & UI_ITEM_FIXED) {
+ ui_item_move(last_free_item, 0, extra_pixel);
+ for (item = last_free_item->next; item; item = item->next) {
+ ui_item_move(item, extra_pixel, extra_pixel);
+ }
+ }
+
+ litem->w = x - litem->x;
+ litem->h = litem->y - y;
+ litem->x = x;
+ litem->y = y;
}
/* single-column layout */
static void ui_litem_estimate_column(uiLayout *litem, bool is_box)
{
- uiItem *item;
- int itemw, itemh;
- bool min_size_flag = true;
+ uiItem *item;
+ int itemw, itemh;
+ bool min_size_flag = true;
- litem->w = 0;
- litem->h = 0;
+ litem->w = 0;
+ litem->h = 0;
- for (item = litem->items.first; item; item = item->next) {
- ui_item_size(item, &itemw, &itemh);
+ for (item = litem->items.first; item; item = item->next) {
+ ui_item_size(item, &itemw, &itemh);
- min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN);
+ min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN);
- litem->w = MAX2(litem->w, itemw);
- litem->h += itemh;
+ litem->w = MAX2(litem->w, itemw);
+ litem->h += itemh;
- if (item->next && (!is_box || item != litem->items.first)) {
- litem->h += litem->space;
- }
- }
+ if (item->next && (!is_box || item != litem->items.first)) {
+ litem->h += litem->space;
+ }
+ }
- if (min_size_flag) {
- litem->item.flag |= UI_ITEM_MIN;
- }
+ if (min_size_flag) {
+ litem->item.flag |= UI_ITEM_MIN;
+ }
}
static void ui_litem_layout_column(uiLayout *litem, bool is_box)
{
- uiItem *item;
- int itemh, x, y;
+ uiItem *item;
+ int itemh, x, y;
- x = litem->x;
- y = litem->y;
+ x = litem->x;
+ y = litem->y;
- for (item = litem->items.first; item; item = item->next) {
- ui_item_size(item, NULL, &itemh);
+ for (item = litem->items.first; item; item = item->next) {
+ ui_item_size(item, NULL, &itemh);
- y -= itemh;
- ui_item_position(item, x, y, litem->w, itemh);
+ y -= itemh;
+ ui_item_position(item, x, y, litem->w, itemh);
- if (item->next && (!is_box || item != litem->items.first)) {
- y -= litem->space;
- }
+ if (item->next && (!is_box || item != litem->items.first)) {
+ y -= litem->space;
+ }
- if (is_box) {
- item->flag |= UI_ITEM_BOX_ITEM;
- }
- }
+ if (is_box) {
+ item->flag |= UI_ITEM_BOX_ITEM;
+ }
+ }
- litem->h = litem->y - y;
- litem->x = x;
- litem->y = y;
+ litem->h = litem->y - y;
+ litem->x = x;
+ litem->y = y;
}
/* calculates the angle of a specified button in a radial menu,
* stores a float vector in unit circle */
static RadialDirection ui_get_radialbut_vec(float vec[2], short itemnum)
{
- RadialDirection dir;
+ RadialDirection dir;
- if (itemnum >= PIE_MAX_ITEMS) {
- itemnum %= PIE_MAX_ITEMS;
- printf("Warning: Pie menus with more than %i items are currently unsupported\n", PIE_MAX_ITEMS);
- }
+ if (itemnum >= PIE_MAX_ITEMS) {
+ itemnum %= PIE_MAX_ITEMS;
+ printf("Warning: Pie menus with more than %i items are currently unsupported\n",
+ PIE_MAX_ITEMS);
+ }
- dir = ui_radial_dir_order[itemnum];
- ui_but_pie_dir(dir, vec);
+ dir = ui_radial_dir_order[itemnum];
+ ui_but_pie_dir(dir, vec);
- return dir;
+ return dir;
}
static bool ui_item_is_radial_displayable(uiItem *item)
{
- if ((item->type == ITEM_BUTTON) && (((uiButtonItem *)item)->but->type == UI_BTYPE_LABEL)) {
- return false;
- }
+ if ((item->type == ITEM_BUTTON) && (((uiButtonItem *)item)->but->type == UI_BTYPE_LABEL)) {
+ return false;
+ }
- return true;
+ return true;
}
static bool ui_item_is_radial_drawable(uiButtonItem *bitem)
{
- if (ELEM(bitem->but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_SEPR_SPACER)) {
- return false;
- }
+ if (ELEM(bitem->but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_SEPR_SPACER)) {
+ return false;
+ }
- return true;
+ return true;
}
static void ui_litem_layout_radial(uiLayout *litem)
{
- uiItem *item;
- int itemh, itemw, x, y;
- int itemnum = 0;
- int totitems = 0;
-
- /* For the radial layout we will use Matt Ebb's design
- * for radiation, see http://mattebb.com/weblog/radiation/
- * also the old code at http://developer.blender.org/T5103
- */
-
- int pie_radius = U.pie_menu_radius * UI_DPI_FAC;
-
- x = litem->x;
- y = litem->y;
-
- int minx = x, miny = y, maxx = x, maxy = y;
-
- /* first count total items */
- for (item = litem->items.first; item; item = item->next) {
- totitems++;
- }
-
- if (totitems < 5) {
- litem->root->block->pie_data.flags |= UI_PIE_DEGREES_RANGE_LARGE;
- }
-
- for (item = litem->items.first; item; item = item->next) {
- /* not all button types are drawn in a radial menu, do filtering here */
- if (ui_item_is_radial_displayable(item)) {
- RadialDirection dir;
- float vec[2];
- float factor[2];
-
- dir = ui_get_radialbut_vec(vec, itemnum);
- factor[0] = (vec[0] > 0.01f) ? 0.0f : ((vec[0] < -0.01f) ? -1.0f : -0.5f);
- factor[1] = (vec[1] > 0.99f) ? 0.0f : ((vec[1] < -0.99f) ? -1.0f : -0.5f);
-
- itemnum++;
-
- if (item->type == ITEM_BUTTON) {
- uiButtonItem *bitem = (uiButtonItem *) item;
-
- bitem->but->pie_dir = dir;
- /* scale the buttons */
- bitem->but->rect.ymax *= 1.5f;
- /* add a little bit more here to include number */
- bitem->but->rect.xmax += 1.5f * UI_UNIT_X;
- /* enable drawing as pie item if supported by widget */
- if (ui_item_is_radial_drawable(bitem)) {
- bitem->but->dt = UI_EMBOSS_RADIAL;
- bitem->but->drawflag |= UI_BUT_ICON_LEFT;
- }
- }
-
- ui_item_size(item, &itemw, &itemh);
-
- ui_item_position(item, x + vec[0] * pie_radius + factor[0] * itemw, y + vec[1] * pie_radius + factor[1] * itemh, itemw, itemh);
-
- minx = min_ii(minx, x + vec[0] * pie_radius - itemw / 2);
- maxx = max_ii(maxx, x + vec[0] * pie_radius + itemw / 2);
- miny = min_ii(miny, y + vec[1] * pie_radius - itemh / 2);
- maxy = max_ii(maxy, y + vec[1] * pie_radius + itemh / 2);
- }
- }
-
- litem->x = minx;
- litem->y = miny;
- litem->w = maxx - minx;
- litem->h = maxy - miny;
+ uiItem *item;
+ int itemh, itemw, x, y;
+ int itemnum = 0;
+ int totitems = 0;
+
+ /* For the radial layout we will use Matt Ebb's design
+ * for radiation, see http://mattebb.com/weblog/radiation/
+ * also the old code at http://developer.blender.org/T5103
+ */
+
+ int pie_radius = U.pie_menu_radius * UI_DPI_FAC;
+
+ x = litem->x;
+ y = litem->y;
+
+ int minx = x, miny = y, maxx = x, maxy = y;
+
+ /* first count total items */
+ for (item = litem->items.first; item; item = item->next) {
+ totitems++;
+ }
+
+ if (totitems < 5) {
+ litem->root->block->pie_data.flags |= UI_PIE_DEGREES_RANGE_LARGE;
+ }
+
+ for (item = litem->items.first; item; item = item->next) {
+ /* not all button types are drawn in a radial menu, do filtering here */
+ if (ui_item_is_radial_displayable(item)) {
+ RadialDirection dir;
+ float vec[2];
+ float factor[2];
+
+ dir = ui_get_radialbut_vec(vec, itemnum);
+ factor[0] = (vec[0] > 0.01f) ? 0.0f : ((vec[0] < -0.01f) ? -1.0f : -0.5f);
+ factor[1] = (vec[1] > 0.99f) ? 0.0f : ((vec[1] < -0.99f) ? -1.0f : -0.5f);
+
+ itemnum++;
+
+ if (item->type == ITEM_BUTTON) {
+ uiButtonItem *bitem = (uiButtonItem *)item;
+
+ bitem->but->pie_dir = dir;
+ /* scale the buttons */
+ bitem->but->rect.ymax *= 1.5f;
+ /* add a little bit more here to include number */
+ bitem->but->rect.xmax += 1.5f * UI_UNIT_X;
+ /* enable drawing as pie item if supported by widget */
+ if (ui_item_is_radial_drawable(bitem)) {
+ bitem->but->dt = UI_EMBOSS_RADIAL;
+ bitem->but->drawflag |= UI_BUT_ICON_LEFT;
+ }
+ }
+
+ ui_item_size(item, &itemw, &itemh);
+
+ ui_item_position(item,
+ x + vec[0] * pie_radius + factor[0] * itemw,
+ y + vec[1] * pie_radius + factor[1] * itemh,
+ itemw,
+ itemh);
+
+ minx = min_ii(minx, x + vec[0] * pie_radius - itemw / 2);
+ maxx = max_ii(maxx, x + vec[0] * pie_radius + itemw / 2);
+ miny = min_ii(miny, y + vec[1] * pie_radius - itemh / 2);
+ maxy = max_ii(maxy, y + vec[1] * pie_radius + itemh / 2);
+ }
+ }
+
+ litem->x = minx;
+ litem->y = miny;
+ litem->w = maxx - minx;
+ litem->h = maxy - miny;
}
/* root layout */
static void ui_litem_estimate_root(uiLayout *UNUSED(litem))
{
- /* nothing to do */
+ /* nothing to do */
}
static void ui_litem_layout_root_radial(uiLayout *litem)
{
- /* first item is pie menu title, align on center of menu */
- uiItem *item = litem->items.first;
+ /* first item is pie menu title, align on center of menu */
+ uiItem *item = litem->items.first;
- if (item->type == ITEM_BUTTON) {
- int itemh, itemw, x, y;
- x = litem->x;
- y = litem->y;
+ if (item->type == ITEM_BUTTON) {
+ int itemh, itemw, x, y;
+ x = litem->x;
+ y = litem->y;
- ui_item_size(item, &itemw, &itemh);
+ ui_item_size(item, &itemw, &itemh);
- ui_item_position(item, x - itemw / 2, y + U.dpi_fac * (U.pie_menu_threshold + 9.0f), itemw, itemh);
- }
+ ui_item_position(
+ item, x - itemw / 2, y + U.dpi_fac * (U.pie_menu_threshold + 9.0f), itemw, itemh);
+ }
}
static void ui_litem_layout_root(uiLayout *litem)
{
- if (litem->root->type == UI_LAYOUT_HEADER) {
- ui_litem_layout_row(litem);
- }
- else if (litem->root->type == UI_LAYOUT_PIEMENU) {
- ui_litem_layout_root_radial(litem);
- }
- else {
- ui_litem_layout_column(litem, false);
- }
+ if (litem->root->type == UI_LAYOUT_HEADER) {
+ ui_litem_layout_row(litem);
+ }
+ else if (litem->root->type == UI_LAYOUT_PIEMENU) {
+ ui_litem_layout_root_radial(litem);
+ }
+ else {
+ ui_litem_layout_column(litem, false);
+ }
}
/* box layout */
static void ui_litem_estimate_box(uiLayout *litem)
{
- uiStyle *style = litem->root->style;
+ uiStyle *style = litem->root->style;
- ui_litem_estimate_column(litem, true);
- litem->w += 2 * style->boxspace;
- litem->h += 2 * style->boxspace;
+ ui_litem_estimate_column(litem, true);
+ litem->w += 2 * style->boxspace;
+ litem->h += 2 * style->boxspace;
}
static void ui_litem_layout_box(uiLayout *litem)
{
- uiLayoutItemBx *box = (uiLayoutItemBx *)litem;
- uiStyle *style = litem->root->style;
- uiBut *but;
- int w, h;
+ uiLayoutItemBx *box = (uiLayoutItemBx *)litem;
+ uiStyle *style = litem->root->style;
+ uiBut *but;
+ int w, h;
- w = litem->w;
- h = litem->h;
+ w = litem->w;
+ h = litem->h;
- litem->x += style->boxspace;
- litem->y -= style->boxspace;
+ litem->x += style->boxspace;
+ litem->y -= style->boxspace;
- if (w != 0) {
- litem->w -= 2 * style->boxspace;
- }
- if (h != 0) {
- litem->h -= 2 * style->boxspace;
- }
+ if (w != 0) {
+ litem->w -= 2 * style->boxspace;
+ }
+ if (h != 0) {
+ litem->h -= 2 * style->boxspace;
+ }
- ui_litem_layout_column(litem, true);
+ ui_litem_layout_column(litem, true);
- litem->x -= style->boxspace;
- litem->y -= style->boxspace;
+ litem->x -= style->boxspace;
+ litem->y -= style->boxspace;
- if (w != 0) {
- litem->w += 2 * style->boxspace;
- }
- if (h != 0) {
- litem->h += 2 * style->boxspace;
- }
+ if (w != 0) {
+ litem->w += 2 * style->boxspace;
+ }
+ if (h != 0) {
+ litem->h += 2 * style->boxspace;
+ }
- /* roundbox around the sublayout */
- but = box->roundbox;
- but->rect.xmin = litem->x;
- but->rect.ymin = litem->y;
- but->rect.xmax = litem->x + litem->w;
- but->rect.ymax = litem->y + litem->h;
+ /* roundbox around the sublayout */
+ but = box->roundbox;
+ but->rect.xmin = litem->x;
+ but->rect.ymin = litem->y;
+ but->rect.xmax = litem->x + litem->w;
+ but->rect.ymax = litem->y + litem->h;
}
/* multi-column layout, automatically flowing to the next */
static void ui_litem_estimate_column_flow(uiLayout *litem)
{
- uiStyle *style = litem->root->style;
- uiLayoutItemFlow *flow = (uiLayoutItemFlow *)litem;
- uiItem *item;
- int col, x, y, emh, emy, miny, itemw, itemh, maxw = 0;
- int toth, totitem;
-
- /* compute max needed width and total height */
- toth = 0;
- totitem = 0;
- for (item = litem->items.first; item; item = item->next) {
- ui_item_size(item, &itemw, &itemh);
- maxw = MAX2(maxw, itemw);
- toth += itemh;
- totitem++;
- }
-
- if (flow->number <= 0) {
- /* auto compute number of columns, not very good */
- if (maxw == 0) {
- flow->totcol = 1;
- return;
- }
-
- flow->totcol = max_ii(litem->root->emw / maxw, 1);
- flow->totcol = min_ii(flow->totcol, totitem);
- }
- else {
- flow->totcol = flow->number;
- }
-
- /* compute sizes */
- x = 0;
- y = 0;
- emy = 0;
- miny = 0;
-
- maxw = 0;
- emh = toth / flow->totcol;
-
- /* create column per column */
- col = 0;
- for (item = litem->items.first; item; item = item->next) {
- ui_item_size(item, &itemw, &itemh);
-
- y -= itemh + style->buttonspacey;
- miny = min_ii(miny, y);
- emy -= itemh;
- maxw = max_ii(itemw, maxw);
-
- /* decide to go to next one */
- if (col < flow->totcol - 1 && emy <= -emh) {
- x += maxw + litem->space;
- maxw = 0;
- y = 0;
- emy = 0; /* need to reset height again for next column */
- col++;
- }
- }
-
- litem->w = x;
- litem->h = litem->y - miny;
+ uiStyle *style = litem->root->style;
+ uiLayoutItemFlow *flow = (uiLayoutItemFlow *)litem;
+ uiItem *item;
+ int col, x, y, emh, emy, miny, itemw, itemh, maxw = 0;
+ int toth, totitem;
+
+ /* compute max needed width and total height */
+ toth = 0;
+ totitem = 0;
+ for (item = litem->items.first; item; item = item->next) {
+ ui_item_size(item, &itemw, &itemh);
+ maxw = MAX2(maxw, itemw);
+ toth += itemh;
+ totitem++;
+ }
+
+ if (flow->number <= 0) {
+ /* auto compute number of columns, not very good */
+ if (maxw == 0) {
+ flow->totcol = 1;
+ return;
+ }
+
+ flow->totcol = max_ii(litem->root->emw / maxw, 1);
+ flow->totcol = min_ii(flow->totcol, totitem);
+ }
+ else {
+ flow->totcol = flow->number;
+ }
+
+ /* compute sizes */
+ x = 0;
+ y = 0;
+ emy = 0;
+ miny = 0;
+
+ maxw = 0;
+ emh = toth / flow->totcol;
+
+ /* create column per column */
+ col = 0;
+ for (item = litem->items.first; item; item = item->next) {
+ ui_item_size(item, &itemw, &itemh);
+
+ y -= itemh + style->buttonspacey;
+ miny = min_ii(miny, y);
+ emy -= itemh;
+ maxw = max_ii(itemw, maxw);
+
+ /* decide to go to next one */
+ if (col < flow->totcol - 1 && emy <= -emh) {
+ x += maxw + litem->space;
+ maxw = 0;
+ y = 0;
+ emy = 0; /* need to reset height again for next column */
+ col++;
+ }
+ }
+
+ litem->w = x;
+ litem->h = litem->y - miny;
}
static void ui_litem_layout_column_flow(uiLayout *litem)
{
- uiStyle *style = litem->root->style;
- uiLayoutItemFlow *flow = (uiLayoutItemFlow *)litem;
- uiItem *item;
- int col, x, y, w, emh, emy, miny, itemw, itemh;
- int toth, totitem;
-
- /* compute max needed width and total height */
- toth = 0;
- totitem = 0;
- for (item = litem->items.first; item; item = item->next) {
- ui_item_size(item, &itemw, &itemh);
- toth += itemh;
- totitem++;
- }
-
- /* compute sizes */
- x = litem->x;
- y = litem->y;
- emy = 0;
- miny = 0;
-
- w = litem->w - (flow->totcol - 1) * style->columnspace;
- emh = toth / flow->totcol;
-
- /* create column per column */
- col = 0;
- w = (litem->w - (flow->totcol - 1) * style->columnspace) / flow->totcol;
- for (item = litem->items.first; item; item = item->next) {
- ui_item_size(item, &itemw, &itemh);
-
- itemw = (litem->alignment == UI_LAYOUT_ALIGN_EXPAND) ? w : min_ii(w, itemw);
-
- y -= itemh;
- emy -= itemh;
- ui_item_position(item, x, y, itemw, itemh);
- y -= style->buttonspacey;
- miny = min_ii(miny, y);
-
- /* decide to go to next one */
- if (col < flow->totcol - 1 && emy <= -emh) {
- x += w + style->columnspace;
- y = litem->y;
- emy = 0; /* need to reset height again for next column */
- col++;
-
- /* (< remaining width > - < space between remaining columns >) / <remamining columns > */
- w = ((litem->w - (x - litem->x)) - (flow->totcol - col - 1) * style->columnspace) / (flow->totcol - col);
- }
- }
-
- litem->h = litem->y - miny;
- litem->x = x;
- litem->y = miny;
+ uiStyle *style = litem->root->style;
+ uiLayoutItemFlow *flow = (uiLayoutItemFlow *)litem;
+ uiItem *item;
+ int col, x, y, w, emh, emy, miny, itemw, itemh;
+ int toth, totitem;
+
+ /* compute max needed width and total height */
+ toth = 0;
+ totitem = 0;
+ for (item = litem->items.first; item; item = item->next) {
+ ui_item_size(item, &itemw, &itemh);
+ toth += itemh;
+ totitem++;
+ }
+
+ /* compute sizes */
+ x = litem->x;
+ y = litem->y;
+ emy = 0;
+ miny = 0;
+
+ w = litem->w - (flow->totcol - 1) * style->columnspace;
+ emh = toth / flow->totcol;
+
+ /* create column per column */
+ col = 0;
+ w = (litem->w - (flow->totcol - 1) * style->columnspace) / flow->totcol;
+ for (item = litem->items.first; item; item = item->next) {
+ ui_item_size(item, &itemw, &itemh);
+
+ itemw = (litem->alignment == UI_LAYOUT_ALIGN_EXPAND) ? w : min_ii(w, itemw);
+
+ y -= itemh;
+ emy -= itemh;
+ ui_item_position(item, x, y, itemw, itemh);
+ y -= style->buttonspacey;
+ miny = min_ii(miny, y);
+
+ /* decide to go to next one */
+ if (col < flow->totcol - 1 && emy <= -emh) {
+ x += w + style->columnspace;
+ y = litem->y;
+ emy = 0; /* need to reset height again for next column */
+ col++;
+
+ /* (< remaining width > - < space between remaining columns >) / <remamining columns > */
+ w = ((litem->w - (x - litem->x)) - (flow->totcol - col - 1) * style->columnspace) /
+ (flow->totcol - col);
+ }
+ }
+
+ litem->h = litem->y - miny;
+ litem->x = x;
+ litem->y = miny;
}
/* multi-column and multi-row layout. */
typedef struct UILayoutGridFlowInput {
- /* General layout control settings. */
- const bool row_major : 1; /* Fill rows before columns */
- const bool even_columns : 1; /* All columns will have same width. */
- const bool even_rows : 1; /* All rows will have same height. */
- const int space_x; /* Space between columns. */
- const int space_y; /* Space between rows. */
- /* Real data about current position and size of this layout item
- * (either estimated, or final values). */
- const int litem_w; /* Layout item width. */
- const int litem_x; /* Layout item X position. */
- const int litem_y; /* Layout item Y position. */
- /* Actual number of columns and rows to generate (computed from first pass usually). */
- const int tot_columns; /* Number of columns. */
- const int tot_rows; /* Number of rows. */
+ /* General layout control settings. */
+ const bool row_major : 1; /* Fill rows before columns */
+ const bool even_columns : 1; /* All columns will have same width. */
+ const bool even_rows : 1; /* All rows will have same height. */
+ const int space_x; /* Space between columns. */
+ const int space_y; /* Space between rows. */
+ /* Real data about current position and size of this layout item
+ * (either estimated, or final values). */
+ const int litem_w; /* Layout item width. */
+ const int litem_x; /* Layout item X position. */
+ const int litem_y; /* Layout item Y position. */
+ /* Actual number of columns and rows to generate (computed from first pass usually). */
+ const int tot_columns; /* Number of columns. */
+ const int tot_rows; /* Number of rows. */
} UILayoutGridFlowInput;
typedef struct UILayoutGridFlowOutput {
- int *tot_items; /* Total number of items in this grid layout. */
- /* Width / X pos data. */
- float *global_avg_w; /* Computed average width of the columns. */
- int *cos_x_array; /* Computed X coordinate of each column. */
- int *widths_array; /* Computed width of each column. */
- int *tot_w; /* Computed total width. */
- /* Height / Y pos data. */
- int *global_max_h; /* Computed height of the tallest item in the grid. */
- int *cos_y_array; /* Computed Y coordinate of each column. */
- int *heights_array; /* Computed height of each column. */
- int *tot_h; /* Computed total height. */
+ int *tot_items; /* Total number of items in this grid layout. */
+ /* Width / X pos data. */
+ float *global_avg_w; /* Computed average width of the columns. */
+ int *cos_x_array; /* Computed X coordinate of each column. */
+ int *widths_array; /* Computed width of each column. */
+ int *tot_w; /* Computed total width. */
+ /* Height / Y pos data. */
+ int *global_max_h; /* Computed height of the tallest item in the grid. */
+ int *cos_y_array; /* Computed Y coordinate of each column. */
+ int *heights_array; /* Computed height of each column. */
+ int *tot_h; /* Computed total height. */
} UILayoutGridFlowOutput;
-static void ui_litem_grid_flow_compute(
- ListBase *items, UILayoutGridFlowInput *parameters, UILayoutGridFlowOutput *results)
-{
- uiItem *item;
- int i;
-
- float tot_w = 0.0f, tot_h = 0.0f;
- float global_avg_w = 0.0f, global_totweight_w = 0.0f;
- int global_max_h = 0;
-
- float *avg_w = NULL, *totweight_w = NULL;
- int *max_h = NULL;
-
- BLI_assert(parameters->tot_columns != 0 || (results->cos_x_array == NULL && results->widths_array == NULL && results->tot_w == NULL));
- BLI_assert(parameters->tot_rows != 0 || (results->cos_y_array == NULL && results->heights_array == NULL && results->tot_h == NULL));
-
- if (results->tot_items) {
- *results->tot_items = 0;
- }
-
- if (items->first == NULL) {
- if (results->global_avg_w) {
- *results->global_avg_w = 0.0f;
- }
- if (results->global_max_h) {
- *results->global_max_h = 0;
- }
- return;
- }
-
- if (parameters->tot_columns != 0) {
- avg_w = BLI_array_alloca(avg_w, parameters->tot_columns);
- totweight_w = BLI_array_alloca(totweight_w, parameters->tot_columns);
- memset(avg_w, 0, sizeof(*avg_w) * parameters->tot_columns);
- memset(totweight_w, 0, sizeof(*totweight_w) * parameters->tot_columns);
- }
- if (parameters->tot_rows != 0) {
- max_h = BLI_array_alloca(max_h, parameters->tot_rows);
- memset(max_h, 0, sizeof(*max_h) * parameters->tot_rows);
- }
-
- for (i = 0, item = items->first; item; item = item->next, i++) {
- int item_w, item_h;
- ui_item_size(item, &item_w, &item_h);
-
- global_avg_w += (float)(item_w * item_w);
- global_totweight_w += (float)item_w;
- global_max_h = max_ii(global_max_h, item_h);
-
- if (parameters->tot_rows != 0 && parameters->tot_columns != 0) {
- const int index_col = parameters->row_major ? i % parameters->tot_columns : i / parameters->tot_rows;
- const int index_row = parameters->row_major ? i / parameters->tot_columns : i % parameters->tot_rows;
-
- avg_w[index_col] += (float)(item_w * item_w);
- totweight_w[index_col] += (float)item_w;
-
- max_h[index_row] = max_ii(max_h[index_row], item_h);
- }
-
- if (results->tot_items) {
- (*results->tot_items)++;
- }
- }
-
- /* Finalize computing of column average sizes */
- global_avg_w /= global_totweight_w;
- if (parameters->tot_columns != 0) {
- for (i = 0; i < parameters->tot_columns; i++) {
- avg_w[i] /= totweight_w[i];
- tot_w += avg_w[i];
- }
- if (parameters->even_columns) {
- tot_w = ceilf(global_avg_w) * parameters->tot_columns;
- }
- }
- /* Finalize computing of rows max sizes */
- if (parameters->tot_rows != 0) {
- for (i = 0; i < parameters->tot_rows; i++) {
- tot_h += max_h[i];
- }
- if (parameters->even_rows) {
- tot_h = global_max_h * parameters->tot_columns;
- }
- }
-
- /* Compute positions and sizes of all cells. */
- if (results->cos_x_array != NULL && results->widths_array != NULL) {
- /* We enlarge/narrow columns evenly to match available width. */
- const float wfac = (float)(parameters->litem_w - (parameters->tot_columns - 1) * parameters->space_x) / tot_w;
-
- for (int col = 0; col < parameters->tot_columns; col++) {
- results->cos_x_array[col] = (
- col ?
- results->cos_x_array[col - 1] + results->widths_array[col - 1] + parameters->space_x :
- parameters->litem_x
- );
- if (parameters->even_columns) {
- /* (< remaining width > - < space between remaining columns >) / < remaining columns > */
- results->widths_array[col] = (
- ((parameters->litem_w - (results->cos_x_array[col] - parameters->litem_x)) -
- (parameters->tot_columns - col - 1) * parameters->space_x) / (parameters->tot_columns - col));
- }
- else if (col == parameters->tot_columns - 1) {
- /* Last column copes width rounding errors... */
- results->widths_array[col] = parameters->litem_w - (results->cos_x_array[col] - parameters->litem_x);
- }
- else {
- results->widths_array[col] = (int)(avg_w[col] * wfac);
- }
- }
- }
- if (results->cos_y_array != NULL && results->heights_array != NULL) {
- for (int row = 0; row < parameters->tot_rows; row++) {
- if (parameters->even_rows) {
- results->heights_array[row] = global_max_h;
- }
- else {
- results->heights_array[row] = max_h[row];
- }
- results->cos_y_array[row] = (
- row ?
- results->cos_y_array[row - 1] - parameters->space_y - results->heights_array[row] :
- parameters->litem_y - results->heights_array[row]);
- }
- }
-
- if (results->global_avg_w) {
- *results->global_avg_w = global_avg_w;
- }
- if (results->global_max_h) {
- *results->global_max_h = global_max_h;
- }
- if (results->tot_w) {
- *results->tot_w = (int)tot_w + parameters->space_x * (parameters->tot_columns - 1);
- }
- if (results->tot_h) {
- *results->tot_h = tot_h + parameters->space_y * (parameters->tot_rows - 1);
- }
+static void ui_litem_grid_flow_compute(ListBase *items,
+ UILayoutGridFlowInput *parameters,
+ UILayoutGridFlowOutput *results)
+{
+ uiItem *item;
+ int i;
+
+ float tot_w = 0.0f, tot_h = 0.0f;
+ float global_avg_w = 0.0f, global_totweight_w = 0.0f;
+ int global_max_h = 0;
+
+ float *avg_w = NULL, *totweight_w = NULL;
+ int *max_h = NULL;
+
+ BLI_assert(
+ parameters->tot_columns != 0 ||
+ (results->cos_x_array == NULL && results->widths_array == NULL && results->tot_w == NULL));
+ BLI_assert(
+ parameters->tot_rows != 0 ||
+ (results->cos_y_array == NULL && results->heights_array == NULL && results->tot_h == NULL));
+
+ if (results->tot_items) {
+ *results->tot_items = 0;
+ }
+
+ if (items->first == NULL) {
+ if (results->global_avg_w) {
+ *results->global_avg_w = 0.0f;
+ }
+ if (results->global_max_h) {
+ *results->global_max_h = 0;
+ }
+ return;
+ }
+
+ if (parameters->tot_columns != 0) {
+ avg_w = BLI_array_alloca(avg_w, parameters->tot_columns);
+ totweight_w = BLI_array_alloca(totweight_w, parameters->tot_columns);
+ memset(avg_w, 0, sizeof(*avg_w) * parameters->tot_columns);
+ memset(totweight_w, 0, sizeof(*totweight_w) * parameters->tot_columns);
+ }
+ if (parameters->tot_rows != 0) {
+ max_h = BLI_array_alloca(max_h, parameters->tot_rows);
+ memset(max_h, 0, sizeof(*max_h) * parameters->tot_rows);
+ }
+
+ for (i = 0, item = items->first; item; item = item->next, i++) {
+ int item_w, item_h;
+ ui_item_size(item, &item_w, &item_h);
+
+ global_avg_w += (float)(item_w * item_w);
+ global_totweight_w += (float)item_w;
+ global_max_h = max_ii(global_max_h, item_h);
+
+ if (parameters->tot_rows != 0 && parameters->tot_columns != 0) {
+ const int index_col = parameters->row_major ? i % parameters->tot_columns :
+ i / parameters->tot_rows;
+ const int index_row = parameters->row_major ? i / parameters->tot_columns :
+ i % parameters->tot_rows;
+
+ avg_w[index_col] += (float)(item_w * item_w);
+ totweight_w[index_col] += (float)item_w;
+
+ max_h[index_row] = max_ii(max_h[index_row], item_h);
+ }
+
+ if (results->tot_items) {
+ (*results->tot_items)++;
+ }
+ }
+
+ /* Finalize computing of column average sizes */
+ global_avg_w /= global_totweight_w;
+ if (parameters->tot_columns != 0) {
+ for (i = 0; i < parameters->tot_columns; i++) {
+ avg_w[i] /= totweight_w[i];
+ tot_w += avg_w[i];
+ }
+ if (parameters->even_columns) {
+ tot_w = ceilf(global_avg_w) * parameters->tot_columns;
+ }
+ }
+ /* Finalize computing of rows max sizes */
+ if (parameters->tot_rows != 0) {
+ for (i = 0; i < parameters->tot_rows; i++) {
+ tot_h += max_h[i];
+ }
+ if (parameters->even_rows) {
+ tot_h = global_max_h * parameters->tot_columns;
+ }
+ }
+
+ /* Compute positions and sizes of all cells. */
+ if (results->cos_x_array != NULL && results->widths_array != NULL) {
+ /* We enlarge/narrow columns evenly to match available width. */
+ const float wfac = (float)(parameters->litem_w -
+ (parameters->tot_columns - 1) * parameters->space_x) /
+ tot_w;
+
+ for (int col = 0; col < parameters->tot_columns; col++) {
+ results->cos_x_array[col] = (col ? results->cos_x_array[col - 1] +
+ results->widths_array[col - 1] + parameters->space_x :
+ parameters->litem_x);
+ if (parameters->even_columns) {
+ /* (< remaining width > - < space between remaining columns >) / < remaining columns > */
+ results->widths_array[col] = (((parameters->litem_w -
+ (results->cos_x_array[col] - parameters->litem_x)) -
+ (parameters->tot_columns - col - 1) * parameters->space_x) /
+ (parameters->tot_columns - col));
+ }
+ else if (col == parameters->tot_columns - 1) {
+ /* Last column copes width rounding errors... */
+ results->widths_array[col] = parameters->litem_w -
+ (results->cos_x_array[col] - parameters->litem_x);
+ }
+ else {
+ results->widths_array[col] = (int)(avg_w[col] * wfac);
+ }
+ }
+ }
+ if (results->cos_y_array != NULL && results->heights_array != NULL) {
+ for (int row = 0; row < parameters->tot_rows; row++) {
+ if (parameters->even_rows) {
+ results->heights_array[row] = global_max_h;
+ }
+ else {
+ results->heights_array[row] = max_h[row];
+ }
+ results->cos_y_array[row] = (row ? results->cos_y_array[row - 1] - parameters->space_y -
+ results->heights_array[row] :
+ parameters->litem_y - results->heights_array[row]);
+ }
+ }
+
+ if (results->global_avg_w) {
+ *results->global_avg_w = global_avg_w;
+ }
+ if (results->global_max_h) {
+ *results->global_max_h = global_max_h;
+ }
+ if (results->tot_w) {
+ *results->tot_w = (int)tot_w + parameters->space_x * (parameters->tot_columns - 1);
+ }
+ if (results->tot_h) {
+ *results->tot_h = tot_h + parameters->space_y * (parameters->tot_rows - 1);
+ }
}
static void ui_litem_estimate_grid_flow(uiLayout *litem)
{
- uiStyle *style = litem->root->style;
- uiLayoutItemGridFlow *gflow = (uiLayoutItemGridFlow *)litem;
-
- const int space_x = style->columnspace;
- const int space_y = style->buttonspacey;
-
- /* Estimate average needed width and height per item. */
- {
- float avg_w;
- int max_h;
-
- ui_litem_grid_flow_compute(
- &litem->items,
- &((UILayoutGridFlowInput) {
- .row_major = gflow->row_major,
- .even_columns = gflow->even_columns,
- .even_rows = gflow->even_rows,
- .litem_w = litem->w,
- .litem_x = litem->x,
- .litem_y = litem->y,
- .space_x = space_x,
- .space_y = space_y,
- }),
- &((UILayoutGridFlowOutput) {
- .tot_items = &gflow->tot_items,
- .global_avg_w = &avg_w,
- .global_max_h = &max_h,
- }));
-
- if (gflow->tot_items == 0) {
- litem->w = litem->h = 0;
- gflow->tot_columns = gflow->tot_rows = 0;
- return;
- }
-
- /* Even in varying column width case, we fix our columns number from weighted average width of items,
- * a proper solving of required width would be too costly, and this should give reasonably good results
- * in all reasonable cases... */
- if (gflow->columns_len > 0) {
- gflow->tot_columns = gflow->columns_len;
- }
- else {
- if (avg_w == 0.0f) {
- gflow->tot_columns = 1;
- }
- else {
- gflow->tot_columns = min_ii(max_ii((int)(litem->w / avg_w), 1), gflow->tot_items);
- }
- }
- gflow->tot_rows = (int)ceilf((float)gflow->tot_items / gflow->tot_columns);
-
- /* Try to tweak number of columns and rows to get better filling of last column or row,
- * and apply 'modulo' value to number of columns or rows.
- * Note that modulo does not prevent ending with fewer columns/rows than modulo, if mandatory
- * to avoid empty column/row. */
- {
- const int modulo = (gflow->columns_len < -1) ? -gflow->columns_len : 0;
- const int step = modulo ? modulo : 1;
-
- if (gflow->row_major) {
- /* Adjust number of columns to be multiple of given modulo. */
- if (modulo && gflow->tot_columns % modulo != 0 && gflow->tot_columns > modulo) {
- gflow->tot_columns = gflow->tot_columns - (gflow->tot_columns % modulo);
- }
- /* Find smallest number of columns conserving computed optimal number of rows. */
- for (gflow->tot_rows = (int)ceilf((float)gflow->tot_items / gflow->tot_columns);
- (gflow->tot_columns - step) > 0 &&
- (int)ceilf((float)gflow->tot_items / (gflow->tot_columns - step)) <= gflow->tot_rows;
- gflow->tot_columns -= step)
- {
- /* pass */
- }
- }
- else {
- /* Adjust number of rows to be multiple of given modulo. */
- if (modulo && gflow->tot_rows % modulo != 0) {
- gflow->tot_rows = min_ii(gflow->tot_rows + modulo - (gflow->tot_rows % modulo), gflow->tot_items);
- }
- /* Find smallest number of rows conserving computed optimal number of columns. */
- for (gflow->tot_columns = (int)ceilf((float)gflow->tot_items / gflow->tot_rows);
- (gflow->tot_rows - step) > 0 &&
- (int)ceilf((float)gflow->tot_items / (gflow->tot_rows - step)) <= gflow->tot_columns;
- gflow->tot_rows -= step)
- {
- /* pass */
- }
- }
- }
-
- /* Set evenly-spaced axes size
- * (quick optimization in case we have even columns and rows). */
- if (gflow->even_columns && gflow->even_rows) {
- litem->w = (int)(gflow->tot_columns * avg_w) + space_x * (gflow->tot_columns - 1);
- litem->h = (int)(gflow->tot_rows * max_h) + space_y * (gflow->tot_rows - 1);
- return;
- }
- }
-
- /* Now that we have our final number of columns and rows,
- * we can compute actual needed space for non-evenly sized axes. */
- {
- int tot_w, tot_h;
-
- ui_litem_grid_flow_compute(
- &litem->items,
- &((UILayoutGridFlowInput) {
- .row_major = gflow->row_major,
- .even_columns = gflow->even_columns,
- .even_rows = gflow->even_rows,
- .litem_w = litem->w,
- .litem_x = litem->x,
- .litem_y = litem->y,
- .space_x = space_x,
- .space_y = space_y,
- .tot_columns = gflow->tot_columns,
- .tot_rows = gflow->tot_rows,
- }),
- &((UILayoutGridFlowOutput) {
- .tot_w = &tot_w,
- .tot_h = &tot_h,
- }));
-
- litem->w = tot_w;
- litem->h = tot_h;
- }
+ uiStyle *style = litem->root->style;
+ uiLayoutItemGridFlow *gflow = (uiLayoutItemGridFlow *)litem;
+
+ const int space_x = style->columnspace;
+ const int space_y = style->buttonspacey;
+
+ /* Estimate average needed width and height per item. */
+ {
+ float avg_w;
+ int max_h;
+
+ ui_litem_grid_flow_compute(&litem->items,
+ &((UILayoutGridFlowInput){
+ .row_major = gflow->row_major,
+ .even_columns = gflow->even_columns,
+ .even_rows = gflow->even_rows,
+ .litem_w = litem->w,
+ .litem_x = litem->x,
+ .litem_y = litem->y,
+ .space_x = space_x,
+ .space_y = space_y,
+ }),
+ &((UILayoutGridFlowOutput){
+ .tot_items = &gflow->tot_items,
+ .global_avg_w = &avg_w,
+ .global_max_h = &max_h,
+ }));
+
+ if (gflow->tot_items == 0) {
+ litem->w = litem->h = 0;
+ gflow->tot_columns = gflow->tot_rows = 0;
+ return;
+ }
+
+ /* Even in varying column width case, we fix our columns number from weighted average width of items,
+ * a proper solving of required width would be too costly, and this should give reasonably good results
+ * in all reasonable cases... */
+ if (gflow->columns_len > 0) {
+ gflow->tot_columns = gflow->columns_len;
+ }
+ else {
+ if (avg_w == 0.0f) {
+ gflow->tot_columns = 1;
+ }
+ else {
+ gflow->tot_columns = min_ii(max_ii((int)(litem->w / avg_w), 1), gflow->tot_items);
+ }
+ }
+ gflow->tot_rows = (int)ceilf((float)gflow->tot_items / gflow->tot_columns);
+
+ /* Try to tweak number of columns and rows to get better filling of last column or row,
+ * and apply 'modulo' value to number of columns or rows.
+ * Note that modulo does not prevent ending with fewer columns/rows than modulo, if mandatory
+ * to avoid empty column/row. */
+ {
+ const int modulo = (gflow->columns_len < -1) ? -gflow->columns_len : 0;
+ const int step = modulo ? modulo : 1;
+
+ if (gflow->row_major) {
+ /* Adjust number of columns to be multiple of given modulo. */
+ if (modulo && gflow->tot_columns % modulo != 0 && gflow->tot_columns > modulo) {
+ gflow->tot_columns = gflow->tot_columns - (gflow->tot_columns % modulo);
+ }
+ /* Find smallest number of columns conserving computed optimal number of rows. */
+ for (gflow->tot_rows = (int)ceilf((float)gflow->tot_items / gflow->tot_columns);
+ (gflow->tot_columns - step) > 0 &&
+ (int)ceilf((float)gflow->tot_items / (gflow->tot_columns - step)) <= gflow->tot_rows;
+ gflow->tot_columns -= step) {
+ /* pass */
+ }
+ }
+ else {
+ /* Adjust number of rows to be multiple of given modulo. */
+ if (modulo && gflow->tot_rows % modulo != 0) {
+ gflow->tot_rows = min_ii(gflow->tot_rows + modulo - (gflow->tot_rows % modulo),
+ gflow->tot_items);
+ }
+ /* Find smallest number of rows conserving computed optimal number of columns. */
+ for (gflow->tot_columns = (int)ceilf((float)gflow->tot_items / gflow->tot_rows);
+ (gflow->tot_rows - step) > 0 &&
+ (int)ceilf((float)gflow->tot_items / (gflow->tot_rows - step)) <= gflow->tot_columns;
+ gflow->tot_rows -= step) {
+ /* pass */
+ }
+ }
+ }
+
+ /* Set evenly-spaced axes size
+ * (quick optimization in case we have even columns and rows). */
+ if (gflow->even_columns && gflow->even_rows) {
+ litem->w = (int)(gflow->tot_columns * avg_w) + space_x * (gflow->tot_columns - 1);
+ litem->h = (int)(gflow->tot_rows * max_h) + space_y * (gflow->tot_rows - 1);
+ return;
+ }
+ }
+
+ /* Now that we have our final number of columns and rows,
+ * we can compute actual needed space for non-evenly sized axes. */
+ {
+ int tot_w, tot_h;
+
+ ui_litem_grid_flow_compute(&litem->items,
+ &((UILayoutGridFlowInput){
+ .row_major = gflow->row_major,
+ .even_columns = gflow->even_columns,
+ .even_rows = gflow->even_rows,
+ .litem_w = litem->w,
+ .litem_x = litem->x,
+ .litem_y = litem->y,
+ .space_x = space_x,
+ .space_y = space_y,
+ .tot_columns = gflow->tot_columns,
+ .tot_rows = gflow->tot_rows,
+ }),
+ &((UILayoutGridFlowOutput){
+ .tot_w = &tot_w,
+ .tot_h = &tot_h,
+ }));
+
+ litem->w = tot_w;
+ litem->h = tot_h;
+ }
}
static void ui_litem_layout_grid_flow(uiLayout *litem)
{
- int i;
- uiStyle *style = litem->root->style;
- uiLayoutItemGridFlow *gflow = (uiLayoutItemGridFlow *)litem;
- uiItem *item;
-
- if (gflow->tot_items == 0) {
- litem->w = litem->h = 0;
- return;
- }
-
- BLI_assert(gflow->tot_columns > 0);
- BLI_assert(gflow->tot_rows > 0);
-
- const int space_x = style->columnspace;
- const int space_y = style->buttonspacey;
-
- int *widths = BLI_array_alloca(widths, gflow->tot_columns);
- int *heights = BLI_array_alloca(heights, gflow->tot_rows);
- int *cos_x = BLI_array_alloca(cos_x, gflow->tot_columns);
- int *cos_y = BLI_array_alloca(cos_y, gflow->tot_rows);
-
- /* This time we directly compute coordinates and sizes of all cells. */
- ui_litem_grid_flow_compute(
- &litem->items,
- &((UILayoutGridFlowInput) {
- .row_major = gflow->row_major,
- .even_columns = gflow->even_columns,
- .even_rows = gflow->even_rows,
- .litem_w = litem->w,
- .litem_x = litem->x,
- .litem_y = litem->y,
- .space_x = space_x,
- .space_y = space_y,
- .tot_columns = gflow->tot_columns,
- .tot_rows = gflow->tot_rows,
- }),
- &((UILayoutGridFlowOutput) {
- .cos_x_array = cos_x,
- .cos_y_array = cos_y,
- .widths_array = widths,
- .heights_array = heights,
- }));
-
- for (item = litem->items.first, i = 0; item; item = item->next, i++) {
- const int col = gflow->row_major ? i % gflow->tot_columns : i / gflow->tot_rows;
- const int row = gflow->row_major ? i / gflow->tot_columns : i % gflow->tot_rows;
- int item_w, item_h;
- ui_item_size(item, &item_w, &item_h);
-
- const int w = widths[col];
- const int h = heights[row];
-
- item_w = (litem->alignment == UI_LAYOUT_ALIGN_EXPAND) ? w : min_ii(w, item_w);
- item_h = (litem->alignment == UI_LAYOUT_ALIGN_EXPAND) ? h : min_ii(h, item_h);
-
- ui_item_position(item, cos_x[col], cos_y[row], item_w, item_h);
- }
-
- litem->h = litem->y - cos_y[gflow->tot_rows - 1];
- litem->x = (cos_x[gflow->tot_columns - 1] - litem->x) + widths[gflow->tot_columns - 1];
- litem->y = litem->y - litem->h;
+ int i;
+ uiStyle *style = litem->root->style;
+ uiLayoutItemGridFlow *gflow = (uiLayoutItemGridFlow *)litem;
+ uiItem *item;
+
+ if (gflow->tot_items == 0) {
+ litem->w = litem->h = 0;
+ return;
+ }
+
+ BLI_assert(gflow->tot_columns > 0);
+ BLI_assert(gflow->tot_rows > 0);
+
+ const int space_x = style->columnspace;
+ const int space_y = style->buttonspacey;
+
+ int *widths = BLI_array_alloca(widths, gflow->tot_columns);
+ int *heights = BLI_array_alloca(heights, gflow->tot_rows);
+ int *cos_x = BLI_array_alloca(cos_x, gflow->tot_columns);
+ int *cos_y = BLI_array_alloca(cos_y, gflow->tot_rows);
+
+ /* This time we directly compute coordinates and sizes of all cells. */
+ ui_litem_grid_flow_compute(&litem->items,
+ &((UILayoutGridFlowInput){
+ .row_major = gflow->row_major,
+ .even_columns = gflow->even_columns,
+ .even_rows = gflow->even_rows,
+ .litem_w = litem->w,
+ .litem_x = litem->x,
+ .litem_y = litem->y,
+ .space_x = space_x,
+ .space_y = space_y,
+ .tot_columns = gflow->tot_columns,
+ .tot_rows = gflow->tot_rows,
+ }),
+ &((UILayoutGridFlowOutput){
+ .cos_x_array = cos_x,
+ .cos_y_array = cos_y,
+ .widths_array = widths,
+ .heights_array = heights,
+ }));
+
+ for (item = litem->items.first, i = 0; item; item = item->next, i++) {
+ const int col = gflow->row_major ? i % gflow->tot_columns : i / gflow->tot_rows;
+ const int row = gflow->row_major ? i / gflow->tot_columns : i % gflow->tot_rows;
+ int item_w, item_h;
+ ui_item_size(item, &item_w, &item_h);
+
+ const int w = widths[col];
+ const int h = heights[row];
+
+ item_w = (litem->alignment == UI_LAYOUT_ALIGN_EXPAND) ? w : min_ii(w, item_w);
+ item_h = (litem->alignment == UI_LAYOUT_ALIGN_EXPAND) ? h : min_ii(h, item_h);
+
+ ui_item_position(item, cos_x[col], cos_y[row], item_w, item_h);
+ }
+
+ litem->h = litem->y - cos_y[gflow->tot_rows - 1];
+ litem->x = (cos_x[gflow->tot_columns - 1] - litem->x) + widths[gflow->tot_columns - 1];
+ litem->y = litem->y - litem->h;
}
/* free layout */
static void ui_litem_estimate_absolute(uiLayout *litem)
{
- uiItem *item;
- int itemx, itemy, itemw, itemh, minx, miny;
+ uiItem *item;
+ int itemx, itemy, itemw, itemh, minx, miny;
- minx = 1e6;
- miny = 1e6;
- litem->w = 0;
- litem->h = 0;
+ minx = 1e6;
+ miny = 1e6;
+ litem->w = 0;
+ litem->h = 0;
- for (item = litem->items.first; item; item = item->next) {
- ui_item_offset(item, &itemx, &itemy);
- ui_item_size(item, &itemw, &itemh);
+ for (item = litem->items.first; item; item = item->next) {
+ ui_item_offset(item, &itemx, &itemy);
+ ui_item_size(item, &itemw, &itemh);
- minx = min_ii(minx, itemx);
- miny = min_ii(miny, itemy);
+ minx = min_ii(minx, itemx);
+ miny = min_ii(miny, itemy);
- litem->w = MAX2(litem->w, itemx + itemw);
- litem->h = MAX2(litem->h, itemy + itemh);
- }
+ litem->w = MAX2(litem->w, itemx + itemw);
+ litem->h = MAX2(litem->h, itemy + itemh);
+ }
- litem->w -= minx;
- litem->h -= miny;
+ litem->w -= minx;
+ litem->h -= miny;
}
static void ui_litem_layout_absolute(uiLayout *litem)
{
- uiItem *item;
- float scalex = 1.0f, scaley = 1.0f;
- int x, y, newx, newy, itemx, itemy, itemh, itemw, minx, miny, totw, toth;
+ uiItem *item;
+ float scalex = 1.0f, scaley = 1.0f;
+ int x, y, newx, newy, itemx, itemy, itemh, itemw, minx, miny, totw, toth;
- minx = 1e6;
- miny = 1e6;
- totw = 0;
- toth = 0;
+ minx = 1e6;
+ miny = 1e6;
+ totw = 0;
+ toth = 0;
- for (item = litem->items.first; item; item = item->next) {
- ui_item_offset(item, &itemx, &itemy);
- ui_item_size(item, &itemw, &itemh);
+ for (item = litem->items.first; item; item = item->next) {
+ ui_item_offset(item, &itemx, &itemy);
+ ui_item_size(item, &itemw, &itemh);
- minx = min_ii(minx, itemx);
- miny = min_ii(miny, itemy);
+ minx = min_ii(minx, itemx);
+ miny = min_ii(miny, itemy);
- totw = max_ii(totw, itemx + itemw);
- toth = max_ii(toth, itemy + itemh);
- }
+ totw = max_ii(totw, itemx + itemw);
+ toth = max_ii(toth, itemy + itemh);
+ }
- totw -= minx;
- toth -= miny;
+ totw -= minx;
+ toth -= miny;
- if (litem->w && totw > 0) {
- scalex = (float)litem->w / (float)totw;
- }
- if (litem->h && toth > 0) {
- scaley = (float)litem->h / (float)toth;
- }
+ if (litem->w && totw > 0) {
+ scalex = (float)litem->w / (float)totw;
+ }
+ if (litem->h && toth > 0) {
+ scaley = (float)litem->h / (float)toth;
+ }
- x = litem->x;
- y = litem->y - scaley * toth;
+ x = litem->x;
+ y = litem->y - scaley * toth;
- for (item = litem->items.first; item; item = item->next) {
- ui_item_offset(item, &itemx, &itemy);
- ui_item_size(item, &itemw, &itemh);
+ for (item = litem->items.first; item; item = item->next) {
+ ui_item_offset(item, &itemx, &itemy);
+ ui_item_size(item, &itemw, &itemh);
- if (scalex != 1.0f) {
- newx = (itemx - minx) * scalex;
- itemw = (itemx - minx + itemw) * scalex - newx;
- itemx = minx + newx;
- }
+ if (scalex != 1.0f) {
+ newx = (itemx - minx) * scalex;
+ itemw = (itemx - minx + itemw) * scalex - newx;
+ itemx = minx + newx;
+ }
- if (scaley != 1.0f) {
- newy = (itemy - miny) * scaley;
- itemh = (itemy - miny + itemh) * scaley - newy;
- itemy = miny + newy;
- }
+ if (scaley != 1.0f) {
+ newy = (itemy - miny) * scaley;
+ itemh = (itemy - miny + itemh) * scaley - newy;
+ itemy = miny + newy;
+ }
- ui_item_position(item, x + itemx - minx, y + itemy - miny, itemw, itemh);
- }
+ ui_item_position(item, x + itemx - minx, y + itemy - miny, itemw, itemh);
+ }
- litem->w = scalex * totw;
- litem->h = litem->y - y;
- litem->x = x + litem->w;
- litem->y = y;
+ litem->w = scalex * totw;
+ litem->h = litem->y - y;
+ litem->x = x + litem->w;
+ litem->y = y;
}
/* split layout */
static void ui_litem_estimate_split(uiLayout *litem)
{
- ui_litem_estimate_row(litem);
- litem->item.flag &= ~UI_ITEM_MIN;
+ ui_litem_estimate_row(litem);
+ litem->item.flag &= ~UI_ITEM_MIN;
}
static void ui_litem_layout_split(uiLayout *litem)
{
- uiLayoutItemSplit *split = (uiLayoutItemSplit *)litem;
- uiItem *item;
- float percentage, extra_pixel = 0.0f;
- const int tot = BLI_listbase_count(&litem->items);
- int itemh, x, y, w, colw = 0;
+ uiLayoutItemSplit *split = (uiLayoutItemSplit *)litem;
+ uiItem *item;
+ float percentage, extra_pixel = 0.0f;
+ const int tot = BLI_listbase_count(&litem->items);
+ int itemh, x, y, w, colw = 0;
- if (tot == 0) {
- return;
- }
+ if (tot == 0) {
+ return;
+ }
- x = litem->x;
- y = litem->y;
+ x = litem->x;
+ y = litem->y;
- percentage = (split->percentage == 0.0f) ? 1.0f / (float)tot : split->percentage;
+ percentage = (split->percentage == 0.0f) ? 1.0f / (float)tot : split->percentage;
- w = (litem->w - (tot - 1) * litem->space);
- colw = w * percentage;
- colw = MAX2(colw, 0);
+ w = (litem->w - (tot - 1) * litem->space);
+ colw = w * percentage;
+ colw = MAX2(colw, 0);
- for (item = litem->items.first; item; item = item->next) {
- ui_item_size(item, NULL, &itemh);
+ for (item = litem->items.first; item; item = item->next) {
+ ui_item_size(item, NULL, &itemh);
- ui_item_position(item, x, y - itemh, colw, itemh);
- x += colw;
+ ui_item_position(item, x, y - itemh, colw, itemh);
+ x += colw;
- if (item->next) {
- const float width = extra_pixel + (w - (int)(w * percentage)) / ((float)tot - 1);
- extra_pixel = width - (int)width;
- colw = (int)width;
- colw = MAX2(colw, 0);
+ if (item->next) {
+ const float width = extra_pixel + (w - (int)(w * percentage)) / ((float)tot - 1);
+ extra_pixel = width - (int)width;
+ colw = (int)width;
+ colw = MAX2(colw, 0);
- x += litem->space;
- }
- }
+ x += litem->space;
+ }
+ }
- litem->w = x - litem->x;
- litem->h = litem->y - y;
- litem->x = x;
- litem->y = y;
+ litem->w = x - litem->x;
+ litem->h = litem->y - y;
+ litem->x = x;
+ litem->y = y;
}
/* overlap layout */
static void ui_litem_estimate_overlap(uiLayout *litem)
{
- uiItem *item;
- int itemw, itemh;
+ uiItem *item;
+ int itemw, itemh;
- litem->w = 0;
- litem->h = 0;
+ litem->w = 0;
+ litem->h = 0;
- for (item = litem->items.first; item; item = item->next) {
- ui_item_size(item, &itemw, &itemh);
+ for (item = litem->items.first; item; item = item->next) {
+ ui_item_size(item, &itemw, &itemh);
- litem->w = MAX2(itemw, litem->w);
- litem->h = MAX2(itemh, litem->h);
- }
+ litem->w = MAX2(itemw, litem->w);
+ litem->h = MAX2(itemh, litem->h);
+ }
}
static void ui_litem_layout_overlap(uiLayout *litem)
{
- uiItem *item;
- int itemw, itemh, x, y;
+ uiItem *item;
+ int itemw, itemh, x, y;
- x = litem->x;
- y = litem->y;
+ x = litem->x;
+ y = litem->y;
- for (item = litem->items.first; item; item = item->next) {
- ui_item_size(item, &itemw, &itemh);
- ui_item_position(item, x, y - itemh, litem->w, itemh);
+ for (item = litem->items.first; item; item = item->next) {
+ ui_item_size(item, &itemw, &itemh);
+ ui_item_position(item, x, y - itemh, litem->w, itemh);
- litem->h = MAX2(litem->h, itemh);
- }
+ litem->h = MAX2(litem->h, itemh);
+ }
- litem->x = x;
- litem->y = y - litem->h;
+ litem->x = x;
+ litem->y = y - litem->h;
}
static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int align)
{
- litem->root = layout->root;
- litem->align = align;
- /* Children of gridflow layout shall never have "ideal big size" returned as estimated size. */
- litem->variable_size = layout->variable_size || layout->item.type == ITEM_LAYOUT_GRID_FLOW;
- litem->active = true;
- litem->enabled = true;
- litem->context = layout->context;
- 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));
-
- if (layout->child_items_layout) {
- BLI_addtail(&layout->child_items_layout->items, litem);
- }
- else {
- BLI_addtail(&layout->items, litem);
- }
+ litem->root = layout->root;
+ litem->align = align;
+ /* Children of gridflow layout shall never have "ideal big size" returned as estimated size. */
+ litem->variable_size = layout->variable_size || layout->item.type == ITEM_LAYOUT_GRID_FLOW;
+ litem->active = true;
+ litem->enabled = true;
+ litem->context = layout->context;
+ 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));
+
+ if (layout->child_items_layout) {
+ BLI_addtail(&layout->child_items_layout->items, litem);
+ }
+ else {
+ BLI_addtail(&layout->items, litem);
+ }
}
/* layout create functions */
uiLayout *uiLayoutRow(uiLayout *layout, bool align)
{
- uiLayout *litem;
+ uiLayout *litem;
- litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRow");
- ui_litem_init_from_parent(litem, layout, align);
+ litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRow");
+ ui_litem_init_from_parent(litem, layout, align);
- litem->item.type = ITEM_LAYOUT_ROW;
- litem->space = (align) ? 0 : layout->root->style->buttonspacex;
+ litem->item.type = ITEM_LAYOUT_ROW;
+ litem->space = (align) ? 0 : layout->root->style->buttonspacex;
- UI_block_layout_set_current(layout->root->block, litem);
+ UI_block_layout_set_current(layout->root->block, litem);
- return litem;
+ return litem;
}
uiLayout *uiLayoutColumn(uiLayout *layout, bool align)
{
- uiLayout *litem;
+ uiLayout *litem;
- litem = MEM_callocN(sizeof(uiLayout), "uiLayoutColumn");
- ui_litem_init_from_parent(litem, layout, align);
+ litem = MEM_callocN(sizeof(uiLayout), "uiLayoutColumn");
+ ui_litem_init_from_parent(litem, layout, align);
- litem->item.type = ITEM_LAYOUT_COLUMN;
- litem->space = (align) ? 0 : layout->root->style->buttonspacey;
+ litem->item.type = ITEM_LAYOUT_COLUMN;
+ litem->space = (align) ? 0 : layout->root->style->buttonspacey;
- UI_block_layout_set_current(layout->root->block, litem);
+ UI_block_layout_set_current(layout->root->block, litem);
- return litem;
+ return litem;
}
uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, bool align)
{
- uiLayoutItemFlow *flow;
+ uiLayoutItemFlow *flow;
- flow = MEM_callocN(sizeof(uiLayoutItemFlow), "uiLayoutItemFlow");
- ui_litem_init_from_parent(&flow->litem, layout, align);
+ flow = MEM_callocN(sizeof(uiLayoutItemFlow), "uiLayoutItemFlow");
+ ui_litem_init_from_parent(&flow->litem, layout, align);
- flow->litem.item.type = ITEM_LAYOUT_COLUMN_FLOW;
- flow->litem.space = (flow->litem.align) ? 0 : layout->root->style->columnspace;
- flow->number = number;
+ flow->litem.item.type = ITEM_LAYOUT_COLUMN_FLOW;
+ flow->litem.space = (flow->litem.align) ? 0 : layout->root->style->columnspace;
+ flow->number = number;
- UI_block_layout_set_current(layout->root->block, &flow->litem);
+ UI_block_layout_set_current(layout->root->block, &flow->litem);
- return &flow->litem;
+ return &flow->litem;
}
-uiLayout *uiLayoutGridFlow(
- uiLayout *layout, bool row_major, int columns_len, bool even_columns, bool even_rows, bool align)
+uiLayout *uiLayoutGridFlow(uiLayout *layout,
+ bool row_major,
+ int columns_len,
+ bool even_columns,
+ bool even_rows,
+ bool align)
{
- uiLayoutItemGridFlow *flow;
+ uiLayoutItemGridFlow *flow;
- flow = MEM_callocN(sizeof(uiLayoutItemGridFlow), __func__);
- flow->litem.item.type = ITEM_LAYOUT_GRID_FLOW;
- ui_litem_init_from_parent(&flow->litem, layout, align);
+ flow = MEM_callocN(sizeof(uiLayoutItemGridFlow), __func__);
+ flow->litem.item.type = ITEM_LAYOUT_GRID_FLOW;
+ ui_litem_init_from_parent(&flow->litem, layout, align);
- flow->litem.space = (flow->litem.align) ? 0 : layout->root->style->columnspace;
- flow->row_major = row_major;
- flow->columns_len = columns_len;
- flow->even_columns = even_columns;
- flow->even_rows = even_rows;
+ flow->litem.space = (flow->litem.align) ? 0 : layout->root->style->columnspace;
+ flow->row_major = row_major;
+ flow->columns_len = columns_len;
+ flow->even_columns = even_columns;
+ flow->even_rows = even_rows;
- UI_block_layout_set_current(layout->root->block, &flow->litem);
+ UI_block_layout_set_current(layout->root->block, &flow->litem);
- return &flow->litem;
+ return &flow->litem;
}
static uiLayoutItemBx *ui_layout_box(uiLayout *layout, int type)
{
- uiLayoutItemBx *box;
+ uiLayoutItemBx *box;
- box = MEM_callocN(sizeof(uiLayoutItemBx), "uiLayoutItemBx");
- ui_litem_init_from_parent(&box->litem, layout, false);
+ box = MEM_callocN(sizeof(uiLayoutItemBx), "uiLayoutItemBx");
+ ui_litem_init_from_parent(&box->litem, layout, false);
- box->litem.item.type = ITEM_LAYOUT_BOX;
- box->litem.space = layout->root->style->columnspace;
+ box->litem.item.type = ITEM_LAYOUT_BOX;
+ box->litem.space = layout->root->style->columnspace;
- UI_block_layout_set_current(layout->root->block, &box->litem);
+ UI_block_layout_set_current(layout->root->block, &box->litem);
- box->roundbox = uiDefBut(layout->root->block, type, 0, "", 0, 0, 0, 0, NULL, 0.0, 0.0, 0, 0, "");
+ box->roundbox = uiDefBut(layout->root->block, type, 0, "", 0, 0, 0, 0, NULL, 0.0, 0.0, 0, 0, "");
- return box;
+ return box;
}
uiLayout *uiLayoutRadial(uiLayout *layout)
{
- uiLayout *litem;
- uiItem *item;
+ uiLayout *litem;
+ uiItem *item;
- /* radial layouts are only valid for radial menus */
- if (layout->root->type != UI_LAYOUT_PIEMENU) {
- return ui_item_local_sublayout(layout, layout, 0);
- }
+ /* radial layouts are only valid for radial menus */
+ if (layout->root->type != UI_LAYOUT_PIEMENU) {
+ return ui_item_local_sublayout(layout, layout, 0);
+ }
- /* only one radial wheel per root layout is allowed, so check and return that, if it exists */
- for (item = layout->root->layout->items.first; item; item = item->next) {
- litem = (uiLayout *)item;
- if (litem->item.type == ITEM_LAYOUT_RADIAL) {
- UI_block_layout_set_current(layout->root->block, litem);
- return litem;
- }
- }
+ /* only one radial wheel per root layout is allowed, so check and return that, if it exists */
+ for (item = layout->root->layout->items.first; item; item = item->next) {
+ litem = (uiLayout *)item;
+ if (litem->item.type == ITEM_LAYOUT_RADIAL) {
+ UI_block_layout_set_current(layout->root->block, litem);
+ return litem;
+ }
+ }
- litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRadial");
- ui_litem_init_from_parent(litem, layout, false);
+ litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRadial");
+ ui_litem_init_from_parent(litem, layout, false);
- litem->item.type = ITEM_LAYOUT_RADIAL;
+ litem->item.type = ITEM_LAYOUT_RADIAL;
- UI_block_layout_set_current(layout->root->block, litem);
+ UI_block_layout_set_current(layout->root->block, litem);
- return litem;
+ return litem;
}
-
uiLayout *uiLayoutBox(uiLayout *layout)
{
- return (uiLayout *)ui_layout_box(layout, UI_BTYPE_ROUNDBOX);
+ return (uiLayout *)ui_layout_box(layout, UI_BTYPE_ROUNDBOX);
}
/**
@@ -4063,762 +4439,763 @@ uiLayout *uiLayoutBox(uiLayout *layout)
*/
void ui_layout_list_set_labels_active(uiLayout *layout)
{
- uiButtonItem *bitem;
- for (bitem = layout->items.first; bitem; bitem = bitem->item.next) {
- if (bitem->item.type != ITEM_BUTTON) {
- ui_layout_list_set_labels_active((uiLayout *)(&bitem->item));
- }
- else if (bitem->but->flag & UI_BUT_LIST_ITEM) {
- UI_but_flag_enable(bitem->but, UI_SELECT);
- }
- }
+ uiButtonItem *bitem;
+ for (bitem = layout->items.first; bitem; bitem = bitem->item.next) {
+ if (bitem->item.type != ITEM_BUTTON) {
+ ui_layout_list_set_labels_active((uiLayout *)(&bitem->item));
+ }
+ else if (bitem->but->flag & UI_BUT_LIST_ITEM) {
+ UI_but_flag_enable(bitem->but, UI_SELECT);
+ }
+ }
}
-uiLayout *uiLayoutListBox(
- uiLayout *layout, uiList *ui_list, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *actptr,
- PropertyRNA *actprop)
+uiLayout *uiLayoutListBox(uiLayout *layout,
+ uiList *ui_list,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ PointerRNA *actptr,
+ PropertyRNA *actprop)
{
- uiLayoutItemBx *box = ui_layout_box(layout, UI_BTYPE_LISTBOX);
- uiBut *but = box->roundbox;
+ uiLayoutItemBx *box = ui_layout_box(layout, UI_BTYPE_LISTBOX);
+ uiBut *but = box->roundbox;
- but->custom_data = ui_list;
+ but->custom_data = ui_list;
- but->rnasearchpoin = *ptr;
- but->rnasearchprop = prop;
- but->rnapoin = *actptr;
- but->rnaprop = actprop;
+ but->rnasearchpoin = *ptr;
+ but->rnasearchprop = prop;
+ but->rnapoin = *actptr;
+ but->rnaprop = actprop;
- /* only for the undo string */
- if (but->flag & UI_BUT_UNDO) {
- but->tip = RNA_property_description(actprop);
- }
+ /* only for the undo string */
+ if (but->flag & UI_BUT_UNDO) {
+ but->tip = RNA_property_description(actprop);
+ }
- return (uiLayout *)box;
+ return (uiLayout *)box;
}
uiLayout *uiLayoutAbsolute(uiLayout *layout, bool align)
{
- uiLayout *litem;
+ uiLayout *litem;
- litem = MEM_callocN(sizeof(uiLayout), "uiLayoutAbsolute");
- ui_litem_init_from_parent(litem, layout, align);
+ litem = MEM_callocN(sizeof(uiLayout), "uiLayoutAbsolute");
+ ui_litem_init_from_parent(litem, layout, align);
- litem->item.type = ITEM_LAYOUT_ABSOLUTE;
+ litem->item.type = ITEM_LAYOUT_ABSOLUTE;
- UI_block_layout_set_current(layout->root->block, litem);
+ UI_block_layout_set_current(layout->root->block, litem);
- return litem;
+ return litem;
}
uiBlock *uiLayoutAbsoluteBlock(uiLayout *layout)
{
- uiBlock *block;
+ uiBlock *block;
- block = uiLayoutGetBlock(layout);
- uiLayoutAbsolute(layout, false);
+ block = uiLayoutGetBlock(layout);
+ uiLayoutAbsolute(layout, false);
- return block;
+ return block;
}
uiLayout *uiLayoutOverlap(uiLayout *layout)
{
- uiLayout *litem;
+ uiLayout *litem;
- litem = MEM_callocN(sizeof(uiLayout), "uiLayoutOverlap");
- ui_litem_init_from_parent(litem, layout, false);
+ litem = MEM_callocN(sizeof(uiLayout), "uiLayoutOverlap");
+ ui_litem_init_from_parent(litem, layout, false);
- litem->item.type = ITEM_LAYOUT_OVERLAP;
+ litem->item.type = ITEM_LAYOUT_OVERLAP;
- UI_block_layout_set_current(layout->root->block, litem);
+ UI_block_layout_set_current(layout->root->block, litem);
- return litem;
+ return litem;
}
uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, bool align)
{
- uiLayoutItemSplit *split;
+ uiLayoutItemSplit *split;
- split = MEM_callocN(sizeof(uiLayoutItemSplit), "uiLayoutItemSplit");
- ui_litem_init_from_parent(&split->litem, layout, align);
+ split = MEM_callocN(sizeof(uiLayoutItemSplit), "uiLayoutItemSplit");
+ ui_litem_init_from_parent(&split->litem, layout, align);
- split->litem.item.type = ITEM_LAYOUT_SPLIT;
- split->litem.space = layout->root->style->columnspace;
- split->percentage = percentage;
+ split->litem.item.type = ITEM_LAYOUT_SPLIT;
+ split->litem.space = layout->root->style->columnspace;
+ split->percentage = percentage;
- UI_block_layout_set_current(layout->root->block, &split->litem);
+ UI_block_layout_set_current(layout->root->block, &split->litem);
- return &split->litem;
+ return &split->litem;
}
void uiLayoutSetActive(uiLayout *layout, bool active)
{
- layout->active = active;
+ layout->active = active;
}
void uiLayoutSetActiveDefault(uiLayout *layout, bool active_default)
{
- layout->active_default = active_default;
+ layout->active_default = active_default;
}
void uiLayoutSetActivateInit(uiLayout *layout, bool activate_init)
{
- layout->activate_init = activate_init;
+ layout->activate_init = activate_init;
}
void uiLayoutSetEnabled(uiLayout *layout, bool enabled)
{
- layout->enabled = enabled;
+ layout->enabled = enabled;
}
void uiLayoutSetRedAlert(uiLayout *layout, bool redalert)
{
- layout->redalert = redalert;
+ layout->redalert = redalert;
}
void uiLayoutSetKeepAspect(uiLayout *layout, bool keepaspect)
{
- layout->keepaspect = keepaspect;
+ layout->keepaspect = keepaspect;
}
void uiLayoutSetAlignment(uiLayout *layout, char alignment)
{
- layout->alignment = alignment;
+ layout->alignment = alignment;
}
void uiLayoutSetScaleX(uiLayout *layout, float scale)
{
- layout->scale[0] = scale;
+ layout->scale[0] = scale;
}
void uiLayoutSetScaleY(uiLayout *layout, float scale)
{
- layout->scale[1] = scale;
+ layout->scale[1] = scale;
}
void uiLayoutSetUnitsX(uiLayout *layout, float unit)
{
- layout->units[0] = unit;
+ layout->units[0] = unit;
}
void uiLayoutSetUnitsY(uiLayout *layout, float unit)
{
- layout->units[1] = unit;
+ layout->units[1] = unit;
}
void uiLayoutSetEmboss(uiLayout *layout, char emboss)
{
- layout->emboss = emboss;
+ layout->emboss = emboss;
}
bool uiLayoutGetPropSep(uiLayout *layout)
{
- return (layout->item.flag & UI_ITEM_PROP_SEP) != 0;
+ return (layout->item.flag & UI_ITEM_PROP_SEP) != 0;
}
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
{
- SET_FLAG_FROM_TEST(layout->item.flag, is_sep, UI_ITEM_PROP_SEP);
+ SET_FLAG_FROM_TEST(layout->item.flag, is_sep, UI_ITEM_PROP_SEP);
}
bool uiLayoutGetPropDecorate(uiLayout *layout)
{
- return (layout->item.flag & UI_ITEM_PROP_DECORATE) != 0;
+ return (layout->item.flag & UI_ITEM_PROP_DECORATE) != 0;
}
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
{
- SET_FLAG_FROM_TEST(layout->item.flag, is_sep, UI_ITEM_PROP_DECORATE);
+ SET_FLAG_FROM_TEST(layout->item.flag, is_sep, UI_ITEM_PROP_DECORATE);
}
bool uiLayoutGetActive(uiLayout *layout)
{
- return layout->active;
+ return layout->active;
}
bool uiLayoutGetActiveDefault(uiLayout *layout)
{
- return layout->active_default;
+ return layout->active_default;
}
bool uiLayoutGetActivateInit(uiLayout *layout)
{
- return layout->activate_init;
+ return layout->activate_init;
}
bool uiLayoutGetEnabled(uiLayout *layout)
{
- return layout->enabled;
+ return layout->enabled;
}
bool uiLayoutGetRedAlert(uiLayout *layout)
{
- return layout->redalert;
+ return layout->redalert;
}
bool uiLayoutGetKeepAspect(uiLayout *layout)
{
- return layout->keepaspect;
+ return layout->keepaspect;
}
int uiLayoutGetAlignment(uiLayout *layout)
{
- return layout->alignment;
+ return layout->alignment;
}
int uiLayoutGetWidth(uiLayout *layout)
{
- return layout->w;
+ return layout->w;
}
float uiLayoutGetScaleX(uiLayout *layout)
{
- return layout->scale[0];
+ return layout->scale[0];
}
float uiLayoutGetScaleY(uiLayout *layout)
{
- return layout->scale[1];
+ return layout->scale[1];
}
float uiLayoutGetUnitsX(uiLayout *layout)
{
- return layout->units[0];
+ return layout->units[0];
}
float uiLayoutGetUnitsY(uiLayout *layout)
{
- return layout->units[1];
+ return layout->units[1];
}
int uiLayoutGetEmboss(uiLayout *layout)
{
- if (layout->emboss == UI_EMBOSS_UNDEFINED) {
- return layout->root->block->dt;
- }
- else {
- return layout->emboss;
- }
+ if (layout->emboss == UI_EMBOSS_UNDEFINED) {
+ return layout->root->block->dt;
+ }
+ else {
+ return layout->emboss;
+ }
}
/********************** Layout *******************/
static void ui_item_scale(uiLayout *litem, const float scale[2])
{
- uiItem *item;
- int x, y, w, h;
+ uiItem *item;
+ int x, y, w, h;
- for (item = litem->items.last; item; item = item->prev) {
- if (item->type != ITEM_BUTTON) {
- uiLayout *subitem = (uiLayout *)item;
- ui_item_scale(subitem, scale);
- }
+ for (item = litem->items.last; item; item = item->prev) {
+ if (item->type != ITEM_BUTTON) {
+ uiLayout *subitem = (uiLayout *)item;
+ ui_item_scale(subitem, scale);
+ }
- ui_item_size(item, &w, &h);
- ui_item_offset(item, &x, &y);
+ ui_item_size(item, &w, &h);
+ ui_item_offset(item, &x, &y);
- if (scale[0] != 0.0f) {
- x *= scale[0];
- w *= scale[0];
- }
+ if (scale[0] != 0.0f) {
+ x *= scale[0];
+ w *= scale[0];
+ }
- if (scale[1] != 0.0f) {
- y *= scale[1];
- h *= scale[1];
- }
+ if (scale[1] != 0.0f) {
+ y *= scale[1];
+ h *= scale[1];
+ }
- ui_item_position(item, x, y, w, h);
- }
+ ui_item_position(item, x, y, w, h);
+ }
}
static void ui_item_estimate(uiItem *item)
{
- uiItem *subitem;
-
- if (item->type != ITEM_BUTTON) {
- uiLayout *litem = (uiLayout *)item;
-
- for (subitem = litem->items.first; subitem; subitem = subitem->next) {
- ui_item_estimate(subitem);
- }
-
- if (BLI_listbase_is_empty(&litem->items)) {
- litem->w = 0;
- litem->h = 0;
- return;
- }
-
- if (litem->scale[0] != 0.0f || litem->scale[1] != 0.0f) {
- ui_item_scale(litem, litem->scale);
- }
-
- switch (litem->item.type) {
- case ITEM_LAYOUT_COLUMN:
- ui_litem_estimate_column(litem, false);
- break;
- case ITEM_LAYOUT_COLUMN_FLOW:
- ui_litem_estimate_column_flow(litem);
- break;
- case ITEM_LAYOUT_GRID_FLOW:
- ui_litem_estimate_grid_flow(litem);
- break;
- case ITEM_LAYOUT_ROW:
- ui_litem_estimate_row(litem);
- break;
- case ITEM_LAYOUT_BOX:
- ui_litem_estimate_box(litem);
- break;
- case ITEM_LAYOUT_ROOT:
- ui_litem_estimate_root(litem);
- break;
- case ITEM_LAYOUT_ABSOLUTE:
- ui_litem_estimate_absolute(litem);
- break;
- case ITEM_LAYOUT_SPLIT:
- ui_litem_estimate_split(litem);
- break;
- case ITEM_LAYOUT_OVERLAP:
- ui_litem_estimate_overlap(litem);
- break;
- default:
- break;
- }
-
- /* Force fixed size. */
- if (litem->units[0] > 0) {
- litem->w = UI_UNIT_X * litem->units[0];
- }
- if (litem->units[1] > 0) {
- litem->h = UI_UNIT_Y * litem->units[1];
- }
- }
+ uiItem *subitem;
+
+ if (item->type != ITEM_BUTTON) {
+ uiLayout *litem = (uiLayout *)item;
+
+ for (subitem = litem->items.first; subitem; subitem = subitem->next) {
+ ui_item_estimate(subitem);
+ }
+
+ if (BLI_listbase_is_empty(&litem->items)) {
+ litem->w = 0;
+ litem->h = 0;
+ return;
+ }
+
+ if (litem->scale[0] != 0.0f || litem->scale[1] != 0.0f) {
+ ui_item_scale(litem, litem->scale);
+ }
+
+ switch (litem->item.type) {
+ case ITEM_LAYOUT_COLUMN:
+ ui_litem_estimate_column(litem, false);
+ break;
+ case ITEM_LAYOUT_COLUMN_FLOW:
+ ui_litem_estimate_column_flow(litem);
+ break;
+ case ITEM_LAYOUT_GRID_FLOW:
+ ui_litem_estimate_grid_flow(litem);
+ break;
+ case ITEM_LAYOUT_ROW:
+ ui_litem_estimate_row(litem);
+ break;
+ case ITEM_LAYOUT_BOX:
+ ui_litem_estimate_box(litem);
+ break;
+ case ITEM_LAYOUT_ROOT:
+ ui_litem_estimate_root(litem);
+ break;
+ case ITEM_LAYOUT_ABSOLUTE:
+ ui_litem_estimate_absolute(litem);
+ break;
+ case ITEM_LAYOUT_SPLIT:
+ ui_litem_estimate_split(litem);
+ break;
+ case ITEM_LAYOUT_OVERLAP:
+ ui_litem_estimate_overlap(litem);
+ break;
+ default:
+ break;
+ }
+
+ /* Force fixed size. */
+ if (litem->units[0] > 0) {
+ litem->w = UI_UNIT_X * litem->units[0];
+ }
+ if (litem->units[1] > 0) {
+ litem->h = UI_UNIT_Y * litem->units[1];
+ }
+ }
}
static void ui_item_align(uiLayout *litem, short nr)
{
- uiItem *item;
- uiButtonItem *bitem;
- uiLayoutItemBx *box;
+ uiItem *item;
+ uiButtonItem *bitem;
+ uiLayoutItemBx *box;
- for (item = litem->items.last; item; item = item->prev) {
- if (item->type == ITEM_BUTTON) {
- bitem = (uiButtonItem *)item;
+ for (item = litem->items.last; item; item = item->prev) {
+ if (item->type == ITEM_BUTTON) {
+ bitem = (uiButtonItem *)item;
#ifndef USE_UIBUT_SPATIAL_ALIGN
- if (ui_but_can_align(bitem->but))
+ if (ui_but_can_align(bitem->but))
#endif
- {
- if (!bitem->but->alignnr) {
- bitem->but->alignnr = nr;
- }
- }
- }
- else if (item->type == ITEM_LAYOUT_ABSOLUTE) {
- /* pass */
- }
- else if (item->type == ITEM_LAYOUT_OVERLAP) {
- /* pass */
- }
- else if (item->type == ITEM_LAYOUT_BOX) {
- box = (uiLayoutItemBx *)item;
- if (!box->roundbox->alignnr) {
- box->roundbox->alignnr = nr;
- }
- }
- else if (((uiLayout *)item)->align) {
- ui_item_align((uiLayout *)item, nr);
- }
- }
+ {
+ if (!bitem->but->alignnr) {
+ bitem->but->alignnr = nr;
+ }
+ }
+ }
+ else if (item->type == ITEM_LAYOUT_ABSOLUTE) {
+ /* pass */
+ }
+ else if (item->type == ITEM_LAYOUT_OVERLAP) {
+ /* pass */
+ }
+ else if (item->type == ITEM_LAYOUT_BOX) {
+ box = (uiLayoutItemBx *)item;
+ if (!box->roundbox->alignnr) {
+ box->roundbox->alignnr = nr;
+ }
+ }
+ else if (((uiLayout *)item)->align) {
+ ui_item_align((uiLayout *)item, nr);
+ }
+ }
}
static void ui_item_flag(uiLayout *litem, int flag)
{
- uiItem *item;
- uiButtonItem *bitem;
+ uiItem *item;
+ uiButtonItem *bitem;
- for (item = litem->items.last; item; item = item->prev) {
- if (item->type == ITEM_BUTTON) {
- bitem = (uiButtonItem *)item;
- bitem->but->flag |= flag;
- }
- else {
- ui_item_flag((uiLayout *)item, flag);
- }
- }
+ for (item = litem->items.last; item; item = item->prev) {
+ if (item->type == ITEM_BUTTON) {
+ bitem = (uiButtonItem *)item;
+ bitem->but->flag |= flag;
+ }
+ else {
+ ui_item_flag((uiLayout *)item, flag);
+ }
+ }
}
static void ui_item_layout(uiItem *item)
{
- uiItem *subitem;
-
- if (item->type != ITEM_BUTTON) {
- uiLayout *litem = (uiLayout *)item;
-
- if (BLI_listbase_is_empty(&litem->items)) {
- return;
- }
-
- if (litem->align) {
- ui_item_align(litem, ++litem->root->block->alignnr);
- }
- if (!litem->active) {
- ui_item_flag(litem, UI_BUT_INACTIVE);
- }
- if (!litem->enabled) {
- ui_item_flag(litem, UI_BUT_DISABLED);
- }
-
- switch (litem->item.type) {
- case ITEM_LAYOUT_COLUMN:
- ui_litem_layout_column(litem, false);
- break;
- case ITEM_LAYOUT_COLUMN_FLOW:
- ui_litem_layout_column_flow(litem);
- break;
- case ITEM_LAYOUT_GRID_FLOW:
- ui_litem_layout_grid_flow(litem);
- break;
- case ITEM_LAYOUT_ROW:
- ui_litem_layout_row(litem);
- break;
- case ITEM_LAYOUT_BOX:
- ui_litem_layout_box(litem);
- break;
- case ITEM_LAYOUT_ROOT:
- ui_litem_layout_root(litem);
- break;
- case ITEM_LAYOUT_ABSOLUTE:
- ui_litem_layout_absolute(litem);
- break;
- case ITEM_LAYOUT_SPLIT:
- ui_litem_layout_split(litem);
- break;
- case ITEM_LAYOUT_OVERLAP:
- ui_litem_layout_overlap(litem);
- break;
- case ITEM_LAYOUT_RADIAL:
- ui_litem_layout_radial(litem);
- break;
- default:
- break;
- }
-
- for (subitem = litem->items.first; subitem; subitem = subitem->next) {
- if (item->flag & UI_ITEM_BOX_ITEM) {
- subitem->flag |= UI_ITEM_BOX_ITEM;
- }
- ui_item_layout(subitem);
- }
- }
- else {
- if (item->flag & UI_ITEM_BOX_ITEM) {
- uiButtonItem *bitem = (uiButtonItem *)item;
- bitem->but->drawflag |= UI_BUT_BOX_ITEM;
- }
- }
+ uiItem *subitem;
+
+ if (item->type != ITEM_BUTTON) {
+ uiLayout *litem = (uiLayout *)item;
+
+ if (BLI_listbase_is_empty(&litem->items)) {
+ return;
+ }
+
+ if (litem->align) {
+ ui_item_align(litem, ++litem->root->block->alignnr);
+ }
+ if (!litem->active) {
+ ui_item_flag(litem, UI_BUT_INACTIVE);
+ }
+ if (!litem->enabled) {
+ ui_item_flag(litem, UI_BUT_DISABLED);
+ }
+
+ switch (litem->item.type) {
+ case ITEM_LAYOUT_COLUMN:
+ ui_litem_layout_column(litem, false);
+ break;
+ case ITEM_LAYOUT_COLUMN_FLOW:
+ ui_litem_layout_column_flow(litem);
+ break;
+ case ITEM_LAYOUT_GRID_FLOW:
+ ui_litem_layout_grid_flow(litem);
+ break;
+ case ITEM_LAYOUT_ROW:
+ ui_litem_layout_row(litem);
+ break;
+ case ITEM_LAYOUT_BOX:
+ ui_litem_layout_box(litem);
+ break;
+ case ITEM_LAYOUT_ROOT:
+ ui_litem_layout_root(litem);
+ break;
+ case ITEM_LAYOUT_ABSOLUTE:
+ ui_litem_layout_absolute(litem);
+ break;
+ case ITEM_LAYOUT_SPLIT:
+ ui_litem_layout_split(litem);
+ break;
+ case ITEM_LAYOUT_OVERLAP:
+ ui_litem_layout_overlap(litem);
+ break;
+ case ITEM_LAYOUT_RADIAL:
+ ui_litem_layout_radial(litem);
+ break;
+ default:
+ break;
+ }
+
+ for (subitem = litem->items.first; subitem; subitem = subitem->next) {
+ if (item->flag & UI_ITEM_BOX_ITEM) {
+ subitem->flag |= UI_ITEM_BOX_ITEM;
+ }
+ ui_item_layout(subitem);
+ }
+ }
+ else {
+ if (item->flag & UI_ITEM_BOX_ITEM) {
+ uiButtonItem *bitem = (uiButtonItem *)item;
+ bitem->but->drawflag |= UI_BUT_BOX_ITEM;
+ }
+ }
}
static void ui_layout_end(uiBlock *block, uiLayout *layout, int *r_x, int *r_y)
{
- if (layout->root->handlefunc) {
- UI_block_func_handle_set(block, layout->root->handlefunc, layout->root->argv);
- }
+ if (layout->root->handlefunc) {
+ UI_block_func_handle_set(block, layout->root->handlefunc, layout->root->argv);
+ }
- ui_item_estimate(&layout->item);
- ui_item_layout(&layout->item);
+ ui_item_estimate(&layout->item);
+ ui_item_layout(&layout->item);
- if (r_x) {
- *r_x = layout->x;
- }
- if (r_y) {
- *r_y = layout->y;
- }
+ if (r_x) {
+ *r_x = layout->x;
+ }
+ if (r_y) {
+ *r_y = layout->y;
+ }
}
static void ui_layout_free(uiLayout *layout)
{
- uiItem *item, *next;
+ uiItem *item, *next;
- for (item = layout->items.first; item; item = next) {
- next = item->next;
+ for (item = layout->items.first; item; item = next) {
+ next = item->next;
- if (item->type == ITEM_BUTTON) {
- MEM_freeN(item);
- }
- else {
- ui_layout_free((uiLayout *)item);
- }
- }
+ if (item->type == ITEM_BUTTON) {
+ MEM_freeN(item);
+ }
+ else {
+ ui_layout_free((uiLayout *)item);
+ }
+ }
- MEM_freeN(layout);
+ MEM_freeN(layout);
}
static void ui_layout_add_padding_button(uiLayoutRoot *root)
{
- if (root->padding) {
- /* add an invisible button for padding */
- uiBlock *block = root->block;
- uiLayout *prev_layout = block->curlayout;
+ if (root->padding) {
+ /* add an invisible button for padding */
+ uiBlock *block = root->block;
+ uiLayout *prev_layout = block->curlayout;
- block->curlayout = root->layout;
- uiDefBut(block, UI_BTYPE_SEPR, 0, "", 0, 0, root->padding, root->padding, NULL, 0.0, 0.0, 0, 0, "");
- block->curlayout = prev_layout;
- }
+ block->curlayout = root->layout;
+ uiDefBut(
+ block, UI_BTYPE_SEPR, 0, "", 0, 0, root->padding, root->padding, NULL, 0.0, 0.0, 0, 0, "");
+ block->curlayout = prev_layout;
+ }
}
-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, uiStyle *style)
{
- uiLayout *layout;
- uiLayoutRoot *root;
+ uiLayout *layout;
+ uiLayoutRoot *root;
- root = MEM_callocN(sizeof(uiLayoutRoot), "uiLayoutRoot");
- root->type = type;
- root->style = style;
- root->block = block;
- root->padding = padding;
- root->opcontext = WM_OP_INVOKE_REGION_WIN;
+ root = MEM_callocN(sizeof(uiLayoutRoot), "uiLayoutRoot");
+ root->type = type;
+ root->style = style;
+ root->block = block;
+ root->padding = padding;
+ root->opcontext = WM_OP_INVOKE_REGION_WIN;
- layout = MEM_callocN(sizeof(uiLayout), "uiLayout");
- layout->item.type = (type == UI_LAYOUT_VERT_BAR) ? ITEM_LAYOUT_COLUMN : ITEM_LAYOUT_ROOT;
+ layout = MEM_callocN(sizeof(uiLayout), "uiLayout");
+ layout->item.type = (type == UI_LAYOUT_VERT_BAR) ? ITEM_LAYOUT_COLUMN : ITEM_LAYOUT_ROOT;
- /* Only used when 'UI_ITEM_PROP_SEP' is set. */
- layout->item.flag = UI_ITEM_PROP_DECORATE;
+ /* Only used when 'UI_ITEM_PROP_SEP' is set. */
+ layout->item.flag = UI_ITEM_PROP_DECORATE;
- layout->x = x;
- layout->y = y;
- layout->root = root;
- layout->space = style->templatespace;
- layout->active = 1;
- layout->enabled = 1;
- layout->context = NULL;
- layout->emboss = UI_EMBOSS_UNDEFINED;
+ layout->x = x;
+ layout->y = y;
+ layout->root = root;
+ layout->space = style->templatespace;
+ layout->active = 1;
+ layout->enabled = 1;
+ layout->context = NULL;
+ layout->emboss = UI_EMBOSS_UNDEFINED;
- if (type == UI_LAYOUT_MENU || type == UI_LAYOUT_PIEMENU) {
- layout->space = 0;
- }
+ if (type == UI_LAYOUT_MENU || type == UI_LAYOUT_PIEMENU) {
+ layout->space = 0;
+ }
- if (dir == UI_LAYOUT_HORIZONTAL) {
- layout->h = size;
- layout->root->emh = em * UI_UNIT_Y;
- }
- else {
- layout->w = size;
- layout->root->emw = em * UI_UNIT_X;
- }
+ if (dir == UI_LAYOUT_HORIZONTAL) {
+ layout->h = size;
+ layout->root->emh = em * UI_UNIT_Y;
+ }
+ else {
+ layout->w = size;
+ layout->root->emw = em * UI_UNIT_X;
+ }
- block->curlayout = layout;
- root->layout = layout;
- BLI_addtail(&block->layouts, root);
+ block->curlayout = layout;
+ root->layout = layout;
+ BLI_addtail(&block->layouts, root);
- ui_layout_add_padding_button(root);
+ ui_layout_add_padding_button(root);
- return layout;
+ return layout;
}
uiBlock *uiLayoutGetBlock(uiLayout *layout)
{
- return layout->root->block;
+ return layout->root->block;
}
int uiLayoutGetOperatorContext(uiLayout *layout)
{
- return layout->root->opcontext;
+ return layout->root->opcontext;
}
-
void UI_block_layout_set_current(uiBlock *block, uiLayout *layout)
{
- block->curlayout = layout;
+ block->curlayout = layout;
}
void ui_layout_add_but(uiLayout *layout, uiBut *but)
{
- uiButtonItem *bitem;
+ uiButtonItem *bitem;
- bitem = MEM_callocN(sizeof(uiButtonItem), "uiButtonItem");
- bitem->item.type = ITEM_BUTTON;
- bitem->but = but;
+ bitem = MEM_callocN(sizeof(uiButtonItem), "uiButtonItem");
+ bitem->item.type = ITEM_BUTTON;
+ bitem->but = but;
- int w, h;
- ui_item_size((uiItem *)bitem, &w, &h);
- /* XXX uiBut hasn't scaled yet
- * we can flag the button as not expandable, depending on its size */
- if (w <= 2 * UI_UNIT_X && (!but->str || but->str[0] == '\0')) {
- bitem->item.flag |= UI_ITEM_MIN;
- }
+ int w, h;
+ ui_item_size((uiItem *)bitem, &w, &h);
+ /* XXX uiBut hasn't scaled yet
+ * we can flag the button as not expandable, depending on its size */
+ if (w <= 2 * UI_UNIT_X && (!but->str || but->str[0] == '\0')) {
+ bitem->item.flag |= UI_ITEM_MIN;
+ }
- if (layout->child_items_layout) {
- BLI_addtail(&layout->child_items_layout->items, bitem);
- }
- else {
- BLI_addtail(&layout->items, bitem);
- }
+ if (layout->child_items_layout) {
+ BLI_addtail(&layout->child_items_layout->items, bitem);
+ }
+ else {
+ BLI_addtail(&layout->items, bitem);
+ }
- if (layout->context) {
- but->context = layout->context;
- but->context->used = true;
- }
+ if (layout->context) {
+ but->context = layout->context;
+ but->context->used = true;
+ }
- if (layout->emboss != UI_EMBOSS_UNDEFINED) {
- but->dt = layout->emboss;
- }
+ if (layout->emboss != UI_EMBOSS_UNDEFINED) {
+ but->dt = layout->emboss;
+ }
}
void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext)
{
- layout->root->opcontext = opcontext;
+ layout->root->opcontext = opcontext;
}
void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv)
{
- layout->root->handlefunc = handlefunc;
- layout->root->argv = argv;
+ layout->root->handlefunc = handlefunc;
+ layout->root->argv = argv;
}
void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y)
{
- uiLayoutRoot *root;
+ uiLayoutRoot *root;
- BLI_assert(block->active);
+ BLI_assert(block->active);
- if (r_x) {
- *r_x = 0;
- }
- if (r_y) {
- *r_y = 0;
- }
+ if (r_x) {
+ *r_x = 0;
+ }
+ if (r_y) {
+ *r_y = 0;
+ }
- block->curlayout = NULL;
+ block->curlayout = NULL;
- for (root = block->layouts.first; root; root = root->next) {
- ui_layout_add_padding_button(root);
+ for (root = block->layouts.first; root; root = root->next) {
+ ui_layout_add_padding_button(root);
- /* NULL in advance so we don't interfere when adding button */
- ui_layout_end(block, root->layout, r_x, r_y);
- ui_layout_free(root->layout);
- }
+ /* NULL in advance so we don't interfere when adding button */
+ ui_layout_end(block, root->layout, r_x, r_y);
+ ui_layout_free(root->layout);
+ }
- BLI_freelistN(&block->layouts);
+ BLI_freelistN(&block->layouts);
- /* XXX silly trick, interface_templates.c doesn't get linked
- * because it's not used by other files in this module? */
- {
- UI_template_fix_linking();
- }
+ /* XXX silly trick, interface_templates.c doesn't get linked
+ * because it's not used by other files in this module? */
+ {
+ UI_template_fix_linking();
+ }
}
void uiLayoutSetContextPointer(uiLayout *layout, const char *name, PointerRNA *ptr)
{
- uiBlock *block = layout->root->block;
- layout->context = CTX_store_add(&block->contexts, name, ptr);
+ uiBlock *block = layout->root->block;
+ layout->context = CTX_store_add(&block->contexts, name, ptr);
}
void uiLayoutContextCopy(uiLayout *layout, bContextStore *context)
{
- uiBlock *block = layout->root->block;
- layout->context = CTX_store_add_all(&block->contexts, context);
+ uiBlock *block = layout->root->block;
+ layout->context = CTX_store_add_all(&block->contexts, context);
}
void uiLayoutSetContextFromBut(uiLayout *layout, uiBut *but)
{
- if (but->opptr) {
- uiLayoutSetContextPointer(layout, "button_operator", but->opptr);
- }
+ if (but->opptr) {
+ uiLayoutSetContextPointer(layout, "button_operator", but->opptr);
+ }
- if (but->rnapoin.data && but->rnaprop) {
- /* TODO: index could be supported as well */
- PointerRNA ptr_prop;
- RNA_pointer_create(NULL, &RNA_Property, but->rnaprop, &ptr_prop);
- uiLayoutSetContextPointer(layout, "button_prop", &ptr_prop);
- uiLayoutSetContextPointer(layout, "button_pointer", &but->rnapoin);
- }
+ if (but->rnapoin.data && but->rnaprop) {
+ /* TODO: index could be supported as well */
+ PointerRNA ptr_prop;
+ RNA_pointer_create(NULL, &RNA_Property, but->rnaprop, &ptr_prop);
+ uiLayoutSetContextPointer(layout, "button_prop", &ptr_prop);
+ uiLayoutSetContextPointer(layout, "button_pointer", &but->rnapoin);
+ }
}
/* this is a bit of a hack but best keep it in one place at least */
MenuType *UI_but_menutype_get(uiBut *but)
{
- if (but->menu_create_func == ui_item_menutype_func) {
- return (MenuType *)but->poin;
- }
- else {
- return NULL;
- }
+ if (but->menu_create_func == ui_item_menutype_func) {
+ return (MenuType *)but->poin;
+ }
+ else {
+ return NULL;
+ }
}
/* this is a bit of a hack but best keep it in one place at least */
PanelType *UI_but_paneltype_get(uiBut *but)
{
- if (but->menu_create_func == ui_item_paneltype_func) {
- return (PanelType *)but->poin;
- }
- else {
- return NULL;
- }
+ if (but->menu_create_func == ui_item_paneltype_func) {
+ return (PanelType *)but->poin;
+ }
+ else {
+ return NULL;
+ }
}
-
void UI_menutype_draw(bContext *C, MenuType *mt, struct uiLayout *layout)
{
- Menu menu = {
- .layout = layout,
- .type = mt,
- };
+ Menu menu = {
+ .layout = layout,
+ .type = mt,
+ };
- if (G.debug & G_DEBUG_WM) {
- printf("%s: opening menu \"%s\"\n", __func__, mt->idname);
- }
+ if (G.debug & G_DEBUG_WM) {
+ printf("%s: opening menu \"%s\"\n", __func__, mt->idname);
+ }
- if (layout->context) {
- CTX_store_set(C, layout->context);
- }
+ if (layout->context) {
+ CTX_store_set(C, layout->context);
+ }
- mt->draw(C, &menu);
+ mt->draw(C, &menu);
- if (layout->context) {
- CTX_store_set(C, NULL);
- }
+ if (layout->context) {
+ CTX_store_set(C, NULL);
+ }
}
-
-static void ui_paneltype_draw_impl(
- bContext *C, PanelType *pt, uiLayout *layout, bool show_header)
+static void ui_paneltype_draw_impl(bContext *C, PanelType *pt, uiLayout *layout, bool show_header)
{
- Panel *panel = MEM_callocN(sizeof(Panel), "popover panel");
- panel->type = pt;
- panel->flag = PNL_POPOVER;
+ Panel *panel = MEM_callocN(sizeof(Panel), "popover panel");
+ panel->type = pt;
+ panel->flag = PNL_POPOVER;
- uiLayout *last_item = layout->items.last;
+ uiLayout *last_item = layout->items.last;
- /* Draw main panel. */
- if (show_header) {
- uiLayout *row = uiLayoutRow(layout, false);
- if (pt->draw_header) {
- panel->layout = row;
- pt->draw_header(C, panel);
- panel->layout = NULL;
- }
- uiItemL(row, pt->label, ICON_NONE);
- }
+ /* Draw main panel. */
+ if (show_header) {
+ uiLayout *row = uiLayoutRow(layout, false);
+ if (pt->draw_header) {
+ panel->layout = row;
+ pt->draw_header(C, panel);
+ panel->layout = NULL;
+ }
+ uiItemL(row, pt->label, ICON_NONE);
+ }
- panel->layout = layout;
- pt->draw(C, panel);
- panel->layout = NULL;
+ panel->layout = layout;
+ pt->draw(C, panel);
+ panel->layout = NULL;
- MEM_freeN(panel);
+ MEM_freeN(panel);
- /* Draw child panels. */
- for (LinkData *link = pt->children.first; link; link = link->next) {
- PanelType *child_pt = link->data;
+ /* Draw child panels. */
+ for (LinkData *link = pt->children.first; link; link = link->next) {
+ PanelType *child_pt = link->data;
- if (child_pt->poll == NULL || child_pt->poll(C, child_pt)) {
- /* Add space if something was added to the layout. */
- if (last_item != layout->items.last) {
- uiItemS(layout);
- last_item = layout->items.last;
- }
+ if (child_pt->poll == NULL || child_pt->poll(C, child_pt)) {
+ /* Add space if something was added to the layout. */
+ if (last_item != layout->items.last) {
+ uiItemS(layout);
+ last_item = layout->items.last;
+ }
- uiLayout *col = uiLayoutColumn(layout, false);
- ui_paneltype_draw_impl(C, child_pt, col, true);
- }
- }
+ uiLayout *col = uiLayoutColumn(layout, false);
+ ui_paneltype_draw_impl(C, child_pt, col, true);
+ }
+ }
}
/**
@@ -4826,14 +5203,13 @@ static void ui_paneltype_draw_impl(
*/
void UI_paneltype_draw(bContext *C, PanelType *pt, uiLayout *layout)
{
- if (layout->context) {
- CTX_store_set(C, layout->context);
- }
-
- ui_paneltype_draw_impl(C, pt, layout, false);
+ if (layout->context) {
+ CTX_store_set(C, layout->context);
+ }
- if (layout->context) {
- CTX_store_set(C, NULL);
- }
+ ui_paneltype_draw_impl(C, pt, layout, false);
+ if (layout->context) {
+ CTX_store_set(C, NULL);
+ }
}
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index e00ea2d16bd..537a1d4c851 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -27,7 +27,7 @@
#include "DNA_armature_types.h"
#include "DNA_screen_types.h"
-#include "DNA_text_types.h" /* for UI_OT_reports_to_text */
+#include "DNA_text_types.h" /* for UI_OT_reports_to_text */
#include "DNA_object_types.h" /* for OB_DATA_SUPPORT_ID */
#include "BLI_blenlib.h"
@@ -76,92 +76,92 @@
static bool copy_data_path_button_poll(bContext *C)
{
- PointerRNA ptr;
- PropertyRNA *prop;
- char *path;
- int index;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ char *path;
+ int index;
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- if (ptr.id.data && ptr.data && prop) {
- path = RNA_path_from_ID_to_property(&ptr, prop);
+ if (ptr.id.data && ptr.data && prop) {
+ path = RNA_path_from_ID_to_property(&ptr, prop);
- if (path) {
- MEM_freeN(path);
- return 1;
- }
- }
+ if (path) {
+ MEM_freeN(path);
+ return 1;
+ }
+ }
- return 0;
+ return 0;
}
static int copy_data_path_button_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr;
- PropertyRNA *prop;
- char *path;
- int index;
-
- const bool full_path = RNA_boolean_get(op->ptr, "full_path");
-
- /* try to create driver using property retrieved from UI */
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
-
- if (ptr.id.data != NULL) {
-
- if (full_path) {
-
- if (prop) {
- path = RNA_path_full_property_py_ex(&ptr, prop, index, true);
- }
- else {
- path = RNA_path_full_struct_py(&ptr);
- }
- }
- else {
- path = RNA_path_from_ID_to_property(&ptr, prop);
- }
-
- if (path) {
- WM_clipboard_text_set(path, false);
- MEM_freeN(path);
- return OPERATOR_FINISHED;
- }
- }
-
- return OPERATOR_CANCELLED;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ char *path;
+ int index;
+
+ const bool full_path = RNA_boolean_get(op->ptr, "full_path");
+
+ /* try to create driver using property retrieved from UI */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ if (ptr.id.data != NULL) {
+
+ if (full_path) {
+
+ if (prop) {
+ path = RNA_path_full_property_py_ex(&ptr, prop, index, true);
+ }
+ else {
+ path = RNA_path_full_struct_py(&ptr);
+ }
+ }
+ else {
+ path = RNA_path_from_ID_to_property(&ptr, prop);
+ }
+
+ if (path) {
+ WM_clipboard_text_set(path, false);
+ MEM_freeN(path);
+ return OPERATOR_FINISHED;
+ }
+ }
+
+ return OPERATOR_CANCELLED;
}
static void UI_OT_copy_data_path_button(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Copy Data Path";
- ot->idname = "UI_OT_copy_data_path_button";
- ot->description = "Copy the RNA data path for this property to the clipboard";
+ /* identifiers */
+ ot->name = "Copy Data Path";
+ ot->idname = "UI_OT_copy_data_path_button";
+ ot->description = "Copy the RNA data path for this property to the clipboard";
- /* callbacks */
- ot->exec = copy_data_path_button_exec;
- ot->poll = copy_data_path_button_poll;
+ /* callbacks */
+ ot->exec = copy_data_path_button_exec;
+ ot->poll = copy_data_path_button_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
- /* properties */
- prop = RNA_def_boolean(ot->srna, "full_path", false, "full_path", "Copy full data path");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "full_path", false, "full_path", "Copy full data path");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static bool copy_python_command_button_poll(bContext *C)
{
- uiBut *but = UI_context_active_but_get(C);
+ uiBut *but = UI_context_active_but_get(C);
- if (but && (but->optype != NULL)) {
- return 1;
- }
+ if (but && (but->optype != NULL)) {
+ return 1;
+ }
- return 0;
+ return 0;
}
/** \} */
@@ -172,38 +172,38 @@ static bool copy_python_command_button_poll(bContext *C)
static int copy_python_command_button_exec(bContext *C, wmOperator *UNUSED(op))
{
- uiBut *but = UI_context_active_but_get(C);
+ uiBut *but = UI_context_active_but_get(C);
- if (but && (but->optype != NULL)) {
- PointerRNA *opptr;
- char *str;
- opptr = UI_but_operator_ptr_get(but); /* allocated when needed, the button owns it */
+ if (but && (but->optype != NULL)) {
+ PointerRNA *opptr;
+ char *str;
+ opptr = UI_but_operator_ptr_get(but); /* allocated when needed, the button owns it */
- str = WM_operator_pystring_ex(C, NULL, false, true, but->optype, opptr);
+ str = WM_operator_pystring_ex(C, NULL, false, true, but->optype, opptr);
- WM_clipboard_text_set(str, 0);
+ WM_clipboard_text_set(str, 0);
- MEM_freeN(str);
+ MEM_freeN(str);
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
static void UI_OT_copy_python_command_button(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Python Command";
- ot->idname = "UI_OT_copy_python_command_button";
- ot->description = "Copy the Python command matching this button";
+ /* identifiers */
+ ot->name = "Copy Python Command";
+ ot->idname = "UI_OT_copy_python_command_button";
+ ot->description = "Copy the Python command matching this button";
- /* callbacks */
- ot->exec = copy_python_command_button_exec;
- ot->poll = copy_python_command_button_poll;
+ /* callbacks */
+ ot->exec = copy_python_command_button_exec;
+ ot->poll = copy_python_command_button_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
}
/** \} */
@@ -214,73 +214,73 @@ static void UI_OT_copy_python_command_button(wmOperatorType *ot)
static int operator_button_property_finish(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
{
- ID *id = ptr->id.data;
-
- /* perform updates required for this property */
- RNA_property_update(C, ptr, prop);
-
- /* as if we pressed the button */
- UI_context_active_but_prop_handle(C);
-
- /* Since we don't want to undo _all_ edits to settings, eg window
- * edits on the screen or on operator settings.
- * it might be better to move undo's inline - campbell */
- if (id && ID_CHECK_UNDO(id)) {
- /* do nothing, go ahead with undo */
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ ID *id = ptr->id.data;
+
+ /* perform updates required for this property */
+ RNA_property_update(C, ptr, prop);
+
+ /* as if we pressed the button */
+ UI_context_active_but_prop_handle(C);
+
+ /* Since we don't want to undo _all_ edits to settings, eg window
+ * edits on the screen or on operator settings.
+ * it might be better to move undo's inline - campbell */
+ if (id && ID_CHECK_UNDO(id)) {
+ /* do nothing, go ahead with undo */
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static bool reset_default_button_poll(bContext *C)
{
- PointerRNA ptr;
- PropertyRNA *prop;
- int index;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- return (ptr.data && prop && RNA_property_editable(&ptr, prop));
+ return (ptr.data && prop && RNA_property_editable(&ptr, prop));
}
static int reset_default_button_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr;
- PropertyRNA *prop;
- int index;
- const bool all = RNA_boolean_get(op->ptr, "all");
-
- /* try to reset the nominated setting to its default value */
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
-
- /* if there is a valid property that is editable... */
- if (ptr.data && prop && RNA_property_editable(&ptr, prop)) {
- if (RNA_property_reset(&ptr, prop, (all) ? -1 : index)) {
- return operator_button_property_finish(C, &ptr, prop);
- }
- }
-
- return OPERATOR_CANCELLED;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+ const bool all = RNA_boolean_get(op->ptr, "all");
+
+ /* try to reset the nominated setting to its default value */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ /* if there is a valid property that is editable... */
+ if (ptr.data && prop && RNA_property_editable(&ptr, prop)) {
+ if (RNA_property_reset(&ptr, prop, (all) ? -1 : index)) {
+ return operator_button_property_finish(C, &ptr, prop);
+ }
+ }
+
+ return OPERATOR_CANCELLED;
}
static void UI_OT_reset_default_button(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reset to Default Value";
- ot->idname = "UI_OT_reset_default_button";
- ot->description = "Reset this property's value to its default value";
+ /* identifiers */
+ ot->name = "Reset to Default Value";
+ ot->idname = "UI_OT_reset_default_button";
+ ot->description = "Reset this property's value to its default value";
- /* callbacks */
- ot->poll = reset_default_button_poll;
- ot->exec = reset_default_button_exec;
+ /* callbacks */
+ ot->poll = reset_default_button_poll;
+ ot->exec = reset_default_button_exec;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
}
/** \} */
@@ -291,53 +291,54 @@ static void UI_OT_reset_default_button(wmOperatorType *ot)
static bool assign_default_button_poll(bContext *C)
{
- PointerRNA ptr;
- PropertyRNA *prop;
- int index;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- if (ptr.data && prop && RNA_property_editable(&ptr, prop)) {
- PropertyType type = RNA_property_type(prop);
+ if (ptr.data && prop && RNA_property_editable(&ptr, prop)) {
+ PropertyType type = RNA_property_type(prop);
- return RNA_property_is_idprop(prop) && !RNA_property_array_check(prop) && ELEM(type, PROP_INT, PROP_FLOAT);
- }
+ return RNA_property_is_idprop(prop) && !RNA_property_array_check(prop) &&
+ ELEM(type, PROP_INT, PROP_FLOAT);
+ }
- return false;
+ return false;
}
static int assign_default_button_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr;
- PropertyRNA *prop;
- int index;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
- /* try to reset the nominated setting to its default value */
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+ /* try to reset the nominated setting to its default value */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- /* if there is a valid property that is editable... */
- if (ptr.data && prop && RNA_property_editable(&ptr, prop)) {
- if (RNA_property_assign_default(&ptr, prop)) {
- return operator_button_property_finish(C, &ptr, prop);
- }
- }
+ /* if there is a valid property that is editable... */
+ if (ptr.data && prop && RNA_property_editable(&ptr, prop)) {
+ if (RNA_property_assign_default(&ptr, prop)) {
+ return operator_button_property_finish(C, &ptr, prop);
+ }
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
static void UI_OT_assign_default_button(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Assign Value as Default";
- ot->idname = "UI_OT_assign_default_button";
- ot->description = "Set this property's current value as the new default";
+ /* identifiers */
+ ot->name = "Assign Value as Default";
+ ot->idname = "UI_OT_assign_default_button";
+ ot->description = "Set this property's current value as the new default";
- /* callbacks */
- ot->poll = assign_default_button_poll;
- ot->exec = assign_default_button_exec;
+ /* callbacks */
+ ot->poll = assign_default_button_poll;
+ ot->exec = assign_default_button_exec;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/** \} */
@@ -348,38 +349,37 @@ static void UI_OT_assign_default_button(wmOperatorType *ot)
static int unset_property_button_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr;
- PropertyRNA *prop;
- int index;
-
- /* try to unset the nominated property */
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
-
- /* if there is a valid property that is editable... */
- if (ptr.data && prop && RNA_property_editable(&ptr, prop) &&
- /* RNA_property_is_idprop(prop) && */
- RNA_property_is_set(&ptr, prop))
- {
- RNA_property_unset(&ptr, prop);
- return operator_button_property_finish(C, &ptr, prop);
- }
-
- return OPERATOR_CANCELLED;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+
+ /* try to unset the nominated property */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ /* if there is a valid property that is editable... */
+ if (ptr.data && prop && RNA_property_editable(&ptr, prop) &&
+ /* RNA_property_is_idprop(prop) && */
+ RNA_property_is_set(&ptr, prop)) {
+ RNA_property_unset(&ptr, prop);
+ return operator_button_property_finish(C, &ptr, prop);
+ }
+
+ return OPERATOR_CANCELLED;
}
static void UI_OT_unset_property_button(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unset property";
- ot->idname = "UI_OT_unset_property_button";
- ot->description = "Clear the property and use default or generated value in operators";
+ /* identifiers */
+ ot->name = "Unset property";
+ ot->idname = "UI_OT_unset_property_button";
+ ot->description = "Clear the property and use default or generated value in operators";
- /* callbacks */
- ot->poll = ED_operator_regionactive;
- ot->exec = unset_property_button_exec;
+ /* callbacks */
+ ot->poll = ED_operator_regionactive;
+ ot->exec = unset_property_button_exec;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/** \} */
@@ -391,211 +391,230 @@ static void UI_OT_unset_property_button(wmOperatorType *ot)
/* Note that we use different values for UI/UX than 'real' override operations, user does not care
* whether it's added or removed for the differential operation e.g. */
enum {
- UIOverride_Type_NOOP = 0,
- UIOverride_Type_Replace = 1,
- UIOverride_Type_Difference = 2, /* Add/subtract */
- UIOverride_Type_Factor = 3, /* Multiply */
- /* TODO: should/can we expose insert/remove ones for collections? Doubt it... */
+ UIOverride_Type_NOOP = 0,
+ UIOverride_Type_Replace = 1,
+ UIOverride_Type_Difference = 2, /* Add/subtract */
+ UIOverride_Type_Factor = 3, /* Multiply */
+ /* TODO: should/can we expose insert/remove ones for collections? Doubt it... */
};
static EnumPropertyItem override_type_items[] = {
- {UIOverride_Type_NOOP, "NOOP", 0, "NoOp",
- "'No-Operation', place holder preventing automatic override to ever affect the property"},
- {UIOverride_Type_Replace, "REPLACE", 0, "Replace", "Completely replace value from linked data by local one"},
- {UIOverride_Type_Difference, "DIFFERENCE", 0, "Difference", "Store difference to linked data value"},
- {UIOverride_Type_Factor, "FACTOR", 0, "Factor", "Store factor to linked data value (useful e.g. for scale)"},
- {0, NULL, 0, NULL, NULL},
+ {UIOverride_Type_NOOP,
+ "NOOP",
+ 0,
+ "NoOp",
+ "'No-Operation', place holder preventing automatic override to ever affect the property"},
+ {UIOverride_Type_Replace,
+ "REPLACE",
+ 0,
+ "Replace",
+ "Completely replace value from linked data by local one"},
+ {UIOverride_Type_Difference,
+ "DIFFERENCE",
+ 0,
+ "Difference",
+ "Store difference to linked data value"},
+ {UIOverride_Type_Factor,
+ "FACTOR",
+ 0,
+ "Factor",
+ "Store factor to linked data value (useful e.g. for scale)"},
+ {0, NULL, 0, NULL, NULL},
};
-
static bool override_type_set_button_poll(bContext *C)
{
- PointerRNA ptr;
- PropertyRNA *prop;
- int index;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- const int override_status = RNA_property_static_override_status(&ptr, prop, index);
+ const int override_status = RNA_property_static_override_status(&ptr, prop, index);
- return (ptr.data && prop && (override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE));
+ return (ptr.data && prop && (override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE));
}
static int override_type_set_button_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr;
- PropertyRNA *prop;
- int index;
- bool created;
- const bool all = RNA_boolean_get(op->ptr, "all");
- const int op_type = RNA_enum_get(op->ptr, "type");
-
- short operation;
-
- switch (op_type) {
- case UIOverride_Type_NOOP:
- operation = IDOVERRIDESTATIC_OP_NOOP;
- break;
- case UIOverride_Type_Replace:
- operation = IDOVERRIDESTATIC_OP_REPLACE;
- break;
- case UIOverride_Type_Difference:
- /* override code will automatically switch to subtract if needed. */
- operation = IDOVERRIDESTATIC_OP_ADD;
- break;
- case UIOverride_Type_Factor:
- operation = IDOVERRIDESTATIC_OP_MULTIPLY;
- break;
- default:
- operation = IDOVERRIDESTATIC_OP_REPLACE;
- BLI_assert(0);
- break;
- }
-
- /* try to reset the nominated setting to its default value */
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
-
- BLI_assert(ptr.id.data != NULL);
-
- if (all) {
- index = -1;
- }
-
- IDOverrideStaticPropertyOperation *opop = RNA_property_override_property_operation_get(
- &ptr, prop, operation, index, true, NULL, &created);
- if (!created) {
- opop->operation = operation;
- }
-
- return operator_button_property_finish(C, &ptr, prop);
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+ bool created;
+ const bool all = RNA_boolean_get(op->ptr, "all");
+ const int op_type = RNA_enum_get(op->ptr, "type");
+
+ short operation;
+
+ switch (op_type) {
+ case UIOverride_Type_NOOP:
+ operation = IDOVERRIDESTATIC_OP_NOOP;
+ break;
+ case UIOverride_Type_Replace:
+ operation = IDOVERRIDESTATIC_OP_REPLACE;
+ break;
+ case UIOverride_Type_Difference:
+ /* override code will automatically switch to subtract if needed. */
+ operation = IDOVERRIDESTATIC_OP_ADD;
+ break;
+ case UIOverride_Type_Factor:
+ operation = IDOVERRIDESTATIC_OP_MULTIPLY;
+ break;
+ default:
+ operation = IDOVERRIDESTATIC_OP_REPLACE;
+ BLI_assert(0);
+ break;
+ }
+
+ /* try to reset the nominated setting to its default value */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ BLI_assert(ptr.id.data != NULL);
+
+ if (all) {
+ index = -1;
+ }
+
+ IDOverrideStaticPropertyOperation *opop = RNA_property_override_property_operation_get(
+ &ptr, prop, operation, index, true, NULL, &created);
+ if (!created) {
+ opop->operation = operation;
+ }
+
+ return operator_button_property_finish(C, &ptr, prop);
}
-static int override_type_set_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int override_type_set_button_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
{
-#if 0 /* Disabled for now */
- return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_DEFAULT);
+#if 0 /* Disabled for now */
+ return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_DEFAULT);
#else
- RNA_enum_set(op->ptr, "type", IDOVERRIDESTATIC_OP_REPLACE);
- return override_type_set_button_exec(C, op);
+ RNA_enum_set(op->ptr, "type", IDOVERRIDESTATIC_OP_REPLACE);
+ return override_type_set_button_exec(C, op);
#endif
}
static void UI_OT_override_type_set_button(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Define Override Type";
- ot->idname = "UI_OT_override_type_set_button";
- ot->description = "Create an override operation, or set the type of an existing one";
-
- /* callbacks */
- ot->poll = override_type_set_button_poll;
- ot->exec = override_type_set_button_exec;
- ot->invoke = override_type_set_button_invoke;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
- ot->prop = RNA_def_enum(
- ot->srna, "type", override_type_items, UIOverride_Type_Replace,
- "Type", "Type of override operation");
- /* TODO: add itemf callback, not all options are available for all data types... */
+ /* identifiers */
+ ot->name = "Define Override Type";
+ ot->idname = "UI_OT_override_type_set_button";
+ ot->description = "Create an override operation, or set the type of an existing one";
+
+ /* callbacks */
+ ot->poll = override_type_set_button_poll;
+ ot->exec = override_type_set_button_exec;
+ ot->invoke = override_type_set_button_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
+ ot->prop = RNA_def_enum(ot->srna,
+ "type",
+ override_type_items,
+ UIOverride_Type_Replace,
+ "Type",
+ "Type of override operation");
+ /* TODO: add itemf callback, not all options are available for all data types... */
}
-
static bool override_remove_button_poll(bContext *C)
{
- PointerRNA ptr;
- PropertyRNA *prop;
- int index;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- const int override_status = RNA_property_static_override_status(&ptr, prop, index);
+ const int override_status = RNA_property_static_override_status(&ptr, prop, index);
- return (ptr.data && ptr.id.data && prop && (override_status & RNA_OVERRIDE_STATUS_OVERRIDDEN));
+ return (ptr.data && ptr.id.data && prop && (override_status & RNA_OVERRIDE_STATUS_OVERRIDDEN));
}
static int override_remove_button_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- PointerRNA ptr, id_refptr, src;
- PropertyRNA *prop;
- int index;
- const bool all = RNA_boolean_get(op->ptr, "all");
-
- /* try to reset the nominated setting to its default value */
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
-
- ID *id = ptr.id.data;
- IDOverrideStaticProperty *oprop = RNA_property_override_property_find(&ptr, prop);
- BLI_assert(oprop != NULL);
- BLI_assert(id != NULL && id->override_static != NULL);
-
- const bool is_template = (id->override_static->reference == NULL);
-
- /* We need source (i.e. linked data) to restore values of deleted overrides...
- * If this is an override template, we obviously do not need to restore anything. */
- if (!is_template) {
- RNA_id_pointer_create(id->override_static->reference, &id_refptr);
- if (!RNA_path_resolve(&id_refptr, oprop->rna_path, &src, NULL)) {
- BLI_assert(0 && "Failed to create matching source (linked data) RNA pointer");
- }
- }
-
- if (!all && index != -1) {
- bool is_strict_find;
- /* Remove override operation for given item,
- * add singular operations for the other items as needed. */
- IDOverrideStaticPropertyOperation *opop = BKE_override_static_property_operation_find(
- oprop, NULL, NULL, index, index, false, &is_strict_find);
- BLI_assert(opop != NULL);
- if (!is_strict_find) {
- /* No specific override operation, we have to get generic one,
- * and create item-specific override operations for all but given index,
- * before removing generic one. */
- for (int idx = RNA_property_array_length(&ptr, prop); idx--; ) {
- if (idx != index) {
- BKE_override_static_property_operation_get(oprop, opop->operation, NULL, NULL, idx, idx, true, NULL, NULL);
- }
- }
- }
- BKE_override_static_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_static_property_delete(id->override_static, oprop);
- }
- }
- else {
- /* Just remove whole generic override operation of this property. */
- BKE_override_static_property_delete(id->override_static, oprop);
- if (!is_template) {
- RNA_property_copy(bmain, &ptr, &src, prop, -1);
- }
- }
-
- return operator_button_property_finish(C, &ptr, prop);
+ Main *bmain = CTX_data_main(C);
+ PointerRNA ptr, id_refptr, src;
+ PropertyRNA *prop;
+ int index;
+ const bool all = RNA_boolean_get(op->ptr, "all");
+
+ /* try to reset the nominated setting to its default value */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ ID *id = ptr.id.data;
+ IDOverrideStaticProperty *oprop = RNA_property_override_property_find(&ptr, prop);
+ BLI_assert(oprop != NULL);
+ BLI_assert(id != NULL && id->override_static != NULL);
+
+ const bool is_template = (id->override_static->reference == NULL);
+
+ /* We need source (i.e. linked data) to restore values of deleted overrides...
+ * If this is an override template, we obviously do not need to restore anything. */
+ if (!is_template) {
+ RNA_id_pointer_create(id->override_static->reference, &id_refptr);
+ if (!RNA_path_resolve(&id_refptr, oprop->rna_path, &src, NULL)) {
+ BLI_assert(0 && "Failed to create matching source (linked data) RNA pointer");
+ }
+ }
+
+ if (!all && index != -1) {
+ bool is_strict_find;
+ /* Remove override operation for given item,
+ * add singular operations for the other items as needed. */
+ IDOverrideStaticPropertyOperation *opop = BKE_override_static_property_operation_find(
+ oprop, NULL, NULL, index, index, false, &is_strict_find);
+ BLI_assert(opop != NULL);
+ if (!is_strict_find) {
+ /* No specific override operation, we have to get generic one,
+ * and create item-specific override operations for all but given index,
+ * before removing generic one. */
+ for (int idx = RNA_property_array_length(&ptr, prop); idx--;) {
+ if (idx != index) {
+ BKE_override_static_property_operation_get(
+ oprop, opop->operation, NULL, NULL, idx, idx, true, NULL, NULL);
+ }
+ }
+ }
+ BKE_override_static_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_static_property_delete(id->override_static, oprop);
+ }
+ }
+ else {
+ /* Just remove whole generic override operation of this property. */
+ BKE_override_static_property_delete(id->override_static, oprop);
+ if (!is_template) {
+ RNA_property_copy(bmain, &ptr, &src, prop, -1);
+ }
+ }
+
+ return operator_button_property_finish(C, &ptr, prop);
}
static void UI_OT_override_remove_button(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Override";
- ot->idname = "UI_OT_override_remove_button";
- ot->description = "Remove an override operation";
+ /* identifiers */
+ ot->name = "Remove Override";
+ ot->idname = "UI_OT_override_remove_button";
+ ot->description = "Remove an override operation";
- /* callbacks */
- ot->poll = override_remove_button_poll;
- ot->exec = override_remove_button_exec;
+ /* callbacks */
+ ot->poll = override_remove_button_poll;
+ ot->exec = override_remove_button_exec;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
}
/** \} */
@@ -604,150 +623,148 @@ static void UI_OT_override_remove_button(wmOperatorType *ot)
/** \name Copy To Selected Operator
* \{ */
-bool UI_context_copy_to_selected_list(
- bContext *C, PointerRNA *ptr, PropertyRNA *prop,
- ListBase *r_lb, bool *r_use_path_from_id, char **r_path)
+bool UI_context_copy_to_selected_list(bContext *C,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ ListBase *r_lb,
+ bool *r_use_path_from_id,
+ char **r_path)
{
- *r_use_path_from_id = false;
- *r_path = NULL;
-
- if (RNA_struct_is_a(ptr->type, &RNA_EditBone)) {
- *r_lb = CTX_data_collection_get(C, "selected_editable_bones");
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
- *r_lb = CTX_data_collection_get(C, "selected_pose_bones");
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_Bone)) {
- ListBase lb;
- lb = CTX_data_collection_get(C, "selected_pose_bones");
-
- if (!BLI_listbase_is_empty(&lb)) {
- CollectionPointerLink *link;
- for (link = lb.first; link; link = link->next) {
- bPoseChannel *pchan = link->ptr.data;
- RNA_pointer_create(link->ptr.id.data, &RNA_Bone, pchan->bone, &link->ptr);
- }
- }
-
- *r_lb = lb;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
- *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_Node) ||
- RNA_struct_is_a(ptr->type, &RNA_NodeSocket))
- {
- ListBase lb = {NULL, NULL};
- char *path = NULL;
- bNode *node = NULL;
-
- /* Get the node we're editing */
- if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
- bNodeTree *ntree = ptr->id.data;
- bNodeSocket *sock = ptr->data;
- if (nodeFindNode(ntree, sock, &node, NULL)) {
- if ((path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Node)) != NULL) {
- /* we're good! */
- }
- else {
- node = NULL;
- }
- }
- }
- else {
- node = ptr->data;
- }
-
- /* Now filter by type */
- if (node) {
- CollectionPointerLink *link, *link_next;
- lb = CTX_data_collection_get(C, "selected_nodes");
-
- for (link = lb.first; link; link = link_next) {
- bNode *node_data = link->ptr.data;
- link_next = link->next;
-
- if (node_data->type != node->type) {
- BLI_remlink(&lb, link);
- MEM_freeN(link);
- }
- }
- }
-
- *r_lb = lb;
- *r_path = path;
- }
- else if (ptr->id.data) {
- ID *id = ptr->id.data;
-
- if (GS(id->name) == ID_OB) {
- *r_lb = CTX_data_collection_get(C, "selected_editable_objects");
- *r_use_path_from_id = true;
- *r_path = RNA_path_from_ID_to_property(ptr, prop);
- }
- else if (OB_DATA_SUPPORT_ID(GS(id->name))) {
- /* check we're using the active object */
- const short id_code = GS(id->name);
- ListBase lb = CTX_data_collection_get(C, "selected_editable_objects");
- char *path = RNA_path_from_ID_to_property(ptr, prop);
-
- /* de-duplicate obdata */
- if (!BLI_listbase_is_empty(&lb)) {
- CollectionPointerLink *link, *link_next;
-
- for (link = lb.first; link; link = link->next) {
- Object *ob = link->ptr.id.data;
- if (ob->data) {
- ID *id_data = ob->data;
- id_data->tag |= LIB_TAG_DOIT;
- }
- }
-
- for (link = lb.first; link; link = link_next) {
- Object *ob = link->ptr.id.data;
- ID *id_data = ob->data;
- link_next = link->next;
-
- if ((id_data == NULL) ||
- (id_data->tag & LIB_TAG_DOIT) == 0 ||
- ID_IS_LINKED(id_data) ||
- (GS(id_data->name) != id_code))
- {
- BLI_remlink(&lb, link);
- MEM_freeN(link);
- }
- else {
- /* avoid prepending 'data' to the path */
- RNA_id_pointer_create(id_data, &link->ptr);
- }
-
- if (id_data) {
- id_data->tag &= ~LIB_TAG_DOIT;
- }
- }
- }
-
- *r_lb = lb;
- *r_path = path;
- }
- else if (GS(id->name) == ID_SCE) {
- /* Sequencer's ID is scene :/ */
- /* 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");
- }
- }
- return (*r_path != NULL);
- }
- else {
- return false;
- }
-
- return true;
+ *r_use_path_from_id = false;
+ *r_path = NULL;
+
+ if (RNA_struct_is_a(ptr->type, &RNA_EditBone)) {
+ *r_lb = CTX_data_collection_get(C, "selected_editable_bones");
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
+ *r_lb = CTX_data_collection_get(C, "selected_pose_bones");
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Bone)) {
+ ListBase lb;
+ lb = CTX_data_collection_get(C, "selected_pose_bones");
+
+ if (!BLI_listbase_is_empty(&lb)) {
+ CollectionPointerLink *link;
+ for (link = lb.first; link; link = link->next) {
+ bPoseChannel *pchan = link->ptr.data;
+ RNA_pointer_create(link->ptr.id.data, &RNA_Bone, pchan->bone, &link->ptr);
+ }
+ }
+
+ *r_lb = lb;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
+ *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_Node) || RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
+ ListBase lb = {NULL, NULL};
+ char *path = NULL;
+ bNode *node = NULL;
+
+ /* Get the node we're editing */
+ if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
+ bNodeTree *ntree = ptr->id.data;
+ bNodeSocket *sock = ptr->data;
+ if (nodeFindNode(ntree, sock, &node, NULL)) {
+ if ((path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Node)) != NULL) {
+ /* we're good! */
+ }
+ else {
+ node = NULL;
+ }
+ }
+ }
+ else {
+ node = ptr->data;
+ }
+
+ /* Now filter by type */
+ if (node) {
+ CollectionPointerLink *link, *link_next;
+ lb = CTX_data_collection_get(C, "selected_nodes");
+
+ for (link = lb.first; link; link = link_next) {
+ bNode *node_data = link->ptr.data;
+ link_next = link->next;
+
+ if (node_data->type != node->type) {
+ BLI_remlink(&lb, link);
+ MEM_freeN(link);
+ }
+ }
+ }
+
+ *r_lb = lb;
+ *r_path = path;
+ }
+ else if (ptr->id.data) {
+ ID *id = ptr->id.data;
+
+ if (GS(id->name) == ID_OB) {
+ *r_lb = CTX_data_collection_get(C, "selected_editable_objects");
+ *r_use_path_from_id = true;
+ *r_path = RNA_path_from_ID_to_property(ptr, prop);
+ }
+ else if (OB_DATA_SUPPORT_ID(GS(id->name))) {
+ /* check we're using the active object */
+ const short id_code = GS(id->name);
+ ListBase lb = CTX_data_collection_get(C, "selected_editable_objects");
+ char *path = RNA_path_from_ID_to_property(ptr, prop);
+
+ /* de-duplicate obdata */
+ if (!BLI_listbase_is_empty(&lb)) {
+ CollectionPointerLink *link, *link_next;
+
+ for (link = lb.first; link; link = link->next) {
+ Object *ob = link->ptr.id.data;
+ if (ob->data) {
+ ID *id_data = ob->data;
+ id_data->tag |= LIB_TAG_DOIT;
+ }
+ }
+
+ for (link = lb.first; link; link = link_next) {
+ Object *ob = link->ptr.id.data;
+ ID *id_data = ob->data;
+ link_next = link->next;
+
+ if ((id_data == NULL) || (id_data->tag & LIB_TAG_DOIT) == 0 || ID_IS_LINKED(id_data) ||
+ (GS(id_data->name) != id_code)) {
+ BLI_remlink(&lb, link);
+ MEM_freeN(link);
+ }
+ else {
+ /* avoid prepending 'data' to the path */
+ RNA_id_pointer_create(id_data, &link->ptr);
+ }
+
+ if (id_data) {
+ id_data->tag &= ~LIB_TAG_DOIT;
+ }
+ }
+ }
+
+ *r_lb = lb;
+ *r_path = path;
+ }
+ else if (GS(id->name) == ID_SCE) {
+ /* Sequencer's ID is scene :/ */
+ /* 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");
+ }
+ }
+ return (*r_path != NULL);
+ }
+ else {
+ return false;
+ }
+
+ return true;
}
/**
@@ -759,104 +776,103 @@ bool UI_context_copy_to_selected_list(
*/
static bool copy_to_selected_button(bContext *C, bool all, bool poll)
{
- Main *bmain = CTX_data_main(C);
- PointerRNA ptr, lptr, idptr;
- PropertyRNA *prop, *lprop;
- bool success = false;
- int index;
-
- /* try to reset the nominated setting to its default value */
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
-
- /* if there is a valid property that is editable... */
- if (ptr.data && prop) {
- char *path = NULL;
- bool use_path_from_id;
- CollectionPointerLink *link;
- ListBase lb = {NULL};
-
- if (UI_context_copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path) &&
- !BLI_listbase_is_empty(&lb))
- {
- for (link = lb.first; link; link = link->next) {
- if (link->ptr.data != ptr.data) {
- if (use_path_from_id) {
- /* Path relative to ID. */
- lprop = NULL;
- RNA_id_pointer_create(link->ptr.id.data, &idptr);
- RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
- }
- else if (path) {
- /* Path relative to elements from list. */
- lprop = NULL;
- RNA_path_resolve_property(&link->ptr, path, &lptr, &lprop);
- }
- else {
- lptr = link->ptr;
- lprop = prop;
- }
-
- if (lptr.data == ptr.data) {
- /* lptr might not be the same as link->ptr! */
- continue;
- }
-
- if (lprop == prop) {
- if (RNA_property_editable(&lptr, lprop)) {
- if (poll) {
- success = true;
- break;
- }
- else {
- if (RNA_property_copy(bmain, &lptr, &ptr, prop, (all) ? -1 : index)) {
- RNA_property_update(C, &lptr, prop);
- success = true;
- }
- }
- }
- }
- }
- }
- }
- MEM_SAFE_FREE(path);
- BLI_freelistN(&lb);
- }
-
- return success;
+ Main *bmain = CTX_data_main(C);
+ PointerRNA ptr, lptr, idptr;
+ PropertyRNA *prop, *lprop;
+ bool success = false;
+ int index;
+
+ /* try to reset the nominated setting to its default value */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ /* if there is a valid property that is editable... */
+ if (ptr.data && prop) {
+ char *path = NULL;
+ bool use_path_from_id;
+ CollectionPointerLink *link;
+ ListBase lb = {NULL};
+
+ if (UI_context_copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path) &&
+ !BLI_listbase_is_empty(&lb)) {
+ for (link = lb.first; link; link = link->next) {
+ if (link->ptr.data != ptr.data) {
+ if (use_path_from_id) {
+ /* Path relative to ID. */
+ lprop = NULL;
+ RNA_id_pointer_create(link->ptr.id.data, &idptr);
+ RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
+ }
+ else if (path) {
+ /* Path relative to elements from list. */
+ lprop = NULL;
+ RNA_path_resolve_property(&link->ptr, path, &lptr, &lprop);
+ }
+ else {
+ lptr = link->ptr;
+ lprop = prop;
+ }
+
+ if (lptr.data == ptr.data) {
+ /* lptr might not be the same as link->ptr! */
+ continue;
+ }
+
+ if (lprop == prop) {
+ if (RNA_property_editable(&lptr, lprop)) {
+ if (poll) {
+ success = true;
+ break;
+ }
+ else {
+ if (RNA_property_copy(bmain, &lptr, &ptr, prop, (all) ? -1 : index)) {
+ RNA_property_update(C, &lptr, prop);
+ success = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ MEM_SAFE_FREE(path);
+ BLI_freelistN(&lb);
+ }
+
+ return success;
}
static bool copy_to_selected_button_poll(bContext *C)
{
- return copy_to_selected_button(C, false, true);
+ return copy_to_selected_button(C, false, true);
}
static int copy_to_selected_button_exec(bContext *C, wmOperator *op)
{
- bool success;
+ bool success;
- const bool all = RNA_boolean_get(op->ptr, "all");
+ const bool all = RNA_boolean_get(op->ptr, "all");
- success = copy_to_selected_button(C, all, false);
+ success = copy_to_selected_button(C, all, false);
- return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static void UI_OT_copy_to_selected_button(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy To Selected";
- ot->idname = "UI_OT_copy_to_selected_button";
- ot->description = "Copy property from this object to selected objects or bones";
+ /* identifiers */
+ ot->name = "Copy To Selected";
+ ot->idname = "UI_OT_copy_to_selected_button";
+ ot->description = "Copy property from this object to selected objects or bones";
- /* callbacks */
- ot->poll = copy_to_selected_button_poll;
- ot->exec = copy_to_selected_button_exec;
+ /* callbacks */
+ ot->poll = copy_to_selected_button_poll;
+ ot->exec = copy_to_selected_button_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "all", true, "All", "Copy to selected all elements of the array");
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", true, "All", "Copy to selected all elements of the array");
}
/** \} */
@@ -868,63 +884,61 @@ static void UI_OT_copy_to_selected_button(wmOperatorType *ot)
/** Jump to the object or bone referenced by the pointer, or check if it is possible. */
static bool jump_to_target_ptr(bContext *C, PointerRNA ptr, const bool poll)
{
- if (RNA_pointer_is_null(&ptr)) {
- return false;
- }
-
- /* Verify pointer type. */
- char bone_name[MAXBONENAME];
- const StructRNA *target_type = NULL;
-
- if (ELEM(ptr.type, &RNA_EditBone, &RNA_PoseBone, &RNA_Bone)) {
- RNA_string_get(&ptr, "name", bone_name);
- if (bone_name[0] != '\0') {
- target_type = &RNA_Bone;
- }
- }
- else if (RNA_struct_is_a(ptr.type, &RNA_Object)) {
- target_type = &RNA_Object;
- }
-
- if (target_type == NULL) {
- return false;
- }
-
- /* Find the containing Object. */
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base = NULL;
- const short id_type = GS(((ID *)ptr.id.data)->name);
- if (id_type == ID_OB) {
- base = BKE_view_layer_base_find(view_layer, ptr.id.data);
- }
- else if (OB_DATA_SUPPORT_ID(id_type)) {
- base = ED_object_find_first_by_data_id(view_layer, ptr.id.data);
- }
-
- bool ok = false;
- if ((base == NULL) ||
- ((target_type == &RNA_Bone) && (base->object->type != OB_ARMATURE)))
- {
- /* pass */
- }
- else if (poll) {
- ok = true;
- }
- else {
- /* Make optional. */
- const bool reveal_hidden = true;
- /* Select and activate the target. */
- if (target_type == &RNA_Bone) {
- ok = ED_object_jump_to_bone(C, base->object, bone_name, reveal_hidden);
- }
- else if (target_type == &RNA_Object) {
- ok = ED_object_jump_to_object(C, base->object, reveal_hidden);
- }
- else {
- BLI_assert(0);
- }
- }
- return ok;
+ if (RNA_pointer_is_null(&ptr)) {
+ return false;
+ }
+
+ /* Verify pointer type. */
+ char bone_name[MAXBONENAME];
+ const StructRNA *target_type = NULL;
+
+ if (ELEM(ptr.type, &RNA_EditBone, &RNA_PoseBone, &RNA_Bone)) {
+ RNA_string_get(&ptr, "name", bone_name);
+ if (bone_name[0] != '\0') {
+ target_type = &RNA_Bone;
+ }
+ }
+ else if (RNA_struct_is_a(ptr.type, &RNA_Object)) {
+ target_type = &RNA_Object;
+ }
+
+ if (target_type == NULL) {
+ return false;
+ }
+
+ /* Find the containing Object. */
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base = NULL;
+ const short id_type = GS(((ID *)ptr.id.data)->name);
+ if (id_type == ID_OB) {
+ base = BKE_view_layer_base_find(view_layer, ptr.id.data);
+ }
+ else if (OB_DATA_SUPPORT_ID(id_type)) {
+ base = ED_object_find_first_by_data_id(view_layer, ptr.id.data);
+ }
+
+ bool ok = false;
+ if ((base == NULL) || ((target_type == &RNA_Bone) && (base->object->type != OB_ARMATURE))) {
+ /* pass */
+ }
+ else if (poll) {
+ ok = true;
+ }
+ else {
+ /* Make optional. */
+ const bool reveal_hidden = true;
+ /* Select and activate the target. */
+ if (target_type == &RNA_Bone) {
+ ok = ED_object_jump_to_bone(C, base->object, bone_name, reveal_hidden);
+ }
+ else if (target_type == &RNA_Object) {
+ ok = ED_object_jump_to_object(C, base->object, reveal_hidden);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ return ok;
}
/**
@@ -936,73 +950,74 @@ static bool jump_to_target_ptr(bContext *C, PointerRNA ptr, const bool poll)
*/
static bool jump_to_target_button(bContext *C, bool poll)
{
- PointerRNA ptr, target_ptr;
- PropertyRNA *prop;
- int index;
+ PointerRNA ptr, target_ptr;
+ PropertyRNA *prop;
+ int index;
- UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- /* If there is a valid property... */
- if (ptr.data && prop) {
- const PropertyType type = RNA_property_type(prop);
+ /* If there is a valid property... */
+ if (ptr.data && prop) {
+ const PropertyType type = RNA_property_type(prop);
- /* For pointer properties, use their value directly. */
- if (type == PROP_POINTER) {
- target_ptr = RNA_property_pointer_get(&ptr, prop);
+ /* For pointer properties, use their value directly. */
+ if (type == PROP_POINTER) {
+ target_ptr = RNA_property_pointer_get(&ptr, prop);
- return jump_to_target_ptr(C, target_ptr, poll);
- }
- /* For string properties with prop_search, look up the search collection item. */
- else if (type == PROP_STRING) {
- const uiBut *but = UI_context_active_but_get(C);
+ return jump_to_target_ptr(C, target_ptr, poll);
+ }
+ /* For string properties with prop_search, look up the search collection item. */
+ 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_func == ui_rna_collection_search_cb) {
+ 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);
+ char str_buf[MAXBONENAME];
+ char *str_ptr = RNA_property_string_get_alloc(&ptr, prop, str_buf, sizeof(str_buf), NULL);
- int found = RNA_property_collection_lookup_string(&coll_search->search_ptr, coll_search->search_prop, str_ptr, &target_ptr);
+ int found = RNA_property_collection_lookup_string(
+ &coll_search->search_ptr, coll_search->search_prop, str_ptr, &target_ptr);
- if (str_ptr != str_buf) {
- MEM_freeN(str_ptr);
- }
+ if (str_ptr != str_buf) {
+ MEM_freeN(str_ptr);
+ }
- if (found) {
- return jump_to_target_ptr(C, target_ptr, poll);
- }
- }
- }
- }
+ if (found) {
+ return jump_to_target_ptr(C, target_ptr, poll);
+ }
+ }
+ }
+ }
- return false;
+ return false;
}
bool ui_jump_to_target_button_poll(bContext *C)
{
- return jump_to_target_button(C, true);
+ return jump_to_target_button(C, true);
}
static int jump_to_target_button_exec(bContext *C, wmOperator *UNUSED(op))
{
- bool success = jump_to_target_button(C, false);
+ bool success = jump_to_target_button(C, false);
- return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static void UI_OT_jump_to_target_button(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Jump To Target";
- ot->idname = "UI_OT_jump_to_target_button";
- ot->description = "Switch to the target object or bone";
+ /* identifiers */
+ ot->name = "Jump To Target";
+ ot->idname = "UI_OT_jump_to_target_button";
+ ot->description = "Switch to the target object or bone";
- /* callbacks */
- ot->poll = ui_jump_to_target_button_poll;
- ot->exec = jump_to_target_button_exec;
+ /* callbacks */
+ ot->poll = ui_jump_to_target_button_poll;
+ ot->exec = jump_to_target_button_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -1017,47 +1032,47 @@ static void UI_OT_jump_to_target_button(wmOperatorType *ot)
static bool reports_to_text_poll(bContext *C)
{
- return CTX_wm_reports(C) != NULL;
+ return CTX_wm_reports(C) != NULL;
}
static int reports_to_text_exec(bContext *C, wmOperator *UNUSED(op))
{
- ReportList *reports = CTX_wm_reports(C);
- Main *bmain = CTX_data_main(C);
- Text *txt;
- char *str;
-
- /* create new text-block to write to */
- txt = BKE_text_add(bmain, "Recent Reports");
-
- /* convert entire list to a display string, and add this to the text-block
- * - if commandline debug option enabled, show debug reports too
- * - otherwise, up to info (which is what users normally see)
- */
- str = BKE_reports_string(reports, (G.debug & G_DEBUG) ? RPT_DEBUG : RPT_INFO);
-
- if (str) {
- TextUndoBuf *utxt = NULL; // FIXME
- BKE_text_write(txt, utxt, str);
- MEM_freeN(str);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ ReportList *reports = CTX_wm_reports(C);
+ Main *bmain = CTX_data_main(C);
+ Text *txt;
+ char *str;
+
+ /* create new text-block to write to */
+ txt = BKE_text_add(bmain, "Recent Reports");
+
+ /* convert entire list to a display string, and add this to the text-block
+ * - if commandline debug option enabled, show debug reports too
+ * - otherwise, up to info (which is what users normally see)
+ */
+ str = BKE_reports_string(reports, (G.debug & G_DEBUG) ? RPT_DEBUG : RPT_INFO);
+
+ if (str) {
+ TextUndoBuf *utxt = NULL; // FIXME
+ BKE_text_write(txt, utxt, str);
+ MEM_freeN(str);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static void UI_OT_reports_to_textblock(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reports to Text Block";
- ot->idname = "UI_OT_reports_to_textblock";
- ot->description = "Write the reports ";
-
- /* callbacks */
- ot->poll = reports_to_text_poll;
- ot->exec = reports_to_text_exec;
+ /* identifiers */
+ ot->name = "Reports to Text Block";
+ ot->idname = "UI_OT_reports_to_textblock";
+ ot->description = "Write the reports ";
+
+ /* callbacks */
+ ot->poll = reports_to_text_poll;
+ ot->exec = reports_to_text_exec;
}
/** \} */
@@ -1073,13 +1088,13 @@ static void UI_OT_reports_to_textblock(wmOperatorType *ot)
* note, this includes utility functions and button matching checks */
typedef struct uiEditSourceStore {
- uiBut but_orig;
- GHash *hash;
+ uiBut but_orig;
+ GHash *hash;
} uiEditSourceStore;
typedef struct uiEditSourceButStore {
- char py_dbg_fn[FILE_MAX];
- int py_dbg_ln;
+ char py_dbg_fn[FILE_MAX];
+ int py_dbg_ln;
} uiEditSourceButStore;
/* should only ever be set while the edit source operator is running */
@@ -1087,198 +1102,190 @@ static struct uiEditSourceStore *ui_editsource_info = NULL;
bool UI_editsource_enable_check(void)
{
- return (ui_editsource_info != NULL);
+ return (ui_editsource_info != NULL);
}
static void ui_editsource_active_but_set(uiBut *but)
{
- BLI_assert(ui_editsource_info == NULL);
+ BLI_assert(ui_editsource_info == NULL);
- ui_editsource_info = MEM_callocN(sizeof(uiEditSourceStore), __func__);
- memcpy(&ui_editsource_info->but_orig, but, sizeof(uiBut));
+ ui_editsource_info = MEM_callocN(sizeof(uiEditSourceStore), __func__);
+ memcpy(&ui_editsource_info->but_orig, but, sizeof(uiBut));
- ui_editsource_info->hash = BLI_ghash_ptr_new(__func__);
+ ui_editsource_info->hash = BLI_ghash_ptr_new(__func__);
}
static void ui_editsource_active_but_clear(void)
{
- BLI_ghash_free(ui_editsource_info->hash, NULL, MEM_freeN);
- MEM_freeN(ui_editsource_info);
- ui_editsource_info = NULL;
+ BLI_ghash_free(ui_editsource_info->hash, NULL, MEM_freeN);
+ MEM_freeN(ui_editsource_info);
+ ui_editsource_info = NULL;
}
static bool ui_editsource_uibut_match(uiBut *but_a, uiBut *but_b)
{
-#if 0
- printf("matching buttons: '%s' == '%s'\n",
- but_a->drawstr, but_b->drawstr);
-#endif
-
- /* this just needs to be a 'good-enough' comparison so we can know beyond
- * reasonable doubt that these buttons are the same between redraws.
- * if this fails it only means edit-source fails - campbell */
- if (BLI_rctf_compare(&but_a->rect, &but_b->rect, FLT_EPSILON) &&
- (but_a->type == but_b->type) &&
- (but_a->rnaprop == but_b->rnaprop) &&
- (but_a->optype == but_b->optype) &&
- (but_a->unit_type == but_b->unit_type) &&
- STREQLEN(but_a->drawstr, but_b->drawstr, UI_MAX_DRAW_STR))
- {
- return true;
- }
- else {
- return false;
- }
+# if 0
+ printf("matching buttons: '%s' == '%s'\n",
+ but_a->drawstr, but_b->drawstr);
+# endif
+
+ /* this just needs to be a 'good-enough' comparison so we can know beyond
+ * reasonable doubt that these buttons are the same between redraws.
+ * if this fails it only means edit-source fails - campbell */
+ if (BLI_rctf_compare(&but_a->rect, &but_b->rect, FLT_EPSILON) && (but_a->type == but_b->type) &&
+ (but_a->rnaprop == but_b->rnaprop) && (but_a->optype == but_b->optype) &&
+ (but_a->unit_type == but_b->unit_type) &&
+ STREQLEN(but_a->drawstr, but_b->drawstr, UI_MAX_DRAW_STR)) {
+ return true;
+ }
+ else {
+ return false;
+ }
}
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 **filename, int *lineno);
- struct uiEditSourceButStore *but_store = MEM_callocN(sizeof(uiEditSourceButStore), __func__);
+ struct uiEditSourceButStore *but_store = MEM_callocN(sizeof(uiEditSourceButStore), __func__);
- const char *fn;
- int lineno = -1;
+ const char *fn;
+ int lineno = -1;
-#if 0
- printf("comparing buttons: '%s' == '%s'\n",
- but->drawstr, ui_editsource_info->but_orig.drawstr);
-#endif
+# if 0
+ printf("comparing buttons: '%s' == '%s'\n",
+ but->drawstr, ui_editsource_info->but_orig.drawstr);
+# endif
- PyC_FileAndNum_Safe(&fn, &lineno);
+ PyC_FileAndNum_Safe(&fn, &lineno);
- if (lineno != -1) {
- BLI_strncpy(but_store->py_dbg_fn, fn,
- sizeof(but_store->py_dbg_fn));
- but_store->py_dbg_ln = lineno;
- }
- else {
- but_store->py_dbg_fn[0] = '\0';
- but_store->py_dbg_ln = -1;
- }
+ if (lineno != -1) {
+ BLI_strncpy(but_store->py_dbg_fn, fn, sizeof(but_store->py_dbg_fn));
+ but_store->py_dbg_ln = lineno;
+ }
+ else {
+ but_store->py_dbg_fn[0] = '\0';
+ but_store->py_dbg_ln = -1;
+ }
- BLI_ghash_insert(ui_editsource_info->hash, but, but_store);
+ BLI_ghash_insert(ui_editsource_info->hash, but, but_store);
}
-static int editsource_text_edit(
- bContext *C, wmOperator *op,
- const char filepath[FILE_MAX], const int line)
+static int editsource_text_edit(bContext *C,
+ wmOperator *op,
+ const char filepath[FILE_MAX],
+ const int line)
{
- struct Main *bmain = CTX_data_main(C);
- Text *text;
-
- /* Developers may wish to copy-paste to an external editor. */
- printf("%s:%d\n", filepath, line);
-
- for (text = bmain->texts.first; text; text = text->id.next) {
- if (text->name && BLI_path_cmp(text->name, filepath) == 0) {
- break;
- }
- }
-
- if (text == NULL) {
- text = BKE_text_load(bmain, filepath, BKE_main_blendfile_path(bmain));
- id_us_ensure_real(&text->id);
- }
-
- if (text == NULL) {
- BKE_reportf(op->reports, RPT_WARNING, "File '%s' cannot be opened", filepath);
- return OPERATOR_CANCELLED;
- }
- 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;
- st->text = text;
- }
- else {
- BKE_reportf(op->reports, RPT_INFO, "See '%s' in the text editor", text->id.name + 2);
- }
-
- txt_move_toline(text, line - 1, false);
- WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
- }
-
- return OPERATOR_FINISHED;
+ struct Main *bmain = CTX_data_main(C);
+ Text *text;
+
+ /* Developers may wish to copy-paste to an external editor. */
+ printf("%s:%d\n", filepath, line);
+
+ for (text = bmain->texts.first; text; text = text->id.next) {
+ if (text->name && BLI_path_cmp(text->name, filepath) == 0) {
+ break;
+ }
+ }
+
+ if (text == NULL) {
+ text = BKE_text_load(bmain, filepath, BKE_main_blendfile_path(bmain));
+ id_us_ensure_real(&text->id);
+ }
+
+ if (text == NULL) {
+ BKE_reportf(op->reports, RPT_WARNING, "File '%s' cannot be opened", filepath);
+ return OPERATOR_CANCELLED;
+ }
+ 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;
+ st->text = text;
+ }
+ else {
+ BKE_reportf(op->reports, RPT_INFO, "See '%s' in the text editor", text->id.name + 2);
+ }
+
+ txt_move_toline(text, line - 1, false);
+ WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
+ }
+
+ return OPERATOR_FINISHED;
}
static int editsource_exec(bContext *C, wmOperator *op)
{
- uiBut *but = UI_context_active_but_get(C);
-
- if (but) {
- GHashIterator ghi;
- struct uiEditSourceButStore *but_store = NULL;
-
- ARegion *ar = CTX_wm_region(C);
- int ret;
-
- /* needed else the active button does not get tested */
- UI_screen_free_active_but(C, CTX_wm_screen(C));
-
- // printf("%s: begin\n", __func__);
-
- /* take care not to return before calling ui_editsource_active_but_clear */
- 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;
-
- for (BLI_ghashIterator_init(&ghi, ui_editsource_info->hash);
- BLI_ghashIterator_done(&ghi) == false;
- BLI_ghashIterator_step(&ghi))
- {
- uiBut *but_key = BLI_ghashIterator_getKey(&ghi);
- if (but_key && ui_editsource_uibut_match(&ui_editsource_info->but_orig, but_key)) {
- but_store = BLI_ghashIterator_getValue(&ghi);
- break;
- }
-
- }
-
- if (but_store) {
- if (but_store->py_dbg_ln != -1) {
- ret = editsource_text_edit(
- C, op,
- but_store->py_dbg_fn,
- but_store->py_dbg_ln);
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Active button is not from a script, cannot edit source");
- ret = OPERATOR_CANCELLED;
- }
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Active button match cannot be found");
- ret = OPERATOR_CANCELLED;
- }
-
-
- ui_editsource_active_but_clear();
-
- // printf("%s: end\n", __func__);
-
- return ret;
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Active button not found");
- return OPERATOR_CANCELLED;
- }
+ uiBut *but = UI_context_active_but_get(C);
+
+ if (but) {
+ GHashIterator ghi;
+ struct uiEditSourceButStore *but_store = NULL;
+
+ ARegion *ar = CTX_wm_region(C);
+ int ret;
+
+ /* needed else the active button does not get tested */
+ UI_screen_free_active_but(C, CTX_wm_screen(C));
+
+ // printf("%s: begin\n", __func__);
+
+ /* take care not to return before calling ui_editsource_active_but_clear */
+ 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;
+
+ for (BLI_ghashIterator_init(&ghi, ui_editsource_info->hash);
+ BLI_ghashIterator_done(&ghi) == false;
+ BLI_ghashIterator_step(&ghi)) {
+ uiBut *but_key = BLI_ghashIterator_getKey(&ghi);
+ if (but_key && ui_editsource_uibut_match(&ui_editsource_info->but_orig, but_key)) {
+ but_store = BLI_ghashIterator_getValue(&ghi);
+ break;
+ }
+ }
+
+ if (but_store) {
+ if (but_store->py_dbg_ln != -1) {
+ ret = editsource_text_edit(C, op, but_store->py_dbg_fn, but_store->py_dbg_ln);
+ }
+ else {
+ BKE_report(
+ op->reports, RPT_ERROR, "Active button is not from a script, cannot edit source");
+ ret = OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Active button match cannot be found");
+ ret = OPERATOR_CANCELLED;
+ }
+
+ ui_editsource_active_but_clear();
+
+ // printf("%s: end\n", __func__);
+
+ return ret;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Active button not found");
+ return OPERATOR_CANCELLED;
+ }
}
static void UI_OT_editsource(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Edit Source";
- ot->idname = "UI_OT_editsource";
- ot->description = "Edit UI source code of the active button";
+ /* identifiers */
+ ot->name = "Edit Source";
+ ot->idname = "UI_OT_editsource";
+ ot->description = "Edit UI source code of the active button";
- /* callbacks */
- ot->exec = editsource_exec;
+ /* callbacks */
+ ot->exec = editsource_exec;
}
/** \} */
@@ -1292,165 +1299,180 @@ static void UI_OT_editsource(wmOperatorType *ot)
* \note: this includes utility functions and button matching checks.
* this only works in conjunction with a py operator!
*/
-static void edittranslation_find_po_file(const char *root, const char *uilng, char *path, const size_t maxlen)
+static void edittranslation_find_po_file(const char *root,
+ const char *uilng,
+ char *path,
+ const size_t maxlen)
{
- char tstr[32]; /* Should be more than enough! */
-
- /* First, full lang code. */
- BLI_snprintf(tstr, sizeof(tstr), "%s.po", uilng);
- BLI_join_dirfile(path, maxlen, root, uilng);
- BLI_path_append(path, maxlen, tstr);
- if (BLI_is_file(path)) {
- return;
- }
-
- /* Now try without the second iso code part (_ES in es_ES). */
- {
- const char *tc = NULL;
- size_t szt = 0;
- tstr[0] = '\0';
-
- tc = strchr(uilng, '_');
- if (tc) {
- szt = tc - uilng;
- if (szt < sizeof(tstr)) { /* Paranoid, should always be true! */
- BLI_strncpy(tstr, uilng, szt + 1); /* +1 for '\0' char! */
- }
- }
- if (tstr[0]) {
- /* Because of some codes like sr_SR@latin... */
- tc = strchr(uilng, '@');
- if (tc) {
- BLI_strncpy(tstr + szt, tc, sizeof(tstr) - szt);
- }
-
- BLI_join_dirfile(path, maxlen, root, tstr);
- strcat(tstr, ".po");
- BLI_path_append(path, maxlen, tstr);
- if (BLI_is_file(path)) {
- return;
- }
- }
- }
-
- /* Else no po file! */
- path[0] = '\0';
+ char tstr[32]; /* Should be more than enough! */
+
+ /* First, full lang code. */
+ BLI_snprintf(tstr, sizeof(tstr), "%s.po", uilng);
+ BLI_join_dirfile(path, maxlen, root, uilng);
+ BLI_path_append(path, maxlen, tstr);
+ if (BLI_is_file(path)) {
+ return;
+ }
+
+ /* Now try without the second iso code part (_ES in es_ES). */
+ {
+ const char *tc = NULL;
+ size_t szt = 0;
+ tstr[0] = '\0';
+
+ tc = strchr(uilng, '_');
+ if (tc) {
+ szt = tc - uilng;
+ if (szt < sizeof(tstr)) { /* Paranoid, should always be true! */
+ BLI_strncpy(tstr, uilng, szt + 1); /* +1 for '\0' char! */
+ }
+ }
+ if (tstr[0]) {
+ /* Because of some codes like sr_SR@latin... */
+ tc = strchr(uilng, '@');
+ if (tc) {
+ BLI_strncpy(tstr + szt, tc, sizeof(tstr) - szt);
+ }
+
+ BLI_join_dirfile(path, maxlen, root, tstr);
+ strcat(tstr, ".po");
+ BLI_path_append(path, maxlen, tstr);
+ if (BLI_is_file(path)) {
+ return;
+ }
+ }
+ }
+
+ /* Else no po file! */
+ path[0] = '\0';
}
static int edittranslation_exec(bContext *C, wmOperator *op)
{
- uiBut *but = UI_context_active_but_get(C);
- int ret = OPERATOR_CANCELLED;
-
- if (but) {
- wmOperatorType *ot;
- PointerRNA ptr;
- char popath[FILE_MAX];
- const char *root = U.i18ndir;
- const char *uilng = BLT_lang_get();
-
- uiStringInfo but_label = {BUT_GET_LABEL, NULL};
- uiStringInfo rna_label = {BUT_GET_RNA_LABEL, NULL};
- uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL};
- uiStringInfo but_tip = {BUT_GET_TIP, NULL};
- uiStringInfo rna_tip = {BUT_GET_RNA_TIP, NULL};
- uiStringInfo enum_tip = {BUT_GET_RNAENUM_TIP, NULL};
- uiStringInfo rna_struct = {BUT_GET_RNASTRUCT_IDENTIFIER, NULL};
- uiStringInfo rna_prop = {BUT_GET_RNAPROP_IDENTIFIER, NULL};
- uiStringInfo rna_enum = {BUT_GET_RNAENUM_IDENTIFIER, NULL};
- uiStringInfo rna_ctxt = {BUT_GET_RNA_LABEL_CONTEXT, NULL};
-
- if (!BLI_is_dir(root)) {
- BKE_report(
- op->reports, RPT_ERROR,
- "Please set your Preferences' 'Translation Branches "
- "Directory' path to a valid directory");
- return OPERATOR_CANCELLED;
- }
- ot = WM_operatortype_find(EDTSRC_I18N_OP_NAME, 0);
- if (ot == NULL) {
- BKE_reportf(
- op->reports, RPT_ERROR,
- "Could not find operator '%s'! Please enable ui_translate add-on "
- "in the User Preferences", EDTSRC_I18N_OP_NAME);
- return OPERATOR_CANCELLED;
- }
- /* Try to find a valid po file for current language... */
- edittranslation_find_po_file(root, uilng, popath, FILE_MAX);
- /* printf("po path: %s\n", popath); */
- if (popath[0] == '\0') {
- BKE_reportf(op->reports, RPT_ERROR, "No valid po found for language '%s' under %s", uilng, root);
- return OPERATOR_CANCELLED;
- }
-
- UI_but_string_info_get(
- C, but, &but_label, &rna_label, &enum_label, &but_tip, &rna_tip, &enum_tip,
- &rna_struct, &rna_prop, &rna_enum, &rna_ctxt, NULL);
-
- WM_operator_properties_create_ptr(&ptr, ot);
- RNA_string_set(&ptr, "lang", uilng);
- RNA_string_set(&ptr, "po_file", popath);
- RNA_string_set(&ptr, "but_label", but_label.strinfo);
- RNA_string_set(&ptr, "rna_label", rna_label.strinfo);
- RNA_string_set(&ptr, "enum_label", enum_label.strinfo);
- RNA_string_set(&ptr, "but_tip", but_tip.strinfo);
- RNA_string_set(&ptr, "rna_tip", rna_tip.strinfo);
- RNA_string_set(&ptr, "enum_tip", enum_tip.strinfo);
- RNA_string_set(&ptr, "rna_struct", rna_struct.strinfo);
- RNA_string_set(&ptr, "rna_prop", rna_prop.strinfo);
- RNA_string_set(&ptr, "rna_enum", rna_enum.strinfo);
- RNA_string_set(&ptr, "rna_ctxt", rna_ctxt.strinfo);
- ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
-
- /* Clean up */
- if (but_label.strinfo) {
- MEM_freeN(but_label.strinfo);
- }
- if (rna_label.strinfo) {
- MEM_freeN(rna_label.strinfo);
- }
- if (enum_label.strinfo) {
- MEM_freeN(enum_label.strinfo);
- }
- if (but_tip.strinfo) {
- MEM_freeN(but_tip.strinfo);
- }
- if (rna_tip.strinfo) {
- MEM_freeN(rna_tip.strinfo);
- }
- if (enum_tip.strinfo) {
- MEM_freeN(enum_tip.strinfo);
- }
- if (rna_struct.strinfo) {
- MEM_freeN(rna_struct.strinfo);
- }
- if (rna_prop.strinfo) {
- MEM_freeN(rna_prop.strinfo);
- }
- if (rna_enum.strinfo) {
- MEM_freeN(rna_enum.strinfo);
- }
- if (rna_ctxt.strinfo) {
- MEM_freeN(rna_ctxt.strinfo);
- }
-
- return ret;
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Active button not found");
- return OPERATOR_CANCELLED;
- }
+ uiBut *but = UI_context_active_but_get(C);
+ int ret = OPERATOR_CANCELLED;
+
+ if (but) {
+ wmOperatorType *ot;
+ PointerRNA ptr;
+ char popath[FILE_MAX];
+ const char *root = U.i18ndir;
+ const char *uilng = BLT_lang_get();
+
+ uiStringInfo but_label = {BUT_GET_LABEL, NULL};
+ uiStringInfo rna_label = {BUT_GET_RNA_LABEL, NULL};
+ uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL};
+ uiStringInfo but_tip = {BUT_GET_TIP, NULL};
+ uiStringInfo rna_tip = {BUT_GET_RNA_TIP, NULL};
+ uiStringInfo enum_tip = {BUT_GET_RNAENUM_TIP, NULL};
+ uiStringInfo rna_struct = {BUT_GET_RNASTRUCT_IDENTIFIER, NULL};
+ uiStringInfo rna_prop = {BUT_GET_RNAPROP_IDENTIFIER, NULL};
+ uiStringInfo rna_enum = {BUT_GET_RNAENUM_IDENTIFIER, NULL};
+ uiStringInfo rna_ctxt = {BUT_GET_RNA_LABEL_CONTEXT, NULL};
+
+ if (!BLI_is_dir(root)) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Please set your Preferences' 'Translation Branches "
+ "Directory' path to a valid directory");
+ return OPERATOR_CANCELLED;
+ }
+ ot = WM_operatortype_find(EDTSRC_I18N_OP_NAME, 0);
+ if (ot == NULL) {
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "Could not find operator '%s'! Please enable ui_translate add-on "
+ "in the User Preferences",
+ EDTSRC_I18N_OP_NAME);
+ return OPERATOR_CANCELLED;
+ }
+ /* Try to find a valid po file for current language... */
+ edittranslation_find_po_file(root, uilng, popath, FILE_MAX);
+ /* printf("po path: %s\n", popath); */
+ if (popath[0] == '\0') {
+ BKE_reportf(
+ op->reports, RPT_ERROR, "No valid po found for language '%s' under %s", uilng, root);
+ return OPERATOR_CANCELLED;
+ }
+
+ UI_but_string_info_get(C,
+ but,
+ &but_label,
+ &rna_label,
+ &enum_label,
+ &but_tip,
+ &rna_tip,
+ &enum_tip,
+ &rna_struct,
+ &rna_prop,
+ &rna_enum,
+ &rna_ctxt,
+ NULL);
+
+ WM_operator_properties_create_ptr(&ptr, ot);
+ RNA_string_set(&ptr, "lang", uilng);
+ RNA_string_set(&ptr, "po_file", popath);
+ RNA_string_set(&ptr, "but_label", but_label.strinfo);
+ RNA_string_set(&ptr, "rna_label", rna_label.strinfo);
+ RNA_string_set(&ptr, "enum_label", enum_label.strinfo);
+ RNA_string_set(&ptr, "but_tip", but_tip.strinfo);
+ RNA_string_set(&ptr, "rna_tip", rna_tip.strinfo);
+ RNA_string_set(&ptr, "enum_tip", enum_tip.strinfo);
+ RNA_string_set(&ptr, "rna_struct", rna_struct.strinfo);
+ RNA_string_set(&ptr, "rna_prop", rna_prop.strinfo);
+ RNA_string_set(&ptr, "rna_enum", rna_enum.strinfo);
+ RNA_string_set(&ptr, "rna_ctxt", rna_ctxt.strinfo);
+ ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
+
+ /* Clean up */
+ if (but_label.strinfo) {
+ MEM_freeN(but_label.strinfo);
+ }
+ if (rna_label.strinfo) {
+ MEM_freeN(rna_label.strinfo);
+ }
+ if (enum_label.strinfo) {
+ MEM_freeN(enum_label.strinfo);
+ }
+ if (but_tip.strinfo) {
+ MEM_freeN(but_tip.strinfo);
+ }
+ if (rna_tip.strinfo) {
+ MEM_freeN(rna_tip.strinfo);
+ }
+ if (enum_tip.strinfo) {
+ MEM_freeN(enum_tip.strinfo);
+ }
+ if (rna_struct.strinfo) {
+ MEM_freeN(rna_struct.strinfo);
+ }
+ if (rna_prop.strinfo) {
+ MEM_freeN(rna_prop.strinfo);
+ }
+ if (rna_enum.strinfo) {
+ MEM_freeN(rna_enum.strinfo);
+ }
+ if (rna_ctxt.strinfo) {
+ MEM_freeN(rna_ctxt.strinfo);
+ }
+
+ return ret;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Active button not found");
+ return OPERATOR_CANCELLED;
+ }
}
static void UI_OT_edittranslation_init(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Edit Translation";
- ot->idname = "UI_OT_edittranslation_init";
- ot->description = "Edit i18n in current language for the active button";
+ /* identifiers */
+ ot->name = "Edit Translation";
+ ot->idname = "UI_OT_edittranslation_init";
+ ot->description = "Edit i18n in current language for the active button";
- /* callbacks */
- ot->exec = edittranslation_exec;
+ /* callbacks */
+ ot->exec = edittranslation_exec;
}
#endif /* WITH_PYTHON */
@@ -1463,22 +1485,22 @@ static void UI_OT_edittranslation_init(wmOperatorType *ot)
static int reloadtranslation_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
{
- BLT_lang_init();
- BLF_cache_clear();
- BLT_lang_set(NULL);
- UI_reinit_font();
- return OPERATOR_FINISHED;
+ BLT_lang_init();
+ BLF_cache_clear();
+ BLT_lang_set(NULL);
+ UI_reinit_font();
+ return OPERATOR_FINISHED;
}
static void UI_OT_reloadtranslation(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reload Translation";
- ot->idname = "UI_OT_reloadtranslation";
- ot->description = "Force a full reload of UI translation";
+ /* identifiers */
+ ot->name = "Reload Translation";
+ ot->idname = "UI_OT_reloadtranslation";
+ ot->description = "Force a full reload of UI translation";
- /* callbacks */
- ot->exec = reloadtranslation_exec;
+ /* callbacks */
+ ot->exec = reloadtranslation_exec;
}
/** \} */
@@ -1489,61 +1511,61 @@ static void UI_OT_reloadtranslation(wmOperatorType *ot)
static ARegion *region_event_inside_for_screen(bContext *C, const int xy[2])
{
- bScreen *sc = CTX_wm_screen(C);
- if (sc) {
- for (ARegion *ar = sc->regionbase.first; ar; ar = ar->next) {
- if (BLI_rcti_isect_pt_v(&ar->winrct, xy)) {
- return ar;
- }
- }
- }
- return NULL;
+ bScreen *sc = CTX_wm_screen(C);
+ if (sc) {
+ for (ARegion *ar = sc->regionbase.first; ar; ar = ar->next) {
+ if (BLI_rcti_isect_pt_v(&ar->winrct, xy)) {
+ return ar;
+ }
+ }
+ }
+ return NULL;
}
static int ui_button_press_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- const bool skip_depressed = RNA_boolean_get(op->ptr, "skip_depressed");
- ARegion *ar_prev = CTX_wm_region(C);
- ARegion *ar = region_event_inside_for_screen(C, &event->x);
+ const bool skip_depressed = RNA_boolean_get(op->ptr, "skip_depressed");
+ ARegion *ar_prev = CTX_wm_region(C);
+ ARegion *ar = region_event_inside_for_screen(C, &event->x);
- if (ar == NULL) {
- ar = ar_prev;
- }
+ if (ar == NULL) {
+ ar = ar_prev;
+ }
- CTX_wm_region_set(C, ar);
- uiBut *but = UI_context_active_but_get(C);
- CTX_wm_region_set(C, ar_prev);
+ CTX_wm_region_set(C, ar);
+ uiBut *but = UI_context_active_but_get(C);
+ CTX_wm_region_set(C, ar_prev);
- if (but == NULL) {
- return OPERATOR_PASS_THROUGH;
- }
- if (skip_depressed && (but->flag & (UI_SELECT | UI_SELECT_DRAW))) {
- return OPERATOR_PASS_THROUGH;
- }
+ if (but == NULL) {
+ return OPERATOR_PASS_THROUGH;
+ }
+ if (skip_depressed && (but->flag & (UI_SELECT | UI_SELECT_DRAW))) {
+ return OPERATOR_PASS_THROUGH;
+ }
- /* Weak, this is a workaround for 'UI_but_is_tool', which checks the operator type,
- * having this avoids a minor drawing glitch. */
- void *but_optype = but->optype;
+ /* Weak, this is a workaround for 'UI_but_is_tool', which checks the operator type,
+ * having this avoids a minor drawing glitch. */
+ void *but_optype = but->optype;
- UI_but_execute(C, but);
+ UI_but_execute(C, but);
- but->optype = but_optype;
+ but->optype = but_optype;
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(C);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void UI_OT_button_execute(wmOperatorType *ot)
{
- ot->name = "Press Button";
- ot->idname = "UI_OT_button_execute";
- ot->description = "Presses active button";
+ ot->name = "Press Button";
+ ot->idname = "UI_OT_button_execute";
+ ot->description = "Presses active button";
- ot->invoke = ui_button_press_invoke;
- ot->flag = OPTYPE_INTERNAL;
+ ot->invoke = ui_button_press_invoke;
+ ot->flag = OPTYPE_INTERNAL;
- RNA_def_boolean(ot->srna, "skip_depressed", 0, "Skip Depressed", "");
+ RNA_def_boolean(ot->srna, "skip_depressed", 0, "Skip Depressed", "");
}
/** \} */
@@ -1552,99 +1574,100 @@ static void UI_OT_button_execute(wmOperatorType *ot)
/** \name Drop Color Operator
* \{ */
-bool UI_drop_color_poll(struct bContext *C, wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
+bool UI_drop_color_poll(struct bContext *C,
+ wmDrag *drag,
+ const wmEvent *UNUSED(event),
+ const char **UNUSED(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);
-
- if (UI_but_active_drop_color(C)) {
- return 1;
- }
-
- if (sima && (sima->mode == SI_MODE_PAINT) &&
- sima->image && (ar && ar->regiontype == RGN_TYPE_WINDOW))
- {
- return 1;
- }
- }
-
- return 0;
+ /* 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);
+
+ if (UI_but_active_drop_color(C)) {
+ return 1;
+ }
+
+ if (sima && (sima->mode == SI_MODE_PAINT) && sima->image &&
+ (ar && ar->regiontype == RGN_TYPE_WINDOW)) {
+ return 1;
+ }
+ }
+
+ return 0;
}
void UI_drop_color_copy(wmDrag *drag, wmDropBox *drop)
{
- uiDragColorHandle *drag_info = drag->poin;
+ uiDragColorHandle *drag_info = drag->poin;
- RNA_float_set_array(drop->ptr, "color", drag_info->color);
- RNA_boolean_set(drop->ptr, "gamma", drag_info->gamma_corrected);
+ RNA_float_set_array(drop->ptr, "color", drag_info->color);
+ RNA_boolean_set(drop->ptr, "gamma", drag_info->gamma_corrected);
}
static int drop_color_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- ARegion *ar = CTX_wm_region(C);
- uiBut *but = NULL;
- float color[4];
- bool gamma;
-
- RNA_float_get_array(op->ptr, "color", color);
- gamma = RNA_boolean_get(op->ptr, "gamma");
-
- /* 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);
-
- if (but && but->type == UI_BTYPE_COLOR && but->rnaprop) {
- const int color_len = RNA_property_array_length(&but->rnapoin, but->rnaprop);
- BLI_assert(color_len <= 4);
-
- /* keep alpha channel as-is */
- if (color_len == 4) {
- color[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
- }
-
- if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
- if (!gamma) {
- IMB_colormanagement_scene_linear_to_srgb_v3(color);
- }
- RNA_property_float_set_array(&but->rnapoin, but->rnaprop, color);
- RNA_property_update(C, &but->rnapoin, but->rnaprop);
- }
- else if (RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
- if (gamma) {
- IMB_colormanagement_srgb_to_scene_linear_v3(color);
- }
- RNA_property_float_set_array(&but->rnapoin, but->rnaprop, color);
- RNA_property_update(C, &but->rnapoin, but->rnaprop);
- }
- }
- else {
- if (gamma) {
- srgb_to_linearrgb_v3_v3(color, color);
- }
-
- ED_imapaint_bucket_fill(C, color, op);
- }
-
- ED_region_tag_redraw(ar);
-
- return OPERATOR_FINISHED;
+ ARegion *ar = CTX_wm_region(C);
+ uiBut *but = NULL;
+ float color[4];
+ bool gamma;
+
+ RNA_float_get_array(op->ptr, "color", color);
+ gamma = RNA_boolean_get(op->ptr, "gamma");
+
+ /* 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);
+
+ if (but && but->type == UI_BTYPE_COLOR && but->rnaprop) {
+ const int color_len = RNA_property_array_length(&but->rnapoin, but->rnaprop);
+ BLI_assert(color_len <= 4);
+
+ /* keep alpha channel as-is */
+ if (color_len == 4) {
+ color[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
+ }
+
+ if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
+ if (!gamma) {
+ IMB_colormanagement_scene_linear_to_srgb_v3(color);
+ }
+ RNA_property_float_set_array(&but->rnapoin, but->rnaprop, color);
+ RNA_property_update(C, &but->rnapoin, but->rnaprop);
+ }
+ else if (RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
+ if (gamma) {
+ IMB_colormanagement_srgb_to_scene_linear_v3(color);
+ }
+ RNA_property_float_set_array(&but->rnapoin, but->rnaprop, color);
+ RNA_property_update(C, &but->rnapoin, but->rnaprop);
+ }
+ }
+ else {
+ if (gamma) {
+ srgb_to_linearrgb_v3_v3(color, color);
+ }
+
+ ED_imapaint_bucket_fill(C, color, op);
+ }
+
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_FINISHED;
}
-
static void UI_OT_drop_color(wmOperatorType *ot)
{
- ot->name = "Drop Color";
- ot->idname = "UI_OT_drop_color";
- ot->description = "Drop colors to buttons";
+ ot->name = "Drop Color";
+ ot->idname = "UI_OT_drop_color";
+ ot->description = "Drop colors to buttons";
- ot->invoke = drop_color_invoke;
- ot->flag = OPTYPE_INTERNAL;
+ ot->invoke = drop_color_invoke;
+ ot->flag = OPTYPE_INTERNAL;
- RNA_def_float_color(ot->srna, "color", 3, NULL, 0.0, FLT_MAX, "Color", "Source color", 0.0, 1.0);
- RNA_def_boolean(ot->srna, "gamma", 0, "Gamma Corrected", "The source color is gamma corrected ");
+ RNA_def_float_color(ot->srna, "color", 3, NULL, 0.0, FLT_MAX, "Color", "Source color", 0.0, 1.0);
+ RNA_def_boolean(ot->srna, "gamma", 0, "Gamma Corrected", "The source color is gamma corrected ");
}
/** \} */
@@ -1655,31 +1678,31 @@ static void UI_OT_drop_color(wmOperatorType *ot)
void ED_operatortypes_ui(void)
{
- WM_operatortype_append(UI_OT_copy_data_path_button);
- WM_operatortype_append(UI_OT_copy_python_command_button);
- WM_operatortype_append(UI_OT_reset_default_button);
- WM_operatortype_append(UI_OT_assign_default_button);
- WM_operatortype_append(UI_OT_unset_property_button);
- WM_operatortype_append(UI_OT_override_type_set_button);
- WM_operatortype_append(UI_OT_override_remove_button);
- WM_operatortype_append(UI_OT_copy_to_selected_button);
- WM_operatortype_append(UI_OT_jump_to_target_button);
- WM_operatortype_append(UI_OT_reports_to_textblock); /* XXX: temp? */
- WM_operatortype_append(UI_OT_drop_color);
+ WM_operatortype_append(UI_OT_copy_data_path_button);
+ WM_operatortype_append(UI_OT_copy_python_command_button);
+ WM_operatortype_append(UI_OT_reset_default_button);
+ WM_operatortype_append(UI_OT_assign_default_button);
+ WM_operatortype_append(UI_OT_unset_property_button);
+ WM_operatortype_append(UI_OT_override_type_set_button);
+ WM_operatortype_append(UI_OT_override_remove_button);
+ WM_operatortype_append(UI_OT_copy_to_selected_button);
+ WM_operatortype_append(UI_OT_jump_to_target_button);
+ WM_operatortype_append(UI_OT_reports_to_textblock); /* XXX: temp? */
+ WM_operatortype_append(UI_OT_drop_color);
#ifdef WITH_PYTHON
- WM_operatortype_append(UI_OT_editsource);
- WM_operatortype_append(UI_OT_edittranslation_init);
+ WM_operatortype_append(UI_OT_editsource);
+ WM_operatortype_append(UI_OT_edittranslation_init);
#endif
- WM_operatortype_append(UI_OT_reloadtranslation);
- WM_operatortype_append(UI_OT_button_execute);
-
- /* external */
- WM_operatortype_append(UI_OT_eyedropper_color);
- WM_operatortype_append(UI_OT_eyedropper_colorramp);
- WM_operatortype_append(UI_OT_eyedropper_colorramp_point);
- WM_operatortype_append(UI_OT_eyedropper_id);
- WM_operatortype_append(UI_OT_eyedropper_depth);
- WM_operatortype_append(UI_OT_eyedropper_driver);
+ WM_operatortype_append(UI_OT_reloadtranslation);
+ WM_operatortype_append(UI_OT_button_execute);
+
+ /* external */
+ WM_operatortype_append(UI_OT_eyedropper_color);
+ WM_operatortype_append(UI_OT_eyedropper_colorramp);
+ WM_operatortype_append(UI_OT_eyedropper_colorramp_point);
+ WM_operatortype_append(UI_OT_eyedropper_id);
+ WM_operatortype_append(UI_OT_eyedropper_depth);
+ WM_operatortype_append(UI_OT_eyedropper_driver);
}
/**
@@ -1687,10 +1710,10 @@ void ED_operatortypes_ui(void)
*/
void ED_keymap_ui(wmKeyConfig *keyconf)
{
- WM_keymap_ensure(keyconf, "User Interface", 0, 0);
+ WM_keymap_ensure(keyconf, "User Interface", 0, 0);
- eyedropper_modal_keymap(keyconf);
- eyedropper_colorband_modal_keymap(keyconf);
+ eyedropper_modal_keymap(keyconf);
+ eyedropper_colorband_modal_keymap(keyconf);
}
/** \} */
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index b44b666a050..34e13f6620b 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -21,7 +21,6 @@
* \ingroup edinterface
*/
-
/* a full doc with API notes can be found in
* bf-blender/trunk/blender/doc/guides/interface_API.txt */
@@ -64,46 +63,46 @@
/*********************** defines and structs ************************/
-#define ANIMATION_TIME 0.30
-#define ANIMATION_INTERVAL 0.02
+#define ANIMATION_TIME 0.30
+#define ANIMATION_INTERVAL 0.02
-#define PNL_LAST_ADDED 1
-#define PNL_ACTIVE 2
-#define PNL_WAS_ACTIVE 4
-#define PNL_ANIM_ALIGN 8
-#define PNL_NEW_ADDED 16
-#define PNL_FIRST 32
+#define PNL_LAST_ADDED 1
+#define PNL_ACTIVE 2
+#define PNL_WAS_ACTIVE 4
+#define PNL_ANIM_ALIGN 8
+#define PNL_NEW_ADDED 16
+#define PNL_FIRST 32
/* only show pin header button for pinned panels */
#define USE_PIN_HIDDEN
/* the state of the mouse position relative to the panel */
typedef enum uiPanelMouseState {
- PANEL_MOUSE_OUTSIDE, /* mouse is not in the panel */
- PANEL_MOUSE_INSIDE_CONTENT, /* mouse is in the actual panel content */
- PANEL_MOUSE_INSIDE_HEADER, /* mouse is in the panel header */
- PANEL_MOUSE_INSIDE_SCALE, /* mouse is inside panel scale widget */
+ PANEL_MOUSE_OUTSIDE, /* mouse is not in the panel */
+ PANEL_MOUSE_INSIDE_CONTENT, /* mouse is in the actual panel content */
+ PANEL_MOUSE_INSIDE_HEADER, /* mouse is in the panel header */
+ PANEL_MOUSE_INSIDE_SCALE, /* mouse is inside panel scale widget */
} uiPanelMouseState;
typedef enum uiHandlePanelState {
- PANEL_STATE_DRAG,
- PANEL_STATE_DRAG_SCALE,
- PANEL_STATE_WAIT_UNTAB,
- PANEL_STATE_ANIMATION,
- PANEL_STATE_EXIT,
+ PANEL_STATE_DRAG,
+ PANEL_STATE_DRAG_SCALE,
+ PANEL_STATE_WAIT_UNTAB,
+ PANEL_STATE_ANIMATION,
+ PANEL_STATE_EXIT,
} uiHandlePanelState;
typedef struct uiHandlePanelData {
- uiHandlePanelState state;
+ uiHandlePanelState state;
- /* animation */
- wmTimer *animtimer;
- double starttime;
+ /* animation */
+ wmTimer *animtimer;
+ double starttime;
- /* dragging */
- int startx, starty;
- int startofsx, startofsy;
- int startsizex, startsizey;
+ /* dragging */
+ int startx, starty;
+ int startofsx, startofsy;
+ int startsizex, startsizey;
} uiHandlePanelData;
static int get_panel_real_size_y(const Panel *pa);
@@ -111,15 +110,15 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
static void panel_title_color_get(bool show_background, uchar color[4])
{
- if (show_background) {
- UI_GetThemeColor4ubv(TH_TITLE, color);
- }
- else {
- /* Use menu colors for floating panels. */
- bTheme *btheme = UI_GetTheme();
- const uiWidgetColors *wcol = &btheme->tui.wcol_menu_back;
- copy_v4_v4_uchar(color, (const uchar *)wcol->text);
- }
+ if (show_background) {
+ UI_GetThemeColor4ubv(TH_TITLE, color);
+ }
+ else {
+ /* Use menu colors for floating panels. */
+ bTheme *btheme = UI_GetTheme();
+ const uiWidgetColors *wcol = &btheme->tui.wcol_menu_back;
+ copy_v4_v4_uchar(color, (const uchar *)wcol->text);
+ }
}
/*********************** space specific code ************************/
@@ -127,141 +126,146 @@ static void panel_title_color_get(bool show_background, uchar color[4])
/* SpaceProperties.align */
typedef enum eSpaceButtons_Align {
- BUT_HORIZONTAL = 0,
- BUT_VERTICAL = 1,
- BUT_AUTO = 2,
+ BUT_HORIZONTAL = 0,
+ BUT_VERTICAL = 1,
+ BUT_AUTO = 2,
} eSpaceButtons_Align;
static int panel_aligned(ScrArea *sa, ARegion *ar)
{
- if (sa->spacetype == SPACE_PROPERTIES && ar->regiontype == RGN_TYPE_WINDOW) {
- return BUT_VERTICAL;
- }
- else if (sa->spacetype == SPACE_USERPREF && ar->regiontype == RGN_TYPE_WINDOW) {
- return BUT_VERTICAL;
- }
- else if (sa->spacetype == SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS) {
- return BUT_VERTICAL;
- }
- else if (sa->spacetype == SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW) {
- return BUT_VERTICAL;
- }
- else if (ELEM(ar->regiontype, RGN_TYPE_UI, RGN_TYPE_TOOLS, RGN_TYPE_TOOL_PROPS, RGN_TYPE_HUD, RGN_TYPE_NAV_BAR, RGN_TYPE_EXECUTE)) {
- return BUT_VERTICAL;
- }
-
- return 0;
+ if (sa->spacetype == SPACE_PROPERTIES && ar->regiontype == RGN_TYPE_WINDOW) {
+ return BUT_VERTICAL;
+ }
+ else if (sa->spacetype == SPACE_USERPREF && ar->regiontype == RGN_TYPE_WINDOW) {
+ return BUT_VERTICAL;
+ }
+ else if (sa->spacetype == SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS) {
+ return BUT_VERTICAL;
+ }
+ else if (sa->spacetype == SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW) {
+ return BUT_VERTICAL;
+ }
+ else if (ELEM(ar->regiontype,
+ RGN_TYPE_UI,
+ RGN_TYPE_TOOLS,
+ RGN_TYPE_TOOL_PROPS,
+ RGN_TYPE_HUD,
+ RGN_TYPE_NAV_BAR,
+ RGN_TYPE_EXECUTE)) {
+ return BUT_VERTICAL;
+ }
+
+ return 0;
}
static bool panel_active_animation_changed(ListBase *lb, Panel **pa_animation, bool *no_animation)
{
- for (Panel *pa = lb->first; pa; pa = pa->next) {
- /* Detect panel active flag changes. */
- if (!(pa->type && pa->type->parent)) {
- if ((pa->runtime_flag & PNL_WAS_ACTIVE) && !(pa->runtime_flag & PNL_ACTIVE)) {
- return true;
- }
- if (!(pa->runtime_flag & PNL_WAS_ACTIVE) && (pa->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)) {
- return true;
- }
- }
-
- /* Detect animation. */
- if (pa->activedata) {
- uiHandlePanelData *data = pa->activedata;
- if (data->state == PANEL_STATE_ANIMATION) {
- *pa_animation = pa;
- }
- else {
- /* Don't animate while handling other interaction. */
- *no_animation = true;
- }
- }
- if ((pa->runtime_flag & PNL_ANIM_ALIGN) && !(*pa_animation)) {
- *pa_animation = pa;
- }
- }
-
- return false;
+ for (Panel *pa = lb->first; pa; pa = pa->next) {
+ /* Detect panel active flag changes. */
+ if (!(pa->type && pa->type->parent)) {
+ if ((pa->runtime_flag & PNL_WAS_ACTIVE) && !(pa->runtime_flag & PNL_ACTIVE)) {
+ return true;
+ }
+ if (!(pa->runtime_flag & PNL_WAS_ACTIVE) && (pa->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)) {
+ return true;
+ }
+ }
+
+ /* Detect animation. */
+ if (pa->activedata) {
+ uiHandlePanelData *data = pa->activedata;
+ if (data->state == PANEL_STATE_ANIMATION) {
+ *pa_animation = pa;
+ }
+ else {
+ /* Don't animate while handling other interaction. */
+ *no_animation = true;
+ }
+ }
+ if ((pa->runtime_flag & PNL_ANIM_ALIGN) && !(*pa_animation)) {
+ *pa_animation = pa;
+ }
+ }
+
+ return false;
}
static bool panels_need_realign(ScrArea *sa, ARegion *ar, Panel **r_pa_animate)
{
- *r_pa_animate = NULL;
-
- if (sa->spacetype == SPACE_PROPERTIES && ar->regiontype == RGN_TYPE_WINDOW) {
- SpaceProperties *sbuts = sa->spacedata.first;
-
- if (sbuts->mainbo != sbuts->mainb) {
- return true;
- }
- }
- else if (sa->spacetype == SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW) {
- return true;
- }
- else if (sa->spacetype == SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS) {
- return true;
- }
-
- /* Detect if a panel was added or removed. */
- Panel *pa_animation = NULL;
- bool no_animation = false;
- if (panel_active_animation_changed(&ar->panels, &pa_animation, &no_animation)) {
- return true;
- }
-
- /* Detect panel marked for animation, if we're not already animating. */
- if (pa_animation) {
- if (!no_animation) {
- *r_pa_animate = pa_animation;
- }
- return true;
- }
-
- return false;
+ *r_pa_animate = NULL;
+
+ if (sa->spacetype == SPACE_PROPERTIES && ar->regiontype == RGN_TYPE_WINDOW) {
+ SpaceProperties *sbuts = sa->spacedata.first;
+
+ if (sbuts->mainbo != sbuts->mainb) {
+ return true;
+ }
+ }
+ else if (sa->spacetype == SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW) {
+ return true;
+ }
+ else if (sa->spacetype == SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS) {
+ return true;
+ }
+
+ /* Detect if a panel was added or removed. */
+ Panel *pa_animation = NULL;
+ bool no_animation = false;
+ if (panel_active_animation_changed(&ar->panels, &pa_animation, &no_animation)) {
+ return true;
+ }
+
+ /* Detect panel marked for animation, if we're not already animating. */
+ if (pa_animation) {
+ if (!no_animation) {
+ *r_pa_animate = pa_animation;
+ }
+ return true;
+ }
+
+ return false;
}
/****************************** panels ******************************/
static void panels_collapse_all(ScrArea *sa, ARegion *ar, const Panel *from_pa)
{
- 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;
-
- for (pa = ar->panels.first; pa; pa = pa->next) {
- PanelType *pt = pa->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] || STREQ(pt->category, category)) {
- pa->flag &= ~PNL_CLOSED;
- pa->flag |= flag;
- }
- }
- }
- }
+ 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;
+
+ for (pa = ar->panels.first; pa; pa = pa->next) {
+ PanelType *pt = pa->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] ||
+ STREQ(pt->category, category)) {
+ pa->flag &= ~PNL_CLOSED;
+ pa->flag |= flag;
+ }
+ }
+ }
+ }
}
-
static void ui_panel_copy_offset(Panel *pa, Panel *papar)
{
- /* with respect to sizes... papar is parent */
+ /* with respect to sizes... papar is parent */
- pa->ofsx = papar->ofsx;
- pa->ofsy = papar->ofsy + papar->sizey - pa->sizey;
+ pa->ofsx = papar->ofsx;
+ pa->ofsy = papar->ofsy + papar->sizey - pa->sizey;
}
-
/**
* XXX Disabled paneltab handling for now. Old 2.4x feature, *DO NOT* confuse it with new tool tabs in 2.70. ;)
* See also T41704.
@@ -270,211 +274,212 @@ static void ui_panel_copy_offset(Panel *pa, Panel *papar)
Panel *UI_panel_find_by_type(ListBase *lb, PanelType *pt)
{
- Panel *pa;
- const char *idname = pt->idname;
+ Panel *pa;
+ const char *idname = pt->idname;
#ifdef UI_USE_PANELTAB
- const char *tabname = pt->idname;
- for (pa = lb->first; pa; pa = pa->next) {
- if (STREQLEN(pa->panelname, idname, sizeof(pa->panelname))) {
- if (STREQLEN(pa->tabname, tabname, sizeof(pa->tabname))) {
- return pa;
- }
- }
- }
+ const char *tabname = pt->idname;
+ for (pa = lb->first; pa; pa = pa->next) {
+ if (STREQLEN(pa->panelname, idname, sizeof(pa->panelname))) {
+ if (STREQLEN(pa->tabname, tabname, sizeof(pa->tabname))) {
+ return pa;
+ }
+ }
+ }
#else
- for (pa = lb->first; pa; pa = pa->next) {
- if (STREQLEN(pa->panelname, idname, sizeof(pa->panelname))) {
- return pa;
- }
- }
+ for (pa = lb->first; pa; pa = pa->next) {
+ if (STREQLEN(pa->panelname, idname, sizeof(pa->panelname))) {
+ return pa;
+ }
+ }
#endif
- return NULL;
+ return NULL;
}
/**
* \note \a pa 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 *UI_panel_begin(
+ ScrArea *sa, ARegion *ar, ListBase *lb, uiBlock *block, PanelType *pt, Panel *pa, bool *r_open)
{
- Panel *palast, *panext;
- const char *drawname = CTX_IFACE_(pt->translation_context, pt->label);
- const char *idname = pt->idname;
+ Panel *palast, *panext;
+ const char *drawname = CTX_IFACE_(pt->translation_context, pt->label);
+ const char *idname = pt->idname;
#ifdef UI_USE_PANELTAB
- const char *tabname = pt->idname;
- const char *hookname = NULL;
+ const char *tabname = pt->idname;
+ const char *hookname = NULL;
#endif
- const bool newpanel = (pa == NULL);
- int align = panel_aligned(sa, ar);
-
- if (!newpanel) {
- pa->type = pt;
- }
- else {
- /* new panel */
- pa = MEM_callocN(sizeof(Panel), "new panel");
- pa->type = pt;
- BLI_strncpy(pa->panelname, idname, sizeof(pa->panelname));
-
- if (pt->flag & PNL_DEFAULT_CLOSED) {
- if (align == BUT_VERTICAL) {
- pa->flag |= PNL_CLOSEDY;
- }
- else {
- pa->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;
-
- BLI_addtail(lb, pa);
+ const bool newpanel = (pa == NULL);
+ int align = panel_aligned(sa, ar);
+
+ if (!newpanel) {
+ pa->type = pt;
+ }
+ else {
+ /* new panel */
+ pa = MEM_callocN(sizeof(Panel), "new panel");
+ pa->type = pt;
+ BLI_strncpy(pa->panelname, idname, sizeof(pa->panelname));
+
+ if (pt->flag & PNL_DEFAULT_CLOSED) {
+ if (align == BUT_VERTICAL) {
+ pa->flag |= PNL_CLOSEDY;
+ }
+ else {
+ pa->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;
+
+ BLI_addtail(lb, pa);
#ifdef UI_USE_PANELTAB
- BLI_strncpy(pa->tabname, tabname, sizeof(pa->tabname));
-
- /* make new Panel tabbed? */
- if (hookname) {
- Panel *patab;
- for (patab = lb->first; patab; patab = patab->next) {
- if ((patab->runtime_flag & PNL_ACTIVE) && patab->paneltab == NULL) {
- if (STREQLEN(hookname, patab->panelname, sizeof(patab->panelname))) {
- if (STREQLEN(tabname, patab->tabname, sizeof(patab->tabname))) {
- pa->paneltab = patab;
- ui_panel_copy_offset(pa, patab);
- break;
- }
- }
- }
- }
- }
+ BLI_strncpy(pa->tabname, tabname, sizeof(pa->tabname));
+
+ /* make new Panel tabbed? */
+ if (hookname) {
+ Panel *patab;
+ for (patab = lb->first; patab; patab = patab->next) {
+ if ((patab->runtime_flag & PNL_ACTIVE) && patab->paneltab == NULL) {
+ if (STREQLEN(hookname, patab->panelname, sizeof(patab->panelname))) {
+ if (STREQLEN(tabname, patab->tabname, sizeof(patab->tabname))) {
+ pa->paneltab = patab;
+ ui_panel_copy_offset(pa, patab);
+ break;
+ }
+ }
+ }
+ }
+ }
#else
- BLI_strncpy(pa->tabname, idname, sizeof(pa->tabname));
+ BLI_strncpy(pa->tabname, idname, sizeof(pa->tabname));
#endif
- }
-
- /* 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;
- /* Force update of panels' positions! */
- pa->sizex = 0;
- pa->sizey = 0;
- pa->blocksizex = 0;
- pa->blocksizey = 0;
- }
-
- BLI_strncpy(pa->drawname, drawname, sizeof(pa->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);
- break;
- }
- }
-
- if (newpanel) {
- pa->sortorder = (palast) ? palast->sortorder + 1 : 0;
-
- for (panext = lb->first; panext; panext = panext->next) {
- if (panext != pa && panext->sortorder >= pa->sortorder) {
- panext->sortorder++;
- }
- }
- }
-
- if (palast) {
- palast->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) {
- UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
- }
-
- *r_open = false;
-
- if (pa->paneltab) {
- return pa;
- }
- if (pa->flag & PNL_CLOSED) {
- return pa;
- }
-
- *r_open = true;
-
- return pa;
+ }
+
+ /* 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;
+ /* Force update of panels' positions! */
+ pa->sizex = 0;
+ pa->sizey = 0;
+ pa->blocksizex = 0;
+ pa->blocksizey = 0;
+ }
+
+ BLI_strncpy(pa->drawname, drawname, sizeof(pa->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);
+ break;
+ }
+ }
+
+ if (newpanel) {
+ pa->sortorder = (palast) ? palast->sortorder + 1 : 0;
+
+ for (panext = lb->first; panext; panext = panext->next) {
+ if (panext != pa && panext->sortorder >= pa->sortorder) {
+ panext->sortorder++;
+ }
+ }
+ }
+
+ if (palast) {
+ palast->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) {
+ UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
+ }
+
+ *r_open = false;
+
+ if (pa->paneltab) {
+ return pa;
+ }
+ if (pa->flag & PNL_CLOSED) {
+ return pa;
+ }
+
+ *r_open = true;
+
+ return pa;
}
void UI_panel_end(uiBlock *block, int width, int height)
{
- Panel *pa = block->panel;
-
- /* Set panel size excluding children. */
- pa->blocksizex = width;
- pa->blocksizey = height;
-
- /* Compute total panel size including children. */
- for (Panel *pachild = pa->children.first; pachild; pachild = pachild->next) {
- if (pachild->runtime_flag & PNL_ACTIVE) {
- width = max_ii(width, pachild->sizex);
- height += get_panel_real_size_y(pachild);
- }
- }
-
- /* Update total panel size. */
- if (pa->runtime_flag & PNL_NEW_ADDED) {
- pa->runtime_flag &= ~PNL_NEW_ADDED;
- pa->sizex = width;
- pa->sizey = height;
- }
- else {
- /* check if we need to do an animation */
- if (!ELEM(width, 0, pa->sizex) || !ELEM(height, 0, pa->sizey)) {
- pa->runtime_flag |= PNL_ANIM_ALIGN;
- if (height != 0) {
- pa->ofsy += pa->sizey - height;
- }
- }
-
- /* update width/height if non-zero */
- if (width != 0) {
- pa->sizex = width;
- }
- if (height != 0) {
- pa->sizey = height;
- }
- }
+ Panel *pa = block->panel;
+
+ /* Set panel size excluding children. */
+ pa->blocksizex = width;
+ pa->blocksizey = height;
+
+ /* Compute total panel size including children. */
+ for (Panel *pachild = pa->children.first; pachild; pachild = pachild->next) {
+ if (pachild->runtime_flag & PNL_ACTIVE) {
+ width = max_ii(width, pachild->sizex);
+ height += get_panel_real_size_y(pachild);
+ }
+ }
+
+ /* Update total panel size. */
+ if (pa->runtime_flag & PNL_NEW_ADDED) {
+ pa->runtime_flag &= ~PNL_NEW_ADDED;
+ pa->sizex = width;
+ pa->sizey = height;
+ }
+ else {
+ /* check if we need to do an animation */
+ if (!ELEM(width, 0, pa->sizex) || !ELEM(height, 0, pa->sizey)) {
+ pa->runtime_flag |= PNL_ANIM_ALIGN;
+ if (height != 0) {
+ pa->ofsy += pa->sizey - height;
+ }
+ }
+
+ /* update width/height if non-zero */
+ if (width != 0) {
+ pa->sizex = width;
+ }
+ if (height != 0) {
+ pa->sizey = height;
+ }
+ }
}
static void ui_offset_panel_block(uiBlock *block)
{
- uiStyle *style = UI_style_get_dpi();
+ uiStyle *style = UI_style_get_dpi();
- /* compute bounds and offset */
- ui_block_bounds_calc(block);
+ /* compute bounds and offset */
+ ui_block_bounds_calc(block);
- int ofsy = block->panel->sizey - style->panelspace;
+ int ofsy = block->panel->sizey - style->panelspace;
- for (uiBut *but = block->buttons.first; but; but = but->next) {
- but->rect.ymin += ofsy;
- but->rect.ymax += ofsy;
- }
+ for (uiBut *but = block->buttons.first; but; but = but->next) {
+ but->rect.ymin += ofsy;
+ but->rect.ymax += ofsy;
+ }
- block->rect.xmax = block->panel->sizex;
- block->rect.ymax = block->panel->sizey;
- block->rect.xmin = block->rect.ymin = 0.0;
+ block->rect.xmax = block->panel->sizex;
+ block->rect.ymax = block->panel->sizey;
+ block->rect.xmin = block->rect.ymin = 0.0;
}
/**************************** drawing *******************************/
@@ -482,474 +487,479 @@ static void ui_offset_panel_block(uiBlock *block)
/* triangle 'icon' for panel header */
void UI_draw_icon_tri(float x, float y, char dir, const float color[4])
{
- float f3 = 0.05 * U.widget_unit;
- float f5 = 0.15 * U.widget_unit;
- float f7 = 0.25 * U.widget_unit;
-
- if (dir == 'h') {
- UI_draw_anti_tria(x - f3, y - f5, x - f3, y + f5, x + f7, y, color);
- }
- else if (dir == 't') {
- UI_draw_anti_tria(x - f5, y - f7, x + f5, y - f7, x, y + f3, color);
- }
- else { /* 'v' = vertical, down */
- UI_draw_anti_tria(x - f5, y + f3, x + f5, y + f3, x, y - f7, color);
- }
+ float f3 = 0.05 * U.widget_unit;
+ float f5 = 0.15 * U.widget_unit;
+ float f7 = 0.25 * U.widget_unit;
+
+ if (dir == 'h') {
+ UI_draw_anti_tria(x - f3, y - f5, x - f3, y + f5, x + f7, y, color);
+ }
+ else if (dir == 't') {
+ UI_draw_anti_tria(x - f5, y - f7, x + f5, y - f7, x, y + f3, color);
+ }
+ else { /* 'v' = vertical, down */
+ UI_draw_anti_tria(x - f5, y + f3, x + f5, y + f3, x, y - f7, color);
+ }
}
static void ui_draw_anti_x(uint pos, float x1, float y1, float x2, float y2)
{
- /* set antialias line */
- GPU_line_smooth(true);
- GPU_blend(true);
+ /* set antialias line */
+ GPU_line_smooth(true);
+ GPU_blend(true);
- GPU_line_width(2.0);
+ GPU_line_width(2.0);
- immBegin(GPU_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, x1, y1);
- immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y2);
- immVertex2f(pos, x1, y2);
- immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x2, y1);
- immEnd();
-
- GPU_line_smooth(false);
- GPU_blend(false);
+ immEnd();
+ GPU_line_smooth(false);
+ GPU_blend(false);
}
/* x 'icon' for panel header */
static void ui_draw_x_icon(uint pos, float x, float y)
{
- ui_draw_anti_x(pos, x, y, x + 9.375f, y + 9.375f);
-
+ ui_draw_anti_x(pos, x, y, x + 9.375f, y + 9.375f);
}
-#define PNL_ICON UI_UNIT_X /* could be UI_UNIT_Y too */
+#define PNL_ICON UI_UNIT_X /* could be UI_UNIT_Y too */
static void ui_draw_panel_scalewidget(uint pos, const rcti *rect)
{
- float xmin, xmax, dx;
- float ymin, ymax, dy;
+ float xmin, xmax, dx;
+ float ymin, ymax, dy;
- xmin = rect->xmax - PNL_HEADER + 2;
- xmax = rect->xmax - 3;
- ymin = rect->ymin + 3;
- ymax = rect->ymin + PNL_HEADER - 2;
+ xmin = rect->xmax - PNL_HEADER + 2;
+ xmax = rect->xmax - 3;
+ ymin = rect->ymin + 3;
+ ymax = rect->ymin + PNL_HEADER - 2;
- dx = 0.5f * (xmax - xmin);
- dy = 0.5f * (ymax - ymin);
+ dx = 0.5f * (xmax - xmin);
+ dy = 0.5f * (ymax - ymin);
- GPU_blend(true);
- immUniformColor4ub(255, 255, 255, 50);
+ GPU_blend(true);
+ immUniformColor4ub(255, 255, 255, 50);
- immBegin(GPU_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, xmin, ymin);
- immVertex2f(pos, xmax, ymax);
+ immVertex2f(pos, xmin, ymin);
+ immVertex2f(pos, xmax, ymax);
- immVertex2f(pos, xmin + dx, ymin);
- immVertex2f(pos, xmax, ymax - dy);
+ immVertex2f(pos, xmin + dx, ymin);
+ immVertex2f(pos, xmax, ymax - dy);
- immEnd();
+ immEnd();
- immUniformColor4ub(0, 0, 0, 50);
+ immUniformColor4ub(0, 0, 0, 50);
- immBegin(GPU_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, xmin, ymin + 1);
- immVertex2f(pos, xmax, ymax + 1);
+ immVertex2f(pos, xmin, ymin + 1);
+ immVertex2f(pos, xmax, ymax + 1);
- immVertex2f(pos, xmin + dx, ymin + 1);
- immVertex2f(pos, xmax, ymax - dy + 1);
+ immVertex2f(pos, xmin + dx, ymin + 1);
+ immVertex2f(pos, xmax, ymax - dy + 1);
- immEnd();
+ immEnd();
- GPU_blend(false);
+ 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])
+ 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);
+ 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();
+ 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)
{
- Panel *panel = block->panel;
- const bool is_subpanel = (panel->type && panel->type->parent);
+ Panel *panel = block->panel;
+ const bool is_subpanel = (panel->type && panel->type->parent);
- *r_x = UI_UNIT_X * 1.0f;
- *r_y = UI_UNIT_Y * 1.5f;
+ *r_x = UI_UNIT_X * 1.0f;
+ *r_y = UI_UNIT_Y * 1.5f;
- if (is_subpanel) {
- *r_x += (0.7f * UI_UNIT_X);
- }
+ if (is_subpanel) {
+ *r_x += (0.7f * UI_UNIT_X);
+ }
}
static void ui_draw_aligned_panel_header(
- uiStyle *style, uiBlock *block, const rcti *rect, char dir,
- const bool show_background)
+ uiStyle *style, uiBlock *block, const rcti *rect, char dir, const bool show_background)
{
- Panel *panel = block->panel;
- rcti hrect;
- int pnl_icons;
- const char *activename = panel->drawname[0] ? panel->drawname : panel->panelname;
- const bool is_subpanel = (panel->type && panel->type->parent);
- uiFontStyle *fontstyle = (is_subpanel) ? &style->widgetlabel : &style->paneltitle;
- uchar col_title[4];
-
- /* + 0.001f to avoid flirting with float inaccuracy */
- if (panel->control & UI_PNL_CLOSE) {
- pnl_icons = (panel->labelofs + (2.0f * PNL_ICON)) / block->aspect + 0.001f;
- }
- else {
- pnl_icons = (panel->labelofs + (1.1f * PNL_ICON)) / block->aspect + 0.001f;
- }
-
- /* draw text label */
- panel_title_color_get(show_background, col_title);
- col_title[3] = 255;
-
- hrect = *rect;
- if (dir == 'h') {
- hrect.xmin = rect->xmin + pnl_icons;
- hrect.ymin -= 2.0f / block->aspect;
- UI_fontstyle_draw(
- fontstyle, &hrect, activename, col_title,
- &(struct uiFontStyleDraw_Params) { .align = UI_STYLE_TEXT_LEFT, });
- }
- else {
- /* ignore 'pnl_icons', otherwise the text gets offset horizontally
- * + 0.001f to avoid flirting with float inaccuracy
- */
- hrect.xmin = rect->xmin + (PNL_ICON + 5) / block->aspect + 0.001f;
- UI_fontstyle_draw_rotated(fontstyle, &hrect, activename, col_title);
- }
+ Panel *panel = block->panel;
+ rcti hrect;
+ int pnl_icons;
+ const char *activename = panel->drawname[0] ? panel->drawname : panel->panelname;
+ const bool is_subpanel = (panel->type && panel->type->parent);
+ uiFontStyle *fontstyle = (is_subpanel) ? &style->widgetlabel : &style->paneltitle;
+ uchar col_title[4];
+
+ /* + 0.001f to avoid flirting with float inaccuracy */
+ if (panel->control & UI_PNL_CLOSE) {
+ pnl_icons = (panel->labelofs + (2.0f * PNL_ICON)) / block->aspect + 0.001f;
+ }
+ else {
+ pnl_icons = (panel->labelofs + (1.1f * PNL_ICON)) / block->aspect + 0.001f;
+ }
+
+ /* draw text label */
+ panel_title_color_get(show_background, col_title);
+ col_title[3] = 255;
+
+ hrect = *rect;
+ if (dir == 'h') {
+ hrect.xmin = rect->xmin + pnl_icons;
+ hrect.ymin -= 2.0f / block->aspect;
+ UI_fontstyle_draw(fontstyle,
+ &hrect,
+ activename,
+ col_title,
+ &(struct uiFontStyleDraw_Params){
+ .align = UI_STYLE_TEXT_LEFT,
+ });
+ }
+ else {
+ /* ignore 'pnl_icons', otherwise the text gets offset horizontally
+ * + 0.001f to avoid flirting with float inaccuracy
+ */
+ hrect.xmin = rect->xmin + (PNL_ICON + 5) / block->aspect + 0.001f;
+ UI_fontstyle_draw_rotated(fontstyle, &hrect, activename, col_title);
+ }
}
/* panel integrated in buttonswindow, tool/property lists etc */
-void ui_draw_aligned_panel(
- uiStyle *style, uiBlock *block, const rcti *rect,
- const bool show_pin, const bool show_background)
+void ui_draw_aligned_panel(uiStyle *style,
+ uiBlock *block,
+ const rcti *rect,
+ const bool show_pin,
+ const bool show_background)
{
- Panel *panel = block->panel;
- rcti headrect;
- rctf itemrect;
- float color[4];
- const bool is_closed_x = (panel->flag & PNL_CLOSEDX) ? true : false;
- const bool is_closed_y = (panel->flag & PNL_CLOSEDY) ? true : false;
- const bool is_subpanel = (panel->type && panel->type->parent);
- const bool show_drag = (
- !is_subpanel &&
- /* FIXME(campbell): currently no background means floating panel which can't be dragged.
- * This may be changed in future. */
- show_background);
+ Panel *panel = block->panel;
+ rcti headrect;
+ rctf itemrect;
+ float color[4];
+ const bool is_closed_x = (panel->flag & PNL_CLOSEDX) ? true : false;
+ const bool is_closed_y = (panel->flag & PNL_CLOSEDY) ? true : false;
+ const bool is_subpanel = (panel->type && panel->type->parent);
+ const bool show_drag =
+ (!is_subpanel &&
+ /* FIXME(campbell): currently no background means floating panel which can't be dragged.
+ * This may be changed in future. */
+ show_background);
- if (panel->paneltab) {
- return;
- }
- if (panel->type && (panel->type->flag & PNL_NO_HEADER)) {
- return;
- }
+ if (panel->paneltab) {
+ return;
+ }
+ if (panel->type && (panel->type->flag & PNL_NO_HEADER)) {
+ return;
+ }
- /* calculate header rect */
- /* + 0.001f to prevent flicker due to float inaccuracy */
- headrect = *rect;
- headrect.ymin = headrect.ymax;
- headrect.ymax = headrect.ymin + floor(PNL_HEADER / block->aspect + 0.001f);
+ /* calculate header rect */
+ /* + 0.001f to prevent flicker due to float inaccuracy */
+ headrect = *rect;
+ headrect.ymin = headrect.ymax;
+ headrect.ymax = headrect.ymin + floor(PNL_HEADER / block->aspect + 0.001f);
- rcti titlerect = headrect;
- if (is_subpanel) {
- titlerect.xmin += (0.7f * UI_UNIT_X);
- }
+ rcti titlerect = headrect;
+ if (is_subpanel) {
+ titlerect.xmin += (0.7f * UI_UNIT_X);
+ }
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- if (show_background && !is_subpanel) {
- float minx = rect->xmin;
- float maxx = is_closed_x ? (minx + PNL_HEADER / block->aspect) : rect->xmax;
- float y = headrect.ymax;
+ if (show_background && !is_subpanel) {
+ float minx = rect->xmin;
+ float maxx = is_closed_x ? (minx + PNL_HEADER / block->aspect) : rect->xmax;
+ float y = headrect.ymax;
- GPU_blend(true);
+ GPU_blend(true);
- /* draw with background color */
- immUniformThemeColor(TH_PANEL_HEADER);
- immRectf(pos, minx, headrect.ymin, maxx, y);
+ /* draw with background color */
+ immUniformThemeColor(TH_PANEL_HEADER);
+ immRectf(pos, minx, headrect.ymin, maxx, y);
- immBegin(GPU_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, minx, y);
- immVertex2f(pos, maxx, y);
+ immVertex2f(pos, minx, y);
+ immVertex2f(pos, maxx, y);
- immVertex2f(pos, minx, y);
- immVertex2f(pos, maxx, y);
+ immVertex2f(pos, minx, y);
+ immVertex2f(pos, maxx, y);
- immEnd();
+ immEnd();
- GPU_blend(false);
- }
+ GPU_blend(false);
+ }
- immUnbindProgram();
+ immUnbindProgram();
- /* draw optional pin icon */
+ /* draw optional pin icon */
#ifdef USE_PIN_HIDDEN
- if (show_pin && (block->panel->flag & PNL_PIN))
+ if (show_pin && (block->panel->flag & PNL_PIN))
#else
- if (show_pin)
+ if (show_pin)
#endif
- {
- uchar col_title[4];
- panel_title_color_get(show_background, col_title);
-
- GPU_blend(true);
- UI_icon_draw_aspect(
- headrect.xmax - ((PNL_ICON * 2.2f) / block->aspect), headrect.ymin + (5.0f / block->aspect),
- (panel->flag & PNL_PIN) ? ICON_PINNED : ICON_UNPINNED,
- (block->aspect / UI_DPI_FAC), 1.0f, (const char *)col_title);
- GPU_blend(false);
- }
-
-
- /* horizontal title */
- if (is_closed_x == false) {
- 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 */
- 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, 0.7f);
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- ui_draw_panel_dragwidget(pos, col, &itemrect);
- immUnbindProgram();
-
- /* Restore format for the following draws. */
- pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- }
- }
-
- /* if the panel is minimized vertically:
- * (------)
- */
- if (is_closed_y) {
- /* skip */
- }
- else if (is_closed_x) {
- /* draw vertical title */
- ui_draw_aligned_panel_header(style, block, &headrect, 'v', show_background);
- pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- }
- /* an open panel */
- else {
- /* in some occasions, draw a border */
- if (panel->flag & PNL_SELECT) {
- if (panel->control & UI_PNL_SOLID) {
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- }
- else {
- UI_draw_roundbox_corner_set(UI_CNR_NONE);
- }
-
- UI_GetThemeColorShade4fv(TH_BACK, -120, color);
- UI_draw_roundbox_aa(false, 0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax + 1, 8, color);
- }
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- GPU_blend(true);
-
- if (show_background) {
- /* panel backdrop */
- int panel_col = is_subpanel ? TH_PANEL_SUB_BACK : TH_PANEL_BACK;
-
- immUniformThemeColor(panel_col);
- immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
- }
-
- if (panel->control & UI_PNL_SCALE) {
- ui_draw_panel_scalewidget(pos, rect);
- }
-
- immUnbindProgram();
- }
-
-
- uchar col_title[4];
- panel_title_color_get(show_background, col_title);
-
- /* draw optional close icon */
-
- if (panel->control & UI_PNL_CLOSE) {
- const int ofsx = 6;
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3ubv(col_title);
- ui_draw_x_icon(pos, rect->xmin + 2 + ofsx, rect->ymax + 2);
- immUnbindProgram();
- }
-
- /* draw collapse icon */
-
- /* itemrect smaller */
- itemrect.xmin = titlerect.xmin;
- itemrect.xmax = itemrect.xmin + BLI_rcti_size_y(&titlerect);
- itemrect.ymin = titlerect.ymin;
- itemrect.ymax = titlerect.ymax;
-
- BLI_rctf_scale(&itemrect, 0.25f);
-
- {
- float tria_color[4];
- rgb_uchar_to_float(tria_color, col_title);
- tria_color[3] = 1.0f;
-
- if (is_closed_y) {
- ui_draw_anti_tria_rect(&itemrect, 'h', tria_color);
- }
- else if (is_closed_x) {
- ui_draw_anti_tria_rect(&itemrect, 'h', tria_color);
- }
- else {
- ui_draw_anti_tria_rect(&itemrect, 'v', tria_color);
- }
- }
+ {
+ uchar col_title[4];
+ panel_title_color_get(show_background, col_title);
+
+ GPU_blend(true);
+ UI_icon_draw_aspect(headrect.xmax - ((PNL_ICON * 2.2f) / block->aspect),
+ headrect.ymin + (5.0f / block->aspect),
+ (panel->flag & PNL_PIN) ? ICON_PINNED : ICON_UNPINNED,
+ (block->aspect / UI_DPI_FAC),
+ 1.0f,
+ (const char *)col_title);
+ GPU_blend(false);
+ }
+
+ /* horizontal title */
+ if (is_closed_x == false) {
+ 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 */
+ 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, 0.7f);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ ui_draw_panel_dragwidget(pos, col, &itemrect);
+ immUnbindProgram();
+
+ /* Restore format for the following draws. */
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ }
+ }
+
+ /* if the panel is minimized vertically:
+ * (------)
+ */
+ if (is_closed_y) {
+ /* skip */
+ }
+ else if (is_closed_x) {
+ /* draw vertical title */
+ ui_draw_aligned_panel_header(style, block, &headrect, 'v', show_background);
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ }
+ /* an open panel */
+ else {
+ /* in some occasions, draw a border */
+ if (panel->flag & PNL_SELECT) {
+ if (panel->control & UI_PNL_SOLID) {
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ }
+ else {
+ UI_draw_roundbox_corner_set(UI_CNR_NONE);
+ }
+
+ UI_GetThemeColorShade4fv(TH_BACK, -120, color);
+ UI_draw_roundbox_aa(false,
+ 0.5f + rect->xmin,
+ 0.5f + rect->ymin,
+ 0.5f + rect->xmax,
+ 0.5f + headrect.ymax + 1,
+ 8,
+ color);
+ }
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ GPU_blend(true);
+
+ if (show_background) {
+ /* panel backdrop */
+ int panel_col = is_subpanel ? TH_PANEL_SUB_BACK : TH_PANEL_BACK;
+
+ immUniformThemeColor(panel_col);
+ immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ }
+
+ if (panel->control & UI_PNL_SCALE) {
+ ui_draw_panel_scalewidget(pos, rect);
+ }
+
+ immUnbindProgram();
+ }
+
+ uchar col_title[4];
+ panel_title_color_get(show_background, col_title);
+
+ /* draw optional close icon */
+
+ if (panel->control & UI_PNL_CLOSE) {
+ const int ofsx = 6;
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3ubv(col_title);
+ ui_draw_x_icon(pos, rect->xmin + 2 + ofsx, rect->ymax + 2);
+ immUnbindProgram();
+ }
+
+ /* draw collapse icon */
+
+ /* itemrect smaller */
+ itemrect.xmin = titlerect.xmin;
+ itemrect.xmax = itemrect.xmin + BLI_rcti_size_y(&titlerect);
+ itemrect.ymin = titlerect.ymin;
+ itemrect.ymax = titlerect.ymax;
+
+ BLI_rctf_scale(&itemrect, 0.25f);
+
+ {
+ float tria_color[4];
+ rgb_uchar_to_float(tria_color, col_title);
+ tria_color[3] = 1.0f;
+
+ if (is_closed_y) {
+ ui_draw_anti_tria_rect(&itemrect, 'h', tria_color);
+ }
+ else if (is_closed_x) {
+ ui_draw_anti_tria_rect(&itemrect, 'h', tria_color);
+ }
+ else {
+ ui_draw_anti_tria_rect(&itemrect, 'v', tria_color);
+ }
+ }
}
/************************** panel alignment *************************/
static int get_panel_header(const Panel *pa)
{
- if (pa->type && (pa->type->flag & PNL_NO_HEADER)) {
- return 0;
- }
+ if (pa->type && (pa->type->flag & PNL_NO_HEADER)) {
+ return 0;
+ }
- return PNL_HEADER;
+ return PNL_HEADER;
}
static int get_panel_size_y(const Panel *pa)
{
- if (pa->type && (pa->type->flag & PNL_NO_HEADER)) {
- return pa->sizey;
- }
+ if (pa->type && (pa->type->flag & PNL_NO_HEADER)) {
+ return pa->sizey;
+ }
- return PNL_HEADER + pa->sizey;
+ return PNL_HEADER + pa->sizey;
}
static int get_panel_real_size_y(const Panel *pa)
{
- int sizey = (pa->flag & PNL_CLOSED) ? 0 : pa->sizey;
+ int sizey = (pa->flag & PNL_CLOSED) ? 0 : pa->sizey;
- if (pa->type && (pa->type->flag & PNL_NO_HEADER)) {
- return sizey;
- }
+ if (pa->type && (pa->type->flag & PNL_NO_HEADER)) {
+ return sizey;
+ }
- return PNL_HEADER + sizey;
+ return PNL_HEADER + sizey;
}
int UI_panel_size_y(const Panel *pa)
{
- return get_panel_real_size_y(pa);
+ return get_panel_real_size_y(pa);
}
/* 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)
{
- if (pa->flag & PNL_CLOSEDY) {
- return pa->ofsy + pa->sizey;
- }
- else if (pa->paneltab && (pa->paneltab->flag & PNL_CLOSEDY)) {
- return pa->ofsy + pa->sizey;
- }
- else if (pa->paneltab) {
- return pa->paneltab->ofsy;
- }
- else {
- return pa->ofsy;
- }
+ if (pa->flag & PNL_CLOSEDY) {
+ return pa->ofsy + pa->sizey;
+ }
+ else if (pa->paneltab && (pa->paneltab->flag & PNL_CLOSEDY)) {
+ return pa->ofsy + pa->sizey;
+ }
+ else if (pa->paneltab) {
+ return pa->paneltab->ofsy;
+ }
+ else {
+ return pa->ofsy;
+ }
}
static int get_panel_real_ofsx(Panel *pa)
{
- if (pa->flag & PNL_CLOSEDX) {
- return pa->ofsx + get_panel_header(pa);
- }
- else if (pa->paneltab && (pa->paneltab->flag & PNL_CLOSEDX)) {
- return pa->ofsx + get_panel_header(pa);
- }
- else {
- return pa->ofsx + pa->sizex;
- }
+ if (pa->flag & PNL_CLOSEDX) {
+ return pa->ofsx + get_panel_header(pa);
+ }
+ else if (pa->paneltab && (pa->paneltab->flag & PNL_CLOSEDX)) {
+ return pa->ofsx + get_panel_header(pa);
+ }
+ else {
+ return pa->ofsx + pa->sizex;
+ }
}
typedef struct PanelSort {
- Panel *pa, *orig;
+ Panel *pa, *orig;
} PanelSort;
/**
@@ -962,590 +972,596 @@ typedef struct PanelSort {
static int find_leftmost_panel(const void *a1, const void *a2)
{
- const PanelSort *ps1 = a1, *ps2 = a2;
-
- if (ps1->pa->ofsx > ps2->pa->ofsx) {
- return 1;
- }
- else if (ps1->pa->ofsx < ps2->pa->ofsx) {
- return -1;
- }
- else if (ps1->pa->sortorder > ps2->pa->sortorder) {
- return 1;
- }
- else if (ps1->pa->sortorder < ps2->pa->sortorder) {
- return -1;
- }
-
- return 0;
+ const PanelSort *ps1 = a1, *ps2 = a2;
+
+ if (ps1->pa->ofsx > ps2->pa->ofsx) {
+ return 1;
+ }
+ else if (ps1->pa->ofsx < ps2->pa->ofsx) {
+ return -1;
+ }
+ else if (ps1->pa->sortorder > ps2->pa->sortorder) {
+ return 1;
+ }
+ else if (ps1->pa->sortorder < ps2->pa->sortorder) {
+ return -1;
+ }
+
+ return 0;
}
-
static int find_highest_panel(const void *a1, const void *a2)
{
- const PanelSort *ps1 = a1, *ps2 = 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) {
- /* skip and check for ofs and sortorder below */
- }
- else if (ps1->pa->type->flag & PNL_NO_HEADER) {
- return -1;
- }
- else if (ps2->pa->type->flag & PNL_NO_HEADER) {
- return 1;
- }
-
- if (ps1->pa->ofsy + ps1->pa->sizey < ps2->pa->ofsy + ps2->pa->sizey) {
- return 1;
- }
- else if (ps1->pa->ofsy + ps1->pa->sizey > ps2->pa->ofsy + ps2->pa->sizey) {
- return -1;
- }
- else if (ps1->pa->sortorder > ps2->pa->sortorder) {
- return 1;
- }
- else if (ps1->pa->sortorder < ps2->pa->sortorder) {
- return -1;
- }
-
- return 0;
+ const PanelSort *ps1 = a1, *ps2 = 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) {
+ /* skip and check for ofs and sortorder below */
+ }
+ else if (ps1->pa->type->flag & PNL_NO_HEADER) {
+ return -1;
+ }
+ else if (ps2->pa->type->flag & PNL_NO_HEADER) {
+ return 1;
+ }
+
+ if (ps1->pa->ofsy + ps1->pa->sizey < ps2->pa->ofsy + ps2->pa->sizey) {
+ return 1;
+ }
+ else if (ps1->pa->ofsy + ps1->pa->sizey > ps2->pa->ofsy + ps2->pa->sizey) {
+ return -1;
+ }
+ else if (ps1->pa->sortorder > ps2->pa->sortorder) {
+ return 1;
+ }
+ else if (ps1->pa->sortorder < ps2->pa->sortorder) {
+ return -1;
+ }
+
+ return 0;
}
static int compare_panel(const void *a1, const void *a2)
{
- const PanelSort *ps1 = a1, *ps2 = a2;
+ const PanelSort *ps1 = a1, *ps2 = a2;
- if (ps1->pa->sortorder > ps2->pa->sortorder) {
- return 1;
- }
- else if (ps1->pa->sortorder < ps2->pa->sortorder) {
- return -1;
- }
+ if (ps1->pa->sortorder > ps2->pa->sortorder) {
+ return 1;
+ }
+ else if (ps1->pa->sortorder < ps2->pa->sortorder) {
+ return -1;
+ }
- return 0;
+ return 0;
}
static void align_sub_panels(Panel *pa)
{
- /* Position sub panels. */
- int ofsy = get_panel_real_ofsy(pa) + pa->sizey - pa->blocksizey;
-
- for (Panel *pachild = pa->children.first; pachild; pachild = pachild->next) {
- if (pachild->runtime_flag & PNL_ACTIVE) {
- pachild->ofsx = pa->ofsx;
- pachild->ofsy = ofsy - get_panel_size_y(pachild);
- ofsy -= get_panel_real_size_y(pachild);
-
- if (pachild->children.first) {
- align_sub_panels(pachild);
- }
- }
- }
+ /* Position sub panels. */
+ int ofsy = get_panel_real_ofsy(pa) + pa->sizey - pa->blocksizey;
+
+ for (Panel *pachild = pa->children.first; pachild; pachild = pachild->next) {
+ if (pachild->runtime_flag & PNL_ACTIVE) {
+ pachild->ofsx = pa->ofsx;
+ pachild->ofsy = ofsy - get_panel_size_y(pachild);
+ ofsy -= get_panel_real_size_y(pachild);
+
+ if (pachild->children.first) {
+ align_sub_panels(pachild);
+ }
+ }
+ }
}
/* this doesn't draw */
/* returns 1 when it did something */
static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bool drag)
{
- Panel *pa;
- PanelSort *ps, *panelsort, *psnext;
- int a, tot = 0;
- bool done;
- int align = panel_aligned(sa, ar);
- bool has_category_tabs = UI_panel_category_is_visible(ar);
-
- /* count active, not tabbed panels */
- for (pa = ar->panels.first; pa; pa = pa->next) {
- if ((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab == NULL) {
- tot++;
- }
- }
-
- if (tot == 0) {
- return 0;
- }
-
- /* extra; change close direction? */
- for (pa = ar->panels.first; pa; pa = pa->next) {
- if ((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab == NULL) {
- if ((pa->flag & PNL_CLOSEDX) && (align == BUT_VERTICAL)) {
- pa->flag ^= PNL_CLOSED;
- }
- else if ((pa->flag & PNL_CLOSEDY) && (align == BUT_HORIZONTAL)) {
- pa->flag ^= PNL_CLOSED;
- }
- }
- }
-
- /* sort panels */
- panelsort = MEM_callocN(tot * sizeof(PanelSort), "panelsort");
-
- ps = panelsort;
- for (pa = ar->panels.first; pa; pa = pa->next) {
- if ((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab == NULL) {
- ps->pa = MEM_dupallocN(pa);
- ps->orig = pa;
- ps++;
- }
- }
-
- if (drag) {
- /* while we are dragging, we sort on location and update sortorder */
- if (align == BUT_VERTICAL) {
- qsort(panelsort, tot, sizeof(PanelSort), find_highest_panel);
- }
- else {
- qsort(panelsort, tot, sizeof(PanelSort), find_leftmost_panel);
- }
-
- for (ps = panelsort, a = 0; a < tot; a++, ps++) {
- ps->orig->sortorder = a;
- }
- }
- else {
- /* otherwise use sortorder */
- qsort(panelsort, tot, sizeof(PanelSort), compare_panel);
- }
-
- /* no smart other default start loc! this keeps switching f5/f6/etc compatible */
- ps = panelsort;
- ps->pa->ofsx = 0;
- ps->pa->ofsy = -get_panel_size_y(ps->pa);
-
- if (has_category_tabs) {
- if (align == BUT_VERTICAL && (ar->alignment != RGN_ALIGN_RIGHT)) {
- ps->pa->ofsx += UI_PANEL_CATEGORY_MARGIN_WIDTH;
- }
- }
-
- 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);
- }
- 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);
- }
- }
-
- /* we interpolate */
- 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 + (1.0f - fac) * (float)ps->orig->ofsx);
- ps->orig->ofsy = round_fl_to_int(fac * (float)ps->pa->ofsy + (1.0f - fac) * (float)ps->orig->ofsy);
- done = true;
- }
- }
- }
-
- /* set locations for tabbed and sub panels */
- for (pa = ar->panels.first; pa; pa = pa->next) {
- if (pa->runtime_flag & PNL_ACTIVE) {
- if (pa->paneltab) {
- ui_panel_copy_offset(pa, pa->paneltab);
- }
- if (pa->children.first) {
- align_sub_panels(pa);
- }
- }
- }
-
- /* free panelsort array */
- for (ps = panelsort, a = 0; a < tot; a++, ps++) {
- MEM_freeN(ps->pa);
- }
- MEM_freeN(panelsort);
-
- return done;
+ Panel *pa;
+ PanelSort *ps, *panelsort, *psnext;
+ int a, tot = 0;
+ bool done;
+ int align = panel_aligned(sa, ar);
+ bool has_category_tabs = UI_panel_category_is_visible(ar);
+
+ /* count active, not tabbed panels */
+ for (pa = ar->panels.first; pa; pa = pa->next) {
+ if ((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab == NULL) {
+ tot++;
+ }
+ }
+
+ if (tot == 0) {
+ return 0;
+ }
+
+ /* extra; change close direction? */
+ for (pa = ar->panels.first; pa; pa = pa->next) {
+ if ((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab == NULL) {
+ if ((pa->flag & PNL_CLOSEDX) && (align == BUT_VERTICAL)) {
+ pa->flag ^= PNL_CLOSED;
+ }
+ else if ((pa->flag & PNL_CLOSEDY) && (align == BUT_HORIZONTAL)) {
+ pa->flag ^= PNL_CLOSED;
+ }
+ }
+ }
+
+ /* sort panels */
+ panelsort = MEM_callocN(tot * sizeof(PanelSort), "panelsort");
+
+ ps = panelsort;
+ for (pa = ar->panels.first; pa; pa = pa->next) {
+ if ((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab == NULL) {
+ ps->pa = MEM_dupallocN(pa);
+ ps->orig = pa;
+ ps++;
+ }
+ }
+
+ if (drag) {
+ /* while we are dragging, we sort on location and update sortorder */
+ if (align == BUT_VERTICAL) {
+ qsort(panelsort, tot, sizeof(PanelSort), find_highest_panel);
+ }
+ else {
+ qsort(panelsort, tot, sizeof(PanelSort), find_leftmost_panel);
+ }
+
+ for (ps = panelsort, a = 0; a < tot; a++, ps++) {
+ ps->orig->sortorder = a;
+ }
+ }
+ else {
+ /* otherwise use sortorder */
+ qsort(panelsort, tot, sizeof(PanelSort), compare_panel);
+ }
+
+ /* no smart other default start loc! this keeps switching f5/f6/etc compatible */
+ ps = panelsort;
+ ps->pa->ofsx = 0;
+ ps->pa->ofsy = -get_panel_size_y(ps->pa);
+
+ if (has_category_tabs) {
+ if (align == BUT_VERTICAL && (ar->alignment != RGN_ALIGN_RIGHT)) {
+ ps->pa->ofsx += UI_PANEL_CATEGORY_MARGIN_WIDTH;
+ }
+ }
+
+ 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);
+ }
+ 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);
+ }
+ }
+
+ /* we interpolate */
+ 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 +
+ (1.0f - fac) * (float)ps->orig->ofsx);
+ ps->orig->ofsy = round_fl_to_int(fac * (float)ps->pa->ofsy +
+ (1.0f - fac) * (float)ps->orig->ofsy);
+ done = true;
+ }
+ }
+ }
+
+ /* set locations for tabbed and sub panels */
+ for (pa = ar->panels.first; pa; pa = pa->next) {
+ if (pa->runtime_flag & PNL_ACTIVE) {
+ if (pa->paneltab) {
+ ui_panel_copy_offset(pa, pa->paneltab);
+ }
+ if (pa->children.first) {
+ align_sub_panels(pa);
+ }
+ }
+ }
+
+ /* free panelsort array */
+ for (ps = panelsort, a = 0; a < tot; a++, ps++) {
+ MEM_freeN(ps->pa);
+ }
+ MEM_freeN(panelsort);
+
+ return done;
}
static void ui_panels_size(ScrArea *sa, ARegion *ar, int *r_x, int *r_y)
{
- Panel *pa;
- int align = panel_aligned(sa, ar);
- 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) {
- int pa_sizex, pa_sizey;
-
- if (align == BUT_VERTICAL) {
- pa_sizex = pa->ofsx + pa->sizex;
- pa_sizey = get_panel_real_ofsy(pa);
- }
- else {
- pa_sizex = get_panel_real_ofsx(pa) + pa->sizex;
- pa_sizey = pa->ofsy + get_panel_size_y(pa);
- }
-
- sizex = max_ii(sizex, pa_sizex);
- sizey = min_ii(sizey, pa_sizey);
- }
- }
-
- if (sizex == 0) {
- sizex = UI_PANEL_WIDTH;
- }
- if (sizey == 0) {
- sizey = -UI_PANEL_WIDTH;
- }
-
- *r_x = sizex;
- *r_y = sizey;
+ Panel *pa;
+ int align = panel_aligned(sa, ar);
+ 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) {
+ int pa_sizex, pa_sizey;
+
+ if (align == BUT_VERTICAL) {
+ pa_sizex = pa->ofsx + pa->sizex;
+ pa_sizey = get_panel_real_ofsy(pa);
+ }
+ else {
+ pa_sizex = get_panel_real_ofsx(pa) + pa->sizex;
+ pa_sizey = pa->ofsy + get_panel_size_y(pa);
+ }
+
+ sizex = max_ii(sizex, pa_sizex);
+ sizey = min_ii(sizey, pa_sizey);
+ }
+ }
+
+ if (sizex == 0) {
+ sizex = UI_PANEL_WIDTH;
+ }
+ if (sizey == 0) {
+ sizey = -UI_PANEL_WIDTH;
+ }
+
+ *r_x = sizex;
+ *r_y = sizey;
}
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);
- 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);
- }
- else {
- fac = 1.0f;
- }
-
- if (fac >= 1.0f) {
- panel_activate_state(C, panel, PANEL_STATE_EXIT);
- return;
- }
+ uiHandlePanelData *data = panel->activedata;
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = 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);
+ }
+ else {
+ fac = 1.0f;
+ }
+
+ if (fac >= 1.0f) {
+ panel_activate_state(C, panel, PANEL_STATE_EXIT);
+ return;
+ }
}
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;
- }
- else {
- pa->runtime_flag = 0;
- }
-
- panel_list_clear_active(&pa->children);
- }
+ /* 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;
+ }
+ else {
+ pa->runtime_flag = 0;
+ }
+
+ panel_list_clear_active(&pa->children);
+ }
}
void UI_panels_begin(const bContext *UNUSED(C), ARegion *ar)
{
- panel_list_clear_active(&ar->panels);
+ panel_list_clear_active(&ar->panels);
}
/* only draws blocks with panels */
void UI_panels_end(const bContext *C, ARegion *ar, int *r_x, int *r_y)
{
- ScrArea *sa = CTX_wm_area(C);
- uiBlock *block;
- Panel *panot, *panew, *patest, *pa, *firstpa;
-
- /* offset contents */
- for (block = ar->uiblocks.first; block; block = block->next) {
- if (block->active && block->panel) {
- ui_offset_panel_block(block);
- }
- }
-
- /* consistency; are panels not made, whilst they have tabs */
- for (panot = ar->panels.first; panot; panot = panot->next) {
- if ((panot->runtime_flag & PNL_ACTIVE) == 0) { /* not made */
-
- for (panew = ar->panels.first; panew; panew = panew->next) {
- if ((panew->runtime_flag & PNL_ACTIVE)) {
- if (panew->paneltab == panot) { /* panew is tab in notmade pa */
- break;
- }
- }
- }
- /* now panew can become the new parent, check all other tabs */
- if (panew) {
- for (patest = ar->panels.first; patest; patest = patest->next) {
- if (patest->paneltab == panot) {
- patest->paneltab = panew;
- }
- }
- panot->paneltab = panew;
- panew->paneltab = NULL;
- ED_region_tag_redraw(ar); /* the buttons panew were not made */
- }
- }
- }
-
- /* re-align, possibly with animation */
- if (panels_need_realign(sa, ar, &pa)) {
- if (pa) {
- panel_activate_state(C, pa, PANEL_STATE_ANIMATION);
- }
- else {
- uiAlignPanelStep(sa, ar, 1.0, false);
- }
- }
-
- /* tag first panel */
- firstpa = NULL;
- for (block = ar->uiblocks.first; block; block = block->next) {
- if (block->active && block->panel) {
- if (!firstpa || block->panel->sortorder < firstpa->sortorder) {
- firstpa = block->panel;
- }
- }
- }
-
- if (firstpa) {
- firstpa->runtime_flag |= PNL_FIRST;
- }
-
- /* compute size taken up by panel */
- ui_panels_size(sa, ar, r_x, r_y);
+ ScrArea *sa = CTX_wm_area(C);
+ uiBlock *block;
+ Panel *panot, *panew, *patest, *pa, *firstpa;
+
+ /* offset contents */
+ for (block = ar->uiblocks.first; block; block = block->next) {
+ if (block->active && block->panel) {
+ ui_offset_panel_block(block);
+ }
+ }
+
+ /* consistency; are panels not made, whilst they have tabs */
+ for (panot = ar->panels.first; panot; panot = panot->next) {
+ if ((panot->runtime_flag & PNL_ACTIVE) == 0) { /* not made */
+
+ for (panew = ar->panels.first; panew; panew = panew->next) {
+ if ((panew->runtime_flag & PNL_ACTIVE)) {
+ if (panew->paneltab == panot) { /* panew is tab in notmade pa */
+ break;
+ }
+ }
+ }
+ /* now panew can become the new parent, check all other tabs */
+ if (panew) {
+ for (patest = ar->panels.first; patest; patest = patest->next) {
+ if (patest->paneltab == panot) {
+ patest->paneltab = panew;
+ }
+ }
+ panot->paneltab = panew;
+ panew->paneltab = NULL;
+ ED_region_tag_redraw(ar); /* the buttons panew were not made */
+ }
+ }
+ }
+
+ /* re-align, possibly with animation */
+ if (panels_need_realign(sa, ar, &pa)) {
+ if (pa) {
+ panel_activate_state(C, pa, PANEL_STATE_ANIMATION);
+ }
+ else {
+ uiAlignPanelStep(sa, ar, 1.0, false);
+ }
+ }
+
+ /* tag first panel */
+ firstpa = NULL;
+ for (block = ar->uiblocks.first; block; block = block->next) {
+ if (block->active && block->panel) {
+ if (!firstpa || block->panel->sortorder < firstpa->sortorder) {
+ firstpa = block->panel;
+ }
+ }
+ }
+
+ if (firstpa) {
+ firstpa->runtime_flag |= PNL_FIRST;
+ }
+
+ /* compute size taken up by panel */
+ ui_panels_size(sa, ar, r_x, r_y);
}
void UI_panels_draw(const bContext *C, ARegion *ar)
{
- uiBlock *block;
-
- if (ar->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) {
- if (block->active && block->panel && !(block->panel->flag & PNL_SELECT)) {
- UI_block_draw(C, block);
- }
- }
-
- for (block = ar->uiblocks.last; block; block = block->prev) {
- if (block->active && block->panel && (block->panel->flag & PNL_SELECT)) {
- UI_block_draw(C, block);
- }
- }
+ uiBlock *block;
+
+ if (ar->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) {
+ if (block->active && block->panel && !(block->panel->flag & PNL_SELECT)) {
+ UI_block_draw(C, block);
+ }
+ }
+
+ for (block = ar->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)
{
- uiBlock *block;
- uiBut *but;
-
- for (block = ar->uiblocks.first; block; block = block->next) {
- if (block->panel) {
- float fac = new_width / (float)block->panel->sizex;
- block->panel->sizex = new_width;
-
- for (but = block->buttons.first; but; but = but->next) {
- but->rect.xmin *= fac;
- but->rect.xmax *= fac;
- }
- }
- }
+ uiBlock *block;
+ uiBut *but;
+
+ for (block = ar->uiblocks.first; block; block = block->next) {
+ if (block->panel) {
+ float fac = new_width / (float)block->panel->sizex;
+ block->panel->sizex = new_width;
+
+ for (but = block->buttons.first; but; but = but->next) {
+ but->rect.xmin *= fac;
+ but->rect.xmax *= fac;
+ }
+ }
+ }
}
/* ------------ panel merging ---------------- */
static void check_panel_overlap(ARegion *ar, Panel *panel)
{
- Panel *pa;
-
- /* 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->paneltab == NULL && (pa->runtime_flag & PNL_ACTIVE)) {
- float safex = 0.2, safey = 0.2;
-
- if (pa->flag & PNL_CLOSEDX) {
- safex = 0.05;
- }
- else if (pa->flag & PNL_CLOSEDY) {
- safey = 0.05;
- }
- else if (panel->flag & PNL_CLOSEDX) {
- safex = 0.05;
- }
- else if (panel->flag & PNL_CLOSEDY) {
- 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;
- }
- }
- }
- }
- }
- }
- }
+ Panel *pa;
+
+ /* 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->paneltab == NULL && (pa->runtime_flag & PNL_ACTIVE)) {
+ float safex = 0.2, safey = 0.2;
+
+ if (pa->flag & PNL_CLOSEDX) {
+ safex = 0.05;
+ }
+ else if (pa->flag & PNL_CLOSEDY) {
+ safey = 0.05;
+ }
+ else if (panel->flag & PNL_CLOSEDX) {
+ safex = 0.05;
+ }
+ else if (panel->flag & PNL_CLOSEDY) {
+ 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;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
/************************ panel dragging ****************************/
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;
-
- /* first clip for window, no dragging outside */
- if (!BLI_rcti_isect_pt_v(&ar->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);
-
- if (data->state == PANEL_STATE_DRAG_SCALE) {
- panel->sizex = MAX2(data->startsizex + dx, UI_PANEL_MINX);
-
- if (data->startsizey - dy < UI_PANEL_MINY) {
- dy = -UI_PANEL_MINY + data->startsizey;
- }
-
- panel->sizey = data->startsizey - dy;
- panel->ofsy = data->startofsy + dy;
- }
- else {
- /* reset the panel snapping, to allow dragging away from snapped edges */
- panel->snap = PNL_SNAP_NONE;
-
- panel->ofsx = data->startofsx + dx;
- panel->ofsy = data->startofsy + dy;
- check_panel_overlap(ar, panel);
-
- if (align) {
- uiAlignPanelStep(sa, ar, 0.2, true);
- }
- }
-
- ED_region_tag_redraw(ar);
+ 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;
+
+ /* first clip for window, no dragging outside */
+ if (!BLI_rcti_isect_pt_v(&ar->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);
+
+ if (data->state == PANEL_STATE_DRAG_SCALE) {
+ panel->sizex = MAX2(data->startsizex + dx, UI_PANEL_MINX);
+
+ if (data->startsizey - dy < UI_PANEL_MINY) {
+ dy = -UI_PANEL_MINY + data->startsizey;
+ }
+
+ panel->sizey = data->startsizey - dy;
+ panel->ofsy = data->startofsy + dy;
+ }
+ else {
+ /* reset the panel snapping, to allow dragging away from snapped edges */
+ panel->snap = PNL_SNAP_NONE;
+
+ panel->ofsx = data->startofsx + dx;
+ panel->ofsy = data->startofsy + dy;
+ check_panel_overlap(ar, panel);
+
+ if (align) {
+ uiAlignPanelStep(sa, ar, 0.2, true);
+ }
+ }
+
+ ED_region_tag_redraw(ar);
}
/******************* region level panel interaction *****************/
-static uiPanelMouseState ui_panel_mouse_state_get(const uiBlock *block, const Panel *pa, const int mx, const int my)
+static uiPanelMouseState ui_panel_mouse_state_get(const uiBlock *block,
+ const Panel *pa,
+ const int mx,
+ const int my)
{
- /* open panel */
- if (pa->flag & PNL_CLOSEDX) {
- if ((block->rect.xmin <= mx) && (block->rect.xmin + PNL_HEADER >= mx)) {
- return PANEL_MOUSE_INSIDE_HEADER;
- }
- }
- /* outside left/right side */
- else if ((block->rect.xmin > mx) || (block->rect.xmax < mx)) {
- /* pass */
- }
- else if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) {
- return PANEL_MOUSE_INSIDE_HEADER;
- }
- /* open panel */
- else if (!(pa->flag & PNL_CLOSEDY)) {
- if (pa->control & UI_PNL_SCALE) {
- if (block->rect.xmax - PNL_HEADER <= mx) {
- if (block->rect.ymin + PNL_HEADER >= my) {
- return PANEL_MOUSE_INSIDE_SCALE;
- }
- }
- }
- if ((block->rect.xmin <= mx) && (block->rect.xmax >= mx)) {
- if ((block->rect.ymin <= my) && (block->rect.ymax + PNL_HEADER >= my)) {
- return PANEL_MOUSE_INSIDE_CONTENT;
- }
- }
- }
- return PANEL_MOUSE_OUTSIDE;
+ /* open panel */
+ if (pa->flag & PNL_CLOSEDX) {
+ if ((block->rect.xmin <= mx) && (block->rect.xmin + PNL_HEADER >= mx)) {
+ return PANEL_MOUSE_INSIDE_HEADER;
+ }
+ }
+ /* outside left/right side */
+ else if ((block->rect.xmin > mx) || (block->rect.xmax < mx)) {
+ /* pass */
+ }
+ else if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) {
+ return PANEL_MOUSE_INSIDE_HEADER;
+ }
+ /* open panel */
+ else if (!(pa->flag & PNL_CLOSEDY)) {
+ if (pa->control & UI_PNL_SCALE) {
+ if (block->rect.xmax - PNL_HEADER <= mx) {
+ if (block->rect.ymin + PNL_HEADER >= my) {
+ return PANEL_MOUSE_INSIDE_SCALE;
+ }
+ }
+ }
+ if ((block->rect.xmin <= mx) && (block->rect.xmax >= mx)) {
+ if ((block->rect.ymin <= my) && (block->rect.ymax + PNL_HEADER >= my)) {
+ return PANEL_MOUSE_INSIDE_CONTENT;
+ }
+ }
+ }
+ return PANEL_MOUSE_OUTSIDE;
}
typedef struct uiPanelDragCollapseHandle {
- bool was_first_open;
- int xy_init[2];
+ bool was_first_open;
+ int xy_init[2];
} uiPanelDragCollapseHandle;
static void ui_panel_drag_collapse_handler_remove(bContext *UNUSED(C), void *userdata)
{
- uiPanelDragCollapseHandle *dragcol_data = userdata;
- MEM_freeN(dragcol_data);
+ uiPanelDragCollapseHandle *dragcol_data = userdata;
+ MEM_freeN(dragcol_data);
}
-static void ui_panel_drag_collapse(bContext *C, uiPanelDragCollapseHandle *dragcol_data, const int xy_dst[2])
+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);
- uiBlock *block;
- Panel *pa;
-
- for (block = ar->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);
-
- if ((pa = block->panel) == 0 || (pa->type && (pa->type->flag & PNL_NO_HEADER))) {
- continue;
- }
- oldflag = pa->flag;
-
- /* lock one axis */
- if (is_horizontal) {
- xy_b_block[1] = dragcol_data->xy_init[1];
- }
- else {
- xy_b_block[0] = dragcol_data->xy_init[0];
- }
-
- /* 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]);
-
- /* set up rect to match header size */
- rect.ymin = rect.ymax;
- rect.ymax = rect.ymin + PNL_HEADER;
- if (pa->flag & PNL_CLOSEDX) {
- rect.xmax = rect.xmin + PNL_HEADER;
- }
-
- /* touch all panels between last mouse coord and the current one */
- 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);
- }
- /* force panel to open */
- else {
- pa->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);
- }
- }
- }
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ uiBlock *block;
+ Panel *pa;
+
+ for (block = ar->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);
+
+ if ((pa = block->panel) == 0 || (pa->type && (pa->type->flag & PNL_NO_HEADER))) {
+ continue;
+ }
+ oldflag = pa->flag;
+
+ /* lock one axis */
+ if (is_horizontal) {
+ xy_b_block[1] = dragcol_data->xy_init[1];
+ }
+ else {
+ xy_b_block[0] = dragcol_data->xy_init[0];
+ }
+
+ /* 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]);
+
+ /* set up rect to match header size */
+ rect.ymin = rect.ymax;
+ rect.ymax = rect.ymin + PNL_HEADER;
+ if (pa->flag & PNL_CLOSEDX) {
+ rect.xmax = rect.xmin + PNL_HEADER;
+ }
+
+ /* touch all panels between last mouse coord and the current one */
+ 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);
+ }
+ /* force panel to open */
+ else {
+ pa->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);
+ }
+ }
+ }
}
/**
@@ -1555,915 +1571,931 @@ static void ui_panel_drag_collapse(bContext *C, uiPanelDragCollapseHandle *dragc
*/
static int ui_panel_drag_collapse_handler(bContext *C, const wmEvent *event, void *userdata)
{
- wmWindow *win = CTX_wm_window(C);
- uiPanelDragCollapseHandle *dragcol_data = userdata;
- short retval = WM_UI_HANDLER_CONTINUE;
-
- switch (event->type) {
- case MOUSEMOVE:
- ui_panel_drag_collapse(C, dragcol_data, &event->x);
-
- retval = WM_UI_HANDLER_BREAK;
- break;
- case LEFTMOUSE:
- if (event->val == KM_RELEASE) {
- /* done! */
- WM_event_remove_ui_handler(
- &win->modalhandlers,
- ui_panel_drag_collapse_handler,
- ui_panel_drag_collapse_handler_remove,
- dragcol_data, true);
- ui_panel_drag_collapse_handler_remove(C, dragcol_data);
- }
- /* don't let any left-mouse event fall through! */
- retval = WM_UI_HANDLER_BREAK;
- break;
- }
-
- return retval;
+ wmWindow *win = CTX_wm_window(C);
+ uiPanelDragCollapseHandle *dragcol_data = userdata;
+ short retval = WM_UI_HANDLER_CONTINUE;
+
+ switch (event->type) {
+ case MOUSEMOVE:
+ ui_panel_drag_collapse(C, dragcol_data, &event->x);
+
+ retval = WM_UI_HANDLER_BREAK;
+ break;
+ case LEFTMOUSE:
+ if (event->val == KM_RELEASE) {
+ /* done! */
+ WM_event_remove_ui_handler(&win->modalhandlers,
+ ui_panel_drag_collapse_handler,
+ ui_panel_drag_collapse_handler_remove,
+ dragcol_data,
+ true);
+ ui_panel_drag_collapse_handler_remove(C, dragcol_data);
+ }
+ /* don't let any left-mouse event fall through! */
+ retval = WM_UI_HANDLER_BREAK;
+ break;
+ }
+
+ return retval;
}
static void ui_panel_drag_collapse_handler_add(const bContext *C, const bool was_open)
{
- wmWindow *win = CTX_wm_window(C);
- const wmEvent *event = win->eventstate;
- uiPanelDragCollapseHandle *dragcol_data = MEM_mallocN(sizeof(*dragcol_data), __func__);
-
- dragcol_data->was_first_open = was_open;
- copy_v2_v2_int(dragcol_data->xy_init, &event->x);
-
- WM_event_add_ui_handler(
- C, &win->modalhandlers,
- ui_panel_drag_collapse_handler,
- ui_panel_drag_collapse_handler_remove,
- dragcol_data, 0);
+ wmWindow *win = CTX_wm_window(C);
+ const wmEvent *event = win->eventstate;
+ uiPanelDragCollapseHandle *dragcol_data = MEM_mallocN(sizeof(*dragcol_data), __func__);
+
+ dragcol_data->was_first_open = was_open;
+ copy_v2_v2_int(dragcol_data->xy_init, &event->x);
+
+ WM_event_add_ui_handler(C,
+ &win->modalhandlers,
+ ui_panel_drag_collapse_handler,
+ ui_panel_drag_collapse_handler_remove,
+ dragcol_data,
+ 0);
}
/* this function is supposed to call general window drawing too */
/* also it supposes a block has panel, and isn't a menu */
-static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, int my, int event, short ctrl, short shift)
+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);
- Panel *pa;
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ Panel *pa;
#ifdef USE_PIN_HIDDEN
- const bool show_pin = UI_panel_category_is_visible(ar) && (block->panel->flag & PNL_PIN);
+ const bool show_pin = UI_panel_category_is_visible(ar) && (block->panel->flag & PNL_PIN);
#else
- const bool show_pin = UI_panel_category_is_visible(ar);
+ const bool show_pin = UI_panel_category_is_visible(ar);
#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;
-
- rctf rect_drag, rect_pin;
- float rect_leftmost;
-
-
- /* drag and pin rect's */
- rect_drag = block->rect;
- rect_drag.xmin = block->rect.xmax - (PNL_ICON * 1.5f);
- rect_pin = rect_drag;
- if (show_pin) {
- BLI_rctf_translate(&rect_pin, -PNL_ICON, 0.0f);
- }
- rect_leftmost = rect_pin.xmin;
-
- /* mouse coordinates in panel space! */
-
- /* XXX weak code, currently it assumes layout style for location of widgets */
-
- /* check open/collapsed button */
- if (event == RETKEY) {
- button = 1;
- }
- else if (event == AKEY) {
- button = 1;
- }
- else if (ELEM(event, 0, RETKEY, LEFTMOUSE) && shift) {
- block->panel->flag ^= PNL_PIN;
- button = 2;
- }
- else if (block->panel->flag & PNL_CLOSEDX) {
- if (my >= block->rect.ymax) {
- button = 1;
- }
- }
- else if (block->panel->control & UI_PNL_CLOSE) {
- /* whole of header can be used to collapse panel (except top-right corner) */
- if (mx <= block->rect.xmax - 8 - PNL_ICON) {
- button = 2;
- }
- //else if (mx <= block->rect.xmin + 10 + 2 * PNL_ICON + 2) {
- // button = 1;
- //}
- }
- else if (mx < rect_leftmost) {
- button = 1;
- }
-
- if (button) {
- if (button == 2) { /* close */
- ED_region_tag_redraw(ar);
- }
- else { /* collapse */
- if (ctrl) {
- panels_collapse_all(sa, ar, block->panel);
-
- /* reset the view - we don't want to display a view without content */
- UI_view2d_offset(&ar->v2d, 0.0f, 1.0f);
- }
-
- if (block->panel->flag & PNL_CLOSED) {
- block->panel->flag &= ~PNL_CLOSED;
- /* snap back up so full panel aligns with screen edge */
- if (block->panel->snap & PNL_SNAP_BOTTOM) {
- block->panel->ofsy = 0;
- }
-
- if (event == LEFTMOUSE) {
- ui_panel_drag_collapse_handler_add(C, false);
- }
- }
- else if (align == BUT_HORIZONTAL) {
- block->panel->flag |= PNL_CLOSEDX;
-
- if (event == LEFTMOUSE) {
- ui_panel_drag_collapse_handler_add(C, true);
- }
- }
- else {
- /* snap down to bottom screen edge */
- block->panel->flag |= PNL_CLOSEDY;
- if (block->panel->snap & PNL_SNAP_BOTTOM) {
- block->panel->ofsy = -block->panel->sizey;
- }
-
- if (event == LEFTMOUSE) {
- ui_panel_drag_collapse_handler_add(C, true);
- }
- }
-
- for (pa = ar->panels.first; pa; pa = pa->next) {
- if (pa->paneltab == block->panel) {
- if (block->panel->flag & PNL_CLOSED) {
- pa->flag |= PNL_CLOSED;
- }
- else {
- pa->flag &= ~PNL_CLOSED;
- }
- }
- }
- }
-
- if (align) {
- panel_activate_state(C, block->panel, PANEL_STATE_ANIMATION);
- }
- else {
- /* 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);
- }
- }
- 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) {
- 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);
- }
+ 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;
+
+ rctf rect_drag, rect_pin;
+ float rect_leftmost;
+
+ /* drag and pin rect's */
+ rect_drag = block->rect;
+ rect_drag.xmin = block->rect.xmax - (PNL_ICON * 1.5f);
+ rect_pin = rect_drag;
+ if (show_pin) {
+ BLI_rctf_translate(&rect_pin, -PNL_ICON, 0.0f);
+ }
+ rect_leftmost = rect_pin.xmin;
+
+ /* mouse coordinates in panel space! */
+
+ /* XXX weak code, currently it assumes layout style for location of widgets */
+
+ /* check open/collapsed button */
+ if (event == RETKEY) {
+ button = 1;
+ }
+ else if (event == AKEY) {
+ button = 1;
+ }
+ else if (ELEM(event, 0, RETKEY, LEFTMOUSE) && shift) {
+ block->panel->flag ^= PNL_PIN;
+ button = 2;
+ }
+ else if (block->panel->flag & PNL_CLOSEDX) {
+ if (my >= block->rect.ymax) {
+ button = 1;
+ }
+ }
+ else if (block->panel->control & UI_PNL_CLOSE) {
+ /* whole of header can be used to collapse panel (except top-right corner) */
+ if (mx <= block->rect.xmax - 8 - PNL_ICON) {
+ button = 2;
+ }
+ //else if (mx <= block->rect.xmin + 10 + 2 * PNL_ICON + 2) {
+ // button = 1;
+ //}
+ }
+ else if (mx < rect_leftmost) {
+ button = 1;
+ }
+
+ if (button) {
+ if (button == 2) { /* close */
+ ED_region_tag_redraw(ar);
+ }
+ else { /* collapse */
+ if (ctrl) {
+ panels_collapse_all(sa, ar, block->panel);
+
+ /* reset the view - we don't want to display a view without content */
+ UI_view2d_offset(&ar->v2d, 0.0f, 1.0f);
+ }
+
+ if (block->panel->flag & PNL_CLOSED) {
+ block->panel->flag &= ~PNL_CLOSED;
+ /* snap back up so full panel aligns with screen edge */
+ if (block->panel->snap & PNL_SNAP_BOTTOM) {
+ block->panel->ofsy = 0;
+ }
+
+ if (event == LEFTMOUSE) {
+ ui_panel_drag_collapse_handler_add(C, false);
+ }
+ }
+ else if (align == BUT_HORIZONTAL) {
+ block->panel->flag |= PNL_CLOSEDX;
+
+ if (event == LEFTMOUSE) {
+ ui_panel_drag_collapse_handler_add(C, true);
+ }
+ }
+ else {
+ /* snap down to bottom screen edge */
+ block->panel->flag |= PNL_CLOSEDY;
+ if (block->panel->snap & PNL_SNAP_BOTTOM) {
+ block->panel->ofsy = -block->panel->sizey;
+ }
+
+ if (event == LEFTMOUSE) {
+ ui_panel_drag_collapse_handler_add(C, true);
+ }
+ }
+
+ for (pa = ar->panels.first; pa; pa = pa->next) {
+ if (pa->paneltab == block->panel) {
+ if (block->panel->flag & PNL_CLOSED) {
+ pa->flag |= PNL_CLOSED;
+ }
+ else {
+ pa->flag &= ~PNL_CLOSED;
+ }
+ }
+ }
+ }
+
+ if (align) {
+ panel_activate_state(C, block->panel, PANEL_STATE_ANIMATION);
+ }
+ else {
+ /* 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);
+ }
+ }
+ 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) {
+ 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);
+ }
}
bool UI_panel_category_is_visible(ARegion *ar)
{
- /* more than one */
- return ar->panels_category.first && ar->panels_category.first != ar->panels_category.last;
+ /* more than one */
+ return ar->panels_category.first && ar->panels_category.first != ar->panels_category.last;
}
PanelCategoryDyn *UI_panel_category_find(ARegion *ar, const char *idname)
{
- return BLI_findstring(&ar->panels_category, idname, offsetof(PanelCategoryDyn, idname));
+ return BLI_findstring(&ar->panels_category, idname, offsetof(PanelCategoryDyn, idname));
}
PanelCategoryStack *UI_panel_category_active_find(ARegion *ar, const char *idname)
{
- return BLI_findstring(&ar->panels_category_active, idname, offsetof(PanelCategoryStack, idname));
+ return BLI_findstring(&ar->panels_category_active, idname, offsetof(PanelCategoryStack, idname));
}
const char *UI_panel_category_active_get(ARegion *ar, bool set_fallback)
{
- PanelCategoryStack *pc_act;
-
- for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next) {
- if (UI_panel_category_find(ar, pc_act->idname)) {
- return pc_act->idname;
- }
- }
-
- if (set_fallback) {
- PanelCategoryDyn *pc_dyn = ar->panels_category.first;
- if (pc_dyn) {
- UI_panel_category_active_set(ar, pc_dyn->idname);
- return pc_dyn->idname;
- }
- }
-
- return NULL;
+ PanelCategoryStack *pc_act;
+
+ for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next) {
+ if (UI_panel_category_find(ar, pc_act->idname)) {
+ return pc_act->idname;
+ }
+ }
+
+ if (set_fallback) {
+ PanelCategoryDyn *pc_dyn = ar->panels_category.first;
+ if (pc_dyn) {
+ UI_panel_category_active_set(ar, pc_dyn->idname);
+ return pc_dyn->idname;
+ }
+ }
+
+ return NULL;
}
void UI_panel_category_active_set(ARegion *ar, const char *idname)
{
- ListBase *lb = &ar->panels_category_active;
- PanelCategoryStack *pc_act = UI_panel_category_active_find(ar, idname);
-
- if (pc_act) {
- BLI_remlink(lb, pc_act);
- }
- else {
- pc_act = MEM_callocN(sizeof(PanelCategoryStack), __func__);
- BLI_strncpy(pc_act->idname, idname, sizeof(pc_act->idname));
- }
-
- BLI_addhead(lb, pc_act);
-
-
- /* validate all active panels, we could do this on load,
- * they are harmless - but we should remove somewhere.
- * (addons could define own and gather cruft over time) */
- {
- PanelCategoryStack *pc_act_next;
- /* intentionally skip first */
- 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))) {
- BLI_remlink(lb, pc_act);
- MEM_freeN(pc_act);
- }
- }
- }
+ ListBase *lb = &ar->panels_category_active;
+ PanelCategoryStack *pc_act = UI_panel_category_active_find(ar, idname);
+
+ if (pc_act) {
+ BLI_remlink(lb, pc_act);
+ }
+ else {
+ pc_act = MEM_callocN(sizeof(PanelCategoryStack), __func__);
+ BLI_strncpy(pc_act->idname, idname, sizeof(pc_act->idname));
+ }
+
+ BLI_addhead(lb, pc_act);
+
+ /* validate all active panels, we could do this on load,
+ * they are harmless - but we should remove somewhere.
+ * (addons could define own and gather cruft over time) */
+ {
+ PanelCategoryStack *pc_act_next;
+ /* intentionally skip first */
+ 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))) {
+ BLI_remlink(lb, pc_act);
+ MEM_freeN(pc_act);
+ }
+ }
+ }
}
PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(ARegion *ar, const int x, const int y)
{
- PanelCategoryDyn *ptd;
+ PanelCategoryDyn *ptd;
- for (ptd = ar->panels_category.first; ptd; ptd = ptd->next) {
- if (BLI_rcti_isect_pt(&ptd->rect, x, y)) {
- return ptd;
- }
- }
+ for (ptd = ar->panels_category.first; ptd; ptd = ptd->next) {
+ if (BLI_rcti_isect_pt(&ptd->rect, x, y)) {
+ return ptd;
+ }
+ }
- return NULL;
+ return NULL;
}
PanelCategoryDyn *UI_panel_category_find_mouse_over(ARegion *ar, 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(ar, event->mval[0], event->mval[1]);
}
-
void UI_panel_category_add(ARegion *ar, const char *name)
{
- PanelCategoryDyn *pc_dyn = MEM_callocN(sizeof(*pc_dyn), __func__);
- BLI_addtail(&ar->panels_category, pc_dyn);
+ PanelCategoryDyn *pc_dyn = MEM_callocN(sizeof(*pc_dyn), __func__);
+ BLI_addtail(&ar->panels_category, pc_dyn);
- BLI_strncpy(pc_dyn->idname, name, sizeof(pc_dyn->idname));
+ BLI_strncpy(pc_dyn->idname, name, sizeof(pc_dyn->idname));
- /* 'pc_dyn->rect' must be set on draw */
+ /* 'pc_dyn->rect' must be set on draw */
}
void UI_panel_category_clear_all(ARegion *ar)
{
- BLI_freelistN(&ar->panels_category);
+ BLI_freelistN(&ar->panels_category);
}
static void imm_buf_append(
- float vbuf[][2],
- uchar cbuf[][3],
- float x, float y, const uchar col[3], int *index)
+ float vbuf[][2], uchar cbuf[][3], float x, float y, const uchar col[3], int *index)
{
- ARRAY_SET_ITEMS(vbuf[*index], x, y);
- ARRAY_SET_ITEMS(cbuf[*index], UNPACK3(col));
- (*index)++;
+ ARRAY_SET_ITEMS(vbuf[*index], x, y);
+ ARRAY_SET_ITEMS(cbuf[*index], UNPACK3(col));
+ (*index)++;
}
/* based on UI_draw_roundbox, check on making a version which allows us to skip some sides */
-static void ui_panel_category_draw_tab(
- bool filled, float minx, float miny, float maxx, float maxy, float rad,
- const int roundboxtype,
- const bool use_highlight, const bool use_shadow, const bool use_flip_x,
- const uchar highlight_fade[3],
- const uchar col[3])
+static void ui_panel_category_draw_tab(bool filled,
+ float minx,
+ float miny,
+ float maxx,
+ float maxy,
+ float rad,
+ const int roundboxtype,
+ const bool use_highlight,
+ const bool use_shadow,
+ const bool use_flip_x,
+ const uchar highlight_fade[3],
+ const uchar col[3])
{
- float vec[4][2] = {
- {0.195, 0.02},
- {0.55, 0.169},
- {0.831, 0.45},
- {0.98, 0.805}};
- int a;
-
- /* mult */
- for (a = 0; a < 4; a++) {
- mul_v2_fl(vec[a], rad);
- }
-
- uint vert_len = 0;
- if (use_highlight) {
- vert_len += (roundboxtype & UI_CNR_TOP_RIGHT) ? 6 : 1;
- vert_len += (roundboxtype & UI_CNR_TOP_LEFT) ? 6 : 1;
- }
- if (use_highlight && !use_shadow) {
- vert_len++;
- }
- else {
- vert_len += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 6 : 1;
- vert_len += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 6 : 1;
- }
- /* Maximum size. */
- float vbuf[24][2];
- uchar cbuf[24][3];
- int buf_index = 0;
-
- /* start with corner right-top */
- if (use_highlight) {
- if (roundboxtype & UI_CNR_TOP_RIGHT) {
- imm_buf_append(vbuf, cbuf, maxx, maxy - rad, col, &buf_index);
- for (a = 0; a < 4; a++) {
- imm_buf_append(vbuf, cbuf, maxx - vec[a][1], maxy - rad + vec[a][0], col, &buf_index);
- }
- imm_buf_append(vbuf, cbuf, maxx - rad, maxy, col, &buf_index);
- }
- else {
- imm_buf_append(vbuf, cbuf, maxx, maxy, col, &buf_index);
- }
-
- /* corner left-top */
- if (roundboxtype & UI_CNR_TOP_LEFT) {
- imm_buf_append(vbuf, cbuf, minx + rad, maxy, col, &buf_index);
- for (a = 0; a < 4; a++) {
- imm_buf_append(vbuf, cbuf, minx + rad - vec[a][0], maxy - vec[a][1], col, &buf_index);
- }
- imm_buf_append(vbuf, cbuf, minx, maxy - rad, col, &buf_index);
- }
- else {
- imm_buf_append(vbuf, cbuf, minx, maxy, col, &buf_index);
- }
- }
-
- if (use_highlight && !use_shadow) {
- imm_buf_append(vbuf, cbuf, minx, miny + rad, highlight_fade ? col : highlight_fade, &buf_index);
- }
- else {
- /* corner left-bottom */
- if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
- imm_buf_append(vbuf, cbuf, minx, miny + rad, col, &buf_index);
- for (a = 0; a < 4; a++) {
- imm_buf_append(vbuf, cbuf, minx + vec[a][1], miny + rad - vec[a][0], col, &buf_index);
- }
- imm_buf_append(vbuf, cbuf, minx + rad, miny, col, &buf_index);
- }
- else {
- imm_buf_append(vbuf, cbuf, minx, miny, col, &buf_index);
- }
-
- /* corner right-bottom */
- if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
- imm_buf_append(vbuf, cbuf, maxx - rad, miny, col, &buf_index);
- for (a = 0; a < 4; a++) {
- imm_buf_append(vbuf, cbuf, maxx - rad + vec[a][0], miny + vec[a][1], col, &buf_index);
- }
- imm_buf_append(vbuf, cbuf, maxx, miny + rad, col, &buf_index);
- }
- else {
- imm_buf_append(vbuf, cbuf, maxx, miny, col, &buf_index);
- }
- }
-
- if (use_flip_x) {
- float midx = (minx + maxx) / 2.0f;
- for (int i = 0; i < buf_index; i++) {
- vbuf[i][0] = midx - (vbuf[i][0] - midx);
- }
-
- }
-
- GPUVertFormat *format = immVertexFormat();
- 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_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
- immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_STRIP, vert_len);
- for (int i = 0; i < buf_index; i++) {
- immAttr3ubv(color, cbuf[i]);
- immVertex2fv(pos, vbuf[i]);
- }
- immEnd();
- immUnbindProgram();
+ float vec[4][2] = {{0.195, 0.02}, {0.55, 0.169}, {0.831, 0.45}, {0.98, 0.805}};
+ int a;
+
+ /* mult */
+ for (a = 0; a < 4; a++) {
+ mul_v2_fl(vec[a], rad);
+ }
+
+ uint vert_len = 0;
+ if (use_highlight) {
+ vert_len += (roundboxtype & UI_CNR_TOP_RIGHT) ? 6 : 1;
+ vert_len += (roundboxtype & UI_CNR_TOP_LEFT) ? 6 : 1;
+ }
+ if (use_highlight && !use_shadow) {
+ vert_len++;
+ }
+ else {
+ vert_len += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 6 : 1;
+ vert_len += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 6 : 1;
+ }
+ /* Maximum size. */
+ float vbuf[24][2];
+ uchar cbuf[24][3];
+ int buf_index = 0;
+
+ /* start with corner right-top */
+ if (use_highlight) {
+ if (roundboxtype & UI_CNR_TOP_RIGHT) {
+ imm_buf_append(vbuf, cbuf, maxx, maxy - rad, col, &buf_index);
+ for (a = 0; a < 4; a++) {
+ imm_buf_append(vbuf, cbuf, maxx - vec[a][1], maxy - rad + vec[a][0], col, &buf_index);
+ }
+ imm_buf_append(vbuf, cbuf, maxx - rad, maxy, col, &buf_index);
+ }
+ else {
+ imm_buf_append(vbuf, cbuf, maxx, maxy, col, &buf_index);
+ }
+
+ /* corner left-top */
+ if (roundboxtype & UI_CNR_TOP_LEFT) {
+ imm_buf_append(vbuf, cbuf, minx + rad, maxy, col, &buf_index);
+ for (a = 0; a < 4; a++) {
+ imm_buf_append(vbuf, cbuf, minx + rad - vec[a][0], maxy - vec[a][1], col, &buf_index);
+ }
+ imm_buf_append(vbuf, cbuf, minx, maxy - rad, col, &buf_index);
+ }
+ else {
+ imm_buf_append(vbuf, cbuf, minx, maxy, col, &buf_index);
+ }
+ }
+
+ if (use_highlight && !use_shadow) {
+ imm_buf_append(
+ vbuf, cbuf, minx, miny + rad, highlight_fade ? col : highlight_fade, &buf_index);
+ }
+ else {
+ /* corner left-bottom */
+ if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
+ imm_buf_append(vbuf, cbuf, minx, miny + rad, col, &buf_index);
+ for (a = 0; a < 4; a++) {
+ imm_buf_append(vbuf, cbuf, minx + vec[a][1], miny + rad - vec[a][0], col, &buf_index);
+ }
+ imm_buf_append(vbuf, cbuf, minx + rad, miny, col, &buf_index);
+ }
+ else {
+ imm_buf_append(vbuf, cbuf, minx, miny, col, &buf_index);
+ }
+
+ /* corner right-bottom */
+ if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
+ imm_buf_append(vbuf, cbuf, maxx - rad, miny, col, &buf_index);
+ for (a = 0; a < 4; a++) {
+ imm_buf_append(vbuf, cbuf, maxx - rad + vec[a][0], miny + vec[a][1], col, &buf_index);
+ }
+ imm_buf_append(vbuf, cbuf, maxx, miny + rad, col, &buf_index);
+ }
+ else {
+ imm_buf_append(vbuf, cbuf, maxx, miny, col, &buf_index);
+ }
+ }
+
+ if (use_flip_x) {
+ float midx = (minx + maxx) / 2.0f;
+ for (int i = 0; i < buf_index; i++) {
+ vbuf[i][0] = midx - (vbuf[i][0] - midx);
+ }
+ }
+
+ GPUVertFormat *format = immVertexFormat();
+ 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_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+ immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_STRIP, vert_len);
+ for (int i = 0; i < buf_index; i++) {
+ immAttr3ubv(color, cbuf[i]);
+ immVertex2fv(pos, vbuf[i]);
+ }
+ immEnd();
+ immUnbindProgram();
}
-
/**
* 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)
{
- /* no tab outlines for */
-// #define USE_FLAT_INACTIVE
- const bool is_left = (ar->alignment != RGN_ALIGN_RIGHT);
- View2D *v2d = &ar->v2d;
- 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 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;
- const int category_tabs_width = round_fl_to_int(UI_PANEL_CATEGORY_MARGIN_WIDTH * zoom);
- const float dpi_fac = UI_DPI_FAC;
- /* padding of tabs around text */
- const int tab_v_pad_text = round_fl_to_int((2 + ((px * 3) * dpi_fac)) * zoom);
- /* padding between tabs */
- const int tab_v_pad = round_fl_to_int((4 + (2 * px * dpi_fac)) * zoom);
- const float tab_curve_radius = ((px * 3) * dpi_fac) * zoom;
- /* We flip the tab drawing, so always use these flags. */
- const int roundboxtype = UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT;
- bool is_alpha;
- bool do_scaletabs = false;
+ /* no tab outlines for */
+ // #define USE_FLAT_INACTIVE
+ const bool is_left = (ar->alignment != RGN_ALIGN_RIGHT);
+ View2D *v2d = &ar->v2d;
+ 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 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;
+ const int category_tabs_width = round_fl_to_int(UI_PANEL_CATEGORY_MARGIN_WIDTH * zoom);
+ const float dpi_fac = UI_DPI_FAC;
+ /* padding of tabs around text */
+ const int tab_v_pad_text = round_fl_to_int((2 + ((px * 3) * dpi_fac)) * zoom);
+ /* padding between tabs */
+ const int tab_v_pad = round_fl_to_int((4 + (2 * px * dpi_fac)) * zoom);
+ const float tab_curve_radius = ((px * 3) * dpi_fac) * zoom;
+ /* We flip the tab drawing, so always use these flags. */
+ const int roundboxtype = UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT;
+ bool is_alpha;
+ bool do_scaletabs = false;
#ifdef USE_FLAT_INACTIVE
- bool is_active_prev = false;
+ bool is_active_prev = false;
#endif
- float scaletabs = 1.0f;
- /* same for all tabs */
- /* intentionally dont scale by 'px' */
- const int rct_xmin = is_left ? v2d->mask.xmin + 3 : (v2d->mask.xmax - category_tabs_width);
- const int rct_xmax = is_left ? v2d->mask.xmin + category_tabs_width : (v2d->mask.xmax - 3);
- const int text_v_ofs = (rct_xmax - rct_xmin) * 0.3f;
-
- int y_ofs = tab_v_pad;
-
- /* Primary theme colors */
- uchar theme_col_back[4];
- uchar theme_col_text[3];
- uchar theme_col_text_hi[3];
-
- /* Tab colors */
- uchar theme_col_tab_bg[4];
- uchar theme_col_tab_active[3];
- uchar theme_col_tab_inactive[3];
-
- /* Secondary theme colors */
- uchar theme_col_tab_outline[3];
- uchar theme_col_tab_divider[3]; /* line that divides tabs from the main region */
- uchar theme_col_tab_highlight[3];
- uchar theme_col_tab_highlight_inactive[3];
-
-
-
- UI_GetThemeColor4ubv(TH_BACK, theme_col_back);
- UI_GetThemeColor3ubv(TH_TEXT, theme_col_text);
- UI_GetThemeColor3ubv(TH_TEXT_HI, theme_col_text_hi);
-
- UI_GetThemeColor4ubv(TH_TAB_BACK, theme_col_tab_bg);
- UI_GetThemeColor3ubv(TH_TAB_ACTIVE, theme_col_tab_active);
- UI_GetThemeColor3ubv(TH_TAB_INACTIVE, theme_col_tab_inactive);
- UI_GetThemeColor3ubv(TH_TAB_OUTLINE, theme_col_tab_outline);
-
- interp_v3_v3v3_uchar(theme_col_tab_divider, theme_col_back, theme_col_tab_outline, 0.3f);
- interp_v3_v3v3_uchar(theme_col_tab_highlight, theme_col_back, theme_col_text_hi, 0.2f);
- 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));
-
- if (fstyle->kerning == 1) {
- BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- }
-
- BLF_enable(fontid, BLF_ROTATION);
- BLF_rotation(fontid, M_PI_2);
- //UI_fontstyle_set(&style->widget);
- ui_fontscale(&fstyle_points, aspect / (U.pixelsize * 1.1f));
- BLF_size(fontid, fstyle_points, U.dpi);
-
- BLI_assert(UI_panel_category_is_visible(ar));
-
-
- /* calculate tab rect's and check if we need to scale down */
- for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
- rcti *rct = &pc_dyn->rect;
- const char *category_id = pc_dyn->idname;
- const char *category_id_draw = IFACE_(category_id);
- const int category_width = BLF_width(fontid, category_id_draw, BLF_DRAW_STR_DUMMY_MAX);
-
- rct->xmin = rct_xmin;
- rct->xmax = rct_xmax;
-
- rct->ymin = v2d->mask.ymax - (y_ofs + category_width + (tab_v_pad_text * 2));
- rct->ymax = v2d->mask.ymax - (y_ofs);
-
- y_ofs += category_width + tab_v_pad + (tab_v_pad_text * 2);
- }
-
- 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) {
- 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;
- }
-
- do_scaletabs = true;
- }
-
-
- /* begin drawing */
- GPU_line_smooth(true);
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* draw the background */
- if (is_alpha) {
- GPU_blend(true);
- immUniformColor4ubv(theme_col_tab_bg);
- }
- else {
- immUniformColor3ubv(theme_col_tab_bg);
- }
-
- if (is_left) {
- immRecti(pos, v2d->mask.xmin, v2d->mask.ymin, v2d->mask.xmin + category_tabs_width, v2d->mask.ymax);
- }
- else {
- immRecti(pos, v2d->mask.xmax - category_tabs_width, v2d->mask.ymin, v2d->mask.xmax, v2d->mask.ymax);
- }
-
- if (is_alpha) {
- GPU_blend(false);
- }
-
- immUnbindProgram();
-
- const int divider_xmin =
- is_left ? (v2d->mask.xmin + (category_tabs_width - px)) : (v2d->mask.xmax - category_tabs_width) + px;
- 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) {
- const rcti *rct = &pc_dyn->rect;
- const char *category_id = pc_dyn->idname;
- const char *category_id_draw = IFACE_(category_id);
- int category_width = BLI_rcti_size_y(rct) - (tab_v_pad_text * 2);
- size_t category_draw_len = BLF_DRAW_STR_DUMMY_MAX;
- // int category_width = BLF_width(fontid, category_id_draw, BLF_DRAW_STR_DUMMY_MAX);
-
- const bool is_active = STREQ(category_id, category_id_active);
-
- GPU_blend(true);
+ float scaletabs = 1.0f;
+ /* same for all tabs */
+ /* intentionally dont scale by 'px' */
+ const int rct_xmin = is_left ? v2d->mask.xmin + 3 : (v2d->mask.xmax - category_tabs_width);
+ const int rct_xmax = is_left ? v2d->mask.xmin + category_tabs_width : (v2d->mask.xmax - 3);
+ const int text_v_ofs = (rct_xmax - rct_xmin) * 0.3f;
+
+ int y_ofs = tab_v_pad;
+
+ /* Primary theme colors */
+ uchar theme_col_back[4];
+ uchar theme_col_text[3];
+ uchar theme_col_text_hi[3];
+
+ /* Tab colors */
+ uchar theme_col_tab_bg[4];
+ uchar theme_col_tab_active[3];
+ uchar theme_col_tab_inactive[3];
+
+ /* Secondary theme colors */
+ uchar theme_col_tab_outline[3];
+ uchar theme_col_tab_divider[3]; /* line that divides tabs from the main region */
+ uchar theme_col_tab_highlight[3];
+ uchar theme_col_tab_highlight_inactive[3];
+
+ UI_GetThemeColor4ubv(TH_BACK, theme_col_back);
+ UI_GetThemeColor3ubv(TH_TEXT, theme_col_text);
+ UI_GetThemeColor3ubv(TH_TEXT_HI, theme_col_text_hi);
+
+ UI_GetThemeColor4ubv(TH_TAB_BACK, theme_col_tab_bg);
+ UI_GetThemeColor3ubv(TH_TAB_ACTIVE, theme_col_tab_active);
+ UI_GetThemeColor3ubv(TH_TAB_INACTIVE, theme_col_tab_inactive);
+ UI_GetThemeColor3ubv(TH_TAB_OUTLINE, theme_col_tab_outline);
+
+ interp_v3_v3v3_uchar(theme_col_tab_divider, theme_col_back, theme_col_tab_outline, 0.3f);
+ interp_v3_v3v3_uchar(theme_col_tab_highlight, theme_col_back, theme_col_text_hi, 0.2f);
+ 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));
+
+ if (fstyle->kerning == 1) {
+ BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
+
+ BLF_enable(fontid, BLF_ROTATION);
+ BLF_rotation(fontid, M_PI_2);
+ //UI_fontstyle_set(&style->widget);
+ ui_fontscale(&fstyle_points, aspect / (U.pixelsize * 1.1f));
+ BLF_size(fontid, fstyle_points, U.dpi);
+
+ BLI_assert(UI_panel_category_is_visible(ar));
+
+ /* calculate tab rect's and check if we need to scale down */
+ for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
+ rcti *rct = &pc_dyn->rect;
+ const char *category_id = pc_dyn->idname;
+ const char *category_id_draw = IFACE_(category_id);
+ const int category_width = BLF_width(fontid, category_id_draw, BLF_DRAW_STR_DUMMY_MAX);
+
+ rct->xmin = rct_xmin;
+ rct->xmax = rct_xmax;
+
+ rct->ymin = v2d->mask.ymax - (y_ofs + category_width + (tab_v_pad_text * 2));
+ rct->ymax = v2d->mask.ymax - (y_ofs);
+
+ y_ofs += category_width + tab_v_pad + (tab_v_pad_text * 2);
+ }
+
+ 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) {
+ 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;
+ }
+
+ do_scaletabs = true;
+ }
+
+ /* begin drawing */
+ GPU_line_smooth(true);
+
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* draw the background */
+ if (is_alpha) {
+ GPU_blend(true);
+ immUniformColor4ubv(theme_col_tab_bg);
+ }
+ else {
+ immUniformColor3ubv(theme_col_tab_bg);
+ }
+
+ if (is_left) {
+ immRecti(
+ pos, v2d->mask.xmin, v2d->mask.ymin, v2d->mask.xmin + category_tabs_width, v2d->mask.ymax);
+ }
+ else {
+ immRecti(
+ pos, v2d->mask.xmax - category_tabs_width, v2d->mask.ymin, v2d->mask.xmax, v2d->mask.ymax);
+ }
+
+ if (is_alpha) {
+ GPU_blend(false);
+ }
+
+ immUnbindProgram();
+
+ const int divider_xmin = is_left ? (v2d->mask.xmin + (category_tabs_width - px)) :
+ (v2d->mask.xmax - category_tabs_width) + px;
+ 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) {
+ const rcti *rct = &pc_dyn->rect;
+ const char *category_id = pc_dyn->idname;
+ const char *category_id_draw = IFACE_(category_id);
+ int category_width = BLI_rcti_size_y(rct) - (tab_v_pad_text * 2);
+ size_t category_draw_len = BLF_DRAW_STR_DUMMY_MAX;
+ // int category_width = BLF_width(fontid, category_id_draw, BLF_DRAW_STR_DUMMY_MAX);
+
+ const bool is_active = STREQ(category_id, category_id_active);
+
+ GPU_blend(true);
#ifdef USE_FLAT_INACTIVE
- if (is_active)
+ if (is_active)
#endif
- {
- const bool use_flip_x = !is_left;
- ui_panel_category_draw_tab(
- true, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
- tab_curve_radius - px, roundboxtype, true, true, use_flip_x,
- NULL,
- is_active ? theme_col_tab_active : theme_col_tab_inactive);
-
- /* tab outline */
- ui_panel_category_draw_tab(
- false, rct->xmin - px_x_sign, rct->ymin - px, rct->xmax - px_x_sign, rct->ymax + px,
- tab_curve_radius, roundboxtype, true, true, use_flip_x,
- NULL,
- theme_col_tab_outline);
-
- /* tab highlight (3d look) */
- ui_panel_category_draw_tab(
- false, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
- tab_curve_radius, roundboxtype, true, false, use_flip_x,
- is_active ? theme_col_back : theme_col_tab_inactive,
- is_active ? theme_col_tab_highlight : theme_col_tab_highlight_inactive);
- }
-
- /* tab blackline */
- if (!is_active) {
- pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- immUniformColor3ubv(theme_col_tab_divider);
- immRecti(pos,
- divider_xmin,
- rct->ymin - tab_v_pad,
- divider_xmax,
- rct->ymax + tab_v_pad);
- immUnbindProgram();
- }
-
- if (do_scaletabs) {
- category_draw_len = BLF_width_to_strlen(
- fontid, category_id_draw, category_draw_len,
- category_width, NULL);
- }
-
- BLF_position(fontid, rct->xmax - text_v_ofs, rct->ymin + tab_v_pad_text, 0.0f);
-
- /* tab titles */
-
- /* draw white shadow to give text more depth */
- BLF_color3ubv(fontid, theme_col_text);
-
- /* main tab title */
- BLF_draw(fontid, category_id_draw, category_draw_len);
-
- GPU_blend(false);
-
- /* tab blackline remaining (last tab) */
- pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- if (pc_dyn->prev == NULL) {
- immUniformColor3ubv(theme_col_tab_divider);
- immRecti(pos,
- divider_xmin,
- rct->ymax + px,
- divider_xmax,
- v2d->mask.ymax);
- }
- if (pc_dyn->next == NULL) {
- immUniformColor3ubv(theme_col_tab_divider);
- immRecti(pos,
- divider_xmin,
- 0,
- divider_xmax,
- rct->ymin);
- }
+ {
+ const bool use_flip_x = !is_left;
+ ui_panel_category_draw_tab(true,
+ rct->xmin,
+ rct->ymin,
+ rct->xmax,
+ rct->ymax,
+ tab_curve_radius - px,
+ roundboxtype,
+ true,
+ true,
+ use_flip_x,
+ NULL,
+ is_active ? theme_col_tab_active : theme_col_tab_inactive);
+
+ /* tab outline */
+ ui_panel_category_draw_tab(false,
+ rct->xmin - px_x_sign,
+ rct->ymin - px,
+ rct->xmax - px_x_sign,
+ rct->ymax + px,
+ tab_curve_radius,
+ roundboxtype,
+ true,
+ true,
+ use_flip_x,
+ NULL,
+ theme_col_tab_outline);
+
+ /* tab highlight (3d look) */
+ ui_panel_category_draw_tab(false,
+ rct->xmin,
+ rct->ymin,
+ rct->xmax,
+ rct->ymax,
+ tab_curve_radius,
+ roundboxtype,
+ true,
+ false,
+ use_flip_x,
+ is_active ? theme_col_back : theme_col_tab_inactive,
+ is_active ? theme_col_tab_highlight :
+ theme_col_tab_highlight_inactive);
+ }
+
+ /* tab blackline */
+ if (!is_active) {
+ pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3ubv(theme_col_tab_divider);
+ immRecti(pos, divider_xmin, rct->ymin - tab_v_pad, divider_xmax, rct->ymax + tab_v_pad);
+ immUnbindProgram();
+ }
+
+ if (do_scaletabs) {
+ category_draw_len = BLF_width_to_strlen(
+ fontid, category_id_draw, category_draw_len, category_width, NULL);
+ }
+
+ BLF_position(fontid, rct->xmax - text_v_ofs, rct->ymin + tab_v_pad_text, 0.0f);
+
+ /* tab titles */
+
+ /* draw white shadow to give text more depth */
+ BLF_color3ubv(fontid, theme_col_text);
+
+ /* main tab title */
+ BLF_draw(fontid, category_id_draw, category_draw_len);
+
+ GPU_blend(false);
+
+ /* tab blackline remaining (last tab) */
+ pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ if (pc_dyn->prev == NULL) {
+ immUniformColor3ubv(theme_col_tab_divider);
+ immRecti(pos, divider_xmin, rct->ymax + px, divider_xmax, v2d->mask.ymax);
+ }
+ if (pc_dyn->next == NULL) {
+ immUniformColor3ubv(theme_col_tab_divider);
+ immRecti(pos, divider_xmin, 0, divider_xmax, rct->ymin);
+ }
#ifdef USE_FLAT_INACTIVE
- /* draw line between inactive tabs */
- if (is_active == false && is_active_prev == false && pc_dyn->prev) {
- immUniformColor3ubv(theme_col_tab_divider);
- immRecti(pos, v2d->mask.xmin + (category_tabs_width / 5),
- rct->ymax + px,
- (v2d->mask.xmin + category_tabs_width) - (category_tabs_width / 5),
- rct->ymax + (px * 3));
- }
-
- is_active_prev = is_active;
+ /* draw line between inactive tabs */
+ if (is_active == false && is_active_prev == false && pc_dyn->prev) {
+ immUniformColor3ubv(theme_col_tab_divider);
+ immRecti(pos,
+ v2d->mask.xmin + (category_tabs_width / 5),
+ rct->ymax + px,
+ (v2d->mask.xmin + category_tabs_width) - (category_tabs_width / 5),
+ rct->ymax + (px * 3));
+ }
+
+ is_active_prev = is_active;
#endif
- immUnbindProgram();
+ immUnbindProgram();
- /* not essential, but allows events to be handled right up until the region edge [#38171] */
- if (is_left) {
- pc_dyn->rect.xmin = v2d->mask.xmin;
- }
- else {
- pc_dyn->rect.xmax = v2d->mask.xmax;
- }
- }
+ /* not essential, but allows events to be handled right up until the region edge [#38171] */
+ if (is_left) {
+ pc_dyn->rect.xmin = v2d->mask.xmin;
+ }
+ else {
+ pc_dyn->rect.xmax = v2d->mask.xmax;
+ }
+ }
- GPU_line_smooth(false);
+ GPU_line_smooth(false);
- BLF_disable(fontid, BLF_ROTATION);
+ BLF_disable(fontid, BLF_ROTATION);
- if (fstyle->kerning == 1) {
- BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- }
+ if (fstyle->kerning == 1) {
+ BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
#undef USE_FLAT_INACTIVE
}
-static int ui_handle_panel_category_cycling(const wmEvent *event, ARegion *ar, const uiBut *active_but)
+static int ui_handle_panel_category_cycling(const wmEvent *event,
+ ARegion *ar,
+ const uiBut *active_but)
{
- const bool is_mousewheel = ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE);
- const bool inside_tabregion = (
- (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));
-
- /* if mouse is inside non-tab region, ctrl key is required */
- if (is_mousewheel && !event->ctrl && !inside_tabregion) {
- return WM_UI_HANDLER_CONTINUE;
- }
-
-
- if (active_but && ui_but_supports_cycling(active_but)) {
- /* skip - exception to make cycling buttons
- * using ctrl+mousewheel work in tabbed regions */
- }
- else {
- const char *category = UI_panel_category_active_get(ar, false);
- if (LIKELY(category)) {
- PanelCategoryDyn *pc_dyn = UI_panel_category_find(ar, category);
- if (LIKELY(pc_dyn)) {
- if (is_mousewheel) {
- /* we can probably get rid of this and only allow ctrl+tabbing */
- pc_dyn = (event->type == WHEELDOWNMOUSE) ? pc_dyn->next : pc_dyn->prev;
- }
- else {
- const bool backwards = event->shift;
- pc_dyn = backwards ? pc_dyn->prev : pc_dyn->next;
- 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;
- }
- }
-
- 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);
- }
- }
- }
- return WM_UI_HANDLER_BREAK;
- }
-
- return WM_UI_HANDLER_CONTINUE;
+ const bool is_mousewheel = ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE);
+ const bool inside_tabregion =
+ ((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));
+
+ /* if mouse is inside non-tab region, ctrl key is required */
+ if (is_mousewheel && !event->ctrl && !inside_tabregion) {
+ return WM_UI_HANDLER_CONTINUE;
+ }
+
+ if (active_but && ui_but_supports_cycling(active_but)) {
+ /* skip - exception to make cycling buttons
+ * using ctrl+mousewheel work in tabbed regions */
+ }
+ else {
+ const char *category = UI_panel_category_active_get(ar, false);
+ if (LIKELY(category)) {
+ PanelCategoryDyn *pc_dyn = UI_panel_category_find(ar, category);
+ if (LIKELY(pc_dyn)) {
+ if (is_mousewheel) {
+ /* we can probably get rid of this and only allow ctrl+tabbing */
+ pc_dyn = (event->type == WHEELDOWNMOUSE) ? pc_dyn->next : pc_dyn->prev;
+ }
+ else {
+ const bool backwards = event->shift;
+ pc_dyn = backwards ? pc_dyn->prev : pc_dyn->next;
+ 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;
+ }
+ }
+
+ 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);
+ }
+ }
+ }
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
}
/* XXX should become modal keymap */
/* AKey is opening/closing panels, independent of button state now */
-int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, const uiBut *active_but)
+int ui_handler_panel_region(bContext *C,
+ const wmEvent *event,
+ ARegion *ar,
+ const uiBut *active_but)
{
- uiBlock *block;
- Panel *pa;
- int retval, mx, my;
- bool has_category_tabs = UI_panel_category_is_visible(ar);
-
- 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)) {
- return retval;
- }
-
- /* handle category tabs */
- if (has_category_tabs) {
- if (event->val == KM_PRESS) {
- if (event->type == LEFTMOUSE) {
- PanelCategoryDyn *pc_dyn = UI_panel_category_find_mouse_over(ar, event);
- if (pc_dyn) {
- UI_panel_category_active_set(ar, pc_dyn->idname);
- ED_region_tag_redraw(ar);
-
- /* reset scroll to the top [#38348] */
- UI_view2d_offset(&ar->v2d, -1.0f, 1.0f);
-
- retval = WM_UI_HANDLER_BREAK;
- }
- }
- else if ((event->type == TABKEY && event->ctrl) || ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
- /* cycle tabs */
- retval = ui_handle_panel_category_cycling(event, ar, active_but);
- }
- }
- }
-
- if (retval == WM_UI_HANDLER_BREAK) {
- return retval;
- }
-
- for (block = ar->uiblocks.last; block; block = block->prev) {
- uiPanelMouseState mouse_state;
-
- mx = event->x;
- my = event->y;
- ui_window_to_block(ar, block, &mx, &my);
-
- /* checks for mouse position inside */
- pa = block->panel;
-
- if (!pa || pa->paneltab != NULL) {
- continue;
- }
- /* XXX - accessed freed panels when scripts reload, need to fix. */
- if (pa->type && pa->type->flag & PNL_NO_HEADER) {
- continue;
- }
-
- mouse_state = ui_panel_mouse_state_get(block, pa, 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 (pa->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);
- }
- }
- else {
- ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl, event->shift);
- }
-
- retval = WM_UI_HANDLER_BREAK;
- continue;
- }
- }
-
- /* on active button, do not handle panels */
- if (ui_region_find_active_but(ar) != NULL) {
- continue;
- }
-
- if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER)) {
-
- if (event->val == KM_PRESS) {
-
- /* open close on header */
- if (ELEM(event->type, RETKEY, PADENTER)) {
- if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) {
- ui_handle_panel_header(C, block, mx, my, RETKEY, event->ctrl, event->shift);
- retval = WM_UI_HANDLER_BREAK;
- break;
- }
- }
- else if (event->type == LEFTMOUSE) {
- /* all inside clicks should return in break - overlapping/float panels */
- retval = WM_UI_HANDLER_BREAK;
-
- if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) {
- ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl, event->shift);
- 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);
- 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);
- retval = WM_UI_HANDLER_BREAK;
- break;
- }
- }
- else if (event->type == ESCKEY) {
- /*XXX 2.50*/
+ uiBlock *block;
+ Panel *pa;
+ int retval, mx, my;
+ bool has_category_tabs = UI_panel_category_is_visible(ar);
+
+ 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)) {
+ return retval;
+ }
+
+ /* handle category tabs */
+ if (has_category_tabs) {
+ if (event->val == KM_PRESS) {
+ if (event->type == LEFTMOUSE) {
+ PanelCategoryDyn *pc_dyn = UI_panel_category_find_mouse_over(ar, event);
+ if (pc_dyn) {
+ UI_panel_category_active_set(ar, pc_dyn->idname);
+ ED_region_tag_redraw(ar);
+
+ /* reset scroll to the top [#38348] */
+ UI_view2d_offset(&ar->v2d, -1.0f, 1.0f);
+
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if ((event->type == TABKEY && event->ctrl) ||
+ ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
+ /* cycle tabs */
+ retval = ui_handle_panel_category_cycling(event, ar, active_but);
+ }
+ }
+ }
+
+ if (retval == WM_UI_HANDLER_BREAK) {
+ return retval;
+ }
+
+ for (block = ar->uiblocks.last; block; block = block->prev) {
+ uiPanelMouseState mouse_state;
+
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(ar, block, &mx, &my);
+
+ /* checks for mouse position inside */
+ pa = block->panel;
+
+ if (!pa || pa->paneltab != NULL) {
+ continue;
+ }
+ /* XXX - accessed freed panels when scripts reload, need to fix. */
+ if (pa->type && pa->type->flag & PNL_NO_HEADER) {
+ continue;
+ }
+
+ mouse_state = ui_panel_mouse_state_get(block, pa, 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 (pa->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);
+ }
+ }
+ else {
+ ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl, event->shift);
+ }
+
+ retval = WM_UI_HANDLER_BREAK;
+ continue;
+ }
+ }
+
+ /* on active button, do not handle panels */
+ if (ui_region_find_active_but(ar) != NULL) {
+ continue;
+ }
+
+ if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER)) {
+
+ if (event->val == KM_PRESS) {
+
+ /* open close on header */
+ if (ELEM(event->type, RETKEY, PADENTER)) {
+ if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) {
+ ui_handle_panel_header(C, block, mx, my, RETKEY, event->ctrl, event->shift);
+ retval = WM_UI_HANDLER_BREAK;
+ break;
+ }
+ }
+ else if (event->type == LEFTMOUSE) {
+ /* all inside clicks should return in break - overlapping/float panels */
+ retval = WM_UI_HANDLER_BREAK;
+
+ if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) {
+ ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl, event->shift);
+ 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);
+ 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);
+ retval = WM_UI_HANDLER_BREAK;
+ break;
+ }
+ }
+ else if (event->type == ESCKEY) {
+ /*XXX 2.50*/
#if 0
- if (block->handler) {
- rem_blockhandler(sa, block->handler);
- ED_region_tag_redraw(ar);
- retval = WM_UI_HANDLER_BREAK;
- }
+ if (block->handler) {
+ rem_blockhandler(sa, block->handler);
+ ED_region_tag_redraw(ar);
+ retval = WM_UI_HANDLER_BREAK;
+ }
#endif
- }
- else if (event->type == PADPLUSKEY || event->type == PADMINUS) {
+ }
+ else if (event->type == PADPLUSKEY || event->type == 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 (inside_header) {
- zoom = 1;
- }
- }
- else {
- zoom = 1;
- }
-
- if (zoom) {
- ScrArea *sa = CTX_wm_area(C);
- SpaceLink *sl = sa->spacedata.first;
-
- if (sa->spacetype != SPACE_PROPERTIES) {
- if (!(pa->control & UI_PNL_SCALE)) {
- if (event->type == PADPLUSKEY) {
- sl->blockscale += 0.1;
- }
- else {
- sl->blockscale -= 0.1;
- }
- CLAMP(sl->blockscale, 0.6, 1.0);
-
- ED_region_tag_redraw(ar);
- retval = WM_UI_HANDLER_BREAK;
- }
- }
- }
+ int zoom = 0;
+
+ /* if panel is closed, only zoom if mouse is over the header */
+ if (pa->flag & (PNL_CLOSEDX | PNL_CLOSEDY)) {
+ if (inside_header) {
+ zoom = 1;
+ }
+ }
+ else {
+ zoom = 1;
+ }
+
+ if (zoom) {
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceLink *sl = sa->spacedata.first;
+
+ if (sa->spacetype != SPACE_PROPERTIES) {
+ if (!(pa->control & UI_PNL_SCALE)) {
+ if (event->type == PADPLUSKEY) {
+ sl->blockscale += 0.1;
+ }
+ else {
+ sl->blockscale -= 0.1;
+ }
+ CLAMP(sl->blockscale, 0.6, 1.0);
+
+ ED_region_tag_redraw(ar);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
+ }
#endif
- }
- }
- }
- }
+ }
+ }
+ }
+ }
- return retval;
+ return retval;
}
/**************** window level modal panel interaction **************/
@@ -2471,125 +2503,127 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons
/* note, this is modal handler and should not swallow events for animation */
static int ui_handler_panel(bContext *C, const wmEvent *event, void *userdata)
{
- Panel *panel = userdata;
- uiHandlePanelData *data = panel->activedata;
-
- /* 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);
-
- if (align) {
- panel_activate_state(C, panel, PANEL_STATE_ANIMATION);
- }
- else {
- panel_activate_state(C, panel, PANEL_STATE_EXIT);
- }
- }
- else if (event->type == MOUSEMOVE) {
- if (data->state == PANEL_STATE_DRAG) {
- ui_do_drag(C, event, panel);
- }
- }
- else if (event->type == TIMER && event->customdata == data->animtimer) {
- if (data->state == PANEL_STATE_ANIMATION) {
- ui_do_animate(C, panel);
- }
- else if (data->state == PANEL_STATE_DRAG) {
- ui_do_drag(C, event, panel);
- }
- }
-
- data = panel->activedata;
-
- if (data && data->state == PANEL_STATE_ANIMATION) {
- return WM_UI_HANDLER_CONTINUE;
- }
- else {
- return WM_UI_HANDLER_BREAK;
- }
+ Panel *panel = userdata;
+ uiHandlePanelData *data = panel->activedata;
+
+ /* 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);
+
+ if (align) {
+ panel_activate_state(C, panel, PANEL_STATE_ANIMATION);
+ }
+ else {
+ panel_activate_state(C, panel, PANEL_STATE_EXIT);
+ }
+ }
+ else if (event->type == MOUSEMOVE) {
+ if (data->state == PANEL_STATE_DRAG) {
+ ui_do_drag(C, event, panel);
+ }
+ }
+ else if (event->type == TIMER && event->customdata == data->animtimer) {
+ if (data->state == PANEL_STATE_ANIMATION) {
+ ui_do_animate(C, panel);
+ }
+ else if (data->state == PANEL_STATE_DRAG) {
+ ui_do_drag(C, event, panel);
+ }
+ }
+
+ data = panel->activedata;
+
+ if (data && data->state == PANEL_STATE_ANIMATION) {
+ return WM_UI_HANDLER_CONTINUE;
+ }
+ else {
+ return WM_UI_HANDLER_BREAK;
+ }
}
static void ui_handler_remove_panel(bContext *C, void *userdata)
{
- Panel *pa = userdata;
+ Panel *pa = userdata;
- panel_activate_state(C, pa, PANEL_STATE_EXIT);
+ panel_activate_state(C, pa, PANEL_STATE_EXIT);
}
static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelState state)
{
- uiHandlePanelData *data = pa->activedata;
- wmWindow *win = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
-
- if (data && data->state == state) {
- return;
- }
-
- if (state == PANEL_STATE_EXIT || state == PANEL_STATE_ANIMATION) {
- if (data && data->state != PANEL_STATE_ANIMATION) {
- /* XXX:
- * - the panel tabbing function call below (test_add_new_tabs()) has been commented out
- * "It is too easy to do by accident when reordering panels,
- * 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 */
- }
-
- pa->flag &= ~PNL_SELECT;
- }
- else {
- pa->flag |= PNL_SELECT;
- }
-
- if (data && data->animtimer) {
- WM_event_remove_timer(CTX_wm_manager(C), win, data->animtimer);
- data->animtimer = NULL;
- }
-
- if (state == PANEL_STATE_EXIT) {
- MEM_freeN(data);
- pa->activedata = NULL;
-
- WM_event_remove_ui_handler(&win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa, false);
- }
- else {
- if (!data) {
- data = MEM_callocN(sizeof(uiHandlePanelData), "uiHandlePanelData");
- pa->activedata = data;
-
- WM_event_add_ui_handler(C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa, 0);
- }
-
- if (ELEM(state, PANEL_STATE_ANIMATION, PANEL_STATE_DRAG)) {
- data->animtimer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, ANIMATION_INTERVAL);
- }
-
- 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->starttime = PIL_check_seconds_timer();
- }
-
- ED_region_tag_redraw(ar);
+ uiHandlePanelData *data = pa->activedata;
+ wmWindow *win = CTX_wm_window(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ if (data && data->state == state) {
+ return;
+ }
+
+ if (state == PANEL_STATE_EXIT || state == PANEL_STATE_ANIMATION) {
+ if (data && data->state != PANEL_STATE_ANIMATION) {
+ /* XXX:
+ * - the panel tabbing function call below (test_add_new_tabs()) has been commented out
+ * "It is too easy to do by accident when reordering panels,
+ * 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 */
+ }
+
+ pa->flag &= ~PNL_SELECT;
+ }
+ else {
+ pa->flag |= PNL_SELECT;
+ }
+
+ if (data && data->animtimer) {
+ WM_event_remove_timer(CTX_wm_manager(C), win, data->animtimer);
+ data->animtimer = NULL;
+ }
+
+ if (state == PANEL_STATE_EXIT) {
+ MEM_freeN(data);
+ pa->activedata = NULL;
+
+ WM_event_remove_ui_handler(
+ &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa, false);
+ }
+ else {
+ if (!data) {
+ data = MEM_callocN(sizeof(uiHandlePanelData), "uiHandlePanelData");
+ pa->activedata = data;
+
+ WM_event_add_ui_handler(
+ C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa, 0);
+ }
+
+ if (ELEM(state, PANEL_STATE_ANIMATION, PANEL_STATE_DRAG)) {
+ data->animtimer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, ANIMATION_INTERVAL);
+ }
+
+ 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->starttime = PIL_check_seconds_timer();
+ }
+
+ ED_region_tag_redraw(ar);
}
PanelType *UI_paneltype_find(int space_id, int region_id, const char *idname)
{
- SpaceType *st = BKE_spacetype_from_id(space_id);
- if (st) {
- ARegionType *art = BKE_regiontype_from_id(st, region_id);
- if (art) {
- return BLI_findstring(&art->paneltypes, idname, offsetof(PanelType, idname));
- }
- }
- return NULL;
+ SpaceType *st = BKE_spacetype_from_id(space_id);
+ if (st) {
+ ARegionType *art = BKE_regiontype_from_id(st, region_id);
+ if (art) {
+ return BLI_findstring(&art->paneltypes, idname, offsetof(PanelType, idname));
+ }
+ }
+ return NULL;
}
diff --git a/source/blender/editors/interface/interface_query.c b/source/blender/editors/interface/interface_query.c
index 1954e20ab8b..be09e44fa9d 100644
--- a/source/blender/editors/interface/interface_query.c
+++ b/source/blender/editors/interface/interface_query.c
@@ -40,37 +40,33 @@
/** \name Button (#uiBut) State
* \{ */
-
bool ui_but_is_editable(const uiBut *but)
{
- return !ELEM(
- but->type,
- UI_BTYPE_LABEL, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE,
- UI_BTYPE_ROUNDBOX, UI_BTYPE_LISTBOX, UI_BTYPE_PROGRESS_BAR);
+ return !ELEM(but->type,
+ UI_BTYPE_LABEL,
+ UI_BTYPE_SEPR,
+ UI_BTYPE_SEPR_LINE,
+ UI_BTYPE_ROUNDBOX,
+ UI_BTYPE_LISTBOX,
+ UI_BTYPE_PROGRESS_BAR);
}
bool ui_but_is_editable_as_text(const uiBut *but)
{
- return ELEM(
- but->type,
- UI_BTYPE_TEXT, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER,
- UI_BTYPE_SEARCH_MENU);
-
+ return ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, UI_BTYPE_SEARCH_MENU);
}
bool ui_but_is_toggle(const uiBut *but)
{
- return ELEM(
- but->type,
- UI_BTYPE_BUT_TOGGLE,
- UI_BTYPE_TOGGLE,
- UI_BTYPE_ICON_TOGGLE,
- UI_BTYPE_ICON_TOGGLE_N,
- UI_BTYPE_TOGGLE_N,
- UI_BTYPE_CHECKBOX,
- UI_BTYPE_CHECKBOX_N,
- UI_BTYPE_ROW
- );
+ return ELEM(but->type,
+ UI_BTYPE_BUT_TOGGLE,
+ UI_BTYPE_TOGGLE,
+ UI_BTYPE_ICON_TOGGLE,
+ UI_BTYPE_ICON_TOGGLE_N,
+ UI_BTYPE_TOGGLE_N,
+ UI_BTYPE_CHECKBOX,
+ UI_BTYPE_CHECKBOX_N,
+ UI_BTYPE_ROW);
}
/**
@@ -80,83 +76,88 @@ bool ui_but_is_toggle(const uiBut *but)
*/
bool ui_but_is_interactive(const uiBut *but, const bool labeledit)
{
- /* note, UI_BTYPE_LABEL is included for highlights, this allows drags */
- if ((but->type == UI_BTYPE_LABEL) && but->dragpoin == NULL) {
- return false;
- }
- if (ELEM(but->type, UI_BTYPE_ROUNDBOX, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_LISTBOX)) {
- return false;
- }
- if (but->flag & UI_HIDDEN) {
- return false;
- }
- if (but->flag & UI_SCROLLED) {
- return false;
- }
- if ((but->type == UI_BTYPE_TEXT) && (but->dt == UI_EMBOSS_NONE) && !labeledit) {
- return false;
- }
- if ((but->type == UI_BTYPE_LISTROW) && labeledit) {
- return false;
- }
-
- return true;
+ /* note, UI_BTYPE_LABEL is included for highlights, this allows drags */
+ if ((but->type == UI_BTYPE_LABEL) && but->dragpoin == NULL) {
+ return false;
+ }
+ if (ELEM(but->type, UI_BTYPE_ROUNDBOX, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_LISTBOX)) {
+ return false;
+ }
+ if (but->flag & UI_HIDDEN) {
+ return false;
+ }
+ if (but->flag & UI_SCROLLED) {
+ return false;
+ }
+ if ((but->type == UI_BTYPE_TEXT) && (but->dt == UI_EMBOSS_NONE) && !labeledit) {
+ return false;
+ }
+ if ((but->type == UI_BTYPE_LISTROW) && labeledit) {
+ return false;
+ }
+
+ return true;
}
/* file selectors are exempt from utf-8 checks */
bool ui_but_is_utf8(const uiBut *but)
{
- if (but->rnaprop) {
- const int subtype = RNA_property_subtype(but->rnaprop);
- return !(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME, PROP_BYTESTRING));
- }
- else {
- return !(but->flag & UI_BUT_NO_UTF8);
- }
+ if (but->rnaprop) {
+ const int subtype = RNA_property_subtype(but->rnaprop);
+ return !(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME, PROP_BYTESTRING));
+ }
+ else {
+ return !(but->flag & UI_BUT_NO_UTF8);
+ }
}
-
#ifdef USE_UI_POPOVER_ONCE
bool ui_but_is_popover_once_compat(const uiBut *but)
{
- return (
- (but->type == UI_BTYPE_BUT) ||
- ui_but_is_toggle(but)
- );
+ return ((but->type == UI_BTYPE_BUT) || ui_but_is_toggle(but));
}
#endif
bool ui_but_has_array_value(const uiBut *but)
{
- return (but->rnapoin.data && but->rnaprop &&
- ELEM(RNA_property_subtype(but->rnaprop), PROP_COLOR, PROP_TRANSLATION, PROP_DIRECTION,
- PROP_VELOCITY, PROP_ACCELERATION, PROP_MATRIX, PROP_EULER, PROP_QUATERNION, PROP_AXISANGLE,
- PROP_XYZ, PROP_XYZ_LENGTH, PROP_COLOR_GAMMA, PROP_COORDS));
+ return (but->rnapoin.data && but->rnaprop &&
+ ELEM(RNA_property_subtype(but->rnaprop),
+ PROP_COLOR,
+ PROP_TRANSLATION,
+ PROP_DIRECTION,
+ PROP_VELOCITY,
+ PROP_ACCELERATION,
+ PROP_MATRIX,
+ PROP_EULER,
+ PROP_QUATERNION,
+ PROP_AXISANGLE,
+ PROP_XYZ,
+ PROP_XYZ_LENGTH,
+ PROP_COLOR_GAMMA,
+ PROP_COORDS));
}
-
-
bool UI_but_is_tool(const uiBut *but)
{
- /* very evil! */
- if (but->optype != NULL) {
- static wmOperatorType *ot = NULL;
- if (ot == NULL) {
- ot = WM_operatortype_find("WM_OT_tool_set_by_id", false);
- }
- if (but->optype == ot) {
- return true;
- }
- }
- return false;
+ /* very evil! */
+ if (but->optype != NULL) {
+ static wmOperatorType *ot = NULL;
+ if (ot == NULL) {
+ ot = WM_operatortype_find("WM_OT_tool_set_by_id", false);
+ }
+ if (but->optype == ot) {
+ return true;
+ }
+ }
+ return false;
}
bool UI_but_has_tooltip_label(const uiBut *but)
{
- if ((but->drawstr[0] == '\0') && !ui_block_is_popover(but->block)) {
- return UI_but_is_tool(but);
- }
- return false;
+ if ((but->drawstr[0] == '\0') && !ui_block_is_popover(but->block)) {
+ return UI_but_is_tool(but);
+ }
+ return false;
}
/** \} */
@@ -167,242 +168,245 @@ bool UI_but_has_tooltip_label(const uiBut *but)
void ui_but_pie_dir(RadialDirection dir, float vec[2])
{
- float angle;
+ float angle;
- BLI_assert(dir != UI_RADIAL_NONE);
+ BLI_assert(dir != UI_RADIAL_NONE);
- angle = DEG2RADF((float)ui_radial_dir_to_angle[dir]);
- vec[0] = cosf(angle);
- vec[1] = sinf(angle);
+ angle = DEG2RADF((float)ui_radial_dir_to_angle[dir]);
+ vec[0] = cosf(angle);
+ vec[1] = sinf(angle);
}
static bool ui_but_isect_pie_seg(const uiBlock *block, const uiBut *but)
{
- const float angle_range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_4 : M_PI_4 / 2.0;
- float vec[2];
+ const float angle_range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_4 :
+ M_PI_4 / 2.0;
+ float vec[2];
- if (block->pie_data.flags & UI_PIE_INVALID_DIR) {
- return false;
- }
+ if (block->pie_data.flags & UI_PIE_INVALID_DIR) {
+ return false;
+ }
- ui_but_pie_dir(but->pie_dir, vec);
+ ui_but_pie_dir(but->pie_dir, vec);
- if (saacos(dot_v2v2(vec, block->pie_data.pie_dir)) < angle_range) {
- return true;
- }
+ if (saacos(dot_v2v2(vec, block->pie_data.pie_dir)) < angle_range) {
+ return true;
+ }
- return false;
+ return false;
}
bool ui_but_contains_pt(const uiBut *but, float mx, float my)
{
- return BLI_rctf_isect_pt(&but->rect, mx, my);
+ return BLI_rctf_isect_pt(&but->rect, mx, my);
}
bool ui_but_contains_point_px(const uiBut *but, const ARegion *ar, int x, int y)
{
- uiBlock *block = but->block;
- float mx, my;
- if (!ui_region_contains_point_px(ar, x, y)) {
- return false;
- }
+ uiBlock *block = but->block;
+ float mx, my;
+ if (!ui_region_contains_point_px(ar, x, y)) {
+ return false;
+ }
- mx = x;
- my = y;
+ mx = x;
+ my = y;
- ui_window_to_block_fl(ar, block, &mx, &my);
+ ui_window_to_block_fl(ar, block, &mx, &my);
- if (but->pie_dir != UI_RADIAL_NONE) {
- if (!ui_but_isect_pie_seg(block, but)) {
- return false;
- }
- }
- else if (!ui_but_contains_pt(but, mx, my)) {
- return false;
- }
+ if (but->pie_dir != UI_RADIAL_NONE) {
+ if (!ui_but_isect_pie_seg(block, but)) {
+ return false;
+ }
+ }
+ else if (!ui_but_contains_pt(but, mx, my)) {
+ return false;
+ }
- return true;
+ return true;
}
bool ui_but_contains_point_px_icon(const uiBut *but, ARegion *ar, const wmEvent *event)
{
- rcti rect;
- int x = event->x, y = event->y;
+ rcti rect;
+ int x = event->x, y = event->y;
- ui_window_to_block(ar, but->block, &x, &y);
+ ui_window_to_block(ar, but->block, &x, &y);
- BLI_rcti_rctf_copy(&rect, &but->rect);
+ BLI_rcti_rctf_copy(&rect, &but->rect);
- if (but->imb || but->type == UI_BTYPE_COLOR) {
- /* use button size itself */
- }
- else if (but->drawflag & UI_BUT_ICON_LEFT) {
- rect.xmax = rect.xmin + (BLI_rcti_size_y(&rect));
- }
- else {
- int delta = BLI_rcti_size_x(&rect) - BLI_rcti_size_y(&rect);
- rect.xmin += delta / 2;
- rect.xmax -= delta / 2;
- }
+ if (but->imb || but->type == UI_BTYPE_COLOR) {
+ /* use button size itself */
+ }
+ else if (but->drawflag & UI_BUT_ICON_LEFT) {
+ rect.xmax = rect.xmin + (BLI_rcti_size_y(&rect));
+ }
+ else {
+ int delta = BLI_rcti_size_x(&rect) - BLI_rcti_size_y(&rect);
+ rect.xmin += delta / 2;
+ rect.xmax -= delta / 2;
+ }
- return BLI_rcti_isect_pt(&rect, x, y);
+ return BLI_rcti_isect_pt(&rect, x, y);
}
/* 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)
{
- uiBlock *block;
- uiBut *but, *butover = NULL;
- float mx, my;
-
-// if (!win->active) {
-// return NULL;
-// }
- if (!ui_region_contains_point_px(ar, x, y)) {
- return NULL;
- }
-
- for (block = ar->uiblocks.first; block; block = block->next) {
- mx = x;
- my = y;
- ui_window_to_block_fl(ar, block, &mx, &my);
-
- for (but = block->buttons.last; but; but = but->prev) {
- if (ui_but_is_interactive(but, labeledit)) {
- if (but->pie_dir != UI_RADIAL_NONE) {
- if (ui_but_isect_pie_seg(block, but)) {
- butover = but;
- break;
- }
- }
- else if (ui_but_contains_pt(but, mx, my)) {
- butover = but;
- break;
- }
- }
- }
-
- /* CLIP_EVENTS prevents the event from reaching other blocks */
- if (block->flag & UI_BLOCK_CLIP_EVENTS) {
- /* check if mouse is inside block */
- if (BLI_rctf_isect_pt(&block->rect, mx, my)) {
- break;
- }
- }
- }
-
- return butover;
+ uiBlock *block;
+ uiBut *but, *butover = NULL;
+ float mx, my;
+
+ // if (!win->active) {
+ // return NULL;
+ // }
+ if (!ui_region_contains_point_px(ar, x, y)) {
+ return NULL;
+ }
+
+ for (block = ar->uiblocks.first; block; block = block->next) {
+ mx = x;
+ my = y;
+ ui_window_to_block_fl(ar, block, &mx, &my);
+
+ for (but = block->buttons.last; but; but = but->prev) {
+ if (ui_but_is_interactive(but, labeledit)) {
+ if (but->pie_dir != UI_RADIAL_NONE) {
+ if (ui_but_isect_pie_seg(block, but)) {
+ butover = but;
+ break;
+ }
+ }
+ else if (ui_but_contains_pt(but, mx, my)) {
+ butover = but;
+ break;
+ }
+ }
+ }
+
+ /* CLIP_EVENTS prevents the event from reaching other blocks */
+ if (block->flag & UI_BLOCK_CLIP_EVENTS) {
+ /* check if mouse is inside block */
+ if (BLI_rctf_isect_pt(&block->rect, mx, my)) {
+ break;
+ }
+ }
+ }
+
+ return butover;
}
uiBut *ui_but_find_mouse_over(ARegion *ar, 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(ar, event->x, event->y, event->ctrl != 0);
}
uiBut *ui_list_find_mouse_over_ex(ARegion *ar, int x, int y)
{
- uiBlock *block;
- uiBut *but;
- float mx, my;
+ uiBlock *block;
+ uiBut *but;
+ float mx, my;
- if (!ui_region_contains_point_px(ar, x, y)) {
- return NULL;
- }
+ if (!ui_region_contains_point_px(ar, x, y)) {
+ return NULL;
+ }
- for (block = ar->uiblocks.first; block; block = block->next) {
- mx = x;
- my = y;
- ui_window_to_block_fl(ar, block, &mx, &my);
+ for (block = ar->uiblocks.first; block; block = block->next) {
+ mx = x;
+ my = y;
+ ui_window_to_block_fl(ar, block, &mx, &my);
- for (but = block->buttons.last; but; but = but->prev) {
- if (but->type == UI_BTYPE_LISTBOX && ui_but_contains_pt(but, mx, my)) {
- return but;
- }
- }
- }
+ for (but = block->buttons.last; but; but = but->prev) {
+ if (but->type == UI_BTYPE_LISTBOX && ui_but_contains_pt(but, mx, my)) {
+ return but;
+ }
+ }
+ }
- return NULL;
+ return NULL;
}
uiBut *ui_list_find_mouse_over(ARegion *ar, const wmEvent *event)
{
- return ui_list_find_mouse_over_ex(ar, event->x, event->y);
+ return ui_list_find_mouse_over_ex(ar, event->x, event->y);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Button (#uiBut) Relations
* \{ */
uiBut *ui_but_prev(uiBut *but)
{
- while (but->prev) {
- but = but->prev;
- if (ui_but_is_editable(but)) {
- return but;
- }
- }
- return NULL;
+ while (but->prev) {
+ but = but->prev;
+ if (ui_but_is_editable(but)) {
+ return but;
+ }
+ }
+ return NULL;
}
uiBut *ui_but_next(uiBut *but)
{
- while (but->next) {
- but = but->next;
- if (ui_but_is_editable(but)) {
- return but;
- }
- }
- return NULL;
+ while (but->next) {
+ but = but->next;
+ if (ui_but_is_editable(but)) {
+ return but;
+ }
+ }
+ return NULL;
}
uiBut *ui_but_first(uiBlock *block)
{
- uiBut *but;
+ uiBut *but;
- but = block->buttons.first;
- while (but) {
- if (ui_but_is_editable(but)) {
- return but;
- }
- but = but->next;
- }
- return NULL;
+ but = block->buttons.first;
+ while (but) {
+ if (ui_but_is_editable(but)) {
+ return but;
+ }
+ but = but->next;
+ }
+ return NULL;
}
uiBut *ui_but_last(uiBlock *block)
{
- uiBut *but;
+ uiBut *but;
- but = block->buttons.last;
- while (but) {
- if (ui_but_is_editable(but)) {
- return but;
- }
- but = but->prev;
- }
- return NULL;
+ but = block->buttons.last;
+ while (but) {
+ if (ui_but_is_editable(but)) {
+ return but;
+ }
+ but = but->prev;
+ }
+ return NULL;
}
bool ui_but_is_cursor_warp(const uiBut *but)
{
- if (U.uiflag & USER_CONTINUOUS_MOUSE) {
- if (ELEM(but->type,
- UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, UI_BTYPE_HSVCIRCLE,
- UI_BTYPE_TRACK_PREVIEW, UI_BTYPE_HSVCUBE, UI_BTYPE_CURVE))
- {
- return true;
- }
- }
+ if (U.uiflag & USER_CONTINUOUS_MOUSE) {
+ if (ELEM(but->type,
+ UI_BTYPE_NUM,
+ UI_BTYPE_NUM_SLIDER,
+ UI_BTYPE_HSVCIRCLE,
+ UI_BTYPE_TRACK_PREVIEW,
+ UI_BTYPE_HSVCUBE,
+ UI_BTYPE_CURVE)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
bool ui_but_contains_password(const uiBut *but)
{
- return but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD);
+ return but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD);
}
/** \} */
@@ -413,38 +417,34 @@ bool ui_but_contains_password(const uiBut *but)
bool ui_block_is_menu(const uiBlock *block)
{
- return (((block->flag & UI_BLOCK_LOOP) != 0) &&
- /* non-menu popups use keep-open, so check this is off */
- ((block->flag & UI_BLOCK_KEEP_OPEN) == 0));
+ return (((block->flag & UI_BLOCK_LOOP) != 0) &&
+ /* non-menu popups use keep-open, so check this is off */
+ ((block->flag & UI_BLOCK_KEEP_OPEN) == 0));
}
bool ui_block_is_popover(const uiBlock *block)
{
- return (block->flag & UI_BLOCK_POPOVER) != 0;
+ return (block->flag & UI_BLOCK_POPOVER) != 0;
}
bool ui_block_is_pie_menu(const uiBlock *block)
{
- return ((block->flag & UI_BLOCK_RADIAL) != 0);
+ return ((block->flag & UI_BLOCK_RADIAL) != 0);
}
bool ui_block_is_popup_any(const uiBlock *block)
{
- return (
- ui_block_is_menu(block) ||
- ui_block_is_popover(block) ||
- ui_block_is_pie_menu(block)
- );
+ return (ui_block_is_menu(block) || ui_block_is_popover(block) || ui_block_is_pie_menu(block));
}
bool UI_block_is_empty(const uiBlock *block)
{
- for (const uiBut *but = block->buttons.first; but; but = but->next) {
- if (!ELEM(but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE)) {
- return false;
- }
- }
- return true;
+ for (const uiBut *but = block->buttons.first; but; but = but->next) {
+ if (!ELEM(but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE)) {
+ return false;
+ }
+ }
+ return true;
}
/** \} */
@@ -455,33 +455,31 @@ bool UI_block_is_empty(const uiBlock *block)
uiBut *ui_region_find_active_but(ARegion *ar)
{
- uiBlock *block;
- uiBut *but;
+ uiBlock *block;
+ uiBut *but;
- for (block = ar->uiblocks.first; block; block = block->next) {
- for (but = block->buttons.first; but; but = but->next) {
- if (but->active) {
- return but;
- }
- }
- }
+ for (block = ar->uiblocks.first; block; block = block->next) {
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->active) {
+ return but;
+ }
+ }
+ }
- return NULL;
+ return NULL;
}
uiBut *ui_region_find_first_but_test_flag(ARegion *ar, 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) {
- if (((but->flag & flag_include) == flag_include) &&
- ((but->flag & flag_exclude) == 0))
- {
- return but;
- }
- }
- }
+ for (uiBlock *block = ar->uiblocks.first; block; block = block->next) {
+ for (uiBut *but = block->buttons.first; but; but = but->next) {
+ if (((but->flag & flag_include) == flag_include) && ((but->flag & flag_exclude) == 0)) {
+ return but;
+ }
+ }
+ }
- return NULL;
+ return NULL;
}
/** \} */
@@ -492,41 +490,42 @@ uiBut *ui_region_find_first_but_test_flag(ARegion *ar, int flag_include, int fla
bool ui_region_contains_point_px(const ARegion *ar, int x, int y)
{
- rcti winrct;
-
- /* scale down area rect to exclude shadow */
- ui_region_winrct_get_no_margin(ar, &winrct);
-
- /* check if the mouse is in the region */
- if (!BLI_rcti_isect_pt(&winrct, x, y)) {
- for (uiBlock *block = ar->uiblocks.first; block; block = block->next) {
- block->auto_open = false;
- }
-
- return false;
- }
-
- /* also, check that with view2d, that the mouse is not over the scrollbars
- * NOTE: care is needed here, since the mask rect may include the scrollbars
- * 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;
- int mx, my;
-
- /* convert window coordinates to region coordinates */
- mx = x;
- my = y;
- ui_window_to_region(ar, &mx, &my);
-
- /* check if in the rect */
- if (!BLI_rcti_isect_pt(&v2d->mask, mx, my) || UI_view2d_mouse_in_scrollers(ar, &ar->v2d, x, y)) {
- return false;
- }
- }
-
- return true;
+ rcti winrct;
+
+ /* scale down area rect to exclude shadow */
+ ui_region_winrct_get_no_margin(ar, &winrct);
+
+ /* check if the mouse is in the region */
+ if (!BLI_rcti_isect_pt(&winrct, x, y)) {
+ for (uiBlock *block = ar->uiblocks.first; block; block = block->next) {
+ block->auto_open = false;
+ }
+
+ return false;
+ }
+
+ /* also, check that with view2d, that the mouse is not over the scrollbars
+ * NOTE: care is needed here, since the mask rect may include the scrollbars
+ * 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;
+ int mx, my;
+
+ /* convert window coordinates to region coordinates */
+ mx = x;
+ my = y;
+ ui_window_to_region(ar, &mx, &my);
+
+ /* check if in the rect */
+ if (!BLI_rcti_isect_pt(&v2d->mask, mx, my) ||
+ UI_view2d_mouse_in_scrollers(ar, &ar->v2d, x, y)) {
+ return false;
+ }
+ }
+
+ return true;
}
/** \} */
diff --git a/source/blender/editors/interface/interface_region_color_picker.c b/source/blender/editors/interface/interface_region_color_picker.c
index 52136cee9ea..7ffe572a848 100644
--- a/source/blender/editors/interface/interface_region_color_picker.c
+++ b/source/blender/editors/interface/interface_region_color_picker.c
@@ -54,9 +54,9 @@
#include "interface_intern.h"
enum ePickerType {
- PICKER_TYPE_RGB = 0,
- PICKER_TYPE_HSV = 1,
- PICKER_TYPE_HEX = 2,
+ PICKER_TYPE_RGB = 0,
+ PICKER_TYPE_HSV = 1,
+ PICKER_TYPE_HEX = 2,
};
/* -------------------------------------------------------------------- */
@@ -65,80 +65,80 @@ enum ePickerType {
void ui_rgb_to_color_picker_compat_v(const float rgb[3], float r_cp[3])
{
- switch (U.color_picker_type) {
- case USER_CP_CIRCLE_HSL:
- rgb_to_hsl_compat_v(rgb, r_cp);
- break;
- default:
- rgb_to_hsv_compat_v(rgb, r_cp);
- break;
- }
+ switch (U.color_picker_type) {
+ case USER_CP_CIRCLE_HSL:
+ rgb_to_hsl_compat_v(rgb, r_cp);
+ break;
+ default:
+ rgb_to_hsv_compat_v(rgb, r_cp);
+ break;
+ }
}
void ui_rgb_to_color_picker_v(const float rgb[3], float r_cp[3])
{
- switch (U.color_picker_type) {
- case USER_CP_CIRCLE_HSL:
- rgb_to_hsl_v(rgb, r_cp);
- break;
- default:
- rgb_to_hsv_v(rgb, r_cp);
- break;
- }
+ switch (U.color_picker_type) {
+ case USER_CP_CIRCLE_HSL:
+ rgb_to_hsl_v(rgb, r_cp);
+ break;
+ default:
+ rgb_to_hsv_v(rgb, r_cp);
+ break;
+ }
}
void ui_color_picker_to_rgb_v(const float r_cp[3], float rgb[3])
{
- switch (U.color_picker_type) {
- case USER_CP_CIRCLE_HSL:
- hsl_to_rgb_v(r_cp, rgb);
- break;
- default:
- hsv_to_rgb_v(r_cp, rgb);
- break;
- }
+ switch (U.color_picker_type) {
+ case USER_CP_CIRCLE_HSL:
+ hsl_to_rgb_v(r_cp, rgb);
+ break;
+ default:
+ hsv_to_rgb_v(r_cp, rgb);
+ break;
+ }
}
void ui_color_picker_to_rgb(float r_cp0, float r_cp1, float r_cp2, float *r, float *g, float *b)
{
- switch (U.color_picker_type) {
- case USER_CP_CIRCLE_HSL:
- hsl_to_rgb(r_cp0, r_cp1, r_cp2, r, g, b);
- break;
- default:
- hsv_to_rgb(r_cp0, r_cp1, r_cp2, r, g, b);
- break;
- }
+ switch (U.color_picker_type) {
+ case USER_CP_CIRCLE_HSL:
+ hsl_to_rgb(r_cp0, r_cp1, r_cp2, r, g, b);
+ break;
+ default:
+ hsv_to_rgb(r_cp0, r_cp1, r_cp2, r, g, b);
+ break;
+ }
}
/* Returns true if the button is for a color with gamma baked in,
* or if it's a color picker for such a button. */
bool ui_but_is_color_gamma(uiBut *but)
{
- if (but->rnaprop) {
- if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
- return true;
- }
- }
+ if (but->rnaprop) {
+ if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
+ return true;
+ }
+ }
- return but->block->is_color_gamma_picker;
+ return but->block->is_color_gamma_picker;
}
void ui_scene_linear_to_color_picker_space(uiBut *but, float rgb[3])
{
- /* Map to color picking space for HSV values and HSV cube/circle,
- * assuming it is more perceptually linear then the scene linear
- * space for intuitive color picking. */
- if (!ui_but_is_color_gamma(but)) {
- IMB_colormanagement_scene_linear_to_color_picking_v3(rgb);
- }
+ /* Map to color picking space for HSV values and HSV cube/circle,
+ * assuming it is more perceptually linear then the scene linear
+ * space for intuitive color picking. */
+ if (!ui_but_is_color_gamma(but)) {
+ IMB_colormanagement_scene_linear_to_color_picking_v3(rgb);
+ }
}
void ui_color_picker_to_scene_linear_space(uiBut *but, float rgb[3])
{
- if (!ui_but_is_color_gamma(but)) {
- IMB_colormanagement_color_picking_to_scene_linear_v3(rgb);
- }
+ if (!ui_but_is_color_gamma(but)) {
+ IMB_colormanagement_color_picking_to_scene_linear_v3(rgb);
+ }
}
/** \} */
@@ -150,536 +150,759 @@ void ui_color_picker_to_scene_linear_space(uiBut *but, float rgb[3])
/* for picker, while editing hsv */
void ui_but_hsv_set(uiBut *but)
{
- float col[3];
- ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
+ float col[3];
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
- ui_color_picker_to_rgb_v(hsv, col);
+ ui_color_picker_to_rgb_v(hsv, col);
- ui_but_v3_set(but, col);
+ ui_but_v3_set(but, col);
}
/* Updates all buttons who share the same color picker as the one passed
* also used by small picker, be careful with name checks below... */
-static void ui_update_color_picker_buts_rgb(
- uiBut *from_but, uiBlock *block, ColorPicker *cpicker, const float rgb[3])
+static void ui_update_color_picker_buts_rgb(uiBut *from_but,
+ uiBlock *block,
+ ColorPicker *cpicker,
+ const float rgb[3])
{
- uiBut *bt;
- float *hsv = cpicker->color_data;
-
- /* Convert from RGB to HSV in perceptually linear space. */
- float tmp[3];
- copy_v3_v3(tmp, rgb);
- if (from_but) {
- ui_scene_linear_to_color_picker_space(from_but, tmp);
- }
- ui_rgb_to_color_picker_compat_v(tmp, hsv);
-
- /* this updates button strings,
- * is hackish... but button pointers are on stack of caller function */
- for (bt = block->buttons.first; bt; bt = bt->next) {
- if (bt->custom_data != cpicker) {
- continue;
- }
-
- if (bt->rnaprop) {
- ui_but_v3_set(bt, rgb);
-
- /* original button that created the color picker already does undo
- * push, so disable it on RNA buttons in the color picker block */
- UI_but_flag_disable(bt, UI_BUT_UNDO);
- }
- else if (STREQ(bt->str, "Hex: ")) {
- float rgb_hex[3];
- uchar rgb_hex_uchar[3];
- double intpart;
- char col[16];
-
- /* Hex code is assumed to be in sRGB space
- * (coming from other applications, web, etc) */
- copy_v3_v3(rgb_hex, rgb);
- if (from_but && !ui_but_is_color_gamma(from_but)) {
- IMB_colormanagement_scene_linear_to_srgb_v3(rgb_hex);
- }
-
- if (rgb_hex[0] > 1.0f) {
- rgb_hex[0] = modf(rgb_hex[0], &intpart);
- }
- if (rgb_hex[1] > 1.0f) {
- rgb_hex[1] = modf(rgb_hex[1], &intpart);
- }
- if (rgb_hex[2] > 1.0f) {
- rgb_hex[2] = modf(rgb_hex[2], &intpart);
- }
-
- rgb_float_to_uchar(rgb_hex_uchar, rgb_hex);
- BLI_snprintf(col, sizeof(col), "%02X%02X%02X", UNPACK3_EX((uint), rgb_hex_uchar, ));
-
- strcpy(bt->poin, col);
- }
- else if (bt->str[1] == ' ') {
- if (bt->str[0] == 'R') {
- ui_but_value_set(bt, rgb[0]);
- }
- else if (bt->str[0] == 'G') {
- ui_but_value_set(bt, rgb[1]);
- }
- else if (bt->str[0] == 'B') {
- ui_but_value_set(bt, rgb[2]);
- }
- else if (bt->str[0] == 'H') {
- ui_but_value_set(bt, hsv[0]);
- }
- else if (bt->str[0] == 'S') {
- ui_but_value_set(bt, hsv[1]);
- }
- else if (bt->str[0] == 'V') {
- ui_but_value_set(bt, hsv[2]);
- }
- else if (bt->str[0] == 'L') {
- ui_but_value_set(bt, hsv[2]);
- }
- }
-
- ui_but_update(bt);
- }
+ uiBut *bt;
+ float *hsv = cpicker->color_data;
+
+ /* Convert from RGB to HSV in perceptually linear space. */
+ float tmp[3];
+ copy_v3_v3(tmp, rgb);
+ if (from_but) {
+ ui_scene_linear_to_color_picker_space(from_but, tmp);
+ }
+ ui_rgb_to_color_picker_compat_v(tmp, hsv);
+
+ /* this updates button strings,
+ * is hackish... but button pointers are on stack of caller function */
+ for (bt = block->buttons.first; bt; bt = bt->next) {
+ if (bt->custom_data != cpicker) {
+ continue;
+ }
+
+ if (bt->rnaprop) {
+ ui_but_v3_set(bt, rgb);
+
+ /* original button that created the color picker already does undo
+ * push, so disable it on RNA buttons in the color picker block */
+ UI_but_flag_disable(bt, UI_BUT_UNDO);
+ }
+ else if (STREQ(bt->str, "Hex: ")) {
+ float rgb_hex[3];
+ uchar rgb_hex_uchar[3];
+ double intpart;
+ char col[16];
+
+ /* Hex code is assumed to be in sRGB space
+ * (coming from other applications, web, etc) */
+ copy_v3_v3(rgb_hex, rgb);
+ if (from_but && !ui_but_is_color_gamma(from_but)) {
+ IMB_colormanagement_scene_linear_to_srgb_v3(rgb_hex);
+ }
+
+ if (rgb_hex[0] > 1.0f) {
+ rgb_hex[0] = modf(rgb_hex[0], &intpart);
+ }
+ if (rgb_hex[1] > 1.0f) {
+ rgb_hex[1] = modf(rgb_hex[1], &intpart);
+ }
+ if (rgb_hex[2] > 1.0f) {
+ rgb_hex[2] = modf(rgb_hex[2], &intpart);
+ }
+
+ rgb_float_to_uchar(rgb_hex_uchar, rgb_hex);
+ BLI_snprintf(col, sizeof(col), "%02X%02X%02X", UNPACK3_EX((uint), rgb_hex_uchar, ));
+
+ strcpy(bt->poin, col);
+ }
+ else if (bt->str[1] == ' ') {
+ if (bt->str[0] == 'R') {
+ ui_but_value_set(bt, rgb[0]);
+ }
+ else if (bt->str[0] == 'G') {
+ ui_but_value_set(bt, rgb[1]);
+ }
+ else if (bt->str[0] == 'B') {
+ ui_but_value_set(bt, rgb[2]);
+ }
+ else if (bt->str[0] == 'H') {
+ ui_but_value_set(bt, hsv[0]);
+ }
+ else if (bt->str[0] == 'S') {
+ ui_but_value_set(bt, hsv[1]);
+ }
+ else if (bt->str[0] == 'V') {
+ ui_but_value_set(bt, hsv[2]);
+ }
+ else if (bt->str[0] == 'L') {
+ ui_but_value_set(bt, hsv[2]);
+ }
+ }
+
+ ui_but_update(bt);
+ }
}
static void ui_colorpicker_rna_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
{
- uiBut *but = (uiBut *)bt1;
- uiPopupBlockHandle *popup = but->block->handle;
- PropertyRNA *prop = but->rnaprop;
- PointerRNA ptr = but->rnapoin;
- float rgb[4];
-
- if (prop) {
- RNA_property_float_get_array(&ptr, prop, rgb);
- ui_update_color_picker_buts_rgb(
- but, but->block, but->custom_data, rgb);
- }
-
- if (popup) {
- popup->menuretval = UI_RETURN_UPDATE;
- }
+ uiBut *but = (uiBut *)bt1;
+ uiPopupBlockHandle *popup = but->block->handle;
+ PropertyRNA *prop = but->rnaprop;
+ PointerRNA ptr = but->rnapoin;
+ float rgb[4];
+
+ if (prop) {
+ RNA_property_float_get_array(&ptr, prop, rgb);
+ ui_update_color_picker_buts_rgb(but, but->block, but->custom_data, rgb);
+ }
+
+ if (popup) {
+ popup->menuretval = UI_RETURN_UPDATE;
+ }
}
static void ui_color_wheel_rna_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
{
- uiBut *but = (uiBut *)bt1;
- uiPopupBlockHandle *popup = but->block->handle;
- float rgb[3];
- ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
+ uiBut *but = (uiBut *)bt1;
+ uiPopupBlockHandle *popup = but->block->handle;
+ float rgb[3];
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
- ui_color_picker_to_rgb_v(hsv, rgb);
+ ui_color_picker_to_rgb_v(hsv, rgb);
- /* hsv is saved in perceptually linear space so convert back */
- ui_color_picker_to_scene_linear_space(but, rgb);
+ /* hsv is saved in perceptually linear space so convert back */
+ ui_color_picker_to_scene_linear_space(but, rgb);
- ui_update_color_picker_buts_rgb(but, but->block, cpicker, rgb);
+ ui_update_color_picker_buts_rgb(but, but->block, cpicker, rgb);
- if (popup) {
- popup->menuretval = UI_RETURN_UPDATE;
- }
+ if (popup) {
+ popup->menuretval = UI_RETURN_UPDATE;
+ }
}
static void ui_colorpicker_hex_rna_cb(bContext *UNUSED(C), void *bt1, void *hexcl)
{
- uiBut *but = (uiBut *)bt1;
- uiPopupBlockHandle *popup = but->block->handle;
- ColorPicker *cpicker = but->custom_data;
- char *hexcol = (char *)hexcl;
- float rgb[3];
+ uiBut *but = (uiBut *)bt1;
+ uiPopupBlockHandle *popup = but->block->handle;
+ ColorPicker *cpicker = but->custom_data;
+ char *hexcol = (char *)hexcl;
+ float rgb[3];
- hex_to_rgb(hexcol, rgb, rgb + 1, rgb + 2);
+ hex_to_rgb(hexcol, rgb, rgb + 1, rgb + 2);
- /* Hex code is assumed to be in sRGB space (coming from other applications, web, etc) */
- if (!ui_but_is_color_gamma(but)) {
- IMB_colormanagement_srgb_to_scene_linear_v3(rgb);
- }
+ /* Hex code is assumed to be in sRGB space (coming from other applications, web, etc) */
+ if (!ui_but_is_color_gamma(but)) {
+ IMB_colormanagement_srgb_to_scene_linear_v3(rgb);
+ }
- ui_update_color_picker_buts_rgb(but, but->block, cpicker, rgb);
+ ui_update_color_picker_buts_rgb(but, but->block, cpicker, rgb);
- if (popup) {
- popup->menuretval = UI_RETURN_UPDATE;
- }
+ if (popup) {
+ popup->menuretval = UI_RETURN_UPDATE;
+ }
}
static void ui_popup_close_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
{
- uiBut *but = (uiBut *)bt1;
- uiPopupBlockHandle *popup = but->block->handle;
-
- if (popup) {
- ColorPicker *cpicker = but->custom_data;
- BLI_assert(cpicker->is_init);
- popup->menuretval = (
- equals_v3v3(cpicker->color_data, cpicker->color_data_init) ?
- UI_RETURN_CANCEL : UI_RETURN_OK);
- }
+ uiBut *but = (uiBut *)bt1;
+ uiPopupBlockHandle *popup = but->block->handle;
+
+ if (popup) {
+ ColorPicker *cpicker = but->custom_data;
+ BLI_assert(cpicker->is_init);
+ popup->menuretval = (equals_v3v3(cpicker->color_data, cpicker->color_data_init) ?
+ UI_RETURN_CANCEL :
+ UI_RETURN_OK);
+ }
}
static void ui_colorpicker_hide_reveal(uiBlock *block, enum ePickerType colormode)
{
- /* tag buttons */
- for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
- 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) */
- SET_FLAG_FROM_TEST(bt->flag, (colormode != PICKER_TYPE_RGB), UI_HIDDEN);
- }
- else if (bt->func == ui_color_wheel_rna_cb) {
- /* HSV sliders */
- SET_FLAG_FROM_TEST(bt->flag, (colormode != PICKER_TYPE_HSV), UI_HIDDEN);
- }
- else if (bt->func == ui_colorpicker_hex_rna_cb || bt->type == UI_BTYPE_LABEL) {
- /* HEX input or gamma correction status label */
- SET_FLAG_FROM_TEST(bt->flag, (colormode != PICKER_TYPE_HEX), UI_HIDDEN);
- }
- }
+ /* tag buttons */
+ for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
+ 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) */
+ SET_FLAG_FROM_TEST(bt->flag, (colormode != PICKER_TYPE_RGB), UI_HIDDEN);
+ }
+ else if (bt->func == ui_color_wheel_rna_cb) {
+ /* HSV sliders */
+ SET_FLAG_FROM_TEST(bt->flag, (colormode != PICKER_TYPE_HSV), UI_HIDDEN);
+ }
+ else if (bt->func == ui_colorpicker_hex_rna_cb || bt->type == UI_BTYPE_LABEL) {
+ /* HEX input or gamma correction status label */
+ SET_FLAG_FROM_TEST(bt->flag, (colormode != PICKER_TYPE_HEX), UI_HIDDEN);
+ }
+ }
}
static void ui_colorpicker_create_mode_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
{
- uiBut *bt = bt1;
- short colormode = ui_but_value_get(bt);
- ui_colorpicker_hide_reveal(bt->block, colormode);
+ uiBut *bt = bt1;
+ short colormode = ui_but_value_get(bt);
+ ui_colorpicker_hide_reveal(bt->block, colormode);
}
-#define PICKER_H (7.5f * U.widget_unit)
-#define PICKER_W (7.5f * U.widget_unit)
-#define PICKER_SPACE (0.3f * U.widget_unit)
-#define PICKER_BAR (0.7f * U.widget_unit)
+#define PICKER_H (7.5f * U.widget_unit)
+#define PICKER_W (7.5f * U.widget_unit)
+#define PICKER_SPACE (0.3f * U.widget_unit)
+#define PICKER_BAR (0.7f * U.widget_unit)
-#define PICKER_TOTAL_W (PICKER_W + PICKER_SPACE + PICKER_BAR)
+#define PICKER_TOTAL_W (PICKER_W + PICKER_SPACE + PICKER_BAR)
-static void ui_colorpicker_circle(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, ColorPicker *cpicker)
+static void ui_colorpicker_circle(uiBlock *block,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ ColorPicker *cpicker)
{
- uiBut *bt;
-
- /* HS circle */
- bt = uiDefButR_prop(
- block, UI_BTYPE_HSVCIRCLE, 0, "", 0, 0, PICKER_H, PICKER_W,
- ptr, prop, -1, 0.0, 0.0, 0.0, 0, TIP_("Color"));
- UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
- bt->custom_data = cpicker;
-
- /* value */
- if (U.color_picker_type == USER_CP_CIRCLE_HSL) {
- bt = uiDefButR_prop(
- block, UI_BTYPE_HSVCUBE, 0, "", PICKER_W + PICKER_SPACE, 0, PICKER_BAR, PICKER_H,
- ptr, prop, -1, 0.0, 0.0, UI_GRAD_L_ALT, 0, "Lightness");
- UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
- }
- else {
- bt = uiDefButR_prop(
- block, UI_BTYPE_HSVCUBE, 0, "", PICKER_W + PICKER_SPACE, 0, PICKER_BAR, PICKER_H,
- ptr, prop, -1, 0.0, 0.0, UI_GRAD_V_ALT, 0, TIP_("Value"));
- UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
- }
- bt->custom_data = cpicker;
+ uiBut *bt;
+
+ /* HS circle */
+ bt = uiDefButR_prop(block,
+ UI_BTYPE_HSVCIRCLE,
+ 0,
+ "",
+ 0,
+ 0,
+ PICKER_H,
+ PICKER_W,
+ ptr,
+ prop,
+ -1,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0,
+ TIP_("Color"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
+
+ /* value */
+ if (U.color_picker_type == USER_CP_CIRCLE_HSL) {
+ bt = uiDefButR_prop(block,
+ UI_BTYPE_HSVCUBE,
+ 0,
+ "",
+ PICKER_W + PICKER_SPACE,
+ 0,
+ PICKER_BAR,
+ PICKER_H,
+ ptr,
+ prop,
+ -1,
+ 0.0,
+ 0.0,
+ UI_GRAD_L_ALT,
+ 0,
+ "Lightness");
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ }
+ else {
+ bt = uiDefButR_prop(block,
+ UI_BTYPE_HSVCUBE,
+ 0,
+ "",
+ PICKER_W + PICKER_SPACE,
+ 0,
+ PICKER_BAR,
+ PICKER_H,
+ ptr,
+ prop,
+ -1,
+ 0.0,
+ 0.0,
+ UI_GRAD_V_ALT,
+ 0,
+ TIP_("Value"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ }
+ bt->custom_data = cpicker;
}
-
-static void ui_colorpicker_square(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int type, ColorPicker *cpicker)
+static void ui_colorpicker_square(
+ uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int type, ColorPicker *cpicker)
{
- uiBut *bt;
- int bartype = type + 3;
-
- /* HS square */
- bt = uiDefButR_prop(
- block, UI_BTYPE_HSVCUBE, 0, "", 0, PICKER_BAR + PICKER_SPACE, PICKER_TOTAL_W, PICKER_H,
- ptr, prop, -1, 0.0, 0.0, type, 0, TIP_("Color"));
- UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
- bt->custom_data = cpicker;
-
- /* value */
- bt = uiDefButR_prop(
- block, UI_BTYPE_HSVCUBE, 0, "", 0, 0, PICKER_TOTAL_W, PICKER_BAR,
- ptr, prop, -1, 0.0, 0.0, bartype, 0, TIP_("Value"));
- UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
- bt->custom_data = cpicker;
+ uiBut *bt;
+ int bartype = type + 3;
+
+ /* HS square */
+ bt = uiDefButR_prop(block,
+ UI_BTYPE_HSVCUBE,
+ 0,
+ "",
+ 0,
+ PICKER_BAR + PICKER_SPACE,
+ PICKER_TOTAL_W,
+ PICKER_H,
+ ptr,
+ prop,
+ -1,
+ 0.0,
+ 0.0,
+ type,
+ 0,
+ TIP_("Color"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
+
+ /* value */
+ bt = uiDefButR_prop(block,
+ UI_BTYPE_HSVCUBE,
+ 0,
+ "",
+ 0,
+ 0,
+ PICKER_TOTAL_W,
+ PICKER_BAR,
+ ptr,
+ prop,
+ -1,
+ 0.0,
+ 0.0,
+ bartype,
+ 0,
+ TIP_("Value"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
}
/* a HS circle, V slider, rgb/hsv/hex sliders */
-static void ui_block_colorpicker(
- uiBlock *block, uiBut *from_but, float rgba[4], bool show_picker)
+static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], bool show_picker)
{
- /* ePickerType */
- static char colormode = 1;
- uiBut *bt;
- int width, butwidth;
- static char hexcol[128];
- float softmin, softmax, hardmin, hardmax, step, precision;
- int yco;
- ColorPicker *cpicker = ui_block_colorpicker_create(block);
- float *hsv = cpicker->color_data;
- PointerRNA *ptr = &from_but->rnapoin;
- PropertyRNA *prop = from_but->rnaprop;
-
- width = PICKER_TOTAL_W;
- butwidth = width - 1.5f * UI_UNIT_X;
-
- /* sneaky way to check for alpha */
- rgba[3] = FLT_MAX;
-
- RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
- RNA_property_float_range(ptr, prop, &hardmin, &hardmax);
- RNA_property_float_get_array(ptr, prop, rgba);
-
- float rgb_perceptual[3];
- copy_v3_v3(rgb_perceptual, rgba);
- ui_scene_linear_to_color_picker_space(from_but, rgb_perceptual);
- ui_rgb_to_color_picker_v(rgb_perceptual, hsv);
- if (cpicker->is_init == false) {
- copy_v3_v3(cpicker->color_data_init, cpicker->color_data);
- cpicker->is_init = true;
- }
-
- /* when the softmax isn't defined in the RNA,
- * using very large numbers causes sRGB/linear round trip to fail. */
- if (softmax == FLT_MAX) {
- softmax = 1.0f;
- }
-
- switch (U.color_picker_type) {
- case USER_CP_SQUARE_SV:
- ui_colorpicker_square(block, ptr, prop, UI_GRAD_SV, cpicker);
- break;
- case USER_CP_SQUARE_HS:
- ui_colorpicker_square(block, ptr, prop, UI_GRAD_HS, cpicker);
- break;
- case USER_CP_SQUARE_HV:
- ui_colorpicker_square(block, ptr, prop, UI_GRAD_HV, cpicker);
- break;
-
- /* user default */
- case USER_CP_CIRCLE_HSV:
- case USER_CP_CIRCLE_HSL:
- default:
- ui_colorpicker_circle(block, ptr, prop, cpicker);
- break;
- }
-
- /* mode */
- yco = -1.5f * UI_UNIT_Y;
- UI_block_align_begin(block);
- bt = uiDefButC(
- block, UI_BTYPE_ROW, 0, IFACE_("RGB"), 0, yco, width / 3, UI_UNIT_Y,
- &colormode, 0.0, (float)PICKER_TYPE_RGB, 0, 0, "");
- UI_but_flag_disable(bt, UI_BUT_UNDO);
- UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, NULL);
- bt->custom_data = cpicker;
- bt = uiDefButC(
- block, UI_BTYPE_ROW, 0,
- IFACE_((U.color_picker_type == USER_CP_CIRCLE_HSL) ? "HSL" : "HSV"),
- width / 3, yco, width / 3, UI_UNIT_Y,
- &colormode, 0.0, PICKER_TYPE_HSV, 0, 0, "");
- UI_but_flag_disable(bt, UI_BUT_UNDO);
- UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, NULL);
- bt->custom_data = cpicker;
- bt = uiDefButC(
- block, UI_BTYPE_ROW, 0, IFACE_("Hex"), 2 * width / 3, yco, width / 3, UI_UNIT_Y,
- &colormode, 0.0, PICKER_TYPE_HEX, 0, 0, "");
- UI_but_flag_disable(bt, UI_BUT_UNDO);
- UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, NULL);
- bt->custom_data = cpicker;
- UI_block_align_end(block);
-
- yco = -3.0f * UI_UNIT_Y;
- if (show_picker) {
- bt = uiDefIconButO(
- block, UI_BTYPE_BUT, "UI_OT_eyedropper_color", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER,
- butwidth + 10, yco, UI_UNIT_X, UI_UNIT_Y, NULL);
- UI_but_flag_disable(bt, UI_BUT_UNDO);
- UI_but_drawflag_disable(bt, UI_BUT_ICON_LEFT);
- UI_but_func_set(bt, ui_popup_close_cb, bt, NULL);
- bt->custom_data = cpicker;
- }
-
- /* Note: don't disable UI_BUT_UNDO for RGBA values, since these don't add undo steps. */
-
- /* RGB values */
- UI_block_align_begin(block);
- bt = uiDefButR_prop(
- block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("R:"), 0, yco, butwidth, UI_UNIT_Y,
- ptr, prop, 0, 0.0, 0.0, 0, 3, TIP_("Red"));
- UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
- bt->custom_data = cpicker;
- bt = uiDefButR_prop(
- block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("G:"), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y,
- ptr, prop, 1, 0.0, 0.0, 0, 3, TIP_("Green"));
- UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
- bt->custom_data = cpicker;
- bt = uiDefButR_prop(
- block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("B:"), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y,
- ptr, prop, 2, 0.0, 0.0, 0, 3, TIP_("Blue"));
- UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
- bt->custom_data = cpicker;
-
- /* could use uiItemFullR(col, ptr, prop, -1, 0, UI_ITEM_R_EXPAND|UI_ITEM_R_SLIDER, "", ICON_NONE);
- * but need to use UI_but_func_set for updating other fake buttons */
-
- /* HSV values */
- yco = -3.0f * UI_UNIT_Y;
- UI_block_align_begin(block);
- bt = uiDefButF(
- block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("H:"), 0, yco, butwidth,
- UI_UNIT_Y, hsv, 0.0, 1.0, 10, 3, TIP_("Hue"));
- UI_but_flag_disable(bt, UI_BUT_UNDO);
- UI_but_func_set(bt, ui_color_wheel_rna_cb, bt, hsv);
- bt->custom_data = cpicker;
- bt = uiDefButF(
- block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("S:"), 0, yco -= UI_UNIT_Y,
- butwidth, UI_UNIT_Y, hsv + 1, 0.0, 1.0, 10, 3, TIP_("Saturation"));
- UI_but_flag_disable(bt, UI_BUT_UNDO);
- UI_but_func_set(bt, ui_color_wheel_rna_cb, bt, hsv);
- bt->custom_data = cpicker;
- if (U.color_picker_type == USER_CP_CIRCLE_HSL) {
- bt = uiDefButF(
- block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("L:"), 0, yco -= UI_UNIT_Y,
- butwidth, UI_UNIT_Y, hsv + 2, 0.0, 1.0, 10, 3, TIP_("Lightness"));
- }
- else {
- bt = uiDefButF(
- block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("V:"), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y,
- hsv + 2, 0.0, softmax, 10, 3, TIP_("Value"));
- }
- UI_but_flag_disable(bt, UI_BUT_UNDO);
-
- bt->hardmax = hardmax; /* not common but rgb may be over 1.0 */
- UI_but_func_set(bt, ui_color_wheel_rna_cb, bt, hsv);
- bt->custom_data = cpicker;
-
- UI_block_align_end(block);
-
- if (rgba[3] != FLT_MAX) {
- bt = uiDefButR_prop(
- block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("A: "), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y,
- ptr, prop, 3, 0.0, 0.0, 0, 3, TIP_("Alpha"));
- UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
- bt->custom_data = cpicker;
- }
- else {
- rgba[3] = 1.0f;
- }
-
- /* Hex color is in sRGB space. */
- float rgb_hex[3];
- uchar rgb_hex_uchar[3];
-
- copy_v3_v3(rgb_hex, rgba);
-
- if (!ui_but_is_color_gamma(from_but)) {
- IMB_colormanagement_scene_linear_to_srgb_v3(rgb_hex);
- }
-
- rgb_float_to_uchar(rgb_hex_uchar, rgb_hex);
- BLI_snprintf(hexcol, sizeof(hexcol), "%02X%02X%02X", UNPACK3_EX((uint), rgb_hex_uchar, ));
-
- yco = -3.0f * UI_UNIT_Y;
- bt = uiDefBut(
- block, UI_BTYPE_TEXT, 0, IFACE_("Hex: "), 0, yco, butwidth, UI_UNIT_Y,
- hexcol, 0, 8, 0, 0, TIP_("Hex triplet for color (#RRGGBB)"));
- UI_but_flag_disable(bt, UI_BUT_UNDO);
- UI_but_func_set(bt, ui_colorpicker_hex_rna_cb, bt, hexcol);
- bt->custom_data = cpicker;
- uiDefBut(
- block, UI_BTYPE_LABEL, 0, IFACE_("(Gamma Corrected)"), 0, yco - UI_UNIT_Y,
- butwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
-
- ui_colorpicker_hide_reveal(block, colormode);
+ /* ePickerType */
+ static char colormode = 1;
+ uiBut *bt;
+ int width, butwidth;
+ static char hexcol[128];
+ float softmin, softmax, hardmin, hardmax, step, precision;
+ int yco;
+ ColorPicker *cpicker = ui_block_colorpicker_create(block);
+ float *hsv = cpicker->color_data;
+ PointerRNA *ptr = &from_but->rnapoin;
+ PropertyRNA *prop = from_but->rnaprop;
+
+ width = PICKER_TOTAL_W;
+ butwidth = width - 1.5f * UI_UNIT_X;
+
+ /* sneaky way to check for alpha */
+ rgba[3] = FLT_MAX;
+
+ RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
+ RNA_property_float_range(ptr, prop, &hardmin, &hardmax);
+ RNA_property_float_get_array(ptr, prop, rgba);
+
+ float rgb_perceptual[3];
+ copy_v3_v3(rgb_perceptual, rgba);
+ ui_scene_linear_to_color_picker_space(from_but, rgb_perceptual);
+ ui_rgb_to_color_picker_v(rgb_perceptual, hsv);
+ if (cpicker->is_init == false) {
+ copy_v3_v3(cpicker->color_data_init, cpicker->color_data);
+ cpicker->is_init = true;
+ }
+
+ /* when the softmax isn't defined in the RNA,
+ * using very large numbers causes sRGB/linear round trip to fail. */
+ if (softmax == FLT_MAX) {
+ softmax = 1.0f;
+ }
+
+ switch (U.color_picker_type) {
+ case USER_CP_SQUARE_SV:
+ ui_colorpicker_square(block, ptr, prop, UI_GRAD_SV, cpicker);
+ break;
+ case USER_CP_SQUARE_HS:
+ ui_colorpicker_square(block, ptr, prop, UI_GRAD_HS, cpicker);
+ break;
+ case USER_CP_SQUARE_HV:
+ ui_colorpicker_square(block, ptr, prop, UI_GRAD_HV, cpicker);
+ break;
+
+ /* user default */
+ case USER_CP_CIRCLE_HSV:
+ case USER_CP_CIRCLE_HSL:
+ default:
+ ui_colorpicker_circle(block, ptr, prop, cpicker);
+ break;
+ }
+
+ /* mode */
+ yco = -1.5f * UI_UNIT_Y;
+ UI_block_align_begin(block);
+ bt = uiDefButC(block,
+ UI_BTYPE_ROW,
+ 0,
+ IFACE_("RGB"),
+ 0,
+ yco,
+ width / 3,
+ UI_UNIT_Y,
+ &colormode,
+ 0.0,
+ (float)PICKER_TYPE_RGB,
+ 0,
+ 0,
+ "");
+ UI_but_flag_disable(bt, UI_BUT_UNDO);
+ UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, NULL);
+ bt->custom_data = cpicker;
+ bt = uiDefButC(block,
+ UI_BTYPE_ROW,
+ 0,
+ IFACE_((U.color_picker_type == USER_CP_CIRCLE_HSL) ? "HSL" : "HSV"),
+ width / 3,
+ yco,
+ width / 3,
+ UI_UNIT_Y,
+ &colormode,
+ 0.0,
+ PICKER_TYPE_HSV,
+ 0,
+ 0,
+ "");
+ UI_but_flag_disable(bt, UI_BUT_UNDO);
+ UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, NULL);
+ bt->custom_data = cpicker;
+ bt = uiDefButC(block,
+ UI_BTYPE_ROW,
+ 0,
+ IFACE_("Hex"),
+ 2 * width / 3,
+ yco,
+ width / 3,
+ UI_UNIT_Y,
+ &colormode,
+ 0.0,
+ PICKER_TYPE_HEX,
+ 0,
+ 0,
+ "");
+ UI_but_flag_disable(bt, UI_BUT_UNDO);
+ UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, NULL);
+ bt->custom_data = cpicker;
+ UI_block_align_end(block);
+
+ yco = -3.0f * UI_UNIT_Y;
+ if (show_picker) {
+ bt = uiDefIconButO(block,
+ UI_BTYPE_BUT,
+ "UI_OT_eyedropper_color",
+ WM_OP_INVOKE_DEFAULT,
+ ICON_EYEDROPPER,
+ butwidth + 10,
+ yco,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL);
+ UI_but_flag_disable(bt, UI_BUT_UNDO);
+ UI_but_drawflag_disable(bt, UI_BUT_ICON_LEFT);
+ UI_but_func_set(bt, ui_popup_close_cb, bt, NULL);
+ bt->custom_data = cpicker;
+ }
+
+ /* Note: don't disable UI_BUT_UNDO for RGBA values, since these don't add undo steps. */
+
+ /* RGB values */
+ UI_block_align_begin(block);
+ bt = uiDefButR_prop(block,
+ UI_BTYPE_NUM_SLIDER,
+ 0,
+ IFACE_("R:"),
+ 0,
+ yco,
+ butwidth,
+ UI_UNIT_Y,
+ ptr,
+ prop,
+ 0,
+ 0.0,
+ 0.0,
+ 0,
+ 3,
+ TIP_("Red"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
+ bt = uiDefButR_prop(block,
+ UI_BTYPE_NUM_SLIDER,
+ 0,
+ IFACE_("G:"),
+ 0,
+ yco -= UI_UNIT_Y,
+ butwidth,
+ UI_UNIT_Y,
+ ptr,
+ prop,
+ 1,
+ 0.0,
+ 0.0,
+ 0,
+ 3,
+ TIP_("Green"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
+ bt = uiDefButR_prop(block,
+ UI_BTYPE_NUM_SLIDER,
+ 0,
+ IFACE_("B:"),
+ 0,
+ yco -= UI_UNIT_Y,
+ butwidth,
+ UI_UNIT_Y,
+ ptr,
+ prop,
+ 2,
+ 0.0,
+ 0.0,
+ 0,
+ 3,
+ TIP_("Blue"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
+
+ /* could use uiItemFullR(col, ptr, prop, -1, 0, UI_ITEM_R_EXPAND|UI_ITEM_R_SLIDER, "", ICON_NONE);
+ * but need to use UI_but_func_set for updating other fake buttons */
+
+ /* HSV values */
+ yco = -3.0f * UI_UNIT_Y;
+ UI_block_align_begin(block);
+ bt = uiDefButF(block,
+ UI_BTYPE_NUM_SLIDER,
+ 0,
+ IFACE_("H:"),
+ 0,
+ yco,
+ butwidth,
+ UI_UNIT_Y,
+ hsv,
+ 0.0,
+ 1.0,
+ 10,
+ 3,
+ TIP_("Hue"));
+ UI_but_flag_disable(bt, UI_BUT_UNDO);
+ UI_but_func_set(bt, ui_color_wheel_rna_cb, bt, hsv);
+ bt->custom_data = cpicker;
+ bt = uiDefButF(block,
+ UI_BTYPE_NUM_SLIDER,
+ 0,
+ IFACE_("S:"),
+ 0,
+ yco -= UI_UNIT_Y,
+ butwidth,
+ UI_UNIT_Y,
+ hsv + 1,
+ 0.0,
+ 1.0,
+ 10,
+ 3,
+ TIP_("Saturation"));
+ UI_but_flag_disable(bt, UI_BUT_UNDO);
+ UI_but_func_set(bt, ui_color_wheel_rna_cb, bt, hsv);
+ bt->custom_data = cpicker;
+ if (U.color_picker_type == USER_CP_CIRCLE_HSL) {
+ bt = uiDefButF(block,
+ UI_BTYPE_NUM_SLIDER,
+ 0,
+ IFACE_("L:"),
+ 0,
+ yco -= UI_UNIT_Y,
+ butwidth,
+ UI_UNIT_Y,
+ hsv + 2,
+ 0.0,
+ 1.0,
+ 10,
+ 3,
+ TIP_("Lightness"));
+ }
+ else {
+ bt = uiDefButF(block,
+ UI_BTYPE_NUM_SLIDER,
+ 0,
+ IFACE_("V:"),
+ 0,
+ yco -= UI_UNIT_Y,
+ butwidth,
+ UI_UNIT_Y,
+ hsv + 2,
+ 0.0,
+ softmax,
+ 10,
+ 3,
+ TIP_("Value"));
+ }
+ UI_but_flag_disable(bt, UI_BUT_UNDO);
+
+ bt->hardmax = hardmax; /* not common but rgb may be over 1.0 */
+ UI_but_func_set(bt, ui_color_wheel_rna_cb, bt, hsv);
+ bt->custom_data = cpicker;
+
+ UI_block_align_end(block);
+
+ if (rgba[3] != FLT_MAX) {
+ bt = uiDefButR_prop(block,
+ UI_BTYPE_NUM_SLIDER,
+ 0,
+ IFACE_("A: "),
+ 0,
+ yco -= UI_UNIT_Y,
+ butwidth,
+ UI_UNIT_Y,
+ ptr,
+ prop,
+ 3,
+ 0.0,
+ 0.0,
+ 0,
+ 3,
+ TIP_("Alpha"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
+ }
+ else {
+ rgba[3] = 1.0f;
+ }
+
+ /* Hex color is in sRGB space. */
+ float rgb_hex[3];
+ uchar rgb_hex_uchar[3];
+
+ copy_v3_v3(rgb_hex, rgba);
+
+ if (!ui_but_is_color_gamma(from_but)) {
+ IMB_colormanagement_scene_linear_to_srgb_v3(rgb_hex);
+ }
+
+ rgb_float_to_uchar(rgb_hex_uchar, rgb_hex);
+ BLI_snprintf(hexcol, sizeof(hexcol), "%02X%02X%02X", UNPACK3_EX((uint), rgb_hex_uchar, ));
+
+ yco = -3.0f * UI_UNIT_Y;
+ bt = uiDefBut(block,
+ UI_BTYPE_TEXT,
+ 0,
+ IFACE_("Hex: "),
+ 0,
+ yco,
+ butwidth,
+ UI_UNIT_Y,
+ hexcol,
+ 0,
+ 8,
+ 0,
+ 0,
+ TIP_("Hex triplet for color (#RRGGBB)"));
+ UI_but_flag_disable(bt, UI_BUT_UNDO);
+ UI_but_func_set(bt, ui_colorpicker_hex_rna_cb, bt, hexcol);
+ bt->custom_data = cpicker;
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ IFACE_("(Gamma Corrected)"),
+ 0,
+ yco - UI_UNIT_Y,
+ butwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+
+ ui_colorpicker_hide_reveal(block, colormode);
}
-
-static int ui_colorpicker_small_wheel_cb(const bContext *UNUSED(C), uiBlock *block, const wmEvent *event)
+static int ui_colorpicker_small_wheel_cb(const bContext *UNUSED(C),
+ uiBlock *block,
+ const wmEvent *event)
{
- float add = 0.0f;
-
- if (event->type == WHEELUPMOUSE) {
- add = 0.05f;
- }
- else if (event->type == WHEELDOWNMOUSE) {
- add = -0.05f;
- }
-
- if (add != 0.0f) {
- uiBut *but;
-
- for (but = block->buttons.first; but; but = but->next) {
- if (but->type == UI_BTYPE_HSVCUBE && but->active == NULL) {
- uiPopupBlockHandle *popup = block->handle;
- float rgb[3];
- ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
-
- ui_but_v3_get(but, rgb);
- ui_scene_linear_to_color_picker_space(but, rgb);
- ui_rgb_to_color_picker_compat_v(rgb, hsv);
-
- hsv[2] = clamp_f(hsv[2] + add, 0.0f, 1.0f);
-
- ui_color_picker_to_rgb_v(hsv, rgb);
- ui_color_picker_to_scene_linear_space(but, rgb);
- ui_but_v3_set(but, rgb);
-
- ui_update_color_picker_buts_rgb(but, block, cpicker, rgb);
- if (popup) {
- popup->menuretval = UI_RETURN_UPDATE;
- }
-
- return 1;
- }
- }
- }
- return 0;
+ float add = 0.0f;
+
+ if (event->type == WHEELUPMOUSE) {
+ add = 0.05f;
+ }
+ else if (event->type == WHEELDOWNMOUSE) {
+ add = -0.05f;
+ }
+
+ if (add != 0.0f) {
+ uiBut *but;
+
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->type == UI_BTYPE_HSVCUBE && but->active == NULL) {
+ uiPopupBlockHandle *popup = block->handle;
+ float rgb[3];
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
+
+ ui_but_v3_get(but, rgb);
+ ui_scene_linear_to_color_picker_space(but, rgb);
+ ui_rgb_to_color_picker_compat_v(rgb, hsv);
+
+ hsv[2] = clamp_f(hsv[2] + add, 0.0f, 1.0f);
+
+ ui_color_picker_to_rgb_v(hsv, rgb);
+ ui_color_picker_to_scene_linear_space(but, rgb);
+ ui_but_v3_set(but, rgb);
+
+ ui_update_color_picker_buts_rgb(but, block, cpicker, rgb);
+ if (popup) {
+ popup->menuretval = UI_RETURN_UPDATE;
+ }
+
+ return 1;
+ }
+ }
+ }
+ return 0;
}
uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_but)
{
- uiBut *but = arg_but;
- uiBlock *block;
- bool show_picker = true;
+ uiBut *but = arg_but;
+ uiBlock *block;
+ bool show_picker = true;
- block = UI_block_begin(C, handle->region, __func__, UI_EMBOSS);
+ block = UI_block_begin(C, handle->region, __func__, UI_EMBOSS);
- if (ui_but_is_color_gamma(but)) {
- block->is_color_gamma_picker = true;
- }
+ if (ui_but_is_color_gamma(but)) {
+ block->is_color_gamma_picker = true;
+ }
- if (but->block) {
- /* if color block is invoked from a popup we wouldn't be able to set color properly
- * this is because color picker will close popups first and then will try to figure
- * out active button RNA, and of course it'll fail
- */
- show_picker = (but->block->flag & UI_BLOCK_POPUP) == 0;
- }
+ if (but->block) {
+ /* if color block is invoked from a popup we wouldn't be able to set color properly
+ * this is because color picker will close popups first and then will try to figure
+ * out active button RNA, and of course it'll fail
+ */
+ show_picker = (but->block->flag & UI_BLOCK_POPUP) == 0;
+ }
- copy_v3_v3(handle->retvec, but->editvec);
+ copy_v3_v3(handle->retvec, but->editvec);
- ui_block_colorpicker(block, but, handle->retvec, show_picker);
+ ui_block_colorpicker(block, but, handle->retvec, show_picker);
- block->flag = UI_BLOCK_LOOP | UI_BLOCK_KEEP_OPEN | UI_BLOCK_OUT_1 | UI_BLOCK_MOVEMOUSE_QUIT;
- UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
- UI_block_bounds_set_normal(block, 0.5 * UI_UNIT_X);
+ block->flag = UI_BLOCK_LOOP | UI_BLOCK_KEEP_OPEN | UI_BLOCK_OUT_1 | UI_BLOCK_MOVEMOUSE_QUIT;
+ UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
+ UI_block_bounds_set_normal(block, 0.5 * UI_UNIT_X);
- block->block_event_func = ui_colorpicker_small_wheel_cb;
+ block->block_event_func = ui_colorpicker_small_wheel_cb;
- /* and lets go */
- block->direction = UI_DIR_UP;
+ /* and lets go */
+ block->direction = UI_DIR_UP;
- return block;
+ return block;
}
ColorPicker *ui_block_colorpicker_create(struct uiBlock *block)
{
- ColorPicker *cpicker = MEM_callocN(sizeof(ColorPicker), "color_picker");
- BLI_addhead(&block->color_pickers.list, cpicker);
+ ColorPicker *cpicker = MEM_callocN(sizeof(ColorPicker), "color_picker");
+ BLI_addhead(&block->color_pickers.list, cpicker);
- return cpicker;
+ return cpicker;
}
/** \} */
diff --git a/source/blender/editors/interface/interface_region_hud.c b/source/blender/editors/interface/interface_region_hud.c
index f6a5c9611af..a1f4b71dc6d 100644
--- a/source/blender/editors/interface/interface_region_hud.c
+++ b/source/blender/editors/interface/interface_region_hud.c
@@ -42,7 +42,6 @@
#include "RNA_access.h"
-
#include "UI_interface.h"
#include "UI_view2d.h"
@@ -54,32 +53,29 @@
#include "interface_intern.h"
#include "GPU_framebuffer.h"
-
/* -------------------------------------------------------------------- */
/** \name Utilities
* \{ */
static bool last_redo_poll(const bContext *C)
{
- wmOperator *op = WM_operator_last_redo(C);
- if (op == NULL) {
- return false;
- }
- bool success = false;
- if (WM_operator_repeat_check(C, op) &&
- WM_operator_check_ui_empty(op->type) == false)
- {
- success = WM_operator_poll((bContext *)C, op->type);
- }
- return success;
+ wmOperator *op = WM_operator_last_redo(C);
+ if (op == NULL) {
+ return false;
+ }
+ bool success = false;
+ if (WM_operator_repeat_check(C, op) && WM_operator_check_ui_empty(op->type) == false) {
+ success = WM_operator_poll((bContext *)C, op->type);
+ }
+ return success;
}
static void hud_region_hide(ARegion *ar)
{
- ar->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);
+ ar->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);
}
/** \} */
@@ -90,43 +86,43 @@ static void hud_region_hide(ARegion *ar)
static bool hud_panel_operator_redo_poll(const bContext *C, PanelType *UNUSED(pt))
{
- return last_redo_poll(C);
+ return last_redo_poll(C);
}
static void hud_panel_operator_redo_draw_header(const bContext *C, Panel *pa)
{
- wmOperator *op = WM_operator_last_redo(C);
- BLI_strncpy(pa->drawname, RNA_struct_ui_name(op->type->srna), sizeof(pa->drawname));
+ wmOperator *op = WM_operator_last_redo(C);
+ BLI_strncpy(pa->drawname, RNA_struct_ui_name(op->type->srna), sizeof(pa->drawname));
}
static void hud_panel_operator_redo_draw(const bContext *C, Panel *pa)
{
- 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);
- }
- uiLayout *col = uiLayoutColumn(pa->layout, false);
- uiTemplateOperatorRedoProperties(col, C);
+ 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);
+ }
+ uiLayout *col = uiLayoutColumn(pa->layout, false);
+ uiTemplateOperatorRedoProperties(col, C);
}
static void hud_panels_register(ARegionType *art, int space_type, int region_type)
{
- PanelType *pt;
-
- pt = MEM_callocN(sizeof(PanelType), __func__);
- strcpy(pt->idname, "OPERATOR_PT_redo");
- strcpy(pt->label, N_("Redo"));
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw_header = hud_panel_operator_redo_draw_header;
- pt->draw = hud_panel_operator_redo_draw;
- pt->poll = hud_panel_operator_redo_poll;
- pt->space_type = space_type;
- pt->region_type = region_type;
- pt->flag |= PNL_DEFAULT_CLOSED;
- BLI_addtail(&art->paneltypes, pt);
+ PanelType *pt;
+
+ pt = MEM_callocN(sizeof(PanelType), __func__);
+ strcpy(pt->idname, "OPERATOR_PT_redo");
+ strcpy(pt->label, N_("Redo"));
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw_header = hud_panel_operator_redo_draw_header;
+ pt->draw = hud_panel_operator_redo_draw;
+ pt->poll = hud_panel_operator_redo_poll;
+ pt->space_type = space_type;
+ pt->region_type = region_type;
+ pt->flag |= PNL_DEFAULT_CLOSED;
+ BLI_addtail(&art->paneltypes, pt);
}
/** \} */
@@ -136,229 +132,240 @@ static void hud_panels_register(ARegionType *art, int space_type, int region_typ
* \{ */
struct HudRegionData {
- short regionid;
+ short regionid;
};
static void hud_region_init(wmWindowManager *wm, ARegion *ar)
{
- ED_region_panels_init(wm, ar);
- UI_region_handlers_add(&ar->handlers);
- ar->flag |= RGN_FLAG_TEMP_REGIONDATA;
+ ED_region_panels_init(wm, ar);
+ UI_region_handlers_add(&ar->handlers);
+ ar->flag |= RGN_FLAG_TEMP_REGIONDATA;
}
static void hud_region_free(ARegion *ar)
{
- MEM_SAFE_FREE(ar->regiondata);
+ MEM_SAFE_FREE(ar->regiondata);
}
static void hud_region_layout(const bContext *C, ARegion *ar)
{
- bool ok = false;
-
- {
- struct HudRegionData *hrd = ar->regiondata;
- if (hrd != NULL) {
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar_op = (hrd->regionid != -1) ? BKE_area_find_region_type(sa, hrd->regionid) : NULL;
- ARegion *ar_prev = CTX_wm_region(C);
- CTX_wm_region_set((bContext *)C, ar_op);
- ok = last_redo_poll(C);
- CTX_wm_region_set((bContext *)C, ar_prev);
- }
- }
-
- if (!ok) {
- ED_region_tag_redraw(ar);
- hud_region_hide(ar);
- return;
- }
-
- int size_y = ar->sizey;
-
- ED_region_panels_layout(C, ar);
-
- 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 (ar->flag & RGN_FLAG_SIZE_CLAMP_X) {
- CLAMP_MAX(winx_new, ar->winx);
- }
- if (ar->flag & RGN_FLAG_SIZE_CLAMP_Y) {
- CLAMP_MAX(winy_new, ar->winy);
- }
-
- ar->winx = winx_new;
- ar->winy = winy_new;
-
- ar->winrct.xmax = (ar->winrct.xmin + ar->winx) - 1;
- ar->winrct.ymax = (ar->winrct.ymin + ar->winy) - 1;
-
- UI_view2d_region_reinit(v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->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);
- }
-
- /* restore view matrix */
- UI_view2d_view_restore(C);
+ bool ok = false;
+
+ {
+ struct HudRegionData *hrd = ar->regiondata;
+ if (hrd != NULL) {
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar_op = (hrd->regionid != -1) ? BKE_area_find_region_type(sa, hrd->regionid) : NULL;
+ ARegion *ar_prev = CTX_wm_region(C);
+ CTX_wm_region_set((bContext *)C, ar_op);
+ ok = last_redo_poll(C);
+ CTX_wm_region_set((bContext *)C, ar_prev);
+ }
+ }
+
+ if (!ok) {
+ ED_region_tag_redraw(ar);
+ hud_region_hide(ar);
+ return;
+ }
+
+ int size_y = ar->sizey;
+
+ ED_region_panels_layout(C, ar);
+
+ 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 (ar->flag & RGN_FLAG_SIZE_CLAMP_X) {
+ CLAMP_MAX(winx_new, ar->winx);
+ }
+ if (ar->flag & RGN_FLAG_SIZE_CLAMP_Y) {
+ CLAMP_MAX(winy_new, ar->winy);
+ }
+
+ ar->winx = winx_new;
+ ar->winy = winy_new;
+
+ ar->winrct.xmax = (ar->winrct.xmin + ar->winx) - 1;
+ ar->winrct.ymax = (ar->winrct.ymin + ar->winy) - 1;
+
+ UI_view2d_region_reinit(v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->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);
+ }
+
+ /* restore view matrix */
+ UI_view2d_view_restore(C);
}
static void hud_region_draw(const bContext *C, ARegion *ar)
{
- UI_view2d_view_ortho(&ar->v2d);
- wmOrtho2_region_pixelspace(ar);
- GPU_clear_color(0, 0, 0, 0.0f);
- GPU_clear(GPU_COLOR_BIT);
-
- if ((ar->flag & RGN_FLAG_HIDDEN) == 0) {
- ui_draw_menu_back(NULL, NULL, &(rcti){ .xmax = ar->winx, .ymax = ar->winy, });
- ED_region_panels_draw(C, ar);
- }
+ UI_view2d_view_ortho(&ar->v2d);
+ wmOrtho2_region_pixelspace(ar);
+ GPU_clear_color(0, 0, 0, 0.0f);
+ GPU_clear(GPU_COLOR_BIT);
+
+ if ((ar->flag & RGN_FLAG_HIDDEN) == 0) {
+ ui_draw_menu_back(NULL,
+ NULL,
+ &(rcti){
+ .xmax = ar->winx,
+ .ymax = ar->winy,
+ });
+ ED_region_panels_draw(C, ar);
+ }
}
ARegionType *ED_area_type_hud(int space_type)
{
- ARegionType *art = MEM_callocN(sizeof(ARegionType), __func__);
- art->regionid = RGN_TYPE_HUD;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
- art->layout = hud_region_layout;
- art->draw = hud_region_draw;
- art->init = hud_region_init;
- art->free = hud_region_free;
-
- hud_panels_register(art, space_type, art->regionid);
-
- art->lock = 1; /* can become flag, see BKE_spacedata_draw_locks */
- return art;
+ ARegionType *art = MEM_callocN(sizeof(ARegionType), __func__);
+ art->regionid = RGN_TYPE_HUD;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
+ art->layout = hud_region_layout;
+ art->draw = hud_region_draw;
+ art->init = hud_region_init;
+ art->free = hud_region_free;
+
+ hud_panels_register(art, space_type, art->regionid);
+
+ art->lock = 1; /* can become flag, see BKE_spacedata_draw_locks */
+ return art;
}
static ARegion *hud_region_add(ScrArea *sa)
{
- 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);
- }
- else {
- BLI_addtail(&sa->regionbase, ar);
- }
- ar->regiontype = RGN_TYPE_HUD;
- ar->alignment = RGN_ALIGN_FLOAT;
- ar->overlap = true;
- ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
-
- return ar;
+ 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);
+ }
+ else {
+ BLI_addtail(&sa->regionbase, ar);
+ }
+ ar->regiontype = RGN_TYPE_HUD;
+ ar->alignment = RGN_ALIGN_FLOAT;
+ ar->overlap = true;
+ ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
+
+ return ar;
}
void ED_area_type_hud_clear(wmWindowManager *wm, ScrArea *sa_keep)
{
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
- 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);
- }
- }
- }
- }
- }
- }
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ 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);
+ }
+ }
+ }
+ }
+ }
+ }
}
void ED_area_type_hud_ensure(bContext *C, ScrArea *sa)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- ED_area_type_hud_clear(wm, sa);
-
- ARegionType *art = BKE_regiontype_from_id(sa->type, RGN_TYPE_HUD);
- if (art == NULL) {
- return;
- }
-
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_HUD);
- bool init = false;
- bool was_hidden = ar == NULL || ar->visible == false;
- if (!last_redo_poll(C)) {
- if (ar) {
- ED_region_tag_redraw(ar);
- hud_region_hide(ar);
- }
- return;
- }
-
- if (ar == NULL) {
- init = true;
- ar = hud_region_add(sa);
- ar->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. */
- if (init) {
- sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
- }
- else {
- if (ar->flag & RGN_FLAG_HIDDEN) {
- sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
- }
- ar->flag &= ~RGN_FLAG_HIDDEN;
- }
-
- {
- ARegion *ar_op = CTX_wm_region(C);
- BLI_assert((ar_op == NULL) || (ar_op->regiontype != RGN_TYPE_HUD));
- struct HudRegionData *hrd = ar->regiondata;
- if (hrd == NULL) {
- hrd = MEM_callocN(sizeof(*hrd), __func__);
- ar->regiondata = hrd;
- }
- if (ar_op) {
- hrd->regionid = ar_op->regiontype;
- }
- else {
- hrd->regionid = -1;
- }
- }
-
- 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_region_init(ar);
- ED_region_tag_redraw(ar);
-
- /* Reset zoom level (not well supported). */
- ar->v2d.cur = ar->v2d.tot = (rctf){ .xmax = ar->winx, .ymax = ar->winy, };
- ar->v2d.minzoom = 1.0f;
- ar->v2d.maxzoom = 1.0f;
-
- ar->visible = !(ar->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 (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, };
- }
- CTX_wm_region_set((bContext *)C, ar_prev);
- }
-
- ar->visible = !((ar->flag & RGN_FLAG_HIDDEN) || (ar->flag & RGN_FLAG_TOO_SMALL));
+ wmWindowManager *wm = CTX_wm_manager(C);
+ ED_area_type_hud_clear(wm, sa);
+
+ ARegionType *art = BKE_regiontype_from_id(sa->type, RGN_TYPE_HUD);
+ if (art == NULL) {
+ return;
+ }
+
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_HUD);
+ bool init = false;
+ bool was_hidden = ar == NULL || ar->visible == false;
+ if (!last_redo_poll(C)) {
+ if (ar) {
+ ED_region_tag_redraw(ar);
+ hud_region_hide(ar);
+ }
+ return;
+ }
+
+ if (ar == NULL) {
+ init = true;
+ ar = hud_region_add(sa);
+ ar->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. */
+ if (init) {
+ sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
+ }
+ else {
+ if (ar->flag & RGN_FLAG_HIDDEN) {
+ sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
+ }
+ ar->flag &= ~RGN_FLAG_HIDDEN;
+ }
+
+ {
+ ARegion *ar_op = CTX_wm_region(C);
+ BLI_assert((ar_op == NULL) || (ar_op->regiontype != RGN_TYPE_HUD));
+ struct HudRegionData *hrd = ar->regiondata;
+ if (hrd == NULL) {
+ hrd = MEM_callocN(sizeof(*hrd), __func__);
+ ar->regiondata = hrd;
+ }
+ if (ar_op) {
+ hrd->regionid = ar_op->regiontype;
+ }
+ else {
+ hrd->regionid = -1;
+ }
+ }
+
+ 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_region_init(ar);
+ ED_region_tag_redraw(ar);
+
+ /* Reset zoom level (not well supported). */
+ ar->v2d.cur = ar->v2d.tot = (rctf){
+ .xmax = ar->winx,
+ .ymax = ar->winy,
+ };
+ ar->v2d.minzoom = 1.0f;
+ ar->v2d.maxzoom = 1.0f;
+
+ ar->visible = !(ar->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 (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,
+ };
+ }
+ CTX_wm_region_set((bContext *)C, ar_prev);
+ }
+
+ ar->visible = !((ar->flag & RGN_FLAG_HIDDEN) || (ar->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 b2fcfc0b23b..b115600a80b 100644
--- a/source/blender/editors/interface/interface_region_menu_pie.c
+++ b/source/blender/editors/interface/interface_region_menu_pie.c
@@ -59,225 +59,249 @@
* \{ */
struct uiPieMenu {
- uiBlock *block_radial; /* radial block of the pie menu (more could be added later) */
- uiLayout *layout;
- int mx, my;
+ uiBlock *block_radial; /* radial block of the pie menu (more could be added later) */
+ uiLayout *layout;
+ int mx, my;
};
static uiBlock *ui_block_func_PIE(bContext *UNUSED(C), uiPopupBlockHandle *handle, void *arg_pie)
{
- uiBlock *block;
- uiPieMenu *pie = arg_pie;
- int minwidth, width, height;
+ uiBlock *block;
+ uiPieMenu *pie = arg_pie;
+ int minwidth, width, height;
- minwidth = UI_MENU_WIDTH_MIN;
- block = pie->block_radial;
+ minwidth = UI_MENU_WIDTH_MIN;
+ block = pie->block_radial;
- /* in some cases we create the block before the region,
- * so we set it delayed here if necessary */
- if (BLI_findindex(&handle->region->uiblocks, block) == -1) {
- UI_block_region_set(block, handle->region);
- }
+ /* in some cases we create the block before the region,
+ * so we set it delayed here if necessary */
+ if (BLI_findindex(&handle->region->uiblocks, block) == -1) {
+ UI_block_region_set(block, handle->region);
+ }
- UI_block_layout_resolve(block, &width, &height);
+ UI_block_layout_resolve(block, &width, &height);
- UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_NUMSELECT);
- UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
+ UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_NUMSELECT);
+ UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
- block->minbounds = minwidth;
- block->bounds = 1;
- block->bounds_offset[0] = 0;
- block->bounds_offset[1] = 0;
- block->bounds_type = UI_BLOCK_BOUNDS_PIE_CENTER;
+ block->minbounds = minwidth;
+ block->bounds = 1;
+ block->bounds_offset[0] = 0;
+ block->bounds_offset[1] = 0;
+ block->bounds_type = UI_BLOCK_BOUNDS_PIE_CENTER;
- block->pie_data.pie_center_spawned[0] = pie->mx;
- block->pie_data.pie_center_spawned[1] = pie->my;
+ block->pie_data.pie_center_spawned[0] = pie->mx;
+ block->pie_data.pie_center_spawned[1] = pie->my;
- return pie->block_radial;
+ return pie->block_radial;
}
static float ui_pie_menu_title_width(const char *name, int icon)
{
- const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- return (UI_fontstyle_string_width(fstyle, name) +
- (UI_UNIT_X * (1.50f + (icon ? 0.25f : 0.0f))));
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ return (UI_fontstyle_string_width(fstyle, name) + (UI_UNIT_X * (1.50f + (icon ? 0.25f : 0.0f))));
}
uiPieMenu *UI_pie_menu_begin(struct bContext *C, const char *title, int icon, const wmEvent *event)
{
- uiStyle *style;
- 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);
- /* may be useful later to allow spawning pies
- * from old positions */
- /* pie->block_radial->flag |= UI_BLOCK_POPUP_MEMORY; */
- pie->block_radial->puphash = ui_popup_menu_hash(title);
- pie->block_radial->flag |= UI_BLOCK_RADIAL;
-
- /* if pie is spawned by a left click, release or click event,
- * it is always assumed to be click style */
- if (event->type == LEFTMOUSE || ELEM(event->val, KM_RELEASE, KM_CLICK)) {
- pie->block_radial->pie_data.flags |= UI_PIE_CLICK_STYLE;
- pie->block_radial->pie_data.event = EVENT_NONE;
- win->lock_pie_event = EVENT_NONE;
- }
- else {
- if (win->last_pie_event != EVENT_NONE) {
- /* original pie key has been released, so don't propagate the event */
- if (win->lock_pie_event == EVENT_NONE) {
- event_type = EVENT_NONE;
- pie->block_radial->pie_data.flags |= UI_PIE_CLICK_STYLE;
- }
- else {
- event_type = win->last_pie_event;
- }
- }
- else {
- event_type = event->type;
- }
-
- pie->block_radial->pie_data.event = event_type;
- win->lock_pie_event = event_type;
- }
-
- pie->layout = UI_block_layout(pie->block_radial, UI_LAYOUT_VERTICAL, UI_LAYOUT_PIEMENU, 0, 0, 200, 0, 0, style);
-
- /* Note event->x/y is where we started dragging in case of KM_CLICK_DRAG. */
- pie->mx = event->x;
- pie->my = event->y;
-
- /* create title button */
- if (title[0]) {
- uiBut *but;
- char titlestr[256];
- int w;
- if (icon) {
- BLI_snprintf(titlestr, sizeof(titlestr), " %s", title);
- w = ui_pie_menu_title_width(titlestr, icon);
- but = uiDefIconTextBut(
- pie->block_radial, UI_BTYPE_LABEL, 0, icon, titlestr, 0, 0, w, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0, 0, "");
- }
- else {
- w = ui_pie_menu_title_width(title, 0);
- but = uiDefBut(
- pie->block_radial, UI_BTYPE_LABEL, 0, title, 0, 0, w, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0, 0, "");
- }
- /* do not align left */
- but->drawflag &= ~UI_BUT_TEXT_LEFT;
- pie->block_radial->pie_data.title = but->str;
- pie->block_radial->pie_data.icon = icon;
- }
-
- return pie;
+ uiStyle *style;
+ 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);
+ /* may be useful later to allow spawning pies
+ * from old positions */
+ /* pie->block_radial->flag |= UI_BLOCK_POPUP_MEMORY; */
+ pie->block_radial->puphash = ui_popup_menu_hash(title);
+ pie->block_radial->flag |= UI_BLOCK_RADIAL;
+
+ /* if pie is spawned by a left click, release or click event,
+ * it is always assumed to be click style */
+ if (event->type == LEFTMOUSE || ELEM(event->val, KM_RELEASE, KM_CLICK)) {
+ pie->block_radial->pie_data.flags |= UI_PIE_CLICK_STYLE;
+ pie->block_radial->pie_data.event = EVENT_NONE;
+ win->lock_pie_event = EVENT_NONE;
+ }
+ else {
+ if (win->last_pie_event != EVENT_NONE) {
+ /* original pie key has been released, so don't propagate the event */
+ if (win->lock_pie_event == EVENT_NONE) {
+ event_type = EVENT_NONE;
+ pie->block_radial->pie_data.flags |= UI_PIE_CLICK_STYLE;
+ }
+ else {
+ event_type = win->last_pie_event;
+ }
+ }
+ else {
+ event_type = event->type;
+ }
+
+ pie->block_radial->pie_data.event = event_type;
+ win->lock_pie_event = event_type;
+ }
+
+ pie->layout = UI_block_layout(
+ pie->block_radial, UI_LAYOUT_VERTICAL, UI_LAYOUT_PIEMENU, 0, 0, 200, 0, 0, style);
+
+ /* Note event->x/y is where we started dragging in case of KM_CLICK_DRAG. */
+ pie->mx = event->x;
+ pie->my = event->y;
+
+ /* create title button */
+ if (title[0]) {
+ uiBut *but;
+ char titlestr[256];
+ int w;
+ if (icon) {
+ BLI_snprintf(titlestr, sizeof(titlestr), " %s", title);
+ w = ui_pie_menu_title_width(titlestr, icon);
+ but = uiDefIconTextBut(pie->block_radial,
+ UI_BTYPE_LABEL,
+ 0,
+ icon,
+ titlestr,
+ 0,
+ 0,
+ w,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ }
+ else {
+ w = ui_pie_menu_title_width(title, 0);
+ but = uiDefBut(pie->block_radial,
+ UI_BTYPE_LABEL,
+ 0,
+ title,
+ 0,
+ 0,
+ w,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ }
+ /* do not align left */
+ but->drawflag &= ~UI_BUT_TEXT_LEFT;
+ pie->block_radial->pie_data.title = but->str;
+ pie->block_radial->pie_data.icon = icon;
+ }
+
+ return pie;
}
void UI_pie_menu_end(bContext *C, uiPieMenu *pie)
{
- wmWindow *window = CTX_wm_window(C);
- uiPopupBlockHandle *menu;
+ wmWindow *window = CTX_wm_window(C);
+ uiPopupBlockHandle *menu;
- menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_PIE, pie);
- menu->popup = true;
- menu->towardstime = PIL_check_seconds_timer();
+ menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_PIE, pie);
+ menu->popup = true;
+ menu->towardstime = PIL_check_seconds_timer();
- UI_popup_handlers_add(
- C, &window->modalhandlers,
- menu, WM_HANDLER_ACCEPT_DBL_CLICK);
- WM_event_add_mousemove(C);
+ UI_popup_handlers_add(C, &window->modalhandlers, menu, WM_HANDLER_ACCEPT_DBL_CLICK);
+ WM_event_add_mousemove(C);
- MEM_freeN(pie);
+ MEM_freeN(pie);
}
uiLayout *UI_pie_menu_layout(uiPieMenu *pie)
{
- return pie->layout;
+ return pie->layout;
}
int UI_pie_menu_invoke(struct bContext *C, const char *idname, const wmEvent *event)
{
- uiPieMenu *pie;
- uiLayout *layout;
- MenuType *mt = WM_menutype_find(idname, true);
+ uiPieMenu *pie;
+ uiLayout *layout;
+ MenuType *mt = WM_menutype_find(idname, true);
- if (mt == NULL) {
- printf("%s: named menu \"%s\" not found\n", __func__, idname);
- return OPERATOR_CANCELLED;
- }
+ if (mt == NULL) {
+ printf("%s: named menu \"%s\" not found\n", __func__, idname);
+ return OPERATOR_CANCELLED;
+ }
- if (WM_menutype_poll(C, mt) == false) {
- /* cancel but allow event to pass through, just like operators do */
- return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
- }
+ if (WM_menutype_poll(C, mt) == false) {
+ /* cancel but allow event to pass through, just like operators do */
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
- pie = UI_pie_menu_begin(C, IFACE_(mt->label), ICON_NONE, event);
- layout = UI_pie_menu_layout(pie);
+ pie = UI_pie_menu_begin(C, IFACE_(mt->label), ICON_NONE, event);
+ layout = UI_pie_menu_layout(pie);
- UI_menutype_draw(C, mt, layout);
+ UI_menutype_draw(C, mt, layout);
- UI_pie_menu_end(C, pie);
+ UI_pie_menu_end(C, pie);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
-int UI_pie_menu_invoke_from_operator_enum(
- struct bContext *C, const char *title, const char *opname,
- const char *propname, const wmEvent *event)
+int UI_pie_menu_invoke_from_operator_enum(struct bContext *C,
+ const char *title,
+ const char *opname,
+ const char *propname,
+ const wmEvent *event)
{
- uiPieMenu *pie;
- uiLayout *layout;
+ uiPieMenu *pie;
+ uiLayout *layout;
- pie = UI_pie_menu_begin(C, IFACE_(title), ICON_NONE, event);
- layout = UI_pie_menu_layout(pie);
+ pie = UI_pie_menu_begin(C, IFACE_(title), ICON_NONE, event);
+ layout = UI_pie_menu_layout(pie);
- layout = uiLayoutRadial(layout);
- uiItemsEnumO(layout, opname, propname);
+ layout = uiLayoutRadial(layout);
+ uiItemsEnumO(layout, opname, propname);
- UI_pie_menu_end(C, pie);
+ UI_pie_menu_end(C, pie);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
-int UI_pie_menu_invoke_from_rna_enum(
- struct bContext *C, const char *title, const char *path,
- const wmEvent *event)
+int UI_pie_menu_invoke_from_rna_enum(struct bContext *C,
+ const char *title,
+ const char *path,
+ const wmEvent *event)
{
- PointerRNA ctx_ptr;
- PointerRNA r_ptr;
- PropertyRNA *r_prop;
- uiPieMenu *pie;
- uiLayout *layout;
+ PointerRNA ctx_ptr;
+ PointerRNA r_ptr;
+ PropertyRNA *r_prop;
+ uiPieMenu *pie;
+ uiLayout *layout;
- RNA_pointer_create(NULL, &RNA_Context, C, &ctx_ptr);
+ RNA_pointer_create(NULL, &RNA_Context, C, &ctx_ptr);
- if (!RNA_path_resolve(&ctx_ptr, path, &r_ptr, &r_prop)) {
- return OPERATOR_CANCELLED;
- }
+ if (!RNA_path_resolve(&ctx_ptr, path, &r_ptr, &r_prop)) {
+ return OPERATOR_CANCELLED;
+ }
- /* invalid property, only accept enums */
- if (RNA_property_type(r_prop) != PROP_ENUM) {
- BLI_assert(0);
- return OPERATOR_CANCELLED;
- }
+ /* invalid property, only accept enums */
+ if (RNA_property_type(r_prop) != PROP_ENUM) {
+ BLI_assert(0);
+ return OPERATOR_CANCELLED;
+ }
- pie = UI_pie_menu_begin(C, IFACE_(title), ICON_NONE, event);
+ pie = UI_pie_menu_begin(C, IFACE_(title), ICON_NONE, event);
- layout = UI_pie_menu_layout(pie);
+ layout = UI_pie_menu_layout(pie);
- layout = uiLayoutRadial(layout);
- uiItemFullR(layout, &r_ptr, r_prop, RNA_NO_INDEX, 0, UI_ITEM_R_EXPAND, NULL, 0);
+ layout = uiLayoutRadial(layout);
+ uiItemFullR(layout, &r_ptr, r_prop, RNA_NO_INDEX, 0, UI_ITEM_R_EXPAND, NULL, 0);
- UI_pie_menu_end(C, pie);
+ UI_pie_menu_end(C, pie);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
/** \} */
@@ -298,15 +322,15 @@ int UI_pie_menu_invoke_from_rna_enum(
* \{ */
typedef struct PieMenuLevelData {
- char title[UI_MAX_NAME_STR]; /* parent pie title, copied for level */
- int icon; /* parent pie icon, copied for level */
- int totitem; /* total count of *remaining* items */
-
- /* needed for calling uiItemsFullEnumO_array again for new level */
- wmOperatorType *ot;
- const char *propname;
- IDProperty *properties;
- int context, flag;
+ char title[UI_MAX_NAME_STR]; /* parent pie title, copied for level */
+ int icon; /* parent pie icon, copied for level */
+ int totitem; /* total count of *remaining* items */
+
+ /* needed for calling uiItemsFullEnumO_array again for new level */
+ wmOperatorType *ot;
+ const char *propname;
+ IDProperty *properties;
+ int context, flag;
} PieMenuLevelData;
/**
@@ -314,66 +338,90 @@ typedef struct PieMenuLevelData {
*/
static void ui_pie_menu_level_invoke(bContext *C, void *argN, void *arg2)
{
- EnumPropertyItem *item_array = (EnumPropertyItem *)argN;
- PieMenuLevelData *lvl = (PieMenuLevelData *)arg2;
- wmWindow *win = CTX_wm_window(C);
-
- uiPieMenu *pie = UI_pie_menu_begin(C, IFACE_(lvl->title), lvl->icon, win->eventstate);
- uiLayout *layout = UI_pie_menu_layout(pie);
-
- layout = uiLayoutRadial(layout);
-
- PointerRNA ptr;
-
- WM_operator_properties_create_ptr(&ptr, lvl->ot);
- /* so the context is passed to itemf functions (some need it) */
- WM_operator_properties_sanitize(&ptr, false);
- PropertyRNA *prop = RNA_struct_find_property(&ptr, lvl->propname);
-
- if (prop) {
- uiItemsFullEnumO_items(
- layout, lvl->ot, ptr, prop, lvl->properties, lvl->context, lvl->flag,
- item_array, lvl->totitem);
- }
- else {
- RNA_warning("%s.%s not found", RNA_struct_identifier(ptr.type), lvl->propname);
- }
-
- UI_pie_menu_end(C, pie);
+ EnumPropertyItem *item_array = (EnumPropertyItem *)argN;
+ PieMenuLevelData *lvl = (PieMenuLevelData *)arg2;
+ wmWindow *win = CTX_wm_window(C);
+
+ uiPieMenu *pie = UI_pie_menu_begin(C, IFACE_(lvl->title), lvl->icon, win->eventstate);
+ uiLayout *layout = UI_pie_menu_layout(pie);
+
+ layout = uiLayoutRadial(layout);
+
+ PointerRNA ptr;
+
+ WM_operator_properties_create_ptr(&ptr, lvl->ot);
+ /* so the context is passed to itemf functions (some need it) */
+ WM_operator_properties_sanitize(&ptr, false);
+ PropertyRNA *prop = RNA_struct_find_property(&ptr, lvl->propname);
+
+ if (prop) {
+ uiItemsFullEnumO_items(layout,
+ lvl->ot,
+ ptr,
+ prop,
+ lvl->properties,
+ lvl->context,
+ lvl->flag,
+ item_array,
+ lvl->totitem);
+ }
+ else {
+ RNA_warning("%s.%s not found", RNA_struct_identifier(ptr.type), lvl->propname);
+ }
+
+ UI_pie_menu_end(C, pie);
}
/**
* Set up data for defining a new pie menu level and add button that invokes it.
*/
-void ui_pie_menu_level_create(
- uiBlock *block, wmOperatorType *ot, const char *propname, IDProperty *properties,
- const EnumPropertyItem *items, int totitem, int context, int flag)
+void ui_pie_menu_level_create(uiBlock *block,
+ wmOperatorType *ot,
+ const char *propname,
+ IDProperty *properties,
+ const EnumPropertyItem *items,
+ int totitem,
+ int context,
+ int flag)
{
- const int totitem_parent = PIE_MAX_ITEMS - 1;
- const int totitem_remain = totitem - totitem_parent;
- size_t array_size = sizeof(EnumPropertyItem) * totitem_remain;
-
- /* used as but->func_argN so freeing is handled elsewhere */
- EnumPropertyItem *remaining = MEM_mallocN(array_size + sizeof(EnumPropertyItem), "pie_level_item_array");
- memcpy(remaining, items + totitem_parent, array_size);
- /* a NULL terminating sentinal element is required */
- memset(&remaining[totitem_remain], 0, sizeof(EnumPropertyItem));
-
-
- /* yuk, static... issue is we can't reliably free this without doing dangerous changes */
- static PieMenuLevelData lvl;
- BLI_strncpy(lvl.title, block->pie_data.title, UI_MAX_NAME_STR);
- lvl.totitem = totitem_remain;
- lvl.ot = ot;
- lvl.propname = propname;
- lvl.properties = properties;
- lvl.context = context;
- lvl.flag = flag;
-
- /* add a 'more' menu entry */
- uiBut *but = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_PLUS, "More", 0, 0, UI_UNIT_X * 3, UI_UNIT_Y, NULL,
- 0.0f, 0.0f, 0.0f, 0.0f, "Show more items of this menu");
- UI_but_funcN_set(but, ui_pie_menu_level_invoke, remaining, &lvl);
+ const int totitem_parent = PIE_MAX_ITEMS - 1;
+ const int totitem_remain = totitem - totitem_parent;
+ size_t array_size = sizeof(EnumPropertyItem) * totitem_remain;
+
+ /* used as but->func_argN so freeing is handled elsewhere */
+ EnumPropertyItem *remaining = MEM_mallocN(array_size + sizeof(EnumPropertyItem),
+ "pie_level_item_array");
+ memcpy(remaining, items + totitem_parent, array_size);
+ /* a NULL terminating sentinal element is required */
+ memset(&remaining[totitem_remain], 0, sizeof(EnumPropertyItem));
+
+ /* yuk, static... issue is we can't reliably free this without doing dangerous changes */
+ static PieMenuLevelData lvl;
+ BLI_strncpy(lvl.title, block->pie_data.title, UI_MAX_NAME_STR);
+ lvl.totitem = totitem_remain;
+ lvl.ot = ot;
+ lvl.propname = propname;
+ lvl.properties = properties;
+ lvl.context = context;
+ lvl.flag = flag;
+
+ /* add a 'more' menu entry */
+ uiBut *but = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_PLUS,
+ "More",
+ 0,
+ 0,
+ UI_UNIT_X * 3,
+ UI_UNIT_Y,
+ NULL,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ "Show more items of this menu");
+ UI_but_funcN_set(but, ui_pie_menu_level_invoke, remaining, &lvl);
}
/** \} */ /* Pie Menu Levels */
diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c
index 0fe847caa20..d364bf7e102 100644
--- a/source/blender/editors/interface/interface_region_menu_popup.c
+++ b/source/blender/editors/interface/interface_region_menu_popup.c
@@ -64,90 +64,91 @@
bool ui_but_menu_step_poll(const uiBut *but)
{
- BLI_assert(but->type == UI_BTYPE_MENU);
+ BLI_assert(but->type == UI_BTYPE_MENU);
- /* currently only RNA buttons */
- return ((but->menu_step_func != NULL) ||
- (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM));
+ /* currently only RNA buttons */
+ return ((but->menu_step_func != NULL) ||
+ (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM));
}
int ui_but_menu_step(uiBut *but, int direction)
{
- if (ui_but_menu_step_poll(but)) {
- if (but->menu_step_func) {
- return but->menu_step_func(but->block->evil_C, direction, but->poin);
- }
- else {
- const int curval = RNA_property_enum_get(&but->rnapoin, but->rnaprop);
- return RNA_property_enum_step(but->block->evil_C, &but->rnapoin, but->rnaprop, curval, direction);
- }
- }
-
- printf("%s: cannot cycle button '%s'\n", __func__, but->str);
- return 0;
+ if (ui_but_menu_step_poll(but)) {
+ if (but->menu_step_func) {
+ return but->menu_step_func(but->block->evil_C, direction, but->poin);
+ }
+ else {
+ const int curval = RNA_property_enum_get(&but->rnapoin, but->rnaprop);
+ return RNA_property_enum_step(
+ but->block->evil_C, &but->rnapoin, but->rnaprop, curval, direction);
+ }
+ }
+
+ printf("%s: cannot cycle button '%s'\n", __func__, but->str);
+ return 0;
}
static uint ui_popup_string_hash(const char *str)
{
- /* sometimes button contains hotkey, sometimes not, strip for proper compare */
- int hash;
- const char *delimit = strrchr(str, UI_SEP_CHAR);
-
- if (delimit) {
- hash = BLI_ghashutil_strhash_n(str, delimit - str);
- }
- else {
- hash = BLI_ghashutil_strhash(str);
- }
-
- return hash;
+ /* sometimes button contains hotkey, sometimes not, strip for proper compare */
+ int hash;
+ const char *delimit = strrchr(str, UI_SEP_CHAR);
+
+ if (delimit) {
+ hash = BLI_ghashutil_strhash_n(str, delimit - str);
+ }
+ else {
+ hash = BLI_ghashutil_strhash(str);
+ }
+
+ return hash;
}
uint ui_popup_menu_hash(const char *str)
{
- return BLI_ghashutil_strhash(str);
+ return BLI_ghashutil_strhash(str);
}
/* but == NULL read, otherwise set */
static uiBut *ui_popup_menu_memory__internal(uiBlock *block, uiBut *but)
{
- static uint mem[256];
- static bool first = true;
-
- const uint hash = block->puphash;
- const uint hash_mod = hash & 255;
-
- if (first) {
- /* init */
- memset(mem, -1, sizeof(mem));
- first = 0;
- }
-
- if (but) {
- /* set */
- mem[hash_mod] = ui_popup_string_hash(but->str);
- return NULL;
- }
- else {
- /* get */
- for (but = block->buttons.first; but; but = but->next) {
- if (ui_popup_string_hash(but->str) == mem[hash_mod]) {
- return but;
- }
- }
-
- return NULL;
- }
+ static uint mem[256];
+ static bool first = true;
+
+ const uint hash = block->puphash;
+ const uint hash_mod = hash & 255;
+
+ if (first) {
+ /* init */
+ memset(mem, -1, sizeof(mem));
+ first = 0;
+ }
+
+ if (but) {
+ /* set */
+ mem[hash_mod] = ui_popup_string_hash(but->str);
+ return NULL;
+ }
+ else {
+ /* get */
+ for (but = block->buttons.first; but; but = but->next) {
+ if (ui_popup_string_hash(but->str) == mem[hash_mod]) {
+ return but;
+ }
+ }
+
+ return NULL;
+ }
}
uiBut *ui_popup_menu_memory_get(uiBlock *block)
{
- return ui_popup_menu_memory__internal(block, NULL);
+ return ui_popup_menu_memory__internal(block, NULL);
}
void ui_popup_menu_memory_set(uiBlock *block, uiBut *but)
{
- ui_popup_menu_memory__internal(block, but);
+ ui_popup_menu_memory__internal(block, but);
}
/** \} */
@@ -157,213 +158,211 @@ void ui_popup_menu_memory_set(uiBlock *block, uiBut *but)
* \{ */
struct uiPopupMenu {
- uiBlock *block;
- uiLayout *layout;
- uiBut *but;
- ARegion *butregion;
+ uiBlock *block;
+ uiLayout *layout;
+ uiBut *but;
+ ARegion *butregion;
- int mx, my;
- bool popup, slideout;
+ int mx, my;
+ bool popup, slideout;
- uiMenuCreateFunc menu_func;
- void *menu_arg;
+ uiMenuCreateFunc menu_func;
+ void *menu_arg;
};
static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, void *arg_pup)
{
- uiBlock *block;
- uiPopupMenu *pup = arg_pup;
- int minwidth, width, height;
- char direction;
- bool flip;
-
- if (pup->menu_func) {
- pup->block->handle = handle;
- pup->menu_func(C, pup->layout, pup->menu_arg);
- pup->block->handle = NULL;
- }
-
- if (pup->but) {
- /* minimum width to enforece */
- if (pup->but->drawstr[0]) {
- minwidth = BLI_rctf_size_x(&pup->but->rect);
- }
- else {
- /* For buttons with no text, use the minimum (typically icon only). */
- minwidth = UI_MENU_WIDTH_MIN;
- }
-
- if (pup->block->direction != 0) {
- /* allow overriding the direction from menu_func */
- direction = pup->block->direction;
- }
- else {
- direction = UI_DIR_DOWN;
- }
- }
- else {
- minwidth = UI_MENU_WIDTH_MIN;
- direction = UI_DIR_DOWN;
- }
-
- flip = (direction == UI_DIR_DOWN);
-
- block = pup->block;
-
- /* in some cases we create the block before the region,
- * so we set it delayed here if necessary */
- if (BLI_findindex(&handle->region->uiblocks, block) == -1) {
- UI_block_region_set(block, handle->region);
- }
-
- block->direction = direction;
-
- UI_block_layout_resolve(block, &width, &height);
-
- UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT);
-
- if (pup->popup) {
- uiBut *bt;
- int offset[2];
-
- uiBut *but_activate = NULL;
- UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_NUMSELECT);
- UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
- UI_block_direction_set(block, direction);
-
- /* offset the mouse position, possibly based on earlier selection */
- if ((block->flag & UI_BLOCK_POPUP_MEMORY) &&
- (bt = ui_popup_menu_memory_get(block)))
- {
- /* position mouse on last clicked item, at 0.8*width of the
- * button, so it doesn't overlap the text too much, also note
- * the offset is negative because we are inverse moving the
- * block to be under the mouse */
- offset[0] = -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect));
- offset[1] = -(bt->rect.ymin + 0.5f * UI_UNIT_Y);
-
- if (ui_but_is_editable(bt)) {
- but_activate = bt;
- }
- }
- else {
- /* position mouse at 0.8*width of the button and below the tile
- * on the first item */
- offset[0] = 0;
- for (bt = block->buttons.first; bt; bt = bt->next) {
- offset[0] = min_ii(offset[0], -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect)));
- }
-
- offset[1] = 2.1 * UI_UNIT_Y;
-
- for (bt = block->buttons.first; bt; bt = bt->next) {
- if (ui_but_is_editable(bt)) {
- but_activate = bt;
- break;
- }
- }
- }
-
- /* in rare cases this is needed since moving the popup
- * to be within the window bounds may move it away from the mouse,
- * This ensures we set an item to be active. */
- if (but_activate) {
- ui_but_activate_over(C, handle->region, but_activate);
- }
-
- block->minbounds = minwidth;
- UI_block_bounds_set_menu(block, 1, offset);
- }
- 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 (ar->regiontype == RGN_TYPE_HEADER) {
- if (ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) {
- UI_block_direction_set(block, UI_DIR_UP);
- UI_block_order_flip(block);
- }
- }
- if (ar->regiontype == RGN_TYPE_FOOTER) {
- if (ED_area_footer_alignment(sa) == RGN_ALIGN_BOTTOM) {
- UI_block_direction_set(block, UI_DIR_UP);
- UI_block_order_flip(block);
- }
- }
- }
- }
-
- block->minbounds = minwidth;
- UI_block_bounds_set_text(block, 3.0f * UI_UNIT_X);
- }
-
- /* if menu slides out of other menu, override direction */
- if (pup->slideout) {
- UI_block_direction_set(block, UI_DIR_RIGHT);
- }
-
- return pup->block;
+ uiBlock *block;
+ uiPopupMenu *pup = arg_pup;
+ int minwidth, width, height;
+ char direction;
+ bool flip;
+
+ if (pup->menu_func) {
+ pup->block->handle = handle;
+ pup->menu_func(C, pup->layout, pup->menu_arg);
+ pup->block->handle = NULL;
+ }
+
+ if (pup->but) {
+ /* minimum width to enforece */
+ if (pup->but->drawstr[0]) {
+ minwidth = BLI_rctf_size_x(&pup->but->rect);
+ }
+ else {
+ /* For buttons with no text, use the minimum (typically icon only). */
+ minwidth = UI_MENU_WIDTH_MIN;
+ }
+
+ if (pup->block->direction != 0) {
+ /* allow overriding the direction from menu_func */
+ direction = pup->block->direction;
+ }
+ else {
+ direction = UI_DIR_DOWN;
+ }
+ }
+ else {
+ minwidth = UI_MENU_WIDTH_MIN;
+ direction = UI_DIR_DOWN;
+ }
+
+ flip = (direction == UI_DIR_DOWN);
+
+ block = pup->block;
+
+ /* in some cases we create the block before the region,
+ * so we set it delayed here if necessary */
+ if (BLI_findindex(&handle->region->uiblocks, block) == -1) {
+ UI_block_region_set(block, handle->region);
+ }
+
+ block->direction = direction;
+
+ UI_block_layout_resolve(block, &width, &height);
+
+ UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT);
+
+ if (pup->popup) {
+ uiBut *bt;
+ int offset[2];
+
+ uiBut *but_activate = NULL;
+ UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_NUMSELECT);
+ UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
+ UI_block_direction_set(block, direction);
+
+ /* offset the mouse position, possibly based on earlier selection */
+ if ((block->flag & UI_BLOCK_POPUP_MEMORY) && (bt = ui_popup_menu_memory_get(block))) {
+ /* position mouse on last clicked item, at 0.8*width of the
+ * button, so it doesn't overlap the text too much, also note
+ * the offset is negative because we are inverse moving the
+ * block to be under the mouse */
+ offset[0] = -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect));
+ offset[1] = -(bt->rect.ymin + 0.5f * UI_UNIT_Y);
+
+ if (ui_but_is_editable(bt)) {
+ but_activate = bt;
+ }
+ }
+ else {
+ /* position mouse at 0.8*width of the button and below the tile
+ * on the first item */
+ offset[0] = 0;
+ for (bt = block->buttons.first; bt; bt = bt->next) {
+ offset[0] = min_ii(offset[0], -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect)));
+ }
+
+ offset[1] = 2.1 * UI_UNIT_Y;
+
+ for (bt = block->buttons.first; bt; bt = bt->next) {
+ if (ui_but_is_editable(bt)) {
+ but_activate = bt;
+ break;
+ }
+ }
+ }
+
+ /* in rare cases this is needed since moving the popup
+ * to be within the window bounds may move it away from the mouse,
+ * This ensures we set an item to be active. */
+ if (but_activate) {
+ ui_but_activate_over(C, handle->region, but_activate);
+ }
+
+ block->minbounds = minwidth;
+ UI_block_bounds_set_menu(block, 1, offset);
+ }
+ 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 (ar->regiontype == RGN_TYPE_HEADER) {
+ if (ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) {
+ UI_block_direction_set(block, UI_DIR_UP);
+ UI_block_order_flip(block);
+ }
+ }
+ if (ar->regiontype == RGN_TYPE_FOOTER) {
+ if (ED_area_footer_alignment(sa) == RGN_ALIGN_BOTTOM) {
+ UI_block_direction_set(block, UI_DIR_UP);
+ UI_block_order_flip(block);
+ }
+ }
+ }
+ }
+
+ block->minbounds = minwidth;
+ UI_block_bounds_set_text(block, 3.0f * UI_UNIT_X);
+ }
+
+ /* if menu slides out of other menu, override direction */
+ if (pup->slideout) {
+ UI_block_direction_set(block, UI_DIR_RIGHT);
+ }
+
+ return pup->block;
}
uiPopupBlockHandle *ui_popup_menu_create(
- bContext *C, ARegion *butregion, uiBut *but,
- uiMenuCreateFunc menu_func, void *arg)
+ bContext *C, ARegion *butregion, uiBut *but, uiMenuCreateFunc menu_func, void *arg)
{
- wmWindow *window = CTX_wm_window(C);
- uiStyle *style = UI_style_get_dpi();
- uiPopupBlockHandle *handle;
- uiPopupMenu *pup;
-
- pup = MEM_callocN(sizeof(uiPopupMenu), __func__);
- pup->block = UI_block_begin(C, NULL, __func__, UI_EMBOSS_PULLDOWN);
- pup->block->flag |= UI_BLOCK_NUMSELECT; /* default menus to numselect */
- pup->layout = UI_block_layout(pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style);
- pup->slideout = but ? ui_block_is_menu(but->block) : false;
- pup->but = but;
- uiLayoutSetOperatorContext(pup->layout, WM_OP_INVOKE_REGION_WIN);
-
- if (!but) {
- /* no button to start from, means we are a popup */
- pup->mx = window->eventstate->x;
- pup->my = window->eventstate->y;
- pup->popup = true;
- pup->block->flag |= UI_BLOCK_NO_FLIP;
- }
- /* some enums reversing is strange, currently we have no good way to
- * reverse some enum's but not others, so reverse all so the first menu
- * items are always close to the mouse cursor */
- else {
+ wmWindow *window = CTX_wm_window(C);
+ uiStyle *style = UI_style_get_dpi();
+ uiPopupBlockHandle *handle;
+ uiPopupMenu *pup;
+
+ pup = MEM_callocN(sizeof(uiPopupMenu), __func__);
+ pup->block = UI_block_begin(C, NULL, __func__, UI_EMBOSS_PULLDOWN);
+ pup->block->flag |= UI_BLOCK_NUMSELECT; /* default menus to numselect */
+ pup->layout = UI_block_layout(
+ pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style);
+ pup->slideout = but ? ui_block_is_menu(but->block) : false;
+ pup->but = but;
+ uiLayoutSetOperatorContext(pup->layout, WM_OP_INVOKE_REGION_WIN);
+
+ if (!but) {
+ /* no button to start from, means we are a popup */
+ pup->mx = window->eventstate->x;
+ pup->my = window->eventstate->y;
+ pup->popup = true;
+ pup->block->flag |= UI_BLOCK_NO_FLIP;
+ }
+ /* some enums reversing is strange, currently we have no good way to
+ * reverse some enum's but not others, so reverse all so the first menu
+ * items are always close to the mouse cursor */
+ else {
#if 0
- /* if this is an rna button then we can assume its an enum
- * flipping enums is generally not good since the order can be
- * important [#28786] */
- if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) {
- pup->block->flag |= UI_BLOCK_NO_FLIP;
- }
+ /* if this is an rna button then we can assume its an enum
+ * flipping enums is generally not good since the order can be
+ * important [#28786] */
+ if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) {
+ pup->block->flag |= UI_BLOCK_NO_FLIP;
+ }
#endif
- if (but->context) {
- uiLayoutContextCopy(pup->layout, but->context);
- }
- }
+ if (but->context) {
+ uiLayoutContextCopy(pup->layout, but->context);
+ }
+ }
- /* menu is created from a callback */
- pup->menu_func = menu_func;
- pup->menu_arg = arg;
+ /* menu is created from a callback */
+ pup->menu_func = menu_func;
+ pup->menu_arg = arg;
- handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup);
+ handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup);
- if (!but) {
- handle->popup = true;
+ if (!but) {
+ handle->popup = true;
- UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
- WM_event_add_mousemove(C);
- }
+ UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
+ WM_event_add_mousemove(C);
+ }
- MEM_freeN(pup);
+ MEM_freeN(pup);
- return handle;
+ return handle;
}
/** \} */
@@ -376,48 +375,66 @@ uiPopupBlockHandle *ui_popup_menu_create(
* Only return handler, and set optional title.
* \param block_name: Assigned to uiBlock.name (useful info for debugging).
*/
-uiPopupMenu *UI_popup_menu_begin_ex(bContext *C, const char *title, const char *block_name, int icon)
+uiPopupMenu *UI_popup_menu_begin_ex(bContext *C,
+ const char *title,
+ const char *block_name,
+ int icon)
{
- uiStyle *style = UI_style_get_dpi();
- uiPopupMenu *pup = MEM_callocN(sizeof(uiPopupMenu), "popup menu");
- uiBut *but;
-
- pup->block = UI_block_begin(C, NULL, block_name, UI_EMBOSS_PULLDOWN);
- pup->block->flag |= UI_BLOCK_POPUP_MEMORY | UI_BLOCK_IS_FLIP;
- pup->block->puphash = ui_popup_menu_hash(title);
- pup->layout = UI_block_layout(pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style);
-
- /* note, this intentionally differs from the menu & submenu default because many operators
- * use popups like this to select one of their options -
- * where having invoke doesn't make sense */
- uiLayoutSetOperatorContext(pup->layout, WM_OP_EXEC_REGION_WIN);
-
- /* create in advance so we can let buttons point to retval already */
- pup->block->handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle");
-
- /* create title button */
- if (title[0]) {
- char titlestr[256];
-
- if (icon) {
- BLI_snprintf(titlestr, sizeof(titlestr), " %s", title);
- uiDefIconTextBut(
- pup->block, UI_BTYPE_LABEL, 0, icon, titlestr, 0, 0, 200, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- }
- else {
- but = uiDefBut(pup->block, UI_BTYPE_LABEL, 0, title, 0, 0, 200, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- but->drawflag = UI_BUT_TEXT_LEFT;
- }
-
- uiItemS(pup->layout);
- }
-
- return pup;
+ uiStyle *style = UI_style_get_dpi();
+ uiPopupMenu *pup = MEM_callocN(sizeof(uiPopupMenu), "popup menu");
+ uiBut *but;
+
+ pup->block = UI_block_begin(C, NULL, block_name, UI_EMBOSS_PULLDOWN);
+ pup->block->flag |= UI_BLOCK_POPUP_MEMORY | UI_BLOCK_IS_FLIP;
+ pup->block->puphash = ui_popup_menu_hash(title);
+ pup->layout = UI_block_layout(
+ pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style);
+
+ /* note, this intentionally differs from the menu & submenu default because many operators
+ * use popups like this to select one of their options -
+ * where having invoke doesn't make sense */
+ uiLayoutSetOperatorContext(pup->layout, WM_OP_EXEC_REGION_WIN);
+
+ /* create in advance so we can let buttons point to retval already */
+ pup->block->handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle");
+
+ /* create title button */
+ if (title[0]) {
+ char titlestr[256];
+
+ if (icon) {
+ BLI_snprintf(titlestr, sizeof(titlestr), " %s", title);
+ uiDefIconTextBut(pup->block,
+ UI_BTYPE_LABEL,
+ 0,
+ icon,
+ titlestr,
+ 0,
+ 0,
+ 200,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ }
+ else {
+ but = uiDefBut(
+ pup->block, UI_BTYPE_LABEL, 0, title, 0, 0, 200, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ but->drawflag = UI_BUT_TEXT_LEFT;
+ }
+
+ uiItemS(pup->layout);
+ }
+
+ return pup;
}
uiPopupMenu *UI_popup_menu_begin(bContext *C, const char *title, int icon)
{
- return UI_popup_menu_begin_ex(C, title, __func__, icon);
+ return UI_popup_menu_begin_ex(C, title, __func__, icon);
}
/**
@@ -425,54 +442,54 @@ uiPopupMenu *UI_popup_menu_begin(bContext *C, const char *title, int icon)
*/
void UI_popup_menu_but_set(uiPopupMenu *pup, struct ARegion *butregion, uiBut *but)
{
- pup->but = but;
- pup->butregion = butregion;
+ pup->but = but;
+ pup->butregion = butregion;
}
/* set the whole structure to work */
void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
{
- wmWindow *window = CTX_wm_window(C);
- uiPopupBlockHandle *menu;
- uiBut *but = NULL;
- ARegion *butregion = NULL;
+ wmWindow *window = CTX_wm_window(C);
+ uiPopupBlockHandle *menu;
+ uiBut *but = NULL;
+ ARegion *butregion = NULL;
- pup->popup = true;
- pup->mx = window->eventstate->x;
- pup->my = window->eventstate->y;
+ pup->popup = true;
+ pup->mx = window->eventstate->x;
+ pup->my = window->eventstate->y;
- if (pup->but) {
- but = pup->but;
- butregion = pup->butregion;
- }
+ if (pup->but) {
+ but = pup->but;
+ butregion = pup->butregion;
+ }
- menu = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup);
- menu->popup = true;
+ menu = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup);
+ menu->popup = true;
- UI_popup_handlers_add(C, &window->modalhandlers, menu, 0);
- WM_event_add_mousemove(C);
+ UI_popup_handlers_add(C, &window->modalhandlers, menu, 0);
+ WM_event_add_mousemove(C);
- MEM_freeN(pup);
+ MEM_freeN(pup);
}
bool UI_popup_menu_end_or_cancel(bContext *C, uiPopupMenu *pup)
{
- if (!UI_block_is_empty(pup->block)) {
- UI_popup_menu_end(C, pup);
- return true;
- }
- else {
- UI_block_layout_resolve(pup->block, NULL, NULL);
- MEM_freeN(pup->block->handle);
- UI_block_free(C, pup->block);
- MEM_freeN(pup);
- return false;
- }
+ if (!UI_block_is_empty(pup->block)) {
+ UI_popup_menu_end(C, pup);
+ return true;
+ }
+ else {
+ UI_block_layout_resolve(pup->block, NULL, NULL);
+ MEM_freeN(pup->block->handle);
+ UI_block_free(C, pup->block);
+ MEM_freeN(pup);
+ return false;
+ }
}
uiLayout *UI_popup_menu_layout(uiPopupMenu *pup)
{
- return pup->layout;
+ return pup->layout;
}
/** \} */
@@ -483,79 +500,79 @@ uiLayout *UI_popup_menu_layout(uiPopupMenu *pup)
void UI_popup_menu_reports(bContext *C, ReportList *reports)
{
- Report *report;
-
- uiPopupMenu *pup = NULL;
- uiLayout *layout;
-
- if (!CTX_wm_window(C)) {
- return;
- }
-
- for (report = reports->list.first; report; report = report->next) {
- int icon;
- const char *msg, *msg_next;
-
- if (report->type < reports->printlevel) {
- continue;
- }
-
- if (pup == NULL) {
- char title[UI_MAX_DRAW_STR];
- BLI_snprintf(title, sizeof(title), "%s: %s", IFACE_("Report"), report->typestr);
- /* popup_menu stuff does just what we need (but pass meaningful block name) */
- pup = UI_popup_menu_begin_ex(C, title, __func__, ICON_NONE);
- layout = UI_popup_menu_layout(pup);
- }
- else {
- uiItemS(layout);
- }
-
- /* split each newline into a label */
- msg = report->message;
- icon = UI_icon_from_report_type(report->type);
- do {
- char buf[UI_MAX_DRAW_STR];
- msg_next = strchr(msg, '\n');
- if (msg_next) {
- msg_next++;
- BLI_strncpy(buf, msg, MIN2(sizeof(buf), msg_next - msg));
- msg = buf;
- }
- uiItemL(layout, msg, icon);
- icon = ICON_NONE;
- } while ((msg = msg_next) && *msg);
- }
-
- if (pup) {
- UI_popup_menu_end(C, pup);
- }
+ Report *report;
+
+ uiPopupMenu *pup = NULL;
+ uiLayout *layout;
+
+ if (!CTX_wm_window(C)) {
+ return;
+ }
+
+ for (report = reports->list.first; report; report = report->next) {
+ int icon;
+ const char *msg, *msg_next;
+
+ if (report->type < reports->printlevel) {
+ continue;
+ }
+
+ if (pup == NULL) {
+ char title[UI_MAX_DRAW_STR];
+ BLI_snprintf(title, sizeof(title), "%s: %s", IFACE_("Report"), report->typestr);
+ /* popup_menu stuff does just what we need (but pass meaningful block name) */
+ pup = UI_popup_menu_begin_ex(C, title, __func__, ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ }
+ else {
+ uiItemS(layout);
+ }
+
+ /* split each newline into a label */
+ msg = report->message;
+ icon = UI_icon_from_report_type(report->type);
+ do {
+ char buf[UI_MAX_DRAW_STR];
+ msg_next = strchr(msg, '\n');
+ if (msg_next) {
+ msg_next++;
+ BLI_strncpy(buf, msg, MIN2(sizeof(buf), msg_next - msg));
+ msg = buf;
+ }
+ uiItemL(layout, msg, icon);
+ icon = ICON_NONE;
+ } while ((msg = msg_next) && *msg);
+ }
+
+ if (pup) {
+ UI_popup_menu_end(C, pup);
+ }
}
int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports)
{
- uiPopupMenu *pup;
- uiLayout *layout;
- MenuType *mt = WM_menutype_find(idname, true);
+ uiPopupMenu *pup;
+ uiLayout *layout;
+ MenuType *mt = WM_menutype_find(idname, true);
- if (mt == NULL) {
- BKE_reportf(reports, RPT_ERROR, "Menu \"%s\" not found", idname);
- return OPERATOR_CANCELLED;
- }
+ if (mt == NULL) {
+ BKE_reportf(reports, RPT_ERROR, "Menu \"%s\" not found", idname);
+ return OPERATOR_CANCELLED;
+ }
- if (WM_menutype_poll(C, mt) == false) {
- /* cancel but allow event to pass through, just like operators do */
- return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
- }
+ if (WM_menutype_poll(C, mt) == false) {
+ /* cancel but allow event to pass through, just like operators do */
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
- pup = UI_popup_menu_begin(C, IFACE_(mt->label), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
+ pup = UI_popup_menu_begin(C, IFACE_(mt->label), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
- UI_menutype_draw(C, mt, layout);
+ UI_menutype_draw(C, mt, layout);
- UI_popup_menu_end(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
/** \} */
@@ -564,104 +581,108 @@ int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports)
/** \name Popup Block API
* \{ */
-void UI_popup_block_invoke_ex(bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext)
+void UI_popup_block_invoke_ex(
+ bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext)
{
- wmWindow *window = CTX_wm_window(C);
- uiPopupBlockHandle *handle;
-
- handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg);
- handle->popup = true;
- handle->can_refresh = true;
- handle->optype = (opname) ? WM_operatortype_find(opname, 0) : NULL;
- handle->opcontext = opcontext;
-
- 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);
+ wmWindow *window = CTX_wm_window(C);
+ uiPopupBlockHandle *handle;
+
+ handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg);
+ handle->popup = true;
+ handle->can_refresh = true;
+ handle->optype = (opname) ? WM_operatortype_find(opname, 0) : NULL;
+ handle->opcontext = opcontext;
+
+ 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);
}
void UI_popup_block_invoke(bContext *C, uiBlockCreateFunc func, void *arg)
{
- UI_popup_block_invoke_ex(C, func, arg, NULL, WM_OP_INVOKE_DEFAULT);
+ UI_popup_block_invoke_ex(C, func, arg, NULL, WM_OP_INVOKE_DEFAULT);
}
-void UI_popup_block_ex(
- bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func,
- void *arg, wmOperator *op)
+void UI_popup_block_ex(bContext *C,
+ uiBlockCreateFunc func,
+ uiBlockHandleFunc popup_func,
+ uiBlockCancelFunc cancel_func,
+ void *arg,
+ wmOperator *op)
{
- wmWindow *window = CTX_wm_window(C);
- uiPopupBlockHandle *handle;
-
- handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg);
- handle->popup = true;
- handle->retvalue = 1;
- handle->can_refresh = true;
-
- handle->popup_op = op;
- handle->popup_arg = arg;
- handle->popup_func = popup_func;
- handle->cancel_func = cancel_func;
- // handle->opcontext = opcontext;
-
- 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);
+ wmWindow *window = CTX_wm_window(C);
+ uiPopupBlockHandle *handle;
+
+ handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg);
+ handle->popup = true;
+ handle->retvalue = 1;
+ handle->can_refresh = true;
+
+ handle->popup_op = op;
+ handle->popup_arg = arg;
+ handle->popup_func = popup_func;
+ handle->cancel_func = cancel_func;
+ // handle->opcontext = opcontext;
+
+ 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);
}
#if 0 /* UNUSED */
void uiPupBlockOperator(bContext *C, uiBlockCreateFunc func, wmOperator *op, int opcontext)
{
- wmWindow *window = CTX_wm_window(C);
- uiPopupBlockHandle *handle;
+ wmWindow *window = CTX_wm_window(C);
+ uiPopupBlockHandle *handle;
- handle = ui_popup_block_create(C, NULL, NULL, func, NULL, op);
- handle->popup = 1;
- handle->retvalue = 1;
- handle->can_refresh = true;
+ handle = ui_popup_block_create(C, NULL, NULL, func, NULL, op);
+ handle->popup = 1;
+ handle->retvalue = 1;
+ handle->can_refresh = true;
- handle->popup_arg = op;
- handle->popup_func = operator_cb;
- handle->cancel_func = confirm_cancel_operator;
- handle->opcontext = opcontext;
+ handle->popup_arg = op;
+ handle->popup_func = operator_cb;
+ handle->cancel_func = confirm_cancel_operator;
+ handle->opcontext = opcontext;
- UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
- WM_event_add_mousemove(C);
+ UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
+ WM_event_add_mousemove(C);
}
#endif
void UI_popup_block_close(bContext *C, wmWindow *win, uiBlock *block)
{
- /* if loading new .blend while popup is open, window will be NULL */
- if (block->handle) {
- if (win) {
- const bScreen *screen = WM_window_get_active_screen(win);
-
- UI_popup_handlers_remove(&win->modalhandlers, block->handle);
- ui_popup_block_free(C, block->handle);
-
- /* 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);
- }
- }
- }
+ /* if loading new .blend while popup is open, window will be NULL */
+ if (block->handle) {
+ if (win) {
+ const bScreen *screen = WM_window_get_active_screen(win);
+
+ UI_popup_handlers_remove(&win->modalhandlers, block->handle);
+ ui_popup_block_free(C, block->handle);
+
+ /* 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);
+ }
+ }
+ }
}
bool UI_popup_block_name_exists(bContext *C, 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) {
- if (STREQ(block->name, name)) {
- return true;
- }
- }
- }
- return false;
+ 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) {
+ if (STREQ(block->name, name)) {
+ return true;
+ }
+ }
+ }
+ return false;
}
/** \} */
diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c
index 7396b5406ed..bbf3df6a264 100644
--- a/source/blender/editors/interface/interface_region_popover.c
+++ b/source/blender/editors/interface/interface_region_popover.c
@@ -59,7 +59,6 @@
#include "WM_api.h"
#include "WM_types.h"
-
#include "UI_interface.h"
#include "interface_intern.h"
@@ -70,222 +69,227 @@
* \{ */
struct uiPopover {
- uiBlock *block;
- uiLayout *layout;
- uiBut *but;
+ uiBlock *block;
+ uiLayout *layout;
+ uiBut *but;
- /* Needed for keymap removal. */
- wmWindow *window;
- wmKeyMap *keymap;
- struct wmEventHandler_Keymap *keymap_handler;
+ /* Needed for keymap removal. */
+ wmWindow *window;
+ wmKeyMap *keymap;
+ struct wmEventHandler_Keymap *keymap_handler;
- uiMenuCreateFunc menu_func;
- void *menu_arg;
+ uiMenuCreateFunc menu_func;
+ void *menu_arg;
- /* Size in pixels (ui scale applied). */
- int ui_size_x;
+ /* Size in pixels (ui scale applied). */
+ int ui_size_x;
#ifdef USE_UI_POPOVER_ONCE
- bool is_once;
+ bool is_once;
#endif
};
static void ui_popover_create_block(bContext *C, uiPopover *pup, int opcontext)
{
- BLI_assert(pup->ui_size_x != 0);
+ BLI_assert(pup->ui_size_x != 0);
- uiStyle *style = UI_style_get_dpi();
+ 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);
+ pup->block = UI_block_begin(C, NULL, __func__, UI_EMBOSS);
+ UI_block_flag_enable(pup->block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_POPOVER);
#ifdef USE_UI_POPOVER_ONCE
- if (pup->is_once) {
- UI_block_flag_enable(pup->block, UI_BLOCK_POPOVER_ONCE);
- }
+ if (pup->is_once) {
+ UI_block_flag_enable(pup->block, UI_BLOCK_POPOVER_ONCE);
+ }
#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);
-
- uiLayoutSetOperatorContext(pup->layout, opcontext);
-
- if (pup->but) {
- if (pup->but->context) {
- uiLayoutContextCopy(pup->layout, pup->but->context);
- }
- }
-
- pup->block->flag |= UI_BLOCK_NO_FLIP;
+ pup->layout = UI_block_layout(pup->block,
+ UI_LAYOUT_VERTICAL,
+ UI_LAYOUT_PANEL,
+ 0,
+ 0,
+ pup->ui_size_x,
+ 0,
+ UI_MENU_PADDING,
+ style);
+
+ uiLayoutSetOperatorContext(pup->layout, opcontext);
+
+ if (pup->but) {
+ if (pup->but->context) {
+ uiLayoutContextCopy(pup->layout, pup->but->context);
+ }
+ }
+
+ pup->block->flag |= UI_BLOCK_NO_FLIP;
}
static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, void *arg_pup)
{
- uiPopover *pup = arg_pup;
-
- /* Create UI block and layout now if it wasn't done between begin/end. */
- if (!pup->layout) {
- ui_popover_create_block(C, pup, WM_OP_INVOKE_REGION_WIN);
-
- if (pup->menu_func) {
- pup->block->handle = handle;
- pup->menu_func(C, pup->layout, pup->menu_arg);
- pup->block->handle = NULL;
- }
-
- pup->layout = NULL;
- }
-
- /* Setup and resolve UI layout for block. */
- uiBlock *block = pup->block;
- int width, height;
-
- UI_block_region_set(block, handle->region);
- UI_block_layout_resolve(block, &width, &height);
- UI_block_direction_set(block, UI_DIR_DOWN | UI_DIR_CENTER_X);
-
- const int block_margin = U.widget_unit / 2;
-
- if (pup->but) {
- /* For a header menu we set the direction automatic. */
- block->minbounds = BLI_rctf_size_x(&pup->but->rect);
- UI_block_bounds_set_normal(block, block_margin);
-
- /* If menu slides out of other menu, override direction. */
- bool slideout = ui_block_is_menu(pup->but->block);
- if (slideout) {
- UI_block_direction_set(block, UI_DIR_RIGHT);
- }
-
- /* Store the button location for positioning the popover arrow hint. */
- if (!handle->refresh) {
- float center[2] = {BLI_rctf_cent_x(&pup->but->rect), BLI_rctf_cent_y(&pup->but->rect)};
- ui_block_to_window_fl(handle->ctx_region, pup->but->block, &center[0], &center[1]);
- /* These variables aren't used for popovers,
- * we could add new variables if there is a conflict. */
- block->bounds_offset[0] = (int)center[0];
- block->bounds_offset[1] = (int)center[1];
- copy_v2_v2_int(handle->prev_bounds_offset, block->bounds_offset);
- }
- else {
- copy_v2_v2_int(block->bounds_offset, handle->prev_bounds_offset);
- }
-
- if (!slideout) {
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
-
- if (ar && ar->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 (ar->regiontype == RGN_TYPE_HEADER) {
- if (ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) {
- UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X);
- }
- }
- if (ar->regiontype == RGN_TYPE_FOOTER) {
- if (ED_area_footer_alignment(sa) == RGN_ALIGN_BOTTOM) {
- UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X);
- }
- }
- }
- }
-
- /* Estimated a maximum size so we don't go offscreen for low height
- * areas near the bottom of the window on refreshes. */
- handle->max_size_y = UI_UNIT_Y * 16.0f;
- }
- else {
- /* Not attached to a button. */
- int bounds_offset[2] = {0, 0};
- UI_block_flag_enable(block, UI_BLOCK_LOOP);
- UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
- UI_block_direction_set(block, block->direction);
- block->minbounds = UI_MENU_WIDTH_MIN;
-
- if (!handle->refresh) {
- uiBut *but = NULL;
- uiBut *but_first = NULL;
- for (but = block->buttons.first; but; but = but->next) {
- if ((but_first == NULL) && ui_but_is_editable(but)) {
- but_first = but;
- }
- if (but->flag & (UI_SELECT | UI_SELECT_DRAW)) {
- break;
- }
- }
-
- if (but) {
- bounds_offset[0] = -(but->rect.xmin + 0.8f * BLI_rctf_size_x(&but->rect));
- bounds_offset[1] = -BLI_rctf_cent_y(&but->rect);
- }
- else {
- bounds_offset[0] = -(pup->ui_size_x / 2);
- bounds_offset[1] = but_first ? -BLI_rctf_cent_y(&but_first->rect) : (UI_UNIT_Y / 2);
- }
- copy_v2_v2_int(handle->prev_bounds_offset, bounds_offset);
- }
- else {
- copy_v2_v2_int(bounds_offset, handle->prev_bounds_offset);
- }
-
- UI_block_bounds_set_popup(block, block_margin, bounds_offset);
- }
-
- return block;
+ uiPopover *pup = arg_pup;
+
+ /* Create UI block and layout now if it wasn't done between begin/end. */
+ if (!pup->layout) {
+ ui_popover_create_block(C, pup, WM_OP_INVOKE_REGION_WIN);
+
+ if (pup->menu_func) {
+ pup->block->handle = handle;
+ pup->menu_func(C, pup->layout, pup->menu_arg);
+ pup->block->handle = NULL;
+ }
+
+ pup->layout = NULL;
+ }
+
+ /* Setup and resolve UI layout for block. */
+ uiBlock *block = pup->block;
+ int width, height;
+
+ UI_block_region_set(block, handle->region);
+ UI_block_layout_resolve(block, &width, &height);
+ UI_block_direction_set(block, UI_DIR_DOWN | UI_DIR_CENTER_X);
+
+ const int block_margin = U.widget_unit / 2;
+
+ if (pup->but) {
+ /* For a header menu we set the direction automatic. */
+ block->minbounds = BLI_rctf_size_x(&pup->but->rect);
+ UI_block_bounds_set_normal(block, block_margin);
+
+ /* If menu slides out of other menu, override direction. */
+ bool slideout = ui_block_is_menu(pup->but->block);
+ if (slideout) {
+ UI_block_direction_set(block, UI_DIR_RIGHT);
+ }
+
+ /* Store the button location for positioning the popover arrow hint. */
+ if (!handle->refresh) {
+ float center[2] = {BLI_rctf_cent_x(&pup->but->rect), BLI_rctf_cent_y(&pup->but->rect)};
+ ui_block_to_window_fl(handle->ctx_region, pup->but->block, &center[0], &center[1]);
+ /* These variables aren't used for popovers,
+ * we could add new variables if there is a conflict. */
+ block->bounds_offset[0] = (int)center[0];
+ block->bounds_offset[1] = (int)center[1];
+ copy_v2_v2_int(handle->prev_bounds_offset, block->bounds_offset);
+ }
+ else {
+ copy_v2_v2_int(block->bounds_offset, handle->prev_bounds_offset);
+ }
+
+ if (!slideout) {
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ if (ar && ar->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 (ar->regiontype == RGN_TYPE_HEADER) {
+ if (ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) {
+ UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X);
+ }
+ }
+ if (ar->regiontype == RGN_TYPE_FOOTER) {
+ if (ED_area_footer_alignment(sa) == RGN_ALIGN_BOTTOM) {
+ UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X);
+ }
+ }
+ }
+ }
+
+ /* Estimated a maximum size so we don't go offscreen for low height
+ * areas near the bottom of the window on refreshes. */
+ handle->max_size_y = UI_UNIT_Y * 16.0f;
+ }
+ else {
+ /* Not attached to a button. */
+ int bounds_offset[2] = {0, 0};
+ UI_block_flag_enable(block, UI_BLOCK_LOOP);
+ UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
+ UI_block_direction_set(block, block->direction);
+ block->minbounds = UI_MENU_WIDTH_MIN;
+
+ if (!handle->refresh) {
+ uiBut *but = NULL;
+ uiBut *but_first = NULL;
+ for (but = block->buttons.first; but; but = but->next) {
+ if ((but_first == NULL) && ui_but_is_editable(but)) {
+ but_first = but;
+ }
+ if (but->flag & (UI_SELECT | UI_SELECT_DRAW)) {
+ break;
+ }
+ }
+
+ if (but) {
+ bounds_offset[0] = -(but->rect.xmin + 0.8f * BLI_rctf_size_x(&but->rect));
+ bounds_offset[1] = -BLI_rctf_cent_y(&but->rect);
+ }
+ else {
+ bounds_offset[0] = -(pup->ui_size_x / 2);
+ bounds_offset[1] = but_first ? -BLI_rctf_cent_y(&but_first->rect) : (UI_UNIT_Y / 2);
+ }
+ copy_v2_v2_int(handle->prev_bounds_offset, bounds_offset);
+ }
+ else {
+ copy_v2_v2_int(bounds_offset, handle->prev_bounds_offset);
+ }
+
+ UI_block_bounds_set_popup(block, block_margin, bounds_offset);
+ }
+
+ return block;
}
static void ui_block_free_func_POPOVER(uiPopupBlockHandle *UNUSED(handle), void *arg_pup)
{
- uiPopover *pup = arg_pup;
- if (pup->keymap != NULL) {
- wmWindow *window = pup->window;
- WM_event_remove_keymap_handler(&window->modalhandlers, pup->keymap);
- }
- MEM_freeN(pup);
+ uiPopover *pup = arg_pup;
+ if (pup->keymap != NULL) {
+ wmWindow *window = pup->window;
+ WM_event_remove_keymap_handler(&window->modalhandlers, pup->keymap);
+ }
+ MEM_freeN(pup);
}
uiPopupBlockHandle *ui_popover_panel_create(
- bContext *C, ARegion *butregion, uiBut *but,
- uiMenuCreateFunc menu_func, void *arg)
+ bContext *C, ARegion *butregion, uiBut *but, uiMenuCreateFunc menu_func, void *arg)
{
- /* Create popover, buttons are created from callback. */
- uiPopover *pup = MEM_callocN(sizeof(uiPopover), __func__);
- pup->but = but;
+ /* Create popover, buttons are created from callback. */
+ uiPopover *pup = MEM_callocN(sizeof(uiPopover), __func__);
+ pup->but = but;
- /* FIXME: maybe one day we want non panel popovers? */
- {
- int ui_units_x = ((PanelType *)arg)->ui_units_x;
- pup->ui_size_x = U.widget_unit * (ui_units_x ? ui_units_x : UI_POPOVER_WIDTH_UNITS);
- }
+ /* FIXME: maybe one day we want non panel popovers? */
+ {
+ int ui_units_x = ((PanelType *)arg)->ui_units_x;
+ pup->ui_size_x = U.widget_unit * (ui_units_x ? ui_units_x : UI_POPOVER_WIDTH_UNITS);
+ }
- pup->menu_func = menu_func;
- pup->menu_arg = arg;
+ pup->menu_func = menu_func;
+ pup->menu_arg = arg;
#ifdef USE_UI_POPOVER_ONCE
- pup->is_once = true;
+ pup->is_once = true;
#endif
- /* Create popup block. */
- uiPopupBlockHandle *handle;
- handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPOVER, pup);
- handle->popup_create_vars.free_func = ui_block_free_func_POPOVER;
- handle->can_refresh = true;
-
- /* Add handlers. If attached to a button, the button will already
- * add a modal handler and pass on events. */
- if (!but) {
- wmWindow *window = CTX_wm_window(C);
- UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
- WM_event_add_mousemove(C);
- handle->popup = true;
- }
-
- return handle;
+ /* Create popup block. */
+ uiPopupBlockHandle *handle;
+ handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPOVER, pup);
+ handle->popup_create_vars.free_func = ui_block_free_func_POPOVER;
+ handle->can_refresh = true;
+
+ /* Add handlers. If attached to a button, the button will already
+ * add a modal handler and pass on events. */
+ if (!but) {
+ wmWindow *window = CTX_wm_window(C);
+ UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
+ WM_event_add_mousemove(C);
+ handle->popup = true;
+ }
+
+ return handle;
}
/** \} */
@@ -294,41 +298,39 @@ uiPopupBlockHandle *ui_popover_panel_create(
/** \name Standard Popover Panels
* \{ */
-int UI_popover_panel_invoke(
- bContext *C, const char *idname,
- bool keep_open, ReportList *reports)
+int UI_popover_panel_invoke(bContext *C, const char *idname, bool keep_open, ReportList *reports)
{
- uiLayout *layout;
- PanelType *pt = WM_paneltype_find(idname, true);
- if (pt == NULL) {
- BKE_reportf(reports, RPT_ERROR, "Panel \"%s\" not found", idname);
- return OPERATOR_CANCELLED;
- }
-
- if (pt->poll && (pt->poll(C, pt) == false)) {
- /* cancel but allow event to pass through, just like operators do */
- return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
- }
-
- uiBlock *block = NULL;
- if (keep_open) {
- uiPopupBlockHandle *handle = ui_popover_panel_create(C, NULL, NULL, ui_item_paneltype_func, pt);
- uiPopover *pup = handle->popup_create_vars.arg;
- block = pup->block;
-
- }
- else {
- uiPopover *pup = UI_popover_begin(C, U.widget_unit * pt->ui_units_x);
- layout = UI_popover_layout(pup);
- UI_paneltype_draw(C, pt, layout);
- UI_popover_end(C, pup, NULL);
- block = pup->block;
- }
-
- if (block) {
- UI_block_active_only_flagged_buttons(C, CTX_wm_region(C), block);
- }
- return OPERATOR_INTERFACE;
+ uiLayout *layout;
+ PanelType *pt = WM_paneltype_find(idname, true);
+ if (pt == NULL) {
+ BKE_reportf(reports, RPT_ERROR, "Panel \"%s\" not found", idname);
+ return OPERATOR_CANCELLED;
+ }
+
+ if (pt->poll && (pt->poll(C, pt) == false)) {
+ /* cancel but allow event to pass through, just like operators do */
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+ uiBlock *block = NULL;
+ if (keep_open) {
+ uiPopupBlockHandle *handle = ui_popover_panel_create(
+ C, NULL, NULL, ui_item_paneltype_func, pt);
+ uiPopover *pup = handle->popup_create_vars.arg;
+ block = pup->block;
+ }
+ else {
+ uiPopover *pup = UI_popover_begin(C, U.widget_unit * pt->ui_units_x);
+ layout = UI_popover_layout(pup);
+ UI_paneltype_draw(C, pt, layout);
+ UI_popover_end(C, pup, NULL);
+ block = pup->block;
+ }
+
+ if (block) {
+ UI_block_active_only_flagged_buttons(C, CTX_wm_region(C), block);
+ }
+ return OPERATOR_INTERFACE;
}
/** \} */
@@ -342,77 +344,77 @@ int UI_popover_panel_invoke(
*/
uiPopover *UI_popover_begin(bContext *C, int ui_size_x)
{
- uiPopover *pup = MEM_callocN(sizeof(uiPopover), "popover menu");
- if (ui_size_x == 0) {
- ui_size_x = U.widget_unit * UI_POPOVER_WIDTH_UNITS;
- }
- pup->ui_size_x = ui_size_x;
+ uiPopover *pup = MEM_callocN(sizeof(uiPopover), "popover menu");
+ if (ui_size_x == 0) {
+ ui_size_x = U.widget_unit * UI_POPOVER_WIDTH_UNITS;
+ }
+ pup->ui_size_x = ui_size_x;
- /* Opertor context default same as menus, change if needed. */
- ui_popover_create_block(C, pup, WM_OP_EXEC_REGION_WIN);
+ /* Opertor context default same as menus, change if needed. */
+ ui_popover_create_block(C, pup, WM_OP_EXEC_REGION_WIN);
- /* create in advance so we can let buttons point to retval already */
- pup->block->handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle");
+ /* create in advance so we can let buttons point to retval already */
+ pup->block->handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle");
- return pup;
+ return pup;
}
static void popover_keymap_fn(wmKeyMap *UNUSED(keymap), wmKeyMapItem *UNUSED(kmi), void *user_data)
{
- uiPopover *pup = user_data;
- pup->block->handle->menuretval = UI_RETURN_OK;
+ uiPopover *pup = user_data;
+ pup->block->handle->menuretval = UI_RETURN_OK;
}
/* set the whole structure to work */
void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap)
{
- wmWindow *window = CTX_wm_window(C);
- /* Create popup block. No refresh support since the buttons were created
- * between begin/end and we have no callback to recreate them. */
- uiPopupBlockHandle *handle;
-
- if (keymap) {
- /* Add so we get keymaps shown in the buttons. */
- UI_block_flag_enable(pup->block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS);
- pup->keymap = keymap;
- pup->keymap_handler = WM_event_add_keymap_handler_priority(&window->modalhandlers, keymap, 0);
- WM_event_set_keymap_handler_post_callback(pup->keymap_handler, popover_keymap_fn, pup);
- }
-
- handle = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_POPOVER, pup);
- handle->popup_create_vars.free_func = ui_block_free_func_POPOVER;
-
- /* Add handlers. */
- UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
- WM_event_add_mousemove(C);
- handle->popup = true;
-
- /* Re-add so it gets priority. */
- if (keymap) {
- BLI_remlink(&window->modalhandlers, pup->keymap_handler);
- BLI_addhead(&window->modalhandlers, pup->keymap_handler);
- }
-
- pup->window = window;
-
- /* TODO(campbell): we may want to make this configurable.
- * The begin/end stype of calling popups doesn't allow to 'can_refresh' to be set.
- * For now close this style of popvers when accessed. */
- UI_block_flag_disable(pup->block, UI_BLOCK_KEEP_OPEN);
-
- /* panels are created flipped (from event handling pov) */
- pup->block->flag ^= UI_BLOCK_IS_FLIP;
+ wmWindow *window = CTX_wm_window(C);
+ /* Create popup block. No refresh support since the buttons were created
+ * between begin/end and we have no callback to recreate them. */
+ uiPopupBlockHandle *handle;
+
+ if (keymap) {
+ /* Add so we get keymaps shown in the buttons. */
+ UI_block_flag_enable(pup->block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS);
+ pup->keymap = keymap;
+ pup->keymap_handler = WM_event_add_keymap_handler_priority(&window->modalhandlers, keymap, 0);
+ WM_event_set_keymap_handler_post_callback(pup->keymap_handler, popover_keymap_fn, pup);
+ }
+
+ handle = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_POPOVER, pup);
+ handle->popup_create_vars.free_func = ui_block_free_func_POPOVER;
+
+ /* Add handlers. */
+ UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
+ WM_event_add_mousemove(C);
+ handle->popup = true;
+
+ /* Re-add so it gets priority. */
+ if (keymap) {
+ BLI_remlink(&window->modalhandlers, pup->keymap_handler);
+ BLI_addhead(&window->modalhandlers, pup->keymap_handler);
+ }
+
+ pup->window = window;
+
+ /* TODO(campbell): we may want to make this configurable.
+ * The begin/end stype of calling popups doesn't allow to 'can_refresh' to be set.
+ * For now close this style of popvers when accessed. */
+ UI_block_flag_disable(pup->block, UI_BLOCK_KEEP_OPEN);
+
+ /* panels are created flipped (from event handling pov) */
+ pup->block->flag ^= UI_BLOCK_IS_FLIP;
}
uiLayout *UI_popover_layout(uiPopover *pup)
{
- return pup->layout;
+ return pup->layout;
}
#ifdef USE_UI_POPOVER_ONCE
void UI_popover_once_clear(uiPopover *pup)
{
- pup->is_once = false;
+ pup->is_once = false;
}
#endif
diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c
index 59223970af8..11b2e069d6c 100644
--- a/source/blender/editors/interface/interface_region_popup.c
+++ b/source/blender/editors/interface/interface_region_popup.c
@@ -59,256 +59,305 @@
*/
void ui_popup_translate(ARegion *ar, const int mdiff[2])
{
- uiBlock *block;
+ uiBlock *block;
- BLI_rcti_translate(&ar->winrct, UNPACK2(mdiff));
+ BLI_rcti_translate(&ar->winrct, UNPACK2(mdiff));
- ED_region_update_rect(ar);
+ ED_region_update_rect(ar);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- /* update blocks */
- for (block = ar->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);
+ /* update blocks */
+ for (block = ar->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);
- uiSafetyRct *saferct;
- for (saferct = block->saferct.first; saferct; saferct = saferct->next) {
- BLI_rctf_translate(&saferct->parent, UNPACK2(mdiff));
- BLI_rctf_translate(&saferct->safety, UNPACK2(mdiff));
- }
- }
+ uiSafetyRct *saferct;
+ for (saferct = block->saferct.first; saferct; saferct = saferct->next) {
+ BLI_rctf_translate(&saferct->parent, UNPACK2(mdiff));
+ BLI_rctf_translate(&saferct->safety, UNPACK2(mdiff));
+ }
+ }
}
/* position block relative to but, result is in window space */
-static void ui_popup_block_position(wmWindow *window, ARegion *butregion, uiBut *but, uiBlock *block)
+static void ui_popup_block_position(wmWindow *window,
+ ARegion *butregion,
+ uiBut *but,
+ uiBlock *block)
{
- uiPopupBlockHandle *handle = block->handle;
-
- /* Compute button position in window coordinates using the source
- * button region/block, to position the popup attached to it. */
- rctf butrct;
-
- if (!handle->refresh) {
- ui_block_to_window_rctf(butregion, but->block, &butrct, &but->rect);
-
- /* widget_roundbox_set has this correction too, keep in sync */
- if (but->type != UI_BTYPE_PULLDOWN) {
- if (but->drawflag & UI_BUT_ALIGN_TOP) {
- butrct.ymax += U.pixelsize;
- }
- if (but->drawflag & UI_BUT_ALIGN_LEFT) {
- butrct.xmin -= U.pixelsize;
- }
- }
-
- handle->prev_butrct = butrct;
- }
- else {
- /* For refreshes, keep same button position so popup doesn't move. */
- butrct = handle->prev_butrct;
- }
-
- /* Compute block size in window space, based on buttons contained in it. */
- if (block->rect.xmin == 0.0f && block->rect.xmax == 0.0f) {
- if (block->buttons.first) {
- BLI_rctf_init_minmax(&block->rect);
-
- for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
- if (block->content_hints & UI_BLOCK_CONTAINS_SUBMENU_BUT) {
- bt->rect.xmax += UI_MENU_SUBMENU_PADDING;
- }
- BLI_rctf_union(&block->rect, &bt->rect);
- }
- }
- else {
- /* we're nice and allow empty blocks too */
- block->rect.xmin = block->rect.ymin = 0;
- block->rect.xmax = block->rect.ymax = 20;
- }
- }
-
- ui_block_to_window_rctf(butregion, but->block, &block->rect, &block->rect);
-
- /* Compute direction relative to button, based on available space. */
- const int size_x = BLI_rctf_size_x(&block->rect) + 0.2f * UI_UNIT_X; /* 4 for shadow */
- const int size_y = BLI_rctf_size_y(&block->rect) + 0.2f * UI_UNIT_Y;
- const int center_x = (block->direction & UI_DIR_CENTER_X) ? size_x / 2 : 0;
- const int center_y = (block->direction & UI_DIR_CENTER_Y) ? size_y / 2 : 0;
-
- short dir1 = 0, dir2 = 0;
-
- if (!handle->refresh) {
- bool left = 0, right = 0, top = 0, down = 0;
-
- const int win_x = WM_window_pixels_x(window);
- const int win_y = WM_window_pixels_y(window);
-
- /* Take into account maximum size so we don't have to flip on refresh. */
- const float max_size_x = max_ff(size_x, handle->max_size_x);
- const float max_size_y = max_ff(size_y, handle->max_size_y);
-
- /* check if there's space at all */
- if (butrct.xmin - max_size_x + center_x > 0.0f) { left = 1; }
- if (butrct.xmax + max_size_x - center_x < win_x) { right = 1; }
- if (butrct.ymin - max_size_y + center_y > 0.0f) { down = 1; }
- if (butrct.ymax + max_size_y - center_y < win_y) { top = 1; }
-
- if (top == 0 && down == 0) {
- if (butrct.ymin - max_size_y < win_y - butrct.ymax - max_size_y) {
- top = 1;
- }
- else {
- down = 1;
- }
- }
-
- dir1 = (block->direction & UI_DIR_ALL);
-
- /* Secondary directions. */
- if (dir1 & (UI_DIR_UP | UI_DIR_DOWN)) {
- if (dir1 & UI_DIR_LEFT) { dir2 = UI_DIR_LEFT; }
- else if (dir1 & UI_DIR_RIGHT) { dir2 = UI_DIR_RIGHT; }
- dir1 &= (UI_DIR_UP | UI_DIR_DOWN);
- }
-
- if ((dir2 == 0) && (dir1 == UI_DIR_LEFT || dir1 == UI_DIR_RIGHT)) { dir2 = UI_DIR_DOWN; }
- if ((dir2 == 0) && (dir1 == UI_DIR_UP || dir1 == UI_DIR_DOWN)) { dir2 = UI_DIR_LEFT; }
-
- /* no space at all? don't change */
- if (left || right) {
- if (dir1 == UI_DIR_LEFT && left == 0) { dir1 = UI_DIR_RIGHT; }
- if (dir1 == UI_DIR_RIGHT && right == 0) { dir1 = UI_DIR_LEFT; }
- /* this is aligning, not append! */
- if (dir2 == UI_DIR_LEFT && right == 0) { dir2 = UI_DIR_RIGHT; }
- if (dir2 == UI_DIR_RIGHT && left == 0) { dir2 = UI_DIR_LEFT; }
- }
- if (down || top) {
- if (dir1 == UI_DIR_UP && top == 0) { dir1 = UI_DIR_DOWN; }
- if (dir1 == UI_DIR_DOWN && down == 0) { dir1 = UI_DIR_UP; }
- BLI_assert(dir2 != UI_DIR_UP);
-// if (dir2 == UI_DIR_UP && top == 0) { dir2 = UI_DIR_DOWN; }
- if (dir2 == UI_DIR_DOWN && down == 0) { dir2 = UI_DIR_UP; }
- }
-
- handle->prev_dir1 = dir1;
- handle->prev_dir2 = dir2;
- }
- else {
- /* For refreshes, keep same popup direct so popup doesn't move
- * to a totally different position while editing in it. */
- dir1 = handle->prev_dir1;
- dir2 = handle->prev_dir2;
- }
-
- /* Compute offset based on direction. */
- int offset_x = 0, offset_y = 0;
-
- if (dir1 == UI_DIR_LEFT) {
- offset_x = butrct.xmin - block->rect.xmax;
- if (dir2 == UI_DIR_UP) { offset_y = butrct.ymin - block->rect.ymin - center_y - UI_MENU_PADDING; }
- else { offset_y = butrct.ymax - block->rect.ymax + center_y + UI_MENU_PADDING; }
- }
- else if (dir1 == UI_DIR_RIGHT) {
- offset_x = butrct.xmax - block->rect.xmin;
- if (dir2 == UI_DIR_UP) { offset_y = butrct.ymin - block->rect.ymin - center_y - UI_MENU_PADDING; }
- else { offset_y = butrct.ymax - block->rect.ymax + center_y + UI_MENU_PADDING; }
- }
- else if (dir1 == UI_DIR_UP) {
- offset_y = butrct.ymax - block->rect.ymin;
- if (dir2 == UI_DIR_RIGHT) { offset_x = butrct.xmax - block->rect.xmax + center_x; }
- else { offset_x = butrct.xmin - block->rect.xmin - center_x; }
- /* changed direction? */
- if ((dir1 & block->direction) == 0) {
- /* TODO: still do */
- UI_block_order_flip(block);
- }
- }
- else if (dir1 == UI_DIR_DOWN) {
- offset_y = butrct.ymin - block->rect.ymax;
- if (dir2 == UI_DIR_RIGHT) { offset_x = butrct.xmax - block->rect.xmax + center_x; }
- else { offset_x = butrct.xmin - block->rect.xmin - center_x; }
- /* changed direction? */
- if ((dir1 & block->direction) == 0) {
- /* TODO: still do */
- UI_block_order_flip(block);
- }
- }
-
- /* Center over popovers for eg. */
- if (block->direction & UI_DIR_CENTER_X) {
- offset_x += BLI_rctf_size_x(&butrct) / ((dir2 == UI_DIR_LEFT) ? 2 : - 2);
- }
-
- /* Apply offset, buttons in window coords. */
- for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
- ui_block_to_window_rctf(butregion, but->block, &bt->rect, &bt->rect);
-
- BLI_rctf_translate(&bt->rect, offset_x, offset_y);
-
- /* ui_but_update recalculates drawstring size in pixels */
- ui_but_update(bt);
- }
-
- BLI_rctf_translate(&block->rect, offset_x, offset_y);
-
- /* Safety calculus. */
- {
- const float midx = BLI_rctf_cent_x(&butrct);
- const float midy = BLI_rctf_cent_y(&butrct);
-
- /* when you are outside parent button, safety there should be smaller */
-
- /* parent button to left */
- if (midx < block->rect.xmin) {
- block->safety.xmin = block->rect.xmin - 3;
- }
- else {
- block->safety.xmin = block->rect.xmin - 40;
- }
- /* parent button to right */
- if (midx > block->rect.xmax) {
- block->safety.xmax = block->rect.xmax + 3;
- }
- else {
- block->safety.xmax = block->rect.xmax + 40;
- }
-
- /* parent button on bottom */
- if (midy < block->rect.ymin) {
- block->safety.ymin = block->rect.ymin - 3;
- }
- else {
- block->safety.ymin = block->rect.ymin - 40;
- }
- /* parent button on top */
- if (midy > block->rect.ymax) {
- block->safety.ymax = block->rect.ymax + 3;
- }
- else {
- block->safety.ymax = block->rect.ymax + 40;
- }
-
- /* exception for switched pulldowns... */
- if (dir1 && (dir1 & block->direction) == 0) {
- if (dir2 == UI_DIR_RIGHT) {
- block->safety.xmax = block->rect.xmax + 3;
- }
- if (dir2 == UI_DIR_LEFT) {
- block->safety.xmin = block->rect.xmin - 3;
- }
- }
- block->direction = dir1;
- }
-
- /* keep a list of these, needed for pulldown menus */
- uiSafetyRct *saferct = MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct");
- saferct->parent = butrct;
- saferct->safety = block->safety;
- BLI_freelistN(&block->saferct);
- BLI_duplicatelist(&block->saferct, &but->block->saferct);
- BLI_addhead(&block->saferct, saferct);
+ uiPopupBlockHandle *handle = block->handle;
+
+ /* Compute button position in window coordinates using the source
+ * button region/block, to position the popup attached to it. */
+ rctf butrct;
+
+ if (!handle->refresh) {
+ ui_block_to_window_rctf(butregion, but->block, &butrct, &but->rect);
+
+ /* widget_roundbox_set has this correction too, keep in sync */
+ if (but->type != UI_BTYPE_PULLDOWN) {
+ if (but->drawflag & UI_BUT_ALIGN_TOP) {
+ butrct.ymax += U.pixelsize;
+ }
+ if (but->drawflag & UI_BUT_ALIGN_LEFT) {
+ butrct.xmin -= U.pixelsize;
+ }
+ }
+
+ handle->prev_butrct = butrct;
+ }
+ else {
+ /* For refreshes, keep same button position so popup doesn't move. */
+ butrct = handle->prev_butrct;
+ }
+
+ /* Compute block size in window space, based on buttons contained in it. */
+ if (block->rect.xmin == 0.0f && block->rect.xmax == 0.0f) {
+ if (block->buttons.first) {
+ BLI_rctf_init_minmax(&block->rect);
+
+ for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
+ if (block->content_hints & UI_BLOCK_CONTAINS_SUBMENU_BUT) {
+ bt->rect.xmax += UI_MENU_SUBMENU_PADDING;
+ }
+ BLI_rctf_union(&block->rect, &bt->rect);
+ }
+ }
+ else {
+ /* we're nice and allow empty blocks too */
+ block->rect.xmin = block->rect.ymin = 0;
+ block->rect.xmax = block->rect.ymax = 20;
+ }
+ }
+
+ ui_block_to_window_rctf(butregion, but->block, &block->rect, &block->rect);
+
+ /* Compute direction relative to button, based on available space. */
+ const int size_x = BLI_rctf_size_x(&block->rect) + 0.2f * UI_UNIT_X; /* 4 for shadow */
+ const int size_y = BLI_rctf_size_y(&block->rect) + 0.2f * UI_UNIT_Y;
+ const int center_x = (block->direction & UI_DIR_CENTER_X) ? size_x / 2 : 0;
+ const int center_y = (block->direction & UI_DIR_CENTER_Y) ? size_y / 2 : 0;
+
+ short dir1 = 0, dir2 = 0;
+
+ if (!handle->refresh) {
+ bool left = 0, right = 0, top = 0, down = 0;
+
+ const int win_x = WM_window_pixels_x(window);
+ const int win_y = WM_window_pixels_y(window);
+
+ /* Take into account maximum size so we don't have to flip on refresh. */
+ const float max_size_x = max_ff(size_x, handle->max_size_x);
+ const float max_size_y = max_ff(size_y, handle->max_size_y);
+
+ /* check if there's space at all */
+ if (butrct.xmin - max_size_x + center_x > 0.0f) {
+ left = 1;
+ }
+ if (butrct.xmax + max_size_x - center_x < win_x) {
+ right = 1;
+ }
+ if (butrct.ymin - max_size_y + center_y > 0.0f) {
+ down = 1;
+ }
+ if (butrct.ymax + max_size_y - center_y < win_y) {
+ top = 1;
+ }
+
+ if (top == 0 && down == 0) {
+ if (butrct.ymin - max_size_y < win_y - butrct.ymax - max_size_y) {
+ top = 1;
+ }
+ else {
+ down = 1;
+ }
+ }
+
+ dir1 = (block->direction & UI_DIR_ALL);
+
+ /* Secondary directions. */
+ if (dir1 & (UI_DIR_UP | UI_DIR_DOWN)) {
+ if (dir1 & UI_DIR_LEFT) {
+ dir2 = UI_DIR_LEFT;
+ }
+ else if (dir1 & UI_DIR_RIGHT) {
+ dir2 = UI_DIR_RIGHT;
+ }
+ dir1 &= (UI_DIR_UP | UI_DIR_DOWN);
+ }
+
+ if ((dir2 == 0) && (dir1 == UI_DIR_LEFT || dir1 == UI_DIR_RIGHT)) {
+ dir2 = UI_DIR_DOWN;
+ }
+ if ((dir2 == 0) && (dir1 == UI_DIR_UP || dir1 == UI_DIR_DOWN)) {
+ dir2 = UI_DIR_LEFT;
+ }
+
+ /* no space at all? don't change */
+ if (left || right) {
+ if (dir1 == UI_DIR_LEFT && left == 0) {
+ dir1 = UI_DIR_RIGHT;
+ }
+ if (dir1 == UI_DIR_RIGHT && right == 0) {
+ dir1 = UI_DIR_LEFT;
+ }
+ /* this is aligning, not append! */
+ if (dir2 == UI_DIR_LEFT && right == 0) {
+ dir2 = UI_DIR_RIGHT;
+ }
+ if (dir2 == UI_DIR_RIGHT && left == 0) {
+ dir2 = UI_DIR_LEFT;
+ }
+ }
+ if (down || top) {
+ if (dir1 == UI_DIR_UP && top == 0) {
+ dir1 = UI_DIR_DOWN;
+ }
+ if (dir1 == UI_DIR_DOWN && down == 0) {
+ dir1 = UI_DIR_UP;
+ }
+ BLI_assert(dir2 != UI_DIR_UP);
+ // if (dir2 == UI_DIR_UP && top == 0) { dir2 = UI_DIR_DOWN; }
+ if (dir2 == UI_DIR_DOWN && down == 0) {
+ dir2 = UI_DIR_UP;
+ }
+ }
+
+ handle->prev_dir1 = dir1;
+ handle->prev_dir2 = dir2;
+ }
+ else {
+ /* For refreshes, keep same popup direct so popup doesn't move
+ * to a totally different position while editing in it. */
+ dir1 = handle->prev_dir1;
+ dir2 = handle->prev_dir2;
+ }
+
+ /* Compute offset based on direction. */
+ int offset_x = 0, offset_y = 0;
+
+ if (dir1 == UI_DIR_LEFT) {
+ offset_x = butrct.xmin - block->rect.xmax;
+ if (dir2 == UI_DIR_UP) {
+ offset_y = butrct.ymin - block->rect.ymin - center_y - UI_MENU_PADDING;
+ }
+ else {
+ offset_y = butrct.ymax - block->rect.ymax + center_y + UI_MENU_PADDING;
+ }
+ }
+ else if (dir1 == UI_DIR_RIGHT) {
+ offset_x = butrct.xmax - block->rect.xmin;
+ if (dir2 == UI_DIR_UP) {
+ offset_y = butrct.ymin - block->rect.ymin - center_y - UI_MENU_PADDING;
+ }
+ else {
+ offset_y = butrct.ymax - block->rect.ymax + center_y + UI_MENU_PADDING;
+ }
+ }
+ else if (dir1 == UI_DIR_UP) {
+ offset_y = butrct.ymax - block->rect.ymin;
+ if (dir2 == UI_DIR_RIGHT) {
+ offset_x = butrct.xmax - block->rect.xmax + center_x;
+ }
+ else {
+ offset_x = butrct.xmin - block->rect.xmin - center_x;
+ }
+ /* changed direction? */
+ if ((dir1 & block->direction) == 0) {
+ /* TODO: still do */
+ UI_block_order_flip(block);
+ }
+ }
+ else if (dir1 == UI_DIR_DOWN) {
+ offset_y = butrct.ymin - block->rect.ymax;
+ if (dir2 == UI_DIR_RIGHT) {
+ offset_x = butrct.xmax - block->rect.xmax + center_x;
+ }
+ else {
+ offset_x = butrct.xmin - block->rect.xmin - center_x;
+ }
+ /* changed direction? */
+ if ((dir1 & block->direction) == 0) {
+ /* TODO: still do */
+ UI_block_order_flip(block);
+ }
+ }
+
+ /* Center over popovers for eg. */
+ if (block->direction & UI_DIR_CENTER_X) {
+ offset_x += BLI_rctf_size_x(&butrct) / ((dir2 == UI_DIR_LEFT) ? 2 : -2);
+ }
+
+ /* Apply offset, buttons in window coords. */
+ for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
+ ui_block_to_window_rctf(butregion, but->block, &bt->rect, &bt->rect);
+
+ BLI_rctf_translate(&bt->rect, offset_x, offset_y);
+
+ /* ui_but_update recalculates drawstring size in pixels */
+ ui_but_update(bt);
+ }
+
+ BLI_rctf_translate(&block->rect, offset_x, offset_y);
+
+ /* Safety calculus. */
+ {
+ const float midx = BLI_rctf_cent_x(&butrct);
+ const float midy = BLI_rctf_cent_y(&butrct);
+
+ /* when you are outside parent button, safety there should be smaller */
+
+ /* parent button to left */
+ if (midx < block->rect.xmin) {
+ block->safety.xmin = block->rect.xmin - 3;
+ }
+ else {
+ block->safety.xmin = block->rect.xmin - 40;
+ }
+ /* parent button to right */
+ if (midx > block->rect.xmax) {
+ block->safety.xmax = block->rect.xmax + 3;
+ }
+ else {
+ block->safety.xmax = block->rect.xmax + 40;
+ }
+
+ /* parent button on bottom */
+ if (midy < block->rect.ymin) {
+ block->safety.ymin = block->rect.ymin - 3;
+ }
+ else {
+ block->safety.ymin = block->rect.ymin - 40;
+ }
+ /* parent button on top */
+ if (midy > block->rect.ymax) {
+ block->safety.ymax = block->rect.ymax + 3;
+ }
+ else {
+ block->safety.ymax = block->rect.ymax + 40;
+ }
+
+ /* exception for switched pulldowns... */
+ if (dir1 && (dir1 & block->direction) == 0) {
+ if (dir2 == UI_DIR_RIGHT) {
+ block->safety.xmax = block->rect.xmax + 3;
+ }
+ if (dir2 == UI_DIR_LEFT) {
+ block->safety.xmin = block->rect.xmin - 3;
+ }
+ }
+ block->direction = dir1;
+ }
+
+ /* keep a list of these, needed for pulldown menus */
+ uiSafetyRct *saferct = MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct");
+ saferct->parent = butrct;
+ saferct->safety = block->safety;
+ BLI_freelistN(&block->saferct);
+ BLI_duplicatelist(&block->saferct, &but->block->saferct);
+ BLI_addhead(&block->saferct, saferct);
}
/** \} */
@@ -319,459 +368,462 @@ static void ui_popup_block_position(wmWindow *window, ARegion *butregion, uiBut
static void ui_block_region_refresh(const bContext *C, ARegion *ar)
{
- ScrArea *ctx_area = CTX_wm_area(C);
- ARegion *ctx_region = CTX_wm_region(C);
- uiBlock *block;
-
- if (ar->do_draw & RGN_DRAW_REFRESH_UI) {
- ScrArea *handle_ctx_area;
- ARegion *handle_ctx_region;
- uiBlock *block_next;
-
- ar->do_draw &= ~RGN_DRAW_REFRESH_UI;
- for (block = ar->uiblocks.first; block; block = block_next) {
- block_next = block->next;
- uiPopupBlockHandle *handle = block->handle;
-
- if (handle->can_refresh) {
- handle_ctx_area = handle->ctx_area;
- handle_ctx_region = handle->ctx_region;
-
- if (handle_ctx_area) {
- CTX_wm_area_set((bContext *)C, handle_ctx_area);
- }
- if (handle_ctx_region) {
- CTX_wm_region_set((bContext *)C, handle_ctx_region);
- }
-
- uiBut *but = handle->popup_create_vars.but;
- ARegion *butregion = handle->popup_create_vars.butregion;
- ui_popup_block_refresh((bContext *)C, handle, butregion, but);
- }
- }
- }
-
- CTX_wm_area_set((bContext *)C, ctx_area);
- CTX_wm_region_set((bContext *)C, ctx_region);
+ ScrArea *ctx_area = CTX_wm_area(C);
+ ARegion *ctx_region = CTX_wm_region(C);
+ uiBlock *block;
+
+ if (ar->do_draw & RGN_DRAW_REFRESH_UI) {
+ ScrArea *handle_ctx_area;
+ ARegion *handle_ctx_region;
+ uiBlock *block_next;
+
+ ar->do_draw &= ~RGN_DRAW_REFRESH_UI;
+ for (block = ar->uiblocks.first; block; block = block_next) {
+ block_next = block->next;
+ uiPopupBlockHandle *handle = block->handle;
+
+ if (handle->can_refresh) {
+ handle_ctx_area = handle->ctx_area;
+ handle_ctx_region = handle->ctx_region;
+
+ if (handle_ctx_area) {
+ CTX_wm_area_set((bContext *)C, handle_ctx_area);
+ }
+ if (handle_ctx_region) {
+ CTX_wm_region_set((bContext *)C, handle_ctx_region);
+ }
+
+ uiBut *but = handle->popup_create_vars.but;
+ ARegion *butregion = handle->popup_create_vars.butregion;
+ ui_popup_block_refresh((bContext *)C, handle, butregion, but);
+ }
+ }
+ }
+
+ CTX_wm_area_set((bContext *)C, ctx_area);
+ CTX_wm_region_set((bContext *)C, ctx_region);
}
static void ui_block_region_draw(const bContext *C, ARegion *ar)
{
- uiBlock *block;
+ uiBlock *block;
- for (block = ar->uiblocks.first; block; block = block->next) {
- UI_block_draw(C, block);
- }
+ for (block = ar->uiblocks.first; block; block = block->next) {
+ UI_block_draw(C, block);
+ }
}
/**
* 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, wmNotifier *wmn, const Scene *UNUSED(scene))
+static void ui_block_region_popup_window_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- switch (wmn->category) {
- case NC_WINDOW:
- {
- switch (wmn->action) {
- case NA_EDITED:
- {
- /* window resize */
- ED_region_tag_refresh_ui(ar);
- break;
- }
- }
- break;
- }
- }
+ switch (wmn->category) {
+ case NC_WINDOW: {
+ switch (wmn->action) {
+ case NA_EDITED: {
+ /* window resize */
+ ED_region_tag_refresh_ui(ar);
+ break;
+ }
+ }
+ break;
+ }
+ }
}
static void ui_popup_block_clip(wmWindow *window, uiBlock *block)
{
- uiBut *bt;
- const float xmin_orig = block->rect.xmin;
- const int margin = UI_SCREEN_MARGIN;
- int winx, winy;
-
- if (block->flag & UI_BLOCK_NO_WIN_CLIP) {
- return;
- }
-
- winx = WM_window_pixels_x(window);
- winy = WM_window_pixels_y(window);
-
- /* shift to left if outside of view */
- if (block->rect.xmax > winx - margin) {
- const float xofs = winx - margin - block->rect.xmax;
- block->rect.xmin += xofs;
- block->rect.xmax += xofs;
- }
- /* shift menus to right if outside of view */
- if (block->rect.xmin < margin) {
- const float xofs = (margin - block->rect.xmin);
- block->rect.xmin += xofs;
- block->rect.xmax += xofs;
- }
-
- if (block->rect.ymin < margin) {
- block->rect.ymin = margin;
- }
- if (block->rect.ymax > winy - UI_POPUP_MENU_TOP) {
- block->rect.ymax = winy - UI_POPUP_MENU_TOP;
- }
-
- /* ensure menu items draw inside left/right boundary */
- const float xofs = block->rect.xmin - xmin_orig;
- for (bt = block->buttons.first; bt; bt = bt->next) {
- bt->rect.xmin += xofs;
- bt->rect.xmax += xofs;
- }
+ uiBut *bt;
+ const float xmin_orig = block->rect.xmin;
+ const int margin = UI_SCREEN_MARGIN;
+ int winx, winy;
+
+ if (block->flag & UI_BLOCK_NO_WIN_CLIP) {
+ return;
+ }
+
+ winx = WM_window_pixels_x(window);
+ winy = WM_window_pixels_y(window);
+
+ /* shift to left if outside of view */
+ if (block->rect.xmax > winx - margin) {
+ const float xofs = winx - margin - block->rect.xmax;
+ block->rect.xmin += xofs;
+ block->rect.xmax += xofs;
+ }
+ /* shift menus to right if outside of view */
+ if (block->rect.xmin < margin) {
+ const float xofs = (margin - block->rect.xmin);
+ block->rect.xmin += xofs;
+ block->rect.xmax += xofs;
+ }
+
+ if (block->rect.ymin < margin) {
+ block->rect.ymin = margin;
+ }
+ if (block->rect.ymax > winy - UI_POPUP_MENU_TOP) {
+ block->rect.ymax = winy - UI_POPUP_MENU_TOP;
+ }
+
+ /* ensure menu items draw inside left/right boundary */
+ const float xofs = block->rect.xmin - xmin_orig;
+ for (bt = block->buttons.first; bt; bt = bt->next) {
+ bt->rect.xmin += xofs;
+ bt->rect.xmax += xofs;
+ }
}
void ui_popup_block_scrolltest(uiBlock *block)
{
- uiBut *bt;
-
- block->flag &= ~(UI_BLOCK_CLIPBOTTOM | UI_BLOCK_CLIPTOP);
-
- for (bt = block->buttons.first; bt; bt = bt->next) {
- bt->flag &= ~UI_SCROLLED;
- }
-
- if (block->buttons.first == block->buttons.last) {
- return;
- }
-
- /* mark buttons that are outside boundary */
- for (bt = block->buttons.first; bt; bt = bt->next) {
- if (bt->rect.ymin < block->rect.ymin) {
- bt->flag |= UI_SCROLLED;
- block->flag |= UI_BLOCK_CLIPBOTTOM;
- }
- if (bt->rect.ymax > block->rect.ymax) {
- bt->flag |= UI_SCROLLED;
- block->flag |= UI_BLOCK_CLIPTOP;
- }
- }
-
- /* mark buttons overlapping arrows, if we have them */
- for (bt = block->buttons.first; bt; bt = bt->next) {
- if (block->flag & UI_BLOCK_CLIPBOTTOM) {
- if (bt->rect.ymin < block->rect.ymin + UI_MENU_SCROLL_ARROW) {
- bt->flag |= UI_SCROLLED;
- }
- }
- if (block->flag & UI_BLOCK_CLIPTOP) {
- if (bt->rect.ymax > block->rect.ymax - UI_MENU_SCROLL_ARROW) {
- bt->flag |= UI_SCROLLED;
- }
- }
- }
+ uiBut *bt;
+
+ block->flag &= ~(UI_BLOCK_CLIPBOTTOM | UI_BLOCK_CLIPTOP);
+
+ for (bt = block->buttons.first; bt; bt = bt->next) {
+ bt->flag &= ~UI_SCROLLED;
+ }
+
+ if (block->buttons.first == block->buttons.last) {
+ return;
+ }
+
+ /* mark buttons that are outside boundary */
+ for (bt = block->buttons.first; bt; bt = bt->next) {
+ if (bt->rect.ymin < block->rect.ymin) {
+ bt->flag |= UI_SCROLLED;
+ block->flag |= UI_BLOCK_CLIPBOTTOM;
+ }
+ if (bt->rect.ymax > block->rect.ymax) {
+ bt->flag |= UI_SCROLLED;
+ block->flag |= UI_BLOCK_CLIPTOP;
+ }
+ }
+
+ /* mark buttons overlapping arrows, if we have them */
+ for (bt = block->buttons.first; bt; bt = bt->next) {
+ if (block->flag & UI_BLOCK_CLIPBOTTOM) {
+ if (bt->rect.ymin < block->rect.ymin + UI_MENU_SCROLL_ARROW) {
+ bt->flag |= UI_SCROLLED;
+ }
+ }
+ if (block->flag & UI_BLOCK_CLIPTOP) {
+ if (bt->rect.ymax > block->rect.ymax - UI_MENU_SCROLL_ARROW) {
+ bt->flag |= UI_SCROLLED;
+ }
+ }
+ }
}
static void ui_popup_block_remove(bContext *C, uiPopupBlockHandle *handle)
{
- wmWindow *win = CTX_wm_window(C);
- bScreen *sc = CTX_wm_screen(C);
+ wmWindow *win = CTX_wm_window(C);
+ bScreen *sc = CTX_wm_screen(C);
- ui_region_temp_remove(C, sc, handle->region);
+ ui_region_temp_remove(C, sc, handle->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_wm_area(C), CTX_wm_region(C));
- /* in case cursor needs to be changed again */
- WM_event_add_mousemove(C);
- }
+ /* 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_wm_area(C), CTX_wm_region(C));
+ /* in case cursor needs to be changed again */
+ WM_event_add_mousemove(C);
+ }
- if (handle->scrolltimer) {
- WM_event_remove_timer(CTX_wm_manager(C), win, handle->scrolltimer);
- }
+ if (handle->scrolltimer) {
+ WM_event_remove_timer(CTX_wm_manager(C), win, handle->scrolltimer);
+ }
}
/**
* Called for creating new popups and refreshing existing ones.
*/
-uiBlock *ui_popup_block_refresh(
- bContext *C, uiPopupBlockHandle *handle,
- ARegion *butregion, uiBut *but)
+uiBlock *ui_popup_block_refresh(bContext *C,
+ uiPopupBlockHandle *handle,
+ ARegion *butregion,
+ uiBut *but)
{
- const int margin = UI_POPUP_MARGIN;
- wmWindow *window = CTX_wm_window(C);
- ARegion *ar = handle->region;
+ const int margin = UI_POPUP_MARGIN;
+ wmWindow *window = CTX_wm_window(C);
+ ARegion *ar = 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;
+ 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;
+ uiBlock *block_old = ar->uiblocks.first;
+ uiBlock *block;
- handle->refresh = (block_old != NULL);
+ handle->refresh = (block_old != NULL);
- BLI_assert(!handle->refresh || handle->can_refresh);
+ BLI_assert(!handle->refresh || handle->can_refresh);
#ifdef DEBUG
- wmEvent *event_back = window->eventstate;
+ wmEvent *event_back = window->eventstate;
#endif
- /* create ui block */
- if (create_func) {
- block = create_func(C, ar, arg);
- }
- else {
- block = handle_create_func(C, handle, arg);
- }
+ /* create ui block */
+ if (create_func) {
+ block = create_func(C, ar, arg);
+ }
+ else {
+ block = handle_create_func(C, handle, arg);
+ }
- /* callbacks _must_ leave this for us, otherwise we can't call UI_block_update_from_old */
- BLI_assert(!block->endblock);
+ /* callbacks _must_ leave this for us, otherwise we can't call UI_block_update_from_old */
+ BLI_assert(!block->endblock);
- /* ensure we don't use mouse coords here! */
+ /* ensure we don't use mouse coords here! */
#ifdef DEBUG
- window->eventstate = NULL;
+ window->eventstate = NULL;
#endif
- if (block->handle) {
- memcpy(block->handle, handle, sizeof(uiPopupBlockHandle));
- MEM_freeN(handle);
- handle = block->handle;
- }
- else {
- block->handle = handle;
- }
-
- ar->regiondata = handle;
-
- /* set UI_BLOCK_NUMSELECT before UI_block_end() so we get alphanumeric keys assigned */
- if (but == NULL) {
- block->flag |= UI_BLOCK_POPUP;
- }
-
- block->flag |= UI_BLOCK_LOOP;
- UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
-
- /* defer this until blocks are translated (below) */
- block->oldblock = NULL;
-
- if (!block->endblock) {
- UI_block_end_ex(C, block, handle->popup_create_vars.event_xy, handle->popup_create_vars.event_xy);
- }
-
- /* if this is being created from a button */
- if (but) {
- block->aspect = but->block->aspect;
- ui_popup_block_position(window, butregion, but, block);
- handle->direction = block->direction;
- }
- else {
- uiSafetyRct *saferct;
- /* keep a list of these, needed for pulldown menus */
- saferct = MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct");
- saferct->safety = block->safety;
- BLI_addhead(&block->saferct, saferct);
- }
-
- if (block->flag & UI_BLOCK_RADIAL) {
- int win_width = UI_SCREEN_MARGIN;
- int winx, winy;
-
- int x_offset = 0, y_offset = 0;
-
- winx = WM_window_pixels_x(window);
- winy = WM_window_pixels_y(window);
-
- copy_v2_v2(block->pie_data.pie_center_init, block->pie_data.pie_center_spawned);
-
- /* only try translation if area is large enough */
- if (BLI_rctf_size_x(&block->rect) < winx - (2.0f * win_width)) {
- if (block->rect.xmin < win_width ) {
- x_offset += win_width - block->rect.xmin;
- }
- if (block->rect.xmax > winx - win_width) {
- x_offset += winx - win_width - block->rect.xmax;
- }
- }
-
- if (BLI_rctf_size_y(&block->rect) < winy - (2.0f * win_width)) {
- if (block->rect.ymin < win_width ) {
- y_offset += win_width - block->rect.ymin;
- }
- if (block->rect.ymax > winy - win_width) {
- y_offset += winy - win_width - block->rect.ymax;
- }
- }
- /* if we are offsetting set up initial data for timeout functionality */
-
- if ((x_offset != 0) || (y_offset != 0)) {
- block->pie_data.pie_center_spawned[0] += x_offset;
- block->pie_data.pie_center_spawned[1] += y_offset;
-
- UI_block_translate(block, x_offset, y_offset);
-
- if (U.pie_initial_timeout > 0) {
- block->pie_data.flags |= UI_PIE_INITIAL_DIRECTION;
- }
- }
-
- ar->winrct.xmin = 0;
- ar->winrct.xmax = winx;
- ar->winrct.ymin = 0;
- ar->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) {
- if (but_iter->pie_dir != UI_RADIAL_NONE) {
- BLI_rctf_recenter(&but_iter->rect, UNPACK2(block->pie_data.pie_center_spawned));
- }
- }
- }
- }
- else {
- /* clip block with window boundary */
- ui_popup_block_clip(window, block);
-
- /* Avoid menu moving down and losing cursor focus by keeping it at
- * the same height. */
- if (handle->refresh && handle->prev_block_rect.ymax > block->rect.ymax) {
- float offset = handle->prev_block_rect.ymax - block->rect.ymax;
- UI_block_translate(block, 0, offset);
- block->rect.ymin = handle->prev_block_rect.ymin;
- }
-
- handle->prev_block_rect = block->rect;
-
- /* 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;
-
- UI_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin);
-
- /* apply scroll offset */
- if (handle->scrolloffset != 0.0f) {
- for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
- bt->rect.ymin += handle->scrolloffset;
- bt->rect.ymax += handle->scrolloffset;
- }
- }
- }
-
- if (block_old) {
- block->oldblock = block_old;
- UI_block_update_from_old(C, block);
- UI_blocklist_free_inactive(C, &ar->uiblocks);
- }
-
- /* checks which buttons are visible, sets flags to prevent draw (do after region init) */
- ui_popup_block_scrolltest(block);
-
- /* adds subwindow */
- ED_region_init(ar);
-
- /* get winmat now that we actually have the subwindow */
- wmGetProjectionMatrix(block->winmat, &ar->winrct);
-
- /* notify change and redraw */
- ED_region_tag_redraw(ar);
-
- ED_region_update_rect(ar);
+ if (block->handle) {
+ memcpy(block->handle, handle, sizeof(uiPopupBlockHandle));
+ MEM_freeN(handle);
+ handle = block->handle;
+ }
+ else {
+ block->handle = handle;
+ }
+
+ ar->regiondata = handle;
+
+ /* set UI_BLOCK_NUMSELECT before UI_block_end() so we get alphanumeric keys assigned */
+ if (but == NULL) {
+ block->flag |= UI_BLOCK_POPUP;
+ }
+
+ block->flag |= UI_BLOCK_LOOP;
+ UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
+
+ /* defer this until blocks are translated (below) */
+ block->oldblock = NULL;
+
+ if (!block->endblock) {
+ UI_block_end_ex(
+ C, block, handle->popup_create_vars.event_xy, handle->popup_create_vars.event_xy);
+ }
+
+ /* if this is being created from a button */
+ if (but) {
+ block->aspect = but->block->aspect;
+ ui_popup_block_position(window, butregion, but, block);
+ handle->direction = block->direction;
+ }
+ else {
+ uiSafetyRct *saferct;
+ /* keep a list of these, needed for pulldown menus */
+ saferct = MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct");
+ saferct->safety = block->safety;
+ BLI_addhead(&block->saferct, saferct);
+ }
+
+ if (block->flag & UI_BLOCK_RADIAL) {
+ int win_width = UI_SCREEN_MARGIN;
+ int winx, winy;
+
+ int x_offset = 0, y_offset = 0;
+
+ winx = WM_window_pixels_x(window);
+ winy = WM_window_pixels_y(window);
+
+ copy_v2_v2(block->pie_data.pie_center_init, block->pie_data.pie_center_spawned);
+
+ /* only try translation if area is large enough */
+ if (BLI_rctf_size_x(&block->rect) < winx - (2.0f * win_width)) {
+ if (block->rect.xmin < win_width) {
+ x_offset += win_width - block->rect.xmin;
+ }
+ if (block->rect.xmax > winx - win_width) {
+ x_offset += winx - win_width - block->rect.xmax;
+ }
+ }
+
+ if (BLI_rctf_size_y(&block->rect) < winy - (2.0f * win_width)) {
+ if (block->rect.ymin < win_width) {
+ y_offset += win_width - block->rect.ymin;
+ }
+ if (block->rect.ymax > winy - win_width) {
+ y_offset += winy - win_width - block->rect.ymax;
+ }
+ }
+ /* if we are offsetting set up initial data for timeout functionality */
+
+ if ((x_offset != 0) || (y_offset != 0)) {
+ block->pie_data.pie_center_spawned[0] += x_offset;
+ block->pie_data.pie_center_spawned[1] += y_offset;
+
+ UI_block_translate(block, x_offset, y_offset);
+
+ if (U.pie_initial_timeout > 0) {
+ block->pie_data.flags |= UI_PIE_INITIAL_DIRECTION;
+ }
+ }
+
+ ar->winrct.xmin = 0;
+ ar->winrct.xmax = winx;
+ ar->winrct.ymin = 0;
+ ar->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) {
+ if (but_iter->pie_dir != UI_RADIAL_NONE) {
+ BLI_rctf_recenter(&but_iter->rect, UNPACK2(block->pie_data.pie_center_spawned));
+ }
+ }
+ }
+ }
+ else {
+ /* clip block with window boundary */
+ ui_popup_block_clip(window, block);
+
+ /* Avoid menu moving down and losing cursor focus by keeping it at
+ * the same height. */
+ if (handle->refresh && handle->prev_block_rect.ymax > block->rect.ymax) {
+ float offset = handle->prev_block_rect.ymax - block->rect.ymax;
+ UI_block_translate(block, 0, offset);
+ block->rect.ymin = handle->prev_block_rect.ymin;
+ }
+
+ handle->prev_block_rect = block->rect;
+
+ /* 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;
+
+ UI_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin);
+
+ /* apply scroll offset */
+ if (handle->scrolloffset != 0.0f) {
+ for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
+ bt->rect.ymin += handle->scrolloffset;
+ bt->rect.ymax += handle->scrolloffset;
+ }
+ }
+ }
+
+ if (block_old) {
+ block->oldblock = block_old;
+ UI_block_update_from_old(C, block);
+ UI_blocklist_free_inactive(C, &ar->uiblocks);
+ }
+
+ /* checks which buttons are visible, sets flags to prevent draw (do after region init) */
+ ui_popup_block_scrolltest(block);
+
+ /* adds subwindow */
+ ED_region_init(ar);
+
+ /* get winmat now that we actually have the subwindow */
+ wmGetProjectionMatrix(block->winmat, &ar->winrct);
+
+ /* notify change and redraw */
+ ED_region_tag_redraw(ar);
+
+ ED_region_update_rect(ar);
#ifdef DEBUG
- window->eventstate = event_back;
+ window->eventstate = event_back;
#endif
- return block;
+ return block;
}
-uiPopupBlockHandle *ui_popup_block_create(
- bContext *C, ARegion *butregion, uiBut *but,
- uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func,
- void *arg)
+uiPopupBlockHandle *ui_popup_block_create(bContext *C,
+ ARegion *butregion,
+ uiBut *but,
+ uiBlockCreateFunc create_func,
+ uiBlockHandleCreateFunc handle_create_func,
+ void *arg)
{
- wmWindow *window = CTX_wm_window(C);
- uiBut *activebut = UI_context_active_but_get(C);
- static ARegionType type;
- ARegion *ar;
- uiBlock *block;
- uiPopupBlockHandle *handle;
-
- /* disable tooltips from buttons below */
- if (activebut) {
- UI_but_tooltip_timer_remove(C, activebut);
- }
- /* standard cursor by default */
- WM_cursor_set(window, CURSOR_STD);
-
- /* create handle */
- handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle");
-
- /* store context for operator */
- handle->ctx_area = CTX_wm_area(C);
- handle->ctx_region = CTX_wm_region(C);
-
- /* store vars to refresh popup (RGN_DRAW_REFRESH_UI) */
- handle->popup_create_vars.create_func = create_func;
- handle->popup_create_vars.handle_create_func = handle_create_func;
- handle->popup_create_vars.arg = arg;
- handle->popup_create_vars.but = but;
- handle->popup_create_vars.butregion = but ? butregion : NULL;
- copy_v2_v2_int(handle->popup_create_vars.event_xy, &window->eventstate->x);
-
- /* don't allow by default, only if popup type explicitly supports it */
- handle->can_refresh = false;
-
- /* create area region */
- ar = ui_region_temp_add(CTX_wm_screen(C));
- handle->region = ar;
-
- 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;
-
- UI_region_handlers_add(&ar->handlers);
-
- block = ui_popup_block_refresh(C, handle, butregion, but);
- handle = block->handle;
-
- /* keep centered on window resizing */
- if (block->bounds_type == UI_BLOCK_BOUNDS_POPUP_CENTER) {
- type.listener = ui_block_region_popup_window_listener;
- }
-
- return handle;
+ wmWindow *window = CTX_wm_window(C);
+ uiBut *activebut = UI_context_active_but_get(C);
+ static ARegionType type;
+ ARegion *ar;
+ uiBlock *block;
+ uiPopupBlockHandle *handle;
+
+ /* disable tooltips from buttons below */
+ if (activebut) {
+ UI_but_tooltip_timer_remove(C, activebut);
+ }
+ /* standard cursor by default */
+ WM_cursor_set(window, CURSOR_STD);
+
+ /* create handle */
+ handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle");
+
+ /* store context for operator */
+ handle->ctx_area = CTX_wm_area(C);
+ handle->ctx_region = CTX_wm_region(C);
+
+ /* store vars to refresh popup (RGN_DRAW_REFRESH_UI) */
+ handle->popup_create_vars.create_func = create_func;
+ handle->popup_create_vars.handle_create_func = handle_create_func;
+ handle->popup_create_vars.arg = arg;
+ handle->popup_create_vars.but = but;
+ handle->popup_create_vars.butregion = but ? butregion : NULL;
+ copy_v2_v2_int(handle->popup_create_vars.event_xy, &window->eventstate->x);
+
+ /* don't allow by default, only if popup type explicitly supports it */
+ handle->can_refresh = false;
+
+ /* create area region */
+ ar = ui_region_temp_add(CTX_wm_screen(C));
+ handle->region = ar;
+
+ 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;
+
+ UI_region_handlers_add(&ar->handlers);
+
+ block = ui_popup_block_refresh(C, handle, butregion, but);
+ handle = block->handle;
+
+ /* keep centered on window resizing */
+ if (block->bounds_type == UI_BLOCK_BOUNDS_POPUP_CENTER) {
+ type.listener = ui_block_region_popup_window_listener;
+ }
+
+ return handle;
}
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) {
- if (block->handle &&
- (block->flag & UI_BLOCK_POPOVER) &&
- (block->flag & UI_BLOCK_KEEP_OPEN) == 0)
- {
- uiPopupBlockHandle *menu = block->handle;
- menu->menuretval = UI_RETURN_OK;
- }
- }
- }
-
- if (handle->popup_create_vars.free_func) {
- handle->popup_create_vars.free_func(handle, handle->popup_create_vars.arg);
- }
-
- ui_popup_block_remove(C, handle);
-
- MEM_freeN(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) {
+ if (block->handle && (block->flag & UI_BLOCK_POPOVER) &&
+ (block->flag & UI_BLOCK_KEEP_OPEN) == 0) {
+ uiPopupBlockHandle *menu = block->handle;
+ menu->menuretval = UI_RETURN_OK;
+ }
+ }
+ }
+
+ if (handle->popup_create_vars.free_func) {
+ handle->popup_create_vars.free_func(handle, handle->popup_create_vars.arg);
+ }
+
+ ui_popup_block_remove(C, handle);
+
+ MEM_freeN(handle);
}
/** \} */
diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c
index 9aebf1183e0..c37775febda 100644
--- a/source/blender/editors/interface/interface_region_search.c
+++ b/source/blender/editors/interface/interface_region_search.c
@@ -46,7 +46,6 @@
#include "RNA_access.h"
-
#include "UI_interface.h"
#include "UI_interface_icons.h"
#include "UI_view2d.h"
@@ -59,606 +58,608 @@
#include "interface_regions_intern.h"
#include "GPU_state.h"
-#define MENU_BORDER (int)(0.3f * U.widget_unit)
+#define MENU_BORDER (int)(0.3f * U.widget_unit)
/* -------------------------------------------------------------------- */
/** \name Search Box Creation
* \{ */
struct uiSearchItems {
- int maxitem, totitem, maxstrlen;
+ int maxitem, totitem, maxstrlen;
- int offset, offset_i; /* offset for inserting in array */
- int more; /* flag indicating there are more items */
+ int offset, offset_i; /* offset for inserting in array */
+ int more; /* flag indicating there are more items */
- char **names;
- void **pointers;
- int *icons;
+ char **names;
+ void **pointers;
+ int *icons;
- AutoComplete *autocpl;
- void *active;
+ AutoComplete *autocpl;
+ void *active;
};
typedef struct uiSearchboxData {
- rcti bbox;
- uiFontStyle fstyle;
- uiSearchItems items;
- /** index in items array */
- int active;
- /** when menu opened with enough space for this */
- 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) */
- bool use_sep;
- int prv_rows, prv_cols;
+ rcti bbox;
+ uiFontStyle fstyle;
+ uiSearchItems items;
+ /** index in items array */
+ int active;
+ /** when menu opened with enough space for this */
+ 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) */
+ bool use_sep;
+ int prv_rows, prv_cols;
} uiSearchboxData;
-#define SEARCH_ITEMS 10
+#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)
{
- /* hijack for autocomplete */
- if (items->autocpl) {
- UI_autocomplete_update_name(items->autocpl, name);
- return true;
- }
-
- /* hijack for finding active item */
- if (items->active) {
- if (poin == items->active) {
- items->offset_i = items->totitem;
- }
- items->totitem++;
- return true;
- }
-
- if (items->totitem >= items->maxitem) {
- items->more = 1;
- return false;
- }
-
- /* skip first items in list */
- if (items->offset_i > 0) {
- items->offset_i--;
- return true;
- }
-
- if (items->names) {
- BLI_strncpy(items->names[items->totitem], name, items->maxstrlen);
- }
- if (items->pointers) {
- items->pointers[items->totitem] = poin;
- }
- if (items->icons) {
- items->icons[items->totitem] = iconid;
- }
-
- items->totitem++;
-
- return true;
+ /* hijack for autocomplete */
+ if (items->autocpl) {
+ UI_autocomplete_update_name(items->autocpl, name);
+ return true;
+ }
+
+ /* hijack for finding active item */
+ if (items->active) {
+ if (poin == items->active) {
+ items->offset_i = items->totitem;
+ }
+ items->totitem++;
+ return true;
+ }
+
+ if (items->totitem >= items->maxitem) {
+ items->more = 1;
+ return false;
+ }
+
+ /* skip first items in list */
+ if (items->offset_i > 0) {
+ items->offset_i--;
+ return true;
+ }
+
+ if (items->names) {
+ BLI_strncpy(items->names[items->totitem], name, items->maxstrlen);
+ }
+ if (items->pointers) {
+ items->pointers[items->totitem] = poin;
+ }
+ if (items->icons) {
+ items->icons[items->totitem] = iconid;
+ }
+
+ items->totitem++;
+
+ return true;
}
int UI_searchbox_size_y(void)
{
- return SEARCH_ITEMS * UI_UNIT_Y + 2 * UI_POPUP_MENU_TOP;
+ return SEARCH_ITEMS * UI_UNIT_Y + 2 * UI_POPUP_MENU_TOP;
}
int UI_searchbox_size_x(void)
{
- return 12 * UI_UNIT_X;
+ return 12 * UI_UNIT_X;
}
int UI_search_items_find_index(uiSearchItems *items, const char *name)
{
- int i;
- for (i = 0; i < items->totitem; i++) {
- if (STREQ(name, items->names[i])) {
- return i;
- }
- }
- return -1;
+ int i;
+ for (i = 0; i < items->totitem; i++) {
+ if (STREQ(name, items->names[i])) {
+ return i;
+ }
+ }
+ return -1;
}
/* ar is the search box itself */
static void ui_searchbox_select(bContext *C, ARegion *ar, uiBut *but, int step)
{
- uiSearchboxData *data = ar->regiondata;
-
- /* apply step */
- data->active += step;
-
- if (data->items.totitem == 0) {
- data->active = -1;
- }
- else if (data->active >= data->items.totitem) {
- if (data->items.more) {
- data->items.offset++;
- data->active = data->items.totitem - 1;
- ui_searchbox_update(C, ar, but, false);
- }
- else {
- data->active = data->items.totitem - 1;
- }
- }
- else if (data->active < 0) {
- if (data->items.offset) {
- data->items.offset--;
- data->active = 0;
- ui_searchbox_update(C, ar, but, false);
- }
- else {
- /* only let users step into an 'unset' state for unlink buttons */
- data->active = (but->flag & UI_BUT_VALUE_CLEAR) ? -1 : 0;
- }
- }
-
- ED_region_tag_redraw(ar);
+ uiSearchboxData *data = ar->regiondata;
+
+ /* apply step */
+ data->active += step;
+
+ if (data->items.totitem == 0) {
+ data->active = -1;
+ }
+ else if (data->active >= data->items.totitem) {
+ if (data->items.more) {
+ data->items.offset++;
+ data->active = data->items.totitem - 1;
+ ui_searchbox_update(C, ar, but, false);
+ }
+ else {
+ data->active = data->items.totitem - 1;
+ }
+ }
+ else if (data->active < 0) {
+ if (data->items.offset) {
+ data->items.offset--;
+ data->active = 0;
+ ui_searchbox_update(C, ar, but, false);
+ }
+ else {
+ /* only let users step into an 'unset' state for unlink buttons */
+ data->active = (but->flag & UI_BUT_VALUE_CLEAR) ? -1 : 0;
+ }
+ }
+
+ ED_region_tag_redraw(ar);
}
static void ui_searchbox_butrect(rcti *r_rect, uiSearchboxData *data, int itemnr)
{
- /* thumbnail preview */
- if (data->preview) {
- int butw = (BLI_rcti_size_x(&data->bbox) - 2 * MENU_BORDER) / data->prv_cols;
- int buth = (BLI_rcti_size_y(&data->bbox) - 2 * MENU_BORDER) / data->prv_rows;
- int row, col;
-
- *r_rect = data->bbox;
-
- col = itemnr % data->prv_cols;
- row = itemnr / data->prv_cols;
-
- r_rect->xmin += MENU_BORDER + (col * butw);
- r_rect->xmax = r_rect->xmin + butw;
-
- r_rect->ymax -= MENU_BORDER + (row * buth);
- r_rect->ymin = r_rect->ymax - buth;
- }
- /* list view */
- else {
- int buth = (BLI_rcti_size_y(&data->bbox) - 2 * UI_POPUP_MENU_TOP) / SEARCH_ITEMS;
-
- *r_rect = data->bbox;
- r_rect->xmin = data->bbox.xmin + 3.0f;
- r_rect->xmax = data->bbox.xmax - 3.0f;
-
- r_rect->ymax = data->bbox.ymax - UI_POPUP_MENU_TOP - itemnr * buth;
- r_rect->ymin = r_rect->ymax - buth;
- }
-
+ /* thumbnail preview */
+ if (data->preview) {
+ int butw = (BLI_rcti_size_x(&data->bbox) - 2 * MENU_BORDER) / data->prv_cols;
+ int buth = (BLI_rcti_size_y(&data->bbox) - 2 * MENU_BORDER) / data->prv_rows;
+ int row, col;
+
+ *r_rect = data->bbox;
+
+ col = itemnr % data->prv_cols;
+ row = itemnr / data->prv_cols;
+
+ r_rect->xmin += MENU_BORDER + (col * butw);
+ r_rect->xmax = r_rect->xmin + butw;
+
+ r_rect->ymax -= MENU_BORDER + (row * buth);
+ r_rect->ymin = r_rect->ymax - buth;
+ }
+ /* list view */
+ else {
+ int buth = (BLI_rcti_size_y(&data->bbox) - 2 * UI_POPUP_MENU_TOP) / SEARCH_ITEMS;
+
+ *r_rect = data->bbox;
+ r_rect->xmin = data->bbox.xmin + 3.0f;
+ r_rect->xmax = data->bbox.xmax - 3.0f;
+
+ r_rect->ymax = data->bbox.ymax - UI_POPUP_MENU_TOP - itemnr * buth;
+ r_rect->ymin = r_rect->ymax - buth;
+ }
}
int ui_searchbox_find_index(ARegion *ar, const char *name)
{
- uiSearchboxData *data = ar->regiondata;
- return UI_search_items_find_index(&data->items, name);
+ uiSearchboxData *data = ar->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)
{
- uiSearchboxData *data = ar->regiondata;
+ uiSearchboxData *data = ar->regiondata;
- return BLI_rcti_isect_pt(&data->bbox, x - ar->winrct.xmin, y - ar->winrct.ymin);
+ return BLI_rcti_isect_pt(&data->bbox, x - ar->winrct.xmin, y - ar->winrct.ymin);
}
/* string validated to be of correct length (but->hardmax) */
bool ui_searchbox_apply(uiBut *but, ARegion *ar)
{
- uiSearchboxData *data = ar->regiondata;
+ uiSearchboxData *data = ar->regiondata;
- but->func_arg2 = NULL;
+ but->func_arg2 = NULL;
- if (data->active != -1) {
- const char *name = data->items.names[data->active];
- const char *name_sep = data->use_sep ? strrchr(name, UI_SEP_CHAR) : NULL;
+ if (data->active != -1) {
+ const char *name = data->items.names[data->active];
+ const char *name_sep = data->use_sep ? strrchr(name, UI_SEP_CHAR) : NULL;
- BLI_strncpy(but->editstr, name, name_sep ? (name_sep - name) : data->items.maxstrlen);
+ BLI_strncpy(but->editstr, name, name_sep ? (name_sep - name) : data->items.maxstrlen);
- but->func_arg2 = data->items.pointers[data->active];
+ but->func_arg2 = data->items.pointers[data->active];
- return true;
- }
- else if (but->flag & UI_BUT_VALUE_CLEAR) {
- /* It is valid for _VALUE_CLEAR flavor to have no active element
- * (it's a valid way to unlink). */
- but->editstr[0] = '\0';
+ return true;
+ }
+ else if (but->flag & UI_BUT_VALUE_CLEAR) {
+ /* It is valid for _VALUE_CLEAR flavor to have no active element
+ * (it's a valid way to unlink). */
+ but->editstr[0] = '\0';
- return true;
- }
- else {
- return false;
- }
+ return true;
+ }
+ else {
+ return false;
+ }
}
void ui_searchbox_event(bContext *C, ARegion *ar, uiBut *but, const wmEvent *event)
{
- uiSearchboxData *data = ar->regiondata;
- int type = event->type, val = event->val;
-
- if (type == MOUSEPAN) {
- ui_pan_to_scroll(event, &type, &val);
- }
-
- switch (type) {
- case WHEELUPMOUSE:
- case UPARROWKEY:
- ui_searchbox_select(C, ar, but, -1);
- break;
- case WHEELDOWNMOUSE:
- case DOWNARROWKEY:
- ui_searchbox_select(C, ar, but, 1);
- break;
- case MOUSEMOVE:
- if (BLI_rcti_isect_pt(&ar->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 (data->active != a) {
- data->active = a;
- ui_searchbox_select(C, ar, but, 0);
- break;
- }
- }
- }
- }
- break;
- }
+ uiSearchboxData *data = ar->regiondata;
+ int type = event->type, val = event->val;
+
+ if (type == MOUSEPAN) {
+ ui_pan_to_scroll(event, &type, &val);
+ }
+
+ switch (type) {
+ case WHEELUPMOUSE:
+ case UPARROWKEY:
+ ui_searchbox_select(C, ar, but, -1);
+ break;
+ case WHEELDOWNMOUSE:
+ case DOWNARROWKEY:
+ ui_searchbox_select(C, ar, but, 1);
+ break;
+ case MOUSEMOVE:
+ if (BLI_rcti_isect_pt(&ar->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 (data->active != a) {
+ data->active = a;
+ ui_searchbox_select(C, ar, but, 0);
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
}
/* ar is the search box itself */
void ui_searchbox_update(bContext *C, ARegion *ar, uiBut *but, const bool reset)
{
- uiSearchboxData *data = ar->regiondata;
-
- /* reset vars */
- data->items.totitem = 0;
- data->items.more = 0;
- if (reset == false) {
- data->items.offset_i = data->items.offset;
- }
- else {
- data->items.offset_i = data->items.offset = 0;
- data->active = -1;
-
- /* handle active */
- if (but->search_func && but->func_arg2) {
- data->items.active = but->func_arg2;
- but->search_func(C, but->search_arg, but->editstr, &data->items);
- data->items.active = NULL;
-
- /* found active item, calculate real offset by centering it */
- if (data->items.totitem) {
- /* first case, begin of list */
- if (data->items.offset_i < data->items.maxitem) {
- data->active = data->items.offset_i;
- data->items.offset_i = 0;
- }
- else {
- /* second case, end of list */
- if (data->items.totitem - data->items.offset_i <= data->items.maxitem) {
- data->active = data->items.offset_i - data->items.totitem + data->items.maxitem;
- data->items.offset_i = data->items.totitem - data->items.maxitem;
- }
- else {
- /* center active item */
- data->items.offset_i -= data->items.maxitem / 2;
- data->active = data->items.maxitem / 2;
- }
- }
- }
- data->items.offset = data->items.offset_i;
- data->items.totitem = 0;
- }
- }
-
- /* callback */
- if (but->search_func) {
- but->search_func(C, but->search_arg, but->editstr, &data->items);
- }
-
- /* handle case where editstr is equal to one of items */
- if (reset && data->active == -1) {
- int a;
-
- for (a = 0; a < data->items.totitem; a++) {
- const char *name = data->items.names[a];
- const char *name_sep = data->use_sep ? strrchr(name, UI_SEP_CHAR) : NULL;
- if (STREQLEN(but->editstr, name, name_sep ? (name_sep - name) : data->items.maxstrlen)) {
- data->active = a;
- break;
- }
- }
- if (data->items.totitem == 1 && but->editstr[0]) {
- data->active = 0;
- }
- }
-
- /* validate selected item */
- ui_searchbox_select(C, ar, but, 0);
-
- ED_region_tag_redraw(ar);
+ uiSearchboxData *data = ar->regiondata;
+
+ /* reset vars */
+ data->items.totitem = 0;
+ data->items.more = 0;
+ if (reset == false) {
+ data->items.offset_i = data->items.offset;
+ }
+ else {
+ data->items.offset_i = data->items.offset = 0;
+ data->active = -1;
+
+ /* handle active */
+ if (but->search_func && but->func_arg2) {
+ data->items.active = but->func_arg2;
+ but->search_func(C, but->search_arg, but->editstr, &data->items);
+ data->items.active = NULL;
+
+ /* found active item, calculate real offset by centering it */
+ if (data->items.totitem) {
+ /* first case, begin of list */
+ if (data->items.offset_i < data->items.maxitem) {
+ data->active = data->items.offset_i;
+ data->items.offset_i = 0;
+ }
+ else {
+ /* second case, end of list */
+ if (data->items.totitem - data->items.offset_i <= data->items.maxitem) {
+ data->active = data->items.offset_i - data->items.totitem + data->items.maxitem;
+ data->items.offset_i = data->items.totitem - data->items.maxitem;
+ }
+ else {
+ /* center active item */
+ data->items.offset_i -= data->items.maxitem / 2;
+ data->active = data->items.maxitem / 2;
+ }
+ }
+ }
+ data->items.offset = data->items.offset_i;
+ data->items.totitem = 0;
+ }
+ }
+
+ /* callback */
+ if (but->search_func) {
+ but->search_func(C, but->search_arg, but->editstr, &data->items);
+ }
+
+ /* handle case where editstr is equal to one of items */
+ if (reset && data->active == -1) {
+ int a;
+
+ for (a = 0; a < data->items.totitem; a++) {
+ const char *name = data->items.names[a];
+ const char *name_sep = data->use_sep ? strrchr(name, UI_SEP_CHAR) : NULL;
+ if (STREQLEN(but->editstr, name, name_sep ? (name_sep - name) : data->items.maxstrlen)) {
+ data->active = a;
+ break;
+ }
+ }
+ if (data->items.totitem == 1 && but->editstr[0]) {
+ data->active = 0;
+ }
+ }
+
+ /* validate selected item */
+ ui_searchbox_select(C, ar, but, 0);
+
+ ED_region_tag_redraw(ar);
}
int ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str)
{
- uiSearchboxData *data = ar->regiondata;
- int match = AUTOCOMPLETE_NO_MATCH;
+ uiSearchboxData *data = ar->regiondata;
+ int match = AUTOCOMPLETE_NO_MATCH;
- if (str[0]) {
- data->items.autocpl = UI_autocomplete_begin(str, ui_but_string_get_max_length(but));
+ 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);
+ but->search_func(C, but->search_arg, but->editstr, &data->items);
- match = UI_autocomplete_end(data->items.autocpl, str);
- data->items.autocpl = NULL;
- }
+ match = UI_autocomplete_end(data->items.autocpl, str);
+ data->items.autocpl = NULL;
+ }
- return match;
+ return match;
}
static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *ar)
{
- uiSearchboxData *data = ar->regiondata;
-
- /* pixel space */
- wmOrtho2_region_pixelspace(ar);
-
- if (data->noback == false) {
- ui_draw_widget_menu_back(&data->bbox, true);
- }
-
- /* draw text */
- if (data->items.totitem) {
- rcti rect;
- int a;
-
- if (data->preview) {
- /* draw items */
- for (a = 0; a < data->items.totitem; 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);
- }
-
- /* indicate more */
- if (data->items.more) {
- ui_searchbox_butrect(&rect, data, data->items.maxitem - 1);
- GPU_blend(true);
- UI_icon_draw(rect.xmax - 18, rect.ymin - 7, ICON_TRIA_DOWN);
- GPU_blend(false);
- }
- if (data->items.offset) {
- ui_searchbox_butrect(&rect, data, 0);
- GPU_blend(true);
- UI_icon_draw(rect.xmin, rect.ymax - 9, ICON_TRIA_UP);
- GPU_blend(false);
- }
-
- }
- else {
- /* draw items */
- for (a = 0; a < data->items.totitem; a++) {
- 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);
-
- }
- /* indicate more */
- if (data->items.more) {
- ui_searchbox_butrect(&rect, data, data->items.maxitem - 1);
- GPU_blend(true);
- UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN);
- GPU_blend(false);
- }
- if (data->items.offset) {
- ui_searchbox_butrect(&rect, data, 0);
- GPU_blend(true);
- UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP);
- GPU_blend(false);
- }
- }
- }
+ uiSearchboxData *data = ar->regiondata;
+
+ /* pixel space */
+ wmOrtho2_region_pixelspace(ar);
+
+ if (data->noback == false) {
+ ui_draw_widget_menu_back(&data->bbox, true);
+ }
+
+ /* draw text */
+ if (data->items.totitem) {
+ rcti rect;
+ int a;
+
+ if (data->preview) {
+ /* draw items */
+ for (a = 0; a < data->items.totitem; 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);
+ }
+
+ /* indicate more */
+ if (data->items.more) {
+ ui_searchbox_butrect(&rect, data, data->items.maxitem - 1);
+ GPU_blend(true);
+ UI_icon_draw(rect.xmax - 18, rect.ymin - 7, ICON_TRIA_DOWN);
+ GPU_blend(false);
+ }
+ if (data->items.offset) {
+ ui_searchbox_butrect(&rect, data, 0);
+ GPU_blend(true);
+ UI_icon_draw(rect.xmin, rect.ymax - 9, ICON_TRIA_UP);
+ GPU_blend(false);
+ }
+ }
+ else {
+ /* draw items */
+ for (a = 0; a < data->items.totitem; a++) {
+ 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);
+ }
+ /* indicate more */
+ if (data->items.more) {
+ ui_searchbox_butrect(&rect, data, data->items.maxitem - 1);
+ GPU_blend(true);
+ UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN);
+ GPU_blend(false);
+ }
+ if (data->items.offset) {
+ ui_searchbox_butrect(&rect, data, 0);
+ GPU_blend(true);
+ UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP);
+ GPU_blend(false);
+ }
+ }
+ }
}
static void ui_searchbox_region_free_cb(ARegion *ar)
{
- uiSearchboxData *data = ar->regiondata;
- int a;
-
- /* free search data */
- for (a = 0; a < data->items.maxitem; a++) {
- MEM_freeN(data->items.names[a]);
- }
- MEM_freeN(data->items.names);
- MEM_freeN(data->items.pointers);
- MEM_freeN(data->items.icons);
-
- MEM_freeN(data);
- ar->regiondata = NULL;
+ uiSearchboxData *data = ar->regiondata;
+ int a;
+
+ /* free search data */
+ for (a = 0; a < data->items.maxitem; a++) {
+ MEM_freeN(data->items.names[a]);
+ }
+ MEM_freeN(data->items.names);
+ MEM_freeN(data->items.pointers);
+ MEM_freeN(data->items.icons);
+
+ MEM_freeN(data);
+ ar->regiondata = NULL;
}
ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but)
{
- wmWindow *win = CTX_wm_window(C);
- uiStyle *style = UI_style_get();
- static ARegionType type;
- ARegion *ar;
- uiSearchboxData *data;
- float aspect = but->block->aspect;
- rctf rect_fl;
- rcti rect_i;
- const int margin = UI_POPUP_MARGIN;
- int winx /*, winy */, ofsx, ofsy;
- int i;
-
- /* create area region */
- ar = 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;
-
- /* create searchbox data */
- data = MEM_callocN(sizeof(uiSearchboxData), "uiSearchboxData");
-
- /* set font, get bb */
- data->fstyle = style->widget; /* copy struct */
- ui_fontscale(&data->fstyle.points, aspect);
- UI_fontstyle_set(&data->fstyle);
-
- ar->regiondata = data;
-
- /* special case, hardcoded feature, not draw backdrop when called from menus,
- * assume for design that popup already added it */
- if (but->block->flag & UI_BLOCK_SEARCH_MENU) {
- data->noback = true;
- }
-
- if (but->a1 > 0 && but->a2 > 0) {
- data->preview = true;
- data->prv_rows = but->a1;
- data->prv_cols = but->a2;
- }
-
- /* Only show key shortcuts when needed (checking RNA prop pointer is useless here, a lot of buttons are about data
- * without having that pointer defined, let's rather try with optype!). One can also enforce that behavior by
- * setting UI_BUT_HAS_SHORTCUT drawflag of search button. */
- if (but->optype != NULL || (but->drawflag & UI_BUT_HAS_SHORTCUT) != 0) {
- data->use_sep = true;
- }
-
- /* compute position */
- if (but->block->flag & UI_BLOCK_SEARCH_MENU) {
- const int search_but_h = BLI_rctf_size_y(&but->rect) + 10;
- /* this case is search menu inside other menu */
- /* we copy region size */
-
- ar->winrct = butregion->winrct;
-
- /* widget rect, in region coords */
- data->bbox.xmin = margin;
- data->bbox.xmax = BLI_rcti_size_x(&ar->winrct) - margin;
- data->bbox.ymin = margin;
- data->bbox.ymax = BLI_rcti_size_y(&ar->winrct) - margin;
-
- /* check if button is lower half */
- if (but->rect.ymax < BLI_rctf_cent_y(&but->block->rect)) {
- data->bbox.ymin += search_but_h;
- }
- else {
- data->bbox.ymax -= search_but_h;
- }
- }
- else {
- const int searchbox_width = UI_searchbox_size_x();
-
- rect_fl.xmin = but->rect.xmin - 5; /* align text with button */
- rect_fl.xmax = but->rect.xmax + 5; /* symmetrical */
- rect_fl.ymax = but->rect.ymin;
- rect_fl.ymin = rect_fl.ymax - UI_searchbox_size_y();
-
- ofsx = (but->block->panel) ? but->block->panel->ofsx : 0;
- ofsy = (but->block->panel) ? but->block->panel->ofsy : 0;
-
- BLI_rctf_translate(&rect_fl, ofsx, ofsy);
-
- /* minimal width */
- if (BLI_rctf_size_x(&rect_fl) < searchbox_width) {
- rect_fl.xmax = rect_fl.xmin + searchbox_width;
- }
-
- /* copy to int, gets projected if possible too */
- BLI_rcti_rctf_copy(&rect_i, &rect_fl);
-
- if (butregion->v2d.cur.xmin != butregion->v2d.cur.xmax) {
- UI_view2d_view_to_region_rcti(&butregion->v2d, &rect_fl, &rect_i);
- }
-
- BLI_rcti_translate(&rect_i, butregion->winrct.xmin, butregion->winrct.ymin);
-
- winx = WM_window_pixels_x(win);
- // winy = WM_window_pixels_y(win); /* UNUSED */
- //wm_window_get_size(win, &winx, &winy);
-
- if (rect_i.xmax > winx) {
- /* super size */
- if (rect_i.xmax > winx + rect_i.xmin) {
- rect_i.xmax = winx;
- rect_i.xmin = 0;
- }
- else {
- rect_i.xmin -= rect_i.xmax - winx;
- rect_i.xmax = winx;
- }
- }
-
- if (rect_i.ymin < 0) {
- int newy1 = but->rect.ymax + ofsy;
-
- if (butregion->v2d.cur.xmin != butregion->v2d.cur.xmax) {
- newy1 = UI_view2d_view_to_region_y(&butregion->v2d, newy1);
- }
-
- newy1 += butregion->winrct.ymin;
-
- rect_i.ymax = BLI_rcti_size_y(&rect_i) + newy1;
- rect_i.ymin = newy1;
- }
-
- /* widget rect, in region coords */
- data->bbox.xmin = margin;
- data->bbox.xmax = BLI_rcti_size_x(&rect_i) + margin;
- data->bbox.ymin = margin;
- 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;
- }
-
- /* adds subwindow */
- ED_region_init(ar);
-
- /* notify change and redraw */
- ED_region_tag_redraw(ar);
-
- /* prepare search data */
- if (data->preview) {
- data->items.maxitem = data->prv_rows * data->prv_cols;
- }
- else {
- data->items.maxitem = SEARCH_ITEMS;
- }
- data->items.maxstrlen = but->hardmax;
- data->items.totitem = 0;
- 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");
- for (i = 0; i < data->items.maxitem; i++) {
- data->items.names[i] = MEM_callocN(but->hardmax + 1, "search pointers");
- }
-
- return ar;
+ wmWindow *win = CTX_wm_window(C);
+ uiStyle *style = UI_style_get();
+ static ARegionType type;
+ ARegion *ar;
+ uiSearchboxData *data;
+ float aspect = but->block->aspect;
+ rctf rect_fl;
+ rcti rect_i;
+ const int margin = UI_POPUP_MARGIN;
+ int winx /*, winy */, ofsx, ofsy;
+ int i;
+
+ /* create area region */
+ ar = 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;
+
+ /* create searchbox data */
+ data = MEM_callocN(sizeof(uiSearchboxData), "uiSearchboxData");
+
+ /* set font, get bb */
+ data->fstyle = style->widget; /* copy struct */
+ ui_fontscale(&data->fstyle.points, aspect);
+ UI_fontstyle_set(&data->fstyle);
+
+ ar->regiondata = data;
+
+ /* special case, hardcoded feature, not draw backdrop when called from menus,
+ * assume for design that popup already added it */
+ if (but->block->flag & UI_BLOCK_SEARCH_MENU) {
+ data->noback = true;
+ }
+
+ if (but->a1 > 0 && but->a2 > 0) {
+ data->preview = true;
+ data->prv_rows = but->a1;
+ data->prv_cols = but->a2;
+ }
+
+ /* Only show key shortcuts when needed (checking RNA prop pointer is useless here, a lot of buttons are about data
+ * without having that pointer defined, let's rather try with optype!). One can also enforce that behavior by
+ * setting UI_BUT_HAS_SHORTCUT drawflag of search button. */
+ if (but->optype != NULL || (but->drawflag & UI_BUT_HAS_SHORTCUT) != 0) {
+ data->use_sep = true;
+ }
+
+ /* compute position */
+ if (but->block->flag & UI_BLOCK_SEARCH_MENU) {
+ const int search_but_h = BLI_rctf_size_y(&but->rect) + 10;
+ /* this case is search menu inside other menu */
+ /* we copy region size */
+
+ ar->winrct = butregion->winrct;
+
+ /* widget rect, in region coords */
+ data->bbox.xmin = margin;
+ data->bbox.xmax = BLI_rcti_size_x(&ar->winrct) - margin;
+ data->bbox.ymin = margin;
+ data->bbox.ymax = BLI_rcti_size_y(&ar->winrct) - margin;
+
+ /* check if button is lower half */
+ if (but->rect.ymax < BLI_rctf_cent_y(&but->block->rect)) {
+ data->bbox.ymin += search_but_h;
+ }
+ else {
+ data->bbox.ymax -= search_but_h;
+ }
+ }
+ else {
+ const int searchbox_width = UI_searchbox_size_x();
+
+ rect_fl.xmin = but->rect.xmin - 5; /* align text with button */
+ rect_fl.xmax = but->rect.xmax + 5; /* symmetrical */
+ rect_fl.ymax = but->rect.ymin;
+ rect_fl.ymin = rect_fl.ymax - UI_searchbox_size_y();
+
+ ofsx = (but->block->panel) ? but->block->panel->ofsx : 0;
+ ofsy = (but->block->panel) ? but->block->panel->ofsy : 0;
+
+ BLI_rctf_translate(&rect_fl, ofsx, ofsy);
+
+ /* minimal width */
+ if (BLI_rctf_size_x(&rect_fl) < searchbox_width) {
+ rect_fl.xmax = rect_fl.xmin + searchbox_width;
+ }
+
+ /* copy to int, gets projected if possible too */
+ BLI_rcti_rctf_copy(&rect_i, &rect_fl);
+
+ if (butregion->v2d.cur.xmin != butregion->v2d.cur.xmax) {
+ UI_view2d_view_to_region_rcti(&butregion->v2d, &rect_fl, &rect_i);
+ }
+
+ BLI_rcti_translate(&rect_i, butregion->winrct.xmin, butregion->winrct.ymin);
+
+ winx = WM_window_pixels_x(win);
+ // winy = WM_window_pixels_y(win); /* UNUSED */
+ //wm_window_get_size(win, &winx, &winy);
+
+ if (rect_i.xmax > winx) {
+ /* super size */
+ if (rect_i.xmax > winx + rect_i.xmin) {
+ rect_i.xmax = winx;
+ rect_i.xmin = 0;
+ }
+ else {
+ rect_i.xmin -= rect_i.xmax - winx;
+ rect_i.xmax = winx;
+ }
+ }
+
+ if (rect_i.ymin < 0) {
+ int newy1 = but->rect.ymax + ofsy;
+
+ if (butregion->v2d.cur.xmin != butregion->v2d.cur.xmax) {
+ newy1 = UI_view2d_view_to_region_y(&butregion->v2d, newy1);
+ }
+
+ newy1 += butregion->winrct.ymin;
+
+ rect_i.ymax = BLI_rcti_size_y(&rect_i) + newy1;
+ rect_i.ymin = newy1;
+ }
+
+ /* widget rect, in region coords */
+ data->bbox.xmin = margin;
+ data->bbox.xmax = BLI_rcti_size_x(&rect_i) + margin;
+ data->bbox.ymin = margin;
+ 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;
+ }
+
+ /* adds subwindow */
+ ED_region_init(ar);
+
+ /* notify change and redraw */
+ ED_region_tag_redraw(ar);
+
+ /* prepare search data */
+ if (data->preview) {
+ data->items.maxitem = data->prv_rows * data->prv_cols;
+ }
+ else {
+ data->items.maxitem = SEARCH_ITEMS;
+ }
+ data->items.maxstrlen = but->hardmax;
+ data->items.totitem = 0;
+ 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");
+ for (i = 0; i < data->items.maxitem; i++) {
+ data->items.names[i] = MEM_callocN(but->hardmax + 1, "search pointers");
+ }
+
+ return ar;
}
/**
@@ -669,152 +670,154 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but
*/
static void str_tolower_titlecaps_ascii(char *str, const size_t len)
{
- size_t i;
- bool prev_delim = true;
-
- for (i = 0; (i < len) && str[i]; i++) {
- if (str[i] >= 'A' && str[i] <= 'Z') {
- if (prev_delim == false) {
- str[i] += 'a' - 'A';
- }
- }
- else if (str[i] == '_') {
- str[i] = ' ';
- }
-
- prev_delim = ELEM(str[i], ' ') || (str[i] >= '0' && str[i] <= '9');
- }
-
+ size_t i;
+ bool prev_delim = true;
+
+ for (i = 0; (i < len) && str[i]; i++) {
+ if (str[i] >= 'A' && str[i] <= 'Z') {
+ if (prev_delim == false) {
+ str[i] += 'a' - 'A';
+ }
+ }
+ else if (str[i] == '_') {
+ str[i] = ' ';
+ }
+
+ prev_delim = ELEM(str[i], ' ') || (str[i] >= '0' && str[i] <= '9');
+ }
}
static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARegion *ar)
{
- uiSearchboxData *data = ar->regiondata;
-
- /* pixel space */
- wmOrtho2_region_pixelspace(ar);
-
- if (data->noback == false) {
- ui_draw_widget_menu_back(&data->bbox, true);
- }
-
- /* draw text */
- if (data->items.totitem) {
- rcti rect;
- int a;
-
- /* draw items */
- for (a = 0; a < data->items.totitem; a++) {
- rcti rect_pre, rect_post;
- ui_searchbox_butrect(&rect, data, a);
-
- rect_pre = rect;
- rect_post = rect;
-
- rect_pre.xmax = rect_post.xmin = rect.xmin + ((rect.xmax - rect.xmin) / 4);
-
- /* widget itself */
- /* NOTE: i18n messages extracting tool does the same, please keep it in sync. */
- {
- wmOperatorType *ot = data->items.pointers[a];
-
- int state = (a == data->active) ? UI_ACTIVE : 0;
- char text_pre[128];
- char *text_pre_p = strstr(ot->idname, "_OT_");
- if (text_pre_p == NULL) {
- text_pre[0] = '\0';
- }
- else {
- int text_pre_len;
- text_pre_p += 1;
- text_pre_len = BLI_strncpy_rlen(
- text_pre, ot->idname, min_ii(sizeof(text_pre), text_pre_p - ot->idname));
- text_pre[text_pre_len] = ':';
- text_pre[text_pre_len + 1] = '\0';
- str_tolower_titlecaps_ascii(text_pre, sizeof(text_pre));
- }
-
- rect_pre.xmax += 4; /* sneaky, avoid showing ugly margin */
- ui_draw_menu_item(
- &data->fstyle, &rect_pre, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, text_pre),
- data->items.icons[a], state, false);
- ui_draw_menu_item(&data->fstyle, &rect_post, data->items.names[a], 0, state, data->use_sep);
- }
-
- }
- /* indicate more */
- if (data->items.more) {
- ui_searchbox_butrect(&rect, data, data->items.maxitem - 1);
- GPU_blend(true);
- UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN);
- GPU_blend(false);
- }
- if (data->items.offset) {
- ui_searchbox_butrect(&rect, data, 0);
- GPU_blend(true);
- UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP);
- GPU_blend(false);
- }
- }
+ uiSearchboxData *data = ar->regiondata;
+
+ /* pixel space */
+ wmOrtho2_region_pixelspace(ar);
+
+ if (data->noback == false) {
+ ui_draw_widget_menu_back(&data->bbox, true);
+ }
+
+ /* draw text */
+ if (data->items.totitem) {
+ rcti rect;
+ int a;
+
+ /* draw items */
+ for (a = 0; a < data->items.totitem; a++) {
+ rcti rect_pre, rect_post;
+ ui_searchbox_butrect(&rect, data, a);
+
+ rect_pre = rect;
+ rect_post = rect;
+
+ rect_pre.xmax = rect_post.xmin = rect.xmin + ((rect.xmax - rect.xmin) / 4);
+
+ /* widget itself */
+ /* NOTE: i18n messages extracting tool does the same, please keep it in sync. */
+ {
+ wmOperatorType *ot = data->items.pointers[a];
+
+ int state = (a == data->active) ? UI_ACTIVE : 0;
+ char text_pre[128];
+ char *text_pre_p = strstr(ot->idname, "_OT_");
+ if (text_pre_p == NULL) {
+ text_pre[0] = '\0';
+ }
+ else {
+ int text_pre_len;
+ text_pre_p += 1;
+ text_pre_len = BLI_strncpy_rlen(
+ text_pre, ot->idname, min_ii(sizeof(text_pre), text_pre_p - ot->idname));
+ text_pre[text_pre_len] = ':';
+ text_pre[text_pre_len + 1] = '\0';
+ str_tolower_titlecaps_ascii(text_pre, sizeof(text_pre));
+ }
+
+ rect_pre.xmax += 4; /* sneaky, avoid showing ugly margin */
+ ui_draw_menu_item(&data->fstyle,
+ &rect_pre,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, text_pre),
+ data->items.icons[a],
+ state,
+ false);
+ ui_draw_menu_item(
+ &data->fstyle, &rect_post, data->items.names[a], 0, state, data->use_sep);
+ }
+ }
+ /* indicate more */
+ if (data->items.more) {
+ ui_searchbox_butrect(&rect, data, data->items.maxitem - 1);
+ GPU_blend(true);
+ UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN);
+ GPU_blend(false);
+ }
+ if (data->items.offset) {
+ ui_searchbox_butrect(&rect, data, 0);
+ GPU_blend(true);
+ UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP);
+ GPU_blend(false);
+ }
+ }
}
ARegion *ui_searchbox_create_operator(bContext *C, ARegion *butregion, uiBut *but)
{
- ARegion *ar;
+ ARegion *ar;
- UI_but_drawflag_enable(but, UI_BUT_HAS_SHORTCUT);
- ar = ui_searchbox_create_generic(C, butregion, but);
+ UI_but_drawflag_enable(but, UI_BUT_HAS_SHORTCUT);
+ ar = ui_searchbox_create_generic(C, butregion, but);
- ar->type->draw = ui_searchbox_region_draw_cb__operator;
+ ar->type->draw = ui_searchbox_region_draw_cb__operator;
- return ar;
+ return ar;
}
void ui_searchbox_free(bContext *C, ARegion *ar)
{
- ui_region_temp_remove(C, CTX_wm_screen(C), ar);
+ ui_region_temp_remove(C, CTX_wm_screen(C), ar);
}
/* sets red alert if button holds a string it can't find */
/* XXX weak: search_func adds all partial matches... */
void ui_but_search_refresh(uiBut *but)
{
- uiSearchItems *items;
- int x1;
-
- /* possibly very large lists (such as ID datablocks) only
- * only validate string RNA buts (not pointers) */
- if (but->rnaprop && RNA_property_type(but->rnaprop) != PROP_STRING) {
- return;
- }
-
- items = MEM_callocN(sizeof(uiSearchItems), "search items");
-
- /* setup search struct */
- items->maxitem = 10;
- items->maxstrlen = 256;
- items->names = MEM_callocN(items->maxitem * sizeof(void *), "search names");
- for (x1 = 0; x1 < items->maxitem; x1++) {
- items->names[x1] = MEM_callocN(but->hardmax + 1, "search names");
- }
-
- but->search_func(but->block->evil_C, but->search_arg, but->drawstr, items);
-
- /* only redalert when we are sure of it, this can miss cases when >10 matches */
- if (items->totitem == 0) {
- UI_but_flag_enable(but, UI_BUT_REDALERT);
- }
- else if (items->more == 0) {
- if (UI_search_items_find_index(items, but->drawstr) == -1) {
- UI_but_flag_enable(but, UI_BUT_REDALERT);
- }
- }
-
- for (x1 = 0; x1 < items->maxitem; x1++) {
- MEM_freeN(items->names[x1]);
- }
- MEM_freeN(items->names);
- MEM_freeN(items);
+ uiSearchItems *items;
+ int x1;
+
+ /* possibly very large lists (such as ID datablocks) only
+ * only validate string RNA buts (not pointers) */
+ if (but->rnaprop && RNA_property_type(but->rnaprop) != PROP_STRING) {
+ return;
+ }
+
+ items = MEM_callocN(sizeof(uiSearchItems), "search items");
+
+ /* setup search struct */
+ items->maxitem = 10;
+ items->maxstrlen = 256;
+ items->names = MEM_callocN(items->maxitem * sizeof(void *), "search names");
+ for (x1 = 0; x1 < items->maxitem; x1++) {
+ items->names[x1] = MEM_callocN(but->hardmax + 1, "search names");
+ }
+
+ but->search_func(but->block->evil_C, but->search_arg, but->drawstr, items);
+
+ /* only redalert when we are sure of it, this can miss cases when >10 matches */
+ if (items->totitem == 0) {
+ UI_but_flag_enable(but, UI_BUT_REDALERT);
+ }
+ else if (items->more == 0) {
+ if (UI_search_items_find_index(items, but->drawstr) == -1) {
+ UI_but_flag_enable(but, UI_BUT_REDALERT);
+ }
+ }
+
+ for (x1 = 0; x1 < items->maxitem; x1++) {
+ MEM_freeN(items->names[x1]);
+ }
+ MEM_freeN(items->names);
+ MEM_freeN(items);
}
/** \} */
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index 4bde694b5da..c8029a2b21a 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -55,7 +55,6 @@
#include "RNA_access.h"
-
#include "UI_interface.h"
#include "BLF_api.h"
@@ -70,46 +69,45 @@
#include "interface_intern.h"
#include "interface_regions_intern.h"
-#define UI_TIP_PAD_FAC 1.3f
-#define UI_TIP_PADDING (int)(UI_TIP_PAD_FAC * UI_UNIT_Y)
-#define UI_TIP_MAXWIDTH 600
-
+#define UI_TIP_PAD_FAC 1.3f
+#define UI_TIP_PADDING (int)(UI_TIP_PAD_FAC * UI_UNIT_Y)
+#define UI_TIP_MAXWIDTH 600
typedef struct uiTooltipFormat {
- enum {
- UI_TIP_STYLE_NORMAL = 0,
- UI_TIP_STYLE_HEADER,
- UI_TIP_STYLE_MONO,
- } style : 3;
- enum {
- UI_TIP_LC_MAIN = 0, /* primary text */
- UI_TIP_LC_VALUE, /* the value of buttons (also shortcuts) */
- UI_TIP_LC_ACTIVE, /* titles of active enum values */
- UI_TIP_LC_NORMAL, /* regular text */
- UI_TIP_LC_PYTHON, /* Python snippet */
- UI_TIP_LC_ALERT, /* description of why operator can't run */
- } color_id : 4;
- int is_pad : 1;
+ enum {
+ UI_TIP_STYLE_NORMAL = 0,
+ UI_TIP_STYLE_HEADER,
+ UI_TIP_STYLE_MONO,
+ } style : 3;
+ enum {
+ UI_TIP_LC_MAIN = 0, /* primary text */
+ UI_TIP_LC_VALUE, /* the value of buttons (also shortcuts) */
+ UI_TIP_LC_ACTIVE, /* titles of active enum values */
+ UI_TIP_LC_NORMAL, /* regular text */
+ UI_TIP_LC_PYTHON, /* Python snippet */
+ UI_TIP_LC_ALERT, /* description of why operator can't run */
+ } color_id : 4;
+ int is_pad : 1;
} uiTooltipFormat;
typedef struct uiTooltipField {
- char *text;
- char *text_suffix;
- struct {
- uint x_pos; /* x cursor position at the end of the last line */
- uint lines; /* number of lines, 1 or more with word-wrap */
- } geom;
- uiTooltipFormat format;
+ char *text;
+ char *text_suffix;
+ struct {
+ uint x_pos; /* x cursor position at the end of the last line */
+ uint lines; /* number of lines, 1 or more with word-wrap */
+ } geom;
+ uiTooltipFormat format;
} uiTooltipField;
typedef struct uiTooltipData {
- rcti bbox;
- uiTooltipField *fields;
- uint fields_len;
- uiFontStyle fstyle;
- int wrap_width;
- int toth, lineh;
+ rcti bbox;
+ uiTooltipField *fields;
+ uint fields_len;
+ uiFontStyle fstyle;
+ int wrap_width;
+ int toth, lineh;
} uiTooltipData;
#define UI_TIP_LC_MAX 6
@@ -117,183 +115,177 @@ typedef struct uiTooltipData {
BLI_STATIC_ASSERT(UI_TIP_LC_MAX == UI_TIP_LC_ALERT + 1, "invalid lc-max");
BLI_STATIC_ASSERT(sizeof(uiTooltipFormat) <= sizeof(int), "oversize");
-static uiTooltipField *text_field_add_only(
- uiTooltipData *data)
+static uiTooltipField *text_field_add_only(uiTooltipData *data)
{
- data->fields_len += 1;
- data->fields = MEM_recallocN(data->fields, sizeof(*data->fields) * data->fields_len);
- return &data->fields[data->fields_len - 1];
+ data->fields_len += 1;
+ data->fields = MEM_recallocN(data->fields, sizeof(*data->fields) * data->fields_len);
+ return &data->fields[data->fields_len - 1];
}
-static uiTooltipField *text_field_add(
- uiTooltipData *data,
- const uiTooltipFormat *format)
+static uiTooltipField *text_field_add(uiTooltipData *data, const uiTooltipFormat *format)
{
- uiTooltipField *field = text_field_add_only(data);
- field->format = *format;
- return field;
+ uiTooltipField *field = text_field_add_only(data);
+ field->format = *format;
+ return field;
}
/* -------------------------------------------------------------------- */
/** \name ToolTip Callbacks (Draw & Free)
* \{ */
-static void rgb_tint(
- float col[3],
- float h, float h_strength,
- float v, float v_strength)
+static void rgb_tint(float col[3], float h, float h_strength, float v, float v_strength)
{
- float col_hsv_from[3];
- float col_hsv_to[3];
+ float col_hsv_from[3];
+ float col_hsv_to[3];
- rgb_to_hsv_v(col, col_hsv_from);
+ rgb_to_hsv_v(col, col_hsv_from);
- col_hsv_to[0] = h;
- col_hsv_to[1] = h_strength;
- col_hsv_to[2] = (col_hsv_from[2] * (1.0f - v_strength)) + (v * v_strength);
+ col_hsv_to[0] = h;
+ col_hsv_to[1] = h_strength;
+ col_hsv_to[2] = (col_hsv_from[2] * (1.0f - v_strength)) + (v * v_strength);
- hsv_to_rgb_v(col_hsv_to, col);
+ hsv_to_rgb_v(col_hsv_to, col);
}
static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
{
- const float pad_px = UI_TIP_PADDING;
- uiTooltipData *data = ar->regiondata;
- const uiWidgetColors *theme = ui_tooltip_get_theme();
- rcti bbox = data->bbox;
- float tip_colors[UI_TIP_LC_MAX][3];
- uchar drawcol[4] = {0, 0, 0, 255}; /* to store color in while drawing (alpha is always 255) */
-
- float *main_color = tip_colors[UI_TIP_LC_MAIN]; /* the color from the theme */
- float *value_color = tip_colors[UI_TIP_LC_VALUE];
- float *active_color = tip_colors[UI_TIP_LC_ACTIVE];
- float *normal_color = tip_colors[UI_TIP_LC_NORMAL];
- float *python_color = tip_colors[UI_TIP_LC_PYTHON];
- float *alert_color = tip_colors[UI_TIP_LC_ALERT];
-
- float background_color[3];
- float tone_bg;
- int i;
-
- wmOrtho2_region_pixelspace(ar);
-
- /* draw background */
- ui_draw_tooltip_background(UI_style_get(), NULL, &bbox);
-
- /* set background_color */
- rgb_uchar_to_float(background_color, (const uchar *)theme->inner);
-
- /* calculate normal_color */
- rgb_uchar_to_float(main_color, (const uchar *)theme->text);
- copy_v3_v3(active_color, main_color);
- copy_v3_v3(normal_color, main_color);
- copy_v3_v3(python_color, main_color);
- copy_v3_v3(alert_color, main_color);
- copy_v3_v3(value_color, main_color);
-
- /* find the brightness difference between background and text colors */
-
- tone_bg = rgb_to_grayscale(background_color);
- /* tone_fg = rgb_to_grayscale(main_color); */
-
- /* mix the colors */
- rgb_tint(value_color, 0.0f, 0.0f, tone_bg, 0.2f); /* light gray */
- rgb_tint(active_color, 0.6f, 0.2f, tone_bg, 0.2f); /* light blue */
- rgb_tint(normal_color, 0.0f, 0.0f, tone_bg, 0.4f); /* gray */
- rgb_tint(python_color, 0.0f, 0.0f, tone_bg, 0.5f); /* dark gray */
- rgb_tint(alert_color, 0.0f, 0.8f, tone_bg, 0.1f); /* red */
-
- /* draw text */
- BLF_wordwrap(data->fstyle.uifont_id, data->wrap_width);
- BLF_wordwrap(blf_mono_font, data->wrap_width);
-
- bbox.xmin += 0.5f * pad_px; /* add padding to the text */
- bbox.ymax -= 0.25f * pad_px;
-
- for (i = 0; i < data->fields_len; i++) {
- const uiTooltipField *field = &data->fields[i];
- const uiTooltipField *field_next = (i + 1) != data->fields_len ? &data->fields[i + 1] : NULL;
-
- bbox.ymin = bbox.ymax - (data->lineh * field->geom.lines);
- if (field->format.style == UI_TIP_STYLE_HEADER) {
- const struct uiFontStyleDraw_Params fs_params = {
- .align = UI_STYLE_TEXT_LEFT,
- .word_wrap = true,
- };
- /* draw header and active data (is done here to be able to change color) */
- rgb_float_to_uchar(drawcol, tip_colors[UI_TIP_LC_MAIN]);
- UI_fontstyle_set(&data->fstyle);
- UI_fontstyle_draw(&data->fstyle, &bbox, field->text, drawcol, &fs_params);
-
- /* offset to the end of the last line */
- if (field->text_suffix) {
- float xofs = field->geom.x_pos;
- float yofs = data->lineh * (field->geom.lines - 1);
- bbox.xmin += xofs;
- bbox.ymax -= yofs;
-
- rgb_float_to_uchar(drawcol, tip_colors[UI_TIP_LC_ACTIVE]);
- UI_fontstyle_draw(&data->fstyle, &bbox, field->text_suffix, drawcol, &fs_params);
-
- /* undo offset */
- bbox.xmin -= xofs;
- bbox.ymax += yofs;
- }
- }
- else if (field->format.style == UI_TIP_STYLE_MONO) {
- const struct uiFontStyleDraw_Params fs_params = {
- .align = UI_STYLE_TEXT_LEFT,
- .word_wrap = true,
- };
- uiFontStyle fstyle_mono = data->fstyle;
- fstyle_mono.uifont_id = blf_mono_font;
-
- UI_fontstyle_set(&fstyle_mono);
- /* XXX, needed because we dont have mono in 'U.uifonts' */
- BLF_size(fstyle_mono.uifont_id, fstyle_mono.points * U.pixelsize, U.dpi);
- rgb_float_to_uchar(drawcol, tip_colors[field->format.color_id]);
- UI_fontstyle_draw(&fstyle_mono, &bbox, field->text, drawcol, &fs_params);
- }
- else {
- BLI_assert(field->format.style == UI_TIP_STYLE_NORMAL);
- const struct uiFontStyleDraw_Params fs_params = {
- .align = UI_STYLE_TEXT_LEFT,
- .word_wrap = true,
- };
-
- /* draw remaining data */
- rgb_float_to_uchar(drawcol, tip_colors[field->format.color_id]);
- UI_fontstyle_set(&data->fstyle);
- UI_fontstyle_draw(&data->fstyle, &bbox, field->text, drawcol, &fs_params);
- }
-
- bbox.ymax -= data->lineh * field->geom.lines;
-
- if (field_next && field_next->format.is_pad) {
- bbox.ymax -= data->lineh * (UI_TIP_PAD_FAC - 1);
- }
- }
-
- BLF_disable(data->fstyle.uifont_id, BLF_WORD_WRAP);
- BLF_disable(blf_mono_font, BLF_WORD_WRAP);
+ const float pad_px = UI_TIP_PADDING;
+ uiTooltipData *data = ar->regiondata;
+ const uiWidgetColors *theme = ui_tooltip_get_theme();
+ rcti bbox = data->bbox;
+ float tip_colors[UI_TIP_LC_MAX][3];
+ uchar drawcol[4] = {0, 0, 0, 255}; /* to store color in while drawing (alpha is always 255) */
+
+ float *main_color = tip_colors[UI_TIP_LC_MAIN]; /* the color from the theme */
+ float *value_color = tip_colors[UI_TIP_LC_VALUE];
+ float *active_color = tip_colors[UI_TIP_LC_ACTIVE];
+ float *normal_color = tip_colors[UI_TIP_LC_NORMAL];
+ float *python_color = tip_colors[UI_TIP_LC_PYTHON];
+ float *alert_color = tip_colors[UI_TIP_LC_ALERT];
+
+ float background_color[3];
+ float tone_bg;
+ int i;
+
+ wmOrtho2_region_pixelspace(ar);
+
+ /* draw background */
+ ui_draw_tooltip_background(UI_style_get(), NULL, &bbox);
+
+ /* set background_color */
+ rgb_uchar_to_float(background_color, (const uchar *)theme->inner);
+
+ /* calculate normal_color */
+ rgb_uchar_to_float(main_color, (const uchar *)theme->text);
+ copy_v3_v3(active_color, main_color);
+ copy_v3_v3(normal_color, main_color);
+ copy_v3_v3(python_color, main_color);
+ copy_v3_v3(alert_color, main_color);
+ copy_v3_v3(value_color, main_color);
+
+ /* find the brightness difference between background and text colors */
+
+ tone_bg = rgb_to_grayscale(background_color);
+ /* tone_fg = rgb_to_grayscale(main_color); */
+
+ /* mix the colors */
+ rgb_tint(value_color, 0.0f, 0.0f, tone_bg, 0.2f); /* light gray */
+ rgb_tint(active_color, 0.6f, 0.2f, tone_bg, 0.2f); /* light blue */
+ rgb_tint(normal_color, 0.0f, 0.0f, tone_bg, 0.4f); /* gray */
+ rgb_tint(python_color, 0.0f, 0.0f, tone_bg, 0.5f); /* dark gray */
+ rgb_tint(alert_color, 0.0f, 0.8f, tone_bg, 0.1f); /* red */
+
+ /* draw text */
+ BLF_wordwrap(data->fstyle.uifont_id, data->wrap_width);
+ BLF_wordwrap(blf_mono_font, data->wrap_width);
+
+ bbox.xmin += 0.5f * pad_px; /* add padding to the text */
+ bbox.ymax -= 0.25f * pad_px;
+
+ for (i = 0; i < data->fields_len; i++) {
+ const uiTooltipField *field = &data->fields[i];
+ const uiTooltipField *field_next = (i + 1) != data->fields_len ? &data->fields[i + 1] : NULL;
+
+ bbox.ymin = bbox.ymax - (data->lineh * field->geom.lines);
+ if (field->format.style == UI_TIP_STYLE_HEADER) {
+ const struct uiFontStyleDraw_Params fs_params = {
+ .align = UI_STYLE_TEXT_LEFT,
+ .word_wrap = true,
+ };
+ /* draw header and active data (is done here to be able to change color) */
+ rgb_float_to_uchar(drawcol, tip_colors[UI_TIP_LC_MAIN]);
+ UI_fontstyle_set(&data->fstyle);
+ UI_fontstyle_draw(&data->fstyle, &bbox, field->text, drawcol, &fs_params);
+
+ /* offset to the end of the last line */
+ if (field->text_suffix) {
+ float xofs = field->geom.x_pos;
+ float yofs = data->lineh * (field->geom.lines - 1);
+ bbox.xmin += xofs;
+ bbox.ymax -= yofs;
+
+ rgb_float_to_uchar(drawcol, tip_colors[UI_TIP_LC_ACTIVE]);
+ UI_fontstyle_draw(&data->fstyle, &bbox, field->text_suffix, drawcol, &fs_params);
+
+ /* undo offset */
+ bbox.xmin -= xofs;
+ bbox.ymax += yofs;
+ }
+ }
+ else if (field->format.style == UI_TIP_STYLE_MONO) {
+ const struct uiFontStyleDraw_Params fs_params = {
+ .align = UI_STYLE_TEXT_LEFT,
+ .word_wrap = true,
+ };
+ uiFontStyle fstyle_mono = data->fstyle;
+ fstyle_mono.uifont_id = blf_mono_font;
+
+ UI_fontstyle_set(&fstyle_mono);
+ /* XXX, needed because we dont have mono in 'U.uifonts' */
+ BLF_size(fstyle_mono.uifont_id, fstyle_mono.points * U.pixelsize, U.dpi);
+ rgb_float_to_uchar(drawcol, tip_colors[field->format.color_id]);
+ UI_fontstyle_draw(&fstyle_mono, &bbox, field->text, drawcol, &fs_params);
+ }
+ else {
+ BLI_assert(field->format.style == UI_TIP_STYLE_NORMAL);
+ const struct uiFontStyleDraw_Params fs_params = {
+ .align = UI_STYLE_TEXT_LEFT,
+ .word_wrap = true,
+ };
+
+ /* draw remaining data */
+ rgb_float_to_uchar(drawcol, tip_colors[field->format.color_id]);
+ UI_fontstyle_set(&data->fstyle);
+ UI_fontstyle_draw(&data->fstyle, &bbox, field->text, drawcol, &fs_params);
+ }
+
+ bbox.ymax -= data->lineh * field->geom.lines;
+
+ if (field_next && field_next->format.is_pad) {
+ bbox.ymax -= data->lineh * (UI_TIP_PAD_FAC - 1);
+ }
+ }
+
+ BLF_disable(data->fstyle.uifont_id, BLF_WORD_WRAP);
+ BLF_disable(blf_mono_font, BLF_WORD_WRAP);
}
static void ui_tooltip_region_free_cb(ARegion *ar)
{
- uiTooltipData *data;
-
- data = ar->regiondata;
-
- for (int i = 0; i < data->fields_len; i++) {
- const uiTooltipField *field = &data->fields[i];
- MEM_freeN(field->text);
- if (field->text_suffix) {
- MEM_freeN(field->text_suffix);
- }
- }
- MEM_freeN(data->fields);
- MEM_freeN(data);
- ar->regiondata = NULL;
+ uiTooltipData *data;
+
+ data = ar->regiondata;
+
+ for (int i = 0; i < data->fields_len; i++) {
+ const uiTooltipField *field = &data->fields[i];
+ MEM_freeN(field->text);
+ if (field->text_suffix) {
+ MEM_freeN(field->text_suffix);
+ }
+ }
+ MEM_freeN(data->fields);
+ MEM_freeN(data);
+ ar->regiondata = NULL;
}
/** \} */
@@ -302,929 +294,938 @@ static void ui_tooltip_region_free_cb(ARegion *ar)
/** \name ToolTip Creation
* \{ */
-static bool ui_tooltip_data_append_from_keymap(
- bContext *C, uiTooltipData *data,
- wmKeyMap *keymap)
+static bool ui_tooltip_data_append_from_keymap(bContext *C, uiTooltipData *data, wmKeyMap *keymap)
{
- const int fields_len_init = data->fields_len;
- char buf[512];
-
- for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) {
- wmOperatorType *ot = WM_operatortype_find(kmi->idname, true);
- if (ot != NULL) {
- /* Tip */
- {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_NORMAL,
- .color_id = UI_TIP_LC_MAIN,
- .is_pad = true,
- });
- field->text = BLI_strdup(ot->description ? ot->description : ot->name);
- }
- /* Shortcut */
- {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_NORMAL,
- .color_id = UI_TIP_LC_NORMAL,
- });
- bool found = false;
- if (WM_keymap_item_to_string(kmi, false, buf, sizeof(buf))) {
- found = true;
- }
- field->text = BLI_sprintfN(TIP_("Shortcut: %s"), found ? buf : "None");
- }
-
- /* Python */
- if (U.flag & USER_TOOLTIPS_PYTHON) {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_NORMAL,
- .color_id = UI_TIP_LC_PYTHON,
- });
- char *str = WM_operator_pystring_ex(C, NULL, false, false, ot, kmi->ptr);
- WM_operator_pystring_abbreviate(str, 32);
- field->text = BLI_sprintfN(TIP_("Python: %s"), str);
- MEM_freeN(str);
- }
- }
- }
-
- return (fields_len_init != data->fields_len);
+ const int fields_len_init = data->fields_len;
+ char buf[512];
+
+ for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) {
+ wmOperatorType *ot = WM_operatortype_find(kmi->idname, true);
+ if (ot != NULL) {
+ /* Tip */
+ {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_MAIN,
+ .is_pad = true,
+ });
+ field->text = BLI_strdup(ot->description ? ot->description : ot->name);
+ }
+ /* Shortcut */
+ {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_NORMAL,
+ });
+ bool found = false;
+ if (WM_keymap_item_to_string(kmi, false, buf, sizeof(buf))) {
+ found = true;
+ }
+ field->text = BLI_sprintfN(TIP_("Shortcut: %s"), found ? buf : "None");
+ }
+
+ /* Python */
+ if (U.flag & USER_TOOLTIPS_PYTHON) {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_PYTHON,
+ });
+ char *str = WM_operator_pystring_ex(C, NULL, false, false, ot, kmi->ptr);
+ WM_operator_pystring_abbreviate(str, 32);
+ field->text = BLI_sprintfN(TIP_("Python: %s"), str);
+ MEM_freeN(str);
+ }
+ }
+ }
+
+ return (fields_len_init != data->fields_len);
}
-
/**
* Special tool-system exception.
*/
static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is_label)
{
- if (but->optype == NULL) {
- return NULL;
- }
+ if (but->optype == NULL) {
+ return NULL;
+ }
- if (!STREQ(but->optype->idname, "WM_OT_tool_set_by_id")) {
- return NULL;
- }
+ if (!STREQ(but->optype->idname, "WM_OT_tool_set_by_id")) {
+ return NULL;
+ }
- /* Needed to get the space-data's type (below). */
- if (CTX_wm_space_data(C) == NULL) {
- return NULL;
- }
+ /* Needed to get the space-data's type (below). */
+ if (CTX_wm_space_data(C) == NULL) {
+ return NULL;
+ }
- char tool_id[MAX_NAME];
- RNA_string_get(but->opptr, "name", tool_id);
- BLI_assert(tool_id[0] != '\0');
+ char tool_id[MAX_NAME];
+ RNA_string_get(but->opptr, "name", tool_id);
+ BLI_assert(tool_id[0] != '\0');
- /* We have a tool, now extract the info. */
- uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
+ /* We have a tool, now extract the info. */
+ uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
#ifdef WITH_PYTHON
- /* it turns out to be most simple to do this via Python since C
- * doesn't have access to information about non-active tools.
- */
-
- /* Title (when icon-only). */
- if (but->drawstr[0] == '\0') {
- const char *expr_imports[] = {"bpy", "bl_ui", NULL};
- char expr[256];
- SNPRINTF(
- expr,
- "bl_ui.space_toolsystem_common.item_from_id("
- "bpy.context, "
- "bpy.context.space_data.type, "
- "'%s').label",
- tool_id);
- char *expr_result = NULL;
- bool is_error = false;
- if (BPY_execute_string_as_string(C, expr_imports, expr, true, &expr_result)) {
- if (STREQ(expr_result, "")) {
- MEM_freeN(expr_result);
- expr_result = NULL;
- }
- }
- else {
- /* Note, this is an exceptional case, we could even remove it
- * however there have been reports of tooltips failing, so keep it for now. */
- expr_result = BLI_strdup("Internal error!");
- is_error = true;
- }
-
- if (expr_result != NULL) {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_NORMAL,
- .color_id = UI_TIP_LC_MAIN,
- .is_pad = true,
- });
- field->text = expr_result;
-
- if (UNLIKELY(is_error)) {
- field->format.color_id = UI_TIP_LC_ALERT;
- }
- }
- }
-
- /* Tip. */
- if (is_label == false) {
- const char *expr_imports[] = {"bpy", "bl_ui", NULL};
- char expr[256];
- SNPRINTF(
- expr,
- "bl_ui.space_toolsystem_common.description_from_id("
- "bpy.context, "
- "bpy.context.space_data.type, "
- "'%s') + '.'",
- tool_id);
-
- char *expr_result = NULL;
- bool is_error = false;
- if (BPY_execute_string_as_string(C, expr_imports, expr, true, &expr_result)) {
- if (STREQ(expr_result, ".")) {
- MEM_freeN(expr_result);
- expr_result = NULL;
- }
- }
- else {
- /* Note, this is an exceptional case, we could even remove it
- * however there have been reports of tooltips failing, so keep it for now. */
- expr_result = BLI_strdup("Internal error!");
- is_error = true;
- }
-
- if (expr_result != NULL) {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_NORMAL,
- .color_id = UI_TIP_LC_MAIN,
- .is_pad = true,
- });
- field->text = expr_result;
-
- if (UNLIKELY(is_error)) {
- field->format.color_id = UI_TIP_LC_ALERT;
- }
- }
- }
-
- /* Shortcut. */
- if (is_label == false && ((but->block->flag & UI_BLOCK_SHOW_SHORTCUT_ALWAYS) == 0)) {
- /* There are different kinds of shortcuts:
- *
- * - Direct access to the tool (as if the toolbar button is pressed).
- * - The key is bound to a brush type (not the exact brush name).
- * - The key is assigned to the operator it's self (bypassing the tool, executing the operator).
- *
- * Either way case it's useful to show the shortcut.
- */
- char *shortcut = NULL;
-
- {
- uiStringInfo op_keymap = {BUT_GET_OP_KEYMAP, NULL};
- UI_but_string_info_get(C, but, &op_keymap, NULL);
- shortcut = op_keymap.strinfo;
- }
-
- if (shortcut == NULL) {
- ePaintMode paint_mode = BKE_paintmode_get_active_from_context(C);
- const char *tool_attr = BKE_paint_get_tool_prop_id_from_paintmode(paint_mode);
- if (tool_attr != NULL) {
- const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode);
- const int i = RNA_enum_from_name(items, tool_id);
- if (i != -1) {
- wmOperatorType *ot = WM_operatortype_find("paint.brush_select", true);
- PointerRNA op_props;
- WM_operator_properties_create_ptr(&op_props, ot);
- RNA_enum_set(&op_props, tool_attr, items[i].value);
-
- /* Check for direct access to the tool. */
- char shortcut_brush[128] = "";
- if (WM_key_event_operator_string(
- C, ot->idname, WM_OP_INVOKE_REGION_WIN, op_props.data, true,
- shortcut_brush, ARRAY_SIZE(shortcut_brush)))
- {
- shortcut = BLI_strdup(shortcut_brush);
- }
- WM_operator_properties_free(&op_props);
- }
- }
- }
-
- if (shortcut == NULL) {
- /* Check for direct access to the tool. */
- char shortcut_toolbar[128] = "";
- if (WM_key_event_operator_string(
- C, "WM_OT_toolbar", WM_OP_INVOKE_REGION_WIN, NULL, true,
- shortcut_toolbar, ARRAY_SIZE(shortcut_toolbar)))
- {
- /* Generate keymap in order to inspect it.
- * Note, we could make a utility to avoid the keymap generation part of this. */
- const char *expr_imports[] = {"bpy", "bl_keymap_utils", "bl_keymap_utils.keymap_from_toolbar", NULL};
- const char *expr = (
- "getattr("
- "bl_keymap_utils.keymap_from_toolbar.generate("
- "bpy.context, "
- "bpy.context.space_data.type), "
- "'as_pointer', lambda: 0)()");
-
- intptr_t expr_result = 0;
- 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) {
- if (STREQ(kmi->idname, but->optype->idname)) {
- char tool_id_test[MAX_NAME];
- RNA_string_get(kmi->ptr, "name", tool_id_test);
- if (STREQ(tool_id, tool_id_test)) {
- char buf[128];
- WM_keymap_item_to_string(kmi, false, buf, sizeof(buf));
- shortcut = BLI_sprintfN("%s, %s", shortcut_toolbar, buf);
- break;
- }
- }
- }
- }
- }
- else {
- BLI_assert(0);
- }
- }
- }
-
- if (shortcut != NULL) {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_NORMAL,
- .color_id = UI_TIP_LC_VALUE,
- .is_pad = true,
- });
- field->text = BLI_sprintfN(TIP_("Shortcut: %s"), shortcut);
- MEM_freeN(shortcut);
- }
- }
-
- /* Keymap */
-
- /* This is too handy not to expose somehow, let's be sneaky for now. */
- if ((is_label == false) && CTX_wm_window(C)->eventstate->shift) {
- const char *expr_imports[] = {"bpy", "bl_ui", NULL};
- char expr[256];
- SNPRINTF(
- expr,
- "getattr("
- "bl_ui.space_toolsystem_common.keymap_from_id("
- "bpy.context, "
- "bpy.context.space_data.type, "
- "'%s'), "
- "'as_pointer', lambda: 0)()",
- tool_id);
-
- intptr_t expr_result = 0;
- if (BPY_execute_string_as_intptr(C, expr_imports, expr, true, &expr_result)) {
- if (expr_result != 0) {
- {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_NORMAL,
- .color_id = UI_TIP_LC_NORMAL,
- .is_pad = true,
- });
- field->text = BLI_strdup("Tool Keymap:");
- }
- wmKeyMap *keymap = (wmKeyMap *)expr_result;
- ui_tooltip_data_append_from_keymap(C, data, keymap);
- }
- }
- else {
- BLI_assert(0);
- }
- }
-#endif /* WITH_PYTHON */
-
- if (data->fields_len == 0) {
- MEM_freeN(data);
- return NULL;
- }
- else {
- return data;
- }
+ /* it turns out to be most simple to do this via Python since C
+ * doesn't have access to information about non-active tools.
+ */
+
+ /* Title (when icon-only). */
+ if (but->drawstr[0] == '\0') {
+ const char *expr_imports[] = {"bpy", "bl_ui", NULL};
+ char expr[256];
+ SNPRINTF(expr,
+ "bl_ui.space_toolsystem_common.item_from_id("
+ "bpy.context, "
+ "bpy.context.space_data.type, "
+ "'%s').label",
+ tool_id);
+ char *expr_result = NULL;
+ bool is_error = false;
+ if (BPY_execute_string_as_string(C, expr_imports, expr, true, &expr_result)) {
+ if (STREQ(expr_result, "")) {
+ MEM_freeN(expr_result);
+ expr_result = NULL;
+ }
+ }
+ else {
+ /* Note, this is an exceptional case, we could even remove it
+ * however there have been reports of tooltips failing, so keep it for now. */
+ expr_result = BLI_strdup("Internal error!");
+ is_error = true;
+ }
+
+ if (expr_result != NULL) {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_MAIN,
+ .is_pad = true,
+ });
+ field->text = expr_result;
+
+ if (UNLIKELY(is_error)) {
+ field->format.color_id = UI_TIP_LC_ALERT;
+ }
+ }
+ }
+
+ /* Tip. */
+ if (is_label == false) {
+ const char *expr_imports[] = {"bpy", "bl_ui", NULL};
+ char expr[256];
+ SNPRINTF(expr,
+ "bl_ui.space_toolsystem_common.description_from_id("
+ "bpy.context, "
+ "bpy.context.space_data.type, "
+ "'%s') + '.'",
+ tool_id);
+
+ char *expr_result = NULL;
+ bool is_error = false;
+ if (BPY_execute_string_as_string(C, expr_imports, expr, true, &expr_result)) {
+ if (STREQ(expr_result, ".")) {
+ MEM_freeN(expr_result);
+ expr_result = NULL;
+ }
+ }
+ else {
+ /* Note, this is an exceptional case, we could even remove it
+ * however there have been reports of tooltips failing, so keep it for now. */
+ expr_result = BLI_strdup("Internal error!");
+ is_error = true;
+ }
+
+ if (expr_result != NULL) {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_MAIN,
+ .is_pad = true,
+ });
+ field->text = expr_result;
+
+ if (UNLIKELY(is_error)) {
+ field->format.color_id = UI_TIP_LC_ALERT;
+ }
+ }
+ }
+
+ /* Shortcut. */
+ if (is_label == false && ((but->block->flag & UI_BLOCK_SHOW_SHORTCUT_ALWAYS) == 0)) {
+ /* There are different kinds of shortcuts:
+ *
+ * - Direct access to the tool (as if the toolbar button is pressed).
+ * - The key is bound to a brush type (not the exact brush name).
+ * - The key is assigned to the operator it's self (bypassing the tool, executing the operator).
+ *
+ * Either way case it's useful to show the shortcut.
+ */
+ char *shortcut = NULL;
+
+ {
+ uiStringInfo op_keymap = {BUT_GET_OP_KEYMAP, NULL};
+ UI_but_string_info_get(C, but, &op_keymap, NULL);
+ shortcut = op_keymap.strinfo;
+ }
+
+ if (shortcut == NULL) {
+ ePaintMode paint_mode = BKE_paintmode_get_active_from_context(C);
+ const char *tool_attr = BKE_paint_get_tool_prop_id_from_paintmode(paint_mode);
+ if (tool_attr != NULL) {
+ const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode);
+ const int i = RNA_enum_from_name(items, tool_id);
+ if (i != -1) {
+ wmOperatorType *ot = WM_operatortype_find("paint.brush_select", true);
+ PointerRNA op_props;
+ WM_operator_properties_create_ptr(&op_props, ot);
+ RNA_enum_set(&op_props, tool_attr, items[i].value);
+
+ /* Check for direct access to the tool. */
+ char shortcut_brush[128] = "";
+ if (WM_key_event_operator_string(C,
+ ot->idname,
+ WM_OP_INVOKE_REGION_WIN,
+ op_props.data,
+ true,
+ shortcut_brush,
+ ARRAY_SIZE(shortcut_brush))) {
+ shortcut = BLI_strdup(shortcut_brush);
+ }
+ WM_operator_properties_free(&op_props);
+ }
+ }
+ }
+
+ if (shortcut == NULL) {
+ /* Check for direct access to the tool. */
+ char shortcut_toolbar[128] = "";
+ if (WM_key_event_operator_string(C,
+ "WM_OT_toolbar",
+ WM_OP_INVOKE_REGION_WIN,
+ NULL,
+ true,
+ shortcut_toolbar,
+ ARRAY_SIZE(shortcut_toolbar))) {
+ /* Generate keymap in order to inspect it.
+ * Note, we could make a utility to avoid the keymap generation part of this. */
+ const char *expr_imports[] = {
+ "bpy", "bl_keymap_utils", "bl_keymap_utils.keymap_from_toolbar", NULL};
+ const char *expr =
+ ("getattr("
+ "bl_keymap_utils.keymap_from_toolbar.generate("
+ "bpy.context, "
+ "bpy.context.space_data.type), "
+ "'as_pointer', lambda: 0)()");
+
+ intptr_t expr_result = 0;
+ 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) {
+ if (STREQ(kmi->idname, but->optype->idname)) {
+ char tool_id_test[MAX_NAME];
+ RNA_string_get(kmi->ptr, "name", tool_id_test);
+ if (STREQ(tool_id, tool_id_test)) {
+ char buf[128];
+ WM_keymap_item_to_string(kmi, false, buf, sizeof(buf));
+ shortcut = BLI_sprintfN("%s, %s", shortcut_toolbar, buf);
+ break;
+ }
+ }
+ }
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ }
+
+ if (shortcut != NULL) {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_VALUE,
+ .is_pad = true,
+ });
+ field->text = BLI_sprintfN(TIP_("Shortcut: %s"), shortcut);
+ MEM_freeN(shortcut);
+ }
+ }
+
+ /* Keymap */
+
+ /* This is too handy not to expose somehow, let's be sneaky for now. */
+ if ((is_label == false) && CTX_wm_window(C)->eventstate->shift) {
+ const char *expr_imports[] = {"bpy", "bl_ui", NULL};
+ char expr[256];
+ SNPRINTF(expr,
+ "getattr("
+ "bl_ui.space_toolsystem_common.keymap_from_id("
+ "bpy.context, "
+ "bpy.context.space_data.type, "
+ "'%s'), "
+ "'as_pointer', lambda: 0)()",
+ tool_id);
+
+ intptr_t expr_result = 0;
+ if (BPY_execute_string_as_intptr(C, expr_imports, expr, true, &expr_result)) {
+ if (expr_result != 0) {
+ {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_NORMAL,
+ .is_pad = true,
+ });
+ field->text = BLI_strdup("Tool Keymap:");
+ }
+ wmKeyMap *keymap = (wmKeyMap *)expr_result;
+ ui_tooltip_data_append_from_keymap(C, data, keymap);
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+#endif /* WITH_PYTHON */
+
+ if (data->fields_len == 0) {
+ MEM_freeN(data);
+ return NULL;
+ }
+ else {
+ return data;
+ }
}
static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
{
- uiStringInfo but_tip = {BUT_GET_TIP, NULL};
- uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL};
- uiStringInfo enum_tip = {BUT_GET_RNAENUM_TIP, NULL};
- uiStringInfo op_keymap = {BUT_GET_OP_KEYMAP, NULL};
- uiStringInfo prop_keymap = {BUT_GET_PROP_KEYMAP, NULL};
- uiStringInfo rna_struct = {BUT_GET_RNASTRUCT_IDENTIFIER, NULL};
- uiStringInfo rna_prop = {BUT_GET_RNAPROP_IDENTIFIER, NULL};
-
- char buf[512];
-
- /* create tooltip data */
- uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
-
- UI_but_string_info_get(C, but, &but_tip, &enum_label, &enum_tip, &op_keymap, &prop_keymap, &rna_struct, &rna_prop, NULL);
-
- /* Tip */
- if (but_tip.strinfo) {
- {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_HEADER,
- .color_id = UI_TIP_LC_NORMAL,
- });
- if (enum_label.strinfo) {
- field->text = BLI_sprintfN("%s: ", but_tip.strinfo);
- field->text_suffix = BLI_strdup(enum_label.strinfo);
- }
- else {
- field->text = BLI_sprintfN("%s.", but_tip.strinfo);
- }
- }
-
- /* special case enum rna buttons */
- if ((but->type & UI_BTYPE_ROW) && but->rnaprop && RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG) {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_NORMAL,
- .color_id = UI_TIP_LC_NORMAL,
- });
- field->text = BLI_strdup(IFACE_("(Shift-Click/Drag to select multiple)"));
- }
-
- }
- /* Enum field label & tip */
- if (enum_tip.strinfo) {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_NORMAL,
- .color_id = UI_TIP_LC_VALUE,
- .is_pad = true,
- });
- field->text = BLI_strdup(enum_tip.strinfo);
- }
-
- /* Op shortcut */
- if (op_keymap.strinfo) {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_NORMAL,
- .color_id = UI_TIP_LC_VALUE,
- .is_pad = true,
- });
- field->text = BLI_sprintfN(TIP_("Shortcut: %s"), op_keymap.strinfo);
- }
-
- /* Property context-toggle shortcut */
- if (prop_keymap.strinfo) {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_NORMAL,
- .color_id = UI_TIP_LC_VALUE,
- .is_pad = true,
- });
- field->text = BLI_sprintfN(TIP_("Shortcut: %s"), prop_keymap.strinfo);
- }
-
- if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
- /* better not show the value of a password */
- if ((but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD)) == 0) {
- /* full string */
- ui_but_string_get(but, buf, sizeof(buf));
- if (buf[0]) {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_NORMAL,
- .color_id = UI_TIP_LC_VALUE,
- .is_pad = true,
- });
- field->text = BLI_sprintfN(TIP_("Value: %s"), buf);
- }
- }
- }
-
- if (but->rnaprop) {
- int unit_type = UI_but_unit_type_get(but);
-
- if (unit_type == PROP_UNIT_ROTATION) {
- if (RNA_property_type(but->rnaprop) == PROP_FLOAT) {
- float value = RNA_property_array_check(but->rnaprop) ?
- RNA_property_float_get_index(&but->rnapoin, but->rnaprop, but->rnaindex) :
- RNA_property_float_get(&but->rnapoin, but->rnaprop);
-
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_NORMAL,
- .color_id = UI_TIP_LC_VALUE,
- });
- field->text = BLI_sprintfN(TIP_("Radians: %f"), value);
- }
- }
-
- if (but->flag & UI_BUT_DRIVEN) {
- if (ui_but_anim_expression_get(but, buf, sizeof(buf))) {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_NORMAL,
- .color_id = UI_TIP_LC_NORMAL,
- });
- field->text = BLI_sprintfN(TIP_("Expression: %s"), buf);
- }
- }
-
- if (but->rnapoin.id.data) {
- const ID *id = but->rnapoin.id.data;
- if (ID_IS_LINKED(id)) {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_NORMAL,
- .color_id = UI_TIP_LC_NORMAL,
- });
- field->text = BLI_sprintfN(TIP_("Library: %s"), id->lib->name);
- }
- }
- }
- else if (but->optype) {
- PointerRNA *opptr;
- char *str;
- opptr = UI_but_operator_ptr_get(but); /* allocated when needed, the button owns it */
-
- /* so the context is passed to fieldf functions (some py fieldf functions use it) */
- WM_operator_properties_sanitize(opptr, false);
-
- str = WM_operator_pystring_ex(C, NULL, false, false, but->optype, opptr);
-
- /* avoid overly verbose tips (eg, arrays of 20 layers), exact limit is arbitrary */
- WM_operator_pystring_abbreviate(str, 32);
-
- /* operator info */
- if (U.flag & USER_TOOLTIPS_PYTHON) {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_MONO,
- .color_id = UI_TIP_LC_PYTHON,
- .is_pad = true,
- });
- field->text = BLI_sprintfN(TIP_("Python: %s"), str);
- }
-
- MEM_freeN(str);
- }
-
- /* button is disabled, we may be able to tell user why */
- if (but->flag & UI_BUT_DISABLED) {
- const char *disabled_msg = NULL;
-
- /* if operator poll check failed, it can give pretty precise info why */
- if (but->optype) {
- CTX_wm_operator_poll_msg_set(C, NULL);
- WM_operator_poll_context(C, but->optype, but->opcontext);
- disabled_msg = CTX_wm_operator_poll_msg_get(C);
- }
- /* alternatively, buttons can store some reasoning too */
- else if (but->disabled_info) {
- disabled_msg = TIP_(but->disabled_info);
- }
-
- if (disabled_msg && disabled_msg[0]) {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_NORMAL,
- .color_id = UI_TIP_LC_ALERT,
- });
- field->text = BLI_sprintfN(TIP_("Disabled: %s"), disabled_msg);
- }
- }
-
- if ((U.flag & USER_TOOLTIPS_PYTHON) && !but->optype && rna_struct.strinfo) {
- {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_MONO,
- .color_id = UI_TIP_LC_PYTHON,
- .is_pad = true,
- });
- if (rna_prop.strinfo) {
- /* Struct and prop */
- field->text = BLI_sprintfN(TIP_("Python: %s.%s"), rna_struct.strinfo, rna_prop.strinfo);
- }
- else {
- /* Only struct (e.g. menus) */
- field->text = BLI_sprintfN(TIP_("Python: %s"), rna_struct.strinfo);
- }
- }
-
- if (but->rnapoin.id.data) {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_MONO,
- .color_id = UI_TIP_LC_PYTHON,
- });
-
- /* this could get its own 'BUT_GET_...' type */
-
- /* never fails */
- /* move ownership (no need for re-alloc) */
- if (but->rnaprop) {
- field->text = RNA_path_full_property_py_ex(&but->rnapoin, but->rnaprop, but->rnaindex, true);
- }
- else {
- field->text = RNA_path_full_struct_py(&but->rnapoin);
- }
-
- }
- }
-
- /* Free strinfo's... */
- if (but_tip.strinfo) {
- MEM_freeN(but_tip.strinfo);
- }
- if (enum_label.strinfo) {
- MEM_freeN(enum_label.strinfo);
- }
- if (enum_tip.strinfo) {
- MEM_freeN(enum_tip.strinfo);
- }
- if (op_keymap.strinfo) {
- MEM_freeN(op_keymap.strinfo);
- }
- if (prop_keymap.strinfo) {
- MEM_freeN(prop_keymap.strinfo);
- }
- if (rna_struct.strinfo) {
- MEM_freeN(rna_struct.strinfo);
- }
- if (rna_prop.strinfo) {
- MEM_freeN(rna_prop.strinfo);
- }
-
- if (data->fields_len == 0) {
- MEM_freeN(data);
- return NULL;
- }
- else {
- return data;
- }
+ uiStringInfo but_tip = {BUT_GET_TIP, NULL};
+ uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL};
+ uiStringInfo enum_tip = {BUT_GET_RNAENUM_TIP, NULL};
+ uiStringInfo op_keymap = {BUT_GET_OP_KEYMAP, NULL};
+ uiStringInfo prop_keymap = {BUT_GET_PROP_KEYMAP, NULL};
+ uiStringInfo rna_struct = {BUT_GET_RNASTRUCT_IDENTIFIER, NULL};
+ uiStringInfo rna_prop = {BUT_GET_RNAPROP_IDENTIFIER, NULL};
+
+ char buf[512];
+
+ /* create tooltip data */
+ uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
+
+ UI_but_string_info_get(C,
+ but,
+ &but_tip,
+ &enum_label,
+ &enum_tip,
+ &op_keymap,
+ &prop_keymap,
+ &rna_struct,
+ &rna_prop,
+ NULL);
+
+ /* Tip */
+ if (but_tip.strinfo) {
+ {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_HEADER,
+ .color_id = UI_TIP_LC_NORMAL,
+ });
+ if (enum_label.strinfo) {
+ field->text = BLI_sprintfN("%s: ", but_tip.strinfo);
+ field->text_suffix = BLI_strdup(enum_label.strinfo);
+ }
+ else {
+ field->text = BLI_sprintfN("%s.", but_tip.strinfo);
+ }
+ }
+
+ /* special case enum rna buttons */
+ if ((but->type & UI_BTYPE_ROW) && but->rnaprop &&
+ RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG) {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_NORMAL,
+ });
+ field->text = BLI_strdup(IFACE_("(Shift-Click/Drag to select multiple)"));
+ }
+ }
+ /* Enum field label & tip */
+ if (enum_tip.strinfo) {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_VALUE,
+ .is_pad = true,
+ });
+ field->text = BLI_strdup(enum_tip.strinfo);
+ }
+
+ /* Op shortcut */
+ if (op_keymap.strinfo) {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_VALUE,
+ .is_pad = true,
+ });
+ field->text = BLI_sprintfN(TIP_("Shortcut: %s"), op_keymap.strinfo);
+ }
+
+ /* Property context-toggle shortcut */
+ if (prop_keymap.strinfo) {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_VALUE,
+ .is_pad = true,
+ });
+ field->text = BLI_sprintfN(TIP_("Shortcut: %s"), prop_keymap.strinfo);
+ }
+
+ if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
+ /* better not show the value of a password */
+ if ((but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD)) == 0) {
+ /* full string */
+ ui_but_string_get(but, buf, sizeof(buf));
+ if (buf[0]) {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_VALUE,
+ .is_pad = true,
+ });
+ field->text = BLI_sprintfN(TIP_("Value: %s"), buf);
+ }
+ }
+ }
+
+ if (but->rnaprop) {
+ int unit_type = UI_but_unit_type_get(but);
+
+ if (unit_type == PROP_UNIT_ROTATION) {
+ if (RNA_property_type(but->rnaprop) == PROP_FLOAT) {
+ float value = RNA_property_array_check(but->rnaprop) ?
+ RNA_property_float_get_index(
+ &but->rnapoin, but->rnaprop, but->rnaindex) :
+ RNA_property_float_get(&but->rnapoin, but->rnaprop);
+
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_VALUE,
+ });
+ field->text = BLI_sprintfN(TIP_("Radians: %f"), value);
+ }
+ }
+
+ if (but->flag & UI_BUT_DRIVEN) {
+ if (ui_but_anim_expression_get(but, buf, sizeof(buf))) {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_NORMAL,
+ });
+ field->text = BLI_sprintfN(TIP_("Expression: %s"), buf);
+ }
+ }
+
+ if (but->rnapoin.id.data) {
+ const ID *id = but->rnapoin.id.data;
+ if (ID_IS_LINKED(id)) {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_NORMAL,
+ });
+ field->text = BLI_sprintfN(TIP_("Library: %s"), id->lib->name);
+ }
+ }
+ }
+ else if (but->optype) {
+ PointerRNA *opptr;
+ char *str;
+ opptr = UI_but_operator_ptr_get(but); /* allocated when needed, the button owns it */
+
+ /* so the context is passed to fieldf functions (some py fieldf functions use it) */
+ WM_operator_properties_sanitize(opptr, false);
+
+ str = WM_operator_pystring_ex(C, NULL, false, false, but->optype, opptr);
+
+ /* avoid overly verbose tips (eg, arrays of 20 layers), exact limit is arbitrary */
+ WM_operator_pystring_abbreviate(str, 32);
+
+ /* operator info */
+ if (U.flag & USER_TOOLTIPS_PYTHON) {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_MONO,
+ .color_id = UI_TIP_LC_PYTHON,
+ .is_pad = true,
+ });
+ field->text = BLI_sprintfN(TIP_("Python: %s"), str);
+ }
+
+ MEM_freeN(str);
+ }
+
+ /* button is disabled, we may be able to tell user why */
+ if (but->flag & UI_BUT_DISABLED) {
+ const char *disabled_msg = NULL;
+
+ /* if operator poll check failed, it can give pretty precise info why */
+ if (but->optype) {
+ CTX_wm_operator_poll_msg_set(C, NULL);
+ WM_operator_poll_context(C, but->optype, but->opcontext);
+ disabled_msg = CTX_wm_operator_poll_msg_get(C);
+ }
+ /* alternatively, buttons can store some reasoning too */
+ else if (but->disabled_info) {
+ disabled_msg = TIP_(but->disabled_info);
+ }
+
+ if (disabled_msg && disabled_msg[0]) {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_ALERT,
+ });
+ field->text = BLI_sprintfN(TIP_("Disabled: %s"), disabled_msg);
+ }
+ }
+
+ if ((U.flag & USER_TOOLTIPS_PYTHON) && !but->optype && rna_struct.strinfo) {
+ {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_MONO,
+ .color_id = UI_TIP_LC_PYTHON,
+ .is_pad = true,
+ });
+ if (rna_prop.strinfo) {
+ /* Struct and prop */
+ field->text = BLI_sprintfN(TIP_("Python: %s.%s"), rna_struct.strinfo, rna_prop.strinfo);
+ }
+ else {
+ /* Only struct (e.g. menus) */
+ field->text = BLI_sprintfN(TIP_("Python: %s"), rna_struct.strinfo);
+ }
+ }
+
+ if (but->rnapoin.id.data) {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_MONO,
+ .color_id = UI_TIP_LC_PYTHON,
+ });
+
+ /* this could get its own 'BUT_GET_...' type */
+
+ /* never fails */
+ /* move ownership (no need for re-alloc) */
+ if (but->rnaprop) {
+ field->text = RNA_path_full_property_py_ex(
+ &but->rnapoin, but->rnaprop, but->rnaindex, true);
+ }
+ else {
+ field->text = RNA_path_full_struct_py(&but->rnapoin);
+ }
+ }
+ }
+
+ /* Free strinfo's... */
+ if (but_tip.strinfo) {
+ MEM_freeN(but_tip.strinfo);
+ }
+ if (enum_label.strinfo) {
+ MEM_freeN(enum_label.strinfo);
+ }
+ if (enum_tip.strinfo) {
+ MEM_freeN(enum_tip.strinfo);
+ }
+ if (op_keymap.strinfo) {
+ MEM_freeN(op_keymap.strinfo);
+ }
+ if (prop_keymap.strinfo) {
+ MEM_freeN(prop_keymap.strinfo);
+ }
+ if (rna_struct.strinfo) {
+ MEM_freeN(rna_struct.strinfo);
+ }
+ if (rna_prop.strinfo) {
+ MEM_freeN(rna_prop.strinfo);
+ }
+
+ if (data->fields_len == 0) {
+ MEM_freeN(data);
+ return NULL;
+ }
+ else {
+ return data;
+ }
}
static uiTooltipData *ui_tooltip_data_from_gizmo(bContext *C, wmGizmo *gz)
{
- uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
-
- /* TODO(campbell): a way for gizmos to have their own descriptions (low priority). */
-
- /* Operator Actions */
- {
- bool use_drag = gz->drag_part != -1 && gz->highlight_part != gz->drag_part;
-
- const struct {
- int part;
- const char *prefix;
- } gzop_actions[] = {
- {
- .part = gz->highlight_part,
- .prefix = use_drag ? TIP_("Click") : NULL,
- }, {
- .part = use_drag ? gz->drag_part : -1,
- .prefix = use_drag ? TIP_("Drag") : NULL,
- },
- };
-
- for (int i = 0; i < ARRAY_SIZE(gzop_actions); i++) {
- wmGizmoOpElem *gzop = (gzop_actions[i].part != -1) ? WM_gizmo_operator_get(gz, gzop_actions[i].part) : NULL;
- if (gzop != NULL) {
- /* Description */
- const char *info = RNA_struct_ui_description(gzop->type->srna);
- if (!(info && info[0])) {
- info = RNA_struct_ui_name(gzop->type->srna);
- }
-
- if (info && info[0]) {
- char *text = NULL;
- if (gzop_actions[i].prefix != NULL) {
- text = BLI_sprintfN("%s: %s", gzop_actions[i].prefix, info);
- }
- else {
- text = BLI_strdup(info);
- }
-
- if (text != NULL) {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_HEADER,
- .color_id = UI_TIP_LC_VALUE,
- .is_pad = true,
- });
- field->text = text;
- }
- }
-
- /* Shortcut */
- {
- IDProperty *prop = gzop->ptr.data;
- char buf[128];
- if (WM_key_event_operator_string(
- C, gzop->type->idname, WM_OP_INVOKE_DEFAULT, prop, true,
- buf, ARRAY_SIZE(buf)))
- {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_NORMAL,
- .color_id = UI_TIP_LC_VALUE,
- .is_pad = true,
- });
- field->text = BLI_sprintfN(TIP_("Shortcut: %s"), buf);
- }
- }
- }
- }
- }
-
- /* Property Actions */
- if (gz->type->target_property_defs_len) {
- wmGizmoProperty *gz_prop_array = WM_gizmo_target_property_array(gz);
- for (int i = 0; i < gz->type->target_property_defs_len; i++) {
- /* TODO(campbell): function callback descriptions. */
- wmGizmoProperty *gz_prop = &gz_prop_array[i];
- if (gz_prop->prop != NULL) {
- const char *info = RNA_property_ui_description(gz_prop->prop);
- if (info && info[0]) {
- uiTooltipField *field = text_field_add(
- data, &(uiTooltipFormat){
- .style = UI_TIP_STYLE_NORMAL,
- .color_id = UI_TIP_LC_VALUE,
- .is_pad = true,
- });
- field->text = BLI_strdup(info);
- }
- }
- }
- }
-
- if (data->fields_len == 0) {
- MEM_freeN(data);
- return NULL;
- }
- else {
- return data;
- }
+ uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
+
+ /* TODO(campbell): a way for gizmos to have their own descriptions (low priority). */
+
+ /* Operator Actions */
+ {
+ bool use_drag = gz->drag_part != -1 && gz->highlight_part != gz->drag_part;
+
+ const struct {
+ int part;
+ const char *prefix;
+ } gzop_actions[] = {
+ {
+ .part = gz->highlight_part,
+ .prefix = use_drag ? TIP_("Click") : NULL,
+ },
+ {
+ .part = use_drag ? gz->drag_part : -1,
+ .prefix = use_drag ? TIP_("Drag") : NULL,
+ },
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(gzop_actions); i++) {
+ wmGizmoOpElem *gzop = (gzop_actions[i].part != -1) ?
+ WM_gizmo_operator_get(gz, gzop_actions[i].part) :
+ NULL;
+ if (gzop != NULL) {
+ /* Description */
+ const char *info = RNA_struct_ui_description(gzop->type->srna);
+ if (!(info && info[0])) {
+ info = RNA_struct_ui_name(gzop->type->srna);
+ }
+
+ if (info && info[0]) {
+ char *text = NULL;
+ if (gzop_actions[i].prefix != NULL) {
+ text = BLI_sprintfN("%s: %s", gzop_actions[i].prefix, info);
+ }
+ else {
+ text = BLI_strdup(info);
+ }
+
+ if (text != NULL) {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_HEADER,
+ .color_id = UI_TIP_LC_VALUE,
+ .is_pad = true,
+ });
+ field->text = text;
+ }
+ }
+
+ /* Shortcut */
+ {
+ IDProperty *prop = gzop->ptr.data;
+ char buf[128];
+ if (WM_key_event_operator_string(
+ C, gzop->type->idname, WM_OP_INVOKE_DEFAULT, prop, true, buf, ARRAY_SIZE(buf))) {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_VALUE,
+ .is_pad = true,
+ });
+ field->text = BLI_sprintfN(TIP_("Shortcut: %s"), buf);
+ }
+ }
+ }
+ }
+ }
+
+ /* Property Actions */
+ if (gz->type->target_property_defs_len) {
+ wmGizmoProperty *gz_prop_array = WM_gizmo_target_property_array(gz);
+ for (int i = 0; i < gz->type->target_property_defs_len; i++) {
+ /* TODO(campbell): function callback descriptions. */
+ wmGizmoProperty *gz_prop = &gz_prop_array[i];
+ if (gz_prop->prop != NULL) {
+ const char *info = RNA_property_ui_description(gz_prop->prop);
+ if (info && info[0]) {
+ uiTooltipField *field = text_field_add(data,
+ &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_VALUE,
+ .is_pad = true,
+ });
+ field->text = BLI_strdup(info);
+ }
+ }
+ }
+ }
+
+ if (data->fields_len == 0) {
+ MEM_freeN(data);
+ return NULL;
+ }
+ else {
+ return data;
+ }
}
-
-static ARegion *ui_tooltip_create_with_data(
- bContext *C, uiTooltipData *data,
- const float init_position[2], const rcti *init_rect_overlap,
- const float aspect)
+static ARegion *ui_tooltip_create_with_data(bContext *C,
+ uiTooltipData *data,
+ const float init_position[2],
+ const rcti *init_rect_overlap,
+ const float aspect)
{
- const float pad_px = UI_TIP_PADDING;
- 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();
- static ARegionType type;
- ARegion *ar;
- 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));
-
- 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;
-
- /* set font, get bb */
- data->fstyle = style->widget; /* copy struct */
- ui_fontscale(&data->fstyle.points, aspect);
-
- UI_fontstyle_set(&data->fstyle);
-
- data->wrap_width = min_ii(UI_TIP_MAXWIDTH * U.pixelsize / aspect, winx - (UI_TIP_PADDING * 2));
-
- font_flag |= BLF_WORD_WRAP;
- if (data->fstyle.kerning == 1) {
- font_flag |= BLF_KERNING_DEFAULT;
- }
- BLF_enable(data->fstyle.uifont_id, font_flag);
- BLF_enable(blf_mono_font, font_flag);
- BLF_wordwrap(data->fstyle.uifont_id, data->wrap_width);
- BLF_wordwrap(blf_mono_font, data->wrap_width);
-
- /* these defines tweaked depending on font */
+ const float pad_px = UI_TIP_PADDING;
+ 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();
+ static ARegionType type;
+ ARegion *ar;
+ 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));
+
+ 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;
+
+ /* set font, get bb */
+ data->fstyle = style->widget; /* copy struct */
+ ui_fontscale(&data->fstyle.points, aspect);
+
+ UI_fontstyle_set(&data->fstyle);
+
+ data->wrap_width = min_ii(UI_TIP_MAXWIDTH * U.pixelsize / aspect, winx - (UI_TIP_PADDING * 2));
+
+ font_flag |= BLF_WORD_WRAP;
+ if (data->fstyle.kerning == 1) {
+ font_flag |= BLF_KERNING_DEFAULT;
+ }
+ BLF_enable(data->fstyle.uifont_id, font_flag);
+ BLF_enable(blf_mono_font, font_flag);
+ BLF_wordwrap(data->fstyle.uifont_id, data->wrap_width);
+ BLF_wordwrap(blf_mono_font, data->wrap_width);
+
+ /* these defines tweaked depending on font */
#define TIP_BORDER_X (16.0f / aspect)
#define TIP_BORDER_Y (6.0f / aspect)
- h = BLF_height_max(data->fstyle.uifont_id);
-
- for (i = 0, fontw = 0, fonth = 0; i < data->fields_len; i++) {
- uiTooltipField *field = &data->fields[i];
- uiTooltipField *field_next = (i + 1) != data->fields_len ? &data->fields[i + 1] : NULL;
-
- struct ResultBLF info;
- int w, x_pos = 0;
- int font_id;
-
- if (field->format.style == UI_TIP_STYLE_MONO) {
- BLF_size(blf_mono_font, data->fstyle.points * U.pixelsize, U.dpi);
- font_id = blf_mono_font;
- }
- else {
- BLI_assert(ELEM(field->format.style, UI_TIP_STYLE_NORMAL, UI_TIP_STYLE_HEADER));
- font_id = data->fstyle.uifont_id;
- }
- w = BLF_width_ex(font_id, field->text, BLF_DRAW_STR_DUMMY_MAX, &info);
-
- /* check for suffix (enum label) */
- if (field->text_suffix && field->text_suffix[0]) {
- x_pos = info.width;
- w = max_ii(w, x_pos + BLF_width(font_id, field->text_suffix, BLF_DRAW_STR_DUMMY_MAX));
- }
- fontw = max_ii(fontw, w);
-
- fonth += h * info.lines;
- if (field_next && field_next->format.is_pad) {
- fonth += h * (UI_TIP_PAD_FAC - 1);
- }
-
- field->geom.lines = info.lines;
- field->geom.x_pos = x_pos;
- }
-
- //fontw *= aspect;
-
- BLF_disable(data->fstyle.uifont_id, font_flag);
- BLF_disable(blf_mono_font, font_flag);
-
- ar->regiondata = data;
-
- data->toth = fonth;
- data->lineh = h;
-
- /* Compute position. */
- {
- rctf rect_fl;
- rect_fl.xmin = init_position[0] - TIP_BORDER_X;
- rect_fl.xmax = rect_fl.xmin + fontw + pad_px;
- rect_fl.ymax = init_position[1] - TIP_BORDER_Y;
- rect_fl.ymin = rect_fl.ymax - fonth - TIP_BORDER_Y;
- BLI_rcti_rctf_copy(&rect_i, &rect_fl);
- }
+ h = BLF_height_max(data->fstyle.uifont_id);
+
+ for (i = 0, fontw = 0, fonth = 0; i < data->fields_len; i++) {
+ uiTooltipField *field = &data->fields[i];
+ uiTooltipField *field_next = (i + 1) != data->fields_len ? &data->fields[i + 1] : NULL;
+
+ struct ResultBLF info;
+ int w, x_pos = 0;
+ int font_id;
+
+ if (field->format.style == UI_TIP_STYLE_MONO) {
+ BLF_size(blf_mono_font, data->fstyle.points * U.pixelsize, U.dpi);
+ font_id = blf_mono_font;
+ }
+ else {
+ BLI_assert(ELEM(field->format.style, UI_TIP_STYLE_NORMAL, UI_TIP_STYLE_HEADER));
+ font_id = data->fstyle.uifont_id;
+ }
+ w = BLF_width_ex(font_id, field->text, BLF_DRAW_STR_DUMMY_MAX, &info);
+
+ /* check for suffix (enum label) */
+ if (field->text_suffix && field->text_suffix[0]) {
+ x_pos = info.width;
+ w = max_ii(w, x_pos + BLF_width(font_id, field->text_suffix, BLF_DRAW_STR_DUMMY_MAX));
+ }
+ fontw = max_ii(fontw, w);
+
+ fonth += h * info.lines;
+ if (field_next && field_next->format.is_pad) {
+ fonth += h * (UI_TIP_PAD_FAC - 1);
+ }
+
+ field->geom.lines = info.lines;
+ field->geom.x_pos = x_pos;
+ }
+
+ //fontw *= aspect;
+
+ BLF_disable(data->fstyle.uifont_id, font_flag);
+ BLF_disable(blf_mono_font, font_flag);
+
+ ar->regiondata = data;
+
+ data->toth = fonth;
+ data->lineh = h;
+
+ /* Compute position. */
+ {
+ rctf rect_fl;
+ rect_fl.xmin = init_position[0] - TIP_BORDER_X;
+ rect_fl.xmax = rect_fl.xmin + fontw + pad_px;
+ rect_fl.ymax = init_position[1] - TIP_BORDER_Y;
+ rect_fl.ymin = rect_fl.ymax - fonth - TIP_BORDER_Y;
+ BLI_rcti_rctf_copy(&rect_i, &rect_fl);
+ }
#undef TIP_BORDER_X
#undef TIP_BORDER_Y
-// #define USE_ALIGN_Y_CENTER
-
- /* Clamp to window bounds. */
- {
- /* Ensure at least 5 px above screen bounds
- * UI_UNIT_Y is just a guess to be above the menu item */
- if (init_rect_overlap != NULL) {
- const int pad = max_ff(1.0f, U.pixelsize) * 5;
- const rcti init_rect = {
- .xmin = init_rect_overlap->xmin - pad,
- .xmax = init_rect_overlap->xmax + pad,
- .ymin = init_rect_overlap->ymin - pad,
- .ymax = init_rect_overlap->ymax + pad,
- };
- const rcti rect_clamp = {
- .xmin = 0,
- .xmax = winx,
- .ymin = 0,
- .ymax = winy,
- };
- /* try right. */
- const int size_x = BLI_rcti_size_x(&rect_i);
- const int size_y = BLI_rcti_size_y(&rect_i);
- const int cent_overlap_x = BLI_rcti_cent_x(&init_rect);
+ // #define USE_ALIGN_Y_CENTER
+
+ /* Clamp to window bounds. */
+ {
+ /* Ensure at least 5 px above screen bounds
+ * UI_UNIT_Y is just a guess to be above the menu item */
+ if (init_rect_overlap != NULL) {
+ const int pad = max_ff(1.0f, U.pixelsize) * 5;
+ const rcti init_rect = {
+ .xmin = init_rect_overlap->xmin - pad,
+ .xmax = init_rect_overlap->xmax + pad,
+ .ymin = init_rect_overlap->ymin - pad,
+ .ymax = init_rect_overlap->ymax + pad,
+ };
+ const rcti rect_clamp = {
+ .xmin = 0,
+ .xmax = winx,
+ .ymin = 0,
+ .ymax = winy,
+ };
+ /* try right. */
+ const int size_x = BLI_rcti_size_x(&rect_i);
+ const int size_y = BLI_rcti_size_y(&rect_i);
+ const int cent_overlap_x = BLI_rcti_cent_x(&init_rect);
#ifdef USE_ALIGN_Y_CENTER
- const int cent_overlap_y = BLI_rcti_cent_y(&init_rect);
+ const int cent_overlap_y = BLI_rcti_cent_y(&init_rect);
#endif
- struct {
- rcti xpos;
- rcti xneg;
- rcti ypos;
- rcti yneg;
- } rect;
-
- { /* xpos */
- rcti r = rect_i;
- r.xmin = init_rect.xmax;
- r.xmax = r.xmin + size_x;
+ struct {
+ rcti xpos;
+ rcti xneg;
+ rcti ypos;
+ rcti yneg;
+ } rect;
+
+ { /* xpos */
+ rcti r = rect_i;
+ r.xmin = init_rect.xmax;
+ r.xmax = r.xmin + size_x;
#ifdef USE_ALIGN_Y_CENTER
- r.ymin = cent_overlap_y - (size_y / 2);
- r.ymax = r.ymin + size_y;
+ r.ymin = cent_overlap_y - (size_y / 2);
+ r.ymax = r.ymin + size_y;
#else
- r.ymin = init_rect.ymax - BLI_rcti_size_y(&rect_i);
- r.ymax = init_rect.ymax;
- r.ymin -= UI_POPUP_MARGIN;
- r.ymax -= UI_POPUP_MARGIN;
+ r.ymin = init_rect.ymax - BLI_rcti_size_y(&rect_i);
+ r.ymax = init_rect.ymax;
+ r.ymin -= UI_POPUP_MARGIN;
+ r.ymax -= UI_POPUP_MARGIN;
#endif
- rect.xpos = r;
- }
- { /* xneg */
- rcti r = rect_i;
- r.xmin = init_rect.xmin - size_x;
- r.xmax = r.xmin + size_x;
+ rect.xpos = r;
+ }
+ { /* xneg */
+ rcti r = rect_i;
+ r.xmin = init_rect.xmin - size_x;
+ r.xmax = r.xmin + size_x;
#ifdef USE_ALIGN_Y_CENTER
- r.ymin = cent_overlap_y - (size_y / 2);
- r.ymax = r.ymin + size_y;
+ r.ymin = cent_overlap_y - (size_y / 2);
+ r.ymax = r.ymin + size_y;
#else
- r.ymin = init_rect.ymax - BLI_rcti_size_y(&rect_i);
- r.ymax = init_rect.ymax;
- r.ymin -= UI_POPUP_MARGIN;
- r.ymax -= UI_POPUP_MARGIN;
+ r.ymin = init_rect.ymax - BLI_rcti_size_y(&rect_i);
+ r.ymax = init_rect.ymax;
+ r.ymin -= UI_POPUP_MARGIN;
+ r.ymax -= UI_POPUP_MARGIN;
#endif
- rect.xneg = r;
- }
- { /* ypos */
- rcti r = rect_i;
- r.xmin = cent_overlap_x - (size_x / 2);
- r.xmax = r.xmin + size_x;
- r.ymin = init_rect.ymax;
- r.ymax = r.ymin + size_y;
- rect.ypos = r;
- }
- { /* yneg */
- rcti r = rect_i;
- r.xmin = cent_overlap_x - (size_x / 2);
- r.xmax = r.xmin + size_x;
- r.ymin = init_rect.ymin - size_y;
- r.ymax = r.ymin + size_y;
- rect.yneg = r;
- }
-
- bool found = false;
- for (int j = 0; j < 4; j++) {
- const rcti *r = (&rect.xpos) + j;
- if (BLI_rcti_inside_rcti(&rect_clamp, r)) {
- rect_i = *r;
- found = true;
- break;
- }
- }
- if (!found) {
- /* Fallback, we could pick the best fallback, for now just use xpos. */
- int offset_dummy[2];
- rect_i = rect.xpos;
- BLI_rcti_clamp(&rect_i, &rect_clamp, offset_dummy);
- }
-
- }
- else {
- const int pad = max_ff(1.0f, U.pixelsize) * 5;
- const rcti rect_clamp = {
- .xmin = pad,
- .xmax = winx - pad,
- .ymin = pad + (UI_UNIT_Y * 2),
- .ymax = winy - pad,
- };
- int offset_dummy[2];
- BLI_rcti_clamp(&rect_i, &rect_clamp, offset_dummy);
- }
- }
+ rect.xneg = r;
+ }
+ { /* ypos */
+ rcti r = rect_i;
+ r.xmin = cent_overlap_x - (size_x / 2);
+ r.xmax = r.xmin + size_x;
+ r.ymin = init_rect.ymax;
+ r.ymax = r.ymin + size_y;
+ rect.ypos = r;
+ }
+ { /* yneg */
+ rcti r = rect_i;
+ r.xmin = cent_overlap_x - (size_x / 2);
+ r.xmax = r.xmin + size_x;
+ r.ymin = init_rect.ymin - size_y;
+ r.ymax = r.ymin + size_y;
+ rect.yneg = r;
+ }
+
+ bool found = false;
+ for (int j = 0; j < 4; j++) {
+ const rcti *r = (&rect.xpos) + j;
+ if (BLI_rcti_inside_rcti(&rect_clamp, r)) {
+ rect_i = *r;
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ /* Fallback, we could pick the best fallback, for now just use xpos. */
+ int offset_dummy[2];
+ rect_i = rect.xpos;
+ BLI_rcti_clamp(&rect_i, &rect_clamp, offset_dummy);
+ }
+ }
+ else {
+ const int pad = max_ff(1.0f, U.pixelsize) * 5;
+ const rcti rect_clamp = {
+ .xmin = pad,
+ .xmax = winx - pad,
+ .ymin = pad + (UI_UNIT_Y * 2),
+ .ymax = winy - pad,
+ };
+ int offset_dummy[2];
+ BLI_rcti_clamp(&rect_i, &rect_clamp, offset_dummy);
+ }
+ }
#undef USE_ALIGN_Y_CENTER
- /* add padding */
- BLI_rcti_resize(&rect_i,
- BLI_rcti_size_x(&rect_i) + pad_px,
- BLI_rcti_size_y(&rect_i) + pad_px);
-
- /* widget rect, in region coords */
- {
- /* Compensate for margin offset, visually this corrects the position. */
- const int margin = UI_POPUP_MARGIN;
- if (init_rect_overlap != NULL) {
- BLI_rcti_translate(&rect_i, margin, margin / 2);
- }
-
- data->bbox.xmin = margin;
- data->bbox.xmax = BLI_rcti_size_x(&rect_i) - margin;
- data->bbox.ymin = margin;
- 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;
- }
-
- /* adds subwindow */
- ED_region_init(ar);
-
- /* notify change and redraw */
- ED_region_tag_redraw(ar);
-
- return ar;
+ /* add padding */
+ BLI_rcti_resize(&rect_i, BLI_rcti_size_x(&rect_i) + pad_px, BLI_rcti_size_y(&rect_i) + pad_px);
+
+ /* widget rect, in region coords */
+ {
+ /* Compensate for margin offset, visually this corrects the position. */
+ const int margin = UI_POPUP_MARGIN;
+ if (init_rect_overlap != NULL) {
+ BLI_rcti_translate(&rect_i, margin, margin / 2);
+ }
+
+ data->bbox.xmin = margin;
+ data->bbox.xmax = BLI_rcti_size_x(&rect_i) - margin;
+ data->bbox.ymin = margin;
+ 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;
+ }
+
+ /* adds subwindow */
+ ED_region_init(ar);
+
+ /* notify change and redraw */
+ ED_region_tag_redraw(ar);
+
+ return ar;
}
/** \} */
@@ -1233,80 +1234,80 @@ static ARegion *ui_tooltip_create_with_data(
/** \name ToolTip Public API
* \{ */
-
ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *but, bool is_label)
{
- wmWindow *win = CTX_wm_window(C);
- /* aspect values that shrink text are likely unreadable */
- const float aspect = min_ff(1.0f, but->block->aspect);
- float init_position[2];
-
- if (but->drawflag & UI_BUT_NO_TOOLTIP) {
- return NULL;
- }
- uiTooltipData *data = NULL;
-
- if (data == NULL) {
- data = ui_tooltip_data_from_tool(C, but, is_label);
- }
-
- if (data == NULL) {
- data = ui_tooltip_data_from_button(C, but);
- }
-
- if (data == NULL) {
- return NULL;
- }
-
- const bool is_no_overlap = UI_but_has_tooltip_label(but) || UI_but_is_tool(but);
- rcti init_rect;
- if (is_no_overlap) {
- rctf overlap_rect_fl;
- init_position[0] = BLI_rctf_cent_x(&but->rect);
- init_position[1] = BLI_rctf_cent_y(&but->rect);
- if (butregion) {
- ui_block_to_window_fl(butregion, but->block, &init_position[0], &init_position[1]);
- ui_block_to_window_rctf(butregion, but->block, &overlap_rect_fl, &but->rect);
- }
- else {
- overlap_rect_fl = but->rect;
- }
- BLI_rcti_rctf_copy_round(&init_rect, &overlap_rect_fl);
- }
- else {
- init_position[0] = BLI_rctf_cent_x(&but->rect);
- init_position[1] = but->rect.ymin - (UI_POPUP_MARGIN / 2);
- if (butregion) {
- ui_block_to_window_fl(butregion, but->block, &init_position[0], &init_position[1]);
- init_position[0] = win->eventstate->x;
- }
- }
-
- ARegion *ar = ui_tooltip_create_with_data(C, data, init_position, is_no_overlap ? &init_rect : NULL, aspect);
-
- return ar;
+ wmWindow *win = CTX_wm_window(C);
+ /* aspect values that shrink text are likely unreadable */
+ const float aspect = min_ff(1.0f, but->block->aspect);
+ float init_position[2];
+
+ if (but->drawflag & UI_BUT_NO_TOOLTIP) {
+ return NULL;
+ }
+ uiTooltipData *data = NULL;
+
+ if (data == NULL) {
+ data = ui_tooltip_data_from_tool(C, but, is_label);
+ }
+
+ if (data == NULL) {
+ data = ui_tooltip_data_from_button(C, but);
+ }
+
+ if (data == NULL) {
+ return NULL;
+ }
+
+ const bool is_no_overlap = UI_but_has_tooltip_label(but) || UI_but_is_tool(but);
+ rcti init_rect;
+ if (is_no_overlap) {
+ rctf overlap_rect_fl;
+ init_position[0] = BLI_rctf_cent_x(&but->rect);
+ init_position[1] = BLI_rctf_cent_y(&but->rect);
+ if (butregion) {
+ ui_block_to_window_fl(butregion, but->block, &init_position[0], &init_position[1]);
+ ui_block_to_window_rctf(butregion, but->block, &overlap_rect_fl, &but->rect);
+ }
+ else {
+ overlap_rect_fl = but->rect;
+ }
+ BLI_rcti_rctf_copy_round(&init_rect, &overlap_rect_fl);
+ }
+ else {
+ init_position[0] = BLI_rctf_cent_x(&but->rect);
+ init_position[1] = but->rect.ymin - (UI_POPUP_MARGIN / 2);
+ if (butregion) {
+ ui_block_to_window_fl(butregion, but->block, &init_position[0], &init_position[1]);
+ init_position[0] = win->eventstate->x;
+ }
+ }
+
+ ARegion *ar = ui_tooltip_create_with_data(
+ C, data, init_position, is_no_overlap ? &init_rect : NULL, aspect);
+
+ return ar;
}
ARegion *UI_tooltip_create_from_gizmo(bContext *C, wmGizmo *gz)
{
- wmWindow *win = CTX_wm_window(C);
- const float aspect = 1.0f;
- float init_position[2];
+ wmWindow *win = CTX_wm_window(C);
+ const float aspect = 1.0f;
+ float init_position[2];
- uiTooltipData *data = ui_tooltip_data_from_gizmo(C, gz);
- if (data == NULL) {
- return NULL;
- }
+ uiTooltipData *data = ui_tooltip_data_from_gizmo(C, gz);
+ if (data == NULL) {
+ return NULL;
+ }
- init_position[0] = win->eventstate->x;
- init_position[1] = win->eventstate->y;
+ init_position[0] = win->eventstate->x;
+ init_position[1] = win->eventstate->y;
- return ui_tooltip_create_with_data(C, data, init_position, NULL, aspect);
+ return ui_tooltip_create_with_data(C, data, init_position, NULL, aspect);
}
void UI_tooltip_free(bContext *C, bScreen *sc, ARegion *ar)
{
- ui_region_temp_remove(C, sc, ar);
+ ui_region_temp_remove(C, sc, ar);
}
/** \} */
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 933864c1cb4..5ba4dcd7439 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -41,28 +41,28 @@
ARegion *ui_region_temp_add(bScreen *sc)
{
- ARegion *ar;
+ ARegion *ar;
- ar = MEM_callocN(sizeof(ARegion), "area region");
- BLI_addtail(&sc->regionbase, ar);
+ ar = MEM_callocN(sizeof(ARegion), "area region");
+ BLI_addtail(&sc->regionbase, ar);
- ar->regiontype = RGN_TYPE_TEMPORARY;
- ar->alignment = RGN_ALIGN_FLOAT;
+ ar->regiontype = RGN_TYPE_TEMPORARY;
+ ar->alignment = RGN_ALIGN_FLOAT;
- return ar;
+ return ar;
}
void ui_region_temp_remove(bContext *C, bScreen *sc, ARegion *ar)
{
- wmWindow *win = CTX_wm_window(C);
+ wmWindow *win = CTX_wm_window(C);
- BLI_assert(ar->regiontype == RGN_TYPE_TEMPORARY);
- BLI_assert(BLI_findindex(&sc->regionbase, ar) != -1);
- if (win) {
- wm_draw_region_clear(win, ar);
- }
+ BLI_assert(ar->regiontype == RGN_TYPE_TEMPORARY);
+ BLI_assert(BLI_findindex(&sc->regionbase, ar) != -1);
+ if (win) {
+ wm_draw_region_clear(win, ar);
+ }
- ED_region_exit(C, ar);
- BKE_area_region_free(NULL, ar); /* NULL: no spacetype */
- BLI_freelinkN(&sc->regionbase, ar);
+ ED_region_exit(C, ar);
+ BKE_area_region_free(NULL, ar); /* NULL: no spacetype */
+ BLI_freelinkN(&sc->regionbase, ar);
}
diff --git a/source/blender/editors/interface/interface_regions_intern.h b/source/blender/editors/interface/interface_regions_intern.h
index fb71cbd788b..31a0a0876a2 100644
--- a/source/blender/editors/interface/interface_regions_intern.h
+++ b/source/blender/editors/interface/interface_regions_intern.h
@@ -28,6 +28,6 @@ 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);
+void ui_region_temp_remove(struct bContext *C, bScreen *sc, ARegion *ar);
-#endif /* __INTERFACE_REGIONS_INTERN_H__ */
+#endif /* __INTERFACE_REGIONS_INTERN_H__ */
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index eecd5885c74..192571044b9 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -21,7 +21,6 @@
* \ingroup edinterface
*/
-
#include <limits.h>
#include <math.h>
#include <stdlib.h>
@@ -71,205 +70,216 @@
* - font types, styles and relative sizes for Panel titles, labels, etc.
*/
-
/* ********************************************** */
static uiStyle *ui_style_new(ListBase *styles, const char *name, short uifont_id)
{
- uiStyle *style = MEM_callocN(sizeof(uiStyle), "new style");
-
- BLI_addtail(styles, style);
- BLI_strncpy(style->name, name, MAX_STYLE_NAME);
-
- style->panelzoom = 1.0; /* unused */
-
- style->paneltitle.uifont_id = uifont_id;
- style->paneltitle.points = 12;
- style->paneltitle.kerning = 1;
- style->paneltitle.shadow = 3;
- style->paneltitle.shadx = 0;
- style->paneltitle.shady = -1;
- style->paneltitle.shadowalpha = 0.5f;
- style->paneltitle.shadowcolor = 0.0f;
-
- style->grouplabel.uifont_id = uifont_id;
- style->grouplabel.points = 12;
- style->grouplabel.kerning = 1;
- style->grouplabel.shadow = 3;
- style->grouplabel.shadx = 0;
- style->grouplabel.shady = -1;
- style->grouplabel.shadowalpha = 0.5f;
- style->grouplabel.shadowcolor = 0.0f;
-
- style->widgetlabel.uifont_id = uifont_id;
- style->widgetlabel.points = 11;
- style->widgetlabel.kerning = 1;
- style->widgetlabel.shadow = 3;
- style->widgetlabel.shadx = 0;
- style->widgetlabel.shady = -1;
- style->widgetlabel.shadowalpha = 0.5f;
- style->widgetlabel.shadowcolor = 0.0f;
-
- style->widget.uifont_id = uifont_id;
- style->widget.points = 11;
- style->widget.kerning = 1;
- style->widget.shadow = 1;
- style->widget.shady = -1;
- style->widget.shadowalpha = 0.5f;
- style->widget.shadowcolor = 0.0f;
-
- style->columnspace = 8;
- style->templatespace = 5;
- style->boxspace = 5;
- style->buttonspacex = 8;
- style->buttonspacey = 2;
- style->panelspace = 8;
- style->panelouter = 4;
-
- return style;
+ uiStyle *style = MEM_callocN(sizeof(uiStyle), "new style");
+
+ BLI_addtail(styles, style);
+ BLI_strncpy(style->name, name, MAX_STYLE_NAME);
+
+ style->panelzoom = 1.0; /* unused */
+
+ style->paneltitle.uifont_id = uifont_id;
+ style->paneltitle.points = 12;
+ style->paneltitle.kerning = 1;
+ style->paneltitle.shadow = 3;
+ style->paneltitle.shadx = 0;
+ style->paneltitle.shady = -1;
+ style->paneltitle.shadowalpha = 0.5f;
+ style->paneltitle.shadowcolor = 0.0f;
+
+ style->grouplabel.uifont_id = uifont_id;
+ style->grouplabel.points = 12;
+ style->grouplabel.kerning = 1;
+ style->grouplabel.shadow = 3;
+ style->grouplabel.shadx = 0;
+ style->grouplabel.shady = -1;
+ style->grouplabel.shadowalpha = 0.5f;
+ style->grouplabel.shadowcolor = 0.0f;
+
+ style->widgetlabel.uifont_id = uifont_id;
+ style->widgetlabel.points = 11;
+ style->widgetlabel.kerning = 1;
+ style->widgetlabel.shadow = 3;
+ style->widgetlabel.shadx = 0;
+ style->widgetlabel.shady = -1;
+ style->widgetlabel.shadowalpha = 0.5f;
+ style->widgetlabel.shadowcolor = 0.0f;
+
+ style->widget.uifont_id = uifont_id;
+ style->widget.points = 11;
+ style->widget.kerning = 1;
+ style->widget.shadow = 1;
+ style->widget.shady = -1;
+ style->widget.shadowalpha = 0.5f;
+ style->widget.shadowcolor = 0.0f;
+
+ style->columnspace = 8;
+ style->templatespace = 5;
+ style->boxspace = 5;
+ style->buttonspacex = 8;
+ style->buttonspacey = 2;
+ style->panelspace = 8;
+ style->panelouter = 4;
+
+ return style;
}
static uiFont *uifont_to_blfont(int id)
{
- uiFont *font = U.uifonts.first;
-
- for (; font; font = font->next) {
- if (font->uifont_id == id) {
- return font;
- }
- }
- return U.uifonts.first;
+ uiFont *font = U.uifonts.first;
+
+ for (; font; font = font->next) {
+ if (font->uifont_id == id) {
+ return font;
+ }
+ }
+ return U.uifonts.first;
}
/* *************** draw ************************ */
-
-void UI_fontstyle_draw_ex(
- const uiFontStyle *fs, const rcti *rect, const char *str, const uchar col[4],
- const struct uiFontStyleDraw_Params *fs_params,
- size_t len, float *r_xofs, float *r_yofs)
+void UI_fontstyle_draw_ex(const uiFontStyle *fs,
+ const rcti *rect,
+ const char *str,
+ const uchar col[4],
+ const struct uiFontStyleDraw_Params *fs_params,
+ size_t len,
+ float *r_xofs,
+ float *r_yofs)
{
- int xofs = 0, yofs;
- int font_flag = BLF_CLIPPING;
-
- UI_fontstyle_set(fs);
-
- /* set the flag */
- if (fs->shadow) {
- font_flag |= BLF_SHADOW;
- const float shadow_color[4] = {fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha};
- BLF_shadow(fs->uifont_id, fs->shadow, shadow_color);
- BLF_shadow_offset(fs->uifont_id, fs->shadx, fs->shady);
- }
- if (fs->kerning == 1) {
- font_flag |= BLF_KERNING_DEFAULT;
- }
- if (fs_params->word_wrap == 1) {
- font_flag |= BLF_WORD_WRAP;
- }
-
- BLF_enable(fs->uifont_id, font_flag);
-
- if (fs_params->word_wrap == 1) {
- /* draw from boundbox top */
- yofs = BLI_rcti_size_y(rect) - BLF_height_max(fs->uifont_id);
- }
- else {
- /* draw from boundbox center */
- float height = BLF_ascender(fs->uifont_id) + BLF_descender(fs->uifont_id);
- yofs = ceil(0.5f * (BLI_rcti_size_y(rect) - height));
- }
-
- if (fs_params->align == UI_STYLE_TEXT_CENTER) {
- xofs = floor(0.5f * (BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str, len)));
- }
- else if (fs_params->align == UI_STYLE_TEXT_RIGHT) {
- xofs = BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str, len);
- }
-
- yofs = MAX2(0, yofs);
- xofs = MAX2(0, xofs);
-
- BLF_clipping(fs->uifont_id, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
- 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_disable(fs->uifont_id, font_flag);
-
- *r_xofs = xofs;
- *r_yofs = yofs;
+ int xofs = 0, yofs;
+ int font_flag = BLF_CLIPPING;
+
+ UI_fontstyle_set(fs);
+
+ /* set the flag */
+ if (fs->shadow) {
+ font_flag |= BLF_SHADOW;
+ const float shadow_color[4] = {
+ fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha};
+ BLF_shadow(fs->uifont_id, fs->shadow, shadow_color);
+ BLF_shadow_offset(fs->uifont_id, fs->shadx, fs->shady);
+ }
+ if (fs->kerning == 1) {
+ font_flag |= BLF_KERNING_DEFAULT;
+ }
+ if (fs_params->word_wrap == 1) {
+ font_flag |= BLF_WORD_WRAP;
+ }
+
+ BLF_enable(fs->uifont_id, font_flag);
+
+ if (fs_params->word_wrap == 1) {
+ /* draw from boundbox top */
+ yofs = BLI_rcti_size_y(rect) - BLF_height_max(fs->uifont_id);
+ }
+ else {
+ /* draw from boundbox center */
+ float height = BLF_ascender(fs->uifont_id) + BLF_descender(fs->uifont_id);
+ yofs = ceil(0.5f * (BLI_rcti_size_y(rect) - height));
+ }
+
+ if (fs_params->align == UI_STYLE_TEXT_CENTER) {
+ xofs = floor(0.5f * (BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str, len)));
+ }
+ else if (fs_params->align == UI_STYLE_TEXT_RIGHT) {
+ xofs = BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str, len);
+ }
+
+ yofs = MAX2(0, yofs);
+ xofs = MAX2(0, xofs);
+
+ BLF_clipping(fs->uifont_id, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ 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_disable(fs->uifont_id, font_flag);
+
+ *r_xofs = xofs;
+ *r_yofs = yofs;
}
-void UI_fontstyle_draw(
- const uiFontStyle *fs, const rcti *rect, const char *str, const uchar col[4],
- const struct uiFontStyleDraw_Params *fs_params)
+void UI_fontstyle_draw(const uiFontStyle *fs,
+ const rcti *rect,
+ const char *str,
+ const uchar col[4],
+ const struct uiFontStyleDraw_Params *fs_params)
{
- float xofs, yofs;
+ float 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);
}
/* drawn same as above, but at 90 degree angle */
-void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const char *str, const uchar col[4])
+void UI_fontstyle_draw_rotated(const uiFontStyle *fs,
+ const rcti *rect,
+ const char *str,
+ const uchar col[4])
{
- float height;
- int xofs, yofs;
- float angle;
- rcti txtrect;
-
- UI_fontstyle_set(fs);
-
- height = BLF_ascender(fs->uifont_id) + BLF_descender(fs->uifont_id);
- /* becomes x-offset when rotated */
- xofs = ceil(0.5f * (BLI_rcti_size_y(rect) - height));
-
- /* ignore UI_STYLE, always aligned to top */
-
- /* rotate counter-clockwise for now (assumes left-to-right language)*/
- xofs += height;
- yofs = BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX) + 5;
- angle = M_PI_2;
-
- /* translate rect to vertical */
- txtrect.xmin = rect->xmin - BLI_rcti_size_y(rect);
- txtrect.ymin = rect->ymin - BLI_rcti_size_x(rect);
- txtrect.xmax = rect->xmin;
- txtrect.ymax = rect->ymin;
-
- /* clip is very strict, so we give it some space */
- /* clipping is done without rotation, so make rect big enough to contain both positions */
- BLF_clipping(fs->uifont_id, txtrect.xmin - 1, txtrect.ymin - yofs - xofs - 4, rect->xmax + 1, rect->ymax + 4);
- BLF_enable(fs->uifont_id, BLF_CLIPPING);
- BLF_position(fs->uifont_id, txtrect.xmin + xofs, txtrect.ymax - yofs, 0.0f);
-
- BLF_enable(fs->uifont_id, BLF_ROTATION);
- BLF_rotation(fs->uifont_id, angle);
- BLF_color4ubv(fs->uifont_id, col);
-
- if (fs->shadow) {
- BLF_enable(fs->uifont_id, BLF_SHADOW);
- const float shadow_color[4] = {fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha};
- BLF_shadow(fs->uifont_id, fs->shadow, shadow_color);
- BLF_shadow_offset(fs->uifont_id, fs->shadx, fs->shady);
- }
-
- if (fs->kerning == 1) {
- BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
- }
-
- BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
- BLF_disable(fs->uifont_id, BLF_ROTATION);
- BLF_disable(fs->uifont_id, BLF_CLIPPING);
- if (fs->shadow) {
- BLF_disable(fs->uifont_id, BLF_SHADOW);
- }
- if (fs->kerning == 1) {
- BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
- }
+ float height;
+ int xofs, yofs;
+ float angle;
+ rcti txtrect;
+
+ UI_fontstyle_set(fs);
+
+ height = BLF_ascender(fs->uifont_id) + BLF_descender(fs->uifont_id);
+ /* becomes x-offset when rotated */
+ xofs = ceil(0.5f * (BLI_rcti_size_y(rect) - height));
+
+ /* ignore UI_STYLE, always aligned to top */
+
+ /* rotate counter-clockwise for now (assumes left-to-right language)*/
+ xofs += height;
+ yofs = BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX) + 5;
+ angle = M_PI_2;
+
+ /* translate rect to vertical */
+ txtrect.xmin = rect->xmin - BLI_rcti_size_y(rect);
+ txtrect.ymin = rect->ymin - BLI_rcti_size_x(rect);
+ txtrect.xmax = rect->xmin;
+ txtrect.ymax = rect->ymin;
+
+ /* clip is very strict, so we give it some space */
+ /* clipping is done without rotation, so make rect big enough to contain both positions */
+ BLF_clipping(fs->uifont_id,
+ txtrect.xmin - 1,
+ txtrect.ymin - yofs - xofs - 4,
+ rect->xmax + 1,
+ rect->ymax + 4);
+ BLF_enable(fs->uifont_id, BLF_CLIPPING);
+ BLF_position(fs->uifont_id, txtrect.xmin + xofs, txtrect.ymax - yofs, 0.0f);
+
+ BLF_enable(fs->uifont_id, BLF_ROTATION);
+ BLF_rotation(fs->uifont_id, angle);
+ BLF_color4ubv(fs->uifont_id, col);
+
+ if (fs->shadow) {
+ BLF_enable(fs->uifont_id, BLF_SHADOW);
+ const float shadow_color[4] = {
+ fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha};
+ BLF_shadow(fs->uifont_id, fs->shadow, shadow_color);
+ BLF_shadow_offset(fs->uifont_id, fs->shadx, fs->shady);
+ }
+
+ if (fs->kerning == 1) {
+ BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
+ }
+
+ BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_disable(fs->uifont_id, BLF_ROTATION);
+ BLF_disable(fs->uifont_id, BLF_CLIPPING);
+ if (fs->shadow) {
+ BLF_disable(fs->uifont_id, BLF_SHADOW);
+ }
+ if (fs->kerning == 1) {
+ BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
+ }
}
/**
@@ -278,313 +288,311 @@ void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const ch
*
* For drawing on-screen labels.
*/
-void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const char *str, const uchar col[4])
+void UI_fontstyle_draw_simple(
+ const uiFontStyle *fs, float x, float y, const char *str, const uchar col[4])
{
- if (fs->kerning == 1) {
- BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
- }
-
- UI_fontstyle_set(fs);
- BLF_position(fs->uifont_id, x, y, 0.0f);
- BLF_color4ubv(fs->uifont_id, col);
- BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
-
- if (fs->kerning == 1) {
- BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
- }
+ if (fs->kerning == 1) {
+ BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
+ }
+
+ UI_fontstyle_set(fs);
+ BLF_position(fs->uifont_id, x, y, 0.0f);
+ BLF_color4ubv(fs->uifont_id, col);
+ BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+
+ if (fs->kerning == 1) {
+ BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
+ }
}
/**
* Same as #UI_fontstyle_draw but draw a colored backdrop.
*/
-void UI_fontstyle_draw_simple_backdrop(
- const uiFontStyle *fs, float x, float y, const char *str,
- const float col_fg[4], const float col_bg[4])
+void UI_fontstyle_draw_simple_backdrop(const uiFontStyle *fs,
+ float x,
+ float y,
+ const char *str,
+ const float col_fg[4],
+ const float col_bg[4])
{
- if (fs->kerning == 1) {
- BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
- }
-
- UI_fontstyle_set(fs);
-
- {
- const float width = BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
- const float height = BLF_height_max(fs->uifont_id);
- const float decent = BLF_descender(fs->uifont_id);
- const float margin = height / 4.0f;
-
- /* backdrop */
- float color[4] = { col_bg[0], col_bg[1], col_bg[2], 0.5f };
-
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_aa(
- true,
- x - margin,
- (y + decent) - margin,
- x + width + margin,
- (y + decent) + height + margin,
- margin, color);
- }
-
- BLF_position(fs->uifont_id, x, y, 0.0f);
- BLF_color4fv(fs->uifont_id, col_fg);
- BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
-
- if (fs->kerning == 1) {
- BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
- }
+ if (fs->kerning == 1) {
+ BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
+ }
+
+ UI_fontstyle_set(fs);
+
+ {
+ const float width = BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+ const float height = BLF_height_max(fs->uifont_id);
+ const float decent = BLF_descender(fs->uifont_id);
+ const float margin = height / 4.0f;
+
+ /* backdrop */
+ float color[4] = {col_bg[0], col_bg[1], col_bg[2], 0.5f};
+
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_aa(true,
+ x - margin,
+ (y + decent) - margin,
+ x + width + margin,
+ (y + decent) + height + margin,
+ margin,
+ color);
+ }
+
+ BLF_position(fs->uifont_id, x, y, 0.0f);
+ BLF_color4fv(fs->uifont_id, col_fg);
+ BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+
+ if (fs->kerning == 1) {
+ BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
+ }
}
-
/* ************** helpers ************************ */
/* XXX: read a style configure */
uiStyle *UI_style_get(void)
{
#if 0
- uiStyle *style = NULL;
- /* offset is two struct uiStyle pointers */
- style = BLI_findstring(&U.uistyles, "Unifont Style", sizeof(style) * 2);
- return (style != NULL) ? style : U.uistyles.first;
+ uiStyle *style = NULL;
+ /* offset is two struct uiStyle pointers */
+ style = BLI_findstring(&U.uistyles, "Unifont Style", sizeof(style) * 2);
+ return (style != NULL) ? style : U.uistyles.first;
#else
- return U.uistyles.first;
+ return U.uistyles.first;
#endif
}
/* for drawing, scaled with DPI setting */
uiStyle *UI_style_get_dpi(void)
{
- uiStyle *style = UI_style_get();
- static uiStyle _style;
-
- _style = *style;
-
- _style.paneltitle.shadx = (short)(UI_DPI_FAC * _style.paneltitle.shadx);
- _style.paneltitle.shady = (short)(UI_DPI_FAC * _style.paneltitle.shady);
- _style.grouplabel.shadx = (short)(UI_DPI_FAC * _style.grouplabel.shadx);
- _style.grouplabel.shady = (short)(UI_DPI_FAC * _style.grouplabel.shady);
- _style.widgetlabel.shadx = (short)(UI_DPI_FAC * _style.widgetlabel.shadx);
- _style.widgetlabel.shady = (short)(UI_DPI_FAC * _style.widgetlabel.shady);
-
- _style.columnspace = (short)(UI_DPI_FAC * _style.columnspace);
- _style.templatespace = (short)(UI_DPI_FAC * _style.templatespace);
- _style.boxspace = (short)(UI_DPI_FAC * _style.boxspace);
- _style.buttonspacex = (short)(UI_DPI_FAC * _style.buttonspacex);
- _style.buttonspacey = (short)(UI_DPI_FAC * _style.buttonspacey);
- _style.panelspace = (short)(UI_DPI_FAC * _style.panelspace);
- _style.panelouter = (short)(UI_DPI_FAC * _style.panelouter);
-
- return &_style;
+ uiStyle *style = UI_style_get();
+ static uiStyle _style;
+
+ _style = *style;
+
+ _style.paneltitle.shadx = (short)(UI_DPI_FAC * _style.paneltitle.shadx);
+ _style.paneltitle.shady = (short)(UI_DPI_FAC * _style.paneltitle.shady);
+ _style.grouplabel.shadx = (short)(UI_DPI_FAC * _style.grouplabel.shadx);
+ _style.grouplabel.shady = (short)(UI_DPI_FAC * _style.grouplabel.shady);
+ _style.widgetlabel.shadx = (short)(UI_DPI_FAC * _style.widgetlabel.shadx);
+ _style.widgetlabel.shady = (short)(UI_DPI_FAC * _style.widgetlabel.shady);
+
+ _style.columnspace = (short)(UI_DPI_FAC * _style.columnspace);
+ _style.templatespace = (short)(UI_DPI_FAC * _style.templatespace);
+ _style.boxspace = (short)(UI_DPI_FAC * _style.boxspace);
+ _style.buttonspacex = (short)(UI_DPI_FAC * _style.buttonspacex);
+ _style.buttonspacey = (short)(UI_DPI_FAC * _style.buttonspacey);
+ _style.panelspace = (short)(UI_DPI_FAC * _style.panelspace);
+ _style.panelouter = (short)(UI_DPI_FAC * _style.panelouter);
+
+ return &_style;
}
int UI_fontstyle_string_width(const uiFontStyle *fs, const char *str)
{
- int width;
+ int width;
- if (fs->kerning == 1) {
- /* for BLF_width */
- BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
- }
+ if (fs->kerning == 1) {
+ /* for BLF_width */
+ BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
+ }
- UI_fontstyle_set(fs);
- width = BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+ UI_fontstyle_set(fs);
+ width = BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
- if (fs->kerning == 1) {
- BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
- }
+ if (fs->kerning == 1) {
+ BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
+ }
- return width;
+ return width;
}
int UI_fontstyle_height_max(const uiFontStyle *fs)
{
- UI_fontstyle_set(fs);
- return BLF_height_max(fs->uifont_id);
+ UI_fontstyle_set(fs);
+ return BLF_height_max(fs->uifont_id);
}
-
/* ************** init exit ************************ */
/* called on each startup.blend read */
/* reading without uifont will create one */
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) {
- U.dpi = 72;
- }
- CLAMP(U.dpi, 48, 144);
-
- for (font = U.uifonts.first; font; font = font->next) {
- BLF_unload_id(font->blf_id);
- }
-
- if (blf_mono_font != -1) {
- BLF_unload_id(blf_mono_font);
- blf_mono_font = -1;
- }
-
- if (blf_mono_font_render != -1) {
- BLF_unload_id(blf_mono_font_render);
- blf_mono_font_render = -1;
- }
-
- font = U.uifonts.first;
-
- /* default builtin */
- if (font == NULL) {
- font = MEM_callocN(sizeof(uiFont), "ui font");
- BLI_addtail(&U.uifonts, font);
- }
-
- if (U.font_path_ui[0]) {
- BLI_strncpy(font->filename, U.font_path_ui, sizeof(font->filename));
- font->uifont_id = UIFONT_CUSTOM1;
- }
- else {
- BLI_strncpy(font->filename, "default", sizeof(font->filename));
- font->uifont_id = UIFONT_DEFAULT;
- }
-
- for (font = U.uifonts.first; font; font = font->next) {
-
- if (font->uifont_id == UIFONT_DEFAULT) {
+ 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) {
+ U.dpi = 72;
+ }
+ CLAMP(U.dpi, 48, 144);
+
+ for (font = U.uifonts.first; font; font = font->next) {
+ BLF_unload_id(font->blf_id);
+ }
+
+ if (blf_mono_font != -1) {
+ BLF_unload_id(blf_mono_font);
+ blf_mono_font = -1;
+ }
+
+ if (blf_mono_font_render != -1) {
+ BLF_unload_id(blf_mono_font_render);
+ blf_mono_font_render = -1;
+ }
+
+ font = U.uifonts.first;
+
+ /* default builtin */
+ if (font == NULL) {
+ font = MEM_callocN(sizeof(uiFont), "ui font");
+ BLI_addtail(&U.uifonts, font);
+ }
+
+ if (U.font_path_ui[0]) {
+ BLI_strncpy(font->filename, U.font_path_ui, sizeof(font->filename));
+ font->uifont_id = UIFONT_CUSTOM1;
+ }
+ else {
+ BLI_strncpy(font->filename, "default", sizeof(font->filename));
+ font->uifont_id = UIFONT_DEFAULT;
+ }
+
+ for (font = U.uifonts.first; font; font = font->next) {
+
+ 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);
+ 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);
+ font->blf_id = BLF_load_mem("default", (uchar *)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
#endif
- }
- 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);
- }
- }
-
- BLF_default_set(font->blf_id);
-
- if (font->blf_id == -1) {
- if (G.debug & G_DEBUG) {
- printf("%s: error, no fonts available\n", __func__);
- }
- }
- else {
- /* ? just for speed to initialize?
- * Yes, this build the glyph cache and create
- * the texture.
- */
- BLF_size(font->blf_id, 11 * U.pixelsize, U.dpi);
- BLF_size(font->blf_id, 12 * U.pixelsize, U.dpi);
- BLF_size(font->blf_id, 14 * U.pixelsize, U.dpi);
- }
- }
-
- if (style == NULL) {
- ui_style_new(&U.uistyles, "Default Style", UIFONT_DEFAULT);
- }
+ }
+ 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);
+ }
+ }
+
+ BLF_default_set(font->blf_id);
+
+ if (font->blf_id == -1) {
+ if (G.debug & G_DEBUG) {
+ printf("%s: error, no fonts available\n", __func__);
+ }
+ }
+ else {
+ /* ? just for speed to initialize?
+ * Yes, this build the glyph cache and create
+ * the texture.
+ */
+ BLF_size(font->blf_id, 11 * U.pixelsize, U.dpi);
+ BLF_size(font->blf_id, 12 * U.pixelsize, U.dpi);
+ BLF_size(font->blf_id, 14 * U.pixelsize, U.dpi);
+ }
+ }
+
+ if (style == NULL) {
+ 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;
- }
- }
+ /* 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);
- 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);
- }
-
- BLF_size(blf_mono_font, 12 * U.pixelsize, 72);
-
- /* Set default flags based on UI preferences (not render fonts) */
- {
- int flag_disable = (
- BLF_MONOCHROME |
- BLF_HINTING_NONE |
- BLF_HINTING_SLIGHT |
- BLF_HINTING_FULL);
- int flag_enable = 0;
-
- if (U.text_render & USER_TEXT_HINTING_NONE) {
- flag_enable |= BLF_HINTING_NONE;
- }
- else if (U.text_render & USER_TEXT_HINTING_SLIGHT) {
- flag_enable |= BLF_HINTING_SLIGHT;
- }
- else if (U.text_render & USER_TEXT_HINTING_FULL) {
- flag_enable |= BLF_HINTING_FULL;
- }
-
- if (U.text_render & USER_TEXT_DISABLE_AA) {
- flag_enable |= BLF_MONOCHROME;
- }
-
- for (font = U.uifonts.first; font; font = font->next) {
- if (font->blf_id != -1) {
- BLF_disable(font->blf_id, flag_disable);
- BLF_enable(font->blf_id, flag_enable);
- }
- }
- if (blf_mono_font != -1) {
- BLF_disable(blf_mono_font, flag_disable);
- BLF_enable(blf_mono_font, flag_enable);
- }
- }
-
- /**
- * Second for rendering else we get threading problems,
- *
- * \note This isn't good that the render font depends on the preferences,
- * 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);
- }
-
- BLF_size(blf_mono_font_render, 12 * U.pixelsize, 72);
+ /* XXX, this should be moved into a style,
+ * but for now best only load the monospaced font once. */
+ BLI_assert(blf_mono_font == -1);
+ 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);
+ }
+
+ BLF_size(blf_mono_font, 12 * U.pixelsize, 72);
+
+ /* Set default flags based on UI preferences (not render fonts) */
+ {
+ int flag_disable = (BLF_MONOCHROME | BLF_HINTING_NONE | BLF_HINTING_SLIGHT | BLF_HINTING_FULL);
+ int flag_enable = 0;
+
+ if (U.text_render & USER_TEXT_HINTING_NONE) {
+ flag_enable |= BLF_HINTING_NONE;
+ }
+ else if (U.text_render & USER_TEXT_HINTING_SLIGHT) {
+ flag_enable |= BLF_HINTING_SLIGHT;
+ }
+ else if (U.text_render & USER_TEXT_HINTING_FULL) {
+ flag_enable |= BLF_HINTING_FULL;
+ }
+
+ if (U.text_render & USER_TEXT_DISABLE_AA) {
+ flag_enable |= BLF_MONOCHROME;
+ }
+
+ for (font = U.uifonts.first; font; font = font->next) {
+ if (font->blf_id != -1) {
+ BLF_disable(font->blf_id, flag_disable);
+ BLF_enable(font->blf_id, flag_enable);
+ }
+ }
+ if (blf_mono_font != -1) {
+ BLF_disable(blf_mono_font, flag_disable);
+ BLF_enable(blf_mono_font, flag_enable);
+ }
+ }
+
+ /**
+ * Second for rendering else we get threading problems,
+ *
+ * \note This isn't good that the render font depends on the preferences,
+ * 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);
+ }
+
+ BLF_size(blf_mono_font_render, 12 * U.pixelsize, 72);
}
void UI_fontstyle_set(const uiFontStyle *fs)
{
- uiFont *font = uifont_to_blfont(fs->uifont_id);
+ uiFont *font = uifont_to_blfont(fs->uifont_id);
- BLF_size(font->blf_id, fs->points * U.pixelsize, U.dpi);
+ BLF_size(font->blf_id, fs->points * U.pixelsize, U.dpi);
}
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 897a07708d0..6666991ad26 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -18,7 +18,6 @@
* \ingroup edinterface
*/
-
#include <ctype.h>
#include <stdlib.h>
#include <stddef.h>
@@ -95,13 +94,11 @@
#include "PIL_time.h"
-
// #define USE_OP_RESET_BUT // we may want to make this optional, disable for now.
/* defines for templateID/TemplateSearch */
-#define TEMPLATE_SEARCH_TEXTBUT_WIDTH (UI_UNIT_X * 6)
-#define TEMPLATE_SEARCH_TEXTBUT_HEIGHT UI_UNIT_Y
-
+#define TEMPLATE_SEARCH_TEXTBUT_WIDTH (UI_UNIT_X * 6)
+#define TEMPLATE_SEARCH_TEXTBUT_HEIGHT UI_UNIT_Y
void UI_template_fix_linking(void)
{
@@ -110,463 +107,543 @@ void UI_template_fix_linking(void)
/**
* Add a block button for the search menu for templateID and templateSearch.
*/
-static void template_add_button_search_menu(
- const bContext *C, uiLayout *layout, uiBlock *block,
- PointerRNA *ptr, PropertyRNA *prop,
- uiBlockCreateFunc block_func, void *block_argN, const char * const tip,
- const bool use_previews, const bool editable, const bool live_icon)
+static void template_add_button_search_menu(const bContext *C,
+ uiLayout *layout,
+ uiBlock *block,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ uiBlockCreateFunc block_func,
+ void *block_argN,
+ const char *const tip,
+ const bool use_previews,
+ const bool editable,
+ const bool live_icon)
{
- PointerRNA active_ptr = RNA_property_pointer_get(ptr, prop);
- ID *id = (active_ptr.data && RNA_struct_is_ID(active_ptr.type)) ? active_ptr.data : NULL;
- const ID *idfrom = ptr->id.data;
- const StructRNA *type = active_ptr.type ? active_ptr.type : RNA_property_pointer_type(ptr, prop);
- uiBut *but;
-
- if (use_previews) {
- ARegion *region = CTX_wm_region(C);
- ScrArea *area = CTX_wm_area(C);
- /* XXX ugly top-bar exception */
- const bool use_big_size = (
- /* silly check, could be more generic */
- (region->regiontype != RGN_TYPE_HEADER) &&
- (area->spacetype != SPACE_TOPBAR));
- /* Ugly exception for screens here,
- * drawing their preview in icon size looks ugly/useless */
- const bool use_preview_icon = use_big_size || (id && (GS(id->name) != ID_SCR));
- const short width = UI_UNIT_X * (use_big_size ? 6 : 1.6f);
- const short height = UI_UNIT_Y * (use_big_size ? 6 : 1);
-
- but = uiDefBlockButN(block, block_func, block_argN, "", 0, 0, width, height, tip);
- if (use_preview_icon) {
- int icon = id ? ui_id_icon_get(C, id, use_big_size) : RNA_struct_ui_icon(type);
- ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
- }
- else {
- ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON);
- UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT);
- }
-
- if ((idfrom && idfrom->lib) || !editable) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- if (use_big_size) {
- uiLayoutRow(layout, true);
- }
- }
- else {
- but = uiDefBlockButN(block, block_func, block_argN, "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y, tip);
-
- if (live_icon) {
- int icon = id ? ui_id_icon_get(C, id, false) : RNA_struct_ui_icon(type);
- ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
- }
- else {
- ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON);
- }
- if (id) {
- /* default dragging of icon for id browse buttons */
- UI_but_drag_set_id(but, id);
- }
- UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT);
-
- if ((idfrom && idfrom->lib) || !editable) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- }
+ PointerRNA active_ptr = RNA_property_pointer_get(ptr, prop);
+ ID *id = (active_ptr.data && RNA_struct_is_ID(active_ptr.type)) ? active_ptr.data : NULL;
+ const ID *idfrom = ptr->id.data;
+ const StructRNA *type = active_ptr.type ? active_ptr.type : RNA_property_pointer_type(ptr, prop);
+ uiBut *but;
+
+ if (use_previews) {
+ ARegion *region = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ /* XXX ugly top-bar exception */
+ const bool use_big_size = (
+ /* silly check, could be more generic */
+ (region->regiontype != RGN_TYPE_HEADER) && (area->spacetype != SPACE_TOPBAR));
+ /* Ugly exception for screens here,
+ * drawing their preview in icon size looks ugly/useless */
+ const bool use_preview_icon = use_big_size || (id && (GS(id->name) != ID_SCR));
+ const short width = UI_UNIT_X * (use_big_size ? 6 : 1.6f);
+ const short height = UI_UNIT_Y * (use_big_size ? 6 : 1);
+
+ but = uiDefBlockButN(block, block_func, block_argN, "", 0, 0, width, height, tip);
+ if (use_preview_icon) {
+ int icon = id ? ui_id_icon_get(C, id, use_big_size) : RNA_struct_ui_icon(type);
+ ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
+ }
+ else {
+ ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON);
+ UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT);
+ }
+
+ if ((idfrom && idfrom->lib) || !editable) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ if (use_big_size) {
+ uiLayoutRow(layout, true);
+ }
+ }
+ else {
+ but = uiDefBlockButN(block, block_func, block_argN, "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y, tip);
+
+ if (live_icon) {
+ int icon = id ? ui_id_icon_get(C, id, false) : RNA_struct_ui_icon(type);
+ ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
+ }
+ else {
+ ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON);
+ }
+ if (id) {
+ /* default dragging of icon for id browse buttons */
+ UI_but_drag_set_id(but, id);
+ }
+ UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT);
+
+ if ((idfrom && idfrom->lib) || !editable) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ }
}
-static uiBlock *template_common_search_menu(
- const bContext *C, ARegion *region,
- uiButSearchFunc search_func, void *search_arg,
- uiButHandleFunc handle_func, void *active_item,
- const int preview_rows, const int preview_cols,
- float scale)
+static uiBlock *template_common_search_menu(const bContext *C,
+ ARegion *region,
+ uiButSearchFunc search_func,
+ void *search_arg,
+ uiButHandleFunc handle_func,
+ void *active_item,
+ const int preview_rows,
+ const int preview_cols,
+ float scale)
{
- static char search[256];
- wmWindow *win = CTX_wm_window(C);
- uiBlock *block;
- uiBut *but;
-
- /* clear initial search string, then all items show */
- search[0] = 0;
-
- block = UI_block_begin(C, region, "_popup", UI_EMBOSS);
- UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU);
- UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
-
- /* preview thumbnails */
- if (preview_rows > 0 && preview_cols > 0) {
- const int w = 4 * U.widget_unit * preview_cols * scale;
- const int h = 5 * U.widget_unit * preview_rows * scale;
-
- /* fake button, it holds space for search items */
- uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 26, w, h, NULL, 0, 0, 0, 0, NULL);
-
- but = uiDefSearchBut(
- block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, UI_UNIT_Y,
- preview_rows, preview_cols, "");
- }
- /* list view */
- else {
- const int searchbox_width = UI_searchbox_size_x();
- const int searchbox_height = UI_searchbox_size_y();
-
- /* fake button, it holds space for search items */
- uiDefBut(
- block, UI_BTYPE_LABEL, 0, "", 10, 15, searchbox_width, searchbox_height,
- NULL, 0, 0, 0, 0, NULL);
- but = uiDefSearchBut(
- block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0,
- searchbox_width, UI_UNIT_Y - 1, 0, 0, "");
- }
- UI_but_func_search_set(
- but, ui_searchbox_create_generic, search_func,
- search_arg, false, handle_func, active_item);
-
-
- UI_block_bounds_set_normal(block, 0.3f * U.widget_unit);
- UI_block_direction_set(block, UI_DIR_DOWN);
-
- /* give search-field focus */
- UI_but_focus_on_enter_event(win, but);
- /* this type of search menu requires undo */
- but->flag |= UI_BUT_UNDO;
-
- return block;
+ static char search[256];
+ wmWindow *win = CTX_wm_window(C);
+ uiBlock *block;
+ uiBut *but;
+
+ /* clear initial search string, then all items show */
+ search[0] = 0;
+
+ block = UI_block_begin(C, region, "_popup", UI_EMBOSS);
+ UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU);
+ UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
+
+ /* preview thumbnails */
+ if (preview_rows > 0 && preview_cols > 0) {
+ const int w = 4 * U.widget_unit * preview_cols * scale;
+ const int h = 5 * U.widget_unit * preview_rows * scale;
+
+ /* fake button, it holds space for search items */
+ uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 26, w, h, NULL, 0, 0, 0, 0, NULL);
+
+ but = uiDefSearchBut(block,
+ search,
+ 0,
+ ICON_VIEWZOOM,
+ sizeof(search),
+ 10,
+ 0,
+ w,
+ UI_UNIT_Y,
+ preview_rows,
+ preview_cols,
+ "");
+ }
+ /* list view */
+ else {
+ const int searchbox_width = UI_searchbox_size_x();
+ const int searchbox_height = UI_searchbox_size_y();
+
+ /* fake button, it holds space for search items */
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ "",
+ 10,
+ 15,
+ searchbox_width,
+ searchbox_height,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL);
+ but = uiDefSearchBut(block,
+ search,
+ 0,
+ ICON_VIEWZOOM,
+ sizeof(search),
+ 10,
+ 0,
+ searchbox_width,
+ UI_UNIT_Y - 1,
+ 0,
+ 0,
+ "");
+ }
+ UI_but_func_search_set(
+ but, ui_searchbox_create_generic, search_func, search_arg, false, handle_func, active_item);
+
+ UI_block_bounds_set_normal(block, 0.3f * U.widget_unit);
+ UI_block_direction_set(block, UI_DIR_DOWN);
+
+ /* give search-field focus */
+ UI_but_focus_on_enter_event(win, but);
+ /* this type of search menu requires undo */
+ but->flag |= UI_BUT_UNDO;
+
+ return block;
}
/********************** Header Template *************************/
void uiTemplateHeader(uiLayout *layout, bContext *C)
{
- uiBlock *block;
+ uiBlock *block;
- block = uiLayoutAbsoluteBlock(layout);
- ED_area_header_switchbutton(C, block, 0);
+ block = uiLayoutAbsoluteBlock(layout);
+ ED_area_header_switchbutton(C, block, 0);
}
/********************** Search Callbacks *************************/
typedef struct TemplateID {
- PointerRNA ptr;
- PropertyRNA *prop;
-
- ListBase *idlb;
- short idcode;
- short filter;
- int prv_rows, prv_cols;
- bool preview;
- float scale;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ ListBase *idlb;
+ short idcode;
+ short filter;
+ int prv_rows, prv_cols;
+ bool preview;
+ float scale;
} TemplateID;
/* Search browse menu, assign */
static void template_ID_set_property_cb(bContext *C, void *arg_template, void *item)
{
- TemplateID *template_ui = (TemplateID *)arg_template;
+ TemplateID *template_ui = (TemplateID *)arg_template;
- /* ID */
- if (item) {
- PointerRNA idptr;
+ /* ID */
+ if (item) {
+ PointerRNA idptr;
- RNA_id_pointer_create(item, &idptr);
- RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr);
- RNA_property_update(C, &template_ui->ptr, template_ui->prop);
- }
+ RNA_id_pointer_create(item, &idptr);
+ RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr);
+ RNA_property_update(C, &template_ui->ptr, template_ui->prop);
+ }
}
-static bool id_search_add(
- const bContext *C, TemplateID *template_ui,
- const int flag, const char *str, uiSearchItems *items,
- ID *id)
+static bool id_search_add(const bContext *C,
+ TemplateID *template_ui,
+ const int flag,
+ const char *str,
+ uiSearchItems *items,
+ ID *id)
{
- ID *id_from = template_ui->ptr.id.data;
-
- if (!((flag & PROP_ID_SELF_CHECK) && id == id_from)) {
-
- /* use filter */
- if (RNA_property_type(template_ui->prop) == PROP_POINTER) {
- PointerRNA ptr;
- RNA_id_pointer_create(id, &ptr);
- if (RNA_property_pointer_poll(&template_ui->ptr, template_ui->prop, &ptr) == 0) {
- return true;
- }
- }
-
- /* hide dot-datablocks, but only if filter does not force it visible */
- if (U.uiflag & USER_HIDE_DOT) {
- if ((id->name[2] == '.') && (str[0] != '.')) {
- return true;
- }
- }
-
- if (*str == '\0' || BLI_strcasestr(id->name + 2, str)) {
- /* +1 is needed because BKE_id_ui_prefix used 3 letter prefix
- * followed by ID_NAME-2 characters from id->name
- */
- char name_ui[MAX_ID_FULL_NAME_UI];
- BKE_id_full_name_ui_prefix_get(name_ui, id);
-
- int iconid = ui_id_icon_get(C, id, template_ui->preview);
-
- if (false == UI_search_item_add(items, name_ui, id, iconid)) {
- return false;
- }
- }
- }
- return true;
+ ID *id_from = template_ui->ptr.id.data;
+
+ if (!((flag & PROP_ID_SELF_CHECK) && id == id_from)) {
+
+ /* use filter */
+ if (RNA_property_type(template_ui->prop) == PROP_POINTER) {
+ PointerRNA ptr;
+ RNA_id_pointer_create(id, &ptr);
+ if (RNA_property_pointer_poll(&template_ui->ptr, template_ui->prop, &ptr) == 0) {
+ return true;
+ }
+ }
+
+ /* hide dot-datablocks, but only if filter does not force it visible */
+ if (U.uiflag & USER_HIDE_DOT) {
+ if ((id->name[2] == '.') && (str[0] != '.')) {
+ return true;
+ }
+ }
+
+ if (*str == '\0' || BLI_strcasestr(id->name + 2, str)) {
+ /* +1 is needed because BKE_id_ui_prefix used 3 letter prefix
+ * followed by ID_NAME-2 characters from id->name
+ */
+ char name_ui[MAX_ID_FULL_NAME_UI];
+ BKE_id_full_name_ui_prefix_get(name_ui, id);
+
+ int iconid = ui_id_icon_get(C, id, template_ui->preview);
+
+ if (false == UI_search_item_add(items, name_ui, id, iconid)) {
+ return false;
+ }
+ }
+ }
+ return true;
}
/* ID Search browse menu, do the search */
-static void id_search_cb(const bContext *C, void *arg_template, const char *str, uiSearchItems *items)
+static void id_search_cb(const bContext *C,
+ void *arg_template,
+ const char *str,
+ uiSearchItems *items)
{
- TemplateID *template_ui = (TemplateID *)arg_template;
- ListBase *lb = template_ui->idlb;
- ID *id;
- int flag = RNA_property_flag(template_ui->prop);
-
- /* ID listbase */
- for (id = lb->first; id; id = id->next) {
- if (!id_search_add(C, template_ui, flag, str, items, id)) {
- break;
- }
- }
+ TemplateID *template_ui = (TemplateID *)arg_template;
+ ListBase *lb = template_ui->idlb;
+ ID *id;
+ int flag = RNA_property_flag(template_ui->prop);
+
+ /* ID listbase */
+ for (id = lb->first; id; id = id->next) {
+ if (!id_search_add(C, template_ui, flag, str, items, id)) {
+ break;
+ }
+ }
}
/**
* Use id tags for filtering.
*/
-static void id_search_cb_tagged(const bContext *C, void *arg_template, const char *str, uiSearchItems *items)
+static void id_search_cb_tagged(const bContext *C,
+ void *arg_template,
+ const char *str,
+ uiSearchItems *items)
{
- TemplateID *template_ui = (TemplateID *)arg_template;
- ListBase *lb = template_ui->idlb;
- ID *id;
- int flag = RNA_property_flag(template_ui->prop);
-
- /* ID listbase */
- for (id = lb->first; id; id = id->next) {
- if (id->tag & LIB_TAG_DOIT) {
- if (!id_search_add(C, template_ui, flag, str, items, id)) {
- break;
- }
- id->tag &= ~LIB_TAG_DOIT;
- }
- }
+ TemplateID *template_ui = (TemplateID *)arg_template;
+ ListBase *lb = template_ui->idlb;
+ ID *id;
+ int flag = RNA_property_flag(template_ui->prop);
+
+ /* ID listbase */
+ for (id = lb->first; id; id = id->next) {
+ if (id->tag & LIB_TAG_DOIT) {
+ if (!id_search_add(C, template_ui, flag, str, items, id)) {
+ break;
+ }
+ id->tag &= ~LIB_TAG_DOIT;
+ }
+ }
}
/**
* A version of 'id_search_cb' that lists scene objects.
*/
-static void id_search_cb_objects_from_scene(const bContext *C, void *arg_template, const char *str, uiSearchItems *items)
+static void id_search_cb_objects_from_scene(const bContext *C,
+ void *arg_template,
+ const char *str,
+ uiSearchItems *items)
{
- TemplateID *template_ui = (TemplateID *)arg_template;
- ListBase *lb = template_ui->idlb;
- Scene *scene = NULL;
- ID *id_from = template_ui->ptr.id.data;
-
- if (id_from && GS(id_from->name) == ID_SCE) {
- scene = (Scene *)id_from;
- }
- else {
- scene = CTX_data_scene(C);
- }
-
- BKE_main_id_flag_listbase(lb, LIB_TAG_DOIT, false);
-
- FOREACH_SCENE_OBJECT_BEGIN(scene, ob_iter)
- {
- ob_iter->id.tag |= LIB_TAG_DOIT;
- }
- FOREACH_SCENE_OBJECT_END;
- id_search_cb_tagged(C, arg_template, str, items);
+ TemplateID *template_ui = (TemplateID *)arg_template;
+ ListBase *lb = template_ui->idlb;
+ Scene *scene = NULL;
+ ID *id_from = template_ui->ptr.id.data;
+
+ if (id_from && GS(id_from->name) == ID_SCE) {
+ scene = (Scene *)id_from;
+ }
+ else {
+ scene = CTX_data_scene(C);
+ }
+
+ BKE_main_id_flag_listbase(lb, LIB_TAG_DOIT, false);
+
+ FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) {
+ ob_iter->id.tag |= LIB_TAG_DOIT;
+ }
+ FOREACH_SCENE_OBJECT_END;
+ id_search_cb_tagged(C, arg_template, str, items);
}
/* ID Search browse menu, open */
static uiBlock *id_search_menu(bContext *C, ARegion *ar, 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;
-
- /* arg_litem is malloced, can be freed by parent button */
- template_ui = *((TemplateID *)arg_litem);
- active_item_ptr = RNA_property_pointer_get(&template_ui.ptr, template_ui.prop);
-
- if (template_ui.filter) {
- /* 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;
- }
- }
- }
-
- return template_common_search_menu(
- C, ar, id_search_cb_p, &template_ui, template_ID_set_property_cb, active_item_ptr.data,
- template_ui.prv_rows, template_ui.prv_cols, template_ui.scale);
+ static TemplateID template_ui;
+ PointerRNA active_item_ptr;
+ void (*id_search_cb_p)(const bContext *, void *, const char *, uiSearchItems *) = id_search_cb;
+
+ /* arg_litem is malloced, can be freed by parent button */
+ template_ui = *((TemplateID *)arg_litem);
+ active_item_ptr = RNA_property_pointer_get(&template_ui.ptr, template_ui.prop);
+
+ if (template_ui.filter) {
+ /* 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;
+ }
+ }
+ }
+
+ return template_common_search_menu(C,
+ ar,
+ id_search_cb_p,
+ &template_ui,
+ template_ID_set_property_cb,
+ active_item_ptr.data,
+ template_ui.prv_rows,
+ template_ui.prv_cols,
+ template_ui.scale);
}
/************************ ID Template ***************************/
/* This is for browsing and editing the ID-blocks used */
/* for new/open operators */
-void UI_context_active_but_prop_get_templateID(
- bContext *C,
- PointerRNA *r_ptr, PropertyRNA **r_prop)
+void UI_context_active_but_prop_get_templateID(bContext *C,
+ PointerRNA *r_ptr,
+ PropertyRNA **r_prop)
{
- TemplateID *template_ui;
- uiBut *but = UI_context_active_but_get(C);
+ TemplateID *template_ui;
+ uiBut *but = UI_context_active_but_get(C);
- memset(r_ptr, 0, sizeof(*r_ptr));
- *r_prop = NULL;
+ memset(r_ptr, 0, sizeof(*r_ptr));
+ *r_prop = NULL;
- if (but && but->func_argN) {
- template_ui = but->func_argN;
- *r_ptr = template_ui->ptr;
- *r_prop = template_ui->prop;
- }
+ if (but && but->func_argN) {
+ template_ui = but->func_argN;
+ *r_ptr = template_ui->ptr;
+ *r_prop = template_ui->prop;
+ }
}
static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
{
- TemplateID *template_ui = (TemplateID *)arg_litem;
- PointerRNA idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
- ID *id = idptr.data;
- int event = POINTER_AS_INT(arg_event);
-
- switch (event) {
- case UI_ID_BROWSE:
- case UI_ID_PIN:
- RNA_warning("warning, id event %d shouldnt come here", event);
- break;
- case UI_ID_OPEN:
- case UI_ID_ADD_NEW:
- /* these call UI_context_active_but_prop_get_templateID */
- break;
- case UI_ID_DELETE:
- memset(&idptr, 0, sizeof(idptr));
- RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr);
- RNA_property_update(C, &template_ui->ptr, template_ui->prop);
-
- if (id && CTX_wm_window(C)->eventstate->shift) {
- /* only way to force-remove data (on save) */
- id_fake_user_clear(id);
- id->us = 0;
- }
-
- break;
- case UI_ID_FAKE_USER:
- if (id) {
- if (id->flag & LIB_FAKEUSER) {
- id_us_plus(id);
- }
- else {
- id_us_min(id);
- }
- }
- else {
- return;
- }
- break;
- case UI_ID_LOCAL:
- if (id) {
- Main *bmain = CTX_data_main(C);
- if (BKE_override_static_is_enabled() && CTX_wm_window(C)->eventstate->shift) {
- ID *override_id = BKE_override_static_create_from_id(bmain, id);
- if (override_id != NULL) {
- BKE_main_id_clear_newpoins(bmain);
-
- /* Assign new pointer, takes care of updates/notifiers */
- RNA_id_pointer_create(override_id, &idptr);
- }
- }
- else {
- if (id_make_local(bmain, id, false, false)) {
- BKE_main_id_clear_newpoins(bmain);
-
- /* reassign to get get proper updates/notifiers */
- idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
- }
- }
- RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr);
- RNA_property_update(C, &template_ui->ptr, template_ui->prop);
- }
- break;
- case UI_ID_OVERRIDE:
- if (id && id->override_static) {
- BKE_override_static_free(&id->override_static);
- /* reassign to get get proper updates/notifiers */
- idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
- RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr);
- RNA_property_update(C, &template_ui->ptr, template_ui->prop);
- }
- break;
- case UI_ID_ALONE:
- if (id) {
- const bool do_scene_obj = (
- (GS(id->name) == ID_OB) &&
- (template_ui->ptr.type == &RNA_LayerObjects));
-
- /* make copy */
- if (do_scene_obj) {
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ED_object_single_user(bmain, scene, (struct Object *)id);
- WM_event_add_notifier(C, NC_WINDOW, NULL);
- 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);
- }
- }
- }
- break;
+ TemplateID *template_ui = (TemplateID *)arg_litem;
+ PointerRNA idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
+ ID *id = idptr.data;
+ int event = POINTER_AS_INT(arg_event);
+
+ switch (event) {
+ case UI_ID_BROWSE:
+ case UI_ID_PIN:
+ RNA_warning("warning, id event %d shouldnt come here", event);
+ break;
+ case UI_ID_OPEN:
+ case UI_ID_ADD_NEW:
+ /* these call UI_context_active_but_prop_get_templateID */
+ break;
+ case UI_ID_DELETE:
+ memset(&idptr, 0, sizeof(idptr));
+ RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr);
+ RNA_property_update(C, &template_ui->ptr, template_ui->prop);
+
+ if (id && CTX_wm_window(C)->eventstate->shift) {
+ /* only way to force-remove data (on save) */
+ id_fake_user_clear(id);
+ id->us = 0;
+ }
+
+ break;
+ case UI_ID_FAKE_USER:
+ if (id) {
+ if (id->flag & LIB_FAKEUSER) {
+ id_us_plus(id);
+ }
+ else {
+ id_us_min(id);
+ }
+ }
+ else {
+ return;
+ }
+ break;
+ case UI_ID_LOCAL:
+ if (id) {
+ Main *bmain = CTX_data_main(C);
+ if (BKE_override_static_is_enabled() && CTX_wm_window(C)->eventstate->shift) {
+ ID *override_id = BKE_override_static_create_from_id(bmain, id);
+ if (override_id != NULL) {
+ BKE_main_id_clear_newpoins(bmain);
+
+ /* Assign new pointer, takes care of updates/notifiers */
+ RNA_id_pointer_create(override_id, &idptr);
+ }
+ }
+ else {
+ if (id_make_local(bmain, id, false, false)) {
+ BKE_main_id_clear_newpoins(bmain);
+
+ /* reassign to get get proper updates/notifiers */
+ idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
+ }
+ }
+ RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr);
+ RNA_property_update(C, &template_ui->ptr, template_ui->prop);
+ }
+ break;
+ case UI_ID_OVERRIDE:
+ if (id && id->override_static) {
+ BKE_override_static_free(&id->override_static);
+ /* reassign to get get proper updates/notifiers */
+ idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
+ RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr);
+ RNA_property_update(C, &template_ui->ptr, template_ui->prop);
+ }
+ break;
+ case UI_ID_ALONE:
+ if (id) {
+ const bool do_scene_obj = ((GS(id->name) == ID_OB) &&
+ (template_ui->ptr.type == &RNA_LayerObjects));
+
+ /* make copy */
+ if (do_scene_obj) {
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ED_object_single_user(bmain, scene, (struct Object *)id);
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ 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);
+ }
+ }
+ }
+ break;
#if 0
- case UI_ID_AUTO_NAME:
- break;
+ case UI_ID_AUTO_NAME:
+ break;
#endif
- }
+ }
}
static const char *template_id_browse_tip(const StructRNA *type)
{
- if (type) {
- switch (RNA_type_to_ID_code(type)) {
- case ID_SCE: return N_("Browse Scene to be linked");
- case ID_OB: return N_("Browse Object to be linked");
- case ID_ME: return N_("Browse Mesh Data to be linked");
- case ID_CU: return N_("Browse Curve Data to be linked");
- case ID_MB: return N_("Browse Metaball Data to be linked");
- case ID_MA: return N_("Browse Material to be linked");
- case ID_TE: return N_("Browse Texture to be linked");
- case ID_IM: return N_("Browse Image to be linked");
- case ID_LS: return N_("Browse Line Style Data to be linked");
- case ID_LT: return N_("Browse Lattice Data to be linked");
- case ID_LA: return N_("Browse Light Data to be linked");
- case ID_CA: return N_("Browse Camera Data to be linked");
- case ID_WO: return N_("Browse World Settings to be linked");
- case ID_SCR: return N_("Choose Screen layout");
- case ID_TXT: return N_("Browse Text to be linked");
- case ID_SPK: return N_("Browse Speaker Data to be linked");
- case ID_SO: return N_("Browse Sound to be linked");
- case ID_AR: return N_("Browse Armature data to be linked");
- case ID_AC: return N_("Browse Action to be linked");
- case ID_NT: return N_("Browse Node Tree to be linked");
- case ID_BR: return N_("Browse Brush to be linked");
- case ID_PA: return N_("Browse Particle Settings to be linked");
- case ID_GD: return N_("Browse Grease Pencil Data to be linked");
- case ID_MC: return N_("Browse Movie Clip to be linked");
- case ID_MSK: return N_("Browse Mask to be linked");
- case ID_PAL: return N_("Browse Palette Data to be linked");
- case ID_PC: return N_("Browse Paint Curve Data to be linked");
- case ID_CF: return N_("Browse Cache Files to be linked");
- case ID_WS: return N_("Browse Workspace to be linked");
- case ID_LP: return N_("Browse LightProbe to be linked");
- }
- }
- return N_("Browse ID data to be linked");
+ if (type) {
+ switch (RNA_type_to_ID_code(type)) {
+ case ID_SCE:
+ return N_("Browse Scene to be linked");
+ case ID_OB:
+ return N_("Browse Object to be linked");
+ case ID_ME:
+ return N_("Browse Mesh Data to be linked");
+ case ID_CU:
+ return N_("Browse Curve Data to be linked");
+ case ID_MB:
+ return N_("Browse Metaball Data to be linked");
+ case ID_MA:
+ return N_("Browse Material to be linked");
+ case ID_TE:
+ return N_("Browse Texture to be linked");
+ case ID_IM:
+ return N_("Browse Image to be linked");
+ case ID_LS:
+ return N_("Browse Line Style Data to be linked");
+ case ID_LT:
+ return N_("Browse Lattice Data to be linked");
+ case ID_LA:
+ return N_("Browse Light Data to be linked");
+ case ID_CA:
+ return N_("Browse Camera Data to be linked");
+ case ID_WO:
+ return N_("Browse World Settings to be linked");
+ case ID_SCR:
+ return N_("Choose Screen layout");
+ case ID_TXT:
+ return N_("Browse Text to be linked");
+ case ID_SPK:
+ return N_("Browse Speaker Data to be linked");
+ case ID_SO:
+ return N_("Browse Sound to be linked");
+ case ID_AR:
+ return N_("Browse Armature data to be linked");
+ case ID_AC:
+ return N_("Browse Action to be linked");
+ case ID_NT:
+ return N_("Browse Node Tree to be linked");
+ case ID_BR:
+ return N_("Browse Brush to be linked");
+ case ID_PA:
+ return N_("Browse Particle Settings to be linked");
+ case ID_GD:
+ return N_("Browse Grease Pencil Data to be linked");
+ case ID_MC:
+ return N_("Browse Movie Clip to be linked");
+ case ID_MSK:
+ return N_("Browse Mask to be linked");
+ case ID_PAL:
+ return N_("Browse Palette Data to be linked");
+ case ID_PC:
+ return N_("Browse Paint Curve Data to be linked");
+ case ID_CF:
+ return N_("Browse Cache Files to be linked");
+ case ID_WS:
+ return N_("Browse Workspace to be linked");
+ case ID_LP:
+ return N_("Browse LightProbe to be linked");
+ }
+ }
+ return N_("Browse ID data to be linked");
}
/**
@@ -576,460 +653,719 @@ static const char *template_id_browse_tip(const StructRNA *type)
#ifdef WITH_INTERNATIONAL
static const char *template_id_context(StructRNA *type)
{
- if (type) {
- return BKE_idcode_to_translation_context(RNA_type_to_ID_code(type));
- }
- return BLT_I18NCONTEXT_DEFAULT;
+ if (type) {
+ return BKE_idcode_to_translation_context(RNA_type_to_ID_code(type));
+ }
+ return BLT_I18NCONTEXT_DEFAULT;
}
#endif
-static uiBut *template_id_def_new_but(
- uiBlock *block, const ID *id, const TemplateID *template_ui, StructRNA *type,
- const char * const newop, const bool editable, const bool id_open, const bool use_tab_but,
- int but_height)
+static uiBut *template_id_def_new_but(uiBlock *block,
+ const ID *id,
+ const TemplateID *template_ui,
+ StructRNA *type,
+ const char *const newop,
+ const bool editable,
+ const bool id_open,
+ const bool use_tab_but,
+ int but_height)
{
- ID *idfrom = template_ui->ptr.id.data;
- uiBut *but;
- const int w = id ? UI_UNIT_X : id_open ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
- const int but_type = use_tab_but ? UI_BTYPE_TAB : UI_BTYPE_BUT;
-
- /* i18n markup, does nothing! */
- BLT_I18N_MSGID_MULTI_CTXT(
- "New",
- BLT_I18NCONTEXT_DEFAULT,
- BLT_I18NCONTEXT_ID_SCENE,
- BLT_I18NCONTEXT_ID_OBJECT,
- BLT_I18NCONTEXT_ID_MESH,
- BLT_I18NCONTEXT_ID_CURVE,
- BLT_I18NCONTEXT_ID_METABALL,
- BLT_I18NCONTEXT_ID_MATERIAL,
- BLT_I18NCONTEXT_ID_TEXTURE,
- BLT_I18NCONTEXT_ID_IMAGE,
- BLT_I18NCONTEXT_ID_LATTICE,
- BLT_I18NCONTEXT_ID_LIGHT,
- BLT_I18NCONTEXT_ID_CAMERA,
- BLT_I18NCONTEXT_ID_WORLD,
- BLT_I18NCONTEXT_ID_SCREEN,
- BLT_I18NCONTEXT_ID_TEXT,
- );
- BLT_I18N_MSGID_MULTI_CTXT(
- "New",
- BLT_I18NCONTEXT_ID_SPEAKER,
- BLT_I18NCONTEXT_ID_SOUND,
- BLT_I18NCONTEXT_ID_ARMATURE,
- BLT_I18NCONTEXT_ID_ACTION,
- BLT_I18NCONTEXT_ID_NODETREE,
- BLT_I18NCONTEXT_ID_BRUSH,
- BLT_I18NCONTEXT_ID_PARTICLESETTINGS,
- BLT_I18NCONTEXT_ID_GPENCIL,
- BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE,
- BLT_I18NCONTEXT_ID_WORKSPACE,
- BLT_I18NCONTEXT_ID_LIGHTPROBE,
- );
-
- if (newop) {
- but = uiDefIconTextButO(
- block, but_type, newop, WM_OP_INVOKE_DEFAULT, (id && !use_tab_but) ? ICON_DUPLICATE : ICON_ADD,
- (id) ? "" : CTX_IFACE_(template_id_context(type), "New"), 0, 0, w, but_height, NULL);
- UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ADD_NEW));
- }
- else {
- but = uiDefIconTextBut(
- block, but_type, 0, (id && !use_tab_but) ? ICON_DUPLICATE : ICON_ADD,
- (id) ? "" : CTX_IFACE_(template_id_context(type), "New"),
- 0, 0, w, but_height, NULL, 0, 0, 0, 0, NULL);
- UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ADD_NEW));
- }
-
- if ((idfrom && idfrom->lib) || !editable) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
+ ID *idfrom = template_ui->ptr.id.data;
+ uiBut *but;
+ const int w = id ? UI_UNIT_X : id_open ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
+ const int but_type = use_tab_but ? UI_BTYPE_TAB : UI_BTYPE_BUT;
+
+ /* i18n markup, does nothing! */
+ BLT_I18N_MSGID_MULTI_CTXT("New",
+ BLT_I18NCONTEXT_DEFAULT,
+ BLT_I18NCONTEXT_ID_SCENE,
+ BLT_I18NCONTEXT_ID_OBJECT,
+ BLT_I18NCONTEXT_ID_MESH,
+ BLT_I18NCONTEXT_ID_CURVE,
+ BLT_I18NCONTEXT_ID_METABALL,
+ BLT_I18NCONTEXT_ID_MATERIAL,
+ BLT_I18NCONTEXT_ID_TEXTURE,
+ BLT_I18NCONTEXT_ID_IMAGE,
+ BLT_I18NCONTEXT_ID_LATTICE,
+ BLT_I18NCONTEXT_ID_LIGHT,
+ BLT_I18NCONTEXT_ID_CAMERA,
+ BLT_I18NCONTEXT_ID_WORLD,
+ BLT_I18NCONTEXT_ID_SCREEN,
+ BLT_I18NCONTEXT_ID_TEXT, );
+ BLT_I18N_MSGID_MULTI_CTXT("New",
+ BLT_I18NCONTEXT_ID_SPEAKER,
+ BLT_I18NCONTEXT_ID_SOUND,
+ BLT_I18NCONTEXT_ID_ARMATURE,
+ BLT_I18NCONTEXT_ID_ACTION,
+ BLT_I18NCONTEXT_ID_NODETREE,
+ BLT_I18NCONTEXT_ID_BRUSH,
+ BLT_I18NCONTEXT_ID_PARTICLESETTINGS,
+ BLT_I18NCONTEXT_ID_GPENCIL,
+ BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE,
+ BLT_I18NCONTEXT_ID_WORKSPACE,
+ BLT_I18NCONTEXT_ID_LIGHTPROBE, );
+
+ if (newop) {
+ but = uiDefIconTextButO(block,
+ but_type,
+ newop,
+ WM_OP_INVOKE_DEFAULT,
+ (id && !use_tab_but) ? ICON_DUPLICATE : ICON_ADD,
+ (id) ? "" : CTX_IFACE_(template_id_context(type), "New"),
+ 0,
+ 0,
+ w,
+ but_height,
+ NULL);
+ UI_but_funcN_set(
+ but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ADD_NEW));
+ }
+ else {
+ but = uiDefIconTextBut(block,
+ but_type,
+ 0,
+ (id && !use_tab_but) ? ICON_DUPLICATE : ICON_ADD,
+ (id) ? "" : CTX_IFACE_(template_id_context(type), "New"),
+ 0,
+ 0,
+ w,
+ but_height,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL);
+ UI_but_funcN_set(
+ but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ADD_NEW));
+ }
+
+ if ((idfrom && idfrom->lib) || !editable) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
#ifndef WITH_INTERNATIONAL
- UNUSED_VARS(type);
+ UNUSED_VARS(type);
#endif
- return but;
+ return but;
}
-static void template_ID(
- bContext *C, uiLayout *layout, TemplateID *template_ui, StructRNA *type, int flag,
- const char *newop, const char *openop, const char *unlinkop,
- const bool live_icon, const bool hide_buttons)
+static void template_ID(bContext *C,
+ uiLayout *layout,
+ TemplateID *template_ui,
+ StructRNA *type,
+ int flag,
+ const char *newop,
+ const char *openop,
+ const char *unlinkop,
+ const bool live_icon,
+ const bool hide_buttons)
{
- uiBut *but;
- uiBlock *block;
- PointerRNA idptr;
- // ListBase *lb; // UNUSED
- ID *id, *idfrom;
- const bool editable = RNA_property_editable(&template_ui->ptr, template_ui->prop);
- const bool use_previews = template_ui->preview = (flag & UI_ID_PREVIEWS) != 0;
-
- idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
- id = idptr.data;
- idfrom = template_ui->ptr.id.data;
- // lb = template_ui->idlb;
-
- block = uiLayoutGetBlock(layout);
- UI_block_align_begin(block);
-
- if (idptr.type) {
- type = idptr.type;
- }
-
- if (flag & UI_ID_BROWSE) {
- template_add_button_search_menu(
- C, layout, block, &template_ui->ptr, template_ui->prop,
- id_search_menu, MEM_dupallocN(template_ui), TIP_(template_id_browse_tip(type)),
- use_previews, editable, live_icon);
- }
-
- /* text button with name */
- if (id) {
- char name[UI_MAX_NAME_STR];
- const bool user_alert = (id->us <= 0);
-
- //text_idbutton(id, name);
- name[0] = '\0';
- but = uiDefButR(
- block, UI_BTYPE_TEXT, 0, name, 0, 0, TEMPLATE_SEARCH_TEXTBUT_WIDTH, TEMPLATE_SEARCH_TEXTBUT_HEIGHT,
- &idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type));
- UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_RENAME));
- if (user_alert) {
- UI_but_flag_enable(but, UI_BUT_REDALERT);
- }
-
- if (id->lib) {
- if (id->tag & LIB_TAG_INDIRECT) {
- but = uiDefIconBut(
- block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0, 0, 0, 0, TIP_("Indirect library data-block, cannot change"));
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- else {
- const bool disabled = (
- !id_make_local(CTX_data_main(C), id, true /* test */, false) ||
- (idfrom && idfrom->lib));
- but = uiDefIconBut(
- block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0, 0, 0, 0,
- BKE_override_static_is_enabled() ?
- TIP_("Direct linked library data-block, click to make local, "
- "Shift + Click to create a static override") :
- TIP_("Direct linked library data-block, click to make local"));
- if (disabled) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- else {
- UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_LOCAL));
- }
- }
- }
- else if (ID_IS_STATIC_OVERRIDE(id)) {
- but = uiDefIconBut(
- block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_OVERRIDE, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0, 0, 0, 0,
- TIP_("Static override of linked library data-block, click to make fully local"));
- UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OVERRIDE));
- }
-
- if ((ID_REAL_USERS(id) > 1) && (hide_buttons == false)) {
- char numstr[32];
- short numstr_len;
-
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", ID_REAL_USERS(id));
-
- but = uiDefBut(
- block, UI_BTYPE_BUT, 0, numstr, 0, 0,
- numstr_len * 0.2f * UI_UNIT_X + UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0,
- TIP_("Display number of users of this data (click to make a single-user copy)"));
- but->flag |= UI_BUT_UNDO;
-
- UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ALONE));
- if ((!BKE_id_copy_is_allowed(id)) ||
- (idfrom && idfrom->lib) ||
- (!editable) ||
- /* object in editmode - don't change data */
- (idfrom && GS(idfrom->name) == ID_OB && (((Object *)idfrom)->mode & OB_MODE_EDIT)))
- {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- }
-
- if (user_alert) {
- UI_but_flag_enable(but, UI_BUT_REDALERT);
- }
-
- if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS)) &&
- (hide_buttons == false))
- {
- uiDefIconButR(
- block, UI_BTYPE_ICON_TOGGLE, 0, ICON_FAKE_USER_OFF, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL);
- }
- }
-
- if ((flag & UI_ID_ADD_NEW) && (hide_buttons == false)) {
- template_id_def_new_but(block, id, template_ui, type, newop, editable, flag & UI_ID_OPEN, false, UI_UNIT_X);
- }
-
- /* Due to space limit in UI - skip the "open" icon for packed data, and allow to unpack.
- * Only for images, sound and fonts */
- if (id && BKE_pack_check(id)) {
- but = uiDefIconButO(
- block, UI_BTYPE_BUT, "FILE_OT_unpack_item", WM_OP_INVOKE_REGION_WIN, ICON_PACKAGE, 0, 0,
- UI_UNIT_X, UI_UNIT_Y, TIP_("Packed File, click to unpack"));
- UI_but_operator_ptr_get(but);
-
- RNA_string_set(but->opptr, "id_name", id->name + 2);
- RNA_int_set(but->opptr, "id_type", GS(id->name));
-
- }
- else if (flag & UI_ID_OPEN) {
- int w = id ? UI_UNIT_X : (flag & UI_ID_ADD_NEW) ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
-
- if (openop) {
- but = uiDefIconTextButO(
- block, UI_BTYPE_BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILEBROWSER, (id) ? "" : IFACE_("Open"),
- 0, 0, w, UI_UNIT_Y, NULL);
- UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OPEN));
- }
- else {
- but = uiDefIconTextBut(
- block, UI_BTYPE_BUT, 0, ICON_FILEBROWSER, (id) ? "" : IFACE_("Open"), 0, 0, w, UI_UNIT_Y,
- NULL, 0, 0, 0, 0, NULL);
- UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OPEN));
- }
-
- if ((idfrom && idfrom->lib) || !editable) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- }
-
- /* delete button */
- /* don't use RNA_property_is_unlink here */
- if (id && (flag & UI_ID_DELETE) && (hide_buttons == false)) {
- /* allow unlink if 'unlinkop' is passed, even when 'PROP_NEVER_UNLINK' is set */
- but = NULL;
-
- if (unlinkop) {
- but = uiDefIconButO(block, UI_BTYPE_BUT, unlinkop, WM_OP_INVOKE_DEFAULT, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
- /* so we can access the template from operators, font unlinking needs this */
- UI_but_funcN_set(but, NULL, MEM_dupallocN(template_ui), NULL);
- }
- else {
- if ((RNA_property_flag(template_ui->prop) & PROP_NEVER_UNLINK) == 0) {
- but = uiDefIconBut(
- block, UI_BTYPE_BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0,
- TIP_("Unlink data-block "
- "(Shift + Click to set users to zero, data will then not be saved)"));
- UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_DELETE));
-
- if (RNA_property_flag(template_ui->prop) & PROP_NEVER_NULL) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- }
- }
-
- if (but) {
- if ((idfrom && idfrom->lib) || !editable) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- }
- }
-
- if (template_ui->idcode == ID_TE) {
- uiTemplateTextureShow(layout, C, &template_ui->ptr, template_ui->prop);
- }
- UI_block_align_end(block);
+ uiBut *but;
+ uiBlock *block;
+ PointerRNA idptr;
+ // ListBase *lb; // UNUSED
+ ID *id, *idfrom;
+ const bool editable = RNA_property_editable(&template_ui->ptr, template_ui->prop);
+ const bool use_previews = template_ui->preview = (flag & UI_ID_PREVIEWS) != 0;
+
+ idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
+ id = idptr.data;
+ idfrom = template_ui->ptr.id.data;
+ // lb = template_ui->idlb;
+
+ block = uiLayoutGetBlock(layout);
+ UI_block_align_begin(block);
+
+ if (idptr.type) {
+ type = idptr.type;
+ }
+
+ if (flag & UI_ID_BROWSE) {
+ template_add_button_search_menu(C,
+ layout,
+ block,
+ &template_ui->ptr,
+ template_ui->prop,
+ id_search_menu,
+ MEM_dupallocN(template_ui),
+ TIP_(template_id_browse_tip(type)),
+ use_previews,
+ editable,
+ live_icon);
+ }
+
+ /* text button with name */
+ if (id) {
+ char name[UI_MAX_NAME_STR];
+ const bool user_alert = (id->us <= 0);
+
+ //text_idbutton(id, name);
+ name[0] = '\0';
+ but = uiDefButR(block,
+ UI_BTYPE_TEXT,
+ 0,
+ name,
+ 0,
+ 0,
+ TEMPLATE_SEARCH_TEXTBUT_WIDTH,
+ TEMPLATE_SEARCH_TEXTBUT_HEIGHT,
+ &idptr,
+ "name",
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ RNA_struct_ui_description(type));
+ UI_but_funcN_set(
+ but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_RENAME));
+ if (user_alert) {
+ UI_but_flag_enable(but, UI_BUT_REDALERT);
+ }
+
+ if (id->lib) {
+ if (id->tag & LIB_TAG_INDIRECT) {
+ but = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_LIBRARY_DATA_INDIRECT,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Indirect library data-block, cannot change"));
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ else {
+ const bool disabled = (!id_make_local(CTX_data_main(C), id, true /* test */, false) ||
+ (idfrom && idfrom->lib));
+ but = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_LIBRARY_DATA_DIRECT,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ BKE_override_static_is_enabled() ?
+ TIP_("Direct linked library data-block, click to make local, "
+ "Shift + Click to create a static override") :
+ TIP_("Direct linked library data-block, click to make local"));
+ if (disabled) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ else {
+ UI_but_funcN_set(
+ but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_LOCAL));
+ }
+ }
+ }
+ else if (ID_IS_STATIC_OVERRIDE(id)) {
+ but = uiDefIconBut(
+ block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_LIBRARY_DATA_OVERRIDE,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Static override of linked library data-block, click to make fully local"));
+ UI_but_funcN_set(
+ but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OVERRIDE));
+ }
+
+ if ((ID_REAL_USERS(id) > 1) && (hide_buttons == false)) {
+ char numstr[32];
+ short numstr_len;
+
+ numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", ID_REAL_USERS(id));
+
+ but = uiDefBut(
+ block,
+ UI_BTYPE_BUT,
+ 0,
+ numstr,
+ 0,
+ 0,
+ numstr_len * 0.2f * UI_UNIT_X + UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Display number of users of this data (click to make a single-user copy)"));
+ but->flag |= UI_BUT_UNDO;
+
+ UI_but_funcN_set(
+ but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ALONE));
+ if ((!BKE_id_copy_is_allowed(id)) || (idfrom && idfrom->lib) || (!editable) ||
+ /* object in editmode - don't change data */
+ (idfrom && GS(idfrom->name) == ID_OB && (((Object *)idfrom)->mode & OB_MODE_EDIT))) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ }
+
+ if (user_alert) {
+ UI_but_flag_enable(but, UI_BUT_REDALERT);
+ }
+
+ if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS)) &&
+ (hide_buttons == false)) {
+ uiDefIconButR(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ ICON_FAKE_USER_OFF,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &idptr,
+ "use_fake_user",
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ }
+ }
+
+ if ((flag & UI_ID_ADD_NEW) && (hide_buttons == false)) {
+ template_id_def_new_but(
+ block, id, template_ui, type, newop, editable, flag & UI_ID_OPEN, false, UI_UNIT_X);
+ }
+
+ /* Due to space limit in UI - skip the "open" icon for packed data, and allow to unpack.
+ * Only for images, sound and fonts */
+ if (id && BKE_pack_check(id)) {
+ but = uiDefIconButO(block,
+ UI_BTYPE_BUT,
+ "FILE_OT_unpack_item",
+ WM_OP_INVOKE_REGION_WIN,
+ ICON_PACKAGE,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ TIP_("Packed File, click to unpack"));
+ UI_but_operator_ptr_get(but);
+
+ RNA_string_set(but->opptr, "id_name", id->name + 2);
+ RNA_int_set(but->opptr, "id_type", GS(id->name));
+ }
+ else if (flag & UI_ID_OPEN) {
+ int w = id ? UI_UNIT_X : (flag & UI_ID_ADD_NEW) ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
+
+ if (openop) {
+ but = uiDefIconTextButO(block,
+ UI_BTYPE_BUT,
+ openop,
+ WM_OP_INVOKE_DEFAULT,
+ ICON_FILEBROWSER,
+ (id) ? "" : IFACE_("Open"),
+ 0,
+ 0,
+ w,
+ UI_UNIT_Y,
+ NULL);
+ UI_but_funcN_set(
+ but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OPEN));
+ }
+ else {
+ but = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_FILEBROWSER,
+ (id) ? "" : IFACE_("Open"),
+ 0,
+ 0,
+ w,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL);
+ UI_but_funcN_set(
+ but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OPEN));
+ }
+
+ if ((idfrom && idfrom->lib) || !editable) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ }
+
+ /* delete button */
+ /* don't use RNA_property_is_unlink here */
+ if (id && (flag & UI_ID_DELETE) && (hide_buttons == false)) {
+ /* allow unlink if 'unlinkop' is passed, even when 'PROP_NEVER_UNLINK' is set */
+ but = NULL;
+
+ if (unlinkop) {
+ but = uiDefIconButO(block,
+ UI_BTYPE_BUT,
+ unlinkop,
+ WM_OP_INVOKE_DEFAULT,
+ ICON_X,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL);
+ /* so we can access the template from operators, font unlinking needs this */
+ UI_but_funcN_set(but, NULL, MEM_dupallocN(template_ui), NULL);
+ }
+ else {
+ if ((RNA_property_flag(template_ui->prop) & PROP_NEVER_UNLINK) == 0) {
+ but = uiDefIconBut(
+ block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_X,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Unlink data-block "
+ "(Shift + Click to set users to zero, data will then not be saved)"));
+ UI_but_funcN_set(
+ but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_DELETE));
+
+ if (RNA_property_flag(template_ui->prop) & PROP_NEVER_NULL) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ }
+ }
+
+ if (but) {
+ if ((idfrom && idfrom->lib) || !editable) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ }
+ }
+
+ if (template_ui->idcode == ID_TE) {
+ uiTemplateTextureShow(layout, C, &template_ui->ptr, template_ui->prop);
+ }
+ UI_block_align_end(block);
}
-
ID *UI_context_active_but_get_tab_ID(bContext *C)
{
- uiBut *but = UI_context_active_but_get(C);
-
- if (but && but->type == UI_BTYPE_TAB) {
- return but->custom_data;
- }
- else {
- return NULL;
- }
+ uiBut *but = UI_context_active_but_get(C);
+
+ if (but && but->type == UI_BTYPE_TAB) {
+ return but->custom_data;
+ }
+ else {
+ return NULL;
+ }
}
-static void template_ID_tabs(
- bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, int flag,
- const char *newop, const char *menu)
+static void template_ID_tabs(bContext *C,
+ uiLayout *layout,
+ TemplateID *template,
+ StructRNA *type,
+ int flag,
+ const char *newop,
+ const char *menu)
{
- const ARegion *region = CTX_wm_region(C);
- const PointerRNA active_ptr = RNA_property_pointer_get(&template->ptr, template->prop);
- MenuType *mt = WM_menutype_find(menu, false);
-
- const int but_align = ui_but_align_opposite_to_area_align_get(region);
- const int but_height = UI_UNIT_Y * 1.1;
-
- uiBlock *block = uiLayoutGetBlock(layout);
- uiStyle *style = UI_style_get_dpi();
-
- ListBase ordered;
- BKE_id_ordered_list(&ordered, template->idlb);
-
- for (LinkData *link = ordered.first; link; link = link->next) {
- 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;
-
- uiButTab *tab = (uiButTab *)uiDefButR_prop(
- block, UI_BTYPE_TAB, 0, id->name + 2, 0, 0, but_width, but_height,
- &template->ptr, template->prop, 0, 0.0f,
- sizeof(id->name) - 2, 0.0f, 0.0f, "");
- UI_but_funcN_set(&tab->but, template_ID_set_property_cb, MEM_dupallocN(template), id);
- tab->but.custom_data = (void *)id;
- tab->but.dragpoin = id;
- tab->menu = mt;
-
- UI_but_drawflag_enable(&tab->but, but_align);
- }
-
- BLI_freelistN(&ordered);
-
- if (flag & UI_ID_ADD_NEW) {
- const bool editable = RNA_property_editable(&template->ptr, template->prop);
- uiBut *but;
-
- if (active_ptr.type) {
- type = active_ptr.type;
- }
-
- but = template_id_def_new_but(block, active_ptr.data, template, type, newop, editable, flag & UI_ID_OPEN, true, but_height);
- UI_but_drawflag_enable(but, but_align);
- }
+ const ARegion *region = CTX_wm_region(C);
+ const PointerRNA active_ptr = RNA_property_pointer_get(&template->ptr, template->prop);
+ MenuType *mt = WM_menutype_find(menu, false);
+
+ const int but_align = ui_but_align_opposite_to_area_align_get(region);
+ const int but_height = UI_UNIT_Y * 1.1;
+
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiStyle *style = UI_style_get_dpi();
+
+ ListBase ordered;
+ BKE_id_ordered_list(&ordered, template->idlb);
+
+ for (LinkData *link = ordered.first; link; link = link->next) {
+ 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;
+
+ uiButTab *tab = (uiButTab *)uiDefButR_prop(block,
+ UI_BTYPE_TAB,
+ 0,
+ id->name + 2,
+ 0,
+ 0,
+ but_width,
+ but_height,
+ &template->ptr,
+ template->prop,
+ 0,
+ 0.0f,
+ sizeof(id->name) - 2,
+ 0.0f,
+ 0.0f,
+ "");
+ UI_but_funcN_set(&tab->but, template_ID_set_property_cb, MEM_dupallocN(template), id);
+ tab->but.custom_data = (void *)id;
+ tab->but.dragpoin = id;
+ tab->menu = mt;
+
+ UI_but_drawflag_enable(&tab->but, but_align);
+ }
+
+ BLI_freelistN(&ordered);
+
+ if (flag & UI_ID_ADD_NEW) {
+ const bool editable = RNA_property_editable(&template->ptr, template->prop);
+ uiBut *but;
+
+ if (active_ptr.type) {
+ type = active_ptr.type;
+ }
+
+ but = template_id_def_new_but(block,
+ active_ptr.data,
+ template,
+ type,
+ newop,
+ editable,
+ flag & UI_ID_OPEN,
+ true,
+ but_height);
+ UI_but_drawflag_enable(but, but_align);
+ }
}
-static void ui_template_id(
- uiLayout *layout, bContext *C,
- PointerRNA *ptr, const char *propname,
- const char *newop, const char *openop, const char *unlinkop,
- int flag, int prv_rows, int prv_cols, int filter, bool use_tabs,
- float scale, const bool live_icon, const bool hide_buttons)
+static void ui_template_id(uiLayout *layout,
+ bContext *C,
+ PointerRNA *ptr,
+ const char *propname,
+ const char *newop,
+ const char *openop,
+ const char *unlinkop,
+ int flag,
+ int prv_rows,
+ int prv_cols,
+ int filter,
+ bool use_tabs,
+ float scale,
+ const bool live_icon,
+ const bool hide_buttons)
{
- TemplateID *template_ui;
- PropertyRNA *prop;
- StructRNA *type;
- short idcode;
-
- prop = RNA_struct_find_property(ptr, propname);
-
- if (!prop || RNA_property_type(prop) != PROP_POINTER) {
- RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- template_ui = MEM_callocN(sizeof(TemplateID), "TemplateID");
- template_ui->ptr = *ptr;
- template_ui->prop = prop;
- template_ui->prv_rows = prv_rows;
- template_ui->prv_cols = prv_cols;
- template_ui->scale = scale;
-
- if ((flag & UI_ID_PIN) == 0) {
- template_ui->filter = filter;
- }
- else {
- template_ui->filter = 0;
- }
-
- if (newop) {
- flag |= UI_ID_ADD_NEW;
- }
- if (openop) {
- flag |= UI_ID_OPEN;
- }
-
- type = RNA_property_pointer_type(ptr, prop);
- idcode = RNA_type_to_ID_code(type);
- template_ui->idcode = idcode;
- template_ui->idlb = which_libbase(CTX_data_main(C), idcode);
-
- /* create UI elements for this template
- * - template_ID makes a copy of the template data and assigns it to the relevant buttons
- */
- if (template_ui->idlb) {
- if (use_tabs) {
- uiLayoutRow(layout, true);
- template_ID_tabs(C, layout, template_ui, type, flag, newop, unlinkop);
- }
- else {
- uiLayoutRow(layout, true);
- template_ID(
- C, layout, template_ui, type, flag, newop, openop,
- unlinkop, live_icon, hide_buttons);
- }
- }
-
- MEM_freeN(template_ui);
+ TemplateID *template_ui;
+ PropertyRNA *prop;
+ StructRNA *type;
+ short idcode;
+
+ prop = RNA_struct_find_property(ptr, propname);
+
+ if (!prop || RNA_property_type(prop) != PROP_POINTER) {
+ RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ template_ui = MEM_callocN(sizeof(TemplateID), "TemplateID");
+ template_ui->ptr = *ptr;
+ template_ui->prop = prop;
+ template_ui->prv_rows = prv_rows;
+ template_ui->prv_cols = prv_cols;
+ template_ui->scale = scale;
+
+ if ((flag & UI_ID_PIN) == 0) {
+ template_ui->filter = filter;
+ }
+ else {
+ template_ui->filter = 0;
+ }
+
+ if (newop) {
+ flag |= UI_ID_ADD_NEW;
+ }
+ if (openop) {
+ flag |= UI_ID_OPEN;
+ }
+
+ type = RNA_property_pointer_type(ptr, prop);
+ idcode = RNA_type_to_ID_code(type);
+ template_ui->idcode = idcode;
+ template_ui->idlb = which_libbase(CTX_data_main(C), idcode);
+
+ /* create UI elements for this template
+ * - template_ID makes a copy of the template data and assigns it to the relevant buttons
+ */
+ if (template_ui->idlb) {
+ if (use_tabs) {
+ uiLayoutRow(layout, true);
+ template_ID_tabs(C, layout, template_ui, type, flag, newop, unlinkop);
+ }
+ else {
+ uiLayoutRow(layout, true);
+ template_ID(
+ C, layout, template_ui, type, flag, newop, openop, unlinkop, live_icon, hide_buttons);
+ }
+ }
+
+ MEM_freeN(template_ui);
}
-void uiTemplateID(
- uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
- const char *openop, const char *unlinkop,
- int filter, const bool live_icon)
+void uiTemplateID(uiLayout *layout,
+ bContext *C,
+ PointerRNA *ptr,
+ const char *propname,
+ const char *newop,
+ const char *openop,
+ const char *unlinkop,
+ int filter,
+ const bool live_icon)
{
- ui_template_id(
- layout, C, ptr, propname,
- newop, openop, unlinkop,
- UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE,
- 0, 0, filter, false, 1.0f, live_icon, false);
+ ui_template_id(layout,
+ C,
+ ptr,
+ propname,
+ newop,
+ openop,
+ unlinkop,
+ UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE,
+ 0,
+ 0,
+ filter,
+ false,
+ 1.0f,
+ live_icon,
+ false);
}
-void uiTemplateIDBrowse(
- uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
- const char *openop, const char *unlinkop, int filter)
+void uiTemplateIDBrowse(uiLayout *layout,
+ bContext *C,
+ PointerRNA *ptr,
+ const char *propname,
+ const char *newop,
+ const char *openop,
+ const char *unlinkop,
+ int filter)
{
- ui_template_id(
- layout, C, ptr, propname,
- newop, openop, unlinkop,
- UI_ID_BROWSE | UI_ID_RENAME,
- 0, 0, filter, false, 1.0f, false, false);
+ ui_template_id(layout,
+ C,
+ ptr,
+ propname,
+ newop,
+ openop,
+ unlinkop,
+ UI_ID_BROWSE | UI_ID_RENAME,
+ 0,
+ 0,
+ filter,
+ false,
+ 1.0f,
+ false,
+ false);
}
-void uiTemplateIDPreview(
- uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
- const char *openop, const char *unlinkop, int rows, int cols, int filter,
- const bool hide_buttons)
+void uiTemplateIDPreview(uiLayout *layout,
+ bContext *C,
+ PointerRNA *ptr,
+ const char *propname,
+ const char *newop,
+ const char *openop,
+ const char *unlinkop,
+ int rows,
+ int cols,
+ int filter,
+ const bool hide_buttons)
{
- ui_template_id(
- layout, C, ptr, propname,
- newop, openop, unlinkop,
- UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS,
- rows, cols, filter, false, 1.0f, false, hide_buttons);
+ ui_template_id(layout,
+ C,
+ ptr,
+ propname,
+ newop,
+ openop,
+ unlinkop,
+ UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS,
+ rows,
+ cols,
+ filter,
+ false,
+ 1.0f,
+ false,
+ hide_buttons);
}
-void uiTemplateGpencilColorPreview(
- uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname,
- int rows, int cols, float scale, int filter)
+void uiTemplateGpencilColorPreview(uiLayout *layout,
+ bContext *C,
+ PointerRNA *ptr,
+ const char *propname,
+ int rows,
+ int cols,
+ float scale,
+ int filter)
{
- ui_template_id(
- layout, C, ptr, propname,
- NULL, NULL, NULL,
- UI_ID_BROWSE | UI_ID_PREVIEWS | UI_ID_DELETE,
- rows, cols, filter, false, scale < 0.5f ? 0.5f : scale, false, false);
+ ui_template_id(layout,
+ C,
+ ptr,
+ propname,
+ NULL,
+ NULL,
+ NULL,
+ UI_ID_BROWSE | UI_ID_PREVIEWS | UI_ID_DELETE,
+ rows,
+ cols,
+ filter,
+ false,
+ scale < 0.5f ? 0.5f : scale,
+ false,
+ false);
}
/**
* Version of #uiTemplateID using tabs.
*/
-void uiTemplateIDTabs(
- uiLayout *layout, bContext *C,
- PointerRNA *ptr, const char *propname,
- const char *newop, const char *unlinkop,
- int filter)
+void uiTemplateIDTabs(uiLayout *layout,
+ bContext *C,
+ PointerRNA *ptr,
+ const char *propname,
+ const char *newop,
+ const char *unlinkop,
+ int filter)
{
- ui_template_id(
- layout, C, ptr, propname,
- newop, NULL, unlinkop,
- UI_ID_BROWSE | UI_ID_RENAME,
- 0, 0, filter, true, 1.0f, false, false);
+ ui_template_id(layout,
+ C,
+ ptr,
+ propname,
+ newop,
+ NULL,
+ unlinkop,
+ UI_ID_BROWSE | UI_ID_RENAME,
+ 0,
+ 0,
+ filter,
+ true,
+ 1.0f,
+ false,
+ false);
}
/************************ ID Chooser Template ***************************/
@@ -1040,267 +1376,313 @@ void uiTemplateIDTabs(
* - propname: property identifier for property that ID-pointer gets stored to
* - proptypename: property identifier for property used to determine the type of ID-pointer that can be used
*/
-void uiTemplateAnyID(
- uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename,
- const char *text)
+void uiTemplateAnyID(uiLayout *layout,
+ PointerRNA *ptr,
+ const char *propname,
+ const char *proptypename,
+ const char *text)
{
- PropertyRNA *propID, *propType;
- uiLayout *split, *row, *sub;
+ PropertyRNA *propID, *propType;
+ uiLayout *split, *row, *sub;
- /* get properties... */
- propID = RNA_struct_find_property(ptr, propname);
- propType = RNA_struct_find_property(ptr, proptypename);
+ /* get properties... */
+ propID = RNA_struct_find_property(ptr, propname);
+ propType = RNA_struct_find_property(ptr, proptypename);
- if (!propID || RNA_property_type(propID) != PROP_POINTER) {
- RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
- return;
- }
- if (!propType || RNA_property_type(propType) != PROP_ENUM) {
- RNA_warning("pointer-type property not found: %s.%s", RNA_struct_identifier(ptr->type), proptypename);
- return;
- }
+ if (!propID || RNA_property_type(propID) != PROP_POINTER) {
+ RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+ if (!propType || RNA_property_type(propType) != PROP_ENUM) {
+ RNA_warning(
+ "pointer-type property not found: %s.%s", RNA_struct_identifier(ptr->type), proptypename);
+ return;
+ }
- /* Start drawing UI Elements using standard defines */
+ /* Start drawing UI Elements using standard defines */
- /* NOTE: split amount here needs to be synced with normal labels */
- split = uiLayoutSplit(layout, 0.33f, false);
+ /* NOTE: split amount here needs to be synced with normal labels */
+ split = uiLayoutSplit(layout, 0.33f, false);
- /* FIRST PART ................................................ */
- row = uiLayoutRow(split, false);
+ /* FIRST PART ................................................ */
+ row = uiLayoutRow(split, false);
- /* Label - either use the provided text, or will become "ID-Block:" */
- if (text) {
- if (text[0]) {
- uiItemL(row, text, ICON_NONE);
- }
- }
- else {
- uiItemL(row, IFACE_("ID-Block:"), ICON_NONE);
- }
+ /* Label - either use the provided text, or will become "ID-Block:" */
+ if (text) {
+ if (text[0]) {
+ uiItemL(row, text, ICON_NONE);
+ }
+ }
+ else {
+ uiItemL(row, IFACE_("ID-Block:"), ICON_NONE);
+ }
- /* SECOND PART ................................................ */
- row = uiLayoutRow(split, true);
+ /* SECOND PART ................................................ */
+ row = uiLayoutRow(split, true);
- /* ID-Type Selector - just have a menu of icons */
+ /* ID-Type Selector - just have a menu of icons */
- /* HACK: special group just for the enum,
- * otherwise we get ugly layout with text included too... */
- sub = uiLayoutRow(row, true);
- uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
+ /* HACK: special group just for the enum,
+ * otherwise we get ugly layout with text included too... */
+ sub = uiLayoutRow(row, true);
+ uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
- uiItemFullR(sub, ptr, propType, 0, 0, UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ uiItemFullR(sub, ptr, propType, 0, 0, UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
- /* ID-Block Selector - just use pointer widget... */
+ /* ID-Block Selector - just use pointer widget... */
- /* HACK: special group to counteract the effects of the previous enum,
- * which now pushes everything too far right. */
- sub = uiLayoutRow(row, true);
- uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_EXPAND);
+ /* HACK: special group to counteract the effects of the previous enum,
+ * which now pushes everything too far right. */
+ sub = uiLayoutRow(row, true);
+ uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_EXPAND);
- uiItemFullR(sub, ptr, propID, 0, 0, 0, "", ICON_NONE);
+ uiItemFullR(sub, ptr, propID, 0, 0, 0, "", ICON_NONE);
}
/********************* Search Template ********************/
typedef struct TemplateSearch {
- uiRNACollectionSearch search_data;
+ uiRNACollectionSearch search_data;
- bool use_previews;
- int preview_rows, preview_cols;
+ bool use_previews;
+ int preview_rows, preview_cols;
} TemplateSearch;
static void template_search_handle_cb(bContext *C, void *arg_template, void *item)
{
- TemplateSearch *template_search = arg_template;
- uiRNACollectionSearch *coll_search = &template_search->search_data;
- StructRNA *type = RNA_property_pointer_type(&coll_search->target_ptr, coll_search->target_prop);
- PointerRNA item_ptr;
-
- RNA_pointer_create(NULL, type, item, &item_ptr);
- RNA_property_pointer_set(&coll_search->target_ptr, coll_search->target_prop, item_ptr);
- RNA_property_update(C, &coll_search->target_ptr, coll_search->target_prop);
+ TemplateSearch *template_search = arg_template;
+ uiRNACollectionSearch *coll_search = &template_search->search_data;
+ StructRNA *type = RNA_property_pointer_type(&coll_search->target_ptr, coll_search->target_prop);
+ PointerRNA item_ptr;
+
+ RNA_pointer_create(NULL, type, item, &item_ptr);
+ RNA_property_pointer_set(&coll_search->target_ptr, coll_search->target_prop, item_ptr);
+ RNA_property_update(C, &coll_search->target_ptr, coll_search->target_prop);
}
static uiBlock *template_search_menu(bContext *C, ARegion *region, void *arg_template)
{
- static TemplateSearch template_search;
- PointerRNA active_ptr;
-
- /* arg_template is malloced, can be freed by parent button */
- template_search = *((TemplateSearch *)arg_template);
- active_ptr = RNA_property_pointer_get(
- &template_search.search_data.target_ptr,
- template_search.search_data.target_prop);
-
- return template_common_search_menu(
- C, region, ui_rna_collection_search_cb, &template_search,
- template_search_handle_cb, active_ptr.data,
- template_search.preview_rows, template_search.preview_cols, 1.0f);
+ static TemplateSearch template_search;
+ PointerRNA active_ptr;
+
+ /* arg_template is malloced, can be freed by parent button */
+ template_search = *((TemplateSearch *)arg_template);
+ active_ptr = RNA_property_pointer_get(&template_search.search_data.target_ptr,
+ template_search.search_data.target_prop);
+
+ return template_common_search_menu(C,
+ region,
+ ui_rna_collection_search_cb,
+ &template_search,
+ template_search_handle_cb,
+ active_ptr.data,
+ template_search.preview_rows,
+ template_search.preview_cols,
+ 1.0f);
}
-static void template_search_add_button_searchmenu(
- const bContext *C, uiLayout *layout, uiBlock *block,
- TemplateSearch *template_search, const bool editable, const bool live_icon)
+static void template_search_add_button_searchmenu(const bContext *C,
+ uiLayout *layout,
+ uiBlock *block,
+ TemplateSearch *template_search,
+ const bool editable,
+ const bool live_icon)
{
- const char *ui_description = RNA_property_ui_description(template_search->search_data.target_prop);
-
- template_add_button_search_menu(
- C, layout, block,
- &template_search->search_data.target_ptr, template_search->search_data.target_prop,
- template_search_menu, MEM_dupallocN(template_search), ui_description,
- template_search->use_previews, editable, live_icon);
+ const char *ui_description = RNA_property_ui_description(
+ template_search->search_data.target_prop);
+
+ template_add_button_search_menu(C,
+ layout,
+ block,
+ &template_search->search_data.target_ptr,
+ template_search->search_data.target_prop,
+ template_search_menu,
+ MEM_dupallocN(template_search),
+ ui_description,
+ template_search->use_previews,
+ editable,
+ live_icon);
}
-static void template_search_add_button_name(
- uiBlock *block, PointerRNA *active_ptr, const StructRNA *type)
+static void template_search_add_button_name(uiBlock *block,
+ PointerRNA *active_ptr,
+ const StructRNA *type)
{
- uiDefAutoButR(
- block, active_ptr, RNA_struct_name_property(type), 0, "", ICON_NONE,
- 0, 0, TEMPLATE_SEARCH_TEXTBUT_WIDTH, TEMPLATE_SEARCH_TEXTBUT_HEIGHT);
+ uiDefAutoButR(block,
+ active_ptr,
+ RNA_struct_name_property(type),
+ 0,
+ "",
+ ICON_NONE,
+ 0,
+ 0,
+ TEMPLATE_SEARCH_TEXTBUT_WIDTH,
+ TEMPLATE_SEARCH_TEXTBUT_HEIGHT);
}
-static void template_search_add_button_operator(
- uiBlock *block, const char * const operator_name,
- const int opcontext, const int icon, const bool editable)
+static void template_search_add_button_operator(uiBlock *block,
+ const char *const operator_name,
+ const int opcontext,
+ const int icon,
+ const bool editable)
{
- if (!operator_name) {
- return;
- }
+ if (!operator_name) {
+ return;
+ }
- uiBut *but = uiDefIconButO(
- block, UI_BTYPE_BUT, operator_name, opcontext, icon,
- 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+ uiBut *but = uiDefIconButO(
+ block, UI_BTYPE_BUT, operator_name, opcontext, icon, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
- if (!editable) {
- UI_but_drawflag_enable(but, UI_BUT_DISABLED);
- }
+ if (!editable) {
+ UI_but_drawflag_enable(but, UI_BUT_DISABLED);
+ }
}
-static void template_search_buttons(
- const bContext *C, uiLayout *layout, TemplateSearch *template_search,
- const char *newop, const char *unlinkop)
+static void template_search_buttons(const bContext *C,
+ uiLayout *layout,
+ TemplateSearch *template_search,
+ const char *newop,
+ const char *unlinkop)
{
- uiBlock *block = uiLayoutGetBlock(layout);
- uiRNACollectionSearch *search_data = &template_search->search_data;
- StructRNA *type = RNA_property_pointer_type(&search_data->target_ptr, search_data->target_prop);
- const bool editable = RNA_property_editable(&search_data->target_ptr, search_data->target_prop);
- PointerRNA active_ptr = RNA_property_pointer_get(&search_data->target_ptr, search_data->target_prop);
-
- if (active_ptr.type) {
- /* can only get correct type when there is an active item */
- type = active_ptr.type;
- }
-
- uiLayoutRow(layout, true);
- UI_block_align_begin(block);
-
- template_search_add_button_searchmenu(C, layout, block, template_search, editable, false);
- template_search_add_button_name(block, &active_ptr, type);
- template_search_add_button_operator(block, newop, WM_OP_INVOKE_DEFAULT, ICON_DUPLICATE, editable);
- template_search_add_button_operator(block, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, editable);
-
- UI_block_align_end(block);
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiRNACollectionSearch *search_data = &template_search->search_data;
+ StructRNA *type = RNA_property_pointer_type(&search_data->target_ptr, search_data->target_prop);
+ const bool editable = RNA_property_editable(&search_data->target_ptr, search_data->target_prop);
+ PointerRNA active_ptr = RNA_property_pointer_get(&search_data->target_ptr,
+ search_data->target_prop);
+
+ if (active_ptr.type) {
+ /* can only get correct type when there is an active item */
+ type = active_ptr.type;
+ }
+
+ uiLayoutRow(layout, true);
+ UI_block_align_begin(block);
+
+ template_search_add_button_searchmenu(C, layout, block, template_search, editable, false);
+ template_search_add_button_name(block, &active_ptr, type);
+ template_search_add_button_operator(
+ block, newop, WM_OP_INVOKE_DEFAULT, ICON_DUPLICATE, editable);
+ template_search_add_button_operator(block, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, editable);
+
+ UI_block_align_end(block);
}
-static PropertyRNA *template_search_get_searchprop(
- PointerRNA *targetptr, PropertyRNA *targetprop,
- PointerRNA *searchptr, const char * const searchpropname)
+static PropertyRNA *template_search_get_searchprop(PointerRNA *targetptr,
+ PropertyRNA *targetprop,
+ PointerRNA *searchptr,
+ const char *const searchpropname)
{
- PropertyRNA *searchprop;
-
- if (searchptr && !searchptr->data) {
- searchptr = NULL;
- }
-
- if (!searchptr && !searchpropname) {
- /* both NULL means we don't use a custom rna collection to search in */
- }
- else if (!searchptr && searchpropname) {
- RNA_warning("searchpropname defined (%s) but searchptr is missing", searchpropname);
- }
- else if (searchptr && !searchpropname) {
- RNA_warning("searchptr defined (%s) but searchpropname is missing", RNA_struct_identifier(searchptr->type));
- }
- else if (!(searchprop = RNA_struct_find_property(searchptr, searchpropname))) {
- RNA_warning("search collection property not found: %s.%s",
- RNA_struct_identifier(searchptr->type), searchpropname);
- }
- else if (RNA_property_type(searchprop) != PROP_COLLECTION) {
- RNA_warning("search collection property is not a collection type: %s.%s",
- RNA_struct_identifier(searchptr->type), searchpropname);
- }
- /* check if searchprop has same type as targetprop */
- else if (RNA_property_pointer_type(searchptr, searchprop) != RNA_property_pointer_type(targetptr, targetprop)) {
- RNA_warning("search collection items from %s.%s are not of type %s",
- RNA_struct_identifier(searchptr->type), searchpropname,
- RNA_struct_identifier(RNA_property_pointer_type(targetptr, targetprop)));
- }
- else {
- return searchprop;
- }
-
- return NULL;
+ PropertyRNA *searchprop;
+
+ if (searchptr && !searchptr->data) {
+ searchptr = NULL;
+ }
+
+ if (!searchptr && !searchpropname) {
+ /* both NULL means we don't use a custom rna collection to search in */
+ }
+ else if (!searchptr && searchpropname) {
+ RNA_warning("searchpropname defined (%s) but searchptr is missing", searchpropname);
+ }
+ else if (searchptr && !searchpropname) {
+ RNA_warning("searchptr defined (%s) but searchpropname is missing",
+ RNA_struct_identifier(searchptr->type));
+ }
+ else if (!(searchprop = RNA_struct_find_property(searchptr, searchpropname))) {
+ RNA_warning("search collection property not found: %s.%s",
+ RNA_struct_identifier(searchptr->type),
+ searchpropname);
+ }
+ else if (RNA_property_type(searchprop) != PROP_COLLECTION) {
+ RNA_warning("search collection property is not a collection type: %s.%s",
+ RNA_struct_identifier(searchptr->type),
+ searchpropname);
+ }
+ /* check if searchprop has same type as targetprop */
+ else if (RNA_property_pointer_type(searchptr, searchprop) !=
+ RNA_property_pointer_type(targetptr, targetprop)) {
+ RNA_warning("search collection items from %s.%s are not of type %s",
+ RNA_struct_identifier(searchptr->type),
+ searchpropname,
+ RNA_struct_identifier(RNA_property_pointer_type(targetptr, targetprop)));
+ }
+ else {
+ return searchprop;
+ }
+
+ return NULL;
}
-static TemplateSearch *template_search_setup(
- PointerRNA *ptr, const char * const propname,
- PointerRNA *searchptr, const char * const searchpropname)
+static TemplateSearch *template_search_setup(PointerRNA *ptr,
+ const char *const propname,
+ PointerRNA *searchptr,
+ const char *const searchpropname)
{
- TemplateSearch *template_search;
- PropertyRNA *prop, *searchprop;
+ TemplateSearch *template_search;
+ PropertyRNA *prop, *searchprop;
- prop = RNA_struct_find_property(ptr, propname);
+ prop = RNA_struct_find_property(ptr, propname);
- if (!prop || RNA_property_type(prop) != PROP_POINTER) {
- RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
- return NULL;
- }
- searchprop = template_search_get_searchprop(ptr, prop, searchptr, searchpropname);
+ if (!prop || RNA_property_type(prop) != PROP_POINTER) {
+ RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return NULL;
+ }
+ searchprop = template_search_get_searchprop(ptr, prop, searchptr, searchpropname);
- template_search = MEM_callocN(sizeof(*template_search), __func__);
- template_search->search_data.target_ptr = *ptr;
- template_search->search_data.target_prop = prop;
- template_search->search_data.search_ptr = *searchptr;
- template_search->search_data.search_prop = searchprop;
+ template_search = MEM_callocN(sizeof(*template_search), __func__);
+ template_search->search_data.target_ptr = *ptr;
+ template_search->search_data.target_prop = prop;
+ template_search->search_data.search_ptr = *searchptr;
+ template_search->search_data.search_prop = searchprop;
- return template_search;
+ return template_search;
}
/**
* Search menu to pick an item from a collection.
* A version of uiTemplateID that works for non-ID types.
*/
-void uiTemplateSearch(
- uiLayout *layout, bContext *C,
- PointerRNA *ptr, const char *propname,
- PointerRNA *searchptr, const char *searchpropname,
- const char *newop, const char *unlinkop)
+void uiTemplateSearch(uiLayout *layout,
+ bContext *C,
+ PointerRNA *ptr,
+ const char *propname,
+ PointerRNA *searchptr,
+ const char *searchpropname,
+ const char *newop,
+ const char *unlinkop)
{
- TemplateSearch *template_search = template_search_setup(ptr, propname, searchptr, searchpropname);
- if (template_search != NULL) {
- template_search_buttons(C, layout, template_search, newop, unlinkop);
- MEM_freeN(template_search);
- }
+ TemplateSearch *template_search = template_search_setup(
+ ptr, propname, searchptr, searchpropname);
+ if (template_search != NULL) {
+ template_search_buttons(C, layout, template_search, newop, unlinkop);
+ MEM_freeN(template_search);
+ }
}
-void uiTemplateSearchPreview(
- uiLayout *layout, bContext *C,
- PointerRNA *ptr, const char *propname,
- PointerRNA *searchptr, const char *searchpropname,
- const char *newop, const char *unlinkop,
- const int rows, const int cols)
+void uiTemplateSearchPreview(uiLayout *layout,
+ bContext *C,
+ PointerRNA *ptr,
+ const char *propname,
+ PointerRNA *searchptr,
+ const char *searchpropname,
+ const char *newop,
+ const char *unlinkop,
+ const int rows,
+ const int cols)
{
- TemplateSearch *template_search = template_search_setup(ptr, propname, searchptr, searchpropname);
+ TemplateSearch *template_search = template_search_setup(
+ ptr, propname, searchptr, searchpropname);
- if (template_search != NULL) {
- template_search->use_previews = true;
- template_search->preview_rows = rows;
- template_search->preview_cols = cols;
+ if (template_search != NULL) {
+ template_search->use_previews = true;
+ template_search->preview_rows = rows;
+ template_search->preview_cols = cols;
- template_search_buttons(C, layout, template_search, newop, unlinkop);
+ template_search_buttons(C, layout, template_search, newop, unlinkop);
- MEM_freeN(template_search);
- }
+ MEM_freeN(template_search);
+ }
}
/********************* RNA Path Builder Template ********************/
@@ -1314,28 +1696,30 @@ void uiTemplateSearchPreview(
* - propname: property identifier for property that path gets stored to
* - root_ptr: struct that path gets built from
*/
-void uiTemplatePathBuilder(
- uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *UNUSED(root_ptr),
- const char *text)
+void uiTemplatePathBuilder(uiLayout *layout,
+ PointerRNA *ptr,
+ const char *propname,
+ PointerRNA *UNUSED(root_ptr),
+ const char *text)
{
- PropertyRNA *propPath;
- uiLayout *row;
+ PropertyRNA *propPath;
+ uiLayout *row;
- /* check that properties are valid */
- propPath = RNA_struct_find_property(ptr, propname);
- if (!propPath || RNA_property_type(propPath) != PROP_STRING) {
- RNA_warning("path property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
- return;
- }
+ /* check that properties are valid */
+ propPath = RNA_struct_find_property(ptr, propname);
+ if (!propPath || RNA_property_type(propPath) != PROP_STRING) {
+ RNA_warning("path property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
- /* Start drawing UI Elements using standard defines */
- row = uiLayoutRow(layout, true);
+ /* Start drawing UI Elements using standard defines */
+ row = uiLayoutRow(layout, true);
- /* Path (existing string) Widget */
- uiItemR(row, ptr, propname, 0, text, ICON_RNA);
+ /* Path (existing string) Widget */
+ uiItemR(row, ptr, propname, 0, text, ICON_RNA);
- /* TODO: attach something to this to make allow
- * searching of nested properties to 'build' the path */
+ /* TODO: attach something to this to make allow
+ * searching of nested properties to 'build' the path */
}
/************************ Modifier Template *************************/
@@ -1344,796 +1728,887 @@ void uiTemplatePathBuilder(
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);
+ Object *ob = ob_v;
+ ModifierData *md = md_v;
+ ModifierData *nmd = modifier_new(md->type);
- modifier_copyData(md, nmd);
- nmd->mode &= ~eModifierMode_Virtual;
+ modifier_copyData(md, nmd);
+ nmd->mode &= ~eModifierMode_Virtual;
- BLI_addhead(&ob->modifiers, nmd);
+ BLI_addhead(&ob->modifiers, nmd);
- modifier_unique_name(&ob->modifiers, nmd);
+ modifier_unique_name(&ob->modifiers, nmd);
- ob->partype = PAROBJECT;
+ ob->partype = PAROBJECT;
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- ED_undo_push(C, "Modifier convert to real");
+ ED_undo_push(C, "Modifier convert to real");
}
static int modifier_can_delete(ModifierData *md)
{
- /* fluid particle modifier can't be deleted here */
- if (md->type == eModifierType_ParticleSystem) {
- if (((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID) {
- return 0;
- }
- }
-
- return 1;
+ /* fluid particle modifier can't be deleted here */
+ if (md->type == eModifierType_ParticleSystem) {
+ if (((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID) {
+ return 0;
+ }
+ }
+
+ return 1;
}
/* Check whether Modifier is a simulation or not,
* this is used for switching to the physics/particles context tab */
static int modifier_is_simulation(ModifierData *md)
{
- /* Physic Tab */
- if (ELEM(md->type, eModifierType_Cloth, eModifierType_Collision, eModifierType_Fluidsim, eModifierType_Smoke,
- eModifierType_Softbody, eModifierType_Surface, eModifierType_DynamicPaint))
- {
- return 1;
- }
- /* Particle Tab */
- else if (md->type == eModifierType_ParticleSystem) {
- return 2;
- }
- else {
- return 0;
- }
+ /* Physic Tab */
+ if (ELEM(md->type,
+ eModifierType_Cloth,
+ eModifierType_Collision,
+ eModifierType_Fluidsim,
+ eModifierType_Smoke,
+ eModifierType_Softbody,
+ eModifierType_Surface,
+ eModifierType_DynamicPaint)) {
+ return 1;
+ }
+ /* Particle Tab */
+ else if (md->type == eModifierType_ParticleSystem) {
+ return 2;
+ }
+ else {
+ return 0;
+ }
}
-static uiLayout *draw_modifier(
- uiLayout *layout, Scene *scene, Object *ob,
- ModifierData *md, int index, int cageIndex, int lastCageIndex)
+static uiLayout *draw_modifier(uiLayout *layout,
+ Scene *scene,
+ Object *ob,
+ ModifierData *md,
+ int index,
+ int cageIndex,
+ int lastCageIndex)
{
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- PointerRNA ptr;
- uiBut *but;
- uiBlock *block;
- uiLayout *box, *column, *row, *sub;
- uiLayout *result = NULL;
- int isVirtual = (md->mode & eModifierMode_Virtual);
- char str[128];
-
- /* create RNA pointer */
- RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr);
-
- column = uiLayoutColumn(layout, true);
- uiLayoutSetContextPointer(column, "modifier", &ptr);
-
- /* rounded header ------------------------------------------------------------------- */
- box = uiLayoutBox(column);
-
- if (isVirtual) {
- row = uiLayoutRow(box, false);
- uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_EXPAND);
- block = uiLayoutGetBlock(row);
- /* VIRTUAL MODIFIER */
- /* XXX this is not used now, since these cannot be accessed via RNA */
- BLI_snprintf(str, sizeof(str), IFACE_("%s parent deform"), md->name);
- uiDefBut(block, UI_BTYPE_LABEL, 0, str, 0, 0, 185, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Modifier name"));
-
- but = uiDefBut(
- block, UI_BTYPE_BUT, 0, IFACE_("Make Real"), 0, 0, 80, 16, NULL, 0.0, 0.0, 0.0, 0.0,
- TIP_("Convert virtual modifier to a real modifier"));
- UI_but_func_set(but, modifiers_convertToReal, ob, md);
- }
- else {
- /* REAL MODIFIER */
- row = uiLayoutRow(box, false);
- block = uiLayoutGetBlock(row);
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- /* Open/Close ................................. */
- uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE);
-
- /* modifier-type icon */
- uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
- UI_block_emboss_set(block, UI_EMBOSS);
-
- /* modifier name */
- if (mti->isDisabled && mti->isDisabled(scene, md, 0)) {
- uiLayoutSetRedAlert(row, true);
- }
- uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
- uiLayoutSetRedAlert(row, false);
-
- /* mode enabling buttons */
- UI_block_align_begin(block);
- /* Collision and Surface are always enabled, hide buttons! */
- if (((md->type != eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) &&
- (md->type != eModifierType_Surface) )
- {
- uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE);
- uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE);
-
- if (mti->flags & eModifierTypeFlag_SupportsEditmode) {
- sub = uiLayoutRow(row, true);
- if (!(md->mode & eModifierMode_Realtime)) {
- uiLayoutSetActive(sub, false);
- }
- uiItemR(sub, &ptr, "show_in_editmode", 0, "", ICON_NONE);
- }
- }
-
- if (ob->type == OB_MESH) {
- if (modifier_supportsCage(scene, md) && (index <= lastCageIndex)) {
- sub = uiLayoutRow(row, true);
- if (index < cageIndex || !modifier_couldBeCage(scene, md)) {
- uiLayoutSetActive(sub, false);
- }
- uiItemR(sub, &ptr, "show_on_cage", 0, "", ICON_NONE);
- }
- } /* tessellation point for curve-typed objects */
- else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
- /* some modifiers could work with pre-tessellated curves only */
- if (ELEM(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
- /* add disabled pre-tessellated button, so users could have
- * message for this modifiers */
- but = uiDefIconButBitI(
- block, UI_BTYPE_TOGGLE, eModifierMode_ApplyOnSpline, 0, ICON_SURFACE_DATA, 0, 0,
- UI_UNIT_X - 2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0,
- TIP_("This modifier can only be applied on splines' points"));
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- else if (mti->type != eModifierTypeType_Constructive) {
- /* constructive modifiers tessellates curve before applying */
- uiItemR(row, &ptr, "use_apply_on_spline", 0, "", ICON_NONE);
- }
- }
-
- UI_block_align_end(block);
-
- /* Up/Down + Delete ........................... */
- UI_block_align_begin(block);
- uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_modifier_move_up");
- uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_modifier_move_down");
- UI_block_align_end(block);
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- /* When Modifier is a simulation,
- * show button to switch to context rather than the delete button. */
- if (modifier_can_delete(md) &&
- !modifier_is_simulation(md))
- {
- uiItemO(row, "", ICON_X, "OBJECT_OT_modifier_remove");
- }
- else if (modifier_is_simulation(md) == 1) {
- uiItemStringO(row, "", ICON_PROPERTIES, "WM_OT_properties_context_change", "context", "PHYSICS");
- }
- else if (modifier_is_simulation(md) == 2) {
- uiItemStringO(row, "", ICON_PROPERTIES, "WM_OT_properties_context_change", "context", "PARTICLES");
- }
- UI_block_emboss_set(block, UI_EMBOSS);
- }
-
-
- /* modifier settings (under the header) --------------------------------------------------- */
- if (!isVirtual && (md->mode & eModifierMode_Expanded)) {
- /* apply/convert/copy */
- box = uiLayoutBox(column);
- row = uiLayoutRow(box, false);
-
- if (!ELEM(md->type, eModifierType_Collision, eModifierType_Surface)) {
- /* only here obdata, the rest of modifiers is ob level */
- UI_block_lock_set(block, BKE_object_obdata_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
-
- if (md->type == eModifierType_ParticleSystem) {
- ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys;
-
- if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) {
- if (ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB)) {
- uiItemO(row, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"), ICON_NONE,
- "OBJECT_OT_duplicates_make_real");
- }
- else if (psys->part->ren_as == PART_DRAW_PATH) {
- uiItemO(row, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"), ICON_NONE,
- "OBJECT_OT_modifier_convert");
- }
- }
- }
- else {
- uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
- uiItemEnumO(
- row, "OBJECT_OT_modifier_apply", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
- 0, "apply_as", MODIFIER_APPLY_DATA);
-
- if (modifier_isSameTopology(md) && !modifier_isNonGeometrical(md)) {
- uiItemEnumO(
- row, "OBJECT_OT_modifier_apply",
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply as Shape Key"),
- 0, "apply_as", MODIFIER_APPLY_SHAPE);
- }
- }
-
- UI_block_lock_clear(block);
- UI_block_lock_set(block, ob && ID_IS_LINKED(ob), ERROR_LIBDATA_MESSAGE);
-
- if (!ELEM(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem,
- eModifierType_Cloth, eModifierType_Smoke))
- {
- uiItemO(row, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy"), ICON_NONE,
- "OBJECT_OT_modifier_copy");
- }
- }
-
- /* result is the layout block inside the box,
- * that we return so that modifier settings can be drawn */
- result = uiLayoutColumn(box, false);
- block = uiLayoutAbsoluteBlock(box);
- }
-
- /* error messages */
- if (md->error) {
- box = uiLayoutBox(column);
- row = uiLayoutRow(box, false);
- uiItemL(row, md->error, ICON_ERROR);
- }
-
- return result;
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ PointerRNA ptr;
+ uiBut *but;
+ uiBlock *block;
+ uiLayout *box, *column, *row, *sub;
+ uiLayout *result = NULL;
+ int isVirtual = (md->mode & eModifierMode_Virtual);
+ char str[128];
+
+ /* create RNA pointer */
+ RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr);
+
+ column = uiLayoutColumn(layout, true);
+ uiLayoutSetContextPointer(column, "modifier", &ptr);
+
+ /* rounded header ------------------------------------------------------------------- */
+ box = uiLayoutBox(column);
+
+ if (isVirtual) {
+ row = uiLayoutRow(box, false);
+ uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_EXPAND);
+ block = uiLayoutGetBlock(row);
+ /* VIRTUAL MODIFIER */
+ /* XXX this is not used now, since these cannot be accessed via RNA */
+ BLI_snprintf(str, sizeof(str), IFACE_("%s parent deform"), md->name);
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ str,
+ 0,
+ 0,
+ 185,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Modifier name"));
+
+ but = uiDefBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ IFACE_("Make Real"),
+ 0,
+ 0,
+ 80,
+ 16,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Convert virtual modifier to a real modifier"));
+ UI_but_func_set(but, modifiers_convertToReal, ob, md);
+ }
+ else {
+ /* REAL MODIFIER */
+ row = uiLayoutRow(box, false);
+ block = uiLayoutGetBlock(row);
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ /* Open/Close ................................. */
+ uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE);
+
+ /* modifier-type icon */
+ uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ /* modifier name */
+ if (mti->isDisabled && mti->isDisabled(scene, md, 0)) {
+ uiLayoutSetRedAlert(row, true);
+ }
+ uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
+ uiLayoutSetRedAlert(row, false);
+
+ /* mode enabling buttons */
+ UI_block_align_begin(block);
+ /* Collision and Surface are always enabled, hide buttons! */
+ if (((md->type != eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) &&
+ (md->type != eModifierType_Surface)) {
+ uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE);
+ uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE);
+
+ if (mti->flags & eModifierTypeFlag_SupportsEditmode) {
+ sub = uiLayoutRow(row, true);
+ if (!(md->mode & eModifierMode_Realtime)) {
+ uiLayoutSetActive(sub, false);
+ }
+ uiItemR(sub, &ptr, "show_in_editmode", 0, "", ICON_NONE);
+ }
+ }
+
+ if (ob->type == OB_MESH) {
+ if (modifier_supportsCage(scene, md) && (index <= lastCageIndex)) {
+ sub = uiLayoutRow(row, true);
+ if (index < cageIndex || !modifier_couldBeCage(scene, md)) {
+ uiLayoutSetActive(sub, false);
+ }
+ uiItemR(sub, &ptr, "show_on_cage", 0, "", ICON_NONE);
+ }
+ } /* tessellation point for curve-typed objects */
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ /* some modifiers could work with pre-tessellated curves only */
+ if (ELEM(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
+ /* add disabled pre-tessellated button, so users could have
+ * message for this modifiers */
+ but = uiDefIconButBitI(block,
+ UI_BTYPE_TOGGLE,
+ eModifierMode_ApplyOnSpline,
+ 0,
+ ICON_SURFACE_DATA,
+ 0,
+ 0,
+ UI_UNIT_X - 2,
+ UI_UNIT_Y,
+ &md->mode,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("This modifier can only be applied on splines' points"));
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ else if (mti->type != eModifierTypeType_Constructive) {
+ /* constructive modifiers tessellates curve before applying */
+ uiItemR(row, &ptr, "use_apply_on_spline", 0, "", ICON_NONE);
+ }
+ }
+
+ UI_block_align_end(block);
+
+ /* Up/Down + Delete ........................... */
+ UI_block_align_begin(block);
+ uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_modifier_move_up");
+ uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_modifier_move_down");
+ UI_block_align_end(block);
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ /* When Modifier is a simulation,
+ * show button to switch to context rather than the delete button. */
+ if (modifier_can_delete(md) && !modifier_is_simulation(md)) {
+ uiItemO(row, "", ICON_X, "OBJECT_OT_modifier_remove");
+ }
+ else if (modifier_is_simulation(md) == 1) {
+ uiItemStringO(
+ row, "", ICON_PROPERTIES, "WM_OT_properties_context_change", "context", "PHYSICS");
+ }
+ else if (modifier_is_simulation(md) == 2) {
+ uiItemStringO(
+ row, "", ICON_PROPERTIES, "WM_OT_properties_context_change", "context", "PARTICLES");
+ }
+ UI_block_emboss_set(block, UI_EMBOSS);
+ }
+
+ /* modifier settings (under the header) --------------------------------------------------- */
+ if (!isVirtual && (md->mode & eModifierMode_Expanded)) {
+ /* apply/convert/copy */
+ box = uiLayoutBox(column);
+ row = uiLayoutRow(box, false);
+
+ if (!ELEM(md->type, eModifierType_Collision, eModifierType_Surface)) {
+ /* only here obdata, the rest of modifiers is ob level */
+ UI_block_lock_set(block, BKE_object_obdata_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
+
+ if (md->type == eModifierType_ParticleSystem) {
+ ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys;
+
+ if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) {
+ if (ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB)) {
+ uiItemO(row,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"),
+ ICON_NONE,
+ "OBJECT_OT_duplicates_make_real");
+ }
+ else if (psys->part->ren_as == PART_DRAW_PATH) {
+ uiItemO(row,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"),
+ ICON_NONE,
+ "OBJECT_OT_modifier_convert");
+ }
+ }
+ }
+ else {
+ uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
+ uiItemEnumO(row,
+ "OBJECT_OT_modifier_apply",
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
+ 0,
+ "apply_as",
+ MODIFIER_APPLY_DATA);
+
+ if (modifier_isSameTopology(md) && !modifier_isNonGeometrical(md)) {
+ uiItemEnumO(row,
+ "OBJECT_OT_modifier_apply",
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply as Shape Key"),
+ 0,
+ "apply_as",
+ MODIFIER_APPLY_SHAPE);
+ }
+ }
+
+ UI_block_lock_clear(block);
+ UI_block_lock_set(block, ob && ID_IS_LINKED(ob), ERROR_LIBDATA_MESSAGE);
+
+ if (!ELEM(md->type,
+ eModifierType_Fluidsim,
+ eModifierType_Softbody,
+ eModifierType_ParticleSystem,
+ eModifierType_Cloth,
+ eModifierType_Smoke)) {
+ uiItemO(row,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy"),
+ ICON_NONE,
+ "OBJECT_OT_modifier_copy");
+ }
+ }
+
+ /* result is the layout block inside the box,
+ * that we return so that modifier settings can be drawn */
+ result = uiLayoutColumn(box, false);
+ block = uiLayoutAbsoluteBlock(box);
+ }
+
+ /* error messages */
+ if (md->error) {
+ box = uiLayoutBox(column);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, md->error, ICON_ERROR);
+ }
+
+ return result;
}
uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob;
- ModifierData *md, *vmd;
- VirtualModifierData virtualModifierData;
- int i, lastCageIndex, cageIndex;
-
- /* verify we have valid data */
- if (!RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
- RNA_warning("Expected modifier on object");
- return NULL;
- }
-
- ob = ptr->id.data;
- md = ptr->data;
-
- if (!ob || !(GS(ob->id.name) == ID_OB)) {
- RNA_warning("Expected modifier on object");
- return NULL;
- }
-
- 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);
-
- /* XXX virtual modifiers are not accessible for python */
- vmd = modifiers_getVirtualModifierList(ob, &virtualModifierData);
-
- for (i = 0; vmd; i++, vmd = vmd->next) {
- if (md == vmd) {
- return draw_modifier(layout, scene, ob, md, i, cageIndex, lastCageIndex);
- }
- else if (vmd->mode & eModifierMode_Virtual) {
- i--;
- }
- }
-
- return NULL;
+ Scene *scene = CTX_data_scene(C);
+ Object *ob;
+ ModifierData *md, *vmd;
+ VirtualModifierData virtualModifierData;
+ int i, lastCageIndex, cageIndex;
+
+ /* verify we have valid data */
+ if (!RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
+ RNA_warning("Expected modifier on object");
+ return NULL;
+ }
+
+ ob = ptr->id.data;
+ md = ptr->data;
+
+ if (!ob || !(GS(ob->id.name) == ID_OB)) {
+ RNA_warning("Expected modifier on object");
+ return NULL;
+ }
+
+ 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);
+
+ /* XXX virtual modifiers are not accessible for python */
+ vmd = modifiers_getVirtualModifierList(ob, &virtualModifierData);
+
+ for (i = 0; vmd; i++, vmd = vmd->next) {
+ if (md == vmd) {
+ return draw_modifier(layout, scene, ob, md, i, cageIndex, lastCageIndex);
+ }
+ else if (vmd->mode & eModifierMode_Virtual) {
+ i--;
+ }
+ }
+
+ return NULL;
}
/************************ Grease Pencil Modifier Template *************************/
-static uiLayout *gpencil_draw_modifier(
- uiLayout *layout, Object *ob,
- GpencilModifierData *md)
+static uiLayout *gpencil_draw_modifier(uiLayout *layout, Object *ob, GpencilModifierData *md)
{
- const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
- PointerRNA ptr;
- uiBlock *block;
- uiLayout *box, *column, *row, *sub;
- uiLayout *result = NULL;
-
- /* create RNA pointer */
- RNA_pointer_create(&ob->id, &RNA_GpencilModifier, md, &ptr);
-
- column = uiLayoutColumn(layout, true);
- uiLayoutSetContextPointer(column, "modifier", &ptr);
-
- /* rounded header ------------------------------------------------------------------- */
- box = uiLayoutBox(column);
-
- row = uiLayoutRow(box, false);
- block = uiLayoutGetBlock(row);
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- /* Open/Close ................................. */
- uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE);
-
- /* modifier-type icon */
- uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
- UI_block_emboss_set(block, UI_EMBOSS);
-
- /* modifier name */
- if (mti->isDisabled && mti->isDisabled(md, 0)) {
- uiLayoutSetRedAlert(row, true);
- }
- uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
- uiLayoutSetRedAlert(row, false);
-
- /* mode enabling buttons */
- UI_block_align_begin(block);
- uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE);
- uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE);
-
- if (mti->flags & eGpencilModifierTypeFlag_SupportsEditmode) {
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, false);
- uiItemR(sub, &ptr, "show_in_editmode", 0, "", ICON_NONE);
- }
-
- UI_block_align_end(block);
-
- /* Up/Down + Delete ........................... */
- UI_block_align_begin(block);
- uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_gpencil_modifier_move_up");
- uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_gpencil_modifier_move_down");
- UI_block_align_end(block);
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- uiItemO(row, "", ICON_X, "OBJECT_OT_gpencil_modifier_remove");
- UI_block_emboss_set(block, UI_EMBOSS);
-
- /* modifier settings (under the header) --------------------------------------------------- */
- if (md->mode & eGpencilModifierMode_Expanded) {
- /* apply/convert/copy */
- box = uiLayoutBox(column);
- row = uiLayoutRow(box, false);
-
- /* only here obdata, the rest of modifiers is ob level */
- UI_block_lock_set(block, BKE_object_obdata_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
-
- uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
-
- sub = uiLayoutRow(row, false);
- if (mti->flags & eGpencilModifierTypeFlag_NoApply) {
- uiLayoutSetEnabled(sub, false);
- }
- uiItemEnumO(sub, "OBJECT_OT_gpencil_modifier_apply", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
- 0, "apply_as", MODIFIER_APPLY_DATA);
- uiItemO(row, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy"), ICON_NONE,
- "OBJECT_OT_gpencil_modifier_copy");
-
- /* result is the layout block inside the box,
- * that we return so that modifier settings can be drawn */
- result = uiLayoutColumn(box, false);
- block = uiLayoutAbsoluteBlock(box);
- }
-
- /* error messages */
- if (md->error) {
- box = uiLayoutBox(column);
- row = uiLayoutRow(box, false);
- uiItemL(row, md->error, ICON_ERROR);
- }
-
- return result;
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+ PointerRNA ptr;
+ uiBlock *block;
+ uiLayout *box, *column, *row, *sub;
+ uiLayout *result = NULL;
+
+ /* create RNA pointer */
+ RNA_pointer_create(&ob->id, &RNA_GpencilModifier, md, &ptr);
+
+ column = uiLayoutColumn(layout, true);
+ uiLayoutSetContextPointer(column, "modifier", &ptr);
+
+ /* rounded header ------------------------------------------------------------------- */
+ box = uiLayoutBox(column);
+
+ row = uiLayoutRow(box, false);
+ block = uiLayoutGetBlock(row);
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ /* Open/Close ................................. */
+ uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE);
+
+ /* modifier-type icon */
+ uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ /* modifier name */
+ if (mti->isDisabled && mti->isDisabled(md, 0)) {
+ uiLayoutSetRedAlert(row, true);
+ }
+ uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
+ uiLayoutSetRedAlert(row, false);
+
+ /* mode enabling buttons */
+ UI_block_align_begin(block);
+ uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE);
+ uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE);
+
+ if (mti->flags & eGpencilModifierTypeFlag_SupportsEditmode) {
+ sub = uiLayoutRow(row, true);
+ uiLayoutSetActive(sub, false);
+ uiItemR(sub, &ptr, "show_in_editmode", 0, "", ICON_NONE);
+ }
+
+ UI_block_align_end(block);
+
+ /* Up/Down + Delete ........................... */
+ UI_block_align_begin(block);
+ uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_gpencil_modifier_move_up");
+ uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_gpencil_modifier_move_down");
+ UI_block_align_end(block);
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ uiItemO(row, "", ICON_X, "OBJECT_OT_gpencil_modifier_remove");
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ /* modifier settings (under the header) --------------------------------------------------- */
+ if (md->mode & eGpencilModifierMode_Expanded) {
+ /* apply/convert/copy */
+ box = uiLayoutBox(column);
+ row = uiLayoutRow(box, false);
+
+ /* only here obdata, the rest of modifiers is ob level */
+ UI_block_lock_set(block, BKE_object_obdata_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
+
+ uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
+
+ sub = uiLayoutRow(row, false);
+ if (mti->flags & eGpencilModifierTypeFlag_NoApply) {
+ uiLayoutSetEnabled(sub, false);
+ }
+ uiItemEnumO(sub,
+ "OBJECT_OT_gpencil_modifier_apply",
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
+ 0,
+ "apply_as",
+ MODIFIER_APPLY_DATA);
+ uiItemO(row,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy"),
+ ICON_NONE,
+ "OBJECT_OT_gpencil_modifier_copy");
+
+ /* result is the layout block inside the box,
+ * that we return so that modifier settings can be drawn */
+ result = uiLayoutColumn(box, false);
+ block = uiLayoutAbsoluteBlock(box);
+ }
+
+ /* error messages */
+ if (md->error) {
+ box = uiLayoutBox(column);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, md->error, ICON_ERROR);
+ }
+
+ return result;
}
uiLayout *uiTemplateGpencilModifier(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- Object *ob;
- GpencilModifierData *md, *vmd;
- int i;
-
- /* verify we have valid data */
- if (!RNA_struct_is_a(ptr->type, &RNA_GpencilModifier)) {
- RNA_warning("Expected modifier on object");
- return NULL;
- }
-
- ob = ptr->id.data;
- md = ptr->data;
-
- if (!ob || !(GS(ob->id.name) == ID_OB)) {
- RNA_warning("Expected modifier on object");
- return NULL;
- }
-
- UI_block_lock_set(uiLayoutGetBlock(layout), (ob && ID_IS_LINKED(ob)), ERROR_LIBDATA_MESSAGE);
-
- /* find modifier and draw it */
- vmd = ob->greasepencil_modifiers.first;
- for (i = 0; vmd; i++, vmd = vmd->next) {
- if (md == vmd) {
- return gpencil_draw_modifier(layout, ob, md);
- }
- }
-
- return NULL;
+ Object *ob;
+ GpencilModifierData *md, *vmd;
+ int i;
+
+ /* verify we have valid data */
+ if (!RNA_struct_is_a(ptr->type, &RNA_GpencilModifier)) {
+ RNA_warning("Expected modifier on object");
+ return NULL;
+ }
+
+ ob = ptr->id.data;
+ md = ptr->data;
+
+ if (!ob || !(GS(ob->id.name) == ID_OB)) {
+ RNA_warning("Expected modifier on object");
+ return NULL;
+ }
+
+ UI_block_lock_set(uiLayoutGetBlock(layout), (ob && ID_IS_LINKED(ob)), ERROR_LIBDATA_MESSAGE);
+
+ /* find modifier and draw it */
+ vmd = ob->greasepencil_modifiers.first;
+ for (i = 0; vmd; i++, vmd = vmd->next) {
+ if (md == vmd) {
+ return gpencil_draw_modifier(layout, ob, md);
+ }
+ }
+
+ return NULL;
}
/************************ Shader FX Template *************************/
-static uiLayout *gpencil_draw_shaderfx(
- uiLayout *layout, Object *ob,
- ShaderFxData *md)
+static uiLayout *gpencil_draw_shaderfx(uiLayout *layout, Object *ob, ShaderFxData *md)
{
- const ShaderFxTypeInfo *mti = BKE_shaderfxType_getInfo(md->type);
- PointerRNA ptr;
- uiBlock *block;
- uiLayout *box, *column, *row, *sub;
- uiLayout *result = NULL;
-
- /* create RNA pointer */
- RNA_pointer_create(&ob->id, &RNA_ShaderFx, md, &ptr);
-
- column = uiLayoutColumn(layout, true);
- uiLayoutSetContextPointer(column, "shaderfx", &ptr);
-
- /* rounded header ------------------------------------------------------------------- */
- box = uiLayoutBox(column);
-
- row = uiLayoutRow(box, false);
- block = uiLayoutGetBlock(row);
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- /* Open/Close ................................. */
- uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE);
-
- /* shader-type icon */
- uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
- UI_block_emboss_set(block, UI_EMBOSS);
-
- /* effect name */
- if (mti->isDisabled && mti->isDisabled(md, 0)) {
- uiLayoutSetRedAlert(row, true);
- }
- uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
- uiLayoutSetRedAlert(row, false);
-
- /* mode enabling buttons */
- UI_block_align_begin(block);
- uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE);
- uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE);
-
- if (mti->flags & eShaderFxTypeFlag_SupportsEditmode) {
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, false);
- uiItemR(sub, &ptr, "show_in_editmode", 0, "", ICON_NONE);
- }
-
- UI_block_align_end(block);
-
- /* Up/Down + Delete ........................... */
- UI_block_align_begin(block);
- uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_shaderfx_move_up");
- uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_shaderfx_move_down");
- UI_block_align_end(block);
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- uiItemO(row, "", ICON_X, "OBJECT_OT_shaderfx_remove");
- UI_block_emboss_set(block, UI_EMBOSS);
-
- /* effect settings (under the header) --------------------------------------------------- */
- if (md->mode & eShaderFxMode_Expanded) {
- /* apply/convert/copy */
- box = uiLayoutBox(column);
- row = uiLayoutRow(box, false);
-
- /* only here obdata, the rest of effect is ob level */
- UI_block_lock_set(block, BKE_object_obdata_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
-
- /* result is the layout block inside the box,
- * that we return so that effect settings can be drawn */
- result = uiLayoutColumn(box, false);
- block = uiLayoutAbsoluteBlock(box);
- }
-
- /* error messages */
- if (md->error) {
- box = uiLayoutBox(column);
- row = uiLayoutRow(box, false);
- uiItemL(row, md->error, ICON_ERROR);
- }
-
- return result;
+ const ShaderFxTypeInfo *mti = BKE_shaderfxType_getInfo(md->type);
+ PointerRNA ptr;
+ uiBlock *block;
+ uiLayout *box, *column, *row, *sub;
+ uiLayout *result = NULL;
+
+ /* create RNA pointer */
+ RNA_pointer_create(&ob->id, &RNA_ShaderFx, md, &ptr);
+
+ column = uiLayoutColumn(layout, true);
+ uiLayoutSetContextPointer(column, "shaderfx", &ptr);
+
+ /* rounded header ------------------------------------------------------------------- */
+ box = uiLayoutBox(column);
+
+ row = uiLayoutRow(box, false);
+ block = uiLayoutGetBlock(row);
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ /* Open/Close ................................. */
+ uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE);
+
+ /* shader-type icon */
+ uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ /* effect name */
+ if (mti->isDisabled && mti->isDisabled(md, 0)) {
+ uiLayoutSetRedAlert(row, true);
+ }
+ uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
+ uiLayoutSetRedAlert(row, false);
+
+ /* mode enabling buttons */
+ UI_block_align_begin(block);
+ uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE);
+ uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE);
+
+ if (mti->flags & eShaderFxTypeFlag_SupportsEditmode) {
+ sub = uiLayoutRow(row, true);
+ uiLayoutSetActive(sub, false);
+ uiItemR(sub, &ptr, "show_in_editmode", 0, "", ICON_NONE);
+ }
+
+ UI_block_align_end(block);
+
+ /* Up/Down + Delete ........................... */
+ UI_block_align_begin(block);
+ uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_shaderfx_move_up");
+ uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_shaderfx_move_down");
+ UI_block_align_end(block);
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ uiItemO(row, "", ICON_X, "OBJECT_OT_shaderfx_remove");
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ /* effect settings (under the header) --------------------------------------------------- */
+ if (md->mode & eShaderFxMode_Expanded) {
+ /* apply/convert/copy */
+ box = uiLayoutBox(column);
+ row = uiLayoutRow(box, false);
+
+ /* only here obdata, the rest of effect is ob level */
+ UI_block_lock_set(block, BKE_object_obdata_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
+
+ /* result is the layout block inside the box,
+ * that we return so that effect settings can be drawn */
+ result = uiLayoutColumn(box, false);
+ block = uiLayoutAbsoluteBlock(box);
+ }
+
+ /* error messages */
+ if (md->error) {
+ box = uiLayoutBox(column);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, md->error, ICON_ERROR);
+ }
+
+ return result;
}
uiLayout *uiTemplateShaderFx(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- Object *ob;
- ShaderFxData *fx, *vfx;
- int i;
-
- /* verify we have valid data */
- if (!RNA_struct_is_a(ptr->type, &RNA_ShaderFx)) {
- RNA_warning("Expected shader fx on object");
- return NULL;
- }
-
- ob = ptr->id.data;
- fx = ptr->data;
-
- if (!ob || !(GS(ob->id.name) == ID_OB)) {
- RNA_warning("Expected shader fx on object");
- return NULL;
- }
-
- UI_block_lock_set(uiLayoutGetBlock(layout), (ob && ID_IS_LINKED(ob)), ERROR_LIBDATA_MESSAGE);
-
- /* find modifier and draw it */
- vfx = ob->shader_fx.first;
- for (i = 0; vfx; i++, vfx = vfx->next) {
- if (fx == vfx) {
- return gpencil_draw_shaderfx(layout, ob, fx);
- }
- }
-
- return NULL;
+ Object *ob;
+ ShaderFxData *fx, *vfx;
+ int i;
+
+ /* verify we have valid data */
+ if (!RNA_struct_is_a(ptr->type, &RNA_ShaderFx)) {
+ RNA_warning("Expected shader fx on object");
+ return NULL;
+ }
+
+ ob = ptr->id.data;
+ fx = ptr->data;
+
+ if (!ob || !(GS(ob->id.name) == ID_OB)) {
+ RNA_warning("Expected shader fx on object");
+ return NULL;
+ }
+
+ UI_block_lock_set(uiLayoutGetBlock(layout), (ob && ID_IS_LINKED(ob)), ERROR_LIBDATA_MESSAGE);
+
+ /* find modifier and draw it */
+ vfx = ob->shader_fx.first;
+ for (i = 0; vfx; i++, vfx = vfx->next) {
+ if (fx == vfx) {
+ return gpencil_draw_shaderfx(layout, ob, fx);
+ }
+ }
+
+ return NULL;
}
/************************ Redo Buttons Template *************************/
static void template_operator_redo_property_buts_draw(
- const bContext *C, wmOperator *op,
- uiLayout *layout, int layout_flags,
- bool *r_has_advanced)
+ const bContext *C, wmOperator *op, uiLayout *layout, 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);
- }
- }
- else {
- /* Might want to make label_align adjustable somehow. */
- eAutoPropButsReturn return_info = uiTemplateOperatorPropertyButs(
- C, layout, op,
- UI_BUT_LABEL_ALIGN_NONE,
- layout_flags);
- if (return_info & UI_PROP_BUTS_ANY_FAILED_CHECK) {
- if (r_has_advanced) {
- *r_has_advanced = true;
- }
- }
- }
+ 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);
+ }
+ }
+ else {
+ /* Might want to make label_align adjustable somehow. */
+ eAutoPropButsReturn return_info = uiTemplateOperatorPropertyButs(
+ C, layout, op, UI_BUT_LABEL_ALIGN_NONE, layout_flags);
+ if (return_info & UI_PROP_BUTS_ANY_FAILED_CHECK) {
+ if (r_has_advanced) {
+ *r_has_advanced = true;
+ }
+ }
+ }
}
void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C)
{
- wmOperator *op = WM_operator_last_redo(C);
- uiBlock *block = uiLayoutGetBlock(layout);
+ wmOperator *op = WM_operator_last_redo(C);
+ uiBlock *block = uiLayoutGetBlock(layout);
- if (op == NULL) {
- return;
- }
+ if (op == NULL) {
+ return;
+ }
- /* Disable for now, doesn't fit well in popover. */
+ /* Disable for now, doesn't fit well in popover. */
#if 0
- /* Repeat button with operator name as text. */
- uiItemFullO(layout, "SCREEN_OT_repeat_last", RNA_struct_ui_name(op->type->srna),
- ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL);
+ /* Repeat button with operator name as text. */
+ uiItemFullO(layout, "SCREEN_OT_repeat_last", RNA_struct_ui_name(op->type->srna),
+ ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL);
#endif
- if (WM_operator_repeat_check(C, op)) {
- int layout_flags = 0;
- if (block->panel == NULL) {
- layout_flags = UI_TEMPLATE_OP_PROPS_SHOW_TITLE;
- }
+ if (WM_operator_repeat_check(C, op)) {
+ int layout_flags = 0;
+ if (block->panel == NULL) {
+ layout_flags = UI_TEMPLATE_OP_PROPS_SHOW_TITLE;
+ }
#if 0
- bool has_advanced = false;
+ bool has_advanced = false;
#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 */ );
- /* Warning! this leaves the handle function for any other users of this block. */
+ 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 */);
+ /* Warning! this leaves the handle function for any other users of this block. */
#if 0
- if (has_advanced) {
- uiItemO(layout, IFACE_("More..."), ICON_NONE, "SCREEN_OT_redo_last");
- }
+ if (has_advanced) {
+ uiItemO(layout, IFACE_("More..."), ICON_NONE, "SCREEN_OT_redo_last");
+ }
#endif
- }
+ }
}
/************************ Constraint Template *************************/
static void constraint_active_func(bContext *UNUSED(C), void *ob_v, void *con_v)
{
- ED_object_constraint_set_active(ob_v, con_v);
+ ED_object_constraint_set_active(ob_v, con_v);
}
/* draw panel showing settings for a constraint */
static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
{
- bPoseChannel *pchan = BKE_pose_channel_active(ob);
- const bConstraintTypeInfo *cti;
- uiBlock *block;
- uiLayout *result = NULL, *col, *box, *row;
- PointerRNA ptr;
- char typestr[32];
- short proxy_protected, xco = 0, yco = 0;
- // int rb_col; // UNUSED
-
- /* get constraint typeinfo */
- cti = BKE_constraint_typeinfo_get(con);
- if (cti == NULL) {
- /* exception for 'Null' constraint - it doesn't have constraint typeinfo! */
- BLI_strncpy(typestr, (con->type == CONSTRAINT_TYPE_NULL) ? IFACE_("Null") : IFACE_("Unknown"), sizeof(typestr));
- }
- else {
- BLI_strncpy(typestr, IFACE_(cti->name), sizeof(typestr));
- }
-
- /* determine whether constraint is proxy protected or not */
- if (BKE_constraints_proxylocked_owner(ob, pchan)) {
- proxy_protected = (con->flag & CONSTRAINT_PROXY_LOCAL) == 0;
- }
- else {
- proxy_protected = 0;
- }
-
- /* unless button has own callback, it adds this callback to button */
- block = uiLayoutGetBlock(layout);
- UI_block_func_set(block, constraint_active_func, ob, con);
-
- RNA_pointer_create(&ob->id, &RNA_Constraint, con, &ptr);
-
- col = uiLayoutColumn(layout, true);
- uiLayoutSetContextPointer(col, "constraint", &ptr);
-
- box = uiLayoutBox(col);
- row = uiLayoutRow(box, false);
- block = uiLayoutGetBlock(box);
-
- /* Draw constraint header */
-
- /* open/close */
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- uiItemR(row, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
- UI_block_emboss_set(block, UI_EMBOSS);
-
- /* name */
- uiDefBut(block, UI_BTYPE_LABEL, 0, typestr,
- xco + 0.5f * UI_UNIT_X, yco, 5 * UI_UNIT_X, 0.9f * UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "");
-
- if (con->flag & CONSTRAINT_DISABLE) {
- uiLayoutSetRedAlert(row, true);
- }
-
- if (proxy_protected == 0) {
- uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
- }
- else {
- uiItemL(row, con->name, ICON_NONE);
- }
-
- uiLayoutSetRedAlert(row, false);
-
- /* proxy-protected constraints cannot be edited, so hide up/down + close buttons */
- if (proxy_protected) {
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
- /* draw a ghost icon (for proxy) and also a lock beside it,
- * to show that constraint is "proxy locked" */
- uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_GHOST_ENABLED, xco + 12.2f * UI_UNIT_X, yco, 0.95f * UI_UNIT_X, 0.95f * UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected"));
- uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_LOCKED, xco + 13.1f * UI_UNIT_X, yco, 0.95f * UI_UNIT_X, 0.95f * UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected"));
-
- UI_block_emboss_set(block, UI_EMBOSS);
- }
- else {
- short prev_proxylock, show_upbut, show_downbut;
-
- /* Up/Down buttons:
- * Proxy-constraints are not allowed to occur after local (non-proxy) constraints
- * as that poses problems when restoring them, so disable the "up" button where
- * it may cause this situation.
- *
- * Up/Down buttons should only be shown (or not grayed - todo) if they serve some purpose.
- */
- if (BKE_constraints_proxylocked_owner(ob, pchan)) {
- if (con->prev) {
- prev_proxylock = (con->prev->flag & CONSTRAINT_PROXY_LOCAL) ? 0 : 1;
- }
- else {
- prev_proxylock = 0;
- }
- }
- else {
- prev_proxylock = 0;
- }
-
- show_upbut = ((prev_proxylock == 0) && (con->prev));
- show_downbut = (con->next) ? 1 : 0;
-
- /* enabled */
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- uiItemR(row, &ptr, "mute", 0, "",
- (con->flag & CONSTRAINT_OFF) ? ICON_HIDE_ON : ICON_HIDE_OFF);
- UI_block_emboss_set(block, UI_EMBOSS);
-
- uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
-
- /* up/down */
- if (show_upbut || show_downbut) {
- UI_block_align_begin(block);
- if (show_upbut) {
- uiItemO(row, "", ICON_TRIA_UP, "CONSTRAINT_OT_move_up");
- }
-
- if (show_downbut) {
- uiItemO(row, "", ICON_TRIA_DOWN, "CONSTRAINT_OT_move_down");
- }
- UI_block_align_end(block);
- }
-
- /* Close 'button' - emboss calls here disable drawing of 'button' behind X */
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- uiItemO(row, "", ICON_X, "CONSTRAINT_OT_delete");
- UI_block_emboss_set(block, UI_EMBOSS);
- }
-
- /* Set but-locks for protected settings (magic numbers are used here!) */
- if (proxy_protected) {
- UI_block_lock_set(block, true, IFACE_("Cannot edit Proxy-Protected Constraint"));
- }
-
- /* Draw constraint data */
- if ((con->flag & CONSTRAINT_EXPAND) == 0) {
- (yco) -= 10.5f * UI_UNIT_Y;
- }
- else {
- box = uiLayoutBox(col);
- block = uiLayoutAbsoluteBlock(box);
- result = box;
- }
-
- /* clear any locks set up for proxies/lib-linking */
- UI_block_lock_clear(block);
-
- return result;
+ bPoseChannel *pchan = BKE_pose_channel_active(ob);
+ const bConstraintTypeInfo *cti;
+ uiBlock *block;
+ uiLayout *result = NULL, *col, *box, *row;
+ PointerRNA ptr;
+ char typestr[32];
+ short proxy_protected, xco = 0, yco = 0;
+ // int rb_col; // UNUSED
+
+ /* get constraint typeinfo */
+ cti = BKE_constraint_typeinfo_get(con);
+ if (cti == NULL) {
+ /* exception for 'Null' constraint - it doesn't have constraint typeinfo! */
+ BLI_strncpy(typestr,
+ (con->type == CONSTRAINT_TYPE_NULL) ? IFACE_("Null") : IFACE_("Unknown"),
+ sizeof(typestr));
+ }
+ else {
+ BLI_strncpy(typestr, IFACE_(cti->name), sizeof(typestr));
+ }
+
+ /* determine whether constraint is proxy protected or not */
+ if (BKE_constraints_proxylocked_owner(ob, pchan)) {
+ proxy_protected = (con->flag & CONSTRAINT_PROXY_LOCAL) == 0;
+ }
+ else {
+ proxy_protected = 0;
+ }
+
+ /* unless button has own callback, it adds this callback to button */
+ block = uiLayoutGetBlock(layout);
+ UI_block_func_set(block, constraint_active_func, ob, con);
+
+ RNA_pointer_create(&ob->id, &RNA_Constraint, con, &ptr);
+
+ col = uiLayoutColumn(layout, true);
+ uiLayoutSetContextPointer(col, "constraint", &ptr);
+
+ box = uiLayoutBox(col);
+ row = uiLayoutRow(box, false);
+ block = uiLayoutGetBlock(box);
+
+ /* Draw constraint header */
+
+ /* open/close */
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ uiItemR(row, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ /* name */
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ typestr,
+ xco + 0.5f * UI_UNIT_X,
+ yco,
+ 5 * UI_UNIT_X,
+ 0.9f * UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ "");
+
+ if (con->flag & CONSTRAINT_DISABLE) {
+ uiLayoutSetRedAlert(row, true);
+ }
+
+ if (proxy_protected == 0) {
+ uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
+ }
+ else {
+ uiItemL(row, con->name, ICON_NONE);
+ }
+
+ uiLayoutSetRedAlert(row, false);
+
+ /* proxy-protected constraints cannot be edited, so hide up/down + close buttons */
+ if (proxy_protected) {
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+
+ /* draw a ghost icon (for proxy) and also a lock beside it,
+ * to show that constraint is "proxy locked" */
+ uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_GHOST_ENABLED,
+ xco + 12.2f * UI_UNIT_X,
+ yco,
+ 0.95f * UI_UNIT_X,
+ 0.95f * UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Proxy Protected"));
+ uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_LOCKED,
+ xco + 13.1f * UI_UNIT_X,
+ yco,
+ 0.95f * UI_UNIT_X,
+ 0.95f * UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Proxy Protected"));
+
+ UI_block_emboss_set(block, UI_EMBOSS);
+ }
+ else {
+ short prev_proxylock, show_upbut, show_downbut;
+
+ /* Up/Down buttons:
+ * Proxy-constraints are not allowed to occur after local (non-proxy) constraints
+ * as that poses problems when restoring them, so disable the "up" button where
+ * it may cause this situation.
+ *
+ * Up/Down buttons should only be shown (or not grayed - todo) if they serve some purpose.
+ */
+ if (BKE_constraints_proxylocked_owner(ob, pchan)) {
+ if (con->prev) {
+ prev_proxylock = (con->prev->flag & CONSTRAINT_PROXY_LOCAL) ? 0 : 1;
+ }
+ else {
+ prev_proxylock = 0;
+ }
+ }
+ else {
+ prev_proxylock = 0;
+ }
+
+ show_upbut = ((prev_proxylock == 0) && (con->prev));
+ show_downbut = (con->next) ? 1 : 0;
+
+ /* enabled */
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ uiItemR(row, &ptr, "mute", 0, "", (con->flag & CONSTRAINT_OFF) ? ICON_HIDE_ON : ICON_HIDE_OFF);
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
+
+ /* up/down */
+ if (show_upbut || show_downbut) {
+ UI_block_align_begin(block);
+ if (show_upbut) {
+ uiItemO(row, "", ICON_TRIA_UP, "CONSTRAINT_OT_move_up");
+ }
+
+ if (show_downbut) {
+ uiItemO(row, "", ICON_TRIA_DOWN, "CONSTRAINT_OT_move_down");
+ }
+ UI_block_align_end(block);
+ }
+
+ /* Close 'button' - emboss calls here disable drawing of 'button' behind X */
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ uiItemO(row, "", ICON_X, "CONSTRAINT_OT_delete");
+ UI_block_emboss_set(block, UI_EMBOSS);
+ }
+
+ /* Set but-locks for protected settings (magic numbers are used here!) */
+ if (proxy_protected) {
+ UI_block_lock_set(block, true, IFACE_("Cannot edit Proxy-Protected Constraint"));
+ }
+
+ /* Draw constraint data */
+ if ((con->flag & CONSTRAINT_EXPAND) == 0) {
+ (yco) -= 10.5f * UI_UNIT_Y;
+ }
+ else {
+ box = uiLayoutBox(col);
+ block = uiLayoutAbsoluteBlock(box);
+ result = box;
+ }
+
+ /* clear any locks set up for proxies/lib-linking */
+ UI_block_lock_clear(block);
+
+ return result;
}
uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr)
{
- Object *ob;
- bConstraint *con;
-
- /* verify we have valid data */
- if (!RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
- RNA_warning("Expected constraint on object");
- return NULL;
- }
-
- ob = ptr->id.data;
- con = ptr->data;
-
- if (!ob || !(GS(ob->id.name) == ID_OB)) {
- RNA_warning("Expected constraint on object");
- return NULL;
- }
-
- UI_block_lock_set(uiLayoutGetBlock(layout), (ob && ID_IS_LINKED(ob)), ERROR_LIBDATA_MESSAGE);
-
- /* hrms, the temporal constraint should not draw! */
- if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
- bKinematicConstraint *data = con->data;
- if (data->flag & CONSTRAINT_IK_TEMP) {
- return NULL;
- }
- }
-
- return draw_constraint(layout, ob, con);
+ Object *ob;
+ bConstraint *con;
+
+ /* verify we have valid data */
+ if (!RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
+ RNA_warning("Expected constraint on object");
+ return NULL;
+ }
+
+ ob = ptr->id.data;
+ con = ptr->data;
+
+ if (!ob || !(GS(ob->id.name) == ID_OB)) {
+ RNA_warning("Expected constraint on object");
+ return NULL;
+ }
+
+ UI_block_lock_set(uiLayoutGetBlock(layout), (ob && ID_IS_LINKED(ob)), ERROR_LIBDATA_MESSAGE);
+
+ /* hrms, the temporal constraint should not draw! */
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
+ bKinematicConstraint *data = con->data;
+ if (data->flag & CONSTRAINT_IK_TEMP) {
+ return NULL;
+ }
+ }
+
+ return draw_constraint(layout, ob, con);
}
-
/************************* Preview Template ***************************/
#include "DNA_light_types.h"
@@ -2144,465 +2619,687 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr)
static void do_preview_buttons(bContext *C, void *arg, int event)
{
- switch (event) {
- case B_MATPRV:
- WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, arg);
- break;
- }
+ switch (event) {
+ case B_MATPRV:
+ WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, arg);
+ break;
+ }
}
-void uiTemplatePreview(
- uiLayout *layout, bContext *C, ID *id, bool show_buttons, ID *parent, MTex *slot,
- const char *preview_id)
+void uiTemplatePreview(uiLayout *layout,
+ bContext *C,
+ ID *id,
+ bool show_buttons,
+ ID *parent,
+ MTex *slot,
+ const char *preview_id)
{
- uiLayout *row, *col;
- uiBlock *block;
- uiPreview *ui_preview = NULL;
- ARegion *ar;
-
- Material *ma = NULL;
- Tex *tex = (Tex *)id;
- ID *pid, *pparent;
- short *pr_texture = NULL;
- PointerRNA material_ptr;
- PointerRNA texture_ptr;
-
- char _preview_id[UI_MAX_NAME_STR];
-
- if (id && !ELEM(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA, ID_LS)) {
- RNA_warning("Expected ID of type material, texture, light, world or line style");
- return;
- }
-
- /* decide what to render */
- pid = id;
- pparent = NULL;
-
- if (id && (GS(id->name) == ID_TE)) {
- if (parent && (GS(parent->name) == ID_MA)) {
- pr_texture = &((Material *)parent)->pr_texture;
- }
- else if (parent && (GS(parent->name) == ID_WO)) {
- pr_texture = &((World *)parent)->pr_texture;
- }
- else if (parent && (GS(parent->name) == ID_LA)) {
- pr_texture = &((Light *)parent)->pr_texture;
- }
- else if (parent && (GS(parent->name) == ID_LS)) {
- pr_texture = &((FreestyleLineStyle *)parent)->pr_texture;
- }
-
- if (pr_texture) {
- if (*pr_texture == TEX_PR_OTHER) {
- pid = parent;
- }
- else if (*pr_texture == TEX_PR_BOTH) {
- pparent = parent;
- }
- }
- }
-
- 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)));
- 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));
-
- 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);
- }
-
- if (ui_preview->height < UI_UNIT_Y) {
- ui_preview->height = UI_UNIT_Y;
- }
- else if (ui_preview->height > UI_UNIT_Y * 50) { /* Rather high upper limit, yet not insane! */
- ui_preview->height = UI_UNIT_Y * 50;
- }
-
- /* layout */
- block = uiLayoutGetBlock(layout);
- row = uiLayoutRow(layout, false);
- col = uiLayoutColumn(row, false);
- uiLayoutSetKeepAspect(col, true);
-
- /* add preview */
- uiDefBut(block, UI_BTYPE_EXTRA, 0, "", 0, 0, UI_UNIT_X * 10, ui_preview->height, pid, 0.0, 0.0, 0, 0, "");
- UI_but_func_drawextra_set(block, ED_preview_draw, pparent, slot);
- UI_block_func_handle_set(block, do_preview_buttons, NULL);
-
- uiDefIconButS(
- block, UI_BTYPE_GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10, (short)(UI_UNIT_Y * 0.3f), &ui_preview->height,
- UI_UNIT_Y, UI_UNIT_Y * 50.0f, 0.0f, 0.0f, "");
-
- /* add buttons */
- if (pid && show_buttons) {
- if (GS(pid->name) == ID_MA || (pparent && GS(pparent->name) == ID_MA)) {
- if (GS(pid->name) == ID_MA) {
- ma = (Material *)pid;
- }
- else {
- ma = (Material *)pparent;
- }
-
- /* Create RNA Pointer */
- RNA_pointer_create(&ma->id, &RNA_Material, ma, &material_ptr);
-
- col = uiLayoutColumn(row, true);
- uiLayoutSetScaleX(col, 1.5);
- uiItemR(col, &material_ptr, "preview_render_type", UI_ITEM_R_EXPAND, "", ICON_NONE);
- uiItemS(col);
- uiItemR(col, &material_ptr, "use_preview_world", 0, "", ICON_WORLD);
- }
-
- if (pr_texture) {
- /* Create RNA Pointer */
- RNA_pointer_create(id, &RNA_Texture, tex, &texture_ptr);
-
- uiLayoutRow(layout, true);
- uiDefButS(block, UI_BTYPE_ROW, B_MATPRV, IFACE_("Texture"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
- pr_texture, 10, TEX_PR_TEXTURE, 0, 0, "");
- if (GS(parent->name) == ID_MA) {
- uiDefButS(block, UI_BTYPE_ROW, B_MATPRV, IFACE_("Material"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
- pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
- }
- else if (GS(parent->name) == ID_LA) {
- uiDefButS(block, UI_BTYPE_ROW, B_MATPRV, CTX_IFACE_(BLT_I18NCONTEXT_ID_LIGHT, "Light"),
- 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
- pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
- }
- else if (GS(parent->name) == ID_WO) {
- uiDefButS(block, UI_BTYPE_ROW, B_MATPRV, IFACE_("World"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
- pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
- }
- else if (GS(parent->name) == ID_LS) {
- uiDefButS(block, UI_BTYPE_ROW, B_MATPRV, IFACE_("Line Style"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
- pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
- }
- uiDefButS(block, UI_BTYPE_ROW, B_MATPRV, IFACE_("Both"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
- pr_texture, 10, TEX_PR_BOTH, 0, 0, "");
-
- /* Alpha button for texture preview */
- if (*pr_texture != TEX_PR_OTHER) {
- row = uiLayoutRow(layout, false);
- uiItemR(row, &texture_ptr, "use_preview_alpha", 0, NULL, ICON_NONE);
- }
- }
- }
+ uiLayout *row, *col;
+ uiBlock *block;
+ uiPreview *ui_preview = NULL;
+ ARegion *ar;
+
+ Material *ma = NULL;
+ Tex *tex = (Tex *)id;
+ ID *pid, *pparent;
+ short *pr_texture = NULL;
+ PointerRNA material_ptr;
+ PointerRNA texture_ptr;
+
+ char _preview_id[UI_MAX_NAME_STR];
+
+ if (id && !ELEM(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA, ID_LS)) {
+ RNA_warning("Expected ID of type material, texture, light, world or line style");
+ return;
+ }
+
+ /* decide what to render */
+ pid = id;
+ pparent = NULL;
+
+ if (id && (GS(id->name) == ID_TE)) {
+ if (parent && (GS(parent->name) == ID_MA)) {
+ pr_texture = &((Material *)parent)->pr_texture;
+ }
+ else if (parent && (GS(parent->name) == ID_WO)) {
+ pr_texture = &((World *)parent)->pr_texture;
+ }
+ else if (parent && (GS(parent->name) == ID_LA)) {
+ pr_texture = &((Light *)parent)->pr_texture;
+ }
+ else if (parent && (GS(parent->name) == ID_LS)) {
+ pr_texture = &((FreestyleLineStyle *)parent)->pr_texture;
+ }
+
+ if (pr_texture) {
+ if (*pr_texture == TEX_PR_OTHER) {
+ pid = parent;
+ }
+ else if (*pr_texture == TEX_PR_BOTH) {
+ pparent = parent;
+ }
+ }
+ }
+
+ 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)));
+ 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));
+
+ 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);
+ }
+
+ if (ui_preview->height < UI_UNIT_Y) {
+ ui_preview->height = UI_UNIT_Y;
+ }
+ else if (ui_preview->height > UI_UNIT_Y * 50) { /* Rather high upper limit, yet not insane! */
+ ui_preview->height = UI_UNIT_Y * 50;
+ }
+
+ /* layout */
+ block = uiLayoutGetBlock(layout);
+ row = uiLayoutRow(layout, false);
+ col = uiLayoutColumn(row, false);
+ uiLayoutSetKeepAspect(col, true);
+
+ /* add preview */
+ uiDefBut(block,
+ UI_BTYPE_EXTRA,
+ 0,
+ "",
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ ui_preview->height,
+ pid,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ UI_but_func_drawextra_set(block, ED_preview_draw, pparent, slot);
+ UI_block_func_handle_set(block, do_preview_buttons, NULL);
+
+ uiDefIconButS(block,
+ UI_BTYPE_GRIP,
+ 0,
+ ICON_GRIP,
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ (short)(UI_UNIT_Y * 0.3f),
+ &ui_preview->height,
+ UI_UNIT_Y,
+ UI_UNIT_Y * 50.0f,
+ 0.0f,
+ 0.0f,
+ "");
+
+ /* add buttons */
+ if (pid && show_buttons) {
+ if (GS(pid->name) == ID_MA || (pparent && GS(pparent->name) == ID_MA)) {
+ if (GS(pid->name) == ID_MA) {
+ ma = (Material *)pid;
+ }
+ else {
+ ma = (Material *)pparent;
+ }
+
+ /* Create RNA Pointer */
+ RNA_pointer_create(&ma->id, &RNA_Material, ma, &material_ptr);
+
+ col = uiLayoutColumn(row, true);
+ uiLayoutSetScaleX(col, 1.5);
+ uiItemR(col, &material_ptr, "preview_render_type", UI_ITEM_R_EXPAND, "", ICON_NONE);
+ uiItemS(col);
+ uiItemR(col, &material_ptr, "use_preview_world", 0, "", ICON_WORLD);
+ }
+
+ if (pr_texture) {
+ /* Create RNA Pointer */
+ RNA_pointer_create(id, &RNA_Texture, tex, &texture_ptr);
+
+ uiLayoutRow(layout, true);
+ uiDefButS(block,
+ UI_BTYPE_ROW,
+ B_MATPRV,
+ IFACE_("Texture"),
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ UI_UNIT_Y,
+ pr_texture,
+ 10,
+ TEX_PR_TEXTURE,
+ 0,
+ 0,
+ "");
+ if (GS(parent->name) == ID_MA) {
+ uiDefButS(block,
+ UI_BTYPE_ROW,
+ B_MATPRV,
+ IFACE_("Material"),
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ UI_UNIT_Y,
+ pr_texture,
+ 10,
+ TEX_PR_OTHER,
+ 0,
+ 0,
+ "");
+ }
+ else if (GS(parent->name) == ID_LA) {
+ uiDefButS(block,
+ UI_BTYPE_ROW,
+ B_MATPRV,
+ CTX_IFACE_(BLT_I18NCONTEXT_ID_LIGHT, "Light"),
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ UI_UNIT_Y,
+ pr_texture,
+ 10,
+ TEX_PR_OTHER,
+ 0,
+ 0,
+ "");
+ }
+ else if (GS(parent->name) == ID_WO) {
+ uiDefButS(block,
+ UI_BTYPE_ROW,
+ B_MATPRV,
+ IFACE_("World"),
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ UI_UNIT_Y,
+ pr_texture,
+ 10,
+ TEX_PR_OTHER,
+ 0,
+ 0,
+ "");
+ }
+ else if (GS(parent->name) == ID_LS) {
+ uiDefButS(block,
+ UI_BTYPE_ROW,
+ B_MATPRV,
+ IFACE_("Line Style"),
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ UI_UNIT_Y,
+ pr_texture,
+ 10,
+ TEX_PR_OTHER,
+ 0,
+ 0,
+ "");
+ }
+ uiDefButS(block,
+ UI_BTYPE_ROW,
+ B_MATPRV,
+ IFACE_("Both"),
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ UI_UNIT_Y,
+ pr_texture,
+ 10,
+ TEX_PR_BOTH,
+ 0,
+ 0,
+ "");
+
+ /* Alpha button for texture preview */
+ if (*pr_texture != TEX_PR_OTHER) {
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, &texture_ptr, "use_preview_alpha", 0, NULL, ICON_NONE);
+ }
+ }
+ }
}
/********************** ColorRamp Template **************************/
-
typedef struct RNAUpdateCb {
- PointerRNA ptr;
- PropertyRNA *prop;
+ PointerRNA ptr;
+ PropertyRNA *prop;
} RNAUpdateCb;
static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
{
- RNAUpdateCb *cb = (RNAUpdateCb *)arg_cb;
+ RNAUpdateCb *cb = (RNAUpdateCb *)arg_cb;
- /* we call update here on the pointer property, this way the
- * owner of the curve mapping can still define it's own update
- * and notifier, even if the CurveMapping struct is shared. */
- RNA_property_update(C, &cb->ptr, cb->prop);
+ /* we call update here on the pointer property, this way the
+ * owner of the curve mapping can still define it's own update
+ * and notifier, even if the CurveMapping struct is shared. */
+ RNA_property_update(C, &cb->ptr, cb->prop);
}
enum {
- CB_FUNC_FLIP,
- CB_FUNC_DISTRIBUTE_LR,
- CB_FUNC_DISTRIBUTE_EVENLY,
- CB_FUNC_RESET,
+ CB_FUNC_FLIP,
+ CB_FUNC_DISTRIBUTE_LR,
+ CB_FUNC_DISTRIBUTE_EVENLY,
+ CB_FUNC_RESET,
};
static void colorband_flip_cb(bContext *C, ColorBand *coba)
{
- CBData data_tmp[MAXCOLORBAND];
+ CBData data_tmp[MAXCOLORBAND];
- int a;
+ int a;
- for (a = 0; a < coba->tot; a++) {
- data_tmp[a] = coba->data[coba->tot - (a + 1)];
- }
- for (a = 0; a < coba->tot; a++) {
- data_tmp[a].pos = 1.0f - data_tmp[a].pos;
- coba->data[a] = data_tmp[a];
- }
+ for (a = 0; a < coba->tot; a++) {
+ data_tmp[a] = coba->data[coba->tot - (a + 1)];
+ }
+ for (a = 0; a < coba->tot; a++) {
+ data_tmp[a].pos = 1.0f - data_tmp[a].pos;
+ coba->data[a] = data_tmp[a];
+ }
- /* may as well flip the cur*/
- coba->cur = coba->tot - (coba->cur + 1);
+ /* may as well flip the cur*/
+ coba->cur = coba->tot - (coba->cur + 1);
- ED_undo_push(C, "Flip Color Ramp");
+ ED_undo_push(C, "Flip Color Ramp");
}
static void colorband_distribute_cb(bContext *C, ColorBand *coba, bool evenly)
{
- if (coba->tot > 1) {
- int a;
- int tot = evenly ? coba->tot - 1 : coba->tot;
- float gap = 1.0f / tot;
- float pos = 0.0f;
- for (a = 0; a < coba->tot; a++) {
- coba->data[a].pos = pos;
- pos += gap;
- }
- ED_undo_push(C, evenly ? "Distribute Stops Evenly" : "Distribute Stops from Left");
- }
+ if (coba->tot > 1) {
+ int a;
+ int tot = evenly ? coba->tot - 1 : coba->tot;
+ float gap = 1.0f / tot;
+ float pos = 0.0f;
+ for (a = 0; a < coba->tot; a++) {
+ coba->data[a].pos = pos;
+ pos += gap;
+ }
+ ED_undo_push(C, evenly ? "Distribute Stops Evenly" : "Distribute Stops from Left");
+ }
}
static void colorband_tools_dofunc(bContext *C, void *coba_v, int event)
{
- ColorBand *coba = coba_v;
-
- switch (event) {
- case CB_FUNC_FLIP:
- colorband_flip_cb(C, coba);
- break;
- case CB_FUNC_DISTRIBUTE_LR:
- colorband_distribute_cb(C, coba, false);
- break;
- case CB_FUNC_DISTRIBUTE_EVENLY:
- colorband_distribute_cb(C, coba, true);
- break;
- case CB_FUNC_RESET:
- BKE_colorband_init(coba, true);
- ED_undo_push(C, "Reset Color Ramp");
- break;
- }
- ED_region_tag_redraw(CTX_wm_region(C));
+ ColorBand *coba = coba_v;
+
+ switch (event) {
+ case CB_FUNC_FLIP:
+ colorband_flip_cb(C, coba);
+ break;
+ case CB_FUNC_DISTRIBUTE_LR:
+ colorband_distribute_cb(C, coba, false);
+ break;
+ case CB_FUNC_DISTRIBUTE_EVENLY:
+ colorband_distribute_cb(C, coba, true);
+ break;
+ case CB_FUNC_RESET:
+ BKE_colorband_init(coba, true);
+ ED_undo_push(C, "Reset Color Ramp");
+ break;
+ }
+ 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 *ar, void *coba_v)
{
- 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);
- UI_block_func_butmenu_set(block, colorband_tools_dofunc, coba);
-
- uiLayout *layout = UI_block_layout(
- block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, UI_MENU_WIDTH_MIN, 0, UI_MENU_PADDING, style);
- UI_block_layout_set_current(block, layout);
- {
- PointerRNA coba_ptr;
- RNA_pointer_create(NULL, &RNA_ColorRamp, coba, &coba_ptr);
- uiLayoutSetContextPointer(layout, "color_ramp", &coba_ptr);
- }
-
- /* We could move these to operators,
- * although this isn't important unless we want to assign key shortcuts to them. */
- {
- uiDefIconTextBut(
- block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1,
- IFACE_("Flip Color Ramp"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0, CB_FUNC_FLIP, "");
- uiDefIconTextBut(
- block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1,
- IFACE_("Distribute Stops from Left"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0, CB_FUNC_DISTRIBUTE_LR, "");
- uiDefIconTextBut(
- block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1,
- IFACE_("Distribute Stops Evenly"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0, CB_FUNC_DISTRIBUTE_EVENLY, "");
-
- uiItemO(layout, IFACE_("Eyedropper"), ICON_EYEDROPPER, "UI_OT_eyedropper_colorramp");
-
- uiDefIconTextBut(
- block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Reset Color Ramp"),
- 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, CB_FUNC_RESET, "");
- }
-
- UI_block_direction_set(block, UI_DIR_DOWN);
- UI_block_bounds_set_text(block, 3.0f * UI_UNIT_X);
-
- return block;
+ 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);
+ UI_block_func_butmenu_set(block, colorband_tools_dofunc, coba);
+
+ uiLayout *layout = UI_block_layout(block,
+ UI_LAYOUT_VERTICAL,
+ UI_LAYOUT_MENU,
+ 0,
+ 0,
+ UI_MENU_WIDTH_MIN,
+ 0,
+ UI_MENU_PADDING,
+ style);
+ UI_block_layout_set_current(block, layout);
+ {
+ PointerRNA coba_ptr;
+ RNA_pointer_create(NULL, &RNA_ColorRamp, coba, &coba_ptr);
+ uiLayoutSetContextPointer(layout, "color_ramp", &coba_ptr);
+ }
+
+ /* We could move these to operators,
+ * although this isn't important unless we want to assign key shortcuts to them. */
+ {
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT_MENU,
+ 1,
+ ICON_BLANK1,
+ IFACE_("Flip Color Ramp"),
+ 0,
+ yco -= UI_UNIT_Y,
+ menuwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ CB_FUNC_FLIP,
+ "");
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT_MENU,
+ 1,
+ ICON_BLANK1,
+ IFACE_("Distribute Stops from Left"),
+ 0,
+ yco -= UI_UNIT_Y,
+ menuwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ CB_FUNC_DISTRIBUTE_LR,
+ "");
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT_MENU,
+ 1,
+ ICON_BLANK1,
+ IFACE_("Distribute Stops Evenly"),
+ 0,
+ yco -= UI_UNIT_Y,
+ menuwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ CB_FUNC_DISTRIBUTE_EVENLY,
+ "");
+
+ uiItemO(layout, IFACE_("Eyedropper"), ICON_EYEDROPPER, "UI_OT_eyedropper_colorramp");
+
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT_MENU,
+ 1,
+ ICON_BLANK1,
+ IFACE_("Reset Color Ramp"),
+ 0,
+ yco -= UI_UNIT_Y,
+ menuwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ CB_FUNC_RESET,
+ "");
+ }
+
+ UI_block_direction_set(block, UI_DIR_DOWN);
+ UI_block_bounds_set_text(block, 3.0f * UI_UNIT_X);
+
+ return block;
}
static void colorband_add_cb(bContext *C, void *cb_v, void *coba_v)
{
- ColorBand *coba = coba_v;
- float pos = 0.5f;
-
- if (coba->tot > 1) {
- if (coba->cur > 0) {
- pos = (coba->data[coba->cur - 1].pos + coba->data[coba->cur].pos) * 0.5f;
- }
- else {
- pos = (coba->data[coba->cur + 1].pos + coba->data[coba->cur].pos) * 0.5f;
- }
- }
-
- if (BKE_colorband_element_add(coba, pos)) {
- rna_update_cb(C, cb_v, NULL);
- ED_undo_push(C, "Add Color Ramp Stop");
- }
+ ColorBand *coba = coba_v;
+ float pos = 0.5f;
+
+ if (coba->tot > 1) {
+ if (coba->cur > 0) {
+ pos = (coba->data[coba->cur - 1].pos + coba->data[coba->cur].pos) * 0.5f;
+ }
+ else {
+ pos = (coba->data[coba->cur + 1].pos + coba->data[coba->cur].pos) * 0.5f;
+ }
+ }
+
+ if (BKE_colorband_element_add(coba, pos)) {
+ rna_update_cb(C, cb_v, NULL);
+ ED_undo_push(C, "Add Color Ramp Stop");
+ }
}
static void colorband_del_cb(bContext *C, void *cb_v, void *coba_v)
{
- ColorBand *coba = coba_v;
+ ColorBand *coba = coba_v;
- if (BKE_colorband_element_remove(coba, coba->cur)) {
- ED_undo_push(C, "Delete Color Ramp Stop");
- rna_update_cb(C, cb_v, NULL);
- }
+ if (BKE_colorband_element_remove(coba, coba->cur)) {
+ ED_undo_push(C, "Delete Color Ramp Stop");
+ rna_update_cb(C, cb_v, NULL);
+ }
}
static void colorband_update_cb(bContext *UNUSED(C), void *bt_v, void *coba_v)
{
- uiBut *bt = bt_v;
- ColorBand *coba = coba_v;
+ uiBut *bt = bt_v;
+ ColorBand *coba = coba_v;
- /* sneaky update here, we need to sort the colorband points to be in order,
- * however the RNA pointer then is wrong, so we update it */
- BKE_colorband_update_sort(coba);
- bt->rnapoin.data = coba->data + coba->cur;
+ /* sneaky update here, we need to sort the colorband points to be in order,
+ * however the RNA pointer then is wrong, so we update it */
+ BKE_colorband_update_sort(coba);
+ bt->rnapoin.data = coba->data + coba->cur;
}
-static void colorband_buttons_layout(
- uiLayout *layout, uiBlock *block, ColorBand *coba, const rctf *butr,
- RNAUpdateCb *cb, int expand)
+static void colorband_buttons_layout(uiLayout *layout,
+ uiBlock *block,
+ ColorBand *coba,
+ const rctf *butr,
+ RNAUpdateCb *cb,
+ int expand)
{
- uiLayout *row, *split, *subsplit;
- uiBut *bt;
- float unit = BLI_rctf_size_x(butr) / 14.0f;
- float xs = butr->xmin;
- float ys = butr->ymin;
- PointerRNA ptr;
-
- RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRamp, coba, &ptr);
-
- split = uiLayoutSplit(layout, 0.4f, false);
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- UI_block_align_begin(block);
- row = uiLayoutRow(split, false);
-
- bt = uiDefIconTextBut(
- block, UI_BTYPE_BUT, 0, ICON_ADD, "", 0, 0, 2.0f * unit, UI_UNIT_Y, NULL,
- 0, 0, 0, 0, TIP_("Add a new color stop to the color ramp"));
- UI_but_funcN_set(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
-
- bt = uiDefIconTextBut(
- block, UI_BTYPE_BUT, 0, ICON_REMOVE, "", xs + 2.0f * unit, ys + UI_UNIT_Y, 2.0f * unit, UI_UNIT_Y,
- NULL, 0, 0, 0, 0, TIP_("Delete the active position"));
- UI_but_funcN_set(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
-
- bt = uiDefIconBlockBut(
- block, colorband_tools_func, coba, 0, ICON_DOWNARROW_HLT,
- xs + 4.0f * unit, ys + UI_UNIT_Y, 2.0f * unit, UI_UNIT_Y, TIP_("Tools"));
- UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), coba);
-
- UI_block_align_end(block);
- UI_block_emboss_set(block, UI_EMBOSS);
-
- row = uiLayoutRow(split, false);
-
- UI_block_align_begin(block);
- uiItemR(row, &ptr, "color_mode", 0, "", ICON_NONE);
- if (ELEM(coba->color_mode, COLBAND_BLEND_HSV, COLBAND_BLEND_HSL)) {
- uiItemR(row, &ptr, "hue_interpolation", 0, "", ICON_NONE);
- }
- else { /* COLBAND_BLEND_RGB */
- uiItemR(row, &ptr, "interpolation", 0, "", ICON_NONE);
- }
- UI_block_align_end(block);
-
- row = uiLayoutRow(layout, false);
-
- bt = uiDefBut(block, UI_BTYPE_COLORBAND, 0, "", xs, ys, BLI_rctf_size_x(butr), UI_UNIT_Y, coba, 0, 0, 0, 0, "");
- UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
-
- row = uiLayoutRow(layout, false);
-
- if (coba->tot) {
- CBData *cbd = coba->data + coba->cur;
-
- RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
-
- if (!expand) {
- split = uiLayoutSplit(layout, 0.3f, false);
-
- row = uiLayoutRow(split, false);
- uiDefButS(block, UI_BTYPE_NUM, 0, "", 0, 0, 5.0f * UI_UNIT_X, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot - 1)),
- 0, 0, TIP_("Choose active color stop"));
- row = uiLayoutRow(split, false);
- uiItemR(row, &ptr, "position", 0, IFACE_("Pos"), ICON_NONE);
- bt = block->buttons.last;
- bt->a1 = 1.0f; /* gives a bit more precision for modifying position */
- UI_but_func_set(bt, colorband_update_cb, bt, coba);
-
- row = uiLayoutRow(layout, false);
- uiItemR(row, &ptr, "color", 0, "", ICON_NONE);
- bt = block->buttons.last;
- UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
- }
- else {
- split = uiLayoutSplit(layout, 0.5f, false);
- subsplit = uiLayoutSplit(split, 0.35f, false);
-
- row = uiLayoutRow(subsplit, false);
- uiDefButS(block, UI_BTYPE_NUM, 0, "", 0, 0, 5.0f * UI_UNIT_X, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot - 1)),
- 0, 0, TIP_("Choose active color stop"));
- row = uiLayoutRow(subsplit, false);
- uiItemR(row, &ptr, "position", UI_ITEM_R_SLIDER, IFACE_("Pos"), ICON_NONE);
- bt = block->buttons.last;
- bt->a1 = 1.0f; /* gives a bit more precision for modifying position */
- UI_but_func_set(bt, colorband_update_cb, bt, coba);
-
- row = uiLayoutRow(split, false);
- uiItemR(row, &ptr, "color", 0, "", ICON_NONE);
- bt = block->buttons.last;
- UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
- }
- }
+ uiLayout *row, *split, *subsplit;
+ uiBut *bt;
+ float unit = BLI_rctf_size_x(butr) / 14.0f;
+ float xs = butr->xmin;
+ float ys = butr->ymin;
+ PointerRNA ptr;
+
+ RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRamp, coba, &ptr);
+
+ split = uiLayoutSplit(layout, 0.4f, false);
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ UI_block_align_begin(block);
+ row = uiLayoutRow(split, false);
+
+ bt = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_ADD,
+ "",
+ 0,
+ 0,
+ 2.0f * unit,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Add a new color stop to the color ramp"));
+ UI_but_funcN_set(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
+
+ bt = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_REMOVE,
+ "",
+ xs + 2.0f * unit,
+ ys + UI_UNIT_Y,
+ 2.0f * unit,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Delete the active position"));
+ UI_but_funcN_set(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
+
+ bt = uiDefIconBlockBut(block,
+ colorband_tools_func,
+ coba,
+ 0,
+ ICON_DOWNARROW_HLT,
+ xs + 4.0f * unit,
+ ys + UI_UNIT_Y,
+ 2.0f * unit,
+ UI_UNIT_Y,
+ TIP_("Tools"));
+ UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), coba);
+
+ UI_block_align_end(block);
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ row = uiLayoutRow(split, false);
+
+ UI_block_align_begin(block);
+ uiItemR(row, &ptr, "color_mode", 0, "", ICON_NONE);
+ if (ELEM(coba->color_mode, COLBAND_BLEND_HSV, COLBAND_BLEND_HSL)) {
+ uiItemR(row, &ptr, "hue_interpolation", 0, "", ICON_NONE);
+ }
+ else { /* COLBAND_BLEND_RGB */
+ uiItemR(row, &ptr, "interpolation", 0, "", ICON_NONE);
+ }
+ UI_block_align_end(block);
+
+ row = uiLayoutRow(layout, false);
+
+ bt = uiDefBut(block,
+ UI_BTYPE_COLORBAND,
+ 0,
+ "",
+ xs,
+ ys,
+ BLI_rctf_size_x(butr),
+ UI_UNIT_Y,
+ coba,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+
+ row = uiLayoutRow(layout, false);
+
+ if (coba->tot) {
+ CBData *cbd = coba->data + coba->cur;
+
+ RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
+
+ if (!expand) {
+ split = uiLayoutSplit(layout, 0.3f, false);
+
+ row = uiLayoutRow(split, false);
+ uiDefButS(block,
+ UI_BTYPE_NUM,
+ 0,
+ "",
+ 0,
+ 0,
+ 5.0f * UI_UNIT_X,
+ UI_UNIT_Y,
+ &coba->cur,
+ 0.0,
+ (float)(MAX2(0, coba->tot - 1)),
+ 0,
+ 0,
+ TIP_("Choose active color stop"));
+ row = uiLayoutRow(split, false);
+ uiItemR(row, &ptr, "position", 0, IFACE_("Pos"), ICON_NONE);
+ bt = block->buttons.last;
+ bt->a1 = 1.0f; /* gives a bit more precision for modifying position */
+ UI_but_func_set(bt, colorband_update_cb, bt, coba);
+
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, &ptr, "color", 0, "", ICON_NONE);
+ bt = block->buttons.last;
+ UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+ }
+ else {
+ split = uiLayoutSplit(layout, 0.5f, false);
+ subsplit = uiLayoutSplit(split, 0.35f, false);
+
+ row = uiLayoutRow(subsplit, false);
+ uiDefButS(block,
+ UI_BTYPE_NUM,
+ 0,
+ "",
+ 0,
+ 0,
+ 5.0f * UI_UNIT_X,
+ UI_UNIT_Y,
+ &coba->cur,
+ 0.0,
+ (float)(MAX2(0, coba->tot - 1)),
+ 0,
+ 0,
+ TIP_("Choose active color stop"));
+ row = uiLayoutRow(subsplit, false);
+ uiItemR(row, &ptr, "position", UI_ITEM_R_SLIDER, IFACE_("Pos"), ICON_NONE);
+ bt = block->buttons.last;
+ bt->a1 = 1.0f; /* gives a bit more precision for modifying position */
+ UI_but_func_set(bt, colorband_update_cb, bt, coba);
+
+ row = uiLayoutRow(split, false);
+ uiItemR(row, &ptr, "color", 0, "", ICON_NONE);
+ bt = block->buttons.last;
+ UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+ }
+ }
}
void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname, bool expand)
{
- PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
- PointerRNA cptr;
- RNAUpdateCb *cb;
- uiBlock *block;
- ID *id;
- rctf rect;
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ PointerRNA cptr;
+ RNAUpdateCb *cb;
+ uiBlock *block;
+ ID *id;
+ rctf rect;
- if (!prop || RNA_property_type(prop) != PROP_POINTER) {
- return;
- }
+ if (!prop || RNA_property_type(prop) != PROP_POINTER) {
+ return;
+ }
- cptr = RNA_property_pointer_get(ptr, prop);
- if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_ColorRamp)) {
- return;
- }
+ cptr = RNA_property_pointer_get(ptr, prop);
+ if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_ColorRamp)) {
+ return;
+ }
- cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
- cb->ptr = *ptr;
- cb->prop = prop;
+ cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
+ cb->ptr = *ptr;
+ cb->prop = prop;
- rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X;
- rect.ymin = 0; rect.ymax = 19.5f * UI_UNIT_X;
+ rect.xmin = 0;
+ rect.xmax = 10.0f * UI_UNIT_X;
+ rect.ymin = 0;
+ rect.ymax = 19.5f * UI_UNIT_X;
- block = uiLayoutAbsoluteBlock(layout);
+ block = uiLayoutAbsoluteBlock(layout);
- id = cptr.id.data;
- UI_block_lock_set(block, (id && ID_IS_LINKED(id)), ERROR_LIBDATA_MESSAGE);
+ id = cptr.id.data;
+ UI_block_lock_set(block, (id && ID_IS_LINKED(id)), ERROR_LIBDATA_MESSAGE);
- colorband_buttons_layout(layout, block, cptr.data, &rect, cb, expand);
+ colorband_buttons_layout(layout, block, cptr.data, &rect, cb, expand);
- UI_block_lock_clear(block);
+ UI_block_lock_clear(block);
- MEM_freeN(cb);
+ MEM_freeN(cb);
}
/********************* Icon Template ************************/
@@ -2611,2549 +3308,3420 @@ void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname
*/
void uiTemplateIcon(uiLayout *layout, int icon_value, float icon_scale)
{
- uiBlock *block;
- uiBut *but;
-
- block = uiLayoutAbsoluteBlock(layout);
- but = uiDefIconBut(block, UI_BTYPE_LABEL, 0, ICON_X, 0, 0, UI_UNIT_X * icon_scale, UI_UNIT_Y * icon_scale, NULL, 0.0, 0.0, 0.0, 0.0, "");
- ui_def_but_icon(but, icon_value, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
+ uiBlock *block;
+ uiBut *but;
+
+ block = uiLayoutAbsoluteBlock(layout);
+ but = uiDefIconBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ ICON_X,
+ 0,
+ 0,
+ UI_UNIT_X * icon_scale,
+ UI_UNIT_Y * icon_scale,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ "");
+ ui_def_but_icon(but, icon_value, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
}
/********************* Icon viewer Template ************************/
typedef struct IconViewMenuArgs {
- PointerRNA ptr;
- PropertyRNA *prop;
- bool show_labels;
- float icon_scale;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ bool show_labels;
+ float icon_scale;
} IconViewMenuArgs;
/* ID Search browse menu, open */
static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *ar, void *arg_litem)
{
- static IconViewMenuArgs args;
- uiBlock *block;
- uiBut *but;
- int icon, value;
- const EnumPropertyItem *item;
- int a;
- bool free;
- int w, h;
-
- /* arg_litem is malloced, can be freed by parent button */
- args = *((IconViewMenuArgs *) 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);
- UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_NO_FLIP);
- UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
-
- RNA_property_enum_items(C, &args.ptr, args.prop, &item, NULL, &free);
-
- for (a = 0; item[a].identifier; a++) {
- int x, y;
-
- x = (a % 8) * w;
- y = -(a / 8) * h;
-
- icon = item[a].icon;
- value = item[a].value;
- if (args.show_labels) {
- but = uiDefIconTextButR_prop(
- block, UI_BTYPE_ROW, 0, icon, item[a].name, x, y, w, h,
- &args.ptr, args.prop, -1, 0, value, -1, -1, NULL);
- }
- else {
- but = uiDefIconButR_prop(
- block, UI_BTYPE_ROW, 0, icon, x, y, w, h,
- &args.ptr, args.prop, -1, 0, value, -1, -1, NULL);
- }
- ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
- }
-
- UI_block_bounds_set_normal(block, 0.3f * U.widget_unit);
- UI_block_direction_set(block, UI_DIR_DOWN);
-
- if (free) {
- MEM_freeN((void *)item);
- }
-
- return block;
+ static IconViewMenuArgs args;
+ uiBlock *block;
+ uiBut *but;
+ int icon, value;
+ const EnumPropertyItem *item;
+ int a;
+ bool free;
+ int w, h;
+
+ /* arg_litem is malloced, can be freed by parent button */
+ args = *((IconViewMenuArgs *)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);
+ UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_NO_FLIP);
+ UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
+
+ RNA_property_enum_items(C, &args.ptr, args.prop, &item, NULL, &free);
+
+ for (a = 0; item[a].identifier; a++) {
+ int x, y;
+
+ x = (a % 8) * w;
+ y = -(a / 8) * h;
+
+ icon = item[a].icon;
+ value = item[a].value;
+ if (args.show_labels) {
+ but = uiDefIconTextButR_prop(block,
+ UI_BTYPE_ROW,
+ 0,
+ icon,
+ item[a].name,
+ x,
+ y,
+ w,
+ h,
+ &args.ptr,
+ args.prop,
+ -1,
+ 0,
+ value,
+ -1,
+ -1,
+ NULL);
+ }
+ else {
+ but = uiDefIconButR_prop(block,
+ UI_BTYPE_ROW,
+ 0,
+ icon,
+ x,
+ y,
+ w,
+ h,
+ &args.ptr,
+ args.prop,
+ -1,
+ 0,
+ value,
+ -1,
+ -1,
+ NULL);
+ }
+ ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
+ }
+
+ UI_block_bounds_set_normal(block, 0.3f * U.widget_unit);
+ UI_block_direction_set(block, UI_DIR_DOWN);
+
+ if (free) {
+ MEM_freeN((void *)item);
+ }
+
+ return block;
}
/**
* \param icon_scale: Scale of the icon, 1x == button height.
*/
-void uiTemplateIconView(
- uiLayout *layout, PointerRNA *ptr, const char *propname, bool show_labels,
- float icon_scale, float icon_scale_popup)
+void uiTemplateIconView(uiLayout *layout,
+ PointerRNA *ptr,
+ const char *propname,
+ bool show_labels,
+ float icon_scale,
+ float icon_scale_popup)
{
- PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
- IconViewMenuArgs *cb_args;
- const EnumPropertyItem *items;
- uiBlock *block;
- uiBut *but;
- int value, icon = ICON_NONE, tot_items;
- bool free_items;
-
- if (!prop || RNA_property_type(prop) != PROP_ENUM) {
- RNA_warning("property of type Enum not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- block = uiLayoutAbsoluteBlock(layout);
-
- RNA_property_enum_items(block->evil_C, ptr, prop, &items, &tot_items, &free_items);
- value = RNA_property_enum_get(ptr, prop);
- RNA_enum_icon_from_value(items, value, &icon);
-
-
- if (RNA_property_editable(ptr, prop)) {
- cb_args = MEM_callocN(sizeof(IconViewMenuArgs), __func__);
- cb_args->ptr = *ptr;
- cb_args->prop = prop;
- cb_args->show_labels = show_labels;
- cb_args->icon_scale = icon_scale_popup;
-
- but = uiDefBlockButN(
- block, ui_icon_view_menu_cb, cb_args, "",
- 0, 0, UI_UNIT_X * icon_scale, UI_UNIT_Y * icon_scale, "");
- }
- else {
- but = uiDefIconBut(
- block, UI_BTYPE_LABEL, 0, ICON_X,
- 0, 0, UI_UNIT_X * icon_scale, UI_UNIT_Y * icon_scale, NULL, 0.0, 0.0, 0.0, 0.0, "");
- }
-
-
- ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
-
- if (free_items) {
- MEM_freeN((void *)items);
- }
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ IconViewMenuArgs *cb_args;
+ const EnumPropertyItem *items;
+ uiBlock *block;
+ uiBut *but;
+ int value, icon = ICON_NONE, tot_items;
+ bool free_items;
+
+ if (!prop || RNA_property_type(prop) != PROP_ENUM) {
+ RNA_warning(
+ "property of type Enum not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ block = uiLayoutAbsoluteBlock(layout);
+
+ RNA_property_enum_items(block->evil_C, ptr, prop, &items, &tot_items, &free_items);
+ value = RNA_property_enum_get(ptr, prop);
+ RNA_enum_icon_from_value(items, value, &icon);
+
+ if (RNA_property_editable(ptr, prop)) {
+ cb_args = MEM_callocN(sizeof(IconViewMenuArgs), __func__);
+ cb_args->ptr = *ptr;
+ cb_args->prop = prop;
+ cb_args->show_labels = show_labels;
+ cb_args->icon_scale = icon_scale_popup;
+
+ but = uiDefBlockButN(block,
+ ui_icon_view_menu_cb,
+ cb_args,
+ "",
+ 0,
+ 0,
+ UI_UNIT_X * icon_scale,
+ UI_UNIT_Y * icon_scale,
+ "");
+ }
+ else {
+ but = uiDefIconBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ ICON_X,
+ 0,
+ 0,
+ UI_UNIT_X * icon_scale,
+ UI_UNIT_Y * icon_scale,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ "");
+ }
+
+ ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
+
+ if (free_items) {
+ MEM_freeN((void *)items);
+ }
}
/********************* Histogram Template ************************/
void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname)
{
- PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
- PointerRNA cptr;
- uiBlock *block;
- uiLayout *col;
- Histogram *hist;
-
- if (!prop || RNA_property_type(prop) != PROP_POINTER) {
- return;
- }
-
- cptr = RNA_property_pointer_get(ptr, prop);
- if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Histogram)) {
- return;
- }
- hist = (Histogram *)cptr.data;
-
- if (hist->height < UI_UNIT_Y) {
- hist->height = UI_UNIT_Y;
- }
- else if (hist->height > UI_UNIT_Y * 20) {
- hist->height = UI_UNIT_Y * 20;
- }
-
- col = uiLayoutColumn(layout, true);
- block = uiLayoutGetBlock(col);
-
- uiDefBut(block, UI_BTYPE_HISTOGRAM, 0, "", 0, 0, UI_UNIT_X * 10, hist->height, hist, 0, 0, 0, 0, "");
-
- /* Resize grip. */
- uiDefIconButI(block, UI_BTYPE_GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10, (short)(UI_UNIT_Y * 0.3f), &hist->height,
- UI_UNIT_Y, UI_UNIT_Y * 20.0f, 0.0f, 0.0f, "");
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ PointerRNA cptr;
+ uiBlock *block;
+ uiLayout *col;
+ Histogram *hist;
+
+ if (!prop || RNA_property_type(prop) != PROP_POINTER) {
+ return;
+ }
+
+ cptr = RNA_property_pointer_get(ptr, prop);
+ if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Histogram)) {
+ return;
+ }
+ hist = (Histogram *)cptr.data;
+
+ if (hist->height < UI_UNIT_Y) {
+ hist->height = UI_UNIT_Y;
+ }
+ else if (hist->height > UI_UNIT_Y * 20) {
+ hist->height = UI_UNIT_Y * 20;
+ }
+
+ col = uiLayoutColumn(layout, true);
+ block = uiLayoutGetBlock(col);
+
+ uiDefBut(
+ block, UI_BTYPE_HISTOGRAM, 0, "", 0, 0, UI_UNIT_X * 10, hist->height, hist, 0, 0, 0, 0, "");
+
+ /* Resize grip. */
+ uiDefIconButI(block,
+ UI_BTYPE_GRIP,
+ 0,
+ ICON_GRIP,
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ (short)(UI_UNIT_Y * 0.3f),
+ &hist->height,
+ UI_UNIT_Y,
+ UI_UNIT_Y * 20.0f,
+ 0.0f,
+ 0.0f,
+ "");
}
/********************* Waveform Template ************************/
void uiTemplateWaveform(uiLayout *layout, PointerRNA *ptr, const char *propname)
{
- PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
- PointerRNA cptr;
- uiBlock *block;
- uiLayout *col;
- Scopes *scopes;
-
- if (!prop || RNA_property_type(prop) != PROP_POINTER) {
- return;
- }
-
- cptr = RNA_property_pointer_get(ptr, prop);
- if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes)) {
- return;
- }
- scopes = (Scopes *)cptr.data;
-
- col = uiLayoutColumn(layout, true);
- block = uiLayoutGetBlock(col);
-
- if (scopes->wavefrm_height < UI_UNIT_Y) {
- scopes->wavefrm_height = UI_UNIT_Y;
- }
- else if (scopes->wavefrm_height > UI_UNIT_Y * 20) {
- scopes->wavefrm_height = UI_UNIT_Y * 20;
- }
-
- uiDefBut(block, UI_BTYPE_WAVEFORM, 0, "", 0, 0, UI_UNIT_X * 10, scopes->wavefrm_height, scopes, 0, 0, 0, 0, "");
-
- /* Resize grip. */
- uiDefIconButI(block, UI_BTYPE_GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10, (short)(UI_UNIT_Y * 0.3f), &scopes->wavefrm_height,
- UI_UNIT_Y, UI_UNIT_Y * 20.0f, 0.0f, 0.0f, "");
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ PointerRNA cptr;
+ uiBlock *block;
+ uiLayout *col;
+ Scopes *scopes;
+
+ if (!prop || RNA_property_type(prop) != PROP_POINTER) {
+ return;
+ }
+
+ cptr = RNA_property_pointer_get(ptr, prop);
+ if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes)) {
+ return;
+ }
+ scopes = (Scopes *)cptr.data;
+
+ col = uiLayoutColumn(layout, true);
+ block = uiLayoutGetBlock(col);
+
+ if (scopes->wavefrm_height < UI_UNIT_Y) {
+ scopes->wavefrm_height = UI_UNIT_Y;
+ }
+ else if (scopes->wavefrm_height > UI_UNIT_Y * 20) {
+ scopes->wavefrm_height = UI_UNIT_Y * 20;
+ }
+
+ uiDefBut(block,
+ UI_BTYPE_WAVEFORM,
+ 0,
+ "",
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ scopes->wavefrm_height,
+ scopes,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+
+ /* Resize grip. */
+ uiDefIconButI(block,
+ UI_BTYPE_GRIP,
+ 0,
+ ICON_GRIP,
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ (short)(UI_UNIT_Y * 0.3f),
+ &scopes->wavefrm_height,
+ UI_UNIT_Y,
+ UI_UNIT_Y * 20.0f,
+ 0.0f,
+ 0.0f,
+ "");
}
/********************* Vectorscope Template ************************/
void uiTemplateVectorscope(uiLayout *layout, PointerRNA *ptr, const char *propname)
{
- PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
- PointerRNA cptr;
- uiBlock *block;
- uiLayout *col;
- Scopes *scopes;
-
- if (!prop || RNA_property_type(prop) != PROP_POINTER) {
- return;
- }
-
- cptr = RNA_property_pointer_get(ptr, prop);
- if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes)) {
- return;
- }
- scopes = (Scopes *)cptr.data;
-
- if (scopes->vecscope_height < UI_UNIT_Y) {
- scopes->vecscope_height = UI_UNIT_Y;
- }
- else if (scopes->vecscope_height > UI_UNIT_Y * 20) {
- scopes->vecscope_height = UI_UNIT_Y * 20;
- }
-
- col = uiLayoutColumn(layout, true);
- block = uiLayoutGetBlock(col);
-
- uiDefBut(block, UI_BTYPE_VECTORSCOPE, 0, "", 0, 0, UI_UNIT_X * 10, scopes->vecscope_height, scopes, 0, 0, 0, 0, "");
-
- /* Resize grip. */
- uiDefIconButI(block, UI_BTYPE_GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10, (short)(UI_UNIT_Y * 0.3f), &scopes->vecscope_height,
- UI_UNIT_Y, UI_UNIT_Y * 20.0f, 0.0f, 0.0f, "");
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ PointerRNA cptr;
+ uiBlock *block;
+ uiLayout *col;
+ Scopes *scopes;
+
+ if (!prop || RNA_property_type(prop) != PROP_POINTER) {
+ return;
+ }
+
+ cptr = RNA_property_pointer_get(ptr, prop);
+ if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes)) {
+ return;
+ }
+ scopes = (Scopes *)cptr.data;
+
+ if (scopes->vecscope_height < UI_UNIT_Y) {
+ scopes->vecscope_height = UI_UNIT_Y;
+ }
+ else if (scopes->vecscope_height > UI_UNIT_Y * 20) {
+ scopes->vecscope_height = UI_UNIT_Y * 20;
+ }
+
+ col = uiLayoutColumn(layout, true);
+ block = uiLayoutGetBlock(col);
+
+ uiDefBut(block,
+ UI_BTYPE_VECTORSCOPE,
+ 0,
+ "",
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ scopes->vecscope_height,
+ scopes,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+
+ /* Resize grip. */
+ uiDefIconButI(block,
+ UI_BTYPE_GRIP,
+ 0,
+ ICON_GRIP,
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ (short)(UI_UNIT_Y * 0.3f),
+ &scopes->vecscope_height,
+ UI_UNIT_Y,
+ UI_UNIT_Y * 20.0f,
+ 0.0f,
+ 0.0f,
+ "");
}
/********************* CurveMapping Template ************************/
-
static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *UNUSED(arg))
{
- CurveMapping *cumap = cumap_v;
- float d;
-
- /* we allow 20 times zoom */
- if (BLI_rctf_size_x(&cumap->curr) > 0.04f * BLI_rctf_size_x(&cumap->clipr)) {
- d = 0.1154f * BLI_rctf_size_x(&cumap->curr);
- cumap->curr.xmin += d;
- cumap->curr.xmax -= d;
- d = 0.1154f * BLI_rctf_size_y(&cumap->curr);
- cumap->curr.ymin += d;
- cumap->curr.ymax -= d;
- }
-
- ED_region_tag_redraw(CTX_wm_region(C));
+ CurveMapping *cumap = cumap_v;
+ float d;
+
+ /* we allow 20 times zoom */
+ if (BLI_rctf_size_x(&cumap->curr) > 0.04f * BLI_rctf_size_x(&cumap->clipr)) {
+ d = 0.1154f * BLI_rctf_size_x(&cumap->curr);
+ cumap->curr.xmin += d;
+ cumap->curr.xmax -= d;
+ d = 0.1154f * BLI_rctf_size_y(&cumap->curr);
+ cumap->curr.ymin += d;
+ cumap->curr.ymax -= d;
+ }
+
+ ED_region_tag_redraw(CTX_wm_region(C));
}
static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *UNUSED(unused))
{
- CurveMapping *cumap = cumap_v;
- float d, d1;
-
- /* we allow 20 times zoom, but don't view outside clip */
- if (BLI_rctf_size_x(&cumap->curr) < 20.0f * BLI_rctf_size_x(&cumap->clipr)) {
- d = d1 = 0.15f * BLI_rctf_size_x(&cumap->curr);
-
- if (cumap->flag & CUMA_DO_CLIP) {
- if (cumap->curr.xmin - d < cumap->clipr.xmin) {
- d1 = cumap->curr.xmin - cumap->clipr.xmin;
- }
- }
- cumap->curr.xmin -= d1;
-
- d1 = d;
- if (cumap->flag & CUMA_DO_CLIP) {
- if (cumap->curr.xmax + d > cumap->clipr.xmax) {
- d1 = -cumap->curr.xmax + cumap->clipr.xmax;
- }
- }
- cumap->curr.xmax += d1;
-
- d = d1 = 0.15f * BLI_rctf_size_y(&cumap->curr);
-
- if (cumap->flag & CUMA_DO_CLIP) {
- if (cumap->curr.ymin - d < cumap->clipr.ymin) {
- d1 = cumap->curr.ymin - cumap->clipr.ymin;
- }
- }
- cumap->curr.ymin -= d1;
-
- d1 = d;
- if (cumap->flag & CUMA_DO_CLIP) {
- if (cumap->curr.ymax + d > cumap->clipr.ymax) {
- d1 = -cumap->curr.ymax + cumap->clipr.ymax;
- }
- }
- cumap->curr.ymax += d1;
- }
-
- ED_region_tag_redraw(CTX_wm_region(C));
+ CurveMapping *cumap = cumap_v;
+ float d, d1;
+
+ /* we allow 20 times zoom, but don't view outside clip */
+ if (BLI_rctf_size_x(&cumap->curr) < 20.0f * BLI_rctf_size_x(&cumap->clipr)) {
+ d = d1 = 0.15f * BLI_rctf_size_x(&cumap->curr);
+
+ if (cumap->flag & CUMA_DO_CLIP) {
+ if (cumap->curr.xmin - d < cumap->clipr.xmin) {
+ d1 = cumap->curr.xmin - cumap->clipr.xmin;
+ }
+ }
+ cumap->curr.xmin -= d1;
+
+ d1 = d;
+ if (cumap->flag & CUMA_DO_CLIP) {
+ if (cumap->curr.xmax + d > cumap->clipr.xmax) {
+ d1 = -cumap->curr.xmax + cumap->clipr.xmax;
+ }
+ }
+ cumap->curr.xmax += d1;
+
+ d = d1 = 0.15f * BLI_rctf_size_y(&cumap->curr);
+
+ if (cumap->flag & CUMA_DO_CLIP) {
+ if (cumap->curr.ymin - d < cumap->clipr.ymin) {
+ d1 = cumap->curr.ymin - cumap->clipr.ymin;
+ }
+ }
+ cumap->curr.ymin -= d1;
+
+ d1 = d;
+ if (cumap->flag & CUMA_DO_CLIP) {
+ if (cumap->curr.ymax + d > cumap->clipr.ymax) {
+ d1 = -cumap->curr.ymax + cumap->clipr.ymax;
+ }
+ }
+ cumap->curr.ymax += d1;
+ }
+
+ ED_region_tag_redraw(CTX_wm_region(C));
}
static void curvemap_buttons_setclip(bContext *UNUSED(C), void *cumap_v, void *UNUSED(arg))
{
- CurveMapping *cumap = cumap_v;
+ CurveMapping *cumap = cumap_v;
- curvemapping_changed(cumap, false);
+ curvemapping_changed(cumap, false);
}
static void curvemap_buttons_delete(bContext *C, void *cb_v, void *cumap_v)
{
- CurveMapping *cumap = cumap_v;
+ CurveMapping *cumap = cumap_v;
- curvemap_remove(cumap->cm + cumap->cur, SELECT);
- curvemapping_changed(cumap, false);
+ curvemap_remove(cumap->cm + cumap->cur, SELECT);
+ curvemapping_changed(cumap, false);
- rna_update_cb(C, cb_v, NULL);
+ rna_update_cb(C, cb_v, NULL);
}
/* 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)
{
- CurveMapping *cumap = cumap_v;
- uiBlock *block;
- uiBut *bt;
- float width = 8 * UI_UNIT_X;
-
- block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
-
- /* use this for a fake extra empty space around the buttons */
- uiDefBut(block, UI_BTYPE_LABEL, 0, "", -4, 16, width + 8, 6 * UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
-
- bt = uiDefButBitI(
- block, UI_BTYPE_TOGGLE, CUMA_DO_CLIP, 1, IFACE_("Use Clipping"),
- 0, 5 * UI_UNIT_Y, width, UI_UNIT_Y, &cumap->flag, 0.0, 0.0, 10, 0, "");
- UI_but_func_set(bt, curvemap_buttons_setclip, cumap, NULL);
-
- UI_block_align_begin(block);
- uiDefButF(block, UI_BTYPE_NUM, 0, IFACE_("Min X "), 0, 4 * UI_UNIT_Y, width, UI_UNIT_Y,
- &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 2, "");
- uiDefButF(block, UI_BTYPE_NUM, 0, IFACE_("Min Y "), 0, 3 * UI_UNIT_Y, width, UI_UNIT_Y,
- &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 2, "");
- uiDefButF(block, UI_BTYPE_NUM, 0, IFACE_("Max X "), 0, 2 * UI_UNIT_Y, width, UI_UNIT_Y,
- &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 2, "");
- uiDefButF(block, UI_BTYPE_NUM, 0, IFACE_("Max Y "), 0, UI_UNIT_Y, width, UI_UNIT_Y,
- &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 2, "");
-
- UI_block_direction_set(block, UI_DIR_RIGHT);
-
- return block;
+ CurveMapping *cumap = cumap_v;
+ uiBlock *block;
+ uiBut *bt;
+ float width = 8 * UI_UNIT_X;
+
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+
+ /* use this for a fake extra empty space around the buttons */
+ uiDefBut(block, UI_BTYPE_LABEL, 0, "", -4, 16, width + 8, 6 * UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+
+ bt = uiDefButBitI(block,
+ UI_BTYPE_TOGGLE,
+ CUMA_DO_CLIP,
+ 1,
+ IFACE_("Use Clipping"),
+ 0,
+ 5 * UI_UNIT_Y,
+ width,
+ UI_UNIT_Y,
+ &cumap->flag,
+ 0.0,
+ 0.0,
+ 10,
+ 0,
+ "");
+ UI_but_func_set(bt, curvemap_buttons_setclip, cumap, NULL);
+
+ UI_block_align_begin(block);
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ 0,
+ IFACE_("Min X "),
+ 0,
+ 4 * UI_UNIT_Y,
+ width,
+ UI_UNIT_Y,
+ &cumap->clipr.xmin,
+ -100.0,
+ cumap->clipr.xmax,
+ 10,
+ 2,
+ "");
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ 0,
+ IFACE_("Min Y "),
+ 0,
+ 3 * UI_UNIT_Y,
+ width,
+ UI_UNIT_Y,
+ &cumap->clipr.ymin,
+ -100.0,
+ cumap->clipr.ymax,
+ 10,
+ 2,
+ "");
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ 0,
+ IFACE_("Max X "),
+ 0,
+ 2 * UI_UNIT_Y,
+ width,
+ UI_UNIT_Y,
+ &cumap->clipr.xmax,
+ cumap->clipr.xmin,
+ 100.0,
+ 10,
+ 2,
+ "");
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ 0,
+ IFACE_("Max Y "),
+ 0,
+ UI_UNIT_Y,
+ width,
+ UI_UNIT_Y,
+ &cumap->clipr.ymax,
+ cumap->clipr.ymin,
+ 100.0,
+ 10,
+ 2,
+ "");
+
+ UI_block_direction_set(block, UI_DIR_RIGHT);
+
+ return block;
}
/* only for curvemap_tools_dofunc */
enum {
- UICURVE_FUNC_RESET_NEG,
- UICURVE_FUNC_RESET_POS,
- UICURVE_FUNC_RESET_VIEW,
- UICURVE_FUNC_HANDLE_VECTOR,
- UICURVE_FUNC_HANDLE_AUTO,
- UICURVE_FUNC_HANDLE_AUTO_ANIM,
- UICURVE_FUNC_EXTEND_HOZ,
- UICURVE_FUNC_EXTEND_EXP,
+ UICURVE_FUNC_RESET_NEG,
+ UICURVE_FUNC_RESET_POS,
+ UICURVE_FUNC_RESET_VIEW,
+ UICURVE_FUNC_HANDLE_VECTOR,
+ UICURVE_FUNC_HANDLE_AUTO,
+ UICURVE_FUNC_HANDLE_AUTO_ANIM,
+ UICURVE_FUNC_EXTEND_HOZ,
+ UICURVE_FUNC_EXTEND_EXP,
};
static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event)
{
- CurveMapping *cumap = cumap_v;
- CurveMap *cuma = cumap->cm + cumap->cur;
-
- switch (event) {
- case UICURVE_FUNC_RESET_NEG:
- case UICURVE_FUNC_RESET_POS: /* reset */
- curvemap_reset(cuma, &cumap->clipr, cumap->preset,
- (event == UICURVE_FUNC_RESET_NEG) ? CURVEMAP_SLOPE_NEGATIVE : CURVEMAP_SLOPE_POSITIVE);
- curvemapping_changed(cumap, false);
- break;
- case UICURVE_FUNC_RESET_VIEW:
- cumap->curr = cumap->clipr;
- break;
- case UICURVE_FUNC_HANDLE_VECTOR: /* set vector */
- curvemap_handle_set(cuma, HD_VECT);
- curvemapping_changed(cumap, false);
- break;
- case UICURVE_FUNC_HANDLE_AUTO: /* set auto */
- curvemap_handle_set(cuma, HD_AUTO);
- curvemapping_changed(cumap, false);
- break;
- case UICURVE_FUNC_HANDLE_AUTO_ANIM: /* set auto-clamped */
- curvemap_handle_set(cuma, HD_AUTO_ANIM);
- curvemapping_changed(cumap, false);
- break;
- case UICURVE_FUNC_EXTEND_HOZ: /* extend horiz */
- cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
- curvemapping_changed(cumap, false);
- break;
- case UICURVE_FUNC_EXTEND_EXP: /* extend extrapolate */
- cuma->flag |= CUMA_EXTEND_EXTRAPOLATE;
- curvemapping_changed(cumap, false);
- break;
- }
- ED_undo_push(C, "CurveMap tools");
- ED_region_tag_redraw(CTX_wm_region(C));
+ CurveMapping *cumap = cumap_v;
+ CurveMap *cuma = cumap->cm + cumap->cur;
+
+ switch (event) {
+ case UICURVE_FUNC_RESET_NEG:
+ case UICURVE_FUNC_RESET_POS: /* reset */
+ curvemap_reset(cuma,
+ &cumap->clipr,
+ cumap->preset,
+ (event == UICURVE_FUNC_RESET_NEG) ? CURVEMAP_SLOPE_NEGATIVE :
+ CURVEMAP_SLOPE_POSITIVE);
+ curvemapping_changed(cumap, false);
+ break;
+ case UICURVE_FUNC_RESET_VIEW:
+ cumap->curr = cumap->clipr;
+ break;
+ case UICURVE_FUNC_HANDLE_VECTOR: /* set vector */
+ curvemap_handle_set(cuma, HD_VECT);
+ curvemapping_changed(cumap, false);
+ break;
+ case UICURVE_FUNC_HANDLE_AUTO: /* set auto */
+ curvemap_handle_set(cuma, HD_AUTO);
+ curvemapping_changed(cumap, false);
+ break;
+ case UICURVE_FUNC_HANDLE_AUTO_ANIM: /* set auto-clamped */
+ curvemap_handle_set(cuma, HD_AUTO_ANIM);
+ curvemapping_changed(cumap, false);
+ break;
+ case UICURVE_FUNC_EXTEND_HOZ: /* extend horiz */
+ cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
+ curvemapping_changed(cumap, false);
+ break;
+ case UICURVE_FUNC_EXTEND_EXP: /* extend extrapolate */
+ cuma->flag |= CUMA_EXTEND_EXTRAPOLATE;
+ curvemapping_changed(cumap, false);
+ break;
+ }
+ ED_undo_push(C, "CurveMap tools");
+ ED_region_tag_redraw(CTX_wm_region(C));
}
static uiBlock *curvemap_tools_func(
- bContext *C, ARegion *ar, CurveMapping *cumap,
- bool show_extend, int reset_mode)
+ bContext *C, ARegion *ar, 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);
- UI_block_func_butmenu_set(block, curvemap_tools_dofunc, cumap);
-
- {
- uiDefIconTextBut(
- block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Reset View"),
- 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_RESET_VIEW, "");
- uiDefIconTextBut(
- block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Vector Handle"),
- 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_HANDLE_VECTOR, "");
- uiDefIconTextBut(
- block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Auto Handle"),
- 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_HANDLE_AUTO, "");
- uiDefIconTextBut(
- block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Auto Clamped Handle"),
- 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_HANDLE_AUTO_ANIM, "");
- }
-
- if (show_extend) {
- uiDefIconTextBut(
- block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Extend Horizontal"),
- 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_EXTEND_HOZ, "");
- uiDefIconTextBut(
- block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Extend Extrapolated"),
- 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_EXTEND_EXP, "");
- }
-
- {
- uiDefIconTextBut(
- block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Reset Curve"),
- 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, reset_mode, "");
- }
-
- UI_block_direction_set(block, UI_DIR_DOWN);
- UI_block_bounds_set_text(block, 3.0f * UI_UNIT_X);
-
- return block;
+ uiBlock *block;
+ short yco = 0, menuwidth = 10 * UI_UNIT_X;
+
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ UI_block_func_butmenu_set(block, curvemap_tools_dofunc, cumap);
+
+ {
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT_MENU,
+ 1,
+ ICON_BLANK1,
+ IFACE_("Reset View"),
+ 0,
+ yco -= UI_UNIT_Y,
+ menuwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ UICURVE_FUNC_RESET_VIEW,
+ "");
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT_MENU,
+ 1,
+ ICON_BLANK1,
+ IFACE_("Vector Handle"),
+ 0,
+ yco -= UI_UNIT_Y,
+ menuwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ UICURVE_FUNC_HANDLE_VECTOR,
+ "");
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT_MENU,
+ 1,
+ ICON_BLANK1,
+ IFACE_("Auto Handle"),
+ 0,
+ yco -= UI_UNIT_Y,
+ menuwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ UICURVE_FUNC_HANDLE_AUTO,
+ "");
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT_MENU,
+ 1,
+ ICON_BLANK1,
+ IFACE_("Auto Clamped Handle"),
+ 0,
+ yco -= UI_UNIT_Y,
+ menuwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ UICURVE_FUNC_HANDLE_AUTO_ANIM,
+ "");
+ }
+
+ if (show_extend) {
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT_MENU,
+ 1,
+ ICON_BLANK1,
+ IFACE_("Extend Horizontal"),
+ 0,
+ yco -= UI_UNIT_Y,
+ menuwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ UICURVE_FUNC_EXTEND_HOZ,
+ "");
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT_MENU,
+ 1,
+ ICON_BLANK1,
+ IFACE_("Extend Extrapolated"),
+ 0,
+ yco -= UI_UNIT_Y,
+ menuwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ UICURVE_FUNC_EXTEND_EXP,
+ "");
+ }
+
+ {
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT_MENU,
+ 1,
+ ICON_BLANK1,
+ IFACE_("Reset Curve"),
+ 0,
+ yco -= UI_UNIT_Y,
+ menuwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ reset_mode,
+ "");
+ }
+
+ UI_block_direction_set(block, UI_DIR_DOWN);
+ UI_block_bounds_set_text(block, 3.0f * UI_UNIT_X);
+
+ return block;
}
static uiBlock *curvemap_tools_posslope_func(bContext *C, ARegion *ar, void *cumap_v)
{
- return curvemap_tools_func(C, ar, cumap_v, true, UICURVE_FUNC_RESET_POS);
+ return curvemap_tools_func(C, ar, cumap_v, true, UICURVE_FUNC_RESET_POS);
}
static uiBlock *curvemap_tools_negslope_func(bContext *C, ARegion *ar, void *cumap_v)
{
- return curvemap_tools_func(C, ar, cumap_v, true, UICURVE_FUNC_RESET_NEG);
+ return curvemap_tools_func(C, ar, cumap_v, true, UICURVE_FUNC_RESET_NEG);
}
static uiBlock *curvemap_brush_tools_func(bContext *C, ARegion *ar, void *cumap_v)
{
- return curvemap_tools_func(C, ar, cumap_v, false, UICURVE_FUNC_RESET_NEG);
+ return curvemap_tools_func(C, ar, cumap_v, false, UICURVE_FUNC_RESET_NEG);
}
static void curvemap_buttons_redraw(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
{
- ED_region_tag_redraw(CTX_wm_region(C));
+ ED_region_tag_redraw(CTX_wm_region(C));
}
static void curvemap_buttons_update(bContext *C, void *arg1_v, void *cumap_v)
{
- CurveMapping *cumap = cumap_v;
- curvemapping_changed(cumap, true);
- rna_update_cb(C, arg1_v, NULL);
+ CurveMapping *cumap = cumap_v;
+ curvemapping_changed(cumap, true);
+ rna_update_cb(C, arg1_v, NULL);
}
static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v)
{
- CurveMapping *cumap = cumap_v;
- int a;
+ CurveMapping *cumap = cumap_v;
+ int a;
- cumap->preset = CURVE_PRESET_LINE;
- for (a = 0; a < CM_TOT; a++) {
- curvemap_reset(cumap->cm + a, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE);
- }
+ cumap->preset = CURVE_PRESET_LINE;
+ for (a = 0; a < CM_TOT; a++) {
+ curvemap_reset(cumap->cm + a, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE);
+ }
- cumap->black[0] = cumap->black[1] = cumap->black[2] = 0.0f;
- cumap->white[0] = cumap->white[1] = cumap->white[2] = 1.0f;
- curvemapping_set_black_white(cumap, NULL, NULL);
+ cumap->black[0] = cumap->black[1] = cumap->black[2] = 0.0f;
+ cumap->white[0] = cumap->white[1] = cumap->white[2] = 1.0f;
+ curvemapping_set_black_white(cumap, NULL, NULL);
- curvemapping_changed(cumap, false);
+ curvemapping_changed(cumap, false);
- rna_update_cb(C, cb_v, NULL);
+ rna_update_cb(C, cb_v, NULL);
}
/* still unsure how this call evolves...
* we use labeltype for defining what curve-channels to show */
-static void curvemap_buttons_layout(
- uiLayout *layout, PointerRNA *ptr, char labeltype, bool levels,
- bool brush, bool neg_slope, bool tone, RNAUpdateCb *cb)
+static void curvemap_buttons_layout(uiLayout *layout,
+ PointerRNA *ptr,
+ char labeltype,
+ bool levels,
+ bool brush,
+ bool neg_slope,
+ bool tone,
+ RNAUpdateCb *cb)
{
- CurveMapping *cumap = ptr->data;
- CurveMap *cm = &cumap->cm[cumap->cur];
- CurveMapPoint *cmp = NULL;
- uiLayout *row, *sub, *split;
- uiBlock *block;
- uiBut *bt;
- float dx = UI_UNIT_X;
- int icon, size;
- int bg = -1, i;
-
- block = uiLayoutGetBlock(layout);
-
- if (tone) {
- split = uiLayoutSplit(layout, 0.0f, false);
- uiItemR(uiLayoutRow(split, false), ptr, "tone", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
- }
-
- /* curve chooser */
- row = uiLayoutRow(layout, false);
-
- if (labeltype == 'v') {
- /* vector */
- sub = uiLayoutRow(row, true);
- uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
-
- if (cumap->cm[0].curve) {
- bt = uiDefButI(block, UI_BTYPE_ROW, 0, "X", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
- UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
- }
- if (cumap->cm[1].curve) {
- bt = uiDefButI(block, UI_BTYPE_ROW, 0, "Y", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
- UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
- }
- if (cumap->cm[2].curve) {
- bt = uiDefButI(block, UI_BTYPE_ROW, 0, "Z", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
- UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
- }
- }
- else if (labeltype == 'c') {
- /* color */
- sub = uiLayoutRow(row, true);
- uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
-
- if (cumap->cm[3].curve) {
- bt = uiDefButI(block, UI_BTYPE_ROW, 0, "C", 0, 0, dx, dx, &cumap->cur, 0.0, 3.0, 0.0, 0.0, "");
- UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
- }
- if (cumap->cm[0].curve) {
- bt = uiDefButI(block, UI_BTYPE_ROW, 0, "R", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
- UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
- }
- if (cumap->cm[1].curve) {
- bt = uiDefButI(block, UI_BTYPE_ROW, 0, "G", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
- UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
- }
- if (cumap->cm[2].curve) {
- bt = uiDefButI(block, UI_BTYPE_ROW, 0, "B", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
- UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
- }
- }
- else if (labeltype == 'h') {
- /* HSV */
- sub = uiLayoutRow(row, true);
- uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
-
- if (cumap->cm[0].curve) {
- bt = uiDefButI(block, UI_BTYPE_ROW, 0, "H", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
- UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
- }
- if (cumap->cm[1].curve) {
- bt = uiDefButI(block, UI_BTYPE_ROW, 0, "S", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
- UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
- }
- if (cumap->cm[2].curve) {
- bt = uiDefButI(block, UI_BTYPE_ROW, 0, "V", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
- UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
- }
- }
- else {
- uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
- }
-
- if (labeltype == 'h') {
- bg = UI_GRAD_H;
- }
-
- /* operation buttons */
- sub = uiLayoutRow(row, true);
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
- bt = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_ZOOM_IN, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Zoom in"));
- UI_but_func_set(bt, curvemap_buttons_zoom_in, cumap, NULL);
-
- bt = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_ZOOM_OUT, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Zoom out"));
- UI_but_func_set(bt, curvemap_buttons_zoom_out, cumap, NULL);
-
- if (brush) {
- bt = uiDefIconBlockBut(block, curvemap_brush_tools_func, cumap, 0, ICON_DOWNARROW_HLT, 0, 0, dx, dx, TIP_("Tools"));
- }
- else if (neg_slope) {
- bt = uiDefIconBlockBut(
- block, curvemap_tools_negslope_func, cumap, 0, ICON_DOWNARROW_HLT,
- 0, 0, dx, dx, TIP_("Tools"));
- }
- else {
- bt = uiDefIconBlockBut(
- block, curvemap_tools_posslope_func, cumap, 0, ICON_DOWNARROW_HLT,
- 0, 0, dx, dx, TIP_("Tools"));
- }
-
- UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
-
- icon = (cumap->flag & CUMA_DO_CLIP) ? ICON_CLIPUV_HLT : ICON_CLIPUV_DEHLT;
- bt = uiDefIconBlockBut(block, curvemap_clipping_func, cumap, 0, icon, 0, 0, dx, dx, TIP_("Clipping Options"));
- UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
-
- bt = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_X, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Delete points"));
- UI_but_funcN_set(bt, curvemap_buttons_delete, MEM_dupallocN(cb), cumap);
-
- UI_block_emboss_set(block, UI_EMBOSS);
-
- UI_block_funcN_set(block, rna_update_cb, MEM_dupallocN(cb), NULL);
-
- /* curve itself */
- size = uiLayoutGetWidth(layout);
- row = uiLayoutRow(layout, false);
- uiDefBut(block, UI_BTYPE_CURVE, 0, "", 0, 0, size, 8.0f * UI_UNIT_X, cumap, 0.0f, 1.0f, bg, 0, "");
-
- /* sliders for selected point */
- for (i = 0; i < cm->totpoint; i++) {
- if (cm->curve[i].flag & CUMA_SELECT) {
- cmp = &cm->curve[i];
- break;
- }
- }
-
- if (cmp) {
- rctf bounds;
-
- if (cumap->flag & CUMA_DO_CLIP) {
- bounds = cumap->clipr;
- }
- else {
- bounds.xmin = bounds.ymin = -1000.0;
- bounds.xmax = bounds.ymax = 1000.0;
- }
-
- uiLayoutRow(layout, true);
- UI_block_funcN_set(block, curvemap_buttons_update, MEM_dupallocN(cb), cumap);
- uiDefButF(block, UI_BTYPE_NUM, 0, "X", 0, 2 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y,
- &cmp->x, bounds.xmin, bounds.xmax, 1, 5, "");
- uiDefButF(block, UI_BTYPE_NUM, 0, "Y", 0, 1 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y,
- &cmp->y, bounds.ymin, bounds.ymax, 1, 5, "");
- }
-
- /* black/white levels */
- if (levels) {
- split = uiLayoutSplit(layout, 0.0f, false);
- uiItemR(uiLayoutColumn(split, false), ptr, "black_level", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
- uiItemR(uiLayoutColumn(split, false), ptr, "white_level", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
-
- uiLayoutRow(layout, false);
- bt = uiDefBut(block, UI_BTYPE_BUT, 0, IFACE_("Reset"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0,
- TIP_("Reset Black/White point and curves"));
- UI_but_funcN_set(bt, curvemap_buttons_reset, MEM_dupallocN(cb), cumap);
- }
-
- UI_block_funcN_set(block, NULL, NULL, NULL);
+ CurveMapping *cumap = ptr->data;
+ CurveMap *cm = &cumap->cm[cumap->cur];
+ CurveMapPoint *cmp = NULL;
+ uiLayout *row, *sub, *split;
+ uiBlock *block;
+ uiBut *bt;
+ float dx = UI_UNIT_X;
+ int icon, size;
+ int bg = -1, i;
+
+ block = uiLayoutGetBlock(layout);
+
+ if (tone) {
+ split = uiLayoutSplit(layout, 0.0f, false);
+ uiItemR(uiLayoutRow(split, false), ptr, "tone", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ }
+
+ /* curve chooser */
+ row = uiLayoutRow(layout, false);
+
+ if (labeltype == 'v') {
+ /* vector */
+ sub = uiLayoutRow(row, true);
+ uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
+
+ if (cumap->cm[0].curve) {
+ bt = uiDefButI(
+ block, UI_BTYPE_ROW, 0, "X", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
+ }
+ if (cumap->cm[1].curve) {
+ bt = uiDefButI(
+ block, UI_BTYPE_ROW, 0, "Y", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
+ }
+ if (cumap->cm[2].curve) {
+ bt = uiDefButI(
+ block, UI_BTYPE_ROW, 0, "Z", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
+ }
+ }
+ else if (labeltype == 'c') {
+ /* color */
+ sub = uiLayoutRow(row, true);
+ uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
+
+ if (cumap->cm[3].curve) {
+ bt = uiDefButI(
+ block, UI_BTYPE_ROW, 0, "C", 0, 0, dx, dx, &cumap->cur, 0.0, 3.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
+ }
+ if (cumap->cm[0].curve) {
+ bt = uiDefButI(
+ block, UI_BTYPE_ROW, 0, "R", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
+ }
+ if (cumap->cm[1].curve) {
+ bt = uiDefButI(
+ block, UI_BTYPE_ROW, 0, "G", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
+ }
+ if (cumap->cm[2].curve) {
+ bt = uiDefButI(
+ block, UI_BTYPE_ROW, 0, "B", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
+ }
+ }
+ else if (labeltype == 'h') {
+ /* HSV */
+ sub = uiLayoutRow(row, true);
+ uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
+
+ if (cumap->cm[0].curve) {
+ bt = uiDefButI(
+ block, UI_BTYPE_ROW, 0, "H", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
+ }
+ if (cumap->cm[1].curve) {
+ bt = uiDefButI(
+ block, UI_BTYPE_ROW, 0, "S", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
+ }
+ if (cumap->cm[2].curve) {
+ bt = uiDefButI(
+ block, UI_BTYPE_ROW, 0, "V", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
+ }
+ }
+ else {
+ uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
+ }
+
+ if (labeltype == 'h') {
+ bg = UI_GRAD_H;
+ }
+
+ /* operation buttons */
+ sub = uiLayoutRow(row, true);
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+
+ bt = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_ZOOM_IN,
+ 0,
+ 0,
+ dx,
+ dx,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Zoom in"));
+ UI_but_func_set(bt, curvemap_buttons_zoom_in, cumap, NULL);
+
+ bt = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_ZOOM_OUT,
+ 0,
+ 0,
+ dx,
+ dx,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Zoom out"));
+ UI_but_func_set(bt, curvemap_buttons_zoom_out, cumap, NULL);
+
+ if (brush) {
+ bt = uiDefIconBlockBut(block,
+ curvemap_brush_tools_func,
+ cumap,
+ 0,
+ ICON_DOWNARROW_HLT,
+ 0,
+ 0,
+ dx,
+ dx,
+ TIP_("Tools"));
+ }
+ else if (neg_slope) {
+ bt = uiDefIconBlockBut(block,
+ curvemap_tools_negslope_func,
+ cumap,
+ 0,
+ ICON_DOWNARROW_HLT,
+ 0,
+ 0,
+ dx,
+ dx,
+ TIP_("Tools"));
+ }
+ else {
+ bt = uiDefIconBlockBut(block,
+ curvemap_tools_posslope_func,
+ cumap,
+ 0,
+ ICON_DOWNARROW_HLT,
+ 0,
+ 0,
+ dx,
+ dx,
+ TIP_("Tools"));
+ }
+
+ UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+
+ icon = (cumap->flag & CUMA_DO_CLIP) ? ICON_CLIPUV_HLT : ICON_CLIPUV_DEHLT;
+ bt = uiDefIconBlockBut(
+ block, curvemap_clipping_func, cumap, 0, icon, 0, 0, dx, dx, TIP_("Clipping Options"));
+ UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+
+ bt = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_X,
+ 0,
+ 0,
+ dx,
+ dx,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Delete points"));
+ UI_but_funcN_set(bt, curvemap_buttons_delete, MEM_dupallocN(cb), cumap);
+
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ UI_block_funcN_set(block, rna_update_cb, MEM_dupallocN(cb), NULL);
+
+ /* curve itself */
+ size = uiLayoutGetWidth(layout);
+ row = uiLayoutRow(layout, false);
+ uiDefBut(
+ block, UI_BTYPE_CURVE, 0, "", 0, 0, size, 8.0f * UI_UNIT_X, cumap, 0.0f, 1.0f, bg, 0, "");
+
+ /* sliders for selected point */
+ for (i = 0; i < cm->totpoint; i++) {
+ if (cm->curve[i].flag & CUMA_SELECT) {
+ cmp = &cm->curve[i];
+ break;
+ }
+ }
+
+ if (cmp) {
+ rctf bounds;
+
+ if (cumap->flag & CUMA_DO_CLIP) {
+ bounds = cumap->clipr;
+ }
+ else {
+ bounds.xmin = bounds.ymin = -1000.0;
+ bounds.xmax = bounds.ymax = 1000.0;
+ }
+
+ uiLayoutRow(layout, true);
+ UI_block_funcN_set(block, curvemap_buttons_update, MEM_dupallocN(cb), cumap);
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ 0,
+ "X",
+ 0,
+ 2 * UI_UNIT_Y,
+ UI_UNIT_X * 10,
+ UI_UNIT_Y,
+ &cmp->x,
+ bounds.xmin,
+ bounds.xmax,
+ 1,
+ 5,
+ "");
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ 0,
+ "Y",
+ 0,
+ 1 * UI_UNIT_Y,
+ UI_UNIT_X * 10,
+ UI_UNIT_Y,
+ &cmp->y,
+ bounds.ymin,
+ bounds.ymax,
+ 1,
+ 5,
+ "");
+ }
+
+ /* black/white levels */
+ if (levels) {
+ split = uiLayoutSplit(layout, 0.0f, false);
+ uiItemR(uiLayoutColumn(split, false), ptr, "black_level", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(uiLayoutColumn(split, false), ptr, "white_level", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+
+ uiLayoutRow(layout, false);
+ bt = uiDefBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ IFACE_("Reset"),
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ UI_UNIT_Y,
+ NULL,
+ 0.0f,
+ 0.0f,
+ 0,
+ 0,
+ TIP_("Reset Black/White point and curves"));
+ UI_but_funcN_set(bt, curvemap_buttons_reset, MEM_dupallocN(cb), cumap);
+ }
+
+ UI_block_funcN_set(block, NULL, NULL, NULL);
}
-void uiTemplateCurveMapping(
- uiLayout *layout, PointerRNA *ptr, const char *propname, int type,
- bool levels, bool brush, bool neg_slope, bool tone)
+void uiTemplateCurveMapping(uiLayout *layout,
+ PointerRNA *ptr,
+ const char *propname,
+ int type,
+ bool levels,
+ bool brush,
+ bool neg_slope,
+ bool tone)
{
- RNAUpdateCb *cb;
- PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
- PointerRNA cptr;
- ID *id;
- uiBlock *block = uiLayoutGetBlock(layout);
+ RNAUpdateCb *cb;
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ PointerRNA cptr;
+ ID *id;
+ uiBlock *block = uiLayoutGetBlock(layout);
- if (!prop) {
- RNA_warning("curve property not found: %s.%s",
- RNA_struct_identifier(ptr->type), propname);
- return;
- }
+ if (!prop) {
+ RNA_warning("curve property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
- if (RNA_property_type(prop) != PROP_POINTER) {
- RNA_warning("curve is not a pointer: %s.%s",
- RNA_struct_identifier(ptr->type), propname);
- return;
- }
+ if (RNA_property_type(prop) != PROP_POINTER) {
+ RNA_warning("curve is not a pointer: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
- cptr = RNA_property_pointer_get(ptr, prop);
- if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_CurveMapping)) {
- return;
- }
+ cptr = RNA_property_pointer_get(ptr, prop);
+ if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_CurveMapping)) {
+ return;
+ }
- cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
- cb->ptr = *ptr;
- cb->prop = prop;
+ cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
+ cb->ptr = *ptr;
+ cb->prop = prop;
- id = cptr.id.data;
- UI_block_lock_set(block, (id && ID_IS_LINKED(id)), ERROR_LIBDATA_MESSAGE);
+ id = cptr.id.data;
+ UI_block_lock_set(block, (id && ID_IS_LINKED(id)), ERROR_LIBDATA_MESSAGE);
- curvemap_buttons_layout(layout, &cptr, type, levels, brush, neg_slope, tone, cb);
+ curvemap_buttons_layout(layout, &cptr, type, levels, brush, neg_slope, tone, cb);
- UI_block_lock_clear(block);
+ UI_block_lock_clear(block);
- MEM_freeN(cb);
+ MEM_freeN(cb);
}
/********************* ColorPicker Template ************************/
-#define WHEEL_SIZE (5 * U.widget_unit)
+#define WHEEL_SIZE (5 * U.widget_unit)
/* This template now follows User Preference for type - name is not correct anymore... */
-void uiTemplateColorPicker(
- uiLayout *layout, PointerRNA *ptr, const char *propname, bool value_slider,
- bool lock, bool lock_luminosity, bool cubic)
+void uiTemplateColorPicker(uiLayout *layout,
+ PointerRNA *ptr,
+ const char *propname,
+ bool value_slider,
+ bool lock,
+ bool lock_luminosity,
+ bool cubic)
{
- PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
- uiBlock *block = uiLayoutGetBlock(layout);
- uiLayout *col, *row;
- uiBut *but = NULL;
- ColorPicker *cpicker = ui_block_colorpicker_create(block);
- float softmin, softmax, step, precision;
-
- if (!prop) {
- RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
-
- col = uiLayoutColumn(layout, true);
- row = uiLayoutRow(col, true);
-
- switch (U.color_picker_type) {
- case USER_CP_SQUARE_SV:
- but = uiDefButR_prop(
- block, UI_BTYPE_HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop,
- -1, 0.0, 0.0, UI_GRAD_SV, 0, "");
- break;
- case USER_CP_SQUARE_HS:
- but = uiDefButR_prop(
- block, UI_BTYPE_HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop,
- -1, 0.0, 0.0, UI_GRAD_HS, 0, "");
- break;
- case USER_CP_SQUARE_HV:
- but = uiDefButR_prop(
- block, UI_BTYPE_HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop,
- -1, 0.0, 0.0, UI_GRAD_HV, 0, "");
- break;
-
- /* user default */
- case USER_CP_CIRCLE_HSV:
- case USER_CP_CIRCLE_HSL:
- default:
- but = uiDefButR_prop(
- block, UI_BTYPE_HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop,
- -1, 0.0, 0.0, 0, 0, "");
- break;
-
- }
-
- but->custom_data = cpicker;
-
- cpicker->use_color_lock = lock;
- cpicker->use_color_cubic = cubic;
- cpicker->use_luminosity_lock = lock_luminosity;
-
- if (lock_luminosity) {
- float color[4]; /* in case of alpha */
- RNA_property_float_get_array(ptr, prop, color);
- but->a2 = len_v3(color);
- cpicker->luminosity_lock_value = len_v3(color);
- }
-
-
- if (value_slider) {
- switch (U.color_picker_type) {
- case USER_CP_CIRCLE_HSL:
- uiItemS(row);
- but = uiDefButR_prop(
- block, UI_BTYPE_HSVCUBE, 0, "", WHEEL_SIZE + 6, 0, 14 * UI_DPI_FAC, WHEEL_SIZE, ptr, prop,
- -1, softmin, softmax, UI_GRAD_L_ALT, 0, "");
- break;
- case USER_CP_SQUARE_SV:
- uiItemS(col);
- but = uiDefButR_prop(
- block, UI_BTYPE_HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18 * UI_DPI_FAC, ptr, prop,
- -1, softmin, softmax, UI_GRAD_SV + 3, 0, "");
- break;
- case USER_CP_SQUARE_HS:
- uiItemS(col);
- but = uiDefButR_prop(
- block, UI_BTYPE_HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18 * UI_DPI_FAC, ptr, prop,
- -1, softmin, softmax, UI_GRAD_HS + 3, 0, "");
- break;
- case USER_CP_SQUARE_HV:
- uiItemS(col);
- but = uiDefButR_prop(
- block, UI_BTYPE_HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18 * UI_DPI_FAC, ptr, prop,
- -1, softmin, softmax, UI_GRAD_HV + 3, 0, "");
- break;
-
- /* user default */
- case USER_CP_CIRCLE_HSV:
- default:
- uiItemS(row);
- but = uiDefButR_prop(
- block, UI_BTYPE_HSVCUBE, 0, "", WHEEL_SIZE + 6, 0, 14 * UI_DPI_FAC, WHEEL_SIZE, ptr, prop,
- -1, softmin, softmax, UI_GRAD_V_ALT, 0, "");
- break;
- }
-
- but->custom_data = cpicker;
- }
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiLayout *col, *row;
+ uiBut *but = NULL;
+ ColorPicker *cpicker = ui_block_colorpicker_create(block);
+ float softmin, softmax, step, precision;
+
+ if (!prop) {
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
+
+ col = uiLayoutColumn(layout, true);
+ row = uiLayoutRow(col, true);
+
+ switch (U.color_picker_type) {
+ case USER_CP_SQUARE_SV:
+ but = uiDefButR_prop(block,
+ UI_BTYPE_HSVCUBE,
+ 0,
+ "",
+ 0,
+ 0,
+ WHEEL_SIZE,
+ WHEEL_SIZE,
+ ptr,
+ prop,
+ -1,
+ 0.0,
+ 0.0,
+ UI_GRAD_SV,
+ 0,
+ "");
+ break;
+ case USER_CP_SQUARE_HS:
+ but = uiDefButR_prop(block,
+ UI_BTYPE_HSVCUBE,
+ 0,
+ "",
+ 0,
+ 0,
+ WHEEL_SIZE,
+ WHEEL_SIZE,
+ ptr,
+ prop,
+ -1,
+ 0.0,
+ 0.0,
+ UI_GRAD_HS,
+ 0,
+ "");
+ break;
+ case USER_CP_SQUARE_HV:
+ but = uiDefButR_prop(block,
+ UI_BTYPE_HSVCUBE,
+ 0,
+ "",
+ 0,
+ 0,
+ WHEEL_SIZE,
+ WHEEL_SIZE,
+ ptr,
+ prop,
+ -1,
+ 0.0,
+ 0.0,
+ UI_GRAD_HV,
+ 0,
+ "");
+ break;
+
+ /* user default */
+ case USER_CP_CIRCLE_HSV:
+ case USER_CP_CIRCLE_HSL:
+ default:
+ but = uiDefButR_prop(block,
+ UI_BTYPE_HSVCIRCLE,
+ 0,
+ "",
+ 0,
+ 0,
+ WHEEL_SIZE,
+ WHEEL_SIZE,
+ ptr,
+ prop,
+ -1,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ break;
+ }
+
+ but->custom_data = cpicker;
+
+ cpicker->use_color_lock = lock;
+ cpicker->use_color_cubic = cubic;
+ cpicker->use_luminosity_lock = lock_luminosity;
+
+ if (lock_luminosity) {
+ float color[4]; /* in case of alpha */
+ RNA_property_float_get_array(ptr, prop, color);
+ but->a2 = len_v3(color);
+ cpicker->luminosity_lock_value = len_v3(color);
+ }
+
+ if (value_slider) {
+ switch (U.color_picker_type) {
+ case USER_CP_CIRCLE_HSL:
+ uiItemS(row);
+ but = uiDefButR_prop(block,
+ UI_BTYPE_HSVCUBE,
+ 0,
+ "",
+ WHEEL_SIZE + 6,
+ 0,
+ 14 * UI_DPI_FAC,
+ WHEEL_SIZE,
+ ptr,
+ prop,
+ -1,
+ softmin,
+ softmax,
+ UI_GRAD_L_ALT,
+ 0,
+ "");
+ break;
+ case USER_CP_SQUARE_SV:
+ uiItemS(col);
+ but = uiDefButR_prop(block,
+ UI_BTYPE_HSVCUBE,
+ 0,
+ "",
+ 0,
+ 4,
+ WHEEL_SIZE,
+ 18 * UI_DPI_FAC,
+ ptr,
+ prop,
+ -1,
+ softmin,
+ softmax,
+ UI_GRAD_SV + 3,
+ 0,
+ "");
+ break;
+ case USER_CP_SQUARE_HS:
+ uiItemS(col);
+ but = uiDefButR_prop(block,
+ UI_BTYPE_HSVCUBE,
+ 0,
+ "",
+ 0,
+ 4,
+ WHEEL_SIZE,
+ 18 * UI_DPI_FAC,
+ ptr,
+ prop,
+ -1,
+ softmin,
+ softmax,
+ UI_GRAD_HS + 3,
+ 0,
+ "");
+ break;
+ case USER_CP_SQUARE_HV:
+ uiItemS(col);
+ but = uiDefButR_prop(block,
+ UI_BTYPE_HSVCUBE,
+ 0,
+ "",
+ 0,
+ 4,
+ WHEEL_SIZE,
+ 18 * UI_DPI_FAC,
+ ptr,
+ prop,
+ -1,
+ softmin,
+ softmax,
+ UI_GRAD_HV + 3,
+ 0,
+ "");
+ break;
+
+ /* user default */
+ case USER_CP_CIRCLE_HSV:
+ default:
+ uiItemS(row);
+ but = uiDefButR_prop(block,
+ UI_BTYPE_HSVCUBE,
+ 0,
+ "",
+ WHEEL_SIZE + 6,
+ 0,
+ 14 * UI_DPI_FAC,
+ WHEEL_SIZE,
+ ptr,
+ prop,
+ -1,
+ softmin,
+ softmax,
+ UI_GRAD_V_ALT,
+ 0,
+ "");
+ break;
+ }
+
+ but->custom_data = cpicker;
+ }
}
-void uiTemplatePalette(uiLayout *layout, PointerRNA *ptr, const char *propname, bool UNUSED(colors))
+void uiTemplatePalette(uiLayout *layout,
+ PointerRNA *ptr,
+ const char *propname,
+ bool UNUSED(colors))
{
- PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
- PointerRNA cptr;
- Palette *palette;
- PaletteColor *color;
- uiBlock *block;
- uiLayout *col;
- int row_cols = 0, col_id = 0;
- int cols_per_row = MAX2(uiLayoutGetWidth(layout) / UI_UNIT_X, 1);
-
- if (!prop) {
- RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- cptr = RNA_property_pointer_get(ptr, prop);
- if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Palette)) {
- return;
- }
-
- block = uiLayoutGetBlock(layout);
-
- palette = cptr.data;
-
- color = palette->colors.first;
-
- col = uiLayoutColumn(layout, true);
- uiLayoutRow(col, true);
- uiDefIconButO(block, UI_BTYPE_BUT, "PALETTE_OT_color_add", WM_OP_INVOKE_DEFAULT, ICON_ADD, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
- uiDefIconButO(block, UI_BTYPE_BUT, "PALETTE_OT_color_delete", WM_OP_INVOKE_DEFAULT, ICON_REMOVE, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
-
- col = uiLayoutColumn(layout, true);
- uiLayoutRow(col, true);
-
- for (; color; color = color->next) {
- PointerRNA color_ptr;
-
- if (row_cols >= cols_per_row) {
- uiLayoutRow(col, true);
- row_cols = 0;
- }
-
- RNA_pointer_create(&palette->id, &RNA_PaletteColor, color, &color_ptr);
- uiDefButR(
- block, UI_BTYPE_COLOR, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, &color_ptr, "color", -1, 0.0, 1.0,
- UI_PALETTE_COLOR, col_id, "");
- row_cols++;
- col_id++;
- }
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ PointerRNA cptr;
+ Palette *palette;
+ PaletteColor *color;
+ uiBlock *block;
+ uiLayout *col;
+ int row_cols = 0, col_id = 0;
+ int cols_per_row = MAX2(uiLayoutGetWidth(layout) / UI_UNIT_X, 1);
+
+ if (!prop) {
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ cptr = RNA_property_pointer_get(ptr, prop);
+ if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Palette)) {
+ return;
+ }
+
+ block = uiLayoutGetBlock(layout);
+
+ palette = cptr.data;
+
+ color = palette->colors.first;
+
+ col = uiLayoutColumn(layout, true);
+ uiLayoutRow(col, true);
+ uiDefIconButO(block,
+ UI_BTYPE_BUT,
+ "PALETTE_OT_color_add",
+ WM_OP_INVOKE_DEFAULT,
+ ICON_ADD,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL);
+ uiDefIconButO(block,
+ UI_BTYPE_BUT,
+ "PALETTE_OT_color_delete",
+ WM_OP_INVOKE_DEFAULT,
+ ICON_REMOVE,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL);
+
+ col = uiLayoutColumn(layout, true);
+ uiLayoutRow(col, true);
+
+ for (; color; color = color->next) {
+ PointerRNA color_ptr;
+
+ if (row_cols >= cols_per_row) {
+ uiLayoutRow(col, true);
+ row_cols = 0;
+ }
+
+ RNA_pointer_create(&palette->id, &RNA_PaletteColor, color, &color_ptr);
+ uiDefButR(block,
+ UI_BTYPE_COLOR,
+ 0,
+ "",
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &color_ptr,
+ "color",
+ -1,
+ 0.0,
+ 1.0,
+ UI_PALETTE_COLOR,
+ col_id,
+ "");
+ row_cols++;
+ col_id++;
+ }
}
void uiTemplateCryptoPicker(uiLayout *layout, PointerRNA *ptr, const char *propname)
{
- PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
- uiBlock *block;
- uiBut *but;
-
- if (!prop) {
- RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- block = uiLayoutGetBlock(layout);
-
- but = uiDefIconTextButO(block, UI_BTYPE_BUT, "UI_OT_eyedropper_color", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER, RNA_property_ui_name(prop), 0, 0, UI_UNIT_X, UI_UNIT_Y, RNA_property_ui_description(prop));
- but->rnapoin = *ptr;
- but->rnaprop = prop;
- but->rnaindex = -1;
-
- PointerRNA *opptr = UI_but_operator_ptr_get(but);
- /* Important for crypto-matte operation. */
- RNA_boolean_set(opptr, "use_accumulate", false);
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ uiBlock *block;
+ uiBut *but;
+
+ if (!prop) {
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ block = uiLayoutGetBlock(layout);
+
+ but = uiDefIconTextButO(block,
+ UI_BTYPE_BUT,
+ "UI_OT_eyedropper_color",
+ WM_OP_INVOKE_DEFAULT,
+ ICON_EYEDROPPER,
+ RNA_property_ui_name(prop),
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ RNA_property_ui_description(prop));
+ but->rnapoin = *ptr;
+ but->rnaprop = prop;
+ but->rnaindex = -1;
+
+ PointerRNA *opptr = UI_but_operator_ptr_get(but);
+ /* Important for crypto-matte operation. */
+ RNA_boolean_set(opptr, "use_accumulate", false);
}
/********************* Layer Buttons Template ************************/
static void handle_layer_buttons(bContext *C, void *arg1, void *arg2)
{
- uiBut *but = arg1;
- int cur = POINTER_AS_INT(arg2);
- wmWindow *win = CTX_wm_window(C);
- int i, tot, shift = win->eventstate->shift;
-
- if (!shift) {
- tot = RNA_property_array_length(&but->rnapoin, but->rnaprop);
-
- /* Normally clicking only selects one layer */
- RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, cur, true);
- for (i = 0; i < tot; ++i) {
- if (i != cur) {
- RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, i, false);
- }
- }
- }
-
- /* view3d layer change should update depsgraph (invisible object changed maybe) */
- /* see view3d_header.c */
+ uiBut *but = arg1;
+ int cur = POINTER_AS_INT(arg2);
+ wmWindow *win = CTX_wm_window(C);
+ int i, tot, shift = win->eventstate->shift;
+
+ if (!shift) {
+ tot = RNA_property_array_length(&but->rnapoin, but->rnaprop);
+
+ /* Normally clicking only selects one layer */
+ RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, cur, true);
+ for (i = 0; i < tot; ++i) {
+ if (i != cur) {
+ RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, i, false);
+ }
+ }
+ }
+
+ /* view3d layer change should update depsgraph (invisible object changed maybe) */
+ /* see view3d_header.c */
}
/**
* \todo for now, grouping of layers is determined by dividing up the length of
* the array of layer bitflags
*/
-void uiTemplateLayers(
- uiLayout *layout, PointerRNA *ptr, const char *propname,
- PointerRNA *used_ptr, const char *used_propname, int active_layer)
+void uiTemplateLayers(uiLayout *layout,
+ PointerRNA *ptr,
+ const char *propname,
+ PointerRNA *used_ptr,
+ const char *used_propname,
+ int active_layer)
{
- uiLayout *uRow, *uCol;
- PropertyRNA *prop, *used_prop = NULL;
- int groups, cols, layers;
- int group, col, layer, row;
- int cols_per_group = 5;
-
- prop = RNA_struct_find_property(ptr, propname);
- if (!prop) {
- RNA_warning("layers property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- /* the number of layers determines the way we group them
- * - we want 2 rows only (for now)
- * - the number of columns (cols) is the total number of buttons per row
- * the 'remainder' is added to this, as it will be ok to have first row slightly wider if need be
- * - for now, only split into groups if group will have at least 5 items
- */
- layers = RNA_property_array_length(ptr, prop);
- cols = (layers / 2) + (layers % 2);
- groups = ((cols / 2) < cols_per_group) ? (1) : (cols / cols_per_group);
-
- if (used_ptr && used_propname) {
- used_prop = RNA_struct_find_property(used_ptr, used_propname);
- if (!used_prop) {
- RNA_warning("used layers property not found: %s.%s", RNA_struct_identifier(ptr->type), used_propname);
- return;
- }
-
- if (RNA_property_array_length(used_ptr, used_prop) < layers) {
- used_prop = NULL;
- }
- }
-
- /* layers are laid out going across rows, with the columns being divided into groups */
-
- for (group = 0; group < groups; group++) {
- uCol = uiLayoutColumn(layout, true);
-
- for (row = 0; row < 2; row++) {
- uiBlock *block;
- uiBut *but;
-
- uRow = uiLayoutRow(uCol, true);
- block = uiLayoutGetBlock(uRow);
- layer = groups * cols_per_group * row + cols_per_group * group;
-
- /* add layers as toggle buts */
- for (col = 0; (col < cols_per_group) && (layer < layers); col++, layer++) {
- int icon = 0;
- int butlay = 1 << layer;
-
- if (active_layer & butlay) {
- icon = ICON_LAYER_ACTIVE;
- }
- else if (used_prop && RNA_property_boolean_get_index(used_ptr, used_prop, layer)) {
- icon = ICON_LAYER_USED;
- }
-
- but = uiDefAutoButR(block, ptr, prop, layer, "", icon, 0, 0, UI_UNIT_X / 2, UI_UNIT_Y / 2);
- UI_but_func_set(but, handle_layer_buttons, but, POINTER_FROM_INT(layer));
- but->type = UI_BTYPE_TOGGLE;
- }
- }
- }
+ uiLayout *uRow, *uCol;
+ PropertyRNA *prop, *used_prop = NULL;
+ int groups, cols, layers;
+ int group, col, layer, row;
+ int cols_per_group = 5;
+
+ prop = RNA_struct_find_property(ptr, propname);
+ if (!prop) {
+ RNA_warning("layers property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ /* the number of layers determines the way we group them
+ * - we want 2 rows only (for now)
+ * - the number of columns (cols) is the total number of buttons per row
+ * the 'remainder' is added to this, as it will be ok to have first row slightly wider if need be
+ * - for now, only split into groups if group will have at least 5 items
+ */
+ layers = RNA_property_array_length(ptr, prop);
+ cols = (layers / 2) + (layers % 2);
+ groups = ((cols / 2) < cols_per_group) ? (1) : (cols / cols_per_group);
+
+ if (used_ptr && used_propname) {
+ used_prop = RNA_struct_find_property(used_ptr, used_propname);
+ if (!used_prop) {
+ RNA_warning("used layers property not found: %s.%s",
+ RNA_struct_identifier(ptr->type),
+ used_propname);
+ return;
+ }
+
+ if (RNA_property_array_length(used_ptr, used_prop) < layers) {
+ used_prop = NULL;
+ }
+ }
+
+ /* layers are laid out going across rows, with the columns being divided into groups */
+
+ for (group = 0; group < groups; group++) {
+ uCol = uiLayoutColumn(layout, true);
+
+ for (row = 0; row < 2; row++) {
+ uiBlock *block;
+ uiBut *but;
+
+ uRow = uiLayoutRow(uCol, true);
+ block = uiLayoutGetBlock(uRow);
+ layer = groups * cols_per_group * row + cols_per_group * group;
+
+ /* add layers as toggle buts */
+ for (col = 0; (col < cols_per_group) && (layer < layers); col++, layer++) {
+ int icon = 0;
+ int butlay = 1 << layer;
+
+ if (active_layer & butlay) {
+ icon = ICON_LAYER_ACTIVE;
+ }
+ else if (used_prop && RNA_property_boolean_get_index(used_ptr, used_prop, layer)) {
+ icon = ICON_LAYER_USED;
+ }
+
+ but = uiDefAutoButR(block, ptr, prop, layer, "", icon, 0, 0, UI_UNIT_X / 2, UI_UNIT_Y / 2);
+ UI_but_func_set(but, handle_layer_buttons, but, POINTER_FROM_INT(layer));
+ but->type = UI_BTYPE_TOGGLE;
+ }
+ }
+ }
}
/************************* List Template **************************/
-static void uilist_draw_item_default(
- struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout,
- struct PointerRNA *UNUSED(dataptr), struct PointerRNA *itemptr, int icon,
- struct PointerRNA *UNUSED(active_dataptr), const char *UNUSED(active_propname),
- int UNUSED(index), int UNUSED(flt_flag))
+static void uilist_draw_item_default(struct uiList *ui_list,
+ struct bContext *UNUSED(C),
+ struct uiLayout *layout,
+ struct PointerRNA *UNUSED(dataptr),
+ struct PointerRNA *itemptr,
+ int icon,
+ struct PointerRNA *UNUSED(active_dataptr),
+ const char *UNUSED(active_propname),
+ int UNUSED(index),
+ int UNUSED(flt_flag))
{
- PropertyRNA *nameprop = RNA_struct_name_property(itemptr->type);
-
- /* Simplest one! */
- switch (ui_list->layout_type) {
- case UILST_LAYOUT_GRID:
- uiItemL(layout, "", icon);
- break;
- case UILST_LAYOUT_DEFAULT:
- case UILST_LAYOUT_COMPACT:
- default:
- if (nameprop) {
- uiItemFullR(layout, itemptr, nameprop, RNA_NO_INDEX, 0, UI_ITEM_R_NO_BG, "", icon);
- }
- else {
- uiItemL(layout, "", icon);
- }
- break;
- }
+ PropertyRNA *nameprop = RNA_struct_name_property(itemptr->type);
+
+ /* Simplest one! */
+ switch (ui_list->layout_type) {
+ case UILST_LAYOUT_GRID:
+ uiItemL(layout, "", icon);
+ break;
+ case UILST_LAYOUT_DEFAULT:
+ case UILST_LAYOUT_COMPACT:
+ default:
+ if (nameprop) {
+ uiItemFullR(layout, itemptr, nameprop, RNA_NO_INDEX, 0, UI_ITEM_R_NO_BG, "", icon);
+ }
+ else {
+ uiItemL(layout, "", icon);
+ }
+ break;
+ }
}
-static void uilist_draw_filter_default(struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout)
+static void uilist_draw_filter_default(struct uiList *ui_list,
+ struct bContext *UNUSED(C),
+ struct uiLayout *layout)
{
- PointerRNA listptr;
- uiLayout *row, *subrow;
-
- RNA_pointer_create(NULL, &RNA_UIList, ui_list, &listptr);
-
- row = uiLayoutRow(layout, false);
-
- subrow = uiLayoutRow(row, true);
- uiItemR(subrow, &listptr, "filter_name", 0, "", ICON_NONE);
- uiItemR(subrow, &listptr, "use_filter_invert", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "",
- (ui_list->filter_flag & UILST_FLT_EXCLUDE) ? ICON_ZOOM_OUT : ICON_ZOOM_IN);
-
- if ((ui_list->filter_sort_flag & UILST_FLT_SORT_LOCK) == 0) {
- subrow = uiLayoutRow(row, true);
- uiItemR(subrow, &listptr, "use_filter_sort_alpha", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
- uiItemR(subrow, &listptr, "use_filter_sort_reverse", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "",
- (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) ? ICON_SORT_DESC : ICON_SORT_ASC);
- }
+ PointerRNA listptr;
+ uiLayout *row, *subrow;
+
+ RNA_pointer_create(NULL, &RNA_UIList, ui_list, &listptr);
+
+ row = uiLayoutRow(layout, false);
+
+ subrow = uiLayoutRow(row, true);
+ uiItemR(subrow, &listptr, "filter_name", 0, "", ICON_NONE);
+ uiItemR(subrow,
+ &listptr,
+ "use_filter_invert",
+ UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY,
+ "",
+ (ui_list->filter_flag & UILST_FLT_EXCLUDE) ? ICON_ZOOM_OUT : ICON_ZOOM_IN);
+
+ if ((ui_list->filter_sort_flag & UILST_FLT_SORT_LOCK) == 0) {
+ subrow = uiLayoutRow(row, true);
+ uiItemR(subrow,
+ &listptr,
+ "use_filter_sort_alpha",
+ UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY,
+ "",
+ ICON_NONE);
+ uiItemR(subrow,
+ &listptr,
+ "use_filter_sort_reverse",
+ UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY,
+ "",
+ (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) ? ICON_SORT_DESC : ICON_SORT_ASC);
+ }
}
typedef struct {
- char name[MAX_IDPROP_NAME];
- int org_idx;
+ char name[MAX_IDPROP_NAME];
+ int org_idx;
} StringCmp;
static int cmpstringp(const void *p1, const void *p2)
{
- /* Case-insensitive comparison. */
- return BLI_strcasecmp(((StringCmp *) p1)->name, ((StringCmp *) p2)->name);
+ /* Case-insensitive comparison. */
+ return BLI_strcasecmp(((StringCmp *)p1)->name, ((StringCmp *)p2)->name);
}
-static void uilist_filter_items_default(
- struct uiList *ui_list, struct bContext *UNUSED(C), struct PointerRNA *dataptr,
- const char *propname)
+static void uilist_filter_items_default(struct uiList *ui_list,
+ struct bContext *UNUSED(C),
+ struct PointerRNA *dataptr,
+ const char *propname)
{
- uiListDyn *dyn_data = ui_list->dyn_data;
- PropertyRNA *prop = RNA_struct_find_property(dataptr, propname);
-
- const char *filter_raw = ui_list->filter_byname;
- char *filter = (char *)filter_raw, filter_buff[32], *filter_dyn = NULL;
- const bool filter_exclude = (ui_list->filter_flag & UILST_FLT_EXCLUDE) != 0;
- const bool order_by_name = (ui_list->filter_sort_flag & UILST_FLT_SORT_MASK) == UILST_FLT_SORT_ALPHA;
- int len = RNA_property_collection_length(dataptr, prop);
-
- dyn_data->items_shown = dyn_data->items_len = len;
-
- if (len && (order_by_name || filter_raw[0])) {
- StringCmp *names = NULL;
- int order_idx = 0, i = 0;
-
- if (order_by_name) {
- names = MEM_callocN(sizeof(StringCmp) * len, "StringCmp");
- }
- if (filter_raw[0]) {
- size_t slen = strlen(filter_raw);
-
- dyn_data->items_filter_flags = MEM_callocN(sizeof(int) * len, "items_filter_flags");
- dyn_data->items_shown = 0;
-
- /* Implicitly add heading/trailing wildcards if needed. */
- if (slen + 3 <= sizeof(filter_buff)) {
- filter = filter_buff;
- }
- else {
- filter = filter_dyn = MEM_mallocN((slen + 3) * sizeof(char), "filter_dyn");
- }
- BLI_strncpy_ensure_pad(filter, filter_raw, '*', slen + 3);
- }
-
- RNA_PROP_BEGIN (dataptr, itemptr, prop)
- {
- char *namebuf;
- const char *name;
- bool do_order = false;
-
- namebuf = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL);
- name = namebuf ? namebuf : "";
-
- if (filter[0]) {
- /* Case-insensitive! */
- if (fnmatch(filter, name, FNM_CASEFOLD) == 0) {
- dyn_data->items_filter_flags[i] = UILST_FLT_ITEM;
- if (!filter_exclude) {
- dyn_data->items_shown++;
- do_order = order_by_name;
- }
- //printf("%s: '%s' matches '%s'\n", __func__, name, filter);
- }
- else if (filter_exclude) {
- dyn_data->items_shown++;
- do_order = order_by_name;
- }
- }
- else {
- do_order = order_by_name;
- }
-
- if (do_order) {
- names[order_idx].org_idx = order_idx;
- BLI_strncpy(names[order_idx++].name, name, MAX_IDPROP_NAME);
- }
-
- /* free name */
- if (namebuf) {
- MEM_freeN(namebuf);
- }
- i++;
- }
- RNA_PROP_END;
-
- if (order_by_name) {
- int new_idx;
- /* note: order_idx equals either to ui_list->items_len if no filtering done,
- * or to ui_list->items_shown if filter is enabled,
- * or to (ui_list->items_len - ui_list->items_shown) if filtered items are excluded.
- * This way, we only sort items we actually intend to draw!
- */
- qsort(names, order_idx, sizeof(StringCmp), cmpstringp);
-
- dyn_data->items_filter_neworder = MEM_mallocN(sizeof(int) * order_idx, "items_filter_neworder");
- for (new_idx = 0; new_idx < order_idx; new_idx++) {
- dyn_data->items_filter_neworder[names[new_idx].org_idx] = new_idx;
- }
- }
-
- if (filter_dyn) {
- MEM_freeN(filter_dyn);
- }
- if (names) {
- MEM_freeN(names);
- }
- }
+ uiListDyn *dyn_data = ui_list->dyn_data;
+ PropertyRNA *prop = RNA_struct_find_property(dataptr, propname);
+
+ const char *filter_raw = ui_list->filter_byname;
+ char *filter = (char *)filter_raw, filter_buff[32], *filter_dyn = NULL;
+ const bool filter_exclude = (ui_list->filter_flag & UILST_FLT_EXCLUDE) != 0;
+ const bool order_by_name = (ui_list->filter_sort_flag & UILST_FLT_SORT_MASK) ==
+ UILST_FLT_SORT_ALPHA;
+ int len = RNA_property_collection_length(dataptr, prop);
+
+ dyn_data->items_shown = dyn_data->items_len = len;
+
+ if (len && (order_by_name || filter_raw[0])) {
+ StringCmp *names = NULL;
+ int order_idx = 0, i = 0;
+
+ if (order_by_name) {
+ names = MEM_callocN(sizeof(StringCmp) * len, "StringCmp");
+ }
+ if (filter_raw[0]) {
+ size_t slen = strlen(filter_raw);
+
+ dyn_data->items_filter_flags = MEM_callocN(sizeof(int) * len, "items_filter_flags");
+ dyn_data->items_shown = 0;
+
+ /* Implicitly add heading/trailing wildcards if needed. */
+ if (slen + 3 <= sizeof(filter_buff)) {
+ filter = filter_buff;
+ }
+ else {
+ filter = filter_dyn = MEM_mallocN((slen + 3) * sizeof(char), "filter_dyn");
+ }
+ BLI_strncpy_ensure_pad(filter, filter_raw, '*', slen + 3);
+ }
+
+ RNA_PROP_BEGIN (dataptr, itemptr, prop) {
+ char *namebuf;
+ const char *name;
+ bool do_order = false;
+
+ namebuf = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL);
+ name = namebuf ? namebuf : "";
+
+ if (filter[0]) {
+ /* Case-insensitive! */
+ if (fnmatch(filter, name, FNM_CASEFOLD) == 0) {
+ dyn_data->items_filter_flags[i] = UILST_FLT_ITEM;
+ if (!filter_exclude) {
+ dyn_data->items_shown++;
+ do_order = order_by_name;
+ }
+ //printf("%s: '%s' matches '%s'\n", __func__, name, filter);
+ }
+ else if (filter_exclude) {
+ dyn_data->items_shown++;
+ do_order = order_by_name;
+ }
+ }
+ else {
+ do_order = order_by_name;
+ }
+
+ if (do_order) {
+ names[order_idx].org_idx = order_idx;
+ BLI_strncpy(names[order_idx++].name, name, MAX_IDPROP_NAME);
+ }
+
+ /* free name */
+ if (namebuf) {
+ MEM_freeN(namebuf);
+ }
+ i++;
+ }
+ RNA_PROP_END;
+
+ if (order_by_name) {
+ int new_idx;
+ /* note: order_idx equals either to ui_list->items_len if no filtering done,
+ * or to ui_list->items_shown if filter is enabled,
+ * or to (ui_list->items_len - ui_list->items_shown) if filtered items are excluded.
+ * This way, we only sort items we actually intend to draw!
+ */
+ qsort(names, order_idx, sizeof(StringCmp), cmpstringp);
+
+ dyn_data->items_filter_neworder = MEM_mallocN(sizeof(int) * order_idx,
+ "items_filter_neworder");
+ for (new_idx = 0; new_idx < order_idx; new_idx++) {
+ dyn_data->items_filter_neworder[names[new_idx].org_idx] = new_idx;
+ }
+ }
+
+ if (filter_dyn) {
+ MEM_freeN(filter_dyn);
+ }
+ if (names) {
+ MEM_freeN(names);
+ }
+ }
}
typedef struct {
- PointerRNA item;
- int org_idx;
- int flt_flag;
+ PointerRNA item;
+ int org_idx;
+ int flt_flag;
} _uilist_item;
typedef struct {
- int visual_items; /* Visual number of items (i.e. number of items we have room to display). */
- int start_idx; /* Index of first item to display. */
- int end_idx; /* Index of last item to display + 1. */
+ int visual_items; /* Visual number of items (i.e. number of items we have room to display). */
+ int start_idx; /* Index of first item to display. */
+ int end_idx; /* Index of last item to display + 1. */
} uiListLayoutdata;
-static void uilist_prepare(
- uiList *ui_list, int len, int activei, int rows, int maxrows, int columns,
- uiListLayoutdata *layoutdata)
+static void uilist_prepare(uiList *ui_list,
+ int len,
+ int activei,
+ int rows,
+ int maxrows,
+ int columns,
+ uiListLayoutdata *layoutdata)
{
- uiListDyn *dyn_data = ui_list->dyn_data;
- int activei_row, max_scroll;
- const bool use_auto_size = (ui_list->list_grip < (rows - UI_LIST_AUTO_SIZE_THRESHOLD));
-
- /* default rows */
- if (rows <= 0) {
- rows = 5;
- }
- dyn_data->visual_height_min = rows;
- if (maxrows < rows) {
- maxrows = max_ii(rows, 5);
- }
- if (columns <= 0) {
- columns = 9;
- }
-
- if (columns > 1) {
- dyn_data->height = (int)ceil((double)len / (double)columns);
- activei_row = (int)floor((double)activei / (double)columns);
- }
- else {
- dyn_data->height = len;
- activei_row = activei;
- }
-
- if (!use_auto_size) {
- /* No auto-size, yet we clamp at min size! */
- maxrows = rows = max_ii(ui_list->list_grip, rows);
- }
- else if ((rows != maxrows) && (dyn_data->height > rows)) {
- /* Expand size if needed and possible. */
- rows = min_ii(dyn_data->height, maxrows);
- }
-
- /* If list length changes or list is tagged to check this,
- * and active is out of view, scroll to it .*/
- if (ui_list->list_last_len != len || ui_list->flag & UILST_SCROLL_TO_ACTIVE_ITEM) {
- if (activei_row < ui_list->list_scroll) {
- ui_list->list_scroll = activei_row;
- }
- else if (activei_row >= ui_list->list_scroll + rows) {
- ui_list->list_scroll = activei_row - rows + 1;
- }
- ui_list->flag &= ~UILST_SCROLL_TO_ACTIVE_ITEM;
- }
-
- max_scroll = max_ii(0, dyn_data->height - rows);
- CLAMP(ui_list->list_scroll, 0, max_scroll);
- ui_list->list_last_len = len;
- dyn_data->visual_height = rows;
- layoutdata->visual_items = rows * columns;
- layoutdata->start_idx = ui_list->list_scroll * columns;
- layoutdata->end_idx = min_ii(layoutdata->start_idx + rows * columns, len);
+ uiListDyn *dyn_data = ui_list->dyn_data;
+ int activei_row, max_scroll;
+ const bool use_auto_size = (ui_list->list_grip < (rows - UI_LIST_AUTO_SIZE_THRESHOLD));
+
+ /* default rows */
+ if (rows <= 0) {
+ rows = 5;
+ }
+ dyn_data->visual_height_min = rows;
+ if (maxrows < rows) {
+ maxrows = max_ii(rows, 5);
+ }
+ if (columns <= 0) {
+ columns = 9;
+ }
+
+ if (columns > 1) {
+ dyn_data->height = (int)ceil((double)len / (double)columns);
+ activei_row = (int)floor((double)activei / (double)columns);
+ }
+ else {
+ dyn_data->height = len;
+ activei_row = activei;
+ }
+
+ if (!use_auto_size) {
+ /* No auto-size, yet we clamp at min size! */
+ maxrows = rows = max_ii(ui_list->list_grip, rows);
+ }
+ else if ((rows != maxrows) && (dyn_data->height > rows)) {
+ /* Expand size if needed and possible. */
+ rows = min_ii(dyn_data->height, maxrows);
+ }
+
+ /* If list length changes or list is tagged to check this,
+ * and active is out of view, scroll to it .*/
+ if (ui_list->list_last_len != len || ui_list->flag & UILST_SCROLL_TO_ACTIVE_ITEM) {
+ if (activei_row < ui_list->list_scroll) {
+ ui_list->list_scroll = activei_row;
+ }
+ else if (activei_row >= ui_list->list_scroll + rows) {
+ ui_list->list_scroll = activei_row - rows + 1;
+ }
+ ui_list->flag &= ~UILST_SCROLL_TO_ACTIVE_ITEM;
+ }
+
+ max_scroll = max_ii(0, dyn_data->height - rows);
+ CLAMP(ui_list->list_scroll, 0, max_scroll);
+ ui_list->list_last_len = len;
+ dyn_data->visual_height = rows;
+ layoutdata->visual_items = rows * columns;
+ layoutdata->start_idx = ui_list->list_scroll * columns;
+ layoutdata->end_idx = min_ii(layoutdata->start_idx + rows * columns, len);
}
static void uilist_resize_update_cb(bContext *C, void *arg1, void *UNUSED(arg2))
{
- uiList *ui_list = arg1;
- uiListDyn *dyn_data = ui_list->dyn_data;
+ uiList *ui_list = arg1;
+ uiListDyn *dyn_data = ui_list->dyn_data;
- /* This way we get diff in number of additional items to show (positive) or hide (negative). */
- const int diff = round_fl_to_int((float)(dyn_data->resize - dyn_data->resize_prev) / (float)UI_UNIT_Y);
+ /* This way we get diff in number of additional items to show (positive) or hide (negative). */
+ const int diff = round_fl_to_int((float)(dyn_data->resize - dyn_data->resize_prev) /
+ (float)UI_UNIT_Y);
- if (diff != 0) {
- ui_list->list_grip += diff;
- dyn_data->resize_prev += diff * UI_UNIT_Y;
- ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
- }
+ if (diff != 0) {
+ ui_list->list_grip += diff;
+ dyn_data->resize_prev += diff * UI_UNIT_Y;
+ ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
+ }
- /* In case uilist is in popup, we need special refreshing */
- ED_region_tag_refresh_ui(CTX_wm_menu(C));
+ /* In case uilist is in popup, we need special refreshing */
+ ED_region_tag_refresh_ui(CTX_wm_menu(C));
}
static void *uilist_item_use_dynamic_tooltip(PointerRNA *itemptr, const char *propname)
{
- if (propname && propname[0] && itemptr && itemptr->data) {
- PropertyRNA *prop = RNA_struct_find_property(itemptr, propname);
-
- if (prop && (RNA_property_type(prop) == PROP_STRING)) {
- return RNA_property_string_get_alloc(itemptr, prop, NULL, 0, NULL);
- }
- }
- return NULL;
+ if (propname && propname[0] && itemptr && itemptr->data) {
+ PropertyRNA *prop = RNA_struct_find_property(itemptr, propname);
+
+ if (prop && (RNA_property_type(prop) == PROP_STRING)) {
+ return RNA_property_string_get_alloc(itemptr, prop, NULL, 0, NULL);
+ }
+ }
+ return NULL;
}
static char *uilist_item_tooltip_func(bContext *UNUSED(C), void *argN, const char *tip)
{
- char *dyn_tooltip = argN;
- return BLI_sprintfN("%s - %s", tip, dyn_tooltip);
+ char *dyn_tooltip = argN;
+ return BLI_sprintfN("%s - %s", tip, dyn_tooltip);
}
-void uiTemplateList(
- uiLayout *layout, bContext *C, const char *listtype_name, const char *list_id,
- PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr, const char *active_propname,
- const char *item_dyntip_propname, int rows, int maxrows, int layout_type, int columns,
- bool sort_reverse, bool sort_lock)
+void uiTemplateList(uiLayout *layout,
+ bContext *C,
+ const char *listtype_name,
+ const char *list_id,
+ PointerRNA *dataptr,
+ const char *propname,
+ PointerRNA *active_dataptr,
+ const char *active_propname,
+ const char *item_dyntip_propname,
+ int rows,
+ int maxrows,
+ int layout_type,
+ int columns,
+ bool sort_reverse,
+ bool sort_lock)
{
- uiListType *ui_list_type;
- uiList *ui_list = NULL;
- uiListDyn *dyn_data;
- ARegion *ar;
- uiListDrawItemFunc draw_item;
- uiListDrawFilterFunc draw_filter;
- uiListFilterItemsFunc filter_items;
-
- PropertyRNA *prop = NULL, *activeprop;
- PropertyType type, activetype;
- _uilist_item *items_ptr = NULL;
- StructRNA *ptype;
- uiLayout *glob = NULL, *box, *row, *col, *subrow, *sub, *overlap;
- uiBlock *block, *subblock;
- uiBut *but;
-
- uiListLayoutdata layoutdata;
- char ui_list_id[UI_MAX_NAME_STR];
- char numstr[32];
- int rnaicon = ICON_NONE, icon = ICON_NONE;
- int i = 0, activei = 0;
- int len = 0;
-
- /* validate arguments */
- /* Forbid default UI_UL_DEFAULT_CLASS_NAME list class without a custom list_id! */
- if (STREQ(UI_UL_DEFAULT_CLASS_NAME, listtype_name) && !(list_id && list_id[0])) {
- RNA_warning("template_list using default '%s' UIList class must provide a custom list_id",
- UI_UL_DEFAULT_CLASS_NAME);
- return;
- }
-
- block = uiLayoutGetBlock(layout);
-
- if (!active_dataptr->data) {
- RNA_warning("No active data");
- return;
- }
-
- if (dataptr->data) {
- prop = RNA_struct_find_property(dataptr, propname);
- if (!prop) {
- RNA_warning("Property not found: %s.%s", RNA_struct_identifier(dataptr->type), propname);
- return;
- }
- }
-
- activeprop = RNA_struct_find_property(active_dataptr, active_propname);
- if (!activeprop) {
- RNA_warning("Property not found: %s.%s", RNA_struct_identifier(active_dataptr->type), active_propname);
- return;
- }
-
- if (prop) {
- type = RNA_property_type(prop);
- if (type != PROP_COLLECTION) {
- RNA_warning("Expected a collection data property");
- return;
- }
- }
-
- activetype = RNA_property_type(activeprop);
- if (activetype != PROP_INT) {
- RNA_warning("Expected an integer active data property");
- return;
- }
-
- /* get icon */
- if (dataptr->data && prop) {
- ptype = RNA_property_pointer_type(dataptr, prop);
- rnaicon = RNA_struct_ui_icon(ptype);
- }
-
- /* get active data */
- activei = RNA_property_int_get(active_dataptr, activeprop);
-
- /* Find the uiList type. */
- ui_list_type = WM_uilisttype_find(listtype_name, false);
-
- if (ui_list_type == NULL) {
- RNA_warning("List type %s not found", listtype_name);
- return;
- }
-
- draw_item = ui_list_type->draw_item ? ui_list_type->draw_item : uilist_draw_item_default;
- draw_filter = ui_list_type->draw_filter ? ui_list_type->draw_filter : uilist_draw_filter_default;
- filter_items = ui_list_type->filter_items ? ui_list_type->filter_items : uilist_filter_items_default;
-
- /* Find or add the uiList to the current Region. */
- /* We tag the list id with the list type... */
- BLI_snprintf(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);
- }
- ui_list = BLI_findstring(&ar->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);
- 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;
- }
- if (sort_lock) {
- ui_list->filter_sort_flag |= UILST_FLT_SORT_LOCK;
- }
- }
-
- if (!ui_list->dyn_data) {
- ui_list->dyn_data = MEM_callocN(sizeof(uiListDyn), "uiList.dyn_data");
- }
- dyn_data = ui_list->dyn_data;
-
- /* Because we can't actually pass type across save&load... */
- ui_list->type = ui_list_type;
- ui_list->layout_type = layout_type;
-
- /* Reset filtering data. */
- MEM_SAFE_FREE(dyn_data->items_filter_flags);
- MEM_SAFE_FREE(dyn_data->items_filter_neworder);
- dyn_data->items_len = dyn_data->items_shown = -1;
-
- /* When active item changed since last draw, scroll to it. */
- if (activei != ui_list->list_last_activei) {
- ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
- ui_list->list_last_activei = activei;
- }
-
- /* Filter list items! (not for compact layout, though) */
- if (dataptr->data && prop) {
- const int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE;
- const bool order_reverse = (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0;
- int items_shown, idx = 0;
+ uiListType *ui_list_type;
+ uiList *ui_list = NULL;
+ uiListDyn *dyn_data;
+ ARegion *ar;
+ uiListDrawItemFunc draw_item;
+ uiListDrawFilterFunc draw_filter;
+ uiListFilterItemsFunc filter_items;
+
+ PropertyRNA *prop = NULL, *activeprop;
+ PropertyType type, activetype;
+ _uilist_item *items_ptr = NULL;
+ StructRNA *ptype;
+ uiLayout *glob = NULL, *box, *row, *col, *subrow, *sub, *overlap;
+ uiBlock *block, *subblock;
+ uiBut *but;
+
+ uiListLayoutdata layoutdata;
+ char ui_list_id[UI_MAX_NAME_STR];
+ char numstr[32];
+ int rnaicon = ICON_NONE, icon = ICON_NONE;
+ int i = 0, activei = 0;
+ int len = 0;
+
+ /* validate arguments */
+ /* Forbid default UI_UL_DEFAULT_CLASS_NAME list class without a custom list_id! */
+ if (STREQ(UI_UL_DEFAULT_CLASS_NAME, listtype_name) && !(list_id && list_id[0])) {
+ RNA_warning("template_list using default '%s' UIList class must provide a custom list_id",
+ UI_UL_DEFAULT_CLASS_NAME);
+ return;
+ }
+
+ block = uiLayoutGetBlock(layout);
+
+ if (!active_dataptr->data) {
+ RNA_warning("No active data");
+ return;
+ }
+
+ if (dataptr->data) {
+ prop = RNA_struct_find_property(dataptr, propname);
+ if (!prop) {
+ RNA_warning("Property not found: %s.%s", RNA_struct_identifier(dataptr->type), propname);
+ return;
+ }
+ }
+
+ activeprop = RNA_struct_find_property(active_dataptr, active_propname);
+ if (!activeprop) {
+ RNA_warning(
+ "Property not found: %s.%s", RNA_struct_identifier(active_dataptr->type), active_propname);
+ return;
+ }
+
+ if (prop) {
+ type = RNA_property_type(prop);
+ if (type != PROP_COLLECTION) {
+ RNA_warning("Expected a collection data property");
+ return;
+ }
+ }
+
+ activetype = RNA_property_type(activeprop);
+ if (activetype != PROP_INT) {
+ RNA_warning("Expected an integer active data property");
+ return;
+ }
+
+ /* get icon */
+ if (dataptr->data && prop) {
+ ptype = RNA_property_pointer_type(dataptr, prop);
+ rnaicon = RNA_struct_ui_icon(ptype);
+ }
+
+ /* get active data */
+ activei = RNA_property_int_get(active_dataptr, activeprop);
+
+ /* Find the uiList type. */
+ ui_list_type = WM_uilisttype_find(listtype_name, false);
+
+ if (ui_list_type == NULL) {
+ RNA_warning("List type %s not found", listtype_name);
+ return;
+ }
+
+ draw_item = ui_list_type->draw_item ? ui_list_type->draw_item : uilist_draw_item_default;
+ draw_filter = ui_list_type->draw_filter ? ui_list_type->draw_filter : uilist_draw_filter_default;
+ filter_items = ui_list_type->filter_items ? ui_list_type->filter_items :
+ uilist_filter_items_default;
+
+ /* Find or add the uiList to the current Region. */
+ /* We tag the list id with the list type... */
+ BLI_snprintf(
+ 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);
+ }
+ ui_list = BLI_findstring(&ar->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);
+ 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;
+ }
+ if (sort_lock) {
+ ui_list->filter_sort_flag |= UILST_FLT_SORT_LOCK;
+ }
+ }
+
+ if (!ui_list->dyn_data) {
+ ui_list->dyn_data = MEM_callocN(sizeof(uiListDyn), "uiList.dyn_data");
+ }
+ dyn_data = ui_list->dyn_data;
+
+ /* Because we can't actually pass type across save&load... */
+ ui_list->type = ui_list_type;
+ ui_list->layout_type = layout_type;
+
+ /* Reset filtering data. */
+ MEM_SAFE_FREE(dyn_data->items_filter_flags);
+ MEM_SAFE_FREE(dyn_data->items_filter_neworder);
+ dyn_data->items_len = dyn_data->items_shown = -1;
+
+ /* When active item changed since last draw, scroll to it. */
+ if (activei != ui_list->list_last_activei) {
+ ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
+ ui_list->list_last_activei = activei;
+ }
+
+ /* Filter list items! (not for compact layout, though) */
+ if (dataptr->data && prop) {
+ const int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE;
+ const bool order_reverse = (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0;
+ int items_shown, idx = 0;
#if 0
- int prev_ii = -1, prev_i;
+ int prev_ii = -1, prev_i;
#endif
- if (layout_type == UILST_LAYOUT_COMPACT) {
- dyn_data->items_len = dyn_data->items_shown = RNA_property_collection_length(dataptr, prop);
- }
- else {
- //printf("%s: filtering...\n", __func__);
- filter_items(ui_list, C, dataptr, propname);
- //printf("%s: filtering done.\n", __func__);
- }
-
- items_shown = dyn_data->items_shown;
- if (items_shown >= 0) {
- bool activei_mapping_pending = true;
- items_ptr = MEM_mallocN(sizeof(_uilist_item) * items_shown, __func__);
- //printf("%s: items shown: %d.\n", __func__, items_shown);
- RNA_PROP_BEGIN (dataptr, itemptr, prop)
- {
- if (!dyn_data->items_filter_flags ||
- ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude))
- {
- int ii;
- if (dyn_data->items_filter_neworder) {
- ii = dyn_data->items_filter_neworder[idx++];
- ii = order_reverse ? items_shown - ii - 1 : ii;
- }
- else {
- ii = order_reverse ? items_shown - ++idx : idx++;
- }
- //printf("%s: ii: %d\n", __func__, ii);
- items_ptr[ii].item = itemptr;
- items_ptr[ii].org_idx = i;
- items_ptr[ii].flt_flag = dyn_data->items_filter_flags ? dyn_data->items_filter_flags[i] : 0;
-
- if (activei_mapping_pending && activei == i) {
- activei = ii;
- /* So that we do not map again activei! */
- activei_mapping_pending = false;
- }
+ if (layout_type == UILST_LAYOUT_COMPACT) {
+ dyn_data->items_len = dyn_data->items_shown = RNA_property_collection_length(dataptr, prop);
+ }
+ else {
+ //printf("%s: filtering...\n", __func__);
+ filter_items(ui_list, C, dataptr, propname);
+ //printf("%s: filtering done.\n", __func__);
+ }
+
+ items_shown = dyn_data->items_shown;
+ if (items_shown >= 0) {
+ bool activei_mapping_pending = true;
+ items_ptr = MEM_mallocN(sizeof(_uilist_item) * items_shown, __func__);
+ //printf("%s: items shown: %d.\n", __func__, items_shown);
+ RNA_PROP_BEGIN (dataptr, itemptr, prop) {
+ if (!dyn_data->items_filter_flags ||
+ ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude)) {
+ int ii;
+ if (dyn_data->items_filter_neworder) {
+ ii = dyn_data->items_filter_neworder[idx++];
+ ii = order_reverse ? items_shown - ii - 1 : ii;
+ }
+ else {
+ ii = order_reverse ? items_shown - ++idx : idx++;
+ }
+ //printf("%s: ii: %d\n", __func__, ii);
+ items_ptr[ii].item = itemptr;
+ items_ptr[ii].org_idx = i;
+ items_ptr[ii].flt_flag = dyn_data->items_filter_flags ? dyn_data->items_filter_flags[i] :
+ 0;
+
+ if (activei_mapping_pending && activei == i) {
+ activei = ii;
+ /* So that we do not map again activei! */
+ activei_mapping_pending = false;
+ }
#if 0 /* For now, do not alter active element, even if it will be hidden... */
- else if (activei < i) {
- /* We do not want an active but invisible item!
- * Only exception is when all items are filtered out...
- */
- if (prev_ii >= 0) {
- activei = prev_ii;
- RNA_property_int_set(active_dataptr, activeprop, prev_i);
- }
- else {
- activei = ii;
- RNA_property_int_set(active_dataptr, activeprop, i);
- }
- }
- prev_i = i;
- prev_ii = ii;
+ else if (activei < i) {
+ /* We do not want an active but invisible item!
+ * Only exception is when all items are filtered out...
+ */
+ if (prev_ii >= 0) {
+ activei = prev_ii;
+ RNA_property_int_set(active_dataptr, activeprop, prev_i);
+ }
+ else {
+ activei = ii;
+ RNA_property_int_set(active_dataptr, activeprop, i);
+ }
+ }
+ prev_i = i;
+ prev_ii = ii;
#endif
- }
- i++;
- }
- RNA_PROP_END;
-
- if (activei_mapping_pending) {
- /* No active item found, set to 'invalid' -1 value... */
- activei = -1;
- }
- }
- if (dyn_data->items_shown >= 0) {
- len = dyn_data->items_shown;
- }
- else {
- len = dyn_data->items_len;
- }
- }
-
- switch (layout_type) {
- case UILST_LAYOUT_DEFAULT:
- /* layout */
- box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
- glob = uiLayoutColumn(box, true);
- row = uiLayoutRow(glob, false);
- col = uiLayoutColumn(row, true);
-
- /* init numbers */
- uilist_prepare(ui_list, len, activei, rows, maxrows, 1, &layoutdata);
-
- if (dataptr->data && prop) {
- /* create list items */
- for (i = layoutdata.start_idx; i < layoutdata.end_idx; i++) {
- PointerRNA *itemptr = &items_ptr[i].item;
- void *dyntip_data;
- int org_i = items_ptr[i].org_idx;
- int flt_flag = items_ptr[i].flt_flag;
- subblock = uiLayoutGetBlock(col);
-
- overlap = uiLayoutOverlap(col);
-
- UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM);
-
- /* list item behind label & other buttons */
- sub = uiLayoutRow(overlap, false);
-
- but = uiDefButR_prop(
- subblock, UI_BTYPE_LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
- active_dataptr, activeprop, 0, 0, org_i, 0, 0,
- TIP_("Double click to rename"));
- if ((dyntip_data = uilist_item_use_dynamic_tooltip(itemptr, item_dyntip_propname))) {
- UI_but_func_tooltip_set(but, uilist_item_tooltip_func, dyntip_data);
- }
-
- sub = uiLayoutRow(overlap, false);
-
- icon = UI_rnaptr_icon_get(C, itemptr, rnaicon, false);
- if (icon == ICON_DOT) {
- icon = ICON_NONE;
- }
- draw_item(ui_list, C, sub, dataptr, itemptr, icon, active_dataptr, active_propname,
- org_i, flt_flag);
-
- /* If we are "drawing" active item, set all labels as active. */
- if (i == activei) {
- ui_layout_list_set_labels_active(sub);
- }
-
- UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM);
- }
- }
-
- /* add dummy buttons to fill space */
- for (; i < layoutdata.start_idx + layoutdata.visual_items; i++) {
- uiItemL(col, "", ICON_NONE);
- }
-
- /* add scrollbar */
- if (len > layoutdata.visual_items) {
- col = uiLayoutColumn(row, false);
- uiDefButI(block, UI_BTYPE_SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height,
- &ui_list->list_scroll, 0, dyn_data->height - dyn_data->visual_height,
- dyn_data->visual_height, 0, "");
- }
- break;
- case UILST_LAYOUT_COMPACT:
- row = uiLayoutRow(layout, true);
-
- if ((dataptr->data && prop) && (dyn_data->items_shown > 0) &&
- (activei >= 0) && (activei < dyn_data->items_shown))
- {
- PointerRNA *itemptr = &items_ptr[activei].item;
- int org_i = items_ptr[activei].org_idx;
-
- icon = UI_rnaptr_icon_get(C, itemptr, rnaicon, false);
- if (icon == ICON_DOT) {
- icon = ICON_NONE;
- }
- draw_item(ui_list, C, row, dataptr, itemptr, icon, active_dataptr, active_propname, org_i, 0);
- }
- /* if list is empty, add in dummy button */
- else {
- uiItemL(row, "", ICON_NONE);
- }
-
- /* next/prev button */
- BLI_snprintf(numstr, sizeof(numstr), "%d :", dyn_data->items_shown);
- but = uiDefIconTextButR_prop(
- block, UI_BTYPE_NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y,
- active_dataptr, activeprop, 0, 0, 0, 0, 0, "");
- if (dyn_data->items_shown == 0) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- break;
- case UILST_LAYOUT_GRID:
- box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
- glob = uiLayoutColumn(box, true);
- row = uiLayoutRow(glob, false);
- col = uiLayoutColumn(row, true);
- subrow = NULL; /* Quite gcc warning! */
-
- uilist_prepare(ui_list, len, activei, rows, maxrows, columns, &layoutdata);
-
- if (dataptr->data && prop) {
- /* create list items */
- for (i = layoutdata.start_idx; i < layoutdata.end_idx; i++) {
- PointerRNA *itemptr = &items_ptr[i].item;
- int org_i = items_ptr[i].org_idx;
- int flt_flag = items_ptr[i].flt_flag;
-
- /* create button */
- if (!(i % columns)) {
- subrow = uiLayoutRow(col, false);
- }
-
- subblock = uiLayoutGetBlock(subrow);
- overlap = uiLayoutOverlap(subrow);
-
- UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM);
-
- /* list item behind label & other buttons */
- sub = uiLayoutRow(overlap, false);
-
- but = uiDefButR_prop(subblock, UI_BTYPE_LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
- active_dataptr, activeprop, 0, 0, org_i, 0, 0, NULL);
- UI_but_drawflag_enable(but, UI_BUT_NO_TOOLTIP);
-
- sub = uiLayoutRow(overlap, false);
-
- icon = UI_rnaptr_icon_get(C, itemptr, rnaicon, false);
- draw_item(ui_list, C, sub, dataptr, itemptr, icon, active_dataptr, active_propname,
- org_i, flt_flag);
-
- /* If we are "drawing" active item, set all labels as active. */
- if (i == activei) {
- ui_layout_list_set_labels_active(sub);
- }
-
- UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM);
- }
- }
-
- /* add dummy buttons to fill space */
- for (; i < layoutdata.start_idx + layoutdata.visual_items; i++) {
- if (!(i % columns)) {
- subrow = uiLayoutRow(col, false);
- }
- uiItemL(subrow, "", ICON_NONE);
- }
-
- /* add scrollbar */
- if (len > layoutdata.visual_items) {
- /* col = */ uiLayoutColumn(row, false);
- uiDefButI(block, UI_BTYPE_SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height,
- &ui_list->list_scroll, 0, dyn_data->height - dyn_data->visual_height,
- dyn_data->visual_height, 0, "");
- }
- break;
- }
-
- if (glob) {
- /* About UI_BTYPE_GRIP drag-resize:
- * We can't directly use results from a grip button, since we have a rather complex behavior here
- * (sizing by discrete steps and, overall, autosize feature).
- * Since we *never* know whether we are grip-resizing or not (because there is no callback for when a
- * button enters/leaves its "edit mode"), we use the fact that grip-controlled value (dyn_data->resize)
- * is completely handled by the grip during the grab resize, so settings its value here has no effect
- * at all.
- * It is only meaningful when we are not resizing, in which case this gives us the correct "init drag" value.
- * Note we cannot affect dyn_data->resize_prev here, since this value is not controlled by the grip!
- */
- dyn_data->resize = dyn_data->resize_prev + (dyn_data->visual_height - ui_list->list_grip) * UI_UNIT_Y;
-
- row = uiLayoutRow(glob, true);
- subblock = uiLayoutGetBlock(row);
- UI_block_emboss_set(subblock, UI_EMBOSS_NONE);
-
- if (ui_list->filter_flag & UILST_FLT_SHOW) {
- but = uiDefIconButBitI(subblock, UI_BTYPE_TOGGLE, UILST_FLT_SHOW, 0, ICON_DISCLOSURE_TRI_DOWN, 0, 0,
- UI_UNIT_X, UI_UNIT_Y * 0.5f, &(ui_list->filter_flag), 0, 0, 0, 0,
- TIP_("Hide filtering options"));
- UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
-
- but = uiDefIconButI(subblock, UI_BTYPE_GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.5f,
- &dyn_data->resize, 0.0, 0.0, 0, 0, "");
- UI_but_func_set(but, uilist_resize_update_cb, ui_list, NULL);
-
- UI_block_emboss_set(subblock, UI_EMBOSS);
-
- col = uiLayoutColumn(glob, false);
- subblock = uiLayoutGetBlock(col);
- uiDefBut(subblock, UI_BTYPE_SEPR, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y * 0.05f, NULL, 0.0, 0.0, 0, 0, "");
-
- draw_filter(ui_list, C, col);
- }
- else {
- but = uiDefIconButBitI(subblock, UI_BTYPE_TOGGLE, UILST_FLT_SHOW, 0, ICON_DISCLOSURE_TRI_RIGHT, 0, 0,
- UI_UNIT_X, UI_UNIT_Y * 0.5f, &(ui_list->filter_flag), 0, 0, 0, 0,
- TIP_("Show filtering options"));
- UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
-
- but = uiDefIconButI(subblock, UI_BTYPE_GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.5f,
- &dyn_data->resize, 0.0, 0.0, 0, 0, "");
- UI_but_func_set(but, uilist_resize_update_cb, ui_list, NULL);
-
- UI_block_emboss_set(subblock, UI_EMBOSS);
- }
- }
-
- if (items_ptr) {
- MEM_freeN(items_ptr);
- }
+ }
+ i++;
+ }
+ RNA_PROP_END;
+
+ if (activei_mapping_pending) {
+ /* No active item found, set to 'invalid' -1 value... */
+ activei = -1;
+ }
+ }
+ if (dyn_data->items_shown >= 0) {
+ len = dyn_data->items_shown;
+ }
+ else {
+ len = dyn_data->items_len;
+ }
+ }
+
+ switch (layout_type) {
+ case UILST_LAYOUT_DEFAULT:
+ /* layout */
+ box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
+ glob = uiLayoutColumn(box, true);
+ row = uiLayoutRow(glob, false);
+ col = uiLayoutColumn(row, true);
+
+ /* init numbers */
+ uilist_prepare(ui_list, len, activei, rows, maxrows, 1, &layoutdata);
+
+ if (dataptr->data && prop) {
+ /* create list items */
+ for (i = layoutdata.start_idx; i < layoutdata.end_idx; i++) {
+ PointerRNA *itemptr = &items_ptr[i].item;
+ void *dyntip_data;
+ int org_i = items_ptr[i].org_idx;
+ int flt_flag = items_ptr[i].flt_flag;
+ subblock = uiLayoutGetBlock(col);
+
+ overlap = uiLayoutOverlap(col);
+
+ UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM);
+
+ /* list item behind label & other buttons */
+ sub = uiLayoutRow(overlap, false);
+
+ but = uiDefButR_prop(subblock,
+ UI_BTYPE_LISTROW,
+ 0,
+ "",
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ UI_UNIT_Y,
+ active_dataptr,
+ activeprop,
+ 0,
+ 0,
+ org_i,
+ 0,
+ 0,
+ TIP_("Double click to rename"));
+ if ((dyntip_data = uilist_item_use_dynamic_tooltip(itemptr, item_dyntip_propname))) {
+ UI_but_func_tooltip_set(but, uilist_item_tooltip_func, dyntip_data);
+ }
+
+ sub = uiLayoutRow(overlap, false);
+
+ icon = UI_rnaptr_icon_get(C, itemptr, rnaicon, false);
+ if (icon == ICON_DOT) {
+ icon = ICON_NONE;
+ }
+ draw_item(ui_list,
+ C,
+ sub,
+ dataptr,
+ itemptr,
+ icon,
+ active_dataptr,
+ active_propname,
+ org_i,
+ flt_flag);
+
+ /* If we are "drawing" active item, set all labels as active. */
+ if (i == activei) {
+ ui_layout_list_set_labels_active(sub);
+ }
+
+ UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM);
+ }
+ }
+
+ /* add dummy buttons to fill space */
+ for (; i < layoutdata.start_idx + layoutdata.visual_items; i++) {
+ uiItemL(col, "", ICON_NONE);
+ }
+
+ /* add scrollbar */
+ if (len > layoutdata.visual_items) {
+ col = uiLayoutColumn(row, false);
+ uiDefButI(block,
+ UI_BTYPE_SCROLL,
+ 0,
+ "",
+ 0,
+ 0,
+ UI_UNIT_X * 0.75,
+ UI_UNIT_Y * dyn_data->visual_height,
+ &ui_list->list_scroll,
+ 0,
+ dyn_data->height - dyn_data->visual_height,
+ dyn_data->visual_height,
+ 0,
+ "");
+ }
+ break;
+ case UILST_LAYOUT_COMPACT:
+ row = uiLayoutRow(layout, true);
+
+ if ((dataptr->data && prop) && (dyn_data->items_shown > 0) && (activei >= 0) &&
+ (activei < dyn_data->items_shown)) {
+ PointerRNA *itemptr = &items_ptr[activei].item;
+ int org_i = items_ptr[activei].org_idx;
+
+ icon = UI_rnaptr_icon_get(C, itemptr, rnaicon, false);
+ if (icon == ICON_DOT) {
+ icon = ICON_NONE;
+ }
+ draw_item(
+ ui_list, C, row, dataptr, itemptr, icon, active_dataptr, active_propname, org_i, 0);
+ }
+ /* if list is empty, add in dummy button */
+ else {
+ uiItemL(row, "", ICON_NONE);
+ }
+
+ /* next/prev button */
+ BLI_snprintf(numstr, sizeof(numstr), "%d :", dyn_data->items_shown);
+ but = uiDefIconTextButR_prop(block,
+ UI_BTYPE_NUM,
+ 0,
+ 0,
+ numstr,
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_Y,
+ active_dataptr,
+ activeprop,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ if (dyn_data->items_shown == 0) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ break;
+ case UILST_LAYOUT_GRID:
+ box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
+ glob = uiLayoutColumn(box, true);
+ row = uiLayoutRow(glob, false);
+ col = uiLayoutColumn(row, true);
+ subrow = NULL; /* Quite gcc warning! */
+
+ uilist_prepare(ui_list, len, activei, rows, maxrows, columns, &layoutdata);
+
+ if (dataptr->data && prop) {
+ /* create list items */
+ for (i = layoutdata.start_idx; i < layoutdata.end_idx; i++) {
+ PointerRNA *itemptr = &items_ptr[i].item;
+ int org_i = items_ptr[i].org_idx;
+ int flt_flag = items_ptr[i].flt_flag;
+
+ /* create button */
+ if (!(i % columns)) {
+ subrow = uiLayoutRow(col, false);
+ }
+
+ subblock = uiLayoutGetBlock(subrow);
+ overlap = uiLayoutOverlap(subrow);
+
+ UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM);
+
+ /* list item behind label & other buttons */
+ sub = uiLayoutRow(overlap, false);
+
+ but = uiDefButR_prop(subblock,
+ UI_BTYPE_LISTROW,
+ 0,
+ "",
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ UI_UNIT_Y,
+ active_dataptr,
+ activeprop,
+ 0,
+ 0,
+ org_i,
+ 0,
+ 0,
+ NULL);
+ UI_but_drawflag_enable(but, UI_BUT_NO_TOOLTIP);
+
+ sub = uiLayoutRow(overlap, false);
+
+ icon = UI_rnaptr_icon_get(C, itemptr, rnaicon, false);
+ draw_item(ui_list,
+ C,
+ sub,
+ dataptr,
+ itemptr,
+ icon,
+ active_dataptr,
+ active_propname,
+ org_i,
+ flt_flag);
+
+ /* If we are "drawing" active item, set all labels as active. */
+ if (i == activei) {
+ ui_layout_list_set_labels_active(sub);
+ }
+
+ UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM);
+ }
+ }
+
+ /* add dummy buttons to fill space */
+ for (; i < layoutdata.start_idx + layoutdata.visual_items; i++) {
+ if (!(i % columns)) {
+ subrow = uiLayoutRow(col, false);
+ }
+ uiItemL(subrow, "", ICON_NONE);
+ }
+
+ /* add scrollbar */
+ if (len > layoutdata.visual_items) {
+ /* col = */ uiLayoutColumn(row, false);
+ uiDefButI(block,
+ UI_BTYPE_SCROLL,
+ 0,
+ "",
+ 0,
+ 0,
+ UI_UNIT_X * 0.75,
+ UI_UNIT_Y * dyn_data->visual_height,
+ &ui_list->list_scroll,
+ 0,
+ dyn_data->height - dyn_data->visual_height,
+ dyn_data->visual_height,
+ 0,
+ "");
+ }
+ break;
+ }
+
+ if (glob) {
+ /* About UI_BTYPE_GRIP drag-resize:
+ * We can't directly use results from a grip button, since we have a rather complex behavior here
+ * (sizing by discrete steps and, overall, autosize feature).
+ * Since we *never* know whether we are grip-resizing or not (because there is no callback for when a
+ * button enters/leaves its "edit mode"), we use the fact that grip-controlled value (dyn_data->resize)
+ * is completely handled by the grip during the grab resize, so settings its value here has no effect
+ * at all.
+ * It is only meaningful when we are not resizing, in which case this gives us the correct "init drag" value.
+ * Note we cannot affect dyn_data->resize_prev here, since this value is not controlled by the grip!
+ */
+ dyn_data->resize = dyn_data->resize_prev +
+ (dyn_data->visual_height - ui_list->list_grip) * UI_UNIT_Y;
+
+ row = uiLayoutRow(glob, true);
+ subblock = uiLayoutGetBlock(row);
+ UI_block_emboss_set(subblock, UI_EMBOSS_NONE);
+
+ if (ui_list->filter_flag & UILST_FLT_SHOW) {
+ but = uiDefIconButBitI(subblock,
+ UI_BTYPE_TOGGLE,
+ UILST_FLT_SHOW,
+ 0,
+ ICON_DISCLOSURE_TRI_DOWN,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y * 0.5f,
+ &(ui_list->filter_flag),
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Hide filtering options"));
+ UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+
+ but = uiDefIconButI(subblock,
+ UI_BTYPE_GRIP,
+ 0,
+ ICON_GRIP,
+ 0,
+ 0,
+ UI_UNIT_X * 10.0f,
+ UI_UNIT_Y * 0.5f,
+ &dyn_data->resize,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ UI_but_func_set(but, uilist_resize_update_cb, ui_list, NULL);
+
+ UI_block_emboss_set(subblock, UI_EMBOSS);
+
+ col = uiLayoutColumn(glob, false);
+ subblock = uiLayoutGetBlock(col);
+ uiDefBut(subblock,
+ UI_BTYPE_SEPR,
+ 0,
+ "",
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y * 0.05f,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+
+ draw_filter(ui_list, C, col);
+ }
+ else {
+ but = uiDefIconButBitI(subblock,
+ UI_BTYPE_TOGGLE,
+ UILST_FLT_SHOW,
+ 0,
+ ICON_DISCLOSURE_TRI_RIGHT,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y * 0.5f,
+ &(ui_list->filter_flag),
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Show filtering options"));
+ UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+
+ but = uiDefIconButI(subblock,
+ UI_BTYPE_GRIP,
+ 0,
+ ICON_GRIP,
+ 0,
+ 0,
+ UI_UNIT_X * 10.0f,
+ UI_UNIT_Y * 0.5f,
+ &dyn_data->resize,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ UI_but_func_set(but, uilist_resize_update_cb, ui_list, NULL);
+
+ UI_block_emboss_set(subblock, UI_EMBOSS);
+ }
+ }
+
+ if (items_ptr) {
+ MEM_freeN(items_ptr);
+ }
}
/************************* Operator Search Template **************************/
static void operator_call_cb(bContext *C, void *UNUSED(arg1), void *arg2)
{
- wmOperatorType *ot = arg2;
+ wmOperatorType *ot = arg2;
- if (ot) {
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, NULL);
- }
+ 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;
- }
+ 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)
+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;
- }
- }
- }
- }
+ 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);
+ 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] = "";
+ uiBlock *block;
+ uiBut *but;
+ static char search[256] = "";
- block = uiLayoutGetBlock(layout);
- UI_block_layout_set_current(block, layout);
+ 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);
+ 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);
}
/************************* 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))
+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);
+ WM_operator_properties_reset((wmOperator *)op_pt);
}
#endif
struct uiTemplateOperatorPropertyPollParam {
- const bContext *C;
- wmOperator *op;
- short flag;
+ 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)
+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);
+ 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)
+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, RNA_struct_ui_name(op->type->srna), 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);
-
- /* 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);
- }
- }
+ 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, RNA_struct_ui_name(op->type->srna), 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);
+
+ /* 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);
- }
+ /* 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 */
+ /* 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;
+ /* 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);
+ 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] */
+ /* 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);
- }
- }
- }
- }
+ /* 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;
+ return return_info;
}
/************************* Running Jobs Template **************************/
-#define B_STOPRENDER 1
-#define B_STOPCAST 2
-#define B_STOPANIM 3
-#define B_STOPCOMPO 4
-#define B_STOPSEQ 5
-#define B_STOPCLIP 6
-#define B_STOPFILE 7
-#define B_STOPOTHER 8
+#define B_STOPRENDER 1
+#define B_STOPCAST 2
+#define B_STOPANIM 3
+#define B_STOPCOMPO 4
+#define B_STOPSEQ 5
+#define B_STOPCLIP 6
+#define B_STOPFILE 7
+#define B_STOPOTHER 8
static void do_running_jobs(bContext *C, void *UNUSED(arg), int event)
{
- switch (event) {
- case B_STOPRENDER:
- G.is_break = true;
- break;
- case B_STOPCAST:
- WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C), NULL);
- break;
- case B_STOPANIM:
- WM_operator_name_call(C, "SCREEN_OT_animation_play", WM_OP_INVOKE_SCREEN, NULL);
- break;
- case B_STOPCOMPO:
- WM_jobs_stop(CTX_wm_manager(C), CTX_data_scene(C), NULL);
- break;
- case B_STOPSEQ:
- WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
- break;
- case B_STOPCLIP:
- WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
- break;
- case B_STOPFILE:
- WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
- break;
- case B_STOPOTHER:
- G.is_break = true;
- break;
- }
+ switch (event) {
+ case B_STOPRENDER:
+ G.is_break = true;
+ break;
+ case B_STOPCAST:
+ WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C), NULL);
+ break;
+ case B_STOPANIM:
+ WM_operator_name_call(C, "SCREEN_OT_animation_play", WM_OP_INVOKE_SCREEN, NULL);
+ break;
+ case B_STOPCOMPO:
+ WM_jobs_stop(CTX_wm_manager(C), CTX_data_scene(C), NULL);
+ break;
+ case B_STOPSEQ:
+ WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
+ break;
+ case B_STOPCLIP:
+ WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
+ break;
+ case B_STOPFILE:
+ WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
+ break;
+ case B_STOPOTHER:
+ G.is_break = true;
+ break;
+ }
}
struct ProgressTooltip_Store {
- wmWindowManager *wm;
- void *owner;
+ wmWindowManager *wm;
+ void *owner;
};
static char *progress_tooltip_func(bContext *UNUSED(C), void *argN, const char *UNUSED(tip))
{
- struct ProgressTooltip_Store *arg = argN;
- wmWindowManager *wm = arg->wm;
- void *owner = arg->owner;
-
- const float progress = WM_jobs_progress(wm, owner);
-
- /* create tooltip text and associate it with the job */
- char elapsed_str[32];
- char remaining_str[32] = "Unknown";
- const double elapsed = PIL_check_seconds_timer() - WM_jobs_starttime(wm, owner);
- BLI_timecode_string_from_time_simple(elapsed_str, sizeof(elapsed_str), elapsed);
-
- if (progress) {
- const double remaining = (elapsed / (double)progress) - elapsed;
- BLI_timecode_string_from_time_simple(remaining_str, sizeof(remaining_str), remaining);
- }
-
- return BLI_sprintfN(
- "Time Remaining: %s\n"
- "Time Elapsed: %s",
- remaining_str, elapsed_str);
+ struct ProgressTooltip_Store *arg = argN;
+ wmWindowManager *wm = arg->wm;
+ void *owner = arg->owner;
+
+ const float progress = WM_jobs_progress(wm, owner);
+
+ /* create tooltip text and associate it with the job */
+ char elapsed_str[32];
+ char remaining_str[32] = "Unknown";
+ const double elapsed = PIL_check_seconds_timer() - WM_jobs_starttime(wm, owner);
+ BLI_timecode_string_from_time_simple(elapsed_str, sizeof(elapsed_str), elapsed);
+
+ if (progress) {
+ const double remaining = (elapsed / (double)progress) - elapsed;
+ BLI_timecode_string_from_time_simple(remaining_str, sizeof(remaining_str), remaining);
+ }
+
+ return BLI_sprintfN(
+ "Time Remaining: %s\n"
+ "Time Elapsed: %s",
+ remaining_str,
+ elapsed_str);
}
void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
{
- bScreen *screen = CTX_wm_screen(C);
- wmWindowManager *wm = CTX_wm_manager(C);
- ScrArea *sa = CTX_wm_area(C);
- uiBlock *block;
- void *owner = NULL;
- int handle_event, icon = 0;
-
- block = uiLayoutGetBlock(layout);
- UI_block_layout_set_current(block, layout);
-
- UI_block_func_handle_set(block, do_running_jobs, NULL);
-
- if (sa->spacetype == SPACE_SEQ) {
- if (WM_jobs_test(wm, sa, WM_JOB_TYPE_ANY)) {
- owner = sa;
- }
- handle_event = B_STOPSEQ;
- icon = ICON_SEQUENCE;
- }
- else if (sa->spacetype == SPACE_CLIP) {
- if (WM_jobs_test(wm, sa, WM_JOB_TYPE_ANY)) {
- owner = sa;
- }
- handle_event = B_STOPCLIP;
- icon = ICON_TRACKER;
- }
- else if (sa->spacetype == SPACE_FILE) {
- if (WM_jobs_test(wm, sa, WM_JOB_TYPE_FILESEL_READDIR)) {
- owner = sa;
- }
- handle_event = B_STOPFILE;
- icon = ICON_FILEBROWSER;
- }
- else {
- 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) {
- if (WM_jobs_test(wm, scene, WM_JOB_TYPE_RENDER)) {
- handle_event = B_STOPRENDER;
- icon = ICON_SCENE;
- break;
- }
- else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_COMPOSITE)) {
- handle_event = B_STOPCOMPO;
- icon = ICON_RENDERLAYERS;
- break;
- }
- else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_OBJECT_BAKE_TEXTURE) ||
- WM_jobs_test(wm, scene, WM_JOB_TYPE_OBJECT_BAKE))
- {
- /* Skip bake jobs in compositor to avoid compo header displaying
- * progress bar which is not being updated (bake jobs only need
- * to update NC_IMAGE context.
- */
- if (sa->spacetype != SPACE_NODE) {
- handle_event = B_STOPOTHER;
- icon = ICON_IMAGE;
- break;
- }
- }
- else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_DPAINT_BAKE)) {
- handle_event = B_STOPOTHER;
- icon = ICON_MOD_DYNAMICPAINT;
- break;
- }
- else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_POINTCACHE)) {
- handle_event = B_STOPOTHER;
- icon = ICON_PHYSICS;
- break;
- }
- else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_OBJECT_SIM_FLUID)) {
- handle_event = B_STOPOTHER;
- icon = ICON_MOD_FLUIDSIM;
- break;
- }
- else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_OBJECT_SIM_OCEAN)) {
- handle_event = B_STOPOTHER;
- icon = ICON_MOD_OCEAN;
- break;
- }
- else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY)) {
- handle_event = B_STOPOTHER;
- icon = ICON_NONE;
- break;
- }
- }
- owner = scene;
- }
-
- if (owner) {
- const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- bool active = !(G.is_break || WM_jobs_is_stopped(wm, owner));
-
- uiLayout *row = uiLayoutRow(layout, false);
- block = uiLayoutGetBlock(row);
-
- /* get percentage done and set it as the UI text */
- const float progress = WM_jobs_progress(wm, owner);
- char text[8];
- BLI_snprintf(text, 8, "%d%%", (int)(progress * 100));
-
- const char *name = active ? WM_jobs_name(wm, owner) : "Canceling...";
-
- /* job name and icon */
- const int textwidth = UI_fontstyle_string_width(fstyle, name);
- uiDefIconTextBut(block, UI_BTYPE_LABEL, 0, icon, name, 0, 0,
- textwidth + UI_UNIT_X * 1.5f, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0.0f, 0.0f, "");
-
- /* stick progress bar and cancel button together */
- row = uiLayoutRow(layout, true);
- uiLayoutSetActive(row, active);
- block = uiLayoutGetBlock(row);
-
- {
- struct ProgressTooltip_Store *tip_arg = MEM_mallocN(sizeof(*tip_arg), __func__);
- tip_arg->wm = wm;
- tip_arg->owner = owner;
- uiBut *but_progress = uiDefIconTextBut(
- block, UI_BTYPE_PROGRESS_BAR, 0, 0, text,
- UI_UNIT_X, 0, UI_UNIT_X * 6.0f, UI_UNIT_Y, NULL, 0.0f, 0.0f,
- progress, 0, NULL);
- UI_but_func_tooltip_set(but_progress, progress_tooltip_func, tip_arg);
- }
-
- if (!wm->is_interface_locked) {
- uiDefIconTextBut(block, UI_BTYPE_BUT, handle_event, ICON_PANEL_CLOSE,
- "", 0, 0, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop this job"));
- }
- }
-
- if (screen->animtimer) {
- uiDefIconTextBut(block, UI_BTYPE_BUT, B_STOPANIM, ICON_CANCEL, IFACE_("Anim Player"), 0, 0, UI_UNIT_X * 5.0f, UI_UNIT_Y,
- NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop animation playback"));
- }
+ bScreen *screen = CTX_wm_screen(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ ScrArea *sa = CTX_wm_area(C);
+ uiBlock *block;
+ void *owner = NULL;
+ int handle_event, icon = 0;
+
+ block = uiLayoutGetBlock(layout);
+ UI_block_layout_set_current(block, layout);
+
+ UI_block_func_handle_set(block, do_running_jobs, NULL);
+
+ if (sa->spacetype == SPACE_SEQ) {
+ if (WM_jobs_test(wm, sa, WM_JOB_TYPE_ANY)) {
+ owner = sa;
+ }
+ handle_event = B_STOPSEQ;
+ icon = ICON_SEQUENCE;
+ }
+ else if (sa->spacetype == SPACE_CLIP) {
+ if (WM_jobs_test(wm, sa, WM_JOB_TYPE_ANY)) {
+ owner = sa;
+ }
+ handle_event = B_STOPCLIP;
+ icon = ICON_TRACKER;
+ }
+ else if (sa->spacetype == SPACE_FILE) {
+ if (WM_jobs_test(wm, sa, WM_JOB_TYPE_FILESEL_READDIR)) {
+ owner = sa;
+ }
+ handle_event = B_STOPFILE;
+ icon = ICON_FILEBROWSER;
+ }
+ else {
+ 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) {
+ if (WM_jobs_test(wm, scene, WM_JOB_TYPE_RENDER)) {
+ handle_event = B_STOPRENDER;
+ icon = ICON_SCENE;
+ break;
+ }
+ else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_COMPOSITE)) {
+ handle_event = B_STOPCOMPO;
+ icon = ICON_RENDERLAYERS;
+ break;
+ }
+ else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_OBJECT_BAKE_TEXTURE) ||
+ WM_jobs_test(wm, scene, WM_JOB_TYPE_OBJECT_BAKE)) {
+ /* Skip bake jobs in compositor to avoid compo header displaying
+ * progress bar which is not being updated (bake jobs only need
+ * to update NC_IMAGE context.
+ */
+ if (sa->spacetype != SPACE_NODE) {
+ handle_event = B_STOPOTHER;
+ icon = ICON_IMAGE;
+ break;
+ }
+ }
+ else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_DPAINT_BAKE)) {
+ handle_event = B_STOPOTHER;
+ icon = ICON_MOD_DYNAMICPAINT;
+ break;
+ }
+ else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_POINTCACHE)) {
+ handle_event = B_STOPOTHER;
+ icon = ICON_PHYSICS;
+ break;
+ }
+ else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_OBJECT_SIM_FLUID)) {
+ handle_event = B_STOPOTHER;
+ icon = ICON_MOD_FLUIDSIM;
+ break;
+ }
+ else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_OBJECT_SIM_OCEAN)) {
+ handle_event = B_STOPOTHER;
+ icon = ICON_MOD_OCEAN;
+ break;
+ }
+ else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY)) {
+ handle_event = B_STOPOTHER;
+ icon = ICON_NONE;
+ break;
+ }
+ }
+ owner = scene;
+ }
+
+ if (owner) {
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ bool active = !(G.is_break || WM_jobs_is_stopped(wm, owner));
+
+ uiLayout *row = uiLayoutRow(layout, false);
+ block = uiLayoutGetBlock(row);
+
+ /* get percentage done and set it as the UI text */
+ const float progress = WM_jobs_progress(wm, owner);
+ char text[8];
+ BLI_snprintf(text, 8, "%d%%", (int)(progress * 100));
+
+ const char *name = active ? WM_jobs_name(wm, owner) : "Canceling...";
+
+ /* job name and icon */
+ const int textwidth = UI_fontstyle_string_width(fstyle, name);
+ uiDefIconTextBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ icon,
+ name,
+ 0,
+ 0,
+ textwidth + UI_UNIT_X * 1.5f,
+ UI_UNIT_Y,
+ NULL,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ "");
+
+ /* stick progress bar and cancel button together */
+ row = uiLayoutRow(layout, true);
+ uiLayoutSetActive(row, active);
+ block = uiLayoutGetBlock(row);
+
+ {
+ struct ProgressTooltip_Store *tip_arg = MEM_mallocN(sizeof(*tip_arg), __func__);
+ tip_arg->wm = wm;
+ tip_arg->owner = owner;
+ uiBut *but_progress = uiDefIconTextBut(block,
+ UI_BTYPE_PROGRESS_BAR,
+ 0,
+ 0,
+ text,
+ UI_UNIT_X,
+ 0,
+ UI_UNIT_X * 6.0f,
+ UI_UNIT_Y,
+ NULL,
+ 0.0f,
+ 0.0f,
+ progress,
+ 0,
+ NULL);
+ UI_but_func_tooltip_set(but_progress, progress_tooltip_func, tip_arg);
+ }
+
+ if (!wm->is_interface_locked) {
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ handle_event,
+ ICON_PANEL_CLOSE,
+ "",
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0f,
+ 0.0f,
+ 0,
+ 0,
+ TIP_("Stop this job"));
+ }
+ }
+
+ if (screen->animtimer) {
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ B_STOPANIM,
+ ICON_CANCEL,
+ IFACE_("Anim Player"),
+ 0,
+ 0,
+ UI_UNIT_X * 5.0f,
+ UI_UNIT_Y,
+ NULL,
+ 0.0f,
+ 0.0f,
+ 0,
+ 0,
+ TIP_("Stop animation playback"));
+ }
}
/************************* Reports for Last Operator Template **************************/
void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
{
- ReportList *reports = CTX_wm_reports(C);
- Report *report = BKE_reports_last_displayable(reports);
- ReportTimerInfo *rti;
-
- uiLayout *ui_abs;
- uiBlock *block;
- uiBut *but;
- uiStyle *style = UI_style_get();
- int width;
- int icon;
-
- /* if the report display has timed out, don't show */
- if (!reports->reporttimer) {
- return;
- }
-
- rti = (ReportTimerInfo *)reports->reporttimer->customdata;
-
- if (!rti || rti->widthfac == 0.0f || !report) {
- return;
- }
-
- ui_abs = uiLayoutAbsolute(layout, false);
- block = uiLayoutGetBlock(ui_abs);
-
- UI_fontstyle_set(&style->widgetlabel);
- width = BLF_width(style->widgetlabel.uifont_id, report->message, report->len);
- width = min_ii((int)(rti->widthfac * width), width);
- width = max_ii(width, 10 * UI_DPI_FAC);
-
- /* make a box around the report to make it stand out */
- UI_block_align_begin(block);
- but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", 0, 0, UI_UNIT_X + 5, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
- /* set the report's bg color in but->col - UI_BTYPE_ROUNDBOX feature */
- rgba_float_to_uchar(but->col, rti->col);
-
- but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", UI_UNIT_X + 5, 0, UI_UNIT_X + width, UI_UNIT_Y,
- NULL, 0.0f, 0.0f, 0, 0, "");
- rgba_float_to_uchar(but->col, rti->col);
-
- UI_block_align_end(block);
-
- /* icon and report message on top */
- icon = UI_icon_from_report_type(report->type);
-
- /* XXX: temporary operator to dump all reports to a text block, but only if more than 1 report
- * to be shown instead of icon when appropriate...
- */
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
- if (reports->list.first != reports->list.last) {
- uiDefIconButO(block, UI_BTYPE_BUT, "UI_OT_reports_to_textblock", WM_OP_INVOKE_REGION_WIN, icon, 2, 0, UI_UNIT_X,
- UI_UNIT_Y, TIP_("Click to see the remaining reports in text block: 'Recent Reports'"));
- }
- else {
- uiDefIconBut(block, UI_BTYPE_LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
- }
-
- UI_block_emboss_set(block, UI_EMBOSS);
-
- uiDefBut(block, UI_BTYPE_LABEL, 0, report->message, UI_UNIT_X + 5, 0, UI_UNIT_X + width, UI_UNIT_Y,
- NULL, 0.0f, 0.0f, 0, 0, "");
+ ReportList *reports = CTX_wm_reports(C);
+ Report *report = BKE_reports_last_displayable(reports);
+ ReportTimerInfo *rti;
+
+ uiLayout *ui_abs;
+ uiBlock *block;
+ uiBut *but;
+ uiStyle *style = UI_style_get();
+ int width;
+ int icon;
+
+ /* if the report display has timed out, don't show */
+ if (!reports->reporttimer) {
+ return;
+ }
+
+ rti = (ReportTimerInfo *)reports->reporttimer->customdata;
+
+ if (!rti || rti->widthfac == 0.0f || !report) {
+ return;
+ }
+
+ ui_abs = uiLayoutAbsolute(layout, false);
+ block = uiLayoutGetBlock(ui_abs);
+
+ UI_fontstyle_set(&style->widgetlabel);
+ width = BLF_width(style->widgetlabel.uifont_id, report->message, report->len);
+ width = min_ii((int)(rti->widthfac * width), width);
+ width = max_ii(width, 10 * UI_DPI_FAC);
+
+ /* make a box around the report to make it stand out */
+ UI_block_align_begin(block);
+ but = uiDefBut(
+ block, UI_BTYPE_ROUNDBOX, 0, "", 0, 0, UI_UNIT_X + 5, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
+ /* set the report's bg color in but->col - UI_BTYPE_ROUNDBOX feature */
+ rgba_float_to_uchar(but->col, rti->col);
+
+ but = uiDefBut(block,
+ UI_BTYPE_ROUNDBOX,
+ 0,
+ "",
+ UI_UNIT_X + 5,
+ 0,
+ UI_UNIT_X + width,
+ UI_UNIT_Y,
+ NULL,
+ 0.0f,
+ 0.0f,
+ 0,
+ 0,
+ "");
+ rgba_float_to_uchar(but->col, rti->col);
+
+ UI_block_align_end(block);
+
+ /* icon and report message on top */
+ icon = UI_icon_from_report_type(report->type);
+
+ /* XXX: temporary operator to dump all reports to a text block, but only if more than 1 report
+ * to be shown instead of icon when appropriate...
+ */
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+
+ if (reports->list.first != reports->list.last) {
+ uiDefIconButO(block,
+ UI_BTYPE_BUT,
+ "UI_OT_reports_to_textblock",
+ WM_OP_INVOKE_REGION_WIN,
+ icon,
+ 2,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ TIP_("Click to see the remaining reports in text block: 'Recent Reports'"));
+ }
+ else {
+ uiDefIconBut(
+ block, UI_BTYPE_LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
+ }
+
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ report->message,
+ UI_UNIT_X + 5,
+ 0,
+ UI_UNIT_X + width,
+ UI_UNIT_Y,
+ NULL,
+ 0.0f,
+ 0.0f,
+ 0,
+ 0,
+ "");
}
-
void uiTemplateInputStatus(uiLayout *layout, struct bContext *C)
{
- wmWindow *win = CTX_wm_window(C);
- WorkSpace *workspace = CTX_wm_workspace(C);
-
- /* Workspace status text has priority. */
- if (workspace->status_text) {
- uiItemL(layout, workspace->status_text, ICON_NONE);
- return;
- }
-
- if (WM_window_modal_keymap_status_draw(C, win, layout)) {
- return;
- }
-
- /* Otherwise should cursor keymap status. */
- for (int i = 0; i < 3; i++) {
- uiLayout *box = uiLayoutRow(layout, false);
- uiLayout *col = uiLayoutColumn(box, false);
- uiLayout *row = uiLayoutRow(col, true);
- uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
-
- const char *msg = WM_window_cursor_keymap_status_get(win, i, 0);
- const char *msg_drag = WM_window_cursor_keymap_status_get(win, i, 1);
-
- if (msg || (msg_drag == NULL)) {
- uiItemL(row, msg ? msg : "", (ICON_MOUSE_LMB + i));
- }
-
- if (msg_drag) {
- uiItemL(row, msg_drag, (ICON_MOUSE_LMB_DRAG + i));
- }
-
- /* Use trick with empty string to keep icons in same position. */
- row = uiLayoutRow(col, false);
- uiItemL(row, " ", ICON_NONE);
- }
+ wmWindow *win = CTX_wm_window(C);
+ WorkSpace *workspace = CTX_wm_workspace(C);
+
+ /* Workspace status text has priority. */
+ if (workspace->status_text) {
+ uiItemL(layout, workspace->status_text, ICON_NONE);
+ return;
+ }
+
+ if (WM_window_modal_keymap_status_draw(C, win, layout)) {
+ return;
+ }
+
+ /* Otherwise should cursor keymap status. */
+ for (int i = 0; i < 3; i++) {
+ uiLayout *box = uiLayoutRow(layout, false);
+ uiLayout *col = uiLayoutColumn(box, false);
+ uiLayout *row = uiLayoutRow(col, true);
+ uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
+
+ const char *msg = WM_window_cursor_keymap_status_get(win, i, 0);
+ const char *msg_drag = WM_window_cursor_keymap_status_get(win, i, 1);
+
+ if (msg || (msg_drag == NULL)) {
+ uiItemL(row, msg ? msg : "", (ICON_MOUSE_LMB + i));
+ }
+
+ if (msg_drag) {
+ uiItemL(row, msg_drag, (ICON_MOUSE_LMB_DRAG + i));
+ }
+
+ /* Use trick with empty string to keep icons in same position. */
+ row = uiLayoutRow(col, false);
+ uiItemL(row, " ", ICON_NONE);
+ }
}
/********************************* Keymap *************************************/
static void keymap_item_modified(bContext *UNUSED(C), void *kmi_p, void *UNUSED(unused))
{
- wmKeyMapItem *kmi = (wmKeyMapItem *)kmi_p;
- WM_keyconfig_update_tag(NULL, kmi);
+ wmKeyMapItem *kmi = (wmKeyMapItem *)kmi_p;
+ WM_keyconfig_update_tag(NULL, kmi);
}
static void template_keymap_item_properties(uiLayout *layout, const char *title, PointerRNA *ptr)
{
- uiLayout *flow, *box, *row;
-
- uiItemS(layout);
-
- if (title) {
- uiItemL(layout, title, ICON_NONE);
- }
-
- flow = uiLayoutColumnFlow(layout, 2, false);
-
- RNA_STRUCT_BEGIN (ptr, prop)
- {
- const bool is_set = RNA_property_is_set(ptr, prop);
- uiBut *but;
-
- /* recurse for nested properties */
- if (RNA_property_type(prop) == PROP_POINTER) {
- PointerRNA propptr = RNA_property_pointer_get(ptr, prop);
-
- if (propptr.data && RNA_struct_is_a(propptr.type, &RNA_OperatorProperties)) {
- const char *name = RNA_property_ui_name(prop);
- template_keymap_item_properties(layout, name, &propptr);
- continue;
- }
- }
-
- box = uiLayoutBox(flow);
- uiLayoutSetActive(box, is_set);
- row = uiLayoutRow(box, false);
-
- /* property value */
- uiItemFullR(row, ptr, prop, -1, 0, 0, NULL, ICON_NONE);
-
- if (is_set) {
- /* unset operator */
- uiBlock *block = uiLayoutGetBlock(row);
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- but = uiDefIconButO(block, UI_BTYPE_BUT, "UI_OT_unset_property_button", WM_OP_EXEC_DEFAULT, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
- but->rnapoin = *ptr;
- but->rnaprop = prop;
- UI_block_emboss_set(block, UI_EMBOSS);
- }
- }
- RNA_STRUCT_END;
+ uiLayout *flow, *box, *row;
+
+ uiItemS(layout);
+
+ if (title) {
+ uiItemL(layout, title, ICON_NONE);
+ }
+
+ flow = uiLayoutColumnFlow(layout, 2, false);
+
+ RNA_STRUCT_BEGIN (ptr, prop) {
+ const bool is_set = RNA_property_is_set(ptr, prop);
+ uiBut *but;
+
+ /* recurse for nested properties */
+ if (RNA_property_type(prop) == PROP_POINTER) {
+ PointerRNA propptr = RNA_property_pointer_get(ptr, prop);
+
+ if (propptr.data && RNA_struct_is_a(propptr.type, &RNA_OperatorProperties)) {
+ const char *name = RNA_property_ui_name(prop);
+ template_keymap_item_properties(layout, name, &propptr);
+ continue;
+ }
+ }
+
+ box = uiLayoutBox(flow);
+ uiLayoutSetActive(box, is_set);
+ row = uiLayoutRow(box, false);
+
+ /* property value */
+ uiItemFullR(row, ptr, prop, -1, 0, 0, NULL, ICON_NONE);
+
+ if (is_set) {
+ /* unset operator */
+ uiBlock *block = uiLayoutGetBlock(row);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ but = uiDefIconButO(block,
+ UI_BTYPE_BUT,
+ "UI_OT_unset_property_button",
+ WM_OP_EXEC_DEFAULT,
+ ICON_X,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL);
+ but->rnapoin = *ptr;
+ but->rnaprop = prop;
+ UI_block_emboss_set(block, UI_EMBOSS);
+ }
+ }
+ RNA_STRUCT_END;
}
void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr)
{
- PointerRNA propptr = RNA_pointer_get(ptr, "properties");
-
- if (propptr.data) {
- uiBut *but = uiLayoutGetBlock(layout)->buttons.last;
-
- WM_operator_properties_sanitize(&propptr, false);
- template_keymap_item_properties(layout, NULL, &propptr);
-
- /* attach callbacks to compensate for missing properties update,
- * we don't know which keymap (item) is being modified there */
- for (; but; but = but->next) {
- /* operator buttons may store props for use (file selector, [#36492]) */
- if (but->rnaprop) {
- UI_but_func_set(but, keymap_item_modified, ptr->data, NULL);
-
- /* Otherwise the keymap will be re-generated which we're trying to edit,
- * see: T47685 */
- UI_but_flag_enable(but, UI_BUT_UPDATE_DELAY);
- }
- }
- }
+ PointerRNA propptr = RNA_pointer_get(ptr, "properties");
+
+ if (propptr.data) {
+ uiBut *but = uiLayoutGetBlock(layout)->buttons.last;
+
+ WM_operator_properties_sanitize(&propptr, false);
+ template_keymap_item_properties(layout, NULL, &propptr);
+
+ /* attach callbacks to compensate for missing properties update,
+ * we don't know which keymap (item) is being modified there */
+ for (; but; but = but->next) {
+ /* operator buttons may store props for use (file selector, [#36492]) */
+ if (but->rnaprop) {
+ UI_but_func_set(but, keymap_item_modified, ptr->data, NULL);
+
+ /* Otherwise the keymap will be re-generated which we're trying to edit,
+ * see: T47685 */
+ UI_but_flag_enable(but, UI_BUT_UPDATE_DELAY);
+ }
+ }
+ }
}
/********************************* Color management *************************************/
void uiTemplateColorspaceSettings(uiLayout *layout, PointerRNA *ptr, const char *propname)
{
- PropertyRNA *prop;
- PointerRNA colorspace_settings_ptr;
+ PropertyRNA *prop;
+ PointerRNA colorspace_settings_ptr;
- prop = RNA_struct_find_property(ptr, propname);
+ prop = RNA_struct_find_property(ptr, propname);
- if (!prop) {
- printf("%s: property not found: %s.%s\n",
- __func__, RNA_struct_identifier(ptr->type), propname);
- return;
- }
+ if (!prop) {
+ printf(
+ "%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
- colorspace_settings_ptr = RNA_property_pointer_get(ptr, prop);
+ colorspace_settings_ptr = RNA_property_pointer_get(ptr, prop);
- uiItemR(layout, &colorspace_settings_ptr, "name", 0, IFACE_("Color Space"), ICON_NONE);
+ uiItemR(layout, &colorspace_settings_ptr, "name", 0, IFACE_("Color Space"), ICON_NONE);
}
-void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr, const char *propname)
+void uiTemplateColormanagedViewSettings(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr,
+ const char *propname)
{
- PropertyRNA *prop;
- PointerRNA view_transform_ptr;
- uiLayout *col, *row;
- ColorManagedViewSettings *view_settings;
+ PropertyRNA *prop;
+ PointerRNA view_transform_ptr;
+ uiLayout *col, *row;
+ ColorManagedViewSettings *view_settings;
- prop = RNA_struct_find_property(ptr, propname);
+ prop = RNA_struct_find_property(ptr, propname);
- if (!prop) {
- printf("%s: property not found: %s.%s\n",
- __func__, RNA_struct_identifier(ptr->type), propname);
- return;
- }
+ if (!prop) {
+ printf(
+ "%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
- view_transform_ptr = RNA_property_pointer_get(ptr, prop);
- view_settings = view_transform_ptr.data;
+ view_transform_ptr = RNA_property_pointer_get(ptr, prop);
+ view_settings = view_transform_ptr.data;
- col = uiLayoutColumn(layout, false);
+ col = uiLayoutColumn(layout, false);
- row = uiLayoutRow(col, false);
- uiItemR(row, &view_transform_ptr, "view_transform", 0, IFACE_("View"), ICON_NONE);
+ row = uiLayoutRow(col, false);
+ uiItemR(row, &view_transform_ptr, "view_transform", 0, IFACE_("View"), ICON_NONE);
- col = uiLayoutColumn(layout, false);
- uiItemR(col, &view_transform_ptr, "exposure", 0, NULL, ICON_NONE);
- uiItemR(col, &view_transform_ptr, "gamma", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, &view_transform_ptr, "exposure", 0, NULL, ICON_NONE);
+ uiItemR(col, &view_transform_ptr, "gamma", 0, NULL, ICON_NONE);
- uiItemR(col, &view_transform_ptr, "look", 0, IFACE_("Look"), ICON_NONE);
+ uiItemR(col, &view_transform_ptr, "look", 0, IFACE_("Look"), ICON_NONE);
- col = uiLayoutColumn(layout, false);
- uiItemR(col, &view_transform_ptr, "use_curve_mapping", 0, NULL, ICON_NONE);
- if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) {
- uiTemplateCurveMapping(col, &view_transform_ptr, "curve_mapping", 'c', true, false, false, false);
- }
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, &view_transform_ptr, "use_curve_mapping", 0, NULL, ICON_NONE);
+ if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) {
+ uiTemplateCurveMapping(
+ col, &view_transform_ptr, "curve_mapping", 'c', true, false, false, false);
+ }
}
/********************************* Component Menu *************************************/
typedef struct ComponentMenuArgs {
- PointerRNA ptr;
- char propname[64]; /* XXX arbitrary */
+ PointerRNA ptr;
+ 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)
{
- ComponentMenuArgs *args = (ComponentMenuArgs *)args_v;
- uiBlock *block;
- uiLayout *layout;
-
- block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
- UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN);
-
- layout = uiLayoutColumn(UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, UI_style_get()), 0);
-
- uiItemR(layout, &args->ptr, args->propname, UI_ITEM_R_EXPAND, "", ICON_NONE);
-
- UI_block_bounds_set_normal(block, 6);
- UI_block_direction_set(block, UI_DIR_DOWN);
-
- return block;
+ ComponentMenuArgs *args = (ComponentMenuArgs *)args_v;
+ uiBlock *block;
+ uiLayout *layout;
+
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN);
+
+ layout = uiLayoutColumn(UI_block_layout(block,
+ UI_LAYOUT_VERTICAL,
+ UI_LAYOUT_PANEL,
+ 0,
+ 0,
+ UI_UNIT_X * 6,
+ UI_UNIT_Y,
+ 0,
+ UI_style_get()),
+ 0);
+
+ uiItemR(layout, &args->ptr, args->propname, UI_ITEM_R_EXPAND, "", ICON_NONE);
+
+ UI_block_bounds_set_normal(block, 6);
+ UI_block_direction_set(block, UI_DIR_DOWN);
+
+ return block;
}
-void uiTemplateComponentMenu(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *name)
+void uiTemplateComponentMenu(uiLayout *layout,
+ PointerRNA *ptr,
+ const char *propname,
+ const char *name)
{
- ComponentMenuArgs *args = MEM_callocN(sizeof(ComponentMenuArgs), "component menu template args");
- uiBlock *block;
- uiBut *but;
+ ComponentMenuArgs *args = MEM_callocN(sizeof(ComponentMenuArgs), "component menu template args");
+ uiBlock *block;
+ uiBut *but;
- args->ptr = *ptr;
- BLI_strncpy(args->propname, propname, sizeof(args->propname));
+ args->ptr = *ptr;
+ BLI_strncpy(args->propname, propname, sizeof(args->propname));
- block = uiLayoutGetBlock(layout);
- UI_block_align_begin(block);
+ block = uiLayoutGetBlock(layout);
+ UI_block_align_begin(block);
- but = uiDefBlockButN(block, component_menu, args, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, "");
- /* set rna directly, uiDefBlockButN doesn't do this */
- but->rnapoin = *ptr;
- but->rnaprop = RNA_struct_find_property(ptr, propname);
- but->rnaindex = 0;
+ but = uiDefBlockButN(block, component_menu, args, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, "");
+ /* set rna directly, uiDefBlockButN doesn't do this */
+ but->rnapoin = *ptr;
+ but->rnaprop = RNA_struct_find_property(ptr, propname);
+ but->rnaindex = 0;
- UI_block_align_end(block);
+ UI_block_align_end(block);
}
/************************* Node Socket Icon **************************/
void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float *color)
{
- uiBlock *block;
- uiBut *but;
+ uiBlock *block;
+ uiBut *but;
- block = uiLayoutGetBlock(layout);
- UI_block_align_begin(block);
+ block = uiLayoutGetBlock(layout);
+ UI_block_align_begin(block);
- /* XXX using explicit socket colors is not quite ideal.
- * Eventually it should be possible to use theme colors for this purpose,
- * but this requires a better design for extendable color palettes in user prefs.
- */
- but = uiDefBut(block, UI_BTYPE_NODE_SOCKET, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- rgba_float_to_uchar(but->col, color);
+ /* XXX using explicit socket colors is not quite ideal.
+ * Eventually it should be possible to use theme colors for this purpose,
+ * but this requires a better design for extendable color palettes in user prefs.
+ */
+ but = uiDefBut(
+ block, UI_BTYPE_NODE_SOCKET, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ rgba_float_to_uchar(but->col, color);
- UI_block_align_end(block);
+ UI_block_align_end(block);
}
/********************************* Cache File *********************************/
void uiTemplateCacheFile(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname)
{
- if (!ptr->data) {
- return;
- }
+ if (!ptr->data) {
+ return;
+ }
- PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
- if (!prop) {
- printf("%s: property not found: %s.%s\n",
- __func__, RNA_struct_identifier(ptr->type), propname);
- return;
- }
+ if (!prop) {
+ printf(
+ "%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
- if (RNA_property_type(prop) != PROP_POINTER) {
- printf("%s: expected pointer property for %s.%s\n",
- __func__, RNA_struct_identifier(ptr->type), propname);
- return;
- }
+ if (RNA_property_type(prop) != PROP_POINTER) {
+ printf("%s: expected pointer property for %s.%s\n",
+ __func__,
+ RNA_struct_identifier(ptr->type),
+ propname);
+ return;
+ }
- PointerRNA fileptr = RNA_property_pointer_get(ptr, prop);
- CacheFile *file = fileptr.data;
+ PointerRNA fileptr = RNA_property_pointer_get(ptr, prop);
+ CacheFile *file = fileptr.data;
- uiLayoutSetContextPointer(layout, "edit_cachefile", &fileptr);
+ uiLayoutSetContextPointer(layout, "edit_cachefile", &fileptr);
- uiTemplateID(layout, C, ptr, propname, NULL, "CACHEFILE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+ uiTemplateID(
+ layout, C, ptr, propname, NULL, "CACHEFILE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
- if (!file) {
- return;
- }
+ if (!file) {
+ return;
+ }
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
- uiLayout *row = uiLayoutRow(layout, false);
- uiBlock *block = uiLayoutGetBlock(row);
- uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("File Path:"), 0, 19, 145, 19, NULL, 0, 0, 0, 0, "");
+ uiLayout *row = uiLayoutRow(layout, false);
+ uiBlock *block = uiLayoutGetBlock(row);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("File Path:"), 0, 19, 145, 19, NULL, 0, 0, 0, 0, "");
- row = uiLayoutRow(layout, false);
- uiLayout *split = uiLayoutSplit(row, 0.0f, false);
- row = uiLayoutRow(split, true);
+ row = uiLayoutRow(layout, false);
+ uiLayout *split = uiLayoutSplit(row, 0.0f, false);
+ row = uiLayoutRow(split, true);
- uiItemR(row, &fileptr, "filepath", 0, "", ICON_NONE);
- uiItemO(row, "", ICON_FILE_REFRESH, "cachefile.reload");
+ uiItemR(row, &fileptr, "filepath", 0, "", ICON_NONE);
+ uiItemO(row, "", ICON_FILE_REFRESH, "cachefile.reload");
- row = uiLayoutRow(layout, false);
- uiItemR(row, &fileptr, "is_sequence", 0, "Is Sequence", ICON_NONE);
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, &fileptr, "is_sequence", 0, "Is Sequence", ICON_NONE);
- row = uiLayoutRow(layout, false);
- uiItemR(row, &fileptr, "override_frame", 0, "Override Frame", ICON_NONE);
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, &fileptr, "override_frame", 0, "Override Frame", ICON_NONE);
- row = uiLayoutRow(layout, false);
- uiLayoutSetEnabled(row, RNA_boolean_get(&fileptr, "override_frame"));
- uiItemR(row, &fileptr, "frame", 0, "Frame", ICON_NONE);
+ row = uiLayoutRow(layout, false);
+ uiLayoutSetEnabled(row, RNA_boolean_get(&fileptr, "override_frame"));
+ uiItemR(row, &fileptr, "frame", 0, "Frame", ICON_NONE);
- row = uiLayoutRow(layout, false);
- uiItemR(row, &fileptr, "frame_offset", 0, "Frame Offset", ICON_NONE);
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, &fileptr, "frame_offset", 0, "Frame Offset", ICON_NONE);
- row = uiLayoutRow(layout, false);
- uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE);
+ row = uiLayoutRow(layout, false);
+ uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE);
- row = uiLayoutRow(layout, false);
- uiLayoutSetEnabled(row, (sbuts->mainb == BCONTEXT_CONSTRAINT));
- uiItemR(row, &fileptr, "scale", 0, "Scale", ICON_NONE);
+ row = uiLayoutRow(layout, false);
+ uiLayoutSetEnabled(row, (sbuts->mainb == BCONTEXT_CONSTRAINT));
+ uiItemR(row, &fileptr, "scale", 0, "Scale", ICON_NONE);
- /* TODO: unused for now, so no need to expose. */
+ /* TODO: unused for now, so no need to expose. */
#if 0
- row = uiLayoutRow(layout, false);
- uiItemR(row, &fileptr, "forward_axis", 0, "Forward Axis", ICON_NONE);
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, &fileptr, "forward_axis", 0, "Forward Axis", ICON_NONE);
- row = uiLayoutRow(layout, false);
- uiItemR(row, &fileptr, "up_axis", 0, "Up Axis", ICON_NONE);
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, &fileptr, "up_axis", 0, "Up Axis", ICON_NONE);
#endif
}
@@ -5161,15 +6729,18 @@ void uiTemplateCacheFile(uiLayout *layout, bContext *C, PointerRNA *ptr, const c
int uiTemplateRecentFiles(uiLayout *layout, int rows)
{
- const RecentFile *recent;
- int i;
-
- for (recent = G.recent_files.first, i = 0; (i < rows) && (recent); recent = recent->next, i++) {
- const char *filename = BLI_path_basename(recent->filepath);
- uiItemStringO(layout, filename,
- BLO_has_bfile_extension(filename) ? ICON_FILE_BLEND : ICON_FILE_BACKUP,
- "WM_OT_open_mainfile", "filepath", recent->filepath);
- }
-
- return i;
+ const RecentFile *recent;
+ int i;
+
+ for (recent = G.recent_files.first, i = 0; (i < rows) && (recent); recent = recent->next, i++) {
+ const char *filename = BLI_path_basename(recent->filepath);
+ uiItemStringO(layout,
+ filename,
+ BLO_has_bfile_extension(filename) ? ICON_FILE_BLEND : ICON_FILE_BACKUP,
+ "WM_OT_open_mainfile",
+ "filepath",
+ recent->filepath);
+ }
+
+ return i;
}
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 915793445db..9920d4f1fa5 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -21,7 +21,6 @@
* \ingroup edinterface
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -51,109 +50,230 @@
#include "interface_intern.h"
-
/*************************** RNA Utilities ******************************/
-uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int index, const char *name, int icon, int x1, int y1, int x2, int y2)
+uiBut *uiDefAutoButR(uiBlock *block,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ int index,
+ const char *name,
+ int icon,
+ int x1,
+ int y1,
+ int x2,
+ int y2)
{
- uiBut *but = NULL;
-
- switch (RNA_property_type(prop)) {
- case PROP_BOOLEAN:
- {
- if (RNA_property_array_check(prop) && index == -1) {
- return NULL;
- }
-
- if (icon && name && name[0] == '\0') {
- but = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
- }
- else if (icon) {
- but = uiDefIconTextButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
- }
- else {
- but = uiDefButR_prop(block, UI_BTYPE_CHECKBOX, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
- }
- break;
- }
- case PROP_INT:
- case PROP_FLOAT:
- {
- if (RNA_property_array_check(prop) && index == -1) {
- if (ELEM(RNA_property_subtype(prop), PROP_COLOR, PROP_COLOR_GAMMA)) {
- but = uiDefButR_prop(block, UI_BTYPE_COLOR, 0, name, x1, y1, x2, y2, ptr, prop, -1, 0, 0, -1, -1, NULL);
- }
- else {
- return NULL;
- }
- }
- else if (RNA_property_subtype(prop) == PROP_PERCENTAGE || RNA_property_subtype(prop) == PROP_FACTOR) {
- but = uiDefButR_prop(block, UI_BTYPE_NUM_SLIDER, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
- }
- else {
- but = uiDefButR_prop(block, UI_BTYPE_NUM, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
- }
-
- if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) {
- UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE);
- }
- break;
- }
- case PROP_ENUM:
- if (icon && name && name[0] == '\0') {
- but = uiDefIconButR_prop(block, UI_BTYPE_MENU, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
- }
- else if (icon) {
- but = uiDefIconTextButR_prop(block, UI_BTYPE_MENU, 0, icon, NULL, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
- }
- else {
- but = uiDefButR_prop(block, UI_BTYPE_MENU, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
- }
- break;
- case PROP_STRING:
- if (icon && name && name[0] == '\0') {
- but = uiDefIconButR_prop(block, UI_BTYPE_TEXT, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
- }
- else if (icon) {
- but = uiDefIconTextButR_prop(block, UI_BTYPE_TEXT, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
- }
- else {
- but = uiDefButR_prop(block, UI_BTYPE_TEXT, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
- }
-
- if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) {
- /* TEXTEDIT_UPDATE is usually used for search buttons. For these we also want
- * the 'x' icon to clear search string, so setting VALUE_CLEAR flag, too. */
- UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE | UI_BUT_VALUE_CLEAR);
- }
- break;
- case PROP_POINTER:
- {
- if (icon == 0) {
- PointerRNA pptr = RNA_property_pointer_get(ptr, prop);
- icon = RNA_struct_ui_icon(pptr.type ? pptr.type : RNA_property_pointer_type(ptr, prop));
- }
- if (icon == ICON_DOT) {
- icon = 0;
- }
-
- but = uiDefIconTextButR_prop(block, UI_BTYPE_SEARCH_MENU, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
- break;
- }
- case PROP_COLLECTION:
- {
- char text[256];
- BLI_snprintf(text, sizeof(text), IFACE_("%d items"), RNA_property_collection_length(ptr, prop));
- but = uiDefBut(block, UI_BTYPE_LABEL, 0, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, NULL);
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- break;
- }
- default:
- but = NULL;
- break;
- }
-
- return but;
+ uiBut *but = NULL;
+
+ switch (RNA_property_type(prop)) {
+ case PROP_BOOLEAN: {
+ if (RNA_property_array_check(prop) && index == -1) {
+ return NULL;
+ }
+
+ if (icon && name && name[0] == '\0') {
+ but = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ icon,
+ x1,
+ y1,
+ x2,
+ y2,
+ ptr,
+ prop,
+ index,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ }
+ else if (icon) {
+ but = uiDefIconTextButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ icon,
+ name,
+ x1,
+ y1,
+ x2,
+ y2,
+ ptr,
+ prop,
+ index,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ }
+ else {
+ but = uiDefButR_prop(block,
+ UI_BTYPE_CHECKBOX,
+ 0,
+ name,
+ x1,
+ y1,
+ x2,
+ y2,
+ ptr,
+ prop,
+ index,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ }
+ break;
+ }
+ case PROP_INT:
+ case PROP_FLOAT: {
+ if (RNA_property_array_check(prop) && index == -1) {
+ if (ELEM(RNA_property_subtype(prop), PROP_COLOR, PROP_COLOR_GAMMA)) {
+ but = uiDefButR_prop(
+ block, UI_BTYPE_COLOR, 0, name, x1, y1, x2, y2, ptr, prop, -1, 0, 0, -1, -1, NULL);
+ }
+ else {
+ return NULL;
+ }
+ }
+ else if (RNA_property_subtype(prop) == PROP_PERCENTAGE ||
+ RNA_property_subtype(prop) == PROP_FACTOR) {
+ but = uiDefButR_prop(block,
+ UI_BTYPE_NUM_SLIDER,
+ 0,
+ name,
+ x1,
+ y1,
+ x2,
+ y2,
+ ptr,
+ prop,
+ index,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ }
+ else {
+ but = uiDefButR_prop(
+ block, UI_BTYPE_NUM, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ }
+
+ if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) {
+ UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE);
+ }
+ break;
+ }
+ case PROP_ENUM:
+ if (icon && name && name[0] == '\0') {
+ but = uiDefIconButR_prop(
+ block, UI_BTYPE_MENU, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ }
+ else if (icon) {
+ but = uiDefIconTextButR_prop(block,
+ UI_BTYPE_MENU,
+ 0,
+ icon,
+ NULL,
+ x1,
+ y1,
+ x2,
+ y2,
+ ptr,
+ prop,
+ index,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ }
+ else {
+ but = uiDefButR_prop(
+ block, UI_BTYPE_MENU, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ }
+ break;
+ case PROP_STRING:
+ if (icon && name && name[0] == '\0') {
+ but = uiDefIconButR_prop(
+ block, UI_BTYPE_TEXT, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ }
+ else if (icon) {
+ but = uiDefIconTextButR_prop(block,
+ UI_BTYPE_TEXT,
+ 0,
+ icon,
+ name,
+ x1,
+ y1,
+ x2,
+ y2,
+ ptr,
+ prop,
+ index,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ }
+ else {
+ but = uiDefButR_prop(
+ block, UI_BTYPE_TEXT, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ }
+
+ if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) {
+ /* TEXTEDIT_UPDATE is usually used for search buttons. For these we also want
+ * the 'x' icon to clear search string, so setting VALUE_CLEAR flag, too. */
+ UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE | UI_BUT_VALUE_CLEAR);
+ }
+ break;
+ case PROP_POINTER: {
+ if (icon == 0) {
+ PointerRNA pptr = RNA_property_pointer_get(ptr, prop);
+ icon = RNA_struct_ui_icon(pptr.type ? pptr.type : RNA_property_pointer_type(ptr, prop));
+ }
+ if (icon == ICON_DOT) {
+ icon = 0;
+ }
+
+ but = uiDefIconTextButR_prop(block,
+ UI_BTYPE_SEARCH_MENU,
+ 0,
+ icon,
+ name,
+ x1,
+ y1,
+ x2,
+ y2,
+ ptr,
+ prop,
+ index,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ break;
+ }
+ case PROP_COLLECTION: {
+ char text[256];
+ BLI_snprintf(
+ text, sizeof(text), IFACE_("%d items"), RNA_property_collection_length(ptr, prop));
+ but = uiDefBut(block, UI_BTYPE_LABEL, 0, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, NULL);
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ break;
+ }
+ default:
+ but = NULL;
+ break;
+ }
+
+ return but;
}
/**
@@ -162,225 +282,227 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
*
* \param prop_activate_init: Property to activate on initial popup (#UI_BUT_ACTIVATE_ON_INIT).
*/
-eAutoPropButsReturn uiDefAutoButsRNA(
- uiLayout *layout, PointerRNA *ptr,
- bool (*check_prop)(PointerRNA *ptr, PropertyRNA *prop, void *user_data), void *user_data,
- PropertyRNA *prop_activate_init,
- const eButLabelAlign label_align, const bool compact)
+eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout,
+ PointerRNA *ptr,
+ bool (*check_prop)(PointerRNA *ptr,
+ PropertyRNA *prop,
+ void *user_data),
+ void *user_data,
+ PropertyRNA *prop_activate_init,
+ const eButLabelAlign label_align,
+ const bool compact)
{
- eAutoPropButsReturn return_info = UI_PROP_BUTS_NONE_ADDED;
- uiLayout *split, *col;
- const char *name;
-
- RNA_STRUCT_BEGIN (ptr, prop)
- {
- const int flag = RNA_property_flag(prop);
-
- if (flag & PROP_HIDDEN) {
- continue;
- }
- if (check_prop && check_prop(ptr, prop, user_data) == 0) {
- return_info |= UI_PROP_BUTS_ANY_FAILED_CHECK;
- continue;
- }
-
- const PropertyType type = RNA_property_type(prop);
- switch (label_align) {
- case UI_BUT_LABEL_ALIGN_COLUMN:
- case UI_BUT_LABEL_ALIGN_SPLIT_COLUMN:
- {
- const bool is_boolean = (type == PROP_BOOLEAN && !RNA_property_array_check(prop));
-
- name = RNA_property_ui_name(prop);
-
- if (label_align == UI_BUT_LABEL_ALIGN_COLUMN) {
- col = uiLayoutColumn(layout, true);
-
- if (!is_boolean) {
- uiItemL(col, name, ICON_NONE);
- }
- }
- 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);
- }
-
- /* 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:
- default:
- col = layout;
- name = NULL; /* no smart label alignment, show default name with button */
- break;
- }
-
- /* Only buttons that can be edited as text. */
- const bool use_activate_init = (
- (prop == prop_activate_init) &&
- (ELEM(type, PROP_STRING, PROP_INT, PROP_FLOAT)));
-
- if (use_activate_init) {
- uiLayoutSetActivateInit(col, true);
- }
-
- uiItemFullR(col, ptr, prop, -1, 0, compact ? UI_ITEM_R_COMPACT : 0, name, ICON_NONE);
- return_info &= ~UI_PROP_BUTS_NONE_ADDED;
-
- if (use_activate_init) {
- uiLayoutSetActivateInit(col, false);
- }
-
- }
- RNA_STRUCT_END;
-
- return return_info;
+ eAutoPropButsReturn return_info = UI_PROP_BUTS_NONE_ADDED;
+ uiLayout *split, *col;
+ const char *name;
+
+ RNA_STRUCT_BEGIN (ptr, prop) {
+ const int flag = RNA_property_flag(prop);
+
+ if (flag & PROP_HIDDEN) {
+ continue;
+ }
+ if (check_prop && check_prop(ptr, prop, user_data) == 0) {
+ return_info |= UI_PROP_BUTS_ANY_FAILED_CHECK;
+ continue;
+ }
+
+ const PropertyType type = RNA_property_type(prop);
+ switch (label_align) {
+ case UI_BUT_LABEL_ALIGN_COLUMN:
+ case UI_BUT_LABEL_ALIGN_SPLIT_COLUMN: {
+ const bool is_boolean = (type == PROP_BOOLEAN && !RNA_property_array_check(prop));
+
+ name = RNA_property_ui_name(prop);
+
+ if (label_align == UI_BUT_LABEL_ALIGN_COLUMN) {
+ col = uiLayoutColumn(layout, true);
+
+ if (!is_boolean) {
+ uiItemL(col, name, ICON_NONE);
+ }
+ }
+ 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);
+ }
+
+ /* 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:
+ default:
+ col = layout;
+ name = NULL; /* no smart label alignment, show default name with button */
+ break;
+ }
+
+ /* Only buttons that can be edited as text. */
+ const bool use_activate_init = ((prop == prop_activate_init) &&
+ (ELEM(type, PROP_STRING, PROP_INT, PROP_FLOAT)));
+
+ if (use_activate_init) {
+ uiLayoutSetActivateInit(col, true);
+ }
+
+ uiItemFullR(col, ptr, prop, -1, 0, compact ? UI_ITEM_R_COMPACT : 0, name, ICON_NONE);
+ return_info &= ~UI_PROP_BUTS_NONE_ADDED;
+
+ if (use_activate_init) {
+ uiLayoutSetActivateInit(col, false);
+ }
+ }
+ RNA_STRUCT_END;
+
+ return return_info;
}
/* *** RNA collection search menu *** */
typedef struct CollItemSearch {
- struct CollItemSearch *next, *prev;
- void *data;
- char *name;
- int index;
- int iconid;
+ struct CollItemSearch *next, *prev;
+ void *data;
+ char *name;
+ int index;
+ int iconid;
} CollItemSearch;
static int sort_search_items_list(const void *a, const void *b)
{
- const CollItemSearch *cis1 = a;
- const CollItemSearch *cis2 = b;
-
- if (BLI_strcasecmp(cis1->name, cis2->name) > 0) {
- return 1;
- }
- else {
- return 0;
- }
+ const CollItemSearch *cis1 = a;
+ const CollItemSearch *cis2 = b;
+
+ if (BLI_strcasecmp(cis1->name, cis2->name) > 0) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
-void ui_rna_collection_search_cb(const struct bContext *C, void *arg, const char *str, uiSearchItems *items)
+void ui_rna_collection_search_cb(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));
-
- /* build a temporary list of relevant items first */
- RNA_PROP_BEGIN (&data->search_ptr, itemptr, data->search_prop)
- {
-
- if (flag & PROP_ID_SELF_CHECK) {
- if (itemptr.data == data->target_ptr.id.data) {
- continue;
- }
- }
-
- /* use filter */
- if (RNA_property_type(data->target_prop) == PROP_POINTER) {
- if (RNA_property_pointer_poll(&data->target_ptr, data->target_prop, &itemptr) == 0) {
- continue;
- }
- }
-
- name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL); /* could use the string length here */
- iconid = 0;
- if (itemptr.type && RNA_struct_is_ID(itemptr.type)) {
- iconid = ui_id_icon_get(C, itemptr.data, false);
- }
-
- 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->index = i;
- cis->iconid = iconid;
- BLI_addtail(items_list, cis);
- }
- MEM_freeN(name);
- }
-
- i++;
- }
- RNA_PROP_END;
-
- BLI_listbase_sort(items_list, sort_search_items_list);
-
- /* 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) {
- break;
- }
- }
-
- for (cis = items_list->first; cis; cis = cis->next) {
- MEM_freeN(cis->name);
- }
- BLI_freelistN(items_list);
- MEM_freeN(items_list);
+ 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));
+
+ /* build a temporary list of relevant items first */
+ RNA_PROP_BEGIN (&data->search_ptr, itemptr, data->search_prop) {
+
+ if (flag & PROP_ID_SELF_CHECK) {
+ if (itemptr.data == data->target_ptr.id.data) {
+ continue;
+ }
+ }
+
+ /* use filter */
+ if (RNA_property_type(data->target_prop) == PROP_POINTER) {
+ if (RNA_property_pointer_poll(&data->target_ptr, data->target_prop, &itemptr) == 0) {
+ continue;
+ }
+ }
+
+ name = RNA_struct_name_get_alloc(
+ &itemptr, NULL, 0, NULL); /* could use the string length here */
+ iconid = 0;
+ if (itemptr.type && RNA_struct_is_ID(itemptr.type)) {
+ iconid = ui_id_icon_get(C, itemptr.data, false);
+ }
+
+ 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->index = i;
+ cis->iconid = iconid;
+ BLI_addtail(items_list, cis);
+ }
+ MEM_freeN(name);
+ }
+
+ i++;
+ }
+ RNA_PROP_END;
+
+ BLI_listbase_sort(items_list, sort_search_items_list);
+
+ /* 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) {
+ break;
+ }
+ }
+
+ for (cis = items_list->first; cis; cis = cis->next) {
+ MEM_freeN(cis->name);
+ }
+ BLI_freelistN(items_list);
+ MEM_freeN(items_list);
}
-
/***************************** ID Utilities *******************************/
int UI_icon_from_id(ID *id)
{
- Object *ob;
- PointerRNA ptr;
- short idcode;
+ Object *ob;
+ PointerRNA ptr;
+ short idcode;
- if (id == NULL) {
- return ICON_NONE;
- }
+ if (id == NULL) {
+ return ICON_NONE;
+ }
- idcode = GS(id->name);
+ idcode = GS(id->name);
- /* exception for objects */
- if (idcode == ID_OB) {
- ob = (Object *)id;
+ /* exception for objects */
+ if (idcode == ID_OB) {
+ ob = (Object *)id;
- if (ob->type == OB_EMPTY) {
- return ICON_EMPTY_DATA;
- }
- else {
- return UI_icon_from_id(ob->data);
- }
- }
+ if (ob->type == OB_EMPTY) {
+ return ICON_EMPTY_DATA;
+ }
+ else {
+ return UI_icon_from_id(ob->data);
+ }
+ }
- /* otherwise get it through RNA, creating the pointer
- * will set the right type, also with subclassing */
- RNA_id_pointer_create(id, &ptr);
+ /* otherwise get it through RNA, creating the pointer
+ * will set the right type, also with subclassing */
+ RNA_id_pointer_create(id, &ptr);
- return (ptr.type) ? RNA_struct_ui_icon(ptr.type) : ICON_NONE;
+ return (ptr.type) ? RNA_struct_ui_icon(ptr.type) : ICON_NONE;
}
/* see: report_type_str */
int UI_icon_from_report_type(int type)
{
- if (type & RPT_ERROR_ALL) {
- return ICON_ERROR;
- }
- else if (type & RPT_WARNING_ALL) {
- return ICON_ERROR;
- }
- else if (type & RPT_INFO_ALL) {
- return ICON_INFO;
- }
- else {
- return ICON_NONE;
- }
+ if (type & RPT_ERROR_ALL) {
+ return ICON_ERROR;
+ }
+ else if (type & RPT_WARNING_ALL) {
+ return ICON_ERROR;
+ }
+ else if (type & RPT_INFO_ALL) {
+ return ICON_INFO;
+ }
+ else {
+ return ICON_NONE;
+ }
}
/********************************** Misc **************************************/
@@ -390,84 +512,86 @@ int UI_icon_from_report_type(int type)
*/
int UI_calc_float_precision(int prec, double value)
{
- static const double pow10_neg[UI_PRECISION_FLOAT_MAX + 1] = {1e0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6};
- static const double max_pow = 10000000.0; /* pow(10, UI_PRECISION_FLOAT_MAX) */
-
- BLI_assert(prec <= UI_PRECISION_FLOAT_MAX);
- BLI_assert(fabs(pow10_neg[prec] - pow(10, -prec)) < 1e-16);
-
- /* check on the number of decimal places need to display the number, 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);
- if ((value < pow10_neg[prec]) && (value > (1.0 / max_pow))) {
- int value_i = (int)((value * max_pow) + 0.5);
- if (value_i != 0) {
- const int prec_span = 3; /* show: 0.01001, 5 would allow 0.0100001 for eg. */
- int test_prec;
- int prec_min = -1;
- int dec_flag = 0;
- int i = UI_PRECISION_FLOAT_MAX;
- while (i && value_i) {
- if (value_i % 10) {
- dec_flag |= 1 << i;
- prec_min = i;
- }
- value_i /= 10;
- i--;
- }
-
- /* even though its a small value, if the second last digit is not 0, use it */
- test_prec = prec_min;
-
- dec_flag = (dec_flag >> (prec_min + 1)) & ((1 << prec_span) - 1);
-
- while (dec_flag) {
- test_prec++;
- dec_flag = dec_flag >> 1;
- }
-
- if (test_prec > prec) {
- prec = test_prec;
- }
- }
- }
-
- CLAMP(prec, 0, UI_PRECISION_FLOAT_MAX);
-
- return prec;
+ static const double pow10_neg[UI_PRECISION_FLOAT_MAX + 1] = {
+ 1e0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6};
+ static const double max_pow = 10000000.0; /* pow(10, UI_PRECISION_FLOAT_MAX) */
+
+ BLI_assert(prec <= UI_PRECISION_FLOAT_MAX);
+ BLI_assert(fabs(pow10_neg[prec] - pow(10, -prec)) < 1e-16);
+
+ /* check on the number of decimal places need to display the number, 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);
+ if ((value < pow10_neg[prec]) && (value > (1.0 / max_pow))) {
+ int value_i = (int)((value * max_pow) + 0.5);
+ if (value_i != 0) {
+ const int prec_span = 3; /* show: 0.01001, 5 would allow 0.0100001 for eg. */
+ int test_prec;
+ int prec_min = -1;
+ int dec_flag = 0;
+ int i = UI_PRECISION_FLOAT_MAX;
+ while (i && value_i) {
+ if (value_i % 10) {
+ dec_flag |= 1 << i;
+ prec_min = i;
+ }
+ value_i /= 10;
+ i--;
+ }
+
+ /* even though its a small value, if the second last digit is not 0, use it */
+ test_prec = prec_min;
+
+ dec_flag = (dec_flag >> (prec_min + 1)) & ((1 << prec_span) - 1);
+
+ while (dec_flag) {
+ test_prec++;
+ dec_flag = dec_flag >> 1;
+ }
+
+ if (test_prec > prec) {
+ prec = test_prec;
+ }
+ }
+ }
+
+ CLAMP(prec, 0, UI_PRECISION_FLOAT_MAX);
+
+ return prec;
}
bool UI_but_online_manual_id(const uiBut *but, char *r_str, size_t maxlength)
{
- if (but->rnapoin.id.data && but->rnapoin.data && but->rnaprop) {
- BLI_snprintf(
- r_str, maxlength, "%s.%s", RNA_struct_identifier(but->rnapoin.type),
- RNA_property_identifier(but->rnaprop));
- return true;
- }
- else if (but->optype) {
- WM_operator_py_idname(r_str, but->optype->idname);
- return true;
- }
-
- *r_str = '\0';
- return false;
+ if (but->rnapoin.id.data && but->rnapoin.data && but->rnaprop) {
+ BLI_snprintf(r_str,
+ maxlength,
+ "%s.%s",
+ RNA_struct_identifier(but->rnapoin.type),
+ RNA_property_identifier(but->rnaprop));
+ return true;
+ }
+ else if (but->optype) {
+ WM_operator_py_idname(r_str, but->optype->idname);
+ return true;
+ }
+
+ *r_str = '\0';
+ return false;
}
bool UI_but_online_manual_id_from_active(const struct bContext *C, char *r_str, size_t maxlength)
{
- uiBut *but = UI_context_active_but_get(C);
+ uiBut *but = UI_context_active_but_get(C);
- if (but) {
- return UI_but_online_manual_id(but, r_str, maxlength);
- }
+ if (but) {
+ return UI_but_online_manual_id(but, r_str, maxlength);
+ }
- *r_str = '\0';
- return false;
+ *r_str = '\0';
+ return false;
}
-
/* -------------------------------------------------------------------- */
/* Modal Button Store API */
@@ -481,14 +605,14 @@ bool UI_but_online_manual_id_from_active(const struct bContext *C, char *r_str,
* \{ */
struct uiButStore {
- struct uiButStore *next, *prev;
- uiBlock *block;
- ListBase items;
+ struct uiButStore *next, *prev;
+ uiBlock *block;
+ ListBase items;
};
struct uiButStoreElem {
- struct uiButStoreElem *next, *prev;
- uiBut **but_p;
+ struct uiButStoreElem *next, *prev;
+ uiBut **but_p;
};
/**
@@ -496,78 +620,77 @@ struct uiButStoreElem {
*/
uiButStore *UI_butstore_create(uiBlock *block)
{
- uiButStore *bs_handle = MEM_callocN(sizeof(uiButStore), __func__);
+ uiButStore *bs_handle = MEM_callocN(sizeof(uiButStore), __func__);
- bs_handle->block = block;
- BLI_addtail(&block->butstore, bs_handle);
+ bs_handle->block = block;
+ BLI_addtail(&block->butstore, bs_handle);
- return bs_handle;
+ return bs_handle;
}
void UI_butstore_free(uiBlock *block, uiButStore *bs_handle)
{
- /* Workaround for button store being moved into new block,
- * which then can't use the previous buttons state ('ui_but_update_from_old_block' fails to find a match),
- * keeping the active button in the old block holding a reference to the button-state in the new block: see T49034.
- *
- * Ideally we would manage moving the 'uiButStore', keeping a correct state.
- * All things considered this is the most straightforward fix - Campbell.
- */
- if (block != bs_handle->block && bs_handle->block != NULL) {
- block = bs_handle->block;
- }
-
- BLI_freelistN(&bs_handle->items);
- BLI_remlink(&block->butstore, bs_handle);
-
- MEM_freeN(bs_handle);
+ /* Workaround for button store being moved into new block,
+ * which then can't use the previous buttons state ('ui_but_update_from_old_block' fails to find a match),
+ * keeping the active button in the old block holding a reference to the button-state in the new block: see T49034.
+ *
+ * Ideally we would manage moving the 'uiButStore', keeping a correct state.
+ * All things considered this is the most straightforward fix - Campbell.
+ */
+ if (block != bs_handle->block && bs_handle->block != NULL) {
+ block = bs_handle->block;
+ }
+
+ BLI_freelistN(&bs_handle->items);
+ BLI_remlink(&block->butstore, bs_handle);
+
+ MEM_freeN(bs_handle);
}
bool UI_butstore_is_valid(uiButStore *bs)
{
- return (bs->block != NULL);
+ return (bs->block != NULL);
}
bool UI_butstore_is_registered(uiBlock *block, uiBut *but)
{
- uiButStore *bs_handle;
+ uiButStore *bs_handle;
- for (bs_handle = block->butstore.first; bs_handle; bs_handle = bs_handle->next) {
- uiButStoreElem *bs_elem;
+ for (bs_handle = block->butstore.first; bs_handle; bs_handle = bs_handle->next) {
+ uiButStoreElem *bs_elem;
- for (bs_elem = bs_handle->items.first; bs_elem; bs_elem = bs_elem->next) {
- if (*bs_elem->but_p == but) {
- return true;
- }
- }
- }
+ for (bs_elem = bs_handle->items.first; bs_elem; bs_elem = bs_elem->next) {
+ if (*bs_elem->but_p == but) {
+ return true;
+ }
+ }
+ }
- return false;
+ return false;
}
void UI_butstore_register(uiButStore *bs_handle, uiBut **but_p)
{
- uiButStoreElem *bs_elem = MEM_callocN(sizeof(uiButStoreElem), __func__);
- BLI_assert(*but_p);
- bs_elem->but_p = but_p;
-
- BLI_addtail(&bs_handle->items, bs_elem);
+ uiButStoreElem *bs_elem = MEM_callocN(sizeof(uiButStoreElem), __func__);
+ BLI_assert(*but_p);
+ bs_elem->but_p = but_p;
+ BLI_addtail(&bs_handle->items, bs_elem);
}
void UI_butstore_unregister(uiButStore *bs_handle, uiBut **but_p)
{
- uiButStoreElem *bs_elem, *bs_elem_next;
+ uiButStoreElem *bs_elem, *bs_elem_next;
- for (bs_elem = bs_handle->items.first; bs_elem; bs_elem = bs_elem_next) {
- bs_elem_next = bs_elem->next;
- if (bs_elem->but_p == but_p) {
- BLI_remlink(&bs_handle->items, bs_elem);
- MEM_freeN(bs_elem);
- }
- }
+ for (bs_elem = bs_handle->items.first; bs_elem; bs_elem = bs_elem_next) {
+ bs_elem_next = bs_elem->next;
+ if (bs_elem->but_p == but_p) {
+ BLI_remlink(&bs_handle->items, bs_elem);
+ MEM_freeN(bs_elem);
+ }
+ }
- BLI_assert(0);
+ BLI_assert(0);
}
/**
@@ -575,20 +698,20 @@ void UI_butstore_unregister(uiButStore *bs_handle, uiBut **but_p)
*/
bool UI_butstore_register_update(uiBlock *block, uiBut *but_dst, const uiBut *but_src)
{
- uiButStore *bs_handle;
- bool found = false;
-
- for (bs_handle = block->butstore.first; bs_handle; bs_handle = bs_handle->next) {
- uiButStoreElem *bs_elem;
- for (bs_elem = bs_handle->items.first; bs_elem; bs_elem = bs_elem->next) {
- if (*bs_elem->but_p == but_src) {
- *bs_elem->but_p = but_dst;
- found = true;
- }
- }
- }
-
- return found;
+ uiButStore *bs_handle;
+ bool found = false;
+
+ for (bs_handle = block->butstore.first; bs_handle; bs_handle = bs_handle->next) {
+ uiButStoreElem *bs_elem;
+ for (bs_elem = bs_handle->items.first; bs_elem; bs_elem = bs_elem->next) {
+ if (*bs_elem->but_p == but_src) {
+ *bs_elem->but_p = but_dst;
+ found = true;
+ }
+ }
+ }
+
+ return found;
}
/**
@@ -596,17 +719,17 @@ bool UI_butstore_register_update(uiBlock *block, uiBut *but_dst, const uiBut *bu
*/
void UI_butstore_clear(uiBlock *block)
{
- uiButStore *bs_handle;
+ uiButStore *bs_handle;
- for (bs_handle = block->butstore.first; bs_handle; bs_handle = bs_handle->next) {
- uiButStoreElem *bs_elem;
+ for (bs_handle = block->butstore.first; bs_handle; bs_handle = bs_handle->next) {
+ uiButStoreElem *bs_elem;
- bs_handle->block = NULL;
+ bs_handle->block = NULL;
- for (bs_elem = bs_handle->items.first; bs_elem; bs_elem = bs_elem->next) {
- *bs_elem->but_p = NULL;
- }
- }
+ for (bs_elem = bs_handle->items.first; bs_elem; bs_elem = bs_elem->next) {
+ *bs_elem->but_p = NULL;
+ }
+ }
}
/**
@@ -614,45 +737,44 @@ void UI_butstore_clear(uiBlock *block)
*/
void UI_butstore_update(uiBlock *block)
{
- uiButStore *bs_handle;
-
- /* 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);
- }
- }
-
- if (LIKELY(block->butstore.first == NULL)) {
- return;
- }
-
- /* warning, loop-in-loop, in practice we only store <10 buttons at a time,
- * so this isn't going to be a problem, if that changes old-new mapping can be cached first */
- for (bs_handle = block->butstore.first; bs_handle; bs_handle = bs_handle->next) {
-
- BLI_assert((bs_handle->block == NULL) ||
- (bs_handle->block == block) ||
- (block->oldblock && block->oldblock == bs_handle->block));
-
- if (bs_handle->block == block->oldblock) {
- uiButStoreElem *bs_elem;
-
- bs_handle->block = block;
-
- for (bs_elem = bs_handle->items.first; bs_elem; bs_elem = bs_elem->next) {
- if (*bs_elem->but_p) {
- uiBut *but_new = ui_but_find_new(block, *bs_elem->but_p);
-
- /* can be NULL if the buttons removed,
- * note: we could allow passing in a callback when buttons are removed
- * so the caller can cleanup */
- *bs_elem->but_p = but_new;
- }
- }
- }
- }
+ uiButStore *bs_handle;
+
+ /* 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);
+ }
+ }
+
+ if (LIKELY(block->butstore.first == NULL)) {
+ return;
+ }
+
+ /* warning, loop-in-loop, in practice we only store <10 buttons at a time,
+ * so this isn't going to be a problem, if that changes old-new mapping can be cached first */
+ for (bs_handle = block->butstore.first; bs_handle; bs_handle = bs_handle->next) {
+
+ BLI_assert((bs_handle->block == NULL) || (bs_handle->block == block) ||
+ (block->oldblock && block->oldblock == bs_handle->block));
+
+ if (bs_handle->block == block->oldblock) {
+ uiButStoreElem *bs_elem;
+
+ bs_handle->block = block;
+
+ for (bs_elem = bs_handle->items.first; bs_elem; bs_elem = bs_elem->next) {
+ if (*bs_elem->but_p) {
+ uiBut *but_new = ui_but_find_new(block, *bs_elem->but_p);
+
+ /* can be NULL if the buttons removed,
+ * note: we could allow passing in a callback when buttons are removed
+ * so the caller can cleanup */
+ *bs_elem->but_p = but_new;
+ }
+ }
+ }
+ }
}
/** \} */
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 6528faca265..e18a2e6068a 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -64,73 +64,67 @@
/* visual types for drawing */
/* for time being separated from functional types */
typedef enum {
- /* default */
- UI_WTYPE_REGULAR,
-
- /* standard set */
- UI_WTYPE_LABEL,
- UI_WTYPE_TOGGLE,
- UI_WTYPE_CHECKBOX,
- UI_WTYPE_RADIO,
- UI_WTYPE_NUMBER,
- UI_WTYPE_SLIDER,
- UI_WTYPE_EXEC,
- UI_WTYPE_TOOLBAR_ITEM,
- UI_WTYPE_TAB,
- UI_WTYPE_TOOLTIP,
-
- /* strings */
- UI_WTYPE_NAME,
- UI_WTYPE_NAME_LINK,
- UI_WTYPE_POINTER_LINK,
- UI_WTYPE_FILENAME,
-
- /* menus */
- UI_WTYPE_MENU_RADIO,
- UI_WTYPE_MENU_ICON_RADIO,
- UI_WTYPE_MENU_POINTER_LINK,
- UI_WTYPE_MENU_NODE_LINK,
-
- UI_WTYPE_PULLDOWN,
- UI_WTYPE_MENU_ITEM,
- UI_WTYPE_MENU_ITEM_RADIAL,
- UI_WTYPE_MENU_BACK,
-
- /* specials */
- UI_WTYPE_ICON,
- UI_WTYPE_ICON_LABEL,
- UI_WTYPE_SWATCH,
- UI_WTYPE_RGB_PICKER,
- UI_WTYPE_UNITVEC,
- UI_WTYPE_BOX,
- UI_WTYPE_SCROLL,
- UI_WTYPE_LISTITEM,
- UI_WTYPE_PROGRESSBAR,
+ /* default */
+ UI_WTYPE_REGULAR,
+
+ /* standard set */
+ UI_WTYPE_LABEL,
+ UI_WTYPE_TOGGLE,
+ UI_WTYPE_CHECKBOX,
+ UI_WTYPE_RADIO,
+ UI_WTYPE_NUMBER,
+ UI_WTYPE_SLIDER,
+ UI_WTYPE_EXEC,
+ UI_WTYPE_TOOLBAR_ITEM,
+ UI_WTYPE_TAB,
+ UI_WTYPE_TOOLTIP,
+
+ /* strings */
+ UI_WTYPE_NAME,
+ UI_WTYPE_NAME_LINK,
+ UI_WTYPE_POINTER_LINK,
+ UI_WTYPE_FILENAME,
+
+ /* menus */
+ UI_WTYPE_MENU_RADIO,
+ UI_WTYPE_MENU_ICON_RADIO,
+ UI_WTYPE_MENU_POINTER_LINK,
+ UI_WTYPE_MENU_NODE_LINK,
+
+ UI_WTYPE_PULLDOWN,
+ UI_WTYPE_MENU_ITEM,
+ UI_WTYPE_MENU_ITEM_RADIAL,
+ UI_WTYPE_MENU_BACK,
+
+ /* specials */
+ UI_WTYPE_ICON,
+ UI_WTYPE_ICON_LABEL,
+ UI_WTYPE_SWATCH,
+ UI_WTYPE_RGB_PICKER,
+ UI_WTYPE_UNITVEC,
+ UI_WTYPE_BOX,
+ UI_WTYPE_SCROLL,
+ UI_WTYPE_LISTITEM,
+ UI_WTYPE_PROGRESSBAR,
} uiWidgetTypeEnum;
-
/* Button state argument shares bits with 'uiBut.flag'.
* reuse flags that aren't needed for drawing to avoid collision. */
enum {
- /* Show that holding the button opens a menu. */
- UI_STATE_HOLD_ACTION = UI_BUT_UPDATE_DELAY,
- UI_STATE_TEXT_INPUT = UI_BUT_UNDO,
- UI_STATE_ACTIVE_LEFT = UI_BUT_VALUE_CLEAR,
- UI_STATE_ACTIVE_RIGHT = UI_BUT_TEXTEDIT_UPDATE,
- UI_STATE_TEXT_BEFORE_WIDGET = UI_BUT_IMMEDIATE,
-
- UI_STATE_FLAGS_ALL = (
- UI_STATE_HOLD_ACTION |
- UI_STATE_TEXT_INPUT |
- UI_STATE_ACTIVE_LEFT |
- UI_STATE_ACTIVE_RIGHT |
- UI_STATE_TEXT_BEFORE_WIDGET),
+ /* Show that holding the button opens a menu. */
+ UI_STATE_HOLD_ACTION = UI_BUT_UPDATE_DELAY,
+ UI_STATE_TEXT_INPUT = UI_BUT_UNDO,
+ UI_STATE_ACTIVE_LEFT = UI_BUT_VALUE_CLEAR,
+ UI_STATE_ACTIVE_RIGHT = UI_BUT_TEXTEDIT_UPDATE,
+ UI_STATE_TEXT_BEFORE_WIDGET = UI_BUT_IMMEDIATE,
+
+ UI_STATE_FLAGS_ALL = (UI_STATE_HOLD_ACTION | UI_STATE_TEXT_INPUT | UI_STATE_ACTIVE_LEFT |
+ UI_STATE_ACTIVE_RIGHT | UI_STATE_TEXT_BEFORE_WIDGET),
};
/* Prevent accidental use. */
#define UI_BUT_UPDATE_DELAY ((void)0)
#define UI_BUT_UNDO ((void)0)
-
/* ************** widget base functions ************** */
/**
* - in: roundbox codes for corner types and radius
@@ -149,12 +143,12 @@ enum {
/* it has outline, back, and two optional tria meshes */
typedef struct uiWidgetTrias {
- uint tot;
- int type;
- float size, center[2];
+ uint tot;
+ int type;
+ float size, center[2];
- float vec[16][2];
- const uint (*index)[3];
+ float vec[16][2];
+ const uint (*index)[3];
} uiWidgetTrias;
@@ -164,19 +158,19 @@ typedef struct uiWidgetTrias {
#define WIDGET_SIZE_MAX (WIDGET_CURVE_RESOLU * 4)
typedef struct uiWidgetBase {
- /* TODO remove these completely */
- int totvert, halfwayvert;
- float outer_v[WIDGET_SIZE_MAX][2];
- float inner_v[WIDGET_SIZE_MAX][2];
- float inner_uv[WIDGET_SIZE_MAX][2];
+ /* TODO remove these completely */
+ int totvert, halfwayvert;
+ float outer_v[WIDGET_SIZE_MAX][2];
+ float inner_v[WIDGET_SIZE_MAX][2];
+ float inner_uv[WIDGET_SIZE_MAX][2];
- bool draw_inner, draw_outline, draw_emboss;
+ bool draw_inner, draw_outline, draw_emboss;
- uiWidgetTrias tria1;
- uiWidgetTrias tria2;
+ uiWidgetTrias tria1;
+ uiWidgetTrias tria2;
- /* Widget shader parameters, must match the shader layout. */
- uiWidgetBaseParameters uniform_params;
+ /* Widget shader parameters, must match the shader layout. */
+ uiWidgetBaseParameters uniform_params;
} uiWidgetBase;
/** uiWidgetType: for time being only for visual appearance,
@@ -184,35 +178,43 @@ typedef struct uiWidgetBase {
*/
typedef struct uiWidgetType {
- /* pointer to theme color definition */
- const uiWidgetColors *wcol_theme;
- uiWidgetStateColors *wcol_state;
+ /* pointer to theme color definition */
+ const uiWidgetColors *wcol_theme;
+ uiWidgetStateColors *wcol_state;
- /* converted colors for state */
- uiWidgetColors wcol;
+ /* converted colors for state */
+ uiWidgetColors wcol;
- void (*state)(struct uiWidgetType *, int state, int drawflag);
- void (*draw)(uiWidgetColors *, rcti *, int state, int roundboxalign);
- void (*custom)(uiBut *, uiWidgetColors *, rcti *, int state, int roundboxalign);
- void (*text)(const uiFontStyle *, const uiWidgetColors *, uiBut *, rcti *);
+ void (*state)(struct uiWidgetType *, int state, int drawflag);
+ void (*draw)(uiWidgetColors *, rcti *, int state, int roundboxalign);
+ void (*custom)(uiBut *, uiWidgetColors *, rcti *, int state, int roundboxalign);
+ void (*text)(const uiFontStyle *, const uiWidgetColors *, uiBut *, rcti *);
} uiWidgetType;
-
/* *********************** draw data ************************** */
static const float cornervec[WIDGET_CURVE_RESOLU][2] = {
- {0.0, 0.0}, {0.195, 0.02}, {0.383, 0.067},
- {0.55, 0.169}, {0.707, 0.293}, {0.831, 0.45},
- {0.924, 0.617}, {0.98, 0.805}, {1.0, 1.0},
+ {0.0, 0.0},
+ {0.195, 0.02},
+ {0.383, 0.067},
+ {0.55, 0.169},
+ {0.707, 0.293},
+ {0.831, 0.45},
+ {0.924, 0.617},
+ {0.98, 0.805},
+ {1.0, 1.0},
};
-
const float ui_pixel_jitter[UI_PIXEL_AA_JITTER][2] = {
- { 0.468813, -0.481430}, {-0.155755, -0.352820},
- { 0.219306, -0.238501}, {-0.393286, -0.110949},
- {-0.024699, 0.013908}, { 0.343805, 0.147431},
- {-0.272855, 0.269918}, { 0.095909, 0.388710},
+ {0.468813, -0.481430},
+ {-0.155755, -0.352820},
+ {0.219306, -0.238501},
+ {-0.393286, -0.110949},
+ {-0.024699, 0.013908},
+ {0.343805, 0.147431},
+ {-0.272855, 0.269918},
+ {0.095909, 0.388710},
};
#define WIDGET_AA_JITTER UI_PIXEL_AA_JITTER
#define jit ui_pixel_jitter
@@ -222,42 +224,81 @@ const float ui_pixel_jitter[UI_PIXEL_AA_JITTER][2] = {
* \{ */
static const float g_shape_preset_number_arrow_vert[3][2] = {
- {-0.352077, 0.532607}, {-0.352077, -0.549313}, {0.330000, -0.008353},
+ {-0.352077, 0.532607},
+ {-0.352077, -0.549313},
+ {0.330000, -0.008353},
};
static const uint g_shape_preset_number_arrow_face[1][3] = {
- {0, 1, 2},
+ {0, 1, 2},
};
static const float g_shape_preset_scroll_circle_vert[16][2] = {
- {0.382684, 0.923879}, {0.000001, 1.000000}, {-0.382683, 0.923880}, {-0.707107, 0.707107},
- {-0.923879, 0.382684}, {-1.000000, 0.000000}, {-0.923880, -0.382684}, {-0.707107, -0.707107},
- {-0.382683, -0.923880}, {0.000000, -1.000000}, {0.382684, -0.923880}, {0.707107, -0.707107},
- {0.923880, -0.382684}, {1.000000, -0.000000}, {0.923880, 0.382683}, {0.707107, 0.707107},
+ {0.382684, 0.923879},
+ {0.000001, 1.000000},
+ {-0.382683, 0.923880},
+ {-0.707107, 0.707107},
+ {-0.923879, 0.382684},
+ {-1.000000, 0.000000},
+ {-0.923880, -0.382684},
+ {-0.707107, -0.707107},
+ {-0.382683, -0.923880},
+ {0.000000, -1.000000},
+ {0.382684, -0.923880},
+ {0.707107, -0.707107},
+ {0.923880, -0.382684},
+ {1.000000, -0.000000},
+ {0.923880, 0.382683},
+ {0.707107, 0.707107},
};
static const uint g_shape_preset_scroll_circle_face[14][3] = {
- {0, 1, 2}, {2, 0, 3}, {3, 0, 15}, {3, 15, 4}, {4, 15, 14}, {4, 14, 5}, {5, 14, 13}, {5, 13, 6},
- {6, 13, 12}, {6, 12, 7}, {7, 12, 11}, {7, 11, 8}, {8, 11, 10}, {8, 10, 9},
+ {0, 1, 2},
+ {2, 0, 3},
+ {3, 0, 15},
+ {3, 15, 4},
+ {4, 15, 14},
+ {4, 14, 5},
+ {5, 14, 13},
+ {5, 13, 6},
+ {6, 13, 12},
+ {6, 12, 7},
+ {7, 12, 11},
+ {7, 11, 8},
+ {8, 11, 10},
+ {8, 10, 9},
};
static const float g_shape_preset_menu_arrow_vert[6][2] = {
- {-0.33, 0.16}, {0.33, 0.16}, {0, 0.82},
- {0, -0.82}, {-0.33, -0.16}, {0.33, -0.16},
+ {-0.33, 0.16},
+ {0.33, 0.16},
+ {0, 0.82},
+ {0, -0.82},
+ {-0.33, -0.16},
+ {0.33, -0.16},
};
static const uint g_shape_preset_menu_arrow_face[2][3] = {{2, 0, 1}, {3, 5, 4}};
static const float g_shape_preset_checkmark_vert[6][2] = {
- {-0.578579, 0.253369}, {-0.392773, 0.412794}, {-0.004241, -0.328551},
- {-0.003001, 0.034320}, {1.055313, 0.864744}, {0.866408, 1.026895},
+ {-0.578579, 0.253369},
+ {-0.392773, 0.412794},
+ {-0.004241, -0.328551},
+ {-0.003001, 0.034320},
+ {1.055313, 0.864744},
+ {0.866408, 1.026895},
};
static const uint g_shape_preset_checkmark_face[4][3] = {
- {3, 2, 4}, {3, 4, 5}, {1, 0, 3}, {0, 2, 3},
+ {3, 2, 4},
+ {3, 4, 5},
+ {1, 0, 3},
+ {0, 2, 3},
};
#define OY (-0.2 / 2)
#define SC (0.35 * 2)
static const float g_shape_preset_hold_action_vert[6][2] = {
- {-0.5 + SC, 1.0 + OY}, {0.5, 1.0 + OY}, {0.5, 0.0 + OY + SC},
+ {-0.5 + SC, 1.0 + OY},
+ {0.5, 1.0 + OY},
+ {0.5, 0.0 + OY + SC},
};
static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}};
#undef OY
@@ -274,41 +315,42 @@ static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}}
/* offset in triavec[] in shader per type */
static const int tria_ofs[ROUNDBOX_TRIA_MAX] = {
- [ROUNDBOX_TRIA_NONE] = 0,
- [ROUNDBOX_TRIA_ARROWS] = 0,
- [ROUNDBOX_TRIA_SCROLL] = 12,
- [ROUNDBOX_TRIA_MENU] = 28,
- [ROUNDBOX_TRIA_CHECK] = 34,
- [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 40,
+ [ROUNDBOX_TRIA_NONE] = 0,
+ [ROUNDBOX_TRIA_ARROWS] = 0,
+ [ROUNDBOX_TRIA_SCROLL] = 12,
+ [ROUNDBOX_TRIA_MENU] = 28,
+ [ROUNDBOX_TRIA_CHECK] = 34,
+ [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 40,
};
static const int tria_vcount[ROUNDBOX_TRIA_MAX] = {
- [ROUNDBOX_TRIA_NONE] = 0,
- [ROUNDBOX_TRIA_ARROWS] = 6,
- [ROUNDBOX_TRIA_SCROLL] = 16,
- [ROUNDBOX_TRIA_MENU] = 6,
- [ROUNDBOX_TRIA_CHECK] = 6,
- [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 3,
+ [ROUNDBOX_TRIA_NONE] = 0,
+ [ROUNDBOX_TRIA_ARROWS] = 6,
+ [ROUNDBOX_TRIA_SCROLL] = 16,
+ [ROUNDBOX_TRIA_MENU] = 6,
+ [ROUNDBOX_TRIA_CHECK] = 6,
+ [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 3,
};
static struct {
- GPUBatch *roundbox_widget[ROUNDBOX_TRIA_MAX];
+ GPUBatch *roundbox_widget[ROUNDBOX_TRIA_MAX];
- GPUBatch *roundbox_simple;
- GPUBatch *roundbox_simple_aa;
- GPUBatch *roundbox_simple_outline;
- GPUBatch *roundbox_shadow;
+ GPUBatch *roundbox_simple;
+ GPUBatch *roundbox_simple_aa;
+ GPUBatch *roundbox_simple_outline;
+ GPUBatch *roundbox_shadow;
- GPUVertFormat format;
- uint vflag_id;
+ GPUVertFormat format;
+ uint vflag_id;
} g_ui_batch_cache = {{0}};
static GPUVertFormat *vflag_format(void)
{
- if (g_ui_batch_cache.format.attr_len == 0) {
- GPUVertFormat *format = &g_ui_batch_cache.format;
- g_ui_batch_cache.vflag_id = GPU_vertformat_attr_add(format, "vflag", GPU_COMP_U32, 1, GPU_FETCH_INT);
- }
- return &g_ui_batch_cache.format;
+ if (g_ui_batch_cache.format.attr_len == 0) {
+ GPUVertFormat *format = &g_ui_batch_cache.format;
+ g_ui_batch_cache.vflag_id = GPU_vertformat_attr_add(
+ format, "vflag", GPU_COMP_U32, 1, GPU_FETCH_INT);
+ }
+ return &g_ui_batch_cache.format;
}
#define INNER 0
@@ -316,231 +358,236 @@ static GPUVertFormat *vflag_format(void)
#define EMBOSS 2
#define NO_AA WIDGET_AA_JITTER
-static void set_roundbox_vertex_data(
- GPUVertBufRaw *vflag_step, uint32_t d)
+static void set_roundbox_vertex_data(GPUVertBufRaw *vflag_step, uint32_t d)
{
- uint32_t *data = GPU_vertbuf_raw_step(vflag_step);
- *data = d;
+ uint32_t *data = GPU_vertbuf_raw_step(vflag_step);
+ *data = d;
}
-static uint32_t set_roundbox_vertex(
- GPUVertBufRaw *vflag_step,
- int corner_id, int corner_v, int jit_v, bool inner, bool emboss, int color)
+static uint32_t set_roundbox_vertex(GPUVertBufRaw *vflag_step,
+ int corner_id,
+ int corner_v,
+ int jit_v,
+ bool inner,
+ bool emboss,
+ int color)
{
- uint32_t *data = GPU_vertbuf_raw_step(vflag_step);
- *data = corner_id;
- *data |= corner_v << 2;
- *data |= jit_v << 6;
- *data |= color << 12;
- *data |= (inner) ? (1 << 10) : 0; /* is inner vert */
- *data |= (emboss) ? (1 << 11) : 0; /* is emboss vert */
- return *data;
+ uint32_t *data = GPU_vertbuf_raw_step(vflag_step);
+ *data = corner_id;
+ *data |= corner_v << 2;
+ *data |= jit_v << 6;
+ *data |= color << 12;
+ *data |= (inner) ? (1 << 10) : 0; /* is inner vert */
+ *data |= (emboss) ? (1 << 11) : 0; /* is emboss vert */
+ return *data;
}
static uint32_t set_tria_vertex(
- GPUVertBufRaw *vflag_step,
- int tria_type, int tria_v, int tria_id, int jit_v)
+ GPUVertBufRaw *vflag_step, int tria_type, int tria_v, int tria_id, int jit_v)
{
- uint32_t *data = GPU_vertbuf_raw_step(vflag_step);
- if (ELEM(tria_type, ROUNDBOX_TRIA_ARROWS)) {
- tria_v += tria_id * tria_vcount[ROUNDBOX_TRIA_ARROWS];
- }
- *data = tria_ofs[tria_type] + tria_v;
- *data |= jit_v << 6;
- *data |= (tria_id == 0) ? (1 << 10) : 0; /* is first tria */
- *data |= 1 << 14; /* is tria vert */
- return *data;
+ uint32_t *data = GPU_vertbuf_raw_step(vflag_step);
+ if (ELEM(tria_type, ROUNDBOX_TRIA_ARROWS)) {
+ tria_v += tria_id * tria_vcount[ROUNDBOX_TRIA_ARROWS];
+ }
+ *data = tria_ofs[tria_type] + tria_v;
+ *data |= jit_v << 6;
+ *data |= (tria_id == 0) ? (1 << 10) : 0; /* is first tria */
+ *data |= 1 << 14; /* is tria vert */
+ return *data;
}
static void roundbox_batch_add_tria(GPUVertBufRaw *vflag_step, int tria, uint32_t last_data)
{
- const int tria_num = ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU) ? 1 : 2;
- /* for each tria */
- for (int t = 0; t < tria_num; ++t) {
- for (int j = 0; j < WIDGET_AA_JITTER; j++) {
- /* restart */
- set_roundbox_vertex_data(vflag_step, last_data);
- set_tria_vertex(vflag_step, tria, 0, t, j);
- for (int v = 0; v < tria_vcount[tria]; v++) {
- last_data = set_tria_vertex(vflag_step, tria, v, t, j);
- }
- }
- }
+ const int tria_num =
+ ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU) ? 1 : 2;
+ /* for each tria */
+ for (int t = 0; t < tria_num; ++t) {
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ /* restart */
+ set_roundbox_vertex_data(vflag_step, last_data);
+ set_tria_vertex(vflag_step, tria, 0, t, j);
+ for (int v = 0; v < tria_vcount[tria]; v++) {
+ last_data = set_tria_vertex(vflag_step, tria, v, t, j);
+ }
+ }
+ }
}
GPUBatch *ui_batch_roundbox_widget_get(int tria)
{
- if (g_ui_batch_cache.roundbox_widget[tria] == NULL) {
- uint32_t last_data;
- GPUVertBufRaw vflag_step;
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(vflag_format());
- int vcount = WIDGET_SIZE_MAX; /* inner */
- vcount += 2; /* restart */
- vcount += ((WIDGET_SIZE_MAX + 1) * 2) * WIDGET_AA_JITTER; /* outline (edges) */
- vcount += 2; /* restart */
- vcount += ((WIDGET_CURVE_RESOLU * 2) * 2) * WIDGET_AA_JITTER; /* emboss */
- if (tria) {
- vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria1 */
- if (!ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU)) {
- vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria2 */
- }
- }
- GPU_vertbuf_data_alloc(vbo, vcount);
- GPU_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
- /* Inner */
- for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) {
- for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU -1; a2 >= 0; a1++, a2--) {
- last_data = set_roundbox_vertex(&vflag_step, c1, a1, NO_AA, true, false, INNER);
- last_data = set_roundbox_vertex(&vflag_step, c2, a2, NO_AA, true, false, INNER);
- }
- }
- /* restart */
- set_roundbox_vertex_data(&vflag_step, last_data);
- set_roundbox_vertex(&vflag_step, 0, 0, 0, true, false, OUTLINE);
- /* Outlines */
- for (int j = 0; j < WIDGET_AA_JITTER; j++) {
- for (int c = 0; c < 4; c++) {
- for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
- set_roundbox_vertex(&vflag_step, c, a, j, true, false, OUTLINE);
- set_roundbox_vertex(&vflag_step, c, a, j, false, false, OUTLINE);
- }
- }
- /* Close the loop. */
- set_roundbox_vertex(&vflag_step, 0, 0, j, true, false, OUTLINE);
- last_data = set_roundbox_vertex(&vflag_step, 0, 0, j, false, false, OUTLINE);
- }
- /* restart */
- set_roundbox_vertex_data(&vflag_step, last_data);
- set_roundbox_vertex(&vflag_step, 0, 0, 0, false, false, EMBOSS);
- /* Emboss */
- /* go back and forth : avoid degenerate triangle (but beware of backface cull) */
- bool rev = false;
- for (int j = 0; j < WIDGET_AA_JITTER; j++, rev = !rev) {
- for (int c = (rev) ? 1 : 0; (rev) ? c >= 0 : c < 2; (rev) ? c-- : c++) {
- int sta = (rev) ? WIDGET_CURVE_RESOLU - 1 : 0;
- int end = WIDGET_CURVE_RESOLU;
- for (int a = sta; (rev) ? a >= 0 : a < end; (rev) ? a-- : a++) {
- set_roundbox_vertex(&vflag_step, c, a, j, false, false, EMBOSS);
- last_data = set_roundbox_vertex(&vflag_step, c, a, j, false, true, EMBOSS);
- }
- }
- }
- if (tria) {
- roundbox_batch_add_tria(&vflag_step, tria, last_data);
- }
- g_ui_batch_cache.roundbox_widget[tria] = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
- gpu_batch_presets_register(g_ui_batch_cache.roundbox_widget[tria]);
- }
- return g_ui_batch_cache.roundbox_widget[tria];
+ if (g_ui_batch_cache.roundbox_widget[tria] == NULL) {
+ uint32_t last_data;
+ GPUVertBufRaw vflag_step;
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(vflag_format());
+ int vcount = WIDGET_SIZE_MAX; /* inner */
+ vcount += 2; /* restart */
+ vcount += ((WIDGET_SIZE_MAX + 1) * 2) * WIDGET_AA_JITTER; /* outline (edges) */
+ vcount += 2; /* restart */
+ vcount += ((WIDGET_CURVE_RESOLU * 2) * 2) * WIDGET_AA_JITTER; /* emboss */
+ if (tria) {
+ vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria1 */
+ if (!ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU)) {
+ vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria2 */
+ }
+ }
+ GPU_vertbuf_data_alloc(vbo, vcount);
+ GPU_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
+ /* Inner */
+ for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) {
+ for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU - 1; a2 >= 0; a1++, a2--) {
+ last_data = set_roundbox_vertex(&vflag_step, c1, a1, NO_AA, true, false, INNER);
+ last_data = set_roundbox_vertex(&vflag_step, c2, a2, NO_AA, true, false, INNER);
+ }
+ }
+ /* restart */
+ set_roundbox_vertex_data(&vflag_step, last_data);
+ set_roundbox_vertex(&vflag_step, 0, 0, 0, true, false, OUTLINE);
+ /* Outlines */
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ for (int c = 0; c < 4; c++) {
+ for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
+ set_roundbox_vertex(&vflag_step, c, a, j, true, false, OUTLINE);
+ set_roundbox_vertex(&vflag_step, c, a, j, false, false, OUTLINE);
+ }
+ }
+ /* Close the loop. */
+ set_roundbox_vertex(&vflag_step, 0, 0, j, true, false, OUTLINE);
+ last_data = set_roundbox_vertex(&vflag_step, 0, 0, j, false, false, OUTLINE);
+ }
+ /* restart */
+ set_roundbox_vertex_data(&vflag_step, last_data);
+ set_roundbox_vertex(&vflag_step, 0, 0, 0, false, false, EMBOSS);
+ /* Emboss */
+ /* go back and forth : avoid degenerate triangle (but beware of backface cull) */
+ bool rev = false;
+ for (int j = 0; j < WIDGET_AA_JITTER; j++, rev = !rev) {
+ for (int c = (rev) ? 1 : 0; (rev) ? c >= 0 : c < 2; (rev) ? c-- : c++) {
+ int sta = (rev) ? WIDGET_CURVE_RESOLU - 1 : 0;
+ int end = WIDGET_CURVE_RESOLU;
+ for (int a = sta; (rev) ? a >= 0 : a < end; (rev) ? a-- : a++) {
+ set_roundbox_vertex(&vflag_step, c, a, j, false, false, EMBOSS);
+ last_data = set_roundbox_vertex(&vflag_step, c, a, j, false, true, EMBOSS);
+ }
+ }
+ }
+ if (tria) {
+ roundbox_batch_add_tria(&vflag_step, tria, last_data);
+ }
+ g_ui_batch_cache.roundbox_widget[tria] = GPU_batch_create_ex(
+ GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ gpu_batch_presets_register(g_ui_batch_cache.roundbox_widget[tria]);
+ }
+ return g_ui_batch_cache.roundbox_widget[tria];
}
GPUBatch *ui_batch_roundbox_get(bool filled, bool antialiased)
{
- GPUBatch **batch = NULL;
-
- if (filled) {
- if (antialiased) {
- batch = &g_ui_batch_cache.roundbox_simple_aa;
- }
- else {
- batch = &g_ui_batch_cache.roundbox_simple;
- }
- }
- else {
- if (antialiased) {
- BLI_assert(0); /* Use GL_LINE_SMOOTH instead!!: */
- }
- else {
- batch = &g_ui_batch_cache.roundbox_simple_outline;
- }
- }
-
- if (*batch == NULL) {
- uint32_t last_data;
- GPUVertBufRaw vflag_step;
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(vflag_format());
- int vcount = WIDGET_SIZE_MAX;
- vcount += (filled) ? 2 : 0;
- vcount *= (antialiased) ? WIDGET_AA_JITTER : 1;
- GPU_vertbuf_data_alloc(vbo, vcount);
- GPU_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
-
- if (filled) {
- for (int j = 0; j < WIDGET_AA_JITTER; j++) {
- if (!antialiased) {
- j = NO_AA;
- }
- /* restart */
- set_roundbox_vertex(&vflag_step, 0, 0, j, true, false, INNER);
- for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) {
- for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU -1; a2 >= 0; a1++, a2--) {
- last_data = set_roundbox_vertex(&vflag_step, c1, a1, j, true, false, INNER);
- last_data = set_roundbox_vertex(&vflag_step, c2, a2, j, true, false, INNER);
- }
- }
- /* restart */
- set_roundbox_vertex_data(&vflag_step, last_data);
- if (!antialiased) {
- break;
- }
- }
- *batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
- }
- else {
- for (int j = 0; j < WIDGET_AA_JITTER; j++) {
- if (!antialiased) {
- j = NO_AA;
- }
- for (int c = 0; c < 4; c++) {
- for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
- set_roundbox_vertex(&vflag_step, c, a, j, true, false, INNER);
- }
- }
- if (!antialiased) {
- break;
- }
- }
- *batch = GPU_batch_create_ex(GPU_PRIM_LINE_LOOP, vbo, NULL, GPU_BATCH_OWNS_VBO);
- }
-
- gpu_batch_presets_register(*batch);
- }
- return *batch;
+ GPUBatch **batch = NULL;
+
+ if (filled) {
+ if (antialiased) {
+ batch = &g_ui_batch_cache.roundbox_simple_aa;
+ }
+ else {
+ batch = &g_ui_batch_cache.roundbox_simple;
+ }
+ }
+ else {
+ if (antialiased) {
+ BLI_assert(0); /* Use GL_LINE_SMOOTH instead!!: */
+ }
+ else {
+ batch = &g_ui_batch_cache.roundbox_simple_outline;
+ }
+ }
+
+ if (*batch == NULL) {
+ uint32_t last_data;
+ GPUVertBufRaw vflag_step;
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(vflag_format());
+ int vcount = WIDGET_SIZE_MAX;
+ vcount += (filled) ? 2 : 0;
+ vcount *= (antialiased) ? WIDGET_AA_JITTER : 1;
+ GPU_vertbuf_data_alloc(vbo, vcount);
+ GPU_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
+
+ if (filled) {
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ if (!antialiased) {
+ j = NO_AA;
+ }
+ /* restart */
+ set_roundbox_vertex(&vflag_step, 0, 0, j, true, false, INNER);
+ for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) {
+ for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU - 1; a2 >= 0; a1++, a2--) {
+ last_data = set_roundbox_vertex(&vflag_step, c1, a1, j, true, false, INNER);
+ last_data = set_roundbox_vertex(&vflag_step, c2, a2, j, true, false, INNER);
+ }
+ }
+ /* restart */
+ set_roundbox_vertex_data(&vflag_step, last_data);
+ if (!antialiased) {
+ break;
+ }
+ }
+ *batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ }
+ else {
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ if (!antialiased) {
+ j = NO_AA;
+ }
+ for (int c = 0; c < 4; c++) {
+ for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
+ set_roundbox_vertex(&vflag_step, c, a, j, true, false, INNER);
+ }
+ }
+ if (!antialiased) {
+ break;
+ }
+ }
+ *batch = GPU_batch_create_ex(GPU_PRIM_LINE_LOOP, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ }
+
+ gpu_batch_presets_register(*batch);
+ }
+ return *batch;
}
GPUBatch *ui_batch_roundbox_shadow_get(void)
{
- if (g_ui_batch_cache.roundbox_shadow == NULL) {
- uint32_t last_data;
- GPUVertBufRaw vflag_step;
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(vflag_format());
- int vcount = (WIDGET_SIZE_MAX + 1) * 2 + 2 + WIDGET_SIZE_MAX;
- GPU_vertbuf_data_alloc(vbo, vcount);
- GPU_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
-
- for (int c = 0; c < 4; c++) {
- for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
- set_roundbox_vertex(&vflag_step, c, a, NO_AA, true, false, INNER);
- set_roundbox_vertex(&vflag_step, c, a, NO_AA, false, false, INNER);
- }
- }
- /* close loop */
- last_data = set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, true, false, INNER);
- last_data = set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, false, false, INNER);
- /* restart */
- set_roundbox_vertex_data(&vflag_step, last_data);
- set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, true, false, INNER);
- /* filled */
- for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) {
- for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU -1; a2 >= 0; a1++, a2--) {
- set_roundbox_vertex(&vflag_step, c1, a1, NO_AA, true, false, INNER);
- set_roundbox_vertex(&vflag_step, c2, a2, NO_AA, true, false, INNER);
- }
- }
- g_ui_batch_cache.roundbox_shadow = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
- gpu_batch_presets_register(g_ui_batch_cache.roundbox_shadow);
- }
- return g_ui_batch_cache.roundbox_shadow;
+ if (g_ui_batch_cache.roundbox_shadow == NULL) {
+ uint32_t last_data;
+ GPUVertBufRaw vflag_step;
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(vflag_format());
+ int vcount = (WIDGET_SIZE_MAX + 1) * 2 + 2 + WIDGET_SIZE_MAX;
+ GPU_vertbuf_data_alloc(vbo, vcount);
+ GPU_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
+
+ for (int c = 0; c < 4; c++) {
+ for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
+ set_roundbox_vertex(&vflag_step, c, a, NO_AA, true, false, INNER);
+ set_roundbox_vertex(&vflag_step, c, a, NO_AA, false, false, INNER);
+ }
+ }
+ /* close loop */
+ last_data = set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, true, false, INNER);
+ last_data = set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, false, false, INNER);
+ /* restart */
+ set_roundbox_vertex_data(&vflag_step, last_data);
+ set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, true, false, INNER);
+ /* filled */
+ for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) {
+ for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU - 1; a2 >= 0; a1++, a2--) {
+ set_roundbox_vertex(&vflag_step, c1, a1, NO_AA, true, false, INNER);
+ set_roundbox_vertex(&vflag_step, c2, a2, NO_AA, true, false, INNER);
+ }
+ }
+ g_ui_batch_cache.roundbox_shadow = GPU_batch_create_ex(
+ GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ gpu_batch_presets_register(g_ui_batch_cache.roundbox_shadow);
+ }
+ return g_ui_batch_cache.roundbox_shadow;
}
#undef INNER
@@ -550,354 +597,360 @@ GPUBatch *ui_batch_roundbox_shadow_get(void)
/* ************************************************* */
-void UI_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3,
- const float color[4])
+void UI_draw_anti_tria(
+ float x1, float y1, float x2, float y2, float x3, float y3, const float color[4])
{
- float tri_arr[3][2] = {{x1, y1}, {x2, y2}, {x3, y3}};
- float draw_color[4];
+ float tri_arr[3][2] = {{x1, y1}, {x2, y2}, {x3, y3}};
+ float draw_color[4];
- copy_v4_v4(draw_color, color);
- /* Note: This won't give back the original color. */
- draw_color[3] *= 1.0f / WIDGET_AA_JITTER;
+ copy_v4_v4(draw_color, color);
+ /* Note: This won't give back the original color. */
+ draw_color[3] *= 1.0f / WIDGET_AA_JITTER;
- GPU_blend(true);
+ GPU_blend(true);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4fv(draw_color);
- immBegin(GPU_PRIM_TRIS, 3 * WIDGET_AA_JITTER);
+ immUniformColor4fv(draw_color);
+ immBegin(GPU_PRIM_TRIS, 3 * WIDGET_AA_JITTER);
- /* for each AA step */
- for (int j = 0; j < WIDGET_AA_JITTER; j++) {
- immVertex2f(pos, tri_arr[0][0] + jit[j][0], tri_arr[0][1] + jit[j][1]);
- immVertex2f(pos, tri_arr[1][0] + jit[j][0], tri_arr[1][1] + jit[j][1]);
- immVertex2f(pos, tri_arr[2][0] + jit[j][0], tri_arr[2][1] + jit[j][1]);
- }
+ /* for each AA step */
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ immVertex2f(pos, tri_arr[0][0] + jit[j][0], tri_arr[0][1] + jit[j][1]);
+ immVertex2f(pos, tri_arr[1][0] + jit[j][0], tri_arr[1][1] + jit[j][1]);
+ immVertex2f(pos, tri_arr[2][0] + jit[j][0], tri_arr[2][1] + jit[j][1]);
+ }
- immEnd();
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
- GPU_blend(false);
+ GPU_blend(false);
}
/* triangle 'icon' inside rect */
void ui_draw_anti_tria_rect(const rctf *rect, char dir, const float color[4])
{
- if (dir == 'h') {
- float half = 0.5f * BLI_rctf_size_y(rect);
- UI_draw_anti_tria(rect->xmin, rect->ymin, rect->xmin, rect->ymax, rect->xmax, rect->ymin + half, color);
- }
- else {
- float half = 0.5f * BLI_rctf_size_x(rect);
- UI_draw_anti_tria(rect->xmin, rect->ymax, rect->xmax, rect->ymax, rect->xmin + half, rect->ymin, color);
- }
+ if (dir == 'h') {
+ float half = 0.5f * BLI_rctf_size_y(rect);
+ UI_draw_anti_tria(
+ rect->xmin, rect->ymin, rect->xmin, rect->ymax, rect->xmax, rect->ymin + half, color);
+ }
+ else {
+ float half = 0.5f * BLI_rctf_size_x(rect);
+ UI_draw_anti_tria(
+ rect->xmin, rect->ymax, rect->xmax, rect->ymax, rect->xmin + half, rect->ymin, color);
+ }
}
-
void UI_draw_anti_fan(float tri_array[][2], uint length, const float color[4])
{
- float draw_color[4];
+ float draw_color[4];
- copy_v4_v4(draw_color, color);
- draw_color[3] *= 2.0f / WIDGET_AA_JITTER;
+ copy_v4_v4(draw_color, color);
+ draw_color[3] *= 2.0f / WIDGET_AA_JITTER;
- GPU_blend(true);
+ GPU_blend(true);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4fv(draw_color);
+ immUniformColor4fv(draw_color);
- /* for each AA step */
- for (int j = 0; j < WIDGET_AA_JITTER; j++) {
- immBegin(GPU_PRIM_TRI_FAN, length);
- immVertex2f(pos, tri_array[0][0], tri_array[0][1]);
- immVertex2f(pos, tri_array[1][0], tri_array[1][1]);
+ /* for each AA step */
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ immBegin(GPU_PRIM_TRI_FAN, length);
+ immVertex2f(pos, tri_array[0][0], tri_array[0][1]);
+ immVertex2f(pos, tri_array[1][0], tri_array[1][1]);
- /* We jitter only the middle of the fan, the extremes are pinned. */
- for (int i = 2; i < length - 1; i++) {
- immVertex2f(pos, tri_array[i][0] + jit[j][0], tri_array[i][1] + jit[j][1]);
- }
+ /* We jitter only the middle of the fan, the extremes are pinned. */
+ for (int i = 2; i < length - 1; i++) {
+ immVertex2f(pos, tri_array[i][0] + jit[j][0], tri_array[i][1] + jit[j][1]);
+ }
- immVertex2f(pos, tri_array[length - 1][0], tri_array[length - 1][1]);
- immEnd();
- }
+ immVertex2f(pos, tri_array[length - 1][0], tri_array[length - 1][1]);
+ immEnd();
+ }
- immUnbindProgram();
+ immUnbindProgram();
- GPU_blend(false);
+ GPU_blend(false);
}
static void widget_init(uiWidgetBase *wtb)
{
- wtb->totvert = wtb->halfwayvert = 0;
- wtb->tria1.tot = 0;
- wtb->tria2.tot = 0;
- wtb->tria1.type = ROUNDBOX_TRIA_NONE;
- wtb->tria1.size = 0;
- wtb->tria2.size = 0;
-
- wtb->draw_inner = true;
- wtb->draw_outline = true;
- wtb->draw_emboss = true;
-
- wtb->uniform_params.shade_dir = 1.0f;
- wtb->uniform_params.alpha_discard = 1.0f;
+ wtb->totvert = wtb->halfwayvert = 0;
+ wtb->tria1.tot = 0;
+ wtb->tria2.tot = 0;
+ wtb->tria1.type = ROUNDBOX_TRIA_NONE;
+ wtb->tria1.size = 0;
+ wtb->tria2.size = 0;
+
+ wtb->draw_inner = true;
+ wtb->draw_outline = true;
+ wtb->draw_emboss = true;
+
+ wtb->uniform_params.shade_dir = 1.0f;
+ wtb->uniform_params.alpha_discard = 1.0f;
}
/* helper call, makes shadow rect, with 'sun' above menu, so only shadow to left/right/bottom */
/* return tot */
-static int round_box_shadow_edges(float (*vert)[2], const rcti *rect, float rad, int roundboxalign, float step)
+static int round_box_shadow_edges(
+ float (*vert)[2], const rcti *rect, float rad, int roundboxalign, float step)
{
- float vec[WIDGET_CURVE_RESOLU][2];
- float minx, miny, maxx, maxy;
- int a, tot = 0;
-
- rad += step;
-
- if (2.0f * rad > BLI_rcti_size_y(rect)) {
- rad = 0.5f * BLI_rcti_size_y(rect);
- }
-
- minx = rect->xmin - step;
- miny = rect->ymin - step;
- maxx = rect->xmax + step;
- maxy = rect->ymax + step;
-
- /* mult */
- for (a = 0; a < WIDGET_CURVE_RESOLU; a++) {
- vec[a][0] = rad * cornervec[a][0];
- vec[a][1] = rad * cornervec[a][1];
- }
-
- /* start with left-top, anti clockwise */
- if (roundboxalign & UI_CNR_TOP_LEFT) {
- for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
- vert[tot][0] = minx + rad - vec[a][0];
- vert[tot][1] = maxy - vec[a][1];
- }
- }
- else {
- for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
- vert[tot][0] = minx;
- vert[tot][1] = maxy;
- }
- }
-
- if (roundboxalign & UI_CNR_BOTTOM_LEFT) {
- for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
- vert[tot][0] = minx + vec[a][1];
- vert[tot][1] = miny + rad - vec[a][0];
- }
- }
- else {
- for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
- vert[tot][0] = minx;
- vert[tot][1] = miny;
- }
- }
-
- if (roundboxalign & UI_CNR_BOTTOM_RIGHT) {
- for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
- vert[tot][0] = maxx - rad + vec[a][0];
- vert[tot][1] = miny + vec[a][1];
- }
- }
- else {
- for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
- vert[tot][0] = maxx;
- vert[tot][1] = miny;
- }
- }
-
- if (roundboxalign & UI_CNR_TOP_RIGHT) {
- for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
- vert[tot][0] = maxx - vec[a][1];
- vert[tot][1] = maxy - rad + vec[a][0];
- }
- }
- else {
- for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
- vert[tot][0] = maxx;
- vert[tot][1] = maxy;
- }
- }
- return tot;
+ float vec[WIDGET_CURVE_RESOLU][2];
+ float minx, miny, maxx, maxy;
+ int a, tot = 0;
+
+ rad += step;
+
+ if (2.0f * rad > BLI_rcti_size_y(rect)) {
+ rad = 0.5f * BLI_rcti_size_y(rect);
+ }
+
+ minx = rect->xmin - step;
+ miny = rect->ymin - step;
+ maxx = rect->xmax + step;
+ maxy = rect->ymax + step;
+
+ /* mult */
+ for (a = 0; a < WIDGET_CURVE_RESOLU; a++) {
+ vec[a][0] = rad * cornervec[a][0];
+ vec[a][1] = rad * cornervec[a][1];
+ }
+
+ /* start with left-top, anti clockwise */
+ if (roundboxalign & UI_CNR_TOP_LEFT) {
+ for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
+ vert[tot][0] = minx + rad - vec[a][0];
+ vert[tot][1] = maxy - vec[a][1];
+ }
+ }
+ else {
+ for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
+ vert[tot][0] = minx;
+ vert[tot][1] = maxy;
+ }
+ }
+
+ if (roundboxalign & UI_CNR_BOTTOM_LEFT) {
+ for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
+ vert[tot][0] = minx + vec[a][1];
+ vert[tot][1] = miny + rad - vec[a][0];
+ }
+ }
+ else {
+ for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
+ vert[tot][0] = minx;
+ vert[tot][1] = miny;
+ }
+ }
+
+ if (roundboxalign & UI_CNR_BOTTOM_RIGHT) {
+ for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
+ vert[tot][0] = maxx - rad + vec[a][0];
+ vert[tot][1] = miny + vec[a][1];
+ }
+ }
+ else {
+ for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
+ vert[tot][0] = maxx;
+ vert[tot][1] = miny;
+ }
+ }
+
+ if (roundboxalign & UI_CNR_TOP_RIGHT) {
+ for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
+ vert[tot][0] = maxx - vec[a][1];
+ vert[tot][1] = maxy - rad + vec[a][0];
+ }
+ }
+ else {
+ for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
+ vert[tot][0] = maxx;
+ vert[tot][1] = maxy;
+ }
+ }
+ return tot;
}
/* this call has 1 extra arg to allow mask outline */
-static void round_box__edges(uiWidgetBase *wt, int roundboxalign, const rcti *rect, float rad, float radi)
+static void round_box__edges(
+ uiWidgetBase *wt, int roundboxalign, const rcti *rect, float rad, float radi)
{
- float vec[WIDGET_CURVE_RESOLU][2], veci[WIDGET_CURVE_RESOLU][2];
- float minx = rect->xmin, miny = rect->ymin, maxx = rect->xmax, maxy = rect->ymax;
- float minxi = minx + U.pixelsize; /* boundbox inner */
- float maxxi = maxx - U.pixelsize;
- float minyi = miny + U.pixelsize;
- float maxyi = maxy - U.pixelsize;
- /* for uv, can divide by zero */
- float facxi = (maxxi != minxi) ? 1.0f / (maxxi - minxi) : 0.0f;
- float facyi = (maxyi != minyi) ? 1.0f / (maxyi - minyi) : 0.0f;
- int a, tot = 0, minsize;
- const int hnum = (
- (roundboxalign & (UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT)) == (UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT) ||
- (roundboxalign & (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT)) == (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT)) ? 1 : 2;
- const int vnum = (
- (roundboxalign & (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)) == (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT) ||
- (roundboxalign & (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) == (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) ? 1 : 2;
-
- minsize = min_ii(
- BLI_rcti_size_x(rect) * hnum,
- BLI_rcti_size_y(rect) * vnum);
-
- if (2.0f * rad > minsize) {
- rad = 0.5f * minsize;
- }
-
- if (2.0f * (radi + 1.0f) > minsize) {
- radi = 0.5f * minsize - U.pixelsize;
- }
-
- wt->uniform_params.rad = rad;
- wt->uniform_params.radi = radi;
- wt->uniform_params.facxi = facxi;
- wt->uniform_params.facyi = facyi;
- wt->uniform_params.round_corners[0] = (roundboxalign & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f;
- wt->uniform_params.round_corners[1] = (roundboxalign & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f;
- wt->uniform_params.round_corners[2] = (roundboxalign & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f;
- wt->uniform_params.round_corners[3] = (roundboxalign & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f;
- BLI_rctf_rcti_copy(&wt->uniform_params.rect, rect);
- BLI_rctf_init(&wt->uniform_params.recti, minxi, maxxi, minyi, maxyi);
-
- /* mult */
- for (a = 0; a < WIDGET_CURVE_RESOLU; a++) {
- veci[a][0] = radi * cornervec[a][0];
- veci[a][1] = radi * cornervec[a][1];
- vec[a][0] = rad * cornervec[a][0];
- vec[a][1] = rad * cornervec[a][1];
- }
-
- /* corner left-bottom */
- if (roundboxalign & UI_CNR_BOTTOM_LEFT) {
-
- for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
- wt->inner_v[tot][0] = minxi + veci[a][1];
- wt->inner_v[tot][1] = minyi + radi - veci[a][0];
-
- wt->outer_v[tot][0] = minx + vec[a][1];
- wt->outer_v[tot][1] = miny + rad - vec[a][0];
-
- wt->inner_uv[tot][0] = facxi * (wt->inner_v[tot][0] - minxi);
- wt->inner_uv[tot][1] = facyi * (wt->inner_v[tot][1] - minyi);
- }
- }
- else {
- wt->inner_v[tot][0] = minxi;
- wt->inner_v[tot][1] = minyi;
-
- wt->outer_v[tot][0] = minx;
- wt->outer_v[tot][1] = miny;
-
- wt->inner_uv[tot][0] = 0.0f;
- wt->inner_uv[tot][1] = 0.0f;
-
- tot++;
- }
-
- /* corner right-bottom */
- if (roundboxalign & UI_CNR_BOTTOM_RIGHT) {
-
- for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
- wt->inner_v[tot][0] = maxxi - radi + veci[a][0];
- wt->inner_v[tot][1] = minyi + veci[a][1];
-
- wt->outer_v[tot][0] = maxx - rad + vec[a][0];
- wt->outer_v[tot][1] = miny + vec[a][1];
-
- wt->inner_uv[tot][0] = facxi * (wt->inner_v[tot][0] - minxi);
- wt->inner_uv[tot][1] = facyi * (wt->inner_v[tot][1] - minyi);
- }
- }
- else {
- wt->inner_v[tot][0] = maxxi;
- wt->inner_v[tot][1] = minyi;
-
- wt->outer_v[tot][0] = maxx;
- wt->outer_v[tot][1] = miny;
-
- wt->inner_uv[tot][0] = 1.0f;
- wt->inner_uv[tot][1] = 0.0f;
-
- tot++;
- }
-
- wt->halfwayvert = tot;
-
- /* corner right-top */
- if (roundboxalign & UI_CNR_TOP_RIGHT) {
-
- for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
- wt->inner_v[tot][0] = maxxi - veci[a][1];
- wt->inner_v[tot][1] = maxyi - radi + veci[a][0];
-
- wt->outer_v[tot][0] = maxx - vec[a][1];
- wt->outer_v[tot][1] = maxy - rad + vec[a][0];
+ float vec[WIDGET_CURVE_RESOLU][2], veci[WIDGET_CURVE_RESOLU][2];
+ float minx = rect->xmin, miny = rect->ymin, maxx = rect->xmax, maxy = rect->ymax;
+ float minxi = minx + U.pixelsize; /* boundbox inner */
+ float maxxi = maxx - U.pixelsize;
+ float minyi = miny + U.pixelsize;
+ float maxyi = maxy - U.pixelsize;
+ /* for uv, can divide by zero */
+ float facxi = (maxxi != minxi) ? 1.0f / (maxxi - minxi) : 0.0f;
+ float facyi = (maxyi != minyi) ? 1.0f / (maxyi - minyi) : 0.0f;
+ int a, tot = 0, minsize;
+ const int hnum = ((roundboxalign & (UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT)) ==
+ (UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT) ||
+ (roundboxalign & (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT)) ==
+ (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT)) ?
+ 1 :
+ 2;
+ const int vnum = ((roundboxalign & (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)) ==
+ (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT) ||
+ (roundboxalign & (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) ==
+ (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) ?
+ 1 :
+ 2;
+
+ minsize = min_ii(BLI_rcti_size_x(rect) * hnum, BLI_rcti_size_y(rect) * vnum);
+
+ if (2.0f * rad > minsize) {
+ rad = 0.5f * minsize;
+ }
+
+ if (2.0f * (radi + 1.0f) > minsize) {
+ radi = 0.5f * minsize - U.pixelsize;
+ }
+
+ wt->uniform_params.rad = rad;
+ wt->uniform_params.radi = radi;
+ wt->uniform_params.facxi = facxi;
+ wt->uniform_params.facyi = facyi;
+ wt->uniform_params.round_corners[0] = (roundboxalign & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f;
+ wt->uniform_params.round_corners[1] = (roundboxalign & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f;
+ wt->uniform_params.round_corners[2] = (roundboxalign & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f;
+ wt->uniform_params.round_corners[3] = (roundboxalign & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f;
+ BLI_rctf_rcti_copy(&wt->uniform_params.rect, rect);
+ BLI_rctf_init(&wt->uniform_params.recti, minxi, maxxi, minyi, maxyi);
+
+ /* mult */
+ for (a = 0; a < WIDGET_CURVE_RESOLU; a++) {
+ veci[a][0] = radi * cornervec[a][0];
+ veci[a][1] = radi * cornervec[a][1];
+ vec[a][0] = rad * cornervec[a][0];
+ vec[a][1] = rad * cornervec[a][1];
+ }
+
+ /* corner left-bottom */
+ if (roundboxalign & UI_CNR_BOTTOM_LEFT) {
+
+ for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
+ wt->inner_v[tot][0] = minxi + veci[a][1];
+ wt->inner_v[tot][1] = minyi + radi - veci[a][0];
+
+ wt->outer_v[tot][0] = minx + vec[a][1];
+ wt->outer_v[tot][1] = miny + rad - vec[a][0];
+
+ wt->inner_uv[tot][0] = facxi * (wt->inner_v[tot][0] - minxi);
+ wt->inner_uv[tot][1] = facyi * (wt->inner_v[tot][1] - minyi);
+ }
+ }
+ else {
+ wt->inner_v[tot][0] = minxi;
+ wt->inner_v[tot][1] = minyi;
+
+ wt->outer_v[tot][0] = minx;
+ wt->outer_v[tot][1] = miny;
+
+ wt->inner_uv[tot][0] = 0.0f;
+ wt->inner_uv[tot][1] = 0.0f;
+
+ tot++;
+ }
+
+ /* corner right-bottom */
+ if (roundboxalign & UI_CNR_BOTTOM_RIGHT) {
+
+ for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
+ wt->inner_v[tot][0] = maxxi - radi + veci[a][0];
+ wt->inner_v[tot][1] = minyi + veci[a][1];
+
+ wt->outer_v[tot][0] = maxx - rad + vec[a][0];
+ wt->outer_v[tot][1] = miny + vec[a][1];
+
+ wt->inner_uv[tot][0] = facxi * (wt->inner_v[tot][0] - minxi);
+ wt->inner_uv[tot][1] = facyi * (wt->inner_v[tot][1] - minyi);
+ }
+ }
+ else {
+ wt->inner_v[tot][0] = maxxi;
+ wt->inner_v[tot][1] = minyi;
+
+ wt->outer_v[tot][0] = maxx;
+ wt->outer_v[tot][1] = miny;
+
+ wt->inner_uv[tot][0] = 1.0f;
+ wt->inner_uv[tot][1] = 0.0f;
+
+ tot++;
+ }
+
+ wt->halfwayvert = tot;
+
+ /* corner right-top */
+ if (roundboxalign & UI_CNR_TOP_RIGHT) {
+
+ for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
+ wt->inner_v[tot][0] = maxxi - veci[a][1];
+ wt->inner_v[tot][1] = maxyi - radi + veci[a][0];
+
+ wt->outer_v[tot][0] = maxx - vec[a][1];
+ wt->outer_v[tot][1] = maxy - rad + vec[a][0];
- wt->inner_uv[tot][0] = facxi * (wt->inner_v[tot][0] - minxi);
- wt->inner_uv[tot][1] = facyi * (wt->inner_v[tot][1] - minyi);
- }
- }
- else {
- wt->inner_v[tot][0] = maxxi;
- wt->inner_v[tot][1] = maxyi;
+ wt->inner_uv[tot][0] = facxi * (wt->inner_v[tot][0] - minxi);
+ wt->inner_uv[tot][1] = facyi * (wt->inner_v[tot][1] - minyi);
+ }
+ }
+ else {
+ wt->inner_v[tot][0] = maxxi;
+ wt->inner_v[tot][1] = maxyi;
- wt->outer_v[tot][0] = maxx;
- wt->outer_v[tot][1] = maxy;
+ wt->outer_v[tot][0] = maxx;
+ wt->outer_v[tot][1] = maxy;
- wt->inner_uv[tot][0] = 1.0f;
- wt->inner_uv[tot][1] = 1.0f;
+ wt->inner_uv[tot][0] = 1.0f;
+ wt->inner_uv[tot][1] = 1.0f;
- tot++;
- }
+ tot++;
+ }
- /* corner left-top */
- if (roundboxalign & UI_CNR_TOP_LEFT) {
+ /* corner left-top */
+ if (roundboxalign & UI_CNR_TOP_LEFT) {
- for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
- wt->inner_v[tot][0] = minxi + radi - veci[a][0];
- wt->inner_v[tot][1] = maxyi - veci[a][1];
+ for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
+ wt->inner_v[tot][0] = minxi + radi - veci[a][0];
+ wt->inner_v[tot][1] = maxyi - veci[a][1];
- wt->outer_v[tot][0] = minx + rad - vec[a][0];
- wt->outer_v[tot][1] = maxy - vec[a][1];
+ wt->outer_v[tot][0] = minx + rad - vec[a][0];
+ wt->outer_v[tot][1] = maxy - vec[a][1];
- wt->inner_uv[tot][0] = facxi * (wt->inner_v[tot][0] - minxi);
- wt->inner_uv[tot][1] = facyi * (wt->inner_v[tot][1] - minyi);
- }
+ wt->inner_uv[tot][0] = facxi * (wt->inner_v[tot][0] - minxi);
+ wt->inner_uv[tot][1] = facyi * (wt->inner_v[tot][1] - minyi);
+ }
+ }
+ else {
- }
- else {
+ wt->inner_v[tot][0] = minxi;
+ wt->inner_v[tot][1] = maxyi;
- wt->inner_v[tot][0] = minxi;
- wt->inner_v[tot][1] = maxyi;
+ wt->outer_v[tot][0] = minx;
+ wt->outer_v[tot][1] = maxy;
- wt->outer_v[tot][0] = minx;
- wt->outer_v[tot][1] = maxy;
+ wt->inner_uv[tot][0] = 0.0f;
+ wt->inner_uv[tot][1] = 1.0f;
- wt->inner_uv[tot][0] = 0.0f;
- wt->inner_uv[tot][1] = 1.0f;
+ tot++;
+ }
- tot++;
- }
+ BLI_assert(tot <= WIDGET_SIZE_MAX);
- BLI_assert(tot <= WIDGET_SIZE_MAX);
-
- wt->totvert = tot;
+ wt->totvert = tot;
}
static void round_box_edges(uiWidgetBase *wt, int roundboxalign, const rcti *rect, float rad)
{
- round_box__edges(wt, roundboxalign, rect, rad, rad - U.pixelsize);
+ round_box__edges(wt, roundboxalign, rect, rad, rad - U.pixelsize);
}
/* -------------------------------------------------------------------- */
@@ -905,239 +958,270 @@ static void round_box_edges(uiWidgetBase *wt, int roundboxalign, const rcti *rec
* \{ */
/* based on button rect, return scaled array of triangles */
-static void shape_preset_init_trias_ex(
- uiWidgetTrias *tria, const rcti *rect, float triasize, char where,
- /* input data */
- const float verts[][2], const int verts_tot,
- const uint tris[][3], const int tris_tot)
+static void shape_preset_init_trias_ex(uiWidgetTrias *tria,
+ const rcti *rect,
+ float triasize,
+ char where,
+ /* input data */
+ const float verts[][2],
+ const int verts_tot,
+ const uint tris[][3],
+ const int tris_tot)
{
- float centx, centy, sizex, sizey, minsize;
- int a, i1 = 0, i2 = 1;
-
- if (where == 'r' || where == 'l') {
- minsize = BLI_rcti_size_y(rect);
- }
- else {
- minsize = BLI_rcti_size_x(rect);
- }
-
- /* center position and size */
- centx = (float)rect->xmin + 0.4f * minsize;
- centy = (float)rect->ymin + 0.5f * minsize;
- tria->size = sizex = sizey = -0.5f * triasize * minsize;
-
- if (where == 'r') {
- centx = (float)rect->xmax - 0.4f * minsize;
- sizex = -sizex;
- }
- else if (where == 't') {
- centx = (float)rect->xmin + 0.5f * minsize;
- centy = (float)rect->ymax - 0.5f * minsize;
- sizey = -sizey;
- i2 = 0; i1 = 1;
- }
- else if (where == 'b') {
- centx = (float)rect->xmin + 0.5f * minsize;
- sizex = -sizex;
- i2 = 0; i1 = 1;
- }
-
- for (a = 0; a < verts_tot; a++) {
- tria->vec[a][0] = sizex * verts[a][i1] + centx;
- tria->vec[a][1] = sizey * verts[a][i2] + centy;
- }
-
- tria->center[0] = centx;
- tria->center[1] = centy;
-
- tria->tot = tris_tot;
- tria->index = tris;
+ float centx, centy, sizex, sizey, minsize;
+ int a, i1 = 0, i2 = 1;
+
+ if (where == 'r' || where == 'l') {
+ minsize = BLI_rcti_size_y(rect);
+ }
+ else {
+ minsize = BLI_rcti_size_x(rect);
+ }
+
+ /* center position and size */
+ centx = (float)rect->xmin + 0.4f * minsize;
+ centy = (float)rect->ymin + 0.5f * minsize;
+ tria->size = sizex = sizey = -0.5f * triasize * minsize;
+
+ if (where == 'r') {
+ centx = (float)rect->xmax - 0.4f * minsize;
+ sizex = -sizex;
+ }
+ else if (where == 't') {
+ centx = (float)rect->xmin + 0.5f * minsize;
+ centy = (float)rect->ymax - 0.5f * minsize;
+ sizey = -sizey;
+ i2 = 0;
+ i1 = 1;
+ }
+ else if (where == 'b') {
+ centx = (float)rect->xmin + 0.5f * minsize;
+ sizex = -sizex;
+ i2 = 0;
+ i1 = 1;
+ }
+
+ for (a = 0; a < verts_tot; a++) {
+ tria->vec[a][0] = sizex * verts[a][i1] + centx;
+ tria->vec[a][1] = sizey * verts[a][i2] + centy;
+ }
+
+ tria->center[0] = centx;
+ tria->center[1] = centy;
+
+ tria->tot = tris_tot;
+ tria->index = tris;
}
-static void shape_preset_init_number_arrows(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
+static void shape_preset_init_number_arrows(uiWidgetTrias *tria,
+ const rcti *rect,
+ float triasize,
+ char where)
{
- tria->type = ROUNDBOX_TRIA_ARROWS;
- shape_preset_init_trias_ex(
- tria, rect, triasize, where,
- g_shape_preset_number_arrow_vert, ARRAY_SIZE(g_shape_preset_number_arrow_vert),
- g_shape_preset_number_arrow_face, ARRAY_SIZE(g_shape_preset_number_arrow_face));
+ tria->type = ROUNDBOX_TRIA_ARROWS;
+ shape_preset_init_trias_ex(tria,
+ rect,
+ triasize,
+ where,
+ g_shape_preset_number_arrow_vert,
+ ARRAY_SIZE(g_shape_preset_number_arrow_vert),
+ g_shape_preset_number_arrow_face,
+ ARRAY_SIZE(g_shape_preset_number_arrow_face));
}
-static void shape_preset_init_hold_action(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
+static void shape_preset_init_hold_action(uiWidgetTrias *tria,
+ const rcti *rect,
+ float triasize,
+ char where)
{
- tria->type = ROUNDBOX_TRIA_HOLD_ACTION_ARROW;
- /* With the current changes to use batches for widget drawing, the code
- * below is doing almost nothing effectively. 'where' doesn't work either,
- * shader is currently hardcoded to work for the button triangle pointing
- * at the lower right. The same limitation applies to other trias as well.
- * XXX Should be addressed. */
- shape_preset_init_trias_ex(
- tria, rect, triasize, where,
- g_shape_preset_hold_action_vert, ARRAY_SIZE(g_shape_preset_hold_action_vert),
- g_shape_preset_hold_action_face, ARRAY_SIZE(g_shape_preset_hold_action_face));
+ tria->type = ROUNDBOX_TRIA_HOLD_ACTION_ARROW;
+ /* With the current changes to use batches for widget drawing, the code
+ * below is doing almost nothing effectively. 'where' doesn't work either,
+ * shader is currently hardcoded to work for the button triangle pointing
+ * at the lower right. The same limitation applies to other trias as well.
+ * XXX Should be addressed. */
+ shape_preset_init_trias_ex(tria,
+ rect,
+ triasize,
+ where,
+ g_shape_preset_hold_action_vert,
+ ARRAY_SIZE(g_shape_preset_hold_action_vert),
+ g_shape_preset_hold_action_face,
+ ARRAY_SIZE(g_shape_preset_hold_action_face));
}
-static void shape_preset_init_scroll_circle(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
+static void shape_preset_init_scroll_circle(uiWidgetTrias *tria,
+ const rcti *rect,
+ float triasize,
+ char where)
{
- tria->type = ROUNDBOX_TRIA_SCROLL;
- shape_preset_init_trias_ex(
- tria, rect, triasize, where,
- g_shape_preset_scroll_circle_vert, ARRAY_SIZE(g_shape_preset_scroll_circle_vert),
- g_shape_preset_scroll_circle_face, ARRAY_SIZE(g_shape_preset_scroll_circle_face));
+ tria->type = ROUNDBOX_TRIA_SCROLL;
+ shape_preset_init_trias_ex(tria,
+ rect,
+ triasize,
+ where,
+ g_shape_preset_scroll_circle_vert,
+ ARRAY_SIZE(g_shape_preset_scroll_circle_vert),
+ g_shape_preset_scroll_circle_face,
+ ARRAY_SIZE(g_shape_preset_scroll_circle_face));
}
-static void widget_draw_vertex_buffer(uint pos, uint col, int mode,
+static void widget_draw_vertex_buffer(uint pos,
+ uint col,
+ int mode,
const float quads_pos[WIDGET_SIZE_MAX][2],
const uchar quads_col[WIDGET_SIZE_MAX][4],
uint totvert)
{
- immBegin(mode, totvert);
- for (int i = 0; i < totvert; ++i) {
- if (quads_col) {
- immAttr4ubv(col, quads_col[i]);
- }
- immVertex2fv(pos, quads_pos[i]);
- }
- immEnd();
+ immBegin(mode, totvert);
+ for (int i = 0; i < totvert; ++i) {
+ if (quads_col) {
+ immAttr4ubv(col, quads_col[i]);
+ }
+ immVertex2fv(pos, quads_pos[i]);
+ }
+ immEnd();
}
static void shape_preset_trias_from_rect_menu(uiWidgetTrias *tria, const rcti *rect)
{
- float width = BLI_rcti_size_x(rect);
- float height = BLI_rcti_size_y(rect);
- float centx, centy, size;
+ float width = BLI_rcti_size_x(rect);
+ float height = BLI_rcti_size_y(rect);
+ float centx, centy, size;
- tria->type = ROUNDBOX_TRIA_MENU;
+ tria->type = ROUNDBOX_TRIA_MENU;
- /* Center position and size. */
- tria->center[0] = centx = rect->xmin + 0.52f * BLI_rcti_size_y(rect);
- tria->center[1] = centy = rect->ymin + 0.52f * BLI_rcti_size_y(rect);
- tria->size = size = 0.4f * height;
+ /* Center position and size. */
+ tria->center[0] = centx = rect->xmin + 0.52f * BLI_rcti_size_y(rect);
+ tria->center[1] = centy = rect->ymin + 0.52f * BLI_rcti_size_y(rect);
+ tria->size = size = 0.4f * height;
- if (width > height * 1.1f) {
- /* For wider buttons align tighter to the right. */
- tria->center[0] = centx = rect->xmax - 0.32f * height;
- }
+ if (width > height * 1.1f) {
+ /* For wider buttons align tighter to the right. */
+ tria->center[0] = centx = rect->xmax - 0.32f * height;
+ }
- for (int a = 0; a < 6; a++) {
- tria->vec[a][0] = size * g_shape_preset_menu_arrow_vert[a][0] + centx;
- tria->vec[a][1] = size * g_shape_preset_menu_arrow_vert[a][1] + centy;
- }
+ for (int a = 0; a < 6; a++) {
+ tria->vec[a][0] = size * g_shape_preset_menu_arrow_vert[a][0] + centx;
+ tria->vec[a][1] = size * g_shape_preset_menu_arrow_vert[a][1] + centy;
+ }
- tria->tot = 2;
- tria->index = g_shape_preset_menu_arrow_face;
+ tria->tot = 2;
+ tria->index = g_shape_preset_menu_arrow_face;
}
static void shape_preset_trias_from_rect_checkmark(uiWidgetTrias *tria, const rcti *rect)
{
- float centx, centy, size;
+ float centx, centy, size;
- tria->type = ROUNDBOX_TRIA_CHECK;
+ tria->type = ROUNDBOX_TRIA_CHECK;
- /* Center position and size. */
- tria->center[0] = centx = rect->xmin + 0.5f * BLI_rcti_size_y(rect);
- tria->center[1] = centy = rect->ymin + 0.5f * BLI_rcti_size_y(rect);
- tria->size = size = 0.5f * BLI_rcti_size_y(rect);
+ /* Center position and size. */
+ tria->center[0] = centx = rect->xmin + 0.5f * BLI_rcti_size_y(rect);
+ tria->center[1] = centy = rect->ymin + 0.5f * BLI_rcti_size_y(rect);
+ tria->size = size = 0.5f * BLI_rcti_size_y(rect);
- for (int a = 0; a < 6; a++) {
- tria->vec[a][0] = size * g_shape_preset_checkmark_vert[a][0] + centx;
- tria->vec[a][1] = size * g_shape_preset_checkmark_vert[a][1] + centy;
- }
+ for (int a = 0; a < 6; a++) {
+ tria->vec[a][0] = size * g_shape_preset_checkmark_vert[a][0] + centx;
+ tria->vec[a][1] = size * g_shape_preset_checkmark_vert[a][1] + centy;
+ }
- tria->tot = 4;
- tria->index = g_shape_preset_checkmark_face;
+ tria->tot = 4;
+ tria->index = g_shape_preset_checkmark_face;
}
/** \} */
-
/* prepares shade colors */
-static void shadecolors4(char coltop[4], char coldown[4], const char *color, short shadetop, short shadedown)
+static void shadecolors4(
+ char coltop[4], char coldown[4], const char *color, short shadetop, short shadedown)
{
- coltop[0] = CLAMPIS(color[0] + shadetop, 0, 255);
- coltop[1] = CLAMPIS(color[1] + shadetop, 0, 255);
- coltop[2] = CLAMPIS(color[2] + shadetop, 0, 255);
- coltop[3] = color[3];
-
- coldown[0] = CLAMPIS(color[0] + shadedown, 0, 255);
- coldown[1] = CLAMPIS(color[1] + shadedown, 0, 255);
- coldown[2] = CLAMPIS(color[2] + shadedown, 0, 255);
- coldown[3] = color[3];
+ coltop[0] = CLAMPIS(color[0] + shadetop, 0, 255);
+ coltop[1] = CLAMPIS(color[1] + shadetop, 0, 255);
+ coltop[2] = CLAMPIS(color[2] + shadetop, 0, 255);
+ coltop[3] = color[3];
+
+ coldown[0] = CLAMPIS(color[0] + shadedown, 0, 255);
+ coldown[1] = CLAMPIS(color[1] + shadedown, 0, 255);
+ coldown[2] = CLAMPIS(color[2] + shadedown, 0, 255);
+ coldown[3] = color[3];
}
-static void round_box_shade_col4_r(uchar r_col[4], const char col1[4], const char col2[4], const float fac)
+static void round_box_shade_col4_r(uchar r_col[4],
+ const char col1[4],
+ const char col2[4],
+ const float fac)
{
- const int faci = unit_float_to_uchar_clamp(fac);
- const int facm = 255 - faci;
+ const int faci = unit_float_to_uchar_clamp(fac);
+ const int facm = 255 - faci;
- r_col[0] = (faci * col1[0] + facm * col2[0]) / 256;
- r_col[1] = (faci * col1[1] + facm * col2[1]) / 256;
- r_col[2] = (faci * col1[2] + facm * col2[2]) / 256;
- r_col[3] = (faci * col1[3] + facm * col2[3]) / 256;
+ r_col[0] = (faci * col1[0] + facm * col2[0]) / 256;
+ r_col[1] = (faci * col1[1] + facm * col2[1]) / 256;
+ r_col[2] = (faci * col1[2] + facm * col2[2]) / 256;
+ r_col[3] = (faci * col1[3] + facm * col2[3]) / 256;
}
-static void widget_verts_to_triangle_strip(uiWidgetBase *wtb, const int totvert, float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2])
+static void widget_verts_to_triangle_strip(uiWidgetBase *wtb,
+ const int totvert,
+ float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2])
{
- int a;
- for (a = 0; a < totvert; a++) {
- copy_v2_v2(triangle_strip[a * 2], wtb->outer_v[a]);
- copy_v2_v2(triangle_strip[a * 2 + 1], wtb->inner_v[a]);
- }
- copy_v2_v2(triangle_strip[a * 2], wtb->outer_v[0]);
- copy_v2_v2(triangle_strip[a * 2 + 1], wtb->inner_v[0]);
+ int a;
+ for (a = 0; a < totvert; a++) {
+ copy_v2_v2(triangle_strip[a * 2], wtb->outer_v[a]);
+ copy_v2_v2(triangle_strip[a * 2 + 1], wtb->inner_v[a]);
+ }
+ copy_v2_v2(triangle_strip[a * 2], wtb->outer_v[0]);
+ copy_v2_v2(triangle_strip[a * 2 + 1], wtb->inner_v[0]);
}
static void widgetbase_outline(uiWidgetBase *wtb, uint pos)
{
- float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
- widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip);
+ float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
+ widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip);
- widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, wtb->totvert * 2 + 2);
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, wtb->totvert * 2 + 2);
}
-static void widgetbase_set_uniform_alpha_discard(
- uiWidgetBase *wtb,
- const bool alpha_check,
- const float discard_factor)
+static void widgetbase_set_uniform_alpha_discard(uiWidgetBase *wtb,
+ const bool alpha_check,
+ const float discard_factor)
{
- if (alpha_check) {
- wtb->uniform_params.alpha_discard = -discard_factor;
- }
- else {
- wtb->uniform_params.alpha_discard = discard_factor;
- }
+ if (alpha_check) {
+ wtb->uniform_params.alpha_discard = -discard_factor;
+ }
+ else {
+ wtb->uniform_params.alpha_discard = discard_factor;
+ }
}
-static void widgetbase_set_uniform_alpha_check(
- uiWidgetBase *wtb,
- const bool alpha_check)
+static void widgetbase_set_uniform_alpha_check(uiWidgetBase *wtb, const bool alpha_check)
{
- const float discard_factor = fabs(wtb->uniform_params.alpha_discard);
- widgetbase_set_uniform_alpha_discard(wtb, alpha_check, discard_factor);
+ const float discard_factor = fabs(wtb->uniform_params.alpha_discard);
+ widgetbase_set_uniform_alpha_discard(wtb, alpha_check, discard_factor);
}
-static void widgetbase_set_uniform_discard_factor(
- uiWidgetBase *wtb,
- const float discard_factor)
+static void widgetbase_set_uniform_discard_factor(uiWidgetBase *wtb, const float discard_factor)
{
- bool alpha_check = wtb->uniform_params.alpha_discard < 0.0f;
- widgetbase_set_uniform_alpha_discard(wtb, alpha_check, discard_factor);
+ bool alpha_check = wtb->uniform_params.alpha_discard < 0.0f;
+ widgetbase_set_uniform_alpha_discard(wtb, alpha_check, discard_factor);
}
-static void widgetbase_set_uniform_colors_ubv(
- uiWidgetBase *wtb,
- const uchar *col1, const uchar *col2,
- const uchar *outline,
- const uchar *emboss,
- const uchar *tria,
- const bool alpha_check)
+static void widgetbase_set_uniform_colors_ubv(uiWidgetBase *wtb,
+ const uchar *col1,
+ const uchar *col2,
+ const uchar *outline,
+ const uchar *emboss,
+ const uchar *tria,
+ const bool alpha_check)
{
- widgetbase_set_uniform_alpha_check(wtb, alpha_check);
- rgba_float_args_set_ch(wtb->uniform_params.color_inner1, col1[0], col1[1], col1[2], col1[3]);
- rgba_float_args_set_ch(wtb->uniform_params.color_inner2, col2[0], col2[1], col2[2], col2[3]);
- rgba_float_args_set_ch(wtb->uniform_params.color_outline, outline[0], outline[1], outline[2], outline[3]);
- rgba_float_args_set_ch(wtb->uniform_params.color_emboss, emboss[0], emboss[1], emboss[2], emboss[3]);
- rgba_float_args_set_ch(wtb->uniform_params.color_tria, tria[0], tria[1], tria[2], tria[3]);
+ widgetbase_set_uniform_alpha_check(wtb, alpha_check);
+ rgba_float_args_set_ch(wtb->uniform_params.color_inner1, col1[0], col1[1], col1[2], col1[3]);
+ rgba_float_args_set_ch(wtb->uniform_params.color_inner2, col2[0], col2[1], col2[2], col2[3]);
+ rgba_float_args_set_ch(
+ wtb->uniform_params.color_outline, outline[0], outline[1], outline[2], outline[3]);
+ rgba_float_args_set_ch(
+ wtb->uniform_params.color_emboss, emboss[0], emboss[1], emboss[2], emboss[3]);
+ rgba_float_args_set_ch(wtb->uniform_params.color_tria, tria[0], tria[1], tria[2], tria[3]);
}
/* keep in sync with shader */
@@ -1145,165 +1229,173 @@ static void widgetbase_set_uniform_colors_ubv(
#define MAX_WIDGET_PARAMETERS 11
static struct {
- GPUBatch *batch; /* Batch type */
- uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH];
- int count;
- bool enabled;
+ GPUBatch *batch; /* Batch type */
+ uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH];
+ int count;
+ bool enabled;
} g_widget_base_batch = {0};
void UI_widgetbase_draw_cache_flush(void)
{
- float checker_params[3] = {UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 8.0f};
-
- if (g_widget_base_batch.count == 0) {
- return;
- }
-
- GPUBatch *batch = g_widget_base_batch.batch;
- if (g_widget_base_batch.count == 1) {
- /* draw single */
- GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
- GPU_batch_uniform_4fv_array(batch, "parameters", MAX_WIDGET_PARAMETERS, (float *)g_widget_base_batch.params);
- GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
- GPU_batch_draw(batch);
- }
- else {
- GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE_INST);
- GPU_batch_uniform_4fv_array(batch, "parameters", MAX_WIDGET_PARAMETERS * MAX_WIDGET_BASE_BATCH,
- (float *)g_widget_base_batch.params);
- GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
- GPU_matrix_bind(batch->interface);
- GPU_batch_draw_range_ex(batch, 0, g_widget_base_batch.count, true);
- GPU_batch_program_use_end(batch);
- }
- g_widget_base_batch.count = 0;
+ float checker_params[3] = {
+ UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 8.0f};
+
+ if (g_widget_base_batch.count == 0) {
+ return;
+ }
+
+ GPUBatch *batch = g_widget_base_batch.batch;
+ if (g_widget_base_batch.count == 1) {
+ /* draw single */
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GPU_batch_uniform_4fv_array(
+ batch, "parameters", MAX_WIDGET_PARAMETERS, (float *)g_widget_base_batch.params);
+ GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
+ GPU_batch_draw(batch);
+ }
+ else {
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE_INST);
+ GPU_batch_uniform_4fv_array(batch,
+ "parameters",
+ MAX_WIDGET_PARAMETERS * MAX_WIDGET_BASE_BATCH,
+ (float *)g_widget_base_batch.params);
+ GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
+ GPU_matrix_bind(batch->interface);
+ GPU_batch_draw_range_ex(batch, 0, g_widget_base_batch.count, true);
+ GPU_batch_program_use_end(batch);
+ }
+ g_widget_base_batch.count = 0;
}
void UI_widgetbase_draw_cache_begin(void)
{
- BLI_assert(g_widget_base_batch.enabled == false);
- g_widget_base_batch.enabled = true;
+ BLI_assert(g_widget_base_batch.enabled == false);
+ g_widget_base_batch.enabled = true;
}
void UI_widgetbase_draw_cache_end(void)
{
- BLI_assert(g_widget_base_batch.enabled == true);
- g_widget_base_batch.enabled = false;
+ BLI_assert(g_widget_base_batch.enabled == true);
+ g_widget_base_batch.enabled = false;
- GPU_blend(true);
+ GPU_blend(true);
- UI_widgetbase_draw_cache_flush();
+ UI_widgetbase_draw_cache_flush();
- GPU_blend(false);
+ GPU_blend(false);
}
static void draw_widgetbase_batch(GPUBatch *batch, uiWidgetBase *wtb)
{
- wtb->uniform_params.tria1_size = wtb->tria1.size;
- wtb->uniform_params.tria2_size = wtb->tria2.size;
- copy_v2_v2(wtb->uniform_params.tria1_center, wtb->tria1.center);
- copy_v2_v2(wtb->uniform_params.tria2_center, wtb->tria2.center);
-
- if (g_widget_base_batch.enabled) {
- if (g_widget_base_batch.batch == NULL) {
- g_widget_base_batch.batch = ui_batch_roundbox_widget_get(ROUNDBOX_TRIA_ARROWS);
- }
-
- /* draw multi */
- if (batch != g_ui_batch_cache.roundbox_widget[ROUNDBOX_TRIA_NONE] &&
- batch != g_widget_base_batch.batch)
- {
- /* issue previous calls before changing batch type. */
- UI_widgetbase_draw_cache_flush();
- g_widget_base_batch.batch = batch;
- }
-
- /* No need to change batch if tria is not visible. Just scale it to 0. */
- if (batch == g_ui_batch_cache.roundbox_widget[ROUNDBOX_TRIA_NONE]) {
- wtb->uniform_params.tria1_size = wtb->uniform_params.tria2_size = 0;
- }
-
- g_widget_base_batch.params[g_widget_base_batch.count] = wtb->uniform_params;
- g_widget_base_batch.count++;
-
- if (g_widget_base_batch.count == MAX_WIDGET_BASE_BATCH) {
- UI_widgetbase_draw_cache_flush();
- }
- }
- else {
- float checker_params[3] = {UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 8.0f};
- /* draw single */
- GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
- GPU_batch_uniform_4fv_array(batch, "parameters", MAX_WIDGET_PARAMETERS, (float *)&wtb->uniform_params);
- GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
- GPU_batch_draw(batch);
- }
+ wtb->uniform_params.tria1_size = wtb->tria1.size;
+ wtb->uniform_params.tria2_size = wtb->tria2.size;
+ copy_v2_v2(wtb->uniform_params.tria1_center, wtb->tria1.center);
+ copy_v2_v2(wtb->uniform_params.tria2_center, wtb->tria2.center);
+
+ if (g_widget_base_batch.enabled) {
+ if (g_widget_base_batch.batch == NULL) {
+ g_widget_base_batch.batch = ui_batch_roundbox_widget_get(ROUNDBOX_TRIA_ARROWS);
+ }
+
+ /* draw multi */
+ if (batch != g_ui_batch_cache.roundbox_widget[ROUNDBOX_TRIA_NONE] &&
+ batch != g_widget_base_batch.batch) {
+ /* issue previous calls before changing batch type. */
+ UI_widgetbase_draw_cache_flush();
+ g_widget_base_batch.batch = batch;
+ }
+
+ /* No need to change batch if tria is not visible. Just scale it to 0. */
+ if (batch == g_ui_batch_cache.roundbox_widget[ROUNDBOX_TRIA_NONE]) {
+ wtb->uniform_params.tria1_size = wtb->uniform_params.tria2_size = 0;
+ }
+
+ g_widget_base_batch.params[g_widget_base_batch.count] = wtb->uniform_params;
+ g_widget_base_batch.count++;
+
+ if (g_widget_base_batch.count == MAX_WIDGET_BASE_BATCH) {
+ UI_widgetbase_draw_cache_flush();
+ }
+ }
+ else {
+ float checker_params[3] = {
+ UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 8.0f};
+ /* draw single */
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GPU_batch_uniform_4fv_array(
+ batch, "parameters", MAX_WIDGET_PARAMETERS, (float *)&wtb->uniform_params);
+ GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
+ GPU_batch_draw(batch);
+ }
}
-static void widgetbase_draw_ex(
- uiWidgetBase *wtb, const uiWidgetColors *wcol,
- bool show_alpha_checkers)
+static void widgetbase_draw_ex(uiWidgetBase *wtb,
+ const uiWidgetColors *wcol,
+ bool show_alpha_checkers)
{
- uchar inner_col1[4] = {0};
- uchar inner_col2[4] = {0};
- uchar emboss_col[4] = {0};
- uchar outline_col[4] = {0};
- uchar tria_col[4] = {0};
- /* For color widget. */
- if (wcol->shaded != 0) {
- show_alpha_checkers = false;
- }
-
- GPU_blend(true);
-
- /* backdrop non AA */
- if (wtb->draw_inner) {
- if (wcol->shaded == 0) {
- /* simple fill */
- inner_col1[0] = inner_col2[0] = (uchar)wcol->inner[0];
- inner_col1[1] = inner_col2[1] = (uchar)wcol->inner[1];
- inner_col1[2] = inner_col2[2] = (uchar)wcol->inner[2];
- inner_col1[3] = inner_col2[3] = (uchar)wcol->inner[3];
- }
- else {
- /* gradient fill */
- shadecolors4((char *)inner_col1, (char *)inner_col2, wcol->inner, wcol->shadetop, wcol->shadedown);
- }
- }
-
- if (wtb->draw_outline) {
- outline_col[0] = wcol->outline[0];
- outline_col[1] = wcol->outline[1];
- outline_col[2] = wcol->outline[2];
- outline_col[3] = wcol->outline[3] / WIDGET_AA_JITTER;
-
- /* emboss bottom shadow */
- if (wtb->draw_emboss) {
- UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss_col);
- }
- }
-
- if (wtb->tria1.type != ROUNDBOX_TRIA_NONE) {
- tria_col[0] = wcol->item[0];
- tria_col[1] = wcol->item[1];
- tria_col[2] = wcol->item[2];
- tria_col[3] = (uchar)((float)wcol->item[3] / WIDGET_AA_JITTER);
- }
-
- /* Draw everything in one drawcall */
- if (inner_col1[3] || inner_col2[3] || outline_col[3] || emboss_col[3] || tria_col[3] || show_alpha_checkers) {
- widgetbase_set_uniform_colors_ubv(wtb, inner_col1, inner_col2, outline_col, emboss_col, tria_col, show_alpha_checkers);
-
- GPUBatch *roundbox_batch = ui_batch_roundbox_widget_get(wtb->tria1.type);
- draw_widgetbase_batch(roundbox_batch, wtb);
- }
-
- GPU_blend(false);
+ uchar inner_col1[4] = {0};
+ uchar inner_col2[4] = {0};
+ uchar emboss_col[4] = {0};
+ uchar outline_col[4] = {0};
+ uchar tria_col[4] = {0};
+ /* For color widget. */
+ if (wcol->shaded != 0) {
+ show_alpha_checkers = false;
+ }
+
+ GPU_blend(true);
+
+ /* backdrop non AA */
+ if (wtb->draw_inner) {
+ if (wcol->shaded == 0) {
+ /* simple fill */
+ inner_col1[0] = inner_col2[0] = (uchar)wcol->inner[0];
+ inner_col1[1] = inner_col2[1] = (uchar)wcol->inner[1];
+ inner_col1[2] = inner_col2[2] = (uchar)wcol->inner[2];
+ inner_col1[3] = inner_col2[3] = (uchar)wcol->inner[3];
+ }
+ else {
+ /* gradient fill */
+ shadecolors4(
+ (char *)inner_col1, (char *)inner_col2, wcol->inner, wcol->shadetop, wcol->shadedown);
+ }
+ }
+
+ if (wtb->draw_outline) {
+ outline_col[0] = wcol->outline[0];
+ outline_col[1] = wcol->outline[1];
+ outline_col[2] = wcol->outline[2];
+ outline_col[3] = wcol->outline[3] / WIDGET_AA_JITTER;
+
+ /* emboss bottom shadow */
+ if (wtb->draw_emboss) {
+ UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss_col);
+ }
+ }
+
+ if (wtb->tria1.type != ROUNDBOX_TRIA_NONE) {
+ tria_col[0] = wcol->item[0];
+ tria_col[1] = wcol->item[1];
+ tria_col[2] = wcol->item[2];
+ tria_col[3] = (uchar)((float)wcol->item[3] / WIDGET_AA_JITTER);
+ }
+
+ /* Draw everything in one drawcall */
+ if (inner_col1[3] || inner_col2[3] || outline_col[3] || emboss_col[3] || tria_col[3] ||
+ show_alpha_checkers) {
+ widgetbase_set_uniform_colors_ubv(
+ wtb, inner_col1, inner_col2, outline_col, emboss_col, tria_col, show_alpha_checkers);
+
+ GPUBatch *roundbox_batch = ui_batch_roundbox_widget_get(wtb->tria1.type);
+ draw_widgetbase_batch(roundbox_batch, wtb);
+ }
+
+ GPU_blend(false);
}
static void widgetbase_draw(uiWidgetBase *wtb, const uiWidgetColors *wcol)
{
- widgetbase_draw_ex(wtb, wcol, false);
+ widgetbase_draw_ex(wtb, wcol, false);
}
/* *********************** text/icon ************************************** */
@@ -1314,160 +1406,162 @@ static void widgetbase_draw(uiWidgetBase *wtb, const uiWidgetColors *wcol)
static void widget_draw_preview(BIFIconID icon, float alpha, const rcti *rect)
{
- int w, h, size;
+ int w, h, size;
- if (icon == ICON_NONE) {
- return;
- }
+ if (icon == ICON_NONE) {
+ return;
+ }
- w = BLI_rcti_size_x(rect);
- h = BLI_rcti_size_y(rect);
- size = MIN2(w, h);
- size -= PREVIEW_PAD * 2; /* padding */
+ w = BLI_rcti_size_x(rect);
+ h = BLI_rcti_size_y(rect);
+ size = MIN2(w, h);
+ size -= PREVIEW_PAD * 2; /* padding */
- if (size > 0) {
- int x = rect->xmin + w / 2 - size / 2;
- int y = rect->ymin + h / 2 - size / 2;
+ if (size > 0) {
+ int x = rect->xmin + w / 2 - size / 2;
+ int y = rect->ymin + h / 2 - size / 2;
- UI_icon_draw_preview_aspect_size(x, y, icon, 1.0f, alpha, size);
- }
+ UI_icon_draw_preview_aspect_size(x, y, icon, 1.0f, alpha, size);
+ }
}
-
static int ui_but_draw_menu_icon(const uiBut *but)
{
- return (but->flag & UI_BUT_ICON_SUBMENU) && (but->dt == UI_EMBOSS_PULLDOWN);
+ return (but->flag & UI_BUT_ICON_SUBMENU) && (but->dt == UI_EMBOSS_PULLDOWN);
}
/* icons have been standardized... and this call draws in untransformed coordinates */
static void widget_draw_icon(
- const uiBut *but, BIFIconID icon, float alpha,
- const rcti *rect, const char mono_color[4])
+ const uiBut *but, BIFIconID icon, float alpha, const rcti *rect, const char mono_color[4])
{
- float xs = 0.0f, ys = 0.0f;
- float aspect, height;
-
- if (but->flag & UI_BUT_ICON_PREVIEW) {
- GPU_blend(true);
- widget_draw_preview(icon, alpha, rect);
- GPU_blend(false);
- return;
- }
-
- /* this icon doesn't need draw... */
- if (icon == ICON_BLANK1 && (but->flag & UI_BUT_ICON_SUBMENU) == 0) {
- return;
- }
-
- aspect = but->block->aspect / UI_DPI_FAC;
- height = ICON_DEFAULT_HEIGHT / aspect;
-
- /* calculate blend color */
- if (ELEM(but->type, UI_BTYPE_TOGGLE, UI_BTYPE_ROW, UI_BTYPE_TOGGLE_N, UI_BTYPE_LISTROW)) {
- if (but->flag & UI_SELECT) {
- /* pass */
- }
- else if (but->flag & UI_ACTIVE) {
- /* pass */
- }
- else {
- alpha = 0.75f;
- }
- }
- else if ((but->type == UI_BTYPE_LABEL)) {
- /* extra feature allows more alpha blending */
- if (but->a1 == 1.0f) {
- alpha *= but->a2;
- }
- }
- else if (ELEM(but->type, UI_BTYPE_BUT)) {
- if (but->flag & UI_BUT_DISABLED) {
- alpha *= 0.5f;
- }
- }
-
- GPU_blend(true);
-
- if (icon && icon != ICON_BLANK1) {
- float ofs = 1.0f / aspect;
-
- if (but->drawflag & UI_BUT_ICON_LEFT) {
- /* special case - icon_only pie buttons */
- if (ui_block_is_pie_menu(but->block) && !ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_POPOVER) && but->str && but->str[0] == '\0') {
- xs = rect->xmin + 2.0f * ofs;
- }
- else if (but->dt == UI_EMBOSS_NONE || but->type == UI_BTYPE_LABEL) {
- xs = rect->xmin + 2.0f * ofs;
- }
- else {
- xs = rect->xmin + 4.0f * ofs;
- }
- }
- else {
- xs = (rect->xmin + rect->xmax - height) / 2.0f;
- }
- ys = (rect->ymin + rect->ymax - height) / 2.0f;
-
- /* force positions to integers, for zoom levels near 1. draws icons crisp. */
- if (aspect > 0.95f && aspect < 1.05f) {
- xs = (int)(xs + 0.1f);
- ys = (int)(ys + 0.1f);
- }
-
- /* to indicate draggable */
- if (but->dragpoin && (but->flag & UI_ACTIVE)) {
- float rgb[3] = {1.25f, 1.25f, 1.25f};
- UI_icon_draw_aspect_color(xs, ys, icon, aspect, rgb, mono_color);
- }
- else if ((but->flag & (UI_ACTIVE | UI_SELECT | UI_SELECT_DRAW)) || !UI_but_is_tool(but)) {
- UI_icon_draw_aspect(xs, ys, icon, aspect, alpha, mono_color);
- }
- else {
- const bTheme *btheme = UI_GetTheme();
- UI_icon_draw_desaturate(xs, ys, icon, aspect, alpha, 1.0 - btheme->tui.icon_saturation, mono_color);
- }
- }
-
- GPU_blend(false);
+ float xs = 0.0f, ys = 0.0f;
+ float aspect, height;
+
+ if (but->flag & UI_BUT_ICON_PREVIEW) {
+ GPU_blend(true);
+ widget_draw_preview(icon, alpha, rect);
+ GPU_blend(false);
+ return;
+ }
+
+ /* this icon doesn't need draw... */
+ if (icon == ICON_BLANK1 && (but->flag & UI_BUT_ICON_SUBMENU) == 0) {
+ return;
+ }
+
+ aspect = but->block->aspect / UI_DPI_FAC;
+ height = ICON_DEFAULT_HEIGHT / aspect;
+
+ /* calculate blend color */
+ if (ELEM(but->type, UI_BTYPE_TOGGLE, UI_BTYPE_ROW, UI_BTYPE_TOGGLE_N, UI_BTYPE_LISTROW)) {
+ if (but->flag & UI_SELECT) {
+ /* pass */
+ }
+ else if (but->flag & UI_ACTIVE) {
+ /* pass */
+ }
+ else {
+ alpha = 0.75f;
+ }
+ }
+ else if ((but->type == UI_BTYPE_LABEL)) {
+ /* extra feature allows more alpha blending */
+ if (but->a1 == 1.0f) {
+ alpha *= but->a2;
+ }
+ }
+ else if (ELEM(but->type, UI_BTYPE_BUT)) {
+ if (but->flag & UI_BUT_DISABLED) {
+ alpha *= 0.5f;
+ }
+ }
+
+ GPU_blend(true);
+
+ if (icon && icon != ICON_BLANK1) {
+ float ofs = 1.0f / aspect;
+
+ if (but->drawflag & UI_BUT_ICON_LEFT) {
+ /* special case - icon_only pie buttons */
+ if (ui_block_is_pie_menu(but->block) && !ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_POPOVER) &&
+ but->str && but->str[0] == '\0') {
+ xs = rect->xmin + 2.0f * ofs;
+ }
+ else if (but->dt == UI_EMBOSS_NONE || but->type == UI_BTYPE_LABEL) {
+ xs = rect->xmin + 2.0f * ofs;
+ }
+ else {
+ xs = rect->xmin + 4.0f * ofs;
+ }
+ }
+ else {
+ xs = (rect->xmin + rect->xmax - height) / 2.0f;
+ }
+ ys = (rect->ymin + rect->ymax - height) / 2.0f;
+
+ /* force positions to integers, for zoom levels near 1. draws icons crisp. */
+ if (aspect > 0.95f && aspect < 1.05f) {
+ xs = (int)(xs + 0.1f);
+ ys = (int)(ys + 0.1f);
+ }
+
+ /* to indicate draggable */
+ if (but->dragpoin && (but->flag & UI_ACTIVE)) {
+ float rgb[3] = {1.25f, 1.25f, 1.25f};
+ UI_icon_draw_aspect_color(xs, ys, icon, aspect, rgb, mono_color);
+ }
+ else if ((but->flag & (UI_ACTIVE | UI_SELECT | UI_SELECT_DRAW)) || !UI_but_is_tool(but)) {
+ UI_icon_draw_aspect(xs, ys, icon, aspect, alpha, mono_color);
+ }
+ else {
+ const bTheme *btheme = UI_GetTheme();
+ UI_icon_draw_desaturate(
+ xs, ys, icon, aspect, alpha, 1.0 - btheme->tui.icon_saturation, mono_color);
+ }
+ }
+
+ GPU_blend(false);
}
-static void widget_draw_submenu_tria(const uiBut *but, const rcti *rect, const uiWidgetColors *wcol)
+static void widget_draw_submenu_tria(const uiBut *but,
+ const rcti *rect,
+ const uiWidgetColors *wcol)
{
- const float aspect = but->block->aspect / UI_DPI_FAC;
- const int tria_height = (int)(ICON_DEFAULT_HEIGHT / aspect);
- const int tria_width = (int)(ICON_DEFAULT_WIDTH / aspect) - 2 * U.pixelsize;
- const int xs = rect->xmax - tria_width;
- const int ys = (rect->ymin + rect->ymax - tria_height) / 2.0f;
- float col[4];
- rctf tria_rect;
-
- rgba_uchar_to_float(col, (const uchar *)wcol->text);
- col[3] *= 0.8f;
-
- BLI_rctf_init(&tria_rect, xs, xs + tria_width, ys, ys + tria_height);
- BLI_rctf_scale(&tria_rect, 0.4f);
-
- GPU_blend(true);
- UI_widgetbase_draw_cache_flush();
- GPU_blend(false);
- ui_draw_anti_tria_rect(&tria_rect, 'h', col);
+ const float aspect = but->block->aspect / UI_DPI_FAC;
+ const int tria_height = (int)(ICON_DEFAULT_HEIGHT / aspect);
+ const int tria_width = (int)(ICON_DEFAULT_WIDTH / aspect) - 2 * U.pixelsize;
+ const int xs = rect->xmax - tria_width;
+ const int ys = (rect->ymin + rect->ymax - tria_height) / 2.0f;
+ float col[4];
+ rctf tria_rect;
+
+ rgba_uchar_to_float(col, (const uchar *)wcol->text);
+ col[3] *= 0.8f;
+
+ BLI_rctf_init(&tria_rect, xs, xs + tria_width, ys, ys + tria_height);
+ BLI_rctf_scale(&tria_rect, 0.4f);
+
+ GPU_blend(true);
+ UI_widgetbase_draw_cache_flush();
+ GPU_blend(false);
+ ui_draw_anti_tria_rect(&tria_rect, 'h', col);
}
static void ui_text_clip_give_prev_off(uiBut *but, const char *str)
{
- const char *prev_utf8 = BLI_str_find_prev_char_utf8(str, str + but->ofs);
- int bytes = str + but->ofs - prev_utf8;
+ const char *prev_utf8 = BLI_str_find_prev_char_utf8(str, str + but->ofs);
+ int bytes = str + but->ofs - prev_utf8;
- but->ofs -= bytes;
+ but->ofs -= bytes;
}
static void ui_text_clip_give_next_off(uiBut *but, const char *str)
{
- const char *next_utf8 = BLI_str_find_next_char_utf8(str + but->ofs, NULL);
- int bytes = next_utf8 - (str + but->ofs);
+ const char *next_utf8 = BLI_str_find_next_char_utf8(str + but->ofs, NULL);
+ int bytes = next_utf8 - (str + but->ofs);
- but->ofs += bytes;
+ but->ofs += bytes;
}
/**
@@ -1475,32 +1569,37 @@ static void ui_text_clip_give_next_off(uiBut *but, const char *str)
* This func assumes things like kerning handling have already been handled!
* Return the length of modified (right-clipped + ellipsis) string.
*/
-static void ui_text_clip_right_ex(
- const uiFontStyle *fstyle, char *str, const size_t max_len, const float okwidth,
- const char *sep, const int sep_len, const float sep_strwidth, size_t *r_final_len)
+static void ui_text_clip_right_ex(const uiFontStyle *fstyle,
+ char *str,
+ const size_t max_len,
+ const float okwidth,
+ const char *sep,
+ const int sep_len,
+ const float sep_strwidth,
+ size_t *r_final_len)
{
- float tmp;
- int l_end;
-
- BLI_assert(str[0]);
-
- /* If the trailing ellipsis takes more than 20% of all available width, just cut the string
- * (as using the ellipsis would remove even more useful chars, and we cannot show much already!).
- */
- if (sep_strwidth / okwidth > 0.2f) {
- l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth, &tmp);
- str[l_end] = '\0';
- if (r_final_len) {
- *r_final_len = (size_t)l_end;
- }
- }
- else {
- l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth - sep_strwidth, &tmp);
- memcpy(str + l_end, sep, sep_len + 1); /* +1 for trailing '\0'. */
- if (r_final_len) {
- *r_final_len = (size_t)(l_end + sep_len);
- }
- }
+ float tmp;
+ int l_end;
+
+ BLI_assert(str[0]);
+
+ /* If the trailing ellipsis takes more than 20% of all available width, just cut the string
+ * (as using the ellipsis would remove even more useful chars, and we cannot show much already!).
+ */
+ if (sep_strwidth / okwidth > 0.2f) {
+ l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth, &tmp);
+ str[l_end] = '\0';
+ if (r_final_len) {
+ *r_final_len = (size_t)l_end;
+ }
+ }
+ else {
+ l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth - sep_strwidth, &tmp);
+ memcpy(str + l_end, sep, sep_len + 1); /* +1 for trailing '\0'. */
+ if (r_final_len) {
+ *r_final_len = (size_t)(l_end + sep_len);
+ }
+ }
}
/**
@@ -1509,126 +1608,131 @@ static void ui_text_clip_right_ex(
* If rpart_sep is not Null, the part of str starting to first occurrence of rpart_sep is preserved at all cost (useful
* for strings with shortcuts, like 'AVeryLongFooBarLabelForMenuEntry|Ctrl O' -> 'AVeryLong...MenuEntry|Ctrl O').
*/
-float UI_text_clip_middle_ex(
- const uiFontStyle *fstyle, char *str, float okwidth, const float minwidth,
- const size_t max_len, const char rpart_sep)
+float UI_text_clip_middle_ex(const uiFontStyle *fstyle,
+ char *str,
+ float okwidth,
+ const float minwidth,
+ const size_t max_len,
+ const char rpart_sep)
{
- float strwidth;
-
- /* Add some epsilon to OK width, avoids 'ellipsing' text that nearly fits!
- * Better to have a small piece of the last char cut out,
- * than two remaining chars replaced by an ellipsis... */
- okwidth += 1.0f + UI_DPI_FAC;
-
- BLI_assert(str[0]);
-
- /* need to set this first */
- UI_fontstyle_set(fstyle);
-
- if (fstyle->kerning == 1) {
- /* for BLF_width */
- BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- }
-
- 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 litteral string. */
- const char sep[] = {0xe2, 0x80, 0xA5, 0x0};
- const int sep_len = sizeof(sep) - 1;
- const float sep_strwidth = BLF_width(fstyle->uifont_id, sep, sep_len + 1);
- float parts_strwidth;
- size_t l_end;
-
- char *rpart = NULL, rpart_buf[UI_MAX_DRAW_STR];
- float rpart_width = 0.0f;
- size_t rpart_len = 0;
- size_t final_lpart_len;
-
- if (rpart_sep) {
- rpart = strrchr(str, rpart_sep);
-
- if (rpart) {
- rpart_len = strlen(rpart);
- rpart_width = BLF_width(fstyle->uifont_id, rpart, rpart_len);
- okwidth -= rpart_width;
- strwidth -= rpart_width;
-
- if (okwidth < 0.0f) {
- /* Not enough place for actual label, just display protected right part.
- * Here just for safety, should never happen in real life! */
- memmove(str, rpart, rpart_len + 1);
- rpart = NULL;
- okwidth += rpart_width;
- strwidth = rpart_width;
- }
- }
- }
-
- parts_strwidth = (okwidth - sep_strwidth) / 2.0f;
-
- if (rpart) {
- strcpy(rpart_buf, rpart);
- *rpart = '\0';
- rpart = rpart_buf;
- }
-
- l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, parts_strwidth, NULL);
- if (l_end < 10 || min_ff(parts_strwidth, strwidth - okwidth) < minwidth) {
- /* If we really have no place, or we would clip a very small piece of string in the middle,
- * only show start of string.
- */
- ui_text_clip_right_ex(fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth, &final_lpart_len);
- }
- else {
- size_t r_offset, r_len;
-
- r_offset = BLF_width_to_rstrlen(fstyle->uifont_id, str, max_len, parts_strwidth, NULL);
- r_len = strlen(str + r_offset) + 1; /* +1 for the trailing '\0'. */
-
- if (l_end + sep_len + r_len + rpart_len > max_len) {
- /* Corner case, the str already takes all available mem, and the ellipsis chars would actually
- * add more chars...
- * Better to just trim one or two letters to the right in this case...
- * Note: with a single-char ellipsis, this should never happen! But better be safe here...
- */
- ui_text_clip_right_ex(fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth, &final_lpart_len);
- }
- else {
- memmove(str + l_end + sep_len, str + r_offset, r_len);
- memcpy(str + l_end, sep, sep_len);
- /* -1 to remove trailing '\0'! */
- final_lpart_len = (size_t)(l_end + sep_len + r_len - 1);
-
- while (BLF_width(fstyle->uifont_id, str, max_len) > okwidth) {
- /* This will happen because a lot of string width processing is done in integer pixels,
- * which can introduce a rather high error in the end (about 2 pixels or so).
- * Only one char removal shall ever be needed in real-life situation... */
- r_len--;
- final_lpart_len--;
- char *c = str + l_end + sep_len;
- memmove(c, c + 1, r_len);
- }
- }
- }
-
- if (rpart) {
- /* Add back preserved right part to our shorten str. */
- memcpy(str + final_lpart_len, rpart, rpart_len + 1); /* +1 for trailing '\0'. */
- okwidth += rpart_width;
- }
-
- strwidth = BLF_width(fstyle->uifont_id, str, max_len);
- }
-
- if (fstyle->kerning == 1) {
- BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- }
-
- BLI_assert(strwidth <= okwidth);
-
- return strwidth;
+ float strwidth;
+
+ /* Add some epsilon to OK width, avoids 'ellipsing' text that nearly fits!
+ * Better to have a small piece of the last char cut out,
+ * than two remaining chars replaced by an ellipsis... */
+ okwidth += 1.0f + UI_DPI_FAC;
+
+ BLI_assert(str[0]);
+
+ /* need to set this first */
+ UI_fontstyle_set(fstyle);
+
+ if (fstyle->kerning == 1) {
+ /* for BLF_width */
+ BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
+
+ 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 litteral string. */
+ const char sep[] = {0xe2, 0x80, 0xA5, 0x0};
+ const int sep_len = sizeof(sep) - 1;
+ const float sep_strwidth = BLF_width(fstyle->uifont_id, sep, sep_len + 1);
+ float parts_strwidth;
+ size_t l_end;
+
+ char *rpart = NULL, rpart_buf[UI_MAX_DRAW_STR];
+ float rpart_width = 0.0f;
+ size_t rpart_len = 0;
+ size_t final_lpart_len;
+
+ if (rpart_sep) {
+ rpart = strrchr(str, rpart_sep);
+
+ if (rpart) {
+ rpart_len = strlen(rpart);
+ rpart_width = BLF_width(fstyle->uifont_id, rpart, rpart_len);
+ okwidth -= rpart_width;
+ strwidth -= rpart_width;
+
+ if (okwidth < 0.0f) {
+ /* Not enough place for actual label, just display protected right part.
+ * Here just for safety, should never happen in real life! */
+ memmove(str, rpart, rpart_len + 1);
+ rpart = NULL;
+ okwidth += rpart_width;
+ strwidth = rpart_width;
+ }
+ }
+ }
+
+ parts_strwidth = (okwidth - sep_strwidth) / 2.0f;
+
+ if (rpart) {
+ strcpy(rpart_buf, rpart);
+ *rpart = '\0';
+ rpart = rpart_buf;
+ }
+
+ l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, parts_strwidth, NULL);
+ if (l_end < 10 || min_ff(parts_strwidth, strwidth - okwidth) < minwidth) {
+ /* If we really have no place, or we would clip a very small piece of string in the middle,
+ * only show start of string.
+ */
+ ui_text_clip_right_ex(
+ fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth, &final_lpart_len);
+ }
+ else {
+ size_t r_offset, r_len;
+
+ r_offset = BLF_width_to_rstrlen(fstyle->uifont_id, str, max_len, parts_strwidth, NULL);
+ r_len = strlen(str + r_offset) + 1; /* +1 for the trailing '\0'. */
+
+ if (l_end + sep_len + r_len + rpart_len > max_len) {
+ /* Corner case, the str already takes all available mem, and the ellipsis chars would actually
+ * add more chars...
+ * Better to just trim one or two letters to the right in this case...
+ * Note: with a single-char ellipsis, this should never happen! But better be safe here...
+ */
+ ui_text_clip_right_ex(
+ fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth, &final_lpart_len);
+ }
+ else {
+ memmove(str + l_end + sep_len, str + r_offset, r_len);
+ memcpy(str + l_end, sep, sep_len);
+ /* -1 to remove trailing '\0'! */
+ final_lpart_len = (size_t)(l_end + sep_len + r_len - 1);
+
+ while (BLF_width(fstyle->uifont_id, str, max_len) > okwidth) {
+ /* This will happen because a lot of string width processing is done in integer pixels,
+ * which can introduce a rather high error in the end (about 2 pixels or so).
+ * Only one char removal shall ever be needed in real-life situation... */
+ r_len--;
+ final_lpart_len--;
+ char *c = str + l_end + sep_len;
+ memmove(c, c + 1, r_len);
+ }
+ }
+ }
+
+ if (rpart) {
+ /* Add back preserved right part to our shorten str. */
+ memcpy(str + final_lpart_len, rpart, rpart_len + 1); /* +1 for trailing '\0'. */
+ okwidth += rpart_width;
+ }
+
+ strwidth = BLF_width(fstyle->uifont_id, str, max_len);
+ }
+
+ if (fstyle->kerning == 1) {
+ BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
+
+ BLI_assert(strwidth <= okwidth);
+
+ return strwidth;
}
/**
@@ -1636,30 +1740,37 @@ float UI_text_clip_middle_ex(
*/
static void ui_text_clip_middle(const uiFontStyle *fstyle, uiBut *but, const rcti *rect)
{
- /* No margin for labels! */
- const int border = ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_MENU, UI_BTYPE_POPOVER) ? 0 : (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
- const float okwidth = (float)max_ii(BLI_rcti_size_x(rect) - border, 0);
- const size_t max_len = sizeof(but->drawstr);
- const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f;
-
- but->ofs = 0;
- but->strwidth = UI_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, '\0');
+ /* No margin for labels! */
+ const int border = ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_MENU, UI_BTYPE_POPOVER) ?
+ 0 :
+ (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
+ const float okwidth = (float)max_ii(BLI_rcti_size_x(rect) - border, 0);
+ const size_t max_len = sizeof(but->drawstr);
+ const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f;
+
+ but->ofs = 0;
+ but->strwidth = UI_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, '\0');
}
/**
* Like ui_text_clip_middle(), but protect/preserve at all cost the right part of the string after sep.
* Useful for strings with shortcuts (like 'AVeryLongFooBarLabelForMenuEntry|Ctrl O' -> 'AVeryLong...MenuEntry|Ctrl O').
*/
-static void ui_text_clip_middle_protect_right(const uiFontStyle *fstyle, uiBut *but, const rcti *rect, const char rsep)
+static void ui_text_clip_middle_protect_right(const uiFontStyle *fstyle,
+ uiBut *but,
+ const rcti *rect,
+ const char rsep)
{
- /* No margin for labels! */
- const int border = ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_MENU, UI_BTYPE_POPOVER) ? 0 : (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
- const float okwidth = (float)max_ii(BLI_rcti_size_x(rect) - border, 0);
- const size_t max_len = sizeof(but->drawstr);
- const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f;
-
- but->ofs = 0;
- but->strwidth = UI_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, rsep);
+ /* No margin for labels! */
+ const int border = ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_MENU, UI_BTYPE_POPOVER) ?
+ 0 :
+ (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
+ const float okwidth = (float)max_ii(BLI_rcti_size_x(rect) - border, 0);
+ const size_t max_len = sizeof(but->drawstr);
+ const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f;
+
+ but->ofs = 0;
+ but->strwidth = UI_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, rsep);
}
/**
@@ -1667,67 +1778,67 @@ static void ui_text_clip_middle_protect_right(const uiFontStyle *fstyle, uiBut *
*/
static void ui_text_clip_cursor(const uiFontStyle *fstyle, uiBut *but, const rcti *rect)
{
- const int border = (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
- const int okwidth = max_ii(BLI_rcti_size_x(rect) - border, 0);
-
- BLI_assert(but->editstr && but->pos >= 0);
-
- /* need to set this first */
- UI_fontstyle_set(fstyle);
-
- if (fstyle->kerning == 1) {
- /* for BLF_width */
- BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- }
-
- /* define ofs dynamically */
- if (but->ofs > but->pos) {
- but->ofs = but->pos;
- }
-
- if (BLF_width(fstyle->uifont_id, but->editstr, INT_MAX) <= okwidth) {
- but->ofs = 0;
- }
-
- but->strwidth = BLF_width(fstyle->uifont_id, but->editstr + but->ofs, INT_MAX);
-
- if (but->strwidth > okwidth) {
- int len = strlen(but->editstr);
-
- while (but->strwidth > okwidth) {
- float width;
-
- /* string position of cursor */
- width = BLF_width(fstyle->uifont_id, but->editstr + but->ofs, (but->pos - but->ofs));
-
- /* if cursor is at 20 pixels of right side button we clip left */
- if (width > okwidth - 20) {
- ui_text_clip_give_next_off(but, but->editstr);
- }
- else {
- int bytes;
- /* shift string to the left */
- if (width < 20 && but->ofs > 0) {
- ui_text_clip_give_prev_off(but, but->editstr);
- }
- bytes = BLI_str_utf8_size(BLI_str_find_prev_char_utf8(but->editstr, but->editstr + len));
- if (bytes == -1) {
- bytes = 1;
- }
- len -= bytes;
- }
-
- but->strwidth = BLF_width(fstyle->uifont_id, but->editstr + but->ofs, len - but->ofs);
-
- if (but->strwidth < 10) {
- break;
- }
- }
- }
-
- if (fstyle->kerning == 1) {
- BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- }
+ const int border = (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
+ const int okwidth = max_ii(BLI_rcti_size_x(rect) - border, 0);
+
+ BLI_assert(but->editstr && but->pos >= 0);
+
+ /* need to set this first */
+ UI_fontstyle_set(fstyle);
+
+ if (fstyle->kerning == 1) {
+ /* for BLF_width */
+ BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
+
+ /* define ofs dynamically */
+ if (but->ofs > but->pos) {
+ but->ofs = but->pos;
+ }
+
+ if (BLF_width(fstyle->uifont_id, but->editstr, INT_MAX) <= okwidth) {
+ but->ofs = 0;
+ }
+
+ but->strwidth = BLF_width(fstyle->uifont_id, but->editstr + but->ofs, INT_MAX);
+
+ if (but->strwidth > okwidth) {
+ int len = strlen(but->editstr);
+
+ while (but->strwidth > okwidth) {
+ float width;
+
+ /* string position of cursor */
+ width = BLF_width(fstyle->uifont_id, but->editstr + but->ofs, (but->pos - but->ofs));
+
+ /* if cursor is at 20 pixels of right side button we clip left */
+ if (width > okwidth - 20) {
+ ui_text_clip_give_next_off(but, but->editstr);
+ }
+ else {
+ int bytes;
+ /* shift string to the left */
+ if (width < 20 && but->ofs > 0) {
+ ui_text_clip_give_prev_off(but, but->editstr);
+ }
+ bytes = BLI_str_utf8_size(BLI_str_find_prev_char_utf8(but->editstr, but->editstr + len));
+ if (bytes == -1) {
+ bytes = 1;
+ }
+ len -= bytes;
+ }
+
+ but->strwidth = BLF_width(fstyle->uifont_id, but->editstr + but->ofs, len - but->ofs);
+
+ if (but->strwidth < 10) {
+ break;
+ }
+ }
+ }
+
+ if (fstyle->kerning == 1) {
+ BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
}
/**
@@ -1737,1093 +1848,1123 @@ static void ui_text_clip_cursor(const uiFontStyle *fstyle, uiBut *but, const rct
*/
static void ui_text_clip_right_label(const uiFontStyle *fstyle, uiBut *but, const rcti *rect)
{
- const int border = UI_TEXT_CLIP_MARGIN + 1;
- const int okwidth = max_ii(BLI_rcti_size_x(rect) - border, 0);
- char *cpoin = NULL;
- int drawstr_len = strlen(but->drawstr);
- const char *cpend = but->drawstr + drawstr_len;
-
- /* need to set this first */
- UI_fontstyle_set(fstyle);
-
- if (fstyle->kerning == 1) {
- /* for BLF_width */
- BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- }
-
- but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr, sizeof(but->drawstr));
- but->ofs = 0;
-
-
- /* First shorten num-buttons eg,
- * Translucency: 0.000
- * becomes
- * Trans: 0.000
- */
-
- /* find the space after ':' separator */
- cpoin = strrchr(but->drawstr, ':');
-
- if (cpoin && (cpoin < cpend - 2)) {
- char *cp2 = cpoin;
-
- /* chop off the leading text, starting from the right */
- while (but->strwidth > okwidth && cp2 > but->drawstr) {
- const char *prev_utf8 = BLI_str_find_prev_char_utf8(but->drawstr, cp2);
- int bytes = cp2 - prev_utf8;
-
- /* shift the text after and including cp2 back by 1 char,
- * +1 to include null terminator */
- memmove(cp2 - bytes, cp2, drawstr_len + 1);
- cp2 -= bytes;
-
- drawstr_len -= bytes;
- // BLI_assert(strlen(but->drawstr) == drawstr_len);
-
- but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, sizeof(but->drawstr) - but->ofs);
- if (but->strwidth < 10) {
- break;
- }
- }
-
-
- /* after the leading text is gone, chop off the : and following space, with ofs */
- while ((but->strwidth > okwidth) && (but->ofs < 2)) {
- ui_text_clip_give_next_off(but, but->drawstr);
- but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, sizeof(but->drawstr) - but->ofs);
- if (but->strwidth < 10) {
- break;
- }
- }
- }
-
-
- /* Now just remove trailing chars */
- /* once the label's gone, chop off the least significant digits */
- if (but->strwidth > okwidth) {
- float strwidth;
- drawstr_len = BLF_width_to_strlen(
- fstyle->uifont_id, but->drawstr + but->ofs,
- drawstr_len - but->ofs, okwidth, &strwidth) + but->ofs;
- but->strwidth = strwidth;
- but->drawstr[drawstr_len] = 0;
- }
-
- if (fstyle->kerning == 1) {
- BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- }
+ const int border = UI_TEXT_CLIP_MARGIN + 1;
+ const int okwidth = max_ii(BLI_rcti_size_x(rect) - border, 0);
+ char *cpoin = NULL;
+ int drawstr_len = strlen(but->drawstr);
+ const char *cpend = but->drawstr + drawstr_len;
+
+ /* need to set this first */
+ UI_fontstyle_set(fstyle);
+
+ if (fstyle->kerning == 1) {
+ /* for BLF_width */
+ BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
+
+ but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr, sizeof(but->drawstr));
+ but->ofs = 0;
+
+ /* First shorten num-buttons eg,
+ * Translucency: 0.000
+ * becomes
+ * Trans: 0.000
+ */
+
+ /* find the space after ':' separator */
+ cpoin = strrchr(but->drawstr, ':');
+
+ if (cpoin && (cpoin < cpend - 2)) {
+ char *cp2 = cpoin;
+
+ /* chop off the leading text, starting from the right */
+ while (but->strwidth > okwidth && cp2 > but->drawstr) {
+ const char *prev_utf8 = BLI_str_find_prev_char_utf8(but->drawstr, cp2);
+ int bytes = cp2 - prev_utf8;
+
+ /* shift the text after and including cp2 back by 1 char,
+ * +1 to include null terminator */
+ memmove(cp2 - bytes, cp2, drawstr_len + 1);
+ cp2 -= bytes;
+
+ drawstr_len -= bytes;
+ // BLI_assert(strlen(but->drawstr) == drawstr_len);
+
+ but->strwidth = BLF_width(
+ fstyle->uifont_id, but->drawstr + but->ofs, sizeof(but->drawstr) - but->ofs);
+ if (but->strwidth < 10) {
+ break;
+ }
+ }
+
+ /* after the leading text is gone, chop off the : and following space, with ofs */
+ while ((but->strwidth > okwidth) && (but->ofs < 2)) {
+ ui_text_clip_give_next_off(but, but->drawstr);
+ but->strwidth = BLF_width(
+ fstyle->uifont_id, but->drawstr + but->ofs, sizeof(but->drawstr) - but->ofs);
+ if (but->strwidth < 10) {
+ break;
+ }
+ }
+ }
+
+ /* Now just remove trailing chars */
+ /* once the label's gone, chop off the least significant digits */
+ if (but->strwidth > okwidth) {
+ float strwidth;
+ drawstr_len = BLF_width_to_strlen(fstyle->uifont_id,
+ but->drawstr + but->ofs,
+ drawstr_len - but->ofs,
+ okwidth,
+ &strwidth) +
+ but->ofs;
+ but->strwidth = strwidth;
+ but->drawstr[drawstr_len] = 0;
+ }
+
+ if (fstyle->kerning == 1) {
+ BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
}
#ifdef WITH_INPUT_IME
-static void widget_draw_text_ime_underline(
- uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, const rcti *rect,
- const wmIMEData *ime_data, const char *drawstr)
+static void widget_draw_text_ime_underline(uiFontStyle *fstyle,
+ uiWidgetColors *wcol,
+ uiBut *but,
+ const rcti *rect,
+ const wmIMEData *ime_data,
+ const char *drawstr)
{
- int ofs_x, width;
- int rect_x = BLI_rcti_size_x(rect);
- int sel_start = ime_data->sel_start, sel_end = ime_data->sel_end;
- float fcol[4];
-
- if (drawstr[0] != 0) {
- if (but->pos >= but->ofs) {
- ofs_x = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->pos - but->ofs);
- }
- else {
- ofs_x = 0;
- }
-
- width = BLF_width(
- fstyle->uifont_id, drawstr + but->ofs,
- ime_data->composite_len + but->pos - but->ofs);
-
- rgba_uchar_to_float(fcol, wcol->text);
- UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 1, fcol);
-
- /* draw the thick line */
- if (sel_start != -1 && sel_end != -1) {
- sel_end -= sel_start;
- sel_start += but->pos;
-
- if (sel_start >= but->ofs) {
- ofs_x = BLF_width(fstyle->uifont_id, drawstr + but->ofs, sel_start - but->ofs);
- }
- else {
- ofs_x = 0;
- }
-
- width = BLF_width(
- fstyle->uifont_id, drawstr + but->ofs,
- sel_end + sel_start - but->ofs);
-
- UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 2, fcol);
- }
- }
+ int ofs_x, width;
+ int rect_x = BLI_rcti_size_x(rect);
+ int sel_start = ime_data->sel_start, sel_end = ime_data->sel_end;
+ float fcol[4];
+
+ if (drawstr[0] != 0) {
+ if (but->pos >= but->ofs) {
+ ofs_x = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->pos - but->ofs);
+ }
+ else {
+ ofs_x = 0;
+ }
+
+ width = BLF_width(
+ fstyle->uifont_id, drawstr + but->ofs, ime_data->composite_len + but->pos - but->ofs);
+
+ rgba_uchar_to_float(fcol, wcol->text);
+ UI_draw_text_underline(rect->xmin + ofs_x,
+ rect->ymin + 6 * U.pixelsize,
+ min_ii(width, rect_x - 2) - ofs_x,
+ 1,
+ fcol);
+
+ /* draw the thick line */
+ if (sel_start != -1 && sel_end != -1) {
+ sel_end -= sel_start;
+ sel_start += but->pos;
+
+ if (sel_start >= but->ofs) {
+ ofs_x = BLF_width(fstyle->uifont_id, drawstr + but->ofs, sel_start - but->ofs);
+ }
+ else {
+ ofs_x = 0;
+ }
+
+ width = BLF_width(fstyle->uifont_id, drawstr + but->ofs, sel_end + sel_start - but->ofs);
+
+ UI_draw_text_underline(rect->xmin + ofs_x,
+ rect->ymin + 6 * U.pixelsize,
+ min_ii(width, rect_x - 2) - ofs_x,
+ 2,
+ fcol);
+ }
+ }
}
-#endif /* WITH_INPUT_IME */
+#endif /* WITH_INPUT_IME */
-static void widget_draw_text(const uiFontStyle *fstyle, const uiWidgetColors *wcol, uiBut *but, rcti *rect)
+static void widget_draw_text(const uiFontStyle *fstyle,
+ const uiWidgetColors *wcol,
+ uiBut *but,
+ rcti *rect)
{
- int drawstr_left_len = UI_MAX_DRAW_STR;
- const char *drawstr = but->drawstr;
- const char *drawstr_right = NULL;
- bool use_right_only = false;
+ int drawstr_left_len = UI_MAX_DRAW_STR;
+ const char *drawstr = but->drawstr;
+ const char *drawstr_right = NULL;
+ bool use_right_only = false;
#ifdef WITH_INPUT_IME
- const wmIMEData *ime_data;
+ const wmIMEData *ime_data;
#endif
- UI_fontstyle_set(fstyle);
-
- eFontStyle_Align align;
- if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT)) {
- align = UI_STYLE_TEXT_LEFT;
- }
- else if (but->drawflag & UI_BUT_TEXT_RIGHT) {
- align = UI_STYLE_TEXT_RIGHT;
- }
- else {
- align = UI_STYLE_TEXT_CENTER;
- }
-
- if (fstyle->kerning == 1) {
- /* for BLF_width */
- BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- }
-
- /* Special case: when we're entering text for multiple buttons,
- * don't draw the text for any of the multi-editing buttons */
- if (UNLIKELY(but->flag & UI_BUT_DRAG_MULTI)) {
- uiBut *but_edit = ui_but_drag_multi_edit_get(but);
- if (but_edit) {
- drawstr = but_edit->editstr;
- align = UI_STYLE_TEXT_LEFT;
- }
- }
- else {
- if (but->editstr) {
- /* max length isn't used in this case,
- * we rely on string being NULL terminated. */
- drawstr_left_len = INT_MAX;
+ UI_fontstyle_set(fstyle);
+
+ eFontStyle_Align align;
+ if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT)) {
+ align = UI_STYLE_TEXT_LEFT;
+ }
+ else if (but->drawflag & UI_BUT_TEXT_RIGHT) {
+ align = UI_STYLE_TEXT_RIGHT;
+ }
+ else {
+ align = UI_STYLE_TEXT_CENTER;
+ }
+
+ if (fstyle->kerning == 1) {
+ /* for BLF_width */
+ BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
+
+ /* Special case: when we're entering text for multiple buttons,
+ * don't draw the text for any of the multi-editing buttons */
+ if (UNLIKELY(but->flag & UI_BUT_DRAG_MULTI)) {
+ uiBut *but_edit = ui_but_drag_multi_edit_get(but);
+ if (but_edit) {
+ drawstr = but_edit->editstr;
+ align = UI_STYLE_TEXT_LEFT;
+ }
+ }
+ else {
+ if (but->editstr) {
+ /* max length isn't used in this case,
+ * we rely on string being NULL terminated. */
+ drawstr_left_len = INT_MAX;
#ifdef WITH_INPUT_IME
- /* FIXME, IME is modifying 'const char *drawstr! */
- ime_data = ui_but_ime_data_get(but);
-
- if (ime_data && ime_data->composite_len) {
- /* insert composite string into cursor pos */
- BLI_snprintf(
- (char *)drawstr, UI_MAX_DRAW_STR, "%s%s%s",
- but->editstr, ime_data->str_composite,
- but->editstr + but->pos);
- }
- else
+ /* FIXME, IME is modifying 'const char *drawstr! */
+ ime_data = ui_but_ime_data_get(but);
+
+ if (ime_data && ime_data->composite_len) {
+ /* insert composite string into cursor pos */
+ BLI_snprintf((char *)drawstr,
+ UI_MAX_DRAW_STR,
+ "%s%s%s",
+ but->editstr,
+ ime_data->str_composite,
+ but->editstr + but->pos);
+ }
+ else
#endif
- {
- drawstr = but->editstr;
- }
- }
- }
-
-
- /* text button selection, cursor, composite underline */
- if (but->editstr && but->pos != -1) {
- int but_pos_ofs;
- int tx, ty;
-
- /* text button selection */
- if ((but->selend - but->selsta) > 0) {
- int selsta_draw, selwidth_draw;
-
- if (drawstr[0] != 0) {
- /* We are drawing on top of widget bases. Flush cache. */
- GPU_blend(true);
- UI_widgetbase_draw_cache_flush();
- GPU_blend(false);
-
- if (but->selsta >= but->ofs) {
- selsta_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->selsta - but->ofs);
- }
- else {
- selsta_draw = 0;
- }
-
- selwidth_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->selend - but->ofs);
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- immUniformColor4ubv((uchar *)wcol->item);
- immRecti(pos, rect->xmin + selsta_draw,
- rect->ymin + 2,
- min_ii(rect->xmin + selwidth_draw, rect->xmax - 2),
- rect->ymax - 2);
-
- immUnbindProgram();
- }
- }
-
- /* text cursor */
- but_pos_ofs = but->pos;
+ {
+ drawstr = but->editstr;
+ }
+ }
+ }
+
+ /* text button selection, cursor, composite underline */
+ if (but->editstr && but->pos != -1) {
+ int but_pos_ofs;
+ int tx, ty;
+
+ /* text button selection */
+ if ((but->selend - but->selsta) > 0) {
+ int selsta_draw, selwidth_draw;
+
+ if (drawstr[0] != 0) {
+ /* We are drawing on top of widget bases. Flush cache. */
+ GPU_blend(true);
+ UI_widgetbase_draw_cache_flush();
+ GPU_blend(false);
+
+ if (but->selsta >= but->ofs) {
+ selsta_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->selsta - but->ofs);
+ }
+ else {
+ selsta_draw = 0;
+ }
+
+ selwidth_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->selend - but->ofs);
+
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4ubv((uchar *)wcol->item);
+ immRecti(pos,
+ rect->xmin + selsta_draw,
+ rect->ymin + 2,
+ min_ii(rect->xmin + selwidth_draw, rect->xmax - 2),
+ rect->ymax - 2);
+
+ immUnbindProgram();
+ }
+ }
+
+ /* text cursor */
+ but_pos_ofs = but->pos;
#ifdef WITH_INPUT_IME
- /* if is ime compositing, move the cursor */
- if (ime_data && ime_data->composite_len && ime_data->cursor_pos != -1) {
- but_pos_ofs += ime_data->cursor_pos;
- }
+ /* if is ime compositing, move the cursor */
+ if (ime_data && ime_data->composite_len && ime_data->cursor_pos != -1) {
+ but_pos_ofs += ime_data->cursor_pos;
+ }
#endif
- if (but->pos >= but->ofs) {
- int t;
- if (drawstr[0] != 0) {
- t = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but_pos_ofs - but->ofs);
- }
- else {
- t = 0;
- }
- /* We are drawing on top of widget bases. Flush cache. */
- GPU_blend(true);
- UI_widgetbase_draw_cache_flush();
- GPU_blend(false);
+ if (but->pos >= but->ofs) {
+ int t;
+ if (drawstr[0] != 0) {
+ t = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but_pos_ofs - but->ofs);
+ }
+ else {
+ t = 0;
+ }
+ /* We are drawing on top of widget bases. Flush cache. */
+ GPU_blend(true);
+ UI_widgetbase_draw_cache_flush();
+ GPU_blend(false);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3f(0.2f, 0.6f, 0.9f);
+ immUniformColor3f(0.2f, 0.6f, 0.9f);
- tx = rect->xmin + t + 2;
- ty = rect->ymin + 2;
+ tx = rect->xmin + t + 2;
+ ty = rect->ymin + 2;
- /* draw cursor */
- immRecti(pos, rect->xmin + t, ty, tx, rect->ymax - 2);
+ /* draw cursor */
+ immRecti(pos, rect->xmin + t, ty, tx, rect->ymax - 2);
- immUnbindProgram();
- }
+ immUnbindProgram();
+ }
#ifdef WITH_INPUT_IME
- if (ime_data && ime_data->composite_len) {
- /* ime cursor following */
- if (but->pos >= but->ofs) {
- ui_but_ime_reposition(but, tx + 5, ty + 3, false);
- }
-
- /* composite underline */
- widget_draw_text_ime_underline(fstyle, wcol, but, rect, ime_data, drawstr);
- }
+ if (ime_data && ime_data->composite_len) {
+ /* ime cursor following */
+ if (but->pos >= but->ofs) {
+ ui_but_ime_reposition(but, tx + 5, ty + 3, false);
+ }
+
+ /* composite underline */
+ widget_draw_text_ime_underline(fstyle, wcol, but, rect, ime_data, drawstr);
+ }
#endif
- }
+ }
- if (fstyle->kerning == 1) {
- BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- }
+ if (fstyle->kerning == 1) {
+ BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
#if 0
- ui_rasterpos_safe(x, y, but->aspect);
- transopts = ui_translate_buttons();
+ ui_rasterpos_safe(x, y, but->aspect);
+ transopts = ui_translate_buttons();
#endif
- /* cut string in 2 parts - only for menu entries */
- if ((but->drawflag & UI_BUT_HAS_SHORTCUT) &&
- (but->editstr == NULL))
- {
- if (but->flag & UI_BUT_HAS_SEP_CHAR) {
- drawstr_right = strrchr(drawstr, UI_SEP_CHAR);
- if (drawstr_right) {
- drawstr_left_len = (drawstr_right - drawstr);
- drawstr_right++;
- }
- }
- }
+ /* cut string in 2 parts - only for menu entries */
+ if ((but->drawflag & UI_BUT_HAS_SHORTCUT) && (but->editstr == NULL)) {
+ if (but->flag & UI_BUT_HAS_SEP_CHAR) {
+ drawstr_right = strrchr(drawstr, UI_SEP_CHAR);
+ if (drawstr_right) {
+ drawstr_left_len = (drawstr_right - drawstr);
+ drawstr_right++;
+ }
+ }
+ }
#ifdef USE_NUMBUTS_LR_ALIGN
- if (!drawstr_right &&
- (but->drawflag & UI_BUT_TEXT_LEFT) &&
- ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) &&
- /* if we're editing or multi-drag (fake editing), then use left alignment */
- (but->editstr == NULL) && (drawstr == but->drawstr))
- {
- drawstr_right = strchr(drawstr + but->ofs, ':');
- if (drawstr_right) {
- drawstr_right++;
- drawstr_left_len = (drawstr_right - drawstr);
-
- while (*drawstr_right == ' ') {
- drawstr_right++;
- }
- }
- else {
- /* no prefix, even so use only cpoin */
- drawstr_right = drawstr + but->ofs;
- use_right_only = true;
- }
- }
+ if (!drawstr_right && (but->drawflag & UI_BUT_TEXT_LEFT) &&
+ ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) &&
+ /* if we're editing or multi-drag (fake editing), then use left alignment */
+ (but->editstr == NULL) && (drawstr == but->drawstr)) {
+ drawstr_right = strchr(drawstr + but->ofs, ':');
+ if (drawstr_right) {
+ drawstr_right++;
+ drawstr_left_len = (drawstr_right - drawstr);
+
+ while (*drawstr_right == ' ') {
+ drawstr_right++;
+ }
+ }
+ else {
+ /* no prefix, even so use only cpoin */
+ drawstr_right = drawstr + but->ofs;
+ use_right_only = true;
+ }
+ }
#endif
- if (!use_right_only) {
- /* for underline drawing */
- float font_xofs, font_yofs;
-
- int drawlen = (drawstr_left_len == INT_MAX) ? strlen(drawstr + but->ofs) : (drawstr_left_len - but->ofs);
-
- if (drawlen > 0) {
- UI_fontstyle_draw_ex(
- fstyle, rect, drawstr + but->ofs, (uchar *)wcol->text,
- &(struct uiFontStyleDraw_Params) { .align = align, },
- drawlen, &font_xofs, &font_yofs);
-
- 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);
- }
-
- if (str) {
- int ul_index = -1;
- float ul_advance;
-
- ul_index = (int)(str - fixedbuf);
-
- 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);
-
- BLF_position(fstyle->uifont_id, rect->xmin + font_xofs + ul_advance, rect->ymin + font_yofs, 0.0f);
- BLF_color4ubv(fstyle->uifont_id, (uchar *)wcol->text);
- BLF_draw(fstyle->uifont_id, "_", 2);
-
- if (fstyle->kerning == 1) {
- BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- }
- }
- }
- }
- }
-
- /* part text right aligned */
- if (drawstr_right) {
- char col[4];
- copy_v4_v4_char(col, wcol->text);
- if (but->drawflag & UI_BUT_HAS_SHORTCUT) {
- col[3] *= 0.5f;
- }
-
- rect->xmax -= UI_TEXT_CLIP_MARGIN;
- UI_fontstyle_draw(
- fstyle, rect, drawstr_right, (const uchar *)col,
- &(struct uiFontStyleDraw_Params) { .align = UI_STYLE_TEXT_RIGHT, });
- }
+ if (!use_right_only) {
+ /* for underline drawing */
+ float font_xofs, font_yofs;
+
+ int drawlen = (drawstr_left_len == INT_MAX) ? strlen(drawstr + but->ofs) :
+ (drawstr_left_len - but->ofs);
+
+ if (drawlen > 0) {
+ UI_fontstyle_draw_ex(fstyle,
+ rect,
+ drawstr + but->ofs,
+ (uchar *)wcol->text,
+ &(struct uiFontStyleDraw_Params){
+ .align = align,
+ },
+ drawlen,
+ &font_xofs,
+ &font_yofs);
+
+ 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);
+ }
+
+ if (str) {
+ int ul_index = -1;
+ float ul_advance;
+
+ ul_index = (int)(str - fixedbuf);
+
+ 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);
+
+ BLF_position(fstyle->uifont_id,
+ rect->xmin + font_xofs + ul_advance,
+ rect->ymin + font_yofs,
+ 0.0f);
+ BLF_color4ubv(fstyle->uifont_id, (uchar *)wcol->text);
+ BLF_draw(fstyle->uifont_id, "_", 2);
+
+ if (fstyle->kerning == 1) {
+ BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
+ }
+ }
+ }
+ }
+
+ /* part text right aligned */
+ if (drawstr_right) {
+ char col[4];
+ copy_v4_v4_char(col, wcol->text);
+ if (but->drawflag & UI_BUT_HAS_SHORTCUT) {
+ col[3] *= 0.5f;
+ }
+
+ rect->xmax -= UI_TEXT_CLIP_MARGIN;
+ UI_fontstyle_draw(fstyle,
+ rect,
+ drawstr_right,
+ (const uchar *)col,
+ &(struct uiFontStyleDraw_Params){
+ .align = UI_STYLE_TEXT_RIGHT,
+ });
+ }
}
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;
- }
+ 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;
+ }
}
/* draws text and icons for buttons */
-static void widget_draw_text_icon(const uiFontStyle *fstyle, const uiWidgetColors *wcol, uiBut *but, rcti *rect)
+static void widget_draw_text_icon(const uiFontStyle *fstyle,
+ const uiWidgetColors *wcol,
+ uiBut *but,
+ rcti *rect)
{
- const uiButExtraIconType extra_icon_type = ui_but_icon_extra_get(but);
- 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];
-
- 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;
- }
-
- /* If there's an icon too (made with uiDefIconTextBut) then draw the icon
- * and offset the text label to accommodate it */
-
- /* 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);
- int icon_size = BLI_rcti_size_y(rect);
- int text_size = 0;
-
- /* This is a bit britle, but avoids adding an 'UI_BUT_HAS_LABEL' flag to but... */
- if (icon_size > BLI_rcti_size_x(rect)) {
- /* button is not square, it has extra height for label */
- text_size = UI_UNIT_Y;
- icon_size -= text_size;
- }
-
- /* draw icon in rect above the space reserved for the label */
- rect->ymin += text_size;
- GPU_blend(true);
- widget_draw_preview(icon, alpha, rect);
- GPU_blend(false);
-
- /* offset rect to draw label in */
- rect->ymin -= text_size;
- rect->ymax -= icon_size;
-
- /* vertically centering text */
- rect->ymin += UI_UNIT_Y / 2;
- }
- /* Icons on the left with optional text label on the right */
- else if (but->flag & UI_HAS_ICON || show_menu_icon) {
- const bool is_tool = UI_but_is_tool(but);
-
- /* XXX add way to draw icons at a different size!
- * Use small icons for popup. */
+ const uiButExtraIconType extra_icon_type = ui_but_icon_extra_get(but);
+ 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];
+
+ 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;
+ }
+
+ /* If there's an icon too (made with uiDefIconTextBut) then draw the icon
+ * and offset the text label to accommodate it */
+
+ /* 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);
+ int icon_size = BLI_rcti_size_y(rect);
+ int text_size = 0;
+
+ /* This is a bit britle, but avoids adding an 'UI_BUT_HAS_LABEL' flag to but... */
+ if (icon_size > BLI_rcti_size_x(rect)) {
+ /* button is not square, it has extra height for label */
+ text_size = UI_UNIT_Y;
+ icon_size -= text_size;
+ }
+
+ /* draw icon in rect above the space reserved for the label */
+ rect->ymin += text_size;
+ GPU_blend(true);
+ widget_draw_preview(icon, alpha, rect);
+ GPU_blend(false);
+
+ /* offset rect to draw label in */
+ rect->ymin -= text_size;
+ rect->ymax -= icon_size;
+
+ /* vertically centering text */
+ rect->ymin += UI_UNIT_Y / 2;
+ }
+ /* Icons on the left with optional text label on the right */
+ else if (but->flag & UI_HAS_ICON || show_menu_icon) {
+ const bool is_tool = UI_but_is_tool(but);
+
+ /* XXX add way to draw icons at a different size!
+ * Use small icons for popup. */
#ifdef USE_UI_TOOLBAR_HACK
- const float aspect_orig = but->block->aspect;
- if (is_tool && (but->block->flag & UI_BLOCK_POPOVER)) {
- but->block->aspect *= 2.0f;
- }
+ const float aspect_orig = but->block->aspect;
+ if (is_tool && (but->block->flag & UI_BLOCK_POPOVER)) {
+ but->block->aspect *= 2.0f;
+ }
#endif
- const BIFIconID icon = widget_icon_id(but);
- int icon_size_init = is_tool ? ICON_DEFAULT_HEIGHT_TOOLBAR : ICON_DEFAULT_HEIGHT;
- const float icon_size = icon_size_init / (but->block->aspect / UI_DPI_FAC);
- const float icon_padding = 2 * UI_DPI_FAC;
+ const BIFIconID icon = widget_icon_id(but);
+ int icon_size_init = is_tool ? ICON_DEFAULT_HEIGHT_TOOLBAR : ICON_DEFAULT_HEIGHT;
+ const float icon_size = icon_size_init / (but->block->aspect / UI_DPI_FAC);
+ const float icon_padding = 2 * UI_DPI_FAC;
#ifdef USE_UI_TOOLBAR_HACK
- if (is_tool) {
- /* pass (even if its a menu toolbar) */
- but->drawflag |= UI_BUT_TEXT_LEFT;
- but->drawflag |= UI_BUT_ICON_LEFT;
- }
+ if (is_tool) {
+ /* pass (even if its a menu toolbar) */
+ but->drawflag |= UI_BUT_TEXT_LEFT;
+ but->drawflag |= UI_BUT_ICON_LEFT;
+ }
#endif
- /* menu item - add some more padding so menus don't feel cramped. it must
- * be part of the button so that this area is still clickable */
- if (is_tool) {
- /* pass (even if its a menu toolbar) */
- }
- else if (ui_block_is_pie_menu(but->block)) {
- if (but->dt == UI_EMBOSS_RADIAL) {
- rect->xmin += 0.3f * U.widget_unit;
- }
- }
- else if (ui_block_is_menu(but->block)) {
- rect->xmin += 0.2f * U.widget_unit;
- }
-
- widget_draw_icon(but, icon, alpha, rect, wcol->text);
- if (show_menu_icon) {
- BLI_assert(but->block->content_hints & UI_BLOCK_CONTAINS_SUBMENU_BUT);
- widget_draw_submenu_tria(but, rect, wcol);
- }
+ /* menu item - add some more padding so menus don't feel cramped. it must
+ * be part of the button so that this area is still clickable */
+ if (is_tool) {
+ /* pass (even if its a menu toolbar) */
+ }
+ else if (ui_block_is_pie_menu(but->block)) {
+ if (but->dt == UI_EMBOSS_RADIAL) {
+ rect->xmin += 0.3f * U.widget_unit;
+ }
+ }
+ else if (ui_block_is_menu(but->block)) {
+ rect->xmin += 0.2f * U.widget_unit;
+ }
+
+ widget_draw_icon(but, icon, alpha, rect, wcol->text);
+ if (show_menu_icon) {
+ BLI_assert(but->block->content_hints & UI_BLOCK_CONTAINS_SUBMENU_BUT);
+ widget_draw_submenu_tria(but, rect, wcol);
+ }
#ifdef USE_UI_TOOLBAR_HACK
- but->block->aspect = aspect_orig;
+ but->block->aspect = aspect_orig;
#endif
- 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) {
- 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;
- }
-
- /* Menu contains sub-menu items with triangle icon on their right. Shortcut
- * strings should be drawn with some padding to the right then. */
- if (ui_block_is_menu(but->block) && (but->block->content_hints & UI_BLOCK_CONTAINS_SUBMENU_BUT)) {
- rect->xmax -= UI_MENU_SUBMENU_PADDING;
- }
-
- /* extra icons, e.g. 'x' icon to clear text or icon for eyedropper */
- if (extra_icon_type != UI_BUT_ICONEXTRA_NONE) {
- rcti temp = *rect;
-
- temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f);
-
- if (extra_icon_type == UI_BUT_ICONEXTRA_CLEAR) {
- widget_draw_icon(but, ICON_PANEL_CLOSE, alpha, &temp, wcol->text);
- }
- else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
- widget_draw_icon(but, ICON_EYEDROPPER, alpha, &temp, wcol->text);
- }
- else {
- BLI_assert(0);
- }
-
- rect->xmax -= ICON_SIZE_FROM_BUTRECT(rect);
- }
-
- /* clip but->drawstr to fit in available space */
- if (but->editstr && but->pos >= 0) {
- ui_text_clip_cursor(fstyle, but, rect);
- }
- else if (but->drawstr[0] == '\0') {
- /* bypass text clipping on icon buttons */
- but->ofs = 0;
- but->strwidth = 0;
- }
- else if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) {
- ui_text_clip_right_label(fstyle, but, rect);
- }
- else if (but->flag & UI_BUT_HAS_SEP_CHAR) {
- /* Clip middle, but protect in all case right part containing the shortcut, if any. */
- ui_text_clip_middle_protect_right(fstyle, but, rect, UI_SEP_CHAR);
- }
- else {
- ui_text_clip_middle(fstyle, but, rect);
- }
-
- /* always draw text for textbutton cursor */
- widget_draw_text(fstyle, wcol, but, rect);
-
- ui_but_text_password_hide(password_str, but, true);
-
- /* if a widget uses font shadow it has to be deactivated now */
- BLF_disable(fstyle->uifont_id, BLF_SHADOW);
+ 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) {
+ 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;
+ }
+
+ /* Menu contains sub-menu items with triangle icon on their right. Shortcut
+ * strings should be drawn with some padding to the right then. */
+ if (ui_block_is_menu(but->block) &&
+ (but->block->content_hints & UI_BLOCK_CONTAINS_SUBMENU_BUT)) {
+ rect->xmax -= UI_MENU_SUBMENU_PADDING;
+ }
+
+ /* extra icons, e.g. 'x' icon to clear text or icon for eyedropper */
+ if (extra_icon_type != UI_BUT_ICONEXTRA_NONE) {
+ rcti temp = *rect;
+
+ temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f);
+
+ if (extra_icon_type == UI_BUT_ICONEXTRA_CLEAR) {
+ widget_draw_icon(but, ICON_PANEL_CLOSE, alpha, &temp, wcol->text);
+ }
+ else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
+ widget_draw_icon(but, ICON_EYEDROPPER, alpha, &temp, wcol->text);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ rect->xmax -= ICON_SIZE_FROM_BUTRECT(rect);
+ }
+
+ /* clip but->drawstr to fit in available space */
+ if (but->editstr && but->pos >= 0) {
+ ui_text_clip_cursor(fstyle, but, rect);
+ }
+ else if (but->drawstr[0] == '\0') {
+ /* bypass text clipping on icon buttons */
+ but->ofs = 0;
+ but->strwidth = 0;
+ }
+ else if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) {
+ ui_text_clip_right_label(fstyle, but, rect);
+ }
+ else if (but->flag & UI_BUT_HAS_SEP_CHAR) {
+ /* Clip middle, but protect in all case right part containing the shortcut, if any. */
+ ui_text_clip_middle_protect_right(fstyle, but, rect, UI_SEP_CHAR);
+ }
+ else {
+ ui_text_clip_middle(fstyle, but, rect);
+ }
+
+ /* always draw text for textbutton cursor */
+ widget_draw_text(fstyle, wcol, but, rect);
+
+ ui_but_text_password_hide(password_str, but, true);
+
+ /* if a widget uses font shadow it has to be deactivated now */
+ BLF_disable(fstyle->uifont_id, BLF_SHADOW);
}
#undef UI_TEXT_CLIP_MARGIN
-
/* *********************** widget types ************************************* */
/* ************ button callbacks, state ***************** */
static void widget_state_blend(char cp[3], const char cpstate[3], const float fac)
{
- if (fac != 0.0f) {
- cp[0] = (int)((1.0f - fac) * cp[0] + fac * cpstate[0]);
- cp[1] = (int)((1.0f - fac) * cp[1] + fac * cpstate[1]);
- cp[2] = (int)((1.0f - fac) * cp[2] + fac * cpstate[2]);
- }
+ if (fac != 0.0f) {
+ cp[0] = (int)((1.0f - fac) * cp[0] + fac * cpstate[0]);
+ cp[1] = (int)((1.0f - fac) * cp[1] + fac * cpstate[1]);
+ cp[2] = (int)((1.0f - fac) * cp[2] + fac * cpstate[2]);
+ }
}
/* put all widget colors on half alpha, use local storage */
static void ui_widget_color_disabled(uiWidgetType *wt)
{
- static uiWidgetColors wcol_theme_s;
+ static uiWidgetColors wcol_theme_s;
- wcol_theme_s = *wt->wcol_theme;
+ wcol_theme_s = *wt->wcol_theme;
- wcol_theme_s.outline[3] *= 0.5;
- wcol_theme_s.inner[3] *= 0.5;
- wcol_theme_s.inner_sel[3] *= 0.5;
- wcol_theme_s.item[3] *= 0.5;
- wcol_theme_s.text[3] *= 0.5;
- wcol_theme_s.text_sel[3] *= 0.5;
+ wcol_theme_s.outline[3] *= 0.5;
+ wcol_theme_s.inner[3] *= 0.5;
+ wcol_theme_s.inner_sel[3] *= 0.5;
+ wcol_theme_s.item[3] *= 0.5;
+ wcol_theme_s.text[3] *= 0.5;
+ wcol_theme_s.text_sel[3] *= 0.5;
- wt->wcol_theme = &wcol_theme_s;
+ wt->wcol_theme = &wcol_theme_s;
}
static void widget_active_color(char cp[3])
{
- cp[0] = cp[0] >= 240 ? 255 : cp[0] + 15;
- cp[1] = cp[1] >= 240 ? 255 : cp[1] + 15;
- cp[2] = cp[2] >= 240 ? 255 : cp[2] + 15;
+ cp[0] = cp[0] >= 240 ? 255 : cp[0] + 15;
+ cp[1] = cp[1] >= 240 ? 255 : cp[1] + 15;
+ cp[2] = cp[2] >= 240 ? 255 : cp[2] + 15;
}
/* copy colors from theme, and set changes in it based on state */
static void widget_state(uiWidgetType *wt, int state, int drawflag)
{
- uiWidgetStateColors *wcol_state = wt->wcol_state;
-
- if ((state & UI_BUT_LIST_ITEM) && !(state & UI_STATE_TEXT_INPUT)) {
- /* Override default widget's colors. */
- bTheme *btheme = UI_GetTheme();
- wt->wcol_theme = &btheme->tui.wcol_list_item;
-
- if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
- ui_widget_color_disabled(wt);
- }
- }
-
- wt->wcol = *(wt->wcol_theme);
-
- if (state & UI_SELECT) {
- copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
- if (drawflag & UI_BUT_ANIMATED_CHANGED) {
- widget_state_blend(wt->wcol.inner, wcol_state->inner_changed_sel, wcol_state->blend);
- }
- else if (state & UI_BUT_ANIMATED_KEY) {
- widget_state_blend(wt->wcol.inner, wcol_state->inner_key_sel, wcol_state->blend);
- }
- else if (state & UI_BUT_ANIMATED) {
- widget_state_blend(wt->wcol.inner, wcol_state->inner_anim_sel, wcol_state->blend);
- }
- else if (state & UI_BUT_DRIVEN) {
- widget_state_blend(wt->wcol.inner, wcol_state->inner_driven_sel, wcol_state->blend);
- }
- else if (state & UI_BUT_OVERRIDEN) {
- widget_state_blend(wt->wcol.inner, wcol_state->inner_overridden_sel, wcol_state->blend);
- }
-
- copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
-
- if (state & UI_SELECT) {
- SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
- }
- }
- else {
- if (drawflag & UI_BUT_ANIMATED_CHANGED) {
- widget_state_blend(wt->wcol.inner, wcol_state->inner_changed, wcol_state->blend);
- }
- else if (state & UI_BUT_ANIMATED_KEY) {
- widget_state_blend(wt->wcol.inner, wcol_state->inner_key, wcol_state->blend);
- }
- else if (state & UI_BUT_ANIMATED) {
- widget_state_blend(wt->wcol.inner, wcol_state->inner_anim, wcol_state->blend);
- }
- else if (state & UI_BUT_DRIVEN) {
- widget_state_blend(wt->wcol.inner, wcol_state->inner_driven, wcol_state->blend);
- }
- else if (state & UI_BUT_OVERRIDEN) {
- widget_state_blend(wt->wcol.inner, wcol_state->inner_overridden, wcol_state->blend);
- }
-
- if (state & UI_ACTIVE) { /* mouse over? */
- widget_active_color(wt->wcol.inner);
- }
- }
-
- if (state & UI_BUT_REDALERT) {
- char red[4] = {255, 0, 0};
- if (wt->draw) {
- widget_state_blend(wt->wcol.inner, red, 0.4f);
- }
- else {
- widget_state_blend(wt->wcol.text, red, 0.4f);
- }
- }
-
- if (state & UI_BUT_DRAG_MULTI) {
- /* the button isn't SELECT but we're editing this so draw with sel color */
- copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
- SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
- widget_state_blend(wt->wcol.text, wt->wcol.text_sel, 0.85f);
- }
-
- if (state & UI_BUT_NODE_ACTIVE) {
- char blue[4] = {86, 128, 194};
- widget_state_blend(wt->wcol.inner, blue, 0.3f);
- }
+ uiWidgetStateColors *wcol_state = wt->wcol_state;
+
+ if ((state & UI_BUT_LIST_ITEM) && !(state & UI_STATE_TEXT_INPUT)) {
+ /* Override default widget's colors. */
+ bTheme *btheme = UI_GetTheme();
+ wt->wcol_theme = &btheme->tui.wcol_list_item;
+
+ if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
+ ui_widget_color_disabled(wt);
+ }
+ }
+
+ wt->wcol = *(wt->wcol_theme);
+
+ if (state & UI_SELECT) {
+ copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
+ if (drawflag & UI_BUT_ANIMATED_CHANGED) {
+ widget_state_blend(wt->wcol.inner, wcol_state->inner_changed_sel, wcol_state->blend);
+ }
+ else if (state & UI_BUT_ANIMATED_KEY) {
+ widget_state_blend(wt->wcol.inner, wcol_state->inner_key_sel, wcol_state->blend);
+ }
+ else if (state & UI_BUT_ANIMATED) {
+ widget_state_blend(wt->wcol.inner, wcol_state->inner_anim_sel, wcol_state->blend);
+ }
+ else if (state & UI_BUT_DRIVEN) {
+ widget_state_blend(wt->wcol.inner, wcol_state->inner_driven_sel, wcol_state->blend);
+ }
+ else if (state & UI_BUT_OVERRIDEN) {
+ widget_state_blend(wt->wcol.inner, wcol_state->inner_overridden_sel, wcol_state->blend);
+ }
+
+ copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
+
+ if (state & UI_SELECT) {
+ SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
+ }
+ }
+ else {
+ if (drawflag & UI_BUT_ANIMATED_CHANGED) {
+ widget_state_blend(wt->wcol.inner, wcol_state->inner_changed, wcol_state->blend);
+ }
+ else if (state & UI_BUT_ANIMATED_KEY) {
+ widget_state_blend(wt->wcol.inner, wcol_state->inner_key, wcol_state->blend);
+ }
+ else if (state & UI_BUT_ANIMATED) {
+ widget_state_blend(wt->wcol.inner, wcol_state->inner_anim, wcol_state->blend);
+ }
+ else if (state & UI_BUT_DRIVEN) {
+ widget_state_blend(wt->wcol.inner, wcol_state->inner_driven, wcol_state->blend);
+ }
+ else if (state & UI_BUT_OVERRIDEN) {
+ widget_state_blend(wt->wcol.inner, wcol_state->inner_overridden, wcol_state->blend);
+ }
+
+ if (state & UI_ACTIVE) { /* mouse over? */
+ widget_active_color(wt->wcol.inner);
+ }
+ }
+
+ if (state & UI_BUT_REDALERT) {
+ char red[4] = {255, 0, 0};
+ if (wt->draw) {
+ widget_state_blend(wt->wcol.inner, red, 0.4f);
+ }
+ else {
+ widget_state_blend(wt->wcol.text, red, 0.4f);
+ }
+ }
+
+ if (state & UI_BUT_DRAG_MULTI) {
+ /* the button isn't SELECT but we're editing this so draw with sel color */
+ copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
+ SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
+ widget_state_blend(wt->wcol.text, wt->wcol.text_sel, 0.85f);
+ }
+
+ if (state & UI_BUT_NODE_ACTIVE) {
+ char blue[4] = {86, 128, 194};
+ widget_state_blend(wt->wcol.inner, blue, 0.3f);
+ }
}
/* sliders use special hack which sets 'item' as inner when drawing filling */
static void widget_state_numslider(uiWidgetType *wt, int state, int drawflag)
{
- uiWidgetStateColors *wcol_state = wt->wcol_state;
- /* XXX special tweak to make sure that bar will still be visible */
- float blend = wcol_state->blend - 0.2f;
-
- /* call this for option button */
- widget_state(wt, state, drawflag);
-
- /* now, set the inner-part so that it reflects state settings too */
- /* TODO: maybe we should have separate settings for the blending colors used for this case? */
- if (state & UI_SELECT) {
-
- if (drawflag & UI_BUT_ANIMATED_CHANGED) {
- widget_state_blend(wt->wcol.item, wcol_state->inner_changed_sel, blend);
- }
- else if (state & UI_BUT_ANIMATED_KEY) {
- widget_state_blend(wt->wcol.item, wcol_state->inner_key_sel, blend);
- }
- else if (state & UI_BUT_ANIMATED) {
- widget_state_blend(wt->wcol.item, wcol_state->inner_anim_sel, blend);
- }
- else if (state & UI_BUT_DRIVEN) {
- widget_state_blend(wt->wcol.item, wcol_state->inner_driven_sel, blend);
- }
- else if (state & UI_BUT_OVERRIDEN) {
- widget_state_blend(wt->wcol.item, wcol_state->inner_overridden_sel, blend);
- }
-
- if (state & UI_SELECT) {
- SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
- }
- }
- else {
- if (drawflag & UI_BUT_ANIMATED_CHANGED) {
- widget_state_blend(wt->wcol.item, wcol_state->inner_changed, blend);
- }
- else if (state & UI_BUT_ANIMATED_KEY) {
- widget_state_blend(wt->wcol.item, wcol_state->inner_key, blend);
- }
- else if (state & UI_BUT_ANIMATED) {
- widget_state_blend(wt->wcol.item, wcol_state->inner_anim, blend);
- }
- else if (state & UI_BUT_DRIVEN) {
- widget_state_blend(wt->wcol.item, wcol_state->inner_driven, blend);
- }
- else if (state & UI_BUT_OVERRIDEN) {
- widget_state_blend(wt->wcol.item, wcol_state->inner_overridden, blend);
- }
- }
+ uiWidgetStateColors *wcol_state = wt->wcol_state;
+ /* XXX special tweak to make sure that bar will still be visible */
+ float blend = wcol_state->blend - 0.2f;
+
+ /* call this for option button */
+ widget_state(wt, state, drawflag);
+
+ /* now, set the inner-part so that it reflects state settings too */
+ /* TODO: maybe we should have separate settings for the blending colors used for this case? */
+ if (state & UI_SELECT) {
+
+ if (drawflag & UI_BUT_ANIMATED_CHANGED) {
+ widget_state_blend(wt->wcol.item, wcol_state->inner_changed_sel, blend);
+ }
+ else if (state & UI_BUT_ANIMATED_KEY) {
+ widget_state_blend(wt->wcol.item, wcol_state->inner_key_sel, blend);
+ }
+ else if (state & UI_BUT_ANIMATED) {
+ widget_state_blend(wt->wcol.item, wcol_state->inner_anim_sel, blend);
+ }
+ else if (state & UI_BUT_DRIVEN) {
+ widget_state_blend(wt->wcol.item, wcol_state->inner_driven_sel, blend);
+ }
+ else if (state & UI_BUT_OVERRIDEN) {
+ widget_state_blend(wt->wcol.item, wcol_state->inner_overridden_sel, blend);
+ }
+
+ if (state & UI_SELECT) {
+ SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
+ }
+ }
+ else {
+ if (drawflag & UI_BUT_ANIMATED_CHANGED) {
+ widget_state_blend(wt->wcol.item, wcol_state->inner_changed, blend);
+ }
+ else if (state & UI_BUT_ANIMATED_KEY) {
+ widget_state_blend(wt->wcol.item, wcol_state->inner_key, blend);
+ }
+ else if (state & UI_BUT_ANIMATED) {
+ widget_state_blend(wt->wcol.item, wcol_state->inner_anim, blend);
+ }
+ else if (state & UI_BUT_DRIVEN) {
+ widget_state_blend(wt->wcol.item, wcol_state->inner_driven, blend);
+ }
+ else if (state & UI_BUT_OVERRIDEN) {
+ widget_state_blend(wt->wcol.item, wcol_state->inner_overridden, blend);
+ }
+ }
}
/* labels use theme colors for text */
static void widget_state_option_menu(uiWidgetType *wt, int state, int drawflag)
{
- bTheme *btheme = UI_GetTheme(); /* XXX */
-
- /* call this for option button */
- widget_state(wt, state, drawflag);
-
- /* if not selected we get theme from menu back */
- if (state & UI_SELECT) {
- copy_v3_v3_char(wt->wcol.text, btheme->tui.wcol_menu_back.text_sel);
- }
- else {
- copy_v3_v3_char(wt->wcol.text, btheme->tui.wcol_menu_back.text);
- }
+ bTheme *btheme = UI_GetTheme(); /* XXX */
+
+ /* call this for option button */
+ widget_state(wt, state, drawflag);
+
+ /* if not selected we get theme from menu back */
+ if (state & UI_SELECT) {
+ copy_v3_v3_char(wt->wcol.text, btheme->tui.wcol_menu_back.text_sel);
+ }
+ else {
+ copy_v3_v3_char(wt->wcol.text, btheme->tui.wcol_menu_back.text);
+ }
}
-
static void widget_state_nothing(uiWidgetType *wt, int UNUSED(state), int UNUSED(drawflag))
{
- wt->wcol = *(wt->wcol_theme);
+ wt->wcol = *(wt->wcol_theme);
}
/* special case, button that calls pulldown */
static void widget_state_pulldown(uiWidgetType *wt, int UNUSED(state), int UNUSED(drawflag))
{
- wt->wcol = *(wt->wcol_theme);
+ wt->wcol = *(wt->wcol_theme);
}
/* special case, pie menu items */
static void widget_state_pie_menu_item(uiWidgetType *wt, int state, int UNUSED(drawflag))
{
- wt->wcol = *(wt->wcol_theme);
-
- /* active and disabled (not so common) */
- if ((state & UI_BUT_DISABLED) && (state & UI_ACTIVE)) {
- widget_state_blend(wt->wcol.text, wt->wcol.text_sel, 0.5f);
- /* draw the backdrop at low alpha, helps navigating with keys
- * when disabled items are active */
- copy_v4_v4_char(wt->wcol.inner, wt->wcol.item);
- wt->wcol.inner[3] = 64;
- }
- else {
- /* regular active */
- if (state & (UI_SELECT | UI_ACTIVE)) {
- copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
- }
- else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
- /* regular disabled */
- widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f);
- }
-
- if (state & UI_SELECT) {
- copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
- }
- else if (state & UI_ACTIVE) {
- copy_v4_v4_char(wt->wcol.inner, wt->wcol.item);
- }
- }
+ wt->wcol = *(wt->wcol_theme);
+
+ /* active and disabled (not so common) */
+ if ((state & UI_BUT_DISABLED) && (state & UI_ACTIVE)) {
+ widget_state_blend(wt->wcol.text, wt->wcol.text_sel, 0.5f);
+ /* draw the backdrop at low alpha, helps navigating with keys
+ * when disabled items are active */
+ copy_v4_v4_char(wt->wcol.inner, wt->wcol.item);
+ wt->wcol.inner[3] = 64;
+ }
+ else {
+ /* regular active */
+ if (state & (UI_SELECT | UI_ACTIVE)) {
+ copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
+ }
+ else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
+ /* regular disabled */
+ widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f);
+ }
+
+ if (state & UI_SELECT) {
+ copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
+ }
+ else if (state & UI_ACTIVE) {
+ copy_v4_v4_char(wt->wcol.inner, wt->wcol.item);
+ }
+ }
}
/* special case, menu items */
static void widget_state_menu_item(uiWidgetType *wt, int state, int UNUSED(drawflag))
{
- wt->wcol = *(wt->wcol_theme);
-
- /* active and disabled (not so common) */
- if ((state & UI_BUT_DISABLED) && (state & UI_ACTIVE)) {
- widget_state_blend(wt->wcol.text, wt->wcol.text_sel, 0.5f);
- /* draw the backdrop at low alpha, helps navigating with keys
- * when disabled items are active */
- copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
- wt->wcol.inner[3] = 64;
- }
- else {
- /* regular active */
- if (state & UI_ACTIVE) {
- copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
- }
- else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
- /* regular disabled */
- widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f);
- }
-
- if (state & UI_ACTIVE) {
- copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
- }
- }
+ wt->wcol = *(wt->wcol_theme);
+
+ /* active and disabled (not so common) */
+ if ((state & UI_BUT_DISABLED) && (state & UI_ACTIVE)) {
+ widget_state_blend(wt->wcol.text, wt->wcol.text_sel, 0.5f);
+ /* draw the backdrop at low alpha, helps navigating with keys
+ * when disabled items are active */
+ copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
+ wt->wcol.inner[3] = 64;
+ }
+ else {
+ /* regular active */
+ if (state & UI_ACTIVE) {
+ copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
+ }
+ else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
+ /* regular disabled */
+ widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f);
+ }
+
+ if (state & UI_ACTIVE) {
+ copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
+ }
+ }
}
-
/* ************ menu backdrop ************************* */
/* outside of rect, rad to left/bottom/right */
static void widget_softshadow(const rcti *rect, int roundboxalign, const float radin)
{
- bTheme *btheme = UI_GetTheme();
- uiWidgetBase wtb;
- rcti rect1 = *rect;
- float alphastep;
- int step, totvert;
- float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2];
- const float radout = UI_ThemeMenuShadowWidth();
+ bTheme *btheme = UI_GetTheme();
+ uiWidgetBase wtb;
+ rcti rect1 = *rect;
+ float alphastep;
+ int step, totvert;
+ float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2];
+ const float radout = UI_ThemeMenuShadowWidth();
- /* disabled shadow */
- if (radout == 0.0f) {
- return;
- }
+ /* disabled shadow */
+ if (radout == 0.0f) {
+ return;
+ }
- /* prevent tooltips to not show round shadow */
- if (radout > 0.2f * BLI_rcti_size_y(&rect1)) {
- rect1.ymax -= 0.2f * BLI_rcti_size_y(&rect1);
- }
- else {
- rect1.ymax -= radout;
- }
+ /* prevent tooltips to not show round shadow */
+ if (radout > 0.2f * BLI_rcti_size_y(&rect1)) {
+ rect1.ymax -= 0.2f * BLI_rcti_size_y(&rect1);
+ }
+ else {
+ rect1.ymax -= radout;
+ }
- /* inner part */
- totvert = round_box_shadow_edges(wtb.inner_v, &rect1, radin, roundboxalign & (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT), 0.0f);
+ /* inner part */
+ totvert = round_box_shadow_edges(wtb.inner_v,
+ &rect1,
+ radin,
+ roundboxalign & (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT),
+ 0.0f);
- /* we draw a number of increasing size alpha quad strips */
- alphastep = 3.0f * btheme->tui.menu_shadow_fac / radout;
+ /* we draw a number of increasing size alpha quad strips */
+ alphastep = 3.0f * btheme->tui.menu_shadow_fac / radout;
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- for (step = 1; step <= (int)radout; step++) {
- float expfac = sqrtf(step / radout);
+ for (step = 1; step <= (int)radout; step++) {
+ float expfac = sqrtf(step / radout);
- round_box_shadow_edges(wtb.outer_v, &rect1, radin, UI_CNR_ALL, (float)step);
+ round_box_shadow_edges(wtb.outer_v, &rect1, radin, UI_CNR_ALL, (float)step);
- immUniformColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac));
+ immUniformColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac));
- widget_verts_to_triangle_strip(&wtb, totvert, triangle_strip);
+ widget_verts_to_triangle_strip(&wtb, totvert, triangle_strip);
- widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, totvert * 2);
- }
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, totvert * 2);
+ }
- immUnbindProgram();
+ immUnbindProgram();
}
static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int direction)
{
- uiWidgetBase wtb;
- int roundboxalign = UI_CNR_ALL;
-
- widget_init(&wtb);
-
- /* menu is 2nd level or deeper */
- if (flag & UI_BLOCK_POPUP) {
- //rect->ymin -= 4.0;
- //rect->ymax += 4.0;
- }
- else if (direction == UI_DIR_DOWN) {
- roundboxalign = (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
- rect->ymin -= 0.1f * U.widget_unit;
- }
- else if (direction == UI_DIR_UP) {
- roundboxalign = UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT;
- rect->ymax += 0.1f * U.widget_unit;
- }
-
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
- widget_softshadow(rect, roundboxalign, wcol->roundness * U.widget_unit);
-
- round_box_edges(&wtb, roundboxalign, rect, wcol->roundness * U.widget_unit);
- wtb.draw_emboss = false;
- widgetbase_draw(&wtb, wcol);
-
- GPU_blend(false);
+ uiWidgetBase wtb;
+ int roundboxalign = UI_CNR_ALL;
+
+ widget_init(&wtb);
+
+ /* menu is 2nd level or deeper */
+ if (flag & UI_BLOCK_POPUP) {
+ //rect->ymin -= 4.0;
+ //rect->ymax += 4.0;
+ }
+ else if (direction == UI_DIR_DOWN) {
+ roundboxalign = (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
+ rect->ymin -= 0.1f * U.widget_unit;
+ }
+ else if (direction == UI_DIR_UP) {
+ roundboxalign = UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT;
+ rect->ymax += 0.1f * U.widget_unit;
+ }
+
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
+ widget_softshadow(rect, roundboxalign, wcol->roundness * U.widget_unit);
+
+ round_box_edges(&wtb, roundboxalign, rect, wcol->roundness * U.widget_unit);
+ wtb.draw_emboss = false;
+ widgetbase_draw(&wtb, wcol);
+
+ GPU_blend(false);
}
static void ui_hsv_cursor(float x, float y)
{
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3f(1.0f, 1.0f, 1.0f);
- imm_draw_circle_fill_2d(pos, x, y, 3.0f * U.pixelsize, 8);
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
+ imm_draw_circle_fill_2d(pos, x, y, 3.0f * U.pixelsize, 8);
- GPU_blend(true);
- GPU_line_smooth(true);
- immUniformColor3f(0.0f, 0.0f, 0.0f);
- imm_draw_circle_wire_2d(pos, x, y, 3.0f * U.pixelsize, 12);
- GPU_blend(false);
- GPU_line_smooth(false);
+ GPU_blend(true);
+ GPU_line_smooth(true);
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+ imm_draw_circle_wire_2d(pos, x, y, 3.0f * U.pixelsize, 12);
+ GPU_blend(false);
+ GPU_line_smooth(false);
- immUnbindProgram();
+ immUnbindProgram();
}
void ui_hsvcircle_vals_from_pos(
- const rcti *rect, const float mx, const float my,
- float *r_val_rad, float *r_val_dist)
+ const rcti *rect, const float mx, const float my, float *r_val_rad, float *r_val_dist)
{
- /* duplication of code... well, simple is better now */
- const float centx = BLI_rcti_cent_x_fl(rect);
- const float centy = BLI_rcti_cent_y_fl(rect);
- const float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
- const float m_delta[2] = {mx - centx, my - centy};
- const float dist_sq = len_squared_v2(m_delta);
-
- *r_val_dist = (dist_sq < (radius * radius)) ? sqrtf(dist_sq) / radius : 1.0f;
- *r_val_rad = atan2f(m_delta[0], m_delta[1]) / (2.0f * (float)M_PI) + 0.5f;
+ /* duplication of code... well, simple is better now */
+ const float centx = BLI_rcti_cent_x_fl(rect);
+ const float centy = BLI_rcti_cent_y_fl(rect);
+ const float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
+ const float m_delta[2] = {mx - centx, my - centy};
+ const float dist_sq = len_squared_v2(m_delta);
+
+ *r_val_dist = (dist_sq < (radius * radius)) ? sqrtf(dist_sq) / radius : 1.0f;
+ *r_val_rad = atan2f(m_delta[0], m_delta[1]) / (2.0f * (float)M_PI) + 0.5f;
}
/* cursor in hsv circle, in float units -1 to 1, to map on radius */
void ui_hsvcircle_pos_from_vals(
- const ColorPicker *cpicker, const rcti *rect, const float *hsv,
- float *r_xpos, float *r_ypos)
+ const ColorPicker *cpicker, const rcti *rect, const float *hsv, float *r_xpos, float *r_ypos)
{
- /* duplication of code... well, simple is better now */
- const float centx = BLI_rcti_cent_x_fl(rect);
- const float centy = BLI_rcti_cent_y_fl(rect);
- float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
- float ang, radius_t;
-
- ang = 2.0f * (float)M_PI * hsv[0] + (float)M_PI_2;
-
- if (cpicker->use_color_cubic && (U.color_picker_type == USER_CP_CIRCLE_HSV)) {
- radius_t = (1.0f - pow3f(1.0f - hsv[1]));
- }
- else {
- radius_t = hsv[1];
- }
-
- radius = clamp_f(radius_t, 0.0f, 1.0f) * radius;
- *r_xpos = centx + cosf(-ang) * radius;
- *r_ypos = centy + sinf(-ang) * radius;
+ /* duplication of code... well, simple is better now */
+ const float centx = BLI_rcti_cent_x_fl(rect);
+ const float centy = BLI_rcti_cent_y_fl(rect);
+ float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
+ float ang, radius_t;
+
+ ang = 2.0f * (float)M_PI * hsv[0] + (float)M_PI_2;
+
+ if (cpicker->use_color_cubic && (U.color_picker_type == USER_CP_CIRCLE_HSV)) {
+ radius_t = (1.0f - pow3f(1.0f - hsv[1]));
+ }
+ else {
+ radius_t = hsv[1];
+ }
+
+ radius = clamp_f(radius_t, 0.0f, 1.0f) * radius;
+ *r_xpos = centx + cosf(-ang) * radius;
+ *r_ypos = centy + sinf(-ang) * radius;
}
static void ui_draw_but_HSVCIRCLE(uiBut *but, const uiWidgetColors *wcol, const rcti *rect)
{
- /* TODO(merwin): reimplement as shader for pixel-perfect colors */
-
- const int tot = 64;
- const float radstep = 2.0f * (float)M_PI / (float)tot;
- const float centx = BLI_rcti_cent_x_fl(rect);
- const float centy = BLI_rcti_cent_y_fl(rect);
- float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
-
- ColorPicker *cpicker = but->custom_data;
- float rgb[3], hsv[3], rgb_center[3];
- bool is_color_gamma = ui_but_is_color_gamma(but);
-
- /* Initialize for compatibility. */
- copy_v3_v3(hsv, cpicker->color_data);
-
- /* Compute current hue. */
- ui_but_v3_get(but, rgb);
- ui_scene_linear_to_color_picker_space(but, rgb);
- ui_rgb_to_color_picker_compat_v(rgb, hsv);
-
- CLAMP(hsv[2], 0.0f, 1.0f); /* for display only */
-
- /* exception: if 'lock' is set
- * lock the value of the color wheel to 1.
- * Useful for color correction tools where you're only interested in hue. */
- if (cpicker->use_color_lock) {
- if (U.color_picker_type == USER_CP_CIRCLE_HSV) {
- hsv[2] = 1.0f;
- }
- else {
- hsv[2] = 0.5f;
- }
- }
-
- const float hsv_center[3] = {0.0f, 0.0f, hsv[2]};
- ui_color_picker_to_rgb_v(hsv_center, rgb_center);
- ui_color_picker_to_scene_linear_space(but, rgb_center);
-
- if (!is_color_gamma) {
- ui_block_cm_to_display_space_v3(but->block, rgb_center);
- }
-
- GPUVertFormat *format = immVertexFormat();
- 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_SMOOTH_COLOR);
-
- immBegin(GPU_PRIM_TRI_FAN, tot + 2);
- immAttr3fv(color, rgb_center);
- immVertex2f(pos, centx, centy);
-
- float ang = 0.0f;
- for (int a = 0; a <= tot; a++, ang += radstep) {
- float si = sinf(ang);
- float co = cosf(ang);
- float hsv_ang[3];
- float rgb_ang[3];
-
- ui_hsvcircle_vals_from_pos(
- rect, centx + co * radius, centy + si * radius,
- hsv_ang, hsv_ang + 1);
- hsv_ang[2] = hsv[2];
-
- ui_color_picker_to_rgb_v(hsv_ang, rgb_ang);
- ui_color_picker_to_scene_linear_space(but, rgb_ang);
-
- if (!is_color_gamma) {
- ui_block_cm_to_display_space_v3(but->block, rgb_ang);
- }
-
- immAttr3fv(color, rgb_ang);
- immVertex2f(pos, centx + co * radius, centy + si * radius);
- }
- immEnd();
- immUnbindProgram();
-
- /* fully rounded outline */
- format = immVertexFormat();
- pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- GPU_blend(true);
- GPU_line_smooth(true);
-
- immUniformColor3ubv((uchar *)wcol->outline);
- imm_draw_circle_wire_2d(pos, centx, centy, radius, tot);
-
- immUnbindProgram();
-
- GPU_blend(false);
- GPU_line_smooth(false);
-
- /* cursor */
- copy_v3_v3(hsv, cpicker->color_data);
- ui_but_v3_get(but, rgb);
- ui_scene_linear_to_color_picker_space(but, rgb);
- ui_rgb_to_color_picker_compat_v(rgb, hsv);
-
- float xpos, ypos;
- ui_hsvcircle_pos_from_vals(cpicker, rect, hsv, &xpos, &ypos);
- ui_hsv_cursor(xpos, ypos);
+ /* TODO(merwin): reimplement as shader for pixel-perfect colors */
+
+ const int tot = 64;
+ const float radstep = 2.0f * (float)M_PI / (float)tot;
+ const float centx = BLI_rcti_cent_x_fl(rect);
+ const float centy = BLI_rcti_cent_y_fl(rect);
+ float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
+
+ ColorPicker *cpicker = but->custom_data;
+ float rgb[3], hsv[3], rgb_center[3];
+ bool is_color_gamma = ui_but_is_color_gamma(but);
+
+ /* Initialize for compatibility. */
+ copy_v3_v3(hsv, cpicker->color_data);
+
+ /* Compute current hue. */
+ ui_but_v3_get(but, rgb);
+ ui_scene_linear_to_color_picker_space(but, rgb);
+ ui_rgb_to_color_picker_compat_v(rgb, hsv);
+
+ CLAMP(hsv[2], 0.0f, 1.0f); /* for display only */
+
+ /* exception: if 'lock' is set
+ * lock the value of the color wheel to 1.
+ * Useful for color correction tools where you're only interested in hue. */
+ if (cpicker->use_color_lock) {
+ if (U.color_picker_type == USER_CP_CIRCLE_HSV) {
+ hsv[2] = 1.0f;
+ }
+ else {
+ hsv[2] = 0.5f;
+ }
+ }
+
+ const float hsv_center[3] = {0.0f, 0.0f, hsv[2]};
+ ui_color_picker_to_rgb_v(hsv_center, rgb_center);
+ ui_color_picker_to_scene_linear_space(but, rgb_center);
+
+ if (!is_color_gamma) {
+ ui_block_cm_to_display_space_v3(but->block, rgb_center);
+ }
+
+ GPUVertFormat *format = immVertexFormat();
+ 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_SMOOTH_COLOR);
+
+ immBegin(GPU_PRIM_TRI_FAN, tot + 2);
+ immAttr3fv(color, rgb_center);
+ immVertex2f(pos, centx, centy);
+
+ float ang = 0.0f;
+ for (int a = 0; a <= tot; a++, ang += radstep) {
+ float si = sinf(ang);
+ float co = cosf(ang);
+ float hsv_ang[3];
+ float rgb_ang[3];
+
+ ui_hsvcircle_vals_from_pos(
+ rect, centx + co * radius, centy + si * radius, hsv_ang, hsv_ang + 1);
+ hsv_ang[2] = hsv[2];
+
+ ui_color_picker_to_rgb_v(hsv_ang, rgb_ang);
+ ui_color_picker_to_scene_linear_space(but, rgb_ang);
+
+ if (!is_color_gamma) {
+ ui_block_cm_to_display_space_v3(but->block, rgb_ang);
+ }
+
+ immAttr3fv(color, rgb_ang);
+ immVertex2f(pos, centx + co * radius, centy + si * radius);
+ }
+ immEnd();
+ immUnbindProgram();
+
+ /* fully rounded outline */
+ format = immVertexFormat();
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ GPU_blend(true);
+ GPU_line_smooth(true);
+
+ immUniformColor3ubv((uchar *)wcol->outline);
+ imm_draw_circle_wire_2d(pos, centx, centy, radius, tot);
+
+ immUnbindProgram();
+
+ GPU_blend(false);
+ GPU_line_smooth(false);
+
+ /* cursor */
+ copy_v3_v3(hsv, cpicker->color_data);
+ ui_but_v3_get(but, rgb);
+ ui_scene_linear_to_color_picker_space(but, rgb);
+ ui_rgb_to_color_picker_compat_v(rgb, hsv);
+
+ float xpos, ypos;
+ ui_hsvcircle_pos_from_vals(cpicker, rect, hsv, &xpos, &ypos);
+ ui_hsv_cursor(xpos, ypos);
}
/* ************ custom buttons, old stuff ************** */
@@ -2831,1427 +2972,1462 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, const uiWidgetColors *wcol, const
/* draws in resolution of 48x4 colors */
void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, const float alpha)
{
- /* allows for 4 steps (red->yellow) */
- const int steps = 48;
- const float color_step = 1.0f / steps;
- int a;
- float h = hsv[0], s = hsv[1], v = hsv[2];
- float dx, dy, sx1, sx2, sy;
- float col0[4][3]; /* left half, rect bottom to top */
- float col1[4][3]; /* right half, rect bottom to top */
-
- /* draw series of gouraud rects */
-
- switch (type) {
- case UI_GRAD_SV:
- hsv_to_rgb(h, 0.0, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
- hsv_to_rgb(h, 0.0, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
- hsv_to_rgb(h, 0.0, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
- hsv_to_rgb(h, 0.0, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]);
- break;
- case UI_GRAD_HV:
- hsv_to_rgb(0.0, s, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
- hsv_to_rgb(0.0, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
- hsv_to_rgb(0.0, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
- hsv_to_rgb(0.0, s, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]);
- break;
- case UI_GRAD_HS:
- hsv_to_rgb(0.0, 0.0, v, &col1[0][0], &col1[0][1], &col1[0][2]);
- hsv_to_rgb(0.0, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
- hsv_to_rgb(0.0, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
- hsv_to_rgb(0.0, 1.0, v, &col1[3][0], &col1[3][1], &col1[3][2]);
- break;
- case UI_GRAD_H:
- hsv_to_rgb(0.0, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]);
- copy_v3_v3(col1[1], col1[0]);
- copy_v3_v3(col1[2], col1[0]);
- copy_v3_v3(col1[3], col1[0]);
- break;
- case UI_GRAD_S:
- hsv_to_rgb(1.0, 0.0, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]);
- copy_v3_v3(col1[0], col1[1]);
- copy_v3_v3(col1[2], col1[1]);
- copy_v3_v3(col1[3], col1[1]);
- break;
- case UI_GRAD_V:
- hsv_to_rgb(1.0, 1.0, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]);
- copy_v3_v3(col1[0], col1[2]);
- copy_v3_v3(col1[1], col1[2]);
- copy_v3_v3(col1[3], col1[2]);
- break;
- default:
- assert(!"invalid 'type' argument");
- hsv_to_rgb(1.0, 1.0, 1.0, &col1[2][0], &col1[2][1], &col1[2][2]);
- copy_v3_v3(col1[0], col1[2]);
- copy_v3_v3(col1[1], col1[2]);
- copy_v3_v3(col1[3], col1[2]);
- break;
- }
-
- /* old below */
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
-
- immBegin(GPU_PRIM_TRIS, steps * 3 * 6);
-
- /* 0.999 = prevent float inaccuracy for steps */
- for (dx = 0.0f; dx < 0.999f; dx += color_step) {
- const float dx_next = dx + color_step;
-
- /* previous color */
- copy_v3_v3(col0[0], col1[0]);
- copy_v3_v3(col0[1], col1[1]);
- copy_v3_v3(col0[2], col1[2]);
- copy_v3_v3(col0[3], col1[3]);
-
- /* new color */
- switch (type) {
- case UI_GRAD_SV:
- hsv_to_rgb(h, dx, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
- hsv_to_rgb(h, dx, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
- hsv_to_rgb(h, dx, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
- hsv_to_rgb(h, dx, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]);
- break;
- case UI_GRAD_HV:
- hsv_to_rgb(dx_next, s, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
- hsv_to_rgb(dx_next, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
- hsv_to_rgb(dx_next, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
- hsv_to_rgb(dx_next, s, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]);
- break;
- case UI_GRAD_HS:
- hsv_to_rgb(dx_next, 0.0, v, &col1[0][0], &col1[0][1], &col1[0][2]);
- hsv_to_rgb(dx_next, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
- hsv_to_rgb(dx_next, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
- hsv_to_rgb(dx_next, 1.0, v, &col1[3][0], &col1[3][1], &col1[3][2]);
- break;
- case UI_GRAD_H:
- /* annoying but without this the color shifts - could be solved some other way
- * - campbell */
- hsv_to_rgb(dx_next, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]);
- copy_v3_v3(col1[1], col1[0]);
- copy_v3_v3(col1[2], col1[0]);
- copy_v3_v3(col1[3], col1[0]);
- break;
- case UI_GRAD_S:
- hsv_to_rgb(h, dx, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]);
- copy_v3_v3(col1[0], col1[1]);
- copy_v3_v3(col1[2], col1[1]);
- copy_v3_v3(col1[3], col1[1]);
- break;
- case UI_GRAD_V:
- hsv_to_rgb(h, 1.0, dx, &col1[2][0], &col1[2][1], &col1[2][2]);
- copy_v3_v3(col1[0], col1[2]);
- copy_v3_v3(col1[1], col1[2]);
- copy_v3_v3(col1[3], col1[2]);
- break;
- }
-
- /* rect */
- sx1 = rect->xmin + dx * BLI_rcti_size_x(rect);
- sx2 = rect->xmin + dx_next * BLI_rcti_size_x(rect);
- sy = rect->ymin;
- dy = (float)BLI_rcti_size_y(rect) / 3.0f;
-
- for (a = 0; a < 3; a++, sy += dy) {
- immAttr4f(col, col0[a][0], col0[a][1], col0[a][2], alpha);
- immVertex2f(pos, sx1, sy);
-
- immAttr4f(col, col1[a][0], col1[a][1], col1[a][2], alpha);
- immVertex2f(pos, sx2, sy);
-
- immAttr4f(col, col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
- immVertex2f(pos, sx2, sy + dy);
-
- immAttr4f(col, col0[a][0], col0[a][1], col0[a][2], alpha);
- immVertex2f(pos, sx1, sy);
-
- immAttr4f(col, col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
- immVertex2f(pos, sx2, sy + dy);
-
- immAttr4f(col, col0[a + 1][0], col0[a + 1][1], col0[a + 1][2], alpha);
- immVertex2f(pos, sx1, sy + dy);
- }
- }
- immEnd();
-
- immUnbindProgram();
+ /* allows for 4 steps (red->yellow) */
+ const int steps = 48;
+ const float color_step = 1.0f / steps;
+ int a;
+ float h = hsv[0], s = hsv[1], v = hsv[2];
+ float dx, dy, sx1, sx2, sy;
+ float col0[4][3]; /* left half, rect bottom to top */
+ float col1[4][3]; /* right half, rect bottom to top */
+
+ /* draw series of gouraud rects */
+
+ switch (type) {
+ case UI_GRAD_SV:
+ hsv_to_rgb(h, 0.0, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
+ hsv_to_rgb(h, 0.0, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
+ hsv_to_rgb(h, 0.0, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
+ hsv_to_rgb(h, 0.0, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]);
+ break;
+ case UI_GRAD_HV:
+ hsv_to_rgb(0.0, s, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
+ hsv_to_rgb(0.0, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
+ hsv_to_rgb(0.0, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
+ hsv_to_rgb(0.0, s, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]);
+ break;
+ case UI_GRAD_HS:
+ hsv_to_rgb(0.0, 0.0, v, &col1[0][0], &col1[0][1], &col1[0][2]);
+ hsv_to_rgb(0.0, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
+ hsv_to_rgb(0.0, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
+ hsv_to_rgb(0.0, 1.0, v, &col1[3][0], &col1[3][1], &col1[3][2]);
+ break;
+ case UI_GRAD_H:
+ hsv_to_rgb(0.0, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]);
+ copy_v3_v3(col1[1], col1[0]);
+ copy_v3_v3(col1[2], col1[0]);
+ copy_v3_v3(col1[3], col1[0]);
+ break;
+ case UI_GRAD_S:
+ hsv_to_rgb(1.0, 0.0, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]);
+ copy_v3_v3(col1[0], col1[1]);
+ copy_v3_v3(col1[2], col1[1]);
+ copy_v3_v3(col1[3], col1[1]);
+ break;
+ case UI_GRAD_V:
+ hsv_to_rgb(1.0, 1.0, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]);
+ copy_v3_v3(col1[0], col1[2]);
+ copy_v3_v3(col1[1], col1[2]);
+ copy_v3_v3(col1[3], col1[2]);
+ break;
+ default:
+ assert(!"invalid 'type' argument");
+ hsv_to_rgb(1.0, 1.0, 1.0, &col1[2][0], &col1[2][1], &col1[2][2]);
+ copy_v3_v3(col1[0], col1[2]);
+ copy_v3_v3(col1[1], col1[2]);
+ copy_v3_v3(col1[3], col1[2]);
+ break;
+ }
+
+ /* old below */
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ immBegin(GPU_PRIM_TRIS, steps * 3 * 6);
+
+ /* 0.999 = prevent float inaccuracy for steps */
+ for (dx = 0.0f; dx < 0.999f; dx += color_step) {
+ const float dx_next = dx + color_step;
+
+ /* previous color */
+ copy_v3_v3(col0[0], col1[0]);
+ copy_v3_v3(col0[1], col1[1]);
+ copy_v3_v3(col0[2], col1[2]);
+ copy_v3_v3(col0[3], col1[3]);
+
+ /* new color */
+ switch (type) {
+ case UI_GRAD_SV:
+ hsv_to_rgb(h, dx, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
+ hsv_to_rgb(h, dx, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
+ hsv_to_rgb(h, dx, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
+ hsv_to_rgb(h, dx, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]);
+ break;
+ case UI_GRAD_HV:
+ hsv_to_rgb(dx_next, s, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
+ hsv_to_rgb(dx_next, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
+ hsv_to_rgb(dx_next, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
+ hsv_to_rgb(dx_next, s, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]);
+ break;
+ case UI_GRAD_HS:
+ hsv_to_rgb(dx_next, 0.0, v, &col1[0][0], &col1[0][1], &col1[0][2]);
+ hsv_to_rgb(dx_next, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
+ hsv_to_rgb(dx_next, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
+ hsv_to_rgb(dx_next, 1.0, v, &col1[3][0], &col1[3][1], &col1[3][2]);
+ break;
+ case UI_GRAD_H:
+ /* annoying but without this the color shifts - could be solved some other way
+ * - campbell */
+ hsv_to_rgb(dx_next, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]);
+ copy_v3_v3(col1[1], col1[0]);
+ copy_v3_v3(col1[2], col1[0]);
+ copy_v3_v3(col1[3], col1[0]);
+ break;
+ case UI_GRAD_S:
+ hsv_to_rgb(h, dx, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]);
+ copy_v3_v3(col1[0], col1[1]);
+ copy_v3_v3(col1[2], col1[1]);
+ copy_v3_v3(col1[3], col1[1]);
+ break;
+ case UI_GRAD_V:
+ hsv_to_rgb(h, 1.0, dx, &col1[2][0], &col1[2][1], &col1[2][2]);
+ copy_v3_v3(col1[0], col1[2]);
+ copy_v3_v3(col1[1], col1[2]);
+ copy_v3_v3(col1[3], col1[2]);
+ break;
+ }
+
+ /* rect */
+ sx1 = rect->xmin + dx * BLI_rcti_size_x(rect);
+ sx2 = rect->xmin + dx_next * BLI_rcti_size_x(rect);
+ sy = rect->ymin;
+ dy = (float)BLI_rcti_size_y(rect) / 3.0f;
+
+ for (a = 0; a < 3; a++, sy += dy) {
+ immAttr4f(col, col0[a][0], col0[a][1], col0[a][2], alpha);
+ immVertex2f(pos, sx1, sy);
+
+ immAttr4f(col, col1[a][0], col1[a][1], col1[a][2], alpha);
+ immVertex2f(pos, sx2, sy);
+
+ immAttr4f(col, col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
+ immVertex2f(pos, sx2, sy + dy);
+
+ immAttr4f(col, col0[a][0], col0[a][1], col0[a][2], alpha);
+ immVertex2f(pos, sx1, sy);
+
+ immAttr4f(col, col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
+ immVertex2f(pos, sx2, sy + dy);
+
+ immAttr4f(col, col0[a + 1][0], col0[a + 1][1], col0[a + 1][2], alpha);
+ immVertex2f(pos, sx1, sy + dy);
+ }
+ }
+ immEnd();
+
+ immUnbindProgram();
}
void ui_hsvcube_pos_from_vals(
- const uiBut *but, const rcti *rect, const float *hsv,
- float *r_xp, float *r_yp)
+ const uiBut *but, const rcti *rect, const float *hsv, float *r_xp, float *r_yp)
{
- float x = 0.0f, y = 0.0f;
-
- switch ((int)but->a1) {
- case UI_GRAD_SV:
- x = hsv[1]; y = hsv[2]; break;
- case UI_GRAD_HV:
- x = hsv[0]; y = hsv[2]; break;
- case UI_GRAD_HS:
- x = hsv[0]; y = hsv[1]; break;
- case UI_GRAD_H:
- x = hsv[0]; y = 0.5; break;
- case UI_GRAD_S:
- x = hsv[1]; y = 0.5; break;
- case UI_GRAD_V:
- x = hsv[2]; y = 0.5; break;
- case UI_GRAD_L_ALT:
- x = 0.5f;
- /* exception only for value strip - use the range set in but->min/max */
- y = hsv[2];
- break;
- case UI_GRAD_V_ALT:
- x = 0.5f;
- /* exception only for value strip - use the range set in but->min/max */
- y = (hsv[2] - but->softmin) / (but->softmax - but->softmin);
- break;
- }
-
- /* cursor */
- *r_xp = rect->xmin + x * BLI_rcti_size_x(rect);
- *r_yp = rect->ymin + y * BLI_rcti_size_y(rect);
+ float x = 0.0f, y = 0.0f;
+
+ switch ((int)but->a1) {
+ case UI_GRAD_SV:
+ x = hsv[1];
+ y = hsv[2];
+ break;
+ case UI_GRAD_HV:
+ x = hsv[0];
+ y = hsv[2];
+ break;
+ case UI_GRAD_HS:
+ x = hsv[0];
+ y = hsv[1];
+ break;
+ case UI_GRAD_H:
+ x = hsv[0];
+ y = 0.5;
+ break;
+ case UI_GRAD_S:
+ x = hsv[1];
+ y = 0.5;
+ break;
+ case UI_GRAD_V:
+ x = hsv[2];
+ y = 0.5;
+ break;
+ case UI_GRAD_L_ALT:
+ x = 0.5f;
+ /* exception only for value strip - use the range set in but->min/max */
+ y = hsv[2];
+ break;
+ case UI_GRAD_V_ALT:
+ x = 0.5f;
+ /* exception only for value strip - use the range set in but->min/max */
+ y = (hsv[2] - but->softmin) / (but->softmax - but->softmin);
+ break;
+ }
+
+ /* cursor */
+ *r_xp = rect->xmin + x * BLI_rcti_size_x(rect);
+ *r_yp = rect->ymin + y * BLI_rcti_size_y(rect);
}
static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect)
{
- float rgb[3];
- float x = 0.0f, y = 0.0f;
- ColorPicker *cpicker = but->custom_data;
- float *hsv = cpicker->color_data;
- float hsv_n[3];
+ float rgb[3];
+ float x = 0.0f, y = 0.0f;
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
+ float hsv_n[3];
- /* Initialize for compatibility. */
- copy_v3_v3(hsv_n, hsv);
+ /* Initialize for compatibility. */
+ copy_v3_v3(hsv_n, hsv);
- ui_but_v3_get(but, rgb);
- ui_scene_linear_to_color_picker_space(but, rgb);
- rgb_to_hsv_compat_v(rgb, hsv_n);
+ ui_but_v3_get(but, rgb);
+ ui_scene_linear_to_color_picker_space(but, rgb);
+ rgb_to_hsv_compat_v(rgb, hsv_n);
- ui_draw_gradient(rect, hsv_n, but->a1, 1.0f);
+ ui_draw_gradient(rect, hsv_n, but->a1, 1.0f);
- ui_hsvcube_pos_from_vals(but, rect, hsv_n, &x, &y);
- CLAMP(x, rect->xmin + 3.0f, rect->xmax - 3.0f);
- CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f);
+ ui_hsvcube_pos_from_vals(but, rect, hsv_n, &x, &y);
+ CLAMP(x, rect->xmin + 3.0f, rect->xmax - 3.0f);
+ CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f);
- ui_hsv_cursor(x, y);
+ ui_hsv_cursor(x, y);
- /* outline */
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3ub(0, 0, 0);
- imm_draw_box_wire_2d(pos, (rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
- immUnbindProgram();
+ /* outline */
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3ub(0, 0, 0);
+ imm_draw_box_wire_2d(pos, (rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
+ immUnbindProgram();
}
/* vertical 'value' slider, using new widget code */
static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
{
- bTheme *btheme = UI_GetTheme();
- uiWidgetColors *wcol = &btheme->tui.wcol_numslider;
- uiWidgetBase wtb;
- const float rad = wcol->roundness * BLI_rcti_size_x(rect);
- float x, y;
- float rgb[3], hsv[3], v;
-
- ui_but_v3_get(but, rgb);
- ui_scene_linear_to_color_picker_space(but, rgb);
-
- if (but->a1 == UI_GRAD_L_ALT) {
- rgb_to_hsl_v(rgb, hsv);
- }
- else {
- rgb_to_hsv_v(rgb, hsv);
- }
- v = hsv[2];
-
- /* map v from property range to [0,1] */
- if (but->a1 == UI_GRAD_V_ALT) {
- float min = but->softmin, max = but->softmax;
- v = (v - min) / (max - min);
- }
-
- widget_init(&wtb);
-
- /* fully rounded */
- round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
-
- /* setup temp colors */
- widgetbase_draw(
- &wtb,
- &((uiWidgetColors){
- .outline = {0, 0, 0, 255},
- .inner = {128, 128, 128, 255},
- .shadetop = 127,
- .shadedown = -128,
- .shaded = 1,
- })
- );
-
- /* We are drawing on top of widget bases. Flush cache. */
- GPU_blend(true);
- UI_widgetbase_draw_cache_flush();
- GPU_blend(false);
-
- /* cursor */
- x = rect->xmin + 0.5f * BLI_rcti_size_x(rect);
- y = rect->ymin + v * BLI_rcti_size_y(rect);
- CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f);
-
- ui_hsv_cursor(x, y);
+ bTheme *btheme = UI_GetTheme();
+ uiWidgetColors *wcol = &btheme->tui.wcol_numslider;
+ uiWidgetBase wtb;
+ const float rad = wcol->roundness * BLI_rcti_size_x(rect);
+ float x, y;
+ float rgb[3], hsv[3], v;
+
+ ui_but_v3_get(but, rgb);
+ ui_scene_linear_to_color_picker_space(but, rgb);
+
+ if (but->a1 == UI_GRAD_L_ALT) {
+ rgb_to_hsl_v(rgb, hsv);
+ }
+ else {
+ rgb_to_hsv_v(rgb, hsv);
+ }
+ v = hsv[2];
+
+ /* map v from property range to [0,1] */
+ if (but->a1 == UI_GRAD_V_ALT) {
+ float min = but->softmin, max = but->softmax;
+ v = (v - min) / (max - min);
+ }
+
+ widget_init(&wtb);
+
+ /* fully rounded */
+ round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
+
+ /* setup temp colors */
+ widgetbase_draw(&wtb,
+ &((uiWidgetColors){
+ .outline = {0, 0, 0, 255},
+ .inner = {128, 128, 128, 255},
+ .shadetop = 127,
+ .shadedown = -128,
+ .shaded = 1,
+ }));
+
+ /* We are drawing on top of widget bases. Flush cache. */
+ GPU_blend(true);
+ UI_widgetbase_draw_cache_flush();
+ GPU_blend(false);
+
+ /* cursor */
+ x = rect->xmin + 0.5f * BLI_rcti_size_x(rect);
+ y = rect->ymin + v * BLI_rcti_size_y(rect);
+ CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f);
+
+ ui_hsv_cursor(x, y);
}
/* Generic round-box drawing. */
static void ui_draw_roundbox(const rcti *rect, const float rad, const uiWidgetColors *wcol)
{
- uiWidgetBase wtb;
- widget_init(&wtb);
- round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
- widgetbase_draw(&wtb, wcol);
-
- /* We are drawing on top of widget bases. Flush cache. */
- GPU_blend(true);
- UI_widgetbase_draw_cache_flush();
- GPU_blend(false);
+ uiWidgetBase wtb;
+ widget_init(&wtb);
+ round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
+ widgetbase_draw(&wtb, wcol);
+
+ /* We are drawing on top of widget bases. Flush cache. */
+ GPU_blend(true);
+ UI_widgetbase_draw_cache_flush();
+ GPU_blend(false);
}
-
/* ************ separator, for menus etc ***************** */
static void ui_draw_separator(const rcti *rect, const uiWidgetColors *wcol)
{
- int y = rect->ymin + BLI_rcti_size_y(rect) / 2 - 1;
- uchar col[4] = {
- wcol->text[0],
- wcol->text[1],
- wcol->text[2],
- 30,
- };
+ int y = rect->ymin + BLI_rcti_size_y(rect) / 2 - 1;
+ uchar col[4] = {
+ wcol->text[0],
+ wcol->text[1],
+ wcol->text[2],
+ 30,
+ };
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- GPU_blend(true);
- immUniformColor4ubv(col);
- GPU_line_width(1.0f);
+ GPU_blend(true);
+ immUniformColor4ubv(col);
+ GPU_line_width(1.0f);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, rect->xmin, y);
- immVertex2f(pos, rect->xmax, y);
- immEnd();
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, rect->xmin, y);
+ immVertex2f(pos, rect->xmax, y);
+ immEnd();
- GPU_blend(false);
+ GPU_blend(false);
- immUnbindProgram();
+ immUnbindProgram();
}
/* ************ button callbacks, draw ***************** */
-static void widget_numbut_draw(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign, bool emboss)
+static void widget_numbut_draw(
+ uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign, bool emboss)
{
- uiWidgetBase wtb;
- const float rad = wcol->roundness * BLI_rcti_size_y(rect);
- const int handle_width = min_ii(BLI_rcti_size_x(rect) / 3, BLI_rcti_size_y(rect) * 0.7f);
-
- if (state & UI_SELECT) {
- SWAP(short, wcol->shadetop, wcol->shadedown);
- }
-
- widget_init(&wtb);
-
- if (!emboss) {
- round_box_edges(&wtb, roundboxalign, rect, rad);
- }
- else {
- wtb.draw_inner = false;
- wtb.draw_outline = false;
- }
-
- /* decoration */
- if ((state & UI_ACTIVE) && !(state & UI_STATE_TEXT_INPUT)) {
- uiWidgetColors wcol_zone;
- uiWidgetBase wtb_zone;
- rcti rect_zone;
- int roundboxalign_zone;
-
- /* left arrow zone */
- widget_init(&wtb_zone);
- wtb_zone.draw_outline = false;
- wtb_zone.draw_emboss = false;
-
- wcol_zone = *wcol;
- copy_v3_v3_char(wcol_zone.item, wcol->text);
- if (state & UI_STATE_ACTIVE_LEFT) {
- widget_active_color(wcol_zone.inner);
- }
-
- rect_zone = *rect;
- rect_zone.xmax = rect->xmin + handle_width + U.pixelsize;
- roundboxalign_zone = roundboxalign & ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
- round_box_edges(&wtb_zone, roundboxalign_zone, &rect_zone, rad);
-
- shape_preset_init_number_arrows(&wtb_zone.tria1, &rect_zone, 0.6f, 'l');
- widgetbase_draw(&wtb_zone, &wcol_zone);
-
- /* right arrow zone */
- widget_init(&wtb_zone);
- wtb_zone.draw_outline = false;
- wtb_zone.draw_emboss = false;
- wtb_zone.tria1.type = ROUNDBOX_TRIA_ARROWS;
-
- wcol_zone = *wcol;
- copy_v3_v3_char(wcol_zone.item, wcol->text);
- if (state & UI_STATE_ACTIVE_RIGHT) {
- widget_active_color(wcol_zone.inner);
- }
-
- rect_zone = *rect;
- rect_zone.xmin = rect->xmax - handle_width - U.pixelsize;
- roundboxalign_zone = roundboxalign & ~(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
- round_box_edges(&wtb_zone, roundboxalign_zone, &rect_zone, rad);
-
- shape_preset_init_number_arrows(&wtb_zone.tria2, &rect_zone, 0.6f, 'r');
- widgetbase_draw(&wtb_zone, &wcol_zone);
-
- /* middle highlight zone */
- widget_init(&wtb_zone);
- wtb_zone.draw_outline = false;
- wtb_zone.draw_emboss = false;
-
- wcol_zone = *wcol;
- copy_v3_v3_char(wcol_zone.item, wcol->text);
- if (!(state & (UI_STATE_ACTIVE_LEFT | UI_STATE_ACTIVE_RIGHT))) {
- widget_active_color(wcol_zone.inner);
- }
-
- rect_zone = *rect;
- rect_zone.xmin = rect->xmin + handle_width - U.pixelsize;
- rect_zone.xmax = rect->xmax - handle_width + U.pixelsize;
- round_box_edges(&wtb_zone, 0, &rect_zone, 0);
- widgetbase_draw(&wtb_zone, &wcol_zone);
-
- /* outline */
- wtb.draw_inner = false;
- widgetbase_draw(&wtb, wcol);
- }
- else {
- /* inner and outline */
- widgetbase_draw(&wtb, wcol);
- }
-
- if (!(state & UI_STATE_TEXT_INPUT)) {
- const float textofs = 0.425f * BLI_rcti_size_y(rect);
-
- /* text space */
- rect->xmin += textofs;
- rect->xmax -= textofs;
- }
+ uiWidgetBase wtb;
+ const float rad = wcol->roundness * BLI_rcti_size_y(rect);
+ const int handle_width = min_ii(BLI_rcti_size_x(rect) / 3, BLI_rcti_size_y(rect) * 0.7f);
+
+ if (state & UI_SELECT) {
+ SWAP(short, wcol->shadetop, wcol->shadedown);
+ }
+
+ widget_init(&wtb);
+
+ if (!emboss) {
+ round_box_edges(&wtb, roundboxalign, rect, rad);
+ }
+ else {
+ wtb.draw_inner = false;
+ wtb.draw_outline = false;
+ }
+
+ /* decoration */
+ if ((state & UI_ACTIVE) && !(state & UI_STATE_TEXT_INPUT)) {
+ uiWidgetColors wcol_zone;
+ uiWidgetBase wtb_zone;
+ rcti rect_zone;
+ int roundboxalign_zone;
+
+ /* left arrow zone */
+ widget_init(&wtb_zone);
+ wtb_zone.draw_outline = false;
+ wtb_zone.draw_emboss = false;
+
+ wcol_zone = *wcol;
+ copy_v3_v3_char(wcol_zone.item, wcol->text);
+ if (state & UI_STATE_ACTIVE_LEFT) {
+ widget_active_color(wcol_zone.inner);
+ }
+
+ rect_zone = *rect;
+ rect_zone.xmax = rect->xmin + handle_width + U.pixelsize;
+ roundboxalign_zone = roundboxalign & ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
+ round_box_edges(&wtb_zone, roundboxalign_zone, &rect_zone, rad);
+
+ shape_preset_init_number_arrows(&wtb_zone.tria1, &rect_zone, 0.6f, 'l');
+ widgetbase_draw(&wtb_zone, &wcol_zone);
+
+ /* right arrow zone */
+ widget_init(&wtb_zone);
+ wtb_zone.draw_outline = false;
+ wtb_zone.draw_emboss = false;
+ wtb_zone.tria1.type = ROUNDBOX_TRIA_ARROWS;
+
+ wcol_zone = *wcol;
+ copy_v3_v3_char(wcol_zone.item, wcol->text);
+ if (state & UI_STATE_ACTIVE_RIGHT) {
+ widget_active_color(wcol_zone.inner);
+ }
+
+ rect_zone = *rect;
+ rect_zone.xmin = rect->xmax - handle_width - U.pixelsize;
+ roundboxalign_zone = roundboxalign & ~(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
+ round_box_edges(&wtb_zone, roundboxalign_zone, &rect_zone, rad);
+
+ shape_preset_init_number_arrows(&wtb_zone.tria2, &rect_zone, 0.6f, 'r');
+ widgetbase_draw(&wtb_zone, &wcol_zone);
+
+ /* middle highlight zone */
+ widget_init(&wtb_zone);
+ wtb_zone.draw_outline = false;
+ wtb_zone.draw_emboss = false;
+
+ wcol_zone = *wcol;
+ copy_v3_v3_char(wcol_zone.item, wcol->text);
+ if (!(state & (UI_STATE_ACTIVE_LEFT | UI_STATE_ACTIVE_RIGHT))) {
+ widget_active_color(wcol_zone.inner);
+ }
+
+ rect_zone = *rect;
+ rect_zone.xmin = rect->xmin + handle_width - U.pixelsize;
+ rect_zone.xmax = rect->xmax - handle_width + U.pixelsize;
+ round_box_edges(&wtb_zone, 0, &rect_zone, 0);
+ widgetbase_draw(&wtb_zone, &wcol_zone);
+
+ /* outline */
+ wtb.draw_inner = false;
+ widgetbase_draw(&wtb, wcol);
+ }
+ else {
+ /* inner and outline */
+ widgetbase_draw(&wtb, wcol);
+ }
+
+ if (!(state & UI_STATE_TEXT_INPUT)) {
+ const float textofs = 0.425f * BLI_rcti_size_y(rect);
+
+ /* text space */
+ rect->xmin += textofs;
+ rect->xmax -= textofs;
+ }
}
static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
- widget_numbut_draw(wcol, rect, state, roundboxalign, false);
+ widget_numbut_draw(wcol, rect, state, roundboxalign, false);
}
/**
* Draw number buttons still with triangles when field is not embossed
*/
-static void widget_numbut_embossn(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
+static void widget_numbut_embossn(
+ uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
- widget_numbut_draw(wcol, rect, state, roundboxalign, true);
+ widget_numbut_draw(wcol, rect, state, roundboxalign, true);
}
/* function in use for buttons and for view2d sliders */
void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *slider, int state)
{
- uiWidgetBase wtb;
- int horizontal;
- float rad;
- bool outline = false;
-
- widget_init(&wtb);
-
- /* determine horizontal/vertical */
- horizontal = (BLI_rcti_size_x(rect) > BLI_rcti_size_y(rect));
-
- if (horizontal) {
- rad = wcol->roundness * BLI_rcti_size_y(rect);
- }
- else {
- rad = wcol->roundness * BLI_rcti_size_x(rect);
- }
-
- wtb.uniform_params.shade_dir = (horizontal) ? 1.0f : 0.0;
-
- /* draw back part, colors swapped and shading inverted */
- if (horizontal) {
- SWAP(short, wcol->shadetop, wcol->shadedown);
- }
-
- round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
- widgetbase_draw(&wtb, wcol);
-
- /* slider */
- if ((BLI_rcti_size_x(slider) < 2) || (BLI_rcti_size_y(slider) < 2)) {
- /* pass */
- }
- else {
- SWAP(short, wcol->shadetop, wcol->shadedown);
-
- copy_v4_v4_char(wcol->inner, wcol->item);
-
- if (wcol->shadetop > wcol->shadedown) {
- wcol->shadetop += 20; /* XXX violates themes... */
- }
- else {
- wcol->shadedown += 20;
- }
-
- if (state & UI_SCROLL_PRESSED) {
- wcol->inner[0] = wcol->inner[0] >= 250 ? 255 : wcol->inner[0] + 5;
- wcol->inner[1] = wcol->inner[1] >= 250 ? 255 : wcol->inner[1] + 5;
- wcol->inner[2] = wcol->inner[2] >= 250 ? 255 : wcol->inner[2] + 5;
- }
-
- /* draw */
- wtb.draw_emboss = false; /* only emboss once */
-
- /* exception for progress bar */
- if (state & UI_SCROLL_NO_OUTLINE) {
- SWAP(bool, outline, wtb.draw_outline);
- }
-
- round_box_edges(&wtb, UI_CNR_ALL, slider, rad);
-
- if (state & UI_SCROLL_ARROWS) {
- if (wcol->item[0] > 48) {
- wcol->item[0] -= 48;
- }
- if (wcol->item[1] > 48) {
- wcol->item[1] -= 48;
- }
- if (wcol->item[2] > 48) {
- wcol->item[2] -= 48;
- }
- wcol->item[3] = 255;
-
- if (horizontal) {
- shape_preset_init_scroll_circle(&wtb.tria1, slider, 0.6f, 'l');
- shape_preset_init_scroll_circle(&wtb.tria2, slider, 0.6f, 'r');
- }
- else {
- shape_preset_init_scroll_circle(&wtb.tria1, slider, 0.6f, 'b');
- shape_preset_init_scroll_circle(&wtb.tria2, slider, 0.6f, 't');
- }
- }
- widgetbase_draw(&wtb, wcol);
-
- if (state & UI_SCROLL_NO_OUTLINE) {
- SWAP(bool, outline, wtb.draw_outline);
- }
- }
+ uiWidgetBase wtb;
+ int horizontal;
+ float rad;
+ bool outline = false;
+
+ widget_init(&wtb);
+
+ /* determine horizontal/vertical */
+ horizontal = (BLI_rcti_size_x(rect) > BLI_rcti_size_y(rect));
+
+ if (horizontal) {
+ rad = wcol->roundness * BLI_rcti_size_y(rect);
+ }
+ else {
+ rad = wcol->roundness * BLI_rcti_size_x(rect);
+ }
+
+ wtb.uniform_params.shade_dir = (horizontal) ? 1.0f : 0.0;
+
+ /* draw back part, colors swapped and shading inverted */
+ if (horizontal) {
+ SWAP(short, wcol->shadetop, wcol->shadedown);
+ }
+
+ round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
+ widgetbase_draw(&wtb, wcol);
+
+ /* slider */
+ if ((BLI_rcti_size_x(slider) < 2) || (BLI_rcti_size_y(slider) < 2)) {
+ /* pass */
+ }
+ else {
+ SWAP(short, wcol->shadetop, wcol->shadedown);
+
+ copy_v4_v4_char(wcol->inner, wcol->item);
+
+ if (wcol->shadetop > wcol->shadedown) {
+ wcol->shadetop += 20; /* XXX violates themes... */
+ }
+ else {
+ wcol->shadedown += 20;
+ }
+
+ if (state & UI_SCROLL_PRESSED) {
+ wcol->inner[0] = wcol->inner[0] >= 250 ? 255 : wcol->inner[0] + 5;
+ wcol->inner[1] = wcol->inner[1] >= 250 ? 255 : wcol->inner[1] + 5;
+ wcol->inner[2] = wcol->inner[2] >= 250 ? 255 : wcol->inner[2] + 5;
+ }
+
+ /* draw */
+ wtb.draw_emboss = false; /* only emboss once */
+
+ /* exception for progress bar */
+ if (state & UI_SCROLL_NO_OUTLINE) {
+ SWAP(bool, outline, wtb.draw_outline);
+ }
+
+ round_box_edges(&wtb, UI_CNR_ALL, slider, rad);
+
+ if (state & UI_SCROLL_ARROWS) {
+ if (wcol->item[0] > 48) {
+ wcol->item[0] -= 48;
+ }
+ if (wcol->item[1] > 48) {
+ wcol->item[1] -= 48;
+ }
+ if (wcol->item[2] > 48) {
+ wcol->item[2] -= 48;
+ }
+ wcol->item[3] = 255;
+
+ if (horizontal) {
+ shape_preset_init_scroll_circle(&wtb.tria1, slider, 0.6f, 'l');
+ shape_preset_init_scroll_circle(&wtb.tria2, slider, 0.6f, 'r');
+ }
+ else {
+ shape_preset_init_scroll_circle(&wtb.tria1, slider, 0.6f, 'b');
+ shape_preset_init_scroll_circle(&wtb.tria2, slider, 0.6f, 't');
+ }
+ }
+ widgetbase_draw(&wtb, wcol);
+
+ if (state & UI_SCROLL_NO_OUTLINE) {
+ SWAP(bool, outline, wtb.draw_outline);
+ }
+ }
}
-static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
+static void widget_scroll(
+ uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
{
- rcti rect1;
- double value;
- float fac, size, min;
- int horizontal;
-
- /* calculate slider part */
- value = ui_but_value_get(but);
-
- size = (but->softmax + but->a1 - but->softmin);
- size = max_ff(size, 2.0f);
-
- /* position */
- rect1 = *rect;
-
- /* determine horizontal/vertical */
- horizontal = (BLI_rcti_size_x(rect) > BLI_rcti_size_y(rect));
-
- if (horizontal) {
- fac = BLI_rcti_size_x(rect) / size;
- rect1.xmin = rect1.xmin + ceilf(fac * ((float)value - but->softmin));
- rect1.xmax = rect1.xmin + ceilf(fac * (but->a1 - but->softmin));
-
- /* ensure minimium size */
- min = BLI_rcti_size_y(rect);
-
- if (BLI_rcti_size_x(&rect1) < min) {
- rect1.xmax = rect1.xmin + min;
-
- if (rect1.xmax > rect->xmax) {
- rect1.xmax = rect->xmax;
- rect1.xmin = max_ii(rect1.xmax - min, rect->xmin);
- }
- }
- }
- else {
- fac = BLI_rcti_size_y(rect) / size;
- rect1.ymax = rect1.ymax - ceilf(fac * ((float)value - but->softmin));
- rect1.ymin = rect1.ymax - ceilf(fac * (but->a1 - but->softmin));
-
- /* ensure minimium size */
- min = BLI_rcti_size_x(rect);
-
- if (BLI_rcti_size_y(&rect1) < min) {
- rect1.ymax = rect1.ymin + min;
-
- if (rect1.ymax > rect->ymax) {
- rect1.ymax = rect->ymax;
- rect1.ymin = max_ii(rect1.ymax - min, rect->ymin);
- }
- }
- }
-
- if (state & UI_SELECT) {
- state = UI_SCROLL_PRESSED;
- }
- else {
- state = 0;
- }
- UI_draw_widget_scroll(wcol, rect, &rect1, state);
+ rcti rect1;
+ double value;
+ float fac, size, min;
+ int horizontal;
+
+ /* calculate slider part */
+ value = ui_but_value_get(but);
+
+ size = (but->softmax + but->a1 - but->softmin);
+ size = max_ff(size, 2.0f);
+
+ /* position */
+ rect1 = *rect;
+
+ /* determine horizontal/vertical */
+ horizontal = (BLI_rcti_size_x(rect) > BLI_rcti_size_y(rect));
+
+ if (horizontal) {
+ fac = BLI_rcti_size_x(rect) / size;
+ rect1.xmin = rect1.xmin + ceilf(fac * ((float)value - but->softmin));
+ rect1.xmax = rect1.xmin + ceilf(fac * (but->a1 - but->softmin));
+
+ /* ensure minimium size */
+ min = BLI_rcti_size_y(rect);
+
+ if (BLI_rcti_size_x(&rect1) < min) {
+ rect1.xmax = rect1.xmin + min;
+
+ if (rect1.xmax > rect->xmax) {
+ rect1.xmax = rect->xmax;
+ rect1.xmin = max_ii(rect1.xmax - min, rect->xmin);
+ }
+ }
+ }
+ else {
+ fac = BLI_rcti_size_y(rect) / size;
+ rect1.ymax = rect1.ymax - ceilf(fac * ((float)value - but->softmin));
+ rect1.ymin = rect1.ymax - ceilf(fac * (but->a1 - but->softmin));
+
+ /* ensure minimium size */
+ min = BLI_rcti_size_x(rect);
+
+ if (BLI_rcti_size_y(&rect1) < min) {
+ rect1.ymax = rect1.ymin + min;
+
+ if (rect1.ymax > rect->ymax) {
+ rect1.ymax = rect->ymax;
+ rect1.ymin = max_ii(rect1.ymax - min, rect->ymin);
+ }
+ }
+ }
+
+ if (state & UI_SELECT) {
+ state = UI_SCROLL_PRESSED;
+ }
+ else {
+ state = 0;
+ }
+ UI_draw_widget_scroll(wcol, rect, &rect1, state);
}
-static void widget_progressbar(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
+static void widget_progressbar(
+ uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
{
- uiWidgetBase wtb, wtb_bar;
- rcti rect_prog = *rect, rect_bar = *rect;
+ uiWidgetBase wtb, wtb_bar;
+ rcti rect_prog = *rect, rect_bar = *rect;
- widget_init(&wtb);
- widget_init(&wtb_bar);
+ widget_init(&wtb);
+ widget_init(&wtb_bar);
- /* round corners */
- float value = but->a1;
- float offs = wcol->roundness * BLI_rcti_size_y(&rect_prog);
- float w = value * BLI_rcti_size_x(&rect_prog);
+ /* round corners */
+ float value = but->a1;
+ float offs = wcol->roundness * BLI_rcti_size_y(&rect_prog);
+ float w = value * BLI_rcti_size_x(&rect_prog);
- /* ensure minimium size */
- w = MAX2(w, offs);
+ /* ensure minimium size */
+ w = MAX2(w, offs);
- rect_bar.xmax = rect_bar.xmin + w;
+ rect_bar.xmax = rect_bar.xmin + w;
- round_box_edges(&wtb, roundboxalign, &rect_prog, offs);
- round_box_edges(&wtb_bar, roundboxalign, &rect_bar, offs);
+ round_box_edges(&wtb, roundboxalign, &rect_prog, offs);
+ round_box_edges(&wtb_bar, roundboxalign, &rect_bar, offs);
- wtb.draw_outline = true;
- widgetbase_draw(&wtb, wcol);
+ wtb.draw_outline = true;
+ widgetbase_draw(&wtb, wcol);
- /* "slider" bar color */
- copy_v3_v3_char(wcol->inner, wcol->item);
- widgetbase_draw(&wtb_bar, wcol);
+ /* "slider" bar color */
+ copy_v3_v3_char(wcol->inner, wcol->item);
+ widgetbase_draw(&wtb_bar, wcol);
- /* raise text a bit */
- rect->xmin += (BLI_rcti_size_x(&rect_prog) / 2);
- rect->xmax += (BLI_rcti_size_x(&rect_prog) / 2);
+ /* raise text a bit */
+ rect->xmin += (BLI_rcti_size_x(&rect_prog) / 2);
+ rect->xmax += (BLI_rcti_size_x(&rect_prog) / 2);
}
-static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
+static void widget_numslider(
+ uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
- uiWidgetBase wtb, wtb1;
- rcti rect1;
- float offs, toffs;
- char outline[3];
-
- widget_init(&wtb);
- widget_init(&wtb1);
-
- /* Backdrop first. */
- offs = wcol->roundness * BLI_rcti_size_y(rect);
- toffs = offs * 0.75f;
- round_box_edges(&wtb, roundboxalign, rect, offs);
-
- wtb.draw_outline = false;
- widgetbase_draw(&wtb, wcol);
-
- /* Draw slider part only when not in text editing. */
- if (!(state & UI_STATE_TEXT_INPUT)) {
- int roundboxalign_slider = roundboxalign;
-
- copy_v3_v3_char(outline, wcol->outline);
- copy_v3_v3_char(wcol->outline, wcol->item);
- copy_v3_v3_char(wcol->inner, wcol->item);
-
- if (!(state & UI_SELECT)) {
- SWAP(short, wcol->shadetop, wcol->shadedown);
- }
-
- rect1 = *rect;
- float factor, factor_ui;
- float factor_discard = 1.0f; /* No discard. */
- float value = (float)ui_but_value_get(but);
-
- if (but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PERCENTAGE)) {
- factor = value / but->softmax;
- }
- else {
- factor = (value - but->softmin) / (but->softmax - but->softmin);
- }
-
- float width = (float)BLI_rcti_size_x(rect);
- factor_ui = factor * width;
-
- if (factor_ui <= offs) {
- /* Left part only. */
- roundboxalign_slider &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
- rect1.xmax = rect1.xmin + offs;
- factor_discard = factor_ui / offs;
- }
- else if (factor_ui <= width - offs) {
- /* Left part + middle part. */
- roundboxalign_slider &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
- rect1.xmax = rect1.xmin + factor_ui;
- }
- else {
- /* Left part + middle part + right part. */
- factor_discard = factor;
- }
-
- round_box_edges(&wtb1, roundboxalign_slider, &rect1, offs);
- wtb1.draw_outline = false;
- widgetbase_set_uniform_discard_factor(&wtb1, factor_discard);
- widgetbase_draw(&wtb1, wcol);
-
- copy_v3_v3_char(wcol->outline, outline);
-
- if (!(state & UI_SELECT)) {
- SWAP(short, wcol->shadetop, wcol->shadedown);
- }
- }
-
- /* Outline. */
- wtb.draw_outline = true;
- wtb.draw_inner = false;
- widgetbase_draw(&wtb, wcol);
-
- /* Add space at either side of the button so text aligns with numbuttons
- * (which have arrow icons). */
- if (!(state & UI_STATE_TEXT_INPUT)) {
- rect->xmax -= toffs;
- rect->xmin += toffs;
- }
+ uiWidgetBase wtb, wtb1;
+ rcti rect1;
+ float offs, toffs;
+ char outline[3];
+
+ widget_init(&wtb);
+ widget_init(&wtb1);
+
+ /* Backdrop first. */
+ offs = wcol->roundness * BLI_rcti_size_y(rect);
+ toffs = offs * 0.75f;
+ round_box_edges(&wtb, roundboxalign, rect, offs);
+
+ wtb.draw_outline = false;
+ widgetbase_draw(&wtb, wcol);
+
+ /* Draw slider part only when not in text editing. */
+ if (!(state & UI_STATE_TEXT_INPUT)) {
+ int roundboxalign_slider = roundboxalign;
+
+ copy_v3_v3_char(outline, wcol->outline);
+ copy_v3_v3_char(wcol->outline, wcol->item);
+ copy_v3_v3_char(wcol->inner, wcol->item);
+
+ if (!(state & UI_SELECT)) {
+ SWAP(short, wcol->shadetop, wcol->shadedown);
+ }
+
+ rect1 = *rect;
+ float factor, factor_ui;
+ float factor_discard = 1.0f; /* No discard. */
+ float value = (float)ui_but_value_get(but);
+
+ if (but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PERCENTAGE)) {
+ factor = value / but->softmax;
+ }
+ else {
+ factor = (value - but->softmin) / (but->softmax - but->softmin);
+ }
+
+ float width = (float)BLI_rcti_size_x(rect);
+ factor_ui = factor * width;
+
+ if (factor_ui <= offs) {
+ /* Left part only. */
+ roundboxalign_slider &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
+ rect1.xmax = rect1.xmin + offs;
+ factor_discard = factor_ui / offs;
+ }
+ else if (factor_ui <= width - offs) {
+ /* Left part + middle part. */
+ roundboxalign_slider &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
+ rect1.xmax = rect1.xmin + factor_ui;
+ }
+ else {
+ /* Left part + middle part + right part. */
+ factor_discard = factor;
+ }
+
+ round_box_edges(&wtb1, roundboxalign_slider, &rect1, offs);
+ wtb1.draw_outline = false;
+ widgetbase_set_uniform_discard_factor(&wtb1, factor_discard);
+ widgetbase_draw(&wtb1, wcol);
+
+ copy_v3_v3_char(wcol->outline, outline);
+
+ if (!(state & UI_SELECT)) {
+ SWAP(short, wcol->shadetop, wcol->shadedown);
+ }
+ }
+
+ /* Outline. */
+ wtb.draw_outline = true;
+ wtb.draw_inner = false;
+ widgetbase_draw(&wtb, wcol);
+
+ /* Add space at either side of the button so text aligns with numbuttons
+ * (which have arrow icons). */
+ if (!(state & UI_STATE_TEXT_INPUT)) {
+ rect->xmax -= toffs;
+ rect->xmin += toffs;
+ }
}
/* I think 3 is sufficient border to indicate keyed status */
#define SWATCH_KEYED_BORDER 3
-static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
+static void widget_swatch(
+ uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
- uiWidgetBase wtb;
- float rad, col[4];
-
- col[3] = 1.0f;
-
- if (but->rnaprop) {
- BLI_assert(but->rnaindex == -1);
-
- if (RNA_property_array_length(&but->rnapoin, but->rnaprop) == 4) {
- col[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
- }
- }
-
- widget_init(&wtb);
-
- rad = wcol->roundness * U.widget_unit;
- round_box_edges(&wtb, roundboxalign, rect, rad);
-
- ui_but_v3_get(but, col);
-
- if ((state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_OVERRIDEN | UI_BUT_REDALERT)) ||
- (but->drawflag & UI_BUT_ANIMATED_CHANGED))
- {
- /* draw based on state - color for keyed etc */
- widgetbase_draw(&wtb, wcol);
-
- /* inset to draw swatch color */
- rect->xmin += SWATCH_KEYED_BORDER;
- rect->xmax -= SWATCH_KEYED_BORDER;
- rect->ymin += SWATCH_KEYED_BORDER;
- rect->ymax -= SWATCH_KEYED_BORDER;
-
- round_box_edges(&wtb, roundboxalign, rect, rad);
- }
-
- if (!ui_but_is_color_gamma(but)) {
- ui_block_cm_to_display_space_v3(but->block, col);
- }
-
- rgba_float_to_uchar((uchar *)wcol->inner, col);
- const bool show_alpha_checkers = (wcol->inner[3] < 255);
-
- wcol->shaded = 0;
-
- if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
- /* Now we reduce alpha of the inner color (i.e. the color shown)
- * so that this setting can look grayed out, while retaining
- * the checkboard (for transparent values). This is needed
- * here as the effects of ui_widget_color_disabled() are overwritten.
- */
- wcol->inner[3] /= 2;
- }
-
- widgetbase_draw_ex(&wtb, wcol, show_alpha_checkers);
- if (but->a1 == UI_PALETTE_COLOR && ((Palette *)but->rnapoin.id.data)->active_color == (int)but->a2) {
- float width = rect->xmax - rect->xmin;
- float height = rect->ymax - rect->ymin;
- /* find color luminance and change it slightly */
- float bw = rgb_to_grayscale(col);
-
- bw += (bw < 0.5f) ? 0.5f : -0.5f;
-
- /* We are drawing on top of widget bases. Flush cache. */
- GPU_blend(true);
- UI_widgetbase_draw_cache_flush();
- GPU_blend(false);
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- immUniformColor3f(bw, bw, bw);
- immBegin(GPU_PRIM_TRIS, 3);
- immVertex2f(pos, rect->xmin + 0.1f * width, rect->ymin + 0.9f * height);
- immVertex2f(pos, rect->xmin + 0.1f * width, rect->ymin + 0.5f * height);
- immVertex2f(pos, rect->xmin + 0.5f * width, rect->ymin + 0.9f * height);
- immEnd();
-
- immUnbindProgram();
- }
+ uiWidgetBase wtb;
+ float rad, col[4];
+
+ col[3] = 1.0f;
+
+ if (but->rnaprop) {
+ BLI_assert(but->rnaindex == -1);
+
+ if (RNA_property_array_length(&but->rnapoin, but->rnaprop) == 4) {
+ col[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
+ }
+ }
+
+ widget_init(&wtb);
+
+ rad = wcol->roundness * U.widget_unit;
+ round_box_edges(&wtb, roundboxalign, rect, rad);
+
+ ui_but_v3_get(but, col);
+
+ if ((state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_OVERRIDEN |
+ UI_BUT_REDALERT)) ||
+ (but->drawflag & UI_BUT_ANIMATED_CHANGED)) {
+ /* draw based on state - color for keyed etc */
+ widgetbase_draw(&wtb, wcol);
+
+ /* inset to draw swatch color */
+ rect->xmin += SWATCH_KEYED_BORDER;
+ rect->xmax -= SWATCH_KEYED_BORDER;
+ rect->ymin += SWATCH_KEYED_BORDER;
+ rect->ymax -= SWATCH_KEYED_BORDER;
+
+ round_box_edges(&wtb, roundboxalign, rect, rad);
+ }
+
+ if (!ui_but_is_color_gamma(but)) {
+ ui_block_cm_to_display_space_v3(but->block, col);
+ }
+
+ rgba_float_to_uchar((uchar *)wcol->inner, col);
+ const bool show_alpha_checkers = (wcol->inner[3] < 255);
+
+ wcol->shaded = 0;
+
+ if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
+ /* Now we reduce alpha of the inner color (i.e. the color shown)
+ * so that this setting can look grayed out, while retaining
+ * the checkboard (for transparent values). This is needed
+ * here as the effects of ui_widget_color_disabled() are overwritten.
+ */
+ wcol->inner[3] /= 2;
+ }
+
+ widgetbase_draw_ex(&wtb, wcol, show_alpha_checkers);
+ if (but->a1 == UI_PALETTE_COLOR &&
+ ((Palette *)but->rnapoin.id.data)->active_color == (int)but->a2) {
+ float width = rect->xmax - rect->xmin;
+ float height = rect->ymax - rect->ymin;
+ /* find color luminance and change it slightly */
+ float bw = rgb_to_grayscale(col);
+
+ bw += (bw < 0.5f) ? 0.5f : -0.5f;
+
+ /* We are drawing on top of widget bases. Flush cache. */
+ GPU_blend(true);
+ UI_widgetbase_draw_cache_flush();
+ GPU_blend(false);
+
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3f(bw, bw, bw);
+ immBegin(GPU_PRIM_TRIS, 3);
+ immVertex2f(pos, rect->xmin + 0.1f * width, rect->ymin + 0.9f * height);
+ immVertex2f(pos, rect->xmin + 0.1f * width, rect->ymin + 0.5f * height);
+ immVertex2f(pos, rect->xmin + 0.5f * width, rect->ymin + 0.9f * height);
+ immEnd();
+
+ immUnbindProgram();
+ }
}
-static void widget_unitvec(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
+static void widget_unitvec(
+ uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
{
- ui_draw_but_UNITVEC(but, wcol, rect);
+ ui_draw_but_UNITVEC(but, wcol, rect);
}
-static void widget_icon_has_anim(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
+static void widget_icon_has_anim(
+ uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
- if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) {
- uiWidgetBase wtb;
- float rad;
-
- widget_init(&wtb);
- wtb.draw_outline = false;
-
- rad = wcol->roundness * BLI_rcti_size_y(rect);
- round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
- widgetbase_draw(&wtb, wcol);
- }
- else if (but->type == UI_BTYPE_NUM) {
- /* Draw number buttons still with left/right
- * triangles when field is not embossed */
- widget_numbut_embossn(but, wcol, rect, state, roundboxalign);
- }
+ if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) {
+ uiWidgetBase wtb;
+ float rad;
+
+ widget_init(&wtb);
+ wtb.draw_outline = false;
+
+ rad = wcol->roundness * BLI_rcti_size_y(rect);
+ round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
+ widgetbase_draw(&wtb, wcol);
+ }
+ else if (but->type == UI_BTYPE_NUM) {
+ /* Draw number buttons still with left/right
+ * triangles when field is not embossed */
+ widget_numbut_embossn(but, wcol, rect, state, roundboxalign);
+ }
}
-
static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
- uiWidgetBase wtb;
- float rad;
+ uiWidgetBase wtb;
+ float rad;
- if (state & UI_SELECT) {
- SWAP(short, wcol->shadetop, wcol->shadedown);
- }
+ if (state & UI_SELECT) {
+ SWAP(short, wcol->shadetop, wcol->shadedown);
+ }
- widget_init(&wtb);
+ widget_init(&wtb);
- rad = wcol->roundness * U.widget_unit;
- round_box_edges(&wtb, roundboxalign, rect, rad);
+ rad = wcol->roundness * U.widget_unit;
+ round_box_edges(&wtb, roundboxalign, rect, rad);
- widgetbase_draw(&wtb, wcol);
+ widgetbase_draw(&wtb, wcol);
}
-
static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
{
- uiWidgetBase wtb;
- float rad;
+ uiWidgetBase wtb;
+ float rad;
- widget_init(&wtb);
+ widget_init(&wtb);
- rad = wcol->roundness * U.widget_unit;
- round_box_edges(&wtb, roundboxalign, rect, rad);
+ rad = wcol->roundness * U.widget_unit;
+ round_box_edges(&wtb, roundboxalign, rect, rad);
- /* decoration */
- shape_preset_trias_from_rect_menu(&wtb.tria1, rect);
- /* copy size and center to 2nd tria */
- wtb.tria2 = wtb.tria1;
+ /* decoration */
+ shape_preset_trias_from_rect_menu(&wtb.tria1, rect);
+ /* copy size and center to 2nd tria */
+ wtb.tria2 = wtb.tria1;
- widgetbase_draw(&wtb, wcol);
+ widgetbase_draw(&wtb, wcol);
- /* text space, arrows are about 0.6 height of button */
- rect->xmax -= (6 * BLI_rcti_size_y(rect)) / 10;
+ /* text space, arrows are about 0.6 height of button */
+ rect->xmax -= (6 * BLI_rcti_size_y(rect)) / 10;
}
-static void widget_menuiconbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
+static void widget_menuiconbut(uiWidgetColors *wcol,
+ rcti *rect,
+ int UNUSED(state),
+ int roundboxalign)
{
- uiWidgetBase wtb;
- float rad;
+ uiWidgetBase wtb;
+ float rad;
- widget_init(&wtb);
+ widget_init(&wtb);
- rad = wcol->roundness * U.widget_unit;
- round_box_edges(&wtb, roundboxalign, rect, rad);
+ rad = wcol->roundness * U.widget_unit;
+ round_box_edges(&wtb, roundboxalign, rect, rad);
- /* decoration */
- widgetbase_draw(&wtb, wcol);
+ /* decoration */
+ widgetbase_draw(&wtb, wcol);
}
static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
- float back[4];
- UI_GetThemeColor4fv(TH_BACK, back);
-
- if ((state & UI_ACTIVE) || (back[3] < 1.0f)) {
- uiWidgetBase wtb;
- const float rad = wcol->roundness * U.widget_unit;
-
- if (state & UI_ACTIVE) {
- copy_v4_v4_char(wcol->inner, wcol->inner_sel);
- copy_v3_v3_char(wcol->text, wcol->text_sel);
- copy_v3_v3_char(wcol->outline, wcol->inner);
- }
- else {
- wcol->inner[3] *= 1.0f - back[3];
- wcol->outline[3] = 0.0f;
- }
-
- widget_init(&wtb);
-
- /* half rounded */
- round_box_edges(&wtb, roundboxalign, rect, rad);
-
- widgetbase_draw(&wtb, wcol);
- }
+ float back[4];
+ UI_GetThemeColor4fv(TH_BACK, back);
+
+ if ((state & UI_ACTIVE) || (back[3] < 1.0f)) {
+ uiWidgetBase wtb;
+ const float rad = wcol->roundness * U.widget_unit;
+
+ if (state & UI_ACTIVE) {
+ copy_v4_v4_char(wcol->inner, wcol->inner_sel);
+ copy_v3_v3_char(wcol->text, wcol->text_sel);
+ copy_v3_v3_char(wcol->outline, wcol->inner);
+ }
+ else {
+ wcol->inner[3] *= 1.0f - back[3];
+ wcol->outline[3] = 0.0f;
+ }
+
+ widget_init(&wtb);
+
+ /* half rounded */
+ round_box_edges(&wtb, roundboxalign, rect, rad);
+
+ widgetbase_draw(&wtb, wcol);
+ }
}
-static void widget_menu_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
+static void widget_menu_itembut(uiWidgetColors *wcol,
+ rcti *rect,
+ int UNUSED(state),
+ int UNUSED(roundboxalign))
{
- uiWidgetBase wtb;
+ uiWidgetBase wtb;
- widget_init(&wtb);
+ widget_init(&wtb);
- /* not rounded, no outline */
- wtb.draw_outline = false;
- round_box_edges(&wtb, 0, rect, 0.0f);
+ /* not rounded, no outline */
+ wtb.draw_outline = false;
+ round_box_edges(&wtb, 0, rect, 0.0f);
- widgetbase_draw(&wtb, wcol);
+ widgetbase_draw(&wtb, wcol);
}
-static void widget_menu_radial_itembut(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
+static void widget_menu_radial_itembut(
+ uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
{
- uiWidgetBase wtb;
- float rad;
- float fac = but->block->pie_data.alphafac;
+ uiWidgetBase wtb;
+ float rad;
+ float fac = but->block->pie_data.alphafac;
- widget_init(&wtb);
+ widget_init(&wtb);
- wtb.draw_emboss = false;
+ wtb.draw_emboss = false;
- rad = wcol->roundness * BLI_rcti_size_y(rect);
- round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
+ rad = wcol->roundness * BLI_rcti_size_y(rect);
+ round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
- wcol->inner[3] *= fac;
- wcol->inner_sel[3] *= fac;
- wcol->item[3] *= fac;
- wcol->text[3] *= fac;
- wcol->text_sel[3] *= fac;
- wcol->outline[3] *= fac;
+ wcol->inner[3] *= fac;
+ wcol->inner_sel[3] *= fac;
+ wcol->item[3] *= fac;
+ wcol->text[3] *= fac;
+ wcol->text_sel[3] *= fac;
+ wcol->outline[3] *= fac;
- widgetbase_draw(&wtb, wcol);
+ widgetbase_draw(&wtb, wcol);
}
-static void widget_list_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
+static void widget_list_itembut(uiWidgetColors *wcol,
+ rcti *rect,
+ int UNUSED(state),
+ int UNUSED(roundboxalign))
{
- uiWidgetBase wtb;
- float rad;
+ uiWidgetBase wtb;
+ float rad;
- widget_init(&wtb);
+ widget_init(&wtb);
- /* no outline */
- wtb.draw_outline = false;
- rad = wcol->roundness * U.widget_unit;
- round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
+ /* no outline */
+ wtb.draw_outline = false;
+ rad = wcol->roundness * U.widget_unit;
+ round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
- widgetbase_draw(&wtb, wcol);
+ widgetbase_draw(&wtb, wcol);
}
-static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
+static void widget_optionbut(uiWidgetColors *wcol,
+ rcti *rect,
+ int state,
+ int UNUSED(roundboxalign))
{
- bool text_before_widget = (state & UI_STATE_TEXT_BEFORE_WIDGET);
- uiWidgetBase wtb;
- rcti recttemp = *rect;
- float rad;
- int delta;
-
- widget_init(&wtb);
-
- /* square */
- if (text_before_widget) {
- recttemp.xmin = recttemp.xmax - BLI_rcti_size_y(&recttemp);
- }
- else {
- recttemp.xmax = recttemp.xmin + BLI_rcti_size_y(&recttemp);
- }
-
- /* smaller */
- delta = 1 + BLI_rcti_size_y(&recttemp) / 8;
- recttemp.xmin += delta;
- recttemp.ymin += delta;
- recttemp.xmax -= delta;
- recttemp.ymax -= delta;
-
- rad = wcol->roundness * BLI_rcti_size_y(&recttemp);
- round_box_edges(&wtb, UI_CNR_ALL, &recttemp, rad);
-
- /* decoration */
- if (state & UI_SELECT) {
- shape_preset_trias_from_rect_checkmark(&wtb.tria1, &recttemp);
- }
-
- widgetbase_draw(&wtb, wcol);
-
- /* text space */
- const float offset = BLI_rcti_size_y(rect) * 0.7 + delta;
- if (text_before_widget) {
- rect->xmax -= offset;
- }
- else {
- rect->xmin += offset;
- }
+ bool text_before_widget = (state & UI_STATE_TEXT_BEFORE_WIDGET);
+ uiWidgetBase wtb;
+ rcti recttemp = *rect;
+ float rad;
+ int delta;
+
+ widget_init(&wtb);
+
+ /* square */
+ if (text_before_widget) {
+ recttemp.xmin = recttemp.xmax - BLI_rcti_size_y(&recttemp);
+ }
+ else {
+ recttemp.xmax = recttemp.xmin + BLI_rcti_size_y(&recttemp);
+ }
+
+ /* smaller */
+ delta = 1 + BLI_rcti_size_y(&recttemp) / 8;
+ recttemp.xmin += delta;
+ recttemp.ymin += delta;
+ recttemp.xmax -= delta;
+ recttemp.ymax -= delta;
+
+ rad = wcol->roundness * BLI_rcti_size_y(&recttemp);
+ round_box_edges(&wtb, UI_CNR_ALL, &recttemp, rad);
+
+ /* decoration */
+ if (state & UI_SELECT) {
+ shape_preset_trias_from_rect_checkmark(&wtb.tria1, &recttemp);
+ }
+
+ widgetbase_draw(&wtb, wcol);
+
+ /* text space */
+ const float offset = BLI_rcti_size_y(rect) * 0.7 + delta;
+ if (text_before_widget) {
+ rect->xmax -= offset;
+ }
+ else {
+ rect->xmin += offset;
+ }
}
/* labels use Editor theme colors for text */
static void widget_state_label(uiWidgetType *wt, int state, int drawflag)
{
- if (state & UI_BUT_LIST_ITEM) {
- /* Override default label theme's colors. */
- bTheme *btheme = UI_GetTheme();
- wt->wcol_theme = &btheme->tui.wcol_list_item;
- /* call this for option button */
- widget_state(wt, state, drawflag);
- }
- else {
- /* call this for option button */
- widget_state(wt, state, drawflag);
- if (state & UI_SELECT) {
- UI_GetThemeColor3ubv(TH_TEXT_HI, (uchar *)wt->wcol.text);
- }
- else {
- UI_GetThemeColor3ubv(TH_TEXT, (uchar *)wt->wcol.text);
- }
- }
-
- if (state & UI_BUT_REDALERT) {
- char red[4] = {255, 0, 0};
- widget_state_blend(wt->wcol.text, red, 0.4f);
- }
+ if (state & UI_BUT_LIST_ITEM) {
+ /* Override default label theme's colors. */
+ bTheme *btheme = UI_GetTheme();
+ wt->wcol_theme = &btheme->tui.wcol_list_item;
+ /* call this for option button */
+ widget_state(wt, state, drawflag);
+ }
+ else {
+ /* call this for option button */
+ widget_state(wt, state, drawflag);
+ if (state & UI_SELECT) {
+ UI_GetThemeColor3ubv(TH_TEXT_HI, (uchar *)wt->wcol.text);
+ }
+ else {
+ UI_GetThemeColor3ubv(TH_TEXT, (uchar *)wt->wcol.text);
+ }
+ }
+
+ if (state & UI_BUT_REDALERT) {
+ char red[4] = {255, 0, 0};
+ widget_state_blend(wt->wcol.text, red, 0.4f);
+ }
}
static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
{
- uiWidgetBase wtb;
- float rad;
+ uiWidgetBase wtb;
+ float rad;
- widget_init(&wtb);
+ widget_init(&wtb);
- rad = wcol->roundness * U.widget_unit;
- round_box_edges(&wtb, roundboxalign, rect, rad);
+ rad = wcol->roundness * U.widget_unit;
+ round_box_edges(&wtb, roundboxalign, rect, rad);
- widgetbase_draw(&wtb, wcol);
+ widgetbase_draw(&wtb, wcol);
}
-static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
+static void widget_box(
+ uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
{
- uiWidgetBase wtb;
- float rad;
- char old_col[3];
+ uiWidgetBase wtb;
+ float rad;
+ char old_col[3];
- widget_init(&wtb);
+ widget_init(&wtb);
- copy_v3_v3_char(old_col, wcol->inner);
+ copy_v3_v3_char(old_col, wcol->inner);
- /* abuse but->hsv - if it's non-zero, use this color as the box's background */
- if (but->col[3]) {
- wcol->inner[0] = but->col[0];
- wcol->inner[1] = but->col[1];
- wcol->inner[2] = but->col[2];
- wcol->inner[3] = but->col[3];
- }
+ /* abuse but->hsv - if it's non-zero, use this color as the box's background */
+ if (but->col[3]) {
+ wcol->inner[0] = but->col[0];
+ wcol->inner[1] = but->col[1];
+ wcol->inner[2] = but->col[2];
+ wcol->inner[3] = but->col[3];
+ }
- rad = wcol->roundness * U.widget_unit;
- round_box_edges(&wtb, roundboxalign, rect, rad);
+ rad = wcol->roundness * U.widget_unit;
+ round_box_edges(&wtb, roundboxalign, rect, rad);
- widgetbase_draw(&wtb, wcol);
+ widgetbase_draw(&wtb, wcol);
- copy_v3_v3_char(wcol->inner, old_col);
+ copy_v3_v3_char(wcol->inner, old_col);
}
static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
{
- uiWidgetBase wtb;
- float rad;
+ uiWidgetBase wtb;
+ float rad;
- widget_init(&wtb);
+ widget_init(&wtb);
- rad = wcol->roundness * U.widget_unit;
- round_box_edges(&wtb, roundboxalign, rect, rad);
+ rad = wcol->roundness * U.widget_unit;
+ round_box_edges(&wtb, roundboxalign, rect, rad);
- widgetbase_draw(&wtb, wcol);
+ widgetbase_draw(&wtb, wcol);
}
#if 0
static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
{
- uiWidgetBase wtb;
- const float rad = wcol->roundness * U.widget_unit;
+ uiWidgetBase wtb;
+ const float rad = wcol->roundness * U.widget_unit;
- widget_init(&wtb);
+ widget_init(&wtb);
- /* half rounded */
- round_box_edges(&wtb, roundboxalign, rect, rad);
+ /* half rounded */
+ round_box_edges(&wtb, roundboxalign, rect, rad);
- widgetbase_draw(&wtb, wcol);
+ widgetbase_draw(&wtb, wcol);
}
#endif
static void widget_roundbut_exec(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
- uiWidgetBase wtb;
- const float rad = wcol->roundness * U.widget_unit;
+ uiWidgetBase wtb;
+ const float rad = wcol->roundness * U.widget_unit;
- widget_init(&wtb);
+ widget_init(&wtb);
- if (state & UI_STATE_HOLD_ACTION) {
- /* Show that keeping pressed performs another action (typically a menu). */
- shape_preset_init_hold_action(&wtb.tria1, rect, 0.75f, 'r');
- }
+ if (state & UI_STATE_HOLD_ACTION) {
+ /* Show that keeping pressed performs another action (typically a menu). */
+ shape_preset_init_hold_action(&wtb.tria1, rect, 0.75f, 'r');
+ }
- /* half rounded */
- round_box_edges(&wtb, roundboxalign, rect, rad);
+ /* half rounded */
+ round_box_edges(&wtb, roundboxalign, rect, rad);
- widgetbase_draw(&wtb, wcol);
+ widgetbase_draw(&wtb, wcol);
}
static void widget_tab(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
- const float rad = wcol->roundness * U.widget_unit;
- const bool is_active = (state & UI_SELECT);
+ const float rad = wcol->roundness * U.widget_unit;
+ const bool is_active = (state & UI_SELECT);
-/* Draw shaded outline - Disabled for now,
+ /* Draw shaded outline - Disabled for now,
* seems incorrect and also looks nicer without it imho ;) */
-//#define USE_TAB_SHADED_HIGHLIGHT
+ //#define USE_TAB_SHADED_HIGHLIGHT
- uiWidgetBase wtb;
- uchar theme_col_tab_highlight[3];
+ uiWidgetBase wtb;
+ uchar theme_col_tab_highlight[3];
#ifdef USE_TAB_SHADED_HIGHLIGHT
- /* create outline highlight colors */
- if (is_active) {
- interp_v3_v3v3_uchar(theme_col_tab_highlight, (uchar *)wcol->inner_sel,
- (uchar *)wcol->outline, 0.2f);
- }
- else {
- interp_v3_v3v3_uchar(theme_col_tab_highlight, (uchar *)wcol->inner,
- (uchar *)wcol->outline, 0.12f);
- }
+ /* create outline highlight colors */
+ if (is_active) {
+ interp_v3_v3v3_uchar(
+ theme_col_tab_highlight, (uchar *)wcol->inner_sel, (uchar *)wcol->outline, 0.2f);
+ }
+ else {
+ interp_v3_v3v3_uchar(
+ theme_col_tab_highlight, (uchar *)wcol->inner, (uchar *)wcol->outline, 0.12f);
+ }
#endif
- widget_init(&wtb);
+ widget_init(&wtb);
- /* half rounded */
- round_box_edges(&wtb, roundboxalign, rect, rad);
+ /* half rounded */
+ round_box_edges(&wtb, roundboxalign, rect, rad);
- /* draw inner */
+ /* draw inner */
#ifdef USE_TAB_SHADED_HIGHLIGHT
- wtb.draw_outline = 0;
+ wtb.draw_outline = 0;
#endif
- widgetbase_draw(&wtb, wcol);
+ widgetbase_draw(&wtb, wcol);
- /* We are drawing on top of widget bases. Flush cache. */
- GPU_blend(true);
- UI_widgetbase_draw_cache_flush();
- GPU_blend(false);
+ /* We are drawing on top of widget bases. Flush cache. */
+ GPU_blend(true);
+ UI_widgetbase_draw_cache_flush();
+ GPU_blend(false);
#ifdef USE_TAB_SHADED_HIGHLIGHT
- /* draw outline (3d look) */
- ui_draw_but_TAB_outline(rect, rad, theme_col_tab_highlight, (uchar *)wcol->inner);
+ /* draw outline (3d look) */
+ ui_draw_but_TAB_outline(rect, rad, theme_col_tab_highlight, (uchar *)wcol->inner);
#endif
#ifndef USE_TAB_SHADED_HIGHLIGHT
- UNUSED_VARS(is_active, theme_col_tab_highlight);
+ UNUSED_VARS(is_active, theme_col_tab_highlight);
#endif
}
static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect)
{
- bTheme *btheme = UI_GetTheme();
- uiWidgetColors *wcol = &btheme->tui.wcol_radio;
- uiWidgetBase wtb;
- const float rad = wcol->roundness * U.widget_unit;
- uchar col[4];
+ bTheme *btheme = UI_GetTheme();
+ uiWidgetColors *wcol = &btheme->tui.wcol_radio;
+ uiWidgetBase wtb;
+ const float rad = wcol->roundness * U.widget_unit;
+ uchar col[4];
- /* state copy! */
- wt->wcol = *(wt->wcol_theme);
+ /* state copy! */
+ wt->wcol = *(wt->wcol_theme);
- widget_init(&wtb);
+ widget_init(&wtb);
- if (but->block->drawextra) {
- /* note: drawextra can change rect +1 or -1, to match round errors of existing previews */
- but->block->drawextra(C, but->poin, but->block->drawextra_arg1, but->block->drawextra_arg2, rect);
+ if (but->block->drawextra) {
+ /* note: drawextra can change rect +1 or -1, to match round errors of existing previews */
+ but->block->drawextra(
+ C, but->poin, but->block->drawextra_arg1, but->block->drawextra_arg2, rect);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- /* make mask to draw over image */
- UI_GetThemeColor3ubv(TH_BACK, col);
- immUniformColor3ubv(col);
+ /* make mask to draw over image */
+ UI_GetThemeColor3ubv(TH_BACK, col);
+ immUniformColor3ubv(col);
- round_box__edges(&wtb, UI_CNR_ALL, rect, 0.0f, rad);
- widgetbase_outline(&wtb, pos);
+ round_box__edges(&wtb, UI_CNR_ALL, rect, 0.0f, rad);
+ widgetbase_outline(&wtb, pos);
- immUnbindProgram();
- }
+ immUnbindProgram();
+ }
- /* outline */
- round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
- wtb.draw_outline = true;
- wtb.draw_inner = false;
- widgetbase_draw(&wtb, &wt->wcol);
+ /* outline */
+ round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
+ wtb.draw_outline = true;
+ wtb.draw_inner = false;
+ widgetbase_draw(&wtb, &wt->wcol);
}
static uiWidgetType *widget_type(uiWidgetTypeEnum type)
{
- bTheme *btheme = UI_GetTheme();
- static uiWidgetType wt;
-
- /* defaults */
- wt.wcol_theme = &btheme->tui.wcol_regular;
- wt.wcol_state = &btheme->tui.wcol_state;
- wt.state = widget_state;
- wt.draw = widget_but;
- wt.custom = NULL;
- wt.text = widget_draw_text_icon;
-
- switch (type) {
- case UI_WTYPE_REGULAR:
- break;
-
- case UI_WTYPE_LABEL:
- wt.draw = NULL;
- wt.state = widget_state_label;
- break;
-
- case UI_WTYPE_TOGGLE:
- wt.wcol_theme = &btheme->tui.wcol_toggle;
- break;
-
- case UI_WTYPE_CHECKBOX:
- wt.wcol_theme = &btheme->tui.wcol_option;
- wt.draw = widget_optionbut;
- break;
-
- case UI_WTYPE_RADIO:
- wt.wcol_theme = &btheme->tui.wcol_radio;
- wt.draw = widget_radiobut;
- break;
-
- case UI_WTYPE_NUMBER:
- wt.wcol_theme = &btheme->tui.wcol_num;
- wt.draw = widget_numbut;
- break;
-
- case UI_WTYPE_SLIDER:
- wt.wcol_theme = &btheme->tui.wcol_numslider;
- wt.custom = widget_numslider;
- wt.state = widget_state_numslider;
- break;
-
- case UI_WTYPE_EXEC:
- wt.wcol_theme = &btheme->tui.wcol_tool;
- wt.draw = widget_roundbut_exec;
- break;
-
- case UI_WTYPE_TOOLBAR_ITEM:
- wt.wcol_theme = &btheme->tui.wcol_toolbar_item;
- wt.draw = widget_roundbut_exec;
- break;
-
- case UI_WTYPE_TAB:
- wt.wcol_theme = &btheme->tui.wcol_tab;
- wt.draw = widget_tab;
- break;
-
- case UI_WTYPE_TOOLTIP:
- wt.wcol_theme = &btheme->tui.wcol_tooltip;
- wt.draw = widget_menu_back;
- break;
-
-
- /* strings */
- case UI_WTYPE_NAME:
- wt.wcol_theme = &btheme->tui.wcol_text;
- wt.draw = widget_textbut;
- break;
-
- case UI_WTYPE_NAME_LINK:
- break;
-
- case UI_WTYPE_POINTER_LINK:
- break;
-
- case UI_WTYPE_FILENAME:
- break;
-
-
- /* start menus */
- case UI_WTYPE_MENU_RADIO:
- wt.wcol_theme = &btheme->tui.wcol_menu;
- wt.draw = widget_menubut;
- break;
-
- case UI_WTYPE_MENU_ICON_RADIO:
- case UI_WTYPE_MENU_NODE_LINK:
- wt.wcol_theme = &btheme->tui.wcol_menu;
- wt.draw = widget_menuiconbut;
- break;
-
- case UI_WTYPE_MENU_POINTER_LINK:
- wt.wcol_theme = &btheme->tui.wcol_menu;
- wt.draw = widget_menubut;
- break;
-
- case UI_WTYPE_PULLDOWN:
- wt.wcol_theme = &btheme->tui.wcol_pulldown;
- wt.draw = widget_pulldownbut;
- wt.state = widget_state_pulldown;
- break;
-
- /* in menus */
- case UI_WTYPE_MENU_ITEM:
- wt.wcol_theme = &btheme->tui.wcol_menu_item;
- wt.draw = widget_menu_itembut;
- wt.state = widget_state_menu_item;
- break;
-
- case UI_WTYPE_MENU_BACK:
- wt.wcol_theme = &btheme->tui.wcol_menu_back;
- wt.draw = widget_menu_back;
- break;
-
- /* specials */
- case UI_WTYPE_ICON:
- wt.custom = widget_icon_has_anim;
- break;
-
- case UI_WTYPE_ICON_LABEL:
- /* behave like regular labels (this is simply a label with an icon) */
- wt.state = widget_state_label;
- wt.custom = widget_icon_has_anim;
- break;
-
- case UI_WTYPE_SWATCH:
- wt.custom = widget_swatch;
- break;
-
- case UI_WTYPE_BOX:
- wt.custom = widget_box;
- wt.wcol_theme = &btheme->tui.wcol_box;
- break;
-
- case UI_WTYPE_RGB_PICKER:
- break;
-
- case UI_WTYPE_UNITVEC:
- wt.custom = widget_unitvec;
- break;
-
- case UI_WTYPE_SCROLL:
- wt.wcol_theme = &btheme->tui.wcol_scroll;
- wt.state = widget_state_nothing;
- wt.custom = widget_scroll;
- break;
-
- case UI_WTYPE_LISTITEM:
- wt.wcol_theme = &btheme->tui.wcol_list_item;
- wt.draw = widget_list_itembut;
- break;
-
- case UI_WTYPE_PROGRESSBAR:
- wt.wcol_theme = &btheme->tui.wcol_progress;
- wt.custom = widget_progressbar;
- break;
-
- case UI_WTYPE_MENU_ITEM_RADIAL:
- wt.wcol_theme = &btheme->tui.wcol_pie_menu;
- wt.custom = widget_menu_radial_itembut;
- wt.state = widget_state_pie_menu_item;
- break;
- }
-
- return &wt;
+ bTheme *btheme = UI_GetTheme();
+ static uiWidgetType wt;
+
+ /* defaults */
+ wt.wcol_theme = &btheme->tui.wcol_regular;
+ wt.wcol_state = &btheme->tui.wcol_state;
+ wt.state = widget_state;
+ wt.draw = widget_but;
+ wt.custom = NULL;
+ wt.text = widget_draw_text_icon;
+
+ switch (type) {
+ case UI_WTYPE_REGULAR:
+ break;
+
+ case UI_WTYPE_LABEL:
+ wt.draw = NULL;
+ wt.state = widget_state_label;
+ break;
+
+ case UI_WTYPE_TOGGLE:
+ wt.wcol_theme = &btheme->tui.wcol_toggle;
+ break;
+
+ case UI_WTYPE_CHECKBOX:
+ wt.wcol_theme = &btheme->tui.wcol_option;
+ wt.draw = widget_optionbut;
+ break;
+
+ case UI_WTYPE_RADIO:
+ wt.wcol_theme = &btheme->tui.wcol_radio;
+ wt.draw = widget_radiobut;
+ break;
+
+ case UI_WTYPE_NUMBER:
+ wt.wcol_theme = &btheme->tui.wcol_num;
+ wt.draw = widget_numbut;
+ break;
+
+ case UI_WTYPE_SLIDER:
+ wt.wcol_theme = &btheme->tui.wcol_numslider;
+ wt.custom = widget_numslider;
+ wt.state = widget_state_numslider;
+ break;
+
+ case UI_WTYPE_EXEC:
+ wt.wcol_theme = &btheme->tui.wcol_tool;
+ wt.draw = widget_roundbut_exec;
+ break;
+
+ case UI_WTYPE_TOOLBAR_ITEM:
+ wt.wcol_theme = &btheme->tui.wcol_toolbar_item;
+ wt.draw = widget_roundbut_exec;
+ break;
+
+ case UI_WTYPE_TAB:
+ wt.wcol_theme = &btheme->tui.wcol_tab;
+ wt.draw = widget_tab;
+ break;
+
+ case UI_WTYPE_TOOLTIP:
+ wt.wcol_theme = &btheme->tui.wcol_tooltip;
+ wt.draw = widget_menu_back;
+ break;
+
+ /* strings */
+ case UI_WTYPE_NAME:
+ wt.wcol_theme = &btheme->tui.wcol_text;
+ wt.draw = widget_textbut;
+ break;
+
+ case UI_WTYPE_NAME_LINK:
+ break;
+
+ case UI_WTYPE_POINTER_LINK:
+ break;
+
+ case UI_WTYPE_FILENAME:
+ break;
+
+ /* start menus */
+ case UI_WTYPE_MENU_RADIO:
+ wt.wcol_theme = &btheme->tui.wcol_menu;
+ wt.draw = widget_menubut;
+ break;
+
+ case UI_WTYPE_MENU_ICON_RADIO:
+ case UI_WTYPE_MENU_NODE_LINK:
+ wt.wcol_theme = &btheme->tui.wcol_menu;
+ wt.draw = widget_menuiconbut;
+ break;
+
+ case UI_WTYPE_MENU_POINTER_LINK:
+ wt.wcol_theme = &btheme->tui.wcol_menu;
+ wt.draw = widget_menubut;
+ break;
+
+ case UI_WTYPE_PULLDOWN:
+ wt.wcol_theme = &btheme->tui.wcol_pulldown;
+ wt.draw = widget_pulldownbut;
+ wt.state = widget_state_pulldown;
+ break;
+
+ /* in menus */
+ case UI_WTYPE_MENU_ITEM:
+ wt.wcol_theme = &btheme->tui.wcol_menu_item;
+ wt.draw = widget_menu_itembut;
+ wt.state = widget_state_menu_item;
+ break;
+
+ case UI_WTYPE_MENU_BACK:
+ wt.wcol_theme = &btheme->tui.wcol_menu_back;
+ wt.draw = widget_menu_back;
+ break;
+
+ /* specials */
+ case UI_WTYPE_ICON:
+ wt.custom = widget_icon_has_anim;
+ break;
+
+ case UI_WTYPE_ICON_LABEL:
+ /* behave like regular labels (this is simply a label with an icon) */
+ wt.state = widget_state_label;
+ wt.custom = widget_icon_has_anim;
+ break;
+
+ case UI_WTYPE_SWATCH:
+ wt.custom = widget_swatch;
+ break;
+
+ case UI_WTYPE_BOX:
+ wt.custom = widget_box;
+ wt.wcol_theme = &btheme->tui.wcol_box;
+ break;
+
+ case UI_WTYPE_RGB_PICKER:
+ break;
+
+ case UI_WTYPE_UNITVEC:
+ wt.custom = widget_unitvec;
+ break;
+
+ case UI_WTYPE_SCROLL:
+ wt.wcol_theme = &btheme->tui.wcol_scroll;
+ wt.state = widget_state_nothing;
+ wt.custom = widget_scroll;
+ break;
+
+ case UI_WTYPE_LISTITEM:
+ wt.wcol_theme = &btheme->tui.wcol_list_item;
+ wt.draw = widget_list_itembut;
+ break;
+
+ case UI_WTYPE_PROGRESSBAR:
+ wt.wcol_theme = &btheme->tui.wcol_progress;
+ wt.custom = widget_progressbar;
+ break;
+
+ case UI_WTYPE_MENU_ITEM_RADIAL:
+ wt.wcol_theme = &btheme->tui.wcol_pie_menu;
+ wt.custom = widget_menu_radial_itembut;
+ wt.state = widget_state_pie_menu_item;
+ break;
+ }
+
+ return &wt;
}
-
static int widget_roundbox_set(uiBut *but, rcti *rect)
{
- int roundbox = UI_CNR_ALL;
-
- /* alignment */
- if ((but->drawflag & UI_BUT_ALIGN) && but->type != UI_BTYPE_PULLDOWN) {
-
- /* ui_popup_block_position has this correction too, keep in sync */
- if (but->drawflag & (UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_STITCH_TOP)) {
- rect->ymax += U.pixelsize;
- }
- if (but->drawflag & (UI_BUT_ALIGN_LEFT | UI_BUT_ALIGN_STITCH_LEFT)) {
- rect->xmin -= U.pixelsize;
- }
-
- switch (but->drawflag & UI_BUT_ALIGN) {
- case UI_BUT_ALIGN_TOP:
- roundbox = UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT;
- break;
- case UI_BUT_ALIGN_DOWN:
- roundbox = UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT;
- break;
- case UI_BUT_ALIGN_LEFT:
- roundbox = UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT;
- break;
- case UI_BUT_ALIGN_RIGHT:
- roundbox = UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT;
- break;
- case UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_RIGHT:
- roundbox = UI_CNR_TOP_LEFT;
- break;
- case UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_LEFT:
- roundbox = UI_CNR_TOP_RIGHT;
- break;
- case UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_RIGHT:
- roundbox = UI_CNR_BOTTOM_LEFT;
- break;
- case UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_LEFT:
- roundbox = UI_CNR_BOTTOM_RIGHT;
- break;
- default:
- roundbox = 0;
- break;
- }
- }
-
- /* align with open menu */
- if (but->active && (but->type != UI_BTYPE_POPOVER)) {
- int direction = ui_but_menu_direction(but);
-
- if (direction == UI_DIR_UP) { roundbox &= ~(UI_CNR_TOP_RIGHT | UI_CNR_TOP_LEFT); }
- else if (direction == UI_DIR_DOWN) { roundbox &= ~(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT); }
- else if (direction == UI_DIR_LEFT) { roundbox &= ~(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT); }
- else if (direction == UI_DIR_RIGHT) { roundbox &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT); }
- }
-
- return roundbox;
+ int roundbox = UI_CNR_ALL;
+
+ /* alignment */
+ if ((but->drawflag & UI_BUT_ALIGN) && but->type != UI_BTYPE_PULLDOWN) {
+
+ /* ui_popup_block_position has this correction too, keep in sync */
+ if (but->drawflag & (UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_STITCH_TOP)) {
+ rect->ymax += U.pixelsize;
+ }
+ if (but->drawflag & (UI_BUT_ALIGN_LEFT | UI_BUT_ALIGN_STITCH_LEFT)) {
+ rect->xmin -= U.pixelsize;
+ }
+
+ switch (but->drawflag & UI_BUT_ALIGN) {
+ case UI_BUT_ALIGN_TOP:
+ roundbox = UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT;
+ break;
+ case UI_BUT_ALIGN_DOWN:
+ roundbox = UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT;
+ break;
+ case UI_BUT_ALIGN_LEFT:
+ roundbox = UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT;
+ break;
+ case UI_BUT_ALIGN_RIGHT:
+ roundbox = UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT;
+ break;
+ case UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_RIGHT:
+ roundbox = UI_CNR_TOP_LEFT;
+ break;
+ case UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_LEFT:
+ roundbox = UI_CNR_TOP_RIGHT;
+ break;
+ case UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_RIGHT:
+ roundbox = UI_CNR_BOTTOM_LEFT;
+ break;
+ case UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_LEFT:
+ roundbox = UI_CNR_BOTTOM_RIGHT;
+ break;
+ default:
+ roundbox = 0;
+ break;
+ }
+ }
+
+ /* align with open menu */
+ if (but->active && (but->type != UI_BTYPE_POPOVER)) {
+ int direction = ui_but_menu_direction(but);
+
+ if (direction == UI_DIR_UP) {
+ roundbox &= ~(UI_CNR_TOP_RIGHT | UI_CNR_TOP_LEFT);
+ }
+ else if (direction == UI_DIR_DOWN) {
+ roundbox &= ~(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
+ }
+ else if (direction == UI_DIR_LEFT) {
+ roundbox &= ~(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
+ }
+ else if (direction == UI_DIR_RIGHT) {
+ roundbox &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
+ }
+ }
+
+ return roundbox;
}
/* -------------------------------------------------------------------- */
@@ -4261,749 +4437,812 @@ 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)
{
- bTheme *btheme = UI_GetTheme();
- const ThemeUI *tui = &btheme->tui;
- const uiFontStyle *fstyle = &style->widget;
- uiWidgetType *wt = NULL;
+ bTheme *btheme = UI_GetTheme();
+ const ThemeUI *tui = &btheme->tui;
+ const uiFontStyle *fstyle = &style->widget;
+ uiWidgetType *wt = NULL;
#ifdef USE_UI_POPOVER_ONCE
- const rcti rect_orig = *rect;
+ const rcti rect_orig = *rect;
#endif
- /* handle menus separately */
- if (but->dt == UI_EMBOSS_PULLDOWN) {
- switch (but->type) {
- case UI_BTYPE_LABEL:
- widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
- break;
- case UI_BTYPE_SEPR_LINE:
- ui_draw_separator(rect, &tui->wcol_menu_item);
- break;
- default:
- wt = widget_type(UI_WTYPE_MENU_ITEM);
- break;
- }
- }
- else if (but->dt == UI_EMBOSS_NONE) {
- /* "nothing" */
- switch (but->type) {
- case UI_BTYPE_LABEL:
- wt = widget_type(UI_WTYPE_ICON_LABEL);
- break;
- default:
- wt = widget_type(UI_WTYPE_ICON);
- break;
- }
- }
- else if (but->dt == UI_EMBOSS_RADIAL) {
- wt = widget_type(UI_WTYPE_MENU_ITEM_RADIAL);
- }
- else {
- BLI_assert(but->dt == UI_EMBOSS);
-
- switch (but->type) {
- case UI_BTYPE_LABEL:
- wt = widget_type(UI_WTYPE_LABEL);
- fstyle = &style->widgetlabel;
- if (but->drawflag & UI_BUT_BOX_ITEM) {
- wt->wcol_theme = &tui->wcol_box;
- wt->state = widget_state;
- }
- else if (but->block->theme_style == UI_BLOCK_THEME_STYLE_POPUP) {
- wt->wcol_theme = &tui->wcol_menu_back;
- wt->state = widget_state;
- }
- break;
-
- case UI_BTYPE_SEPR:
- case UI_BTYPE_SEPR_LINE:
- case UI_BTYPE_SEPR_SPACER:
- break;
-
- case UI_BTYPE_BUT:
+ /* handle menus separately */
+ if (but->dt == UI_EMBOSS_PULLDOWN) {
+ switch (but->type) {
+ case UI_BTYPE_LABEL:
+ widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
+ break;
+ case UI_BTYPE_SEPR_LINE:
+ ui_draw_separator(rect, &tui->wcol_menu_item);
+ break;
+ default:
+ wt = widget_type(UI_WTYPE_MENU_ITEM);
+ break;
+ }
+ }
+ else if (but->dt == UI_EMBOSS_NONE) {
+ /* "nothing" */
+ switch (but->type) {
+ case UI_BTYPE_LABEL:
+ wt = widget_type(UI_WTYPE_ICON_LABEL);
+ break;
+ default:
+ wt = widget_type(UI_WTYPE_ICON);
+ break;
+ }
+ }
+ else if (but->dt == UI_EMBOSS_RADIAL) {
+ wt = widget_type(UI_WTYPE_MENU_ITEM_RADIAL);
+ }
+ else {
+ BLI_assert(but->dt == UI_EMBOSS);
+
+ switch (but->type) {
+ case UI_BTYPE_LABEL:
+ wt = widget_type(UI_WTYPE_LABEL);
+ fstyle = &style->widgetlabel;
+ if (but->drawflag & UI_BUT_BOX_ITEM) {
+ wt->wcol_theme = &tui->wcol_box;
+ wt->state = widget_state;
+ }
+ else if (but->block->theme_style == UI_BLOCK_THEME_STYLE_POPUP) {
+ wt->wcol_theme = &tui->wcol_menu_back;
+ wt->state = widget_state;
+ }
+ break;
+
+ case UI_BTYPE_SEPR:
+ case UI_BTYPE_SEPR_LINE:
+ case UI_BTYPE_SEPR_SPACER:
+ break;
+
+ case UI_BTYPE_BUT:
#ifdef USE_UI_TOOLBAR_HACK
- if (UI_but_is_tool(but)) {
- wt = widget_type(UI_WTYPE_TOOLBAR_ITEM);
- }
- else {
- wt = widget_type(UI_WTYPE_EXEC);
- }
+ if (UI_but_is_tool(but)) {
+ wt = widget_type(UI_WTYPE_TOOLBAR_ITEM);
+ }
+ else {
+ wt = widget_type(UI_WTYPE_EXEC);
+ }
#else
- wt = widget_type(UI_WTYPE_EXEC);
+ wt = widget_type(UI_WTYPE_EXEC);
#endif
- break;
-
- case UI_BTYPE_NUM:
- wt = widget_type(UI_WTYPE_NUMBER);
- break;
-
- case UI_BTYPE_NUM_SLIDER:
- wt = widget_type(UI_WTYPE_SLIDER);
- break;
-
- case UI_BTYPE_ROW:
- wt = widget_type(UI_WTYPE_RADIO);
- break;
-
- case UI_BTYPE_LISTROW:
- wt = widget_type(UI_WTYPE_LISTITEM);
- break;
-
- case UI_BTYPE_TEXT:
- wt = widget_type(UI_WTYPE_NAME);
- break;
-
- case UI_BTYPE_SEARCH_MENU:
- wt = widget_type(UI_WTYPE_NAME);
- if (but->block->theme_style == UI_BLOCK_THEME_STYLE_POPUP) {
- wt->wcol_theme = &btheme->tui.wcol_menu_back;
- }
- break;
-
- case UI_BTYPE_TAB:
- wt = widget_type(UI_WTYPE_TAB);
- break;
-
- case UI_BTYPE_BUT_TOGGLE:
- case UI_BTYPE_TOGGLE:
- case UI_BTYPE_TOGGLE_N:
- wt = widget_type(UI_WTYPE_TOGGLE);
- break;
-
- case UI_BTYPE_CHECKBOX:
- 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;
- }
- }
- else {
- wt = widget_type(UI_WTYPE_TOGGLE);
- }
-
- /* option buttons have strings outside, on menus use different colors */
- if (but->block->theme_style == UI_BLOCK_THEME_STYLE_POPUP) {
- wt->state = widget_state_option_menu;
- }
- break;
-
- case UI_BTYPE_MENU:
- case UI_BTYPE_BLOCK:
- case UI_BTYPE_POPOVER:
- if (but->flag & UI_BUT_NODE_LINK) {
- /* new node-link button, not active yet XXX */
- wt = widget_type(UI_WTYPE_MENU_NODE_LINK);
- }
- else {
- /* with menu arrows */
-
- /* we could use a flag for this, but for now just check size,
- * add updown arrows if there is room. */
- if ((!but->str[0] && but->icon && (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect) + 2)) ||
- /* disable for brushes also */
- (but->flag & UI_BUT_ICON_PREVIEW))
- {
- /* no arrows */
- wt = widget_type(UI_WTYPE_MENU_ICON_RADIO);
- }
- else {
- wt = widget_type(UI_WTYPE_MENU_RADIO);
- }
- }
- break;
-
- case UI_BTYPE_PULLDOWN:
- wt = widget_type(UI_WTYPE_PULLDOWN);
- break;
-
- case UI_BTYPE_BUT_MENU:
- wt = widget_type(UI_WTYPE_MENU_ITEM);
- break;
-
- case UI_BTYPE_COLOR:
- wt = widget_type(UI_WTYPE_SWATCH);
- break;
-
- case UI_BTYPE_ROUNDBOX:
- case UI_BTYPE_LISTBOX:
- wt = widget_type(UI_WTYPE_BOX);
- break;
-
- case UI_BTYPE_EXTRA:
- widget_draw_extra_mask(C, but, widget_type(UI_WTYPE_BOX), rect);
- break;
-
- case UI_BTYPE_HSVCUBE:
- if (ELEM(but->a1, UI_GRAD_V_ALT, UI_GRAD_L_ALT)) {
- /* vertical V slider, uses new widget draw now */
- ui_draw_but_HSV_v(but, rect);
- }
- else { /* other HSV pickers... */
- ui_draw_but_HSVCUBE(but, rect);
- }
- break;
-
- case UI_BTYPE_HSVCIRCLE:
- ui_draw_but_HSVCIRCLE(but, &tui->wcol_regular, rect);
- break;
-
- case UI_BTYPE_COLORBAND:
- ui_draw_but_COLORBAND(but, &tui->wcol_regular, rect);
- break;
-
- case UI_BTYPE_UNITVEC:
- wt = widget_type(UI_WTYPE_UNITVEC);
- break;
-
- case UI_BTYPE_IMAGE:
- ui_draw_but_IMAGE(ar, but, &tui->wcol_regular, rect);
- break;
-
- case UI_BTYPE_HISTOGRAM:
- ui_draw_but_HISTOGRAM(ar, but, &tui->wcol_regular, rect);
- break;
-
- case UI_BTYPE_WAVEFORM:
- ui_draw_but_WAVEFORM(ar, but, &tui->wcol_regular, rect);
- break;
-
- case UI_BTYPE_VECTORSCOPE:
- ui_draw_but_VECTORSCOPE(ar, but, &tui->wcol_regular, rect);
- break;
-
- case UI_BTYPE_CURVE:
- ui_draw_but_CURVE(ar, but, &tui->wcol_regular, rect);
- break;
-
- case UI_BTYPE_PROGRESS_BAR:
- wt = widget_type(UI_WTYPE_PROGRESSBAR);
- fstyle = &style->widgetlabel;
- break;
-
- case UI_BTYPE_SCROLL:
- wt = widget_type(UI_WTYPE_SCROLL);
- break;
-
- case UI_BTYPE_GRIP:
- wt = widget_type(UI_WTYPE_ICON);
- break;
-
- case UI_BTYPE_TRACK_PREVIEW:
- ui_draw_but_TRACKPREVIEW(ar, but, &tui->wcol_regular, rect);
- break;
-
- case UI_BTYPE_NODE_SOCKET:
- ui_draw_but_NODESOCKET(ar, but, &tui->wcol_regular, rect);
- break;
-
- default:
- wt = widget_type(UI_WTYPE_REGULAR);
- break;
- }
- }
-
- if (wt) {
- //rcti disablerect = *rect; /* rect gets clipped smaller for text */
- int roundboxalign, state, drawflag;
- bool disabled = false;
-
- roundboxalign = widget_roundbox_set(but, rect);
-
- /* Mask out flags re-used for local state. */
- state = but->flag & ~UI_STATE_FLAGS_ALL;
- drawflag = but->drawflag;
-
- if (state & UI_SELECT_DRAW) {
- state |= UI_SELECT;
- }
-
- if ((but->editstr) ||
- (UNLIKELY(but->flag & UI_BUT_DRAG_MULTI) && ui_but_drag_multi_edit_get(but)))
- {
- state |= UI_STATE_TEXT_INPUT;
- }
-
- if (but->hold_func) {
- state |= UI_STATE_HOLD_ACTION;
- }
-
- if (state & UI_ACTIVE) {
- if (but->drawflag & UI_BUT_ACTIVE_LEFT) {
- state |= UI_STATE_ACTIVE_LEFT;
- }
- else if (but->drawflag & UI_BUT_ACTIVE_RIGHT) {
- state |= UI_STATE_ACTIVE_RIGHT;
- }
- }
-
- if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
- if (but->dt != UI_EMBOSS_PULLDOWN) {
- disabled = true;
- }
- }
-
- if (drawflag & UI_BUT_TEXT_RIGHT) {
- state |= UI_STATE_TEXT_BEFORE_WIDGET;
- }
-
- if (disabled) {
- ui_widget_color_disabled(wt);
- }
-
- wt->state(wt, state, drawflag);
- if (wt->custom) {
- wt->custom(but, &wt->wcol, rect, state, roundboxalign);
- }
- else if (wt->draw) {
- wt->draw(&wt->wcol, rect, state, roundboxalign);
- }
-
- if (disabled) {
- GPU_blend(true);
- }
-
- bool show_semi_highlight = false;
+ break;
+
+ case UI_BTYPE_NUM:
+ wt = widget_type(UI_WTYPE_NUMBER);
+ break;
+
+ case UI_BTYPE_NUM_SLIDER:
+ wt = widget_type(UI_WTYPE_SLIDER);
+ break;
+
+ case UI_BTYPE_ROW:
+ wt = widget_type(UI_WTYPE_RADIO);
+ break;
+
+ case UI_BTYPE_LISTROW:
+ wt = widget_type(UI_WTYPE_LISTITEM);
+ break;
+
+ case UI_BTYPE_TEXT:
+ wt = widget_type(UI_WTYPE_NAME);
+ break;
+
+ case UI_BTYPE_SEARCH_MENU:
+ wt = widget_type(UI_WTYPE_NAME);
+ if (but->block->theme_style == UI_BLOCK_THEME_STYLE_POPUP) {
+ wt->wcol_theme = &btheme->tui.wcol_menu_back;
+ }
+ break;
+
+ case UI_BTYPE_TAB:
+ wt = widget_type(UI_WTYPE_TAB);
+ break;
+
+ case UI_BTYPE_BUT_TOGGLE:
+ case UI_BTYPE_TOGGLE:
+ case UI_BTYPE_TOGGLE_N:
+ wt = widget_type(UI_WTYPE_TOGGLE);
+ break;
+
+ case UI_BTYPE_CHECKBOX:
+ 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;
+ }
+ }
+ else {
+ wt = widget_type(UI_WTYPE_TOGGLE);
+ }
+
+ /* option buttons have strings outside, on menus use different colors */
+ if (but->block->theme_style == UI_BLOCK_THEME_STYLE_POPUP) {
+ wt->state = widget_state_option_menu;
+ }
+ break;
+
+ case UI_BTYPE_MENU:
+ case UI_BTYPE_BLOCK:
+ case UI_BTYPE_POPOVER:
+ if (but->flag & UI_BUT_NODE_LINK) {
+ /* new node-link button, not active yet XXX */
+ wt = widget_type(UI_WTYPE_MENU_NODE_LINK);
+ }
+ else {
+ /* with menu arrows */
+
+ /* we could use a flag for this, but for now just check size,
+ * add updown arrows if there is room. */
+ if ((!but->str[0] && but->icon && (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect) + 2)) ||
+ /* disable for brushes also */
+ (but->flag & UI_BUT_ICON_PREVIEW)) {
+ /* no arrows */
+ wt = widget_type(UI_WTYPE_MENU_ICON_RADIO);
+ }
+ else {
+ wt = widget_type(UI_WTYPE_MENU_RADIO);
+ }
+ }
+ break;
+
+ case UI_BTYPE_PULLDOWN:
+ wt = widget_type(UI_WTYPE_PULLDOWN);
+ break;
+
+ case UI_BTYPE_BUT_MENU:
+ wt = widget_type(UI_WTYPE_MENU_ITEM);
+ break;
+
+ case UI_BTYPE_COLOR:
+ wt = widget_type(UI_WTYPE_SWATCH);
+ break;
+
+ case UI_BTYPE_ROUNDBOX:
+ case UI_BTYPE_LISTBOX:
+ wt = widget_type(UI_WTYPE_BOX);
+ break;
+
+ case UI_BTYPE_EXTRA:
+ widget_draw_extra_mask(C, but, widget_type(UI_WTYPE_BOX), rect);
+ break;
+
+ case UI_BTYPE_HSVCUBE:
+ if (ELEM(but->a1, UI_GRAD_V_ALT, UI_GRAD_L_ALT)) {
+ /* vertical V slider, uses new widget draw now */
+ ui_draw_but_HSV_v(but, rect);
+ }
+ else { /* other HSV pickers... */
+ ui_draw_but_HSVCUBE(but, rect);
+ }
+ break;
+
+ case UI_BTYPE_HSVCIRCLE:
+ ui_draw_but_HSVCIRCLE(but, &tui->wcol_regular, rect);
+ break;
+
+ case UI_BTYPE_COLORBAND:
+ ui_draw_but_COLORBAND(but, &tui->wcol_regular, rect);
+ break;
+
+ case UI_BTYPE_UNITVEC:
+ wt = widget_type(UI_WTYPE_UNITVEC);
+ break;
+
+ case UI_BTYPE_IMAGE:
+ ui_draw_but_IMAGE(ar, but, &tui->wcol_regular, rect);
+ break;
+
+ case UI_BTYPE_HISTOGRAM:
+ ui_draw_but_HISTOGRAM(ar, but, &tui->wcol_regular, rect);
+ break;
+
+ case UI_BTYPE_WAVEFORM:
+ ui_draw_but_WAVEFORM(ar, but, &tui->wcol_regular, rect);
+ break;
+
+ case UI_BTYPE_VECTORSCOPE:
+ ui_draw_but_VECTORSCOPE(ar, but, &tui->wcol_regular, rect);
+ break;
+
+ case UI_BTYPE_CURVE:
+ ui_draw_but_CURVE(ar, but, &tui->wcol_regular, rect);
+ break;
+
+ case UI_BTYPE_PROGRESS_BAR:
+ wt = widget_type(UI_WTYPE_PROGRESSBAR);
+ fstyle = &style->widgetlabel;
+ break;
+
+ case UI_BTYPE_SCROLL:
+ wt = widget_type(UI_WTYPE_SCROLL);
+ break;
+
+ case UI_BTYPE_GRIP:
+ wt = widget_type(UI_WTYPE_ICON);
+ break;
+
+ case UI_BTYPE_TRACK_PREVIEW:
+ ui_draw_but_TRACKPREVIEW(ar, but, &tui->wcol_regular, rect);
+ break;
+
+ case UI_BTYPE_NODE_SOCKET:
+ ui_draw_but_NODESOCKET(ar, but, &tui->wcol_regular, rect);
+ break;
+
+ default:
+ wt = widget_type(UI_WTYPE_REGULAR);
+ break;
+ }
+ }
+
+ if (wt) {
+ //rcti disablerect = *rect; /* rect gets clipped smaller for text */
+ int roundboxalign, state, drawflag;
+ bool disabled = false;
+
+ roundboxalign = widget_roundbox_set(but, rect);
+
+ /* Mask out flags re-used for local state. */
+ state = but->flag & ~UI_STATE_FLAGS_ALL;
+ drawflag = but->drawflag;
+
+ if (state & UI_SELECT_DRAW) {
+ state |= UI_SELECT;
+ }
+
+ if ((but->editstr) ||
+ (UNLIKELY(but->flag & UI_BUT_DRAG_MULTI) && ui_but_drag_multi_edit_get(but))) {
+ state |= UI_STATE_TEXT_INPUT;
+ }
+
+ if (but->hold_func) {
+ state |= UI_STATE_HOLD_ACTION;
+ }
+
+ if (state & UI_ACTIVE) {
+ if (but->drawflag & UI_BUT_ACTIVE_LEFT) {
+ state |= UI_STATE_ACTIVE_LEFT;
+ }
+ else if (but->drawflag & UI_BUT_ACTIVE_RIGHT) {
+ state |= UI_STATE_ACTIVE_RIGHT;
+ }
+ }
+
+ if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
+ if (but->dt != UI_EMBOSS_PULLDOWN) {
+ disabled = true;
+ }
+ }
+
+ if (drawflag & UI_BUT_TEXT_RIGHT) {
+ state |= UI_STATE_TEXT_BEFORE_WIDGET;
+ }
+
+ if (disabled) {
+ ui_widget_color_disabled(wt);
+ }
+
+ wt->state(wt, state, drawflag);
+ if (wt->custom) {
+ wt->custom(but, &wt->wcol, rect, state, roundboxalign);
+ }
+ else if (wt->draw) {
+ wt->draw(&wt->wcol, rect, state, roundboxalign);
+ }
+
+ if (disabled) {
+ GPU_blend(true);
+ }
+
+ bool show_semi_highlight = false;
#ifdef USE_UI_POPOVER_ONCE
- if (but->block->flag & UI_BLOCK_POPOVER_ONCE) {
- if ((state & UI_ACTIVE) && ui_but_is_popover_once_compat(but)) {
- show_semi_highlight = true;
- }
- }
+ if (but->block->flag & UI_BLOCK_POPOVER_ONCE) {
+ if ((state & UI_ACTIVE) && ui_but_is_popover_once_compat(but)) {
+ show_semi_highlight = true;
+ }
+ }
#endif
- if (but->flag & UI_BUT_ACTIVE_DEFAULT) {
- show_semi_highlight = true;
- }
-
- if (show_semi_highlight) {
- uiWidgetType wt_back = *wt;
- uiWidgetType *wt_temp = widget_type(UI_WTYPE_MENU_ITEM);
- wt_temp->state(wt_temp, state, drawflag);
- copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
- wt->wcol.inner[3] = 128;
- wt->wcol.roundness = 0.5f;
- ui_draw_roundbox(
- &rect_orig,
- 0.25f * min_ff(BLI_rcti_size_x(&rect_orig), BLI_rcti_size_y(&rect_orig)),
- &wt_temp->wcol);
- *wt = wt_back;
- }
-
- wt->text(fstyle, &wt->wcol, but, rect);
- if (disabled) {
- GPU_blend(false);
- }
-
-// if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
-// if (but->dt != UI_EMBOSS_PULLDOWN) {
-// widget_disabled(&disablerect);
-// }
-// }
- }
+ if (but->flag & UI_BUT_ACTIVE_DEFAULT) {
+ show_semi_highlight = true;
+ }
+
+ if (show_semi_highlight) {
+ uiWidgetType wt_back = *wt;
+ uiWidgetType *wt_temp = widget_type(UI_WTYPE_MENU_ITEM);
+ wt_temp->state(wt_temp, state, drawflag);
+ copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
+ wt->wcol.inner[3] = 128;
+ wt->wcol.roundness = 0.5f;
+ ui_draw_roundbox(&rect_orig,
+ 0.25f * min_ff(BLI_rcti_size_x(&rect_orig), BLI_rcti_size_y(&rect_orig)),
+ &wt_temp->wcol);
+ *wt = wt_back;
+ }
+
+ wt->text(fstyle, &wt->wcol, but, rect);
+ if (disabled) {
+ GPU_blend(false);
+ }
+
+ // if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
+ // if (but->dt != UI_EMBOSS_PULLDOWN) {
+ // widget_disabled(&disablerect);
+ // }
+ // }
+ }
}
static void ui_draw_clip_tri(uiBlock *block, rcti *rect, uiWidgetType *wt)
{
- if (block) {
- float draw_color[4];
- uchar *color = (uchar *)wt->wcol.text;
-
- draw_color[0] = ((float)color[0]) / 255.0f;
- draw_color[1] = ((float)color[1]) / 255.0f;
- draw_color[2] = ((float)color[2]) / 255.0f;
- draw_color[3] = 1.0f;
-
- if (block->flag & UI_BLOCK_CLIPTOP) {
- /* XXX no scaling for UI here yet */
- UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymax - 8, 't', draw_color);
- }
- if (block->flag & UI_BLOCK_CLIPBOTTOM) {
- /* XXX no scaling for UI here yet */
- UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymin + 10, 'v', draw_color);
- }
- }
+ if (block) {
+ float draw_color[4];
+ uchar *color = (uchar *)wt->wcol.text;
+
+ draw_color[0] = ((float)color[0]) / 255.0f;
+ draw_color[1] = ((float)color[1]) / 255.0f;
+ draw_color[2] = ((float)color[2]) / 255.0f;
+ draw_color[3] = 1.0f;
+
+ if (block->flag & UI_BLOCK_CLIPTOP) {
+ /* XXX no scaling for UI here yet */
+ UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymax - 8, 't', draw_color);
+ }
+ if (block->flag & UI_BLOCK_CLIPBOTTOM) {
+ /* XXX no scaling for UI here yet */
+ UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymin + 10, 'v', draw_color);
+ }
+ }
}
void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
{
- uiWidgetType *wt = widget_type(UI_WTYPE_MENU_BACK);
+ uiWidgetType *wt = widget_type(UI_WTYPE_MENU_BACK);
- wt->state(wt, 0, 0);
- if (block) {
- wt->draw(&wt->wcol, rect, block->flag, block->direction);
- }
- else {
- wt->draw(&wt->wcol, rect, 0, 0);
- }
+ wt->state(wt, 0, 0);
+ if (block) {
+ wt->draw(&wt->wcol, rect, block->flag, block->direction);
+ }
+ else {
+ wt->draw(&wt->wcol, rect, 0, 0);
+ }
- ui_draw_clip_tri(block, rect, wt);
+ ui_draw_clip_tri(block, rect, wt);
}
/**
* Similar to 'widget_menu_back', however we can't use the widget preset system
* because we need to pass in the original location so we know where to show the arrow.
*/
-static void ui_draw_popover_back_impl(
- const uiWidgetColors *wcol, rcti *rect, int direction, const float unit_size,
- const float mval_origin[2])
+static void ui_draw_popover_back_impl(const uiWidgetColors *wcol,
+ rcti *rect,
+ int direction,
+ const float unit_size,
+ const float mval_origin[2])
{
- /* tsk, this isn't nice. */
- const float unit_half = unit_size / 2;
- const float cent_x = mval_origin ? mval_origin[0] : BLI_rcti_cent_x(rect);
- rect->ymax -= unit_half;
- rect->ymin += unit_half;
-
- GPU_blend(true);
-
- /* Extracted from 'widget_menu_back', keep separate to avoid menu changes breaking popovers */
- {
- uiWidgetBase wtb;
- widget_init(&wtb);
-
- const int roundboxalign = UI_CNR_ALL;
- widget_softshadow(rect, roundboxalign, wcol->roundness * U.widget_unit);
-
- round_box_edges(&wtb, roundboxalign, rect, wcol->roundness * U.widget_unit);
- wtb.draw_emboss = false;
- widgetbase_draw(&wtb, wcol);
- }
-
- /* Draw popover arrow (top/bottom) */
- 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((uchar *)wcol->inner);
- 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);
- }
- immEnd();
- immUnbindProgram();
- }
-
- GPU_blend(false);
+ /* tsk, this isn't nice. */
+ const float unit_half = unit_size / 2;
+ const float cent_x = mval_origin ? mval_origin[0] : BLI_rcti_cent_x(rect);
+ rect->ymax -= unit_half;
+ rect->ymin += unit_half;
+
+ GPU_blend(true);
+
+ /* Extracted from 'widget_menu_back', keep separate to avoid menu changes breaking popovers */
+ {
+ uiWidgetBase wtb;
+ widget_init(&wtb);
+
+ const int roundboxalign = UI_CNR_ALL;
+ widget_softshadow(rect, roundboxalign, wcol->roundness * U.widget_unit);
+
+ round_box_edges(&wtb, roundboxalign, rect, wcol->roundness * U.widget_unit);
+ wtb.draw_emboss = false;
+ widgetbase_draw(&wtb, wcol);
+ }
+
+ /* Draw popover arrow (top/bottom) */
+ 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((uchar *)wcol->inner);
+ 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);
+ }
+ immEnd();
+ immUnbindProgram();
+ }
+
+ GPU_blend(false);
}
void ui_draw_popover_back(ARegion *ar, 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_draw_popover_back_impl(wt->wcol_theme, rect, block->direction, U.widget_unit / block->aspect, mval_origin);
- }
- else {
- wt->state(wt, 0, 0);
- wt->draw(&wt->wcol, rect, 0, 0);
- }
-
- ui_draw_clip_tri(block, rect, wt);
+ 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_draw_popover_back_impl(
+ wt->wcol_theme, rect, block->direction, U.widget_unit / block->aspect, mval_origin);
+ }
+ else {
+ wt->state(wt, 0, 0);
+ wt->draw(&wt->wcol, rect, 0, 0);
+ }
+
+ ui_draw_clip_tri(block, rect, wt);
}
-static void draw_disk_shaded(
- float start, float angle,
- float radius_int, float radius_ext, int subd,
- const char col1[4], const char col2[4],
- bool shaded)
+static void draw_disk_shaded(float start,
+ float angle,
+ float radius_int,
+ float radius_ext,
+ int subd,
+ const char col1[4],
+ const char col2[4],
+ bool shaded)
{
- const float radius_ext_scale = (0.5f / radius_ext); /* 1 / (2 * radius_ext) */
- int i;
-
- float s, c;
- float y1, y2;
- float fac;
- uchar r_col[4];
- uint pos, col;
-
- GPUVertFormat *format = immVertexFormat();
- pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- if (shaded) {
- col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
- }
- else {
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4ubv((uchar *)col1);
- }
-
- immBegin(GPU_PRIM_TRI_STRIP, subd * 2);
- for (i = 0; i < subd; i++) {
- float a;
-
- a = start + ((i) / (float)(subd - 1)) * angle;
- s = sinf(a);
- c = cosf(a);
- y1 = s * radius_int;
- y2 = s * radius_ext;
-
- if (shaded) {
- fac = (y1 + radius_ext) * radius_ext_scale;
- round_box_shade_col4_r(r_col, col1, col2, fac);
- immAttr4ubv(col, r_col);
- }
- immVertex2f(pos, c * radius_int, s * radius_int);
-
- if (shaded) {
- fac = (y2 + radius_ext) * radius_ext_scale;
- round_box_shade_col4_r(r_col, col1, col2, fac);
- immAttr4ubv(col, r_col);
- }
- immVertex2f(pos, c * radius_ext, s * radius_ext);
- }
- immEnd();
-
- immUnbindProgram();
+ const float radius_ext_scale = (0.5f / radius_ext); /* 1 / (2 * radius_ext) */
+ int i;
+
+ float s, c;
+ float y1, y2;
+ float fac;
+ uchar r_col[4];
+ uint pos, col;
+
+ GPUVertFormat *format = immVertexFormat();
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ if (shaded) {
+ col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv((uchar *)col1);
+ }
+
+ immBegin(GPU_PRIM_TRI_STRIP, subd * 2);
+ for (i = 0; i < subd; i++) {
+ float a;
+
+ a = start + ((i) / (float)(subd - 1)) * angle;
+ s = sinf(a);
+ c = cosf(a);
+ y1 = s * radius_int;
+ y2 = s * radius_ext;
+
+ if (shaded) {
+ fac = (y1 + radius_ext) * radius_ext_scale;
+ round_box_shade_col4_r(r_col, col1, col2, fac);
+ immAttr4ubv(col, r_col);
+ }
+ immVertex2f(pos, c * radius_int, s * radius_int);
+
+ if (shaded) {
+ fac = (y2 + radius_ext) * radius_ext_scale;
+ round_box_shade_col4_r(r_col, col1, col2, fac);
+ immAttr4ubv(col, r_col);
+ }
+ immVertex2f(pos, c * radius_ext, s * radius_ext);
+ }
+ immEnd();
+
+ immUnbindProgram();
}
void ui_draw_pie_center(uiBlock *block)
{
- bTheme *btheme = UI_GetTheme();
- float cx = block->pie_data.pie_center_spawned[0];
- float cy = block->pie_data.pie_center_spawned[1];
-
- float *pie_dir = block->pie_data.pie_dir;
-
- float pie_radius_internal = U.dpi_fac * U.pie_menu_threshold;
- float pie_radius_external = U.dpi_fac * (U.pie_menu_threshold + 7.0f);
-
- int subd = 40;
-
- float angle = atan2f(pie_dir[1], pie_dir[0]);
- float range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_2 : M_PI_4;
-
- GPU_matrix_push();
- GPU_matrix_translate_2f(cx, cy);
-
- GPU_blend(true);
- if (btheme->tui.wcol_pie_menu.shaded) {
- char col1[4], col2[4];
- shadecolors4(col1, col2, btheme->tui.wcol_pie_menu.inner, btheme->tui.wcol_pie_menu.shadetop, btheme->tui.wcol_pie_menu.shadedown);
- draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, col1, col2, true);
- }
- else {
- draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, btheme->tui.wcol_pie_menu.inner, NULL, false);
- }
-
- if (!(block->pie_data.flags & UI_PIE_INVALID_DIR)) {
- if (btheme->tui.wcol_pie_menu.shaded) {
- char col1[4], col2[4];
- shadecolors4(col1, col2, btheme->tui.wcol_pie_menu.inner_sel, btheme->tui.wcol_pie_menu.shadetop, btheme->tui.wcol_pie_menu.shadedown);
- draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, col1, col2, true);
- }
- else {
- draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, btheme->tui.wcol_pie_menu.inner_sel, NULL, false);
- }
- }
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4ubv((uchar *)btheme->tui.wcol_pie_menu.outline);
-
- imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, pie_radius_internal, subd);
- imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, pie_radius_external, subd);
-
- immUnbindProgram();
-
- if (U.pie_menu_confirm > 0 && !(block->pie_data.flags & (UI_PIE_INVALID_DIR | UI_PIE_CLICK_STYLE))) {
- float pie_confirm_radius = U.dpi_fac * (pie_radius_internal + U.pie_menu_confirm);
- float pie_confirm_external = U.dpi_fac * (pie_radius_internal + U.pie_menu_confirm + 7.0f);
-
- const char col[4] = {UNPACK3(btheme->tui.wcol_pie_menu.text_sel), 64};
- draw_disk_shaded(angle - range / 2.0f, range, pie_confirm_radius, pie_confirm_external, subd, col, NULL, false);
- }
-
- GPU_blend(false);
- GPU_matrix_pop();
+ bTheme *btheme = UI_GetTheme();
+ float cx = block->pie_data.pie_center_spawned[0];
+ float cy = block->pie_data.pie_center_spawned[1];
+
+ float *pie_dir = block->pie_data.pie_dir;
+
+ float pie_radius_internal = U.dpi_fac * U.pie_menu_threshold;
+ float pie_radius_external = U.dpi_fac * (U.pie_menu_threshold + 7.0f);
+
+ int subd = 40;
+
+ float angle = atan2f(pie_dir[1], pie_dir[0]);
+ float range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_2 : M_PI_4;
+
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(cx, cy);
+
+ GPU_blend(true);
+ if (btheme->tui.wcol_pie_menu.shaded) {
+ char col1[4], col2[4];
+ shadecolors4(col1,
+ col2,
+ btheme->tui.wcol_pie_menu.inner,
+ btheme->tui.wcol_pie_menu.shadetop,
+ btheme->tui.wcol_pie_menu.shadedown);
+ draw_disk_shaded(0.0f,
+ (float)(M_PI * 2.0),
+ pie_radius_internal,
+ pie_radius_external,
+ subd,
+ col1,
+ col2,
+ true);
+ }
+ else {
+ draw_disk_shaded(0.0f,
+ (float)(M_PI * 2.0),
+ pie_radius_internal,
+ pie_radius_external,
+ subd,
+ btheme->tui.wcol_pie_menu.inner,
+ NULL,
+ false);
+ }
+
+ if (!(block->pie_data.flags & UI_PIE_INVALID_DIR)) {
+ if (btheme->tui.wcol_pie_menu.shaded) {
+ char col1[4], col2[4];
+ shadecolors4(col1,
+ col2,
+ btheme->tui.wcol_pie_menu.inner_sel,
+ btheme->tui.wcol_pie_menu.shadetop,
+ btheme->tui.wcol_pie_menu.shadedown);
+ draw_disk_shaded(angle - range / 2.0f,
+ range,
+ pie_radius_internal,
+ pie_radius_external,
+ subd,
+ col1,
+ col2,
+ true);
+ }
+ else {
+ draw_disk_shaded(angle - range / 2.0f,
+ range,
+ pie_radius_internal,
+ pie_radius_external,
+ subd,
+ btheme->tui.wcol_pie_menu.inner_sel,
+ NULL,
+ false);
+ }
+ }
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv((uchar *)btheme->tui.wcol_pie_menu.outline);
+
+ imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, pie_radius_internal, subd);
+ imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, pie_radius_external, subd);
+
+ immUnbindProgram();
+
+ if (U.pie_menu_confirm > 0 &&
+ !(block->pie_data.flags & (UI_PIE_INVALID_DIR | UI_PIE_CLICK_STYLE))) {
+ float pie_confirm_radius = U.dpi_fac * (pie_radius_internal + U.pie_menu_confirm);
+ float pie_confirm_external = U.dpi_fac * (pie_radius_internal + U.pie_menu_confirm + 7.0f);
+
+ const char col[4] = {UNPACK3(btheme->tui.wcol_pie_menu.text_sel), 64};
+ draw_disk_shaded(angle - range / 2.0f,
+ range,
+ pie_confirm_radius,
+ pie_confirm_external,
+ subd,
+ col,
+ NULL,
+ false);
+ }
+
+ GPU_blend(false);
+ GPU_matrix_pop();
}
-
const uiWidgetColors *ui_tooltip_get_theme(void)
{
- uiWidgetType *wt = widget_type(UI_WTYPE_TOOLTIP);
- return wt->wcol_theme;
+ uiWidgetType *wt = widget_type(UI_WTYPE_TOOLTIP);
+ return wt->wcol_theme;
}
/**
* Generic drawing for background.
*/
-static void ui_draw_widget_back_color(
- uiWidgetTypeEnum type, bool use_shadow, const rcti *rect,
- const float color[4])
+static void ui_draw_widget_back_color(uiWidgetTypeEnum type,
+ bool use_shadow,
+ const rcti *rect,
+ const float color[4])
{
- uiWidgetType *wt = widget_type(type);
-
- if (use_shadow) {
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- widget_softshadow(rect, UI_CNR_ALL, 0.25f * U.widget_unit);
- GPU_blend(false);
- }
-
- rcti rect_copy = *rect;
- wt->state(wt, 0, 0);
- if (color) {
- rgba_float_to_uchar((uchar *)wt->wcol.inner, color);
- }
- wt->draw(&wt->wcol, &rect_copy, 0, UI_CNR_ALL);
+ uiWidgetType *wt = widget_type(type);
+
+ if (use_shadow) {
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ widget_softshadow(rect, UI_CNR_ALL, 0.25f * U.widget_unit);
+ GPU_blend(false);
+ }
+
+ rcti rect_copy = *rect;
+ wt->state(wt, 0, 0);
+ if (color) {
+ rgba_float_to_uchar((uchar *)wt->wcol.inner, color);
+ }
+ wt->draw(&wt->wcol, &rect_copy, 0, UI_CNR_ALL);
}
void ui_draw_widget_menu_back_color(const rcti *rect, bool use_shadow, const float color[4])
{
- ui_draw_widget_back_color(UI_WTYPE_MENU_BACK, use_shadow, rect, color);
+ ui_draw_widget_back_color(UI_WTYPE_MENU_BACK, use_shadow, rect, color);
}
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);
+ 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)
{
- uiWidgetType *wt = widget_type(UI_WTYPE_TOOLTIP);
- wt->state(wt, 0, 0);
- /* wt->draw ends up using same function to draw the tooltip as menu_back */
- wt->draw(&wt->wcol, rect, 0, 0);
+ uiWidgetType *wt = widget_type(UI_WTYPE_TOOLTIP);
+ wt->state(wt, 0, 0);
+ /* wt->draw ends up using same function to draw the tooltip as menu_back */
+ 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)
+void ui_draw_menu_item(
+ const uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state, bool use_sep)
{
- uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM);
- rcti _rect = *rect;
- char *cpoin = NULL;
-
- wt->state(wt, state, 0);
- wt->draw(&wt->wcol, rect, 0, 0);
-
- UI_fontstyle_set(fstyle);
-
- /* text location offset */
- rect->xmin += 0.25f * UI_UNIT_X;
- if (iconid) {
- rect->xmin += UI_DPI_ICON_SIZE;
- }
-
- /* cut string in 2 parts? */
- if (use_sep) {
- cpoin = strchr(name, UI_SEP_CHAR);
- if (cpoin) {
- *cpoin = 0;
-
- /* need to set this first */
- UI_fontstyle_set(fstyle);
-
- if (fstyle->kerning == 1) {
- /* for BLF_width */
- BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- }
-
- rect->xmax -= BLF_width(fstyle->uifont_id, cpoin + 1, INT_MAX) + UI_DPI_ICON_SIZE;
-
- if (fstyle->kerning == 1) {
- BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- }
- }
- }
-
- {
- char drawstr[UI_MAX_DRAW_STR];
- const float okwidth = (float)BLI_rcti_size_x(rect);
- const size_t max_len = sizeof(drawstr);
- const float minwidth = (float)(UI_DPI_ICON_SIZE);
-
- BLI_strncpy(drawstr, name, sizeof(drawstr));
- if (drawstr[0]) {
- UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0');
- }
-
- UI_fontstyle_draw(
- fstyle, rect, drawstr, (uchar *)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, (uchar *)wt->wcol.text,
- &(struct uiFontStyleDraw_Params) { .align = UI_STYLE_TEXT_RIGHT, });
- *cpoin = UI_SEP_CHAR;
- }
- }
-
- /* restore rect, was messed with */
- *rect = _rect;
-
- if (iconid) {
- float height, aspect;
- int xs = rect->xmin + 0.2f * UI_UNIT_X;
- int ys = rect->ymin + 0.1f * BLI_rcti_size_y(rect);
-
- height = ICON_SIZE_FROM_BUTRECT(rect);
- aspect = ICON_DEFAULT_HEIGHT / height;
-
- GPU_blend(true);
- /* XXX scale weak get from fstyle? */
- UI_icon_draw_aspect(xs, ys, iconid, aspect, 1.0f, wt->wcol.text);
- GPU_blend(false);
- }
+ uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM);
+ rcti _rect = *rect;
+ char *cpoin = NULL;
+
+ wt->state(wt, state, 0);
+ wt->draw(&wt->wcol, rect, 0, 0);
+
+ UI_fontstyle_set(fstyle);
+
+ /* text location offset */
+ rect->xmin += 0.25f * UI_UNIT_X;
+ if (iconid) {
+ rect->xmin += UI_DPI_ICON_SIZE;
+ }
+
+ /* cut string in 2 parts? */
+ if (use_sep) {
+ cpoin = strchr(name, UI_SEP_CHAR);
+ if (cpoin) {
+ *cpoin = 0;
+
+ /* need to set this first */
+ UI_fontstyle_set(fstyle);
+
+ if (fstyle->kerning == 1) {
+ /* for BLF_width */
+ BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
+
+ rect->xmax -= BLF_width(fstyle->uifont_id, cpoin + 1, INT_MAX) + UI_DPI_ICON_SIZE;
+
+ if (fstyle->kerning == 1) {
+ BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
+ }
+ }
+
+ {
+ char drawstr[UI_MAX_DRAW_STR];
+ const float okwidth = (float)BLI_rcti_size_x(rect);
+ const size_t max_len = sizeof(drawstr);
+ const float minwidth = (float)(UI_DPI_ICON_SIZE);
+
+ BLI_strncpy(drawstr, name, sizeof(drawstr));
+ if (drawstr[0]) {
+ UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0');
+ }
+
+ UI_fontstyle_draw(fstyle,
+ rect,
+ drawstr,
+ (uchar *)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,
+ (uchar *)wt->wcol.text,
+ &(struct uiFontStyleDraw_Params){
+ .align = UI_STYLE_TEXT_RIGHT,
+ });
+ *cpoin = UI_SEP_CHAR;
+ }
+ }
+
+ /* restore rect, was messed with */
+ *rect = _rect;
+
+ if (iconid) {
+ float height, aspect;
+ int xs = rect->xmin + 0.2f * UI_UNIT_X;
+ int ys = rect->ymin + 0.1f * BLI_rcti_size_y(rect);
+
+ height = ICON_SIZE_FROM_BUTRECT(rect);
+ aspect = ICON_DEFAULT_HEIGHT / height;
+
+ GPU_blend(true);
+ /* XXX scale weak get from fstyle? */
+ UI_icon_draw_aspect(xs, ys, iconid, aspect, 1.0f, wt->wcol.text);
+ GPU_blend(false);
+ }
}
-void ui_draw_preview_item(const uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state)
+void ui_draw_preview_item(
+ const uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state)
{
- rcti trect = *rect;
- const float text_size = UI_UNIT_Y;
- float font_dims[2] = {0.0f, 0.0f};
- uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM);
-
- /* drawing button background */
- wt->state(wt, state, 0);
- wt->draw(&wt->wcol, rect, 0, 0);
-
- /* draw icon in rect above the space reserved for the label */
- rect->ymin += text_size;
- GPU_blend(true);
- widget_draw_preview(iconid, 1.0f, rect);
- GPU_blend(false);
-
- BLF_width_and_height(fstyle->uifont_id, name, BLF_DRAW_STR_DUMMY_MAX, &font_dims[0], &font_dims[1]);
-
- /* text rect */
- trect.xmin += 0;
- trect.xmax = trect.xmin + font_dims[0] + U.widget_unit / 2;
- trect.ymin += U.widget_unit / 2;
- trect.ymax = trect.ymin + font_dims[1];
- if (trect.xmax > rect->xmax - PREVIEW_PAD) {
- trect.xmax = rect->xmax - PREVIEW_PAD;
- }
-
- {
- char drawstr[UI_MAX_DRAW_STR];
- const float okwidth = (float)BLI_rcti_size_x(&trect);
- const size_t max_len = sizeof(drawstr);
- const float minwidth = (float)(UI_DPI_ICON_SIZE);
-
- BLI_strncpy(drawstr, name, sizeof(drawstr));
- UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0');
-
- UI_fontstyle_draw(
- fstyle, &trect, drawstr, (uchar *)wt->wcol.text,
- &(struct uiFontStyleDraw_Params) { .align = UI_STYLE_TEXT_CENTER, });
- }
+ rcti trect = *rect;
+ const float text_size = UI_UNIT_Y;
+ float font_dims[2] = {0.0f, 0.0f};
+ uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM);
+
+ /* drawing button background */
+ wt->state(wt, state, 0);
+ wt->draw(&wt->wcol, rect, 0, 0);
+
+ /* draw icon in rect above the space reserved for the label */
+ rect->ymin += text_size;
+ GPU_blend(true);
+ widget_draw_preview(iconid, 1.0f, rect);
+ GPU_blend(false);
+
+ BLF_width_and_height(
+ fstyle->uifont_id, name, BLF_DRAW_STR_DUMMY_MAX, &font_dims[0], &font_dims[1]);
+
+ /* text rect */
+ trect.xmin += 0;
+ trect.xmax = trect.xmin + font_dims[0] + U.widget_unit / 2;
+ trect.ymin += U.widget_unit / 2;
+ trect.ymax = trect.ymin + font_dims[1];
+ if (trect.xmax > rect->xmax - PREVIEW_PAD) {
+ trect.xmax = rect->xmax - PREVIEW_PAD;
+ }
+
+ {
+ char drawstr[UI_MAX_DRAW_STR];
+ const float okwidth = (float)BLI_rcti_size_x(&trect);
+ const size_t max_len = sizeof(drawstr);
+ const float minwidth = (float)(UI_DPI_ICON_SIZE);
+
+ BLI_strncpy(drawstr, name, sizeof(drawstr));
+ UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0');
+
+ UI_fontstyle_draw(fstyle,
+ &trect,
+ drawstr,
+ (uchar *)wt->wcol.text,
+ &(struct uiFontStyleDraw_Params){
+ .align = UI_STYLE_TEXT_CENTER,
+ });
+ }
}
/** \} */
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 8d908375c1b..fa56dc04143 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -40,7 +40,7 @@
#include "BKE_main.h"
#include "BKE_mesh_runtime.h"
-#include "BLO_readfile.h" /* for UserDef version patching. */
+#include "BLO_readfile.h" /* for UserDef version patching. */
#include "BLF_api.h"
@@ -68,693 +68,853 @@ static struct bThemeState g_theme_state = {
void ui_resources_init(void)
{
- UI_icons_init();
+ UI_icons_init();
}
void ui_resources_free(void)
{
- UI_icons_free();
+ UI_icons_free();
}
-
/* ******************************************************** */
/* THEMES */
/* ******************************************************** */
const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
{
- ThemeSpace *ts = NULL;
- static char error[4] = {240, 0, 240, 255};
- static char alert[4] = {240, 60, 60, 255};
- static char headerdesel[4] = {0, 0, 0, 255};
- static char back[4] = {0, 0, 0, 255};
- static char setting = 0;
- const char *cp = error;
-
- /* ensure we're not getting a color after running BKE_blender_userdef_free */
- BLI_assert(BLI_findindex(&U.themes, theme_active) != -1);
- BLI_assert(colorid != TH_UNDEFINED);
-
- if (btheme) {
-
- /* first check for ui buttons theme */
- if (colorid < TH_THEMEUI) {
-
- switch (colorid) {
-
- case TH_REDALERT:
- cp = alert; break;
- }
- }
- else {
-
- switch (spacetype) {
- case SPACE_PROPERTIES:
- ts = &btheme->space_properties;
- break;
- case SPACE_VIEW3D:
- ts = &btheme->space_view3d;
- break;
- case SPACE_GRAPH:
- ts = &btheme->space_graph;
- break;
- case SPACE_FILE:
- ts = &btheme->space_file;
- break;
- case SPACE_NLA:
- ts = &btheme->space_nla;
- break;
- case SPACE_ACTION:
- ts = &btheme->space_action;
- break;
- case SPACE_SEQ:
- ts = &btheme->space_sequencer;
- break;
- case SPACE_IMAGE:
- ts = &btheme->space_image;
- break;
- case SPACE_TEXT:
- ts = &btheme->space_text;
- break;
- case SPACE_OUTLINER:
- ts = &btheme->space_outliner;
- break;
- case SPACE_INFO:
- ts = &btheme->space_info;
- break;
- case SPACE_USERPREF:
- ts = &btheme->space_preferences;
- break;
- case SPACE_CONSOLE:
- ts = &btheme->space_console;
- break;
- case SPACE_NODE:
- ts = &btheme->space_node;
- break;
- case SPACE_CLIP:
- ts = &btheme->space_clip;
- break;
- case SPACE_TOPBAR:
- ts = &btheme->space_topbar;
- break;
- case SPACE_STATUSBAR:
- ts = &btheme->space_statusbar;
- break;
- default:
- ts = &btheme->space_view3d;
- break;
- }
-
- switch (colorid) {
- case TH_BACK:
- if (ELEM(theme_regionid, RGN_TYPE_WINDOW, RGN_TYPE_PREVIEW)) {
- cp = ts->back;
- }
- else if (theme_regionid == RGN_TYPE_CHANNELS) {
- cp = ts->list;
- }
- else if (ELEM(theme_regionid, RGN_TYPE_HEADER, RGN_TYPE_FOOTER)) {
- cp = ts->header;
- }
- else if (theme_regionid == RGN_TYPE_NAV_BAR) {
- cp = ts->navigation_bar;
- }
- else if (theme_regionid == RGN_TYPE_EXECUTE) {
- cp = ts->execution_buts;
- }
- else {
- cp = ts->button;
- }
-
- copy_v4_v4_char(back, cp);
- if (!ED_region_is_overlap(spacetype, theme_regionid)) {
- back[3] = 255;
- }
- cp = back;
- break;
- case TH_BACK_GRAD:
- cp = ts->back_grad;
- break;
-
- case TH_SHOW_BACK_GRAD:
- cp = &setting;
- setting = ts->show_back_grad;
- break;
- case TH_TEXT:
- if (theme_regionid == RGN_TYPE_WINDOW) {
- cp = ts->text;
- }
- else if (theme_regionid == RGN_TYPE_CHANNELS) {
- cp = ts->list_text;
- }
- else if (ELEM(theme_regionid, RGN_TYPE_HEADER, RGN_TYPE_FOOTER)) {
- cp = ts->header_text;
- }
- else {
- cp = ts->button_text;
- }
- break;
- case TH_TEXT_HI:
- if (theme_regionid == RGN_TYPE_WINDOW) {
- cp = ts->text_hi;
- }
- else if (theme_regionid == RGN_TYPE_CHANNELS) {
- cp = ts->list_text_hi;
- }
- else if (ELEM(theme_regionid, RGN_TYPE_HEADER, RGN_TYPE_FOOTER)) {
- cp = ts->header_text_hi;
- }
- else {
- cp = ts->button_text_hi;
- }
- break;
- case TH_TITLE:
- if (theme_regionid == RGN_TYPE_WINDOW) {
- cp = ts->title;
- }
- else if (theme_regionid == RGN_TYPE_CHANNELS) {
- cp = ts->list_title;
- }
- else if (ELEM(theme_regionid, RGN_TYPE_HEADER, RGN_TYPE_FOOTER)) {
- cp = ts->header_title;
- }
- else {
- cp = ts->button_title;
- }
- break;
-
- case TH_HEADER:
- cp = ts->header; break;
- case TH_HEADERDESEL:
- /* we calculate a dynamic builtin header deselect color,
- * also for pulldowns... */
- cp = ts->header;
- headerdesel[0] = cp[0] > 10 ? cp[0] - 10 : 0;
- headerdesel[1] = cp[1] > 10 ? cp[1] - 10 : 0;
- headerdesel[2] = cp[2] > 10 ? cp[2] - 10 : 0;
- headerdesel[3] = cp[3];
- cp = headerdesel;
- break;
- case TH_HEADER_TEXT:
- cp = ts->header_text; break;
- case TH_HEADER_TEXT_HI:
- cp = ts->header_text_hi; break;
-
- case TH_PANEL_HEADER:
- cp = ts->panelcolors.header; break;
- case TH_PANEL_BACK:
- cp = ts->panelcolors.back; break;
- case TH_PANEL_SUB_BACK:
- cp = ts->panelcolors.sub_back; break;
-
- case TH_BUTBACK:
- cp = ts->button; break;
- case TH_BUTBACK_TEXT:
- cp = ts->button_text; break;
- case TH_BUTBACK_TEXT_HI:
- cp = ts->button_text_hi; break;
-
- case TH_TAB_ACTIVE:
- cp = ts->tab_active; break;
- case TH_TAB_INACTIVE:
- cp = ts->tab_inactive; break;
- case TH_TAB_BACK:
- cp = ts->tab_back; break;
- case TH_TAB_OUTLINE:
- cp = ts->tab_outline; break;
-
- case TH_SHADE1:
- cp = ts->shade1; break;
- case TH_SHADE2:
- cp = ts->shade2; break;
- case TH_HILITE:
- cp = ts->hilite; break;
-
- case TH_GRID:
- cp = ts->grid; break;
- case TH_VIEW_OVERLAY:
- cp = ts->view_overlay; break;
- case TH_WIRE:
- cp = ts->wire; break;
- case TH_WIRE_INNER:
- cp = ts->syntaxr; break;
- case TH_WIRE_EDIT:
- cp = ts->wire_edit; break;
- case TH_LIGHT:
- cp = ts->lamp; break;
- case TH_SPEAKER:
- cp = ts->speaker; break;
- case TH_CAMERA:
- cp = ts->camera; break;
- case TH_EMPTY:
- cp = ts->empty; break;
- case TH_SELECT:
- cp = ts->select; break;
- case TH_ACTIVE:
- cp = ts->active; break;
- case TH_GROUP:
- cp = ts->group; break;
- case TH_GROUP_ACTIVE:
- cp = ts->group_active; break;
- case TH_TRANSFORM:
- cp = ts->transform; break;
- case TH_VERTEX:
- cp = ts->vertex; break;
- case TH_VERTEX_SELECT:
- cp = ts->vertex_select; break;
- case TH_VERTEX_BEVEL:
- cp = ts->vertex_bevel; break;
- case TH_VERTEX_UNREFERENCED:
- cp = ts->vertex_unreferenced; break;
- case TH_VERTEX_SIZE:
- cp = &ts->vertex_size; break;
- case TH_OUTLINE_WIDTH:
- cp = &ts->outline_width; break;
- case TH_EDGE:
- cp = ts->edge; break;
- case TH_EDGE_SELECT:
- cp = ts->edge_select; break;
- case TH_EDGE_SEAM:
- cp = ts->edge_seam; break;
- case TH_EDGE_SHARP:
- cp = ts->edge_sharp; break;
- case TH_EDGE_CREASE:
- cp = ts->edge_crease; break;
- case TH_EDGE_BEVEL:
- cp = ts->edge_bevel; break;
- case TH_EDITMESH_ACTIVE:
- cp = ts->editmesh_active; break;
- case TH_EDGE_FACESEL:
- cp = ts->edge_facesel; break;
- case TH_FACE:
- cp = ts->face; break;
- case TH_FACE_SELECT:
- cp = ts->face_select; break;
- case TH_FACE_DOT:
- cp = ts->face_dot; break;
- case TH_FACEDOT_SIZE:
- cp = &ts->facedot_size; break;
- case TH_DRAWEXTRA_EDGELEN:
- cp = ts->extra_edge_len; break;
- case TH_DRAWEXTRA_EDGEANG:
- cp = ts->extra_edge_angle; break;
- case TH_DRAWEXTRA_FACEAREA:
- cp = ts->extra_face_area; break;
- case TH_DRAWEXTRA_FACEANG:
- cp = ts->extra_face_angle; break;
- case TH_NORMAL:
- cp = ts->normal; break;
- case TH_VNORMAL:
- cp = ts->vertex_normal; break;
- case TH_LNORMAL:
- cp = ts->loop_normal; break;
- case TH_BONE_SOLID:
- cp = ts->bone_solid; break;
- case TH_BONE_POSE:
- cp = ts->bone_pose; break;
- case TH_BONE_POSE_ACTIVE:
- cp = ts->bone_pose_active; break;
- case TH_STRIP:
- cp = ts->strip; break;
- case TH_STRIP_SELECT:
- cp = ts->strip_select; break;
- case TH_KEYTYPE_KEYFRAME:
- cp = ts->keytype_keyframe; break;
- case TH_KEYTYPE_KEYFRAME_SELECT:
- cp = ts->keytype_keyframe_select; break;
- case TH_KEYTYPE_EXTREME:
- cp = ts->keytype_extreme; break;
- case TH_KEYTYPE_EXTREME_SELECT:
- cp = ts->keytype_extreme_select; break;
- case TH_KEYTYPE_BREAKDOWN:
- cp = ts->keytype_breakdown; break;
- case TH_KEYTYPE_BREAKDOWN_SELECT:
- cp = ts->keytype_breakdown_select; break;
- case TH_KEYTYPE_JITTER:
- cp = ts->keytype_jitter; break;
- case TH_KEYTYPE_JITTER_SELECT:
- cp = ts->keytype_jitter_select; break;
- case TH_KEYTYPE_MOVEHOLD:
- cp = ts->keytype_movehold; break;
- case TH_KEYTYPE_MOVEHOLD_SELECT:
- cp = ts->keytype_movehold_select; break;
- case TH_KEYBORDER:
- cp = ts->keyborder; break;
- case TH_KEYBORDER_SELECT:
- cp = ts->keyborder_select; break;
- case TH_CFRAME:
- cp = ts->cframe; break;
- case TH_TIME_KEYFRAME:
- cp = ts->time_keyframe; break;
- case TH_TIME_GP_KEYFRAME:
- cp = ts->time_gp_keyframe; break;
- case TH_NURB_ULINE:
- cp = ts->nurb_uline; break;
- case TH_NURB_VLINE:
- cp = ts->nurb_vline; break;
- case TH_NURB_SEL_ULINE:
- cp = ts->nurb_sel_uline; break;
- case TH_NURB_SEL_VLINE:
- cp = ts->nurb_sel_vline; break;
- case TH_ACTIVE_SPLINE:
- cp = ts->act_spline; break;
- case TH_ACTIVE_VERT:
- cp = ts->lastsel_point; break;
- case TH_HANDLE_FREE:
- cp = ts->handle_free; break;
- case TH_HANDLE_AUTO:
- cp = ts->handle_auto; break;
- case TH_HANDLE_AUTOCLAMP:
- cp = ts->handle_auto_clamped; break;
- case TH_HANDLE_VECT:
- cp = ts->handle_vect; break;
- case TH_HANDLE_ALIGN:
- cp = ts->handle_align; break;
- case TH_HANDLE_SEL_FREE:
- cp = ts->handle_sel_free; break;
- case TH_HANDLE_SEL_AUTO:
- cp = ts->handle_sel_auto; break;
- case TH_HANDLE_SEL_AUTOCLAMP:
- cp = ts->handle_sel_auto_clamped; break;
- case TH_HANDLE_SEL_VECT:
- cp = ts->handle_sel_vect; break;
- case TH_HANDLE_SEL_ALIGN:
- cp = ts->handle_sel_align; break;
- case TH_FREESTYLE_EDGE_MARK:
- cp = ts->freestyle_edge_mark; break;
- case TH_FREESTYLE_FACE_MARK:
- cp = ts->freestyle_face_mark; break;
-
- case TH_SYNTAX_B:
- cp = ts->syntaxb; break;
- case TH_SYNTAX_V:
- cp = ts->syntaxv; break;
- case TH_SYNTAX_C:
- cp = ts->syntaxc; break;
- case TH_SYNTAX_L:
- cp = ts->syntaxl; break;
- case TH_SYNTAX_D:
- cp = ts->syntaxd; break;
- case TH_SYNTAX_R:
- cp = ts->syntaxr; break;
- case TH_SYNTAX_N:
- cp = ts->syntaxn; break;
- case TH_SYNTAX_S:
- cp = ts->syntaxs; break;
-
- case TH_NODE:
- cp = ts->syntaxl; break;
- case TH_NODE_INPUT:
- cp = ts->syntaxn; break;
- case TH_NODE_OUTPUT:
- cp = ts->nodeclass_output; break;
- case TH_NODE_COLOR:
- cp = ts->syntaxb; break;
- case TH_NODE_FILTER:
- cp = ts->nodeclass_filter; break;
- case TH_NODE_VECTOR:
- cp = ts->nodeclass_vector; break;
- case TH_NODE_TEXTURE:
- cp = ts->nodeclass_texture; break;
- case TH_NODE_PATTERN:
- cp = ts->nodeclass_pattern; break;
- case TH_NODE_SCRIPT:
- cp = ts->nodeclass_script; break;
- case TH_NODE_LAYOUT:
- cp = ts->nodeclass_layout; break;
- case TH_NODE_SHADER:
- cp = ts->nodeclass_shader; break;
- case TH_NODE_CONVERTOR:
- cp = ts->syntaxv; break;
- case TH_NODE_GROUP:
- cp = ts->syntaxc; break;
- case TH_NODE_INTERFACE:
- cp = ts->console_output; break;
- case TH_NODE_FRAME:
- cp = ts->movie; break;
- case TH_NODE_MATTE:
- cp = ts->syntaxs; break;
- case TH_NODE_DISTORT:
- cp = ts->syntaxd; break;
- case TH_NODE_CURVING:
- cp = &ts->noodle_curving; break;
-
- case TH_SEQ_MOVIE:
- cp = ts->movie; break;
- case TH_SEQ_MOVIECLIP:
- cp = ts->movieclip; break;
- case TH_SEQ_MASK:
- cp = ts->mask; break;
- case TH_SEQ_IMAGE:
- cp = ts->image; break;
- case TH_SEQ_SCENE:
- cp = ts->scene; break;
- case TH_SEQ_AUDIO:
- cp = ts->audio; break;
- case TH_SEQ_EFFECT:
- cp = ts->effect; break;
- case TH_SEQ_TRANSITION:
- cp = ts->transition; break;
- case TH_SEQ_META:
- cp = ts->meta; break;
- case TH_SEQ_TEXT:
- cp = ts->text_strip; break;
- case TH_SEQ_PREVIEW:
- cp = ts->preview_back; break;
-
- case TH_CONSOLE_OUTPUT:
- cp = ts->console_output; break;
- case TH_CONSOLE_INPUT:
- cp = ts->console_input; break;
- case TH_CONSOLE_INFO:
- cp = ts->console_info; break;
- case TH_CONSOLE_ERROR:
- cp = ts->console_error; break;
- case TH_CONSOLE_CURSOR:
- cp = ts->console_cursor; break;
- case TH_CONSOLE_SELECT:
- cp = ts->console_select; break;
-
- case TH_HANDLE_VERTEX:
- cp = ts->handle_vertex;
- break;
- case TH_HANDLE_VERTEX_SELECT:
- cp = ts->handle_vertex_select;
- break;
- case TH_HANDLE_VERTEX_SIZE:
- cp = &ts->handle_vertex_size;
- break;
-
- case TH_GP_VERTEX:
- cp = ts->gp_vertex;
- break;
- case TH_GP_VERTEX_SELECT:
- cp = ts->gp_vertex_select;
- break;
- case TH_GP_VERTEX_SIZE:
- cp = &ts->gp_vertex_size;
- break;
-
- case TH_DOPESHEET_CHANNELOB:
- cp = ts->ds_channel;
- break;
- case TH_DOPESHEET_CHANNELSUBOB:
- cp = ts->ds_subchannel;
- break;
- case TH_DOPESHEET_IPOLINE:
- cp = ts->ds_ipoline;
- break;
-
- case TH_PREVIEW_BACK:
- cp = ts->preview_back;
- break;
-
- case TH_STITCH_PREVIEW_FACE:
- cp = ts->preview_stitch_face;
- break;
-
- case TH_STITCH_PREVIEW_EDGE:
- cp = ts->preview_stitch_edge;
- break;
-
- case TH_STITCH_PREVIEW_VERT:
- cp = ts->preview_stitch_vert;
- break;
-
- case TH_STITCH_PREVIEW_STITCHABLE:
- cp = ts->preview_stitch_stitchable;
- break;
-
- case TH_STITCH_PREVIEW_UNSTITCHABLE:
- cp = ts->preview_stitch_unstitchable;
- break;
- case TH_STITCH_PREVIEW_ACTIVE:
- cp = ts->preview_stitch_active;
- break;
-
- case TH_PAINT_CURVE_HANDLE:
- cp = ts->paint_curve_handle;
- break;
- case TH_PAINT_CURVE_PIVOT:
- cp = ts->paint_curve_pivot;
- break;
-
- case TH_METADATA_BG:
- cp = ts->metadatabg;
- break;
- case TH_METADATA_TEXT:
- cp = ts->metadatatext;
- break;
-
- case TH_UV_OTHERS:
- cp = ts->uv_others;
- break;
- case TH_UV_SHADOW:
- cp = ts->uv_shadow;
- break;
-
- case TH_MARKER_OUTLINE:
- cp = ts->marker_outline; break;
- case TH_MARKER:
- cp = ts->marker; break;
- case TH_ACT_MARKER:
- cp = ts->act_marker; break;
- case TH_SEL_MARKER:
- cp = ts->sel_marker; break;
- case TH_BUNDLE_SOLID:
- cp = ts->bundle_solid; break;
- case TH_DIS_MARKER:
- cp = ts->dis_marker; break;
- case TH_PATH_BEFORE:
- cp = ts->path_before; break;
- case TH_PATH_AFTER:
- cp = ts->path_after; break;
- case TH_CAMERA_PATH:
- cp = ts->camera_path; break;
- case TH_LOCK_MARKER:
- cp = ts->lock_marker; break;
-
- case TH_MATCH:
- cp = ts->match;
- break;
-
- case TH_SELECT_HIGHLIGHT:
- cp = ts->selected_highlight;
- break;
-
- case TH_SKIN_ROOT:
- cp = ts->skin_root;
- break;
-
- case TH_ANIM_ACTIVE:
- cp = ts->anim_active;
- break;
- case TH_ANIM_INACTIVE:
- cp = ts->anim_non_active;
- break;
- case TH_ANIM_PREVIEW_RANGE:
- cp = ts->anim_preview_range;
- break;
-
- case TH_NLA_TWEAK:
- cp = ts->nla_tweaking;
- break;
- case TH_NLA_TWEAK_DUPLI:
- cp = ts->nla_tweakdupli;
- break;
-
- case TH_NLA_TRANSITION:
- cp = ts->nla_transition;
- break;
- case TH_NLA_TRANSITION_SEL:
- cp = ts->nla_transition_sel;
- break;
- case TH_NLA_META:
- cp = ts->nla_meta;
- break;
- case TH_NLA_META_SEL:
- cp = ts->nla_meta_sel;
- break;
- case TH_NLA_SOUND:
- cp = ts->nla_sound;
- break;
- case TH_NLA_SOUND_SEL:
- cp = ts->nla_sound_sel;
- break;
-
- case TH_WIDGET_EMBOSS:
- cp = btheme->tui.widget_emboss; break;
-
- case TH_EDITOR_OUTLINE:
- cp = btheme->tui.editor_outline;
- break;
- case TH_AXIS_X:
- cp = btheme->tui.xaxis; break;
- case TH_AXIS_Y:
- cp = btheme->tui.yaxis; break;
- case TH_AXIS_Z:
- cp = btheme->tui.zaxis; break;
-
- case TH_GIZMO_HI:
- cp = btheme->tui.gizmo_hi; break;
- case TH_GIZMO_PRIMARY:
- cp = btheme->tui.gizmo_primary; break;
- case TH_GIZMO_SECONDARY:
- cp = btheme->tui.gizmo_secondary; break;
- case TH_GIZMO_A:
- cp = btheme->tui.gizmo_a; break;
- case TH_GIZMO_B:
- cp = btheme->tui.gizmo_b; break;
-
- case TH_ICON_COLLECTION:
- cp = btheme->tui.icon_collection; break;
- case TH_ICON_OBJECT:
- cp = btheme->tui.icon_object; break;
- case TH_ICON_OBJECT_DATA:
- cp = btheme->tui.icon_object_data; break;
- case TH_ICON_MODIFIER:
- cp = btheme->tui.icon_modifier; break;
- case TH_ICON_SHADING:
- cp = btheme->tui.icon_shading; break;
-
- case TH_INFO_SELECTED:
- cp = ts->info_selected;
- break;
- case TH_INFO_SELECTED_TEXT:
- cp = ts->info_selected_text;
- break;
- case TH_INFO_ERROR:
- cp = ts->info_error;
- break;
- case TH_INFO_ERROR_TEXT:
- cp = ts->info_error_text;
- break;
- case TH_INFO_WARNING:
- cp = ts->info_warning;
- break;
- case TH_INFO_WARNING_TEXT:
- cp = ts->info_warning_text;
- break;
- case TH_INFO_INFO:
- cp = ts->info_info;
- break;
- case TH_INFO_INFO_TEXT:
- cp = ts->info_info_text;
- break;
- case TH_INFO_DEBUG:
- cp = ts->info_debug;
- break;
- case TH_INFO_DEBUG_TEXT:
- cp = ts->info_debug_text;
- break;
- case TH_V3D_CLIPPING_BORDER:
- cp = ts->clipping_border_3d;
- break;
- }
- }
- }
-
- return (const uchar *)cp;
+ ThemeSpace *ts = NULL;
+ static char error[4] = {240, 0, 240, 255};
+ static char alert[4] = {240, 60, 60, 255};
+ static char headerdesel[4] = {0, 0, 0, 255};
+ static char back[4] = {0, 0, 0, 255};
+ static char setting = 0;
+ const char *cp = error;
+
+ /* ensure we're not getting a color after running BKE_blender_userdef_free */
+ BLI_assert(BLI_findindex(&U.themes, theme_active) != -1);
+ BLI_assert(colorid != TH_UNDEFINED);
+
+ if (btheme) {
+
+ /* first check for ui buttons theme */
+ if (colorid < TH_THEMEUI) {
+
+ switch (colorid) {
+
+ case TH_REDALERT:
+ cp = alert;
+ break;
+ }
+ }
+ else {
+
+ switch (spacetype) {
+ case SPACE_PROPERTIES:
+ ts = &btheme->space_properties;
+ break;
+ case SPACE_VIEW3D:
+ ts = &btheme->space_view3d;
+ break;
+ case SPACE_GRAPH:
+ ts = &btheme->space_graph;
+ break;
+ case SPACE_FILE:
+ ts = &btheme->space_file;
+ break;
+ case SPACE_NLA:
+ ts = &btheme->space_nla;
+ break;
+ case SPACE_ACTION:
+ ts = &btheme->space_action;
+ break;
+ case SPACE_SEQ:
+ ts = &btheme->space_sequencer;
+ break;
+ case SPACE_IMAGE:
+ ts = &btheme->space_image;
+ break;
+ case SPACE_TEXT:
+ ts = &btheme->space_text;
+ break;
+ case SPACE_OUTLINER:
+ ts = &btheme->space_outliner;
+ break;
+ case SPACE_INFO:
+ ts = &btheme->space_info;
+ break;
+ case SPACE_USERPREF:
+ ts = &btheme->space_preferences;
+ break;
+ case SPACE_CONSOLE:
+ ts = &btheme->space_console;
+ break;
+ case SPACE_NODE:
+ ts = &btheme->space_node;
+ break;
+ case SPACE_CLIP:
+ ts = &btheme->space_clip;
+ break;
+ case SPACE_TOPBAR:
+ ts = &btheme->space_topbar;
+ break;
+ case SPACE_STATUSBAR:
+ ts = &btheme->space_statusbar;
+ break;
+ default:
+ ts = &btheme->space_view3d;
+ break;
+ }
+
+ switch (colorid) {
+ case TH_BACK:
+ if (ELEM(theme_regionid, RGN_TYPE_WINDOW, RGN_TYPE_PREVIEW)) {
+ cp = ts->back;
+ }
+ else if (theme_regionid == RGN_TYPE_CHANNELS) {
+ cp = ts->list;
+ }
+ else if (ELEM(theme_regionid, RGN_TYPE_HEADER, RGN_TYPE_FOOTER)) {
+ cp = ts->header;
+ }
+ else if (theme_regionid == RGN_TYPE_NAV_BAR) {
+ cp = ts->navigation_bar;
+ }
+ else if (theme_regionid == RGN_TYPE_EXECUTE) {
+ cp = ts->execution_buts;
+ }
+ else {
+ cp = ts->button;
+ }
+
+ copy_v4_v4_char(back, cp);
+ if (!ED_region_is_overlap(spacetype, theme_regionid)) {
+ back[3] = 255;
+ }
+ cp = back;
+ break;
+ case TH_BACK_GRAD:
+ cp = ts->back_grad;
+ break;
+
+ case TH_SHOW_BACK_GRAD:
+ cp = &setting;
+ setting = ts->show_back_grad;
+ break;
+ case TH_TEXT:
+ if (theme_regionid == RGN_TYPE_WINDOW) {
+ cp = ts->text;
+ }
+ else if (theme_regionid == RGN_TYPE_CHANNELS) {
+ cp = ts->list_text;
+ }
+ else if (ELEM(theme_regionid, RGN_TYPE_HEADER, RGN_TYPE_FOOTER)) {
+ cp = ts->header_text;
+ }
+ else {
+ cp = ts->button_text;
+ }
+ break;
+ case TH_TEXT_HI:
+ if (theme_regionid == RGN_TYPE_WINDOW) {
+ cp = ts->text_hi;
+ }
+ else if (theme_regionid == RGN_TYPE_CHANNELS) {
+ cp = ts->list_text_hi;
+ }
+ else if (ELEM(theme_regionid, RGN_TYPE_HEADER, RGN_TYPE_FOOTER)) {
+ cp = ts->header_text_hi;
+ }
+ else {
+ cp = ts->button_text_hi;
+ }
+ break;
+ case TH_TITLE:
+ if (theme_regionid == RGN_TYPE_WINDOW) {
+ cp = ts->title;
+ }
+ else if (theme_regionid == RGN_TYPE_CHANNELS) {
+ cp = ts->list_title;
+ }
+ else if (ELEM(theme_regionid, RGN_TYPE_HEADER, RGN_TYPE_FOOTER)) {
+ cp = ts->header_title;
+ }
+ else {
+ cp = ts->button_title;
+ }
+ break;
+
+ case TH_HEADER:
+ cp = ts->header;
+ break;
+ case TH_HEADERDESEL:
+ /* we calculate a dynamic builtin header deselect color,
+ * also for pulldowns... */
+ cp = ts->header;
+ headerdesel[0] = cp[0] > 10 ? cp[0] - 10 : 0;
+ headerdesel[1] = cp[1] > 10 ? cp[1] - 10 : 0;
+ headerdesel[2] = cp[2] > 10 ? cp[2] - 10 : 0;
+ headerdesel[3] = cp[3];
+ cp = headerdesel;
+ break;
+ case TH_HEADER_TEXT:
+ cp = ts->header_text;
+ break;
+ case TH_HEADER_TEXT_HI:
+ cp = ts->header_text_hi;
+ break;
+
+ case TH_PANEL_HEADER:
+ cp = ts->panelcolors.header;
+ break;
+ case TH_PANEL_BACK:
+ cp = ts->panelcolors.back;
+ break;
+ case TH_PANEL_SUB_BACK:
+ cp = ts->panelcolors.sub_back;
+ break;
+
+ case TH_BUTBACK:
+ cp = ts->button;
+ break;
+ case TH_BUTBACK_TEXT:
+ cp = ts->button_text;
+ break;
+ case TH_BUTBACK_TEXT_HI:
+ cp = ts->button_text_hi;
+ break;
+
+ case TH_TAB_ACTIVE:
+ cp = ts->tab_active;
+ break;
+ case TH_TAB_INACTIVE:
+ cp = ts->tab_inactive;
+ break;
+ case TH_TAB_BACK:
+ cp = ts->tab_back;
+ break;
+ case TH_TAB_OUTLINE:
+ cp = ts->tab_outline;
+ break;
+
+ case TH_SHADE1:
+ cp = ts->shade1;
+ break;
+ case TH_SHADE2:
+ cp = ts->shade2;
+ break;
+ case TH_HILITE:
+ cp = ts->hilite;
+ break;
+
+ case TH_GRID:
+ cp = ts->grid;
+ break;
+ case TH_VIEW_OVERLAY:
+ cp = ts->view_overlay;
+ break;
+ case TH_WIRE:
+ cp = ts->wire;
+ break;
+ case TH_WIRE_INNER:
+ cp = ts->syntaxr;
+ break;
+ case TH_WIRE_EDIT:
+ cp = ts->wire_edit;
+ break;
+ case TH_LIGHT:
+ cp = ts->lamp;
+ break;
+ case TH_SPEAKER:
+ cp = ts->speaker;
+ break;
+ case TH_CAMERA:
+ cp = ts->camera;
+ break;
+ case TH_EMPTY:
+ cp = ts->empty;
+ break;
+ case TH_SELECT:
+ cp = ts->select;
+ break;
+ case TH_ACTIVE:
+ cp = ts->active;
+ break;
+ case TH_GROUP:
+ cp = ts->group;
+ break;
+ case TH_GROUP_ACTIVE:
+ cp = ts->group_active;
+ break;
+ case TH_TRANSFORM:
+ cp = ts->transform;
+ break;
+ case TH_VERTEX:
+ cp = ts->vertex;
+ break;
+ case TH_VERTEX_SELECT:
+ cp = ts->vertex_select;
+ break;
+ case TH_VERTEX_BEVEL:
+ cp = ts->vertex_bevel;
+ break;
+ case TH_VERTEX_UNREFERENCED:
+ cp = ts->vertex_unreferenced;
+ break;
+ case TH_VERTEX_SIZE:
+ cp = &ts->vertex_size;
+ break;
+ case TH_OUTLINE_WIDTH:
+ cp = &ts->outline_width;
+ break;
+ case TH_EDGE:
+ cp = ts->edge;
+ break;
+ case TH_EDGE_SELECT:
+ cp = ts->edge_select;
+ break;
+ case TH_EDGE_SEAM:
+ cp = ts->edge_seam;
+ break;
+ case TH_EDGE_SHARP:
+ cp = ts->edge_sharp;
+ break;
+ case TH_EDGE_CREASE:
+ cp = ts->edge_crease;
+ break;
+ case TH_EDGE_BEVEL:
+ cp = ts->edge_bevel;
+ break;
+ case TH_EDITMESH_ACTIVE:
+ cp = ts->editmesh_active;
+ break;
+ case TH_EDGE_FACESEL:
+ cp = ts->edge_facesel;
+ break;
+ case TH_FACE:
+ cp = ts->face;
+ break;
+ case TH_FACE_SELECT:
+ cp = ts->face_select;
+ break;
+ case TH_FACE_DOT:
+ cp = ts->face_dot;
+ break;
+ case TH_FACEDOT_SIZE:
+ cp = &ts->facedot_size;
+ break;
+ case TH_DRAWEXTRA_EDGELEN:
+ cp = ts->extra_edge_len;
+ break;
+ case TH_DRAWEXTRA_EDGEANG:
+ cp = ts->extra_edge_angle;
+ break;
+ case TH_DRAWEXTRA_FACEAREA:
+ cp = ts->extra_face_area;
+ break;
+ case TH_DRAWEXTRA_FACEANG:
+ cp = ts->extra_face_angle;
+ break;
+ case TH_NORMAL:
+ cp = ts->normal;
+ break;
+ case TH_VNORMAL:
+ cp = ts->vertex_normal;
+ break;
+ case TH_LNORMAL:
+ cp = ts->loop_normal;
+ break;
+ case TH_BONE_SOLID:
+ cp = ts->bone_solid;
+ break;
+ case TH_BONE_POSE:
+ cp = ts->bone_pose;
+ break;
+ case TH_BONE_POSE_ACTIVE:
+ cp = ts->bone_pose_active;
+ break;
+ case TH_STRIP:
+ cp = ts->strip;
+ break;
+ case TH_STRIP_SELECT:
+ cp = ts->strip_select;
+ break;
+ case TH_KEYTYPE_KEYFRAME:
+ cp = ts->keytype_keyframe;
+ break;
+ case TH_KEYTYPE_KEYFRAME_SELECT:
+ cp = ts->keytype_keyframe_select;
+ break;
+ case TH_KEYTYPE_EXTREME:
+ cp = ts->keytype_extreme;
+ break;
+ case TH_KEYTYPE_EXTREME_SELECT:
+ cp = ts->keytype_extreme_select;
+ break;
+ case TH_KEYTYPE_BREAKDOWN:
+ cp = ts->keytype_breakdown;
+ break;
+ case TH_KEYTYPE_BREAKDOWN_SELECT:
+ cp = ts->keytype_breakdown_select;
+ break;
+ case TH_KEYTYPE_JITTER:
+ cp = ts->keytype_jitter;
+ break;
+ case TH_KEYTYPE_JITTER_SELECT:
+ cp = ts->keytype_jitter_select;
+ break;
+ case TH_KEYTYPE_MOVEHOLD:
+ cp = ts->keytype_movehold;
+ break;
+ case TH_KEYTYPE_MOVEHOLD_SELECT:
+ cp = ts->keytype_movehold_select;
+ break;
+ case TH_KEYBORDER:
+ cp = ts->keyborder;
+ break;
+ case TH_KEYBORDER_SELECT:
+ cp = ts->keyborder_select;
+ break;
+ case TH_CFRAME:
+ cp = ts->cframe;
+ break;
+ case TH_TIME_KEYFRAME:
+ cp = ts->time_keyframe;
+ break;
+ case TH_TIME_GP_KEYFRAME:
+ cp = ts->time_gp_keyframe;
+ break;
+ case TH_NURB_ULINE:
+ cp = ts->nurb_uline;
+ break;
+ case TH_NURB_VLINE:
+ cp = ts->nurb_vline;
+ break;
+ case TH_NURB_SEL_ULINE:
+ cp = ts->nurb_sel_uline;
+ break;
+ case TH_NURB_SEL_VLINE:
+ cp = ts->nurb_sel_vline;
+ break;
+ case TH_ACTIVE_SPLINE:
+ cp = ts->act_spline;
+ break;
+ case TH_ACTIVE_VERT:
+ cp = ts->lastsel_point;
+ break;
+ case TH_HANDLE_FREE:
+ cp = ts->handle_free;
+ break;
+ case TH_HANDLE_AUTO:
+ cp = ts->handle_auto;
+ break;
+ case TH_HANDLE_AUTOCLAMP:
+ cp = ts->handle_auto_clamped;
+ break;
+ case TH_HANDLE_VECT:
+ cp = ts->handle_vect;
+ break;
+ case TH_HANDLE_ALIGN:
+ cp = ts->handle_align;
+ break;
+ case TH_HANDLE_SEL_FREE:
+ cp = ts->handle_sel_free;
+ break;
+ case TH_HANDLE_SEL_AUTO:
+ cp = ts->handle_sel_auto;
+ break;
+ case TH_HANDLE_SEL_AUTOCLAMP:
+ cp = ts->handle_sel_auto_clamped;
+ break;
+ case TH_HANDLE_SEL_VECT:
+ cp = ts->handle_sel_vect;
+ break;
+ case TH_HANDLE_SEL_ALIGN:
+ cp = ts->handle_sel_align;
+ break;
+ case TH_FREESTYLE_EDGE_MARK:
+ cp = ts->freestyle_edge_mark;
+ break;
+ case TH_FREESTYLE_FACE_MARK:
+ cp = ts->freestyle_face_mark;
+ break;
+
+ case TH_SYNTAX_B:
+ cp = ts->syntaxb;
+ break;
+ case TH_SYNTAX_V:
+ cp = ts->syntaxv;
+ break;
+ case TH_SYNTAX_C:
+ cp = ts->syntaxc;
+ break;
+ case TH_SYNTAX_L:
+ cp = ts->syntaxl;
+ break;
+ case TH_SYNTAX_D:
+ cp = ts->syntaxd;
+ break;
+ case TH_SYNTAX_R:
+ cp = ts->syntaxr;
+ break;
+ case TH_SYNTAX_N:
+ cp = ts->syntaxn;
+ break;
+ case TH_SYNTAX_S:
+ cp = ts->syntaxs;
+ break;
+
+ case TH_NODE:
+ cp = ts->syntaxl;
+ break;
+ case TH_NODE_INPUT:
+ cp = ts->syntaxn;
+ break;
+ case TH_NODE_OUTPUT:
+ cp = ts->nodeclass_output;
+ break;
+ case TH_NODE_COLOR:
+ cp = ts->syntaxb;
+ break;
+ case TH_NODE_FILTER:
+ cp = ts->nodeclass_filter;
+ break;
+ case TH_NODE_VECTOR:
+ cp = ts->nodeclass_vector;
+ break;
+ case TH_NODE_TEXTURE:
+ cp = ts->nodeclass_texture;
+ break;
+ case TH_NODE_PATTERN:
+ cp = ts->nodeclass_pattern;
+ break;
+ case TH_NODE_SCRIPT:
+ cp = ts->nodeclass_script;
+ break;
+ case TH_NODE_LAYOUT:
+ cp = ts->nodeclass_layout;
+ break;
+ case TH_NODE_SHADER:
+ cp = ts->nodeclass_shader;
+ break;
+ case TH_NODE_CONVERTOR:
+ cp = ts->syntaxv;
+ break;
+ case TH_NODE_GROUP:
+ cp = ts->syntaxc;
+ break;
+ case TH_NODE_INTERFACE:
+ cp = ts->console_output;
+ break;
+ case TH_NODE_FRAME:
+ cp = ts->movie;
+ break;
+ case TH_NODE_MATTE:
+ cp = ts->syntaxs;
+ break;
+ case TH_NODE_DISTORT:
+ cp = ts->syntaxd;
+ break;
+ case TH_NODE_CURVING:
+ cp = &ts->noodle_curving;
+ break;
+
+ case TH_SEQ_MOVIE:
+ cp = ts->movie;
+ break;
+ case TH_SEQ_MOVIECLIP:
+ cp = ts->movieclip;
+ break;
+ case TH_SEQ_MASK:
+ cp = ts->mask;
+ break;
+ case TH_SEQ_IMAGE:
+ cp = ts->image;
+ break;
+ case TH_SEQ_SCENE:
+ cp = ts->scene;
+ break;
+ case TH_SEQ_AUDIO:
+ cp = ts->audio;
+ break;
+ case TH_SEQ_EFFECT:
+ cp = ts->effect;
+ break;
+ case TH_SEQ_TRANSITION:
+ cp = ts->transition;
+ break;
+ case TH_SEQ_META:
+ cp = ts->meta;
+ break;
+ case TH_SEQ_TEXT:
+ cp = ts->text_strip;
+ break;
+ case TH_SEQ_PREVIEW:
+ cp = ts->preview_back;
+ break;
+
+ case TH_CONSOLE_OUTPUT:
+ cp = ts->console_output;
+ break;
+ case TH_CONSOLE_INPUT:
+ cp = ts->console_input;
+ break;
+ case TH_CONSOLE_INFO:
+ cp = ts->console_info;
+ break;
+ case TH_CONSOLE_ERROR:
+ cp = ts->console_error;
+ break;
+ case TH_CONSOLE_CURSOR:
+ cp = ts->console_cursor;
+ break;
+ case TH_CONSOLE_SELECT:
+ cp = ts->console_select;
+ break;
+
+ case TH_HANDLE_VERTEX:
+ cp = ts->handle_vertex;
+ break;
+ case TH_HANDLE_VERTEX_SELECT:
+ cp = ts->handle_vertex_select;
+ break;
+ case TH_HANDLE_VERTEX_SIZE:
+ cp = &ts->handle_vertex_size;
+ break;
+
+ case TH_GP_VERTEX:
+ cp = ts->gp_vertex;
+ break;
+ case TH_GP_VERTEX_SELECT:
+ cp = ts->gp_vertex_select;
+ break;
+ case TH_GP_VERTEX_SIZE:
+ cp = &ts->gp_vertex_size;
+ break;
+
+ case TH_DOPESHEET_CHANNELOB:
+ cp = ts->ds_channel;
+ break;
+ case TH_DOPESHEET_CHANNELSUBOB:
+ cp = ts->ds_subchannel;
+ break;
+ case TH_DOPESHEET_IPOLINE:
+ cp = ts->ds_ipoline;
+ break;
+
+ case TH_PREVIEW_BACK:
+ cp = ts->preview_back;
+ break;
+
+ case TH_STITCH_PREVIEW_FACE:
+ cp = ts->preview_stitch_face;
+ break;
+
+ case TH_STITCH_PREVIEW_EDGE:
+ cp = ts->preview_stitch_edge;
+ break;
+
+ case TH_STITCH_PREVIEW_VERT:
+ cp = ts->preview_stitch_vert;
+ break;
+
+ case TH_STITCH_PREVIEW_STITCHABLE:
+ cp = ts->preview_stitch_stitchable;
+ break;
+
+ case TH_STITCH_PREVIEW_UNSTITCHABLE:
+ cp = ts->preview_stitch_unstitchable;
+ break;
+ case TH_STITCH_PREVIEW_ACTIVE:
+ cp = ts->preview_stitch_active;
+ break;
+
+ case TH_PAINT_CURVE_HANDLE:
+ cp = ts->paint_curve_handle;
+ break;
+ case TH_PAINT_CURVE_PIVOT:
+ cp = ts->paint_curve_pivot;
+ break;
+
+ case TH_METADATA_BG:
+ cp = ts->metadatabg;
+ break;
+ case TH_METADATA_TEXT:
+ cp = ts->metadatatext;
+ break;
+
+ case TH_UV_OTHERS:
+ cp = ts->uv_others;
+ break;
+ case TH_UV_SHADOW:
+ cp = ts->uv_shadow;
+ break;
+
+ case TH_MARKER_OUTLINE:
+ cp = ts->marker_outline;
+ break;
+ case TH_MARKER:
+ cp = ts->marker;
+ break;
+ case TH_ACT_MARKER:
+ cp = ts->act_marker;
+ break;
+ case TH_SEL_MARKER:
+ cp = ts->sel_marker;
+ break;
+ case TH_BUNDLE_SOLID:
+ cp = ts->bundle_solid;
+ break;
+ case TH_DIS_MARKER:
+ cp = ts->dis_marker;
+ break;
+ case TH_PATH_BEFORE:
+ cp = ts->path_before;
+ break;
+ case TH_PATH_AFTER:
+ cp = ts->path_after;
+ break;
+ case TH_CAMERA_PATH:
+ cp = ts->camera_path;
+ break;
+ case TH_LOCK_MARKER:
+ cp = ts->lock_marker;
+ break;
+
+ case TH_MATCH:
+ cp = ts->match;
+ break;
+
+ case TH_SELECT_HIGHLIGHT:
+ cp = ts->selected_highlight;
+ break;
+
+ case TH_SKIN_ROOT:
+ cp = ts->skin_root;
+ break;
+
+ case TH_ANIM_ACTIVE:
+ cp = ts->anim_active;
+ break;
+ case TH_ANIM_INACTIVE:
+ cp = ts->anim_non_active;
+ break;
+ case TH_ANIM_PREVIEW_RANGE:
+ cp = ts->anim_preview_range;
+ break;
+
+ case TH_NLA_TWEAK:
+ cp = ts->nla_tweaking;
+ break;
+ case TH_NLA_TWEAK_DUPLI:
+ cp = ts->nla_tweakdupli;
+ break;
+
+ case TH_NLA_TRANSITION:
+ cp = ts->nla_transition;
+ break;
+ case TH_NLA_TRANSITION_SEL:
+ cp = ts->nla_transition_sel;
+ break;
+ case TH_NLA_META:
+ cp = ts->nla_meta;
+ break;
+ case TH_NLA_META_SEL:
+ cp = ts->nla_meta_sel;
+ break;
+ case TH_NLA_SOUND:
+ cp = ts->nla_sound;
+ break;
+ case TH_NLA_SOUND_SEL:
+ cp = ts->nla_sound_sel;
+ break;
+
+ case TH_WIDGET_EMBOSS:
+ cp = btheme->tui.widget_emboss;
+ break;
+
+ case TH_EDITOR_OUTLINE:
+ cp = btheme->tui.editor_outline;
+ break;
+ case TH_AXIS_X:
+ cp = btheme->tui.xaxis;
+ break;
+ case TH_AXIS_Y:
+ cp = btheme->tui.yaxis;
+ break;
+ case TH_AXIS_Z:
+ cp = btheme->tui.zaxis;
+ break;
+
+ case TH_GIZMO_HI:
+ cp = btheme->tui.gizmo_hi;
+ break;
+ case TH_GIZMO_PRIMARY:
+ cp = btheme->tui.gizmo_primary;
+ break;
+ case TH_GIZMO_SECONDARY:
+ cp = btheme->tui.gizmo_secondary;
+ break;
+ case TH_GIZMO_A:
+ cp = btheme->tui.gizmo_a;
+ break;
+ case TH_GIZMO_B:
+ cp = btheme->tui.gizmo_b;
+ break;
+
+ case TH_ICON_COLLECTION:
+ cp = btheme->tui.icon_collection;
+ break;
+ case TH_ICON_OBJECT:
+ cp = btheme->tui.icon_object;
+ break;
+ case TH_ICON_OBJECT_DATA:
+ cp = btheme->tui.icon_object_data;
+ break;
+ case TH_ICON_MODIFIER:
+ cp = btheme->tui.icon_modifier;
+ break;
+ case TH_ICON_SHADING:
+ cp = btheme->tui.icon_shading;
+ break;
+
+ case TH_INFO_SELECTED:
+ cp = ts->info_selected;
+ break;
+ case TH_INFO_SELECTED_TEXT:
+ cp = ts->info_selected_text;
+ break;
+ case TH_INFO_ERROR:
+ cp = ts->info_error;
+ break;
+ case TH_INFO_ERROR_TEXT:
+ cp = ts->info_error_text;
+ break;
+ case TH_INFO_WARNING:
+ cp = ts->info_warning;
+ break;
+ case TH_INFO_WARNING_TEXT:
+ cp = ts->info_warning_text;
+ break;
+ case TH_INFO_INFO:
+ cp = ts->info_info;
+ break;
+ case TH_INFO_INFO_TEXT:
+ cp = ts->info_info_text;
+ break;
+ case TH_INFO_DEBUG:
+ cp = ts->info_debug;
+ break;
+ case TH_INFO_DEBUG_TEXT:
+ cp = ts->info_debug_text;
+ break;
+ case TH_V3D_CLIPPING_BORDER:
+ cp = ts->clipping_border_3d;
+ break;
+ }
+ }
+ }
+
+ return (const uchar *)cp;
}
/**
@@ -764,53 +924,52 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
*/
void UI_theme_init_default(void)
{
- /* we search for the theme with name Default */
- bTheme *btheme = BLI_findstring(&U.themes, "Default", offsetof(bTheme, name));
- if (btheme == NULL) {
- btheme = MEM_callocN(sizeof(bTheme), __func__);
- BLI_addtail(&U.themes, btheme);
- }
-
- UI_SetTheme(0, 0); /* make sure the global used in this file is set */
-
- const int active_theme_area = btheme->active_theme_area;
- memcpy(btheme, &U_theme_default, sizeof(*btheme));
- btheme->active_theme_area = active_theme_area;
+ /* we search for the theme with name Default */
+ bTheme *btheme = BLI_findstring(&U.themes, "Default", offsetof(bTheme, name));
+ if (btheme == NULL) {
+ btheme = MEM_callocN(sizeof(bTheme), __func__);
+ BLI_addtail(&U.themes, btheme);
+ }
+
+ UI_SetTheme(0, 0); /* make sure the global used in this file is set */
+
+ const int active_theme_area = btheme->active_theme_area;
+ memcpy(btheme, &U_theme_default, sizeof(*btheme));
+ btheme->active_theme_area = active_theme_area;
}
void UI_style_init_default(void)
{
- BLI_freelistN(&U.uistyles);
- /* gets automatically re-allocated */
- uiStyleInit();
+ BLI_freelistN(&U.uistyles);
+ /* gets automatically re-allocated */
+ uiStyleInit();
}
-
void UI_SetTheme(int spacetype, int regionid)
{
- if (spacetype) {
- /* later on, a local theme can be found too */
- theme_active = U.themes.first;
- theme_spacetype = spacetype;
- theme_regionid = regionid;
- }
- else if (regionid) {
- /* popups */
- theme_active = U.themes.first;
- theme_spacetype = SPACE_PROPERTIES;
- theme_regionid = regionid;
- }
- else {
- /* for safety, when theme was deleted */
- theme_active = U.themes.first;
- theme_spacetype = SPACE_VIEW3D;
- theme_regionid = RGN_TYPE_WINDOW;
- }
+ if (spacetype) {
+ /* later on, a local theme can be found too */
+ theme_active = U.themes.first;
+ theme_spacetype = spacetype;
+ theme_regionid = regionid;
+ }
+ else if (regionid) {
+ /* popups */
+ theme_active = U.themes.first;
+ theme_spacetype = SPACE_PROPERTIES;
+ theme_regionid = regionid;
+ }
+ else {
+ /* for safety, when theme was deleted */
+ theme_active = U.themes.first;
+ theme_spacetype = SPACE_VIEW3D;
+ theme_regionid = RGN_TYPE_WINDOW;
+ }
}
bTheme *UI_GetTheme(void)
{
- return U.themes.first;
+ return U.themes.first;
}
/**
@@ -818,492 +977,487 @@ bTheme *UI_GetTheme(void)
*/
void UI_Theme_Store(struct bThemeState *theme_state)
{
- *theme_state = g_theme_state;
+ *theme_state = g_theme_state;
}
void UI_Theme_Restore(struct bThemeState *theme_state)
{
- g_theme_state = *theme_state;
+ g_theme_state = *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);
- r = coloffset + (int) cp[0];
- CLAMP(r, 0, 255);
- g = coloffset + (int) cp[1];
- CLAMP(g, 0, 255);
- b = coloffset + (int) cp[2];
- CLAMP(b, 0, 255);
- a = alphaoffset + (int) cp[3];
- CLAMP(a, 0, 255);
-
- col[0] = r;
- col[1] = g;
- col[2] = b;
- col[3] = a;
+ 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);
+ g = coloffset + (int)cp[1];
+ CLAMP(g, 0, 255);
+ b = coloffset + (int)cp[2];
+ CLAMP(b, 0, 255);
+ a = alphaoffset + (int)cp[3];
+ CLAMP(a, 0, 255);
+
+ col[0] = r;
+ col[1] = g;
+ col[2] = b;
+ col[3] = a;
}
void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, uchar col[3])
{
- const uchar *cp1, *cp2;
+ const uchar *cp1, *cp2;
- cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
- cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+ cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ 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]);
- col[1] = floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
- col[2] = floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
+ CLAMP(fac, 0.0f, 1.0f);
+ col[0] = floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
+ col[1] = floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
+ col[2] = floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
}
void UI_GetThemeColorBlend3f(int colorid1, int colorid2, float fac, float r_col[3])
{
- const uchar *cp1, *cp2;
+ const uchar *cp1, *cp2;
- cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
- cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+ cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ 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;
- r_col[1] = ((1.0f - fac) * cp1[1] + fac * cp2[1]) / 255.0f;
- r_col[2] = ((1.0f - fac) * cp1[2] + fac * cp2[2]) / 255.0f;
+ CLAMP(fac, 0.0f, 1.0f);
+ r_col[0] = ((1.0f - fac) * cp1[0] + fac * cp2[0]) / 255.0f;
+ r_col[1] = ((1.0f - fac) * cp1[1] + fac * cp2[1]) / 255.0f;
+ r_col[2] = ((1.0f - fac) * cp1[2] + fac * cp2[2]) / 255.0f;
}
void UI_GetThemeColorBlend4f(int colorid1, int colorid2, float fac, float r_col[4])
{
- const uchar *cp1, *cp2;
+ const uchar *cp1, *cp2;
- cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
- cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+ cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ 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;
- r_col[1] = ((1.0f - fac) * cp1[1] + fac * cp2[1]) / 255.0f;
- r_col[2] = ((1.0f - fac) * cp1[2] + fac * cp2[2]) / 255.0f;
- r_col[3] = ((1.0f - fac) * cp1[3] + fac * cp2[3]) / 255.0f;
+ CLAMP(fac, 0.0f, 1.0f);
+ r_col[0] = ((1.0f - fac) * cp1[0] + fac * cp2[0]) / 255.0f;
+ r_col[1] = ((1.0f - fac) * cp1[1] + fac * cp2[1]) / 255.0f;
+ r_col[2] = ((1.0f - fac) * cp1[2] + fac * cp2[2]) / 255.0f;
+ r_col[3] = ((1.0f - fac) * cp1[3] + fac * cp2[3]) / 255.0f;
}
void UI_FontThemeColor(int fontid, int colorid)
{
- uchar color[4];
- UI_GetThemeColor4ubv(colorid, color);
- BLF_color4ubv(fontid, color);
+ uchar color[4];
+ UI_GetThemeColor4ubv(colorid, color);
+ BLF_color4ubv(fontid, color);
}
/* get individual values, not scaled */
float UI_GetThemeValuef(int colorid)
{
- const uchar *cp;
+ const uchar *cp;
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
- return ((float)cp[0]);
+ 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;
+ const uchar *cp;
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
- return ((int) cp[0]);
+ 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;
+ const uchar *cp;
- cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
- return ((float)cp[0]);
+ cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
+ return ((float)cp[0]);
}
int UI_GetThemeValueType(int colorid, int spacetype)
{
- const uchar *cp;
+ const uchar *cp;
- cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
- return ((int)cp[0]);
+ 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;
+ const uchar *cp;
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
- col[0] = ((float)cp[0]) / 255.0f;
- col[1] = ((float)cp[1]) / 255.0f;
- col[2] = ((float)cp[2]) / 255.0f;
+ 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;
}
void UI_GetThemeColor4fv(int colorid, float col[4])
{
- const uchar *cp;
+ const uchar *cp;
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
- col[0] = ((float)cp[0]) / 255.0f;
- col[1] = ((float)cp[1]) / 255.0f;
- col[2] = ((float)cp[2]) / 255.0f;
- col[3] = ((float)cp[3]) / 255.0f;
+ cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ col[0] = ((float)cp[0]) / 255.0f;
+ col[1] = ((float)cp[1]) / 255.0f;
+ col[2] = ((float)cp[2]) / 255.0f;
+ col[3] = ((float)cp[3]) / 255.0f;
}
void UI_GetThemeColorType4fv(int colorid, int spacetype, float col[4])
{
- const unsigned char *cp;
+ const unsigned char *cp;
- 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;
- col[3] = ((float)cp[3]) / 255.0f;
+ 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;
+ col[3] = ((float)cp[3]) / 255.0f;
}
/* get the color, range 0.0-1.0, complete with shading offset */
void UI_GetThemeColorShade3fv(int colorid, int offset, float col[3])
{
- int r, g, b;
- const uchar *cp;
+ int r, g, b;
+ const uchar *cp;
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
- r = offset + (int) cp[0];
- CLAMP(r, 0, 255);
- g = offset + (int) cp[1];
- CLAMP(g, 0, 255);
- b = offset + (int) cp[2];
- CLAMP(b, 0, 255);
+ r = offset + (int)cp[0];
+ CLAMP(r, 0, 255);
+ g = offset + (int)cp[1];
+ CLAMP(g, 0, 255);
+ b = offset + (int)cp[2];
+ CLAMP(b, 0, 255);
- col[0] = ((float)r) / 255.0f;
- col[1] = ((float)g) / 255.0f;
- col[2] = ((float)b) / 255.0f;
+ col[0] = ((float)r) / 255.0f;
+ col[1] = ((float)g) / 255.0f;
+ col[2] = ((float)b) / 255.0f;
}
void UI_GetThemeColorShade3ubv(int colorid, int offset, uchar col[3])
{
- int r, g, b;
- const uchar *cp;
+ int r, g, b;
+ const uchar *cp;
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
- r = offset + (int) cp[0];
- CLAMP(r, 0, 255);
- g = offset + (int) cp[1];
- CLAMP(g, 0, 255);
- b = offset + (int) cp[2];
- CLAMP(b, 0, 255);
+ r = offset + (int)cp[0];
+ CLAMP(r, 0, 255);
+ g = offset + (int)cp[1];
+ CLAMP(g, 0, 255);
+ b = offset + (int)cp[2];
+ CLAMP(b, 0, 255);
- col[0] = r;
- col[1] = g;
- col[2] = b;
+ col[0] = r;
+ col[1] = g;
+ col[2] = b;
}
-void UI_GetThemeColorBlendShade3ubv(int colorid1, int colorid2, float fac, int offset, uchar col[3])
+void UI_GetThemeColorBlendShade3ubv(
+ int colorid1, int colorid2, float fac, int offset, uchar col[3])
{
- const uchar *cp1, *cp2;
+ const uchar *cp1, *cp2;
- cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
- cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+ cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
- CLAMP(fac, 0.0f, 1.0f);
+ CLAMP(fac, 0.0f, 1.0f);
- float blend[3];
- blend[0] = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
- blend[1] = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
- blend[2] = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
+ float blend[3];
+ blend[0] = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
+ blend[1] = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
+ blend[2] = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
- unit_float_to_uchar_clamp_v3(col, blend);
+ unit_float_to_uchar_clamp_v3(col, blend);
}
void UI_GetThemeColorShade4ubv(int colorid, int offset, uchar col[4])
{
- 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];
- CLAMP(g, 0, 255);
- b = offset + (int) cp[2];
- CLAMP(b, 0, 255);
-
- col[0] = r;
- col[1] = g;
- col[2] = b;
- col[3] = cp[3];
+ 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];
+ CLAMP(g, 0, 255);
+ b = offset + (int)cp[2];
+ CLAMP(b, 0, 255);
+
+ col[0] = r;
+ col[1] = g;
+ col[2] = b;
+ col[3] = cp[3];
}
void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4])
{
- 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);
- g = coloffset + (int) cp[1];
- CLAMP(g, 0, 255);
- b = coloffset + (int) cp[2];
- CLAMP(b, 0, 255);
- a = alphaoffset + (int) cp[3];
- CLAMP(b, 0, 255);
-
- col[0] = ((float)r) / 255.0f;
- col[1] = ((float)g) / 255.0f;
- col[2] = ((float)b) / 255.0f;
- col[3] = ((float)a) / 255.0f;
+ 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);
+ g = coloffset + (int)cp[1];
+ CLAMP(g, 0, 255);
+ b = coloffset + (int)cp[2];
+ CLAMP(b, 0, 255);
+ a = alphaoffset + (int)cp[3];
+ CLAMP(b, 0, 255);
+
+ col[0] = ((float)r) / 255.0f;
+ col[1] = ((float)g) / 255.0f;
+ col[2] = ((float)b) / 255.0f;
+ col[3] = ((float)a) / 255.0f;
}
void UI_GetThemeColorBlendShade3fv(int colorid1, int colorid2, float fac, int offset, float col[3])
{
- int r, g, b;
- const uchar *cp1, *cp2;
+ int r, g, b;
+ const uchar *cp1, *cp2;
- cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
- cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+ cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
- CLAMP(fac, 0.0f, 1.0f);
+ CLAMP(fac, 0.0f, 1.0f);
- r = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
- CLAMP(r, 0, 255);
- g = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
- CLAMP(g, 0, 255);
- b = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
- CLAMP(b, 0, 255);
+ r = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
+ CLAMP(r, 0, 255);
+ g = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
+ CLAMP(g, 0, 255);
+ b = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
+ CLAMP(b, 0, 255);
- col[0] = ((float)r) / 255.0f;
- col[1] = ((float)g) / 255.0f;
- col[2] = ((float)b) / 255.0f;
+ col[0] = ((float)r) / 255.0f;
+ col[1] = ((float)g) / 255.0f;
+ col[2] = ((float)b) / 255.0f;
}
void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int offset, float col[4])
{
- 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);
-
- r = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
- CLAMP(r, 0, 255);
- g = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
- CLAMP(g, 0, 255);
- b = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
- CLAMP(b, 0, 255);
- a = offset + floorf((1.0f - fac) * cp1[3] + fac * cp2[3]);
- CLAMP(a, 0, 255);
-
- col[0] = ((float)r) / 255.0f;
- col[1] = ((float)g) / 255.0f;
- col[2] = ((float)b) / 255.0f;
- col[3] = ((float)a) / 255.0f;
+ 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);
+
+ r = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
+ CLAMP(r, 0, 255);
+ g = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
+ CLAMP(g, 0, 255);
+ b = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
+ CLAMP(b, 0, 255);
+ a = offset + floorf((1.0f - fac) * cp1[3] + fac * cp2[3]);
+ CLAMP(a, 0, 255);
+
+ col[0] = ((float)r) / 255.0f;
+ col[1] = ((float)g) / 255.0f;
+ col[2] = ((float)b) / 255.0f;
+ col[3] = ((float)a) / 255.0f;
}
/* get the color, in char pointer */
void UI_GetThemeColor3ubv(int colorid, uchar col[3])
{
- const uchar *cp;
+ const uchar *cp;
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
- col[0] = cp[0];
- col[1] = cp[1];
- col[2] = cp[2];
+ cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ col[0] = cp[0];
+ col[1] = cp[1];
+ col[2] = cp[2];
}
/* get the color, range 0.0-1.0, complete with shading offset */
void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4])
{
- int r, g, b, a;
- const uchar *cp;
+ int r, g, b, a;
+ const uchar *cp;
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
- r = offset + (int) cp[0];
- CLAMP(r, 0, 255);
- g = offset + (int) cp[1];
- CLAMP(g, 0, 255);
- b = offset + (int) cp[2];
- CLAMP(b, 0, 255);
+ r = offset + (int)cp[0];
+ CLAMP(r, 0, 255);
+ g = offset + (int)cp[1];
+ CLAMP(g, 0, 255);
+ b = offset + (int)cp[2];
+ CLAMP(b, 0, 255);
- a = (int) cp[3]; /* no shading offset... */
- CLAMP(a, 0, 255);
+ a = (int)cp[3]; /* no shading offset... */
+ CLAMP(a, 0, 255);
- col[0] = ((float)r) / 255.0f;
- col[1] = ((float)g) / 255.0f;
- col[2] = ((float)b) / 255.0f;
- col[3] = ((float)a) / 255.0f;
+ col[0] = ((float)r) / 255.0f;
+ col[1] = ((float)g) / 255.0f;
+ col[2] = ((float)b) / 255.0f;
+ col[3] = ((float)a) / 255.0f;
}
/* get the color, in char pointer */
void UI_GetThemeColor4ubv(int colorid, uchar col[4])
{
- const uchar *cp;
+ const uchar *cp;
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
- col[0] = cp[0];
- col[1] = cp[1];
- col[2] = cp[2];
- col[3] = cp[3];
+ cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ col[0] = cp[0];
+ col[1] = cp[1];
+ col[2] = cp[2];
+ col[3] = cp[3];
}
void UI_GetThemeColorType3fv(int colorid, int spacetype, float col[3])
{
- const uchar *cp;
+ const uchar *cp;
- 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;
+ 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;
}
void UI_GetThemeColorType3ubv(int colorid, int spacetype, uchar col[3])
{
- const uchar *cp;
+ const uchar *cp;
- cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
- col[0] = cp[0];
- col[1] = cp[1];
- col[2] = cp[2];
+ cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
+ col[0] = cp[0];
+ col[1] = cp[1];
+ col[2] = cp[2];
}
void UI_GetThemeColorType4ubv(int colorid, int spacetype, uchar col[4])
{
- const uchar *cp;
+ const uchar *cp;
- cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
- col[0] = cp[0];
- col[1] = cp[1];
- col[2] = cp[2];
- col[3] = cp[3];
+ cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
+ col[0] = cp[0];
+ col[1] = cp[1];
+ col[2] = cp[2];
+ col[3] = cp[3];
}
bool UI_GetIconThemeColor4fv(int colorid, float col[4])
{
- if (colorid == 0) {
- return false;
- }
-
- /* Only colored icons in outliner and popups, overall UI is intended
- * to stay monochrome and out of the way except a few places where it
- * is important to communicate different data types. */
- if (!((theme_spacetype == SPACE_OUTLINER) ||
- (theme_regionid == RGN_TYPE_TEMPORARY)))
- {
- return false;
- }
-
- const uchar *cp;
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
- col[0] = ((float)cp[0]) / 255.0f;
- col[1] = ((float)cp[1]) / 255.0f;
- col[2] = ((float)cp[2]) / 255.0f;
- col[3] = ((float)cp[3]) / 255.0f;
-
- return true;
+ if (colorid == 0) {
+ return false;
+ }
+
+ /* Only colored icons in outliner and popups, overall UI is intended
+ * to stay monochrome and out of the way except a few places where it
+ * is important to communicate different data types. */
+ if (!((theme_spacetype == SPACE_OUTLINER) || (theme_regionid == RGN_TYPE_TEMPORARY))) {
+ return false;
+ }
+
+ const uchar *cp;
+ cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ col[0] = ((float)cp[0]) / 255.0f;
+ col[1] = ((float)cp[1]) / 255.0f;
+ col[2] = ((float)cp[2]) / 255.0f;
+ col[3] = ((float)cp[3]) / 255.0f;
+
+ return true;
}
void UI_GetColorPtrShade3ubv(const uchar cp[3], uchar col[3], int offset)
{
- int r, g, b;
+ int r, g, b;
- r = offset + (int)cp[0];
- g = offset + (int)cp[1];
- b = offset + (int)cp[2];
+ r = offset + (int)cp[0];
+ g = offset + (int)cp[1];
+ b = offset + (int)cp[2];
- CLAMP(r, 0, 255);
- CLAMP(g, 0, 255);
- CLAMP(b, 0, 255);
+ CLAMP(r, 0, 255);
+ CLAMP(g, 0, 255);
+ CLAMP(b, 0, 255);
- col[0] = r;
- col[1] = g;
- col[2] = b;
+ col[0] = r;
+ col[1] = g;
+ col[2] = b;
}
/* get a 3 byte color, blended and shaded between two other char color pointers */
void UI_GetColorPtrBlendShade3ubv(
- const uchar cp1[3], const uchar cp2[3], uchar col[3],
- float fac, int offset)
+ const uchar cp1[3], const uchar cp2[3], uchar col[3], float fac, int offset)
{
- int r, g, b;
+ int r, g, b;
- CLAMP(fac, 0.0f, 1.0f);
- r = offset + floor((1.0f - fac) * cp1[0] + fac * cp2[0]);
- g = offset + floor((1.0f - fac) * cp1[1] + fac * cp2[1]);
- b = offset + floor((1.0f - fac) * cp1[2] + fac * cp2[2]);
+ CLAMP(fac, 0.0f, 1.0f);
+ r = offset + floor((1.0f - fac) * cp1[0] + fac * cp2[0]);
+ g = offset + floor((1.0f - fac) * cp1[1] + fac * cp2[1]);
+ b = offset + floor((1.0f - fac) * cp1[2] + fac * cp2[2]);
- CLAMP(r, 0, 255);
- CLAMP(g, 0, 255);
- CLAMP(b, 0, 255);
+ CLAMP(r, 0, 255);
+ CLAMP(g, 0, 255);
+ CLAMP(b, 0, 255);
- col[0] = r;
- col[1] = g;
- col[2] = b;
+ col[0] = r;
+ col[1] = g;
+ col[2] = b;
}
void UI_ThemeClearColor(int colorid)
{
- float col[3];
+ float col[3];
- UI_GetThemeColor3fv(colorid, col);
- GPU_clear_color(col[0], col[1], col[2], 0.0f);
+ UI_GetThemeColor3fv(colorid, col);
+ GPU_clear_color(col[0], col[1], col[2], 0.0f);
}
void UI_ThemeClearColorAlpha(int colorid, float alpha)
{
- float col[3];
- UI_GetThemeColor3fv(colorid, col);
- GPU_clear_color(col[0], col[1], col[2], alpha);
+ float col[3];
+ UI_GetThemeColor3fv(colorid, col);
+ GPU_clear_color(col[0], col[1], col[2], alpha);
}
-
int UI_ThemeMenuShadowWidth(void)
{
- bTheme *btheme = UI_GetTheme();
- return (int)(btheme->tui.menu_shadow_width * UI_DPI_FAC);
+ bTheme *btheme = UI_GetTheme();
+ return (int)(btheme->tui.menu_shadow_width * UI_DPI_FAC);
}
void UI_make_axis_color(const uchar src_col[3], uchar dst_col[3], const char axis)
{
- uchar col[3];
-
- switch (axis) {
- case 'X':
- UI_GetThemeColor3ubv(TH_AXIS_X, col);
- UI_GetColorPtrBlendShade3ubv(src_col, col, dst_col, 0.5f, -10);
- break;
- case 'Y':
- UI_GetThemeColor3ubv(TH_AXIS_Y, col);
- UI_GetColorPtrBlendShade3ubv(src_col, col, dst_col, 0.5f, -10);
- break;
- case 'Z':
- UI_GetThemeColor3ubv(TH_AXIS_Z, col);
- UI_GetColorPtrBlendShade3ubv(src_col, col, dst_col, 0.5f, -10);
- break;
- default:
- BLI_assert(0);
- break;
- }
+ uchar col[3];
+
+ switch (axis) {
+ case 'X':
+ UI_GetThemeColor3ubv(TH_AXIS_X, col);
+ UI_GetColorPtrBlendShade3ubv(src_col, col, dst_col, 0.5f, -10);
+ break;
+ case 'Y':
+ UI_GetThemeColor3ubv(TH_AXIS_Y, col);
+ UI_GetColorPtrBlendShade3ubv(src_col, col, dst_col, 0.5f, -10);
+ break;
+ case 'Z':
+ UI_GetThemeColor3ubv(TH_AXIS_Z, col);
+ UI_GetColorPtrBlendShade3ubv(src_col, col, dst_col, 0.5f, -10);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
}
/* patching UserDef struct and Themes */
void init_userdef_do_versions(Main *bmain)
{
- BLO_version_defaults_userpref_blend(bmain, &U);
+ BLO_version_defaults_userpref_blend(bmain, &U);
- if (STREQ(U.tempdir, "/")) {
- BKE_tempdir_system_init(U.tempdir);
- }
+ if (STREQ(U.tempdir, "/")) {
+ BKE_tempdir_system_init(U.tempdir);
+ }
- /* Not versioning, just avoid errors. */
+ /* Not versioning, just avoid errors. */
#ifndef WITH_CYCLES
- BKE_addon_remove_safe(&U.addons, "cycles");
+ BKE_addon_remove_safe(&U.addons, "cycles");
#endif
-
}
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index a01088277f2..fa56721c11f 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -21,7 +21,6 @@
* \ingroup edinterface
*/
-
#include <float.h>
#include <limits.h>
#include <math.h>
@@ -64,18 +63,18 @@ 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;
-
- if (UNLIKELY(f < min)) {
- return min;
- }
- else if (UNLIKELY(f > max)) {
- return (int)max;
- }
- else {
- return (int)f;
- }
+ const float min = INT_MIN;
+ const float max = INT_MAX;
+
+ if (UNLIKELY(f < min)) {
+ return min;
+ }
+ else if (UNLIKELY(f > max)) {
+ return (int)max;
+ }
+ else {
+ return (int)f;
+ }
}
/**
@@ -84,13 +83,12 @@ BLI_INLINE int clamp_float_to_int(const float f)
*/
BLI_INLINE void clamp_rctf_to_rcti(rcti *dst, const rctf *src)
{
- dst->xmin = clamp_float_to_int(src->xmin);
- dst->xmax = clamp_float_to_int(src->xmax);
- dst->ymin = clamp_float_to_int(src->ymin);
- dst->ymax = clamp_float_to_int(src->ymax);
+ dst->xmin = clamp_float_to_int(src->xmin);
+ dst->xmax = clamp_float_to_int(src->xmax);
+ dst->ymin = clamp_float_to_int(src->ymin);
+ dst->ymax = clamp_float_to_int(src->ymax);
}
-
/* XXX still unresolved: scrolls hide/unhide vs region mask handling */
/* XXX there's V2D_SCROLL_HORIZONTAL_HIDE and V2D_SCROLL_HORIZONTAL_FULLR ... */
@@ -103,21 +101,21 @@ BLI_INLINE void clamp_rctf_to_rcti(rcti *dst, const rctf *src)
*/
static int view2d_scroll_mapped(int scroll)
{
- if (scroll & V2D_SCROLL_HORIZONTAL_FULLR) {
- scroll &= ~(V2D_SCROLL_HORIZONTAL);
- }
- if (scroll & V2D_SCROLL_VERTICAL_FULLR) {
- scroll &= ~(V2D_SCROLL_VERTICAL);
- }
- return scroll;
+ if (scroll & V2D_SCROLL_HORIZONTAL_FULLR) {
+ scroll &= ~(V2D_SCROLL_HORIZONTAL);
+ }
+ if (scroll & V2D_SCROLL_VERTICAL_FULLR) {
+ scroll &= ~(V2D_SCROLL_VERTICAL);
+ }
+ return scroll;
}
void UI_view2d_mask_from_win(const View2D *v2d, rcti *r_mask)
{
- r_mask->xmin = 0;
- r_mask->ymin = 0;
- r_mask->xmax = v2d->winx - 1; /* -1 yes! masks are pixels */
- r_mask->ymax = v2d->winy - 1;
+ r_mask->xmin = 0;
+ r_mask->ymin = 0;
+ r_mask->xmax = v2d->winx - 1; /* -1 yes! masks are pixels */
+ r_mask->ymax = v2d->winy - 1;
}
/**
@@ -127,87 +125,88 @@ void UI_view2d_mask_from_win(const View2D *v2d, rcti *r_mask)
*/
static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scroll)
{
- int scroll;
-
- /* mask - view frame */
- UI_view2d_mask_from_win(v2d, &v2d->mask);
- if (mask_scroll == NULL) {
- 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_SCALE_HORIZONTAL)) {
- 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_SCALE_VERTICAL)) {
- 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;
- }
- }
- }
- }
-
- scroll = view2d_scroll_mapped(v2d->scroll);
-
- /* scrollers are based off regionsize
- * - they can only be on one to two edges of the region they define
- * - if they overlap, they must not occupy the corners (which are reserved for other widgets)
- */
- if (scroll) {
- const int scroll_width = (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) ?
- V2D_SCROLL_WIDTH_TEXT : V2D_SCROLL_WIDTH;
- const int scroll_height = (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) ?
- V2D_SCROLL_HEIGHT_TEXT : V2D_SCROLL_HEIGHT;
-
- /* vertical scroller */
- if (scroll & V2D_SCROLL_LEFT) {
- /* on left-hand edge of region */
- v2d->vert = *mask_scroll;
- v2d->vert.xmax = scroll_width;
- }
- else if (scroll & V2D_SCROLL_RIGHT) {
- /* on right-hand edge of region */
- v2d->vert = *mask_scroll;
- v2d->vert.xmax++; /* one pixel extra... was leaving a minor gap... */
- v2d->vert.xmin = v2d->vert.xmax - scroll_width;
- }
-
- /* horizontal scroller */
- if (scroll & (V2D_SCROLL_BOTTOM)) {
- /* on bottom edge of region */
- v2d->hor = *mask_scroll;
- v2d->hor.ymax = scroll_height;
- }
- else if (scroll & V2D_SCROLL_TOP) {
- /* on upper edge of region */
- v2d->hor = *mask_scroll;
- v2d->hor.ymin = v2d->hor.ymax - scroll_height;
- }
-
- /* adjust vertical scroller if there's a horizontal scroller, to leave corner free */
- if (scroll & V2D_SCROLL_VERTICAL) {
- if (scroll & (V2D_SCROLL_BOTTOM)) {
- /* on bottom edge of region */
- v2d->vert.ymin = v2d->hor.ymax;
- }
- else if (scroll & V2D_SCROLL_TOP) {
- /* on upper edge of region */
- v2d->vert.ymax = v2d->hor.ymin;
- }
- }
- }
+ int scroll;
+
+ /* mask - view frame */
+ UI_view2d_mask_from_win(v2d, &v2d->mask);
+ if (mask_scroll == NULL) {
+ 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_SCALE_HORIZONTAL)) {
+ 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_SCALE_VERTICAL)) {
+ 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;
+ }
+ }
+ }
+ }
+
+ scroll = view2d_scroll_mapped(v2d->scroll);
+
+ /* scrollers are based off regionsize
+ * - they can only be on one to two edges of the region they define
+ * - if they overlap, they must not occupy the corners (which are reserved for other widgets)
+ */
+ if (scroll) {
+ const int scroll_width = (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) ? V2D_SCROLL_WIDTH_TEXT :
+ V2D_SCROLL_WIDTH;
+ const int scroll_height = (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) ?
+ V2D_SCROLL_HEIGHT_TEXT :
+ V2D_SCROLL_HEIGHT;
+
+ /* vertical scroller */
+ if (scroll & V2D_SCROLL_LEFT) {
+ /* on left-hand edge of region */
+ v2d->vert = *mask_scroll;
+ v2d->vert.xmax = scroll_width;
+ }
+ else if (scroll & V2D_SCROLL_RIGHT) {
+ /* on right-hand edge of region */
+ v2d->vert = *mask_scroll;
+ v2d->vert.xmax++; /* one pixel extra... was leaving a minor gap... */
+ v2d->vert.xmin = v2d->vert.xmax - scroll_width;
+ }
+
+ /* horizontal scroller */
+ if (scroll & (V2D_SCROLL_BOTTOM)) {
+ /* on bottom edge of region */
+ v2d->hor = *mask_scroll;
+ v2d->hor.ymax = scroll_height;
+ }
+ else if (scroll & V2D_SCROLL_TOP) {
+ /* on upper edge of region */
+ v2d->hor = *mask_scroll;
+ v2d->hor.ymin = v2d->hor.ymax - scroll_height;
+ }
+
+ /* adjust vertical scroller if there's a horizontal scroller, to leave corner free */
+ if (scroll & V2D_SCROLL_VERTICAL) {
+ if (scroll & (V2D_SCROLL_BOTTOM)) {
+ /* on bottom edge of region */
+ v2d->vert.ymin = v2d->hor.ymax;
+ }
+ else if (scroll & V2D_SCROLL_TOP) {
+ /* on upper edge of region */
+ v2d->vert.ymax = v2d->hor.ymin;
+ }
+ }
+ }
}
/* Refresh and Validation */
@@ -221,175 +220,169 @@ 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();
-
- do_init = (v2d->flag & V2D_IS_INITIALISED) == 0;
-
- /* see eView2D_CommonViewTypes in UI_view2d.h for available view presets */
- switch (type) {
- /* 'standard view' - optimum setup for 'standard' view behavior,
- * that should be used new views as basis for their
- * own unique View2D settings, which should be used instead of this in most cases...
- */
- case V2D_COMMONVIEW_STANDARD:
- {
- /* for now, aspect ratio should be maintained,
- * and zoom is clamped within sane default limits */
- v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM);
- v2d->minzoom = 0.01f;
- v2d->maxzoom = 1000.0f;
-
- /* tot rect and cur should be same size, and aligned using 'standard' OpenGL coordinates for now
- * - region can resize 'tot' later to fit other data
- * - keeptot is only within bounds, as strict locking is not that critical
- * - view is aligned for (0,0) -> (winx-1, winy-1) setup
- */
- 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);
- v2d->tot.ymax = (float)(winy - 1);
-
- v2d->cur = v2d->tot;
- }
- /* scrollers - should we have these by default? */
- /* XXX for now, we don't override this, or set it either! */
- break;
- }
- /* 'list/channel view' - zoom, aspect ratio, and alignment restrictions are set here */
- case V2D_COMMONVIEW_LIST:
- {
- /* zoom + aspect ratio are locked */
- v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
- v2d->minzoom = v2d->maxzoom = 1.0f;
-
- /* tot rect has strictly regulated placement, and must only occur in +/- quadrant */
- v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
- v2d->keeptot = V2D_KEEPTOT_STRICT;
- tot_changed = do_init;
-
- /* scroller settings are currently not set here... that is left for regions... */
- break;
- }
- /* 'stack view' - practically the same as list/channel view, except is located in the pos y half instead.
- * zoom, aspect ratio, and alignment restrictions are set here */
- case V2D_COMMONVIEW_STACK:
- {
- /* zoom + aspect ratio are locked */
- v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
- v2d->minzoom = v2d->maxzoom = 1.0f;
-
- /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
- v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
- v2d->keeptot = V2D_KEEPTOT_STRICT;
- tot_changed = do_init;
-
- /* scroller settings are currently not set here... that is left for regions... */
- break;
- }
- /* 'header' regions - zoom, aspect ratio,
- * alignment, and panning restrictions are set here */
- case V2D_COMMONVIEW_HEADER:
- {
- /* zoom + aspect ratio are locked */
- v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
- v2d->minzoom = v2d->maxzoom = 1.0f;
-
- if (do_init) {
- v2d->tot.xmin = 0.0f;
- v2d->tot.xmax = winx;
- v2d->tot.ymin = 0.0f;
- v2d->tot.ymax = winy;
- v2d->cur = v2d->tot;
-
- v2d->min[0] = v2d->max[0] = (float)(winx - 1);
- v2d->min[1] = v2d->max[1] = (float)(winy - 1);
- }
- /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
- v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
- v2d->keeptot = V2D_KEEPTOT_STRICT;
- tot_changed = do_init;
-
- /* panning in y-axis is prohibited */
- v2d->keepofs = V2D_LOCKOFS_Y;
-
- /* absolutely no scrollers allowed */
- v2d->scroll = 0;
- break;
- }
- /* panels view, with horizontal/vertical align */
- case V2D_COMMONVIEW_PANELS_UI:
- {
-
- /* for now, aspect ratio should be maintained,
- * and zoom is clamped within sane default limits */
- v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM | V2D_KEEPZOOM);
- v2d->minzoom = 0.5f;
- v2d->maxzoom = 2.0f;
-
- v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
- v2d->keeptot = V2D_KEEPTOT_BOUNDS;
-
- /* note, scroll is being flipped in ED_region_panels() drawing */
- v2d->scroll |= (V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_VERTICAL_HIDE);
-
- /* initialize without scroll bars (interferes with zoom level see: T47047) */
- if (do_init) {
- v2d->scroll |= (V2D_SCROLL_VERTICAL_FULLR | V2D_SCROLL_HORIZONTAL_FULLR);
- }
-
- if (do_init) {
- float panelzoom = (style) ? style->panelzoom : 1.0f;
-
- v2d->tot.xmin = 0.0f;
- v2d->tot.xmax = winx;
-
- v2d->tot.ymax = 0.0f;
- v2d->tot.ymin = -winy;
-
- v2d->cur.xmin = 0.0f;
- v2d->cur.xmax = (winx) * panelzoom;
-
- v2d->cur.ymax = 0.0f;
- v2d->cur.ymin = (-winy) * panelzoom;
- }
- break;
- }
- /* other view types are completely defined using their own settings already */
- default:
- /* we don't do anything here,
- * as settings should be fine, but just make sure that rect */
- break;
- }
-
- /* set initialized flag so that View2D doesn't get reinitialised next time again */
- v2d->flag |= V2D_IS_INITIALISED;
-
- /* store view size */
- v2d->winx = winx;
- v2d->winy = winy;
-
- /* set masks (always do), but leave scroller scheck to totrect_set */
- view2d_masks(v2d, 0, NULL);
-
- if (do_init) {
- /* Visible by default. */
- v2d->alpha_hor = v2d->alpha_vert = 255;
- }
-
- /* set 'tot' rect before setting cur? */
- /* XXX confusing stuff here still -
- * I made this function not check scroller hide - that happens in totrect_set */
- if (tot_changed) {
- UI_view2d_totRect_set_resize(v2d, winx, winy, !do_init);
- }
- else {
- ui_view2d_curRect_validate_resize(v2d, !do_init, 0);
- }
-
+ bool tot_changed = false, do_init;
+ uiStyle *style = UI_style_get();
+
+ do_init = (v2d->flag & V2D_IS_INITIALISED) == 0;
+
+ /* see eView2D_CommonViewTypes in UI_view2d.h for available view presets */
+ switch (type) {
+ /* 'standard view' - optimum setup for 'standard' view behavior,
+ * that should be used new views as basis for their
+ * own unique View2D settings, which should be used instead of this in most cases...
+ */
+ case V2D_COMMONVIEW_STANDARD: {
+ /* for now, aspect ratio should be maintained,
+ * and zoom is clamped within sane default limits */
+ v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM);
+ v2d->minzoom = 0.01f;
+ v2d->maxzoom = 1000.0f;
+
+ /* tot rect and cur should be same size, and aligned using 'standard' OpenGL coordinates for now
+ * - region can resize 'tot' later to fit other data
+ * - keeptot is only within bounds, as strict locking is not that critical
+ * - view is aligned for (0,0) -> (winx-1, winy-1) setup
+ */
+ 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);
+ v2d->tot.ymax = (float)(winy - 1);
+
+ v2d->cur = v2d->tot;
+ }
+ /* scrollers - should we have these by default? */
+ /* XXX for now, we don't override this, or set it either! */
+ break;
+ }
+ /* 'list/channel view' - zoom, aspect ratio, and alignment restrictions are set here */
+ case V2D_COMMONVIEW_LIST: {
+ /* zoom + aspect ratio are locked */
+ v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+ v2d->minzoom = v2d->maxzoom = 1.0f;
+
+ /* tot rect has strictly regulated placement, and must only occur in +/- quadrant */
+ v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
+ v2d->keeptot = V2D_KEEPTOT_STRICT;
+ tot_changed = do_init;
+
+ /* scroller settings are currently not set here... that is left for regions... */
+ break;
+ }
+ /* 'stack view' - practically the same as list/channel view, except is located in the pos y half instead.
+ * zoom, aspect ratio, and alignment restrictions are set here */
+ case V2D_COMMONVIEW_STACK: {
+ /* zoom + aspect ratio are locked */
+ v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+ v2d->minzoom = v2d->maxzoom = 1.0f;
+
+ /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
+ v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
+ v2d->keeptot = V2D_KEEPTOT_STRICT;
+ tot_changed = do_init;
+
+ /* scroller settings are currently not set here... that is left for regions... */
+ break;
+ }
+ /* 'header' regions - zoom, aspect ratio,
+ * alignment, and panning restrictions are set here */
+ case V2D_COMMONVIEW_HEADER: {
+ /* zoom + aspect ratio are locked */
+ v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+ v2d->minzoom = v2d->maxzoom = 1.0f;
+
+ if (do_init) {
+ v2d->tot.xmin = 0.0f;
+ v2d->tot.xmax = winx;
+ v2d->tot.ymin = 0.0f;
+ v2d->tot.ymax = winy;
+ v2d->cur = v2d->tot;
+
+ v2d->min[0] = v2d->max[0] = (float)(winx - 1);
+ v2d->min[1] = v2d->max[1] = (float)(winy - 1);
+ }
+ /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
+ v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
+ v2d->keeptot = V2D_KEEPTOT_STRICT;
+ tot_changed = do_init;
+
+ /* panning in y-axis is prohibited */
+ v2d->keepofs = V2D_LOCKOFS_Y;
+
+ /* absolutely no scrollers allowed */
+ v2d->scroll = 0;
+ break;
+ }
+ /* panels view, with horizontal/vertical align */
+ case V2D_COMMONVIEW_PANELS_UI: {
+
+ /* for now, aspect ratio should be maintained,
+ * and zoom is clamped within sane default limits */
+ v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM | V2D_KEEPZOOM);
+ v2d->minzoom = 0.5f;
+ v2d->maxzoom = 2.0f;
+
+ v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
+ v2d->keeptot = V2D_KEEPTOT_BOUNDS;
+
+ /* note, scroll is being flipped in ED_region_panels() drawing */
+ v2d->scroll |= (V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_VERTICAL_HIDE);
+
+ /* initialize without scroll bars (interferes with zoom level see: T47047) */
+ if (do_init) {
+ v2d->scroll |= (V2D_SCROLL_VERTICAL_FULLR | V2D_SCROLL_HORIZONTAL_FULLR);
+ }
+
+ if (do_init) {
+ float panelzoom = (style) ? style->panelzoom : 1.0f;
+
+ v2d->tot.xmin = 0.0f;
+ v2d->tot.xmax = winx;
+
+ v2d->tot.ymax = 0.0f;
+ v2d->tot.ymin = -winy;
+
+ v2d->cur.xmin = 0.0f;
+ v2d->cur.xmax = (winx)*panelzoom;
+
+ v2d->cur.ymax = 0.0f;
+ v2d->cur.ymin = (-winy) * panelzoom;
+ }
+ break;
+ }
+ /* other view types are completely defined using their own settings already */
+ default:
+ /* we don't do anything here,
+ * as settings should be fine, but just make sure that rect */
+ break;
+ }
+
+ /* set initialized flag so that View2D doesn't get reinitialised next time again */
+ v2d->flag |= V2D_IS_INITIALISED;
+
+ /* store view size */
+ v2d->winx = winx;
+ v2d->winy = winy;
+
+ /* set masks (always do), but leave scroller scheck to totrect_set */
+ view2d_masks(v2d, 0, NULL);
+
+ if (do_init) {
+ /* Visible by default. */
+ v2d->alpha_hor = v2d->alpha_vert = 255;
+ }
+
+ /* set 'tot' rect before setting cur? */
+ /* XXX confusing stuff here still -
+ * I made this function not check scroller hide - that happens in totrect_set */
+ if (tot_changed) {
+ UI_view2d_totRect_set_resize(v2d, winx, winy, !do_init);
+ }
+ else {
+ ui_view2d_curRect_validate_resize(v2d, !do_init, 0);
+ }
}
/**
@@ -399,449 +392,450 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
// XXX pre2.5 -> this used to be called test_view2d()
static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mask_scrollers)
{
- float totwidth, totheight, curwidth, curheight, width, height;
- float winx, winy;
- rctf *cur, *tot;
-
- /* use mask as size of region that View2D resides in, as it takes into account
- * scrollbars already - keep in sync with zoomx/zoomy in view_zoomstep_apply_ex! */
- winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
- winy = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
-
- /* get pointers to rcts for less typing */
- cur = &v2d->cur;
- tot = &v2d->tot;
-
- /* we must satisfy the following constraints (in decreasing order of importance):
- * - alignment restrictions are respected
- * - cur must not fall outside of tot
- * - axis locks (zoom and offset) must be maintained
- * - zoom must not be excessive (check either sizes or zoom values)
- * - aspect ratio should be respected (NOTE: this is quite closely related to zoom too)
- */
-
- /* Step 1: if keepzoom, adjust the sizes of the rects only
- * - firstly, we calculate the sizes of the rects
- * - curwidth and curheight are saved as reference... modify width and height values here
- */
- totwidth = BLI_rctf_size_x(tot);
- totheight = BLI_rctf_size_y(tot);
- /* keep in sync with zoomx/zoomy in view_zoomstep_apply_ex! */
- curwidth = width = BLI_rctf_size_x(cur);
- curheight = height = BLI_rctf_size_y(cur);
-
- /* if zoom is locked, size on the appropriate axis is reset to mask size */
- if (v2d->keepzoom & V2D_LOCKZOOM_X) {
- width = winx;
- }
- if (v2d->keepzoom & V2D_LOCKZOOM_Y) {
- height = winy;
- }
-
- /* values used to divide, so make it safe
- * NOTE: width and height must use FLT_MIN instead of 1, otherwise it is impossible to
- * get enough resolution in Graph Editor for editing some curves
- */
- if (width < FLT_MIN) {
- width = 1;
- }
- if (height < FLT_MIN) {
- height = 1;
- }
- if (winx < 1) {
- winx = 1;
- }
- if (winy < 1) {
- winy = 1;
- }
-
- /* V2D_LIMITZOOM indicates that zoom level should be preserved when the window size changes */
- if (resize && (v2d->keepzoom & V2D_KEEPZOOM)) {
- float zoom, oldzoom;
-
- if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
- zoom = winx / width;
- oldzoom = v2d->oldwinx / curwidth;
-
- if (oldzoom != zoom) {
- width *= zoom / oldzoom;
- }
- }
-
- if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
- zoom = winy / height;
- oldzoom = v2d->oldwiny / curheight;
-
- if (oldzoom != zoom) {
- height *= zoom / oldzoom;
- }
- }
- }
- /* keepzoom (V2D_LIMITZOOM set), indicates that zoom level on each axis must not exceed limits
- * NOTE: in general, it is not expected that the lock-zoom will be used in conjunction with this
- */
- else if (v2d->keepzoom & V2D_LIMITZOOM) {
-
- /* check if excessive zoom on x-axis */
- if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
- const float zoom = winx / width;
- if (zoom < v2d->minzoom) {
- width = winx / v2d->minzoom;
- }
- else if (zoom > v2d->maxzoom) {
- width = winx / v2d->maxzoom;
- }
- }
-
- /* check if excessive zoom on y-axis */
- if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
- const float zoom = winy / height;
- if (zoom < v2d->minzoom) {
- height = winy / v2d->minzoom;
- }
- else if (zoom > v2d->maxzoom) {
- height = winy / v2d->maxzoom;
- }
- }
- }
- else {
- /* make sure sizes don't exceed that of the min/max sizes
- * (even though we're not doing zoom clamping) */
- CLAMP(width, v2d->min[0], v2d->max[0]);
- CLAMP(height, v2d->min[1], v2d->max[1]);
- }
-
- /* check if we should restore aspect ratio (if view size changed) */
- if (v2d->keepzoom & V2D_KEEPASPECT) {
- bool do_x = false, do_y = false, do_cur /* , do_win */ /* UNUSED */;
- float curRatio, winRatio;
-
- /* when a window edge changes, the aspect ratio can't be used to
- * find which is the best new 'cur' rect. that's why it stores 'old'
- */
- if (winx != v2d->oldwinx) {
- do_x = true;
- }
- if (winy != v2d->oldwiny) {
- do_y = true;
- }
-
- curRatio = height / width;
- winRatio = winy / winx;
-
- /* both sizes change (area/region maximized) */
- if (do_x == do_y) {
- if (do_x && do_y) {
- /* here is 1,1 case, so all others must be 0,0 */
- if (fabsf(winx - v2d->oldwinx) > fabsf(winy - v2d->oldwiny)) {
- do_y = false;
- }
- else {
- do_x = false;
- }
- }
- else if (winRatio > curRatio) {
- do_x = false;
- }
- else {
- do_x = true;
- }
- }
- do_cur = do_x;
- /* do_win = do_y; */ /* UNUSED */
-
- if (do_cur) {
- if ((v2d->keeptot == V2D_KEEPTOT_STRICT) && (winx != v2d->oldwinx)) {
- /* special exception for Outliner (and later channel-lists):
- * - The view may be moved left to avoid contents being pushed out of view when view shrinks.
- * - The keeptot code will make sure cur->xmin will not be less than tot->xmin (which cannot be allowed)
- * - width is not adjusted for changed ratios here...
- */
- if (winx < v2d->oldwinx) {
- float temp = v2d->oldwinx - winx;
-
- cur->xmin -= temp;
- cur->xmax -= temp;
-
- /* width does not get modified, as keepaspect here is just set to make
- * sure visible area adjusts to changing view shape!
- */
- }
- }
- else {
- /* portrait window: correct for x */
- width = height / winRatio;
- }
- }
- else {
- if ((v2d->keeptot == V2D_KEEPTOT_STRICT) && (winy != v2d->oldwiny)) {
- /* special exception for Outliner (and later channel-lists):
- * - Currently, no actions need to be taken here...
- */
-
- if (winy < v2d->oldwiny) {
- float temp = v2d->oldwiny - winy;
-
- if (v2d->align & V2D_ALIGN_NO_NEG_Y) {
- cur->ymin -= temp;
- cur->ymax -= temp;
- }
- else { /* Assume V2D_ALIGN_NO_POS_Y or combination */
- cur->ymin += temp;
- cur->ymax += temp;
- }
- }
-
- }
- else {
- /* landscape window: correct for y */
- height = width * winRatio;
- }
- }
-
- /* store region size for next time */
- v2d->oldwinx = (short)winx;
- v2d->oldwiny = (short)winy;
- }
-
- /* Step 2: apply new sizes to cur rect,
- * but need to take into account alignment settings here... */
- if ((width != curwidth) || (height != curheight)) {
- float temp, dh;
-
- /* resize from centerpoint, unless otherwise specified */
- if (width != curwidth) {
- if (v2d->keepofs & V2D_LOCKOFS_X) {
- cur->xmax += width - BLI_rctf_size_x(cur);
- }
- else if (v2d->keepofs & V2D_KEEPOFS_X) {
- if (v2d->align & V2D_ALIGN_NO_POS_X) {
- cur->xmin -= width - BLI_rctf_size_x(cur);
- }
- else {
- cur->xmax += width - BLI_rctf_size_x(cur);
- }
- }
- else {
- temp = BLI_rctf_cent_x(cur);
- dh = width * 0.5f;
-
- cur->xmin = temp - dh;
- cur->xmax = temp + dh;
- }
- }
- if (height != curheight) {
- if (v2d->keepofs & V2D_LOCKOFS_Y) {
- cur->ymax += height - BLI_rctf_size_y(cur);
- }
- else if (v2d->keepofs & V2D_KEEPOFS_Y) {
- if (v2d->align & V2D_ALIGN_NO_POS_Y) {
- cur->ymin -= height - BLI_rctf_size_y(cur);
- }
- else {
- cur->ymax += height - BLI_rctf_size_y(cur);
- }
- }
- else {
- temp = BLI_rctf_cent_y(cur);
- dh = height * 0.5f;
-
- cur->ymin = temp - dh;
- cur->ymax = temp + dh;
- }
- }
- }
-
- /* Step 3: adjust so that it doesn't fall outside of bounds of 'tot' */
- if (v2d->keeptot) {
- float temp, diff;
-
- /* recalculate extents of cur */
- curwidth = BLI_rctf_size_x(cur);
- curheight = BLI_rctf_size_y(cur);
-
- /* width */
- if ((curwidth > totwidth) && !(v2d->keepzoom & (V2D_KEEPZOOM | V2D_LOCKZOOM_X | V2D_LIMITZOOM))) {
- /* if zoom doesn't have to be maintained, just clamp edges */
- if (cur->xmin < tot->xmin) {
- cur->xmin = tot->xmin;
- }
- if (cur->xmax > tot->xmax) {
- cur->xmax = tot->xmax;
- }
- }
- else if (v2d->keeptot == V2D_KEEPTOT_STRICT) {
- /* This is an exception for the outliner (and later channel-lists, headers)
- * - must clamp within tot rect (absolutely no excuses)
- * --> therefore, cur->xmin must not be less than tot->xmin
- */
- if (cur->xmin < tot->xmin) {
- /* move cur across so that it sits at minimum of tot */
- temp = tot->xmin - cur->xmin;
-
- cur->xmin += temp;
- cur->xmax += temp;
- }
- else if (cur->xmax > tot->xmax) {
- /* - only offset by difference of cur-xmax and tot-xmax if that would not move
- * cur-xmin to lie past tot-xmin
- * - otherwise, simply shift to tot-xmin???
- */
- temp = cur->xmax - tot->xmax;
-
- if ((cur->xmin - temp) < tot->xmin) {
- /* only offset by difference from cur-min and tot-min */
- temp = cur->xmin - tot->xmin;
-
- cur->xmin -= temp;
- cur->xmax -= temp;
- }
- else {
- cur->xmin -= temp;
- cur->xmax -= temp;
- }
- }
- }
- else {
- /* This here occurs when:
- * - width too big, but maintaining zoom (i.e. widths cannot be changed)
- * - 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
- * (XXX - in the past, max was favored... if there are bugs, swap!)
- */
- if ((cur->xmin < tot->xmin) && (cur->xmax > tot->xmax)) {
- /* outside boundaries on both sides,
- * so take middle-point of tot, and place in balanced way */
- temp = BLI_rctf_cent_x(tot);
- diff = curwidth * 0.5f;
-
- cur->xmin = temp - diff;
- cur->xmax = temp + diff;
- }
- else if (cur->xmin < tot->xmin) {
- /* move cur across so that it sits at minimum of tot */
- temp = tot->xmin - cur->xmin;
-
- cur->xmin += temp;
- cur->xmax += temp;
- }
- else if (cur->xmax > tot->xmax) {
- /* - only offset by difference of cur-xmax and tot-xmax if that would not move
- * cur-xmin to lie past tot-xmin
- * - otherwise, simply shift to tot-xmin???
- */
- temp = cur->xmax - tot->xmax;
-
- if ((cur->xmin - temp) < tot->xmin) {
- /* only offset by difference from cur-min and tot-min */
- temp = cur->xmin - tot->xmin;
-
- cur->xmin -= temp;
- cur->xmax -= temp;
- }
- else {
- cur->xmin -= temp;
- cur->xmax -= temp;
- }
- }
- }
-
- /* height */
- if ((curheight > totheight) && !(v2d->keepzoom & (V2D_KEEPZOOM | V2D_LOCKZOOM_Y | V2D_LIMITZOOM))) {
- /* if zoom doesn't have to be maintained, just clamp edges */
- if (cur->ymin < tot->ymin) {
- cur->ymin = tot->ymin;
- }
- if (cur->ymax > tot->ymax) {
- cur->ymax = tot->ymax;
- }
- }
- else {
- /* This here occurs when:
- * - height too big, but maintaining zoom (i.e. heights cannot be changed)
- * - 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
- */
- if ((cur->ymin < tot->ymin) && (cur->ymax > tot->ymax)) {
- /* outside boundaries on both sides,
- * so take middle-point of tot, and place in balanced way */
- temp = BLI_rctf_cent_y(tot);
- diff = curheight * 0.5f;
-
- cur->ymin = temp - diff;
- cur->ymax = temp + diff;
- }
- else if (cur->ymin < tot->ymin) {
- /* there's still space remaining, so shift up */
- temp = tot->ymin - cur->ymin;
-
- cur->ymin += temp;
- cur->ymax += temp;
- }
- else if (cur->ymax > tot->ymax) {
- /* there's still space remaining, so shift down */
- temp = cur->ymax - tot->ymax;
-
- cur->ymin -= temp;
- cur->ymax -= temp;
- }
- }
- }
-
- /* Step 4: Make sure alignment restrictions are respected */
- if (v2d->align) {
- /* If alignment flags are set (but keeptot is not), they must still be respected, as although
- * they don't specify any particular bounds to stay within, they do define ranges which are
- * invalid.
- *
- * Here, we only check to make sure that on each axis, the 'cur' rect doesn't stray into these
- * invalid zones, otherwise we offset.
- */
-
- /* handle width - posx and negx flags are mutually exclusive, so watch out */
- if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
- /* width is in negative-x half */
- if (v2d->cur.xmax > 0) {
- v2d->cur.xmin -= v2d->cur.xmax;
- v2d->cur.xmax = 0.0f;
- }
- }
- else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
- /* width is in positive-x half */
- if (v2d->cur.xmin < 0) {
- v2d->cur.xmax -= v2d->cur.xmin;
- v2d->cur.xmin = 0.0f;
- }
- }
-
- /* handle height - posx and negx flags are mutually exclusive, so watch out */
- if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
- /* height is in negative-y half */
- if (v2d->cur.ymax > 0) {
- v2d->cur.ymin -= v2d->cur.ymax;
- v2d->cur.ymax = 0.0f;
- }
- }
- else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
- /* height is in positive-y half */
- if (v2d->cur.ymin < 0) {
- v2d->cur.ymax -= v2d->cur.ymin;
- v2d->cur.ymin = 0.0f;
- }
- }
- }
-
- /* set masks */
- view2d_masks(v2d, mask_scrollers, NULL);
+ float totwidth, totheight, curwidth, curheight, width, height;
+ float winx, winy;
+ rctf *cur, *tot;
+
+ /* use mask as size of region that View2D resides in, as it takes into account
+ * scrollbars already - keep in sync with zoomx/zoomy in view_zoomstep_apply_ex! */
+ winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
+ winy = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
+
+ /* get pointers to rcts for less typing */
+ cur = &v2d->cur;
+ tot = &v2d->tot;
+
+ /* we must satisfy the following constraints (in decreasing order of importance):
+ * - alignment restrictions are respected
+ * - cur must not fall outside of tot
+ * - axis locks (zoom and offset) must be maintained
+ * - zoom must not be excessive (check either sizes or zoom values)
+ * - aspect ratio should be respected (NOTE: this is quite closely related to zoom too)
+ */
+
+ /* Step 1: if keepzoom, adjust the sizes of the rects only
+ * - firstly, we calculate the sizes of the rects
+ * - curwidth and curheight are saved as reference... modify width and height values here
+ */
+ totwidth = BLI_rctf_size_x(tot);
+ totheight = BLI_rctf_size_y(tot);
+ /* keep in sync with zoomx/zoomy in view_zoomstep_apply_ex! */
+ curwidth = width = BLI_rctf_size_x(cur);
+ curheight = height = BLI_rctf_size_y(cur);
+
+ /* if zoom is locked, size on the appropriate axis is reset to mask size */
+ if (v2d->keepzoom & V2D_LOCKZOOM_X) {
+ width = winx;
+ }
+ if (v2d->keepzoom & V2D_LOCKZOOM_Y) {
+ height = winy;
+ }
+
+ /* values used to divide, so make it safe
+ * NOTE: width and height must use FLT_MIN instead of 1, otherwise it is impossible to
+ * get enough resolution in Graph Editor for editing some curves
+ */
+ if (width < FLT_MIN) {
+ width = 1;
+ }
+ if (height < FLT_MIN) {
+ height = 1;
+ }
+ if (winx < 1) {
+ winx = 1;
+ }
+ if (winy < 1) {
+ winy = 1;
+ }
+
+ /* V2D_LIMITZOOM indicates that zoom level should be preserved when the window size changes */
+ if (resize && (v2d->keepzoom & V2D_KEEPZOOM)) {
+ float zoom, oldzoom;
+
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
+ zoom = winx / width;
+ oldzoom = v2d->oldwinx / curwidth;
+
+ if (oldzoom != zoom) {
+ width *= zoom / oldzoom;
+ }
+ }
+
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
+ zoom = winy / height;
+ oldzoom = v2d->oldwiny / curheight;
+
+ if (oldzoom != zoom) {
+ height *= zoom / oldzoom;
+ }
+ }
+ }
+ /* keepzoom (V2D_LIMITZOOM set), indicates that zoom level on each axis must not exceed limits
+ * NOTE: in general, it is not expected that the lock-zoom will be used in conjunction with this
+ */
+ else if (v2d->keepzoom & V2D_LIMITZOOM) {
+
+ /* check if excessive zoom on x-axis */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
+ const float zoom = winx / width;
+ if (zoom < v2d->minzoom) {
+ width = winx / v2d->minzoom;
+ }
+ else if (zoom > v2d->maxzoom) {
+ width = winx / v2d->maxzoom;
+ }
+ }
+
+ /* check if excessive zoom on y-axis */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
+ const float zoom = winy / height;
+ if (zoom < v2d->minzoom) {
+ height = winy / v2d->minzoom;
+ }
+ else if (zoom > v2d->maxzoom) {
+ height = winy / v2d->maxzoom;
+ }
+ }
+ }
+ else {
+ /* make sure sizes don't exceed that of the min/max sizes
+ * (even though we're not doing zoom clamping) */
+ CLAMP(width, v2d->min[0], v2d->max[0]);
+ CLAMP(height, v2d->min[1], v2d->max[1]);
+ }
+
+ /* check if we should restore aspect ratio (if view size changed) */
+ if (v2d->keepzoom & V2D_KEEPASPECT) {
+ bool do_x = false, do_y = false, do_cur /* , do_win */ /* UNUSED */;
+ float curRatio, winRatio;
+
+ /* when a window edge changes, the aspect ratio can't be used to
+ * find which is the best new 'cur' rect. that's why it stores 'old'
+ */
+ if (winx != v2d->oldwinx) {
+ do_x = true;
+ }
+ if (winy != v2d->oldwiny) {
+ do_y = true;
+ }
+
+ curRatio = height / width;
+ winRatio = winy / winx;
+
+ /* both sizes change (area/region maximized) */
+ if (do_x == do_y) {
+ if (do_x && do_y) {
+ /* here is 1,1 case, so all others must be 0,0 */
+ if (fabsf(winx - v2d->oldwinx) > fabsf(winy - v2d->oldwiny)) {
+ do_y = false;
+ }
+ else {
+ do_x = false;
+ }
+ }
+ else if (winRatio > curRatio) {
+ do_x = false;
+ }
+ else {
+ do_x = true;
+ }
+ }
+ do_cur = do_x;
+ /* do_win = do_y; */ /* UNUSED */
+
+ if (do_cur) {
+ if ((v2d->keeptot == V2D_KEEPTOT_STRICT) && (winx != v2d->oldwinx)) {
+ /* special exception for Outliner (and later channel-lists):
+ * - The view may be moved left to avoid contents being pushed out of view when view shrinks.
+ * - The keeptot code will make sure cur->xmin will not be less than tot->xmin (which cannot be allowed)
+ * - width is not adjusted for changed ratios here...
+ */
+ if (winx < v2d->oldwinx) {
+ float temp = v2d->oldwinx - winx;
+
+ cur->xmin -= temp;
+ cur->xmax -= temp;
+
+ /* width does not get modified, as keepaspect here is just set to make
+ * sure visible area adjusts to changing view shape!
+ */
+ }
+ }
+ else {
+ /* portrait window: correct for x */
+ width = height / winRatio;
+ }
+ }
+ else {
+ if ((v2d->keeptot == V2D_KEEPTOT_STRICT) && (winy != v2d->oldwiny)) {
+ /* special exception for Outliner (and later channel-lists):
+ * - Currently, no actions need to be taken here...
+ */
+
+ if (winy < v2d->oldwiny) {
+ float temp = v2d->oldwiny - winy;
+
+ if (v2d->align & V2D_ALIGN_NO_NEG_Y) {
+ cur->ymin -= temp;
+ cur->ymax -= temp;
+ }
+ else { /* Assume V2D_ALIGN_NO_POS_Y or combination */
+ cur->ymin += temp;
+ cur->ymax += temp;
+ }
+ }
+ }
+ else {
+ /* landscape window: correct for y */
+ height = width * winRatio;
+ }
+ }
+
+ /* store region size for next time */
+ v2d->oldwinx = (short)winx;
+ v2d->oldwiny = (short)winy;
+ }
+
+ /* Step 2: apply new sizes to cur rect,
+ * but need to take into account alignment settings here... */
+ if ((width != curwidth) || (height != curheight)) {
+ float temp, dh;
+
+ /* resize from centerpoint, unless otherwise specified */
+ if (width != curwidth) {
+ if (v2d->keepofs & V2D_LOCKOFS_X) {
+ cur->xmax += width - BLI_rctf_size_x(cur);
+ }
+ else if (v2d->keepofs & V2D_KEEPOFS_X) {
+ if (v2d->align & V2D_ALIGN_NO_POS_X) {
+ cur->xmin -= width - BLI_rctf_size_x(cur);
+ }
+ else {
+ cur->xmax += width - BLI_rctf_size_x(cur);
+ }
+ }
+ else {
+ temp = BLI_rctf_cent_x(cur);
+ dh = width * 0.5f;
+
+ cur->xmin = temp - dh;
+ cur->xmax = temp + dh;
+ }
+ }
+ if (height != curheight) {
+ if (v2d->keepofs & V2D_LOCKOFS_Y) {
+ cur->ymax += height - BLI_rctf_size_y(cur);
+ }
+ else if (v2d->keepofs & V2D_KEEPOFS_Y) {
+ if (v2d->align & V2D_ALIGN_NO_POS_Y) {
+ cur->ymin -= height - BLI_rctf_size_y(cur);
+ }
+ else {
+ cur->ymax += height - BLI_rctf_size_y(cur);
+ }
+ }
+ else {
+ temp = BLI_rctf_cent_y(cur);
+ dh = height * 0.5f;
+
+ cur->ymin = temp - dh;
+ cur->ymax = temp + dh;
+ }
+ }
+ }
+
+ /* Step 3: adjust so that it doesn't fall outside of bounds of 'tot' */
+ if (v2d->keeptot) {
+ float temp, diff;
+
+ /* recalculate extents of cur */
+ curwidth = BLI_rctf_size_x(cur);
+ curheight = BLI_rctf_size_y(cur);
+
+ /* width */
+ if ((curwidth > totwidth) &&
+ !(v2d->keepzoom & (V2D_KEEPZOOM | V2D_LOCKZOOM_X | V2D_LIMITZOOM))) {
+ /* if zoom doesn't have to be maintained, just clamp edges */
+ if (cur->xmin < tot->xmin) {
+ cur->xmin = tot->xmin;
+ }
+ if (cur->xmax > tot->xmax) {
+ cur->xmax = tot->xmax;
+ }
+ }
+ else if (v2d->keeptot == V2D_KEEPTOT_STRICT) {
+ /* This is an exception for the outliner (and later channel-lists, headers)
+ * - must clamp within tot rect (absolutely no excuses)
+ * --> therefore, cur->xmin must not be less than tot->xmin
+ */
+ if (cur->xmin < tot->xmin) {
+ /* move cur across so that it sits at minimum of tot */
+ temp = tot->xmin - cur->xmin;
+
+ cur->xmin += temp;
+ cur->xmax += temp;
+ }
+ else if (cur->xmax > tot->xmax) {
+ /* - only offset by difference of cur-xmax and tot-xmax if that would not move
+ * cur-xmin to lie past tot-xmin
+ * - otherwise, simply shift to tot-xmin???
+ */
+ temp = cur->xmax - tot->xmax;
+
+ if ((cur->xmin - temp) < tot->xmin) {
+ /* only offset by difference from cur-min and tot-min */
+ temp = cur->xmin - tot->xmin;
+
+ cur->xmin -= temp;
+ cur->xmax -= temp;
+ }
+ else {
+ cur->xmin -= temp;
+ cur->xmax -= temp;
+ }
+ }
+ }
+ else {
+ /* This here occurs when:
+ * - width too big, but maintaining zoom (i.e. widths cannot be changed)
+ * - 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
+ * (XXX - in the past, max was favored... if there are bugs, swap!)
+ */
+ if ((cur->xmin < tot->xmin) && (cur->xmax > tot->xmax)) {
+ /* outside boundaries on both sides,
+ * so take middle-point of tot, and place in balanced way */
+ temp = BLI_rctf_cent_x(tot);
+ diff = curwidth * 0.5f;
+
+ cur->xmin = temp - diff;
+ cur->xmax = temp + diff;
+ }
+ else if (cur->xmin < tot->xmin) {
+ /* move cur across so that it sits at minimum of tot */
+ temp = tot->xmin - cur->xmin;
+
+ cur->xmin += temp;
+ cur->xmax += temp;
+ }
+ else if (cur->xmax > tot->xmax) {
+ /* - only offset by difference of cur-xmax and tot-xmax if that would not move
+ * cur-xmin to lie past tot-xmin
+ * - otherwise, simply shift to tot-xmin???
+ */
+ temp = cur->xmax - tot->xmax;
+
+ if ((cur->xmin - temp) < tot->xmin) {
+ /* only offset by difference from cur-min and tot-min */
+ temp = cur->xmin - tot->xmin;
+
+ cur->xmin -= temp;
+ cur->xmax -= temp;
+ }
+ else {
+ cur->xmin -= temp;
+ cur->xmax -= temp;
+ }
+ }
+ }
+
+ /* height */
+ if ((curheight > totheight) &&
+ !(v2d->keepzoom & (V2D_KEEPZOOM | V2D_LOCKZOOM_Y | V2D_LIMITZOOM))) {
+ /* if zoom doesn't have to be maintained, just clamp edges */
+ if (cur->ymin < tot->ymin) {
+ cur->ymin = tot->ymin;
+ }
+ if (cur->ymax > tot->ymax) {
+ cur->ymax = tot->ymax;
+ }
+ }
+ else {
+ /* This here occurs when:
+ * - height too big, but maintaining zoom (i.e. heights cannot be changed)
+ * - 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
+ */
+ if ((cur->ymin < tot->ymin) && (cur->ymax > tot->ymax)) {
+ /* outside boundaries on both sides,
+ * so take middle-point of tot, and place in balanced way */
+ temp = BLI_rctf_cent_y(tot);
+ diff = curheight * 0.5f;
+
+ cur->ymin = temp - diff;
+ cur->ymax = temp + diff;
+ }
+ else if (cur->ymin < tot->ymin) {
+ /* there's still space remaining, so shift up */
+ temp = tot->ymin - cur->ymin;
+
+ cur->ymin += temp;
+ cur->ymax += temp;
+ }
+ else if (cur->ymax > tot->ymax) {
+ /* there's still space remaining, so shift down */
+ temp = cur->ymax - tot->ymax;
+
+ cur->ymin -= temp;
+ cur->ymax -= temp;
+ }
+ }
+ }
+
+ /* Step 4: Make sure alignment restrictions are respected */
+ if (v2d->align) {
+ /* If alignment flags are set (but keeptot is not), they must still be respected, as although
+ * they don't specify any particular bounds to stay within, they do define ranges which are
+ * invalid.
+ *
+ * Here, we only check to make sure that on each axis, the 'cur' rect doesn't stray into these
+ * invalid zones, otherwise we offset.
+ */
+
+ /* handle width - posx and negx flags are mutually exclusive, so watch out */
+ if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
+ /* width is in negative-x half */
+ if (v2d->cur.xmax > 0) {
+ v2d->cur.xmin -= v2d->cur.xmax;
+ v2d->cur.xmax = 0.0f;
+ }
+ }
+ else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
+ /* width is in positive-x half */
+ if (v2d->cur.xmin < 0) {
+ v2d->cur.xmax -= v2d->cur.xmin;
+ v2d->cur.xmin = 0.0f;
+ }
+ }
+
+ /* handle height - posx and negx flags are mutually exclusive, so watch out */
+ if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
+ /* height is in negative-y half */
+ if (v2d->cur.ymax > 0) {
+ v2d->cur.ymin -= v2d->cur.ymax;
+ v2d->cur.ymax = 0.0f;
+ }
+ }
+ else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
+ /* height is in positive-y half */
+ if (v2d->cur.ymin < 0) {
+ v2d->cur.ymax -= v2d->cur.ymin;
+ v2d->cur.ymin = 0.0f;
+ }
+ }
+ }
+
+ /* set masks */
+ view2d_masks(v2d, mask_scrollers, NULL);
}
void UI_view2d_curRect_validate(View2D *v2d)
{
- ui_view2d_curRect_validate_resize(v2d, 0, 1);
+ ui_view2d_curRect_validate_resize(v2d, 0, 1);
}
/* ------------------ */
@@ -850,117 +844,116 @@ 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;
-
- /* don't continue if no view syncing to be done */
- if ((v2dcur->flag & (V2D_VIEWSYNC_SCREEN_TIME | V2D_VIEWSYNC_AREA_VERTICAL)) == 0) {
- return;
- }
-
- /* 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) {
- /* don't operate on self */
- if (v2dcur != &ar->v2d) {
- /* only if view has vertical locks enabled */
- if (ar->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;
- }
- else { /* V2D_LOCK_SET */
- /* active must copy others */
- v2dcur->cur.ymin = ar->v2d.cur.ymin;
- v2dcur->cur.ymax = ar->v2d.cur.ymax;
- }
-
- /* region possibly changed, so refresh */
- ED_region_tag_redraw_no_rebuild(ar);
- }
- }
- }
- }
-
- /* 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) {
- /* don't operate on self */
- if (v2dcur != &ar->v2d) {
- /* only if view has horizontal locks enabled */
- if (ar->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;
- }
- else { /* V2D_LOCK_SET */
- /* active must copy others */
- v2dcur->cur.xmin = ar->v2d.cur.xmin;
- v2dcur->cur.xmax = ar->v2d.cur.xmax;
- }
-
- /* region possibly changed, so refresh */
- ED_region_tag_redraw_no_rebuild(ar);
- }
- }
- }
- }
- }
+ ScrArea *sa;
+ ARegion *ar;
+
+ /* don't continue if no view syncing to be done */
+ if ((v2dcur->flag & (V2D_VIEWSYNC_SCREEN_TIME | V2D_VIEWSYNC_AREA_VERTICAL)) == 0) {
+ return;
+ }
+
+ /* 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) {
+ /* don't operate on self */
+ if (v2dcur != &ar->v2d) {
+ /* only if view has vertical locks enabled */
+ if (ar->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;
+ }
+ else { /* V2D_LOCK_SET */
+ /* active must copy others */
+ v2dcur->cur.ymin = ar->v2d.cur.ymin;
+ v2dcur->cur.ymax = ar->v2d.cur.ymax;
+ }
+
+ /* region possibly changed, so refresh */
+ ED_region_tag_redraw_no_rebuild(ar);
+ }
+ }
+ }
+ }
+
+ /* 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) {
+ /* don't operate on self */
+ if (v2dcur != &ar->v2d) {
+ /* only if view has horizontal locks enabled */
+ if (ar->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;
+ }
+ else { /* V2D_LOCK_SET */
+ /* active must copy others */
+ v2dcur->cur.xmin = ar->v2d.cur.xmin;
+ v2dcur->cur.xmax = ar->v2d.cur.xmax;
+ }
+
+ /* region possibly changed, so refresh */
+ ED_region_tag_redraw_no_rebuild(ar);
+ }
+ }
+ }
+ }
+ }
}
-
/**
* Restore 'cur' rect to standard orientation (i.e. optimal maximum view of tot)
* This does not take into account if zooming the view on an axis will improve the view (if allowed)
*/
void UI_view2d_curRect_reset(View2D *v2d)
{
- float width, height;
-
- /* assume width and height of 'cur' rect by default, should be same size as mask */
- width = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
- height = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
-
- /* handle width - posx and negx flags are mutually exclusive, so watch out */
- if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
- /* width is in negative-x half */
- v2d->cur.xmin = -width;
- v2d->cur.xmax = 0.0f;
- }
- else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
- /* width is in positive-x half */
- v2d->cur.xmin = 0.0f;
- v2d->cur.xmax = width;
- }
- else {
- /* width is centered around (x == 0) */
- const float dx = width / 2.0f;
-
- v2d->cur.xmin = -dx;
- v2d->cur.xmax = dx;
- }
-
- /* handle height - posx and negx flags are mutually exclusive, so watch out */
- if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
- /* height is in negative-y half */
- v2d->cur.ymin = -height;
- v2d->cur.ymax = 0.0f;
- }
- else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
- /* height is in positive-y half */
- v2d->cur.ymin = 0.0f;
- v2d->cur.ymax = height;
- }
- else {
- /* height is centered around (y == 0) */
- const float dy = height / 2.0f;
-
- v2d->cur.ymin = -dy;
- v2d->cur.ymax = dy;
- }
+ float width, height;
+
+ /* assume width and height of 'cur' rect by default, should be same size as mask */
+ width = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
+ height = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
+
+ /* handle width - posx and negx flags are mutually exclusive, so watch out */
+ if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
+ /* width is in negative-x half */
+ v2d->cur.xmin = -width;
+ v2d->cur.xmax = 0.0f;
+ }
+ else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
+ /* width is in positive-x half */
+ v2d->cur.xmin = 0.0f;
+ v2d->cur.xmax = width;
+ }
+ else {
+ /* width is centered around (x == 0) */
+ const float dx = width / 2.0f;
+
+ v2d->cur.xmin = -dx;
+ v2d->cur.xmax = dx;
+ }
+
+ /* handle height - posx and negx flags are mutually exclusive, so watch out */
+ if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
+ /* height is in negative-y half */
+ v2d->cur.ymin = -height;
+ v2d->cur.ymax = 0.0f;
+ }
+ else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
+ /* height is in positive-y half */
+ v2d->cur.ymin = 0.0f;
+ v2d->cur.ymax = height;
+ }
+ else {
+ /* height is centered around (y == 0) */
+ const float dy = height / 2.0f;
+
+ v2d->cur.ymin = -dy;
+ v2d->cur.ymax = dy;
+ }
}
/* ------------------ */
@@ -968,147 +961,148 @@ 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", (void *)v2d, width, height); // XXX temp debug info
- }
- return;
- }
-
- /* handle width - posx and negx flags are mutually exclusive, so watch out */
- if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
- /* width is in negative-x half */
- v2d->tot.xmin = (float)-width;
- v2d->tot.xmax = 0.0f;
- }
- else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
- /* width is in positive-x half */
- v2d->tot.xmin = 0.0f;
- v2d->tot.xmax = (float)width;
- }
- else {
- /* width is centered around (x == 0) */
- const float dx = (float)width / 2.0f;
-
- v2d->tot.xmin = -dx;
- v2d->tot.xmax = dx;
- }
-
- /* handle height - posx and negx flags are mutually exclusive, so watch out */
- if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
- /* height is in negative-y half */
- v2d->tot.ymin = (float)-height;
- v2d->tot.ymax = 0.0f;
- }
- else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
- /* height is in positive-y half */
- v2d->tot.ymin = 0.0f;
- v2d->tot.ymax = (float)height;
- }
- else {
- /* height is centered around (y == 0) */
- const float dy = (float)height / 2.0f;
-
- v2d->tot.ymin = -dy;
- v2d->tot.ymax = dy;
- }
-
- /* make sure that 'cur' rect is in a valid state as a result of these changes */
- ui_view2d_curRect_validate_resize(v2d, resize, 1);
-
+ // 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",
+ (void *)v2d,
+ width,
+ height); // XXX temp debug info
+ }
+ return;
+ }
+
+ /* handle width - posx and negx flags are mutually exclusive, so watch out */
+ if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
+ /* width is in negative-x half */
+ v2d->tot.xmin = (float)-width;
+ v2d->tot.xmax = 0.0f;
+ }
+ else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
+ /* width is in positive-x half */
+ v2d->tot.xmin = 0.0f;
+ v2d->tot.xmax = (float)width;
+ }
+ else {
+ /* width is centered around (x == 0) */
+ const float dx = (float)width / 2.0f;
+
+ v2d->tot.xmin = -dx;
+ v2d->tot.xmax = dx;
+ }
+
+ /* handle height - posx and negx flags are mutually exclusive, so watch out */
+ if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
+ /* height is in negative-y half */
+ v2d->tot.ymin = (float)-height;
+ v2d->tot.ymax = 0.0f;
+ }
+ else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
+ /* height is in positive-y half */
+ v2d->tot.ymin = 0.0f;
+ v2d->tot.ymax = (float)height;
+ }
+ else {
+ /* height is centered around (y == 0) */
+ const float dy = (float)height / 2.0f;
+
+ v2d->tot.ymin = -dy;
+ v2d->tot.ymax = dy;
+ }
+
+ /* make sure that 'cur' rect is in a valid state as a result of these changes */
+ ui_view2d_curRect_validate_resize(v2d, resize, 1);
}
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);
+ int scroll = view2d_scroll_mapped(v2d->scroll);
- /* 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, 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);
+ }
}
bool UI_view2d_tab_set(View2D *v2d, int tab)
{
- float default_offset[2] = {0.0f, 0.0f};
- float *offset, *new_offset;
- bool changed = false;
+ float default_offset[2] = {0.0f, 0.0f};
+ float *offset, *new_offset;
+ bool changed = false;
- /* if tab changed, change offset */
- if (tab != v2d->tab_cur && v2d->tab_offset) {
- if (tab < v2d->tab_num) {
- offset = &v2d->tab_offset[tab * 2];
- }
- else {
- offset = default_offset;
- }
+ /* if tab changed, change offset */
+ if (tab != v2d->tab_cur && v2d->tab_offset) {
+ if (tab < v2d->tab_num) {
+ offset = &v2d->tab_offset[tab * 2];
+ }
+ else {
+ offset = default_offset;
+ }
- v2d->cur.xmax += offset[0] - v2d->cur.xmin;
- v2d->cur.xmin = offset[0];
+ v2d->cur.xmax += offset[0] - v2d->cur.xmin;
+ v2d->cur.xmin = offset[0];
- v2d->cur.ymin += offset[1] - v2d->cur.ymax;
- v2d->cur.ymax = offset[1];
+ v2d->cur.ymin += offset[1] - v2d->cur.ymax;
+ v2d->cur.ymax = offset[1];
- /* validation should happen in subsequent totRect_set */
+ /* validation should happen in subsequent totRect_set */
- changed = true;
- }
+ changed = true;
+ }
- /* resize array if needed */
- if (tab >= v2d->tab_num) {
- new_offset = MEM_callocN(sizeof(float) * (tab + 1) * 2, "view2d tab offset");
+ /* resize array if needed */
+ if (tab >= v2d->tab_num) {
+ new_offset = MEM_callocN(sizeof(float) * (tab + 1) * 2, "view2d tab offset");
- if (v2d->tab_offset) {
- memcpy(new_offset, v2d->tab_offset, sizeof(float) * v2d->tab_num * 2);
- MEM_freeN(v2d->tab_offset);
- }
+ if (v2d->tab_offset) {
+ memcpy(new_offset, v2d->tab_offset, sizeof(float) * v2d->tab_num * 2);
+ MEM_freeN(v2d->tab_offset);
+ }
- v2d->tab_offset = new_offset;
- v2d->tab_num = tab + 1;
- }
+ v2d->tab_offset = new_offset;
+ v2d->tab_num = tab + 1;
+ }
- /* set current tab and offset */
- v2d->tab_cur = tab;
- v2d->tab_offset[2 * tab + 0] = v2d->cur.xmin;
- v2d->tab_offset[2 * tab + 1] = v2d->cur.ymax;
+ /* set current tab and offset */
+ v2d->tab_cur = tab;
+ v2d->tab_offset[2 * tab + 0] = v2d->cur.xmin;
+ v2d->tab_offset[2 * tab + 1] = v2d->cur.ymax;
- return changed;
+ return changed;
}
void UI_view2d_zoom_cache_reset(void)
{
- /* TODO(sergey): This way we avoid threading conflict with sequencer rendering
- * text strip. But ideally we want to make glyph cache to be fully safe
- * for threading.
- */
- if (G.is_rendering) {
- return;
- }
- /* While scaling we can accumulate fonts at many sizes (~20 or so).
- * Not an issue with embedded font, but can use over 500Mb with i18n ones! See [#38244]. */
-
- /* note: only some views draw text, we could check for this case to avoid clearning cache */
- BLF_cache_clear();
+ /* TODO(sergey): This way we avoid threading conflict with sequencer rendering
+ * text strip. But ideally we want to make glyph cache to be fully safe
+ * for threading.
+ */
+ if (G.is_rendering) {
+ return;
+ }
+ /* While scaling we can accumulate fonts at many sizes (~20 or so).
+ * Not an issue with embedded font, but can use over 500Mb with i18n ones! See [#38244]. */
+
+ /* note: only some views draw text, we could check for this case to avoid clearning cache */
+ BLF_cache_clear();
}
/* *********************************************************************** */
@@ -1117,74 +1111,74 @@ void UI_view2d_zoom_cache_reset(void)
/* mapping function to ensure 'cur' draws extended over the area where sliders are */
static void view2d_map_cur_using_mask(View2D *v2d, rctf *r_curmasked)
{
- *r_curmasked = v2d->cur;
-
- if (view2d_scroll_mapped(v2d->scroll)) {
- float sizex = BLI_rcti_size_x(&v2d->mask);
- float sizey = BLI_rcti_size_y(&v2d->mask);
-
- /* prevent tiny or narrow regions to get
- * invalid coordinates - mask can get negative even... */
- if (sizex > 0.0f && sizey > 0.0f) {
- float dx = BLI_rctf_size_x(&v2d->cur) / (sizex + 1);
- float dy = BLI_rctf_size_y(&v2d->cur) / (sizey + 1);
-
- if (v2d->mask.xmin != 0) {
- r_curmasked->xmin -= dx * (float)v2d->mask.xmin;
- }
- if (v2d->mask.xmax + 1 != v2d->winx) {
- r_curmasked->xmax += dx * (float)(v2d->winx - v2d->mask.xmax - 1);
- }
-
- if (v2d->mask.ymin != 0) {
- r_curmasked->ymin -= dy * (float)v2d->mask.ymin;
- }
- if (v2d->mask.ymax + 1 != v2d->winy) {
- r_curmasked->ymax += dy * (float)(v2d->winy - v2d->mask.ymax - 1);
- }
- }
- }
+ *r_curmasked = v2d->cur;
+
+ if (view2d_scroll_mapped(v2d->scroll)) {
+ float sizex = BLI_rcti_size_x(&v2d->mask);
+ float sizey = BLI_rcti_size_y(&v2d->mask);
+
+ /* prevent tiny or narrow regions to get
+ * invalid coordinates - mask can get negative even... */
+ if (sizex > 0.0f && sizey > 0.0f) {
+ float dx = BLI_rctf_size_x(&v2d->cur) / (sizex + 1);
+ float dy = BLI_rctf_size_y(&v2d->cur) / (sizey + 1);
+
+ if (v2d->mask.xmin != 0) {
+ r_curmasked->xmin -= dx * (float)v2d->mask.xmin;
+ }
+ if (v2d->mask.xmax + 1 != v2d->winx) {
+ r_curmasked->xmax += dx * (float)(v2d->winx - v2d->mask.xmax - 1);
+ }
+
+ if (v2d->mask.ymin != 0) {
+ r_curmasked->ymin -= dy * (float)v2d->mask.ymin;
+ }
+ if (v2d->mask.ymax + 1 != v2d->winy) {
+ r_curmasked->ymax += dy * (float)(v2d->winy - v2d->mask.ymax - 1);
+ }
+ }
+ }
}
/* Set view matrices to use 'cur' rect as viewing frame for View2D drawing */
void UI_view2d_view_ortho(View2D *v2d)
{
- rctf curmasked;
- const int sizex = BLI_rcti_size_x(&v2d->mask);
- const int sizey = BLI_rcti_size_y(&v2d->mask);
- const float eps = 0.001f;
- float xofs = 0.0f, yofs = 0.0f;
-
- /* pixel offsets (-GLA_PIXEL_OFS) are needed to get 1:1 correspondence with pixels for smooth UI drawing,
- * but only applied where requested
- */
- /* XXX brecht: instead of zero at least use a tiny offset, otherwise
- * pixel rounding is effectively random due to float inaccuracy */
- if (sizex > 0) {
- xofs = eps * BLI_rctf_size_x(&v2d->cur) / sizex;
- }
- if (sizey > 0) {
- yofs = eps * BLI_rctf_size_y(&v2d->cur) / sizey;
- }
-
- /* apply mask-based adjustments to cur rect (due to scrollers),
- * to eliminate scaling artifacts */
- view2d_map_cur_using_mask(v2d, &curmasked);
-
- BLI_rctf_translate(&curmasked, -xofs, -yofs);
-
- /* XXX ton: this flag set by outliner, for icons */
- if (v2d->flag & V2D_PIXELOFS_X) {
- curmasked.xmin = floorf(curmasked.xmin) - (eps + xofs);
- curmasked.xmax = floorf(curmasked.xmax) - (eps + xofs);
- }
- if (v2d->flag & V2D_PIXELOFS_Y) {
- curmasked.ymin = floorf(curmasked.ymin) - (eps + yofs);
- curmasked.ymax = floorf(curmasked.ymax) - (eps + yofs);
- }
-
- /* set matrix on all appropriate axes */
- wmOrtho2(curmasked.xmin, curmasked.xmax, curmasked.ymin, curmasked.ymax);
+ rctf curmasked;
+ const int sizex = BLI_rcti_size_x(&v2d->mask);
+ const int sizey = BLI_rcti_size_y(&v2d->mask);
+ const float eps = 0.001f;
+ float xofs = 0.0f, yofs = 0.0f;
+
+ /* pixel offsets (-GLA_PIXEL_OFS) are needed to get 1:1 correspondence with pixels for smooth UI drawing,
+ * but only applied where requested
+ */
+ /* XXX brecht: instead of zero at least use a tiny offset, otherwise
+ * pixel rounding is effectively random due to float inaccuracy */
+ if (sizex > 0) {
+ xofs = eps * BLI_rctf_size_x(&v2d->cur) / sizex;
+ }
+ if (sizey > 0) {
+ yofs = eps * BLI_rctf_size_y(&v2d->cur) / sizey;
+ }
+
+ /* apply mask-based adjustments to cur rect (due to scrollers),
+ * to eliminate scaling artifacts */
+ view2d_map_cur_using_mask(v2d, &curmasked);
+
+ BLI_rctf_translate(&curmasked, -xofs, -yofs);
+
+ /* XXX ton: this flag set by outliner, for icons */
+ if (v2d->flag & V2D_PIXELOFS_X) {
+ curmasked.xmin = floorf(curmasked.xmin) - (eps + xofs);
+ curmasked.xmax = floorf(curmasked.xmax) - (eps + xofs);
+ }
+ if (v2d->flag & V2D_PIXELOFS_Y) {
+ curmasked.ymin = floorf(curmasked.ymin) - (eps + yofs);
+ curmasked.ymax = floorf(curmasked.ymax) - (eps + yofs);
+ }
+
+ /* set matrix on all appropriate axes */
+ wmOrtho2(curmasked.xmin, curmasked.xmax, curmasked.ymin, curmasked.ymax);
}
/**
@@ -1194,41 +1188,40 @@ void UI_view2d_view_ortho(View2D *v2d)
*/
void UI_view2d_view_orthoSpecial(ARegion *ar, View2D *v2d, const bool xaxis)
{
- rctf curmasked;
- float xofs, yofs;
-
- /* pixel offsets (-GLA_PIXEL_OFS) are needed to get 1:1 correspondence with pixels for smooth UI drawing,
- * but only applied where requested
- */
- /* XXX temp (ton) */
- xofs = 0.0f; // (v2d->flag & V2D_PIXELOFS_X) ? GLA_PIXEL_OFS : 0.0f;
- yofs = 0.0f; // (v2d->flag & V2D_PIXELOFS_Y) ? GLA_PIXEL_OFS : 0.0f;
-
- /* apply mask-based adjustments to cur rect (due to scrollers),
- * to eliminate scaling artifacts */
- view2d_map_cur_using_mask(v2d, &curmasked);
-
- /* only set matrix with 'cur' coordinates on relevant axes */
- if (xaxis) {
- wmOrtho2(curmasked.xmin - xofs, curmasked.xmax - xofs, -yofs, ar->winy - yofs);
- }
- else {
- wmOrtho2(-xofs, ar->winx - xofs, curmasked.ymin - yofs, curmasked.ymax - yofs);
- }
+ rctf curmasked;
+ float xofs, yofs;
+
+ /* pixel offsets (-GLA_PIXEL_OFS) are needed to get 1:1 correspondence with pixels for smooth UI drawing,
+ * but only applied where requested
+ */
+ /* XXX temp (ton) */
+ xofs = 0.0f; // (v2d->flag & V2D_PIXELOFS_X) ? GLA_PIXEL_OFS : 0.0f;
+ yofs = 0.0f; // (v2d->flag & V2D_PIXELOFS_Y) ? GLA_PIXEL_OFS : 0.0f;
+
+ /* apply mask-based adjustments to cur rect (due to scrollers),
+ * to eliminate scaling artifacts */
+ view2d_map_cur_using_mask(v2d, &curmasked);
+
+ /* only set matrix with 'cur' coordinates on relevant axes */
+ if (xaxis) {
+ wmOrtho2(curmasked.xmin - xofs, curmasked.xmax - xofs, -yofs, ar->winy - yofs);
+ }
+ else {
+ wmOrtho2(-xofs, ar->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 *ar = CTX_wm_region(C);
+ int width = BLI_rcti_size_x(&ar->winrct) + 1;
+ int height = BLI_rcti_size_y(&ar->winrct) + 1;
- wmOrtho2(0.0f, (float)width, 0.0f, (float)height);
- GPU_matrix_identity_set();
+ wmOrtho2(0.0f, (float)width, 0.0f, (float)height);
+ GPU_matrix_identity_set();
- // ED_region_pixelspace(CTX_wm_region(C));
+ // ED_region_pixelspace(CTX_wm_region(C));
}
/* *********************************************************************** */
@@ -1236,9 +1229,9 @@ void UI_view2d_view_restore(const bContext *C)
/* View2DGrid is typedef'd in UI_view2d.h */
struct View2DGrid {
- float dx, dy; /* stepsize (in pixels) between gridlines */
- float startx, starty; /* initial coordinates to start drawing grid from */
- int powerx, powery; /* step as power of 10 */
+ float dx, dy; /* stepsize (in pixels) between gridlines */
+ float startx, starty; /* initial coordinates to start drawing grid from */
+ int powerx, powery; /* step as power of 10 */
};
/* --------------- */
@@ -1246,61 +1239,61 @@ struct View2DGrid {
/* try to write step as a power of 10 */
static void step_to_grid(float *step, const int unit, int *r_power)
{
- const float loga = (float)log10(*step);
- float rem;
-
- int power = (int)(loga);
-
- rem = loga - power;
- rem = (float)pow(10.0, rem);
-
- if (loga < 0.0f) {
- if (rem < 0.2f) {
- rem = 0.2f;
- }
- else if (rem < 0.5f) {
- rem = 0.5f;
- }
- else {
- rem = 1.0f;
- }
-
- *step = rem * (float)pow(10.0, power);
-
- /* for frames, we want 1.0 frame intervals only */
- if (unit == V2D_UNIT_FRAMES) {
- rem = 1.0f;
- /* use 2 since there are grid lines drawn in between,
- * this way to get 1 line per frame */
- *step = 2.0f;
- }
-
- /* prevents printing 1.0 2.0 3.0 etc */
- if (rem == 1.0f) {
- power++;
- }
- }
- else {
- if (rem < 2.0f) {
- rem = 2.0f;
- }
- else if (rem < 5.0f) {
- rem = 5.0f;
- }
- else {
- rem = 10.0f;
- }
-
- *step = rem * (float)pow(10.0, power);
-
- power++;
- /* prevents printing 1.0, 2.0, 3.0, etc. */
- if (rem == 10.0f) {
- power++;
- }
- }
-
- *r_power = power;
+ const float loga = (float)log10(*step);
+ float rem;
+
+ int power = (int)(loga);
+
+ rem = loga - power;
+ rem = (float)pow(10.0, rem);
+
+ if (loga < 0.0f) {
+ if (rem < 0.2f) {
+ rem = 0.2f;
+ }
+ else if (rem < 0.5f) {
+ rem = 0.5f;
+ }
+ else {
+ rem = 1.0f;
+ }
+
+ *step = rem * (float)pow(10.0, power);
+
+ /* for frames, we want 1.0 frame intervals only */
+ if (unit == V2D_UNIT_FRAMES) {
+ rem = 1.0f;
+ /* use 2 since there are grid lines drawn in between,
+ * this way to get 1 line per frame */
+ *step = 2.0f;
+ }
+
+ /* prevents printing 1.0 2.0 3.0 etc */
+ if (rem == 1.0f) {
+ power++;
+ }
+ }
+ else {
+ if (rem < 2.0f) {
+ rem = 2.0f;
+ }
+ else if (rem < 5.0f) {
+ rem = 5.0f;
+ }
+ else {
+ rem = 10.0f;
+ }
+
+ *step = rem * (float)pow(10.0, power);
+
+ power++;
+ /* prevents printing 1.0, 2.0, 3.0, etc. */
+ if (rem == 10.0f) {
+ power++;
+ }
+ }
+
+ *r_power = power;
}
/**
@@ -1317,540 +1310,539 @@ static void step_to_grid(float *step, const int unit, int *r_power)
* - winx = width of region we're drawing to, note: not used but keeping for completeness.
* - winy = height of region we're drawing into
*/
-View2DGrid *UI_view2d_grid_calc(
- Scene *scene, View2D *v2d,
- short xunits, short xclamp, short yunits, short yclamp, int UNUSED(winx), int winy)
+View2DGrid *UI_view2d_grid_calc(Scene *scene,
+ View2D *v2d,
+ short xunits,
+ short xclamp,
+ short yunits,
+ short yclamp,
+ int UNUSED(winx),
+ int winy)
{
- View2DGrid *grid;
- float space, seconddiv;
-
- /* check that there are at least some workable args */
- if (ELEM(V2D_ARG_DUMMY, xunits, xclamp) && ELEM(V2D_ARG_DUMMY, yunits, yclamp)) {
- return NULL;
- }
-
- /* grid here is allocated... */
- grid = MEM_callocN(sizeof(View2DGrid), "View2DGrid");
-
- /* rule: gridstep is minimal GRIDSTEP pixels */
- if (xunits == V2D_UNIT_SECONDS) {
- seconddiv = (float)(0.01 * FPS);
- }
- else {
- seconddiv = 1.0f;
- }
-
- /* calculate x-axis grid scale (only if both args are valid) */
- if (ELEM(V2D_ARG_DUMMY, xunits, xclamp) == 0) {
- space = BLI_rctf_size_x(&v2d->cur);
-
- if (space != 0.0f) {
- const float pixels = (float)BLI_rcti_size_x(&v2d->mask);
- if (pixels != 0.0f) {
- grid->dx = (U.v2d_min_gridsize * UI_DPI_FAC * space) / (seconddiv * pixels);
- step_to_grid(&grid->dx, xunits, &grid->powerx);
- grid->dx *= seconddiv;
- }
- }
-
- if (xclamp == V2D_GRID_CLAMP) {
- CLAMP_MIN(grid->dx, 0.1f);
- CLAMP_MIN(grid->powerx, 0);
- grid->powerx -= 2;
- }
- }
-
- /* calculate y-axis grid scale (only if both args are valid) */
- if (ELEM(V2D_ARG_DUMMY, yunits, yclamp) == 0) {
- space = BLI_rctf_size_y(&v2d->cur);
- if (space != 0.0f) {
- const float pixels = (float)winy;
- if (pixels != 0.0f) {
- grid->dy = U.v2d_min_gridsize * UI_DPI_FAC * space / pixels;
- step_to_grid(&grid->dy, yunits, &grid->powery);
- }
- }
-
- if (yclamp == V2D_GRID_CLAMP) {
- CLAMP_MIN(grid->dy, 1.0f);
- CLAMP_MIN(grid->powery, 1);
- }
- }
-
- /* calculate start position */
- if (ELEM(V2D_ARG_DUMMY, xunits, xclamp) == 0) {
- grid->startx = seconddiv * (v2d->cur.xmin / seconddiv - (float)fmod(v2d->cur.xmin / seconddiv, grid->dx / seconddiv));
- if (v2d->cur.xmin < 0.0f) {
- grid->startx -= grid->dx;
- }
- }
- else {
- grid->startx = v2d->cur.xmin;
- }
-
- if (ELEM(V2D_ARG_DUMMY, yunits, yclamp) == 0) {
- grid->starty = (v2d->cur.ymin - (float)fmod(v2d->cur.ymin, grid->dy));
- if (v2d->cur.ymin < 0.0f) {
- grid->starty -= grid->dy;
- }
- }
- else {
- grid->starty = v2d->cur.ymin;
- }
-
- return grid;
+ View2DGrid *grid;
+ float space, seconddiv;
+
+ /* check that there are at least some workable args */
+ if (ELEM(V2D_ARG_DUMMY, xunits, xclamp) && ELEM(V2D_ARG_DUMMY, yunits, yclamp)) {
+ return NULL;
+ }
+
+ /* grid here is allocated... */
+ grid = MEM_callocN(sizeof(View2DGrid), "View2DGrid");
+
+ /* rule: gridstep is minimal GRIDSTEP pixels */
+ if (xunits == V2D_UNIT_SECONDS) {
+ seconddiv = (float)(0.01 * FPS);
+ }
+ else {
+ seconddiv = 1.0f;
+ }
+
+ /* calculate x-axis grid scale (only if both args are valid) */
+ if (ELEM(V2D_ARG_DUMMY, xunits, xclamp) == 0) {
+ space = BLI_rctf_size_x(&v2d->cur);
+
+ if (space != 0.0f) {
+ const float pixels = (float)BLI_rcti_size_x(&v2d->mask);
+ if (pixels != 0.0f) {
+ grid->dx = (U.v2d_min_gridsize * UI_DPI_FAC * space) / (seconddiv * pixels);
+ step_to_grid(&grid->dx, xunits, &grid->powerx);
+ grid->dx *= seconddiv;
+ }
+ }
+
+ if (xclamp == V2D_GRID_CLAMP) {
+ CLAMP_MIN(grid->dx, 0.1f);
+ CLAMP_MIN(grid->powerx, 0);
+ grid->powerx -= 2;
+ }
+ }
+
+ /* calculate y-axis grid scale (only if both args are valid) */
+ if (ELEM(V2D_ARG_DUMMY, yunits, yclamp) == 0) {
+ space = BLI_rctf_size_y(&v2d->cur);
+ if (space != 0.0f) {
+ const float pixels = (float)winy;
+ if (pixels != 0.0f) {
+ grid->dy = U.v2d_min_gridsize * UI_DPI_FAC * space / pixels;
+ step_to_grid(&grid->dy, yunits, &grid->powery);
+ }
+ }
+
+ if (yclamp == V2D_GRID_CLAMP) {
+ CLAMP_MIN(grid->dy, 1.0f);
+ CLAMP_MIN(grid->powery, 1);
+ }
+ }
+
+ /* calculate start position */
+ if (ELEM(V2D_ARG_DUMMY, xunits, xclamp) == 0) {
+ grid->startx = seconddiv * (v2d->cur.xmin / seconddiv -
+ (float)fmod(v2d->cur.xmin / seconddiv, grid->dx / seconddiv));
+ if (v2d->cur.xmin < 0.0f) {
+ grid->startx -= grid->dx;
+ }
+ }
+ else {
+ grid->startx = v2d->cur.xmin;
+ }
+
+ if (ELEM(V2D_ARG_DUMMY, yunits, yclamp) == 0) {
+ grid->starty = (v2d->cur.ymin - (float)fmod(v2d->cur.ymin, grid->dy));
+ if (v2d->cur.ymin < 0.0f) {
+ grid->starty -= grid->dy;
+ }
+ }
+ else {
+ grid->starty = v2d->cur.ymin;
+ }
+
+ return grid;
}
/* Draw gridlines in the given 2d-region */
void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
{
- float vec1[2], vec2[2];
- int a, step;
- int vertical_minor_step = (BLI_rcti_size_x(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC);
- int horizontal_major_step = (BLI_rcti_size_y(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC);
- uchar grid_line_color[3];
-
- /* check for grid first, as it may not exist */
- if (grid == NULL) {
- return;
- }
-
- /* Count the needed vertices for the gridlines */
- unsigned vertex_count = 0;
- if (flag & V2D_VERTICAL_LINES) {
- /* vertical lines */
- vertex_count += 2 * vertical_minor_step; /* minor gridlines */
- vertex_count += 2 * (vertical_minor_step + 2); /* major gridlines */
- }
- if (flag & V2D_HORIZONTAL_LINES) {
- /* horizontal lines */
- vertex_count += 2 * (horizontal_major_step + 1); /* major gridlines */
-
- /* fine lines */
- if (flag & V2D_HORIZONTAL_FINELINES) {
- vertex_count += 2 * (horizontal_major_step + 1);
- }
- }
- /* axes */
- if (flag & V2D_HORIZONTAL_AXIS) {
- vertex_count += 2;
- }
- if (flag & V2D_VERTICAL_AXIS) {
- vertex_count += 2;
- }
-
- /* If there is nothing to render, exit early */
- if (vertex_count == 0) {
- return;
- }
-
- GPUVertFormat *format = immVertexFormat();
- 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_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- immBegin(GPU_PRIM_LINES, vertex_count);
-
- /* vertical lines */
- if (flag & V2D_VERTICAL_LINES) {
- /* initialize initial settings */
- vec1[0] = vec2[0] = grid->startx;
- vec1[1] = grid->starty;
- vec2[1] = v2d->cur.ymax;
-
- /* minor gridlines */
- step = vertical_minor_step;
- if (step != 0) {
- UI_GetThemeColor3ubv(TH_GRID, grid_line_color);
-
- for (a = 0; a < step; a++) {
- immAttrSkip(color);
- immVertex2fv(pos, vec1);
- immAttr3ubv(color, grid_line_color);
- immVertex2fv(pos, vec2);
-
- vec2[0] = vec1[0] += grid->dx;
- }
- }
-
- /* major gridlines */
- vec2[0] = vec1[0] -= 0.5f * grid->dx;
-
- UI_GetThemeColorShade3ubv(TH_GRID, 16, grid_line_color);
-
- step++;
- for (a = 0; a <= step; a++) {
- immAttrSkip(color);
- immVertex2fv(pos, vec1);
- immAttr3ubv(color, grid_line_color);
- immVertex2fv(pos, vec2);
-
- vec2[0] = vec1[0] -= grid->dx;
- }
- }
-
- /* horizontal lines */
- if (flag & V2D_HORIZONTAL_LINES) {
- /* only major gridlines */
- vec1[1] = vec2[1] = grid->starty;
- vec1[0] = grid->startx;
- vec2[0] = v2d->cur.xmax;
-
- step = horizontal_major_step;
-
- UI_GetThemeColor3ubv(TH_GRID, grid_line_color);
-
- for (a = 0; a <= step; a++) {
- immAttrSkip(color);
- immVertex2fv(pos, vec1);
- immAttr3ubv(color, grid_line_color);
- immVertex2fv(pos, vec2);
-
- vec2[1] = vec1[1] += grid->dy;
- }
-
- /* fine grid lines */
- vec2[1] = vec1[1] -= 0.5f * grid->dy;
- step++;
-
- if (flag & V2D_HORIZONTAL_FINELINES) {
- UI_GetThemeColorShade3ubv(TH_GRID, 16, grid_line_color);
- for (a = 0; a < step; a++) {
- immAttrSkip(color);
- immVertex2fv(pos, vec1);
- immAttr3ubv(color, grid_line_color);
- immVertex2fv(pos, vec2);
-
- vec2[1] = vec1[1] -= grid->dy;
- }
- }
- }
-
- /* Axes are drawn as darker lines */
- UI_GetThemeColorShade3ubv(TH_GRID, -50, grid_line_color);
-
- /* horizontal axis */
- if (flag & V2D_HORIZONTAL_AXIS) {
- vec1[0] = v2d->cur.xmin;
- vec2[0] = v2d->cur.xmax;
- vec1[1] = vec2[1] = 0.0f;
-
- immAttrSkip(color);
- immVertex2fv(pos, vec1);
- immAttr3ubv(color, grid_line_color);
- immVertex2fv(pos, vec2);
- }
-
- /* vertical axis */
- if (flag & V2D_VERTICAL_AXIS) {
- vec1[1] = v2d->cur.ymin;
- vec2[1] = v2d->cur.ymax;
- vec1[0] = vec2[0] = 0.0f;
-
- immAttrSkip(color);
- immVertex2fv(pos, vec1);
- immAttr3ubv(color, grid_line_color);
- immVertex2fv(pos, vec2);
- }
-
- immEnd();
- immUnbindProgram();
+ float vec1[2], vec2[2];
+ int a, step;
+ int vertical_minor_step = (BLI_rcti_size_x(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC);
+ int horizontal_major_step = (BLI_rcti_size_y(&v2d->mask) + 1) /
+ (U.v2d_min_gridsize * UI_DPI_FAC);
+ uchar grid_line_color[3];
+
+ /* check for grid first, as it may not exist */
+ if (grid == NULL) {
+ return;
+ }
+
+ /* Count the needed vertices for the gridlines */
+ unsigned vertex_count = 0;
+ if (flag & V2D_VERTICAL_LINES) {
+ /* vertical lines */
+ vertex_count += 2 * vertical_minor_step; /* minor gridlines */
+ vertex_count += 2 * (vertical_minor_step + 2); /* major gridlines */
+ }
+ if (flag & V2D_HORIZONTAL_LINES) {
+ /* horizontal lines */
+ vertex_count += 2 * (horizontal_major_step + 1); /* major gridlines */
+
+ /* fine lines */
+ if (flag & V2D_HORIZONTAL_FINELINES) {
+ vertex_count += 2 * (horizontal_major_step + 1);
+ }
+ }
+ /* axes */
+ if (flag & V2D_HORIZONTAL_AXIS) {
+ vertex_count += 2;
+ }
+ if (flag & V2D_VERTICAL_AXIS) {
+ vertex_count += 2;
+ }
+
+ /* If there is nothing to render, exit early */
+ if (vertex_count == 0) {
+ return;
+ }
+
+ GPUVertFormat *format = immVertexFormat();
+ 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_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GPU_PRIM_LINES, vertex_count);
+
+ /* vertical lines */
+ if (flag & V2D_VERTICAL_LINES) {
+ /* initialize initial settings */
+ vec1[0] = vec2[0] = grid->startx;
+ vec1[1] = grid->starty;
+ vec2[1] = v2d->cur.ymax;
+
+ /* minor gridlines */
+ step = vertical_minor_step;
+ if (step != 0) {
+ UI_GetThemeColor3ubv(TH_GRID, grid_line_color);
+
+ for (a = 0; a < step; a++) {
+ immAttrSkip(color);
+ immVertex2fv(pos, vec1);
+ immAttr3ubv(color, grid_line_color);
+ immVertex2fv(pos, vec2);
+
+ vec2[0] = vec1[0] += grid->dx;
+ }
+ }
+
+ /* major gridlines */
+ vec2[0] = vec1[0] -= 0.5f * grid->dx;
+
+ UI_GetThemeColorShade3ubv(TH_GRID, 16, grid_line_color);
+
+ step++;
+ for (a = 0; a <= step; a++) {
+ immAttrSkip(color);
+ immVertex2fv(pos, vec1);
+ immAttr3ubv(color, grid_line_color);
+ immVertex2fv(pos, vec2);
+
+ vec2[0] = vec1[0] -= grid->dx;
+ }
+ }
+
+ /* horizontal lines */
+ if (flag & V2D_HORIZONTAL_LINES) {
+ /* only major gridlines */
+ vec1[1] = vec2[1] = grid->starty;
+ vec1[0] = grid->startx;
+ vec2[0] = v2d->cur.xmax;
+
+ step = horizontal_major_step;
+
+ UI_GetThemeColor3ubv(TH_GRID, grid_line_color);
+
+ for (a = 0; a <= step; a++) {
+ immAttrSkip(color);
+ immVertex2fv(pos, vec1);
+ immAttr3ubv(color, grid_line_color);
+ immVertex2fv(pos, vec2);
+
+ vec2[1] = vec1[1] += grid->dy;
+ }
+
+ /* fine grid lines */
+ vec2[1] = vec1[1] -= 0.5f * grid->dy;
+ step++;
+
+ if (flag & V2D_HORIZONTAL_FINELINES) {
+ UI_GetThemeColorShade3ubv(TH_GRID, 16, grid_line_color);
+ for (a = 0; a < step; a++) {
+ immAttrSkip(color);
+ immVertex2fv(pos, vec1);
+ immAttr3ubv(color, grid_line_color);
+ immVertex2fv(pos, vec2);
+
+ vec2[1] = vec1[1] -= grid->dy;
+ }
+ }
+ }
+
+ /* Axes are drawn as darker lines */
+ UI_GetThemeColorShade3ubv(TH_GRID, -50, grid_line_color);
+
+ /* horizontal axis */
+ if (flag & V2D_HORIZONTAL_AXIS) {
+ vec1[0] = v2d->cur.xmin;
+ vec2[0] = v2d->cur.xmax;
+ vec1[1] = vec2[1] = 0.0f;
+
+ immAttrSkip(color);
+ immVertex2fv(pos, vec1);
+ immAttr3ubv(color, grid_line_color);
+ immVertex2fv(pos, vec2);
+ }
+
+ /* vertical axis */
+ if (flag & V2D_VERTICAL_AXIS) {
+ vec1[1] = v2d->cur.ymin;
+ vec2[1] = v2d->cur.ymax;
+ vec1[0] = vec2[0] = 0.0f;
+
+ immAttrSkip(color);
+ immVertex2fv(pos, vec1);
+ immAttr3ubv(color, grid_line_color);
+ immVertex2fv(pos, vec2);
+ }
+
+ immEnd();
+ immUnbindProgram();
}
/* Draw a constant grid in given 2d-region */
void UI_view2d_constant_grid_draw(View2D *v2d, float step)
{
- float start_x, start_y;
- int count_x, count_y;
-
- start_x = v2d->cur.xmin;
- if (start_x < 0.0) {
- start_x += -(float)fmod(v2d->cur.xmin, step);
- }
- else {
- start_x += (step - (float)fmod(v2d->cur.xmin, step));
- }
-
- if (start_x > v2d->cur.xmax) {
- count_x = 0;
- }
- else {
- count_x = (v2d->cur.xmax - start_x) / step + 1;
- }
-
- start_y = v2d->cur.ymin;
- if (start_y < 0.0) {
- start_y += -(float)fmod(v2d->cur.ymin, step);
- }
- else {
- start_y += (step - (float)fabs(fmod(v2d->cur.ymin, step)));
- }
-
- if (start_y > v2d->cur.ymax) {
- count_y = 0;
- }
- else {
- count_y = (v2d->cur.ymax - start_y) / step + 1;
- }
-
- if (count_x > 0 || count_y > 0) {
- GPUVertFormat *format = immVertexFormat();
- 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);
- float theme_color[3];
-
- UI_GetThemeColorShade3fv(TH_BACK, -10, theme_color);
-
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- immBegin(GPU_PRIM_LINES, count_x * 2 + count_y * 2 + 4);
-
- immAttr3fv(color, theme_color);
- for (int i = 0; i < count_x ; start_x += step, i++) {
- immVertex2f(pos, start_x, v2d->cur.ymin);
- immVertex2f(pos, start_x, v2d->cur.ymax);
- }
-
- for (int i = 0; i < count_y; start_y += step, i++) {
- immVertex2f(pos, v2d->cur.xmin, start_y);
- immVertex2f(pos, v2d->cur.xmax, start_y);
- }
-
- /* X and Y axis */
- UI_GetThemeColorShade3fv(TH_BACK, -18, theme_color);
-
- immAttr3fv(color, theme_color);
- immVertex2f(pos, 0.0f, v2d->cur.ymin);
- immVertex2f(pos, 0.0f, v2d->cur.ymax);
- immVertex2f(pos, v2d->cur.xmin, 0.0f);
- immVertex2f(pos, v2d->cur.xmax, 0.0f);
-
- immEnd();
- immUnbindProgram();
- }
+ float start_x, start_y;
+ int count_x, count_y;
+
+ start_x = v2d->cur.xmin;
+ if (start_x < 0.0) {
+ start_x += -(float)fmod(v2d->cur.xmin, step);
+ }
+ else {
+ start_x += (step - (float)fmod(v2d->cur.xmin, step));
+ }
+
+ if (start_x > v2d->cur.xmax) {
+ count_x = 0;
+ }
+ else {
+ count_x = (v2d->cur.xmax - start_x) / step + 1;
+ }
+
+ start_y = v2d->cur.ymin;
+ if (start_y < 0.0) {
+ start_y += -(float)fmod(v2d->cur.ymin, step);
+ }
+ else {
+ start_y += (step - (float)fabs(fmod(v2d->cur.ymin, step)));
+ }
+
+ if (start_y > v2d->cur.ymax) {
+ count_y = 0;
+ }
+ else {
+ count_y = (v2d->cur.ymax - start_y) / step + 1;
+ }
+
+ if (count_x > 0 || count_y > 0) {
+ GPUVertFormat *format = immVertexFormat();
+ 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);
+ float theme_color[3];
+
+ UI_GetThemeColorShade3fv(TH_BACK, -10, theme_color);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GPU_PRIM_LINES, count_x * 2 + count_y * 2 + 4);
+
+ immAttr3fv(color, theme_color);
+ for (int i = 0; i < count_x; start_x += step, i++) {
+ immVertex2f(pos, start_x, v2d->cur.ymin);
+ immVertex2f(pos, start_x, v2d->cur.ymax);
+ }
+
+ for (int i = 0; i < count_y; start_y += step, i++) {
+ immVertex2f(pos, v2d->cur.xmin, start_y);
+ immVertex2f(pos, v2d->cur.xmax, start_y);
+ }
+
+ /* X and Y axis */
+ UI_GetThemeColorShade3fv(TH_BACK, -18, theme_color);
+
+ immAttr3fv(color, theme_color);
+ immVertex2f(pos, 0.0f, v2d->cur.ymin);
+ immVertex2f(pos, 0.0f, v2d->cur.ymax);
+ immVertex2f(pos, v2d->cur.xmin, 0.0f);
+ immVertex2f(pos, v2d->cur.xmax, 0.0f);
+
+ immEnd();
+ immUnbindProgram();
+ }
}
/* 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)
{
- /* Exit if there is nothing to draw */
- if (totlevels == 0) {
- return;
- }
-
- int offset = -10;
- float lstep = step;
- uchar grid_line_color[3];
-
- /* Make an estimate of at least how many vertices will be needed */
- unsigned 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);
-
- GPUVertFormat *format = immVertexFormat();
- 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_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
-
- GPU_line_width(1.0f);
-
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- immBeginAtMost(GPU_PRIM_LINES, vertex_count);
-
- for (int level = 0; level < totlevels; ++level) {
- UI_GetThemeColorShade3ubv(colorid, offset, grid_line_color);
-
- int i = (int)(v2d->cur.xmin / lstep);
- if (v2d->cur.xmin > 0.0f) {
- i++;
- }
- float start = i * lstep;
-
- for (; start < v2d->cur.xmax; start += lstep, ++i) {
- if (i == 0 || (level < totlevels - 1 && i % level_size == 0)) {
- continue;
- }
-
- immAttrSkip(color);
- immVertex2f(pos, start, v2d->cur.ymin);
- immAttr3ubv(color, grid_line_color);
- immVertex2f(pos, start, v2d->cur.ymax);
- }
-
- i = (int)(v2d->cur.ymin / lstep);
- if (v2d->cur.ymin > 0.0f) {
- i++;
- }
- start = i * lstep;
-
- for (; start < v2d->cur.ymax; start += lstep, ++i) {
- if (i == 0 || (level < totlevels - 1 && i % level_size == 0)) {
- continue;
- }
-
- immAttrSkip(color);
- immVertex2f(pos, v2d->cur.xmin, start);
- immAttr3ubv(color, grid_line_color);
- immVertex2f(pos, v2d->cur.xmax, start);
- }
-
- lstep *= level_size;
- offset -= 6;
- }
-
- /* X and Y axis */
- UI_GetThemeColorShade3ubv(colorid, -18 + ((totlevels - 1) * -6), grid_line_color);
-
- immAttrSkip(color);
- immVertex2f(pos, 0.0f, v2d->cur.ymin);
- immAttr3ubv(color, grid_line_color);
- immVertex2f(pos, 0.0f, v2d->cur.ymax);
-
- immAttrSkip(color);
- immVertex2f(pos, v2d->cur.xmin, 0.0f);
- immAttr3ubv(color, grid_line_color);
- immVertex2f(pos, v2d->cur.xmax, 0.0f);
-
- immEnd();
- immUnbindProgram();
+ /* Exit if there is nothing to draw */
+ if (totlevels == 0) {
+ return;
+ }
+
+ int offset = -10;
+ float lstep = step;
+ uchar grid_line_color[3];
+
+ /* Make an estimate of at least how many vertices will be needed */
+ unsigned 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);
+
+ GPUVertFormat *format = immVertexFormat();
+ 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_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+
+ GPU_line_width(1.0f);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBeginAtMost(GPU_PRIM_LINES, vertex_count);
+
+ for (int level = 0; level < totlevels; ++level) {
+ UI_GetThemeColorShade3ubv(colorid, offset, grid_line_color);
+
+ int i = (int)(v2d->cur.xmin / lstep);
+ if (v2d->cur.xmin > 0.0f) {
+ i++;
+ }
+ float start = i * lstep;
+
+ for (; start < v2d->cur.xmax; start += lstep, ++i) {
+ if (i == 0 || (level < totlevels - 1 && i % level_size == 0)) {
+ continue;
+ }
+
+ immAttrSkip(color);
+ immVertex2f(pos, start, v2d->cur.ymin);
+ immAttr3ubv(color, grid_line_color);
+ immVertex2f(pos, start, v2d->cur.ymax);
+ }
+
+ i = (int)(v2d->cur.ymin / lstep);
+ if (v2d->cur.ymin > 0.0f) {
+ i++;
+ }
+ start = i * lstep;
+
+ for (; start < v2d->cur.ymax; start += lstep, ++i) {
+ if (i == 0 || (level < totlevels - 1 && i % level_size == 0)) {
+ continue;
+ }
+
+ immAttrSkip(color);
+ immVertex2f(pos, v2d->cur.xmin, start);
+ immAttr3ubv(color, grid_line_color);
+ immVertex2f(pos, v2d->cur.xmax, start);
+ }
+
+ lstep *= level_size;
+ offset -= 6;
+ }
+
+ /* X and Y axis */
+ UI_GetThemeColorShade3ubv(colorid, -18 + ((totlevels - 1) * -6), grid_line_color);
+
+ immAttrSkip(color);
+ immVertex2f(pos, 0.0f, v2d->cur.ymin);
+ immAttr3ubv(color, grid_line_color);
+ immVertex2f(pos, 0.0f, v2d->cur.ymax);
+
+ immAttrSkip(color);
+ immVertex2f(pos, v2d->cur.xmin, 0.0f);
+ immAttr3ubv(color, grid_line_color);
+ immVertex2f(pos, v2d->cur.xmax, 0.0f);
+
+ immEnd();
+ immUnbindProgram();
}
static void get_scale_indicator_text(
- const Scene *scene,
- float value,
- int brevity_level,
- short unit,
- uint max_length,
- char *r_str)
+ const Scene *scene, float value, int brevity_level, short unit, uint max_length, char *r_str)
{
- if (unit == V2D_UNIT_SECONDS) {
- BLI_timecode_string_from_time(r_str, max_length, brevity_level, value / (float)FPS, FPS, U.timecode_style);
- }
- else {
- BLI_timecode_string_from_time_seconds(r_str, max_length, brevity_level, value);
- }
+ if (unit == V2D_UNIT_SECONDS) {
+ BLI_timecode_string_from_time(
+ r_str, max_length, brevity_level, value / (float)FPS, FPS, U.timecode_style);
+ }
+ else {
+ BLI_timecode_string_from_time_seconds(r_str, max_length, brevity_level, value);
+ }
}
-void UI_view2d_grid_draw_numbers_horizontal(
- const Scene *scene,
- const View2D *v2d,
- const View2DGrid *grid,
- const rcti *rect,
- int unit,
- bool whole_numbers_only)
+void UI_view2d_grid_draw_numbers_horizontal(const Scene *scene,
+ const View2D *v2d,
+ const View2DGrid *grid,
+ const rcti *rect,
+ int unit,
+ bool whole_numbers_only)
{
- BLI_assert(grid);
- float xstep = grid->dx * UI_view2d_scale_get_x(v2d);
- if (xstep <= 0.0f) {
- return;
- }
-
- float initial_xpos = UI_view2d_view_to_region_x(v2d, grid->startx);
- float ypos = (float)rect->ymin + 2 * UI_DPI_FAC;
- float initial_value = grid->startx;
- float value_step = grid->dx;
- int brevity_level = grid->powerx;
-
- /* Make sure that the value_step is >= 1 when only whole numbers are displayed.
- * Otherwise the same number could be displayed more than once. */
- if (whole_numbers_only) {
- while (value_step < 0.9999f) {
- xstep *= 2.0f;
- value_step *= 2.0f;
- }
- }
-
- /* Skip first few steps if they don't intersect
- * the rectangle that will contain the numbers. */
- while (initial_xpos < rect->xmin) {
- initial_xpos += xstep;
- initial_value += value_step;
- }
-
- if (unit == V2D_UNIT_FRAMES) {
- brevity_level = 1;
- }
-
- const int font_id = BLF_default();
- UI_FontThemeColor(font_id, TH_TEXT);
-
- BLF_batch_draw_begin();
-
- for (float xpos = initial_xpos, value = initial_value;
- xpos < rect->xmax;
- xpos += xstep, value += value_step)
- {
- char text[32];
- get_scale_indicator_text(scene, value, brevity_level, unit, sizeof(text), text);
- float text_width = BLF_width(font_id, text, strlen(text));
- BLF_draw_default_ascii(xpos - text_width / 2.0f, ypos, 0.0f, text, sizeof(text));
- }
-
- BLF_batch_draw_end();
+ BLI_assert(grid);
+ float xstep = grid->dx * UI_view2d_scale_get_x(v2d);
+ if (xstep <= 0.0f) {
+ return;
+ }
+
+ float initial_xpos = UI_view2d_view_to_region_x(v2d, grid->startx);
+ float ypos = (float)rect->ymin + 2 * UI_DPI_FAC;
+ float initial_value = grid->startx;
+ float value_step = grid->dx;
+ int brevity_level = grid->powerx;
+
+ /* Make sure that the value_step is >= 1 when only whole numbers are displayed.
+ * Otherwise the same number could be displayed more than once. */
+ if (whole_numbers_only) {
+ while (value_step < 0.9999f) {
+ xstep *= 2.0f;
+ value_step *= 2.0f;
+ }
+ }
+
+ /* Skip first few steps if they don't intersect
+ * the rectangle that will contain the numbers. */
+ while (initial_xpos < rect->xmin) {
+ initial_xpos += xstep;
+ initial_value += value_step;
+ }
+
+ if (unit == V2D_UNIT_FRAMES) {
+ brevity_level = 1;
+ }
+
+ const int font_id = BLF_default();
+ UI_FontThemeColor(font_id, TH_TEXT);
+
+ BLF_batch_draw_begin();
+
+ for (float xpos = initial_xpos, value = initial_value; xpos < rect->xmax;
+ xpos += xstep, value += value_step) {
+ char text[32];
+ get_scale_indicator_text(scene, value, brevity_level, unit, sizeof(text), text);
+ float text_width = BLF_width(font_id, text, strlen(text));
+ BLF_draw_default_ascii(xpos - text_width / 2.0f, ypos, 0.0f, text, sizeof(text));
+ }
+
+ BLF_batch_draw_end();
}
-void UI_view2d_grid_draw_numbers_vertical(
- const Scene *scene,
- const View2D *v2d,
- const View2DGrid *grid,
- const rcti *rect,
- int unit,
- float text_offset)
+void UI_view2d_grid_draw_numbers_vertical(const Scene *scene,
+ const View2D *v2d,
+ const View2DGrid *grid,
+ const rcti *rect,
+ int unit,
+ float text_offset)
{
- BLI_assert(grid);
- float ystep = grid->dy * UI_view2d_scale_get_y(v2d);
- if (ystep <= 0.0f) {
- return;
- }
-
- const int font_id = BLF_default();
- UI_FontThemeColor(font_id, TH_TEXT);
-
- BLF_enable(font_id, BLF_ROTATION);
- BLF_rotation(font_id, M_PI_2);
-
- float initial_value = grid->starty;
- float value_step = grid->dy;
- float xpos = rect->xmax - 2.0f * UI_DPI_FAC;
- float initial_ypos = UI_view2d_view_to_region_y(v2d, grid->starty);
-
- /* Currently only used by the sequencer to display
- * channel numbers in the center. */
- initial_ypos += text_offset * ystep;
-
- /* Skip first few steps if they don't intersect
- * the rectangle that will contain the numbers. */
- while (initial_ypos < rect->ymin) {
- initial_ypos += ystep;
- initial_value += value_step;
- }
-
- for (float ypos = initial_ypos, value = initial_value;
- ypos < rect->ymax;
- ypos += ystep, value += value_step)
- {
- char text[32];
- get_scale_indicator_text(scene, value, grid->powery, unit, sizeof(text), text);
- float text_width = BLF_width(font_id, text, sizeof(text));
- BLF_draw_default_ascii(xpos, ypos - text_width / 2.0f, 0.0f, text, sizeof(text));
- }
-
- BLF_disable(font_id, BLF_ROTATION);
+ BLI_assert(grid);
+ float ystep = grid->dy * UI_view2d_scale_get_y(v2d);
+ if (ystep <= 0.0f) {
+ return;
+ }
+
+ const int font_id = BLF_default();
+ UI_FontThemeColor(font_id, TH_TEXT);
+
+ BLF_enable(font_id, BLF_ROTATION);
+ BLF_rotation(font_id, M_PI_2);
+
+ float initial_value = grid->starty;
+ float value_step = grid->dy;
+ float xpos = rect->xmax - 2.0f * UI_DPI_FAC;
+ float initial_ypos = UI_view2d_view_to_region_y(v2d, grid->starty);
+
+ /* Currently only used by the sequencer to display
+ * channel numbers in the center. */
+ initial_ypos += text_offset * ystep;
+
+ /* Skip first few steps if they don't intersect
+ * the rectangle that will contain the numbers. */
+ while (initial_ypos < rect->ymin) {
+ initial_ypos += ystep;
+ initial_value += value_step;
+ }
+
+ for (float ypos = initial_ypos, value = initial_value; ypos < rect->ymax;
+ ypos += ystep, value += value_step) {
+ char text[32];
+ get_scale_indicator_text(scene, value, grid->powery, unit, sizeof(text), text);
+ float text_width = BLF_width(font_id, text, sizeof(text));
+ BLF_draw_default_ascii(xpos, ypos - text_width / 2.0f, 0.0f, text, sizeof(text));
+ }
+
+ BLF_disable(font_id, BLF_ROTATION);
}
/* the price we pay for not exposting structs :( */
void UI_view2d_grid_size(View2DGrid *grid, float *r_dx, float *r_dy)
{
- *r_dx = grid->dx;
- *r_dy = grid->dy;
+ *r_dx = grid->dx;
+ *r_dy = grid->dy;
}
/* free temporary memory used for drawing grid */
void UI_view2d_grid_free(View2DGrid *grid)
{
- /* only free if there's a grid */
- if (grid) {
- MEM_freeN(grid);
- }
+ /* only free if there's a grid */
+ if (grid) {
+ MEM_freeN(grid);
+ }
}
/* *********************************************************************** */
@@ -1863,288 +1855,290 @@ void UI_view2d_grid_free(View2DGrid *grid)
* For now, we don't need to have a separate (internal) header for structs like this...
*/
struct View2DScrollers {
- /* focus bubbles */
- int vert_min, vert_max; /* vertical scrollbar */
- int hor_min, hor_max; /* horizontal scrollbar */
+ /* focus bubbles */
+ int vert_min, vert_max; /* vertical scrollbar */
+ int hor_min, hor_max; /* horizontal scrollbar */
- rcti hor, vert; /* exact size of slider backdrop */
- int horfull, vertfull; /* set if sliders are full, we don't draw them */
+ rcti hor, vert; /* exact size of slider backdrop */
+ int horfull, vertfull; /* set if sliders are full, we don't draw them */
- /* scales */
- View2DGrid *grid; /* grid for coordinate drawing */
- short xunits, xclamp; /* units and clamping options for x-axis */
- short yunits, yclamp; /* units and clamping options for y-axis */
+ /* scales */
+ View2DGrid *grid; /* grid for coordinate drawing */
+ short xunits, xclamp; /* units and clamping options for x-axis */
+ short yunits, yclamp; /* units and clamping options for y-axis */
};
/* Calculate relevant scroller properties */
-View2DScrollers *UI_view2d_scrollers_calc(
- const bContext *C, View2D *v2d, const rcti *mask_custom,
- short xunits, short xclamp, short yunits, short yclamp)
+View2DScrollers *UI_view2d_scrollers_calc(const bContext *C,
+ View2D *v2d,
+ const rcti *mask_custom,
+ short xunits,
+ short xclamp,
+ short yunits,
+ short yclamp)
{
- View2DScrollers *scrollers;
- rcti vert, hor;
- float fac1, fac2, totsize, scrollsize;
- int scroll = view2d_scroll_mapped(v2d->scroll);
- int smaller;
-
- /* scrollers is allocated here... */
- scrollers = MEM_callocN(sizeof(View2DScrollers), "View2DScrollers");
-
- /* Always update before drawing (for dynamically sized scrollers). */
- view2d_masks(v2d, false, mask_custom);
-
- vert = v2d->vert;
- hor = v2d->hor;
-
- /* slider rects need to be smaller than region and not interfere with splitter areas */
- hor.xmin += UI_HEADER_OFFSET;
- hor.xmax -= UI_HEADER_OFFSET;
- vert.ymin += UI_HEADER_OFFSET;
- vert.ymax -= UI_HEADER_OFFSET;
-
- /* width of sliders */
- smaller = (int)(0.1f * U.widget_unit);
- if (scroll & V2D_SCROLL_BOTTOM) {
- hor.ymin += smaller;
- }
- else {
- hor.ymax -= smaller;
- }
-
- if (scroll & V2D_SCROLL_LEFT) {
- vert.xmin += smaller;
- }
- else {
- vert.xmax -= smaller;
- }
-
- CLAMP(vert.ymin, vert.ymin, vert.ymax - V2D_SCROLLER_HANDLE_SIZE);
- CLAMP(hor.xmin, hor.xmin, hor.xmax - V2D_SCROLLER_HANDLE_SIZE);
-
- /* store in scrollers, used for drawing */
- scrollers->vert = vert;
- scrollers->hor = hor;
-
- /* scroller 'buttons':
- * - These should always remain within the visible region of the scrollbar
- * - They represent the region of 'tot' that is visible in 'cur'
- */
-
- /* horizontal scrollers */
- if (scroll & V2D_SCROLL_HORIZONTAL) {
- /* scroller 'button' extents */
- totsize = BLI_rctf_size_x(&v2d->tot);
- scrollsize = (float)BLI_rcti_size_x(&hor);
- if (totsize == 0.0f) {
- totsize = 1.0f; /* avoid divide by zero */
- }
-
- fac1 = (v2d->cur.xmin - v2d->tot.xmin) / totsize;
- if (fac1 <= 0.0f) {
- scrollers->hor_min = hor.xmin;
- }
- else {
- scrollers->hor_min = (int)(hor.xmin + (fac1 * scrollsize));
- }
-
- fac2 = (v2d->cur.xmax - v2d->tot.xmin) / totsize;
- if (fac2 >= 1.0f) {
- scrollers->hor_max = hor.xmax;
- }
- else {
- scrollers->hor_max = (int)(hor.xmin + (fac2 * scrollsize));
- }
-
- /* prevent inverted sliders */
- if (scrollers->hor_min > scrollers->hor_max) {
- scrollers->hor_min = scrollers->hor_max;
- }
- /* prevent sliders from being too small, and disappearing */
- if ((scrollers->hor_max - scrollers->hor_min) < V2D_SCROLLER_HANDLE_SIZE) {
- scrollers->hor_max = scrollers->hor_min + V2D_SCROLLER_HANDLE_SIZE;
-
- CLAMP(scrollers->hor_max, hor.xmin + V2D_SCROLLER_HANDLE_SIZE, hor.xmax);
- CLAMP(scrollers->hor_min, hor.xmin, hor.xmax - V2D_SCROLLER_HANDLE_SIZE);
- }
-
- }
-
- /* vertical scrollers */
- if (scroll & V2D_SCROLL_VERTICAL) {
- /* scroller 'button' extents */
- totsize = BLI_rctf_size_y(&v2d->tot);
- scrollsize = (float)BLI_rcti_size_y(&vert);
- if (totsize == 0.0f) {
- totsize = 1.0f; /* avoid divide by zero */
- }
-
- fac1 = (v2d->cur.ymin - v2d->tot.ymin) / totsize;
- if (fac1 <= 0.0f) {
- scrollers->vert_min = vert.ymin;
- }
- else {
- scrollers->vert_min = (int)(vert.ymin + (fac1 * scrollsize));
- }
-
- fac2 = (v2d->cur.ymax - v2d->tot.ymin) / totsize;
- if (fac2 >= 1.0f) {
- scrollers->vert_max = vert.ymax;
- }
- else {
- scrollers->vert_max = (int)(vert.ymin + (fac2 * scrollsize));
- }
-
- /* prevent inverted sliders */
- if (scrollers->vert_min > scrollers->vert_max) {
- scrollers->vert_min = scrollers->vert_max;
- }
- /* prevent sliders from being too small, and disappearing */
- if ((scrollers->vert_max - scrollers->vert_min) < V2D_SCROLLER_HANDLE_SIZE) {
-
- scrollers->vert_max = scrollers->vert_min + V2D_SCROLLER_HANDLE_SIZE;
-
- CLAMP(scrollers->vert_max, vert.ymin + V2D_SCROLLER_HANDLE_SIZE, vert.ymax);
- CLAMP(scrollers->vert_min, vert.ymin, vert.ymax - V2D_SCROLLER_HANDLE_SIZE);
- }
-
- }
-
- /* grid markings on scrollbars */
- if (scroll & (V2D_SCROLL_SCALE_HORIZONTAL | V2D_SCROLL_SCALE_VERTICAL)) {
- /* store clamping */
- scrollers->xclamp = xclamp;
- scrollers->xunits = xunits;
- scrollers->yclamp = yclamp;
- scrollers->yunits = yunits;
-
- scrollers->grid = UI_view2d_grid_calc(
- CTX_data_scene(C), v2d,
- xunits, xclamp, yunits, yclamp,
- BLI_rcti_size_x(&hor), BLI_rcti_size_y(&vert));
- }
-
- /* return scrollers */
- return scrollers;
+ View2DScrollers *scrollers;
+ rcti vert, hor;
+ float fac1, fac2, totsize, scrollsize;
+ int scroll = view2d_scroll_mapped(v2d->scroll);
+ int smaller;
+
+ /* scrollers is allocated here... */
+ scrollers = MEM_callocN(sizeof(View2DScrollers), "View2DScrollers");
+
+ /* Always update before drawing (for dynamically sized scrollers). */
+ view2d_masks(v2d, false, mask_custom);
+
+ vert = v2d->vert;
+ hor = v2d->hor;
+
+ /* slider rects need to be smaller than region and not interfere with splitter areas */
+ hor.xmin += UI_HEADER_OFFSET;
+ hor.xmax -= UI_HEADER_OFFSET;
+ vert.ymin += UI_HEADER_OFFSET;
+ vert.ymax -= UI_HEADER_OFFSET;
+
+ /* width of sliders */
+ smaller = (int)(0.1f * U.widget_unit);
+ if (scroll & V2D_SCROLL_BOTTOM) {
+ hor.ymin += smaller;
+ }
+ else {
+ hor.ymax -= smaller;
+ }
+
+ if (scroll & V2D_SCROLL_LEFT) {
+ vert.xmin += smaller;
+ }
+ else {
+ vert.xmax -= smaller;
+ }
+
+ CLAMP(vert.ymin, vert.ymin, vert.ymax - V2D_SCROLLER_HANDLE_SIZE);
+ CLAMP(hor.xmin, hor.xmin, hor.xmax - V2D_SCROLLER_HANDLE_SIZE);
+
+ /* store in scrollers, used for drawing */
+ scrollers->vert = vert;
+ scrollers->hor = hor;
+
+ /* scroller 'buttons':
+ * - These should always remain within the visible region of the scrollbar
+ * - They represent the region of 'tot' that is visible in 'cur'
+ */
+
+ /* horizontal scrollers */
+ if (scroll & V2D_SCROLL_HORIZONTAL) {
+ /* scroller 'button' extents */
+ totsize = BLI_rctf_size_x(&v2d->tot);
+ scrollsize = (float)BLI_rcti_size_x(&hor);
+ if (totsize == 0.0f) {
+ totsize = 1.0f; /* avoid divide by zero */
+ }
+
+ fac1 = (v2d->cur.xmin - v2d->tot.xmin) / totsize;
+ if (fac1 <= 0.0f) {
+ scrollers->hor_min = hor.xmin;
+ }
+ else {
+ scrollers->hor_min = (int)(hor.xmin + (fac1 * scrollsize));
+ }
+
+ fac2 = (v2d->cur.xmax - v2d->tot.xmin) / totsize;
+ if (fac2 >= 1.0f) {
+ scrollers->hor_max = hor.xmax;
+ }
+ else {
+ scrollers->hor_max = (int)(hor.xmin + (fac2 * scrollsize));
+ }
+
+ /* prevent inverted sliders */
+ if (scrollers->hor_min > scrollers->hor_max) {
+ scrollers->hor_min = scrollers->hor_max;
+ }
+ /* prevent sliders from being too small, and disappearing */
+ if ((scrollers->hor_max - scrollers->hor_min) < V2D_SCROLLER_HANDLE_SIZE) {
+ scrollers->hor_max = scrollers->hor_min + V2D_SCROLLER_HANDLE_SIZE;
+
+ CLAMP(scrollers->hor_max, hor.xmin + V2D_SCROLLER_HANDLE_SIZE, hor.xmax);
+ CLAMP(scrollers->hor_min, hor.xmin, hor.xmax - V2D_SCROLLER_HANDLE_SIZE);
+ }
+ }
+
+ /* vertical scrollers */
+ if (scroll & V2D_SCROLL_VERTICAL) {
+ /* scroller 'button' extents */
+ totsize = BLI_rctf_size_y(&v2d->tot);
+ scrollsize = (float)BLI_rcti_size_y(&vert);
+ if (totsize == 0.0f) {
+ totsize = 1.0f; /* avoid divide by zero */
+ }
+
+ fac1 = (v2d->cur.ymin - v2d->tot.ymin) / totsize;
+ if (fac1 <= 0.0f) {
+ scrollers->vert_min = vert.ymin;
+ }
+ else {
+ scrollers->vert_min = (int)(vert.ymin + (fac1 * scrollsize));
+ }
+
+ fac2 = (v2d->cur.ymax - v2d->tot.ymin) / totsize;
+ if (fac2 >= 1.0f) {
+ scrollers->vert_max = vert.ymax;
+ }
+ else {
+ scrollers->vert_max = (int)(vert.ymin + (fac2 * scrollsize));
+ }
+
+ /* prevent inverted sliders */
+ if (scrollers->vert_min > scrollers->vert_max) {
+ scrollers->vert_min = scrollers->vert_max;
+ }
+ /* prevent sliders from being too small, and disappearing */
+ if ((scrollers->vert_max - scrollers->vert_min) < V2D_SCROLLER_HANDLE_SIZE) {
+
+ scrollers->vert_max = scrollers->vert_min + V2D_SCROLLER_HANDLE_SIZE;
+
+ CLAMP(scrollers->vert_max, vert.ymin + V2D_SCROLLER_HANDLE_SIZE, vert.ymax);
+ CLAMP(scrollers->vert_min, vert.ymin, vert.ymax - V2D_SCROLLER_HANDLE_SIZE);
+ }
+ }
+
+ /* grid markings on scrollbars */
+ if (scroll & (V2D_SCROLL_SCALE_HORIZONTAL | V2D_SCROLL_SCALE_VERTICAL)) {
+ /* store clamping */
+ scrollers->xclamp = xclamp;
+ scrollers->xunits = xunits;
+ scrollers->yclamp = yclamp;
+ scrollers->yunits = yunits;
+
+ scrollers->grid = UI_view2d_grid_calc(CTX_data_scene(C),
+ v2d,
+ xunits,
+ xclamp,
+ yunits,
+ yclamp,
+ BLI_rcti_size_x(&hor),
+ BLI_rcti_size_y(&vert));
+ }
+
+ /* return scrollers */
+ return scrollers;
}
/* Draw scrollbars in the given 2d-region */
void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *vs)
{
- bTheme *btheme = UI_GetTheme();
- rcti vert, hor;
- const int scroll = view2d_scroll_mapped(v2d->scroll);
- const char emboss_alpha = btheme->tui.widget_emboss[3];
- uchar scrollers_back_color[4];
-
- /* Color for scrollbar backs */
- UI_GetThemeColor4ubv(TH_BACK, scrollers_back_color);
-
- /* make copies of rects for less typing */
- vert = vs->vert;
- hor = vs->hor;
-
- /* horizontal scrollbar */
- if (scroll & V2D_SCROLL_HORIZONTAL) {
- uiWidgetColors wcol = btheme->tui.wcol_scroll;
- const float alpha_fac = v2d->alpha_hor / 255.0f;
- rcti slider;
- int state;
-
- slider.xmin = vs->hor_min;
- slider.xmax = vs->hor_max;
- slider.ymin = hor.ymin;
- slider.ymax = hor.ymax;
-
- state = (v2d->scroll_ui & V2D_SCROLL_H_ACTIVE) ? UI_SCROLL_PRESSED : 0;
-
- wcol.inner[3] *= alpha_fac;
- wcol.item[3] *= alpha_fac;
- wcol.outline[3] *= alpha_fac;
- btheme->tui.widget_emboss[3] *= alpha_fac; /* will be reset later */
-
- /* show zoom handles if:
- * - zooming on x-axis is allowed (no scroll otherwise)
- * - 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)
- */
- if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 &&
- (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) &&
- (BLI_rcti_size_x(&slider) > V2D_SCROLLER_HANDLE_SIZE))
- {
- state |= UI_SCROLL_ARROWS;
- }
-
- UI_draw_widget_scroll(&wcol, &hor, &slider, state);
-
- {
- if (scroll & V2D_SCROLL_SCALE_HORIZONTAL) {
- UI_view2d_grid_draw_numbers_horizontal(
- CTX_data_scene(C), v2d, vs->grid, &vs->hor, vs->xunits, vs->xclamp == V2D_GRID_CLAMP);
- }
- }
- }
-
- /* vertical scrollbar */
- if (scroll & V2D_SCROLL_VERTICAL) {
- uiWidgetColors wcol = btheme->tui.wcol_scroll;
- rcti slider;
- const float alpha_fac = v2d->alpha_vert / 255.0f;
- int state;
-
- slider.xmin = vert.xmin;
- slider.xmax = vert.xmax;
- slider.ymin = vs->vert_min;
- slider.ymax = vs->vert_max;
-
- state = (v2d->scroll_ui & V2D_SCROLL_V_ACTIVE) ? UI_SCROLL_PRESSED : 0;
-
- wcol.inner[3] *= alpha_fac;
- wcol.item[3] *= alpha_fac;
- wcol.outline[3] *= alpha_fac;
- btheme->tui.widget_emboss[3] *= alpha_fac; /* will be reset later */
-
- /* show zoom handles if:
- * - zooming on y-axis is allowed (no scroll otherwise)
- * - 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)
- */
- if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 &&
- (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) &&
- (BLI_rcti_size_y(&slider) > V2D_SCROLLER_HANDLE_SIZE))
- {
- state |= UI_SCROLL_ARROWS;
- }
-
- UI_draw_widget_scroll(&wcol, &vert, &slider, state);
-
- {
- if (scroll & V2D_SCROLL_SCALE_VERTICAL) {
- float text_offset = 0.0f;
- if (vs->yclamp & V2D_GRID_CLAMP) {
- text_offset = 0.5f;
- }
- UI_view2d_grid_draw_numbers_vertical(
- CTX_data_scene(C), v2d, vs->grid, &vs->vert, vs->yunits, text_offset);
- }
- }
- }
-
- /* Was changed above, so reset. */
- btheme->tui.widget_emboss[3] = emboss_alpha;
+ bTheme *btheme = UI_GetTheme();
+ rcti vert, hor;
+ const int scroll = view2d_scroll_mapped(v2d->scroll);
+ const char emboss_alpha = btheme->tui.widget_emboss[3];
+ uchar scrollers_back_color[4];
+
+ /* Color for scrollbar backs */
+ UI_GetThemeColor4ubv(TH_BACK, scrollers_back_color);
+
+ /* make copies of rects for less typing */
+ vert = vs->vert;
+ hor = vs->hor;
+
+ /* horizontal scrollbar */
+ if (scroll & V2D_SCROLL_HORIZONTAL) {
+ uiWidgetColors wcol = btheme->tui.wcol_scroll;
+ const float alpha_fac = v2d->alpha_hor / 255.0f;
+ rcti slider;
+ int state;
+
+ slider.xmin = vs->hor_min;
+ slider.xmax = vs->hor_max;
+ slider.ymin = hor.ymin;
+ slider.ymax = hor.ymax;
+
+ state = (v2d->scroll_ui & V2D_SCROLL_H_ACTIVE) ? UI_SCROLL_PRESSED : 0;
+
+ wcol.inner[3] *= alpha_fac;
+ wcol.item[3] *= alpha_fac;
+ wcol.outline[3] *= alpha_fac;
+ btheme->tui.widget_emboss[3] *= alpha_fac; /* will be reset later */
+
+ /* show zoom handles if:
+ * - zooming on x-axis is allowed (no scroll otherwise)
+ * - 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)
+ */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 && (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) &&
+ (BLI_rcti_size_x(&slider) > V2D_SCROLLER_HANDLE_SIZE)) {
+ state |= UI_SCROLL_ARROWS;
+ }
+
+ UI_draw_widget_scroll(&wcol, &hor, &slider, state);
+
+ {
+ if (scroll & V2D_SCROLL_SCALE_HORIZONTAL) {
+ UI_view2d_grid_draw_numbers_horizontal(
+ CTX_data_scene(C), v2d, vs->grid, &vs->hor, vs->xunits, vs->xclamp == V2D_GRID_CLAMP);
+ }
+ }
+ }
+
+ /* vertical scrollbar */
+ if (scroll & V2D_SCROLL_VERTICAL) {
+ uiWidgetColors wcol = btheme->tui.wcol_scroll;
+ rcti slider;
+ const float alpha_fac = v2d->alpha_vert / 255.0f;
+ int state;
+
+ slider.xmin = vert.xmin;
+ slider.xmax = vert.xmax;
+ slider.ymin = vs->vert_min;
+ slider.ymax = vs->vert_max;
+
+ state = (v2d->scroll_ui & V2D_SCROLL_V_ACTIVE) ? UI_SCROLL_PRESSED : 0;
+
+ wcol.inner[3] *= alpha_fac;
+ wcol.item[3] *= alpha_fac;
+ wcol.outline[3] *= alpha_fac;
+ btheme->tui.widget_emboss[3] *= alpha_fac; /* will be reset later */
+
+ /* show zoom handles if:
+ * - zooming on y-axis is allowed (no scroll otherwise)
+ * - 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)
+ */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 && (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) &&
+ (BLI_rcti_size_y(&slider) > V2D_SCROLLER_HANDLE_SIZE)) {
+ state |= UI_SCROLL_ARROWS;
+ }
+
+ UI_draw_widget_scroll(&wcol, &vert, &slider, state);
+
+ {
+ if (scroll & V2D_SCROLL_SCALE_VERTICAL) {
+ float text_offset = 0.0f;
+ if (vs->yclamp & V2D_GRID_CLAMP) {
+ text_offset = 0.5f;
+ }
+ UI_view2d_grid_draw_numbers_vertical(
+ CTX_data_scene(C), v2d, vs->grid, &vs->vert, vs->yunits, text_offset);
+ }
+ }
+ }
+
+ /* Was changed above, so reset. */
+ btheme->tui.widget_emboss[3] = emboss_alpha;
}
/* free temporary memory used for drawing scrollers */
void UI_view2d_scrollers_free(View2DScrollers *scrollers)
{
- /* need to free grid as well... */
- if (scrollers->grid) {
- MEM_freeN(scrollers->grid);
- }
- MEM_freeN(scrollers);
+ /* need to free grid as well... */
+ if (scrollers->grid) {
+ MEM_freeN(scrollers->grid);
+ }
+ MEM_freeN(scrollers);
}
/* *********************************************************************** */
@@ -2162,41 +2156,45 @@ void UI_view2d_scrollers_free(View2DScrollers *scrollers)
* \param rect: coordinates of the cell
* (passed as single var instead of 4 separate, as it's more useful this way)
*/
-void UI_view2d_listview_cell_to_view(
- View2D *v2d, float columnwidth, float rowheight,
- float startx, float starty,
- int column, int row, rctf *rect)
+void UI_view2d_listview_cell_to_view(View2D *v2d,
+ float columnwidth,
+ float rowheight,
+ float startx,
+ float starty,
+ int column,
+ int row,
+ rctf *rect)
{
- /* sanity checks */
- if (ELEM(NULL, v2d, rect)) {
- return;
- }
-
- if ((columnwidth <= 0) && (rowheight <= 0)) {
- rect->xmin = rect->xmax = 0.0f;
- rect->ymin = rect->ymax = 0.0f;
- return;
- }
-
- /* x-coordinates */
- rect->xmin = startx + (float)(columnwidth * column);
- rect->xmax = startx + (float)(columnwidth * (column + 1));
-
- if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
- /* simply negate the values for the coordinates if in negative half */
- rect->xmin = -rect->xmin;
- rect->xmax = -rect->xmax;
- }
-
- /* y-coordinates */
- rect->ymin = starty + (float)(rowheight * row);
- rect->ymax = starty + (float)(rowheight * (row + 1));
-
- if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
- /* simply negate the values for the coordinates if in negative half */
- rect->ymin = -rect->ymin;
- rect->ymax = -rect->ymax;
- }
+ /* sanity checks */
+ if (ELEM(NULL, v2d, rect)) {
+ return;
+ }
+
+ if ((columnwidth <= 0) && (rowheight <= 0)) {
+ rect->xmin = rect->xmax = 0.0f;
+ rect->ymin = rect->ymax = 0.0f;
+ return;
+ }
+
+ /* x-coordinates */
+ rect->xmin = startx + (float)(columnwidth * column);
+ rect->xmax = startx + (float)(columnwidth * (column + 1));
+
+ if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
+ /* simply negate the values for the coordinates if in negative half */
+ rect->xmin = -rect->xmin;
+ rect->xmax = -rect->xmax;
+ }
+
+ /* y-coordinates */
+ rect->ymin = starty + (float)(rowheight * row);
+ rect->ymax = starty + (float)(rowheight * (row + 1));
+
+ if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
+ /* simply negate the values for the coordinates if in negative half */
+ rect->ymin = -rect->ymin;
+ rect->ymax = -rect->ymax;
+ }
}
/**
@@ -2210,41 +2208,47 @@ void UI_view2d_listview_cell_to_view(
* \param viewx, viewy: 2D-coordinates (in 2D-view / 'tot' rect space) to get the cell for
* \param r_column, r_row: the 'coordinates' of the relevant 'cell'
*/
-void UI_view2d_listview_view_to_cell(
- View2D *v2d, float columnwidth, float rowheight, float startx, float starty,
- float viewx, float viewy, int *r_column, int *r_row)
+void UI_view2d_listview_view_to_cell(View2D *v2d,
+ float columnwidth,
+ float rowheight,
+ float startx,
+ float starty,
+ float viewx,
+ float viewy,
+ int *r_column,
+ int *r_row)
{
- /* adjust view coordinates to be all positive ints, corrected for the start offset */
- const int x = (int)(floorf(fabsf(viewx) + 0.5f) - startx);
- const int y = (int)(floorf(fabsf(viewy) + 0.5f) - starty);
-
- /* sizes must not be negative */
- if ((v2d == NULL) || ((columnwidth <= 0) && (rowheight <= 0))) {
- if (r_column) {
- *r_column = 0;
- }
- if (r_row) {
- *r_row = 0;
- }
-
- return;
- }
-
- /* get column */
- if ((r_column) && (columnwidth > 0)) {
- *r_column = x / columnwidth;
- }
- else if (r_column) {
- *r_column = 0;
- }
-
- /* get row */
- if ((r_row) && (rowheight > 0)) {
- *r_row = y / rowheight;
- }
- else if (r_row) {
- *r_row = 0;
- }
+ /* adjust view coordinates to be all positive ints, corrected for the start offset */
+ const int x = (int)(floorf(fabsf(viewx) + 0.5f) - startx);
+ const int y = (int)(floorf(fabsf(viewy) + 0.5f) - starty);
+
+ /* sizes must not be negative */
+ if ((v2d == NULL) || ((columnwidth <= 0) && (rowheight <= 0))) {
+ if (r_column) {
+ *r_column = 0;
+ }
+ if (r_row) {
+ *r_row = 0;
+ }
+
+ return;
+ }
+
+ /* get column */
+ if ((r_column) && (columnwidth > 0)) {
+ *r_column = x / columnwidth;
+ }
+ else if (r_column) {
+ *r_column = 0;
+ }
+
+ /* get row */
+ if ((r_row) && (rowheight > 0)) {
+ *r_row = y / rowheight;
+ }
+ else if (r_row) {
+ *r_row = 0;
+ }
}
/**
@@ -2254,22 +2258,40 @@ void UI_view2d_listview_view_to_cell(
* \param startx, starty: Coordinates that the list starts from, which should be (0,0) for most views
* \param column_min, column_max, row_min, row_max: The starting and ending column/row indices
*/
-void UI_view2d_listview_visible_cells(
- View2D *v2d, float columnwidth, float rowheight, float startx, float starty,
- int *column_min, int *column_max, int *row_min, int *row_max)
+void UI_view2d_listview_visible_cells(View2D *v2d,
+ float columnwidth,
+ float rowheight,
+ float startx,
+ float starty,
+ int *column_min,
+ int *column_max,
+ int *row_min,
+ int *row_max)
{
- /* using 'cur' rect coordinates, call the cell-getting function to get the cells for this */
- if (v2d) {
- /* min */
- UI_view2d_listview_view_to_cell(
- v2d, columnwidth, rowheight, startx, starty,
- v2d->cur.xmin, v2d->cur.ymin, column_min, row_min);
-
- /* max*/
- UI_view2d_listview_view_to_cell(
- v2d, columnwidth, rowheight, startx, starty,
- v2d->cur.xmax, v2d->cur.ymax, column_max, row_max);
- }
+ /* using 'cur' rect coordinates, call the cell-getting function to get the cells for this */
+ if (v2d) {
+ /* min */
+ UI_view2d_listview_view_to_cell(v2d,
+ columnwidth,
+ rowheight,
+ startx,
+ starty,
+ v2d->cur.xmin,
+ v2d->cur.ymin,
+ column_min,
+ row_min);
+
+ /* max*/
+ UI_view2d_listview_view_to_cell(v2d,
+ columnwidth,
+ rowheight,
+ startx,
+ starty,
+ v2d->cur.xmax,
+ v2d->cur.ymax,
+ column_max,
+ row_max);
+ }
}
/* *********************************************************************** */
@@ -2277,11 +2299,13 @@ void UI_view2d_listview_visible_cells(
float UI_view2d_region_to_view_x(const struct View2D *v2d, float x)
{
- return (v2d->cur.xmin + (BLI_rctf_size_x(&v2d->cur) * (x - v2d->mask.xmin) / BLI_rcti_size_x(&v2d->mask)));
+ return (v2d->cur.xmin +
+ (BLI_rctf_size_x(&v2d->cur) * (x - v2d->mask.xmin) / BLI_rcti_size_x(&v2d->mask)));
}
float UI_view2d_region_to_view_y(const struct View2D *v2d, float y)
{
- return (v2d->cur.ymin + (BLI_rctf_size_y(&v2d->cur) * (y - v2d->mask.ymin) / BLI_rcti_size_y(&v2d->mask)));
+ return (v2d->cur.ymin +
+ (BLI_rctf_size_y(&v2d->cur) * (y - v2d->mask.ymin) / BLI_rcti_size_y(&v2d->mask)));
}
/**
@@ -2290,30 +2314,37 @@ float UI_view2d_region_to_view_y(const struct View2D *v2d, float y)
* \param x, y: coordinates to convert
* \param r_view_x, r_view_y: resultant coordinates
*/
-void UI_view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y)
+void UI_view2d_region_to_view(
+ const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y)
{
- *r_view_x = UI_view2d_region_to_view_x(v2d, x);
- *r_view_y = UI_view2d_region_to_view_y(v2d, y);
+ *r_view_x = UI_view2d_region_to_view_x(v2d, x);
+ *r_view_y = UI_view2d_region_to_view_y(v2d, y);
}
void UI_view2d_region_to_view_rctf(const View2D *v2d, const rctf *rect_src, rctf *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)};
-
- rect_dst->xmin = (v2d->cur.xmin + (cur_size[0] * (rect_src->xmin - v2d->mask.xmin) / mask_size[0]));
- rect_dst->xmax = (v2d->cur.xmin + (cur_size[0] * (rect_src->xmax - v2d->mask.xmin) / mask_size[0]));
- rect_dst->ymin = (v2d->cur.ymin + (cur_size[1] * (rect_src->ymin - v2d->mask.ymin) / mask_size[1]));
- rect_dst->ymax = (v2d->cur.ymin + (cur_size[1] * (rect_src->ymax - v2d->mask.ymin) / mask_size[1]));
+ 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)};
+
+ rect_dst->xmin = (v2d->cur.xmin +
+ (cur_size[0] * (rect_src->xmin - v2d->mask.xmin) / mask_size[0]));
+ rect_dst->xmax = (v2d->cur.xmin +
+ (cur_size[0] * (rect_src->xmax - v2d->mask.xmin) / mask_size[0]));
+ rect_dst->ymin = (v2d->cur.ymin +
+ (cur_size[1] * (rect_src->ymin - v2d->mask.ymin) / mask_size[1]));
+ rect_dst->ymax = (v2d->cur.ymin +
+ (cur_size[1] * (rect_src->ymax - v2d->mask.ymin) / mask_size[1]));
}
float UI_view2d_view_to_region_x(const View2D *v2d, float x)
{
- return (v2d->mask.xmin + (((x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur)) * BLI_rcti_size_x(&v2d->mask)));
+ return (v2d->mask.xmin +
+ (((x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur)) * BLI_rcti_size_x(&v2d->mask)));
}
float UI_view2d_view_to_region_y(const View2D *v2d, float y)
{
- return (v2d->mask.ymin + (((y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur)) * BLI_rcti_size_y(&v2d->mask)));
+ return (v2d->mask.ymin +
+ (((y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur)) * BLI_rcti_size_y(&v2d->mask)));
}
/**
@@ -2323,25 +2354,26 @@ float UI_view2d_view_to_region_y(const View2D *v2d, float y)
* \param x, y: Coordinates to convert.
* \param r_region_x, r_region_y: Resultant coordinates.
*/
-bool UI_view2d_view_to_region_clip(const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y)
+bool UI_view2d_view_to_region_clip(
+ const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y)
{
- /* express given coordinates as proportional values */
- x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
- y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
-
- /* check if values are within bounds */
- if ((x >= 0.0f) && (x <= 1.0f) && (y >= 0.0f) && (y <= 1.0f)) {
- *r_region_x = (int)(v2d->mask.xmin + (x * BLI_rcti_size_x(&v2d->mask)));
- *r_region_y = (int)(v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask)));
-
- return true;
- }
- else {
- /* set initial value in case coordinate lies outside of bounds */
- *r_region_x = *r_region_y = V2D_IS_CLIPPED;
-
- return false;
- }
+ /* express given coordinates as proportional values */
+ x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
+ y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
+
+ /* check if values are within bounds */
+ if ((x >= 0.0f) && (x <= 1.0f) && (y >= 0.0f) && (y <= 1.0f)) {
+ *r_region_x = (int)(v2d->mask.xmin + (x * BLI_rcti_size_x(&v2d->mask)));
+ *r_region_y = (int)(v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask)));
+
+ return true;
+ }
+ else {
+ /* set initial value in case coordinate lies outside of bounds */
+ *r_region_x = *r_region_y = V2D_IS_CLIPPED;
+
+ return false;
+ }
}
/**
@@ -2354,92 +2386,91 @@ bool UI_view2d_view_to_region_clip(const View2D *v2d, float x, float y, int *r_r
*/
void UI_view2d_view_to_region(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);
- y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
+ /* step 1: express given coordinates as proportional values */
+ x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
+ y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
- /* step 2: convert proportional distances to screen coordinates */
- x = v2d->mask.xmin + (x * BLI_rcti_size_x(&v2d->mask));
- y = v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask));
+ /* step 2: convert proportional distances to screen coordinates */
+ x = v2d->mask.xmin + (x * BLI_rcti_size_x(&v2d->mask));
+ y = v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask));
- /* although we don't clamp to lie within region bounds, we must avoid exceeding size of ints */
- *r_region_x = clamp_float_to_int(x);
- *r_region_y = clamp_float_to_int(y);
+ /* although we don't clamp to lie within region bounds, we must avoid exceeding size of ints */
+ *r_region_x = clamp_float_to_int(x);
+ *r_region_y = clamp_float_to_int(y);
}
-void UI_view2d_view_to_region_fl(View2D *v2d, float x, float y, float *r_region_x, float *r_region_y)
+void UI_view2d_view_to_region_fl(
+ 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);
- y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
+ /* express given coordinates as proportional values */
+ x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
+ y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
- /* convert proportional distances to screen coordinates */
- *r_region_x = v2d->mask.xmin + (x * BLI_rcti_size_x(&v2d->mask));
- *r_region_y = v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask));
+ /* convert proportional distances to screen coordinates */
+ *r_region_x = v2d->mask.xmin + (x * BLI_rcti_size_x(&v2d->mask));
+ *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)
{
- 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)};
- rctf rect_tmp;
-
- /* step 1: express given coordinates as proportional values */
- rect_tmp.xmin = (rect_src->xmin - v2d->cur.xmin) / cur_size[0];
- rect_tmp.xmax = (rect_src->xmax - v2d->cur.xmin) / cur_size[0];
- rect_tmp.ymin = (rect_src->ymin - v2d->cur.ymin) / cur_size[1];
- rect_tmp.ymax = (rect_src->ymax - v2d->cur.ymin) / cur_size[1];
-
-
- /* step 2: convert proportional distances to screen coordinates */
- rect_tmp.xmin = v2d->mask.xmin + (rect_tmp.xmin * mask_size[0]);
- rect_tmp.xmax = v2d->mask.xmin + (rect_tmp.xmax * mask_size[0]);
- rect_tmp.ymin = v2d->mask.ymin + (rect_tmp.ymin * mask_size[1]);
- rect_tmp.ymax = v2d->mask.ymin + (rect_tmp.ymax * mask_size[1]);
-
- clamp_rctf_to_rcti(rect_dst, &rect_tmp);
+ 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)};
+ rctf rect_tmp;
+
+ /* step 1: express given coordinates as proportional values */
+ rect_tmp.xmin = (rect_src->xmin - v2d->cur.xmin) / cur_size[0];
+ rect_tmp.xmax = (rect_src->xmax - v2d->cur.xmin) / cur_size[0];
+ rect_tmp.ymin = (rect_src->ymin - v2d->cur.ymin) / cur_size[1];
+ rect_tmp.ymax = (rect_src->ymax - v2d->cur.ymin) / cur_size[1];
+
+ /* step 2: convert proportional distances to screen coordinates */
+ rect_tmp.xmin = v2d->mask.xmin + (rect_tmp.xmin * mask_size[0]);
+ rect_tmp.xmax = v2d->mask.xmin + (rect_tmp.xmax * mask_size[0]);
+ rect_tmp.ymin = v2d->mask.ymin + (rect_tmp.ymin * mask_size[1]);
+ rect_tmp.ymax = v2d->mask.ymin + (rect_tmp.ymax * mask_size[1]);
+
+ clamp_rctf_to_rcti(rect_dst, &rect_tmp);
}
void UI_view2d_view_to_region_m4(View2D *v2d, float matrix[4][4])
{
- rctf mask;
- unit_m4(matrix);
- BLI_rctf_rcti_copy(&mask, &v2d->mask);
- BLI_rctf_transform_calc_m4_pivot_min(&v2d->cur, &mask, matrix);
+ rctf mask;
+ unit_m4(matrix);
+ BLI_rctf_rcti_copy(&mask, &v2d->mask);
+ 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)
{
- 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)};
- rctf rect_tmp;
-
- BLI_assert(rect_src->xmin <= rect_src->xmax && rect_src->ymin <= rect_src->ymax);
-
- /* step 1: express given coordinates as proportional values */
- rect_tmp.xmin = (rect_src->xmin - v2d->cur.xmin) / cur_size[0];
- rect_tmp.xmax = (rect_src->xmax - v2d->cur.xmin) / cur_size[0];
- rect_tmp.ymin = (rect_src->ymin - v2d->cur.ymin) / cur_size[1];
- rect_tmp.ymax = (rect_src->ymax - v2d->cur.ymin) / cur_size[1];
-
- if (((rect_tmp.xmax < 0.0f) || (rect_tmp.xmin > 1.0f) ||
- (rect_tmp.ymax < 0.0f) || (rect_tmp.ymin > 1.0f)) == 0)
- {
- /* step 2: convert proportional distances to screen coordinates */
- rect_tmp.xmin = v2d->mask.xmin + (rect_tmp.xmin * mask_size[0]);
- rect_tmp.xmax = v2d->mask.ymin + (rect_tmp.xmax * mask_size[0]);
- rect_tmp.ymin = v2d->mask.ymin + (rect_tmp.ymin * mask_size[1]);
- rect_tmp.ymax = v2d->mask.ymin + (rect_tmp.ymax * mask_size[1]);
-
- clamp_rctf_to_rcti(rect_dst, &rect_tmp);
-
- return true;
- }
- else {
- rect_dst->xmin = rect_dst->xmax = rect_dst->ymin = rect_dst->ymax = V2D_IS_CLIPPED;
-
- return false;
- }
+ 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)};
+ rctf rect_tmp;
+
+ BLI_assert(rect_src->xmin <= rect_src->xmax && rect_src->ymin <= rect_src->ymax);
+
+ /* step 1: express given coordinates as proportional values */
+ rect_tmp.xmin = (rect_src->xmin - v2d->cur.xmin) / cur_size[0];
+ rect_tmp.xmax = (rect_src->xmax - v2d->cur.xmin) / cur_size[0];
+ rect_tmp.ymin = (rect_src->ymin - v2d->cur.ymin) / cur_size[1];
+ rect_tmp.ymax = (rect_src->ymax - v2d->cur.ymin) / cur_size[1];
+
+ if (((rect_tmp.xmax < 0.0f) || (rect_tmp.xmin > 1.0f) || (rect_tmp.ymax < 0.0f) ||
+ (rect_tmp.ymin > 1.0f)) == 0) {
+ /* step 2: convert proportional distances to screen coordinates */
+ rect_tmp.xmin = v2d->mask.xmin + (rect_tmp.xmin * mask_size[0]);
+ rect_tmp.xmax = v2d->mask.ymin + (rect_tmp.xmax * mask_size[0]);
+ rect_tmp.ymin = v2d->mask.ymin + (rect_tmp.ymin * mask_size[1]);
+ rect_tmp.ymax = v2d->mask.ymin + (rect_tmp.ymax * mask_size[1]);
+
+ clamp_rctf_to_rcti(rect_dst, &rect_tmp);
+
+ return true;
+ }
+ else {
+ rect_dst->xmin = rect_dst->xmax = rect_dst->ymin = rect_dst->ymax = V2D_IS_CLIPPED;
+
+ return false;
+ }
}
/* *********************************************************************** */
@@ -2448,38 +2479,37 @@ bool UI_view2d_view_to_region_rcti_clip(View2D *v2d, const rctf *rect_src, rcti
/* View2D data by default resides in region, so get from region stored in context */
View2D *UI_view2d_fromcontext(const bContext *C)
{
- ScrArea *area = CTX_wm_area(C);
- ARegion *region = CTX_wm_region(C);
-
- if (area == NULL) {
- return NULL;
- }
- if (region == NULL) {
- return NULL;
- }
- return &(region->v2d);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+
+ if (area == NULL) {
+ return NULL;
+ }
+ if (region == NULL) {
+ return NULL;
+ }
+ return &(region->v2d);
}
/* 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);
- ARegion *region = CTX_wm_region(C);
-
- if (sa == 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;
- }
- return &(region->v2d);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+
+ if (sa == 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;
+ }
+ return &(region->v2d);
}
-
/**
* Calculate the scale per-axis of the drawing-area
*
@@ -2490,32 +2520,32 @@ View2D *UI_view2d_fromcontext_rwin(const bContext *C)
*/
void UI_view2d_scale_get(View2D *v2d, float *r_x, float *r_y)
{
- if (r_x) {
- *r_x = UI_view2d_scale_get_x(v2d);
- }
- if (r_y) {
- *r_y = UI_view2d_scale_get_y(v2d);
- }
+ if (r_x) {
+ *r_x = UI_view2d_scale_get_x(v2d);
+ }
+ if (r_y) {
+ *r_y = UI_view2d_scale_get_y(v2d);
+ }
}
float UI_view2d_scale_get_x(const View2D *v2d)
{
- return BLI_rcti_size_x(&v2d->mask) / BLI_rctf_size_x(&v2d->cur);
+ return BLI_rcti_size_x(&v2d->mask) / BLI_rctf_size_x(&v2d->cur);
}
float UI_view2d_scale_get_y(const View2D *v2d)
{
- return BLI_rcti_size_y(&v2d->mask) / BLI_rctf_size_y(&v2d->cur);
+ return BLI_rcti_size_y(&v2d->mask) / BLI_rctf_size_y(&v2d->cur);
}
/**
* Same as ``UI_view2d_scale_get() - 1.0f / x, y``
*/
void UI_view2d_scale_get_inverse(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);
- }
- if (r_y) {
- *r_y = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
- }
+ if (r_x) {
+ *r_x = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
+ }
+ if (r_y) {
+ *r_y = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
+ }
}
/**
@@ -2524,20 +2554,20 @@ void UI_view2d_scale_get_inverse(View2D *v2d, float *r_x, float *r_y)
*/
void UI_view2d_center_get(struct View2D *v2d, float *r_x, float *r_y)
{
- /* get center */
- if (r_x) {
- *r_x = BLI_rctf_cent_x(&v2d->cur);
- }
- if (r_y) {
- *r_y = BLI_rctf_cent_y(&v2d->cur);
- }
+ /* get center */
+ if (r_x) {
+ *r_x = BLI_rctf_cent_x(&v2d->cur);
+ }
+ if (r_y) {
+ *r_y = BLI_rctf_cent_y(&v2d->cur);
+ }
}
void UI_view2d_center_set(struct View2D *v2d, float x, float y)
{
- BLI_rctf_recenter(&v2d->cur, x, y);
+ BLI_rctf_recenter(&v2d->cur, x, y);
- /* make sure that 'cur' rect is in a valid state as a result of these changes */
- UI_view2d_curRect_validate(v2d);
+ /* make sure that 'cur' rect is in a valid state as a result of these changes */
+ UI_view2d_curRect_validate(v2d);
}
/**
@@ -2548,25 +2578,25 @@ void UI_view2d_center_set(struct View2D *v2d, float x, float y)
*/
void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac)
{
- if (xfac != -1.0f) {
- const float xsize = BLI_rctf_size_x(&v2d->cur);
- const float xmin = v2d->tot.xmin;
- const float xmax = v2d->tot.xmax - xsize;
+ if (xfac != -1.0f) {
+ const float xsize = BLI_rctf_size_x(&v2d->cur);
+ const float xmin = v2d->tot.xmin;
+ const float xmax = v2d->tot.xmax - xsize;
- v2d->cur.xmin = (xmin * (1.0f - xfac)) + (xmax * xfac);
- v2d->cur.xmax = v2d->cur.xmin + xsize;
- }
+ v2d->cur.xmin = (xmin * (1.0f - xfac)) + (xmax * xfac);
+ v2d->cur.xmax = v2d->cur.xmin + xsize;
+ }
- if (yfac != -1.0f) {
- const float ysize = BLI_rctf_size_y(&v2d->cur);
- const float ymin = v2d->tot.ymin;
- const float ymax = v2d->tot.ymax - ysize;
+ if (yfac != -1.0f) {
+ const float ysize = BLI_rctf_size_y(&v2d->cur);
+ const float ymin = v2d->tot.ymin;
+ const float ymax = v2d->tot.ymax - ysize;
- v2d->cur.ymin = (ymin * (1.0f - yfac)) + (ymax * yfac);
- v2d->cur.ymax = v2d->cur.ymin + ysize;
- }
+ v2d->cur.ymin = (ymin * (1.0f - yfac)) + (ymax * yfac);
+ v2d->cur.ymax = v2d->cur.ymin + ysize;
+ }
- UI_view2d_curRect_validate(v2d);
+ UI_view2d_curRect_validate(v2d);
}
/**
@@ -2581,169 +2611,166 @@ 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 *ar, const View2D *v2d, int x, int y, int *r_scroll)
{
- int co[2];
- int scroll = view2d_scroll_mapped(v2d->scroll);
- *r_scroll = scroll;
-
- /* clamp x,y to region-coordinates first */
- co[0] = x - ar->winrct.xmin;
- co[1] = y - ar->winrct.ymin;
-
- /* check if within scrollbars */
- if (scroll & V2D_SCROLL_HORIZONTAL) {
- if (IN_2D_HORIZ_SCROLL(v2d, co)) {
- return 'h';
- }
- }
- if (scroll & V2D_SCROLL_VERTICAL) {
- if (IN_2D_VERT_SCROLL(v2d, co)) {
- return 'v';
- }
- }
-
- /* not found */
- return 0;
+ int co[2];
+ int scroll = view2d_scroll_mapped(v2d->scroll);
+ *r_scroll = scroll;
+
+ /* clamp x,y to region-coordinates first */
+ co[0] = x - ar->winrct.xmin;
+ co[1] = y - ar->winrct.ymin;
+
+ /* check if within scrollbars */
+ if (scroll & V2D_SCROLL_HORIZONTAL) {
+ if (IN_2D_HORIZ_SCROLL(v2d, co)) {
+ return 'h';
+ }
+ }
+ if (scroll & V2D_SCROLL_VERTICAL) {
+ if (IN_2D_VERT_SCROLL(v2d, co)) {
+ return 'v';
+ }
+ }
+
+ /* not found */
+ 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 *ar, const View2D *v2d, int x, int y)
{
- int scroll_dummy = 0;
- return UI_view2d_mouse_in_scrollers_ex(ar, v2d, x, y, &scroll_dummy);
+ int scroll_dummy = 0;
+ return UI_view2d_mouse_in_scrollers_ex(ar, v2d, x, y, &scroll_dummy);
}
/* ******************* view2d text drawing cache ******************** */
typedef struct View2DString {
- struct View2DString *next;
- union {
- uchar ub[4];
- int pack;
- } col;
- rcti rect;
- int mval[2];
-
- /* str is allocated past the end */
- char str[0];
+ struct View2DString *next;
+ union {
+ uchar ub[4];
+ int pack;
+ } col;
+ rcti rect;
+ int mval[2];
+
+ /* str is allocated past the end */
+ char str[0];
} View2DString;
/* assumes caches are used correctly, so for time being no local storage in v2d */
-static MemArena *g_v2d_strings_arena = NULL;
+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 char col[4])
{
- int mval[2];
+ int mval[2];
- BLI_assert(str_len == strlen(str));
+ BLI_assert(str_len == strlen(str));
- if (UI_view2d_view_to_region_clip(v2d, x, y, &mval[0], &mval[1])) {
- int alloc_len = str_len + 1;
- View2DString *v2s;
+ if (UI_view2d_view_to_region_clip(v2d, x, y, &mval[0], &mval[1])) {
+ int alloc_len = str_len + 1;
+ View2DString *v2s;
- if (g_v2d_strings_arena == NULL) {
- g_v2d_strings_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 14), __func__);
- }
+ if (g_v2d_strings_arena == NULL) {
+ g_v2d_strings_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 14), __func__);
+ }
- v2s = BLI_memarena_alloc(g_v2d_strings_arena, sizeof(View2DString) + alloc_len);
+ v2s = BLI_memarena_alloc(g_v2d_strings_arena, sizeof(View2DString) + alloc_len);
- BLI_LINKS_PREPEND(g_v2d_strings, v2s);
+ BLI_LINKS_PREPEND(g_v2d_strings, v2s);
- v2s->col.pack = *((const int *)col);
+ v2s->col.pack = *((const int *)col);
- memset(&v2s->rect, 0, sizeof(v2s->rect));
+ memset(&v2s->rect, 0, sizeof(v2s->rect));
- v2s->mval[0] = mval[0];
- v2s->mval[1] = mval[1];
+ v2s->mval[0] = mval[0];
+ v2s->mval[1] = mval[1];
- memcpy(v2s->str, str, alloc_len);
- }
+ memcpy(v2s->str, str, alloc_len);
+ }
}
/* 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 char col[4])
{
- rcti rect;
+ rcti rect;
- BLI_assert(str_len == strlen(str));
+ BLI_assert(str_len == strlen(str));
- if (UI_view2d_view_to_region_rcti_clip(v2d, rect_view, &rect)) {
- int alloc_len = str_len + 1;
- View2DString *v2s;
+ if (UI_view2d_view_to_region_rcti_clip(v2d, rect_view, &rect)) {
+ int alloc_len = str_len + 1;
+ View2DString *v2s;
- if (g_v2d_strings_arena == NULL) {
- g_v2d_strings_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 14), __func__);
- }
+ if (g_v2d_strings_arena == NULL) {
+ g_v2d_strings_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 14), __func__);
+ }
- v2s = BLI_memarena_alloc(g_v2d_strings_arena, sizeof(View2DString) + alloc_len);
+ v2s = BLI_memarena_alloc(g_v2d_strings_arena, sizeof(View2DString) + alloc_len);
- BLI_LINKS_PREPEND(g_v2d_strings, v2s);
+ BLI_LINKS_PREPEND(g_v2d_strings, v2s);
- v2s->col.pack = *((const int *)col);
+ v2s->col.pack = *((const int *)col);
- v2s->rect = rect;
+ v2s->rect = rect;
- v2s->mval[0] = v2s->rect.xmin;
- v2s->mval[1] = v2s->rect.ymin;
+ v2s->mval[0] = v2s->rect.xmin;
+ v2s->mval[1] = v2s->rect.ymin;
- memcpy(v2s->str, str, alloc_len);
- }
+ memcpy(v2s->str, str, alloc_len);
+ }
}
-
void UI_view2d_text_cache_draw(ARegion *ar)
{
- View2DString *v2s;
- int col_pack_prev = 0;
-
- /* investigate using BLF_ascender() */
- const int font_id = BLF_default();
-
- BLF_set_default();
- const float default_height = g_v2d_strings ? BLF_height(font_id, "28", 3) : 0.0f;
-
- wmOrtho2_region_pixelspace(ar);
-
- for (v2s = g_v2d_strings; v2s; v2s = v2s->next) {
- int xofs = 0, yofs;
-
- yofs = ceil(0.5f * (BLI_rcti_size_y(&v2s->rect) - default_height));
- if (yofs < 1) {
- yofs = 1;
- }
-
- if (col_pack_prev != v2s->col.pack) {
- BLF_color3ubv(font_id, v2s->col.ub);
- col_pack_prev = v2s->col.pack;
- }
-
- if (v2s->rect.xmin >= v2s->rect.xmax) {
- BLF_draw_default(
- (float)(v2s->mval[0] + xofs), (float)(v2s->mval[1] + yofs), 0.0,
- v2s->str, BLF_DRAW_STR_DUMMY_MAX);
- }
- else {
- BLF_enable(font_id, BLF_CLIPPING);
- BLF_clipping(font_id, v2s->rect.xmin - 4, v2s->rect.ymin - 4, v2s->rect.xmax + 4, v2s->rect.ymax + 4);
- BLF_draw_default(v2s->rect.xmin + xofs, v2s->rect.ymin + yofs, 0.0f,
- v2s->str, BLF_DRAW_STR_DUMMY_MAX);
- BLF_disable(font_id, BLF_CLIPPING);
- }
- }
- g_v2d_strings = NULL;
-
- if (g_v2d_strings_arena) {
- BLI_memarena_free(g_v2d_strings_arena);
- g_v2d_strings_arena = NULL;
- }
+ View2DString *v2s;
+ int col_pack_prev = 0;
+
+ /* investigate using BLF_ascender() */
+ const int font_id = BLF_default();
+
+ BLF_set_default();
+ const float default_height = g_v2d_strings ? BLF_height(font_id, "28", 3) : 0.0f;
+
+ wmOrtho2_region_pixelspace(ar);
+
+ for (v2s = g_v2d_strings; v2s; v2s = v2s->next) {
+ int xofs = 0, yofs;
+
+ yofs = ceil(0.5f * (BLI_rcti_size_y(&v2s->rect) - default_height));
+ if (yofs < 1) {
+ yofs = 1;
+ }
+
+ if (col_pack_prev != v2s->col.pack) {
+ BLF_color3ubv(font_id, v2s->col.ub);
+ col_pack_prev = v2s->col.pack;
+ }
+
+ if (v2s->rect.xmin >= v2s->rect.xmax) {
+ BLF_draw_default((float)(v2s->mval[0] + xofs),
+ (float)(v2s->mval[1] + yofs),
+ 0.0,
+ v2s->str,
+ BLF_DRAW_STR_DUMMY_MAX);
+ }
+ else {
+ BLF_enable(font_id, BLF_CLIPPING);
+ BLF_clipping(
+ font_id, v2s->rect.xmin - 4, v2s->rect.ymin - 4, v2s->rect.xmax + 4, v2s->rect.ymax + 4);
+ BLF_draw_default(
+ v2s->rect.xmin + xofs, v2s->rect.ymin + yofs, 0.0f, v2s->str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_disable(font_id, BLF_CLIPPING);
+ }
+ }
+ g_v2d_strings = NULL;
+
+ if (g_v2d_strings_arena) {
+ BLI_memarena_free(g_v2d_strings_arena);
+ g_v2d_strings_arena = NULL;
+ }
}
-
/* ******************************************************** */
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 62d434584fe..855ad0306c4 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -21,7 +21,6 @@
* \ingroup edinterface
*/
-
#include <math.h>
#include "MEM_guardedalloc.h"
@@ -50,13 +49,13 @@
static bool view2d_poll(bContext *C)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *ar = CTX_wm_region(C);
- return (ar != NULL) && (ar->v2d.flag & V2D_IS_INITIALISED);
+ return (ar != NULL) && (ar->v2d.flag & V2D_IS_INITIALISED);
}
/* ********************************************************* */
-/* VIEW PANNING OPERATOR */
+/* VIEW PANNING OPERATOR */
/**
* This group of operators come in several forms:
@@ -71,139 +70,135 @@ static bool view2d_poll(bContext *C)
/* temp customdata for operator */
typedef struct v2dViewPanData {
- /** screen where view pan was initiated */
- bScreen *sc;
- /** area where view pan was initiated */
- ScrArea *sa;
- /** region where view pan was initiated */
- ARegion *ar;
- /** view2d we're operating in */
- View2D *v2d;
-
- /** amount to move view relative to zoom */
- float facx, facy;
-
- /* options for version 1 */
- /** mouse x/y values in window when operator was initiated */
- int startx, starty;
- /** previous x/y values of mouse in window */
- int lastx, lasty;
- /** event starting pan, for modal exit */
- int invoke_event;
-
- /** for MMB in scrollers (old feature in past, but now not that useful) */
- short in_scroller;
+ /** screen where view pan was initiated */
+ bScreen *sc;
+ /** area where view pan was initiated */
+ ScrArea *sa;
+ /** region where view pan was initiated */
+ ARegion *ar;
+ /** view2d we're operating in */
+ View2D *v2d;
+
+ /** amount to move view relative to zoom */
+ float facx, facy;
+
+ /* options for version 1 */
+ /** mouse x/y values in window when operator was initiated */
+ int startx, starty;
+ /** previous x/y values of mouse in window */
+ int lastx, lasty;
+ /** event starting pan, for modal exit */
+ int invoke_event;
+
+ /** for MMB in scrollers (old feature in past, but now not that useful) */
+ short in_scroller;
} v2dViewPanData;
/* initialize panning customdata */
static int view_pan_init(bContext *C, wmOperator *op)
{
- ARegion *ar = 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) {
- return 0;
- }
-
- /* check if panning is allowed at all */
- v2d = &ar->v2d;
- if ((v2d->keepofs & V2D_LOCKOFS_X) && (v2d->keepofs & V2D_LOCKOFS_Y)) {
- return 0;
- }
-
- /* set custom-data for operator */
- vpd = MEM_callocN(sizeof(v2dViewPanData), "v2dViewPanData");
- op->customdata = vpd;
-
- /* set pointers to owners */
- vpd->sc = CTX_wm_screen(C);
- vpd->sa = CTX_wm_area(C);
- vpd->v2d = v2d;
- vpd->ar = ar;
-
- /* 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);
- vpd->facx = (BLI_rctf_size_x(&v2d->cur)) / winx;
- vpd->facy = (BLI_rctf_size_y(&v2d->cur)) / winy;
-
- return 1;
+ ARegion *ar = 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) {
+ return 0;
+ }
+
+ /* check if panning is allowed at all */
+ v2d = &ar->v2d;
+ if ((v2d->keepofs & V2D_LOCKOFS_X) && (v2d->keepofs & V2D_LOCKOFS_Y)) {
+ return 0;
+ }
+
+ /* set custom-data for operator */
+ vpd = MEM_callocN(sizeof(v2dViewPanData), "v2dViewPanData");
+ op->customdata = vpd;
+
+ /* set pointers to owners */
+ vpd->sc = CTX_wm_screen(C);
+ vpd->sa = CTX_wm_area(C);
+ vpd->v2d = v2d;
+ vpd->ar = ar;
+
+ /* 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);
+ vpd->facx = (BLI_rctf_size_x(&v2d->cur)) / winx;
+ vpd->facy = (BLI_rctf_size_y(&v2d->cur)) / winy;
+
+ return 1;
}
#ifdef WITH_INPUT_NDOF
static bool view_pan_poll(bContext *C)
{
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d;
-
- /* check if there's a region in context to work with */
- if (ar == NULL) {
- return 0;
- }
- v2d = &ar->v2d;
-
- /* check that 2d-view can pan */
- if ((v2d->keepofs & V2D_LOCKOFS_X) && (v2d->keepofs & V2D_LOCKOFS_Y)) {
- return 0;
- }
-
- /* view can pan */
- return 1;
+ ARegion *ar = CTX_wm_region(C);
+ View2D *v2d;
+
+ /* check if there's a region in context to work with */
+ if (ar == NULL) {
+ return 0;
+ }
+ v2d = &ar->v2d;
+
+ /* check that 2d-view can pan */
+ if ((v2d->keepofs & V2D_LOCKOFS_X) && (v2d->keepofs & V2D_LOCKOFS_Y)) {
+ return 0;
+ }
+
+ /* view can pan */
+ return 1;
}
#endif
/* apply transform to view (i.e. adjust 'cur' rect) */
static void view_pan_apply_ex(bContext *C, v2dViewPanData *vpd, float dx, float dy)
{
- View2D *v2d = vpd->v2d;
+ View2D *v2d = vpd->v2d;
- /* calculate amount to move view by */
- dx *= vpd->facx;
- dy *= vpd->facy;
+ /* calculate amount to move view by */
+ dx *= vpd->facx;
+ dy *= vpd->facy;
- /* only move view on an axis if change is allowed */
- if ((v2d->keepofs & V2D_LOCKOFS_X) == 0) {
- v2d->cur.xmin += dx;
- v2d->cur.xmax += dx;
- }
- if ((v2d->keepofs & V2D_LOCKOFS_Y) == 0) {
- v2d->cur.ymin += dy;
- v2d->cur.ymax += dy;
- }
+ /* only move view on an axis if change is allowed */
+ if ((v2d->keepofs & V2D_LOCKOFS_X) == 0) {
+ v2d->cur.xmin += dx;
+ v2d->cur.xmax += dx;
+ }
+ if ((v2d->keepofs & V2D_LOCKOFS_Y) == 0) {
+ v2d->cur.ymin += dy;
+ v2d->cur.ymax += dy;
+ }
- /* validate that view is in valid configuration after this operation */
- UI_view2d_curRect_validate(v2d);
+ /* validate that view is in valid configuration after this operation */
+ 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);
+ /* don't rebuild full tree in outliner, since we're just changing our view */
+ ED_region_tag_redraw_no_rebuild(vpd->ar);
- /* request updates to be done... */
- WM_event_add_mousemove(C);
+ /* request updates to be done... */
+ WM_event_add_mousemove(C);
- UI_view2d_sync(vpd->sc, vpd->sa, v2d, V2D_LOCK_COPY);
+ UI_view2d_sync(vpd->sc, vpd->sa, v2d, V2D_LOCK_COPY);
}
static void view_pan_apply(bContext *C, wmOperator *op)
{
- v2dViewPanData *vpd = op->customdata;
-
- view_pan_apply_ex(
- C, vpd,
- RNA_int_get(op->ptr, "deltax"),
- RNA_int_get(op->ptr, "deltay"));
+ v2dViewPanData *vpd = op->customdata;
+ view_pan_apply_ex(C, vpd, RNA_int_get(op->ptr, "deltax"), RNA_int_get(op->ptr, "deltay"));
}
/* cleanup temp customdata */
static void view_pan_exit(wmOperator *op)
{
- if (op->customdata) {
- MEM_freeN(op->customdata);
- op->customdata = NULL;
- }
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+ }
}
/* ------------------ Modal Drag Version (1) ---------------------- */
@@ -211,141 +206,140 @@ static void view_pan_exit(wmOperator *op)
/* for 'redo' only, with no user input */
static int view_pan_exec(bContext *C, wmOperator *op)
{
- if (!view_pan_init(C, op)) {
- return OPERATOR_CANCELLED;
- }
+ if (!view_pan_init(C, op)) {
+ return OPERATOR_CANCELLED;
+ }
- view_pan_apply(C, op);
- view_pan_exit(op);
- return OPERATOR_FINISHED;
+ view_pan_apply(C, op);
+ view_pan_exit(op);
+ return OPERATOR_FINISHED;
}
/* set up modal operator and relevant settings */
static int view_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- wmWindow *window = CTX_wm_window(C);
- v2dViewPanData *vpd;
- View2D *v2d;
-
- /* set up customdata */
- if (!view_pan_init(C, op)) {
- return OPERATOR_PASS_THROUGH;
- }
-
- vpd = op->customdata;
- v2d = vpd->v2d;
-
- /* set initial settings */
- vpd->startx = vpd->lastx = event->x;
- vpd->starty = vpd->lasty = event->y;
- vpd->invoke_event = event->type;
-
- if (event->type == MOUSEPAN) {
- RNA_int_set(op->ptr, "deltax", event->prevx - event->x);
- RNA_int_set(op->ptr, "deltay", event->prevy - event->y);
-
- view_pan_apply(C, op);
- view_pan_exit(op);
- return OPERATOR_FINISHED;
- }
-
- RNA_int_set(op->ptr, "deltax", 0);
- RNA_int_set(op->ptr, "deltay", 0);
-
- if (v2d->keepofs & V2D_LOCKOFS_X) {
- WM_cursor_modal_set(window, BC_NS_SCROLLCURSOR);
- }
- else if (v2d->keepofs & V2D_LOCKOFS_Y) {
- WM_cursor_modal_set(window, BC_EW_SCROLLCURSOR);
- }
- else {
- WM_cursor_modal_set(window, BC_NSEW_SCROLLCURSOR);
- }
-
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
+ wmWindow *window = CTX_wm_window(C);
+ v2dViewPanData *vpd;
+ View2D *v2d;
+
+ /* set up customdata */
+ if (!view_pan_init(C, op)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ vpd = op->customdata;
+ v2d = vpd->v2d;
+
+ /* set initial settings */
+ vpd->startx = vpd->lastx = event->x;
+ vpd->starty = vpd->lasty = event->y;
+ vpd->invoke_event = event->type;
+
+ if (event->type == MOUSEPAN) {
+ RNA_int_set(op->ptr, "deltax", event->prevx - event->x);
+ RNA_int_set(op->ptr, "deltay", event->prevy - event->y);
+
+ view_pan_apply(C, op);
+ view_pan_exit(op);
+ return OPERATOR_FINISHED;
+ }
+
+ RNA_int_set(op->ptr, "deltax", 0);
+ RNA_int_set(op->ptr, "deltay", 0);
+
+ if (v2d->keepofs & V2D_LOCKOFS_X) {
+ WM_cursor_modal_set(window, BC_NS_SCROLLCURSOR);
+ }
+ else if (v2d->keepofs & V2D_LOCKOFS_Y) {
+ WM_cursor_modal_set(window, BC_EW_SCROLLCURSOR);
+ }
+ else {
+ WM_cursor_modal_set(window, BC_NSEW_SCROLLCURSOR);
+ }
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
}
/* handle user input - calculations of mouse-movement
* need to be done here, not in the apply callback! */
static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- v2dViewPanData *vpd = op->customdata;
-
- /* execute the events */
- switch (event->type) {
- case MOUSEMOVE:
- {
- /* calculate new delta transform, then store mouse-coordinates for next-time */
- RNA_int_set(op->ptr, "deltax", (vpd->lastx - event->x));
- RNA_int_set(op->ptr, "deltay", (vpd->lasty - event->y));
-
- vpd->lastx = event->x;
- vpd->lasty = event->y;
-
- view_pan_apply(C, op);
- break;
- }
- /* XXX - Mode switching isn't implemented. See comments in 36818.
- * switch to zoom */
+ v2dViewPanData *vpd = op->customdata;
+
+ /* execute the events */
+ switch (event->type) {
+ case MOUSEMOVE: {
+ /* calculate new delta transform, then store mouse-coordinates for next-time */
+ RNA_int_set(op->ptr, "deltax", (vpd->lastx - event->x));
+ RNA_int_set(op->ptr, "deltay", (vpd->lasty - event->y));
+
+ vpd->lastx = event->x;
+ vpd->lasty = event->y;
+
+ view_pan_apply(C, op);
+ break;
+ }
+ /* XXX - Mode switching isn't implemented. See comments in 36818.
+ * switch to zoom */
#if 0
- case LEFTMOUSE:
- if (event->val == KM_PRESS) {
- /* calculate overall delta mouse-movement for redo */
- RNA_int_set(op->ptr, "deltax", (vpd->startx - vpd->lastx));
- RNA_int_set(op->ptr, "deltay", (vpd->starty - vpd->lasty));
-
- view_pan_exit(op);
- WM_cursor_modal_restore(CTX_wm_window(C));
- WM_operator_name_call(C, "VIEW2D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL);
- return OPERATOR_FINISHED;
- }
+ case LEFTMOUSE:
+ if (event->val == KM_PRESS) {
+ /* calculate overall delta mouse-movement for redo */
+ RNA_int_set(op->ptr, "deltax", (vpd->startx - vpd->lastx));
+ RNA_int_set(op->ptr, "deltay", (vpd->starty - vpd->lasty));
+
+ view_pan_exit(op);
+ WM_cursor_modal_restore(CTX_wm_window(C));
+ WM_operator_name_call(C, "VIEW2D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL);
+ return OPERATOR_FINISHED;
+ }
#endif
- default:
- if (event->type == vpd->invoke_event || event->type == ESCKEY) {
- if (event->val == KM_RELEASE) {
- /* calculate overall delta mouse-movement for redo */
- RNA_int_set(op->ptr, "deltax", (vpd->startx - vpd->lastx));
- RNA_int_set(op->ptr, "deltay", (vpd->starty - vpd->lasty));
-
- view_pan_exit(op);
- WM_cursor_modal_restore(CTX_wm_window(C));
-
- return OPERATOR_FINISHED;
- }
- }
- break;
- }
-
- return OPERATOR_RUNNING_MODAL;
+ default:
+ if (event->type == vpd->invoke_event || event->type == ESCKEY) {
+ if (event->val == KM_RELEASE) {
+ /* calculate overall delta mouse-movement for redo */
+ RNA_int_set(op->ptr, "deltax", (vpd->startx - vpd->lastx));
+ RNA_int_set(op->ptr, "deltay", (vpd->starty - vpd->lasty));
+
+ view_pan_exit(op);
+ WM_cursor_modal_restore(CTX_wm_window(C));
+
+ return OPERATOR_FINISHED;
+ }
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
static void view_pan_cancel(bContext *UNUSED(C), wmOperator *op)
{
- view_pan_exit(op);
+ view_pan_exit(op);
}
static void VIEW2D_OT_pan(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Pan View";
- ot->description = "Pan the view";
- ot->idname = "VIEW2D_OT_pan";
-
- /* api callbacks */
- ot->exec = view_pan_exec;
- ot->invoke = view_pan_invoke;
- ot->modal = view_pan_modal;
- ot->cancel = view_pan_cancel;
-
- /* operator is modal */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
-
- /* rna - must keep these in sync with the other operators */
- RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
+ /* identifiers */
+ ot->name = "Pan View";
+ ot->description = "Pan the view";
+ ot->idname = "VIEW2D_OT_pan";
+
+ /* api callbacks */
+ ot->exec = view_pan_exec;
+ ot->invoke = view_pan_invoke;
+ ot->modal = view_pan_modal;
+ ot->cancel = view_pan_cancel;
+
+ /* operator is modal */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
+
+ /* rna - must keep these in sync with the other operators */
+ RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
}
/* ------------------ Scrollwheel Versions (2) ---------------------- */
@@ -353,196 +347,191 @@ static void VIEW2D_OT_pan(wmOperatorType *ot)
/* this operator only needs this single callback, where it calls the view_pan_*() methods */
static int view_scrollright_exec(bContext *C, wmOperator *op)
{
- v2dViewPanData *vpd;
+ v2dViewPanData *vpd;
- /* initialize default settings (and validate if ok to run) */
- if (!view_pan_init(C, op)) {
- return OPERATOR_PASS_THROUGH;
- }
+ /* initialize default settings (and validate if ok to run) */
+ if (!view_pan_init(C, op)) {
+ return OPERATOR_PASS_THROUGH;
+ }
- /* also, check if can pan in horizontal axis */
- vpd = op->customdata;
- if (vpd->v2d->keepofs & V2D_LOCKOFS_X) {
- view_pan_exit(op);
- return OPERATOR_PASS_THROUGH;
- }
+ /* also, check if can pan in horizontal axis */
+ vpd = op->customdata;
+ if (vpd->v2d->keepofs & V2D_LOCKOFS_X) {
+ view_pan_exit(op);
+ return OPERATOR_PASS_THROUGH;
+ }
- /* set RNA-Props - only movement in positive x-direction */
- RNA_int_set(op->ptr, "deltax", 40);
- RNA_int_set(op->ptr, "deltay", 0);
+ /* set RNA-Props - only movement in positive x-direction */
+ RNA_int_set(op->ptr, "deltax", 40);
+ RNA_int_set(op->ptr, "deltay", 0);
- /* apply movement, then we're done */
- view_pan_apply(C, op);
- view_pan_exit(op);
+ /* apply movement, then we're done */
+ view_pan_apply(C, op);
+ view_pan_exit(op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void VIEW2D_OT_scroll_right(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Scroll Right";
- ot->description = "Scroll the view right";
- ot->idname = "VIEW2D_OT_scroll_right";
+ /* identifiers */
+ ot->name = "Scroll Right";
+ ot->description = "Scroll the view right";
+ ot->idname = "VIEW2D_OT_scroll_right";
- /* api callbacks */
- ot->exec = view_scrollright_exec;
+ /* api callbacks */
+ ot->exec = view_scrollright_exec;
- /* rna - must keep these in sync with the other operators */
- RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
+ /* rna - must keep these in sync with the other operators */
+ RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
}
-
-
/* this operator only needs this single callback, where it calls the view_pan_*() methods */
static int view_scrollleft_exec(bContext *C, wmOperator *op)
{
- v2dViewPanData *vpd;
+ v2dViewPanData *vpd;
- /* initialize default settings (and validate if ok to run) */
- if (!view_pan_init(C, op)) {
- return OPERATOR_PASS_THROUGH;
- }
+ /* initialize default settings (and validate if ok to run) */
+ if (!view_pan_init(C, op)) {
+ return OPERATOR_PASS_THROUGH;
+ }
- /* also, check if can pan in horizontal axis */
- vpd = op->customdata;
- if (vpd->v2d->keepofs & V2D_LOCKOFS_X) {
- view_pan_exit(op);
- return OPERATOR_PASS_THROUGH;
- }
+ /* also, check if can pan in horizontal axis */
+ vpd = op->customdata;
+ if (vpd->v2d->keepofs & V2D_LOCKOFS_X) {
+ view_pan_exit(op);
+ return OPERATOR_PASS_THROUGH;
+ }
- /* set RNA-Props - only movement in negative x-direction */
- RNA_int_set(op->ptr, "deltax", -40);
- RNA_int_set(op->ptr, "deltay", 0);
+ /* set RNA-Props - only movement in negative x-direction */
+ RNA_int_set(op->ptr, "deltax", -40);
+ RNA_int_set(op->ptr, "deltay", 0);
- /* apply movement, then we're done */
- view_pan_apply(C, op);
- view_pan_exit(op);
+ /* apply movement, then we're done */
+ view_pan_apply(C, op);
+ view_pan_exit(op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void VIEW2D_OT_scroll_left(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Scroll Left";
- ot->description = "Scroll the view left";
- ot->idname = "VIEW2D_OT_scroll_left";
+ /* identifiers */
+ ot->name = "Scroll Left";
+ ot->description = "Scroll the view left";
+ ot->idname = "VIEW2D_OT_scroll_left";
- /* api callbacks */
- ot->exec = view_scrollleft_exec;
+ /* api callbacks */
+ ot->exec = view_scrollleft_exec;
- /* rna - must keep these in sync with the other operators */
- RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
+ /* rna - must keep these in sync with the other operators */
+ RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
}
-
/* this operator only needs this single callback, where it calls the view_pan_*() methods */
static int view_scrolldown_exec(bContext *C, wmOperator *op)
{
- v2dViewPanData *vpd;
-
- /* initialize default settings (and validate if ok to run) */
- if (!view_pan_init(C, op)) {
- return OPERATOR_PASS_THROUGH;
- }
-
- /* also, check if can pan in vertical axis */
- vpd = op->customdata;
- if (vpd->v2d->keepofs & V2D_LOCKOFS_Y) {
- view_pan_exit(op);
- return OPERATOR_PASS_THROUGH;
- }
-
- /* set RNA-Props */
- RNA_int_set(op->ptr, "deltax", 0);
- RNA_int_set(op->ptr, "deltay", -40);
-
- 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);
- }
-
- /* apply movement, then we're done */
- view_pan_apply(C, op);
- view_pan_exit(op);
-
- return OPERATOR_FINISHED;
+ v2dViewPanData *vpd;
+
+ /* initialize default settings (and validate if ok to run) */
+ if (!view_pan_init(C, op)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ /* also, check if can pan in vertical axis */
+ vpd = op->customdata;
+ if (vpd->v2d->keepofs & V2D_LOCKOFS_Y) {
+ view_pan_exit(op);
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ /* set RNA-Props */
+ RNA_int_set(op->ptr, "deltax", 0);
+ RNA_int_set(op->ptr, "deltay", -40);
+
+ 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);
+ }
+
+ /* apply movement, then we're done */
+ view_pan_apply(C, op);
+ view_pan_exit(op);
+
+ return OPERATOR_FINISHED;
}
static void VIEW2D_OT_scroll_down(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Scroll Down";
- ot->description = "Scroll the view down";
- ot->idname = "VIEW2D_OT_scroll_down";
-
- /* api callbacks */
- ot->exec = view_scrolldown_exec;
-
- /* rna - must keep these in sync with the other operators */
- RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
- RNA_def_boolean(ot->srna, "page", 0, "Page", "Scroll down one page");
+ /* identifiers */
+ ot->name = "Scroll Down";
+ ot->description = "Scroll the view down";
+ ot->idname = "VIEW2D_OT_scroll_down";
+
+ /* api callbacks */
+ ot->exec = view_scrolldown_exec;
+
+ /* rna - must keep these in sync with the other operators */
+ RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
+ RNA_def_boolean(ot->srna, "page", 0, "Page", "Scroll down one page");
}
-
-
/* this operator only needs this single callback, where it calls the view_pan_*() methods */
static int view_scrollup_exec(bContext *C, wmOperator *op)
{
- v2dViewPanData *vpd;
-
- /* initialize default settings (and validate if ok to run) */
- if (!view_pan_init(C, op)) {
- return OPERATOR_PASS_THROUGH;
- }
-
- /* also, check if can pan in vertical axis */
- vpd = op->customdata;
- if (vpd->v2d->keepofs & V2D_LOCKOFS_Y) {
- view_pan_exit(op);
- return OPERATOR_PASS_THROUGH;
- }
-
- /* set RNA-Props */
- RNA_int_set(op->ptr, "deltax", 0);
- RNA_int_set(op->ptr, "deltay", 40);
-
- 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));
- }
-
- /* apply movement, then we're done */
- view_pan_apply(C, op);
- view_pan_exit(op);
-
- return OPERATOR_FINISHED;
+ v2dViewPanData *vpd;
+
+ /* initialize default settings (and validate if ok to run) */
+ if (!view_pan_init(C, op)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ /* also, check if can pan in vertical axis */
+ vpd = op->customdata;
+ if (vpd->v2d->keepofs & V2D_LOCKOFS_Y) {
+ view_pan_exit(op);
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ /* set RNA-Props */
+ RNA_int_set(op->ptr, "deltax", 0);
+ RNA_int_set(op->ptr, "deltay", 40);
+
+ 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));
+ }
+
+ /* apply movement, then we're done */
+ view_pan_apply(C, op);
+ view_pan_exit(op);
+
+ return OPERATOR_FINISHED;
}
static void VIEW2D_OT_scroll_up(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Scroll Up";
- ot->description = "Scroll the view up";
- ot->idname = "VIEW2D_OT_scroll_up";
-
- /* api callbacks */
- ot->exec = view_scrollup_exec;
-
- /* rna - must keep these in sync with the other operators */
- RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
- RNA_def_boolean(ot->srna, "page", 0, "Page", "Scroll up one page");
+ /* identifiers */
+ ot->name = "Scroll Up";
+ ot->description = "Scroll the view up";
+ ot->idname = "VIEW2D_OT_scroll_up";
+
+ /* api callbacks */
+ ot->exec = view_scrollup_exec;
+
+ /* rna - must keep these in sync with the other operators */
+ RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
+ RNA_def_boolean(ot->srna, "page", 0, "Page", "Scroll up one page");
}
/* ********************************************************* */
-/* SINGLE-STEP VIEW ZOOMING OPERATOR */
+/* SINGLE-STEP VIEW ZOOMING OPERATOR */
/**
* This group of operators come in several forms:
@@ -562,17 +551,17 @@ static void VIEW2D_OT_scroll_up(wmOperatorType *ot)
/* temp customdata for operator */
typedef struct v2dViewZoomData {
- View2D *v2d; /* view2d we're operating in */
- ARegion *ar;
+ View2D *v2d; /* view2d we're operating in */
+ ARegion *ar;
- /* needed for continuous zoom */
- wmTimer *timer;
- double timer_lastdraw;
+ /* needed for continuous zoom */
+ wmTimer *timer;
+ double timer_lastdraw;
- int lastx, lasty; /* previous x/y values of mouse in window */
- int invoke_event; /* event type that invoked, for modal exits */
- float dx, dy; /* running tally of previous delta values (for obtaining final zoom) */
- float mx_2d, my_2d; /* initial mouse location in v2d coords */
+ int lastx, lasty; /* previous x/y values of mouse in window */
+ int invoke_event; /* event type that invoked, for modal exits */
+ float dx, dy; /* running tally of previous delta values (for obtaining final zoom) */
+ float mx_2d, my_2d; /* initial mouse location in v2d coords */
} v2dViewZoomData;
/**
@@ -581,195 +570,190 @@ 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 *sa = CTX_wm_area(C);
- r_do_zoom_xy[0] = true;
- r_do_zoom_xy[1] = true;
+ 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);
+ /* default not to zoom the sequencer vertically */
+ if (sa && sa->spacetype == SPACE_SEQ) {
+ ARegion *ar = CTX_wm_region(C);
- if (ar && ar->regiontype == RGN_TYPE_WINDOW) {
- r_do_zoom_xy[1] = false;
- }
- }
+ if (ar && ar->regiontype == RGN_TYPE_WINDOW) {
+ r_do_zoom_xy[1] = false;
+ }
+ }
}
/* initialize panning customdata */
static int view_zoomdrag_init(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
- v2dViewZoomData *vzd;
- View2D *v2d;
-
- /* regions now have v2d-data by default, so check for region */
- if (ar == NULL) {
- return 0;
- }
- v2d = &ar->v2d;
-
- /* check that 2d-view is zoomable */
- if ((v2d->keepzoom & V2D_LOCKZOOM_X) && (v2d->keepzoom & V2D_LOCKZOOM_Y)) {
- return 0;
- }
-
- /* set custom-data for operator */
- vzd = MEM_callocN(sizeof(v2dViewZoomData), "v2dViewZoomData");
- op->customdata = vzd;
-
- /* set pointers to owners */
- vzd->v2d = v2d;
- vzd->ar = ar;
-
- return 1;
+ ARegion *ar = CTX_wm_region(C);
+ v2dViewZoomData *vzd;
+ View2D *v2d;
+
+ /* regions now have v2d-data by default, so check for region */
+ if (ar == NULL) {
+ return 0;
+ }
+ v2d = &ar->v2d;
+
+ /* check that 2d-view is zoomable */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X) && (v2d->keepzoom & V2D_LOCKZOOM_Y)) {
+ return 0;
+ }
+
+ /* set custom-data for operator */
+ vzd = MEM_callocN(sizeof(v2dViewZoomData), "v2dViewZoomData");
+ op->customdata = vzd;
+
+ /* set pointers to owners */
+ vzd->v2d = v2d;
+ vzd->ar = ar;
+
+ return 1;
}
/* check if step-zoom can be applied */
static bool view_zoom_poll(bContext *C)
{
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d;
+ ARegion *ar = CTX_wm_region(C);
+ View2D *v2d;
- /* check if there's a region in context to work with */
- if (ar == NULL) {
- return false;
- }
+ /* check if there's a region in context to work with */
+ if (ar == NULL) {
+ return false;
+ }
- /* Do not show that in 3DView context. */
- if (CTX_wm_region_view3d(C)) {
- return false;
- }
+ /* Do not show that in 3DView context. */
+ if (CTX_wm_region_view3d(C)) {
+ return false;
+ }
- v2d = &ar->v2d;
+ v2d = &ar->v2d;
- /* check that 2d-view is zoomable */
- if ((v2d->keepzoom & V2D_LOCKZOOM_X) && (v2d->keepzoom & V2D_LOCKZOOM_Y)) {
- return false;
- }
+ /* check that 2d-view is zoomable */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X) && (v2d->keepzoom & V2D_LOCKZOOM_Y)) {
+ return false;
+ }
- /* view is zoomable */
- return true;
+ /* view is zoomable */
+ return true;
}
/* apply transform to view (i.e. adjust 'cur' rect) */
static void view_zoomstep_apply_ex(
- bContext *C, v2dViewZoomData *vzd, const bool use_mousepos,
- const float facx, const float facy)
+ bContext *C, v2dViewZoomData *vzd, const bool use_mousepos, const float facx, const float facy)
{
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = &ar->v2d;
- const rctf cur_old = v2d->cur;
- float dx, dy;
- const int snap_test = ED_region_snap_size_test(ar);
-
- /* calculate amount to move view by, ensuring symmetry so the
- * old zoom level is restored after zooming back the same amount
- */
- if (facx >= 0.0f) {
- dx = BLI_rctf_size_x(&v2d->cur) * facx;
- dy = BLI_rctf_size_y(&v2d->cur) * facy;
- }
- else {
- dx = (BLI_rctf_size_x(&v2d->cur) / (1.0f + 2.0f * facx)) * facx;
- dy = (BLI_rctf_size_y(&v2d->cur) / (1.0f + 2.0f * facy)) * facy;
- }
-
- /* only resize view on an axis if change is allowed */
- if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
- if (v2d->keepofs & V2D_LOCKOFS_X) {
- v2d->cur.xmax -= 2 * dx;
- }
- else if (v2d->keepofs & V2D_KEEPOFS_X) {
- if (v2d->align & V2D_ALIGN_NO_POS_X) {
- v2d->cur.xmin += 2 * dx;
- }
- else {
- v2d->cur.xmax -= 2 * dx;
- }
- }
- else {
-
- v2d->cur.xmin += dx;
- v2d->cur.xmax -= dx;
-
- if (use_mousepos && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) {
- /* get zoom fac the same way as in
- * ui_view2d_curRect_validate_resize - better keep in sync! */
- const float zoomx = (float)(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur);
-
- /* only move view to mouse if zoom fac is inside minzoom/maxzoom */
- if (((v2d->keepzoom & V2D_LIMITZOOM) == 0) ||
- IN_RANGE_INCL(zoomx, v2d->minzoom, v2d->maxzoom))
- {
- float mval_fac = (vzd->mx_2d - cur_old.xmin) / BLI_rctf_size_x(&cur_old);
- float mval_faci = 1.0f - mval_fac;
- float ofs = (mval_fac * dx) - (mval_faci * dx);
-
- v2d->cur.xmin += ofs;
- v2d->cur.xmax += ofs;
- }
- }
- }
- }
- if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
- if (v2d->keepofs & V2D_LOCKOFS_Y) {
- v2d->cur.ymax -= 2 * dy;
- }
- else if (v2d->keepofs & V2D_KEEPOFS_Y) {
- if (v2d->align & V2D_ALIGN_NO_POS_Y) {
- v2d->cur.ymin += 2 * dy;
- }
- else {
- v2d->cur.ymax -= 2 * dy;
- }
- }
- else {
-
- v2d->cur.ymin += dy;
- v2d->cur.ymax -= dy;
-
- if (use_mousepos && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) {
- /* get zoom fac the same way as in
- * ui_view2d_curRect_validate_resize - better keep in sync! */
- const float zoomy = (float)(BLI_rcti_size_y(&v2d->mask) + 1) / BLI_rctf_size_y(&v2d->cur);
-
- /* only move view to mouse if zoom fac is inside minzoom/maxzoom */
- if (((v2d->keepzoom & V2D_LIMITZOOM) == 0) ||
- IN_RANGE_INCL(zoomy, v2d->minzoom, v2d->maxzoom))
- {
- float mval_fac = (vzd->my_2d - cur_old.ymin) / BLI_rctf_size_y(&cur_old);
- float mval_faci = 1.0f - mval_fac;
- float ofs = (mval_fac * dy) - (mval_faci * dy);
-
- v2d->cur.ymin += ofs;
- v2d->cur.ymax += ofs;
- }
- }
- }
- }
-
- /* 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);
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
- }
-
- /* request updates to be done... */
- ED_region_tag_redraw_no_rebuild(vzd->ar);
- UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
+ ARegion *ar = CTX_wm_region(C);
+ View2D *v2d = &ar->v2d;
+ const rctf cur_old = v2d->cur;
+ float dx, dy;
+ const int snap_test = ED_region_snap_size_test(ar);
+
+ /* calculate amount to move view by, ensuring symmetry so the
+ * old zoom level is restored after zooming back the same amount
+ */
+ if (facx >= 0.0f) {
+ dx = BLI_rctf_size_x(&v2d->cur) * facx;
+ dy = BLI_rctf_size_y(&v2d->cur) * facy;
+ }
+ else {
+ dx = (BLI_rctf_size_x(&v2d->cur) / (1.0f + 2.0f * facx)) * facx;
+ dy = (BLI_rctf_size_y(&v2d->cur) / (1.0f + 2.0f * facy)) * facy;
+ }
+
+ /* only resize view on an axis if change is allowed */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
+ if (v2d->keepofs & V2D_LOCKOFS_X) {
+ v2d->cur.xmax -= 2 * dx;
+ }
+ else if (v2d->keepofs & V2D_KEEPOFS_X) {
+ if (v2d->align & V2D_ALIGN_NO_POS_X) {
+ v2d->cur.xmin += 2 * dx;
+ }
+ else {
+ v2d->cur.xmax -= 2 * dx;
+ }
+ }
+ else {
+
+ v2d->cur.xmin += dx;
+ v2d->cur.xmax -= dx;
+
+ if (use_mousepos && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) {
+ /* get zoom fac the same way as in
+ * ui_view2d_curRect_validate_resize - better keep in sync! */
+ const float zoomx = (float)(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur);
+
+ /* only move view to mouse if zoom fac is inside minzoom/maxzoom */
+ if (((v2d->keepzoom & V2D_LIMITZOOM) == 0) ||
+ IN_RANGE_INCL(zoomx, v2d->minzoom, v2d->maxzoom)) {
+ float mval_fac = (vzd->mx_2d - cur_old.xmin) / BLI_rctf_size_x(&cur_old);
+ float mval_faci = 1.0f - mval_fac;
+ float ofs = (mval_fac * dx) - (mval_faci * dx);
+
+ v2d->cur.xmin += ofs;
+ v2d->cur.xmax += ofs;
+ }
+ }
+ }
+ }
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
+ if (v2d->keepofs & V2D_LOCKOFS_Y) {
+ v2d->cur.ymax -= 2 * dy;
+ }
+ else if (v2d->keepofs & V2D_KEEPOFS_Y) {
+ if (v2d->align & V2D_ALIGN_NO_POS_Y) {
+ v2d->cur.ymin += 2 * dy;
+ }
+ else {
+ v2d->cur.ymax -= 2 * dy;
+ }
+ }
+ else {
+
+ v2d->cur.ymin += dy;
+ v2d->cur.ymax -= dy;
+
+ if (use_mousepos && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) {
+ /* get zoom fac the same way as in
+ * ui_view2d_curRect_validate_resize - better keep in sync! */
+ const float zoomy = (float)(BLI_rcti_size_y(&v2d->mask) + 1) / BLI_rctf_size_y(&v2d->cur);
+
+ /* only move view to mouse if zoom fac is inside minzoom/maxzoom */
+ if (((v2d->keepzoom & V2D_LIMITZOOM) == 0) ||
+ IN_RANGE_INCL(zoomy, v2d->minzoom, v2d->maxzoom)) {
+ float mval_fac = (vzd->my_2d - cur_old.ymin) / BLI_rctf_size_y(&cur_old);
+ float mval_faci = 1.0f - mval_fac;
+ float ofs = (mval_fac * dy) - (mval_faci * dy);
+
+ v2d->cur.ymin += ofs;
+ v2d->cur.ymax += ofs;
+ }
+ }
+ }
+ }
+
+ /* 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);
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ }
+
+ /* request updates to be done... */
+ ED_region_tag_redraw_no_rebuild(vzd->ar);
+ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
}
static void view_zoomstep_apply(bContext *C, wmOperator *op)
{
- v2dViewZoomData *vzd = op->customdata;
- view_zoomstep_apply_ex(
- C, vzd, true,
- RNA_float_get(op->ptr, "zoomfacx"),
- RNA_float_get(op->ptr, "zoomfacy"));
+ v2dViewZoomData *vzd = op->customdata;
+ view_zoomstep_apply_ex(
+ C, vzd, true, RNA_float_get(op->ptr, "zoomfacx"), RNA_float_get(op->ptr, "zoomfacy"));
}
/* --------------- Individual Operators ------------------- */
@@ -777,153 +761,150 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op)
/* cleanup temp customdata */
static void view_zoomstep_exit(wmOperator *op)
{
- UI_view2d_zoom_cache_reset();
+ UI_view2d_zoom_cache_reset();
- if (op->customdata) {
- MEM_freeN(op->customdata);
- op->customdata = NULL;
- }
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+ }
}
/* this operator only needs this single callback, where it calls the view_zoom_*() methods */
static int view_zoomin_exec(bContext *C, wmOperator *op)
{
- bool do_zoom_xy[2];
-
- /* check that there's an active region, as View2D data resides there */
- if (!view_zoom_poll(C)) {
- return OPERATOR_PASS_THROUGH;
- }
+ bool do_zoom_xy[2];
+ /* check that there's an active region, as View2D data resides there */
+ if (!view_zoom_poll(C)) {
+ return OPERATOR_PASS_THROUGH;
+ }
- view_zoom_axis_lock_defaults(C, do_zoom_xy);
+ view_zoom_axis_lock_defaults(C, do_zoom_xy);
- /* set RNA-Props - zooming in by uniform factor */
- RNA_float_set(op->ptr, "zoomfacx", do_zoom_xy[0] ? 0.0375f : 0.0f);
- RNA_float_set(op->ptr, "zoomfacy", do_zoom_xy[1] ? 0.0375f : 0.0f);
+ /* set RNA-Props - zooming in by uniform factor */
+ RNA_float_set(op->ptr, "zoomfacx", do_zoom_xy[0] ? 0.0375f : 0.0f);
+ RNA_float_set(op->ptr, "zoomfacy", do_zoom_xy[1] ? 0.0375f : 0.0f);
- /* apply movement, then we're done */
- view_zoomstep_apply(C, op);
+ /* apply movement, then we're done */
+ view_zoomstep_apply(C, op);
- view_zoomstep_exit(op);
+ view_zoomstep_exit(op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int view_zoomin_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- v2dViewZoomData *vzd;
+ v2dViewZoomData *vzd;
- if (!view_zoomdrag_init(C, op)) {
- return OPERATOR_PASS_THROUGH;
- }
+ if (!view_zoomdrag_init(C, op)) {
+ return OPERATOR_PASS_THROUGH;
+ }
- vzd = op->customdata;
+ vzd = op->customdata;
- if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
- ARegion *ar = CTX_wm_region(C);
+ if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
+ ARegion *ar = 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);
- }
+ /* 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);
+ }
- return view_zoomin_exec(C, op);
+ return view_zoomin_exec(C, op);
}
static void VIEW2D_OT_zoom_in(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Zoom In";
- ot->description = "Zoom in the view";
- ot->idname = "VIEW2D_OT_zoom_in";
-
- /* api callbacks */
- ot->invoke = view_zoomin_invoke;
- ot->exec = view_zoomin_exec; // XXX, needs view_zoomdrag_init called first.
- ot->poll = view_zoom_poll;
-
- /* rna - must keep these in sync with the other operators */
- prop = RNA_def_float(ot->srna, "zoomfacx", 0, -FLT_MAX, FLT_MAX, "Zoom Factor X", "", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
- prop = RNA_def_float(ot->srna, "zoomfacy", 0, -FLT_MAX, FLT_MAX, "Zoom Factor Y", "", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Zoom In";
+ ot->description = "Zoom in the view";
+ ot->idname = "VIEW2D_OT_zoom_in";
+
+ /* api callbacks */
+ ot->invoke = view_zoomin_invoke;
+ ot->exec = view_zoomin_exec; // XXX, needs view_zoomdrag_init called first.
+ ot->poll = view_zoom_poll;
+
+ /* rna - must keep these in sync with the other operators */
+ prop = RNA_def_float(
+ ot->srna, "zoomfacx", 0, -FLT_MAX, FLT_MAX, "Zoom Factor X", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_float(
+ ot->srna, "zoomfacy", 0, -FLT_MAX, FLT_MAX, "Zoom Factor Y", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/* this operator only needs this single callback, where it calls the view_zoom_*() methods */
static int view_zoomout_exec(bContext *C, wmOperator *op)
{
- bool do_zoom_xy[2];
+ bool do_zoom_xy[2];
- /* check that there's an active region, as View2D data resides there */
- if (!view_zoom_poll(C)) {
- return OPERATOR_PASS_THROUGH;
- }
+ /* check that there's an active region, as View2D data resides there */
+ if (!view_zoom_poll(C)) {
+ return OPERATOR_PASS_THROUGH;
+ }
- view_zoom_axis_lock_defaults(C, do_zoom_xy);
+ view_zoom_axis_lock_defaults(C, do_zoom_xy);
- /* set RNA-Props - zooming in by uniform factor */
- RNA_float_set(op->ptr, "zoomfacx", do_zoom_xy[0] ? -0.0375f : 0.0f);
- RNA_float_set(op->ptr, "zoomfacy", do_zoom_xy[1] ? -0.0375f : 0.0f);
+ /* set RNA-Props - zooming in by uniform factor */
+ RNA_float_set(op->ptr, "zoomfacx", do_zoom_xy[0] ? -0.0375f : 0.0f);
+ RNA_float_set(op->ptr, "zoomfacy", do_zoom_xy[1] ? -0.0375f : 0.0f);
- /* apply movement, then we're done */
- view_zoomstep_apply(C, op);
+ /* apply movement, then we're done */
+ view_zoomstep_apply(C, op);
- view_zoomstep_exit(op);
+ view_zoomstep_exit(op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int view_zoomout_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- v2dViewZoomData *vzd;
+ v2dViewZoomData *vzd;
- if (!view_zoomdrag_init(C, op)) {
- return OPERATOR_PASS_THROUGH;
- }
+ if (!view_zoomdrag_init(C, op)) {
+ return OPERATOR_PASS_THROUGH;
+ }
- vzd = op->customdata;
+ vzd = op->customdata;
- if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
- ARegion *ar = CTX_wm_region(C);
+ if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
+ ARegion *ar = 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);
- }
+ /* 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);
+ }
- return view_zoomout_exec(C, op);
+ return view_zoomout_exec(C, op);
}
static void VIEW2D_OT_zoom_out(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Zoom Out";
- ot->description = "Zoom out the view";
- ot->idname = "VIEW2D_OT_zoom_out";
-
- /* api callbacks */
- ot->invoke = view_zoomout_invoke;
-// ot->exec = view_zoomout_exec; // XXX, needs view_zoomdrag_init called first.
- ot->poll = view_zoom_poll;
-
- /* rna - must keep these in sync with the other operators */
- prop = RNA_def_float(ot->srna, "zoomfacx", 0, -FLT_MAX, FLT_MAX, "Zoom Factor X", "", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
- prop = RNA_def_float(ot->srna, "zoomfacy", 0, -FLT_MAX, FLT_MAX, "Zoom Factor Y", "", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Zoom Out";
+ ot->description = "Zoom out the view";
+ ot->idname = "VIEW2D_OT_zoom_out";
+
+ /* api callbacks */
+ ot->invoke = view_zoomout_invoke;
+ // ot->exec = view_zoomout_exec; // XXX, needs view_zoomdrag_init called first.
+ ot->poll = view_zoom_poll;
+
+ /* rna - must keep these in sync with the other operators */
+ prop = RNA_def_float(
+ ot->srna, "zoomfacx", 0, -FLT_MAX, FLT_MAX, "Zoom Factor X", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_float(
+ ot->srna, "zoomfacy", 0, -FLT_MAX, FLT_MAX, "Zoom Factor Y", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/* ********************************************************* */
-/* DRAG-ZOOM OPERATOR */
+/* DRAG-ZOOM OPERATOR */
/**
* MMB Drag - allows non-uniform scaling by dragging mouse
@@ -935,339 +916,337 @@ static void VIEW2D_OT_zoom_out(wmOperatorType *ot)
/* apply transform to view (i.e. adjust 'cur' rect) */
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);
-
- /* get amount to move view by */
- dx = RNA_float_get(op->ptr, "deltax");
- dy = RNA_float_get(op->ptr, "deltay");
-
- if (U.uiflag & USER_ZOOM_INVERT) {
- dx *= -1;
- dy *= -1;
- }
-
- /* continuous zoom shouldn't move that fast... */
- if (U.viewzoom == USER_ZOOM_CONT) { // XXX store this setting as RNA prop?
- double time = PIL_check_seconds_timer();
- float time_step = (float)(time - vzd->timer_lastdraw);
-
- dx *= time_step * 0.5f;
- dy *= time_step * 0.5f;
-
- vzd->timer_lastdraw = time;
- }
-
- /* only move view on an axis if change is allowed */
- if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
- if (v2d->keepofs & V2D_LOCKOFS_X) {
- v2d->cur.xmax -= 2 * dx;
- }
- else {
- if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
- float mval_fac = (vzd->mx_2d - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
- float mval_faci = 1.0f - mval_fac;
- float ofs = (mval_fac * dx) - (mval_faci * dx);
-
- v2d->cur.xmin += ofs + dx;
- v2d->cur.xmax += ofs - dx;
- }
- else {
- v2d->cur.xmin += dx;
- v2d->cur.xmax -= dx;
- }
- }
- }
- if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
- if (v2d->keepofs & V2D_LOCKOFS_Y) {
- v2d->cur.ymax -= 2 * dy;
- }
- else {
- if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
- float mval_fac = (vzd->my_2d - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
- float mval_faci = 1.0f - mval_fac;
- float ofs = (mval_fac * dy) - (mval_faci * dy);
-
- v2d->cur.ymin += ofs + dy;
- v2d->cur.ymax += ofs - dy;
- }
- else {
- v2d->cur.ymin += dy;
- v2d->cur.ymax -= dy;
- }
- }
- }
-
- /* 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);
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
- }
-
- /* request updates to be done... */
- ED_region_tag_redraw_no_rebuild(vzd->ar);
- UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
+ v2dViewZoomData *vzd = op->customdata;
+ View2D *v2d = vzd->v2d;
+ float dx, dy;
+ const int snap_test = ED_region_snap_size_test(vzd->ar);
+
+ /* get amount to move view by */
+ dx = RNA_float_get(op->ptr, "deltax");
+ dy = RNA_float_get(op->ptr, "deltay");
+
+ if (U.uiflag & USER_ZOOM_INVERT) {
+ dx *= -1;
+ dy *= -1;
+ }
+
+ /* continuous zoom shouldn't move that fast... */
+ if (U.viewzoom == USER_ZOOM_CONT) { // XXX store this setting as RNA prop?
+ double time = PIL_check_seconds_timer();
+ float time_step = (float)(time - vzd->timer_lastdraw);
+
+ dx *= time_step * 0.5f;
+ dy *= time_step * 0.5f;
+
+ vzd->timer_lastdraw = time;
+ }
+
+ /* only move view on an axis if change is allowed */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
+ if (v2d->keepofs & V2D_LOCKOFS_X) {
+ v2d->cur.xmax -= 2 * dx;
+ }
+ else {
+ if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
+ float mval_fac = (vzd->mx_2d - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
+ float mval_faci = 1.0f - mval_fac;
+ float ofs = (mval_fac * dx) - (mval_faci * dx);
+
+ v2d->cur.xmin += ofs + dx;
+ v2d->cur.xmax += ofs - dx;
+ }
+ else {
+ v2d->cur.xmin += dx;
+ v2d->cur.xmax -= dx;
+ }
+ }
+ }
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
+ if (v2d->keepofs & V2D_LOCKOFS_Y) {
+ v2d->cur.ymax -= 2 * dy;
+ }
+ else {
+ if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
+ float mval_fac = (vzd->my_2d - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
+ float mval_faci = 1.0f - mval_fac;
+ float ofs = (mval_fac * dy) - (mval_faci * dy);
+
+ v2d->cur.ymin += ofs + dy;
+ v2d->cur.ymax += ofs - dy;
+ }
+ else {
+ v2d->cur.ymin += dy;
+ v2d->cur.ymax -= dy;
+ }
+ }
+ }
+
+ /* 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);
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ }
+
+ /* request updates to be done... */
+ ED_region_tag_redraw_no_rebuild(vzd->ar);
+ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
}
/* cleanup temp customdata */
static void view_zoomdrag_exit(bContext *C, wmOperator *op)
{
- UI_view2d_zoom_cache_reset();
+ UI_view2d_zoom_cache_reset();
- if (op->customdata) {
- v2dViewZoomData *vzd = op->customdata;
+ if (op->customdata) {
+ v2dViewZoomData *vzd = op->customdata;
- if (vzd->timer) {
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), vzd->timer);
- }
+ if (vzd->timer) {
+ WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), vzd->timer);
+ }
- MEM_freeN(op->customdata);
- op->customdata = NULL;
- }
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+ }
}
static void view_zoomdrag_cancel(bContext *C, wmOperator *op)
{
- view_zoomdrag_exit(C, op);
+ view_zoomdrag_exit(C, op);
}
/* for 'redo' only, with no user input */
static int view_zoomdrag_exec(bContext *C, wmOperator *op)
{
- if (!view_zoomdrag_init(C, op)) {
- return OPERATOR_PASS_THROUGH;
- }
+ if (!view_zoomdrag_init(C, op)) {
+ return OPERATOR_PASS_THROUGH;
+ }
- view_zoomdrag_apply(C, op);
- view_zoomdrag_exit(C, op);
- return OPERATOR_FINISHED;
+ view_zoomdrag_apply(C, op);
+ view_zoomdrag_exit(C, op);
+ return OPERATOR_FINISHED;
}
/* set up modal operator and relevant settings */
static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- wmWindow *window = CTX_wm_window(C);
- v2dViewZoomData *vzd;
- View2D *v2d;
-
- /* set up customdata */
- if (!view_zoomdrag_init(C, op)) {
- return OPERATOR_PASS_THROUGH;
- }
-
- vzd = op->customdata;
- v2d = vzd->v2d;
-
- if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
- float dx, dy, fac;
-
- vzd->lastx = event->prevx;
- vzd->lasty = event->prevy;
-
- /* As we have only 1D information (magnify value), feed both axes
- * with magnify information that is stored in x axis
- */
- fac = 0.01f * (event->prevx - event->x);
- dx = fac * BLI_rctf_size_x(&v2d->cur) / 10.0f;
- if (event->type == MOUSEPAN) {
- fac = 0.01f * (event->prevy - event->y);
- }
- dy = fac * BLI_rctf_size_y(&v2d->cur) / 10.0f;
-
- /* support trackpad zoom to always zoom entirely - the v2d code uses portrait or
- * landscape exceptions */
- if (v2d->keepzoom & V2D_KEEPASPECT) {
- if (fabsf(dx) > fabsf(dy)) {
- dy = dx;
- }
- else {
- dx = dy;
- }
- }
- RNA_float_set(op->ptr, "deltax", dx);
- RNA_float_set(op->ptr, "deltay", dy);
-
- view_zoomdrag_apply(C, op);
- view_zoomdrag_exit(C, op);
- return OPERATOR_FINISHED;
- }
-
- /* set initial settings */
- vzd->lastx = event->x;
- vzd->lasty = event->y;
- RNA_float_set(op->ptr, "deltax", 0);
- RNA_float_set(op->ptr, "deltay", 0);
-
- /* for modal exit test */
- vzd->invoke_event = event->type;
-
- if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
- ARegion *ar = 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);
- }
-
- if (v2d->keepofs & V2D_LOCKOFS_X) {
- WM_cursor_modal_set(window, BC_NS_SCROLLCURSOR);
- }
- else if (v2d->keepofs & V2D_LOCKOFS_Y) {
- WM_cursor_modal_set(window, BC_EW_SCROLLCURSOR);
- }
- else {
- WM_cursor_modal_set(window, BC_NSEW_SCROLLCURSOR);
- }
-
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
-
- if (U.viewzoom == USER_ZOOM_CONT) {
- /* needs a timer to continue redrawing */
- vzd->timer = WM_event_add_timer(CTX_wm_manager(C), window, TIMER, 0.01f);
- vzd->timer_lastdraw = PIL_check_seconds_timer();
- }
-
- return OPERATOR_RUNNING_MODAL;
+ wmWindow *window = CTX_wm_window(C);
+ v2dViewZoomData *vzd;
+ View2D *v2d;
+
+ /* set up customdata */
+ if (!view_zoomdrag_init(C, op)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ vzd = op->customdata;
+ v2d = vzd->v2d;
+
+ if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
+ float dx, dy, fac;
+
+ vzd->lastx = event->prevx;
+ vzd->lasty = event->prevy;
+
+ /* As we have only 1D information (magnify value), feed both axes
+ * with magnify information that is stored in x axis
+ */
+ fac = 0.01f * (event->prevx - event->x);
+ dx = fac * BLI_rctf_size_x(&v2d->cur) / 10.0f;
+ if (event->type == MOUSEPAN) {
+ fac = 0.01f * (event->prevy - event->y);
+ }
+ dy = fac * BLI_rctf_size_y(&v2d->cur) / 10.0f;
+
+ /* support trackpad zoom to always zoom entirely - the v2d code uses portrait or
+ * landscape exceptions */
+ if (v2d->keepzoom & V2D_KEEPASPECT) {
+ if (fabsf(dx) > fabsf(dy)) {
+ dy = dx;
+ }
+ else {
+ dx = dy;
+ }
+ }
+ RNA_float_set(op->ptr, "deltax", dx);
+ RNA_float_set(op->ptr, "deltay", dy);
+
+ view_zoomdrag_apply(C, op);
+ view_zoomdrag_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+
+ /* set initial settings */
+ vzd->lastx = event->x;
+ vzd->lasty = event->y;
+ RNA_float_set(op->ptr, "deltax", 0);
+ RNA_float_set(op->ptr, "deltay", 0);
+
+ /* for modal exit test */
+ vzd->invoke_event = event->type;
+
+ if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
+ ARegion *ar = 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);
+ }
+
+ if (v2d->keepofs & V2D_LOCKOFS_X) {
+ WM_cursor_modal_set(window, BC_NS_SCROLLCURSOR);
+ }
+ else if (v2d->keepofs & V2D_LOCKOFS_Y) {
+ WM_cursor_modal_set(window, BC_EW_SCROLLCURSOR);
+ }
+ else {
+ WM_cursor_modal_set(window, BC_NSEW_SCROLLCURSOR);
+ }
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ if (U.viewzoom == USER_ZOOM_CONT) {
+ /* needs a timer to continue redrawing */
+ vzd->timer = WM_event_add_timer(CTX_wm_manager(C), window, TIMER, 0.01f);
+ vzd->timer_lastdraw = PIL_check_seconds_timer();
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
/* handle user input - calculations of mouse-movement need to be done here,
* not in the apply callback! */
static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- v2dViewZoomData *vzd = op->customdata;
- View2D *v2d = vzd->v2d;
-
- /* execute the events */
- if (event->type == TIMER && event->customdata == vzd->timer) {
- view_zoomdrag_apply(C, op);
- }
- else if (event->type == MOUSEMOVE) {
- float dx, dy;
-
- /* calculate new delta transform, based on zooming mode */
- if (U.viewzoom == USER_ZOOM_SCALE) {
- /* 'scale' zooming */
- float dist;
-
- /* x-axis transform */
- dist = BLI_rcti_size_x(&v2d->mask) / 2.0f;
- dx = 1.0f - (fabsf(vzd->lastx - vzd->ar->winrct.xmin - dist) + 2.0f) / (fabsf(event->mval[0] - dist) + 2.0f);
- dx *= 0.5f * BLI_rctf_size_x(&v2d->cur);
-
- /* y-axis transform */
- dist = BLI_rcti_size_y(&v2d->mask) / 2.0f;
- dy = 1.0f - (fabsf(vzd->lasty - vzd->ar->winrct.ymin - dist) + 2.0f) / (fabsf(event->mval[1] - dist) + 2.0f);
- dy *= 0.5f * BLI_rctf_size_y(&v2d->cur);
- }
- else {
- /* 'continuous' or 'dolly' */
- float fac, zoomfac = 0.01f;
-
- /* some view2d's (graph) don't have min/max zoom, or extreme ones */
- if (v2d->maxzoom > 0.0f) {
- zoomfac = clamp_f(0.001f * v2d->maxzoom, 0.001f, 0.01f);
- }
-
- /* x-axis transform */
- fac = zoomfac * (event->x - vzd->lastx);
- dx = fac * BLI_rctf_size_x(&v2d->cur);
-
- /* y-axis transform */
- fac = zoomfac * (event->y - vzd->lasty);
- dy = fac * BLI_rctf_size_y(&v2d->cur);
-
- }
-
- /* support zoom to always zoom entirely - the v2d code uses portrait or
- * landscape exceptions */
- if (v2d->keepzoom & V2D_KEEPASPECT) {
- if (fabsf(dx) > fabsf(dy)) {
- dy = dx;
- }
- else {
- dx = dy;
- }
- }
-
- /* set transform amount, and add current deltas to stored total delta (for redo) */
- RNA_float_set(op->ptr, "deltax", dx);
- RNA_float_set(op->ptr, "deltay", dy);
-
- vzd->dx += dx;
- vzd->dy += dy;
-
- /* store mouse coordinates for next time, if not doing continuous zoom
- * - continuous zoom only depends on distance of mouse to starting point to determine rate of change
- */
- if (U.viewzoom != USER_ZOOM_CONT) { // XXX store this setting as RNA prop?
- vzd->lastx = event->x;
- vzd->lasty = event->y;
- }
-
- /* apply zooming */
- view_zoomdrag_apply(C, op);
- }
- else if (event->type == vzd->invoke_event || event->type == ESCKEY) {
- if (event->val == KM_RELEASE) {
-
- /* for redo, store the overall deltas - need to respect zoom-locks here... */
- if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
- RNA_float_set(op->ptr, "deltax", vzd->dx);
- }
- else {
- RNA_float_set(op->ptr, "deltax", 0);
- }
-
- if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
- RNA_float_set(op->ptr, "deltay", vzd->dy);
- }
- else {
- RNA_float_set(op->ptr, "deltay", 0);
- }
-
- /* free customdata */
- view_zoomdrag_exit(C, op);
- WM_cursor_modal_restore(CTX_wm_window(C));
-
- return OPERATOR_FINISHED;
- }
- }
-
- return OPERATOR_RUNNING_MODAL;
+ v2dViewZoomData *vzd = op->customdata;
+ View2D *v2d = vzd->v2d;
+
+ /* execute the events */
+ if (event->type == TIMER && event->customdata == vzd->timer) {
+ view_zoomdrag_apply(C, op);
+ }
+ else if (event->type == MOUSEMOVE) {
+ float dx, dy;
+
+ /* calculate new delta transform, based on zooming mode */
+ if (U.viewzoom == USER_ZOOM_SCALE) {
+ /* 'scale' zooming */
+ float dist;
+
+ /* x-axis transform */
+ dist = BLI_rcti_size_x(&v2d->mask) / 2.0f;
+ dx = 1.0f - (fabsf(vzd->lastx - vzd->ar->winrct.xmin - dist) + 2.0f) /
+ (fabsf(event->mval[0] - dist) + 2.0f);
+ dx *= 0.5f * BLI_rctf_size_x(&v2d->cur);
+
+ /* y-axis transform */
+ dist = BLI_rcti_size_y(&v2d->mask) / 2.0f;
+ dy = 1.0f - (fabsf(vzd->lasty - vzd->ar->winrct.ymin - dist) + 2.0f) /
+ (fabsf(event->mval[1] - dist) + 2.0f);
+ dy *= 0.5f * BLI_rctf_size_y(&v2d->cur);
+ }
+ else {
+ /* 'continuous' or 'dolly' */
+ float fac, zoomfac = 0.01f;
+
+ /* some view2d's (graph) don't have min/max zoom, or extreme ones */
+ if (v2d->maxzoom > 0.0f) {
+ zoomfac = clamp_f(0.001f * v2d->maxzoom, 0.001f, 0.01f);
+ }
+
+ /* x-axis transform */
+ fac = zoomfac * (event->x - vzd->lastx);
+ dx = fac * BLI_rctf_size_x(&v2d->cur);
+
+ /* y-axis transform */
+ fac = zoomfac * (event->y - vzd->lasty);
+ dy = fac * BLI_rctf_size_y(&v2d->cur);
+ }
+
+ /* support zoom to always zoom entirely - the v2d code uses portrait or
+ * landscape exceptions */
+ if (v2d->keepzoom & V2D_KEEPASPECT) {
+ if (fabsf(dx) > fabsf(dy)) {
+ dy = dx;
+ }
+ else {
+ dx = dy;
+ }
+ }
+
+ /* set transform amount, and add current deltas to stored total delta (for redo) */
+ RNA_float_set(op->ptr, "deltax", dx);
+ RNA_float_set(op->ptr, "deltay", dy);
+
+ vzd->dx += dx;
+ vzd->dy += dy;
+
+ /* store mouse coordinates for next time, if not doing continuous zoom
+ * - continuous zoom only depends on distance of mouse to starting point to determine rate of change
+ */
+ if (U.viewzoom != USER_ZOOM_CONT) { // XXX store this setting as RNA prop?
+ vzd->lastx = event->x;
+ vzd->lasty = event->y;
+ }
+
+ /* apply zooming */
+ view_zoomdrag_apply(C, op);
+ }
+ else if (event->type == vzd->invoke_event || event->type == ESCKEY) {
+ if (event->val == KM_RELEASE) {
+
+ /* for redo, store the overall deltas - need to respect zoom-locks here... */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
+ RNA_float_set(op->ptr, "deltax", vzd->dx);
+ }
+ else {
+ RNA_float_set(op->ptr, "deltax", 0);
+ }
+
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
+ RNA_float_set(op->ptr, "deltay", vzd->dy);
+ }
+ else {
+ RNA_float_set(op->ptr, "deltay", 0);
+ }
+
+ /* free customdata */
+ view_zoomdrag_exit(C, op);
+ WM_cursor_modal_restore(CTX_wm_window(C));
+
+ return OPERATOR_FINISHED;
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
static void VIEW2D_OT_zoom(wmOperatorType *ot)
{
- PropertyRNA *prop;
- /* identifiers */
- ot->name = "Zoom 2D View";
- ot->description = "Zoom in/out the view";
- ot->idname = "VIEW2D_OT_zoom";
-
- /* api callbacks */
- ot->exec = view_zoomdrag_exec;
- ot->invoke = view_zoomdrag_invoke;
- ot->modal = view_zoomdrag_modal;
- ot->cancel = view_zoomdrag_cancel;
-
- ot->poll = view_zoom_poll;
-
- /* operator is repeatable */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
-
- /* rna - must keep these in sync with the other operators */
- prop = RNA_def_float(ot->srna, "deltax", 0, -FLT_MAX, FLT_MAX, "Delta X", "", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
- prop = RNA_def_float(ot->srna, "deltay", 0, -FLT_MAX, FLT_MAX, "Delta Y", "", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop;
+ /* identifiers */
+ ot->name = "Zoom 2D View";
+ ot->description = "Zoom in/out the view";
+ ot->idname = "VIEW2D_OT_zoom";
+
+ /* api callbacks */
+ ot->exec = view_zoomdrag_exec;
+ ot->invoke = view_zoomdrag_invoke;
+ ot->modal = view_zoomdrag_modal;
+ ot->cancel = view_zoomdrag_cancel;
+
+ ot->poll = view_zoom_poll;
+
+ /* operator is repeatable */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
+
+ /* rna - must keep these in sync with the other operators */
+ prop = RNA_def_float(ot->srna, "deltax", 0, -FLT_MAX, FLT_MAX, "Delta X", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_float(ot->srna, "deltay", 0, -FLT_MAX, FLT_MAX, "Delta Y", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/* ********************************************************* */
@@ -1286,160 +1265,158 @@ 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;
- rctf rect;
- rctf cur_new = v2d->cur;
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
-
- /* 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);
-
- /* check if zooming in/out view */
- const bool zoom_in = !RNA_boolean_get(op->ptr, "zoom_out");
-
- if (zoom_in) {
- /* zoom in:
- * - 'cur' rect will be defined by the coordinates of the border region
- * - just set the 'cur' rect to have the same coordinates as the border region
- * if zoom is allowed to be changed
- */
- if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
- cur_new.xmin = rect.xmin;
- cur_new.xmax = rect.xmax;
- }
- if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
- cur_new.ymin = rect.ymin;
- cur_new.ymax = rect.ymax;
- }
- }
- else {
- /* zoom out:
- * - the current 'cur' rect coordinates are going to end up where the 'rect' ones are,
- * but the 'cur' rect coordinates will need to be adjusted to take in more of the view
- * - calculate zoom factor, and adjust using center-point
- */
- float zoom, center, size;
-
- /* TODO: is this zoom factor calculation valid?
- * It seems to produce same results every time... */
- if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
- size = BLI_rctf_size_x(&cur_new);
- zoom = size / BLI_rctf_size_x(&rect);
- center = BLI_rctf_cent_x(&cur_new);
-
- cur_new.xmin = center - (size * zoom);
- cur_new.xmax = center + (size * zoom);
- }
- if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
- size = BLI_rctf_size_y(&cur_new);
- zoom = size / BLI_rctf_size_y(&rect);
- center = BLI_rctf_cent_y(&cur_new);
-
- cur_new.ymin = center - (size * zoom);
- cur_new.ymax = center + (size * zoom);
- }
- }
-
- UI_view2d_smooth_view(C, ar, &cur_new, smooth_viewtx);
-
- return OPERATOR_FINISHED;
+ ARegion *ar = CTX_wm_region(C);
+ View2D *v2d = &ar->v2d;
+ rctf rect;
+ rctf cur_new = v2d->cur;
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+
+ /* 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);
+
+ /* check if zooming in/out view */
+ const bool zoom_in = !RNA_boolean_get(op->ptr, "zoom_out");
+
+ if (zoom_in) {
+ /* zoom in:
+ * - 'cur' rect will be defined by the coordinates of the border region
+ * - just set the 'cur' rect to have the same coordinates as the border region
+ * if zoom is allowed to be changed
+ */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
+ cur_new.xmin = rect.xmin;
+ cur_new.xmax = rect.xmax;
+ }
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
+ cur_new.ymin = rect.ymin;
+ cur_new.ymax = rect.ymax;
+ }
+ }
+ else {
+ /* zoom out:
+ * - the current 'cur' rect coordinates are going to end up where the 'rect' ones are,
+ * but the 'cur' rect coordinates will need to be adjusted to take in more of the view
+ * - calculate zoom factor, and adjust using center-point
+ */
+ float zoom, center, size;
+
+ /* TODO: is this zoom factor calculation valid?
+ * It seems to produce same results every time... */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
+ size = BLI_rctf_size_x(&cur_new);
+ zoom = size / BLI_rctf_size_x(&rect);
+ center = BLI_rctf_cent_x(&cur_new);
+
+ cur_new.xmin = center - (size * zoom);
+ cur_new.xmax = center + (size * zoom);
+ }
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
+ size = BLI_rctf_size_y(&cur_new);
+ zoom = size / BLI_rctf_size_y(&rect);
+ center = BLI_rctf_cent_y(&cur_new);
+
+ cur_new.ymin = center - (size * zoom);
+ cur_new.ymax = center + (size * zoom);
+ }
+ }
+
+ UI_view2d_smooth_view(C, ar, &cur_new, smooth_viewtx);
+
+ return OPERATOR_FINISHED;
}
static void VIEW2D_OT_zoom_border(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Zoom to Border";
- ot->description = "Zoom in the view to the nearest item contained in the border";
- ot->idname = "VIEW2D_OT_zoom_border";
+ /* identifiers */
+ ot->name = "Zoom to Border";
+ ot->description = "Zoom in the view to the nearest item contained in the border";
+ ot->idname = "VIEW2D_OT_zoom_border";
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = view_borderzoom_exec;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = view_borderzoom_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
- ot->poll = view_zoom_poll;
+ ot->poll = view_zoom_poll;
- /* rna */
- WM_operator_properties_gesture_box_zoom(ot);
+ /* rna */
+ WM_operator_properties_gesture_box_zoom(ot);
}
#ifdef WITH_INPUT_NDOF
static int view2d_ndof_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (event->type != NDOF_MOTION) {
- return OPERATOR_CANCELLED;
- }
- else {
- const wmNDOFMotionData *ndof = event->customdata;
+ if (event->type != NDOF_MOTION) {
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ const wmNDOFMotionData *ndof = event->customdata;
- /* tune these until it feels right */
- const float zoom_sensitivity = 0.5f;
- const float speed = 10.0f; /* match view3d ortho */
- const bool has_translate = (ndof->tvec[0] && ndof->tvec[1]) && view_pan_poll(C);
- const bool has_zoom = (ndof->tvec[2] != 0.0f) && view_zoom_poll(C);
+ /* tune these until it feels right */
+ const float zoom_sensitivity = 0.5f;
+ const float speed = 10.0f; /* match view3d ortho */
+ const bool has_translate = (ndof->tvec[0] && ndof->tvec[1]) && view_pan_poll(C);
+ const bool has_zoom = (ndof->tvec[2] != 0.0f) && view_zoom_poll(C);
- if (has_translate) {
- if (view_pan_init(C, op)) {
- v2dViewPanData *vpd;
- float pan_vec[3];
+ if (has_translate) {
+ if (view_pan_init(C, op)) {
+ v2dViewPanData *vpd;
+ float pan_vec[3];
- WM_event_ndof_pan_get(ndof, pan_vec, false);
+ WM_event_ndof_pan_get(ndof, pan_vec, false);
- pan_vec[0] *= speed;
- pan_vec[1] *= speed;
+ pan_vec[0] *= speed;
+ pan_vec[1] *= speed;
- vpd = op->customdata;
+ vpd = op->customdata;
- view_pan_apply_ex(C, vpd, pan_vec[0], pan_vec[1]);
+ view_pan_apply_ex(C, vpd, pan_vec[0], pan_vec[1]);
- view_pan_exit(op);
- }
- }
+ view_pan_exit(op);
+ }
+ }
- if (has_zoom) {
- if (view_zoomdrag_init(C, op)) {
- v2dViewZoomData *vzd;
- float zoom_factor = zoom_sensitivity * ndof->dt * -ndof->tvec[2];
+ if (has_zoom) {
+ if (view_zoomdrag_init(C, op)) {
+ v2dViewZoomData *vzd;
+ float zoom_factor = zoom_sensitivity * ndof->dt * -ndof->tvec[2];
- bool do_zoom_xy[2];
+ bool do_zoom_xy[2];
- if (U.ndof_flag & NDOF_ZOOM_INVERT) {
- zoom_factor = -zoom_factor;
- }
+ if (U.ndof_flag & NDOF_ZOOM_INVERT) {
+ zoom_factor = -zoom_factor;
+ }
- view_zoom_axis_lock_defaults(C, do_zoom_xy);
+ view_zoom_axis_lock_defaults(C, do_zoom_xy);
- vzd = op->customdata;
+ vzd = op->customdata;
- view_zoomstep_apply_ex(
- C, vzd, false,
- do_zoom_xy[0] ? zoom_factor : 0.0f,
- do_zoom_xy[1] ? zoom_factor : 0.0f);
+ view_zoomstep_apply_ex(
+ C, vzd, false, do_zoom_xy[0] ? zoom_factor : 0.0f, do_zoom_xy[1] ? zoom_factor : 0.0f);
- view_zoomstep_exit(op);
- }
- }
+ view_zoomstep_exit(op);
+ }
+ }
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
}
static void VIEW2D_OT_ndof(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "NDOF Pan/Zoom";
- ot->idname = "VIEW2D_OT_ndof";
- ot->description = "Use a 3D mouse device to pan/zoom the view";
+ /* identifiers */
+ ot->name = "NDOF Pan/Zoom";
+ ot->idname = "VIEW2D_OT_ndof";
+ ot->description = "Use a 3D mouse device to pan/zoom the view";
- /* api callbacks */
- ot->invoke = view2d_ndof_invoke;
- ot->poll = view2d_poll;
+ /* api callbacks */
+ ot->invoke = view2d_ndof_invoke;
+ ot->poll = view2d_poll;
- /* flags */
- ot->flag = OPTYPE_LOCK_BYPASS;
+ /* flags */
+ ot->flag = OPTYPE_LOCK_BYPASS;
}
#endif /* WITH_INPUT_NDOF */
@@ -1447,9 +1424,9 @@ static void VIEW2D_OT_ndof(wmOperatorType *ot)
/* SMOOTH VIEW */
struct SmoothView2DStore {
- rctf orig_cur, new_cur;
+ rctf orig_cur, new_cur;
- double time_allowed;
+ double time_allowed;
};
/**
@@ -1462,177 +1439,167 @@ struct SmoothView2DStore {
*/
static float smooth_view_rect_to_fac(const rctf *rect_a, const rctf *rect_b)
{
- const float size_a[2] = {
- BLI_rctf_size_x(rect_a),
- BLI_rctf_size_y(rect_a)};
- const float size_b[2] = {
- BLI_rctf_size_x(rect_b),
- BLI_rctf_size_y(rect_b)};
- const float cent_a[2] = {
- BLI_rctf_cent_x(rect_a),
- BLI_rctf_cent_y(rect_a)};
- const float cent_b[2] = {
- BLI_rctf_cent_x(rect_b),
- BLI_rctf_cent_y(rect_b)};
-
- float fac_max = 0.0f;
- float tfac;
-
- int i;
-
- for (i = 0; i < 2; i++) {
- /* axis translation normalized to scale */
- tfac = fabsf(cent_a[i] - cent_b[i]) / min_ff(size_a[i], size_b[i]);
- fac_max = max_ff(fac_max, tfac);
- if (fac_max >= 1.0f) {
- break;
- }
-
- /* axis scale difference, x2 so doubling or half gives 1.0f */
- tfac = (1.0f - (min_ff(size_a[i], size_b[i]) / max_ff(size_a[i], size_b[i]))) * 2.0f;
- fac_max = max_ff(fac_max, tfac);
- if (fac_max >= 1.0f) {
- break;
- }
- }
- return min_ff(fac_max, 1.0f);
+ const float size_a[2] = {BLI_rctf_size_x(rect_a), BLI_rctf_size_y(rect_a)};
+ const float size_b[2] = {BLI_rctf_size_x(rect_b), BLI_rctf_size_y(rect_b)};
+ const float cent_a[2] = {BLI_rctf_cent_x(rect_a), BLI_rctf_cent_y(rect_a)};
+ const float cent_b[2] = {BLI_rctf_cent_x(rect_b), BLI_rctf_cent_y(rect_b)};
+
+ float fac_max = 0.0f;
+ float tfac;
+
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ /* axis translation normalized to scale */
+ tfac = fabsf(cent_a[i] - cent_b[i]) / min_ff(size_a[i], size_b[i]);
+ fac_max = max_ff(fac_max, tfac);
+ if (fac_max >= 1.0f) {
+ break;
+ }
+
+ /* axis scale difference, x2 so doubling or half gives 1.0f */
+ tfac = (1.0f - (min_ff(size_a[i], size_b[i]) / max_ff(size_a[i], size_b[i]))) * 2.0f;
+ fac_max = max_ff(fac_max, tfac);
+ if (fac_max >= 1.0f) {
+ break;
+ }
+ }
+ return min_ff(fac_max, 1.0f);
}
/* 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 *ar, const rctf *cur, const int smooth_viewtx)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
-
- View2D *v2d = &ar->v2d;
- struct SmoothView2DStore sms = {{0}};
- bool ok = false;
- float fac = 1.0f;
-
- /* initialize sms */
- sms.new_cur = v2d->cur;
-
- /* store the options we want to end with */
- if (cur) {
- sms.new_cur = *cur;
- }
-
- if (cur) {
- fac = smooth_view_rect_to_fac(&v2d->cur, cur);
- }
-
- if (smooth_viewtx && fac > FLT_EPSILON) {
- bool changed = false;
-
- if (BLI_rctf_compare(&sms.new_cur, &v2d->cur, FLT_EPSILON) == false) {
- changed = true;
- }
-
- /* The new view is different from the old one
- * so animate the view */
- if (changed) {
- sms.orig_cur = v2d->cur;
-
- sms.time_allowed = (double)smooth_viewtx / 1000.0;
-
- /* scale the time allowed the change in view */
- sms.time_allowed *= (double)fac;
-
- /* keep track of running timer! */
- if (v2d->sms == NULL) {
- v2d->sms = MEM_mallocN(sizeof(struct SmoothView2DStore), "smoothview v2d");
- }
- *v2d->sms = sms;
- if (v2d->smooth_timer) {
- WM_event_remove_timer(wm, win, v2d->smooth_timer);
- }
- /* TIMER1 is hardcoded in keymap */
- /* max 30 frs/sec */
- v2d->smooth_timer = WM_event_add_timer(wm, win, TIMER1, 1.0 / 100.0);
-
- ok = true;
- }
- }
-
- /* if we get here nothing happens */
- if (ok == false) {
- v2d->cur = sms.new_cur;
-
- UI_view2d_curRect_validate(v2d);
- ED_region_tag_redraw_no_rebuild(ar);
- UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
- }
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+
+ View2D *v2d = &ar->v2d;
+ struct SmoothView2DStore sms = {{0}};
+ bool ok = false;
+ float fac = 1.0f;
+
+ /* initialize sms */
+ sms.new_cur = v2d->cur;
+
+ /* store the options we want to end with */
+ if (cur) {
+ sms.new_cur = *cur;
+ }
+
+ if (cur) {
+ fac = smooth_view_rect_to_fac(&v2d->cur, cur);
+ }
+
+ if (smooth_viewtx && fac > FLT_EPSILON) {
+ bool changed = false;
+
+ if (BLI_rctf_compare(&sms.new_cur, &v2d->cur, FLT_EPSILON) == false) {
+ changed = true;
+ }
+
+ /* The new view is different from the old one
+ * so animate the view */
+ if (changed) {
+ sms.orig_cur = v2d->cur;
+
+ sms.time_allowed = (double)smooth_viewtx / 1000.0;
+
+ /* scale the time allowed the change in view */
+ sms.time_allowed *= (double)fac;
+
+ /* keep track of running timer! */
+ if (v2d->sms == NULL) {
+ v2d->sms = MEM_mallocN(sizeof(struct SmoothView2DStore), "smoothview v2d");
+ }
+ *v2d->sms = sms;
+ if (v2d->smooth_timer) {
+ WM_event_remove_timer(wm, win, v2d->smooth_timer);
+ }
+ /* TIMER1 is hardcoded in keymap */
+ /* max 30 frs/sec */
+ v2d->smooth_timer = WM_event_add_timer(wm, win, TIMER1, 1.0 / 100.0);
+
+ ok = true;
+ }
+ }
+
+ /* if we get here nothing happens */
+ if (ok == false) {
+ v2d->cur = sms.new_cur;
+
+ UI_view2d_curRect_validate(v2d);
+ ED_region_tag_redraw_no_rebuild(ar);
+ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
+ }
}
/* 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;
- struct SmoothView2DStore *sms = v2d->sms;
- float step;
-
- /* escape if not our timer */
- if (v2d->smooth_timer == NULL || v2d->smooth_timer != event->customdata) {
- return OPERATOR_PASS_THROUGH;
- }
-
- if (sms->time_allowed != 0.0) {
- step = (float)((v2d->smooth_timer->duration) / sms->time_allowed);
- }
- else {
- step = 1.0f;
- }
-
- /* end timer */
- if (step >= 1.0f) {
- v2d->cur = sms->new_cur;
-
- MEM_freeN(v2d->sms);
- v2d->sms = NULL;
-
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), 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);
- }
- else {
- /* ease in/out */
- step = (3.0f * step * step - 2.0f * step * step * step);
-
- BLI_rctf_interp(&v2d->cur, &sms->orig_cur, &sms->new_cur, step);
- }
-
- 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);
-
- if (v2d->sms == NULL) {
- UI_view2d_zoom_cache_reset();
- }
-
- return OPERATOR_FINISHED;
+ ARegion *ar = CTX_wm_region(C);
+ View2D *v2d = &ar->v2d;
+ struct SmoothView2DStore *sms = v2d->sms;
+ float step;
+
+ /* escape if not our timer */
+ if (v2d->smooth_timer == NULL || v2d->smooth_timer != event->customdata) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ if (sms->time_allowed != 0.0) {
+ step = (float)((v2d->smooth_timer->duration) / sms->time_allowed);
+ }
+ else {
+ step = 1.0f;
+ }
+
+ /* end timer */
+ if (step >= 1.0f) {
+ v2d->cur = sms->new_cur;
+
+ MEM_freeN(v2d->sms);
+ v2d->sms = NULL;
+
+ WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), 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);
+ }
+ else {
+ /* ease in/out */
+ step = (3.0f * step * step - 2.0f * step * step * step);
+
+ BLI_rctf_interp(&v2d->cur, &sms->orig_cur, &sms->new_cur, step);
+ }
+
+ 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);
+
+ if (v2d->sms == NULL) {
+ UI_view2d_zoom_cache_reset();
+ }
+
+ return OPERATOR_FINISHED;
}
static void VIEW2D_OT_smoothview(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Smooth View 2D";
- ot->idname = "VIEW2D_OT_smoothview";
+ /* identifiers */
+ ot->name = "Smooth View 2D";
+ ot->idname = "VIEW2D_OT_smoothview";
- /* api callbacks */
- ot->invoke = view2d_smoothview_invoke;
- ot->poll = view2d_poll;
+ /* api callbacks */
+ ot->invoke = view2d_smoothview_invoke;
+ ot->poll = view2d_poll;
- /* flags */
- ot->flag = OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_INTERNAL;
- /* rna */
- WM_operator_properties_gesture_box(ot);
+ /* rna */
+ WM_operator_properties_gesture_box(ot);
}
/* ********************************************************* */
@@ -1650,35 +1617,34 @@ static void VIEW2D_OT_smoothview(wmOperatorType *ot)
/* customdata for scroller-invoke data */
typedef struct v2dScrollerMove {
- /** View2D data that this operation affects */
- View2D *v2d;
- /** region that the scroller is in */
- ARegion *ar;
-
- /** scroller that mouse is in ('h' or 'v') */
- char scroller;
-
- /* XXX find some way to provide visual feedback of this (active color?) */
- /** -1 is min zoomer, 0 is bar, 1 is max zoomer */
- short zone;
-
- /** view adjustment factor, based on size of region */
- float fac;
- /** for pixel rounding (avoid visible UI jitter) */
- float fac_round;
- /** amount moved by mouse on axis of interest */
- float delta;
-
- /** width of the scrollbar itself, used for page up/down clicks */
- float scrollbarwidth;
- /** initial location of scrollbar x/y, mouse relative */
- int scrollbar_orig;
-
- /** previous mouse coordinates (in screen coordinates) for determining movement */
- int lastx, lasty;
+ /** View2D data that this operation affects */
+ View2D *v2d;
+ /** region that the scroller is in */
+ ARegion *ar;
+
+ /** scroller that mouse is in ('h' or 'v') */
+ char scroller;
+
+ /* XXX find some way to provide visual feedback of this (active color?) */
+ /** -1 is min zoomer, 0 is bar, 1 is max zoomer */
+ short zone;
+
+ /** view adjustment factor, based on size of region */
+ float fac;
+ /** for pixel rounding (avoid visible UI jitter) */
+ float fac_round;
+ /** amount moved by mouse on axis of interest */
+ float delta;
+
+ /** width of the scrollbar itself, used for page up/down clicks */
+ float scrollbarwidth;
+ /** initial location of scrollbar x/y, mouse relative */
+ int scrollbar_orig;
+
+ /** previous mouse coordinates (in screen coordinates) for determining movement */
+ int lastx, lasty;
} v2dScrollerMove;
-
/**
* #View2DScrollers is typedef'd in UI_view2d.h
* This is a CUT DOWN VERSION of the 'real' version, which is defined in view2d.c, as we only need focus bubble info
@@ -1687,18 +1653,18 @@ typedef struct v2dScrollerMove {
* For now, we don't need to have a separate (internal) header for structs like this...
*/
struct View2DScrollers {
- /* focus bubbles */
- int vert_min, vert_max; /* vertical scrollbar */
- int hor_min, hor_max; /* horizontal scrollbar */
+ /* focus bubbles */
+ int vert_min, vert_max; /* vertical scrollbar */
+ int hor_min, hor_max; /* horizontal scrollbar */
};
/* quick enum for vsm->zone (scroller handles) */
enum {
- SCROLLHANDLE_MIN = -1,
- SCROLLHANDLE_BAR,
- SCROLLHANDLE_MAX,
- SCROLLHANDLE_MIN_OUTSIDE,
- SCROLLHANDLE_MAX_OUTSIDE,
+ SCROLLHANDLE_MIN = -1,
+ SCROLLHANDLE_BAR,
+ SCROLLHANDLE_MAX,
+ SCROLLHANDLE_MIN_OUTSIDE,
+ SCROLLHANDLE_MAX_OUTSIDE,
} /*eV2DScrollerHandle_Zone*/;
/* ------------------------ */
@@ -1712,240 +1678,241 @@ 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;
- }
- 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;
- }
- }
-
-
- if (in_view == 0) {
- 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_SCROLLER_HANDLE_SIZE)) && (mouse <= (sh_max + V2D_SCROLLER_HANDLE_SIZE)));
- in_min = ((mouse <= (sh_min + V2D_SCROLLER_HANDLE_SIZE)) && (mouse >= (sh_min - V2D_SCROLLER_HANDLE_SIZE)));
- in_bar = ((mouse < (sh_max - V2D_SCROLLER_HANDLE_SIZE)) && (mouse > (sh_min + V2D_SCROLLER_HANDLE_SIZE)));
- out_min = mouse < (sh_min - V2D_SCROLLER_HANDLE_SIZE);
- out_max = mouse > (sh_max + V2D_SCROLLER_HANDLE_SIZE);
-
- if (in_bar) {
- return SCROLLHANDLE_BAR;
- }
- else if (in_max) {
- return SCROLLHANDLE_MAX;
- }
- else if (in_min) {
- return SCROLLHANDLE_MIN;
- }
- else if (out_min) {
- return SCROLLHANDLE_MIN_OUTSIDE;
- }
- else if (out_max) {
- return SCROLLHANDLE_MAX_OUTSIDE;
- }
-
- /* unlikely to happen, though we just cover it in case */
- return SCROLLHANDLE_BAR;
+ 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;
+ }
+ 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;
+ }
+ }
+
+ if (in_view == 0) {
+ 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_SCROLLER_HANDLE_SIZE)) &&
+ (mouse <= (sh_max + V2D_SCROLLER_HANDLE_SIZE)));
+ in_min = ((mouse <= (sh_min + V2D_SCROLLER_HANDLE_SIZE)) &&
+ (mouse >= (sh_min - V2D_SCROLLER_HANDLE_SIZE)));
+ in_bar = ((mouse < (sh_max - V2D_SCROLLER_HANDLE_SIZE)) &&
+ (mouse > (sh_min + V2D_SCROLLER_HANDLE_SIZE)));
+ out_min = mouse < (sh_min - V2D_SCROLLER_HANDLE_SIZE);
+ out_max = mouse > (sh_max + V2D_SCROLLER_HANDLE_SIZE);
+
+ if (in_bar) {
+ return SCROLLHANDLE_BAR;
+ }
+ else if (in_max) {
+ return SCROLLHANDLE_MAX;
+ }
+ else if (in_min) {
+ return SCROLLHANDLE_MIN;
+ }
+ else if (out_min) {
+ return SCROLLHANDLE_MIN_OUTSIDE;
+ }
+ else if (out_max) {
+ return SCROLLHANDLE_MAX_OUTSIDE;
+ }
+
+ /* unlikely to happen, though we just cover it in case */
+ return SCROLLHANDLE_BAR;
}
static bool scroller_activate_poll(bContext *C)
{
- if (!view2d_poll(C)) {
- return false;
- }
+ if (!view2d_poll(C)) {
+ return false;
+ }
- wmWindow *win = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = &ar->v2d;
- wmEvent *event = win->eventstate;
+ wmWindow *win = CTX_wm_window(C);
+ ARegion *ar = CTX_wm_region(C);
+ View2D *v2d = &ar->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);
+ /* check if mouse in scrollbars, if they're enabled */
+ return (UI_view2d_mouse_in_scrollers(ar, v2d, event->x, event->y) != 0);
}
/* initialize customdata for scroller manipulation operator */
-static void scroller_activate_init(bContext *C, wmOperator *op, const wmEvent *event, const char in_scroller)
+static void scroller_activate_init(bContext *C,
+ wmOperator *op,
+ const wmEvent *event,
+ const char in_scroller)
{
- v2dScrollerMove *vsm;
- View2DScrollers *scrollers;
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = &ar->v2d;
- rctf tot_cur_union;
- float mask_size;
-
- /* set custom-data for operator */
- vsm = MEM_callocN(sizeof(v2dScrollerMove), "v2dScrollerMove");
- op->customdata = vsm;
-
- /* set general data */
- vsm->v2d = v2d;
- vsm->ar = ar;
- vsm->scroller = in_scroller;
-
- /* store mouse-coordinates, and convert mouse/screen coordinates to region coordinates */
- vsm->lastx = event->x;
- vsm->lasty = event->y;
- /* 'zone' depends on where mouse is relative to bubble
- * - zooming must be allowed on this axis, otherwise, default to pan
- */
- scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
-
- /* use a union of 'cur' & 'tot' incase the current view is far outside 'tot'. In this cases
- * moving the scroll bars has far too little effect and the view can get stuck T31476. */
- tot_cur_union = v2d->tot;
- BLI_rctf_union(&tot_cur_union, &v2d->cur);
-
- if (in_scroller == 'h') {
- /* horizontal scroller - calculate adjustment factor first */
- mask_size = (float)BLI_rcti_size_x(&v2d->hor);
- 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);
-
- /* get 'zone' (i.e. which part of scroller is activated) */
- vsm->zone = mouse_in_scroller_handle(
- event->mval[0],
- v2d->hor.xmin, v2d->hor.xmax,
- scrollers->hor_min, scrollers->hor_max);
-
- if ((v2d->keepzoom & V2D_LOCKZOOM_X) && ELEM(vsm->zone, SCROLLHANDLE_MIN, SCROLLHANDLE_MAX)) {
- /* default to scroll, as handles not usable */
- vsm->zone = SCROLLHANDLE_BAR;
- }
-
- vsm->scrollbarwidth = scrollers->hor_max - scrollers->hor_min;
- vsm->scrollbar_orig = ((scrollers->hor_max + scrollers->hor_min) / 2) + ar->winrct.xmin;
- }
- else {
- /* vertical scroller - calculate adjustment factor first */
- mask_size = (float)BLI_rcti_size_y(&v2d->vert);
- 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);
-
- /* get 'zone' (i.e. which part of scroller is activated) */
- vsm->zone = mouse_in_scroller_handle(
- event->mval[1],
- v2d->vert.ymin, v2d->vert.ymax,
- scrollers->vert_min, scrollers->vert_max);
-
- if ((v2d->keepzoom & V2D_LOCKZOOM_Y) && ELEM(vsm->zone, SCROLLHANDLE_MIN, SCROLLHANDLE_MAX)) {
- /* default to scroll, as handles not usable */
- vsm->zone = SCROLLHANDLE_BAR;
- }
-
- vsm->scrollbarwidth = scrollers->vert_max - scrollers->vert_min;
- vsm->scrollbar_orig = ((scrollers->vert_max + scrollers->vert_min) / 2) + ar->winrct.ymin;
- }
-
- UI_view2d_scrollers_free(scrollers);
- ED_region_tag_redraw_no_rebuild(ar);
+ v2dScrollerMove *vsm;
+ View2DScrollers *scrollers;
+ ARegion *ar = CTX_wm_region(C);
+ View2D *v2d = &ar->v2d;
+ rctf tot_cur_union;
+ float mask_size;
+
+ /* set custom-data for operator */
+ vsm = MEM_callocN(sizeof(v2dScrollerMove), "v2dScrollerMove");
+ op->customdata = vsm;
+
+ /* set general data */
+ vsm->v2d = v2d;
+ vsm->ar = ar;
+ vsm->scroller = in_scroller;
+
+ /* store mouse-coordinates, and convert mouse/screen coordinates to region coordinates */
+ vsm->lastx = event->x;
+ vsm->lasty = event->y;
+ /* 'zone' depends on where mouse is relative to bubble
+ * - zooming must be allowed on this axis, otherwise, default to pan
+ */
+ scrollers = UI_view2d_scrollers_calc(
+ C, v2d, NULL, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+
+ /* use a union of 'cur' & 'tot' incase the current view is far outside 'tot'. In this cases
+ * moving the scroll bars has far too little effect and the view can get stuck T31476. */
+ tot_cur_union = v2d->tot;
+ BLI_rctf_union(&tot_cur_union, &v2d->cur);
+
+ if (in_scroller == 'h') {
+ /* horizontal scroller - calculate adjustment factor first */
+ mask_size = (float)BLI_rcti_size_x(&v2d->hor);
+ 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);
+
+ /* get 'zone' (i.e. which part of scroller is activated) */
+ vsm->zone = mouse_in_scroller_handle(
+ event->mval[0], v2d->hor.xmin, v2d->hor.xmax, scrollers->hor_min, scrollers->hor_max);
+
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X) && ELEM(vsm->zone, SCROLLHANDLE_MIN, SCROLLHANDLE_MAX)) {
+ /* default to scroll, as handles not usable */
+ vsm->zone = SCROLLHANDLE_BAR;
+ }
+
+ vsm->scrollbarwidth = scrollers->hor_max - scrollers->hor_min;
+ vsm->scrollbar_orig = ((scrollers->hor_max + scrollers->hor_min) / 2) + ar->winrct.xmin;
+ }
+ else {
+ /* vertical scroller - calculate adjustment factor first */
+ mask_size = (float)BLI_rcti_size_y(&v2d->vert);
+ 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);
+
+ /* get 'zone' (i.e. which part of scroller is activated) */
+ vsm->zone = mouse_in_scroller_handle(
+ event->mval[1], v2d->vert.ymin, v2d->vert.ymax, scrollers->vert_min, scrollers->vert_max);
+
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y) && ELEM(vsm->zone, SCROLLHANDLE_MIN, SCROLLHANDLE_MAX)) {
+ /* default to scroll, as handles not usable */
+ vsm->zone = SCROLLHANDLE_BAR;
+ }
+
+ vsm->scrollbarwidth = scrollers->vert_max - scrollers->vert_min;
+ vsm->scrollbar_orig = ((scrollers->vert_max + scrollers->vert_min) / 2) + ar->winrct.ymin;
+ }
+
+ UI_view2d_scrollers_free(scrollers);
+ ED_region_tag_redraw_no_rebuild(ar);
}
/* cleanup temp customdata */
static void scroller_activate_exit(bContext *C, wmOperator *op)
{
- if (op->customdata) {
- v2dScrollerMove *vsm = op->customdata;
+ if (op->customdata) {
+ v2dScrollerMove *vsm = op->customdata;
- vsm->v2d->scroll_ui &= ~(V2D_SCROLL_H_ACTIVE | V2D_SCROLL_V_ACTIVE);
+ vsm->v2d->scroll_ui &= ~(V2D_SCROLL_H_ACTIVE | V2D_SCROLL_V_ACTIVE);
- MEM_freeN(op->customdata);
- op->customdata = NULL;
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
- ED_region_tag_redraw_no_rebuild(CTX_wm_region(C));
- }
+ ED_region_tag_redraw_no_rebuild(CTX_wm_region(C));
+ }
}
static void scroller_activate_cancel(bContext *C, wmOperator *op)
{
- scroller_activate_exit(C, op);
+ scroller_activate_exit(C, op);
}
/* apply transform to view (i.e. adjust 'cur' rect) */
static void scroller_activate_apply(bContext *C, wmOperator *op)
{
- v2dScrollerMove *vsm = op->customdata;
- View2D *v2d = vsm->v2d;
- float temp;
-
- /* calculate amount to move view by */
- temp = vsm->fac * vsm->delta;
-
- /* round to pixel */
- temp = roundf(temp / vsm->fac_round) * vsm->fac_round;
-
- /* type of movement */
- switch (vsm->zone) {
- case SCROLLHANDLE_MIN:
- /* only expand view on axis if zoom is allowed */
- if ((vsm->scroller == 'h') && !(v2d->keepzoom & V2D_LOCKZOOM_X)) {
- v2d->cur.xmin -= temp;
- }
- if ((vsm->scroller == 'v') && !(v2d->keepzoom & V2D_LOCKZOOM_Y)) {
- v2d->cur.ymin -= temp;
- }
- break;
-
- case SCROLLHANDLE_MAX:
-
- /* only expand view on axis if zoom is allowed */
- if ((vsm->scroller == 'h') && !(v2d->keepzoom & V2D_LOCKZOOM_X)) {
- v2d->cur.xmax += temp;
- }
- if ((vsm->scroller == 'v') && !(v2d->keepzoom & V2D_LOCKZOOM_Y)) {
- v2d->cur.ymax += temp;
- }
- break;
-
- case SCROLLHANDLE_MIN_OUTSIDE:
- case SCROLLHANDLE_MAX_OUTSIDE:
- case SCROLLHANDLE_BAR:
- default:
- /* only move view on an axis if panning is allowed */
- if ((vsm->scroller == 'h') && !(v2d->keepofs & V2D_LOCKOFS_X)) {
- v2d->cur.xmin += temp;
- v2d->cur.xmax += temp;
- }
- if ((vsm->scroller == 'v') && !(v2d->keepofs & V2D_LOCKOFS_Y)) {
- v2d->cur.ymin += temp;
- v2d->cur.ymax += temp;
- }
- break;
-
- }
-
- /* validate that view is in valid configuration after this operation */
- UI_view2d_curRect_validate(v2d);
-
- /* request updates to be done... */
- ED_region_tag_redraw_no_rebuild(vsm->ar);
- UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
+ v2dScrollerMove *vsm = op->customdata;
+ View2D *v2d = vsm->v2d;
+ float temp;
+
+ /* calculate amount to move view by */
+ temp = vsm->fac * vsm->delta;
+
+ /* round to pixel */
+ temp = roundf(temp / vsm->fac_round) * vsm->fac_round;
+
+ /* type of movement */
+ switch (vsm->zone) {
+ case SCROLLHANDLE_MIN:
+ /* only expand view on axis if zoom is allowed */
+ if ((vsm->scroller == 'h') && !(v2d->keepzoom & V2D_LOCKZOOM_X)) {
+ v2d->cur.xmin -= temp;
+ }
+ if ((vsm->scroller == 'v') && !(v2d->keepzoom & V2D_LOCKZOOM_Y)) {
+ v2d->cur.ymin -= temp;
+ }
+ break;
+
+ case SCROLLHANDLE_MAX:
+
+ /* only expand view on axis if zoom is allowed */
+ if ((vsm->scroller == 'h') && !(v2d->keepzoom & V2D_LOCKZOOM_X)) {
+ v2d->cur.xmax += temp;
+ }
+ if ((vsm->scroller == 'v') && !(v2d->keepzoom & V2D_LOCKZOOM_Y)) {
+ v2d->cur.ymax += temp;
+ }
+ break;
+
+ case SCROLLHANDLE_MIN_OUTSIDE:
+ case SCROLLHANDLE_MAX_OUTSIDE:
+ case SCROLLHANDLE_BAR:
+ default:
+ /* only move view on an axis if panning is allowed */
+ if ((vsm->scroller == 'h') && !(v2d->keepofs & V2D_LOCKOFS_X)) {
+ v2d->cur.xmin += temp;
+ v2d->cur.xmax += temp;
+ }
+ if ((vsm->scroller == 'v') && !(v2d->keepofs & V2D_LOCKOFS_Y)) {
+ v2d->cur.ymin += temp;
+ v2d->cur.ymax += temp;
+ }
+ break;
+ }
+
+ /* validate that view is in valid configuration after this operation */
+ UI_view2d_curRect_validate(v2d);
+
+ /* request updates to be done... */
+ ED_region_tag_redraw_no_rebuild(vsm->ar);
+ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
}
/**
@@ -1954,187 +1921,181 @@ static void scroller_activate_apply(bContext *C, wmOperator *op)
*/
static int scroller_activate_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- v2dScrollerMove *vsm = op->customdata;
-
- /* execute the events */
- switch (event->type) {
- case MOUSEMOVE:
- {
- /* calculate new delta transform, then store mouse-coordinates for next-time */
- if (ELEM(vsm->zone, SCROLLHANDLE_BAR, SCROLLHANDLE_MAX)) {
- /* if using bar (i.e. 'panning') or 'max' zoom widget */
- switch (vsm->scroller) {
- case 'h': /* horizontal scroller - so only horizontal movement
- * ('cur' moves opposite to mouse) */
- vsm->delta = (float)(event->x - vsm->lastx);
- break;
- case 'v': /* vertical scroller - so only vertical movement
- * ('cur' moves opposite to mouse) */
- vsm->delta = (float)(event->y - vsm->lasty);
- break;
- }
- }
- else if (vsm->zone == SCROLLHANDLE_MIN) {
- /* using 'min' zoom widget */
- switch (vsm->scroller) {
- case 'h': /* horizontal scroller - so only horizontal movement
- * ('cur' moves with mouse) */
- vsm->delta = (float)(vsm->lastx - event->x);
- break;
- case 'v': /* vertical scroller - so only vertical movement
- * ('cur' moves with to mouse) */
- vsm->delta = (float)(vsm->lasty - event->y);
- break;
- }
- }
-
- /* store previous coordinates */
- vsm->lastx = event->x;
- vsm->lasty = event->y;
-
- scroller_activate_apply(C, op);
- break;
- }
- case LEFTMOUSE:
- case MIDDLEMOUSE:
- if (event->val == KM_RELEASE) {
- /* single-click was in empty space outside bubble, so scroll by 1 'page' */
- if (ELEM(vsm->zone, SCROLLHANDLE_MIN_OUTSIDE, SCROLLHANDLE_MAX_OUTSIDE)) {
- if (vsm->zone == SCROLLHANDLE_MIN_OUTSIDE) {
- vsm->delta = -vsm->scrollbarwidth * 0.8f;
- }
- else if (vsm->zone == SCROLLHANDLE_MAX_OUTSIDE) {
- vsm->delta = vsm->scrollbarwidth * 0.8f;
- }
-
- scroller_activate_apply(C, op);
- scroller_activate_exit(C, op);
- return OPERATOR_FINISHED;
- }
-
- /* otherwise, end the drag action */
- if (vsm->lastx || vsm->lasty) {
- scroller_activate_exit(C, op);
- return OPERATOR_FINISHED;
- }
- }
- break;
-
- }
-
- return OPERATOR_RUNNING_MODAL;
+ v2dScrollerMove *vsm = op->customdata;
+
+ /* execute the events */
+ switch (event->type) {
+ case MOUSEMOVE: {
+ /* calculate new delta transform, then store mouse-coordinates for next-time */
+ if (ELEM(vsm->zone, SCROLLHANDLE_BAR, SCROLLHANDLE_MAX)) {
+ /* if using bar (i.e. 'panning') or 'max' zoom widget */
+ switch (vsm->scroller) {
+ case 'h': /* horizontal scroller - so only horizontal movement
+ * ('cur' moves opposite to mouse) */
+ vsm->delta = (float)(event->x - vsm->lastx);
+ break;
+ case 'v': /* vertical scroller - so only vertical movement
+ * ('cur' moves opposite to mouse) */
+ vsm->delta = (float)(event->y - vsm->lasty);
+ break;
+ }
+ }
+ else if (vsm->zone == SCROLLHANDLE_MIN) {
+ /* using 'min' zoom widget */
+ switch (vsm->scroller) {
+ case 'h': /* horizontal scroller - so only horizontal movement
+ * ('cur' moves with mouse) */
+ vsm->delta = (float)(vsm->lastx - event->x);
+ break;
+ case 'v': /* vertical scroller - so only vertical movement
+ * ('cur' moves with to mouse) */
+ vsm->delta = (float)(vsm->lasty - event->y);
+ break;
+ }
+ }
+
+ /* store previous coordinates */
+ vsm->lastx = event->x;
+ vsm->lasty = event->y;
+
+ scroller_activate_apply(C, op);
+ break;
+ }
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ if (event->val == KM_RELEASE) {
+ /* single-click was in empty space outside bubble, so scroll by 1 'page' */
+ if (ELEM(vsm->zone, SCROLLHANDLE_MIN_OUTSIDE, SCROLLHANDLE_MAX_OUTSIDE)) {
+ if (vsm->zone == SCROLLHANDLE_MIN_OUTSIDE) {
+ vsm->delta = -vsm->scrollbarwidth * 0.8f;
+ }
+ else if (vsm->zone == SCROLLHANDLE_MAX_OUTSIDE) {
+ vsm->delta = vsm->scrollbarwidth * 0.8f;
+ }
+
+ scroller_activate_apply(C, op);
+ scroller_activate_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+
+ /* otherwise, end the drag action */
+ if (vsm->lastx || vsm->lasty) {
+ scroller_activate_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
-
/* a click (or click drag in progress)
* 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;
-
- /* check if mouse in scrollbars, if they're enabled */
- const char in_scroller = UI_view2d_mouse_in_scrollers(ar, v2d, event->x, event->y);
-
- /* if in a scroller, init customdata then set modal handler which will
- * catch mousedown to start doing useful stuff */
- if (in_scroller) {
- v2dScrollerMove *vsm;
-
- /* initialize customdata */
- scroller_activate_init(C, op, event, in_scroller);
- vsm = (v2dScrollerMove *)op->customdata;
-
- /* support for quick jump to location - gtk and qt do this on linux */
- if (event->type == MIDDLEMOUSE) {
- switch (vsm->scroller) {
- case 'h': /* horizontal scroller - so only horizontal movement
- * ('cur' moves opposite to mouse) */
- vsm->delta = (float)(event->x - vsm->scrollbar_orig);
- break;
- case 'v': /* vertical scroller - so only vertical movement
- * ('cur' moves opposite to mouse) */
- vsm->delta = (float)(event->y - vsm->scrollbar_orig);
- break;
- }
- scroller_activate_apply(C, op);
-
- vsm->zone = SCROLLHANDLE_BAR;
- }
-
- /* check if zoom zones are inappropriate (i.e. zoom widgets not shown), so cannot continue
- * NOTE: see view2d.c for latest conditions, and keep this in sync with that
- */
- if (ELEM(vsm->zone, SCROLLHANDLE_MIN, SCROLLHANDLE_MAX)) {
- if (((vsm->scroller == 'h') && (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) == 0) ||
- ((vsm->scroller == 'v') && (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) == 0))
- {
- /* switch to bar (i.e. no scaling gets handled) */
- vsm->zone = SCROLLHANDLE_BAR;
- }
- }
-
- /* check if zone is inappropriate (i.e. 'bar' but panning is banned), so cannot continue */
- if (vsm->zone == SCROLLHANDLE_BAR) {
- if (((vsm->scroller == 'h') && (v2d->keepofs & V2D_LOCKOFS_X)) ||
- ((vsm->scroller == 'v') && (v2d->keepofs & V2D_LOCKOFS_Y)))
- {
- /* free customdata initialized */
- scroller_activate_exit(C, op);
-
- /* can't catch this event for ourselves, so let it go to someone else? */
- return OPERATOR_PASS_THROUGH;
- }
- }
-
- /* zone is also inappropriate if scroller is not visible... */
- if (((vsm->scroller == 'h') && (v2d->scroll & (V2D_SCROLL_HORIZONTAL_FULLR))) ||
- ((vsm->scroller == 'v') && (v2d->scroll & (V2D_SCROLL_VERTICAL_FULLR))) )
- {
- /* free customdata initialized */
- scroller_activate_exit(C, op);
-
- /* can't catch this event for ourselves, so let it go to someone else? */
- /* XXX note: if handlers use mask rect to clip input, input will fail for this case */
- return OPERATOR_PASS_THROUGH;
- }
-
- /* activate the scroller */
- if (vsm->scroller == 'h') {
- v2d->scroll_ui |= V2D_SCROLL_H_ACTIVE;
- }
- else {
- v2d->scroll_ui |= V2D_SCROLL_V_ACTIVE;
- }
-
- /* still ok, so can add */
- WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
- }
- else {
- /* not in scroller, so nothing happened...
- * (pass through let's something else catch event) */
- return OPERATOR_PASS_THROUGH;
- }
+ ARegion *ar = CTX_wm_region(C);
+ View2D *v2d = &ar->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);
+
+ /* if in a scroller, init customdata then set modal handler which will
+ * catch mousedown to start doing useful stuff */
+ if (in_scroller) {
+ v2dScrollerMove *vsm;
+
+ /* initialize customdata */
+ scroller_activate_init(C, op, event, in_scroller);
+ vsm = (v2dScrollerMove *)op->customdata;
+
+ /* support for quick jump to location - gtk and qt do this on linux */
+ if (event->type == MIDDLEMOUSE) {
+ switch (vsm->scroller) {
+ case 'h': /* horizontal scroller - so only horizontal movement
+ * ('cur' moves opposite to mouse) */
+ vsm->delta = (float)(event->x - vsm->scrollbar_orig);
+ break;
+ case 'v': /* vertical scroller - so only vertical movement
+ * ('cur' moves opposite to mouse) */
+ vsm->delta = (float)(event->y - vsm->scrollbar_orig);
+ break;
+ }
+ scroller_activate_apply(C, op);
+
+ vsm->zone = SCROLLHANDLE_BAR;
+ }
+
+ /* check if zoom zones are inappropriate (i.e. zoom widgets not shown), so cannot continue
+ * NOTE: see view2d.c for latest conditions, and keep this in sync with that
+ */
+ if (ELEM(vsm->zone, SCROLLHANDLE_MIN, SCROLLHANDLE_MAX)) {
+ if (((vsm->scroller == 'h') && (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) == 0) ||
+ ((vsm->scroller == 'v') && (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) == 0)) {
+ /* switch to bar (i.e. no scaling gets handled) */
+ vsm->zone = SCROLLHANDLE_BAR;
+ }
+ }
+
+ /* check if zone is inappropriate (i.e. 'bar' but panning is banned), so cannot continue */
+ if (vsm->zone == SCROLLHANDLE_BAR) {
+ if (((vsm->scroller == 'h') && (v2d->keepofs & V2D_LOCKOFS_X)) ||
+ ((vsm->scroller == 'v') && (v2d->keepofs & V2D_LOCKOFS_Y))) {
+ /* free customdata initialized */
+ scroller_activate_exit(C, op);
+
+ /* can't catch this event for ourselves, so let it go to someone else? */
+ return OPERATOR_PASS_THROUGH;
+ }
+ }
+
+ /* zone is also inappropriate if scroller is not visible... */
+ if (((vsm->scroller == 'h') && (v2d->scroll & (V2D_SCROLL_HORIZONTAL_FULLR))) ||
+ ((vsm->scroller == 'v') && (v2d->scroll & (V2D_SCROLL_VERTICAL_FULLR)))) {
+ /* free customdata initialized */
+ scroller_activate_exit(C, op);
+
+ /* can't catch this event for ourselves, so let it go to someone else? */
+ /* XXX note: if handlers use mask rect to clip input, input will fail for this case */
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ /* activate the scroller */
+ if (vsm->scroller == 'h') {
+ v2d->scroll_ui |= V2D_SCROLL_H_ACTIVE;
+ }
+ else {
+ v2d->scroll_ui |= V2D_SCROLL_V_ACTIVE;
+ }
+
+ /* still ok, so can add */
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ /* not in scroller, so nothing happened...
+ * (pass through let's something else catch event) */
+ return OPERATOR_PASS_THROUGH;
+ }
}
/* LMB-Drag in Scrollers - not repeatable operator! */
static void VIEW2D_OT_scroller_activate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Scroller Activate";
- ot->description = "Scroll view by mouse click and drag";
- ot->idname = "VIEW2D_OT_scroller_activate";
+ /* identifiers */
+ ot->name = "Scroller Activate";
+ ot->description = "Scroll view by mouse click and drag";
+ ot->idname = "VIEW2D_OT_scroller_activate";
- /* flags */
- ot->flag = OPTYPE_BLOCKING;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
- /* api callbacks */
- ot->invoke = scroller_activate_invoke;
- ot->modal = scroller_activate_modal;
- ot->cancel = scroller_activate_cancel;
+ /* api callbacks */
+ ot->invoke = scroller_activate_invoke;
+ ot->modal = scroller_activate_modal;
+ ot->cancel = scroller_activate_cancel;
- ot->poll = scroller_activate_poll;
+ ot->poll = scroller_activate_poll;
}
/* ********************************************************* */
@@ -2142,70 +2103,70 @@ 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;
- int winx, winy;
- const int snap_test = ED_region_snap_size_test(ar);
-
- /* zoom 1.0 */
- winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
- winy = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
-
- v2d->cur.xmax = v2d->cur.xmin + winx;
- v2d->cur.ymax = v2d->cur.ymin + winy;
-
- /* align */
- if (v2d->align) {
- /* posx and negx flags are mutually exclusive, so watch out */
- if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
- v2d->cur.xmax = 0.0f;
- v2d->cur.xmin = -winx * style->panelzoom;
- }
- else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
- v2d->cur.xmax = winx * style->panelzoom;
- v2d->cur.xmin = 0.0f;
- }
-
- /* - posx and negx flags are mutually exclusive, so watch out */
- if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
- v2d->cur.ymax = 0.0f;
- v2d->cur.ymin = -winy * style->panelzoom;
- }
- else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
- v2d->cur.ymax = winy * style->panelzoom;
- v2d->cur.ymin = 0.0f;
- }
- }
-
- /* 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);
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
- }
-
- /* request updates to be done... */
- ED_region_tag_redraw(ar);
- UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
-
- UI_view2d_zoom_cache_reset();
-
- return OPERATOR_FINISHED;
+ uiStyle *style = UI_style_get();
+ ARegion *ar = CTX_wm_region(C);
+ View2D *v2d = &ar->v2d;
+ int winx, winy;
+ const int snap_test = ED_region_snap_size_test(ar);
+
+ /* zoom 1.0 */
+ winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
+ winy = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
+
+ v2d->cur.xmax = v2d->cur.xmin + winx;
+ v2d->cur.ymax = v2d->cur.ymin + winy;
+
+ /* align */
+ if (v2d->align) {
+ /* posx and negx flags are mutually exclusive, so watch out */
+ if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
+ v2d->cur.xmax = 0.0f;
+ v2d->cur.xmin = -winx * style->panelzoom;
+ }
+ else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
+ v2d->cur.xmax = winx * style->panelzoom;
+ v2d->cur.xmin = 0.0f;
+ }
+
+ /* - posx and negx flags are mutually exclusive, so watch out */
+ if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
+ v2d->cur.ymax = 0.0f;
+ v2d->cur.ymin = -winy * style->panelzoom;
+ }
+ else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
+ v2d->cur.ymax = winy * style->panelzoom;
+ v2d->cur.ymin = 0.0f;
+ }
+ }
+
+ /* 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);
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ }
+
+ /* request updates to be done... */
+ ED_region_tag_redraw(ar);
+ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
+
+ UI_view2d_zoom_cache_reset();
+
+ return OPERATOR_FINISHED;
}
static void VIEW2D_OT_reset(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reset View";
- ot->description = "Reset the view";
- ot->idname = "VIEW2D_OT_reset";
-
- /* api callbacks */
- ot->exec = reset_exec;
- ot->poll = view2d_poll;
+ /* identifiers */
+ ot->name = "Reset View";
+ ot->description = "Reset the view";
+ ot->idname = "VIEW2D_OT_reset";
+
+ /* api callbacks */
+ ot->exec = reset_exec;
+ ot->poll = view2d_poll;
}
/* ********************************************************* */
@@ -2213,31 +2174,31 @@ static void VIEW2D_OT_reset(wmOperatorType *ot)
void ED_operatortypes_view2d(void)
{
- WM_operatortype_append(VIEW2D_OT_pan);
+ WM_operatortype_append(VIEW2D_OT_pan);
- WM_operatortype_append(VIEW2D_OT_scroll_left);
- WM_operatortype_append(VIEW2D_OT_scroll_right);
- WM_operatortype_append(VIEW2D_OT_scroll_up);
- WM_operatortype_append(VIEW2D_OT_scroll_down);
+ WM_operatortype_append(VIEW2D_OT_scroll_left);
+ WM_operatortype_append(VIEW2D_OT_scroll_right);
+ WM_operatortype_append(VIEW2D_OT_scroll_up);
+ WM_operatortype_append(VIEW2D_OT_scroll_down);
- WM_operatortype_append(VIEW2D_OT_zoom_in);
- WM_operatortype_append(VIEW2D_OT_zoom_out);
+ WM_operatortype_append(VIEW2D_OT_zoom_in);
+ WM_operatortype_append(VIEW2D_OT_zoom_out);
- WM_operatortype_append(VIEW2D_OT_zoom);
- WM_operatortype_append(VIEW2D_OT_zoom_border);
+ WM_operatortype_append(VIEW2D_OT_zoom);
+ WM_operatortype_append(VIEW2D_OT_zoom_border);
#ifdef WITH_INPUT_NDOF
- WM_operatortype_append(VIEW2D_OT_ndof);
+ WM_operatortype_append(VIEW2D_OT_ndof);
#endif
- WM_operatortype_append(VIEW2D_OT_smoothview);
+ WM_operatortype_append(VIEW2D_OT_smoothview);
- WM_operatortype_append(VIEW2D_OT_scroller_activate);
+ WM_operatortype_append(VIEW2D_OT_scroller_activate);
- WM_operatortype_append(VIEW2D_OT_reset);
+ WM_operatortype_append(VIEW2D_OT_reset);
}
void ED_keymap_view2d(wmKeyConfig *keyconf)
{
- WM_keymap_ensure(keyconf, "View2D", 0, 0);
+ WM_keymap_ensure(keyconf, "View2D", 0, 0);
}
diff --git a/source/blender/editors/io/CMakeLists.txt b/source/blender/editors/io/CMakeLists.txt
index 6e3e111739c..fbbb8621ae6 100644
--- a/source/blender/editors/io/CMakeLists.txt
+++ b/source/blender/editors/io/CMakeLists.txt
@@ -16,18 +16,18 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../bmesh
- ../../depsgraph
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../collada
- ../../alembic
- ../../../../intern/guardedalloc
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../bmesh
+ ../../depsgraph
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../collada
+ ../../alembic
+ ../../../../intern/guardedalloc
)
set(INC_SYS
@@ -35,42 +35,42 @@ set(INC_SYS
)
set(SRC
- io_alembic.c
- io_cache.c
- io_collada.c
- io_ops.c
+ io_alembic.c
+ io_cache.c
+ io_collada.c
+ io_ops.c
- io_alembic.h
- io_cache.h
- io_collada.h
- io_ops.h
+ io_alembic.h
+ io_cache.h
+ io_collada.h
+ io_ops.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
+ bf_blenkernel
+ bf_blenlib
)
if(WITH_OPENCOLLADA)
- list(APPEND LIB
- bf_collada
- )
- add_definitions(-DWITH_COLLADA)
+ list(APPEND LIB
+ bf_collada
+ )
+ add_definitions(-DWITH_COLLADA)
endif()
if(WITH_ALEMBIC)
- list(APPEND LIB
- bf_alembic
- )
- add_definitions(-DWITH_ALEMBIC)
+ list(APPEND LIB
+ bf_alembic
+ )
+ add_definitions(-DWITH_ALEMBIC)
- if(WITH_ALEMBIC_HDF5)
- add_definitions(-DWITH_ALEMBIC_HDF5)
- endif()
+ if(WITH_ALEMBIC_HDF5)
+ add_definitions(-DWITH_ALEMBIC_HDF5)
+ endif()
endif()
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
blender_add_lib(bf_editor_io "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c
index 576d51b7c49..dc8e33c817e 100644
--- a/source/blender/editors/io/io_alembic.c
+++ b/source/blender/editors/io/io_alembic.c
@@ -24,385 +24,470 @@
#ifdef WITH_ALEMBIC
/* needed for directory lookup */
-#ifndef WIN32
-# include <dirent.h>
-#else
-# include "BLI_winstuff.h"
-#endif
+# ifndef WIN32
+# include <dirent.h>
+# else
+# include "BLI_winstuff.h"
+# endif
-#include <string.h>
-#include <errno.h>
+# include <string.h>
+# include <errno.h>
-#include "MEM_guardedalloc.h"
+# include "MEM_guardedalloc.h"
-#include "DNA_mesh_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_space_types.h"
+# include "DNA_mesh_types.h"
+# include "DNA_modifier_types.h"
+# include "DNA_object_types.h"
+# include "DNA_scene_types.h"
+# include "DNA_space_types.h"
-#include "BKE_context.h"
-#include "BKE_global.h"
-#include "BKE_main.h"
-#include "BKE_report.h"
+# include "BKE_context.h"
+# include "BKE_global.h"
+# include "BKE_main.h"
+# include "BKE_report.h"
-#include "BLI_listbase.h"
-#include "BLI_math_vector.h"
-#include "BLI_path_util.h"
-#include "BLI_string.h"
-#include "BLI_utildefines.h"
+# include "BLI_listbase.h"
+# include "BLI_math_vector.h"
+# include "BLI_path_util.h"
+# include "BLI_string.h"
+# include "BLI_utildefines.h"
-#include "BLT_translation.h"
+# include "BLT_translation.h"
-#include "RNA_access.h"
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
+# include "RNA_access.h"
+# include "RNA_define.h"
+# include "RNA_enum_types.h"
-#include "ED_object.h"
+# include "ED_object.h"
-#include "UI_interface.h"
-#include "UI_resources.h"
+# include "UI_interface.h"
+# include "UI_resources.h"
-#include "WM_api.h"
-#include "WM_types.h"
+# include "WM_api.h"
+# include "WM_types.h"
-#include "io_alembic.h"
+# include "io_alembic.h"
-#include "ABC_alembic.h"
+# include "ABC_alembic.h"
static int wm_alembic_export_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (!RNA_struct_property_is_set(op->ptr, "as_background_job")) {
- RNA_boolean_set(op->ptr, "as_background_job", true);
- }
+ if (!RNA_struct_property_is_set(op->ptr, "as_background_job")) {
+ RNA_boolean_set(op->ptr, "as_background_job", true);
+ }
- RNA_boolean_set(op->ptr, "init_scene_frame_range", true);
+ RNA_boolean_set(op->ptr, "init_scene_frame_range", true);
- if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
- Main *bmain = CTX_data_main(C);
- char filepath[FILE_MAX];
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ Main *bmain = CTX_data_main(C);
+ char filepath[FILE_MAX];
- if (BKE_main_blendfile_path(bmain)[0] == '\0') {
- BLI_strncpy(filepath, "untitled", sizeof(filepath));
- }
- else {
- BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath));
- }
+ if (BKE_main_blendfile_path(bmain)[0] == '\0') {
+ BLI_strncpy(filepath, "untitled", sizeof(filepath));
+ }
+ else {
+ BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath));
+ }
- BLI_path_extension_replace(filepath, sizeof(filepath), ".abc");
- RNA_string_set(op->ptr, "filepath", filepath);
- }
+ BLI_path_extension_replace(filepath, sizeof(filepath), ".abc");
+ RNA_string_set(op->ptr, "filepath", filepath);
+ }
- WM_event_add_fileselect(C, op);
+ WM_event_add_fileselect(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
- UNUSED_VARS(event);
+ UNUSED_VARS(event);
}
static int wm_alembic_export_exec(bContext *C, wmOperator *op)
{
- if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
- BKE_report(op->reports, RPT_ERROR, "No filename given");
- return OPERATOR_CANCELLED;
- }
-
- char filename[FILE_MAX];
- RNA_string_get(op->ptr, "filepath", filename);
-
- struct AlembicExportParams params = {
- .frame_start = RNA_int_get(op->ptr, "start"),
- .frame_end = RNA_int_get(op->ptr, "end"),
-
- .frame_samples_xform = RNA_int_get(op->ptr, "xsamples"),
- .frame_samples_shape = RNA_int_get(op->ptr, "gsamples"),
-
- .shutter_open = RNA_float_get(op->ptr, "sh_open"),
- .shutter_close = RNA_float_get(op->ptr, "sh_close"),
-
- .selected_only = RNA_boolean_get(op->ptr, "selected"),
- .uvs = RNA_boolean_get(op->ptr, "uvs"),
- .normals = RNA_boolean_get(op->ptr, "normals"),
- .vcolors = RNA_boolean_get(op->ptr, "vcolors"),
- .apply_subdiv = RNA_boolean_get(op->ptr, "apply_subdiv"),
- .curves_as_mesh = RNA_boolean_get(op->ptr, "curves_as_mesh"),
- .flatten_hierarchy = RNA_boolean_get(op->ptr, "flatten"),
- .visible_layers_only = RNA_boolean_get(op->ptr, "visible_layers_only"),
- .renderable_only = RNA_boolean_get(op->ptr, "renderable_only"),
- .face_sets = RNA_boolean_get(op->ptr, "face_sets"),
- .use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"),
- .export_hair = RNA_boolean_get(op->ptr, "export_hair"),
- .export_particles = RNA_boolean_get(op->ptr, "export_particles"),
- .compression_type = RNA_enum_get(op->ptr, "compression_type"),
- .packuv = RNA_boolean_get(op->ptr, "packuv"),
- .triangulate = RNA_boolean_get(op->ptr, "triangulate"),
- .quad_method = RNA_enum_get(op->ptr, "quad_method"),
- .ngon_method = RNA_enum_get(op->ptr, "ngon_method"),
-
- .global_scale = RNA_float_get(op->ptr, "global_scale"),
- };
-
- /* Take some defaults from the scene, if not specified explicitly. */
- Scene *scene = CTX_data_scene(C);
- if (params.frame_start == INT_MIN) {
- params.frame_start = SFRA;
- }
- if (params.frame_end == INT_MIN) {
- params.frame_end = EFRA;
- }
-
- const bool as_background_job = RNA_boolean_get(op->ptr, "as_background_job");
- bool ok = ABC_export(scene, C, filename, &params, as_background_job);
-
- return as_background_job || ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ BKE_report(op->reports, RPT_ERROR, "No filename given");
+ return OPERATOR_CANCELLED;
+ }
+
+ char filename[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filename);
+
+ struct AlembicExportParams params = {
+ .frame_start = RNA_int_get(op->ptr, "start"),
+ .frame_end = RNA_int_get(op->ptr, "end"),
+
+ .frame_samples_xform = RNA_int_get(op->ptr, "xsamples"),
+ .frame_samples_shape = RNA_int_get(op->ptr, "gsamples"),
+
+ .shutter_open = RNA_float_get(op->ptr, "sh_open"),
+ .shutter_close = RNA_float_get(op->ptr, "sh_close"),
+
+ .selected_only = RNA_boolean_get(op->ptr, "selected"),
+ .uvs = RNA_boolean_get(op->ptr, "uvs"),
+ .normals = RNA_boolean_get(op->ptr, "normals"),
+ .vcolors = RNA_boolean_get(op->ptr, "vcolors"),
+ .apply_subdiv = RNA_boolean_get(op->ptr, "apply_subdiv"),
+ .curves_as_mesh = RNA_boolean_get(op->ptr, "curves_as_mesh"),
+ .flatten_hierarchy = RNA_boolean_get(op->ptr, "flatten"),
+ .visible_layers_only = RNA_boolean_get(op->ptr, "visible_layers_only"),
+ .renderable_only = RNA_boolean_get(op->ptr, "renderable_only"),
+ .face_sets = RNA_boolean_get(op->ptr, "face_sets"),
+ .use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"),
+ .export_hair = RNA_boolean_get(op->ptr, "export_hair"),
+ .export_particles = RNA_boolean_get(op->ptr, "export_particles"),
+ .compression_type = RNA_enum_get(op->ptr, "compression_type"),
+ .packuv = RNA_boolean_get(op->ptr, "packuv"),
+ .triangulate = RNA_boolean_get(op->ptr, "triangulate"),
+ .quad_method = RNA_enum_get(op->ptr, "quad_method"),
+ .ngon_method = RNA_enum_get(op->ptr, "ngon_method"),
+
+ .global_scale = RNA_float_get(op->ptr, "global_scale"),
+ };
+
+ /* Take some defaults from the scene, if not specified explicitly. */
+ Scene *scene = CTX_data_scene(C);
+ if (params.frame_start == INT_MIN) {
+ params.frame_start = SFRA;
+ }
+ if (params.frame_end == INT_MIN) {
+ params.frame_end = EFRA;
+ }
+
+ const bool as_background_job = RNA_boolean_get(op->ptr, "as_background_job");
+ bool ok = ABC_export(scene, C, filename, &params, as_background_job);
+
+ return as_background_job || ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr)
{
- uiLayout *box;
- uiLayout *row;
- uiLayout *col;
+ uiLayout *box;
+ uiLayout *row;
+ uiLayout *col;
-#ifdef WITH_ALEMBIC_HDF5
- box = uiLayoutBox(layout);
- row = uiLayoutRow(box, false);
- uiItemL(row, IFACE_("Archive Options:"), ICON_NONE);
+# ifdef WITH_ALEMBIC_HDF5
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Archive Options:"), ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "compression_type", 0, NULL, ICON_NONE);
-#endif
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "compression_type", 0, NULL, ICON_NONE);
+# endif
- box = uiLayoutBox(layout);
- row = uiLayoutRow(box, false);
- uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE);
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "global_scale", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "global_scale", 0, NULL, ICON_NONE);
- /* Scene Options */
- box = uiLayoutBox(layout);
- row = uiLayoutRow(box, false);
- uiItemL(row, IFACE_("Scene Options:"), ICON_SCENE_DATA);
+ /* Scene Options */
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Scene Options:"), ICON_SCENE_DATA);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "start", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "start", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "end", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "end", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "xsamples", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "xsamples", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "gsamples", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "gsamples", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "sh_open", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "sh_open", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "sh_close", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "sh_close", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "selected", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "selected", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "renderable_only", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "renderable_only", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "visible_layers_only", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "visible_layers_only", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "flatten", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "flatten", 0, NULL, ICON_NONE);
- /* Object Data */
- box = uiLayoutBox(layout);
- row = uiLayoutRow(box, false);
- uiItemL(row, IFACE_("Object Options:"), ICON_OBJECT_DATA);
+ /* Object Data */
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Object Options:"), ICON_OBJECT_DATA);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "uvs", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "uvs", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "packuv", 0, NULL, ICON_NONE);
- uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "uvs"));
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "packuv", 0, NULL, ICON_NONE);
+ uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "uvs"));
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "normals", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "normals", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "vcolors", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "vcolors", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "face_sets", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "face_sets", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "subdiv_schema", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "subdiv_schema", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "apply_subdiv", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "apply_subdiv", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "curves_as_mesh", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "curves_as_mesh", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "triangulate", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "triangulate", 0, NULL, ICON_NONE);
- const bool triangulate = RNA_boolean_get(imfptr, "triangulate");
+ const bool triangulate = RNA_boolean_get(imfptr, "triangulate");
- row = uiLayoutRow(box, false);
- uiLayoutSetEnabled(row, triangulate);
- uiItemR(row, imfptr, "quad_method", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiLayoutSetEnabled(row, triangulate);
+ uiItemR(row, imfptr, "quad_method", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiLayoutSetEnabled(row, triangulate);
- uiItemR(row, imfptr, "ngon_method", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiLayoutSetEnabled(row, triangulate);
+ uiItemR(row, imfptr, "ngon_method", 0, NULL, ICON_NONE);
- /* Object Data */
- box = uiLayoutBox(layout);
- row = uiLayoutRow(box, false);
- uiItemL(row, IFACE_("Particle Systems:"), ICON_PARTICLE_DATA);
+ /* Object Data */
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Particle Systems:"), ICON_PARTICLE_DATA);
- col = uiLayoutColumn(box, true);
- uiItemR(col, imfptr, "export_hair", 0, NULL, ICON_NONE);
- uiItemR(col, imfptr, "export_particles", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(box, true);
+ uiItemR(col, imfptr, "export_hair", 0, NULL, ICON_NONE);
+ uiItemR(col, imfptr, "export_particles", 0, NULL, ICON_NONE);
}
static void wm_alembic_export_draw(bContext *C, wmOperator *op)
{
- PointerRNA ptr;
+ PointerRNA ptr;
- RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
- /* Conveniently set start and end frame to match the scene's frame range. */
- Scene *scene = CTX_data_scene(C);
+ /* Conveniently set start and end frame to match the scene's frame range. */
+ Scene *scene = CTX_data_scene(C);
- if (scene != NULL && RNA_boolean_get(&ptr, "init_scene_frame_range")) {
- RNA_int_set(&ptr, "start", SFRA);
- RNA_int_set(&ptr, "end", EFRA);
+ if (scene != NULL && RNA_boolean_get(&ptr, "init_scene_frame_range")) {
+ RNA_int_set(&ptr, "start", SFRA);
+ RNA_int_set(&ptr, "end", EFRA);
- RNA_boolean_set(&ptr, "init_scene_frame_range", false);
- }
+ RNA_boolean_set(&ptr, "init_scene_frame_range", false);
+ }
- ui_alembic_export_settings(op->layout, &ptr);
+ ui_alembic_export_settings(op->layout, &ptr);
}
static bool wm_alembic_export_check(bContext *UNUSED(C), wmOperator *op)
{
- char filepath[FILE_MAX];
- RNA_string_get(op->ptr, "filepath", filepath);
+ char filepath[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filepath);
- if (!BLI_path_extension_check(filepath, ".abc")) {
- BLI_path_extension_ensure(filepath, FILE_MAX, ".abc");
- RNA_string_set(op->ptr, "filepath", filepath);
- return true;
- }
+ if (!BLI_path_extension_check(filepath, ".abc")) {
+ BLI_path_extension_ensure(filepath, FILE_MAX, ".abc");
+ RNA_string_set(op->ptr, "filepath", filepath);
+ return true;
+ }
- return false;
+ return false;
}
void WM_OT_alembic_export(wmOperatorType *ot)
{
- ot->name = "Export Alembic";
- ot->description = "Export current scene in an Alembic archive";
- ot->idname = "WM_OT_alembic_export";
-
- ot->invoke = wm_alembic_export_invoke;
- ot->exec = wm_alembic_export_exec;
- ot->poll = WM_operator_winactive;
- ot->ui = wm_alembic_export_draw;
- ot->check = wm_alembic_export_check;
-
- WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_ALEMBIC,
- FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH,
- FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
-
- RNA_def_int(ot->srna, "start", INT_MIN, INT_MIN, INT_MAX,
- "Start Frame",
- "Start frame of the export, use the default value to "
- "take the start frame of the current scene",
- INT_MIN, INT_MAX);
-
- RNA_def_int(ot->srna, "end", INT_MIN, INT_MIN, INT_MAX,
- "End Frame",
- "End frame of the export, use the default value to "
- "take the end frame of the current scene",
- INT_MIN, INT_MAX);
-
- RNA_def_int(ot->srna, "xsamples", 1, 1, 128,
- "Transform Samples", "Number of times per frame transformations are sampled", 1, 128);
-
- RNA_def_int(ot->srna, "gsamples", 1, 1, 128,
- "Geometry Samples", "Number of times per frame object data are sampled", 1, 128);
-
- RNA_def_float(ot->srna, "sh_open", 0.0f, -1.0f, 1.0f,
- "Shutter Open", "Time at which the shutter is open", -1.0f, 1.0f);
-
- RNA_def_float(ot->srna, "sh_close", 1.0f, -1.0f, 1.0f,
- "Shutter Close", "Time at which the shutter is closed", -1.0f, 1.0f);
-
- RNA_def_boolean(ot->srna, "selected", 0,
- "Selected Objects Only", "Export only selected objects");
-
- RNA_def_boolean(ot->srna, "renderable_only", 1,
- "Renderable Objects Only",
- "Export only objects marked renderable in the outliner");
-
- RNA_def_boolean(ot->srna, "visible_layers_only", 0,
- "Visible Layers Only", "Export only objects in visible layers");
-
- RNA_def_boolean(ot->srna, "flatten", 0,
- "Flatten Hierarchy",
- "Do not preserve objects' parent/children relationship");
-
- RNA_def_boolean(ot->srna, "uvs", 1, "UVs", "Export UVs");
-
- RNA_def_boolean(ot->srna, "packuv", 1, "Pack UV Islands",
- "Export UVs with packed island");
-
- RNA_def_boolean(ot->srna, "normals", 1, "Normals", "Export normals");
-
- RNA_def_boolean(ot->srna, "vcolors", 0, "Vertex Colors", "Export vertex colors");
-
- RNA_def_boolean(ot->srna, "face_sets", 0, "Face Sets", "Export per face shading group assignments");
-
- RNA_def_boolean(ot->srna, "subdiv_schema", 0,
- "Use Subdivision Schema",
- "Export meshes using Alembic's subdivision schema");
-
- RNA_def_boolean(ot->srna, "apply_subdiv", 0,
- "Apply Subsurf", "Export subdivision surfaces as meshes");
-
- RNA_def_boolean(ot->srna, "curves_as_mesh", false,
- "Curves as Mesh", "Export curves and NURBS surfaces as meshes");
-
- RNA_def_enum(ot->srna, "compression_type", rna_enum_abc_compression_items,
- ABC_ARCHIVE_OGAWA, "Compression", "");
-
- RNA_def_float(ot->srna, "global_scale", 1.0f, 0.0001f, 1000.0f, "Scale",
- "Value by which to enlarge or shrink the objects with respect to the world's origin",
- 0.0001f, 1000.0f);
-
- RNA_def_boolean(ot->srna, "triangulate", false, "Triangulate",
- "Export Polygons (Quads & NGons) as Triangles");
-
- RNA_def_enum(ot->srna, "quad_method", rna_enum_modifier_triangulate_quad_method_items,
- MOD_TRIANGULATE_QUAD_SHORTEDGE, "Quad Method", "Method for splitting the quads into triangles");
-
- RNA_def_enum(ot->srna, "ngon_method", rna_enum_modifier_triangulate_quad_method_items,
- MOD_TRIANGULATE_NGON_BEAUTY, "Polygon Method", "Method for splitting the polygons into triangles");
-
- RNA_def_boolean(ot->srna, "export_hair", 1, "Export Hair", "Exports hair particle systems as animated curves");
- RNA_def_boolean(ot->srna, "export_particles", 1, "Export Particles", "Exports non-hair particle systems");
-
- RNA_def_boolean(ot->srna, "as_background_job", false, "Run as Background Job",
- "Enable this to run the import in the background, disable to block Blender while importing. "
- "This option is deprecated; EXECUTE this operator to run in the foreground, and INVOKE it "
- "to run as a background job");
-
- /* This dummy prop is used to check whether we need to init the start and
- * end frame values to that of the scene's, otherwise they are reset at
- * every change, draw update. */
- RNA_def_boolean(ot->srna, "init_scene_frame_range", false, "", "");
+ ot->name = "Export Alembic";
+ ot->description = "Export current scene in an Alembic archive";
+ ot->idname = "WM_OT_alembic_export";
+
+ ot->invoke = wm_alembic_export_invoke;
+ ot->exec = wm_alembic_export_exec;
+ ot->poll = WM_operator_winactive;
+ ot->ui = wm_alembic_export_draw;
+ ot->check = wm_alembic_export_check;
+
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_ALEMBIC,
+ FILE_BLENDER,
+ FILE_SAVE,
+ WM_FILESEL_FILEPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
+
+ RNA_def_int(ot->srna,
+ "start",
+ INT_MIN,
+ INT_MIN,
+ INT_MAX,
+ "Start Frame",
+ "Start frame of the export, use the default value to "
+ "take the start frame of the current scene",
+ INT_MIN,
+ INT_MAX);
+
+ RNA_def_int(ot->srna,
+ "end",
+ INT_MIN,
+ INT_MIN,
+ INT_MAX,
+ "End Frame",
+ "End frame of the export, use the default value to "
+ "take the end frame of the current scene",
+ INT_MIN,
+ INT_MAX);
+
+ RNA_def_int(ot->srna,
+ "xsamples",
+ 1,
+ 1,
+ 128,
+ "Transform Samples",
+ "Number of times per frame transformations are sampled",
+ 1,
+ 128);
+
+ RNA_def_int(ot->srna,
+ "gsamples",
+ 1,
+ 1,
+ 128,
+ "Geometry Samples",
+ "Number of times per frame object data are sampled",
+ 1,
+ 128);
+
+ RNA_def_float(ot->srna,
+ "sh_open",
+ 0.0f,
+ -1.0f,
+ 1.0f,
+ "Shutter Open",
+ "Time at which the shutter is open",
+ -1.0f,
+ 1.0f);
+
+ RNA_def_float(ot->srna,
+ "sh_close",
+ 1.0f,
+ -1.0f,
+ 1.0f,
+ "Shutter Close",
+ "Time at which the shutter is closed",
+ -1.0f,
+ 1.0f);
+
+ RNA_def_boolean(
+ ot->srna, "selected", 0, "Selected Objects Only", "Export only selected objects");
+
+ RNA_def_boolean(ot->srna,
+ "renderable_only",
+ 1,
+ "Renderable Objects Only",
+ "Export only objects marked renderable in the outliner");
+
+ RNA_def_boolean(ot->srna,
+ "visible_layers_only",
+ 0,
+ "Visible Layers Only",
+ "Export only objects in visible layers");
+
+ RNA_def_boolean(ot->srna,
+ "flatten",
+ 0,
+ "Flatten Hierarchy",
+ "Do not preserve objects' parent/children relationship");
+
+ RNA_def_boolean(ot->srna, "uvs", 1, "UVs", "Export UVs");
+
+ RNA_def_boolean(ot->srna, "packuv", 1, "Pack UV Islands", "Export UVs with packed island");
+
+ RNA_def_boolean(ot->srna, "normals", 1, "Normals", "Export normals");
+
+ RNA_def_boolean(ot->srna, "vcolors", 0, "Vertex Colors", "Export vertex colors");
+
+ RNA_def_boolean(
+ ot->srna, "face_sets", 0, "Face Sets", "Export per face shading group assignments");
+
+ RNA_def_boolean(ot->srna,
+ "subdiv_schema",
+ 0,
+ "Use Subdivision Schema",
+ "Export meshes using Alembic's subdivision schema");
+
+ RNA_def_boolean(
+ ot->srna, "apply_subdiv", 0, "Apply Subsurf", "Export subdivision surfaces as meshes");
+
+ RNA_def_boolean(ot->srna,
+ "curves_as_mesh",
+ false,
+ "Curves as Mesh",
+ "Export curves and NURBS surfaces as meshes");
+
+ RNA_def_enum(ot->srna,
+ "compression_type",
+ rna_enum_abc_compression_items,
+ ABC_ARCHIVE_OGAWA,
+ "Compression",
+ "");
+
+ RNA_def_float(
+ ot->srna,
+ "global_scale",
+ 1.0f,
+ 0.0001f,
+ 1000.0f,
+ "Scale",
+ "Value by which to enlarge or shrink the objects with respect to the world's origin",
+ 0.0001f,
+ 1000.0f);
+
+ RNA_def_boolean(ot->srna,
+ "triangulate",
+ false,
+ "Triangulate",
+ "Export Polygons (Quads & NGons) as Triangles");
+
+ RNA_def_enum(ot->srna,
+ "quad_method",
+ rna_enum_modifier_triangulate_quad_method_items,
+ MOD_TRIANGULATE_QUAD_SHORTEDGE,
+ "Quad Method",
+ "Method for splitting the quads into triangles");
+
+ RNA_def_enum(ot->srna,
+ "ngon_method",
+ rna_enum_modifier_triangulate_quad_method_items,
+ MOD_TRIANGULATE_NGON_BEAUTY,
+ "Polygon Method",
+ "Method for splitting the polygons into triangles");
+
+ RNA_def_boolean(ot->srna,
+ "export_hair",
+ 1,
+ "Export Hair",
+ "Exports hair particle systems as animated curves");
+ RNA_def_boolean(
+ ot->srna, "export_particles", 1, "Export Particles", "Exports non-hair particle systems");
+
+ RNA_def_boolean(
+ ot->srna,
+ "as_background_job",
+ false,
+ "Run as Background Job",
+ "Enable this to run the import in the background, disable to block Blender while importing. "
+ "This option is deprecated; EXECUTE this operator to run in the foreground, and INVOKE it "
+ "to run as a background job");
+
+ /* This dummy prop is used to check whether we need to init the start and
+ * end frame values to that of the scene's, otherwise they are reset at
+ * every change, draw update. */
+ RNA_def_boolean(ot->srna, "init_scene_frame_range", false, "", "");
}
/* ************************************************************************** */
@@ -410,210 +495,242 @@ void WM_OT_alembic_export(wmOperatorType *ot)
/* TODO(kevin): check on de-duplicating all this with code in image_ops.c */
typedef struct CacheFrame {
- struct CacheFrame *next, *prev;
- int framenr;
+ struct CacheFrame *next, *prev;
+ int framenr;
} CacheFrame;
static int cmp_frame(const void *a, const void *b)
{
- const CacheFrame *frame_a = a;
- const CacheFrame *frame_b = b;
-
- if (frame_a->framenr < frame_b->framenr) return -1;
- if (frame_a->framenr > frame_b->framenr) return 1;
- return 0;
+ const CacheFrame *frame_a = a;
+ const CacheFrame *frame_b = b;
+
+ if (frame_a->framenr < frame_b->framenr)
+ return -1;
+ if (frame_a->framenr > frame_b->framenr)
+ return 1;
+ return 0;
}
static int get_sequence_len(char *filename, int *ofs)
{
- int frame;
- int numdigit;
+ int frame;
+ int numdigit;
- if (!BLI_path_frame_get(filename, &frame, &numdigit)) {
- return 1;
- }
+ if (!BLI_path_frame_get(filename, &frame, &numdigit)) {
+ return 1;
+ }
- char path[FILE_MAX];
- BLI_path_abs(filename, BKE_main_blendfile_path_from_global());
- BLI_split_dir_part(filename, path, FILE_MAX);
+ char path[FILE_MAX];
+ BLI_path_abs(filename, BKE_main_blendfile_path_from_global());
+ BLI_split_dir_part(filename, path, FILE_MAX);
- if (path[0] == '\0') {
- /* The filename had no path, so just use the blend file path. */
- BLI_split_dir_part(BKE_main_blendfile_path_from_global(), path, FILE_MAX);
- }
+ if (path[0] == '\0') {
+ /* The filename had no path, so just use the blend file path. */
+ BLI_split_dir_part(BKE_main_blendfile_path_from_global(), path, FILE_MAX);
+ }
- DIR *dir = opendir(path);
- if (dir == NULL) {
- fprintf(stderr, "Error opening directory '%s': %s\n",
- path, errno ? strerror(errno) : "unknown error");
- return -1;
- }
+ DIR *dir = opendir(path);
+ if (dir == NULL) {
+ fprintf(stderr,
+ "Error opening directory '%s': %s\n",
+ path,
+ errno ? strerror(errno) : "unknown error");
+ return -1;
+ }
- const char *ext = ".abc";
- const char *basename = BLI_path_basename(filename);
- const int len = strlen(basename) - (numdigit + strlen(ext));
+ const char *ext = ".abc";
+ const char *basename = BLI_path_basename(filename);
+ const int len = strlen(basename) - (numdigit + strlen(ext));
- ListBase frames;
- BLI_listbase_clear(&frames);
+ ListBase frames;
+ BLI_listbase_clear(&frames);
- struct dirent *fname;
- while ((fname = readdir(dir)) != NULL) {
- /* do we have the right extension? */
- if (!strstr(fname->d_name, ext)) {
- continue;
- }
+ struct dirent *fname;
+ while ((fname = readdir(dir)) != NULL) {
+ /* do we have the right extension? */
+ if (!strstr(fname->d_name, ext)) {
+ continue;
+ }
- if (!STREQLEN(basename, fname->d_name, len)) {
- continue;
- }
+ if (!STREQLEN(basename, fname->d_name, len)) {
+ continue;
+ }
- CacheFrame *cache_frame = MEM_callocN(sizeof(CacheFrame), "abc_frame");
+ CacheFrame *cache_frame = MEM_callocN(sizeof(CacheFrame), "abc_frame");
- BLI_path_frame_get(fname->d_name, &cache_frame->framenr, &numdigit);
+ BLI_path_frame_get(fname->d_name, &cache_frame->framenr, &numdigit);
- BLI_addtail(&frames, cache_frame);
- }
+ BLI_addtail(&frames, cache_frame);
+ }
- closedir(dir);
+ closedir(dir);
- BLI_listbase_sort(&frames, cmp_frame);
+ BLI_listbase_sort(&frames, cmp_frame);
- CacheFrame *cache_frame = frames.first;
+ CacheFrame *cache_frame = frames.first;
- if (cache_frame) {
- int frame_curr = cache_frame->framenr;
- (*ofs) = frame_curr;
+ if (cache_frame) {
+ int frame_curr = cache_frame->framenr;
+ (*ofs) = frame_curr;
- while (cache_frame && (cache_frame->framenr == frame_curr)) {
- ++frame_curr;
- cache_frame = cache_frame->next;
- }
+ while (cache_frame && (cache_frame->framenr == frame_curr)) {
+ ++frame_curr;
+ cache_frame = cache_frame->next;
+ }
- BLI_freelistN(&frames);
+ BLI_freelistN(&frames);
- return frame_curr - (*ofs);
- }
+ return frame_curr - (*ofs);
+ }
- return 1;
+ return 1;
}
/* ************************************************************************** */
static void ui_alembic_import_settings(uiLayout *layout, PointerRNA *imfptr)
{
- uiLayout *box = uiLayoutBox(layout);
- uiLayout *row = uiLayoutRow(box, false);
- uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE);
+ uiLayout *box = uiLayoutBox(layout);
+ uiLayout *row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "scale", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "scale", 0, NULL, ICON_NONE);
- box = uiLayoutBox(layout);
- row = uiLayoutRow(box, false);
- uiItemL(row, IFACE_("Options:"), ICON_NONE);
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Options:"), ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "set_frame_range", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "set_frame_range", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "is_sequence", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "is_sequence", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "validate_meshes", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "validate_meshes", 0, NULL, ICON_NONE);
}
static void wm_alembic_import_draw(bContext *UNUSED(C), wmOperator *op)
{
- PointerRNA ptr;
+ PointerRNA ptr;
- RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
- ui_alembic_import_settings(op->layout, &ptr);
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+ ui_alembic_import_settings(op->layout, &ptr);
}
-
/* op->invoke, opens fileselect if path property not set, otherwise executes */
static int wm_alembic_import_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (!RNA_struct_property_is_set(op->ptr, "as_background_job")) {
- RNA_boolean_set(op->ptr, "as_background_job", true);
- }
- return WM_operator_filesel(C, op, event);
+ if (!RNA_struct_property_is_set(op->ptr, "as_background_job")) {
+ RNA_boolean_set(op->ptr, "as_background_job", true);
+ }
+ return WM_operator_filesel(C, op, event);
}
-
static int wm_alembic_import_exec(bContext *C, wmOperator *op)
{
- if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
- BKE_report(op->reports, RPT_ERROR, "No filename given");
- return OPERATOR_CANCELLED;
- }
-
- char filename[FILE_MAX];
- RNA_string_get(op->ptr, "filepath", filename);
-
- const float scale = RNA_float_get(op->ptr, "scale");
- const bool is_sequence = RNA_boolean_get(op->ptr, "is_sequence");
- const bool set_frame_range = RNA_boolean_get(op->ptr, "set_frame_range");
- const bool validate_meshes = RNA_boolean_get(op->ptr, "validate_meshes");
- const bool as_background_job = RNA_boolean_get(op->ptr, "as_background_job");
-
- int offset = 0;
- int sequence_len = 1;
-
- if (is_sequence) {
- sequence_len = get_sequence_len(filename, &offset);
- if (sequence_len < 0) {
- BKE_report(op->reports, RPT_ERROR, "Unable to determine ABC sequence length");
- return OPERATOR_CANCELLED;
- }
- }
-
- /* Switch out of edit mode to avoid being stuck in it (T54326). */
- Object *obedit = CTX_data_edit_object(C);
- if (obedit) {
- ED_object_mode_toggle(C, OB_MODE_EDIT);
- }
-
- bool ok = ABC_import(C, filename, scale, is_sequence, set_frame_range,
- sequence_len, offset, validate_meshes,
- as_background_job);
-
- return as_background_job || ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ BKE_report(op->reports, RPT_ERROR, "No filename given");
+ return OPERATOR_CANCELLED;
+ }
+
+ char filename[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filename);
+
+ const float scale = RNA_float_get(op->ptr, "scale");
+ const bool is_sequence = RNA_boolean_get(op->ptr, "is_sequence");
+ const bool set_frame_range = RNA_boolean_get(op->ptr, "set_frame_range");
+ const bool validate_meshes = RNA_boolean_get(op->ptr, "validate_meshes");
+ const bool as_background_job = RNA_boolean_get(op->ptr, "as_background_job");
+
+ int offset = 0;
+ int sequence_len = 1;
+
+ if (is_sequence) {
+ sequence_len = get_sequence_len(filename, &offset);
+ if (sequence_len < 0) {
+ BKE_report(op->reports, RPT_ERROR, "Unable to determine ABC sequence length");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ /* Switch out of edit mode to avoid being stuck in it (T54326). */
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit) {
+ ED_object_mode_toggle(C, OB_MODE_EDIT);
+ }
+
+ bool ok = ABC_import(C,
+ filename,
+ scale,
+ is_sequence,
+ set_frame_range,
+ sequence_len,
+ offset,
+ validate_meshes,
+ as_background_job);
+
+ return as_background_job || ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void WM_OT_alembic_import(wmOperatorType *ot)
{
- ot->name = "Import Alembic";
- ot->description = "Load an Alembic archive";
- ot->idname = "WM_OT_alembic_import";
-
- ot->invoke = wm_alembic_import_invoke;
- ot->exec = wm_alembic_import_exec;
- ot->poll = WM_operator_winactive;
- ot->ui = wm_alembic_import_draw;
-
- WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_ALEMBIC,
- FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH,
- FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
-
- RNA_def_float(ot->srna, "scale", 1.0f, 0.0001f, 1000.0f, "Scale",
- "Value by which to enlarge or shrink the objects with respect to the world's origin",
- 0.0001f, 1000.0f);
-
- RNA_def_boolean(ot->srna, "set_frame_range", true,
- "Set Frame Range",
- "If checked, update scene's start and end frame to match those of the Alembic archive");
-
- RNA_def_boolean(ot->srna, "validate_meshes", 0,
- "Validate Meshes", "Check imported mesh objects for invalid data (slow)");
-
- RNA_def_boolean(ot->srna, "is_sequence", false, "Is Sequence",
- "Set to true if the cache is split into separate files");
-
- RNA_def_boolean(ot->srna, "as_background_job", false, "Run as Background Job",
- "Enable this to run the export in the background, disable to block Blender while exporting. "
- "This option is deprecated; EXECUTE this operator to run in the foreground, and INVOKE it "
- "to run as a background job");
+ ot->name = "Import Alembic";
+ ot->description = "Load an Alembic archive";
+ ot->idname = "WM_OT_alembic_import";
+
+ ot->invoke = wm_alembic_import_invoke;
+ ot->exec = wm_alembic_import_exec;
+ ot->poll = WM_operator_winactive;
+ ot->ui = wm_alembic_import_draw;
+
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_ALEMBIC,
+ FILE_BLENDER,
+ FILE_SAVE,
+ WM_FILESEL_FILEPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
+
+ RNA_def_float(
+ ot->srna,
+ "scale",
+ 1.0f,
+ 0.0001f,
+ 1000.0f,
+ "Scale",
+ "Value by which to enlarge or shrink the objects with respect to the world's origin",
+ 0.0001f,
+ 1000.0f);
+
+ RNA_def_boolean(
+ ot->srna,
+ "set_frame_range",
+ true,
+ "Set Frame Range",
+ "If checked, update scene's start and end frame to match those of the Alembic archive");
+
+ RNA_def_boolean(ot->srna,
+ "validate_meshes",
+ 0,
+ "Validate Meshes",
+ "Check imported mesh objects for invalid data (slow)");
+
+ RNA_def_boolean(ot->srna,
+ "is_sequence",
+ false,
+ "Is Sequence",
+ "Set to true if the cache is split into separate files");
+
+ RNA_def_boolean(
+ ot->srna,
+ "as_background_job",
+ false,
+ "Run as Background Job",
+ "Enable this to run the export in the background, disable to block Blender while exporting. "
+ "This option is deprecated; EXECUTE this operator to run in the foreground, and INVOKE it "
+ "to run as a background job");
}
#endif
diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c
index 300382d3071..6358c2c1370 100644
--- a/source/blender/editors/io/io_cache.c
+++ b/source/blender/editors/io/io_cache.c
@@ -47,119 +47,123 @@
static void cachefile_init(bContext *C, wmOperator *op)
{
- PropertyPointerRNA *pprop;
+ PropertyPointerRNA *pprop;
- op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
- UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
+ op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
+ UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
}
static int cachefile_open_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
- char filepath[FILE_MAX];
- Main *bmain = CTX_data_main(C);
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ char filepath[FILE_MAX];
+ Main *bmain = CTX_data_main(C);
- BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath));
- BLI_path_extension_replace(filepath, sizeof(filepath), ".abc");
- RNA_string_set(op->ptr, "filepath", filepath);
- }
+ BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath));
+ BLI_path_extension_replace(filepath, sizeof(filepath), ".abc");
+ RNA_string_set(op->ptr, "filepath", filepath);
+ }
- cachefile_init(C, op);
+ cachefile_init(C, op);
- WM_event_add_fileselect(C, op);
+ WM_event_add_fileselect(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
- UNUSED_VARS(event);
+ UNUSED_VARS(event);
}
static void open_cancel(bContext *UNUSED(C), wmOperator *op)
{
- MEM_freeN(op->customdata);
- op->customdata = NULL;
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
}
static int cachefile_open_exec(bContext *C, wmOperator *op)
{
- if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
- BKE_report(op->reports, RPT_ERROR, "No filename given");
- return OPERATOR_CANCELLED;
- }
-
- char filename[FILE_MAX];
- RNA_string_get(op->ptr, "filepath", filename);
-
- Main *bmain = CTX_data_main(C);
-
- CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, BLI_path_basename(filename), 0);
- BLI_strncpy(cache_file->filepath, filename, FILE_MAX);
- BKE_cachefile_reload(bmain, cache_file);
-
- /* Will be set when running invoke, not exec directly. */
- if (op->customdata != NULL) {
- /* hook into UI */
- PropertyPointerRNA *pprop = op->customdata;
- if (pprop->prop) {
- /* When creating new ID blocks, use is already 1, but RNA
- * pointer see also increases user, so this compensates it. */
- id_us_min(&cache_file->id);
-
- PointerRNA idptr;
- RNA_id_pointer_create(&cache_file->id, &idptr);
- RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
- RNA_property_update(C, &pprop->ptr, pprop->prop);
- }
-
- MEM_freeN(op->customdata);
- }
-
- return OPERATOR_FINISHED;
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ BKE_report(op->reports, RPT_ERROR, "No filename given");
+ return OPERATOR_CANCELLED;
+ }
+
+ char filename[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filename);
+
+ Main *bmain = CTX_data_main(C);
+
+ CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, BLI_path_basename(filename), 0);
+ BLI_strncpy(cache_file->filepath, filename, FILE_MAX);
+ BKE_cachefile_reload(bmain, cache_file);
+
+ /* Will be set when running invoke, not exec directly. */
+ if (op->customdata != NULL) {
+ /* hook into UI */
+ PropertyPointerRNA *pprop = op->customdata;
+ if (pprop->prop) {
+ /* When creating new ID blocks, use is already 1, but RNA
+ * pointer see also increases user, so this compensates it. */
+ id_us_min(&cache_file->id);
+
+ PointerRNA idptr;
+ RNA_id_pointer_create(&cache_file->id, &idptr);
+ RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
+ RNA_property_update(C, &pprop->ptr, pprop->prop);
+ }
+
+ MEM_freeN(op->customdata);
+ }
+
+ return OPERATOR_FINISHED;
}
void CACHEFILE_OT_open(wmOperatorType *ot)
{
- ot->name = "Open Cache File";
- ot->description = "Load a cache file";
- ot->idname = "CACHEFILE_OT_open";
-
- ot->invoke = cachefile_open_invoke;
- ot->exec = cachefile_open_exec;
- ot->cancel = open_cancel;
-
- WM_operator_properties_filesel(ot, FILE_TYPE_ALEMBIC | FILE_TYPE_FOLDER,
- FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH,
- FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+ ot->name = "Open Cache File";
+ ot->description = "Load a cache file";
+ ot->idname = "CACHEFILE_OT_open";
+
+ ot->invoke = cachefile_open_invoke;
+ ot->exec = cachefile_open_exec;
+ ot->cancel = open_cancel;
+
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_ALEMBIC | FILE_TYPE_FOLDER,
+ FILE_BLENDER,
+ FILE_SAVE,
+ WM_FILESEL_FILEPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
}
/* ***************************** Reload Operator **************************** */
static int cachefile_reload_exec(bContext *C, wmOperator *op)
{
- CacheFile *cache_file = CTX_data_edit_cachefile(C);
+ CacheFile *cache_file = CTX_data_edit_cachefile(C);
- if (!cache_file) {
- return OPERATOR_CANCELLED;
- }
+ if (!cache_file) {
+ return OPERATOR_CANCELLED;
+ }
- Main *bmain = CTX_data_main(C);
+ Main *bmain = CTX_data_main(C);
- BLI_freelistN(&cache_file->object_paths);
- BKE_cachefile_reload(bmain, cache_file);
+ BLI_freelistN(&cache_file->object_paths);
+ BKE_cachefile_reload(bmain, cache_file);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
- UNUSED_VARS(op);
+ UNUSED_VARS(op);
}
void CACHEFILE_OT_reload(wmOperatorType *ot)
{
- ot->name = "Refresh Archive";
- ot->description = "Update objects paths list with new data from the archive";
- ot->idname = "CACHEFILE_OT_reload";
+ ot->name = "Refresh Archive";
+ ot->description = "Update objects paths list with new data from the archive";
+ ot->idname = "CACHEFILE_OT_reload";
- /* api callbacks */
- ot->exec = cachefile_reload_exec;
+ /* api callbacks */
+ ot->exec = cachefile_reload_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index 3829821ef2e..6ccdf8628a8 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -21,673 +21,781 @@
* \ingroup collada
*/
#ifdef WITH_COLLADA
-#include "DNA_space_types.h"
+# include "DNA_space_types.h"
-#include "BLT_translation.h"
+# include "BLT_translation.h"
-#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
+# include "BLI_blenlib.h"
+# include "BLI_utildefines.h"
-#include "BKE_context.h"
-#include "BKE_global.h"
-#include "BKE_main.h"
-#include "BKE_object.h"
-#include "BKE_report.h"
+# include "BKE_context.h"
+# include "BKE_global.h"
+# include "BKE_main.h"
+# include "BKE_object.h"
+# include "BKE_report.h"
-#include "DEG_depsgraph.h"
+# include "DEG_depsgraph.h"
-#include "ED_screen.h"
-#include "ED_object.h"
+# include "ED_screen.h"
+# include "ED_object.h"
-#include "RNA_access.h"
-#include "RNA_define.h"
+# include "RNA_access.h"
+# include "RNA_define.h"
-#include "UI_interface.h"
-#include "UI_resources.h"
+# include "UI_interface.h"
+# include "UI_resources.h"
-#include "WM_api.h"
-#include "WM_types.h"
+# include "WM_api.h"
+# include "WM_types.h"
-#include "../../collada/collada.h"
+# include "../../collada/collada.h"
-#include "io_collada.h"
+# include "io_collada.h"
static int wm_collada_export_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Main *bmain = CTX_data_main(C);
+ Main *bmain = CTX_data_main(C);
- if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
- char filepath[FILE_MAX];
- const char *blendfile_path = BKE_main_blendfile_path(bmain);
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ char filepath[FILE_MAX];
+ const char *blendfile_path = BKE_main_blendfile_path(bmain);
- if (blendfile_path[0] == '\0')
- BLI_strncpy(filepath, "untitled", sizeof(filepath));
- else
- BLI_strncpy(filepath, blendfile_path, sizeof(filepath));
+ if (blendfile_path[0] == '\0')
+ BLI_strncpy(filepath, "untitled", sizeof(filepath));
+ else
+ BLI_strncpy(filepath, blendfile_path, sizeof(filepath));
- BLI_path_extension_replace(filepath, sizeof(filepath), ".dae");
- RNA_string_set(op->ptr, "filepath", filepath);
- }
+ BLI_path_extension_replace(filepath, sizeof(filepath), ".dae");
+ RNA_string_set(op->ptr, "filepath", filepath);
+ }
- WM_event_add_fileselect(C, op);
+ WM_event_add_fileselect(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
/* function used for WM_OT_save_mainfile too */
static int wm_collada_export_exec(bContext *C, wmOperator *op)
{
- char filepath[FILE_MAX];
- int apply_modifiers;
- int export_mesh_type;
- int selected;
- int include_children;
- int include_armatures;
- int include_shapekeys;
- int deform_bones_only;
-
- int include_animations;
- int include_all_actions;
- int sampling_rate;
- int keep_smooth_curves;
- int keep_keyframes;
- int keep_flat_curves;
-
- int export_animation_type;
- int use_texture_copies;
- int active_uv_only;
-
- int triangulate;
- int use_object_instantiation;
- int use_blender_profile;
- int sort_by_name;
- int export_transformation_type;
-
- int open_sim;
- int limit_precision;
- int keep_bind_info;
-
- int export_count;
- int sample_animations;
-
- if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
- BKE_report(op->reports, RPT_ERROR, "No filename given");
- return OPERATOR_CANCELLED;
- }
-
- RNA_string_get(op->ptr, "filepath", filepath);
- BLI_path_extension_ensure(filepath, sizeof(filepath), ".dae");
-
-
- /* Avoid File write exceptions in Collada */
- if (!BLI_exists(filepath)) {
- BLI_make_existing_file(filepath);
- if (!BLI_file_touch(filepath)) {
- BKE_report(op->reports, RPT_ERROR, "Can't create export file");
- fprintf(stdout, "Collada export: Can not create: %s\n", filepath);
- return OPERATOR_CANCELLED;
- }
- }
- else if (!BLI_file_is_writable(filepath)) {
- BKE_report(op->reports, RPT_ERROR, "Can't overwrite export file");
- fprintf(stdout, "Collada export: Can not modify: %s\n", filepath);
- return OPERATOR_CANCELLED;
- }
-
- /* Now the exporter can create and write the export file */
-
- /* Options panel */
- apply_modifiers = RNA_boolean_get(op->ptr, "apply_modifiers");
- export_mesh_type = RNA_enum_get(op->ptr, "export_mesh_type_selection");
- selected = RNA_boolean_get(op->ptr, "selected");
- include_children = RNA_boolean_get(op->ptr, "include_children");
- include_armatures = RNA_boolean_get(op->ptr, "include_armatures");
- include_shapekeys = RNA_boolean_get(op->ptr, "include_shapekeys");
-
- include_animations = RNA_boolean_get(op->ptr, "include_animations");
- include_all_actions = RNA_boolean_get(op->ptr, "include_all_actions");
- export_animation_type = RNA_enum_get(op->ptr, "export_animation_type_selection");
- sample_animations = (export_animation_type == BC_ANIMATION_EXPORT_SAMPLES);
- sampling_rate = (sample_animations) ? RNA_int_get(op->ptr, "sampling_rate") : 0;
- keep_smooth_curves = RNA_boolean_get(op->ptr, "keep_smooth_curves");
- keep_keyframes = RNA_boolean_get(op->ptr, "keep_keyframes");
- keep_flat_curves = RNA_boolean_get(op->ptr, "keep_flat_curves");
-
- deform_bones_only = RNA_boolean_get(op->ptr, "deform_bones_only");
-
- use_texture_copies = RNA_boolean_get(op->ptr, "use_texture_copies");
- active_uv_only = RNA_boolean_get(op->ptr, "active_uv_only");
-
- triangulate = RNA_boolean_get(op->ptr, "triangulate");
- use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation");
- use_blender_profile = RNA_boolean_get(op->ptr, "use_blender_profile");
- sort_by_name = RNA_boolean_get(op->ptr, "sort_by_name");
- export_transformation_type = RNA_enum_get(op->ptr, "export_transformation_type_selection");
- open_sim = RNA_boolean_get(op->ptr, "open_sim");
-
- limit_precision = RNA_boolean_get(op->ptr, "limit_precision");
- keep_bind_info = RNA_boolean_get(op->ptr, "keep_bind_info");
-
- Main *bmain = CTX_data_main(C);
-
- /* get editmode results */
- ED_object_editmode_load(bmain, CTX_data_edit_object(C));
-
- //Scene *scene = CTX_data_scene(C);
-
- ExportSettings export_settings;
-
- export_settings.filepath = filepath;
-
- export_settings.apply_modifiers = apply_modifiers != 0;
- export_settings.export_mesh_type = export_mesh_type;
- export_settings.selected = selected != 0;
- export_settings.include_children = include_children != 0;
- export_settings.include_armatures = include_armatures != 0;
- export_settings.include_shapekeys = include_shapekeys != 0;
- export_settings.deform_bones_only = deform_bones_only != 0;
- export_settings.include_animations = include_animations != 0;
- export_settings.include_all_actions = include_all_actions != 0;
- export_settings.sampling_rate = sampling_rate;
- export_settings.keep_keyframes = keep_keyframes != 0 || sampling_rate < 1;
- export_settings.keep_flat_curves = keep_flat_curves != 0;
-
- export_settings.active_uv_only = active_uv_only != 0;
- export_settings.export_animation_type = export_animation_type;
- export_settings.use_texture_copies = use_texture_copies != 0;
-
- export_settings.triangulate = triangulate != 0;
- export_settings.use_object_instantiation = use_object_instantiation != 0;
- export_settings.use_blender_profile = use_blender_profile != 0;
- export_settings.sort_by_name = sort_by_name != 0;
-
- if (export_animation_type == BC_ANIMATION_EXPORT_SAMPLES) {
- export_settings.export_transformation_type = export_transformation_type;
- }
- else {
- // When curves are exported then we can not export as matrix
- export_settings.export_transformation_type = BC_TRANSFORMATION_TYPE_TRANSROTLOC;
- }
-
- if (export_settings.export_transformation_type == BC_TRANSFORMATION_TYPE_TRANSROTLOC) {
- export_settings.keep_smooth_curves = keep_smooth_curves != 0;
- }
- else {
- // Can not export smooth curves when Matrix export is enabled.
- export_settings.keep_smooth_curves = false;
- }
-
- export_settings.open_sim = open_sim != 0;
- export_settings.limit_precision = limit_precision != 0;
- export_settings.keep_bind_info = keep_bind_info != 0;
-
- int includeFilter = OB_REL_NONE;
- if (export_settings.include_armatures) includeFilter |= OB_REL_MOD_ARMATURE;
- if (export_settings.include_children) includeFilter |= OB_REL_CHILDREN_RECURSIVE;
-
- export_count = collada_export(
- C,
- &export_settings
- );
-
- if (export_count == 0) {
- BKE_report(op->reports, RPT_WARNING, "No objects selected -- Created empty export file");
- return OPERATOR_CANCELLED;
- }
- else if (export_count < 0) {
- BKE_report(op->reports, RPT_WARNING, "Error during export (see Console)");
- return OPERATOR_CANCELLED;
- }
- else {
- char buff[100];
- sprintf(buff, "Exported %d Objects", export_count);
- BKE_report(op->reports, RPT_INFO, buff);
- return OPERATOR_FINISHED;
- }
+ char filepath[FILE_MAX];
+ int apply_modifiers;
+ int export_mesh_type;
+ int selected;
+ int include_children;
+ int include_armatures;
+ int include_shapekeys;
+ int deform_bones_only;
+
+ int include_animations;
+ int include_all_actions;
+ int sampling_rate;
+ int keep_smooth_curves;
+ int keep_keyframes;
+ int keep_flat_curves;
+
+ int export_animation_type;
+ int use_texture_copies;
+ int active_uv_only;
+
+ int triangulate;
+ int use_object_instantiation;
+ int use_blender_profile;
+ int sort_by_name;
+ int export_transformation_type;
+
+ int open_sim;
+ int limit_precision;
+ int keep_bind_info;
+
+ int export_count;
+ int sample_animations;
+
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ BKE_report(op->reports, RPT_ERROR, "No filename given");
+ return OPERATOR_CANCELLED;
+ }
+
+ RNA_string_get(op->ptr, "filepath", filepath);
+ BLI_path_extension_ensure(filepath, sizeof(filepath), ".dae");
+
+ /* Avoid File write exceptions in Collada */
+ if (!BLI_exists(filepath)) {
+ BLI_make_existing_file(filepath);
+ if (!BLI_file_touch(filepath)) {
+ BKE_report(op->reports, RPT_ERROR, "Can't create export file");
+ fprintf(stdout, "Collada export: Can not create: %s\n", filepath);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else if (!BLI_file_is_writable(filepath)) {
+ BKE_report(op->reports, RPT_ERROR, "Can't overwrite export file");
+ fprintf(stdout, "Collada export: Can not modify: %s\n", filepath);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Now the exporter can create and write the export file */
+
+ /* Options panel */
+ apply_modifiers = RNA_boolean_get(op->ptr, "apply_modifiers");
+ export_mesh_type = RNA_enum_get(op->ptr, "export_mesh_type_selection");
+ selected = RNA_boolean_get(op->ptr, "selected");
+ include_children = RNA_boolean_get(op->ptr, "include_children");
+ include_armatures = RNA_boolean_get(op->ptr, "include_armatures");
+ include_shapekeys = RNA_boolean_get(op->ptr, "include_shapekeys");
+
+ include_animations = RNA_boolean_get(op->ptr, "include_animations");
+ include_all_actions = RNA_boolean_get(op->ptr, "include_all_actions");
+ export_animation_type = RNA_enum_get(op->ptr, "export_animation_type_selection");
+ sample_animations = (export_animation_type == BC_ANIMATION_EXPORT_SAMPLES);
+ sampling_rate = (sample_animations) ? RNA_int_get(op->ptr, "sampling_rate") : 0;
+ keep_smooth_curves = RNA_boolean_get(op->ptr, "keep_smooth_curves");
+ keep_keyframes = RNA_boolean_get(op->ptr, "keep_keyframes");
+ keep_flat_curves = RNA_boolean_get(op->ptr, "keep_flat_curves");
+
+ deform_bones_only = RNA_boolean_get(op->ptr, "deform_bones_only");
+
+ use_texture_copies = RNA_boolean_get(op->ptr, "use_texture_copies");
+ active_uv_only = RNA_boolean_get(op->ptr, "active_uv_only");
+
+ triangulate = RNA_boolean_get(op->ptr, "triangulate");
+ use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation");
+ use_blender_profile = RNA_boolean_get(op->ptr, "use_blender_profile");
+ sort_by_name = RNA_boolean_get(op->ptr, "sort_by_name");
+ export_transformation_type = RNA_enum_get(op->ptr, "export_transformation_type_selection");
+ open_sim = RNA_boolean_get(op->ptr, "open_sim");
+
+ limit_precision = RNA_boolean_get(op->ptr, "limit_precision");
+ keep_bind_info = RNA_boolean_get(op->ptr, "keep_bind_info");
+
+ Main *bmain = CTX_data_main(C);
+
+ /* get editmode results */
+ ED_object_editmode_load(bmain, CTX_data_edit_object(C));
+
+ //Scene *scene = CTX_data_scene(C);
+
+ ExportSettings export_settings;
+
+ export_settings.filepath = filepath;
+
+ export_settings.apply_modifiers = apply_modifiers != 0;
+ export_settings.export_mesh_type = export_mesh_type;
+ export_settings.selected = selected != 0;
+ export_settings.include_children = include_children != 0;
+ export_settings.include_armatures = include_armatures != 0;
+ export_settings.include_shapekeys = include_shapekeys != 0;
+ export_settings.deform_bones_only = deform_bones_only != 0;
+ export_settings.include_animations = include_animations != 0;
+ export_settings.include_all_actions = include_all_actions != 0;
+ export_settings.sampling_rate = sampling_rate;
+ export_settings.keep_keyframes = keep_keyframes != 0 || sampling_rate < 1;
+ export_settings.keep_flat_curves = keep_flat_curves != 0;
+
+ export_settings.active_uv_only = active_uv_only != 0;
+ export_settings.export_animation_type = export_animation_type;
+ export_settings.use_texture_copies = use_texture_copies != 0;
+
+ export_settings.triangulate = triangulate != 0;
+ export_settings.use_object_instantiation = use_object_instantiation != 0;
+ export_settings.use_blender_profile = use_blender_profile != 0;
+ export_settings.sort_by_name = sort_by_name != 0;
+
+ if (export_animation_type == BC_ANIMATION_EXPORT_SAMPLES) {
+ export_settings.export_transformation_type = export_transformation_type;
+ }
+ else {
+ // When curves are exported then we can not export as matrix
+ export_settings.export_transformation_type = BC_TRANSFORMATION_TYPE_TRANSROTLOC;
+ }
+
+ if (export_settings.export_transformation_type == BC_TRANSFORMATION_TYPE_TRANSROTLOC) {
+ export_settings.keep_smooth_curves = keep_smooth_curves != 0;
+ }
+ else {
+ // Can not export smooth curves when Matrix export is enabled.
+ export_settings.keep_smooth_curves = false;
+ }
+
+ export_settings.open_sim = open_sim != 0;
+ export_settings.limit_precision = limit_precision != 0;
+ export_settings.keep_bind_info = keep_bind_info != 0;
+
+ int includeFilter = OB_REL_NONE;
+ if (export_settings.include_armatures)
+ includeFilter |= OB_REL_MOD_ARMATURE;
+ if (export_settings.include_children)
+ includeFilter |= OB_REL_CHILDREN_RECURSIVE;
+
+ export_count = collada_export(C, &export_settings);
+
+ if (export_count == 0) {
+ BKE_report(op->reports, RPT_WARNING, "No objects selected -- Created empty export file");
+ return OPERATOR_CANCELLED;
+ }
+ else if (export_count < 0) {
+ BKE_report(op->reports, RPT_WARNING, "Error during export (see Console)");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ char buff[100];
+ sprintf(buff, "Exported %d Objects", export_count);
+ BKE_report(op->reports, RPT_INFO, buff);
+ return OPERATOR_FINISHED;
+ }
}
static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
{
- uiLayout *box, *row, *col, *split;
- bool include_animations = RNA_boolean_get(imfptr, "include_animations");
- int ui_section = RNA_enum_get(imfptr, "prop_bc_export_ui_section");
-
- BC_export_animation_type animation_type = RNA_enum_get(imfptr, "export_animation_type_selection");
- BC_export_transformation_type transformation_type = RNA_enum_get(imfptr, "export_transformation_type_selection");
-
- bool sampling = animation_type == BC_ANIMATION_EXPORT_SAMPLES;
-
- /* Export Options: */
- box = uiLayoutBox(layout);
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "prop_bc_export_ui_section", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
-
- if (ui_section == BC_UI_SECTION_MAIN) {
- /* =================== */
- /* Export Data options */
- /* =================== */
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "selected", 0, NULL, ICON_NONE);
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "include_children", 0, NULL, ICON_NONE);
- uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "include_armatures", 0, NULL, ICON_NONE);
- uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "include_shapekeys", 0, NULL, ICON_NONE);
- uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
-
- /* Texture options */
- box = uiLayoutBox(layout);
- row = uiLayoutRow(box, false);
- uiItemL(row, IFACE_("Texture Options:"), ICON_TEXTURE_DATA);
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "active_uv_only", 0, NULL, ICON_NONE);
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "use_texture_copies", 1, NULL, ICON_NONE);
-
- }
- else if (ui_section == BC_UI_SECTION_GEOMETRY) {
- row = uiLayoutRow(box, false);
- uiItemL(row, IFACE_("Export Data Options:"), ICON_MESH_DATA);
-
- row = uiLayoutRow(box, false);
- split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
- col = uiLayoutColumn(split, false);
- uiItemR(col, imfptr, "apply_modifiers", 0, NULL, ICON_NONE);
- col = uiLayoutColumn(split, false);
- uiItemR(col, imfptr, "export_mesh_type_selection", 0, "", ICON_NONE);
- uiLayoutSetEnabled(col, RNA_boolean_get(imfptr, "apply_modifiers"));
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "triangulate", 1, NULL, ICON_NONE);
- }
- else if (ui_section == BC_UI_SECTION_ARMATURE) {
- /* Armature options */
- box = uiLayoutBox(layout);
- row = uiLayoutRow(box, false);
- uiItemL(row, IFACE_("Armature Options:"), ICON_ARMATURE_DATA);
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "deform_bones_only", 0, NULL, ICON_NONE);
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "open_sim", 0, NULL, ICON_NONE);
- }
- else if (ui_section == BC_UI_SECTION_ANIMATION) {
-
- /* ====================== */
- /* Animation Data options */
- /* ====================== */
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "include_animations", 0, NULL, ICON_NONE);
-
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "export_animation_type_selection", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
-
- row = uiLayoutRow(box, false);
- split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
- uiItemL(split, IFACE_("Transformation Type"), ICON_NONE);
- uiItemR(split, imfptr, "export_transformation_type_selection", 0, "", ICON_NONE);
- uiLayoutSetEnabled(row, animation_type == BC_ANIMATION_EXPORT_SAMPLES);
-
- row = uiLayoutColumn(box, false);
- uiItemR(row, imfptr, "keep_smooth_curves", 0, NULL, ICON_NONE);
- uiLayoutSetEnabled(row, include_animations &&
- (transformation_type == BC_TRANSFORMATION_TYPE_TRANSROTLOC || animation_type == BC_ANIMATION_EXPORT_KEYS));
-
- row = uiLayoutColumn(box, false);
- uiItemR(row, imfptr, "sampling_rate", 0, NULL, ICON_NONE);
- uiLayoutSetEnabled(row, sampling && include_animations);
-
- row = uiLayoutColumn(box, false);
- uiItemR(row, imfptr, "keep_keyframes", 0, NULL, ICON_NONE);
- uiLayoutSetEnabled(row, sampling && include_animations);
-
- row = uiLayoutColumn(box, false);
- uiItemR(row, imfptr, "keep_flat_curves", 0, NULL, ICON_NONE);
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "include_all_actions", 0, NULL, ICON_NONE);
- uiLayoutSetEnabled(row, include_animations);
-
- }
- else if (ui_section == BC_UI_SECTION_COLLADA) {
- /* Collada options: */
- box = uiLayoutBox(layout);
- row = uiLayoutRow(box, false);
- uiItemL(row, IFACE_("Collada Options:"), ICON_MODIFIER);
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "use_object_instantiation", 1, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "use_blender_profile", 1, NULL, ICON_NONE);
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "sort_by_name", 0, NULL, ICON_NONE);
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "keep_bind_info", 0, NULL, ICON_NONE);
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "limit_precision", 0, NULL, ICON_NONE);
- }
+ uiLayout *box, *row, *col, *split;
+ bool include_animations = RNA_boolean_get(imfptr, "include_animations");
+ int ui_section = RNA_enum_get(imfptr, "prop_bc_export_ui_section");
+
+ BC_export_animation_type animation_type = RNA_enum_get(imfptr,
+ "export_animation_type_selection");
+ BC_export_transformation_type transformation_type = RNA_enum_get(
+ imfptr, "export_transformation_type_selection");
+
+ bool sampling = animation_type == BC_ANIMATION_EXPORT_SAMPLES;
+
+ /* Export Options: */
+ box = uiLayoutBox(layout);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "prop_bc_export_ui_section", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+
+ if (ui_section == BC_UI_SECTION_MAIN) {
+ /* =================== */
+ /* Export Data options */
+ /* =================== */
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "selected", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "include_children", 0, NULL, ICON_NONE);
+ uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "include_armatures", 0, NULL, ICON_NONE);
+ uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "include_shapekeys", 0, NULL, ICON_NONE);
+ uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
+
+ /* Texture options */
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Texture Options:"), ICON_TEXTURE_DATA);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "active_uv_only", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "use_texture_copies", 1, NULL, ICON_NONE);
+ }
+ else if (ui_section == BC_UI_SECTION_GEOMETRY) {
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Export Data Options:"), ICON_MESH_DATA);
+
+ row = uiLayoutRow(box, false);
+ split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
+ col = uiLayoutColumn(split, false);
+ uiItemR(col, imfptr, "apply_modifiers", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(split, false);
+ uiItemR(col, imfptr, "export_mesh_type_selection", 0, "", ICON_NONE);
+ uiLayoutSetEnabled(col, RNA_boolean_get(imfptr, "apply_modifiers"));
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "triangulate", 1, NULL, ICON_NONE);
+ }
+ else if (ui_section == BC_UI_SECTION_ARMATURE) {
+ /* Armature options */
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Armature Options:"), ICON_ARMATURE_DATA);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "deform_bones_only", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "open_sim", 0, NULL, ICON_NONE);
+ }
+ else if (ui_section == BC_UI_SECTION_ANIMATION) {
+
+ /* ====================== */
+ /* Animation Data options */
+ /* ====================== */
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "include_animations", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "export_animation_type_selection", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
+ uiItemL(split, IFACE_("Transformation Type"), ICON_NONE);
+ uiItemR(split, imfptr, "export_transformation_type_selection", 0, "", ICON_NONE);
+ uiLayoutSetEnabled(row, animation_type == BC_ANIMATION_EXPORT_SAMPLES);
+
+ row = uiLayoutColumn(box, false);
+ uiItemR(row, imfptr, "keep_smooth_curves", 0, NULL, ICON_NONE);
+ uiLayoutSetEnabled(row,
+ include_animations &&
+ (transformation_type == BC_TRANSFORMATION_TYPE_TRANSROTLOC ||
+ animation_type == BC_ANIMATION_EXPORT_KEYS));
+
+ row = uiLayoutColumn(box, false);
+ uiItemR(row, imfptr, "sampling_rate", 0, NULL, ICON_NONE);
+ uiLayoutSetEnabled(row, sampling && include_animations);
+
+ row = uiLayoutColumn(box, false);
+ uiItemR(row, imfptr, "keep_keyframes", 0, NULL, ICON_NONE);
+ uiLayoutSetEnabled(row, sampling && include_animations);
+
+ row = uiLayoutColumn(box, false);
+ uiItemR(row, imfptr, "keep_flat_curves", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "include_all_actions", 0, NULL, ICON_NONE);
+ uiLayoutSetEnabled(row, include_animations);
+ }
+ else if (ui_section == BC_UI_SECTION_COLLADA) {
+ /* Collada options: */
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Collada Options:"), ICON_MODIFIER);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "use_object_instantiation", 1, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "use_blender_profile", 1, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "sort_by_name", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "keep_bind_info", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "limit_precision", 0, NULL, ICON_NONE);
+ }
}
static void wm_collada_export_draw(bContext *UNUSED(C), wmOperator *op)
{
- PointerRNA ptr;
+ PointerRNA ptr;
- RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
- uiCollada_exportSettings(op->layout, &ptr);
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+ uiCollada_exportSettings(op->layout, &ptr);
}
static bool wm_collada_export_check(bContext *UNUSED(C), wmOperator *op)
{
- char filepath[FILE_MAX];
- RNA_string_get(op->ptr, "filepath", filepath);
+ char filepath[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filepath);
- if (!BLI_path_extension_check(filepath, ".dae")) {
- BLI_path_extension_ensure(filepath, FILE_MAX, ".dae");
- RNA_string_set(op->ptr, "filepath", filepath);
- return true;
- }
+ if (!BLI_path_extension_check(filepath, ".dae")) {
+ BLI_path_extension_ensure(filepath, FILE_MAX, ".dae");
+ RNA_string_set(op->ptr, "filepath", filepath);
+ return true;
+ }
- return false;
+ return false;
}
void WM_OT_collada_export(wmOperatorType *ot)
{
- struct StructRNA *func = ot->srna;
-
- static const EnumPropertyItem prop_bc_export_mesh_type[] = {
- {BC_MESH_TYPE_VIEW, "view", 0, "View", "Apply modifier's view settings"},
- {BC_MESH_TYPE_RENDER, "render", 0, "Render", "Apply modifier's render settings"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem prop_bc_export_transformation_type[] = {
- { BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations" },
- { BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations" },
- { 0, NULL, 0, NULL, NULL }
- };
-
- static const EnumPropertyItem prop_bc_export_animation_type[] = {
- { BC_ANIMATION_EXPORT_SAMPLES, "sample", 0, "Samples", "Export Sampled points guided by sampling rate" },
- { BC_ANIMATION_EXPORT_KEYS, "keys", 0, "Curves", "Export Curves (note: guided by curve keys)" },
- { 0, NULL, 0, NULL, NULL }
- };
-
- static const EnumPropertyItem prop_bc_export_ui_section[] = {
- { BC_UI_SECTION_MAIN, "main", 0, "Main", "Data Export Section" },
- { BC_UI_SECTION_GEOMETRY, "geometry", 0, "Geom", "Geometry Export Section" },
- { BC_UI_SECTION_ARMATURE, "armature", 0, "Arm", "Armature Export Section" },
- { BC_UI_SECTION_ANIMATION, "animation", 0, "Anim", "Animation Export Section" },
- { BC_UI_SECTION_COLLADA, "collada", 0, "Extra", "Collada Export Section" },
- { 0, NULL, 0, NULL, NULL }
- };
-
-
- ot->name = "Export COLLADA";
- ot->description = "Save a Collada file";
- ot->idname = "WM_OT_collada_export";
-
- ot->invoke = wm_collada_export_invoke;
- ot->exec = wm_collada_export_exec;
- ot->poll = WM_operator_winactive;
- ot->check = wm_collada_export_check;
-
- ot->flag |= OPTYPE_PRESET;
-
- ot->ui = wm_collada_export_draw;
-
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_COLLADA, FILE_BLENDER, FILE_SAVE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
-
- RNA_def_enum(func, "prop_bc_export_ui_section", prop_bc_export_ui_section, 0,
- "Export Section", "Only for User Interface organization");
-
- RNA_def_boolean(func, "apply_modifiers", 0, "Apply Modifiers",
- "Apply modifiers to exported mesh (non destructive))");
-
- RNA_def_int(func, "export_mesh_type", 0, INT_MIN, INT_MAX,
- "Resolution", "Modifier resolution for export", INT_MIN, INT_MAX);
-
- RNA_def_enum(func, "export_mesh_type_selection", prop_bc_export_mesh_type, 0,
- "Resolution", "Modifier resolution for export");
-
- RNA_def_boolean(func, "selected", false, "Selection Only",
- "Export only selected elements");
-
- RNA_def_boolean(func, "include_children", false, "Include Children",
- "Export all children of selected objects (even if not selected)");
-
- RNA_def_boolean(func, "include_armatures", false, "Include Armatures",
- "Export related armatures (even if not selected)");
-
- RNA_def_boolean(func, "include_shapekeys", false, "Include Shape Keys",
- "Export all Shape Keys from Mesh Objects");
-
- RNA_def_boolean(func, "deform_bones_only", false, "Deform Bones only",
- "Only export deforming bones with armatures");
-
-
-
- RNA_def_boolean(func, "include_animations", true, "Include Animations",
- "Export animations if available (exporting animations will enforce the decomposition of "
- "node transforms into <translation> <rotation> and <scale> components)");
-
- RNA_def_boolean(func, "include_all_actions", true, "Include all Actions",
- "Export also unassigned actions (this allows you to export entire animation libraries for your character(s))");
-
- RNA_def_enum(func, "export_animation_type_selection", prop_bc_export_animation_type, 0, "Key Type",
- "Type for exported animations (use sample keys or Curve keys)");
-
- RNA_def_int(func, "sampling_rate", 1, 1, INT_MAX, "Sampling Rate",
- "The distance between 2 keyframes (1 to key every frame)", 1, INT_MAX);
-
- RNA_def_boolean(func, "keep_smooth_curves", 0, "Keep Smooth curves",
- "Export also the curve handles (if available) (this does only work when the inverse parent matrix "
- "is the unity matrix, otherwise you may end up with odd results)");
-
- RNA_def_boolean(
- func, "keep_keyframes", 0, "Keep Keyframes",
- "Use existing keyframes as additional sample points (this helps when you want to keep manual tweaks)");
-
- RNA_def_boolean(
- func, "keep_flat_curves", 0, "All keyed curves",
- "Export also curves which have only one key or are totally flat");
-
- RNA_def_boolean(func, "active_uv_only", 0, "Only Selected UV Map",
- "Export only the selected UV Map");
-
- RNA_def_boolean(func, "use_texture_copies", 1, "Copy",
- "Copy textures to same folder where the .dae file is exported");
-
-
- RNA_def_boolean(func, "triangulate", 1, "Triangulate",
- "Export Polygons (Quads & NGons) as Triangles");
-
- RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instances",
- "Instantiate multiple Objects from same Data");
-
- RNA_def_boolean(func, "use_blender_profile", 1, "Use Blender Profile",
- "Export additional Blender specific information (for material, shaders, bones, etc.)");
-
- RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name",
- "Sort exported data by Object name");
-
- RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX, "Transform",
- "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
-
- RNA_def_enum(func, "export_transformation_type_selection", prop_bc_export_transformation_type, 0, "Transform",
- "Transformation type for translation, scale and rotation");
-
- RNA_def_boolean(func, "open_sim", 0, "Export to SL/OpenSim",
- "Compatibility mode for SL, OpenSim and other compatible online worlds");
-
- RNA_def_boolean(func, "limit_precision", 0, "Limit Precision",
- "Reduce the precision of the exported data to 6 digits");
-
- RNA_def_boolean(func, "keep_bind_info", 0, "Keep Bind Info",
- "Store Bindpose information in custom bone properties for later use during Collada export");
+ struct StructRNA *func = ot->srna;
+
+ static const EnumPropertyItem prop_bc_export_mesh_type[] = {
+ {BC_MESH_TYPE_VIEW, "view", 0, "View", "Apply modifier's view settings"},
+ {BC_MESH_TYPE_RENDER, "render", 0, "Render", "Apply modifier's render settings"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem prop_bc_export_transformation_type[] = {
+ {BC_TRANSFORMATION_TYPE_MATRIX,
+ "matrix",
+ 0,
+ "Matrix",
+ "Use <matrix> to specify transformations"},
+ {BC_TRANSFORMATION_TYPE_TRANSROTLOC,
+ "transrotloc",
+ 0,
+ "TransRotLoc",
+ "Use <translate>, <rotate>, <scale> to specify transformations"},
+ {0, NULL, 0, NULL, NULL}};
+
+ static const EnumPropertyItem prop_bc_export_animation_type[] = {
+ {BC_ANIMATION_EXPORT_SAMPLES,
+ "sample",
+ 0,
+ "Samples",
+ "Export Sampled points guided by sampling rate"},
+ {BC_ANIMATION_EXPORT_KEYS,
+ "keys",
+ 0,
+ "Curves",
+ "Export Curves (note: guided by curve keys)"},
+ {0, NULL, 0, NULL, NULL}};
+
+ static const EnumPropertyItem prop_bc_export_ui_section[] = {
+ {BC_UI_SECTION_MAIN, "main", 0, "Main", "Data Export Section"},
+ {BC_UI_SECTION_GEOMETRY, "geometry", 0, "Geom", "Geometry Export Section"},
+ {BC_UI_SECTION_ARMATURE, "armature", 0, "Arm", "Armature Export Section"},
+ {BC_UI_SECTION_ANIMATION, "animation", 0, "Anim", "Animation Export Section"},
+ {BC_UI_SECTION_COLLADA, "collada", 0, "Extra", "Collada Export Section"},
+ {0, NULL, 0, NULL, NULL}};
+
+ ot->name = "Export COLLADA";
+ ot->description = "Save a Collada file";
+ ot->idname = "WM_OT_collada_export";
+
+ ot->invoke = wm_collada_export_invoke;
+ ot->exec = wm_collada_export_exec;
+ ot->poll = WM_operator_winactive;
+ ot->check = wm_collada_export_check;
+
+ ot->flag |= OPTYPE_PRESET;
+
+ ot->ui = wm_collada_export_draw;
+
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_COLLADA,
+ FILE_BLENDER,
+ FILE_SAVE,
+ WM_FILESEL_FILEPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
+
+ RNA_def_enum(func,
+ "prop_bc_export_ui_section",
+ prop_bc_export_ui_section,
+ 0,
+ "Export Section",
+ "Only for User Interface organization");
+
+ RNA_def_boolean(func,
+ "apply_modifiers",
+ 0,
+ "Apply Modifiers",
+ "Apply modifiers to exported mesh (non destructive))");
+
+ RNA_def_int(func,
+ "export_mesh_type",
+ 0,
+ INT_MIN,
+ INT_MAX,
+ "Resolution",
+ "Modifier resolution for export",
+ INT_MIN,
+ INT_MAX);
+
+ RNA_def_enum(func,
+ "export_mesh_type_selection",
+ prop_bc_export_mesh_type,
+ 0,
+ "Resolution",
+ "Modifier resolution for export");
+
+ RNA_def_boolean(func, "selected", false, "Selection Only", "Export only selected elements");
+
+ RNA_def_boolean(func,
+ "include_children",
+ false,
+ "Include Children",
+ "Export all children of selected objects (even if not selected)");
+
+ RNA_def_boolean(func,
+ "include_armatures",
+ false,
+ "Include Armatures",
+ "Export related armatures (even if not selected)");
+
+ RNA_def_boolean(func,
+ "include_shapekeys",
+ false,
+ "Include Shape Keys",
+ "Export all Shape Keys from Mesh Objects");
+
+ RNA_def_boolean(func,
+ "deform_bones_only",
+ false,
+ "Deform Bones only",
+ "Only export deforming bones with armatures");
+
+ RNA_def_boolean(
+ func,
+ "include_animations",
+ true,
+ "Include Animations",
+ "Export animations if available (exporting animations will enforce the decomposition of "
+ "node transforms into <translation> <rotation> and <scale> components)");
+
+ RNA_def_boolean(func,
+ "include_all_actions",
+ true,
+ "Include all Actions",
+ "Export also unassigned actions (this allows you to export entire animation "
+ "libraries for your character(s))");
+
+ RNA_def_enum(func,
+ "export_animation_type_selection",
+ prop_bc_export_animation_type,
+ 0,
+ "Key Type",
+ "Type for exported animations (use sample keys or Curve keys)");
+
+ RNA_def_int(func,
+ "sampling_rate",
+ 1,
+ 1,
+ INT_MAX,
+ "Sampling Rate",
+ "The distance between 2 keyframes (1 to key every frame)",
+ 1,
+ INT_MAX);
+
+ RNA_def_boolean(func,
+ "keep_smooth_curves",
+ 0,
+ "Keep Smooth curves",
+ "Export also the curve handles (if available) (this does only work when the "
+ "inverse parent matrix "
+ "is the unity matrix, otherwise you may end up with odd results)");
+
+ RNA_def_boolean(func,
+ "keep_keyframes",
+ 0,
+ "Keep Keyframes",
+ "Use existing keyframes as additional sample points (this helps when you want "
+ "to keep manual tweaks)");
+
+ RNA_def_boolean(func,
+ "keep_flat_curves",
+ 0,
+ "All keyed curves",
+ "Export also curves which have only one key or are totally flat");
+
+ RNA_def_boolean(
+ func, "active_uv_only", 0, "Only Selected UV Map", "Export only the selected UV Map");
+
+ RNA_def_boolean(func,
+ "use_texture_copies",
+ 1,
+ "Copy",
+ "Copy textures to same folder where the .dae file is exported");
+
+ RNA_def_boolean(
+ func, "triangulate", 1, "Triangulate", "Export Polygons (Quads & NGons) as Triangles");
+
+ RNA_def_boolean(func,
+ "use_object_instantiation",
+ 1,
+ "Use Object Instances",
+ "Instantiate multiple Objects from same Data");
+
+ RNA_def_boolean(
+ func,
+ "use_blender_profile",
+ 1,
+ "Use Blender Profile",
+ "Export additional Blender specific information (for material, shaders, bones, etc.)");
+
+ RNA_def_boolean(
+ func, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name");
+
+ RNA_def_int(func,
+ "export_transformation_type",
+ 0,
+ INT_MIN,
+ INT_MAX,
+ "Transform",
+ "Transformation type for translation, scale and rotation",
+ INT_MIN,
+ INT_MAX);
+
+ RNA_def_enum(func,
+ "export_transformation_type_selection",
+ prop_bc_export_transformation_type,
+ 0,
+ "Transform",
+ "Transformation type for translation, scale and rotation");
+
+ RNA_def_boolean(func,
+ "open_sim",
+ 0,
+ "Export to SL/OpenSim",
+ "Compatibility mode for SL, OpenSim and other compatible online worlds");
+
+ RNA_def_boolean(func,
+ "limit_precision",
+ 0,
+ "Limit Precision",
+ "Reduce the precision of the exported data to 6 digits");
+
+ RNA_def_boolean(
+ func,
+ "keep_bind_info",
+ 0,
+ "Keep Bind Info",
+ "Store Bindpose information in custom bone properties for later use during Collada export");
}
-
/* function used for WM_OT_save_mainfile too */
static int wm_collada_import_exec(bContext *C, wmOperator *op)
{
- char filename[FILE_MAX];
- int import_units;
- int find_chains;
- int auto_connect;
- int fix_orientation;
- int min_chain_length;
-
- int keep_bind_info;
- ImportSettings import_settings;
-
- if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
- BKE_report(op->reports, RPT_ERROR, "No filename given");
- return OPERATOR_CANCELLED;
- }
-
- /* Options panel */
- import_units = RNA_boolean_get(op->ptr, "import_units");
- find_chains = RNA_boolean_get(op->ptr, "find_chains");
- auto_connect = RNA_boolean_get(op->ptr, "auto_connect");
- fix_orientation = RNA_boolean_get(op->ptr, "fix_orientation");
-
- keep_bind_info = RNA_boolean_get(op->ptr, "keep_bind_info");
-
- min_chain_length = RNA_int_get(op->ptr, "min_chain_length");
-
- RNA_string_get(op->ptr, "filepath", filename);
-
- import_settings.filepath = filename;
- import_settings.import_units = import_units != 0;
- import_settings.auto_connect = auto_connect != 0;
- import_settings.find_chains = find_chains != 0;
- import_settings.fix_orientation = fix_orientation != 0;
- import_settings.min_chain_length = min_chain_length;
- import_settings.keep_bind_info = keep_bind_info != 0;
-
- if (collada_import(C, &import_settings)) {
- DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_BASE_FLAGS);
- return OPERATOR_FINISHED;
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Parsing errors in Document (see Blender Console)");
- return OPERATOR_CANCELLED;
- }
+ char filename[FILE_MAX];
+ int import_units;
+ int find_chains;
+ int auto_connect;
+ int fix_orientation;
+ int min_chain_length;
+
+ int keep_bind_info;
+ ImportSettings import_settings;
+
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ BKE_report(op->reports, RPT_ERROR, "No filename given");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Options panel */
+ import_units = RNA_boolean_get(op->ptr, "import_units");
+ find_chains = RNA_boolean_get(op->ptr, "find_chains");
+ auto_connect = RNA_boolean_get(op->ptr, "auto_connect");
+ fix_orientation = RNA_boolean_get(op->ptr, "fix_orientation");
+
+ keep_bind_info = RNA_boolean_get(op->ptr, "keep_bind_info");
+
+ min_chain_length = RNA_int_get(op->ptr, "min_chain_length");
+
+ RNA_string_get(op->ptr, "filepath", filename);
+
+ import_settings.filepath = filename;
+ import_settings.import_units = import_units != 0;
+ import_settings.auto_connect = auto_connect != 0;
+ import_settings.find_chains = find_chains != 0;
+ import_settings.fix_orientation = fix_orientation != 0;
+ import_settings.min_chain_length = min_chain_length;
+ import_settings.keep_bind_info = keep_bind_info != 0;
+
+ if (collada_import(C, &import_settings)) {
+ DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_BASE_FLAGS);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Parsing errors in Document (see Blender Console)");
+ return OPERATOR_CANCELLED;
+ }
}
static void uiCollada_importSettings(uiLayout *layout, PointerRNA *imfptr)
{
- uiLayout *box, *row;
+ uiLayout *box, *row;
- /* Import Options: */
- box = uiLayoutBox(layout);
- row = uiLayoutRow(box, false);
- uiItemL(row, IFACE_("Import Data Options:"), ICON_MESH_DATA);
+ /* Import Options: */
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Import Data Options:"), ICON_MESH_DATA);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "import_units", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "import_units", 0, NULL, ICON_NONE);
- box = uiLayoutBox(layout);
- row = uiLayoutRow(box, false);
- uiItemL(row, IFACE_("Armature Options:"), ICON_MESH_DATA);
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Armature Options:"), ICON_MESH_DATA);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "fix_orientation", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "fix_orientation", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "find_chains", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "find_chains", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "auto_connect", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "auto_connect", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "min_chain_length", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "min_chain_length", 0, NULL, ICON_NONE);
- box = uiLayoutBox(layout);
- row = uiLayoutRow(box, false);
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "keep_bind_info", 0, NULL, ICON_NONE);
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "keep_bind_info", 0, NULL, ICON_NONE);
}
static void wm_collada_import_draw(bContext *UNUSED(C), wmOperator *op)
{
- PointerRNA ptr;
+ PointerRNA ptr;
- RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
- uiCollada_importSettings(op->layout, &ptr);
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+ uiCollada_importSettings(op->layout, &ptr);
}
void WM_OT_collada_import(wmOperatorType *ot)
{
- ot->name = "Import COLLADA";
- ot->description = "Load a Collada file";
- ot->idname = "WM_OT_collada_import";
-
- ot->invoke = WM_operator_filesel;
- ot->exec = wm_collada_import_exec;
- ot->poll = WM_operator_winactive;
-
- //ot->flag |= OPTYPE_PRESET;
-
- ot->ui = wm_collada_import_draw;
-
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_COLLADA, FILE_BLENDER, FILE_OPENFILE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
-
- RNA_def_boolean(
- ot->srna,
- "import_units", 0, "Import Units",
- "If disabled match import to Blender's current Unit settings, "
- "otherwise use the settings from the Imported scene");
-
- RNA_def_boolean(
- ot->srna,
- "fix_orientation", 0, "Fix Leaf Bones",
- "Fix Orientation of Leaf Bones (Collada does only support Joints)");
-
- RNA_def_boolean(
- ot->srna,
- "find_chains", 0, "Find Bone Chains",
- "Find best matching Bone Chains and ensure bones in chain are connected");
-
- RNA_def_boolean(
- ot->srna,
- "auto_connect", 0, "Auto Connect",
- "Set use_connect for parent bones which have exactly one child bone");
-
- RNA_def_int(
- ot->srna,
- "min_chain_length",
- 0,
- 0, INT_MAX,
- "Minimum Chain Length",
- "When searching Bone Chains disregard chains of length below this value",
- 0, INT_MAX);
-
- RNA_def_boolean(
- ot->srna,
- "keep_bind_info", 0, "Keep Bind Info",
- "Store Bindpose information in custom bone properties for later use during Collada export");
-
+ ot->name = "Import COLLADA";
+ ot->description = "Load a Collada file";
+ ot->idname = "WM_OT_collada_import";
+
+ ot->invoke = WM_operator_filesel;
+ ot->exec = wm_collada_import_exec;
+ ot->poll = WM_operator_winactive;
+
+ //ot->flag |= OPTYPE_PRESET;
+
+ ot->ui = wm_collada_import_draw;
+
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_COLLADA,
+ FILE_BLENDER,
+ FILE_OPENFILE,
+ WM_FILESEL_FILEPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
+
+ RNA_def_boolean(ot->srna,
+ "import_units",
+ 0,
+ "Import Units",
+ "If disabled match import to Blender's current Unit settings, "
+ "otherwise use the settings from the Imported scene");
+
+ RNA_def_boolean(ot->srna,
+ "fix_orientation",
+ 0,
+ "Fix Leaf Bones",
+ "Fix Orientation of Leaf Bones (Collada does only support Joints)");
+
+ RNA_def_boolean(ot->srna,
+ "find_chains",
+ 0,
+ "Find Bone Chains",
+ "Find best matching Bone Chains and ensure bones in chain are connected");
+
+ RNA_def_boolean(ot->srna,
+ "auto_connect",
+ 0,
+ "Auto Connect",
+ "Set use_connect for parent bones which have exactly one child bone");
+
+ RNA_def_int(ot->srna,
+ "min_chain_length",
+ 0,
+ 0,
+ INT_MAX,
+ "Minimum Chain Length",
+ "When searching Bone Chains disregard chains of length below this value",
+ 0,
+ INT_MAX);
+
+ RNA_def_boolean(
+ ot->srna,
+ "keep_bind_info",
+ 0,
+ "Keep Bind Info",
+ "Store Bindpose information in custom bone properties for later use during Collada export");
}
#endif
diff --git a/source/blender/editors/io/io_ops.c b/source/blender/editors/io/io_ops.c
index 93874031ea2..e04fe4a20c0 100644
--- a/source/blender/editors/io/io_ops.c
+++ b/source/blender/editors/io/io_ops.c
@@ -21,7 +21,7 @@
* \ingroup collada
*/
-#include "io_ops.h" /* own include */
+#include "io_ops.h" /* own include */
#include "WM_api.h"
@@ -38,15 +38,15 @@
void ED_operatortypes_io(void)
{
#ifdef WITH_COLLADA
- /* Collada operators: */
- WM_operatortype_append(WM_OT_collada_export);
- WM_operatortype_append(WM_OT_collada_import);
+ /* Collada operators: */
+ WM_operatortype_append(WM_OT_collada_export);
+ WM_operatortype_append(WM_OT_collada_import);
#endif
#ifdef WITH_ALEMBIC
- WM_operatortype_append(WM_OT_alembic_import);
- WM_operatortype_append(WM_OT_alembic_export);
+ WM_operatortype_append(WM_OT_alembic_import);
+ WM_operatortype_append(WM_OT_alembic_export);
#endif
- WM_operatortype_append(CACHEFILE_OT_open);
- WM_operatortype_append(CACHEFILE_OT_reload);
+ WM_operatortype_append(CACHEFILE_OT_open);
+ WM_operatortype_append(CACHEFILE_OT_reload);
}
diff --git a/source/blender/editors/lattice/CMakeLists.txt b/source/blender/editors/lattice/CMakeLists.txt
index 5a231837d0b..f9c08727128 100644
--- a/source/blender/editors/lattice/CMakeLists.txt
+++ b/source/blender/editors/lattice/CMakeLists.txt
@@ -16,16 +16,16 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../depsgraph
- ../../makesdna
- ../../makesrna
- ../../render/extern/include
- ../../windowmanager
- ../../../../intern/clog
- ../../../../intern/guardedalloc
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../depsgraph
+ ../../makesdna
+ ../../makesrna
+ ../../render/extern/include
+ ../../windowmanager
+ ../../../../intern/clog
+ ../../../../intern/guardedalloc
)
set(INC_SYS
@@ -33,12 +33,12 @@ set(INC_SYS
)
set(SRC
- editlattice_select.c
- editlattice_tools.c
- editlattice_undo.c
- lattice_ops.c
+ editlattice_select.c
+ editlattice_tools.c
+ editlattice_undo.c
+ lattice_ops.c
- lattice_intern.h
+ lattice_intern.h
)
set(LIB
diff --git a/source/blender/editors/lattice/editlattice_select.c b/source/blender/editors/lattice/editlattice_select.c
index a92ed02c483..782c0644313 100644
--- a/source/blender/editors/lattice/editlattice_select.c
+++ b/source/blender/editors/lattice/editlattice_select.c
@@ -65,37 +65,38 @@
static void bpoint_select_set(BPoint *bp, bool select)
{
- if (select) {
- if (!bp->hide) {
- bp->f1 |= SELECT;
- }
- }
- else {
- bp->f1 &= ~SELECT;
- }
+ if (select) {
+ if (!bp->hide) {
+ bp->f1 |= SELECT;
+ }
+ }
+ else {
+ bp->f1 &= ~SELECT;
+ }
}
bool ED_lattice_deselect_all_multi_ex(struct Base **bases, const uint bases_len)
{
- bool changed_multi = false;
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *ob_iter = base_iter->object;
- changed_multi |= ED_lattice_flags_set(ob_iter, 0);
- DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
- }
- return changed_multi;
+ bool changed_multi = false;
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ Object *ob_iter = base_iter->object;
+ changed_multi |= ED_lattice_flags_set(ob_iter, 0);
+ DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
+ }
+ return changed_multi;
}
bool ED_lattice_deselect_all_multi(struct bContext *C)
{
- ViewContext vc;
- ED_view3d_viewcontext_init(C, &vc);
- uint bases_len = 0;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &bases_len);
- bool changed_multi = ED_lattice_deselect_all_multi_ex(bases, bases_len);
- MEM_freeN(bases);
- return changed_multi;
+ ViewContext vc;
+ ED_view3d_viewcontext_init(C, &vc);
+ uint bases_len = 0;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
+ vc.view_layer, vc.v3d, &bases_len);
+ bool changed_multi = ED_lattice_deselect_all_multi_ex(bases, bases_len);
+ MEM_freeN(bases);
+ return changed_multi;
}
/** \} */
@@ -106,64 +107,64 @@ bool ED_lattice_deselect_all_multi(struct bContext *C)
static int lattice_select_random_exec(bContext *C, wmOperator *op)
{
- const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
- const int seed = WM_operator_properties_select_random_seed_increment_get(op);
- const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
-
- 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];
- Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
-
- RNG *rng = BLI_rng_new_srandom(seed);
-
- int tot;
- BPoint *bp;
-
- tot = lt->pntsu * lt->pntsv * lt->pntsw;
- bp = lt->def;
- while (tot--) {
- if (!bp->hide) {
- if (BLI_rng_get_float(rng) < randfac) {
- bpoint_select_set(bp, select);
- }
- }
- bp++;
- }
-
- if (select == false) {
- lt->actbp = LT_ACTBP_NONE;
- }
-
- BLI_rng_free(rng);
-
- 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;
+ const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
+ const int seed = WM_operator_properties_select_random_seed_increment_get(op);
+ const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
+
+ 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];
+ Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
+
+ RNG *rng = BLI_rng_new_srandom(seed);
+
+ int tot;
+ BPoint *bp;
+
+ tot = lt->pntsu * lt->pntsv * lt->pntsw;
+ bp = lt->def;
+ while (tot--) {
+ if (!bp->hide) {
+ if (BLI_rng_get_float(rng) < randfac) {
+ bpoint_select_set(bp, select);
+ }
+ }
+ bp++;
+ }
+
+ if (select == false) {
+ lt->actbp = LT_ACTBP_NONE;
+ }
+
+ BLI_rng_free(rng);
+
+ 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;
}
void LATTICE_OT_select_random(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Random";
- ot->description = "Randomly select UVW control points";
- ot->idname = "LATTICE_OT_select_random";
+ /* identifiers */
+ ot->name = "Select Random";
+ ot->description = "Randomly select UVW control points";
+ ot->idname = "LATTICE_OT_select_random";
- /* api callbacks */
- ot->exec = lattice_select_random_exec;
- ot->poll = ED_operator_editlattice;
+ /* api callbacks */
+ ot->exec = lattice_select_random_exec;
+ ot->poll = ED_operator_editlattice;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- WM_operator_properties_select_random(ot);
+ /* props */
+ WM_operator_properties_select_random(ot);
}
/** \} */
@@ -174,89 +175,89 @@ void LATTICE_OT_select_random(wmOperatorType *ot)
static void ed_lattice_select_mirrored(Lattice *lt, const int axis, const bool extend)
{
- const int tot = lt->pntsu * lt->pntsv * lt->pntsw;
- int i;
- BPoint *bp;
- BLI_bitmap *selpoints;
-
- bool flip_uvw[3] = {false};
- flip_uvw[axis] = true;
-
- /* we could flip this too */
- if (!extend) {
- lt->actbp = LT_ACTBP_NONE;
- }
-
- /* store "original" selection */
- selpoints = BLI_BITMAP_NEW(tot, __func__);
- BKE_lattice_bitmap_from_flag(lt, selpoints, SELECT, false, false);
-
- /* actual (de)selection */
- for (i = 0; i < tot; i++) {
- const int i_flip = BKE_lattice_index_flip(lt, i, flip_uvw[0], flip_uvw[1], flip_uvw[2]);
- bp = &lt->def[i];
- if (!bp->hide) {
- if (BLI_BITMAP_TEST(selpoints, i_flip)) {
- bp->f1 |= SELECT;
- }
- else {
- if (!extend) {
- bp->f1 &= ~SELECT;
- }
- }
- }
- }
-
-
- MEM_freeN(selpoints);
+ const int tot = lt->pntsu * lt->pntsv * lt->pntsw;
+ int i;
+ BPoint *bp;
+ BLI_bitmap *selpoints;
+
+ bool flip_uvw[3] = {false};
+ flip_uvw[axis] = true;
+
+ /* we could flip this too */
+ if (!extend) {
+ lt->actbp = LT_ACTBP_NONE;
+ }
+
+ /* store "original" selection */
+ selpoints = BLI_BITMAP_NEW(tot, __func__);
+ BKE_lattice_bitmap_from_flag(lt, selpoints, SELECT, false, false);
+
+ /* actual (de)selection */
+ for (i = 0; i < tot; i++) {
+ const int i_flip = BKE_lattice_index_flip(lt, i, flip_uvw[0], flip_uvw[1], flip_uvw[2]);
+ bp = &lt->def[i];
+ if (!bp->hide) {
+ if (BLI_BITMAP_TEST(selpoints, i_flip)) {
+ bp->f1 |= SELECT;
+ }
+ else {
+ if (!extend) {
+ bp->f1 &= ~SELECT;
+ }
+ }
+ }
+ }
+
+ MEM_freeN(selpoints);
}
static int lattice_select_mirror_exec(bContext *C, wmOperator *op)
{
- const int axis_flag = RNA_enum_get(op->ptr, "axis");
- const bool extend = RNA_boolean_get(op->ptr, "extend");
-
- 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];
- Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
-
- for (int axis = 0; axis < 3; axis++) {
- if ((1 << axis) & axis_flag) {
- ed_lattice_select_mirrored(lt, axis, extend);
- }
- }
-
- /* TODO, only notify changes */
- 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;
+ const int axis_flag = RNA_enum_get(op->ptr, "axis");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+
+ 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];
+ Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
+
+ for (int axis = 0; axis < 3; axis++) {
+ if ((1 << axis) & axis_flag) {
+ ed_lattice_select_mirrored(lt, axis, extend);
+ }
+ }
+
+ /* TODO, only notify changes */
+ 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;
}
void LATTICE_OT_select_mirror(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Mirror";
- ot->description = "Select mirrored lattice points";
- ot->idname = "LATTICE_OT_select_mirror";
+ /* identifiers */
+ ot->name = "Select Mirror";
+ ot->description = "Select mirrored lattice points";
+ ot->idname = "LATTICE_OT_select_mirror";
- /* api callbacks */
- ot->exec = lattice_select_mirror_exec;
- ot->poll = ED_operator_editlattice;
+ /* api callbacks */
+ ot->exec = lattice_select_mirror_exec;
+ ot->poll = ED_operator_editlattice;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_enum_flag(ot->srna, "axis", rna_enum_axis_flag_xyz_items, (1 << 0), "Axis", "");
+ /* props */
+ RNA_def_enum_flag(ot->srna, "axis", rna_enum_axis_flag_xyz_items, (1 << 0), "Axis", "");
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
/** \} */
@@ -265,112 +266,110 @@ void LATTICE_OT_select_mirror(wmOperatorType *ot)
/** \name Select More/Less Operator
* \{ */
-static bool lattice_test_bitmap_uvw(Lattice *lt, BLI_bitmap *selpoints, int u, int v, int w, const bool selected)
+static bool lattice_test_bitmap_uvw(
+ Lattice *lt, BLI_bitmap *selpoints, int u, int v, int w, const bool selected)
{
- if ((u < 0 || u >= lt->pntsu) ||
- (v < 0 || v >= lt->pntsv) ||
- (w < 0 || w >= lt->pntsw))
- {
- return false;
- }
- else {
- int i = BKE_lattice_index_from_uvw(lt, u, v, w);
- if (lt->def[i].hide == 0) {
- return (BLI_BITMAP_TEST(selpoints, i) != 0) == selected;
- }
- return false;
- }
+ if ((u < 0 || u >= lt->pntsu) || (v < 0 || v >= lt->pntsv) || (w < 0 || w >= lt->pntsw)) {
+ return false;
+ }
+ else {
+ int i = BKE_lattice_index_from_uvw(lt, u, v, w);
+ if (lt->def[i].hide == 0) {
+ return (BLI_BITMAP_TEST(selpoints, i) != 0) == selected;
+ }
+ return false;
+ }
}
static int lattice_select_more_less(bContext *C, const bool select)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len;
- bool changed = false;
-
- 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];
- Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
- BPoint *bp;
- const int tot = lt->pntsu * lt->pntsv * lt->pntsw;
- int u, v, w;
- BLI_bitmap *selpoints;
-
- lt->actbp = LT_ACTBP_NONE;
-
- selpoints = BLI_BITMAP_NEW(tot, __func__);
- BKE_lattice_bitmap_from_flag(lt, selpoints, SELECT, false, false);
-
- bp = lt->def;
- for (w = 0; w < lt->pntsw; w++) {
- for (v = 0; v < lt->pntsv; v++) {
- for (u = 0; u < lt->pntsu; u++) {
- if ((bp->hide == 0) && (((bp->f1 & SELECT) == 0) == select)) {
- if (lattice_test_bitmap_uvw(lt, selpoints, u + 1, v, w, select) ||
- lattice_test_bitmap_uvw(lt, selpoints, u - 1, v, w, select) ||
- lattice_test_bitmap_uvw(lt, selpoints, u, v + 1, w, select) ||
- lattice_test_bitmap_uvw(lt, selpoints, u, v - 1, w, select) ||
- lattice_test_bitmap_uvw(lt, selpoints, u, v, w + 1, select) ||
- lattice_test_bitmap_uvw(lt, selpoints, u, v, w - 1, select))
- {
- SET_FLAG_FROM_TEST(bp->f1, select, SELECT);
- }
- }
- bp++;
- }
- }
- }
-
- MEM_freeN(selpoints);
-
- changed = true;
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- MEM_freeN(objects);
-
- return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len;
+ bool changed = false;
+
+ 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];
+ Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
+ BPoint *bp;
+ const int tot = lt->pntsu * lt->pntsv * lt->pntsw;
+ int u, v, w;
+ BLI_bitmap *selpoints;
+
+ lt->actbp = LT_ACTBP_NONE;
+
+ selpoints = BLI_BITMAP_NEW(tot, __func__);
+ BKE_lattice_bitmap_from_flag(lt, selpoints, SELECT, false, false);
+
+ bp = lt->def;
+ for (w = 0; w < lt->pntsw; w++) {
+ for (v = 0; v < lt->pntsv; v++) {
+ for (u = 0; u < lt->pntsu; u++) {
+ if ((bp->hide == 0) && (((bp->f1 & SELECT) == 0) == select)) {
+ if (lattice_test_bitmap_uvw(lt, selpoints, u + 1, v, w, select) ||
+ lattice_test_bitmap_uvw(lt, selpoints, u - 1, v, w, select) ||
+ lattice_test_bitmap_uvw(lt, selpoints, u, v + 1, w, select) ||
+ lattice_test_bitmap_uvw(lt, selpoints, u, v - 1, w, select) ||
+ lattice_test_bitmap_uvw(lt, selpoints, u, v, w + 1, select) ||
+ lattice_test_bitmap_uvw(lt, selpoints, u, v, w - 1, select)) {
+ SET_FLAG_FROM_TEST(bp->f1, select, SELECT);
+ }
+ }
+ bp++;
+ }
+ }
+ }
+
+ MEM_freeN(selpoints);
+
+ changed = true;
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ MEM_freeN(objects);
+
+ return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static int lattice_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
- return lattice_select_more_less(C, true);
+ return lattice_select_more_less(C, true);
}
static int lattice_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
- return lattice_select_more_less(C, false);
+ return lattice_select_more_less(C, false);
}
void LATTICE_OT_select_more(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select More";
- ot->description = "Select vertex directly linked to already selected ones";
- ot->idname = "LATTICE_OT_select_more";
+ /* identifiers */
+ ot->name = "Select More";
+ ot->description = "Select vertex directly linked to already selected ones";
+ ot->idname = "LATTICE_OT_select_more";
- /* api callbacks */
- ot->exec = lattice_select_more_exec;
- ot->poll = ED_operator_editlattice;
+ /* api callbacks */
+ ot->exec = lattice_select_more_exec;
+ ot->poll = ED_operator_editlattice;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void LATTICE_OT_select_less(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Less";
- ot->description = "Deselect vertices at the boundary of each selection region";
- ot->idname = "LATTICE_OT_select_less";
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->description = "Deselect vertices at the boundary of each selection region";
+ ot->idname = "LATTICE_OT_select_less";
- /* api callbacks */
- ot->exec = lattice_select_less_exec;
- ot->poll = ED_operator_editlattice;
+ /* api callbacks */
+ ot->exec = lattice_select_less_exec;
+ ot->poll = ED_operator_editlattice;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -381,111 +380,112 @@ void LATTICE_OT_select_less(wmOperatorType *ot)
bool ED_lattice_flags_set(Object *obedit, int flag)
{
- Lattice *lt = obedit->data;
- BPoint *bp;
- int a;
- bool changed = false;
-
- bp = lt->editlatt->latt->def;
-
- a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
-
- if (lt->editlatt->latt->actbp != LT_ACTBP_NONE) {
- lt->editlatt->latt->actbp = LT_ACTBP_NONE;
- changed = true;
- }
-
- while (a--) {
- if (bp->hide == 0) {
- if (bp->f1 != flag) {
- bp->f1 = flag;
- changed = true;
- }
- }
- bp++;
- }
- return changed;
+ Lattice *lt = obedit->data;
+ BPoint *bp;
+ int a;
+ bool changed = false;
+
+ bp = lt->editlatt->latt->def;
+
+ a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
+
+ if (lt->editlatt->latt->actbp != LT_ACTBP_NONE) {
+ lt->editlatt->latt->actbp = LT_ACTBP_NONE;
+ changed = true;
+ }
+
+ while (a--) {
+ if (bp->hide == 0) {
+ if (bp->f1 != flag) {
+ bp->f1 = flag;
+ changed = true;
+ }
+ }
+ bp++;
+ }
+ return changed;
}
static int lattice_select_all_exec(bContext *C, wmOperator *op)
{
- 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(view_layer, CTX_wm_view3d(C), &objects_len);
-
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Lattice *lt = obedit->data;
- if (BKE_lattice_is_any_selected(lt->editlatt->latt)) {
- action = SEL_DESELECT;
- break;
- }
- }
- }
-
- bool changed_multi = false;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Lattice *lt;
- BPoint *bp;
- int a;
- bool changed = false;
-
- switch (action) {
- case SEL_SELECT:
- changed = ED_lattice_flags_set(obedit, 1);
- break;
- case SEL_DESELECT:
- changed = ED_lattice_flags_set(obedit, 0);
- break;
- case SEL_INVERT:
- lt = obedit->data;
- bp = lt->editlatt->latt->def;
- a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
- lt->editlatt->latt->actbp = LT_ACTBP_NONE;
-
- while (a--) {
- if (bp->hide == 0) {
- bp->f1 ^= SELECT;
- changed = true;
- }
- bp++;
- }
- break;
- }
- if (changed) {
- changed_multi = true;
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- }
- MEM_freeN(objects);
-
- if (changed_multi) {
- return OPERATOR_FINISHED;
- }
- return OPERATOR_CANCELLED;
+ 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(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Lattice *lt = obedit->data;
+ if (BKE_lattice_is_any_selected(lt->editlatt->latt)) {
+ action = SEL_DESELECT;
+ break;
+ }
+ }
+ }
+
+ bool changed_multi = false;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Lattice *lt;
+ BPoint *bp;
+ int a;
+ bool changed = false;
+
+ switch (action) {
+ case SEL_SELECT:
+ changed = ED_lattice_flags_set(obedit, 1);
+ break;
+ case SEL_DESELECT:
+ changed = ED_lattice_flags_set(obedit, 0);
+ break;
+ case SEL_INVERT:
+ lt = obedit->data;
+ bp = lt->editlatt->latt->def;
+ a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
+ lt->editlatt->latt->actbp = LT_ACTBP_NONE;
+
+ while (a--) {
+ if (bp->hide == 0) {
+ bp->f1 ^= SELECT;
+ changed = true;
+ }
+ bp++;
+ }
+ break;
+ }
+ if (changed) {
+ changed_multi = true;
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ }
+ MEM_freeN(objects);
+
+ if (changed_multi) {
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_CANCELLED;
}
void LATTICE_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All";
- ot->description = "Change selection of all UVW control points";
- ot->idname = "LATTICE_OT_select_all";
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->description = "Change selection of all UVW control points";
+ ot->idname = "LATTICE_OT_select_all";
- /* api callbacks */
- ot->exec = lattice_select_all_exec;
- ot->poll = ED_operator_editlattice;
+ /* api callbacks */
+ ot->exec = lattice_select_all_exec;
+ ot->poll = ED_operator_editlattice;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_select_all(ot);
+ WM_operator_properties_select_all(ot);
}
/** \} */
@@ -496,74 +496,74 @@ void LATTICE_OT_select_all(wmOperatorType *ot)
static int lattice_select_ungrouped_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len;
- const bool is_extend = RNA_boolean_get(op->ptr, "extend");
- bool changed = false;
-
- 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];
- Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
- MDeformVert *dv;
- BPoint *bp;
- int a, tot;
-
- if (BLI_listbase_is_empty(&obedit->defbase) || lt->dvert == NULL) {
- continue;
- }
-
- if (!is_extend) {
- ED_lattice_flags_set(obedit, 0);
- }
-
- dv = lt->dvert;
- tot = lt->pntsu * lt->pntsv * lt->pntsw;
-
- for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) {
- if (bp->hide == 0) {
- if (dv->dw == NULL) {
- bp->f1 |= SELECT;
- }
- }
- }
-
- changed = true;
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- MEM_freeN(objects);
-
- if (!changed) {
- BKE_report(op->reports,
- RPT_ERROR,
- objects_len > 1 ? "No weights/vertex groups on objects" :
- "No weights/vertex groups on object");
- return OPERATOR_CANCELLED;
- }
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len;
+ const bool is_extend = RNA_boolean_get(op->ptr, "extend");
+ bool changed = false;
+
+ 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];
+ Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
+ MDeformVert *dv;
+ BPoint *bp;
+ int a, tot;
+
+ if (BLI_listbase_is_empty(&obedit->defbase) || lt->dvert == NULL) {
+ continue;
+ }
+
+ if (!is_extend) {
+ ED_lattice_flags_set(obedit, 0);
+ }
+
+ dv = lt->dvert;
+ tot = lt->pntsu * lt->pntsv * lt->pntsw;
+
+ for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) {
+ if (bp->hide == 0) {
+ if (dv->dw == NULL) {
+ bp->f1 |= SELECT;
+ }
+ }
+ }
+
+ changed = true;
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ MEM_freeN(objects);
+
+ if (!changed) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ objects_len > 1 ? "No weights/vertex groups on objects" :
+ "No weights/vertex groups on object");
+ return OPERATOR_CANCELLED;
+ }
+ return OPERATOR_FINISHED;
}
void LATTICE_OT_select_ungrouped(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Ungrouped";
- ot->idname = "LATTICE_OT_select_ungrouped";
- ot->description = "Select vertices without a group";
+ /* identifiers */
+ ot->name = "Select Ungrouped";
+ ot->idname = "LATTICE_OT_select_ungrouped";
+ ot->description = "Select vertices without a group";
- /* api callbacks */
- ot->exec = lattice_select_ungrouped_exec;
- ot->poll = ED_operator_editlattice;
+ /* api callbacks */
+ ot->exec = lattice_select_ungrouped_exec;
+ ot->poll = ED_operator_editlattice;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Select Picking API
*
@@ -571,112 +571,127 @@ void LATTICE_OT_select_ungrouped(wmOperatorType *ot)
* Gets called via generic mouse select operator.
* \{ */
-
static void findnearestLattvert__doClosest(void *userData, BPoint *bp, const float screen_co[2])
{
- struct { BPoint *bp; float dist; int select; float mval_fl[2]; bool is_changed; } *data = userData;
- float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
-
- if ((bp->f1 & SELECT) && data->select)
- dist_test += 5.0f;
-
- if (dist_test < data->dist) {
- data->dist = dist_test;
- data->bp = bp;
- data->is_changed = true;
- }
+ struct {
+ BPoint *bp;
+ float dist;
+ int select;
+ float mval_fl[2];
+ bool is_changed;
+ } *data = userData;
+ float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
+
+ if ((bp->f1 & SELECT) && data->select)
+ dist_test += 5.0f;
+
+ if (dist_test < data->dist) {
+ data->dist = dist_test;
+ data->bp = bp;
+ data->is_changed = true;
+ }
}
static BPoint *findnearestLattvert(ViewContext *vc, int sel, 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; float dist; int select; float mval_fl[2]; bool is_changed; } data = {NULL};
-
- data.dist = ED_view3d_select_dist_px();
- 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(base->object, vc->rv3d);
- lattice_foreachScreenVert(vc, findnearestLattvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
-
- if (data.is_changed) {
- *r_base = base;
- }
- }
- MEM_freeN(bases);
- return data.bp;
+ /* (sel == 1): selected gets a disadvantage */
+ /* in nurb and bezt or bp the nearest is written */
+ /* return 0 1 2: handlepunt */
+ struct {
+ BPoint *bp;
+ float dist;
+ int select;
+ float mval_fl[2];
+ bool is_changed;
+ } data = {NULL};
+
+ data.dist = ED_view3d_select_dist_px();
+ 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(base->object, vc->rv3d);
+ lattice_foreachScreenVert(
+ vc, findnearestLattvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ if (data.is_changed) {
+ *r_base = base;
+ }
+ }
+ MEM_freeN(bases);
+ return data.bp;
}
-bool ED_lattice_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
+bool ED_lattice_select_pick(
+ bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
{
- ViewContext vc;
- BPoint *bp = NULL;
- Base *basact = NULL;
-
- ED_view3d_viewcontext_init(C, &vc);
- vc.mval[0] = mval[0];
- vc.mval[1] = mval[1];
-
- bp = findnearestLattvert(&vc, true, &basact);
- if (bp) {
- ED_view3d_viewcontext_init_object(&vc, basact->object);
- Lattice *lt = ((Lattice *)vc.obedit->data)->editlatt->latt;
-
- if (!extend && !deselect && !toggle) {
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- if (ED_lattice_flags_set(ob, 0)) {
- DEG_id_tag_update(ob->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
- }
- }
- MEM_freeN(objects);
- }
-
- if (extend) {
- bp->f1 |= SELECT;
- }
- else if (deselect) {
- bp->f1 &= ~SELECT;
- }
- else if (toggle) {
- bp->f1 ^= SELECT; /* swap */
- }
- else {
- ED_lattice_flags_set(vc.obedit, 0);
- bp->f1 |= SELECT;
- }
-
- if (bp->f1 & SELECT) {
- lt->actbp = bp - lt->def;
- }
- else {
- lt->actbp = LT_ACTBP_NONE;
- }
-
- if (vc.view_layer->basact != basact) {
- ED_object_base_activate(C, basact);
- }
-
- DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
-
- return true;
- }
-
- return false;
+ ViewContext vc;
+ BPoint *bp = NULL;
+ Base *basact = NULL;
+
+ ED_view3d_viewcontext_init(C, &vc);
+ vc.mval[0] = mval[0];
+ vc.mval[1] = mval[1];
+
+ bp = findnearestLattvert(&vc, true, &basact);
+ if (bp) {
+ ED_view3d_viewcontext_init_object(&vc, basact->object);
+ Lattice *lt = ((Lattice *)vc.obedit->data)->editlatt->latt;
+
+ if (!extend && !deselect && !toggle) {
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ vc.view_layer, vc.v3d, &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ if (ED_lattice_flags_set(ob, 0)) {
+ DEG_id_tag_update(ob->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
+ }
+ }
+ MEM_freeN(objects);
+ }
+
+ if (extend) {
+ bp->f1 |= SELECT;
+ }
+ else if (deselect) {
+ bp->f1 &= ~SELECT;
+ }
+ else if (toggle) {
+ bp->f1 ^= SELECT; /* swap */
+ }
+ else {
+ ED_lattice_flags_set(vc.obedit, 0);
+ bp->f1 |= SELECT;
+ }
+
+ if (bp->f1 & SELECT) {
+ lt->actbp = bp - lt->def;
+ }
+ else {
+ lt->actbp = LT_ACTBP_NONE;
+ }
+
+ if (vc.view_layer->basact != basact) {
+ ED_object_base_activate(C, basact);
+ }
+
+ DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
+
+ return true;
+ }
+
+ return false;
}
/** \} */
diff --git a/source/blender/editors/lattice/editlattice_tools.c b/source/blender/editors/lattice/editlattice_tools.c
index edb79797c2a..8ef383de552 100644
--- a/source/blender/editors/lattice/editlattice_tools.c
+++ b/source/blender/editors/lattice/editlattice_tools.c
@@ -21,7 +21,6 @@
* \ingroup edlattice
*/
-
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
@@ -56,67 +55,70 @@
static bool make_regular_poll(bContext *C)
{
- Object *ob;
+ Object *ob;
- if (ED_operator_editlattice(C)) return 1;
+ if (ED_operator_editlattice(C))
+ return 1;
- ob = CTX_data_active_object(C);
- return (ob && ob->type == OB_LATTICE);
+ ob = CTX_data_active_object(C);
+ return (ob && ob->type == OB_LATTICE);
}
static int make_regular_exec(bContext *C, wmOperator *UNUSED(op))
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- const bool is_editmode = CTX_data_edit_object(C) != NULL;
-
- if (is_editmode) {
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- Lattice *lt = ob->data;
-
- if (lt->editlatt->latt == NULL) {
- continue;
- }
-
- BKE_lattice_resize(lt->editlatt->latt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- }
- MEM_freeN(objects);
- }
- else {
- FOREACH_SELECTED_OBJECT_BEGIN(view_layer, v3d, ob) {
- if (ob->type != OB_LATTICE) {
- continue;
- }
-
- Lattice *lt = ob->data;
- BKE_lattice_resize(lt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- } FOREACH_SELECTED_OBJECT_END;
- }
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ const bool is_editmode = CTX_data_edit_object(C) != NULL;
+
+ if (is_editmode) {
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ Lattice *lt = ob->data;
+
+ if (lt->editlatt->latt == NULL) {
+ continue;
+ }
+
+ BKE_lattice_resize(lt->editlatt->latt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ }
+ MEM_freeN(objects);
+ }
+ else {
+ FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) {
+ if (ob->type != OB_LATTICE) {
+ continue;
+ }
+
+ Lattice *lt = ob->data;
+ BKE_lattice_resize(lt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ }
+ FOREACH_SELECTED_OBJECT_END;
+ }
+ return OPERATOR_FINISHED;
}
void LATTICE_OT_make_regular(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Regular";
- ot->description = "Set UVW control points a uniform distance apart";
- ot->idname = "LATTICE_OT_make_regular";
+ /* identifiers */
+ ot->name = "Make Regular";
+ ot->description = "Set UVW control points a uniform distance apart";
+ ot->idname = "LATTICE_OT_make_regular";
- /* api callbacks */
- ot->exec = make_regular_exec;
- ot->poll = make_regular_poll;
+ /* api callbacks */
+ ot->exec = make_regular_exec;
+ ot->poll = make_regular_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -127,9 +129,9 @@ void LATTICE_OT_make_regular(wmOperatorType *ot)
/* flipping options */
typedef enum eLattice_FlipAxes {
- LATTICE_FLIP_U = 0,
- LATTICE_FLIP_V = 1,
- LATTICE_FLIP_W = 2,
+ LATTICE_FLIP_U = 0,
+ LATTICE_FLIP_V = 1,
+ LATTICE_FLIP_W = 2,
} eLattice_FlipAxes;
/**
@@ -137,233 +139,238 @@ typedef enum eLattice_FlipAxes {
* Assumes that uvw <=> xyz (i.e. axis-aligned index-axes with coordinate-axes).
* - Helper for #lattice_flip_exec()
*/
-static void lattice_flip_point_value(Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
+static void lattice_flip_point_value(
+ Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
{
- BPoint *bp;
- float diff;
+ BPoint *bp;
+ float diff;
- /* just the point in the middle (unpaired) */
- bp = &lt->def[BKE_lattice_index_from_uvw(lt, u, v, w)];
+ /* just the point in the middle (unpaired) */
+ bp = &lt->def[BKE_lattice_index_from_uvw(lt, u, v, w)];
- /* flip over axis */
- diff = mid - bp->vec[axis];
- bp->vec[axis] = mid + diff;
+ /* flip over axis */
+ diff = mid - bp->vec[axis];
+ bp->vec[axis] = mid + diff;
}
/**
* Swap pairs of lattice points along a specified axis.
* - Helper for #lattice_flip_exec()
*/
-static void lattice_swap_point_pairs(Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
+static void lattice_swap_point_pairs(
+ Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
{
- BPoint *bpA, *bpB;
-
- int numU = lt->pntsu;
- int numV = lt->pntsv;
- int numW = lt->pntsw;
-
- int u0 = u, u1 = u;
- int v0 = v, v1 = v;
- int w0 = w, w1 = w;
-
- /* get pair index by just overriding the relevant pair-value
- * - "-1" else buffer overflow
- */
- switch (axis) {
- case LATTICE_FLIP_U:
- u1 = numU - u - 1;
- break;
- case LATTICE_FLIP_V:
- v1 = numV - v - 1;
- break;
- case LATTICE_FLIP_W:
- w1 = numW - w - 1;
- break;
- }
-
- /* get points to operate on */
- bpA = &lt->def[BKE_lattice_index_from_uvw(lt, u0, v0, w0)];
- bpB = &lt->def[BKE_lattice_index_from_uvw(lt, u1, v1, w1)];
-
- /* Swap all coordinates, so that flipped coordinates belong to
- * the indices on the correct side of the lattice.
- *
- * Coords: (-2 4) |0| (3 4) --> (3 4) |0| (-2 4)
- * Indices: (0,L) (1,R) --> (0,L) (1,R)
- */
- swap_v3_v3(bpA->vec, bpB->vec);
-
- /* However, we need to mirror the coordinate values on the axis we're dealing with,
- * otherwise we'd have effectively only rotated the points around. If we don't do this,
- * we'd just be reimplementing the naive mirroring algorithm, which causes unwanted deforms
- * such as flipped normals, etc.
- *
- * Coords: (3 4) |0| (-2 4) --\
- * \-> (-3 4) |0| (2 4)
- * Indices: (0,L) (1,R) --> (0,L) (1,R)
- */
- lattice_flip_point_value(lt, u0, v0, w0, mid, axis);
- lattice_flip_point_value(lt, u1, v1, w1, mid, axis);
+ BPoint *bpA, *bpB;
+
+ int numU = lt->pntsu;
+ int numV = lt->pntsv;
+ int numW = lt->pntsw;
+
+ int u0 = u, u1 = u;
+ int v0 = v, v1 = v;
+ int w0 = w, w1 = w;
+
+ /* get pair index by just overriding the relevant pair-value
+ * - "-1" else buffer overflow
+ */
+ switch (axis) {
+ case LATTICE_FLIP_U:
+ u1 = numU - u - 1;
+ break;
+ case LATTICE_FLIP_V:
+ v1 = numV - v - 1;
+ break;
+ case LATTICE_FLIP_W:
+ w1 = numW - w - 1;
+ break;
+ }
+
+ /* get points to operate on */
+ bpA = &lt->def[BKE_lattice_index_from_uvw(lt, u0, v0, w0)];
+ bpB = &lt->def[BKE_lattice_index_from_uvw(lt, u1, v1, w1)];
+
+ /* Swap all coordinates, so that flipped coordinates belong to
+ * the indices on the correct side of the lattice.
+ *
+ * Coords: (-2 4) |0| (3 4) --> (3 4) |0| (-2 4)
+ * Indices: (0,L) (1,R) --> (0,L) (1,R)
+ */
+ swap_v3_v3(bpA->vec, bpB->vec);
+
+ /* However, we need to mirror the coordinate values on the axis we're dealing with,
+ * otherwise we'd have effectively only rotated the points around. If we don't do this,
+ * we'd just be reimplementing the naive mirroring algorithm, which causes unwanted deforms
+ * such as flipped normals, etc.
+ *
+ * Coords: (3 4) |0| (-2 4) --\
+ * \-> (-3 4) |0| (2 4)
+ * Indices: (0,L) (1,R) --> (0,L) (1,R)
+ */
+ lattice_flip_point_value(lt, u0, v0, w0, mid, axis);
+ lattice_flip_point_value(lt, u1, v1, w1, mid, axis);
}
static int lattice_flip_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len;
- bool changed = false;
- const eLattice_FlipAxes axis = RNA_enum_get(op->ptr, "axis");
-
- 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];
- Lattice *lt;
-
- int numU, numV, numW;
- int totP;
-
- float mid = 0.0f;
- short isOdd = 0;
-
- /* get lattice - we need the "edit lattice" from the lattice... confusing... */
- lt = (Lattice *)obedit->data;
- lt = lt->editlatt->latt;
-
- numU = lt->pntsu;
- numV = lt->pntsv;
- numW = lt->pntsw;
- totP = numU * numV * numW;
-
- /* First Pass: determine midpoint - used for flipping center verts if there
- * are odd number of points on axis */
- switch (axis) {
- case LATTICE_FLIP_U:
- isOdd = numU & 1;
- break;
- case LATTICE_FLIP_V:
- isOdd = numV & 1;
- break;
- case LATTICE_FLIP_W:
- isOdd = numW & 1;
- break;
-
- default:
- printf("lattice_flip(): Unknown flipping axis (%u)\n", axis);
- return OPERATOR_CANCELLED;
- }
-
- if (isOdd) {
- BPoint *bp;
- float avgInv = 1.0f / (float)totP;
- int i;
-
- /* midpoint calculation - assuming that u/v/w are axis-aligned */
- for (i = 0, bp = lt->def; i < totP; i++, bp++) {
- mid += bp->vec[axis] * avgInv;
- }
- }
-
- /* Second Pass: swap pairs of vertices per axis, assuming they are all sorted */
- switch (axis) {
- case LATTICE_FLIP_U:
- {
- int u, v, w;
-
- /* v/w strips - front to back, top to bottom */
- for (w = 0; w < numW; w++) {
- for (v = 0; v < numV; v++) {
- /* swap coordinates of pairs of vertices on u */
- for (u = 0; u < (numU / 2); u++) {
- lattice_swap_point_pairs(lt, u, v, w, mid, axis);
- }
-
- /* flip u-coordinate of midpoint (i.e. unpaired point on u) */
- if (isOdd) {
- u = (numU / 2);
- lattice_flip_point_value(lt, u, v, w, mid, axis);
- }
- }
- }
- break;
- }
- case LATTICE_FLIP_V:
- {
- int u, v, w;
-
- /* u/w strips - front to back, left to right */
- for (w = 0; w < numW; w++) {
- for (u = 0; u < numU; u++) {
- /* swap coordinates of pairs of vertices on v */
- for (v = 0; v < (numV / 2); v++) {
- lattice_swap_point_pairs(lt, u, v, w, mid, axis);
- }
-
- /* flip v-coordinate of midpoint (i.e. unpaired point on v) */
- if (isOdd) {
- v = (numV / 2);
- lattice_flip_point_value(lt, u, v, w, mid, axis);
- }
- }
- }
- break;
- }
- case LATTICE_FLIP_W:
- {
- int u, v, w;
-
- for (v = 0; v < numV; v++) {
- for (u = 0; u < numU; u++) {
- /* swap coordinates of pairs of vertices on w */
- for (w = 0; w < (numW / 2); w++) {
- lattice_swap_point_pairs(lt, u, v, w, mid, axis);
- }
-
- /* flip w-coordinate of midpoint (i.e. unpaired point on w) */
- if (isOdd) {
- w = (numW / 2);
- lattice_flip_point_value(lt, u, v, w, mid, axis);
- }
- }
- }
- break;
- }
- default: /* shouldn't happen, but just in case */
- break;
- }
-
- /* updates */
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- changed = true;
- }
- MEM_freeN(objects);
-
- return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len;
+ bool changed = false;
+ const eLattice_FlipAxes axis = RNA_enum_get(op->ptr, "axis");
+
+ 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];
+ Lattice *lt;
+
+ int numU, numV, numW;
+ int totP;
+
+ float mid = 0.0f;
+ short isOdd = 0;
+
+ /* get lattice - we need the "edit lattice" from the lattice... confusing... */
+ lt = (Lattice *)obedit->data;
+ lt = lt->editlatt->latt;
+
+ numU = lt->pntsu;
+ numV = lt->pntsv;
+ numW = lt->pntsw;
+ totP = numU * numV * numW;
+
+ /* First Pass: determine midpoint - used for flipping center verts if there
+ * are odd number of points on axis */
+ switch (axis) {
+ case LATTICE_FLIP_U:
+ isOdd = numU & 1;
+ break;
+ case LATTICE_FLIP_V:
+ isOdd = numV & 1;
+ break;
+ case LATTICE_FLIP_W:
+ isOdd = numW & 1;
+ break;
+
+ default:
+ printf("lattice_flip(): Unknown flipping axis (%u)\n", axis);
+ return OPERATOR_CANCELLED;
+ }
+
+ if (isOdd) {
+ BPoint *bp;
+ float avgInv = 1.0f / (float)totP;
+ int i;
+
+ /* midpoint calculation - assuming that u/v/w are axis-aligned */
+ for (i = 0, bp = lt->def; i < totP; i++, bp++) {
+ mid += bp->vec[axis] * avgInv;
+ }
+ }
+
+ /* Second Pass: swap pairs of vertices per axis, assuming they are all sorted */
+ switch (axis) {
+ case LATTICE_FLIP_U: {
+ int u, v, w;
+
+ /* v/w strips - front to back, top to bottom */
+ for (w = 0; w < numW; w++) {
+ for (v = 0; v < numV; v++) {
+ /* swap coordinates of pairs of vertices on u */
+ for (u = 0; u < (numU / 2); u++) {
+ lattice_swap_point_pairs(lt, u, v, w, mid, axis);
+ }
+
+ /* flip u-coordinate of midpoint (i.e. unpaired point on u) */
+ if (isOdd) {
+ u = (numU / 2);
+ lattice_flip_point_value(lt, u, v, w, mid, axis);
+ }
+ }
+ }
+ break;
+ }
+ case LATTICE_FLIP_V: {
+ int u, v, w;
+
+ /* u/w strips - front to back, left to right */
+ for (w = 0; w < numW; w++) {
+ for (u = 0; u < numU; u++) {
+ /* swap coordinates of pairs of vertices on v */
+ for (v = 0; v < (numV / 2); v++) {
+ lattice_swap_point_pairs(lt, u, v, w, mid, axis);
+ }
+
+ /* flip v-coordinate of midpoint (i.e. unpaired point on v) */
+ if (isOdd) {
+ v = (numV / 2);
+ lattice_flip_point_value(lt, u, v, w, mid, axis);
+ }
+ }
+ }
+ break;
+ }
+ case LATTICE_FLIP_W: {
+ int u, v, w;
+
+ for (v = 0; v < numV; v++) {
+ for (u = 0; u < numU; u++) {
+ /* swap coordinates of pairs of vertices on w */
+ for (w = 0; w < (numW / 2); w++) {
+ lattice_swap_point_pairs(lt, u, v, w, mid, axis);
+ }
+
+ /* flip w-coordinate of midpoint (i.e. unpaired point on w) */
+ if (isOdd) {
+ w = (numW / 2);
+ lattice_flip_point_value(lt, u, v, w, mid, axis);
+ }
+ }
+ }
+ break;
+ }
+ default: /* shouldn't happen, but just in case */
+ break;
+ }
+
+ /* updates */
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ changed = true;
+ }
+ MEM_freeN(objects);
+
+ return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void LATTICE_OT_flip(wmOperatorType *ot)
{
- static const EnumPropertyItem flip_items[] = {
- {LATTICE_FLIP_U, "U", 0, "U (X) Axis", ""},
- {LATTICE_FLIP_V, "V", 0, "V (Y) Axis", ""},
- {LATTICE_FLIP_W, "W", 0, "W (Z) Axis", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Flip (Distortion Free)";
- ot->description = "Mirror all control points without inverting the lattice deform";
- ot->idname = "LATTICE_OT_flip";
-
- /* api callbacks */
- ot->poll = ED_operator_editlattice;
- ot->invoke = WM_menu_invoke;
- ot->exec = lattice_flip_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "axis", flip_items, LATTICE_FLIP_U, "Flip Axis", "Coordinates along this axis get flipped");
+ static const EnumPropertyItem flip_items[] = {
+ {LATTICE_FLIP_U, "U", 0, "U (X) Axis", ""},
+ {LATTICE_FLIP_V, "V", 0, "V (Y) Axis", ""},
+ {LATTICE_FLIP_W, "W", 0, "W (Z) Axis", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Flip (Distortion Free)";
+ ot->description = "Mirror all control points without inverting the lattice deform";
+ ot->idname = "LATTICE_OT_flip";
+
+ /* api callbacks */
+ ot->poll = ED_operator_editlattice;
+ ot->invoke = WM_menu_invoke;
+ ot->exec = lattice_flip_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna,
+ "axis",
+ flip_items,
+ LATTICE_FLIP_U,
+ "Flip Axis",
+ "Coordinates along this axis get flipped");
}
/** \} */
diff --git a/source/blender/editors/lattice/editlattice_undo.c b/source/blender/editors/lattice/editlattice_undo.c
index be8e0ae0633..9ee2e8b563b 100644
--- a/source/blender/editors/lattice/editlattice_undo.c
+++ b/source/blender/editors/lattice/editlattice_undo.c
@@ -61,64 +61,64 @@ static CLG_LogRef LOG = {"ed.undo.lattice"};
* \{ */
typedef struct UndoLattice {
- BPoint *def;
- int pntsu, pntsv, pntsw, actbp;
- size_t undo_size;
+ BPoint *def;
+ int pntsu, pntsv, pntsw, actbp;
+ size_t undo_size;
} UndoLattice;
static void undolatt_to_editlatt(UndoLattice *ult, EditLatt *editlatt)
{
- int len = editlatt->latt->pntsu * editlatt->latt->pntsv * editlatt->latt->pntsw;
+ int len = editlatt->latt->pntsu * editlatt->latt->pntsv * editlatt->latt->pntsw;
- memcpy(editlatt->latt->def, ult->def, sizeof(BPoint) * len);
- editlatt->latt->actbp = ult->actbp;
+ memcpy(editlatt->latt->def, ult->def, sizeof(BPoint) * len);
+ editlatt->latt->actbp = ult->actbp;
}
static void *undolatt_from_editlatt(UndoLattice *ult, EditLatt *editlatt)
{
- BLI_assert(BLI_array_is_zeroed(ult, 1));
+ BLI_assert(BLI_array_is_zeroed(ult, 1));
- ult->def = MEM_dupallocN(editlatt->latt->def);
- ult->pntsu = editlatt->latt->pntsu;
- ult->pntsv = editlatt->latt->pntsv;
- ult->pntsw = editlatt->latt->pntsw;
- ult->actbp = editlatt->latt->actbp;
+ ult->def = MEM_dupallocN(editlatt->latt->def);
+ ult->pntsu = editlatt->latt->pntsu;
+ ult->pntsv = editlatt->latt->pntsv;
+ ult->pntsw = editlatt->latt->pntsw;
+ ult->actbp = editlatt->latt->actbp;
- ult->undo_size += sizeof(*ult->def) * ult->pntsu * ult->pntsv * ult->pntsw;
+ ult->undo_size += sizeof(*ult->def) * ult->pntsu * ult->pntsv * ult->pntsw;
- return ult;
+ return ult;
}
static void undolatt_free_data(UndoLattice *ult)
{
- if (ult->def) {
- MEM_freeN(ult->def);
- }
+ if (ult->def) {
+ MEM_freeN(ult->def);
+ }
}
#if 0
static int validate_undoLatt(void *data, void *edata)
{
- UndoLattice *ult = (UndoLattice *)data;
- EditLatt *editlatt = (EditLatt *)edata;
+ UndoLattice *ult = (UndoLattice *)data;
+ EditLatt *editlatt = (EditLatt *)edata;
- return (ult->pntsu == editlatt->latt->pntsu &&
- ult->pntsv == editlatt->latt->pntsv &&
- ult->pntsw == editlatt->latt->pntsw);
+ return (ult->pntsu == editlatt->latt->pntsu &&
+ ult->pntsv == editlatt->latt->pntsv &&
+ ult->pntsw == editlatt->latt->pntsw);
}
#endif
static Object *editlatt_object_from_context(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_LATTICE) {
- Lattice *lt = obedit->data;
- if (lt->editlatt != NULL) {
- return obedit;
- }
- }
-
- return NULL;
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_LATTICE) {
+ Lattice *lt = obedit->data;
+ if (lt->editlatt != NULL) {
+ return obedit;
+ }
+ }
+
+ return NULL;
}
/** \} */
@@ -130,112 +130,123 @@ static Object *editlatt_object_from_context(bContext *C)
* \{ */
typedef struct LatticeUndoStep_Elem {
- UndoRefID_Object obedit_ref;
- UndoLattice data;
+ UndoRefID_Object obedit_ref;
+ UndoLattice data;
} LatticeUndoStep_Elem;
typedef struct LatticeUndoStep {
- UndoStep step;
- LatticeUndoStep_Elem *elems;
- uint elems_len;
+ UndoStep step;
+ LatticeUndoStep_Elem *elems;
+ uint elems_len;
} LatticeUndoStep;
static bool lattice_undosys_poll(bContext *C)
{
- return editlatt_object_from_context(C) != NULL;
+ return editlatt_object_from_context(C) != NULL;
}
-static bool lattice_undosys_step_encode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p)
+static bool lattice_undosys_step_encode(struct bContext *C,
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p)
{
- LatticeUndoStep *us = (LatticeUndoStep *)us_p;
-
- /* Important not to use the 3D view when getting objects because all objects
- * 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);
-
- us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
- us->elems_len = objects_len;
-
- for (uint i = 0; i < objects_len; i++) {
- Object *ob = objects[i];
- LatticeUndoStep_Elem *elem = &us->elems[i];
-
- elem->obedit_ref.ptr = ob;
- Lattice *lt = ob->data;
- undolatt_from_editlatt(&elem->data, lt->editlatt);
- us->step.data_size += elem->data.undo_size;
- }
- MEM_freeN(objects);
- return true;
+ LatticeUndoStep *us = (LatticeUndoStep *)us_p;
+
+ /* Important not to use the 3D view when getting objects because all objects
+ * 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);
+
+ us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
+ us->elems_len = objects_len;
+
+ for (uint i = 0; i < objects_len; i++) {
+ Object *ob = objects[i];
+ LatticeUndoStep_Elem *elem = &us->elems[i];
+
+ elem->obedit_ref.ptr = ob;
+ Lattice *lt = ob->data;
+ undolatt_from_editlatt(&elem->data, lt->editlatt);
+ us->step.data_size += elem->data.undo_size;
+ }
+ MEM_freeN(objects);
+ return true;
}
-static void lattice_undosys_step_decode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p, int UNUSED(dir))
+static void lattice_undosys_step_decode(struct bContext *C,
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p,
+ int UNUSED(dir))
{
- LatticeUndoStep *us = (LatticeUndoStep *)us_p;
-
- /* Load all our objects into edit-mode, clear everything else. */
- ED_undo_object_editmode_restore_helper(C, &us->elems[0].obedit_ref.ptr, us->elems_len, sizeof(*us->elems));
-
- BLI_assert(lattice_undosys_poll(C));
-
- for (uint i = 0; i < us->elems_len; i++) {
- LatticeUndoStep_Elem *elem = &us->elems[i];
- Object *obedit = elem->obedit_ref.ptr;
- Lattice *lt = obedit->data;
- if (lt->editlatt == NULL) {
- /* Should never fail, may not crash but can give odd behavior. */
- CLOG_ERROR(&LOG, "name='%s', failed to enter edit-mode for object '%s', undo state invalid",
- us_p->name, obedit->id.name);
- continue;
- }
- undolatt_to_editlatt(&elem->data, lt->editlatt);
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
-
- /* The first element is always active */
- ED_undo_object_set_active_or_warn(CTX_data_view_layer(C), us->elems[0].obedit_ref.ptr, us_p->name, &LOG);
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+ LatticeUndoStep *us = (LatticeUndoStep *)us_p;
+
+ /* Load all our objects into edit-mode, clear everything else. */
+ ED_undo_object_editmode_restore_helper(
+ C, &us->elems[0].obedit_ref.ptr, us->elems_len, sizeof(*us->elems));
+
+ BLI_assert(lattice_undosys_poll(C));
+
+ for (uint i = 0; i < us->elems_len; i++) {
+ LatticeUndoStep_Elem *elem = &us->elems[i];
+ Object *obedit = elem->obedit_ref.ptr;
+ Lattice *lt = obedit->data;
+ if (lt->editlatt == NULL) {
+ /* Should never fail, may not crash but can give odd behavior. */
+ CLOG_ERROR(&LOG,
+ "name='%s', failed to enter edit-mode for object '%s', undo state invalid",
+ us_p->name,
+ obedit->id.name);
+ continue;
+ }
+ undolatt_to_editlatt(&elem->data, lt->editlatt);
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ }
+
+ /* The first element is always active */
+ ED_undo_object_set_active_or_warn(
+ CTX_data_view_layer(C), us->elems[0].obedit_ref.ptr, us_p->name, &LOG);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
}
static void lattice_undosys_step_free(UndoStep *us_p)
{
- LatticeUndoStep *us = (LatticeUndoStep *)us_p;
+ LatticeUndoStep *us = (LatticeUndoStep *)us_p;
- for (uint i = 0; i < us->elems_len; i++) {
- LatticeUndoStep_Elem *elem = &us->elems[i];
- undolatt_free_data(&elem->data);
- }
- MEM_freeN(us->elems);
+ for (uint i = 0; i < us->elems_len; i++) {
+ LatticeUndoStep_Elem *elem = &us->elems[i];
+ undolatt_free_data(&elem->data);
+ }
+ MEM_freeN(us->elems);
}
-static void lattice_undosys_foreach_ID_ref(
- UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+static void lattice_undosys_foreach_ID_ref(UndoStep *us_p,
+ UndoTypeForEachIDRefFn foreach_ID_ref_fn,
+ void *user_data)
{
- LatticeUndoStep *us = (LatticeUndoStep *)us_p;
+ LatticeUndoStep *us = (LatticeUndoStep *)us_p;
- for (uint i = 0; i < us->elems_len; i++) {
- LatticeUndoStep_Elem *elem = &us->elems[i];
- foreach_ID_ref_fn(user_data, ((UndoRefID *)&elem->obedit_ref));
- }
+ for (uint i = 0; i < us->elems_len; i++) {
+ LatticeUndoStep_Elem *elem = &us->elems[i];
+ foreach_ID_ref_fn(user_data, ((UndoRefID *)&elem->obedit_ref));
+ }
}
/* Export for ED_undo_sys. */
void ED_lattice_undosys_type(UndoType *ut)
{
- ut->name = "Edit Lattice";
- ut->poll = lattice_undosys_poll;
- ut->step_encode = lattice_undosys_step_encode;
- ut->step_decode = lattice_undosys_step_decode;
- ut->step_free = lattice_undosys_step_free;
+ ut->name = "Edit Lattice";
+ ut->poll = lattice_undosys_poll;
+ ut->step_encode = lattice_undosys_step_encode;
+ ut->step_decode = lattice_undosys_step_decode;
+ ut->step_free = lattice_undosys_step_free;
- ut->step_foreach_ID_ref = lattice_undosys_foreach_ID_ref;
+ ut->step_foreach_ID_ref = lattice_undosys_foreach_ID_ref;
- ut->use_context = true;
+ ut->use_context = true;
- ut->step_size = sizeof(LatticeUndoStep);
+ ut->step_size = sizeof(LatticeUndoStep);
}
/** \} */
diff --git a/source/blender/editors/lattice/lattice_intern.h b/source/blender/editors/lattice/lattice_intern.h
index c08e6b6adb5..fe3f35b9223 100644
--- a/source/blender/editors/lattice/lattice_intern.h
+++ b/source/blender/editors/lattice/lattice_intern.h
@@ -21,7 +21,6 @@
* \ingroup edlattice
*/
-
#ifndef __LATTICE_INTERN_H__
#define __LATTICE_INTERN_H__
@@ -37,4 +36,4 @@ void LATTICE_OT_select_mirror(struct wmOperatorType *ot);
void LATTICE_OT_make_regular(struct wmOperatorType *ot);
void LATTICE_OT_flip(struct wmOperatorType *ot);
-#endif /* __LATTICE_INTERN_H__ */
+#endif /* __LATTICE_INTERN_H__ */
diff --git a/source/blender/editors/lattice/lattice_ops.c b/source/blender/editors/lattice/lattice_ops.c
index 49be5a6a4c9..a665d138163 100644
--- a/source/blender/editors/lattice/lattice_ops.c
+++ b/source/blender/editors/lattice/lattice_ops.c
@@ -37,18 +37,18 @@
void ED_operatortypes_lattice(void)
{
- WM_operatortype_append(LATTICE_OT_select_all);
- WM_operatortype_append(LATTICE_OT_select_more);
- WM_operatortype_append(LATTICE_OT_select_less);
- WM_operatortype_append(LATTICE_OT_select_ungrouped);
- WM_operatortype_append(LATTICE_OT_select_random);
- WM_operatortype_append(LATTICE_OT_select_mirror);
- WM_operatortype_append(LATTICE_OT_make_regular);
- WM_operatortype_append(LATTICE_OT_flip);
+ WM_operatortype_append(LATTICE_OT_select_all);
+ WM_operatortype_append(LATTICE_OT_select_more);
+ WM_operatortype_append(LATTICE_OT_select_less);
+ WM_operatortype_append(LATTICE_OT_select_ungrouped);
+ WM_operatortype_append(LATTICE_OT_select_random);
+ WM_operatortype_append(LATTICE_OT_select_mirror);
+ WM_operatortype_append(LATTICE_OT_make_regular);
+ WM_operatortype_append(LATTICE_OT_flip);
}
void ED_keymap_lattice(wmKeyConfig *keyconf)
{
- wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Lattice", 0, 0);
- keymap->poll = ED_operator_editlattice;
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Lattice", 0, 0);
+ keymap->poll = ED_operator_editlattice;
}
diff --git a/source/blender/editors/mask/CMakeLists.txt b/source/blender/editors/mask/CMakeLists.txt
index a8ed6812897..9dabcc0e8bb 100644
--- a/source/blender/editors/mask/CMakeLists.txt
+++ b/source/blender/editors/mask/CMakeLists.txt
@@ -18,33 +18,33 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../depsgraph
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../depsgraph
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- mask_add.c
- mask_draw.c
- mask_edit.c
- mask_editaction.c
- mask_ops.c
- mask_relationships.c
- mask_select.c
- mask_shapekey.c
+ mask_add.c
+ mask_draw.c
+ mask_edit.c
+ mask_editaction.c
+ mask_ops.c
+ mask_relationships.c
+ mask_select.c
+ mask_shapekey.c
- mask_intern.h
+ mask_intern.h
)
set(LIB
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index 579f3765710..1c872e73226 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -38,19 +38,19 @@
#include "WM_types.h"
#include "ED_select_utils.h"
-#include "ED_mask.h" /* own include */
+#include "ED_mask.h" /* own include */
#include "ED_screen.h"
#include "RNA_access.h"
#include "RNA_define.h"
-#include "mask_intern.h" /* own include */
-
+#include "mask_intern.h" /* own include */
bool ED_mask_find_nearest_diff_point(const bContext *C,
struct Mask *mask,
const float normal_co[2],
- int threshold, bool feather,
+ int threshold,
+ bool feather,
float tangent[2],
const bool use_deform,
const bool use_project,
@@ -60,840 +60,882 @@ bool ED_mask_find_nearest_diff_point(const bContext *C,
float *u_r,
float *score_r)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
-
- MaskLayer *masklay, *point_masklay;
- MaskSpline *point_spline;
- MaskSplinePoint *point = NULL;
- float dist_best_sq = FLT_MAX, co[2];
- int width, height;
- float u = 0.0f;
- float scalex, scaley;
-
- ED_mask_get_size(sa, &width, &height);
- ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
-
- co[0] = normal_co[0] * scalex;
- co[1] = normal_co[1] * scaley;
-
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
-
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
-
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- int i;
- MaskSplinePoint *cur_point;
-
- for (i = 0, cur_point = use_deform ? spline->points_deform : spline->points;
- i < spline->tot_point;
- i++, cur_point++)
- {
- float *diff_points;
- unsigned int tot_diff_point;
-
- diff_points = BKE_mask_point_segment_diff(spline, cur_point, 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, cur_point,
- 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_masklay = masklay;
- point_spline = spline;
- point = use_deform ? &spline->points[(cur_point - spline->points_deform)] : cur_point;
- dist_best_sq = dist_sq;
- u = (float)j / tot_point;
- }
- }
-
- if (feather_points)
- MEM_freeN(feather_points);
-
- MEM_freeN(diff_points);
- }
- }
- }
- }
-
- if (point && dist_best_sq < threshold) {
- if (masklay_r)
- *masklay_r = point_masklay;
-
- 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;
- }
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ MaskLayer *masklay, *point_masklay;
+ MaskSpline *point_spline;
+ MaskSplinePoint *point = NULL;
+ float dist_best_sq = FLT_MAX, co[2];
+ int width, height;
+ float u = 0.0f;
+ float scalex, scaley;
+
+ ED_mask_get_size(sa, &width, &height);
+ ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
+
+ co[0] = normal_co[0] * scalex;
+ co[1] = normal_co[1] * scaley;
+
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ int i;
+ MaskSplinePoint *cur_point;
+
+ for (i = 0, cur_point = use_deform ? spline->points_deform : spline->points;
+ i < spline->tot_point;
+ i++, cur_point++) {
+ float *diff_points;
+ unsigned int tot_diff_point;
+
+ diff_points = BKE_mask_point_segment_diff(
+ spline, cur_point, 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, cur_point, 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]);
- if (score_r) {
- *score_r = dist_best_sq;
- }
+ point_masklay = masklay;
+ point_spline = spline;
+ point = use_deform ? &spline->points[(cur_point - spline->points_deform)] :
+ cur_point;
+ dist_best_sq = dist_sq;
+ u = (float)j / tot_point;
+ }
+ }
- return true;
- }
+ if (feather_points)
+ MEM_freeN(feather_points);
- if (masklay_r)
- *masklay_r = NULL;
+ MEM_freeN(diff_points);
+ }
+ }
+ }
+ }
- if (spline_r)
- *spline_r = NULL;
+ if (point && dist_best_sq < threshold) {
+ if (masklay_r)
+ *masklay_r = point_masklay;
- if (point_r)
- *point_r = NULL;
+ if (spline_r)
+ *spline_r = point_spline;
- return false;
+ 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 (masklay_r)
+ *masklay_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, MaskSpline *spline, MaskSplinePoint *new_point,
- const float point_co[2], const float u, const float ctime,
- const MaskSplinePoint *reference_point, const bool reference_adjacent)
+static void setup_vertex_point(Mask *mask,
+ MaskSpline *spline,
+ MaskSplinePoint *new_point,
+ const float point_co[2],
+ const float u,
+ const float ctime,
+ const MaskSplinePoint *reference_point,
+ const bool reference_adjacent)
{
- const MaskSplinePoint *reference_parent_point = NULL;
- BezTriple *bezt;
- float co[3];
-
- copy_v2_v2(co, point_co);
- co[2] = 0.0f;
-
- /* point coordinate */
- bezt = &new_point->bezt;
-
- bezt->h1 = bezt->h2 = HD_ALIGN;
-
- if (reference_point) {
- if (reference_point->bezt.h1 == HD_VECT && reference_point->bezt.h2 == HD_VECT) {
- /* If the reference point is sharp try using some smooth point as reference
- * for handles.
- */
- int point_index = reference_point - spline->points;
- int delta = new_point == spline->points ? 1 : -1;
- int i = 0;
- for (i = 0; i < spline->tot_point - 1; ++i) {
- MaskSplinePoint *current_point;
-
- point_index += delta;
- if (point_index == -1 || point_index >= spline->tot_point) {
- if (spline->flag & MASK_SPLINE_CYCLIC) {
- if (point_index == -1) {
- point_index = spline->tot_point - 1;
- }
- else if (point_index >= spline->tot_point) {
- point_index = 0;
- }
- }
- else {
- break;
- }
- }
-
- current_point = &spline->points[point_index];
- if (current_point->bezt.h1 != HD_VECT || current_point->bezt.h2 != HD_VECT) {
- bezt->h1 = bezt->h2 = MAX2(current_point->bezt.h2, current_point->bezt.h1);
- break;
- }
- }
- }
- else {
- bezt->h1 = bezt->h2 = MAX2(reference_point->bezt.h2, reference_point->bezt.h1);
- }
-
- reference_parent_point = reference_point;
- }
- else if (reference_adjacent) {
- if (spline->tot_point != 1) {
- MaskSplinePoint *prev_point, *next_point, *close_point;
-
- const int index = (int)(new_point - spline->points);
- if (spline->flag & MASK_SPLINE_CYCLIC) {
- prev_point = &spline->points[mod_i(index - 1, spline->tot_point)];
- next_point = &spline->points[mod_i(index + 1, spline->tot_point)];
- }
- else {
- prev_point = (index != 0) ? &spline->points[index - 1] : NULL;
- next_point = (index != spline->tot_point - 1) ? &spline->points[index + 1] : NULL;
- }
-
- if (prev_point && next_point) {
- close_point = (len_squared_v2v2(new_point->bezt.vec[1], prev_point->bezt.vec[1]) <
- len_squared_v2v2(new_point->bezt.vec[1], next_point->bezt.vec[1])) ?
- prev_point : next_point;
- }
- else {
- close_point = prev_point ? prev_point : next_point;
- }
-
- /* handle type */
- char handle_type = 0;
- if (prev_point) {
- handle_type = prev_point->bezt.h2;
- }
- if (next_point) {
- handle_type = MAX2(next_point->bezt.h2, handle_type);
- }
- bezt->h1 = bezt->h2 = handle_type;
-
- /* parent */
- reference_parent_point = close_point;
-
- /* note, we may want to copy other attributes later, radius? pressure? color? */
- }
- }
-
- copy_v3_v3(bezt->vec[0], co);
- copy_v3_v3(bezt->vec[1], co);
- copy_v3_v3(bezt->vec[2], co);
-
- if (reference_parent_point) {
- new_point->parent = reference_parent_point->parent;
-
- if (new_point->parent.id) {
- float parent_matrix[3][3];
- BKE_mask_point_parent_matrix_get(new_point, ctime, parent_matrix);
- invert_m3(parent_matrix);
- mul_m3_v2(parent_matrix, new_point->bezt.vec[1]);
- }
- }
- else {
- BKE_mask_parent_init(&new_point->parent);
- }
-
- if (spline->tot_point != 1) {
- BKE_mask_calc_handle_adjacent_interp(spline, new_point, u);
- }
-
- /* select new point */
- MASKPOINT_SEL_ALL(new_point);
- ED_mask_select_flush_all(mask);
+ const MaskSplinePoint *reference_parent_point = NULL;
+ BezTriple *bezt;
+ float co[3];
+
+ copy_v2_v2(co, point_co);
+ co[2] = 0.0f;
+
+ /* point coordinate */
+ bezt = &new_point->bezt;
+
+ bezt->h1 = bezt->h2 = HD_ALIGN;
+
+ if (reference_point) {
+ if (reference_point->bezt.h1 == HD_VECT && reference_point->bezt.h2 == HD_VECT) {
+ /* If the reference point is sharp try using some smooth point as reference
+ * for handles.
+ */
+ int point_index = reference_point - spline->points;
+ int delta = new_point == spline->points ? 1 : -1;
+ int i = 0;
+ for (i = 0; i < spline->tot_point - 1; ++i) {
+ MaskSplinePoint *current_point;
+
+ point_index += delta;
+ if (point_index == -1 || point_index >= spline->tot_point) {
+ if (spline->flag & MASK_SPLINE_CYCLIC) {
+ if (point_index == -1) {
+ point_index = spline->tot_point - 1;
+ }
+ else if (point_index >= spline->tot_point) {
+ point_index = 0;
+ }
+ }
+ else {
+ break;
+ }
+ }
+
+ current_point = &spline->points[point_index];
+ if (current_point->bezt.h1 != HD_VECT || current_point->bezt.h2 != HD_VECT) {
+ bezt->h1 = bezt->h2 = MAX2(current_point->bezt.h2, current_point->bezt.h1);
+ break;
+ }
+ }
+ }
+ else {
+ bezt->h1 = bezt->h2 = MAX2(reference_point->bezt.h2, reference_point->bezt.h1);
+ }
+
+ reference_parent_point = reference_point;
+ }
+ else if (reference_adjacent) {
+ if (spline->tot_point != 1) {
+ MaskSplinePoint *prev_point, *next_point, *close_point;
+
+ const int index = (int)(new_point - spline->points);
+ if (spline->flag & MASK_SPLINE_CYCLIC) {
+ prev_point = &spline->points[mod_i(index - 1, spline->tot_point)];
+ next_point = &spline->points[mod_i(index + 1, spline->tot_point)];
+ }
+ else {
+ prev_point = (index != 0) ? &spline->points[index - 1] : NULL;
+ next_point = (index != spline->tot_point - 1) ? &spline->points[index + 1] : NULL;
+ }
+
+ if (prev_point && next_point) {
+ close_point = (len_squared_v2v2(new_point->bezt.vec[1], prev_point->bezt.vec[1]) <
+ len_squared_v2v2(new_point->bezt.vec[1], next_point->bezt.vec[1])) ?
+ prev_point :
+ next_point;
+ }
+ else {
+ close_point = prev_point ? prev_point : next_point;
+ }
+
+ /* handle type */
+ char handle_type = 0;
+ if (prev_point) {
+ handle_type = prev_point->bezt.h2;
+ }
+ if (next_point) {
+ handle_type = MAX2(next_point->bezt.h2, handle_type);
+ }
+ bezt->h1 = bezt->h2 = handle_type;
+
+ /* parent */
+ reference_parent_point = close_point;
+
+ /* note, we may want to copy other attributes later, radius? pressure? color? */
+ }
+ }
+
+ copy_v3_v3(bezt->vec[0], co);
+ copy_v3_v3(bezt->vec[1], co);
+ copy_v3_v3(bezt->vec[2], co);
+
+ if (reference_parent_point) {
+ new_point->parent = reference_parent_point->parent;
+
+ if (new_point->parent.id) {
+ float parent_matrix[3][3];
+ BKE_mask_point_parent_matrix_get(new_point, ctime, parent_matrix);
+ invert_m3(parent_matrix);
+ mul_m3_v2(parent_matrix, new_point->bezt.vec[1]);
+ }
+ }
+ else {
+ BKE_mask_parent_init(&new_point->parent);
+ }
+
+ if (spline->tot_point != 1) {
+ BKE_mask_calc_handle_adjacent_interp(spline, new_point, u);
+ }
+
+ /* select new point */
+ MASKPOINT_SEL_ALL(new_point);
+ ED_mask_select_flush_all(mask);
}
-
/* **** add extrude vertex **** */
-static void finSelectedSplinePoint(MaskLayer *masklay, MaskSpline **spline, MaskSplinePoint **point, bool check_active)
+static void finSelectedSplinePoint(MaskLayer *masklay,
+ MaskSpline **spline,
+ MaskSplinePoint **point,
+ bool check_active)
{
- MaskSpline *cur_spline = masklay->splines.first;
-
- *spline = NULL;
- *point = NULL;
-
- if (check_active) {
- /* TODO, having an active point but no active spline is possible, why? */
- if (masklay->act_spline && masklay->act_point && MASKPOINT_ISSEL_ANY(masklay->act_point)) {
- *spline = masklay->act_spline;
- *point = masklay->act_point;
- return;
- }
- }
-
- while (cur_spline) {
- int i;
-
- for (i = 0; i < cur_spline->tot_point; i++) {
- MaskSplinePoint *cur_point = &cur_spline->points[i];
-
- if (MASKPOINT_ISSEL_ANY(cur_point)) {
- if (*spline != NULL && *spline != cur_spline) {
- *spline = NULL;
- *point = NULL;
- return;
- }
- else if (*point) {
- *point = NULL;
- }
- else {
- *spline = cur_spline;
- *point = cur_point;
- }
- }
- }
-
- cur_spline = cur_spline->next;
- }
+ MaskSpline *cur_spline = masklay->splines.first;
+
+ *spline = NULL;
+ *point = NULL;
+
+ if (check_active) {
+ /* TODO, having an active point but no active spline is possible, why? */
+ if (masklay->act_spline && masklay->act_point && MASKPOINT_ISSEL_ANY(masklay->act_point)) {
+ *spline = masklay->act_spline;
+ *point = masklay->act_point;
+ return;
+ }
+ }
+
+ while (cur_spline) {
+ int i;
+
+ for (i = 0; i < cur_spline->tot_point; i++) {
+ MaskSplinePoint *cur_point = &cur_spline->points[i];
+
+ if (MASKPOINT_ISSEL_ANY(cur_point)) {
+ if (*spline != NULL && *spline != cur_spline) {
+ *spline = NULL;
+ *point = NULL;
+ return;
+ }
+ else if (*point) {
+ *point = NULL;
+ }
+ else {
+ *spline = cur_spline;
+ *point = cur_point;
+ }
+ }
+ }
+
+ cur_spline = cur_spline->next;
+ }
}
/* **** add subdivide vertex **** */
static void mask_spline_add_point_at_index(MaskSpline *spline, int point_index)
{
- MaskSplinePoint *new_point_array;
+ MaskSplinePoint *new_point_array;
- new_point_array = MEM_callocN(sizeof(MaskSplinePoint) * (spline->tot_point + 1), "add mask vert points");
+ new_point_array = MEM_callocN(sizeof(MaskSplinePoint) * (spline->tot_point + 1),
+ "add mask vert points");
- memcpy(new_point_array, spline->points, sizeof(MaskSplinePoint) * (point_index + 1));
- memcpy(new_point_array + point_index + 2, spline->points + point_index + 1,
- sizeof(MaskSplinePoint) * (spline->tot_point - point_index - 1));
+ memcpy(new_point_array, spline->points, sizeof(MaskSplinePoint) * (point_index + 1));
+ memcpy(new_point_array + point_index + 2,
+ spline->points + point_index + 1,
+ sizeof(MaskSplinePoint) * (spline->tot_point - point_index - 1));
- MEM_freeN(spline->points);
- spline->points = new_point_array;
- spline->tot_point++;
+ MEM_freeN(spline->points);
+ spline->points = new_point_array;
+ spline->tot_point++;
}
static bool add_vertex_subdivide(const bContext *C, Mask *mask, const float co[2])
{
- MaskLayer *masklay;
- MaskSpline *spline;
- MaskSplinePoint *point = NULL;
- const float threshold = 9;
- float tangent[2];
- float u;
-
- if (ED_mask_find_nearest_diff_point(C, mask, co, threshold, false, tangent, true, true,
- &masklay, &spline, &point, &u, NULL))
- {
- Scene *scene = CTX_data_scene(C);
- const float ctime = CFRA;
-
- MaskSplinePoint *new_point;
- int point_index = point - spline->points;
-
- ED_mask_select_toggle_all(mask, SEL_DESELECT);
-
- mask_spline_add_point_at_index(spline, point_index);
-
- new_point = &spline->points[point_index + 1];
-
- setup_vertex_point(mask, spline, new_point, co, u, ctime, NULL, true);
-
- /* TODO - we could pass the spline! */
- BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index + 1, true, true);
-
- masklay->act_spline = spline;
- masklay->act_point = new_point;
-
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
-
- return true;
- }
-
- return false;
+ MaskLayer *masklay;
+ MaskSpline *spline;
+ MaskSplinePoint *point = NULL;
+ const float threshold = 9;
+ float tangent[2];
+ float u;
+
+ if (ED_mask_find_nearest_diff_point(C,
+ mask,
+ co,
+ threshold,
+ false,
+ tangent,
+ true,
+ true,
+ &masklay,
+ &spline,
+ &point,
+ &u,
+ NULL)) {
+ Scene *scene = CTX_data_scene(C);
+ const float ctime = CFRA;
+
+ MaskSplinePoint *new_point;
+ int point_index = point - spline->points;
+
+ ED_mask_select_toggle_all(mask, SEL_DESELECT);
+
+ mask_spline_add_point_at_index(spline, point_index);
+
+ new_point = &spline->points[point_index + 1];
+
+ setup_vertex_point(mask, spline, new_point, co, u, ctime, NULL, true);
+
+ /* TODO - we could pass the spline! */
+ BKE_mask_layer_shape_changed_add(masklay,
+ BKE_mask_layer_shape_spline_to_index(masklay, spline) +
+ point_index + 1,
+ true,
+ true);
+
+ masklay->act_spline = spline;
+ masklay->act_point = new_point;
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+
+ return true;
+ }
+
+ return false;
}
-static bool add_vertex_extrude(const bContext *C, Mask *mask, MaskLayer *masklay, const float co[2])
+static bool add_vertex_extrude(const bContext *C,
+ Mask *mask,
+ MaskLayer *masklay,
+ const float co[2])
{
- Scene *scene = CTX_data_scene(C);
- const float ctime = CFRA;
-
- MaskSpline *spline;
- MaskSplinePoint *point;
- MaskSplinePoint *new_point = NULL, *ref_point = NULL;
-
- /* check on which side we want to add the point */
- int point_index;
- float tangent_point[2];
- float tangent_co[2];
- bool do_cyclic_correct = false;
- bool do_prev; /* use prev point rather then next?? */
-
- if (!masklay) {
- return false;
- }
- else {
- finSelectedSplinePoint(masklay, &spline, &point, true);
- }
-
- ED_mask_select_toggle_all(mask, SEL_DESELECT);
-
- point_index = (point - spline->points);
-
- MASKPOINT_DESEL_ALL(point);
-
- if ((spline->flag & MASK_SPLINE_CYCLIC) ||
- (point_index > 0 && point_index != spline->tot_point - 1))
- {
- BKE_mask_calc_tangent_polyline(spline, point, tangent_point);
- sub_v2_v2v2(tangent_co, co, point->bezt.vec[1]);
-
- if (dot_v2v2(tangent_point, tangent_co) < 0.0f) {
- do_prev = true;
- }
- else {
- do_prev = false;
- }
- }
- else if (((spline->flag & MASK_SPLINE_CYCLIC) == 0) && (point_index == 0)) {
- do_prev = true;
- }
- else if (((spline->flag & MASK_SPLINE_CYCLIC) == 0) && (point_index == spline->tot_point - 1)) {
- do_prev = false;
- }
- else {
- do_prev = false; /* quiet warning */
- /* should never get here */
- BLI_assert(0);
- }
-
- /* use the point before the active one */
- if (do_prev) {
- point_index--;
- if (point_index < 0) {
- point_index += spline->tot_point; /* wrap index */
- if ((spline->flag & MASK_SPLINE_CYCLIC) == 0) {
- do_cyclic_correct = true;
- point_index = 0;
- }
- }
- }
-
-// print_v2("", tangent_point);
-// printf("%d\n", point_index);
-
- mask_spline_add_point_at_index(spline, point_index);
-
- if (do_cyclic_correct) {
- ref_point = &spline->points[point_index + 1];
- new_point = &spline->points[point_index];
- *ref_point = *new_point;
- memset(new_point, 0, sizeof(*new_point));
- }
- else {
- ref_point = &spline->points[point_index];
- new_point = &spline->points[point_index + 1];
- }
-
- masklay->act_point = new_point;
-
- setup_vertex_point(mask, spline, new_point, co, 0.5f, ctime, ref_point, false);
-
- if (masklay->splines_shapes.first) {
- point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point);
- BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index, true, true);
- }
-
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
-
- return true;
+ Scene *scene = CTX_data_scene(C);
+ const float ctime = CFRA;
+
+ MaskSpline *spline;
+ MaskSplinePoint *point;
+ MaskSplinePoint *new_point = NULL, *ref_point = NULL;
+
+ /* check on which side we want to add the point */
+ int point_index;
+ float tangent_point[2];
+ float tangent_co[2];
+ bool do_cyclic_correct = false;
+ bool do_prev; /* use prev point rather then next?? */
+
+ if (!masklay) {
+ return false;
+ }
+ else {
+ finSelectedSplinePoint(masklay, &spline, &point, true);
+ }
+
+ ED_mask_select_toggle_all(mask, SEL_DESELECT);
+
+ point_index = (point - spline->points);
+
+ MASKPOINT_DESEL_ALL(point);
+
+ if ((spline->flag & MASK_SPLINE_CYCLIC) ||
+ (point_index > 0 && point_index != spline->tot_point - 1)) {
+ BKE_mask_calc_tangent_polyline(spline, point, tangent_point);
+ sub_v2_v2v2(tangent_co, co, point->bezt.vec[1]);
+
+ if (dot_v2v2(tangent_point, tangent_co) < 0.0f) {
+ do_prev = true;
+ }
+ else {
+ do_prev = false;
+ }
+ }
+ else if (((spline->flag & MASK_SPLINE_CYCLIC) == 0) && (point_index == 0)) {
+ do_prev = true;
+ }
+ else if (((spline->flag & MASK_SPLINE_CYCLIC) == 0) && (point_index == spline->tot_point - 1)) {
+ do_prev = false;
+ }
+ else {
+ do_prev = false; /* quiet warning */
+ /* should never get here */
+ BLI_assert(0);
+ }
+
+ /* use the point before the active one */
+ if (do_prev) {
+ point_index--;
+ if (point_index < 0) {
+ point_index += spline->tot_point; /* wrap index */
+ if ((spline->flag & MASK_SPLINE_CYCLIC) == 0) {
+ do_cyclic_correct = true;
+ point_index = 0;
+ }
+ }
+ }
+
+ // print_v2("", tangent_point);
+ // printf("%d\n", point_index);
+
+ mask_spline_add_point_at_index(spline, point_index);
+
+ if (do_cyclic_correct) {
+ ref_point = &spline->points[point_index + 1];
+ new_point = &spline->points[point_index];
+ *ref_point = *new_point;
+ memset(new_point, 0, sizeof(*new_point));
+ }
+ else {
+ ref_point = &spline->points[point_index];
+ new_point = &spline->points[point_index + 1];
+ }
+
+ masklay->act_point = new_point;
+
+ setup_vertex_point(mask, spline, new_point, co, 0.5f, ctime, ref_point, false);
+
+ if (masklay->splines_shapes.first) {
+ point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point);
+ BKE_mask_layer_shape_changed_add(
+ masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index, true, true);
+ }
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+
+ return true;
}
static bool add_vertex_new(const bContext *C, Mask *mask, MaskLayer *masklay, const float co[2])
{
- Scene *scene = CTX_data_scene(C);
- const float ctime = CFRA;
+ Scene *scene = CTX_data_scene(C);
+ const float ctime = CFRA;
- MaskSpline *spline;
- MaskSplinePoint *new_point = NULL, *ref_point = NULL;
+ MaskSpline *spline;
+ MaskSplinePoint *new_point = NULL, *ref_point = NULL;
- if (!masklay) {
- /* if there's no masklay currently operationg on, create new one */
- masklay = BKE_mask_layer_new(mask, "");
- mask->masklay_act = mask->masklay_tot - 1;
- }
+ if (!masklay) {
+ /* if there's no masklay currently operationg on, create new one */
+ masklay = BKE_mask_layer_new(mask, "");
+ mask->masklay_act = mask->masklay_tot - 1;
+ }
- ED_mask_select_toggle_all(mask, SEL_DESELECT);
+ ED_mask_select_toggle_all(mask, SEL_DESELECT);
- spline = BKE_mask_spline_add(masklay);
+ spline = BKE_mask_spline_add(masklay);
- masklay->act_spline = spline;
- new_point = spline->points;
+ masklay->act_spline = spline;
+ new_point = spline->points;
- masklay->act_point = new_point;
+ masklay->act_point = new_point;
- setup_vertex_point(mask, spline, new_point, co, 0.5f, ctime, ref_point, false);
+ setup_vertex_point(mask, spline, new_point, co, 0.5f, ctime, ref_point, false);
- {
- int point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point);
- BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index, true, true);
- }
+ {
+ int point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point);
+ BKE_mask_layer_shape_changed_add(
+ masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index, true, true);
+ }
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
- return true;
+ return true;
}
static int add_vertex_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
-
- float co[2];
-
- if (mask == NULL) {
- /* if there's no active mask, create one */
- mask = ED_mask_new(C, NULL);
- }
-
- masklay = BKE_mask_layer_active(mask);
-
- if (masklay && masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- masklay = NULL;
- }
-
- RNA_float_get_array(op->ptr, "location", co);
-
- /* TODO, having an active point but no active spline is possible, why? */
- if (masklay && masklay->act_spline && masklay->act_point && MASKPOINT_ISSEL_ANY(masklay->act_point)) {
-
- /* cheap trick - double click for cyclic */
- MaskSpline *spline = masklay->act_spline;
- MaskSplinePoint *point = masklay->act_point;
-
- const bool is_sta = (point == spline->points);
- const bool is_end = (point == &spline->points[spline->tot_point - 1]);
-
- /* then check are we overlapping the mouse */
- if ((is_sta || is_end) && equals_v2v2(co, point->bezt.vec[1])) {
- if (spline->flag & MASK_SPLINE_CYCLIC) {
- /* nothing to do */
- return OPERATOR_CANCELLED;
- }
- else {
- /* recalc the connecting point as well to make a nice even curve */
- MaskSplinePoint *point_other = is_end ? spline->points : &spline->points[spline->tot_point - 1];
- spline->flag |= MASK_SPLINE_CYCLIC;
-
- /* TODO, update keyframes in time */
- BKE_mask_calc_handle_point_auto(spline, point, false);
- BKE_mask_calc_handle_point_auto(spline, point_other, false);
-
- /* TODO: only update this spline */
- BKE_mask_update_display(mask, CFRA);
-
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
- return OPERATOR_FINISHED;
- }
- }
-
- if (!add_vertex_subdivide(C, mask, co)) {
- if (!add_vertex_extrude(C, mask, masklay, co)) {
- return OPERATOR_CANCELLED;
- }
- }
- }
- else {
- if (!add_vertex_subdivide(C, mask, co)) {
- if (!add_vertex_new(C, mask, masklay, co)) {
- return OPERATOR_CANCELLED;
- }
- }
- }
-
- /* TODO: only update this spline */
- BKE_mask_update_display(mask, CFRA);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+
+ float co[2];
+
+ if (mask == NULL) {
+ /* if there's no active mask, create one */
+ mask = ED_mask_new(C, NULL);
+ }
+
+ masklay = BKE_mask_layer_active(mask);
+
+ if (masklay && masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ masklay = NULL;
+ }
+
+ RNA_float_get_array(op->ptr, "location", co);
+
+ /* TODO, having an active point but no active spline is possible, why? */
+ if (masklay && masklay->act_spline && masklay->act_point &&
+ MASKPOINT_ISSEL_ANY(masklay->act_point)) {
+
+ /* cheap trick - double click for cyclic */
+ MaskSpline *spline = masklay->act_spline;
+ MaskSplinePoint *point = masklay->act_point;
+
+ const bool is_sta = (point == spline->points);
+ const bool is_end = (point == &spline->points[spline->tot_point - 1]);
+
+ /* then check are we overlapping the mouse */
+ if ((is_sta || is_end) && equals_v2v2(co, point->bezt.vec[1])) {
+ if (spline->flag & MASK_SPLINE_CYCLIC) {
+ /* nothing to do */
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* recalc the connecting point as well to make a nice even curve */
+ MaskSplinePoint *point_other = is_end ? spline->points :
+ &spline->points[spline->tot_point - 1];
+ spline->flag |= MASK_SPLINE_CYCLIC;
+
+ /* TODO, update keyframes in time */
+ BKE_mask_calc_handle_point_auto(spline, point, false);
+ BKE_mask_calc_handle_point_auto(spline, point_other, false);
+
+ /* TODO: only update this spline */
+ BKE_mask_update_display(mask, CFRA);
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ return OPERATOR_FINISHED;
+ }
+ }
+
+ if (!add_vertex_subdivide(C, mask, co)) {
+ if (!add_vertex_extrude(C, mask, masklay, co)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+ }
+ else {
+ if (!add_vertex_subdivide(C, mask, co)) {
+ if (!add_vertex_new(C, mask, masklay, co)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+ }
+
+ /* TODO: only update this spline */
+ BKE_mask_update_display(mask, CFRA);
+
+ return OPERATOR_FINISHED;
}
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 *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
- float co[2];
+ float co[2];
- ED_mask_mouse_pos(sa, ar, event->mval, co);
+ ED_mask_mouse_pos(sa, ar, event->mval, co);
- RNA_float_set_array(op->ptr, "location", co);
+ RNA_float_set_array(op->ptr, "location", co);
- return add_vertex_exec(C, op);
+ return add_vertex_exec(C, op);
}
void MASK_OT_add_vertex(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Vertex";
- ot->description = "Add vertex to active spline";
- ot->idname = "MASK_OT_add_vertex";
-
- /* api callbacks */
- ot->exec = add_vertex_exec;
- ot->invoke = add_vertex_invoke;
- ot->poll = ED_operator_mask;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
- "Location", "Location of vertex in normalized space", -1.0f, 1.0f);
+ /* identifiers */
+ ot->name = "Add Vertex";
+ ot->description = "Add vertex to active spline";
+ ot->idname = "MASK_OT_add_vertex";
+
+ /* api callbacks */
+ ot->exec = add_vertex_exec;
+ ot->invoke = add_vertex_invoke;
+ ot->poll = ED_operator_mask;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float_vector(ot->srna,
+ "location",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Location",
+ "Location of vertex in normalized space",
+ -1.0f,
+ 1.0f);
}
/******************** add feather vertex *********************/
static int add_feather_vertex_exec(bContext *C, wmOperator *op)
{
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
- MaskSpline *spline;
- MaskSplinePoint *point = NULL;
- const float threshold = 9;
- float co[2], u;
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+ MaskSpline *spline;
+ MaskSplinePoint *point = NULL;
+ const float threshold = 9;
+ float co[2], u;
- RNA_float_get_array(op->ptr, "location", co);
+ RNA_float_get_array(op->ptr, "location", co);
- point = ED_mask_point_find_nearest(C, mask, co, threshold, NULL, NULL, NULL, NULL);
- if (point)
- return OPERATOR_FINISHED;
+ point = ED_mask_point_find_nearest(C, mask, co, threshold, NULL, NULL, NULL, NULL);
+ if (point)
+ return OPERATOR_FINISHED;
- if (ED_mask_find_nearest_diff_point(C, mask, co, threshold, true, NULL, true, true,
- &masklay, &spline, &point, &u, NULL))
- {
- Scene *scene = CTX_data_scene(C);
- float w = BKE_mask_point_weight(spline, point, u);
- float weight_scalar = BKE_mask_point_weight_scalar(spline, point, u);
+ if (ED_mask_find_nearest_diff_point(
+ C, mask, co, threshold, true, NULL, true, true, &masklay, &spline, &point, &u, NULL)) {
+ Scene *scene = CTX_data_scene(C);
+ float w = BKE_mask_point_weight(spline, point, u);
+ float weight_scalar = BKE_mask_point_weight_scalar(spline, point, u);
- if (weight_scalar != 0.0f) {
- w = w / weight_scalar;
- }
+ if (weight_scalar != 0.0f) {
+ w = w / weight_scalar;
+ }
- BKE_mask_point_add_uw(point, u, w);
+ BKE_mask_point_add_uw(point, u, w);
- BKE_mask_update_display(mask, scene->r.cfra);
+ BKE_mask_update_display(mask, scene->r.cfra);
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
- DEG_id_tag_update(&mask->id, 0);
+ DEG_id_tag_update(&mask->id, 0);
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
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 *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
- float co[2];
+ float co[2];
- ED_mask_mouse_pos(sa, ar, event->mval, co);
+ ED_mask_mouse_pos(sa, ar, event->mval, co);
- RNA_float_set_array(op->ptr, "location", co);
+ RNA_float_set_array(op->ptr, "location", co);
- return add_feather_vertex_exec(C, op);
+ return add_feather_vertex_exec(C, op);
}
void MASK_OT_add_feather_vertex(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Feather Vertex";
- ot->description = "Add vertex to feather";
- ot->idname = "MASK_OT_add_feather_vertex";
-
- /* api callbacks */
- ot->exec = add_feather_vertex_exec;
- ot->invoke = add_feather_vertex_invoke;
- ot->poll = ED_maskedit_mask_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
- "Location", "Location of vertex in normalized space", -1.0f, 1.0f);
+ /* identifiers */
+ ot->name = "Add Feather Vertex";
+ ot->description = "Add vertex to feather";
+ ot->idname = "MASK_OT_add_feather_vertex";
+
+ /* api callbacks */
+ ot->exec = add_feather_vertex_exec;
+ ot->invoke = add_feather_vertex_invoke;
+ ot->poll = ED_maskedit_mask_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float_vector(ot->srna,
+ "location",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Location",
+ "Location of vertex in normalized space",
+ -1.0f,
+ 1.0f);
}
/******************** common primitive functions *********************/
-static int create_primitive_from_points(bContext *C, wmOperator *op, const float (*points)[2],
- int num_points, char handle_type)
+static int create_primitive_from_points(
+ bContext *C, wmOperator *op, const float (*points)[2], int num_points, char handle_type)
{
- ScrArea *sa = CTX_wm_area(C);
- Scene *scene = CTX_data_scene(C);
- Mask *mask;
- MaskLayer *mask_layer;
- MaskSpline *new_spline;
- float scale, location[2], frame_size[2];
- int i, width, height;
- int size = RNA_float_get(op->ptr, "size");
-
- ED_mask_get_size(sa, &width, &height);
- scale = (float)size / max_ii(width, height);
-
- /* Get location in mask space. */
- frame_size[0] = width;
- frame_size[1] = height;
- RNA_float_get_array(op->ptr, "location", location);
- location[0] /= width;
- location[1] /= height;
- BKE_mask_coord_from_frame(location, location, frame_size);
-
- /* Make it so new primitive is centered to mouse location. */
- location[0] -= 0.5f * scale;
- location[1] -= 0.5f * scale;
-
- bool added_mask = false;
- mask_layer = ED_mask_layer_ensure(C, &added_mask);
- mask = CTX_data_edit_mask(C);
-
- ED_mask_select_toggle_all(mask, SEL_DESELECT);
-
- new_spline = BKE_mask_spline_add(mask_layer);
- new_spline->flag = MASK_SPLINE_CYCLIC | SELECT;
- new_spline->points = MEM_recallocN(new_spline->points,
- sizeof(MaskSplinePoint) * num_points);
-
- mask_layer->act_spline = new_spline;
- mask_layer->act_point = NULL;
-
- const int spline_index = BKE_mask_layer_shape_spline_to_index(mask_layer, new_spline);
-
- for (i = 0; i < num_points; i++) {
- new_spline->tot_point = i + 1;
-
- MaskSplinePoint *new_point = &new_spline->points[i];
- BKE_mask_parent_init(&new_point->parent);
-
- copy_v2_v2(new_point->bezt.vec[1], points[i]);
- mul_v2_fl(new_point->bezt.vec[1], scale);
- add_v2_v2(new_point->bezt.vec[1], location);
-
- new_point->bezt.h1 = handle_type;
- new_point->bezt.h2 = handle_type;
- BKE_mask_point_select_set(new_point, true);
-
- if (mask_layer->splines_shapes.first) {
- BKE_mask_layer_shape_changed_add(mask_layer,
- spline_index + i,
- true, true);
- }
- }
-
- if (added_mask) {
- WM_event_add_notifier(C, NC_MASK | NA_ADDED, NULL);
- }
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
-
- /* TODO: only update this spline */
- BKE_mask_update_display(mask, CFRA);
-
- return OPERATOR_FINISHED;
+ ScrArea *sa = CTX_wm_area(C);
+ Scene *scene = CTX_data_scene(C);
+ Mask *mask;
+ MaskLayer *mask_layer;
+ MaskSpline *new_spline;
+ float scale, location[2], frame_size[2];
+ int i, width, height;
+ int size = RNA_float_get(op->ptr, "size");
+
+ ED_mask_get_size(sa, &width, &height);
+ scale = (float)size / max_ii(width, height);
+
+ /* Get location in mask space. */
+ frame_size[0] = width;
+ frame_size[1] = height;
+ RNA_float_get_array(op->ptr, "location", location);
+ location[0] /= width;
+ location[1] /= height;
+ BKE_mask_coord_from_frame(location, location, frame_size);
+
+ /* Make it so new primitive is centered to mouse location. */
+ location[0] -= 0.5f * scale;
+ location[1] -= 0.5f * scale;
+
+ bool added_mask = false;
+ mask_layer = ED_mask_layer_ensure(C, &added_mask);
+ mask = CTX_data_edit_mask(C);
+
+ ED_mask_select_toggle_all(mask, SEL_DESELECT);
+
+ new_spline = BKE_mask_spline_add(mask_layer);
+ new_spline->flag = MASK_SPLINE_CYCLIC | SELECT;
+ new_spline->points = MEM_recallocN(new_spline->points, sizeof(MaskSplinePoint) * num_points);
+
+ mask_layer->act_spline = new_spline;
+ mask_layer->act_point = NULL;
+
+ const int spline_index = BKE_mask_layer_shape_spline_to_index(mask_layer, new_spline);
+
+ for (i = 0; i < num_points; i++) {
+ new_spline->tot_point = i + 1;
+
+ MaskSplinePoint *new_point = &new_spline->points[i];
+ BKE_mask_parent_init(&new_point->parent);
+
+ copy_v2_v2(new_point->bezt.vec[1], points[i]);
+ mul_v2_fl(new_point->bezt.vec[1], scale);
+ add_v2_v2(new_point->bezt.vec[1], location);
+
+ new_point->bezt.h1 = handle_type;
+ new_point->bezt.h2 = handle_type;
+ BKE_mask_point_select_set(new_point, true);
+
+ if (mask_layer->splines_shapes.first) {
+ BKE_mask_layer_shape_changed_add(mask_layer, spline_index + i, true, true);
+ }
+ }
+
+ if (added_mask) {
+ WM_event_add_notifier(C, NC_MASK | NA_ADDED, NULL);
+ }
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+
+ /* TODO: only update this spline */
+ BKE_mask_update_display(mask, CFRA);
+
+ return OPERATOR_FINISHED;
}
static int primitive_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- ScrArea *sa = CTX_wm_area(C);
- float cursor[2];
- int width, height;
+ ScrArea *sa = 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(sa, &width, &height);
+ ED_mask_cursor_location_get(sa, cursor);
- cursor[0] *= width;
- cursor[1] *= height;
+ cursor[0] *= width;
+ cursor[1] *= height;
- RNA_float_set_array(op->ptr, "location", cursor);
+ RNA_float_set_array(op->ptr, "location", cursor);
- return op->type->exec(C, op);
+ return op->type->exec(C, op);
}
static void define_prinitive_add_properties(wmOperatorType *ot)
{
- RNA_def_float(ot->srna, "size", 100, -FLT_MAX, FLT_MAX,
- "Size", "Size of new circle", -FLT_MAX, FLT_MAX);
- RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
- "Location", "Location of new circle", -FLT_MAX, FLT_MAX);
+ RNA_def_float(
+ ot->srna, "size", 100, -FLT_MAX, FLT_MAX, "Size", "Size of new circle", -FLT_MAX, FLT_MAX);
+ RNA_def_float_vector(ot->srna,
+ "location",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Location",
+ "Location of new circle",
+ -FLT_MAX,
+ FLT_MAX);
}
/******************** primitive add circle *********************/
static int primitive_circle_add_exec(bContext *C, wmOperator *op)
{
- const float points[4][2] = {{0.0f, 0.5f},
- {0.5f, 1.0f},
- {1.0f, 0.5f},
- {0.5f, 0.0f}};
- int num_points = sizeof(points) / (2 * sizeof(float));
+ const float points[4][2] = {{0.0f, 0.5f}, {0.5f, 1.0f}, {1.0f, 0.5f}, {0.5f, 0.0f}};
+ int num_points = sizeof(points) / (2 * sizeof(float));
- create_primitive_from_points(C, op, points, num_points, HD_AUTO);
+ create_primitive_from_points(C, op, points, num_points, HD_AUTO);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MASK_OT_primitive_circle_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Circle";
- ot->description = "Add new circle-shaped spline";
- ot->idname = "MASK_OT_primitive_circle_add";
+ /* identifiers */
+ ot->name = "Add Circle";
+ ot->description = "Add new circle-shaped spline";
+ ot->idname = "MASK_OT_primitive_circle_add";
- /* api callbacks */
- ot->exec = primitive_circle_add_exec;
- ot->invoke = primitive_add_invoke;
- ot->poll = ED_operator_mask;
+ /* api callbacks */
+ ot->exec = primitive_circle_add_exec;
+ ot->invoke = primitive_add_invoke;
+ ot->poll = ED_operator_mask;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- define_prinitive_add_properties(ot);
+ /* properties */
+ define_prinitive_add_properties(ot);
}
/******************** primitive add suqare *********************/
static int primitive_square_add_exec(bContext *C, wmOperator *op)
{
- const float points[4][2] = {{0.0f, 0.0f},
- {0.0f, 1.0f},
- {1.0f, 1.0f},
- {1.0f, 0.0f}};
- int num_points = sizeof(points) / (2 * sizeof(float));
+ const float points[4][2] = {{0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}};
+ int num_points = sizeof(points) / (2 * sizeof(float));
- create_primitive_from_points(C, op, points, num_points, HD_VECT);
+ create_primitive_from_points(C, op, points, num_points, HD_VECT);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MASK_OT_primitive_square_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Square";
- ot->description = "Add new square-shaped spline";
- ot->idname = "MASK_OT_primitive_square_add";
+ /* identifiers */
+ ot->name = "Add Square";
+ ot->description = "Add new square-shaped spline";
+ ot->idname = "MASK_OT_primitive_square_add";
- /* api callbacks */
- ot->exec = primitive_square_add_exec;
- ot->invoke = primitive_add_invoke;
- ot->poll = ED_operator_mask;
+ /* api callbacks */
+ ot->exec = primitive_square_add_exec;
+ ot->invoke = primitive_add_invoke;
+ ot->poll = ED_operator_mask;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- define_prinitive_add_properties(ot);
+ /* properties */
+ define_prinitive_add_properties(ot);
}
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index 0164fe4cc03..479e4fd2d6c 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -33,11 +33,11 @@
#include "DNA_mask_types.h"
#include "DNA_screen_types.h"
-#include "DNA_object_types.h" /* SELECT */
+#include "DNA_object_types.h" /* SELECT */
#include "DNA_space_types.h"
#include "ED_clip.h"
-#include "ED_mask.h" /* own include */
+#include "ED_mask.h" /* own include */
#include "ED_space_api.h"
#include "BIF_glutil.h"
@@ -52,720 +52,761 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "mask_intern.h" /* own include */
+#include "mask_intern.h" /* own include */
-static void mask_spline_color_get(MaskLayer *masklay, MaskSpline *spline, const bool is_sel,
+static void mask_spline_color_get(MaskLayer *masklay,
+ MaskSpline *spline,
+ const bool is_sel,
unsigned char r_rgb[4])
{
- if (is_sel) {
- if (masklay->act_spline == spline) {
- r_rgb[0] = r_rgb[1] = r_rgb[2] = 255;
- }
- else {
- r_rgb[0] = 255;
- r_rgb[1] = r_rgb[2] = 0;
- }
- }
- else {
- r_rgb[0] = 128;
- r_rgb[1] = r_rgb[2] = 0;
- }
-
- r_rgb[3] = 255;
+ if (is_sel) {
+ if (masklay->act_spline == spline) {
+ r_rgb[0] = r_rgb[1] = r_rgb[2] = 255;
+ }
+ else {
+ r_rgb[0] = 255;
+ r_rgb[1] = r_rgb[2] = 0;
+ }
+ }
+ else {
+ r_rgb[0] = 128;
+ r_rgb[1] = r_rgb[2] = 0;
+ }
+
+ r_rgb[3] = 255;
}
-static void mask_spline_feather_color_get(MaskLayer *UNUSED(masklay), MaskSpline *UNUSED(spline), const bool is_sel,
+static void mask_spline_feather_color_get(MaskLayer *UNUSED(masklay),
+ MaskSpline *UNUSED(spline),
+ const bool is_sel,
unsigned char r_rgb[4])
{
- if (is_sel) {
- r_rgb[1] = 255;
- r_rgb[0] = r_rgb[2] = 0;
- }
- else {
- r_rgb[1] = 128;
- r_rgb[0] = r_rgb[2] = 0;
- }
-
- r_rgb[3] = 255;
+ if (is_sel) {
+ r_rgb[1] = 255;
+ r_rgb[0] = r_rgb[2] = 0;
+ }
+ else {
+ r_rgb[1] = 128;
+ r_rgb[0] = r_rgb[2] = 0;
+ }
+
+ r_rgb[3] = 255;
}
static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float co[2])
{
- BKE_mask_coord_to_movieclip(sc->clip, &sc->user, r_co, co);
- ED_clip_point_undistorted_pos(sc, r_co, r_co);
- BKE_mask_coord_from_movieclip(sc->clip, &sc->user, r_co, r_co);
+ BKE_mask_coord_to_movieclip(sc->clip, &sc->user, r_co, co);
+ ED_clip_point_undistorted_pos(sc, r_co, r_co);
+ BKE_mask_coord_from_movieclip(sc->clip, &sc->user, r_co, r_co);
}
-static void draw_single_handle(const MaskLayer *mask_layer, const MaskSplinePoint *point,
- const eMaskWhichHandle which_handle, const int draw_type,
+static void draw_single_handle(const MaskLayer *mask_layer,
+ const MaskSplinePoint *point,
+ const eMaskWhichHandle which_handle,
+ const int draw_type,
const float handle_size,
- const float point_pos[2], const float handle_pos[2])
+ const float point_pos[2],
+ const float handle_pos[2])
{
- const BezTriple *bezt = &point->bezt;
- char handle_type;
-
- if (which_handle == MASK_WHICH_HANDLE_STICK || which_handle == MASK_WHICH_HANDLE_LEFT) {
- handle_type = bezt->h1;
- }
- else {
- handle_type = bezt->h2;
- }
-
- if (handle_type == HD_VECT) {
- return;
- }
-
- 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};
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3ubv(rgb_gray);
-
- /* this could be split into its own loop */
- if (draw_type == MASK_DT_OUTLINE) {
- GPU_line_width(3.0f);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2fv(pos, point_pos);
- immVertex2fv(pos, handle_pos);
- immEnd();
- }
-
- switch (handle_type) {
- case HD_FREE:
- immUniformThemeColor(TH_HANDLE_FREE);
- break;
- case HD_AUTO:
- immUniformThemeColor(TH_HANDLE_AUTO);
- break;
- case HD_ALIGN:
- case HD_ALIGN_DOUBLESIDE:
- immUniformThemeColor(TH_HANDLE_ALIGN);
- break;
- }
-
- GPU_line_width(1.0f);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2fv(pos, point_pos);
- immVertex2fv(pos, handle_pos);
- immEnd();
- immUnbindProgram();
-
- /* draw handle points */
- immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
- immUniform1f("size", handle_size);
- immUniform1f("outlineWidth", 1.5f);
-
- float point_color[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; /* active color by default */
- if (MASKPOINT_ISSEL_HANDLE(point, which_handle)) {
- if (point != mask_layer->act_point) {
- UI_GetThemeColor3fv(TH_HANDLE_VERTEX_SELECT, point_color);
- }
- }
- else {
- UI_GetThemeColor3fv(TH_HANDLE_VERTEX, point_color);
- }
-
- immUniform4fv("outlineColor", point_color);
- immUniformColor3fvAlpha(point_color, 0.25f);
-
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex2fv(pos, handle_pos);
- immEnd();
-
- immUnbindProgram();
+ const BezTriple *bezt = &point->bezt;
+ char handle_type;
+
+ if (which_handle == MASK_WHICH_HANDLE_STICK || which_handle == MASK_WHICH_HANDLE_LEFT) {
+ handle_type = bezt->h1;
+ }
+ else {
+ handle_type = bezt->h2;
+ }
+
+ if (handle_type == HD_VECT) {
+ return;
+ }
+
+ 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};
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3ubv(rgb_gray);
+
+ /* this could be split into its own loop */
+ if (draw_type == MASK_DT_OUTLINE) {
+ GPU_line_width(3.0f);
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2fv(pos, point_pos);
+ immVertex2fv(pos, handle_pos);
+ immEnd();
+ }
+
+ switch (handle_type) {
+ case HD_FREE:
+ immUniformThemeColor(TH_HANDLE_FREE);
+ break;
+ case HD_AUTO:
+ immUniformThemeColor(TH_HANDLE_AUTO);
+ break;
+ case HD_ALIGN:
+ case HD_ALIGN_DOUBLESIDE:
+ immUniformThemeColor(TH_HANDLE_ALIGN);
+ break;
+ }
+
+ GPU_line_width(1.0f);
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2fv(pos, point_pos);
+ immVertex2fv(pos, handle_pos);
+ immEnd();
+ immUnbindProgram();
+
+ /* draw handle points */
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
+ immUniform1f("size", handle_size);
+ immUniform1f("outlineWidth", 1.5f);
+
+ float point_color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; /* active color by default */
+ if (MASKPOINT_ISSEL_HANDLE(point, which_handle)) {
+ if (point != mask_layer->act_point) {
+ UI_GetThemeColor3fv(TH_HANDLE_VERTEX_SELECT, point_color);
+ }
+ }
+ else {
+ UI_GetThemeColor3fv(TH_HANDLE_VERTEX, point_color);
+ }
+
+ immUniform4fv("outlineColor", point_color);
+ immUniformColor3fvAlpha(point_color, 0.25f);
+
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex2fv(pos, handle_pos);
+ immEnd();
+
+ immUnbindProgram();
}
/* return non-zero if spline is selected */
-static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline *spline,
- const char draw_flag, const char draw_type)
+static void draw_spline_points(const bContext *C,
+ MaskLayer *masklay,
+ MaskSpline *spline,
+ const char draw_flag,
+ const char draw_type)
{
- const bool is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0;
- const bool is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH) != 0;
-
- unsigned char rgb_spline[4];
- MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
- SpaceClip *sc = CTX_wm_space_clip(C);
- bool undistort = false;
-
- int tot_feather_point;
- float (*feather_points)[2], (*fp)[2];
- float min[2], max[2];
-
- if (!spline->tot_point)
- return;
-
- if (sc)
- undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT);
-
- /* TODO, add this to sequence editor */
- float handle_size = 2.0f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize;
-
- mask_spline_color_get(masklay, spline, is_spline_sel, rgb_spline);
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
- immUniform1f("size", 0.7f * handle_size);
-
- /* feather points */
- feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point);
- for (int i = 0; i < spline->tot_point; i++) {
-
- /* watch it! this is intentionally not the deform array, only check for sel */
- MaskSplinePoint *point = &spline->points[i];
-
- for (int j = 0; j <= point->tot_uw; j++) {
- float feather_point[2];
- bool sel = false;
-
- copy_v2_v2(feather_point, *fp);
-
- if (undistort)
- mask_point_undistort_pos(sc, feather_point, feather_point);
-
- if (j == 0) {
- sel = MASKPOINT_ISSEL_ANY(point);
- }
- else {
- sel = (point->uw[j - 1].flag & SELECT) != 0;
- }
-
- if (sel) {
- if (point == masklay->act_point)
- immUniformColor3f(1.0f, 1.0f, 1.0f);
- else
- immUniformThemeColorShadeAlpha(TH_HANDLE_VERTEX_SELECT, 0, 255);
- }
- else {
- immUniformThemeColorShadeAlpha(TH_HANDLE_VERTEX, 0, 255);
- }
-
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex2fv(pos, feather_point);
- immEnd();
-
- fp++;
- }
- }
- MEM_freeN(feather_points);
-
- immUnbindProgram();
-
- if (is_smooth) {
- GPU_line_smooth(true);
- }
-
- /* control points */
- INIT_MINMAX2(min, max);
- for (int i = 0; i < spline->tot_point; i++) {
-
- /* watch it! this is intentionally not the deform array, only check for sel */
- MaskSplinePoint *point = &spline->points[i];
- MaskSplinePoint *point_deform = &points_array[i];
- BezTriple *bezt = &point_deform->bezt;
-
- float vert[2];
-
- copy_v2_v2(vert, bezt->vec[1]);
-
- if (undistort) {
- mask_point_undistort_pos(sc, vert, vert);
- }
-
- /* draw handle segment */
- if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
- float handle[2];
- BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_STICK, handle);
- if (undistort) {
- mask_point_undistort_pos(sc, handle, handle);
- }
- draw_single_handle(masklay, point, MASK_WHICH_HANDLE_STICK,
- draw_type, handle_size, vert, handle);
- }
- else {
- float handle_left[2], handle_right[2];
- BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_LEFT, handle_left);
- BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_RIGHT, handle_right);
- if (undistort) {
- mask_point_undistort_pos(sc, handle_left, handle_left);
- mask_point_undistort_pos(sc, handle_left, handle_left);
- }
- draw_single_handle(masklay, point, MASK_WHICH_HANDLE_LEFT,
- draw_type, handle_size, vert, handle_left);
- draw_single_handle(masklay, point, MASK_WHICH_HANDLE_RIGHT,
- draw_type, handle_size, vert, handle_right);
- }
-
- /* bind program in loop so it does not interfere with draw_single_handle */
- immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
-
- /* draw CV point */
- if (MASKPOINT_ISSEL_KNOT(point)) {
- if (point == masklay->act_point)
- immUniformColor3f(1.0f, 1.0f, 1.0f);
- else
- immUniformThemeColorShadeAlpha(TH_HANDLE_VERTEX_SELECT, 0, 255);
- }
- else
- immUniformThemeColorShadeAlpha(TH_HANDLE_VERTEX, 0, 255);
-
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex2fv(pos, vert);
- immEnd();
-
- immUnbindProgram();
-
- minmax_v2v2_v2(min, max, vert);
- }
-
- if (is_smooth) {
- GPU_line_smooth(false);
- }
-
- if (is_spline_sel) {
- float x = (min[0] + max[0]) * 0.5f;
- float y = (min[1] + max[1]) * 0.5f;
-
- immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
- immUniform1f("outlineWidth", 1.5f);
-
- if (masklay->act_spline == spline) {
- immUniformColor3f(1.0f, 1.0f, 1.0f);
- }
- else {
- immUniformColor3f(1.0f, 1.0f, 0.0f);
- }
-
- immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 1.0f);
- immUniform1f("size", 12.0f);
-
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex2f(pos, x, y);
- immEnd();
-
- immUnbindProgram();
- }
+ const bool is_spline_sel = (spline->flag & SELECT) &&
+ (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0;
+ const bool is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH) != 0;
+
+ unsigned char rgb_spline[4];
+ MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ bool undistort = false;
+
+ int tot_feather_point;
+ float(*feather_points)[2], (*fp)[2];
+ float min[2], max[2];
+
+ if (!spline->tot_point)
+ return;
+
+ if (sc)
+ undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT);
+
+ /* TODO, add this to sequence editor */
+ float handle_size = 2.0f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize;
+
+ mask_spline_color_get(masklay, spline, is_spline_sel, rgb_spline);
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
+ immUniform1f("size", 0.7f * handle_size);
+
+ /* feather points */
+ feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point);
+ for (int i = 0; i < spline->tot_point; i++) {
+
+ /* watch it! this is intentionally not the deform array, only check for sel */
+ MaskSplinePoint *point = &spline->points[i];
+
+ for (int j = 0; j <= point->tot_uw; j++) {
+ float feather_point[2];
+ bool sel = false;
+
+ copy_v2_v2(feather_point, *fp);
+
+ if (undistort)
+ mask_point_undistort_pos(sc, feather_point, feather_point);
+
+ if (j == 0) {
+ sel = MASKPOINT_ISSEL_ANY(point);
+ }
+ else {
+ sel = (point->uw[j - 1].flag & SELECT) != 0;
+ }
+
+ if (sel) {
+ if (point == masklay->act_point)
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
+ else
+ immUniformThemeColorShadeAlpha(TH_HANDLE_VERTEX_SELECT, 0, 255);
+ }
+ else {
+ immUniformThemeColorShadeAlpha(TH_HANDLE_VERTEX, 0, 255);
+ }
+
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex2fv(pos, feather_point);
+ immEnd();
+
+ fp++;
+ }
+ }
+ MEM_freeN(feather_points);
+
+ immUnbindProgram();
+
+ if (is_smooth) {
+ GPU_line_smooth(true);
+ }
+
+ /* control points */
+ INIT_MINMAX2(min, max);
+ for (int i = 0; i < spline->tot_point; i++) {
+
+ /* watch it! this is intentionally not the deform array, only check for sel */
+ MaskSplinePoint *point = &spline->points[i];
+ MaskSplinePoint *point_deform = &points_array[i];
+ BezTriple *bezt = &point_deform->bezt;
+
+ float vert[2];
+
+ copy_v2_v2(vert, bezt->vec[1]);
+
+ if (undistort) {
+ mask_point_undistort_pos(sc, vert, vert);
+ }
+
+ /* draw handle segment */
+ if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
+ float handle[2];
+ BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_STICK, handle);
+ if (undistort) {
+ mask_point_undistort_pos(sc, handle, handle);
+ }
+ draw_single_handle(
+ masklay, point, MASK_WHICH_HANDLE_STICK, draw_type, handle_size, vert, handle);
+ }
+ else {
+ float handle_left[2], handle_right[2];
+ BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_LEFT, handle_left);
+ BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_RIGHT, handle_right);
+ if (undistort) {
+ mask_point_undistort_pos(sc, handle_left, handle_left);
+ mask_point_undistort_pos(sc, handle_left, handle_left);
+ }
+ draw_single_handle(
+ masklay, point, MASK_WHICH_HANDLE_LEFT, draw_type, handle_size, vert, handle_left);
+ draw_single_handle(
+ masklay, point, MASK_WHICH_HANDLE_RIGHT, draw_type, handle_size, vert, handle_right);
+ }
+
+ /* bind program in loop so it does not interfere with draw_single_handle */
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
+
+ /* draw CV point */
+ if (MASKPOINT_ISSEL_KNOT(point)) {
+ if (point == masklay->act_point)
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
+ else
+ immUniformThemeColorShadeAlpha(TH_HANDLE_VERTEX_SELECT, 0, 255);
+ }
+ else
+ immUniformThemeColorShadeAlpha(TH_HANDLE_VERTEX, 0, 255);
+
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex2fv(pos, vert);
+ immEnd();
+
+ immUnbindProgram();
+
+ minmax_v2v2_v2(min, max, vert);
+ }
+
+ if (is_smooth) {
+ GPU_line_smooth(false);
+ }
+
+ if (is_spline_sel) {
+ float x = (min[0] + max[0]) * 0.5f;
+ float y = (min[1] + max[1]) * 0.5f;
+
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
+ immUniform1f("outlineWidth", 1.5f);
+
+ if (masklay->act_spline == spline) {
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
+ }
+ else {
+ immUniformColor3f(1.0f, 1.0f, 0.0f);
+ }
+
+ immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 1.0f);
+ immUniform1f("size", 12.0f);
+
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex2f(pos, x, y);
+ immEnd();
+
+ immUnbindProgram();
+ }
}
-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(unsigned char r_rgb[4],
+ const unsigned char 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[3] = rgb[3];
- }
- else {
- *(unsigned int *)r_rgb = *(const unsigned int *)rgb;
- }
+ 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[3] = rgb[3];
+ }
+ else {
+ *(unsigned int *)r_rgb = *(const unsigned int *)rgb;
+ }
}
-static void mask_draw_array(unsigned int pos, GPUPrimType prim_type, const float (*points)[2], unsigned int vertex_len)
+static void mask_draw_array(unsigned int pos,
+ GPUPrimType prim_type,
+ const float (*points)[2],
+ unsigned int vertex_len)
{
- immBegin(prim_type, vertex_len);
- for (unsigned int i = 0; i < vertex_len; ++i) {
- immVertex2fv(pos, points[i]);
- }
- immEnd();
+ immBegin(prim_type, vertex_len);
+ for (unsigned int i = 0; i < vertex_len; ++i) {
+ immVertex2fv(pos, points[i]);
+ }
+ immEnd();
}
-static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*orig_points)[2], int tot_point,
- const bool is_feather, const bool is_active,
- const unsigned char rgb_spline[4], const char draw_type)
+static void mask_draw_curve_type(const bContext *C,
+ MaskSpline *spline,
+ float (*orig_points)[2],
+ int tot_point,
+ const bool is_feather,
+ const bool is_active,
+ const unsigned char 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];
- SpaceClip *sc = CTX_wm_space_clip(C);
- float (*points)[2] = orig_points;
-
- if (sc) {
- const bool undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT);
-
- if (undistort) {
- points = MEM_callocN(2 * tot_point * sizeof(float), "undistorthed mask curve");
-
- for (int i = 0; i < tot_point; i++) {
- mask_point_undistort_pos(sc, points[i], orig_points[i]);
- }
- }
- }
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- switch (draw_type) {
-
- case MASK_DT_OUTLINE:
- /* TODO(merwin): use fancy line shader here
- * probably better with geometry shader (after core profile switch)
- */
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- GPU_line_width(3.0f);
-
- mask_color_active_tint(rgb_tmp, rgb_black, is_active);
- immUniformColor4ubv(rgb_tmp);
- mask_draw_array(pos, draw_method, points, tot_point);
-
- GPU_line_width(1.0f);
-
- mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
- immUniformColor4ubv(rgb_tmp);
- mask_draw_array(pos, draw_method, points, tot_point);
-
- immUnbindProgram();
- break;
-
- case MASK_DT_BLACK:
- case MASK_DT_WHITE:
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- GPU_line_width(1.0f);
-
- if (draw_type == MASK_DT_BLACK) { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 0; }
- else { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 255; }
- /* alpha values seem too low but gl draws many points that compensate for it */
- if (is_feather) { rgb_tmp[3] = 64; }
- else { rgb_tmp[3] = 128; }
-
- 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);
- }
-
- mask_color_active_tint(rgb_tmp, rgb_tmp, is_active);
- immUniformColor4ubv(rgb_tmp);
- mask_draw_array(pos, draw_method, points, tot_point);
-
- immUnbindProgram();
- break;
+ 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];
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ float(*points)[2] = orig_points;
+
+ if (sc) {
+ const bool undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT);
+
+ if (undistort) {
+ points = MEM_callocN(2 * tot_point * sizeof(float), "undistorthed mask curve");
+
+ for (int i = 0; i < tot_point; i++) {
+ mask_point_undistort_pos(sc, points[i], orig_points[i]);
+ }
+ }
+ }
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ switch (draw_type) {
+
+ case MASK_DT_OUTLINE:
+ /* TODO(merwin): use fancy line shader here
+ * probably better with geometry shader (after core profile switch)
+ */
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ GPU_line_width(3.0f);
+
+ mask_color_active_tint(rgb_tmp, rgb_black, is_active);
+ immUniformColor4ubv(rgb_tmp);
+ mask_draw_array(pos, draw_method, points, tot_point);
+
+ GPU_line_width(1.0f);
+
+ mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
+ immUniformColor4ubv(rgb_tmp);
+ mask_draw_array(pos, draw_method, points, tot_point);
+
+ immUnbindProgram();
+ break;
+
+ case MASK_DT_BLACK:
+ case MASK_DT_WHITE:
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ GPU_line_width(1.0f);
+
+ if (draw_type == MASK_DT_BLACK) {
+ rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 0;
+ }
+ else {
+ rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 255;
+ }
+ /* alpha values seem too low but gl draws many points that compensate for it */
+ if (is_feather) {
+ rgb_tmp[3] = 64;
+ }
+ else {
+ rgb_tmp[3] = 128;
+ }
+
+ 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);
+ }
+
+ mask_color_active_tint(rgb_tmp, rgb_tmp, is_active);
+ immUniformColor4ubv(rgb_tmp);
+ mask_draw_array(pos, draw_method, points, tot_point);
+
+ immUnbindProgram();
+ break;
+
+ case MASK_DT_DASH: {
+ float colors[8];
+
+ mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
+ rgba_uchar_to_float(colors, rgb_tmp);
+ mask_color_active_tint(rgb_tmp, rgb_black, is_active);
+ rgba_uchar_to_float(colors + 4, rgb_tmp);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("colors_len", 2); /* "advanced" mode */
+ immUniformArray4fv("colors", colors, 2);
+ immUniform1f("dash_width", 4.0f);
+ GPU_line_width(1.0f);
+
+ mask_draw_array(pos, draw_method, points, tot_point);
+
+ immUnbindProgram();
+ break;
+ }
+
+ default:
+ BLI_assert(false);
+ }
- case MASK_DT_DASH:
- {
- float colors[8];
-
- mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
- rgba_uchar_to_float(colors, rgb_tmp);
- mask_color_active_tint(rgb_tmp, rgb_black, is_active);
- rgba_uchar_to_float(colors + 4, rgb_tmp);
-
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
-
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
-
- immUniform1i("colors_len", 2); /* "advanced" mode */
- immUniformArray4fv("colors", colors, 2);
- immUniform1f("dash_width", 4.0f);
- GPU_line_width(1.0f);
-
- mask_draw_array(pos, draw_method, points, tot_point);
-
- immUnbindProgram();
- break;
- }
-
- default:
- BLI_assert(false);
- }
-
- if (points != orig_points)
- MEM_freeN(points);
+ if (points != orig_points)
+ MEM_freeN(points);
}
-static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline *spline,
- const char draw_flag, const char draw_type,
+static void draw_spline_curve(const bContext *C,
+ MaskLayer *masklay,
+ MaskSpline *spline,
+ const char draw_flag,
+ const char draw_type,
const bool is_active,
- const int width, const int height)
+ 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 unsigned int resol = max_ii(BKE_mask_spline_feather_resolution(spline, width, height),
+ BKE_mask_spline_resolution(spline, width, height));
- unsigned char rgb_tmp[4];
+ unsigned char rgb_tmp[4];
- const bool is_spline_sel = (spline->flag & SELECT) && (masklay->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;
+ const bool is_spline_sel = (spline->flag & SELECT) &&
+ (masklay->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;
- float (*diff_points)[2];
+ unsigned int tot_diff_point;
+ float(*diff_points)[2];
- unsigned int tot_feather_point;
- float (*feather_points)[2];
+ unsigned int tot_feather_point;
+ float(*feather_points)[2];
- diff_points = BKE_mask_spline_differentiate_with_resolution(spline, &tot_diff_point, resol);
+ diff_points = BKE_mask_spline_differentiate_with_resolution(spline, &tot_diff_point, resol);
- if (!diff_points)
- return;
+ if (!diff_points)
+ return;
- if (is_smooth) {
- GPU_line_smooth(true);
- }
+ if (is_smooth) {
+ GPU_line_smooth(true);
+ }
- feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution(spline, &tot_feather_point, resol, (is_fill != false));
+ feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution(
+ spline, &tot_feather_point, resol, (is_fill != false));
- /* draw feather */
- mask_spline_feather_color_get(masklay, spline, is_spline_sel, rgb_tmp);
- mask_draw_curve_type(C, spline, feather_points, tot_feather_point,
- true, is_active,
- rgb_tmp, draw_type);
+ /* draw feather */
+ mask_spline_feather_color_get(masklay, spline, is_spline_sel, rgb_tmp);
+ mask_draw_curve_type(
+ C, spline, feather_points, tot_feather_point, true, is_active, rgb_tmp, draw_type);
- if (!is_fill) {
- const float *fp = &diff_points[0][0];
- float *fp_feather = &feather_points[0][0];
+ if (!is_fill) {
+ const float *fp = &diff_points[0][0];
+ float *fp_feather = &feather_points[0][0];
- BLI_assert(tot_diff_point == tot_feather_point);
+ BLI_assert(tot_diff_point == tot_feather_point);
- for (int i = 0; i < tot_diff_point; i++, fp += 2, fp_feather += 2) {
- float tvec[2];
- sub_v2_v2v2(tvec, fp, fp_feather);
- add_v2_v2v2(fp_feather, fp, tvec);
- }
+ for (int i = 0; i < tot_diff_point; i++, fp += 2, fp_feather += 2) {
+ float tvec[2];
+ sub_v2_v2v2(tvec, fp, fp_feather);
+ add_v2_v2v2(fp_feather, fp, tvec);
+ }
- /* same as above */
- mask_draw_curve_type(C, spline, feather_points, tot_feather_point,
- true, is_active,
- rgb_tmp, draw_type);
- }
+ /* same as above */
+ mask_draw_curve_type(
+ C, spline, feather_points, tot_feather_point, true, is_active, rgb_tmp, draw_type);
+ }
- MEM_freeN(feather_points);
+ MEM_freeN(feather_points);
- /* draw main curve */
- mask_spline_color_get(masklay, spline, is_spline_sel, rgb_tmp);
- mask_draw_curve_type(C, spline, diff_points, tot_diff_point,
- false, is_active,
- rgb_tmp, draw_type);
- MEM_freeN(diff_points);
+ /* draw main curve */
+ mask_spline_color_get(masklay, spline, is_spline_sel, rgb_tmp);
+ mask_draw_curve_type(
+ C, spline, diff_points, tot_diff_point, false, is_active, rgb_tmp, draw_type);
+ MEM_freeN(diff_points);
- if (is_smooth) {
- GPU_line_smooth(false);
- }
+ if (is_smooth) {
+ GPU_line_smooth(false);
+ }
}
-static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, const char draw_type,
- const int width, const int height)
+static void draw_masklays(const bContext *C,
+ Mask *mask,
+ const char draw_flag,
+ const char draw_type,
+ const int width,
+ const int height)
{
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_enable_program_point_size();
-
- MaskLayer *masklay;
- int i;
-
- for (masklay = mask->masklayers.first, i = 0; masklay; masklay = masklay->next, i++) {
- MaskSpline *spline;
- const bool is_active = (i == mask->masklay_act);
-
- if (masklay->restrictflag & MASK_RESTRICT_VIEW) {
- continue;
- }
-
- for (spline = masklay->splines.first; spline; spline = spline->next) {
-
- /* draw curve itself first... */
- draw_spline_curve(C, masklay, spline, draw_flag, draw_type, is_active, width, height);
-
- if (!(masklay->restrictflag & MASK_RESTRICT_SELECT)) {
- /* ...and then handles over the curve so they're nicely visible */
- draw_spline_points(C, masklay, spline, draw_flag, draw_type);
- }
-
- /* show undeform for testing */
- if (0) {
- void *back = spline->points_deform;
-
- spline->points_deform = NULL;
- draw_spline_curve(C, masklay, spline, draw_flag, draw_type, is_active, width, height);
- draw_spline_points(C, masklay, spline, draw_flag, draw_type);
- spline->points_deform = back;
- }
- }
- }
-
- GPU_disable_program_point_size();
- GPU_blend(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_enable_program_point_size();
+
+ MaskLayer *masklay;
+ int i;
+
+ for (masklay = mask->masklayers.first, i = 0; masklay; masklay = masklay->next, i++) {
+ MaskSpline *spline;
+ const bool is_active = (i == mask->masklay_act);
+
+ if (masklay->restrictflag & MASK_RESTRICT_VIEW) {
+ continue;
+ }
+
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+
+ /* draw curve itself first... */
+ draw_spline_curve(C, masklay, spline, draw_flag, draw_type, is_active, width, height);
+
+ if (!(masklay->restrictflag & MASK_RESTRICT_SELECT)) {
+ /* ...and then handles over the curve so they're nicely visible */
+ draw_spline_points(C, masklay, spline, draw_flag, draw_type);
+ }
+
+ /* show undeform for testing */
+ if (0) {
+ void *back = spline->points_deform;
+
+ spline->points_deform = NULL;
+ draw_spline_curve(C, masklay, spline, draw_flag, draw_type, is_active, width, height);
+ draw_spline_points(C, masklay, spline, draw_flag, draw_type);
+ spline->points_deform = back;
+ }
+ }
+ }
+
+ GPU_disable_program_point_size();
+ GPU_blend(false);
}
-void ED_mask_draw(const bContext *C,
- const char draw_flag, const char draw_type)
+void ED_mask_draw(const bContext *C, const char draw_flag, const char draw_type)
{
- ScrArea *sa = CTX_wm_area(C);
- Mask *mask = CTX_data_edit_mask(C);
- int width, height;
+ ScrArea *sa = CTX_wm_area(C);
+ Mask *mask = CTX_data_edit_mask(C);
+ int width, height;
- if (!mask)
- return;
+ if (!mask)
+ return;
- ED_mask_get_size(sa, &width, &height);
+ ED_mask_get_size(sa, &width, &height);
- draw_masklays(C, mask, draw_flag, draw_type, width, height);
+ draw_masklays(C, mask, draw_flag, draw_type, width, height);
}
static float *mask_rasterize(Mask *mask, const int width, const int height)
{
- MaskRasterHandle *handle;
- float *buffer = MEM_mallocN(sizeof(float) * height * width, "rasterized mask buffer");
+ MaskRasterHandle *handle;
+ float *buffer = MEM_mallocN(sizeof(float) * height * width, "rasterized mask buffer");
- /* Initialize rasterization handle. */
- handle = BKE_maskrasterize_handle_new();
- BKE_maskrasterize_handle_init(handle, mask, width, height, true, true, true);
+ /* Initialize rasterization handle. */
+ handle = BKE_maskrasterize_handle_new();
+ BKE_maskrasterize_handle_init(handle, mask, width, height, true, true, true);
- BKE_maskrasterize_buffer(handle, width, height, buffer);
+ BKE_maskrasterize_buffer(handle, width, height, buffer);
- /* Free memory. */
- BKE_maskrasterize_handle_free(handle);
+ /* Free memory. */
+ BKE_maskrasterize_handle_free(handle);
- return buffer;
+ return buffer;
}
/* sets up the opengl context.
* width, height are to match the values from ED_mask_get_size() */
void ED_mask_draw_region(
- Mask *mask, ARegion *ar,
- const char draw_flag, const char draw_type, const char overlay_mode,
- /* convert directly into aspect corrected vars */
- const int width_i, const int height_i,
- const float aspx, const float aspy,
- const bool do_scale_applied, const bool do_draw_cb,
- /* optional - only used by clip */
- float stabmat[4][4],
- /* optional - only used when do_post_draw is set or called from clip editor */
- const bContext *C)
+ Mask *mask,
+ ARegion *ar,
+ const char draw_flag,
+ const char draw_type,
+ const char overlay_mode,
+ /* convert directly into aspect corrected vars */
+ const int width_i,
+ const int height_i,
+ const float aspx,
+ const float aspy,
+ const bool do_scale_applied,
+ const bool do_draw_cb,
+ /* optional - only used by clip */
+ float stabmat[4][4],
+ /* optional - only used when do_post_draw is set or called from clip editor */
+ const bContext *C)
{
- struct View2D *v2d = &ar->v2d;
-
- /* aspect always scales vertically in movie and image spaces */
- const float width = width_i, height = (float)height_i * (aspy / aspx);
-
- int x, y;
- /* int w, h; */
- float zoomx, zoomy;
-
- /* frame image */
- float maxdim;
- float xofs, yofs;
-
- /* find window pixel coordinates of origin */
- UI_view2d_view_to_region(&ar->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);
-
- if (do_scale_applied) {
- zoomx /= width;
- zoomy /= height;
- }
-
- x += v2d->tot.xmin * zoomx;
- y += v2d->tot.ymin * zoomy;
-
- /* frame the image */
- maxdim = max_ff(width, height);
- if (width == height) {
- xofs = yofs = 0;
- }
- else if (width < height) {
- xofs = ((height - width) / -2.0f) * zoomx;
- yofs = 0.0f;
- }
- else { /* (width > height) */
- xofs = 0.0f;
- yofs = ((width - height) / -2.0f) * zoomy;
- }
-
- if (draw_flag & MASK_DRAWFLAG_OVERLAY) {
- float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
- float *buffer = mask_rasterize(mask, width, height);
-
- if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) {
- /* More blending types could be supported in the future. */
- GPU_blend(true);
- GPU_blend_set_func(GPU_DST_COLOR, GPU_ZERO);
- }
-
- GPU_matrix_push();
- GPU_matrix_translate_2f(x, y);
- GPU_matrix_scale_2f(zoomx, zoomy);
- if (stabmat) {
- GPU_matrix_mul(stabmat);
- }
- IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
- GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red);
- immDrawPixelsTex(&state, 0.0f, 0.0f, width, height, GL_RED, GL_FLOAT, GL_NEAREST, buffer, 1.0f, 1.0f, NULL);
-
- GPU_matrix_pop();
-
- if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) {
- GPU_blend(false);
- }
-
- MEM_freeN(buffer);
- }
-
- /* apply transformation so mask editing tools will assume drawing from the
- * origin in normalized space */
- GPU_matrix_push();
- GPU_matrix_translate_2f(x + xofs, y + yofs);
- GPU_matrix_scale_2f(zoomx, zoomy);
- if (stabmat) {
- GPU_matrix_mul(stabmat);
- }
- GPU_matrix_scale_2f(maxdim, maxdim);
-
- if (do_draw_cb) {
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
- }
-
- /* draw! */
- draw_masklays(C, mask, draw_flag, draw_type, width, height);
-
- if (do_draw_cb) {
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
- }
-
- GPU_matrix_pop();
+ struct View2D *v2d = &ar->v2d;
+
+ /* aspect always scales vertically in movie and image spaces */
+ const float width = width_i, height = (float)height_i * (aspy / aspx);
+
+ int x, y;
+ /* int w, h; */
+ float zoomx, zoomy;
+
+ /* frame image */
+ float maxdim;
+ float xofs, yofs;
+
+ /* find window pixel coordinates of origin */
+ UI_view2d_view_to_region(&ar->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);
+
+ if (do_scale_applied) {
+ zoomx /= width;
+ zoomy /= height;
+ }
+
+ x += v2d->tot.xmin * zoomx;
+ y += v2d->tot.ymin * zoomy;
+
+ /* frame the image */
+ maxdim = max_ff(width, height);
+ if (width == height) {
+ xofs = yofs = 0;
+ }
+ else if (width < height) {
+ xofs = ((height - width) / -2.0f) * zoomx;
+ yofs = 0.0f;
+ }
+ else { /* (width > height) */
+ xofs = 0.0f;
+ yofs = ((width - height) / -2.0f) * zoomy;
+ }
+
+ if (draw_flag & MASK_DRAWFLAG_OVERLAY) {
+ float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
+ float *buffer = mask_rasterize(mask, width, height);
+
+ if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) {
+ /* More blending types could be supported in the future. */
+ GPU_blend(true);
+ GPU_blend_set_func(GPU_DST_COLOR, GPU_ZERO);
+ }
+
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(x, y);
+ GPU_matrix_scale_2f(zoomx, zoomy);
+ if (stabmat) {
+ GPU_matrix_mul(stabmat);
+ }
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_uniform_vector(
+ state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red);
+ immDrawPixelsTex(
+ &state, 0.0f, 0.0f, width, height, GL_RED, GL_FLOAT, GL_NEAREST, buffer, 1.0f, 1.0f, NULL);
+
+ GPU_matrix_pop();
+
+ if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) {
+ GPU_blend(false);
+ }
+
+ MEM_freeN(buffer);
+ }
+
+ /* apply transformation so mask editing tools will assume drawing from the
+ * origin in normalized space */
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(x + xofs, y + yofs);
+ GPU_matrix_scale_2f(zoomx, zoomy);
+ if (stabmat) {
+ GPU_matrix_mul(stabmat);
+ }
+ GPU_matrix_scale_2f(maxdim, maxdim);
+
+ if (do_draw_cb) {
+ ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
+ }
+
+ /* draw! */
+ draw_masklays(C, mask, draw_flag, draw_type, width, height);
+
+ if (do_draw_cb) {
+ ED_region_draw_cb_draw(C, ar, 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)
{
- const float framelen = ar->winx / (float)(efra - sfra + 1);
+ const float framelen = ar->winx / (float)(efra - sfra + 1);
- MaskLayer *masklay = BKE_mask_layer_active(mask);
+ MaskLayer *masklay = BKE_mask_layer_active(mask);
- if (masklay) {
- unsigned int num_lines = BLI_listbase_count(&masklay->splines_shapes);
+ if (masklay) {
+ unsigned int num_lines = BLI_listbase_count(&masklay->splines_shapes);
- if (num_lines > 0) {
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ if (num_lines > 0) {
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4ub(255, 175, 0, 255);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ub(255, 175, 0, 255);
- immBegin(GPU_PRIM_LINES, 2 * num_lines);
+ immBegin(GPU_PRIM_LINES, 2 * num_lines);
- for (MaskLayerShape *masklay_shape = masklay->splines_shapes.first;
- masklay_shape;
- masklay_shape = masklay_shape->next)
- {
- int frame = masklay_shape->frame;
+ for (MaskLayerShape *masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape->next) {
+ int frame = masklay_shape->frame;
- /* draw_keyframe(i, CFRA, sfra, framelen, 1); */
- int height = (frame == cfra) ? 22 : 10;
- int x = (frame - sfra) * framelen;
- immVertex2i(pos, x, 0);
- immVertex2i(pos, x, height);
- }
- immEnd();
- immUnbindProgram();
- }
- }
+ /* draw_keyframe(i, CFRA, sfra, framelen, 1); */
+ int height = (frame == cfra) ? 22 : 10;
+ int x = (frame - sfra) * framelen;
+ immVertex2i(pos, x, 0);
+ immVertex2i(pos, x, height);
+ }
+ immEnd();
+ immUnbindProgram();
+ }
+ }
}
diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c
index a2deaac30ac..7325686d4f0 100644
--- a/source/blender/editors/mask/mask_edit.c
+++ b/source/blender/editors/mask/mask_edit.c
@@ -21,7 +21,6 @@
* \ingroup edmask
*/
-
#include "BLI_math.h"
#include "BKE_context.h"
@@ -35,7 +34,7 @@
#include "ED_screen.h"
#include "ED_select_utils.h"
-#include "ED_mask.h" /* own include */
+#include "ED_mask.h" /* own include */
#include "ED_image.h"
#include "ED_object.h" /* ED_keymap_proportional_maskmode only */
#include "ED_clip.h"
@@ -46,40 +45,40 @@
#include "RNA_access.h"
-#include "mask_intern.h" /* own include */
+#include "mask_intern.h" /* own include */
/********************** generic poll functions *********************/
bool ED_maskedit_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- if (sa) {
- switch (sa->spacetype) {
- case SPACE_CLIP:
- return ED_space_clip_maskedit_poll(C);
- case SPACE_SEQ:
- return ED_space_sequencer_maskedit_poll(C);
- case SPACE_IMAGE:
- return ED_space_image_maskedit_poll(C);
- }
- }
- return false;
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa) {
+ switch (sa->spacetype) {
+ case SPACE_CLIP:
+ return ED_space_clip_maskedit_poll(C);
+ case SPACE_SEQ:
+ return ED_space_sequencer_maskedit_poll(C);
+ case SPACE_IMAGE:
+ return ED_space_image_maskedit_poll(C);
+ }
+ }
+ return false;
}
bool ED_maskedit_mask_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- if (sa) {
- switch (sa->spacetype) {
- case SPACE_CLIP:
- return ED_space_clip_maskedit_mask_poll(C);
- case SPACE_SEQ:
- return ED_space_sequencer_maskedit_mask_poll(C);
- case SPACE_IMAGE:
- return ED_space_image_maskedit_mask_poll(C);
- }
- }
- return false;
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa) {
+ switch (sa->spacetype) {
+ case SPACE_CLIP:
+ return ED_space_clip_maskedit_mask_poll(C);
+ case SPACE_SEQ:
+ return ED_space_sequencer_maskedit_mask_poll(C);
+ case SPACE_IMAGE:
+ return ED_space_image_maskedit_mask_poll(C);
+ }
+ }
+ return false;
}
/********************** registration *********************/
@@ -87,461 +86,439 @@ bool ED_maskedit_mask_poll(bContext *C)
/* 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);
- }
+ 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];
+ 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];
+ 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;
- }
+ 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;
- }
+ 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;
- }
+ 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;
- }
+ 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);
- }
+ 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);
- MaskLayer *mask_layer;
- bool ok = false;
-
- if (mask == NULL)
- return ok;
-
- INIT_MINMAX2(min, max);
- for (mask_layer = mask->masklayers.first;
- mask_layer != NULL;
- mask_layer = mask_layer->next)
- {
- MaskSpline *spline;
- if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
- for (spline = mask_layer->splines.first;
- spline != NULL;
- spline = spline->next)
- {
- MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
- int i;
- for (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;
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *mask_layer;
+ bool ok = false;
+
+ if (mask == NULL)
+ return ok;
+
+ INIT_MINMAX2(min, max);
+ for (mask_layer = mask->masklayers.first; mask_layer != NULL; mask_layer = mask_layer->next) {
+ MaskSpline *spline;
+ if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+ for (spline = mask_layer->splines.first; spline != NULL; spline = spline->next) {
+ MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
+ int i;
+ for (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 *********************/
void ED_operatortypes_mask(void)
{
- WM_operatortype_append(MASK_OT_new);
-
- /* mask layers */
- WM_operatortype_append(MASK_OT_layer_new);
- WM_operatortype_append(MASK_OT_layer_remove);
-
- /* add */
- WM_operatortype_append(MASK_OT_add_vertex);
- WM_operatortype_append(MASK_OT_add_feather_vertex);
- WM_operatortype_append(MASK_OT_primitive_circle_add);
- WM_operatortype_append(MASK_OT_primitive_square_add);
-
- /* geometry */
- WM_operatortype_append(MASK_OT_switch_direction);
- WM_operatortype_append(MASK_OT_normals_make_consistent);
- WM_operatortype_append(MASK_OT_delete);
-
- /* select */
- WM_operatortype_append(MASK_OT_select);
- WM_operatortype_append(MASK_OT_select_all);
- WM_operatortype_append(MASK_OT_select_box);
- WM_operatortype_append(MASK_OT_select_lasso);
- WM_operatortype_append(MASK_OT_select_circle);
- WM_operatortype_append(MASK_OT_select_linked_pick);
- WM_operatortype_append(MASK_OT_select_linked);
- WM_operatortype_append(MASK_OT_select_more);
- WM_operatortype_append(MASK_OT_select_less);
-
- /* hide/reveal */
- WM_operatortype_append(MASK_OT_hide_view_clear);
- WM_operatortype_append(MASK_OT_hide_view_set);
-
- /* feather */
- WM_operatortype_append(MASK_OT_feather_weight_clear);
-
- /* shape */
- WM_operatortype_append(MASK_OT_slide_point);
- WM_operatortype_append(MASK_OT_slide_spline_curvature);
- WM_operatortype_append(MASK_OT_cyclic_toggle);
- WM_operatortype_append(MASK_OT_handle_type_set);
-
- /* relationships */
- WM_operatortype_append(MASK_OT_parent_set);
- WM_operatortype_append(MASK_OT_parent_clear);
-
- /* shapekeys */
- WM_operatortype_append(MASK_OT_shape_key_insert);
- WM_operatortype_append(MASK_OT_shape_key_clear);
- WM_operatortype_append(MASK_OT_shape_key_feather_reset);
- WM_operatortype_append(MASK_OT_shape_key_rekey);
-
- /* layers */
- WM_operatortype_append(MASK_OT_layer_move);
-
- /* duplicate */
- WM_operatortype_append(MASK_OT_duplicate);
-
- /* clipboard */
- WM_operatortype_append(MASK_OT_copy_splines);
- WM_operatortype_append(MASK_OT_paste_splines);
+ WM_operatortype_append(MASK_OT_new);
+
+ /* mask layers */
+ WM_operatortype_append(MASK_OT_layer_new);
+ WM_operatortype_append(MASK_OT_layer_remove);
+
+ /* add */
+ WM_operatortype_append(MASK_OT_add_vertex);
+ WM_operatortype_append(MASK_OT_add_feather_vertex);
+ WM_operatortype_append(MASK_OT_primitive_circle_add);
+ WM_operatortype_append(MASK_OT_primitive_square_add);
+
+ /* geometry */
+ WM_operatortype_append(MASK_OT_switch_direction);
+ WM_operatortype_append(MASK_OT_normals_make_consistent);
+ WM_operatortype_append(MASK_OT_delete);
+
+ /* select */
+ WM_operatortype_append(MASK_OT_select);
+ WM_operatortype_append(MASK_OT_select_all);
+ WM_operatortype_append(MASK_OT_select_box);
+ WM_operatortype_append(MASK_OT_select_lasso);
+ WM_operatortype_append(MASK_OT_select_circle);
+ WM_operatortype_append(MASK_OT_select_linked_pick);
+ WM_operatortype_append(MASK_OT_select_linked);
+ WM_operatortype_append(MASK_OT_select_more);
+ WM_operatortype_append(MASK_OT_select_less);
+
+ /* hide/reveal */
+ WM_operatortype_append(MASK_OT_hide_view_clear);
+ WM_operatortype_append(MASK_OT_hide_view_set);
+
+ /* feather */
+ WM_operatortype_append(MASK_OT_feather_weight_clear);
+
+ /* shape */
+ WM_operatortype_append(MASK_OT_slide_point);
+ WM_operatortype_append(MASK_OT_slide_spline_curvature);
+ WM_operatortype_append(MASK_OT_cyclic_toggle);
+ WM_operatortype_append(MASK_OT_handle_type_set);
+
+ /* relationships */
+ WM_operatortype_append(MASK_OT_parent_set);
+ WM_operatortype_append(MASK_OT_parent_clear);
+
+ /* shapekeys */
+ WM_operatortype_append(MASK_OT_shape_key_insert);
+ WM_operatortype_append(MASK_OT_shape_key_clear);
+ WM_operatortype_append(MASK_OT_shape_key_feather_reset);
+ WM_operatortype_append(MASK_OT_shape_key_rekey);
+
+ /* layers */
+ WM_operatortype_append(MASK_OT_layer_move);
+
+ /* duplicate */
+ WM_operatortype_append(MASK_OT_duplicate);
+
+ /* clipboard */
+ WM_operatortype_append(MASK_OT_copy_splines);
+ WM_operatortype_append(MASK_OT_paste_splines);
}
void ED_keymap_mask(wmKeyConfig *keyconf)
{
- wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Mask Editing", 0, 0);
- keymap->poll = ED_maskedit_poll;
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Mask Editing", 0, 0);
+ keymap->poll = ED_maskedit_poll;
}
void ED_operatormacros_mask(void)
{
- wmOperatorType *ot;
- wmOperatorTypeMacro *otmacro;
-
- ot = WM_operatortype_append_macro("MASK_OT_add_vertex_slide", "Add Vertex and Slide",
- "Add new vertex and slide it", OPTYPE_UNDO | OPTYPE_REGISTER);
- ot->description = "Add new vertex and slide it";
- WM_operatortype_macro_define(ot, "MASK_OT_add_vertex");
- otmacro = WM_operatortype_macro_define(ot, "MASK_OT_slide_point");
- RNA_boolean_set(otmacro->ptr, "is_new_point", true);
-
- ot = WM_operatortype_append_macro("MASK_OT_add_feather_vertex_slide", "Add Feather Vertex and Slide",
- "Add new vertex to feather and slide it", OPTYPE_UNDO | OPTYPE_REGISTER);
- ot->description = "Add new feather vertex and slide it";
- WM_operatortype_macro_define(ot, "MASK_OT_add_feather_vertex");
- otmacro = WM_operatortype_macro_define(ot, "MASK_OT_slide_point");
- RNA_boolean_set(otmacro->ptr, "slide_feather", true);
-
- ot = WM_operatortype_append_macro("MASK_OT_duplicate_move", "Add Duplicate", "Duplicate mask and move",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "MASK_OT_duplicate");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", false);
+ wmOperatorType *ot;
+ wmOperatorTypeMacro *otmacro;
+
+ ot = WM_operatortype_append_macro("MASK_OT_add_vertex_slide",
+ "Add Vertex and Slide",
+ "Add new vertex and slide it",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ ot->description = "Add new vertex and slide it";
+ WM_operatortype_macro_define(ot, "MASK_OT_add_vertex");
+ otmacro = WM_operatortype_macro_define(ot, "MASK_OT_slide_point");
+ RNA_boolean_set(otmacro->ptr, "is_new_point", true);
+
+ ot = WM_operatortype_append_macro("MASK_OT_add_feather_vertex_slide",
+ "Add Feather Vertex and Slide",
+ "Add new vertex to feather and slide it",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ ot->description = "Add new feather vertex and slide it";
+ WM_operatortype_macro_define(ot, "MASK_OT_add_feather_vertex");
+ otmacro = WM_operatortype_macro_define(ot, "MASK_OT_slide_point");
+ RNA_boolean_set(otmacro->ptr, "slide_feather", true);
+
+ ot = WM_operatortype_append_macro("MASK_OT_duplicate_move",
+ "Add Duplicate",
+ "Duplicate mask and move",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "MASK_OT_duplicate");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ 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 9c7eed6ba51..d30e62d89f5 100644
--- a/source/blender/editors/mask/mask_editaction.c
+++ b/source/blender/editors/mask/mask_editaction.c
@@ -40,7 +40,7 @@
#include "ED_anim_api.h"
#include "ED_keyframes_edit.h"
-#include "ED_mask.h" /* own include */
+#include "ED_mask.h" /* own include */
#include "ED_markers.h"
/* ***************************************** */
@@ -53,23 +53,26 @@
/* Generics - Loopers */
/* Loops over the mask-frames for a mask-layer, and applies the given callback */
-bool ED_masklayer_frames_looper(MaskLayer *masklay, Scene *scene, short (*masklay_shape_cb)(MaskLayerShape *, Scene *))
+bool ED_masklayer_frames_looper(MaskLayer *masklay,
+ Scene *scene,
+ short (*masklay_shape_cb)(MaskLayerShape *, Scene *))
{
- MaskLayerShape *masklay_shape;
-
- /* error checker */
- if (masklay == NULL)
- return false;
-
- /* do loop */
- for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
- /* execute callback */
- if (masklay_shape_cb(masklay_shape, scene))
- return true;
- }
-
- /* nothing to return */
- return false;
+ MaskLayerShape *masklay_shape;
+
+ /* error checker */
+ if (masklay == NULL)
+ return false;
+
+ /* do loop */
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape->next) {
+ /* execute callback */
+ if (masklay_shape_cb(masklay_shape, scene))
+ return true;
+ }
+
+ /* nothing to return */
+ return false;
}
/* ****************************************** */
@@ -78,24 +81,25 @@ bool ED_masklayer_frames_looper(MaskLayer *masklay, Scene *scene, short (*maskla
/* make a listing all the mask-frames in a layer as cfraelems */
void ED_masklayer_make_cfra_list(MaskLayer *masklay, ListBase *elems, bool onlysel)
{
- MaskLayerShape *masklay_shape;
- CfraElem *ce;
+ MaskLayerShape *masklay_shape;
+ CfraElem *ce;
- /* error checking */
- if (ELEM(NULL, masklay, elems))
- return;
+ /* error checking */
+ if (ELEM(NULL, masklay, elems))
+ return;
- /* loop through mask-frames, adding */
- for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
- if ((onlysel == false) || (masklay_shape->flag & MASK_SHAPE_SELECT)) {
- ce = MEM_callocN(sizeof(CfraElem), "CfraElem");
+ /* loop through mask-frames, adding */
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape->next) {
+ if ((onlysel == false) || (masklay_shape->flag & MASK_SHAPE_SELECT)) {
+ ce = MEM_callocN(sizeof(CfraElem), "CfraElem");
- ce->cfra = (float)masklay_shape->frame;
- ce->sel = (masklay_shape->flag & MASK_SHAPE_SELECT) ? 1 : 0;
+ ce->cfra = (float)masklay_shape->frame;
+ ce->sel = (masklay_shape->flag & MASK_SHAPE_SELECT) ? 1 : 0;
- BLI_addtail(elems, ce);
- }
- }
+ BLI_addtail(elems, ce);
+ }
+ }
}
/* ***************************************** */
@@ -104,125 +108,132 @@ void ED_masklayer_make_cfra_list(MaskLayer *masklay, ListBase *elems, bool onlys
/* check if one of the frames in this layer is selected */
bool ED_masklayer_frame_select_check(MaskLayer *masklay)
{
- MaskLayerShape *masklay_shape;
+ MaskLayerShape *masklay_shape;
- /* error checking */
- if (masklay == NULL)
- return 0;
+ /* error checking */
+ if (masklay == NULL)
+ return 0;
- /* stop at the first one found */
- for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
- if (masklay_shape->flag & MASK_SHAPE_SELECT)
- return 1;
- }
+ /* stop at the first one found */
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape->next) {
+ if (masklay_shape->flag & MASK_SHAPE_SELECT)
+ return 1;
+ }
- /* not found */
- return 0;
+ /* not found */
+ return 0;
}
/* helper function - select mask-frame based on SELECT_* mode */
static void masklayshape_select(MaskLayerShape *masklay_shape, short select_mode)
{
- if (masklay_shape == NULL)
- return;
-
- switch (select_mode) {
- case SELECT_ADD:
- masklay_shape->flag |= MASK_SHAPE_SELECT;
- break;
- case SELECT_SUBTRACT:
- masklay_shape->flag &= ~MASK_SHAPE_SELECT;
- break;
- case SELECT_INVERT:
- masklay_shape->flag ^= MASK_SHAPE_SELECT;
- break;
- }
+ if (masklay_shape == NULL)
+ return;
+
+ switch (select_mode) {
+ case SELECT_ADD:
+ masklay_shape->flag |= MASK_SHAPE_SELECT;
+ break;
+ case SELECT_SUBTRACT:
+ masklay_shape->flag &= ~MASK_SHAPE_SELECT;
+ break;
+ case SELECT_INVERT:
+ masklay_shape->flag ^= MASK_SHAPE_SELECT;
+ break;
+ }
}
/* set all/none/invert select (like above, but with SELECT_* modes) */
void ED_mask_select_frames(MaskLayer *masklay, short select_mode)
{
- MaskLayerShape *masklay_shape;
+ MaskLayerShape *masklay_shape;
- /* error checking */
- if (masklay == NULL)
- return;
+ /* error checking */
+ if (masklay == NULL)
+ return;
- /* handle according to mode */
- for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
- masklayshape_select(masklay_shape, select_mode);
- }
+ /* handle according to mode */
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape->next) {
+ masklayshape_select(masklay_shape, select_mode);
+ }
}
/* set all/none/invert select */
void ED_masklayer_frame_select_set(MaskLayer *masklay, short mode)
{
- /* error checking */
- if (masklay == NULL)
- return;
+ /* error checking */
+ if (masklay == NULL)
+ return;
- /* now call the standard function */
- ED_mask_select_frames(masklay, mode);
+ /* now call the standard function */
+ ED_mask_select_frames(masklay, mode);
}
/* select the frame in this layer that occurs on this frame (there should only be one at most) */
void ED_mask_select_frame(MaskLayer *masklay, int selx, short select_mode)
{
- MaskLayerShape *masklay_shape;
+ MaskLayerShape *masklay_shape;
- if (masklay == NULL)
- return;
+ if (masklay == NULL)
+ return;
- masklay_shape = BKE_mask_layer_shape_find_frame(masklay, selx);
+ masklay_shape = BKE_mask_layer_shape_find_frame(masklay, selx);
- if (masklay_shape) {
- masklayshape_select(masklay_shape, select_mode);
- }
+ if (masklay_shape) {
+ masklayshape_select(masklay_shape, select_mode);
+ }
}
/* select the frames in this layer that occur within the bounds specified */
void ED_masklayer_frames_select_box(MaskLayer *masklay, float min, float max, short select_mode)
{
- MaskLayerShape *masklay_shape;
+ MaskLayerShape *masklay_shape;
- if (masklay == NULL)
- return;
+ if (masklay == NULL)
+ return;
- /* only select those frames which are in bounds */
- for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
- if (IN_RANGE(masklay_shape->frame, min, max))
- masklayshape_select(masklay_shape, select_mode);
- }
+ /* only select those frames which are in bounds */
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape->next) {
+ if (IN_RANGE(masklay_shape->frame, min, max))
+ masklayshape_select(masklay_shape, select_mode);
+ }
}
/* select the frames in this layer that occur within the lasso/circle region specified */
-void ED_masklayer_frames_select_region(KeyframeEditData *ked, MaskLayer *masklay, short tool, short select_mode)
+void ED_masklayer_frames_select_region(KeyframeEditData *ked,
+ MaskLayer *masklay,
+ short tool,
+ short select_mode)
{
- MaskLayerShape *masklay_shape;
-
- if (masklay == NULL)
- return;
-
- /* only select frames which are within the region */
- for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
- /* construct a dummy point coordinate to do this testing with */
- float pt[2] = {0};
-
- pt[0] = masklay_shape->frame;
- pt[1] = ked->channel_y;
-
- /* check the necessary regions */
- if (tool == BEZT_OK_CHANNEL_LASSO) {
- /* Lasso */
- if (keyframe_region_lasso_test(ked->data, pt))
- masklayshape_select(masklay_shape, select_mode);
- }
- else if (tool == BEZT_OK_CHANNEL_CIRCLE) {
- /* Circle */
- if (keyframe_region_circle_test(ked->data, pt))
- masklayshape_select(masklay_shape, select_mode);
- }
- }
+ MaskLayerShape *masklay_shape;
+
+ if (masklay == NULL)
+ return;
+
+ /* only select frames which are within the region */
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape->next) {
+ /* construct a dummy point coordinate to do this testing with */
+ float pt[2] = {0};
+
+ pt[0] = masklay_shape->frame;
+ pt[1] = ked->channel_y;
+
+ /* check the necessary regions */
+ if (tool == BEZT_OK_CHANNEL_LASSO) {
+ /* Lasso */
+ if (keyframe_region_lasso_test(ked->data, pt))
+ masklayshape_select(masklay_shape, select_mode);
+ }
+ else if (tool == BEZT_OK_CHANNEL_CIRCLE) {
+ /* Circle */
+ if (keyframe_region_circle_test(ked->data, pt))
+ masklayshape_select(masklay_shape, select_mode);
+ }
+ }
}
/* ***************************************** */
@@ -231,51 +242,52 @@ void ED_masklayer_frames_select_region(KeyframeEditData *ked, MaskLayer *masklay
/* Delete selected frames */
bool ED_masklayer_frames_delete(MaskLayer *masklay)
{
- MaskLayerShape *masklay_shape, *masklay_shape_next;
- bool changed = false;
+ MaskLayerShape *masklay_shape, *masklay_shape_next;
+ bool changed = false;
- /* error checking */
- if (masklay == NULL)
- return false;
+ /* error checking */
+ if (masklay == NULL)
+ return false;
- /* check for frames to delete */
- for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape_next) {
- masklay_shape_next = masklay_shape->next;
+ /* check for frames to delete */
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape_next) {
+ masklay_shape_next = masklay_shape->next;
- if (masklay_shape->flag & MASK_SHAPE_SELECT) {
- BKE_mask_layer_shape_unlink(masklay, masklay_shape);
- changed = true;
- }
- }
+ if (masklay_shape->flag & MASK_SHAPE_SELECT) {
+ BKE_mask_layer_shape_unlink(masklay, masklay_shape);
+ changed = true;
+ }
+ }
- return changed;
+ return changed;
}
/* Duplicate selected frames from given mask-layer */
void ED_masklayer_frames_duplicate(MaskLayer *masklay)
{
- MaskLayerShape *masklay_shape, *gpfn;
+ MaskLayerShape *masklay_shape, *gpfn;
- /* error checking */
- if (masklay == NULL)
- return;
+ /* error checking */
+ if (masklay == NULL)
+ return;
- /* duplicate selected frames */
- for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = gpfn) {
- gpfn = masklay_shape->next;
+ /* duplicate selected frames */
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = gpfn) {
+ gpfn = masklay_shape->next;
- /* duplicate this frame */
- if (masklay_shape->flag & MASK_SHAPE_SELECT) {
- MaskLayerShape *mask_shape_dupe;
+ /* duplicate this frame */
+ if (masklay_shape->flag & MASK_SHAPE_SELECT) {
+ MaskLayerShape *mask_shape_dupe;
- /* duplicate frame, and deselect self */
- mask_shape_dupe = BKE_mask_layer_shape_duplicate(masklay_shape);
- masklay_shape->flag &= ~MASK_SHAPE_SELECT;
+ /* duplicate frame, and deselect self */
+ mask_shape_dupe = BKE_mask_layer_shape_duplicate(masklay_shape);
+ masklay_shape->flag &= ~MASK_SHAPE_SELECT;
- /* XXX - how to handle duplicate frames? */
- BLI_insertlinkafter(&masklay->splines_shapes, masklay_shape, mask_shape_dupe);
- }
- }
+ /* XXX - how to handle duplicate frames? */
+ BLI_insertlinkafter(&masklay->splines_shapes, masklay_shape, mask_shape_dupe);
+ }
+ }
}
/* -------------------------------------- */
@@ -283,50 +295,51 @@ void ED_masklayer_frames_duplicate(MaskLayer *masklay)
static short snap_masklayer_nearest(MaskLayerShape *masklay_shape, Scene *UNUSED(scene))
{
- if (masklay_shape->flag & MASK_SHAPE_SELECT)
- masklay_shape->frame = (int)(floor(masklay_shape->frame + 0.5));
- return 0;
+ if (masklay_shape->flag & MASK_SHAPE_SELECT)
+ masklay_shape->frame = (int)(floor(masklay_shape->frame + 0.5));
+ return 0;
}
static short snap_masklayer_nearestsec(MaskLayerShape *masklay_shape, Scene *scene)
{
- float secf = (float)FPS;
- if (masklay_shape->flag & MASK_SHAPE_SELECT)
- masklay_shape->frame = (int)(floorf(masklay_shape->frame / secf + 0.5f) * secf);
- return 0;
+ float secf = (float)FPS;
+ if (masklay_shape->flag & MASK_SHAPE_SELECT)
+ masklay_shape->frame = (int)(floorf(masklay_shape->frame / secf + 0.5f) * secf);
+ return 0;
}
static short snap_masklayer_cframe(MaskLayerShape *masklay_shape, Scene *scene)
{
- if (masklay_shape->flag & MASK_SHAPE_SELECT)
- masklay_shape->frame = (int)CFRA;
- return 0;
+ if (masklay_shape->flag & MASK_SHAPE_SELECT)
+ masklay_shape->frame = (int)CFRA;
+ return 0;
}
static short snap_masklayer_nearmarker(MaskLayerShape *masklay_shape, Scene *scene)
{
- if (masklay_shape->flag & MASK_SHAPE_SELECT)
- masklay_shape->frame = (int)ED_markers_find_nearest_marker_time(&scene->markers, (float)masklay_shape->frame);
- return 0;
+ if (masklay_shape->flag & MASK_SHAPE_SELECT)
+ masklay_shape->frame = (int)ED_markers_find_nearest_marker_time(&scene->markers,
+ (float)masklay_shape->frame);
+ return 0;
}
/* snap selected frames to ... */
void ED_masklayer_snap_frames(MaskLayer *masklay, Scene *scene, short mode)
{
- switch (mode) {
- case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */
- ED_masklayer_frames_looper(masklay, scene, snap_masklayer_nearest);
- break;
- case SNAP_KEYS_CURFRAME: /* snap to current frame */
- ED_masklayer_frames_looper(masklay, scene, snap_masklayer_cframe);
- break;
- case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */
- ED_masklayer_frames_looper(masklay, scene, snap_masklayer_nearmarker);
- break;
- case SNAP_KEYS_NEARSEC: /* snap to nearest second */
- ED_masklayer_frames_looper(masklay, scene, snap_masklayer_nearestsec);
- break;
- default: /* just in case */
- break;
- }
+ switch (mode) {
+ case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */
+ ED_masklayer_frames_looper(masklay, scene, snap_masklayer_nearest);
+ break;
+ case SNAP_KEYS_CURFRAME: /* snap to current frame */
+ ED_masklayer_frames_looper(masklay, scene, snap_masklayer_cframe);
+ break;
+ case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */
+ ED_masklayer_frames_looper(masklay, scene, snap_masklayer_nearmarker);
+ break;
+ case SNAP_KEYS_NEARSEC: /* snap to nearest second */
+ ED_masklayer_frames_looper(masklay, scene, snap_masklayer_nearestsec);
+ break;
+ default: /* just in case */
+ break;
+ }
}
diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h
index 77f537e2e4a..67785f1ae46 100644
--- a/source/blender/editors/mask/mask_intern.h
+++ b/source/blender/editors/mask/mask_intern.h
@@ -34,7 +34,8 @@ struct wmOperatorType;
bool ED_mask_find_nearest_diff_point(const struct bContext *C,
struct Mask *mask,
const float normal_co[2],
- int threshold, bool feather,
+ int threshold,
+ bool feather,
float tangent[2],
const bool use_deform,
const bool use_project,
@@ -71,15 +72,24 @@ 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 **masklay_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 **masklay_r, struct MaskSpline **spline_r, eMaskWhichHandle *which_handle_r,
- float *score);
+bool ED_mask_feather_find_nearest(const struct bContext *C,
+ struct Mask *mask,
+ const float normal_co[2],
+ const float threshold,
+ struct MaskLayer **masklay_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 **masklay_r,
+ struct MaskSpline **spline_r,
+ eMaskWhichHandle *which_handle_r,
+ float *score);
void MASK_OT_layer_move(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index 1bb76045c72..2b925b9095e 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -34,7 +34,7 @@
#include "DNA_scene_types.h"
#include "DNA_mask_types.h"
-#include "DNA_object_types.h" /* SELECT */
+#include "DNA_object_types.h" /* SELECT */
#include "WM_api.h"
#include "WM_types.h"
@@ -49,1255 +49,1292 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "mask_intern.h" /* own include */
+#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])
+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;
+ 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, const float normal_co[2], const float threshold,
- MaskLayer **masklay_r, MaskSpline **spline_r,
- eMaskWhichHandle *which_handle_r, float *score)
+MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C,
+ Mask *mask,
+ const float normal_co[2],
+ const float threshold,
+ MaskLayer **masklay_r,
+ MaskSpline **spline_r,
+ eMaskWhichHandle *which_handle_r,
+ float *score)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
-
- MaskLayer *masklay;
- MaskLayer *point_masklay = NULL;
- MaskSpline *point_spline = NULL;
- MaskSplinePoint *point = NULL;
- 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;
-
- ED_mask_get_size(sa, &width, &height);
- ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
-
- co[0] = normal_co[0] * scalex;
- co[1] = normal_co[1] * scaley;
-
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
-
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
-
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
-
- int i;
-
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *cur_point = &spline->points[i];
- MaskSplinePoint *cur_point_deform = &points_array[i];
- eMaskWhichHandle cur_which_handle = MASK_WHICH_HANDLE_NONE;
- BezTriple *bezt = &cur_point_deform->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;
- point_masklay = masklay;
- point = cur_point;
- len_sq = cur_len_sq;
- which_handle = MASK_WHICH_HANDLE_NONE;
- }
-
- if (BKE_mask_point_handles_mode_get(cur_point_deform) == MASK_HANDLE_MODE_STICK) {
- float handle[2];
- mask_point_scaled_handle(cur_point_deform, 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, MASK_WHICH_HANDLE_LEFT, scalex, scaley, handle_left);
- mask_point_scaled_handle(cur_point_deform, 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_masklay = masklay;
- point_spline = spline;
- point = cur_point;
- len_sq = cur_len_sq;
- which_handle = cur_which_handle;
- }
- }
- }
- }
-
- if (len_sq < threshold_sq) {
- if (masklay_r)
- *masklay_r = point_masklay;
-
- 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 (masklay_r)
- *masklay_r = NULL;
-
- if (spline_r)
- *spline_r = NULL;
-
- if (which_handle_r)
- *which_handle_r = MASK_WHICH_HANDLE_NONE;
-
- return NULL;
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ MaskLayer *masklay;
+ MaskLayer *point_masklay = NULL;
+ MaskSpline *point_spline = NULL;
+ MaskSplinePoint *point = NULL;
+ 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;
+
+ ED_mask_get_size(sa, &width, &height);
+ ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
+
+ co[0] = normal_co[0] * scalex;
+ co[1] = normal_co[1] * scaley;
+
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
+
+ int i;
+
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *cur_point = &spline->points[i];
+ MaskSplinePoint *cur_point_deform = &points_array[i];
+ eMaskWhichHandle cur_which_handle = MASK_WHICH_HANDLE_NONE;
+ BezTriple *bezt = &cur_point_deform->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;
+ point_masklay = masklay;
+ point = cur_point;
+ len_sq = cur_len_sq;
+ which_handle = MASK_WHICH_HANDLE_NONE;
+ }
+
+ if (BKE_mask_point_handles_mode_get(cur_point_deform) == MASK_HANDLE_MODE_STICK) {
+ float handle[2];
+ mask_point_scaled_handle(
+ cur_point_deform, 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, MASK_WHICH_HANDLE_LEFT, scalex, scaley, handle_left);
+ mask_point_scaled_handle(
+ cur_point_deform, 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_masklay = masklay;
+ point_spline = spline;
+ point = cur_point;
+ len_sq = cur_len_sq;
+ which_handle = cur_which_handle;
+ }
+ }
+ }
+ }
+
+ if (len_sq < threshold_sq) {
+ if (masklay_r)
+ *masklay_r = point_masklay;
+
+ 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 (masklay_r)
+ *masklay_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, const float normal_co[2], const float threshold,
- MaskLayer **masklay_r, MaskSpline **spline_r, MaskSplinePoint **point_r,
- MaskSplinePointUW **uw_r, float *score)
+bool ED_mask_feather_find_nearest(const bContext *C,
+ Mask *mask,
+ const float normal_co[2],
+ const float threshold,
+ MaskLayer **masklay_r,
+ MaskSpline **spline_r,
+ MaskSplinePoint **point_r,
+ MaskSplinePointUW **uw_r,
+ float *score)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
- MaskLayer *masklay, *point_masklay = 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;
+ MaskLayer *masklay, *point_masklay = 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;
- ED_mask_get_size(sa, &width, &height);
- ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
+ 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;
+ co[0] = normal_co[0] * scalex;
+ co[1] = normal_co[1] * scaley;
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- //MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ //MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
- int i, tot_feather_point;
- float (*feather_points)[2], (*fp)[2];
+ int i, tot_feather_point;
+ float(*feather_points)[2], (*fp)[2];
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
- feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point);
+ feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point);
- for (i = 0; i < spline->tot_point; i++) {
- int j;
- MaskSplinePoint *cur_point = &spline->points[i];
+ for (i = 0; i < spline->tot_point; i++) {
+ int j;
+ MaskSplinePoint *cur_point = &spline->points[i];
- for (j = 0; j <= cur_point->tot_uw; j++) {
- float cur_len_sq, vec[2];
+ for (j = 0; j <= cur_point->tot_uw; j++) {
+ float cur_len_sq, vec[2];
- vec[0] = (*fp)[0] * scalex;
- vec[1] = (*fp)[1] * scaley;
+ vec[0] = (*fp)[0] * scalex;
+ vec[1] = (*fp)[1] * scaley;
- cur_len_sq = len_squared_v2v2(vec, co);
+ cur_len_sq = len_squared_v2v2(vec, co);
- if (point == NULL || cur_len_sq < len) {
- if (j == 0)
- uw = NULL;
- else
- uw = &cur_point->uw[j - 1];
+ if (point == NULL || cur_len_sq < len) {
+ if (j == 0)
+ uw = NULL;
+ else
+ uw = &cur_point->uw[j - 1];
- point_masklay = masklay;
- point_spline = spline;
- point = cur_point;
- len = cur_len_sq;
- }
+ point_masklay = masklay;
+ point_spline = spline;
+ point = cur_point;
+ len = cur_len_sq;
+ }
- fp++;
- }
- }
+ fp++;
+ }
+ }
- MEM_freeN(feather_points);
- }
- }
+ MEM_freeN(feather_points);
+ }
+ }
- if (len < threshold_sq) {
- if (masklay_r)
- *masklay_r = point_masklay;
+ if (len < threshold_sq) {
+ if (masklay_r)
+ *masklay_r = point_masklay;
- if (spline_r)
- *spline_r = point_spline;
+ if (spline_r)
+ *spline_r = point_spline;
- if (point_r)
- *point_r = point;
+ if (point_r)
+ *point_r = point;
- if (uw_r)
- *uw_r = uw;
+ if (uw_r)
+ *uw_r = uw;
- if (score)
- *score = sqrtf(len);
+ if (score)
+ *score = sqrtf(len);
- return true;
- }
+ return true;
+ }
- if (masklay_r)
- *masklay_r = NULL;
+ if (masklay_r)
+ *masklay_r = NULL;
- if (spline_r)
- *spline_r = NULL;
+ if (spline_r)
+ *spline_r = NULL;
- if (point_r)
- *point_r = NULL;
+ if (point_r)
+ *point_r = NULL;
- return false;
+ return false;
}
-
/******************** create new mask *********************/
Mask *ED_mask_new(bContext *C, const char *name)
{
- ScrArea *sa = 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) {
- case SPACE_CLIP:
- {
- SpaceClip *sc = sa->spacedata.first;
- ED_space_clip_set_mask(C, sc, mask);
- break;
- }
- case SPACE_SEQ:
- {
- /* do nothing */
- break;
- }
- case SPACE_IMAGE:
- {
- SpaceImage *sima = sa->spacedata.first;
- ED_space_image_set_mask(C, sima, mask);
- break;
- }
- }
- }
-
- return mask;
+ ScrArea *sa = 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) {
+ case SPACE_CLIP: {
+ SpaceClip *sc = sa->spacedata.first;
+ ED_space_clip_set_mask(C, sc, mask);
+ break;
+ }
+ case SPACE_SEQ: {
+ /* do nothing */
+ break;
+ }
+ case SPACE_IMAGE: {
+ SpaceImage *sima = sa->spacedata.first;
+ ED_space_image_set_mask(C, sima, mask);
+ break;
+ }
+ }
+ }
+
+ return mask;
}
/* Get ative layer. Will create mask/layer to be sure there's an active layer. */
MaskLayer *ED_mask_layer_ensure(bContext *C, bool *r_added_mask)
{
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *mask_layer;
-
- if (mask == NULL) {
- /* If there's no active mask, create one. */
- mask = ED_mask_new(C, NULL);
- *r_added_mask = true;
- }
-
- mask_layer = BKE_mask_layer_active(mask);
- if (mask_layer == NULL) {
- /* If there's no active mask layer, create one. */
- mask_layer = BKE_mask_layer_new(mask, "");
- }
-
- return mask_layer;
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *mask_layer;
+
+ if (mask == NULL) {
+ /* If there's no active mask, create one. */
+ mask = ED_mask_new(C, NULL);
+ *r_added_mask = true;
+ }
+
+ mask_layer = BKE_mask_layer_active(mask);
+ if (mask_layer == NULL) {
+ /* If there's no active mask layer, create one. */
+ mask_layer = BKE_mask_layer_new(mask, "");
+ }
+
+ return mask_layer;
}
static int mask_new_exec(bContext *C, wmOperator *op)
{
- char name[MAX_ID_NAME - 2];
+ char name[MAX_ID_NAME - 2];
- RNA_string_get(op->ptr, "name", name);
+ RNA_string_get(op->ptr, "name", name);
- ED_mask_new(C, name);
+ ED_mask_new(C, name);
- WM_event_add_notifier(C, NC_MASK | NA_ADDED, NULL);
+ WM_event_add_notifier(C, NC_MASK | NA_ADDED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MASK_OT_new(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "New Mask";
- ot->description = "Create new mask";
- ot->idname = "MASK_OT_new";
+ /* identifiers */
+ ot->name = "New Mask";
+ ot->description = "Create new mask";
+ ot->idname = "MASK_OT_new";
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* api callbacks */
- ot->exec = mask_new_exec;
- ot->poll = ED_operator_mask;
+ /* api callbacks */
+ ot->exec = mask_new_exec;
+ ot->poll = ED_operator_mask;
- /* properties */
- RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Name of new mask");
+ /* properties */
+ RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Name of new mask");
}
/******************** create new masklay *********************/
static int masklay_new_exec(bContext *C, wmOperator *op)
{
- Mask *mask = CTX_data_edit_mask(C);
- char name[MAX_ID_NAME - 2];
+ Mask *mask = CTX_data_edit_mask(C);
+ char name[MAX_ID_NAME - 2];
- RNA_string_get(op->ptr, "name", name);
+ RNA_string_get(op->ptr, "name", name);
- BKE_mask_layer_new(mask, name);
- mask->masklay_act = mask->masklay_tot - 1;
+ BKE_mask_layer_new(mask, name);
+ mask->masklay_act = mask->masklay_tot - 1;
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MASK_OT_layer_new(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Mask Layer";
- ot->description = "Add new mask layer for masking";
- ot->idname = "MASK_OT_layer_new";
+ /* identifiers */
+ ot->name = "Add Mask Layer";
+ ot->description = "Add new mask layer for masking";
+ ot->idname = "MASK_OT_layer_new";
- /* api callbacks */
- ot->exec = masklay_new_exec;
- ot->poll = ED_maskedit_poll;
+ /* api callbacks */
+ ot->exec = masklay_new_exec;
+ ot->poll = ED_maskedit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Name of new mask layer");
+ /* properties */
+ RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Name of new mask layer");
}
/******************** remove mask layer *********************/
static int masklay_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay = BKE_mask_layer_active(mask);
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay = BKE_mask_layer_active(mask);
- if (masklay) {
- BKE_mask_layer_remove(mask, masklay);
+ if (masklay) {
+ BKE_mask_layer_remove(mask, masklay);
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
- }
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MASK_OT_layer_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Mask Layer";
- ot->description = "Remove mask layer";
- ot->idname = "MASK_OT_layer_remove";
+ /* identifiers */
+ ot->name = "Remove Mask Layer";
+ ot->description = "Remove mask layer";
+ ot->idname = "MASK_OT_layer_remove";
- /* api callbacks */
- ot->exec = masklay_remove_exec;
- ot->poll = ED_maskedit_poll;
+ /* api callbacks */
+ ot->exec = masklay_remove_exec;
+ ot->poll = ED_maskedit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************** slide *********************/
enum {
- SLIDE_ACTION_NONE = 0,
- SLIDE_ACTION_POINT = 1,
- SLIDE_ACTION_HANDLE = 2,
- SLIDE_ACTION_FEATHER = 3,
- SLIDE_ACTION_SPLINE = 4,
+ SLIDE_ACTION_NONE = 0,
+ SLIDE_ACTION_POINT = 1,
+ SLIDE_ACTION_HANDLE = 2,
+ SLIDE_ACTION_FEATHER = 3,
+ SLIDE_ACTION_SPLINE = 4,
};
typedef struct SlidePointData {
- /* Generic fields. */
- short event_invoke_type;
- int action;
- Mask *mask;
- MaskLayer *masklay;
- MaskSpline *spline, *orig_spline;
- MaskSplinePoint *point;
- MaskSplinePointUW *uw;
- eMaskWhichHandle which_handle;
- int width, height;
-
- float prev_mouse_coord[2];
- float no[2];
-
- bool is_curvature_only,
- is_accurate,
- is_initial_feather,
- is_overall_feather;
-
- bool is_sliding_new_point;
-
- /* Data needed to restre the state. */
- float vec[3][3];
- char old_h1, old_h2;
-
- /* Point sliding. */
-
- /* Handle sliding. */
- float orig_handle_coord[2], prev_handle_coord[2];
-
- /* Feather sliding. */
- float prev_feather_coord[2];
- float weight, weight_scalar;
+ /* Generic fields. */
+ short event_invoke_type;
+ int action;
+ Mask *mask;
+ MaskLayer *masklay;
+ MaskSpline *spline, *orig_spline;
+ MaskSplinePoint *point;
+ MaskSplinePointUW *uw;
+ eMaskWhichHandle which_handle;
+ int width, height;
+
+ float prev_mouse_coord[2];
+ float no[2];
+
+ bool is_curvature_only, is_accurate, is_initial_feather, is_overall_feather;
+
+ bool is_sliding_new_point;
+
+ /* Data needed to restre the state. */
+ float vec[3][3];
+ char old_h1, old_h2;
+
+ /* Point sliding. */
+
+ /* Handle sliding. */
+ float orig_handle_coord[2], prev_handle_coord[2];
+
+ /* Feather sliding. */
+ float prev_feather_coord[2];
+ float weight, weight_scalar;
} SlidePointData;
static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float co[2])
{
- BKE_mask_coord_to_movieclip(sc->clip, &sc->user, r_co, co);
- ED_clip_point_undistorted_pos(sc, r_co, r_co);
- BKE_mask_coord_from_movieclip(sc->clip, &sc->user, r_co, r_co);
+ BKE_mask_coord_to_movieclip(sc->clip, &sc->user, r_co, co);
+ ED_clip_point_undistorted_pos(sc, r_co, r_co);
+ BKE_mask_coord_from_movieclip(sc->clip, &sc->user, r_co, r_co);
}
static bool spline_under_mouse_get(const bContext *C,
- Mask *mask, const float co[2],
+ Mask *mask,
+ const float co[2],
MaskLayer **mask_layer_r,
MaskSpline **mask_spline_r)
{
- const float threshold = 19.0f;
- ScrArea *sa = CTX_wm_area(C);
- SpaceClip *sc = CTX_wm_space_clip(C);
- MaskLayer *mask_layer;
- int width, height;
- float pixel_co[2];
- float closest_dist_squared = 0.0f;
- 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);
- pixel_co[0] = co[0] * width;
- pixel_co[1] = co[1] * height;
- if (sc != NULL) {
- undistort = (sc->clip != NULL) &&
- (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0;
- }
- for (mask_layer = mask->masklayers.first;
- mask_layer != NULL;
- mask_layer = mask_layer->next)
- {
- MaskSpline *spline;
- if (mask_layer->restrictflag & MASK_RESTRICT_SELECT) {
- continue;
- }
-
- for (spline = mask_layer->splines.first;
- spline != NULL;
- spline = spline->next)
- {
- MaskSplinePoint *points_array;
- float min[2], max[2], center[2];
- float dist_squared;
- int i;
- float max_bb_side;
- if ((spline->flag & SELECT) == 0) {
- continue;
- }
-
- points_array = BKE_mask_spline_point_array(spline);
- INIT_MINMAX2(min, max);
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point_deform = &points_array[i];
- BezTriple *bezt = &point_deform->bezt;
-
- float vert[2];
-
- copy_v2_v2(vert, bezt->vec[1]);
-
- if (undistort) {
- mask_point_undistort_pos(sc, vert, vert);
- }
-
- minmax_v2v2_v2(min, max, vert);
- }
-
- center[0] = (min[0] + max[0]) / 2.0f * width;
- center[1] = (min[1] + max[1]) / 2.0f * height;
- dist_squared = len_squared_v2v2(pixel_co, center);
- max_bb_side = min_ff((max[0] - min[0]) * width, (max[1] - min[1]) * height);
- if (dist_squared <= max_bb_side * max_bb_side * 0.5f &&
- (closest_spline == NULL || dist_squared < closest_dist_squared))
- {
- closest_layer = mask_layer;
- closest_spline = spline;
- closest_dist_squared = dist_squared;
- }
- }
- }
- if (closest_dist_squared < SQUARE(threshold) && closest_spline != NULL) {
- float diff_score;
- if (ED_mask_find_nearest_diff_point(C, mask, co, threshold,
- false, NULL, true, false,
- NULL, NULL, NULL, NULL,
- &diff_score))
- {
- if (SQUARE(diff_score) < closest_dist_squared) {
- return false;
- }
- }
-
- *mask_layer_r = closest_layer;
- *mask_spline_r = closest_spline;
- return true;
- }
- return false;
+ const float threshold = 19.0f;
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MaskLayer *mask_layer;
+ int width, height;
+ float pixel_co[2];
+ float closest_dist_squared = 0.0f;
+ 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);
+ pixel_co[0] = co[0] * width;
+ pixel_co[1] = co[1] * height;
+ if (sc != NULL) {
+ undistort = (sc->clip != NULL) && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0;
+ }
+ for (mask_layer = mask->masklayers.first; mask_layer != NULL; mask_layer = mask_layer->next) {
+ MaskSpline *spline;
+ if (mask_layer->restrictflag & MASK_RESTRICT_SELECT) {
+ continue;
+ }
+
+ for (spline = mask_layer->splines.first; spline != NULL; spline = spline->next) {
+ MaskSplinePoint *points_array;
+ float min[2], max[2], center[2];
+ float dist_squared;
+ int i;
+ float max_bb_side;
+ if ((spline->flag & SELECT) == 0) {
+ continue;
+ }
+
+ points_array = BKE_mask_spline_point_array(spline);
+ INIT_MINMAX2(min, max);
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point_deform = &points_array[i];
+ BezTriple *bezt = &point_deform->bezt;
+
+ float vert[2];
+
+ copy_v2_v2(vert, bezt->vec[1]);
+
+ if (undistort) {
+ mask_point_undistort_pos(sc, vert, vert);
+ }
+
+ minmax_v2v2_v2(min, max, vert);
+ }
+
+ center[0] = (min[0] + max[0]) / 2.0f * width;
+ center[1] = (min[1] + max[1]) / 2.0f * height;
+ dist_squared = len_squared_v2v2(pixel_co, center);
+ max_bb_side = min_ff((max[0] - min[0]) * width, (max[1] - min[1]) * height);
+ if (dist_squared <= max_bb_side * max_bb_side * 0.5f &&
+ (closest_spline == NULL || dist_squared < closest_dist_squared)) {
+ closest_layer = mask_layer;
+ closest_spline = spline;
+ closest_dist_squared = dist_squared;
+ }
+ }
+ }
+ if (closest_dist_squared < SQUARE(threshold) && closest_spline != NULL) {
+ float diff_score;
+ if (ED_mask_find_nearest_diff_point(C,
+ mask,
+ co,
+ threshold,
+ false,
+ NULL,
+ true,
+ false,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &diff_score)) {
+ if (SQUARE(diff_score) < closest_dist_squared) {
+ return false;
+ }
+ }
+
+ *mask_layer_r = closest_layer;
+ *mask_spline_r = closest_spline;
+ return true;
+ }
+ return false;
}
static bool slide_point_check_initial_feather(MaskSpline *spline)
{
- int i;
+ int i;
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
- if (point->bezt.weight != 0.0f) {
- return false;
- }
- }
+ if (point->bezt.weight != 0.0f) {
+ return false;
+ }
+ }
- return true;
+ return true;
}
-static void select_sliding_point(Mask *mask, MaskLayer *mask_layer, MaskSpline *spline,
- MaskSplinePoint *point, eMaskWhichHandle which_handle)
+static void select_sliding_point(Mask *mask,
+ MaskLayer *mask_layer,
+ MaskSpline *spline,
+ MaskSplinePoint *point,
+ eMaskWhichHandle which_handle)
{
- ED_mask_select_toggle_all(mask, SEL_DESELECT);
-
- switch (which_handle) {
- case MASK_WHICH_HANDLE_NONE:
- BKE_mask_point_select_set(point, true);
- break;
- case MASK_WHICH_HANDLE_LEFT:
- point->bezt.f1 |= SELECT;
- break;
- case MASK_WHICH_HANDLE_RIGHT:
- point->bezt.f3 |= SELECT;
- break;
- case MASK_WHICH_HANDLE_STICK:
- point->bezt.f1 |= SELECT;
- point->bezt.f3 |= SELECT;
- break;
- default:
- BLI_assert(!"Unexpected situation in select_sliding_point()");
- }
-
- mask_layer->act_spline = spline;
- mask_layer->act_point = point;
- ED_mask_select_flush_all(mask);
+ ED_mask_select_toggle_all(mask, SEL_DESELECT);
+
+ switch (which_handle) {
+ case MASK_WHICH_HANDLE_NONE:
+ BKE_mask_point_select_set(point, true);
+ break;
+ case MASK_WHICH_HANDLE_LEFT:
+ point->bezt.f1 |= SELECT;
+ break;
+ case MASK_WHICH_HANDLE_RIGHT:
+ point->bezt.f3 |= SELECT;
+ break;
+ case MASK_WHICH_HANDLE_STICK:
+ point->bezt.f1 |= SELECT;
+ point->bezt.f3 |= SELECT;
+ break;
+ default:
+ BLI_assert(!"Unexpected situation in select_sliding_point()");
+ }
+
+ mask_layer->act_spline = spline;
+ mask_layer->act_point = point;
+ ED_mask_select_flush_all(mask);
}
static void check_sliding_handle_type(MaskSplinePoint *point, eMaskWhichHandle which_handle)
{
- BezTriple *bezt = &point->bezt;
-
- if (which_handle == MASK_WHICH_HANDLE_LEFT) {
- if (bezt->h1 == HD_VECT) {
- bezt->h1 = HD_FREE;
- }
- else if (bezt->h1 == HD_AUTO) {
- bezt->h1 = HD_ALIGN_DOUBLESIDE;
- bezt->h2 = HD_ALIGN_DOUBLESIDE;
- }
- }
- else if (which_handle == MASK_WHICH_HANDLE_RIGHT) {
- if (bezt->h2 == HD_VECT) {
- bezt->h2 = HD_FREE;
- }
- else if (bezt->h2 == HD_AUTO) {
- bezt->h1 = HD_ALIGN_DOUBLESIDE;
- bezt->h2 = HD_ALIGN_DOUBLESIDE;
- }
- }
+ BezTriple *bezt = &point->bezt;
+
+ if (which_handle == MASK_WHICH_HANDLE_LEFT) {
+ if (bezt->h1 == HD_VECT) {
+ bezt->h1 = HD_FREE;
+ }
+ else if (bezt->h1 == HD_AUTO) {
+ bezt->h1 = HD_ALIGN_DOUBLESIDE;
+ bezt->h2 = HD_ALIGN_DOUBLESIDE;
+ }
+ }
+ else if (which_handle == MASK_WHICH_HANDLE_RIGHT) {
+ if (bezt->h2 == HD_VECT) {
+ bezt->h2 = HD_FREE;
+ }
+ else if (bezt->h2 == HD_AUTO) {
+ bezt->h1 = HD_ALIGN_DOUBLESIDE;
+ bezt->h2 = HD_ALIGN_DOUBLESIDE;
+ }
+ }
}
static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *event)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
-
- Mask *mask = CTX_data_edit_mask(C);
- SlidePointData *customdata = NULL;
- MaskLayer *masklay, *cv_masklay, *feather_masklay;
- MaskSpline *spline, *cv_spline, *feather_spline;
- MaskSplinePoint *point, *cv_point, *feather_point;
- MaskSplinePointUW *uw = NULL;
- int width, height, action = SLIDE_ACTION_NONE;
- const bool slide_feather = RNA_boolean_get(op->ptr, "slide_feather");
- float co[2], cv_score, feather_score;
- const float threshold = 19;
- eMaskWhichHandle which_handle;
-
- ED_mask_mouse_pos(sa, ar, event->mval, co);
- ED_mask_get_size(sa, &width, &height);
-
- cv_point = ED_mask_point_find_nearest(C, mask, co, threshold, &cv_masklay, &cv_spline, &which_handle, &cv_score);
-
- if (ED_mask_feather_find_nearest(C, mask, co, threshold, &feather_masklay, &feather_spline, &feather_point, &uw, &feather_score)) {
- if (slide_feather || !cv_point || feather_score < cv_score) {
- action = SLIDE_ACTION_FEATHER;
-
- masklay = feather_masklay;
- spline = feather_spline;
- point = feather_point;
- }
- }
-
- if (cv_point && action == SLIDE_ACTION_NONE) {
- if (which_handle != MASK_WHICH_HANDLE_NONE)
- action = SLIDE_ACTION_HANDLE;
- else
- action = SLIDE_ACTION_POINT;
-
- masklay = cv_masklay;
- spline = cv_spline;
- point = cv_point;
- }
-
- if (action == SLIDE_ACTION_NONE) {
- if (spline_under_mouse_get(C, mask, co, &masklay, &spline)) {
- action = SLIDE_ACTION_SPLINE;
- point = NULL;
- }
- }
-
- if (action != SLIDE_ACTION_NONE) {
- customdata = MEM_callocN(sizeof(SlidePointData), "mask slide point data");
- customdata->event_invoke_type = event->type;
- customdata->mask = mask;
- customdata->masklay = masklay;
- customdata->spline = spline;
- customdata->point = point;
- customdata->width = width;
- customdata->height = height;
- customdata->action = action;
- customdata->uw = uw;
-
- customdata->is_sliding_new_point = RNA_boolean_get(op->ptr, "is_new_point");
-
- if (customdata->action != SLIDE_ACTION_SPLINE) {
- customdata->old_h1 = point->bezt.h1;
- customdata->old_h2 = point->bezt.h2;
- select_sliding_point(mask, masklay, spline, point, which_handle);
- check_sliding_handle_type(point, which_handle);
- }
-
- if (uw) {
- float co_uw[2];
- float weight_scalar = BKE_mask_point_weight_scalar(spline, point, uw->u);
-
- customdata->weight = uw->w;
- customdata->weight_scalar = weight_scalar;
- BKE_mask_point_segment_co(spline, point, uw->u, co_uw);
- BKE_mask_point_normal(spline, point, uw->u, customdata->no);
-
- madd_v2_v2v2fl(customdata->prev_feather_coord, co_uw, customdata->no, uw->w * weight_scalar);
- }
- else if (customdata->action != SLIDE_ACTION_SPLINE) {
- BezTriple *bezt = &point->bezt;
-
- customdata->weight = bezt->weight;
- customdata->weight_scalar = 1.0f;
- BKE_mask_point_normal(spline, point, 0.0f, customdata->no);
-
- madd_v2_v2v2fl(customdata->prev_feather_coord, bezt->vec[1], customdata->no, bezt->weight);
- }
-
- if (customdata->action == SLIDE_ACTION_FEATHER) {
- customdata->is_initial_feather = slide_point_check_initial_feather(spline);
- }
-
- if (customdata->action != SLIDE_ACTION_SPLINE) {
- copy_m3_m3(customdata->vec, point->bezt.vec);
- if (which_handle != MASK_WHICH_HANDLE_NONE) {
- BKE_mask_point_handle(point, which_handle, customdata->orig_handle_coord);
- copy_v2_v2(customdata->prev_handle_coord, customdata->orig_handle_coord);
- }
- }
- customdata->which_handle = which_handle;
-
- ED_mask_mouse_pos(sa, ar, event->mval, customdata->prev_mouse_coord);
- }
-
- return customdata;
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ Mask *mask = CTX_data_edit_mask(C);
+ SlidePointData *customdata = NULL;
+ MaskLayer *masklay, *cv_masklay, *feather_masklay;
+ MaskSpline *spline, *cv_spline, *feather_spline;
+ MaskSplinePoint *point, *cv_point, *feather_point;
+ MaskSplinePointUW *uw = NULL;
+ int width, height, action = SLIDE_ACTION_NONE;
+ const bool slide_feather = RNA_boolean_get(op->ptr, "slide_feather");
+ float co[2], cv_score, feather_score;
+ const float threshold = 19;
+ eMaskWhichHandle which_handle;
+
+ ED_mask_mouse_pos(sa, ar, event->mval, co);
+ ED_mask_get_size(sa, &width, &height);
+
+ cv_point = ED_mask_point_find_nearest(
+ C, mask, co, threshold, &cv_masklay, &cv_spline, &which_handle, &cv_score);
+
+ if (ED_mask_feather_find_nearest(C,
+ mask,
+ co,
+ threshold,
+ &feather_masklay,
+ &feather_spline,
+ &feather_point,
+ &uw,
+ &feather_score)) {
+ if (slide_feather || !cv_point || feather_score < cv_score) {
+ action = SLIDE_ACTION_FEATHER;
+
+ masklay = feather_masklay;
+ spline = feather_spline;
+ point = feather_point;
+ }
+ }
+
+ if (cv_point && action == SLIDE_ACTION_NONE) {
+ if (which_handle != MASK_WHICH_HANDLE_NONE)
+ action = SLIDE_ACTION_HANDLE;
+ else
+ action = SLIDE_ACTION_POINT;
+
+ masklay = cv_masklay;
+ spline = cv_spline;
+ point = cv_point;
+ }
+
+ if (action == SLIDE_ACTION_NONE) {
+ if (spline_under_mouse_get(C, mask, co, &masklay, &spline)) {
+ action = SLIDE_ACTION_SPLINE;
+ point = NULL;
+ }
+ }
+
+ if (action != SLIDE_ACTION_NONE) {
+ customdata = MEM_callocN(sizeof(SlidePointData), "mask slide point data");
+ customdata->event_invoke_type = event->type;
+ customdata->mask = mask;
+ customdata->masklay = masklay;
+ customdata->spline = spline;
+ customdata->point = point;
+ customdata->width = width;
+ customdata->height = height;
+ customdata->action = action;
+ customdata->uw = uw;
+
+ customdata->is_sliding_new_point = RNA_boolean_get(op->ptr, "is_new_point");
+
+ if (customdata->action != SLIDE_ACTION_SPLINE) {
+ customdata->old_h1 = point->bezt.h1;
+ customdata->old_h2 = point->bezt.h2;
+ select_sliding_point(mask, masklay, spline, point, which_handle);
+ check_sliding_handle_type(point, which_handle);
+ }
+
+ if (uw) {
+ float co_uw[2];
+ float weight_scalar = BKE_mask_point_weight_scalar(spline, point, uw->u);
+
+ customdata->weight = uw->w;
+ customdata->weight_scalar = weight_scalar;
+ BKE_mask_point_segment_co(spline, point, uw->u, co_uw);
+ BKE_mask_point_normal(spline, point, uw->u, customdata->no);
+
+ madd_v2_v2v2fl(customdata->prev_feather_coord, co_uw, customdata->no, uw->w * weight_scalar);
+ }
+ else if (customdata->action != SLIDE_ACTION_SPLINE) {
+ BezTriple *bezt = &point->bezt;
+
+ customdata->weight = bezt->weight;
+ customdata->weight_scalar = 1.0f;
+ BKE_mask_point_normal(spline, point, 0.0f, customdata->no);
+
+ madd_v2_v2v2fl(customdata->prev_feather_coord, bezt->vec[1], customdata->no, bezt->weight);
+ }
+
+ if (customdata->action == SLIDE_ACTION_FEATHER) {
+ customdata->is_initial_feather = slide_point_check_initial_feather(spline);
+ }
+
+ if (customdata->action != SLIDE_ACTION_SPLINE) {
+ copy_m3_m3(customdata->vec, point->bezt.vec);
+ if (which_handle != MASK_WHICH_HANDLE_NONE) {
+ BKE_mask_point_handle(point, which_handle, customdata->orig_handle_coord);
+ copy_v2_v2(customdata->prev_handle_coord, customdata->orig_handle_coord);
+ }
+ }
+ customdata->which_handle = which_handle;
+
+ ED_mask_mouse_pos(sa, ar, event->mval, customdata->prev_mouse_coord);
+ }
+
+ return customdata;
}
static int slide_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Mask *mask = CTX_data_edit_mask(C);
- SlidePointData *slidedata;
+ Mask *mask = CTX_data_edit_mask(C);
+ SlidePointData *slidedata;
- if (mask == NULL) {
- return OPERATOR_PASS_THROUGH;
- }
+ if (mask == NULL) {
+ return OPERATOR_PASS_THROUGH;
+ }
- slidedata = slide_point_customdata(C, op, event);
+ slidedata = slide_point_customdata(C, op, event);
- if (slidedata) {
- op->customdata = slidedata;
+ if (slidedata) {
+ op->customdata = slidedata;
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
- slidedata->masklay->act_spline = slidedata->spline;
- slidedata->masklay->act_point = slidedata->point;
+ slidedata->masklay->act_spline = slidedata->spline;
+ slidedata->masklay->act_point = slidedata->point;
- WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
+ WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
- return OPERATOR_RUNNING_MODAL;
- }
+ return OPERATOR_RUNNING_MODAL;
+ }
- return OPERATOR_PASS_THROUGH;
+ return OPERATOR_PASS_THROUGH;
}
static void slide_point_delta_all_feather(SlidePointData *data, float delta)
{
- int i;
+ int i;
- for (i = 0; i < data->spline->tot_point; i++) {
- MaskSplinePoint *point = &data->spline->points[i];
- MaskSplinePoint *orig_point = &data->orig_spline->points[i];
+ for (i = 0; i < data->spline->tot_point; i++) {
+ MaskSplinePoint *point = &data->spline->points[i];
+ MaskSplinePoint *orig_point = &data->orig_spline->points[i];
- point->bezt.weight = orig_point->bezt.weight + delta;
- if (point->bezt.weight < 0.0f) {
- point->bezt.weight = 0.0f;
- }
- }
+ point->bezt.weight = orig_point->bezt.weight + delta;
+ if (point->bezt.weight < 0.0f) {
+ point->bezt.weight = 0.0f;
+ }
+ }
}
static void slide_point_restore_spline(SlidePointData *data)
{
- int i;
+ int i;
- for (i = 0; i < data->spline->tot_point; i++) {
- MaskSplinePoint *point = &data->spline->points[i];
- MaskSplinePoint *orig_point = &data->orig_spline->points[i];
- int j;
+ for (i = 0; i < data->spline->tot_point; i++) {
+ MaskSplinePoint *point = &data->spline->points[i];
+ MaskSplinePoint *orig_point = &data->orig_spline->points[i];
+ int j;
- point->bezt = orig_point->bezt;
+ point->bezt = orig_point->bezt;
- for (j = 0; j < point->tot_uw; j++)
- point->uw[j] = orig_point->uw[j];
- }
+ for (j = 0; j < point->tot_uw; j++)
+ point->uw[j] = orig_point->uw[j];
+ }
}
static void cancel_slide_point(SlidePointData *data)
{
- /* cancel sliding */
-
- if (data->orig_spline) {
- slide_point_restore_spline(data);
- }
- else {
- if (data->action == SLIDE_ACTION_FEATHER) {
- if (data->uw)
- data->uw->w = data->weight;
- else
- data->point->bezt.weight = data->weight;
- }
- else if (data->action != SLIDE_ACTION_SPLINE) {
- copy_m3_m3(data->point->bezt.vec, data->vec);
- data->point->bezt.h1 = data->old_h1;
- data->point->bezt.h2 = data->old_h2;
- }
- }
+ /* cancel sliding */
+
+ if (data->orig_spline) {
+ slide_point_restore_spline(data);
+ }
+ else {
+ if (data->action == SLIDE_ACTION_FEATHER) {
+ if (data->uw)
+ data->uw->w = data->weight;
+ else
+ data->point->bezt.weight = data->weight;
+ }
+ else if (data->action != SLIDE_ACTION_SPLINE) {
+ copy_m3_m3(data->point->bezt.vec, data->vec);
+ data->point->bezt.h1 = data->old_h1;
+ data->point->bezt.h2 = data->old_h2;
+ }
+ }
}
static void free_slide_point_data(SlidePointData *data)
{
- if (data->orig_spline)
- BKE_mask_spline_free(data->orig_spline);
+ if (data->orig_spline)
+ BKE_mask_spline_free(data->orig_spline);
- MEM_freeN(data);
+ MEM_freeN(data);
}
static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- SlidePointData *data = (SlidePointData *)op->customdata;
- BezTriple *bezt = &data->point->bezt;
- float co[2];
-
- switch (event->type) {
- case LEFTALTKEY:
- case RIGHTALTKEY:
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
- if (ELEM(event->type, LEFTALTKEY, RIGHTALTKEY)) {
- if (data->action == SLIDE_ACTION_FEATHER) {
- data->is_overall_feather = (event->val == KM_PRESS);
- }
- else {
- data->is_curvature_only = (event->val == KM_PRESS);
- }
- }
-
- if (ELEM(event->type, LEFTSHIFTKEY, 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);
- float delta[2];
-
- ED_mask_mouse_pos(sa, ar, event->mval, co);
- sub_v2_v2v2(delta, co, data->prev_mouse_coord);
- if (data->is_accurate) {
- mul_v2_fl(delta, 0.2f);
- }
- copy_v2_v2(data->prev_mouse_coord, co);
-
- if (data->action == SLIDE_ACTION_HANDLE) {
- float new_handle[2];
-
- if (data->is_sliding_new_point && data->which_handle == MASK_WHICH_HANDLE_STICK) {
- if (ELEM(data->point, &data->spline->points[0],
- &data->spline->points[data->spline->tot_point - 1]))
- {
- SWAP(float, delta[0], delta[1]);
- delta[1] *= -1;
-
- /* flip last point */
- if (data->point != &data->spline->points[0]) {
- negate_v2(delta);
- }
- }
- }
-
- add_v2_v2v2(new_handle, data->prev_handle_coord, delta);
-
- BKE_mask_point_set_handle(data->point, data->which_handle,
- new_handle, data->is_curvature_only,
- data->orig_handle_coord, data->vec);
- BKE_mask_point_handle(data->point, data->which_handle, data->prev_handle_coord);
-
- if (data->is_sliding_new_point) {
- if (ELEM(data->which_handle, MASK_WHICH_HANDLE_LEFT, MASK_WHICH_HANDLE_RIGHT)) {
- float vec[2];
- short self_handle = (data->which_handle == MASK_WHICH_HANDLE_LEFT) ? 0 : 2;
- short other_handle = (data->which_handle == MASK_WHICH_HANDLE_LEFT) ? 2 : 0;
-
- sub_v2_v2v2(vec, bezt->vec[1], bezt->vec[self_handle]);
- add_v2_v2v2(bezt->vec[other_handle], bezt->vec[1], vec);
- }
- }
- }
- else if (data->action == SLIDE_ACTION_POINT) {
- add_v2_v2(bezt->vec[0], delta);
- add_v2_v2(bezt->vec[1], delta);
- add_v2_v2(bezt->vec[2], delta);
- }
- else if (data->action == SLIDE_ACTION_FEATHER) {
- float vec[2], no[2], p[2], c[2], w, offco[2];
- float *weight = NULL;
- float weight_scalar = 1.0f;
- bool is_overall_feather = data->is_overall_feather || data->is_initial_feather;
-
- add_v2_v2v2(offco, data->prev_feather_coord, delta);
-
- if (data->uw) {
- /* project on both sides and find the closest one,
- * prevents flickering when projecting onto both sides can happen */
- const float u_pos = BKE_mask_spline_project_co(data->spline, data->point,
- data->uw->u, offco, MASK_PROJ_NEG);
- const float u_neg = BKE_mask_spline_project_co(data->spline, data->point,
- data->uw->u, offco, MASK_PROJ_POS);
- float dist_pos = FLT_MAX;
- float dist_neg = FLT_MAX;
- float co_pos[2];
- float co_neg[2];
- float u;
-
- if (u_pos > 0.0f && u_pos < 1.0f) {
- BKE_mask_point_segment_co(data->spline, data->point, u_pos, co_pos);
- dist_pos = len_squared_v2v2(offco, co_pos);
- }
-
- if (u_neg > 0.0f && u_neg < 1.0f) {
- BKE_mask_point_segment_co(data->spline, data->point, u_neg, co_neg);
- dist_neg = len_squared_v2v2(offco, co_neg);
- }
-
- u = dist_pos < dist_neg ? u_pos : u_neg;
-
- if (u > 0.0f && u < 1.0f) {
- data->uw->u = u;
-
- data->uw = BKE_mask_point_sort_uw(data->point, data->uw);
- weight = &data->uw->w;
- weight_scalar = BKE_mask_point_weight_scalar(data->spline, data->point, u);
- if (weight_scalar != 0.0f) {
- weight_scalar = 1.0f / weight_scalar;
- }
-
- BKE_mask_point_normal(data->spline, data->point, data->uw->u, no);
- BKE_mask_point_segment_co(data->spline, data->point, data->uw->u, p);
- }
- }
- else {
- weight = &bezt->weight;
- /* weight_scalar = 1.0f; keep as is */
- copy_v2_v2(no, data->no);
- copy_v2_v2(p, bezt->vec[1]);
- }
-
- if (weight) {
- sub_v2_v2v2(c, offco, p);
- project_v2_v2v2_normalized(vec, c, no);
-
- w = len_v2(vec);
-
- if (is_overall_feather) {
- float w_delta;
-
- if (dot_v2v2(no, vec) <= 0.0f)
- w = -w;
-
- w_delta = w - data->weight * data->weight_scalar;
-
- if (data->orig_spline == NULL) {
- /* restore weight for currently sliding point, so orig_spline would be created
- * with original weights used
- */
- *weight = data->weight;
-
- data->orig_spline = BKE_mask_spline_copy(data->spline);
- }
-
- if (data->is_initial_feather) {
- *weight = w * weight_scalar;
- }
-
- slide_point_delta_all_feather(data, w_delta);
- }
- else {
- if (dot_v2v2(no, vec) <= 0.0f)
- w = 0.0f;
-
- if (data->orig_spline) {
- /* restore possible overall feather changes */
- slide_point_restore_spline(data);
-
- BKE_mask_spline_free(data->orig_spline);
- data->orig_spline = NULL;
- }
-
- if (weight_scalar != 0.0f) {
- *weight = w * weight_scalar;
- }
- }
-
- copy_v2_v2(data->prev_feather_coord, offco);
- }
- }
- else if (data->action == SLIDE_ACTION_SPLINE) {
- int i;
-
- if (data->orig_spline == NULL) {
- data->orig_spline = BKE_mask_spline_copy(data->spline);
- }
-
- for (i = 0; i < data->spline->tot_point; i++) {
- MaskSplinePoint *point = &data->spline->points[i];
- add_v2_v2(point->bezt.vec[0], delta);
- add_v2_v2(point->bezt.vec[1], delta);
- add_v2_v2(point->bezt.vec[2], delta);
- }
- }
-
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
- DEG_id_tag_update(&data->mask->id, 0);
-
- break;
- }
-
- case LEFTMOUSE:
- case RIGHTMOUSE:
- if (event->type == data->event_invoke_type && event->val == KM_RELEASE) {
- Scene *scene = CTX_data_scene(C);
-
- /* dont key sliding feather uw's */
- if ((data->action == SLIDE_ACTION_FEATHER && data->uw) == false) {
- if (IS_AUTOKEY_ON(scene)) {
- ED_mask_layer_shape_auto_key(data->masklay, CFRA);
- }
- }
-
- if (data->is_sliding_new_point) {
- if (len_squared_v2v2(bezt->vec[0], bezt->vec[1]) < FLT_EPSILON) {
- bezt->h1 = HD_VECT;
- }
- if (len_squared_v2v2(bezt->vec[2], bezt->vec[1]) < FLT_EPSILON) {
- bezt->h2 = HD_VECT;
- }
- }
-
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
- DEG_id_tag_update(&data->mask->id, 0);
-
- free_slide_point_data(op->customdata); /* keep this last! */
- return OPERATOR_FINISHED;
- }
- else if (event->type != data->event_invoke_type && event->val == KM_PRESS) {
- /* pass to ESCKEY */
- }
- else {
- break;
- }
-
- case ESCKEY:
- cancel_slide_point(op->customdata);
-
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
- DEG_id_tag_update(&data->mask->id, 0);
-
- free_slide_point_data(op->customdata); /* keep this last! */
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_RUNNING_MODAL;
+ SlidePointData *data = (SlidePointData *)op->customdata;
+ BezTriple *bezt = &data->point->bezt;
+ float co[2];
+
+ switch (event->type) {
+ case LEFTALTKEY:
+ case RIGHTALTKEY:
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ if (ELEM(event->type, LEFTALTKEY, RIGHTALTKEY)) {
+ if (data->action == SLIDE_ACTION_FEATHER) {
+ data->is_overall_feather = (event->val == KM_PRESS);
+ }
+ else {
+ data->is_curvature_only = (event->val == KM_PRESS);
+ }
+ }
+
+ if (ELEM(event->type, LEFTSHIFTKEY, 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);
+ float delta[2];
+
+ ED_mask_mouse_pos(sa, ar, event->mval, co);
+ sub_v2_v2v2(delta, co, data->prev_mouse_coord);
+ if (data->is_accurate) {
+ mul_v2_fl(delta, 0.2f);
+ }
+ copy_v2_v2(data->prev_mouse_coord, co);
+
+ if (data->action == SLIDE_ACTION_HANDLE) {
+ float new_handle[2];
+
+ if (data->is_sliding_new_point && data->which_handle == MASK_WHICH_HANDLE_STICK) {
+ if (ELEM(data->point,
+ &data->spline->points[0],
+ &data->spline->points[data->spline->tot_point - 1])) {
+ SWAP(float, delta[0], delta[1]);
+ delta[1] *= -1;
+
+ /* flip last point */
+ if (data->point != &data->spline->points[0]) {
+ negate_v2(delta);
+ }
+ }
+ }
+
+ add_v2_v2v2(new_handle, data->prev_handle_coord, delta);
+
+ BKE_mask_point_set_handle(data->point,
+ data->which_handle,
+ new_handle,
+ data->is_curvature_only,
+ data->orig_handle_coord,
+ data->vec);
+ BKE_mask_point_handle(data->point, data->which_handle, data->prev_handle_coord);
+
+ if (data->is_sliding_new_point) {
+ if (ELEM(data->which_handle, MASK_WHICH_HANDLE_LEFT, MASK_WHICH_HANDLE_RIGHT)) {
+ float vec[2];
+ short self_handle = (data->which_handle == MASK_WHICH_HANDLE_LEFT) ? 0 : 2;
+ short other_handle = (data->which_handle == MASK_WHICH_HANDLE_LEFT) ? 2 : 0;
+
+ sub_v2_v2v2(vec, bezt->vec[1], bezt->vec[self_handle]);
+ add_v2_v2v2(bezt->vec[other_handle], bezt->vec[1], vec);
+ }
+ }
+ }
+ else if (data->action == SLIDE_ACTION_POINT) {
+ add_v2_v2(bezt->vec[0], delta);
+ add_v2_v2(bezt->vec[1], delta);
+ add_v2_v2(bezt->vec[2], delta);
+ }
+ else if (data->action == SLIDE_ACTION_FEATHER) {
+ float vec[2], no[2], p[2], c[2], w, offco[2];
+ float *weight = NULL;
+ float weight_scalar = 1.0f;
+ bool is_overall_feather = data->is_overall_feather || data->is_initial_feather;
+
+ add_v2_v2v2(offco, data->prev_feather_coord, delta);
+
+ if (data->uw) {
+ /* project on both sides and find the closest one,
+ * prevents flickering when projecting onto both sides can happen */
+ const float u_pos = BKE_mask_spline_project_co(
+ data->spline, data->point, data->uw->u, offco, MASK_PROJ_NEG);
+ const float u_neg = BKE_mask_spline_project_co(
+ data->spline, data->point, data->uw->u, offco, MASK_PROJ_POS);
+ float dist_pos = FLT_MAX;
+ float dist_neg = FLT_MAX;
+ float co_pos[2];
+ float co_neg[2];
+ float u;
+
+ if (u_pos > 0.0f && u_pos < 1.0f) {
+ BKE_mask_point_segment_co(data->spline, data->point, u_pos, co_pos);
+ dist_pos = len_squared_v2v2(offco, co_pos);
+ }
+
+ if (u_neg > 0.0f && u_neg < 1.0f) {
+ BKE_mask_point_segment_co(data->spline, data->point, u_neg, co_neg);
+ dist_neg = len_squared_v2v2(offco, co_neg);
+ }
+
+ u = dist_pos < dist_neg ? u_pos : u_neg;
+
+ if (u > 0.0f && u < 1.0f) {
+ data->uw->u = u;
+
+ data->uw = BKE_mask_point_sort_uw(data->point, data->uw);
+ weight = &data->uw->w;
+ weight_scalar = BKE_mask_point_weight_scalar(data->spline, data->point, u);
+ if (weight_scalar != 0.0f) {
+ weight_scalar = 1.0f / weight_scalar;
+ }
+
+ BKE_mask_point_normal(data->spline, data->point, data->uw->u, no);
+ BKE_mask_point_segment_co(data->spline, data->point, data->uw->u, p);
+ }
+ }
+ else {
+ weight = &bezt->weight;
+ /* weight_scalar = 1.0f; keep as is */
+ copy_v2_v2(no, data->no);
+ copy_v2_v2(p, bezt->vec[1]);
+ }
+
+ if (weight) {
+ sub_v2_v2v2(c, offco, p);
+ project_v2_v2v2_normalized(vec, c, no);
+
+ w = len_v2(vec);
+
+ if (is_overall_feather) {
+ float w_delta;
+
+ if (dot_v2v2(no, vec) <= 0.0f)
+ w = -w;
+
+ w_delta = w - data->weight * data->weight_scalar;
+
+ if (data->orig_spline == NULL) {
+ /* restore weight for currently sliding point, so orig_spline would be created
+ * with original weights used
+ */
+ *weight = data->weight;
+
+ data->orig_spline = BKE_mask_spline_copy(data->spline);
+ }
+
+ if (data->is_initial_feather) {
+ *weight = w * weight_scalar;
+ }
+
+ slide_point_delta_all_feather(data, w_delta);
+ }
+ else {
+ if (dot_v2v2(no, vec) <= 0.0f)
+ w = 0.0f;
+
+ if (data->orig_spline) {
+ /* restore possible overall feather changes */
+ slide_point_restore_spline(data);
+
+ BKE_mask_spline_free(data->orig_spline);
+ data->orig_spline = NULL;
+ }
+
+ if (weight_scalar != 0.0f) {
+ *weight = w * weight_scalar;
+ }
+ }
+
+ copy_v2_v2(data->prev_feather_coord, offco);
+ }
+ }
+ else if (data->action == SLIDE_ACTION_SPLINE) {
+ int i;
+
+ if (data->orig_spline == NULL) {
+ data->orig_spline = BKE_mask_spline_copy(data->spline);
+ }
+
+ for (i = 0; i < data->spline->tot_point; i++) {
+ MaskSplinePoint *point = &data->spline->points[i];
+ add_v2_v2(point->bezt.vec[0], delta);
+ add_v2_v2(point->bezt.vec[1], delta);
+ add_v2_v2(point->bezt.vec[2], delta);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
+ DEG_id_tag_update(&data->mask->id, 0);
+
+ break;
+ }
+
+ case LEFTMOUSE:
+ case RIGHTMOUSE:
+ if (event->type == data->event_invoke_type && event->val == KM_RELEASE) {
+ Scene *scene = CTX_data_scene(C);
+
+ /* dont key sliding feather uw's */
+ if ((data->action == SLIDE_ACTION_FEATHER && data->uw) == false) {
+ if (IS_AUTOKEY_ON(scene)) {
+ ED_mask_layer_shape_auto_key(data->masklay, CFRA);
+ }
+ }
+
+ if (data->is_sliding_new_point) {
+ if (len_squared_v2v2(bezt->vec[0], bezt->vec[1]) < FLT_EPSILON) {
+ bezt->h1 = HD_VECT;
+ }
+ if (len_squared_v2v2(bezt->vec[2], bezt->vec[1]) < FLT_EPSILON) {
+ bezt->h2 = HD_VECT;
+ }
+ }
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
+ DEG_id_tag_update(&data->mask->id, 0);
+
+ free_slide_point_data(op->customdata); /* keep this last! */
+ return OPERATOR_FINISHED;
+ }
+ else if (event->type != data->event_invoke_type && event->val == KM_PRESS) {
+ /* pass to ESCKEY */
+ }
+ else {
+ break;
+ }
+
+ case ESCKEY:
+ cancel_slide_point(op->customdata);
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
+ DEG_id_tag_update(&data->mask->id, 0);
+
+ free_slide_point_data(op->customdata); /* keep this last! */
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
void MASK_OT_slide_point(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Slide Point";
- ot->description = "Slide control points";
- ot->idname = "MASK_OT_slide_point";
-
- /* api callbacks */
- ot->invoke = slide_point_invoke;
- ot->modal = slide_point_modal;
- ot->poll = ED_operator_mask;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "slide_feather", 0, "Slide Feather", "First try to slide feather instead of vertex");
-
- prop = RNA_def_boolean(ot->srna, "is_new_point", 0, "Slide New Point", "Newly created vertex is being slid");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Slide Point";
+ ot->description = "Slide control points";
+ ot->idname = "MASK_OT_slide_point";
+
+ /* api callbacks */
+ ot->invoke = slide_point_invoke;
+ ot->modal = slide_point_modal;
+ ot->poll = ED_operator_mask;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna,
+ "slide_feather",
+ 0,
+ "Slide Feather",
+ "First try to slide feather instead of vertex");
+
+ prop = RNA_def_boolean(
+ ot->srna, "is_new_point", 0, "Slide New Point", "Newly created vertex is being slid");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/******************** slide spline curvature *********************/
typedef struct SlideSplineCurvatureData {
- short event_invoke_type;
+ short event_invoke_type;
- Mask *mask;
- MaskLayer *mask_layer;
- MaskSpline *spline;
- MaskSplinePoint *point;
- float u;
- bool accurate;
+ Mask *mask;
+ MaskLayer *mask_layer;
+ MaskSpline *spline;
+ MaskSplinePoint *point;
+ float u;
+ bool accurate;
- BezTriple *adjust_bezt, *other_bezt;
- BezTriple bezt_backup, other_bezt_backup;
+ BezTriple *adjust_bezt, *other_bezt;
+ BezTriple bezt_backup, other_bezt_backup;
- float prev_mouse_coord[2];
- float prev_spline_coord[2];
+ float prev_mouse_coord[2];
+ float prev_spline_coord[2];
- float P0[2], P1[2], P2[2], P3[3];
+ float P0[2], P1[2], P2[2], P3[3];
} SlideSplineCurvatureData;
static void cancel_slide_spline_curvature(SlideSplineCurvatureData *slide_data)
{
- *slide_data->adjust_bezt = slide_data->bezt_backup;
- *slide_data->other_bezt = slide_data->other_bezt_backup;
+ *slide_data->adjust_bezt = slide_data->bezt_backup;
+ *slide_data->other_bezt = slide_data->other_bezt_backup;
}
-
static void free_slide_spline_curvature_data(SlideSplineCurvatureData *slide_data)
{
- MEM_freeN(slide_data);
+ MEM_freeN(slide_data);
}
static bool slide_spline_curvature_check(bContext *C, const wmEvent *event)
{
- Mask *mask = CTX_data_edit_mask(C);
- float co[2];
- const float threshold = 19.0f;
+ Mask *mask = CTX_data_edit_mask(C);
+ float co[2];
+ const float threshold = 19.0f;
- ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, co);
+ ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, co);
- if (ED_mask_point_find_nearest(C, mask, co, threshold, NULL, NULL, NULL, NULL)) {
- return false;
- }
+ if (ED_mask_point_find_nearest(C, mask, co, threshold, NULL, NULL, NULL, NULL)) {
+ return false;
+ }
- if (ED_mask_feather_find_nearest(C, mask, co, threshold, NULL, NULL, NULL, NULL, NULL)) {
- return false;
- }
+ if (ED_mask_feather_find_nearest(C, mask, co, threshold, NULL, NULL, NULL, NULL, NULL)) {
+ return false;
+ }
- return true;
+ return true;
}
-static SlideSplineCurvatureData *slide_spline_curvature_customdata(
- bContext *C, const wmEvent *event)
+static SlideSplineCurvatureData *slide_spline_curvature_customdata(bContext *C,
+ const wmEvent *event)
{
- const float threshold = 19.0f;
-
- Mask *mask = CTX_data_edit_mask(C);
- SlideSplineCurvatureData *slide_data;
- MaskLayer *mask_layer;
- MaskSpline *spline;
- MaskSplinePoint *point;
- float u, co[2];
- BezTriple *next_bezt;
-
- ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, co);
-
- if (!ED_mask_find_nearest_diff_point(C, mask, co, threshold, false,
- NULL, true, false,
- &mask_layer, &spline, &point, &u,
- NULL))
- {
- return NULL;
- }
-
- next_bezt = BKE_mask_spline_point_next_bezt(spline, spline->points, point);
- if (next_bezt == NULL) {
- return NULL;
- }
-
- slide_data = MEM_callocN(sizeof(SlideSplineCurvatureData), "slide curvature slide");
- slide_data->event_invoke_type = event->type;
- slide_data->mask = mask;
- slide_data->mask_layer = mask_layer;
- slide_data->spline = spline;
- slide_data->point = point;
- slide_data->u = u;
-
- copy_v2_v2(slide_data->prev_mouse_coord, co);
- BKE_mask_point_segment_co(spline, point, u, slide_data->prev_spline_coord);
-
- copy_v2_v2(slide_data->P0, point->bezt.vec[1]);
- copy_v2_v2(slide_data->P1, point->bezt.vec[2]);
- copy_v2_v2(slide_data->P2, next_bezt->vec[0]);
- copy_v2_v2(slide_data->P3, next_bezt->vec[1]);
-
- /* Depending to which end we're closer to adjust either left or right side of the spline. */
- if (u <= 0.5f) {
- slide_data->adjust_bezt = &point->bezt;
- slide_data->other_bezt = next_bezt;
- }
- else {
- slide_data->adjust_bezt = next_bezt;
- slide_data->other_bezt = &point->bezt;
- }
-
- /* Data needed for restoring state. */
- slide_data->bezt_backup = *slide_data->adjust_bezt;
- slide_data->other_bezt_backup = *slide_data->other_bezt;
-
- /* Let's dont touch other side of the point for now, so set handle to FREE. */
- if (u < 0.5f) {
- if (slide_data->adjust_bezt->h2 <= HD_VECT) {
- slide_data->adjust_bezt->h2 = HD_FREE;
- }
- }
- else {
- if (slide_data->adjust_bezt->h1 <= HD_VECT) {
- slide_data->adjust_bezt->h1 = HD_FREE;
- }
- }
-
- /* Change selection */
- ED_mask_select_toggle_all(mask, SEL_DESELECT);
- slide_data->adjust_bezt->f2 |= SELECT;
- slide_data->other_bezt->f2 |= SELECT;
- if (u < 0.5f) {
- slide_data->adjust_bezt->f3 |= SELECT;
- slide_data->other_bezt->f1 |= SELECT;
- }
- else {
- slide_data->adjust_bezt->f1 |= SELECT;
- slide_data->other_bezt->f3 |= SELECT;
- }
- mask_layer->act_spline = spline;
- mask_layer->act_point = point;
- ED_mask_select_flush_all(mask);
-
- return slide_data;
+ const float threshold = 19.0f;
+
+ Mask *mask = CTX_data_edit_mask(C);
+ SlideSplineCurvatureData *slide_data;
+ MaskLayer *mask_layer;
+ MaskSpline *spline;
+ MaskSplinePoint *point;
+ float u, co[2];
+ BezTriple *next_bezt;
+
+ ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, co);
+
+ if (!ED_mask_find_nearest_diff_point(C,
+ mask,
+ co,
+ threshold,
+ false,
+ NULL,
+ true,
+ false,
+ &mask_layer,
+ &spline,
+ &point,
+ &u,
+ NULL)) {
+ return NULL;
+ }
+
+ next_bezt = BKE_mask_spline_point_next_bezt(spline, spline->points, point);
+ if (next_bezt == NULL) {
+ return NULL;
+ }
+
+ slide_data = MEM_callocN(sizeof(SlideSplineCurvatureData), "slide curvature slide");
+ slide_data->event_invoke_type = event->type;
+ slide_data->mask = mask;
+ slide_data->mask_layer = mask_layer;
+ slide_data->spline = spline;
+ slide_data->point = point;
+ slide_data->u = u;
+
+ copy_v2_v2(slide_data->prev_mouse_coord, co);
+ BKE_mask_point_segment_co(spline, point, u, slide_data->prev_spline_coord);
+
+ copy_v2_v2(slide_data->P0, point->bezt.vec[1]);
+ copy_v2_v2(slide_data->P1, point->bezt.vec[2]);
+ copy_v2_v2(slide_data->P2, next_bezt->vec[0]);
+ copy_v2_v2(slide_data->P3, next_bezt->vec[1]);
+
+ /* Depending to which end we're closer to adjust either left or right side of the spline. */
+ if (u <= 0.5f) {
+ slide_data->adjust_bezt = &point->bezt;
+ slide_data->other_bezt = next_bezt;
+ }
+ else {
+ slide_data->adjust_bezt = next_bezt;
+ slide_data->other_bezt = &point->bezt;
+ }
+
+ /* Data needed for restoring state. */
+ slide_data->bezt_backup = *slide_data->adjust_bezt;
+ slide_data->other_bezt_backup = *slide_data->other_bezt;
+
+ /* Let's dont touch other side of the point for now, so set handle to FREE. */
+ if (u < 0.5f) {
+ if (slide_data->adjust_bezt->h2 <= HD_VECT) {
+ slide_data->adjust_bezt->h2 = HD_FREE;
+ }
+ }
+ else {
+ if (slide_data->adjust_bezt->h1 <= HD_VECT) {
+ slide_data->adjust_bezt->h1 = HD_FREE;
+ }
+ }
+
+ /* Change selection */
+ ED_mask_select_toggle_all(mask, SEL_DESELECT);
+ slide_data->adjust_bezt->f2 |= SELECT;
+ slide_data->other_bezt->f2 |= SELECT;
+ if (u < 0.5f) {
+ slide_data->adjust_bezt->f3 |= SELECT;
+ slide_data->other_bezt->f1 |= SELECT;
+ }
+ else {
+ slide_data->adjust_bezt->f1 |= SELECT;
+ slide_data->other_bezt->f3 |= SELECT;
+ }
+ mask_layer->act_spline = spline;
+ mask_layer->act_point = point;
+ ED_mask_select_flush_all(mask);
+
+ return slide_data;
}
static int slide_spline_curvature_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Mask *mask = CTX_data_edit_mask(C);
- SlideSplineCurvatureData *slide_data;
-
- if (mask == NULL) {
- return OPERATOR_PASS_THROUGH;
- }
-
- /* Be sure we don't conflict with point slide here. */
- if (!slide_spline_curvature_check(C, event)) {
- return OPERATOR_PASS_THROUGH;
- }
-
- slide_data = slide_spline_curvature_customdata(C, event);
- if (slide_data != NULL) {
- op->customdata = slide_data;
- WM_event_add_modal_handler(C, op);
- WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
- return OPERATOR_RUNNING_MODAL;
- }
-
- return OPERATOR_PASS_THROUGH;
+ Mask *mask = CTX_data_edit_mask(C);
+ SlideSplineCurvatureData *slide_data;
+
+ if (mask == NULL) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ /* Be sure we don't conflict with point slide here. */
+ if (!slide_spline_curvature_check(C, event)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ slide_data = slide_spline_curvature_customdata(C, event);
+ if (slide_data != NULL) {
+ op->customdata = slide_data;
+ WM_event_add_modal_handler(C, op);
+ WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ return OPERATOR_PASS_THROUGH;
}
static void slide_spline_solve_P1(const float u,
@@ -1307,13 +1344,13 @@ static void slide_spline_solve_P1(const float u,
const float P3[2],
float solution[2])
{
- const float u2 = u * u, u3 = u * u * u;
- const float v = 1.0f - u;
- const float v2 = v * v, v3 = v * v * v;
- const float inv_divider = 1.0f / (3.0f * v2 * u);
- const float t = 3.0f * v * u2;
- solution[0] = -(v3 * P0[0] + t * P2[0] + u3 * P3[0] - B[0]) * inv_divider;
- solution[1] = -(v3 * P0[1] + t * P2[1] + u3 * P3[1] - B[1]) * inv_divider;
+ const float u2 = u * u, u3 = u * u * u;
+ const float v = 1.0f - u;
+ const float v2 = v * v, v3 = v * v * v;
+ const float inv_divider = 1.0f / (3.0f * v2 * u);
+ const float t = 3.0f * v * u2;
+ solution[0] = -(v3 * P0[0] + t * P2[0] + u3 * P3[0] - B[0]) * inv_divider;
+ solution[1] = -(v3 * P0[1] + t * P2[1] + u3 * P3[1] - B[1]) * inv_divider;
}
static void slide_spline_solve_P2(const float u,
@@ -1323,1055 +1360,1032 @@ static void slide_spline_solve_P2(const float u,
const float P3[2],
float solution[2])
{
- const float u2 = u * u, u3 = u * u * u;
- const float v = 1.0f - u;
- const float v2 = v * v, v3 = v * v * v;
- const float inv_divider = 1.0f / (3.0f * v * u2);
- const float t = 3.0f * v2 * u;
- solution[0] = -(v3 * P0[0] + t * P1[0] + u3 * P3[0] - B[0]) * inv_divider;
- solution[1] = -(v3 * P0[1] + t * P1[1] + u3 * P3[1] - B[1]) * inv_divider;
+ const float u2 = u * u, u3 = u * u * u;
+ const float v = 1.0f - u;
+ const float v2 = v * v, v3 = v * v * v;
+ const float inv_divider = 1.0f / (3.0f * v * u2);
+ const float t = 3.0f * v2 * u;
+ solution[0] = -(v3 * P0[0] + t * P1[0] + u3 * P3[0] - B[0]) * inv_divider;
+ solution[1] = -(v3 * P0[1] + t * P1[1] + u3 * P3[1] - B[1]) * inv_divider;
}
static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- Scene *scene = CTX_data_scene(C);
- const float margin = 0.2f;
- SlideSplineCurvatureData *slide_data = (SlideSplineCurvatureData *) op->customdata;
- float u = slide_data->u;
-
- switch (event->type) {
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
- case LEFTCTRLKEY:
- case RIGHTCTRLKEY:
- if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) {
- slide_data->accurate = (event->val == KM_PRESS);
- }
-
- if (ELEM(event->type, LEFTCTRLKEY, 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)) {
- slide_data->other_bezt->h1 = slide_data->other_bezt->h2 = HD_FREE;
- }
- }
- else if (event->val == KM_RELEASE) {
- slide_data->adjust_bezt->h1 = slide_data->bezt_backup.h1;
- slide_data->adjust_bezt->h2 = slide_data->bezt_backup.h2;
- slide_data->other_bezt->h1 = slide_data->other_bezt_backup.h1;
- slide_data->other_bezt->h2 = slide_data->other_bezt_backup.h2;
- }
-
- if (u < 0.5f) {
- copy_v2_v2(slide_data->adjust_bezt->vec[0], slide_data->bezt_backup.vec[0]);
- copy_v2_v2(slide_data->other_bezt->vec[2], slide_data->other_bezt_backup.vec[2]);
- }
- else {
- copy_v2_v2(slide_data->adjust_bezt->vec[2], slide_data->bezt_backup.vec[2]);
- copy_v2_v2(slide_data->other_bezt->vec[0], slide_data->other_bezt_backup.vec[0]);
- }
-
- }
-
- ATTR_FALLTHROUGH; /* update CV position */
- case MOUSEMOVE:
- {
- float B[2], mouse_coord[2], delta[2];
-
- /* Get coordinate spline is expected to go through. */
- ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, mouse_coord);
- sub_v2_v2v2(delta, mouse_coord, slide_data->prev_mouse_coord);
- if (slide_data->accurate) {
- mul_v2_fl(delta, 0.2f);
- }
- add_v2_v2v2(B, slide_data->prev_spline_coord, delta);
- copy_v2_v2(slide_data->prev_spline_coord, B);
- copy_v2_v2(slide_data->prev_mouse_coord, mouse_coord);
-
- if (u < 0.5f) {
- float oldP2[2];
- bool need_restore_P2 = false;
-
- if (u > margin) {
- float solution[2];
- float x = (u - margin) * 0.5f / (0.5f - margin);
- float weight = (3 * x * x - 2 * x * x * x);
-
- slide_spline_solve_P2(u, B,
- slide_data->P0,
- slide_data->P1,
- slide_data->P3,
- solution);
-
- copy_v2_v2(oldP2, slide_data->P2);
- interp_v2_v2v2(slide_data->P2, slide_data->P2, solution, weight);
- copy_v2_v2(slide_data->other_bezt->vec[0], slide_data->P2);
- need_restore_P2 = true;
-
- /* Tweak handle type in order to be able to apply the delta. */
- if (weight > 0.0f) {
- if (slide_data->other_bezt->h1 <= HD_VECT) {
- slide_data->other_bezt->h1 = HD_FREE;
- }
- }
- }
-
- slide_spline_solve_P1(u, B,
- slide_data->P0,
- slide_data->P2,
- slide_data->P3,
- slide_data->adjust_bezt->vec[2]);
-
- if (need_restore_P2) {
- copy_v2_v2(slide_data->P2, oldP2);
- }
- }
- else {
- float oldP1[2];
- bool need_restore_P1 = false;
-
- if (u < 1.0f - margin) {
- float solution[2];
- float x = ((1.0f - u) - margin) * 0.5f / (0.5f - margin);
- float weight = 3 * x * x - 2 * x * x * x;
-
- slide_spline_solve_P1(u, B,
- slide_data->P0,
- slide_data->P2,
- slide_data->P3,
- solution);
-
- copy_v2_v2(oldP1, slide_data->P1);
- interp_v2_v2v2(slide_data->P1, slide_data->P1, solution, weight);
- copy_v2_v2(slide_data->other_bezt->vec[2], slide_data->P1);
- need_restore_P1 = true;
-
- /* Tweak handle type in order to be able to apply the delta. */
- if (weight > 0.0f) {
- if (slide_data->other_bezt->h2 <= HD_VECT) {
- slide_data->other_bezt->h2 = HD_FREE;
- }
- }
- }
-
- slide_spline_solve_P2(u, B,
- slide_data->P0,
- slide_data->P1,
- slide_data->P3,
- slide_data->adjust_bezt->vec[0]);
-
- if (need_restore_P1) {
- copy_v2_v2(slide_data->P1, oldP1);
- }
- }
-
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
- DEG_id_tag_update(&slide_data->mask->id, 0);
-
- break;
- }
-
- case LEFTMOUSE:
- case RIGHTMOUSE:
- if (event->type == slide_data->event_invoke_type && event->val == KM_RELEASE) {
- /* dont key sliding feather uw's */
- if (IS_AUTOKEY_ON(scene)) {
- ED_mask_layer_shape_auto_key(slide_data->mask_layer, CFRA);
- }
-
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
- DEG_id_tag_update(&slide_data->mask->id, 0);
-
- free_slide_spline_curvature_data(slide_data); /* keep this last! */
- return OPERATOR_FINISHED;
- }
-
- break;
-
- case ESCKEY:
- cancel_slide_spline_curvature(slide_data);
-
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
- DEG_id_tag_update(&slide_data->mask->id, 0);
-
- free_slide_spline_curvature_data(op->customdata); /* keep this last! */
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_RUNNING_MODAL;
+ Scene *scene = CTX_data_scene(C);
+ const float margin = 0.2f;
+ SlideSplineCurvatureData *slide_data = (SlideSplineCurvatureData *)op->customdata;
+ float u = slide_data->u;
+
+ switch (event->type) {
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ case LEFTCTRLKEY:
+ case RIGHTCTRLKEY:
+ if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) {
+ slide_data->accurate = (event->val == KM_PRESS);
+ }
+
+ if (ELEM(event->type, LEFTCTRLKEY, 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)) {
+ slide_data->other_bezt->h1 = slide_data->other_bezt->h2 = HD_FREE;
+ }
+ }
+ else if (event->val == KM_RELEASE) {
+ slide_data->adjust_bezt->h1 = slide_data->bezt_backup.h1;
+ slide_data->adjust_bezt->h2 = slide_data->bezt_backup.h2;
+ slide_data->other_bezt->h1 = slide_data->other_bezt_backup.h1;
+ slide_data->other_bezt->h2 = slide_data->other_bezt_backup.h2;
+ }
+
+ if (u < 0.5f) {
+ copy_v2_v2(slide_data->adjust_bezt->vec[0], slide_data->bezt_backup.vec[0]);
+ copy_v2_v2(slide_data->other_bezt->vec[2], slide_data->other_bezt_backup.vec[2]);
+ }
+ else {
+ copy_v2_v2(slide_data->adjust_bezt->vec[2], slide_data->bezt_backup.vec[2]);
+ copy_v2_v2(slide_data->other_bezt->vec[0], slide_data->other_bezt_backup.vec[0]);
+ }
+ }
+
+ ATTR_FALLTHROUGH; /* update CV position */
+ case MOUSEMOVE: {
+ float B[2], mouse_coord[2], delta[2];
+
+ /* Get coordinate spline is expected to go through. */
+ ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, mouse_coord);
+ sub_v2_v2v2(delta, mouse_coord, slide_data->prev_mouse_coord);
+ if (slide_data->accurate) {
+ mul_v2_fl(delta, 0.2f);
+ }
+ add_v2_v2v2(B, slide_data->prev_spline_coord, delta);
+ copy_v2_v2(slide_data->prev_spline_coord, B);
+ copy_v2_v2(slide_data->prev_mouse_coord, mouse_coord);
+
+ if (u < 0.5f) {
+ float oldP2[2];
+ bool need_restore_P2 = false;
+
+ if (u > margin) {
+ float solution[2];
+ float x = (u - margin) * 0.5f / (0.5f - margin);
+ float weight = (3 * x * x - 2 * x * x * x);
+
+ slide_spline_solve_P2(u, B, slide_data->P0, slide_data->P1, slide_data->P3, solution);
+
+ copy_v2_v2(oldP2, slide_data->P2);
+ interp_v2_v2v2(slide_data->P2, slide_data->P2, solution, weight);
+ copy_v2_v2(slide_data->other_bezt->vec[0], slide_data->P2);
+ need_restore_P2 = true;
+
+ /* Tweak handle type in order to be able to apply the delta. */
+ if (weight > 0.0f) {
+ if (slide_data->other_bezt->h1 <= HD_VECT) {
+ slide_data->other_bezt->h1 = HD_FREE;
+ }
+ }
+ }
+
+ slide_spline_solve_P1(
+ u, B, slide_data->P0, slide_data->P2, slide_data->P3, slide_data->adjust_bezt->vec[2]);
+
+ if (need_restore_P2) {
+ copy_v2_v2(slide_data->P2, oldP2);
+ }
+ }
+ else {
+ float oldP1[2];
+ bool need_restore_P1 = false;
+
+ if (u < 1.0f - margin) {
+ float solution[2];
+ float x = ((1.0f - u) - margin) * 0.5f / (0.5f - margin);
+ float weight = 3 * x * x - 2 * x * x * x;
+
+ slide_spline_solve_P1(u, B, slide_data->P0, slide_data->P2, slide_data->P3, solution);
+
+ copy_v2_v2(oldP1, slide_data->P1);
+ interp_v2_v2v2(slide_data->P1, slide_data->P1, solution, weight);
+ copy_v2_v2(slide_data->other_bezt->vec[2], slide_data->P1);
+ need_restore_P1 = true;
+
+ /* Tweak handle type in order to be able to apply the delta. */
+ if (weight > 0.0f) {
+ if (slide_data->other_bezt->h2 <= HD_VECT) {
+ slide_data->other_bezt->h2 = HD_FREE;
+ }
+ }
+ }
+
+ slide_spline_solve_P2(
+ u, B, slide_data->P0, slide_data->P1, slide_data->P3, slide_data->adjust_bezt->vec[0]);
+
+ if (need_restore_P1) {
+ copy_v2_v2(slide_data->P1, oldP1);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
+ DEG_id_tag_update(&slide_data->mask->id, 0);
+
+ break;
+ }
+
+ case LEFTMOUSE:
+ case RIGHTMOUSE:
+ if (event->type == slide_data->event_invoke_type && event->val == KM_RELEASE) {
+ /* dont key sliding feather uw's */
+ if (IS_AUTOKEY_ON(scene)) {
+ ED_mask_layer_shape_auto_key(slide_data->mask_layer, CFRA);
+ }
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
+ DEG_id_tag_update(&slide_data->mask->id, 0);
+
+ free_slide_spline_curvature_data(slide_data); /* keep this last! */
+ return OPERATOR_FINISHED;
+ }
+
+ break;
+
+ case ESCKEY:
+ cancel_slide_spline_curvature(slide_data);
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
+ DEG_id_tag_update(&slide_data->mask->id, 0);
+
+ free_slide_spline_curvature_data(op->customdata); /* keep this last! */
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
void MASK_OT_slide_spline_curvature(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Slide Spline Curvature";
- ot->description = "Slide a point on the spline to define it's curvature";
- ot->idname = "MASK_OT_slide_spline_curvature";
-
- /* api callbacks */
- ot->invoke = slide_spline_curvature_invoke;
- ot->modal = slide_spline_curvature_modal;
- ot->poll = ED_operator_mask;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Slide Spline Curvature";
+ ot->description = "Slide a point on the spline to define it's curvature";
+ ot->idname = "MASK_OT_slide_spline_curvature";
+
+ /* api callbacks */
+ ot->invoke = slide_spline_curvature_invoke;
+ ot->modal = slide_spline_curvature_modal;
+ ot->poll = ED_operator_mask;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************** toggle cyclic *********************/
static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- if (ED_mask_spline_select_check(spline)) {
- spline->flag ^= MASK_SPLINE_CYCLIC;
- }
- }
- }
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ if (ED_mask_spline_select_check(spline)) {
+ spline->flag ^= MASK_SPLINE_CYCLIC;
+ }
+ }
+ }
- DEG_id_tag_update(&mask->id, 0);
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ DEG_id_tag_update(&mask->id, 0);
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MASK_OT_cyclic_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Cyclic";
- ot->description = "Toggle cyclic for selected splines";
- ot->idname = "MASK_OT_cyclic_toggle";
+ /* identifiers */
+ ot->name = "Toggle Cyclic";
+ ot->description = "Toggle cyclic for selected splines";
+ ot->idname = "MASK_OT_cyclic_toggle";
- /* api callbacks */
- ot->exec = cyclic_toggle_exec;
- ot->poll = ED_maskedit_mask_poll;
+ /* api callbacks */
+ ot->exec = cyclic_toggle_exec;
+ ot->poll = ED_maskedit_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************** delete *********************/
static void delete_feather_points(MaskSplinePoint *point)
{
- int i, count = 0;
-
- if (!point->tot_uw)
- return;
-
- for (i = 0; i < point->tot_uw; i++) {
- if ((point->uw[i].flag & SELECT) == 0)
- count++;
- }
-
- if (count == 0) {
- MEM_freeN(point->uw);
- point->uw = NULL;
- point->tot_uw = 0;
- }
- else {
- MaskSplinePointUW *new_uw;
- int j = 0;
-
- new_uw = MEM_callocN(count * sizeof(MaskSplinePointUW), "new mask uw points");
-
- for (i = 0; i < point->tot_uw; i++) {
- if ((point->uw[i].flag & SELECT) == 0) {
- new_uw[j++] = point->uw[i];
- }
- }
-
- MEM_freeN(point->uw);
-
- point->uw = new_uw;
- point->tot_uw = count;
- }
+ int i, count = 0;
+
+ if (!point->tot_uw)
+ return;
+
+ for (i = 0; i < point->tot_uw; i++) {
+ if ((point->uw[i].flag & SELECT) == 0)
+ count++;
+ }
+
+ if (count == 0) {
+ MEM_freeN(point->uw);
+ point->uw = NULL;
+ point->tot_uw = 0;
+ }
+ else {
+ MaskSplinePointUW *new_uw;
+ int j = 0;
+
+ new_uw = MEM_callocN(count * sizeof(MaskSplinePointUW), "new mask uw points");
+
+ for (i = 0; i < point->tot_uw; i++) {
+ if ((point->uw[i].flag & SELECT) == 0) {
+ new_uw[j++] = point->uw[i];
+ }
+ }
+
+ MEM_freeN(point->uw);
+
+ point->uw = new_uw;
+ point->tot_uw = count;
+ }
}
static int delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
- bool changed = false;
+ Scene *scene = CTX_data_scene(C);
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+ bool changed = false;
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
- int mask_layer_shape_ofs = 0;
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+ int mask_layer_shape_ofs = 0;
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
- spline = masklay->splines.first;
+ spline = masklay->splines.first;
- while (spline) {
- const int tot_point_orig = spline->tot_point;
- int i, count = 0;
- MaskSpline *next_spline = spline->next;
+ while (spline) {
+ const int tot_point_orig = spline->tot_point;
+ int i, count = 0;
+ MaskSpline *next_spline = spline->next;
- /* count unselected points */
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
+ /* count unselected points */
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
- if (!MASKPOINT_ISSEL_ANY(point))
- count++;
- }
+ if (!MASKPOINT_ISSEL_ANY(point))
+ count++;
+ }
- if (count == 0) {
- /* delete the whole spline */
- BLI_remlink(&masklay->splines, spline);
- BKE_mask_spline_free(spline);
+ if (count == 0) {
+ /* delete the whole spline */
+ BLI_remlink(&masklay->splines, spline);
+ BKE_mask_spline_free(spline);
- if (spline == masklay->act_spline) {
- masklay->act_spline = NULL;
- masklay->act_point = NULL;
- }
+ if (spline == masklay->act_spline) {
+ masklay->act_spline = NULL;
+ masklay->act_point = NULL;
+ }
- BKE_mask_layer_shape_changed_remove(masklay, mask_layer_shape_ofs, tot_point_orig);
- }
- else {
- MaskSplinePoint *new_points;
- int j;
+ BKE_mask_layer_shape_changed_remove(masklay, mask_layer_shape_ofs, tot_point_orig);
+ }
+ else {
+ MaskSplinePoint *new_points;
+ int j;
- new_points = MEM_callocN(count * sizeof(MaskSplinePoint), "deleteMaskPoints");
+ new_points = MEM_callocN(count * sizeof(MaskSplinePoint), "deleteMaskPoints");
- for (i = 0, j = 0; i < tot_point_orig; i++) {
- MaskSplinePoint *point = &spline->points[i];
+ for (i = 0, j = 0; i < tot_point_orig; i++) {
+ MaskSplinePoint *point = &spline->points[i];
- if (!MASKPOINT_ISSEL_ANY(point)) {
- if (point == masklay->act_point)
- masklay->act_point = &new_points[j];
+ if (!MASKPOINT_ISSEL_ANY(point)) {
+ if (point == masklay->act_point)
+ masklay->act_point = &new_points[j];
- delete_feather_points(point);
+ delete_feather_points(point);
- new_points[j] = *point;
- j++;
- }
- else {
- if (point == masklay->act_point)
- masklay->act_point = NULL;
+ new_points[j] = *point;
+ j++;
+ }
+ else {
+ if (point == masklay->act_point)
+ masklay->act_point = NULL;
- BKE_mask_point_free(point);
- spline->tot_point--;
+ BKE_mask_point_free(point);
+ spline->tot_point--;
- BKE_mask_layer_shape_changed_remove(masklay, mask_layer_shape_ofs + j, 1);
- }
- }
+ BKE_mask_layer_shape_changed_remove(masklay, mask_layer_shape_ofs + j, 1);
+ }
+ }
- mask_layer_shape_ofs += spline->tot_point;
+ mask_layer_shape_ofs += spline->tot_point;
- MEM_freeN(spline->points);
- spline->points = new_points;
+ MEM_freeN(spline->points);
+ spline->points = new_points;
- ED_mask_select_flush_all(mask);
- }
+ ED_mask_select_flush_all(mask);
+ }
- changed = true;
- spline = next_spline;
- }
+ changed = true;
+ spline = next_spline;
+ }
- /* not essential but confuses users when there are keys with no data!
- * assume if they delete all data from the layer they also dont care about keys */
- if (BLI_listbase_is_empty(&masklay->splines)) {
- BKE_mask_layer_free_shapes(masklay);
- }
- }
+ /* not essential but confuses users when there are keys with no data!
+ * assume if they delete all data from the layer they also dont care about keys */
+ if (BLI_listbase_is_empty(&masklay->splines)) {
+ BKE_mask_layer_free_shapes(masklay);
+ }
+ }
- if (!changed) {
- return OPERATOR_CANCELLED;
- }
+ if (!changed) {
+ return OPERATOR_CANCELLED;
+ }
- /* TODO: only update edited splines */
- BKE_mask_update_display(mask, CFRA);
+ /* TODO: only update edited splines */
+ BKE_mask_update_display(mask, CFRA);
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MASK_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete";
- ot->description = "Delete selected control points or splines";
- ot->idname = "MASK_OT_delete";
-
- /* api callbacks */
- ot->invoke = WM_operator_confirm;
- ot->exec = delete_exec;
- ot->poll = ED_maskedit_mask_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Delete";
+ ot->description = "Delete selected control points or splines";
+ ot->idname = "MASK_OT_delete";
+
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = delete_exec;
+ ot->poll = ED_maskedit_mask_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* *** switch direction *** */
static int mask_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
-
- bool changed = false;
-
- /* do actual selection */
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
- bool changed_layer = false;
-
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
-
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- if (ED_mask_spline_select_check(spline)) {
- BKE_mask_spline_direction_switch(masklay, spline);
- changed = true;
- changed_layer = true;
- }
- }
-
- if (changed_layer) {
- if (IS_AUTOKEY_ON(scene)) {
- ED_mask_layer_shape_auto_key(masklay, CFRA);
- }
- }
- }
-
- if (changed) {
- /* TODO: only update this spline */
- BKE_mask_update_display(mask, CFRA);
-
- WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
-
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+
+ bool changed = false;
+
+ /* do actual selection */
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+ bool changed_layer = false;
+
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ if (ED_mask_spline_select_check(spline)) {
+ BKE_mask_spline_direction_switch(masklay, spline);
+ changed = true;
+ changed_layer = true;
+ }
+ }
+
+ if (changed_layer) {
+ if (IS_AUTOKEY_ON(scene)) {
+ ED_mask_layer_shape_auto_key(masklay, CFRA);
+ }
+ }
+ }
+
+ if (changed) {
+ /* TODO: only update this spline */
+ BKE_mask_update_display(mask, CFRA);
+
+ WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
}
void MASK_OT_switch_direction(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Switch Direction";
- ot->description = "Switch direction of selected splines";
- ot->idname = "MASK_OT_switch_direction";
+ /* identifiers */
+ ot->name = "Switch Direction";
+ ot->description = "Switch direction of selected splines";
+ ot->idname = "MASK_OT_switch_direction";
- /* api callbacks */
- ot->exec = mask_switch_direction_exec;
- ot->poll = ED_maskedit_mask_poll;
+ /* api callbacks */
+ ot->exec = mask_switch_direction_exec;
+ ot->poll = ED_maskedit_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/* *** recalc normals *** */
static int mask_normals_make_consistent_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
- int i;
-
- bool changed = false;
-
- /* do actual selection */
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
- bool changed_layer = false;
-
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
-
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
-
- if (MASKPOINT_ISSEL_ANY(point)) {
- BKE_mask_calc_handle_point_auto(spline, point, false);
- changed = true;
- changed_layer = true;
- }
- }
- }
-
- if (changed_layer) {
- if (IS_AUTOKEY_ON(scene)) {
- ED_mask_layer_shape_auto_key(masklay, CFRA);
- }
- }
- }
-
- if (changed) {
- /* TODO: only update this spline */
- BKE_mask_update_display(mask, CFRA);
-
- WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
-
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+ int i;
+
+ bool changed = false;
+
+ /* do actual selection */
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+ bool changed_layer = false;
+
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
+
+ if (MASKPOINT_ISSEL_ANY(point)) {
+ BKE_mask_calc_handle_point_auto(spline, point, false);
+ changed = true;
+ changed_layer = true;
+ }
+ }
+ }
+
+ if (changed_layer) {
+ if (IS_AUTOKEY_ON(scene)) {
+ ED_mask_layer_shape_auto_key(masklay, CFRA);
+ }
+ }
+ }
+
+ if (changed) {
+ /* TODO: only update this spline */
+ BKE_mask_update_display(mask, CFRA);
+
+ WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
}
/* named to match mesh recalc normals */
void MASK_OT_normals_make_consistent(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Recalc Normals";
- ot->description = "Re-calculate the direction of selected handles";
- ot->idname = "MASK_OT_normals_make_consistent";
+ /* identifiers */
+ ot->name = "Recalc Normals";
+ ot->description = "Re-calculate the direction of selected handles";
+ ot->idname = "MASK_OT_normals_make_consistent";
- /* api callbacks */
- ot->exec = mask_normals_make_consistent_exec;
- ot->poll = ED_maskedit_mask_poll;
+ /* api callbacks */
+ ot->exec = mask_normals_make_consistent_exec;
+ ot->poll = ED_maskedit_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/******************** set handle type *********************/
static int set_handle_type_exec(bContext *C, wmOperator *op)
{
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
- int handle_type = RNA_enum_get(op->ptr, "type");
-
- bool changed = false;
-
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
- int i;
-
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
-
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
-
- if (MASKPOINT_ISSEL_ANY(point)) {
- BezTriple *bezt = &point->bezt;
-
- if (bezt->f2 & SELECT) {
- bezt->h1 = handle_type;
- bezt->h2 = handle_type;
- }
- else {
- if (bezt->f1 & SELECT) {
- bezt->h1 = handle_type;
- }
- if (bezt->f3 & SELECT) {
- bezt->h2 = handle_type;
- }
- }
-
- if (handle_type == HD_ALIGN) {
- float vec[3];
- sub_v3_v3v3(vec, bezt->vec[0], bezt->vec[1]);
- add_v3_v3v3(bezt->vec[2], bezt->vec[1], vec);
- }
-
- changed = true;
- }
- }
- }
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
- DEG_id_tag_update(&mask->id, 0);
-
- return OPERATOR_FINISHED;
- }
- return OPERATOR_CANCELLED;
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+ int handle_type = RNA_enum_get(op->ptr, "type");
+
+ bool changed = false;
+
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+ int i;
+
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
+
+ if (MASKPOINT_ISSEL_ANY(point)) {
+ BezTriple *bezt = &point->bezt;
+
+ if (bezt->f2 & SELECT) {
+ bezt->h1 = handle_type;
+ bezt->h2 = handle_type;
+ }
+ else {
+ if (bezt->f1 & SELECT) {
+ bezt->h1 = handle_type;
+ }
+ if (bezt->f3 & SELECT) {
+ bezt->h2 = handle_type;
+ }
+ }
+
+ if (handle_type == HD_ALIGN) {
+ float vec[3];
+ sub_v3_v3v3(vec, bezt->vec[0], bezt->vec[1]);
+ add_v3_v3v3(bezt->vec[2], bezt->vec[1], vec);
+ }
+
+ changed = true;
+ }
+ }
+ }
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
+ DEG_id_tag_update(&mask->id, 0);
+
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_CANCELLED;
}
void MASK_OT_handle_type_set(wmOperatorType *ot)
{
- static const EnumPropertyItem editcurve_handle_type_items[] = {
- {HD_AUTO, "AUTO", 0, "Auto", ""},
- {HD_VECT, "VECTOR", 0, "Vector", ""},
- {HD_ALIGN, "ALIGNED", 0, "Aligned Single", ""},
- {HD_ALIGN_DOUBLESIDE, "ALIGNED_DOUBLESIDE", 0, "Aligned", ""},
- {HD_FREE, "FREE", 0, "Free", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Set Handle Type";
- ot->description = "Set type of handles for selected control points";
- ot->idname = "MASK_OT_handle_type_set";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = set_handle_type_exec;
- ot->poll = ED_maskedit_mask_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type");
+ static const EnumPropertyItem editcurve_handle_type_items[] = {
+ {HD_AUTO, "AUTO", 0, "Auto", ""},
+ {HD_VECT, "VECTOR", 0, "Vector", ""},
+ {HD_ALIGN, "ALIGNED", 0, "Aligned Single", ""},
+ {HD_ALIGN_DOUBLESIDE, "ALIGNED_DOUBLESIDE", 0, "Aligned", ""},
+ {HD_FREE, "FREE", 0, "Free", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Set Handle Type";
+ ot->description = "Set type of handles for selected control points";
+ ot->idname = "MASK_OT_handle_type_set";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = set_handle_type_exec;
+ ot->poll = ED_maskedit_mask_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type");
}
-
/* ********* clear/set restrict view *********/
static int mask_hide_view_clear_exec(bContext *C, wmOperator *op)
{
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
- bool changed = false;
- const bool select = RNA_boolean_get(op->ptr, "select");
-
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
-
- if (masklay->restrictflag & OB_RESTRICT_VIEW) {
- ED_mask_layer_select_set(masklay, select);
- masklay->restrictflag &= ~OB_RESTRICT_VIEW;
- changed = true;
- }
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask);
- DEG_id_tag_update(&mask->id, 0);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+ bool changed = false;
+ const bool select = RNA_boolean_get(op->ptr, "select");
+
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+
+ if (masklay->restrictflag & OB_RESTRICT_VIEW) {
+ ED_mask_layer_select_set(masklay, select);
+ masklay->restrictflag &= ~OB_RESTRICT_VIEW;
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask);
+ DEG_id_tag_update(&mask->id, 0);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void MASK_OT_hide_view_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Restrict View";
- ot->description = "Reveal the layer by setting the hide flag";
- ot->idname = "MASK_OT_hide_view_clear";
+ /* identifiers */
+ ot->name = "Clear Restrict View";
+ ot->description = "Reveal the layer by setting the hide flag";
+ ot->idname = "MASK_OT_hide_view_clear";
- /* api callbacks */
- ot->exec = mask_hide_view_clear_exec;
- ot->poll = ED_maskedit_mask_poll;
+ /* api callbacks */
+ ot->exec = mask_hide_view_clear_exec;
+ ot->poll = ED_maskedit_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "select", true, "Select", "");
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
static int mask_hide_view_set_exec(bContext *C, wmOperator *op)
{
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
- const bool unselected = RNA_boolean_get(op->ptr, "unselected");
- bool changed = false;
-
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
-
- if (masklay->restrictflag & MASK_RESTRICT_SELECT) {
- continue;
- }
-
- if (!unselected) {
- if (ED_mask_layer_select_check(masklay)) {
- ED_mask_layer_select_set(masklay, false);
-
- masklay->restrictflag |= OB_RESTRICT_VIEW;
- changed = true;
- if (masklay == BKE_mask_layer_active(mask)) {
- BKE_mask_layer_active_set(mask, NULL);
- }
- }
- }
- else {
- if (!ED_mask_layer_select_check(masklay)) {
- masklay->restrictflag |= OB_RESTRICT_VIEW;
- changed = true;
- if (masklay == BKE_mask_layer_active(mask)) {
- BKE_mask_layer_active_set(mask, NULL);
- }
- }
- }
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask);
- DEG_id_tag_update(&mask->id, 0);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+ const bool unselected = RNA_boolean_get(op->ptr, "unselected");
+ bool changed = false;
+
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+
+ if (masklay->restrictflag & MASK_RESTRICT_SELECT) {
+ continue;
+ }
+
+ if (!unselected) {
+ if (ED_mask_layer_select_check(masklay)) {
+ ED_mask_layer_select_set(masklay, false);
+
+ masklay->restrictflag |= OB_RESTRICT_VIEW;
+ changed = true;
+ if (masklay == BKE_mask_layer_active(mask)) {
+ BKE_mask_layer_active_set(mask, NULL);
+ }
+ }
+ }
+ else {
+ if (!ED_mask_layer_select_check(masklay)) {
+ masklay->restrictflag |= OB_RESTRICT_VIEW;
+ changed = true;
+ if (masklay == BKE_mask_layer_active(mask)) {
+ BKE_mask_layer_active_set(mask, NULL);
+ }
+ }
+ }
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask);
+ DEG_id_tag_update(&mask->id, 0);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void MASK_OT_hide_view_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Restrict View";
- ot->description = "Hide the layer by setting the hide flag";
- ot->idname = "MASK_OT_hide_view_set";
+ /* identifiers */
+ ot->name = "Set Restrict View";
+ ot->description = "Hide the layer by setting the hide flag";
+ ot->idname = "MASK_OT_hide_view_set";
- /* api callbacks */
- ot->exec = mask_hide_view_set_exec;
- ot->poll = ED_maskedit_mask_poll;
+ /* api callbacks */
+ ot->exec = mask_hide_view_set_exec;
+ ot->poll = ED_maskedit_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected layers");
+ RNA_def_boolean(
+ ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected layers");
}
-
static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
- bool changed = false;
- int i;
-
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
-
- if (masklay->restrictflag & (MASK_RESTRICT_SELECT | MASK_RESTRICT_VIEW)) {
- continue;
- }
-
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
-
- if (MASKPOINT_ISSEL_ANY(point)) {
- BezTriple *bezt = &point->bezt;
- bezt->weight = 0.0f;
- changed = true;
- }
- }
- }
- }
-
- if (changed) {
- /* TODO: only update edited splines */
- BKE_mask_update_display(mask, CFRA);
-
- WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask);
- DEG_id_tag_update(&mask->id, 0);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Scene *scene = CTX_data_scene(C);
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+ bool changed = false;
+ int i;
+
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+
+ if (masklay->restrictflag & (MASK_RESTRICT_SELECT | MASK_RESTRICT_VIEW)) {
+ continue;
+ }
+
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
+
+ if (MASKPOINT_ISSEL_ANY(point)) {
+ BezTriple *bezt = &point->bezt;
+ bezt->weight = 0.0f;
+ changed = true;
+ }
+ }
+ }
+ }
+
+ if (changed) {
+ /* TODO: only update edited splines */
+ BKE_mask_update_display(mask, CFRA);
+
+ WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask);
+ DEG_id_tag_update(&mask->id, 0);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void MASK_OT_feather_weight_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Feather Weight";
- ot->description = "Reset the feather weight to zero";
- ot->idname = "MASK_OT_feather_weight_clear";
+ /* identifiers */
+ ot->name = "Clear Feather Weight";
+ ot->description = "Reset the feather weight to zero";
+ ot->idname = "MASK_OT_feather_weight_clear";
- /* api callbacks */
- ot->exec = mask_feather_weight_clear_exec;
- ot->poll = ED_maskedit_mask_poll;
+ /* api callbacks */
+ ot->exec = mask_feather_weight_clear_exec;
+ ot->poll = ED_maskedit_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************** move mask layer operator *********************/
static bool mask_layer_move_poll(bContext *C)
{
- if (ED_maskedit_mask_poll(C)) {
- Mask *mask = CTX_data_edit_mask(C);
+ if (ED_maskedit_mask_poll(C)) {
+ Mask *mask = CTX_data_edit_mask(C);
- return mask->masklay_tot > 0;
- }
+ return mask->masklay_tot > 0;
+ }
- return false;
+ return false;
}
static int mask_layer_move_exec(bContext *C, wmOperator *op)
{
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *mask_layer = BLI_findlink(&mask->masklayers, mask->masklay_act);
- MaskLayer *mask_layer_other;
- int direction = RNA_enum_get(op->ptr, "direction");
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *mask_layer = BLI_findlink(&mask->masklayers, mask->masklay_act);
+ MaskLayer *mask_layer_other;
+ int direction = RNA_enum_get(op->ptr, "direction");
- if (!mask_layer)
- return OPERATOR_CANCELLED;
+ if (!mask_layer)
+ return OPERATOR_CANCELLED;
- if (direction == -1) {
- mask_layer_other = mask_layer->prev;
+ if (direction == -1) {
+ mask_layer_other = mask_layer->prev;
- if (!mask_layer_other)
- return OPERATOR_CANCELLED;
+ if (!mask_layer_other)
+ return OPERATOR_CANCELLED;
- BLI_remlink(&mask->masklayers, mask_layer);
- BLI_insertlinkbefore(&mask->masklayers, mask_layer_other, mask_layer);
- mask->masklay_act--;
- }
- else if (direction == 1) {
- mask_layer_other = mask_layer->next;
+ BLI_remlink(&mask->masklayers, mask_layer);
+ BLI_insertlinkbefore(&mask->masklayers, mask_layer_other, mask_layer);
+ mask->masklay_act--;
+ }
+ else if (direction == 1) {
+ mask_layer_other = mask_layer->next;
- if (!mask_layer_other)
- return OPERATOR_CANCELLED;
+ if (!mask_layer_other)
+ return OPERATOR_CANCELLED;
- BLI_remlink(&mask->masklayers, mask_layer);
- BLI_insertlinkafter(&mask->masklayers, mask_layer_other, mask_layer);
- mask->masklay_act++;
- }
+ BLI_remlink(&mask->masklayers, mask_layer);
+ BLI_insertlinkafter(&mask->masklayers, mask_layer_other, mask_layer);
+ mask->masklay_act++;
+ }
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MASK_OT_layer_move(wmOperatorType *ot)
{
- static const EnumPropertyItem direction_items[] = {
- {-1, "UP", 0, "Up", ""},
- {1, "DOWN", 0, "Down", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Move Layer";
- ot->description = "Move the active layer up/down in the list";
- ot->idname = "MASK_OT_layer_move";
-
- /* api callbacks */
- ot->exec = mask_layer_move_exec;
- ot->poll = mask_layer_move_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to move the active layer");
+ static const EnumPropertyItem direction_items[] = {
+ {-1, "UP", 0, "Up", ""},
+ {1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Move Layer";
+ ot->description = "Move the active layer up/down in the list";
+ ot->idname = "MASK_OT_layer_move";
+
+ /* api callbacks */
+ ot->exec = mask_layer_move_exec;
+ ot->poll = mask_layer_move_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna,
+ "direction",
+ direction_items,
+ 0,
+ "Direction",
+ "Direction to move the active layer");
}
/******************** duplicate *********************/
static int mask_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *mask_layer;
-
- for (mask_layer = mask->masklayers.first;
- mask_layer;
- mask_layer = mask_layer->next)
- {
- MaskSpline *spline;
-
- for (spline = mask_layer->splines.last;
- spline;
- spline = spline->prev)
- {
- MaskSplinePoint *point = spline->points;
- int i = 0;
- while (i < spline->tot_point) {
- int start = i, end = -1;
- /* Find next selected segment. */
- while (MASKPOINT_ISSEL_ANY(point)) {
- BKE_mask_point_select_set(point, false);
- end = i;
- if (i >= spline->tot_point - 1) {
- break;
- }
- i++;
- point++;
- }
- if (end >= start) {
- int tot_point;
- int tot_point_shape_start = 0;
- MaskSpline *new_spline = BKE_mask_spline_add(mask_layer);
- MaskSplinePoint *new_point;
- int b;
-
- /* BKE_mask_spline_add might allocate the points,
- * need to free them in this case. */
- if (new_spline->points) {
- MEM_freeN(new_spline->points);
- }
-
- /* Copy options from old spline. */
- new_spline->flag = spline->flag;
- new_spline->offset_mode = spline->offset_mode;
- new_spline->weight_interp = spline->weight_interp;
- new_spline->parent = spline->parent;
-
- /* Allocate new points and copy them from old spline. */
- new_spline->tot_point = end - start + 1;
- new_spline->points = MEM_mallocN(sizeof(MaskSplinePoint) * new_spline->tot_point,
- "duplicated mask points");
-
- memcpy(new_spline->points, spline->points + start,
- new_spline->tot_point * sizeof(MaskSplinePoint));
-
- tot_point = new_spline->tot_point;
-
- /* animation requires points added one by one */
- if (mask_layer->splines_shapes.first) {
- new_spline->tot_point = 0;
- tot_point_shape_start = BKE_mask_layer_shape_spline_to_index(mask_layer, new_spline);
- }
-
- /* Select points and duplicate their UWs (if needed). */
- for (b = 0, new_point = new_spline->points;
- b < tot_point;
- b++, new_point++)
- {
- if (new_point->uw) {
- new_point->uw = MEM_dupallocN(new_point->uw);
- }
- BKE_mask_point_select_set(new_point, true);
-
-
- if (mask_layer->splines_shapes.first) {
- new_spline->tot_point++;
- BKE_mask_layer_shape_changed_add(mask_layer, tot_point_shape_start + b, true, false);
- }
- }
-
- /* Clear cyclic flag if we didn't copy the whole spline. */
- if (new_spline->flag & MASK_SPLINE_CYCLIC) {
- if (start != 0 || end != spline->tot_point - 1) {
- new_spline->flag &= ~MASK_SPLINE_CYCLIC;
- }
- }
-
- /* Flush selection to splines. */
- new_spline->flag |= SELECT;
- spline->flag &= ~SELECT;
-
- mask_layer->act_spline = new_spline;
- }
- i++;
- point++;
- }
- }
- }
-
- /* TODO: only update edited splines */
- BKE_mask_update_display(mask, CFRA);
-
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *mask_layer;
+
+ for (mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ MaskSpline *spline;
+
+ for (spline = mask_layer->splines.last; spline; spline = spline->prev) {
+ MaskSplinePoint *point = spline->points;
+ int i = 0;
+ while (i < spline->tot_point) {
+ int start = i, end = -1;
+ /* Find next selected segment. */
+ while (MASKPOINT_ISSEL_ANY(point)) {
+ BKE_mask_point_select_set(point, false);
+ end = i;
+ if (i >= spline->tot_point - 1) {
+ break;
+ }
+ i++;
+ point++;
+ }
+ if (end >= start) {
+ int tot_point;
+ int tot_point_shape_start = 0;
+ MaskSpline *new_spline = BKE_mask_spline_add(mask_layer);
+ MaskSplinePoint *new_point;
+ int b;
+
+ /* BKE_mask_spline_add might allocate the points,
+ * need to free them in this case. */
+ if (new_spline->points) {
+ MEM_freeN(new_spline->points);
+ }
+
+ /* Copy options from old spline. */
+ new_spline->flag = spline->flag;
+ new_spline->offset_mode = spline->offset_mode;
+ new_spline->weight_interp = spline->weight_interp;
+ new_spline->parent = spline->parent;
+
+ /* Allocate new points and copy them from old spline. */
+ new_spline->tot_point = end - start + 1;
+ new_spline->points = MEM_mallocN(sizeof(MaskSplinePoint) * new_spline->tot_point,
+ "duplicated mask points");
+
+ memcpy(new_spline->points,
+ spline->points + start,
+ new_spline->tot_point * sizeof(MaskSplinePoint));
+
+ tot_point = new_spline->tot_point;
+
+ /* animation requires points added one by one */
+ if (mask_layer->splines_shapes.first) {
+ new_spline->tot_point = 0;
+ tot_point_shape_start = BKE_mask_layer_shape_spline_to_index(mask_layer, new_spline);
+ }
+
+ /* Select points and duplicate their UWs (if needed). */
+ for (b = 0, new_point = new_spline->points; b < tot_point; b++, new_point++) {
+ if (new_point->uw) {
+ new_point->uw = MEM_dupallocN(new_point->uw);
+ }
+ BKE_mask_point_select_set(new_point, true);
+
+ if (mask_layer->splines_shapes.first) {
+ new_spline->tot_point++;
+ BKE_mask_layer_shape_changed_add(mask_layer, tot_point_shape_start + b, true, false);
+ }
+ }
+
+ /* Clear cyclic flag if we didn't copy the whole spline. */
+ if (new_spline->flag & MASK_SPLINE_CYCLIC) {
+ if (start != 0 || end != spline->tot_point - 1) {
+ new_spline->flag &= ~MASK_SPLINE_CYCLIC;
+ }
+ }
+
+ /* Flush selection to splines. */
+ new_spline->flag |= SELECT;
+ spline->flag &= ~SELECT;
+
+ mask_layer->act_spline = new_spline;
+ }
+ i++;
+ point++;
+ }
+ }
+ }
+
+ /* TODO: only update edited splines */
+ BKE_mask_update_display(mask, CFRA);
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+
+ return OPERATOR_FINISHED;
}
void MASK_OT_duplicate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Duplicate Mask";
- ot->description = "Duplicate selected control points and segments between them";
- ot->idname = "MASK_OT_duplicate";
+ /* identifiers */
+ ot->name = "Duplicate Mask";
+ ot->description = "Duplicate selected control points and segments between them";
+ ot->idname = "MASK_OT_duplicate";
- /* api callbacks */
- ot->exec = mask_duplicate_exec;
- ot->poll = ED_maskedit_mask_poll;
+ /* api callbacks */
+ ot->exec = mask_duplicate_exec;
+ ot->poll = ED_maskedit_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** copy splines to clipboard operator *********************/
static int copy_splines_exec(bContext *C, wmOperator *UNUSED(op))
{
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *mask_layer = BKE_mask_layer_active(mask);
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *mask_layer = BKE_mask_layer_active(mask);
- if (mask_layer == NULL) {
- return OPERATOR_CANCELLED;
- }
+ if (mask_layer == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- BKE_mask_clipboard_copy_from_layer(mask_layer);
+ BKE_mask_clipboard_copy_from_layer(mask_layer);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MASK_OT_copy_splines(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Splines";
- ot->description = "Copy selected splines to clipboard";
- ot->idname = "MASK_OT_copy_splines";
+ /* identifiers */
+ ot->name = "Copy Splines";
+ ot->description = "Copy selected splines to clipboard";
+ ot->idname = "MASK_OT_copy_splines";
- /* api callbacks */
- ot->exec = copy_splines_exec;
- ot->poll = ED_maskedit_mask_poll;
+ /* api callbacks */
+ ot->exec = copy_splines_exec;
+ ot->poll = ED_maskedit_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
}
/********************** paste tracks from clipboard operator *********************/
static bool paste_splines_poll(bContext *C)
{
- if (ED_maskedit_mask_poll(C)) {
- return BKE_mask_clipboard_is_empty() == false;
- }
+ if (ED_maskedit_mask_poll(C)) {
+ return BKE_mask_clipboard_is_empty() == false;
+ }
- return 0;
+ return 0;
}
static int paste_splines_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *mask_layer = BKE_mask_layer_active(mask);
+ Scene *scene = CTX_data_scene(C);
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *mask_layer = BKE_mask_layer_active(mask);
- if (mask_layer == NULL) {
- mask_layer = BKE_mask_layer_new(mask, "");
- }
+ if (mask_layer == NULL) {
+ mask_layer = BKE_mask_layer_new(mask, "");
+ }
- BKE_mask_clipboard_paste_to_layer(CTX_data_main(C), mask_layer);
+ BKE_mask_clipboard_paste_to_layer(CTX_data_main(C), mask_layer);
- /* TODO: only update edited splines */
- BKE_mask_update_display(mask, CFRA);
+ /* TODO: only update edited splines */
+ BKE_mask_update_display(mask, CFRA);
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MASK_OT_paste_splines(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Paste Splines";
- ot->description = "Paste splines from clipboard";
- ot->idname = "MASK_OT_paste_splines";
+ /* identifiers */
+ ot->name = "Paste Splines";
+ ot->description = "Paste splines from clipboard";
+ ot->idname = "MASK_OT_paste_splines";
- /* api callbacks */
- ot->exec = paste_splines_exec;
- ot->poll = paste_splines_poll;
+ /* api callbacks */
+ ot->exec = paste_splines_exec;
+ ot->poll = paste_splines_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c
index d7dfcc64ab0..bb9359bad71 100644
--- a/source/blender/editors/mask/mask_relationships.c
+++ b/source/blender/editors/mask/mask_relationships.c
@@ -21,7 +21,6 @@
* \ingroup edmask
*/
-
#include "BLI_math.h"
#include "BLI_string.h"
@@ -37,157 +36,159 @@
#include "WM_types.h"
#include "ED_screen.h"
-#include "ED_clip.h" /* frame remapping functions */
+#include "ED_clip.h" /* frame remapping functions */
-#include "mask_intern.h" /* own include */
+#include "mask_intern.h" /* own include */
static int mask_parent_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
- int i;
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+ int i;
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
- if (MASKPOINT_ISSEL_ANY(point)) {
- point->parent.id = NULL;
- }
- }
- }
- }
+ if (MASKPOINT_ISSEL_ANY(point)) {
+ point->parent.id = NULL;
+ }
+ }
+ }
+ }
- WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
- DEG_id_tag_update(&mask->id, 0);
+ WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
+ DEG_id_tag_update(&mask->id, 0);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MASK_OT_parent_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Parent";
- ot->description = "Clear the mask's parenting";
- ot->idname = "MASK_OT_parent_clear";
+ /* identifiers */
+ ot->name = "Clear Parent";
+ ot->description = "Clear the mask's parenting";
+ ot->idname = "MASK_OT_parent_clear";
- /* api callbacks */
- ot->exec = mask_parent_clear_exec;
+ /* api callbacks */
+ ot->exec = mask_parent_clear_exec;
- ot->poll = ED_maskedit_mask_poll;
+ ot->poll = ED_maskedit_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
{
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
-
- /* parent info */
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking;
- MovieTrackingTrack *track;
- MovieTrackingPlaneTrack *plane_track;
- MovieTrackingObject *tracking_object;
- /* done */
-
- int framenr, parent_type;
- float parmask_pos[2], orig_corners[4][2];
- const char *sub_parent_name;
-
- if (ELEM(NULL, sc, clip)) {
- return OPERATOR_CANCELLED;
- }
-
- framenr = ED_space_clip_get_clip_frame_number(sc);
-
- tracking = &clip->tracking;
- tracking_object = BKE_tracking_object_get_active(&clip->tracking);
-
- if (tracking_object == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- if ((track = BKE_tracking_track_get_active(tracking)) != NULL) {
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
- float marker_pos_ofs[2];
-
- add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset);
-
- BKE_mask_coord_from_movieclip(clip, &sc->user, parmask_pos, marker_pos_ofs);
-
- sub_parent_name = track->name;
- parent_type = MASK_PARENT_POINT_TRACK;
- memset(orig_corners, 0, sizeof(orig_corners));
- }
- else if ((plane_track = BKE_tracking_plane_track_get_active(tracking)) != NULL) {
- MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
-
- zero_v2(parmask_pos);
- sub_parent_name = plane_track->name;
- parent_type = MASK_PARENT_PLANE_TRACK;
- memcpy(orig_corners, plane_marker->corners, sizeof(orig_corners));
- }
- else {
- return OPERATOR_CANCELLED;
- }
-
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
- int i;
-
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
-
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
-
- if (MASKPOINT_ISSEL_ANY(point)) {
- point->parent.id_type = ID_MC;
- point->parent.id = &clip->id;
- point->parent.type = parent_type;
- BLI_strncpy(point->parent.parent, tracking_object->name, sizeof(point->parent.parent));
- BLI_strncpy(point->parent.sub_parent, sub_parent_name, sizeof(point->parent.sub_parent));
-
- copy_v2_v2(point->parent.parent_orig, parmask_pos);
- memcpy(point->parent.parent_corners_orig, orig_corners, sizeof(point->parent.parent_corners_orig));
- }
- }
- }
- }
-
- WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
- DEG_id_tag_update(&mask->id, 0);
-
- return OPERATOR_FINISHED;
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+
+ /* parent info */
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking;
+ MovieTrackingTrack *track;
+ MovieTrackingPlaneTrack *plane_track;
+ MovieTrackingObject *tracking_object;
+ /* done */
+
+ int framenr, parent_type;
+ float parmask_pos[2], orig_corners[4][2];
+ const char *sub_parent_name;
+
+ if (ELEM(NULL, sc, clip)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ tracking = &clip->tracking;
+ tracking_object = BKE_tracking_object_get_active(&clip->tracking);
+
+ if (tracking_object == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if ((track = BKE_tracking_track_get_active(tracking)) != NULL) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+ float marker_pos_ofs[2];
+
+ add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset);
+
+ BKE_mask_coord_from_movieclip(clip, &sc->user, parmask_pos, marker_pos_ofs);
+
+ sub_parent_name = track->name;
+ parent_type = MASK_PARENT_POINT_TRACK;
+ memset(orig_corners, 0, sizeof(orig_corners));
+ }
+ else if ((plane_track = BKE_tracking_plane_track_get_active(tracking)) != NULL) {
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+
+ zero_v2(parmask_pos);
+ sub_parent_name = plane_track->name;
+ parent_type = MASK_PARENT_PLANE_TRACK;
+ memcpy(orig_corners, plane_marker->corners, sizeof(orig_corners));
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+ int i;
+
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
+
+ if (MASKPOINT_ISSEL_ANY(point)) {
+ point->parent.id_type = ID_MC;
+ point->parent.id = &clip->id;
+ point->parent.type = parent_type;
+ BLI_strncpy(point->parent.parent, tracking_object->name, sizeof(point->parent.parent));
+ BLI_strncpy(point->parent.sub_parent, sub_parent_name, sizeof(point->parent.sub_parent));
+
+ copy_v2_v2(point->parent.parent_orig, parmask_pos);
+ memcpy(point->parent.parent_corners_orig,
+ orig_corners,
+ sizeof(point->parent.parent_corners_orig));
+ }
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
+ DEG_id_tag_update(&mask->id, 0);
+
+ return OPERATOR_FINISHED;
}
/** based on #OBJECT_OT_parent_set */
void MASK_OT_parent_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Parent";
- ot->description = "Set the mask's parenting";
- ot->idname = "MASK_OT_parent_set";
+ /* identifiers */
+ ot->name = "Make Parent";
+ ot->description = "Set the mask's parenting";
+ ot->idname = "MASK_OT_parent_set";
- /* api callbacks */
- //ot->invoke = mask_parent_set_invoke;
- ot->exec = mask_parent_set_exec;
+ /* api callbacks */
+ //ot->invoke = mask_parent_set_invoke;
+ ot->exec = mask_parent_set_exec;
- ot->poll = ED_space_clip_maskedit_mask_poll;
+ ot->poll = ED_space_clip_maskedit_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c
index 89a15ec316d..076f8d067b9 100644
--- a/source/blender/editors/mask/mask_select.c
+++ b/source/blender/editors/mask/mask_select.c
@@ -38,12 +38,12 @@
#include "ED_screen.h"
#include "ED_select_utils.h"
-#include "ED_mask.h" /* own include */
+#include "ED_mask.h" /* own include */
#include "RNA_access.h"
#include "RNA_define.h"
-#include "mask_intern.h" /* own include */
+#include "mask_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Public Mask Selection API
@@ -52,157 +52,156 @@
/* 'check' select */
bool ED_mask_spline_select_check(MaskSpline *spline)
{
- int i;
+ int i;
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
- if (MASKPOINT_ISSEL_ANY(point))
- return true;
- }
+ if (MASKPOINT_ISSEL_ANY(point))
+ return true;
+ }
- return false;
+ return false;
}
bool ED_mask_layer_select_check(MaskLayer *masklay)
{
- MaskSpline *spline;
+ MaskSpline *spline;
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- return false;
- }
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ return false;
+ }
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- if (ED_mask_spline_select_check(spline)) {
- return true;
- }
- }
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ if (ED_mask_spline_select_check(spline)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
bool ED_mask_select_check(Mask *mask)
{
- MaskLayer *masklay;
+ MaskLayer *masklay;
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- if (ED_mask_layer_select_check(masklay)) {
- return true;
- }
- }
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ if (ED_mask_layer_select_check(masklay)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
/* 'sel' select */
void ED_mask_spline_select_set(MaskSpline *spline, const bool do_select)
{
- int i;
+ int i;
- if (do_select)
- spline->flag |= SELECT;
- else
- spline->flag &= ~SELECT;
+ if (do_select)
+ spline->flag |= SELECT;
+ else
+ spline->flag &= ~SELECT;
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
- BKE_mask_point_select_set(point, do_select);
- }
+ BKE_mask_point_select_set(point, do_select);
+ }
}
void ED_mask_layer_select_set(MaskLayer *masklay, const bool do_select)
{
- MaskSpline *spline;
+ MaskSpline *spline;
- if (masklay->restrictflag & MASK_RESTRICT_SELECT) {
- if (do_select == true) {
- return;
- }
- }
+ if (masklay->restrictflag & MASK_RESTRICT_SELECT) {
+ if (do_select == true) {
+ return;
+ }
+ }
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- ED_mask_spline_select_set(spline, do_select);
- }
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ ED_mask_spline_select_set(spline, do_select);
+ }
}
void ED_mask_select_toggle_all(Mask *mask, int action)
{
- MaskLayer *masklay;
-
- if (action == SEL_TOGGLE) {
- if (ED_mask_select_check(mask))
- action = SEL_DESELECT;
- else
- action = SEL_SELECT;
- }
-
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
-
- if (masklay->restrictflag & MASK_RESTRICT_VIEW) {
- continue;
- }
-
- if (action == SEL_INVERT) {
- /* we don't have generic functions for this, its restricted to this operator
- * if one day we need to re-use such functionality, they can be split out */
-
- MaskSpline *spline;
- if (masklay->restrictflag & MASK_RESTRICT_SELECT) {
- continue;
- }
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- int i;
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
- BKE_mask_point_select_set(point, !MASKPOINT_ISSEL_ANY(point));
- }
- }
-
- }
- else {
- ED_mask_layer_select_set(masklay, (action == SEL_SELECT) ? true : false);
- }
- }
+ MaskLayer *masklay;
+
+ if (action == SEL_TOGGLE) {
+ if (ED_mask_select_check(mask))
+ action = SEL_DESELECT;
+ else
+ action = SEL_SELECT;
+ }
+
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+
+ if (masklay->restrictflag & MASK_RESTRICT_VIEW) {
+ continue;
+ }
+
+ if (action == SEL_INVERT) {
+ /* we don't have generic functions for this, its restricted to this operator
+ * if one day we need to re-use such functionality, they can be split out */
+
+ MaskSpline *spline;
+ if (masklay->restrictflag & MASK_RESTRICT_SELECT) {
+ continue;
+ }
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ int i;
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
+ BKE_mask_point_select_set(point, !MASKPOINT_ISSEL_ANY(point));
+ }
+ }
+ }
+ else {
+ ED_mask_layer_select_set(masklay, (action == SEL_SELECT) ? true : false);
+ }
+ }
}
void ED_mask_select_flush_all(Mask *mask)
{
- MaskLayer *masklay;
-
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
-
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- int i;
-
- spline->flag &= ~SELECT;
-
- /* intentionally _dont_ do this in the masklay loop
- * so we clear flags on all splines */
- if (masklay->restrictflag & MASK_RESTRICT_VIEW) {
- continue;
- }
-
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *cur_point = &spline->points[i];
-
- if (MASKPOINT_ISSEL_ANY(cur_point)) {
- spline->flag |= SELECT;
- }
- else {
- int j;
-
- for (j = 0; j < cur_point->tot_uw; j++) {
- if (cur_point->uw[j].flag & SELECT) {
- spline->flag |= SELECT;
- break;
- }
- }
- }
- }
- }
- }
+ MaskLayer *masklay;
+
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ int i;
+
+ spline->flag &= ~SELECT;
+
+ /* intentionally _dont_ do this in the masklay loop
+ * so we clear flags on all splines */
+ if (masklay->restrictflag & MASK_RESTRICT_VIEW) {
+ continue;
+ }
+
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *cur_point = &spline->points[i];
+
+ if (MASKPOINT_ISSEL_ANY(cur_point)) {
+ spline->flag |= SELECT;
+ }
+ else {
+ int j;
+
+ for (j = 0; j < cur_point->tot_uw; j++) {
+ if (cur_point->uw[j].flag & SELECT) {
+ spline->flag |= SELECT;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
}
/** \} */
@@ -213,33 +212,33 @@ void ED_mask_select_flush_all(Mask *mask)
static int select_all_exec(bContext *C, wmOperator *op)
{
- Mask *mask = CTX_data_edit_mask(C);
- int action = RNA_enum_get(op->ptr, "action");
+ Mask *mask = CTX_data_edit_mask(C);
+ int action = RNA_enum_get(op->ptr, "action");
- ED_mask_select_toggle_all(mask, action);
- ED_mask_select_flush_all(mask);
+ ED_mask_select_toggle_all(mask, action);
+ ED_mask_select_flush_all(mask);
- WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
+ WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MASK_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All";
- ot->description = "Change selection of all curve points";
- ot->idname = "MASK_OT_select_all";
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->description = "Change selection of all curve points";
+ ot->idname = "MASK_OT_select_all";
- /* api callbacks */
- ot->exec = select_all_exec;
- ot->poll = ED_maskedit_mask_poll;
+ /* api callbacks */
+ ot->exec = select_all_exec;
+ ot->poll = ED_maskedit_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_select_all(ot);
+ /* properties */
+ WM_operator_properties_select_all(ot);
}
/** \} */
@@ -250,152 +249,164 @@ void MASK_OT_select_all(wmOperatorType *ot)
static int select_exec(bContext *C, wmOperator *op)
{
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
- MaskSpline *spline;
- MaskSplinePoint *point = NULL;
- float co[2];
- bool extend = RNA_boolean_get(op->ptr, "extend");
- bool deselect = RNA_boolean_get(op->ptr, "deselect");
- bool toggle = RNA_boolean_get(op->ptr, "toggle");
- eMaskWhichHandle which_handle;
- const float threshold = 19;
-
- RNA_float_get_array(op->ptr, "location", co);
-
- point = ED_mask_point_find_nearest(C, mask, co, threshold, &masklay, &spline, &which_handle, NULL);
-
- if (extend == false && deselect == false && toggle == false)
- ED_mask_select_toggle_all(mask, SEL_DESELECT);
-
- if (point) {
- if (which_handle != MASK_WHICH_HANDLE_NONE) {
- if (extend) {
- masklay->act_spline = spline;
- masklay->act_point = point;
-
- BKE_mask_point_select_set_handle(point, which_handle, true);
- }
- else if (deselect) {
- BKE_mask_point_select_set_handle(point, which_handle, false);
- }
- else {
- masklay->act_spline = spline;
- masklay->act_point = point;
-
- if (!MASKPOINT_ISSEL_HANDLE(point, which_handle)) {
- BKE_mask_point_select_set_handle(point, which_handle, true);
- }
- else if (toggle) {
- BKE_mask_point_select_set_handle(point, which_handle, false);
- }
- }
- }
- else {
- if (extend) {
- masklay->act_spline = spline;
- masklay->act_point = point;
-
- BKE_mask_point_select_set(point, true);
- }
- else if (deselect) {
- BKE_mask_point_select_set(point, false);
- }
- else {
- masklay->act_spline = spline;
- masklay->act_point = point;
-
- if (!MASKPOINT_ISSEL_ANY(point)) {
- BKE_mask_point_select_set(point, true);
- }
- else if (toggle) {
- BKE_mask_point_select_set(point, false);
- }
- }
- }
-
- masklay->act_spline = spline;
- masklay->act_point = point;
-
- ED_mask_select_flush_all(mask);
-
- WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
-
- return OPERATOR_FINISHED;
- }
- else {
- MaskSplinePointUW *uw;
-
- if (ED_mask_feather_find_nearest(C, mask, co, threshold, &masklay, &spline, &point, &uw, NULL)) {
-
- if (extend) {
- masklay->act_spline = spline;
- masklay->act_point = point;
-
- if (uw) uw->flag |= SELECT;
- }
- else if (deselect) {
- if (uw) uw->flag &= ~SELECT;
- }
- else {
- masklay->act_spline = spline;
- masklay->act_point = point;
-
- if (uw) {
- if (!(uw->flag & SELECT)) {
- uw->flag |= SELECT;
- }
- else if (toggle) {
- uw->flag &= ~SELECT;
- }
- }
- }
-
- ED_mask_select_flush_all(mask);
-
- WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
-
- return OPERATOR_FINISHED;
- }
- }
-
- return OPERATOR_PASS_THROUGH;
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+ MaskSpline *spline;
+ MaskSplinePoint *point = NULL;
+ float co[2];
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+ bool deselect = RNA_boolean_get(op->ptr, "deselect");
+ bool toggle = RNA_boolean_get(op->ptr, "toggle");
+ eMaskWhichHandle which_handle;
+ const float threshold = 19;
+
+ RNA_float_get_array(op->ptr, "location", co);
+
+ point = ED_mask_point_find_nearest(
+ C, mask, co, threshold, &masklay, &spline, &which_handle, NULL);
+
+ if (extend == false && deselect == false && toggle == false)
+ ED_mask_select_toggle_all(mask, SEL_DESELECT);
+
+ if (point) {
+ if (which_handle != MASK_WHICH_HANDLE_NONE) {
+ if (extend) {
+ masklay->act_spline = spline;
+ masklay->act_point = point;
+
+ BKE_mask_point_select_set_handle(point, which_handle, true);
+ }
+ else if (deselect) {
+ BKE_mask_point_select_set_handle(point, which_handle, false);
+ }
+ else {
+ masklay->act_spline = spline;
+ masklay->act_point = point;
+
+ if (!MASKPOINT_ISSEL_HANDLE(point, which_handle)) {
+ BKE_mask_point_select_set_handle(point, which_handle, true);
+ }
+ else if (toggle) {
+ BKE_mask_point_select_set_handle(point, which_handle, false);
+ }
+ }
+ }
+ else {
+ if (extend) {
+ masklay->act_spline = spline;
+ masklay->act_point = point;
+
+ BKE_mask_point_select_set(point, true);
+ }
+ else if (deselect) {
+ BKE_mask_point_select_set(point, false);
+ }
+ else {
+ masklay->act_spline = spline;
+ masklay->act_point = point;
+
+ if (!MASKPOINT_ISSEL_ANY(point)) {
+ BKE_mask_point_select_set(point, true);
+ }
+ else if (toggle) {
+ BKE_mask_point_select_set(point, false);
+ }
+ }
+ }
+
+ masklay->act_spline = spline;
+ masklay->act_point = point;
+
+ ED_mask_select_flush_all(mask);
+
+ WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ MaskSplinePointUW *uw;
+
+ if (ED_mask_feather_find_nearest(
+ C, mask, co, threshold, &masklay, &spline, &point, &uw, NULL)) {
+
+ if (extend) {
+ masklay->act_spline = spline;
+ masklay->act_point = point;
+
+ if (uw)
+ uw->flag |= SELECT;
+ }
+ else if (deselect) {
+ if (uw)
+ uw->flag &= ~SELECT;
+ }
+ else {
+ masklay->act_spline = spline;
+ masklay->act_point = point;
+
+ if (uw) {
+ if (!(uw->flag & SELECT)) {
+ uw->flag |= SELECT;
+ }
+ else if (toggle) {
+ uw->flag &= ~SELECT;
+ }
+ }
+ }
+
+ ED_mask_select_flush_all(mask);
+
+ WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
+
+ return OPERATOR_FINISHED;
+ }
+ }
+
+ return OPERATOR_PASS_THROUGH;
}
static int select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
- float co[2];
+ float co[2];
- ED_mask_mouse_pos(sa, ar, event->mval, co);
+ ED_mask_mouse_pos(sa, ar, event->mval, co);
- RNA_float_set_array(op->ptr, "location", co);
+ RNA_float_set_array(op->ptr, "location", co);
- return select_exec(C, op);
+ return select_exec(C, op);
}
void MASK_OT_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select";
- ot->description = "Select spline points";
- ot->idname = "MASK_OT_select";
-
- /* api callbacks */
- ot->exec = select_exec;
- ot->invoke = select_invoke;
- ot->poll = ED_maskedit_mask_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_mouse_select(ot);
-
- RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
- "Location", "Location of vertex in normalized space", -1.0f, 1.0f);
+ /* identifiers */
+ ot->name = "Select";
+ ot->description = "Select spline points";
+ ot->idname = "MASK_OT_select";
+
+ /* api callbacks */
+ ot->exec = select_exec;
+ ot->invoke = select_invoke;
+ ot->poll = ED_maskedit_mask_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_mouse_select(ot);
+
+ RNA_def_float_vector(ot->srna,
+ "location",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Location",
+ "Location of vertex in normalized space",
+ -1.0f,
+ 1.0f);
}
/** \} */
@@ -406,86 +417,86 @@ 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 *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
- int i;
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+ int i;
- rcti rect;
- rctf rectf;
- bool changed = false;
+ rcti rect;
+ rctf rectf;
+ bool changed = false;
- 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)) {
- ED_mask_select_toggle_all(mask, SEL_DESELECT);
- changed = true;
- }
+ 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)) {
+ ED_mask_select_toggle_all(mask, SEL_DESELECT);
+ changed = true;
+ }
- /* get rectangle from operator */
- WM_operator_properties_border_to_rcti(op, &rect);
+ /* 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(sa, ar, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin);
+ ED_mask_point_pos(sa, ar, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);
- /* do actual selection */
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
+ /* do actual selection */
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
- MaskSplinePoint *point_deform = &points_array[i];
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
+ MaskSplinePoint *point_deform = &points_array[i];
- /* TODO: handles? */
- /* TODO: uw? */
- if (BLI_rctf_isect_pt_v(&rectf, point_deform->bezt.vec[1])) {
- BKE_mask_point_select_set(point, select);
- BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, select);
- changed = true;
- }
- }
- }
- }
+ /* TODO: handles? */
+ /* TODO: uw? */
+ if (BLI_rctf_isect_pt_v(&rectf, point_deform->bezt.vec[1])) {
+ BKE_mask_point_select_set(point, select);
+ BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, select);
+ changed = true;
+ }
+ }
+ }
+ }
- if (changed) {
- ED_mask_select_flush_all(mask);
+ if (changed) {
+ ED_mask_select_flush_all(mask);
- WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
+ WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
void MASK_OT_select_box(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Box Select";
- ot->description = "Select curve points using box selection";
- ot->idname = "MASK_OT_select_box";
-
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = box_select_exec;
- ot->modal = WM_gesture_box_modal;
- ot->poll = ED_maskedit_mask_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_gesture_box(ot);
- WM_operator_properties_select_operation_simple(ot);
+ /* identifiers */
+ ot->name = "Box Select";
+ ot->description = "Select curve points using box selection";
+ ot->idname = "MASK_OT_select_box";
+
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = box_select_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->poll = ED_maskedit_mask_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_gesture_box(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
/** \} */
@@ -494,112 +505,117 @@ void MASK_OT_select_box(wmOperatorType *ot)
/** \name Lasso Select Operator
* \{ */
-static bool do_lasso_select_mask(bContext *C, const int mcords[][2], short moves, const eSelectOp sel_op)
+static bool do_lasso_select_mask(bContext *C,
+ const int mcords[][2],
+ short moves,
+ const eSelectOp sel_op)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
-
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
- int i;
-
- rcti rect;
- bool changed = false;
-
- const bool select = (sel_op != SEL_OP_SUB);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- ED_mask_select_toggle_all(mask, SEL_DESELECT);
- changed = true;
- }
-
- /* get rectangle from operator */
- BLI_lasso_boundbox(&rect, mcords, moves);
-
- /* do actual selection */
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
-
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
-
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
-
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
- MaskSplinePoint *point_deform = &points_array[i];
-
- /* TODO: handles? */
- /* TODO: uw? */
-
- if (MASKPOINT_ISSEL_ANY(point) && select) {
- continue;
- }
-
- float screen_co[2];
-
- /* point in screen coords */
- ED_mask_point_pos__reverse(sa, ar,
- 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))
- {
- BKE_mask_point_select_set(point, select);
- BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, select);
- changed = true;
- }
- }
- }
- }
-
- if (changed) {
- ED_mask_select_flush_all(mask);
-
- WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
- }
-
- return changed;
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+ int i;
+
+ rcti rect;
+ bool changed = false;
+
+ const bool select = (sel_op != SEL_OP_SUB);
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ ED_mask_select_toggle_all(mask, SEL_DESELECT);
+ changed = true;
+ }
+
+ /* get rectangle from operator */
+ BLI_lasso_boundbox(&rect, mcords, moves);
+
+ /* do actual selection */
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
+
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
+ MaskSplinePoint *point_deform = &points_array[i];
+
+ /* TODO: handles? */
+ /* TODO: uw? */
+
+ if (MASKPOINT_ISSEL_ANY(point) && select) {
+ continue;
+ }
+
+ float screen_co[2];
+
+ /* point in screen coords */
+ ED_mask_point_pos__reverse(sa,
+ ar,
+ 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)) {
+ BKE_mask_point_select_set(point, select);
+ BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, select);
+ changed = true;
+ }
+ }
+ }
+ }
+
+ if (changed) {
+ ED_mask_select_flush_all(mask);
+
+ WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
+ }
+
+ return changed;
}
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 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");
- do_lasso_select_mask(C, mcords, mcords_tot, sel_op);
+ if (mcords) {
+ const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
+ do_lasso_select_mask(C, mcords, mcords_tot, sel_op);
- MEM_freeN((void *)mcords);
+ MEM_freeN((void *)mcords);
- return OPERATOR_FINISHED;
- }
- return OPERATOR_PASS_THROUGH;
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_PASS_THROUGH;
}
void MASK_OT_select_lasso(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Lasso Select";
- ot->description = "Select curve points using lasso selection";
- ot->idname = "MASK_OT_select_lasso";
-
- /* api callbacks */
- ot->invoke = WM_gesture_lasso_invoke;
- ot->modal = WM_gesture_lasso_modal;
- ot->exec = clip_lasso_select_exec;
- ot->poll = ED_maskedit_mask_poll;
- 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);
+ /* identifiers */
+ ot->name = "Lasso Select";
+ ot->description = "Select curve points using lasso selection";
+ ot->idname = "MASK_OT_select_lasso";
+
+ /* api callbacks */
+ ot->invoke = WM_gesture_lasso_invoke;
+ ot->modal = WM_gesture_lasso_modal;
+ ot->exec = clip_lasso_select_exec;
+ ot->poll = ED_maskedit_mask_poll;
+ 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);
}
/** \} */
@@ -608,108 +624,110 @@ void MASK_OT_select_lasso(wmOperatorType *ot)
/** \name Circle Select Operator
* \{ */
-static int mask_spline_point_inside_ellipse(BezTriple *bezt, const float offset[2], const float ellipse[2])
+static int mask_spline_point_inside_ellipse(BezTriple *bezt,
+ const float offset[2],
+ const float ellipse[2])
{
- /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */
- float x, y;
+ /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */
+ float x, y;
- x = (bezt->vec[1][0] - offset[0]) * ellipse[0];
- y = (bezt->vec[1][1] - offset[1]) * ellipse[1];
+ x = (bezt->vec[1][0] - offset[0]) * ellipse[0];
+ y = (bezt->vec[1][1] - offset[1]) * ellipse[1];
- return x * x + y * y < 1.0f;
+ return x * x + y * y < 1.0f;
}
static int circle_select_exec(bContext *C, wmOperator *op)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
- int i;
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+ int i;
- float zoomx, zoomy, offset[2], ellipse[2];
- int width, height;
- bool changed = false;
+ float zoomx, zoomy, offset[2], ellipse[2];
+ int width, height;
+ bool changed = false;
- /* get operator properties */
- const int x = RNA_int_get(op->ptr, "x");
- const int y = RNA_int_get(op->ptr, "y");
- const int radius = RNA_int_get(op->ptr, "radius");
+ /* get operator properties */
+ const int x = RNA_int_get(op->ptr, "x");
+ const int y = RNA_int_get(op->ptr, "y");
+ 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);
- width = height = max_ii(width, height);
+ /* compute ellipse and position in unified coordinates */
+ ED_mask_get_size(sa, &width, &height);
+ ED_mask_zoom(sa, ar, &zoomx, &zoomy);
+ width = height = max_ii(width, height);
- ellipse[0] = width * zoomx / radius;
- ellipse[1] = height * zoomy / radius;
+ 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(sa, ar, 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));
- const bool select = (sel_op != SEL_OP_SUB);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- ED_mask_select_toggle_all(mask, SEL_DESELECT);
- changed = true;
- }
+ 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);
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ ED_mask_select_toggle_all(mask, SEL_DESELECT);
+ changed = true;
+ }
- /* do actual selection */
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
+ /* do actual selection */
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
- MaskSplinePoint *point_deform = &points_array[i];
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
+ MaskSplinePoint *point_deform = &points_array[i];
- if (mask_spline_point_inside_ellipse(&point_deform->bezt, offset, ellipse)) {
- BKE_mask_point_select_set(point, select);
- BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, select);
+ if (mask_spline_point_inside_ellipse(&point_deform->bezt, offset, ellipse)) {
+ BKE_mask_point_select_set(point, select);
+ BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, select);
- changed = true;
- }
- }
- }
- }
+ changed = true;
+ }
+ }
+ }
+ }
- if (changed) {
- ED_mask_select_flush_all(mask);
+ if (changed) {
+ ED_mask_select_flush_all(mask);
- WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
+ WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
void MASK_OT_select_circle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Circle Select";
- ot->description = "Select curve points using circle selection";
- ot->idname = "MASK_OT_select_circle";
-
- /* api callbacks */
- ot->invoke = WM_gesture_circle_invoke;
- ot->modal = WM_gesture_circle_modal;
- ot->exec = circle_select_exec;
- ot->poll = ED_maskedit_mask_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_gesture_circle(ot);
- WM_operator_properties_select_operation_simple(ot);
+ /* identifiers */
+ ot->name = "Circle Select";
+ ot->description = "Select curve points using circle selection";
+ ot->idname = "MASK_OT_select_circle";
+
+ /* api callbacks */
+ ot->invoke = WM_gesture_circle_invoke;
+ ot->modal = WM_gesture_circle_modal;
+ ot->exec = circle_select_exec;
+ ot->poll = ED_maskedit_mask_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_gesture_circle(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
/** \} */
@@ -720,56 +738,56 @@ 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 *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
- MaskSpline *spline;
- MaskSplinePoint *point = NULL;
- float co[2];
- bool do_select = !RNA_boolean_get(op->ptr, "deselect");
- const float threshold = 19;
- bool changed = false;
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+ MaskSpline *spline;
+ MaskSplinePoint *point = NULL;
+ float co[2];
+ bool do_select = !RNA_boolean_get(op->ptr, "deselect");
+ const float threshold = 19;
+ bool changed = false;
- ED_mask_mouse_pos(sa, ar, event->mval, co);
+ ED_mask_mouse_pos(sa, ar, event->mval, co);
- point = ED_mask_point_find_nearest(C, mask, co, threshold, &masklay, &spline, NULL, NULL);
+ point = ED_mask_point_find_nearest(C, mask, co, threshold, &masklay, &spline, NULL, NULL);
- if (point) {
- ED_mask_spline_select_set(spline, do_select);
- masklay->act_spline = spline;
- masklay->act_point = point;
+ if (point) {
+ ED_mask_spline_select_set(spline, do_select);
+ masklay->act_spline = spline;
+ masklay->act_point = point;
- changed = true;
- }
+ changed = true;
+ }
- if (changed) {
- ED_mask_select_flush_all(mask);
+ if (changed) {
+ ED_mask_select_flush_all(mask);
- WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
+ WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
void MASK_OT_select_linked_pick(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Linked";
- ot->idname = "MASK_OT_select_linked_pick";
- ot->description = "(De)select all points linked to the curve under the mouse cursor";
+ /* identifiers */
+ ot->name = "Select Linked";
+ ot->idname = "MASK_OT_select_linked_pick";
+ ot->description = "(De)select all points linked to the curve under the mouse cursor";
- /* api callbacks */
- ot->invoke = mask_select_linked_pick_invoke;
- ot->poll = ED_maskedit_mask_poll;
+ /* api callbacks */
+ ot->invoke = mask_select_linked_pick_invoke;
+ ot->poll = ED_maskedit_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
}
/** \} */
@@ -780,51 +798,51 @@ void MASK_OT_select_linked_pick(wmOperatorType *ot)
static int mask_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
{
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
- bool changed = false;
+ bool changed = false;
- /* do actual selection */
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
+ /* do actual selection */
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- if (ED_mask_spline_select_check(spline)) {
- ED_mask_spline_select_set(spline, true);
- changed = true;
- }
- }
- }
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ if (ED_mask_spline_select_check(spline)) {
+ ED_mask_spline_select_set(spline, true);
+ changed = true;
+ }
+ }
+ }
- if (changed) {
- ED_mask_select_flush_all(mask);
+ if (changed) {
+ ED_mask_select_flush_all(mask);
- WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
+ WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
void MASK_OT_select_linked(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Linked All";
- ot->idname = "MASK_OT_select_linked";
- ot->description = "Select all curve points linked to already selected ones";
+ /* identifiers */
+ ot->name = "Select Linked All";
+ ot->idname = "MASK_OT_select_linked";
+ ot->description = "Select all curve points linked to already selected ones";
- /* api callbacks */
- ot->exec = mask_select_linked_exec;
- ot->poll = ED_maskedit_mask_poll;
+ /* api callbacks */
+ ot->exec = mask_select_linked_exec;
+ ot->poll = ED_maskedit_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -835,118 +853,118 @@ void MASK_OT_select_linked(wmOperatorType *ot)
static int mask_select_more_less(bContext *C, bool more)
{
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
-
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
-
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
-
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- const bool cyclic = (spline->flag & MASK_SPLINE_CYCLIC) != 0;
- bool start_sel, end_sel, prev_sel, cur_sel;
- int i;
-
- /* reselect point if any handle is selected to make the result more predictable */
- for (i = 0; i < spline->tot_point; i++) {
- BKE_mask_point_select_set(spline->points + i, MASKPOINT_ISSEL_ANY(spline->points + i));
- }
-
- /* select more/less does not affect empty/single point splines */
- if (spline->tot_point < 2) {
- continue;
- }
-
- if (cyclic) {
- start_sel = !!MASKPOINT_ISSEL_KNOT(spline->points);
- end_sel = !!MASKPOINT_ISSEL_KNOT(&spline->points[spline->tot_point - 1]);
- }
- else {
- start_sel = false;
- end_sel = false;
- }
-
- for (i = 0; i < spline->tot_point; i++) {
- if (i == 0 && !cyclic) {
- continue;
- }
-
- prev_sel = (i > 0) ? !!MASKPOINT_ISSEL_KNOT(&spline->points[i - 1]) : end_sel;
- cur_sel = !!MASKPOINT_ISSEL_KNOT(&spline->points[i]);
-
- if (cur_sel != more) {
- if (prev_sel == more) {
- BKE_mask_point_select_set(&spline->points[i], more);
- }
- i++;
- }
- }
-
- for (i = spline->tot_point - 1; i >= 0; i--) {
- if (i == spline->tot_point - 1 && !cyclic) {
- continue;
- }
-
- prev_sel = (i < spline->tot_point - 1) ? !!MASKPOINT_ISSEL_KNOT(&spline->points[i + 1]) : start_sel;
- cur_sel = !!MASKPOINT_ISSEL_KNOT(&spline->points[i]);
-
- if (cur_sel != more) {
- if (prev_sel == more) {
- BKE_mask_point_select_set(&spline->points[i], more);
- }
- i--;
- }
- }
- }
- }
-
- WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
-
- return OPERATOR_FINISHED;
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ const bool cyclic = (spline->flag & MASK_SPLINE_CYCLIC) != 0;
+ bool start_sel, end_sel, prev_sel, cur_sel;
+ int i;
+
+ /* reselect point if any handle is selected to make the result more predictable */
+ for (i = 0; i < spline->tot_point; i++) {
+ BKE_mask_point_select_set(spline->points + i, MASKPOINT_ISSEL_ANY(spline->points + i));
+ }
+
+ /* select more/less does not affect empty/single point splines */
+ if (spline->tot_point < 2) {
+ continue;
+ }
+
+ if (cyclic) {
+ start_sel = !!MASKPOINT_ISSEL_KNOT(spline->points);
+ end_sel = !!MASKPOINT_ISSEL_KNOT(&spline->points[spline->tot_point - 1]);
+ }
+ else {
+ start_sel = false;
+ end_sel = false;
+ }
+
+ for (i = 0; i < spline->tot_point; i++) {
+ if (i == 0 && !cyclic) {
+ continue;
+ }
+
+ prev_sel = (i > 0) ? !!MASKPOINT_ISSEL_KNOT(&spline->points[i - 1]) : end_sel;
+ cur_sel = !!MASKPOINT_ISSEL_KNOT(&spline->points[i]);
+
+ if (cur_sel != more) {
+ if (prev_sel == more) {
+ BKE_mask_point_select_set(&spline->points[i], more);
+ }
+ i++;
+ }
+ }
+
+ for (i = spline->tot_point - 1; i >= 0; i--) {
+ if (i == spline->tot_point - 1 && !cyclic) {
+ continue;
+ }
+
+ prev_sel = (i < spline->tot_point - 1) ? !!MASKPOINT_ISSEL_KNOT(&spline->points[i + 1]) :
+ start_sel;
+ cur_sel = !!MASKPOINT_ISSEL_KNOT(&spline->points[i]);
+
+ if (cur_sel != more) {
+ if (prev_sel == more) {
+ BKE_mask_point_select_set(&spline->points[i], more);
+ }
+ i--;
+ }
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
+
+ return OPERATOR_FINISHED;
}
static int mask_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
- return mask_select_more_less(C, true);
+ return mask_select_more_less(C, true);
}
void MASK_OT_select_more(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select More";
- ot->idname = "MASK_OT_select_more";
- ot->description = "Select more spline points connected to initial selection";
+ /* identifiers */
+ ot->name = "Select More";
+ ot->idname = "MASK_OT_select_more";
+ ot->description = "Select more spline points connected to initial selection";
- /* api callbacks */
- ot->exec = mask_select_more_exec;
- ot->poll = ED_maskedit_mask_poll;
+ /* api callbacks */
+ ot->exec = mask_select_more_exec;
+ ot->poll = ED_maskedit_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int mask_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
- return mask_select_more_less(C, false);
+ return mask_select_more_less(C, false);
}
void MASK_OT_select_less(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Less";
- ot->idname = "MASK_OT_select_less";
- ot->description = "Deselect spline points at the boundary of each selection region";
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->idname = "MASK_OT_select_less";
+ ot->description = "Deselect spline points at the boundary of each selection region";
- /* api callbacks */
- ot->exec = mask_select_less_exec;
- ot->poll = ED_maskedit_mask_poll;
+ /* api callbacks */
+ ot->exec = mask_select_less_exec;
+ ot->poll = ED_maskedit_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/** \} */
diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c
index 7d33d13cbd3..edc22943124 100644
--- a/source/blender/editors/mask/mask_shapekey.c
+++ b/source/blender/editors/mask/mask_shapekey.c
@@ -42,193 +42,190 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_mask.h" /* own include */
+#include "ED_mask.h" /* own include */
-#include "mask_intern.h" /* own include */
+#include "mask_intern.h" /* own include */
static int mask_shape_key_insert_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- const int frame = CFRA;
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
- bool changed = false;
-
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskLayerShape *masklay_shape;
-
- if (!ED_mask_layer_select_check(masklay)) {
- continue;
- }
-
- masklay_shape = BKE_mask_layer_shape_verify_frame(masklay, frame);
- BKE_mask_layer_shape_from_mask(masklay, masklay_shape);
- changed = true;
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
- DEG_id_tag_update(&mask->id, 0);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Scene *scene = CTX_data_scene(C);
+ const int frame = CFRA;
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+ bool changed = false;
+
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskLayerShape *masklay_shape;
+
+ if (!ED_mask_layer_select_check(masklay)) {
+ continue;
+ }
+
+ masklay_shape = BKE_mask_layer_shape_verify_frame(masklay, frame);
+ BKE_mask_layer_shape_from_mask(masklay, masklay_shape);
+ changed = true;
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
+ DEG_id_tag_update(&mask->id, 0);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void MASK_OT_shape_key_insert(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Insert Shape Key";
- ot->idname = "MASK_OT_shape_key_insert";
+ /* identifiers */
+ ot->name = "Insert Shape Key";
+ ot->idname = "MASK_OT_shape_key_insert";
- /* api callbacks */
- ot->exec = mask_shape_key_insert_exec;
- ot->poll = ED_maskedit_mask_poll;
+ /* api callbacks */
+ ot->exec = mask_shape_key_insert_exec;
+ ot->poll = ED_maskedit_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int mask_shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- const int frame = CFRA;
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
- bool changed = false;
-
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskLayerShape *masklay_shape;
-
- if (!ED_mask_layer_select_check(masklay)) {
- continue;
- }
-
- masklay_shape = BKE_mask_layer_shape_find_frame(masklay, frame);
-
- if (masklay_shape) {
- BKE_mask_layer_shape_unlink(masklay, masklay_shape);
- changed = true;
- }
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
- DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Scene *scene = CTX_data_scene(C);
+ const int frame = CFRA;
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+ bool changed = false;
+
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskLayerShape *masklay_shape;
+
+ if (!ED_mask_layer_select_check(masklay)) {
+ continue;
+ }
+
+ masklay_shape = BKE_mask_layer_shape_find_frame(masklay, frame);
+
+ if (masklay_shape) {
+ BKE_mask_layer_shape_unlink(masklay, masklay_shape);
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
+ DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void MASK_OT_shape_key_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Shape Key";
- ot->idname = "MASK_OT_shape_key_clear";
+ /* identifiers */
+ ot->name = "Clear Shape Key";
+ ot->idname = "MASK_OT_shape_key_clear";
- /* api callbacks */
- ot->exec = mask_shape_key_clear_exec;
- ot->poll = ED_maskedit_mask_poll;
+ /* api callbacks */
+ ot->exec = mask_shape_key_clear_exec;
+ ot->poll = ED_maskedit_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- const int frame = CFRA;
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
- bool changed = false;
-
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
-
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
-
- if (masklay->splines_shapes.first) {
- MaskLayerShape *masklay_shape_reset;
- MaskLayerShape *masklay_shape;
-
- /* get the shapekey of the current state */
- masklay_shape_reset = BKE_mask_layer_shape_alloc(masklay, frame);
- /* initialize from mask - as if inseting a keyframe */
- BKE_mask_layer_shape_from_mask(masklay, masklay_shape_reset);
-
- for (masklay_shape = masklay->splines_shapes.first;
- masklay_shape;
- masklay_shape = masklay_shape->next)
- {
-
- if (masklay_shape_reset->tot_vert == masklay_shape->tot_vert) {
- int i_abs = 0;
- int i;
- MaskSpline *spline;
- MaskLayerShapeElem *shape_ele_src;
- MaskLayerShapeElem *shape_ele_dst;
-
- shape_ele_src = (MaskLayerShapeElem *)masklay_shape_reset->data;
- shape_ele_dst = (MaskLayerShapeElem *)masklay_shape->data;
-
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
-
- if (MASKPOINT_ISSEL_ANY(point)) {
- /* TODO - nicer access here */
- shape_ele_dst->value[6] = shape_ele_src->value[6];
- }
-
- shape_ele_src++;
- shape_ele_dst++;
-
- i_abs++;
- }
- }
-
- }
- else {
- // printf("%s: skipping\n", __func__);
- }
-
- changed = true;
- }
-
- BKE_mask_layer_shape_free(masklay_shape_reset);
- }
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
- DEG_id_tag_update(&mask->id, 0);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Scene *scene = CTX_data_scene(C);
+ const int frame = CFRA;
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+ bool changed = false;
+
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+
+ if (masklay->splines_shapes.first) {
+ MaskLayerShape *masklay_shape_reset;
+ MaskLayerShape *masklay_shape;
+
+ /* get the shapekey of the current state */
+ masklay_shape_reset = BKE_mask_layer_shape_alloc(masklay, frame);
+ /* initialize from mask - as if inseting a keyframe */
+ BKE_mask_layer_shape_from_mask(masklay, masklay_shape_reset);
+
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape->next) {
+
+ if (masklay_shape_reset->tot_vert == masklay_shape->tot_vert) {
+ int i_abs = 0;
+ int i;
+ MaskSpline *spline;
+ MaskLayerShapeElem *shape_ele_src;
+ MaskLayerShapeElem *shape_ele_dst;
+
+ shape_ele_src = (MaskLayerShapeElem *)masklay_shape_reset->data;
+ shape_ele_dst = (MaskLayerShapeElem *)masklay_shape->data;
+
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
+
+ if (MASKPOINT_ISSEL_ANY(point)) {
+ /* TODO - nicer access here */
+ shape_ele_dst->value[6] = shape_ele_src->value[6];
+ }
+
+ shape_ele_src++;
+ shape_ele_dst++;
+
+ i_abs++;
+ }
+ }
+ }
+ else {
+ // printf("%s: skipping\n", __func__);
+ }
+
+ changed = true;
+ }
+
+ BKE_mask_layer_shape_free(masklay_shape_reset);
+ }
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
+ DEG_id_tag_update(&mask->id, 0);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void MASK_OT_shape_key_feather_reset(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Feather Reset Animation";
- ot->description = "Reset feather weights on all selected points animation values";
- ot->idname = "MASK_OT_shape_key_feather_reset";
+ /* identifiers */
+ ot->name = "Feather Reset Animation";
+ ot->description = "Reset feather weights on all selected points animation values";
+ ot->idname = "MASK_OT_shape_key_feather_reset";
- /* api callbacks */
- ot->exec = mask_shape_key_feather_reset_exec;
- ot->poll = ED_maskedit_mask_poll;
+ /* api callbacks */
+ ot->exec = mask_shape_key_feather_reset_exec;
+ ot->poll = ED_maskedit_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/*
@@ -241,208 +238,202 @@ void MASK_OT_shape_key_feather_reset(wmOperatorType *ot)
*/
static int mask_shape_key_rekey_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- const int frame = CFRA;
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
- bool changed = false;
-
- const bool do_feather = RNA_boolean_get(op->ptr, "feather");
- const bool do_location = RNA_boolean_get(op->ptr, "location");
-
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
-
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
-
- /* we need at least one point selected here to bother re-interpolating */
- if (!ED_mask_layer_select_check(masklay)) {
- continue;
- }
-
- if (masklay->splines_shapes.first) {
- MaskLayerShape *masklay_shape, *masklay_shape_next;
- MaskLayerShape *masklay_shape_lastsel = NULL;
-
- for (masklay_shape = masklay->splines_shapes.first;
- masklay_shape;
- masklay_shape = masklay_shape_next)
- {
- MaskLayerShape *masklay_shape_a = NULL;
- MaskLayerShape *masklay_shape_b = NULL;
-
- masklay_shape_next = masklay_shape->next;
-
- /* find contiguous selections */
- if (masklay_shape->flag & MASK_SHAPE_SELECT) {
- if (masklay_shape_lastsel == NULL) {
- masklay_shape_lastsel = masklay_shape;
- }
- if ((masklay_shape->next == NULL) ||
- (((MaskLayerShape *)masklay_shape->next)->flag & MASK_SHAPE_SELECT) == 0)
- {
- masklay_shape_a = masklay_shape_lastsel;
- masklay_shape_b = masklay_shape;
- masklay_shape_lastsel = NULL;
-
- /* this will be freed below, step over selection */
- masklay_shape_next = masklay_shape->next;
- }
- }
-
- /* we have a from<>to? - re-interpolate! */
- if (masklay_shape_a && masklay_shape_b) {
- ListBase shapes_tmp = {NULL, NULL};
- MaskLayerShape *masklay_shape_tmp;
- MaskLayerShape *masklay_shape_tmp_next;
- MaskLayerShape *masklay_shape_tmp_last = masklay_shape_b->next;
- MaskLayerShape *masklay_shape_tmp_rekey;
-
- /* move keys */
- for (masklay_shape_tmp = masklay_shape_a;
- masklay_shape_tmp && (masklay_shape_tmp != masklay_shape_tmp_last);
- masklay_shape_tmp = masklay_shape_tmp_next)
- {
- masklay_shape_tmp_next = masklay_shape_tmp->next;
- BLI_remlink(&masklay->splines_shapes, masklay_shape_tmp);
- BLI_addtail(&shapes_tmp, masklay_shape_tmp);
- }
-
- /* re-key, note: cant modify the keys here since it messes uop */
- for (masklay_shape_tmp = shapes_tmp.first;
- masklay_shape_tmp;
- masklay_shape_tmp = masklay_shape_tmp->next)
- {
- BKE_mask_layer_evaluate(masklay, masklay_shape_tmp->frame, true);
- masklay_shape_tmp_rekey = BKE_mask_layer_shape_verify_frame(masklay, masklay_shape_tmp->frame);
- BKE_mask_layer_shape_from_mask(masklay, masklay_shape_tmp_rekey);
- masklay_shape_tmp_rekey->flag = masklay_shape_tmp->flag & MASK_SHAPE_SELECT;
- }
-
- /* restore unselected points and free copies */
- for (masklay_shape_tmp = shapes_tmp.first;
- masklay_shape_tmp;
- masklay_shape_tmp = masklay_shape_tmp_next)
- {
- /* restore */
- int i_abs = 0;
- int i;
- MaskSpline *spline;
- MaskLayerShapeElem *shape_ele_src;
- MaskLayerShapeElem *shape_ele_dst;
-
- masklay_shape_tmp_next = masklay_shape_tmp->next;
-
- /* we know this exists, added above */
- masklay_shape_tmp_rekey = BKE_mask_layer_shape_find_frame(masklay, masklay_shape_tmp->frame);
-
- shape_ele_src = (MaskLayerShapeElem *)masklay_shape_tmp->data;
- shape_ele_dst = (MaskLayerShapeElem *)masklay_shape_tmp_rekey->data;
-
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
-
- /* not especially efficient but makes this easier to follow */
- SWAP(MaskLayerShapeElem, *shape_ele_src, *shape_ele_dst);
-
- if (MASKPOINT_ISSEL_ANY(point)) {
- if (do_location) {
- memcpy(shape_ele_dst->value, shape_ele_src->value, sizeof(float) * 6);
- }
- if (do_feather) {
- shape_ele_dst->value[6] = shape_ele_src->value[6];
- }
- }
-
- shape_ele_src++;
- shape_ele_dst++;
-
- i_abs++;
- }
- }
-
- BKE_mask_layer_shape_free(masklay_shape_tmp);
- }
-
- changed = true;
- }
- }
-
- /* re-evaluate */
- BKE_mask_layer_evaluate(masklay, frame, true);
- }
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
- DEG_id_tag_update(&mask->id, 0);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Scene *scene = CTX_data_scene(C);
+ const int frame = CFRA;
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+ bool changed = false;
+
+ const bool do_feather = RNA_boolean_get(op->ptr, "feather");
+ const bool do_location = RNA_boolean_get(op->ptr, "location");
+
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+
+ /* we need at least one point selected here to bother re-interpolating */
+ if (!ED_mask_layer_select_check(masklay)) {
+ continue;
+ }
+
+ if (masklay->splines_shapes.first) {
+ MaskLayerShape *masklay_shape, *masklay_shape_next;
+ MaskLayerShape *masklay_shape_lastsel = NULL;
+
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape_next) {
+ MaskLayerShape *masklay_shape_a = NULL;
+ MaskLayerShape *masklay_shape_b = NULL;
+
+ masklay_shape_next = masklay_shape->next;
+
+ /* find contiguous selections */
+ if (masklay_shape->flag & MASK_SHAPE_SELECT) {
+ if (masklay_shape_lastsel == NULL) {
+ masklay_shape_lastsel = masklay_shape;
+ }
+ if ((masklay_shape->next == NULL) ||
+ (((MaskLayerShape *)masklay_shape->next)->flag & MASK_SHAPE_SELECT) == 0) {
+ masklay_shape_a = masklay_shape_lastsel;
+ masklay_shape_b = masklay_shape;
+ masklay_shape_lastsel = NULL;
+
+ /* this will be freed below, step over selection */
+ masklay_shape_next = masklay_shape->next;
+ }
+ }
+
+ /* we have a from<>to? - re-interpolate! */
+ if (masklay_shape_a && masklay_shape_b) {
+ ListBase shapes_tmp = {NULL, NULL};
+ MaskLayerShape *masklay_shape_tmp;
+ MaskLayerShape *masklay_shape_tmp_next;
+ MaskLayerShape *masklay_shape_tmp_last = masklay_shape_b->next;
+ MaskLayerShape *masklay_shape_tmp_rekey;
+
+ /* move keys */
+ for (masklay_shape_tmp = masklay_shape_a;
+ masklay_shape_tmp && (masklay_shape_tmp != masklay_shape_tmp_last);
+ masklay_shape_tmp = masklay_shape_tmp_next) {
+ masklay_shape_tmp_next = masklay_shape_tmp->next;
+ BLI_remlink(&masklay->splines_shapes, masklay_shape_tmp);
+ BLI_addtail(&shapes_tmp, masklay_shape_tmp);
+ }
+
+ /* re-key, note: cant modify the keys here since it messes uop */
+ for (masklay_shape_tmp = shapes_tmp.first; masklay_shape_tmp;
+ masklay_shape_tmp = masklay_shape_tmp->next) {
+ BKE_mask_layer_evaluate(masklay, masklay_shape_tmp->frame, true);
+ masklay_shape_tmp_rekey = BKE_mask_layer_shape_verify_frame(masklay,
+ masklay_shape_tmp->frame);
+ BKE_mask_layer_shape_from_mask(masklay, masklay_shape_tmp_rekey);
+ masklay_shape_tmp_rekey->flag = masklay_shape_tmp->flag & MASK_SHAPE_SELECT;
+ }
+
+ /* restore unselected points and free copies */
+ for (masklay_shape_tmp = shapes_tmp.first; masklay_shape_tmp;
+ masklay_shape_tmp = masklay_shape_tmp_next) {
+ /* restore */
+ int i_abs = 0;
+ int i;
+ MaskSpline *spline;
+ MaskLayerShapeElem *shape_ele_src;
+ MaskLayerShapeElem *shape_ele_dst;
+
+ masklay_shape_tmp_next = masklay_shape_tmp->next;
+
+ /* we know this exists, added above */
+ masklay_shape_tmp_rekey = BKE_mask_layer_shape_find_frame(masklay,
+ masklay_shape_tmp->frame);
+
+ shape_ele_src = (MaskLayerShapeElem *)masklay_shape_tmp->data;
+ shape_ele_dst = (MaskLayerShapeElem *)masklay_shape_tmp_rekey->data;
+
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
+
+ /* not especially efficient but makes this easier to follow */
+ SWAP(MaskLayerShapeElem, *shape_ele_src, *shape_ele_dst);
+
+ if (MASKPOINT_ISSEL_ANY(point)) {
+ if (do_location) {
+ memcpy(shape_ele_dst->value, shape_ele_src->value, sizeof(float) * 6);
+ }
+ if (do_feather) {
+ shape_ele_dst->value[6] = shape_ele_src->value[6];
+ }
+ }
+
+ shape_ele_src++;
+ shape_ele_dst++;
+
+ i_abs++;
+ }
+ }
+
+ BKE_mask_layer_shape_free(masklay_shape_tmp);
+ }
+
+ changed = true;
+ }
+ }
+
+ /* re-evaluate */
+ BKE_mask_layer_evaluate(masklay, frame, true);
+ }
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
+ DEG_id_tag_update(&mask->id, 0);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void MASK_OT_shape_key_rekey(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Re-Key Points of Selected Shapes";
- ot->description = "Recalculate animation data on selected points for frames selected in the dopesheet";
- ot->idname = "MASK_OT_shape_key_rekey";
-
- /* api callbacks */
- ot->exec = mask_shape_key_rekey_exec;
- ot->poll = ED_maskedit_mask_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "location", true, "Location", "");
- RNA_def_boolean(ot->srna, "feather", true, "Feather", "");
+ /* identifiers */
+ ot->name = "Re-Key Points of Selected Shapes";
+ ot->description =
+ "Recalculate animation data on selected points for frames selected in the dopesheet";
+ ot->idname = "MASK_OT_shape_key_rekey";
+
+ /* api callbacks */
+ ot->exec = mask_shape_key_rekey_exec;
+ ot->poll = ED_maskedit_mask_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "location", true, "Location", "");
+ RNA_def_boolean(ot->srna, "feather", true, "Feather", "");
}
-
/* *** Shape Key Utils *** */
void ED_mask_layer_shape_auto_key(MaskLayer *masklay, const int frame)
{
- MaskLayerShape *masklay_shape;
+ MaskLayerShape *masklay_shape;
- masklay_shape = BKE_mask_layer_shape_verify_frame(masklay, frame);
- BKE_mask_layer_shape_from_mask(masklay, masklay_shape);
+ masklay_shape = BKE_mask_layer_shape_verify_frame(masklay, frame);
+ BKE_mask_layer_shape_from_mask(masklay, masklay_shape);
}
bool ED_mask_layer_shape_auto_key_all(Mask *mask, const int frame)
{
- MaskLayer *masklay;
- bool changed = false;
+ MaskLayer *masklay;
+ bool changed = false;
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- ED_mask_layer_shape_auto_key(masklay, frame);
- changed = true;
- }
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ ED_mask_layer_shape_auto_key(masklay, frame);
+ changed = true;
+ }
- return changed;
+ return changed;
}
bool ED_mask_layer_shape_auto_key_select(Mask *mask, const int frame)
{
- MaskLayer *masklay;
- bool changed = false;
+ MaskLayer *masklay;
+ bool changed = false;
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- if (!ED_mask_layer_select_check(masklay)) {
- continue;
- }
+ if (!ED_mask_layer_select_check(masklay)) {
+ continue;
+ }
- ED_mask_layer_shape_auto_key(masklay, frame);
- changed = true;
- }
+ ED_mask_layer_shape_auto_key(masklay, frame);
+ changed = true;
+ }
- return changed;
+ return changed;
}
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt
index 707aeb781c6..e67d63b01a5 100644
--- a/source/blender/editors/mesh/CMakeLists.txt
+++ b/source/blender/editors/mesh/CMakeLists.txt
@@ -16,77 +16,77 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../uvedit
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../depsgraph
- ../../bmesh
- ../../gpu
- ../../imbuf
- ../../makesdna
- ../../makesrna
- ../../render/extern/include
- ../../windowmanager
- ../../../../intern/clog
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../uvedit
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../depsgraph
+ ../../bmesh
+ ../../gpu
+ ../../imbuf
+ ../../makesdna
+ ../../makesrna
+ ../../render/extern/include
+ ../../windowmanager
+ ../../../../intern/clog
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- editface.c
- editmesh_add.c
- editmesh_add_gizmo.c
- editmesh_bevel.c
- editmesh_bisect.c
- editmesh_extrude.c
- editmesh_extrude_screw.c
- editmesh_extrude_spin.c
- editmesh_extrude_spin_gizmo.c
- editmesh_inset.c
- editmesh_intersect.c
- editmesh_knife.c
- editmesh_knife_project.c
- editmesh_loopcut.c
- editmesh_path.c
- editmesh_polybuild.c
- editmesh_preselect_edgering.c
- editmesh_preselect_elem.c
- editmesh_rip.c
- editmesh_rip_edge.c
- editmesh_select.c
- editmesh_select_similar.c
- editmesh_tools.c
- editmesh_undo.c
- editmesh_utils.c
- mesh_data.c
- mesh_mirror.c
- mesh_ops.c
- meshtools.c
+ editface.c
+ editmesh_add.c
+ editmesh_add_gizmo.c
+ editmesh_bevel.c
+ editmesh_bisect.c
+ editmesh_extrude.c
+ editmesh_extrude_screw.c
+ editmesh_extrude_spin.c
+ editmesh_extrude_spin_gizmo.c
+ editmesh_inset.c
+ editmesh_intersect.c
+ editmesh_knife.c
+ editmesh_knife_project.c
+ editmesh_loopcut.c
+ editmesh_path.c
+ editmesh_polybuild.c
+ editmesh_preselect_edgering.c
+ editmesh_preselect_elem.c
+ editmesh_rip.c
+ editmesh_rip_edge.c
+ editmesh_select.c
+ editmesh_select_similar.c
+ editmesh_tools.c
+ editmesh_undo.c
+ editmesh_utils.c
+ mesh_data.c
+ mesh_mirror.c
+ mesh_ops.c
+ meshtools.c
- mesh_intern.h
+ mesh_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
+ bf_blenkernel
+ bf_blenlib
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
if(WITH_FREESTYLE)
- add_definitions(-DWITH_FREESTYLE)
+ add_definitions(-DWITH_FREESTYLE)
endif()
if(WITH_BULLET)
- add_definitions(-DWITH_BULLET)
+ add_definitions(-DWITH_BULLET)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 7a6144d8e0f..f342cc3a809 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -57,601 +57,603 @@
* use in object mode when selecting faces (while painting) */
void paintface_flush_flags(struct bContext *C, Object *ob, short flag)
{
- Mesh *me = BKE_mesh_from_object(ob);
- MPoly *polys, *mp_orig;
- const int *index_array = NULL;
- int totpoly;
- int i;
-
- BLI_assert((flag & ~(SELECT | ME_HIDE)) == 0);
-
- if (me == NULL)
- return;
-
- /* note, call #BKE_mesh_flush_hidden_from_verts_ex first when changing hidden flags */
-
- /* we could call this directly in all areas that change selection,
- * since this could become slow for realtime updates (circle-select for eg) */
- if (flag & SELECT) {
- BKE_mesh_flush_select_from_polys(me);
- }
-
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
-
- if (ob_eval == NULL) {
- return;
- }
-
- Mesh *me_orig = ob_eval->runtime.mesh_orig;
- Mesh *me_eval = ob_eval->runtime.mesh_eval;
- bool updated = false;
-
- if (me_orig != NULL && me_eval != NULL && me_orig->totpoly == me->totpoly) {
- /* Update the COW copy of the mesh. */
- for (i = 0; i < me->totpoly; i++) {
- me_orig->mpoly[i].flag = me->mpoly[i].flag;
- }
-
- /* If the mesh has only deform modifiers, the evaluated mesh shares arrays. */
- if (me_eval->mpoly == me_orig->mpoly) {
- updated = true;
- }
- /* Mesh polys => Final derived polys */
- else if ((index_array = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) {
- polys = me_eval->mpoly;
- totpoly = me_eval->totpoly;
-
- /* loop over final derived polys */
- for (i = 0; i < totpoly; i++) {
- if (index_array[i] != ORIGINDEX_NONE) {
- /* Copy flags onto the final derived poly from the original mesh poly */
- mp_orig = me->mpoly + index_array[i];
- polys[i].flag = mp_orig->flag;
-
- }
- }
-
- updated = true;
- }
- }
-
- if (updated) {
- if (flag & ME_HIDE) {
- BKE_mesh_batch_cache_dirty_tag(me_eval, BKE_MESH_BATCH_DIRTY_ALL);
- }
- else {
- BKE_mesh_batch_cache_dirty_tag(me_eval, BKE_MESH_BATCH_DIRTY_SELECT);
- }
-
- DEG_id_tag_update(ob->data, ID_RECALC_SELECT);
- }
- else {
- DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
+ Mesh *me = BKE_mesh_from_object(ob);
+ MPoly *polys, *mp_orig;
+ const int *index_array = NULL;
+ int totpoly;
+ int i;
+
+ BLI_assert((flag & ~(SELECT | ME_HIDE)) == 0);
+
+ if (me == NULL)
+ return;
+
+ /* note, call #BKE_mesh_flush_hidden_from_verts_ex first when changing hidden flags */
+
+ /* we could call this directly in all areas that change selection,
+ * since this could become slow for realtime updates (circle-select for eg) */
+ if (flag & SELECT) {
+ BKE_mesh_flush_select_from_polys(me);
+ }
+
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+
+ if (ob_eval == NULL) {
+ return;
+ }
+
+ Mesh *me_orig = ob_eval->runtime.mesh_orig;
+ Mesh *me_eval = ob_eval->runtime.mesh_eval;
+ bool updated = false;
+
+ if (me_orig != NULL && me_eval != NULL && me_orig->totpoly == me->totpoly) {
+ /* Update the COW copy of the mesh. */
+ for (i = 0; i < me->totpoly; i++) {
+ me_orig->mpoly[i].flag = me->mpoly[i].flag;
+ }
+
+ /* If the mesh has only deform modifiers, the evaluated mesh shares arrays. */
+ if (me_eval->mpoly == me_orig->mpoly) {
+ updated = true;
+ }
+ /* Mesh polys => Final derived polys */
+ else if ((index_array = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) {
+ polys = me_eval->mpoly;
+ totpoly = me_eval->totpoly;
+
+ /* loop over final derived polys */
+ for (i = 0; i < totpoly; i++) {
+ if (index_array[i] != ORIGINDEX_NONE) {
+ /* Copy flags onto the final derived poly from the original mesh poly */
+ mp_orig = me->mpoly + index_array[i];
+ polys[i].flag = mp_orig->flag;
+ }
+ }
+
+ updated = true;
+ }
+ }
+
+ if (updated) {
+ if (flag & ME_HIDE) {
+ BKE_mesh_batch_cache_dirty_tag(me_eval, BKE_MESH_BATCH_DIRTY_ALL);
+ }
+ else {
+ BKE_mesh_batch_cache_dirty_tag(me_eval, BKE_MESH_BATCH_DIRTY_SELECT);
+ }
+
+ DEG_id_tag_update(ob->data, ID_RECALC_SELECT);
+ }
+ else {
+ DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
}
void paintface_hide(bContext *C, Object *ob, const bool unselected)
{
- Mesh *me;
- MPoly *mpoly;
- int a;
+ Mesh *me;
+ MPoly *mpoly;
+ int a;
- me = BKE_mesh_from_object(ob);
- if (me == NULL || me->totpoly == 0) return;
+ me = BKE_mesh_from_object(ob);
+ if (me == NULL || me->totpoly == 0)
+ return;
- mpoly = me->mpoly;
- a = me->totpoly;
- while (a--) {
- if ((mpoly->flag & ME_HIDE) == 0) {
- if (((mpoly->flag & ME_FACE_SEL) == 0) == unselected) {
- mpoly->flag |= ME_HIDE;
- }
- }
+ mpoly = me->mpoly;
+ a = me->totpoly;
+ while (a--) {
+ if ((mpoly->flag & ME_HIDE) == 0) {
+ if (((mpoly->flag & ME_FACE_SEL) == 0) == unselected) {
+ mpoly->flag |= ME_HIDE;
+ }
+ }
- if (mpoly->flag & ME_HIDE) {
- mpoly->flag &= ~ME_FACE_SEL;
- }
+ if (mpoly->flag & ME_HIDE) {
+ mpoly->flag &= ~ME_FACE_SEL;
+ }
- mpoly++;
- }
+ mpoly++;
+ }
- BKE_mesh_flush_hidden_from_polys(me);
+ BKE_mesh_flush_hidden_from_polys(me);
- paintface_flush_flags(C, ob, SELECT | ME_HIDE);
+ paintface_flush_flags(C, ob, SELECT | ME_HIDE);
}
-
void paintface_reveal(bContext *C, Object *ob, const bool select)
{
- Mesh *me;
- MPoly *mpoly;
- int a;
-
- me = BKE_mesh_from_object(ob);
- if (me == NULL || me->totpoly == 0) return;
-
- mpoly = me->mpoly;
- a = me->totpoly;
- while (a--) {
- if (mpoly->flag & ME_HIDE) {
- SET_FLAG_FROM_TEST(mpoly->flag, select, ME_FACE_SEL);
- mpoly->flag &= ~ME_HIDE;
- }
- mpoly++;
- }
-
- BKE_mesh_flush_hidden_from_polys(me);
-
- paintface_flush_flags(C, ob, SELECT | ME_HIDE);
+ Mesh *me;
+ MPoly *mpoly;
+ int a;
+
+ me = BKE_mesh_from_object(ob);
+ if (me == NULL || me->totpoly == 0)
+ return;
+
+ mpoly = me->mpoly;
+ a = me->totpoly;
+ while (a--) {
+ if (mpoly->flag & ME_HIDE) {
+ SET_FLAG_FROM_TEST(mpoly->flag, select, ME_FACE_SEL);
+ mpoly->flag &= ~ME_HIDE;
+ }
+ mpoly++;
+ }
+
+ BKE_mesh_flush_hidden_from_polys(me);
+
+ paintface_flush_flags(C, ob, SELECT | ME_HIDE);
}
/* 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)
{
- MPoly *mp;
- MLoop *ml;
- int a, b;
- bool do_it = true;
- bool mark = false;
-
- 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) {
- /* only put face under cursor in array */
- mp = &me->mpoly[index];
- BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
- BLI_BITMAP_ENABLE(poly_tag, index);
- }
- else {
- /* fill array by selection */
- mp = me->mpoly;
- for (a = 0; a < me->totpoly; a++, mp++) {
- if (mp->flag & ME_HIDE) {
- /* pass */
- }
- else if (mp->flag & ME_FACE_SEL) {
- BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
- BLI_BITMAP_ENABLE(poly_tag, a);
- }
- }
- }
-
- while (do_it) {
- do_it = false;
-
- /* expand selection */
- mp = me->mpoly;
- for (a = 0; a < me->totpoly; a++, mp++) {
- if (mp->flag & ME_HIDE)
- continue;
-
- if (!BLI_BITMAP_TEST(poly_tag, a)) {
- mark = false;
-
- ml = me->mloop + mp->loopstart;
- for (b = 0; b < mp->totloop; b++, ml++) {
- if ((me->medge[ml->e].flag & ME_SEAM) == 0) {
- if (BLI_BITMAP_TEST(edge_tag, ml->e)) {
- mark = true;
- break;
- }
- }
- }
-
- if (mark) {
- BLI_BITMAP_ENABLE(poly_tag, a);
- BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
- do_it = true;
- }
- }
- }
- }
-
- MEM_freeN(edge_tag);
-
- for (a = 0, mp = me->mpoly; a < me->totpoly; a++, mp++) {
- if (BLI_BITMAP_TEST(poly_tag, a)) {
- SET_FLAG_FROM_TEST(mp->flag, select, ME_FACE_SEL);
- }
- }
-
- MEM_freeN(poly_tag);
+ MPoly *mp;
+ MLoop *ml;
+ int a, b;
+ bool do_it = true;
+ bool mark = false;
+
+ 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) {
+ /* only put face under cursor in array */
+ mp = &me->mpoly[index];
+ BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
+ BLI_BITMAP_ENABLE(poly_tag, index);
+ }
+ else {
+ /* fill array by selection */
+ mp = me->mpoly;
+ for (a = 0; a < me->totpoly; a++, mp++) {
+ if (mp->flag & ME_HIDE) {
+ /* pass */
+ }
+ else if (mp->flag & ME_FACE_SEL) {
+ BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
+ BLI_BITMAP_ENABLE(poly_tag, a);
+ }
+ }
+ }
+
+ while (do_it) {
+ do_it = false;
+
+ /* expand selection */
+ mp = me->mpoly;
+ for (a = 0; a < me->totpoly; a++, mp++) {
+ if (mp->flag & ME_HIDE)
+ continue;
+
+ if (!BLI_BITMAP_TEST(poly_tag, a)) {
+ mark = false;
+
+ ml = me->mloop + mp->loopstart;
+ for (b = 0; b < mp->totloop; b++, ml++) {
+ if ((me->medge[ml->e].flag & ME_SEAM) == 0) {
+ if (BLI_BITMAP_TEST(edge_tag, ml->e)) {
+ mark = true;
+ break;
+ }
+ }
+ }
+
+ if (mark) {
+ BLI_BITMAP_ENABLE(poly_tag, a);
+ BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
+ do_it = true;
+ }
+ }
+ }
+ }
+
+ MEM_freeN(edge_tag);
+
+ for (a = 0, mp = me->mpoly; a < me->totpoly; a++, mp++) {
+ if (BLI_BITMAP_TEST(poly_tag, a)) {
+ SET_FLAG_FROM_TEST(mp->flag, select, ME_FACE_SEL);
+ }
+ }
+
+ MEM_freeN(poly_tag);
}
void paintface_select_linked(bContext *C, Object *ob, const int mval[2], const bool select)
{
- Mesh *me;
- unsigned int index = (unsigned int)-1;
+ Mesh *me;
+ unsigned int index = (unsigned int)-1;
- me = BKE_mesh_from_object(ob);
- if (me == NULL || me->totpoly == 0) return;
+ me = BKE_mesh_from_object(ob);
+ if (me == NULL || me->totpoly == 0)
+ return;
- if (mval) {
- if (!ED_mesh_pick_face(C, ob, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
- return;
- }
- }
+ if (mval) {
+ if (!ED_mesh_pick_face(C, ob, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
+ return;
+ }
+ }
- select_linked_tfaces_with_seams(me, index, select);
+ select_linked_tfaces_with_seams(me, index, select);
- paintface_flush_flags(C, ob, SELECT);
+ paintface_flush_flags(C, ob, SELECT);
}
bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool flush_flags)
{
- Mesh *me;
- MPoly *mpoly;
- int a;
-
- me = BKE_mesh_from_object(ob);
- if (me == NULL) {
- return false;
- }
-
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
-
- mpoly = me->mpoly;
- a = me->totpoly;
- while (a--) {
- if ((mpoly->flag & ME_HIDE) == 0 && mpoly->flag & ME_FACE_SEL) {
- action = SEL_DESELECT;
- break;
- }
- mpoly++;
- }
- }
-
- bool changed = false;
-
- mpoly = me->mpoly;
- a = me->totpoly;
- while (a--) {
- if ((mpoly->flag & ME_HIDE) == 0) {
- switch (action) {
- case SEL_SELECT:
- if ((mpoly->flag & ME_FACE_SEL) == 0) {
- mpoly->flag |= ME_FACE_SEL;
- changed = true;
- }
- break;
- case SEL_DESELECT:
- if ((mpoly->flag & ME_FACE_SEL) != 0) {
- mpoly->flag &= ~ME_FACE_SEL;
- changed = true;
- }
- break;
- case SEL_INVERT:
- mpoly->flag ^= ME_FACE_SEL;
- changed = true;
- break;
- }
- }
- mpoly++;
- }
-
- if (changed) {
- if (flush_flags) {
- paintface_flush_flags(C, ob, SELECT);
- }
- }
- return changed;
+ Mesh *me;
+ MPoly *mpoly;
+ int a;
+
+ me = BKE_mesh_from_object(ob);
+ if (me == NULL) {
+ return false;
+ }
+
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+
+ mpoly = me->mpoly;
+ a = me->totpoly;
+ while (a--) {
+ if ((mpoly->flag & ME_HIDE) == 0 && mpoly->flag & ME_FACE_SEL) {
+ action = SEL_DESELECT;
+ break;
+ }
+ mpoly++;
+ }
+ }
+
+ bool changed = false;
+
+ mpoly = me->mpoly;
+ a = me->totpoly;
+ while (a--) {
+ if ((mpoly->flag & ME_HIDE) == 0) {
+ switch (action) {
+ case SEL_SELECT:
+ if ((mpoly->flag & ME_FACE_SEL) == 0) {
+ mpoly->flag |= ME_FACE_SEL;
+ changed = true;
+ }
+ break;
+ case SEL_DESELECT:
+ if ((mpoly->flag & ME_FACE_SEL) != 0) {
+ mpoly->flag &= ~ME_FACE_SEL;
+ changed = true;
+ }
+ break;
+ case SEL_INVERT:
+ mpoly->flag ^= ME_FACE_SEL;
+ changed = true;
+ break;
+ }
+ }
+ mpoly++;
+ }
+
+ if (changed) {
+ if (flush_flags) {
+ paintface_flush_flags(C, ob, SELECT);
+ }
+ }
+ return changed;
}
bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
{
- const Mesh *me;
- const MPoly *mp;
- const MLoop *ml;
- const MVert *mvert;
- int a, b;
- bool ok = false;
- float vec[3], bmat[3][3];
-
- me = BKE_mesh_from_object(ob);
- if (!me || !me->mloopuv) {
- return ok;
- }
-
- copy_m3_m4(bmat, ob->obmat);
-
- mvert = me->mvert;
- mp = me->mpoly;
- for (a = me->totpoly; a > 0; a--, mp++) {
- if (mp->flag & ME_HIDE || !(mp->flag & ME_FACE_SEL))
- continue;
-
- ml = me->mloop + mp->totloop;
- for (b = 0; b < mp->totloop; b++, ml++) {
- mul_v3_m3v3(vec, bmat, mvert[ml->v].co);
- add_v3_v3v3(vec, vec, ob->obmat[3]);
- minmax_v3v3_v3(r_min, r_max, vec);
- }
-
- ok = true;
- }
-
- return ok;
+ const Mesh *me;
+ const MPoly *mp;
+ const MLoop *ml;
+ const MVert *mvert;
+ int a, b;
+ bool ok = false;
+ float vec[3], bmat[3][3];
+
+ me = BKE_mesh_from_object(ob);
+ if (!me || !me->mloopuv) {
+ return ok;
+ }
+
+ copy_m3_m4(bmat, ob->obmat);
+
+ mvert = me->mvert;
+ mp = me->mpoly;
+ for (a = me->totpoly; a > 0; a--, mp++) {
+ if (mp->flag & ME_HIDE || !(mp->flag & ME_FACE_SEL))
+ continue;
+
+ ml = me->mloop + mp->totloop;
+ for (b = 0; b < mp->totloop; b++, ml++) {
+ mul_v3_m3v3(vec, bmat, mvert[ml->v].co);
+ add_v3_v3v3(vec, vec, ob->obmat[3]);
+ minmax_v3v3_v3(r_min, r_max, vec);
+ }
+
+ ok = true;
+ }
+
+ return ok;
}
-bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], bool extend, bool deselect, bool toggle)
+bool paintface_mouse_select(
+ struct bContext *C, Object *ob, const int mval[2], bool extend, bool deselect, bool toggle)
{
- Mesh *me;
- MPoly *mpoly_sel;
- uint index;
-
- /* Get the face under the cursor */
- me = BKE_mesh_from_object(ob);
-
- if (!ED_mesh_pick_face(C, ob, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
- return false;
- }
-
- if (index >= me->totpoly) {
- return false;
- }
-
- mpoly_sel = me->mpoly + index;
- if (mpoly_sel->flag & ME_HIDE) return false;
-
- /* clear flags */
- if (!extend && !deselect && !toggle) {
- paintface_deselect_all_visible(C, ob, SEL_DESELECT, false);
- }
-
- me->act_face = (int)index;
-
- if (extend) {
- mpoly_sel->flag |= ME_FACE_SEL;
- }
- else if (deselect) {
- mpoly_sel->flag &= ~ME_FACE_SEL;
- }
- else if (toggle) {
- if (mpoly_sel->flag & ME_FACE_SEL)
- mpoly_sel->flag &= ~ME_FACE_SEL;
- else
- mpoly_sel->flag |= ME_FACE_SEL;
- }
- else {
- mpoly_sel->flag |= ME_FACE_SEL;
- }
-
- /* image window redraw */
-
- paintface_flush_flags(C, ob, SELECT);
- ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
- return true;
+ Mesh *me;
+ MPoly *mpoly_sel;
+ uint index;
+
+ /* Get the face under the cursor */
+ me = BKE_mesh_from_object(ob);
+
+ if (!ED_mesh_pick_face(C, ob, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
+ return false;
+ }
+
+ if (index >= me->totpoly) {
+ return false;
+ }
+
+ mpoly_sel = me->mpoly + index;
+ if (mpoly_sel->flag & ME_HIDE)
+ return false;
+
+ /* clear flags */
+ if (!extend && !deselect && !toggle) {
+ paintface_deselect_all_visible(C, ob, SEL_DESELECT, false);
+ }
+
+ me->act_face = (int)index;
+
+ if (extend) {
+ mpoly_sel->flag |= ME_FACE_SEL;
+ }
+ else if (deselect) {
+ mpoly_sel->flag &= ~ME_FACE_SEL;
+ }
+ else if (toggle) {
+ if (mpoly_sel->flag & ME_FACE_SEL)
+ mpoly_sel->flag &= ~ME_FACE_SEL;
+ else
+ mpoly_sel->flag |= ME_FACE_SEL;
+ }
+ else {
+ mpoly_sel->flag |= ME_FACE_SEL;
+ }
+
+ /* image window redraw */
+
+ paintface_flush_flags(C, ob, SELECT);
+ ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
+ return true;
}
bool do_paintface_box_select(ViewContext *vc, const rcti *rect, int sel_op)
{
- Object *ob = vc->obact;
- Mesh *me;
-
- me = BKE_mesh_from_object(ob);
- if ((me == NULL) || (me->totpoly == 0)) {
- return false;
- }
-
- bool changed = false;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- changed |= paintface_deselect_all_visible(vc->C, vc->obact, SEL_DESELECT, false);
- }
-
- if (BLI_rcti_is_empty(rect)) {
- /* pass */
- }
- else {
- MPoly *mpoly;
- uint *rt;
- int a, index;
-
- char *selar = MEM_callocN(me->totpoly + 1, "selar");
-
- uint buf_len;
- uint *buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len);
-
- rt = buf;
-
- a = buf_len;
- while (a--) {
- if (*rt) {
- index = *rt;
- if (index <= me->totpoly) {
- selar[index] = 1;
- }
- }
- rt++;
- }
-
- mpoly = me->mpoly;
- for (a = 1; a <= me->totpoly; a++, mpoly++) {
- if ((mpoly->flag & ME_HIDE) == 0) {
- const bool is_select = mpoly->flag & ME_FACE_SEL;
- const bool is_inside = (selar[a] != 0);
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(mpoly->flag, sel_op_result, ME_FACE_SEL);
- changed = true;
- }
- }
- }
-
- MEM_freeN(buf);
- MEM_freeN(selar);
+ Object *ob = vc->obact;
+ Mesh *me;
+
+ me = BKE_mesh_from_object(ob);
+ if ((me == NULL) || (me->totpoly == 0)) {
+ return false;
+ }
+
+ bool changed = false;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ changed |= paintface_deselect_all_visible(vc->C, vc->obact, SEL_DESELECT, false);
+ }
+
+ if (BLI_rcti_is_empty(rect)) {
+ /* pass */
+ }
+ else {
+ MPoly *mpoly;
+ uint *rt;
+ int a, index;
+
+ char *selar = MEM_callocN(me->totpoly + 1, "selar");
+
+ uint buf_len;
+ uint *buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len);
+
+ rt = buf;
+
+ a = buf_len;
+ while (a--) {
+ if (*rt) {
+ index = *rt;
+ if (index <= me->totpoly) {
+ selar[index] = 1;
+ }
+ }
+ rt++;
+ }
+
+ mpoly = me->mpoly;
+ for (a = 1; a <= me->totpoly; a++, mpoly++) {
+ if ((mpoly->flag & ME_HIDE) == 0) {
+ const bool is_select = mpoly->flag & ME_FACE_SEL;
+ const bool is_inside = (selar[a] != 0);
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ SET_FLAG_FROM_TEST(mpoly->flag, sel_op_result, ME_FACE_SEL);
+ changed = true;
+ }
+ }
+ }
+
+ MEM_freeN(buf);
+ MEM_freeN(selar);
#ifdef __APPLE__
- glReadBuffer(GL_BACK);
+ glReadBuffer(GL_BACK);
#endif
- }
+ }
- if (changed) {
- paintface_flush_flags(vc->C, vc->obact, SELECT);
- }
- return changed;
+ if (changed) {
+ paintface_flush_flags(vc->C, vc->obact, SELECT);
+ }
+ return changed;
}
-
/* (similar to void paintface_flush_flags(Object *ob))
* copy the vertex flags, most importantly selection from the mesh to the final derived mesh,
* use in object mode when selecting vertices (while painting) */
void paintvert_flush_flags(Object *ob)
{
- Mesh *me = BKE_mesh_from_object(ob);
- Mesh *me_eval = ob->runtime.mesh_eval;
- MVert *mvert_eval, *mv;
- const int *index_array = NULL;
- int totvert;
- int i;
-
- if (me == NULL)
- return;
-
- /* we could call this directly in all areas that change selection,
- * since this could become slow for realtime updates (circle-select for eg) */
- BKE_mesh_flush_select_from_verts(me);
-
- if (me_eval == NULL)
- return;
-
- index_array = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
-
- mvert_eval = me_eval->mvert;
- totvert = me_eval->totvert;
-
- mv = mvert_eval;
-
- if (index_array) {
- int orig_index;
- for (i = 0; i < totvert; i++, mv++) {
- orig_index = index_array[i];
- if (orig_index != ORIGINDEX_NONE) {
- mv->flag = me->mvert[index_array[i]].flag;
- }
- }
- }
- else {
- for (i = 0; i < totvert; i++, mv++) {
- mv->flag = me->mvert[i].flag;
- }
- }
-
- BKE_mesh_batch_cache_dirty_tag(me, BKE_MESH_BATCH_DIRTY_ALL);
+ Mesh *me = BKE_mesh_from_object(ob);
+ Mesh *me_eval = ob->runtime.mesh_eval;
+ MVert *mvert_eval, *mv;
+ const int *index_array = NULL;
+ int totvert;
+ int i;
+
+ if (me == NULL)
+ return;
+
+ /* we could call this directly in all areas that change selection,
+ * since this could become slow for realtime updates (circle-select for eg) */
+ BKE_mesh_flush_select_from_verts(me);
+
+ if (me_eval == NULL)
+ return;
+
+ index_array = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
+
+ mvert_eval = me_eval->mvert;
+ totvert = me_eval->totvert;
+
+ mv = mvert_eval;
+
+ if (index_array) {
+ int orig_index;
+ for (i = 0; i < totvert; i++, mv++) {
+ orig_index = index_array[i];
+ if (orig_index != ORIGINDEX_NONE) {
+ mv->flag = me->mvert[index_array[i]].flag;
+ }
+ }
+ }
+ else {
+ for (i = 0; i < totvert; i++, mv++) {
+ mv->flag = me->mvert[i].flag;
+ }
+ }
+
+ BKE_mesh_batch_cache_dirty_tag(me, BKE_MESH_BATCH_DIRTY_ALL);
}
void paintvert_tag_select_update(struct bContext *C, struct Object *ob)
{
- DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
+ DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
+ 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 */
bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
{
- Mesh *me;
- MVert *mvert;
- int a;
-
- me = BKE_mesh_from_object(ob);
- if (me == NULL) {
- return false;
- }
-
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
-
- mvert = me->mvert;
- a = me->totvert;
- while (a--) {
- if ((mvert->flag & ME_HIDE) == 0 && mvert->flag & SELECT) {
- action = SEL_DESELECT;
- break;
- }
- mvert++;
- }
- }
-
- bool changed = false;
- mvert = me->mvert;
- a = me->totvert;
- while (a--) {
- if ((mvert->flag & ME_HIDE) == 0) {
- switch (action) {
- case SEL_SELECT:
- if ((mvert->flag & SELECT) == 0) {
- mvert->flag |= SELECT;
- changed = true;
- }
- break;
- case SEL_DESELECT:
- if ((mvert->flag & SELECT) != 0) {
- mvert->flag &= ~SELECT;
- changed = true;
- }
- break;
- case SEL_INVERT:
- mvert->flag ^= SELECT;
- changed = true;
- break;
- }
- }
- mvert++;
- }
-
- if (changed) {
- /* handle mselect */
- if (action == SEL_SELECT) {
- /* pass */
- }
- else if (ELEM(action, SEL_DESELECT, SEL_INVERT)) {
- BKE_mesh_mselect_clear(me);
- }
- else {
- BKE_mesh_mselect_validate(me);
- }
-
- if (flush_flags) {
- paintvert_flush_flags(ob);
- }
- }
- return changed;
+ Mesh *me;
+ MVert *mvert;
+ int a;
+
+ me = BKE_mesh_from_object(ob);
+ if (me == NULL) {
+ return false;
+ }
+
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+
+ mvert = me->mvert;
+ a = me->totvert;
+ while (a--) {
+ if ((mvert->flag & ME_HIDE) == 0 && mvert->flag & SELECT) {
+ action = SEL_DESELECT;
+ break;
+ }
+ mvert++;
+ }
+ }
+
+ bool changed = false;
+ mvert = me->mvert;
+ a = me->totvert;
+ while (a--) {
+ if ((mvert->flag & ME_HIDE) == 0) {
+ switch (action) {
+ case SEL_SELECT:
+ if ((mvert->flag & SELECT) == 0) {
+ mvert->flag |= SELECT;
+ changed = true;
+ }
+ break;
+ case SEL_DESELECT:
+ if ((mvert->flag & SELECT) != 0) {
+ mvert->flag &= ~SELECT;
+ changed = true;
+ }
+ break;
+ case SEL_INVERT:
+ mvert->flag ^= SELECT;
+ changed = true;
+ break;
+ }
+ }
+ mvert++;
+ }
+
+ if (changed) {
+ /* handle mselect */
+ if (action == SEL_SELECT) {
+ /* pass */
+ }
+ else if (ELEM(action, SEL_DESELECT, SEL_INVERT)) {
+ BKE_mesh_mselect_clear(me);
+ }
+ else {
+ BKE_mesh_mselect_validate(me);
+ }
+
+ if (flush_flags) {
+ paintvert_flush_flags(ob);
+ }
+ }
+ return changed;
}
void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
{
- Mesh *me = BKE_mesh_from_object(ob);
- MVert *mv;
- MDeformVert *dv;
- int a, tot;
-
- if (me == NULL || me->dvert == NULL) {
- return;
- }
-
- if (!extend) {
- paintvert_deselect_all_visible(ob, SEL_DESELECT, false);
- }
-
- dv = me->dvert;
- tot = me->totvert;
-
- for (a = 0, mv = me->mvert; a < tot; a++, mv++, dv++) {
- if ((mv->flag & ME_HIDE) == 0) {
- if (dv->dw == NULL) {
- /* if null weight then not grouped */
- mv->flag |= SELECT;
- }
- }
- }
-
- if (flush_flags) {
- paintvert_flush_flags(ob);
- }
+ Mesh *me = BKE_mesh_from_object(ob);
+ MVert *mv;
+ MDeformVert *dv;
+ int a, tot;
+
+ if (me == NULL || me->dvert == NULL) {
+ return;
+ }
+
+ if (!extend) {
+ paintvert_deselect_all_visible(ob, SEL_DESELECT, false);
+ }
+
+ dv = me->dvert;
+ tot = me->totvert;
+
+ for (a = 0, mv = me->mvert; a < tot; a++, mv++, dv++) {
+ if ((mv->flag & ME_HIDE) == 0) {
+ if (dv->dw == NULL) {
+ /* if null weight then not grouped */
+ mv->flag |= SELECT;
+ }
+ }
+ }
+
+ if (flush_flags) {
+ paintvert_flush_flags(ob);
+ }
}
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index aca8fac8bf7..815f51a4772 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -44,595 +44,646 @@
#include "ED_object.h"
#include "ED_uvedit.h"
-#include "mesh_intern.h" /* own include */
-
+#include "mesh_intern.h" /* own include */
#define MESH_ADD_VERTS_MAXI 10000000
-
/* ********* add primitive operators ************* */
typedef struct MakePrimitiveData {
- float mat[4][4];
- bool was_editmode;
+ float mat[4][4];
+ bool was_editmode;
} MakePrimitiveData;
-static Object *make_prim_init(
- bContext *C, const char *idname,
- const float loc[3], const float rot[3], ushort local_view_bits,
- MakePrimitiveData *r_creation_data)
+static Object *make_prim_init(bContext *C,
+ const char *idname,
+ const float loc[3],
+ const float rot[3],
+ ushort local_view_bits,
+ MakePrimitiveData *r_creation_data)
{
- struct Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
+ struct Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
- r_creation_data->was_editmode = false;
- if (obedit == NULL || obedit->type != OB_MESH) {
- obedit = ED_object_add_type(C, OB_MESH, idname, loc, rot, false, local_view_bits);
- ED_object_editmode_enter_ex(bmain, scene, obedit, 0);
+ r_creation_data->was_editmode = false;
+ if (obedit == NULL || obedit->type != OB_MESH) {
+ obedit = ED_object_add_type(C, OB_MESH, idname, loc, rot, false, local_view_bits);
+ ED_object_editmode_enter_ex(bmain, scene, obedit, 0);
- r_creation_data->was_editmode = true;
- }
+ r_creation_data->was_editmode = true;
+ }
- ED_object_new_primitive_matrix(C, obedit, loc, rot, r_creation_data->mat);
+ ED_object_new_primitive_matrix(C, obedit, loc, rot, r_creation_data->mat);
- return obedit;
+ return obedit;
}
-static void make_prim_finish(bContext *C, Object *obedit, const MakePrimitiveData *creation_data, int enter_editmode)
+static void make_prim_finish(bContext *C,
+ Object *obedit,
+ const MakePrimitiveData *creation_data,
+ int enter_editmode)
{
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- const bool exit_editmode = ((creation_data->was_editmode == true) && (enter_editmode == false));
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ const bool exit_editmode = ((creation_data->was_editmode == true) && (enter_editmode == false));
- /* Primitive has all verts selected, use vert select flush
- * to push this up to edges & faces. */
- EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX);
+ /* Primitive has all verts selected, use vert select flush
+ * to push this up to edges & faces. */
+ EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX);
- /* only recalc editmode tessface if we are staying in editmode */
- EDBM_update_generic(em, !exit_editmode, true);
+ /* only recalc editmode tessface if we are staying in editmode */
+ EDBM_update_generic(em, !exit_editmode, true);
- /* userdef */
- if (exit_editmode) {
- ED_object_editmode_exit(C, EM_FREEDATA);
- }
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
+ /* userdef */
+ if (exit_editmode) {
+ ED_object_editmode_exit(C, EM_FREEDATA);
+ }
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
}
static int add_primitive_plane_exec(bContext *C, wmOperator *op)
{
- MakePrimitiveData creation_data;
- Object *obedit;
- BMEditMesh *em;
- float loc[3], rot[3];
- bool enter_editmode;
- ushort local_view_bits;
- const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
-
- WM_operator_view3d_unit_defaults(C, op);
- ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
- obedit = make_prim_init(
- C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Plane"),
- loc, rot, local_view_bits, &creation_data);
- em = BKE_editmesh_from_object(obedit);
-
- if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
- }
-
- if (!EDBM_op_call_and_selectf(
- em, op, "verts.out", false,
- "create_grid x_segments=%i y_segments=%i size=%f matrix=%m4 calc_uvs=%b",
- 1, 1, RNA_float_get(op->ptr, "size") / 2.0f, creation_data.mat, calc_uvs))
- {
- return OPERATOR_CANCELLED;
- }
-
- make_prim_finish(C, obedit, &creation_data, enter_editmode);
-
- return OPERATOR_FINISHED;
+ MakePrimitiveData creation_data;
+ Object *obedit;
+ BMEditMesh *em;
+ float loc[3], rot[3];
+ bool enter_editmode;
+ ushort local_view_bits;
+ const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
+
+ WM_operator_view3d_unit_defaults(C, op);
+ ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
+ obedit = make_prim_init(
+ C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Plane"), loc, rot, local_view_bits, &creation_data);
+ em = BKE_editmesh_from_object(obedit);
+
+ if (calc_uvs) {
+ ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ }
+
+ if (!EDBM_op_call_and_selectf(
+ em,
+ op,
+ "verts.out",
+ false,
+ "create_grid x_segments=%i y_segments=%i size=%f matrix=%m4 calc_uvs=%b",
+ 1,
+ 1,
+ RNA_float_get(op->ptr, "size") / 2.0f,
+ creation_data.mat,
+ calc_uvs)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ make_prim_finish(C, obedit, &creation_data, enter_editmode);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_primitive_plane_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Plane";
- ot->description = "Construct a filled planar mesh with 4 vertices";
- ot->idname = "MESH_OT_primitive_plane_add";
+ /* identifiers */
+ ot->name = "Add Plane";
+ ot->description = "Construct a filled planar mesh with 4 vertices";
+ ot->idname = "MESH_OT_primitive_plane_add";
- /* api callbacks */
- ot->exec = add_primitive_plane_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = add_primitive_plane_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_unit_props_size(ot);
- ED_object_add_mesh_props(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_size(ot);
+ ED_object_add_mesh_props(ot);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_cube_exec(bContext *C, wmOperator *op)
{
- MakePrimitiveData creation_data;
- Object *obedit;
- BMEditMesh *em;
- float loc[3], rot[3];
- bool enter_editmode;
- ushort local_view_bits;
- const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
-
- WM_operator_view3d_unit_defaults(C, op);
- ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
- obedit = make_prim_init(
- C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cube"),
- loc, rot, local_view_bits, &creation_data);
- em = BKE_editmesh_from_object(obedit);
-
- if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
- }
-
- if (!EDBM_op_call_and_selectf(
- em, op, "verts.out", false,
- "create_cube matrix=%m4 size=%f calc_uvs=%b",
- creation_data.mat, RNA_float_get(op->ptr, "size"), calc_uvs))
- {
- return OPERATOR_CANCELLED;
- }
-
- /* BMESH_TODO make plane side this: M_SQRT2 - plane (diameter of 1.41 makes it unit size) */
- make_prim_finish(C, obedit, &creation_data, enter_editmode);
-
- return OPERATOR_FINISHED;
+ MakePrimitiveData creation_data;
+ Object *obedit;
+ BMEditMesh *em;
+ float loc[3], rot[3];
+ bool enter_editmode;
+ ushort local_view_bits;
+ const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
+
+ WM_operator_view3d_unit_defaults(C, op);
+ ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
+ obedit = make_prim_init(
+ C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cube"), loc, rot, local_view_bits, &creation_data);
+ em = BKE_editmesh_from_object(obedit);
+
+ if (calc_uvs) {
+ ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ }
+
+ if (!EDBM_op_call_and_selectf(em,
+ op,
+ "verts.out",
+ false,
+ "create_cube matrix=%m4 size=%f calc_uvs=%b",
+ creation_data.mat,
+ RNA_float_get(op->ptr, "size"),
+ calc_uvs)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* BMESH_TODO make plane side this: M_SQRT2 - plane (diameter of 1.41 makes it unit size) */
+ make_prim_finish(C, obedit, &creation_data, enter_editmode);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_primitive_cube_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Cube";
- ot->description = "Construct a cube mesh";
- ot->idname = "MESH_OT_primitive_cube_add";
+ /* identifiers */
+ ot->name = "Add Cube";
+ ot->description = "Construct a cube mesh";
+ ot->idname = "MESH_OT_primitive_cube_add";
- /* api callbacks */
- ot->exec = add_primitive_cube_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = add_primitive_cube_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_unit_props_size(ot);
- ED_object_add_mesh_props(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_size(ot);
+ ED_object_add_mesh_props(ot);
+ ED_object_add_generic_props(ot, true);
}
static const EnumPropertyItem fill_type_items[] = {
- {0, "NOTHING", 0, "Nothing", "Don't fill at all"},
- {1, "NGON", 0, "Ngon", "Use ngons"},
- {2, "TRIFAN", 0, "Triangle Fan", "Use triangle fans"},
- {0, NULL, 0, NULL, NULL},
+ {0, "NOTHING", 0, "Nothing", "Don't fill at all"},
+ {1, "NGON", 0, "Ngon", "Use ngons"},
+ {2, "TRIFAN", 0, "Triangle Fan", "Use triangle fans"},
+ {0, NULL, 0, NULL, NULL},
};
static int add_primitive_circle_exec(bContext *C, wmOperator *op)
{
- MakePrimitiveData creation_data;
- Object *obedit;
- BMEditMesh *em;
- float loc[3], rot[3];
- bool enter_editmode;
- ushort local_view_bits;
- int cap_end, cap_tri;
- const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
-
- cap_end = RNA_enum_get(op->ptr, "fill_type");
- cap_tri = (cap_end == 2);
-
- WM_operator_view3d_unit_defaults(C, op);
- ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
- obedit = make_prim_init(
- C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Circle"),
- loc, rot, local_view_bits, &creation_data);
- em = BKE_editmesh_from_object(obedit);
-
- if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
- }
-
- if (!EDBM_op_call_and_selectf(
- em, op, "verts.out", false,
- "create_circle segments=%i radius=%f cap_ends=%b cap_tris=%b matrix=%m4 calc_uvs=%b",
- RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius"),
- cap_end, cap_tri, creation_data.mat, calc_uvs))
- {
- return OPERATOR_CANCELLED;
- }
-
- make_prim_finish(C, obedit, &creation_data, enter_editmode);
-
- return OPERATOR_FINISHED;
+ MakePrimitiveData creation_data;
+ Object *obedit;
+ BMEditMesh *em;
+ float loc[3], rot[3];
+ bool enter_editmode;
+ ushort local_view_bits;
+ int cap_end, cap_tri;
+ const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
+
+ cap_end = RNA_enum_get(op->ptr, "fill_type");
+ cap_tri = (cap_end == 2);
+
+ WM_operator_view3d_unit_defaults(C, op);
+ ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
+ obedit = make_prim_init(
+ C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Circle"), loc, rot, local_view_bits, &creation_data);
+ em = BKE_editmesh_from_object(obedit);
+
+ if (calc_uvs) {
+ ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ }
+
+ if (!EDBM_op_call_and_selectf(
+ em,
+ op,
+ "verts.out",
+ false,
+ "create_circle segments=%i radius=%f cap_ends=%b cap_tris=%b matrix=%m4 calc_uvs=%b",
+ RNA_int_get(op->ptr, "vertices"),
+ RNA_float_get(op->ptr, "radius"),
+ cap_end,
+ cap_tri,
+ creation_data.mat,
+ calc_uvs)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ make_prim_finish(C, obedit, &creation_data, enter_editmode);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_primitive_circle_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Circle";
- ot->description = "Construct a circle mesh";
- ot->idname = "MESH_OT_primitive_circle_add";
+ /* identifiers */
+ ot->name = "Add Circle";
+ ot->description = "Construct a circle mesh";
+ ot->idname = "MESH_OT_primitive_circle_add";
- /* api callbacks */
- ot->exec = add_primitive_circle_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = add_primitive_circle_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_int(ot->srna, "vertices", 32, 3, MESH_ADD_VERTS_MAXI, "Vertices", "", 3, 500);
- ED_object_add_unit_props_radius(ot);
- RNA_def_enum(ot->srna, "fill_type", fill_type_items, 0, "Fill Type", "");
+ /* props */
+ RNA_def_int(ot->srna, "vertices", 32, 3, MESH_ADD_VERTS_MAXI, "Vertices", "", 3, 500);
+ ED_object_add_unit_props_radius(ot);
+ RNA_def_enum(ot->srna, "fill_type", fill_type_items, 0, "Fill Type", "");
- ED_object_add_mesh_props(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_mesh_props(ot);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
{
- MakePrimitiveData creation_data;
- Object *obedit;
- BMEditMesh *em;
- float loc[3], rot[3];
- bool enter_editmode;
- ushort local_view_bits;
- const int end_fill_type = RNA_enum_get(op->ptr, "end_fill_type");
- const bool cap_end = (end_fill_type != 0);
- const bool cap_tri = (end_fill_type == 2);
- const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
-
- WM_operator_view3d_unit_defaults(C, op);
- ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
- obedit = make_prim_init(
- C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cylinder"),
- loc, rot, local_view_bits, &creation_data);
- em = BKE_editmesh_from_object(obedit);
-
- if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
- }
-
- if (!EDBM_op_call_and_selectf(
- em, op, "verts.out", false,
- "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f matrix=%m4 calc_uvs=%b",
- RNA_int_get(op->ptr, "vertices"),
- RNA_float_get(op->ptr, "radius"),
- RNA_float_get(op->ptr, "radius"),
- cap_end, cap_tri,
- RNA_float_get(op->ptr, "depth"), creation_data.mat, calc_uvs))
- {
- return OPERATOR_CANCELLED;
- }
-
- make_prim_finish(C, obedit, &creation_data, enter_editmode);
-
- return OPERATOR_FINISHED;
+ MakePrimitiveData creation_data;
+ Object *obedit;
+ BMEditMesh *em;
+ float loc[3], rot[3];
+ bool enter_editmode;
+ ushort local_view_bits;
+ const int end_fill_type = RNA_enum_get(op->ptr, "end_fill_type");
+ const bool cap_end = (end_fill_type != 0);
+ const bool cap_tri = (end_fill_type == 2);
+ const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
+
+ WM_operator_view3d_unit_defaults(C, op);
+ ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
+ obedit = make_prim_init(C,
+ CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cylinder"),
+ loc,
+ rot,
+ local_view_bits,
+ &creation_data);
+ em = BKE_editmesh_from_object(obedit);
+
+ if (calc_uvs) {
+ ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ }
+
+ if (!EDBM_op_call_and_selectf(em,
+ op,
+ "verts.out",
+ false,
+ "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b "
+ "cap_tris=%b depth=%f matrix=%m4 calc_uvs=%b",
+ RNA_int_get(op->ptr, "vertices"),
+ RNA_float_get(op->ptr, "radius"),
+ RNA_float_get(op->ptr, "radius"),
+ cap_end,
+ cap_tri,
+ RNA_float_get(op->ptr, "depth"),
+ creation_data.mat,
+ calc_uvs)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ make_prim_finish(C, obedit, &creation_data, enter_editmode);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_primitive_cylinder_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Cylinder";
- ot->description = "Construct a cylinder mesh";
- ot->idname = "MESH_OT_primitive_cylinder_add";
-
- /* api callbacks */
- ot->exec = add_primitive_cylinder_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- RNA_def_int(ot->srna, "vertices", 32, 3, MESH_ADD_VERTS_MAXI, "Vertices", "", 3, 500);
- ED_object_add_unit_props_radius(ot);
- RNA_def_float_distance(ot->srna, "depth", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Depth", "", 0.001, 100.00);
- RNA_def_enum(ot->srna, "end_fill_type", fill_type_items, 1, "Cap Fill Type", "");
-
- ED_object_add_mesh_props(ot);
- ED_object_add_generic_props(ot, true);
+ /* identifiers */
+ ot->name = "Add Cylinder";
+ ot->description = "Construct a cylinder mesh";
+ ot->idname = "MESH_OT_primitive_cylinder_add";
+
+ /* api callbacks */
+ ot->exec = add_primitive_cylinder_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "vertices", 32, 3, MESH_ADD_VERTS_MAXI, "Vertices", "", 3, 500);
+ ED_object_add_unit_props_radius(ot);
+ RNA_def_float_distance(
+ ot->srna, "depth", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Depth", "", 0.001, 100.00);
+ RNA_def_enum(ot->srna, "end_fill_type", fill_type_items, 1, "Cap Fill Type", "");
+
+ ED_object_add_mesh_props(ot);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_cone_exec(bContext *C, wmOperator *op)
{
- MakePrimitiveData creation_data;
- Object *obedit;
- BMEditMesh *em;
- float loc[3], rot[3];
- bool enter_editmode;
- ushort local_view_bits;
- const int end_fill_type = RNA_enum_get(op->ptr, "end_fill_type");
- const bool cap_end = (end_fill_type != 0);
- const bool cap_tri = (end_fill_type == 2);
- const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
-
- WM_operator_view3d_unit_defaults(C, op);
- ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
- obedit = make_prim_init(
- C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cone"),
- loc, rot, local_view_bits, &creation_data);
- em = BKE_editmesh_from_object(obedit);
-
- if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
- }
-
- if (!EDBM_op_call_and_selectf(
- em, op, "verts.out", false,
- "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f matrix=%m4 calc_uvs=%b",
- RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius1"),
- RNA_float_get(op->ptr, "radius2"), cap_end, cap_tri, RNA_float_get(op->ptr, "depth"),
- creation_data.mat, calc_uvs))
- {
- return OPERATOR_CANCELLED;
- }
-
- make_prim_finish(C, obedit, &creation_data, enter_editmode);
-
- return OPERATOR_FINISHED;
+ MakePrimitiveData creation_data;
+ Object *obedit;
+ BMEditMesh *em;
+ float loc[3], rot[3];
+ bool enter_editmode;
+ ushort local_view_bits;
+ const int end_fill_type = RNA_enum_get(op->ptr, "end_fill_type");
+ const bool cap_end = (end_fill_type != 0);
+ const bool cap_tri = (end_fill_type == 2);
+ const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
+
+ WM_operator_view3d_unit_defaults(C, op);
+ ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
+ obedit = make_prim_init(
+ C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cone"), loc, rot, local_view_bits, &creation_data);
+ em = BKE_editmesh_from_object(obedit);
+
+ if (calc_uvs) {
+ ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ }
+
+ if (!EDBM_op_call_and_selectf(em,
+ op,
+ "verts.out",
+ false,
+ "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b "
+ "cap_tris=%b depth=%f matrix=%m4 calc_uvs=%b",
+ RNA_int_get(op->ptr, "vertices"),
+ RNA_float_get(op->ptr, "radius1"),
+ RNA_float_get(op->ptr, "radius2"),
+ cap_end,
+ cap_tri,
+ RNA_float_get(op->ptr, "depth"),
+ creation_data.mat,
+ calc_uvs)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ make_prim_finish(C, obedit, &creation_data, enter_editmode);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_primitive_cone_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Cone";
- ot->description = "Construct a conic mesh";
- ot->idname = "MESH_OT_primitive_cone_add";
-
- /* api callbacks */
- ot->exec = add_primitive_cone_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- RNA_def_int(ot->srna, "vertices", 32, 3, MESH_ADD_VERTS_MAXI, "Vertices", "", 3, 500);
- RNA_def_float_distance(ot->srna, "radius1", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 1", "", 0.001, 100.00);
- RNA_def_float_distance(ot->srna, "radius2", 0.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 2", "", 0.0, 100.00);
- RNA_def_float_distance(ot->srna, "depth", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Depth", "", 0.001, 100.00);
- RNA_def_enum(ot->srna, "end_fill_type", fill_type_items, 1, "Base Fill Type", "");
-
- ED_object_add_mesh_props(ot);
- ED_object_add_generic_props(ot, true);
+ /* identifiers */
+ ot->name = "Add Cone";
+ ot->description = "Construct a conic mesh";
+ ot->idname = "MESH_OT_primitive_cone_add";
+
+ /* api callbacks */
+ ot->exec = add_primitive_cone_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "vertices", 32, 3, MESH_ADD_VERTS_MAXI, "Vertices", "", 3, 500);
+ RNA_def_float_distance(
+ ot->srna, "radius1", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 1", "", 0.001, 100.00);
+ RNA_def_float_distance(
+ ot->srna, "radius2", 0.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 2", "", 0.0, 100.00);
+ RNA_def_float_distance(
+ ot->srna, "depth", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Depth", "", 0.001, 100.00);
+ RNA_def_enum(ot->srna, "end_fill_type", fill_type_items, 1, "Base Fill Type", "");
+
+ ED_object_add_mesh_props(ot);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_grid_exec(bContext *C, wmOperator *op)
{
- MakePrimitiveData creation_data;
- Object *obedit;
- BMEditMesh *em;
- float loc[3], rot[3];
- bool enter_editmode;
- ushort local_view_bits;
- const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
-
- WM_operator_view3d_unit_defaults(C, op);
- ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
- obedit = make_prim_init(
- C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Grid"),
- loc, rot, local_view_bits, &creation_data);
- em = BKE_editmesh_from_object(obedit);
-
- if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
- }
-
- if (!EDBM_op_call_and_selectf(
- em, op, "verts.out", false,
- "create_grid x_segments=%i y_segments=%i size=%f matrix=%m4 calc_uvs=%b",
- RNA_int_get(op->ptr, "x_subdivisions"),
- RNA_int_get(op->ptr, "y_subdivisions"),
- RNA_float_get(op->ptr, "size") / 2.0f, creation_data.mat, calc_uvs))
- {
- return OPERATOR_CANCELLED;
- }
-
- make_prim_finish(C, obedit, &creation_data, enter_editmode);
-
- return OPERATOR_FINISHED;
+ MakePrimitiveData creation_data;
+ Object *obedit;
+ BMEditMesh *em;
+ float loc[3], rot[3];
+ bool enter_editmode;
+ ushort local_view_bits;
+ const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
+
+ WM_operator_view3d_unit_defaults(C, op);
+ ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
+ obedit = make_prim_init(
+ C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Grid"), loc, rot, local_view_bits, &creation_data);
+ em = BKE_editmesh_from_object(obedit);
+
+ if (calc_uvs) {
+ ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ }
+
+ if (!EDBM_op_call_and_selectf(
+ em,
+ op,
+ "verts.out",
+ false,
+ "create_grid x_segments=%i y_segments=%i size=%f matrix=%m4 calc_uvs=%b",
+ RNA_int_get(op->ptr, "x_subdivisions"),
+ RNA_int_get(op->ptr, "y_subdivisions"),
+ RNA_float_get(op->ptr, "size") / 2.0f,
+ creation_data.mat,
+ calc_uvs)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ make_prim_finish(C, obedit, &creation_data, enter_editmode);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_primitive_grid_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Grid";
- ot->description = "Construct a grid mesh";
- ot->idname = "MESH_OT_primitive_grid_add";
-
- /* api callbacks */
- ot->exec = add_primitive_grid_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- /* Note that if you use MESH_ADD_VERTS_MAXI for both x and y at the same time you will still reach
- * impossible values (10^12 vertices or so...). */
- RNA_def_int(ot->srna, "x_subdivisions", 10, 2, MESH_ADD_VERTS_MAXI, "X Subdivisions", "", 2, 1000);
- RNA_def_int(ot->srna, "y_subdivisions", 10, 2, MESH_ADD_VERTS_MAXI, "Y Subdivisions", "", 2, 1000);
-
- ED_object_add_unit_props_size(ot);
- ED_object_add_mesh_props(ot);
- ED_object_add_generic_props(ot, true);
+ /* identifiers */
+ ot->name = "Add Grid";
+ ot->description = "Construct a grid mesh";
+ ot->idname = "MESH_OT_primitive_grid_add";
+
+ /* api callbacks */
+ ot->exec = add_primitive_grid_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ /* Note that if you use MESH_ADD_VERTS_MAXI for both x and y at the same time you will still reach
+ * impossible values (10^12 vertices or so...). */
+ RNA_def_int(
+ ot->srna, "x_subdivisions", 10, 2, MESH_ADD_VERTS_MAXI, "X Subdivisions", "", 2, 1000);
+ RNA_def_int(
+ ot->srna, "y_subdivisions", 10, 2, MESH_ADD_VERTS_MAXI, "Y Subdivisions", "", 2, 1000);
+
+ ED_object_add_unit_props_size(ot);
+ ED_object_add_mesh_props(ot);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
{
- MakePrimitiveData creation_data;
- Object *obedit;
- BMEditMesh *em;
- float loc[3], rot[3];
- float dia;
- bool enter_editmode;
- ushort local_view_bits;
- const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
-
- WM_operator_view3d_unit_defaults(C, op);
- ED_object_add_generic_get_opts(C, op, 'Y', loc, rot, &enter_editmode, &local_view_bits, NULL);
-
- obedit = make_prim_init(
- C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Suzanne"),
- loc, rot, local_view_bits, &creation_data);
- dia = RNA_float_get(op->ptr, "size") / 2.0f;
- mul_mat3_m4_fl(creation_data.mat, dia);
-
- em = BKE_editmesh_from_object(obedit);
-
- if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
- }
-
- if (!EDBM_op_call_and_selectf(
- em, op, "verts.out", false,
- "create_monkey matrix=%m4 calc_uvs=%b", creation_data.mat, calc_uvs))
- {
- return OPERATOR_CANCELLED;
- }
-
- make_prim_finish(C, obedit, &creation_data, enter_editmode);
-
- return OPERATOR_FINISHED;
+ MakePrimitiveData creation_data;
+ Object *obedit;
+ BMEditMesh *em;
+ float loc[3], rot[3];
+ float dia;
+ bool enter_editmode;
+ ushort local_view_bits;
+ const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
+
+ WM_operator_view3d_unit_defaults(C, op);
+ ED_object_add_generic_get_opts(C, op, 'Y', loc, rot, &enter_editmode, &local_view_bits, NULL);
+
+ obedit = make_prim_init(
+ C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Suzanne"), loc, rot, local_view_bits, &creation_data);
+ dia = RNA_float_get(op->ptr, "size") / 2.0f;
+ mul_mat3_m4_fl(creation_data.mat, dia);
+
+ em = BKE_editmesh_from_object(obedit);
+
+ if (calc_uvs) {
+ ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ }
+
+ if (!EDBM_op_call_and_selectf(em,
+ op,
+ "verts.out",
+ false,
+ "create_monkey matrix=%m4 calc_uvs=%b",
+ creation_data.mat,
+ calc_uvs)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ make_prim_finish(C, obedit, &creation_data, enter_editmode);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_primitive_monkey_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Monkey";
- ot->description = "Construct a Suzanne mesh";
- ot->idname = "MESH_OT_primitive_monkey_add";
-
- /* api callbacks */
- ot->exec = add_primitive_monkey_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- ED_object_add_unit_props_size(ot);
- ED_object_add_mesh_props(ot);
- ED_object_add_generic_props(ot, true);
+ /* identifiers */
+ ot->name = "Add Monkey";
+ ot->description = "Construct a Suzanne mesh";
+ ot->idname = "MESH_OT_primitive_monkey_add";
+
+ /* api callbacks */
+ ot->exec = add_primitive_monkey_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ ED_object_add_unit_props_size(ot);
+ ED_object_add_mesh_props(ot);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
{
- MakePrimitiveData creation_data;
- Object *obedit;
- BMEditMesh *em;
- float loc[3], rot[3];
- bool enter_editmode;
- ushort local_view_bits;
- const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
-
- WM_operator_view3d_unit_defaults(C, op);
- ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
- obedit = make_prim_init(
- C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Sphere"),
- loc, rot, local_view_bits, &creation_data);
- em = BKE_editmesh_from_object(obedit);
-
- if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
- }
-
- if (!EDBM_op_call_and_selectf(
- em, op, "verts.out", false,
- "create_uvsphere u_segments=%i v_segments=%i diameter=%f matrix=%m4 calc_uvs=%b",
- RNA_int_get(op->ptr, "segments"), RNA_int_get(op->ptr, "ring_count"),
- RNA_float_get(op->ptr, "radius"), creation_data.mat, calc_uvs))
- {
- return OPERATOR_CANCELLED;
- }
-
- make_prim_finish(C, obedit, &creation_data, enter_editmode);
-
- return OPERATOR_FINISHED;
+ MakePrimitiveData creation_data;
+ Object *obedit;
+ BMEditMesh *em;
+ float loc[3], rot[3];
+ bool enter_editmode;
+ ushort local_view_bits;
+ const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
+
+ WM_operator_view3d_unit_defaults(C, op);
+ ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
+ obedit = make_prim_init(
+ C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Sphere"), loc, rot, local_view_bits, &creation_data);
+ em = BKE_editmesh_from_object(obedit);
+
+ if (calc_uvs) {
+ ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ }
+
+ if (!EDBM_op_call_and_selectf(
+ em,
+ op,
+ "verts.out",
+ false,
+ "create_uvsphere u_segments=%i v_segments=%i diameter=%f matrix=%m4 calc_uvs=%b",
+ RNA_int_get(op->ptr, "segments"),
+ RNA_int_get(op->ptr, "ring_count"),
+ RNA_float_get(op->ptr, "radius"),
+ creation_data.mat,
+ calc_uvs)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ make_prim_finish(C, obedit, &creation_data, enter_editmode);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add UV Sphere";
- ot->description = "Construct a UV sphere mesh";
- ot->idname = "MESH_OT_primitive_uv_sphere_add";
+ /* identifiers */
+ ot->name = "Add UV Sphere";
+ ot->description = "Construct a UV sphere mesh";
+ ot->idname = "MESH_OT_primitive_uv_sphere_add";
- /* api callbacks */
- ot->exec = add_primitive_uvsphere_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = add_primitive_uvsphere_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_int(ot->srna, "segments", 32, 3, MESH_ADD_VERTS_MAXI / 100, "Segments", "", 3, 500);
- RNA_def_int(ot->srna, "ring_count", 16, 3, MESH_ADD_VERTS_MAXI / 100, "Rings", "", 3, 500);
+ /* props */
+ RNA_def_int(ot->srna, "segments", 32, 3, MESH_ADD_VERTS_MAXI / 100, "Segments", "", 3, 500);
+ RNA_def_int(ot->srna, "ring_count", 16, 3, MESH_ADD_VERTS_MAXI / 100, "Rings", "", 3, 500);
- ED_object_add_unit_props_radius(ot);
- ED_object_add_mesh_props(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_mesh_props(ot);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
{
- MakePrimitiveData creation_data;
- Object *obedit;
- BMEditMesh *em;
- float loc[3], rot[3];
- bool enter_editmode;
- ushort local_view_bits;
- const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
-
- WM_operator_view3d_unit_defaults(C, op);
- ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
- obedit = make_prim_init(
- C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Icosphere"),
- loc, rot, local_view_bits, &creation_data);
- em = BKE_editmesh_from_object(obedit);
-
- if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
- }
-
- if (!EDBM_op_call_and_selectf(
- em, op, "verts.out", false,
- "create_icosphere subdivisions=%i diameter=%f matrix=%m4 calc_uvs=%b",
- RNA_int_get(op->ptr, "subdivisions"),
- RNA_float_get(op->ptr, "radius"), creation_data.mat, calc_uvs))
- {
- return OPERATOR_CANCELLED;
- }
-
- make_prim_finish(C, obedit, &creation_data, enter_editmode);
-
- return OPERATOR_FINISHED;
+ MakePrimitiveData creation_data;
+ Object *obedit;
+ BMEditMesh *em;
+ float loc[3], rot[3];
+ bool enter_editmode;
+ ushort local_view_bits;
+ const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
+
+ WM_operator_view3d_unit_defaults(C, op);
+ ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
+ obedit = make_prim_init(C,
+ CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Icosphere"),
+ loc,
+ rot,
+ local_view_bits,
+ &creation_data);
+ em = BKE_editmesh_from_object(obedit);
+
+ if (calc_uvs) {
+ ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ }
+
+ if (!EDBM_op_call_and_selectf(
+ em,
+ op,
+ "verts.out",
+ false,
+ "create_icosphere subdivisions=%i diameter=%f matrix=%m4 calc_uvs=%b",
+ RNA_int_get(op->ptr, "subdivisions"),
+ RNA_float_get(op->ptr, "radius"),
+ creation_data.mat,
+ calc_uvs)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ make_prim_finish(C, obedit, &creation_data, enter_editmode);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Ico Sphere";
- ot->description = "Construct an Icosphere mesh";
- ot->idname = "MESH_OT_primitive_ico_sphere_add";
+ /* identifiers */
+ ot->name = "Add Ico Sphere";
+ ot->description = "Construct an Icosphere mesh";
+ ot->idname = "MESH_OT_primitive_ico_sphere_add";
- /* api callbacks */
- ot->exec = add_primitive_icosphere_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = add_primitive_icosphere_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_int(ot->srna, "subdivisions", 2, 1, 10, "Subdivisions", "", 1, 8);
+ /* props */
+ RNA_def_int(ot->srna, "subdivisions", 2, 1, 10, "Subdivisions", "", 1, 8);
- ED_object_add_unit_props_radius(ot);
- ED_object_add_mesh_props(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_mesh_props(ot);
+ ED_object_add_generic_props(ot, true);
}
diff --git a/source/blender/editors/mesh/editmesh_add_gizmo.c b/source/blender/editors/mesh/editmesh_add_gizmo.c
index b01a935e4d2..9ed2c15f1c1 100644
--- a/source/blender/editors/mesh/editmesh_add_gizmo.c
+++ b/source/blender/editors/mesh/editmesh_add_gizmo.c
@@ -48,7 +48,7 @@
#include "BLT_translation.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Helper Functions
@@ -60,51 +60,52 @@
* We may base this choice on context,
* for now pick the "ground" based on the 3D cursor's dominant plane pointing down relative to the view.
*/
-static void calc_initial_placement_point_from_view(
- bContext *C, const float mval[2],
- float r_location[3], float r_rotation[3][3])
+static void calc_initial_placement_point_from_view(bContext *C,
+ const float mval[2],
+ float r_location[3],
+ float r_rotation[3][3])
{
- Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
-
- bool use_mouse_project = true; /* TODO: make optional */
-
- float cursor_matrix[4][4];
- float orient_matrix[3][3];
- ED_view3d_cursor3d_calc_mat4(scene, cursor_matrix);
-
- float dots[3] = {
- dot_v3v3(rv3d->viewinv[2], cursor_matrix[0]),
- dot_v3v3(rv3d->viewinv[2], cursor_matrix[1]),
- dot_v3v3(rv3d->viewinv[2], cursor_matrix[2]),
- };
- const int axis = axis_dominant_v3_single(dots);
-
- copy_v3_v3(orient_matrix[0], cursor_matrix[(axis + 1) % 3]);
- copy_v3_v3(orient_matrix[1], cursor_matrix[(axis + 2) % 3]);
- copy_v3_v3(orient_matrix[2], cursor_matrix[axis]);
-
- if (dot_v3v3(rv3d->viewinv[2], orient_matrix[2]) < 0.0f) {
- negate_v3(orient_matrix[2]);
- }
- if (is_negative_m3(orient_matrix)) {
- swap_v3_v3(orient_matrix[0], orient_matrix[1]);
- }
-
- 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)) {
- copy_m3_m3(r_rotation, orient_matrix);
- return;
- }
- }
-
- /* fallback */
- copy_v3_v3(r_location, cursor_matrix[3]);
- copy_m3_m3(r_rotation, orient_matrix);
+ Scene *scene = CTX_data_scene(C);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ bool use_mouse_project = true; /* TODO: make optional */
+
+ float cursor_matrix[4][4];
+ float orient_matrix[3][3];
+ ED_view3d_cursor3d_calc_mat4(scene, cursor_matrix);
+
+ float dots[3] = {
+ dot_v3v3(rv3d->viewinv[2], cursor_matrix[0]),
+ dot_v3v3(rv3d->viewinv[2], cursor_matrix[1]),
+ dot_v3v3(rv3d->viewinv[2], cursor_matrix[2]),
+ };
+ const int axis = axis_dominant_v3_single(dots);
+
+ copy_v3_v3(orient_matrix[0], cursor_matrix[(axis + 1) % 3]);
+ copy_v3_v3(orient_matrix[1], cursor_matrix[(axis + 2) % 3]);
+ copy_v3_v3(orient_matrix[2], cursor_matrix[axis]);
+
+ if (dot_v3v3(rv3d->viewinv[2], orient_matrix[2]) < 0.0f) {
+ negate_v3(orient_matrix[2]);
+ }
+ if (is_negative_m3(orient_matrix)) {
+ swap_v3_v3(orient_matrix[0], orient_matrix[1]);
+ }
+
+ 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)) {
+ copy_m3_m3(r_rotation, orient_matrix);
+ return;
+ }
+ }
+
+ /* fallback */
+ copy_v3_v3(r_location, cursor_matrix[3]);
+ copy_m3_m3(r_rotation, orient_matrix);
}
/** \} */
@@ -114,12 +115,12 @@ static void calc_initial_placement_point_from_view(
* \{ */
typedef struct GizmoPlacementGroup {
- struct wmGizmo *cage;
- struct {
- bContext *context;
- wmOperator *op;
- PropertyRNA *prop_matrix;
- } data;
+ struct wmGizmo *cage;
+ struct {
+ bContext *context;
+ wmOperator *op;
+ PropertyRNA *prop_matrix;
+ } data;
} GizmoPlacementGroup;
/**
@@ -129,178 +130,181 @@ typedef struct GizmoPlacementGroup {
*/
static void gizmo_placement_exec(GizmoPlacementGroup *ggd)
{
- wmOperator *op = ggd->data.op;
- if (op == WM_operator_last_redo((bContext *)ggd->data.context)) {
- ED_undo_operator_repeat((bContext *)ggd->data.context, op);
- }
+ wmOperator *op = ggd->data.op;
+ if (op == WM_operator_last_redo((bContext *)ggd->data.context)) {
+ ED_undo_operator_repeat((bContext *)ggd->data.context, op);
+ }
}
static void gizmo_mesh_placement_update_from_op(GizmoPlacementGroup *ggd)
{
- wmOperator *op = ggd->data.op;
- UNUSED_VARS(op);
- /* For now don't read back from the operator. */
+ wmOperator *op = ggd->data.op;
+ UNUSED_VARS(op);
+ /* For now don't read back from the operator. */
#if 0
- RNA_property_float_get_array(op->ptr, ggd->data.prop_matrix, &ggd->cage->matrix_offset[0][0]);
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_matrix, &ggd->cage->matrix_offset[0][0]);
#endif
}
/* translate callbacks */
-static void gizmo_placement_prop_matrix_get(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- void *value_p)
+static void gizmo_placement_prop_matrix_get(const wmGizmo *gz,
+ wmGizmoProperty *gz_prop,
+ void *value_p)
{
- GizmoPlacementGroup *ggd = gz->parent_gzgroup->customdata;
- wmOperator *op = ggd->data.op;
- float *value = value_p;
- BLI_assert(gz_prop->type->array_length == 16);
- UNUSED_VARS_NDEBUG(gz_prop);
-
- if (value_p != ggd->cage->matrix_offset) {
- mul_m4_m4m4(value_p, ggd->cage->matrix_basis, ggd->cage->matrix_offset);
- RNA_property_float_get_array(op->ptr, ggd->data.prop_matrix, value);
- }
+ GizmoPlacementGroup *ggd = gz->parent_gzgroup->customdata;
+ wmOperator *op = ggd->data.op;
+ float *value = value_p;
+ BLI_assert(gz_prop->type->array_length == 16);
+ UNUSED_VARS_NDEBUG(gz_prop);
+
+ if (value_p != ggd->cage->matrix_offset) {
+ mul_m4_m4m4(value_p, ggd->cage->matrix_basis, ggd->cage->matrix_offset);
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_matrix, value);
+ }
}
-static void gizmo_placement_prop_matrix_set(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- const void *value)
+static void gizmo_placement_prop_matrix_set(const wmGizmo *gz,
+ wmGizmoProperty *gz_prop,
+ const void *value)
{
- GizmoPlacementGroup *ggd = gz->parent_gzgroup->customdata;
- wmOperator *op = ggd->data.op;
+ GizmoPlacementGroup *ggd = gz->parent_gzgroup->customdata;
+ wmOperator *op = ggd->data.op;
- BLI_assert(gz_prop->type->array_length == 16);
- UNUSED_VARS_NDEBUG(gz_prop);
+ BLI_assert(gz_prop->type->array_length == 16);
+ UNUSED_VARS_NDEBUG(gz_prop);
- float mat[4][4];
- mul_m4_m4m4(mat, ggd->cage->matrix_basis, value);
+ float mat[4][4];
+ mul_m4_m4m4(mat, ggd->cage->matrix_basis, value);
- if (is_negative_m4(mat)) {
- negate_mat3_m4(mat);
- }
+ if (is_negative_m4(mat)) {
+ negate_mat3_m4(mat);
+ }
- RNA_property_float_set_array(op->ptr, ggd->data.prop_matrix, &mat[0][0]);
+ RNA_property_float_set_array(op->ptr, ggd->data.prop_matrix, &mat[0][0]);
- gizmo_placement_exec(ggd);
+ gizmo_placement_exec(ggd);
}
static bool gizmo_mesh_placement_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
- return ED_gizmo_poll_or_unlink_delayed_from_operator(C, gzgt, "MESH_OT_primitive_cube_add_gizmo");
+ return ED_gizmo_poll_or_unlink_delayed_from_operator(
+ C, gzgt, "MESH_OT_primitive_cube_add_gizmo");
}
-static void gizmo_mesh_placement_modal_from_setup(
- const bContext *C, wmGizmoGroup *gzgroup)
+static void gizmo_mesh_placement_modal_from_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoPlacementGroup *ggd = gzgroup->customdata;
-
- /* Initial size. */
- {
- wmGizmo *gz = ggd->cage;
- zero_m4(gz->matrix_offset);
-
- /* TODO: support zero scaled matrix in 'GIZMO_GT_cage_3d'. */
- gz->matrix_offset[0][0] = 0.01;
- gz->matrix_offset[1][1] = 0.01;
- gz->matrix_offset[2][2] = 0.01;
- gz->matrix_offset[3][3] = 1.0f;
- }
-
- /* Start off dragging. */
- {
- wmWindow *win = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
- wmGizmo *gz = ggd->cage;
-
- {
- float mat3[3][3];
- 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,
- },
- location, mat3);
- copy_m4_m3(gz->matrix_basis, mat3);
- copy_v3_v3(gz->matrix_basis[3], location);
- }
-
- if (1) {
- wmGizmoMap *gzmap = gzgroup->parent_gzmap;
- WM_gizmo_modal_set_from_setup(
- gzmap, (bContext *)C, ggd->cage, ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z, win->eventstate);
- }
- }
+ GizmoPlacementGroup *ggd = gzgroup->customdata;
+
+ /* Initial size. */
+ {
+ wmGizmo *gz = ggd->cage;
+ zero_m4(gz->matrix_offset);
+
+ /* TODO: support zero scaled matrix in 'GIZMO_GT_cage_3d'. */
+ gz->matrix_offset[0][0] = 0.01;
+ gz->matrix_offset[1][1] = 0.01;
+ gz->matrix_offset[2][2] = 0.01;
+ gz->matrix_offset[3][3] = 1.0f;
+ }
+
+ /* Start off dragging. */
+ {
+ wmWindow *win = CTX_wm_window(C);
+ ARegion *ar = CTX_wm_region(C);
+ wmGizmo *gz = ggd->cage;
+
+ {
+ float mat3[3][3];
+ 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,
+ },
+ location,
+ mat3);
+ copy_m4_m3(gz->matrix_basis, mat3);
+ copy_v3_v3(gz->matrix_basis[3], location);
+ }
+
+ if (1) {
+ wmGizmoMap *gzmap = gzgroup->parent_gzmap;
+ WM_gizmo_modal_set_from_setup(gzmap,
+ (bContext *)C,
+ ggd->cage,
+ ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z,
+ win->eventstate);
+ }
+ }
}
static void gizmo_mesh_placement_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
- wmOperator *op = WM_operator_last_redo(C);
+ wmOperator *op = WM_operator_last_redo(C);
- if (op == NULL || !STREQ(op->type->idname, "MESH_OT_primitive_cube_add_gizmo")) {
- return;
- }
+ if (op == NULL || !STREQ(op->type->idname, "MESH_OT_primitive_cube_add_gizmo")) {
+ return;
+ }
- struct GizmoPlacementGroup *ggd = MEM_callocN(sizeof(GizmoPlacementGroup), __func__);
- gzgroup->customdata = ggd;
+ struct GizmoPlacementGroup *ggd = MEM_callocN(sizeof(GizmoPlacementGroup), __func__);
+ gzgroup->customdata = ggd;
- const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_3d", true);
+ const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_3d", true);
- ggd->cage = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL);
+ ggd->cage = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL);
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, ggd->cage->color);
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, ggd->cage->color);
- RNA_enum_set(ggd->cage->ptr, "transform",
- ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE |
- ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE |
- ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_SIGNED);
+ RNA_enum_set(ggd->cage->ptr,
+ "transform",
+ ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE | ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE |
+ ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_SIGNED);
- WM_gizmo_set_flag(ggd->cage, WM_GIZMO_DRAW_VALUE, true);
+ WM_gizmo_set_flag(ggd->cage, WM_GIZMO_DRAW_VALUE, true);
- ggd->data.context = (bContext *)C;
- ggd->data.op = op;
- ggd->data.prop_matrix = RNA_struct_find_property(op->ptr, "matrix");
+ ggd->data.context = (bContext *)C;
+ ggd->data.op = op;
+ ggd->data.prop_matrix = RNA_struct_find_property(op->ptr, "matrix");
- gizmo_mesh_placement_update_from_op(ggd);
+ gizmo_mesh_placement_update_from_op(ggd);
- /* Setup property callbacks */
- {
- WM_gizmo_target_property_def_func(
- ggd->cage, "matrix",
- &(const struct wmGizmoPropertyFnParams) {
- .value_get_fn = gizmo_placement_prop_matrix_get,
- .value_set_fn = gizmo_placement_prop_matrix_set,
- .range_get_fn = NULL,
- .user_data = NULL,
- });
- }
+ /* Setup property callbacks */
+ {
+ WM_gizmo_target_property_def_func(ggd->cage,
+ "matrix",
+ &(const struct wmGizmoPropertyFnParams){
+ .value_get_fn = gizmo_placement_prop_matrix_get,
+ .value_set_fn = gizmo_placement_prop_matrix_set,
+ .range_get_fn = NULL,
+ .user_data = NULL,
+ });
+ }
- gizmo_mesh_placement_modal_from_setup(C, gzgroup);
+ gizmo_mesh_placement_modal_from_setup(C, gzgroup);
}
-static void gizmo_mesh_placement_draw_prepare(
- const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
+static void gizmo_mesh_placement_draw_prepare(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- GizmoPlacementGroup *ggd = gzgroup->customdata;
- if (ggd->data.op->next) {
- ggd->data.op = WM_operator_last_redo((bContext *)ggd->data.context);
- }
- gizmo_mesh_placement_update_from_op(ggd);
+ GizmoPlacementGroup *ggd = gzgroup->customdata;
+ if (ggd->data.op->next) {
+ ggd->data.op = WM_operator_last_redo((bContext *)ggd->data.context);
+ }
+ gizmo_mesh_placement_update_from_op(ggd);
}
static void MESH_GGT_add_bounds(struct wmGizmoGroupType *gzgt)
{
- gzgt->name = "Mesh Add Bounds";
- gzgt->idname = "MESH_GGT_add_bounds";
+ gzgt->name = "Mesh Add Bounds";
+ gzgt->idname = "MESH_GGT_add_bounds";
- gzgt->flag = WM_GIZMOGROUPTYPE_3D;
+ gzgt->flag = WM_GIZMOGROUPTYPE_3D;
- gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
- gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- gzgt->poll = gizmo_mesh_placement_poll;
- gzgt->setup = gizmo_mesh_placement_setup;
- gzgt->draw_prepare = gizmo_mesh_placement_draw_prepare;
+ gzgt->poll = gizmo_mesh_placement_poll;
+ gzgt->setup = gizmo_mesh_placement_setup;
+ gzgt->draw_prepare = gizmo_mesh_placement_draw_prepare;
}
/** \} */
@@ -313,89 +317,94 @@ static void MESH_GGT_add_bounds(struct wmGizmoGroupType *gzgt)
* and share the same BMesh creation code.
* \{ */
-
static int add_primitive_cube_gizmo_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- float matrix[4][4];
-
- /* Get the matrix that defines the cube bounds (as set by the gizmo cage). */
- {
- PropertyRNA *prop_matrix = RNA_struct_find_property(op->ptr, "matrix");
- if (RNA_property_is_set(op->ptr, prop_matrix)) {
- RNA_property_float_get_array(op->ptr, prop_matrix, &matrix[0][0]);
- invert_m4_m4(obedit->imat, obedit->obmat);
- mul_m4_m4m4(matrix, obedit->imat, matrix);
- }
- else {
- /* For the first update the widget may not set the matrix. */
- return OPERATOR_FINISHED;
- }
- }
-
- const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
-
- if (calc_uvs) {
- ED_mesh_uv_texture_ensure(obedit->data, NULL);
- }
-
- if (!EDBM_op_call_and_selectf(
- em, op, "verts.out", false,
- "create_cube matrix=%m4 size=%f calc_uvs=%b",
- matrix, 1.0f, calc_uvs))
- {
- return OPERATOR_CANCELLED;
- }
-
- EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX);
- EDBM_update_generic(em, true, true);
-
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ float matrix[4][4];
+
+ /* Get the matrix that defines the cube bounds (as set by the gizmo cage). */
+ {
+ PropertyRNA *prop_matrix = RNA_struct_find_property(op->ptr, "matrix");
+ if (RNA_property_is_set(op->ptr, prop_matrix)) {
+ RNA_property_float_get_array(op->ptr, prop_matrix, &matrix[0][0]);
+ invert_m4_m4(obedit->imat, obedit->obmat);
+ mul_m4_m4m4(matrix, obedit->imat, matrix);
+ }
+ else {
+ /* For the first update the widget may not set the matrix. */
+ return OPERATOR_FINISHED;
+ }
+ }
+
+ const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
+
+ if (calc_uvs) {
+ ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ }
+
+ if (!EDBM_op_call_and_selectf(em,
+ op,
+ "verts.out",
+ false,
+ "create_cube matrix=%m4 size=%f calc_uvs=%b",
+ matrix,
+ 1.0f,
+ calc_uvs)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX);
+ EDBM_update_generic(em, true, true);
+
+ return OPERATOR_FINISHED;
}
-static int add_primitive_cube_gizmo_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int add_primitive_cube_gizmo_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
{
- View3D *v3d = CTX_wm_view3d(C);
-
- int ret = add_primitive_cube_gizmo_exec(C, op);
- if (ret & OPERATOR_FINISHED) {
- /* Setup gizmos */
- if (v3d && ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0)) {
- wmGizmoGroupType *gzgt = WM_gizmogrouptype_find("MESH_GGT_add_bounds", false);
- if (!WM_gizmo_group_type_ensure_ptr(gzgt)) {
- struct Main *bmain = CTX_data_main(C);
- WM_gizmo_group_type_reinit_ptr(bmain, gzgt);
- }
- }
- }
-
- return ret;
+ View3D *v3d = CTX_wm_view3d(C);
+
+ int ret = add_primitive_cube_gizmo_exec(C, op);
+ if (ret & OPERATOR_FINISHED) {
+ /* Setup gizmos */
+ if (v3d && ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0)) {
+ wmGizmoGroupType *gzgt = WM_gizmogrouptype_find("MESH_GGT_add_bounds", false);
+ if (!WM_gizmo_group_type_ensure_ptr(gzgt)) {
+ struct Main *bmain = CTX_data_main(C);
+ WM_gizmo_group_type_reinit_ptr(bmain, gzgt);
+ }
+ }
+ }
+
+ return ret;
}
void MESH_OT_primitive_cube_add_gizmo(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Cube";
- ot->description = "Construct a cube mesh";
- ot->idname = "MESH_OT_primitive_cube_add_gizmo";
+ /* identifiers */
+ ot->name = "Add Cube";
+ ot->description = "Construct a cube mesh";
+ ot->idname = "MESH_OT_primitive_cube_add_gizmo";
- /* api callbacks */
- ot->invoke = add_primitive_cube_gizmo_invoke;
- ot->exec = add_primitive_cube_gizmo_exec;
- ot->poll = ED_operator_editmesh_view3d;
+ /* api callbacks */
+ ot->invoke = add_primitive_cube_gizmo_invoke;
+ ot->exec = add_primitive_cube_gizmo_exec;
+ ot->poll = ED_operator_editmesh_view3d;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_mesh_props(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_mesh_props(ot);
+ ED_object_add_generic_props(ot, true);
- /* hidden props */
- PropertyRNA *prop = RNA_def_float_matrix(ot->srna, "matrix", 4, 4, NULL, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ /* hidden props */
+ PropertyRNA *prop = RNA_def_float_matrix(
+ ot->srna, "matrix", 4, 4, NULL, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- WM_gizmogrouptype_append(MESH_GGT_add_bounds);
+ WM_gizmogrouptype_append(MESH_GGT_add_bounds);
}
/** \} */
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index 1059374dcc5..2c0c8b2c708 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -51,10 +51,9 @@
#include "ED_transform.h"
#include "ED_view3d.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
-
-#define MVAL_PIXEL_MARGIN 5.0f
+#define MVAL_PIXEL_MARGIN 5.0f
#define PROFILE_HARD_MIN 0.0f
@@ -67,839 +66,925 @@
#define SEGMENTS_VALUE 3
#define NUM_VALUE_KINDS 4
-static const char *value_rna_name[NUM_VALUE_KINDS] = {"offset", "offset_pct", "profile", "segments"};
+static const char *value_rna_name[NUM_VALUE_KINDS] = {
+ "offset", "offset_pct", "profile", "segments"};
static const float value_clamp_min[NUM_VALUE_KINDS] = {0.0f, 0.0f, PROFILE_HARD_MIN, 1.0f};
static const float value_clamp_max[NUM_VALUE_KINDS] = {1e6, 100.0f, 1.0f, SEGMENTS_HARD_MAX};
static const float value_start[NUM_VALUE_KINDS] = {0.0f, 0.0f, 0.5f, 1.0f};
-static const float value_scale_per_inch[NUM_VALUE_KINDS] = { 0.0f, 100.0f, 1.0f, 4.0f};
+static const float value_scale_per_inch[NUM_VALUE_KINDS] = {0.0f, 100.0f, 1.0f, 4.0f};
typedef struct {
- BMEditMesh *em;
- BMBackup mesh_backup;
+ BMEditMesh *em;
+ BMBackup mesh_backup;
} BevelObjectStore;
-
typedef struct {
- float initial_length[NUM_VALUE_KINDS];
- float scale[NUM_VALUE_KINDS];
- NumInput num_input[NUM_VALUE_KINDS];
- /** The current value when shift is pressed. Negative when shift not active. */
- float shift_value[NUM_VALUE_KINDS];
- float max_obj_scale;
- bool is_modal;
-
- BevelObjectStore *ob_store;
- uint ob_store_len;
-
- /* modal only */
- float mcenter[2];
- void *draw_handle_pixel;
- short gizmo_flag;
- short value_mode; /* Which value does mouse movement and numeric input affect? */
- float segments; /* Segments as float so smooth mouse pan works in small increments */
+ float initial_length[NUM_VALUE_KINDS];
+ float scale[NUM_VALUE_KINDS];
+ NumInput num_input[NUM_VALUE_KINDS];
+ /** The current value when shift is pressed. Negative when shift not active. */
+ float shift_value[NUM_VALUE_KINDS];
+ float max_obj_scale;
+ bool is_modal;
+
+ BevelObjectStore *ob_store;
+ uint ob_store_len;
+
+ /* modal only */
+ float mcenter[2];
+ void *draw_handle_pixel;
+ short gizmo_flag;
+ short value_mode; /* Which value does mouse movement and numeric input affect? */
+ float segments; /* Segments as float so smooth mouse pan works in small increments */
} BevelData;
enum {
- BEV_MODAL_CANCEL = 1,
- BEV_MODAL_CONFIRM,
- BEV_MODAL_VALUE_OFFSET,
- BEV_MODAL_VALUE_PROFILE,
- BEV_MODAL_VALUE_SEGMENTS,
- BEV_MODAL_SEGMENTS_UP,
- BEV_MODAL_SEGMENTS_DOWN,
- BEV_MODAL_OFFSET_MODE_CHANGE,
- BEV_MODAL_CLAMP_OVERLAP_TOGGLE,
- BEV_MODAL_VERTEX_ONLY_TOGGLE,
- BEV_MODAL_HARDEN_NORMALS_TOGGLE,
- BEV_MODAL_MARK_SEAM_TOGGLE,
- BEV_MODAL_MARK_SHARP_TOGGLE,
- BEV_MODAL_OUTER_MITER_CHANGE,
- BEV_MODAL_INNER_MITER_CHANGE,
+ BEV_MODAL_CANCEL = 1,
+ BEV_MODAL_CONFIRM,
+ BEV_MODAL_VALUE_OFFSET,
+ BEV_MODAL_VALUE_PROFILE,
+ BEV_MODAL_VALUE_SEGMENTS,
+ BEV_MODAL_SEGMENTS_UP,
+ BEV_MODAL_SEGMENTS_DOWN,
+ BEV_MODAL_OFFSET_MODE_CHANGE,
+ BEV_MODAL_CLAMP_OVERLAP_TOGGLE,
+ BEV_MODAL_VERTEX_ONLY_TOGGLE,
+ BEV_MODAL_HARDEN_NORMALS_TOGGLE,
+ BEV_MODAL_MARK_SEAM_TOGGLE,
+ BEV_MODAL_MARK_SHARP_TOGGLE,
+ BEV_MODAL_OUTER_MITER_CHANGE,
+ BEV_MODAL_INNER_MITER_CHANGE,
};
static float get_bevel_offset(wmOperator *op)
{
- float val;
+ float val;
- if (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT)
- val = RNA_float_get(op->ptr, "offset_pct");
- else
- val = RNA_float_get(op->ptr, "offset");
- return val;
+ if (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT)
+ val = RNA_float_get(op->ptr, "offset_pct");
+ else
+ val = RNA_float_get(op->ptr, "offset");
+ return val;
}
static void edbm_bevel_update_header(bContext *C, wmOperator *op)
{
- char header[UI_MAX_DRAW_STR];
- char buf[UI_MAX_DRAW_STR];
- char *p = buf;
- int available_len = sizeof(buf);
- Scene *sce = CTX_data_scene(C);
- char offset_str[NUM_STR_REP_LEN];
- const char *mode_str, *omiter_str, *imiter_str;
- PropertyRNA *prop;
+ char header[UI_MAX_DRAW_STR];
+ char buf[UI_MAX_DRAW_STR];
+ char *p = buf;
+ int available_len = sizeof(buf);
+ Scene *sce = CTX_data_scene(C);
+ char offset_str[NUM_STR_REP_LEN];
+ const char *mode_str, *omiter_str, *imiter_str;
+ PropertyRNA *prop;
#define WM_MODALKEY(_id) \
- WM_modalkeymap_operator_items_to_string_buf(op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p)
-
- if (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT) {
- BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%.1f%%", RNA_float_get(op->ptr, "offset_pct"));
- }
- else {
- bUnit_AsString2(
- offset_str, NUM_STR_REP_LEN, (double)RNA_float_get(op->ptr, "offset"), 3,
- B_UNIT_LENGTH, &sce->unit, true);
- }
-
- prop = RNA_struct_find_property(op->ptr, "offset_type");
- RNA_property_enum_name_gettexted(C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &mode_str);
- prop = RNA_struct_find_property(op->ptr, "miter_outer");
- RNA_property_enum_name_gettexted(C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &omiter_str);
- prop = RNA_struct_find_property(op->ptr, "miter_inner");
- RNA_property_enum_name_gettexted(C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &imiter_str);
-
- BLI_snprintf(
- header, sizeof(header),
- IFACE_("%s: confirm, "
- "%s: cancel, "
- "%s: mode (%s), "
- "%s: width (%s), "
- "%s: segments (%d), "
- "%s: profile (%.3f), "
- "%s: clamp overlap (%s), "
- "%s: vertex only (%s), "
- "%s: outer miter (%s), "
- "%s: inner miter (%s), "
- "%s: harden normals (%s), "
- "%s: mark seam (%s), "
- "%s: mark sharp (%s)"
- ),
- WM_MODALKEY(BEV_MODAL_CONFIRM),
- WM_MODALKEY(BEV_MODAL_CANCEL),
- WM_MODALKEY(BEV_MODAL_OFFSET_MODE_CHANGE),
- mode_str,
- WM_MODALKEY(BEV_MODAL_VALUE_OFFSET),
- offset_str,
- WM_MODALKEY(BEV_MODAL_VALUE_SEGMENTS),
- RNA_int_get(op->ptr, "segments"),
- WM_MODALKEY(BEV_MODAL_VALUE_PROFILE),
- RNA_float_get(op->ptr, "profile"),
- WM_MODALKEY(BEV_MODAL_CLAMP_OVERLAP_TOGGLE),
- WM_bool_as_string(RNA_boolean_get(op->ptr, "clamp_overlap")),
- WM_MODALKEY(BEV_MODAL_VERTEX_ONLY_TOGGLE),
- WM_bool_as_string(RNA_boolean_get(op->ptr, "vertex_only")),
- WM_MODALKEY(BEV_MODAL_OUTER_MITER_CHANGE),
- omiter_str,
- WM_MODALKEY(BEV_MODAL_INNER_MITER_CHANGE),
- imiter_str,
- WM_MODALKEY(BEV_MODAL_HARDEN_NORMALS_TOGGLE),
- WM_bool_as_string(RNA_boolean_get(op->ptr, "harden_normals")),
- WM_MODALKEY(BEV_MODAL_MARK_SEAM_TOGGLE),
- WM_bool_as_string(RNA_boolean_get(op->ptr, "mark_seam")),
- WM_MODALKEY(BEV_MODAL_MARK_SHARP_TOGGLE),
- WM_bool_as_string(RNA_boolean_get(op->ptr, "mark_sharp"))
- );
+ WM_modalkeymap_operator_items_to_string_buf( \
+ op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p)
+
+ if (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT) {
+ BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%.1f%%", RNA_float_get(op->ptr, "offset_pct"));
+ }
+ else {
+ bUnit_AsString2(offset_str,
+ NUM_STR_REP_LEN,
+ (double)RNA_float_get(op->ptr, "offset"),
+ 3,
+ B_UNIT_LENGTH,
+ &sce->unit,
+ true);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "offset_type");
+ RNA_property_enum_name_gettexted(
+ C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &mode_str);
+ prop = RNA_struct_find_property(op->ptr, "miter_outer");
+ RNA_property_enum_name_gettexted(
+ C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &omiter_str);
+ prop = RNA_struct_find_property(op->ptr, "miter_inner");
+ RNA_property_enum_name_gettexted(
+ C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &imiter_str);
+
+ BLI_snprintf(header,
+ sizeof(header),
+ IFACE_("%s: confirm, "
+ "%s: cancel, "
+ "%s: mode (%s), "
+ "%s: width (%s), "
+ "%s: segments (%d), "
+ "%s: profile (%.3f), "
+ "%s: clamp overlap (%s), "
+ "%s: vertex only (%s), "
+ "%s: outer miter (%s), "
+ "%s: inner miter (%s), "
+ "%s: harden normals (%s), "
+ "%s: mark seam (%s), "
+ "%s: mark sharp (%s)"),
+ WM_MODALKEY(BEV_MODAL_CONFIRM),
+ WM_MODALKEY(BEV_MODAL_CANCEL),
+ WM_MODALKEY(BEV_MODAL_OFFSET_MODE_CHANGE),
+ mode_str,
+ WM_MODALKEY(BEV_MODAL_VALUE_OFFSET),
+ offset_str,
+ WM_MODALKEY(BEV_MODAL_VALUE_SEGMENTS),
+ RNA_int_get(op->ptr, "segments"),
+ WM_MODALKEY(BEV_MODAL_VALUE_PROFILE),
+ RNA_float_get(op->ptr, "profile"),
+ WM_MODALKEY(BEV_MODAL_CLAMP_OVERLAP_TOGGLE),
+ WM_bool_as_string(RNA_boolean_get(op->ptr, "clamp_overlap")),
+ WM_MODALKEY(BEV_MODAL_VERTEX_ONLY_TOGGLE),
+ WM_bool_as_string(RNA_boolean_get(op->ptr, "vertex_only")),
+ WM_MODALKEY(BEV_MODAL_OUTER_MITER_CHANGE),
+ omiter_str,
+ WM_MODALKEY(BEV_MODAL_INNER_MITER_CHANGE),
+ imiter_str,
+ WM_MODALKEY(BEV_MODAL_HARDEN_NORMALS_TOGGLE),
+ WM_bool_as_string(RNA_boolean_get(op->ptr, "harden_normals")),
+ WM_MODALKEY(BEV_MODAL_MARK_SEAM_TOGGLE),
+ WM_bool_as_string(RNA_boolean_get(op->ptr, "mark_seam")),
+ WM_MODALKEY(BEV_MODAL_MARK_SHARP_TOGGLE),
+ WM_bool_as_string(RNA_boolean_get(op->ptr, "mark_sharp")));
#undef WM_MODALKEY
- ED_workspace_status_text(C, header);
+ ED_workspace_status_text(C, header);
}
static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
{
- Scene *scene = CTX_data_scene(C);
- BevelData *opdata;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- float pixels_per_inch;
- int i, otype;
-
- if (is_modal) {
- RNA_float_set(op->ptr, "offset", 0.0f);
- RNA_float_set(op->ptr, "offset_pct", 0.0f);
- }
-
- op->customdata = opdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator");
- uint objects_used_len = 0;
- opdata->max_obj_scale = FLT_MIN;
-
- {
- uint ob_store_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
- view_layer, CTX_wm_view3d(C), &ob_store_len);
- opdata->ob_store = MEM_malloc_arrayN(ob_store_len, sizeof(*opdata->ob_store), __func__);
- for (uint ob_index = 0; ob_index < ob_store_len; ob_index++) {
- Object *obedit = objects[ob_index];
- float scale = mat4_to_scale(obedit->obmat);
- opdata->max_obj_scale = max_ff(opdata->max_obj_scale, scale);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totvertsel > 0) {
- opdata->ob_store[objects_used_len].em = em;
- objects_used_len++;
- }
- }
- MEM_freeN(objects);
- opdata->ob_store_len = objects_used_len;
- }
-
- opdata->is_modal = is_modal;
- otype = RNA_enum_get(op->ptr, "offset_type");
- opdata->value_mode = (otype == BEVEL_AMT_PERCENT) ? OFFSET_VALUE_PERCENT : OFFSET_VALUE;
- opdata->segments = (float) RNA_int_get(op->ptr, "segments");
- pixels_per_inch = U.dpi * U.pixelsize;
-
- for (i = 0; i < NUM_VALUE_KINDS; i++) {
- opdata->shift_value[i] = -1.0f;
- opdata->initial_length[i] = -1.0f;
- /* note: scale for OFFSET_VALUE will get overwritten in edbm_bevel_invoke */
- opdata->scale[i] = value_scale_per_inch[i] / pixels_per_inch;
-
- initNumInput(&opdata->num_input[i]);
- opdata->num_input[i].idx_max = 0;
- opdata->num_input[i].val_flag[0] |= NUM_NO_NEGATIVE;
- if (i == SEGMENTS_VALUE) {
- opdata->num_input[i].val_flag[0] |= NUM_NO_FRACTION | NUM_NO_ZERO;
- }
- if (i == OFFSET_VALUE) {
- opdata->num_input[i].unit_sys = scene->unit.system;
- }
- /* Not sure this is a factor or a unit? */
- opdata->num_input[i].unit_type[0] = B_UNIT_NONE;
- }
-
- /* avoid the cost of allocating a bm copy */
- if (is_modal) {
- View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
-
- for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
- opdata->ob_store[ob_index].mesh_backup = EDBM_redo_state_store(opdata->ob_store[ob_index].em);
- }
- opdata->draw_handle_pixel = ED_region_draw_cb_activate(
- ar->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;
- v3d->gizmo_flag = V3D_GIZMO_HIDE;
- }
- }
-
- return true;
+ Scene *scene = CTX_data_scene(C);
+ BevelData *opdata;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ float pixels_per_inch;
+ int i, otype;
+
+ if (is_modal) {
+ RNA_float_set(op->ptr, "offset", 0.0f);
+ RNA_float_set(op->ptr, "offset_pct", 0.0f);
+ }
+
+ op->customdata = opdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator");
+ uint objects_used_len = 0;
+ opdata->max_obj_scale = FLT_MIN;
+
+ {
+ uint ob_store_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &ob_store_len);
+ opdata->ob_store = MEM_malloc_arrayN(ob_store_len, sizeof(*opdata->ob_store), __func__);
+ for (uint ob_index = 0; ob_index < ob_store_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ float scale = mat4_to_scale(obedit->obmat);
+ opdata->max_obj_scale = max_ff(opdata->max_obj_scale, scale);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ if (em->bm->totvertsel > 0) {
+ opdata->ob_store[objects_used_len].em = em;
+ objects_used_len++;
+ }
+ }
+ MEM_freeN(objects);
+ opdata->ob_store_len = objects_used_len;
+ }
+
+ opdata->is_modal = is_modal;
+ otype = RNA_enum_get(op->ptr, "offset_type");
+ opdata->value_mode = (otype == BEVEL_AMT_PERCENT) ? OFFSET_VALUE_PERCENT : OFFSET_VALUE;
+ opdata->segments = (float)RNA_int_get(op->ptr, "segments");
+ pixels_per_inch = U.dpi * U.pixelsize;
+
+ for (i = 0; i < NUM_VALUE_KINDS; i++) {
+ opdata->shift_value[i] = -1.0f;
+ opdata->initial_length[i] = -1.0f;
+ /* note: scale for OFFSET_VALUE will get overwritten in edbm_bevel_invoke */
+ opdata->scale[i] = value_scale_per_inch[i] / pixels_per_inch;
+
+ initNumInput(&opdata->num_input[i]);
+ opdata->num_input[i].idx_max = 0;
+ opdata->num_input[i].val_flag[0] |= NUM_NO_NEGATIVE;
+ if (i == SEGMENTS_VALUE) {
+ opdata->num_input[i].val_flag[0] |= NUM_NO_FRACTION | NUM_NO_ZERO;
+ }
+ if (i == OFFSET_VALUE) {
+ opdata->num_input[i].unit_sys = scene->unit.system;
+ }
+ /* Not sure this is a factor or a unit? */
+ opdata->num_input[i].unit_type[0] = B_UNIT_NONE;
+ }
+
+ /* avoid the cost of allocating a bm copy */
+ if (is_modal) {
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
+ opdata->ob_store[ob_index].mesh_backup = EDBM_redo_state_store(
+ opdata->ob_store[ob_index].em);
+ }
+ opdata->draw_handle_pixel = ED_region_draw_cb_activate(
+ ar->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;
+ v3d->gizmo_flag = V3D_GIZMO_HIDE;
+ }
+ }
+
+ return true;
}
static bool edbm_bevel_calc(wmOperator *op)
{
- BevelData *opdata = op->customdata;
- BMEditMesh *em;
- BMOperator bmop;
- bool changed = false;
-
- const float offset = get_bevel_offset(op);
- const int offset_type = RNA_enum_get(op->ptr, "offset_type");
- const int segments = RNA_int_get(op->ptr, "segments");
- const float profile = RNA_float_get(op->ptr, "profile");
- const bool vertex_only = RNA_boolean_get(op->ptr, "vertex_only");
- const bool clamp_overlap = RNA_boolean_get(op->ptr, "clamp_overlap");
- int material = RNA_int_get(op->ptr, "material");
- const bool loop_slide = RNA_boolean_get(op->ptr, "loop_slide");
- const bool mark_seam = RNA_boolean_get(op->ptr, "mark_seam");
- const bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp");
- const bool harden_normals = RNA_boolean_get(op->ptr, "harden_normals");
- const int face_strength_mode = RNA_enum_get(op->ptr, "face_strength_mode");
- const int miter_outer = RNA_enum_get(op->ptr, "miter_outer");
- const int miter_inner = RNA_enum_get(op->ptr, "miter_inner");
- const float spread = RNA_float_get(op->ptr, "spread");
-
- for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
- em = opdata->ob_store[ob_index].em;
-
- /* revert to original mesh */
- if (opdata->is_modal) {
- EDBM_redo_state_restore(opdata->ob_store[ob_index].mesh_backup, em, false);
- }
-
- if (em->ob) {
- material = CLAMPIS(material, -1, em->ob->totcol - 1);
- }
-
- Mesh *me = em->ob->data;
-
- if (harden_normals && !(me->flag & ME_AUTOSMOOTH)) {
- /* harden_normals only has a visible effect if autosmooth is on, so turn it on */
- me->flag |= ME_AUTOSMOOTH;
- }
-
- EDBM_op_init(
- em, &bmop, op,
- "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f "
- "clamp_overlap=%b material=%i loop_slide=%b mark_seam=%b mark_sharp=%b "
- "harden_normals=%b face_strength_mode=%i "
- "miter_outer=%i miter_inner=%i spread=%f smoothresh=%f",
- BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile,
- clamp_overlap, material, loop_slide, mark_seam, mark_sharp, harden_normals, face_strength_mode,
- miter_outer, miter_inner, spread, me->smoothresh);
-
- BMO_op_exec(em->bm, &bmop);
-
- if (offset != 0.0f) {
- /* not essential, but we may have some loose geometry that
- * won't get bevel'd and better not leave it selected */
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
- }
-
- /* no need to de-select existing geometry */
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
-
- EDBM_mesh_normals_update(em);
-
- EDBM_update_generic(em, true, true);
- changed = true;
- }
- return changed;
+ BevelData *opdata = op->customdata;
+ BMEditMesh *em;
+ BMOperator bmop;
+ bool changed = false;
+
+ const float offset = get_bevel_offset(op);
+ const int offset_type = RNA_enum_get(op->ptr, "offset_type");
+ const int segments = RNA_int_get(op->ptr, "segments");
+ const float profile = RNA_float_get(op->ptr, "profile");
+ const bool vertex_only = RNA_boolean_get(op->ptr, "vertex_only");
+ const bool clamp_overlap = RNA_boolean_get(op->ptr, "clamp_overlap");
+ int material = RNA_int_get(op->ptr, "material");
+ const bool loop_slide = RNA_boolean_get(op->ptr, "loop_slide");
+ const bool mark_seam = RNA_boolean_get(op->ptr, "mark_seam");
+ const bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp");
+ const bool harden_normals = RNA_boolean_get(op->ptr, "harden_normals");
+ const int face_strength_mode = RNA_enum_get(op->ptr, "face_strength_mode");
+ const int miter_outer = RNA_enum_get(op->ptr, "miter_outer");
+ const int miter_inner = RNA_enum_get(op->ptr, "miter_inner");
+ const float spread = RNA_float_get(op->ptr, "spread");
+
+ for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
+ em = opdata->ob_store[ob_index].em;
+
+ /* revert to original mesh */
+ if (opdata->is_modal) {
+ EDBM_redo_state_restore(opdata->ob_store[ob_index].mesh_backup, em, false);
+ }
+
+ if (em->ob) {
+ material = CLAMPIS(material, -1, em->ob->totcol - 1);
+ }
+
+ Mesh *me = em->ob->data;
+
+ if (harden_normals && !(me->flag & ME_AUTOSMOOTH)) {
+ /* harden_normals only has a visible effect if autosmooth is on, so turn it on */
+ me->flag |= ME_AUTOSMOOTH;
+ }
+
+ EDBM_op_init(em,
+ &bmop,
+ op,
+ "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f "
+ "clamp_overlap=%b material=%i loop_slide=%b mark_seam=%b mark_sharp=%b "
+ "harden_normals=%b face_strength_mode=%i "
+ "miter_outer=%i miter_inner=%i spread=%f smoothresh=%f",
+ BM_ELEM_SELECT,
+ offset,
+ segments,
+ vertex_only,
+ offset_type,
+ profile,
+ clamp_overlap,
+ material,
+ loop_slide,
+ mark_seam,
+ mark_sharp,
+ harden_normals,
+ face_strength_mode,
+ miter_outer,
+ miter_inner,
+ spread,
+ me->smoothresh);
+
+ BMO_op_exec(em->bm, &bmop);
+
+ if (offset != 0.0f) {
+ /* not essential, but we may have some loose geometry that
+ * won't get bevel'd and better not leave it selected */
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BMO_slot_buffer_hflag_enable(
+ em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
+ }
+
+ /* no need to de-select existing geometry */
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
+
+ EDBM_mesh_normals_update(em);
+
+ EDBM_update_generic(em, true, true);
+ changed = true;
+ }
+ return changed;
}
static void edbm_bevel_exit(bContext *C, wmOperator *op)
{
- BevelData *opdata = op->customdata;
-
- ScrArea *sa = CTX_wm_area(C);
-
- if (sa) {
- ED_area_status_text(sa, NULL);
- }
-
- if (opdata->is_modal) {
- View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = 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);
- if (v3d) {
- v3d->gizmo_flag = opdata->gizmo_flag;
- }
- G.moving = 0;
- }
- MEM_SAFE_FREE(opdata->ob_store);
- MEM_SAFE_FREE(op->customdata);
- op->customdata = NULL;
+ BevelData *opdata = op->customdata;
+
+ ScrArea *sa = CTX_wm_area(C);
+
+ if (sa) {
+ ED_area_status_text(sa, NULL);
+ }
+
+ if (opdata->is_modal) {
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = 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);
+ if (v3d) {
+ v3d->gizmo_flag = opdata->gizmo_flag;
+ }
+ G.moving = 0;
+ }
+ MEM_SAFE_FREE(opdata->ob_store);
+ MEM_SAFE_FREE(op->customdata);
+ op->customdata = NULL;
}
static void edbm_bevel_cancel(bContext *C, wmOperator *op)
{
- BevelData *opdata = op->customdata;
- if (opdata->is_modal) {
- for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
- EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, opdata->ob_store[ob_index].em, true);
- EDBM_update_generic(opdata->ob_store[ob_index].em, false, true);
- }
- }
-
- edbm_bevel_exit(C, op);
-
- /* need to force redisplay or we may still view the modified result */
- ED_region_tag_redraw(CTX_wm_region(C));
+ BevelData *opdata = op->customdata;
+ if (opdata->is_modal) {
+ for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
+ EDBM_redo_state_free(
+ &opdata->ob_store[ob_index].mesh_backup, opdata->ob_store[ob_index].em, true);
+ EDBM_update_generic(opdata->ob_store[ob_index].em, false, true);
+ }
+ }
+
+ edbm_bevel_exit(C, op);
+
+ /* need to force redisplay or we may still view the modified result */
+ ED_region_tag_redraw(CTX_wm_region(C));
}
/* bevel! yay!!*/
static int edbm_bevel_exec(bContext *C, wmOperator *op)
{
- if (!edbm_bevel_init(C, op, false)) {
- return OPERATOR_CANCELLED;
- }
+ if (!edbm_bevel_init(C, op, false)) {
+ return OPERATOR_CANCELLED;
+ }
- if (!edbm_bevel_calc(op)) {
- edbm_bevel_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
+ if (!edbm_bevel_calc(op)) {
+ edbm_bevel_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
- edbm_bevel_exit(C, op);
+ edbm_bevel_exit(C, op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void edbm_bevel_calc_initial_length(wmOperator *op, const wmEvent *event, bool mode_changed)
{
- BevelData *opdata;
- float mlen[2], len, value, sc, st;
- int vmode;
-
- opdata = op->customdata;
- mlen[0] = opdata->mcenter[0] - event->mval[0];
- mlen[1] = opdata->mcenter[1] - event->mval[1];
- len = len_v2(mlen);
- vmode = opdata->value_mode;
- if (mode_changed || opdata->initial_length[vmode] == -1.0f) {
- /* If current value is not default start value, adjust len so that
- * the scaling and offset in edbm_bevel_mouse_set_value will
- * start at current value */
- value = (vmode == SEGMENTS_VALUE) ?
- opdata->segments : RNA_float_get(op->ptr, value_rna_name[vmode]);
- sc = opdata->scale[vmode];
- st = value_start[vmode];
- if (value != value_start[vmode]) {
- len = (st + sc * (len - MVAL_PIXEL_MARGIN) - value) / sc;
- }
- }
- opdata->initial_length[opdata->value_mode] = len;
+ BevelData *opdata;
+ float mlen[2], len, value, sc, st;
+ int vmode;
+
+ opdata = op->customdata;
+ mlen[0] = opdata->mcenter[0] - event->mval[0];
+ mlen[1] = opdata->mcenter[1] - event->mval[1];
+ len = len_v2(mlen);
+ vmode = opdata->value_mode;
+ if (mode_changed || opdata->initial_length[vmode] == -1.0f) {
+ /* If current value is not default start value, adjust len so that
+ * the scaling and offset in edbm_bevel_mouse_set_value will
+ * start at current value */
+ value = (vmode == SEGMENTS_VALUE) ? opdata->segments :
+ RNA_float_get(op->ptr, value_rna_name[vmode]);
+ sc = opdata->scale[vmode];
+ st = value_start[vmode];
+ if (value != value_start[vmode]) {
+ len = (st + sc * (len - MVAL_PIXEL_MARGIN) - value) / sc;
+ }
+ }
+ opdata->initial_length[opdata->value_mode] = len;
}
static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- BevelData *opdata;
- float center_3d[3];
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ BevelData *opdata;
+ float center_3d[3];
- if (!edbm_bevel_init(C, op, true)) {
- return OPERATOR_CANCELLED;
- }
+ if (!edbm_bevel_init(C, op, true)) {
+ return OPERATOR_CANCELLED;
+ }
- opdata = op->customdata;
+ opdata = op->customdata;
- /* initialize mouse values */
- if (!calculateTransformCenter(C, V3D_AROUND_CENTER_MEDIAN, center_3d, opdata->mcenter)) {
- /* in this case the tool will likely do nothing,
- * ideally this will never happen and should be checked for above */
- opdata->mcenter[0] = opdata->mcenter[1] = 0;
- }
+ /* initialize mouse values */
+ if (!calculateTransformCenter(C, V3D_AROUND_CENTER_MEDIAN, center_3d, opdata->mcenter)) {
+ /* in this case the tool will likely do nothing,
+ * ideally this will never happen and should be checked for above */
+ opdata->mcenter[0] = opdata->mcenter[1] = 0;
+ }
- /* for OFFSET_VALUE only, the scale is the size of a pixel under the mouse in 3d space */
- opdata->scale[OFFSET_VALUE] = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f;
- /* since we are affecting untransformed object but seeing in transformed space, compensate for that */
- opdata->scale[OFFSET_VALUE] /= opdata->max_obj_scale;
+ /* for OFFSET_VALUE only, the scale is the size of a pixel under the mouse in 3d space */
+ opdata->scale[OFFSET_VALUE] = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f;
+ /* since we are affecting untransformed object but seeing in transformed space, compensate for that */
+ opdata->scale[OFFSET_VALUE] /= opdata->max_obj_scale;
- edbm_bevel_calc_initial_length(op, event, false);
+ edbm_bevel_calc_initial_length(op, event, false);
- edbm_bevel_update_header(C, op);
+ edbm_bevel_update_header(C, op);
- if (!edbm_bevel_calc(op)) {
- edbm_bevel_cancel(C, op);
- ED_workspace_status_text(C, NULL);
- return OPERATOR_CANCELLED;
- }
+ if (!edbm_bevel_calc(op)) {
+ edbm_bevel_cancel(C, op);
+ ED_workspace_status_text(C, NULL);
+ return OPERATOR_CANCELLED;
+ }
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static void edbm_bevel_mouse_set_value(wmOperator *op, const wmEvent *event)
{
- BevelData *opdata = op->customdata;
- int vmode = opdata->value_mode;
- float mdiff[2];
- float value;
-
- mdiff[0] = opdata->mcenter[0] - event->mval[0];
- mdiff[1] = opdata->mcenter[1] - event->mval[1];
-
- value = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length[vmode]);
-
- /* Scale according to value mode */
- value = value_start[vmode] + value * opdata->scale[vmode];
-
- /* Fake shift-transform... */
- if (event->shift) {
- if (opdata->shift_value[vmode] < 0.0f) {
- opdata->shift_value[vmode] = (vmode == SEGMENTS_VALUE) ?
- opdata->segments : RNA_float_get(op->ptr, value_rna_name[vmode]);
- }
- value = (value - opdata->shift_value[vmode]) * 0.1f + opdata->shift_value[vmode];
- }
- else if (opdata->shift_value[vmode] >= 0.0f) {
- opdata->shift_value[vmode] = -1.0f;
- }
-
- /* clamp accordingto value mode, and store value back */
- CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]);
- if (vmode == SEGMENTS_VALUE) {
- opdata->segments = value;
- RNA_int_set(op->ptr, "segments", (int)(value + 0.5f));
- }
- else {
- RNA_float_set(op->ptr, value_rna_name[vmode], value);
- }
+ BevelData *opdata = op->customdata;
+ int vmode = opdata->value_mode;
+ float mdiff[2];
+ float value;
+
+ mdiff[0] = opdata->mcenter[0] - event->mval[0];
+ mdiff[1] = opdata->mcenter[1] - event->mval[1];
+
+ value = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length[vmode]);
+
+ /* Scale according to value mode */
+ value = value_start[vmode] + value * opdata->scale[vmode];
+
+ /* Fake shift-transform... */
+ if (event->shift) {
+ if (opdata->shift_value[vmode] < 0.0f) {
+ opdata->shift_value[vmode] = (vmode == SEGMENTS_VALUE) ?
+ opdata->segments :
+ RNA_float_get(op->ptr, value_rna_name[vmode]);
+ }
+ value = (value - opdata->shift_value[vmode]) * 0.1f + opdata->shift_value[vmode];
+ }
+ else if (opdata->shift_value[vmode] >= 0.0f) {
+ opdata->shift_value[vmode] = -1.0f;
+ }
+
+ /* clamp accordingto value mode, and store value back */
+ CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]);
+ if (vmode == SEGMENTS_VALUE) {
+ opdata->segments = value;
+ RNA_int_set(op->ptr, "segments", (int)(value + 0.5f));
+ }
+ else {
+ RNA_float_set(op->ptr, value_rna_name[vmode], value);
+ }
}
static void edbm_bevel_numinput_set_value(wmOperator *op)
{
- BevelData *opdata = op->customdata;
- float value;
- int vmode;
-
- vmode = opdata->value_mode;
- value = (vmode == SEGMENTS_VALUE) ?
- opdata->segments : RNA_float_get(op->ptr, value_rna_name[vmode]);
- applyNumInput(&opdata->num_input[vmode], &value);
- CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]);
- if (vmode == SEGMENTS_VALUE) {
- opdata->segments = value;
- RNA_int_set(op->ptr, "segments", (int)value);
- }
- else {
- RNA_float_set(op->ptr, value_rna_name[vmode], value);
- }
+ BevelData *opdata = op->customdata;
+ float value;
+ int vmode;
+
+ vmode = opdata->value_mode;
+ value = (vmode == SEGMENTS_VALUE) ? opdata->segments :
+ RNA_float_get(op->ptr, value_rna_name[vmode]);
+ applyNumInput(&opdata->num_input[vmode], &value);
+ CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]);
+ if (vmode == SEGMENTS_VALUE) {
+ opdata->segments = value;
+ RNA_int_set(op->ptr, "segments", (int)value);
+ }
+ else {
+ RNA_float_set(op->ptr, value_rna_name[vmode], value);
+ }
}
/* Hide one of offset or offset_pct, depending on offset_type */
-static bool edbm_bevel_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop)
+static bool edbm_bevel_poll_property(const bContext *UNUSED(C),
+ wmOperator *op,
+ const PropertyRNA *prop)
{
- const char *prop_id = RNA_property_identifier(prop);
+ const char *prop_id = RNA_property_identifier(prop);
- if (STRPREFIX(prop_id, "offset")) {
- int offset_type = RNA_enum_get(op->ptr, "offset_type");
+ if (STRPREFIX(prop_id, "offset")) {
+ int offset_type = RNA_enum_get(op->ptr, "offset_type");
- if (STREQ(prop_id, "offset") && offset_type == BEVEL_AMT_PERCENT)
- return false;
- else if (STREQ(prop_id, "offset_pct") && offset_type != BEVEL_AMT_PERCENT)
- return false;
- }
+ if (STREQ(prop_id, "offset") && offset_type == BEVEL_AMT_PERCENT)
+ return false;
+ else if (STREQ(prop_id, "offset_pct") && offset_type != BEVEL_AMT_PERCENT)
+ return false;
+ }
- return true;
+ return true;
}
wmKeyMap *bevel_modal_keymap(wmKeyConfig *keyconf)
{
- static const EnumPropertyItem modal_items[] = {
- {BEV_MODAL_CANCEL, "CANCEL", 0, "Cancel", "Cancel bevel"},
- {BEV_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", "Confirm bevel"},
- {BEV_MODAL_VALUE_OFFSET, "VALUE_OFFSET", 0, "Value is offset",
- "Value changes offset"},
- {BEV_MODAL_VALUE_PROFILE, "VALUE_PROFILE", 0, "Value is profile",
- "Value changes profile"},
- {BEV_MODAL_VALUE_SEGMENTS, "VALUE_SEGMENTS", 0, "Value is segments",
- "Value changes segments"},
- {BEV_MODAL_SEGMENTS_UP, "SEGMENTS_UP", 0, "Increase segments",
- "Increase segments"},
- {BEV_MODAL_SEGMENTS_DOWN, "SEGMENTS_DOWN", 0, "Decrease segments",
- "Decrease segments"},
- {BEV_MODAL_OFFSET_MODE_CHANGE, "OFFSET_MODE_CHANGE", 0, "Change offset mode",
- "Cycle through offset modes"},
- {BEV_MODAL_CLAMP_OVERLAP_TOGGLE, "CLAMP_OVERLAP_TOGGLE", 0, "Toggle clamp overlap",
- "Toggle clamp overlap flag"},
- {BEV_MODAL_VERTEX_ONLY_TOGGLE, "VERTEX_ONLY_TOGGLE", 0, "Toggle vertex only",
- "Toggle vertex only flag"},
- {BEV_MODAL_HARDEN_NORMALS_TOGGLE, "HARDEN_NORMALS_TOGGLE", 0, "Toggle harden normals",
- "Toggle harden normals flag"},
- {BEV_MODAL_MARK_SEAM_TOGGLE, "MARK_SEAM_TOGGLE", 0, "Toggle mark seam",
- "Toggle mark seam flag"},
- {BEV_MODAL_MARK_SHARP_TOGGLE, "MARK_SHARP_TOGGLE", 0, "Toggle mark sharp",
- "Toggle mark sharp flag"},
- {BEV_MODAL_OUTER_MITER_CHANGE, "OUTER_MITER_CHANGE", 0, "Change outer miter",
- "Cycle through outer miter kinds"},
- {BEV_MODAL_INNER_MITER_CHANGE, "INNER_MITER_CHANGE", 0, "Change inner miter",
- "Cycle through inner miter kinds"},
- {0, NULL, 0, NULL, NULL},
- };
-
- wmKeyMap *keymap = WM_modalkeymap_get(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);
-
- WM_modalkeymap_assign(keymap, "MESH_OT_bevel");
-
- return keymap;
+ static const EnumPropertyItem modal_items[] = {
+ {BEV_MODAL_CANCEL, "CANCEL", 0, "Cancel", "Cancel bevel"},
+ {BEV_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", "Confirm bevel"},
+ {BEV_MODAL_VALUE_OFFSET, "VALUE_OFFSET", 0, "Value is offset", "Value changes offset"},
+ {BEV_MODAL_VALUE_PROFILE, "VALUE_PROFILE", 0, "Value is profile", "Value changes profile"},
+ {BEV_MODAL_VALUE_SEGMENTS,
+ "VALUE_SEGMENTS",
+ 0,
+ "Value is segments",
+ "Value changes segments"},
+ {BEV_MODAL_SEGMENTS_UP, "SEGMENTS_UP", 0, "Increase segments", "Increase segments"},
+ {BEV_MODAL_SEGMENTS_DOWN, "SEGMENTS_DOWN", 0, "Decrease segments", "Decrease segments"},
+ {BEV_MODAL_OFFSET_MODE_CHANGE,
+ "OFFSET_MODE_CHANGE",
+ 0,
+ "Change offset mode",
+ "Cycle through offset modes"},
+ {BEV_MODAL_CLAMP_OVERLAP_TOGGLE,
+ "CLAMP_OVERLAP_TOGGLE",
+ 0,
+ "Toggle clamp overlap",
+ "Toggle clamp overlap flag"},
+ {BEV_MODAL_VERTEX_ONLY_TOGGLE,
+ "VERTEX_ONLY_TOGGLE",
+ 0,
+ "Toggle vertex only",
+ "Toggle vertex only flag"},
+ {BEV_MODAL_HARDEN_NORMALS_TOGGLE,
+ "HARDEN_NORMALS_TOGGLE",
+ 0,
+ "Toggle harden normals",
+ "Toggle harden normals flag"},
+ {BEV_MODAL_MARK_SEAM_TOGGLE,
+ "MARK_SEAM_TOGGLE",
+ 0,
+ "Toggle mark seam",
+ "Toggle mark seam flag"},
+ {BEV_MODAL_MARK_SHARP_TOGGLE,
+ "MARK_SHARP_TOGGLE",
+ 0,
+ "Toggle mark sharp",
+ "Toggle mark sharp flag"},
+ {BEV_MODAL_OUTER_MITER_CHANGE,
+ "OUTER_MITER_CHANGE",
+ 0,
+ "Change outer miter",
+ "Cycle through outer miter kinds"},
+ {BEV_MODAL_INNER_MITER_CHANGE,
+ "INNER_MITER_CHANGE",
+ 0,
+ "Change inner miter",
+ "Cycle through inner miter kinds"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ wmKeyMap *keymap = WM_modalkeymap_get(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);
+
+ WM_modalkeymap_assign(keymap, "MESH_OT_bevel");
+
+ return keymap;
}
static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- BevelData *opdata = op->customdata;
- const bool has_numinput = hasNumInput(&opdata->num_input[opdata->value_mode]);
- bool handled = false;
- short etype = event->type;
- short eval = event->val;
-
- /* When activated from toolbar, need to convert leftmouse release to confirm */
- if (etype == LEFTMOUSE && eval == KM_RELEASE &&
- RNA_boolean_get(op->ptr, "release_confirm"))
- {
- etype = EVT_MODAL_MAP;
- eval = BEV_MODAL_CONFIRM;
- }
- /* Modal numinput active, try to handle numeric inputs first... */
- if (etype != EVT_MODAL_MAP && eval == KM_PRESS && has_numinput &&
- handleNumInput(C, &opdata->num_input[opdata->value_mode], event))
- {
- edbm_bevel_numinput_set_value(op);
- edbm_bevel_calc(op);
- edbm_bevel_update_header(C, op);
- return OPERATOR_RUNNING_MODAL;
- }
- else if (etype == MOUSEMOVE) {
- if (!has_numinput) {
- edbm_bevel_mouse_set_value(op, event);
- edbm_bevel_calc(op);
- edbm_bevel_update_header(C, op);
- handled = true;
- }
- }
- else if (etype == MOUSEPAN) {
- float delta = 0.02f * (event->y - event->prevy);
- if (opdata->segments >= 1 && opdata->segments + delta < 1)
- opdata->segments = 1;
- else
- opdata->segments += delta;
- RNA_int_set(op->ptr, "segments", (int)opdata->segments);
- edbm_bevel_calc(op);
- edbm_bevel_update_header(C, op);
- handled = true;
- }
- else if (etype == EVT_MODAL_MAP) {
- switch (eval) {
- case BEV_MODAL_CANCEL:
- edbm_bevel_cancel(C, op);
- ED_workspace_status_text(C, NULL);
- return OPERATOR_CANCELLED;
-
- case BEV_MODAL_CONFIRM:
- edbm_bevel_calc(op);
- edbm_bevel_exit(C, op);
- ED_workspace_status_text(C, NULL);
- return OPERATOR_FINISHED;
-
- case BEV_MODAL_SEGMENTS_UP:
- opdata->segments = opdata->segments + 1;
- RNA_int_set(op->ptr, "segments", (int)opdata->segments);
- edbm_bevel_calc(op);
- edbm_bevel_update_header(C, op);
- handled = true;
- break;
-
- case BEV_MODAL_SEGMENTS_DOWN:
- opdata->segments = max_ff(opdata->segments - 1, 1);
- RNA_int_set(op->ptr, "segments", (int)opdata->segments);
- edbm_bevel_calc(op);
- edbm_bevel_update_header(C, op);
- handled = true;
- break;
-
- case BEV_MODAL_OFFSET_MODE_CHANGE:
- {
- int type = RNA_enum_get(op->ptr, "offset_type");
- type++;
- if (type > BEVEL_AMT_PERCENT) {
- type = BEVEL_AMT_OFFSET;
- }
- if (opdata->value_mode == OFFSET_VALUE && type == BEVEL_AMT_PERCENT)
- opdata->value_mode = OFFSET_VALUE_PERCENT;
- else if (opdata->value_mode == OFFSET_VALUE_PERCENT && type != BEVEL_AMT_PERCENT)
- opdata->value_mode = OFFSET_VALUE;
- RNA_enum_set(op->ptr, "offset_type", type);
- if (opdata->initial_length[opdata->value_mode] == -1.0f)
- edbm_bevel_calc_initial_length(op, event, true);
- }
- /* Update offset accordingly to new offset_type. */
- if (!has_numinput &&
- (opdata->value_mode == OFFSET_VALUE || opdata->value_mode == OFFSET_VALUE_PERCENT))
- {
- edbm_bevel_mouse_set_value(op, event);
- }
- edbm_bevel_calc(op);
- edbm_bevel_update_header(C, op);
- handled = true;
- break;
-
- case BEV_MODAL_CLAMP_OVERLAP_TOGGLE:
- {
- bool clamp_overlap = RNA_boolean_get(op->ptr, "clamp_overlap");
- RNA_boolean_set(op->ptr, "clamp_overlap", !clamp_overlap);
- edbm_bevel_calc(op);
- edbm_bevel_update_header(C, op);
- handled = true;
- break;
- }
-
- case BEV_MODAL_VALUE_OFFSET:
- opdata->value_mode = OFFSET_VALUE;
- edbm_bevel_calc_initial_length(op, event, true);
- break;
-
- case BEV_MODAL_VALUE_PROFILE:
- opdata->value_mode = PROFILE_VALUE;
- edbm_bevel_calc_initial_length(op, event, true);
- break;
-
- case BEV_MODAL_VALUE_SEGMENTS:
- opdata->value_mode = SEGMENTS_VALUE;
- edbm_bevel_calc_initial_length(op, event, true);
- break;
-
- case BEV_MODAL_VERTEX_ONLY_TOGGLE:
- {
- bool vertex_only = RNA_boolean_get(op->ptr, "vertex_only");
- RNA_boolean_set(op->ptr, "vertex_only", !vertex_only);
- edbm_bevel_calc(op);
- edbm_bevel_update_header(C, op);
- handled = true;
- break;
- }
-
- case BEV_MODAL_MARK_SEAM_TOGGLE:
- {
- bool mark_seam = RNA_boolean_get(op->ptr, "mark_seam");
- RNA_boolean_set(op->ptr, "mark_seam", !mark_seam);
- edbm_bevel_calc(op);
- edbm_bevel_update_header(C, op);
- handled = true;
- break;
- }
-
- case BEV_MODAL_MARK_SHARP_TOGGLE:
- {
- bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp");
- RNA_boolean_set(op->ptr, "mark_sharp", !mark_sharp);
- edbm_bevel_calc(op);
- edbm_bevel_update_header(C, op);
- handled = true;
- break;
- }
-
- case BEV_MODAL_INNER_MITER_CHANGE:
- {
- int miter_inner = RNA_enum_get(op->ptr, "miter_inner");
- miter_inner++;
- if (miter_inner == BEVEL_MITER_PATCH)
- miter_inner++; /* no patch option for inner miter */
- if (miter_inner > BEVEL_MITER_ARC)
- miter_inner = BEVEL_MITER_SHARP;
- RNA_enum_set(op->ptr, "miter_inner", miter_inner);
- edbm_bevel_calc(op);
- edbm_bevel_update_header(C, op);
- handled = true;
- break;
- }
-
- case BEV_MODAL_OUTER_MITER_CHANGE:
- {
- int miter_outer = RNA_enum_get(op->ptr, "miter_outer");
- miter_outer++;
- if (miter_outer > BEVEL_MITER_ARC)
- miter_outer = BEVEL_MITER_SHARP;
- RNA_enum_set(op->ptr, "miter_outer", miter_outer);
- edbm_bevel_calc(op);
- edbm_bevel_update_header(C, op);
- handled = true;
- break;
- }
-
- case BEV_MODAL_HARDEN_NORMALS_TOGGLE:
- {
- bool harden_normals = RNA_boolean_get(op->ptr, "harden_normals");
- RNA_boolean_set(op->ptr, "harden_normals", !harden_normals);
- edbm_bevel_calc(op);
- edbm_bevel_update_header(C, op);
- handled = true;
- break;
- }
- }
- }
-
- /* Modal numinput inactive, try to handle numeric inputs last... */
- if (!handled && eval == KM_PRESS && handleNumInput(C, &opdata->num_input[opdata->value_mode], event)) {
- edbm_bevel_numinput_set_value(op);
- edbm_bevel_calc(op);
- edbm_bevel_update_header(C, op);
- return OPERATOR_RUNNING_MODAL;
- }
-
- return OPERATOR_RUNNING_MODAL;
+ BevelData *opdata = op->customdata;
+ const bool has_numinput = hasNumInput(&opdata->num_input[opdata->value_mode]);
+ bool handled = false;
+ short etype = event->type;
+ short eval = event->val;
+
+ /* When activated from toolbar, need to convert leftmouse release to confirm */
+ if (etype == LEFTMOUSE && eval == KM_RELEASE && RNA_boolean_get(op->ptr, "release_confirm")) {
+ etype = EVT_MODAL_MAP;
+ eval = BEV_MODAL_CONFIRM;
+ }
+ /* Modal numinput active, try to handle numeric inputs first... */
+ if (etype != EVT_MODAL_MAP && eval == KM_PRESS && has_numinput &&
+ handleNumInput(C, &opdata->num_input[opdata->value_mode], event)) {
+ edbm_bevel_numinput_set_value(op);
+ edbm_bevel_calc(op);
+ edbm_bevel_update_header(C, op);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else if (etype == MOUSEMOVE) {
+ if (!has_numinput) {
+ edbm_bevel_mouse_set_value(op, event);
+ edbm_bevel_calc(op);
+ edbm_bevel_update_header(C, op);
+ handled = true;
+ }
+ }
+ else if (etype == MOUSEPAN) {
+ float delta = 0.02f * (event->y - event->prevy);
+ if (opdata->segments >= 1 && opdata->segments + delta < 1)
+ opdata->segments = 1;
+ else
+ opdata->segments += delta;
+ RNA_int_set(op->ptr, "segments", (int)opdata->segments);
+ edbm_bevel_calc(op);
+ edbm_bevel_update_header(C, op);
+ handled = true;
+ }
+ else if (etype == EVT_MODAL_MAP) {
+ switch (eval) {
+ case BEV_MODAL_CANCEL:
+ edbm_bevel_cancel(C, op);
+ ED_workspace_status_text(C, NULL);
+ return OPERATOR_CANCELLED;
+
+ case BEV_MODAL_CONFIRM:
+ edbm_bevel_calc(op);
+ edbm_bevel_exit(C, op);
+ ED_workspace_status_text(C, NULL);
+ return OPERATOR_FINISHED;
+
+ case BEV_MODAL_SEGMENTS_UP:
+ opdata->segments = opdata->segments + 1;
+ RNA_int_set(op->ptr, "segments", (int)opdata->segments);
+ edbm_bevel_calc(op);
+ edbm_bevel_update_header(C, op);
+ handled = true;
+ break;
+
+ case BEV_MODAL_SEGMENTS_DOWN:
+ opdata->segments = max_ff(opdata->segments - 1, 1);
+ RNA_int_set(op->ptr, "segments", (int)opdata->segments);
+ edbm_bevel_calc(op);
+ edbm_bevel_update_header(C, op);
+ handled = true;
+ break;
+
+ case BEV_MODAL_OFFSET_MODE_CHANGE: {
+ int type = RNA_enum_get(op->ptr, "offset_type");
+ type++;
+ if (type > BEVEL_AMT_PERCENT) {
+ type = BEVEL_AMT_OFFSET;
+ }
+ if (opdata->value_mode == OFFSET_VALUE && type == BEVEL_AMT_PERCENT)
+ opdata->value_mode = OFFSET_VALUE_PERCENT;
+ else if (opdata->value_mode == OFFSET_VALUE_PERCENT && type != BEVEL_AMT_PERCENT)
+ opdata->value_mode = OFFSET_VALUE;
+ RNA_enum_set(op->ptr, "offset_type", type);
+ if (opdata->initial_length[opdata->value_mode] == -1.0f)
+ edbm_bevel_calc_initial_length(op, event, true);
+ }
+ /* Update offset accordingly to new offset_type. */
+ if (!has_numinput &&
+ (opdata->value_mode == OFFSET_VALUE || opdata->value_mode == OFFSET_VALUE_PERCENT)) {
+ edbm_bevel_mouse_set_value(op, event);
+ }
+ edbm_bevel_calc(op);
+ edbm_bevel_update_header(C, op);
+ handled = true;
+ break;
+
+ case BEV_MODAL_CLAMP_OVERLAP_TOGGLE: {
+ bool clamp_overlap = RNA_boolean_get(op->ptr, "clamp_overlap");
+ RNA_boolean_set(op->ptr, "clamp_overlap", !clamp_overlap);
+ edbm_bevel_calc(op);
+ edbm_bevel_update_header(C, op);
+ handled = true;
+ break;
+ }
+
+ case BEV_MODAL_VALUE_OFFSET:
+ opdata->value_mode = OFFSET_VALUE;
+ edbm_bevel_calc_initial_length(op, event, true);
+ break;
+
+ case BEV_MODAL_VALUE_PROFILE:
+ opdata->value_mode = PROFILE_VALUE;
+ edbm_bevel_calc_initial_length(op, event, true);
+ break;
+
+ case BEV_MODAL_VALUE_SEGMENTS:
+ opdata->value_mode = SEGMENTS_VALUE;
+ edbm_bevel_calc_initial_length(op, event, true);
+ break;
+
+ case BEV_MODAL_VERTEX_ONLY_TOGGLE: {
+ bool vertex_only = RNA_boolean_get(op->ptr, "vertex_only");
+ RNA_boolean_set(op->ptr, "vertex_only", !vertex_only);
+ edbm_bevel_calc(op);
+ edbm_bevel_update_header(C, op);
+ handled = true;
+ break;
+ }
+
+ case BEV_MODAL_MARK_SEAM_TOGGLE: {
+ bool mark_seam = RNA_boolean_get(op->ptr, "mark_seam");
+ RNA_boolean_set(op->ptr, "mark_seam", !mark_seam);
+ edbm_bevel_calc(op);
+ edbm_bevel_update_header(C, op);
+ handled = true;
+ break;
+ }
+
+ case BEV_MODAL_MARK_SHARP_TOGGLE: {
+ bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp");
+ RNA_boolean_set(op->ptr, "mark_sharp", !mark_sharp);
+ edbm_bevel_calc(op);
+ edbm_bevel_update_header(C, op);
+ handled = true;
+ break;
+ }
+
+ case BEV_MODAL_INNER_MITER_CHANGE: {
+ int miter_inner = RNA_enum_get(op->ptr, "miter_inner");
+ miter_inner++;
+ if (miter_inner == BEVEL_MITER_PATCH)
+ miter_inner++; /* no patch option for inner miter */
+ if (miter_inner > BEVEL_MITER_ARC)
+ miter_inner = BEVEL_MITER_SHARP;
+ RNA_enum_set(op->ptr, "miter_inner", miter_inner);
+ edbm_bevel_calc(op);
+ edbm_bevel_update_header(C, op);
+ handled = true;
+ break;
+ }
+
+ case BEV_MODAL_OUTER_MITER_CHANGE: {
+ int miter_outer = RNA_enum_get(op->ptr, "miter_outer");
+ miter_outer++;
+ if (miter_outer > BEVEL_MITER_ARC)
+ miter_outer = BEVEL_MITER_SHARP;
+ RNA_enum_set(op->ptr, "miter_outer", miter_outer);
+ edbm_bevel_calc(op);
+ edbm_bevel_update_header(C, op);
+ handled = true;
+ break;
+ }
+
+ case BEV_MODAL_HARDEN_NORMALS_TOGGLE: {
+ bool harden_normals = RNA_boolean_get(op->ptr, "harden_normals");
+ RNA_boolean_set(op->ptr, "harden_normals", !harden_normals);
+ edbm_bevel_calc(op);
+ edbm_bevel_update_header(C, op);
+ handled = true;
+ break;
+ }
+ }
+ }
+
+ /* Modal numinput inactive, try to handle numeric inputs last... */
+ if (!handled && eval == KM_PRESS &&
+ handleNumInput(C, &opdata->num_input[opdata->value_mode], event)) {
+ edbm_bevel_numinput_set_value(op);
+ edbm_bevel_calc(op);
+ edbm_bevel_update_header(C, op);
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
void MESH_OT_bevel(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- static const EnumPropertyItem offset_type_items[] = {
- {BEVEL_AMT_OFFSET, "OFFSET", 0, "Offset", "Amount is offset of new edges from original"},
- {BEVEL_AMT_WIDTH, "WIDTH", 0, "Width", "Amount is width of new face"},
- {BEVEL_AMT_DEPTH, "DEPTH", 0, "Depth", "Amount is perpendicular distance from original edge to bevel face"},
- {BEVEL_AMT_PERCENT, "PERCENT", 0, "Percent", "Amount is percent of adjacent edge length"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem face_strength_mode_items[] = {
- {BEVEL_FACE_STRENGTH_NONE, "NONE", 0, "None", "Do not set face strength"},
- {BEVEL_FACE_STRENGTH_NEW, "NEW", 0, "New", "Set face strength on new faces only"},
- {BEVEL_FACE_STRENGTH_AFFECTED, "AFFECTED", 0, "Affected", "Set face strength on new and modified faces only"},
- {BEVEL_FACE_STRENGTH_ALL, "ALL", 0, "All", "Set face strength on all faces"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem miter_outer_items[] = {
- {BEVEL_MITER_SHARP, "SHARP", 0, "Sharp", "Outside of miter is sharp"},
- {BEVEL_MITER_PATCH, "PATCH", 0, "Patch", "Outside of miter is squared-off patch"},
- {BEVEL_MITER_ARC, "ARC", 0, "Arc", "Outside of miter is arc"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem miter_inner_items[] = {
- {BEVEL_MITER_SHARP, "SHARP", 0, "Sharp", "Inside of miter is sharp"},
- {BEVEL_MITER_ARC, "ARC", 0, "Arc", "Inside of miter is arc"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Bevel";
- ot->description = "Edge Bevel";
- ot->idname = "MESH_OT_bevel";
-
- /* api callbacks */
- ot->exec = edbm_bevel_exec;
- ot->invoke = edbm_bevel_invoke;
- ot->modal = edbm_bevel_modal;
- ot->cancel = edbm_bevel_cancel;
- ot->poll = ED_operator_editmesh;
- ot->poll_property = edbm_bevel_poll_property;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
-
- RNA_def_enum(ot->srna, "offset_type", offset_type_items, 0, "Width Type", "What distance Width measures");
- prop = RNA_def_property(ot->srna, "offset", PROP_FLOAT, PROP_DISTANCE);
- RNA_def_property_range(prop, 0.0, 1e6);
- RNA_def_property_ui_range(prop, 0.0f, 100.0, 1, 3);
- RNA_def_property_ui_text(prop, "Width", "Bevel amount");
- prop = RNA_def_property(ot->srna, "offset_pct", PROP_FLOAT, PROP_PERCENTAGE);
- RNA_def_property_range(prop, 0.0, 100);
- RNA_def_property_ui_text(prop, "Width Percent", "Bevel amount for percentage method");
- RNA_def_int(ot->srna, "segments", 1, 1, SEGMENTS_HARD_MAX, "Segments", "Segments for curved edge", 1, 100);
- RNA_def_float(
- ot->srna, "profile", 0.5f, PROFILE_HARD_MIN, 1.0f, "Profile",
- "Controls profile shape (0.5 = round)", PROFILE_HARD_MIN, 1.0f);
- RNA_def_boolean(ot->srna, "vertex_only", false, "Vertex Only", "Bevel only vertices");
- RNA_def_boolean(
- ot->srna, "clamp_overlap", false, "Clamp Overlap",
- "Do not allow beveled edges/vertices to overlap each other");
- RNA_def_boolean(ot->srna, "loop_slide", true, "Loop Slide", "Prefer slide along edge to even widths");
- RNA_def_boolean(ot->srna, "mark_seam", false, "Mark Seams", "Mark Seams along beveled edges");
- RNA_def_boolean(ot->srna, "mark_sharp", false, "Mark Sharp", "Mark beveled edges as sharp");
- RNA_def_int(
- ot->srna, "material", -1, -1, INT_MAX, "Material",
- "Material for bevel faces (-1 means use adjacent faces)", -1, 100);
- RNA_def_boolean(
- ot->srna, "harden_normals", false, "Harden Normals",
- "Match normals of new faces to adjacent faces");
- RNA_def_enum(
- ot->srna, "face_strength_mode", face_strength_mode_items, BEVEL_FACE_STRENGTH_NONE,
- "Face Strength Mode", "Whether to set face strength, and which faces to set face strength on");
- RNA_def_enum(
- ot->srna, "miter_outer", miter_outer_items, BEVEL_MITER_SHARP,
- "Outer Miter", "Pattern to use for outside of miters");
- RNA_def_enum(
- ot->srna, "miter_inner", miter_inner_items, BEVEL_MITER_SHARP,
- "Inner Miter", "Pattern to use for inside of miters");
- RNA_def_float(
- ot->srna, "spread", 0.1f, 0.0f, 1e6f, "Spread",
- "Amount to spread arcs for arc inner miters", 0.0f, 100.0f);
- prop = RNA_def_boolean(ot->srna, "release_confirm", 0, "Confirm on Release", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
-
+ PropertyRNA *prop;
+
+ static const EnumPropertyItem offset_type_items[] = {
+ {BEVEL_AMT_OFFSET, "OFFSET", 0, "Offset", "Amount is offset of new edges from original"},
+ {BEVEL_AMT_WIDTH, "WIDTH", 0, "Width", "Amount is width of new face"},
+ {BEVEL_AMT_DEPTH,
+ "DEPTH",
+ 0,
+ "Depth",
+ "Amount is perpendicular distance from original edge to bevel face"},
+ {BEVEL_AMT_PERCENT, "PERCENT", 0, "Percent", "Amount is percent of adjacent edge length"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem face_strength_mode_items[] = {
+ {BEVEL_FACE_STRENGTH_NONE, "NONE", 0, "None", "Do not set face strength"},
+ {BEVEL_FACE_STRENGTH_NEW, "NEW", 0, "New", "Set face strength on new faces only"},
+ {BEVEL_FACE_STRENGTH_AFFECTED,
+ "AFFECTED",
+ 0,
+ "Affected",
+ "Set face strength on new and modified faces only"},
+ {BEVEL_FACE_STRENGTH_ALL, "ALL", 0, "All", "Set face strength on all faces"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem miter_outer_items[] = {
+ {BEVEL_MITER_SHARP, "SHARP", 0, "Sharp", "Outside of miter is sharp"},
+ {BEVEL_MITER_PATCH, "PATCH", 0, "Patch", "Outside of miter is squared-off patch"},
+ {BEVEL_MITER_ARC, "ARC", 0, "Arc", "Outside of miter is arc"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem miter_inner_items[] = {
+ {BEVEL_MITER_SHARP, "SHARP", 0, "Sharp", "Inside of miter is sharp"},
+ {BEVEL_MITER_ARC, "ARC", 0, "Arc", "Inside of miter is arc"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Bevel";
+ ot->description = "Edge Bevel";
+ ot->idname = "MESH_OT_bevel";
+
+ /* api callbacks */
+ ot->exec = edbm_bevel_exec;
+ ot->invoke = edbm_bevel_invoke;
+ ot->modal = edbm_bevel_modal;
+ ot->cancel = edbm_bevel_cancel;
+ ot->poll = ED_operator_editmesh;
+ ot->poll_property = edbm_bevel_poll_property;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
+
+ RNA_def_enum(
+ ot->srna, "offset_type", offset_type_items, 0, "Width Type", "What distance Width measures");
+ prop = RNA_def_property(ot->srna, "offset", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_range(prop, 0.0, 1e6);
+ RNA_def_property_ui_range(prop, 0.0f, 100.0, 1, 3);
+ RNA_def_property_ui_text(prop, "Width", "Bevel amount");
+ prop = RNA_def_property(ot->srna, "offset_pct", PROP_FLOAT, PROP_PERCENTAGE);
+ RNA_def_property_range(prop, 0.0, 100);
+ RNA_def_property_ui_text(prop, "Width Percent", "Bevel amount for percentage method");
+ RNA_def_int(ot->srna,
+ "segments",
+ 1,
+ 1,
+ SEGMENTS_HARD_MAX,
+ "Segments",
+ "Segments for curved edge",
+ 1,
+ 100);
+ RNA_def_float(ot->srna,
+ "profile",
+ 0.5f,
+ PROFILE_HARD_MIN,
+ 1.0f,
+ "Profile",
+ "Controls profile shape (0.5 = round)",
+ PROFILE_HARD_MIN,
+ 1.0f);
+ RNA_def_boolean(ot->srna, "vertex_only", false, "Vertex Only", "Bevel only vertices");
+ RNA_def_boolean(ot->srna,
+ "clamp_overlap",
+ false,
+ "Clamp Overlap",
+ "Do not allow beveled edges/vertices to overlap each other");
+ RNA_def_boolean(
+ ot->srna, "loop_slide", true, "Loop Slide", "Prefer slide along edge to even widths");
+ RNA_def_boolean(ot->srna, "mark_seam", false, "Mark Seams", "Mark Seams along beveled edges");
+ RNA_def_boolean(ot->srna, "mark_sharp", false, "Mark Sharp", "Mark beveled edges as sharp");
+ RNA_def_int(ot->srna,
+ "material",
+ -1,
+ -1,
+ INT_MAX,
+ "Material",
+ "Material for bevel faces (-1 means use adjacent faces)",
+ -1,
+ 100);
+ RNA_def_boolean(ot->srna,
+ "harden_normals",
+ false,
+ "Harden Normals",
+ "Match normals of new faces to adjacent faces");
+ RNA_def_enum(ot->srna,
+ "face_strength_mode",
+ face_strength_mode_items,
+ BEVEL_FACE_STRENGTH_NONE,
+ "Face Strength Mode",
+ "Whether to set face strength, and which faces to set face strength on");
+ RNA_def_enum(ot->srna,
+ "miter_outer",
+ miter_outer_items,
+ BEVEL_MITER_SHARP,
+ "Outer Miter",
+ "Pattern to use for outside of miters");
+ RNA_def_enum(ot->srna,
+ "miter_inner",
+ miter_inner_items,
+ BEVEL_MITER_SHARP,
+ "Inner Miter",
+ "Pattern to use for inside of miters");
+ RNA_def_float(ot->srna,
+ "spread",
+ 0.1f,
+ 0.0f,
+ 1e6f,
+ "Spread",
+ "Amount to spread arcs for arc inner miters",
+ 0.0f,
+ 100.0f);
+ prop = RNA_def_boolean(ot->srna, "release_confirm", 0, "Confirm on Release", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c
index 61531109a01..bc60ff9274f 100644
--- a/source/blender/editors/mesh/editmesh_bisect.c
+++ b/source/blender/editors/mesh/editmesh_bisect.c
@@ -48,13 +48,13 @@
#include "UI_resources.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
#define USE_GIZMO
#ifdef USE_GIZMO
-#include "ED_gizmo_library.h"
-#include "ED_undo.h"
+# include "ED_gizmo_library.h"
+# include "ED_undo.h"
#endif
static int mesh_bisect_exec(bContext *C, wmOperator *op);
@@ -63,315 +63,334 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op);
/* Model Helpers */
typedef struct {
- /* modal only */
-
- /* Aligned with objects array. */
- struct {
- BMBackup mesh;
- bool is_valid;
- bool is_dirty;
- } *backup;
- int backup_len;
- short gizmo_flag;
+ /* modal only */
+
+ /* Aligned with objects array. */
+ struct {
+ BMBackup mesh;
+ bool is_valid;
+ bool is_dirty;
+ } * backup;
+ int backup_len;
+ short gizmo_flag;
} BisectData;
-static void mesh_bisect_interactive_calc(
- bContext *C, wmOperator *op,
- float plane_co[3], float plane_no[3])
+static void mesh_bisect_interactive_calc(bContext *C,
+ wmOperator *op,
+ float plane_co[3],
+ float plane_no[3])
{
- View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
-
- int x_start = RNA_int_get(op->ptr, "xstart");
- int y_start = RNA_int_get(op->ptr, "ystart");
- int x_end = RNA_int_get(op->ptr, "xend");
- int y_end = RNA_int_get(op->ptr, "yend");
-
- /* reference location (some point in front of the view) for finding a point on a plane */
- const float *co_ref = rv3d->ofs;
- float co_a_ss[2] = {x_start, y_start}, co_b_ss[2] = {x_end, y_end}, co_delta_ss[2];
- float co_a[3], co_b[3];
- const float zfac = ED_view3d_calc_zfac(rv3d, co_ref, NULL);
-
- /* view vector */
- ED_view3d_win_to_vector(ar, 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);
-
- /* 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);
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ int x_start = RNA_int_get(op->ptr, "xstart");
+ int y_start = RNA_int_get(op->ptr, "ystart");
+ int x_end = RNA_int_get(op->ptr, "xend");
+ int y_end = RNA_int_get(op->ptr, "yend");
+
+ /* reference location (some point in front of the view) for finding a point on a plane */
+ const float *co_ref = rv3d->ofs;
+ float co_a_ss[2] = {x_start, y_start}, co_b_ss[2] = {x_end, y_end}, co_delta_ss[2];
+ float co_a[3], co_b[3];
+ const float zfac = ED_view3d_calc_zfac(rv3d, co_ref, NULL);
+
+ /* view vector */
+ ED_view3d_win_to_vector(ar, 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);
+
+ /* 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);
}
static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- int valid_objects = 0;
-
- /* If the properties are set or there is no rv3d,
- * skip model and exec immediately. */
- if ((CTX_wm_region_view3d(C) == NULL) ||
- (RNA_struct_property_is_set(op->ptr, "plane_co") &&
- RNA_struct_property_is_set(op->ptr, "plane_no")))
- {
- return mesh_bisect_exec(C, op);
- }
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totedgesel != 0) {
- valid_objects++;
- }
- }
-
- if (valid_objects == 0) {
- BKE_report(op->reports, RPT_ERROR, "Selected edges/faces required");
- MEM_freeN(objects);
- return OPERATOR_CANCELLED;
- }
-
- int ret = WM_gesture_straightline_invoke(C, op, event);
- if (ret & OPERATOR_RUNNING_MODAL) {
- View3D *v3d = CTX_wm_view3d(C);
-
- wmGesture *gesture = op->customdata;
- BisectData *opdata;
-
- opdata = MEM_mallocN(sizeof(BisectData), "inset_operator_data");
- gesture->userdata = opdata;
-
- opdata->backup_len = objects_len;
- opdata->backup = MEM_callocN(sizeof(*opdata->backup) * objects_len, __func__);
-
- /* Store the mesh backups. */
- 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) {
- opdata->backup[ob_index].is_valid = true;
- opdata->backup[ob_index].mesh = EDBM_redo_state_store(em);
- }
- }
-
- /* Misc other vars. */
- G.moving = G_TRANSFORM_EDIT;
- opdata->gizmo_flag = v3d->gizmo_flag;
- v3d->gizmo_flag = V3D_GIZMO_HIDE;
-
- /* Initialize modal callout. */
- ED_workspace_status_text(C, IFACE_("LMB: Click and drag to draw cut line"));
- }
- MEM_freeN(objects);
- return ret;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ int valid_objects = 0;
+
+ /* If the properties are set or there is no rv3d,
+ * skip model and exec immediately. */
+ if ((CTX_wm_region_view3d(C) == NULL) || (RNA_struct_property_is_set(op->ptr, "plane_co") &&
+ RNA_struct_property_is_set(op->ptr, "plane_no"))) {
+ return mesh_bisect_exec(C, op);
+ }
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totedgesel != 0) {
+ valid_objects++;
+ }
+ }
+
+ if (valid_objects == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Selected edges/faces required");
+ MEM_freeN(objects);
+ return OPERATOR_CANCELLED;
+ }
+
+ int ret = WM_gesture_straightline_invoke(C, op, event);
+ if (ret & OPERATOR_RUNNING_MODAL) {
+ View3D *v3d = CTX_wm_view3d(C);
+
+ wmGesture *gesture = op->customdata;
+ BisectData *opdata;
+
+ opdata = MEM_mallocN(sizeof(BisectData), "inset_operator_data");
+ gesture->userdata = opdata;
+
+ opdata->backup_len = objects_len;
+ opdata->backup = MEM_callocN(sizeof(*opdata->backup) * objects_len, __func__);
+
+ /* Store the mesh backups. */
+ 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) {
+ opdata->backup[ob_index].is_valid = true;
+ opdata->backup[ob_index].mesh = EDBM_redo_state_store(em);
+ }
+ }
+
+ /* Misc other vars. */
+ G.moving = G_TRANSFORM_EDIT;
+ opdata->gizmo_flag = v3d->gizmo_flag;
+ v3d->gizmo_flag = V3D_GIZMO_HIDE;
+
+ /* Initialize modal callout. */
+ ED_workspace_status_text(C, IFACE_("LMB: Click and drag to draw cut line"));
+ }
+ MEM_freeN(objects);
+ return ret;
}
static void edbm_bisect_exit(bContext *C, BisectData *opdata)
{
- View3D *v3d = CTX_wm_view3d(C);
- v3d->gizmo_flag = opdata->gizmo_flag;
- G.moving = 0;
-
- for (int ob_index = 0; ob_index < opdata->backup_len; ob_index++) {
- if (opdata->backup[ob_index].is_valid) {
- EDBM_redo_state_free(&opdata->backup[ob_index].mesh, NULL, false);
- }
- }
- MEM_freeN(opdata->backup);
+ View3D *v3d = CTX_wm_view3d(C);
+ v3d->gizmo_flag = opdata->gizmo_flag;
+ G.moving = 0;
+
+ for (int ob_index = 0; ob_index < opdata->backup_len; ob_index++) {
+ if (opdata->backup[ob_index].is_valid) {
+ EDBM_redo_state_free(&opdata->backup[ob_index].mesh, NULL, false);
+ }
+ }
+ MEM_freeN(opdata->backup);
}
static int mesh_bisect_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- wmGesture *gesture = op->customdata;
- BisectData *opdata = gesture->userdata;
- BisectData opdata_back = *opdata; /* annoyance, WM_gesture_straightline_modal, frees */
- int ret;
-
- ret = WM_gesture_straightline_modal(C, op, event);
-
- /* update or clear modal callout */
- if (event->type == EVT_MODAL_MAP) {
- if (event->val == GESTURE_MODAL_BEGIN) {
- ED_workspace_status_text(C, IFACE_("LMB: Release to confirm cut line"));
- }
- else {
- ED_workspace_status_text(C, NULL);
- }
- }
-
- if (ret & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) {
- edbm_bisect_exit(C, &opdata_back);
+ wmGesture *gesture = op->customdata;
+ BisectData *opdata = gesture->userdata;
+ BisectData opdata_back = *opdata; /* annoyance, WM_gesture_straightline_modal, frees */
+ int ret;
+
+ ret = WM_gesture_straightline_modal(C, op, event);
+
+ /* update or clear modal callout */
+ if (event->type == EVT_MODAL_MAP) {
+ if (event->val == GESTURE_MODAL_BEGIN) {
+ ED_workspace_status_text(C, IFACE_("LMB: Release to confirm cut line"));
+ }
+ else {
+ ED_workspace_status_text(C, NULL);
+ }
+ }
+
+ if (ret & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) {
+ edbm_bisect_exit(C, &opdata_back);
#ifdef USE_GIZMO
- /* Setup gizmos */
- {
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d && (v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) {
- WM_gizmo_group_type_ensure("MESH_GGT_bisect");
- }
- }
+ /* Setup gizmos */
+ {
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d && (v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) {
+ WM_gizmo_group_type_ensure("MESH_GGT_bisect");
+ }
+ }
#endif
- }
+ }
- return ret;
+ return ret;
}
/* End Model Helpers */
/* -------------------------------------------------------------------- */
-
-
static int mesh_bisect_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
-
- /* both can be NULL, fallbacks values are used */
- RegionView3D *rv3d = ED_view3d_context_rv3d(C);
-
- int ret = OPERATOR_CANCELLED;
-
- float plane_co[3];
- float plane_no[3];
- float imat[4][4];
-
- const float thresh = RNA_float_get(op->ptr, "threshold");
- const bool use_fill = RNA_boolean_get(op->ptr, "use_fill");
- const bool clear_inner = RNA_boolean_get(op->ptr, "clear_inner");
- const bool clear_outer = RNA_boolean_get(op->ptr, "clear_outer");
-
- PropertyRNA *prop_plane_co;
- PropertyRNA *prop_plane_no;
-
- prop_plane_co = RNA_struct_find_property(op->ptr, "plane_co");
- if (RNA_property_is_set(op->ptr, prop_plane_co)) {
- RNA_property_float_get_array(op->ptr, prop_plane_co, plane_co);
- }
- else {
- copy_v3_v3(plane_co, scene->cursor.location);
- RNA_property_float_set_array(op->ptr, prop_plane_co, plane_co);
- }
-
- prop_plane_no = RNA_struct_find_property(op->ptr, "plane_no");
- if (RNA_property_is_set(op->ptr, prop_plane_no)) {
- RNA_property_float_get_array(op->ptr, prop_plane_no, plane_no);
- }
- else {
- if (rv3d) {
- copy_v3_v3(plane_no, rv3d->viewinv[1]);
- }
- else {
- /* fallback... */
- plane_no[0] = plane_no[1] = 0.0f; plane_no[2] = 1.0f;
- }
- RNA_property_float_set_array(op->ptr, prop_plane_no, plane_no);
- }
-
- wmGesture *gesture = op->customdata;
- BisectData *opdata = (gesture != NULL) ? gesture->userdata : NULL;
-
- /* -------------------------------------------------------------------- */
- /* Modal support */
- /* Note: keep this isolated, exec can work without this */
- if (opdata != NULL) {
- mesh_bisect_interactive_calc(C, op, plane_co, plane_no);
- /* Write back to the props. */
- RNA_property_float_set_array(op->ptr, prop_plane_no, plane_no);
- RNA_property_float_set_array(op->ptr, prop_plane_co, plane_co);
- }
- /* End Modal */
- /* -------------------------------------------------------------------- */
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(CTX_data_view_layer(C), CTX_wm_view3d(C), &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);
- BMesh *bm = em->bm;
-
- if (opdata != NULL) {
- if (opdata->backup[ob_index].is_dirty) {
- EDBM_redo_state_restore(opdata->backup[ob_index].mesh, em, false);
- opdata->backup[ob_index].is_dirty = false;
- }
- }
-
- if (bm->totedgesel == 0) {
- continue;
- }
-
- if (opdata != NULL) {
- if (opdata->backup[ob_index].is_valid) {
- opdata->backup[ob_index].is_dirty = true;
- }
- }
-
- float plane_co_local[3];
- float plane_no_local[3];
- copy_v3_v3(plane_co_local, plane_co);
- copy_v3_v3(plane_no_local, plane_no);
-
- invert_m4_m4(imat, obedit->obmat);
- mul_m4_v3(imat, plane_co_local);
- mul_transposed_mat3_m4_v3(obedit->obmat, plane_no_local);
-
- BMOperator bmop;
- EDBM_op_init(em, &bmop, op,
- "bisect_plane geom=%hvef plane_co=%v plane_no=%v dist=%f clear_inner=%b clear_outer=%b",
- BM_ELEM_SELECT, plane_co_local, plane_no_local, thresh, clear_inner, clear_outer);
- BMO_op_exec(bm, &bmop);
-
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
-
- if (use_fill) {
- float normal_fill[3];
- BMOperator bmop_fill;
- BMOperator bmop_attr;
-
- normalize_v3_v3(normal_fill, plane_no_local);
- if (clear_outer == true && clear_inner == false) {
- negate_v3(normal_fill);
- }
-
- /* Fill */
- BMO_op_initf(
- bm, &bmop_fill, 0,
- "triangle_fill edges=%S normal=%v use_dissolve=%b",
- &bmop, "geom_cut.out", normal_fill, true);
- BMO_op_exec(bm, &bmop_fill);
-
- /* Copy Attributes */
- BMO_op_initf(bm, &bmop_attr, 0,
- "face_attribute_fill faces=%S use_normals=%b use_data=%b",
- &bmop_fill, "geom.out", false, true);
- BMO_op_exec(bm, &bmop_attr);
-
- BMO_slot_buffer_hflag_enable(bm, bmop_fill.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
-
- BMO_op_finish(bm, &bmop_attr);
- BMO_op_finish(bm, &bmop_fill);
- }
-
- BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom_cut.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true);
-
- if (EDBM_op_finish(em, &bmop, op, true)) {
- EDBM_update_generic(em, true, true);
- EDBM_selectmode_flush(em);
- ret = OPERATOR_FINISHED;
- }
- }
- MEM_freeN(objects);
- return ret;
+ Scene *scene = CTX_data_scene(C);
+
+ /* both can be NULL, fallbacks values are used */
+ RegionView3D *rv3d = ED_view3d_context_rv3d(C);
+
+ int ret = OPERATOR_CANCELLED;
+
+ float plane_co[3];
+ float plane_no[3];
+ float imat[4][4];
+
+ const float thresh = RNA_float_get(op->ptr, "threshold");
+ const bool use_fill = RNA_boolean_get(op->ptr, "use_fill");
+ const bool clear_inner = RNA_boolean_get(op->ptr, "clear_inner");
+ const bool clear_outer = RNA_boolean_get(op->ptr, "clear_outer");
+
+ PropertyRNA *prop_plane_co;
+ PropertyRNA *prop_plane_no;
+
+ prop_plane_co = RNA_struct_find_property(op->ptr, "plane_co");
+ if (RNA_property_is_set(op->ptr, prop_plane_co)) {
+ RNA_property_float_get_array(op->ptr, prop_plane_co, plane_co);
+ }
+ else {
+ copy_v3_v3(plane_co, scene->cursor.location);
+ RNA_property_float_set_array(op->ptr, prop_plane_co, plane_co);
+ }
+
+ prop_plane_no = RNA_struct_find_property(op->ptr, "plane_no");
+ if (RNA_property_is_set(op->ptr, prop_plane_no)) {
+ RNA_property_float_get_array(op->ptr, prop_plane_no, plane_no);
+ }
+ else {
+ if (rv3d) {
+ copy_v3_v3(plane_no, rv3d->viewinv[1]);
+ }
+ else {
+ /* fallback... */
+ plane_no[0] = plane_no[1] = 0.0f;
+ plane_no[2] = 1.0f;
+ }
+ RNA_property_float_set_array(op->ptr, prop_plane_no, plane_no);
+ }
+
+ wmGesture *gesture = op->customdata;
+ BisectData *opdata = (gesture != NULL) ? gesture->userdata : NULL;
+
+ /* -------------------------------------------------------------------- */
+ /* Modal support */
+ /* Note: keep this isolated, exec can work without this */
+ if (opdata != NULL) {
+ mesh_bisect_interactive_calc(C, op, plane_co, plane_no);
+ /* Write back to the props. */
+ RNA_property_float_set_array(op->ptr, prop_plane_no, plane_no);
+ RNA_property_float_set_array(op->ptr, prop_plane_co, plane_co);
+ }
+ /* End Modal */
+ /* -------------------------------------------------------------------- */
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ CTX_data_view_layer(C), CTX_wm_view3d(C), &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);
+ BMesh *bm = em->bm;
+
+ if (opdata != NULL) {
+ if (opdata->backup[ob_index].is_dirty) {
+ EDBM_redo_state_restore(opdata->backup[ob_index].mesh, em, false);
+ opdata->backup[ob_index].is_dirty = false;
+ }
+ }
+
+ if (bm->totedgesel == 0) {
+ continue;
+ }
+
+ if (opdata != NULL) {
+ if (opdata->backup[ob_index].is_valid) {
+ opdata->backup[ob_index].is_dirty = true;
+ }
+ }
+
+ float plane_co_local[3];
+ float plane_no_local[3];
+ copy_v3_v3(plane_co_local, plane_co);
+ copy_v3_v3(plane_no_local, plane_no);
+
+ invert_m4_m4(imat, obedit->obmat);
+ mul_m4_v3(imat, plane_co_local);
+ mul_transposed_mat3_m4_v3(obedit->obmat, plane_no_local);
+
+ BMOperator bmop;
+ EDBM_op_init(
+ em,
+ &bmop,
+ op,
+ "bisect_plane geom=%hvef plane_co=%v plane_no=%v dist=%f clear_inner=%b clear_outer=%b",
+ BM_ELEM_SELECT,
+ plane_co_local,
+ plane_no_local,
+ thresh,
+ clear_inner,
+ clear_outer);
+ BMO_op_exec(bm, &bmop);
+
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+
+ if (use_fill) {
+ float normal_fill[3];
+ BMOperator bmop_fill;
+ BMOperator bmop_attr;
+
+ normalize_v3_v3(normal_fill, plane_no_local);
+ if (clear_outer == true && clear_inner == false) {
+ negate_v3(normal_fill);
+ }
+
+ /* Fill */
+ BMO_op_initf(bm,
+ &bmop_fill,
+ 0,
+ "triangle_fill edges=%S normal=%v use_dissolve=%b",
+ &bmop,
+ "geom_cut.out",
+ normal_fill,
+ true);
+ BMO_op_exec(bm, &bmop_fill);
+
+ /* Copy Attributes */
+ BMO_op_initf(bm,
+ &bmop_attr,
+ 0,
+ "face_attribute_fill faces=%S use_normals=%b use_data=%b",
+ &bmop_fill,
+ "geom.out",
+ false,
+ true);
+ BMO_op_exec(bm, &bmop_attr);
+
+ BMO_slot_buffer_hflag_enable(
+ bm, bmop_fill.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
+
+ BMO_op_finish(bm, &bmop_attr);
+ BMO_op_finish(bm, &bmop_fill);
+ }
+
+ BMO_slot_buffer_hflag_enable(
+ bm, bmop.slots_out, "geom_cut.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true);
+
+ if (EDBM_op_finish(em, &bmop, op, true)) {
+ EDBM_update_generic(em, true, true);
+ EDBM_selectmode_flush(em);
+ ret = OPERATOR_FINISHED;
+ }
+ }
+ MEM_freeN(objects);
+ return ret;
}
#ifdef USE_GIZMO
@@ -380,46 +399,69 @@ static void MESH_GGT_bisect(struct wmGizmoGroupType *gzgt);
void MESH_OT_bisect(struct wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Bisect";
- ot->description = "Cut geometry along a plane (click-drag to define plane)";
- ot->idname = "MESH_OT_bisect";
-
- /* api callbacks */
- ot->exec = mesh_bisect_exec;
- ot->invoke = mesh_bisect_invoke;
- ot->modal = mesh_bisect_modal;
- ot->cancel = WM_gesture_straightline_cancel;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
-
- prop = RNA_def_float_vector_xyz(ot->srna, "plane_co", 3, NULL, -1e12f, 1e12f,
- "Plane Point", "A point on the plane", -1e4f, 1e4f);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_float_vector(ot->srna, "plane_no", 3, NULL, -1.0f, 1.0f,
- "Plane Normal", "The direction the plane points", -1.0f, 1.0f);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- RNA_def_boolean(ot->srna, "use_fill", false, "Fill", "Fill in the cut");
- RNA_def_boolean(ot->srna, "clear_inner", false, "Clear Inner", "Remove geometry behind the plane");
- RNA_def_boolean(ot->srna, "clear_outer", false, "Clear Outer", "Remove geometry in front of the plane");
-
- RNA_def_float(ot->srna, "threshold", 0.0001, 0.0, 10.0, "Axis Threshold",
- "Preserves the existing geometry along the cut plane", 0.00001, 0.1);
-
- WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Bisect";
+ ot->description = "Cut geometry along a plane (click-drag to define plane)";
+ ot->idname = "MESH_OT_bisect";
+
+ /* api callbacks */
+ ot->exec = mesh_bisect_exec;
+ ot->invoke = mesh_bisect_invoke;
+ ot->modal = mesh_bisect_modal;
+ ot->cancel = WM_gesture_straightline_cancel;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_float_vector_xyz(ot->srna,
+ "plane_co",
+ 3,
+ NULL,
+ -1e12f,
+ 1e12f,
+ "Plane Point",
+ "A point on the plane",
+ -1e4f,
+ 1e4f);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_float_vector(ot->srna,
+ "plane_no",
+ 3,
+ NULL,
+ -1.0f,
+ 1.0f,
+ "Plane Normal",
+ "The direction the plane points",
+ -1.0f,
+ 1.0f);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ RNA_def_boolean(ot->srna, "use_fill", false, "Fill", "Fill in the cut");
+ RNA_def_boolean(
+ ot->srna, "clear_inner", false, "Clear Inner", "Remove geometry behind the plane");
+ RNA_def_boolean(
+ ot->srna, "clear_outer", false, "Clear Outer", "Remove geometry in front of the plane");
+
+ RNA_def_float(ot->srna,
+ "threshold",
+ 0.0001,
+ 0.0,
+ 10.0,
+ "Axis Threshold",
+ "Preserves the existing geometry along the cut plane",
+ 0.00001,
+ 0.1);
+
+ WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT);
#ifdef USE_GIZMO
- WM_gizmogrouptype_append(MESH_GGT_bisect);
+ WM_gizmogrouptype_append(MESH_GGT_bisect);
#endif
}
-
#ifdef USE_GIZMO
/* -------------------------------------------------------------------- */
@@ -427,23 +469,23 @@ void MESH_OT_bisect(struct wmOperatorType *ot)
* \{ */
typedef struct GizmoGroup {
- /* Arrow to change plane depth. */
- struct wmGizmo *translate_z;
- /* Translate XYZ */
- struct wmGizmo *translate_c;
- /* For grabbing the gizmo and moving freely. */
- struct wmGizmo *rotate_c;
-
- /* We could store more vars here! */
- struct {
- bContext *context;
- wmOperator *op;
- PropertyRNA *prop_plane_co;
- PropertyRNA *prop_plane_no;
-
- float rotate_axis[3];
- float rotate_up[3];
- } data;
+ /* Arrow to change plane depth. */
+ struct wmGizmo *translate_z;
+ /* Translate XYZ */
+ struct wmGizmo *translate_c;
+ /* For grabbing the gizmo and moving freely. */
+ struct wmGizmo *rotate_c;
+
+ /* We could store more vars here! */
+ struct {
+ bContext *context;
+ wmOperator *op;
+ PropertyRNA *prop_plane_co;
+ PropertyRNA *prop_plane_no;
+
+ float rotate_axis[3];
+ float rotate_up[3];
+ } data;
} GizmoGroup;
/**
@@ -453,285 +495,284 @@ typedef struct GizmoGroup {
*/
static void gizmo_bisect_exec(GizmoGroup *ggd)
{
- wmOperator *op = ggd->data.op;
- if (op == WM_operator_last_redo((bContext *)ggd->data.context)) {
- ED_undo_operator_repeat((bContext *)ggd->data.context, op);
- }
+ wmOperator *op = ggd->data.op;
+ if (op == WM_operator_last_redo((bContext *)ggd->data.context)) {
+ ED_undo_operator_repeat((bContext *)ggd->data.context, op);
+ }
}
static void gizmo_mesh_bisect_update_from_op(GizmoGroup *ggd)
{
- wmOperator *op = ggd->data.op;
+ wmOperator *op = ggd->data.op;
- float plane_co[3], plane_no[3];
+ float plane_co[3], plane_no[3];
- RNA_property_float_get_array(op->ptr, ggd->data.prop_plane_co, plane_co);
- RNA_property_float_get_array(op->ptr, ggd->data.prop_plane_no, plane_no);
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_plane_co, plane_co);
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_plane_no, plane_no);
- WM_gizmo_set_matrix_location(ggd->translate_z, plane_co);
- WM_gizmo_set_matrix_location(ggd->rotate_c, plane_co);
- /* translate_c location comes from the property. */
+ WM_gizmo_set_matrix_location(ggd->translate_z, plane_co);
+ WM_gizmo_set_matrix_location(ggd->rotate_c, plane_co);
+ /* translate_c location comes from the property. */
- WM_gizmo_set_matrix_rotation_from_z_axis(ggd->translate_z, plane_no);
+ WM_gizmo_set_matrix_rotation_from_z_axis(ggd->translate_z, plane_no);
- WM_gizmo_set_scale(ggd->translate_c, 0.2);
+ WM_gizmo_set_scale(ggd->translate_c, 0.2);
- RegionView3D *rv3d = ED_view3d_context_rv3d(ggd->data.context);
- if (rv3d) {
- normalize_v3_v3(ggd->data.rotate_axis, rv3d->viewinv[2]);
- normalize_v3_v3(ggd->data.rotate_up, rv3d->viewinv[1]);
+ RegionView3D *rv3d = ED_view3d_context_rv3d(ggd->data.context);
+ if (rv3d) {
+ normalize_v3_v3(ggd->data.rotate_axis, rv3d->viewinv[2]);
+ normalize_v3_v3(ggd->data.rotate_up, rv3d->viewinv[1]);
- /* ensure its orthogonal */
- project_plane_normalized_v3_v3v3(ggd->data.rotate_up, ggd->data.rotate_up, ggd->data.rotate_axis);
- normalize_v3(ggd->data.rotate_up);
+ /* ensure its orthogonal */
+ project_plane_normalized_v3_v3v3(
+ ggd->data.rotate_up, ggd->data.rotate_up, ggd->data.rotate_axis);
+ normalize_v3(ggd->data.rotate_up);
- WM_gizmo_set_matrix_rotation_from_z_axis(ggd->translate_c, plane_no);
+ WM_gizmo_set_matrix_rotation_from_z_axis(ggd->translate_c, plane_no);
- float plane_no_cross[3];
- cross_v3_v3v3(plane_no_cross, plane_no, ggd->data.rotate_axis);
+ float plane_no_cross[3];
+ cross_v3_v3v3(plane_no_cross, plane_no, ggd->data.rotate_axis);
- WM_gizmo_set_matrix_offset_rotation_from_yz_axis(ggd->rotate_c, plane_no_cross, ggd->data.rotate_axis);
- RNA_enum_set(ggd->rotate_c->ptr, "draw_options",
- ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR |
- ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y);
- }
+ WM_gizmo_set_matrix_offset_rotation_from_yz_axis(
+ ggd->rotate_c, plane_no_cross, ggd->data.rotate_axis);
+ RNA_enum_set(ggd->rotate_c->ptr,
+ "draw_options",
+ ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR | ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y);
+ }
}
/* depth callbacks */
-static void gizmo_bisect_prop_depth_get(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- void *value_p)
+static void gizmo_bisect_prop_depth_get(const wmGizmo *gz, wmGizmoProperty *gz_prop, void *value_p)
{
- GizmoGroup *ggd = gz->parent_gzgroup->customdata;
- wmOperator *op = ggd->data.op;
- float *value = value_p;
+ GizmoGroup *ggd = gz->parent_gzgroup->customdata;
+ wmOperator *op = ggd->data.op;
+ float *value = value_p;
- BLI_assert(gz_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(gz_prop);
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
- float plane_co[3], plane_no[3];
- RNA_property_float_get_array(op->ptr, ggd->data.prop_plane_co, plane_co);
- RNA_property_float_get_array(op->ptr, ggd->data.prop_plane_no, plane_no);
+ float plane_co[3], plane_no[3];
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_plane_co, plane_co);
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_plane_no, plane_no);
- value[0] = dot_v3v3(plane_no, plane_co) - dot_v3v3(plane_no, gz->matrix_basis[3]);
+ value[0] = dot_v3v3(plane_no, plane_co) - dot_v3v3(plane_no, gz->matrix_basis[3]);
}
-static void gizmo_bisect_prop_depth_set(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- const void *value_p)
+static void gizmo_bisect_prop_depth_set(const wmGizmo *gz,
+ wmGizmoProperty *gz_prop,
+ const void *value_p)
{
- GizmoGroup *ggd = gz->parent_gzgroup->customdata;
- wmOperator *op = ggd->data.op;
- const float *value = value_p;
+ GizmoGroup *ggd = gz->parent_gzgroup->customdata;
+ wmOperator *op = ggd->data.op;
+ const float *value = value_p;
- BLI_assert(gz_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(gz_prop);
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
- float plane_co[3], plane[4];
- RNA_property_float_get_array(op->ptr, ggd->data.prop_plane_co, plane_co);
- RNA_property_float_get_array(op->ptr, ggd->data.prop_plane_no, plane);
- normalize_v3(plane);
+ float plane_co[3], plane[4];
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_plane_co, plane_co);
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_plane_no, plane);
+ normalize_v3(plane);
- plane[3] = -value[0] - dot_v3v3(plane, gz->matrix_basis[3]);
+ plane[3] = -value[0] - dot_v3v3(plane, gz->matrix_basis[3]);
- /* Keep our location, may be offset simply to be inside the viewport. */
- closest_to_plane_normalized_v3(plane_co, plane, plane_co);
+ /* Keep our location, may be offset simply to be inside the viewport. */
+ closest_to_plane_normalized_v3(plane_co, plane, plane_co);
- RNA_property_float_set_array(op->ptr, ggd->data.prop_plane_co, plane_co);
+ RNA_property_float_set_array(op->ptr, ggd->data.prop_plane_co, plane_co);
- gizmo_bisect_exec(ggd);
+ gizmo_bisect_exec(ggd);
}
/* translate callbacks */
-static void gizmo_bisect_prop_translate_get(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- void *value_p)
+static void gizmo_bisect_prop_translate_get(const wmGizmo *gz,
+ wmGizmoProperty *gz_prop,
+ void *value_p)
{
- GizmoGroup *ggd = gz->parent_gzgroup->customdata;
- wmOperator *op = ggd->data.op;
+ GizmoGroup *ggd = gz->parent_gzgroup->customdata;
+ wmOperator *op = ggd->data.op;
- BLI_assert(gz_prop->type->array_length == 3);
- UNUSED_VARS_NDEBUG(gz_prop);
+ BLI_assert(gz_prop->type->array_length == 3);
+ UNUSED_VARS_NDEBUG(gz_prop);
- RNA_property_float_get_array(op->ptr, ggd->data.prop_plane_co, value_p);
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_plane_co, value_p);
}
-static void gizmo_bisect_prop_translate_set(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- const void *value_p)
+static void gizmo_bisect_prop_translate_set(const wmGizmo *gz,
+ wmGizmoProperty *gz_prop,
+ const void *value_p)
{
- GizmoGroup *ggd = gz->parent_gzgroup->customdata;
- wmOperator *op = ggd->data.op;
+ GizmoGroup *ggd = gz->parent_gzgroup->customdata;
+ wmOperator *op = ggd->data.op;
- BLI_assert(gz_prop->type->array_length == 3);
- UNUSED_VARS_NDEBUG(gz_prop);
+ BLI_assert(gz_prop->type->array_length == 3);
+ UNUSED_VARS_NDEBUG(gz_prop);
- RNA_property_float_set_array(op->ptr, ggd->data.prop_plane_co, value_p);
+ RNA_property_float_set_array(op->ptr, ggd->data.prop_plane_co, value_p);
- gizmo_bisect_exec(ggd);
+ gizmo_bisect_exec(ggd);
}
/* angle callbacks */
-static void gizmo_bisect_prop_angle_get(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- void *value_p)
+static void gizmo_bisect_prop_angle_get(const wmGizmo *gz, wmGizmoProperty *gz_prop, void *value_p)
{
- GizmoGroup *ggd = gz->parent_gzgroup->customdata;
- wmOperator *op = ggd->data.op;
- float *value = value_p;
-
- BLI_assert(gz_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(gz_prop);
-
- float plane_no[4];
- RNA_property_float_get_array(op->ptr, ggd->data.prop_plane_no, plane_no);
- normalize_v3(plane_no);
-
- float plane_no_proj[3];
- project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, ggd->data.rotate_axis);
-
- if (!is_zero_v3(plane_no_proj)) {
- const float angle = -angle_signed_on_axis_v3v3_v3(plane_no_proj, ggd->data.rotate_up, ggd->data.rotate_axis);
- value[0] = angle;
- }
- else {
- value[0] = 0.0f;
- }
+ GizmoGroup *ggd = gz->parent_gzgroup->customdata;
+ wmOperator *op = ggd->data.op;
+ float *value = value_p;
+
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
+
+ float plane_no[4];
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_plane_no, plane_no);
+ normalize_v3(plane_no);
+
+ float plane_no_proj[3];
+ project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, ggd->data.rotate_axis);
+
+ if (!is_zero_v3(plane_no_proj)) {
+ const float angle = -angle_signed_on_axis_v3v3_v3(
+ plane_no_proj, ggd->data.rotate_up, ggd->data.rotate_axis);
+ value[0] = angle;
+ }
+ else {
+ value[0] = 0.0f;
+ }
}
-static void gizmo_bisect_prop_angle_set(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- const void *value_p)
+static void gizmo_bisect_prop_angle_set(const wmGizmo *gz,
+ wmGizmoProperty *gz_prop,
+ const void *value_p)
{
- GizmoGroup *ggd = gz->parent_gzgroup->customdata;
- wmOperator *op = ggd->data.op;
- const float *value = value_p;
-
- BLI_assert(gz_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(gz_prop);
-
- float plane_no[4];
- RNA_property_float_get_array(op->ptr, ggd->data.prop_plane_no, plane_no);
- normalize_v3(plane_no);
-
- float plane_no_proj[3];
- project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, ggd->data.rotate_axis);
-
- if (!is_zero_v3(plane_no_proj)) {
- const float angle = -angle_signed_on_axis_v3v3_v3(plane_no_proj, ggd->data.rotate_up, ggd->data.rotate_axis);
- const float angle_delta = angle - angle_compat_rad(value[0], angle);
- if (angle_delta != 0.0f) {
- float mat[3][3];
- axis_angle_normalized_to_mat3(mat, ggd->data.rotate_axis, angle_delta);
- mul_m3_v3(mat, plane_no);
-
- /* re-normalize - seems acceptable */
- RNA_property_float_set_array(op->ptr, ggd->data.prop_plane_no, plane_no);
-
- gizmo_bisect_exec(ggd);
- }
- }
+ GizmoGroup *ggd = gz->parent_gzgroup->customdata;
+ wmOperator *op = ggd->data.op;
+ const float *value = value_p;
+
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
+
+ float plane_no[4];
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_plane_no, plane_no);
+ normalize_v3(plane_no);
+
+ float plane_no_proj[3];
+ project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, ggd->data.rotate_axis);
+
+ if (!is_zero_v3(plane_no_proj)) {
+ const float angle = -angle_signed_on_axis_v3v3_v3(
+ plane_no_proj, ggd->data.rotate_up, ggd->data.rotate_axis);
+ const float angle_delta = angle - angle_compat_rad(value[0], angle);
+ if (angle_delta != 0.0f) {
+ float mat[3][3];
+ axis_angle_normalized_to_mat3(mat, ggd->data.rotate_axis, angle_delta);
+ mul_m3_v3(mat, plane_no);
+
+ /* re-normalize - seems acceptable */
+ RNA_property_float_set_array(op->ptr, ggd->data.prop_plane_no, plane_no);
+
+ gizmo_bisect_exec(ggd);
+ }
+ }
}
static bool gizmo_mesh_bisect_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
- return ED_gizmo_poll_or_unlink_delayed_from_operator(C, gzgt, "MESH_OT_bisect");
+ return ED_gizmo_poll_or_unlink_delayed_from_operator(C, gzgt, "MESH_OT_bisect");
}
static void gizmo_mesh_bisect_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
- wmOperator *op = WM_operator_last_redo(C);
-
- if (op == NULL || !STREQ(op->type->idname, "MESH_OT_bisect")) {
- return;
- }
-
- struct GizmoGroup *ggd = MEM_callocN(sizeof(GizmoGroup), __func__);
- gzgroup->customdata = ggd;
-
- const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
- const wmGizmoType *gzt_move = WM_gizmotype_find("GIZMO_GT_move_3d", true);
- const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true);
-
- ggd->translate_z = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
- ggd->translate_c = WM_gizmo_new_ptr(gzt_move, gzgroup, NULL);
- ggd->rotate_c = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL);
-
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, ggd->translate_z->color);
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, ggd->translate_c->color);
- UI_GetThemeColor3fv(TH_GIZMO_SECONDARY, ggd->rotate_c->color);
-
- RNA_enum_set(ggd->translate_z->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_NORMAL);
- RNA_enum_set(ggd->translate_c->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_RING_2D);
-
- WM_gizmo_set_flag(ggd->translate_c, WM_GIZMO_DRAW_VALUE, true);
- WM_gizmo_set_flag(ggd->rotate_c, WM_GIZMO_DRAW_VALUE, true);
-
- {
- ggd->data.context = (bContext *)C;
- ggd->data.op = op;
- ggd->data.prop_plane_co = RNA_struct_find_property(op->ptr, "plane_co");
- ggd->data.prop_plane_no = RNA_struct_find_property(op->ptr, "plane_no");
- }
-
- gizmo_mesh_bisect_update_from_op(ggd);
-
- /* Setup property callbacks */
- {
- WM_gizmo_target_property_def_func(
- ggd->translate_z, "offset",
- &(const struct wmGizmoPropertyFnParams) {
- .value_get_fn = gizmo_bisect_prop_depth_get,
- .value_set_fn = gizmo_bisect_prop_depth_set,
- .range_get_fn = NULL,
- .user_data = NULL,
- });
-
- WM_gizmo_target_property_def_func(
- ggd->translate_c, "offset",
- &(const struct wmGizmoPropertyFnParams) {
- .value_get_fn = gizmo_bisect_prop_translate_get,
- .value_set_fn = gizmo_bisect_prop_translate_set,
- .range_get_fn = NULL,
- .user_data = NULL,
- });
-
- WM_gizmo_target_property_def_func(
- ggd->rotate_c, "offset",
- &(const struct wmGizmoPropertyFnParams) {
- .value_get_fn = gizmo_bisect_prop_angle_get,
- .value_set_fn = gizmo_bisect_prop_angle_set,
- .range_get_fn = NULL,
- .user_data = NULL,
- });
- }
+ wmOperator *op = WM_operator_last_redo(C);
+
+ if (op == NULL || !STREQ(op->type->idname, "MESH_OT_bisect")) {
+ return;
+ }
+
+ struct GizmoGroup *ggd = MEM_callocN(sizeof(GizmoGroup), __func__);
+ gzgroup->customdata = ggd;
+
+ const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
+ const wmGizmoType *gzt_move = WM_gizmotype_find("GIZMO_GT_move_3d", true);
+ const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true);
+
+ ggd->translate_z = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ ggd->translate_c = WM_gizmo_new_ptr(gzt_move, gzgroup, NULL);
+ ggd->rotate_c = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL);
+
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, ggd->translate_z->color);
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, ggd->translate_c->color);
+ UI_GetThemeColor3fv(TH_GIZMO_SECONDARY, ggd->rotate_c->color);
+
+ RNA_enum_set(ggd->translate_z->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_NORMAL);
+ RNA_enum_set(ggd->translate_c->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_RING_2D);
+
+ WM_gizmo_set_flag(ggd->translate_c, WM_GIZMO_DRAW_VALUE, true);
+ WM_gizmo_set_flag(ggd->rotate_c, WM_GIZMO_DRAW_VALUE, true);
+
+ {
+ ggd->data.context = (bContext *)C;
+ ggd->data.op = op;
+ ggd->data.prop_plane_co = RNA_struct_find_property(op->ptr, "plane_co");
+ ggd->data.prop_plane_no = RNA_struct_find_property(op->ptr, "plane_no");
+ }
+
+ gizmo_mesh_bisect_update_from_op(ggd);
+
+ /* Setup property callbacks */
+ {
+ WM_gizmo_target_property_def_func(ggd->translate_z,
+ "offset",
+ &(const struct wmGizmoPropertyFnParams){
+ .value_get_fn = gizmo_bisect_prop_depth_get,
+ .value_set_fn = gizmo_bisect_prop_depth_set,
+ .range_get_fn = NULL,
+ .user_data = NULL,
+ });
+
+ WM_gizmo_target_property_def_func(ggd->translate_c,
+ "offset",
+ &(const struct wmGizmoPropertyFnParams){
+ .value_get_fn = gizmo_bisect_prop_translate_get,
+ .value_set_fn = gizmo_bisect_prop_translate_set,
+ .range_get_fn = NULL,
+ .user_data = NULL,
+ });
+
+ WM_gizmo_target_property_def_func(ggd->rotate_c,
+ "offset",
+ &(const struct wmGizmoPropertyFnParams){
+ .value_get_fn = gizmo_bisect_prop_angle_get,
+ .value_set_fn = gizmo_bisect_prop_angle_set,
+ .range_get_fn = NULL,
+ .user_data = NULL,
+ });
+ }
}
-static void gizmo_mesh_bisect_draw_prepare(
- const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
+static void gizmo_mesh_bisect_draw_prepare(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- GizmoGroup *ggd = gzgroup->customdata;
- if (ggd->data.op->next) {
- ggd->data.op = WM_operator_last_redo((bContext *)ggd->data.context);
- }
- gizmo_mesh_bisect_update_from_op(ggd);
+ GizmoGroup *ggd = gzgroup->customdata;
+ if (ggd->data.op->next) {
+ ggd->data.op = WM_operator_last_redo((bContext *)ggd->data.context);
+ }
+ gizmo_mesh_bisect_update_from_op(ggd);
}
static void MESH_GGT_bisect(struct wmGizmoGroupType *gzgt)
{
- gzgt->name = "Mesh Bisect";
- gzgt->idname = "MESH_GGT_bisect";
+ gzgt->name = "Mesh Bisect";
+ gzgt->idname = "MESH_GGT_bisect";
- gzgt->flag = WM_GIZMOGROUPTYPE_3D;
+ gzgt->flag = WM_GIZMOGROUPTYPE_3D;
- gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
- gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- gzgt->poll = gizmo_mesh_bisect_poll;
- gzgt->setup = gizmo_mesh_bisect_setup;
- gzgt->draw_prepare = gizmo_mesh_bisect_draw_prepare;
+ gzgt->poll = gizmo_mesh_bisect_poll;
+ gzgt->setup = gizmo_mesh_bisect_setup;
+ gzgt->draw_prepare = gizmo_mesh_bisect_draw_prepare;
}
/** \} */
-#endif /* USE_GIZMO */
+#endif /* USE_GIZMO */
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index f2ba227fd2e..eeda7ec5f2d 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -44,232 +44,225 @@
#include "MEM_guardedalloc.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Extrude Internal Utilities
* \{ */
static void edbm_extrude_edge_exclude_mirror(
- Object *obedit, BMEditMesh *em,
- const char hflag,
- BMOperator *op, BMOpSlot *slot_edges_exclude)
+ Object *obedit, BMEditMesh *em, const char hflag, BMOperator *op, BMOpSlot *slot_edges_exclude)
{
- BMesh *bm = em->bm;
- ModifierData *md;
-
- /* If a mirror modifier with clipping is on, we need to adjust some
- * of the cases above to handle edges on the line of symmetry.
- */
- for (md = obedit->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) {
- BMIter iter;
- BMEdge *edge;
-
- float mtx[4][4];
- if (mmd->mirror_ob) {
- float imtx[4][4];
- invert_m4_m4(imtx, mmd->mirror_ob->obmat);
- mul_m4_m4m4(mtx, imtx, obedit->obmat);
- }
-
- BM_ITER_MESH (edge, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(edge, hflag) &&
- BM_edge_is_boundary(edge) &&
- BM_elem_flag_test(edge->l->f, hflag))
- {
- float co1[3], co2[3];
-
- copy_v3_v3(co1, edge->v1->co);
- copy_v3_v3(co2, edge->v2->co);
-
- if (mmd->mirror_ob) {
- mul_v3_m4v3(co1, mtx, co1);
- mul_v3_m4v3(co2, mtx, co2);
- }
-
- if (mmd->flag & MOD_MIR_AXIS_X) {
- if ((fabsf(co1[0]) < mmd->tolerance) &&
- (fabsf(co2[0]) < mmd->tolerance))
- {
- BMO_slot_map_empty_insert(op, slot_edges_exclude, edge);
- }
- }
- if (mmd->flag & MOD_MIR_AXIS_Y) {
- if ((fabsf(co1[1]) < mmd->tolerance) &&
- (fabsf(co2[1]) < mmd->tolerance))
- {
- BMO_slot_map_empty_insert(op, slot_edges_exclude, edge);
- }
- }
- if (mmd->flag & MOD_MIR_AXIS_Z) {
- if ((fabsf(co1[2]) < mmd->tolerance) &&
- (fabsf(co2[2]) < mmd->tolerance))
- {
- BMO_slot_map_empty_insert(op, slot_edges_exclude, edge);
- }
- }
- }
- }
- }
- }
- }
+ BMesh *bm = em->bm;
+ ModifierData *md;
+
+ /* If a mirror modifier with clipping is on, we need to adjust some
+ * of the cases above to handle edges on the line of symmetry.
+ */
+ for (md = obedit->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) {
+ BMIter iter;
+ BMEdge *edge;
+
+ float mtx[4][4];
+ if (mmd->mirror_ob) {
+ float imtx[4][4];
+ invert_m4_m4(imtx, mmd->mirror_ob->obmat);
+ mul_m4_m4m4(mtx, imtx, obedit->obmat);
+ }
+
+ BM_ITER_MESH (edge, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(edge, hflag) && BM_edge_is_boundary(edge) &&
+ BM_elem_flag_test(edge->l->f, hflag)) {
+ float co1[3], co2[3];
+
+ copy_v3_v3(co1, edge->v1->co);
+ copy_v3_v3(co2, edge->v2->co);
+
+ if (mmd->mirror_ob) {
+ mul_v3_m4v3(co1, mtx, co1);
+ mul_v3_m4v3(co2, mtx, co2);
+ }
+
+ if (mmd->flag & MOD_MIR_AXIS_X) {
+ if ((fabsf(co1[0]) < mmd->tolerance) && (fabsf(co2[0]) < mmd->tolerance)) {
+ BMO_slot_map_empty_insert(op, slot_edges_exclude, edge);
+ }
+ }
+ if (mmd->flag & MOD_MIR_AXIS_Y) {
+ if ((fabsf(co1[1]) < mmd->tolerance) && (fabsf(co2[1]) < mmd->tolerance)) {
+ BMO_slot_map_empty_insert(op, slot_edges_exclude, edge);
+ }
+ }
+ if (mmd->flag & MOD_MIR_AXIS_Z) {
+ if ((fabsf(co1[2]) < mmd->tolerance) && (fabsf(co2[2]) < mmd->tolerance)) {
+ BMO_slot_map_empty_insert(op, slot_edges_exclude, edge);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
/* individual face extrude */
/* will use vertex normals for extrusion directions, so *nor is unaffected */
static bool edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const char hflag)
{
- BMOIter siter;
- BMIter liter;
- BMFace *f;
- BMLoop *l;
- BMOperator bmop;
+ BMOIter siter;
+ BMIter liter;
+ BMFace *f;
+ BMLoop *l;
+ BMOperator bmop;
- EDBM_op_init(
- em, &bmop, op,
- "extrude_discrete_faces faces=%hf use_select_history=%b",
- hflag, true);
+ EDBM_op_init(
+ em, &bmop, op, "extrude_discrete_faces faces=%hf use_select_history=%b", hflag, true);
- /* deselect original verts */
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ /* deselect original verts */
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_op_exec(em->bm, &bmop);
+ BMO_op_exec(em->bm, &bmop);
- BMO_ITER (f, &siter, bmop.slots_out, "faces.out", BM_FACE) {
- BM_face_select_set(em->bm, f, true);
+ BMO_ITER (f, &siter, bmop.slots_out, "faces.out", BM_FACE) {
+ BM_face_select_set(em->bm, f, true);
- /* set face vertex normals to face normal */
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- copy_v3_v3(l->v->no, f->no);
- }
- }
+ /* set face vertex normals to face normal */
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ copy_v3_v3(l->v->no, f->no);
+ }
+ }
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- return false;
- }
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ return false;
+ }
- return true;
+ return true;
}
/* extrudes individual edges */
-static bool edbm_extrude_edges_indiv(BMEditMesh *em, wmOperator *op, const char hflag, const bool use_normal_flip)
+static bool edbm_extrude_edges_indiv(BMEditMesh *em,
+ wmOperator *op,
+ const char hflag,
+ const bool use_normal_flip)
{
- BMesh *bm = em->bm;
- BMOperator bmop;
-
- EDBM_op_init(
- em, &bmop, op,
- "extrude_edge_only edges=%he use_normal_flip=%b use_select_history=%b",
- hflag, use_normal_flip, true);
-
- /* deselect original verts */
- BM_SELECT_HISTORY_BACKUP(bm);
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BM_SELECT_HISTORY_RESTORE(bm);
-
- BMO_op_exec(em->bm, &bmop);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true);
-
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- return false;
- }
-
- return true;
+ BMesh *bm = em->bm;
+ BMOperator bmop;
+
+ EDBM_op_init(em,
+ &bmop,
+ op,
+ "extrude_edge_only edges=%he use_normal_flip=%b use_select_history=%b",
+ hflag,
+ use_normal_flip,
+ true);
+
+ /* deselect original verts */
+ BM_SELECT_HISTORY_BACKUP(bm);
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BM_SELECT_HISTORY_RESTORE(bm);
+
+ BMO_op_exec(em->bm, &bmop);
+ BMO_slot_buffer_hflag_enable(
+ em->bm, bmop.slots_out, "geom.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true);
+
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ return false;
+ }
+
+ return true;
}
/* extrudes individual vertices */
static bool edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char hflag)
{
- BMOperator bmop;
+ BMOperator bmop;
- EDBM_op_init(
- em, &bmop, op,
- "extrude_vert_indiv verts=%hv use_select_history=%b",
- hflag, true);
+ EDBM_op_init(em, &bmop, op, "extrude_vert_indiv verts=%hv use_select_history=%b", hflag, true);
- /* deselect original verts */
- BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "verts", BM_VERT, BM_ELEM_SELECT, true);
+ /* deselect original verts */
+ BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "verts", BM_VERT, BM_ELEM_SELECT, true);
- BMO_op_exec(em->bm, &bmop);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, true);
+ BMO_op_exec(em->bm, &bmop);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, true);
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- return false;
- }
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ return false;
+ }
- return true;
+ return true;
}
static char edbm_extrude_htype_from_em_select(BMEditMesh *em)
{
- char htype = BM_ALL_NOLOOP;
-
- if (em->selectmode & SCE_SELECT_VERTEX) {
- /* pass */
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- htype &= ~BM_VERT;
- }
- else {
- htype &= ~(BM_VERT | BM_EDGE);
- }
-
- if (em->bm->totedgesel == 0) {
- htype &= ~(BM_EDGE | BM_FACE);
- }
- else if (em->bm->totfacesel == 0) {
- htype &= ~BM_FACE;
- }
-
- return htype;
+ char htype = BM_ALL_NOLOOP;
+
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ /* pass */
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ htype &= ~BM_VERT;
+ }
+ else {
+ htype &= ~(BM_VERT | BM_EDGE);
+ }
+
+ if (em->bm->totedgesel == 0) {
+ htype &= ~(BM_EDGE | BM_FACE);
+ }
+ else if (em->bm->totfacesel == 0) {
+ htype &= ~BM_FACE;
+ }
+
+ return htype;
}
-static bool edbm_extrude_ex(
- Object *obedit, BMEditMesh *em,
- char htype, const char hflag,
- const bool use_normal_flip,
- const bool use_mirror,
- const bool use_select_history)
+static bool edbm_extrude_ex(Object *obedit,
+ BMEditMesh *em,
+ char htype,
+ const char hflag,
+ const bool use_normal_flip,
+ const bool use_mirror,
+ const bool use_select_history)
{
- BMesh *bm = em->bm;
- BMOIter siter;
- BMOperator extop;
- BMElem *ele;
+ BMesh *bm = em->bm;
+ BMOIter siter;
+ BMOperator extop;
+ BMElem *ele;
- /* needed to remove the faces left behind */
- if (htype & BM_FACE) {
- htype |= BM_EDGE;
- }
+ /* needed to remove the faces left behind */
+ if (htype & BM_FACE) {
+ htype |= BM_EDGE;
+ }
- 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_select_history", use_select_history);
- BMO_slot_buffer_from_enabled_hflag(bm, &extop, extop.slots_in, "geom", htype, hflag);
+ 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_select_history", use_select_history);
+ BMO_slot_buffer_from_enabled_hflag(bm, &extop, extop.slots_in, "geom", htype, hflag);
- if (use_mirror) {
- BMOpSlot *slot_edges_exclude;
- slot_edges_exclude = BMO_slot_get(extop.slots_in, "edges_exclude");
+ if (use_mirror) {
+ BMOpSlot *slot_edges_exclude;
+ slot_edges_exclude = BMO_slot_get(extop.slots_in, "edges_exclude");
- edbm_extrude_edge_exclude_mirror(obedit, em, hflag, &extop, slot_edges_exclude);
- }
+ edbm_extrude_edge_exclude_mirror(obedit, em, hflag, &extop, slot_edges_exclude);
+ }
- BM_SELECT_HISTORY_BACKUP(bm);
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BM_SELECT_HISTORY_RESTORE(bm);
+ BM_SELECT_HISTORY_BACKUP(bm);
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BM_SELECT_HISTORY_RESTORE(bm);
- BMO_op_exec(bm, &extop);
+ BMO_op_exec(bm, &extop);
- BMO_ITER (ele, &siter, extop.slots_out, "geom.out", BM_ALL_NOLOOP) {
- BM_elem_select_set(bm, ele, true);
- }
+ BMO_ITER (ele, &siter, extop.slots_out, "geom.out", BM_ALL_NOLOOP) {
+ BM_elem_select_set(bm, ele, true);
+ }
- BMO_op_finish(bm, &extop);
+ BMO_op_finish(bm, &extop);
- return true;
+ return true;
}
/** \} */
@@ -280,65 +273,63 @@ static bool edbm_extrude_ex(
static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- 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;
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ 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;
- 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);
+ 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++) {
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- /* dvec */
- normalize_v3_v3_length(dvec, rv3d->persinv[2], offs);
+ /* 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);
+ /* base correction */
+ copy_m3_m4(bmat, obedit->obmat);
+ invert_m3_m3(tmat, bmat);
+ mul_m3_v3(tmat, dvec);
- for (a = 0; a < steps; a++) {
- edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false, false);
+ 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);
- }
+ BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "translate vec=%v verts=%hv", dvec, BM_ELEM_SELECT);
+ }
- EDBM_mesh_normals_update(em);
+ EDBM_mesh_normals_update(em);
- EDBM_update_generic(em, true, true);
- }
+ EDBM_update_generic(em, true, true);
+ }
- MEM_freeN(objects);
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_extrude_repeat(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Extrude Repeat Mesh";
- ot->description = "Extrude selected vertices, edges or faces repeatedly";
- ot->idname = "MESH_OT_extrude_repeat";
+ /* identifiers */
+ ot->name = "Extrude Repeat Mesh";
+ 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;
+ /* api callbacks */
+ ot->exec = edbm_extrude_repeat_exec;
+ ot->poll = ED_operator_editmesh_view3d;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* 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);
+ /* 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);
}
/** \} */
@@ -350,95 +341,105 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot)
/* generic extern called extruder */
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 char htype = edbm_extrude_htype_from_em_select(em);
- enum {NONE = 0, ELEM_FLAG, VERT_ONLY, EDGE_ONLY} nr;
- bool changed = false;
-
- if (em->selectmode & SCE_SELECT_VERTEX) {
- if (em->bm->totvertsel == 0) nr = NONE;
- else if (em->bm->totvertsel == 1) nr = VERT_ONLY;
- else if (em->bm->totedgesel == 0) nr = VERT_ONLY;
- else nr = ELEM_FLAG;
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- if (em->bm->totedgesel == 0) nr = NONE;
- else if (em->bm->totfacesel == 0) nr = EDGE_ONLY;
- else nr = ELEM_FLAG;
- }
- else {
- if (em->bm->totfacesel == 0) nr = NONE;
- else nr = ELEM_FLAG;
- }
-
- switch (nr) {
- case NONE:
- return false;
- case ELEM_FLAG:
- changed = edbm_extrude_ex(obedit, em, htype, BM_ELEM_SELECT, use_normal_flip, true, true);
- break;
- case VERT_ONLY:
- changed = edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT);
- break;
- case EDGE_ONLY:
- changed = edbm_extrude_edges_indiv(em, op, BM_ELEM_SELECT, use_normal_flip);
- break;
- }
-
- if (changed) {
- return true;
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Not a valid selection for extrude");
- return false;
- }
+ const bool use_normal_flip = RNA_boolean_get(op->ptr, "use_normal_flip");
+ const char htype = edbm_extrude_htype_from_em_select(em);
+ enum { NONE = 0, ELEM_FLAG, VERT_ONLY, EDGE_ONLY } nr;
+ bool changed = false;
+
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ if (em->bm->totvertsel == 0)
+ nr = NONE;
+ else if (em->bm->totvertsel == 1)
+ nr = VERT_ONLY;
+ else if (em->bm->totedgesel == 0)
+ nr = VERT_ONLY;
+ else
+ nr = ELEM_FLAG;
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ if (em->bm->totedgesel == 0)
+ nr = NONE;
+ else if (em->bm->totfacesel == 0)
+ nr = EDGE_ONLY;
+ else
+ nr = ELEM_FLAG;
+ }
+ else {
+ if (em->bm->totfacesel == 0)
+ nr = NONE;
+ else
+ nr = ELEM_FLAG;
+ }
+
+ switch (nr) {
+ case NONE:
+ return false;
+ case ELEM_FLAG:
+ changed = edbm_extrude_ex(obedit, em, htype, BM_ELEM_SELECT, use_normal_flip, true, true);
+ break;
+ case VERT_ONLY:
+ changed = edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT);
+ break;
+ case EDGE_ONLY:
+ changed = edbm_extrude_edges_indiv(em, op, BM_ELEM_SELECT, use_normal_flip);
+ break;
+ }
+
+ if (changed) {
+ return true;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Not a valid selection for extrude");
+ return false;
+ }
}
/* extrude without transform */
static int edbm_extrude_region_exec(bContext *C, wmOperator *op)
{
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totvertsel == 0) {
- continue;
- }
-
- if (!edbm_extrude_mesh(obedit, em, op)) {
- continue;
- }
- /* This normally happens when pushing undo but modal operators
- * like this one don't push undo data until after modal mode is
- * done.*/
- EDBM_mesh_normals_update(em);
-
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
+
+ if (!edbm_extrude_mesh(obedit, em, op)) {
+ continue;
+ }
+ /* This normally happens when pushing undo but modal operators
+ * like this one don't push undo data until after modal mode is
+ * done.*/
+ EDBM_mesh_normals_update(em);
+
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_extrude_region(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Extrude Region";
- ot->idname = "MESH_OT_extrude_region";
- ot->description = "Extrude region of faces";
+ /* identifiers */
+ ot->name = "Extrude Region";
+ ot->idname = "MESH_OT_extrude_region";
+ ot->description = "Extrude region of faces";
- /* api callbacks */
- //ot->invoke = mesh_extrude_region_invoke;
- ot->exec = edbm_extrude_region_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ //ot->invoke = mesh_extrude_region_invoke;
+ ot->exec = edbm_extrude_region_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", "");
- Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
+ RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", "");
+ Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
}
/** \} */
@@ -452,46 +453,47 @@ void MESH_OT_extrude_region(wmOperatorType *ot)
/* extrude without transform */
static int edbm_extrude_context_exec(bContext *C, wmOperator *op)
{
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totvertsel == 0) {
- continue;
- }
-
- edbm_extrude_mesh(obedit, em, op);
- /* This normally happens when pushing undo but modal operators
- * like this one don't push undo data until after modal mode is
- * done.*/
-
- EDBM_mesh_normals_update(em);
-
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
+
+ edbm_extrude_mesh(obedit, em, op);
+ /* This normally happens when pushing undo but modal operators
+ * like this one don't push undo data until after modal mode is
+ * done.*/
+
+ EDBM_mesh_normals_update(em);
+
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_extrude_context(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Extrude Context";
- ot->idname = "MESH_OT_extrude_context";
- ot->description = "Extrude selection";
+ /* identifiers */
+ ot->name = "Extrude Context";
+ ot->idname = "MESH_OT_extrude_context";
+ ot->description = "Extrude selection";
- /* api callbacks */
- ot->exec = edbm_extrude_context_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_extrude_context_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", "");
- Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
+ RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", "");
+ Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
}
/** \} */
@@ -502,42 +504,43 @@ void MESH_OT_extrude_context(wmOperatorType *ot)
static int edbm_extrude_verts_exec(bContext *C, wmOperator *op)
{
- 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);
+ 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totvertsel == 0) {
- continue;
- }
+ 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->totvertsel == 0) {
+ continue;
+ }
- edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT);
+ edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT);
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_extrude_verts_indiv(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Extrude Only Vertices";
- ot->idname = "MESH_OT_extrude_verts_indiv";
- ot->description = "Extrude individual vertices only";
+ /* identifiers */
+ ot->name = "Extrude Only Vertices";
+ ot->idname = "MESH_OT_extrude_verts_indiv";
+ ot->description = "Extrude individual vertices only";
- /* api callbacks */
- ot->exec = edbm_extrude_verts_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_extrude_verts_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* to give to transform */
- Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
+ /* to give to transform */
+ Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
}
/** \} */
@@ -548,44 +551,45 @@ void MESH_OT_extrude_verts_indiv(wmOperatorType *ot)
static int edbm_extrude_edges_exec(bContext *C, wmOperator *op)
{
- const bool use_normal_flip = RNA_boolean_get(op->ptr, "use_normal_flip");
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totedgesel == 0) {
- continue;
- }
-
- edbm_extrude_edges_indiv(em, op, BM_ELEM_SELECT, use_normal_flip);
-
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ const bool use_normal_flip = RNA_boolean_get(op->ptr, "use_normal_flip");
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ if (em->bm->totedgesel == 0) {
+ continue;
+ }
+
+ edbm_extrude_edges_indiv(em, op, BM_ELEM_SELECT, use_normal_flip);
+
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_extrude_edges_indiv(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Extrude Only Edges";
- ot->idname = "MESH_OT_extrude_edges_indiv";
- ot->description = "Extrude individual edges only";
+ /* identifiers */
+ ot->name = "Extrude Only Edges";
+ ot->idname = "MESH_OT_extrude_edges_indiv";
+ ot->description = "Extrude individual edges only";
- /* api callbacks */
- ot->exec = edbm_extrude_edges_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_extrude_edges_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* to give to transform */
- RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", "");
- Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
+ /* to give to transform */
+ RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", "");
+ Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
}
/** \} */
@@ -596,41 +600,42 @@ void MESH_OT_extrude_edges_indiv(wmOperatorType *ot)
static int edbm_extrude_faces_exec(bContext *C, wmOperator *op)
{
- 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);
+ 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totfacesel == 0) {
- continue;
- }
+ 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->totfacesel == 0) {
+ continue;
+ }
- edbm_extrude_discrete_faces(em, op, BM_ELEM_SELECT);
+ edbm_extrude_discrete_faces(em, op, BM_ELEM_SELECT);
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_extrude_faces_indiv(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Extrude Individual Faces";
- ot->idname = "MESH_OT_extrude_faces_indiv";
- ot->description = "Extrude individual faces only";
+ /* identifiers */
+ ot->name = "Extrude Individual Faces";
+ ot->idname = "MESH_OT_extrude_faces_indiv";
+ ot->description = "Extrude individual faces only";
- /* api callbacks */
- ot->exec = edbm_extrude_faces_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_extrude_faces_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
+ Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
}
/** \} */
@@ -643,230 +648,235 @@ void MESH_OT_extrude_faces_indiv(wmOperatorType *ot)
static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewContext vc;
- BMVert *v1;
- BMIter iter;
- float center[3];
- uint verts_len;
-
- em_setup_viewcontext(C, &vc);
- const Object *object_active = vc.obact;
-
- const bool rot_src = RNA_boolean_get(op->ptr, "rotate_source");
- const bool use_proj = ((vc.scene->toolsettings->snap_flag & SCE_SNAP) &&
- (vc.scene->toolsettings->snap_mode == SCE_SNAP_MODE_FACE));
-
- /* First calculate the center of transformation. */
- zero_v3(center);
- verts_len = 0;
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- ED_view3d_viewcontext_init_object(&vc, obedit);
- const int local_verts_len = vc.em->bm->totvertsel;
-
- if (vc.em->bm->totvertsel == 0) {
- continue;
- }
-
- float local_center[3];
- zero_v3(local_center);
-
- BM_ITER_MESH(v1, &iter, vc.em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v1, BM_ELEM_SELECT)) {
- add_v3_v3(local_center, v1->co);
- }
- }
-
- mul_v3_fl(local_center, 1.0f / (float)local_verts_len);
- mul_m4_v3(vc.obedit->obmat, local_center);
- mul_v3_fl(local_center, (float)local_verts_len);
-
- add_v3_v3(center, local_center);
- verts_len += local_verts_len;
- }
-
- if (verts_len != 0) {
- mul_v3_fl(center, 1.0f / (float)verts_len);
- }
-
- /* Then we process the meshes. */
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- ED_view3d_viewcontext_init_object(&vc, obedit);
-
- if (verts_len != 0) {
- if (vc.em->bm->totvertsel == 0) {
- continue;
- }
- }
- else if (obedit != object_active) {
- continue;
- }
-
- invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
- ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
-
- float local_center[3];
- mul_v3_m4v3(local_center, vc.obedit->imat, center);
-
- /* call extrude? */
- if (verts_len != 0) {
- const char extrude_htype = edbm_extrude_htype_from_em_select(vc.em);
- BMEdge *eed;
- float mat[3][3];
- float vec[3], ofs[3];
- float nor[3] = { 0.0, 0.0, 0.0 };
-
- /* 2D normal calc */
- const float mval_f[2] = { (float)event->mval[0],
- (float)event->mval[1] };
-
- /* check for edges that are half selected, use for rotation */
- bool done = false;
- BM_ITER_MESH(eed, &iter, vc.em->bm, BM_EDGES_OF_MESH) {
- 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) == V3D_PROJ_RET_OK) &&
- (ED_view3d_project_float_object(vc.ar, eed->v2->co, co2, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK))
- {
- /* 2D rotate by 90d while adding.
- * (x, y) = (y, -x)
- *
- * accumulate the screenspace normal in 2D,
- * with screenspace edge length weighting the result. */
- if (line_point_side_v2(co1, co2, mval_f) >= 0.0f) {
- nor[0] += (co1[1] - co2[1]);
- nor[1] += -(co1[0] - co2[0]);
- }
- else {
- nor[0] += (co2[1] - co1[1]);
- nor[1] += -(co2[0] - co1[0]);
- }
- done = true;
- }
- }
- }
-
- if (done) {
- float view_vec[3], cross[3];
-
- /* convert the 2D normal into 3D */
- mul_mat3_m4_v3(vc.rv3d->viewinv, nor); /* worldspace */
- mul_mat3_m4_v3(vc.obedit->imat, nor); /* local space */
-
- /* correct the normal to be aligned on the view plane */
- mul_v3_mat3_m4v3(view_vec, vc.obedit->imat, vc.rv3d->viewinv[2]);
- cross_v3_v3v3(cross, nor, view_vec);
- cross_v3_v3v3(nor, view_vec, cross);
- normalize_v3(nor);
- }
-
- /* center */
- 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);
- mul_m4_v3(vc.obedit->imat, ofs); // back in object space
-
- sub_v3_v3(ofs, local_center);
-
- /* calculate rotation */
- unit_m3(mat);
- if (done) {
- float angle;
-
- normalize_v3_v3(vec, ofs);
-
- angle = angle_normalized_v3v3(vec, nor);
-
- if (angle != 0.0f) {
- float axis[3];
-
- cross_v3_v3v3(axis, nor, vec);
-
- /* halve the rotation if its applied twice */
- if (rot_src) {
- angle *= 0.5f;
- }
-
- axis_angle_to_mat3(mat, axis, angle);
- }
- }
-
- if (rot_src) {
- EDBM_op_callf(vc.em, op, "rotate verts=%hv cent=%v matrix=%m3",
- BM_ELEM_SELECT, local_center, mat);
-
- /* also project the source, for retopo workflow */
- if (use_proj) {
- EDBM_project_snap_verts(C, vc.ar, vc.em);
- }
- }
-
- edbm_extrude_ex(vc.obedit, vc.em, extrude_htype, BM_ELEM_SELECT, 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);
- }
- else {
- /* This only runs for the active object. */
- const float *cursor = vc.scene->cursor.location;
- BMOperator bmop;
- BMOIter oiter;
-
- copy_v3_v3(local_center, cursor);
- ED_view3d_win_to_3d_int(vc.v3d, vc.ar, local_center, event->mval, local_center);
-
- mul_m4_v3(vc.obedit->imat, local_center); // back in object space
-
- EDBM_op_init(vc.em, &bmop, op, "create_vert co=%v", local_center);
- BMO_op_exec(vc.em->bm, &bmop);
-
- BMO_ITER(v1, &oiter, bmop.slots_out, "vert.out", BM_VERT) {
- BM_vert_select_set(vc.em->bm, v1, true);
- }
-
- if (!EDBM_op_finish(vc.em, &bmop, op, true)) {
- continue;
- }
- }
-
- if (use_proj) {
- EDBM_project_snap_verts(C, vc.ar, vc.em);
- }
-
- /* This normally happens when pushing undo but modal operators
- * like this one don't push undo data until after modal mode is
- * done. */
- EDBM_mesh_normals_update(vc.em);
-
- EDBM_update_generic(vc.em, true, true);
- }
- MEM_freeN(objects);
+ ViewContext vc;
+ BMVert *v1;
+ BMIter iter;
+ float center[3];
+ uint verts_len;
+
+ em_setup_viewcontext(C, &vc);
+ const Object *object_active = vc.obact;
+
+ const bool rot_src = RNA_boolean_get(op->ptr, "rotate_source");
+ const bool use_proj = ((vc.scene->toolsettings->snap_flag & SCE_SNAP) &&
+ (vc.scene->toolsettings->snap_mode == SCE_SNAP_MODE_FACE));
+
+ /* First calculate the center of transformation. */
+ zero_v3(center);
+ verts_len = 0;
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ vc.view_layer, vc.v3d, &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ ED_view3d_viewcontext_init_object(&vc, obedit);
+ const int local_verts_len = vc.em->bm->totvertsel;
+
+ if (vc.em->bm->totvertsel == 0) {
+ continue;
+ }
+
+ float local_center[3];
+ zero_v3(local_center);
+
+ BM_ITER_MESH (v1, &iter, vc.em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v1, BM_ELEM_SELECT)) {
+ add_v3_v3(local_center, v1->co);
+ }
+ }
+
+ mul_v3_fl(local_center, 1.0f / (float)local_verts_len);
+ mul_m4_v3(vc.obedit->obmat, local_center);
+ mul_v3_fl(local_center, (float)local_verts_len);
+
+ add_v3_v3(center, local_center);
+ verts_len += local_verts_len;
+ }
+
+ if (verts_len != 0) {
+ mul_v3_fl(center, 1.0f / (float)verts_len);
+ }
+
+ /* Then we process the meshes. */
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ ED_view3d_viewcontext_init_object(&vc, obedit);
+
+ if (verts_len != 0) {
+ if (vc.em->bm->totvertsel == 0) {
+ continue;
+ }
+ }
+ else if (obedit != object_active) {
+ continue;
+ }
+
+ invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
+ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
+
+ float local_center[3];
+ mul_v3_m4v3(local_center, vc.obedit->imat, center);
+
+ /* call extrude? */
+ if (verts_len != 0) {
+ const char extrude_htype = edbm_extrude_htype_from_em_select(vc.em);
+ BMEdge *eed;
+ float mat[3][3];
+ float vec[3], ofs[3];
+ float nor[3] = {0.0, 0.0, 0.0};
+
+ /* 2D normal calc */
+ const float mval_f[2] = {(float)event->mval[0], (float)event->mval[1]};
+
+ /* check for edges that are half selected, use for rotation */
+ bool done = false;
+ BM_ITER_MESH (eed, &iter, vc.em->bm, BM_EDGES_OF_MESH) {
+ 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) ==
+ V3D_PROJ_RET_OK) &&
+ (ED_view3d_project_float_object(vc.ar, eed->v2->co, co2, V3D_PROJ_TEST_NOP) ==
+ V3D_PROJ_RET_OK)) {
+ /* 2D rotate by 90d while adding.
+ * (x, y) = (y, -x)
+ *
+ * accumulate the screenspace normal in 2D,
+ * with screenspace edge length weighting the result. */
+ if (line_point_side_v2(co1, co2, mval_f) >= 0.0f) {
+ nor[0] += (co1[1] - co2[1]);
+ nor[1] += -(co1[0] - co2[0]);
+ }
+ else {
+ nor[0] += (co2[1] - co1[1]);
+ nor[1] += -(co2[0] - co1[0]);
+ }
+ done = true;
+ }
+ }
+ }
+
+ if (done) {
+ float view_vec[3], cross[3];
+
+ /* convert the 2D normal into 3D */
+ mul_mat3_m4_v3(vc.rv3d->viewinv, nor); /* worldspace */
+ mul_mat3_m4_v3(vc.obedit->imat, nor); /* local space */
+
+ /* correct the normal to be aligned on the view plane */
+ mul_v3_mat3_m4v3(view_vec, vc.obedit->imat, vc.rv3d->viewinv[2]);
+ cross_v3_v3v3(cross, nor, view_vec);
+ cross_v3_v3v3(nor, view_vec, cross);
+ normalize_v3(nor);
+ }
+
+ /* center */
+ 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);
+ mul_m4_v3(vc.obedit->imat, ofs); // back in object space
+
+ sub_v3_v3(ofs, local_center);
+
+ /* calculate rotation */
+ unit_m3(mat);
+ if (done) {
+ float angle;
+
+ normalize_v3_v3(vec, ofs);
+
+ angle = angle_normalized_v3v3(vec, nor);
+
+ if (angle != 0.0f) {
+ float axis[3];
+
+ cross_v3_v3v3(axis, nor, vec);
+
+ /* halve the rotation if its applied twice */
+ if (rot_src) {
+ angle *= 0.5f;
+ }
+
+ axis_angle_to_mat3(mat, axis, angle);
+ }
+ }
+
+ if (rot_src) {
+ EDBM_op_callf(
+ vc.em, op, "rotate verts=%hv cent=%v matrix=%m3", BM_ELEM_SELECT, local_center, mat);
+
+ /* also project the source, for retopo workflow */
+ if (use_proj) {
+ EDBM_project_snap_verts(C, vc.ar, vc.em);
+ }
+ }
+
+ edbm_extrude_ex(vc.obedit, vc.em, extrude_htype, BM_ELEM_SELECT, 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);
+ }
+ else {
+ /* This only runs for the active object. */
+ const float *cursor = vc.scene->cursor.location;
+ BMOperator bmop;
+ BMOIter oiter;
+
+ copy_v3_v3(local_center, cursor);
+ ED_view3d_win_to_3d_int(vc.v3d, vc.ar, local_center, event->mval, local_center);
+
+ mul_m4_v3(vc.obedit->imat, local_center); // back in object space
+
+ EDBM_op_init(vc.em, &bmop, op, "create_vert co=%v", local_center);
+ BMO_op_exec(vc.em->bm, &bmop);
+
+ BMO_ITER (v1, &oiter, bmop.slots_out, "vert.out", BM_VERT) {
+ BM_vert_select_set(vc.em->bm, v1, true);
+ }
+
+ if (!EDBM_op_finish(vc.em, &bmop, op, true)) {
+ continue;
+ }
+ }
+
+ if (use_proj) {
+ EDBM_project_snap_verts(C, vc.ar, vc.em);
+ }
+
+ /* This normally happens when pushing undo but modal operators
+ * like this one don't push undo data until after modal mode is
+ * done. */
+ EDBM_mesh_normals_update(vc.em);
+
+ EDBM_update_generic(vc.em, true, true);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Duplicate or Extrude to Cursor";
- ot->idname = "MESH_OT_dupli_extrude_cursor";
- ot->description = "Duplicate and extrude selected vertices, edges or faces towards the mouse cursor";
-
- /* api callbacks */
- ot->invoke = edbm_dupli_extrude_cursor_invoke;
- ot->poll = ED_operator_editmesh_region_view3d;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "rotate_source", true, "Rotate Source", "Rotate initial selection giving better shape");
+ /* identifiers */
+ ot->name = "Duplicate or Extrude to Cursor";
+ ot->idname = "MESH_OT_dupli_extrude_cursor";
+ ot->description =
+ "Duplicate and extrude selected vertices, edges or faces towards the mouse cursor";
+
+ /* api callbacks */
+ ot->invoke = edbm_dupli_extrude_cursor_invoke;
+ ot->poll = ED_operator_editmesh_region_view3d;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna,
+ "rotate_source",
+ true,
+ "Rotate Source",
+ "Rotate initial selection giving better shape");
}
/** \} */
diff --git a/source/blender/editors/mesh/editmesh_extrude_screw.c b/source/blender/editors/mesh/editmesh_extrude_screw.c
index 4b3a93a2111..c9422545c7b 100644
--- a/source/blender/editors/mesh/editmesh_extrude_screw.c
+++ b/source/blender/editors/mesh/editmesh_extrude_screw.c
@@ -41,7 +41,7 @@
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Screw Operator
@@ -49,158 +49,178 @@
static int edbm_screw_exec(bContext *C, wmOperator *op)
{
- BMEdge *eed;
- BMVert *eve, *v1, *v2;
- BMIter iter, eiter;
- float dvec[3], nor[3], cent[3], axis[3], v1_co_global[3], v2_co_global[3];
- int steps, turns;
- int valence;
- uint objects_empty_len = 0;
- uint failed_axis_len = 0;
- uint failed_vertices_len = 0;
-
- turns = RNA_int_get(op->ptr, "turns");
- steps = RNA_int_get(op->ptr, "steps");
- RNA_float_get_array(op->ptr, "center", cent);
- RNA_float_get_array(op->ptr, "axis", axis);
-
- uint objects_len = 0;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- if (bm->totvertsel < 2) {
- if (bm->totvertsel == 0) {
- objects_empty_len++;
- }
- continue;
- }
-
- if (is_zero_v3(axis)) {
- failed_axis_len++;
- continue;
- }
-
- /* find two vertices with valence count == 1, more or less is wrong */
- v1 = NULL;
- v2 = NULL;
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- valence = 0;
- BM_ITER_ELEM (eed, &eiter, eve, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- valence++;
- }
- }
-
- if (valence == 1) {
- if (v1 == NULL) {
- v1 = eve;
- }
- else if (v2 == NULL) {
- v2 = eve;
- }
- else {
- v1 = NULL;
- break;
- }
- }
- }
-
- if (v1 == NULL || v2 == NULL) {
- failed_vertices_len++;
- continue;
- }
-
- copy_v3_v3(nor, obedit->obmat[2]);
-
- /* calculate dvec */
- mul_v3_m4v3(v1_co_global, obedit->obmat, v1->co);
- mul_v3_m4v3(v2_co_global, obedit->obmat, v2->co);
- sub_v3_v3v3(dvec, v1_co_global, v2_co_global);
- mul_v3_fl(dvec, 1.0f / steps);
-
- if (dot_v3v3(nor, dvec) > 0.0f)
- negate_v3(dvec);
-
- BMOperator spinop;
- if (!EDBM_op_init(em, &spinop, op,
- "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i angle=%f space=%m4 use_duplicate=%b",
- BM_ELEM_SELECT, cent, axis, dvec, turns * steps, DEG2RADF(360.0f * turns), obedit->obmat, false))
- {
- continue;
- }
-
- BMO_op_exec(bm, &spinop);
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_slot_buffer_hflag_enable(bm, spinop.slots_out, "geom_last.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
-
- if (!EDBM_op_finish(em, &spinop, op, true)) {
- continue;
- }
-
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
-
- if (failed_axis_len == objects_len - objects_empty_len) {
- BKE_report(op->reports, RPT_ERROR, "Invalid/unset axis");
- }
- else if (failed_vertices_len == objects_len - objects_empty_len) {
- BKE_report(op->reports, RPT_ERROR, "You have to select a string of connected vertices too");
- }
-
- return OPERATOR_FINISHED;
+ BMEdge *eed;
+ BMVert *eve, *v1, *v2;
+ BMIter iter, eiter;
+ float dvec[3], nor[3], cent[3], axis[3], v1_co_global[3], v2_co_global[3];
+ int steps, turns;
+ int valence;
+ uint objects_empty_len = 0;
+ uint failed_axis_len = 0;
+ uint failed_vertices_len = 0;
+
+ turns = RNA_int_get(op->ptr, "turns");
+ steps = RNA_int_get(op->ptr, "steps");
+ RNA_float_get_array(op->ptr, "center", cent);
+ RNA_float_get_array(op->ptr, "axis", axis);
+
+ uint objects_len = 0;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ if (bm->totvertsel < 2) {
+ if (bm->totvertsel == 0) {
+ objects_empty_len++;
+ }
+ continue;
+ }
+
+ if (is_zero_v3(axis)) {
+ failed_axis_len++;
+ continue;
+ }
+
+ /* find two vertices with valence count == 1, more or less is wrong */
+ v1 = NULL;
+ v2 = NULL;
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ valence = 0;
+ BM_ITER_ELEM (eed, &eiter, eve, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ valence++;
+ }
+ }
+
+ if (valence == 1) {
+ if (v1 == NULL) {
+ v1 = eve;
+ }
+ else if (v2 == NULL) {
+ v2 = eve;
+ }
+ else {
+ v1 = NULL;
+ break;
+ }
+ }
+ }
+
+ if (v1 == NULL || v2 == NULL) {
+ failed_vertices_len++;
+ continue;
+ }
+
+ copy_v3_v3(nor, obedit->obmat[2]);
+
+ /* calculate dvec */
+ mul_v3_m4v3(v1_co_global, obedit->obmat, v1->co);
+ mul_v3_m4v3(v2_co_global, obedit->obmat, v2->co);
+ sub_v3_v3v3(dvec, v1_co_global, v2_co_global);
+ mul_v3_fl(dvec, 1.0f / steps);
+
+ if (dot_v3v3(nor, dvec) > 0.0f)
+ negate_v3(dvec);
+
+ BMOperator spinop;
+ if (!EDBM_op_init(
+ em,
+ &spinop,
+ op,
+ "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i angle=%f space=%m4 use_duplicate=%b",
+ BM_ELEM_SELECT,
+ cent,
+ axis,
+ dvec,
+ turns * steps,
+ DEG2RADF(360.0f * turns),
+ obedit->obmat,
+ false)) {
+ continue;
+ }
+
+ BMO_op_exec(bm, &spinop);
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BMO_slot_buffer_hflag_enable(
+ bm, spinop.slots_out, "geom_last.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
+
+ if (!EDBM_op_finish(em, &spinop, op, true)) {
+ continue;
+ }
+
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
+
+ if (failed_axis_len == objects_len - objects_empty_len) {
+ BKE_report(op->reports, RPT_ERROR, "Invalid/unset axis");
+ }
+ else if (failed_vertices_len == objects_len - objects_empty_len) {
+ BKE_report(op->reports, RPT_ERROR, "You have to select a string of connected vertices too");
+ }
+
+ return OPERATOR_FINISHED;
}
/* get center and axis, in global coords */
static int edbm_screw_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Scene *scene = CTX_data_scene(C);
- RegionView3D *rv3d = ED_view3d_context_rv3d(C);
-
- PropertyRNA *prop;
- prop = RNA_struct_find_property(op->ptr, "center");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_float_set_array(op->ptr, prop, scene->cursor.location);
- }
- if (rv3d) {
- prop = RNA_struct_find_property(op->ptr, "axis");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_float_set_array(op->ptr, prop, rv3d->viewinv[1]);
- }
- }
-
- return edbm_screw_exec(C, op);
+ Scene *scene = CTX_data_scene(C);
+ RegionView3D *rv3d = ED_view3d_context_rv3d(C);
+
+ PropertyRNA *prop;
+ prop = RNA_struct_find_property(op->ptr, "center");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_float_set_array(op->ptr, prop, scene->cursor.location);
+ }
+ if (rv3d) {
+ prop = RNA_struct_find_property(op->ptr, "axis");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_float_set_array(op->ptr, prop, rv3d->viewinv[1]);
+ }
+ }
+
+ return edbm_screw_exec(C, op);
}
void MESH_OT_screw(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Screw";
- ot->description = "Extrude selected vertices in screw-shaped rotation around the cursor in indicated viewport";
- ot->idname = "MESH_OT_screw";
-
- /* api callbacks */
- ot->invoke = edbm_screw_invoke;
- ot->exec = edbm_screw_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- RNA_def_int(ot->srna, "steps", 9, 1, 100000, "Steps", "Steps", 3, 256);
- RNA_def_int(ot->srna, "turns", 1, 1, 100000, "Turns", "Turns", 1, 256);
-
- RNA_def_float_vector_xyz(ot->srna, "center", 3, NULL, -1e12f, 1e12f,
- "Center", "Center in global view space", -1e4f, 1e4f);
- RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f,
- "Axis", "Axis in global view space", -1.0f, 1.0f);
+ /* identifiers */
+ ot->name = "Screw";
+ ot->description =
+ "Extrude selected vertices in screw-shaped rotation around the cursor in indicated viewport";
+ ot->idname = "MESH_OT_screw";
+
+ /* api callbacks */
+ ot->invoke = edbm_screw_invoke;
+ ot->exec = edbm_screw_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "steps", 9, 1, 100000, "Steps", "Steps", 3, 256);
+ RNA_def_int(ot->srna, "turns", 1, 1, 100000, "Turns", "Turns", 1, 256);
+
+ RNA_def_float_vector_xyz(ot->srna,
+ "center",
+ 3,
+ NULL,
+ -1e12f,
+ 1e12f,
+ "Center",
+ "Center in global view space",
+ -1e4f,
+ 1e4f);
+ RNA_def_float_vector(
+ ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -1.0f, 1.0f);
}
/** \} */
diff --git a/source/blender/editors/mesh/editmesh_extrude_spin.c b/source/blender/editors/mesh/editmesh_extrude_spin.c
index a098751fd21..c546e9b866f 100644
--- a/source/blender/editors/mesh/editmesh_extrude_spin.c
+++ b/source/blender/editors/mesh/editmesh_extrude_spin.c
@@ -45,7 +45,7 @@
#include "MEM_guardedalloc.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
#define USE_GIZMO
@@ -55,158 +55,185 @@
static int edbm_spin_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- float cent[3], axis[3];
- float d[3] = {0.0f, 0.0f, 0.0f};
-
- RNA_float_get_array(op->ptr, "center", cent);
- RNA_float_get_array(op->ptr, "axis", axis);
- const int steps = RNA_int_get(op->ptr, "steps");
- const float angle = RNA_float_get(op->ptr, "angle");
- const bool use_normal_flip = RNA_boolean_get(op->ptr, "use_normal_flip");
- const bool dupli = RNA_boolean_get(op->ptr, "dupli");
- const bool use_auto_merge = (
- RNA_boolean_get(op->ptr, "use_auto_merge") &&
- (dupli == false) &&
- (steps >= 3) &&
- fabsf((fabsf(angle) - (float)(M_PI * 2))) <= 1e-6f);
-
- if (is_zero_v3(axis)) {
- BKE_report(op->reports, RPT_ERROR, "Invalid/unset axis");
- return OPERATOR_CANCELLED;
- }
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMOperator spinop;
-
- /* keep the values in worldspace since we're passing the obmat */
- if (!EDBM_op_init(
- em, &spinop, op,
- "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i angle=%f space=%m4 "
- "use_normal_flip=%b use_duplicate=%b use_merge=%b",
- BM_ELEM_SELECT, cent, axis, d, steps, -angle, obedit->obmat,
- use_normal_flip, dupli, use_auto_merge))
- {
- continue;
- }
- BMO_op_exec(bm, &spinop);
- if (use_auto_merge == false) {
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_slot_buffer_hflag_enable(bm, spinop.slots_out, "geom_last.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
- }
- if (!EDBM_op_finish(em, &spinop, op, true)) {
- continue;
- }
-
- EDBM_update_generic(em, true, true);
- }
-
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ float cent[3], axis[3];
+ float d[3] = {0.0f, 0.0f, 0.0f};
+
+ RNA_float_get_array(op->ptr, "center", cent);
+ RNA_float_get_array(op->ptr, "axis", axis);
+ const int steps = RNA_int_get(op->ptr, "steps");
+ const float angle = RNA_float_get(op->ptr, "angle");
+ const bool use_normal_flip = RNA_boolean_get(op->ptr, "use_normal_flip");
+ const bool dupli = RNA_boolean_get(op->ptr, "dupli");
+ const bool use_auto_merge = (RNA_boolean_get(op->ptr, "use_auto_merge") && (dupli == false) &&
+ (steps >= 3) && fabsf((fabsf(angle) - (float)(M_PI * 2))) <= 1e-6f);
+
+ if (is_zero_v3(axis)) {
+ BKE_report(op->reports, RPT_ERROR, "Invalid/unset axis");
+ return OPERATOR_CANCELLED;
+ }
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMOperator spinop;
+
+ /* keep the values in worldspace since we're passing the obmat */
+ if (!EDBM_op_init(em,
+ &spinop,
+ op,
+ "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i angle=%f space=%m4 "
+ "use_normal_flip=%b use_duplicate=%b use_merge=%b",
+ BM_ELEM_SELECT,
+ cent,
+ axis,
+ d,
+ steps,
+ -angle,
+ obedit->obmat,
+ use_normal_flip,
+ dupli,
+ use_auto_merge)) {
+ continue;
+ }
+ BMO_op_exec(bm, &spinop);
+ if (use_auto_merge == false) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BMO_slot_buffer_hflag_enable(
+ bm, spinop.slots_out, "geom_last.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
+ }
+ if (!EDBM_op_finish(em, &spinop, op, true)) {
+ continue;
+ }
+
+ EDBM_update_generic(em, true, true);
+ }
+
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
/* get center and axis, in global coords */
static int edbm_spin_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = ED_view3d_context_rv3d(C);
-
- PropertyRNA *prop;
- prop = RNA_struct_find_property(op->ptr, "center");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_float_set_array(op->ptr, prop, scene->cursor.location);
- }
- if (rv3d) {
- prop = RNA_struct_find_property(op->ptr, "axis");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_float_set_array(op->ptr, prop, rv3d->viewinv[2]);
- }
- }
-
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = ED_view3d_context_rv3d(C);
+
+ PropertyRNA *prop;
+ prop = RNA_struct_find_property(op->ptr, "center");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_float_set_array(op->ptr, prop, scene->cursor.location);
+ }
+ if (rv3d) {
+ prop = RNA_struct_find_property(op->ptr, "axis");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_float_set_array(op->ptr, prop, rv3d->viewinv[2]);
+ }
+ }
#ifdef USE_GIZMO
- /* Start with zero angle, drag out the value. */
- prop = RNA_struct_find_property(op->ptr, "angle");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_float_set(op->ptr, prop, 0.0f);
- }
+ /* Start with zero angle, drag out the value. */
+ prop = RNA_struct_find_property(op->ptr, "angle");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_float_set(op->ptr, prop, 0.0f);
+ }
#endif
- int ret = edbm_spin_exec(C, op);
+ int ret = edbm_spin_exec(C, op);
#ifdef USE_GIZMO
- if (ret & OPERATOR_FINISHED) {
- /* Setup gizmos */
- if (v3d && ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0)) {
- wmGizmoGroupType *gzgt = WM_gizmogrouptype_find("MESH_GGT_spin_redo", false);
- if (!WM_gizmo_group_type_ensure_ptr(gzgt)) {
- struct Main *bmain = CTX_data_main(C);
- WM_gizmo_group_type_reinit_ptr(bmain, gzgt);
- }
- }
- }
+ if (ret & OPERATOR_FINISHED) {
+ /* Setup gizmos */
+ if (v3d && ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0)) {
+ wmGizmoGroupType *gzgt = WM_gizmogrouptype_find("MESH_GGT_spin_redo", false);
+ if (!WM_gizmo_group_type_ensure_ptr(gzgt)) {
+ struct Main *bmain = CTX_data_main(C);
+ WM_gizmo_group_type_reinit_ptr(bmain, gzgt);
+ }
+ }
+ }
#endif
- return ret;
+ return ret;
}
-static bool edbm_spin_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop)
+static bool edbm_spin_poll_property(const bContext *UNUSED(C),
+ wmOperator *op,
+ const PropertyRNA *prop)
{
- const char *prop_id = RNA_property_identifier(prop);
- const bool dupli = RNA_boolean_get(op->ptr, "dupli");
-
- if (dupli) {
- if (STREQ(prop_id, "use_auto_merge") ||
- STREQ(prop_id, "use_normal_flip"))
- {
- return false;
- }
- }
- return true;
+ const char *prop_id = RNA_property_identifier(prop);
+ const bool dupli = RNA_boolean_get(op->ptr, "dupli");
+
+ if (dupli) {
+ if (STREQ(prop_id, "use_auto_merge") || STREQ(prop_id, "use_normal_flip")) {
+ return false;
+ }
+ }
+ return true;
}
void MESH_OT_spin(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Spin";
- ot->description = "Extrude selected vertices in a circle around the cursor in indicated viewport";
- ot->idname = "MESH_OT_spin";
-
- /* api callbacks */
- ot->invoke = edbm_spin_invoke;
- ot->exec = edbm_spin_exec;
- ot->poll = ED_operator_editmesh;
- ot->poll_property = edbm_spin_poll_property;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- RNA_def_int(ot->srna, "steps", 9, 0, 1000000, "Steps", "Steps", 0, 1000);
- RNA_def_boolean(ot->srna, "dupli", 0, "Dupli", "Make Duplicates");
- prop = RNA_def_float(ot->srna, "angle", DEG2RADF(90.0f), -1e12f, 1e12f, "Angle", "Rotation for each step",
- DEG2RADF(-360.0f), DEG2RADF(360.0f));
- RNA_def_property_subtype(prop, PROP_ANGLE);
- RNA_def_boolean(ot->srna, "use_auto_merge", true, "Auto Merge", "Merge first/last when the angle is a full revolution");
- RNA_def_boolean(ot->srna, "use_normal_flip", 0, "Flip Normals", "");
-
- RNA_def_float_vector_xyz(ot->srna, "center", 3, NULL, -1e12f, 1e12f,
- "Center", "Center in global view space", -1e4f, 1e4f);
- RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -1.0f, 1.0f);
-
- WM_gizmogrouptype_append(MESH_GGT_spin);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Spin";
+ ot->description =
+ "Extrude selected vertices in a circle around the cursor in indicated viewport";
+ ot->idname = "MESH_OT_spin";
+
+ /* api callbacks */
+ ot->invoke = edbm_spin_invoke;
+ ot->exec = edbm_spin_exec;
+ ot->poll = ED_operator_editmesh;
+ ot->poll_property = edbm_spin_poll_property;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "steps", 9, 0, 1000000, "Steps", "Steps", 0, 1000);
+ RNA_def_boolean(ot->srna, "dupli", 0, "Dupli", "Make Duplicates");
+ prop = RNA_def_float(ot->srna,
+ "angle",
+ DEG2RADF(90.0f),
+ -1e12f,
+ 1e12f,
+ "Angle",
+ "Rotation for each step",
+ DEG2RADF(-360.0f),
+ DEG2RADF(360.0f));
+ RNA_def_property_subtype(prop, PROP_ANGLE);
+ RNA_def_boolean(ot->srna,
+ "use_auto_merge",
+ true,
+ "Auto Merge",
+ "Merge first/last when the angle is a full revolution");
+ RNA_def_boolean(ot->srna, "use_normal_flip", 0, "Flip Normals", "");
+
+ RNA_def_float_vector_xyz(ot->srna,
+ "center",
+ 3,
+ NULL,
+ -1e12f,
+ 1e12f,
+ "Center",
+ "Center in global view space",
+ -1e4f,
+ 1e4f);
+ RNA_def_float_vector(
+ ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -1.0f, 1.0f);
+
+ WM_gizmogrouptype_append(MESH_GGT_spin);
#ifdef USE_GIZMO
- WM_gizmogrouptype_append(MESH_GGT_spin_redo);
+ WM_gizmogrouptype_append(MESH_GGT_spin_redo);
#endif
}
diff --git a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
index 1ff7d835aad..85be7d902ad 100644
--- a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
+++ b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
@@ -40,7 +40,7 @@
#include "MEM_guardedalloc.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
#include "ED_transform.h"
@@ -67,32 +67,32 @@ static const float dial_angle_partial_margin = 0.92f;
* \{ */
typedef struct GizmoGroupData_SpinInit {
- struct {
- wmGizmo *xyz_view[4];
- wmGizmo *icon_button[3][2];
- } gizmos;
-
- /* Only for view orientation. */
- struct {
- float viewinv_m3[3][3];
- } prev;
-
- /* We could store more vars here! */
- struct {
- wmOperatorType *ot_spin;
- PropertyRNA *gzgt_axis_prop;
- float orient_mat[3][3];
+ struct {
+ wmGizmo *xyz_view[4];
+ wmGizmo *icon_button[3][2];
+ } gizmos;
+
+ /* Only for view orientation. */
+ struct {
+ float viewinv_m3[3][3];
+ } prev;
+
+ /* We could store more vars here! */
+ struct {
+ wmOperatorType *ot_spin;
+ PropertyRNA *gzgt_axis_prop;
+ float orient_mat[3][3];
#ifdef USE_SELECT_CENTER
- float select_center[3];
- float select_center_ortho_axis[3][3];
- bool use_select_center;
+ float select_center[3];
+ float select_center_ortho_axis[3][3];
+ bool use_select_center;
#endif
- } data;
+ } data;
- /* Store data for invoke. */
- struct {
- int ortho_axis_active;
- } invoke;
+ /* Store data for invoke. */
+ struct {
+ int ortho_axis_active;
+ } invoke;
} GizmoGroupData_SpinInit;
@@ -103,374 +103,376 @@ typedef struct GizmoGroupData_SpinInit {
#define INIT_SCALE_BUTTON 0.15f
static const uchar shape_plus[] = {
- 0x5f, 0xfb, 0x40, 0xee, 0x25, 0xda, 0x11, 0xbf, 0x4, 0xa0, 0x0, 0x80, 0x4, 0x5f, 0x11,
- 0x40, 0x25, 0x25, 0x40, 0x11, 0x5f, 0x4, 0x7f, 0x0, 0xa0, 0x4, 0xbf, 0x11, 0xda, 0x25,
- 0xee, 0x40, 0xfb, 0x5f, 0xff, 0x7f, 0xfb, 0xa0, 0xee, 0xbf, 0xda, 0xda, 0xbf, 0xee,
- 0xa0, 0xfb, 0x80, 0xff, 0x6e, 0xd7, 0x92, 0xd7, 0x92, 0x90, 0xd8, 0x90, 0xd8, 0x6d,
- 0x92, 0x6d, 0x92, 0x27, 0x6e, 0x27, 0x6e, 0x6d, 0x28, 0x6d, 0x28, 0x90, 0x6e,
- 0x90, 0x6e, 0xd7, 0x80, 0xff, 0x5f, 0xfb, 0x5f, 0xfb,
+ 0x5f, 0xfb, 0x40, 0xee, 0x25, 0xda, 0x11, 0xbf, 0x4, 0xa0, 0x0, 0x80, 0x4, 0x5f, 0x11, 0x40,
+ 0x25, 0x25, 0x40, 0x11, 0x5f, 0x4, 0x7f, 0x0, 0xa0, 0x4, 0xbf, 0x11, 0xda, 0x25, 0xee, 0x40,
+ 0xfb, 0x5f, 0xff, 0x7f, 0xfb, 0xa0, 0xee, 0xbf, 0xda, 0xda, 0xbf, 0xee, 0xa0, 0xfb, 0x80, 0xff,
+ 0x6e, 0xd7, 0x92, 0xd7, 0x92, 0x90, 0xd8, 0x90, 0xd8, 0x6d, 0x92, 0x6d, 0x92, 0x27, 0x6e, 0x27,
+ 0x6e, 0x6d, 0x28, 0x6d, 0x28, 0x90, 0x6e, 0x90, 0x6e, 0xd7, 0x80, 0xff, 0x5f, 0xfb, 0x5f, 0xfb,
};
static void gizmo_mesh_spin_init_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- /* alpha values for normal/highlighted states */
- const float alpha = 0.6f;
- const float alpha_hi = 1.0f;
- const float scale_base = INIT_SCALE_BASE;
- const float scale_button = INIT_SCALE_BUTTON;
-
- GizmoGroupData_SpinInit *ggd = MEM_callocN(sizeof(*ggd), __func__);
- gzgroup->customdata = ggd;
- const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true);
- const wmGizmoType *gzt_button = WM_gizmotype_find("GIZMO_GT_button_2d", true);
-
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 2; j++) {
- wmGizmo *gz = WM_gizmo_new_ptr(gzt_button, gzgroup, NULL);
- PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "shape");
- RNA_property_string_set_bytes(
- gz->ptr, prop,
- (const char *)shape_plus, ARRAY_SIZE(shape_plus));
-
- float color[4];
- UI_GetThemeColor3fv(TH_AXIS_X + i, color);
- color[3] = alpha;
- WM_gizmo_set_color(gz, color);
-
- WM_gizmo_set_scale(gz, scale_button);
- gz->color[3] = 0.6f;
-
- gz->flag |= WM_GIZMO_DRAW_OFFSET_SCALE | WM_GIZMO_OPERATOR_TOOL_INIT;
-
- ggd->gizmos.icon_button[i][j] = gz;
- }
- }
-
- for (int i = 0; i < ARRAY_SIZE(ggd->gizmos.xyz_view); i++) {
- wmGizmo *gz = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL);
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
- WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_VALUE | WM_GIZMO_HIDDEN_SELECT, true);
- ggd->gizmos.xyz_view[i] = gz;
- }
-
- for (int i = 0; i < 3; i++) {
- wmGizmo *gz = ggd->gizmos.xyz_view[i];
+ /* alpha values for normal/highlighted states */
+ const float alpha = 0.6f;
+ const float alpha_hi = 1.0f;
+ const float scale_base = INIT_SCALE_BASE;
+ const float scale_button = INIT_SCALE_BUTTON;
+
+ GizmoGroupData_SpinInit *ggd = MEM_callocN(sizeof(*ggd), __func__);
+ gzgroup->customdata = ggd;
+ const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true);
+ const wmGizmoType *gzt_button = WM_gizmotype_find("GIZMO_GT_button_2d", true);
+
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 2; j++) {
+ wmGizmo *gz = WM_gizmo_new_ptr(gzt_button, gzgroup, NULL);
+ PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "shape");
+ RNA_property_string_set_bytes(
+ gz->ptr, prop, (const char *)shape_plus, ARRAY_SIZE(shape_plus));
+
+ float color[4];
+ UI_GetThemeColor3fv(TH_AXIS_X + i, color);
+ color[3] = alpha;
+ WM_gizmo_set_color(gz, color);
+
+ WM_gizmo_set_scale(gz, scale_button);
+ gz->color[3] = 0.6f;
+
+ gz->flag |= WM_GIZMO_DRAW_OFFSET_SCALE | WM_GIZMO_OPERATOR_TOOL_INIT;
+
+ ggd->gizmos.icon_button[i][j] = gz;
+ }
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(ggd->gizmos.xyz_view); i++) {
+ wmGizmo *gz = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL);
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_VALUE | WM_GIZMO_HIDDEN_SELECT, true);
+ ggd->gizmos.xyz_view[i] = gz;
+ }
+
+ for (int i = 0; i < 3; i++) {
+ wmGizmo *gz = ggd->gizmos.xyz_view[i];
#ifndef USE_DIAL_HOVER
- RNA_enum_set(gz->ptr, "draw_options", ED_GIZMO_DIAL_DRAW_FLAG_CLIP);
+ RNA_enum_set(gz->ptr, "draw_options", ED_GIZMO_DIAL_DRAW_FLAG_CLIP);
#endif
- WM_gizmo_set_line_width(gz, 2.0f);
- float color[4];
- UI_GetThemeColor3fv(TH_AXIS_X + i, color);
- color[3] = alpha;
- WM_gizmo_set_color(gz, color);
- color[3] = alpha_hi;
- WM_gizmo_set_color_highlight(gz, color);
- WM_gizmo_set_scale(gz, INIT_SCALE_BASE);
- RNA_float_set(gz->ptr, "arc_partial_angle", (M_PI * 2) - (dial_angle_partial * dial_angle_partial_margin));
- }
-
- {
- wmGizmo *gz = ggd->gizmos.xyz_view[3];
- WM_gizmo_set_line_width(gz, 2.0f);
- float color[4];
- copy_v3_fl(color, 1.0f);
- color[3] = alpha;
- WM_gizmo_set_color(gz, color);
- color[3] = alpha_hi;
- WM_gizmo_set_color_highlight(gz, color);
- WM_gizmo_set_scale(gz, scale_base);
- }
-
+ WM_gizmo_set_line_width(gz, 2.0f);
+ float color[4];
+ UI_GetThemeColor3fv(TH_AXIS_X + i, color);
+ color[3] = alpha;
+ WM_gizmo_set_color(gz, color);
+ color[3] = alpha_hi;
+ WM_gizmo_set_color_highlight(gz, color);
+ WM_gizmo_set_scale(gz, INIT_SCALE_BASE);
+ RNA_float_set(gz->ptr,
+ "arc_partial_angle",
+ (M_PI * 2) - (dial_angle_partial * dial_angle_partial_margin));
+ }
+
+ {
+ wmGizmo *gz = ggd->gizmos.xyz_view[3];
+ WM_gizmo_set_line_width(gz, 2.0f);
+ float color[4];
+ copy_v3_fl(color, 1.0f);
+ color[3] = alpha;
+ WM_gizmo_set_color(gz, color);
+ color[3] = alpha_hi;
+ WM_gizmo_set_color_highlight(gz, color);
+ WM_gizmo_set_scale(gz, scale_base);
+ }
#ifdef USE_DIAL_HOVER
- for (int i = 0; i < 4; i++) {
- wmGizmo *gz = ggd->gizmos.xyz_view[i];
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
- }
+ for (int i = 0; i < 4; i++) {
+ wmGizmo *gz = ggd->gizmos.xyz_view[i];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
+ }
#endif
- ggd->data.ot_spin = WM_operatortype_find("MESH_OT_spin", true);
- ggd->data.gzgt_axis_prop = RNA_struct_type_find_property(gzgroup->type->srna, "axis");
+ ggd->data.ot_spin = WM_operatortype_find("MESH_OT_spin", true);
+ ggd->data.gzgt_axis_prop = RNA_struct_type_find_property(gzgroup->type->srna, "axis");
}
static void gizmo_mesh_spin_init_refresh(const bContext *C, wmGizmoGroup *gzgroup);
-static void gizmo_mesh_spin_init_refresh_axis_orientation(
- wmGizmoGroup *gzgroup,
- int axis_index, const float axis_vec[3], const float axis_tan[3])
+static void gizmo_mesh_spin_init_refresh_axis_orientation(wmGizmoGroup *gzgroup,
+ int axis_index,
+ const float axis_vec[3],
+ const float axis_tan[3])
{
- GizmoGroupData_SpinInit *ggd = gzgroup->customdata;
- wmGizmo *gz = ggd->gizmos.xyz_view[axis_index];
- if (axis_tan != NULL) {
- WM_gizmo_set_matrix_rotation_from_yz_axis(gz, axis_tan, axis_vec);
- }
- else {
- WM_gizmo_set_matrix_rotation_from_z_axis(gz, axis_vec);
- }
-
- /* Only for display, use icons to access. */
+ GizmoGroupData_SpinInit *ggd = gzgroup->customdata;
+ wmGizmo *gz = ggd->gizmos.xyz_view[axis_index];
+ if (axis_tan != NULL) {
+ WM_gizmo_set_matrix_rotation_from_yz_axis(gz, axis_tan, axis_vec);
+ }
+ else {
+ WM_gizmo_set_matrix_rotation_from_z_axis(gz, axis_vec);
+ }
+
+ /* Only for display, use icons to access. */
#ifndef USE_DIAL_HOVER
- {
- PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ggd->data.ot_spin, NULL);
- RNA_float_set_array(ptr, "axis", axis_vec);
- }
+ {
+ PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ggd->data.ot_spin, NULL);
+ RNA_float_set_array(ptr, "axis", axis_vec);
+ }
#endif
- if (axis_index < 3) {
- for (int j = 0; j < 2; j++) {
- gz = ggd->gizmos.icon_button[axis_index][j];
- PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ggd->data.ot_spin, NULL);
- float axis_vec_flip[3];
- if (0 == j) {
- negate_v3_v3(axis_vec_flip, axis_vec);
- }
- else {
- copy_v3_v3(axis_vec_flip, axis_vec);
- }
- RNA_float_set_array(ptr, "axis", axis_vec_flip);
- }
- }
+ if (axis_index < 3) {
+ for (int j = 0; j < 2; j++) {
+ gz = ggd->gizmos.icon_button[axis_index][j];
+ PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ggd->data.ot_spin, NULL);
+ float axis_vec_flip[3];
+ if (0 == j) {
+ negate_v3_v3(axis_vec_flip, axis_vec);
+ }
+ else {
+ copy_v3_v3(axis_vec_flip, axis_vec);
+ }
+ RNA_float_set_array(ptr, "axis", axis_vec_flip);
+ }
+ }
}
-static void gizmo_mesh_spin_init_draw_prepare(
- const bContext *C, wmGizmoGroup *gzgroup)
+static void gizmo_mesh_spin_init_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoGroupData_SpinInit *ggd = gzgroup->customdata;
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- float viewinv_m3[3][3];
- copy_m3_m4(viewinv_m3, rv3d->viewinv);
-
- {
- Scene *scene = CTX_data_scene(C);
- const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene, SCE_ORIENT_ROTATE);
- switch (orient_slot->type) {
- case V3D_ORIENT_VIEW:
- {
- if (!equals_m3m3(viewinv_m3, ggd->prev.viewinv_m3)) {
- /* Take care calling refresh from draw_prepare,
- * this should be OK because it's only adjusting the cage orientation. */
- gizmo_mesh_spin_init_refresh(C, gzgroup);
- }
- break;
- }
- }
- }
-
- /* Refresh handled above when using view orientation. */
- if (!equals_m3m3(viewinv_m3, ggd->prev.viewinv_m3)) {
- gizmo_mesh_spin_init_refresh_axis_orientation(gzgroup, 3, rv3d->viewinv[2], NULL);
- copy_m3_m4(ggd->prev.viewinv_m3, rv3d->viewinv);
- }
-
- /* Hack! highlight XYZ dials based on buttons */
+ GizmoGroupData_SpinInit *ggd = gzgroup->customdata;
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float viewinv_m3[3][3];
+ copy_m3_m4(viewinv_m3, rv3d->viewinv);
+
+ {
+ Scene *scene = CTX_data_scene(C);
+ const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(
+ scene, SCE_ORIENT_ROTATE);
+ switch (orient_slot->type) {
+ case V3D_ORIENT_VIEW: {
+ if (!equals_m3m3(viewinv_m3, ggd->prev.viewinv_m3)) {
+ /* Take care calling refresh from draw_prepare,
+ * this should be OK because it's only adjusting the cage orientation. */
+ gizmo_mesh_spin_init_refresh(C, gzgroup);
+ }
+ break;
+ }
+ }
+ }
+
+ /* Refresh handled above when using view orientation. */
+ if (!equals_m3m3(viewinv_m3, ggd->prev.viewinv_m3)) {
+ gizmo_mesh_spin_init_refresh_axis_orientation(gzgroup, 3, rv3d->viewinv[2], NULL);
+ copy_m3_m4(ggd->prev.viewinv_m3, rv3d->viewinv);
+ }
+
+ /* Hack! highlight XYZ dials based on buttons */
#ifdef USE_DIAL_HOVER
- {
- PointerRNA ptr;
- bToolRef *tref = WM_toolsystem_ref_from_context((bContext *)C);
- WM_toolsystem_ref_properties_ensure_from_gizmo_group(tref, gzgroup->type, &ptr);
- const int axis_flag = RNA_property_enum_get(&ptr, ggd->data.gzgt_axis_prop);
- for (int i = 0; i < 4; i++) {
- bool hide = (axis_flag & (1 << i)) == 0;
- wmGizmo *gz = ggd->gizmos.xyz_view[i];
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, hide);
- if (!hide) {
- RNA_float_set(gz->ptr, "arc_partial_angle", (M_PI * 2) - (dial_angle_partial * dial_angle_partial_margin));
- }
- }
-
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 2; j++) {
- wmGizmo *gz = ggd->gizmos.icon_button[i][j];
- if (gz->state & WM_GIZMO_STATE_HIGHLIGHT) {
- WM_gizmo_set_flag(ggd->gizmos.xyz_view[i], WM_GIZMO_HIDDEN, false);
- RNA_float_set(ggd->gizmos.xyz_view[i]->ptr, "arc_partial_angle", 0.0f);
- i = 3;
- break;
- }
- }
- }
- }
+ {
+ PointerRNA ptr;
+ bToolRef *tref = WM_toolsystem_ref_from_context((bContext *)C);
+ WM_toolsystem_ref_properties_ensure_from_gizmo_group(tref, gzgroup->type, &ptr);
+ const int axis_flag = RNA_property_enum_get(&ptr, ggd->data.gzgt_axis_prop);
+ for (int i = 0; i < 4; i++) {
+ bool hide = (axis_flag & (1 << i)) == 0;
+ wmGizmo *gz = ggd->gizmos.xyz_view[i];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, hide);
+ if (!hide) {
+ RNA_float_set(gz->ptr,
+ "arc_partial_angle",
+ (M_PI * 2) - (dial_angle_partial * dial_angle_partial_margin));
+ }
+ }
+
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 2; j++) {
+ wmGizmo *gz = ggd->gizmos.icon_button[i][j];
+ if (gz->state & WM_GIZMO_STATE_HIGHLIGHT) {
+ WM_gizmo_set_flag(ggd->gizmos.xyz_view[i], WM_GIZMO_HIDDEN, false);
+ RNA_float_set(ggd->gizmos.xyz_view[i]->ptr, "arc_partial_angle", 0.0f);
+ i = 3;
+ break;
+ }
+ }
+ }
+ }
#endif
-
}
-static void gizmo_mesh_spin_init_invoke_prepare(
- const bContext *UNUSED(C), wmGizmoGroup *gzgroup, wmGizmo *gz)
+static void gizmo_mesh_spin_init_invoke_prepare(const bContext *UNUSED(C),
+ wmGizmoGroup *gzgroup,
+ wmGizmo *gz)
{
- /* Set the initial ortho axis. */
- GizmoGroupData_SpinInit *ggd = gzgroup->customdata;
- ggd->invoke.ortho_axis_active = -1;
- for (int i = 0; i < 3; i++) {
- if (ELEM(gz, UNPACK2(ggd->gizmos.icon_button[i]))) {
- ggd->invoke.ortho_axis_active = i;
- break;
- }
- }
+ /* Set the initial ortho axis. */
+ GizmoGroupData_SpinInit *ggd = gzgroup->customdata;
+ ggd->invoke.ortho_axis_active = -1;
+ for (int i = 0; i < 3; i++) {
+ if (ELEM(gz, UNPACK2(ggd->gizmos.icon_button[i]))) {
+ ggd->invoke.ortho_axis_active = i;
+ break;
+ }
+ }
}
static void gizmo_mesh_spin_init_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoGroupData_SpinInit *ggd = gzgroup->customdata;
- RegionView3D *rv3d = ED_view3d_context_rv3d((bContext *)C);
- const float *gizmo_center = NULL;
- {
- Scene *scene = CTX_data_scene(C);
- const View3DCursor *cursor = &scene->cursor;
- gizmo_center = cursor->location;
- }
-
- for (int i = 0; i < ARRAY_SIZE(ggd->gizmos.xyz_view); i++) {
- wmGizmo *gz = ggd->gizmos.xyz_view[i];
- WM_gizmo_set_matrix_location(gz, gizmo_center);
- }
-
- for (int i = 0; i < ARRAY_SIZE(ggd->gizmos.icon_button); i++) {
- for (int j = 0; j < 2; j++) {
- wmGizmo *gz = ggd->gizmos.icon_button[i][j];
- WM_gizmo_set_matrix_location(gz, gizmo_center);
- }
- }
-
- ED_transform_calc_orientation_from_type(C, ggd->data.orient_mat);
- for (int i = 0; i < 3; i++) {
- const int axis_ortho = (i + ORTHO_AXIS_OFFSET) % 3;
- const float *axis_ortho_vec = ggd->data.orient_mat[axis_ortho];
+ GizmoGroupData_SpinInit *ggd = gzgroup->customdata;
+ RegionView3D *rv3d = ED_view3d_context_rv3d((bContext *)C);
+ const float *gizmo_center = NULL;
+ {
+ Scene *scene = CTX_data_scene(C);
+ const View3DCursor *cursor = &scene->cursor;
+ gizmo_center = cursor->location;
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(ggd->gizmos.xyz_view); i++) {
+ wmGizmo *gz = ggd->gizmos.xyz_view[i];
+ WM_gizmo_set_matrix_location(gz, gizmo_center);
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(ggd->gizmos.icon_button); i++) {
+ for (int j = 0; j < 2; j++) {
+ wmGizmo *gz = ggd->gizmos.icon_button[i][j];
+ WM_gizmo_set_matrix_location(gz, gizmo_center);
+ }
+ }
+
+ ED_transform_calc_orientation_from_type(C, ggd->data.orient_mat);
+ for (int i = 0; i < 3; i++) {
+ const int axis_ortho = (i + ORTHO_AXIS_OFFSET) % 3;
+ const float *axis_ortho_vec = ggd->data.orient_mat[axis_ortho];
#ifdef USE_SELECT_CENTER
- if (ggd->data.use_select_center) {
- float delta[3];
- sub_v3_v3v3(delta, ggd->data.select_center, gizmo_center);
- project_plane_normalized_v3_v3v3(ggd->data.select_center_ortho_axis[i], delta, ggd->data.orient_mat[i]);
- if (normalize_v3(ggd->data.select_center_ortho_axis[i]) != 0.0f) {
- axis_ortho_vec = ggd->data.select_center_ortho_axis[i];
- }
- }
+ if (ggd->data.use_select_center) {
+ float delta[3];
+ sub_v3_v3v3(delta, ggd->data.select_center, gizmo_center);
+ project_plane_normalized_v3_v3v3(
+ ggd->data.select_center_ortho_axis[i], delta, ggd->data.orient_mat[i]);
+ if (normalize_v3(ggd->data.select_center_ortho_axis[i]) != 0.0f) {
+ axis_ortho_vec = ggd->data.select_center_ortho_axis[i];
+ }
+ }
#endif
- gizmo_mesh_spin_init_refresh_axis_orientation(
- gzgroup, i, ggd->data.orient_mat[i], axis_ortho_vec);
- }
-
- {
- gizmo_mesh_spin_init_refresh_axis_orientation(
- gzgroup, 3, rv3d->viewinv[2], NULL);
- }
+ gizmo_mesh_spin_init_refresh_axis_orientation(
+ gzgroup, i, ggd->data.orient_mat[i], axis_ortho_vec);
+ }
+ {
+ gizmo_mesh_spin_init_refresh_axis_orientation(gzgroup, 3, rv3d->viewinv[2], NULL);
+ }
#ifdef USE_SELECT_CENTER
- {
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- float select_center[3] = {0};
- int totsel = 0;
-
- BMesh *bm = em->bm;
- BMVert *eve;
- BMIter iter;
-
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- totsel++;
- add_v3_v3(select_center, eve->co);
- }
- }
- }
- if (totsel) {
- mul_v3_fl(select_center, 1.0f / totsel);
- mul_m4_v3(obedit->obmat, select_center);
- copy_v3_v3(ggd->data.select_center, select_center);
- ggd->data.use_select_center = true;
- }
- else {
- ggd->data.use_select_center = false;
- }
- }
+ {
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ float select_center[3] = {0};
+ int totsel = 0;
+
+ BMesh *bm = em->bm;
+ BMVert *eve;
+ BMIter iter;
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ totsel++;
+ add_v3_v3(select_center, eve->co);
+ }
+ }
+ }
+ if (totsel) {
+ mul_v3_fl(select_center, 1.0f / totsel);
+ mul_m4_v3(obedit->obmat, select_center);
+ copy_v3_v3(ggd->data.select_center, select_center);
+ ggd->data.use_select_center = true;
+ }
+ else {
+ ggd->data.use_select_center = false;
+ }
+ }
#endif
- for (int i = 0; i < ARRAY_SIZE(ggd->gizmos.icon_button); i++) {
- const int axis_ortho = (i + ORTHO_AXIS_OFFSET) % 3;
- const float *axis_ortho_vec = ggd->data.orient_mat[axis_ortho];
- float offset = INIT_SCALE_BASE / INIT_SCALE_BUTTON;
- float offset_vec[3];
+ for (int i = 0; i < ARRAY_SIZE(ggd->gizmos.icon_button); i++) {
+ const int axis_ortho = (i + ORTHO_AXIS_OFFSET) % 3;
+ const float *axis_ortho_vec = ggd->data.orient_mat[axis_ortho];
+ float offset = INIT_SCALE_BASE / INIT_SCALE_BUTTON;
+ float offset_vec[3];
#ifdef USE_SELECT_CENTER
- if (ggd->data.use_select_center && !is_zero_v3(ggd->data.select_center_ortho_axis[i])) {
- axis_ortho_vec = ggd->data.select_center_ortho_axis[i];
- }
+ if (ggd->data.use_select_center && !is_zero_v3(ggd->data.select_center_ortho_axis[i])) {
+ axis_ortho_vec = ggd->data.select_center_ortho_axis[i];
+ }
#endif
- mul_v3_v3fl(offset_vec, axis_ortho_vec, offset);
- for (int j = 0; j < 2; j++) {
- wmGizmo *gz = ggd->gizmos.icon_button[i][j];
- float mat3[3][3];
- axis_angle_to_mat3(mat3, ggd->data.orient_mat[i], dial_angle_partial * (j ? -0.5f : 0.5f));
- mul_v3_m3v3(gz->matrix_offset[3], mat3, offset_vec);
- }
- }
-
- {
- PointerRNA ptr;
- bToolRef *tref = WM_toolsystem_ref_from_context((bContext *)C);
- WM_toolsystem_ref_properties_ensure_from_gizmo_group(tref, gzgroup->type, &ptr);
- const int axis_flag = RNA_property_enum_get(&ptr, ggd->data.gzgt_axis_prop);
- for (int i = 0; i < ARRAY_SIZE(ggd->gizmos.icon_button); i++) {
- for (int j = 0; j < 2; j++) {
- wmGizmo *gz = ggd->gizmos.icon_button[i][j];
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, (axis_flag & (1 << i)) == 0);
- }
- }
- }
-
- /* Needed to test view orientation changes. */
- copy_m3_m4(ggd->prev.viewinv_m3, rv3d->viewinv);
+ mul_v3_v3fl(offset_vec, axis_ortho_vec, offset);
+ for (int j = 0; j < 2; j++) {
+ wmGizmo *gz = ggd->gizmos.icon_button[i][j];
+ float mat3[3][3];
+ axis_angle_to_mat3(mat3, ggd->data.orient_mat[i], dial_angle_partial * (j ? -0.5f : 0.5f));
+ mul_v3_m3v3(gz->matrix_offset[3], mat3, offset_vec);
+ }
+ }
+
+ {
+ PointerRNA ptr;
+ bToolRef *tref = WM_toolsystem_ref_from_context((bContext *)C);
+ WM_toolsystem_ref_properties_ensure_from_gizmo_group(tref, gzgroup->type, &ptr);
+ const int axis_flag = RNA_property_enum_get(&ptr, ggd->data.gzgt_axis_prop);
+ for (int i = 0; i < ARRAY_SIZE(ggd->gizmos.icon_button); i++) {
+ for (int j = 0; j < 2; j++) {
+ wmGizmo *gz = ggd->gizmos.icon_button[i][j];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, (axis_flag & (1 << i)) == 0);
+ }
+ }
+ }
+
+ /* Needed to test view orientation changes. */
+ copy_m3_m4(ggd->prev.viewinv_m3, rv3d->viewinv);
}
-
-static void gizmo_mesh_spin_init_message_subscribe(
- const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus)
+static void gizmo_mesh_spin_init_message_subscribe(const bContext *C,
+ wmGizmoGroup *gzgroup,
+ struct wmMsgBus *mbus)
{
- GizmoGroupData_SpinInit *ggd = gzgroup->customdata;
- Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
-
- /* Subscribe to view properties */
- wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
- .owner = ar,
- .user_data = gzgroup->parent_gzmap,
- .notify = WM_gizmo_do_msg_notify_tag_refresh,
- };
-
- PointerRNA cursor_ptr;
- RNA_pointer_create(&scene->id, &RNA_View3DCursor, &scene->cursor, &cursor_ptr);
- /* All cursor properties. */
- WM_msg_subscribe_rna(mbus, &cursor_ptr, NULL, &msg_sub_value_gz_tag_refresh, __func__);
-
- WM_msg_subscribe_rna_params(
- mbus,
- &(const wmMsgParams_RNA){
- .ptr = (PointerRNA){ .type = gzgroup->type->srna, },
- .prop = ggd->data.gzgt_axis_prop,
- },
- &msg_sub_value_gz_tag_refresh, __func__);
-
+ GizmoGroupData_SpinInit *ggd = gzgroup->customdata;
+ Scene *scene = CTX_data_scene(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ /* Subscribe to view properties */
+ wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
+ .owner = ar,
+ .user_data = gzgroup->parent_gzmap,
+ .notify = WM_gizmo_do_msg_notify_tag_refresh,
+ };
+
+ PointerRNA cursor_ptr;
+ RNA_pointer_create(&scene->id, &RNA_View3DCursor, &scene->cursor, &cursor_ptr);
+ /* All cursor properties. */
+ WM_msg_subscribe_rna(mbus, &cursor_ptr, NULL, &msg_sub_value_gz_tag_refresh, __func__);
+
+ WM_msg_subscribe_rna_params(mbus,
+ &(const wmMsgParams_RNA){
+ .ptr =
+ (PointerRNA){
+ .type = gzgroup->type->srna,
+ },
+ .prop = ggd->data.gzgt_axis_prop,
+ },
+ &msg_sub_value_gz_tag_refresh,
+ __func__);
}
void MESH_GGT_spin(struct wmGizmoGroupType *gzgt)
{
- gzgt->name = "Mesh Spin Init";
- gzgt->idname = "MESH_GGT_spin";
+ gzgt->name = "Mesh Spin Init";
+ gzgt->idname = "MESH_GGT_spin";
- gzgt->flag = WM_GIZMOGROUPTYPE_3D;
+ gzgt->flag = WM_GIZMOGROUPTYPE_3D;
- gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
- gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool;
- gzgt->setup = gizmo_mesh_spin_init_setup;
- gzgt->refresh = gizmo_mesh_spin_init_refresh;
- gzgt->message_subscribe = gizmo_mesh_spin_init_message_subscribe;
- gzgt->draw_prepare = gizmo_mesh_spin_init_draw_prepare;
- gzgt->invoke_prepare = gizmo_mesh_spin_init_invoke_prepare;
+ gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool;
+ gzgt->setup = gizmo_mesh_spin_init_setup;
+ gzgt->refresh = gizmo_mesh_spin_init_refresh;
+ gzgt->message_subscribe = gizmo_mesh_spin_init_message_subscribe;
+ gzgt->draw_prepare = gizmo_mesh_spin_init_draw_prepare;
+ gzgt->invoke_prepare = gizmo_mesh_spin_init_invoke_prepare;
- RNA_def_enum_flag(gzgt->srna, "axis", rna_enum_axis_flag_xyz_items, (1 << 2), "Axis", "");
+ RNA_def_enum_flag(gzgt->srna, "axis", rna_enum_axis_flag_xyz_items, (1 << 2), "Axis", "");
}
#undef INIT_SCALE_BASE
@@ -490,49 +492,49 @@ void MESH_GGT_spin(struct wmGizmoGroupType *gzgt)
#define USE_ANGLE_Z_ORIENT
typedef struct GizmoGroupData_SpinRedo {
- /* Translate XYZ. */
- struct wmGizmo *translate_c;
- /* Spin angle */
- struct wmGizmo *angle_z;
-
- /* Translate XY constrained ('orient_mat'). */
- struct wmGizmo *translate_xy[2];
- /* Rotate XY constrained ('orient_mat'). */
- struct wmGizmo *rotate_xy[2];
-
- /* Rotate on view axis. */
- struct wmGizmo *rotate_view;
-
- struct {
- float plane_co[3];
- float plane_no[3];
- } prev;
-
- bool is_init;
-
- /* We could store more vars here! */
- struct {
- bContext *context;
- wmOperatorType *ot;
- wmOperator *op;
- PropertyRNA *prop_axis_co;
- PropertyRNA *prop_axis_no;
- PropertyRNA *prop_angle;
-
- float rotate_axis[3];
+ /* Translate XYZ. */
+ struct wmGizmo *translate_c;
+ /* Spin angle */
+ struct wmGizmo *angle_z;
+
+ /* Translate XY constrained ('orient_mat'). */
+ struct wmGizmo *translate_xy[2];
+ /* Rotate XY constrained ('orient_mat'). */
+ struct wmGizmo *rotate_xy[2];
+
+ /* Rotate on view axis. */
+ struct wmGizmo *rotate_view;
+
+ struct {
+ float plane_co[3];
+ float plane_no[3];
+ } prev;
+
+ bool is_init;
+
+ /* We could store more vars here! */
+ struct {
+ bContext *context;
+ wmOperatorType *ot;
+ wmOperator *op;
+ PropertyRNA *prop_axis_co;
+ PropertyRNA *prop_axis_no;
+ PropertyRNA *prop_angle;
+
+ float rotate_axis[3];
#ifdef USE_ANGLE_Z_ORIENT
- /* Apply 'orient_mat' for the final value. */
- float orient_axis_relative[3];
+ /* Apply 'orient_mat' for the final value. */
+ float orient_axis_relative[3];
#endif
- /* The orientation, since the operator doesn't store this, we store our own.
- * this is kept in sync with the operator,
- * rotating the orientation when it doesn't match.
- *
- * Initialize to a sensible value where possible.
- */
- float orient_mat[3][3];
-
- } data;
+ /* The orientation, since the operator doesn't store this, we store our own.
+ * this is kept in sync with the operator,
+ * rotating the orientation when it doesn't match.
+ *
+ * Initialize to a sensible value where possible.
+ */
+ float orient_mat[3][3];
+
+ } data;
} GizmoGroupData_SpinRedo;
/**
@@ -542,526 +544,520 @@ typedef struct GizmoGroupData_SpinRedo {
*/
static void gizmo_spin_exec(GizmoGroupData_SpinRedo *ggd)
{
- if (ggd->is_init) {
- wmGizmo *gz = ggd->angle_z;
- PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "click_value");
- RNA_property_unset(gz->ptr, prop);
- ggd->is_init = false;
- }
-
- wmOperator *op = ggd->data.op;
- if (op == WM_operator_last_redo((bContext *)ggd->data.context)) {
- ED_undo_operator_repeat((bContext *)ggd->data.context, op);
- }
+ if (ggd->is_init) {
+ wmGizmo *gz = ggd->angle_z;
+ PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "click_value");
+ RNA_property_unset(gz->ptr, prop);
+ ggd->is_init = false;
+ }
+
+ wmOperator *op = ggd->data.op;
+ if (op == WM_operator_last_redo((bContext *)ggd->data.context)) {
+ ED_undo_operator_repeat((bContext *)ggd->data.context, op);
+ }
}
-static void gizmo_mesh_spin_redo_update_orient_axis(GizmoGroupData_SpinRedo *ggd, const float plane_no[3])
+static void gizmo_mesh_spin_redo_update_orient_axis(GizmoGroupData_SpinRedo *ggd,
+ const float plane_no[3])
{
- float mat[3][3];
- rotation_between_vecs_to_mat3(mat, ggd->data.orient_mat[2], plane_no);
- mul_m3_m3m3(ggd->data.orient_mat, mat, ggd->data.orient_mat);
- /* Not needed, just set for numeric stability. */
- copy_v3_v3(ggd->data.orient_mat[2], plane_no);
+ float mat[3][3];
+ rotation_between_vecs_to_mat3(mat, ggd->data.orient_mat[2], plane_no);
+ mul_m3_m3m3(ggd->data.orient_mat, mat, ggd->data.orient_mat);
+ /* Not needed, just set for numeric stability. */
+ copy_v3_v3(ggd->data.orient_mat[2], plane_no);
}
static void gizmo_mesh_spin_redo_update_from_op(GizmoGroupData_SpinRedo *ggd)
{
- wmOperator *op = ggd->data.op;
- float plane_co[3], plane_no[3];
- RNA_property_float_get_array(op->ptr, ggd->data.prop_axis_co, plane_co);
- RNA_property_float_get_array(op->ptr, ggd->data.prop_axis_no, plane_no);
- if (UNLIKELY(normalize_v3(plane_no) == 0.0f)) {
- return;
- }
- const bool is_plane_co_eq = equals_v3v3(plane_co, ggd->prev.plane_co);
- const bool is_plane_no_eq = equals_v3v3(plane_no, ggd->prev.plane_no);
- if (is_plane_co_eq && is_plane_no_eq) {
- return;
- }
- copy_v3_v3(ggd->prev.plane_co, plane_co);
- copy_v3_v3(ggd->prev.plane_no, plane_no);
-
- if (is_plane_no_eq == false) {
- gizmo_mesh_spin_redo_update_orient_axis(ggd, plane_no);
- }
-
- for (int i = 0; i < 2; i++) {
- WM_gizmo_set_matrix_location(ggd->rotate_xy[i], plane_co);
- WM_gizmo_set_matrix_location(ggd->translate_xy[i], plane_co);
- }
- WM_gizmo_set_matrix_location(ggd->angle_z, plane_co);
- WM_gizmo_set_matrix_location(ggd->rotate_view, plane_co);
- /* translate_c location comes from the property. */
-
- for (int i = 0; i < 2; i++) {
- WM_gizmo_set_matrix_rotation_from_z_axis(ggd->translate_xy[i], ggd->data.orient_mat[i]);
- WM_gizmo_set_matrix_rotation_from_z_axis(ggd->rotate_xy[i], ggd->data.orient_mat[i]);
- }
+ wmOperator *op = ggd->data.op;
+ float plane_co[3], plane_no[3];
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_axis_co, plane_co);
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_axis_no, plane_no);
+ if (UNLIKELY(normalize_v3(plane_no) == 0.0f)) {
+ return;
+ }
+ const bool is_plane_co_eq = equals_v3v3(plane_co, ggd->prev.plane_co);
+ const bool is_plane_no_eq = equals_v3v3(plane_no, ggd->prev.plane_no);
+ if (is_plane_co_eq && is_plane_no_eq) {
+ return;
+ }
+ copy_v3_v3(ggd->prev.plane_co, plane_co);
+ copy_v3_v3(ggd->prev.plane_no, plane_no);
+
+ if (is_plane_no_eq == false) {
+ gizmo_mesh_spin_redo_update_orient_axis(ggd, plane_no);
+ }
+
+ for (int i = 0; i < 2; i++) {
+ WM_gizmo_set_matrix_location(ggd->rotate_xy[i], plane_co);
+ WM_gizmo_set_matrix_location(ggd->translate_xy[i], plane_co);
+ }
+ WM_gizmo_set_matrix_location(ggd->angle_z, plane_co);
+ WM_gizmo_set_matrix_location(ggd->rotate_view, plane_co);
+ /* translate_c location comes from the property. */
+
+ for (int i = 0; i < 2; i++) {
+ WM_gizmo_set_matrix_rotation_from_z_axis(ggd->translate_xy[i], ggd->data.orient_mat[i]);
+ WM_gizmo_set_matrix_rotation_from_z_axis(ggd->rotate_xy[i], ggd->data.orient_mat[i]);
+ }
#ifdef USE_ANGLE_Z_ORIENT
- {
- float plane_tan[3];
- float orient_axis[3];
- mul_v3_m3v3(orient_axis, ggd->data.orient_mat, ggd->data.orient_axis_relative);
- project_plane_normalized_v3_v3v3(plane_tan, orient_axis, plane_no);
- if (normalize_v3(plane_tan) != 0.0f) {
- WM_gizmo_set_matrix_rotation_from_yz_axis(ggd->angle_z, plane_tan, plane_no);
- }
- else {
- WM_gizmo_set_matrix_rotation_from_z_axis(ggd->angle_z, plane_no);
- }
- }
+ {
+ float plane_tan[3];
+ float orient_axis[3];
+ mul_v3_m3v3(orient_axis, ggd->data.orient_mat, ggd->data.orient_axis_relative);
+ project_plane_normalized_v3_v3v3(plane_tan, orient_axis, plane_no);
+ if (normalize_v3(plane_tan) != 0.0f) {
+ WM_gizmo_set_matrix_rotation_from_yz_axis(ggd->angle_z, plane_tan, plane_no);
+ }
+ else {
+ WM_gizmo_set_matrix_rotation_from_z_axis(ggd->angle_z, plane_no);
+ }
+ }
#else
- WM_gizmo_set_matrix_rotation_from_z_axis(ggd->angle_z, plane_no);
+ WM_gizmo_set_matrix_rotation_from_z_axis(ggd->angle_z, plane_no);
#endif
}
/* depth callbacks */
-static void gizmo_spin_prop_depth_get(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- void *value_p)
+static void gizmo_spin_prop_depth_get(const wmGizmo *gz, wmGizmoProperty *gz_prop, void *value_p)
{
- GizmoGroupData_SpinRedo *ggd = gz->parent_gzgroup->customdata;
- wmOperator *op = ggd->data.op;
- float *value = value_p;
+ GizmoGroupData_SpinRedo *ggd = gz->parent_gzgroup->customdata;
+ wmOperator *op = ggd->data.op;
+ float *value = value_p;
- BLI_assert(gz_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(gz_prop);
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
- const float *plane_no = gz->matrix_basis[2];
- float plane_co[3];
- RNA_property_float_get_array(op->ptr, ggd->data.prop_axis_co, plane_co);
+ const float *plane_no = gz->matrix_basis[2];
+ float plane_co[3];
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_axis_co, plane_co);
- value[0] = dot_v3v3(plane_no, plane_co) - dot_v3v3(plane_no, gz->matrix_basis[3]);
+ value[0] = dot_v3v3(plane_no, plane_co) - dot_v3v3(plane_no, gz->matrix_basis[3]);
}
-static void gizmo_spin_prop_depth_set(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- const void *value_p)
+static void gizmo_spin_prop_depth_set(const wmGizmo *gz,
+ wmGizmoProperty *gz_prop,
+ const void *value_p)
{
- GizmoGroupData_SpinRedo *ggd = gz->parent_gzgroup->customdata;
- wmOperator *op = ggd->data.op;
- const float *value = value_p;
+ GizmoGroupData_SpinRedo *ggd = gz->parent_gzgroup->customdata;
+ wmOperator *op = ggd->data.op;
+ const float *value = value_p;
- BLI_assert(gz_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(gz_prop);
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
- float plane_co[3], plane[4];
- RNA_property_float_get_array(op->ptr, ggd->data.prop_axis_co, plane_co);
- normalize_v3_v3(plane, gz->matrix_basis[2]);
+ float plane_co[3], plane[4];
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_axis_co, plane_co);
+ normalize_v3_v3(plane, gz->matrix_basis[2]);
- plane[3] = -value[0] - dot_v3v3(plane, gz->matrix_basis[3]);
+ plane[3] = -value[0] - dot_v3v3(plane, gz->matrix_basis[3]);
- /* Keep our location, may be offset simply to be inside the viewport. */
- closest_to_plane_normalized_v3(plane_co, plane, plane_co);
+ /* Keep our location, may be offset simply to be inside the viewport. */
+ closest_to_plane_normalized_v3(plane_co, plane, plane_co);
- RNA_property_float_set_array(op->ptr, ggd->data.prop_axis_co, plane_co);
+ RNA_property_float_set_array(op->ptr, ggd->data.prop_axis_co, plane_co);
- gizmo_spin_exec(ggd);
+ gizmo_spin_exec(ggd);
}
/* translate callbacks */
-static void gizmo_spin_prop_translate_get(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- void *value_p)
+static void gizmo_spin_prop_translate_get(const wmGizmo *gz,
+ wmGizmoProperty *gz_prop,
+ void *value_p)
{
- GizmoGroupData_SpinRedo *ggd = gz->parent_gzgroup->customdata;
- wmOperator *op = ggd->data.op;
- float *value = value_p;
+ GizmoGroupData_SpinRedo *ggd = gz->parent_gzgroup->customdata;
+ wmOperator *op = ggd->data.op;
+ float *value = value_p;
- BLI_assert(gz_prop->type->array_length == 3);
- UNUSED_VARS_NDEBUG(gz_prop);
+ BLI_assert(gz_prop->type->array_length == 3);
+ UNUSED_VARS_NDEBUG(gz_prop);
- RNA_property_float_get_array(op->ptr, ggd->data.prop_axis_co, value);
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_axis_co, value);
}
-static void gizmo_spin_prop_translate_set(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- const void *value)
+static void gizmo_spin_prop_translate_set(const wmGizmo *gz,
+ wmGizmoProperty *gz_prop,
+ const void *value)
{
- GizmoGroupData_SpinRedo *ggd = gz->parent_gzgroup->customdata;
- wmOperator *op = ggd->data.op;
+ GizmoGroupData_SpinRedo *ggd = gz->parent_gzgroup->customdata;
+ wmOperator *op = ggd->data.op;
- BLI_assert(gz_prop->type->array_length == 3);
- UNUSED_VARS_NDEBUG(gz_prop);
+ BLI_assert(gz_prop->type->array_length == 3);
+ UNUSED_VARS_NDEBUG(gz_prop);
- RNA_property_float_set_array(op->ptr, ggd->data.prop_axis_co, value);
+ RNA_property_float_set_array(op->ptr, ggd->data.prop_axis_co, value);
- gizmo_spin_exec(ggd);
+ gizmo_spin_exec(ggd);
}
/* angle callbacks */
-static void gizmo_spin_prop_axis_angle_get(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- void *value_p)
+static void gizmo_spin_prop_axis_angle_get(const wmGizmo *gz,
+ wmGizmoProperty *gz_prop,
+ void *value_p)
{
- GizmoGroupData_SpinRedo *ggd = gz->parent_gzgroup->customdata;
- wmOperator *op = ggd->data.op;
- float *value = value_p;
-
- BLI_assert(gz_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(gz_prop);
-
- float plane_no[4];
- RNA_property_float_get_array(op->ptr, ggd->data.prop_axis_no, plane_no);
- normalize_v3(plane_no);
-
- const float *rotate_axis = gz->matrix_basis[2];
- float rotate_up[3];
- ortho_v3_v3(rotate_up, rotate_axis);
-
- float plane_no_proj[3];
- project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, rotate_axis);
-
- if (!is_zero_v3(plane_no_proj)) {
- const float angle = -angle_signed_on_axis_v3v3_v3(plane_no_proj, rotate_up, rotate_axis);
- value[0] = angle;
- }
- else {
- value[0] = 0.0f;
- }
+ GizmoGroupData_SpinRedo *ggd = gz->parent_gzgroup->customdata;
+ wmOperator *op = ggd->data.op;
+ float *value = value_p;
+
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
+
+ float plane_no[4];
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_axis_no, plane_no);
+ normalize_v3(plane_no);
+
+ const float *rotate_axis = gz->matrix_basis[2];
+ float rotate_up[3];
+ ortho_v3_v3(rotate_up, rotate_axis);
+
+ float plane_no_proj[3];
+ project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, rotate_axis);
+
+ if (!is_zero_v3(plane_no_proj)) {
+ const float angle = -angle_signed_on_axis_v3v3_v3(plane_no_proj, rotate_up, rotate_axis);
+ value[0] = angle;
+ }
+ else {
+ value[0] = 0.0f;
+ }
}
-static void gizmo_spin_prop_axis_angle_set(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- const void *value_p)
+static void gizmo_spin_prop_axis_angle_set(const wmGizmo *gz,
+ wmGizmoProperty *gz_prop,
+ const void *value_p)
{
- GizmoGroupData_SpinRedo *ggd = gz->parent_gzgroup->customdata;
- wmOperator *op = ggd->data.op;
- const float *value = value_p;
-
- BLI_assert(gz_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(gz_prop);
-
- float plane_no[4];
- RNA_property_float_get_array(op->ptr, ggd->data.prop_axis_no, plane_no);
- normalize_v3(plane_no);
-
- const float *rotate_axis = gz->matrix_basis[2];
- float rotate_up[3];
- ortho_v3_v3(rotate_up, rotate_axis);
-
- float plane_no_proj[3];
- project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, rotate_axis);
-
- if (!is_zero_v3(plane_no_proj)) {
- const float angle = -angle_signed_on_axis_v3v3_v3(plane_no_proj, rotate_up, rotate_axis);
- const float angle_delta = angle - angle_compat_rad(value[0], angle);
- if (angle_delta != 0.0f) {
- float mat[3][3];
- axis_angle_normalized_to_mat3(mat, rotate_axis, angle_delta);
- mul_m3_v3(mat, plane_no);
-
- /* re-normalize - seems acceptable */
- RNA_property_float_set_array(op->ptr, ggd->data.prop_axis_no, plane_no);
-
- gizmo_spin_exec(ggd);
- }
- }
+ GizmoGroupData_SpinRedo *ggd = gz->parent_gzgroup->customdata;
+ wmOperator *op = ggd->data.op;
+ const float *value = value_p;
+
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
+
+ float plane_no[4];
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_axis_no, plane_no);
+ normalize_v3(plane_no);
+
+ const float *rotate_axis = gz->matrix_basis[2];
+ float rotate_up[3];
+ ortho_v3_v3(rotate_up, rotate_axis);
+
+ float plane_no_proj[3];
+ project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, rotate_axis);
+
+ if (!is_zero_v3(plane_no_proj)) {
+ const float angle = -angle_signed_on_axis_v3v3_v3(plane_no_proj, rotate_up, rotate_axis);
+ const float angle_delta = angle - angle_compat_rad(value[0], angle);
+ if (angle_delta != 0.0f) {
+ float mat[3][3];
+ axis_angle_normalized_to_mat3(mat, rotate_axis, angle_delta);
+ mul_m3_v3(mat, plane_no);
+
+ /* re-normalize - seems acceptable */
+ RNA_property_float_set_array(op->ptr, ggd->data.prop_axis_no, plane_no);
+
+ gizmo_spin_exec(ggd);
+ }
+ }
}
/* angle callbacks */
-static void gizmo_spin_prop_angle_get(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- void *value_p)
+static void gizmo_spin_prop_angle_get(const wmGizmo *gz, wmGizmoProperty *gz_prop, void *value_p)
{
- GizmoGroupData_SpinRedo *ggd = gz->parent_gzgroup->customdata;
- wmOperator *op = ggd->data.op;
- float *value = value_p;
+ GizmoGroupData_SpinRedo *ggd = gz->parent_gzgroup->customdata;
+ wmOperator *op = ggd->data.op;
+ float *value = value_p;
- BLI_assert(gz_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(gz_prop);
- value[0] = RNA_property_float_get(op->ptr, ggd->data.prop_angle);
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
+ value[0] = RNA_property_float_get(op->ptr, ggd->data.prop_angle);
}
-static void gizmo_spin_prop_angle_set(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- const void *value_p)
+static void gizmo_spin_prop_angle_set(const wmGizmo *gz,
+ wmGizmoProperty *gz_prop,
+ const void *value_p)
{
- GizmoGroupData_SpinRedo *ggd = gz->parent_gzgroup->customdata;
- wmOperator *op = ggd->data.op;
- BLI_assert(gz_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(gz_prop);
- const float *value = value_p;
- RNA_property_float_set(op->ptr, ggd->data.prop_angle, value[0]);
-
- gizmo_spin_exec(ggd);
+ GizmoGroupData_SpinRedo *ggd = gz->parent_gzgroup->customdata;
+ wmOperator *op = ggd->data.op;
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
+ const float *value = value_p;
+ RNA_property_float_set(op->ptr, ggd->data.prop_angle, value[0]);
+
+ gizmo_spin_exec(ggd);
}
static bool gizmo_mesh_spin_redo_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
- if (ED_gizmo_poll_or_unlink_delayed_from_operator(C, gzgt, "MESH_OT_spin")) {
- if (ED_gizmo_poll_or_unlink_delayed_from_tool_ex(C, gzgt, "MESH_GGT_spin")) {
- return true;
- }
- }
- return false;
+ if (ED_gizmo_poll_or_unlink_delayed_from_operator(C, gzgt, "MESH_OT_spin")) {
+ if (ED_gizmo_poll_or_unlink_delayed_from_tool_ex(C, gzgt, "MESH_GGT_spin")) {
+ return true;
+ }
+ }
+ return false;
}
-static void gizmo_mesh_spin_redo_modal_from_setup(
- const bContext *C, wmGizmoGroup *gzgroup)
+static void gizmo_mesh_spin_redo_modal_from_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
- /* Start off dragging. */
- GizmoGroupData_SpinRedo *ggd = gzgroup->customdata;
- wmWindow *win = CTX_wm_window(C);
- wmGizmo *gz = ggd->angle_z;
- wmGizmoMap *gzmap = gzgroup->parent_gzmap;
+ /* Start off dragging. */
+ GizmoGroupData_SpinRedo *ggd = gzgroup->customdata;
+ wmWindow *win = CTX_wm_window(C);
+ wmGizmo *gz = ggd->angle_z;
+ wmGizmoMap *gzmap = gzgroup->parent_gzmap;
- ggd->is_init = true;
+ ggd->is_init = true;
- WM_gizmo_modal_set_from_setup(
- gzmap, (bContext *)C, gz, 0, win->eventstate);
+ WM_gizmo_modal_set_from_setup(gzmap, (bContext *)C, gz, 0, win->eventstate);
}
static void gizmo_mesh_spin_redo_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
- wmOperatorType *ot = WM_operatortype_find("MESH_OT_spin", true);
- wmOperator *op = WM_operator_last_redo(C);
-
- if ((op == NULL) || (op->type != ot)) {
- return;
- }
-
- GizmoGroupData_SpinRedo *ggd = MEM_callocN(sizeof(*ggd), __func__);
- gzgroup->customdata = ggd;
-
- const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
- const wmGizmoType *gzt_move = WM_gizmotype_find("GIZMO_GT_move_3d", true);
- const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true);
-
- /* Rotate View Axis (rotate_view) */
- {
- wmGizmo *gz = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL);
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
- zero_v4(gz->color);
- copy_v3_fl(gz->color_hi, 1.0f);
- gz->color_hi[3] = 0.1f;
- WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_VALUE, true);
- RNA_enum_set(gz->ptr, "draw_options",
- ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR |
- ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y |
- ED_GIZMO_DIAL_DRAW_FLAG_FILL);
- ggd->rotate_view = gz;
- }
-
- /* Translate Center (translate_c) */
- {
- wmGizmo *gz = WM_gizmo_new_ptr(gzt_move, gzgroup, NULL);
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
- gz->color[3] = 0.6f;
- RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_RING_2D);
- WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_VALUE, true);
- WM_gizmo_set_scale(gz, 0.15);
- WM_gizmo_set_line_width(gz, 2.0f);
- ggd->translate_c = gz;
- }
-
- /* Spin Angle (angle_z) */
- {
- wmGizmo *gz = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL);
- copy_v3_v3(gz->color, gz->color_hi);
- gz->color[3] = 0.5f;
- RNA_boolean_set(gz->ptr, "wrap_angle", false);
- RNA_enum_set(gz->ptr, "draw_options", ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE);
- RNA_float_set(gz->ptr, "arc_inner_factor", 0.9f);
- RNA_float_set(gz->ptr, "click_value", M_PI * 2);
- WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_VALUE, true);
- WM_gizmo_set_scale(gz, 2.0f);
- WM_gizmo_set_line_width(gz, 1.0f);
- ggd->angle_z = gz;
- }
-
- /* Translate X/Y Tangents (translate_xy) */
- for (int i = 0; i < 2; i++) {
- wmGizmo *gz = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
- UI_GetThemeColor3fv(TH_AXIS_X + i, gz->color);
- RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_NORMAL);
- RNA_enum_set(gz->ptr, "draw_options", 0);
- WM_gizmo_set_scale(gz, 1.2f);
- ggd->translate_xy[i] = gz;
- }
-
- /* Rotate X/Y Tangents (rotate_xy) */
- for (int i = 0; i < 2; i++) {
- wmGizmo *gz = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL);
- UI_GetThemeColor3fv(TH_AXIS_X + i, gz->color);
- gz->color[3] = 0.6f;
- WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_VALUE, true);
- WM_gizmo_set_line_width(gz, 3.0f);
- /* show the axis instead of mouse cursor */
- RNA_enum_set(gz->ptr, "draw_options",
- ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR |
- ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y |
- ED_GIZMO_DIAL_DRAW_FLAG_CLIP);
- ggd->rotate_xy[i] = gz;
- }
-
- {
- ggd->data.context = (bContext *)C;
- ggd->data.ot = ot;
- ggd->data.op = op;
- ggd->data.prop_axis_co = RNA_struct_type_find_property(ot->srna, "center");
- ggd->data.prop_axis_no = RNA_struct_type_find_property(ot->srna, "axis");
- ggd->data.prop_angle = RNA_struct_type_find_property(ot->srna, "angle");
- }
-
- /* The spin operator only knows about an axis,
- * while the manipulator has X/Y orientation for the gizmos.
- * Initialize the orientation from the spin gizmo if possible.
- */
- {
- ARegion *ar = CTX_wm_region(C);
- wmGizmoMap *gzmap = ar->gizmo_map;
- wmGizmoGroup *gzgroup_init = WM_gizmomap_group_find(gzmap, "MESH_GGT_spin");
- if (gzgroup_init) {
- GizmoGroupData_SpinInit *ggd_init = gzgroup_init->customdata;
- copy_m3_m3(ggd->data.orient_mat, ggd_init->data.orient_mat);
- if (ggd_init->invoke.ortho_axis_active != -1) {
- copy_v3_v3(ggd->data.orient_axis_relative,
- ggd_init->gizmos.xyz_view[ggd_init->invoke.ortho_axis_active]->matrix_basis[1]);
- ggd_init->invoke.ortho_axis_active = -1;
- }
- }
- else {
- unit_m3(ggd->data.orient_mat);
- }
- }
+ wmOperatorType *ot = WM_operatortype_find("MESH_OT_spin", true);
+ wmOperator *op = WM_operator_last_redo(C);
+
+ if ((op == NULL) || (op->type != ot)) {
+ return;
+ }
+
+ GizmoGroupData_SpinRedo *ggd = MEM_callocN(sizeof(*ggd), __func__);
+ gzgroup->customdata = ggd;
+
+ const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
+ const wmGizmoType *gzt_move = WM_gizmotype_find("GIZMO_GT_move_3d", true);
+ const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true);
+
+ /* Rotate View Axis (rotate_view) */
+ {
+ wmGizmo *gz = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL);
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ zero_v4(gz->color);
+ copy_v3_fl(gz->color_hi, 1.0f);
+ gz->color_hi[3] = 0.1f;
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_VALUE, true);
+ RNA_enum_set(gz->ptr,
+ "draw_options",
+ ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR | ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y |
+ ED_GIZMO_DIAL_DRAW_FLAG_FILL);
+ ggd->rotate_view = gz;
+ }
+
+ /* Translate Center (translate_c) */
+ {
+ wmGizmo *gz = WM_gizmo_new_ptr(gzt_move, gzgroup, NULL);
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ gz->color[3] = 0.6f;
+ RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_RING_2D);
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_VALUE, true);
+ WM_gizmo_set_scale(gz, 0.15);
+ WM_gizmo_set_line_width(gz, 2.0f);
+ ggd->translate_c = gz;
+ }
+
+ /* Spin Angle (angle_z) */
+ {
+ wmGizmo *gz = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL);
+ copy_v3_v3(gz->color, gz->color_hi);
+ gz->color[3] = 0.5f;
+ RNA_boolean_set(gz->ptr, "wrap_angle", false);
+ RNA_enum_set(gz->ptr, "draw_options", ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE);
+ RNA_float_set(gz->ptr, "arc_inner_factor", 0.9f);
+ RNA_float_set(gz->ptr, "click_value", M_PI * 2);
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_VALUE, true);
+ WM_gizmo_set_scale(gz, 2.0f);
+ WM_gizmo_set_line_width(gz, 1.0f);
+ ggd->angle_z = gz;
+ }
+
+ /* Translate X/Y Tangents (translate_xy) */
+ for (int i = 0; i < 2; i++) {
+ wmGizmo *gz = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ UI_GetThemeColor3fv(TH_AXIS_X + i, gz->color);
+ RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_NORMAL);
+ RNA_enum_set(gz->ptr, "draw_options", 0);
+ WM_gizmo_set_scale(gz, 1.2f);
+ ggd->translate_xy[i] = gz;
+ }
+
+ /* Rotate X/Y Tangents (rotate_xy) */
+ for (int i = 0; i < 2; i++) {
+ wmGizmo *gz = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL);
+ UI_GetThemeColor3fv(TH_AXIS_X + i, gz->color);
+ gz->color[3] = 0.6f;
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_VALUE, true);
+ WM_gizmo_set_line_width(gz, 3.0f);
+ /* show the axis instead of mouse cursor */
+ RNA_enum_set(gz->ptr,
+ "draw_options",
+ ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR | ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y |
+ ED_GIZMO_DIAL_DRAW_FLAG_CLIP);
+ ggd->rotate_xy[i] = gz;
+ }
+
+ {
+ ggd->data.context = (bContext *)C;
+ ggd->data.ot = ot;
+ ggd->data.op = op;
+ ggd->data.prop_axis_co = RNA_struct_type_find_property(ot->srna, "center");
+ ggd->data.prop_axis_no = RNA_struct_type_find_property(ot->srna, "axis");
+ ggd->data.prop_angle = RNA_struct_type_find_property(ot->srna, "angle");
+ }
+
+ /* The spin operator only knows about an axis,
+ * while the manipulator has X/Y orientation for the gizmos.
+ * Initialize the orientation from the spin gizmo if possible.
+ */
+ {
+ ARegion *ar = CTX_wm_region(C);
+ wmGizmoMap *gzmap = ar->gizmo_map;
+ wmGizmoGroup *gzgroup_init = WM_gizmomap_group_find(gzmap, "MESH_GGT_spin");
+ if (gzgroup_init) {
+ GizmoGroupData_SpinInit *ggd_init = gzgroup_init->customdata;
+ copy_m3_m3(ggd->data.orient_mat, ggd_init->data.orient_mat);
+ if (ggd_init->invoke.ortho_axis_active != -1) {
+ copy_v3_v3(ggd->data.orient_axis_relative,
+ ggd_init->gizmos.xyz_view[ggd_init->invoke.ortho_axis_active]->matrix_basis[1]);
+ ggd_init->invoke.ortho_axis_active = -1;
+ }
+ }
+ else {
+ unit_m3(ggd->data.orient_mat);
+ }
+ }
#ifdef USE_ANGLE_Z_ORIENT
- {
- wmWindow *win = CTX_wm_window(C);
- View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = 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);
- RNA_property_float_get_array(op->ptr, ggd->data.prop_axis_no, plane_no);
-
- gizmo_mesh_spin_redo_update_orient_axis(ggd, plane_no);
-
- /* 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};
- 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);
- }
- sub_v3_v3v3(ggd->data.orient_axis_relative, cursor_co, plane_co);
- }
-
- if (!is_zero_v3(ggd->data.orient_axis_relative)) {
- normalize_v3(ggd->data.orient_axis_relative);
- float imat3[3][3];
- invert_m3_m3(imat3, ggd->data.orient_mat);
- mul_m3_v3(imat3, ggd->data.orient_axis_relative);
- }
- }
+ {
+ wmWindow *win = CTX_wm_window(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = 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);
+ RNA_property_float_get_array(op->ptr, ggd->data.prop_axis_no, plane_no);
+
+ gizmo_mesh_spin_redo_update_orient_axis(ggd, plane_no);
+
+ /* 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};
+ 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);
+ }
+ sub_v3_v3v3(ggd->data.orient_axis_relative, cursor_co, plane_co);
+ }
+
+ if (!is_zero_v3(ggd->data.orient_axis_relative)) {
+ normalize_v3(ggd->data.orient_axis_relative);
+ float imat3[3][3];
+ invert_m3_m3(imat3, ggd->data.orient_mat);
+ mul_m3_v3(imat3, ggd->data.orient_axis_relative);
+ }
+ }
#endif
- gizmo_mesh_spin_redo_update_from_op(ggd);
-
- /* Setup property callbacks */
- {
- WM_gizmo_target_property_def_func(
- ggd->translate_c, "offset",
- &(const struct wmGizmoPropertyFnParams) {
- .value_get_fn = gizmo_spin_prop_translate_get,
- .value_set_fn = gizmo_spin_prop_translate_set,
- .range_get_fn = NULL,
- .user_data = NULL,
- });
-
- WM_gizmo_target_property_def_func(
- ggd->rotate_view, "offset",
- &(const struct wmGizmoPropertyFnParams) {
- .value_get_fn = gizmo_spin_prop_axis_angle_get,
- .value_set_fn = gizmo_spin_prop_axis_angle_set,
- .range_get_fn = NULL,
- .user_data = NULL,
- });
-
- for (int i = 0; i < 2; i++) {
- WM_gizmo_target_property_def_func(
- ggd->rotate_xy[i], "offset",
- &(const struct wmGizmoPropertyFnParams) {
- .value_get_fn = gizmo_spin_prop_axis_angle_get,
- .value_set_fn = gizmo_spin_prop_axis_angle_set,
- .range_get_fn = NULL,
- .user_data = NULL,
- });
- WM_gizmo_target_property_def_func(
- ggd->translate_xy[i], "offset",
- &(const struct wmGizmoPropertyFnParams) {
- .value_get_fn = gizmo_spin_prop_depth_get,
- .value_set_fn = gizmo_spin_prop_depth_set,
- .range_get_fn = NULL,
- .user_data = NULL,
- });
- }
-
- WM_gizmo_target_property_def_func(
- ggd->angle_z, "offset",
- &(const struct wmGizmoPropertyFnParams) {
- .value_get_fn = gizmo_spin_prop_angle_get,
- .value_set_fn = gizmo_spin_prop_angle_set,
- .range_get_fn = NULL,
- .user_data = NULL,
- });
- }
-
- /* Become modal as soon as it's started. */
- gizmo_mesh_spin_redo_modal_from_setup(C, gzgroup);
+ gizmo_mesh_spin_redo_update_from_op(ggd);
+
+ /* Setup property callbacks */
+ {
+ WM_gizmo_target_property_def_func(ggd->translate_c,
+ "offset",
+ &(const struct wmGizmoPropertyFnParams){
+ .value_get_fn = gizmo_spin_prop_translate_get,
+ .value_set_fn = gizmo_spin_prop_translate_set,
+ .range_get_fn = NULL,
+ .user_data = NULL,
+ });
+
+ WM_gizmo_target_property_def_func(ggd->rotate_view,
+ "offset",
+ &(const struct wmGizmoPropertyFnParams){
+ .value_get_fn = gizmo_spin_prop_axis_angle_get,
+ .value_set_fn = gizmo_spin_prop_axis_angle_set,
+ .range_get_fn = NULL,
+ .user_data = NULL,
+ });
+
+ for (int i = 0; i < 2; i++) {
+ WM_gizmo_target_property_def_func(ggd->rotate_xy[i],
+ "offset",
+ &(const struct wmGizmoPropertyFnParams){
+ .value_get_fn = gizmo_spin_prop_axis_angle_get,
+ .value_set_fn = gizmo_spin_prop_axis_angle_set,
+ .range_get_fn = NULL,
+ .user_data = NULL,
+ });
+ WM_gizmo_target_property_def_func(ggd->translate_xy[i],
+ "offset",
+ &(const struct wmGizmoPropertyFnParams){
+ .value_get_fn = gizmo_spin_prop_depth_get,
+ .value_set_fn = gizmo_spin_prop_depth_set,
+ .range_get_fn = NULL,
+ .user_data = NULL,
+ });
+ }
+
+ WM_gizmo_target_property_def_func(ggd->angle_z,
+ "offset",
+ &(const struct wmGizmoPropertyFnParams){
+ .value_get_fn = gizmo_spin_prop_angle_get,
+ .value_set_fn = gizmo_spin_prop_angle_set,
+ .range_get_fn = NULL,
+ .user_data = NULL,
+ });
+ }
+
+ /* Become modal as soon as it's started. */
+ gizmo_mesh_spin_redo_modal_from_setup(C, gzgroup);
}
-static void gizmo_mesh_spin_redo_draw_prepare(
- const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
+static void gizmo_mesh_spin_redo_draw_prepare(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- GizmoGroupData_SpinRedo *ggd = gzgroup->customdata;
- if (ggd->data.op->next) {
- ggd->data.op = WM_operator_last_redo((bContext *)ggd->data.context);
- }
-
- /* Not essential, just avoids feedback loop where matrices 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) {
- if (gz->state & WM_GIZMO_STATE_MODAL) {
- is_modal = true;
- break;
- }
- }
- if (!is_modal) {
- gizmo_mesh_spin_redo_update_from_op(ggd);
- }
-
- RegionView3D *rv3d = ED_view3d_context_rv3d(ggd->data.context);
- WM_gizmo_set_matrix_rotation_from_z_axis(ggd->translate_c, rv3d->viewinv[2]);
- {
- float view_up[3];
- project_plane_normalized_v3_v3v3(view_up, ggd->data.orient_mat[2], rv3d->viewinv[2]);
- if (normalize_v3(view_up) != 0.0f) {
- WM_gizmo_set_matrix_rotation_from_yz_axis(ggd->rotate_view, view_up, rv3d->viewinv[2]);
- }
- else {
- WM_gizmo_set_matrix_rotation_from_z_axis(ggd->rotate_view, rv3d->viewinv[2]);
- }
- }
+ GizmoGroupData_SpinRedo *ggd = gzgroup->customdata;
+ if (ggd->data.op->next) {
+ ggd->data.op = WM_operator_last_redo((bContext *)ggd->data.context);
+ }
+
+ /* Not essential, just avoids feedback loop where matrices 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) {
+ if (gz->state & WM_GIZMO_STATE_MODAL) {
+ is_modal = true;
+ break;
+ }
+ }
+ if (!is_modal) {
+ gizmo_mesh_spin_redo_update_from_op(ggd);
+ }
+
+ RegionView3D *rv3d = ED_view3d_context_rv3d(ggd->data.context);
+ WM_gizmo_set_matrix_rotation_from_z_axis(ggd->translate_c, rv3d->viewinv[2]);
+ {
+ float view_up[3];
+ project_plane_normalized_v3_v3v3(view_up, ggd->data.orient_mat[2], rv3d->viewinv[2]);
+ if (normalize_v3(view_up) != 0.0f) {
+ WM_gizmo_set_matrix_rotation_from_yz_axis(ggd->rotate_view, view_up, rv3d->viewinv[2]);
+ }
+ else {
+ WM_gizmo_set_matrix_rotation_from_z_axis(ggd->rotate_view, rv3d->viewinv[2]);
+ }
+ }
}
void MESH_GGT_spin_redo(struct wmGizmoGroupType *gzgt)
{
- gzgt->name = "Mesh Spin Redo";
- gzgt->idname = "MESH_GGT_spin_redo";
+ gzgt->name = "Mesh Spin Redo";
+ gzgt->idname = "MESH_GGT_spin_redo";
- gzgt->flag = WM_GIZMOGROUPTYPE_3D;
+ gzgt->flag = WM_GIZMOGROUPTYPE_3D;
- gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
- gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- gzgt->poll = gizmo_mesh_spin_redo_poll;
- gzgt->setup = gizmo_mesh_spin_redo_setup;
- gzgt->draw_prepare = gizmo_mesh_spin_redo_draw_prepare;
+ gzgt->poll = gizmo_mesh_spin_redo_poll;
+ gzgt->setup = gizmo_mesh_spin_redo_setup;
+ gzgt->draw_prepare = gizmo_mesh_spin_redo_draw_prepare;
}
/** \} */
diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c
index 3b48c4e29b0..7bee030bb46 100644
--- a/source/blender/editors/mesh/editmesh_inset.c
+++ b/source/blender/editors/mesh/editmesh_inset.c
@@ -48,539 +48,560 @@
#include "ED_transform.h"
#include "ED_view3d.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
typedef struct {
- BMEditMesh *em;
- BMBackup mesh_backup;
+ BMEditMesh *em;
+ BMBackup mesh_backup;
} InsetObjectStore;
typedef struct {
- float old_thickness;
- float old_depth;
- bool modify_depth;
- float initial_length;
- float pixel_size; /* use when mouse input is interpreted as spatial distance */
- bool is_modal;
- bool shift;
- float shift_amount;
- float max_obj_scale;
- NumInput num_input;
-
- InsetObjectStore *ob_store;
- uint ob_store_len;
-
- /* modal only */
- float mcenter[2];
- void *draw_handle_pixel;
- short gizmo_flag;
+ float old_thickness;
+ float old_depth;
+ bool modify_depth;
+ float initial_length;
+ float pixel_size; /* use when mouse input is interpreted as spatial distance */
+ bool is_modal;
+ bool shift;
+ float shift_amount;
+ float max_obj_scale;
+ NumInput num_input;
+
+ InsetObjectStore *ob_store;
+ uint ob_store_len;
+
+ /* modal only */
+ float mcenter[2];
+ void *draw_handle_pixel;
+ short gizmo_flag;
} InsetData;
-
static void edbm_inset_update_header(wmOperator *op, bContext *C)
{
- InsetData *opdata = op->customdata;
-
- const char *str = IFACE_(
- "Confirm: Enter/LClick, Cancel: (Esc/RClick), Thickness: %s, "
- "Depth (Ctrl to tweak): %s (%s), Outset (O): (%s), Boundary (B): (%s), Individual (I): (%s)"
- );
-
- char msg[UI_MAX_DRAW_STR];
- ScrArea *sa = CTX_wm_area(C);
- Scene *sce = CTX_data_scene(C);
-
- if (sa) {
- char flts_str[NUM_STR_REP_LEN * 2];
- if (hasNumInput(&opdata->num_input))
- outputNumInput(&opdata->num_input, flts_str, &sce->unit);
- else {
- BLI_snprintf(flts_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "thickness"));
- BLI_snprintf(flts_str + NUM_STR_REP_LEN, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "depth"));
- }
- BLI_snprintf(msg, sizeof(msg), str,
- flts_str,
- flts_str + NUM_STR_REP_LEN,
- WM_bool_as_string(opdata->modify_depth),
- WM_bool_as_string(RNA_boolean_get(op->ptr, "use_outset")),
- 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);
- }
+ InsetData *opdata = op->customdata;
+
+ const char *str = IFACE_(
+ "Confirm: Enter/LClick, Cancel: (Esc/RClick), Thickness: %s, "
+ "Depth (Ctrl to tweak): %s (%s), Outset (O): (%s), Boundary (B): (%s), Individual (I): "
+ "(%s)");
+
+ char msg[UI_MAX_DRAW_STR];
+ ScrArea *sa = CTX_wm_area(C);
+ Scene *sce = CTX_data_scene(C);
+
+ if (sa) {
+ char flts_str[NUM_STR_REP_LEN * 2];
+ if (hasNumInput(&opdata->num_input))
+ outputNumInput(&opdata->num_input, flts_str, &sce->unit);
+ else {
+ BLI_snprintf(flts_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "thickness"));
+ BLI_snprintf(
+ flts_str + NUM_STR_REP_LEN, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "depth"));
+ }
+ BLI_snprintf(msg,
+ sizeof(msg),
+ str,
+ flts_str,
+ flts_str + NUM_STR_REP_LEN,
+ WM_bool_as_string(opdata->modify_depth),
+ WM_bool_as_string(RNA_boolean_get(op->ptr, "use_outset")),
+ 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);
+ }
}
-
static bool edbm_inset_init(bContext *C, wmOperator *op, const bool is_modal)
{
- InsetData *opdata;
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- if (is_modal) {
- RNA_float_set(op->ptr, "thickness", 0.0f);
- RNA_float_set(op->ptr, "depth", 0.0f);
- }
-
- op->customdata = opdata = MEM_mallocN(sizeof(InsetData), "inset_operator_data");
-
- uint objects_used_len = 0;
-
- opdata->max_obj_scale = FLT_MIN;
-
- {
- uint ob_store_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &ob_store_len);
- opdata->ob_store = MEM_malloc_arrayN(ob_store_len, sizeof(*opdata->ob_store), __func__);
- for (uint ob_index = 0; ob_index < ob_store_len; ob_index++) {
- Object *obedit = objects[ob_index];
- float scale = mat4_to_scale(obedit->obmat);
- opdata->max_obj_scale = max_ff(opdata->max_obj_scale, scale);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totvertsel > 0) {
- opdata->ob_store[objects_used_len].em = em;
- objects_used_len++;
- }
- }
- MEM_freeN(objects);
- opdata->ob_store_len = objects_used_len;
- }
-
- opdata->old_thickness = 0.0;
- opdata->old_depth = 0.0;
- opdata->modify_depth = false;
- opdata->shift = false;
- opdata->shift_amount = 0.0f;
- opdata->is_modal = is_modal;
-
- initNumInput(&opdata->num_input);
- opdata->num_input.idx_max = 1; /* Two elements. */
- opdata->num_input.unit_sys = scene->unit.system;
- opdata->num_input.unit_type[0] = B_UNIT_LENGTH;
- opdata->num_input.unit_type[1] = B_UNIT_LENGTH;
-
- if (is_modal) {
- View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
-
- for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
- opdata->ob_store[ob_index].mesh_backup = EDBM_redo_state_store(opdata->ob_store[ob_index].em);
- }
-
- opdata->draw_handle_pixel = ED_region_draw_cb_activate(
- ar->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;
- v3d->gizmo_flag = V3D_GIZMO_HIDE;
- }
- }
-
- return true;
+ InsetData *opdata;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ if (is_modal) {
+ RNA_float_set(op->ptr, "thickness", 0.0f);
+ RNA_float_set(op->ptr, "depth", 0.0f);
+ }
+
+ op->customdata = opdata = MEM_mallocN(sizeof(InsetData), "inset_operator_data");
+
+ uint objects_used_len = 0;
+
+ opdata->max_obj_scale = FLT_MIN;
+
+ {
+ uint ob_store_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &ob_store_len);
+ opdata->ob_store = MEM_malloc_arrayN(ob_store_len, sizeof(*opdata->ob_store), __func__);
+ for (uint ob_index = 0; ob_index < ob_store_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ float scale = mat4_to_scale(obedit->obmat);
+ opdata->max_obj_scale = max_ff(opdata->max_obj_scale, scale);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ if (em->bm->totvertsel > 0) {
+ opdata->ob_store[objects_used_len].em = em;
+ objects_used_len++;
+ }
+ }
+ MEM_freeN(objects);
+ opdata->ob_store_len = objects_used_len;
+ }
+
+ opdata->old_thickness = 0.0;
+ opdata->old_depth = 0.0;
+ opdata->modify_depth = false;
+ opdata->shift = false;
+ opdata->shift_amount = 0.0f;
+ opdata->is_modal = is_modal;
+
+ initNumInput(&opdata->num_input);
+ opdata->num_input.idx_max = 1; /* Two elements. */
+ opdata->num_input.unit_sys = scene->unit.system;
+ opdata->num_input.unit_type[0] = B_UNIT_LENGTH;
+ opdata->num_input.unit_type[1] = B_UNIT_LENGTH;
+
+ if (is_modal) {
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
+ opdata->ob_store[ob_index].mesh_backup = EDBM_redo_state_store(
+ opdata->ob_store[ob_index].em);
+ }
+
+ opdata->draw_handle_pixel = ED_region_draw_cb_activate(
+ ar->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;
+ v3d->gizmo_flag = V3D_GIZMO_HIDE;
+ }
+ }
+
+ return true;
}
static void edbm_inset_exit(bContext *C, wmOperator *op)
{
- InsetData *opdata;
- ScrArea *sa = CTX_wm_area(C);
-
- opdata = op->customdata;
-
- if (opdata->is_modal) {
- View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = 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);
- if (v3d) {
- v3d->gizmo_flag = opdata->gizmo_flag;
- }
- G.moving = 0;
- }
-
- if (sa) {
- ED_area_status_text(sa, NULL);
- }
-
- MEM_SAFE_FREE(opdata->ob_store);
- MEM_SAFE_FREE(op->customdata);
+ InsetData *opdata;
+ ScrArea *sa = CTX_wm_area(C);
+
+ opdata = op->customdata;
+
+ if (opdata->is_modal) {
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = 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);
+ if (v3d) {
+ v3d->gizmo_flag = opdata->gizmo_flag;
+ }
+ G.moving = 0;
+ }
+
+ if (sa) {
+ ED_area_status_text(sa, NULL);
+ }
+
+ MEM_SAFE_FREE(opdata->ob_store);
+ MEM_SAFE_FREE(op->customdata);
}
static void edbm_inset_cancel(bContext *C, wmOperator *op)
{
- InsetData *opdata;
+ InsetData *opdata;
- opdata = op->customdata;
- if (opdata->is_modal) {
- for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
- EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, opdata->ob_store[ob_index].em, true);
- EDBM_update_generic(opdata->ob_store[ob_index].em, false, true);
- }
- }
+ opdata = op->customdata;
+ if (opdata->is_modal) {
+ for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
+ EDBM_redo_state_free(
+ &opdata->ob_store[ob_index].mesh_backup, opdata->ob_store[ob_index].em, true);
+ EDBM_update_generic(opdata->ob_store[ob_index].em, false, true);
+ }
+ }
- edbm_inset_exit(C, op);
+ edbm_inset_exit(C, op);
- /* need to force redisplay or we may still view the modified result */
- ED_region_tag_redraw(CTX_wm_region(C));
+ /* need to force redisplay or we may still view the modified result */
+ ED_region_tag_redraw(CTX_wm_region(C));
}
static bool edbm_inset_calc(wmOperator *op)
{
- InsetData *opdata;
- BMEditMesh *em;
- BMOperator bmop;
- bool changed = false;
-
- const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary");
- const bool use_even_offset = RNA_boolean_get(op->ptr, "use_even_offset");
- const bool use_relative_offset = RNA_boolean_get(op->ptr, "use_relative_offset");
- const bool use_edge_rail = RNA_boolean_get(op->ptr, "use_edge_rail");
- const float thickness = RNA_float_get(op->ptr, "thickness");
- const float depth = RNA_float_get(op->ptr, "depth");
- const bool use_outset = RNA_boolean_get(op->ptr, "use_outset");
- /* not passed onto the BMO */
- const bool use_select_inset = RNA_boolean_get(op->ptr, "use_select_inset");
- const bool use_individual = RNA_boolean_get(op->ptr, "use_individual");
- const bool use_interpolate = RNA_boolean_get(op->ptr, "use_interpolate");
-
- opdata = op->customdata;
-
- for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
- em = opdata->ob_store[ob_index].em;
-
- if (opdata->is_modal) {
- EDBM_redo_state_restore(opdata->ob_store[ob_index].mesh_backup, em, false);
- }
-
- if (use_individual) {
- EDBM_op_init(
- em, &bmop, op,
- "inset_individual faces=%hf use_even_offset=%b use_relative_offset=%b "
- "use_interpolate=%b thickness=%f depth=%f",
- BM_ELEM_SELECT, use_even_offset, use_relative_offset, use_interpolate,
- thickness, depth);
- }
- else {
- EDBM_op_init(
- em, &bmop, op,
- "inset_region faces=%hf use_boundary=%b use_even_offset=%b use_relative_offset=%b "
- "use_interpolate=%b thickness=%f depth=%f use_outset=%b use_edge_rail=%b",
- BM_ELEM_SELECT, use_boundary, use_even_offset, use_relative_offset, use_interpolate,
- thickness, depth, use_outset, use_edge_rail);
-
- if (use_outset) {
- BMO_slot_buffer_from_enabled_hflag(em->bm, &bmop, bmop.slots_in, "faces_exclude", BM_FACE, BM_ELEM_HIDDEN);
- }
- }
- BMO_op_exec(em->bm, &bmop);
-
- if (use_select_inset) {
- /* deselect original faces/verts */
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
- }
- else {
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_in, "faces", BM_FACE, BM_ELEM_SELECT, true);
- }
-
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
- else {
- EDBM_update_generic(em, true, true);
- changed = true;
- }
- }
- return changed;
+ InsetData *opdata;
+ BMEditMesh *em;
+ BMOperator bmop;
+ bool changed = false;
+
+ const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary");
+ const bool use_even_offset = RNA_boolean_get(op->ptr, "use_even_offset");
+ const bool use_relative_offset = RNA_boolean_get(op->ptr, "use_relative_offset");
+ const bool use_edge_rail = RNA_boolean_get(op->ptr, "use_edge_rail");
+ const float thickness = RNA_float_get(op->ptr, "thickness");
+ const float depth = RNA_float_get(op->ptr, "depth");
+ const bool use_outset = RNA_boolean_get(op->ptr, "use_outset");
+ /* not passed onto the BMO */
+ const bool use_select_inset = RNA_boolean_get(op->ptr, "use_select_inset");
+ const bool use_individual = RNA_boolean_get(op->ptr, "use_individual");
+ const bool use_interpolate = RNA_boolean_get(op->ptr, "use_interpolate");
+
+ opdata = op->customdata;
+
+ for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
+ em = opdata->ob_store[ob_index].em;
+
+ if (opdata->is_modal) {
+ EDBM_redo_state_restore(opdata->ob_store[ob_index].mesh_backup, em, false);
+ }
+
+ if (use_individual) {
+ EDBM_op_init(em,
+ &bmop,
+ op,
+ "inset_individual faces=%hf use_even_offset=%b use_relative_offset=%b "
+ "use_interpolate=%b thickness=%f depth=%f",
+ BM_ELEM_SELECT,
+ use_even_offset,
+ use_relative_offset,
+ use_interpolate,
+ thickness,
+ depth);
+ }
+ else {
+ EDBM_op_init(
+ em,
+ &bmop,
+ op,
+ "inset_region faces=%hf use_boundary=%b use_even_offset=%b use_relative_offset=%b "
+ "use_interpolate=%b thickness=%f depth=%f use_outset=%b use_edge_rail=%b",
+ BM_ELEM_SELECT,
+ use_boundary,
+ use_even_offset,
+ use_relative_offset,
+ use_interpolate,
+ thickness,
+ depth,
+ use_outset,
+ use_edge_rail);
+
+ if (use_outset) {
+ BMO_slot_buffer_from_enabled_hflag(
+ em->bm, &bmop, bmop.slots_in, "faces_exclude", BM_FACE, BM_ELEM_HIDDEN);
+ }
+ }
+ BMO_op_exec(em->bm, &bmop);
+
+ if (use_select_inset) {
+ /* deselect original faces/verts */
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BMO_slot_buffer_hflag_enable(
+ em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
+ }
+ else {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_in, "faces", BM_FACE, BM_ELEM_SELECT, true);
+ }
+
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
+ else {
+ EDBM_update_generic(em, true, true);
+ changed = true;
+ }
+ }
+ return changed;
}
static int edbm_inset_exec(bContext *C, wmOperator *op)
{
- if (!edbm_inset_init(C, op, false)) {
- return OPERATOR_CANCELLED;
- }
+ if (!edbm_inset_init(C, op, false)) {
+ return OPERATOR_CANCELLED;
+ }
- if (!edbm_inset_calc(op)) {
- edbm_inset_exit(C, op);
- return OPERATOR_CANCELLED;
- }
+ if (!edbm_inset_calc(op)) {
+ edbm_inset_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
- edbm_inset_exit(C, op);
- return OPERATOR_FINISHED;
+ edbm_inset_exit(C, op);
+ return OPERATOR_FINISHED;
}
static int edbm_inset_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- InsetData *opdata;
- float mlen[2];
- float center_3d[3];
-
- if (!edbm_inset_init(C, op, true)) {
- return OPERATOR_CANCELLED;
- }
-
- opdata = op->customdata;
-
- /* initialize mouse values */
- if (!calculateTransformCenter(C, V3D_AROUND_CENTER_MEDIAN, center_3d, opdata->mcenter)) {
- /* in this case the tool will likely do nothing,
- * ideally this will never happen and should be checked for above */
- opdata->mcenter[0] = opdata->mcenter[1] = 0;
- }
- 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;
-
- edbm_inset_calc(op);
-
- edbm_inset_update_header(op, C);
-
- WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ InsetData *opdata;
+ float mlen[2];
+ float center_3d[3];
+
+ if (!edbm_inset_init(C, op, true)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ opdata = op->customdata;
+
+ /* initialize mouse values */
+ if (!calculateTransformCenter(C, V3D_AROUND_CENTER_MEDIAN, center_3d, opdata->mcenter)) {
+ /* in this case the tool will likely do nothing,
+ * ideally this will never happen and should be checked for above */
+ opdata->mcenter[0] = opdata->mcenter[1] = 0;
+ }
+ 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;
+
+ edbm_inset_calc(op);
+
+ edbm_inset_update_header(op, C);
+
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
}
static int edbm_inset_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- InsetData *opdata = op->customdata;
- const bool has_numinput = hasNumInput(&opdata->num_input);
-
- /* Modal numinput active, try to handle numeric inputs first... */
- if (event->val == KM_PRESS && has_numinput && handleNumInput(C, &opdata->num_input, event)) {
- float amounts[2] = {RNA_float_get(op->ptr, "thickness"),
- RNA_float_get(op->ptr, "depth")};
- applyNumInput(&opdata->num_input, amounts);
- amounts[0] = max_ff(amounts[0], 0.0f);
- RNA_float_set(op->ptr, "thickness", amounts[0]);
- RNA_float_set(op->ptr, "depth", amounts[1]);
-
- if (edbm_inset_calc(op)) {
- edbm_inset_update_header(op, C);
- return OPERATOR_RUNNING_MODAL;
- }
- else {
- edbm_inset_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- }
- else {
- bool handled = false;
- switch (event->type) {
- case ESCKEY:
- case RIGHTMOUSE:
- edbm_inset_cancel(C, op);
- return OPERATOR_CANCELLED;
-
- case MOUSEMOVE:
- if (!has_numinput) {
- float mdiff[2];
- float amount;
-
- mdiff[0] = opdata->mcenter[0] - event->mval[0];
- mdiff[1] = opdata->mcenter[1] - event->mval[1];
-
- if (opdata->modify_depth) {
- amount = opdata->old_depth +
- ((len_v2(mdiff) - opdata->initial_length) * opdata->pixel_size) / opdata->max_obj_scale;
- }
- else {
- amount = opdata->old_thickness -
- ((len_v2(mdiff) - opdata->initial_length) * opdata->pixel_size) / opdata->max_obj_scale;
- }
-
- /* Fake shift-transform... */
- if (opdata->shift)
- amount = (amount - opdata->shift_amount) * 0.1f + opdata->shift_amount;
-
- if (opdata->modify_depth)
- RNA_float_set(op->ptr, "depth", amount);
- else {
- amount = max_ff(amount, 0.0f);
- RNA_float_set(op->ptr, "thickness", amount);
- }
-
- if (edbm_inset_calc(op))
- edbm_inset_update_header(op, C);
- else {
- edbm_inset_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- handled = true;
- }
- break;
-
- case LEFTMOUSE:
- case PADENTER:
- case RETKEY:
- if ((event->val == KM_PRESS) ||
- ((event->val == KM_RELEASE) && RNA_boolean_get(op->ptr, "release_confirm")))
- {
- edbm_inset_calc(op);
- edbm_inset_exit(C, op);
- return OPERATOR_FINISHED;
- }
- break;
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
- if (event->val == KM_PRESS) {
- if (opdata->modify_depth)
- opdata->shift_amount = RNA_float_get(op->ptr, "depth");
- else
- opdata->shift_amount = RNA_float_get(op->ptr, "thickness");
- opdata->shift = true;
- handled = true;
- }
- else {
- opdata->shift_amount = 0.0f;
- opdata->shift = false;
- handled = true;
- }
- break;
-
- case LEFTCTRLKEY:
- case RIGHTCTRLKEY:
- {
- float mlen[2];
-
- mlen[0] = opdata->mcenter[0] - event->mval[0];
- mlen[1] = opdata->mcenter[1] - event->mval[1];
-
- if (event->val == KM_PRESS) {
- opdata->old_thickness = RNA_float_get(op->ptr, "thickness");
- if (opdata->shift)
- opdata->shift_amount = opdata->old_thickness;
- opdata->modify_depth = true;
- }
- else {
- opdata->old_depth = RNA_float_get(op->ptr, "depth");
- if (opdata->shift)
- opdata->shift_amount = opdata->old_depth;
- opdata->modify_depth = false;
- }
- opdata->initial_length = len_v2(mlen);
-
- edbm_inset_update_header(op, C);
- handled = true;
- break;
- }
-
- case 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);
- if (edbm_inset_calc(op)) {
- edbm_inset_update_header(op, C);
- }
- else {
- edbm_inset_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- handled = true;
- }
- break;
- case 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);
- if (edbm_inset_calc(op)) {
- edbm_inset_update_header(op, C);
- }
- else {
- edbm_inset_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- handled = true;
- }
- break;
- case 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);
- if (edbm_inset_calc(op)) {
- edbm_inset_update_header(op, C);
- }
- else {
- edbm_inset_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- handled = true;
- }
- break;
- }
-
- /* Modal numinput inactive, try to handle numeric inputs last... */
- if (!handled && event->val == KM_PRESS && handleNumInput(C, &opdata->num_input, event)) {
- float amounts[2] = {RNA_float_get(op->ptr, "thickness"),
- RNA_float_get(op->ptr, "depth")};
- applyNumInput(&opdata->num_input, amounts);
- amounts[0] = max_ff(amounts[0], 0.0f);
- RNA_float_set(op->ptr, "thickness", amounts[0]);
- RNA_float_set(op->ptr, "depth", amounts[1]);
-
- if (edbm_inset_calc(op)) {
- edbm_inset_update_header(op, C);
- return OPERATOR_RUNNING_MODAL;
- }
- else {
- edbm_inset_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- }
- }
-
- return OPERATOR_RUNNING_MODAL;
+ InsetData *opdata = op->customdata;
+ const bool has_numinput = hasNumInput(&opdata->num_input);
+
+ /* Modal numinput active, try to handle numeric inputs first... */
+ if (event->val == KM_PRESS && has_numinput && handleNumInput(C, &opdata->num_input, event)) {
+ float amounts[2] = {RNA_float_get(op->ptr, "thickness"), RNA_float_get(op->ptr, "depth")};
+ applyNumInput(&opdata->num_input, amounts);
+ amounts[0] = max_ff(amounts[0], 0.0f);
+ RNA_float_set(op->ptr, "thickness", amounts[0]);
+ RNA_float_set(op->ptr, "depth", amounts[1]);
+
+ if (edbm_inset_calc(op)) {
+ edbm_inset_update_header(op, C);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ edbm_inset_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ bool handled = false;
+ switch (event->type) {
+ case ESCKEY:
+ case RIGHTMOUSE:
+ edbm_inset_cancel(C, op);
+ return OPERATOR_CANCELLED;
+
+ case MOUSEMOVE:
+ if (!has_numinput) {
+ float mdiff[2];
+ float amount;
+
+ mdiff[0] = opdata->mcenter[0] - event->mval[0];
+ mdiff[1] = opdata->mcenter[1] - event->mval[1];
+
+ if (opdata->modify_depth) {
+ amount = opdata->old_depth +
+ ((len_v2(mdiff) - opdata->initial_length) * opdata->pixel_size) /
+ opdata->max_obj_scale;
+ }
+ else {
+ amount = opdata->old_thickness -
+ ((len_v2(mdiff) - opdata->initial_length) * opdata->pixel_size) /
+ opdata->max_obj_scale;
+ }
+
+ /* Fake shift-transform... */
+ if (opdata->shift)
+ amount = (amount - opdata->shift_amount) * 0.1f + opdata->shift_amount;
+
+ if (opdata->modify_depth)
+ RNA_float_set(op->ptr, "depth", amount);
+ else {
+ amount = max_ff(amount, 0.0f);
+ RNA_float_set(op->ptr, "thickness", amount);
+ }
+
+ if (edbm_inset_calc(op))
+ edbm_inset_update_header(op, C);
+ else {
+ edbm_inset_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ handled = true;
+ }
+ break;
+
+ case LEFTMOUSE:
+ case PADENTER:
+ case RETKEY:
+ if ((event->val == KM_PRESS) ||
+ ((event->val == KM_RELEASE) && RNA_boolean_get(op->ptr, "release_confirm"))) {
+ edbm_inset_calc(op);
+ edbm_inset_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ break;
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ if (event->val == KM_PRESS) {
+ if (opdata->modify_depth)
+ opdata->shift_amount = RNA_float_get(op->ptr, "depth");
+ else
+ opdata->shift_amount = RNA_float_get(op->ptr, "thickness");
+ opdata->shift = true;
+ handled = true;
+ }
+ else {
+ opdata->shift_amount = 0.0f;
+ opdata->shift = false;
+ handled = true;
+ }
+ break;
+
+ case LEFTCTRLKEY:
+ case RIGHTCTRLKEY: {
+ float mlen[2];
+
+ mlen[0] = opdata->mcenter[0] - event->mval[0];
+ mlen[1] = opdata->mcenter[1] - event->mval[1];
+
+ if (event->val == KM_PRESS) {
+ opdata->old_thickness = RNA_float_get(op->ptr, "thickness");
+ if (opdata->shift)
+ opdata->shift_amount = opdata->old_thickness;
+ opdata->modify_depth = true;
+ }
+ else {
+ opdata->old_depth = RNA_float_get(op->ptr, "depth");
+ if (opdata->shift)
+ opdata->shift_amount = opdata->old_depth;
+ opdata->modify_depth = false;
+ }
+ opdata->initial_length = len_v2(mlen);
+
+ edbm_inset_update_header(op, C);
+ handled = true;
+ break;
+ }
+
+ case 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);
+ if (edbm_inset_calc(op)) {
+ edbm_inset_update_header(op, C);
+ }
+ else {
+ edbm_inset_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ handled = true;
+ }
+ break;
+ case 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);
+ if (edbm_inset_calc(op)) {
+ edbm_inset_update_header(op, C);
+ }
+ else {
+ edbm_inset_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ handled = true;
+ }
+ break;
+ case 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);
+ if (edbm_inset_calc(op)) {
+ edbm_inset_update_header(op, C);
+ }
+ else {
+ edbm_inset_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ handled = true;
+ }
+ break;
+ }
+
+ /* Modal numinput inactive, try to handle numeric inputs last... */
+ if (!handled && event->val == KM_PRESS && handleNumInput(C, &opdata->num_input, event)) {
+ float amounts[2] = {RNA_float_get(op->ptr, "thickness"), RNA_float_get(op->ptr, "depth")};
+ applyNumInput(&opdata->num_input, amounts);
+ amounts[0] = max_ff(amounts[0], 0.0f);
+ RNA_float_set(op->ptr, "thickness", amounts[0]);
+ RNA_float_set(op->ptr, "depth", amounts[1]);
+
+ if (edbm_inset_calc(op)) {
+ edbm_inset_update_header(op, C);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ edbm_inset_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
-
void MESH_OT_inset(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Inset Faces";
- ot->idname = "MESH_OT_inset";
- ot->description = "Inset new faces into selected faces";
-
- /* api callbacks */
- ot->invoke = edbm_inset_invoke;
- ot->modal = edbm_inset_modal;
- ot->exec = edbm_inset_exec;
- ot->cancel = edbm_inset_cancel;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
-
- /* properties */
- RNA_def_boolean(
- ot->srna, "use_boundary",
- true, "Boundary", "Inset face boundaries");
- RNA_def_boolean(
- ot->srna, "use_even_offset",
- true, "Offset Even", "Scale the offset to give more even thickness");
- RNA_def_boolean(
- ot->srna, "use_relative_offset",
- false, "Offset Relative", "Scale the offset by surrounding geometry");
- RNA_def_boolean(
- ot->srna, "use_edge_rail",
- false, "Edge Rail", "Inset the region along existing edges");
-
- prop = RNA_def_float_distance(ot->srna, "thickness", 0.0f, 0.0f, 1e12f, "Thickness", "", 0.0f, 10.0f);
- /* use 1 rather then 10 for max else dragging the button moves too far */
- RNA_def_property_ui_range(prop, 0.0, 1.0, 0.01, 4);
-
- prop = RNA_def_float_distance(ot->srna, "depth", 0.0f, -1e12f, 1e12f, "Depth", "", -10.0f, 10.0f);
- RNA_def_property_ui_range(prop, -10.0f, 10.0f, 0.01, 4);
-
- RNA_def_boolean(ot->srna, "use_outset", false, "Outset", "Outset rather than inset");
- RNA_def_boolean(ot->srna, "use_select_inset", false, "Select Outer", "Select the new inset faces");
- RNA_def_boolean(ot->srna, "use_individual", false, "Individual", "Individual Face Inset");
- RNA_def_boolean(ot->srna, "use_interpolate", true, "Interpolate", "Blend face data across the inset");
-
- prop = RNA_def_boolean(ot->srna, "release_confirm", 0, "Confirm on Release", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Inset Faces";
+ ot->idname = "MESH_OT_inset";
+ ot->description = "Inset new faces into selected faces";
+
+ /* api callbacks */
+ ot->invoke = edbm_inset_invoke;
+ ot->modal = edbm_inset_modal;
+ ot->exec = edbm_inset_exec;
+ ot->cancel = edbm_inset_cancel;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "use_boundary", true, "Boundary", "Inset face boundaries");
+ RNA_def_boolean(ot->srna,
+ "use_even_offset",
+ true,
+ "Offset Even",
+ "Scale the offset to give more even thickness");
+ RNA_def_boolean(ot->srna,
+ "use_relative_offset",
+ false,
+ "Offset Relative",
+ "Scale the offset by surrounding geometry");
+ RNA_def_boolean(
+ ot->srna, "use_edge_rail", false, "Edge Rail", "Inset the region along existing edges");
+
+ prop = RNA_def_float_distance(
+ ot->srna, "thickness", 0.0f, 0.0f, 1e12f, "Thickness", "", 0.0f, 10.0f);
+ /* use 1 rather then 10 for max else dragging the button moves too far */
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 0.01, 4);
+
+ prop = RNA_def_float_distance(
+ ot->srna, "depth", 0.0f, -1e12f, 1e12f, "Depth", "", -10.0f, 10.0f);
+ RNA_def_property_ui_range(prop, -10.0f, 10.0f, 0.01, 4);
+
+ RNA_def_boolean(ot->srna, "use_outset", false, "Outset", "Outset rather than inset");
+ RNA_def_boolean(
+ ot->srna, "use_select_inset", false, "Select Outer", "Select the new inset faces");
+ RNA_def_boolean(ot->srna, "use_individual", false, "Individual", "Individual Face Inset");
+ RNA_def_boolean(
+ ot->srna, "use_interpolate", true, "Interpolate", "Blend face data across the inset");
+
+ prop = RNA_def_boolean(ot->srna, "release_confirm", 0, "Confirm on Release", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
index c500683a228..06e2ef6e304 100644
--- a/source/blender/editors/mesh/editmesh_intersect.c
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -44,12 +44,11 @@
#include "intern/bmesh_private.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
#include "tools/bmesh_intersect.h"
#include "tools/bmesh_separate.h"
-
/* detect isolated holes and fill them */
#define USE_NET_ISLAND_CONNECT
@@ -58,12 +57,12 @@
*/
static int bm_face_isect_self(BMFace *f, void *UNUSED(user_data))
{
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- return 0;
- }
- else {
- return -1;
- }
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ return 0;
+ }
+ else {
+ return -1;
+ }
}
/**
@@ -71,15 +70,15 @@ static int bm_face_isect_self(BMFace *f, void *UNUSED(user_data))
*/
static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data))
{
- if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- return -1;
- }
- else if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- return 1;
- }
- else {
- return 0;
- }
+ if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ return -1;
+ }
+ else if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
/**
@@ -88,15 +87,15 @@ static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data))
*/
static int bm_face_isect_pair_swap(BMFace *f, void *UNUSED(user_data))
{
- if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- return -1;
- }
- else if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- return 0;
- }
- else {
- return 1;
- }
+ if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ return -1;
+ }
+ else if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ return 0;
+ }
+ else {
+ return 1;
+ }
}
/**
@@ -104,22 +103,21 @@ static int bm_face_isect_pair_swap(BMFace *f, void *UNUSED(user_data))
*/
static void edbm_intersect_select(BMEditMesh *em)
{
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
-
- if (em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
- BMIter iter;
- BMEdge *e;
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BM_edge_select_set(em->bm, e, true);
- }
- }
- }
+ if (em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
+ BMIter iter;
+ BMEdge *e;
- EDBM_mesh_normals_update(em);
- EDBM_update_generic(em, true, true);
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BM_edge_select_set(em->bm, e, true);
+ }
+ }
+ }
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
}
/* -------------------------------------------------------------------- */
@@ -130,138 +128,148 @@ static void edbm_intersect_select(BMEditMesh *em)
*/
enum {
- ISECT_SEL = 0,
- ISECT_SEL_UNSEL = 1,
+ ISECT_SEL = 0,
+ ISECT_SEL_UNSEL = 1,
};
enum {
- ISECT_SEPARATE_ALL = 0,
- ISECT_SEPARATE_CUT = 1,
- ISECT_SEPARATE_NONE = 2,
+ ISECT_SEPARATE_ALL = 0,
+ ISECT_SEPARATE_CUT = 1,
+ ISECT_SEPARATE_NONE = 2,
};
static int edbm_intersect_exec(bContext *C, wmOperator *op)
{
- const int mode = RNA_enum_get(op->ptr, "mode");
- int (*test_fn)(BMFace *, void *);
- bool use_separate_all = false;
- bool use_separate_cut = false;
- const int separate_mode = RNA_enum_get(op->ptr, "separate_mode");
- const float eps = RNA_float_get(op->ptr, "threshold");
- bool use_self;
- bool has_isect;
-
- switch (mode) {
- case ISECT_SEL:
- test_fn = bm_face_isect_self;
- use_self = true;
- break;
- default: /* ISECT_SEL_UNSEL */
- test_fn = bm_face_isect_pair;
- use_self = false;
- break;
- }
-
- switch (separate_mode) {
- case ISECT_SEPARATE_ALL:
- use_separate_all = true;
- break;
- case ISECT_SEPARATE_CUT:
- if (use_self == false) {
- use_separate_cut = true;
- }
- else {
- /* we could support this but would require more advanced logic inside 'BM_mesh_intersect'
- * for now just separate all */
- use_separate_all = true;
- }
- break;
- default: /* ISECT_SEPARATE_NONE */
- break;
- }
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- uint isect_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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totfacesel == 0) {
- continue;
- }
-
- has_isect = BM_mesh_intersect(
- em->bm,
- em->looptris, em->tottri,
- test_fn, NULL,
- use_self, use_separate_all, true, true, true, true,
- -1,
- eps);
-
- if (use_separate_cut) {
- /* detach selected/un-selected faces */
- BM_mesh_separate_faces(
- em->bm,
- BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT));
- }
-
- if (has_isect) {
- edbm_intersect_select(em);
- }
- else {
- isect_len++;
- }
- }
- MEM_freeN(objects);
-
- if (isect_len == objects_len) {
- BKE_report(op->reports, RPT_WARNING, "No intersections found");
- }
- return OPERATOR_FINISHED;
+ const int mode = RNA_enum_get(op->ptr, "mode");
+ int (*test_fn)(BMFace *, void *);
+ bool use_separate_all = false;
+ bool use_separate_cut = false;
+ const int separate_mode = RNA_enum_get(op->ptr, "separate_mode");
+ const float eps = RNA_float_get(op->ptr, "threshold");
+ bool use_self;
+ bool has_isect;
+
+ switch (mode) {
+ case ISECT_SEL:
+ test_fn = bm_face_isect_self;
+ use_self = true;
+ break;
+ default: /* ISECT_SEL_UNSEL */
+ test_fn = bm_face_isect_pair;
+ use_self = false;
+ break;
+ }
+
+ switch (separate_mode) {
+ case ISECT_SEPARATE_ALL:
+ use_separate_all = true;
+ break;
+ case ISECT_SEPARATE_CUT:
+ if (use_self == false) {
+ use_separate_cut = true;
+ }
+ else {
+ /* we could support this but would require more advanced logic inside 'BM_mesh_intersect'
+ * for now just separate all */
+ use_separate_all = true;
+ }
+ break;
+ default: /* ISECT_SEPARATE_NONE */
+ break;
+ }
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ uint isect_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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
+
+ has_isect = BM_mesh_intersect(em->bm,
+ em->looptris,
+ em->tottri,
+ test_fn,
+ NULL,
+ use_self,
+ use_separate_all,
+ true,
+ true,
+ true,
+ true,
+ -1,
+ eps);
+
+ if (use_separate_cut) {
+ /* detach selected/un-selected faces */
+ BM_mesh_separate_faces(
+ em->bm, BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT));
+ }
+
+ if (has_isect) {
+ edbm_intersect_select(em);
+ }
+ else {
+ isect_len++;
+ }
+ }
+ MEM_freeN(objects);
+
+ if (isect_len == objects_len) {
+ BKE_report(op->reports, RPT_WARNING, "No intersections found");
+ }
+ return OPERATOR_FINISHED;
}
void MESH_OT_intersect(struct wmOperatorType *ot)
{
- static const EnumPropertyItem isect_mode_items[] = {
- {ISECT_SEL, "SELECT", 0, "Self Intersect",
- "Self intersect selected faces"},
- {ISECT_SEL_UNSEL, "SELECT_UNSELECT", 0, "Selected/Unselected",
- "Intersect selected with unselected faces"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem isect_separate_items[] = {
- {ISECT_SEPARATE_ALL, "ALL", 0, "All",
- "Separate all geometry from intersections"},
- {ISECT_SEPARATE_CUT, "CUT", 0, "Cut",
- "Cut into geometry keeping each side separate (Selected/Unselected only)"},
- {ISECT_SEPARATE_NONE, "NONE", 0, "Merge",
- "Merge all geometry from the intersection"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Intersect (Knife)";
- ot->description = "Cut an intersection into faces";
- ot->idname = "MESH_OT_intersect";
-
- /* api callbacks */
- ot->exec = edbm_intersect_exec;
- ot->poll = ED_operator_editmesh;
-
- /* props */
- RNA_def_enum(ot->srna, "mode", isect_mode_items, ISECT_SEL_UNSEL, "Source", "");
- RNA_def_enum(ot->srna, "separate_mode", isect_separate_items, ISECT_SEPARATE_CUT, "Separate Mode", "");
- RNA_def_float_distance(ot->srna, "threshold", 0.000001f, 0.0, 0.01, "Merge threshold", "", 0.0, 0.001);
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ static const EnumPropertyItem isect_mode_items[] = {
+ {ISECT_SEL, "SELECT", 0, "Self Intersect", "Self intersect selected faces"},
+ {ISECT_SEL_UNSEL,
+ "SELECT_UNSELECT",
+ 0,
+ "Selected/Unselected",
+ "Intersect selected with unselected faces"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem isect_separate_items[] = {
+ {ISECT_SEPARATE_ALL, "ALL", 0, "All", "Separate all geometry from intersections"},
+ {ISECT_SEPARATE_CUT,
+ "CUT",
+ 0,
+ "Cut",
+ "Cut into geometry keeping each side separate (Selected/Unselected only)"},
+ {ISECT_SEPARATE_NONE, "NONE", 0, "Merge", "Merge all geometry from the intersection"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Intersect (Knife)";
+ ot->description = "Cut an intersection into faces";
+ ot->idname = "MESH_OT_intersect";
+
+ /* api callbacks */
+ ot->exec = edbm_intersect_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* props */
+ RNA_def_enum(ot->srna, "mode", isect_mode_items, ISECT_SEL_UNSEL, "Source", "");
+ RNA_def_enum(
+ ot->srna, "separate_mode", isect_separate_items, ISECT_SEPARATE_CUT, "Separate Mode", "");
+ RNA_def_float_distance(
+ ot->srna, "threshold", 0.000001f, 0.0, 0.01, "Merge threshold", "", 0.0, 0.001);
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Boolean (a kind of intersect) */
@@ -275,74 +283,90 @@ void MESH_OT_intersect(struct wmOperatorType *ot)
static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op)
{
- const int boolean_operation = RNA_enum_get(op->ptr, "operation");
- bool use_swap = RNA_boolean_get(op->ptr, "use_swap");
- const float eps = RNA_float_get(op->ptr, "threshold");
- int (*test_fn)(BMFace *, void *);
- bool has_isect;
-
- test_fn = use_swap ? bm_face_isect_pair_swap : bm_face_isect_pair;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- uint isect_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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totfacesel == 0) {
- continue;
- }
-
- has_isect = BM_mesh_intersect(
- em->bm,
- em->looptris, em->tottri,
- test_fn, NULL,
- false, false, true, true, false, true,
- boolean_operation,
- eps);
-
-
- if (has_isect) {
- edbm_intersect_select(em);
- }
- else {
- isect_len++;
- }
- }
- MEM_freeN(objects);
-
- if (isect_len == objects_len) {
- BKE_report(op->reports, RPT_WARNING, "No intersections found");
- }
- return OPERATOR_FINISHED;
+ const int boolean_operation = RNA_enum_get(op->ptr, "operation");
+ bool use_swap = RNA_boolean_get(op->ptr, "use_swap");
+ const float eps = RNA_float_get(op->ptr, "threshold");
+ int (*test_fn)(BMFace *, void *);
+ bool has_isect;
+
+ test_fn = use_swap ? bm_face_isect_pair_swap : bm_face_isect_pair;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ uint isect_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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
+
+ has_isect = BM_mesh_intersect(em->bm,
+ em->looptris,
+ em->tottri,
+ test_fn,
+ NULL,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ boolean_operation,
+ eps);
+
+ if (has_isect) {
+ edbm_intersect_select(em);
+ }
+ else {
+ isect_len++;
+ }
+ }
+ MEM_freeN(objects);
+
+ if (isect_len == objects_len) {
+ BKE_report(op->reports, RPT_WARNING, "No intersections found");
+ }
+ return OPERATOR_FINISHED;
}
void MESH_OT_intersect_boolean(struct wmOperatorType *ot)
{
- static const EnumPropertyItem isect_boolean_operation_items[] = {
- {BMESH_ISECT_BOOLEAN_ISECT, "INTERSECT", 0, "Intersect", ""},
- {BMESH_ISECT_BOOLEAN_UNION, "UNION", 0, "Union", ""},
- {BMESH_ISECT_BOOLEAN_DIFFERENCE, "DIFFERENCE", 0, "Difference", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Intersect (Boolean)";
- ot->description = "Cut solid geometry from selected to unselected";
- ot->idname = "MESH_OT_intersect_boolean";
-
- /* api callbacks */
- ot->exec = edbm_intersect_boolean_exec;
- ot->poll = ED_operator_editmesh;
-
- /* props */
- RNA_def_enum(ot->srna, "operation", isect_boolean_operation_items, BMESH_ISECT_BOOLEAN_DIFFERENCE, "Boolean", "");
- RNA_def_boolean(ot->srna, "use_swap", false, "Swap", "Use with difference intersection to swap which side is kept");
- RNA_def_float_distance(ot->srna, "threshold", 0.000001f, 0.0, 0.01, "Merge threshold", "", 0.0, 0.001);
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ static const EnumPropertyItem isect_boolean_operation_items[] = {
+ {BMESH_ISECT_BOOLEAN_ISECT, "INTERSECT", 0, "Intersect", ""},
+ {BMESH_ISECT_BOOLEAN_UNION, "UNION", 0, "Union", ""},
+ {BMESH_ISECT_BOOLEAN_DIFFERENCE, "DIFFERENCE", 0, "Difference", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Intersect (Boolean)";
+ ot->description = "Cut solid geometry from selected to unselected";
+ ot->idname = "MESH_OT_intersect_boolean";
+
+ /* api callbacks */
+ ot->exec = edbm_intersect_boolean_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* props */
+ RNA_def_enum(ot->srna,
+ "operation",
+ isect_boolean_operation_items,
+ BMESH_ISECT_BOOLEAN_DIFFERENCE,
+ "Boolean",
+ "");
+ RNA_def_boolean(ot->srna,
+ "use_swap",
+ false,
+ "Swap",
+ "Use with difference intersection to swap which side is kept");
+ RNA_def_float_distance(
+ ot->srna, "threshold", 0.000001f, 0.0, 0.01, "Merge threshold", "", 0.0, 0.001);
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -353,88 +377,82 @@ void MESH_OT_intersect_boolean(struct wmOperatorType *ot)
/** \name Face/Edge Split
* \{ */
-static void bm_face_split_by_edges(
- BMesh *bm, BMFace *f, const char hflag,
- /* reusable memory buffer */
- BLI_Buffer *edge_net_temp_buf)
+static void bm_face_split_by_edges(BMesh *bm,
+ BMFace *f,
+ const char hflag,
+ /* reusable memory buffer */
+ BLI_Buffer *edge_net_temp_buf)
{
- const int f_index = BM_elem_index_get(f);
-
- BMLoop *l_iter;
- BMLoop *l_first;
- BMVert *v;
-
- BMFace **face_arr;
- int face_arr_len;
-
- /* likely this will stay very small
- * all verts pushed into this stack _must_ have their previous edges set! */
- BLI_SMALLSTACK_DECLARE(vert_stack, BMVert *);
- BLI_SMALLSTACK_DECLARE(vert_stack_next, BMVert *);
-
- BLI_assert(edge_net_temp_buf->count == 0);
-
- /* collect all edges */
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BMIter iter;
- BMEdge *e;
-
- BM_ITER_ELEM (e, &iter, l_iter->v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e, hflag) &&
- (BM_elem_index_get(e) == f_index))
- {
- v = BM_edge_other_vert(e, l_iter->v);
- v->e = e;
-
- BLI_SMALLSTACK_PUSH(vert_stack, v);
- BLI_buffer_append(edge_net_temp_buf, BMEdge *, e);
- }
- }
- } while ((l_iter = l_iter->next) != l_first);
-
-
-
- /* now assign all */
- /* pop free values into the next stack */
- while ((v = BLI_SMALLSTACK_POP_EX(vert_stack, vert_stack_next))) {
- BMIter eiter;
- BMEdge *e_next;
-
- BM_ITER_ELEM (e_next, &eiter, v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e_next, hflag) &&
- (BM_elem_index_get(e_next) == -1))
- {
- BMVert *v_next;
- v_next = BM_edge_other_vert(e_next, v);
- BM_elem_index_set(e_next, f_index);
- BLI_SMALLSTACK_PUSH(vert_stack_next, v_next);
- BLI_buffer_append(edge_net_temp_buf, BMEdge *, e_next);
- }
- }
-
- if (BLI_SMALLSTACK_IS_EMPTY(vert_stack)) {
- BLI_SMALLSTACK_SWAP(vert_stack, vert_stack_next);
- }
- }
-
- BM_face_split_edgenet(
- bm, f, edge_net_temp_buf->data, edge_net_temp_buf->count,
- &face_arr, &face_arr_len);
-
- BLI_buffer_clear(edge_net_temp_buf);
-
- if (face_arr_len) {
- int i;
- for (i = 0; i < face_arr_len; i++) {
- BM_face_select_set(bm, face_arr[i], true);
- BM_elem_flag_disable(face_arr[i], hflag);
- }
- }
-
- if (face_arr) {
- MEM_freeN(face_arr);
- }
+ const int f_index = BM_elem_index_get(f);
+
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ BMVert *v;
+
+ BMFace **face_arr;
+ int face_arr_len;
+
+ /* likely this will stay very small
+ * all verts pushed into this stack _must_ have their previous edges set! */
+ BLI_SMALLSTACK_DECLARE(vert_stack, BMVert *);
+ BLI_SMALLSTACK_DECLARE(vert_stack_next, BMVert *);
+
+ BLI_assert(edge_net_temp_buf->count == 0);
+
+ /* collect all edges */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BMIter iter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &iter, l_iter->v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e, hflag) && (BM_elem_index_get(e) == f_index)) {
+ v = BM_edge_other_vert(e, l_iter->v);
+ v->e = e;
+
+ BLI_SMALLSTACK_PUSH(vert_stack, v);
+ BLI_buffer_append(edge_net_temp_buf, BMEdge *, e);
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ /* now assign all */
+ /* pop free values into the next stack */
+ while ((v = BLI_SMALLSTACK_POP_EX(vert_stack, vert_stack_next))) {
+ BMIter eiter;
+ BMEdge *e_next;
+
+ BM_ITER_ELEM (e_next, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e_next, hflag) && (BM_elem_index_get(e_next) == -1)) {
+ BMVert *v_next;
+ v_next = BM_edge_other_vert(e_next, v);
+ BM_elem_index_set(e_next, f_index);
+ BLI_SMALLSTACK_PUSH(vert_stack_next, v_next);
+ BLI_buffer_append(edge_net_temp_buf, BMEdge *, e_next);
+ }
+ }
+
+ if (BLI_SMALLSTACK_IS_EMPTY(vert_stack)) {
+ BLI_SMALLSTACK_SWAP(vert_stack, vert_stack_next);
+ }
+ }
+
+ BM_face_split_edgenet(
+ bm, f, edge_net_temp_buf->data, edge_net_temp_buf->count, &face_arr, &face_arr_len);
+
+ BLI_buffer_clear(edge_net_temp_buf);
+
+ if (face_arr_len) {
+ int i;
+ for (i = 0; i < face_arr_len; i++) {
+ BM_face_select_set(bm, face_arr[i], true);
+ BM_elem_flag_disable(face_arr[i], hflag);
+ }
+ }
+
+ if (face_arr) {
+ MEM_freeN(face_arr);
+ }
}
/**
@@ -443,113 +461,114 @@ static void bm_face_split_by_edges(
*/
static bool bm_vert_in_faces_radial(BMVert *v, BMEdge *e_radial, BMFace *f_ignore)
{
- BLI_assert(BM_vert_in_face(v, f_ignore) == false);
- if (e_radial->l) {
- BMLoop *l_iter = e_radial->l;
- do {
- if (l_iter->f != f_ignore) {
- if (BM_vert_in_face(v, l_iter->f)) {
- return true;
- }
- }
- } while ((l_iter = l_iter->radial_next) != e_radial->l);
- }
- return false;
+ BLI_assert(BM_vert_in_face(v, f_ignore) == false);
+ if (e_radial->l) {
+ BMLoop *l_iter = e_radial->l;
+ do {
+ if (l_iter->f != f_ignore) {
+ if (BM_vert_in_face(v, l_iter->f)) {
+ return true;
+ }
+ }
+ } while ((l_iter = l_iter->radial_next) != e_radial->l);
+ }
+ return false;
}
#ifdef USE_NET_ISLAND_CONNECT
struct LinkBase {
- LinkNode *list;
- unsigned int list_len;
+ LinkNode *list;
+ unsigned int list_len;
};
-static void ghash_insert_face_edge_link(
- GHash *gh, BMFace *f_key, BMEdge *e_val,
- MemArena *mem_arena)
+static void ghash_insert_face_edge_link(GHash *gh,
+ BMFace *f_key,
+ BMEdge *e_val,
+ MemArena *mem_arena)
{
- void **ls_base_p;
- struct LinkBase *ls_base;
- LinkNode *ls;
-
- if (!BLI_ghash_ensure_p(gh, f_key, &ls_base_p)) {
- ls_base = *ls_base_p = BLI_memarena_alloc(mem_arena, sizeof(*ls_base));
- ls_base->list = NULL;
- ls_base->list_len = 0;
- }
- else {
- ls_base = *ls_base_p;
- }
-
- ls = BLI_memarena_alloc(mem_arena, sizeof(*ls));
- ls->next = ls_base->list;
- ls->link = e_val;
- ls_base->list = ls;
- ls_base->list_len += 1;
+ void **ls_base_p;
+ struct LinkBase *ls_base;
+ LinkNode *ls;
+
+ if (!BLI_ghash_ensure_p(gh, f_key, &ls_base_p)) {
+ ls_base = *ls_base_p = BLI_memarena_alloc(mem_arena, sizeof(*ls_base));
+ ls_base->list = NULL;
+ ls_base->list_len = 0;
+ }
+ else {
+ ls_base = *ls_base_p;
+ }
+
+ ls = BLI_memarena_alloc(mem_arena, sizeof(*ls));
+ ls->next = ls_base->list;
+ ls->link = e_val;
+ ls_base->list = ls;
+ ls_base->list_len += 1;
}
static int bm_edge_sort_length_cb(const void *e_a_v, const void *e_b_v)
{
- const float val_a = -BM_edge_calc_length_squared(*((BMEdge **)e_a_v));
- const float val_b = -BM_edge_calc_length_squared(*((BMEdge **)e_b_v));
-
- if (val_a > val_b) return 1;
- else if (val_a < val_b) return -1;
- else return 0;
+ const float val_a = -BM_edge_calc_length_squared(*((BMEdge **)e_a_v));
+ const float val_b = -BM_edge_calc_length_squared(*((BMEdge **)e_b_v));
+
+ if (val_a > val_b)
+ return 1;
+ else if (val_a < val_b)
+ return -1;
+ else
+ return 0;
}
static void bm_face_split_by_edges_island_connect(
- BMesh *bm, BMFace *f,
- LinkNode *e_link, const int e_link_len,
- MemArena *mem_arena_edgenet)
+ BMesh *bm, BMFace *f, LinkNode *e_link, const int e_link_len, MemArena *mem_arena_edgenet)
{
- BMEdge **edge_arr = BLI_memarena_alloc(mem_arena_edgenet, sizeof(*edge_arr) * e_link_len);
- int edge_arr_len = 0;
-
- while (e_link) {
- edge_arr[edge_arr_len++] = e_link->link;
- e_link = e_link->next;
- }
-
- {
- unsigned int edge_arr_holes_len;
- BMEdge **edge_arr_holes;
- if (BM_face_split_edgenet_connect_islands(
- bm, f,
- edge_arr, e_link_len,
- true,
- mem_arena_edgenet,
- &edge_arr_holes, &edge_arr_holes_len))
- {
- edge_arr_len = edge_arr_holes_len;
- edge_arr = edge_arr_holes; /* owned by the arena */
- }
- }
-
- BM_face_split_edgenet(
- bm, f, edge_arr, edge_arr_len,
- NULL, NULL);
-
- for (int i = e_link_len; i < edge_arr_len; i++) {
- BM_edge_select_set(bm, edge_arr[i], true);
- }
-
- if (e_link_len != edge_arr_len) {
- /* connecting partial islands can add redundant edges
- * sort before removal to give deterministic outcome */
- qsort(edge_arr, edge_arr_len - e_link_len, sizeof(*edge_arr), bm_edge_sort_length_cb);
- for (int i = e_link_len; i < edge_arr_len; i++) {
- BMFace *f_pair[2];
- if (BM_edge_face_pair(edge_arr[i], &f_pair[0], &f_pair[1])) {
- if (BM_face_share_vert_count(f_pair[0], f_pair[1]) == 2) {
- BMFace *f_new = BM_faces_join(bm, f_pair, 2, true);
- if (f_new) {
- BM_face_select_set(bm, f_new, true);
- }
- }
- }
- }
- }
+ BMEdge **edge_arr = BLI_memarena_alloc(mem_arena_edgenet, sizeof(*edge_arr) * e_link_len);
+ int edge_arr_len = 0;
+
+ while (e_link) {
+ edge_arr[edge_arr_len++] = e_link->link;
+ e_link = e_link->next;
+ }
+
+ {
+ unsigned int edge_arr_holes_len;
+ BMEdge **edge_arr_holes;
+ if (BM_face_split_edgenet_connect_islands(bm,
+ f,
+ edge_arr,
+ e_link_len,
+ true,
+ mem_arena_edgenet,
+ &edge_arr_holes,
+ &edge_arr_holes_len)) {
+ edge_arr_len = edge_arr_holes_len;
+ edge_arr = edge_arr_holes; /* owned by the arena */
+ }
+ }
+
+ BM_face_split_edgenet(bm, f, edge_arr, edge_arr_len, NULL, NULL);
+
+ for (int i = e_link_len; i < edge_arr_len; i++) {
+ BM_edge_select_set(bm, edge_arr[i], true);
+ }
+
+ if (e_link_len != edge_arr_len) {
+ /* connecting partial islands can add redundant edges
+ * sort before removal to give deterministic outcome */
+ qsort(edge_arr, edge_arr_len - e_link_len, sizeof(*edge_arr), bm_edge_sort_length_cb);
+ for (int i = e_link_len; i < edge_arr_len; i++) {
+ BMFace *f_pair[2];
+ if (BM_edge_face_pair(edge_arr[i], &f_pair[0], &f_pair[1])) {
+ if (BM_face_share_vert_count(f_pair[0], f_pair[1]) == 2) {
+ BMFace *f_new = BM_faces_join(bm, f_pair, 2, true);
+ if (f_new) {
+ BM_face_select_set(bm, f_new, true);
+ }
+ }
+ }
+ }
+ }
}
/**
@@ -570,394 +589,389 @@ static void bm_face_split_by_edges_island_connect(
*
* \note Currently we don't snap to verts or split chains by verts on-edges.
*/
-static BMEdge *bm_face_split_edge_find(
- BMEdge *e_a, BMFace *f_a, BMVert *v_pivot, BMFace **ftable, const int ftable_len,
- float r_v_pivot_co[3], float *r_v_pivot_fac)
+static BMEdge *bm_face_split_edge_find(BMEdge *e_a,
+ BMFace *f_a,
+ BMVert *v_pivot,
+ BMFace **ftable,
+ const int ftable_len,
+ float r_v_pivot_co[3],
+ float *r_v_pivot_fac)
{
- const int f_a_index = BM_elem_index_get(e_a);
- bool found_other_self = false;
- int found_other_face = 0;
- BLI_SMALLSTACK_DECLARE(face_stack, BMFace *);
-
- /* loop over surrounding edges to check if we're part of a chain or a delimiter vertex */
- BMEdge *e_b = v_pivot->e;
- do {
- if (e_b != e_a) {
- const int f_b_index = BM_elem_index_get(e_b);
- if (f_b_index == f_a_index) {
- /* not an endpoint */
- found_other_self = true;
- }
- else if (f_b_index != -1) {
- BLI_assert(f_b_index < ftable_len);
- UNUSED_VARS_NDEBUG(ftable_len);
-
- /* 'v_pivot' spans 2+ faces,
- * tag to ensure we pick an edge that includes this face */
- BMFace *f_b = ftable[f_b_index];
- if (!BM_elem_flag_test(f_b, BM_ELEM_INTERNAL_TAG)) {
- BM_elem_flag_enable(f_b, BM_ELEM_INTERNAL_TAG);
- BLI_SMALLSTACK_PUSH(face_stack, f_b);
- found_other_face++;
- }
- }
- }
- } while ((e_b = BM_DISK_EDGE_NEXT(e_b, v_pivot)) != v_pivot->e);
-
- BMEdge *e_split = NULL;
-
- /* if we have no others or the other edge is outside this face,
- * we're an endpoint to connect to a boundary */
- if ((found_other_self == false) || found_other_face) {
-
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_a);
- float dist_best_sq = FLT_MAX;
-
- do {
- float v_pivot_co_test[3];
- float v_pivot_fac = line_point_factor_v3(v_pivot->co, l_iter->e->v1->co, l_iter->e->v2->co);
- CLAMP(v_pivot_fac, 0.0f, 1.0f);
- interp_v3_v3v3(v_pivot_co_test, l_iter->e->v1->co, l_iter->e->v2->co, v_pivot_fac);
-
- float dist_test_sq = len_squared_v3v3(v_pivot_co_test, v_pivot->co);
- if ((dist_test_sq < dist_best_sq) || (e_split == NULL)) {
- bool ok = true;
-
- if (UNLIKELY(BM_edge_exists(v_pivot, l_iter->e->v1) ||
- BM_edge_exists(v_pivot, l_iter->e->v2)))
- {
- /* very unlikely but will cause complications splicing the verts together,
- * so just skip this case */
- ok = false;
- }
- else if (found_other_face) {
- /* double check that _all_ the faces used by v_pivot's edges are attached
- * to this edge otherwise don't attempt the split since it will give
- * non-deterministic results */
- BMLoop *l_radial_iter = l_iter->radial_next;
- int other_face_shared = 0;
- if (l_radial_iter != l_iter) {
- do {
- if (BM_elem_flag_test(l_radial_iter->f, BM_ELEM_INTERNAL_TAG)) {
- other_face_shared++;
- }
- } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter);
- }
- if (other_face_shared != found_other_face) {
- ok = false;
- }
- }
-
- if (ok) {
- e_split = l_iter->e;
- dist_best_sq = dist_test_sq;
- copy_v3_v3(r_v_pivot_co, v_pivot_co_test);
- *r_v_pivot_fac = v_pivot_fac;
- }
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- {
- /* reset the flag, for future use */
- BMFace *f;
- while ((f = BLI_SMALLSTACK_POP(face_stack))) {
- BM_elem_flag_disable(f, BM_ELEM_INTERNAL_TAG);
- }
- }
-
- return e_split;
+ const int f_a_index = BM_elem_index_get(e_a);
+ bool found_other_self = false;
+ int found_other_face = 0;
+ BLI_SMALLSTACK_DECLARE(face_stack, BMFace *);
+
+ /* loop over surrounding edges to check if we're part of a chain or a delimiter vertex */
+ BMEdge *e_b = v_pivot->e;
+ do {
+ if (e_b != e_a) {
+ const int f_b_index = BM_elem_index_get(e_b);
+ if (f_b_index == f_a_index) {
+ /* not an endpoint */
+ found_other_self = true;
+ }
+ else if (f_b_index != -1) {
+ BLI_assert(f_b_index < ftable_len);
+ UNUSED_VARS_NDEBUG(ftable_len);
+
+ /* 'v_pivot' spans 2+ faces,
+ * tag to ensure we pick an edge that includes this face */
+ BMFace *f_b = ftable[f_b_index];
+ if (!BM_elem_flag_test(f_b, BM_ELEM_INTERNAL_TAG)) {
+ BM_elem_flag_enable(f_b, BM_ELEM_INTERNAL_TAG);
+ BLI_SMALLSTACK_PUSH(face_stack, f_b);
+ found_other_face++;
+ }
+ }
+ }
+ } while ((e_b = BM_DISK_EDGE_NEXT(e_b, v_pivot)) != v_pivot->e);
+
+ BMEdge *e_split = NULL;
+
+ /* if we have no others or the other edge is outside this face,
+ * we're an endpoint to connect to a boundary */
+ if ((found_other_self == false) || found_other_face) {
+
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_a);
+ float dist_best_sq = FLT_MAX;
+
+ do {
+ float v_pivot_co_test[3];
+ float v_pivot_fac = line_point_factor_v3(v_pivot->co, l_iter->e->v1->co, l_iter->e->v2->co);
+ CLAMP(v_pivot_fac, 0.0f, 1.0f);
+ interp_v3_v3v3(v_pivot_co_test, l_iter->e->v1->co, l_iter->e->v2->co, v_pivot_fac);
+
+ float dist_test_sq = len_squared_v3v3(v_pivot_co_test, v_pivot->co);
+ if ((dist_test_sq < dist_best_sq) || (e_split == NULL)) {
+ bool ok = true;
+
+ if (UNLIKELY(BM_edge_exists(v_pivot, l_iter->e->v1) ||
+ BM_edge_exists(v_pivot, l_iter->e->v2))) {
+ /* very unlikely but will cause complications splicing the verts together,
+ * so just skip this case */
+ ok = false;
+ }
+ else if (found_other_face) {
+ /* double check that _all_ the faces used by v_pivot's edges are attached
+ * to this edge otherwise don't attempt the split since it will give
+ * non-deterministic results */
+ BMLoop *l_radial_iter = l_iter->radial_next;
+ int other_face_shared = 0;
+ if (l_radial_iter != l_iter) {
+ do {
+ if (BM_elem_flag_test(l_radial_iter->f, BM_ELEM_INTERNAL_TAG)) {
+ other_face_shared++;
+ }
+ } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter);
+ }
+ if (other_face_shared != found_other_face) {
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ e_split = l_iter->e;
+ dist_best_sq = dist_test_sq;
+ copy_v3_v3(r_v_pivot_co, v_pivot_co_test);
+ *r_v_pivot_fac = v_pivot_fac;
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ {
+ /* reset the flag, for future use */
+ BMFace *f;
+ while ((f = BLI_SMALLSTACK_POP(face_stack))) {
+ BM_elem_flag_disable(f, BM_ELEM_INTERNAL_TAG);
+ }
+ }
+
+ return e_split;
}
-#endif /* USE_NET_ISLAND_CONNECT */
-
+#endif /* USE_NET_ISLAND_CONNECT */
static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *UNUSED(op))
{
- const char hflag = BM_ELEM_TAG;
-
- BMEdge *e;
- BMIter iter;
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- if ((bm->totedgesel == 0) ||
- (bm->totfacesel == 0))
- {
- continue;
- }
-
- BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
-
- {
- BMVert *v;
- BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_disable(v, hflag);
- }
- }
-
- /* edge index is set to -1 then used to associate them with faces */
- BM_ITER_MESH(e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_wire(e)) {
- BM_elem_flag_enable(e, hflag);
-
- BM_elem_flag_enable(e->v1, hflag);
- BM_elem_flag_enable(e->v2, hflag);
-
- }
- else {
- BM_elem_flag_disable(e, hflag);
- }
- BM_elem_index_set(e, -1); /* set_dirty */
- }
- bm->elem_index_dirty |= BM_EDGE;
-
- {
- BMFace *f;
- int i;
- BM_ITER_MESH_INDEX(f, &iter, bm, BM_FACES_OF_MESH, i) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- BM_elem_flag_enable(f, hflag);
- }
- else {
- BM_elem_flag_disable(f, hflag);
- }
- BM_elem_flag_disable(f, BM_ELEM_INTERNAL_TAG);
- BM_elem_index_set(f, i); /* set_ok */
- }
- }
- bm->elem_index_dirty &= ~BM_FACE;
-
- BM_ITER_MESH(e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, hflag)) {
- BMIter viter;
- BMVert *v;
- BM_ITER_ELEM(v, &viter, e, BM_VERTS_OF_EDGE) {
- BMIter liter;
- BMLoop *l;
-
- unsigned int loop_stack_len;
- BMLoop *l_best = NULL;
-
- BLI_assert(BLI_SMALLSTACK_IS_EMPTY(loop_stack));
- loop_stack_len = 0;
-
- BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) {
- if (BM_elem_flag_test(l->f, hflag)) {
- BLI_SMALLSTACK_PUSH(loop_stack, l);
- loop_stack_len++;
- }
- }
-
- if (loop_stack_len == 0) {
- /* pass */
- }
- else if (loop_stack_len == 1) {
- l_best = BLI_SMALLSTACK_POP(loop_stack);
- }
- else {
- /* complicated case, match the edge with a face-loop */
-
- BMVert *v_other = BM_edge_other_vert(e, v);
- float e_dir[3];
-
- /* we want closest to zero */
- float dot_best = FLT_MAX;
-
- sub_v3_v3v3(e_dir, v_other->co, v->co);
- normalize_v3(e_dir);
-
- while ((l = BLI_SMALLSTACK_POP(loop_stack))) {
- float dot_test;
-
- /* Check dot first to save on expensive angle-comparison.
- * ideal case is 90d difference == 0.0 dot */
- dot_test = fabsf(dot_v3v3(e_dir, l->f->no));
- if (dot_test < dot_best) {
-
- /* check we're in the correct corner
- * (works with convex loops too) */
- if (angle_signed_on_axis_v3v3v3_v3(l->prev->v->co, l->v->co, v_other->co, l->f->no) <
- angle_signed_on_axis_v3v3v3_v3(l->prev->v->co, l->v->co, l->next->v->co, l->f->no))
- {
- dot_best = dot_test;
- l_best = l;
- }
- }
- }
- }
-
- if (l_best) {
- BM_elem_index_set(e, BM_elem_index_get(l_best->f)); /* set_dirty */
- }
- }
- }
- }
-
- {
- BMFace *f;
- BLI_buffer_declare_static(BMEdge **, edge_net_temp_buf, 0, 128);
-
- BM_ITER_MESH(f, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, hflag)) {
- bm_face_split_by_edges(bm, f, hflag, &edge_net_temp_buf);
- }
- }
- BLI_buffer_free(&edge_net_temp_buf);
- }
+ const char hflag = BM_ELEM_TAG;
+
+ BMEdge *e;
+ BMIter iter;
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ if ((bm->totedgesel == 0) || (bm->totfacesel == 0)) {
+ continue;
+ }
+
+ BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
+
+ {
+ BMVert *v;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_disable(v, hflag);
+ }
+ }
+
+ /* edge index is set to -1 then used to associate them with faces */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_wire(e)) {
+ BM_elem_flag_enable(e, hflag);
+
+ BM_elem_flag_enable(e->v1, hflag);
+ BM_elem_flag_enable(e->v2, hflag);
+ }
+ else {
+ BM_elem_flag_disable(e, hflag);
+ }
+ BM_elem_index_set(e, -1); /* set_dirty */
+ }
+ bm->elem_index_dirty |= BM_EDGE;
+
+ {
+ BMFace *f;
+ int i;
+ BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_elem_flag_enable(f, hflag);
+ }
+ else {
+ BM_elem_flag_disable(f, hflag);
+ }
+ BM_elem_flag_disable(f, BM_ELEM_INTERNAL_TAG);
+ BM_elem_index_set(f, i); /* set_ok */
+ }
+ }
+ bm->elem_index_dirty &= ~BM_FACE;
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, hflag)) {
+ BMIter viter;
+ BMVert *v;
+ BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
+ BMIter liter;
+ BMLoop *l;
+
+ unsigned int loop_stack_len;
+ BMLoop *l_best = NULL;
+
+ BLI_assert(BLI_SMALLSTACK_IS_EMPTY(loop_stack));
+ loop_stack_len = 0;
+
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ if (BM_elem_flag_test(l->f, hflag)) {
+ BLI_SMALLSTACK_PUSH(loop_stack, l);
+ loop_stack_len++;
+ }
+ }
+
+ if (loop_stack_len == 0) {
+ /* pass */
+ }
+ else if (loop_stack_len == 1) {
+ l_best = BLI_SMALLSTACK_POP(loop_stack);
+ }
+ else {
+ /* complicated case, match the edge with a face-loop */
+
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ float e_dir[3];
+
+ /* we want closest to zero */
+ float dot_best = FLT_MAX;
+
+ sub_v3_v3v3(e_dir, v_other->co, v->co);
+ normalize_v3(e_dir);
+
+ while ((l = BLI_SMALLSTACK_POP(loop_stack))) {
+ float dot_test;
+
+ /* Check dot first to save on expensive angle-comparison.
+ * ideal case is 90d difference == 0.0 dot */
+ dot_test = fabsf(dot_v3v3(e_dir, l->f->no));
+ if (dot_test < dot_best) {
+
+ /* check we're in the correct corner
+ * (works with convex loops too) */
+ if (angle_signed_on_axis_v3v3v3_v3(
+ l->prev->v->co, l->v->co, v_other->co, l->f->no) <
+ angle_signed_on_axis_v3v3v3_v3(
+ l->prev->v->co, l->v->co, l->next->v->co, l->f->no)) {
+ dot_best = dot_test;
+ l_best = l;
+ }
+ }
+ }
+ }
+
+ if (l_best) {
+ BM_elem_index_set(e, BM_elem_index_get(l_best->f)); /* set_dirty */
+ }
+ }
+ }
+ }
+
+ {
+ BMFace *f;
+ BLI_buffer_declare_static(BMEdge **, edge_net_temp_buf, 0, 128);
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, hflag)) {
+ bm_face_split_by_edges(bm, f, hflag, &edge_net_temp_buf);
+ }
+ }
+ BLI_buffer_free(&edge_net_temp_buf);
+ }
#ifdef USE_NET_ISLAND_CONNECT
- /* before overwriting edge index values, collect edges left untouched */
- BLI_Stack *edges_loose = BLI_stack_new(sizeof(BMEdge *), __func__);
- BM_ITER_MESH(e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_wire(e)) {
- BLI_stack_push(edges_loose, &e);
- }
- }
+ /* before overwriting edge index values, collect edges left untouched */
+ BLI_Stack *edges_loose = BLI_stack_new(sizeof(BMEdge *), __func__);
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_wire(e)) {
+ BLI_stack_push(edges_loose, &e);
+ }
+ }
#endif
- EDBM_mesh_normals_update(em);
- EDBM_update_generic(em, true, true);
-
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
#ifdef USE_NET_ISLAND_CONNECT
- /* we may have remaining isolated regions remaining,
- * these will need to have connecting edges created */
- if (!BLI_stack_is_empty(edges_loose)) {
- GHash *face_edge_map = BLI_ghash_ptr_new(__func__);
-
- MemArena *mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
-
- BM_mesh_elem_index_ensure(bm, BM_FACE);
-
- {
- BMBVHTree *bmbvh = BKE_bmbvh_new(bm, em->looptris, em->tottri, BMBVH_RESPECT_SELECT, NULL, false);
-
- BM_ITER_MESH(e, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_index_set(e, -1); /* set_dirty */
- }
-
- while (!BLI_stack_is_empty(edges_loose)) {
- BLI_stack_pop(edges_loose, &e);
- float e_center[3];
- mid_v3_v3v3(e_center, e->v1->co, e->v2->co);
-
- BMFace *f = BKE_bmbvh_find_face_closest(bmbvh, e_center, FLT_MAX);
- if (f) {
- ghash_insert_face_edge_link(face_edge_map, f, e, mem_arena);
- BM_elem_index_set(e, BM_elem_index_get(f)); /* set_dirty */
- }
- }
-
- BKE_bmbvh_free(bmbvh);
- }
-
- bm->elem_index_dirty |= BM_EDGE;
-
- BM_mesh_elem_table_ensure(bm, BM_FACE);
-
- /* detect edges chains that span faces
- * and splice vertices into the closest edges */
- {
- GHashIterator gh_iter;
-
- GHASH_ITER(gh_iter, face_edge_map) {
- BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
- struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
- LinkNode *e_link = e_ls_base->list;
-
- do {
- e = e_link->link;
-
- for (int j = 0; j < 2; j++) {
- BMVert *v_pivot = (&e->v1)[j];
- /* checking that \a v_pivot isn't in the face prevents attempting
- * to splice the same vertex into an edge from multiple faces */
- if (!BM_vert_in_face(v_pivot, f)) {
- float v_pivot_co[3];
- float v_pivot_fac;
- BMEdge *e_split = bm_face_split_edge_find(
- e, f, v_pivot, bm->ftable, bm->totface,
- v_pivot_co, &v_pivot_fac);
-
- if (e_split) {
- /* for degenerate cases this vertex may be in one
- * of this edges radial faces */
- if (!bm_vert_in_faces_radial(v_pivot, e_split, f)) {
- BMEdge *e_new;
- BMVert *v_new = BM_edge_split(bm, e_split, e_split->v1, &e_new, v_pivot_fac);
- if (v_new) {
- /* we _know_ these don't share an edge */
- BM_vert_splice(bm, v_pivot, v_new);
- BM_elem_index_set(e_new, BM_elem_index_get(e_split));
- }
- }
- }
- }
- }
-
- } while ((e_link = e_link->next));
- }
- }
-
-
- {
- MemArena *mem_arena_edgenet = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
-
- GHashIterator gh_iter;
-
- GHASH_ITER(gh_iter, face_edge_map) {
- BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
- struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
-
- bm_face_split_by_edges_island_connect(
- bm, f,
- e_ls_base->list, e_ls_base->list_len,
- mem_arena_edgenet);
-
- BLI_memarena_clear(mem_arena_edgenet);
- }
-
- BLI_memarena_free(mem_arena_edgenet);
- }
-
- BLI_memarena_free(mem_arena);
-
- BLI_ghash_free(face_edge_map, NULL, NULL);
-
- EDBM_mesh_normals_update(em);
- EDBM_update_generic(em, true, true);
- }
-
- BLI_stack_free(edges_loose);
-#endif /* USE_NET_ISLAND_CONNECT */
-
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ /* we may have remaining isolated regions remaining,
+ * these will need to have connecting edges created */
+ if (!BLI_stack_is_empty(edges_loose)) {
+ GHash *face_edge_map = BLI_ghash_ptr_new(__func__);
+
+ MemArena *mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
+ BM_mesh_elem_index_ensure(bm, BM_FACE);
+
+ {
+ BMBVHTree *bmbvh = BKE_bmbvh_new(
+ bm, em->looptris, em->tottri, BMBVH_RESPECT_SELECT, NULL, false);
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_index_set(e, -1); /* set_dirty */
+ }
+
+ while (!BLI_stack_is_empty(edges_loose)) {
+ BLI_stack_pop(edges_loose, &e);
+ float e_center[3];
+ mid_v3_v3v3(e_center, e->v1->co, e->v2->co);
+
+ BMFace *f = BKE_bmbvh_find_face_closest(bmbvh, e_center, FLT_MAX);
+ if (f) {
+ ghash_insert_face_edge_link(face_edge_map, f, e, mem_arena);
+ BM_elem_index_set(e, BM_elem_index_get(f)); /* set_dirty */
+ }
+ }
+
+ BKE_bmbvh_free(bmbvh);
+ }
+
+ bm->elem_index_dirty |= BM_EDGE;
+
+ BM_mesh_elem_table_ensure(bm, BM_FACE);
+
+ /* detect edges chains that span faces
+ * and splice vertices into the closest edges */
+ {
+ GHashIterator gh_iter;
+
+ GHASH_ITER (gh_iter, face_edge_map) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+ struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
+ LinkNode *e_link = e_ls_base->list;
+
+ do {
+ e = e_link->link;
+
+ for (int j = 0; j < 2; j++) {
+ BMVert *v_pivot = (&e->v1)[j];
+ /* checking that \a v_pivot isn't in the face prevents attempting
+ * to splice the same vertex into an edge from multiple faces */
+ if (!BM_vert_in_face(v_pivot, f)) {
+ float v_pivot_co[3];
+ float v_pivot_fac;
+ BMEdge *e_split = bm_face_split_edge_find(
+ e, f, v_pivot, bm->ftable, bm->totface, v_pivot_co, &v_pivot_fac);
+
+ if (e_split) {
+ /* for degenerate cases this vertex may be in one
+ * of this edges radial faces */
+ if (!bm_vert_in_faces_radial(v_pivot, e_split, f)) {
+ BMEdge *e_new;
+ BMVert *v_new = BM_edge_split(bm, e_split, e_split->v1, &e_new, v_pivot_fac);
+ if (v_new) {
+ /* we _know_ these don't share an edge */
+ BM_vert_splice(bm, v_pivot, v_new);
+ BM_elem_index_set(e_new, BM_elem_index_get(e_split));
+ }
+ }
+ }
+ }
+ }
+
+ } while ((e_link = e_link->next));
+ }
+ }
+
+ {
+ MemArena *mem_arena_edgenet = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
+ GHashIterator gh_iter;
+
+ GHASH_ITER (gh_iter, face_edge_map) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+ struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
+
+ bm_face_split_by_edges_island_connect(
+ bm, f, e_ls_base->list, e_ls_base->list_len, mem_arena_edgenet);
+
+ BLI_memarena_clear(mem_arena_edgenet);
+ }
+
+ BLI_memarena_free(mem_arena_edgenet);
+ }
+
+ BLI_memarena_free(mem_arena);
+
+ BLI_ghash_free(face_edge_map, NULL, NULL);
+
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
+ }
+
+ BLI_stack_free(edges_loose);
+#endif /* USE_NET_ISLAND_CONNECT */
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
-
void MESH_OT_face_split_by_edges(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Weld Edges into Faces";
- ot->description = "Weld loose edges into faces (splitting them into new faces)";
- ot->idname = "MESH_OT_face_split_by_edges";
+ /* identifiers */
+ ot->name = "Weld Edges into Faces";
+ ot->description = "Weld loose edges into faces (splitting them into new faces)";
+ ot->idname = "MESH_OT_face_split_by_edges";
- /* api callbacks */
- ot->exec = edbm_face_split_by_edges_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_face_split_by_edges_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 0017044f2ff..f4979c8f2a8 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -69,199 +69,196 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
/* detect isolated holes and fill them */
#define USE_NET_ISLAND_CONNECT
-#define KMAXDIST 10 /* max mouse distance from edge before not detecting it */
+#define KMAXDIST 10 /* max mouse distance from edge before not detecting it */
/* WARNING: knife float precision is fragile:
* be careful before making changes here see: (T43229, T42864, T42459, T41164).
*/
-#define KNIFE_FLT_EPS 0.00001f
-#define KNIFE_FLT_EPS_SQUARED (KNIFE_FLT_EPS * KNIFE_FLT_EPS)
-#define KNIFE_FLT_EPSBIG 0.0005f
+#define KNIFE_FLT_EPS 0.00001f
+#define KNIFE_FLT_EPS_SQUARED (KNIFE_FLT_EPS * KNIFE_FLT_EPS)
+#define KNIFE_FLT_EPSBIG 0.0005f
-#define KNIFE_FLT_EPS_PX_VERT 0.5f
-#define KNIFE_FLT_EPS_PX_EDGE 0.05f
-#define KNIFE_FLT_EPS_PX_FACE 0.05f
+#define KNIFE_FLT_EPS_PX_VERT 0.5f
+#define KNIFE_FLT_EPS_PX_EDGE 0.05f
+#define KNIFE_FLT_EPS_PX_FACE 0.05f
typedef struct KnifeColors {
- uchar line[3];
- uchar edge[3];
- uchar curpoint[3];
- uchar curpoint_a[4];
- uchar point[3];
- uchar point_a[4];
+ uchar line[3];
+ uchar edge[3];
+ uchar curpoint[3];
+ uchar curpoint_a[4];
+ uchar point[3];
+ uchar point_a[4];
} KnifeColors;
/* knifetool operator */
typedef struct KnifeVert {
- BMVert *v; /* non-NULL if this is an original vert */
- ListBase edges;
- ListBase faces;
+ BMVert *v; /* non-NULL if this is an original vert */
+ ListBase edges;
+ ListBase faces;
- float co[3], cageco[3], sco[2]; /* sco is screen coordinates for cageco */
- bool is_face, in_space;
- bool is_cut; /* along a cut created by user input (will draw too) */
+ float co[3], cageco[3], sco[2]; /* sco is screen coordinates for cageco */
+ bool is_face, in_space;
+ bool is_cut; /* along a cut created by user input (will draw too) */
} KnifeVert;
typedef struct Ref {
- struct Ref *next, *prev;
- void *ref;
+ struct Ref *next, *prev;
+ void *ref;
} Ref;
typedef struct KnifeEdge {
- KnifeVert *v1, *v2;
- BMFace *basef; /* face to restrict face fill to */
- ListBase faces;
+ KnifeVert *v1, *v2;
+ BMFace *basef; /* face to restrict face fill to */
+ ListBase faces;
- BMEdge *e /* , *e_old */; /* non-NULL if this is an original edge */
- bool is_cut; /* along a cut created by user input (will draw too) */
+ BMEdge *e /* , *e_old */; /* non-NULL if this is an original edge */
+ bool is_cut; /* along a cut created by user input (will draw too) */
} KnifeEdge;
typedef struct KnifeLineHit {
- float hit[3], cagehit[3];
- float schit[2]; /* screen coordinates for cagehit */
- float l; /* lambda along cut line */
- float perc; /* lambda along hit line */
- float m; /* depth front-to-back */
-
- /* Exactly one of kfe, v, or f should be non-NULL,
- * saying whether cut line crosses and edge,
- * is snapped to a vert, or is in the middle of some face. */
- KnifeEdge *kfe;
- KnifeVert *v;
- BMFace *f;
+ float hit[3], cagehit[3];
+ float schit[2]; /* screen coordinates for cagehit */
+ float l; /* lambda along cut line */
+ float perc; /* lambda along hit line */
+ float m; /* depth front-to-back */
+
+ /* Exactly one of kfe, v, or f should be non-NULL,
+ * saying whether cut line crosses and edge,
+ * is snapped to a vert, or is in the middle of some face. */
+ KnifeEdge *kfe;
+ KnifeVert *v;
+ BMFace *f;
} KnifeLineHit;
typedef struct KnifePosData {
- float co[3];
- float cage[3];
-
- /* At most one of vert, edge, or bmface should be non-NULL,
- * saying whether the point is snapped to a vertex, edge, or in a face.
- * If none are set, this point is in space and is_space should be true. */
- KnifeVert *vert;
- KnifeEdge *edge;
- BMFace *bmface;
- bool is_space;
-
- float mval[2]; /* mouse screen position (may be non-integral if snapped to something) */
+ float co[3];
+ float cage[3];
+
+ /* At most one of vert, edge, or bmface should be non-NULL,
+ * saying whether the point is snapped to a vertex, edge, or in a face.
+ * If none are set, this point is in space and is_space should be true. */
+ KnifeVert *vert;
+ KnifeEdge *edge;
+ BMFace *bmface;
+ bool is_space;
+
+ float mval[2]; /* mouse screen position (may be non-integral if snapped to something) */
} KnifePosData;
/* struct for properties used while drawing */
typedef struct KnifeTool_OpData {
- ARegion *ar; /* 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 */
- //bContext *C;
-
- Scene *scene;
- Object *ob;
- BMEditMesh *em;
-
- MemArena *arena;
-
- /* reused for edge-net filling */
- struct {
- /* cleared each use */
- GSet *edge_visit;
+ ARegion *ar; /* 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 */
+ //bContext *C;
+
+ Scene *scene;
+ Object *ob;
+ BMEditMesh *em;
+
+ MemArena *arena;
+
+ /* reused for edge-net filling */
+ struct {
+ /* cleared each use */
+ GSet *edge_visit;
#ifdef USE_NET_ISLAND_CONNECT
- MemArena *arena;
+ MemArena *arena;
#endif
- } edgenet;
+ } edgenet;
- GHash *origvertmap;
- GHash *origedgemap;
- GHash *kedgefacemap;
- GHash *facetrimap;
+ GHash *origvertmap;
+ GHash *origedgemap;
+ GHash *kedgefacemap;
+ GHash *facetrimap;
- BMBVHTree *bmbvh;
+ BMBVHTree *bmbvh;
- BLI_mempool *kverts;
- BLI_mempool *kedges;
+ BLI_mempool *kverts;
+ BLI_mempool *kedges;
- float vthresh;
- float ethresh;
+ float vthresh;
+ float ethresh;
- /* used for drag-cutting */
- KnifeLineHit *linehits;
- int totlinehit;
+ /* used for drag-cutting */
+ KnifeLineHit *linehits;
+ int totlinehit;
- /* Data for mouse-position-derived data */
- KnifePosData curr; /* current point under the cursor */
- KnifePosData prev; /* last added cut (a line draws from the cursor to this) */
- KnifePosData init; /* the first point in the cut-list, used for closing the loop */
+ /* Data for mouse-position-derived data */
+ KnifePosData curr; /* current point under the cursor */
+ KnifePosData prev; /* last added cut (a line draws from the cursor to this) */
+ KnifePosData init; /* the first point in the cut-list, used for closing the loop */
- int totkedge, totkvert;
+ int totkedge, totkvert;
- BLI_mempool *refs;
+ BLI_mempool *refs;
- float projmat[4][4];
- float projmat_inv[4][4];
- /* vector along view z axis (object space, normalized) */
- float proj_zaxis[3];
+ float projmat[4][4];
+ float projmat_inv[4][4];
+ /* vector along view z axis (object space, normalized) */
+ float proj_zaxis[3];
- KnifeColors colors;
+ KnifeColors colors;
- /* run by the UI or not */
- bool is_interactive;
+ /* run by the UI or not */
+ bool is_interactive;
- /* operatpr options */
- bool cut_through; /* preference, can be modified at runtime (that feature may go) */
- bool only_select; /* set on initialization */
- bool select_result; /* set on initialization */
+ /* operatpr options */
+ bool cut_through; /* preference, can be modified at runtime (that feature may go) */
+ bool only_select; /* set on initialization */
+ bool select_result; /* set on initialization */
- bool is_ortho;
- float ortho_extent;
- float ortho_extent_center[3];
+ bool is_ortho;
+ float ortho_extent;
+ float ortho_extent_center[3];
- float clipsta, clipend;
+ float clipsta, clipend;
- enum {
- MODE_IDLE,
- MODE_DRAGGING,
- MODE_CONNECT,
- MODE_PANNING
- } mode;
- bool is_drag_hold;
+ enum { MODE_IDLE, MODE_DRAGGING, MODE_CONNECT, MODE_PANNING } mode;
+ bool is_drag_hold;
- int prevmode;
- bool snap_midpoints;
- bool ignore_edge_snapping;
- bool ignore_vert_snapping;
+ int prevmode;
+ bool snap_midpoints;
+ bool ignore_edge_snapping;
+ bool ignore_vert_snapping;
- /* use to check if we're currently dragging an angle snapped line */
- bool is_angle_snapping;
- bool angle_snapping;
- float angle;
+ /* use to check if we're currently dragging an angle snapped line */
+ bool is_angle_snapping;
+ bool angle_snapping;
+ float angle;
- const float (*cagecos)[3];
+ const float (*cagecos)[3];
} KnifeTool_OpData;
enum {
- KNF_MODAL_CANCEL = 1,
- KNF_MODAL_CONFIRM,
- KNF_MODAL_MIDPOINT_ON,
- KNF_MODAL_MIDPOINT_OFF,
- KNF_MODAL_NEW_CUT,
- KNF_MODEL_IGNORE_SNAP_ON,
- KNF_MODEL_IGNORE_SNAP_OFF,
- KNF_MODAL_ADD_CUT,
- KNF_MODAL_ANGLE_SNAP_TOGGLE,
- KNF_MODAL_CUT_THROUGH_TOGGLE,
- KNF_MODAL_PANNING,
- KNF_MODAL_ADD_CUT_CLOSED,
+ KNF_MODAL_CANCEL = 1,
+ KNF_MODAL_CONFIRM,
+ KNF_MODAL_MIDPOINT_ON,
+ KNF_MODAL_MIDPOINT_OFF,
+ KNF_MODAL_NEW_CUT,
+ KNF_MODEL_IGNORE_SNAP_ON,
+ KNF_MODEL_IGNORE_SNAP_OFF,
+ KNF_MODAL_ADD_CUT,
+ KNF_MODAL_ANGLE_SNAP_TOGGLE,
+ KNF_MODAL_CUT_THROUGH_TOGGLE,
+ KNF_MODAL_PANNING,
+ KNF_MODAL_ADD_CUT_CLOSED,
};
-
static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd, BMFace *f);
-static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2], const float ofs,
- float r_origin[3], float r_dest[3]);
+static void knife_input_ray_segment(KnifeTool_OpData *kcd,
+ const float mval[2],
+ const float ofs,
+ float r_origin[3],
+ float r_dest[3]);
static bool knife_verts_edge_in_face(KnifeVert *v1, KnifeVert *v2, BMFace *f);
@@ -271,205 +268,217 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event);
static void knife_update_header(bContext *C, wmOperator *op, KnifeTool_OpData *kcd)
{
- char header[UI_MAX_DRAW_STR];
- char buf[UI_MAX_DRAW_STR];
+ char header[UI_MAX_DRAW_STR];
+ char buf[UI_MAX_DRAW_STR];
- char *p = buf;
- int available_len = sizeof(buf);
+ char *p = buf;
+ int available_len = sizeof(buf);
#define WM_MODALKEY(_id) \
- WM_modalkeymap_operator_items_to_string_buf(op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p)
-
- BLI_snprintf(header, sizeof(header), IFACE_("%s: confirm, %s: cancel, "
- "%s: start/define cut, %s: close cut, %s: new cut, "
- "%s: midpoint snap (%s), %s: ignore snap (%s), "
- "%s: angle constraint (%s), %s: cut through (%s), "
- "%s: panning"),
- WM_MODALKEY(KNF_MODAL_CONFIRM), WM_MODALKEY(KNF_MODAL_CANCEL),
- WM_MODALKEY(KNF_MODAL_ADD_CUT), WM_MODALKEY(KNF_MODAL_ADD_CUT_CLOSED), WM_MODALKEY(KNF_MODAL_NEW_CUT),
- WM_MODALKEY(KNF_MODAL_MIDPOINT_ON), WM_bool_as_string(kcd->snap_midpoints),
- WM_MODALKEY(KNF_MODEL_IGNORE_SNAP_ON), WM_bool_as_string(kcd->ignore_edge_snapping),
- WM_MODALKEY(KNF_MODAL_ANGLE_SNAP_TOGGLE), WM_bool_as_string(kcd->angle_snapping),
- WM_MODALKEY(KNF_MODAL_CUT_THROUGH_TOGGLE), WM_bool_as_string(kcd->cut_through),
- WM_MODALKEY(KNF_MODAL_PANNING));
+ WM_modalkeymap_operator_items_to_string_buf( \
+ op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p)
+
+ BLI_snprintf(header,
+ sizeof(header),
+ IFACE_("%s: confirm, %s: cancel, "
+ "%s: start/define cut, %s: close cut, %s: new cut, "
+ "%s: midpoint snap (%s), %s: ignore snap (%s), "
+ "%s: angle constraint (%s), %s: cut through (%s), "
+ "%s: panning"),
+ WM_MODALKEY(KNF_MODAL_CONFIRM),
+ WM_MODALKEY(KNF_MODAL_CANCEL),
+ WM_MODALKEY(KNF_MODAL_ADD_CUT),
+ WM_MODALKEY(KNF_MODAL_ADD_CUT_CLOSED),
+ WM_MODALKEY(KNF_MODAL_NEW_CUT),
+ WM_MODALKEY(KNF_MODAL_MIDPOINT_ON),
+ WM_bool_as_string(kcd->snap_midpoints),
+ WM_MODALKEY(KNF_MODEL_IGNORE_SNAP_ON),
+ WM_bool_as_string(kcd->ignore_edge_snapping),
+ WM_MODALKEY(KNF_MODAL_ANGLE_SNAP_TOGGLE),
+ WM_bool_as_string(kcd->angle_snapping),
+ WM_MODALKEY(KNF_MODAL_CUT_THROUGH_TOGGLE),
+ WM_bool_as_string(kcd->cut_through),
+ WM_MODALKEY(KNF_MODAL_PANNING));
#undef WM_MODALKEY
- ED_workspace_status_text(C, header);
+ ED_workspace_status_text(C, header);
}
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->ar, co, sco, (float(*)[4])kcd->projmat);
}
/* use when lambda is in screen-space */
-static void knife_interp_v3_v3v3(
- const KnifeTool_OpData *kcd,
- float r_co[3], const float v1[3], const float v2[3], float lambda_ss)
+static void knife_interp_v3_v3v3(const KnifeTool_OpData *kcd,
+ float r_co[3],
+ const float v1[3],
+ const float v2[3],
+ float lambda_ss)
{
- if (kcd->is_ortho) {
- interp_v3_v3v3(r_co, v1, v2, lambda_ss);
- }
- else {
- /* transform into screen-space, interp, then transform back */
- float v1_ss[3], v2_ss[3];
+ if (kcd->is_ortho) {
+ interp_v3_v3v3(r_co, v1, v2, lambda_ss);
+ }
+ else {
+ /* transform into screen-space, interp, then transform back */
+ float v1_ss[3], v2_ss[3];
- mul_v3_project_m4_v3(v1_ss, (float (*)[4])kcd->projmat, v1);
- mul_v3_project_m4_v3(v2_ss, (float (*)[4])kcd->projmat, v2);
+ mul_v3_project_m4_v3(v1_ss, (float(*)[4])kcd->projmat, v1);
+ mul_v3_project_m4_v3(v2_ss, (float(*)[4])kcd->projmat, v2);
- interp_v3_v3v3(r_co, v1_ss, v2_ss, lambda_ss);
+ interp_v3_v3v3(r_co, v1_ss, v2_ss, lambda_ss);
- mul_project_m4_v3((float (*)[4])kcd->projmat_inv, r_co);
- }
+ mul_project_m4_v3((float(*)[4])kcd->projmat_inv, r_co);
+ }
}
static void knife_pos_data_clear(KnifePosData *kpd)
{
- zero_v3(kpd->co);
- zero_v3(kpd->cage);
- kpd->vert = NULL;
- kpd->edge = NULL;
- kpd->bmface = NULL;
- zero_v2(kpd->mval);
+ zero_v3(kpd->co);
+ zero_v3(kpd->cage);
+ kpd->vert = NULL;
+ kpd->edge = NULL;
+ kpd->bmface = NULL;
+ zero_v2(kpd->mval);
}
static ListBase *knife_empty_list(KnifeTool_OpData *kcd)
{
- ListBase *lst;
+ ListBase *lst;
- lst = BLI_memarena_alloc(kcd->arena, sizeof(ListBase));
- BLI_listbase_clear(lst);
- return lst;
+ lst = BLI_memarena_alloc(kcd->arena, sizeof(ListBase));
+ BLI_listbase_clear(lst);
+ return lst;
}
static void knife_append_list(KnifeTool_OpData *kcd, ListBase *lst, void *elem)
{
- Ref *ref;
+ Ref *ref;
- ref = BLI_mempool_calloc(kcd->refs);
- ref->ref = elem;
- BLI_addtail(lst, ref);
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = elem;
+ BLI_addtail(lst, ref);
}
static Ref *find_ref(ListBase *lb, void *ref)
{
- Ref *ref1;
+ Ref *ref1;
- for (ref1 = lb->first; ref1; ref1 = ref1->next) {
- if (ref1->ref == ref)
- return ref1;
- }
+ for (ref1 = lb->first; ref1; ref1 = ref1->next) {
+ if (ref1->ref == ref)
+ return ref1;
+ }
- return NULL;
+ return NULL;
}
static void knife_append_list_no_dup(KnifeTool_OpData *kcd, ListBase *lst, void *elem)
{
- if (!find_ref(lst, elem))
- knife_append_list(kcd, lst, elem);
+ if (!find_ref(lst, elem))
+ knife_append_list(kcd, lst, elem);
}
static KnifeEdge *new_knife_edge(KnifeTool_OpData *kcd)
{
- kcd->totkedge++;
- return BLI_mempool_calloc(kcd->kedges);
+ kcd->totkedge++;
+ return BLI_mempool_calloc(kcd->kedges);
}
static void knife_add_to_vert_edges(KnifeTool_OpData *kcd, KnifeEdge *kfe)
{
- knife_append_list(kcd, &kfe->v1->edges, kfe);
- knife_append_list(kcd, &kfe->v2->edges, kfe);
+ knife_append_list(kcd, &kfe->v1->edges, kfe);
+ knife_append_list(kcd, &kfe->v2->edges, kfe);
}
/* Add faces of an edge to a KnifeVert's faces list. No checks for dups. */
static void knife_add_edge_faces_to_vert(KnifeTool_OpData *kcd, KnifeVert *kfv, BMEdge *e)
{
- BMIter bmiter;
- BMFace *f;
+ BMIter bmiter;
+ BMFace *f;
- BM_ITER_ELEM (f, &bmiter, e, BM_FACES_OF_EDGE) {
- knife_append_list(kcd, &kfv->faces, f);
- }
+ BM_ITER_ELEM (f, &bmiter, e, BM_FACES_OF_EDGE) {
+ knife_append_list(kcd, &kfv->faces, f);
+ }
}
/* Find a face in common in the two faces lists.
* If more than one, return the first; if none, return NULL */
static BMFace *knife_find_common_face(ListBase *faces1, ListBase *faces2)
{
- Ref *ref1, *ref2;
+ Ref *ref1, *ref2;
- for (ref1 = faces1->first; ref1; ref1 = ref1->next) {
- for (ref2 = faces2->first; ref2; ref2 = ref2->next) {
- if (ref1->ref == ref2->ref)
- return (BMFace *)(ref1->ref);
- }
- }
- return NULL;
+ for (ref1 = faces1->first; ref1; ref1 = ref1->next) {
+ for (ref2 = faces2->first; ref2; ref2 = ref2->next) {
+ if (ref1->ref == ref2->ref)
+ return (BMFace *)(ref1->ref);
+ }
+ }
+ return NULL;
}
static KnifeVert *new_knife_vert(KnifeTool_OpData *kcd, const float co[3], const float cageco[3])
{
- KnifeVert *kfv = BLI_mempool_calloc(kcd->kverts);
+ KnifeVert *kfv = BLI_mempool_calloc(kcd->kverts);
- kcd->totkvert++;
+ kcd->totkvert++;
- copy_v3_v3(kfv->co, co);
- copy_v3_v3(kfv->cageco, cageco);
+ copy_v3_v3(kfv->co, co);
+ copy_v3_v3(kfv->cageco, cageco);
- knife_project_v2(kcd, kfv->cageco, kfv->sco);
+ knife_project_v2(kcd, kfv->cageco, kfv->sco);
- return kfv;
+ return kfv;
}
/* get a KnifeVert wrapper for an existing BMVert */
static KnifeVert *get_bm_knife_vert(KnifeTool_OpData *kcd, BMVert *v)
{
- KnifeVert *kfv = BLI_ghash_lookup(kcd->origvertmap, v);
- const float *cageco;
+ KnifeVert *kfv = BLI_ghash_lookup(kcd->origvertmap, v);
+ const float *cageco;
- if (!kfv) {
- BMIter bmiter;
- BMFace *f;
+ if (!kfv) {
+ BMIter bmiter;
+ BMFace *f;
- if (BM_elem_index_get(v) >= 0)
- cageco = kcd->cagecos[BM_elem_index_get(v)];
- else
- cageco = v->co;
- kfv = new_knife_vert(kcd, v->co, cageco);
- kfv->v = v;
- BLI_ghash_insert(kcd->origvertmap, v, kfv);
- BM_ITER_ELEM (f, &bmiter, v, BM_FACES_OF_VERT) {
- knife_append_list(kcd, &kfv->faces, f);
- }
- }
+ if (BM_elem_index_get(v) >= 0)
+ cageco = kcd->cagecos[BM_elem_index_get(v)];
+ else
+ cageco = v->co;
+ kfv = new_knife_vert(kcd, v->co, cageco);
+ kfv->v = v;
+ BLI_ghash_insert(kcd->origvertmap, v, kfv);
+ BM_ITER_ELEM (f, &bmiter, v, BM_FACES_OF_VERT) {
+ knife_append_list(kcd, &kfv->faces, f);
+ }
+ }
- return kfv;
+ return kfv;
}
/* get a KnifeEdge wrapper for an existing BMEdge */
static KnifeEdge *get_bm_knife_edge(KnifeTool_OpData *kcd, BMEdge *e)
{
- KnifeEdge *kfe = BLI_ghash_lookup(kcd->origedgemap, e);
- if (!kfe) {
- BMIter bmiter;
- BMFace *f;
+ KnifeEdge *kfe = BLI_ghash_lookup(kcd->origedgemap, e);
+ if (!kfe) {
+ BMIter bmiter;
+ BMFace *f;
- kfe = new_knife_edge(kcd);
- kfe->e = e;
- kfe->v1 = get_bm_knife_vert(kcd, e->v1);
- kfe->v2 = get_bm_knife_vert(kcd, e->v2);
+ kfe = new_knife_edge(kcd);
+ kfe->e = e;
+ kfe->v1 = get_bm_knife_vert(kcd, e->v1);
+ kfe->v2 = get_bm_knife_vert(kcd, e->v2);
- knife_add_to_vert_edges(kcd, kfe);
+ knife_add_to_vert_edges(kcd, kfe);
- BLI_ghash_insert(kcd->origedgemap, e, kfe);
+ BLI_ghash_insert(kcd->origedgemap, e, kfe);
- BM_ITER_ELEM (f, &bmiter, e, BM_FACES_OF_EDGE) {
- knife_append_list(kcd, &kfe->faces, f);
- }
- }
+ BM_ITER_ELEM (f, &bmiter, e, BM_FACES_OF_EDGE) {
+ knife_append_list(kcd, &kfe->faces, f);
+ }
+ }
- return kfe;
+ return kfe;
}
/* Record the index in kcd->em->looptris of first looptri triple for a given face,
@@ -482,140 +491,141 @@ static KnifeEdge *get_bm_knife_edge(KnifeTool_OpData *kcd, BMEdge *e)
*/
static void set_lowest_face_tri(KnifeTool_OpData *kcd, BMFace *f, int index)
{
- int i;
+ int i;
- if (BLI_ghash_lookup(kcd->facetrimap, f))
- return;
+ if (BLI_ghash_lookup(kcd->facetrimap, f))
+ return;
- BLI_assert(index >= 0 && index < kcd->em->tottri);
- BLI_assert(kcd->em->looptris[index][0]->f == f);
- for (i = index - 1; i >= 0; i--) {
- if (kcd->em->looptris[i][0]->f != f) {
- i++;
- break;
- }
- }
- if (i == -1)
- i++;
+ BLI_assert(index >= 0 && index < kcd->em->tottri);
+ BLI_assert(kcd->em->looptris[index][0]->f == f);
+ for (i = index - 1; i >= 0; i--) {
+ if (kcd->em->looptris[i][0]->f != f) {
+ i++;
+ break;
+ }
+ }
+ if (i == -1)
+ i++;
- BLI_ghash_insert(kcd->facetrimap, f, POINTER_FROM_INT(i + 1));
+ BLI_ghash_insert(kcd->facetrimap, f, POINTER_FROM_INT(i + 1));
}
/* This should only be called for faces that have had a lowest face tri set by previous function */
static int get_lowest_face_tri(KnifeTool_OpData *kcd, BMFace *f)
{
- int ans;
+ int ans;
- ans = POINTER_AS_INT(BLI_ghash_lookup(kcd->facetrimap, f));
- BLI_assert(ans != 0);
- return ans - 1;
+ ans = POINTER_AS_INT(BLI_ghash_lookup(kcd->facetrimap, f));
+ BLI_assert(ans != 0);
+ return ans - 1;
}
/* User has just clicked for first time or first time after a restart (E key).
* Copy the current position data into prev. */
static void knife_start_cut(KnifeTool_OpData *kcd)
{
- kcd->prev = kcd->curr;
- kcd->curr.is_space = 0; /*TODO: why do we do this? */
+ kcd->prev = kcd->curr;
+ kcd->curr.is_space = 0; /*TODO: why do we do this? */
- if (kcd->prev.vert == NULL && kcd->prev.edge == NULL) {
- float origin[3], origin_ofs[3];
- float ofs_local[3];
+ if (kcd->prev.vert == NULL && kcd->prev.edge == NULL) {
+ float origin[3], origin_ofs[3];
+ float ofs_local[3];
- negate_v3_v3(ofs_local, kcd->vc.rv3d->ofs);
- invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
- mul_m4_v3(kcd->ob->imat, ofs_local);
+ negate_v3_v3(ofs_local, kcd->vc.rv3d->ofs);
+ invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
+ mul_m4_v3(kcd->ob->imat, ofs_local);
- knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
+ knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
- if (!isect_line_plane_v3(kcd->prev.cage, origin, origin_ofs, ofs_local, kcd->proj_zaxis)) {
- zero_v3(kcd->prev.cage);
- }
+ if (!isect_line_plane_v3(kcd->prev.cage, origin, origin_ofs, ofs_local, kcd->proj_zaxis)) {
+ zero_v3(kcd->prev.cage);
+ }
- copy_v3_v3(kcd->prev.co, kcd->prev.cage); /*TODO: do we need this? */
- copy_v3_v3(kcd->curr.cage, kcd->prev.cage);
- copy_v3_v3(kcd->curr.co, kcd->prev.co);
- }
+ copy_v3_v3(kcd->prev.co, kcd->prev.cage); /*TODO: do we need this? */
+ copy_v3_v3(kcd->curr.cage, kcd->prev.cage);
+ copy_v3_v3(kcd->curr.co, kcd->prev.co);
+ }
}
static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd, BMFace *f)
{
- ListBase *lst = BLI_ghash_lookup(kcd->kedgefacemap, f);
+ ListBase *lst = BLI_ghash_lookup(kcd->kedgefacemap, f);
- if (!lst) {
- BMIter bmiter;
- BMEdge *e;
+ if (!lst) {
+ BMIter bmiter;
+ BMEdge *e;
- lst = knife_empty_list(kcd);
+ lst = knife_empty_list(kcd);
- BM_ITER_ELEM (e, &bmiter, f, BM_EDGES_OF_FACE) {
- knife_append_list(kcd, lst, get_bm_knife_edge(kcd, e));
- }
+ BM_ITER_ELEM (e, &bmiter, f, BM_EDGES_OF_FACE) {
+ knife_append_list(kcd, lst, get_bm_knife_edge(kcd, e));
+ }
- BLI_ghash_insert(kcd->kedgefacemap, f, lst);
- }
+ BLI_ghash_insert(kcd->kedgefacemap, f, lst);
+ }
- return lst;
+ return lst;
}
static void knife_edge_append_face(KnifeTool_OpData *kcd, KnifeEdge *kfe, BMFace *f)
{
- knife_append_list(kcd, knife_get_face_kedges(kcd, f), kfe);
- knife_append_list(kcd, &kfe->faces, f);
+ knife_append_list(kcd, knife_get_face_kedges(kcd, f), kfe);
+ knife_append_list(kcd, &kfe->faces, f);
}
-static KnifeVert *knife_split_edge(
- KnifeTool_OpData *kcd, KnifeEdge *kfe,
- const float co[3], const float cageco[3],
- KnifeEdge **r_kfe)
+static KnifeVert *knife_split_edge(KnifeTool_OpData *kcd,
+ KnifeEdge *kfe,
+ const float co[3],
+ const float cageco[3],
+ KnifeEdge **r_kfe)
{
- KnifeEdge *newkfe = new_knife_edge(kcd);
- Ref *ref;
- BMFace *f;
+ KnifeEdge *newkfe = new_knife_edge(kcd);
+ Ref *ref;
+ BMFace *f;
- newkfe->v1 = kfe->v1;
- newkfe->v2 = new_knife_vert(kcd, co, cageco);
- newkfe->v2->is_cut = true;
- if (kfe->e) {
- knife_add_edge_faces_to_vert(kcd, newkfe->v2, kfe->e);
- }
- else {
- /* kfe cuts across an existing face.
- * If v1 and v2 are in multiple faces together (e.g., if they
- * are in doubled polys) then this arbitrarily chooses one of them */
- f = knife_find_common_face(&kfe->v1->faces, &kfe->v2->faces);
- if (f)
- knife_append_list(kcd, &newkfe->v2->faces, f);
- }
- newkfe->basef = kfe->basef;
+ newkfe->v1 = kfe->v1;
+ newkfe->v2 = new_knife_vert(kcd, co, cageco);
+ newkfe->v2->is_cut = true;
+ if (kfe->e) {
+ knife_add_edge_faces_to_vert(kcd, newkfe->v2, kfe->e);
+ }
+ else {
+ /* kfe cuts across an existing face.
+ * If v1 and v2 are in multiple faces together (e.g., if they
+ * are in doubled polys) then this arbitrarily chooses one of them */
+ f = knife_find_common_face(&kfe->v1->faces, &kfe->v2->faces);
+ if (f)
+ knife_append_list(kcd, &newkfe->v2->faces, f);
+ }
+ newkfe->basef = kfe->basef;
- ref = find_ref(&kfe->v1->edges, kfe);
- BLI_remlink(&kfe->v1->edges, ref);
+ ref = find_ref(&kfe->v1->edges, kfe);
+ BLI_remlink(&kfe->v1->edges, ref);
- kfe->v1 = newkfe->v2;
- BLI_addtail(&kfe->v1->edges, ref);
+ kfe->v1 = newkfe->v2;
+ BLI_addtail(&kfe->v1->edges, ref);
- for (ref = kfe->faces.first; ref; ref = ref->next)
- knife_edge_append_face(kcd, newkfe, ref->ref);
+ for (ref = kfe->faces.first; ref; ref = ref->next)
+ knife_edge_append_face(kcd, newkfe, ref->ref);
- knife_add_to_vert_edges(kcd, newkfe);
+ knife_add_to_vert_edges(kcd, newkfe);
- newkfe->is_cut = kfe->is_cut;
- newkfe->e = kfe->e;
+ newkfe->is_cut = kfe->is_cut;
+ newkfe->e = kfe->e;
- *r_kfe = newkfe;
+ *r_kfe = newkfe;
- return newkfe->v2;
+ return newkfe->v2;
}
static void linehit_to_knifepos(KnifePosData *kpos, KnifeLineHit *lh)
{
- kpos->bmface = lh->f;
- kpos->vert = lh->v;
- kpos->edge = lh->kfe;
- copy_v3_v3(kpos->cage, lh->cagehit);
- copy_v3_v3(kpos->co, lh->hit);
- copy_v2_v2(kpos->mval, lh->schit);
+ kpos->bmface = lh->f;
+ kpos->vert = lh->v;
+ kpos->edge = lh->kfe;
+ copy_v3_v3(kpos->cage, lh->cagehit);
+ copy_v3_v3(kpos->co, lh->hit);
+ copy_v2_v2(kpos->mval, lh->schit);
}
/* primary key: lambda along cut
@@ -624,20 +634,27 @@ static void linehit_to_knifepos(KnifePosData *kpos, KnifeLineHit *lh)
*/
static int linehit_compare(const void *vlh1, const void *vlh2)
{
- const KnifeLineHit *lh1 = vlh1;
- const KnifeLineHit *lh2 = vlh2;
-
- if (lh1->l < lh2->l) return -1;
- else if (lh1->l > lh2->l) return 1;
- else {
- if (lh1->m < lh2->m) return -1;
- else if (lh1->m > lh2->m) return 1;
- else {
- if (lh1->v < lh2->v) return -1;
- else if (lh1->v > lh2->v) return 1;
- else return 0;
- }
- }
+ const KnifeLineHit *lh1 = vlh1;
+ const KnifeLineHit *lh2 = vlh2;
+
+ if (lh1->l < lh2->l)
+ return -1;
+ else if (lh1->l > lh2->l)
+ return 1;
+ else {
+ if (lh1->m < lh2->m)
+ return -1;
+ else if (lh1->m > lh2->m)
+ return 1;
+ else {
+ if (lh1->v < lh2->v)
+ return -1;
+ else if (lh1->v > lh2->v)
+ return 1;
+ else
+ return 0;
+ }
+ }
}
/*
@@ -647,202 +664,195 @@ static int linehit_compare(const void *vlh1, const void *vlh2)
*/
static void prepare_linehits_for_cut(KnifeTool_OpData *kcd)
{
- KnifeLineHit *linehits, *lhi, *lhj;
- int i, j, n;
- bool is_double = false;
-
- n = kcd->totlinehit;
- linehits = kcd->linehits;
- if (n == 0)
- return;
-
- qsort(linehits, n, sizeof(KnifeLineHit), linehit_compare);
-
- /* Remove any edge hits that are preceded or followed
- * by a vertex hit that is very near. Mark such edge hits using
- * l == -1 and then do another pass to actually remove.
- * Also remove all but one of a series of vertex hits for the same vertex. */
- for (i = 0; i < n; i++) {
- lhi = &linehits[i];
- if (lhi->v) {
- for (j = i - 1; j >= 0; j--) {
- lhj = &linehits[j];
- if (!lhj->kfe ||
- fabsf(lhi->l - lhj->l) > KNIFE_FLT_EPSBIG ||
- fabsf(lhi->m - lhj->m) > KNIFE_FLT_EPSBIG)
- {
- break;
- }
-
- if (lhi->kfe == lhj->kfe) {
- lhj->l = -1.0f;
- is_double = true;
- }
- }
- for (j = i + 1; j < n; j++) {
- lhj = &linehits[j];
- if (fabsf(lhi->l - lhj->l) > KNIFE_FLT_EPSBIG ||
- fabsf(lhi->m - lhj->m) > KNIFE_FLT_EPSBIG)
- {
- break;
- }
- if ((lhj->kfe && (lhi->kfe == lhj->kfe)) ||
- (lhi->v == lhj->v))
- {
- lhj->l = -1.0f;
- is_double = true;
- }
- }
- }
- }
-
- if (is_double) {
- /* delete-in-place loop: copying from pos j to pos i+1 */
- i = 0;
- j = 1;
- while (j < n) {
- lhi = &linehits[i];
- lhj = &linehits[j];
- if (lhj->l == -1.0f) {
- j++; /* skip copying this one */
- }
- else {
- /* copy unless a no-op */
- if (lhi->l == -1.0f) {
- /* could happen if linehits[0] is being deleted */
- memcpy(&linehits[i], &linehits[j], sizeof(KnifeLineHit));
- }
- else {
- if (i + 1 != j)
- memcpy(&linehits[i + 1], &linehits[j], sizeof(KnifeLineHit));
- i++;
- }
- j++;
- }
- }
- kcd->totlinehit = i + 1;
- }
+ KnifeLineHit *linehits, *lhi, *lhj;
+ int i, j, n;
+ bool is_double = false;
+
+ n = kcd->totlinehit;
+ linehits = kcd->linehits;
+ if (n == 0)
+ return;
+
+ qsort(linehits, n, sizeof(KnifeLineHit), linehit_compare);
+
+ /* Remove any edge hits that are preceded or followed
+ * by a vertex hit that is very near. Mark such edge hits using
+ * l == -1 and then do another pass to actually remove.
+ * Also remove all but one of a series of vertex hits for the same vertex. */
+ for (i = 0; i < n; i++) {
+ lhi = &linehits[i];
+ if (lhi->v) {
+ for (j = i - 1; j >= 0; j--) {
+ lhj = &linehits[j];
+ if (!lhj->kfe || fabsf(lhi->l - lhj->l) > KNIFE_FLT_EPSBIG ||
+ fabsf(lhi->m - lhj->m) > KNIFE_FLT_EPSBIG) {
+ break;
+ }
+
+ if (lhi->kfe == lhj->kfe) {
+ lhj->l = -1.0f;
+ is_double = true;
+ }
+ }
+ for (j = i + 1; j < n; j++) {
+ lhj = &linehits[j];
+ if (fabsf(lhi->l - lhj->l) > KNIFE_FLT_EPSBIG ||
+ fabsf(lhi->m - lhj->m) > KNIFE_FLT_EPSBIG) {
+ break;
+ }
+ if ((lhj->kfe && (lhi->kfe == lhj->kfe)) || (lhi->v == lhj->v)) {
+ lhj->l = -1.0f;
+ is_double = true;
+ }
+ }
+ }
+ }
+
+ if (is_double) {
+ /* delete-in-place loop: copying from pos j to pos i+1 */
+ i = 0;
+ j = 1;
+ while (j < n) {
+ lhi = &linehits[i];
+ lhj = &linehits[j];
+ if (lhj->l == -1.0f) {
+ j++; /* skip copying this one */
+ }
+ else {
+ /* copy unless a no-op */
+ if (lhi->l == -1.0f) {
+ /* could happen if linehits[0] is being deleted */
+ memcpy(&linehits[i], &linehits[j], sizeof(KnifeLineHit));
+ }
+ else {
+ if (i + 1 != j)
+ memcpy(&linehits[i + 1], &linehits[j], sizeof(KnifeLineHit));
+ i++;
+ }
+ j++;
+ }
+ }
+ kcd->totlinehit = i + 1;
+ }
}
/* Add hit to list of hits in facehits[f], where facehits is a map, if not already there */
-static void add_hit_to_facehits(KnifeTool_OpData *kcd, GHash *facehits, BMFace *f, KnifeLineHit *hit)
+static void add_hit_to_facehits(KnifeTool_OpData *kcd,
+ GHash *facehits,
+ BMFace *f,
+ KnifeLineHit *hit)
{
- ListBase *lst = BLI_ghash_lookup(facehits, f);
+ ListBase *lst = BLI_ghash_lookup(facehits, f);
- if (!lst) {
- lst = knife_empty_list(kcd);
- BLI_ghash_insert(facehits, f, lst);
- }
- knife_append_list_no_dup(kcd, lst, hit);
+ if (!lst) {
+ lst = knife_empty_list(kcd);
+ BLI_ghash_insert(facehits, f, lst);
+ }
+ knife_append_list_no_dup(kcd, lst, hit);
}
/**
* special purpose function, if the linehit is connected to a real edge/vert
* return true if \a co is outside the face.
*/
-static bool knife_add_single_cut__is_linehit_outside_face(BMFace *f, const KnifeLineHit *lh, const float co[3])
-{
-
- if (lh->v && lh->v->v) {
- BMLoop *l; /* side-of-loop */
- if ((l = BM_face_vert_share_loop(f, lh->v->v)) &&
- (BM_loop_point_side_of_loop_test(l, co) < 0.0f))
- {
- return true;
- }
- }
- else if ((lh->kfe && lh->kfe->e)) {
- BMLoop *l; /* side-of-edge */
- if ((l = BM_face_edge_share_loop(f, lh->kfe->e)) &&
- (BM_loop_point_side_of_edge_test(l, co) < 0.0f))
- {
- return true;
- }
- }
-
- return false;
-}
-
-
-static void knife_add_single_cut(KnifeTool_OpData *kcd, KnifeLineHit *lh1, KnifeLineHit *lh2, BMFace *f)
-{
- KnifeEdge *kfe, *kfe2;
- BMEdge *e_base;
-
- if ((lh1->v && lh1->v == lh2->v) ||
- (lh1->kfe && lh1->kfe == lh2->kfe))
- {
- return;
- }
-
- /* if the cut is on an edge, just tag that its a cut and return */
- if ((lh1->v && lh2->v) &&
- (lh1->v->v && lh2->v && lh2->v->v) &&
- (e_base = BM_edge_exists(lh1->v->v, lh2->v->v)))
- {
- kfe = get_bm_knife_edge(kcd, e_base);
- kfe->is_cut = true;
- kfe->e = e_base;
- return;
- }
- else {
- if (knife_add_single_cut__is_linehit_outside_face(f, lh1, lh2->hit) ||
- knife_add_single_cut__is_linehit_outside_face(f, lh2, lh1->hit))
- {
- return;
- }
- }
-
-
- /* Check if edge actually lies within face (might not, if this face is concave) */
- if ((lh1->v && !lh1->kfe) && (lh2->v && !lh2->kfe)) {
- if (!knife_verts_edge_in_face(lh1->v, lh2->v, f)) {
- return;
- }
- }
-
- kfe = new_knife_edge(kcd);
- kfe->is_cut = true;
- kfe->basef = f;
-
- if (lh1->v) {
- kfe->v1 = lh1->v;
- }
- else if (lh1->kfe) {
- kfe->v1 = knife_split_edge(kcd, lh1->kfe, lh1->hit, lh1->cagehit, &kfe2);
- lh1->v = kfe->v1; /* record the KnifeVert for this hit */
- }
- else {
- BLI_assert(lh1->f);
- kfe->v1 = new_knife_vert(kcd, lh1->hit, lh1->cagehit);
- kfe->v1->is_cut = true;
- kfe->v1->is_face = true;
- knife_append_list(kcd, &kfe->v1->faces, lh1->f);
- lh1->v = kfe->v1; /* record the KnifeVert for this hit */
- }
-
- if (lh2->v) {
- kfe->v2 = lh2->v;
- }
- else if (lh2->kfe) {
- kfe->v2 = knife_split_edge(kcd, lh2->kfe, lh2->hit, lh2->cagehit, &kfe2);
- lh2->v = kfe->v2; /* future uses of lh2 won't split again */
- }
- else {
- BLI_assert(lh2->f);
- kfe->v2 = new_knife_vert(kcd, lh2->hit, lh2->cagehit);
- kfe->v2->is_cut = true;
- kfe->v2->is_face = true;
- knife_append_list(kcd, &kfe->v2->faces, lh2->f);
- lh2->v = kfe->v2; /* record the KnifeVert for this hit */
- }
-
- knife_add_to_vert_edges(kcd, kfe);
-
- /* TODO: check if this is ever needed */
- if (kfe->basef && !find_ref(&kfe->faces, kfe->basef))
- knife_edge_append_face(kcd, kfe, kfe->basef);
-
+static bool knife_add_single_cut__is_linehit_outside_face(BMFace *f,
+ const KnifeLineHit *lh,
+ const float co[3])
+{
+
+ if (lh->v && lh->v->v) {
+ BMLoop *l; /* side-of-loop */
+ if ((l = BM_face_vert_share_loop(f, lh->v->v)) &&
+ (BM_loop_point_side_of_loop_test(l, co) < 0.0f)) {
+ return true;
+ }
+ }
+ else if ((lh->kfe && lh->kfe->e)) {
+ BMLoop *l; /* side-of-edge */
+ if ((l = BM_face_edge_share_loop(f, lh->kfe->e)) &&
+ (BM_loop_point_side_of_edge_test(l, co) < 0.0f)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void knife_add_single_cut(KnifeTool_OpData *kcd,
+ KnifeLineHit *lh1,
+ KnifeLineHit *lh2,
+ BMFace *f)
+{
+ KnifeEdge *kfe, *kfe2;
+ BMEdge *e_base;
+
+ if ((lh1->v && lh1->v == lh2->v) || (lh1->kfe && lh1->kfe == lh2->kfe)) {
+ return;
+ }
+
+ /* if the cut is on an edge, just tag that its a cut and return */
+ if ((lh1->v && lh2->v) && (lh1->v->v && lh2->v && lh2->v->v) &&
+ (e_base = BM_edge_exists(lh1->v->v, lh2->v->v))) {
+ kfe = get_bm_knife_edge(kcd, e_base);
+ kfe->is_cut = true;
+ kfe->e = e_base;
+ return;
+ }
+ else {
+ if (knife_add_single_cut__is_linehit_outside_face(f, lh1, lh2->hit) ||
+ knife_add_single_cut__is_linehit_outside_face(f, lh2, lh1->hit)) {
+ return;
+ }
+ }
+
+ /* Check if edge actually lies within face (might not, if this face is concave) */
+ if ((lh1->v && !lh1->kfe) && (lh2->v && !lh2->kfe)) {
+ if (!knife_verts_edge_in_face(lh1->v, lh2->v, f)) {
+ return;
+ }
+ }
+
+ kfe = new_knife_edge(kcd);
+ kfe->is_cut = true;
+ kfe->basef = f;
+
+ if (lh1->v) {
+ kfe->v1 = lh1->v;
+ }
+ else if (lh1->kfe) {
+ kfe->v1 = knife_split_edge(kcd, lh1->kfe, lh1->hit, lh1->cagehit, &kfe2);
+ lh1->v = kfe->v1; /* record the KnifeVert for this hit */
+ }
+ else {
+ BLI_assert(lh1->f);
+ kfe->v1 = new_knife_vert(kcd, lh1->hit, lh1->cagehit);
+ kfe->v1->is_cut = true;
+ kfe->v1->is_face = true;
+ knife_append_list(kcd, &kfe->v1->faces, lh1->f);
+ lh1->v = kfe->v1; /* record the KnifeVert for this hit */
+ }
+
+ if (lh2->v) {
+ kfe->v2 = lh2->v;
+ }
+ else if (lh2->kfe) {
+ kfe->v2 = knife_split_edge(kcd, lh2->kfe, lh2->hit, lh2->cagehit, &kfe2);
+ lh2->v = kfe->v2; /* future uses of lh2 won't split again */
+ }
+ else {
+ BLI_assert(lh2->f);
+ kfe->v2 = new_knife_vert(kcd, lh2->hit, lh2->cagehit);
+ kfe->v2->is_cut = true;
+ kfe->v2->is_face = true;
+ knife_append_list(kcd, &kfe->v2->faces, lh2->f);
+ lh2->v = kfe->v2; /* record the KnifeVert for this hit */
+ }
+
+ knife_add_to_vert_edges(kcd, kfe);
+
+ /* TODO: check if this is ever needed */
+ if (kfe->basef && !find_ref(&kfe->faces, kfe->basef))
+ knife_edge_append_face(kcd, kfe, kfe->basef);
}
/* Given a list of KnifeLineHits for one face, sorted by l
@@ -851,14 +861,14 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd, KnifeLineHit *lh1, Knife
*/
static void knife_cut_face(KnifeTool_OpData *kcd, BMFace *f, ListBase *hits)
{
- Ref *r;
+ Ref *r;
- if (BLI_listbase_count_at_most(hits, 2) != 2)
- return;
+ if (BLI_listbase_count_at_most(hits, 2) != 2)
+ return;
- for (r = hits->first; r->next; r = r->next) {
- knife_add_single_cut(kcd, r->ref, r->next->ref, f);
- }
+ for (r = hits->first; r->next; r = r->next) {
+ knife_add_single_cut(kcd, r->ref, r->next->ref, f);
+ }
}
/* User has just left-clicked after the first time.
@@ -868,338 +878,337 @@ static void knife_cut_face(KnifeTool_OpData *kcd, BMFace *f, ListBase *hits)
*/
static void knife_add_cut(KnifeTool_OpData *kcd)
{
- int i;
- GHash *facehits;
- BMFace *f;
- Ref *r;
- GHashIterator giter;
- ListBase *lst;
-
- prepare_linehits_for_cut(kcd);
- if (kcd->totlinehit == 0) {
- if (kcd->is_drag_hold == false) {
- kcd->prev = kcd->curr;
- }
- return;
- }
-
- /* make facehits: map face -> list of linehits touching it */
- facehits = BLI_ghash_ptr_new("knife facehits");
- for (i = 0; i < kcd->totlinehit; i++) {
- KnifeLineHit *lh = &kcd->linehits[i];
- if (lh->f) {
- add_hit_to_facehits(kcd, facehits, lh->f, lh);
- }
- if (lh->v) {
- for (r = lh->v->faces.first; r; r = r->next) {
- add_hit_to_facehits(kcd, facehits, r->ref, lh);
- }
- }
- if (lh->kfe) {
- for (r = lh->kfe->faces.first; r; r = r->next) {
- add_hit_to_facehits(kcd, facehits, r->ref, lh);
- }
- }
- }
-
- /* Note: as following loop progresses, the 'v' fields of
- * the linehits will be filled in (as edges are split or
- * in-face verts are made), so it may be true that both
- * the v and the kfe or f fields will be non-NULL. */
- GHASH_ITER (giter, facehits) {
- f = (BMFace *)BLI_ghashIterator_getKey(&giter);
- lst = (ListBase *)BLI_ghashIterator_getValue(&giter);
- knife_cut_face(kcd, f, lst);
- }
-
- /* set up for next cut */
- kcd->prev = kcd->curr;
-
-
- if (kcd->prev.bmface) {
- /* was "in face" but now we have a KnifeVert it is snapped to */
- KnifeLineHit *lh = &kcd->linehits[kcd->totlinehit - 1];
- kcd->prev.vert = lh->v;
- kcd->prev.bmface = NULL;
- }
-
- if (kcd->is_drag_hold) {
- KnifeLineHit *lh = &kcd->linehits[kcd->totlinehit - 1];
- linehit_to_knifepos(&kcd->prev, lh);
- }
-
- BLI_ghash_free(facehits, NULL, NULL);
- MEM_freeN(kcd->linehits);
- kcd->linehits = NULL;
- kcd->totlinehit = 0;
+ int i;
+ GHash *facehits;
+ BMFace *f;
+ Ref *r;
+ GHashIterator giter;
+ ListBase *lst;
+
+ prepare_linehits_for_cut(kcd);
+ if (kcd->totlinehit == 0) {
+ if (kcd->is_drag_hold == false) {
+ kcd->prev = kcd->curr;
+ }
+ return;
+ }
+
+ /* make facehits: map face -> list of linehits touching it */
+ facehits = BLI_ghash_ptr_new("knife facehits");
+ for (i = 0; i < kcd->totlinehit; i++) {
+ KnifeLineHit *lh = &kcd->linehits[i];
+ if (lh->f) {
+ add_hit_to_facehits(kcd, facehits, lh->f, lh);
+ }
+ if (lh->v) {
+ for (r = lh->v->faces.first; r; r = r->next) {
+ add_hit_to_facehits(kcd, facehits, r->ref, lh);
+ }
+ }
+ if (lh->kfe) {
+ for (r = lh->kfe->faces.first; r; r = r->next) {
+ add_hit_to_facehits(kcd, facehits, r->ref, lh);
+ }
+ }
+ }
+
+ /* Note: as following loop progresses, the 'v' fields of
+ * the linehits will be filled in (as edges are split or
+ * in-face verts are made), so it may be true that both
+ * the v and the kfe or f fields will be non-NULL. */
+ GHASH_ITER (giter, facehits) {
+ f = (BMFace *)BLI_ghashIterator_getKey(&giter);
+ lst = (ListBase *)BLI_ghashIterator_getValue(&giter);
+ knife_cut_face(kcd, f, lst);
+ }
+
+ /* set up for next cut */
+ kcd->prev = kcd->curr;
+
+ if (kcd->prev.bmface) {
+ /* was "in face" but now we have a KnifeVert it is snapped to */
+ KnifeLineHit *lh = &kcd->linehits[kcd->totlinehit - 1];
+ kcd->prev.vert = lh->v;
+ kcd->prev.bmface = NULL;
+ }
+
+ if (kcd->is_drag_hold) {
+ KnifeLineHit *lh = &kcd->linehits[kcd->totlinehit - 1];
+ linehit_to_knifepos(&kcd->prev, lh);
+ }
+
+ BLI_ghash_free(facehits, NULL, NULL);
+ MEM_freeN(kcd->linehits);
+ kcd->linehits = NULL;
+ kcd->totlinehit = 0;
}
static void knife_finish_cut(KnifeTool_OpData *kcd)
{
- if (kcd->linehits) {
- MEM_freeN(kcd->linehits);
- kcd->linehits = NULL;
- kcd->totlinehit = 0;
- }
+ if (kcd->linehits) {
+ MEM_freeN(kcd->linehits);
+ kcd->linehits = NULL;
+ kcd->totlinehit = 0;
+ }
}
static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd)
{
- float v1[3], v2[3];
- float planes[4][4];
+ float v1[3], v2[3];
+ float planes[4][4];
- planes_from_projmat(
- (float (*)[4])kcd->projmat,
- planes[2], planes[0], planes[3], planes[1], NULL, NULL);
+ planes_from_projmat(
+ (float(*)[4])kcd->projmat, planes[2], planes[0], planes[3], planes[1], NULL, NULL);
- /* ray-cast all planes */
- {
- float ray_dir[3];
- float ray_hit_best[2][3] = {{UNPACK3(kcd->prev.cage)}, {UNPACK3(kcd->curr.cage)}};
- float lambda_best[2] = {-FLT_MAX, FLT_MAX};
- int i;
+ /* ray-cast all planes */
+ {
+ float ray_dir[3];
+ float ray_hit_best[2][3] = {{UNPACK3(kcd->prev.cage)}, {UNPACK3(kcd->curr.cage)}};
+ float lambda_best[2] = {-FLT_MAX, FLT_MAX};
+ int i;
- /* we (sometimes) need the lines to be at the same depth before projecting */
+ /* we (sometimes) need the lines to be at the same depth before projecting */
#if 0
- sub_v3_v3v3(ray_dir, kcd->curr.cage, kcd->prev.cage);
+ sub_v3_v3v3(ray_dir, kcd->curr.cage, kcd->prev.cage);
#else
- {
- float curr_cage_adjust[3];
- float co_depth[3];
+ {
+ float curr_cage_adjust[3];
+ float co_depth[3];
- 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);
- mul_m4_v3(kcd->ob->imat, curr_cage_adjust);
+ 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);
+ mul_m4_v3(kcd->ob->imat, curr_cage_adjust);
- sub_v3_v3v3(ray_dir, curr_cage_adjust, kcd->prev.cage);
- }
+ sub_v3_v3v3(ray_dir, curr_cage_adjust, kcd->prev.cage);
+ }
#endif
- for (i = 0; i < 4; i++) {
- float ray_hit[3];
- float lambda_test;
- if (isect_ray_plane_v3(kcd->prev.cage, ray_dir, planes[i], &lambda_test, false)) {
- madd_v3_v3v3fl(ray_hit, kcd->prev.cage, ray_dir, lambda_test);
- if (lambda_test < 0.0f) {
- if (lambda_test > lambda_best[0]) {
- copy_v3_v3(ray_hit_best[0], ray_hit);
- lambda_best[0] = lambda_test;
- }
- }
- else {
- if (lambda_test < lambda_best[1]) {
- copy_v3_v3(ray_hit_best[1], ray_hit);
- lambda_best[1] = lambda_test;
- }
- }
- }
- }
-
- copy_v3_v3(v1, ray_hit_best[0]);
- copy_v3_v3(v2, ray_hit_best[1]);
- }
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformThemeColor(TH_TRANSFORM);
- GPU_line_width(2.0);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3fv(pos, v1);
- immVertex3fv(pos, v2);
- immEnd();
-
- immUnbindProgram();
+ for (i = 0; i < 4; i++) {
+ float ray_hit[3];
+ float lambda_test;
+ if (isect_ray_plane_v3(kcd->prev.cage, ray_dir, planes[i], &lambda_test, false)) {
+ madd_v3_v3v3fl(ray_hit, kcd->prev.cage, ray_dir, lambda_test);
+ if (lambda_test < 0.0f) {
+ if (lambda_test > lambda_best[0]) {
+ copy_v3_v3(ray_hit_best[0], ray_hit);
+ lambda_best[0] = lambda_test;
+ }
+ }
+ else {
+ if (lambda_test < lambda_best[1]) {
+ copy_v3_v3(ray_hit_best[1], ray_hit);
+ lambda_best[1] = lambda_test;
+ }
+ }
+ }
+ }
+
+ copy_v3_v3(v1, ray_hit_best[0]);
+ copy_v3_v3(v2, ray_hit_best[1]);
+ }
+
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_TRANSFORM);
+ GPU_line_width(2.0);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immEnd();
+
+ immUnbindProgram();
}
static void knife_init_colors(KnifeColors *colors)
{
- /* possible BMESH_TODO: add explicit themes or calculate these by
- * figuring out contrasting colors with grid / edges / verts
- * a la UI_make_axis_color */
- UI_GetThemeColorType3ubv(TH_NURB_VLINE, SPACE_VIEW3D, colors->line);
- UI_GetThemeColorType3ubv(TH_NURB_ULINE, SPACE_VIEW3D, colors->edge);
- UI_GetThemeColorType3ubv(TH_HANDLE_SEL_VECT, SPACE_VIEW3D, colors->curpoint);
- UI_GetThemeColorType3ubv(TH_HANDLE_SEL_VECT, SPACE_VIEW3D, colors->curpoint_a);
- colors->curpoint_a[3] = 102;
- UI_GetThemeColorType3ubv(TH_ACTIVE_SPLINE, SPACE_VIEW3D, colors->point);
- UI_GetThemeColorType3ubv(TH_ACTIVE_SPLINE, SPACE_VIEW3D, colors->point_a);
- colors->point_a[3] = 102;
+ /* possible BMESH_TODO: add explicit themes or calculate these by
+ * figuring out contrasting colors with grid / edges / verts
+ * a la UI_make_axis_color */
+ UI_GetThemeColorType3ubv(TH_NURB_VLINE, SPACE_VIEW3D, colors->line);
+ UI_GetThemeColorType3ubv(TH_NURB_ULINE, SPACE_VIEW3D, colors->edge);
+ UI_GetThemeColorType3ubv(TH_HANDLE_SEL_VECT, SPACE_VIEW3D, colors->curpoint);
+ UI_GetThemeColorType3ubv(TH_HANDLE_SEL_VECT, SPACE_VIEW3D, colors->curpoint_a);
+ colors->curpoint_a[3] = 102;
+ UI_GetThemeColorType3ubv(TH_ACTIVE_SPLINE, SPACE_VIEW3D, colors->point);
+ UI_GetThemeColorType3ubv(TH_ACTIVE_SPLINE, SPACE_VIEW3D, colors->point_a);
+ colors->point_a[3] = 102;
}
/* modal loop selection drawing callback */
static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
{
- const KnifeTool_OpData *kcd = arg;
- GPU_depth_test(false);
-
- glPolygonOffset(1.0f, 1.0f);
-
- GPU_matrix_push();
- GPU_matrix_mul(kcd->ob->obmat);
-
- if (kcd->mode == MODE_DRAGGING && kcd->is_angle_snapping) {
- knifetool_draw_angle_snapping(kcd);
- }
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
-
- if (kcd->mode == MODE_DRAGGING) {
- immUniformColor3ubv(kcd->colors.line);
- GPU_line_width(2.0);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3fv(pos, kcd->prev.cage);
- immVertex3fv(pos, kcd->curr.cage);
- immEnd();
- }
-
- if (kcd->prev.vert) {
- immUniformColor3ubv(kcd->colors.point);
- GPU_point_size(11);
-
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex3fv(pos, kcd->prev.cage);
- immEnd();
- }
-
- if (kcd->prev.bmface) {
- immUniformColor3ubv(kcd->colors.curpoint);
- GPU_point_size(9);
-
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex3fv(pos, kcd->prev.cage);
- immEnd();
- }
-
- if (kcd->curr.edge) {
- immUniformColor3ubv(kcd->colors.edge);
- GPU_line_width(2.0);
+ const KnifeTool_OpData *kcd = arg;
+ GPU_depth_test(false);
+
+ glPolygonOffset(1.0f, 1.0f);
+
+ GPU_matrix_push();
+ GPU_matrix_mul(kcd->ob->obmat);
+
+ if (kcd->mode == MODE_DRAGGING && kcd->is_angle_snapping) {
+ knifetool_draw_angle_snapping(kcd);
+ }
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ if (kcd->mode == MODE_DRAGGING) {
+ immUniformColor3ubv(kcd->colors.line);
+ GPU_line_width(2.0);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3fv(pos, kcd->prev.cage);
+ immVertex3fv(pos, kcd->curr.cage);
+ immEnd();
+ }
+
+ if (kcd->prev.vert) {
+ immUniformColor3ubv(kcd->colors.point);
+ GPU_point_size(11);
+
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex3fv(pos, kcd->prev.cage);
+ immEnd();
+ }
+
+ if (kcd->prev.bmface) {
+ immUniformColor3ubv(kcd->colors.curpoint);
+ GPU_point_size(9);
+
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex3fv(pos, kcd->prev.cage);
+ immEnd();
+ }
+
+ if (kcd->curr.edge) {
+ immUniformColor3ubv(kcd->colors.edge);
+ GPU_line_width(2.0);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3fv(pos, kcd->curr.edge->v1->cageco);
- immVertex3fv(pos, kcd->curr.edge->v2->cageco);
- immEnd();
- }
- else if (kcd->curr.vert) {
- immUniformColor3ubv(kcd->colors.point);
- GPU_point_size(11);
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3fv(pos, kcd->curr.edge->v1->cageco);
+ immVertex3fv(pos, kcd->curr.edge->v2->cageco);
+ immEnd();
+ }
+ else if (kcd->curr.vert) {
+ immUniformColor3ubv(kcd->colors.point);
+ GPU_point_size(11);
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex3fv(pos, kcd->curr.cage);
- immEnd();
- }
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex3fv(pos, kcd->curr.cage);
+ immEnd();
+ }
- if (kcd->curr.bmface) {
- immUniformColor3ubv(kcd->colors.curpoint);
- GPU_point_size(9);
+ if (kcd->curr.bmface) {
+ immUniformColor3ubv(kcd->colors.curpoint);
+ GPU_point_size(9);
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex3fv(pos, kcd->curr.cage);
- immEnd();
- }
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex3fv(pos, kcd->curr.cage);
+ immEnd();
+ }
- if (kcd->totlinehit > 0) {
- KnifeLineHit *lh;
- int i, v, vs;
- float fcol[4];
+ if (kcd->totlinehit > 0) {
+ KnifeLineHit *lh;
+ int i, v, vs;
+ float fcol[4];
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPUVertBuf *vert = GPU_vertbuf_create_with_format(format);
- GPU_vertbuf_data_alloc(vert, kcd->totlinehit);
+ GPUVertBuf *vert = GPU_vertbuf_create_with_format(format);
+ GPU_vertbuf_data_alloc(vert, kcd->totlinehit);
- lh = kcd->linehits;
- for (i = 0, v = 0, vs = kcd->totlinehit - 1; i < kcd->totlinehit; i++, lh++) {
- if (lh->v) {
- GPU_vertbuf_attr_set(vert, pos, v++, lh->cagehit);
- }
- else {
- GPU_vertbuf_attr_set(vert, pos, vs--, lh->cagehit);
- }
- }
+ lh = kcd->linehits;
+ for (i = 0, v = 0, vs = kcd->totlinehit - 1; i < kcd->totlinehit; i++, lh++) {
+ if (lh->v) {
+ GPU_vertbuf_attr_set(vert, pos, v++, lh->cagehit);
+ }
+ else {
+ GPU_vertbuf_attr_set(vert, pos, vs--, lh->cagehit);
+ }
+ }
- GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_POINTS, vert, NULL, GPU_BATCH_OWNS_VBO);
- GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_POINTS, vert, NULL, GPU_BATCH_OWNS_VBO);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
- /* draw any snapped verts first */
- rgba_uchar_to_float(fcol, kcd->colors.point_a);
- GPU_batch_uniform_4fv(batch, "color", fcol);
- GPU_matrix_bind(batch->interface);
- GPU_point_size(11);
- GPU_batch_draw_range_ex(batch, 0, v - 1, false);
+ /* draw any snapped verts first */
+ rgba_uchar_to_float(fcol, kcd->colors.point_a);
+ GPU_batch_uniform_4fv(batch, "color", fcol);
+ GPU_matrix_bind(batch->interface);
+ GPU_point_size(11);
+ GPU_batch_draw_range_ex(batch, 0, v - 1, false);
- /* now draw the rest */
- rgba_uchar_to_float(fcol, kcd->colors.curpoint_a);
- GPU_batch_uniform_4fv(batch, "color", fcol);
- GPU_point_size(7);
- GPU_batch_draw_range_ex(batch, vs + 1, kcd->totlinehit - (vs + 1), false);
+ /* now draw the rest */
+ rgba_uchar_to_float(fcol, kcd->colors.curpoint_a);
+ GPU_batch_uniform_4fv(batch, "color", fcol);
+ GPU_point_size(7);
+ GPU_batch_draw_range_ex(batch, vs + 1, kcd->totlinehit - (vs + 1), false);
- GPU_batch_program_use_end(batch);
- GPU_batch_discard(batch);
+ GPU_batch_program_use_end(batch);
+ GPU_batch_discard(batch);
- GPU_blend(false);
- }
+ GPU_blend(false);
+ }
- if (kcd->totkedge > 0) {
- BLI_mempool_iter iter;
- KnifeEdge *kfe;
+ if (kcd->totkedge > 0) {
+ BLI_mempool_iter iter;
+ KnifeEdge *kfe;
- immUniformColor3ubv(kcd->colors.line);
- GPU_line_width(1.0);
+ immUniformColor3ubv(kcd->colors.line);
+ GPU_line_width(1.0);
- GPUBatch *batch = immBeginBatchAtMost(GPU_PRIM_LINES, BLI_mempool_len(kcd->kedges) * 2);
+ GPUBatch *batch = immBeginBatchAtMost(GPU_PRIM_LINES, BLI_mempool_len(kcd->kedges) * 2);
- BLI_mempool_iternew(kcd->kedges, &iter);
- for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) {
- if (!kfe->is_cut)
- continue;
+ BLI_mempool_iternew(kcd->kedges, &iter);
+ for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) {
+ if (!kfe->is_cut)
+ continue;
- immVertex3fv(pos, kfe->v1->cageco);
- immVertex3fv(pos, kfe->v2->cageco);
- }
+ immVertex3fv(pos, kfe->v1->cageco);
+ immVertex3fv(pos, kfe->v2->cageco);
+ }
- immEnd();
+ immEnd();
- GPU_batch_draw(batch);
- GPU_batch_discard(batch);
- }
+ GPU_batch_draw(batch);
+ GPU_batch_discard(batch);
+ }
- if (kcd->totkvert > 0) {
- BLI_mempool_iter iter;
- KnifeVert *kfv;
+ if (kcd->totkvert > 0) {
+ BLI_mempool_iter iter;
+ KnifeVert *kfv;
- immUniformColor3ubv(kcd->colors.point);
- GPU_point_size(5.0);
+ immUniformColor3ubv(kcd->colors.point);
+ GPU_point_size(5.0);
- GPUBatch *batch = immBeginBatchAtMost(GPU_PRIM_POINTS, BLI_mempool_len(kcd->kverts));
+ GPUBatch *batch = immBeginBatchAtMost(GPU_PRIM_POINTS, BLI_mempool_len(kcd->kverts));
- BLI_mempool_iternew(kcd->kverts, &iter);
- for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) {
- if (!kfv->is_cut)
- continue;
+ BLI_mempool_iternew(kcd->kverts, &iter);
+ for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) {
+ if (!kfv->is_cut)
+ continue;
- immVertex3fv(pos, kfv->cageco);
- }
+ immVertex3fv(pos, kfv->cageco);
+ }
- immEnd();
+ immEnd();
- GPU_batch_draw(batch);
- GPU_batch_discard(batch);
- }
+ GPU_batch_draw(batch);
+ GPU_batch_discard(batch);
+ }
- immUnbindProgram();
+ immUnbindProgram();
- GPU_matrix_pop();
+ GPU_matrix_pop();
- /* Reset default */
- GPU_depth_test(true);
+ /* Reset default */
+ GPU_depth_test(true);
}
/**
@@ -1210,68 +1219,70 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void
* it really means "infinite number of intersections".
* In such a case we should have gotten hits on edges or verts of the face.
*/
-static bool knife_ray_intersect_face(
- KnifeTool_OpData *kcd,
- const float s[2], const float v1[3], const float v2[3],
- BMFace *f, const float face_tol_sq,
- float hit_co[3], float hit_cageco[3])
-{
- int tottri, tri_i;
- float raydir[3];
- float tri_norm[3], tri_plane[4];
- float se1[2], se2[2];
- float d, lambda;
- BMLoop **tri;
- ListBase *lst;
- Ref *ref;
- KnifeEdge *kfe;
-
- sub_v3_v3v3(raydir, v2, v1);
- normalize_v3(raydir);
- tri_i = get_lowest_face_tri(kcd, f);
- tottri = kcd->em->tottri;
- BLI_assert(tri_i >= 0 && tri_i < tottri);
-
- for (; tri_i < tottri; tri_i++) {
- const float *lv1, *lv2, *lv3;
- float ray_tri_uv[2];
-
- tri = kcd->em->looptris[tri_i];
- if (tri[0]->f != f)
- break;
- lv1 = kcd->cagecos[BM_elem_index_get(tri[0]->v)];
- lv2 = kcd->cagecos[BM_elem_index_get(tri[1]->v)];
- lv3 = kcd->cagecos[BM_elem_index_get(tri[2]->v)];
- /* using epsilon test in case ray is directly through an internal
- * tessellation edge and might not hit either tessellation tri with
- * an exact test;
- * we will exclude hits near real edges by a later test */
- if (isect_ray_tri_epsilon_v3(v1, raydir, lv1, lv2, lv3, &lambda, ray_tri_uv, KNIFE_FLT_EPS)) {
- /* check if line coplanar with tri */
- normal_tri_v3(tri_norm, lv1, lv2, lv3);
- plane_from_point_normal_v3(tri_plane, lv1, tri_norm);
- if ((dist_squared_to_plane_v3(v1, tri_plane) < KNIFE_FLT_EPS) &&
- (dist_squared_to_plane_v3(v2, tri_plane) < KNIFE_FLT_EPS))
- {
- return false;
- }
- interp_v3_v3v3v3_uv(hit_cageco, lv1, lv2, lv3, ray_tri_uv);
- /* Now check that far enough away from verts and edges */
- lst = knife_get_face_kedges(kcd, f);
- for (ref = lst->first; ref; ref = ref->next) {
- kfe = ref->ref;
- knife_project_v2(kcd, kfe->v1->cageco, se1);
- knife_project_v2(kcd, kfe->v2->cageco, se2);
- d = dist_squared_to_line_segment_v2(s, se1, se2);
- if (d < face_tol_sq) {
- return false;
- }
- }
- interp_v3_v3v3v3_uv(hit_co, tri[0]->v->co, tri[1]->v->co, tri[2]->v->co, ray_tri_uv);
- return true;
- }
- }
- return false;
+static bool knife_ray_intersect_face(KnifeTool_OpData *kcd,
+ const float s[2],
+ const float v1[3],
+ const float v2[3],
+ BMFace *f,
+ const float face_tol_sq,
+ float hit_co[3],
+ float hit_cageco[3])
+{
+ int tottri, tri_i;
+ float raydir[3];
+ float tri_norm[3], tri_plane[4];
+ float se1[2], se2[2];
+ float d, lambda;
+ BMLoop **tri;
+ ListBase *lst;
+ Ref *ref;
+ KnifeEdge *kfe;
+
+ sub_v3_v3v3(raydir, v2, v1);
+ normalize_v3(raydir);
+ tri_i = get_lowest_face_tri(kcd, f);
+ tottri = kcd->em->tottri;
+ BLI_assert(tri_i >= 0 && tri_i < tottri);
+
+ for (; tri_i < tottri; tri_i++) {
+ const float *lv1, *lv2, *lv3;
+ float ray_tri_uv[2];
+
+ tri = kcd->em->looptris[tri_i];
+ if (tri[0]->f != f)
+ break;
+ lv1 = kcd->cagecos[BM_elem_index_get(tri[0]->v)];
+ lv2 = kcd->cagecos[BM_elem_index_get(tri[1]->v)];
+ lv3 = kcd->cagecos[BM_elem_index_get(tri[2]->v)];
+ /* using epsilon test in case ray is directly through an internal
+ * tessellation edge and might not hit either tessellation tri with
+ * an exact test;
+ * we will exclude hits near real edges by a later test */
+ if (isect_ray_tri_epsilon_v3(v1, raydir, lv1, lv2, lv3, &lambda, ray_tri_uv, KNIFE_FLT_EPS)) {
+ /* check if line coplanar with tri */
+ normal_tri_v3(tri_norm, lv1, lv2, lv3);
+ plane_from_point_normal_v3(tri_plane, lv1, tri_norm);
+ if ((dist_squared_to_plane_v3(v1, tri_plane) < KNIFE_FLT_EPS) &&
+ (dist_squared_to_plane_v3(v2, tri_plane) < KNIFE_FLT_EPS)) {
+ return false;
+ }
+ interp_v3_v3v3v3_uv(hit_cageco, lv1, lv2, lv3, ray_tri_uv);
+ /* Now check that far enough away from verts and edges */
+ lst = knife_get_face_kedges(kcd, f);
+ for (ref = lst->first; ref; ref = ref->next) {
+ kfe = ref->ref;
+ knife_project_v2(kcd, kfe->v1->cageco, se1);
+ knife_project_v2(kcd, kfe->v2->cageco, se2);
+ d = dist_squared_to_line_segment_v2(s, se1, se2);
+ if (d < face_tol_sq) {
+ return false;
+ }
+ }
+ interp_v3_v3v3v3_uv(hit_co, tri[0]->v->co, tri[1]->v->co, tri[2]->v->co, ray_tri_uv);
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -1279,96 +1290,95 @@ static bool knife_ray_intersect_face(
*/
static void calc_ortho_extent(KnifeTool_OpData *kcd)
{
- BMIter iter;
- BMVert *v;
- BMesh *bm = kcd->em->bm;
- float min[3], max[3];
+ BMIter iter;
+ BMVert *v;
+ BMesh *bm = kcd->em->bm;
+ float min[3], max[3];
- INIT_MINMAX(min, max);
+ INIT_MINMAX(min, max);
- if (kcd->cagecos) {
- minmax_v3v3_v3_array(min, max, kcd->cagecos, bm->totvert);
- }
- else {
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- minmax_v3v3_v3(min, max, v->co);
- }
- }
+ if (kcd->cagecos) {
+ minmax_v3v3_v3_array(min, max, kcd->cagecos, bm->totvert);
+ }
+ else {
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ minmax_v3v3_v3(min, max, v->co);
+ }
+ }
- kcd->ortho_extent = len_v3v3(min, max) / 2;
- mid_v3_v3v3(kcd->ortho_extent_center, min, max);
+ kcd->ortho_extent = len_v3v3(min, max) / 2;
+ mid_v3_v3v3(kcd->ortho_extent_center, min, max);
}
static BMElem *bm_elem_from_knife_vert(KnifeVert *kfv, KnifeEdge **r_kfe)
{
- BMElem *ele_test;
- KnifeEdge *kfe = NULL;
-
- /* vert? */
- ele_test = (BMElem *)kfv->v;
-
- if (r_kfe || ele_test == NULL) {
- if (kfv->v == NULL) {
- Ref *ref;
- for (ref = kfv->edges.first; ref; ref = ref->next) {
- kfe = ref->ref;
- if (kfe->e) {
- if (r_kfe) {
- *r_kfe = kfe;
- }
- break;
- }
- }
- }
- }
-
- /* edge? */
- if (ele_test == NULL) {
- if (kfe) {
- ele_test = (BMElem *)kfe->e;
- }
- }
-
- /* face? */
- if (ele_test == NULL) {
- if (BLI_listbase_is_single(&kfe->faces)) {
- ele_test = ((Ref *)kfe->faces.first)->ref;
- }
- }
-
- return ele_test;
+ BMElem *ele_test;
+ KnifeEdge *kfe = NULL;
+
+ /* vert? */
+ ele_test = (BMElem *)kfv->v;
+
+ if (r_kfe || ele_test == NULL) {
+ if (kfv->v == NULL) {
+ Ref *ref;
+ for (ref = kfv->edges.first; ref; ref = ref->next) {
+ kfe = ref->ref;
+ if (kfe->e) {
+ if (r_kfe) {
+ *r_kfe = kfe;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ /* edge? */
+ if (ele_test == NULL) {
+ if (kfe) {
+ ele_test = (BMElem *)kfe->e;
+ }
+ }
+
+ /* face? */
+ if (ele_test == NULL) {
+ if (BLI_listbase_is_single(&kfe->faces)) {
+ ele_test = ((Ref *)kfe->faces.first)->ref;
+ }
+ }
+
+ return ele_test;
}
static BMElem *bm_elem_from_knife_edge(KnifeEdge *kfe)
{
- BMElem *ele_test;
+ BMElem *ele_test;
- ele_test = (BMElem *)kfe->e;
+ ele_test = (BMElem *)kfe->e;
- if (ele_test == NULL) {
- ele_test = (BMElem *)kfe->basef;
- }
+ if (ele_test == NULL) {
+ ele_test = (BMElem *)kfe->basef;
+ }
- return ele_test;
+ return ele_test;
}
/* Do edges e1 and e2 go between exactly the same coordinates? */
static bool coinciding_edges(BMEdge *e1, BMEdge *e2)
{
- const float *co11, *co12, *co21, *co22;
+ const float *co11, *co12, *co21, *co22;
- co11 = e1->v1->co;
- co12 = e1->v2->co;
- co21 = e2->v1->co;
- co22 = e2->v2->co;
- if ((equals_v3v3(co11, co21) && equals_v3v3(co12, co22)) ||
- (equals_v3v3(co11, co22) && equals_v3v3(co12, co21)))
- {
- return true;
- }
- else {
- return false;
- }
+ co11 = e1->v1->co;
+ co12 = e1->v2->co;
+ co21 = e2->v1->co;
+ co22 = e2->v2->co;
+ if ((equals_v3v3(co11, co21) && equals_v3v3(co12, co22)) ||
+ (equals_v3v3(co11, co22) && equals_v3v3(co12, co21))) {
+ return true;
+ }
+ else {
+ return false;
+ }
}
/* Callback used in point_is_visible to exclude hits on the faces that are the same
@@ -1378,40 +1388,39 @@ static bool coinciding_edges(BMEdge *e1, BMEdge *e2)
*/
static bool bm_ray_cast_cb_elem_not_in_face_check(BMFace *f, void *user_data)
{
- bool ans;
- BMEdge *e, *e2;
- BMIter iter;
-
- switch (((BMElem *)user_data)->head.htype) {
- case BM_FACE:
- ans = (BMFace *)user_data != f;
- break;
- case BM_EDGE:
- e = (BMEdge *)user_data;
- ans = !BM_edge_in_face(e, f);
- if (ans) {
- /* Is it a boundary edge, coincident with a split edge? */
- if (BM_edge_is_boundary(e)) {
- BM_ITER_ELEM(e2, &iter, f, BM_EDGES_OF_FACE) {
- if (coinciding_edges(e, e2)) {
- ans = false;
- break;
- }
- }
- }
- }
- break;
- case BM_VERT:
- ans = !BM_vert_in_face((BMVert *)user_data, f);
- break;
- default:
- ans = true;
- break;
- }
- return ans;
+ bool ans;
+ BMEdge *e, *e2;
+ BMIter iter;
+
+ switch (((BMElem *)user_data)->head.htype) {
+ case BM_FACE:
+ ans = (BMFace *)user_data != f;
+ break;
+ case BM_EDGE:
+ e = (BMEdge *)user_data;
+ ans = !BM_edge_in_face(e, f);
+ if (ans) {
+ /* Is it a boundary edge, coincident with a split edge? */
+ if (BM_edge_is_boundary(e)) {
+ BM_ITER_ELEM (e2, &iter, f, BM_EDGES_OF_FACE) {
+ if (coinciding_edges(e, e2)) {
+ ans = false;
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case BM_VERT:
+ ans = !BM_vert_in_face((BMVert *)user_data, f);
+ break;
+ default:
+ ans = true;
+ break;
+ }
+ return ans;
}
-
/**
* Check if \a p is visible (not clipped, not occluded by another face).
* s in screen projection of p.
@@ -1419,729 +1428,737 @@ static bool bm_ray_cast_cb_elem_not_in_face_check(BMFace *f, void *user_data)
* \param ele_test: Optional vert/edge/face to use when \a p is on the surface of the geometry,
* intersecting faces matching this face (or connected when an vert/edge) will be ignored.
*/
-static bool point_is_visible(
- KnifeTool_OpData *kcd, const float p[3], const float s[2],
- BMElem *ele_test)
-{
- BMFace *f_hit;
-
- /* If box clipping on, make sure p is not clipped */
- if (kcd->vc.rv3d->rflag & RV3D_CLIPPING &&
- ED_view3d_clipping_test(kcd->vc.rv3d, p, true))
- {
- return false;
- }
-
- /* If not cutting through, make sure no face is in front of p */
- if (!kcd->cut_through) {
- float dist;
- 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);
-
- mul_m4_v3(kcd->ob->imat, view);
-
- /* make p_ofs a little towards view, so ray doesn't hit p's face. */
- sub_v3_v3(view, p);
- dist = normalize_v3(view);
- copy_v3_v3(p_ofs, p);
-
- /* avoid projecting behind the viewpoint */
- if (kcd->is_ortho && (kcd->vc.rv3d->persp != RV3D_CAMOB)) {
- dist = kcd->vc.v3d->clip_end * 2.0f;
- }
-
- if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
- float view_clip[2][3];
- /* note: view_clip[0] should never get clipped */
- copy_v3_v3(view_clip[0], p_ofs);
- madd_v3_v3v3fl(view_clip[1], p_ofs, view, dist);
-
- if (clip_segment_v3_plane_n(
- view_clip[0], view_clip[1], kcd->vc.rv3d->clip_local, 6,
- view_clip[0], view_clip[1]))
- {
- dist = len_v3v3(p_ofs, view_clip[1]);
- }
- }
-
- /* see if there's a face hit between p1 and the view */
- if (ele_test) {
- f_hit = BKE_bmbvh_ray_cast_filter(
- kcd->bmbvh, p_ofs, view, KNIFE_FLT_EPS, &dist, NULL, NULL,
- bm_ray_cast_cb_elem_not_in_face_check, ele_test);
- }
- else {
- f_hit = BKE_bmbvh_ray_cast(
- kcd->bmbvh, p_ofs, view, KNIFE_FLT_EPS, &dist, NULL, NULL);
- }
-
- if (f_hit) {
- return false;
- }
- }
-
- return true;
+static bool point_is_visible(KnifeTool_OpData *kcd,
+ const float p[3],
+ const float s[2],
+ BMElem *ele_test)
+{
+ BMFace *f_hit;
+
+ /* If box clipping on, make sure p is not clipped */
+ if (kcd->vc.rv3d->rflag & RV3D_CLIPPING && ED_view3d_clipping_test(kcd->vc.rv3d, p, true)) {
+ return false;
+ }
+
+ /* If not cutting through, make sure no face is in front of p */
+ if (!kcd->cut_through) {
+ float dist;
+ 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);
+
+ mul_m4_v3(kcd->ob->imat, view);
+
+ /* make p_ofs a little towards view, so ray doesn't hit p's face. */
+ sub_v3_v3(view, p);
+ dist = normalize_v3(view);
+ copy_v3_v3(p_ofs, p);
+
+ /* avoid projecting behind the viewpoint */
+ if (kcd->is_ortho && (kcd->vc.rv3d->persp != RV3D_CAMOB)) {
+ dist = kcd->vc.v3d->clip_end * 2.0f;
+ }
+
+ if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
+ float view_clip[2][3];
+ /* note: view_clip[0] should never get clipped */
+ copy_v3_v3(view_clip[0], p_ofs);
+ madd_v3_v3v3fl(view_clip[1], p_ofs, view, dist);
+
+ if (clip_segment_v3_plane_n(view_clip[0],
+ view_clip[1],
+ kcd->vc.rv3d->clip_local,
+ 6,
+ view_clip[0],
+ view_clip[1])) {
+ dist = len_v3v3(p_ofs, view_clip[1]);
+ }
+ }
+
+ /* see if there's a face hit between p1 and the view */
+ if (ele_test) {
+ f_hit = BKE_bmbvh_ray_cast_filter(kcd->bmbvh,
+ p_ofs,
+ view,
+ KNIFE_FLT_EPS,
+ &dist,
+ NULL,
+ NULL,
+ bm_ray_cast_cb_elem_not_in_face_check,
+ ele_test);
+ }
+ else {
+ f_hit = BKE_bmbvh_ray_cast(kcd->bmbvh, p_ofs, view, KNIFE_FLT_EPS, &dist, NULL, NULL);
+ }
+
+ if (f_hit) {
+ return false;
+ }
+ }
+
+ return true;
}
/* Clip the line (v1, v2) to planes perpendicular to it and distances d from
* the closest point on the line to the origin */
static void clip_to_ortho_planes(float v1[3], float v2[3], const float center[3], const float d)
{
- float closest[3], dir[3];
+ float closest[3], dir[3];
- sub_v3_v3v3(dir, v1, v2);
- normalize_v3(dir);
+ sub_v3_v3v3(dir, v1, v2);
+ normalize_v3(dir);
- /* could be v1 or v2 */
- sub_v3_v3(v1, center);
- project_plane_normalized_v3_v3v3(closest, v1, dir);
- add_v3_v3(closest, center);
+ /* could be v1 or v2 */
+ sub_v3_v3(v1, center);
+ project_plane_normalized_v3_v3v3(closest, v1, dir);
+ add_v3_v3(closest, center);
- madd_v3_v3v3fl(v1, closest, dir, d);
- madd_v3_v3v3fl(v2, closest, dir, -d);
+ madd_v3_v3v3fl(v1, closest, dir, d);
+ madd_v3_v3v3fl(v2, closest, dir, -d);
}
static void set_linehit_depth(KnifeTool_OpData *kcd, KnifeLineHit *lh)
{
- lh->m = dot_m4_v3_row_z(kcd->vc.rv3d->persmatob, lh->cagehit);
+ lh->m = dot_m4_v3_row_z(kcd->vc.rv3d->persmatob, lh->cagehit);
}
/* Finds visible (or all, if cutting through) edges that intersects the current screen drag line */
static void knife_find_line_hits(KnifeTool_OpData *kcd)
{
- SmallHash faces, kfes, kfvs;
- float v1[3], v2[3], v3[3], v4[3], s1[2], s2[2];
- BVHTree *planetree, *tree;
- BVHTreeOverlap *results, *result;
- BMLoop **ls;
- BMFace *f;
- KnifeEdge *kfe;
- KnifeVert *v;
- ListBase *lst;
- Ref *ref;
- KnifeLineHit *linehits = NULL;
- BLI_array_declare(linehits);
- SmallHashIter hiter;
- KnifeLineHit hit;
- void *val;
- void **val_p;
- float plane_cos[12];
- float s[2], se1[2], se2[2], sint[2];
- float r1[3], r2[3];
- float d, d1, d2, lambda;
- float vert_tol, vert_tol_sq;
- float line_tol, line_tol_sq;
- float face_tol, face_tol_sq;
- int isect_kind;
- unsigned int tot;
- int i;
- const bool use_hit_prev = true;
- const bool use_hit_curr = (kcd->is_drag_hold == false);
-
- if (kcd->linehits) {
- MEM_freeN(kcd->linehits);
- kcd->linehits = NULL;
- kcd->totlinehit = 0;
- }
-
- copy_v3_v3(v1, kcd->prev.cage);
- copy_v3_v3(v2, kcd->curr.cage);
-
- /* project screen line's 3d coordinates back into 2d */
- knife_project_v2(kcd, v1, s1);
- knife_project_v2(kcd, v2, s2);
-
- if (kcd->is_interactive) {
- if (len_squared_v2v2(s1, s2) < 1.0f) {
- return;
- }
- }
- else {
- if (len_squared_v2v2(s1, s2) < KNIFE_FLT_EPS_SQUARED) {
- return;
- }
- }
-
- /* 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);
-
- mul_m4_v3(kcd->ob->imat, v1);
- mul_m4_v3(kcd->ob->imat, v2);
- mul_m4_v3(kcd->ob->imat, v3);
- mul_m4_v3(kcd->ob->imat, v4);
-
- /* numeric error, 'v1' -> 'v2', 'v2' -> 'v4' can end up being ~2000 units apart in otho mode
- * (from ED_view3d_win_to_segment_clipped() above)
- * this gives precision error; rather then solving properly
- * (which may involve using doubles everywhere!),
- * limit the distance between these points */
- if (kcd->is_ortho && (kcd->vc.rv3d->persp != RV3D_CAMOB)) {
- if (kcd->ortho_extent == 0.0f)
- calc_ortho_extent(kcd);
- clip_to_ortho_planes(v1, v3, kcd->ortho_extent_center, kcd->ortho_extent + 10.0f);
- clip_to_ortho_planes(v2, v4, kcd->ortho_extent_center, kcd->ortho_extent + 10.0f);
- }
-
- /* First use bvh tree to find faces, knife edges, and knife verts that might
- * intersect the cut plane with rays v1-v3 and v2-v4.
- * This deduplicates the candidates before doing more expensive intersection tests. */
-
- tree = BKE_bmbvh_tree_get(kcd->bmbvh);
- planetree = BLI_bvhtree_new(4, FLT_EPSILON * 4, 8, 8);
- copy_v3_v3(plane_cos + 0, v1);
- copy_v3_v3(plane_cos + 3, v2);
- copy_v3_v3(plane_cos + 6, v3);
- copy_v3_v3(plane_cos + 9, v4);
- BLI_bvhtree_insert(planetree, 0, plane_cos, 4);
- BLI_bvhtree_balance(planetree);
-
- results = BLI_bvhtree_overlap(tree, planetree, &tot, NULL, NULL);
- if (!results) {
- BLI_bvhtree_free(planetree);
- return;
- }
-
- BLI_smallhash_init(&faces);
- BLI_smallhash_init(&kfes);
- BLI_smallhash_init(&kfvs);
-
- for (i = 0, result = results; i < tot; i++, result++) {
- ls = (BMLoop **)kcd->em->looptris[result->indexA];
- f = ls[0]->f;
- set_lowest_face_tri(kcd, f, result->indexA);
-
- /* occlude but never cut unselected faces (when only_select is used) */
- if (kcd->only_select && !BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- continue;
- }
- /* for faces, store index of lowest hit looptri in hash */
- if (BLI_smallhash_haskey(&faces, (uintptr_t)f)) {
- continue;
- }
- /* don't care what the value is except that it is non-NULL, for iterator */
- BLI_smallhash_insert(&faces, (uintptr_t)f, f);
-
- lst = knife_get_face_kedges(kcd, f);
- for (ref = lst->first; ref; ref = ref->next) {
- kfe = ref->ref;
- if (BLI_smallhash_haskey(&kfes, (uintptr_t)kfe))
- continue;
- BLI_smallhash_insert(&kfes, (uintptr_t)kfe, kfe);
- v = kfe->v1;
- BLI_smallhash_reinsert(&kfvs, (uintptr_t)v, v);
- v = kfe->v2;
- BLI_smallhash_reinsert(&kfvs, (uintptr_t)v, v);
- }
- }
-
- /* Now go through the candidates and find intersections */
- /* These tolerances, in screen space, are for intermediate hits, as ends are already snapped to screen */
-
- if (kcd->is_interactive) {
- vert_tol = KNIFE_FLT_EPS_PX_VERT;
- line_tol = KNIFE_FLT_EPS_PX_EDGE;
- face_tol = KNIFE_FLT_EPS_PX_FACE;
- }
- else {
- /* Use 1/100th of a pixel, see T43896 (too big), T47910 (too small).
- *
- * Update, leave this as is until we investigate not using pixel coords for geometry calculations: T48023
- */
- vert_tol = line_tol = face_tol = 0.5f;
- }
-
- vert_tol_sq = vert_tol * vert_tol;
- line_tol_sq = line_tol * line_tol;
- face_tol_sq = face_tol * face_tol;
-
- /* Assume these tolerances swamp floating point rounding errors in calculations below */
-
- /* first look for vertex hits */
- for (val_p = BLI_smallhash_iternew_p(&kfvs, &hiter, (uintptr_t *)&v); val_p;
- val_p = BLI_smallhash_iternext_p(&hiter, (uintptr_t *)&v))
- {
- KnifeEdge *kfe_hit = NULL;
-
- knife_project_v2(kcd, v->cageco, s);
- d = dist_squared_to_line_segment_v2(s, s1, s2);
- if ((d <= vert_tol_sq) &&
- (point_is_visible(kcd, v->cageco, s, bm_elem_from_knife_vert(v, &kfe_hit))))
- {
- memset(&hit, 0, sizeof(hit));
- hit.v = v;
-
- /* If this isn't from an existing BMVert, it may have been added to a BMEdge originally.
- * knowing if the hit comes from an edge is important for edge-in-face checks later on
- * see: #knife_add_single_cut -> #knife_verts_edge_in_face, T42611 */
- if (kfe_hit) {
- hit.kfe = kfe_hit;
- }
-
- copy_v3_v3(hit.hit, v->co);
- copy_v3_v3(hit.cagehit, v->cageco);
- copy_v2_v2(hit.schit, s);
- set_linehit_depth(kcd, &hit);
- BLI_array_append(linehits, hit);
- }
- else {
- /* note that these vertes aren't used */
- *val_p = NULL;
- }
- }
-
- /* now edge hits; don't add if a vertex at end of edge should have hit */
- for (val = BLI_smallhash_iternew(&kfes, &hiter, (uintptr_t *)&kfe); val;
- val = BLI_smallhash_iternext(&hiter, (uintptr_t *)&kfe))
- {
- int kfe_verts_in_cut;
- /* if we intersect both verts, don't attempt to intersect the edge */
-
- kfe_verts_in_cut = (BLI_smallhash_lookup(&kfvs, (intptr_t)kfe->v1) != NULL) +
- (BLI_smallhash_lookup(&kfvs, (intptr_t)kfe->v2) != NULL);
-
- if (kfe_verts_in_cut == 2) {
- continue;
- }
-
- knife_project_v2(kcd, kfe->v1->cageco, se1);
- knife_project_v2(kcd, kfe->v2->cageco, se2);
- isect_kind = (kfe_verts_in_cut) ? -1 : isect_seg_seg_v2_point(s1, s2, se1, se2, sint);
- if (isect_kind == -1) {
- /* isect_seg_seg_v2_simple doesn't do tolerance test around ends of s1-s2 */
- closest_to_line_segment_v2(sint, s1, se1, se2);
- if (len_squared_v2v2(sint, s1) <= line_tol_sq)
- isect_kind = 1;
- else {
- closest_to_line_segment_v2(sint, s2, se1, se2);
- if (len_squared_v2v2(sint, s2) <= line_tol_sq)
- isect_kind = 1;
- }
- }
- if (isect_kind == 1) {
- d1 = len_v2v2(sint, se1);
- d2 = len_v2v2(se2, se1);
- if (!(d1 <= line_tol || d2 <= line_tol || fabsf(d1 - d2) <= line_tol)) {
- float p_cage[3], p_cage_tmp[3];
- lambda = d1 / d2;
- /* Can't just interpolate between ends of kfe because
- * that doesn't work with perspective transformation.
- * Need to find 3d intersection of ray through sint */
- knife_input_ray_segment(kcd, sint, 1.0f, r1, r2);
- isect_kind = isect_line_line_v3(kfe->v1->cageco, kfe->v2->cageco, r1, r2, p_cage, p_cage_tmp);
- if (isect_kind >= 1 && point_is_visible(kcd, p_cage, sint, bm_elem_from_knife_edge(kfe))) {
- memset(&hit, 0, sizeof(hit));
- if (kcd->snap_midpoints) {
- /* choose intermediate point snap too */
- mid_v3_v3v3(p_cage, kfe->v1->cageco, kfe->v2->cageco);
- mid_v2_v2v2(sint, se1, se2);
- lambda = 0.5f;
- }
- hit.kfe = kfe;
- transform_point_by_seg_v3(
- hit.hit, p_cage,
- kfe->v1->co, kfe->v2->co,
- kfe->v1->cageco, kfe->v2->cageco);
- copy_v3_v3(hit.cagehit, p_cage);
- copy_v2_v2(hit.schit, sint);
- hit.perc = lambda;
- set_linehit_depth(kcd, &hit);
- BLI_array_append(linehits, hit);
- }
- }
- }
- }
- /* now face hits; don't add if a vertex or edge in face should have hit */
- for (val = BLI_smallhash_iternew(&faces, &hiter, (uintptr_t *)&f); val;
- val = BLI_smallhash_iternext(&hiter, (uintptr_t *)&f))
- {
- float p[3], p_cage[3];
-
- if (use_hit_prev && knife_ray_intersect_face(kcd, s1, v1, v3, f, face_tol_sq, p, p_cage)) {
- if (point_is_visible(kcd, p_cage, s1, (BMElem *)f)) {
- memset(&hit, 0, sizeof(hit));
- hit.f = f;
- copy_v3_v3(hit.hit, p);
- copy_v3_v3(hit.cagehit, p_cage);
- copy_v2_v2(hit.schit, s1);
- set_linehit_depth(kcd, &hit);
- BLI_array_append(linehits, hit);
- }
- }
-
- if (use_hit_curr && knife_ray_intersect_face(kcd, s2, v2, v4, f, face_tol_sq, p, p_cage)) {
- if (point_is_visible(kcd, p_cage, s2, (BMElem *)f)) {
- memset(&hit, 0, sizeof(hit));
- hit.f = f;
- copy_v3_v3(hit.hit, p);
- copy_v3_v3(hit.cagehit, p_cage);
- copy_v2_v2(hit.schit, s2);
- set_linehit_depth(kcd, &hit);
- BLI_array_append(linehits, hit);
- }
- }
- }
-
- kcd->linehits = linehits;
- kcd->totlinehit = BLI_array_len(linehits);
-
- /* find position along screen line, used for sorting */
- for (i = 0; i < kcd->totlinehit; i++) {
- KnifeLineHit *lh = kcd->linehits + i;
-
- lh->l = len_v2v2(lh->schit, s1) / len_v2v2(s2, s1);
- }
-
- BLI_smallhash_release(&faces);
- BLI_smallhash_release(&kfes);
- BLI_smallhash_release(&kfvs);
- BLI_bvhtree_free(planetree);
- if (results)
- MEM_freeN(results);
-}
-
-static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2], const float ofs,
- float r_origin[3], 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);
-
- /* transform into object space */
- invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
-
- mul_m4_v3(kcd->ob->imat, r_origin);
- mul_m4_v3(kcd->ob->imat, r_origin_ofs);
-}
-
-static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float cageco[3], bool *is_space)
-{
- BMFace *f;
- float dist = KMAXDIST;
- float origin[3];
- float origin_ofs[3];
- float ray[3], ray_normal[3];
-
- /* unproject to find view ray */
- knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
- sub_v3_v3v3(ray, origin_ofs, origin);
- normalize_v3_v3(ray_normal, ray);
-
- f = BKE_bmbvh_ray_cast(kcd->bmbvh, origin, ray_normal, 0.0f, NULL, co, cageco);
-
- if (f && kcd->only_select && BM_elem_flag_test(f, BM_ELEM_SELECT) == 0) {
- f = NULL;
- }
-
- if (is_space)
- *is_space = !f;
-
- if (!f) {
- if (kcd->is_interactive) {
- /* try to use backbuffer selection method if ray casting failed */
- f = EDBM_face_find_nearest(&kcd->vc, &dist);
-
- /* cheat for now; just put in the origin instead
- * of a true coordinate on the face.
- * This just puts a point 1.0f infront of the view. */
- add_v3_v3v3(co, origin, ray);
- }
- }
-
- return f;
+ SmallHash faces, kfes, kfvs;
+ float v1[3], v2[3], v3[3], v4[3], s1[2], s2[2];
+ BVHTree *planetree, *tree;
+ BVHTreeOverlap *results, *result;
+ BMLoop **ls;
+ BMFace *f;
+ KnifeEdge *kfe;
+ KnifeVert *v;
+ ListBase *lst;
+ Ref *ref;
+ KnifeLineHit *linehits = NULL;
+ BLI_array_declare(linehits);
+ SmallHashIter hiter;
+ KnifeLineHit hit;
+ void *val;
+ void **val_p;
+ float plane_cos[12];
+ float s[2], se1[2], se2[2], sint[2];
+ float r1[3], r2[3];
+ float d, d1, d2, lambda;
+ float vert_tol, vert_tol_sq;
+ float line_tol, line_tol_sq;
+ float face_tol, face_tol_sq;
+ int isect_kind;
+ unsigned int tot;
+ int i;
+ const bool use_hit_prev = true;
+ const bool use_hit_curr = (kcd->is_drag_hold == false);
+
+ if (kcd->linehits) {
+ MEM_freeN(kcd->linehits);
+ kcd->linehits = NULL;
+ kcd->totlinehit = 0;
+ }
+
+ copy_v3_v3(v1, kcd->prev.cage);
+ copy_v3_v3(v2, kcd->curr.cage);
+
+ /* project screen line's 3d coordinates back into 2d */
+ knife_project_v2(kcd, v1, s1);
+ knife_project_v2(kcd, v2, s2);
+
+ if (kcd->is_interactive) {
+ if (len_squared_v2v2(s1, s2) < 1.0f) {
+ return;
+ }
+ }
+ else {
+ if (len_squared_v2v2(s1, s2) < KNIFE_FLT_EPS_SQUARED) {
+ return;
+ }
+ }
+
+ /* 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);
+
+ mul_m4_v3(kcd->ob->imat, v1);
+ mul_m4_v3(kcd->ob->imat, v2);
+ mul_m4_v3(kcd->ob->imat, v3);
+ mul_m4_v3(kcd->ob->imat, v4);
+
+ /* numeric error, 'v1' -> 'v2', 'v2' -> 'v4' can end up being ~2000 units apart in otho mode
+ * (from ED_view3d_win_to_segment_clipped() above)
+ * this gives precision error; rather then solving properly
+ * (which may involve using doubles everywhere!),
+ * limit the distance between these points */
+ if (kcd->is_ortho && (kcd->vc.rv3d->persp != RV3D_CAMOB)) {
+ if (kcd->ortho_extent == 0.0f)
+ calc_ortho_extent(kcd);
+ clip_to_ortho_planes(v1, v3, kcd->ortho_extent_center, kcd->ortho_extent + 10.0f);
+ clip_to_ortho_planes(v2, v4, kcd->ortho_extent_center, kcd->ortho_extent + 10.0f);
+ }
+
+ /* First use bvh tree to find faces, knife edges, and knife verts that might
+ * intersect the cut plane with rays v1-v3 and v2-v4.
+ * This deduplicates the candidates before doing more expensive intersection tests. */
+
+ tree = BKE_bmbvh_tree_get(kcd->bmbvh);
+ planetree = BLI_bvhtree_new(4, FLT_EPSILON * 4, 8, 8);
+ copy_v3_v3(plane_cos + 0, v1);
+ copy_v3_v3(plane_cos + 3, v2);
+ copy_v3_v3(plane_cos + 6, v3);
+ copy_v3_v3(plane_cos + 9, v4);
+ BLI_bvhtree_insert(planetree, 0, plane_cos, 4);
+ BLI_bvhtree_balance(planetree);
+
+ results = BLI_bvhtree_overlap(tree, planetree, &tot, NULL, NULL);
+ if (!results) {
+ BLI_bvhtree_free(planetree);
+ return;
+ }
+
+ BLI_smallhash_init(&faces);
+ BLI_smallhash_init(&kfes);
+ BLI_smallhash_init(&kfvs);
+
+ for (i = 0, result = results; i < tot; i++, result++) {
+ ls = (BMLoop **)kcd->em->looptris[result->indexA];
+ f = ls[0]->f;
+ set_lowest_face_tri(kcd, f, result->indexA);
+
+ /* occlude but never cut unselected faces (when only_select is used) */
+ if (kcd->only_select && !BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ continue;
+ }
+ /* for faces, store index of lowest hit looptri in hash */
+ if (BLI_smallhash_haskey(&faces, (uintptr_t)f)) {
+ continue;
+ }
+ /* don't care what the value is except that it is non-NULL, for iterator */
+ BLI_smallhash_insert(&faces, (uintptr_t)f, f);
+
+ lst = knife_get_face_kedges(kcd, f);
+ for (ref = lst->first; ref; ref = ref->next) {
+ kfe = ref->ref;
+ if (BLI_smallhash_haskey(&kfes, (uintptr_t)kfe))
+ continue;
+ BLI_smallhash_insert(&kfes, (uintptr_t)kfe, kfe);
+ v = kfe->v1;
+ BLI_smallhash_reinsert(&kfvs, (uintptr_t)v, v);
+ v = kfe->v2;
+ BLI_smallhash_reinsert(&kfvs, (uintptr_t)v, v);
+ }
+ }
+
+ /* Now go through the candidates and find intersections */
+ /* These tolerances, in screen space, are for intermediate hits, as ends are already snapped to screen */
+
+ if (kcd->is_interactive) {
+ vert_tol = KNIFE_FLT_EPS_PX_VERT;
+ line_tol = KNIFE_FLT_EPS_PX_EDGE;
+ face_tol = KNIFE_FLT_EPS_PX_FACE;
+ }
+ else {
+ /* Use 1/100th of a pixel, see T43896 (too big), T47910 (too small).
+ *
+ * Update, leave this as is until we investigate not using pixel coords for geometry calculations: T48023
+ */
+ vert_tol = line_tol = face_tol = 0.5f;
+ }
+
+ vert_tol_sq = vert_tol * vert_tol;
+ line_tol_sq = line_tol * line_tol;
+ face_tol_sq = face_tol * face_tol;
+
+ /* Assume these tolerances swamp floating point rounding errors in calculations below */
+
+ /* first look for vertex hits */
+ for (val_p = BLI_smallhash_iternew_p(&kfvs, &hiter, (uintptr_t *)&v); val_p;
+ val_p = BLI_smallhash_iternext_p(&hiter, (uintptr_t *)&v)) {
+ KnifeEdge *kfe_hit = NULL;
+
+ knife_project_v2(kcd, v->cageco, s);
+ d = dist_squared_to_line_segment_v2(s, s1, s2);
+ if ((d <= vert_tol_sq) &&
+ (point_is_visible(kcd, v->cageco, s, bm_elem_from_knife_vert(v, &kfe_hit)))) {
+ memset(&hit, 0, sizeof(hit));
+ hit.v = v;
+
+ /* If this isn't from an existing BMVert, it may have been added to a BMEdge originally.
+ * knowing if the hit comes from an edge is important for edge-in-face checks later on
+ * see: #knife_add_single_cut -> #knife_verts_edge_in_face, T42611 */
+ if (kfe_hit) {
+ hit.kfe = kfe_hit;
+ }
+
+ copy_v3_v3(hit.hit, v->co);
+ copy_v3_v3(hit.cagehit, v->cageco);
+ copy_v2_v2(hit.schit, s);
+ set_linehit_depth(kcd, &hit);
+ BLI_array_append(linehits, hit);
+ }
+ else {
+ /* note that these vertes aren't used */
+ *val_p = NULL;
+ }
+ }
+
+ /* now edge hits; don't add if a vertex at end of edge should have hit */
+ for (val = BLI_smallhash_iternew(&kfes, &hiter, (uintptr_t *)&kfe); val;
+ val = BLI_smallhash_iternext(&hiter, (uintptr_t *)&kfe)) {
+ int kfe_verts_in_cut;
+ /* if we intersect both verts, don't attempt to intersect the edge */
+
+ kfe_verts_in_cut = (BLI_smallhash_lookup(&kfvs, (intptr_t)kfe->v1) != NULL) +
+ (BLI_smallhash_lookup(&kfvs, (intptr_t)kfe->v2) != NULL);
+
+ if (kfe_verts_in_cut == 2) {
+ continue;
+ }
+
+ knife_project_v2(kcd, kfe->v1->cageco, se1);
+ knife_project_v2(kcd, kfe->v2->cageco, se2);
+ isect_kind = (kfe_verts_in_cut) ? -1 : isect_seg_seg_v2_point(s1, s2, se1, se2, sint);
+ if (isect_kind == -1) {
+ /* isect_seg_seg_v2_simple doesn't do tolerance test around ends of s1-s2 */
+ closest_to_line_segment_v2(sint, s1, se1, se2);
+ if (len_squared_v2v2(sint, s1) <= line_tol_sq)
+ isect_kind = 1;
+ else {
+ closest_to_line_segment_v2(sint, s2, se1, se2);
+ if (len_squared_v2v2(sint, s2) <= line_tol_sq)
+ isect_kind = 1;
+ }
+ }
+ if (isect_kind == 1) {
+ d1 = len_v2v2(sint, se1);
+ d2 = len_v2v2(se2, se1);
+ if (!(d1 <= line_tol || d2 <= line_tol || fabsf(d1 - d2) <= line_tol)) {
+ float p_cage[3], p_cage_tmp[3];
+ lambda = d1 / d2;
+ /* Can't just interpolate between ends of kfe because
+ * that doesn't work with perspective transformation.
+ * Need to find 3d intersection of ray through sint */
+ knife_input_ray_segment(kcd, sint, 1.0f, r1, r2);
+ isect_kind = isect_line_line_v3(
+ kfe->v1->cageco, kfe->v2->cageco, r1, r2, p_cage, p_cage_tmp);
+ if (isect_kind >= 1 && point_is_visible(kcd, p_cage, sint, bm_elem_from_knife_edge(kfe))) {
+ memset(&hit, 0, sizeof(hit));
+ if (kcd->snap_midpoints) {
+ /* choose intermediate point snap too */
+ mid_v3_v3v3(p_cage, kfe->v1->cageco, kfe->v2->cageco);
+ mid_v2_v2v2(sint, se1, se2);
+ lambda = 0.5f;
+ }
+ hit.kfe = kfe;
+ transform_point_by_seg_v3(
+ hit.hit, p_cage, kfe->v1->co, kfe->v2->co, kfe->v1->cageco, kfe->v2->cageco);
+ copy_v3_v3(hit.cagehit, p_cage);
+ copy_v2_v2(hit.schit, sint);
+ hit.perc = lambda;
+ set_linehit_depth(kcd, &hit);
+ BLI_array_append(linehits, hit);
+ }
+ }
+ }
+ }
+ /* now face hits; don't add if a vertex or edge in face should have hit */
+ for (val = BLI_smallhash_iternew(&faces, &hiter, (uintptr_t *)&f); val;
+ val = BLI_smallhash_iternext(&hiter, (uintptr_t *)&f)) {
+ float p[3], p_cage[3];
+
+ if (use_hit_prev && knife_ray_intersect_face(kcd, s1, v1, v3, f, face_tol_sq, p, p_cage)) {
+ if (point_is_visible(kcd, p_cage, s1, (BMElem *)f)) {
+ memset(&hit, 0, sizeof(hit));
+ hit.f = f;
+ copy_v3_v3(hit.hit, p);
+ copy_v3_v3(hit.cagehit, p_cage);
+ copy_v2_v2(hit.schit, s1);
+ set_linehit_depth(kcd, &hit);
+ BLI_array_append(linehits, hit);
+ }
+ }
+
+ if (use_hit_curr && knife_ray_intersect_face(kcd, s2, v2, v4, f, face_tol_sq, p, p_cage)) {
+ if (point_is_visible(kcd, p_cage, s2, (BMElem *)f)) {
+ memset(&hit, 0, sizeof(hit));
+ hit.f = f;
+ copy_v3_v3(hit.hit, p);
+ copy_v3_v3(hit.cagehit, p_cage);
+ copy_v2_v2(hit.schit, s2);
+ set_linehit_depth(kcd, &hit);
+ BLI_array_append(linehits, hit);
+ }
+ }
+ }
+
+ kcd->linehits = linehits;
+ kcd->totlinehit = BLI_array_len(linehits);
+
+ /* find position along screen line, used for sorting */
+ for (i = 0; i < kcd->totlinehit; i++) {
+ KnifeLineHit *lh = kcd->linehits + i;
+
+ lh->l = len_v2v2(lh->schit, s1) / len_v2v2(s2, s1);
+ }
+
+ BLI_smallhash_release(&faces);
+ BLI_smallhash_release(&kfes);
+ BLI_smallhash_release(&kfvs);
+ BLI_bvhtree_free(planetree);
+ if (results)
+ MEM_freeN(results);
+}
+
+static void knife_input_ray_segment(KnifeTool_OpData *kcd,
+ const float mval[2],
+ const float ofs,
+ float r_origin[3],
+ 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);
+
+ /* transform into object space */
+ invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
+
+ mul_m4_v3(kcd->ob->imat, r_origin);
+ mul_m4_v3(kcd->ob->imat, r_origin_ofs);
+}
+
+static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd,
+ float co[3],
+ float cageco[3],
+ bool *is_space)
+{
+ BMFace *f;
+ float dist = KMAXDIST;
+ float origin[3];
+ float origin_ofs[3];
+ float ray[3], ray_normal[3];
+
+ /* unproject to find view ray */
+ knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
+ sub_v3_v3v3(ray, origin_ofs, origin);
+ normalize_v3_v3(ray_normal, ray);
+
+ f = BKE_bmbvh_ray_cast(kcd->bmbvh, origin, ray_normal, 0.0f, NULL, co, cageco);
+
+ if (f && kcd->only_select && BM_elem_flag_test(f, BM_ELEM_SELECT) == 0) {
+ f = NULL;
+ }
+
+ if (is_space)
+ *is_space = !f;
+
+ if (!f) {
+ if (kcd->is_interactive) {
+ /* try to use backbuffer selection method if ray casting failed */
+ f = EDBM_face_find_nearest(&kcd->vc, &dist);
+
+ /* cheat for now; just put in the origin instead
+ * of a true coordinate on the face.
+ * This just puts a point 1.0f infront of the view. */
+ add_v3_v3v3(co, origin, ray);
+ }
+ }
+
+ return f;
}
/* find the 2d screen space density of vertices within a radius. used to scale snapping
* distance for picking edges/verts.*/
static int knife_sample_screen_density(KnifeTool_OpData *kcd, const float radius)
{
- BMFace *f;
- bool is_space;
- float co[3], cageco[3], sco[2];
+ BMFace *f;
+ bool is_space;
+ float co[3], cageco[3], sco[2];
- BLI_assert(kcd->is_interactive == true);
+ BLI_assert(kcd->is_interactive == true);
- f = knife_find_closest_face(kcd, co, cageco, &is_space);
+ f = knife_find_closest_face(kcd, co, cageco, &is_space);
- if (f && !is_space) {
- const float radius_sq = radius * radius;
- ListBase *lst;
- Ref *ref;
- float dis_sq;
- int c = 0;
+ if (f && !is_space) {
+ const float radius_sq = radius * radius;
+ ListBase *lst;
+ Ref *ref;
+ float dis_sq;
+ int c = 0;
- knife_project_v2(kcd, cageco, sco);
+ knife_project_v2(kcd, cageco, sco);
- lst = knife_get_face_kedges(kcd, f);
- for (ref = lst->first; ref; ref = ref->next) {
- KnifeEdge *kfe = ref->ref;
- int i;
+ lst = knife_get_face_kedges(kcd, f);
+ for (ref = lst->first; ref; ref = ref->next) {
+ KnifeEdge *kfe = ref->ref;
+ int i;
- for (i = 0; i < 2; i++) {
- KnifeVert *kfv = i ? kfe->v2 : kfe->v1;
+ for (i = 0; i < 2; i++) {
+ KnifeVert *kfv = i ? kfe->v2 : kfe->v1;
- knife_project_v2(kcd, kfv->cageco, kfv->sco);
+ knife_project_v2(kcd, kfv->cageco, kfv->sco);
- dis_sq = len_squared_v2v2(kfv->sco, sco);
- if (dis_sq < radius_sq) {
- if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
- if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, true) == 0) {
- c++;
- }
- }
- else {
- c++;
- }
- }
- }
- }
+ dis_sq = len_squared_v2v2(kfv->sco, sco);
+ if (dis_sq < radius_sq) {
+ if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
+ if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, true) == 0) {
+ c++;
+ }
+ }
+ else {
+ c++;
+ }
+ }
+ }
+ }
- return c;
- }
+ return c;
+ }
- return 0;
+ return 0;
}
/* returns snapping distance for edges/verts, scaled by the density of the
* surrounding mesh (in screen space)*/
static float knife_snap_size(KnifeTool_OpData *kcd, float maxsize)
{
- float density = (float)knife_sample_screen_density(kcd, maxsize * 2.0f);
+ float density = (float)knife_sample_screen_density(kcd, maxsize * 2.0f);
- return min_ff(maxsize / (density * 0.5f), maxsize);
+ return min_ff(maxsize / (density * 0.5f), maxsize);
}
/* p is closest point on edge to the mouse cursor */
-static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], float cagep[3],
- BMFace **fptr, bool *is_space)
-{
- BMFace *f;
- float co[3], cageco[3], sco[2];
- float maxdist;
-
- if (kcd->is_interactive) {
- maxdist = knife_snap_size(kcd, kcd->ethresh);
-
- if (kcd->ignore_vert_snapping) {
- maxdist *= 0.5f;
- }
- }
- else {
- maxdist = KNIFE_FLT_EPS;
- }
-
- f = knife_find_closest_face(kcd, co, cageco, NULL);
- *is_space = !f;
-
- kcd->curr.bmface = f;
-
- if (f) {
- const float maxdist_sq = maxdist * maxdist;
- KnifeEdge *cure = NULL;
- float cur_cagep[3];
- ListBase *lst;
- Ref *ref;
- float dis_sq, curdis_sq = FLT_MAX;
-
- /* set p to co, in case we don't find anything, means a face cut */
- copy_v3_v3(p, co);
- copy_v3_v3(cagep, cageco);
-
- knife_project_v2(kcd, cageco, sco);
-
- /* look through all edges associated with this face */
- lst = knife_get_face_kedges(kcd, f);
- for (ref = lst->first; ref; ref = ref->next) {
- KnifeEdge *kfe = ref->ref;
- float test_cagep[3];
- float lambda;
-
- /* project edge vertices into screen space */
- knife_project_v2(kcd, kfe->v1->cageco, kfe->v1->sco);
- knife_project_v2(kcd, kfe->v2->cageco, kfe->v2->sco);
-
- /* check if we're close enough and calculate 'lambda' */
- if (kcd->is_angle_snapping) {
- /* if snapping, check we're in bounds */
- float sco_snap[2];
- isect_line_line_v2_point(kfe->v1->sco, kfe->v2->sco, kcd->prev.mval, kcd->curr.mval, sco_snap);
- lambda = line_point_factor_v2(sco_snap, kfe->v1->sco, kfe->v2->sco);
-
- /* be strict about angle-snapping within edge */
- if ((lambda < 0.0f - KNIFE_FLT_EPSBIG) || (lambda > 1.0f + KNIFE_FLT_EPSBIG)) {
- continue;
- }
-
- dis_sq = len_squared_v2v2(sco, sco_snap);
- if (dis_sq < curdis_sq && dis_sq < maxdist_sq) {
- /* we already have 'lambda' */
- }
- else {
- continue;
- }
- }
- else {
- dis_sq = dist_squared_to_line_segment_v2(sco, kfe->v1->sco, kfe->v2->sco);
- if (dis_sq < curdis_sq && dis_sq < maxdist_sq) {
- lambda = line_point_factor_v2(sco, kfe->v1->sco, kfe->v2->sco);
- }
- else {
- continue;
- }
- }
-
- /* now we have 'lambda' calculated (in screen-space) */
- knife_interp_v3_v3v3(kcd, test_cagep, kfe->v1->cageco, kfe->v2->cageco, lambda);
-
- if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
- /* check we're in the view */
- if (ED_view3d_clipping_test(kcd->vc.rv3d, test_cagep, true)) {
- continue;
- }
- }
-
- cure = kfe;
- curdis_sq = dis_sq;
- copy_v3_v3(cur_cagep, test_cagep);
- }
-
- if (fptr)
- *fptr = f;
-
- if (cure) {
- if (!kcd->ignore_edge_snapping || !(cure->e)) {
- KnifeVert *edgesnap = NULL;
-
- if (kcd->snap_midpoints) {
- mid_v3_v3v3(p, cure->v1->co, cure->v2->co);
- mid_v3_v3v3(cagep, cure->v1->cageco, cure->v2->cageco);
- }
- else {
- float lambda = line_point_factor_v3(cur_cagep, cure->v1->cageco, cure->v2->cageco);
- copy_v3_v3(cagep, cur_cagep);
- interp_v3_v3v3(p, cure->v1->co, cure->v2->co, lambda);
- }
-
- /* update mouse coordinates to the snapped-to edge's screen coordinates
- * this is important for angle snap, which uses the previous mouse position */
- edgesnap = new_knife_vert(kcd, p, cagep);
- kcd->curr.mval[0] = edgesnap->sco[0];
- kcd->curr.mval[1] = edgesnap->sco[1];
-
- }
- else {
- return NULL;
- }
- }
-
- return cure;
- }
-
- if (fptr)
- *fptr = NULL;
-
- return NULL;
+static KnifeEdge *knife_find_closest_edge(
+ KnifeTool_OpData *kcd, float p[3], float cagep[3], BMFace **fptr, bool *is_space)
+{
+ BMFace *f;
+ float co[3], cageco[3], sco[2];
+ float maxdist;
+
+ if (kcd->is_interactive) {
+ maxdist = knife_snap_size(kcd, kcd->ethresh);
+
+ if (kcd->ignore_vert_snapping) {
+ maxdist *= 0.5f;
+ }
+ }
+ else {
+ maxdist = KNIFE_FLT_EPS;
+ }
+
+ f = knife_find_closest_face(kcd, co, cageco, NULL);
+ *is_space = !f;
+
+ kcd->curr.bmface = f;
+
+ if (f) {
+ const float maxdist_sq = maxdist * maxdist;
+ KnifeEdge *cure = NULL;
+ float cur_cagep[3];
+ ListBase *lst;
+ Ref *ref;
+ float dis_sq, curdis_sq = FLT_MAX;
+
+ /* set p to co, in case we don't find anything, means a face cut */
+ copy_v3_v3(p, co);
+ copy_v3_v3(cagep, cageco);
+
+ knife_project_v2(kcd, cageco, sco);
+
+ /* look through all edges associated with this face */
+ lst = knife_get_face_kedges(kcd, f);
+ for (ref = lst->first; ref; ref = ref->next) {
+ KnifeEdge *kfe = ref->ref;
+ float test_cagep[3];
+ float lambda;
+
+ /* project edge vertices into screen space */
+ knife_project_v2(kcd, kfe->v1->cageco, kfe->v1->sco);
+ knife_project_v2(kcd, kfe->v2->cageco, kfe->v2->sco);
+
+ /* check if we're close enough and calculate 'lambda' */
+ if (kcd->is_angle_snapping) {
+ /* if snapping, check we're in bounds */
+ float sco_snap[2];
+ isect_line_line_v2_point(
+ kfe->v1->sco, kfe->v2->sco, kcd->prev.mval, kcd->curr.mval, sco_snap);
+ lambda = line_point_factor_v2(sco_snap, kfe->v1->sco, kfe->v2->sco);
+
+ /* be strict about angle-snapping within edge */
+ if ((lambda < 0.0f - KNIFE_FLT_EPSBIG) || (lambda > 1.0f + KNIFE_FLT_EPSBIG)) {
+ continue;
+ }
+
+ dis_sq = len_squared_v2v2(sco, sco_snap);
+ if (dis_sq < curdis_sq && dis_sq < maxdist_sq) {
+ /* we already have 'lambda' */
+ }
+ else {
+ continue;
+ }
+ }
+ else {
+ dis_sq = dist_squared_to_line_segment_v2(sco, kfe->v1->sco, kfe->v2->sco);
+ if (dis_sq < curdis_sq && dis_sq < maxdist_sq) {
+ lambda = line_point_factor_v2(sco, kfe->v1->sco, kfe->v2->sco);
+ }
+ else {
+ continue;
+ }
+ }
+
+ /* now we have 'lambda' calculated (in screen-space) */
+ knife_interp_v3_v3v3(kcd, test_cagep, kfe->v1->cageco, kfe->v2->cageco, lambda);
+
+ if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
+ /* check we're in the view */
+ if (ED_view3d_clipping_test(kcd->vc.rv3d, test_cagep, true)) {
+ continue;
+ }
+ }
+
+ cure = kfe;
+ curdis_sq = dis_sq;
+ copy_v3_v3(cur_cagep, test_cagep);
+ }
+
+ if (fptr)
+ *fptr = f;
+
+ if (cure) {
+ if (!kcd->ignore_edge_snapping || !(cure->e)) {
+ KnifeVert *edgesnap = NULL;
+
+ if (kcd->snap_midpoints) {
+ mid_v3_v3v3(p, cure->v1->co, cure->v2->co);
+ mid_v3_v3v3(cagep, cure->v1->cageco, cure->v2->cageco);
+ }
+ else {
+ float lambda = line_point_factor_v3(cur_cagep, cure->v1->cageco, cure->v2->cageco);
+ copy_v3_v3(cagep, cur_cagep);
+ interp_v3_v3v3(p, cure->v1->co, cure->v2->co, lambda);
+ }
+
+ /* update mouse coordinates to the snapped-to edge's screen coordinates
+ * this is important for angle snap, which uses the previous mouse position */
+ edgesnap = new_knife_vert(kcd, p, cagep);
+ kcd->curr.mval[0] = edgesnap->sco[0];
+ kcd->curr.mval[1] = edgesnap->sco[1];
+ }
+ else {
+ return NULL;
+ }
+ }
+
+ return cure;
+ }
+
+ if (fptr)
+ *fptr = NULL;
+
+ return NULL;
}
/* find a vertex near the mouse cursor, if it exists */
-static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], float cagep[3], BMFace **fptr,
- bool *is_space)
-{
- BMFace *f;
- float co[3], cageco[3], sco[2];
- float maxdist;
-
- if (kcd->is_interactive) {
- maxdist = knife_snap_size(kcd, kcd->vthresh);
- if (kcd->ignore_vert_snapping) {
- maxdist *= 0.5f;
- }
- }
- else {
- maxdist = KNIFE_FLT_EPS;
- }
-
- f = knife_find_closest_face(kcd, co, cageco, is_space);
-
- kcd->curr.bmface = f;
-
- if (f) {
- const float maxdist_sq = maxdist * maxdist;
- ListBase *lst;
- Ref *ref;
- KnifeVert *curv = NULL;
- float dis_sq, curdis_sq = FLT_MAX;
-
- /* set p to co, in case we don't find anything, means a face cut */
- copy_v3_v3(p, co);
- copy_v3_v3(cagep, cageco);
-
- knife_project_v2(kcd, cageco, sco);
-
- lst = knife_get_face_kedges(kcd, f);
- for (ref = lst->first; ref; ref = ref->next) {
- KnifeEdge *kfe = ref->ref;
- int i;
-
- for (i = 0; i < 2; i++) {
- KnifeVert *kfv = i ? kfe->v2 : kfe->v1;
-
- knife_project_v2(kcd, kfv->cageco, kfv->sco);
-
- /* be strict about angle snapping, the vertex needs to be very close to the angle,
- * or we ignore */
- if (kcd->is_angle_snapping) {
- if (dist_squared_to_line_segment_v2(kfv->sco, kcd->prev.mval, kcd->curr.mval) > KNIFE_FLT_EPSBIG) {
- continue;
- }
- }
-
- dis_sq = len_squared_v2v2(kfv->sco, sco);
- if (dis_sq < curdis_sq && dis_sq < maxdist_sq) {
- if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
- if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, true) == 0) {
- curv = kfv;
- curdis_sq = dis_sq;
- }
- }
- else {
- curv = kfv;
- curdis_sq = dis_sq;
- }
- }
- }
- }
-
- if (!kcd->ignore_vert_snapping || !(curv && curv->v)) {
- if (fptr)
- *fptr = f;
-
- if (curv) {
- copy_v3_v3(p, curv->co);
- copy_v3_v3(cagep, curv->cageco);
-
- /* update mouse coordinates to the snapped-to vertex's screen coordinates
- * this is important for angle snap, which uses the previous mouse position */
- kcd->curr.mval[0] = curv->sco[0];
- kcd->curr.mval[1] = curv->sco[1];
- }
-
- return curv;
- }
- else {
- if (fptr)
- *fptr = f;
-
- return NULL;
- }
- }
-
- if (fptr)
- *fptr = NULL;
-
- return NULL;
+static KnifeVert *knife_find_closest_vert(
+ KnifeTool_OpData *kcd, float p[3], float cagep[3], BMFace **fptr, bool *is_space)
+{
+ BMFace *f;
+ float co[3], cageco[3], sco[2];
+ float maxdist;
+
+ if (kcd->is_interactive) {
+ maxdist = knife_snap_size(kcd, kcd->vthresh);
+ if (kcd->ignore_vert_snapping) {
+ maxdist *= 0.5f;
+ }
+ }
+ else {
+ maxdist = KNIFE_FLT_EPS;
+ }
+
+ f = knife_find_closest_face(kcd, co, cageco, is_space);
+
+ kcd->curr.bmface = f;
+
+ if (f) {
+ const float maxdist_sq = maxdist * maxdist;
+ ListBase *lst;
+ Ref *ref;
+ KnifeVert *curv = NULL;
+ float dis_sq, curdis_sq = FLT_MAX;
+
+ /* set p to co, in case we don't find anything, means a face cut */
+ copy_v3_v3(p, co);
+ copy_v3_v3(cagep, cageco);
+
+ knife_project_v2(kcd, cageco, sco);
+
+ lst = knife_get_face_kedges(kcd, f);
+ for (ref = lst->first; ref; ref = ref->next) {
+ KnifeEdge *kfe = ref->ref;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ KnifeVert *kfv = i ? kfe->v2 : kfe->v1;
+
+ knife_project_v2(kcd, kfv->cageco, kfv->sco);
+
+ /* be strict about angle snapping, the vertex needs to be very close to the angle,
+ * or we ignore */
+ if (kcd->is_angle_snapping) {
+ if (dist_squared_to_line_segment_v2(kfv->sco, kcd->prev.mval, kcd->curr.mval) >
+ KNIFE_FLT_EPSBIG) {
+ continue;
+ }
+ }
+
+ dis_sq = len_squared_v2v2(kfv->sco, sco);
+ if (dis_sq < curdis_sq && dis_sq < maxdist_sq) {
+ if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
+ if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, true) == 0) {
+ curv = kfv;
+ curdis_sq = dis_sq;
+ }
+ }
+ else {
+ curv = kfv;
+ curdis_sq = dis_sq;
+ }
+ }
+ }
+ }
+
+ if (!kcd->ignore_vert_snapping || !(curv && curv->v)) {
+ if (fptr)
+ *fptr = f;
+
+ if (curv) {
+ copy_v3_v3(p, curv->co);
+ copy_v3_v3(cagep, curv->cageco);
+
+ /* update mouse coordinates to the snapped-to vertex's screen coordinates
+ * this is important for angle snap, which uses the previous mouse position */
+ kcd->curr.mval[0] = curv->sco[0];
+ kcd->curr.mval[1] = curv->sco[1];
+ }
+
+ return curv;
+ }
+ else {
+ if (fptr)
+ *fptr = f;
+
+ return NULL;
+ }
+ }
+
+ if (fptr)
+ *fptr = NULL;
+
+ return NULL;
}
/**
@@ -2149,859 +2166,863 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo
*/
static float snap_v2_angle(float r[2], const float v[2], const float v_ref[2], float angle_snap)
{
- float m2[2][2];
- float v_unit[2];
- float angle, angle_delta;
+ float m2[2][2];
+ float v_unit[2];
+ float angle, angle_delta;
- BLI_ASSERT_UNIT_V2(v_ref);
+ BLI_ASSERT_UNIT_V2(v_ref);
- normalize_v2_v2(v_unit, v);
- angle = angle_signed_v2v2(v_unit, v_ref);
- angle_delta = (roundf(angle / angle_snap) * angle_snap) - angle;
- angle_to_mat2(m2, angle_delta);
+ normalize_v2_v2(v_unit, v);
+ angle = angle_signed_v2v2(v_unit, v_ref);
+ angle_delta = (roundf(angle / angle_snap) * angle_snap) - angle;
+ angle_to_mat2(m2, angle_delta);
- mul_v2_m2v2(r, m2, v);
- return angle + angle_delta;
+ mul_v2_m2v2(r, m2, v);
+ return angle + angle_delta;
}
/* update both kcd->curr.mval and kcd->mval to snap to required angle */
static bool knife_snap_angle(KnifeTool_OpData *kcd)
{
- const float dvec_ref[2] = {0.0f, 1.0f};
- float dvec[2], dvec_snap[2];
- float snap_step = DEG2RADF(45);
+ const float dvec_ref[2] = {0.0f, 1.0f};
+ float dvec[2], dvec_snap[2];
+ float snap_step = DEG2RADF(45);
- sub_v2_v2v2(dvec, kcd->curr.mval, kcd->prev.mval);
- if (is_zero_v2(dvec)) {
- return false;
- }
+ sub_v2_v2v2(dvec, kcd->curr.mval, kcd->prev.mval);
+ if (is_zero_v2(dvec)) {
+ return false;
+ }
- kcd->angle = snap_v2_angle(dvec_snap, dvec, dvec_ref, snap_step);
+ kcd->angle = snap_v2_angle(dvec_snap, dvec, dvec_ref, snap_step);
- add_v2_v2v2(kcd->curr.mval, kcd->prev.mval, dvec_snap);
+ add_v2_v2v2(kcd->curr.mval, kcd->prev.mval, dvec_snap);
- copy_v2_v2(kcd->mval, kcd->curr.mval);
+ copy_v2_v2(kcd->mval, kcd->curr.mval);
- return true;
+ return true;
}
/* update active knife edge/vert pointers */
static int knife_update_active(KnifeTool_OpData *kcd)
{
- knife_pos_data_clear(&kcd->curr);
- copy_v2_v2(kcd->curr.mval, kcd->mval);
+ knife_pos_data_clear(&kcd->curr);
+ copy_v2_v2(kcd->curr.mval, kcd->mval);
- /* view matrix may have changed, reproject */
- knife_project_v2(kcd, kcd->prev.cage, kcd->prev.mval);
+ /* view matrix may have changed, reproject */
+ knife_project_v2(kcd, kcd->prev.cage, kcd->prev.mval);
- if (kcd->angle_snapping && (kcd->mode == MODE_DRAGGING)) {
- kcd->is_angle_snapping = knife_snap_angle(kcd);
- }
- else {
- kcd->is_angle_snapping = false;
- }
+ if (kcd->angle_snapping && (kcd->mode == MODE_DRAGGING)) {
+ kcd->is_angle_snapping = knife_snap_angle(kcd);
+ }
+ else {
+ kcd->is_angle_snapping = false;
+ }
- kcd->curr.vert = knife_find_closest_vert(kcd, kcd->curr.co, kcd->curr.cage, &kcd->curr.bmface, &kcd->curr.is_space);
+ kcd->curr.vert = knife_find_closest_vert(
+ kcd, kcd->curr.co, kcd->curr.cage, &kcd->curr.bmface, &kcd->curr.is_space);
- if (!kcd->curr.vert &&
- /* no edge snapping while dragging (edges are too sticky when cuts are immediate) */
- !kcd->is_drag_hold)
- {
- kcd->curr.edge = knife_find_closest_edge(kcd, kcd->curr.co, kcd->curr.cage,
- &kcd->curr.bmface, &kcd->curr.is_space);
- }
+ if (!kcd->curr.vert &&
+ /* no edge snapping while dragging (edges are too sticky when cuts are immediate) */
+ !kcd->is_drag_hold) {
+ kcd->curr.edge = knife_find_closest_edge(
+ kcd, kcd->curr.co, kcd->curr.cage, &kcd->curr.bmface, &kcd->curr.is_space);
+ }
- /* if no hits are found this would normally default to (0, 0, 0) so instead
- * get a point at the mouse ray closest to the previous point.
- * Note that drawing lines in `free-space` isn't properly supported
- * but there's no guarantee (0, 0, 0) has any geometry either - campbell */
- if (kcd->curr.vert == NULL && kcd->curr.edge == NULL && kcd->curr.bmface == NULL) {
- float origin[3];
- float origin_ofs[3];
+ /* if no hits are found this would normally default to (0, 0, 0) so instead
+ * get a point at the mouse ray closest to the previous point.
+ * Note that drawing lines in `free-space` isn't properly supported
+ * but there's no guarantee (0, 0, 0) has any geometry either - campbell */
+ if (kcd->curr.vert == NULL && kcd->curr.edge == NULL && kcd->curr.bmface == NULL) {
+ float origin[3];
+ float origin_ofs[3];
- knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
+ knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
- if (!isect_line_plane_v3(kcd->curr.cage, origin, origin_ofs, kcd->prev.cage, kcd->proj_zaxis)) {
- copy_v3_v3(kcd->curr.cage, kcd->prev.cage);
+ if (!isect_line_plane_v3(
+ kcd->curr.cage, origin, origin_ofs, kcd->prev.cage, kcd->proj_zaxis)) {
+ copy_v3_v3(kcd->curr.cage, kcd->prev.cage);
- /* should never fail! */
- BLI_assert(0);
- }
- }
+ /* should never fail! */
+ BLI_assert(0);
+ }
+ }
- if (kcd->mode == MODE_DRAGGING) {
- knife_find_line_hits(kcd);
- }
- return 1;
+ if (kcd->mode == MODE_DRAGGING) {
+ knife_find_line_hits(kcd);
+ }
+ return 1;
}
static int sort_verts_by_dist_cb(void *co_p, const void *cur_a_p, const void *cur_b_p)
{
- const KnifeVert *cur_a = ((const Ref *)cur_a_p)->ref;
- const KnifeVert *cur_b = ((const Ref *)cur_b_p)->ref;
- const float *co = co_p;
- const float a_sq = len_squared_v3v3(co, cur_a->co);
- const float b_sq = len_squared_v3v3(co, cur_b->co);
+ const KnifeVert *cur_a = ((const Ref *)cur_a_p)->ref;
+ const KnifeVert *cur_b = ((const Ref *)cur_b_p)->ref;
+ const float *co = co_p;
+ const float a_sq = len_squared_v3v3(co, cur_a->co);
+ const float b_sq = len_squared_v3v3(co, cur_b->co);
- if (a_sq < b_sq) return -1;
- else if (a_sq > b_sq) return 1;
- else return 0;
+ if (a_sq < b_sq)
+ return -1;
+ else if (a_sq > b_sq)
+ return 1;
+ else
+ return 0;
}
static bool knife_verts_edge_in_face(KnifeVert *v1, KnifeVert *v2, BMFace *f)
{
- bool v1_inside, v2_inside;
- bool v1_inface, v2_inface;
- BMLoop *l1, *l2;
-
- if (!f || !v1 || !v2)
- return false;
-
- l1 = v1->v ? BM_face_vert_share_loop(f, v1->v) : NULL;
- l2 = v2->v ? BM_face_vert_share_loop(f, v2->v) : NULL;
-
- if ((l1 && l2) && BM_loop_is_adjacent(l1, l2)) {
- /* boundary-case, always false to avoid edge-in-face checks below */
- return false;
- }
-
- /* find out if v1 and v2, if set, are part of the face */
- v1_inface = (l1 != NULL);
- v2_inface = (l2 != NULL);
-
- /* BM_face_point_inside_test uses best-axis projection so this isn't most accurate test... */
- v1_inside = v1_inface ? false : BM_face_point_inside_test(f, v1->co);
- v2_inside = v2_inface ? false : BM_face_point_inside_test(f, v2->co);
- if ((v1_inface && v2_inside) ||
- (v2_inface && v1_inside) ||
- (v1_inside && v2_inside))
- {
- return true;
- }
-
- if (v1_inface && v2_inface) {
- float mid[3];
- /* Can have case where v1 and v2 are on shared chain between two faces.
- * BM_face_splits_check_legal does visibility and self-intersection tests,
- * but it is expensive and maybe a bit buggy, so use a simple
- * "is the midpoint in the face" test */
- mid_v3_v3v3(mid, v1->co, v2->co);
- return BM_face_point_inside_test(f, mid);
- }
- return false;
+ bool v1_inside, v2_inside;
+ bool v1_inface, v2_inface;
+ BMLoop *l1, *l2;
+
+ if (!f || !v1 || !v2)
+ return false;
+
+ l1 = v1->v ? BM_face_vert_share_loop(f, v1->v) : NULL;
+ l2 = v2->v ? BM_face_vert_share_loop(f, v2->v) : NULL;
+
+ if ((l1 && l2) && BM_loop_is_adjacent(l1, l2)) {
+ /* boundary-case, always false to avoid edge-in-face checks below */
+ return false;
+ }
+
+ /* find out if v1 and v2, if set, are part of the face */
+ v1_inface = (l1 != NULL);
+ v2_inface = (l2 != NULL);
+
+ /* BM_face_point_inside_test uses best-axis projection so this isn't most accurate test... */
+ v1_inside = v1_inface ? false : BM_face_point_inside_test(f, v1->co);
+ v2_inside = v2_inface ? false : BM_face_point_inside_test(f, v2->co);
+ if ((v1_inface && v2_inside) || (v2_inface && v1_inside) || (v1_inside && v2_inside)) {
+ return true;
+ }
+
+ if (v1_inface && v2_inface) {
+ float mid[3];
+ /* Can have case where v1 and v2 are on shared chain between two faces.
+ * BM_face_splits_check_legal does visibility and self-intersection tests,
+ * but it is expensive and maybe a bit buggy, so use a simple
+ * "is the midpoint in the face" test */
+ mid_v3_v3v3(mid, v1->co, v2->co);
+ return BM_face_point_inside_test(f, mid);
+ }
+ return false;
}
static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfedges)
{
- BMesh *bm = kcd->em->bm;
- KnifeEdge *kfe;
- Ref *ref;
- int edge_array_len = BLI_listbase_count(kfedges);
- int i;
-
- BMEdge **edge_array = BLI_array_alloca(edge_array, edge_array_len);
-
- /* point to knife edges we've created edges in, edge_array aligned */
- KnifeEdge **kfe_array = BLI_array_alloca(kfe_array, edge_array_len);
-
- BLI_assert(BLI_gset_len(kcd->edgenet.edge_visit) == 0);
-
- i = 0;
- for (ref = kfedges->first; ref; ref = ref->next) {
- bool is_new_edge = false;
- kfe = ref->ref;
-
- if (kfe->e == NULL) {
- if (kfe->v1->v && kfe->v2->v) {
- kfe->e = BM_edge_exists(kfe->v1->v, kfe->v2->v);
- }
- }
-
- if (kfe->e) {
- if (BM_edge_in_face(kfe->e, f)) {
- /* shouldn't happen, but in this case - just ignore */
- continue;
- }
- }
- else {
- if (kfe->v1->v == NULL) {
- kfe->v1->v = BM_vert_create(bm, kfe->v1->co, NULL, 0);
- }
- if (kfe->v2->v == NULL) {
- kfe->v2->v = BM_vert_create(bm, kfe->v2->co, NULL, 0);
- }
- BLI_assert(kfe->e == NULL);
- kfe->e = BM_edge_create(bm, kfe->v1->v, kfe->v2->v, NULL, 0);
- if (kfe->e) {
- if (kcd->select_result || BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- BM_edge_select_set(bm, kfe->e, true);
- }
- is_new_edge = true;
- }
- }
-
- BLI_assert(kfe->e);
-
- if (BLI_gset_add(kcd->edgenet.edge_visit, kfe->e)) {
- kfe_array[i] = is_new_edge ? kfe : 0;
- edge_array[i] = kfe->e;
- i += 1;
- }
- }
-
- if (i) {
- const int edge_array_len_orig = i;
- edge_array_len = i;
+ BMesh *bm = kcd->em->bm;
+ KnifeEdge *kfe;
+ Ref *ref;
+ int edge_array_len = BLI_listbase_count(kfedges);
+ int i;
+
+ BMEdge **edge_array = BLI_array_alloca(edge_array, edge_array_len);
+
+ /* point to knife edges we've created edges in, edge_array aligned */
+ KnifeEdge **kfe_array = BLI_array_alloca(kfe_array, edge_array_len);
+
+ BLI_assert(BLI_gset_len(kcd->edgenet.edge_visit) == 0);
+
+ i = 0;
+ for (ref = kfedges->first; ref; ref = ref->next) {
+ bool is_new_edge = false;
+ kfe = ref->ref;
+
+ if (kfe->e == NULL) {
+ if (kfe->v1->v && kfe->v2->v) {
+ kfe->e = BM_edge_exists(kfe->v1->v, kfe->v2->v);
+ }
+ }
+
+ if (kfe->e) {
+ if (BM_edge_in_face(kfe->e, f)) {
+ /* shouldn't happen, but in this case - just ignore */
+ continue;
+ }
+ }
+ else {
+ if (kfe->v1->v == NULL) {
+ kfe->v1->v = BM_vert_create(bm, kfe->v1->co, NULL, 0);
+ }
+ if (kfe->v2->v == NULL) {
+ kfe->v2->v = BM_vert_create(bm, kfe->v2->co, NULL, 0);
+ }
+ BLI_assert(kfe->e == NULL);
+ kfe->e = BM_edge_create(bm, kfe->v1->v, kfe->v2->v, NULL, 0);
+ if (kfe->e) {
+ if (kcd->select_result || BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_edge_select_set(bm, kfe->e, true);
+ }
+ is_new_edge = true;
+ }
+ }
+
+ BLI_assert(kfe->e);
+
+ if (BLI_gset_add(kcd->edgenet.edge_visit, kfe->e)) {
+ kfe_array[i] = is_new_edge ? kfe : 0;
+ edge_array[i] = kfe->e;
+ i += 1;
+ }
+ }
+
+ if (i) {
+ const int edge_array_len_orig = i;
+ edge_array_len = i;
#ifdef USE_NET_ISLAND_CONNECT
- unsigned int edge_array_holes_len;
- BMEdge **edge_array_holes;
- if (BM_face_split_edgenet_connect_islands(
- bm, f,
- edge_array, edge_array_len,
- true,
- kcd->edgenet.arena,
- &edge_array_holes, &edge_array_holes_len))
- {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- for (i = edge_array_len; i < edge_array_holes_len; i++) {
- BM_edge_select_set(bm, edge_array_holes[i], true);
- }
- }
-
- edge_array_len = edge_array_holes_len;
- edge_array = edge_array_holes; /* owned by the arena */
- }
+ unsigned int edge_array_holes_len;
+ BMEdge **edge_array_holes;
+ if (BM_face_split_edgenet_connect_islands(bm,
+ f,
+ edge_array,
+ edge_array_len,
+ true,
+ kcd->edgenet.arena,
+ &edge_array_holes,
+ &edge_array_holes_len)) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ for (i = edge_array_len; i < edge_array_holes_len; i++) {
+ BM_edge_select_set(bm, edge_array_holes[i], true);
+ }
+ }
+
+ edge_array_len = edge_array_holes_len;
+ edge_array = edge_array_holes; /* owned by the arena */
+ }
#endif
- {
- BMFace **face_arr = NULL;
- int face_arr_len;
+ {
+ BMFace **face_arr = NULL;
+ int face_arr_len;
- BM_face_split_edgenet(
- bm, f, edge_array, edge_array_len,
- &face_arr, &face_arr_len);
+ BM_face_split_edgenet(bm, f, edge_array, edge_array_len, &face_arr, &face_arr_len);
- if (face_arr) {
- MEM_freeN(face_arr);
- }
- }
-
- /* remove dangling edges, not essential - but nice for users */
- for (i = 0; i < edge_array_len_orig; i++) {
- if (kfe_array[i]) {
- if (BM_edge_is_wire(kfe_array[i]->e)) {
- BM_edge_kill(bm, kfe_array[i]->e);
- kfe_array[i]->e = NULL;
- }
- }
- }
+ if (face_arr) {
+ MEM_freeN(face_arr);
+ }
+ }
+ /* remove dangling edges, not essential - but nice for users */
+ for (i = 0; i < edge_array_len_orig; i++) {
+ if (kfe_array[i]) {
+ if (BM_edge_is_wire(kfe_array[i]->e)) {
+ BM_edge_kill(bm, kfe_array[i]->e);
+ kfe_array[i]->e = NULL;
+ }
+ }
+ }
#ifdef USE_NET_ISLAND_CONNECT
- BLI_memarena_clear(kcd->edgenet.arena);
+ BLI_memarena_clear(kcd->edgenet.arena);
#endif
- }
+ }
- BLI_gset_clear(kcd->edgenet.edge_visit, NULL);
+ BLI_gset_clear(kcd->edgenet.edge_visit, NULL);
}
/* Use the network of KnifeEdges and KnifeVerts accumulated to make real BMVerts and BMEdedges */
static void knife_make_cuts(KnifeTool_OpData *kcd)
{
- BMesh *bm = kcd->em->bm;
- KnifeEdge *kfe;
- KnifeVert *kfv;
- BMFace *f;
- BMEdge *e, *enew;
- ListBase *lst;
- Ref *ref;
- float pct;
- SmallHashIter hiter;
- BLI_mempool_iter iter;
- SmallHash fhash_, *fhash = &fhash_;
- SmallHash ehash_, *ehash = &ehash_;
-
- BLI_smallhash_init(fhash);
- BLI_smallhash_init(ehash);
-
- /* put list of cutting edges for a face into fhash, keyed by face */
- BLI_mempool_iternew(kcd->kedges, &iter);
- for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) {
-
- /* select edges that lie directly on the cut */
- if (kcd->select_result) {
- if (kfe->e && kfe->is_cut) {
- BM_edge_select_set(bm, kfe->e, true);
- }
- }
-
- f = kfe->basef;
- if (!f || kfe->e)
- continue;
- lst = BLI_smallhash_lookup(fhash, (uintptr_t)f);
- if (!lst) {
- lst = knife_empty_list(kcd);
- BLI_smallhash_insert(fhash, (uintptr_t)f, lst);
- }
- knife_append_list(kcd, lst, kfe);
- }
-
- /* put list of splitting vertices for an edge into ehash, keyed by edge */
- BLI_mempool_iternew(kcd->kverts, &iter);
- for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) {
- if (kfv->v)
- continue; /* already have a BMVert */
- for (ref = kfv->edges.first; ref; ref = ref->next) {
- kfe = ref->ref;
- e = kfe->e;
- if (!e)
- continue;
- lst = BLI_smallhash_lookup(ehash, (uintptr_t)e);
- if (!lst) {
- lst = knife_empty_list(kcd);
- BLI_smallhash_insert(ehash, (uintptr_t)e, lst);
- }
- /* there can be more than one kfe in kfv's list with same e */
- if (!find_ref(lst, kfv))
- knife_append_list(kcd, lst, kfv);
- }
- }
-
- /* split bmesh edges where needed */
- for (lst = BLI_smallhash_iternew(ehash, &hiter, (uintptr_t *)&e); lst;
- lst = BLI_smallhash_iternext(&hiter, (uintptr_t *)&e))
- {
- BLI_listbase_sort_r(lst, sort_verts_by_dist_cb, e->v1->co);
-
- for (ref = lst->first; ref; ref = ref->next) {
- kfv = ref->ref;
- pct = line_point_factor_v3(kfv->co, e->v1->co, e->v2->co);
- kfv->v = BM_edge_split(bm, e, e->v1, &enew, pct);
- }
- }
-
- if (kcd->only_select) {
- EDBM_flag_disable_all(kcd->em, BM_ELEM_SELECT);
- }
-
- /* do cuts for each face */
- for (lst = BLI_smallhash_iternew(fhash, &hiter, (uintptr_t *)&f); lst;
- lst = BLI_smallhash_iternext(&hiter, (uintptr_t *)&f))
- {
- knife_make_face_cuts(kcd, f, lst);
- }
-
- BLI_smallhash_release(fhash);
- BLI_smallhash_release(ehash);
+ BMesh *bm = kcd->em->bm;
+ KnifeEdge *kfe;
+ KnifeVert *kfv;
+ BMFace *f;
+ BMEdge *e, *enew;
+ ListBase *lst;
+ Ref *ref;
+ float pct;
+ SmallHashIter hiter;
+ BLI_mempool_iter iter;
+ SmallHash fhash_, *fhash = &fhash_;
+ SmallHash ehash_, *ehash = &ehash_;
+
+ BLI_smallhash_init(fhash);
+ BLI_smallhash_init(ehash);
+
+ /* put list of cutting edges for a face into fhash, keyed by face */
+ BLI_mempool_iternew(kcd->kedges, &iter);
+ for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) {
+
+ /* select edges that lie directly on the cut */
+ if (kcd->select_result) {
+ if (kfe->e && kfe->is_cut) {
+ BM_edge_select_set(bm, kfe->e, true);
+ }
+ }
+
+ f = kfe->basef;
+ if (!f || kfe->e)
+ continue;
+ lst = BLI_smallhash_lookup(fhash, (uintptr_t)f);
+ if (!lst) {
+ lst = knife_empty_list(kcd);
+ BLI_smallhash_insert(fhash, (uintptr_t)f, lst);
+ }
+ knife_append_list(kcd, lst, kfe);
+ }
+
+ /* put list of splitting vertices for an edge into ehash, keyed by edge */
+ BLI_mempool_iternew(kcd->kverts, &iter);
+ for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) {
+ if (kfv->v)
+ continue; /* already have a BMVert */
+ for (ref = kfv->edges.first; ref; ref = ref->next) {
+ kfe = ref->ref;
+ e = kfe->e;
+ if (!e)
+ continue;
+ lst = BLI_smallhash_lookup(ehash, (uintptr_t)e);
+ if (!lst) {
+ lst = knife_empty_list(kcd);
+ BLI_smallhash_insert(ehash, (uintptr_t)e, lst);
+ }
+ /* there can be more than one kfe in kfv's list with same e */
+ if (!find_ref(lst, kfv))
+ knife_append_list(kcd, lst, kfv);
+ }
+ }
+
+ /* split bmesh edges where needed */
+ for (lst = BLI_smallhash_iternew(ehash, &hiter, (uintptr_t *)&e); lst;
+ lst = BLI_smallhash_iternext(&hiter, (uintptr_t *)&e)) {
+ BLI_listbase_sort_r(lst, sort_verts_by_dist_cb, e->v1->co);
+
+ for (ref = lst->first; ref; ref = ref->next) {
+ kfv = ref->ref;
+ pct = line_point_factor_v3(kfv->co, e->v1->co, e->v2->co);
+ kfv->v = BM_edge_split(bm, e, e->v1, &enew, pct);
+ }
+ }
+
+ if (kcd->only_select) {
+ EDBM_flag_disable_all(kcd->em, BM_ELEM_SELECT);
+ }
+
+ /* do cuts for each face */
+ for (lst = BLI_smallhash_iternew(fhash, &hiter, (uintptr_t *)&f); lst;
+ lst = BLI_smallhash_iternext(&hiter, (uintptr_t *)&f)) {
+ knife_make_face_cuts(kcd, f, lst);
+ }
+
+ BLI_smallhash_release(fhash);
+ BLI_smallhash_release(ehash);
}
/* called on tool confirmation */
static void knifetool_finish_ex(KnifeTool_OpData *kcd)
{
- knife_make_cuts(kcd);
+ knife_make_cuts(kcd);
- EDBM_selectmode_flush(kcd->em);
- EDBM_mesh_normals_update(kcd->em);
- EDBM_update_generic(kcd->em, true, true);
+ EDBM_selectmode_flush(kcd->em);
+ EDBM_mesh_normals_update(kcd->em);
+ EDBM_update_generic(kcd->em, true, true);
- /* re-tessellating makes this invalid, dont use again by accident */
- knifetool_free_bmbvh(kcd);
+ /* re-tessellating makes this invalid, dont use again by accident */
+ knifetool_free_bmbvh(kcd);
}
static void knifetool_finish(wmOperator *op)
{
- KnifeTool_OpData *kcd = op->customdata;
- knifetool_finish_ex(kcd);
+ KnifeTool_OpData *kcd = op->customdata;
+ knifetool_finish_ex(kcd);
}
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);
- invert_m4_m4(kcd->projmat_inv, kcd->projmat);
+ invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
+ ED_view3d_ob_project_mat_get(kcd->ar->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]);
- normalize_v3(kcd->proj_zaxis);
+ mul_v3_mat3_m4v3(kcd->proj_zaxis, kcd->ob->imat, kcd->vc.rv3d->viewinv[2]);
+ normalize_v3(kcd->proj_zaxis);
- kcd->is_ortho = ED_view3d_clip_range_get(kcd->vc.depsgraph,
- kcd->vc.v3d, kcd->vc.rv3d,
- &kcd->clipsta, &kcd->clipend, true);
+ kcd->is_ortho = ED_view3d_clip_range_get(
+ kcd->vc.depsgraph, kcd->vc.v3d, kcd->vc.rv3d, &kcd->clipsta, &kcd->clipend, true);
}
/* called when modal loop selection is done... */
static void knifetool_exit_ex(bContext *C, KnifeTool_OpData *kcd)
{
- if (!kcd)
- return;
+ if (!kcd)
+ return;
- if (kcd->is_interactive) {
- WM_cursor_modal_restore(CTX_wm_window(C));
+ if (kcd->is_interactive) {
+ 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);
- }
+ /* deactivate the extra drawing stuff in 3D-View */
+ ED_region_draw_cb_exit(kcd->ar->type, kcd->draw_handle);
+ }
- /* free the custom data */
- BLI_mempool_destroy(kcd->refs);
- BLI_mempool_destroy(kcd->kverts);
- BLI_mempool_destroy(kcd->kedges);
+ /* free the custom data */
+ BLI_mempool_destroy(kcd->refs);
+ BLI_mempool_destroy(kcd->kverts);
+ BLI_mempool_destroy(kcd->kedges);
- BLI_ghash_free(kcd->origedgemap, NULL, NULL);
- BLI_ghash_free(kcd->origvertmap, NULL, NULL);
- BLI_ghash_free(kcd->kedgefacemap, NULL, NULL);
- BLI_ghash_free(kcd->facetrimap, NULL, NULL);
+ BLI_ghash_free(kcd->origedgemap, NULL, NULL);
+ BLI_ghash_free(kcd->origvertmap, NULL, NULL);
+ BLI_ghash_free(kcd->kedgefacemap, NULL, NULL);
+ BLI_ghash_free(kcd->facetrimap, NULL, NULL);
- BLI_memarena_free(kcd->arena);
+ BLI_memarena_free(kcd->arena);
#ifdef USE_NET_ISLAND_CONNECT
- BLI_memarena_free(kcd->edgenet.arena);
+ BLI_memarena_free(kcd->edgenet.arena);
#endif
- BLI_gset_free(kcd->edgenet.edge_visit, NULL);
+ BLI_gset_free(kcd->edgenet.edge_visit, NULL);
- /* tag for redraw */
- ED_region_tag_redraw(kcd->ar);
+ /* tag for redraw */
+ ED_region_tag_redraw(kcd->ar);
- knifetool_free_bmbvh(kcd);
+ knifetool_free_bmbvh(kcd);
- if (kcd->linehits)
- MEM_freeN(kcd->linehits);
+ if (kcd->linehits)
+ MEM_freeN(kcd->linehits);
- /* destroy kcd itself */
- MEM_freeN(kcd);
+ /* destroy kcd itself */
+ MEM_freeN(kcd);
}
static void knifetool_exit(bContext *C, wmOperator *op)
{
- KnifeTool_OpData *kcd = op->customdata;
- knifetool_exit_ex(C, kcd);
- op->customdata = NULL;
+ KnifeTool_OpData *kcd = op->customdata;
+ knifetool_exit_ex(C, kcd);
+ op->customdata = NULL;
}
static void knifetool_update_mval(KnifeTool_OpData *kcd, const float mval[2])
{
- knife_recalc_projmat(kcd);
- copy_v2_v2(kcd->mval, mval);
+ knife_recalc_projmat(kcd);
+ copy_v2_v2(kcd->mval, mval);
- if (knife_update_active(kcd)) {
- ED_region_tag_redraw(kcd->ar);
- }
+ if (knife_update_active(kcd)) {
+ ED_region_tag_redraw(kcd->ar);
+ }
}
static void knifetool_update_mval_i(KnifeTool_OpData *kcd, const int mval_i[2])
{
- float mval[2] = {UNPACK2(mval_i)};
- knifetool_update_mval(kcd, mval);
+ float mval[2] = {UNPACK2(mval_i)};
+ knifetool_update_mval(kcd, mval);
}
static void knifetool_init_bmbvh(KnifeTool_OpData *kcd)
{
- BM_mesh_elem_index_ensure(kcd->em->bm, BM_VERT);
+ BM_mesh_elem_index_ensure(kcd->em->bm, BM_VERT);
- Scene *scene_eval = (Scene *)DEG_get_evaluated_id(kcd->vc.depsgraph, &kcd->scene->id);
- Object *obedit_eval = (Object *)DEG_get_evaluated_id(kcd->vc.depsgraph, &kcd->em->ob->id);
- BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval);
+ Scene *scene_eval = (Scene *)DEG_get_evaluated_id(kcd->vc.depsgraph, &kcd->scene->id);
+ Object *obedit_eval = (Object *)DEG_get_evaluated_id(kcd->vc.depsgraph, &kcd->em->ob->id);
+ BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval);
- kcd->cagecos = (const float (*)[3])BKE_editmesh_vertexCos_get(
- kcd->vc.depsgraph, em_eval, scene_eval, NULL);
+ kcd->cagecos = (const float(*)[3])BKE_editmesh_vertexCos_get(
+ kcd->vc.depsgraph, em_eval, scene_eval, NULL);
- kcd->bmbvh = BKE_bmbvh_new_from_editmesh(
- kcd->em,
- BMBVH_RETURN_ORIG |
- ((kcd->only_select && kcd->cut_through) ? BMBVH_RESPECT_SELECT : BMBVH_RESPECT_HIDDEN),
- kcd->cagecos, false);
+ kcd->bmbvh = BKE_bmbvh_new_from_editmesh(
+ kcd->em,
+ BMBVH_RETURN_ORIG |
+ ((kcd->only_select && kcd->cut_through) ? BMBVH_RESPECT_SELECT : BMBVH_RESPECT_HIDDEN),
+ kcd->cagecos,
+ false);
}
static void knifetool_free_bmbvh(KnifeTool_OpData *kcd)
{
- if (kcd->bmbvh) {
- BKE_bmbvh_free(kcd->bmbvh);
- kcd->bmbvh = NULL;
- }
+ if (kcd->bmbvh) {
+ BKE_bmbvh_free(kcd->bmbvh);
+ kcd->bmbvh = NULL;
+ }
- if (kcd->cagecos) {
- MEM_freeN((void *)kcd->cagecos);
- kcd->cagecos = NULL;
- }
+ if (kcd->cagecos) {
+ MEM_freeN((void *)kcd->cagecos);
+ kcd->cagecos = NULL;
+ }
}
/* called when modal loop selection gets set up... */
-static void knifetool_init(bContext *C, KnifeTool_OpData *kcd,
- const bool only_select, const bool cut_through, const bool is_interactive)
+static void knifetool_init(bContext *C,
+ KnifeTool_OpData *kcd,
+ const bool only_select,
+ const bool cut_through,
+ const bool is_interactive)
{
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
- /* assign the drawing handle for drawing preview line... */
- kcd->scene = scene;
- kcd->ob = obedit;
- kcd->ar = CTX_wm_region(C);
+ /* assign the drawing handle for drawing preview line... */
+ kcd->scene = scene;
+ kcd->ob = obedit;
+ kcd->ar = CTX_wm_region(C);
- em_setup_viewcontext(C, &kcd->vc);
+ em_setup_viewcontext(C, &kcd->vc);
- kcd->em = BKE_editmesh_from_object(kcd->ob);
+ kcd->em = BKE_editmesh_from_object(kcd->ob);
- /* cut all the way through the mesh if use_occlude_geometry button not pushed */
- kcd->is_interactive = is_interactive;
- kcd->cut_through = cut_through;
- kcd->only_select = only_select;
+ /* cut all the way through the mesh if use_occlude_geometry button not pushed */
+ kcd->is_interactive = is_interactive;
+ kcd->cut_through = cut_through;
+ kcd->only_select = only_select;
- knifetool_init_bmbvh(kcd);
+ knifetool_init_bmbvh(kcd);
- kcd->arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 15), "knife");
+ kcd->arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 15), "knife");
#ifdef USE_NET_ISLAND_CONNECT
- kcd->edgenet.arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 15), __func__);
+ kcd->edgenet.arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 15), __func__);
#endif
- kcd->edgenet.edge_visit = BLI_gset_ptr_new(__func__);
+ kcd->edgenet.edge_visit = BLI_gset_ptr_new(__func__);
- kcd->vthresh = KMAXDIST - 1;
- kcd->ethresh = KMAXDIST;
+ kcd->vthresh = KMAXDIST - 1;
+ kcd->ethresh = KMAXDIST;
- knife_recalc_projmat(kcd);
+ knife_recalc_projmat(kcd);
- ED_region_tag_redraw(kcd->ar);
+ ED_region_tag_redraw(kcd->ar);
- kcd->refs = BLI_mempool_create(sizeof(Ref), 0, 2048, 0);
- kcd->kverts = BLI_mempool_create(sizeof(KnifeVert), 0, 512, BLI_MEMPOOL_ALLOW_ITER);
- kcd->kedges = BLI_mempool_create(sizeof(KnifeEdge), 0, 512, BLI_MEMPOOL_ALLOW_ITER);
+ kcd->refs = BLI_mempool_create(sizeof(Ref), 0, 2048, 0);
+ kcd->kverts = BLI_mempool_create(sizeof(KnifeVert), 0, 512, BLI_MEMPOOL_ALLOW_ITER);
+ kcd->kedges = BLI_mempool_create(sizeof(KnifeEdge), 0, 512, BLI_MEMPOOL_ALLOW_ITER);
- kcd->origedgemap = BLI_ghash_ptr_new("knife origedgemap");
- kcd->origvertmap = BLI_ghash_ptr_new("knife origvertmap");
- kcd->kedgefacemap = BLI_ghash_ptr_new("knife kedgefacemap");
- kcd->facetrimap = BLI_ghash_ptr_new("knife facetrimap");
+ kcd->origedgemap = BLI_ghash_ptr_new("knife origedgemap");
+ kcd->origvertmap = BLI_ghash_ptr_new("knife origvertmap");
+ kcd->kedgefacemap = BLI_ghash_ptr_new("knife kedgefacemap");
+ kcd->facetrimap = BLI_ghash_ptr_new("knife facetrimap");
- /* can't usefully select resulting edges in face mode */
- kcd->select_result = (kcd->em->selectmode != SCE_SELECT_FACE);
+ /* can't usefully select resulting edges in face mode */
+ kcd->select_result = (kcd->em->selectmode != SCE_SELECT_FACE);
- knife_pos_data_clear(&kcd->curr);
- knife_pos_data_clear(&kcd->prev);
+ knife_pos_data_clear(&kcd->curr);
+ knife_pos_data_clear(&kcd->prev);
- if (is_interactive) {
- kcd->draw_handle = ED_region_draw_cb_activate(kcd->ar->type, knifetool_draw, kcd, REGION_DRAW_POST_VIEW);
+ if (is_interactive) {
+ kcd->draw_handle = ED_region_draw_cb_activate(
+ kcd->ar->type, knifetool_draw, kcd, REGION_DRAW_POST_VIEW);
- knife_init_colors(&kcd->colors);
- }
+ knife_init_colors(&kcd->colors);
+ }
}
static void knifetool_cancel(bContext *C, wmOperator *op)
{
- /* this is just a wrapper around exit() */
- knifetool_exit(C, op);
+ /* this is just a wrapper around exit() */
+ knifetool_exit(C, op);
}
static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- const bool only_select = RNA_boolean_get(op->ptr, "only_selected");
- const bool cut_through = !RNA_boolean_get(op->ptr, "use_occlude_geometry");
- const bool wait_for_input = RNA_boolean_get(op->ptr, "wait_for_input");
+ const bool only_select = RNA_boolean_get(op->ptr, "only_selected");
+ const bool cut_through = !RNA_boolean_get(op->ptr, "use_occlude_geometry");
+ const bool wait_for_input = RNA_boolean_get(op->ptr, "wait_for_input");
- KnifeTool_OpData *kcd;
+ KnifeTool_OpData *kcd;
- if (only_select) {
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totfacesel == 0) {
- BKE_report(op->reports, RPT_ERROR, "Selected faces required");
- return OPERATOR_CANCELLED;
- }
- }
+ if (only_select) {
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ if (em->bm->totfacesel == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Selected faces required");
+ return OPERATOR_CANCELLED;
+ }
+ }
- view3d_operator_needs_opengl(C);
+ view3d_operator_needs_opengl(C);
- /* alloc new customdata */
- kcd = op->customdata = MEM_callocN(sizeof(KnifeTool_OpData), __func__);
+ /* alloc new customdata */
+ kcd = op->customdata = MEM_callocN(sizeof(KnifeTool_OpData), __func__);
- knifetool_init(C, kcd, only_select, cut_through, true);
+ knifetool_init(C, kcd, only_select, cut_through, true);
- op->flag |= OP_IS_MODAL_CURSOR_REGION;
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
- /* add a modal handler for this operator - handles loop selection */
- WM_cursor_modal_set(CTX_wm_window(C), BC_KNIFECURSOR);
- WM_event_add_modal_handler(C, op);
+ /* add a modal handler for this operator - handles loop selection */
+ WM_cursor_modal_set(CTX_wm_window(C), BC_KNIFECURSOR);
+ WM_event_add_modal_handler(C, op);
- knifetool_update_mval_i(kcd, event->mval);
+ knifetool_update_mval_i(kcd, event->mval);
- if (wait_for_input == false) {
- /* Avoid copy-paste logic. */
- wmEvent event_modal = {
- .prevval = KM_NOTHING,
- .type = EVT_MODAL_MAP,
- .val = KNF_MODAL_ADD_CUT,
- };
- int ret = knifetool_modal(C, op, &event_modal);
- BLI_assert(ret == OPERATOR_RUNNING_MODAL);
- UNUSED_VARS_NDEBUG(ret);
- }
+ if (wait_for_input == false) {
+ /* Avoid copy-paste logic. */
+ wmEvent event_modal = {
+ .prevval = KM_NOTHING,
+ .type = EVT_MODAL_MAP,
+ .val = KNF_MODAL_ADD_CUT,
+ };
+ int ret = knifetool_modal(C, op, &event_modal);
+ BLI_assert(ret == OPERATOR_RUNNING_MODAL);
+ UNUSED_VARS_NDEBUG(ret);
+ }
- knife_update_header(C, op, kcd);
+ knife_update_header(C, op, kcd);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf)
{
- static const EnumPropertyItem modal_items[] = {
- {KNF_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
- {KNF_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
- {KNF_MODAL_MIDPOINT_ON, "SNAP_MIDPOINTS_ON", 0, "Snap To Midpoints On", ""},
- {KNF_MODAL_MIDPOINT_OFF, "SNAP_MIDPOINTS_OFF", 0, "Snap To Midpoints Off", ""},
- {KNF_MODEL_IGNORE_SNAP_ON, "IGNORE_SNAP_ON", 0, "Ignore Snapping On", ""},
- {KNF_MODEL_IGNORE_SNAP_OFF, "IGNORE_SNAP_OFF", 0, "Ignore Snapping Off", ""},
- {KNF_MODAL_ANGLE_SNAP_TOGGLE, "ANGLE_SNAP_TOGGLE", 0, "Toggle Angle Snapping", ""},
- {KNF_MODAL_CUT_THROUGH_TOGGLE, "CUT_THROUGH_TOGGLE", 0, "Toggle Cut Through", ""},
- {KNF_MODAL_NEW_CUT, "NEW_CUT", 0, "End Current Cut", ""},
- {KNF_MODAL_ADD_CUT, "ADD_CUT", 0, "Add Cut", ""},
- {KNF_MODAL_PANNING, "PANNING", 0, "Panning", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem modal_items[] = {
+ {KNF_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
+ {KNF_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+ {KNF_MODAL_MIDPOINT_ON, "SNAP_MIDPOINTS_ON", 0, "Snap To Midpoints On", ""},
+ {KNF_MODAL_MIDPOINT_OFF, "SNAP_MIDPOINTS_OFF", 0, "Snap To Midpoints Off", ""},
+ {KNF_MODEL_IGNORE_SNAP_ON, "IGNORE_SNAP_ON", 0, "Ignore Snapping On", ""},
+ {KNF_MODEL_IGNORE_SNAP_OFF, "IGNORE_SNAP_OFF", 0, "Ignore Snapping Off", ""},
+ {KNF_MODAL_ANGLE_SNAP_TOGGLE, "ANGLE_SNAP_TOGGLE", 0, "Toggle Angle Snapping", ""},
+ {KNF_MODAL_CUT_THROUGH_TOGGLE, "CUT_THROUGH_TOGGLE", 0, "Toggle Cut Through", ""},
+ {KNF_MODAL_NEW_CUT, "NEW_CUT", 0, "End Current Cut", ""},
+ {KNF_MODAL_ADD_CUT, "ADD_CUT", 0, "Add Cut", ""},
+ {KNF_MODAL_PANNING, "PANNING", 0, "Panning", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Knife Tool Modal Map");
+ wmKeyMap *keymap = WM_modalkeymap_get(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;
+ /* 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_add(keyconf, "Knife Tool Modal Map", modal_items);
- WM_modalkeymap_assign(keymap, "MESH_OT_knife_tool");
+ WM_modalkeymap_assign(keymap, "MESH_OT_knife_tool");
- return keymap;
+ return keymap;
}
static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- Object *obedit = CTX_data_edit_object(C);
- KnifeTool_OpData *kcd = op->customdata;
- bool do_refresh = false;
-
- if (!obedit || obedit->type != OB_MESH || BKE_editmesh_from_object(obedit) != kcd->em) {
- knifetool_exit(C, op);
- ED_workspace_status_text(C, NULL);
- return OPERATOR_FINISHED;
- }
-
- em_setup_viewcontext(C, &kcd->vc);
- kcd->ar = kcd->vc.ar;
-
- view3d_operator_needs_opengl(C);
- ED_view3d_init_mats_rv3d(obedit, kcd->vc.rv3d); /* needed to initialize clipping */
-
- if (kcd->mode == MODE_PANNING)
- kcd->mode = kcd->prevmode;
-
- /* handle modal keymap */
- if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case KNF_MODAL_CANCEL:
- /* finish */
- ED_region_tag_redraw(kcd->ar);
-
- knifetool_exit(C, op);
- ED_workspace_status_text(C, NULL);
-
- return OPERATOR_CANCELLED;
- case KNF_MODAL_CONFIRM:
- /* finish */
- ED_region_tag_redraw(kcd->ar);
-
- knifetool_finish(op);
- knifetool_exit(C, op);
- ED_workspace_status_text(C, NULL);
-
- return OPERATOR_FINISHED;
- case KNF_MODAL_MIDPOINT_ON:
- kcd->snap_midpoints = true;
-
- knife_recalc_projmat(kcd);
- knife_update_active(kcd);
- knife_update_header(C, op, kcd);
- ED_region_tag_redraw(kcd->ar);
- do_refresh = true;
- break;
- case KNF_MODAL_MIDPOINT_OFF:
- kcd->snap_midpoints = false;
-
- knife_recalc_projmat(kcd);
- knife_update_active(kcd);
- knife_update_header(C, op, kcd);
- ED_region_tag_redraw(kcd->ar);
- do_refresh = true;
- break;
- case KNF_MODEL_IGNORE_SNAP_ON:
- ED_region_tag_redraw(kcd->ar);
- 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);
- kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = false;
- knife_update_header(C, op, kcd);
- do_refresh = true;
- break;
- case KNF_MODAL_ANGLE_SNAP_TOGGLE:
- kcd->angle_snapping = !kcd->angle_snapping;
- knife_update_header(C, op, kcd);
- do_refresh = true;
- break;
- case KNF_MODAL_CUT_THROUGH_TOGGLE:
- kcd->cut_through = !kcd->cut_through;
- knife_update_header(C, op, kcd);
- do_refresh = true;
- break;
- case KNF_MODAL_NEW_CUT:
- ED_region_tag_redraw(kcd->ar);
- knife_finish_cut(kcd);
- kcd->mode = MODE_IDLE;
- break;
- case KNF_MODAL_ADD_CUT:
- knife_recalc_projmat(kcd);
-
- /* get the value of the event which triggered this one */
- if (event->prevval != KM_RELEASE) {
- if (kcd->mode == MODE_DRAGGING) {
- knife_add_cut(kcd);
- }
- else if (kcd->mode != MODE_PANNING) {
- knife_start_cut(kcd);
- kcd->mode = MODE_DRAGGING;
- kcd->init = kcd->curr;
- }
-
- /* freehand drawing is incompatible with cut-through */
- if (kcd->cut_through == false) {
- kcd->is_drag_hold = true;
- }
- }
- else {
- kcd->is_drag_hold = false;
-
- /* needed because the last face 'hit' is ignored when dragging */
- knifetool_update_mval(kcd, kcd->curr.mval);
- }
-
- ED_region_tag_redraw(kcd->ar);
- break;
- case KNF_MODAL_ADD_CUT_CLOSED:
- if (kcd->mode == MODE_DRAGGING) {
-
- /* shouldn't be possible with default key-layout, just incase... */
- if (kcd->is_drag_hold) {
- kcd->is_drag_hold = false;
- knifetool_update_mval(kcd, kcd->curr.mval);
- }
-
- kcd->prev = kcd->curr;
- kcd->curr = kcd->init;
-
- knife_project_v2(kcd, kcd->curr.cage, kcd->curr.mval);
- knifetool_update_mval(kcd, kcd->curr.mval);
-
- knife_add_cut(kcd);
-
- /* KNF_MODAL_NEW_CUT */
- knife_finish_cut(kcd);
- kcd->mode = MODE_IDLE;
- }
- break;
- case KNF_MODAL_PANNING:
- if (event->val != KM_RELEASE) {
- if (kcd->mode != MODE_PANNING) {
- kcd->prevmode = kcd->mode;
- kcd->mode = MODE_PANNING;
- }
- }
- else {
- kcd->mode = kcd->prevmode;
- }
-
- ED_region_tag_redraw(kcd->ar);
- return OPERATOR_PASS_THROUGH;
- }
- }
- else { /* non-modal-mapped events */
- switch (event->type) {
- case MOUSEPAN:
- case MOUSEZOOM:
- case MOUSEROTATE:
- case WHEELUPMOUSE:
- case WHEELDOWNMOUSE:
- return OPERATOR_PASS_THROUGH;
- case MOUSEMOVE: /* mouse moved somewhere to select another loop */
- if (kcd->mode != MODE_PANNING) {
- knifetool_update_mval_i(kcd, event->mval);
-
- if (kcd->is_drag_hold) {
- if (kcd->totlinehit >= 2) {
- knife_add_cut(kcd);
- }
- }
- }
-
- break;
- }
- }
-
- if (kcd->mode == MODE_DRAGGING) {
- op->flag &= ~OP_IS_MODAL_CURSOR_REGION;
- }
- else {
- op->flag |= OP_IS_MODAL_CURSOR_REGION;
- }
-
- if (do_refresh) {
- /* we don't really need to update mval,
- * but this happens to be the best way to refresh at the moment */
- knifetool_update_mval_i(kcd, event->mval);
- }
-
- /* keep going until the user confirms */
- return OPERATOR_RUNNING_MODAL;
+ Object *obedit = CTX_data_edit_object(C);
+ KnifeTool_OpData *kcd = op->customdata;
+ bool do_refresh = false;
+
+ if (!obedit || obedit->type != OB_MESH || BKE_editmesh_from_object(obedit) != kcd->em) {
+ knifetool_exit(C, op);
+ ED_workspace_status_text(C, NULL);
+ return OPERATOR_FINISHED;
+ }
+
+ em_setup_viewcontext(C, &kcd->vc);
+ kcd->ar = kcd->vc.ar;
+
+ view3d_operator_needs_opengl(C);
+ ED_view3d_init_mats_rv3d(obedit, kcd->vc.rv3d); /* needed to initialize clipping */
+
+ if (kcd->mode == MODE_PANNING)
+ kcd->mode = kcd->prevmode;
+
+ /* handle modal keymap */
+ if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case KNF_MODAL_CANCEL:
+ /* finish */
+ ED_region_tag_redraw(kcd->ar);
+
+ knifetool_exit(C, op);
+ ED_workspace_status_text(C, NULL);
+
+ return OPERATOR_CANCELLED;
+ case KNF_MODAL_CONFIRM:
+ /* finish */
+ ED_region_tag_redraw(kcd->ar);
+
+ knifetool_finish(op);
+ knifetool_exit(C, op);
+ ED_workspace_status_text(C, NULL);
+
+ return OPERATOR_FINISHED;
+ case KNF_MODAL_MIDPOINT_ON:
+ kcd->snap_midpoints = true;
+
+ knife_recalc_projmat(kcd);
+ knife_update_active(kcd);
+ knife_update_header(C, op, kcd);
+ ED_region_tag_redraw(kcd->ar);
+ do_refresh = true;
+ break;
+ case KNF_MODAL_MIDPOINT_OFF:
+ kcd->snap_midpoints = false;
+
+ knife_recalc_projmat(kcd);
+ knife_update_active(kcd);
+ knife_update_header(C, op, kcd);
+ ED_region_tag_redraw(kcd->ar);
+ do_refresh = true;
+ break;
+ case KNF_MODEL_IGNORE_SNAP_ON:
+ ED_region_tag_redraw(kcd->ar);
+ 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);
+ kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = false;
+ knife_update_header(C, op, kcd);
+ do_refresh = true;
+ break;
+ case KNF_MODAL_ANGLE_SNAP_TOGGLE:
+ kcd->angle_snapping = !kcd->angle_snapping;
+ knife_update_header(C, op, kcd);
+ do_refresh = true;
+ break;
+ case KNF_MODAL_CUT_THROUGH_TOGGLE:
+ kcd->cut_through = !kcd->cut_through;
+ knife_update_header(C, op, kcd);
+ do_refresh = true;
+ break;
+ case KNF_MODAL_NEW_CUT:
+ ED_region_tag_redraw(kcd->ar);
+ knife_finish_cut(kcd);
+ kcd->mode = MODE_IDLE;
+ break;
+ case KNF_MODAL_ADD_CUT:
+ knife_recalc_projmat(kcd);
+
+ /* get the value of the event which triggered this one */
+ if (event->prevval != KM_RELEASE) {
+ if (kcd->mode == MODE_DRAGGING) {
+ knife_add_cut(kcd);
+ }
+ else if (kcd->mode != MODE_PANNING) {
+ knife_start_cut(kcd);
+ kcd->mode = MODE_DRAGGING;
+ kcd->init = kcd->curr;
+ }
+
+ /* freehand drawing is incompatible with cut-through */
+ if (kcd->cut_through == false) {
+ kcd->is_drag_hold = true;
+ }
+ }
+ else {
+ kcd->is_drag_hold = false;
+
+ /* needed because the last face 'hit' is ignored when dragging */
+ knifetool_update_mval(kcd, kcd->curr.mval);
+ }
+
+ ED_region_tag_redraw(kcd->ar);
+ break;
+ case KNF_MODAL_ADD_CUT_CLOSED:
+ if (kcd->mode == MODE_DRAGGING) {
+
+ /* shouldn't be possible with default key-layout, just incase... */
+ if (kcd->is_drag_hold) {
+ kcd->is_drag_hold = false;
+ knifetool_update_mval(kcd, kcd->curr.mval);
+ }
+
+ kcd->prev = kcd->curr;
+ kcd->curr = kcd->init;
+
+ knife_project_v2(kcd, kcd->curr.cage, kcd->curr.mval);
+ knifetool_update_mval(kcd, kcd->curr.mval);
+
+ knife_add_cut(kcd);
+
+ /* KNF_MODAL_NEW_CUT */
+ knife_finish_cut(kcd);
+ kcd->mode = MODE_IDLE;
+ }
+ break;
+ case KNF_MODAL_PANNING:
+ if (event->val != KM_RELEASE) {
+ if (kcd->mode != MODE_PANNING) {
+ kcd->prevmode = kcd->mode;
+ kcd->mode = MODE_PANNING;
+ }
+ }
+ else {
+ kcd->mode = kcd->prevmode;
+ }
+
+ ED_region_tag_redraw(kcd->ar);
+ return OPERATOR_PASS_THROUGH;
+ }
+ }
+ else { /* non-modal-mapped events */
+ switch (event->type) {
+ case MOUSEPAN:
+ case MOUSEZOOM:
+ case MOUSEROTATE:
+ case WHEELUPMOUSE:
+ case WHEELDOWNMOUSE:
+ return OPERATOR_PASS_THROUGH;
+ case MOUSEMOVE: /* mouse moved somewhere to select another loop */
+ if (kcd->mode != MODE_PANNING) {
+ knifetool_update_mval_i(kcd, event->mval);
+
+ if (kcd->is_drag_hold) {
+ if (kcd->totlinehit >= 2) {
+ knife_add_cut(kcd);
+ }
+ }
+ }
+
+ break;
+ }
+ }
+
+ if (kcd->mode == MODE_DRAGGING) {
+ op->flag &= ~OP_IS_MODAL_CURSOR_REGION;
+ }
+ else {
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+ }
+
+ if (do_refresh) {
+ /* we don't really need to update mval,
+ * but this happens to be the best way to refresh at the moment */
+ knifetool_update_mval_i(kcd, event->mval);
+ }
+
+ /* keep going until the user confirms */
+ return OPERATOR_RUNNING_MODAL;
}
void MESH_OT_knife_tool(wmOperatorType *ot)
{
- /* description */
- ot->name = "Knife Topology Tool";
- ot->idname = "MESH_OT_knife_tool";
- ot->description = "Cut new topology";
+ /* description */
+ ot->name = "Knife Topology Tool";
+ ot->idname = "MESH_OT_knife_tool";
+ ot->description = "Cut new topology";
- /* callbacks */
- ot->invoke = knifetool_invoke;
- ot->modal = knifetool_modal;
- ot->cancel = knifetool_cancel;
- ot->poll = ED_operator_editmesh_view3d;
+ /* callbacks */
+ ot->invoke = knifetool_invoke;
+ ot->modal = knifetool_modal;
+ ot->cancel = knifetool_cancel;
+ ot->poll = ED_operator_editmesh_view3d;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
- /* properties */
- PropertyRNA *prop;
- RNA_def_boolean(ot->srna, "use_occlude_geometry", true, "Occlude Geometry", "Only cut the front most geometry");
- RNA_def_boolean(ot->srna, "only_selected", false, "Only Selected", "Only cut selected geometry");
+ /* properties */
+ PropertyRNA *prop;
+ RNA_def_boolean(ot->srna,
+ "use_occlude_geometry",
+ true,
+ "Occlude Geometry",
+ "Only cut the front most geometry");
+ RNA_def_boolean(ot->srna, "only_selected", false, "Only Selected", "Only cut selected geometry");
- prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "");
- 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);
}
-
/* -------------------------------------------------------------------- */
/* Knife tool as a utility function
* that can be used for internal slicing operations */
static bool edbm_mesh_knife_point_isect(LinkNode *polys, const float cent_ss[2])
{
- LinkNode *p = polys;
- int isect = 0;
+ LinkNode *p = polys;
+ int isect = 0;
- while (p) {
- const float (*mval_fl)[2] = p->link;
- const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl);
- isect += (int)isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1, false);
- p = p->next;
- }
+ while (p) {
+ const float(*mval_fl)[2] = p->link;
+ const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl);
+ isect += (int)isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1, false);
+ p = p->next;
+ }
- if (isect % 2) {
- return true;
- }
- return false;
+ if (isect % 2) {
+ return true;
+ }
+ return false;
}
/**
@@ -3009,156 +3030,155 @@ static bool edbm_mesh_knife_point_isect(LinkNode *polys, const float cent_ss[2])
*/
void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_through)
{
- KnifeTool_OpData *kcd;
+ KnifeTool_OpData *kcd;
- view3d_operator_needs_opengl(C);
+ view3d_operator_needs_opengl(C);
- /* init */
- {
- const bool only_select = false;
- const bool is_interactive = false; /* can enable for testing */
+ /* init */
+ {
+ const bool only_select = false;
+ const bool is_interactive = false; /* can enable for testing */
- kcd = MEM_callocN(sizeof(KnifeTool_OpData), __func__);
+ kcd = MEM_callocN(sizeof(KnifeTool_OpData), __func__);
- knifetool_init(C, kcd, only_select, cut_through, is_interactive);
+ knifetool_init(C, kcd, only_select, cut_through, is_interactive);
- kcd->ignore_edge_snapping = true;
- kcd->ignore_vert_snapping = true;
+ kcd->ignore_edge_snapping = true;
+ kcd->ignore_vert_snapping = true;
- if (use_tag) {
- BM_mesh_elem_hflag_enable_all(kcd->em->bm, BM_EDGE, BM_ELEM_TAG, false);
- }
- }
+ if (use_tag) {
+ BM_mesh_elem_hflag_enable_all(kcd->em->bm, BM_EDGE, BM_ELEM_TAG, false);
+ }
+ }
- /* execute */
- {
- LinkNode *p = polys;
+ /* execute */
+ {
+ LinkNode *p = polys;
- knife_recalc_projmat(kcd);
+ knife_recalc_projmat(kcd);
- while (p) {
- const float (*mval_fl)[2] = p->link;
- const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl);
- int i;
+ while (p) {
+ const float(*mval_fl)[2] = p->link;
+ const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl);
+ int i;
- for (i = 0; i < mval_tot; i++) {
- knifetool_update_mval(kcd, mval_fl[i]);
- if (i == 0) {
- knife_start_cut(kcd);
- kcd->mode = MODE_DRAGGING;
- }
- else {
- knife_add_cut(kcd);
- }
- }
- knife_finish_cut(kcd);
- kcd->mode = MODE_IDLE;
- p = p->next;
- }
- }
+ for (i = 0; i < mval_tot; i++) {
+ knifetool_update_mval(kcd, mval_fl[i]);
+ if (i == 0) {
+ knife_start_cut(kcd);
+ kcd->mode = MODE_DRAGGING;
+ }
+ else {
+ knife_add_cut(kcd);
+ }
+ }
+ knife_finish_cut(kcd);
+ kcd->mode = MODE_IDLE;
+ p = p->next;
+ }
+ }
- /* finish */
- {
- knifetool_finish_ex(kcd);
+ /* finish */
+ {
+ knifetool_finish_ex(kcd);
- /* tag faces inside! */
- if (use_tag) {
- BMesh *bm = kcd->em->bm;
- float projmat[4][4];
+ /* tag faces inside! */
+ if (use_tag) {
+ BMesh *bm = kcd->em->bm;
+ float projmat[4][4];
- BMEdge *e;
- BMIter iter;
+ BMEdge *e;
+ BMIter iter;
- bool keep_search;
+ bool keep_search;
- /* freed on knifetool_finish_ex, but we need again to check if points are visible */
- if (kcd->cut_through == false) {
- knifetool_init_bmbvh(kcd);
- }
+ /* freed on knifetool_finish_ex, but we need again to check if points are visible */
+ if (kcd->cut_through == false) {
+ knifetool_init_bmbvh(kcd);
+ }
- ED_view3d_ob_project_mat_get(kcd->ar->regiondata, kcd->ob, projmat);
+ ED_view3d_ob_project_mat_get(kcd->ar->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)
+ /* 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)
#define F_ISECT_SET_UNKNOWN(f) BM_elem_flag_enable(BM_FACE_FIRST_LOOP(f), BM_ELEM_TAG)
#define F_ISECT_SET_OUTSIDE(f) BM_elem_flag_disable(BM_FACE_FIRST_LOOP(f), BM_ELEM_TAG)
- {
- BMFace *f;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- F_ISECT_SET_UNKNOWN(f);
- BM_elem_flag_disable(f, BM_ELEM_TAG);
- }
- }
-
- /* tag all faces linked to cut edges */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- /* check are we tagged?, then we are an original face */
- if (BM_elem_flag_test(e, BM_ELEM_TAG) == false) {
- BMFace *f;
- BMIter fiter;
- BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
- float cent[3], cent_ss[2];
- BM_face_calc_point_in_face(f, cent);
- knife_project_v2(kcd, cent, cent_ss);
- if (edbm_mesh_knife_point_isect(polys, cent_ss)) {
- BM_elem_flag_enable(f, BM_ELEM_TAG);
- }
- }
- }
- }
-
- /* expand tags for faces which are not cut, but are inside the polys */
- do {
- BMFace *f;
- keep_search = false;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_TAG) == false && (F_ISECT_IS_UNKNOWN(f))) {
- /* am I connected to a tagged face via an un-tagged edge
- * (ie, not across a cut) */
- BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
- BMLoop *l_iter = l_first;
- bool found = false;
-
- do {
- if (BM_elem_flag_test(l_iter->e, BM_ELEM_TAG) != false) {
- /* now check if the adjacent faces is tagged */
- BMLoop *l_radial_iter = l_iter->radial_next;
- if (l_radial_iter != l_iter) {
- do {
- if (BM_elem_flag_test(l_radial_iter->f, BM_ELEM_TAG)) {
- found = true;
- }
- } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter && (found == false));
- }
- }
- } while ((l_iter = l_iter->next) != l_first && (found == false));
-
- if (found) {
- float cent[3], cent_ss[2];
- BM_face_calc_point_in_face(f, cent);
- knife_project_v2(kcd, cent, cent_ss);
- if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, (BMElem *)f)) &&
- edbm_mesh_knife_point_isect(polys, cent_ss))
- {
- BM_elem_flag_enable(f, BM_ELEM_TAG);
- keep_search = true;
- }
- else {
- /* don't loose time on this face again, set it as outside */
- F_ISECT_SET_OUTSIDE(f);
- }
- }
- }
- }
- } while (keep_search);
+ {
+ BMFace *f;
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ F_ISECT_SET_UNKNOWN(f);
+ BM_elem_flag_disable(f, BM_ELEM_TAG);
+ }
+ }
+
+ /* tag all faces linked to cut edges */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ /* check are we tagged?, then we are an original face */
+ if (BM_elem_flag_test(e, BM_ELEM_TAG) == false) {
+ BMFace *f;
+ BMIter fiter;
+ BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
+ float cent[3], cent_ss[2];
+ BM_face_calc_point_in_face(f, cent);
+ knife_project_v2(kcd, cent, cent_ss);
+ if (edbm_mesh_knife_point_isect(polys, cent_ss)) {
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+ }
+ }
+ }
+ }
+
+ /* expand tags for faces which are not cut, but are inside the polys */
+ do {
+ BMFace *f;
+ keep_search = false;
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_TAG) == false && (F_ISECT_IS_UNKNOWN(f))) {
+ /* am I connected to a tagged face via an un-tagged edge
+ * (ie, not across a cut) */
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter = l_first;
+ bool found = false;
+
+ do {
+ if (BM_elem_flag_test(l_iter->e, BM_ELEM_TAG) != false) {
+ /* now check if the adjacent faces is tagged */
+ BMLoop *l_radial_iter = l_iter->radial_next;
+ if (l_radial_iter != l_iter) {
+ do {
+ if (BM_elem_flag_test(l_radial_iter->f, BM_ELEM_TAG)) {
+ found = true;
+ }
+ } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter &&
+ (found == false));
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_first && (found == false));
+
+ if (found) {
+ float cent[3], cent_ss[2];
+ BM_face_calc_point_in_face(f, cent);
+ knife_project_v2(kcd, cent, cent_ss);
+ if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, (BMElem *)f)) &&
+ edbm_mesh_knife_point_isect(polys, cent_ss)) {
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+ keep_search = true;
+ }
+ else {
+ /* don't loose time on this face again, set it as outside */
+ F_ISECT_SET_OUTSIDE(f);
+ }
+ }
+ }
+ }
+ } while (keep_search);
#undef F_ISECT_IS_UNKNOWN
#undef F_ISECT_SET_UNKNOWN
#undef F_ISECT_SET_OUTSIDE
+ }
- }
-
- knifetool_exit_ex(C, kcd);
- kcd = NULL;
- }
+ knifetool_exit_ex(C, kcd);
+ kcd = NULL;
+ }
}
diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c
index 13fcb99f59b..13bcb1334a9 100644
--- a/source/blender/editors/mesh/editmesh_knife_project.c
+++ b/source/blender/editors/mesh/editmesh_knife_project.c
@@ -50,130 +50,135 @@
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
-
-static LinkNode *knifeproject_poly_from_object(const bContext *C, Scene *scene, Object *ob, LinkNode *polys)
+static LinkNode *knifeproject_poly_from_object(const bContext *C,
+ Scene *scene,
+ Object *ob,
+ LinkNode *polys)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ARegion *ar = CTX_wm_region(C);
- struct Mesh *me_eval;
- bool me_eval_needs_free;
-
- if (ob->type == OB_MESH || ob->runtime.mesh_eval) {
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- me_eval = ob_eval->runtime.mesh_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);
- }
- me_eval_needs_free = false;
- }
- else if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- me_eval = BKE_mesh_new_nomain_from_curve(ob_eval);
- me_eval_needs_free = true;
- }
- else {
- me_eval = NULL;
- }
-
- if (me_eval) {
- ListBase nurbslist = {NULL, NULL};
- float projmat[4][4];
-
- 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);
-
- if (nurbslist.first) {
- Nurb *nu;
- for (nu = nurbslist.first; nu; nu = nu->next) {
- if (nu->bp) {
- int a;
- BPoint *bp;
- bool is_cyclic = (nu->flagu & CU_NURB_CYCLIC) != 0;
- 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);
- }
- if (is_cyclic) {
- copy_v2_v2(mval[a], mval[0]);
- }
-
- BLI_linklist_prepend(&polys, mval);
- }
- }
- }
-
- BKE_nurbList_free(&nurbslist);
-
- if (me_eval_needs_free) {
- BKE_mesh_free(me_eval);
- }
- }
-
- return polys;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ARegion *ar = CTX_wm_region(C);
+ struct Mesh *me_eval;
+ bool me_eval_needs_free;
+
+ if (ob->type == OB_MESH || ob->runtime.mesh_eval) {
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ me_eval = ob_eval->runtime.mesh_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);
+ }
+ me_eval_needs_free = false;
+ }
+ else if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ me_eval = BKE_mesh_new_nomain_from_curve(ob_eval);
+ me_eval_needs_free = true;
+ }
+ else {
+ me_eval = NULL;
+ }
+
+ if (me_eval) {
+ ListBase nurbslist = {NULL, NULL};
+ float projmat[4][4];
+
+ 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);
+
+ if (nurbslist.first) {
+ Nurb *nu;
+ for (nu = nurbslist.first; nu; nu = nu->next) {
+ if (nu->bp) {
+ int a;
+ BPoint *bp;
+ bool is_cyclic = (nu->flagu & CU_NURB_CYCLIC) != 0;
+ 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);
+ }
+ if (is_cyclic) {
+ copy_v2_v2(mval[a], mval[0]);
+ }
+
+ BLI_linklist_prepend(&polys, mval);
+ }
+ }
+ }
+
+ BKE_nurbList_free(&nurbslist);
+
+ if (me_eval_needs_free) {
+ BKE_mesh_free(me_eval);
+ }
+ }
+
+ return polys;
}
static int knifeproject_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- const bool cut_through = RNA_boolean_get(op->ptr, "cut_through");
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ const bool cut_through = RNA_boolean_get(op->ptr, "cut_through");
- LinkNode *polys = NULL;
+ LinkNode *polys = NULL;
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- if (ob != obedit) {
- polys = knifeproject_poly_from_object(C, scene, ob, polys);
- }
- }
- CTX_DATA_END;
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ if (ob != obedit) {
+ polys = knifeproject_poly_from_object(C, scene, ob, polys);
+ }
+ }
+ CTX_DATA_END;
- if (polys) {
- EDBM_mesh_knife(C, polys, true, cut_through);
+ if (polys) {
+ EDBM_mesh_knife(C, polys, true, cut_through);
- /* select only tagged faces */
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
+ /* select only tagged faces */
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
- /* not essential, but switch out of vertex mode since the
- * selected regions wont be nicely isolated after flushing.
- * note: call after de-select to avoid selection flushing */
- EDBM_selectmode_disable(scene, em, SCE_SELECT_VERTEX, SCE_SELECT_EDGE);
+ /* not essential, but switch out of vertex mode since the
+ * selected regions wont be nicely isolated after flushing.
+ * note: call after de-select to avoid selection flushing */
+ EDBM_selectmode_disable(scene, em, SCE_SELECT_VERTEX, SCE_SELECT_EDGE);
- BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG);
+ BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG);
- BM_mesh_select_mode_flush(em->bm);
+ BM_mesh_select_mode_flush(em->bm);
- BLI_linklist_freeN(polys);
+ BLI_linklist_freeN(polys);
- return OPERATOR_FINISHED;
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "No other selected objects found to use for projection");
- return OPERATOR_CANCELLED;
- }
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No other selected objects found to use for projection");
+ return OPERATOR_CANCELLED;
+ }
}
void MESH_OT_knife_project(wmOperatorType *ot)
{
- /* description */
- ot->name = "Knife Project";
- ot->idname = "MESH_OT_knife_project";
- ot->description = "Use other objects outlines & boundaries to project knife cuts";
-
- /* callbacks */
- ot->exec = knifeproject_exec;
- ot->poll = ED_operator_editmesh_region_view3d;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_USE_EVAL_DATA;
-
- /* parameters */
- RNA_def_boolean(ot->srna, "cut_through", false, "Cut through", "Cut through all faces, not just visible ones");
+ /* description */
+ ot->name = "Knife Project";
+ ot->idname = "MESH_OT_knife_project";
+ ot->description = "Use other objects outlines & boundaries to project knife cuts";
+
+ /* callbacks */
+ ot->exec = knifeproject_exec;
+ ot->poll = ED_operator_editmesh_region_view3d;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_USE_EVAL_DATA;
+
+ /* parameters */
+ RNA_def_boolean(ot->srna,
+ "cut_through",
+ false,
+ "Cut through",
+ "Cut through all faces, not just visible ones");
}
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index f0c2023dfcc..d0988811d15 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -61,7 +61,7 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
#define SUBD_SMOOTH_MAX 4.0f
#define SUBD_CUTS_MAX 500
@@ -70,584 +70,609 @@
/* struct for properties used while drawing */
typedef struct RingSelOpData {
- ARegion *ar; /* region that ringsel was activated in */
- void *draw_handle; /* for drawing preview loop */
+ ARegion *ar; /* region that ringsel was activated in */
+ void *draw_handle; /* for drawing preview loop */
- struct EditMesh_PreSelEdgeRing *presel_edgering;
+ struct EditMesh_PreSelEdgeRing *presel_edgering;
- ViewContext vc;
+ ViewContext vc;
- Depsgraph *depsgraph;
+ Depsgraph *depsgraph;
- Object **objects;
- uint objects_len;
+ Object **objects;
+ uint objects_len;
- /* These values switch objects based on the object under the cursor. */
- uint ob_index;
- Object *ob;
- BMEditMesh *em;
- BMEdge *eed;
+ /* These values switch objects based on the object under the cursor. */
+ uint ob_index;
+ Object *ob;
+ BMEditMesh *em;
+ BMEdge *eed;
- NumInput num;
+ NumInput num;
- bool extend;
- bool do_cut;
+ bool extend;
+ bool do_cut;
- float cuts; /* cuts as float so smooth mouse pan works in small increments */
- float smoothness;
+ float cuts; /* cuts as float so smooth mouse pan works in small increments */
+ float smoothness;
} RingSelOpData;
/* modal loop selection drawing callback */
static void ringsel_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
{
- RingSelOpData *lcd = arg;
- EDBM_preselect_edgering_draw(lcd->presel_edgering, lcd->ob->obmat);
+ RingSelOpData *lcd = arg;
+ EDBM_preselect_edgering_draw(lcd->presel_edgering, lcd->ob->obmat);
}
static void edgering_select(RingSelOpData *lcd)
{
- if (!lcd->eed) {
- return;
- }
-
- if (!lcd->extend) {
- for (uint ob_index = 0; ob_index < lcd->objects_len; ob_index++) {
- Object *ob_iter = lcd->objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(ob_iter);
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
- WM_main_add_notifier(NC_GEOM | ND_SELECT, ob_iter->data);
- }
- }
-
- BMEditMesh *em = lcd->em;
- BMEdge *eed_start = lcd->eed;
- BMWalker walker;
- BMEdge *eed;
- BMW_init(&walker, em->bm, BMW_EDGERING,
- BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
- for (eed = BMW_begin(&walker, eed_start); eed; eed = BMW_step(&walker)) {
- BM_edge_select_set(em->bm, eed, true);
- }
- BMW_end(&walker);
+ if (!lcd->eed) {
+ return;
+ }
+
+ if (!lcd->extend) {
+ for (uint ob_index = 0; ob_index < lcd->objects_len; ob_index++) {
+ Object *ob_iter = lcd->objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(ob_iter);
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
+ WM_main_add_notifier(NC_GEOM | ND_SELECT, ob_iter->data);
+ }
+ }
+
+ BMEditMesh *em = lcd->em;
+ BMEdge *eed_start = lcd->eed;
+ BMWalker walker;
+ BMEdge *eed;
+ BMW_init(&walker,
+ em->bm,
+ BMW_EDGERING,
+ BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ for (eed = BMW_begin(&walker, eed_start); eed; eed = BMW_step(&walker)) {
+ BM_edge_select_set(em->bm, eed, true);
+ }
+ BMW_end(&walker);
}
static void ringsel_find_edge(RingSelOpData *lcd, const int previewlines)
{
- if (lcd->eed) {
- const float (*coords)[3] = NULL;
- {
- Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(lcd->depsgraph, lcd->ob->data);
- if (me_eval->runtime.edit_data) {
- coords = me_eval->runtime.edit_data->vertexCos;
- }
- }
- EDBM_preselect_edgering_update_from_edge(lcd->presel_edgering, lcd->em->bm, lcd->eed, previewlines, coords);
- }
- else {
- EDBM_preselect_edgering_clear(lcd->presel_edgering);
- }
+ if (lcd->eed) {
+ const float(*coords)[3] = NULL;
+ {
+ Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(lcd->depsgraph, lcd->ob->data);
+ if (me_eval->runtime.edit_data) {
+ coords = me_eval->runtime.edit_data->vertexCos;
+ }
+ }
+ EDBM_preselect_edgering_update_from_edge(
+ lcd->presel_edgering, lcd->em->bm, lcd->eed, previewlines, coords);
+ }
+ else {
+ EDBM_preselect_edgering_clear(lcd->presel_edgering);
+ }
}
static void ringsel_finish(bContext *C, wmOperator *op)
{
- RingSelOpData *lcd = op->customdata;
- const int cuts = RNA_int_get(op->ptr, "number_cuts");
- const float smoothness = RNA_float_get(op->ptr, "smoothness");
- const int smooth_falloff = RNA_enum_get(op->ptr, "falloff");
+ RingSelOpData *lcd = op->customdata;
+ const int cuts = RNA_int_get(op->ptr, "number_cuts");
+ const float smoothness = RNA_float_get(op->ptr, "smoothness");
+ const int smooth_falloff = RNA_enum_get(op->ptr, "falloff");
#ifdef BMW_EDGERING_NGON
- const bool use_only_quads = false;
+ const bool use_only_quads = false;
#else
- const bool use_only_quads = false;
+ const bool use_only_quads = false;
#endif
- if (lcd->eed) {
- BMEditMesh *em = lcd->em;
- BMVert *v_eed_orig[2] = {lcd->eed->v1, lcd->eed->v2};
-
- edgering_select(lcd);
-
- if (lcd->do_cut) {
- const bool is_macro = (op->opm != NULL);
- /* a single edge (rare, but better support) */
- const bool is_single = (BM_edge_is_wire(lcd->eed));
- const int seltype = is_single ? SUBDIV_SELECT_INNER : SUBDIV_SELECT_LOOPCUT;
-
- /* Enable gridfill, so that intersecting loopcut works as one would expect.
- * Note though that it will break edgeslide in this specific case.
- * See [#31939]. */
- BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT,
- smoothness, smooth_falloff, true,
- 0.0f, 0.0f,
- cuts, seltype, SUBD_CORNER_PATH, 0, true,
- use_only_quads, 0);
-
- /* when used in a macro the tessfaces will be recalculated anyway,
- * this is needed here because modifiers depend on updated tessellation, see T45920 */
- EDBM_update_generic(em, true, true);
-
- if (is_single) {
- /* de-select endpoints */
- BM_vert_select_set(em->bm, v_eed_orig[0], false);
- BM_vert_select_set(em->bm, v_eed_orig[1], false);
-
- EDBM_selectmode_flush_ex(lcd->em, SCE_SELECT_VERTEX);
- }
- /* we cant slide multiple edges in vertex select mode */
- else if (is_macro && (cuts > 1) && (em->selectmode & SCE_SELECT_VERTEX)) {
- EDBM_selectmode_disable(lcd->vc.scene, em, SCE_SELECT_VERTEX, SCE_SELECT_EDGE);
- }
- /* force edge slide to edge select mode in in face select mode */
- else if (EDBM_selectmode_disable(lcd->vc.scene, em, SCE_SELECT_FACE, SCE_SELECT_EDGE)) {
- /* pass, the change will flush selection */
- }
- else {
- /* else flush explicitly */
- EDBM_selectmode_flush(lcd->em);
- }
- }
- else {
- /* XXX Is this piece of code ever used now? Simple loop select is now
- * in editmesh_select.c (around line 1000)... */
- /* sets as active, useful for other tools */
- if (em->selectmode & SCE_SELECT_VERTEX) {
- /* low priority TODO, get vertrex close to mouse */
- BM_select_history_store(em->bm, lcd->eed->v1);
- }
- if (em->selectmode & SCE_SELECT_EDGE) {
- BM_select_history_store(em->bm, lcd->eed);
- }
-
- EDBM_selectmode_flush(lcd->em);
- DEG_id_tag_update(lcd->ob->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, lcd->ob->data);
- }
- }
+ if (lcd->eed) {
+ BMEditMesh *em = lcd->em;
+ BMVert *v_eed_orig[2] = {lcd->eed->v1, lcd->eed->v2};
+
+ edgering_select(lcd);
+
+ if (lcd->do_cut) {
+ const bool is_macro = (op->opm != NULL);
+ /* a single edge (rare, but better support) */
+ const bool is_single = (BM_edge_is_wire(lcd->eed));
+ const int seltype = is_single ? SUBDIV_SELECT_INNER : SUBDIV_SELECT_LOOPCUT;
+
+ /* Enable gridfill, so that intersecting loopcut works as one would expect.
+ * Note though that it will break edgeslide in this specific case.
+ * See [#31939]. */
+ BM_mesh_esubdivide(em->bm,
+ BM_ELEM_SELECT,
+ smoothness,
+ smooth_falloff,
+ true,
+ 0.0f,
+ 0.0f,
+ cuts,
+ seltype,
+ SUBD_CORNER_PATH,
+ 0,
+ true,
+ use_only_quads,
+ 0);
+
+ /* when used in a macro the tessfaces will be recalculated anyway,
+ * this is needed here because modifiers depend on updated tessellation, see T45920 */
+ EDBM_update_generic(em, true, true);
+
+ if (is_single) {
+ /* de-select endpoints */
+ BM_vert_select_set(em->bm, v_eed_orig[0], false);
+ BM_vert_select_set(em->bm, v_eed_orig[1], false);
+
+ EDBM_selectmode_flush_ex(lcd->em, SCE_SELECT_VERTEX);
+ }
+ /* we cant slide multiple edges in vertex select mode */
+ else if (is_macro && (cuts > 1) && (em->selectmode & SCE_SELECT_VERTEX)) {
+ EDBM_selectmode_disable(lcd->vc.scene, em, SCE_SELECT_VERTEX, SCE_SELECT_EDGE);
+ }
+ /* force edge slide to edge select mode in in face select mode */
+ else if (EDBM_selectmode_disable(lcd->vc.scene, em, SCE_SELECT_FACE, SCE_SELECT_EDGE)) {
+ /* pass, the change will flush selection */
+ }
+ else {
+ /* else flush explicitly */
+ EDBM_selectmode_flush(lcd->em);
+ }
+ }
+ else {
+ /* XXX Is this piece of code ever used now? Simple loop select is now
+ * in editmesh_select.c (around line 1000)... */
+ /* sets as active, useful for other tools */
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ /* low priority TODO, get vertrex close to mouse */
+ BM_select_history_store(em->bm, lcd->eed->v1);
+ }
+ if (em->selectmode & SCE_SELECT_EDGE) {
+ BM_select_history_store(em->bm, lcd->eed);
+ }
+
+ EDBM_selectmode_flush(lcd->em);
+ DEG_id_tag_update(lcd->ob->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, lcd->ob->data);
+ }
+ }
}
/* called when modal loop selection is done... */
static void ringsel_exit(bContext *UNUSED(C), wmOperator *op)
{
- RingSelOpData *lcd = op->customdata;
+ RingSelOpData *lcd = op->customdata;
- /* deactivate the extra drawing stuff in 3D-View */
- ED_region_draw_cb_exit(lcd->ar->type, lcd->draw_handle);
+ /* deactivate the extra drawing stuff in 3D-View */
+ ED_region_draw_cb_exit(lcd->ar->type, lcd->draw_handle);
- EDBM_preselect_edgering_destroy(lcd->presel_edgering);
+ EDBM_preselect_edgering_destroy(lcd->presel_edgering);
- MEM_freeN(lcd->objects);
+ MEM_freeN(lcd->objects);
- ED_region_tag_redraw(lcd->ar);
+ ED_region_tag_redraw(lcd->ar);
- /* free the custom data */
- MEM_freeN(lcd);
- op->customdata = NULL;
+ /* free the custom data */
+ MEM_freeN(lcd);
+ op->customdata = NULL;
}
-
/* called when modal loop selection gets set up... */
static int ringsel_init(bContext *C, wmOperator *op, bool do_cut)
{
- RingSelOpData *lcd;
- Scene *scene = CTX_data_scene(C);
-
- /* alloc new customdata */
- lcd = op->customdata = MEM_callocN(sizeof(RingSelOpData), "ringsel Modal Op Data");
-
- em_setup_viewcontext(C, &lcd->vc);
-
- lcd->depsgraph = CTX_data_depsgraph(C);
-
- /* assign the drawing handle for drawing preview line... */
- lcd->ar = CTX_wm_region(C);
- lcd->draw_handle = ED_region_draw_cb_activate(lcd->ar->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;
- lcd->em = NULL;
- lcd->extend = do_cut ? false : RNA_boolean_get(op->ptr, "extend");
- lcd->do_cut = do_cut;
- lcd->cuts = RNA_int_get(op->ptr, "number_cuts");
- lcd->smoothness = RNA_float_get(op->ptr, "smoothness");
-
- initNumInput(&lcd->num);
- lcd->num.idx_max = 1;
- lcd->num.val_flag[0] |= NUM_NO_NEGATIVE | NUM_NO_FRACTION;
- /* No specific flags for smoothness. */
- lcd->num.unit_sys = scene->unit.system;
- lcd->num.unit_type[0] = B_UNIT_NONE;
- lcd->num.unit_type[1] = B_UNIT_NONE;
-
- ED_region_tag_redraw(lcd->ar);
-
- return 1;
+ RingSelOpData *lcd;
+ Scene *scene = CTX_data_scene(C);
+
+ /* alloc new customdata */
+ lcd = op->customdata = MEM_callocN(sizeof(RingSelOpData), "ringsel Modal Op Data");
+
+ em_setup_viewcontext(C, &lcd->vc);
+
+ lcd->depsgraph = CTX_data_depsgraph(C);
+
+ /* assign the drawing handle for drawing preview line... */
+ lcd->ar = CTX_wm_region(C);
+ lcd->draw_handle = ED_region_draw_cb_activate(
+ lcd->ar->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;
+ lcd->em = NULL;
+ lcd->extend = do_cut ? false : RNA_boolean_get(op->ptr, "extend");
+ lcd->do_cut = do_cut;
+ lcd->cuts = RNA_int_get(op->ptr, "number_cuts");
+ lcd->smoothness = RNA_float_get(op->ptr, "smoothness");
+
+ initNumInput(&lcd->num);
+ lcd->num.idx_max = 1;
+ lcd->num.val_flag[0] |= NUM_NO_NEGATIVE | NUM_NO_FRACTION;
+ /* No specific flags for smoothness. */
+ lcd->num.unit_sys = scene->unit.system;
+ lcd->num.unit_type[0] = B_UNIT_NONE;
+ lcd->num.unit_type[1] = B_UNIT_NONE;
+
+ ED_region_tag_redraw(lcd->ar);
+
+ return 1;
}
static void ringcut_cancel(bContext *C, wmOperator *op)
{
- /* this is just a wrapper around exit() */
- ringsel_exit(C, op);
+ /* this is just a wrapper around exit() */
+ ringsel_exit(C, op);
}
-static void loopcut_update_edge(RingSelOpData *lcd, uint ob_index, BMEdge *e, const int previewlines)
+static void loopcut_update_edge(RingSelOpData *lcd,
+ uint ob_index,
+ BMEdge *e,
+ const int previewlines)
{
- if (e != lcd->eed) {
- lcd->eed = e;
- lcd->ob = lcd->vc.obedit;
- lcd->ob_index = ob_index;
- lcd->em = lcd->vc.em;
- ringsel_find_edge(lcd, previewlines);
- }
- else if (e == NULL) {
- lcd->ob = NULL;
- lcd->em = NULL;
- lcd->ob_index = UINT_MAX;
- }
+ if (e != lcd->eed) {
+ lcd->eed = e;
+ lcd->ob = lcd->vc.obedit;
+ lcd->ob_index = ob_index;
+ lcd->em = lcd->vc.em;
+ ringsel_find_edge(lcd, previewlines);
+ }
+ else if (e == NULL) {
+ lcd->ob = NULL;
+ lcd->em = NULL;
+ lcd->ob_index = UINT_MAX;
+ }
}
static void loopcut_mouse_move(RingSelOpData *lcd, const int previewlines)
{
- struct {
- Object *ob;
- BMEdge *eed;
- float dist;
- int ob_index;
- } best = {
- .dist = ED_view3d_select_dist_px(),
- };
-
- for (uint ob_index = 0; ob_index < lcd->objects_len; ob_index++) {
- Object *ob_iter = lcd->objects[ob_index];
- ED_view3d_viewcontext_init_object(&lcd->vc, ob_iter);
- BMEdge *eed_test = EDBM_edge_find_nearest_ex(&lcd->vc, &best.dist, NULL, false, false, NULL);
- if (eed_test) {
- best.ob = ob_iter;
- best.eed = eed_test;
- best.ob_index = ob_index;
- }
- }
-
- if (best.eed) {
- ED_view3d_viewcontext_init_object(&lcd->vc, best.ob);
- }
-
- loopcut_update_edge(lcd, best.ob_index, best.eed, previewlines);
+ struct {
+ Object *ob;
+ BMEdge *eed;
+ float dist;
+ int ob_index;
+ } best = {
+ .dist = ED_view3d_select_dist_px(),
+ };
+
+ for (uint ob_index = 0; ob_index < lcd->objects_len; ob_index++) {
+ Object *ob_iter = lcd->objects[ob_index];
+ ED_view3d_viewcontext_init_object(&lcd->vc, ob_iter);
+ BMEdge *eed_test = EDBM_edge_find_nearest_ex(&lcd->vc, &best.dist, NULL, false, false, NULL);
+ if (eed_test) {
+ best.ob = ob_iter;
+ best.eed = eed_test;
+ best.ob_index = ob_index;
+ }
+ }
+
+ if (best.eed) {
+ ED_view3d_viewcontext_init_object(&lcd->vc, best.ob);
+ }
+
+ loopcut_update_edge(lcd, best.ob_index, best.eed, previewlines);
}
/* called by both init() and exec() */
static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
{
- const bool is_interactive = (event != NULL);
-
- /* Use for redo - intentionally wrap int to uint. */
- const struct {
- uint ob_index;
- uint e_index;
- } exec_data = {
- .ob_index = (uint)RNA_int_get(op->ptr, "object_index"),
- .e_index = (uint)RNA_int_get(op->ptr, "edge_index"),
- };
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(view_layer, CTX_wm_view3d(C), &objects_len);
-
- if (is_interactive) {
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob_iter = objects[ob_index];
- if (modifiers_isDeformedByLattice(ob_iter) || modifiers_isDeformedByArmature(ob_iter)) {
- BKE_report(op->reports, RPT_WARNING, "Loop cut does not work well on deformed edit mesh display");
- break;
- }
- }
- }
-
- view3d_operator_needs_opengl(C);
-
- /* for re-execution, check edge index is in range before we setup ringsel */
- bool ok = true;
- if (is_interactive == false) {
- if (exec_data.ob_index >= objects_len) {
- return OPERATOR_CANCELLED;
- ok = false;
- }
- else {
- Object *ob_iter = objects[exec_data.ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(ob_iter);
- if (exec_data.e_index >= em->bm->totedge) {
- ok = false;
- }
- }
- }
-
- if (!ok || !ringsel_init(C, op, true)) {
- MEM_freeN(objects);
- return OPERATOR_CANCELLED;
- }
-
- /* add a modal handler for this operator - handles loop selection */
- if (is_interactive) {
- op->flag |= OP_IS_MODAL_CURSOR_REGION;
- WM_event_add_modal_handler(C, op);
- }
-
- RingSelOpData *lcd = op->customdata;
-
- lcd->objects = objects;
- lcd->objects_len = objects_len;
-
- if (is_interactive) {
- copy_v2_v2_int(lcd->vc.mval, event->mval);
- loopcut_mouse_move(lcd, is_interactive ? 1 : 0);
- }
- else {
-
- Object *ob_iter = objects[exec_data.ob_index];
- ED_view3d_viewcontext_init_object(&lcd->vc, ob_iter);
-
- BMEdge *e;
- BM_mesh_elem_table_ensure(lcd->vc.em->bm, BM_EDGE);
- e = BM_edge_at_index(lcd->vc.em->bm, exec_data.e_index);
- loopcut_update_edge(lcd, exec_data.ob_index, e, 0);
- }
+ const bool is_interactive = (event != NULL);
+
+ /* Use for redo - intentionally wrap int to uint. */
+ const struct {
+ uint ob_index;
+ uint e_index;
+ } exec_data = {
+ .ob_index = (uint)RNA_int_get(op->ptr, "object_index"),
+ .e_index = (uint)RNA_int_get(op->ptr, "edge_index"),
+ };
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ if (is_interactive) {
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob_iter = objects[ob_index];
+ if (modifiers_isDeformedByLattice(ob_iter) || modifiers_isDeformedByArmature(ob_iter)) {
+ BKE_report(
+ op->reports, RPT_WARNING, "Loop cut does not work well on deformed edit mesh display");
+ break;
+ }
+ }
+ }
+
+ view3d_operator_needs_opengl(C);
+
+ /* for re-execution, check edge index is in range before we setup ringsel */
+ bool ok = true;
+ if (is_interactive == false) {
+ if (exec_data.ob_index >= objects_len) {
+ return OPERATOR_CANCELLED;
+ ok = false;
+ }
+ else {
+ Object *ob_iter = objects[exec_data.ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(ob_iter);
+ if (exec_data.e_index >= em->bm->totedge) {
+ ok = false;
+ }
+ }
+ }
+
+ if (!ok || !ringsel_init(C, op, true)) {
+ MEM_freeN(objects);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* add a modal handler for this operator - handles loop selection */
+ if (is_interactive) {
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+ WM_event_add_modal_handler(C, op);
+ }
+
+ RingSelOpData *lcd = op->customdata;
+
+ lcd->objects = objects;
+ lcd->objects_len = objects_len;
+
+ if (is_interactive) {
+ copy_v2_v2_int(lcd->vc.mval, event->mval);
+ loopcut_mouse_move(lcd, is_interactive ? 1 : 0);
+ }
+ else {
+
+ Object *ob_iter = objects[exec_data.ob_index];
+ ED_view3d_viewcontext_init_object(&lcd->vc, ob_iter);
+
+ BMEdge *e;
+ BM_mesh_elem_table_ensure(lcd->vc.em->bm, BM_EDGE);
+ e = BM_edge_at_index(lcd->vc.em->bm, exec_data.e_index);
+ loopcut_update_edge(lcd, exec_data.ob_index, e, 0);
+ }
#ifdef USE_LOOPSLIDE_HACK
- /* for use in macro so we can restore, HACK */
- {
- Scene *scene = CTX_data_scene(C);
- ToolSettings *settings = scene->toolsettings;
- const bool mesh_select_mode[3] = {
- (settings->selectmode & SCE_SELECT_VERTEX) != 0,
- (settings->selectmode & SCE_SELECT_EDGE) != 0,
- (settings->selectmode & SCE_SELECT_FACE) != 0,
- };
-
- RNA_boolean_set_array(op->ptr, "mesh_select_mode_init", mesh_select_mode);
- }
+ /* for use in macro so we can restore, HACK */
+ {
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *settings = scene->toolsettings;
+ const bool mesh_select_mode[3] = {
+ (settings->selectmode & SCE_SELECT_VERTEX) != 0,
+ (settings->selectmode & SCE_SELECT_EDGE) != 0,
+ (settings->selectmode & SCE_SELECT_FACE) != 0,
+ };
+
+ RNA_boolean_set_array(op->ptr, "mesh_select_mode_init", mesh_select_mode);
+ }
#endif
- if (is_interactive) {
- ED_workspace_status_text(C, IFACE_("Select a ring to be cut, use mouse-wheel or page-up/down for number of cuts, "
- "hold Alt for smooth"));
- return OPERATOR_RUNNING_MODAL;
- }
- else {
- ringsel_finish(C, op);
- ringsel_exit(C, op);
- return OPERATOR_FINISHED;
- }
+ if (is_interactive) {
+ ED_workspace_status_text(
+ C,
+ IFACE_("Select a ring to be cut, use mouse-wheel or page-up/down for number of cuts, "
+ "hold Alt for smooth"));
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ ringsel_finish(C, op);
+ ringsel_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
}
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;
- wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap, "VIEW3D_GGT_mesh_preselect_edgering") : NULL;
- if ((gzgroup != NULL) && gzgroup->gizmos.first) {
- wmGizmo *gz = gzgroup->gizmos.first;
- const int object_index = RNA_int_get(gz->ptr, "object_index");
- const int edge_index = RNA_int_get(gz->ptr, "edge_index");
-
- if (object_index != -1 && edge_index != -1) {
- RNA_int_set(op->ptr, "object_index", object_index);
- RNA_int_set(op->ptr, "edge_index", edge_index);
- return loopcut_init(C, op, NULL);
- }
- return OPERATOR_CANCELLED;
- }
- }
-
- return loopcut_init(C, op, 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;
+ wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap,
+ "VIEW3D_GGT_mesh_preselect_edgering") :
+ NULL;
+ if ((gzgroup != NULL) && gzgroup->gizmos.first) {
+ wmGizmo *gz = gzgroup->gizmos.first;
+ const int object_index = RNA_int_get(gz->ptr, "object_index");
+ const int edge_index = RNA_int_get(gz->ptr, "edge_index");
+
+ if (object_index != -1 && edge_index != -1) {
+ RNA_int_set(op->ptr, "object_index", object_index);
+ RNA_int_set(op->ptr, "edge_index", edge_index);
+ return loopcut_init(C, op, NULL);
+ }
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ return loopcut_init(C, op, event);
}
static int loopcut_exec(bContext *C, wmOperator *op)
{
- return loopcut_init(C, op, NULL);
+ return loopcut_init(C, op, NULL);
}
static int loopcut_finish(RingSelOpData *lcd, bContext *C, wmOperator *op)
{
- /* finish */
- ED_region_tag_redraw(lcd->ar);
- ED_workspace_status_text(C, NULL);
-
- if (lcd->eed) {
- /* set for redo */
- BM_mesh_elem_index_ensure(lcd->em->bm, BM_EDGE);
- RNA_int_set(op->ptr, "object_index", lcd->ob_index);
- RNA_int_set(op->ptr, "edge_index", BM_elem_index_get(lcd->eed));
-
- /* execute */
- ringsel_finish(C, op);
- ringsel_exit(C, op);
- }
- else {
- ringcut_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ /* finish */
+ ED_region_tag_redraw(lcd->ar);
+ ED_workspace_status_text(C, NULL);
+
+ if (lcd->eed) {
+ /* set for redo */
+ BM_mesh_elem_index_ensure(lcd->em->bm, BM_EDGE);
+ RNA_int_set(op->ptr, "object_index", lcd->ob_index);
+ RNA_int_set(op->ptr, "edge_index", BM_elem_index_get(lcd->eed));
+
+ /* execute */
+ ringsel_finish(C, op);
+ ringsel_exit(C, op);
+ }
+ else {
+ ringcut_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- RingSelOpData *lcd = op->customdata;
- float cuts = lcd->cuts;
- float smoothness = lcd->smoothness;
- bool show_cuts = false;
- const bool has_numinput = hasNumInput(&lcd->num);
-
- em_setup_viewcontext(C, &lcd->vc);
- lcd->ar = lcd->vc.ar;
-
- view3d_operator_needs_opengl(C);
-
- /* using the keyboard to input the number of cuts */
- /* Modal numinput active, try to handle numeric inputs first... */
- if (event->val == KM_PRESS && has_numinput && handleNumInput(C, &lcd->num, event)) {
- float values[2] = {cuts, smoothness};
- applyNumInput(&lcd->num, values);
- cuts = values[0];
- smoothness = values[1];
- }
- else {
- bool handled = false;
- switch (event->type) {
- case RETKEY:
- case PADENTER:
- case LEFTMOUSE: /* confirm */ // XXX hardcoded
- if (event->val == KM_PRESS)
- return loopcut_finish(lcd, C, op);
-
- ED_region_tag_redraw(lcd->ar);
- handled = true;
- break;
- case RIGHTMOUSE: /* abort */ // XXX hardcoded
- ED_region_tag_redraw(lcd->ar);
- ringsel_exit(C, op);
- ED_workspace_status_text(C, NULL);
-
- return OPERATOR_CANCELLED;
- case ESCKEY:
- if (event->val == KM_RELEASE) {
- /* cancel */
- ED_region_tag_redraw(lcd->ar);
- ED_workspace_status_text(C, NULL);
-
- ringcut_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
-
- ED_region_tag_redraw(lcd->ar);
- handled = true;
- break;
- case MOUSEPAN:
- if (event->alt == 0) {
- cuts += 0.02f * (event->y - event->prevy);
- if (cuts < 1 && lcd->cuts >= 1)
- cuts = 1;
- }
- else {
- smoothness += 0.002f * (event->y - event->prevy);
- }
- handled = true;
- break;
- case PADPLUSKEY:
- case PAGEUPKEY:
- case WHEELUPMOUSE: /* change number of cuts */
- if (event->val == KM_RELEASE)
- break;
- if (event->alt == 0) {
- cuts += 1;
- }
- else {
- smoothness += 0.05f;
- }
- handled = true;
- break;
- case PADMINUS:
- case PAGEDOWNKEY:
- case WHEELDOWNMOUSE: /* change number of cuts */
- if (event->val == KM_RELEASE)
- break;
- if (event->alt == 0) {
- cuts = max_ff(cuts - 1, 1);
- }
- else {
- smoothness -= 0.05f;
- }
- handled = true;
- break;
- case MOUSEMOVE: /* mouse moved somewhere to select another loop */
-
- /* This is normally disabled for all modal operators.
- * This is an exception since mouse movement doesn't relate to numeric input.
- *
- * If numeric input changes we'll need to add this back see: D2973 */
+ RingSelOpData *lcd = op->customdata;
+ float cuts = lcd->cuts;
+ float smoothness = lcd->smoothness;
+ bool show_cuts = false;
+ const bool has_numinput = hasNumInput(&lcd->num);
+
+ em_setup_viewcontext(C, &lcd->vc);
+ lcd->ar = lcd->vc.ar;
+
+ view3d_operator_needs_opengl(C);
+
+ /* using the keyboard to input the number of cuts */
+ /* Modal numinput active, try to handle numeric inputs first... */
+ if (event->val == KM_PRESS && has_numinput && handleNumInput(C, &lcd->num, event)) {
+ float values[2] = {cuts, smoothness};
+ applyNumInput(&lcd->num, values);
+ cuts = values[0];
+ smoothness = values[1];
+ }
+ else {
+ bool handled = false;
+ switch (event->type) {
+ case RETKEY:
+ case PADENTER:
+ case LEFTMOUSE: /* confirm */ // XXX hardcoded
+ if (event->val == KM_PRESS)
+ return loopcut_finish(lcd, C, op);
+
+ ED_region_tag_redraw(lcd->ar);
+ handled = true;
+ break;
+ case RIGHTMOUSE: /* abort */ // XXX hardcoded
+ ED_region_tag_redraw(lcd->ar);
+ ringsel_exit(C, op);
+ ED_workspace_status_text(C, NULL);
+
+ return OPERATOR_CANCELLED;
+ case ESCKEY:
+ if (event->val == KM_RELEASE) {
+ /* cancel */
+ ED_region_tag_redraw(lcd->ar);
+ ED_workspace_status_text(C, NULL);
+
+ ringcut_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_region_tag_redraw(lcd->ar);
+ handled = true;
+ break;
+ case MOUSEPAN:
+ if (event->alt == 0) {
+ cuts += 0.02f * (event->y - event->prevy);
+ if (cuts < 1 && lcd->cuts >= 1)
+ cuts = 1;
+ }
+ else {
+ smoothness += 0.002f * (event->y - event->prevy);
+ }
+ handled = true;
+ break;
+ case PADPLUSKEY:
+ case PAGEUPKEY:
+ case WHEELUPMOUSE: /* change number of cuts */
+ if (event->val == KM_RELEASE)
+ break;
+ if (event->alt == 0) {
+ cuts += 1;
+ }
+ else {
+ smoothness += 0.05f;
+ }
+ handled = true;
+ break;
+ case PADMINUS:
+ case PAGEDOWNKEY:
+ case WHEELDOWNMOUSE: /* change number of cuts */
+ if (event->val == KM_RELEASE)
+ break;
+ if (event->alt == 0) {
+ cuts = max_ff(cuts - 1, 1);
+ }
+ else {
+ smoothness -= 0.05f;
+ }
+ handled = true;
+ break;
+ case MOUSEMOVE: /* mouse moved somewhere to select another loop */
+
+ /* This is normally disabled for all modal operators.
+ * This is an exception since mouse movement doesn't relate to numeric input.
+ *
+ * If numeric input changes we'll need to add this back see: D2973 */
#if 0
- if (!has_numinput)
+ if (!has_numinput)
#endif
- {
- lcd->vc.mval[0] = event->mval[0];
- lcd->vc.mval[1] = event->mval[1];
- loopcut_mouse_move(lcd, (int)lcd->cuts);
-
- ED_region_tag_redraw(lcd->ar);
- handled = true;
- }
- break;
- }
-
- /* Modal numinput inactive, try to handle numeric inputs last... */
- if (!handled && event->val == KM_PRESS && handleNumInput(C, &lcd->num, event)) {
- float values[2] = {cuts, smoothness};
- applyNumInput(&lcd->num, values);
- cuts = values[0];
- smoothness = values[1];
- }
- }
-
- if (cuts != lcd->cuts) {
- /* allow zero so you can backspace and type in a value
- * otherwise 1 as minimum would make more sense */
- lcd->cuts = clamp_i(cuts, 0, SUBD_CUTS_MAX);
- 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);
- }
-
- 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);
- }
-
- if (show_cuts) {
- Scene *sce = CTX_data_scene(C);
- char buf[UI_MAX_DRAW_STR];
- char str_rep[NUM_STR_REP_LEN * 2];
- if (hasNumInput(&lcd->num)) {
- outputNumInput(&lcd->num, str_rep, &sce->unit);
- }
- else {
- BLI_snprintf(str_rep, NUM_STR_REP_LEN, "%d", (int)lcd->cuts);
- BLI_snprintf(str_rep + NUM_STR_REP_LEN, NUM_STR_REP_LEN, "%.2f", smoothness);
- }
- BLI_snprintf(buf, sizeof(buf), IFACE_("Number of Cuts: %s, Smooth: %s (Alt)"),
- str_rep, str_rep + NUM_STR_REP_LEN);
- ED_workspace_status_text(C, buf);
- }
-
- /* keep going until the user confirms */
- return OPERATOR_RUNNING_MODAL;
+ {
+ lcd->vc.mval[0] = event->mval[0];
+ lcd->vc.mval[1] = event->mval[1];
+ loopcut_mouse_move(lcd, (int)lcd->cuts);
+
+ ED_region_tag_redraw(lcd->ar);
+ handled = true;
+ } break;
+ }
+
+ /* Modal numinput inactive, try to handle numeric inputs last... */
+ if (!handled && event->val == KM_PRESS && handleNumInput(C, &lcd->num, event)) {
+ float values[2] = {cuts, smoothness};
+ applyNumInput(&lcd->num, values);
+ cuts = values[0];
+ smoothness = values[1];
+ }
+ }
+
+ if (cuts != lcd->cuts) {
+ /* allow zero so you can backspace and type in a value
+ * otherwise 1 as minimum would make more sense */
+ lcd->cuts = clamp_i(cuts, 0, SUBD_CUTS_MAX);
+ 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);
+ }
+
+ 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);
+ }
+
+ if (show_cuts) {
+ Scene *sce = CTX_data_scene(C);
+ char buf[UI_MAX_DRAW_STR];
+ char str_rep[NUM_STR_REP_LEN * 2];
+ if (hasNumInput(&lcd->num)) {
+ outputNumInput(&lcd->num, str_rep, &sce->unit);
+ }
+ else {
+ BLI_snprintf(str_rep, NUM_STR_REP_LEN, "%d", (int)lcd->cuts);
+ BLI_snprintf(str_rep + NUM_STR_REP_LEN, NUM_STR_REP_LEN, "%.2f", smoothness);
+ }
+ BLI_snprintf(buf,
+ sizeof(buf),
+ IFACE_("Number of Cuts: %s, Smooth: %s (Alt)"),
+ str_rep,
+ str_rep + NUM_STR_REP_LEN);
+ ED_workspace_status_text(C, buf);
+ }
+
+ /* keep going until the user confirms */
+ return OPERATOR_RUNNING_MODAL;
}
/* for bmesh this tool is in bmesh_select.c */
@@ -655,68 +680,75 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
void MESH_OT_edgering_select(wmOperatorType *ot)
{
- /* description */
- ot->name = "Edge Ring Select";
- ot->idname = "MESH_OT_edgering_select";
- ot->description = "Select an edge ring";
+ /* description */
+ ot->name = "Edge Ring Select";
+ ot->idname = "MESH_OT_edgering_select";
+ ot->description = "Select an edge ring";
- /* callbacks */
- ot->invoke = ringsel_invoke;
- ot->poll = ED_operator_editmesh_region_view3d;
+ /* callbacks */
+ ot->invoke = ringsel_invoke;
+ ot->poll = ED_operator_editmesh_region_view3d;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
}
#endif
void MESH_OT_loopcut(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* description */
- ot->name = "Loop Cut";
- ot->idname = "MESH_OT_loopcut";
- ot->description = "Add a new loop between existing loops";
-
- /* callbacks */
- ot->invoke = ringcut_invoke;
- ot->exec = loopcut_exec;
- ot->modal = loopcut_modal;
- ot->cancel = ringcut_cancel;
- ot->poll = ED_operator_editmesh_region_view3d;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* properties */
- prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000000, "Number of Cuts", "", 1, 100);
- /* avoid re-using last var because it can cause
- * _very_ high poly meshes and annoy users (or worse crash) */
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- prop = RNA_def_float(ot->srna, "smoothness", 0.0f, -1e3f, 1e3f,
- "Smoothness", "Smoothness factor", -SUBD_SMOOTH_MAX, SUBD_SMOOTH_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- WM_operatortype_props_advanced_begin(ot);
-
- prop = RNA_def_property(ot->srna, "falloff", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, rna_enum_proportional_falloff_curve_only_items);
- RNA_def_property_enum_default(prop, PROP_INVSQUARE);
- RNA_def_property_ui_text(prop, "Falloff", "Falloff type the feather");
- RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
-
- /* For redo only. */
- prop = RNA_def_int(ot->srna, "object_index", -1, -1, INT_MAX, "Object Index", "", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
- prop = RNA_def_int(ot->srna, "edge_index", -1, -1, INT_MAX, "Edge Index", "", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop;
+
+ /* description */
+ ot->name = "Loop Cut";
+ ot->idname = "MESH_OT_loopcut";
+ ot->description = "Add a new loop between existing loops";
+
+ /* callbacks */
+ ot->invoke = ringcut_invoke;
+ ot->exec = loopcut_exec;
+ ot->modal = loopcut_modal;
+ ot->cancel = ringcut_cancel;
+ ot->poll = ED_operator_editmesh_region_view3d;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* properties */
+ prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000000, "Number of Cuts", "", 1, 100);
+ /* avoid re-using last var because it can cause
+ * _very_ high poly meshes and annoy users (or worse crash) */
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_float(ot->srna,
+ "smoothness",
+ 0.0f,
+ -1e3f,
+ 1e3f,
+ "Smoothness",
+ "Smoothness factor",
+ -SUBD_SMOOTH_MAX,
+ SUBD_SMOOTH_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ prop = RNA_def_property(ot->srna, "falloff", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_enum_proportional_falloff_curve_only_items);
+ RNA_def_property_enum_default(prop, PROP_INVSQUARE);
+ RNA_def_property_ui_text(prop, "Falloff", "Falloff type the feather");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
+
+ /* For redo only. */
+ prop = RNA_def_int(ot->srna, "object_index", -1, -1, INT_MAX, "Object Index", "", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_int(ot->srna, "edge_index", -1, -1, INT_MAX, "Edge Index", "", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
#ifdef USE_LOOPSLIDE_HACK
- prop = RNA_def_boolean_array(ot->srna, "mesh_select_mode_init", 3, NULL, "", "");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_boolean_array(ot->srna, "mesh_select_mode_init", 3, NULL, "", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
#endif
}
diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c
index d16cd639c0d..c6b1ab9f1f2 100644
--- a/source/blender/editors/mesh/editmesh_path.c
+++ b/source/blender/editors/mesh/editmesh_path.c
@@ -57,50 +57,56 @@
#include "DEG_depsgraph.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Path Select Struct & Properties
* \{ */
struct PathSelectParams {
- /** ensure the active element is the last selected item (handy for picking) */
- bool track_active;
- bool use_topology_distance;
- bool use_face_step;
- bool use_fill;
- char edge_mode;
- struct CheckerIntervalParams interval_params;
+ /** ensure the active element is the last selected item (handy for picking) */
+ bool track_active;
+ bool use_topology_distance;
+ bool use_face_step;
+ bool use_fill;
+ char edge_mode;
+ struct CheckerIntervalParams interval_params;
};
static void path_select_properties(wmOperatorType *ot)
{
- RNA_def_boolean(
- ot->srna, "use_face_step", false, "Face Stepping",
- "Traverse connected faces (includes diagonals and edge-rings)");
- RNA_def_boolean(
- ot->srna, "use_topology_distance", false, "Topology Distance",
- "Find the minimum number of steps, ignoring spatial distance");
- RNA_def_boolean(
- ot->srna, "use_fill", false, "Fill Region",
- "Select all paths between the source/destination elements");
- WM_operator_properties_checker_interval(ot, true);
+ RNA_def_boolean(ot->srna,
+ "use_face_step",
+ false,
+ "Face Stepping",
+ "Traverse connected faces (includes diagonals and edge-rings)");
+ RNA_def_boolean(ot->srna,
+ "use_topology_distance",
+ false,
+ "Topology Distance",
+ "Find the minimum number of steps, ignoring spatial distance");
+ RNA_def_boolean(ot->srna,
+ "use_fill",
+ false,
+ "Fill Region",
+ "Select all paths between the source/destination elements");
+ WM_operator_properties_checker_interval(ot, true);
}
static void path_select_params_from_op(wmOperator *op, struct PathSelectParams *op_params)
{
- op_params->edge_mode = EDGE_MODE_SELECT;
- op_params->track_active = false;
- op_params->use_face_step = RNA_boolean_get(op->ptr, "use_face_step");
- op_params->use_fill = RNA_boolean_get(op->ptr, "use_fill");
- op_params->use_topology_distance = RNA_boolean_get(op->ptr, "use_topology_distance");
- WM_operator_properties_checker_interval_from_op(op, &op_params->interval_params);
+ op_params->edge_mode = EDGE_MODE_SELECT;
+ op_params->track_active = false;
+ op_params->use_face_step = RNA_boolean_get(op->ptr, "use_face_step");
+ op_params->use_fill = RNA_boolean_get(op->ptr, "use_fill");
+ op_params->use_topology_distance = RNA_boolean_get(op->ptr, "use_topology_distance");
+ WM_operator_properties_checker_interval_from_op(op, &op_params->interval_params);
}
struct UserData {
- BMesh *bm;
- Mesh *me;
- const struct PathSelectParams *op_params;
+ BMesh *bm;
+ Mesh *me;
+ const struct PathSelectParams *op_params;
};
/** \} */
@@ -112,102 +118,104 @@ struct UserData {
/* callbacks */
static bool verttag_filter_cb(BMVert *v, void *UNUSED(user_data_v))
{
- return !BM_elem_flag_test(v, BM_ELEM_HIDDEN);
+ return !BM_elem_flag_test(v, BM_ELEM_HIDDEN);
}
static bool verttag_test_cb(BMVert *v, void *UNUSED(user_data_v))
{
- return BM_elem_flag_test_bool(v, BM_ELEM_SELECT);
+ return BM_elem_flag_test_bool(v, BM_ELEM_SELECT);
}
static void verttag_set_cb(BMVert *v, bool val, void *user_data_v)
{
- struct UserData *user_data = user_data_v;
- BM_vert_select_set(user_data->bm, v, val);
+ struct UserData *user_data = user_data_v;
+ BM_vert_select_set(user_data->bm, v, val);
}
-static void mouse_mesh_shortest_path_vert(
- Scene *UNUSED(scene), Object *obedit, const struct PathSelectParams *op_params,
- BMVert *v_act, BMVert *v_dst)
+static void mouse_mesh_shortest_path_vert(Scene *UNUSED(scene),
+ Object *obedit,
+ const struct PathSelectParams *op_params,
+ BMVert *v_act,
+ BMVert *v_dst)
{
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- struct UserData user_data = {bm, obedit->data, op_params};
- LinkNode *path = NULL;
- bool is_path_ordered = false;
-
- if (v_act && (v_act != v_dst)) {
- if (op_params->use_fill) {
- path = BM_mesh_calc_path_region_vert(
- bm, (BMElem *)v_act, (BMElem *)v_dst,
- verttag_filter_cb, &user_data);
- }
- else {
- is_path_ordered = true;
- path = BM_mesh_calc_path_vert(
- bm, v_act, v_dst,
- &(const struct BMCalcPathParams) {
- .use_topology_distance = op_params->use_topology_distance,
- .use_step_face = op_params->use_face_step,
- },
- verttag_filter_cb, &user_data);
- }
-
- if (path) {
- if (op_params->track_active) {
- BM_select_history_remove(bm, v_act);
- }
- }
- }
-
- BMVert *v_dst_last = v_dst;
-
- if (path) {
- /* toggle the flag */
- bool all_set = true;
- LinkNode *node;
-
- node = path;
- do {
- if (!verttag_test_cb((BMVert *)node->link, &user_data)) {
- all_set = false;
- break;
- }
- } while ((node = node->next));
-
- /* We need to start as if just *after* a 'skip' block... */
- int depth = op_params->interval_params.skip;
- node = path;
- do {
- if ((is_path_ordered == false) ||
- WM_operator_properties_checker_interval_test(&op_params->interval_params, depth))
- {
- verttag_set_cb((BMVert *)node->link, !all_set, &user_data);
- if (is_path_ordered) {
- v_dst_last = node->link;
- }
- }
- } while ((void)depth++, (node = node->next));
-
- BLI_linklist_free(path, NULL);
- }
- else {
- const bool is_act = !verttag_test_cb(v_dst, &user_data);
- verttag_set_cb(v_dst, is_act, &user_data); /* switch the face option */
- }
-
- EDBM_selectmode_flush(em);
-
- if (op_params->track_active) {
- /* even if this is selected it may not be in the selection list */
- if (BM_elem_flag_test(v_dst_last, BM_ELEM_SELECT) == 0) {
- BM_select_history_remove(bm, v_dst_last);
- }
- else {
- BM_select_history_store(bm, v_dst_last);
- }
- }
-
- EDBM_update_generic(em, false, false);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ struct UserData user_data = {bm, obedit->data, op_params};
+ LinkNode *path = NULL;
+ bool is_path_ordered = false;
+
+ if (v_act && (v_act != v_dst)) {
+ if (op_params->use_fill) {
+ path = BM_mesh_calc_path_region_vert(
+ bm, (BMElem *)v_act, (BMElem *)v_dst, verttag_filter_cb, &user_data);
+ }
+ else {
+ is_path_ordered = true;
+ path = BM_mesh_calc_path_vert(bm,
+ v_act,
+ v_dst,
+ &(const struct BMCalcPathParams){
+ .use_topology_distance = op_params->use_topology_distance,
+ .use_step_face = op_params->use_face_step,
+ },
+ verttag_filter_cb,
+ &user_data);
+ }
+
+ if (path) {
+ if (op_params->track_active) {
+ BM_select_history_remove(bm, v_act);
+ }
+ }
+ }
+
+ BMVert *v_dst_last = v_dst;
+
+ if (path) {
+ /* toggle the flag */
+ bool all_set = true;
+ LinkNode *node;
+
+ node = path;
+ do {
+ if (!verttag_test_cb((BMVert *)node->link, &user_data)) {
+ all_set = false;
+ break;
+ }
+ } while ((node = node->next));
+
+ /* We need to start as if just *after* a 'skip' block... */
+ int depth = op_params->interval_params.skip;
+ node = path;
+ do {
+ if ((is_path_ordered == false) ||
+ WM_operator_properties_checker_interval_test(&op_params->interval_params, depth)) {
+ verttag_set_cb((BMVert *)node->link, !all_set, &user_data);
+ if (is_path_ordered) {
+ v_dst_last = node->link;
+ }
+ }
+ } while ((void)depth++, (node = node->next));
+
+ BLI_linklist_free(path, NULL);
+ }
+ else {
+ const bool is_act = !verttag_test_cb(v_dst, &user_data);
+ verttag_set_cb(v_dst, is_act, &user_data); /* switch the face option */
+ }
+
+ EDBM_selectmode_flush(em);
+
+ if (op_params->track_active) {
+ /* even if this is selected it may not be in the selection list */
+ if (BM_elem_flag_test(v_dst_last, BM_ELEM_SELECT) == 0) {
+ BM_select_history_remove(bm, v_dst_last);
+ }
+ else {
+ BM_select_history_store(bm, v_dst_last);
+ }
+ }
+
+ EDBM_update_generic(em, false, false);
}
/** \} */
@@ -219,195 +227,195 @@ static void mouse_mesh_shortest_path_vert(
/* callbacks */
static bool edgetag_filter_cb(BMEdge *e, void *UNUSED(user_data_v))
{
- return !BM_elem_flag_test(e, BM_ELEM_HIDDEN);
+ return !BM_elem_flag_test(e, BM_ELEM_HIDDEN);
}
static bool edgetag_test_cb(BMEdge *e, void *user_data_v)
{
- struct UserData *user_data = user_data_v;
- const char edge_mode = user_data->op_params->edge_mode;
- BMesh *bm = user_data->bm;
-
- switch (edge_mode) {
- case EDGE_MODE_SELECT:
- return BM_elem_flag_test(e, BM_ELEM_SELECT) ? true : false;
- case EDGE_MODE_TAG_SEAM:
- return BM_elem_flag_test(e, BM_ELEM_SEAM) ? true : false;
- case EDGE_MODE_TAG_SHARP:
- return BM_elem_flag_test(e, BM_ELEM_SMOOTH) ? false : true;
- case EDGE_MODE_TAG_CREASE:
- return BM_elem_float_data_get(&bm->edata, e, CD_CREASE) ? true : false;
- case EDGE_MODE_TAG_BEVEL:
- return BM_elem_float_data_get(&bm->edata, e, CD_BWEIGHT) ? true : false;
+ struct UserData *user_data = user_data_v;
+ const char edge_mode = user_data->op_params->edge_mode;
+ BMesh *bm = user_data->bm;
+
+ switch (edge_mode) {
+ case EDGE_MODE_SELECT:
+ return BM_elem_flag_test(e, BM_ELEM_SELECT) ? true : false;
+ case EDGE_MODE_TAG_SEAM:
+ return BM_elem_flag_test(e, BM_ELEM_SEAM) ? true : false;
+ case EDGE_MODE_TAG_SHARP:
+ return BM_elem_flag_test(e, BM_ELEM_SMOOTH) ? false : true;
+ case EDGE_MODE_TAG_CREASE:
+ return BM_elem_float_data_get(&bm->edata, e, CD_CREASE) ? true : false;
+ case EDGE_MODE_TAG_BEVEL:
+ return BM_elem_float_data_get(&bm->edata, e, CD_BWEIGHT) ? true : false;
#ifdef WITH_FREESTYLE
- case EDGE_MODE_TAG_FREESTYLE:
- {
- FreestyleEdge *fed = CustomData_bmesh_get(&bm->edata, e->head.data, CD_FREESTYLE_EDGE);
- return (!fed) ? false : (fed->flag & FREESTYLE_EDGE_MARK) ? true : false;
- }
+ case EDGE_MODE_TAG_FREESTYLE: {
+ FreestyleEdge *fed = CustomData_bmesh_get(&bm->edata, e->head.data, CD_FREESTYLE_EDGE);
+ return (!fed) ? false : (fed->flag & FREESTYLE_EDGE_MARK) ? true : false;
+ }
#endif
- }
- return 0;
+ }
+ return 0;
}
static void edgetag_set_cb(BMEdge *e, bool val, void *user_data_v)
{
- struct UserData *user_data = user_data_v;
- const char edge_mode = user_data->op_params->edge_mode;
- BMesh *bm = user_data->bm;
-
- switch (edge_mode) {
- case EDGE_MODE_SELECT:
- BM_edge_select_set(bm, e, val);
- break;
- case EDGE_MODE_TAG_SEAM:
- BM_elem_flag_set(e, BM_ELEM_SEAM, val);
- break;
- case EDGE_MODE_TAG_SHARP:
- BM_elem_flag_set(e, BM_ELEM_SMOOTH, !val);
- break;
- case EDGE_MODE_TAG_CREASE:
- BM_elem_float_data_set(&bm->edata, e, CD_CREASE, (val) ? 1.0f : 0.0f);
- break;
- case EDGE_MODE_TAG_BEVEL:
- BM_elem_float_data_set(&bm->edata, e, CD_BWEIGHT, (val) ? 1.0f : 0.0f);
- break;
+ struct UserData *user_data = user_data_v;
+ const char edge_mode = user_data->op_params->edge_mode;
+ BMesh *bm = user_data->bm;
+
+ switch (edge_mode) {
+ case EDGE_MODE_SELECT:
+ BM_edge_select_set(bm, e, val);
+ break;
+ case EDGE_MODE_TAG_SEAM:
+ BM_elem_flag_set(e, BM_ELEM_SEAM, val);
+ break;
+ case EDGE_MODE_TAG_SHARP:
+ BM_elem_flag_set(e, BM_ELEM_SMOOTH, !val);
+ break;
+ case EDGE_MODE_TAG_CREASE:
+ BM_elem_float_data_set(&bm->edata, e, CD_CREASE, (val) ? 1.0f : 0.0f);
+ break;
+ case EDGE_MODE_TAG_BEVEL:
+ BM_elem_float_data_set(&bm->edata, e, CD_BWEIGHT, (val) ? 1.0f : 0.0f);
+ break;
#ifdef WITH_FREESTYLE
- case EDGE_MODE_TAG_FREESTYLE:
- {
- FreestyleEdge *fed;
- fed = CustomData_bmesh_get(&bm->edata, e->head.data, CD_FREESTYLE_EDGE);
- if (!val)
- fed->flag &= ~FREESTYLE_EDGE_MARK;
- else
- fed->flag |= FREESTYLE_EDGE_MARK;
- break;
- }
+ case EDGE_MODE_TAG_FREESTYLE: {
+ FreestyleEdge *fed;
+ fed = CustomData_bmesh_get(&bm->edata, e->head.data, CD_FREESTYLE_EDGE);
+ if (!val)
+ fed->flag &= ~FREESTYLE_EDGE_MARK;
+ else
+ fed->flag |= FREESTYLE_EDGE_MARK;
+ break;
+ }
#endif
- }
+ }
}
static void edgetag_ensure_cd_flag(Mesh *me, const char edge_mode)
{
- BMesh *bm = me->edit_mesh->bm;
-
- switch (edge_mode) {
- case EDGE_MODE_TAG_CREASE:
- BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_CREASE);
- break;
- case EDGE_MODE_TAG_BEVEL:
- BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_BWEIGHT);
- break;
+ BMesh *bm = me->edit_mesh->bm;
+
+ switch (edge_mode) {
+ case EDGE_MODE_TAG_CREASE:
+ BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_CREASE);
+ break;
+ case EDGE_MODE_TAG_BEVEL:
+ BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_BWEIGHT);
+ break;
#ifdef WITH_FREESTYLE
- case EDGE_MODE_TAG_FREESTYLE:
- if (!CustomData_has_layer(&bm->edata, CD_FREESTYLE_EDGE)) {
- BM_data_layer_add(bm, &bm->edata, CD_FREESTYLE_EDGE);
- }
- break;
+ case EDGE_MODE_TAG_FREESTYLE:
+ if (!CustomData_has_layer(&bm->edata, CD_FREESTYLE_EDGE)) {
+ BM_data_layer_add(bm, &bm->edata, CD_FREESTYLE_EDGE);
+ }
+ break;
#endif
- default:
- break;
- }
+ default:
+ break;
+ }
}
/* mesh shortest path select, uses prev-selected edge */
/* since you want to create paths with multiple selects, it doesn't have extend option */
-static void mouse_mesh_shortest_path_edge(
- Scene *UNUSED(scene), Object *obedit, const struct PathSelectParams *op_params,
- BMEdge *e_act, BMEdge *e_dst)
+static void mouse_mesh_shortest_path_edge(Scene *UNUSED(scene),
+ Object *obedit,
+ const struct PathSelectParams *op_params,
+ BMEdge *e_act,
+ BMEdge *e_dst)
{
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- struct UserData user_data = {bm, obedit->data, op_params};
- LinkNode *path = NULL;
- bool is_path_ordered = false;
-
- edgetag_ensure_cd_flag(obedit->data, op_params->edge_mode);
-
- if (e_act && (e_act != e_dst)) {
- if (op_params->use_fill) {
- path = BM_mesh_calc_path_region_edge(
- bm, (BMElem *)e_act, (BMElem *)e_dst,
- edgetag_filter_cb, &user_data);
- }
- else {
- is_path_ordered = true;
- path = BM_mesh_calc_path_edge(
- bm, e_act, e_dst,
- &(const struct BMCalcPathParams) {
- .use_topology_distance = op_params->use_topology_distance,
- .use_step_face = op_params->use_face_step,
- },
- edgetag_filter_cb, &user_data);
- }
-
- if (path) {
- if (op_params->track_active) {
- BM_select_history_remove(bm, e_act);
- }
- }
- }
-
- BMEdge *e_dst_last = e_dst;
-
- if (path) {
- /* toggle the flag */
- bool all_set = true;
- LinkNode *node;
-
- node = path;
- do {
- if (!edgetag_test_cb((BMEdge *)node->link, &user_data)) {
- all_set = false;
- break;
- }
- } while ((node = node->next));
-
- /* We need to start as if just *after* a 'skip' block... */
- int depth = op_params->interval_params.skip;
- node = path;
- do {
- if ((is_path_ordered == false) ||
- WM_operator_properties_checker_interval_test(&op_params->interval_params, depth))
- {
- edgetag_set_cb((BMEdge *)node->link, !all_set, &user_data);
- if (is_path_ordered) {
- e_dst_last = node->link;
- }
- }
- } while ((void)depth++, (node = node->next));
-
- BLI_linklist_free(path, NULL);
- }
- else {
- const bool is_act = !edgetag_test_cb(e_dst, &user_data);
- edgetag_ensure_cd_flag(obedit->data, op_params->edge_mode);
- edgetag_set_cb(e_dst, is_act, &user_data); /* switch the edge option */
- }
-
- if (op_params->edge_mode != EDGE_MODE_SELECT) {
- if (op_params->track_active) {
- /* simple rules - last edge is _always_ active and selected */
- if (e_act)
- BM_edge_select_set(bm, e_act, false);
- BM_edge_select_set(bm, e_dst_last, true);
- BM_select_history_store(bm, e_dst_last);
- }
- }
-
- EDBM_selectmode_flush(em);
-
- if (op_params->track_active) {
- /* even if this is selected it may not be in the selection list */
- if (op_params->edge_mode == EDGE_MODE_SELECT) {
- if (edgetag_test_cb(e_dst_last, &user_data) == 0)
- BM_select_history_remove(bm, e_dst_last);
- else
- BM_select_history_store(bm, e_dst_last);
- }
- }
-
- EDBM_update_generic(em, false, false);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ struct UserData user_data = {bm, obedit->data, op_params};
+ LinkNode *path = NULL;
+ bool is_path_ordered = false;
+
+ edgetag_ensure_cd_flag(obedit->data, op_params->edge_mode);
+
+ if (e_act && (e_act != e_dst)) {
+ if (op_params->use_fill) {
+ path = BM_mesh_calc_path_region_edge(
+ bm, (BMElem *)e_act, (BMElem *)e_dst, edgetag_filter_cb, &user_data);
+ }
+ else {
+ is_path_ordered = true;
+ path = BM_mesh_calc_path_edge(bm,
+ e_act,
+ e_dst,
+ &(const struct BMCalcPathParams){
+ .use_topology_distance = op_params->use_topology_distance,
+ .use_step_face = op_params->use_face_step,
+ },
+ edgetag_filter_cb,
+ &user_data);
+ }
+
+ if (path) {
+ if (op_params->track_active) {
+ BM_select_history_remove(bm, e_act);
+ }
+ }
+ }
+
+ BMEdge *e_dst_last = e_dst;
+
+ if (path) {
+ /* toggle the flag */
+ bool all_set = true;
+ LinkNode *node;
+
+ node = path;
+ do {
+ if (!edgetag_test_cb((BMEdge *)node->link, &user_data)) {
+ all_set = false;
+ break;
+ }
+ } while ((node = node->next));
+
+ /* We need to start as if just *after* a 'skip' block... */
+ int depth = op_params->interval_params.skip;
+ node = path;
+ do {
+ if ((is_path_ordered == false) ||
+ WM_operator_properties_checker_interval_test(&op_params->interval_params, depth)) {
+ edgetag_set_cb((BMEdge *)node->link, !all_set, &user_data);
+ if (is_path_ordered) {
+ e_dst_last = node->link;
+ }
+ }
+ } while ((void)depth++, (node = node->next));
+
+ BLI_linklist_free(path, NULL);
+ }
+ else {
+ const bool is_act = !edgetag_test_cb(e_dst, &user_data);
+ edgetag_ensure_cd_flag(obedit->data, op_params->edge_mode);
+ edgetag_set_cb(e_dst, is_act, &user_data); /* switch the edge option */
+ }
+
+ if (op_params->edge_mode != EDGE_MODE_SELECT) {
+ if (op_params->track_active) {
+ /* simple rules - last edge is _always_ active and selected */
+ if (e_act)
+ BM_edge_select_set(bm, e_act, false);
+ BM_edge_select_set(bm, e_dst_last, true);
+ BM_select_history_store(bm, e_dst_last);
+ }
+ }
+
+ EDBM_selectmode_flush(em);
+
+ if (op_params->track_active) {
+ /* even if this is selected it may not be in the selection list */
+ if (op_params->edge_mode == EDGE_MODE_SELECT) {
+ if (edgetag_test_cb(e_dst_last, &user_data) == 0)
+ BM_select_history_remove(bm, e_dst_last);
+ else
+ BM_select_history_store(bm, e_dst_last);
+ }
+ }
+
+ EDBM_update_generic(em, false, false);
}
/** \} */
@@ -419,107 +427,109 @@ static void mouse_mesh_shortest_path_edge(
/* callbacks */
static bool facetag_filter_cb(BMFace *f, void *UNUSED(user_data_v))
{
- return !BM_elem_flag_test(f, BM_ELEM_HIDDEN);
+ return !BM_elem_flag_test(f, BM_ELEM_HIDDEN);
}
//static bool facetag_test_cb(Scene *UNUSED(scene), BMesh *UNUSED(bm), BMFace *f)
static bool facetag_test_cb(BMFace *f, void *UNUSED(user_data_v))
{
- return BM_elem_flag_test_bool(f, BM_ELEM_SELECT);
+ return BM_elem_flag_test_bool(f, BM_ELEM_SELECT);
}
//static void facetag_set_cb(BMesh *bm, Scene *UNUSED(scene), BMFace *f, const bool val)
static void facetag_set_cb(BMFace *f, bool val, void *user_data_v)
{
- struct UserData *user_data = user_data_v;
- BM_face_select_set(user_data->bm, f, val);
+ struct UserData *user_data = user_data_v;
+ BM_face_select_set(user_data->bm, f, val);
}
-static void mouse_mesh_shortest_path_face(
- Scene *UNUSED(scene), Object *obedit, const struct PathSelectParams *op_params,
- BMFace *f_act, BMFace *f_dst)
+static void mouse_mesh_shortest_path_face(Scene *UNUSED(scene),
+ Object *obedit,
+ const struct PathSelectParams *op_params,
+ BMFace *f_act,
+ BMFace *f_dst)
{
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- struct UserData user_data = {bm, obedit->data, op_params};
- LinkNode *path = NULL;
- bool is_path_ordered = false;
-
- if (f_act) {
- if (op_params->use_fill) {
- path = BM_mesh_calc_path_region_face(
- bm, (BMElem *)f_act, (BMElem *)f_dst,
- facetag_filter_cb, &user_data);
- }
- else {
- is_path_ordered = true;
- path = BM_mesh_calc_path_face(
- bm, f_act, f_dst,
- &(const struct BMCalcPathParams) {
- .use_topology_distance = op_params->use_topology_distance,
- .use_step_face = op_params->use_face_step,
- },
- facetag_filter_cb, &user_data);
- }
-
- if (f_act != f_dst) {
- if (path) {
- if (op_params->track_active) {
- BM_select_history_remove(bm, f_act);
- }
- }
- }
- }
-
- BMFace *f_dst_last = f_dst;
-
- if (path) {
- /* toggle the flag */
- bool all_set = true;
- LinkNode *node;
-
- node = path;
- do {
- if (!facetag_test_cb((BMFace *)node->link, &user_data)) {
- all_set = false;
- break;
- }
- } while ((node = node->next));
-
- /* We need to start as if just *after* a 'skip' block... */
- int depth = op_params->interval_params.skip;
- node = path;
- do {
- if ((is_path_ordered == false) ||
- WM_operator_properties_checker_interval_test(&op_params->interval_params, depth))
- {
- facetag_set_cb((BMFace *)node->link, !all_set, &user_data);
- if (is_path_ordered) {
- f_dst_last = node->link;
- }
- }
- } while ((void)depth++, (node = node->next));
-
- BLI_linklist_free(path, NULL);
- }
- else {
- const bool is_act = !facetag_test_cb(f_dst, &user_data);
- facetag_set_cb(f_dst, is_act, &user_data); /* switch the face option */
- }
-
- EDBM_selectmode_flush(em);
-
- if (op_params->track_active) {
- /* even if this is selected it may not be in the selection list */
- if (facetag_test_cb(f_dst_last, &user_data) == 0) {
- BM_select_history_remove(bm, f_dst_last);
- }
- else {
- BM_select_history_store(bm, f_dst_last);
- }
- BM_mesh_active_face_set(bm, f_dst_last);
- }
-
- EDBM_update_generic(em, false, false);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ struct UserData user_data = {bm, obedit->data, op_params};
+ LinkNode *path = NULL;
+ bool is_path_ordered = false;
+
+ if (f_act) {
+ if (op_params->use_fill) {
+ path = BM_mesh_calc_path_region_face(
+ bm, (BMElem *)f_act, (BMElem *)f_dst, facetag_filter_cb, &user_data);
+ }
+ else {
+ is_path_ordered = true;
+ path = BM_mesh_calc_path_face(bm,
+ f_act,
+ f_dst,
+ &(const struct BMCalcPathParams){
+ .use_topology_distance = op_params->use_topology_distance,
+ .use_step_face = op_params->use_face_step,
+ },
+ facetag_filter_cb,
+ &user_data);
+ }
+
+ if (f_act != f_dst) {
+ if (path) {
+ if (op_params->track_active) {
+ BM_select_history_remove(bm, f_act);
+ }
+ }
+ }
+ }
+
+ BMFace *f_dst_last = f_dst;
+
+ if (path) {
+ /* toggle the flag */
+ bool all_set = true;
+ LinkNode *node;
+
+ node = path;
+ do {
+ if (!facetag_test_cb((BMFace *)node->link, &user_data)) {
+ all_set = false;
+ break;
+ }
+ } while ((node = node->next));
+
+ /* We need to start as if just *after* a 'skip' block... */
+ int depth = op_params->interval_params.skip;
+ node = path;
+ do {
+ if ((is_path_ordered == false) ||
+ WM_operator_properties_checker_interval_test(&op_params->interval_params, depth)) {
+ facetag_set_cb((BMFace *)node->link, !all_set, &user_data);
+ if (is_path_ordered) {
+ f_dst_last = node->link;
+ }
+ }
+ } while ((void)depth++, (node = node->next));
+
+ BLI_linklist_free(path, NULL);
+ }
+ else {
+ const bool is_act = !facetag_test_cb(f_dst, &user_data);
+ facetag_set_cb(f_dst, is_act, &user_data); /* switch the face option */
+ }
+
+ EDBM_selectmode_flush(em);
+
+ if (op_params->track_active) {
+ /* even if this is selected it may not be in the selection list */
+ if (facetag_test_cb(f_dst_last, &user_data) == 0) {
+ BM_select_history_remove(bm, f_dst_last);
+ }
+ else {
+ BM_select_history_store(bm, f_dst_last);
+ }
+ BM_mesh_active_face_set(bm, f_dst_last);
+ }
+
+ EDBM_update_generic(em, false, false);
}
/** \} */
@@ -528,206 +538,204 @@ static void mouse_mesh_shortest_path_face(
/** \name Main Operator for vert/edge/face tag
* \{ */
-static bool edbm_shortest_path_pick_ex(
- Scene *scene, Object *obedit, const struct PathSelectParams *op_params,
- BMElem *ele_src, BMElem *ele_dst)
+static bool edbm_shortest_path_pick_ex(Scene *scene,
+ Object *obedit,
+ const struct PathSelectParams *op_params,
+ BMElem *ele_src,
+ BMElem *ele_dst)
{
- bool ok = false;
-
- if (ELEM(NULL, ele_src, ele_dst) || (ele_src->head.htype != ele_dst->head.htype)) {
- /* pass */
- }
- else if (ele_src->head.htype == BM_VERT) {
- mouse_mesh_shortest_path_vert(scene, obedit, op_params, (BMVert *)ele_src, (BMVert *)ele_dst);
- ok = true;
- }
- else if (ele_src->head.htype == BM_EDGE) {
- mouse_mesh_shortest_path_edge(scene, obedit, op_params, (BMEdge *)ele_src, (BMEdge *)ele_dst);
- ok = true;
- }
- else if (ele_src->head.htype == BM_FACE) {
- mouse_mesh_shortest_path_face(scene, obedit, op_params, (BMFace *)ele_src, (BMFace *)ele_dst);
- ok = true;
- }
-
- if (ok) {
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_main_add_notifier(NC_GEOM | ND_SELECT, obedit->data);
- }
-
- return ok;
+ bool ok = false;
+
+ if (ELEM(NULL, ele_src, ele_dst) || (ele_src->head.htype != ele_dst->head.htype)) {
+ /* pass */
+ }
+ else if (ele_src->head.htype == BM_VERT) {
+ mouse_mesh_shortest_path_vert(scene, obedit, op_params, (BMVert *)ele_src, (BMVert *)ele_dst);
+ ok = true;
+ }
+ else if (ele_src->head.htype == BM_EDGE) {
+ mouse_mesh_shortest_path_edge(scene, obedit, op_params, (BMEdge *)ele_src, (BMEdge *)ele_dst);
+ ok = true;
+ }
+ else if (ele_src->head.htype == BM_FACE) {
+ mouse_mesh_shortest_path_face(scene, obedit, op_params, (BMFace *)ele_src, (BMFace *)ele_dst);
+ ok = true;
+ }
+
+ if (ok) {
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_main_add_notifier(NC_GEOM | ND_SELECT, obedit->data);
+ }
+
+ return ok;
}
static int edbm_shortest_path_pick_exec(bContext *C, wmOperator *op);
static BMElem *edbm_elem_find_nearest(ViewContext *vc, const char htype)
{
- BMEditMesh *em = vc->em;
- float dist = ED_view3d_select_dist_px();
-
- if ((em->selectmode & SCE_SELECT_VERTEX) && (htype == BM_VERT)) {
- return (BMElem *)EDBM_vert_find_nearest(vc, &dist);
- }
- else if ((em->selectmode & SCE_SELECT_EDGE) && (htype == BM_EDGE)) {
- return (BMElem *)EDBM_edge_find_nearest(vc, &dist);
- }
- else if ((em->selectmode & SCE_SELECT_FACE) && (htype == BM_FACE)) {
- return (BMElem *)EDBM_face_find_nearest(vc, &dist);
- }
-
- return NULL;
+ BMEditMesh *em = vc->em;
+ float dist = ED_view3d_select_dist_px();
+
+ if ((em->selectmode & SCE_SELECT_VERTEX) && (htype == BM_VERT)) {
+ return (BMElem *)EDBM_vert_find_nearest(vc, &dist);
+ }
+ else if ((em->selectmode & SCE_SELECT_EDGE) && (htype == BM_EDGE)) {
+ return (BMElem *)EDBM_edge_find_nearest(vc, &dist);
+ }
+ else if ((em->selectmode & SCE_SELECT_FACE) && (htype == BM_FACE)) {
+ return (BMElem *)EDBM_face_find_nearest(vc, &dist);
+ }
+
+ return NULL;
}
static BMElem *edbm_elem_active_elem_or_face_get(BMesh *bm)
{
- BMElem *ele = BM_mesh_active_elem_get(bm);
+ BMElem *ele = BM_mesh_active_elem_get(bm);
- if ((ele == NULL) && bm->act_face && BM_elem_flag_test(bm->act_face, BM_ELEM_SELECT)) {
- ele = (BMElem *)bm->act_face;
- }
+ if ((ele == NULL) && bm->act_face && BM_elem_flag_test(bm->act_face, BM_ELEM_SELECT)) {
+ ele = (BMElem *)bm->act_face;
+ }
- return ele;
+ return ele;
}
static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (RNA_struct_property_is_set(op->ptr, "index")) {
- return edbm_shortest_path_pick_exec(C, op);
- }
-
- Base *basact = NULL;
- BMVert *eve = NULL;
- BMEdge *eed = NULL;
- BMFace *efa = NULL;
-
- ViewContext vc;
- BMEditMesh *em;
- bool track_active = true;
-
- em_setup_viewcontext(C, &vc);
- copy_v2_v2_int(vc.mval, event->mval);
- em = vc.em;
-
- view3d_operator_needs_opengl(C);
-
- {
- int base_index = -1;
- uint bases_len = 0;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len);
- if (EDBM_unified_findnearest(&vc, bases, bases_len, &base_index, &eve, &eed, &efa)) {
- basact = bases[base_index];
- ED_view3d_viewcontext_init_object(&vc, basact->object);
- em = vc.em;
- }
- MEM_freeN(bases);
- }
-
- /* If nothing is selected, let's select the picked vertex/edge/face. */
- if ((vc.em->bm->totvertsel == 0) && (eve || eed || efa)) {
- /* TODO (dfelinto) right now we try to find the closest element twice.
- * The ideal is to refactor EDBM_select_pick so it doesn't
- * have to pick the nearest vert/edge/face again.
- */
- EDBM_select_pick(C, event->mval, true, false, false);
- return OPERATOR_FINISHED;
- }
-
- BMElem *ele_src, *ele_dst;
- if (!(ele_src = edbm_elem_active_elem_or_face_get(em->bm)) ||
- !(ele_dst = edbm_elem_find_nearest(&vc, ele_src->head.htype)))
- {
- /* special case, toggle edge tags even when we don't have a path */
- if (((em->selectmode & SCE_SELECT_EDGE) &&
- (vc.scene->toolsettings->edge_mode != EDGE_MODE_SELECT)) &&
- /* check if we only have a destination edge */
- ((ele_src == NULL) &&
- (ele_dst = edbm_elem_find_nearest(&vc, BM_EDGE))))
- {
- ele_src = ele_dst;
- track_active = false;
- }
- else {
- return OPERATOR_PASS_THROUGH;
- }
- }
-
- struct PathSelectParams op_params;
-
- path_select_params_from_op(op, &op_params);
- op_params.track_active = track_active;
- op_params.edge_mode = vc.scene->toolsettings->edge_mode;
-
- if (!edbm_shortest_path_pick_ex(vc.scene, vc.obedit, &op_params, ele_src, ele_dst)) {
- return OPERATOR_PASS_THROUGH;
- }
-
- if (vc.view_layer->basact != basact) {
- ED_object_base_activate(C, basact);
- }
-
- /* to support redo */
- BM_mesh_elem_index_ensure(em->bm, ele_dst->head.htype);
- int index = EDBM_elem_to_index_any(em, ele_dst);
-
- RNA_int_set(op->ptr, "index", index);
-
- return OPERATOR_FINISHED;
+ if (RNA_struct_property_is_set(op->ptr, "index")) {
+ return edbm_shortest_path_pick_exec(C, op);
+ }
+
+ Base *basact = NULL;
+ BMVert *eve = NULL;
+ BMEdge *eed = NULL;
+ BMFace *efa = NULL;
+
+ ViewContext vc;
+ BMEditMesh *em;
+ bool track_active = true;
+
+ em_setup_viewcontext(C, &vc);
+ copy_v2_v2_int(vc.mval, event->mval);
+ em = vc.em;
+
+ view3d_operator_needs_opengl(C);
+
+ {
+ int base_index = -1;
+ uint bases_len = 0;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len);
+ if (EDBM_unified_findnearest(&vc, bases, bases_len, &base_index, &eve, &eed, &efa)) {
+ basact = bases[base_index];
+ ED_view3d_viewcontext_init_object(&vc, basact->object);
+ em = vc.em;
+ }
+ MEM_freeN(bases);
+ }
+
+ /* If nothing is selected, let's select the picked vertex/edge/face. */
+ if ((vc.em->bm->totvertsel == 0) && (eve || eed || efa)) {
+ /* TODO (dfelinto) right now we try to find the closest element twice.
+ * The ideal is to refactor EDBM_select_pick so it doesn't
+ * have to pick the nearest vert/edge/face again.
+ */
+ EDBM_select_pick(C, event->mval, true, false, false);
+ return OPERATOR_FINISHED;
+ }
+
+ BMElem *ele_src, *ele_dst;
+ if (!(ele_src = edbm_elem_active_elem_or_face_get(em->bm)) ||
+ !(ele_dst = edbm_elem_find_nearest(&vc, ele_src->head.htype))) {
+ /* special case, toggle edge tags even when we don't have a path */
+ if (((em->selectmode & SCE_SELECT_EDGE) &&
+ (vc.scene->toolsettings->edge_mode != EDGE_MODE_SELECT)) &&
+ /* check if we only have a destination edge */
+ ((ele_src == NULL) && (ele_dst = edbm_elem_find_nearest(&vc, BM_EDGE)))) {
+ ele_src = ele_dst;
+ track_active = false;
+ }
+ else {
+ return OPERATOR_PASS_THROUGH;
+ }
+ }
+
+ struct PathSelectParams op_params;
+
+ path_select_params_from_op(op, &op_params);
+ op_params.track_active = track_active;
+ op_params.edge_mode = vc.scene->toolsettings->edge_mode;
+
+ if (!edbm_shortest_path_pick_ex(vc.scene, vc.obedit, &op_params, ele_src, ele_dst)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ if (vc.view_layer->basact != basact) {
+ ED_object_base_activate(C, basact);
+ }
+
+ /* to support redo */
+ BM_mesh_elem_index_ensure(em->bm, ele_dst->head.htype);
+ int index = EDBM_elem_to_index_any(em, ele_dst);
+
+ RNA_int_set(op->ptr, "index", index);
+
+ return OPERATOR_FINISHED;
}
static int edbm_shortest_path_pick_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- const int index = RNA_int_get(op->ptr, "index");
- if (index < 0 || index >= (bm->totvert + bm->totedge + bm->totface)) {
- return OPERATOR_CANCELLED;
- }
-
- BMElem *ele_src, *ele_dst;
- if (!(ele_src = edbm_elem_active_elem_or_face_get(em->bm)) ||
- !(ele_dst = EDBM_elem_from_index_any(em, index)))
- {
- return OPERATOR_CANCELLED;
- }
-
- struct PathSelectParams op_params;
- path_select_params_from_op(op, &op_params);
- op_params.track_active = true;
- op_params.edge_mode = scene->toolsettings->edge_mode;
-
- if (!edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst)) {
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ const int index = RNA_int_get(op->ptr, "index");
+ if (index < 0 || index >= (bm->totvert + bm->totedge + bm->totface)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BMElem *ele_src, *ele_dst;
+ if (!(ele_src = edbm_elem_active_elem_or_face_get(em->bm)) ||
+ !(ele_dst = EDBM_elem_from_index_any(em, index))) {
+ return OPERATOR_CANCELLED;
+ }
+
+ struct PathSelectParams op_params;
+ path_select_params_from_op(op, &op_params);
+ op_params.track_active = true;
+ op_params.edge_mode = scene->toolsettings->edge_mode;
+
+ if (!edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_shortest_path_pick(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Pick Shortest Path";
- ot->idname = "MESH_OT_shortest_path_pick";
- ot->description = "Select shortest path between two selections";
+ /* identifiers */
+ ot->name = "Pick Shortest Path";
+ ot->idname = "MESH_OT_shortest_path_pick";
+ ot->description = "Select shortest path between two selections";
- /* api callbacks */
- ot->invoke = edbm_shortest_path_pick_invoke;
- ot->exec = edbm_shortest_path_pick_exec;
- ot->poll = ED_operator_editmesh_region_view3d;
+ /* api callbacks */
+ ot->invoke = edbm_shortest_path_pick_invoke;
+ ot->exec = edbm_shortest_path_pick_exec;
+ ot->poll = ED_operator_editmesh_region_view3d;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- path_select_properties(ot);
+ /* properties */
+ path_select_properties(ot);
- /* use for redo */
- prop = RNA_def_int(ot->srna, "index", -1, -1, INT_MAX, "", "", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ /* use for redo */
+ prop = RNA_def_int(ot->srna, "index", -1, -1, INT_MAX, "", "", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/** \} */
@@ -738,106 +746,112 @@ void MESH_OT_shortest_path_pick(wmOperatorType *ot)
static int edbm_shortest_path_select_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- bool found_valid_elements = 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 *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMIter iter;
- BMEditSelection *ese_src, *ese_dst;
- BMElem *ele_src = NULL, *ele_dst = NULL, *ele;
-
- if ((em->bm->totvertsel == 0) &&
- (em->bm->totedgesel == 0) &&
- (em->bm->totfacesel == 0))
- {
- continue;
- }
-
- /* first try to find vertices in edit selection */
- ese_src = bm->selected.last;
- if (ese_src && (ese_dst = ese_src->prev) && (ese_src->htype == ese_dst->htype)) {
- ele_src = ese_src->ele;
- ele_dst = ese_dst->ele;
- }
- else {
- /* if selection history isn't available, find two selected elements */
- ele_src = ele_dst = NULL;
- if ((em->selectmode & SCE_SELECT_VERTEX) && (bm->totvertsel >= 2)) {
- BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
- if (ele_src == NULL) ele_src = ele;
- else if (ele_dst == NULL) ele_dst = ele;
- else break;
- }
- }
- }
-
- if ((ele_dst == NULL) && (em->selectmode & SCE_SELECT_EDGE) && (bm->totedgesel >= 2)) {
- ele_src = NULL;
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
- if (ele_src == NULL) ele_src = ele;
- else if (ele_dst == NULL) ele_dst = ele;
- else break;
- }
- }
- }
-
- if ((ele_dst == NULL) && (em->selectmode & SCE_SELECT_FACE) && (bm->totfacesel >= 2)) {
- ele_src = NULL;
- BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
- if (ele_src == NULL) ele_src = ele;
- else if (ele_dst == NULL) ele_dst = ele;
- else break;
- }
- }
- }
- }
-
- if (ele_src && ele_dst) {
- struct PathSelectParams op_params;
- path_select_params_from_op(op, &op_params);
-
- edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst);
-
- found_valid_elements = true;
- }
- }
- MEM_freeN(objects);
-
- if (!found_valid_elements) {
- BKE_report(op->reports,
- RPT_WARNING,
- "Path selection requires two matching elements to be selected");
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ bool found_valid_elements = 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 *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMEditSelection *ese_src, *ese_dst;
+ BMElem *ele_src = NULL, *ele_dst = NULL, *ele;
+
+ if ((em->bm->totvertsel == 0) && (em->bm->totedgesel == 0) && (em->bm->totfacesel == 0)) {
+ continue;
+ }
+
+ /* first try to find vertices in edit selection */
+ ese_src = bm->selected.last;
+ if (ese_src && (ese_dst = ese_src->prev) && (ese_src->htype == ese_dst->htype)) {
+ ele_src = ese_src->ele;
+ ele_dst = ese_dst->ele;
+ }
+ else {
+ /* if selection history isn't available, find two selected elements */
+ ele_src = ele_dst = NULL;
+ if ((em->selectmode & SCE_SELECT_VERTEX) && (bm->totvertsel >= 2)) {
+ BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+ if (ele_src == NULL)
+ ele_src = ele;
+ else if (ele_dst == NULL)
+ ele_dst = ele;
+ else
+ break;
+ }
+ }
+ }
+
+ if ((ele_dst == NULL) && (em->selectmode & SCE_SELECT_EDGE) && (bm->totedgesel >= 2)) {
+ ele_src = NULL;
+ BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+ if (ele_src == NULL)
+ ele_src = ele;
+ else if (ele_dst == NULL)
+ ele_dst = ele;
+ else
+ break;
+ }
+ }
+ }
+
+ if ((ele_dst == NULL) && (em->selectmode & SCE_SELECT_FACE) && (bm->totfacesel >= 2)) {
+ ele_src = NULL;
+ BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+ if (ele_src == NULL)
+ ele_src = ele;
+ else if (ele_dst == NULL)
+ ele_dst = ele;
+ else
+ break;
+ }
+ }
+ }
+ }
+
+ if (ele_src && ele_dst) {
+ struct PathSelectParams op_params;
+ path_select_params_from_op(op, &op_params);
+
+ edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst);
+
+ found_valid_elements = true;
+ }
+ }
+ MEM_freeN(objects);
+
+ if (!found_valid_elements) {
+ BKE_report(
+ op->reports, RPT_WARNING, "Path selection requires two matching elements to be selected");
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_shortest_path_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Shortest Path";
- ot->idname = "MESH_OT_shortest_path_select";
- ot->description = "Selected shortest path between two vertices/edges/faces";
+ /* identifiers */
+ ot->name = "Select Shortest Path";
+ ot->idname = "MESH_OT_shortest_path_select";
+ ot->description = "Selected shortest path between two vertices/edges/faces";
- /* api callbacks */
- ot->exec = edbm_shortest_path_select_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_shortest_path_select_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- path_select_properties(ot);
+ /* properties */
+ path_select_properties(ot);
}
/** \} */
diff --git a/source/blender/editors/mesh/editmesh_polybuild.c b/source/blender/editors/mesh/editmesh_polybuild.c
index 7decd5f4b2f..088d1672cc9 100644
--- a/source/blender/editors/mesh/editmesh_polybuild.c
+++ b/source/blender/editors/mesh/editmesh_polybuild.c
@@ -44,7 +44,7 @@
#include "bmesh.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
#include "RNA_access.h"
#include "RNA_define.h"
@@ -59,70 +59,67 @@
static void edbm_selectmode_ensure(Scene *scene, BMEditMesh *em, short selectmode)
{
- if ((scene->toolsettings->selectmode & selectmode) == 0) {
- scene->toolsettings->selectmode |= selectmode;
- em->selectmode = scene->toolsettings->selectmode;
- EDBM_selectmode_set(em);
- }
+ if ((scene->toolsettings->selectmode & selectmode) == 0) {
+ scene->toolsettings->selectmode |= selectmode;
+ em->selectmode = scene->toolsettings->selectmode;
+ EDBM_selectmode_set(em);
+ }
}
/* Could make public, for now just keep here. */
static void edbm_flag_disable_all_multi(ViewLayer *view_layer, View3D *v3d, const char hflag)
{
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, v3d, &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob_iter = objects[ob_index];
- BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
- BMesh *bm_iter = em_iter->bm;
- if (bm_iter->totvertsel) {
- EDBM_flag_disable_all(em_iter, hflag);
- DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
- }
- }
- MEM_freeN(objects);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, v3d, &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob_iter = objects[ob_index];
+ BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
+ BMesh *bm_iter = em_iter->bm;
+ if (bm_iter->totvertsel) {
+ EDBM_flag_disable_all(em_iter, hflag);
+ DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
+ }
+ }
+ MEM_freeN(objects);
}
/* 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)
+static bool edbm_preselect_or_active(bContext *C, const View3D *v3d, Base **r_base, BMElem **r_ele)
{
- ARegion *ar = 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;
- wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap, "VIEW3D_GGT_mesh_preselect_elem") : NULL;
- if (gzgroup != NULL) {
- wmGizmo *gz = gzgroup->gizmos.first;
- ED_view3d_gizmo_mesh_preselect_get_active(C, gz, r_base, r_ele);
- }
- else {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base = view_layer->basact;
- Object *obedit = base->object;
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- *r_base = base;
- *r_ele = BM_mesh_active_elem_get(bm);
- }
- return (*r_ele != NULL);
+ ARegion *ar = 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;
+ wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap, "VIEW3D_GGT_mesh_preselect_elem") :
+ NULL;
+ if (gzgroup != NULL) {
+ wmGizmo *gz = gzgroup->gizmos.first;
+ ED_view3d_gizmo_mesh_preselect_get_active(C, gz, r_base, r_ele);
+ }
+ else {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base = view_layer->basact;
+ Object *obedit = base->object;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ *r_base = base;
+ *r_ele = BM_mesh_active_elem_get(bm);
+ }
+ return (*r_ele != NULL);
}
-static bool edbm_preselect_or_active_init_viewcontext(
- bContext *C,
- ViewContext *vc,
- Base **r_base,
- BMElem **r_ele)
+static bool edbm_preselect_or_active_init_viewcontext(bContext *C,
+ ViewContext *vc,
+ Base **r_base,
+ BMElem **r_ele)
{
- em_setup_viewcontext(C, vc);
- bool ok = edbm_preselect_or_active(C, vc->v3d, r_base, r_ele);
- if (ok) {
- ED_view3d_viewcontext_init_object(vc, (*r_base)->object);
- }
- return ok;
+ em_setup_viewcontext(C, vc);
+ bool ok = edbm_preselect_or_active(C, vc->v3d, r_base, r_ele);
+ if (ok) {
+ ED_view3d_viewcontext_init_object(vc, (*r_base)->object);
+ }
+ return ok;
}
/** \} */
@@ -131,163 +128,161 @@ static bool edbm_preselect_or_active_init_viewcontext(
/** \name Face at Cursor
* \{ */
-static int edbm_polybuild_face_at_cursor_invoke(
- bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+static int edbm_polybuild_face_at_cursor_invoke(bContext *C,
+ wmOperator *UNUSED(op),
+ const wmEvent *event)
{
- float center[3];
- bool changed = false;
-
- ViewContext vc;
- Base *basact = NULL;
- BMElem *ele_act = NULL;
- edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act);
- BMEditMesh *em = vc.em;
- BMesh *bm = em->bm;
-
- invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
- ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
-
- edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX);
-
- if (ele_act == NULL || ele_act->head.htype == BM_FACE) {
- /* 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);
- mul_m4_v3(vc.obedit->imat, center);
-
- BMVert *v_new = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
- edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
- BM_vert_select_set(bm, v_new, true);
- BM_select_history_store(bm, v_new);
- changed = true;
- }
- else if (ele_act->head.htype == BM_EDGE) {
- BMEdge *e_act = (BMEdge *)ele_act;
- BMFace *f_reference = e_act->l ? e_act->l->f : NULL;
-
- 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);
- mul_m4_v3(vc.obedit->imat, center);
-
- BMVert *v_tri[3];
- v_tri[0] = e_act->v1;
- v_tri[1] = e_act->v2;
- v_tri[2] = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
- if (e_act->l && e_act->l->v == v_tri[0]) {
- SWAP(BMVert *, v_tri[0], v_tri[1]);
- }
- // BMFace *f_new =
- BM_face_create_verts(bm, v_tri, 3, f_reference, BM_CREATE_NOP, true);
-
- edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
- BM_vert_select_set(bm, v_tri[2], true);
- BM_select_history_store(bm, v_tri[2]);
- changed = true;
- }
- else if (ele_act->head.htype == BM_VERT) {
- BMVert *v_act = (BMVert *)ele_act;
- BMEdge *e_pair[2] = {NULL};
-
- if (v_act->e != NULL) {
- for (uint allow_wire = 0; allow_wire < 2 && (e_pair[1] == NULL); allow_wire++) {
- int i = 0;
- BMEdge *e_iter = v_act->e;
- do {
- if ((BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) &&
- (allow_wire ? BM_edge_is_wire(e_iter) : BM_edge_is_boundary(e_iter)))
- {
- if (i == 2) {
- e_pair[0] = e_pair[1] = NULL;
- break;
- }
- e_pair[i++] = e_iter;
- }
- } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_act)) != v_act->e);
- }
- }
-
- if (e_pair[1] != NULL) {
- /* Quad from edge pair. */
- if (BM_edge_calc_length_squared(e_pair[0]) <
- BM_edge_calc_length_squared(e_pair[1]))
- {
- SWAP(BMEdge *, e_pair[0], e_pair[1]);
- }
-
- 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);
- mul_m4_v3(vc.obedit->imat, center);
-
- BMVert *v_quad[4];
- v_quad[0] = v_act;
- v_quad[1] = BM_edge_other_vert(e_pair[0], v_act);
- v_quad[2] = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
- v_quad[3] = BM_edge_other_vert(e_pair[1], v_act);
- if (e_pair[0]->l && e_pair[0]->l->v == v_quad[0]) {
- SWAP(BMVert *, v_quad[1], v_quad[3]);
- }
- // BMFace *f_new =
- BM_face_create_verts(bm, v_quad, 4, f_reference, BM_CREATE_NOP, true);
-
- edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
- BM_vert_select_set(bm, v_quad[2], true);
- BM_select_history_store(bm, v_quad[2]);
- changed = true;
- }
- 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);
- mul_m4_v3(vc.obedit->imat, center);
-
- BMVert *v_new = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
-
- BM_edge_create(bm, v_act, v_new, NULL, BM_CREATE_NOP);
-
- BM_vert_select_set(bm, v_new, true);
- BM_select_history_store(bm, v_new);
- changed = true;
- }
- }
-
- if (changed) {
- EDBM_mesh_normals_update(em);
- EDBM_update_generic(em, true, true);
-
- if (basact != NULL) {
- if (vc.view_layer->basact != basact) {
- ED_object_base_activate(C, basact);
- }
- }
-
- WM_event_add_mousemove(C);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ float center[3];
+ bool changed = false;
+
+ ViewContext vc;
+ Base *basact = NULL;
+ BMElem *ele_act = NULL;
+ edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act);
+ BMEditMesh *em = vc.em;
+ BMesh *bm = em->bm;
+
+ invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
+ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
+
+ edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX);
+
+ if (ele_act == NULL || ele_act->head.htype == BM_FACE) {
+ /* 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);
+ mul_m4_v3(vc.obedit->imat, center);
+
+ BMVert *v_new = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
+ edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
+ BM_vert_select_set(bm, v_new, true);
+ BM_select_history_store(bm, v_new);
+ changed = true;
+ }
+ else if (ele_act->head.htype == BM_EDGE) {
+ BMEdge *e_act = (BMEdge *)ele_act;
+ BMFace *f_reference = e_act->l ? e_act->l->f : NULL;
+
+ 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);
+ mul_m4_v3(vc.obedit->imat, center);
+
+ BMVert *v_tri[3];
+ v_tri[0] = e_act->v1;
+ v_tri[1] = e_act->v2;
+ v_tri[2] = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
+ if (e_act->l && e_act->l->v == v_tri[0]) {
+ SWAP(BMVert *, v_tri[0], v_tri[1]);
+ }
+ // BMFace *f_new =
+ BM_face_create_verts(bm, v_tri, 3, f_reference, BM_CREATE_NOP, true);
+
+ edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
+ BM_vert_select_set(bm, v_tri[2], true);
+ BM_select_history_store(bm, v_tri[2]);
+ changed = true;
+ }
+ else if (ele_act->head.htype == BM_VERT) {
+ BMVert *v_act = (BMVert *)ele_act;
+ BMEdge *e_pair[2] = {NULL};
+
+ if (v_act->e != NULL) {
+ for (uint allow_wire = 0; allow_wire < 2 && (e_pair[1] == NULL); allow_wire++) {
+ int i = 0;
+ BMEdge *e_iter = v_act->e;
+ do {
+ if ((BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) &&
+ (allow_wire ? BM_edge_is_wire(e_iter) : BM_edge_is_boundary(e_iter))) {
+ if (i == 2) {
+ e_pair[0] = e_pair[1] = NULL;
+ break;
+ }
+ e_pair[i++] = e_iter;
+ }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_act)) != v_act->e);
+ }
+ }
+
+ if (e_pair[1] != NULL) {
+ /* Quad from edge pair. */
+ if (BM_edge_calc_length_squared(e_pair[0]) < BM_edge_calc_length_squared(e_pair[1])) {
+ SWAP(BMEdge *, e_pair[0], e_pair[1]);
+ }
+
+ 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);
+ mul_m4_v3(vc.obedit->imat, center);
+
+ BMVert *v_quad[4];
+ v_quad[0] = v_act;
+ v_quad[1] = BM_edge_other_vert(e_pair[0], v_act);
+ v_quad[2] = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
+ v_quad[3] = BM_edge_other_vert(e_pair[1], v_act);
+ if (e_pair[0]->l && e_pair[0]->l->v == v_quad[0]) {
+ SWAP(BMVert *, v_quad[1], v_quad[3]);
+ }
+ // BMFace *f_new =
+ BM_face_create_verts(bm, v_quad, 4, f_reference, BM_CREATE_NOP, true);
+
+ edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
+ BM_vert_select_set(bm, v_quad[2], true);
+ BM_select_history_store(bm, v_quad[2]);
+ changed = true;
+ }
+ 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);
+ mul_m4_v3(vc.obedit->imat, center);
+
+ BMVert *v_new = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
+
+ BM_edge_create(bm, v_act, v_new, NULL, BM_CREATE_NOP);
+
+ BM_vert_select_set(bm, v_new, true);
+ BM_select_history_store(bm, v_new);
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
+
+ if (basact != NULL) {
+ if (vc.view_layer->basact != basact) {
+ ED_object_base_activate(C, basact);
+ }
+ }
+
+ WM_event_add_mousemove(C);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void MESH_OT_polybuild_face_at_cursor(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Poly Build Face at Cursor";
- ot->idname = "MESH_OT_polybuild_face_at_cursor";
+ /* identifiers */
+ ot->name = "Poly Build Face at Cursor";
+ ot->idname = "MESH_OT_polybuild_face_at_cursor";
- /* api callbacks */
- ot->invoke = edbm_polybuild_face_at_cursor_invoke;
- ot->poll = EDBM_view3d_poll;
+ /* api callbacks */
+ ot->invoke = edbm_polybuild_face_at_cursor_invoke;
+ ot->poll = EDBM_view3d_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* to give to transform */
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
+ /* to give to transform */
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
}
/** \} */
@@ -296,170 +291,171 @@ void MESH_OT_polybuild_face_at_cursor(wmOperatorType *ot)
/** \name Split at Cursor
* \{ */
-static int edbm_polybuild_split_at_cursor_invoke(
- bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+static int edbm_polybuild_split_at_cursor_invoke(bContext *C,
+ wmOperator *UNUSED(op),
+ const wmEvent *event)
{
- float center[3];
- bool changed = false;
-
- ViewContext vc;
- Base *basact = NULL;
- BMElem *ele_act = NULL;
- edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act);
- BMEditMesh *em = vc.em;
- BMesh *bm = em->bm;
-
- invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
- ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
-
- edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX);
-
- if (ele_act == NULL || ele_act->head.hflag == BM_FACE) {
- return OPERATOR_PASS_THROUGH;
- }
- else if (ele_act->head.htype == BM_EDGE) {
- 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);
- mul_m4_v3(vc.obedit->imat, center);
-
- const float fac = line_point_factor_v3(center, e_act->v1->co, e_act->v2->co);
- BMVert *v_new = BM_edge_split(bm, e_act, e_act->v1, NULL, CLAMPIS(fac, 0.0f, 1.0f));
- copy_v3_v3(v_new->co, center);
-
- edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
- BM_vert_select_set(bm, v_new, true);
- BM_select_history_store(bm, v_new);
- changed = true;
- }
- else if (ele_act->head.htype == BM_VERT) {
- /* Just do nothing, allow dragging. */
- return OPERATOR_FINISHED;
- }
-
- if (changed) {
- EDBM_mesh_normals_update(em);
- EDBM_update_generic(em, true, true);
-
- WM_event_add_mousemove(C);
-
- if (vc.view_layer->basact != basact) {
- ED_object_base_activate(C, basact);
- }
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ float center[3];
+ bool changed = false;
+
+ ViewContext vc;
+ Base *basact = NULL;
+ BMElem *ele_act = NULL;
+ edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act);
+ BMEditMesh *em = vc.em;
+ BMesh *bm = em->bm;
+
+ invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
+ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
+
+ edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX);
+
+ if (ele_act == NULL || ele_act->head.hflag == BM_FACE) {
+ return OPERATOR_PASS_THROUGH;
+ }
+ else if (ele_act->head.htype == BM_EDGE) {
+ 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);
+ mul_m4_v3(vc.obedit->imat, center);
+
+ const float fac = line_point_factor_v3(center, e_act->v1->co, e_act->v2->co);
+ BMVert *v_new = BM_edge_split(bm, e_act, e_act->v1, NULL, CLAMPIS(fac, 0.0f, 1.0f));
+ copy_v3_v3(v_new->co, center);
+
+ edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
+ BM_vert_select_set(bm, v_new, true);
+ BM_select_history_store(bm, v_new);
+ changed = true;
+ }
+ else if (ele_act->head.htype == BM_VERT) {
+ /* Just do nothing, allow dragging. */
+ return OPERATOR_FINISHED;
+ }
+
+ if (changed) {
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
+
+ WM_event_add_mousemove(C);
+
+ if (vc.view_layer->basact != basact) {
+ ED_object_base_activate(C, basact);
+ }
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void MESH_OT_polybuild_split_at_cursor(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Poly Build Split at Cursor";
- ot->idname = "MESH_OT_polybuild_split_at_cursor";
+ /* identifiers */
+ ot->name = "Poly Build Split at Cursor";
+ ot->idname = "MESH_OT_polybuild_split_at_cursor";
- /* api callbacks */
- ot->invoke = edbm_polybuild_split_at_cursor_invoke;
- ot->poll = EDBM_view3d_poll;
+ /* api callbacks */
+ ot->invoke = edbm_polybuild_split_at_cursor_invoke;
+ ot->poll = EDBM_view3d_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* to give to transform */
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
+ /* to give to transform */
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Dissolve at Cursor
*
* \{ */
-static int edbm_polybuild_dissolve_at_cursor_invoke(
- bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int edbm_polybuild_dissolve_at_cursor_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
{
- bool changed = false;
-
- ViewContext vc;
- Base *basact = NULL;
- BMElem *ele_act = NULL;
- edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act);
- BMEditMesh *em = vc.em;
- BMesh *bm = em->bm;
-
- if (ele_act == NULL) {
- /* pass */
- }
- else if (ele_act->head.htype == BM_EDGE) {
- BMEdge *e_act = (BMEdge *)ele_act;
- BMLoop *l_a, *l_b;
- if (BM_edge_loop_pair(e_act, &l_a, &l_b)) {
- BMFace *f_new = BM_faces_join_pair(bm, l_a, l_b, true);
- if (f_new) {
- changed = true;
- }
- }
- }
- else if (ele_act->head.htype == BM_VERT) {
- BMVert *v_act = (BMVert *)ele_act;
- if (BM_vert_is_edge_pair(v_act)) {
- BM_edge_collapse(
- bm, v_act->e, v_act,
- true, true);
- }
- else {
- /* too involved to do inline */
-
- /* Avoid using selection so failure wont leave modified state. */
- EDBM_flag_disable_all(em, BM_ELEM_TAG);
- BM_elem_flag_enable(v_act, BM_ELEM_TAG);
-
- if (!EDBM_op_callf(em, op,
- "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
- BM_ELEM_TAG, false, false))
- {
- return OPERATOR_CANCELLED;
- }
- }
- changed = true;
- }
-
- if (changed) {
- edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
-
- EDBM_mesh_normals_update(em);
- EDBM_update_generic(em, true, true);
-
- if (vc.view_layer->basact != basact) {
- ED_object_base_activate(C, basact);
- }
-
- WM_event_add_mousemove(C);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ bool changed = false;
+
+ ViewContext vc;
+ Base *basact = NULL;
+ BMElem *ele_act = NULL;
+ edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act);
+ BMEditMesh *em = vc.em;
+ BMesh *bm = em->bm;
+
+ if (ele_act == NULL) {
+ /* pass */
+ }
+ else if (ele_act->head.htype == BM_EDGE) {
+ BMEdge *e_act = (BMEdge *)ele_act;
+ BMLoop *l_a, *l_b;
+ if (BM_edge_loop_pair(e_act, &l_a, &l_b)) {
+ BMFace *f_new = BM_faces_join_pair(bm, l_a, l_b, true);
+ if (f_new) {
+ changed = true;
+ }
+ }
+ }
+ else if (ele_act->head.htype == BM_VERT) {
+ BMVert *v_act = (BMVert *)ele_act;
+ if (BM_vert_is_edge_pair(v_act)) {
+ BM_edge_collapse(bm, v_act->e, v_act, true, true);
+ }
+ else {
+ /* too involved to do inline */
+
+ /* Avoid using selection so failure wont leave modified state. */
+ EDBM_flag_disable_all(em, BM_ELEM_TAG);
+ BM_elem_flag_enable(v_act, BM_ELEM_TAG);
+
+ if (!EDBM_op_callf(em,
+ op,
+ "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
+ BM_ELEM_TAG,
+ false,
+ false)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+ changed = true;
+ }
+
+ if (changed) {
+ edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
+
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
+
+ if (vc.view_layer->basact != basact) {
+ ED_object_base_activate(C, basact);
+ }
+
+ WM_event_add_mousemove(C);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void MESH_OT_polybuild_dissolve_at_cursor(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Poly Build Dissolve at Cursor";
- ot->idname = "MESH_OT_polybuild_dissolve_at_cursor";
+ /* identifiers */
+ ot->name = "Poly Build Dissolve at Cursor";
+ ot->idname = "MESH_OT_polybuild_dissolve_at_cursor";
- /* api callbacks */
- ot->invoke = edbm_polybuild_dissolve_at_cursor_invoke;
- ot->poll = EDBM_view3d_poll;
+ /* api callbacks */
+ ot->invoke = edbm_polybuild_dissolve_at_cursor_invoke;
+ ot->poll = EDBM_view3d_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
diff --git a/source/blender/editors/mesh/editmesh_preselect_edgering.c b/source/blender/editors/mesh/editmesh_preselect_edgering.c
index 9e761713f7e..b007343e14e 100644
--- a/source/blender/editors/mesh/editmesh_preselect_edgering.c
+++ b/source/blender/editors/mesh/editmesh_preselect_edgering.c
@@ -47,304 +47,309 @@
static void edgering_vcos_get(BMVert *v[2][2], float r_cos[2][2][3], const float (*coords)[3])
{
- if (coords) {
- int j, k;
- for (j = 0; j < 2; j++) {
- for (k = 0; k < 2; k++) {
- copy_v3_v3(r_cos[j][k], coords[BM_elem_index_get(v[j][k])]);
- }
- }
- }
- else {
- int j, k;
- for (j = 0; j < 2; j++) {
- for (k = 0; k < 2; k++) {
- copy_v3_v3(r_cos[j][k], v[j][k]->co);
- }
- }
- }
+ if (coords) {
+ int j, k;
+ for (j = 0; j < 2; j++) {
+ for (k = 0; k < 2; k++) {
+ copy_v3_v3(r_cos[j][k], coords[BM_elem_index_get(v[j][k])]);
+ }
+ }
+ }
+ else {
+ int j, k;
+ for (j = 0; j < 2; j++) {
+ for (k = 0; k < 2; k++) {
+ copy_v3_v3(r_cos[j][k], v[j][k]->co);
+ }
+ }
+ }
}
static void edgering_vcos_get_pair(BMVert *v[2], float r_cos[2][3], const float (*coords)[3])
{
- if (coords) {
- int j;
- for (j = 0; j < 2; j++) {
- copy_v3_v3(r_cos[j], coords[BM_elem_index_get(v[j])]);
- }
- }
- else {
- int j;
- for (j = 0; j < 2; j++) {
- copy_v3_v3(r_cos[j], v[j]->co);
- }
- }
+ if (coords) {
+ int j;
+ for (j = 0; j < 2; j++) {
+ copy_v3_v3(r_cos[j], coords[BM_elem_index_get(v[j])]);
+ }
+ }
+ else {
+ int j;
+ for (j = 0; j < 2; j++) {
+ copy_v3_v3(r_cos[j], v[j]->co);
+ }
+ }
}
-
/**
* Given two opposite edges in a face, finds the ordering of their vertices so
* that cut preview lines won't cross each other.
*/
-static void edgering_find_order(
- BMEdge *eed_last, BMEdge *eed,
- BMVert *eve_last, BMVert *v[2][2])
+static void edgering_find_order(BMEdge *eed_last, BMEdge *eed, BMVert *eve_last, BMVert *v[2][2])
{
- BMLoop *l = eed->l;
-
- /* find correct order for v[1] */
- if (!(BM_edge_in_face(eed, l->f) && BM_edge_in_face(eed_last, l->f))) {
- BMIter liter;
- BM_ITER_ELEM (l, &liter, l, BM_LOOPS_OF_LOOP) {
- if (BM_edge_in_face(eed, l->f) && BM_edge_in_face(eed_last, l->f))
- break;
- }
- }
-
- /* this should never happen */
- if (!l) {
- v[0][0] = eed->v1;
- v[0][1] = eed->v2;
- v[1][0] = eed_last->v1;
- v[1][1] = eed_last->v2;
- return;
- }
-
- BMLoop *l_other = BM_loop_other_edge_loop(l, eed->v1);
- const bool rev = (l_other == l->prev);
- while (l_other->v != eed_last->v1 && l_other->v != eed_last->v2) {
- l_other = rev ? l_other->prev : l_other->next;
- }
-
- if (l_other->v == eve_last) {
- v[0][0] = eed->v1;
- v[0][1] = eed->v2;
- }
- else {
- v[0][0] = eed->v2;
- v[0][1] = eed->v1;
- }
+ BMLoop *l = eed->l;
+
+ /* find correct order for v[1] */
+ if (!(BM_edge_in_face(eed, l->f) && BM_edge_in_face(eed_last, l->f))) {
+ BMIter liter;
+ BM_ITER_ELEM (l, &liter, l, BM_LOOPS_OF_LOOP) {
+ if (BM_edge_in_face(eed, l->f) && BM_edge_in_face(eed_last, l->f))
+ break;
+ }
+ }
+
+ /* this should never happen */
+ if (!l) {
+ v[0][0] = eed->v1;
+ v[0][1] = eed->v2;
+ v[1][0] = eed_last->v1;
+ v[1][1] = eed_last->v2;
+ return;
+ }
+
+ BMLoop *l_other = BM_loop_other_edge_loop(l, eed->v1);
+ const bool rev = (l_other == l->prev);
+ while (l_other->v != eed_last->v1 && l_other->v != eed_last->v2) {
+ l_other = rev ? l_other->prev : l_other->next;
+ }
+
+ if (l_other->v == eve_last) {
+ v[0][0] = eed->v1;
+ v[0][1] = eed->v2;
+ }
+ else {
+ v[0][0] = eed->v2;
+ v[0][1] = eed->v1;
+ }
}
struct EditMesh_PreSelEdgeRing {
- float (*edges)[2][3];
- int edges_len;
+ float (*edges)[2][3];
+ int edges_len;
- float (*verts)[3];
- int verts_len;
+ float (*verts)[3];
+ int verts_len;
};
struct EditMesh_PreSelEdgeRing *EDBM_preselect_edgering_create(void)
{
- struct EditMesh_PreSelEdgeRing *psel = MEM_callocN(sizeof(*psel), __func__);
- return psel;
+ struct EditMesh_PreSelEdgeRing *psel = MEM_callocN(sizeof(*psel), __func__);
+ return psel;
}
-void EDBM_preselect_edgering_destroy(
- struct EditMesh_PreSelEdgeRing *psel)
+void EDBM_preselect_edgering_destroy(struct EditMesh_PreSelEdgeRing *psel)
{
- EDBM_preselect_edgering_clear(psel);
- MEM_freeN(psel);
+ EDBM_preselect_edgering_clear(psel);
+ MEM_freeN(psel);
}
-void EDBM_preselect_edgering_clear(
- struct EditMesh_PreSelEdgeRing *psel)
+void EDBM_preselect_edgering_clear(struct EditMesh_PreSelEdgeRing *psel)
{
- MEM_SAFE_FREE(psel->edges);
- psel->edges_len = 0;
+ MEM_SAFE_FREE(psel->edges);
+ psel->edges_len = 0;
- MEM_SAFE_FREE(psel->verts);
- psel->verts_len = 0;
+ MEM_SAFE_FREE(psel->verts);
+ psel->verts_len = 0;
}
-void EDBM_preselect_edgering_draw(
- struct EditMesh_PreSelEdgeRing *psel, const float matrix[4][4])
+void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const float matrix[4][4])
{
- if ((psel->edges_len == 0) && (psel->verts_len == 0)) {
- return;
- }
+ if ((psel->edges_len == 0) && (psel->verts_len == 0)) {
+ return;
+ }
- GPU_depth_test(false);
+ GPU_depth_test(false);
- GPU_matrix_push();
- GPU_matrix_mul(matrix);
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformThemeColor3(TH_GIZMO_PRIMARY);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor3(TH_GIZMO_PRIMARY);
- if (psel->edges_len > 0) {
- immBegin(GPU_PRIM_LINES, psel->edges_len * 2);
+ if (psel->edges_len > 0) {
+ immBegin(GPU_PRIM_LINES, psel->edges_len * 2);
- for (int i = 0; i < psel->edges_len; i++) {
- immVertex3fv(pos, psel->edges[i][0]);
- immVertex3fv(pos, psel->edges[i][1]);
- }
+ for (int i = 0; i < psel->edges_len; i++) {
+ immVertex3fv(pos, psel->edges[i][0]);
+ immVertex3fv(pos, psel->edges[i][1]);
+ }
- immEnd();
- }
+ immEnd();
+ }
- if (psel->verts_len > 0) {
- GPU_point_size(3.0f);
+ if (psel->verts_len > 0) {
+ GPU_point_size(3.0f);
- immBegin(GPU_PRIM_POINTS, psel->verts_len);
+ immBegin(GPU_PRIM_POINTS, psel->verts_len);
- for (int i = 0; i < psel->verts_len; i++) {
- immVertex3fv(pos, psel->verts[i]);
- }
+ for (int i = 0; i < psel->verts_len; i++) {
+ immVertex3fv(pos, psel->verts[i]);
+ }
- immEnd();
- }
+ immEnd();
+ }
- immUnbindProgram();
+ immUnbindProgram();
- GPU_matrix_pop();
+ GPU_matrix_pop();
- /* Reset default */
- GPU_depth_test(true);
+ /* Reset default */
+ GPU_depth_test(true);
}
static void view3d_preselect_mesh_edgering_update_verts_from_edge(
- struct EditMesh_PreSelEdgeRing *psel,
- BMesh *UNUSED(bm), BMEdge *eed_start, int previewlines, const float (*coords)[3])
+ struct EditMesh_PreSelEdgeRing *psel,
+ BMesh *UNUSED(bm),
+ BMEdge *eed_start,
+ int previewlines,
+ const float (*coords)[3])
{
- float v_cos[2][3];
- float (*verts)[3];
- int i, tot = 0;
+ float v_cos[2][3];
+ float(*verts)[3];
+ int i, tot = 0;
- verts = MEM_mallocN(sizeof(*psel->verts) * previewlines, __func__);
+ verts = MEM_mallocN(sizeof(*psel->verts) * previewlines, __func__);
- edgering_vcos_get_pair(&eed_start->v1, v_cos, coords);
+ edgering_vcos_get_pair(&eed_start->v1, v_cos, coords);
- for (i = 1; i <= previewlines; i++) {
- const float fac = (i / ((float)previewlines + 1));
- interp_v3_v3v3(verts[tot], v_cos[0], v_cos[1], fac);
- tot++;
- }
+ for (i = 1; i <= previewlines; i++) {
+ const float fac = (i / ((float)previewlines + 1));
+ interp_v3_v3v3(verts[tot], v_cos[0], v_cos[1], fac);
+ tot++;
+ }
- psel->verts = verts;
- psel->verts_len = previewlines;
+ psel->verts = verts;
+ psel->verts_len = previewlines;
}
static void view3d_preselect_mesh_edgering_update_edges_from_edge(
- struct EditMesh_PreSelEdgeRing *psel,
- BMesh *bm, BMEdge *eed_start, int previewlines, const float (*coords)[3])
+ struct EditMesh_PreSelEdgeRing *psel,
+ BMesh *bm,
+ BMEdge *eed_start,
+ int previewlines,
+ const float (*coords)[3])
{
- BMWalker walker;
- BMEdge *eed, *eed_last;
- BMVert *v[2][2] = {{NULL}}, *eve_last;
- float (*edges)[2][3] = NULL;
- BLI_Stack *edge_stack;
-
- int i, tot = 0;
-
- BMW_init(&walker, bm, BMW_EDGERING,
- BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
-
- edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__);
-
- eed_last = NULL;
- for (eed = eed_last = BMW_begin(&walker, eed_start); eed; eed = BMW_step(&walker)) {
- BLI_stack_push(edge_stack, &eed);
- }
- BMW_end(&walker);
-
-
- eed_start = *(BMEdge **)BLI_stack_peek(edge_stack);
-
- edges = MEM_mallocN(
- (sizeof(*edges) * (BLI_stack_count(edge_stack) + (eed_last != eed_start))) * previewlines, __func__);
-
- eve_last = NULL;
- eed_last = NULL;
-
- while (!BLI_stack_is_empty(edge_stack)) {
- BLI_stack_pop(edge_stack, &eed);
-
- if (eed_last) {
- if (eve_last) {
- v[1][0] = v[0][0];
- v[1][1] = v[0][1];
- }
- else {
- v[1][0] = eed_last->v1;
- v[1][1] = eed_last->v2;
- eve_last = eed_last->v1;
- }
-
- edgering_find_order(eed_last, eed, eve_last, v);
- eve_last = v[0][0];
-
- for (i = 1; i <= previewlines; i++) {
- const float fac = (i / ((float)previewlines + 1));
- float v_cos[2][2][3];
-
- edgering_vcos_get(v, v_cos, coords);
-
- interp_v3_v3v3(edges[tot][0], v_cos[0][0], v_cos[0][1], fac);
- interp_v3_v3v3(edges[tot][1], v_cos[1][0], v_cos[1][1], fac);
- tot++;
- }
- }
- eed_last = eed;
- }
-
- if ((eed_last != eed_start) &&
+ BMWalker walker;
+ BMEdge *eed, *eed_last;
+ BMVert *v[2][2] = {{NULL}}, *eve_last;
+ float(*edges)[2][3] = NULL;
+ BLI_Stack *edge_stack;
+
+ int i, tot = 0;
+
+ BMW_init(&walker,
+ bm,
+ BMW_EDGERING,
+ BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__);
+
+ eed_last = NULL;
+ for (eed = eed_last = BMW_begin(&walker, eed_start); eed; eed = BMW_step(&walker)) {
+ BLI_stack_push(edge_stack, &eed);
+ }
+ BMW_end(&walker);
+
+ eed_start = *(BMEdge **)BLI_stack_peek(edge_stack);
+
+ edges = MEM_mallocN((sizeof(*edges) * (BLI_stack_count(edge_stack) + (eed_last != eed_start))) *
+ previewlines,
+ __func__);
+
+ eve_last = NULL;
+ eed_last = NULL;
+
+ while (!BLI_stack_is_empty(edge_stack)) {
+ BLI_stack_pop(edge_stack, &eed);
+
+ if (eed_last) {
+ if (eve_last) {
+ v[1][0] = v[0][0];
+ v[1][1] = v[0][1];
+ }
+ else {
+ v[1][0] = eed_last->v1;
+ v[1][1] = eed_last->v2;
+ eve_last = eed_last->v1;
+ }
+
+ edgering_find_order(eed_last, eed, eve_last, v);
+ eve_last = v[0][0];
+
+ for (i = 1; i <= previewlines; i++) {
+ const float fac = (i / ((float)previewlines + 1));
+ float v_cos[2][2][3];
+
+ edgering_vcos_get(v, v_cos, coords);
+
+ interp_v3_v3v3(edges[tot][0], v_cos[0][0], v_cos[0][1], fac);
+ interp_v3_v3v3(edges[tot][1], v_cos[1][0], v_cos[1][1], fac);
+ tot++;
+ }
+ }
+ eed_last = eed;
+ }
+
+ if ((eed_last != eed_start) &&
#ifdef BMW_EDGERING_NGON
- BM_edge_share_face_check(eed_last, eed_start)
+ BM_edge_share_face_check(eed_last, eed_start)
#else
- BM_edge_share_quad_check(eed_last, eed_start)
+ BM_edge_share_quad_check(eed_last, eed_start)
#endif
- )
- {
- v[1][0] = v[0][0];
- v[1][1] = v[0][1];
+ ) {
+ v[1][0] = v[0][0];
+ v[1][1] = v[0][1];
- edgering_find_order(eed_last, eed_start, eve_last, v);
+ edgering_find_order(eed_last, eed_start, eve_last, v);
- for (i = 1; i <= previewlines; i++) {
- const float fac = (i / ((float)previewlines + 1));
- float v_cos[2][2][3];
+ for (i = 1; i <= previewlines; i++) {
+ const float fac = (i / ((float)previewlines + 1));
+ float v_cos[2][2][3];
- if (!v[0][0] || !v[0][1] || !v[1][0] || !v[1][1]) {
- continue;
- }
+ if (!v[0][0] || !v[0][1] || !v[1][0] || !v[1][1]) {
+ continue;
+ }
- edgering_vcos_get(v, v_cos, coords);
+ edgering_vcos_get(v, v_cos, coords);
- interp_v3_v3v3(edges[tot][0], v_cos[0][0], v_cos[0][1], fac);
- interp_v3_v3v3(edges[tot][1], v_cos[1][0], v_cos[1][1], fac);
- tot++;
- }
- }
+ interp_v3_v3v3(edges[tot][0], v_cos[0][0], v_cos[0][1], fac);
+ interp_v3_v3v3(edges[tot][1], v_cos[1][0], v_cos[1][1], fac);
+ tot++;
+ }
+ }
- BLI_stack_free(edge_stack);
+ BLI_stack_free(edge_stack);
- psel->edges = edges;
- psel->edges_len = tot;
+ psel->edges = edges;
+ psel->edges_len = tot;
}
-void EDBM_preselect_edgering_update_from_edge(
- struct EditMesh_PreSelEdgeRing *psel,
- BMesh *bm, BMEdge *eed_start, int previewlines, const float (*coords)[3])
+void EDBM_preselect_edgering_update_from_edge(struct EditMesh_PreSelEdgeRing *psel,
+ BMesh *bm,
+ BMEdge *eed_start,
+ int previewlines,
+ const float (*coords)[3])
{
- EDBM_preselect_edgering_clear(psel);
-
- if (coords) {
- BM_mesh_elem_index_ensure(bm, BM_VERT);
- }
-
- if (BM_edge_is_wire(eed_start)) {
- view3d_preselect_mesh_edgering_update_verts_from_edge(psel, bm, eed_start, previewlines, coords);
- }
- else {
- view3d_preselect_mesh_edgering_update_edges_from_edge(psel, bm, eed_start, previewlines, coords);
- }
-
+ EDBM_preselect_edgering_clear(psel);
+
+ if (coords) {
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+ }
+
+ if (BM_edge_is_wire(eed_start)) {
+ view3d_preselect_mesh_edgering_update_verts_from_edge(
+ psel, bm, eed_start, previewlines, coords);
+ }
+ else {
+ view3d_preselect_mesh_edgering_update_edges_from_edge(
+ psel, bm, eed_start, previewlines, coords);
+ }
}
/** \} */
diff --git a/source/blender/editors/mesh/editmesh_preselect_elem.c b/source/blender/editors/mesh/editmesh_preselect_elem.c
index 827d47a265c..a3e684a5493 100644
--- a/source/blender/editors/mesh/editmesh_preselect_elem.c
+++ b/source/blender/editors/mesh/editmesh_preselect_elem.c
@@ -47,166 +47,166 @@
static void vcos_get(BMVert *v, float r_co[3], const float (*coords)[3])
{
- if (coords) {
- copy_v3_v3(r_co, coords[BM_elem_index_get(v)]);
- }
- else {
- copy_v3_v3(r_co, v->co);
- }
+ if (coords) {
+ copy_v3_v3(r_co, coords[BM_elem_index_get(v)]);
+ }
+ else {
+ copy_v3_v3(r_co, v->co);
+ }
}
static void vcos_get_pair(BMVert *v[2], float r_cos[2][3], const float (*coords)[3])
{
- if (coords) {
- for (int j = 0; j < 2; j++) {
- copy_v3_v3(r_cos[j], coords[BM_elem_index_get(v[j])]);
- }
- }
- else {
- for (int j = 0; j < 2; j++) {
- copy_v3_v3(r_cos[j], v[j]->co);
- }
- }
+ if (coords) {
+ for (int j = 0; j < 2; j++) {
+ copy_v3_v3(r_cos[j], coords[BM_elem_index_get(v[j])]);
+ }
+ }
+ else {
+ for (int j = 0; j < 2; j++) {
+ copy_v3_v3(r_cos[j], v[j]->co);
+ }
+ }
}
struct EditMesh_PreSelElem {
- float (*edges)[2][3];
- int edges_len;
+ float (*edges)[2][3];
+ int edges_len;
- float (*verts)[3];
- int verts_len;
+ float (*verts)[3];
+ int verts_len;
};
struct EditMesh_PreSelElem *EDBM_preselect_elem_create(void)
{
- struct EditMesh_PreSelElem *psel = MEM_callocN(sizeof(*psel), __func__);
- return psel;
+ struct EditMesh_PreSelElem *psel = MEM_callocN(sizeof(*psel), __func__);
+ return psel;
}
-void EDBM_preselect_elem_destroy(
- struct EditMesh_PreSelElem *psel)
+void EDBM_preselect_elem_destroy(struct EditMesh_PreSelElem *psel)
{
- EDBM_preselect_elem_clear(psel);
- MEM_freeN(psel);
+ EDBM_preselect_elem_clear(psel);
+ MEM_freeN(psel);
}
-void EDBM_preselect_elem_clear(
- struct EditMesh_PreSelElem *psel)
+void EDBM_preselect_elem_clear(struct EditMesh_PreSelElem *psel)
{
- MEM_SAFE_FREE(psel->edges);
- psel->edges_len = 0;
+ MEM_SAFE_FREE(psel->edges);
+ psel->edges_len = 0;
- MEM_SAFE_FREE(psel->verts);
- psel->verts_len = 0;
+ MEM_SAFE_FREE(psel->verts);
+ psel->verts_len = 0;
}
-void EDBM_preselect_elem_draw(
- struct EditMesh_PreSelElem *psel, const float matrix[4][4])
+void EDBM_preselect_elem_draw(struct EditMesh_PreSelElem *psel, const float matrix[4][4])
{
- if ((psel->edges_len == 0) && (psel->verts_len == 0)) {
- return;
- }
+ if ((psel->edges_len == 0) && (psel->verts_len == 0)) {
+ return;
+ }
- GPU_depth_test(false);
+ GPU_depth_test(false);
- GPU_matrix_push();
- GPU_matrix_mul(matrix);
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformColor3ub(255, 0, 255);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ub(255, 0, 255);
- if (psel->edges_len > 0) {
- immBegin(GPU_PRIM_LINES, psel->edges_len * 2);
+ if (psel->edges_len > 0) {
+ immBegin(GPU_PRIM_LINES, psel->edges_len * 2);
- for (int i = 0; i < psel->edges_len; i++) {
- immVertex3fv(pos, psel->edges[i][0]);
- immVertex3fv(pos, psel->edges[i][1]);
- }
+ for (int i = 0; i < psel->edges_len; i++) {
+ immVertex3fv(pos, psel->edges[i][0]);
+ immVertex3fv(pos, psel->edges[i][1]);
+ }
- immEnd();
- }
+ immEnd();
+ }
- if (psel->verts_len > 0) {
- GPU_point_size(3.0f);
+ if (psel->verts_len > 0) {
+ GPU_point_size(3.0f);
- immBegin(GPU_PRIM_POINTS, psel->verts_len);
+ immBegin(GPU_PRIM_POINTS, psel->verts_len);
- for (int i = 0; i < psel->verts_len; i++) {
- immVertex3fv(pos, psel->verts[i]);
- }
+ for (int i = 0; i < psel->verts_len; i++) {
+ immVertex3fv(pos, psel->verts[i]);
+ }
- immEnd();
- }
+ immEnd();
+ }
- immUnbindProgram();
+ immUnbindProgram();
- GPU_matrix_pop();
+ GPU_matrix_pop();
- /* Reset default */
- GPU_depth_test(true);
+ /* Reset default */
+ GPU_depth_test(true);
}
-static void view3d_preselect_mesh_elem_update_from_vert(
- struct EditMesh_PreSelElem *psel,
- BMesh *UNUSED(bm), BMVert *eve, const float (*coords)[3])
+static void view3d_preselect_mesh_elem_update_from_vert(struct EditMesh_PreSelElem *psel,
+ BMesh *UNUSED(bm),
+ BMVert *eve,
+ const float (*coords)[3])
{
- float (*verts)[3] = MEM_mallocN(sizeof(*psel->verts), __func__);
- vcos_get(eve, verts[0], coords);
- psel->verts = verts;
- psel->verts_len = 1;
+ float(*verts)[3] = MEM_mallocN(sizeof(*psel->verts), __func__);
+ vcos_get(eve, verts[0], coords);
+ psel->verts = verts;
+ psel->verts_len = 1;
}
-static void view3d_preselect_mesh_elem_update_from_edge(
- struct EditMesh_PreSelElem *psel,
- BMesh *UNUSED(bm), BMEdge *eed, const float (*coords)[3])
+static void view3d_preselect_mesh_elem_update_from_edge(struct EditMesh_PreSelElem *psel,
+ BMesh *UNUSED(bm),
+ BMEdge *eed,
+ const float (*coords)[3])
{
- float (*edges)[2][3] = MEM_mallocN(sizeof(*psel->edges), __func__);
- vcos_get_pair(&eed->v1, edges[0], coords);
- psel->edges = edges;
- psel->edges_len = 1;
+ float(*edges)[2][3] = MEM_mallocN(sizeof(*psel->edges), __func__);
+ vcos_get_pair(&eed->v1, edges[0], coords);
+ psel->edges = edges;
+ psel->edges_len = 1;
}
-static void view3d_preselect_mesh_elem_update_from_face(
- struct EditMesh_PreSelElem *psel,
- BMesh *UNUSED(bm), BMFace *efa, const float (*coords)[3])
+static void view3d_preselect_mesh_elem_update_from_face(struct EditMesh_PreSelElem *psel,
+ BMesh *UNUSED(bm),
+ BMFace *efa,
+ const float (*coords)[3])
{
- float (*edges)[2][3] = MEM_mallocN(sizeof(*psel->edges) * efa->len, __func__);
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
- int i = 0;
- do {
- vcos_get_pair(&l_iter->e->v1, edges[i++], coords);
- } while ((l_iter = l_iter->next) != l_first);
- psel->edges = edges;
- psel->edges_len = efa->len;
+ float(*edges)[2][3] = MEM_mallocN(sizeof(*psel->edges) * efa->len, __func__);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ int i = 0;
+ do {
+ vcos_get_pair(&l_iter->e->v1, edges[i++], coords);
+ } while ((l_iter = l_iter->next) != l_first);
+ psel->edges = edges;
+ psel->edges_len = efa->len;
}
-void EDBM_preselect_elem_update_from_single(
- struct EditMesh_PreSelElem *psel,
- BMesh *bm, BMElem *ele,
- const float (*coords)[3])
+void EDBM_preselect_elem_update_from_single(struct EditMesh_PreSelElem *psel,
+ BMesh *bm,
+ BMElem *ele,
+ const float (*coords)[3])
{
- EDBM_preselect_elem_clear(psel);
-
- if (coords) {
- BM_mesh_elem_index_ensure(bm, BM_VERT);
- }
-
- switch (ele->head.htype) {
- case BM_VERT:
- view3d_preselect_mesh_elem_update_from_vert(psel, bm, (BMVert *)ele, coords);
- break;
- case BM_EDGE:
- view3d_preselect_mesh_elem_update_from_edge(psel, bm, (BMEdge *)ele, coords);
- break;
- case BM_FACE:
- view3d_preselect_mesh_elem_update_from_face(psel, bm, (BMFace *)ele, coords);
- break;
- default:
- BLI_assert(0);
- }
+ EDBM_preselect_elem_clear(psel);
+
+ if (coords) {
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+ }
+
+ switch (ele->head.htype) {
+ case BM_VERT:
+ view3d_preselect_mesh_elem_update_from_vert(psel, bm, (BMVert *)ele, coords);
+ break;
+ case BM_EDGE:
+ view3d_preselect_mesh_elem_update_from_edge(psel, bm, (BMEdge *)ele, coords);
+ break;
+ case BM_FACE:
+ view3d_preselect_mesh_elem_update_from_face(psel, bm, (BMFace *)ele, coords);
+ break;
+ default:
+ BLI_assert(0);
+ }
}
/** \} */
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index 2117c2bb689..42521d04008 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -46,7 +46,7 @@
#include "bmesh.h"
#include "bmesh_tools.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
/**
* helper to find edge for edge_rip,
@@ -56,30 +56,32 @@
* point and would result in the same distance.
*/
#define INSET_DEFAULT 0.00001f
-static float edbm_rip_edgedist_squared(
- ARegion *ar, float mat[4][4],
- const float co1[3], const float co2[3], const float mvalf[2],
- const float inset)
+static float edbm_rip_edgedist_squared(ARegion *ar,
+ float mat[4][4],
+ const float co1[3],
+ const float co2[3],
+ const float mvalf[2],
+ const float inset)
{
- float vec1[2], vec2[2], dist_sq;
+ 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(ar, co1, vec1, mat);
+ ED_view3d_project_float_v2_m4(ar, co2, vec2, mat);
- if (inset != 0.0f) {
- const float dist_2d = len_v2v2(vec1, vec2);
- if (dist_2d > FLT_EPSILON) {
- const float dist = inset / dist_2d;
- BLI_assert(isfinite(dist));
- interp_v2_v2v2(vec1, vec1, vec2, dist);
- interp_v2_v2v2(vec2, vec2, vec1, dist);
- }
- }
+ if (inset != 0.0f) {
+ const float dist_2d = len_v2v2(vec1, vec2);
+ if (dist_2d > FLT_EPSILON) {
+ const float dist = inset / dist_2d;
+ BLI_assert(isfinite(dist));
+ interp_v2_v2v2(vec1, vec1, vec2, dist);
+ interp_v2_v2v2(vec2, vec2, vec1, dist);
+ }
+ }
- dist_sq = dist_squared_to_line_segment_v2(mvalf, vec1, vec2);
- BLI_assert(isfinite(dist_sq));
+ dist_sq = dist_squared_to_line_segment_v2(mvalf, vec1, vec2);
+ BLI_assert(isfinite(dist_sq));
- return dist_sq;
+ return dist_sq;
}
#if 0
@@ -87,83 +89,78 @@ static float edbm_rip_linedist(
ARegion *ar, float mat[4][4],
const float co1[3], const float co2[3], const float mvalf[2])
{
- float vec1[2], vec2[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(ar, co1, vec1, mat);
+ ED_view3d_project_float_v2_m4(ar, co2, vec2, mat);
- return dist_to_line_v2(mvalf, vec1, vec2);
+ return dist_to_line_v2(mvalf, vec1, vec2);
}
#endif
/* calculaters a point along the loop tangent which can be used to measure against edges */
static void edbm_calc_loop_co(BMLoop *l, float l_mid_co[3])
{
- BM_loop_calc_face_tangent(l, l_mid_co);
+ BM_loop_calc_face_tangent(l, l_mid_co);
- /* scale to average of surrounding edge size, only needs to be approx, but should
- * be roughly equivalent to the check below which uses the middle of the edge. */
- mul_v3_fl(l_mid_co, (BM_edge_calc_length(l->e) + BM_edge_calc_length(l->prev->e)) / 2.0f);
+ /* scale to average of surrounding edge size, only needs to be approx, but should
+ * be roughly equivalent to the check below which uses the middle of the edge. */
+ mul_v3_fl(l_mid_co, (BM_edge_calc_length(l->e) + BM_edge_calc_length(l->prev->e)) / 2.0f);
- add_v3_v3(l_mid_co, l->v->co);
+ add_v3_v3(l_mid_co, l->v->co);
}
-
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 *ar, float projectMat[4][4], const float fmval[2])
{
- float cent[3] = {0, 0, 0}, mid[3];
+ float cent[3] = {0, 0, 0}, mid[3];
- float vec[2];
- float fmval_tweak[2];
- float e_v1_co[2], e_v2_co[2];
- float score;
+ float vec[2];
+ float fmval_tweak[2];
+ float e_v1_co[2], e_v2_co[2];
+ float score;
- BMVert *v1_other;
- BMVert *v2_other;
+ BMVert *v1_other;
+ BMVert *v2_other;
- BLI_assert(BM_vert_in_edge(e, e_l->v));
+ BLI_assert(BM_vert_in_edge(e, e_l->v));
- /* method for calculating distance:
- *
- * for each edge: calculate face center, then made a vector
- * from edge midpoint to face center. offset edge midpoint
- * by a small amount along this vector. */
+ /* method for calculating distance:
+ *
+ * for each edge: calculate face center, then made a vector
+ * from edge midpoint to face center. offset edge midpoint
+ * by a small amount along this vector. */
- /* rather then the face center, get the middle of
- * both edge verts connected to this one */
- v1_other = BM_face_other_vert_loop(e_l->f, e->v2, e->v1)->v;
- v2_other = BM_face_other_vert_loop(e_l->f, e->v1, e->v2)->v;
- mid_v3_v3v3(cent, v1_other->co, v2_other->co);
- mid_v3_v3v3(mid, e->v1->co, e->v2->co);
+ /* rather then the face center, get the middle of
+ * both edge verts connected to this one */
+ v1_other = BM_face_other_vert_loop(e_l->f, e->v2, e->v1)->v;
+ v2_other = BM_face_other_vert_loop(e_l->f, e->v1, e->v2)->v;
+ 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(ar, cent, cent, projectMat);
+ ED_view3d_project_float_v2_m4(ar, 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(ar, e->v1->co, e_v1_co, projectMat);
+ ED_view3d_project_float_v2_m4(ar, e->v2->co, e_v2_co, projectMat);
- sub_v2_v2v2(vec, cent, mid);
- normalize_v2_length(vec, 0.01f);
+ sub_v2_v2v2(vec, cent, mid);
+ normalize_v2_length(vec, 0.01f);
- /* rather then adding to both verts, subtract from the mouse */
- sub_v2_v2v2(fmval_tweak, fmval, vec);
+ /* rather then adding to both verts, subtract from the mouse */
+ sub_v2_v2v2(fmval_tweak, fmval, vec);
- score = len_v2v2(e_v1_co, e_v2_co);
+ score = len_v2v2(e_v1_co, e_v2_co);
- if (dist_squared_to_line_segment_v2(fmval_tweak, e_v1_co, e_v2_co) >
- dist_squared_to_line_segment_v2(fmval, e_v1_co, e_v2_co))
- {
- return score;
- }
- else {
- return -score;
- }
+ if (dist_squared_to_line_segment_v2(fmval_tweak, e_v1_co, e_v2_co) >
+ dist_squared_to_line_segment_v2(fmval, e_v1_co, e_v2_co)) {
+ return score;
+ }
+ else {
+ return -score;
+ }
}
-
/* - Advanced selection handling 'ripsel' functions ----- */
/**
@@ -195,195 +192,189 @@ static float edbm_rip_edge_side_measure(
* - campbell.
*/
-
-#define IS_VISIT_POSSIBLE(e) (BM_edge_is_manifold(e) && BM_elem_flag_test(e, BM_ELEM_TAG))
+#define IS_VISIT_POSSIBLE(e) (BM_edge_is_manifold(e) && BM_elem_flag_test(e, BM_ELEM_TAG))
#define IS_VISIT_DONE(e) ((e)->l && (BM_elem_index_get((e)->l) != INVALID_UID))
#define INVALID_UID INT_MIN
/* mark, assign uid and step */
static BMEdge *edbm_ripsel_edge_mark_step(BMVert *v, const int uid)
{
- BMIter iter;
- BMEdge *e;
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- if (IS_VISIT_POSSIBLE(e) && !IS_VISIT_DONE(e)) {
- BMLoop *l_a, *l_b;
-
- BM_edge_loop_pair(e, &l_a, &l_b); /* no need to check, we know this will be true */
-
- /* so (IS_VISIT_DONE == true) */
- BM_elem_index_set(l_a, uid); /* set_dirty */
- BM_elem_index_set(l_b, uid); /* set_dirty */
-
- return e;
- }
- }
- return NULL;
+ BMIter iter;
+ BMEdge *e;
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ if (IS_VISIT_POSSIBLE(e) && !IS_VISIT_DONE(e)) {
+ BMLoop *l_a, *l_b;
+
+ BM_edge_loop_pair(e, &l_a, &l_b); /* no need to check, we know this will be true */
+
+ /* so (IS_VISIT_DONE == true) */
+ BM_elem_index_set(l_a, uid); /* set_dirty */
+ BM_elem_index_set(l_b, uid); /* set_dirty */
+
+ return e;
+ }
+ }
+ return NULL;
}
typedef struct EdgeLoopPair {
- BMLoop *l_a;
- BMLoop *l_b;
+ BMLoop *l_a;
+ BMLoop *l_b;
} EdgeLoopPair;
static EdgeLoopPair *edbm_ripsel_looptag_helper(BMesh *bm)
{
- BMIter fiter;
- BMIter liter;
-
- BMFace *f;
- BMLoop *l;
-
- int uid_start;
- int uid_end;
- int uid = bm->totedge; /* can start anywhere */
-
- EdgeLoopPair *eloop_pairs = NULL;
- BLI_array_declare(eloop_pairs);
- EdgeLoopPair *lp;
-
- /* initialize loops with dummy invalid index values */
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- BM_elem_index_set(l, INVALID_UID); /* set_dirty */
- }
- }
- bm->elem_index_dirty |= BM_LOOP;
-
- /* set contiguous loops ordered 'uid' values for walking after split */
- while (true) {
- int tot = 0;
- BMIter eiter;
- BMEdge *e_step;
- BMVert *v_step;
- BMEdge *e;
- BMEdge *e_first;
- BMEdge *e_last;
-
- e_first = NULL;
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (IS_VISIT_POSSIBLE(e) && !IS_VISIT_DONE(e)) {
- e_first = e;
- break;
- }
- }
-
- if (e_first == NULL) {
- break;
- }
-
- /* initialize */
- e_first = e;
- v_step = e_first->v1;
- e_step = NULL; /* quiet warning, will never remain this value */
-
- uid_start = uid;
- while ((e = edbm_ripsel_edge_mark_step(v_step, uid))) {
- v_step = BM_edge_other_vert((e_step = e), v_step);
- uid++; /* only different line */
- tot++;
- }
-
- /* this edges loops have the highest uid's, store this to walk down later */
- e_last = e_step;
-
- /* always store the highest 'uid' edge for the stride */
- uid_end = uid - 1;
- uid = uid_start - 1;
-
- /* initialize */
- v_step = e_first->v1;
-
- while ((e = edbm_ripsel_edge_mark_step(v_step, uid))) {
- v_step = BM_edge_other_vert((e_step = e), v_step);
- uid--; /* only different line */
- tot++;
- }
-
- /* stride far enough not to _ever_ overlap range */
- uid_start = uid;
- uid = uid_end + bm->totedge;
-
- lp = BLI_array_append_ret(eloop_pairs);
- /* no need to check, we know this will be true */
- BM_edge_loop_pair(e_last, &lp->l_a, &lp->l_b);
-
-
- BLI_assert(tot == uid_end - uid_start);
+ BMIter fiter;
+ BMIter liter;
+
+ BMFace *f;
+ BMLoop *l;
+
+ int uid_start;
+ int uid_end;
+ int uid = bm->totedge; /* can start anywhere */
+
+ EdgeLoopPair *eloop_pairs = NULL;
+ BLI_array_declare(eloop_pairs);
+ EdgeLoopPair *lp;
+
+ /* initialize loops with dummy invalid index values */
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ BM_elem_index_set(l, INVALID_UID); /* set_dirty */
+ }
+ }
+ bm->elem_index_dirty |= BM_LOOP;
+
+ /* set contiguous loops ordered 'uid' values for walking after split */
+ while (true) {
+ int tot = 0;
+ BMIter eiter;
+ BMEdge *e_step;
+ BMVert *v_step;
+ BMEdge *e;
+ BMEdge *e_first;
+ BMEdge *e_last;
+
+ e_first = NULL;
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (IS_VISIT_POSSIBLE(e) && !IS_VISIT_DONE(e)) {
+ e_first = e;
+ break;
+ }
+ }
+
+ if (e_first == NULL) {
+ break;
+ }
+
+ /* initialize */
+ e_first = e;
+ v_step = e_first->v1;
+ e_step = NULL; /* quiet warning, will never remain this value */
+
+ uid_start = uid;
+ while ((e = edbm_ripsel_edge_mark_step(v_step, uid))) {
+ v_step = BM_edge_other_vert((e_step = e), v_step);
+ uid++; /* only different line */
+ tot++;
+ }
+
+ /* this edges loops have the highest uid's, store this to walk down later */
+ e_last = e_step;
+
+ /* always store the highest 'uid' edge for the stride */
+ uid_end = uid - 1;
+ uid = uid_start - 1;
+
+ /* initialize */
+ v_step = e_first->v1;
+
+ while ((e = edbm_ripsel_edge_mark_step(v_step, uid))) {
+ v_step = BM_edge_other_vert((e_step = e), v_step);
+ uid--; /* only different line */
+ tot++;
+ }
+
+ /* stride far enough not to _ever_ overlap range */
+ uid_start = uid;
+ uid = uid_end + bm->totedge;
+
+ lp = BLI_array_append_ret(eloop_pairs);
+ /* no need to check, we know this will be true */
+ BM_edge_loop_pair(e_last, &lp->l_a, &lp->l_b);
+
+ BLI_assert(tot == uid_end - uid_start);
#if 0
- printf("%s: found contiguous edge loop of (%d)\n", __func__, uid_end - uid_start);
+ printf("%s: found contiguous edge loop of (%d)\n", __func__, uid_end - uid_start);
#endif
+ }
- }
-
- /* null terminate */
- lp = BLI_array_append_ret(eloop_pairs);
- lp->l_a = lp->l_b = NULL;
+ /* null terminate */
+ lp = BLI_array_append_ret(eloop_pairs);
+ lp->l_a = lp->l_b = NULL;
- return eloop_pairs;
+ return eloop_pairs;
}
-
/* - De-Select the worst rip-edge side -------------------------------- */
-
static BMEdge *edbm_ripsel_edge_uid_step(BMEdge *e_orig, BMVert **v_prev)
{
- BMIter eiter;
- BMEdge *e;
- BMVert *v = BM_edge_other_vert(e_orig, *v_prev);
- const int uid_cmp = BM_elem_index_get(e_orig->l) - 1;
-
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (BM_elem_index_get(e->l) == uid_cmp) {
- *v_prev = v;
- return e;
- }
- }
- return NULL;
+ BMIter eiter;
+ BMEdge *e;
+ BMVert *v = BM_edge_other_vert(e_orig, *v_prev);
+ const int uid_cmp = BM_elem_index_get(e_orig->l) - 1;
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_index_get(e->l) == uid_cmp) {
+ *v_prev = v;
+ return e;
+ }
+ }
+ return NULL;
}
static BMVert *edbm_ripsel_edloop_pair_start_vert(BMEdge *e)
{
- /* try step in a direction, if it fails we know do go the other way */
- BMVert *v_test = e->v1;
- return (edbm_ripsel_edge_uid_step(e, &v_test)) ? e->v1 : e->v2;
+ /* try step in a direction, if it fails we know do go the other way */
+ BMVert *v_test = e->v1;
+ return (edbm_ripsel_edge_uid_step(e, &v_test)) ? e->v1 : e->v2;
}
-static void edbm_ripsel_deselect_helper(BMesh *bm, EdgeLoopPair *eloop_pairs,
- ARegion *ar, float projectMat[4][4], float fmval[2])
+static void edbm_ripsel_deselect_helper(
+ BMesh *bm, EdgeLoopPair *eloop_pairs, ARegion *ar, float projectMat[4][4], float fmval[2])
{
- EdgeLoopPair *lp;
-
- for (lp = eloop_pairs; lp->l_a; lp++) {
- BMEdge *e;
- BMVert *v_prev;
-
- float score_a = 0.0f;
- float score_b = 0.0f;
-
- 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);
- }
- 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);
- }
-
- e = (score_a > score_b) ? lp->l_a->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)) {
- BM_edge_select_set(bm, e, false);
- }
- }
+ EdgeLoopPair *lp;
+
+ for (lp = eloop_pairs; lp->l_a; lp++) {
+ BMEdge *e;
+ BMVert *v_prev;
+
+ float score_a = 0.0f;
+ float score_b = 0.0f;
+
+ 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);
+ }
+ 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);
+ }
+
+ e = (score_a > score_b) ? lp->l_a->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)) {
+ BM_edge_select_set(bm, e, false);
+ }
+ }
}
/* --- end 'ripsel' selection handling code --- */
-
/* --- face-fill code --- */
/**
* return an un-ordered array of loop pairs
@@ -396,120 +387,121 @@ static void edbm_ripsel_deselect_helper(BMesh *bm, EdgeLoopPair *eloop_pairs,
*/
typedef struct UnorderedLoopPair {
- BMLoop *l_pair[2];
- char flag;
+ BMLoop *l_pair[2];
+ char flag;
} UnorderedLoopPair;
enum {
- ULP_FLIP_0 = (1 << 0),
- ULP_FLIP_1 = (1 << 1),
+ ULP_FLIP_0 = (1 << 0),
+ ULP_FLIP_1 = (1 << 1),
};
static UnorderedLoopPair *edbm_tagged_loop_pairs_to_fill(BMesh *bm)
{
- BMIter iter;
- BMEdge *e;
-
- unsigned int 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)) {
- total_tag++;
- }
- }
-
- if (total_tag) {
- UnorderedLoopPair *uloop_pairs = MEM_mallocN(total_tag * sizeof(UnorderedLoopPair), __func__);
- UnorderedLoopPair *ulp = uloop_pairs;
-
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BMLoop *l1, *l2;
- if (BM_edge_loop_pair(e, &l1, &l2)) {
- BMVert *v_cmp = l1->e->v1;
- ulp->flag = (((l1->v != v_cmp) ? ULP_FLIP_0 : 0) |
- ((l2->v == v_cmp) ? ULP_FLIP_1 : 0));
- }
- else {
- ulp->flag = 0;
- }
- ulp->l_pair[0] = l1;
- ulp->l_pair[1] = l2;
-
- ulp++;
- }
- }
-
- return uloop_pairs;
- }
- else {
- return NULL;
- }
+ BMIter iter;
+ BMEdge *e;
+
+ unsigned int 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)) {
+ total_tag++;
+ }
+ }
+
+ if (total_tag) {
+ UnorderedLoopPair *uloop_pairs = MEM_mallocN(total_tag * sizeof(UnorderedLoopPair), __func__);
+ UnorderedLoopPair *ulp = uloop_pairs;
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BMLoop *l1, *l2;
+ if (BM_edge_loop_pair(e, &l1, &l2)) {
+ BMVert *v_cmp = l1->e->v1;
+ ulp->flag = (((l1->v != v_cmp) ? ULP_FLIP_0 : 0) | ((l2->v == v_cmp) ? ULP_FLIP_1 : 0));
+ }
+ else {
+ ulp->flag = 0;
+ }
+ ulp->l_pair[0] = l1;
+ ulp->l_pair[1] = l2;
+
+ ulp++;
+ }
+ }
+
+ return uloop_pairs;
+ }
+ else {
+ return NULL;
+ }
}
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;
-
- 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))
- {
- /* time has come to make a face! */
- BMVert *v_shared = BM_edge_share_vert(ulp->l_pair[0]->e, ulp->l_pair[1]->e);
- BMFace *f, *f_example = ulp->l_pair[0]->f;
- BMLoop *l_iter;
- BMVert *f_verts[4];
-
- if (v_shared == NULL) {
- /* quad */
- f_verts[0] = ulp->l_pair[0]->e->v1;
- f_verts[1] = ulp->l_pair[1]->e->v1;
- f_verts[2] = ulp->l_pair[1]->e->v2;
- f_verts[3] = ulp->l_pair[0]->e->v2;
-
- if (ulp->flag & ULP_FLIP_0) {
- SWAP(BMVert *, f_verts[0], f_verts[3]);
- }
- if (ulp->flag & ULP_FLIP_1) {
- SWAP(BMVert *, f_verts[1], f_verts[2]);
- }
- }
- else {
- /* tri */
- f_verts[0] = v_shared;
- f_verts[1] = BM_edge_other_vert(ulp->l_pair[0]->e, v_shared);
- f_verts[2] = BM_edge_other_vert(ulp->l_pair[1]->e, v_shared);
- f_verts[3] = NULL;
-
- /* don't use the flip flags */
- if (v_shared == ulp->l_pair[0]->v) {
- SWAP(BMVert *, f_verts[0], f_verts[1]);
- }
- }
-
- /* face should never exist */
- BLI_assert(!BM_face_exists(f_verts, f_verts[3] ? 4 : 3));
-
- f = BM_face_create_verts(bm, f_verts, f_verts[3] ? 4 : 3, f_example, BM_CREATE_NOP, true);
-
- l_iter = BM_FACE_FIRST_LOOP(f);
-
- if (f_verts[3]) {
- BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next;
- BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter); l_iter = l_iter->next;
- BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter); l_iter = l_iter->next;
- BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter);
- }
- else {
- BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next;
- BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next;
- BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter);
- }
-
- }
- }
+ UnorderedLoopPair *ulp;
+ unsigned int total_tag = MEM_allocN_len(uloop_pairs) / sizeof(UnorderedLoopPair);
+ unsigned int 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)) {
+ /* time has come to make a face! */
+ BMVert *v_shared = BM_edge_share_vert(ulp->l_pair[0]->e, ulp->l_pair[1]->e);
+ BMFace *f, *f_example = ulp->l_pair[0]->f;
+ BMLoop *l_iter;
+ BMVert *f_verts[4];
+
+ if (v_shared == NULL) {
+ /* quad */
+ f_verts[0] = ulp->l_pair[0]->e->v1;
+ f_verts[1] = ulp->l_pair[1]->e->v1;
+ f_verts[2] = ulp->l_pair[1]->e->v2;
+ f_verts[3] = ulp->l_pair[0]->e->v2;
+
+ if (ulp->flag & ULP_FLIP_0) {
+ SWAP(BMVert *, f_verts[0], f_verts[3]);
+ }
+ if (ulp->flag & ULP_FLIP_1) {
+ SWAP(BMVert *, f_verts[1], f_verts[2]);
+ }
+ }
+ else {
+ /* tri */
+ f_verts[0] = v_shared;
+ f_verts[1] = BM_edge_other_vert(ulp->l_pair[0]->e, v_shared);
+ f_verts[2] = BM_edge_other_vert(ulp->l_pair[1]->e, v_shared);
+ f_verts[3] = NULL;
+
+ /* don't use the flip flags */
+ if (v_shared == ulp->l_pair[0]->v) {
+ SWAP(BMVert *, f_verts[0], f_verts[1]);
+ }
+ }
+
+ /* face should never exist */
+ BLI_assert(!BM_face_exists(f_verts, f_verts[3] ? 4 : 3));
+
+ f = BM_face_create_verts(bm, f_verts, f_verts[3] ? 4 : 3, f_example, BM_CREATE_NOP, true);
+
+ l_iter = BM_FACE_FIRST_LOOP(f);
+
+ if (f_verts[3]) {
+ BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter);
+ l_iter = l_iter->next;
+ BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter);
+ l_iter = l_iter->next;
+ BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter);
+ l_iter = l_iter->next;
+ BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter);
+ }
+ else {
+ BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter);
+ l_iter = l_iter->next;
+ BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter);
+ l_iter = l_iter->next;
+ BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter);
+ }
+ }
+ }
}
/* --- end 'face-fill' code --- */
@@ -519,357 +511,355 @@ 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);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMIter iter, liter;
- BMLoop *l;
- BMEdge *e_best;
- BMVert *v;
- const int totvert_orig = bm->totvert;
- int i;
- float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]};
- float dist_sq = FLT_MAX;
- float d;
- bool is_wire, is_manifold_region;
-
- BMEditSelection ese;
- int totboundary_edge = 0;
-
- ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat);
-
- /* find selected vert - same some time and check history first */
- if (BM_select_history_active_get(bm, &ese) && ese.htype == BM_VERT) {
- v = (BMVert *)ese.ele;
- }
- else {
- ese.ele = NULL;
-
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT))
- break;
- }
- }
-
- /* (v == NULL) should be impossible */
- if ((v == NULL) || (v->e == NULL)) {
- return OPERATOR_CANCELLED;
- }
-
- is_wire = BM_vert_is_wire(v);
- is_manifold_region = BM_vert_is_manifold_region(v);
-
- e_best = NULL;
-
- {
- BMEdge *e;
- /* find closest edge to mouse cursor */
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- /* consider wire as boundary for this purpose,
- * otherwise we can't a face away from a wire edge */
- totboundary_edge += (BM_edge_is_boundary(e) || BM_edge_is_wire(e));
- 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);
- if ((e_best == NULL) || (d < dist_sq)) {
- dist_sq = d;
- e_best = e;
- }
- }
- }
- }
- }
-
- if (e_best && e_best->l && (is_manifold_region == false)) {
- /* Try to split off a non-manifold fan (when we have multiple disconnected fans) */
- BMLoop *l_sep = e_best->l->v == v ? e_best->l : e_best->l->next;
- BMVert *v_new;
-
- BLI_assert(l_sep->v == v);
- v_new = BM_face_loop_separate_multi_isolated(bm, l_sep);
- BLI_assert(BM_vert_find_first_loop(v));
-
- BM_vert_select_set(bm, v, false);
- BM_select_history_remove(bm, v);
-
- BM_vert_select_set(bm, v_new, true);
- if (ese.ele) {
- BM_select_history_store(bm, v_new);
- }
-
- if (do_fill) {
- BM_edge_create(bm, v, v_new, NULL, BM_CREATE_NOP);
- }
-
- return OPERATOR_FINISHED;
- }
-
- /* if we are ripping a single vertex from 3 faces,
- * then measure the distance to the face corner as well as the edge */
- if (BM_vert_face_count_is_equal(v, 3) &&
- BM_vert_edge_count_is_equal(v, 3))
- {
- BMEdge *e_all[3];
- BMLoop *l_all[3];
- int i1, i2;
-
- BM_iter_as_array(bm, BM_EDGES_OF_VERT, v, (void **)e_all, 3);
- BM_iter_as_array(bm, BM_LOOPS_OF_VERT, v, (void **)l_all, 3);
-
- /* not do a loop similar to the one above, but test against loops */
- for (i1 = 0; i1 < 3; i1++) {
- /* consider wire as boundary for this purpose,
- * otherwise we can't a face away from a wire edge */
- 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);
- if ((e_best == NULL) || (d < dist_sq)) {
- dist_sq = d;
-
- /* find the edge that is not in this loop */
- e_best = NULL;
- for (i2 = 0; i2 < 3; i2++) {
- if (!BM_edge_in_loop(e_all[i2], l)) {
- e_best = e_all[i2];
- break;
- }
- }
- BLI_assert(e_best != NULL);
- }
- }
- }
-
- /* should we go ahead with edge rip or do we need to do special case, split off vertex?:
- * split off vertex if...
- * - we cant find an edge - this means we are ripping a faces vert that is connected to other
- * geometry only at the vertex.
- * - the boundary edge total is greater than 2,
- * in this case edge split _can_ work but we get far nicer results if we use this special case.
- * - there are only 2 edges but we are a wire vert. */
- if ((is_wire == false && totboundary_edge > 2) ||
- (is_wire == true && totboundary_edge > 1))
- {
- BMVert **vout;
- int vout_len;
-
- BM_vert_select_set(bm, v, false);
-
- bmesh_kernel_vert_separate(bm, v, &vout, &vout_len, true);
-
- if (vout_len < 2) {
- MEM_freeN(vout);
- /* set selection back to avoid active-unselected vertex */
- BM_vert_select_set(bm, v, true);
- /* should never happen */
- return OPERATOR_CANCELLED;
- }
- else {
- int vi_best = 0;
-
- if (ese.ele) {
- BM_select_history_remove(bm, ese.ele);
- }
-
- dist_sq = FLT_MAX;
-
- /* in the loop below we find the best vertex to drag based on its connected geometry,
- * either by its face corner, or connected edge (when no faces are attached) */
- for (i = 0; i < vout_len; i++) {
-
- if (BM_vert_is_wire(vout[i]) == false) {
- /* find the best face corner */
- BM_ITER_ELEM (l, &iter, vout[i], BM_LOOPS_OF_VERT) {
- if (!BM_elem_flag_test(l->f, BM_ELEM_HIDDEN)) {
- 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);
-
- if (d < dist_sq) {
- dist_sq = d;
- vi_best = i;
- }
- }
- }
- }
- else {
- BMEdge *e;
- /* a wire vert, find the best edge */
- BM_ITER_ELEM (e, &iter, vout[i], BM_EDGES_OF_VERT) {
- if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- 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);
-
- if (d < dist_sq) {
- dist_sq = d;
- vi_best = i;
- }
- }
- }
- }
- }
-
- /* vout[0] == best
- * vout[1] == glue
- * vout[2+] == splice with glue (when vout_len > 2)
- */
- if (vi_best != 0) {
- SWAP(BMVert *, vout[0], vout[vi_best]);
- vi_best = 0;
- }
-
- /* select the vert from the best region */
- v = vout[vi_best];
- BM_vert_select_set(bm, v, true);
-
- if (ese.ele) {
- BM_select_history_store(bm, v);
- }
-
- /* splice all others back together */
- if (vout_len > 2) {
- for (i = 2; i < vout_len; i++) {
- BM_vert_splice(bm, vout[1], vout[i]);
- }
- }
-
- if (do_fill) {
- /* match extrude vert-order */
- BM_edge_create(bm, vout[1], vout[0], NULL, BM_CREATE_NOP);
- }
-
- MEM_freeN(vout);
-
- return OPERATOR_FINISHED;
- }
- }
-
- if (!e_best) {
- return OPERATOR_CANCELLED;
- }
-
- /* *** Execute the split! *** */
- /* unlike edge split, for single vertex split we only use the operator in one of the cases
- * but both allocate fill */
-
- {
- BMVert *v_rip;
- BMLoop *larr[2];
- int larr_len = 0;
-
- /* rip two adjacent edges */
- if (BM_edge_is_boundary(e_best) || BM_vert_face_count_is_equal(v, 2)) {
- /* Don't run the edge split operator in this case */
-
- l = BM_edge_vert_share_loop(e_best->l, v);
- larr[larr_len] = l;
- larr_len++;
-
- /* only tag for face-fill (we don't call the operator) */
- if (BM_edge_is_boundary(e_best)) {
- BM_elem_flag_enable(e_best, BM_ELEM_TAG);
- }
- else {
- BM_elem_flag_enable(l->e, BM_ELEM_TAG);
- BM_elem_flag_enable(l->prev->e, BM_ELEM_TAG);
- }
- }
- else {
- if (BM_edge_is_manifold(e_best)) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = e_best->l;
- do {
- larr[larr_len] = BM_edge_vert_share_loop(l_iter, v);
-
- if (do_fill) {
- /* Only needed when filling...
- * Also, we never want to tag best edge,
- * that one won't change during split. See T44618. */
- if (larr[larr_len]->e == e_best) {
- BM_elem_flag_enable(larr[larr_len]->prev->e, BM_ELEM_TAG);
- }
- else {
- BM_elem_flag_enable(larr[larr_len]->e, BM_ELEM_TAG);
- }
- }
- larr_len++;
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
- else {
- /* looks like there are no split edges, we could just return/report-error? - Campbell */
- }
- }
-
- /* keep directly before edgesplit */
- if (do_fill) {
- fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm);
- }
-
- if (larr_len) {
- v_rip = BM_face_loop_separate_multi(bm, larr, larr_len);
- }
- else {
- v_rip = NULL;
- }
-
- if (v_rip) {
- BM_vert_select_set(bm, v_rip, true);
- }
- else {
- if (fill_uloop_pairs) MEM_freeN(fill_uloop_pairs);
- return OPERATOR_CANCELLED;
- }
- }
-
- {
- /* --- select which vert --- */
- BMVert *v_best = NULL;
- float l_corner_co[3];
-
- dist_sq = FLT_MAX;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- /* disable by default, re-enable winner at end */
- BM_vert_select_set(bm, v, false);
- BM_select_history_remove(bm, v);
-
- BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
-
- /* 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);
- if ((v_best == NULL) || (d < dist_sq)) {
- v_best = v;
- dist_sq = d;
- }
- }
- }
- }
-
- if (v_best) {
- BM_vert_select_set(bm, v_best, true);
- if (ese.ele) {
- BM_select_history_store(bm, v_best);
- }
- }
- }
-
- if (do_fill && fill_uloop_pairs) {
- edbm_tagged_loop_pairs_do_fill_faces(bm, fill_uloop_pairs);
- MEM_freeN(fill_uloop_pairs);
- }
-
-
- if (totvert_orig == bm->totvert) {
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ UnorderedLoopPair *fill_uloop_pairs = NULL;
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMIter iter, liter;
+ BMLoop *l;
+ BMEdge *e_best;
+ BMVert *v;
+ const int totvert_orig = bm->totvert;
+ int i;
+ float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]};
+ float dist_sq = FLT_MAX;
+ float d;
+ bool is_wire, is_manifold_region;
+
+ BMEditSelection ese;
+ int totboundary_edge = 0;
+
+ ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat);
+
+ /* find selected vert - same some time and check history first */
+ if (BM_select_history_active_get(bm, &ese) && ese.htype == BM_VERT) {
+ v = (BMVert *)ese.ele;
+ }
+ else {
+ ese.ele = NULL;
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT))
+ break;
+ }
+ }
+
+ /* (v == NULL) should be impossible */
+ if ((v == NULL) || (v->e == NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ is_wire = BM_vert_is_wire(v);
+ is_manifold_region = BM_vert_is_manifold_region(v);
+
+ e_best = NULL;
+
+ {
+ BMEdge *e;
+ /* find closest edge to mouse cursor */
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ /* consider wire as boundary for this purpose,
+ * otherwise we can't a face away from a wire edge */
+ totboundary_edge += (BM_edge_is_boundary(e) || BM_edge_is_wire(e));
+ 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);
+ if ((e_best == NULL) || (d < dist_sq)) {
+ dist_sq = d;
+ e_best = e;
+ }
+ }
+ }
+ }
+ }
+
+ if (e_best && e_best->l && (is_manifold_region == false)) {
+ /* Try to split off a non-manifold fan (when we have multiple disconnected fans) */
+ BMLoop *l_sep = e_best->l->v == v ? e_best->l : e_best->l->next;
+ BMVert *v_new;
+
+ BLI_assert(l_sep->v == v);
+ v_new = BM_face_loop_separate_multi_isolated(bm, l_sep);
+ BLI_assert(BM_vert_find_first_loop(v));
+
+ BM_vert_select_set(bm, v, false);
+ BM_select_history_remove(bm, v);
+
+ BM_vert_select_set(bm, v_new, true);
+ if (ese.ele) {
+ BM_select_history_store(bm, v_new);
+ }
+
+ if (do_fill) {
+ BM_edge_create(bm, v, v_new, NULL, BM_CREATE_NOP);
+ }
+
+ return OPERATOR_FINISHED;
+ }
+
+ /* if we are ripping a single vertex from 3 faces,
+ * then measure the distance to the face corner as well as the edge */
+ if (BM_vert_face_count_is_equal(v, 3) && BM_vert_edge_count_is_equal(v, 3)) {
+ BMEdge *e_all[3];
+ BMLoop *l_all[3];
+ int i1, i2;
+
+ BM_iter_as_array(bm, BM_EDGES_OF_VERT, v, (void **)e_all, 3);
+ BM_iter_as_array(bm, BM_LOOPS_OF_VERT, v, (void **)l_all, 3);
+
+ /* not do a loop similar to the one above, but test against loops */
+ for (i1 = 0; i1 < 3; i1++) {
+ /* consider wire as boundary for this purpose,
+ * otherwise we can't a face away from a wire edge */
+ 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);
+ if ((e_best == NULL) || (d < dist_sq)) {
+ dist_sq = d;
+
+ /* find the edge that is not in this loop */
+ e_best = NULL;
+ for (i2 = 0; i2 < 3; i2++) {
+ if (!BM_edge_in_loop(e_all[i2], l)) {
+ e_best = e_all[i2];
+ break;
+ }
+ }
+ BLI_assert(e_best != NULL);
+ }
+ }
+ }
+
+ /* should we go ahead with edge rip or do we need to do special case, split off vertex?:
+ * split off vertex if...
+ * - we cant find an edge - this means we are ripping a faces vert that is connected to other
+ * geometry only at the vertex.
+ * - the boundary edge total is greater than 2,
+ * in this case edge split _can_ work but we get far nicer results if we use this special case.
+ * - there are only 2 edges but we are a wire vert. */
+ if ((is_wire == false && totboundary_edge > 2) || (is_wire == true && totboundary_edge > 1)) {
+ BMVert **vout;
+ int vout_len;
+
+ BM_vert_select_set(bm, v, false);
+
+ bmesh_kernel_vert_separate(bm, v, &vout, &vout_len, true);
+
+ if (vout_len < 2) {
+ MEM_freeN(vout);
+ /* set selection back to avoid active-unselected vertex */
+ BM_vert_select_set(bm, v, true);
+ /* should never happen */
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ int vi_best = 0;
+
+ if (ese.ele) {
+ BM_select_history_remove(bm, ese.ele);
+ }
+
+ dist_sq = FLT_MAX;
+
+ /* in the loop below we find the best vertex to drag based on its connected geometry,
+ * either by its face corner, or connected edge (when no faces are attached) */
+ for (i = 0; i < vout_len; i++) {
+
+ if (BM_vert_is_wire(vout[i]) == false) {
+ /* find the best face corner */
+ BM_ITER_ELEM (l, &iter, vout[i], BM_LOOPS_OF_VERT) {
+ if (!BM_elem_flag_test(l->f, BM_ELEM_HIDDEN)) {
+ 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);
+
+ if (d < dist_sq) {
+ dist_sq = d;
+ vi_best = i;
+ }
+ }
+ }
+ }
+ else {
+ BMEdge *e;
+ /* a wire vert, find the best edge */
+ BM_ITER_ELEM (e, &iter, vout[i], BM_EDGES_OF_VERT) {
+ if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ 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);
+
+ if (d < dist_sq) {
+ dist_sq = d;
+ vi_best = i;
+ }
+ }
+ }
+ }
+ }
+
+ /* vout[0] == best
+ * vout[1] == glue
+ * vout[2+] == splice with glue (when vout_len > 2)
+ */
+ if (vi_best != 0) {
+ SWAP(BMVert *, vout[0], vout[vi_best]);
+ vi_best = 0;
+ }
+
+ /* select the vert from the best region */
+ v = vout[vi_best];
+ BM_vert_select_set(bm, v, true);
+
+ if (ese.ele) {
+ BM_select_history_store(bm, v);
+ }
+
+ /* splice all others back together */
+ if (vout_len > 2) {
+ for (i = 2; i < vout_len; i++) {
+ BM_vert_splice(bm, vout[1], vout[i]);
+ }
+ }
+
+ if (do_fill) {
+ /* match extrude vert-order */
+ BM_edge_create(bm, vout[1], vout[0], NULL, BM_CREATE_NOP);
+ }
+
+ MEM_freeN(vout);
+
+ return OPERATOR_FINISHED;
+ }
+ }
+
+ if (!e_best) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* *** Execute the split! *** */
+ /* unlike edge split, for single vertex split we only use the operator in one of the cases
+ * but both allocate fill */
+
+ {
+ BMVert *v_rip;
+ BMLoop *larr[2];
+ int larr_len = 0;
+
+ /* rip two adjacent edges */
+ if (BM_edge_is_boundary(e_best) || BM_vert_face_count_is_equal(v, 2)) {
+ /* Don't run the edge split operator in this case */
+
+ l = BM_edge_vert_share_loop(e_best->l, v);
+ larr[larr_len] = l;
+ larr_len++;
+
+ /* only tag for face-fill (we don't call the operator) */
+ if (BM_edge_is_boundary(e_best)) {
+ BM_elem_flag_enable(e_best, BM_ELEM_TAG);
+ }
+ else {
+ BM_elem_flag_enable(l->e, BM_ELEM_TAG);
+ BM_elem_flag_enable(l->prev->e, BM_ELEM_TAG);
+ }
+ }
+ else {
+ if (BM_edge_is_manifold(e_best)) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = e_best->l;
+ do {
+ larr[larr_len] = BM_edge_vert_share_loop(l_iter, v);
+
+ if (do_fill) {
+ /* Only needed when filling...
+ * Also, we never want to tag best edge,
+ * that one won't change during split. See T44618. */
+ if (larr[larr_len]->e == e_best) {
+ BM_elem_flag_enable(larr[larr_len]->prev->e, BM_ELEM_TAG);
+ }
+ else {
+ BM_elem_flag_enable(larr[larr_len]->e, BM_ELEM_TAG);
+ }
+ }
+ larr_len++;
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ else {
+ /* looks like there are no split edges, we could just return/report-error? - Campbell */
+ }
+ }
+
+ /* keep directly before edgesplit */
+ if (do_fill) {
+ fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm);
+ }
+
+ if (larr_len) {
+ v_rip = BM_face_loop_separate_multi(bm, larr, larr_len);
+ }
+ else {
+ v_rip = NULL;
+ }
+
+ if (v_rip) {
+ BM_vert_select_set(bm, v_rip, true);
+ }
+ else {
+ if (fill_uloop_pairs)
+ MEM_freeN(fill_uloop_pairs);
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ {
+ /* --- select which vert --- */
+ BMVert *v_best = NULL;
+ float l_corner_co[3];
+
+ dist_sq = FLT_MAX;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ /* disable by default, re-enable winner at end */
+ BM_vert_select_set(bm, v, false);
+ BM_select_history_remove(bm, v);
+
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+
+ /* 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);
+ if ((v_best == NULL) || (d < dist_sq)) {
+ v_best = v;
+ dist_sq = d;
+ }
+ }
+ }
+ }
+
+ if (v_best) {
+ BM_vert_select_set(bm, v_best, true);
+ if (ese.ele) {
+ BM_select_history_store(bm, v_best);
+ }
+ }
+ }
+
+ if (do_fill && fill_uloop_pairs) {
+ edbm_tagged_loop_pairs_do_fill_faces(bm, fill_uloop_pairs);
+ MEM_freeN(fill_uloop_pairs);
+ }
+
+ if (totvert_orig == bm->totvert) {
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
/**
@@ -877,247 +867,246 @@ 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);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMIter iter, eiter;
- BMLoop *l;
- BMEdge *e_best;
- BMVert *v;
- const int totedge_orig = bm->totedge;
- float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]};
-
- EdgeLoopPair *eloop_pairs;
-
- ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat);
-
- /* important this runs on the original selection, before tampering with tagging */
- eloop_pairs = edbm_ripsel_looptag_helper(bm);
-
- /* expand edge selection */
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BMEdge *e;
- bool all_manifold;
- int totedge_manifold; /* manifold, visible edges */
- int i;
-
- e_best = NULL;
- i = 0;
- totedge_manifold = 0;
- all_manifold = true;
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
-
- if (!BM_edge_is_wire(e) &&
- !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
- {
- /* important to check selection rather then tag here
- * else we get feedback loop */
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- e_best = e;
- i++;
- }
- totedge_manifold++;
- }
-
- /** #BM_vert_other_disk_edge has no hidden checks so don't check hidden here */
- if ((all_manifold == true) && (BM_edge_is_manifold(e) == false)) {
- all_manifold = false;
- }
- }
-
- /* single edge, extend */
- if (i == 1 && e_best->l) {
- /* note: if the case of 3 edges has one change in loop stepping,
- * if this becomes more involved we may be better off splitting
- * the 3 edge case into its own else-if branch */
- if ((totedge_manifold == 4 || totedge_manifold == 3) || (all_manifold == false)) {
- BMLoop *l_a = e_best->l;
- BMLoop *l_b = l_a->radial_next;
-
- /* 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_a : l_b;
-
- l = BM_loop_other_edge_loop(l, v);
- /* important edge is manifold else we can be attempting to split off a fan that don't budge,
- * not crashing but adds duplicate edge. */
- if (BM_edge_is_manifold(l->e)) {
- l = l->radial_next;
-
- if (totedge_manifold != 3)
- l = BM_loop_other_edge_loop(l, v);
-
- if (l) {
- BLI_assert(!BM_elem_flag_test(l->e, BM_ELEM_TAG));
- BM_elem_flag_enable(l->e, BM_ELEM_TAG);
- }
- }
- }
- else {
- e = BM_vert_other_disk_edge(v, e_best);
-
- if (e) {
- BLI_assert(!BM_elem_flag_test(e, BM_ELEM_TAG));
- BM_elem_flag_enable(e, BM_ELEM_TAG);
- }
- }
- }
- }
-
- /* keep directly before edgesplit */
- if (do_fill) {
- fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm);
- }
-
- BM_mesh_edgesplit(em->bm, true, true, true);
-
- /* note: the output of the bmesh operator is ignored, since we built
- * the contiguous loop pairs to split already, its possible that some
- * 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);
- MEM_freeN(eloop_pairs);
-
- /* deselect loose verts */
- BM_mesh_select_mode_clean_ex(bm, SCE_SELECT_EDGE);
-
- if (do_fill && fill_uloop_pairs) {
- edbm_tagged_loop_pairs_do_fill_faces(bm, fill_uloop_pairs);
- MEM_freeN(fill_uloop_pairs);
- }
-
- if (totedge_orig == bm->totedge) {
- return OPERATOR_CANCELLED;
- }
-
- BM_select_history_validate(bm);
-
- return OPERATOR_FINISHED;
+ UnorderedLoopPair *fill_uloop_pairs = NULL;
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMIter iter, eiter;
+ BMLoop *l;
+ BMEdge *e_best;
+ BMVert *v;
+ const int totedge_orig = bm->totedge;
+ float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]};
+
+ EdgeLoopPair *eloop_pairs;
+
+ ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat);
+
+ /* important this runs on the original selection, before tampering with tagging */
+ eloop_pairs = edbm_ripsel_looptag_helper(bm);
+
+ /* expand edge selection */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BMEdge *e;
+ bool all_manifold;
+ int totedge_manifold; /* manifold, visible edges */
+ int i;
+
+ e_best = NULL;
+ i = 0;
+ totedge_manifold = 0;
+ all_manifold = true;
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+
+ if (!BM_edge_is_wire(e) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ /* important to check selection rather then tag here
+ * else we get feedback loop */
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ e_best = e;
+ i++;
+ }
+ totedge_manifold++;
+ }
+
+ /** #BM_vert_other_disk_edge has no hidden checks so don't check hidden here */
+ if ((all_manifold == true) && (BM_edge_is_manifold(e) == false)) {
+ all_manifold = false;
+ }
+ }
+
+ /* single edge, extend */
+ if (i == 1 && e_best->l) {
+ /* note: if the case of 3 edges has one change in loop stepping,
+ * if this becomes more involved we may be better off splitting
+ * the 3 edge case into its own else-if branch */
+ if ((totedge_manifold == 4 || totedge_manifold == 3) || (all_manifold == false)) {
+ BMLoop *l_a = e_best->l;
+ BMLoop *l_b = l_a->radial_next;
+
+ /* 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_a :
+ l_b;
+
+ l = BM_loop_other_edge_loop(l, v);
+ /* important edge is manifold else we can be attempting to split off a fan that don't budge,
+ * not crashing but adds duplicate edge. */
+ if (BM_edge_is_manifold(l->e)) {
+ l = l->radial_next;
+
+ if (totedge_manifold != 3)
+ l = BM_loop_other_edge_loop(l, v);
+
+ if (l) {
+ BLI_assert(!BM_elem_flag_test(l->e, BM_ELEM_TAG));
+ BM_elem_flag_enable(l->e, BM_ELEM_TAG);
+ }
+ }
+ }
+ else {
+ e = BM_vert_other_disk_edge(v, e_best);
+
+ if (e) {
+ BLI_assert(!BM_elem_flag_test(e, BM_ELEM_TAG));
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ }
+ }
+ }
+ }
+
+ /* keep directly before edgesplit */
+ if (do_fill) {
+ fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm);
+ }
+
+ BM_mesh_edgesplit(em->bm, true, true, true);
+
+ /* note: the output of the bmesh operator is ignored, since we built
+ * the contiguous loop pairs to split already, its possible that some
+ * 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);
+ MEM_freeN(eloop_pairs);
+
+ /* deselect loose verts */
+ BM_mesh_select_mode_clean_ex(bm, SCE_SELECT_EDGE);
+
+ if (do_fill && fill_uloop_pairs) {
+ edbm_tagged_loop_pairs_do_fill_faces(bm, fill_uloop_pairs);
+ MEM_freeN(fill_uloop_pairs);
+ }
+
+ if (totedge_orig == bm->totedge) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BM_select_history_validate(bm);
+
+ return OPERATOR_FINISHED;
}
/* based on mouse cursor position, it defines how is being ripped */
static int edbm_rip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- const bool do_fill = RNA_boolean_get(op->ptr, "use_fill");
-
- bool no_vertex_selected = true;
- bool error_face_selected = true;
- bool error_disconnected_vertices = true;
- bool error_rip_failed = true;
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- BMesh *bm = em->bm;
- BMIter iter;
- BMEdge *e;
- const bool singlesel = (bm->totvertsel == 1 && bm->totedgesel == 0 && bm->totfacesel == 0);
- int ret;
-
- if (em->bm->totvertsel == 0) {
- continue;
- }
- no_vertex_selected = false;
-
- /* running in face mode hardly makes sense, so convert to region loop and rip */
- if (bm->totfacesel) {
- /* highly nifty but hard to support since the operator can fail and we're left
- * with modified selection */
- // WM_operator_name_call(C, "MESH_OT_region_to_loop", WM_OP_INVOKE_DEFAULT, NULL);
- continue;
- }
- error_face_selected = false;
-
- /* we could support this, but not for now */
- if ((bm->totvertsel > 1) && (bm->totedgesel == 0)) {
- continue;
- }
- error_disconnected_vertices = false;
-
- /* note on selection:
- * When calling edge split we operate on tagged edges rather then selected
- * this is important because the edges to operate on are extended by one,
- * but the selection is left alone.
- *
- * After calling edge split - the duplicated edges have the same selection state as the
- * original, so all we do is de-select the far side from the mouse and we have a
- * useful selection for grabbing.
- */
-
- /* BM_ELEM_SELECT --> BM_ELEM_TAG */
- 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));
- }
-
- /* split 2 main parts of this operator out into vertex and edge ripping */
- if (singlesel) {
- ret = edbm_rip_invoke__vert(C, event, obedit, do_fill);
- }
- else {
- ret = edbm_rip_invoke__edge(C, event, obedit, do_fill);
- }
-
- if (ret != OPERATOR_FINISHED) {
- continue;
- }
-
- BLI_assert(singlesel ? (bm->totvertsel > 0) : (bm->totedgesel > 0));
-
- if (bm->totvertsel == 0) {
- continue;
- }
- error_rip_failed = false;
-
- EDBM_update_generic(em, true, true);
- }
-
- MEM_freeN(objects);
-
- if (no_vertex_selected) {
- /* Ignore it. */
- return OPERATOR_CANCELLED;
- }
- else if (error_face_selected) {
- BKE_report(op->reports, RPT_ERROR, "Cannot rip selected faces");
- return OPERATOR_CANCELLED;
- }
- else if (error_disconnected_vertices) {
- BKE_report(op->reports, RPT_ERROR, "Cannot rip multiple disconnected vertices");
- return OPERATOR_CANCELLED;
- }
- else if (error_rip_failed) {
- BKE_report(op->reports, RPT_ERROR, "Rip failed");
- return OPERATOR_CANCELLED;
- }
- /* No errors, everything went fine. */
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ const bool do_fill = RNA_boolean_get(op->ptr, "use_fill");
+
+ bool no_vertex_selected = true;
+ bool error_face_selected = true;
+ bool error_disconnected_vertices = true;
+ bool error_rip_failed = true;
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMEdge *e;
+ const bool singlesel = (bm->totvertsel == 1 && bm->totedgesel == 0 && bm->totfacesel == 0);
+ int ret;
+
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
+ no_vertex_selected = false;
+
+ /* running in face mode hardly makes sense, so convert to region loop and rip */
+ if (bm->totfacesel) {
+ /* highly nifty but hard to support since the operator can fail and we're left
+ * with modified selection */
+ // WM_operator_name_call(C, "MESH_OT_region_to_loop", WM_OP_INVOKE_DEFAULT, NULL);
+ continue;
+ }
+ error_face_selected = false;
+
+ /* we could support this, but not for now */
+ if ((bm->totvertsel > 1) && (bm->totedgesel == 0)) {
+ continue;
+ }
+ error_disconnected_vertices = false;
+
+ /* note on selection:
+ * When calling edge split we operate on tagged edges rather then selected
+ * this is important because the edges to operate on are extended by one,
+ * but the selection is left alone.
+ *
+ * After calling edge split - the duplicated edges have the same selection state as the
+ * original, so all we do is de-select the far side from the mouse and we have a
+ * useful selection for grabbing.
+ */
+
+ /* BM_ELEM_SELECT --> BM_ELEM_TAG */
+ 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));
+ }
+
+ /* split 2 main parts of this operator out into vertex and edge ripping */
+ if (singlesel) {
+ ret = edbm_rip_invoke__vert(C, event, obedit, do_fill);
+ }
+ else {
+ ret = edbm_rip_invoke__edge(C, event, obedit, do_fill);
+ }
+
+ if (ret != OPERATOR_FINISHED) {
+ continue;
+ }
+
+ BLI_assert(singlesel ? (bm->totvertsel > 0) : (bm->totedgesel > 0));
+
+ if (bm->totvertsel == 0) {
+ continue;
+ }
+ error_rip_failed = false;
+
+ EDBM_update_generic(em, true, true);
+ }
+
+ MEM_freeN(objects);
+
+ if (no_vertex_selected) {
+ /* Ignore it. */
+ return OPERATOR_CANCELLED;
+ }
+ else if (error_face_selected) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot rip selected faces");
+ return OPERATOR_CANCELLED;
+ }
+ else if (error_disconnected_vertices) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot rip multiple disconnected vertices");
+ return OPERATOR_CANCELLED;
+ }
+ else if (error_rip_failed) {
+ BKE_report(op->reports, RPT_ERROR, "Rip failed");
+ return OPERATOR_CANCELLED;
+ }
+ /* No errors, everything went fine. */
+ return OPERATOR_FINISHED;
}
-
void MESH_OT_rip(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Rip";
- ot->idname = "MESH_OT_rip";
- ot->description = "Disconnect vertex or edges from connected geometry";
+ /* identifiers */
+ ot->name = "Rip";
+ ot->idname = "MESH_OT_rip";
+ ot->description = "Disconnect vertex or edges from connected geometry";
- /* api callbacks */
- ot->invoke = edbm_rip_invoke;
- ot->poll = EDBM_view3d_poll;
+ /* api callbacks */
+ ot->invoke = edbm_rip_invoke;
+ ot->poll = EDBM_view3d_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* to give to transform */
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
- RNA_def_boolean(ot->srna, "use_fill", false, "Fill", "Fill the ripped region");
+ /* to give to transform */
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
+ RNA_def_boolean(ot->srna, "use_fill", false, "Fill", "Fill the ripped region");
}
diff --git a/source/blender/editors/mesh/editmesh_rip_edge.c b/source/blender/editors/mesh/editmesh_rip_edge.c
index e449f96bc05..e2b77d8c83b 100644
--- a/source/blender/editors/mesh/editmesh_rip_edge.c
+++ b/source/blender/editors/mesh/editmesh_rip_edge.c
@@ -40,213 +40,211 @@
#include "bmesh.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
/* uses total number of selected edges around a vertex to choose how to extend */
#define USE_TRICKY_EXTEND
static int edbm_rip_edge_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- BMIter viter;
- BMVert *v;
- const float mval_fl[2] = { UNPACK2(event->mval) };
- float cent_sco[2];
- int cent_tot;
- bool changed = false;
-
- /* mouse direction to view center */
- float mval_dir[2];
-
- float projectMat[4][4];
-
- if (bm->totvertsel == 0)
- continue;
-
- ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat);
-
- zero_v2(cent_sco);
- cent_tot = 0;
-
- /* clear tags and calc screen center */
- BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_disable(v, BM_ELEM_TAG);
-
- 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);
-
- add_v2_v2(cent_sco, v_sco);
- cent_tot += 1;
- }
- }
- mul_v2_fl(cent_sco, 1.0f / (float)cent_tot);
-
- /* not essential, but gives more expected results with edge selection */
- if (bm->totedgesel) {
- /* angle against center can give odd result,
- * try re-position the center to the closest edge */
- BMIter eiter;
- BMEdge *e;
- float dist_sq_best = len_squared_v2v2(cent_sco, mval_fl);
-
- BM_ITER_MESH(e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- float e_sco[2][2];
- 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);
-
- 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);
- if (dist_sq_test < dist_sq_best) {
- dist_sq_best = dist_sq_test;
-
- /* we have a new screen center */
- copy_v2_v2(cent_sco, cent_sco_test);
- }
- }
- }
- }
-
- sub_v2_v2v2(mval_dir, mval_fl, cent_sco);
- normalize_v2(mval_dir);
-
- /* operate on selected verts */
- BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) {
- BMIter eiter;
- BMEdge *e;
- float v_sco[2];
-
- if (BM_elem_flag_test(v, BM_ELEM_SELECT) &&
- BM_elem_flag_test(v, BM_ELEM_TAG) == false)
- {
- /* Rules for */
- float angle_best = FLT_MAX;
- BMEdge *e_best = NULL;
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ BMIter viter;
+ BMVert *v;
+ const float mval_fl[2] = {UNPACK2(event->mval)};
+ float cent_sco[2];
+ int cent_tot;
+ bool changed = false;
+
+ /* mouse direction to view center */
+ float mval_dir[2];
+
+ float projectMat[4][4];
+
+ if (bm->totvertsel == 0)
+ continue;
+
+ ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat);
+
+ zero_v2(cent_sco);
+ cent_tot = 0;
+
+ /* clear tags and calc screen center */
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+
+ 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);
+
+ add_v2_v2(cent_sco, v_sco);
+ cent_tot += 1;
+ }
+ }
+ mul_v2_fl(cent_sco, 1.0f / (float)cent_tot);
+
+ /* not essential, but gives more expected results with edge selection */
+ if (bm->totedgesel) {
+ /* angle against center can give odd result,
+ * try re-position the center to the closest edge */
+ BMIter eiter;
+ BMEdge *e;
+ float dist_sq_best = len_squared_v2v2(cent_sco, mval_fl);
+
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ float e_sco[2][2];
+ 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);
+
+ 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);
+ if (dist_sq_test < dist_sq_best) {
+ dist_sq_best = dist_sq_test;
+
+ /* we have a new screen center */
+ copy_v2_v2(cent_sco, cent_sco_test);
+ }
+ }
+ }
+ }
+
+ sub_v2_v2v2(mval_dir, mval_fl, cent_sco);
+ normalize_v2(mval_dir);
+
+ /* operate on selected verts */
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ BMIter eiter;
+ BMEdge *e;
+ float v_sco[2];
+
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT) && BM_elem_flag_test(v, BM_ELEM_TAG) == false) {
+ /* Rules for */
+ float angle_best = FLT_MAX;
+ BMEdge *e_best = NULL;
#ifdef USE_TRICKY_EXTEND
- /* first check if we can select the edge to split based on selection-only */
- int tot_sel = 0, tot = 0;
-
- BM_ITER_ELEM(e, &eiter, v, BM_EDGES_OF_VERT) {
- if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- e_best = e;
- tot_sel += 1;
- }
- tot += 1;
- }
- }
- if (tot_sel != 1) {
- e_best = NULL;
- }
-
- /* only one edge selected, operate on that */
- if (e_best) {
- goto found_edge;
- }
- /* none selected, fall through and find one */
- else if (tot_sel == 0) {
- /* pass */
- }
- /* selection not 0 or 1, do nothing */
- else {
- goto found_edge;
- }
+ /* first check if we can select the edge to split based on selection-only */
+ int tot_sel = 0, tot = 0;
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ e_best = e;
+ tot_sel += 1;
+ }
+ tot += 1;
+ }
+ }
+ if (tot_sel != 1) {
+ e_best = NULL;
+ }
+
+ /* only one edge selected, operate on that */
+ if (e_best) {
+ goto found_edge;
+ }
+ /* none selected, fall through and find one */
+ else if (tot_sel == 0) {
+ /* pass */
+ }
+ /* selection not 0 or 1, do nothing */
+ else {
+ goto found_edge;
+ }
#endif
- ED_view3d_project_float_v2_m4(ar, v->co, v_sco, projectMat);
+ ED_view3d_project_float_v2_m4(ar, v->co, v_sco, projectMat);
- 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);
- float v_other_sco[2];
- float angle_test;
+ 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);
+ 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(ar, 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) {
- float v_dir[2];
+ /* avoid comparing with view-axis aligned edges (less than a pixel) */
+ if (len_squared_v2v2(v_sco, v_other_sco) > 1.0f) {
+ float v_dir[2];
- sub_v2_v2v2(v_dir, v_other_sco, v_sco);
- normalize_v2(v_dir);
+ sub_v2_v2v2(v_dir, v_other_sco, v_sco);
+ normalize_v2(v_dir);
- angle_test = angle_normalized_v2v2(mval_dir, v_dir);
+ angle_test = angle_normalized_v2v2(mval_dir, v_dir);
- if (angle_test < angle_best) {
- angle_best = angle_test;
- e_best = e;
- }
- }
- }
- }
+ if (angle_test < angle_best) {
+ angle_best = angle_test;
+ e_best = e;
+ }
+ }
+ }
+ }
#ifdef USE_TRICKY_EXTEND
-found_edge :
+ found_edge:
#endif
- if (e_best) {
- const bool e_select = BM_elem_flag_test_bool(e_best, BM_ELEM_SELECT);
- BMVert *v_new;
- BMEdge *e_new;
+ if (e_best) {
+ const bool e_select = BM_elem_flag_test_bool(e_best, BM_ELEM_SELECT);
+ BMVert *v_new;
+ BMEdge *e_new;
- v_new = BM_edge_split(bm, e_best, v, &e_new, 0.0f);
+ v_new = BM_edge_split(bm, e_best, v, &e_new, 0.0f);
- BM_vert_select_set(bm, v, false);
- BM_edge_select_set(bm, e_new, false);
+ BM_vert_select_set(bm, v, false);
+ BM_edge_select_set(bm, e_new, false);
- BM_vert_select_set(bm, v_new, true);
- if (e_select) {
- BM_edge_select_set(bm, e_best, true);
- }
- BM_elem_flag_enable(v_new, BM_ELEM_TAG); /* prevent further splitting */
+ BM_vert_select_set(bm, v_new, true);
+ if (e_select) {
+ BM_edge_select_set(bm, e_best, true);
+ }
+ BM_elem_flag_enable(v_new, BM_ELEM_TAG); /* prevent further splitting */
- changed = true;
- }
- }
- }
+ changed = true;
+ }
+ }
+ }
- if (changed) {
- BM_select_history_clear(bm);
+ if (changed) {
+ BM_select_history_clear(bm);
- BM_mesh_select_mode_flush(bm);
+ BM_mesh_select_mode_flush(bm);
- EDBM_update_generic(em, true, true);
- }
- }
+ EDBM_update_generic(em, true, true);
+ }
+ }
- MEM_freeN(objects);
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
void MESH_OT_rip_edge(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Extend Vertices";
- ot->idname = "MESH_OT_rip_edge";
- ot->description = "Extend vertices along the edge closest to the cursor";
+ /* identifiers */
+ ot->name = "Extend Vertices";
+ ot->idname = "MESH_OT_rip_edge";
+ ot->description = "Extend vertices along the edge closest to the cursor";
- /* api callbacks */
- ot->invoke = edbm_rip_edge_invoke;
- ot->poll = EDBM_view3d_poll;
+ /* api callbacks */
+ ot->invoke = edbm_rip_edge_invoke;
+ ot->poll = EDBM_view3d_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* to give to transform */
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
+ /* to give to transform */
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
}
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 8b75b511319..94886266d24 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -67,7 +67,7 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
/* use bmesh operator flags for a few operators */
#define BMO_ELE_TAG 1
@@ -77,94 +77,92 @@
* \{ */
void EDBM_select_mirrored(
- BMEditMesh *em, const int axis, const bool extend,
- int *r_totmirr, int *r_totfail)
+ BMEditMesh *em, const int axis, const bool extend, int *r_totmirr, int *r_totfail)
{
- Mesh *me = (Mesh *)em->ob->data;
- BMesh *bm = em->bm;
- BMIter iter;
- int totmirr = 0;
- int totfail = 0;
- bool use_topology = (me && (me->editflag & ME_EDIT_MIRROR_TOPO));
-
- *r_totmirr = *r_totfail = 0;
-
- /* select -> tag */
- if (bm->selectmode & SCE_SELECT_VERTEX) {
- BMVert *v;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_set(v, BM_ELEM_TAG, BM_elem_flag_test(v, BM_ELEM_SELECT));
- }
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- BMEdge *e;
- 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));
- }
- }
- else {
- BMFace *f;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- BM_elem_flag_set(f, BM_ELEM_TAG, BM_elem_flag_test(f, BM_ELEM_SELECT));
- }
- }
-
- EDBM_verts_mirror_cache_begin(em, axis, true, true, use_topology);
-
- if (!extend)
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
-
-
- if (bm->selectmode & SCE_SELECT_VERTEX) {
- BMVert *v;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN) && BM_elem_flag_test(v, BM_ELEM_TAG)) {
- BMVert *v_mirr = EDBM_verts_mirror_get(em, v);
- if (v_mirr && !BM_elem_flag_test(v_mirr, BM_ELEM_HIDDEN)) {
- BM_vert_select_set(bm, v_mirr, true);
- totmirr++;
- }
- else {
- totfail++;
- }
- }
- }
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- BMEdge *e;
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN) && BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BMEdge *e_mirr = EDBM_verts_mirror_get_edge(em, e);
- if (e_mirr && !BM_elem_flag_test(e_mirr, BM_ELEM_HIDDEN)) {
- BM_edge_select_set(bm, e_mirr, true);
- totmirr++;
- }
- else {
- totfail++;
- }
- }
- }
- }
- else {
- BMFace *f;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN) && BM_elem_flag_test(f, BM_ELEM_TAG)) {
- BMFace *f_mirr = EDBM_verts_mirror_get_face(em, f);
- if (f_mirr && !BM_elem_flag_test(f_mirr, BM_ELEM_HIDDEN)) {
- BM_face_select_set(bm, f_mirr, true);
- totmirr++;
- }
- else {
- totfail++;
- }
- }
- }
- }
-
- EDBM_verts_mirror_cache_end(em);
-
- *r_totmirr = totmirr;
- *r_totfail = totfail;
+ Mesh *me = (Mesh *)em->ob->data;
+ BMesh *bm = em->bm;
+ BMIter iter;
+ int totmirr = 0;
+ int totfail = 0;
+ bool use_topology = (me && (me->editflag & ME_EDIT_MIRROR_TOPO));
+
+ *r_totmirr = *r_totfail = 0;
+
+ /* select -> tag */
+ if (bm->selectmode & SCE_SELECT_VERTEX) {
+ BMVert *v;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_set(v, BM_ELEM_TAG, BM_elem_flag_test(v, BM_ELEM_SELECT));
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ BMEdge *e;
+ 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));
+ }
+ }
+ else {
+ BMFace *f;
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_set(f, BM_ELEM_TAG, BM_elem_flag_test(f, BM_ELEM_SELECT));
+ }
+ }
+
+ EDBM_verts_mirror_cache_begin(em, axis, true, true, use_topology);
+
+ if (!extend)
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+
+ if (bm->selectmode & SCE_SELECT_VERTEX) {
+ BMVert *v;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN) && BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ BMVert *v_mirr = EDBM_verts_mirror_get(em, v);
+ if (v_mirr && !BM_elem_flag_test(v_mirr, BM_ELEM_HIDDEN)) {
+ BM_vert_select_set(bm, v_mirr, true);
+ totmirr++;
+ }
+ else {
+ totfail++;
+ }
+ }
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ BMEdge *e;
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN) && BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BMEdge *e_mirr = EDBM_verts_mirror_get_edge(em, e);
+ if (e_mirr && !BM_elem_flag_test(e_mirr, BM_ELEM_HIDDEN)) {
+ BM_edge_select_set(bm, e_mirr, true);
+ totmirr++;
+ }
+ else {
+ totfail++;
+ }
+ }
+ }
+ }
+ else {
+ BMFace *f;
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN) && BM_elem_flag_test(f, BM_ELEM_TAG)) {
+ BMFace *f_mirr = EDBM_verts_mirror_get_face(em, f);
+ if (f_mirr && !BM_elem_flag_test(f_mirr, BM_ELEM_HIDDEN)) {
+ BM_face_select_set(bm, f_mirr, true);
+ totmirr++;
+ }
+ else {
+ totfail++;
+ }
+ }
+ }
+ }
+
+ EDBM_verts_mirror_cache_end(em);
+
+ *r_totmirr = totmirr;
+ *r_totfail = totfail;
}
/** \} */
@@ -177,17 +175,18 @@ void EDBM_select_mirrored(
void EDBM_automerge(Scene *scene, Object *obedit, bool update, const char hflag)
{
- bool ok;
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- ok = BMO_op_callf(
- em->bm, BMO_FLAG_DEFAULTS,
- "automerge verts=%hv dist=%f",
- hflag, scene->toolsettings->doublimit);
-
- if (LIKELY(ok) && update) {
- EDBM_update_generic(em, true, true);
- }
+ bool ok;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ ok = BMO_op_callf(em->bm,
+ BMO_FLAG_DEFAULTS,
+ "automerge verts=%hv dist=%f",
+ hflag,
+ scene->toolsettings->doublimit);
+
+ if (LIKELY(ok) && update) {
+ EDBM_update_generic(em, true, true);
+ }
}
/** \} */
@@ -204,173 +203,175 @@ static BLI_bitmap *selbuf = NULL;
static BLI_bitmap *edbm_backbuf_alloc(const int size)
{
- return BLI_BITMAP_NEW(size, "selbuf");
+ return BLI_BITMAP_NEW(size, "selbuf");
}
/* reads rect, and builds selection array for quick lookup */
/* returns if all is OK */
-bool EDBM_backbuf_border_init(
- ViewContext *vc, short xmin,
- short ymin, short xmax, short ymax)
+bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
{
- uint *buf, *dr, buf_len;
-
- if (vc->obedit == NULL || XRAY_FLAG_ENABLED(vc->v3d)) {
- return false;
- }
-
- buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len);
- if ((buf == NULL) || (bm_vertoffs == 0)) {
- return false;
- }
-
- dr = buf;
-
- /* build selection lookup */
- selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
-
- while (buf_len--) {
- if (*dr > 0 && *dr <= bm_vertoffs) {
- BLI_BITMAP_ENABLE(selbuf, *dr);
- }
- dr++;
- }
- MEM_freeN(buf);
- return true;
+ uint *buf, *dr, buf_len;
+
+ if (vc->obedit == NULL || XRAY_FLAG_ENABLED(vc->v3d)) {
+ return false;
+ }
+
+ buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len);
+ if ((buf == NULL) || (bm_vertoffs == 0)) {
+ return false;
+ }
+
+ dr = buf;
+
+ /* build selection lookup */
+ selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
+
+ while (buf_len--) {
+ if (*dr > 0 && *dr <= bm_vertoffs) {
+ BLI_BITMAP_ENABLE(selbuf, *dr);
+ }
+ dr++;
+ }
+ MEM_freeN(buf);
+ return true;
}
bool EDBM_backbuf_check(unsigned int index)
{
- /* odd logic, if selbuf is NULL we assume no zbuf-selection is enabled
- * and just ignore the depth buffer, this is error prone since its possible
- * code doesn't set the depth buffer by accident, but leave for now. - Campbell */
- if (selbuf == NULL)
- return true;
+ /* odd logic, if selbuf is NULL we assume no zbuf-selection is enabled
+ * and just ignore the depth buffer, this is error prone since its possible
+ * code doesn't set the depth buffer by accident, but leave for now. - Campbell */
+ if (selbuf == NULL)
+ return true;
- if (index > 0 && index <= bm_vertoffs)
- return BLI_BITMAP_TEST_BOOL(selbuf, index);
+ if (index > 0 && index <= bm_vertoffs)
+ return BLI_BITMAP_TEST_BOOL(selbuf, index);
- return false;
+ return false;
}
void EDBM_backbuf_free(void)
{
- if (selbuf) MEM_freeN(selbuf);
- selbuf = NULL;
+ if (selbuf)
+ MEM_freeN(selbuf);
+ selbuf = NULL;
}
struct LassoMaskData {
- unsigned int *px;
- int width;
+ unsigned int *px;
+ int width;
};
static void edbm_mask_lasso_px_cb(int x, int x_end, int y, void *user_data)
{
- struct LassoMaskData *data = user_data;
- unsigned int *px = &data->px[(y * data->width) + x];
- do {
- *px = true;
- px++;
- } while (++x != x_end);
+ struct LassoMaskData *data = user_data;
+ unsigned int *px = &data->px[(y * data->width) + x];
+ do {
+ *px = true;
+ px++;
+ } while (++x != x_end);
}
-
/* mcords is a polygon mask
* - grab backbuffer,
* - draw with black in backbuffer,
* - grab again and compare
* returns 'OK'
*/
-bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
+bool EDBM_backbuf_border_mask_init(ViewContext *vc,
+ const int mcords[][2],
+ short tot,
+ short xmin,
+ short ymin,
+ short xmax,
+ short ymax)
{
- uint *buf, *dr, *dr_mask, *dr_mask_arr, buf_len;
- struct LassoMaskData lasso_mask_data;
-
- /* method in use for face selecting too */
- if (vc->obedit == NULL) {
- if (!BKE_paint_select_elem_test(vc->obact)) {
- return false;
- }
- }
- else if (XRAY_FLAG_ENABLED(vc->v3d)) {
- return false;
- }
-
- buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len);
- if ((buf == NULL) || (bm_vertoffs == 0)) {
- return false;
- }
-
- dr = buf;
-
- dr_mask = dr_mask_arr = MEM_callocN(sizeof(*dr_mask) * buf_len, __func__);
- lasso_mask_data.px = dr_mask;
- lasso_mask_data.width = (xmax - xmin) + 1;
-
- BLI_bitmap_draw_2d_poly_v2i_n(
- xmin, ymin, xmax + 1, ymax + 1,
- mcords, tot,
- edbm_mask_lasso_px_cb, &lasso_mask_data);
-
- /* build selection lookup */
- selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
-
- while (buf_len--) {
- if (*dr > 0 && *dr <= bm_vertoffs && *dr_mask == true) {
- BLI_BITMAP_ENABLE(selbuf, *dr);
- }
- dr++; dr_mask++;
- }
- MEM_freeN(buf);
- MEM_freeN(dr_mask_arr);
-
- return true;
+ uint *buf, *dr, *dr_mask, *dr_mask_arr, buf_len;
+ struct LassoMaskData lasso_mask_data;
+
+ /* method in use for face selecting too */
+ if (vc->obedit == NULL) {
+ if (!BKE_paint_select_elem_test(vc->obact)) {
+ return false;
+ }
+ }
+ else if (XRAY_FLAG_ENABLED(vc->v3d)) {
+ return false;
+ }
+
+ buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len);
+ if ((buf == NULL) || (bm_vertoffs == 0)) {
+ return false;
+ }
+
+ dr = buf;
+
+ dr_mask = dr_mask_arr = MEM_callocN(sizeof(*dr_mask) * buf_len, __func__);
+ lasso_mask_data.px = dr_mask;
+ lasso_mask_data.width = (xmax - xmin) + 1;
+
+ BLI_bitmap_draw_2d_poly_v2i_n(
+ xmin, ymin, xmax + 1, ymax + 1, mcords, tot, edbm_mask_lasso_px_cb, &lasso_mask_data);
+
+ /* build selection lookup */
+ selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
+
+ while (buf_len--) {
+ if (*dr > 0 && *dr <= bm_vertoffs && *dr_mask == true) {
+ BLI_BITMAP_ENABLE(selbuf, *dr);
+ }
+ dr++;
+ dr_mask++;
+ }
+ MEM_freeN(buf);
+ MEM_freeN(dr_mask_arr);
+
+ return true;
}
/* circle shaped sample area */
-bool EDBM_backbuf_circle_init(
- ViewContext *vc,
- short xs, short ys, short rads)
+bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads)
{
- uint *buf, *dr;
- short xmin, ymin, xmax, ymax, xc, yc;
- int radsq;
-
- /* method in use for face selecting too */
- if (vc->obedit == NULL) {
- if (!BKE_paint_select_elem_test(vc->obact)) {
- return false;
- }
- }
- else if (XRAY_FLAG_ENABLED(vc->v3d)) {
- return false;
- }
-
- xmin = xs - rads; xmax = xs + rads;
- ymin = ys - rads; ymax = ys + rads;
- buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, NULL);
- if ((buf == NULL) || (bm_vertoffs == 0)) {
- return false;
- }
-
- dr = buf;
-
- /* build selection lookup */
- selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
- radsq = rads * rads;
- for (yc = -rads; yc <= rads; yc++) {
- for (xc = -rads; xc <= rads; xc++, dr++) {
- if (xc * xc + yc * yc < radsq) {
- if (*dr > 0 && *dr <= bm_vertoffs) {
- BLI_BITMAP_ENABLE(selbuf, *dr);
- }
- }
- }
- }
-
- MEM_freeN(buf);
- return true;
-
+ uint *buf, *dr;
+ short xmin, ymin, xmax, ymax, xc, yc;
+ int radsq;
+
+ /* method in use for face selecting too */
+ if (vc->obedit == NULL) {
+ if (!BKE_paint_select_elem_test(vc->obact)) {
+ return false;
+ }
+ }
+ else if (XRAY_FLAG_ENABLED(vc->v3d)) {
+ return false;
+ }
+
+ xmin = xs - rads;
+ xmax = xs + rads;
+ ymin = ys - rads;
+ ymax = ys + rads;
+ buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, NULL);
+ if ((buf == NULL) || (bm_vertoffs == 0)) {
+ return false;
+ }
+
+ dr = buf;
+
+ /* build selection lookup */
+ selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
+ radsq = rads * rads;
+ for (yc = -rads; yc <= rads; yc++) {
+ for (xc = -rads; xc <= rads; xc++, dr++) {
+ if (xc * xc + yc * yc < radsq) {
+ if (*dr > 0 && *dr <= bm_vertoffs) {
+ BLI_BITMAP_ENABLE(selbuf, *dr);
+ }
+ }
+ }
+ }
+
+ MEM_freeN(buf);
+ return true;
}
/** \} */
@@ -387,66 +388,69 @@ bool EDBM_backbuf_circle_init(
* \{ */
#define FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, select_mode_required) \
- short select_mode = select_mode_required; \
- bool fake_select_mode = (select_mode & (vc)->scene->toolsettings->selectmode) == 0; \
- if (fake_select_mode) { \
- (vc)->v3d->flag |= V3D_INVALID_BACKBUF; \
- } ((void)0)
+ short select_mode = select_mode_required; \
+ bool fake_select_mode = (select_mode & (vc)->scene->toolsettings->selectmode) == 0; \
+ if (fake_select_mode) { \
+ (vc)->v3d->flag |= V3D_INVALID_BACKBUF; \
+ } \
+ ((void)0)
#define FAKE_SELECT_MODE_END(vc, fake_select_mode) \
- if (fake_select_mode) { \
- (vc)->v3d->flag |= V3D_INVALID_BACKBUF; \
- } ((void)0)
+ if (fake_select_mode) { \
+ (vc)->v3d->flag |= V3D_INVALID_BACKBUF; \
+ } \
+ ((void)0)
#define FIND_NEAR_SELECT_BIAS 5
#define FIND_NEAR_CYCLE_THRESHOLD_MIN 3
struct NearestVertUserData_Hit {
- float dist;
- float dist_bias;
- int index;
- BMVert *vert;
+ float dist;
+ float dist_bias;
+ int index;
+ BMVert *vert;
};
struct NearestVertUserData {
- float mval_fl[2];
- bool use_select_bias;
- bool use_cycle;
- int cycle_index_prev;
+ float mval_fl[2];
+ bool use_select_bias;
+ bool use_cycle;
+ int cycle_index_prev;
- struct NearestVertUserData_Hit hit;
- struct NearestVertUserData_Hit hit_cycle;
+ struct NearestVertUserData_Hit hit;
+ struct NearestVertUserData_Hit hit_cycle;
};
-static void findnearestvert__doClosest(void *userData, BMVert *eve, const float screen_co[2], int index)
+static void findnearestvert__doClosest(void *userData,
+ BMVert *eve,
+ const float screen_co[2],
+ int index)
{
- struct NearestVertUserData *data = userData;
- float dist_test, dist_test_bias;
-
- dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
-
- if (data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- dist_test_bias += FIND_NEAR_SELECT_BIAS;
- }
-
- if (dist_test_bias < data->hit.dist_bias) {
- data->hit.dist_bias = dist_test_bias;
- data->hit.dist = dist_test;
- data->hit.index = index;
- data->hit.vert = eve;
- }
-
- if (data->use_cycle) {
- if ((data->hit_cycle.vert == NULL) &&
- (index > data->cycle_index_prev) &&
- (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
- {
- data->hit_cycle.dist_bias = dist_test_bias;
- data->hit_cycle.dist = dist_test;
- data->hit_cycle.index = index;
- data->hit_cycle.vert = eve;
- }
- }
+ struct NearestVertUserData *data = userData;
+ float dist_test, dist_test_bias;
+
+ dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
+
+ if (data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ dist_test_bias += FIND_NEAR_SELECT_BIAS;
+ }
+
+ if (dist_test_bias < data->hit.dist_bias) {
+ data->hit.dist_bias = dist_test_bias;
+ data->hit.dist = dist_test;
+ data->hit.index = index;
+ data->hit.vert = eve;
+ }
+
+ if (data->use_cycle) {
+ if ((data->hit_cycle.vert == NULL) && (index > data->cycle_index_prev) &&
+ (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN)) {
+ data->hit_cycle.dist_bias = dist_test_bias;
+ data->hit_cycle.dist = dist_test;
+ data->hit_cycle.index = index;
+ data->hit_cycle.vert = eve;
+ }
+ }
}
/**
@@ -458,618 +462,632 @@ static void findnearestvert__doClosest(void *userData, BMVert *eve, const float
* - When false, unselected vertices are given the bias.
* \param use_cycle: Cycle over elements within #FIND_NEAR_CYCLE_THRESHOLD_MIN in order of index.
*/
-BMVert *EDBM_vert_find_nearest_ex(
- ViewContext *vc, float *r_dist,
- const bool use_select_bias, bool use_cycle)
+BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
+ float *r_dist,
+ const bool use_select_bias,
+ bool use_cycle)
{
- BMesh *bm = vc->em->bm;
-
- if (!XRAY_FLAG_ENABLED(vc->v3d)) {
- uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
- unsigned int index;
- BMVert *eve;
-
- /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
- {
- FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX);
- ED_view3d_select_id_validate_with_select_mode(vc, select_mode);
-
- index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_wireoffs, 0xFFFFFF, &dist_px);
- eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL;
-
- FAKE_SELECT_MODE_END(vc, fake_select_mode);
- }
-
- if (eve) {
- if (dist_px < *r_dist) {
- *r_dist = dist_px;
- return eve;
- }
- }
- return NULL;
- }
- else {
- struct NearestVertUserData data = {{0}};
- const struct NearestVertUserData_Hit *hit;
- const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
-
- static int prev_select_index = 0;
- static const BMVert *prev_select_elem = NULL;
-
- if ((use_cycle == false) ||
- (prev_select_elem && (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index))))
- {
- prev_select_index = 0;
- prev_select_elem = NULL;
- }
-
- data.mval_fl[0] = vc->mval[0];
- data.mval_fl[1] = vc->mval[1];
- data.use_select_bias = use_select_bias;
- data.use_cycle = use_cycle;
- data.hit.dist = data.hit_cycle.dist = \
- data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
- data.cycle_index_prev = prev_select_index;
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag);
-
- hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit;
- *r_dist = hit->dist;
-
- prev_select_elem = hit->vert;
- prev_select_index = hit->index;
-
- return hit->vert;
- }
+ BMesh *bm = vc->em->bm;
+
+ if (!XRAY_FLAG_ENABLED(vc->v3d)) {
+ uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
+ unsigned int index;
+ BMVert *eve;
+
+ /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
+ {
+ FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX)
+ ;
+ ED_view3d_select_id_validate_with_select_mode(vc, select_mode);
+
+ index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_wireoffs, 0xFFFFFF, &dist_px);
+ eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL;
+
+ FAKE_SELECT_MODE_END(vc, fake_select_mode);
+ }
+
+ if (eve) {
+ if (dist_px < *r_dist) {
+ *r_dist = dist_px;
+ return eve;
+ }
+ }
+ return NULL;
+ }
+ else {
+ struct NearestVertUserData data = {{0}};
+ const struct NearestVertUserData_Hit *hit;
+ const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
+
+ static int prev_select_index = 0;
+ static const BMVert *prev_select_elem = NULL;
+
+ if ((use_cycle == false) ||
+ (prev_select_elem &&
+ (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index)))) {
+ prev_select_index = 0;
+ prev_select_elem = NULL;
+ }
+
+ data.mval_fl[0] = vc->mval[0];
+ data.mval_fl[1] = vc->mval[1];
+ data.use_select_bias = use_select_bias;
+ data.use_cycle = use_cycle;
+ data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
+ data.cycle_index_prev = prev_select_index;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag);
+
+ hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit;
+ *r_dist = hit->dist;
+
+ prev_select_elem = hit->vert;
+ prev_select_index = hit->index;
+
+ return hit->vert;
+ }
}
BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist)
{
- return EDBM_vert_find_nearest_ex(vc, r_dist, false, false);
+ return EDBM_vert_find_nearest_ex(vc, r_dist, false, false);
}
/* find the distance to the edge we already have */
struct NearestEdgeUserData_ZBuf {
- float mval_fl[2];
- float dist;
- const BMEdge *edge_test;
+ float mval_fl[2];
+ float dist;
+ const BMEdge *edge_test;
};
-static void find_nearest_edge_center__doZBuf(
- void *userData, BMEdge *eed,
- const float screen_co_a[2], const float screen_co_b[2],
- int UNUSED(index))
+static void find_nearest_edge_center__doZBuf(void *userData,
+ BMEdge *eed,
+ const float screen_co_a[2],
+ const float screen_co_b[2],
+ int UNUSED(index))
{
- struct NearestEdgeUserData_ZBuf *data = userData;
+ struct NearestEdgeUserData_ZBuf *data = userData;
- if (eed == data->edge_test) {
- float dist_test;
- float screen_co_mid[2];
+ if (eed == data->edge_test) {
+ float dist_test;
+ float screen_co_mid[2];
- mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
- dist_test = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
+ mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
+ dist_test = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
- if (dist_test < data->dist) {
- data->dist = dist_test;
- }
- }
+ if (dist_test < data->dist) {
+ data->dist = dist_test;
+ }
+ }
}
struct NearestEdgeUserData_Hit {
- float dist;
- float dist_bias;
- int index;
- BMEdge *edge;
-
- /* edges only, un-biased manhatten distance to which ever edge we pick
- * (not used for choosing) */
- float dist_center;
+ float dist;
+ float dist_bias;
+ int index;
+ BMEdge *edge;
+
+ /* edges only, un-biased manhatten distance to which ever edge we pick
+ * (not used for choosing) */
+ float dist_center;
};
struct NearestEdgeUserData {
- ViewContext vc;
- float mval_fl[2];
- bool use_select_bias;
- bool use_cycle;
- int cycle_index_prev;
-
- struct NearestEdgeUserData_Hit hit;
- struct NearestEdgeUserData_Hit hit_cycle;
+ ViewContext vc;
+ float mval_fl[2];
+ bool use_select_bias;
+ bool use_cycle;
+ int cycle_index_prev;
+
+ struct NearestEdgeUserData_Hit hit;
+ struct NearestEdgeUserData_Hit hit_cycle;
};
/* note; uses v3d, so needs active 3d window */
static void find_nearest_edge__doClosest(
- void *userData, BMEdge *eed,
- const float screen_co_a[2], const float screen_co_b[2],
- int index)
+ void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
{
- struct NearestEdgeUserData *data = userData;
- float dist_test, dist_test_bias;
-
- float fac = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b);
- float screen_co[2];
-
- if (fac <= 0.0f) {
- fac = 0.0f;
- copy_v2_v2(screen_co, screen_co_a);
- }
- else if (fac >= 1.0f) {
- fac = 1.0f;
- copy_v2_v2(screen_co, screen_co_b);
- }
- else {
- interp_v2_v2v2(screen_co, screen_co_a, screen_co_b, fac);
- }
-
- dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
-
- if (data->use_select_bias && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- dist_test_bias += FIND_NEAR_SELECT_BIAS;
- }
-
- if (data->vc.rv3d->rflag & RV3D_CLIPPING) {
- float vec[3];
-
- interp_v3_v3v3(vec, eed->v1->co, eed->v2->co, fac);
- if (ED_view3d_clipping_test(data->vc.rv3d, vec, true)) {
- return;
- }
- }
-
- if (dist_test_bias < data->hit.dist_bias) {
- float screen_co_mid[2];
-
- data->hit.dist_bias = dist_test_bias;
- data->hit.dist = dist_test;
- data->hit.index = index;
- data->hit.edge = eed;
-
- mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
- data->hit.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
- }
-
- if (data->use_cycle) {
- if ((data->hit_cycle.edge == NULL) &&
- (index > data->cycle_index_prev) &&
- (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
- {
- float screen_co_mid[2];
-
- data->hit_cycle.dist_bias = dist_test_bias;
- data->hit_cycle.dist = dist_test;
- data->hit_cycle.index = index;
- data->hit_cycle.edge = eed;
-
- mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
- data->hit_cycle.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
- }
- }
+ struct NearestEdgeUserData *data = userData;
+ float dist_test, dist_test_bias;
+
+ float fac = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b);
+ float screen_co[2];
+
+ if (fac <= 0.0f) {
+ fac = 0.0f;
+ copy_v2_v2(screen_co, screen_co_a);
+ }
+ else if (fac >= 1.0f) {
+ fac = 1.0f;
+ copy_v2_v2(screen_co, screen_co_b);
+ }
+ else {
+ interp_v2_v2v2(screen_co, screen_co_a, screen_co_b, fac);
+ }
+
+ dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
+
+ if (data->use_select_bias && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ dist_test_bias += FIND_NEAR_SELECT_BIAS;
+ }
+
+ if (data->vc.rv3d->rflag & RV3D_CLIPPING) {
+ float vec[3];
+
+ interp_v3_v3v3(vec, eed->v1->co, eed->v2->co, fac);
+ if (ED_view3d_clipping_test(data->vc.rv3d, vec, true)) {
+ return;
+ }
+ }
+
+ if (dist_test_bias < data->hit.dist_bias) {
+ float screen_co_mid[2];
+
+ data->hit.dist_bias = dist_test_bias;
+ data->hit.dist = dist_test;
+ data->hit.index = index;
+ data->hit.edge = eed;
+
+ mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
+ data->hit.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
+ }
+
+ if (data->use_cycle) {
+ if ((data->hit_cycle.edge == NULL) && (index > data->cycle_index_prev) &&
+ (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN)) {
+ float screen_co_mid[2];
+
+ data->hit_cycle.dist_bias = dist_test_bias;
+ data->hit_cycle.dist = dist_test;
+ data->hit_cycle.index = index;
+ data->hit_cycle.edge = eed;
+
+ mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
+ data->hit_cycle.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
+ }
+ }
}
-BMEdge *EDBM_edge_find_nearest_ex(
- ViewContext *vc, float *r_dist,
- float *r_dist_center,
- const bool use_select_bias, const bool use_cycle,
- BMEdge **r_eed_zbuf)
+BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
+ float *r_dist,
+ float *r_dist_center,
+ const bool use_select_bias,
+ const bool use_cycle,
+ BMEdge **r_eed_zbuf)
{
- BMesh *bm = vc->em->bm;
-
- if (!XRAY_FLAG_ENABLED(vc->v3d)) {
- uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
- unsigned int index;
- BMEdge *eed;
-
- /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
- {
- FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_EDGE);
- ED_view3d_select_id_validate_with_select_mode(vc, select_mode);
-
- index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_solidoffs, bm_wireoffs, &dist_px);
- eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL;
-
- FAKE_SELECT_MODE_END(vc, fake_select_mode);
- }
-
- if (r_eed_zbuf) {
- *r_eed_zbuf = eed;
- }
-
- /* exception for faces (verts don't need this) */
- if (r_dist_center && eed) {
- struct NearestEdgeUserData_ZBuf data;
-
- data.mval_fl[0] = vc->mval[0];
- data.mval_fl[1] = vc->mval[1];
- data.dist = FLT_MAX;
- data.edge_test = eed;
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
-
- mesh_foreachScreenEdge(vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
-
- *r_dist_center = data.dist;
- }
- /* end exception */
-
- if (eed) {
- if (dist_px < *r_dist) {
- *r_dist = dist_px;
- return eed;
- }
- }
- return NULL;
- }
- else {
- struct NearestEdgeUserData data = {{0}};
- const struct NearestEdgeUserData_Hit *hit;
- /* interpolate along the edge before doing a clipping plane test */
- const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT & ~V3D_PROJ_TEST_CLIP_BB;
-
- static int prev_select_index = 0;
- static const BMEdge *prev_select_elem = NULL;
-
- if ((use_cycle == false) ||
- (prev_select_elem && (prev_select_elem != BM_edge_at_index_find_or_table(bm, prev_select_index))))
- {
- prev_select_index = 0;
- prev_select_elem = NULL;
- }
-
- data.vc = *vc;
- data.mval_fl[0] = vc->mval[0];
- data.mval_fl[1] = vc->mval[1];
- data.use_select_bias = use_select_bias;
- data.use_cycle = use_cycle;
- data.hit.dist = data.hit_cycle.dist = \
- data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
- data.cycle_index_prev = prev_select_index;
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag);
-
- hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit;
- *r_dist = hit->dist;
- if (r_dist_center) {
- *r_dist_center = hit->dist_center;
- }
-
- prev_select_elem = hit->edge;
- prev_select_index = hit->index;
-
- return hit->edge;
- }
+ BMesh *bm = vc->em->bm;
+
+ if (!XRAY_FLAG_ENABLED(vc->v3d)) {
+ uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
+ unsigned int index;
+ BMEdge *eed;
+
+ /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
+ {
+ FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_EDGE)
+ ;
+ ED_view3d_select_id_validate_with_select_mode(vc, select_mode);
+
+ index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_solidoffs, bm_wireoffs, &dist_px);
+ eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL;
+
+ FAKE_SELECT_MODE_END(vc, fake_select_mode);
+ }
+
+ if (r_eed_zbuf) {
+ *r_eed_zbuf = eed;
+ }
+
+ /* exception for faces (verts don't need this) */
+ if (r_dist_center && eed) {
+ struct NearestEdgeUserData_ZBuf data;
+
+ data.mval_fl[0] = vc->mval[0];
+ data.mval_fl[1] = vc->mval[1];
+ data.dist = FLT_MAX;
+ data.edge_test = eed;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+
+ mesh_foreachScreenEdge(
+ vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ *r_dist_center = data.dist;
+ }
+ /* end exception */
+
+ if (eed) {
+ if (dist_px < *r_dist) {
+ *r_dist = dist_px;
+ return eed;
+ }
+ }
+ return NULL;
+ }
+ else {
+ struct NearestEdgeUserData data = {{0}};
+ const struct NearestEdgeUserData_Hit *hit;
+ /* interpolate along the edge before doing a clipping plane test */
+ const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT & ~V3D_PROJ_TEST_CLIP_BB;
+
+ static int prev_select_index = 0;
+ static const BMEdge *prev_select_elem = NULL;
+
+ if ((use_cycle == false) ||
+ (prev_select_elem &&
+ (prev_select_elem != BM_edge_at_index_find_or_table(bm, prev_select_index)))) {
+ prev_select_index = 0;
+ prev_select_elem = NULL;
+ }
+
+ data.vc = *vc;
+ data.mval_fl[0] = vc->mval[0];
+ data.mval_fl[1] = vc->mval[1];
+ data.use_select_bias = use_select_bias;
+ data.use_cycle = use_cycle;
+ data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
+ data.cycle_index_prev = prev_select_index;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag);
+
+ hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit;
+ *r_dist = hit->dist;
+ if (r_dist_center) {
+ *r_dist_center = hit->dist_center;
+ }
+
+ prev_select_elem = hit->edge;
+ prev_select_index = hit->index;
+
+ return hit->edge;
+ }
}
-BMEdge *EDBM_edge_find_nearest(
- ViewContext *vc, float *r_dist)
+BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist)
{
- return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
+ return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
}
/* find the distance to the face we already have */
struct NearestFaceUserData_ZBuf {
- float mval_fl[2];
- float dist;
- const BMFace *face_test;
+ float mval_fl[2];
+ float dist;
+ const BMFace *face_test;
};
-static void find_nearest_face_center__doZBuf(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
+static void find_nearest_face_center__doZBuf(void *userData,
+ BMFace *efa,
+ const float screen_co[2],
+ int UNUSED(index))
{
- struct NearestFaceUserData_ZBuf *data = userData;
+ struct NearestFaceUserData_ZBuf *data = userData;
- if (efa == data->face_test) {
- const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
+ if (efa == data->face_test) {
+ const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
- if (dist_test < data->dist) {
- data->dist = dist_test;
- }
- }
+ if (dist_test < data->dist) {
+ data->dist = dist_test;
+ }
+ }
}
-
struct NearestFaceUserData_Hit {
- float dist;
- float dist_bias;
- int index;
- BMFace *face;
+ float dist;
+ float dist_bias;
+ int index;
+ BMFace *face;
};
struct NearestFaceUserData {
- float mval_fl[2];
- bool use_select_bias;
- bool use_cycle;
- int cycle_index_prev;
+ float mval_fl[2];
+ bool use_select_bias;
+ bool use_cycle;
+ int cycle_index_prev;
- struct NearestFaceUserData_Hit hit;
- struct NearestFaceUserData_Hit hit_cycle;
+ struct NearestFaceUserData_Hit hit;
+ struct NearestFaceUserData_Hit hit_cycle;
};
-static void findnearestface__doClosest(void *userData, BMFace *efa, const float screen_co[2], int index)
+static void findnearestface__doClosest(void *userData,
+ BMFace *efa,
+ const float screen_co[2],
+ int index)
{
- struct NearestFaceUserData *data = userData;
- float dist_test, dist_test_bias;
-
- dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
-
- if (data->use_select_bias && BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- dist_test_bias += FIND_NEAR_SELECT_BIAS;
- }
-
- if (dist_test_bias < data->hit.dist_bias) {
- data->hit.dist_bias = dist_test_bias;
- data->hit.dist = dist_test;
- data->hit.index = index;
- data->hit.face = efa;
- }
-
- if (data->use_cycle) {
- if ((data->hit_cycle.face == NULL) &&
- (index > data->cycle_index_prev) &&
- (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
- {
- data->hit_cycle.dist_bias = dist_test_bias;
- data->hit_cycle.dist = dist_test;
- data->hit_cycle.index = index;
- data->hit_cycle.face = efa;
- }
- }
+ struct NearestFaceUserData *data = userData;
+ float dist_test, dist_test_bias;
+
+ dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
+
+ if (data->use_select_bias && BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ dist_test_bias += FIND_NEAR_SELECT_BIAS;
+ }
+
+ if (dist_test_bias < data->hit.dist_bias) {
+ data->hit.dist_bias = dist_test_bias;
+ data->hit.dist = dist_test;
+ data->hit.index = index;
+ data->hit.face = efa;
+ }
+
+ if (data->use_cycle) {
+ if ((data->hit_cycle.face == NULL) && (index > data->cycle_index_prev) &&
+ (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN)) {
+ data->hit_cycle.dist_bias = dist_test_bias;
+ data->hit_cycle.dist = dist_test;
+ data->hit_cycle.index = index;
+ data->hit_cycle.face = efa;
+ }
+ }
}
-
-BMFace *EDBM_face_find_nearest_ex(
- ViewContext *vc, float *r_dist,
- float *r_dist_center,
- const bool use_select_bias, const bool use_cycle,
- BMFace **r_efa_zbuf)
+BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
+ float *r_dist,
+ float *r_dist_center,
+ const bool use_select_bias,
+ const bool use_cycle,
+ BMFace **r_efa_zbuf)
{
- BMesh *bm = vc->em->bm;
-
- if (!XRAY_FLAG_ENABLED(vc->v3d)) {
- float dist_test = 0.0f;
- unsigned int index;
- BMFace *efa;
-
- {
- FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_FACE);
- ED_view3d_select_id_validate_with_select_mode(vc, select_mode);
-
- index = ED_view3d_select_id_sample(vc, vc->mval[0], vc->mval[1]);
- efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL;
-
- FAKE_SELECT_MODE_END(vc, fake_select_mode);
- }
-
- if (r_efa_zbuf) {
- *r_efa_zbuf = efa;
- }
-
- /* exception for faces (verts don't need this) */
- if (r_dist_center && efa) {
- struct NearestFaceUserData_ZBuf data;
-
- data.mval_fl[0] = vc->mval[0];
- data.mval_fl[1] = vc->mval[1];
- data.dist = FLT_MAX;
- data.face_test = efa;
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
-
- mesh_foreachScreenFace(vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
-
- *r_dist_center = data.dist;
- }
- /* end exception */
-
- if (efa) {
- if (dist_test < *r_dist) {
- *r_dist = dist_test;
- return efa;
- }
- }
- return NULL;
- }
- else {
- struct NearestFaceUserData data = {{0}};
- const struct NearestFaceUserData_Hit *hit;
- const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
-
- static int prev_select_index = 0;
- static const BMFace *prev_select_elem = NULL;
-
- if ((use_cycle == false) ||
- (prev_select_elem && (prev_select_elem != BM_face_at_index_find_or_table(bm, prev_select_index))))
- {
- prev_select_index = 0;
- prev_select_elem = NULL;
- }
-
- data.mval_fl[0] = vc->mval[0];
- data.mval_fl[1] = vc->mval[1];
- data.use_select_bias = use_select_bias;
- data.use_cycle = use_cycle;
- data.hit.dist = data.hit_cycle.dist = \
- data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
- data.cycle_index_prev = prev_select_index;
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag);
-
- hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit;
- *r_dist = hit->dist;
- if (r_dist_center) {
- *r_dist_center = hit->dist;
- }
-
- prev_select_elem = hit->face;
- prev_select_index = hit->index;
-
- return hit->face;
- }
+ BMesh *bm = vc->em->bm;
+
+ if (!XRAY_FLAG_ENABLED(vc->v3d)) {
+ float dist_test = 0.0f;
+ unsigned int index;
+ BMFace *efa;
+
+ {
+ FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_FACE)
+ ;
+ ED_view3d_select_id_validate_with_select_mode(vc, select_mode);
+
+ index = ED_view3d_select_id_sample(vc, vc->mval[0], vc->mval[1]);
+ efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL;
+
+ FAKE_SELECT_MODE_END(vc, fake_select_mode);
+ }
+
+ if (r_efa_zbuf) {
+ *r_efa_zbuf = efa;
+ }
+
+ /* exception for faces (verts don't need this) */
+ if (r_dist_center && efa) {
+ struct NearestFaceUserData_ZBuf data;
+
+ data.mval_fl[0] = vc->mval[0];
+ data.mval_fl[1] = vc->mval[1];
+ data.dist = FLT_MAX;
+ data.face_test = efa;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+
+ mesh_foreachScreenFace(
+ vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ *r_dist_center = data.dist;
+ }
+ /* end exception */
+
+ if (efa) {
+ if (dist_test < *r_dist) {
+ *r_dist = dist_test;
+ return efa;
+ }
+ }
+ return NULL;
+ }
+ else {
+ struct NearestFaceUserData data = {{0}};
+ const struct NearestFaceUserData_Hit *hit;
+ const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
+
+ static int prev_select_index = 0;
+ static const BMFace *prev_select_elem = NULL;
+
+ if ((use_cycle == false) ||
+ (prev_select_elem &&
+ (prev_select_elem != BM_face_at_index_find_or_table(bm, prev_select_index)))) {
+ prev_select_index = 0;
+ prev_select_elem = NULL;
+ }
+
+ data.mval_fl[0] = vc->mval[0];
+ data.mval_fl[1] = vc->mval[1];
+ data.use_select_bias = use_select_bias;
+ data.use_cycle = use_cycle;
+ data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
+ data.cycle_index_prev = prev_select_index;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag);
+
+ hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit;
+ *r_dist = hit->dist;
+ if (r_dist_center) {
+ *r_dist_center = hit->dist;
+ }
+
+ prev_select_elem = hit->face;
+ prev_select_index = hit->index;
+
+ return hit->face;
+ }
}
BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist)
{
- return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
+ return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
}
#undef FIND_NEAR_SELECT_BIAS
#undef FIND_NEAR_CYCLE_THRESHOLD_MIN
-
/* best distance based on screen coords.
* use em->selectmode to define how to use
* selected vertices and edges get disadvantage
* return 1 if found one
*/
-static bool unified_findnearest(
- ViewContext *vc, Base **bases, const uint bases_len,
- int *r_base_index, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa)
+static bool unified_findnearest(ViewContext *vc,
+ Base **bases,
+ const uint bases_len,
+ int *r_base_index,
+ BMVert **r_eve,
+ BMEdge **r_eed,
+ BMFace **r_efa)
{
- BMEditMesh *em = vc->em;
- static short mval_prev[2] = {-1, -1};
- /* only cycle while the mouse remains still */
- const bool use_cycle = ((mval_prev[0] == vc->mval[0]) && (mval_prev[1] == vc->mval[1]));
- const float dist_init = ED_view3d_select_dist_px();
- /* since edges select lines, we give dots advantage of ~20 pix */
- const float dist_margin = (dist_init / 2);
- float dist = dist_init;
-
- struct {
- struct {
- BMVert *ele;
- int base_index;
- } v;
- struct {
- BMEdge *ele;
- int base_index;
- } e, e_zbuf;
- struct {
- BMFace *ele;
- int base_index;
- } f, f_zbuf;
- } hit = {{NULL}};
-
- /* TODO(campbell): perform selection as one pass
- * instead of many smaller passes (which doesn't work for zbuf occlusion). */
-
- /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
-
- if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) {
- float dist_center = 0.0f;
- float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? &dist_center : NULL;
-
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *obedit = base_iter->object;
- ED_view3d_viewcontext_init_object(vc, obedit);
- BLI_assert(vc->em->selectmode == em->selectmode);
- BMFace *efa_zbuf = NULL;
- BMFace *efa_test = EDBM_face_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf);
- if (efa_test && dist_center_p) {
- dist = min_ff(dist_margin, dist_center);
- }
- if (efa_test) {
- hit.f.base_index = base_index;
- hit.f.ele = efa_test;
- }
- if (efa_zbuf) {
- hit.f_zbuf.base_index = base_index;
- hit.f_zbuf.ele = efa_zbuf;
- }
- } /* bases */
- }
-
- if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) {
- float dist_center = 0.0f;
- float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL;
-
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *obedit = base_iter->object;
- ED_view3d_viewcontext_init_object(vc, obedit);
- BMEdge *eed_zbuf = NULL;
- BMEdge *eed_test = EDBM_edge_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf);
- if (eed_test && dist_center_p) {
- dist = min_ff(dist_margin, dist_center);
- }
- if (eed_test) {
- hit.e.base_index = base_index;
- hit.e.ele = eed_test;
- }
- if (eed_zbuf) {
- hit.e_zbuf.base_index = base_index;
- hit.e_zbuf.ele = eed_zbuf;
- }
- } /* bases */
- }
-
- if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) {
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *obedit = base_iter->object;
- ED_view3d_viewcontext_init_object(vc, obedit);
- BMVert *eve_test = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle);
- if (eve_test) {
- hit.v.base_index = base_index;
- hit.v.ele = eve_test;
- }
- } /* bases */
- }
-
- /* return only one of 3 pointers, for frontbuffer redraws */
- if (hit.v.ele) {
- hit.f.ele = NULL;
- hit.e.ele = NULL;
- }
- else if (hit.e.ele) {
- hit.f.ele = NULL;
- }
-
- /* there may be a face under the cursor, who's center if too far away
- * use this if all else fails, it makes sense to select this */
- if ((hit.v.ele || hit.e.ele || hit.f.ele) == 0) {
- if (hit.e_zbuf.ele) {
- hit.e.base_index = hit.e_zbuf.base_index;
- hit.e.ele = hit.e_zbuf.ele;
- }
- else if (hit.f_zbuf.ele) {
- hit.f.base_index = hit.f_zbuf.base_index;
- hit.f.ele = hit.f_zbuf.ele;
- }
- }
-
- mval_prev[0] = vc->mval[0];
- mval_prev[1] = vc->mval[1];
-
- /* Only one element type will be non-null. */
- BLI_assert(((hit.v.ele != NULL) + (hit.e.ele != NULL) + (hit.f.ele != NULL)) <= 1);
-
- if (hit.v.ele) {
- *r_base_index = hit.v.base_index;
- }
- if (hit.e.ele) {
- *r_base_index = hit.e.base_index;
- }
- if (hit.f.ele) {
- *r_base_index = hit.f.base_index;
- }
-
- *r_eve = hit.v.ele;
- *r_eed = hit.e.ele;
- *r_efa = hit.f.ele;
-
- return (hit.v.ele || hit.e.ele || hit.f.ele);
+ BMEditMesh *em = vc->em;
+ static short mval_prev[2] = {-1, -1};
+ /* only cycle while the mouse remains still */
+ const bool use_cycle = ((mval_prev[0] == vc->mval[0]) && (mval_prev[1] == vc->mval[1]));
+ const float dist_init = ED_view3d_select_dist_px();
+ /* since edges select lines, we give dots advantage of ~20 pix */
+ const float dist_margin = (dist_init / 2);
+ float dist = dist_init;
+
+ struct {
+ struct {
+ BMVert *ele;
+ int base_index;
+ } v;
+ struct {
+ BMEdge *ele;
+ int base_index;
+ } e, e_zbuf;
+ struct {
+ BMFace *ele;
+ int base_index;
+ } f, f_zbuf;
+ } hit = {{NULL}};
+
+ /* TODO(campbell): perform selection as one pass
+ * instead of many smaller passes (which doesn't work for zbuf occlusion). */
+
+ /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
+
+ if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) {
+ float dist_center = 0.0f;
+ float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ?
+ &dist_center :
+ NULL;
+
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ Object *obedit = base_iter->object;
+ ED_view3d_viewcontext_init_object(vc, obedit);
+ BLI_assert(vc->em->selectmode == em->selectmode);
+ BMFace *efa_zbuf = NULL;
+ BMFace *efa_test = EDBM_face_find_nearest_ex(
+ vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf);
+ if (efa_test && dist_center_p) {
+ dist = min_ff(dist_margin, dist_center);
+ }
+ if (efa_test) {
+ hit.f.base_index = base_index;
+ hit.f.ele = efa_test;
+ }
+ if (efa_zbuf) {
+ hit.f_zbuf.base_index = base_index;
+ hit.f_zbuf.ele = efa_zbuf;
+ }
+ } /* bases */
+ }
+
+ if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) {
+ float dist_center = 0.0f;
+ float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL;
+
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ Object *obedit = base_iter->object;
+ ED_view3d_viewcontext_init_object(vc, obedit);
+ BMEdge *eed_zbuf = NULL;
+ BMEdge *eed_test = EDBM_edge_find_nearest_ex(
+ vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf);
+ if (eed_test && dist_center_p) {
+ dist = min_ff(dist_margin, dist_center);
+ }
+ if (eed_test) {
+ hit.e.base_index = base_index;
+ hit.e.ele = eed_test;
+ }
+ if (eed_zbuf) {
+ hit.e_zbuf.base_index = base_index;
+ hit.e_zbuf.ele = eed_zbuf;
+ }
+ } /* bases */
+ }
+
+ if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) {
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ Object *obedit = base_iter->object;
+ ED_view3d_viewcontext_init_object(vc, obedit);
+ BMVert *eve_test = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle);
+ if (eve_test) {
+ hit.v.base_index = base_index;
+ hit.v.ele = eve_test;
+ }
+ } /* bases */
+ }
+
+ /* return only one of 3 pointers, for frontbuffer redraws */
+ if (hit.v.ele) {
+ hit.f.ele = NULL;
+ hit.e.ele = NULL;
+ }
+ else if (hit.e.ele) {
+ hit.f.ele = NULL;
+ }
+
+ /* there may be a face under the cursor, who's center if too far away
+ * use this if all else fails, it makes sense to select this */
+ if ((hit.v.ele || hit.e.ele || hit.f.ele) == 0) {
+ if (hit.e_zbuf.ele) {
+ hit.e.base_index = hit.e_zbuf.base_index;
+ hit.e.ele = hit.e_zbuf.ele;
+ }
+ else if (hit.f_zbuf.ele) {
+ hit.f.base_index = hit.f_zbuf.base_index;
+ hit.f.ele = hit.f_zbuf.ele;
+ }
+ }
+
+ mval_prev[0] = vc->mval[0];
+ mval_prev[1] = vc->mval[1];
+
+ /* Only one element type will be non-null. */
+ BLI_assert(((hit.v.ele != NULL) + (hit.e.ele != NULL) + (hit.f.ele != NULL)) <= 1);
+
+ if (hit.v.ele) {
+ *r_base_index = hit.v.base_index;
+ }
+ if (hit.e.ele) {
+ *r_base_index = hit.e.base_index;
+ }
+ if (hit.f.ele) {
+ *r_base_index = hit.f.base_index;
+ }
+
+ *r_eve = hit.v.ele;
+ *r_eed = hit.e.ele;
+ *r_efa = hit.f.ele;
+
+ return (hit.v.ele || hit.e.ele || hit.f.ele);
}
#undef FAKE_SELECT_MODE_BEGIN
#undef FAKE_SELECT_MODE_END
-bool EDBM_unified_findnearest(
- ViewContext *vc, Base **bases, const uint bases_len,
- int *r_base_index, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa)
+bool EDBM_unified_findnearest(ViewContext *vc,
+ Base **bases,
+ const uint bases_len,
+ int *r_base_index,
+ BMVert **r_eve,
+ BMEdge **r_eed,
+ BMFace **r_efa)
{
- return unified_findnearest(vc, bases, bases_len, r_base_index, r_eve, r_eed, r_efa);
+ return unified_findnearest(vc, bases, bases_len, r_base_index, r_eve, r_eed, r_efa);
}
/** \} */
@@ -1081,205 +1099,202 @@ bool EDBM_unified_findnearest(
* currently used for poly-build.
* \{ */
-bool EDBM_unified_findnearest_from_raycast(
- ViewContext *vc,
- Base **bases, const uint bases_len,
- bool use_boundary,
- int *r_base_index,
- struct BMVert **r_eve,
- struct BMEdge **r_eed,
- struct BMFace **r_efa)
+bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
+ Base **bases,
+ const uint bases_len,
+ bool use_boundary,
+ int *r_base_index,
+ struct BMVert **r_eve,
+ struct BMEdge **r_eed,
+ struct BMFace **r_efa)
{
- const float mval_fl[2] = {UNPACK2(vc->mval)};
- float ray_origin[3], ray_direction[3];
-
- struct {
- uint base_index;
- BMElem *ele;
- } best = {0, NULL};
-
- if (ED_view3d_win_to_ray_clipped(
- vc->depsgraph,
- vc->ar, vc->v3d, mval_fl,
- ray_origin, ray_direction, true))
- {
- float dist_sq_best = FLT_MAX;
-
- const bool use_vert = (r_eve != NULL);
- const bool use_edge = (r_eed != NULL);
- const bool use_face = (r_efa != NULL);
-
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *obedit = base_iter->object;
-
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- float imat3[3][3];
-
- ED_view3d_viewcontext_init_object(vc, obedit);
- copy_m3_m4(imat3, obedit->obmat);
- invert_m3(imat3);
-
- const float (*coords)[3] = NULL;
- {
- Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(vc->depsgraph, obedit->data);
- if (me_eval->runtime.edit_data) {
- coords = me_eval->runtime.edit_data->vertexCos;
- }
- }
-
- if (coords != NULL) {
- BM_mesh_elem_index_ensure(bm, BM_VERT);
- }
-
- if (use_boundary && (use_vert || use_edge)) {
- BMEdge *e;
- BMIter eiter;
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if ((BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) &&
- (BM_edge_is_boundary(e)))
- {
- if (use_vert) {
- for (uint j = 0; j < 2; j++) {
- BMVert *v = *((&e->v1) + j);
- float point[3];
- mul_v3_m4v3(point, obedit->obmat, coords ? coords[BM_elem_index_get(v)] : v->co);
- const float dist_sq_test = dist_squared_to_ray_v3_normalized(
- ray_origin, ray_direction, point);
- if (dist_sq_test < dist_sq_best) {
- dist_sq_best = dist_sq_test;
- best.base_index = base_index;
- best.ele = (BMElem *)v;
- }
- }
- }
-
- if (use_edge) {
- float point[3];
+ const float mval_fl[2] = {UNPACK2(vc->mval)};
+ float ray_origin[3], ray_direction[3];
+
+ struct {
+ uint base_index;
+ BMElem *ele;
+ } best = {0, NULL};
+
+ if (ED_view3d_win_to_ray_clipped(
+ vc->depsgraph, vc->ar, vc->v3d, mval_fl, ray_origin, ray_direction, true)) {
+ float dist_sq_best = FLT_MAX;
+
+ const bool use_vert = (r_eve != NULL);
+ const bool use_edge = (r_eed != NULL);
+ const bool use_face = (r_efa != NULL);
+
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ Object *obedit = base_iter->object;
+
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ float imat3[3][3];
+
+ ED_view3d_viewcontext_init_object(vc, obedit);
+ copy_m3_m4(imat3, obedit->obmat);
+ invert_m3(imat3);
+
+ const float(*coords)[3] = NULL;
+ {
+ Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(vc->depsgraph, obedit->data);
+ if (me_eval->runtime.edit_data) {
+ coords = me_eval->runtime.edit_data->vertexCos;
+ }
+ }
+
+ if (coords != NULL) {
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+ }
+
+ if (use_boundary && (use_vert || use_edge)) {
+ BMEdge *e;
+ BMIter eiter;
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if ((BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) && (BM_edge_is_boundary(e))) {
+ if (use_vert) {
+ for (uint j = 0; j < 2; j++) {
+ BMVert *v = *((&e->v1) + j);
+ float point[3];
+ mul_v3_m4v3(point, obedit->obmat, coords ? coords[BM_elem_index_get(v)] : v->co);
+ const float dist_sq_test = dist_squared_to_ray_v3_normalized(
+ ray_origin, ray_direction, point);
+ if (dist_sq_test < dist_sq_best) {
+ dist_sq_best = dist_sq_test;
+ best.base_index = base_index;
+ best.ele = (BMElem *)v;
+ }
+ }
+ }
+
+ if (use_edge) {
+ float point[3];
#if 0
- const float dist_sq_test = dist_squared_ray_to_seg_v3(
- ray_origin, ray_direction,
- e->v1->co, e->v2->co,
- point, &depth);
+ const float dist_sq_test = dist_squared_ray_to_seg_v3(
+ ray_origin, ray_direction,
+ e->v1->co, e->v2->co,
+ point, &depth);
#else
- if (coords) {
- mid_v3_v3v3(point, coords[BM_elem_index_get(e->v1)], coords[BM_elem_index_get(e->v2)]);
- }
- else {
- mid_v3_v3v3(point, e->v1->co, e->v2->co);
- }
- mul_m4_v3(obedit->obmat, point);
- const float dist_sq_test = dist_squared_to_ray_v3_normalized(
- ray_origin, ray_direction, point);
- if (dist_sq_test < dist_sq_best) {
- dist_sq_best = dist_sq_test;
- best.base_index = base_index;
- best.ele = (BMElem *)e;
- }
+ if (coords) {
+ mid_v3_v3v3(
+ point, coords[BM_elem_index_get(e->v1)], coords[BM_elem_index_get(e->v2)]);
+ }
+ else {
+ mid_v3_v3v3(point, e->v1->co, e->v2->co);
+ }
+ mul_m4_v3(obedit->obmat, point);
+ const float dist_sq_test = dist_squared_to_ray_v3_normalized(
+ ray_origin, ray_direction, point);
+ if (dist_sq_test < dist_sq_best) {
+ dist_sq_best = dist_sq_test;
+ best.base_index = base_index;
+ best.ele = (BMElem *)e;
+ }
#endif
- }
- }
- }
- }
- else {
- /* Non boundary case. */
- if (use_vert) {
- BMVert *v;
- BMIter viter;
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == false) {
- float point[3];
- mul_v3_m4v3(point, obedit->obmat, v->co);
- const float dist_sq_test = dist_squared_to_ray_v3_normalized(
- ray_origin, ray_direction, v->co);
- if (dist_sq_test < dist_sq_best) {
- dist_sq_best = dist_sq_test;
- best.base_index = base_index;
- best.ele = (BMElem *)v;
- }
- }
- }
- }
- if (use_edge) {
- BMEdge *e;
- BMIter eiter;
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) {
- float point[3];
- if (coords) {
- mid_v3_v3v3(point, coords[BM_elem_index_get(e->v1)], coords[BM_elem_index_get(e->v2)]);
- }
- else {
- mid_v3_v3v3(point, e->v1->co, e->v2->co);
- }
- mul_m4_v3(obedit->obmat, point);
- const float dist_sq_test = dist_squared_to_ray_v3_normalized(
- ray_origin, ray_direction, point);
- if (dist_sq_test < dist_sq_best) {
- dist_sq_best = dist_sq_test;
- best.base_index = base_index;
- best.ele = (BMElem *)e;
- }
- }
- }
- }
- }
-
- if (use_face) {
- BMFace *f;
- BMIter fiter;
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_HIDDEN) == false) {
- float point[3];
- if (coords) {
- BM_face_calc_center_median_vcos(bm, f, point, coords);
- }
- else {
- BM_face_calc_center_median(f, point);
- }
- mul_m4_v3(obedit->obmat, point);
- const float dist_sq_test = dist_squared_to_ray_v3_normalized(
- ray_origin, ray_direction, point);
- if (dist_sq_test < dist_sq_best) {
- dist_sq_best = dist_sq_test;
- best.base_index = base_index;
- best.ele = (BMElem *)f;
- }
- }
- }
- }
- }
- }
-
- *r_base_index = best.base_index;
- if (r_eve) {
- *r_eve = NULL;
- }
- if (r_eed) {
- *r_eed = NULL;
- }
- if (r_efa) {
- *r_efa = NULL;
- }
-
- if (best.ele) {
- switch (best.ele->head.htype) {
- case BM_VERT:
- *r_eve = (BMVert *)best.ele;
- break;
- case BM_EDGE:
- *r_eed = (BMEdge *)best.ele;
- break;
- case BM_FACE:
- *r_efa = (BMFace *)best.ele;
- break;
- default:
- BLI_assert(0);
- }
- }
- return (best.ele != NULL);
+ }
+ }
+ }
+ }
+ else {
+ /* Non boundary case. */
+ if (use_vert) {
+ BMVert *v;
+ BMIter viter;
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == false) {
+ float point[3];
+ mul_v3_m4v3(point, obedit->obmat, v->co);
+ const float dist_sq_test = dist_squared_to_ray_v3_normalized(
+ ray_origin, ray_direction, v->co);
+ if (dist_sq_test < dist_sq_best) {
+ dist_sq_best = dist_sq_test;
+ best.base_index = base_index;
+ best.ele = (BMElem *)v;
+ }
+ }
+ }
+ }
+ if (use_edge) {
+ BMEdge *e;
+ BMIter eiter;
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) {
+ float point[3];
+ if (coords) {
+ mid_v3_v3v3(
+ point, coords[BM_elem_index_get(e->v1)], coords[BM_elem_index_get(e->v2)]);
+ }
+ else {
+ mid_v3_v3v3(point, e->v1->co, e->v2->co);
+ }
+ mul_m4_v3(obedit->obmat, point);
+ const float dist_sq_test = dist_squared_to_ray_v3_normalized(
+ ray_origin, ray_direction, point);
+ if (dist_sq_test < dist_sq_best) {
+ dist_sq_best = dist_sq_test;
+ best.base_index = base_index;
+ best.ele = (BMElem *)e;
+ }
+ }
+ }
+ }
+ }
+
+ if (use_face) {
+ BMFace *f;
+ BMIter fiter;
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_HIDDEN) == false) {
+ float point[3];
+ if (coords) {
+ BM_face_calc_center_median_vcos(bm, f, point, coords);
+ }
+ else {
+ BM_face_calc_center_median(f, point);
+ }
+ mul_m4_v3(obedit->obmat, point);
+ const float dist_sq_test = dist_squared_to_ray_v3_normalized(
+ ray_origin, ray_direction, point);
+ if (dist_sq_test < dist_sq_best) {
+ dist_sq_best = dist_sq_test;
+ best.base_index = base_index;
+ best.ele = (BMElem *)f;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ *r_base_index = best.base_index;
+ if (r_eve) {
+ *r_eve = NULL;
+ }
+ if (r_eed) {
+ *r_eed = NULL;
+ }
+ if (r_efa) {
+ *r_efa = NULL;
+ }
+
+ if (best.ele) {
+ switch (best.ele->head.htype) {
+ case BM_VERT:
+ *r_eve = (BMVert *)best.ele;
+ break;
+ case BM_EDGE:
+ *r_eed = (BMEdge *)best.ele;
+ break;
+ case BM_FACE:
+ *r_efa = (BMFace *)best.ele;
+ break;
+ default:
+ BLI_assert(0);
+ }
+ }
+ return (best.ele != NULL);
}
/** \} */
@@ -1290,90 +1305,87 @@ bool EDBM_unified_findnearest_from_raycast(
static int edbm_select_similar_region_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- bool changed = false;
-
- /* group vars */
- int *groups_array;
- int (*group_index)[2];
- int group_tot;
- int i;
-
- if (bm->totfacesel < 2) {
- BKE_report(op->reports, RPT_ERROR, "No face regions selected");
- return OPERATOR_CANCELLED;
- }
-
- groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__);
- group_tot = BM_mesh_calc_face_groups(
- bm, groups_array, &group_index,
- NULL, NULL,
- BM_ELEM_SELECT, BM_VERT);
-
- BM_mesh_elem_table_ensure(bm, BM_FACE);
-
- for (i = 0; i < group_tot; i++) {
- ListBase faces_regions;
- int tot;
-
- const int fg_sta = group_index[i][0];
- const int fg_len = group_index[i][1];
- int j;
- BMFace **fg = MEM_mallocN(sizeof(*fg) * fg_len, __func__);
-
-
- for (j = 0; j < fg_len; j++) {
- fg[j] = BM_face_at_index(bm, groups_array[fg_sta + j]);
- }
-
- tot = BM_mesh_region_match(bm, fg, fg_len, &faces_regions);
-
- MEM_freeN(fg);
-
- if (tot) {
- LinkData *link;
- while ((link = BLI_pophead(&faces_regions))) {
- BMFace *f, **faces = link->data;
- while ((f = *(faces++))) {
- BM_face_select_set(bm, f, true);
- }
- MEM_freeN(link->data);
- MEM_freeN(link);
-
- changed = true;
- }
- }
- }
-
- MEM_freeN(groups_array);
- MEM_freeN(group_index);
-
- if (changed) {
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- else {
- BKE_report(op->reports, RPT_WARNING, "No matching face regions found");
- }
-
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ bool changed = false;
+
+ /* group vars */
+ int *groups_array;
+ int(*group_index)[2];
+ int group_tot;
+ int i;
+
+ if (bm->totfacesel < 2) {
+ BKE_report(op->reports, RPT_ERROR, "No face regions selected");
+ return OPERATOR_CANCELLED;
+ }
+
+ groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__);
+ group_tot = BM_mesh_calc_face_groups(
+ bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT, BM_VERT);
+
+ BM_mesh_elem_table_ensure(bm, BM_FACE);
+
+ for (i = 0; i < group_tot; i++) {
+ ListBase faces_regions;
+ int tot;
+
+ const int fg_sta = group_index[i][0];
+ const int fg_len = group_index[i][1];
+ int j;
+ BMFace **fg = MEM_mallocN(sizeof(*fg) * fg_len, __func__);
+
+ for (j = 0; j < fg_len; j++) {
+ fg[j] = BM_face_at_index(bm, groups_array[fg_sta + j]);
+ }
+
+ tot = BM_mesh_region_match(bm, fg, fg_len, &faces_regions);
+
+ MEM_freeN(fg);
+
+ if (tot) {
+ LinkData *link;
+ while ((link = BLI_pophead(&faces_regions))) {
+ BMFace *f, **faces = link->data;
+ while ((f = *(faces++))) {
+ BM_face_select_set(bm, f, true);
+ }
+ MEM_freeN(link->data);
+ MEM_freeN(link);
+
+ changed = true;
+ }
+ }
+ }
+
+ MEM_freeN(groups_array);
+ MEM_freeN(group_index);
+
+ if (changed) {
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ else {
+ BKE_report(op->reports, RPT_WARNING, "No matching face regions found");
+ }
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_similar_region(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Similar Regions";
- ot->idname = "MESH_OT_select_similar_region";
- ot->description = "Select similar face regions to the current selection";
+ /* identifiers */
+ ot->name = "Select Similar Regions";
+ ot->idname = "MESH_OT_select_similar_region";
+ ot->description = "Select similar face regions to the current selection";
- /* api callbacks */
- ot->exec = edbm_select_similar_region_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_select_similar_region_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -1384,85 +1396,86 @@ void MESH_OT_select_similar_region(wmOperatorType *ot)
static int edbm_select_mode_exec(bContext *C, wmOperator *op)
{
- const int type = RNA_enum_get(op->ptr, "type");
- const int action = RNA_enum_get(op->ptr, "action");
- const bool use_extend = RNA_boolean_get(op->ptr, "use_extend");
- const bool use_expand = RNA_boolean_get(op->ptr, "use_expand");
-
- if (EDBM_selectmode_toggle(C, type, action, use_extend, use_expand)) {
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ const int type = RNA_enum_get(op->ptr, "type");
+ const int action = RNA_enum_get(op->ptr, "action");
+ const bool use_extend = RNA_boolean_get(op->ptr, "use_extend");
+ const bool use_expand = RNA_boolean_get(op->ptr, "use_expand");
+
+ if (EDBM_selectmode_toggle(C, type, action, use_extend, use_expand)) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static int edbm_select_mode_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- /* Bypass when in UV non sync-select mode, fall through to keymap that edits. */
- if (CTX_wm_space_image(C)) {
- ToolSettings *ts = CTX_data_tool_settings(C);
- if ((ts->uv_flag & UV_SYNC_SELECTION) == 0) {
- return OPERATOR_PASS_THROUGH;
- }
- /* Bypass when no action is needed. */
- if (!RNA_struct_property_is_set(op->ptr, "type")) {
- return OPERATOR_CANCELLED;
- }
- }
-
- /* detecting these options based on shift/ctrl here is weak, but it's done
- * to make this work when clicking buttons or menus */
- if (!RNA_struct_property_is_set(op->ptr, "use_extend"))
- RNA_boolean_set(op->ptr, "use_extend", event->shift);
- if (!RNA_struct_property_is_set(op->ptr, "use_expand"))
- RNA_boolean_set(op->ptr, "use_expand", event->ctrl);
-
- return edbm_select_mode_exec(C, op);
+ /* Bypass when in UV non sync-select mode, fall through to keymap that edits. */
+ if (CTX_wm_space_image(C)) {
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ if ((ts->uv_flag & UV_SYNC_SELECTION) == 0) {
+ return OPERATOR_PASS_THROUGH;
+ }
+ /* Bypass when no action is needed. */
+ if (!RNA_struct_property_is_set(op->ptr, "type")) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ /* detecting these options based on shift/ctrl here is weak, but it's done
+ * to make this work when clicking buttons or menus */
+ if (!RNA_struct_property_is_set(op->ptr, "use_extend"))
+ RNA_boolean_set(op->ptr, "use_extend", event->shift);
+ if (!RNA_struct_property_is_set(op->ptr, "use_expand"))
+ RNA_boolean_set(op->ptr, "use_expand", event->ctrl);
+
+ return edbm_select_mode_exec(C, op);
}
void MESH_OT_select_mode(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- static const EnumPropertyItem elem_items[] = {
- {SCE_SELECT_VERTEX, "VERT", ICON_VERTEXSEL, "Vertices", ""},
- {SCE_SELECT_EDGE, "EDGE", ICON_EDGESEL, "Edges", ""},
- {SCE_SELECT_FACE, "FACE", ICON_FACESEL, "Faces", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem actions_items[] = {
- {0, "DISABLE", 0, "Disable", "Disable selected markers"},
- {1, "ENABLE", 0, "Enable", "Enable selected markers"},
- {2, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Select Mode";
- ot->idname = "MESH_OT_select_mode";
- ot->description = "Change selection mode";
-
- /* api callbacks */
- ot->invoke = edbm_select_mode_invoke;
- ot->exec = edbm_select_mode_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- /* Hide all, not to show redo panel. */
- prop = RNA_def_boolean(ot->srna, "use_extend", false, "Extend", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "use_expand", false, "Expand", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- ot->prop = prop = RNA_def_enum(ot->srna, "type", elem_items, 0, "Type", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
-
- prop = RNA_def_enum(ot->srna, "action", actions_items, 2, "Action", "Selection action to execute");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop;
+
+ static const EnumPropertyItem elem_items[] = {
+ {SCE_SELECT_VERTEX, "VERT", ICON_VERTEXSEL, "Vertices", ""},
+ {SCE_SELECT_EDGE, "EDGE", ICON_EDGESEL, "Edges", ""},
+ {SCE_SELECT_FACE, "FACE", ICON_FACESEL, "Faces", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem actions_items[] = {
+ {0, "DISABLE", 0, "Disable", "Disable selected markers"},
+ {1, "ENABLE", 0, "Enable", "Enable selected markers"},
+ {2, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Select Mode";
+ ot->idname = "MESH_OT_select_mode";
+ ot->description = "Change selection mode";
+
+ /* api callbacks */
+ ot->invoke = edbm_select_mode_invoke;
+ ot->exec = edbm_select_mode_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ /* Hide all, not to show redo panel. */
+ prop = RNA_def_boolean(ot->srna, "use_extend", false, "Extend", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "use_expand", false, "Expand", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ ot->prop = prop = RNA_def_enum(ot->srna, "type", elem_items, 0, "Type", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_enum(
+ ot->srna, "action", actions_items, 2, "Action", "Selection action to execute");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/** \} */
@@ -1471,132 +1484,145 @@ void MESH_OT_select_mode(wmOperatorType *ot)
/** \name Select Loop (Non Modal) Operator
* \{ */
-static void walker_select_count(
- BMEditMesh *em, int walkercode, void *start, const bool select, const bool select_mix,
- int *r_totsel, int *r_totunsel)
+static void walker_select_count(BMEditMesh *em,
+ int walkercode,
+ void *start,
+ const bool select,
+ const bool select_mix,
+ int *r_totsel,
+ int *r_totunsel)
{
- BMesh *bm = em->bm;
- BMElem *ele;
- BMWalker walker;
- int tot[2] = {0, 0};
-
- BMW_init(&walker, bm, walkercode,
- BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
- for (ele = BMW_begin(&walker, start); ele; ele = BMW_step(&walker)) {
- tot[(BM_elem_flag_test_bool(ele, BM_ELEM_SELECT) != select)] += 1;
-
- if (!select_mix && tot[0] && tot[1]) {
- tot[0] = tot[1] = -1;
- break;
- }
- }
-
- *r_totsel = tot[0];
- *r_totunsel = tot[1];
-
- BMW_end(&walker);
+ BMesh *bm = em->bm;
+ BMElem *ele;
+ BMWalker walker;
+ int tot[2] = {0, 0};
+
+ BMW_init(&walker,
+ bm,
+ walkercode,
+ BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ for (ele = BMW_begin(&walker, start); ele; ele = BMW_step(&walker)) {
+ tot[(BM_elem_flag_test_bool(ele, BM_ELEM_SELECT) != select)] += 1;
+
+ if (!select_mix && tot[0] && tot[1]) {
+ tot[0] = tot[1] = -1;
+ break;
+ }
+ }
+
+ *r_totsel = tot[0];
+ *r_totunsel = tot[1];
+
+ BMW_end(&walker);
}
static void walker_select(BMEditMesh *em, int walkercode, void *start, const bool select)
{
- BMesh *bm = em->bm;
- BMElem *ele;
- BMWalker walker;
-
- BMW_init(&walker, bm, walkercode,
- BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
- for (ele = BMW_begin(&walker, start); ele; ele = BMW_step(&walker)) {
- if (!select) {
- BM_select_history_remove(bm, ele);
- }
- BM_elem_select_set(bm, ele, select);
- }
- BMW_end(&walker);
+ BMesh *bm = em->bm;
+ BMElem *ele;
+ BMWalker walker;
+
+ BMW_init(&walker,
+ bm,
+ walkercode,
+ BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ for (ele = BMW_begin(&walker, start); ele; ele = BMW_step(&walker)) {
+ if (!select) {
+ BM_select_history_remove(bm, ele);
+ }
+ BM_elem_select_set(bm, ele, select);
+ }
+ BMW_end(&walker);
}
static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op)
{
- const bool is_ring = RNA_boolean_get(op->ptr, "ring");
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totedgesel == 0) {
- continue;
- }
-
- BMEdge *eed;
- BMEdge **edarray;
- int edindex;
- BMIter iter;
- int totedgesel = 0;
-
- BM_ITER_MESH(eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- totedgesel++;
- }
- }
-
- edarray = MEM_mallocN(sizeof(BMEdge *) * totedgesel, "edge array");
- edindex = 0;
-
- BM_ITER_MESH(eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- edarray[edindex] = eed;
- edindex++;
- }
- }
-
- if (is_ring) {
- for (edindex = 0; edindex < totedgesel; edindex += 1) {
- eed = edarray[edindex];
- walker_select(em, BMW_EDGERING, eed, true);
- }
- EDBM_selectmode_flush(em);
- }
- else {
- for (edindex = 0; edindex < totedgesel; edindex += 1) {
- eed = edarray[edindex];
- walker_select(em, BMW_EDGELOOP, eed, true);
- }
- EDBM_selectmode_flush(em);
- }
- MEM_freeN(edarray);
- // if (EM_texFaceCheck())
-
- 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;
+ const bool is_ring = RNA_boolean_get(op->ptr, "ring");
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totedgesel == 0) {
+ continue;
+ }
+
+ BMEdge *eed;
+ BMEdge **edarray;
+ int edindex;
+ BMIter iter;
+ int totedgesel = 0;
+
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ totedgesel++;
+ }
+ }
+
+ edarray = MEM_mallocN(sizeof(BMEdge *) * totedgesel, "edge array");
+ edindex = 0;
+
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ edarray[edindex] = eed;
+ edindex++;
+ }
+ }
+
+ if (is_ring) {
+ for (edindex = 0; edindex < totedgesel; edindex += 1) {
+ eed = edarray[edindex];
+ walker_select(em, BMW_EDGERING, eed, true);
+ }
+ EDBM_selectmode_flush(em);
+ }
+ else {
+ for (edindex = 0; edindex < totedgesel; edindex += 1) {
+ eed = edarray[edindex];
+ walker_select(em, BMW_EDGELOOP, eed, true);
+ }
+ EDBM_selectmode_flush(em);
+ }
+ MEM_freeN(edarray);
+ // if (EM_texFaceCheck())
+
+ 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;
}
void MESH_OT_loop_multi_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Multi Select Loops";
- ot->idname = "MESH_OT_loop_multi_select";
- ot->description = "Select a loop of connected edges by connection type";
+ /* identifiers */
+ ot->name = "Multi Select Loops";
+ ot->idname = "MESH_OT_loop_multi_select";
+ ot->description = "Select a loop of connected edges by connection type";
- /* api callbacks */
- ot->exec = edbm_loop_multiselect_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_loop_multiselect_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "ring", 0, "Ring", "");
+ /* properties */
+ RNA_def_boolean(ot->srna, "ring", 0, "Ring", "");
}
/** \} */
@@ -1607,285 +1633,281 @@ void MESH_OT_loop_multi_select(wmOperatorType *ot)
static void mouse_mesh_loop_face(BMEditMesh *em, BMEdge *eed, bool select, bool select_clear)
{
- if (select_clear) {
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- }
+ if (select_clear) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ }
- walker_select(em, BMW_FACELOOP, eed, select);
+ walker_select(em, BMW_FACELOOP, eed, select);
}
static void mouse_mesh_loop_edge_ring(BMEditMesh *em, BMEdge *eed, bool select, bool select_clear)
{
- if (select_clear) {
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- }
+ if (select_clear) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ }
- walker_select(em, BMW_EDGERING, eed, select);
+ walker_select(em, BMW_EDGERING, eed, select);
}
-static void mouse_mesh_loop_edge(BMEditMesh *em, BMEdge *eed, bool select, bool select_clear, bool select_cycle)
+static void mouse_mesh_loop_edge(
+ BMEditMesh *em, BMEdge *eed, bool select, bool select_clear, bool select_cycle)
{
- bool edge_boundary = false;
-
- /* cycle between BMW_EDGELOOP / BMW_EDGEBOUNDARY */
- if (select_cycle && BM_edge_is_boundary(eed)) {
- int tot[2];
-
- /* if the loops selected toggle the boundaries */
- walker_select_count(em, BMW_EDGELOOP, eed, select, false,
- &tot[0], &tot[1]);
- if (tot[select] == 0) {
- edge_boundary = true;
-
- /* if the boundaries selected, toggle back to the loop */
- walker_select_count(em, BMW_EDGEBOUNDARY, eed, select, false,
- &tot[0], &tot[1]);
- if (tot[select] == 0) {
- edge_boundary = false;
- }
- }
- }
-
- if (select_clear) {
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- }
-
- if (edge_boundary) {
- walker_select(em, BMW_EDGEBOUNDARY, eed, select);
- }
- else {
- walker_select(em, BMW_EDGELOOP, eed, select);
- }
+ bool edge_boundary = false;
+
+ /* cycle between BMW_EDGELOOP / BMW_EDGEBOUNDARY */
+ if (select_cycle && BM_edge_is_boundary(eed)) {
+ int tot[2];
+
+ /* if the loops selected toggle the boundaries */
+ walker_select_count(em, BMW_EDGELOOP, eed, select, false, &tot[0], &tot[1]);
+ if (tot[select] == 0) {
+ edge_boundary = true;
+
+ /* if the boundaries selected, toggle back to the loop */
+ walker_select_count(em, BMW_EDGEBOUNDARY, eed, select, false, &tot[0], &tot[1]);
+ if (tot[select] == 0) {
+ edge_boundary = false;
+ }
+ }
+ }
+
+ if (select_clear) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ }
+
+ if (edge_boundary) {
+ walker_select(em, BMW_EDGEBOUNDARY, eed, select);
+ }
+ else {
+ walker_select(em, BMW_EDGELOOP, eed, select);
+ }
}
-static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, bool ring)
+static bool mouse_mesh_loop(
+ bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, bool ring)
{
- Base *basact = NULL;
- BMVert *eve = NULL;
- BMEdge *eed = NULL;
- BMFace *efa = NULL;
-
- ViewContext vc;
- BMEditMesh *em;
- bool select = true;
- bool select_clear = false;
- bool select_cycle = true;
- float mvalf[2];
-
- em_setup_viewcontext(C, &vc);
- mvalf[0] = (float)(vc.mval[0] = mval[0]);
- mvalf[1] = (float)(vc.mval[1] = mval[1]);
-
- BMEditMesh *em_original = vc.em;
- const short selectmode = em_original->selectmode;
- em_original->selectmode = SCE_SELECT_EDGE;
-
- uint bases_len;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len);
-
- {
- int base_index = -1;
- if (EDBM_unified_findnearest(&vc, bases, bases_len, &base_index, &eve, &eed, &efa)) {
- basact = bases[base_index];
- ED_view3d_viewcontext_init_object(&vc, basact->object);
- em = vc.em;
- }
- else {
- em = NULL;
- }
- }
-
- em_original->selectmode = selectmode;
-
- if (em == NULL || eed == NULL) {
- MEM_freeN(bases);
- return false;
- }
-
- if (extend == false && deselect == false && toggle == false) {
- select_clear = true;
- }
-
- if (extend) {
- select = true;
- }
- else if (deselect) {
- select = false;
- }
- else if (select_clear || (BM_elem_flag_test(eed, BM_ELEM_SELECT) == 0)) {
- select = true;
- }
- else if (toggle) {
- select = false;
- select_cycle = false;
- }
-
- if (select_clear) {
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *ob_iter = base_iter->object;
- BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
-
- if (em_iter->bm->totvertsel == 0) {
- continue;
- }
-
- if (em_iter == em) {
- continue;
- }
-
- EDBM_flag_disable_all(em_iter, BM_ELEM_SELECT);
- DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
- }
- }
-
- if (em->selectmode & SCE_SELECT_FACE) {
- mouse_mesh_loop_face(em, eed, select, select_clear);
- }
- else {
- if (ring) {
- mouse_mesh_loop_edge_ring(em, eed, select, select_clear);
- }
- else {
- mouse_mesh_loop_edge(em, eed, select, select_clear, select_cycle);
- }
- }
-
- EDBM_selectmode_flush(em);
-
- /* sets as active, useful for other tools */
- if (select) {
- if (em->selectmode & SCE_SELECT_VERTEX) {
- /* Find nearest vert from mouse
- * (initialize to large values in case only one vertex can be projected) */
- float v1_co[2], v2_co[2];
- float length_1 = FLT_MAX;
- float length_2 = FLT_MAX;
-
- /* 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) == 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) == V3D_PROJ_RET_OK)
- {
- length_2 = len_squared_v2v2(mvalf, v2_co);
- }
+ Base *basact = NULL;
+ BMVert *eve = NULL;
+ BMEdge *eed = NULL;
+ BMFace *efa = NULL;
+
+ ViewContext vc;
+ BMEditMesh *em;
+ bool select = true;
+ bool select_clear = false;
+ bool select_cycle = true;
+ float mvalf[2];
+
+ em_setup_viewcontext(C, &vc);
+ mvalf[0] = (float)(vc.mval[0] = mval[0]);
+ mvalf[1] = (float)(vc.mval[1] = mval[1]);
+
+ BMEditMesh *em_original = vc.em;
+ const short selectmode = em_original->selectmode;
+ em_original->selectmode = SCE_SELECT_EDGE;
+
+ uint bases_len;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len);
+
+ {
+ int base_index = -1;
+ if (EDBM_unified_findnearest(&vc, bases, bases_len, &base_index, &eve, &eed, &efa)) {
+ basact = bases[base_index];
+ ED_view3d_viewcontext_init_object(&vc, basact->object);
+ em = vc.em;
+ }
+ else {
+ em = NULL;
+ }
+ }
+
+ em_original->selectmode = selectmode;
+
+ if (em == NULL || eed == NULL) {
+ MEM_freeN(bases);
+ return false;
+ }
+
+ if (extend == false && deselect == false && toggle == false) {
+ select_clear = true;
+ }
+
+ if (extend) {
+ select = true;
+ }
+ else if (deselect) {
+ select = false;
+ }
+ else if (select_clear || (BM_elem_flag_test(eed, BM_ELEM_SELECT) == 0)) {
+ select = true;
+ }
+ else if (toggle) {
+ select = false;
+ select_cycle = false;
+ }
+
+ if (select_clear) {
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ Object *ob_iter = base_iter->object;
+ BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
+
+ if (em_iter->bm->totvertsel == 0) {
+ continue;
+ }
+
+ if (em_iter == em) {
+ continue;
+ }
+
+ EDBM_flag_disable_all(em_iter, BM_ELEM_SELECT);
+ DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
+ }
+ }
+
+ if (em->selectmode & SCE_SELECT_FACE) {
+ mouse_mesh_loop_face(em, eed, select, select_clear);
+ }
+ else {
+ if (ring) {
+ mouse_mesh_loop_edge_ring(em, eed, select, select_clear);
+ }
+ else {
+ mouse_mesh_loop_edge(em, eed, select, select_clear, select_cycle);
+ }
+ }
+
+ EDBM_selectmode_flush(em);
+
+ /* sets as active, useful for other tools */
+ if (select) {
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ /* Find nearest vert from mouse
+ * (initialize to large values in case only one vertex can be projected) */
+ float v1_co[2], v2_co[2];
+ float length_1 = FLT_MAX;
+ float length_2 = FLT_MAX;
+
+ /* 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) ==
+ 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) ==
+ V3D_PROJ_RET_OK) {
+ length_2 = len_squared_v2v2(mvalf, v2_co);
+ }
#if 0
- printf("mouse to v1: %f\nmouse to v2: %f\n", len_squared_v2v2(mvalf, v1_co),
- len_squared_v2v2(mvalf, v2_co));
+ printf("mouse to v1: %f\nmouse to v2: %f\n", len_squared_v2v2(mvalf, v1_co),
+ len_squared_v2v2(mvalf, v2_co));
#endif
- BM_select_history_store(em->bm, (length_1 < length_2) ? eed->v1 : eed->v2);
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- BM_select_history_store(em->bm, eed);
- }
- else if (em->selectmode & SCE_SELECT_FACE) {
- /* Select the face of eed which is the nearest of mouse. */
- BMFace *f;
- BMIter iterf;
- float best_dist = FLT_MAX;
- efa = NULL;
-
- /* We can't be sure this has already been set... */
- ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
-
- BM_ITER_ELEM (f, &iterf, eed, BM_FACES_OF_EDGE) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- float cent[3];
- 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) == V3D_PROJ_RET_OK)
- {
- tdist = len_squared_v2v2(mvalf, co);
- if (tdist < best_dist) {
-/* printf("Best face: %p (%f)\n", f, tdist);*/
- best_dist = tdist;
- efa = f;
- }
- }
- }
- }
- if (efa) {
- BM_mesh_active_face_set(em->bm, efa);
- BM_select_history_store(em->bm, efa);
- }
- }
- }
-
- MEM_freeN(bases);
-
- DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
-
- return true;
+ BM_select_history_store(em->bm, (length_1 < length_2) ? eed->v1 : eed->v2);
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ BM_select_history_store(em->bm, eed);
+ }
+ else if (em->selectmode & SCE_SELECT_FACE) {
+ /* Select the face of eed which is the nearest of mouse. */
+ BMFace *f;
+ BMIter iterf;
+ float best_dist = FLT_MAX;
+ efa = NULL;
+
+ /* We can't be sure this has already been set... */
+ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
+
+ BM_ITER_ELEM (f, &iterf, eed, BM_FACES_OF_EDGE) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ float cent[3];
+ 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) ==
+ V3D_PROJ_RET_OK) {
+ tdist = len_squared_v2v2(mvalf, co);
+ if (tdist < best_dist) {
+ /* printf("Best face: %p (%f)\n", f, tdist);*/
+ best_dist = tdist;
+ efa = f;
+ }
+ }
+ }
+ }
+ if (efa) {
+ BM_mesh_active_face_set(em->bm, efa);
+ BM_select_history_store(em->bm, efa);
+ }
+ }
+ }
+
+ MEM_freeN(bases);
+
+ DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
+
+ return true;
}
static int edbm_select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- view3d_operator_needs_opengl(C);
-
- if (mouse_mesh_loop(
- C, event->mval,
- RNA_boolean_get(op->ptr, "extend"),
- RNA_boolean_get(op->ptr, "deselect"),
- RNA_boolean_get(op->ptr, "toggle"),
- RNA_boolean_get(op->ptr, "ring")))
- {
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ view3d_operator_needs_opengl(C);
+
+ if (mouse_mesh_loop(C,
+ event->mval,
+ RNA_boolean_get(op->ptr, "extend"),
+ RNA_boolean_get(op->ptr, "deselect"),
+ RNA_boolean_get(op->ptr, "toggle"),
+ RNA_boolean_get(op->ptr, "ring"))) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void MESH_OT_loop_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Loop Select";
- ot->idname = "MESH_OT_loop_select";
- ot->description = "Select a loop of connected edges";
-
- /* api callbacks */
- ot->invoke = edbm_select_loop_invoke;
- ot->poll = ED_operator_editmesh_region_view3d;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "Extend the selection");
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection");
- RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection");
- RNA_def_boolean(ot->srna, "ring", 0, "Select Ring", "Select ring");
+ /* identifiers */
+ ot->name = "Loop Select";
+ ot->idname = "MESH_OT_loop_select";
+ ot->description = "Select a loop of connected edges";
+
+ /* api callbacks */
+ ot->invoke = edbm_select_loop_invoke;
+ ot->poll = ED_operator_editmesh_region_view3d;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "Extend the selection");
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection");
+ RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection");
+ RNA_def_boolean(ot->srna, "ring", 0, "Select Ring", "Select ring");
}
void MESH_OT_edgering_select(wmOperatorType *ot)
{
- /* description */
- ot->name = "Edge Ring Select";
- ot->idname = "MESH_OT_edgering_select";
- ot->description = "Select an edge ring";
-
- /* callbacks */
- ot->invoke = edbm_select_loop_invoke;
- ot->poll = ED_operator_editmesh_region_view3d;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection");
- RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection");
- RNA_def_boolean(ot->srna, "ring", 1, "Select Ring", "Select ring");
+ /* description */
+ ot->name = "Edge Ring Select";
+ ot->idname = "MESH_OT_edgering_select";
+ ot->description = "Select an edge ring";
+
+ /* callbacks */
+ ot->invoke = edbm_select_loop_invoke;
+ ot->poll = ED_operator_editmesh_region_view3d;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection");
+ RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection");
+ RNA_def_boolean(ot->srna, "ring", 1, "Select Ring", "Select ring");
}
/** \} */
@@ -1896,63 +1918,64 @@ void MESH_OT_edgering_select(wmOperatorType *ot)
static int edbm_select_all_exec(bContext *C, wmOperator *op)
{
- 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(view_layer, CTX_wm_view3d(C), &objects_len);
-
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
- 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->totvertsel || em->bm->totedgesel || em->bm->totfacesel) {
- action = SEL_DESELECT;
- break;
- }
- }
- }
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- switch (action) {
- 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;
- }
- 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;
+ 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(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+ 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->totvertsel || em->bm->totedgesel || em->bm->totfacesel) {
+ action = SEL_DESELECT;
+ break;
+ }
+ }
+ }
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ switch (action) {
+ 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;
+ }
+ 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;
}
void MESH_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All";
- ot->idname = "MESH_OT_select_all";
- ot->description = "(De)select all vertices, edges or faces";
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->idname = "MESH_OT_select_all";
+ ot->description = "(De)select all vertices, edges or faces";
- /* api callbacks */
- ot->exec = edbm_select_all_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_select_all_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_select_all(ot);
+ WM_operator_properties_select_all(ot);
}
/** \} */
@@ -1963,39 +1986,40 @@ void MESH_OT_select_all(wmOperatorType *ot)
static int edbm_faces_select_interior_exec(bContext *C, wmOperator *UNUSED(op))
{
- 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);
+ 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (!EDBM_select_interior_faces(em)) {
- continue;
- }
+ if (!EDBM_select_interior_faces(em)) {
+ continue;
+ }
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- MEM_freeN(objects);
+ 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;
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_interior_faces(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Interior Faces";
- ot->idname = "MESH_OT_select_interior_faces";
- ot->description = "Select faces where all edges have more than 2 face users";
+ /* identifiers */
+ ot->name = "Select Interior Faces";
+ ot->idname = "MESH_OT_select_interior_faces";
+ ot->description = "Select faces where all edges have more than 2 face users";
- /* api callbacks */
- ot->exec = edbm_faces_select_interior_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_faces_select_interior_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -2009,163 +2033,162 @@ void MESH_OT_select_interior_faces(wmOperatorType *ot)
bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
{
- ViewContext vc;
-
- int base_index_active = -1;
- BMVert *eve = NULL;
- BMEdge *eed = NULL;
- BMFace *efa = NULL;
-
- /* setup view context for argument to callbacks */
- em_setup_viewcontext(C, &vc);
- vc.mval[0] = mval[0];
- vc.mval[1] = mval[1];
-
- uint bases_len = 0;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len);
-
- bool ok = false;
-
- if (unified_findnearest(&vc, bases, bases_len, &base_index_active, &eve, &eed, &efa)) {
- Base *basact = bases[base_index_active];
- ED_view3d_viewcontext_init_object(&vc, basact->object);
-
- /* Deselect everything */
- if (extend == false && deselect == false && toggle == false) {
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *ob_iter = base_iter->object;
- EDBM_flag_disable_all(BKE_editmesh_from_object(ob_iter), BM_ELEM_SELECT);
- if (basact->object != ob_iter) {
- DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
- }
- }
- }
-
- if (efa) {
- if (extend) {
- /* set the last selected face */
- BM_mesh_active_face_set(vc.em->bm, efa);
-
- /* Work-around: deselect first, so we can guarantee it will */
- /* be active even if it was already selected */
- BM_select_history_remove(vc.em->bm, efa);
- BM_face_select_set(vc.em->bm, efa, false);
- BM_select_history_store(vc.em->bm, efa);
- BM_face_select_set(vc.em->bm, efa, true);
- }
- else if (deselect) {
- BM_select_history_remove(vc.em->bm, efa);
- BM_face_select_set(vc.em->bm, efa, false);
- }
- else {
- /* set the last selected face */
- BM_mesh_active_face_set(vc.em->bm, efa);
-
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- BM_select_history_store(vc.em->bm, efa);
- BM_face_select_set(vc.em->bm, efa, true);
- }
- else if (toggle) {
- BM_select_history_remove(vc.em->bm, efa);
- BM_face_select_set(vc.em->bm, efa, false);
- }
- }
- }
- else if (eed) {
- if (extend) {
- /* Work-around: deselect first, so we can guarantee it will */
- /* be active even if it was already selected */
- BM_select_history_remove(vc.em->bm, eed);
- BM_edge_select_set(vc.em->bm, eed, false);
- BM_select_history_store(vc.em->bm, eed);
- BM_edge_select_set(vc.em->bm, eed, true);
- }
- else if (deselect) {
- BM_select_history_remove(vc.em->bm, eed);
- BM_edge_select_set(vc.em->bm, eed, false);
- }
- else {
- if (!BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- BM_select_history_store(vc.em->bm, eed);
- BM_edge_select_set(vc.em->bm, eed, true);
- }
- else if (toggle) {
- BM_select_history_remove(vc.em->bm, eed);
- BM_edge_select_set(vc.em->bm, eed, false);
- }
- }
- }
- else if (eve) {
- if (extend) {
- /* Work-around: deselect first, so we can guarantee it will */
- /* be active even if it was already selected */
- BM_select_history_remove(vc.em->bm, eve);
- BM_vert_select_set(vc.em->bm, eve, false);
- BM_select_history_store(vc.em->bm, eve);
- BM_vert_select_set(vc.em->bm, eve, true);
- }
- else if (deselect) {
- BM_select_history_remove(vc.em->bm, eve);
- BM_vert_select_set(vc.em->bm, eve, false);
- }
- else {
- if (!BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- BM_select_history_store(vc.em->bm, eve);
- BM_vert_select_set(vc.em->bm, eve, true);
- }
- else if (toggle) {
- BM_select_history_remove(vc.em->bm, eve);
- BM_vert_select_set(vc.em->bm, eve, false);
- }
- }
- }
-
- EDBM_selectmode_flush(vc.em);
-
- if (efa) {
- /* Change active material on object. */
- if (efa->mat_nr != vc.obedit->actcol - 1) {
- vc.obedit->actcol = efa->mat_nr + 1;
- vc.em->mat_nr = efa->mat_nr;
- WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL);
- }
-
- /* Change active face-map on object. */
- if (!BLI_listbase_is_empty(&vc.obedit->fmaps)) {
- const int cd_fmap_offset = CustomData_get_offset(&vc.em->bm->pdata, CD_FACEMAP);
- if (cd_fmap_offset != -1) {
- int map = *((int *)BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset));
- if ((map < -1) || (map > BLI_listbase_count_at_most(&vc.obedit->fmaps, map))) {
- map = -1;
- }
- map += 1;
- if (map != vc.obedit->actfmap) {
- /* We may want to add notifiers later,
- * currently select update handles redraw. */
- vc.obedit->actfmap = map;
- }
- }
- }
-
- }
-
- /* Changing active object is handy since it allows us to
- * switch UV layers, vgroups for eg. */
- if (vc.view_layer->basact != basact) {
- ED_object_base_activate(C, basact);
- }
-
- DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
-
- ok = true;
- }
-
- MEM_freeN(bases);
-
- return ok;
+ ViewContext vc;
+
+ int base_index_active = -1;
+ BMVert *eve = NULL;
+ BMEdge *eed = NULL;
+ BMFace *efa = NULL;
+
+ /* setup view context for argument to callbacks */
+ em_setup_viewcontext(C, &vc);
+ vc.mval[0] = mval[0];
+ vc.mval[1] = mval[1];
+
+ uint bases_len = 0;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len);
+
+ bool ok = false;
+
+ if (unified_findnearest(&vc, bases, bases_len, &base_index_active, &eve, &eed, &efa)) {
+ Base *basact = bases[base_index_active];
+ ED_view3d_viewcontext_init_object(&vc, basact->object);
+
+ /* Deselect everything */
+ if (extend == false && deselect == false && toggle == false) {
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ Object *ob_iter = base_iter->object;
+ EDBM_flag_disable_all(BKE_editmesh_from_object(ob_iter), BM_ELEM_SELECT);
+ if (basact->object != ob_iter) {
+ DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
+ }
+ }
+ }
+
+ if (efa) {
+ if (extend) {
+ /* set the last selected face */
+ BM_mesh_active_face_set(vc.em->bm, efa);
+
+ /* Work-around: deselect first, so we can guarantee it will */
+ /* be active even if it was already selected */
+ BM_select_history_remove(vc.em->bm, efa);
+ BM_face_select_set(vc.em->bm, efa, false);
+ BM_select_history_store(vc.em->bm, efa);
+ BM_face_select_set(vc.em->bm, efa, true);
+ }
+ else if (deselect) {
+ BM_select_history_remove(vc.em->bm, efa);
+ BM_face_select_set(vc.em->bm, efa, false);
+ }
+ else {
+ /* set the last selected face */
+ BM_mesh_active_face_set(vc.em->bm, efa);
+
+ if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ BM_select_history_store(vc.em->bm, efa);
+ BM_face_select_set(vc.em->bm, efa, true);
+ }
+ else if (toggle) {
+ BM_select_history_remove(vc.em->bm, efa);
+ BM_face_select_set(vc.em->bm, efa, false);
+ }
+ }
+ }
+ else if (eed) {
+ if (extend) {
+ /* Work-around: deselect first, so we can guarantee it will */
+ /* be active even if it was already selected */
+ BM_select_history_remove(vc.em->bm, eed);
+ BM_edge_select_set(vc.em->bm, eed, false);
+ BM_select_history_store(vc.em->bm, eed);
+ BM_edge_select_set(vc.em->bm, eed, true);
+ }
+ else if (deselect) {
+ BM_select_history_remove(vc.em->bm, eed);
+ BM_edge_select_set(vc.em->bm, eed, false);
+ }
+ else {
+ if (!BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ BM_select_history_store(vc.em->bm, eed);
+ BM_edge_select_set(vc.em->bm, eed, true);
+ }
+ else if (toggle) {
+ BM_select_history_remove(vc.em->bm, eed);
+ BM_edge_select_set(vc.em->bm, eed, false);
+ }
+ }
+ }
+ else if (eve) {
+ if (extend) {
+ /* Work-around: deselect first, so we can guarantee it will */
+ /* be active even if it was already selected */
+ BM_select_history_remove(vc.em->bm, eve);
+ BM_vert_select_set(vc.em->bm, eve, false);
+ BM_select_history_store(vc.em->bm, eve);
+ BM_vert_select_set(vc.em->bm, eve, true);
+ }
+ else if (deselect) {
+ BM_select_history_remove(vc.em->bm, eve);
+ BM_vert_select_set(vc.em->bm, eve, false);
+ }
+ else {
+ if (!BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ BM_select_history_store(vc.em->bm, eve);
+ BM_vert_select_set(vc.em->bm, eve, true);
+ }
+ else if (toggle) {
+ BM_select_history_remove(vc.em->bm, eve);
+ BM_vert_select_set(vc.em->bm, eve, false);
+ }
+ }
+ }
+
+ EDBM_selectmode_flush(vc.em);
+
+ if (efa) {
+ /* Change active material on object. */
+ if (efa->mat_nr != vc.obedit->actcol - 1) {
+ vc.obedit->actcol = efa->mat_nr + 1;
+ vc.em->mat_nr = efa->mat_nr;
+ WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL);
+ }
+
+ /* Change active face-map on object. */
+ if (!BLI_listbase_is_empty(&vc.obedit->fmaps)) {
+ const int cd_fmap_offset = CustomData_get_offset(&vc.em->bm->pdata, CD_FACEMAP);
+ if (cd_fmap_offset != -1) {
+ int map = *((int *)BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset));
+ if ((map < -1) || (map > BLI_listbase_count_at_most(&vc.obedit->fmaps, map))) {
+ map = -1;
+ }
+ map += 1;
+ if (map != vc.obedit->actfmap) {
+ /* We may want to add notifiers later,
+ * currently select update handles redraw. */
+ vc.obedit->actfmap = map;
+ }
+ }
+ }
+ }
+
+ /* Changing active object is handy since it allows us to
+ * switch UV layers, vgroups for eg. */
+ if (vc.view_layer->basact != basact) {
+ ED_object_base_activate(C, basact);
+ }
+
+ DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
+
+ ok = true;
+ }
+
+ MEM_freeN(bases);
+
+ return ok;
}
/** \} */
@@ -2176,91 +2199,91 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect
static void edbm_strip_selections(BMEditMesh *em)
{
- BMEditSelection *ese, *nextese;
-
- if (!(em->selectmode & SCE_SELECT_VERTEX)) {
- ese = em->bm->selected.first;
- while (ese) {
- nextese = ese->next;
- if (ese->htype == BM_VERT) BLI_freelinkN(&(em->bm->selected), ese);
- ese = nextese;
- }
- }
- if (!(em->selectmode & SCE_SELECT_EDGE)) {
- ese = em->bm->selected.first;
- while (ese) {
- nextese = ese->next;
- if (ese->htype == BM_EDGE) BLI_freelinkN(&(em->bm->selected), ese);
- ese = nextese;
- }
- }
- if (!(em->selectmode & SCE_SELECT_FACE)) {
- ese = em->bm->selected.first;
- while (ese) {
- nextese = ese->next;
- if (ese->htype == BM_FACE) BLI_freelinkN(&(em->bm->selected), ese);
- ese = nextese;
- }
- }
+ BMEditSelection *ese, *nextese;
+
+ if (!(em->selectmode & SCE_SELECT_VERTEX)) {
+ ese = em->bm->selected.first;
+ while (ese) {
+ nextese = ese->next;
+ if (ese->htype == BM_VERT)
+ BLI_freelinkN(&(em->bm->selected), ese);
+ ese = nextese;
+ }
+ }
+ if (!(em->selectmode & SCE_SELECT_EDGE)) {
+ ese = em->bm->selected.first;
+ while (ese) {
+ nextese = ese->next;
+ if (ese->htype == BM_EDGE)
+ BLI_freelinkN(&(em->bm->selected), ese);
+ ese = nextese;
+ }
+ }
+ if (!(em->selectmode & SCE_SELECT_FACE)) {
+ ese = em->bm->selected.first;
+ while (ese) {
+ nextese = ese->next;
+ if (ese->htype == BM_FACE)
+ BLI_freelinkN(&(em->bm->selected), ese);
+ ese = nextese;
+ }
+ }
}
/* when switching select mode, makes sure selection is consistent for editing */
/* also for paranoia checks to make sure edge or face mode works */
void EDBM_selectmode_set(BMEditMesh *em)
{
- BMVert *eve;
- BMEdge *eed;
- BMFace *efa;
- BMIter iter;
-
- em->bm->selectmode = em->selectmode;
-
- /* strip BMEditSelections from em->selected that are not relevant to new mode */
- edbm_strip_selections(em);
-
- if (em->bm->totvertsel == 0 &&
- em->bm->totedgesel == 0 &&
- em->bm->totfacesel == 0)
- {
- return;
- }
-
- if (em->selectmode & SCE_SELECT_VERTEX) {
- if (em->bm->totvertsel) {
- EDBM_select_flush(em);
- }
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- /* deselect vertices, and select again based on edge select */
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- BM_vert_select_set(em->bm, eve, false);
- }
-
- if (em->bm->totedgesel) {
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- BM_edge_select_set(em->bm, eed, true);
- }
- }
-
- /* selects faces based on edge status */
- EDBM_selectmode_flush(em);
- }
- }
- else if (em->selectmode & SCE_SELECT_FACE) {
- /* deselect eges, and select again based on face select */
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- BM_edge_select_set(em->bm, eed, false);
- }
-
- if (em->bm->totfacesel) {
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- BM_face_select_set(em->bm, efa, true);
- }
- }
- }
- }
+ BMVert *eve;
+ BMEdge *eed;
+ BMFace *efa;
+ BMIter iter;
+
+ em->bm->selectmode = em->selectmode;
+
+ /* strip BMEditSelections from em->selected that are not relevant to new mode */
+ edbm_strip_selections(em);
+
+ if (em->bm->totvertsel == 0 && em->bm->totedgesel == 0 && em->bm->totfacesel == 0) {
+ return;
+ }
+
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ if (em->bm->totvertsel) {
+ EDBM_select_flush(em);
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ /* deselect vertices, and select again based on edge select */
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ BM_vert_select_set(em->bm, eve, false);
+ }
+
+ if (em->bm->totedgesel) {
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ BM_edge_select_set(em->bm, eed, true);
+ }
+ }
+
+ /* selects faces based on edge status */
+ EDBM_selectmode_flush(em);
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_FACE) {
+ /* deselect eges, and select again based on face select */
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ BM_edge_select_set(em->bm, eed, false);
+ }
+
+ if (em->bm->totfacesel) {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ BM_face_select_set(em->bm, efa, true);
+ }
+ }
+ }
+ }
}
/**
@@ -2277,230 +2300,235 @@ void EDBM_selectmode_set(BMEditMesh *em)
* - face -> vert
* - edge -> vert
*/
-void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const short selectmode_new)
+void EDBM_selectmode_convert(BMEditMesh *em,
+ const short selectmode_old,
+ const short selectmode_new)
{
- BMesh *bm = em->bm;
-
- BMVert *eve;
- BMEdge *eed;
- BMFace *efa;
- BMIter iter;
-
- /* first tag-to-select, then select --- this avoids a feedback loop */
-
- /* have to find out what the selectionmode was previously */
- if (selectmode_old == SCE_SELECT_VERTEX) {
- if (bm->totvertsel == 0) {
- /* pass */
- }
- else if (selectmode_new == SCE_SELECT_EDGE) {
- /* flush up (vert -> edge) */
-
- /* select all edges associated with every selected vert */
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_set(eed, BM_ELEM_TAG, BM_edge_is_any_vert_flag_test(eed, BM_ELEM_SELECT));
- }
-
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_TAG)) {
- BM_edge_select_set(bm, eed, true);
- }
- }
- }
- else if (selectmode_new == SCE_SELECT_FACE) {
- /* flush up (vert -> face) */
-
- /* select all faces associated with every selected vert */
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_vert_flag_test(efa, BM_ELEM_SELECT));
- }
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- BM_face_select_set(bm, efa, true);
- }
- }
- }
- }
- else if (selectmode_old == SCE_SELECT_EDGE) {
- if (bm->totedgesel == 0) {
- /* pass */
- }
- else if (selectmode_new == SCE_SELECT_FACE) {
- /* flush up (edge -> face) */
-
- /* select all faces associated with every selected edge */
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_edge_flag_test(efa, BM_ELEM_SELECT));
- }
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- BM_face_select_set(bm, efa, true);
- }
- }
- }
- else if (selectmode_new == SCE_SELECT_VERTEX) {
- /* flush down (edge -> vert) */
-
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_vert_is_all_edge_flag_test(eve, BM_ELEM_SELECT, true)) {
- BM_vert_select_set(bm, eve, false);
- }
- }
- /* deselect edges without both verts selected */
- BM_mesh_deselect_flush(bm);
- }
- }
- else if (selectmode_old == SCE_SELECT_FACE) {
- if (bm->totfacesel == 0) {
- /* pass */
- }
- else if (selectmode_new == SCE_SELECT_EDGE) {
- /* flush down (face -> edge) */
-
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (!BM_edge_is_all_face_flag_test(eed, BM_ELEM_SELECT, true)) {
- BM_edge_select_set(bm, eed, false);
- }
- }
- }
- else if (selectmode_new == SCE_SELECT_VERTEX) {
- /* flush down (face -> vert) */
-
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_vert_is_all_face_flag_test(eve, BM_ELEM_SELECT, true)) {
- BM_vert_select_set(bm, eve, false);
- }
- }
- /* deselect faces without verts selected */
- BM_mesh_deselect_flush(bm);
- }
- }
+ BMesh *bm = em->bm;
+
+ BMVert *eve;
+ BMEdge *eed;
+ BMFace *efa;
+ BMIter iter;
+
+ /* first tag-to-select, then select --- this avoids a feedback loop */
+
+ /* have to find out what the selectionmode was previously */
+ if (selectmode_old == SCE_SELECT_VERTEX) {
+ if (bm->totvertsel == 0) {
+ /* pass */
+ }
+ else if (selectmode_new == SCE_SELECT_EDGE) {
+ /* flush up (vert -> edge) */
+
+ /* select all edges associated with every selected vert */
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_set(eed, BM_ELEM_TAG, BM_edge_is_any_vert_flag_test(eed, BM_ELEM_SELECT));
+ }
+
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_TAG)) {
+ BM_edge_select_set(bm, eed, true);
+ }
+ }
+ }
+ else if (selectmode_new == SCE_SELECT_FACE) {
+ /* flush up (vert -> face) */
+
+ /* select all faces associated with every selected vert */
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_vert_flag_test(efa, BM_ELEM_SELECT));
+ }
+
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
+ BM_face_select_set(bm, efa, true);
+ }
+ }
+ }
+ }
+ else if (selectmode_old == SCE_SELECT_EDGE) {
+ if (bm->totedgesel == 0) {
+ /* pass */
+ }
+ else if (selectmode_new == SCE_SELECT_FACE) {
+ /* flush up (edge -> face) */
+
+ /* select all faces associated with every selected edge */
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_edge_flag_test(efa, BM_ELEM_SELECT));
+ }
+
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
+ BM_face_select_set(bm, efa, true);
+ }
+ }
+ }
+ else if (selectmode_new == SCE_SELECT_VERTEX) {
+ /* flush down (edge -> vert) */
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_vert_is_all_edge_flag_test(eve, BM_ELEM_SELECT, true)) {
+ BM_vert_select_set(bm, eve, false);
+ }
+ }
+ /* deselect edges without both verts selected */
+ BM_mesh_deselect_flush(bm);
+ }
+ }
+ else if (selectmode_old == SCE_SELECT_FACE) {
+ if (bm->totfacesel == 0) {
+ /* pass */
+ }
+ else if (selectmode_new == SCE_SELECT_EDGE) {
+ /* flush down (face -> edge) */
+
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (!BM_edge_is_all_face_flag_test(eed, BM_ELEM_SELECT, true)) {
+ BM_edge_select_set(bm, eed, false);
+ }
+ }
+ }
+ else if (selectmode_new == SCE_SELECT_VERTEX) {
+ /* flush down (face -> vert) */
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_vert_is_all_face_flag_test(eve, BM_ELEM_SELECT, true)) {
+ BM_vert_select_set(bm, eve, false);
+ }
+ }
+ /* deselect faces without verts selected */
+ BM_mesh_deselect_flush(bm);
+ }
+ }
}
/* user facing function, does notification */
-bool EDBM_selectmode_toggle(
- bContext *C, const short selectmode_new,
- const int action, const bool use_extend, const bool use_expand)
+bool EDBM_selectmode_toggle(bContext *C,
+ const short selectmode_new,
+ const int action,
+ const bool use_extend,
+ const bool use_expand)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = NULL;
- bool ret = false;
-
- if (obedit && obedit->type == OB_MESH) {
- em = BKE_editmesh_from_object(obedit);
- }
-
- if (em == NULL) {
- return ret;
- }
-
- bool only_update = false;
- switch (action) {
- case -1:
- /* already set */
- break;
- case 0: /* disable */
- /* check we have something to do */
- if ((em->selectmode & selectmode_new) == 0) {
- only_update = true;
- break;
- }
- em->selectmode &= ~selectmode_new;
- break;
- case 1: /* enable */
- /* check we have something to do */
- if ((em->selectmode & selectmode_new) != 0) {
- only_update = true;
- break;
- }
- em->selectmode |= selectmode_new;
- break;
- case 2: /* toggle */
- /* can't disable this flag if its the only one set */
- if (em->selectmode == selectmode_new) {
- only_update = true;
- break;
- }
- em->selectmode ^= selectmode_new;
- break;
- default:
- BLI_assert(0);
- break;
- }
-
- 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_iter = objects[ob_index];
- BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
- if (em_iter != em) {
- em_iter->selectmode = em->selectmode;
- }
- }
-
- if (only_update) {
- MEM_freeN(objects);
- return false;
- }
-
- if (use_extend == 0 || em->selectmode == 0) {
- if (use_expand) {
- const short selmode_max = highest_order_bit_s(ts->selectmode);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob_iter = objects[ob_index];
- BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
- EDBM_selectmode_convert(em_iter, selmode_max, selectmode_new);
- }
- }
- }
-
- switch (selectmode_new) {
- case SCE_SELECT_VERTEX:
- if (use_extend == 0 || em->selectmode == 0) {
- em->selectmode = SCE_SELECT_VERTEX;
- }
- ret = true;
- break;
- case SCE_SELECT_EDGE:
- if (use_extend == 0 || em->selectmode == 0) {
- em->selectmode = SCE_SELECT_EDGE;
- }
- ret = true;
- break;
- case SCE_SELECT_FACE:
- if (use_extend == 0 || em->selectmode == 0) {
- em->selectmode = SCE_SELECT_FACE;
- }
- ret = true;
- break;
- default:
- BLI_assert(0);
- break;
- }
-
- if (ret == true) {
- ts->selectmode = em->selectmode;
- em = NULL;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob_iter = objects[ob_index];
- BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
- em_iter->selectmode = ts->selectmode;
- EDBM_selectmode_set(em_iter);
- DEG_id_tag_update(ob_iter->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
- }
- WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- }
-
- MEM_freeN(objects);
- return ret;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = NULL;
+ bool ret = false;
+
+ if (obedit && obedit->type == OB_MESH) {
+ em = BKE_editmesh_from_object(obedit);
+ }
+
+ if (em == NULL) {
+ return ret;
+ }
+
+ bool only_update = false;
+ switch (action) {
+ case -1:
+ /* already set */
+ break;
+ case 0: /* disable */
+ /* check we have something to do */
+ if ((em->selectmode & selectmode_new) == 0) {
+ only_update = true;
+ break;
+ }
+ em->selectmode &= ~selectmode_new;
+ break;
+ case 1: /* enable */
+ /* check we have something to do */
+ if ((em->selectmode & selectmode_new) != 0) {
+ only_update = true;
+ break;
+ }
+ em->selectmode |= selectmode_new;
+ break;
+ case 2: /* toggle */
+ /* can't disable this flag if its the only one set */
+ if (em->selectmode == selectmode_new) {
+ only_update = true;
+ break;
+ }
+ em->selectmode ^= selectmode_new;
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ 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_iter = objects[ob_index];
+ BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
+ if (em_iter != em) {
+ em_iter->selectmode = em->selectmode;
+ }
+ }
+
+ if (only_update) {
+ MEM_freeN(objects);
+ return false;
+ }
+
+ if (use_extend == 0 || em->selectmode == 0) {
+ if (use_expand) {
+ const short selmode_max = highest_order_bit_s(ts->selectmode);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob_iter = objects[ob_index];
+ BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
+ EDBM_selectmode_convert(em_iter, selmode_max, selectmode_new);
+ }
+ }
+ }
+
+ switch (selectmode_new) {
+ case SCE_SELECT_VERTEX:
+ if (use_extend == 0 || em->selectmode == 0) {
+ em->selectmode = SCE_SELECT_VERTEX;
+ }
+ ret = true;
+ break;
+ case SCE_SELECT_EDGE:
+ if (use_extend == 0 || em->selectmode == 0) {
+ em->selectmode = SCE_SELECT_EDGE;
+ }
+ ret = true;
+ break;
+ case SCE_SELECT_FACE:
+ if (use_extend == 0 || em->selectmode == 0) {
+ em->selectmode = SCE_SELECT_FACE;
+ }
+ ret = true;
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ if (ret == true) {
+ ts->selectmode = em->selectmode;
+ em = NULL;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob_iter = objects[ob_index];
+ BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
+ em_iter->selectmode = ts->selectmode;
+ EDBM_selectmode_set(em_iter);
+ DEG_id_tag_update(ob_iter->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
+ }
+ WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ }
+
+ MEM_freeN(objects);
+ return ret;
}
/**
@@ -2509,30 +2537,30 @@ bool EDBM_selectmode_toggle(
*
* \return true if the mode is changed.
*/
-bool EDBM_selectmode_disable(
- Scene *scene, BMEditMesh *em,
- const short selectmode_disable,
- const short selectmode_fallback)
+bool EDBM_selectmode_disable(Scene *scene,
+ BMEditMesh *em,
+ const short selectmode_disable,
+ const short selectmode_fallback)
{
- /* note essential, but switch out of vertex mode since the
- * selected regions wont be nicely isolated after flushing */
- if (em->selectmode & selectmode_disable) {
- if (em->selectmode == selectmode_disable) {
- em->selectmode = selectmode_fallback;
- }
- else {
- em->selectmode &= ~selectmode_disable;
- }
- scene->toolsettings->selectmode = em->selectmode;
- EDBM_selectmode_set(em);
-
- WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, scene);
-
- return true;
- }
- else {
- return false;
- }
+ /* note essential, but switch out of vertex mode since the
+ * selected regions wont be nicely isolated after flushing */
+ if (em->selectmode & selectmode_disable) {
+ if (em->selectmode == selectmode_disable) {
+ em->selectmode = selectmode_fallback;
+ }
+ else {
+ em->selectmode &= ~selectmode_disable;
+ }
+ scene->toolsettings->selectmode = em->selectmode;
+ EDBM_selectmode_set(em);
+
+ WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, scene);
+
+ return true;
+ }
+ else {
+ return false;
+ }
}
/** \} */
@@ -2543,88 +2571,88 @@ bool EDBM_selectmode_disable(
bool EDBM_deselect_by_material(BMEditMesh *em, const short index, const bool select)
{
- BMIter iter;
- BMFace *efa;
- bool changed = false;
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
- continue;
- if (efa->mat_nr == index) {
- changed = true;
- BM_face_select_set(em->bm, efa, select);
- }
- }
- return changed;
+ BMIter iter;
+ BMFace *efa;
+ bool changed = false;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
+ continue;
+ if (efa->mat_nr == index) {
+ changed = true;
+ BM_face_select_set(em->bm, efa, select);
+ }
+ }
+ return changed;
}
void EDBM_select_toggle_all(BMEditMesh *em) /* exported for UV */
{
- if (em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel)
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- else
- EDBM_flag_enable_all(em, BM_ELEM_SELECT);
+ if (em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel)
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ else
+ EDBM_flag_enable_all(em, BM_ELEM_SELECT);
}
void EDBM_select_swap(BMEditMesh *em) /* exported for UV */
{
- BMIter iter;
- BMVert *eve;
- BMEdge *eed;
- BMFace *efa;
-
- if (em->bm->selectmode & SCE_SELECT_VERTEX) {
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN))
- continue;
- BM_vert_select_set(em->bm, eve, !BM_elem_flag_test(eve, BM_ELEM_SELECT));
- }
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_HIDDEN))
- continue;
- BM_edge_select_set(em->bm, eed, !BM_elem_flag_test(eed, BM_ELEM_SELECT));
- }
- }
- else {
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
- continue;
- BM_face_select_set(em->bm, efa, !BM_elem_flag_test(efa, BM_ELEM_SELECT));
- }
-
- }
+ BMIter iter;
+ BMVert *eve;
+ BMEdge *eed;
+ BMFace *efa;
+
+ if (em->bm->selectmode & SCE_SELECT_VERTEX) {
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN))
+ continue;
+ BM_vert_select_set(em->bm, eve, !BM_elem_flag_test(eve, BM_ELEM_SELECT));
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_HIDDEN))
+ continue;
+ BM_edge_select_set(em->bm, eed, !BM_elem_flag_test(eed, BM_ELEM_SELECT));
+ }
+ }
+ else {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
+ continue;
+ BM_face_select_set(em->bm, efa, !BM_elem_flag_test(efa, BM_ELEM_SELECT));
+ }
+ }
}
bool EDBM_mesh_deselect_all_multi_ex(struct Base **bases, const uint bases_len)
{
- bool changed_multi = false;
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *ob_iter = base_iter->object;
- BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
-
- if (em_iter->bm->totvertsel == 0) {
- continue;
- }
-
- EDBM_flag_disable_all(em_iter, BM_ELEM_SELECT);
- DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
- changed_multi = true;
- }
- return changed_multi;
+ bool changed_multi = false;
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ Object *ob_iter = base_iter->object;
+ BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
+
+ if (em_iter->bm->totvertsel == 0) {
+ continue;
+ }
+
+ EDBM_flag_disable_all(em_iter, BM_ELEM_SELECT);
+ DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
+ changed_multi = true;
+ }
+ return changed_multi;
}
bool EDBM_mesh_deselect_all_multi(struct bContext *C)
{
- ViewContext vc;
- ED_view3d_viewcontext_init(C, &vc);
- uint bases_len = 0;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &bases_len);
- bool changed_multi = EDBM_mesh_deselect_all_multi_ex(bases, bases_len);
- MEM_freeN(bases);
- return changed_multi;
+ ViewContext vc;
+ ED_view3d_viewcontext_init(C, &vc);
+ uint bases_len = 0;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
+ vc.view_layer, vc.v3d, &bases_len);
+ bool changed_multi = EDBM_mesh_deselect_all_multi_ex(bases, bases_len);
+ MEM_freeN(bases);
+ return changed_multi;
}
/** \} */
@@ -2638,34 +2666,33 @@ bool EDBM_mesh_deselect_all_multi(struct bContext *C)
bool EDBM_select_interior_faces(BMEditMesh *em)
{
- BMesh *bm = em->bm;
- BMIter iter;
- BMIter eiter;
- BMFace *efa;
- BMEdge *eed;
- bool ok;
- bool changed = false;
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
- continue;
-
-
- ok = true;
- BM_ITER_ELEM (eed, &eiter, efa, BM_EDGES_OF_FACE) {
- if (!BM_edge_face_count_is_over(eed, 2)) {
- ok = false;
- break;
- }
- }
-
- if (ok) {
- BM_face_select_set(bm, efa, true);
- changed = true;
- }
- }
-
- return changed;
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMIter eiter;
+ BMFace *efa;
+ BMEdge *eed;
+ bool ok;
+ bool changed = false;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
+ continue;
+
+ ok = true;
+ BM_ITER_ELEM (eed, &eiter, efa, BM_EDGES_OF_FACE) {
+ if (!BM_edge_face_count_is_over(eed, 2)) {
+ ok = false;
+ break;
+ }
+ }
+
+ if (ok) {
+ BM_face_select_set(bm, efa, true);
+ changed = true;
+ }
+ }
+
+ return changed;
}
/** \} */
@@ -2680,53 +2707,54 @@ bool EDBM_select_interior_faces(BMEditMesh *em)
#define USE_LINKED_SELECT_DEFAULT_HACK
struct DelimitData {
- int cd_loop_type;
- int cd_loop_offset;
+ int cd_loop_type;
+ int cd_loop_offset;
};
-static bool select_linked_delimit_test(
- BMEdge *e, int delimit,
- const struct DelimitData *delimit_data)
+static bool select_linked_delimit_test(BMEdge *e,
+ int delimit,
+ const struct DelimitData *delimit_data)
{
- BLI_assert(delimit);
-
- if (delimit & BMO_DELIM_SEAM) {
- if (BM_elem_flag_test(e, BM_ELEM_SEAM)) {
- return true;
- }
- }
-
- if (delimit & BMO_DELIM_SHARP) {
- if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == 0) {
- return true;
- }
- }
-
- if (delimit & BMO_DELIM_NORMAL) {
- if (!BM_edge_is_contiguous(e)) {
- return true;
- }
- }
-
- if (delimit & BMO_DELIM_MATERIAL) {
- if (e->l && e->l->radial_next != e->l) {
- const short mat_nr = e->l->f->mat_nr;
- BMLoop *l_iter = e->l->radial_next;
- do {
- if (l_iter->f->mat_nr != mat_nr) {
- return true;
- }
- } while ((l_iter = l_iter->radial_next) != e->l);
- }
- }
-
- if (delimit & BMO_DELIM_UV) {
- if (BM_edge_is_contiguous_loop_cd(e, delimit_data->cd_loop_type, delimit_data->cd_loop_offset) == 0) {
- return true;
- }
- }
-
- return false;
+ BLI_assert(delimit);
+
+ if (delimit & BMO_DELIM_SEAM) {
+ if (BM_elem_flag_test(e, BM_ELEM_SEAM)) {
+ return true;
+ }
+ }
+
+ if (delimit & BMO_DELIM_SHARP) {
+ if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == 0) {
+ return true;
+ }
+ }
+
+ if (delimit & BMO_DELIM_NORMAL) {
+ if (!BM_edge_is_contiguous(e)) {
+ return true;
+ }
+ }
+
+ if (delimit & BMO_DELIM_MATERIAL) {
+ if (e->l && e->l->radial_next != e->l) {
+ const short mat_nr = e->l->f->mat_nr;
+ BMLoop *l_iter = e->l->radial_next;
+ do {
+ if (l_iter->f->mat_nr != mat_nr) {
+ return true;
+ }
+ } while ((l_iter = l_iter->radial_next) != e->l);
+ }
+ }
+
+ if (delimit & BMO_DELIM_UV) {
+ if (BM_edge_is_contiguous_loop_cd(
+ e, delimit_data->cd_loop_type, delimit_data->cd_loop_offset) == 0) {
+ return true;
+ }
+ }
+
+ return false;
}
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
@@ -2736,277 +2764,294 @@ static bool select_linked_delimit_test(
*/
static int select_linked_delimit_default_from_op(wmOperator *op, const int select_mode)
{
- static char delimit_last_store[2] = {0, BMO_DELIM_SEAM};
- int delimit_last_index = (select_mode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) == 0;
- char *delimit_last = &delimit_last_store[delimit_last_index];
- PropertyRNA *prop_delimit = RNA_struct_find_property(op->ptr, "delimit");
- int delimit;
-
- if (RNA_property_is_set(op->ptr, prop_delimit)) {
- delimit = RNA_property_enum_get(op->ptr, prop_delimit);
- *delimit_last = delimit;
- }
- else {
- delimit = *delimit_last;
- RNA_property_enum_set(op->ptr, prop_delimit, delimit);
- }
- return delimit;
+ static char delimit_last_store[2] = {0, BMO_DELIM_SEAM};
+ int delimit_last_index = (select_mode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) == 0;
+ char *delimit_last = &delimit_last_store[delimit_last_index];
+ PropertyRNA *prop_delimit = RNA_struct_find_property(op->ptr, "delimit");
+ int delimit;
+
+ if (RNA_property_is_set(op->ptr, prop_delimit)) {
+ delimit = RNA_property_enum_get(op->ptr, prop_delimit);
+ *delimit_last = delimit;
+ }
+ else {
+ delimit = *delimit_last;
+ RNA_property_enum_set(op->ptr, prop_delimit, delimit);
+ }
+ return delimit;
}
#endif
static void select_linked_delimit_validate(BMesh *bm, int *delimit)
{
- if ((*delimit) & BMO_DELIM_UV) {
- if (!CustomData_has_layer(&bm->ldata, CD_MLOOPUV)) {
- (*delimit) &= ~BMO_DELIM_UV;
- }
- }
+ if ((*delimit) & BMO_DELIM_UV) {
+ if (!CustomData_has_layer(&bm->ldata, CD_MLOOPUV)) {
+ (*delimit) &= ~BMO_DELIM_UV;
+ }
+ }
}
static void select_linked_delimit_begin(BMesh *bm, int delimit)
{
- struct DelimitData delimit_data = {0};
-
- if (delimit & BMO_DELIM_UV) {
- delimit_data.cd_loop_type = CD_MLOOPUV;
- delimit_data.cd_loop_offset = CustomData_get_offset(&bm->ldata, delimit_data.cd_loop_type);
- if (delimit_data.cd_loop_offset == -1) {
- delimit &= ~BMO_DELIM_UV;
- }
- }
-
- /* grr, shouldn't need to alloc BMO flags here */
- BM_mesh_elem_toolflags_ensure(bm);
-
- {
- BMIter iter;
- BMEdge *e;
-
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- const bool is_walk_ok = (
- (select_linked_delimit_test(e, delimit, &delimit_data) == false));
-
- BMO_edge_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok);
- }
- }
+ struct DelimitData delimit_data = {0};
+
+ if (delimit & BMO_DELIM_UV) {
+ delimit_data.cd_loop_type = CD_MLOOPUV;
+ delimit_data.cd_loop_offset = CustomData_get_offset(&bm->ldata, delimit_data.cd_loop_type);
+ if (delimit_data.cd_loop_offset == -1) {
+ delimit &= ~BMO_DELIM_UV;
+ }
+ }
+
+ /* grr, shouldn't need to alloc BMO flags here */
+ BM_mesh_elem_toolflags_ensure(bm);
+
+ {
+ BMIter iter;
+ BMEdge *e;
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ const bool is_walk_ok = ((select_linked_delimit_test(e, delimit, &delimit_data) == false));
+
+ BMO_edge_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok);
+ }
+ }
}
static void select_linked_delimit_end(BMEditMesh *em)
{
- BMesh *bm = em->bm;
+ BMesh *bm = em->bm;
- BM_mesh_elem_toolflags_clear(bm);
+ BM_mesh_elem_toolflags_clear(bm);
}
static int edbm_select_linked_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
- const int delimit_init = select_linked_delimit_default_from_op(op, scene->toolsettings->selectmode);
+ const int delimit_init = select_linked_delimit_default_from_op(op,
+ scene->toolsettings->selectmode);
#else
- const int delimit_init = RNA_enum_get(op->ptr, "delimit");
+ const int delimit_init = RNA_enum_get(op->ptr, "delimit");
#endif
- 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];
-
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMIter iter;
- BMWalker walker;
-
- int delimit = delimit_init;
-
- select_linked_delimit_validate(bm, &delimit);
-
- if (delimit) {
- select_linked_delimit_begin(em->bm, delimit);
- }
-
- if (em->selectmode & SCE_SELECT_VERTEX) {
- BMVert *v;
-
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_set(v, BM_ELEM_TAG, BM_elem_flag_test(v, BM_ELEM_SELECT));
- }
-
- /* exclude all delimited verts */
- if (delimit) {
- 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);
- }
- }
- }
-
- BMW_init(&walker, em->bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
- BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
- if (delimit) {
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- BMElem *ele_walk;
- BMW_ITER (ele_walk, &walker, v) {
- if (ele_walk->head.htype == BM_LOOP) {
- BMVert *v_step = ((BMLoop *)ele_walk)->v;
- BM_vert_select_set(em->bm, v_step, true);
- BM_elem_flag_disable(v_step, BM_ELEM_TAG);
- }
- else {
- BMEdge *e_step = (BMEdge *)ele_walk;
- BLI_assert(ele_walk->head.htype == BM_EDGE);
- BM_edge_select_set(em->bm, e_step, true);
- BM_elem_flag_disable(e_step->v1, BM_ELEM_TAG);
- BM_elem_flag_disable(e_step->v2, BM_ELEM_TAG);
- }
- }
- }
- }
- }
- else {
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- BMEdge *e_walk;
- BMW_ITER (e_walk, &walker, v) {
- BM_edge_select_set(em->bm, e_walk, true);
- BM_elem_flag_disable(e_walk, BM_ELEM_TAG);
- }
- }
- }
- }
-
- BMW_end(&walker);
-
- EDBM_selectmode_flush(em);
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- BMEdge *e;
-
- 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)));
- }
- }
- else {
- 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));
- }
- }
-
- BMW_init(&walker, em->bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
- BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
- if (delimit) {
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BMElem *ele_walk;
- BMW_ITER (ele_walk, &walker, e) {
- if (ele_walk->head.htype == BM_LOOP) {
- BMLoop *l_step = (BMLoop *)ele_walk;
- BM_edge_select_set(em->bm, l_step->e, true);
- BM_edge_select_set(em->bm, l_step->prev->e, true);
- BM_elem_flag_disable(l_step->e, BM_ELEM_TAG);
- }
- else {
- BMEdge *e_step = (BMEdge *)ele_walk;
- BLI_assert(ele_walk->head.htype == BM_EDGE);
- BM_edge_select_set(em->bm, e_step, true);
- BM_elem_flag_disable(e_step, BM_ELEM_TAG);
- }
- }
- }
- }
- }
- else {
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BMEdge *e_walk;
- BMW_ITER (e_walk, &walker, e) {
- BM_edge_select_set(em->bm, e_walk, true);
- BM_elem_flag_disable(e_walk, BM_ELEM_TAG);
- }
- }
- }
- }
-
- BMW_end(&walker);
-
- EDBM_selectmode_flush(em);
- }
- else {
- BMFace *f;
-
- BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_elem_flag_set(f, BM_ELEM_TAG, BM_elem_flag_test(f, BM_ELEM_SELECT));
- }
-
- BMW_init(&walker, bm, BMW_ISLAND,
- BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
- BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_TAG)) {
- BMFace *f_walk;
- BMW_ITER (f_walk, &walker, f) {
- BM_face_select_set(bm, f_walk, true);
- BM_elem_flag_disable(f_walk, BM_ELEM_TAG);
- }
- }
- }
-
- BMW_end(&walker);
- }
-
- if (delimit) {
- select_linked_delimit_end(em);
- }
-
- 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;
+ 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];
+
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMWalker walker;
+
+ int delimit = delimit_init;
+
+ select_linked_delimit_validate(bm, &delimit);
+
+ if (delimit) {
+ select_linked_delimit_begin(em->bm, delimit);
+ }
+
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ BMVert *v;
+
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_set(v, BM_ELEM_TAG, BM_elem_flag_test(v, BM_ELEM_SELECT));
+ }
+
+ /* exclude all delimited verts */
+ if (delimit) {
+ 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);
+ }
+ }
+ }
+
+ BMW_init(&walker,
+ em->bm,
+ delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
+ BMW_MASK_NOP,
+ delimit ? BMO_ELE_TAG : BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ if (delimit) {
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ BMElem *ele_walk;
+ BMW_ITER (ele_walk, &walker, v) {
+ if (ele_walk->head.htype == BM_LOOP) {
+ BMVert *v_step = ((BMLoop *)ele_walk)->v;
+ BM_vert_select_set(em->bm, v_step, true);
+ BM_elem_flag_disable(v_step, BM_ELEM_TAG);
+ }
+ else {
+ BMEdge *e_step = (BMEdge *)ele_walk;
+ BLI_assert(ele_walk->head.htype == BM_EDGE);
+ BM_edge_select_set(em->bm, e_step, true);
+ BM_elem_flag_disable(e_step->v1, BM_ELEM_TAG);
+ BM_elem_flag_disable(e_step->v2, BM_ELEM_TAG);
+ }
+ }
+ }
+ }
+ }
+ else {
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ BMEdge *e_walk;
+ BMW_ITER (e_walk, &walker, v) {
+ BM_edge_select_set(em->bm, e_walk, true);
+ BM_elem_flag_disable(e_walk, BM_ELEM_TAG);
+ }
+ }
+ }
+ }
+
+ BMW_end(&walker);
+
+ EDBM_selectmode_flush(em);
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ BMEdge *e;
+
+ 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)));
+ }
+ }
+ else {
+ 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));
+ }
+ }
+
+ BMW_init(&walker,
+ em->bm,
+ delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
+ BMW_MASK_NOP,
+ delimit ? BMO_ELE_TAG : BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ if (delimit) {
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BMElem *ele_walk;
+ BMW_ITER (ele_walk, &walker, e) {
+ if (ele_walk->head.htype == BM_LOOP) {
+ BMLoop *l_step = (BMLoop *)ele_walk;
+ BM_edge_select_set(em->bm, l_step->e, true);
+ BM_edge_select_set(em->bm, l_step->prev->e, true);
+ BM_elem_flag_disable(l_step->e, BM_ELEM_TAG);
+ }
+ else {
+ BMEdge *e_step = (BMEdge *)ele_walk;
+ BLI_assert(ele_walk->head.htype == BM_EDGE);
+ BM_edge_select_set(em->bm, e_step, true);
+ BM_elem_flag_disable(e_step, BM_ELEM_TAG);
+ }
+ }
+ }
+ }
+ }
+ else {
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BMEdge *e_walk;
+ BMW_ITER (e_walk, &walker, e) {
+ BM_edge_select_set(em->bm, e_walk, true);
+ BM_elem_flag_disable(e_walk, BM_ELEM_TAG);
+ }
+ }
+ }
+ }
+
+ BMW_end(&walker);
+
+ EDBM_selectmode_flush(em);
+ }
+ else {
+ BMFace *f;
+
+ BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_set(f, BM_ELEM_TAG, BM_elem_flag_test(f, BM_ELEM_SELECT));
+ }
+
+ BMW_init(&walker,
+ bm,
+ BMW_ISLAND,
+ BMW_MASK_NOP,
+ delimit ? BMO_ELE_TAG : BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_TAG)) {
+ BMFace *f_walk;
+ BMW_ITER (f_walk, &walker, f) {
+ BM_face_select_set(bm, f_walk, true);
+ BM_elem_flag_disable(f_walk, BM_ELEM_TAG);
+ }
+ }
+ }
+
+ BMW_end(&walker);
+ }
+
+ if (delimit) {
+ select_linked_delimit_end(em);
+ }
+
+ 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;
}
void MESH_OT_select_linked(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Select Linked All";
- ot->idname = "MESH_OT_select_linked";
- ot->description = "Select all vertices connected to the current selection";
-
- /* api callbacks */
- ot->exec = edbm_select_linked_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- prop = RNA_def_enum_flag(ot->srna, "delimit", rna_enum_mesh_delimit_mode_items, BMO_DELIM_SEAM, "Delimit",
- "Delimit selected region");
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Linked All";
+ ot->idname = "MESH_OT_select_linked";
+ ot->description = "Select all vertices connected to the current selection";
+
+ /* api callbacks */
+ ot->exec = edbm_select_linked_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_enum_flag(ot->srna,
+ "delimit",
+ rna_enum_mesh_delimit_mode_items,
+ BMO_DELIM_SEAM,
+ "Delimit",
+ "Delimit selected region");
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
#else
- UNUSED_VARS(prop);
+ UNUSED_VARS(prop);
#endif
}
@@ -3020,245 +3065,260 @@ static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op);
static void edbm_select_linked_pick_ex(BMEditMesh *em, BMElem *ele, bool sel, int delimit)
{
- BMesh *bm = em->bm;
- BMWalker walker;
-
- select_linked_delimit_validate(bm, &delimit);
-
- if (delimit) {
- select_linked_delimit_begin(bm, delimit);
- }
-
- /* Note: logic closely matches 'edbm_select_linked_exec', keep in sync */
-
- if (ele->head.htype == BM_VERT) {
- BMVert *eve = (BMVert *)ele;
-
- BMW_init(&walker, bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
- BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
- if (delimit) {
- BMElem *ele_walk;
- BMW_ITER (ele_walk, &walker, eve) {
- if (ele_walk->head.htype == BM_LOOP) {
- BMVert *v_step = ((BMLoop *)ele_walk)->v;
- BM_vert_select_set(bm, v_step, sel);
- }
- else {
- BMEdge *e_step = (BMEdge *)ele_walk;
- BLI_assert(ele_walk->head.htype == BM_EDGE);
- BM_edge_select_set(bm, e_step, sel);
- }
- }
- }
- else {
- BMEdge *e_walk;
- BMW_ITER (e_walk, &walker, eve) {
- BM_edge_select_set(bm, e_walk, sel);
- }
- }
-
- BMW_end(&walker);
-
- EDBM_selectmode_flush(em);
- }
- else if (ele->head.htype == BM_EDGE) {
- BMEdge *eed = (BMEdge *)ele;
-
- BMW_init(&walker, bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
- BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
- if (delimit) {
- BMElem *ele_walk;
- BMW_ITER (ele_walk, &walker, eed) {
- if (ele_walk->head.htype == BM_LOOP) {
- BMEdge *e_step = ((BMLoop *)ele_walk)->e;
- BM_edge_select_set(bm, e_step, sel);
- }
- else {
- BMEdge *e_step = (BMEdge *)ele_walk;
- BLI_assert(ele_walk->head.htype == BM_EDGE);
- BM_edge_select_set(bm, e_step, sel);
- }
- }
- }
- else {
- BMEdge *e_walk;
- BMW_ITER (e_walk, &walker, eed) {
- BM_edge_select_set(bm, e_walk, sel);
- }
- }
-
- BMW_end(&walker);
-
- EDBM_selectmode_flush(em);
- }
- else if (ele->head.htype == BM_FACE) {
- BMFace *efa = (BMFace *)ele;
-
- BMW_init(&walker, bm, BMW_ISLAND,
- BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
- {
- BMFace *f_walk;
- BMW_ITER (f_walk, &walker, efa) {
- BM_face_select_set(bm, f_walk, sel);
- BM_elem_flag_disable(f_walk, BM_ELEM_TAG);
- }
- }
-
- BMW_end(&walker);
- }
-
- if (delimit) {
- select_linked_delimit_end(em);
- }
+ BMesh *bm = em->bm;
+ BMWalker walker;
+
+ select_linked_delimit_validate(bm, &delimit);
+
+ if (delimit) {
+ select_linked_delimit_begin(bm, delimit);
+ }
+
+ /* Note: logic closely matches 'edbm_select_linked_exec', keep in sync */
+
+ if (ele->head.htype == BM_VERT) {
+ BMVert *eve = (BMVert *)ele;
+
+ BMW_init(&walker,
+ bm,
+ delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
+ BMW_MASK_NOP,
+ delimit ? BMO_ELE_TAG : BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ if (delimit) {
+ BMElem *ele_walk;
+ BMW_ITER (ele_walk, &walker, eve) {
+ if (ele_walk->head.htype == BM_LOOP) {
+ BMVert *v_step = ((BMLoop *)ele_walk)->v;
+ BM_vert_select_set(bm, v_step, sel);
+ }
+ else {
+ BMEdge *e_step = (BMEdge *)ele_walk;
+ BLI_assert(ele_walk->head.htype == BM_EDGE);
+ BM_edge_select_set(bm, e_step, sel);
+ }
+ }
+ }
+ else {
+ BMEdge *e_walk;
+ BMW_ITER (e_walk, &walker, eve) {
+ BM_edge_select_set(bm, e_walk, sel);
+ }
+ }
+
+ BMW_end(&walker);
+
+ EDBM_selectmode_flush(em);
+ }
+ else if (ele->head.htype == BM_EDGE) {
+ BMEdge *eed = (BMEdge *)ele;
+
+ BMW_init(&walker,
+ bm,
+ delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
+ BMW_MASK_NOP,
+ delimit ? BMO_ELE_TAG : BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ if (delimit) {
+ BMElem *ele_walk;
+ BMW_ITER (ele_walk, &walker, eed) {
+ if (ele_walk->head.htype == BM_LOOP) {
+ BMEdge *e_step = ((BMLoop *)ele_walk)->e;
+ BM_edge_select_set(bm, e_step, sel);
+ }
+ else {
+ BMEdge *e_step = (BMEdge *)ele_walk;
+ BLI_assert(ele_walk->head.htype == BM_EDGE);
+ BM_edge_select_set(bm, e_step, sel);
+ }
+ }
+ }
+ else {
+ BMEdge *e_walk;
+ BMW_ITER (e_walk, &walker, eed) {
+ BM_edge_select_set(bm, e_walk, sel);
+ }
+ }
+
+ BMW_end(&walker);
+
+ EDBM_selectmode_flush(em);
+ }
+ else if (ele->head.htype == BM_FACE) {
+ BMFace *efa = (BMFace *)ele;
+
+ BMW_init(&walker,
+ bm,
+ BMW_ISLAND,
+ BMW_MASK_NOP,
+ delimit ? BMO_ELE_TAG : BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ {
+ BMFace *f_walk;
+ BMW_ITER (f_walk, &walker, efa) {
+ BM_face_select_set(bm, f_walk, sel);
+ BM_elem_flag_disable(f_walk, BM_ELEM_TAG);
+ }
+ }
+
+ BMW_end(&walker);
+ }
+
+ if (delimit) {
+ select_linked_delimit_end(em);
+ }
}
static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewContext vc;
- Base *basact = NULL;
- BMVert *eve;
- BMEdge *eed;
- BMFace *efa;
- const bool sel = !RNA_boolean_get(op->ptr, "deselect");
- int index;
-
- if (RNA_struct_property_is_set(op->ptr, "index")) {
- return edbm_select_linked_pick_exec(C, op);
- }
-
- /* unified_finednearest needs ogl */
- view3d_operator_needs_opengl(C);
-
- /* setup view context for argument to callbacks */
- em_setup_viewcontext(C, &vc);
-
- uint bases_len;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len);
-
- {
- bool has_edges = false;
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Object *ob_iter = bases[base_index]->object;
- ED_view3d_viewcontext_init_object(&vc, ob_iter);
- if (vc.em->bm->totedge) {
- has_edges = true;
- }
- }
- if (has_edges == false) {
- MEM_freeN(bases);
- return OPERATOR_CANCELLED;
- }
- }
-
- vc.mval[0] = event->mval[0];
- vc.mval[1] = event->mval[1];
-
- /* return warning! */
- {
- int base_index = -1;
- const bool ok = unified_findnearest(&vc, bases, bases_len, &base_index, &eve, &eed, &efa);
- if (!ok) {
- MEM_freeN(bases);
- return OPERATOR_CANCELLED;
- }
- basact = bases[base_index];
- }
-
- ED_view3d_viewcontext_init_object(&vc, basact->object);
- BMEditMesh *em = vc.em;
- BMesh *bm = em->bm;
+ ViewContext vc;
+ Base *basact = NULL;
+ BMVert *eve;
+ BMEdge *eed;
+ BMFace *efa;
+ const bool sel = !RNA_boolean_get(op->ptr, "deselect");
+ int index;
+
+ if (RNA_struct_property_is_set(op->ptr, "index")) {
+ return edbm_select_linked_pick_exec(C, op);
+ }
+
+ /* unified_finednearest needs ogl */
+ view3d_operator_needs_opengl(C);
+
+ /* setup view context for argument to callbacks */
+ em_setup_viewcontext(C, &vc);
+
+ uint bases_len;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len);
+
+ {
+ bool has_edges = false;
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Object *ob_iter = bases[base_index]->object;
+ ED_view3d_viewcontext_init_object(&vc, ob_iter);
+ if (vc.em->bm->totedge) {
+ has_edges = true;
+ }
+ }
+ if (has_edges == false) {
+ MEM_freeN(bases);
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ vc.mval[0] = event->mval[0];
+ vc.mval[1] = event->mval[1];
+
+ /* return warning! */
+ {
+ int base_index = -1;
+ const bool ok = unified_findnearest(&vc, bases, bases_len, &base_index, &eve, &eed, &efa);
+ if (!ok) {
+ MEM_freeN(bases);
+ return OPERATOR_CANCELLED;
+ }
+ basact = bases[base_index];
+ }
+
+ ED_view3d_viewcontext_init_object(&vc, basact->object);
+ BMEditMesh *em = vc.em;
+ BMesh *bm = em->bm;
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
- int delimit = select_linked_delimit_default_from_op(op, vc.scene->toolsettings->selectmode);
+ int delimit = select_linked_delimit_default_from_op(op, vc.scene->toolsettings->selectmode);
#else
- int delimit = RNA_enum_get(op->ptr, "delimit");
+ int delimit = RNA_enum_get(op->ptr, "delimit");
#endif
- BMElem *ele = EDBM_elem_from_selectmode(em, eve, eed, efa);
+ BMElem *ele = EDBM_elem_from_selectmode(em, eve, eed, efa);
- edbm_select_linked_pick_ex(em, ele, sel, delimit);
+ edbm_select_linked_pick_ex(em, ele, sel, delimit);
- /* to support redo */
- BM_mesh_elem_index_ensure(bm, ele->head.htype);
- index = EDBM_elem_to_index_any(em, ele);
+ /* to support redo */
+ BM_mesh_elem_index_ensure(bm, ele->head.htype);
+ index = EDBM_elem_to_index_any(em, ele);
- /* TODO(MULTI_EDIT), index doesn't know which object,
- * index selections isn't very common. */
- RNA_int_set(op->ptr, "index", index);
+ /* TODO(MULTI_EDIT), index doesn't know which object,
+ * index selections isn't very common. */
+ RNA_int_set(op->ptr, "index", index);
- DEG_id_tag_update(basact->object->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, basact->object->data);
+ DEG_id_tag_update(basact->object->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, basact->object->data);
- MEM_freeN(bases);
- return OPERATOR_FINISHED;
+ MEM_freeN(bases);
+ return OPERATOR_FINISHED;
}
-
static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- int index;
- const bool sel = !RNA_boolean_get(op->ptr, "deselect");
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ int index;
+ const bool sel = !RNA_boolean_get(op->ptr, "deselect");
- index = RNA_int_get(op->ptr, "index");
- if (index < 0 || index >= (bm->totvert + bm->totedge + bm->totface)) {
- return OPERATOR_CANCELLED;
- }
+ index = RNA_int_get(op->ptr, "index");
+ if (index < 0 || index >= (bm->totvert + bm->totedge + bm->totface)) {
+ return OPERATOR_CANCELLED;
+ }
- BMElem *ele = EDBM_elem_from_index_any(em, index);
+ BMElem *ele = EDBM_elem_from_index_any(em, index);
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
- int delimit = select_linked_delimit_default_from_op(op, em->selectmode);
+ int delimit = select_linked_delimit_default_from_op(op, em->selectmode);
#else
- int delimit = RNA_enum_get(op->ptr, "delimit");
+ int delimit = RNA_enum_get(op->ptr, "delimit");
#endif
- edbm_select_linked_pick_ex(em, ele, sel, delimit);
+ edbm_select_linked_pick_ex(em, ele, sel, delimit);
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_linked_pick(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Select Linked";
- ot->idname = "MESH_OT_select_linked_pick";
- ot->description = "(De)select all vertices linked to the edge under the mouse cursor";
-
- /* api callbacks */
- ot->invoke = edbm_select_linked_pick_invoke;
- ot->exec = edbm_select_linked_pick_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
- prop = RNA_def_enum_flag(ot->srna, "delimit", rna_enum_mesh_delimit_mode_items, BMO_DELIM_SEAM, "Delimit",
- "Delimit selected region");
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Linked";
+ ot->idname = "MESH_OT_select_linked_pick";
+ ot->description = "(De)select all vertices linked to the edge under the mouse cursor";
+
+ /* api callbacks */
+ ot->invoke = edbm_select_linked_pick_invoke;
+ ot->exec = edbm_select_linked_pick_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
+ prop = RNA_def_enum_flag(ot->srna,
+ "delimit",
+ rna_enum_mesh_delimit_mode_items,
+ BMO_DELIM_SEAM,
+ "Delimit",
+ "Delimit selected region");
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
#endif
- /* use for redo */
- prop = RNA_def_int(ot->srna, "index", -1, -1, INT_MAX, "", "", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ /* use for redo */
+ prop = RNA_def_int(ot->srna, "index", -1, -1, INT_MAX, "", "", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/** \} */
@@ -3269,86 +3329,87 @@ void MESH_OT_select_linked_pick(wmOperatorType *ot)
static int edbm_select_face_by_sides_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- const bool extend = RNA_boolean_get(op->ptr, "extend");
- const int numverts = RNA_int_get(op->ptr, "number");
- const int type = RNA_enum_get(op->ptr, "type");
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMIter iter;
-
- if (!extend) {
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- }
-
- BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
- bool select;
-
- switch (type) {
- case 0:
- select = (efa->len < numverts);
- break;
- case 1:
- select = (efa->len == numverts);
- break;
- case 2:
- select = (efa->len > numverts);
- break;
- case 3:
- select = (efa->len != numverts);
- break;
- default:
- BLI_assert(0);
- select = false;
- break;
- }
-
- if (select) {
- BM_face_select_set(em->bm, efa, true);
- }
- }
-
- EDBM_selectmode_flush(em);
-
- 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;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const int numverts = RNA_int_get(op->ptr, "number");
+ const int type = RNA_enum_get(op->ptr, "type");
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMIter iter;
+
+ if (!extend) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ }
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ bool select;
+
+ switch (type) {
+ case 0:
+ select = (efa->len < numverts);
+ break;
+ case 1:
+ select = (efa->len == numverts);
+ break;
+ case 2:
+ select = (efa->len > numverts);
+ break;
+ case 3:
+ select = (efa->len != numverts);
+ break;
+ default:
+ BLI_assert(0);
+ select = false;
+ break;
+ }
+
+ if (select) {
+ BM_face_select_set(em->bm, efa, true);
+ }
+ }
+
+ EDBM_selectmode_flush(em);
+
+ 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;
}
void MESH_OT_select_face_by_sides(wmOperatorType *ot)
{
- static const EnumPropertyItem type_items[] = {
- {0, "LESS", 0, "Less Than", ""},
- {1, "EQUAL", 0, "Equal To", ""},
- {2, "GREATER", 0, "Greater Than", ""},
- {3, "NOTEQUAL", 0, "Not Equal To", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Select Faces by Sides";
- ot->description = "Select vertices or faces by the number of polygon sides";
- ot->idname = "MESH_OT_select_face_by_sides";
-
- /* api callbacks */
- ot->exec = edbm_select_face_by_sides_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_int(ot->srna, "number", 4, 3, INT_MAX, "Number of Vertices", "", 3, INT_MAX);
- RNA_def_enum(ot->srna, "type", type_items, 1, "Type", "Type of comparison to make");
- RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend the selection");
+ static const EnumPropertyItem type_items[] = {
+ {0, "LESS", 0, "Less Than", ""},
+ {1, "EQUAL", 0, "Equal To", ""},
+ {2, "GREATER", 0, "Greater Than", ""},
+ {3, "NOTEQUAL", 0, "Not Equal To", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Select Faces by Sides";
+ ot->description = "Select vertices or faces by the number of polygon sides";
+ ot->idname = "MESH_OT_select_face_by_sides";
+
+ /* api callbacks */
+ ot->exec = edbm_select_face_by_sides_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "number", 4, 3, INT_MAX, "Number of Vertices", "", 3, INT_MAX);
+ RNA_def_enum(ot->srna, "type", type_items, 1, "Type", "Type of comparison to make");
+ RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend the selection");
}
/** \} */
@@ -3359,85 +3420,86 @@ void MESH_OT_select_face_by_sides(wmOperatorType *ot)
static int edbm_select_loose_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const bool extend = RNA_boolean_get(op->ptr, "extend");
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMIter iter;
-
- if (!extend) {
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- }
-
- if (em->selectmode & SCE_SELECT_VERTEX) {
- BMVert *eve;
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (!eve->e) {
- BM_vert_select_set(bm, eve, true);
- }
- }
- }
-
- if (em->selectmode & SCE_SELECT_EDGE) {
- BMEdge *eed;
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_edge_is_wire(eed)) {
- BM_edge_select_set(bm, eed, true);
- }
- }
- }
-
- if (em->selectmode & SCE_SELECT_FACE) {
- BMFace *efa;
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- BMIter liter;
- BMLoop *l;
- bool is_loose = true;
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (!BM_edge_is_boundary(l->e)) {
- is_loose = false;
- break;
- }
- }
- if (is_loose) {
- BM_face_select_set(bm, efa, true);
- }
- }
- }
-
- EDBM_selectmode_flush(em);
-
- 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;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMIter iter;
+
+ if (!extend) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ }
+
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ BMVert *eve;
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!eve->e) {
+ BM_vert_select_set(bm, eve, true);
+ }
+ }
+ }
+
+ if (em->selectmode & SCE_SELECT_EDGE) {
+ BMEdge *eed;
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_edge_is_wire(eed)) {
+ BM_edge_select_set(bm, eed, true);
+ }
+ }
+ }
+
+ if (em->selectmode & SCE_SELECT_FACE) {
+ BMFace *efa;
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ BMIter liter;
+ BMLoop *l;
+ bool is_loose = true;
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (!BM_edge_is_boundary(l->e)) {
+ is_loose = false;
+ break;
+ }
+ }
+ if (is_loose) {
+ BM_face_select_set(bm, efa, true);
+ }
+ }
+ }
+
+ EDBM_selectmode_flush(em);
+
+ 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;
}
void MESH_OT_select_loose(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Loose Geometry";
- ot->description = "Select loose geometry based on the selection mode";
- ot->idname = "MESH_OT_select_loose";
+ /* identifiers */
+ ot->name = "Select Loose Geometry";
+ ot->description = "Select loose geometry based on the selection mode";
+ ot->idname = "MESH_OT_select_loose";
- /* api callbacks */
- ot->exec = edbm_select_loose_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_select_loose_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+ /* props */
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
/** \} */
@@ -3448,69 +3510,70 @@ void MESH_OT_select_loose(wmOperatorType *ot)
static int edbm_select_mirror_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const int axis_flag = RNA_enum_get(op->ptr, "axis");
- const bool extend = RNA_boolean_get(op->ptr, "extend");
- Object *obedit_active = CTX_data_edit_object(C);
- BMEditMesh *em_active = BKE_editmesh_from_object(obedit_active);
- const int select_mode = em_active->bm->selectmode;
- int tot_mirr = 0, tot_fail = 0;
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totvertsel == 0) {
- continue;
- }
-
- int tot_mirr_iter = 0, tot_fail_iter = 0;
-
- for (int axis = 0; axis < 3; axis++) {
- if ((1 << axis) & axis_flag) {
- EDBM_select_mirrored(em, axis, extend, &tot_mirr_iter, &tot_fail_iter);
- }
- }
-
- if (tot_mirr_iter) {
- EDBM_selectmode_flush(em);
-
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
-
- tot_fail += tot_fail_iter;
- tot_mirr += tot_mirr_iter;
- }
- MEM_freeN(objects);
-
- if (tot_mirr || tot_fail) {
- ED_mesh_report_mirror_ex(op, tot_mirr, tot_fail, select_mode);
- }
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const int axis_flag = RNA_enum_get(op->ptr, "axis");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ Object *obedit_active = CTX_data_edit_object(C);
+ BMEditMesh *em_active = BKE_editmesh_from_object(obedit_active);
+ const int select_mode = em_active->bm->selectmode;
+ int tot_mirr = 0, tot_fail = 0;
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
+
+ int tot_mirr_iter = 0, tot_fail_iter = 0;
+
+ for (int axis = 0; axis < 3; axis++) {
+ if ((1 << axis) & axis_flag) {
+ EDBM_select_mirrored(em, axis, extend, &tot_mirr_iter, &tot_fail_iter);
+ }
+ }
+
+ if (tot_mirr_iter) {
+ EDBM_selectmode_flush(em);
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+
+ tot_fail += tot_fail_iter;
+ tot_mirr += tot_mirr_iter;
+ }
+ MEM_freeN(objects);
+
+ if (tot_mirr || tot_fail) {
+ ED_mesh_report_mirror_ex(op, tot_mirr, tot_fail, select_mode);
+ }
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_mirror(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Mirror";
- ot->description = "Select mesh items at mirrored locations";
- ot->idname = "MESH_OT_select_mirror";
+ /* identifiers */
+ ot->name = "Select Mirror";
+ ot->description = "Select mesh items at mirrored locations";
+ ot->idname = "MESH_OT_select_mirror";
- /* api callbacks */
- ot->exec = edbm_select_mirror_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_select_mirror_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_enum_flag(ot->srna, "axis", rna_enum_axis_flag_xyz_items, (1 << 0), "Axis", "");
+ /* props */
+ RNA_def_enum_flag(ot->srna, "axis", rna_enum_axis_flag_xyz_items, (1 << 0), "Axis", "");
- RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection");
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection");
}
/** \} */
@@ -3521,47 +3584,46 @@ void MESH_OT_select_mirror(wmOperatorType *ot)
static int edbm_select_more_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const bool use_face_step = RNA_boolean_get(op->ptr, "use_face_step");
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- if ((bm->totvertsel == 0) &&
- (bm->totedgesel == 0) &&
- (bm->totfacesel == 0))
- {
- continue;
- }
-
- EDBM_select_more(em, use_face_step);
- 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;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool use_face_step = RNA_boolean_get(op->ptr, "use_face_step");
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ if ((bm->totvertsel == 0) && (bm->totedgesel == 0) && (bm->totfacesel == 0)) {
+ continue;
+ }
+
+ EDBM_select_more(em, use_face_step);
+ 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;
}
void MESH_OT_select_more(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select More";
- ot->idname = "MESH_OT_select_more";
- ot->description = "Select more vertices, edges or faces connected to initial selection";
+ /* identifiers */
+ ot->name = "Select More";
+ ot->idname = "MESH_OT_select_more";
+ ot->description = "Select more vertices, edges or faces connected to initial selection";
- /* api callbacks */
- ot->exec = edbm_select_more_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_select_more_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "use_face_step", true, "Face Step", "Connected faces (instead of edges)");
+ RNA_def_boolean(
+ ot->srna, "use_face_step", true, "Face Step", "Connected faces (instead of edges)");
}
/** \} */
@@ -3572,47 +3634,46 @@ void MESH_OT_select_more(wmOperatorType *ot)
static int edbm_select_less_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const bool use_face_step = RNA_boolean_get(op->ptr, "use_face_step");
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- if ((bm->totvertsel == 0) &&
- (bm->totedgesel == 0) &&
- (bm->totfacesel == 0))
- {
- continue;
- }
-
- EDBM_select_less(em, use_face_step);
- 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;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool use_face_step = RNA_boolean_get(op->ptr, "use_face_step");
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ if ((bm->totvertsel == 0) && (bm->totedgesel == 0) && (bm->totfacesel == 0)) {
+ continue;
+ }
+
+ EDBM_select_less(em, use_face_step);
+ 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;
}
void MESH_OT_select_less(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Less";
- ot->idname = "MESH_OT_select_less";
- ot->description = "Deselect vertices, edges or faces at the boundary of each selection region";
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->idname = "MESH_OT_select_less";
+ ot->description = "Deselect vertices, edges or faces at the boundary of each selection region";
- /* api callbacks */
- ot->exec = edbm_select_less_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_select_less_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "use_face_step", true, "Face Step", "Connected faces (instead of edges)");
+ RNA_def_boolean(
+ ot->srna, "use_face_step", true, "Face Step", "Connected faces (instead of edges)");
}
/** \} */
@@ -3626,249 +3687,250 @@ void MESH_OT_select_less(wmOperatorType *ot)
*/
static bool bm_edge_is_select_isolated(BMEdge *e)
{
- BMIter viter;
- BMVert *v;
-
- BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
- BMIter eiter;
- BMEdge *e_other;
-
- BM_ITER_ELEM (e_other, &eiter, v, BM_EDGES_OF_VERT) {
- if ((e_other != e) && BM_elem_flag_test(e_other, BM_ELEM_SELECT)) {
- return false;
- }
- }
- }
- return true;
+ BMIter viter;
+ BMVert *v;
+
+ BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
+ BMIter eiter;
+ BMEdge *e_other;
+
+ BM_ITER_ELEM (e_other, &eiter, v, BM_EDGES_OF_VERT) {
+ if ((e_other != e) && BM_elem_flag_test(e_other, BM_ELEM_SELECT)) {
+ return false;
+ }
+ }
+ }
+ return true;
}
/* Walk all reachable elements of the same type as h_act in breadth-first
* order, starting from h_act. Deselects elements if the depth when they
* are reached is not a multiple of "nth". */
-static void walker_deselect_nth(
- BMEditMesh *em, const struct CheckerIntervalParams *op_params,
- BMHeader *h_act)
+static void walker_deselect_nth(BMEditMesh *em,
+ const struct CheckerIntervalParams *op_params,
+ BMHeader *h_act)
{
- BMElem *ele;
- BMesh *bm = em->bm;
- BMWalker walker;
- BMIter iter;
- int walktype = 0, itertype = 0, flushtype = 0;
- short mask_vert = 0, mask_edge = 0, mask_face = 0;
-
- /* No active element from which to start - nothing to do */
- if (h_act == NULL) {
- return;
- }
-
- /* Determine which type of iter, walker, and select flush to use
- * based on type of the elements being deselected */
- switch (h_act->htype) {
- case BM_VERT:
- itertype = BM_VERTS_OF_MESH;
- walktype = BMW_CONNECTED_VERTEX;
- flushtype = SCE_SELECT_VERTEX;
- mask_vert = BMO_ELE_TAG;
- break;
- case BM_EDGE:
- /* When an edge has no connected-selected edges,
- * use face-stepping (supports edge-rings) */
- itertype = BM_EDGES_OF_MESH;
- walktype = bm_edge_is_select_isolated((BMEdge *)h_act) ? BMW_FACE_SHELL : BMW_VERT_SHELL;
- flushtype = SCE_SELECT_EDGE;
- mask_edge = BMO_ELE_TAG;
- break;
- case BM_FACE:
- itertype = BM_FACES_OF_MESH;
- walktype = BMW_ISLAND;
- flushtype = SCE_SELECT_FACE;
- mask_face = BMO_ELE_TAG;
- break;
- }
-
- /* grr, shouldn't need to alloc BMO flags here */
- BM_mesh_elem_toolflags_ensure(bm);
-
- /* Walker restrictions uses BMO flags, not header flags,
- * so transfer BM_ELEM_SELECT from HFlags onto a BMO flag layer. */
- BMO_push(bm, NULL);
- BM_ITER_MESH (ele, &iter, bm, itertype) {
- if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
- BMO_elem_flag_enable(bm, (BMElemF *)ele, BMO_ELE_TAG);
- }
- }
-
- /* Walk over selected elements starting at active */
- BMW_init(&walker, bm, walktype,
- mask_vert, mask_edge, mask_face,
- BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */
- BMW_NIL_LAY);
-
- /* use tag to avoid touching the same verts twice */
- BM_ITER_MESH (ele, &iter, bm, itertype) {
- BM_elem_flag_disable(ele, BM_ELEM_TAG);
- }
-
- BLI_assert(walker.order == BMW_BREADTH_FIRST);
- for (ele = BMW_begin(&walker, h_act); ele != NULL; ele = BMW_step(&walker)) {
- if (!BM_elem_flag_test(ele, BM_ELEM_TAG)) {
- /* Deselect elements that aren't at "nth" depth from active */
- const int depth = BMW_current_depth(&walker) - 1;
- if (WM_operator_properties_checker_interval_test(op_params, depth)) {
- BM_elem_select_set(bm, ele, false);
- }
- BM_elem_flag_enable(ele, BM_ELEM_TAG);
- }
- }
- BMW_end(&walker);
-
- BMO_pop(bm);
-
- /* Flush selection up */
- EDBM_selectmode_flush_ex(em, flushtype);
+ BMElem *ele;
+ BMesh *bm = em->bm;
+ BMWalker walker;
+ BMIter iter;
+ int walktype = 0, itertype = 0, flushtype = 0;
+ short mask_vert = 0, mask_edge = 0, mask_face = 0;
+
+ /* No active element from which to start - nothing to do */
+ if (h_act == NULL) {
+ return;
+ }
+
+ /* Determine which type of iter, walker, and select flush to use
+ * based on type of the elements being deselected */
+ switch (h_act->htype) {
+ case BM_VERT:
+ itertype = BM_VERTS_OF_MESH;
+ walktype = BMW_CONNECTED_VERTEX;
+ flushtype = SCE_SELECT_VERTEX;
+ mask_vert = BMO_ELE_TAG;
+ break;
+ case BM_EDGE:
+ /* When an edge has no connected-selected edges,
+ * use face-stepping (supports edge-rings) */
+ itertype = BM_EDGES_OF_MESH;
+ walktype = bm_edge_is_select_isolated((BMEdge *)h_act) ? BMW_FACE_SHELL : BMW_VERT_SHELL;
+ flushtype = SCE_SELECT_EDGE;
+ mask_edge = BMO_ELE_TAG;
+ break;
+ case BM_FACE:
+ itertype = BM_FACES_OF_MESH;
+ walktype = BMW_ISLAND;
+ flushtype = SCE_SELECT_FACE;
+ mask_face = BMO_ELE_TAG;
+ break;
+ }
+
+ /* grr, shouldn't need to alloc BMO flags here */
+ BM_mesh_elem_toolflags_ensure(bm);
+
+ /* Walker restrictions uses BMO flags, not header flags,
+ * so transfer BM_ELEM_SELECT from HFlags onto a BMO flag layer. */
+ BMO_push(bm, NULL);
+ BM_ITER_MESH (ele, &iter, bm, itertype) {
+ if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+ BMO_elem_flag_enable(bm, (BMElemF *)ele, BMO_ELE_TAG);
+ }
+ }
+
+ /* Walk over selected elements starting at active */
+ BMW_init(&walker,
+ bm,
+ walktype,
+ mask_vert,
+ mask_edge,
+ mask_face,
+ BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */
+ BMW_NIL_LAY);
+
+ /* use tag to avoid touching the same verts twice */
+ BM_ITER_MESH (ele, &iter, bm, itertype) {
+ BM_elem_flag_disable(ele, BM_ELEM_TAG);
+ }
+
+ BLI_assert(walker.order == BMW_BREADTH_FIRST);
+ for (ele = BMW_begin(&walker, h_act); ele != NULL; ele = BMW_step(&walker)) {
+ if (!BM_elem_flag_test(ele, BM_ELEM_TAG)) {
+ /* Deselect elements that aren't at "nth" depth from active */
+ const int depth = BMW_current_depth(&walker) - 1;
+ if (WM_operator_properties_checker_interval_test(op_params, depth)) {
+ BM_elem_select_set(bm, ele, false);
+ }
+ BM_elem_flag_enable(ele, BM_ELEM_TAG);
+ }
+ }
+ BMW_end(&walker);
+
+ BMO_pop(bm);
+
+ /* Flush selection up */
+ EDBM_selectmode_flush_ex(em, flushtype);
}
static void deselect_nth_active(BMEditMesh *em, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa)
{
- BMIter iter;
- BMElem *ele;
-
- *r_eve = NULL;
- *r_eed = NULL;
- *r_efa = NULL;
-
- EDBM_selectmode_flush(em);
- ele = BM_mesh_active_elem_get(em->bm);
-
- if (ele && BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
- switch (ele->head.htype) {
- case BM_VERT:
- *r_eve = (BMVert *)ele;
- return;
- case BM_EDGE:
- *r_eed = (BMEdge *)ele;
- return;
- case BM_FACE:
- *r_efa = (BMFace *)ele;
- return;
- }
- }
-
- if (em->selectmode & SCE_SELECT_VERTEX) {
- BMVert *v;
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- *r_eve = v;
- return;
- }
- }
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- BMEdge *e;
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- *r_eed = e;
- return;
- }
- }
- }
- else if (em->selectmode & SCE_SELECT_FACE) {
- BMFace *f = BM_mesh_active_face_get(em->bm, true, false);
- if (f && BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- *r_efa = f;
- return;
- }
- }
+ BMIter iter;
+ BMElem *ele;
+
+ *r_eve = NULL;
+ *r_eed = NULL;
+ *r_efa = NULL;
+
+ EDBM_selectmode_flush(em);
+ ele = BM_mesh_active_elem_get(em->bm);
+
+ if (ele && BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+ switch (ele->head.htype) {
+ case BM_VERT:
+ *r_eve = (BMVert *)ele;
+ return;
+ case BM_EDGE:
+ *r_eed = (BMEdge *)ele;
+ return;
+ case BM_FACE:
+ *r_efa = (BMFace *)ele;
+ return;
+ }
+ }
+
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ BMVert *v;
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ *r_eve = v;
+ return;
+ }
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ BMEdge *e;
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ *r_eed = e;
+ return;
+ }
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_FACE) {
+ BMFace *f = BM_mesh_active_face_get(em->bm, true, false);
+ if (f && BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ *r_efa = f;
+ return;
+ }
+ }
}
static bool edbm_deselect_nth(BMEditMesh *em, const struct CheckerIntervalParams *op_params)
{
- BMVert *v;
- BMEdge *e;
- BMFace *f;
-
- deselect_nth_active(em, &v, &e, &f);
-
- if (v) {
- walker_deselect_nth(em, op_params, &v->head);
- return true;
- }
- else if (e) {
- walker_deselect_nth(em, op_params, &e->head);
- return true;
- }
- else if (f) {
- walker_deselect_nth(em, op_params, &f->head);
- return true;
- }
-
- return false;
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ deselect_nth_active(em, &v, &e, &f);
+
+ if (v) {
+ walker_deselect_nth(em, op_params, &v->head);
+ return true;
+ }
+ else if (e) {
+ walker_deselect_nth(em, op_params, &e->head);
+ return true;
+ }
+ else if (f) {
+ walker_deselect_nth(em, op_params, &f->head);
+ return true;
+ }
+
+ return false;
}
static int edbm_select_nth_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- struct CheckerIntervalParams op_params;
- WM_operator_properties_checker_interval_from_op(op, &op_params);
- bool found_active_elt = false;
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if ((em->bm->totvertsel == 0) &&
- (em->bm->totedgesel == 0) &&
- (em->bm->totfacesel == 0))
- {
- continue;
- }
-
- if (edbm_deselect_nth(em, &op_params) == true) {
- found_active_elt = true;
- EDBM_update_generic(em, false, false);
- }
- }
- MEM_freeN(objects);
-
- if (!found_active_elt) {
- BKE_report(op->reports, RPT_ERROR,
- (objects_len == 1 ?
- "Mesh has no active vert/edge/face" :
- "Meshes have no active vert/edge/face"));
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ struct CheckerIntervalParams op_params;
+ WM_operator_properties_checker_interval_from_op(op, &op_params);
+ bool found_active_elt = false;
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if ((em->bm->totvertsel == 0) && (em->bm->totedgesel == 0) && (em->bm->totfacesel == 0)) {
+ continue;
+ }
+
+ if (edbm_deselect_nth(em, &op_params) == true) {
+ found_active_elt = true;
+ EDBM_update_generic(em, false, false);
+ }
+ }
+ MEM_freeN(objects);
+
+ if (!found_active_elt) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ (objects_len == 1 ? "Mesh has no active vert/edge/face" :
+ "Meshes have no active vert/edge/face"));
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
-
void MESH_OT_select_nth(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Checker Deselect";
- ot->idname = "MESH_OT_select_nth";
- ot->description = "Deselect every Nth element starting from the active vertex, edge or face";
+ /* identifiers */
+ ot->name = "Checker Deselect";
+ ot->idname = "MESH_OT_select_nth";
+ ot->description = "Deselect every Nth element starting from the active vertex, edge or face";
- /* api callbacks */
- ot->exec = edbm_select_nth_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_select_nth_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_checker_interval(ot, false);
+ WM_operator_properties_checker_interval(ot, false);
}
void em_setup_viewcontext(bContext *C, ViewContext *vc)
{
- ED_view3d_viewcontext_init(C, vc);
+ ED_view3d_viewcontext_init(C, vc);
- if (vc->obedit) {
- vc->em = BKE_editmesh_from_object(vc->obedit);
- }
+ if (vc->obedit) {
+ vc->em = BKE_editmesh_from_object(vc->obedit);
+ }
}
/** \} */
@@ -3879,71 +3941,78 @@ void em_setup_viewcontext(bContext *C, ViewContext *vc)
static int edbm_select_sharp_edges_exec(bContext *C, wmOperator *op)
{
- /* Find edges that have exactly two neighboring faces,
- * check the angle between those faces, and if angle is
- * small enough, select the edge
- */
- const float angle_limit_cos = cosf(RNA_float_get(op->ptr, "sharpness"));
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMIter iter;
- BMEdge *e;
- BMLoop *l1, *l2;
-
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false &&
- BM_edge_loop_pair(e, &l1, &l2))
- {
- /* edge has exactly two neighboring faces, check angle */
- const float angle_cos = dot_v3v3(l1->f->no, l2->f->no);
-
- if (angle_cos < angle_limit_cos) {
- BM_edge_select_set(em->bm, e, true);
- }
- }
- }
-
- if ((em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) == 0) {
- /* Since we can't select individual edges, select faces connected to them. */
- EDBM_selectmode_convert(em, SCE_SELECT_EDGE, SCE_SELECT_FACE);
- }
- else {
- EDBM_selectmode_flush(em);
- }
- 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;
+ /* Find edges that have exactly two neighboring faces,
+ * check the angle between those faces, and if angle is
+ * small enough, select the edge
+ */
+ const float angle_limit_cos = cosf(RNA_float_get(op->ptr, "sharpness"));
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMIter iter;
+ BMEdge *e;
+ BMLoop *l1, *l2;
+
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false && BM_edge_loop_pair(e, &l1, &l2)) {
+ /* edge has exactly two neighboring faces, check angle */
+ const float angle_cos = dot_v3v3(l1->f->no, l2->f->no);
+
+ if (angle_cos < angle_limit_cos) {
+ BM_edge_select_set(em->bm, e, true);
+ }
+ }
+ }
+
+ if ((em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) == 0) {
+ /* Since we can't select individual edges, select faces connected to them. */
+ EDBM_selectmode_convert(em, SCE_SELECT_EDGE, SCE_SELECT_FACE);
+ }
+ else {
+ EDBM_selectmode_flush(em);
+ }
+ 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;
}
void MESH_OT_edges_select_sharp(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Select Sharp Edges";
- ot->description = "Select all sharp-enough edges";
- ot->idname = "MESH_OT_edges_select_sharp";
-
- /* api callbacks */
- ot->exec = edbm_select_sharp_edges_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- prop = RNA_def_float_rotation(ot->srna, "sharpness", 0, NULL, DEG2RADF(0.01f), DEG2RADF(180.0f),
- "Sharpness", "", DEG2RADF(1.0f), DEG2RADF(180.0f));
- RNA_def_property_float_default(prop, DEG2RADF(30.0f));
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Sharp Edges";
+ ot->description = "Select all sharp-enough edges";
+ ot->idname = "MESH_OT_edges_select_sharp";
+
+ /* api callbacks */
+ ot->exec = edbm_select_sharp_edges_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ prop = RNA_def_float_rotation(ot->srna,
+ "sharpness",
+ 0,
+ NULL,
+ DEG2RADF(0.01f),
+ DEG2RADF(180.0f),
+ "Sharpness",
+ "",
+ DEG2RADF(1.0f),
+ DEG2RADF(180.0f));
+ RNA_def_property_float_default(prop, DEG2RADF(30.0f));
}
/** \} */
@@ -3954,95 +4023,102 @@ void MESH_OT_edges_select_sharp(wmOperatorType *ot)
static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- const float angle_limit_cos = cosf(RNA_float_get(op->ptr, "sharpness"));
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ const float angle_limit_cos = cosf(RNA_float_get(op->ptr, "sharpness"));
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
- if (bm->totfacesel == 0) {
- continue;
- }
+ if (bm->totfacesel == 0) {
+ continue;
+ }
- BLI_LINKSTACK_DECLARE(stack, BMFace *);
+ BLI_LINKSTACK_DECLARE(stack, BMFace *);
- BMIter iter, liter, liter2;
- BMFace *f;
- BMLoop *l, *l2;
+ BMIter iter, liter, liter2;
+ BMFace *f;
+ BMLoop *l, *l2;
- BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
+ BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
- BLI_LINKSTACK_INIT(stack);
+ BLI_LINKSTACK_INIT(stack);
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if ((BM_elem_flag_test(f, BM_ELEM_HIDDEN) != 0) ||
- (BM_elem_flag_test(f, BM_ELEM_TAG) != 0) ||
- (BM_elem_flag_test(f, BM_ELEM_SELECT) == 0))
- {
- continue;
- }
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if ((BM_elem_flag_test(f, BM_ELEM_HIDDEN) != 0) ||
+ (BM_elem_flag_test(f, BM_ELEM_TAG) != 0) ||
+ (BM_elem_flag_test(f, BM_ELEM_SELECT) == 0)) {
+ continue;
+ }
- BLI_assert(BLI_LINKSTACK_SIZE(stack) == 0);
+ BLI_assert(BLI_LINKSTACK_SIZE(stack) == 0);
- do {
- BM_face_select_set(bm, f, true);
+ do {
+ BM_face_select_set(bm, f, true);
- BM_elem_flag_enable(f, BM_ELEM_TAG);
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- BM_ITER_ELEM (l2, &liter2, l, BM_LOOPS_OF_LOOP) {
- float angle_cos;
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ BM_ITER_ELEM (l2, &liter2, l, BM_LOOPS_OF_LOOP) {
+ float angle_cos;
- if (BM_elem_flag_test(l2->f, BM_ELEM_TAG) ||
- BM_elem_flag_test(l2->f, BM_ELEM_HIDDEN))
- {
- continue;
- }
+ if (BM_elem_flag_test(l2->f, BM_ELEM_TAG) ||
+ BM_elem_flag_test(l2->f, BM_ELEM_HIDDEN)) {
+ continue;
+ }
- angle_cos = dot_v3v3(f->no, l2->f->no);
+ angle_cos = dot_v3v3(f->no, l2->f->no);
- if (angle_cos > angle_limit_cos) {
- BLI_LINKSTACK_PUSH(stack, l2->f);
- }
- }
- }
- } while ((f = BLI_LINKSTACK_POP(stack)));
- }
+ if (angle_cos > angle_limit_cos) {
+ BLI_LINKSTACK_PUSH(stack, l2->f);
+ }
+ }
+ }
+ } while ((f = BLI_LINKSTACK_POP(stack)));
+ }
- BLI_LINKSTACK_FREE(stack);
+ BLI_LINKSTACK_FREE(stack);
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- MEM_freeN(objects);
+ 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;
+ return OPERATOR_FINISHED;
}
void MESH_OT_faces_select_linked_flat(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Select Linked Flat Faces";
- ot->description = "Select linked faces by angle";
- ot->idname = "MESH_OT_faces_select_linked_flat";
-
- /* api callbacks */
- ot->exec = edbm_select_linked_flat_faces_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- prop = RNA_def_float_rotation(ot->srna, "sharpness", 0, NULL, DEG2RADF(0.01f), DEG2RADF(180.0f),
- "Sharpness", "", DEG2RADF(1.0f), DEG2RADF(180.0f));
- RNA_def_property_float_default(prop, DEG2RADF(1.0f));
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Linked Flat Faces";
+ ot->description = "Select linked faces by angle";
+ ot->idname = "MESH_OT_faces_select_linked_flat";
+
+ /* api callbacks */
+ ot->exec = edbm_select_linked_flat_faces_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ prop = RNA_def_float_rotation(ot->srna,
+ "sharpness",
+ 0,
+ NULL,
+ DEG2RADF(0.01f),
+ DEG2RADF(180.0f),
+ "Sharpness",
+ "",
+ DEG2RADF(1.0f),
+ DEG2RADF(180.0f));
+ RNA_def_property_float_default(prop, DEG2RADF(1.0f));
}
/** \} */
@@ -4053,103 +4129,102 @@ void MESH_OT_faces_select_linked_flat(wmOperatorType *ot)
static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op)
{
- const bool use_extend = RNA_boolean_get(op->ptr, "extend");
- const bool use_wire = RNA_boolean_get(op->ptr, "use_wire");
- const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary");
- const bool use_multi_face = RNA_boolean_get(op->ptr, "use_multi_face");
- const bool use_non_contiguous = RNA_boolean_get(op->ptr, "use_non_contiguous");
- const bool use_verts = RNA_boolean_get(op->ptr, "use_verts");
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMVert *v;
- BMEdge *e;
- BMIter iter;
-
- if (!use_extend) {
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- }
-
- /* Selects isolated verts, and edges that do not have 2 neighboring
- * faces
- */
-
- if (em->selectmode == SCE_SELECT_FACE) {
- BKE_report(op->reports, RPT_ERROR, "Does not work in face selection mode");
- MEM_freeN(objects);
- return OPERATOR_CANCELLED;
- }
-
- if (use_verts) {
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
- if (!BM_vert_is_manifold(v)) {
- BM_vert_select_set(em->bm, v, true);
- }
- }
- }
- }
-
- if (use_wire || use_boundary || use_multi_face || use_non_contiguous) {
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- if ((use_wire && BM_edge_is_wire(e)) ||
- (use_boundary && BM_edge_is_boundary(e)) ||
- (use_non_contiguous && (BM_edge_is_manifold(e) && !BM_edge_is_contiguous(e))) ||
- (use_multi_face && (BM_edge_face_count_is_over(e, 2))))
- {
- /* check we never select perfect edge (in test above) */
- BLI_assert(!(BM_edge_is_manifold(e) && BM_edge_is_contiguous(e)));
-
- BM_edge_select_set(em->bm, e, true);
- }
- }
- }
- }
-
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- EDBM_selectmode_flush(em);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ const bool use_extend = RNA_boolean_get(op->ptr, "extend");
+ const bool use_wire = RNA_boolean_get(op->ptr, "use_wire");
+ const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary");
+ const bool use_multi_face = RNA_boolean_get(op->ptr, "use_multi_face");
+ const bool use_non_contiguous = RNA_boolean_get(op->ptr, "use_non_contiguous");
+ const bool use_verts = RNA_boolean_get(op->ptr, "use_verts");
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMVert *v;
+ BMEdge *e;
+ BMIter iter;
+
+ if (!use_extend) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ }
+
+ /* Selects isolated verts, and edges that do not have 2 neighboring
+ * faces
+ */
+
+ if (em->selectmode == SCE_SELECT_FACE) {
+ BKE_report(op->reports, RPT_ERROR, "Does not work in face selection mode");
+ MEM_freeN(objects);
+ return OPERATOR_CANCELLED;
+ }
+
+ if (use_verts) {
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
+ if (!BM_vert_is_manifold(v)) {
+ BM_vert_select_set(em->bm, v, true);
+ }
+ }
+ }
+ }
+
+ if (use_wire || use_boundary || use_multi_face || use_non_contiguous) {
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ if ((use_wire && BM_edge_is_wire(e)) || (use_boundary && BM_edge_is_boundary(e)) ||
+ (use_non_contiguous && (BM_edge_is_manifold(e) && !BM_edge_is_contiguous(e))) ||
+ (use_multi_face && (BM_edge_face_count_is_over(e, 2)))) {
+ /* check we never select perfect edge (in test above) */
+ BLI_assert(!(BM_edge_is_manifold(e) && BM_edge_is_contiguous(e)));
+
+ BM_edge_select_set(em->bm, e, true);
+ }
+ }
+ }
+ }
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ EDBM_selectmode_flush(em);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_non_manifold(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Non Manifold";
- ot->description = "Select all non-manifold vertices or edges";
- ot->idname = "MESH_OT_select_non_manifold";
-
- /* api callbacks */
- ot->exec = edbm_select_non_manifold_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend the selection");
- /* edges */
- RNA_def_boolean(ot->srna, "use_wire", true, "Wire",
- "Wire edges");
- RNA_def_boolean(ot->srna, "use_boundary", true, "Boundaries",
- "Boundary edges");
- RNA_def_boolean(ot->srna, "use_multi_face", true,
- "Multiple Faces", "Edges shared by 3+ faces");
- RNA_def_boolean(ot->srna, "use_non_contiguous", true, "Non Contiguous",
- "Edges between faces pointing in alternate directions");
- /* verts */
- RNA_def_boolean(ot->srna, "use_verts", true, "Vertices",
- "Vertices connecting multiple face regions");
+ /* identifiers */
+ ot->name = "Select Non Manifold";
+ ot->description = "Select all non-manifold vertices or edges";
+ ot->idname = "MESH_OT_select_non_manifold";
+
+ /* api callbacks */
+ ot->exec = edbm_select_non_manifold_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend the selection");
+ /* edges */
+ RNA_def_boolean(ot->srna, "use_wire", true, "Wire", "Wire edges");
+ RNA_def_boolean(ot->srna, "use_boundary", true, "Boundaries", "Boundary edges");
+ RNA_def_boolean(ot->srna, "use_multi_face", true, "Multiple Faces", "Edges shared by 3+ faces");
+ RNA_def_boolean(ot->srna,
+ "use_non_contiguous",
+ true,
+ "Non Contiguous",
+ "Edges between faces pointing in alternate directions");
+ /* verts */
+ RNA_def_boolean(
+ ot->srna, "use_verts", true, "Vertices", "Vertices connecting multiple face regions");
}
/** \} */
@@ -4160,86 +4235,87 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot)
static int edbm_select_random_exec(bContext *C, wmOperator *op)
{
- const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
- const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
- const int seed = WM_operator_properties_select_random_seed_increment_get(op);
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMIter iter;
- int seed_iter = seed;
-
- /* This gives a consistent result regardless of object order. */
- if (ob_index) {
- seed_iter += BLI_ghashutil_strhash_p(obedit->id.name);
- }
-
- RNG *rng = BLI_rng_new_srandom(seed_iter);
-
- if (em->selectmode & SCE_SELECT_VERTEX) {
- BMVert *eve;
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BLI_rng_get_float(rng) < randfac) {
- BM_vert_select_set(em->bm, eve, select);
- }
- }
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- BMEdge *eed;
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BLI_rng_get_float(rng) < randfac) {
- BM_edge_select_set(em->bm, eed, select);
- }
- }
- }
- else {
- BMFace *efa;
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BLI_rng_get_float(rng) < randfac) {
- BM_face_select_set(em->bm, efa, select);
- }
- }
- }
-
- BLI_rng_free(rng);
-
- if (select) {
- /* was EDBM_select_flush, but it over select in edge/face mode */
- EDBM_selectmode_flush(em);
- }
- else {
- EDBM_deselect_flush(em);
- }
-
- 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;
+ const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
+ const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
+ const int seed = WM_operator_properties_select_random_seed_increment_get(op);
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMIter iter;
+ int seed_iter = seed;
+
+ /* This gives a consistent result regardless of object order. */
+ if (ob_index) {
+ seed_iter += BLI_ghashutil_strhash_p(obedit->id.name);
+ }
+
+ RNG *rng = BLI_rng_new_srandom(seed_iter);
+
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ BMVert *eve;
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BLI_rng_get_float(rng) < randfac) {
+ BM_vert_select_set(em->bm, eve, select);
+ }
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ BMEdge *eed;
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BLI_rng_get_float(rng) < randfac) {
+ BM_edge_select_set(em->bm, eed, select);
+ }
+ }
+ }
+ else {
+ BMFace *efa;
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BLI_rng_get_float(rng) < randfac) {
+ BM_face_select_set(em->bm, efa, select);
+ }
+ }
+ }
+
+ BLI_rng_free(rng);
+
+ if (select) {
+ /* was EDBM_select_flush, but it over select in edge/face mode */
+ EDBM_selectmode_flush(em);
+ }
+ else {
+ EDBM_deselect_flush(em);
+ }
+
+ 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;
}
void MESH_OT_select_random(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Random";
- ot->description = "Randomly select vertices";
- ot->idname = "MESH_OT_select_random";
+ /* identifiers */
+ ot->name = "Select Random";
+ ot->description = "Randomly select vertices";
+ ot->idname = "MESH_OT_select_random";
- /* api callbacks */
- ot->exec = edbm_select_random_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_select_random_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- WM_operator_properties_select_random(ot);
+ /* props */
+ WM_operator_properties_select_random(ot);
}
/** \} */
@@ -4250,90 +4326,91 @@ void MESH_OT_select_random(wmOperatorType *ot)
static bool edbm_select_ungrouped_poll(bContext *C)
{
- if (ED_operator_editmesh(C)) {
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
-
- if ((em->selectmode & SCE_SELECT_VERTEX) == 0) {
- CTX_wm_operator_poll_msg_set(C, "Must be in vertex selection mode");
- }
- else if (BLI_listbase_is_empty(&obedit->defbase) || cd_dvert_offset == -1) {
- CTX_wm_operator_poll_msg_set(C, "No weights/vertex groups on object");
- }
- else {
- return true;
- }
- }
- return false;
+ if (ED_operator_editmesh(C)) {
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+
+ if ((em->selectmode & SCE_SELECT_VERTEX) == 0) {
+ CTX_wm_operator_poll_msg_set(C, "Must be in vertex selection mode");
+ }
+ else if (BLI_listbase_is_empty(&obedit->defbase) || cd_dvert_offset == -1) {
+ CTX_wm_operator_poll_msg_set(C, "No weights/vertex groups on object");
+ }
+ else {
+ return true;
+ }
+ }
+ return false;
}
static int edbm_select_ungrouped_exec(bContext *C, wmOperator *op)
{
- const bool extend = RNA_boolean_get(op->ptr, "extend");
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
-
- if (cd_dvert_offset == -1) {
- continue;
- }
-
- BMVert *eve;
- BMIter iter;
-
- bool changed = false;
-
- if (!extend) {
- if (em->bm->totvertsel) {
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- changed = true;
- }
- }
-
- 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);
- /* no dv or dv set with no weight */
- if (ELEM(NULL, dv, dv->dw)) {
- BM_vert_select_set(em->bm, eve, true);
- changed = true;
- }
- }
- }
-
- if (changed) {
- EDBM_selectmode_flush(em);
- 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;
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+
+ if (cd_dvert_offset == -1) {
+ continue;
+ }
+
+ BMVert *eve;
+ BMIter iter;
+
+ bool changed = false;
+
+ if (!extend) {
+ if (em->bm->totvertsel) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ changed = true;
+ }
+ }
+
+ 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);
+ /* no dv or dv set with no weight */
+ if (ELEM(NULL, dv, dv->dw)) {
+ BM_vert_select_set(em->bm, eve, true);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ EDBM_selectmode_flush(em);
+ 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;
}
void MESH_OT_select_ungrouped(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Ungrouped";
- ot->idname = "MESH_OT_select_ungrouped";
- ot->description = "Select vertices without a group";
+ /* identifiers */
+ ot->name = "Select Ungrouped";
+ ot->idname = "MESH_OT_select_ungrouped";
+ ot->description = "Select vertices without a group";
- /* api callbacks */
- ot->exec = edbm_select_ungrouped_exec;
- ot->poll = edbm_select_ungrouped_poll;
+ /* api callbacks */
+ ot->exec = edbm_select_ungrouped_exec;
+ ot->poll = edbm_select_ungrouped_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
/** \} */
@@ -4343,131 +4420,149 @@ void MESH_OT_select_ungrouped(wmOperatorType *ot)
* \{ */
enum {
- SELECT_AXIS_POS = 0,
- SELECT_AXIS_NEG = 1,
- SELECT_AXIS_ALIGN = 2,
+ SELECT_AXIS_POS = 0,
+ SELECT_AXIS_NEG = 1,
+ SELECT_AXIS_ALIGN = 2,
};
static int edbm_select_axis_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMVert *v_act = BM_mesh_active_vert_get(em->bm);
- const int orientation = RNA_enum_get(op->ptr, "orientation");
- const int axis = RNA_enum_get(op->ptr, "axis");
- const int sign = RNA_enum_get(op->ptr, "sign");
-
- if (v_act == NULL) {
- BKE_report(op->reports, RPT_WARNING, "This operator requires an active vertex (last selected)");
- return OPERATOR_CANCELLED;
- }
-
- const float limit = RNA_float_get(op->ptr, "threshold");
-
- float value;
- float axis_mat[3][3];
-
- /* 3D view variables may be NULL, (no need to check in poll function). */
- ED_transform_calc_orientation_from_type_ex(
- C, axis_mat,
- scene, CTX_wm_region_view3d(C), obedit, obedit,
- orientation, 0, V3D_AROUND_ACTIVE);
-
- const float *axis_vector = axis_mat[axis];
-
- {
- float vertex_world[3];
- mul_v3_m4v3(vertex_world, obedit->obmat, v_act->co);
- value = dot_v3v3(axis_vector, vertex_world);
- }
-
- if (sign == SELECT_AXIS_NEG) {
- value += limit;
- }
- else if (sign == SELECT_AXIS_POS) {
- value -= limit;
- }
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit_iter = objects[ob_index];
- BMEditMesh *em_iter = BKE_editmesh_from_object(obedit_iter);
- BMesh *bm = em_iter->bm;
-
- if (bm->totvert == bm->totvertsel) {
- continue;
- }
-
- BMIter iter;
- BMVert *v;
- bool changed = false;
-
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN | BM_ELEM_SELECT)) {
- float v_iter_world[3];
- mul_v3_m4v3(v_iter_world, obedit_iter->obmat, v->co);
- const float value_iter = dot_v3v3(axis_vector, v_iter_world);
- switch (sign) {
- case SELECT_AXIS_ALIGN:
- if (fabsf(value_iter - value) < limit) {
- BM_vert_select_set(bm, v, true);
- changed = true;
- }
- break;
- case SELECT_AXIS_NEG:
- if (value_iter < value) {
- BM_vert_select_set(bm, v, true);
- changed = true;
- }
- break;
- case SELECT_AXIS_POS:
- if (value_iter > value) {
- BM_vert_select_set(bm, v, true);
- changed = true;
- }
- break;
- }
- }
- }
- if (changed) {
- EDBM_selectmode_flush(em_iter);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit_iter->data);
- DEG_id_tag_update(obedit_iter->data, ID_RECALC_SELECT);
- }
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMVert *v_act = BM_mesh_active_vert_get(em->bm);
+ const int orientation = RNA_enum_get(op->ptr, "orientation");
+ const int axis = RNA_enum_get(op->ptr, "axis");
+ const int sign = RNA_enum_get(op->ptr, "sign");
+
+ if (v_act == NULL) {
+ BKE_report(
+ op->reports, RPT_WARNING, "This operator requires an active vertex (last selected)");
+ return OPERATOR_CANCELLED;
+ }
+
+ const float limit = RNA_float_get(op->ptr, "threshold");
+
+ float value;
+ float axis_mat[3][3];
+
+ /* 3D view variables may be NULL, (no need to check in poll function). */
+ ED_transform_calc_orientation_from_type_ex(C,
+ axis_mat,
+ scene,
+ CTX_wm_region_view3d(C),
+ obedit,
+ obedit,
+ orientation,
+ 0,
+ V3D_AROUND_ACTIVE);
+
+ const float *axis_vector = axis_mat[axis];
+
+ {
+ float vertex_world[3];
+ mul_v3_m4v3(vertex_world, obedit->obmat, v_act->co);
+ value = dot_v3v3(axis_vector, vertex_world);
+ }
+
+ if (sign == SELECT_AXIS_NEG) {
+ value += limit;
+ }
+ else if (sign == SELECT_AXIS_POS) {
+ value -= limit;
+ }
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit_iter = objects[ob_index];
+ BMEditMesh *em_iter = BKE_editmesh_from_object(obedit_iter);
+ BMesh *bm = em_iter->bm;
+
+ if (bm->totvert == bm->totvertsel) {
+ continue;
+ }
+
+ BMIter iter;
+ BMVert *v;
+ bool changed = false;
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN | BM_ELEM_SELECT)) {
+ float v_iter_world[3];
+ mul_v3_m4v3(v_iter_world, obedit_iter->obmat, v->co);
+ const float value_iter = dot_v3v3(axis_vector, v_iter_world);
+ switch (sign) {
+ case SELECT_AXIS_ALIGN:
+ if (fabsf(value_iter - value) < limit) {
+ BM_vert_select_set(bm, v, true);
+ changed = true;
+ }
+ break;
+ case SELECT_AXIS_NEG:
+ if (value_iter < value) {
+ BM_vert_select_set(bm, v, true);
+ changed = true;
+ }
+ break;
+ case SELECT_AXIS_POS:
+ if (value_iter > value) {
+ BM_vert_select_set(bm, v, true);
+ changed = true;
+ }
+ break;
+ }
+ }
+ }
+ if (changed) {
+ EDBM_selectmode_flush(em_iter);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit_iter->data);
+ DEG_id_tag_update(obedit_iter->data, ID_RECALC_SELECT);
+ }
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_axis(wmOperatorType *ot)
{
- static const EnumPropertyItem axis_sign_items[] = {
- {SELECT_AXIS_POS, "POS", 0, "Positive Axis", ""},
- {SELECT_AXIS_NEG, "NEG", 0, "Negative Axis", ""},
- {SELECT_AXIS_ALIGN, "ALIGN", 0, "Aligned Axis", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Select Axis";
- ot->description = "Select all data in the mesh on a single axis";
- ot->idname = "MESH_OT_select_axis";
-
- /* api callbacks */
- ot->exec = edbm_select_axis_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "orientation", rna_enum_transform_orientation_items, V3D_ORIENT_LOCAL, "Axis Mode", "Axis orientation");
- RNA_def_enum(ot->srna, "sign", axis_sign_items, SELECT_AXIS_POS, "Axis Sign", "Side to select");
- RNA_def_enum(ot->srna, "axis", rna_enum_axis_xyz_items, 0, "Axis", "Select the axis to compare each vertex on");
- RNA_def_float(ot->srna, "threshold", 0.0001f, 0.000001f, 50.0f, "Threshold", "", 0.00001f, 10.0f);
+ static const EnumPropertyItem axis_sign_items[] = {
+ {SELECT_AXIS_POS, "POS", 0, "Positive Axis", ""},
+ {SELECT_AXIS_NEG, "NEG", 0, "Negative Axis", ""},
+ {SELECT_AXIS_ALIGN, "ALIGN", 0, "Aligned Axis", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Select Axis";
+ ot->description = "Select all data in the mesh on a single axis";
+ ot->idname = "MESH_OT_select_axis";
+
+ /* api callbacks */
+ ot->exec = edbm_select_axis_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna,
+ "orientation",
+ rna_enum_transform_orientation_items,
+ V3D_ORIENT_LOCAL,
+ "Axis Mode",
+ "Axis orientation");
+ RNA_def_enum(ot->srna, "sign", axis_sign_items, SELECT_AXIS_POS, "Axis Sign", "Side to select");
+ RNA_def_enum(ot->srna,
+ "axis",
+ rna_enum_axis_xyz_items,
+ 0,
+ "Axis",
+ "Select the axis to compare each vertex on");
+ RNA_def_float(
+ ot->srna, "threshold", 0.0001f, 0.000001f, 50.0f, "Threshold", "", 0.00001f, 10.0f);
}
/** \} */
@@ -4478,76 +4573,77 @@ void MESH_OT_select_axis(wmOperatorType *ot)
static int edbm_region_to_loop_exec(bContext *C, wmOperator *UNUSED(op))
{
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totfacesel == 0) {
- continue;
- }
- BMFace *f;
- BMEdge *e;
- BMIter iter;
-
- BM_mesh_elem_hflag_disable_all(em->bm, BM_EDGE, BM_ELEM_TAG, false);
-
- BM_ITER_MESH(f, &iter, em->bm, BM_FACES_OF_MESH) {
- BMLoop *l1, *l2;
- BMIter liter1, liter2;
-
- BM_ITER_ELEM(l1, &liter1, f, BM_LOOPS_OF_FACE) {
- int tot = 0, totsel = 0;
-
- BM_ITER_ELEM(l2, &liter2, l1->e, BM_LOOPS_OF_EDGE) {
- tot++;
- totsel += BM_elem_flag_test(l2->f, BM_ELEM_SELECT) != 0;
- }
-
- if ((tot != totsel && totsel > 0) || (totsel == 1 && tot == 1))
- BM_elem_flag_enable(l1->e, BM_ELEM_TAG);
- }
- }
-
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
-
- BM_ITER_MESH(e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BM_edge_select_set(em->bm, e, true);
- }
- }
-
- /* If in face-only select mode, switch to edge select mode so that
- * an edge-only selection is not inconsistent state */
- if (em->selectmode == SCE_SELECT_FACE) {
- em->selectmode = SCE_SELECT_EDGE;
- EDBM_selectmode_set(em);
- EDBM_selectmode_to_scene(C);
- }
-
- 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;
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
+ BMFace *f;
+ BMEdge *e;
+ BMIter iter;
+
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_EDGE, BM_ELEM_TAG, false);
+
+ BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
+ BMLoop *l1, *l2;
+ BMIter liter1, liter2;
+
+ BM_ITER_ELEM (l1, &liter1, f, BM_LOOPS_OF_FACE) {
+ int tot = 0, totsel = 0;
+
+ BM_ITER_ELEM (l2, &liter2, l1->e, BM_LOOPS_OF_EDGE) {
+ tot++;
+ totsel += BM_elem_flag_test(l2->f, BM_ELEM_SELECT) != 0;
+ }
+
+ if ((tot != totsel && totsel > 0) || (totsel == 1 && tot == 1))
+ BM_elem_flag_enable(l1->e, BM_ELEM_TAG);
+ }
+ }
+
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BM_edge_select_set(em->bm, e, true);
+ }
+ }
+
+ /* If in face-only select mode, switch to edge select mode so that
+ * an edge-only selection is not inconsistent state */
+ if (em->selectmode == SCE_SELECT_FACE) {
+ em->selectmode = SCE_SELECT_EDGE;
+ EDBM_selectmode_set(em);
+ EDBM_selectmode_to_scene(C);
+ }
+
+ 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;
}
void MESH_OT_region_to_loop(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Boundary Loop";
- ot->idname = "MESH_OT_region_to_loop";
- ot->description = "Select boundary edges around the selected faces";
+ /* identifiers */
+ ot->name = "Select Boundary Loop";
+ ot->idname = "MESH_OT_region_to_loop";
+ ot->description = "Select boundary edges around the selected faces";
- /* api callbacks */
- ot->exec = edbm_region_to_loop_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_region_to_loop_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -4556,61 +4652,61 @@ void MESH_OT_region_to_loop(wmOperatorType *ot)
/** \name Select Loop to Region Operator
* \{ */
-static int loop_find_region(
- BMLoop *l, int flag,
- GSet *visit_face_set, BMFace ***region_out)
+static int loop_find_region(BMLoop *l, int flag, GSet *visit_face_set, BMFace ***region_out)
{
- BMFace **region = NULL;
- BMFace **stack = NULL;
- BLI_array_declare(region);
- BLI_array_declare(stack);
- BMFace *f;
-
- BLI_array_append(stack, l->f);
- BLI_gset_insert(visit_face_set, l->f);
-
- while (BLI_array_len(stack) > 0) {
- BMIter liter1, liter2;
- BMLoop *l1, *l2;
-
- f = BLI_array_pop(stack);
- BLI_array_append(region, f);
-
- BM_ITER_ELEM (l1, &liter1, f, BM_LOOPS_OF_FACE) {
- if (BM_elem_flag_test(l1->e, flag))
- continue;
-
- BM_ITER_ELEM (l2, &liter2, l1->e, BM_LOOPS_OF_EDGE) {
- /* avoids finding same region twice
- * (otherwise) the logic works fine without */
- if (BM_elem_flag_test(l2->f, BM_ELEM_TAG)) {
- continue;
- }
-
- if (BLI_gset_add(visit_face_set, l2->f)) {
- BLI_array_append(stack, l2->f);
- }
- }
- }
- }
-
- BLI_array_free(stack);
-
- *region_out = region;
- return BLI_array_len(region);
+ BMFace **region = NULL;
+ BMFace **stack = NULL;
+ BLI_array_declare(region);
+ BLI_array_declare(stack);
+ BMFace *f;
+
+ BLI_array_append(stack, l->f);
+ BLI_gset_insert(visit_face_set, l->f);
+
+ while (BLI_array_len(stack) > 0) {
+ BMIter liter1, liter2;
+ BMLoop *l1, *l2;
+
+ f = BLI_array_pop(stack);
+ BLI_array_append(region, f);
+
+ BM_ITER_ELEM (l1, &liter1, f, BM_LOOPS_OF_FACE) {
+ if (BM_elem_flag_test(l1->e, flag))
+ continue;
+
+ BM_ITER_ELEM (l2, &liter2, l1->e, BM_LOOPS_OF_EDGE) {
+ /* avoids finding same region twice
+ * (otherwise) the logic works fine without */
+ if (BM_elem_flag_test(l2->f, BM_ELEM_TAG)) {
+ continue;
+ }
+
+ if (BLI_gset_add(visit_face_set, l2->f)) {
+ BLI_array_append(stack, l2->f);
+ }
+ }
+ }
+ }
+
+ BLI_array_free(stack);
+
+ *region_out = region;
+ return BLI_array_len(region);
}
static int verg_radial(const void *va, const void *vb)
{
- const BMEdge *e_a = *((const BMEdge **)va);
- const BMEdge *e_b = *((const BMEdge **)vb);
+ const BMEdge *e_a = *((const BMEdge **)va);
+ const BMEdge *e_b = *((const BMEdge **)vb);
- const int a = BM_edge_face_count(e_a);
- const int b = BM_edge_face_count(e_b);
+ const int a = BM_edge_face_count(e_a);
+ const int b = BM_edge_face_count(e_b);
- if (a > b) return -1;
- if (a < b) return 1;
- return 0;
+ if (a > b)
+ return -1;
+ if (a < b)
+ return 1;
+ return 0;
}
/**
@@ -4621,143 +4717,148 @@ static int verg_radial(const void *va, const void *vb)
*/
static int loop_find_regions(BMEditMesh *em, const bool selbigger)
{
- GSet *visit_face_set;
- BMIter iter;
- const int edges_len = em->bm->totedgesel;
- BMEdge *e, **edges;
- int count = 0, i;
-
- visit_face_set = BLI_gset_ptr_new_ex(__func__, edges_len);
- edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__);
-
- i = 0;
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- edges[i++] = e;
- BM_elem_flag_enable(e, BM_ELEM_TAG);
- }
- else {
- BM_elem_flag_disable(e, BM_ELEM_TAG);
- }
- }
-
- /* sort edges by radial cycle length */
- qsort(edges, edges_len, sizeof(*edges), verg_radial);
-
- for (i = 0; i < edges_len; i++) {
- BMIter liter;
- BMLoop *l;
- BMFace **region = NULL, **region_out;
- int c, tot = 0;
-
- e = edges[i];
-
- if (!BM_elem_flag_test(e, BM_ELEM_TAG))
- continue;
-
- BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) {
- if (BLI_gset_haskey(visit_face_set, l->f))
- continue;
-
- c = loop_find_region(l, BM_ELEM_SELECT, visit_face_set, &region_out);
-
- if (!region || (selbigger ? c >= tot : c < tot)) {
- /* this region is the best seen so far */
- tot = c;
- if (region) {
- /* free the previous best */
- MEM_freeN(region);
- }
- /* track the current region as the new best */
- region = region_out;
- }
- else {
- /* this region is not as good as best so far, just free it */
- MEM_freeN(region_out);
- }
- }
-
- if (region) {
- int j;
-
- for (j = 0; j < tot; j++) {
- BM_elem_flag_enable(region[j], BM_ELEM_TAG);
- BM_ITER_ELEM (l, &liter, region[j], BM_LOOPS_OF_FACE) {
- BM_elem_flag_disable(l->e, BM_ELEM_TAG);
- }
- }
-
- count += tot;
-
- MEM_freeN(region);
- }
- }
-
- MEM_freeN(edges);
- BLI_gset_free(visit_face_set, NULL);
-
- return count;
+ GSet *visit_face_set;
+ BMIter iter;
+ const int edges_len = em->bm->totedgesel;
+ BMEdge *e, **edges;
+ int count = 0, i;
+
+ visit_face_set = BLI_gset_ptr_new_ex(__func__, edges_len);
+ edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__);
+
+ i = 0;
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ edges[i++] = e;
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ }
+ else {
+ BM_elem_flag_disable(e, BM_ELEM_TAG);
+ }
+ }
+
+ /* sort edges by radial cycle length */
+ qsort(edges, edges_len, sizeof(*edges), verg_radial);
+
+ for (i = 0; i < edges_len; i++) {
+ BMIter liter;
+ BMLoop *l;
+ BMFace **region = NULL, **region_out;
+ int c, tot = 0;
+
+ e = edges[i];
+
+ if (!BM_elem_flag_test(e, BM_ELEM_TAG))
+ continue;
+
+ BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) {
+ if (BLI_gset_haskey(visit_face_set, l->f))
+ continue;
+
+ c = loop_find_region(l, BM_ELEM_SELECT, visit_face_set, &region_out);
+
+ if (!region || (selbigger ? c >= tot : c < tot)) {
+ /* this region is the best seen so far */
+ tot = c;
+ if (region) {
+ /* free the previous best */
+ MEM_freeN(region);
+ }
+ /* track the current region as the new best */
+ region = region_out;
+ }
+ else {
+ /* this region is not as good as best so far, just free it */
+ MEM_freeN(region_out);
+ }
+ }
+
+ if (region) {
+ int j;
+
+ for (j = 0; j < tot; j++) {
+ BM_elem_flag_enable(region[j], BM_ELEM_TAG);
+ BM_ITER_ELEM (l, &liter, region[j], BM_LOOPS_OF_FACE) {
+ BM_elem_flag_disable(l->e, BM_ELEM_TAG);
+ }
+ }
+
+ count += tot;
+
+ MEM_freeN(region);
+ }
+ }
+
+ MEM_freeN(edges);
+ BLI_gset_free(visit_face_set, NULL);
+
+ return count;
}
static int edbm_loop_to_region_exec(bContext *C, wmOperator *op)
{
- const bool select_bigger = RNA_boolean_get(op->ptr, "select_bigger");
+ const bool select_bigger = RNA_boolean_get(op->ptr, "select_bigger");
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totedgesel == 0) {
- continue;
- }
+ if (em->bm->totedgesel == 0) {
+ continue;
+ }
- BMIter iter;
- BMFace *f;
+ BMIter iter;
+ BMFace *f;
- /* find the set of regions with smallest number of total faces */
- BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
- const int a = loop_find_regions(em, select_bigger);
- const int b = loop_find_regions(em, !select_bigger);
+ /* find the set of regions with smallest number of total faces */
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
+ const int a = loop_find_regions(em, select_bigger);
+ const int b = loop_find_regions(em, !select_bigger);
- BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
- loop_find_regions(em, ((a <= b) != select_bigger) ? select_bigger : !select_bigger);
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
+ loop_find_regions(em, ((a <= b) != select_bigger) ? select_bigger : !select_bigger);
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BM_ITER_MESH(f, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_TAG) && !BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- BM_face_select_set(em->bm, f, true);
- }
- }
+ BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_TAG) && !BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ BM_face_select_set(em->bm, f, true);
+ }
+ }
- EDBM_selectmode_flush(em);
+ EDBM_selectmode_flush(em);
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- MEM_freeN(objects);
+ 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;
+ return OPERATOR_FINISHED;
}
void MESH_OT_loop_to_region(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Loop Inner-Region";
- ot->idname = "MESH_OT_loop_to_region";
- ot->description = "Select region of faces inside of a selected loop of edges";
-
- /* api callbacks */
- ot->exec = edbm_loop_to_region_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "select_bigger", 0, "Select Bigger", "Select bigger regions instead of smaller ones");
+ /* identifiers */
+ ot->name = "Select Loop Inner-Region";
+ ot->idname = "MESH_OT_loop_to_region";
+ ot->description = "Select region of faces inside of a selected loop of edges";
+
+ /* api callbacks */
+ ot->exec = edbm_loop_to_region_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna,
+ "select_bigger",
+ 0,
+ "Select Bigger",
+ "Select bigger regions instead of smaller ones");
}
/** \} */
diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c
index 67e455375df..3006e2ed73d 100644
--- a/source/blender/editors/mesh/editmesh_select_similar.c
+++ b/source/blender/editors/mesh/editmesh_select_similar.c
@@ -45,66 +45,66 @@
#include "ED_screen.h"
#include "ED_select_utils.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Select Similar (Vert/Edge/Face) Operator - common
* \{ */
static const EnumPropertyItem prop_similar_compare_types[] = {
- {SIM_CMP_EQ, "EQUAL", 0, "Equal", ""},
- {SIM_CMP_GT, "GREATER", 0, "Greater", ""},
- {SIM_CMP_LT, "LESS", 0, "Less", ""},
+ {SIM_CMP_EQ, "EQUAL", 0, "Equal", ""},
+ {SIM_CMP_GT, "GREATER", 0, "Greater", ""},
+ {SIM_CMP_LT, "LESS", 0, "Less", ""},
- {0, NULL, 0, NULL, NULL},
+ {0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem prop_similar_types[] = {
- {SIMVERT_NORMAL, "NORMAL", 0, "Normal", ""},
- {SIMVERT_FACE, "FACE", 0, "Amount of Adjacent Faces", ""},
- {SIMVERT_VGROUP, "VGROUP", 0, "Vertex Groups", ""},
- {SIMVERT_EDGE, "EDGE", 0, "Amount of connecting edges", ""},
-
- {SIMEDGE_LENGTH, "LENGTH", 0, "Length", ""},
- {SIMEDGE_DIR, "DIR", 0, "Direction", ""},
- {SIMEDGE_FACE, "FACE", 0, "Amount of Faces Around an Edge", ""},
- {SIMEDGE_FACE_ANGLE, "FACE_ANGLE", 0, "Face Angles", ""},
- {SIMEDGE_CREASE, "CREASE", 0, "Crease", ""},
- {SIMEDGE_BEVEL, "BEVEL", 0, "Bevel", ""},
- {SIMEDGE_SEAM, "SEAM", 0, "Seam", ""},
- {SIMEDGE_SHARP, "SHARP", 0, "Sharpness", ""},
+ {SIMVERT_NORMAL, "NORMAL", 0, "Normal", ""},
+ {SIMVERT_FACE, "FACE", 0, "Amount of Adjacent Faces", ""},
+ {SIMVERT_VGROUP, "VGROUP", 0, "Vertex Groups", ""},
+ {SIMVERT_EDGE, "EDGE", 0, "Amount of connecting edges", ""},
+
+ {SIMEDGE_LENGTH, "LENGTH", 0, "Length", ""},
+ {SIMEDGE_DIR, "DIR", 0, "Direction", ""},
+ {SIMEDGE_FACE, "FACE", 0, "Amount of Faces Around an Edge", ""},
+ {SIMEDGE_FACE_ANGLE, "FACE_ANGLE", 0, "Face Angles", ""},
+ {SIMEDGE_CREASE, "CREASE", 0, "Crease", ""},
+ {SIMEDGE_BEVEL, "BEVEL", 0, "Bevel", ""},
+ {SIMEDGE_SEAM, "SEAM", 0, "Seam", ""},
+ {SIMEDGE_SHARP, "SHARP", 0, "Sharpness", ""},
#ifdef WITH_FREESTYLE
- {SIMEDGE_FREESTYLE, "FREESTYLE_EDGE", 0, "Freestyle Edge Marks", ""},
+ {SIMEDGE_FREESTYLE, "FREESTYLE_EDGE", 0, "Freestyle Edge Marks", ""},
#endif
- {SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""},
- {SIMFACE_AREA, "AREA", 0, "Area", ""},
- {SIMFACE_SIDES, "SIDES", 0, "Polygon Sides", ""},
- {SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""},
- {SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""},
- {SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""},
- {SIMFACE_SMOOTH, "SMOOTH", 0, "Flat/Smooth", ""},
- {SIMFACE_FACEMAP, "FACE_MAP", 0, "Face-Map", ""},
+ {SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""},
+ {SIMFACE_AREA, "AREA", 0, "Area", ""},
+ {SIMFACE_SIDES, "SIDES", 0, "Polygon Sides", ""},
+ {SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""},
+ {SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""},
+ {SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""},
+ {SIMFACE_SMOOTH, "SMOOTH", 0, "Flat/Smooth", ""},
+ {SIMFACE_FACEMAP, "FACE_MAP", 0, "Face-Map", ""},
#ifdef WITH_FREESTYLE
- {SIMFACE_FREESTYLE, "FREESTYLE_FACE", 0, "Freestyle Face Marks", ""},
+ {SIMFACE_FREESTYLE, "FREESTYLE_FACE", 0, "Freestyle Face Marks", ""},
#endif
- {0, NULL, 0, NULL, NULL},
+ {0, NULL, 0, NULL, NULL},
};
static int mesh_select_similar_compare_int(const int delta, const int compare)
{
- switch (compare) {
- case SIM_CMP_EQ:
- return (delta == 0);
- case SIM_CMP_GT:
- return (delta > 0);
- case SIM_CMP_LT:
- return (delta < 0);
- default:
- BLI_assert(0);
- return 0;
- }
+ switch (compare) {
+ case SIM_CMP_EQ:
+ return (delta == 0);
+ case SIM_CMP_GT:
+ return (delta > 0);
+ case SIM_CMP_LT:
+ return (delta < 0);
+ default:
+ BLI_assert(0);
+ return 0;
+ }
}
/** \} */
@@ -114,10 +114,10 @@ static int mesh_select_similar_compare_int(const int delta, const int compare)
* \{ */
enum {
- SIMFACE_DATA_NONE = 0,
- SIMFACE_DATA_TRUE = (1 << 0),
- SIMFACE_DATA_FALSE = (1 << 1),
- SIMFACE_DATA_ALL = (SIMFACE_DATA_TRUE | SIMFACE_DATA_FALSE),
+ SIMFACE_DATA_NONE = 0,
+ SIMFACE_DATA_TRUE = (1 << 0),
+ SIMFACE_DATA_FALSE = (1 << 1),
+ SIMFACE_DATA_ALL = (SIMFACE_DATA_TRUE | SIMFACE_DATA_FALSE),
};
/**
@@ -127,14 +127,14 @@ enum {
*/
static bool face_data_value_set(BMFace *face, const int hflag, int *r_value)
{
- if (BM_elem_flag_test(face, hflag)) {
- *r_value |= SIMFACE_DATA_TRUE;
- }
- else {
- *r_value |= SIMFACE_DATA_FALSE;
- }
-
- return *r_value != SIMFACE_DATA_ALL;
+ if (BM_elem_flag_test(face, hflag)) {
+ *r_value |= SIMFACE_DATA_TRUE;
+ }
+ else {
+ *r_value |= SIMFACE_DATA_FALSE;
+ }
+
+ return *r_value != SIMFACE_DATA_ALL;
}
/**
@@ -142,12 +142,12 @@ static bool face_data_value_set(BMFace *face, const int hflag, int *r_value)
*/
static void face_to_plane(const Object *ob, BMFace *face, float r_plane[4])
{
- float normal[3], co[3];
- copy_v3_v3(normal, face->no);
- mul_transposed_mat3_m4_v3(ob->imat, normal);
- normalize_v3(normal);
- mul_v3_m4v3(co, ob->obmat, BM_FACE_FIRST_LOOP(face)->v->co);
- plane_from_point_normal_v3(r_plane, co, normal);
+ float normal[3], co[3];
+ copy_v3_v3(normal, face->no);
+ mul_transposed_mat3_m4_v3(ob->imat, normal);
+ normalize_v3(normal);
+ mul_v3_m4v3(co, ob->obmat, BM_FACE_FIRST_LOOP(face)->v->co);
+ plane_from_point_normal_v3(r_plane, co, normal);
}
/* TODO(dfelinto): `types` that should technically be compared in world space but are not:
@@ -156,418 +156,390 @@ static void face_to_plane(const Object *ob, BMFace *face, float r_plane[4])
*/
static int similar_face_select_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- const int type = RNA_enum_get(op->ptr, "type");
- const float thresh = RNA_float_get(op->ptr, "threshold");
- const float thresh_radians = thresh * (float)M_PI;
- const int compare = RNA_enum_get(op->ptr, "compare");
-
- int tot_faces_selected_all = 0;
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- tot_faces_selected_all += em->bm->totfacesel;
- }
-
- if (tot_faces_selected_all == 0) {
- BKE_report(op->reports, RPT_ERROR, "No face selected");
- MEM_freeN(objects);
- return OPERATOR_CANCELLED;
- }
-
- KDTree_1d *tree_1d = NULL;
- KDTree_3d *tree_3d = NULL;
- KDTree_4d *tree_4d = NULL;
- GSet *gset = NULL;
- GSet **gset_array = NULL;
- int face_data_value = SIMFACE_DATA_NONE;
-
- switch (type) {
- case SIMFACE_AREA:
- case SIMFACE_PERIMETER:
- tree_1d = BLI_kdtree_1d_new(tot_faces_selected_all);
- break;
- case SIMFACE_NORMAL:
- tree_3d = BLI_kdtree_3d_new(tot_faces_selected_all);
- break;
- case SIMFACE_COPLANAR:
- tree_4d = BLI_kdtree_4d_new(tot_faces_selected_all);
- break;
- case SIMFACE_SIDES:
- case SIMFACE_MATERIAL:
- gset = BLI_gset_ptr_new("Select similar face");
- break;
- case SIMFACE_FACEMAP:
- gset_array = MEM_callocN(sizeof(GSet *) * objects_len, "Select similar face: facemap gset array");
- break;
- }
-
- int tree_index = 0;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em->bm;
- Material ***material_array = NULL;
- invert_m4_m4(ob->imat, ob->obmat);
- int custom_data_offset = 0;
-
- if (bm->totfacesel == 0) {
- continue;
- }
-
- float ob_m3[3][3];
- copy_m3_m4(ob_m3, ob->obmat);
-
- switch (type) {
- case SIMFACE_MATERIAL:
- {
- if (ob->totcol == 0) {
- continue;
- }
- material_array = give_matarar(ob);
- break;
- }
- case SIMFACE_FREESTYLE:
- {
- if (!CustomData_has_layer(&bm->pdata, CD_FREESTYLE_FACE)) {
- face_data_value |= SIMFACE_DATA_FALSE;
- continue;
- }
- break;
- }
- case SIMFACE_FACEMAP:
- {
- custom_data_offset = CustomData_get_offset(&bm->pdata, CD_FACEMAP);
- if (custom_data_offset == -1) {
- continue;
- }
- else {
- gset_array[ob_index] = BLI_gset_ptr_new("Select similar face: facemap gset");
- }
- }
- }
-
- BMFace *face; /* Mesh face. */
- BMIter iter; /* Selected faces iterator. */
-
- BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(face, BM_ELEM_SELECT)) {
- switch (type) {
- case SIMFACE_SIDES:
- BLI_gset_add(gset, POINTER_FROM_INT(face->len));
- break;
- case SIMFACE_MATERIAL:
- {
- Material *material = (*material_array)[face->mat_nr];
- if (material != NULL) {
- BLI_gset_add(gset, material);
- }
- break;
- }
- case SIMFACE_AREA:
- {
- float area = BM_face_calc_area_with_mat3(face, ob_m3);
- BLI_kdtree_1d_insert(tree_1d, tree_index++, &area);
- break;
- }
- case SIMFACE_PERIMETER:
- {
- float perimeter = BM_face_calc_perimeter_with_mat3(face, ob_m3);
- BLI_kdtree_1d_insert(tree_1d, tree_index++, &perimeter);
- break;
- }
- case SIMFACE_NORMAL:
- {
- float normal[3];
- copy_v3_v3(normal, face->no);
- mul_transposed_mat3_m4_v3(ob->imat, normal);
- normalize_v3(normal);
- BLI_kdtree_3d_insert(tree_3d, tree_index++, normal);
- break;
- }
- case SIMFACE_COPLANAR:
- {
- float plane[4];
- face_to_plane(ob, face, plane);
- BLI_kdtree_4d_insert(tree_4d, tree_index++, plane);
- break;
- }
- case SIMFACE_SMOOTH:
- {
- if (!face_data_value_set(face, BM_ELEM_SMOOTH, &face_data_value)) {
- goto face_select_all;
- }
- break;
- }
- case SIMFACE_FREESTYLE:
- {
- FreestyleFace *fface;
- fface = CustomData_bmesh_get(&bm->pdata, face->head.data, CD_FREESTYLE_FACE);
- if ((fface == NULL) || ((fface->flag & FREESTYLE_FACE_MARK) == 0)) {
- face_data_value |= SIMFACE_DATA_FALSE;
- }
- else {
- face_data_value |= SIMFACE_DATA_TRUE;
- }
- if (face_data_value == SIMFACE_DATA_ALL) {
- goto face_select_all;
- }
- break;
- }
- case SIMFACE_FACEMAP:
- {
- BLI_assert(custom_data_offset != -1);
- int *face_map = BM_ELEM_CD_GET_VOID_P(face, custom_data_offset);
- BLI_gset_add(gset_array[ob_index], face_map);
- break;
- }
- }
- }
- }
- }
-
- BLI_assert((type != SIMFACE_FREESTYLE) || (face_data_value != SIMFACE_DATA_NONE));
-
- if (tree_1d != NULL) {
- BLI_kdtree_1d_deduplicate(tree_1d);
- BLI_kdtree_1d_balance(tree_1d);
- }
- if (tree_3d != NULL) {
- BLI_kdtree_3d_deduplicate(tree_3d);
- BLI_kdtree_3d_balance(tree_3d);
- }
- if (tree_4d != NULL) {
- BLI_kdtree_4d_deduplicate(tree_4d);
- BLI_kdtree_4d_balance(tree_4d);
- }
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em->bm;
- bool changed = false;
- Material ***material_array = NULL;
- int custom_data_offset;
-
- float ob_m3[3][3];
- copy_m3_m4(ob_m3, ob->obmat);
-
- bool has_custom_data_layer = false;
- switch (type) {
- case SIMFACE_MATERIAL:
- {
- if (ob->totcol == 0) {
- continue;
- }
- material_array = give_matarar(ob);
- break;
- }
- case SIMFACE_FREESTYLE:
- {
- has_custom_data_layer = CustomData_has_layer(&bm->pdata, CD_FREESTYLE_FACE);
- if ((face_data_value == SIMFACE_DATA_TRUE) && !has_custom_data_layer) {
- continue;
- }
- break;
- }
- case SIMFACE_FACEMAP:
- {
- custom_data_offset = CustomData_get_offset(&bm->pdata, CD_FACEMAP);
- if (custom_data_offset == -1) {
- continue;
- }
- }
- }
-
- BMFace *face; /* Mesh face. */
- BMIter iter; /* Selected faces iterator. */
-
- BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(face, BM_ELEM_SELECT) &&
- !BM_elem_flag_test(face, BM_ELEM_HIDDEN))
- {
- bool select = false;
- switch (type) {
- case SIMFACE_SIDES:
- {
- const int num_sides = face->len;
- GSetIterator gs_iter;
- GSET_ITER(gs_iter, gset) {
- const int num_sides_iter = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter));
- const int delta_i = num_sides - num_sides_iter;
- if (mesh_select_similar_compare_int(delta_i, compare)) {
- select = true;
- break;
- }
- }
- break;
- }
- case SIMFACE_MATERIAL:
- {
- const Material *material = (*material_array)[face->mat_nr];
- if (material == NULL) {
- continue;
- }
-
- GSetIterator gs_iter;
- GSET_ITER(gs_iter, gset) {
- const Material *material_iter = BLI_gsetIterator_getKey(&gs_iter);
- if (material == material_iter) {
- select = true;
- break;
- }
- }
- break;
- }
- case SIMFACE_AREA:
- {
- float area = BM_face_calc_area_with_mat3(face, ob_m3);
- if (ED_select_similar_compare_float_tree(tree_1d, area, thresh, compare)) {
- select = true;
- }
- break;
- }
- case SIMFACE_PERIMETER:
- {
- float perimeter = BM_face_calc_perimeter_with_mat3(face, ob_m3);
- if (ED_select_similar_compare_float_tree(tree_1d, perimeter, thresh, compare)) {
- select = true;
- }
- break;
- }
- case SIMFACE_NORMAL:
- {
- float normal[3];
- copy_v3_v3(normal, face->no);
- mul_transposed_mat3_m4_v3(ob->imat, normal);
- normalize_v3(normal);
-
- /* We are treating the normals as coordinates, the "nearest" one will
- * also be the one closest to the angle. */
- KDTreeNearest_3d nearest;
- if (BLI_kdtree_3d_find_nearest(tree_3d, normal, &nearest) != -1) {
- if (angle_normalized_v3v3(normal, nearest.co) <= thresh_radians) {
- select = true;
- }
- }
- break;
- }
- case SIMFACE_COPLANAR:
- {
- float plane[4];
- face_to_plane(ob, face, plane);
-
- KDTreeNearest_4d nearest;
- if (BLI_kdtree_4d_find_nearest(tree_4d, plane, &nearest) != -1) {
- if (nearest.dist <= thresh) {
- if ((fabsf(plane[3] - nearest.co[3]) <= thresh) &&
- (angle_v3v3(plane, nearest.co) <= thresh_radians))
- {
- select = true;
- }
- }
- }
- break;
- }
- case SIMFACE_SMOOTH:
- if ((BM_elem_flag_test(face, BM_ELEM_SMOOTH) != 0) ==
- ((face_data_value & SIMFACE_DATA_TRUE) != 0))
- {
- select = true;
- }
- break;
- case SIMFACE_FREESTYLE:
- {
- FreestyleFace *fface;
-
- if (!has_custom_data_layer) {
- BLI_assert(face_data_value == SIMFACE_DATA_FALSE);
- select = true;
- break;
- }
-
- fface = CustomData_bmesh_get(&bm->pdata, face->head.data, CD_FREESTYLE_FACE);
- if (((fface != NULL) && (fface->flag & FREESTYLE_FACE_MARK)) ==
- ((face_data_value & SIMFACE_DATA_TRUE) != 0))
- {
- select = true;
- }
- break;
- }
- case SIMFACE_FACEMAP:
- {
- const int *face_map = BM_ELEM_CD_GET_VOID_P(face, custom_data_offset);
- GSetIterator gs_iter;
- GSET_ITER(gs_iter, gset_array[ob_index]) {
- const int *face_map_iter = BLI_gsetIterator_getKey(&gs_iter);
- if (*face_map == *face_map_iter) {
- select = true;
- break;
- }
- }
- break;
- }
- }
-
- if (select) {
- BM_face_select_set(bm, face, true);
- changed = true;
- }
- }
- }
-
- if (changed) {
- EDBM_selectmode_flush(em);
- EDBM_update_generic(em, false, false);
- }
- }
-
- if (false) {
-face_select_all:
- BLI_assert(ELEM(type,
- SIMFACE_SMOOTH,
- SIMFACE_FREESTYLE
- ));
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em->bm;
-
- BMFace *face; /* Mesh face. */
- BMIter iter; /* Selected faces iterator. */
-
- BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(face, BM_ELEM_SELECT)) {
- BM_face_select_set(bm, face, true);
- }
- }
- EDBM_selectmode_flush(em);
- EDBM_update_generic(em, false, false);
- }
- }
-
- MEM_freeN(objects);
- BLI_kdtree_1d_free(tree_1d);
- BLI_kdtree_3d_free(tree_3d);
- BLI_kdtree_4d_free(tree_4d);
- if (gset != NULL) {
- BLI_gset_free(gset, NULL);
- }
- if (gset_array != NULL) {
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- if (gset_array[ob_index] != NULL) {
- BLI_gset_free(gset_array[ob_index], NULL);
- }
- }
- MEM_freeN(gset_array);
- }
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ const int type = RNA_enum_get(op->ptr, "type");
+ const float thresh = RNA_float_get(op->ptr, "threshold");
+ const float thresh_radians = thresh * (float)M_PI;
+ const int compare = RNA_enum_get(op->ptr, "compare");
+
+ int tot_faces_selected_all = 0;
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ tot_faces_selected_all += em->bm->totfacesel;
+ }
+
+ if (tot_faces_selected_all == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No face selected");
+ MEM_freeN(objects);
+ return OPERATOR_CANCELLED;
+ }
+
+ KDTree_1d *tree_1d = NULL;
+ KDTree_3d *tree_3d = NULL;
+ KDTree_4d *tree_4d = NULL;
+ GSet *gset = NULL;
+ GSet **gset_array = NULL;
+ int face_data_value = SIMFACE_DATA_NONE;
+
+ switch (type) {
+ case SIMFACE_AREA:
+ case SIMFACE_PERIMETER:
+ tree_1d = BLI_kdtree_1d_new(tot_faces_selected_all);
+ break;
+ case SIMFACE_NORMAL:
+ tree_3d = BLI_kdtree_3d_new(tot_faces_selected_all);
+ break;
+ case SIMFACE_COPLANAR:
+ tree_4d = BLI_kdtree_4d_new(tot_faces_selected_all);
+ break;
+ case SIMFACE_SIDES:
+ case SIMFACE_MATERIAL:
+ gset = BLI_gset_ptr_new("Select similar face");
+ break;
+ case SIMFACE_FACEMAP:
+ gset_array = MEM_callocN(sizeof(GSet *) * objects_len,
+ "Select similar face: facemap gset array");
+ break;
+ }
+
+ int tree_index = 0;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
+ Material ***material_array = NULL;
+ invert_m4_m4(ob->imat, ob->obmat);
+ int custom_data_offset = 0;
+
+ if (bm->totfacesel == 0) {
+ continue;
+ }
+
+ float ob_m3[3][3];
+ copy_m3_m4(ob_m3, ob->obmat);
+
+ switch (type) {
+ case SIMFACE_MATERIAL: {
+ if (ob->totcol == 0) {
+ continue;
+ }
+ material_array = give_matarar(ob);
+ break;
+ }
+ case SIMFACE_FREESTYLE: {
+ if (!CustomData_has_layer(&bm->pdata, CD_FREESTYLE_FACE)) {
+ face_data_value |= SIMFACE_DATA_FALSE;
+ continue;
+ }
+ break;
+ }
+ case SIMFACE_FACEMAP: {
+ custom_data_offset = CustomData_get_offset(&bm->pdata, CD_FACEMAP);
+ if (custom_data_offset == -1) {
+ continue;
+ }
+ else {
+ gset_array[ob_index] = BLI_gset_ptr_new("Select similar face: facemap gset");
+ }
+ }
+ }
+
+ BMFace *face; /* Mesh face. */
+ BMIter iter; /* Selected faces iterator. */
+
+ BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(face, BM_ELEM_SELECT)) {
+ switch (type) {
+ case SIMFACE_SIDES:
+ BLI_gset_add(gset, POINTER_FROM_INT(face->len));
+ break;
+ case SIMFACE_MATERIAL: {
+ Material *material = (*material_array)[face->mat_nr];
+ if (material != NULL) {
+ BLI_gset_add(gset, material);
+ }
+ break;
+ }
+ case SIMFACE_AREA: {
+ float area = BM_face_calc_area_with_mat3(face, ob_m3);
+ BLI_kdtree_1d_insert(tree_1d, tree_index++, &area);
+ break;
+ }
+ case SIMFACE_PERIMETER: {
+ float perimeter = BM_face_calc_perimeter_with_mat3(face, ob_m3);
+ BLI_kdtree_1d_insert(tree_1d, tree_index++, &perimeter);
+ break;
+ }
+ case SIMFACE_NORMAL: {
+ float normal[3];
+ copy_v3_v3(normal, face->no);
+ mul_transposed_mat3_m4_v3(ob->imat, normal);
+ normalize_v3(normal);
+ BLI_kdtree_3d_insert(tree_3d, tree_index++, normal);
+ break;
+ }
+ case SIMFACE_COPLANAR: {
+ float plane[4];
+ face_to_plane(ob, face, plane);
+ BLI_kdtree_4d_insert(tree_4d, tree_index++, plane);
+ break;
+ }
+ case SIMFACE_SMOOTH: {
+ if (!face_data_value_set(face, BM_ELEM_SMOOTH, &face_data_value)) {
+ goto face_select_all;
+ }
+ break;
+ }
+ case SIMFACE_FREESTYLE: {
+ FreestyleFace *fface;
+ fface = CustomData_bmesh_get(&bm->pdata, face->head.data, CD_FREESTYLE_FACE);
+ if ((fface == NULL) || ((fface->flag & FREESTYLE_FACE_MARK) == 0)) {
+ face_data_value |= SIMFACE_DATA_FALSE;
+ }
+ else {
+ face_data_value |= SIMFACE_DATA_TRUE;
+ }
+ if (face_data_value == SIMFACE_DATA_ALL) {
+ goto face_select_all;
+ }
+ break;
+ }
+ case SIMFACE_FACEMAP: {
+ BLI_assert(custom_data_offset != -1);
+ int *face_map = BM_ELEM_CD_GET_VOID_P(face, custom_data_offset);
+ BLI_gset_add(gset_array[ob_index], face_map);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ BLI_assert((type != SIMFACE_FREESTYLE) || (face_data_value != SIMFACE_DATA_NONE));
+
+ if (tree_1d != NULL) {
+ BLI_kdtree_1d_deduplicate(tree_1d);
+ BLI_kdtree_1d_balance(tree_1d);
+ }
+ if (tree_3d != NULL) {
+ BLI_kdtree_3d_deduplicate(tree_3d);
+ BLI_kdtree_3d_balance(tree_3d);
+ }
+ if (tree_4d != NULL) {
+ BLI_kdtree_4d_deduplicate(tree_4d);
+ BLI_kdtree_4d_balance(tree_4d);
+ }
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
+ bool changed = false;
+ Material ***material_array = NULL;
+ int custom_data_offset;
+
+ float ob_m3[3][3];
+ copy_m3_m4(ob_m3, ob->obmat);
+
+ bool has_custom_data_layer = false;
+ switch (type) {
+ case SIMFACE_MATERIAL: {
+ if (ob->totcol == 0) {
+ continue;
+ }
+ material_array = give_matarar(ob);
+ break;
+ }
+ case SIMFACE_FREESTYLE: {
+ has_custom_data_layer = CustomData_has_layer(&bm->pdata, CD_FREESTYLE_FACE);
+ if ((face_data_value == SIMFACE_DATA_TRUE) && !has_custom_data_layer) {
+ continue;
+ }
+ break;
+ }
+ case SIMFACE_FACEMAP: {
+ custom_data_offset = CustomData_get_offset(&bm->pdata, CD_FACEMAP);
+ if (custom_data_offset == -1) {
+ continue;
+ }
+ }
+ }
+
+ BMFace *face; /* Mesh face. */
+ BMIter iter; /* Selected faces iterator. */
+
+ BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(face, BM_ELEM_SELECT) && !BM_elem_flag_test(face, BM_ELEM_HIDDEN)) {
+ bool select = false;
+ switch (type) {
+ case SIMFACE_SIDES: {
+ const int num_sides = face->len;
+ GSetIterator gs_iter;
+ GSET_ITER (gs_iter, gset) {
+ const int num_sides_iter = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter));
+ const int delta_i = num_sides - num_sides_iter;
+ if (mesh_select_similar_compare_int(delta_i, compare)) {
+ select = true;
+ break;
+ }
+ }
+ break;
+ }
+ case SIMFACE_MATERIAL: {
+ const Material *material = (*material_array)[face->mat_nr];
+ if (material == NULL) {
+ continue;
+ }
+
+ GSetIterator gs_iter;
+ GSET_ITER (gs_iter, gset) {
+ const Material *material_iter = BLI_gsetIterator_getKey(&gs_iter);
+ if (material == material_iter) {
+ select = true;
+ break;
+ }
+ }
+ break;
+ }
+ case SIMFACE_AREA: {
+ float area = BM_face_calc_area_with_mat3(face, ob_m3);
+ if (ED_select_similar_compare_float_tree(tree_1d, area, thresh, compare)) {
+ select = true;
+ }
+ break;
+ }
+ case SIMFACE_PERIMETER: {
+ float perimeter = BM_face_calc_perimeter_with_mat3(face, ob_m3);
+ if (ED_select_similar_compare_float_tree(tree_1d, perimeter, thresh, compare)) {
+ select = true;
+ }
+ break;
+ }
+ case SIMFACE_NORMAL: {
+ float normal[3];
+ copy_v3_v3(normal, face->no);
+ mul_transposed_mat3_m4_v3(ob->imat, normal);
+ normalize_v3(normal);
+
+ /* We are treating the normals as coordinates, the "nearest" one will
+ * also be the one closest to the angle. */
+ KDTreeNearest_3d nearest;
+ if (BLI_kdtree_3d_find_nearest(tree_3d, normal, &nearest) != -1) {
+ if (angle_normalized_v3v3(normal, nearest.co) <= thresh_radians) {
+ select = true;
+ }
+ }
+ break;
+ }
+ case SIMFACE_COPLANAR: {
+ float plane[4];
+ face_to_plane(ob, face, plane);
+
+ KDTreeNearest_4d nearest;
+ if (BLI_kdtree_4d_find_nearest(tree_4d, plane, &nearest) != -1) {
+ if (nearest.dist <= thresh) {
+ if ((fabsf(plane[3] - nearest.co[3]) <= thresh) &&
+ (angle_v3v3(plane, nearest.co) <= thresh_radians)) {
+ select = true;
+ }
+ }
+ }
+ break;
+ }
+ case SIMFACE_SMOOTH:
+ if ((BM_elem_flag_test(face, BM_ELEM_SMOOTH) != 0) ==
+ ((face_data_value & SIMFACE_DATA_TRUE) != 0)) {
+ select = true;
+ }
+ break;
+ case SIMFACE_FREESTYLE: {
+ FreestyleFace *fface;
+
+ if (!has_custom_data_layer) {
+ BLI_assert(face_data_value == SIMFACE_DATA_FALSE);
+ select = true;
+ break;
+ }
+
+ fface = CustomData_bmesh_get(&bm->pdata, face->head.data, CD_FREESTYLE_FACE);
+ if (((fface != NULL) && (fface->flag & FREESTYLE_FACE_MARK)) ==
+ ((face_data_value & SIMFACE_DATA_TRUE) != 0)) {
+ select = true;
+ }
+ break;
+ }
+ case SIMFACE_FACEMAP: {
+ const int *face_map = BM_ELEM_CD_GET_VOID_P(face, custom_data_offset);
+ GSetIterator gs_iter;
+ GSET_ITER (gs_iter, gset_array[ob_index]) {
+ const int *face_map_iter = BLI_gsetIterator_getKey(&gs_iter);
+ if (*face_map == *face_map_iter) {
+ select = true;
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ if (select) {
+ BM_face_select_set(bm, face, true);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ EDBM_selectmode_flush(em);
+ EDBM_update_generic(em, false, false);
+ }
+ }
+
+ if (false) {
+ face_select_all:
+ BLI_assert(ELEM(type, SIMFACE_SMOOTH, SIMFACE_FREESTYLE));
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
+
+ BMFace *face; /* Mesh face. */
+ BMIter iter; /* Selected faces iterator. */
+
+ BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(face, BM_ELEM_SELECT)) {
+ BM_face_select_set(bm, face, true);
+ }
+ }
+ EDBM_selectmode_flush(em);
+ EDBM_update_generic(em, false, false);
+ }
+ }
+
+ MEM_freeN(objects);
+ BLI_kdtree_1d_free(tree_1d);
+ BLI_kdtree_3d_free(tree_3d);
+ BLI_kdtree_4d_free(tree_4d);
+ if (gset != NULL) {
+ BLI_gset_free(gset, NULL);
+ }
+ if (gset_array != NULL) {
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ if (gset_array[ob_index] != NULL) {
+ BLI_gset_free(gset_array[ob_index], NULL);
+ }
+ }
+ MEM_freeN(gset_array);
+ }
+
+ return OPERATOR_FINISHED;
}
/** \} */
@@ -576,7 +548,6 @@ face_select_all:
/** \name Select Similar Edge
* \{ */
-
/**
* Note: This is not normal, but the edge direction itself and always in
* a positive quadrant (tries z, y then x).
@@ -584,48 +555,48 @@ face_select_all:
*/
static void edge_pos_direction_worldspace_get(Object *ob, BMEdge *edge, float *r_dir)
{
- float v1[3], v2[3];
- copy_v3_v3(v1, edge->v1->co);
- copy_v3_v3(v2, edge->v2->co);
-
- mul_m4_v3(ob->obmat, v1);
- mul_m4_v3(ob->obmat, v2);
-
- sub_v3_v3v3(r_dir, v1, v2);
- normalize_v3(r_dir);
-
- /* Make sure we have a consistent direction that can be checked regardless of
- * the verts order of the edges. This spares us from storing dir and -dir in the tree_3d. */
- if (fabs(r_dir[2]) < FLT_EPSILON) {
- if (fabs(r_dir[1]) < FLT_EPSILON) {
- if (r_dir[0] < 0.0f) {
- mul_v3_fl(r_dir, -1.0f);
- }
- }
- else if (r_dir[1] < 0.0f) {
- mul_v3_fl(r_dir, -1.0f);
- }
- }
- else if (r_dir[2] < 0.0f) {
- mul_v3_fl(r_dir, -1.0f);
- }
+ float v1[3], v2[3];
+ copy_v3_v3(v1, edge->v1->co);
+ copy_v3_v3(v2, edge->v2->co);
+
+ mul_m4_v3(ob->obmat, v1);
+ mul_m4_v3(ob->obmat, v2);
+
+ sub_v3_v3v3(r_dir, v1, v2);
+ normalize_v3(r_dir);
+
+ /* Make sure we have a consistent direction that can be checked regardless of
+ * the verts order of the edges. This spares us from storing dir and -dir in the tree_3d. */
+ if (fabs(r_dir[2]) < FLT_EPSILON) {
+ if (fabs(r_dir[1]) < FLT_EPSILON) {
+ if (r_dir[0] < 0.0f) {
+ mul_v3_fl(r_dir, -1.0f);
+ }
+ }
+ else if (r_dir[1] < 0.0f) {
+ mul_v3_fl(r_dir, -1.0f);
+ }
+ }
+ else if (r_dir[2] < 0.0f) {
+ mul_v3_fl(r_dir, -1.0f);
+ }
}
static float edge_length_squared_worldspace_get(Object *ob, BMEdge *edge)
{
- float v1[3], v2[3];
+ float v1[3], v2[3];
- mul_v3_mat3_m4v3(v1, ob->obmat, edge->v1->co);
- mul_v3_mat3_m4v3(v2, ob->obmat, edge->v2->co);
+ mul_v3_mat3_m4v3(v1, ob->obmat, edge->v1->co);
+ mul_v3_mat3_m4v3(v2, ob->obmat, edge->v2->co);
- return len_squared_v3v3(v1, v2);
+ return len_squared_v3v3(v1, v2);
}
enum {
- SIMEDGE_DATA_NONE = 0,
- SIMEDGE_DATA_TRUE = (1 << 0),
- SIMEDGE_DATA_FALSE = (1 << 1),
- SIMEDGE_DATA_ALL = (SIMEDGE_DATA_TRUE | SIMEDGE_DATA_FALSE),
+ SIMEDGE_DATA_NONE = 0,
+ SIMEDGE_DATA_TRUE = (1 << 0),
+ SIMEDGE_DATA_FALSE = (1 << 1),
+ SIMEDGE_DATA_ALL = (SIMEDGE_DATA_TRUE | SIMEDGE_DATA_FALSE),
};
/**
@@ -635,14 +606,14 @@ enum {
*/
static bool edge_data_value_set(BMEdge *edge, const int hflag, int *r_value)
{
- if (BM_elem_flag_test(edge, hflag)) {
- *r_value |= SIMEDGE_DATA_TRUE;
- }
- else {
- *r_value |= SIMEDGE_DATA_FALSE;
- }
-
- return *r_value != SIMEDGE_DATA_ALL;
+ if (BM_elem_flag_test(edge, hflag)) {
+ *r_value |= SIMEDGE_DATA_TRUE;
+ }
+ else {
+ *r_value |= SIMEDGE_DATA_FALSE;
+ }
+
+ return *r_value != SIMEDGE_DATA_ALL;
}
/* TODO(dfelinto): `types` that should technically be compared in world space but are not:
@@ -650,357 +621,336 @@ static bool edge_data_value_set(BMEdge *edge, const int hflag, int *r_value)
*/
static int similar_edge_select_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- const int type = RNA_enum_get(op->ptr, "type");
- const float thresh = RNA_float_get(op->ptr, "threshold");
- const float thresh_radians = thresh * (float)M_PI + FLT_EPSILON;
- const int compare = RNA_enum_get(op->ptr, "compare");
- int custom_data_type = -1;
-
- int tot_edges_selected_all = 0;
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- tot_edges_selected_all += em->bm->totedgesel;
- }
-
- if (tot_edges_selected_all == 0) {
- BKE_report(op->reports, RPT_ERROR, "No edge selected");
- MEM_freeN(objects);
- return OPERATOR_CANCELLED;
- }
-
- KDTree_1d *tree_1d = NULL;
- KDTree_3d *tree_3d = NULL;
- GSet *gset = NULL;
- int edge_data_value = SIMEDGE_DATA_NONE;
-
- switch (type) {
- case SIMEDGE_CREASE:
- case SIMEDGE_BEVEL:
- case SIMEDGE_FACE_ANGLE:
- case SIMEDGE_LENGTH:
- tree_1d = BLI_kdtree_1d_new(tot_edges_selected_all);
- break;
- case SIMEDGE_DIR:
- tree_3d = BLI_kdtree_3d_new(tot_edges_selected_all);
- break;
- case SIMEDGE_FACE:
- gset = BLI_gset_ptr_new("Select similar edge: face");
- break;
- }
-
- switch (type) {
- case SIMEDGE_CREASE:
- custom_data_type = CD_CREASE;
- break;
- case SIMEDGE_BEVEL:
- custom_data_type = CD_BWEIGHT;
- break;
- }
-
- int tree_index = 0;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em->bm;
-
- if (bm->totedgesel == 0) {
- continue;
- }
-
- switch (type) {
- case SIMEDGE_FREESTYLE:
- {
- if (!CustomData_has_layer(&bm->edata, CD_FREESTYLE_EDGE)) {
- edge_data_value |= SIMEDGE_DATA_FALSE;
- continue;
- }
- break;
- }
- case SIMEDGE_CREASE:
- case SIMEDGE_BEVEL:
- {
- if (!CustomData_has_layer(&bm->edata, custom_data_type)) {
- BLI_kdtree_1d_insert(tree_1d, tree_index++, (float[1]){0.0f});
- continue;
- }
- break;
- }
- }
-
- float ob_m3[3][3], ob_m3_inv[3][3];
- copy_m3_m4(ob_m3, ob->obmat);
- invert_m3_m3(ob_m3_inv, ob_m3);
-
- BMEdge *edge; /* Mesh edge. */
- BMIter iter; /* Selected edges iterator. */
-
- BM_ITER_MESH (edge, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(edge, BM_ELEM_SELECT)) {
- switch (type) {
- case SIMEDGE_FACE:
- BLI_gset_add(gset, POINTER_FROM_INT(BM_edge_face_count(edge)));
- break;
- case SIMEDGE_DIR:
- {
- float dir[3];
- edge_pos_direction_worldspace_get(ob, edge, dir);
- BLI_kdtree_3d_insert(tree_3d, tree_index++, dir);
- break;
- }
- case SIMEDGE_LENGTH:
- {
- float length = edge_length_squared_worldspace_get(ob, edge);
- BLI_kdtree_1d_insert(tree_1d, tree_index++, &length);
- break;
- }
- case SIMEDGE_FACE_ANGLE:
- {
- if (BM_edge_face_count_at_most(edge, 2) == 2) {
- float angle = BM_edge_calc_face_angle_with_imat3(edge, ob_m3_inv);
- BLI_kdtree_1d_insert(tree_1d, tree_index++, &angle);
- }
- break;
- }
- case SIMEDGE_SEAM:
- if (!edge_data_value_set(edge, BM_ELEM_SEAM, &edge_data_value)) {
- goto edge_select_all;
- }
- break;
- case SIMEDGE_SHARP:
- if (!edge_data_value_set(edge, BM_ELEM_SMOOTH, &edge_data_value)) {
- goto edge_select_all;
- }
- break;
- case SIMEDGE_FREESTYLE:
- {
- FreestyleEdge *fedge;
- fedge = CustomData_bmesh_get(&bm->edata, edge->head.data, CD_FREESTYLE_EDGE);
- if ((fedge == NULL) || ((fedge->flag & FREESTYLE_EDGE_MARK) == 0)) {
- edge_data_value |= SIMEDGE_DATA_FALSE;
- }
- else {
- edge_data_value |= SIMEDGE_DATA_TRUE;
- }
- if (edge_data_value == SIMEDGE_DATA_ALL) {
- goto edge_select_all;
- }
- break;
- }
- case SIMEDGE_CREASE:
- case SIMEDGE_BEVEL:
- {
- const float *value = CustomData_bmesh_get(&bm->edata, edge->head.data, custom_data_type);
- BLI_kdtree_1d_insert(tree_1d, tree_index++, value);
- break;
- }
- }
- }
- }
- }
-
- BLI_assert((type != SIMEDGE_FREESTYLE) || (edge_data_value != SIMEDGE_DATA_NONE));
-
- if (tree_1d != NULL) {
- BLI_kdtree_1d_deduplicate(tree_1d);
- BLI_kdtree_1d_balance(tree_1d);
- }
- if (tree_3d != NULL) {
- BLI_kdtree_3d_deduplicate(tree_3d);
- BLI_kdtree_3d_balance(tree_3d);
- }
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em->bm;
- bool changed = false;
-
- bool has_custom_data_layer = false;
- switch (type) {
- case SIMEDGE_FREESTYLE:
- {
- has_custom_data_layer = CustomData_has_layer(&bm->edata, CD_FREESTYLE_EDGE);
- if ((edge_data_value == SIMEDGE_DATA_TRUE) && !has_custom_data_layer) {
- continue;
- }
- break;
- }
- case SIMEDGE_CREASE:
- case SIMEDGE_BEVEL:
- {
- has_custom_data_layer = CustomData_has_layer(&bm->edata, custom_data_type);
- if (!has_custom_data_layer) {
- /* Proceed only if we have to select all the edges that have custom data value of 0.0f.
- * In this case we will just select all the edges.
- * Otherwise continue the for loop. */
- if (!ED_select_similar_compare_float_tree(tree_1d, 0.0f, thresh, compare)) {
- continue;
- }
- }
- }
- }
-
- float ob_m3[3][3], ob_m3_inv[3][3];
- copy_m3_m4(ob_m3, ob->obmat);
- invert_m3_m3(ob_m3_inv, ob_m3);
-
- BMEdge *edge; /* Mesh edge. */
- BMIter iter; /* Selected edges iterator. */
-
- BM_ITER_MESH (edge, &iter, bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(edge, BM_ELEM_SELECT) &&
- !BM_elem_flag_test(edge, BM_ELEM_HIDDEN))
- {
- bool select = false;
- switch (type) {
- case SIMEDGE_FACE:
- {
- const int num_faces = BM_edge_face_count(edge);
- GSetIterator gs_iter;
- GSET_ITER(gs_iter, gset) {
- const int num_faces_iter = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter));
- const int delta_i = num_faces - num_faces_iter;
- if (mesh_select_similar_compare_int(delta_i, compare)) {
- select = true;
- break;
- }
- }
- break;
- }
- case SIMEDGE_DIR:
- {
- float dir[3];
- edge_pos_direction_worldspace_get(ob, edge, dir);
-
- /* We are treating the direction as coordinates, the "nearest" one will
- * also be the one closest to the intended direction. */
- KDTreeNearest_3d nearest;
- if (BLI_kdtree_3d_find_nearest(tree_3d, dir, &nearest) != -1) {
- if (angle_normalized_v3v3(dir, nearest.co) <= thresh_radians) {
- select = true;
- }
- }
- break;
- }
- case SIMEDGE_LENGTH:
- {
- float length = edge_length_squared_worldspace_get(ob, edge);
- if (ED_select_similar_compare_float_tree(tree_1d, length, thresh, compare)) {
- select = true;
- }
- break;
- }
- case SIMEDGE_FACE_ANGLE:
- {
- if (BM_edge_face_count_at_most(edge, 2) == 2) {
- float angle = BM_edge_calc_face_angle_with_imat3(edge, ob_m3_inv);
- if (ED_select_similar_compare_float_tree(tree_1d, angle, thresh, SIM_CMP_EQ)) {
- select = true;
- }
- }
- break;
- }
- case SIMEDGE_SEAM:
- if ((BM_elem_flag_test(edge, BM_ELEM_SEAM) != 0) ==
- ((edge_data_value & SIMEDGE_DATA_TRUE) != 0))
- {
- select = true;
- }
- break;
- case SIMEDGE_SHARP:
- if ((BM_elem_flag_test(edge, BM_ELEM_SMOOTH) != 0) ==
- ((edge_data_value & SIMEDGE_DATA_TRUE) != 0))
- {
- select = true;
- }
- break;
- case SIMEDGE_FREESTYLE:
- {
- FreestyleEdge *fedge;
-
- if (!has_custom_data_layer) {
- BLI_assert(edge_data_value == SIMEDGE_DATA_FALSE);
- select = true;
- break;
- }
-
- fedge = CustomData_bmesh_get(&bm->edata, edge->head.data, CD_FREESTYLE_EDGE);
- if (((fedge != NULL) && (fedge->flag & FREESTYLE_EDGE_MARK)) ==
- ((edge_data_value & SIMEDGE_DATA_TRUE) != 0))
- {
- select = true;
- }
- break;
- }
- case SIMEDGE_CREASE:
- case SIMEDGE_BEVEL:
- {
- if (!has_custom_data_layer) {
- select = true;
- break;
- }
-
- const float *value = CustomData_bmesh_get(&bm->edata, edge->head.data, custom_data_type);
- if (ED_select_similar_compare_float_tree(tree_1d, *value, thresh, compare)) {
- select = true;
- }
- break;
- }
- }
-
- if (select) {
- BM_edge_select_set(bm, edge, true);
- changed = true;
- }
- }
- }
-
- if (changed) {
- EDBM_selectmode_flush(em);
- EDBM_update_generic(em, false, false);
- }
- }
-
- if (false) {
-edge_select_all:
- BLI_assert(ELEM(type,
- SIMEDGE_SEAM,
- SIMEDGE_SHARP,
- SIMEDGE_FREESTYLE
- ));
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em->bm;
-
- BMEdge *edge; /* Mesh edge. */
- BMIter iter; /* Selected edges iterator. */
-
- BM_ITER_MESH (edge, &iter, bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(edge, BM_ELEM_SELECT)) {
- BM_edge_select_set(bm, edge, true);
- }
- }
- EDBM_selectmode_flush(em);
- EDBM_update_generic(em, false, false);
- }
- }
-
- MEM_freeN(objects);
- BLI_kdtree_1d_free(tree_1d);
- BLI_kdtree_3d_free(tree_3d);
- if (gset != NULL) {
- BLI_gset_free(gset, NULL);
- }
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ const int type = RNA_enum_get(op->ptr, "type");
+ const float thresh = RNA_float_get(op->ptr, "threshold");
+ const float thresh_radians = thresh * (float)M_PI + FLT_EPSILON;
+ const int compare = RNA_enum_get(op->ptr, "compare");
+ int custom_data_type = -1;
+
+ int tot_edges_selected_all = 0;
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ tot_edges_selected_all += em->bm->totedgesel;
+ }
+
+ if (tot_edges_selected_all == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No edge selected");
+ MEM_freeN(objects);
+ return OPERATOR_CANCELLED;
+ }
+
+ KDTree_1d *tree_1d = NULL;
+ KDTree_3d *tree_3d = NULL;
+ GSet *gset = NULL;
+ int edge_data_value = SIMEDGE_DATA_NONE;
+
+ switch (type) {
+ case SIMEDGE_CREASE:
+ case SIMEDGE_BEVEL:
+ case SIMEDGE_FACE_ANGLE:
+ case SIMEDGE_LENGTH:
+ tree_1d = BLI_kdtree_1d_new(tot_edges_selected_all);
+ break;
+ case SIMEDGE_DIR:
+ tree_3d = BLI_kdtree_3d_new(tot_edges_selected_all);
+ break;
+ case SIMEDGE_FACE:
+ gset = BLI_gset_ptr_new("Select similar edge: face");
+ break;
+ }
+
+ switch (type) {
+ case SIMEDGE_CREASE:
+ custom_data_type = CD_CREASE;
+ break;
+ case SIMEDGE_BEVEL:
+ custom_data_type = CD_BWEIGHT;
+ break;
+ }
+
+ int tree_index = 0;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
+
+ if (bm->totedgesel == 0) {
+ continue;
+ }
+
+ switch (type) {
+ case SIMEDGE_FREESTYLE: {
+ if (!CustomData_has_layer(&bm->edata, CD_FREESTYLE_EDGE)) {
+ edge_data_value |= SIMEDGE_DATA_FALSE;
+ continue;
+ }
+ break;
+ }
+ case SIMEDGE_CREASE:
+ case SIMEDGE_BEVEL: {
+ if (!CustomData_has_layer(&bm->edata, custom_data_type)) {
+ BLI_kdtree_1d_insert(tree_1d, tree_index++, (float[1]){0.0f});
+ continue;
+ }
+ break;
+ }
+ }
+
+ float ob_m3[3][3], ob_m3_inv[3][3];
+ copy_m3_m4(ob_m3, ob->obmat);
+ invert_m3_m3(ob_m3_inv, ob_m3);
+
+ BMEdge *edge; /* Mesh edge. */
+ BMIter iter; /* Selected edges iterator. */
+
+ BM_ITER_MESH (edge, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(edge, BM_ELEM_SELECT)) {
+ switch (type) {
+ case SIMEDGE_FACE:
+ BLI_gset_add(gset, POINTER_FROM_INT(BM_edge_face_count(edge)));
+ break;
+ case SIMEDGE_DIR: {
+ float dir[3];
+ edge_pos_direction_worldspace_get(ob, edge, dir);
+ BLI_kdtree_3d_insert(tree_3d, tree_index++, dir);
+ break;
+ }
+ case SIMEDGE_LENGTH: {
+ float length = edge_length_squared_worldspace_get(ob, edge);
+ BLI_kdtree_1d_insert(tree_1d, tree_index++, &length);
+ break;
+ }
+ case SIMEDGE_FACE_ANGLE: {
+ if (BM_edge_face_count_at_most(edge, 2) == 2) {
+ float angle = BM_edge_calc_face_angle_with_imat3(edge, ob_m3_inv);
+ BLI_kdtree_1d_insert(tree_1d, tree_index++, &angle);
+ }
+ break;
+ }
+ case SIMEDGE_SEAM:
+ if (!edge_data_value_set(edge, BM_ELEM_SEAM, &edge_data_value)) {
+ goto edge_select_all;
+ }
+ break;
+ case SIMEDGE_SHARP:
+ if (!edge_data_value_set(edge, BM_ELEM_SMOOTH, &edge_data_value)) {
+ goto edge_select_all;
+ }
+ break;
+ case SIMEDGE_FREESTYLE: {
+ FreestyleEdge *fedge;
+ fedge = CustomData_bmesh_get(&bm->edata, edge->head.data, CD_FREESTYLE_EDGE);
+ if ((fedge == NULL) || ((fedge->flag & FREESTYLE_EDGE_MARK) == 0)) {
+ edge_data_value |= SIMEDGE_DATA_FALSE;
+ }
+ else {
+ edge_data_value |= SIMEDGE_DATA_TRUE;
+ }
+ if (edge_data_value == SIMEDGE_DATA_ALL) {
+ goto edge_select_all;
+ }
+ break;
+ }
+ case SIMEDGE_CREASE:
+ case SIMEDGE_BEVEL: {
+ const float *value = CustomData_bmesh_get(
+ &bm->edata, edge->head.data, custom_data_type);
+ BLI_kdtree_1d_insert(tree_1d, tree_index++, value);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ BLI_assert((type != SIMEDGE_FREESTYLE) || (edge_data_value != SIMEDGE_DATA_NONE));
+
+ if (tree_1d != NULL) {
+ BLI_kdtree_1d_deduplicate(tree_1d);
+ BLI_kdtree_1d_balance(tree_1d);
+ }
+ if (tree_3d != NULL) {
+ BLI_kdtree_3d_deduplicate(tree_3d);
+ BLI_kdtree_3d_balance(tree_3d);
+ }
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
+ bool changed = false;
+
+ bool has_custom_data_layer = false;
+ switch (type) {
+ case SIMEDGE_FREESTYLE: {
+ has_custom_data_layer = CustomData_has_layer(&bm->edata, CD_FREESTYLE_EDGE);
+ if ((edge_data_value == SIMEDGE_DATA_TRUE) && !has_custom_data_layer) {
+ continue;
+ }
+ break;
+ }
+ case SIMEDGE_CREASE:
+ case SIMEDGE_BEVEL: {
+ has_custom_data_layer = CustomData_has_layer(&bm->edata, custom_data_type);
+ if (!has_custom_data_layer) {
+ /* Proceed only if we have to select all the edges that have custom data value of 0.0f.
+ * In this case we will just select all the edges.
+ * Otherwise continue the for loop. */
+ if (!ED_select_similar_compare_float_tree(tree_1d, 0.0f, thresh, compare)) {
+ continue;
+ }
+ }
+ }
+ }
+
+ float ob_m3[3][3], ob_m3_inv[3][3];
+ copy_m3_m4(ob_m3, ob->obmat);
+ invert_m3_m3(ob_m3_inv, ob_m3);
+
+ BMEdge *edge; /* Mesh edge. */
+ BMIter iter; /* Selected edges iterator. */
+
+ BM_ITER_MESH (edge, &iter, bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(edge, BM_ELEM_SELECT) && !BM_elem_flag_test(edge, BM_ELEM_HIDDEN)) {
+ bool select = false;
+ switch (type) {
+ case SIMEDGE_FACE: {
+ const int num_faces = BM_edge_face_count(edge);
+ GSetIterator gs_iter;
+ GSET_ITER (gs_iter, gset) {
+ const int num_faces_iter = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter));
+ const int delta_i = num_faces - num_faces_iter;
+ if (mesh_select_similar_compare_int(delta_i, compare)) {
+ select = true;
+ break;
+ }
+ }
+ break;
+ }
+ case SIMEDGE_DIR: {
+ float dir[3];
+ edge_pos_direction_worldspace_get(ob, edge, dir);
+
+ /* We are treating the direction as coordinates, the "nearest" one will
+ * also be the one closest to the intended direction. */
+ KDTreeNearest_3d nearest;
+ if (BLI_kdtree_3d_find_nearest(tree_3d, dir, &nearest) != -1) {
+ if (angle_normalized_v3v3(dir, nearest.co) <= thresh_radians) {
+ select = true;
+ }
+ }
+ break;
+ }
+ case SIMEDGE_LENGTH: {
+ float length = edge_length_squared_worldspace_get(ob, edge);
+ if (ED_select_similar_compare_float_tree(tree_1d, length, thresh, compare)) {
+ select = true;
+ }
+ break;
+ }
+ case SIMEDGE_FACE_ANGLE: {
+ if (BM_edge_face_count_at_most(edge, 2) == 2) {
+ float angle = BM_edge_calc_face_angle_with_imat3(edge, ob_m3_inv);
+ if (ED_select_similar_compare_float_tree(tree_1d, angle, thresh, SIM_CMP_EQ)) {
+ select = true;
+ }
+ }
+ break;
+ }
+ case SIMEDGE_SEAM:
+ if ((BM_elem_flag_test(edge, BM_ELEM_SEAM) != 0) ==
+ ((edge_data_value & SIMEDGE_DATA_TRUE) != 0)) {
+ select = true;
+ }
+ break;
+ case SIMEDGE_SHARP:
+ if ((BM_elem_flag_test(edge, BM_ELEM_SMOOTH) != 0) ==
+ ((edge_data_value & SIMEDGE_DATA_TRUE) != 0)) {
+ select = true;
+ }
+ break;
+ case SIMEDGE_FREESTYLE: {
+ FreestyleEdge *fedge;
+
+ if (!has_custom_data_layer) {
+ BLI_assert(edge_data_value == SIMEDGE_DATA_FALSE);
+ select = true;
+ break;
+ }
+
+ fedge = CustomData_bmesh_get(&bm->edata, edge->head.data, CD_FREESTYLE_EDGE);
+ if (((fedge != NULL) && (fedge->flag & FREESTYLE_EDGE_MARK)) ==
+ ((edge_data_value & SIMEDGE_DATA_TRUE) != 0)) {
+ select = true;
+ }
+ break;
+ }
+ case SIMEDGE_CREASE:
+ case SIMEDGE_BEVEL: {
+ if (!has_custom_data_layer) {
+ select = true;
+ break;
+ }
+
+ const float *value = CustomData_bmesh_get(
+ &bm->edata, edge->head.data, custom_data_type);
+ if (ED_select_similar_compare_float_tree(tree_1d, *value, thresh, compare)) {
+ select = true;
+ }
+ break;
+ }
+ }
+
+ if (select) {
+ BM_edge_select_set(bm, edge, true);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ EDBM_selectmode_flush(em);
+ EDBM_update_generic(em, false, false);
+ }
+ }
+
+ if (false) {
+ edge_select_all:
+ BLI_assert(ELEM(type, SIMEDGE_SEAM, SIMEDGE_SHARP, SIMEDGE_FREESTYLE));
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
+
+ BMEdge *edge; /* Mesh edge. */
+ BMIter iter; /* Selected edges iterator. */
+
+ BM_ITER_MESH (edge, &iter, bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(edge, BM_ELEM_SELECT)) {
+ BM_edge_select_set(bm, edge, true);
+ }
+ }
+ EDBM_selectmode_flush(em);
+ EDBM_update_generic(em, false, false);
+ }
+ }
+
+ MEM_freeN(objects);
+ BLI_kdtree_1d_free(tree_1d);
+ BLI_kdtree_3d_free(tree_3d);
+ if (gset != NULL) {
+ BLI_gset_free(gset, NULL);
+ }
+
+ return OPERATOR_FINISHED;
}
/** \} */
@@ -1010,254 +960,243 @@ edge_select_all:
static int similar_vert_select_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- /* get the type from RNA */
- const int type = RNA_enum_get(op->ptr, "type");
- const float thresh = RNA_float_get(op->ptr, "threshold");
- const float thresh_radians = thresh * (float)M_PI + FLT_EPSILON;
- const int compare = RNA_enum_get(op->ptr, "compare");
-
- int tot_verts_selected_all = 0;
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- tot_verts_selected_all += em->bm->totvertsel;
- }
-
- if (tot_verts_selected_all == 0) {
- BKE_report(op->reports, RPT_ERROR, "No vertex selected");
- MEM_freeN(objects);
- return OPERATOR_CANCELLED;
- }
-
- KDTree_3d *tree_3d = NULL;
- GSet *gset = NULL;
-
- switch (type) {
- case SIMVERT_NORMAL:
- tree_3d = BLI_kdtree_3d_new(tot_verts_selected_all);
- break;
- case SIMVERT_EDGE:
- case SIMVERT_FACE:
- gset = BLI_gset_ptr_new("Select similar vertex: edge/face");
- break;
- case SIMVERT_VGROUP:
- gset = BLI_gset_str_new("Select similar vertex: vertex groups");
- break;
- }
-
- int normal_tree_index = 0;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em->bm;
- int cd_dvert_offset = -1;
- int dvert_selected = 0;
- invert_m4_m4(ob->imat, ob->obmat);
-
- if (bm->totvertsel == 0) {
- continue;
- }
-
- if (type == SIMVERT_VGROUP) {
- cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
- if (cd_dvert_offset == -1) {
- continue;
- }
- }
-
- BMVert *vert; /* Mesh vertex. */
- BMIter iter; /* Selected verts iterator. */
-
- BM_ITER_MESH (vert, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(vert, BM_ELEM_SELECT)) {
- switch (type) {
- case SIMVERT_FACE:
- BLI_gset_add(gset, POINTER_FROM_INT(BM_vert_face_count(vert)));
- break;
- case SIMVERT_EDGE:
- BLI_gset_add(gset, POINTER_FROM_INT(BM_vert_edge_count(vert)));
- break;
- case SIMVERT_NORMAL:
- {
- float normal[3];
- copy_v3_v3(normal, vert->no);
- mul_transposed_mat3_m4_v3(ob->imat, normal);
- normalize_v3(normal);
-
- BLI_kdtree_3d_insert(tree_3d, normal_tree_index++, normal);
- break;
- }
- case SIMVERT_VGROUP:
- {
- MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(vert, cd_dvert_offset);
- MDeformWeight *dw = dvert->dw;
-
- for (int i = 0; i < dvert->totweight; i++, dw++) {
- if (dw->weight > 0.0f) {
- dvert_selected |= (1 << dw->def_nr);
- }
- }
- break;
- }
- }
- }
- }
-
- 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. */
- const int dvert_tot = BLI_listbase_count(&ob->defbase);
- for (int i = 0; i < dvert_tot; i++) {
- if (dvert_selected & (1 << i)) {
- bDeformGroup *dg = BLI_findlink(&ob->defbase, i);
- BLI_gset_add(gset, dg->name);
- }
- }
- }
- }
-
- if (type == SIMVERT_VGROUP) {
- if (BLI_gset_len(gset) == 0) {
- BKE_report(op->reports,
- RPT_INFO,
- "No vertex group among the selected vertices");
- }
- }
-
- /* Remove duplicated entries. */
- if (tree_3d != NULL) {
- BLI_kdtree_3d_deduplicate(tree_3d);
- BLI_kdtree_3d_balance(tree_3d);
- }
-
- /* Run .the BM operators. */
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em->bm;
- bool changed = false;
- int cd_dvert_offset = -1;
- int dvert_selected = 0;
-
- if (type == SIMVERT_VGROUP) {
- cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
- if (cd_dvert_offset == -1) {
- continue;
- }
-
- /* We map back the names of the vertex groups to their corresponding indices
- * for this object. This is fast, and keep the logic for each vertex very simple. */
- GSetIterator gs_iter;
- GSET_ITER(gs_iter, gset) {
- const char *name = BLI_gsetIterator_getKey(&gs_iter);
- int vgroup_id = BLI_findstringindex(&ob->defbase,
- name,
- offsetof(bDeformGroup, name));
- if (vgroup_id != -1) {
- dvert_selected |= (1 << vgroup_id);
- }
- }
- if (dvert_selected == 0) {
- continue;
- }
- }
-
- BMVert *vert; /* Mesh vertex. */
- BMIter iter; /* Selected verts iterator. */
-
- BM_ITER_MESH (vert, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(vert, BM_ELEM_SELECT) &&
- !BM_elem_flag_test(vert, BM_ELEM_HIDDEN))
- {
- bool select = false;
- switch (type) {
- case SIMVERT_EDGE:
- {
- const int num_edges = BM_vert_edge_count(vert);
- GSetIterator gs_iter;
- GSET_ITER(gs_iter, gset) {
- const int num_edges_iter = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter));
- const int delta_i = num_edges - num_edges_iter;
- if (mesh_select_similar_compare_int(delta_i, compare)) {
- select = true;
- break;
- }
- }
- break;
- }
- case SIMVERT_FACE:
- {
- const int num_faces = BM_vert_face_count(vert);
- GSetIterator gs_iter;
- GSET_ITER(gs_iter, gset) {
- const int num_faces_iter = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter));
- const int delta_i = num_faces - num_faces_iter;
- if (mesh_select_similar_compare_int(delta_i, compare)) {
- select = true;
- break;
- }
- }
- break;
- }
- case SIMVERT_NORMAL:
- {
- float normal[3];
- copy_v3_v3(normal, vert->no);
- mul_transposed_mat3_m4_v3(ob->imat, normal);
- normalize_v3(normal);
-
- /* We are treating the normals as coordinates, the "nearest" one will
- * also be the one closest to the angle. */
- KDTreeNearest_3d nearest;
- if (BLI_kdtree_3d_find_nearest(tree_3d, normal, &nearest) != -1) {
- if (angle_normalized_v3v3(normal, nearest.co) <= thresh_radians) {
- select = true;
- }
- }
- break;
- }
- case SIMVERT_VGROUP:
- {
- MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(vert, cd_dvert_offset);
- MDeformWeight *dw = dvert->dw;
-
- for (int i = 0; i < dvert->totweight; i++, dw++) {
- if (dw->weight > 0.0f) {
- if (dvert_selected & (1 << dw->def_nr)) {
- select = true;
- break;
- }
- }
- }
- break;
- }
- }
-
- if (select) {
- BM_vert_select_set(bm, vert, true);
- changed = true;
- }
- }
- }
-
- if (changed) {
- EDBM_selectmode_flush(em);
- EDBM_update_generic(em, false, false);
- }
- }
-
- MEM_freeN(objects);
- BLI_kdtree_3d_free(tree_3d);
- if (gset != NULL) {
- BLI_gset_free(gset, NULL);
- }
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ /* get the type from RNA */
+ const int type = RNA_enum_get(op->ptr, "type");
+ const float thresh = RNA_float_get(op->ptr, "threshold");
+ const float thresh_radians = thresh * (float)M_PI + FLT_EPSILON;
+ const int compare = RNA_enum_get(op->ptr, "compare");
+
+ int tot_verts_selected_all = 0;
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ tot_verts_selected_all += em->bm->totvertsel;
+ }
+
+ if (tot_verts_selected_all == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No vertex selected");
+ MEM_freeN(objects);
+ return OPERATOR_CANCELLED;
+ }
+
+ KDTree_3d *tree_3d = NULL;
+ GSet *gset = NULL;
+
+ switch (type) {
+ case SIMVERT_NORMAL:
+ tree_3d = BLI_kdtree_3d_new(tot_verts_selected_all);
+ break;
+ case SIMVERT_EDGE:
+ case SIMVERT_FACE:
+ gset = BLI_gset_ptr_new("Select similar vertex: edge/face");
+ break;
+ case SIMVERT_VGROUP:
+ gset = BLI_gset_str_new("Select similar vertex: vertex groups");
+ break;
+ }
+
+ int normal_tree_index = 0;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
+ int cd_dvert_offset = -1;
+ int dvert_selected = 0;
+ invert_m4_m4(ob->imat, ob->obmat);
+
+ if (bm->totvertsel == 0) {
+ continue;
+ }
+
+ if (type == SIMVERT_VGROUP) {
+ cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
+ if (cd_dvert_offset == -1) {
+ continue;
+ }
+ }
+
+ BMVert *vert; /* Mesh vertex. */
+ BMIter iter; /* Selected verts iterator. */
+
+ BM_ITER_MESH (vert, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(vert, BM_ELEM_SELECT)) {
+ switch (type) {
+ case SIMVERT_FACE:
+ BLI_gset_add(gset, POINTER_FROM_INT(BM_vert_face_count(vert)));
+ break;
+ case SIMVERT_EDGE:
+ BLI_gset_add(gset, POINTER_FROM_INT(BM_vert_edge_count(vert)));
+ break;
+ case SIMVERT_NORMAL: {
+ float normal[3];
+ copy_v3_v3(normal, vert->no);
+ mul_transposed_mat3_m4_v3(ob->imat, normal);
+ normalize_v3(normal);
+
+ BLI_kdtree_3d_insert(tree_3d, normal_tree_index++, normal);
+ break;
+ }
+ case SIMVERT_VGROUP: {
+ MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(vert, cd_dvert_offset);
+ MDeformWeight *dw = dvert->dw;
+
+ for (int i = 0; i < dvert->totweight; i++, dw++) {
+ if (dw->weight > 0.0f) {
+ dvert_selected |= (1 << dw->def_nr);
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ 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. */
+ const int dvert_tot = BLI_listbase_count(&ob->defbase);
+ for (int i = 0; i < dvert_tot; i++) {
+ if (dvert_selected & (1 << i)) {
+ bDeformGroup *dg = BLI_findlink(&ob->defbase, i);
+ BLI_gset_add(gset, dg->name);
+ }
+ }
+ }
+ }
+
+ if (type == SIMVERT_VGROUP) {
+ if (BLI_gset_len(gset) == 0) {
+ BKE_report(op->reports, RPT_INFO, "No vertex group among the selected vertices");
+ }
+ }
+
+ /* Remove duplicated entries. */
+ if (tree_3d != NULL) {
+ BLI_kdtree_3d_deduplicate(tree_3d);
+ BLI_kdtree_3d_balance(tree_3d);
+ }
+
+ /* Run .the BM operators. */
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
+ bool changed = false;
+ int cd_dvert_offset = -1;
+ int dvert_selected = 0;
+
+ if (type == SIMVERT_VGROUP) {
+ cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
+ if (cd_dvert_offset == -1) {
+ continue;
+ }
+
+ /* We map back the names of the vertex groups to their corresponding indices
+ * for this object. This is fast, and keep the logic for each vertex very simple. */
+ GSetIterator gs_iter;
+ GSET_ITER (gs_iter, gset) {
+ const char *name = BLI_gsetIterator_getKey(&gs_iter);
+ int vgroup_id = BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name));
+ if (vgroup_id != -1) {
+ dvert_selected |= (1 << vgroup_id);
+ }
+ }
+ if (dvert_selected == 0) {
+ continue;
+ }
+ }
+
+ BMVert *vert; /* Mesh vertex. */
+ BMIter iter; /* Selected verts iterator. */
+
+ BM_ITER_MESH (vert, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(vert, BM_ELEM_SELECT) && !BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) {
+ bool select = false;
+ switch (type) {
+ case SIMVERT_EDGE: {
+ const int num_edges = BM_vert_edge_count(vert);
+ GSetIterator gs_iter;
+ GSET_ITER (gs_iter, gset) {
+ const int num_edges_iter = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter));
+ const int delta_i = num_edges - num_edges_iter;
+ if (mesh_select_similar_compare_int(delta_i, compare)) {
+ select = true;
+ break;
+ }
+ }
+ break;
+ }
+ case SIMVERT_FACE: {
+ const int num_faces = BM_vert_face_count(vert);
+ GSetIterator gs_iter;
+ GSET_ITER (gs_iter, gset) {
+ const int num_faces_iter = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter));
+ const int delta_i = num_faces - num_faces_iter;
+ if (mesh_select_similar_compare_int(delta_i, compare)) {
+ select = true;
+ break;
+ }
+ }
+ break;
+ }
+ case SIMVERT_NORMAL: {
+ float normal[3];
+ copy_v3_v3(normal, vert->no);
+ mul_transposed_mat3_m4_v3(ob->imat, normal);
+ normalize_v3(normal);
+
+ /* We are treating the normals as coordinates, the "nearest" one will
+ * also be the one closest to the angle. */
+ KDTreeNearest_3d nearest;
+ if (BLI_kdtree_3d_find_nearest(tree_3d, normal, &nearest) != -1) {
+ if (angle_normalized_v3v3(normal, nearest.co) <= thresh_radians) {
+ select = true;
+ }
+ }
+ break;
+ }
+ case SIMVERT_VGROUP: {
+ MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(vert, cd_dvert_offset);
+ MDeformWeight *dw = dvert->dw;
+
+ for (int i = 0; i < dvert->totweight; i++, dw++) {
+ if (dw->weight > 0.0f) {
+ if (dvert_selected & (1 << dw->def_nr)) {
+ select = true;
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ if (select) {
+ BM_vert_select_set(bm, vert, true);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ EDBM_selectmode_flush(em);
+ EDBM_update_generic(em, false, false);
+ }
+ }
+
+ MEM_freeN(objects);
+ BLI_kdtree_3d_free(tree_3d);
+ if (gset != NULL) {
+ BLI_gset_free(gset, NULL);
+ }
+
+ return OPERATOR_FINISHED;
}
/** \} */
@@ -1267,93 +1206,97 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op)
static int edbm_select_similar_exec(bContext *C, wmOperator *op)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, "threshold");
-
- const int type = RNA_enum_get(op->ptr, "type");
-
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_float_set(op->ptr, prop, ts->select_thresh);
- }
- else {
- ts->select_thresh = RNA_property_float_get(op->ptr, prop);
- }
-
- if (type < 100) return similar_vert_select_exec(C, op);
- else if (type < 200) return similar_edge_select_exec(C, op);
- else return similar_face_select_exec(C, op);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "threshold");
+
+ const int type = RNA_enum_get(op->ptr, "type");
+
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_float_set(op->ptr, prop, ts->select_thresh);
+ }
+ else {
+ ts->select_thresh = RNA_property_float_get(op->ptr, prop);
+ }
+
+ if (type < 100)
+ return similar_vert_select_exec(C, op);
+ else if (type < 200)
+ return similar_edge_select_exec(C, op);
+ else
+ return similar_face_select_exec(C, op);
}
-static const EnumPropertyItem *select_similar_type_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop),
- bool *r_free)
+static const EnumPropertyItem *select_similar_type_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- Object *obedit;
-
- if (!C) /* needed for docs and i18n tools */
- return prop_similar_types;
-
- obedit = CTX_data_edit_object(C);
-
- if (obedit && obedit->type == OB_MESH) {
- EnumPropertyItem *item = NULL;
- int a, totitem = 0;
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->selectmode & SCE_SELECT_VERTEX) {
- for (a = SIMVERT_NORMAL; a < SIMEDGE_LENGTH; a++) {
- RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
- }
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- for (a = SIMEDGE_LENGTH; a < SIMFACE_MATERIAL; a++) {
- RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
- }
- }
- else if (em->selectmode & SCE_SELECT_FACE) {
+ Object *obedit;
+
+ if (!C) /* needed for docs and i18n tools */
+ return prop_similar_types;
+
+ obedit = CTX_data_edit_object(C);
+
+ if (obedit && obedit->type == OB_MESH) {
+ EnumPropertyItem *item = NULL;
+ int a, totitem = 0;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ for (a = SIMVERT_NORMAL; a < SIMEDGE_LENGTH; a++) {
+ RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ for (a = SIMEDGE_LENGTH; a < SIMFACE_MATERIAL; a++) {
+ RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_FACE) {
#ifdef WITH_FREESTYLE
- const int a_end = SIMFACE_FREESTYLE;
+ const int a_end = SIMFACE_FREESTYLE;
#else
- const int a_end = SIMFACE_FACEMAP;
+ const int a_end = SIMFACE_FACEMAP;
#endif
- for (a = SIMFACE_MATERIAL; a <= a_end; a++) {
- RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
- }
- }
- RNA_enum_item_end(&item, &totitem);
+ for (a = SIMFACE_MATERIAL; a <= a_end; a++) {
+ RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
+ }
+ }
+ RNA_enum_item_end(&item, &totitem);
- *r_free = true;
+ *r_free = true;
- return item;
- }
+ return item;
+ }
- return prop_similar_types;
+ return prop_similar_types;
}
void MESH_OT_select_similar(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Select Similar";
- ot->idname = "MESH_OT_select_similar";
- ot->description = "Select similar vertices, edges or faces by property types";
+ /* identifiers */
+ ot->name = "Select Similar";
+ ot->idname = "MESH_OT_select_similar";
+ ot->description = "Select similar vertices, edges or faces by property types";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = edbm_select_similar_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = edbm_select_similar_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- prop = ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, SIMVERT_NORMAL, "Type", "");
- RNA_def_enum_funcs(prop, select_similar_type_itemf);
+ /* properties */
+ prop = ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, SIMVERT_NORMAL, "Type", "");
+ RNA_def_enum_funcs(prop, select_similar_type_itemf);
- RNA_def_enum(ot->srna, "compare", prop_similar_compare_types, SIM_CMP_EQ, "Compare", "");
+ RNA_def_enum(ot->srna, "compare", prop_similar_compare_types, SIM_CMP_EQ, "Compare", "");
- RNA_def_float(ot->srna, "threshold", 0.0f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
+ RNA_def_float(ot->srna, "threshold", 0.0f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
}
/** \} */
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 9fb200951ca..79bbf021829 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -80,7 +80,7 @@
#include "UI_interface.h"
#include "UI_resources.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
#include "bmesh_tools.h"
@@ -92,92 +92,131 @@
static int edbm_subdivide_exec(bContext *C, wmOperator *op)
{
- const int cuts = RNA_int_get(op->ptr, "number_cuts");
- const float smooth = RNA_float_get(op->ptr, "smoothness");
- const float fractal = RNA_float_get(op->ptr, "fractal") / 2.5f;
- const float along_normal = RNA_float_get(op->ptr, "fractal_along_normal");
-
- if (RNA_boolean_get(op->ptr, "ngon") &&
- RNA_enum_get(op->ptr, "quadcorner") == SUBD_CORNER_STRAIGHT_CUT)
- {
- RNA_enum_set(op->ptr, "quadcorner", SUBD_CORNER_INNERVERT);
- }
- const int quad_corner_type = RNA_enum_get(op->ptr, "quadcorner");
- const bool use_quad_tri = !RNA_boolean_get(op->ptr, "ngon");
- const int seed = RNA_int_get(op->ptr, "seed");
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (!(em->bm->totedgesel || em->bm->totfacesel)) {
- continue;
- }
-
- BM_mesh_esubdivide(
- em->bm, BM_ELEM_SELECT,
- smooth, SUBD_FALLOFF_LIN, false,
- fractal, along_normal,
- cuts,
- SUBDIV_SELECT_ORIG, quad_corner_type,
- use_quad_tri, true, false,
- seed);
-
- EDBM_update_generic(em, true, true);
- }
-
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ const int cuts = RNA_int_get(op->ptr, "number_cuts");
+ const float smooth = RNA_float_get(op->ptr, "smoothness");
+ const float fractal = RNA_float_get(op->ptr, "fractal") / 2.5f;
+ const float along_normal = RNA_float_get(op->ptr, "fractal_along_normal");
+
+ if (RNA_boolean_get(op->ptr, "ngon") &&
+ RNA_enum_get(op->ptr, "quadcorner") == SUBD_CORNER_STRAIGHT_CUT) {
+ RNA_enum_set(op->ptr, "quadcorner", SUBD_CORNER_INNERVERT);
+ }
+ const int quad_corner_type = RNA_enum_get(op->ptr, "quadcorner");
+ const bool use_quad_tri = !RNA_boolean_get(op->ptr, "ngon");
+ const int seed = RNA_int_get(op->ptr, "seed");
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (!(em->bm->totedgesel || em->bm->totfacesel)) {
+ continue;
+ }
+
+ BM_mesh_esubdivide(em->bm,
+ BM_ELEM_SELECT,
+ smooth,
+ SUBD_FALLOFF_LIN,
+ false,
+ fractal,
+ along_normal,
+ cuts,
+ SUBDIV_SELECT_ORIG,
+ quad_corner_type,
+ use_quad_tri,
+ true,
+ false,
+ seed);
+
+ EDBM_update_generic(em, true, true);
+ }
+
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
/* Note, these values must match delete_mesh() event values */
static const EnumPropertyItem prop_mesh_cornervert_types[] = {
- {SUBD_CORNER_INNERVERT, "INNERVERT", 0, "Inner Vert", ""},
- {SUBD_CORNER_PATH, "PATH", 0, "Path", ""},
- {SUBD_CORNER_STRAIGHT_CUT, "STRAIGHT_CUT", 0, "Straight Cut", ""},
- {SUBD_CORNER_FAN, "FAN", 0, "Fan", ""},
- {0, NULL, 0, NULL, NULL},
+ {SUBD_CORNER_INNERVERT, "INNERVERT", 0, "Inner Vert", ""},
+ {SUBD_CORNER_PATH, "PATH", 0, "Path", ""},
+ {SUBD_CORNER_STRAIGHT_CUT, "STRAIGHT_CUT", 0, "Straight Cut", ""},
+ {SUBD_CORNER_FAN, "FAN", 0, "Fan", ""},
+ {0, NULL, 0, NULL, NULL},
};
void MESH_OT_subdivide(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Subdivide";
- ot->description = "Subdivide selected edges";
- ot->idname = "MESH_OT_subdivide";
-
- /* api callbacks */
- ot->exec = edbm_subdivide_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 100, "Number of Cuts", "", 1, 10);
- /* avoid re-using last var because it can cause
- * _very_ high poly meshes and annoy users (or worse crash) */
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- RNA_def_float(ot->srna, "smoothness", 0.0f, 0.0f, 1e3f, "Smoothness", "Smoothness factor", 0.0f, 1.0f);
-
- WM_operatortype_props_advanced_begin(ot);
-
- RNA_def_boolean(ot->srna, "ngon", true, "Create N-Gons", "When disabled, newly created faces are limited to 3-4 sided faces");
- RNA_def_enum(ot->srna, "quadcorner", prop_mesh_cornervert_types, SUBD_CORNER_STRAIGHT_CUT,
- "Quad Corner Type", "How to subdivide quad corners (anything other than Straight Cut will prevent ngons)");
-
- RNA_def_float(ot->srna, "fractal", 0.0f, 0.0f, 1e6f, "Fractal", "Fractal randomness factor", 0.0f, 1000.0f);
- RNA_def_float(ot->srna, "fractal_along_normal", 0.0f, 0.0f, 1.0f,
- "Along Normal", "Apply fractal displacement along normal only", 0.0f, 1.0f);
- RNA_def_int(ot->srna, "seed", 0, 0, INT_MAX, "Random Seed", "Seed for the random number generator", 0, 255);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Subdivide";
+ ot->description = "Subdivide selected edges";
+ ot->idname = "MESH_OT_subdivide";
+
+ /* api callbacks */
+ ot->exec = edbm_subdivide_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 100, "Number of Cuts", "", 1, 10);
+ /* avoid re-using last var because it can cause
+ * _very_ high poly meshes and annoy users (or worse crash) */
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ RNA_def_float(
+ ot->srna, "smoothness", 0.0f, 0.0f, 1e3f, "Smoothness", "Smoothness factor", 0.0f, 1.0f);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ RNA_def_boolean(ot->srna,
+ "ngon",
+ true,
+ "Create N-Gons",
+ "When disabled, newly created faces are limited to 3-4 sided faces");
+ RNA_def_enum(
+ ot->srna,
+ "quadcorner",
+ prop_mesh_cornervert_types,
+ SUBD_CORNER_STRAIGHT_CUT,
+ "Quad Corner Type",
+ "How to subdivide quad corners (anything other than Straight Cut will prevent ngons)");
+
+ RNA_def_float(ot->srna,
+ "fractal",
+ 0.0f,
+ 0.0f,
+ 1e6f,
+ "Fractal",
+ "Fractal randomness factor",
+ 0.0f,
+ 1000.0f);
+ RNA_def_float(ot->srna,
+ "fractal_along_normal",
+ 0.0f,
+ 0.0f,
+ 1.0f,
+ "Along Normal",
+ "Apply fractal displacement along normal only",
+ 0.0f,
+ 1.0f);
+ RNA_def_int(ot->srna,
+ "seed",
+ 0,
+ 0,
+ INT_MAX,
+ "Random Seed",
+ "Seed for the random number generator",
+ 0,
+ 255);
}
/** \} */
@@ -190,107 +229,124 @@ void MESH_OT_subdivide(wmOperatorType *ot)
* \{ */
struct EdgeRingOpSubdProps {
- int interp_mode;
- int cuts;
- float smooth;
+ int interp_mode;
+ int cuts;
+ float smooth;
- int profile_shape;
- float profile_shape_factor;
+ int profile_shape;
+ float profile_shape_factor;
};
-
-static void mesh_operator_edgering_props(wmOperatorType *ot, const int cuts_min, const int cuts_default)
-{
- /* Note, these values must match delete_mesh() event values */
- static const EnumPropertyItem prop_subd_edgering_types[] = {
- {SUBD_RING_INTERP_LINEAR, "LINEAR", 0, "Linear", ""},
- {SUBD_RING_INTERP_PATH, "PATH", 0, "Blend Path", ""},
- {SUBD_RING_INTERP_SURF, "SURFACE", 0, "Blend Surface", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- PropertyRNA *prop;
-
- prop = RNA_def_int(ot->srna, "number_cuts", cuts_default, 0, 1000, "Number of Cuts", "", cuts_min, 64);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- RNA_def_enum(ot->srna, "interpolation", prop_subd_edgering_types, SUBD_RING_INTERP_PATH,
- "Interpolation", "Interpolation method");
-
- RNA_def_float(ot->srna, "smoothness", 1.0f, 0.0f, 1e3f,
- "Smoothness", "Smoothness factor", 0.0f, 2.0f);
-
- /* profile-shape */
- RNA_def_float(ot->srna, "profile_shape_factor", 0.0f, -1e3f, 1e3f,
- "Profile Factor", "How much intermediary new edges are shrunk/expanded", -2.0f, 2.0f);
-
- prop = RNA_def_property(ot->srna, "profile_shape", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, rna_enum_proportional_falloff_curve_only_items);
- RNA_def_property_enum_default(prop, PROP_SMOOTH);
- RNA_def_property_ui_text(prop, "Profile Shape", "Shape of the profile");
- RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
+static void mesh_operator_edgering_props(wmOperatorType *ot,
+ const int cuts_min,
+ const int cuts_default)
+{
+ /* Note, these values must match delete_mesh() event values */
+ static const EnumPropertyItem prop_subd_edgering_types[] = {
+ {SUBD_RING_INTERP_LINEAR, "LINEAR", 0, "Linear", ""},
+ {SUBD_RING_INTERP_PATH, "PATH", 0, "Blend Path", ""},
+ {SUBD_RING_INTERP_SURF, "SURFACE", 0, "Blend Surface", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ PropertyRNA *prop;
+
+ prop = RNA_def_int(
+ ot->srna, "number_cuts", cuts_default, 0, 1000, "Number of Cuts", "", cuts_min, 64);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ RNA_def_enum(ot->srna,
+ "interpolation",
+ prop_subd_edgering_types,
+ SUBD_RING_INTERP_PATH,
+ "Interpolation",
+ "Interpolation method");
+
+ RNA_def_float(
+ ot->srna, "smoothness", 1.0f, 0.0f, 1e3f, "Smoothness", "Smoothness factor", 0.0f, 2.0f);
+
+ /* profile-shape */
+ RNA_def_float(ot->srna,
+ "profile_shape_factor",
+ 0.0f,
+ -1e3f,
+ 1e3f,
+ "Profile Factor",
+ "How much intermediary new edges are shrunk/expanded",
+ -2.0f,
+ 2.0f);
+
+ prop = RNA_def_property(ot->srna, "profile_shape", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_enum_proportional_falloff_curve_only_items);
+ RNA_def_property_enum_default(prop, PROP_SMOOTH);
+ RNA_def_property_ui_text(prop, "Profile Shape", "Shape of the profile");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
}
static void mesh_operator_edgering_props_get(wmOperator *op, struct EdgeRingOpSubdProps *op_props)
{
- op_props->interp_mode = RNA_enum_get(op->ptr, "interpolation");
- op_props->cuts = RNA_int_get(op->ptr, "number_cuts");
- op_props->smooth = RNA_float_get(op->ptr, "smoothness");
+ op_props->interp_mode = RNA_enum_get(op->ptr, "interpolation");
+ op_props->cuts = RNA_int_get(op->ptr, "number_cuts");
+ op_props->smooth = RNA_float_get(op->ptr, "smoothness");
- op_props->profile_shape = RNA_enum_get(op->ptr, "profile_shape");
- op_props->profile_shape_factor = RNA_float_get(op->ptr, "profile_shape_factor");
+ op_props->profile_shape = RNA_enum_get(op->ptr, "profile_shape");
+ op_props->profile_shape_factor = RNA_float_get(op->ptr, "profile_shape_factor");
}
static int edbm_subdivide_edge_ring_exec(bContext *C, wmOperator *op)
{
- 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);
- struct EdgeRingOpSubdProps op_props;
+ 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);
+ struct EdgeRingOpSubdProps op_props;
- mesh_operator_edgering_props_get(op, &op_props);
+ mesh_operator_edgering_props_get(op, &op_props);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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 (em->bm->totedgesel == 0) {
+ continue;
+ }
- if (!EDBM_op_callf(
- em, op,
- "subdivide_edgering edges=%he interp_mode=%i cuts=%i smooth=%f "
- "profile_shape=%i profile_shape_factor=%f",
- BM_ELEM_SELECT, op_props.interp_mode, op_props.cuts, op_props.smooth,
- op_props.profile_shape, op_props.profile_shape_factor))
- {
- continue;
- }
+ if (!EDBM_op_callf(em,
+ op,
+ "subdivide_edgering edges=%he interp_mode=%i cuts=%i smooth=%f "
+ "profile_shape=%i profile_shape_factor=%f",
+ BM_ELEM_SELECT,
+ op_props.interp_mode,
+ op_props.cuts,
+ op_props.smooth,
+ op_props.profile_shape,
+ op_props.profile_shape_factor)) {
+ continue;
+ }
- EDBM_update_generic(em, true, true);
- }
+ EDBM_update_generic(em, true, true);
+ }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_subdivide_edgering(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Subdivide Edge-Ring";
- ot->idname = "MESH_OT_subdivide_edgering";
+ /* identifiers */
+ ot->name = "Subdivide Edge-Ring";
+ ot->idname = "MESH_OT_subdivide_edgering";
- /* api callbacks */
- ot->exec = edbm_subdivide_edge_ring_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_subdivide_edge_ring_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- mesh_operator_edgering_props(ot, 1, 10);
+ /* properties */
+ mesh_operator_edgering_props(ot, 1, 10);
}
/** \} */
@@ -301,96 +357,94 @@ void MESH_OT_subdivide_edgering(wmOperatorType *ot)
static int edbm_unsubdivide_exec(bContext *C, wmOperator *op)
{
- const int iterations = RNA_int_get(op->ptr, "iterations");
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(view_layer, CTX_wm_view3d(C), &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 iterations = RNA_int_get(op->ptr, "iterations");
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
+ view_layer, CTX_wm_view3d(C), &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);
- if ((em->bm->totvertsel == 0) &&
- (em->bm->totedgesel == 0) &&
- (em->bm->totfacesel == 0))
- {
- continue;
- }
+ if ((em->bm->totvertsel == 0) && (em->bm->totedgesel == 0) && (em->bm->totfacesel == 0)) {
+ continue;
+ }
- BMOperator bmop;
- EDBM_op_init(em, &bmop, op,
- "unsubdivide verts=%hv iterations=%i", BM_ELEM_SELECT, iterations);
+ BMOperator bmop;
+ EDBM_op_init(em, &bmop, op, "unsubdivide verts=%hv iterations=%i", BM_ELEM_SELECT, iterations);
- BMO_op_exec(em->bm, &bmop);
+ BMO_op_exec(em->bm, &bmop);
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
- if ((em->selectmode & SCE_SELECT_VERTEX) == 0) {
- EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX); /* need to flush vert->face first */
- }
- EDBM_selectmode_flush(em);
+ if ((em->selectmode & SCE_SELECT_VERTEX) == 0) {
+ EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX); /* need to flush vert->face first */
+ }
+ EDBM_selectmode_flush(em);
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_unsubdivide(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Un-Subdivide";
- ot->description = "UnSubdivide selected edges & faces";
- ot->idname = "MESH_OT_unsubdivide";
+ /* identifiers */
+ ot->name = "Un-Subdivide";
+ ot->description = "UnSubdivide selected edges & faces";
+ ot->idname = "MESH_OT_unsubdivide";
- /* api callbacks */
- ot->exec = edbm_unsubdivide_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_unsubdivide_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_int(ot->srna, "iterations", 2, 1, 1000, "Iterations", "Number of times to unsubdivide", 1, 100);
+ /* props */
+ RNA_def_int(
+ ot->srna, "iterations", 2, 1, 1000, "Iterations", "Number of times to unsubdivide", 1, 100);
}
void EDBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
{
- Main *bmain = CTX_data_main(C);
- Object *obedit = em->ob;
- 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), CTX_data_depsgraph(C), 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,
- co_proj, NULL))
- {
- mul_v3_m4v3(eve->co, obedit->imat, co_proj);
- }
- }
- }
- }
-
- ED_transform_snap_object_context_destroy(snap_context);
+ Main *bmain = CTX_data_main(C);
+ Object *obedit = em->ob;
+ 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), CTX_data_depsgraph(C), 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,
+ co_proj,
+ NULL)) {
+ mul_v3_m4v3(eve->co, obedit->imat, co_proj);
+ }
+ }
+ }
+ }
+
+ ED_transform_snap_object_context_destroy(snap_context);
}
/** \} */
@@ -401,117 +455,124 @@ void EDBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
/* Note, these values must match delete_mesh() event values */
enum {
- MESH_DELETE_VERT = 0,
- MESH_DELETE_EDGE = 1,
- MESH_DELETE_FACE = 2,
- MESH_DELETE_EDGE_FACE = 3,
- MESH_DELETE_ONLY_FACE = 4,
+ MESH_DELETE_VERT = 0,
+ MESH_DELETE_EDGE = 1,
+ MESH_DELETE_FACE = 2,
+ MESH_DELETE_EDGE_FACE = 3,
+ MESH_DELETE_ONLY_FACE = 4,
};
-static void edbm_report_delete_info(ReportList *reports, const int totelem_old[3], const int totelem_new[3])
+static void edbm_report_delete_info(ReportList *reports,
+ const int totelem_old[3],
+ const int totelem_new[3])
{
- BKE_reportf(reports, RPT_INFO,
- "Removed: %d vertices, %d edges, %d faces",
- totelem_old[0] - totelem_new[0], totelem_old[1] - totelem_new[1], totelem_old[2] - totelem_new[2]);
+ BKE_reportf(reports,
+ RPT_INFO,
+ "Removed: %d vertices, %d edges, %d faces",
+ totelem_old[0] - totelem_new[0],
+ totelem_old[1] - totelem_new[1],
+ totelem_old[2] - totelem_new[2]);
}
static int edbm_delete_exec(bContext *C, wmOperator *op)
{
- 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);
- bool changed_multi = false;
-
- 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 type = RNA_enum_get(op->ptr, "type");
-
- switch (type) {
- case MESH_DELETE_VERT: /* Erase Vertices */
- if (!(em->bm->totvertsel &&
- EDBM_op_callf(em, op, "delete geom=%hv context=%i", BM_ELEM_SELECT, DEL_VERTS)))
- {
- continue;
- }
- break;
- case MESH_DELETE_EDGE: /* Erase Edges */
- if (!(em->bm->totedgesel &&
- EDBM_op_callf(em, op, "delete geom=%he context=%i", BM_ELEM_SELECT, DEL_EDGES)))
- {
- continue;
- }
- break;
- case MESH_DELETE_FACE: /* Erase Faces */
- if (!(em->bm->totfacesel &&
- EDBM_op_callf(em, op, "delete geom=%hf context=%i", BM_ELEM_SELECT, DEL_FACES)))
- {
- continue;
- }
- break;
- case MESH_DELETE_EDGE_FACE:
- /* Edges and Faces */
- if (!((em->bm->totedgesel || em->bm->totfacesel) &&
- EDBM_op_callf(em, op, "delete geom=%hef context=%i", BM_ELEM_SELECT, DEL_EDGESFACES)))
- {
- continue;
- }
- break;
- case MESH_DELETE_ONLY_FACE:
- /* Only faces. */
- if (!(em->bm->totfacesel &&
- EDBM_op_callf(em, op, "delete geom=%hf context=%i", BM_ELEM_SELECT, DEL_ONLYFACES)))
- {
- continue;
- }
- break;
- default:
- BLI_assert(0);
- break;
- }
-
- changed_multi = true;
-
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
-
- EDBM_update_generic(em, true, true);
- }
-
- MEM_freeN(objects);
-
- return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ bool changed_multi = false;
+
+ 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 type = RNA_enum_get(op->ptr, "type");
+
+ switch (type) {
+ case MESH_DELETE_VERT: /* Erase Vertices */
+ if (!(em->bm->totvertsel &&
+ EDBM_op_callf(em, op, "delete geom=%hv context=%i", BM_ELEM_SELECT, DEL_VERTS))) {
+ continue;
+ }
+ break;
+ case MESH_DELETE_EDGE: /* Erase Edges */
+ if (!(em->bm->totedgesel &&
+ EDBM_op_callf(em, op, "delete geom=%he context=%i", BM_ELEM_SELECT, DEL_EDGES))) {
+ continue;
+ }
+ break;
+ case MESH_DELETE_FACE: /* Erase Faces */
+ if (!(em->bm->totfacesel &&
+ EDBM_op_callf(em, op, "delete geom=%hf context=%i", BM_ELEM_SELECT, DEL_FACES))) {
+ continue;
+ }
+ break;
+ case MESH_DELETE_EDGE_FACE:
+ /* Edges and Faces */
+ if (!((em->bm->totedgesel || em->bm->totfacesel) &&
+ EDBM_op_callf(
+ em, op, "delete geom=%hef context=%i", BM_ELEM_SELECT, DEL_EDGESFACES))) {
+ continue;
+ }
+ break;
+ case MESH_DELETE_ONLY_FACE:
+ /* Only faces. */
+ if (!(em->bm->totfacesel &&
+ EDBM_op_callf(
+ em, op, "delete geom=%hf context=%i", BM_ELEM_SELECT, DEL_ONLYFACES))) {
+ continue;
+ }
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ changed_multi = true;
+
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+
+ EDBM_update_generic(em, true, true);
+ }
+
+ MEM_freeN(objects);
+
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void MESH_OT_delete(wmOperatorType *ot)
{
- static const EnumPropertyItem prop_mesh_delete_types[] = {
- {MESH_DELETE_VERT, "VERT", 0, "Vertices", ""},
- {MESH_DELETE_EDGE, "EDGE", 0, "Edges", ""},
- {MESH_DELETE_FACE, "FACE", 0, "Faces", ""},
- {MESH_DELETE_EDGE_FACE, "EDGE_FACE", 0, "Only Edges & Faces", ""},
- {MESH_DELETE_ONLY_FACE, "ONLY_FACE", 0, "Only Faces", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem prop_mesh_delete_types[] = {
+ {MESH_DELETE_VERT, "VERT", 0, "Vertices", ""},
+ {MESH_DELETE_EDGE, "EDGE", 0, "Edges", ""},
+ {MESH_DELETE_FACE, "FACE", 0, "Faces", ""},
+ {MESH_DELETE_EDGE_FACE, "EDGE_FACE", 0, "Only Edges & Faces", ""},
+ {MESH_DELETE_ONLY_FACE, "ONLY_FACE", 0, "Only Faces", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Delete";
- ot->description = "Delete selected vertices, edges or faces";
- ot->idname = "MESH_OT_delete";
+ /* identifiers */
+ ot->name = "Delete";
+ ot->description = "Delete selected vertices, edges or faces";
+ ot->idname = "MESH_OT_delete";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = edbm_delete_exec;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = edbm_delete_exec;
- ot->poll = ED_operator_editmesh;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_mesh_delete_types, MESH_DELETE_VERT,
- "Type", "Method used for deleting mesh data");
- RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ /* props */
+ ot->prop = RNA_def_enum(ot->srna,
+ "type",
+ prop_mesh_delete_types,
+ MESH_DELETE_VERT,
+ "Type",
+ "Method used for deleting mesh data");
+ RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/** \} */
@@ -522,113 +583,113 @@ void MESH_OT_delete(wmOperatorType *ot)
static bool bm_face_is_loose(BMFace *f)
{
- BMLoop *l_iter, *l_first;
+ BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (!BM_edge_is_boundary(l_iter->e)) {
- return false;
- }
- } while ((l_iter = l_iter->next) != l_first);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (!BM_edge_is_boundary(l_iter->e)) {
+ return false;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
- return true;
+ return true;
}
static int edbm_delete_loose_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- int totelem_old_sel[3];
- int totelem_old[3];
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ int totelem_old_sel[3];
+ int totelem_old[3];
- 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);
+ 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);
- EDBM_mesh_stats_multi(objects, objects_len, totelem_old, totelem_old_sel);
+ EDBM_mesh_stats_multi(objects, objects_len, totelem_old, totelem_old_sel);
- const bool use_verts = (RNA_boolean_get(op->ptr, "use_verts") && totelem_old_sel[0]);
- const bool use_edges = (RNA_boolean_get(op->ptr, "use_edges") && totelem_old_sel[1]);
- const bool use_faces = (RNA_boolean_get(op->ptr, "use_faces") && totelem_old_sel[2]);
+ const bool use_verts = (RNA_boolean_get(op->ptr, "use_verts") && totelem_old_sel[0]);
+ const bool use_edges = (RNA_boolean_get(op->ptr, "use_edges") && totelem_old_sel[1]);
+ const bool use_faces = (RNA_boolean_get(op->ptr, "use_faces") && totelem_old_sel[2]);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMIter iter;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMIter iter;
- BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
- if (use_faces) {
- BMFace *f;
+ if (use_faces) {
+ BMFace *f;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- BM_elem_flag_set(f, BM_ELEM_TAG, bm_face_is_loose(f));
- }
- }
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_elem_flag_set(f, BM_ELEM_TAG, bm_face_is_loose(f));
+ }
+ }
- BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_FACES);
- }
+ BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_FACES);
+ }
- if (use_edges) {
- BMEdge *e;
+ if (use_edges) {
+ BMEdge *e;
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- BM_elem_flag_set(e, BM_ELEM_TAG, BM_edge_is_wire(e));
- }
- }
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ BM_elem_flag_set(e, BM_ELEM_TAG, BM_edge_is_wire(e));
+ }
+ }
- BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_EDGES);
- }
+ BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_EDGES);
+ }
- if (use_verts) {
- BMVert *v;
+ if (use_verts) {
+ BMVert *v;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- BM_elem_flag_set(v, BM_ELEM_TAG, (v->e == NULL));
- }
- }
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ BM_elem_flag_set(v, BM_ELEM_TAG, (v->e == NULL));
+ }
+ }
- BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_VERTS);
- }
+ BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_VERTS);
+ }
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- EDBM_update_generic(em, true, true);
- }
+ EDBM_update_generic(em, true, true);
+ }
- int totelem_new[3];
- EDBM_mesh_stats_multi(objects, objects_len, totelem_new, NULL);
+ int totelem_new[3];
+ EDBM_mesh_stats_multi(objects, objects_len, totelem_new, NULL);
- edbm_report_delete_info(op->reports, totelem_old, totelem_new);
+ edbm_report_delete_info(op->reports, totelem_old, totelem_new);
- MEM_freeN(objects);
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
void MESH_OT_delete_loose(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Loose";
- ot->description = "Delete loose vertices, edges or faces";
- ot->idname = "MESH_OT_delete_loose";
+ /* identifiers */
+ ot->name = "Delete Loose";
+ ot->description = "Delete loose vertices, edges or faces";
+ ot->idname = "MESH_OT_delete_loose";
- /* api callbacks */
- ot->exec = edbm_delete_loose_exec;
+ /* api callbacks */
+ ot->exec = edbm_delete_loose_exec;
- ot->poll = ED_operator_editmesh;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "use_verts", true, "Vertices", "Remove loose vertices");
- RNA_def_boolean(ot->srna, "use_edges", true, "Edges", "Remove loose edges");
- RNA_def_boolean(ot->srna, "use_faces", false, "Faces", "Remove loose faces");
+ /* props */
+ RNA_def_boolean(ot->srna, "use_verts", true, "Vertices", "Remove loose vertices");
+ RNA_def_boolean(ot->srna, "use_edges", true, "Edges", "Remove loose edges");
+ RNA_def_boolean(ot->srna, "use_faces", false, "Faces", "Remove loose faces");
}
/** \} */
@@ -639,41 +700,42 @@ void MESH_OT_delete_loose(wmOperatorType *ot)
static int edbm_collapse_edge_exec(bContext *C, wmOperator *op)
{
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totedgesel == 0) {
- continue;
- }
+ if (em->bm->totedgesel == 0) {
+ continue;
+ }
- if (!EDBM_op_callf(em, op, "collapse edges=%he uvs=%b", BM_ELEM_SELECT, true)) {
- continue;
- }
+ if (!EDBM_op_callf(em, op, "collapse edges=%he uvs=%b", BM_ELEM_SELECT, true)) {
+ continue;
+ }
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_edge_collapse(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Edge Collapse";
- ot->description = "Collapse selected edges";
- ot->idname = "MESH_OT_edge_collapse";
+ /* identifiers */
+ ot->name = "Edge Collapse";
+ ot->description = "Collapse selected edges";
+ ot->idname = "MESH_OT_edge_collapse";
- /* api callbacks */
- ot->exec = edbm_collapse_edge_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_collapse_edge_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -684,18 +746,18 @@ void MESH_OT_edge_collapse(wmOperatorType *ot)
static bool edbm_add_edge_face__smooth_get(BMesh *bm)
{
- BMEdge *e;
- BMIter iter;
+ BMEdge *e;
+ BMIter iter;
- unsigned int vote_on_smooth[2] = {0, 0};
+ unsigned int 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) {
- vote_on_smooth[BM_elem_flag_test_bool(e->l->f, BM_ELEM_SMOOTH)]++;
- }
- }
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT) && e->l) {
+ vote_on_smooth[BM_elem_flag_test_bool(e->l->f, BM_ELEM_SMOOTH)]++;
+ }
+ }
- return (vote_on_smooth[0] < vote_on_smooth[1]);
+ return (vote_on_smooth[0] < vote_on_smooth[1]);
}
#ifdef USE_FACE_CREATE_SEL_EXTEND
@@ -704,255 +766,257 @@ static bool edbm_add_edge_face__smooth_get(BMesh *bm)
* This is used so we can request all boundary edges connected to a vertex for eg.
*/
static int edbm_add_edge_face_exec__vert_edge_lookup(
- BMVert *v, BMEdge *e_used, BMEdge **e_arr, const int e_arr_len,
- bool (* func)(const BMEdge *))
-{
- BMIter iter;
- BMEdge *e_iter;
- int i = 0;
- BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) {
- if ((e_used == NULL) || (e_used != e_iter)) {
- if (func(e_iter)) {
- e_arr[i++] = e_iter;
- if (i >= e_arr_len) {
- break;
- }
- }
- }
- }
- }
- return i;
+ BMVert *v, BMEdge *e_used, BMEdge **e_arr, const int e_arr_len, bool (*func)(const BMEdge *))
+{
+ BMIter iter;
+ BMEdge *e_iter;
+ int i = 0;
+ BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) {
+ if ((e_used == NULL) || (e_used != e_iter)) {
+ if (func(e_iter)) {
+ e_arr[i++] = e_iter;
+ if (i >= e_arr_len) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ return i;
}
static BMElem *edbm_add_edge_face_exec__tricky_extend_sel(BMesh *bm)
{
- BMIter iter;
- bool found = false;
-
- if (bm->totvertsel == 1 && bm->totedgesel == 0 && bm->totfacesel == 0) {
- /* first look for 2 boundary edges */
- BMVert *v;
-
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- found = true;
- break;
- }
- }
-
- if (found) {
- BMEdge *ed_pair[3];
- if (
- ((edbm_add_edge_face_exec__vert_edge_lookup(v, NULL, ed_pair, 3, BM_edge_is_wire) == 2) &&
- (BM_edge_share_face_check(ed_pair[0], ed_pair[1]) == false)) ||
-
- ((edbm_add_edge_face_exec__vert_edge_lookup(v, NULL, ed_pair, 3, BM_edge_is_boundary) == 2) &&
- (BM_edge_share_face_check(ed_pair[0], ed_pair[1]) == false))
- )
- {
- BMEdge *e_other = BM_edge_exists(
- BM_edge_other_vert(ed_pair[0], v),
- BM_edge_other_vert(ed_pair[1], v));
- BM_edge_select_set(bm, ed_pair[0], true);
- BM_edge_select_set(bm, ed_pair[1], true);
- if (e_other) {
- BM_edge_select_set(bm, e_other, true);
- }
- return (BMElem *)v;
- }
- }
- }
- else if (bm->totvertsel == 2 && bm->totedgesel == 1 && bm->totfacesel == 0) {
- /* first look for 2 boundary edges */
- BMEdge *e;
-
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- found = true;
- break;
- }
- }
- if (found) {
- BMEdge *ed_pair_v1[2];
- BMEdge *ed_pair_v2[2];
- if (
- ((edbm_add_edge_face_exec__vert_edge_lookup(e->v1, e, ed_pair_v1, 2, BM_edge_is_wire) == 1) &&
- (edbm_add_edge_face_exec__vert_edge_lookup(e->v2, e, ed_pair_v2, 2, BM_edge_is_wire) == 1) &&
- (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) &&
- (BM_edge_share_face_check(e, ed_pair_v2[0]) == false)) ||
-
-#if 1 /* better support mixed cases [#37203] */
- ((edbm_add_edge_face_exec__vert_edge_lookup(e->v1, e, ed_pair_v1, 2, BM_edge_is_wire) == 1) &&
- (edbm_add_edge_face_exec__vert_edge_lookup(e->v2, e, ed_pair_v2, 2, BM_edge_is_boundary) == 1) &&
- (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) &&
- (BM_edge_share_face_check(e, ed_pair_v2[0]) == false)) ||
-
- ((edbm_add_edge_face_exec__vert_edge_lookup(e->v1, e, ed_pair_v1, 2, BM_edge_is_boundary) == 1) &&
- (edbm_add_edge_face_exec__vert_edge_lookup(e->v2, e, ed_pair_v2, 2, BM_edge_is_wire) == 1) &&
- (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) &&
- (BM_edge_share_face_check(e, ed_pair_v2[0]) == false)) ||
-#endif
-
- ((edbm_add_edge_face_exec__vert_edge_lookup(e->v1, e, ed_pair_v1, 2, BM_edge_is_boundary) == 1) &&
- (edbm_add_edge_face_exec__vert_edge_lookup(e->v2, e, ed_pair_v2, 2, BM_edge_is_boundary) == 1) &&
- (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) &&
- (BM_edge_share_face_check(e, ed_pair_v2[0]) == false))
- )
- {
- BMVert *v1_other = BM_edge_other_vert(ed_pair_v1[0], e->v1);
- BMVert *v2_other = BM_edge_other_vert(ed_pair_v2[0], e->v2);
- BMEdge *e_other = (v1_other != v2_other) ? BM_edge_exists(v1_other, v2_other) : NULL;
- BM_edge_select_set(bm, ed_pair_v1[0], true);
- BM_edge_select_set(bm, ed_pair_v2[0], true);
- if (e_other) {
- BM_edge_select_set(bm, e_other, true);
- }
- return (BMElem *)e;
- }
- }
- }
-
- return NULL;
+ BMIter iter;
+ bool found = false;
+
+ if (bm->totvertsel == 1 && bm->totedgesel == 0 && bm->totfacesel == 0) {
+ /* first look for 2 boundary edges */
+ BMVert *v;
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ BMEdge *ed_pair[3];
+ if (((edbm_add_edge_face_exec__vert_edge_lookup(v, NULL, ed_pair, 3, BM_edge_is_wire) ==
+ 2) &&
+ (BM_edge_share_face_check(ed_pair[0], ed_pair[1]) == false)) ||
+
+ ((edbm_add_edge_face_exec__vert_edge_lookup(v, NULL, ed_pair, 3, BM_edge_is_boundary) ==
+ 2) &&
+ (BM_edge_share_face_check(ed_pair[0], ed_pair[1]) == false))) {
+ BMEdge *e_other = BM_edge_exists(BM_edge_other_vert(ed_pair[0], v),
+ BM_edge_other_vert(ed_pair[1], v));
+ BM_edge_select_set(bm, ed_pair[0], true);
+ BM_edge_select_set(bm, ed_pair[1], true);
+ if (e_other) {
+ BM_edge_select_set(bm, e_other, true);
+ }
+ return (BMElem *)v;
+ }
+ }
+ }
+ else if (bm->totvertsel == 2 && bm->totedgesel == 1 && bm->totfacesel == 0) {
+ /* first look for 2 boundary edges */
+ BMEdge *e;
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ BMEdge *ed_pair_v1[2];
+ BMEdge *ed_pair_v2[2];
+ if (((edbm_add_edge_face_exec__vert_edge_lookup(e->v1, e, ed_pair_v1, 2, BM_edge_is_wire) ==
+ 1) &&
+ (edbm_add_edge_face_exec__vert_edge_lookup(e->v2, e, ed_pair_v2, 2, BM_edge_is_wire) ==
+ 1) &&
+ (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) &&
+ (BM_edge_share_face_check(e, ed_pair_v2[0]) == false)) ||
+
+# if 1 /* better support mixed cases [#37203] */
+ ((edbm_add_edge_face_exec__vert_edge_lookup(e->v1, e, ed_pair_v1, 2, BM_edge_is_wire) ==
+ 1) &&
+ (edbm_add_edge_face_exec__vert_edge_lookup(
+ e->v2, e, ed_pair_v2, 2, BM_edge_is_boundary) == 1) &&
+ (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) &&
+ (BM_edge_share_face_check(e, ed_pair_v2[0]) == false)) ||
+
+ ((edbm_add_edge_face_exec__vert_edge_lookup(
+ e->v1, e, ed_pair_v1, 2, BM_edge_is_boundary) == 1) &&
+ (edbm_add_edge_face_exec__vert_edge_lookup(e->v2, e, ed_pair_v2, 2, BM_edge_is_wire) ==
+ 1) &&
+ (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) &&
+ (BM_edge_share_face_check(e, ed_pair_v2[0]) == false)) ||
+# endif
+
+ ((edbm_add_edge_face_exec__vert_edge_lookup(
+ e->v1, e, ed_pair_v1, 2, BM_edge_is_boundary) == 1) &&
+ (edbm_add_edge_face_exec__vert_edge_lookup(
+ e->v2, e, ed_pair_v2, 2, BM_edge_is_boundary) == 1) &&
+ (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) &&
+ (BM_edge_share_face_check(e, ed_pair_v2[0]) == false))) {
+ BMVert *v1_other = BM_edge_other_vert(ed_pair_v1[0], e->v1);
+ BMVert *v2_other = BM_edge_other_vert(ed_pair_v2[0], e->v2);
+ BMEdge *e_other = (v1_other != v2_other) ? BM_edge_exists(v1_other, v2_other) : NULL;
+ BM_edge_select_set(bm, ed_pair_v1[0], true);
+ BM_edge_select_set(bm, ed_pair_v2[0], true);
+ if (e_other) {
+ BM_edge_select_set(bm, e_other, true);
+ }
+ return (BMElem *)e;
+ }
+ }
+ }
+
+ return NULL;
}
static void edbm_add_edge_face_exec__tricky_finalize_sel(BMesh *bm, BMElem *ele_desel, BMFace *f)
{
- /* now we need to find the edge that isnt connected to this element */
- BM_select_history_clear(bm);
-
- /* Notes on hidden geometry:
- * - un-hide the face since its possible hidden was copied when copying surrounding face attributes.
- * - un-hide before adding to select history
- * since we may extend into an existing, hidden vert/edge.
- */
-
- BM_elem_flag_disable(f, BM_ELEM_HIDDEN);
- BM_face_select_set(bm, f, false);
-
- if (ele_desel->head.htype == BM_VERT) {
- BMLoop *l = BM_face_vert_share_loop(f, (BMVert *)ele_desel);
- BLI_assert(f->len == 3);
- BM_vert_select_set(bm, (BMVert *)ele_desel, false);
- BM_edge_select_set(bm, l->next->e, true);
- BM_select_history_store(bm, l->next->e);
- }
- else {
- BMLoop *l = BM_face_edge_share_loop(f, (BMEdge *)ele_desel);
- BLI_assert(f->len == 4 || f->len == 3);
-
- BM_edge_select_set(bm, (BMEdge *)ele_desel, false);
- if (f->len == 4) {
- BMEdge *e_active = l->next->next->e;
- BM_elem_flag_disable(e_active, BM_ELEM_HIDDEN);
- BM_edge_select_set(bm, e_active, true);
- BM_select_history_store(bm, e_active);
- }
- else {
- BMVert *v_active = l->next->next->v;
- BM_elem_flag_disable(v_active, BM_ELEM_HIDDEN);
- BM_vert_select_set(bm, v_active, true);
- BM_select_history_store(bm, v_active);
- }
- }
-}
-#endif /* USE_FACE_CREATE_SEL_EXTEND */
+ /* now we need to find the edge that isnt connected to this element */
+ BM_select_history_clear(bm);
+
+ /* Notes on hidden geometry:
+ * - un-hide the face since its possible hidden was copied when copying surrounding face attributes.
+ * - un-hide before adding to select history
+ * since we may extend into an existing, hidden vert/edge.
+ */
+
+ BM_elem_flag_disable(f, BM_ELEM_HIDDEN);
+ BM_face_select_set(bm, f, false);
+
+ if (ele_desel->head.htype == BM_VERT) {
+ BMLoop *l = BM_face_vert_share_loop(f, (BMVert *)ele_desel);
+ BLI_assert(f->len == 3);
+ BM_vert_select_set(bm, (BMVert *)ele_desel, false);
+ BM_edge_select_set(bm, l->next->e, true);
+ BM_select_history_store(bm, l->next->e);
+ }
+ else {
+ BMLoop *l = BM_face_edge_share_loop(f, (BMEdge *)ele_desel);
+ BLI_assert(f->len == 4 || f->len == 3);
+
+ BM_edge_select_set(bm, (BMEdge *)ele_desel, false);
+ if (f->len == 4) {
+ BMEdge *e_active = l->next->next->e;
+ BM_elem_flag_disable(e_active, BM_ELEM_HIDDEN);
+ BM_edge_select_set(bm, e_active, true);
+ BM_select_history_store(bm, e_active);
+ }
+ else {
+ BMVert *v_active = l->next->next->v;
+ BM_elem_flag_disable(v_active, BM_ELEM_HIDDEN);
+ BM_vert_select_set(bm, v_active, true);
+ BM_select_history_store(bm, v_active);
+ }
+ }
+}
+#endif /* USE_FACE_CREATE_SEL_EXTEND */
static int edbm_add_edge_face_exec(bContext *C, wmOperator *op)
{
- /* when this is used to dissolve we could avoid this, but checking isnt too slow */
+ /* when this is used to dissolve we could avoid this, but checking isnt too slow */
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if ((em->bm->totvertsel == 0) &&
- (em->bm->totedgesel == 0) &&
- (em->bm->totvertsel == 0))
- {
- continue;
- }
+ if ((em->bm->totvertsel == 0) && (em->bm->totedgesel == 0) && (em->bm->totvertsel == 0)) {
+ continue;
+ }
- bool use_smooth = edbm_add_edge_face__smooth_get(em->bm);
- int totedge_orig = em->bm->totedge;
- int totface_orig = em->bm->totface;
+ bool use_smooth = edbm_add_edge_face__smooth_get(em->bm);
+ int totedge_orig = em->bm->totedge;
+ int totface_orig = em->bm->totface;
- BMOperator bmop;
+ BMOperator bmop;
#ifdef USE_FACE_CREATE_SEL_EXTEND
- BMElem *ele_desel;
- BMFace *ele_desel_face;
+ BMElem *ele_desel;
+ BMFace *ele_desel_face;
- /* be extra clever, figure out if a partial selection should be extended so we can create geometry
- * with single vert or single edge selection */
- ele_desel = edbm_add_edge_face_exec__tricky_extend_sel(em->bm);
+ /* be extra clever, figure out if a partial selection should be extended so we can create geometry
+ * with single vert or single edge selection */
+ ele_desel = edbm_add_edge_face_exec__tricky_extend_sel(em->bm);
#endif
- if (!EDBM_op_init(
- em, &bmop, op,
- "contextual_create geom=%hfev mat_nr=%i use_smooth=%b",
- BM_ELEM_SELECT, em->mat_nr, use_smooth))
- {
- continue;
- }
-
- BMO_op_exec(em->bm, &bmop);
-
- /* cancel if nothing was done */
- if ((totedge_orig == em->bm->totedge) &&
- (totface_orig == em->bm->totface))
- {
- EDBM_op_finish(em, &bmop, op, true);
- continue;
- }
+ if (!EDBM_op_init(em,
+ &bmop,
+ op,
+ "contextual_create geom=%hfev mat_nr=%i use_smooth=%b",
+ BM_ELEM_SELECT,
+ em->mat_nr,
+ use_smooth)) {
+ continue;
+ }
+
+ BMO_op_exec(em->bm, &bmop);
+
+ /* cancel if nothing was done */
+ if ((totedge_orig == em->bm->totedge) && (totface_orig == em->bm->totface)) {
+ EDBM_op_finish(em, &bmop, op, true);
+ continue;
+ }
#ifdef USE_FACE_CREATE_SEL_EXTEND
- /* normally we would want to leave the new geometry selected,
- * but being able to press F many times to add geometry is too useful! */
- if (ele_desel &&
- (BMO_slot_buffer_count(bmop.slots_out, "faces.out") == 1) &&
- (ele_desel_face = BMO_slot_buffer_get_first(bmop.slots_out, "faces.out")))
- {
- edbm_add_edge_face_exec__tricky_finalize_sel(em->bm, ele_desel, ele_desel_face);
- }
- else
+ /* normally we would want to leave the new geometry selected,
+ * but being able to press F many times to add geometry is too useful! */
+ if (ele_desel && (BMO_slot_buffer_count(bmop.slots_out, "faces.out") == 1) &&
+ (ele_desel_face = BMO_slot_buffer_get_first(bmop.slots_out, "faces.out"))) {
+ edbm_add_edge_face_exec__tricky_finalize_sel(em->bm, ele_desel, ele_desel_face);
+ }
+ else
#endif
- {
- /* Newly created faces may include existing hidden edges,
- * copying face data from surrounding, may have copied hidden face flag too.
- *
- * Important that faces use flushing since 'edges.out' wont include hidden edges that already existed.
- */
- BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_HIDDEN, true);
- BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_HIDDEN, false);
-
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
- 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;
- }
-
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ {
+ /* Newly created faces may include existing hidden edges,
+ * copying face data from surrounding, may have copied hidden face flag too.
+ *
+ * Important that faces use flushing since 'edges.out' wont include hidden edges that already existed.
+ */
+ BMO_slot_buffer_hflag_disable(
+ em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_HIDDEN, true);
+ BMO_slot_buffer_hflag_disable(
+ em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_HIDDEN, false);
+
+ BMO_slot_buffer_hflag_enable(
+ em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
+ 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;
+ }
+
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_edge_face_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Edge/Face";
- ot->description = "Add an edge or face to selected";
- ot->idname = "MESH_OT_edge_face_add";
+ /* identifiers */
+ ot->name = "Make Edge/Face";
+ ot->description = "Add an edge or face to selected";
+ ot->idname = "MESH_OT_edge_face_add";
- /* api callbacks */
- ot->exec = edbm_add_edge_face_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_add_edge_face_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -963,75 +1027,76 @@ void MESH_OT_edge_face_add(wmOperatorType *ot)
static int edbm_mark_seam_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- BMEdge *eed;
- BMIter iter;
- const bool clear = RNA_boolean_get(op->ptr, "clear");
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- if (bm->totedgesel == 0) {
- continue;
- }
-
- if (clear) {
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(eed, BM_ELEM_SELECT) || BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- continue;
- }
-
- BM_elem_flag_disable(eed, BM_ELEM_SEAM);
- }
- }
- else {
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(eed, BM_ELEM_SELECT) || BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- continue;
- }
- BM_elem_flag_enable(eed, BM_ELEM_SEAM);
- }
- }
- }
-
- ED_uvedit_live_unwrap(scene, objects, 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);
- EDBM_update_generic(em, true, false);
- }
-
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ BMEdge *eed;
+ BMIter iter;
+ const bool clear = RNA_boolean_get(op->ptr, "clear");
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ if (bm->totedgesel == 0) {
+ continue;
+ }
+
+ if (clear) {
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(eed, BM_ELEM_SELECT) || BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+ continue;
+ }
+
+ BM_elem_flag_disable(eed, BM_ELEM_SEAM);
+ }
+ }
+ else {
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(eed, BM_ELEM_SELECT) || BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+ continue;
+ }
+ BM_elem_flag_enable(eed, BM_ELEM_SEAM);
+ }
+ }
+ }
+
+ ED_uvedit_live_unwrap(scene, objects, 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);
+ EDBM_update_generic(em, true, false);
+ }
+
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_mark_seam(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Mark Seam";
- ot->idname = "MESH_OT_mark_seam";
- ot->description = "(Un)mark selected edges as a seam";
+ /* identifiers */
+ ot->name = "Mark Seam";
+ ot->idname = "MESH_OT_mark_seam";
+ ot->description = "(Un)mark selected edges as a seam";
- /* api callbacks */
- ot->exec = edbm_mark_seam_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_mark_seam_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- WM_operatortype_props_advanced_begin(ot);
+ WM_operatortype_props_advanced_begin(ot);
}
/** \} */
@@ -1042,178 +1107,192 @@ void MESH_OT_mark_seam(wmOperatorType *ot)
static int edbm_mark_sharp_exec(bContext *C, wmOperator *op)
{
- BMEdge *eed;
- BMIter iter;
- const bool clear = RNA_boolean_get(op->ptr, "clear");
- const bool use_verts = RNA_boolean_get(op->ptr, "use_verts");
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- if (bm->totedgesel == 0) {
- continue;
- }
-
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (use_verts) {
- if (!(BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) || BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))) {
- continue;
- }
- }
- else if (!BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- continue;
- }
-
- BM_elem_flag_set(eed, BM_ELEM_SMOOTH, clear);
- }
-
- EDBM_update_generic(em, true, false);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ BMEdge *eed;
+ BMIter iter;
+ const bool clear = RNA_boolean_get(op->ptr, "clear");
+ const bool use_verts = RNA_boolean_get(op->ptr, "use_verts");
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ if (bm->totedgesel == 0) {
+ continue;
+ }
+
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (use_verts) {
+ if (!(BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
+ BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))) {
+ continue;
+ }
+ }
+ else if (!BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ continue;
+ }
+
+ BM_elem_flag_set(eed, BM_ELEM_SMOOTH, clear);
+ }
+
+ EDBM_update_generic(em, true, false);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_mark_sharp(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Mark Sharp";
- ot->idname = "MESH_OT_mark_sharp";
- ot->description = "(Un)mark selected edges as sharp";
+ /* identifiers */
+ ot->name = "Mark Sharp";
+ ot->idname = "MESH_OT_mark_sharp";
+ ot->description = "(Un)mark selected edges as sharp";
- /* api callbacks */
- ot->exec = edbm_mark_sharp_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_mark_sharp_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "use_verts", false, "Vertices",
- "Consider vertices instead of edges to select which edges to (un)tag as sharp");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(
+ ot->srna,
+ "use_verts",
+ false,
+ "Vertices",
+ "Consider vertices instead of edges to select which edges to (un)tag as sharp");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static bool edbm_connect_vert_pair(BMEditMesh *em, wmOperator *op)
{
- BMesh *bm = em->bm;
- BMOperator bmop;
- const int verts_len = bm->totvertsel;
- bool is_pair = (verts_len == 2);
- int len = 0;
- bool check_degenerate = true;
-
- BMVert **verts;
- bool checks_succeded = true;
-
- /* sanity check */
- if (verts_len < 2) {
- return false;
- }
-
- verts = MEM_mallocN(sizeof(*verts) * verts_len, __func__);
- {
- BMIter iter;
- BMVert *v;
- int i = 0;
-
- BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- verts[i++] = v;
- }
- }
-
- if (BM_vert_pair_share_face_check_cb(
- verts[0], verts[1],
- BM_elem_cb_check_hflag_disabled_simple(BMFace *, BM_ELEM_HIDDEN)))
- {
- check_degenerate = false;
- is_pair = false;
- }
- }
-
- if (is_pair) {
- if (!EDBM_op_init(
- em, &bmop, op,
- "connect_vert_pair verts=%eb verts_exclude=%hv faces_exclude=%hf",
- verts, verts_len, BM_ELEM_HIDDEN, BM_ELEM_HIDDEN))
- {
- checks_succeded = false;
- }
- }
- else {
- if (!EDBM_op_init(
- em, &bmop, op,
- "connect_verts verts=%eb faces_exclude=%hf check_degenerate=%b",
- verts, verts_len, BM_ELEM_HIDDEN, check_degenerate))
- {
- checks_succeded = false;
- }
- }
- if (checks_succeded) {
- BMO_op_exec(bm, &bmop);
- len = BMO_slot_get(bmop.slots_out, "edges.out")->len;
-
- if (len && is_pair) {
- /* new verts have been added, we have to select the edges, not just flush */
- 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)) {
- len = 0;
- }
- else {
- /* so newly created edges get the selection state from the vertex */
- EDBM_selectmode_flush(em);
-
- EDBM_update_generic(em, true, true);
- }
- }
- MEM_freeN(verts);
-
- return len;
+ BMesh *bm = em->bm;
+ BMOperator bmop;
+ const int verts_len = bm->totvertsel;
+ bool is_pair = (verts_len == 2);
+ int len = 0;
+ bool check_degenerate = true;
+
+ BMVert **verts;
+ bool checks_succeded = true;
+
+ /* sanity check */
+ if (verts_len < 2) {
+ return false;
+ }
+
+ verts = MEM_mallocN(sizeof(*verts) * verts_len, __func__);
+ {
+ BMIter iter;
+ BMVert *v;
+ int i = 0;
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ verts[i++] = v;
+ }
+ }
+
+ if (BM_vert_pair_share_face_check_cb(
+ verts[0],
+ verts[1],
+ BM_elem_cb_check_hflag_disabled_simple(BMFace *, BM_ELEM_HIDDEN))) {
+ check_degenerate = false;
+ is_pair = false;
+ }
+ }
+
+ if (is_pair) {
+ if (!EDBM_op_init(em,
+ &bmop,
+ op,
+ "connect_vert_pair verts=%eb verts_exclude=%hv faces_exclude=%hf",
+ verts,
+ verts_len,
+ BM_ELEM_HIDDEN,
+ BM_ELEM_HIDDEN)) {
+ checks_succeded = false;
+ }
+ }
+ else {
+ if (!EDBM_op_init(em,
+ &bmop,
+ op,
+ "connect_verts verts=%eb faces_exclude=%hf check_degenerate=%b",
+ verts,
+ verts_len,
+ BM_ELEM_HIDDEN,
+ check_degenerate)) {
+ checks_succeded = false;
+ }
+ }
+ if (checks_succeded) {
+ BMO_op_exec(bm, &bmop);
+ len = BMO_slot_get(bmop.slots_out, "edges.out")->len;
+
+ if (len && is_pair) {
+ /* new verts have been added, we have to select the edges, not just flush */
+ 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)) {
+ len = 0;
+ }
+ else {
+ /* so newly created edges get the selection state from the vertex */
+ EDBM_selectmode_flush(em);
+
+ EDBM_update_generic(em, true, true);
+ }
+ }
+ MEM_freeN(verts);
+
+ return len;
}
static int edbm_vert_connect_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- uint failed_objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ uint failed_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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (!edbm_connect_vert_pair(em, op)) {
- failed_objects_len++;
- }
- }
- MEM_freeN(objects);
- return failed_objects_len == objects_len ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ if (!edbm_connect_vert_pair(em, op)) {
+ failed_objects_len++;
+ }
+ }
+ MEM_freeN(objects);
+ return failed_objects_len == objects_len ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void MESH_OT_vert_connect(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Vertex Connect";
- ot->idname = "MESH_OT_vert_connect";
- ot->description = "Connect selected vertices of faces, splitting the face";
+ /* identifiers */
+ ot->name = "Vertex Connect";
+ ot->idname = "MESH_OT_vert_connect";
+ ot->description = "Connect selected vertices of faces, splitting the face";
- /* api callbacks */
- ot->exec = edbm_vert_connect_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_vert_connect_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -1227,146 +1306,139 @@ void MESH_OT_vert_connect(wmOperatorType *ot)
*/
static bool bm_vert_is_select_history_open(BMesh *bm)
{
- BMEditSelection *ele_a = bm->selected.first;
- BMEditSelection *ele_b = bm->selected.last;
- if ((ele_a->htype == BM_VERT) &&
- (ele_b->htype == BM_VERT))
- {
- if ((BM_iter_elem_count_flag(BM_EDGES_OF_VERT, (BMVert *)ele_a->ele, BM_ELEM_SELECT, true) == 1) &&
- (BM_iter_elem_count_flag(BM_EDGES_OF_VERT, (BMVert *)ele_b->ele, BM_ELEM_SELECT, true) == 1))
- {
- return true;
- }
- }
+ BMEditSelection *ele_a = bm->selected.first;
+ BMEditSelection *ele_b = bm->selected.last;
+ if ((ele_a->htype == BM_VERT) && (ele_b->htype == BM_VERT)) {
+ if ((BM_iter_elem_count_flag(BM_EDGES_OF_VERT, (BMVert *)ele_a->ele, BM_ELEM_SELECT, true) ==
+ 1) &&
+ (BM_iter_elem_count_flag(BM_EDGES_OF_VERT, (BMVert *)ele_b->ele, BM_ELEM_SELECT, true) ==
+ 1)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
static bool bm_vert_connect_pair(BMesh *bm, BMVert *v_a, BMVert *v_b)
{
- BMOperator bmop;
- BMVert **verts;
- const int totedge_orig = bm->totedge;
+ BMOperator bmop;
+ BMVert **verts;
+ const int totedge_orig = bm->totedge;
- BMO_op_init(bm, &bmop, BMO_FLAG_DEFAULTS, "connect_vert_pair");
+ BMO_op_init(bm, &bmop, BMO_FLAG_DEFAULTS, "connect_vert_pair");
- verts = BMO_slot_buffer_alloc(&bmop, bmop.slots_in, "verts", 2);
- verts[0] = v_a;
- verts[1] = v_b;
+ verts = BMO_slot_buffer_alloc(&bmop, bmop.slots_in, "verts", 2);
+ verts[0] = v_a;
+ verts[1] = v_b;
- BM_vert_normal_update(verts[0]);
- BM_vert_normal_update(verts[1]);
+ BM_vert_normal_update(verts[0]);
+ BM_vert_normal_update(verts[1]);
- BMO_op_exec(bm, &bmop);
- BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
- BMO_op_finish(bm, &bmop);
- return (bm->totedge != totedge_orig);
+ BMO_op_exec(bm, &bmop);
+ BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
+ BMO_op_finish(bm, &bmop);
+ return (bm->totedge != totedge_orig);
}
static bool bm_vert_connect_select_history(BMesh *bm)
{
- /* Logic is as follows:
- *
- * - If there are any isolated/wire verts - connect as edges.
- * - Otherwise connect faces.
- * - If all edges have been created already, closed the loop.
- */
- if (BLI_listbase_count_at_most(&bm->selected, 2) == 2 && (bm->totvertsel > 2)) {
- BMEditSelection *ese;
- int tot = 0;
- bool changed = false;
- bool has_wire = false;
- // bool all_verts;
-
- /* ensure all verts have history */
- for (ese = bm->selected.first; ese; ese = ese->next, tot++) {
- BMVert *v;
- if (ese->htype != BM_VERT) {
- break;
- }
- v = (BMVert *)ese->ele;
- if ((has_wire == false) && ((v->e == NULL) || BM_vert_is_wire(v))) {
- has_wire = true;
- }
- }
- // all_verts = (ese == NULL);
-
- if (has_wire == false) {
- /* all verts have faces , connect verts via faces! */
- if (tot == bm->totvertsel) {
- BMEditSelection *ese_last;
- ese_last = bm->selected.first;
- ese = ese_last->next;
-
- do {
-
- if (BM_edge_exists((BMVert *)ese_last->ele, (BMVert *)ese->ele)) {
- /* pass, edge exists (and will be selected) */
- }
- else {
- changed |= bm_vert_connect_pair(bm, (BMVert *)ese_last->ele, (BMVert *)ese->ele);
- }
- } while ((void)
- (ese_last = ese),
- (ese = ese->next));
-
- if (changed) {
- return true;
- }
- }
-
- if (changed == false) {
- /* existing loops: close the selection */
- if (bm_vert_is_select_history_open(bm)) {
- changed |= bm_vert_connect_pair(
- bm,
- (BMVert *)((BMEditSelection *)bm->selected.first)->ele,
- (BMVert *)((BMEditSelection *)bm->selected.last)->ele);
-
- if (changed) {
- return true;
- }
- }
- }
- }
-
- else {
- /* no faces, simply connect the verts by edges */
- BMEditSelection *ese_prev;
- ese_prev = bm->selected.first;
- ese = ese_prev->next;
-
-
- do {
- if (BM_edge_exists((BMVert *)ese_prev->ele, (BMVert *)ese->ele)) {
- /* pass, edge exists (and will be selected) */
- }
- else {
- BMEdge *e;
- e = BM_edge_create(bm, (BMVert *)ese_prev->ele, (BMVert *)ese->ele, NULL, 0);
- BM_edge_select_set(bm, e, true);
- changed = true;
- }
- } while ((void)
- (ese_prev = ese),
- (ese = ese->next));
-
- if (changed == false) {
- /* existing loops: close the selection */
- if (bm_vert_is_select_history_open(bm)) {
- BMEdge *e;
- ese_prev = bm->selected.first;
- ese = bm->selected.last;
- e = BM_edge_create(bm, (BMVert *)ese_prev->ele, (BMVert *)ese->ele, NULL, 0);
- BM_edge_select_set(bm, e, true);
- }
- }
-
- return true;
- }
- }
-
- return false;
+ /* Logic is as follows:
+ *
+ * - If there are any isolated/wire verts - connect as edges.
+ * - Otherwise connect faces.
+ * - If all edges have been created already, closed the loop.
+ */
+ if (BLI_listbase_count_at_most(&bm->selected, 2) == 2 && (bm->totvertsel > 2)) {
+ BMEditSelection *ese;
+ int tot = 0;
+ bool changed = false;
+ bool has_wire = false;
+ // bool all_verts;
+
+ /* ensure all verts have history */
+ for (ese = bm->selected.first; ese; ese = ese->next, tot++) {
+ BMVert *v;
+ if (ese->htype != BM_VERT) {
+ break;
+ }
+ v = (BMVert *)ese->ele;
+ if ((has_wire == false) && ((v->e == NULL) || BM_vert_is_wire(v))) {
+ has_wire = true;
+ }
+ }
+ // all_verts = (ese == NULL);
+
+ if (has_wire == false) {
+ /* all verts have faces , connect verts via faces! */
+ if (tot == bm->totvertsel) {
+ BMEditSelection *ese_last;
+ ese_last = bm->selected.first;
+ ese = ese_last->next;
+
+ do {
+
+ if (BM_edge_exists((BMVert *)ese_last->ele, (BMVert *)ese->ele)) {
+ /* pass, edge exists (and will be selected) */
+ }
+ else {
+ changed |= bm_vert_connect_pair(bm, (BMVert *)ese_last->ele, (BMVert *)ese->ele);
+ }
+ } while ((void)(ese_last = ese), (ese = ese->next));
+
+ if (changed) {
+ return true;
+ }
+ }
+
+ if (changed == false) {
+ /* existing loops: close the selection */
+ if (bm_vert_is_select_history_open(bm)) {
+ changed |= bm_vert_connect_pair(bm,
+ (BMVert *)((BMEditSelection *)bm->selected.first)->ele,
+ (BMVert *)((BMEditSelection *)bm->selected.last)->ele);
+
+ if (changed) {
+ return true;
+ }
+ }
+ }
+ }
+
+ else {
+ /* no faces, simply connect the verts by edges */
+ BMEditSelection *ese_prev;
+ ese_prev = bm->selected.first;
+ ese = ese_prev->next;
+
+ do {
+ if (BM_edge_exists((BMVert *)ese_prev->ele, (BMVert *)ese->ele)) {
+ /* pass, edge exists (and will be selected) */
+ }
+ else {
+ BMEdge *e;
+ e = BM_edge_create(bm, (BMVert *)ese_prev->ele, (BMVert *)ese->ele, NULL, 0);
+ BM_edge_select_set(bm, e, true);
+ changed = true;
+ }
+ } while ((void)(ese_prev = ese), (ese = ese->next));
+
+ if (changed == false) {
+ /* existing loops: close the selection */
+ if (bm_vert_is_select_history_open(bm)) {
+ BMEdge *e;
+ ese_prev = bm->selected.first;
+ ese = bm->selected.last;
+ e = BM_edge_create(bm, (BMVert *)ese_prev->ele, (BMVert *)ese->ele, NULL, 0);
+ BM_edge_select_set(bm, e, true);
+ }
+ }
+
+ return true;
+ }
+ }
+
+ return false;
}
/**
@@ -1375,186 +1447,184 @@ static bool bm_vert_connect_select_history(BMesh *bm)
*/
static bool bm_vert_connect_select_history_edge_to_vert_path(BMesh *bm, ListBase *r_selected)
{
- ListBase selected_orig = {NULL, NULL};
- BMEditSelection *ese;
- int edges_len = 0;
- bool side = false;
-
- /* first check all edges are OK */
- for (ese = bm->selected.first; ese; ese = ese->next) {
- if (ese->htype == BM_EDGE) {
- edges_len += 1;
- }
- else {
- return false;
- }
- }
- /* if this is a mixed selection, bail out! */
- if (bm->totedgesel != edges_len) {
- return false;
- }
-
- SWAP(ListBase, bm->selected, selected_orig);
-
- /* convert edge selection into 2 ordered loops (where the first edge ends up in the middle) */
- for (ese = selected_orig.first; ese; ese = ese->next) {
- BMEdge *e_curr = (BMEdge *)ese->ele;
- BMEdge *e_prev = ese->prev ? (BMEdge *)ese->prev->ele : NULL;
- BMLoop *l_curr;
- BMLoop *l_prev;
- BMVert *v;
-
- if (e_prev) {
- BMFace *f = BM_edge_pair_share_face_by_len(e_curr, e_prev, &l_curr, &l_prev, true);
- if (f) {
- if ((e_curr->v1 != l_curr->v) == (e_prev->v1 != l_prev->v)) {
- side = !side;
- }
- }
- else if (is_quad_flip_v3(e_curr->v1->co, e_curr->v2->co, e_prev->v2->co, e_prev->v1->co)) {
- side = !side;
- }
- }
-
- v = (&e_curr->v1)[side];
- if (!bm->selected.last || (BMVert *)((BMEditSelection *)bm->selected.last)->ele != v) {
- BM_select_history_store_notest(bm, v);
- }
-
- v = (&e_curr->v1)[!side];
- if (!bm->selected.first || (BMVert *)((BMEditSelection *)bm->selected.first)->ele != v) {
- BM_select_history_store_head_notest(bm, v);
- }
-
- e_prev = e_curr;
- }
-
- *r_selected = bm->selected;
- bm->selected = selected_orig;
-
- return true;
+ ListBase selected_orig = {NULL, NULL};
+ BMEditSelection *ese;
+ int edges_len = 0;
+ bool side = false;
+
+ /* first check all edges are OK */
+ for (ese = bm->selected.first; ese; ese = ese->next) {
+ if (ese->htype == BM_EDGE) {
+ edges_len += 1;
+ }
+ else {
+ return false;
+ }
+ }
+ /* if this is a mixed selection, bail out! */
+ if (bm->totedgesel != edges_len) {
+ return false;
+ }
+
+ SWAP(ListBase, bm->selected, selected_orig);
+
+ /* convert edge selection into 2 ordered loops (where the first edge ends up in the middle) */
+ for (ese = selected_orig.first; ese; ese = ese->next) {
+ BMEdge *e_curr = (BMEdge *)ese->ele;
+ BMEdge *e_prev = ese->prev ? (BMEdge *)ese->prev->ele : NULL;
+ BMLoop *l_curr;
+ BMLoop *l_prev;
+ BMVert *v;
+
+ if (e_prev) {
+ BMFace *f = BM_edge_pair_share_face_by_len(e_curr, e_prev, &l_curr, &l_prev, true);
+ if (f) {
+ if ((e_curr->v1 != l_curr->v) == (e_prev->v1 != l_prev->v)) {
+ side = !side;
+ }
+ }
+ else if (is_quad_flip_v3(e_curr->v1->co, e_curr->v2->co, e_prev->v2->co, e_prev->v1->co)) {
+ side = !side;
+ }
+ }
+
+ v = (&e_curr->v1)[side];
+ if (!bm->selected.last || (BMVert *)((BMEditSelection *)bm->selected.last)->ele != v) {
+ BM_select_history_store_notest(bm, v);
+ }
+
+ v = (&e_curr->v1)[!side];
+ if (!bm->selected.first || (BMVert *)((BMEditSelection *)bm->selected.first)->ele != v) {
+ BM_select_history_store_head_notest(bm, v);
+ }
+
+ e_prev = e_curr;
+ }
+
+ *r_selected = bm->selected;
+ bm->selected = selected_orig;
+
+ return true;
}
static int edbm_vert_connect_path_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- uint failed_selection_order_len = 0;
- uint failed_connect_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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- const bool is_pair = (em->bm->totvertsel == 2);
- ListBase selected_orig = {NULL, NULL};
-
- if (bm->totvertsel == 0) {
- continue;
- }
-
- /* when there is only 2 vertices, we can ignore selection order */
- if (is_pair) {
- if (!edbm_connect_vert_pair(em, op)) {
- failed_connect_len++;
- }
- continue;
- }
-
- if (bm->selected.first) {
- BMEditSelection *ese = bm->selected.first;
- if (ese->htype == BM_EDGE) {
- if (bm_vert_connect_select_history_edge_to_vert_path(bm, &selected_orig)) {
- SWAP(ListBase, bm->selected, selected_orig);
- }
- }
- }
-
- if (bm_vert_connect_select_history(bm)) {
- EDBM_selectmode_flush(em);
- EDBM_update_generic(em, true, true);
- }
- else {
- failed_selection_order_len++;
- }
-
- if (!BLI_listbase_is_empty(&selected_orig)) {
- BM_select_history_clear(bm);
- bm->selected = selected_orig;
- }
- }
-
- MEM_freeN(objects);
-
- if (failed_selection_order_len == objects_len) {
- BKE_report(op->reports, RPT_ERROR, "Invalid selection order");
- return OPERATOR_CANCELLED;
- }
- else if (failed_connect_len == objects_len) {
- BKE_report(op->reports, RPT_ERROR, "Could not connect vertices");
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ uint failed_selection_order_len = 0;
+ uint failed_connect_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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ const bool is_pair = (em->bm->totvertsel == 2);
+ ListBase selected_orig = {NULL, NULL};
+
+ if (bm->totvertsel == 0) {
+ continue;
+ }
+
+ /* when there is only 2 vertices, we can ignore selection order */
+ if (is_pair) {
+ if (!edbm_connect_vert_pair(em, op)) {
+ failed_connect_len++;
+ }
+ continue;
+ }
+
+ if (bm->selected.first) {
+ BMEditSelection *ese = bm->selected.first;
+ if (ese->htype == BM_EDGE) {
+ if (bm_vert_connect_select_history_edge_to_vert_path(bm, &selected_orig)) {
+ SWAP(ListBase, bm->selected, selected_orig);
+ }
+ }
+ }
+
+ if (bm_vert_connect_select_history(bm)) {
+ EDBM_selectmode_flush(em);
+ EDBM_update_generic(em, true, true);
+ }
+ else {
+ failed_selection_order_len++;
+ }
+
+ if (!BLI_listbase_is_empty(&selected_orig)) {
+ BM_select_history_clear(bm);
+ bm->selected = selected_orig;
+ }
+ }
+
+ MEM_freeN(objects);
+
+ if (failed_selection_order_len == objects_len) {
+ BKE_report(op->reports, RPT_ERROR, "Invalid selection order");
+ return OPERATOR_CANCELLED;
+ }
+ else if (failed_connect_len == objects_len) {
+ BKE_report(op->reports, RPT_ERROR, "Could not connect vertices");
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_vert_connect_path(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Vertex Connect Path";
- ot->idname = "MESH_OT_vert_connect_path";
- ot->description = "Connect vertices by their selection order, creating edges, splitting faces";
+ /* identifiers */
+ ot->name = "Vertex Connect Path";
+ ot->idname = "MESH_OT_vert_connect_path";
+ ot->description = "Connect vertices by their selection order, creating edges, splitting faces";
- /* api callbacks */
- ot->exec = edbm_vert_connect_path_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_vert_connect_path_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int edbm_vert_connect_concave_exec(bContext *C, wmOperator *op)
{
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totfacesel == 0) {
- continue;
- }
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
- if (!EDBM_op_call_and_selectf(
- em, op,
- "faces.out", true,
- "connect_verts_concave faces=%hf",
- BM_ELEM_SELECT))
- {
- continue;
- }
- EDBM_update_generic(em, true, true);
- }
+ if (!EDBM_op_call_and_selectf(
+ em, op, "faces.out", true, "connect_verts_concave faces=%hf", BM_ELEM_SELECT)) {
+ continue;
+ }
+ EDBM_update_generic(em, true, true);
+ }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_vert_connect_concave(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Split Concave Faces";
- ot->idname = "MESH_OT_vert_connect_concave";
- ot->description = "Make all faces convex";
+ /* identifiers */
+ ot->name = "Split Concave Faces";
+ ot->idname = "MESH_OT_vert_connect_concave";
+ ot->description = "Make all faces convex";
- /* api callbacks */
- ot->exec = edbm_vert_connect_concave_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_vert_connect_concave_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -1565,55 +1635,65 @@ void MESH_OT_vert_connect_concave(wmOperatorType *ot)
static int edbm_vert_connect_nonplaner_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const float angle_limit = RNA_float_get(op->ptr, "angle_limit");
- 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);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const float angle_limit = RNA_float_get(op->ptr, "angle_limit");
+ 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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->totfacesel == 0) {
- continue;
- }
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
- if (!EDBM_op_call_and_selectf(
- em, op,
- "faces.out", true,
- "connect_verts_nonplanar faces=%hf angle_limit=%f",
- BM_ELEM_SELECT, angle_limit))
- {
- continue;
- }
+ if (!EDBM_op_call_and_selectf(em,
+ op,
+ "faces.out",
+ true,
+ "connect_verts_nonplanar faces=%hf angle_limit=%f",
+ BM_ELEM_SELECT,
+ angle_limit)) {
+ continue;
+ }
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_vert_connect_nonplanar(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Split Non-Planar Faces";
- ot->idname = "MESH_OT_vert_connect_nonplanar";
- ot->description = "Split non-planar faces that exceed the angle threshold";
+ /* identifiers */
+ ot->name = "Split Non-Planar Faces";
+ ot->idname = "MESH_OT_vert_connect_nonplanar";
+ ot->description = "Split non-planar faces that exceed the angle threshold";
- /* api callbacks */
- ot->exec = edbm_vert_connect_nonplaner_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_vert_connect_nonplaner_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- prop = RNA_def_float_rotation(ot->srna, "angle_limit", 0, NULL, 0.0f, DEG2RADF(180.0f),
- "Max Angle", "Angle limit", 0.0f, DEG2RADF(180.0f));
- RNA_def_property_float_default(prop, DEG2RADF(5.0f));
+ /* props */
+ prop = RNA_def_float_rotation(ot->srna,
+ "angle_limit",
+ 0,
+ NULL,
+ 0.0f,
+ DEG2RADF(180.0f),
+ "Max Angle",
+ "Angle limit",
+ 0.0f,
+ DEG2RADF(180.0f));
+ RNA_def_property_float_default(prop, DEG2RADF(5.0f));
}
/** \} */
@@ -1624,51 +1704,54 @@ void MESH_OT_vert_connect_nonplanar(wmOperatorType *ot)
static int edbm_face_make_planar_exec(bContext *C, wmOperator *op)
{
- 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);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
- const int repeat = RNA_int_get(op->ptr, "repeat");
- const float fac = RNA_float_get(op->ptr, "factor");
+ const int repeat = RNA_int_get(op->ptr, "repeat");
+ const float fac = RNA_float_get(op->ptr, "factor");
- 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->totfacesel == 0) {
- continue;
- }
+ 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->totfacesel == 0) {
+ continue;
+ }
- if (!EDBM_op_callf(
- em, op, "planar_faces faces=%hf iterations=%i factor=%f",
- BM_ELEM_SELECT, repeat, fac))
- {
- continue;
- }
+ if (!EDBM_op_callf(em,
+ op,
+ "planar_faces faces=%hf iterations=%i factor=%f",
+ BM_ELEM_SELECT,
+ repeat,
+ fac)) {
+ continue;
+ }
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_face_make_planar(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Planar Faces";
- ot->idname = "MESH_OT_face_make_planar";
- ot->description = "Flatten selected faces";
+ /* identifiers */
+ ot->name = "Make Planar Faces";
+ ot->idname = "MESH_OT_face_make_planar";
+ ot->description = "Flatten selected faces";
- /* api callbacks */
- ot->exec = edbm_face_make_planar_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_face_make_planar_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_float(ot->srna, "factor", 1.0f, -10.0f, 10.0f, "Factor", "", 0.0f, 1.0f);
- RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
+ /* props */
+ RNA_def_float(ot->srna, "factor", 1.0f, -10.0f, 10.0f, "Factor", "", 0.0f, 1.0f);
+ RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
}
/** \} */
@@ -1679,49 +1762,46 @@ void MESH_OT_face_make_planar(wmOperatorType *ot)
static int edbm_edge_split_exec(bContext *C, wmOperator *op)
{
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totedgesel == 0) {
- continue;
- }
+ 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];
+ 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 (!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);
- }
+ if (em->selectmode == SCE_SELECT_FACE) {
+ EDBM_select_flush(em);
+ }
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_edge_split(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Edge Split";
- ot->idname = "MESH_OT_edge_split";
- ot->description = "Split selected edges so that each neighbor face gets its own copy";
+ /* identifiers */
+ ot->name = "Edge Split";
+ ot->idname = "MESH_OT_edge_split";
+ ot->description = "Split selected edges so that each neighbor face gets its own copy";
- /* api callbacks */
- ot->exec = edbm_edge_split_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_edge_split_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -1732,71 +1812,76 @@ void MESH_OT_edge_split(wmOperatorType *ot)
static int edbm_duplicate_exec(bContext *C, wmOperator *op)
{
- 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);
+ 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totvertsel == 0) {
- continue;
- }
+ 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->totvertsel == 0) {
+ continue;
+ }
- BMOperator bmop;
- BMesh *bm = em->bm;
+ BMOperator bmop;
+ BMesh *bm = em->bm;
- EDBM_op_init(
- em, &bmop, op,
- "duplicate geom=%hvef use_select_history=%b use_edge_flip_from_face=%b",
- BM_ELEM_SELECT, true, true);
+ EDBM_op_init(em,
+ &bmop,
+ op,
+ "duplicate geom=%hvef use_select_history=%b use_edge_flip_from_face=%b",
+ BM_ELEM_SELECT,
+ true,
+ true);
- BMO_op_exec(bm, &bmop);
+ BMO_op_exec(bm, &bmop);
- /* de-select all would clear otherwise */
- BM_SELECT_HISTORY_BACKUP(bm);
+ /* de-select all would clear otherwise */
+ BM_SELECT_HISTORY_BACKUP(bm);
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
+ BMO_slot_buffer_hflag_enable(
+ bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
- /* rebuild editselection */
- BM_SELECT_HISTORY_RESTORE(bm);
+ /* rebuild editselection */
+ BM_SELECT_HISTORY_RESTORE(bm);
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int edbm_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- WM_cursor_wait(1);
- edbm_duplicate_exec(C, op);
- WM_cursor_wait(0);
+ WM_cursor_wait(1);
+ edbm_duplicate_exec(C, op);
+ WM_cursor_wait(0);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_duplicate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Duplicate";
- ot->description = "Duplicate selected vertices, edges or faces";
- ot->idname = "MESH_OT_duplicate";
+ /* identifiers */
+ ot->name = "Duplicate";
+ ot->description = "Duplicate selected vertices, edges or faces";
+ ot->idname = "MESH_OT_duplicate";
- /* api callbacks */
- ot->invoke = edbm_duplicate_invoke;
- ot->exec = edbm_duplicate_exec;
+ /* api callbacks */
+ ot->invoke = edbm_duplicate_invoke;
+ ot->exec = edbm_duplicate_exec;
- ot->poll = ED_operator_editmesh;
+ ot->poll = ED_operator_editmesh;
- /* to give to transform */
- RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
+ /* to give to transform */
+ RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
}
/** \} */
@@ -1806,45 +1891,43 @@ void MESH_OT_duplicate(wmOperatorType *ot)
* \{ */
static int edbm_flip_normals_exec(bContext *C, wmOperator *op)
{
- 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);
+ 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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->totfacesel == 0) {
- continue;
- }
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
- if (!EDBM_op_callf(
- em, op, "reverse_faces faces=%hf flip_multires=%b",
- BM_ELEM_SELECT, true))
- {
- continue;
- }
+ if (!EDBM_op_callf(em, op, "reverse_faces faces=%hf flip_multires=%b", BM_ELEM_SELECT, true)) {
+ continue;
+ }
- EDBM_update_generic(em, true, false);
- }
+ EDBM_update_generic(em, true, false);
+ }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_flip_normals(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Flip Normals";
- ot->description = "Flip the direction of selected faces' normals (and of their vertices)";
- ot->idname = "MESH_OT_flip_normals";
+ /* identifiers */
+ ot->name = "Flip Normals";
+ ot->description = "Flip the direction of selected faces' normals (and of their vertices)";
+ ot->idname = "MESH_OT_flip_normals";
- /* api callbacks */
- ot->exec = edbm_flip_normals_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_flip_normals_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -1858,120 +1941,124 @@ void MESH_OT_flip_normals(wmOperatorType *ot)
*/
static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op)
{
- BMEdge *eed;
- BMIter iter;
- const bool use_ccw = RNA_boolean_get(op->ptr, "use_ccw");
-
- int tot_rotate_all = 0, tot_failed_all = 0;
- bool no_selected_edges = true, invalid_selected_edges = true;
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- int tot = 0;
-
- if (em->bm->totedgesel == 0) {
- continue;
- }
- no_selected_edges = false;
-
- /* first see if we have two adjacent faces */
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_disable(eed, BM_ELEM_TAG);
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- BMFace *fa, *fb;
- if (BM_edge_face_pair(eed, &fa, &fb)) {
- /* if both faces are selected we rotate between them,
- * otherwise - rotate between 2 unselected - but not mixed */
- if (BM_elem_flag_test(fa, BM_ELEM_SELECT) == BM_elem_flag_test(fb, BM_ELEM_SELECT)) {
- BM_elem_flag_enable(eed, BM_ELEM_TAG);
- tot++;
- }
- }
- }
- }
-
- /* ok, we don't have two adjacent faces, but we do have two selected ones.
- * that's an error condition.*/
- if (tot == 0) {
- continue;
- }
- invalid_selected_edges = false;
-
- BMOperator bmop;
- EDBM_op_init(em, &bmop, op, "rotate_edges edges=%he use_ccw=%b", BM_ELEM_TAG, use_ccw);
-
- /* avoids leaving old verts selected which can be a problem running multiple times,
- * since this means the edges become selected around the face
- * which then attempt to rotate */
- BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "edges", BM_EDGE, BM_ELEM_SELECT, true);
-
- BMO_op_exec(em->bm, &bmop);
- /* edges may rotate into hidden vertices, if this does _not_ run we get an illogical state */
- BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_HIDDEN, true);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
-
- const int tot_rotate = BMO_slot_buffer_count(bmop.slots_out, "edges.out");
- const int tot_failed = tot - tot_rotate;
-
- tot_rotate_all += tot_rotate;
- tot_failed_all += tot_failed;
-
- if (tot_failed != 0) {
- /* If some edges fail to rotate, we need to re-select them,
- * otherwise we can end up with invalid selection
- * (unselected edge between 2 selected faces). */
- BM_mesh_elem_hflag_enable_test(em->bm, BM_EDGE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG);
- }
-
- EDBM_selectmode_flush(em);
-
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
-
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
-
- if (no_selected_edges) {
- BKE_report(op->reports, RPT_ERROR, "Select edges or face pairs for edge loops to rotate about");
- return OPERATOR_CANCELLED;
- }
-
- /* Ok, we don't have two adjacent faces, but we do have two selected ones.
- * that's an error condition. */
- if (invalid_selected_edges) {
- BKE_report(op->reports, RPT_ERROR, "Could not find any selected edges that can be rotated");
- return OPERATOR_CANCELLED;
- }
-
- if (tot_failed_all != 0) {
- BKE_reportf(op->reports, RPT_WARNING, "Unable to rotate %d edge(s)", tot_failed_all);
- }
-
- return OPERATOR_FINISHED;
+ BMEdge *eed;
+ BMIter iter;
+ const bool use_ccw = RNA_boolean_get(op->ptr, "use_ccw");
+
+ int tot_rotate_all = 0, tot_failed_all = 0;
+ bool no_selected_edges = true, invalid_selected_edges = true;
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ int tot = 0;
+
+ if (em->bm->totedgesel == 0) {
+ continue;
+ }
+ no_selected_edges = false;
+
+ /* first see if we have two adjacent faces */
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_disable(eed, BM_ELEM_TAG);
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ BMFace *fa, *fb;
+ if (BM_edge_face_pair(eed, &fa, &fb)) {
+ /* if both faces are selected we rotate between them,
+ * otherwise - rotate between 2 unselected - but not mixed */
+ if (BM_elem_flag_test(fa, BM_ELEM_SELECT) == BM_elem_flag_test(fb, BM_ELEM_SELECT)) {
+ BM_elem_flag_enable(eed, BM_ELEM_TAG);
+ tot++;
+ }
+ }
+ }
+ }
+
+ /* ok, we don't have two adjacent faces, but we do have two selected ones.
+ * that's an error condition.*/
+ if (tot == 0) {
+ continue;
+ }
+ invalid_selected_edges = false;
+
+ BMOperator bmop;
+ EDBM_op_init(em, &bmop, op, "rotate_edges edges=%he use_ccw=%b", BM_ELEM_TAG, use_ccw);
+
+ /* avoids leaving old verts selected which can be a problem running multiple times,
+ * since this means the edges become selected around the face
+ * which then attempt to rotate */
+ BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "edges", BM_EDGE, BM_ELEM_SELECT, true);
+
+ BMO_op_exec(em->bm, &bmop);
+ /* edges may rotate into hidden vertices, if this does _not_ run we get an illogical state */
+ BMO_slot_buffer_hflag_disable(
+ em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_HIDDEN, true);
+ BMO_slot_buffer_hflag_enable(
+ em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
+
+ const int tot_rotate = BMO_slot_buffer_count(bmop.slots_out, "edges.out");
+ const int tot_failed = tot - tot_rotate;
+
+ tot_rotate_all += tot_rotate;
+ tot_failed_all += tot_failed;
+
+ if (tot_failed != 0) {
+ /* If some edges fail to rotate, we need to re-select them,
+ * otherwise we can end up with invalid selection
+ * (unselected edge between 2 selected faces). */
+ BM_mesh_elem_hflag_enable_test(em->bm, BM_EDGE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG);
+ }
+
+ EDBM_selectmode_flush(em);
+
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
+
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
+
+ if (no_selected_edges) {
+ BKE_report(
+ op->reports, RPT_ERROR, "Select edges or face pairs for edge loops to rotate about");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Ok, we don't have two adjacent faces, but we do have two selected ones.
+ * that's an error condition. */
+ if (invalid_selected_edges) {
+ BKE_report(op->reports, RPT_ERROR, "Could not find any selected edges that can be rotated");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (tot_failed_all != 0) {
+ BKE_reportf(op->reports, RPT_WARNING, "Unable to rotate %d edge(s)", tot_failed_all);
+ }
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_edge_rotate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Rotate Selected Edge";
- ot->description = "Rotate selected edge or adjoining faces";
- ot->idname = "MESH_OT_edge_rotate";
+ /* identifiers */
+ ot->name = "Rotate Selected Edge";
+ ot->description = "Rotate selected edge or adjoining faces";
+ ot->idname = "MESH_OT_edge_rotate";
- /* api callbacks */
- ot->exec = edbm_edge_rotate_selected_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_edge_rotate_selected_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "use_ccw", false, "Counter Clockwise", "");
+ /* props */
+ RNA_def_boolean(ot->srna, "use_ccw", false, "Counter Clockwise", "");
}
/** \} */
@@ -1982,58 +2069,60 @@ void MESH_OT_edge_rotate(wmOperatorType *ot)
static int edbm_hide_exec(bContext *C, wmOperator *op)
{
- const bool unselected = RNA_boolean_get(op->ptr, "unselected");
- ViewLayer *view_layer = CTX_data_view_layer(C);
- bool changed = false;
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- if (unselected) {
- if (bm->totvertsel == bm->totvert) {
- continue;
- }
- }
- else {
- if (bm->totvertsel == 0) {
- continue;
- }
- }
-
- if (EDBM_mesh_hide(em, unselected)) {
- EDBM_update_generic(em, true, false);
- changed = true;
- }
- }
- MEM_freeN(objects);
-
- if (!changed) {
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ const bool unselected = RNA_boolean_get(op->ptr, "unselected");
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ bool changed = false;
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ if (unselected) {
+ if (bm->totvertsel == bm->totvert) {
+ continue;
+ }
+ }
+ else {
+ if (bm->totvertsel == 0) {
+ continue;
+ }
+ }
+
+ if (EDBM_mesh_hide(em, unselected)) {
+ EDBM_update_generic(em, true, false);
+ changed = true;
+ }
+ }
+ MEM_freeN(objects);
+
+ if (!changed) {
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_hide(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Selected";
- ot->idname = "MESH_OT_hide";
- ot->description = "Hide (un)selected vertices, edges or faces";
+ /* identifiers */
+ ot->name = "Hide Selected";
+ ot->idname = "MESH_OT_hide";
+ ot->description = "Hide (un)selected vertices, edges or faces";
- /* api callbacks */
- ot->exec = edbm_hide_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_hide_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected");
+ /* props */
+ RNA_def_boolean(
+ ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected");
}
/** \} */
@@ -2044,39 +2133,40 @@ void MESH_OT_hide(wmOperatorType *ot)
static int edbm_reveal_exec(bContext *C, wmOperator *op)
{
- const bool select = RNA_boolean_get(op->ptr, "select");
- ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool select = RNA_boolean_get(op->ptr, "select");
+ 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (EDBM_mesh_reveal(em, select)) {
- EDBM_update_generic(em, true, false);
- }
- }
- MEM_freeN(objects);
+ if (EDBM_mesh_reveal(em, select)) {
+ EDBM_update_generic(em, true, false);
+ }
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_reveal(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reveal Hidden";
- ot->idname = "MESH_OT_reveal";
- ot->description = "Reveal all hidden vertices, edges and faces";
+ /* identifiers */
+ ot->name = "Reveal Hidden";
+ ot->idname = "MESH_OT_reveal";
+ ot->description = "Reveal all hidden vertices, edges and faces";
- /* api callbacks */
- ot->exec = edbm_reveal_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_reveal_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "select", true, "Select", "");
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
/** \} */
@@ -2087,47 +2177,48 @@ 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);
+ 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totfacesel == 0) {
- continue;
- }
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
- if (!EDBM_op_callf(em, op, "recalc_face_normals faces=%hf", BM_ELEM_SELECT)) {
- continue;
- }
- if (RNA_boolean_get(op->ptr, "inside")) {
- EDBM_op_callf(em, op, "reverse_faces faces=%hf flip_multires=%b", BM_ELEM_SELECT, true);
- }
+ if (!EDBM_op_callf(em, op, "recalc_face_normals faces=%hf", BM_ELEM_SELECT)) {
+ continue;
+ }
+ if (RNA_boolean_get(op->ptr, "inside")) {
+ EDBM_op_callf(em, op, "reverse_faces faces=%hf flip_multires=%b", BM_ELEM_SELECT, true);
+ }
- EDBM_update_generic(em, true, false);
- }
- MEM_freeN(objects);
+ EDBM_update_generic(em, true, false);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_normals_make_consistent(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Normals Consistent";
- ot->description = "Make face and vertex normals point either outside or inside the mesh";
- ot->idname = "MESH_OT_normals_make_consistent";
+ /* identifiers */
+ ot->name = "Make Normals Consistent";
+ ot->description = "Make face and vertex normals point either outside or inside the mesh";
+ ot->idname = "MESH_OT_normals_make_consistent";
- /* api callbacks */
- ot->exec = edbm_normals_make_consistent_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_normals_make_consistent_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "inside", false, "Inside", "");
+ RNA_def_boolean(ot->srna, "inside", false, "Inside", "");
}
/** \} */
@@ -2138,105 +2229,116 @@ void MESH_OT_normals_make_consistent(wmOperatorType *ot)
static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
{
- const float fac = RNA_float_get(op->ptr, "factor");
-
- const bool xaxis = RNA_boolean_get(op->ptr, "xaxis");
- const bool yaxis = RNA_boolean_get(op->ptr, "yaxis");
- const bool zaxis = RNA_boolean_get(op->ptr, "zaxis");
- int repeat = RNA_int_get(op->ptr, "repeat");
-
- if (!repeat) {
- repeat = 1;
- }
-
- 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];
- Mesh *me = obedit->data;
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- ModifierData *md;
- bool mirrx = false, mirry = false, mirrz = false;
- int i;
- float clip_dist = 0.0f;
- const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
-
- if (em->bm->totvertsel == 0) {
- continue;
- }
-
- /* mirror before smooth */
- if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
- EDBM_verts_mirror_cache_begin(em, 0, false, true, use_topology);
- }
-
- /* if there is a mirror modifier with clipping, flag the verts that
- * are within tolerance of the plane(s) of reflection
- */
- for (md = obedit->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) {
- if (mmd->flag & MOD_MIR_AXIS_X)
- mirrx = true;
- if (mmd->flag & MOD_MIR_AXIS_Y)
- mirry = true;
- if (mmd->flag & MOD_MIR_AXIS_Z)
- mirrz = true;
-
- clip_dist = mmd->tolerance;
- }
- }
- }
-
- for (i = 0; i < repeat; i++) {
- if (!EDBM_op_callf(
- em, op,
- "smooth_vert verts=%hv factor=%f mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b "
- "clip_dist=%f use_axis_x=%b use_axis_y=%b use_axis_z=%b",
- BM_ELEM_SELECT, fac, mirrx, mirry, mirrz, clip_dist, xaxis, yaxis, zaxis))
- {
- continue;
- }
- }
-
- /* apply mirror */
- if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
- EDBM_verts_mirror_apply(em, BM_ELEM_SELECT, 0);
- EDBM_verts_mirror_cache_end(em);
- }
-
- EDBM_update_generic(em, true, false);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ const float fac = RNA_float_get(op->ptr, "factor");
+
+ const bool xaxis = RNA_boolean_get(op->ptr, "xaxis");
+ const bool yaxis = RNA_boolean_get(op->ptr, "yaxis");
+ const bool zaxis = RNA_boolean_get(op->ptr, "zaxis");
+ int repeat = RNA_int_get(op->ptr, "repeat");
+
+ if (!repeat) {
+ repeat = 1;
+ }
+
+ 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];
+ Mesh *me = obedit->data;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ ModifierData *md;
+ bool mirrx = false, mirry = false, mirrz = false;
+ int i;
+ float clip_dist = 0.0f;
+ const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
+
+ /* mirror before smooth */
+ if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
+ EDBM_verts_mirror_cache_begin(em, 0, false, true, use_topology);
+ }
+
+ /* if there is a mirror modifier with clipping, flag the verts that
+ * are within tolerance of the plane(s) of reflection
+ */
+ for (md = obedit->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) {
+ if (mmd->flag & MOD_MIR_AXIS_X)
+ mirrx = true;
+ if (mmd->flag & MOD_MIR_AXIS_Y)
+ mirry = true;
+ if (mmd->flag & MOD_MIR_AXIS_Z)
+ mirrz = true;
+
+ clip_dist = mmd->tolerance;
+ }
+ }
+ }
+
+ for (i = 0; i < repeat; i++) {
+ if (!EDBM_op_callf(
+ em,
+ op,
+ "smooth_vert verts=%hv factor=%f mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b "
+ "clip_dist=%f use_axis_x=%b use_axis_y=%b use_axis_z=%b",
+ BM_ELEM_SELECT,
+ fac,
+ mirrx,
+ mirry,
+ mirrz,
+ clip_dist,
+ xaxis,
+ yaxis,
+ zaxis)) {
+ continue;
+ }
+ }
+
+ /* apply mirror */
+ if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
+ EDBM_verts_mirror_apply(em, BM_ELEM_SELECT, 0);
+ EDBM_verts_mirror_cache_end(em);
+ }
+
+ EDBM_update_generic(em, true, false);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_vertices_smooth(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Smooth Vertices";
- ot->description = "Flatten angles of selected vertices";
- ot->idname = "MESH_OT_vertices_smooth";
+ /* identifiers */
+ ot->name = "Smooth Vertices";
+ ot->description = "Flatten angles of selected vertices";
+ ot->idname = "MESH_OT_vertices_smooth";
- /* api callbacks */
- ot->exec = edbm_do_smooth_vertex_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_do_smooth_vertex_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_float_factor(ot->srna, "factor", 0.5f, -10.0f, 10.0f, "Smoothing", "Smoothing factor", 0.0f, 1.0f);
- RNA_def_int(ot->srna, "repeat", 1, 1, 1000, "Repeat", "Number of times to smooth the mesh", 1, 100);
+ ot->prop = RNA_def_float_factor(
+ ot->srna, "factor", 0.5f, -10.0f, 10.0f, "Smoothing", "Smoothing factor", 0.0f, 1.0f);
+ RNA_def_int(
+ ot->srna, "repeat", 1, 1, 1000, "Repeat", "Number of times to smooth the mesh", 1, 100);
- WM_operatortype_props_advanced_begin(ot);
+ WM_operatortype_props_advanced_begin(ot);
- RNA_def_boolean(ot->srna, "xaxis", true, "X-Axis", "Smooth along the X axis");
- RNA_def_boolean(ot->srna, "yaxis", true, "Y-Axis", "Smooth along the Y axis");
- RNA_def_boolean(ot->srna, "zaxis", true, "Z-Axis", "Smooth along the Z axis");
+ RNA_def_boolean(ot->srna, "xaxis", true, "X-Axis", "Smooth along the X axis");
+ RNA_def_boolean(ot->srna, "yaxis", true, "Y-Axis", "Smooth along the Y axis");
+ RNA_def_boolean(ot->srna, "zaxis", true, "Z-Axis", "Smooth along the Z axis");
}
/** \} */
@@ -2247,122 +2349,140 @@ void MESH_OT_vertices_smooth(wmOperatorType *ot)
static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
{
- BMIter fiter;
- BMFace *f;
- int tot_invalid = 0;
- int tot_unselected = 0;
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- const float lambda_factor = RNA_float_get(op->ptr, "lambda_factor");
- const float lambda_border = RNA_float_get(op->ptr, "lambda_border");
- const bool usex = RNA_boolean_get(op->ptr, "use_x");
- const bool usey = RNA_boolean_get(op->ptr, "use_y");
- const bool usez = RNA_boolean_get(op->ptr, "use_z");
- const bool preserve_volume = RNA_boolean_get(op->ptr, "preserve_volume");
- int repeat = RNA_int_get(op->ptr, "repeat");
-
- if (!repeat) {
- repeat = 1;
- }
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- Mesh *me = obedit->data;
- bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
-
- if (em->bm->totvertsel == 0) {
- tot_unselected++;
- tot_invalid++;
- continue;
- }
-
- bool is_invalid = false;
- /* Check if select faces are triangles. */
- BM_ITER_MESH (f, &fiter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- if (f->len > 4) {
- tot_invalid++;
- is_invalid = true;
- break;
- }
- }
- }
- if (is_invalid) {
- continue;
- }
-
- /* Mirror before smooth. */
- if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
- EDBM_verts_mirror_cache_begin(em, 0, false, true, use_topology);
- }
-
- bool failed_repeat_loop = false;
- for (int i = 0; i < repeat; i++) {
- if (!EDBM_op_callf(
- em, op,
- "smooth_laplacian_vert verts=%hv lambda_factor=%f lambda_border=%f use_x=%b use_y=%b use_z=%b preserve_volume=%b",
- BM_ELEM_SELECT, lambda_factor, lambda_border, usex, usey, usez, preserve_volume))
- {
- failed_repeat_loop = true;
- break;
- }
- }
- if (failed_repeat_loop) {
- continue;
- }
-
- /* Apply mirror. */
- if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
- EDBM_verts_mirror_apply(em, BM_ELEM_SELECT, 0);
- EDBM_verts_mirror_cache_end(em);
- }
-
- EDBM_update_generic(em, true, false);
- }
- MEM_freeN(objects);
-
- if (tot_unselected == objects_len) {
- BKE_report(op->reports, RPT_WARNING, "No selected vertex");
- return OPERATOR_CANCELLED;
- }
- else if (tot_invalid == objects_len) {
- BKE_report(op->reports, RPT_WARNING, "Selected faces must be triangles or quads");
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ BMIter fiter;
+ BMFace *f;
+ int tot_invalid = 0;
+ int tot_unselected = 0;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ const float lambda_factor = RNA_float_get(op->ptr, "lambda_factor");
+ const float lambda_border = RNA_float_get(op->ptr, "lambda_border");
+ const bool usex = RNA_boolean_get(op->ptr, "use_x");
+ const bool usey = RNA_boolean_get(op->ptr, "use_y");
+ const bool usez = RNA_boolean_get(op->ptr, "use_z");
+ const bool preserve_volume = RNA_boolean_get(op->ptr, "preserve_volume");
+ int repeat = RNA_int_get(op->ptr, "repeat");
+
+ if (!repeat) {
+ repeat = 1;
+ }
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ Mesh *me = obedit->data;
+ bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+
+ if (em->bm->totvertsel == 0) {
+ tot_unselected++;
+ tot_invalid++;
+ continue;
+ }
+
+ bool is_invalid = false;
+ /* Check if select faces are triangles. */
+ BM_ITER_MESH (f, &fiter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ if (f->len > 4) {
+ tot_invalid++;
+ is_invalid = true;
+ break;
+ }
+ }
+ }
+ if (is_invalid) {
+ continue;
+ }
+
+ /* Mirror before smooth. */
+ if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
+ EDBM_verts_mirror_cache_begin(em, 0, false, true, use_topology);
+ }
+
+ bool failed_repeat_loop = false;
+ for (int i = 0; i < repeat; i++) {
+ if (!EDBM_op_callf(em,
+ op,
+ "smooth_laplacian_vert verts=%hv lambda_factor=%f lambda_border=%f "
+ "use_x=%b use_y=%b use_z=%b preserve_volume=%b",
+ BM_ELEM_SELECT,
+ lambda_factor,
+ lambda_border,
+ usex,
+ usey,
+ usez,
+ preserve_volume)) {
+ failed_repeat_loop = true;
+ break;
+ }
+ }
+ if (failed_repeat_loop) {
+ continue;
+ }
+
+ /* Apply mirror. */
+ if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
+ EDBM_verts_mirror_apply(em, BM_ELEM_SELECT, 0);
+ EDBM_verts_mirror_cache_end(em);
+ }
+
+ EDBM_update_generic(em, true, false);
+ }
+ MEM_freeN(objects);
+
+ if (tot_unselected == objects_len) {
+ BKE_report(op->reports, RPT_WARNING, "No selected vertex");
+ return OPERATOR_CANCELLED;
+ }
+ else if (tot_invalid == objects_len) {
+ BKE_report(op->reports, RPT_WARNING, "Selected faces must be triangles or quads");
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Laplacian Smooth Vertices";
- ot->description = "Laplacian smooth of selected vertices";
- ot->idname = "MESH_OT_vertices_smooth_laplacian";
-
- /* api callbacks */
- ot->exec = edbm_do_smooth_laplacian_vertex_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_int(ot->srna, "repeat", 1, 1, 1000,
- "Number of iterations to smooth the mesh", "", 1, 200);
- RNA_def_float(ot->srna, "lambda_factor", 1.0f, 1e-7f, 1000.0f,
- "Lambda factor", "", 1e-7f, 1000.0f);
- RNA_def_float(ot->srna, "lambda_border", 5e-5f, 1e-7f, 1000.0f,
- "Lambda factor in border", "", 1e-7f, 1000.0f);
-
- WM_operatortype_props_advanced_begin(ot);
-
- RNA_def_boolean(ot->srna, "use_x", true, "Smooth X Axis", "Smooth object along X axis");
- RNA_def_boolean(ot->srna, "use_y", true, "Smooth Y Axis", "Smooth object along Y axis");
- RNA_def_boolean(ot->srna, "use_z", true, "Smooth Z Axis", "Smooth object along Z axis");
- RNA_def_boolean(ot->srna, "preserve_volume", true, "Preserve Volume", "Apply volume preservation after smooth");
+ /* identifiers */
+ ot->name = "Laplacian Smooth Vertices";
+ ot->description = "Laplacian smooth of selected vertices";
+ ot->idname = "MESH_OT_vertices_smooth_laplacian";
+
+ /* api callbacks */
+ ot->exec = edbm_do_smooth_laplacian_vertex_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_int(
+ ot->srna, "repeat", 1, 1, 1000, "Number of iterations to smooth the mesh", "", 1, 200);
+ RNA_def_float(
+ ot->srna, "lambda_factor", 1.0f, 1e-7f, 1000.0f, "Lambda factor", "", 1e-7f, 1000.0f);
+ RNA_def_float(ot->srna,
+ "lambda_border",
+ 5e-5f,
+ 1e-7f,
+ 1000.0f,
+ "Lambda factor in border",
+ "",
+ 1e-7f,
+ 1000.0f);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ RNA_def_boolean(ot->srna, "use_x", true, "Smooth X Axis", "Smooth object along X axis");
+ RNA_def_boolean(ot->srna, "use_y", true, "Smooth Y Axis", "Smooth object along Y axis");
+ RNA_def_boolean(ot->srna, "use_z", true, "Smooth Z Axis", "Smooth object along Z axis");
+ RNA_def_boolean(ot->srna,
+ "preserve_volume",
+ true,
+ "Preserve Volume",
+ "Apply volume preservation after smooth");
}
/** \} */
@@ -2373,52 +2493,54 @@ void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot)
static void mesh_set_smooth_faces(BMEditMesh *em, short smooth)
{
- BMIter iter;
- BMFace *efa;
+ BMIter iter;
+ BMFace *efa;
- if (em == NULL) return;
+ if (em == NULL)
+ return;
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- BM_elem_flag_set(efa, BM_ELEM_SMOOTH, smooth);
- }
- }
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ BM_elem_flag_set(efa, BM_ELEM_SMOOTH, smooth);
+ }
+ }
}
static int edbm_faces_shade_smooth_exec(bContext *C, wmOperator *UNUSED(op))
{
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totfacesel == 0) {
- continue;
- }
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
- mesh_set_smooth_faces(em, 1);
- EDBM_update_generic(em, false, false);
- }
- MEM_freeN(objects);
+ mesh_set_smooth_faces(em, 1);
+ EDBM_update_generic(em, false, false);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_faces_shade_smooth(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Shade Smooth";
- ot->description = "Display faces smooth (using vertex normals)";
- ot->idname = "MESH_OT_faces_shade_smooth";
+ /* identifiers */
+ ot->name = "Shade Smooth";
+ ot->description = "Display faces smooth (using vertex normals)";
+ ot->idname = "MESH_OT_faces_shade_smooth";
- /* api callbacks */
- ot->exec = edbm_faces_shade_smooth_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_faces_shade_smooth_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -2429,38 +2551,39 @@ void MESH_OT_faces_shade_smooth(wmOperatorType *ot)
static int edbm_faces_shade_flat_exec(bContext *C, wmOperator *UNUSED(op))
{
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totfacesel == 0) {
- continue;
- }
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
- mesh_set_smooth_faces(em, 0);
- EDBM_update_generic(em, false, false);
- }
- MEM_freeN(objects);
+ mesh_set_smooth_faces(em, 0);
+ EDBM_update_generic(em, false, false);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_faces_shade_flat(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Shade Flat";
- ot->description = "Display faces flat";
- ot->idname = "MESH_OT_faces_shade_flat";
+ /* identifiers */
+ ot->name = "Shade Flat";
+ ot->description = "Display faces flat";
+ ot->idname = "MESH_OT_faces_shade_flat";
- /* api callbacks */
- ot->exec = edbm_faces_shade_flat_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_faces_shade_flat_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -2471,214 +2594,217 @@ void MESH_OT_faces_shade_flat(wmOperatorType *ot)
static int edbm_rotate_uvs_exec(bContext *C, wmOperator *op)
{
- /* get the direction from RNA */
- const bool use_ccw = RNA_boolean_get(op->ptr, "use_ccw");
+ /* get the direction from RNA */
+ const bool use_ccw = RNA_boolean_get(op->ptr, "use_ccw");
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totfacesel == 0) {
- continue;
- }
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
- BMOperator bmop;
+ BMOperator bmop;
- /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
- EDBM_op_init(em, &bmop, op, "rotate_uvs faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw);
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_op_init(em, &bmop, op, "rotate_uvs faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw);
- /* execute the operator */
- BMO_op_exec(em->bm, &bmop);
+ /* execute the operator */
+ BMO_op_exec(em->bm, &bmop);
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
- EDBM_update_generic(em, false, false);
- }
+ EDBM_update_generic(em, false, false);
+ }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
static int edbm_reverse_uvs_exec(bContext *C, wmOperator *op)
{
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totfacesel == 0) {
- continue;
- }
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
- BMOperator bmop;
+ BMOperator bmop;
- /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
- EDBM_op_init(em, &bmop, op, "reverse_uvs faces=%hf", BM_ELEM_SELECT);
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_op_init(em, &bmop, op, "reverse_uvs faces=%hf", BM_ELEM_SELECT);
- /* execute the operator */
- BMO_op_exec(em->bm, &bmop);
+ /* execute the operator */
+ BMO_op_exec(em->bm, &bmop);
- /* finish the operator */
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
- EDBM_update_generic(em, false, false);
- }
+ /* finish the operator */
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
+ EDBM_update_generic(em, false, false);
+ }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
static int edbm_rotate_colors_exec(bContext *C, wmOperator *op)
{
- /* get the direction from RNA */
- const bool use_ccw = RNA_boolean_get(op->ptr, "use_ccw");
+ /* get the direction from RNA */
+ const bool use_ccw = RNA_boolean_get(op->ptr, "use_ccw");
- 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);
+ 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];
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- if (em->bm->totfacesel == 0) {
- continue;
- }
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
- BMOperator bmop;
+ BMOperator bmop;
- /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
- EDBM_op_init(em, &bmop, op, "rotate_colors faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw);
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_op_init(em, &bmop, op, "rotate_colors faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw);
- /* execute the operator */
- BMO_op_exec(em->bm, &bmop);
+ /* execute the operator */
+ BMO_op_exec(em->bm, &bmop);
- /* finish the operator */
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
+ /* finish the operator */
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
- /* dependencies graph and notification stuff */
- EDBM_update_generic(em, false, false);
- }
+ /* dependencies graph and notification stuff */
+ EDBM_update_generic(em, false, false);
+ }
- MEM_freeN(objects);
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
static int edbm_reverse_colors_exec(bContext *C, wmOperator *op)
{
- 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);
+ 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];
- BMEditMesh *em = BKE_editmesh_from_object(ob);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
- if (em->bm->totfacesel == 0) {
- continue;
- }
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
- BMOperator bmop;
+ BMOperator bmop;
- /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
- EDBM_op_init(em, &bmop, op, "reverse_colors faces=%hf", BM_ELEM_SELECT);
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_op_init(em, &bmop, op, "reverse_colors faces=%hf", BM_ELEM_SELECT);
- /* execute the operator */
- BMO_op_exec(em->bm, &bmop);
+ /* execute the operator */
+ BMO_op_exec(em->bm, &bmop);
- /* finish the operator */
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- return OPERATOR_CANCELLED;
- }
+ /* finish the operator */
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ return OPERATOR_CANCELLED;
+ }
- EDBM_update_generic(em, false, false);
- }
- MEM_freeN(objects);
+ EDBM_update_generic(em, false, false);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_uvs_rotate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Rotate UVs";
- ot->idname = "MESH_OT_uvs_rotate";
- ot->description = "Rotate UV coordinates inside faces";
+ /* identifiers */
+ ot->name = "Rotate UVs";
+ ot->idname = "MESH_OT_uvs_rotate";
+ ot->description = "Rotate UV coordinates inside faces";
- /* api callbacks */
- ot->exec = edbm_rotate_uvs_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_rotate_uvs_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "use_ccw", false, "Counter Clockwise", "");
+ /* props */
+ RNA_def_boolean(ot->srna, "use_ccw", false, "Counter Clockwise", "");
}
void MESH_OT_uvs_reverse(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reverse UVs";
- ot->idname = "MESH_OT_uvs_reverse";
- ot->description = "Flip direction of UV coordinates inside faces";
+ /* identifiers */
+ ot->name = "Reverse UVs";
+ ot->idname = "MESH_OT_uvs_reverse";
+ ot->description = "Flip direction of UV coordinates inside faces";
- /* api callbacks */
- ot->exec = edbm_reverse_uvs_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_reverse_uvs_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- //RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror UVs around");
+ /* props */
+ //RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror UVs around");
}
void MESH_OT_colors_rotate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Rotate Colors";
- ot->idname = "MESH_OT_colors_rotate";
- ot->description = "Rotate vertex colors inside faces";
+ /* identifiers */
+ ot->name = "Rotate Colors";
+ ot->idname = "MESH_OT_colors_rotate";
+ ot->description = "Rotate vertex colors inside faces";
- /* api callbacks */
- ot->exec = edbm_rotate_colors_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_rotate_colors_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "use_ccw", false, "Counter Clockwise", "");
+ /* props */
+ RNA_def_boolean(ot->srna, "use_ccw", false, "Counter Clockwise", "");
}
void MESH_OT_colors_reverse(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reverse Colors";
- ot->idname = "MESH_OT_colors_reverse";
- ot->description = "Flip direction of vertex colors inside faces";
+ /* identifiers */
+ ot->name = "Reverse Colors";
+ ot->idname = "MESH_OT_colors_reverse";
+ ot->description = "Flip direction of vertex colors inside faces";
- /* api callbacks */
- ot->exec = edbm_reverse_colors_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_reverse_colors_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- //RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror colors around");
+ /* props */
+ //RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror colors around");
}
/** \} */
@@ -2688,238 +2814,251 @@ void MESH_OT_colors_reverse(wmOperatorType *ot)
* \{ */
enum {
- MESH_MERGE_LAST = 1,
- MESH_MERGE_CENTER = 3,
- MESH_MERGE_CURSOR = 4,
- MESH_MERGE_COLLAPSE = 5,
- MESH_MERGE_FIRST = 6,
+ MESH_MERGE_LAST = 1,
+ MESH_MERGE_CENTER = 3,
+ MESH_MERGE_CURSOR = 4,
+ MESH_MERGE_COLLAPSE = 5,
+ MESH_MERGE_FIRST = 6,
};
-static bool merge_firstlast(BMEditMesh *em, const bool use_first, const bool use_uvmerge, wmOperator *wmop)
-{
- BMVert *mergevert;
- BMEditSelection *ese;
-
- /* operator could be called directly from shortcut or python,
- * so do extra check for data here
- */
-
- /* do sanity check in mergemenu in edit.c ?*/
- if (use_first == false) {
- if (!em->bm->selected.last || ((BMEditSelection *)em->bm->selected.last)->htype != BM_VERT)
- return false;
-
- ese = em->bm->selected.last;
- mergevert = (BMVert *)ese->ele;
- }
- else {
- if (!em->bm->selected.first || ((BMEditSelection *)em->bm->selected.first)->htype != BM_VERT)
- return false;
-
- ese = em->bm->selected.first;
- mergevert = (BMVert *)ese->ele;
- }
-
- if (!BM_elem_flag_test(mergevert, BM_ELEM_SELECT))
- return false;
-
- if (use_uvmerge) {
- if (!EDBM_op_callf(em, wmop, "pointmerge_facedata verts=%hv vert_snap=%e", BM_ELEM_SELECT, mergevert))
- return false;
- }
-
- if (!EDBM_op_callf(em, wmop, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, mergevert->co))
- return false;
-
- return true;
-}
-
-static bool merge_target(
- BMEditMesh *em, Scene *scene, Object *ob,
- const bool use_cursor, const bool use_uvmerge, wmOperator *wmop)
-{
- BMIter iter;
- BMVert *v;
- float co[3], cent[3] = {0.0f, 0.0f, 0.0f};
- const float *vco = NULL;
-
- if (use_cursor) {
- vco = scene->cursor.location;
- copy_v3_v3(co, vco);
- invert_m4_m4(ob->imat, ob->obmat);
- mul_m4_v3(ob->imat, co);
- }
- else {
- float fac;
- int i = 0;
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(v, BM_ELEM_SELECT))
- continue;
- add_v3_v3(cent, v->co);
- i++;
- }
-
- if (!i)
- return false;
-
- fac = 1.0f / (float)i;
- mul_v3_fl(cent, fac);
- copy_v3_v3(co, cent);
- vco = co;
- }
-
- if (!vco)
- return false;
-
- if (use_uvmerge) {
- if (!EDBM_op_callf(em, wmop, "average_vert_facedata verts=%hv", BM_ELEM_SELECT))
- return false;
- }
-
- if (!EDBM_op_callf(em, wmop, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, co))
- return false;
-
- return true;
+static bool merge_firstlast(BMEditMesh *em,
+ const bool use_first,
+ const bool use_uvmerge,
+ wmOperator *wmop)
+{
+ BMVert *mergevert;
+ BMEditSelection *ese;
+
+ /* operator could be called directly from shortcut or python,
+ * so do extra check for data here
+ */
+
+ /* do sanity check in mergemenu in edit.c ?*/
+ if (use_first == false) {
+ if (!em->bm->selected.last || ((BMEditSelection *)em->bm->selected.last)->htype != BM_VERT)
+ return false;
+
+ ese = em->bm->selected.last;
+ mergevert = (BMVert *)ese->ele;
+ }
+ else {
+ if (!em->bm->selected.first || ((BMEditSelection *)em->bm->selected.first)->htype != BM_VERT)
+ return false;
+
+ ese = em->bm->selected.first;
+ mergevert = (BMVert *)ese->ele;
+ }
+
+ if (!BM_elem_flag_test(mergevert, BM_ELEM_SELECT))
+ return false;
+
+ if (use_uvmerge) {
+ if (!EDBM_op_callf(
+ em, wmop, "pointmerge_facedata verts=%hv vert_snap=%e", BM_ELEM_SELECT, mergevert))
+ return false;
+ }
+
+ if (!EDBM_op_callf(em, wmop, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, mergevert->co))
+ return false;
+
+ return true;
+}
+
+static bool merge_target(BMEditMesh *em,
+ Scene *scene,
+ Object *ob,
+ const bool use_cursor,
+ const bool use_uvmerge,
+ wmOperator *wmop)
+{
+ BMIter iter;
+ BMVert *v;
+ float co[3], cent[3] = {0.0f, 0.0f, 0.0f};
+ const float *vco = NULL;
+
+ if (use_cursor) {
+ vco = scene->cursor.location;
+ copy_v3_v3(co, vco);
+ invert_m4_m4(ob->imat, ob->obmat);
+ mul_m4_v3(ob->imat, co);
+ }
+ else {
+ float fac;
+ int i = 0;
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(v, BM_ELEM_SELECT))
+ continue;
+ add_v3_v3(cent, v->co);
+ i++;
+ }
+
+ if (!i)
+ return false;
+
+ fac = 1.0f / (float)i;
+ mul_v3_fl(cent, fac);
+ copy_v3_v3(co, cent);
+ vco = co;
+ }
+
+ if (!vco)
+ return false;
+
+ if (use_uvmerge) {
+ if (!EDBM_op_callf(em, wmop, "average_vert_facedata verts=%hv", BM_ELEM_SELECT))
+ return false;
+ }
+
+ if (!EDBM_op_callf(em, wmop, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, co))
+ return false;
+
+ return true;
}
static int edbm_merge_exec(bContext *C, wmOperator *op)
{
- 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);
- const int type = RNA_enum_get(op->ptr, "type");
- const bool uvs = RNA_boolean_get(op->ptr, "uvs");
-
- 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->totvertsel == 0) {
- continue;
- }
-
- bool ok = false;
- switch (type) {
- case MESH_MERGE_CENTER:
- ok = merge_target(em, scene, obedit, false, uvs, op);
- break;
- case MESH_MERGE_CURSOR:
- ok = merge_target(em, scene, obedit, true, uvs, op);
- break;
- case MESH_MERGE_LAST:
- ok = merge_firstlast(em, false, uvs, op);
- break;
- case MESH_MERGE_FIRST:
- ok = merge_firstlast(em, true, uvs, op);
- break;
- case MESH_MERGE_COLLAPSE:
- ok = EDBM_op_callf(em, op, "collapse edges=%he uvs=%b", BM_ELEM_SELECT, uvs);
- break;
- default:
- BLI_assert(0);
- break;
- }
-
- if (!ok) {
- continue;
- }
-
- EDBM_update_generic(em, true, true);
-
- /* once collapsed, we can't have edge/face selection */
- if ((em->selectmode & SCE_SELECT_VERTEX) == 0) {
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- }
- /* Only active object supported, see comment below. */
- if (ELEM(type, MESH_MERGE_FIRST, MESH_MERGE_LAST)) {
- break;
- }
- }
-
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ 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);
+ const int type = RNA_enum_get(op->ptr, "type");
+ const bool uvs = RNA_boolean_get(op->ptr, "uvs");
+
+ 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->totvertsel == 0) {
+ continue;
+ }
+
+ bool ok = false;
+ switch (type) {
+ case MESH_MERGE_CENTER:
+ ok = merge_target(em, scene, obedit, false, uvs, op);
+ break;
+ case MESH_MERGE_CURSOR:
+ ok = merge_target(em, scene, obedit, true, uvs, op);
+ break;
+ case MESH_MERGE_LAST:
+ ok = merge_firstlast(em, false, uvs, op);
+ break;
+ case MESH_MERGE_FIRST:
+ ok = merge_firstlast(em, true, uvs, op);
+ break;
+ case MESH_MERGE_COLLAPSE:
+ ok = EDBM_op_callf(em, op, "collapse edges=%he uvs=%b", BM_ELEM_SELECT, uvs);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ if (!ok) {
+ continue;
+ }
+
+ EDBM_update_generic(em, true, true);
+
+ /* once collapsed, we can't have edge/face selection */
+ if ((em->selectmode & SCE_SELECT_VERTEX) == 0) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ }
+ /* Only active object supported, see comment below. */
+ if (ELEM(type, MESH_MERGE_FIRST, MESH_MERGE_LAST)) {
+ break;
+ }
+ }
+
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
static const EnumPropertyItem merge_type_items[] = {
- {MESH_MERGE_FIRST, "FIRST", 0, "At First", ""},
- {MESH_MERGE_LAST, "LAST", 0, "At Last", ""},
- {MESH_MERGE_CENTER, "CENTER", 0, "At Center", ""},
- {MESH_MERGE_CURSOR, "CURSOR", 0, "At Cursor", ""},
- {MESH_MERGE_COLLAPSE, "COLLAPSE", 0, "Collapse", ""},
- {0, NULL, 0, NULL, NULL},
+ {MESH_MERGE_FIRST, "FIRST", 0, "At First", ""},
+ {MESH_MERGE_LAST, "LAST", 0, "At Last", ""},
+ {MESH_MERGE_CENTER, "CENTER", 0, "At Center", ""},
+ {MESH_MERGE_CURSOR, "CURSOR", 0, "At Cursor", ""},
+ {MESH_MERGE_COLLAPSE, "COLLAPSE", 0, "Collapse", ""},
+ {0, NULL, 0, NULL, NULL},
};
-static const EnumPropertyItem *merge_type_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
-{
- Object *obedit;
- EnumPropertyItem *item = NULL;
- int totitem = 0;
-
- if (!C) /* needed for docs */
- return merge_type_items;
-
- obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_MESH) {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- /* Only active object supported:
- * In practice it doesn't make sense to run this operation on non-active meshes
- * since selecting will activate - we could have own code-path for these but it's a hassle
- * for now just apply to the active (first) object. */
- if (em->selectmode & SCE_SELECT_VERTEX) {
- if (em->bm->selected.first && em->bm->selected.last &&
- ((BMEditSelection *)em->bm->selected.first)->htype == BM_VERT &&
- ((BMEditSelection *)em->bm->selected.last)->htype == BM_VERT)
- {
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_FIRST);
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_LAST);
- }
- else if (em->bm->selected.first && ((BMEditSelection *)em->bm->selected.first)->htype == BM_VERT) {
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_FIRST);
- }
- else if (em->bm->selected.last && ((BMEditSelection *)em->bm->selected.last)->htype == BM_VERT) {
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_LAST);
- }
- }
-
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_CENTER);
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_CURSOR);
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_COLLAPSE);
- RNA_enum_item_end(&item, &totitem);
-
- *r_free = true;
-
- return item;
- }
-
- /* Get all items e.g. when creating keymap item. */
- return merge_type_items;
+static const EnumPropertyItem *merge_type_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
+{
+ Object *obedit;
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+
+ if (!C) /* needed for docs */
+ return merge_type_items;
+
+ obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_MESH) {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ /* Only active object supported:
+ * In practice it doesn't make sense to run this operation on non-active meshes
+ * since selecting will activate - we could have own code-path for these but it's a hassle
+ * for now just apply to the active (first) object. */
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ if (em->bm->selected.first && em->bm->selected.last &&
+ ((BMEditSelection *)em->bm->selected.first)->htype == BM_VERT &&
+ ((BMEditSelection *)em->bm->selected.last)->htype == BM_VERT) {
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_FIRST);
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_LAST);
+ }
+ else if (em->bm->selected.first &&
+ ((BMEditSelection *)em->bm->selected.first)->htype == BM_VERT) {
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_FIRST);
+ }
+ else if (em->bm->selected.last &&
+ ((BMEditSelection *)em->bm->selected.last)->htype == BM_VERT) {
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_LAST);
+ }
+ }
+
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_CENTER);
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_CURSOR);
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_COLLAPSE);
+ RNA_enum_item_end(&item, &totitem);
+
+ *r_free = true;
+
+ return item;
+ }
+
+ /* Get all items e.g. when creating keymap item. */
+ return merge_type_items;
}
void MESH_OT_merge(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Merge";
- ot->description = "Merge selected vertices";
- ot->idname = "MESH_OT_merge";
+ /* identifiers */
+ ot->name = "Merge";
+ ot->description = "Merge selected vertices";
+ ot->idname = "MESH_OT_merge";
- /* api callbacks */
- ot->exec = edbm_merge_exec;
- ot->invoke = WM_menu_invoke;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_merge_exec;
+ ot->invoke = WM_menu_invoke;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", merge_type_items, MESH_MERGE_CENTER, "Type", "Merge method to use");
- RNA_def_enum_funcs(ot->prop, merge_type_itemf);
+ /* properties */
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", merge_type_items, MESH_MERGE_CENTER, "Type", "Merge method to use");
+ RNA_def_enum_funcs(ot->prop, merge_type_itemf);
- WM_operatortype_props_advanced_begin(ot);
+ WM_operatortype_props_advanced_begin(ot);
- RNA_def_boolean(ot->srna, "uvs", false, "UVs", "Move UVs according to merge");
+ RNA_def_boolean(ot->srna, "uvs", false, "UVs", "Move UVs according to merge");
}
/** \} */
@@ -2930,100 +3069,108 @@ void MESH_OT_merge(wmOperatorType *ot)
static int edbm_remove_doubles_exec(bContext *C, wmOperator *op)
{
- const float threshold = RNA_float_get(op->ptr, "threshold");
- const bool use_unselected = RNA_boolean_get(op->ptr, "use_unselected");
- int count_multi = 0;
+ const float threshold = RNA_float_get(op->ptr, "threshold");
+ const bool use_unselected = RNA_boolean_get(op->ptr, "use_unselected");
+ int count_multi = 0;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
+ 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- /* Selection used as target with 'use_unselected'. */
- if (em->bm->totvertsel == 0) {
- continue;
- }
+ /* Selection used as target with 'use_unselected'. */
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
- BMOperator bmop;
- const int totvert_orig = em->bm->totvert;
+ BMOperator bmop;
+ const int totvert_orig = em->bm->totvert;
- /* avoid losing selection state (select -> tags) */
- char htype_select;
- if (em->selectmode & SCE_SELECT_VERTEX) htype_select = BM_VERT;
- else if (em->selectmode & SCE_SELECT_EDGE) htype_select = BM_EDGE;
- else htype_select = BM_FACE;
+ /* avoid losing selection state (select -> tags) */
+ char htype_select;
+ if (em->selectmode & SCE_SELECT_VERTEX)
+ htype_select = BM_VERT;
+ else if (em->selectmode & SCE_SELECT_EDGE)
+ htype_select = BM_EDGE;
+ else
+ htype_select = BM_FACE;
- /* store selection as tags */
- BM_mesh_elem_hflag_enable_test(em->bm, htype_select, BM_ELEM_TAG, true, true, BM_ELEM_SELECT);
+ /* store selection as tags */
+ BM_mesh_elem_hflag_enable_test(em->bm, htype_select, BM_ELEM_TAG, true, true, BM_ELEM_SELECT);
+ if (use_unselected) {
+ EDBM_op_init(em, &bmop, op, "automerge verts=%hv dist=%f", BM_ELEM_SELECT, threshold);
+ BMO_op_exec(em->bm, &bmop);
- if (use_unselected) {
- EDBM_op_init(
- em, &bmop, op,
- "automerge verts=%hv dist=%f",
- BM_ELEM_SELECT, threshold);
- BMO_op_exec(em->bm, &bmop);
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
+ }
+ else {
+ EDBM_op_init(em, &bmop, op, "find_doubles verts=%hv dist=%f", BM_ELEM_SELECT, threshold);
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
- }
- else {
- EDBM_op_init(
- em, &bmop, op,
- "find_doubles verts=%hv dist=%f",
- BM_ELEM_SELECT, threshold);
+ BMO_op_exec(em->bm, &bmop);
- BMO_op_exec(em->bm, &bmop);
+ if (!EDBM_op_callf(em, op, "weld_verts targetmap=%S", &bmop, "targetmap.out")) {
+ BMO_op_finish(em->bm, &bmop);
+ continue;
+ }
- if (!EDBM_op_callf(em, op, "weld_verts targetmap=%S", &bmop, "targetmap.out")) {
- BMO_op_finish(em->bm, &bmop);
- continue;
- }
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
+ }
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
- }
+ const int count = (totvert_orig - em->bm->totvert);
- const int count = (totvert_orig - em->bm->totvert);
+ /* restore selection from tags */
+ BM_mesh_elem_hflag_enable_test(em->bm, htype_select, BM_ELEM_SELECT, true, true, BM_ELEM_TAG);
+ EDBM_selectmode_flush(em);
- /* restore selection from tags */
- BM_mesh_elem_hflag_enable_test(em->bm, htype_select, BM_ELEM_SELECT, true, true, BM_ELEM_TAG);
- EDBM_selectmode_flush(em);
+ if (count) {
+ count_multi += count;
+ EDBM_update_generic(em, true, true);
+ }
+ }
+ MEM_freeN(objects);
- if (count) {
- count_multi += count;
- EDBM_update_generic(em, true, true);
- }
- }
- MEM_freeN(objects);
+ BKE_reportf(op->reports, RPT_INFO, "Removed %d vertices", count_multi);
- BKE_reportf(op->reports, RPT_INFO, "Removed %d vertices", count_multi);
-
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_remove_doubles(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Doubles";
- ot->description = "Remove duplicate vertices";
- ot->idname = "MESH_OT_remove_doubles";
-
- /* api callbacks */
- ot->exec = edbm_remove_doubles_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_float_distance(ot->srna, "threshold", 1e-4f, 1e-6f, 50.0f, "Merge Distance",
- "Minimum distance between elements to merge", 1e-5f, 10.0f);
- RNA_def_boolean(ot->srna, "use_unselected", false, "Unselected", "Merge selected to other unselected vertices");
+ /* identifiers */
+ ot->name = "Remove Doubles";
+ ot->description = "Remove duplicate vertices";
+ ot->idname = "MESH_OT_remove_doubles";
+
+ /* api callbacks */
+ ot->exec = edbm_remove_doubles_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_float_distance(ot->srna,
+ "threshold",
+ 1e-4f,
+ 1e-6f,
+ 50.0f,
+ "Merge Distance",
+ "Minimum distance between elements to merge",
+ 1e-5f,
+ 10.0f);
+ RNA_def_boolean(ot->srna,
+ "use_unselected",
+ false,
+ "Unselected",
+ "Merge selected to other unselected vertices");
}
/** \} */
@@ -3035,85 +3182,83 @@ void MESH_OT_remove_doubles(wmOperatorType *ot)
/* BMESH_TODO this should be properly encapsulated in a bmop. but later.*/
static bool shape_propagate(BMEditMesh *em)
{
- BMIter iter;
- BMVert *eve = NULL;
- float *co;
- int totshape = CustomData_number_of_layers(&em->bm->vdata, CD_SHAPEKEY);
+ BMIter iter;
+ BMVert *eve = NULL;
+ float *co;
+ int totshape = CustomData_number_of_layers(&em->bm->vdata, CD_SHAPEKEY);
- if (!CustomData_has_layer(&em->bm->vdata, CD_SHAPEKEY)) {
- return false;
- }
+ if (!CustomData_has_layer(&em->bm->vdata, CD_SHAPEKEY)) {
+ return false;
+ }
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(eve, BM_ELEM_SELECT) || BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- continue;
- }
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_SELECT) || BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+ continue;
+ }
- for (int i = 0; i < totshape; i++) {
- co = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, i);
- copy_v3_v3(co, eve->co);
- }
- }
- return true;
+ for (int i = 0; i < totshape; i++) {
+ co = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, i);
+ copy_v3_v3(co, eve->co);
+ }
+ }
+ return true;
}
static int edbm_shape_propagate_to_all_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- int tot_shapekeys = 0;
- int tot_selected_verts_objects = 0;
-
- 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];
- Mesh *me = obedit->data;
- BMEditMesh *em = me->edit_mesh;
-
- if (em->bm->totvertsel == 0) {
- continue;
- }
- tot_selected_verts_objects++;
-
- if (shape_propagate(em)) {
- tot_shapekeys++;
- }
-
- EDBM_update_generic(em, false, false);
- }
- MEM_freeN(objects);
-
- if (tot_selected_verts_objects == 0) {
- BKE_report(op->reports, RPT_ERROR, "No selected vertex");
- return OPERATOR_CANCELLED;
- }
- else if (tot_shapekeys == 0) {
- BKE_report(
- op->reports,
- RPT_ERROR,
- objects_len > 1 ?
- "Meshes do not have shape keys" :
- "Mesh does not have shape keys");
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ int tot_shapekeys = 0;
+ int tot_selected_verts_objects = 0;
+
+ 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];
+ Mesh *me = obedit->data;
+ BMEditMesh *em = me->edit_mesh;
+
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
+ tot_selected_verts_objects++;
+
+ if (shape_propagate(em)) {
+ tot_shapekeys++;
+ }
+
+ EDBM_update_generic(em, false, false);
+ }
+ MEM_freeN(objects);
+
+ if (tot_selected_verts_objects == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No selected vertex");
+ return OPERATOR_CANCELLED;
+ }
+ else if (tot_shapekeys == 0) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ objects_len > 1 ? "Meshes do not have shape keys" :
+ "Mesh does not have shape keys");
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
-
void MESH_OT_shape_propagate_to_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Shape Propagate";
- ot->description = "Apply selected vertex locations to all other shape keys";
- ot->idname = "MESH_OT_shape_propagate_to_all";
+ /* identifiers */
+ ot->name = "Shape Propagate";
+ ot->description = "Apply selected vertex locations to all other shape keys";
+ ot->idname = "MESH_OT_shape_propagate_to_all";
- /* api callbacks */
- ot->exec = edbm_shape_propagate_to_all_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_shape_propagate_to_all_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -3125,171 +3270,175 @@ void MESH_OT_shape_propagate_to_all(wmOperatorType *ot)
/* BMESH_TODO this should be properly encapsulated in a bmop. but later.*/
static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op)
{
- Object *obedit_ref = CTX_data_edit_object(C);
- Mesh *me_ref = obedit_ref->data;
- Key *key_ref = me_ref->key;
- KeyBlock *kb_ref = NULL;
- BMEditMesh *em_ref = me_ref->edit_mesh;
- BMVert *eve;
- BMIter iter;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- float co[3], *sco;
- int totshape_ref = 0;
-
- const float blend = RNA_float_get(op->ptr, "blend");
- int shape_ref = RNA_enum_get(op->ptr, "shape");
- const bool use_add = RNA_boolean_get(op->ptr, "add");
-
- /* Sanity check. */
- totshape_ref = CustomData_number_of_layers(&em_ref->bm->vdata, CD_SHAPEKEY);
-
- if (totshape_ref == 0 || shape_ref < 0) {
- BKE_report(op->reports, RPT_ERROR, "Active mesh does not have shape keys");
- return OPERATOR_CANCELLED;
- }
- else if (shape_ref >= totshape_ref) {
- /* This case occurs if operator was used before on object with more keys than current one. */
- shape_ref = 0; /* default to basis */
- }
-
- /* Get shape key - needed for finding reference shape (for add mode only). */
- if (key_ref) {
- kb_ref = BLI_findlink(&key_ref->block, shape_ref);
- }
-
- int tot_selected_verts_objects = 0;
- 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];
- Mesh *me = obedit->data;
- Key *key = me->key;
- KeyBlock *kb = NULL;
- BMEditMesh *em = me->edit_mesh;
- int shape;
-
- if (em->bm->totvertsel == 0) {
- continue;
- }
- tot_selected_verts_objects++;
-
- if (!key) {
- continue;
- }
- else {
- kb = BKE_keyblock_find_name(key, kb_ref->name);
- shape = BLI_findindex(&key->block, kb);
- }
-
- if (kb) {
- /* Perform blending on selected vertices. */
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(eve, BM_ELEM_SELECT) || BM_elem_flag_test(eve, BM_ELEM_HIDDEN))
- continue;
-
- /* Get coordinates of shapekey we're blending from. */
- sco = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, shape);
- copy_v3_v3(co, sco);
-
- 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);
- }
-
- madd_v3_v3fl(eve->co, co, blend);
- }
- else {
- /* In blend mode, we interpolate to the shape key. */
- interp_v3_v3v3(eve->co, eve->co, co, blend);
- }
- }
- EDBM_update_generic(em, true, false);
- }
- }
- MEM_freeN(objects);
-
- if (tot_selected_verts_objects == 0) {
- BKE_report(op->reports, RPT_ERROR, "No selected vertex");
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
-}
-
-static const EnumPropertyItem *shape_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
-{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em;
- EnumPropertyItem *item = NULL;
- int totitem = 0;
-
- if ((obedit && obedit->type == OB_MESH) &&
- (em = BKE_editmesh_from_object(obedit)) &&
- CustomData_has_layer(&em->bm->vdata, CD_SHAPEKEY))
- {
- EnumPropertyItem tmp = {0, "", 0, "", ""};
- int a;
-
- for (a = 0; a < em->bm->vdata.totlayer; a++) {
- if (em->bm->vdata.layers[a].type != CD_SHAPEKEY)
- continue;
-
- tmp.value = totitem;
- tmp.identifier = em->bm->vdata.layers[a].name;
- tmp.name = em->bm->vdata.layers[a].name;
- /* RNA_enum_item_add sets totitem itself! */
- RNA_enum_item_add(&item, &totitem, &tmp);
- }
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ Object *obedit_ref = CTX_data_edit_object(C);
+ Mesh *me_ref = obedit_ref->data;
+ Key *key_ref = me_ref->key;
+ KeyBlock *kb_ref = NULL;
+ BMEditMesh *em_ref = me_ref->edit_mesh;
+ BMVert *eve;
+ BMIter iter;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ float co[3], *sco;
+ int totshape_ref = 0;
+
+ const float blend = RNA_float_get(op->ptr, "blend");
+ int shape_ref = RNA_enum_get(op->ptr, "shape");
+ const bool use_add = RNA_boolean_get(op->ptr, "add");
+
+ /* Sanity check. */
+ totshape_ref = CustomData_number_of_layers(&em_ref->bm->vdata, CD_SHAPEKEY);
+
+ if (totshape_ref == 0 || shape_ref < 0) {
+ BKE_report(op->reports, RPT_ERROR, "Active mesh does not have shape keys");
+ return OPERATOR_CANCELLED;
+ }
+ else if (shape_ref >= totshape_ref) {
+ /* This case occurs if operator was used before on object with more keys than current one. */
+ shape_ref = 0; /* default to basis */
+ }
+
+ /* Get shape key - needed for finding reference shape (for add mode only). */
+ if (key_ref) {
+ kb_ref = BLI_findlink(&key_ref->block, shape_ref);
+ }
+
+ int tot_selected_verts_objects = 0;
+ 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];
+ Mesh *me = obedit->data;
+ Key *key = me->key;
+ KeyBlock *kb = NULL;
+ BMEditMesh *em = me->edit_mesh;
+ int shape;
+
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
+ tot_selected_verts_objects++;
+
+ if (!key) {
+ continue;
+ }
+ else {
+ kb = BKE_keyblock_find_name(key, kb_ref->name);
+ shape = BLI_findindex(&key->block, kb);
+ }
+
+ if (kb) {
+ /* Perform blending on selected vertices. */
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_SELECT) || BM_elem_flag_test(eve, BM_ELEM_HIDDEN))
+ continue;
+
+ /* Get coordinates of shapekey we're blending from. */
+ sco = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, shape);
+ copy_v3_v3(co, sco);
+
+ 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);
+ }
+
+ madd_v3_v3fl(eve->co, co, blend);
+ }
+ else {
+ /* In blend mode, we interpolate to the shape key. */
+ interp_v3_v3v3(eve->co, eve->co, co, blend);
+ }
+ }
+ EDBM_update_generic(em, true, false);
+ }
+ }
+ MEM_freeN(objects);
+
+ if (tot_selected_verts_objects == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No selected vertex");
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static const EnumPropertyItem *shape_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em;
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+
+ if ((obedit && obedit->type == OB_MESH) && (em = BKE_editmesh_from_object(obedit)) &&
+ CustomData_has_layer(&em->bm->vdata, CD_SHAPEKEY)) {
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ int a;
+
+ for (a = 0; a < em->bm->vdata.totlayer; a++) {
+ if (em->bm->vdata.layers[a].type != CD_SHAPEKEY)
+ continue;
+
+ tmp.value = totitem;
+ tmp.identifier = em->bm->vdata.layers[a].name;
+ tmp.name = em->bm->vdata.layers[a].name;
+ /* RNA_enum_item_add sets totitem itself! */
+ RNA_enum_item_add(&item, &totitem, &tmp);
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
static void edbm_blend_from_shape_ui(bContext *C, wmOperator *op)
{
- uiLayout *layout = op->layout;
- PointerRNA ptr;
- Object *obedit = CTX_data_edit_object(C);
- Mesh *me = obedit->data;
- PointerRNA ptr_key;
+ uiLayout *layout = op->layout;
+ PointerRNA ptr;
+ Object *obedit = CTX_data_edit_object(C);
+ Mesh *me = obedit->data;
+ PointerRNA ptr_key;
- RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
- RNA_id_pointer_create((ID *)me->key, &ptr_key);
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+ RNA_id_pointer_create((ID *)me->key, &ptr_key);
- uiItemPointerR(layout, &ptr, "shape", &ptr_key, "key_blocks", "", ICON_SHAPEKEY_DATA);
- uiItemR(layout, &ptr, "blend", 0, NULL, ICON_NONE);
- uiItemR(layout, &ptr, "add", 0, NULL, ICON_NONE);
+ uiItemPointerR(layout, &ptr, "shape", &ptr_key, "key_blocks", "", ICON_SHAPEKEY_DATA);
+ uiItemR(layout, &ptr, "blend", 0, NULL, ICON_NONE);
+ uiItemR(layout, &ptr, "add", 0, NULL, ICON_NONE);
}
void MESH_OT_blend_from_shape(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Blend From Shape";
- ot->description = "Blend in shape from a shape key";
- ot->idname = "MESH_OT_blend_from_shape";
+ /* identifiers */
+ ot->name = "Blend From Shape";
+ ot->description = "Blend in shape from a shape key";
+ ot->idname = "MESH_OT_blend_from_shape";
- /* api callbacks */
- ot->exec = edbm_blend_from_shape_exec;
-// ot->invoke = WM_operator_props_popup_call; /* disable because search popup closes too easily */
- ot->ui = edbm_blend_from_shape_ui;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_blend_from_shape_exec;
+ // ot->invoke = WM_operator_props_popup_call; /* disable because search popup closes too easily */
+ ot->ui = edbm_blend_from_shape_ui;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- prop = RNA_def_enum(ot->srna, "shape", DummyRNA_NULL_items, 0, "Shape", "Shape key to use for blending");
- RNA_def_enum_funcs(prop, shape_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE | PROP_NEVER_UNLINK);
- RNA_def_float(ot->srna, "blend", 1.0f, -1e3f, 1e3f, "Blend", "Blending factor", -2.0f, 2.0f);
- RNA_def_boolean(ot->srna, "add", true, "Add", "Add rather than blend between shapes");
+ /* properties */
+ prop = RNA_def_enum(
+ ot->srna, "shape", DummyRNA_NULL_items, 0, "Shape", "Shape key to use for blending");
+ RNA_def_enum_funcs(prop, shape_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE | PROP_NEVER_UNLINK);
+ RNA_def_float(ot->srna, "blend", 1.0f, -1e3f, 1e3f, "Blend", "Blending factor", -2.0f, 2.0f);
+ RNA_def_boolean(ot->srna, "add", true, "Add", "Add rather than blend between shapes");
}
/** \} */
@@ -3300,65 +3449,68 @@ void MESH_OT_blend_from_shape(wmOperatorType *ot)
static int edbm_solidify_exec(bContext *C, wmOperator *op)
{
- const float thickness = RNA_float_get(op->ptr, "thickness");
+ const float thickness = RNA_float_get(op->ptr, "thickness");
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
- if (em->bm->totfacesel == 0) {
- continue;
- }
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
- BMOperator bmop;
+ BMOperator bmop;
- if (!EDBM_op_init(em, &bmop, op, "solidify geom=%hf thickness=%f", BM_ELEM_SELECT, thickness)) {
- continue;
- }
+ if (!EDBM_op_init(
+ em, &bmop, op, "solidify geom=%hf thickness=%f", BM_ELEM_SELECT, thickness)) {
+ continue;
+ }
- /* deselect only the faces in the region to be solidified (leave wire
- * edges and loose verts selected, as there will be no corresponding
- * geometry selected below) */
- BMO_slot_buffer_hflag_disable(bm, bmop.slots_in, "geom", BM_FACE, BM_ELEM_SELECT, true);
+ /* deselect only the faces in the region to be solidified (leave wire
+ * edges and loose verts selected, as there will be no corresponding
+ * geometry selected below) */
+ BMO_slot_buffer_hflag_disable(bm, bmop.slots_in, "geom", BM_FACE, BM_ELEM_SELECT, true);
- /* run the solidify operator */
- BMO_op_exec(bm, &bmop);
+ /* run the solidify operator */
+ BMO_op_exec(bm, &bmop);
- /* select the newly generated faces */
- BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
+ /* select the newly generated faces */
+ BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
- EDBM_update_generic(em, true, true);
- }
+ EDBM_update_generic(em, true, true);
+ }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_solidify(wmOperatorType *ot)
{
- PropertyRNA *prop;
- /* identifiers */
- ot->name = "Solidify";
- ot->description = "Create a solid skin by extruding, compensating for sharp angles";
- ot->idname = "MESH_OT_solidify";
+ PropertyRNA *prop;
+ /* identifiers */
+ ot->name = "Solidify";
+ ot->description = "Create a solid skin by extruding, compensating for sharp angles";
+ ot->idname = "MESH_OT_solidify";
- /* api callbacks */
- ot->exec = edbm_solidify_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_solidify_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_float_distance(ot->srna, "thickness", 0.01f, -1e4f, 1e4f, "Thickness", "", -10.0f, 10.0f);
- RNA_def_property_ui_range(prop, -10.0, 10.0, 0.1, 4);
+ prop = RNA_def_float_distance(
+ ot->srna, "thickness", 0.01f, -1e4f, 1e4f, "Thickness", "", -10.0f, 10.0f);
+ RNA_def_property_ui_range(prop, -10.0, 10.0, 0.1, 4);
}
/** \} */
@@ -3367,322 +3519,328 @@ void MESH_OT_solidify(wmOperatorType *ot)
/** \name Knife Subdivide Operator
* \{ */
-#define KNIFE_EXACT 1
-#define KNIFE_MIDPOINT 2
-#define KNIFE_MULTICUT 3
+#define KNIFE_EXACT 1
+#define KNIFE_MIDPOINT 2
+#define KNIFE_MULTICUT 3
static const EnumPropertyItem knife_items[] = {
- {KNIFE_EXACT, "EXACT", 0, "Exact", ""},
- {KNIFE_MIDPOINT, "MIDPOINTS", 0, "Midpoints", ""},
- {KNIFE_MULTICUT, "MULTICUT", 0, "Multicut", ""},
- {0, NULL, 0, NULL, NULL},
+ {KNIFE_EXACT, "EXACT", 0, "Exact", ""},
+ {KNIFE_MIDPOINT, "MIDPOINTS", 0, "Midpoints", ""},
+ {KNIFE_MULTICUT, "MULTICUT", 0, "Multicut", ""},
+ {0, NULL, 0, NULL, NULL},
};
/* bm_edge_seg_isect() Determines if and where a mouse trail intersects an BMEdge */
-static float bm_edge_seg_isect(
- const float sco_a[2], const float sco_b[2],
- float (*mouse_path)[2], int len, char mode, int *isected)
+static float bm_edge_seg_isect(const float sco_a[2],
+ const float sco_b[2],
+ float (*mouse_path)[2],
+ int len,
+ char mode,
+ int *isected)
{
#define MAXSLOPE 100000
- float x11, y11, x12 = 0, y12 = 0, x2max, x2min, y2max;
- float y2min, dist, lastdist = 0, xdiff2, xdiff1;
- float m1, b1, m2, b2, x21, x22, y21, y22, xi;
- float yi, x1min, x1max, y1max, y1min, perc = 0;
- float threshold = 0.0;
- int i;
-
- //threshold = 0.000001; /* tolerance for vertex intersection */
- // XXX threshold = scene->toolsettings->select_thresh / 100;
-
- /* Get screen coords of verts */
- x21 = sco_a[0];
- y21 = sco_a[1];
-
- x22 = sco_b[0];
- y22 = sco_b[1];
-
- xdiff2 = (x22 - x21);
- if (xdiff2) {
- m2 = (y22 - y21) / xdiff2;
- b2 = ((x22 * y21) - (x21 * y22)) / xdiff2;
- }
- else {
- m2 = MAXSLOPE; /* Vertical slope */
- b2 = x22;
- }
-
- *isected = 0;
-
- /* check for _exact_ vertex intersection first */
- if (mode != KNIFE_MULTICUT) {
- for (i = 0; i < len; i++) {
- if (i > 0) {
- x11 = x12;
- y11 = y12;
- }
- else {
- x11 = mouse_path[i][0];
- y11 = mouse_path[i][1];
- }
- x12 = mouse_path[i][0];
- y12 = mouse_path[i][1];
-
- /* test e->v1 */
- if ((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)) {
- perc = 0;
- *isected = 1;
- return perc;
- }
- /* test e->v2 */
- else if ((x11 == x22 && y11 == y22) || (x12 == x22 && y12 == y22)) {
- perc = 0;
- *isected = 2;
- return perc;
- }
- }
- }
-
- /* now check for edge intersect (may produce vertex intersection as well) */
- for (i = 0; i < len; i++) {
- if (i > 0) {
- x11 = x12;
- y11 = y12;
- }
- else {
- x11 = mouse_path[i][0];
- y11 = mouse_path[i][1];
- }
- x12 = mouse_path[i][0];
- y12 = mouse_path[i][1];
-
- /* Perp. Distance from point to line */
- if (m2 != MAXSLOPE) {
- /* sqrt(m2 * m2 + 1); Only looking for change in sign. Skip extra math .*/
- dist = (y12 - m2 * x12 - b2);
- }
- else dist = x22 - x12;
-
- if (i == 0) lastdist = dist;
-
- /* if dist changes sign, and intersect point in edge's Bound Box */
- if ((lastdist * dist) <= 0) {
- xdiff1 = (x12 - x11); /* Equation of line between last 2 points */
- if (xdiff1) {
- m1 = (y12 - y11) / xdiff1;
- b1 = ((x12 * y11) - (x11 * y12)) / xdiff1;
- }
- else {
- m1 = MAXSLOPE;
- b1 = x12;
- }
- x2max = max_ff(x21, x22) + 0.001f; /* prevent missed edges */
- x2min = min_ff(x21, x22) - 0.001f; /* due to round off error */
- y2max = max_ff(y21, y22) + 0.001f;
- y2min = min_ff(y21, y22) - 0.001f;
-
- /* Found an intersect, calc intersect point */
- if (m1 == m2) { /* co-incident lines */
- /* cut at 50% of overlap area */
- x1max = max_ff(x11, x12);
- x1min = min_ff(x11, x12);
- xi = (min_ff(x2max, x1max) + max_ff(x2min, x1min)) / 2.0f;
-
- y1max = max_ff(y11, y12);
- y1min = min_ff(y11, y12);
- yi = (min_ff(y2max, y1max) + max_ff(y2min, y1min)) / 2.0f;
- }
- else if (m2 == MAXSLOPE) {
- xi = x22;
- yi = m1 * x22 + b1;
- }
- else if (m1 == MAXSLOPE) {
- xi = x12;
- yi = m2 * x12 + b2;
- }
- else {
- xi = (b1 - b2) / (m2 - m1);
- yi = (b1 * m2 - m1 * b2) / (m2 - m1);
- }
-
- /* Intersect inside bounding box of edge?*/
- if ((xi >= x2min) && (xi <= x2max) && (yi <= y2max) && (yi >= y2min)) {
- /* test for vertex intersect that may be 'close enough'*/
- if (mode != KNIFE_MULTICUT) {
- if (xi <= (x21 + threshold) && xi >= (x21 - threshold)) {
- if (yi <= (y21 + threshold) && yi >= (y21 - threshold)) {
- *isected = 1;
- perc = 0;
- break;
- }
- }
- if (xi <= (x22 + threshold) && xi >= (x22 - threshold)) {
- if (yi <= (y22 + threshold) && yi >= (y22 - threshold)) {
- *isected = 2;
- perc = 0;
- break;
- }
- }
- }
- if ((m2 <= 1.0f) && (m2 >= -1.0f)) perc = (xi - x21) / (x22 - x21);
- else perc = (yi - y21) / (y22 - y21); /* lower slope more accurate */
- //isect = 32768.0 * (perc + 0.0000153); /* Percentage in 1 / 32768ths */
-
- break;
- }
- }
- lastdist = dist;
- }
- return perc;
+ float x11, y11, x12 = 0, y12 = 0, x2max, x2min, y2max;
+ float y2min, dist, lastdist = 0, xdiff2, xdiff1;
+ float m1, b1, m2, b2, x21, x22, y21, y22, xi;
+ float yi, x1min, x1max, y1max, y1min, perc = 0;
+ float threshold = 0.0;
+ int i;
+
+ //threshold = 0.000001; /* tolerance for vertex intersection */
+ // XXX threshold = scene->toolsettings->select_thresh / 100;
+
+ /* Get screen coords of verts */
+ x21 = sco_a[0];
+ y21 = sco_a[1];
+
+ x22 = sco_b[0];
+ y22 = sco_b[1];
+
+ xdiff2 = (x22 - x21);
+ if (xdiff2) {
+ m2 = (y22 - y21) / xdiff2;
+ b2 = ((x22 * y21) - (x21 * y22)) / xdiff2;
+ }
+ else {
+ m2 = MAXSLOPE; /* Vertical slope */
+ b2 = x22;
+ }
+
+ *isected = 0;
+
+ /* check for _exact_ vertex intersection first */
+ if (mode != KNIFE_MULTICUT) {
+ for (i = 0; i < len; i++) {
+ if (i > 0) {
+ x11 = x12;
+ y11 = y12;
+ }
+ else {
+ x11 = mouse_path[i][0];
+ y11 = mouse_path[i][1];
+ }
+ x12 = mouse_path[i][0];
+ y12 = mouse_path[i][1];
+
+ /* test e->v1 */
+ if ((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)) {
+ perc = 0;
+ *isected = 1;
+ return perc;
+ }
+ /* test e->v2 */
+ else if ((x11 == x22 && y11 == y22) || (x12 == x22 && y12 == y22)) {
+ perc = 0;
+ *isected = 2;
+ return perc;
+ }
+ }
+ }
+
+ /* now check for edge intersect (may produce vertex intersection as well) */
+ for (i = 0; i < len; i++) {
+ if (i > 0) {
+ x11 = x12;
+ y11 = y12;
+ }
+ else {
+ x11 = mouse_path[i][0];
+ y11 = mouse_path[i][1];
+ }
+ x12 = mouse_path[i][0];
+ y12 = mouse_path[i][1];
+
+ /* Perp. Distance from point to line */
+ if (m2 != MAXSLOPE) {
+ /* sqrt(m2 * m2 + 1); Only looking for change in sign. Skip extra math .*/
+ dist = (y12 - m2 * x12 - b2);
+ }
+ else
+ dist = x22 - x12;
+
+ if (i == 0)
+ lastdist = dist;
+
+ /* if dist changes sign, and intersect point in edge's Bound Box */
+ if ((lastdist * dist) <= 0) {
+ xdiff1 = (x12 - x11); /* Equation of line between last 2 points */
+ if (xdiff1) {
+ m1 = (y12 - y11) / xdiff1;
+ b1 = ((x12 * y11) - (x11 * y12)) / xdiff1;
+ }
+ else {
+ m1 = MAXSLOPE;
+ b1 = x12;
+ }
+ x2max = max_ff(x21, x22) + 0.001f; /* prevent missed edges */
+ x2min = min_ff(x21, x22) - 0.001f; /* due to round off error */
+ y2max = max_ff(y21, y22) + 0.001f;
+ y2min = min_ff(y21, y22) - 0.001f;
+
+ /* Found an intersect, calc intersect point */
+ if (m1 == m2) { /* co-incident lines */
+ /* cut at 50% of overlap area */
+ x1max = max_ff(x11, x12);
+ x1min = min_ff(x11, x12);
+ xi = (min_ff(x2max, x1max) + max_ff(x2min, x1min)) / 2.0f;
+
+ y1max = max_ff(y11, y12);
+ y1min = min_ff(y11, y12);
+ yi = (min_ff(y2max, y1max) + max_ff(y2min, y1min)) / 2.0f;
+ }
+ else if (m2 == MAXSLOPE) {
+ xi = x22;
+ yi = m1 * x22 + b1;
+ }
+ else if (m1 == MAXSLOPE) {
+ xi = x12;
+ yi = m2 * x12 + b2;
+ }
+ else {
+ xi = (b1 - b2) / (m2 - m1);
+ yi = (b1 * m2 - m1 * b2) / (m2 - m1);
+ }
+
+ /* Intersect inside bounding box of edge?*/
+ if ((xi >= x2min) && (xi <= x2max) && (yi <= y2max) && (yi >= y2min)) {
+ /* test for vertex intersect that may be 'close enough'*/
+ if (mode != KNIFE_MULTICUT) {
+ if (xi <= (x21 + threshold) && xi >= (x21 - threshold)) {
+ if (yi <= (y21 + threshold) && yi >= (y21 - threshold)) {
+ *isected = 1;
+ perc = 0;
+ break;
+ }
+ }
+ if (xi <= (x22 + threshold) && xi >= (x22 - threshold)) {
+ if (yi <= (y22 + threshold) && yi >= (y22 - threshold)) {
+ *isected = 2;
+ perc = 0;
+ break;
+ }
+ }
+ }
+ if ((m2 <= 1.0f) && (m2 >= -1.0f))
+ perc = (xi - x21) / (x22 - x21);
+ else
+ perc = (yi - y21) / (y22 - y21); /* lower slope more accurate */
+ //isect = 32768.0 * (perc + 0.0000153); /* Percentage in 1 / 32768ths */
+
+ break;
+ }
+ }
+ lastdist = dist;
+ }
+ return perc;
}
#define ELE_EDGE_CUT 1
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);
- BMVert *bv;
- BMIter iter;
- BMEdge *be;
- BMOperator bmop;
- float isect = 0.0f;
- int len = 0, isected, i;
- short numcuts = 1;
- const short mode = RNA_int_get(op->ptr, "type");
- BMOpSlot *slot_edge_percents;
-
- /* 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))
- return OPERATOR_CANCELLED;
-
- if (bm->totvertsel < 2) {
- BKE_report(op->reports, RPT_ERROR, "No edges are selected to operate on");
- return OPERATOR_CANCELLED;
- }
-
- len = RNA_collection_length(op->ptr, "path");
-
- if (len < 2) {
- BKE_report(op->reports, RPT_ERROR, "Mouse path too short");
- return OPERATOR_CANCELLED;
- }
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ ARegion *ar = CTX_wm_region(C);
+ BMVert *bv;
+ BMIter iter;
+ BMEdge *be;
+ BMOperator bmop;
+ float isect = 0.0f;
+ int len = 0, isected, i;
+ short numcuts = 1;
+ const short mode = RNA_int_get(op->ptr, "type");
+ BMOpSlot *slot_edge_percents;
+
+ /* 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))
+ return OPERATOR_CANCELLED;
+
+ if (bm->totvertsel < 2) {
+ BKE_report(op->reports, RPT_ERROR, "No edges are selected to operate on");
+ return OPERATOR_CANCELLED;
+ }
+
+ len = RNA_collection_length(op->ptr, "path");
+
+ if (len < 2) {
+ BKE_report(op->reports, RPT_ERROR, "Mouse path too short");
+ return OPERATOR_CANCELLED;
+ }
+
+ mouse_path = MEM_mallocN(len * sizeof(*mouse_path), __func__);
+
+ /* get the cut curve */
+ RNA_BEGIN (op->ptr, itemptr, "path") {
+ RNA_float_get_array(&itemptr, "loc", (float *)&mouse_path[len]);
+ }
+ RNA_END;
+
+ /* for ED_view3d_project_float_object */
+ ED_view3d_init_mats_rv3d(obedit, ar->regiondata);
+
+ /* TODO, investigate using index lookup for screen_vert_coords() rather then a hash table */
+
+ /* the floating point coordinates of verts in screen space will be
+ * stored in a hash table according to the vertices pointer */
+ 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) !=
+ V3D_PROJ_RET_OK) {
+ copy_v2_fl(*sco, FLT_MAX); /* set error value */
+ }
+ BM_elem_index_set(bv, i); /* set_inline */
+ sco++;
+ }
+ bm->elem_index_dirty &= ~BM_VERT; /* clear dirty flag */
+
+ if (!EDBM_op_init(em, &bmop, op, "subdivide_edges")) {
+ MEM_freeN(mouse_path);
+ MEM_freeN(screen_vert_coords);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* store percentage of edge cut for KNIFE_EXACT here.*/
+ slot_edge_percents = BMO_slot_get(bmop.slots_in, "edge_percents");
+ BM_ITER_MESH (be, &iter, bm, BM_EDGES_OF_MESH) {
+ bool is_cut = false;
+ if (BM_elem_flag_test(be, BM_ELEM_SELECT)) {
+ const float *sco_a = screen_vert_coords[BM_elem_index_get(be->v1)];
+ const float *sco_b = screen_vert_coords[BM_elem_index_get(be->v2)];
+
+ /* check for error value (vert cant be projected) */
+ if ((sco_a[0] != FLT_MAX) && (sco_b[0] != FLT_MAX)) {
+ isect = bm_edge_seg_isect(sco_a, sco_b, mouse_path, len, mode, &isected);
+
+ if (isect != 0.0f) {
+ if (mode != KNIFE_MULTICUT && mode != KNIFE_MIDPOINT) {
+ BMO_slot_map_float_insert(&bmop, slot_edge_percents, be, isect);
+ }
+ }
+ }
+ }
+
+ BMO_edge_flag_set(bm, be, ELE_EDGE_CUT, is_cut);
+ }
+
+ /* free all allocs */
+ MEM_freeN(screen_vert_coords);
+ MEM_freeN(mouse_path);
+
+ BMO_slot_buffer_from_enabled_flag(bm, &bmop, bmop.slots_in, "edges", BM_EDGE, ELE_EDGE_CUT);
+
+ if (mode == KNIFE_MIDPOINT)
+ numcuts = 1;
+ BMO_slot_int_set(bmop.slots_in, "cuts", numcuts);
+
+ BMO_slot_int_set(bmop.slots_in, "quad_corner_type", SUBD_CORNER_STRAIGHT_CUT);
+ BMO_slot_bool_set(bmop.slots_in, "use_single_edge", false);
+ BMO_slot_bool_set(bmop.slots_in, "use_grid_fill", false);
+
+ BMO_slot_float_set(bmop.slots_in, "radius", 0);
+
+ BMO_op_exec(bm, &bmop);
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ return OPERATOR_CANCELLED;
+ }
- mouse_path = MEM_mallocN(len * sizeof(*mouse_path), __func__);
+ EDBM_update_generic(em, true, true);
- /* get the cut curve */
- RNA_BEGIN (op->ptr, itemptr, "path")
- {
- RNA_float_get_array(&itemptr, "loc", (float *)&mouse_path[len]);
- }
- RNA_END;
-
- /* for ED_view3d_project_float_object */
- ED_view3d_init_mats_rv3d(obedit, ar->regiondata);
-
- /* TODO, investigate using index lookup for screen_vert_coords() rather then a hash table */
-
- /* the floating point coordinates of verts in screen space will be
- * stored in a hash table according to the vertices pointer */
- 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) != V3D_PROJ_RET_OK) {
- copy_v2_fl(*sco, FLT_MAX); /* set error value */
- }
- BM_elem_index_set(bv, i); /* set_inline */
- sco++;
-
- }
- bm->elem_index_dirty &= ~BM_VERT; /* clear dirty flag */
-
- if (!EDBM_op_init(em, &bmop, op, "subdivide_edges")) {
- MEM_freeN(mouse_path);
- MEM_freeN(screen_vert_coords);
- return OPERATOR_CANCELLED;
- }
-
- /* store percentage of edge cut for KNIFE_EXACT here.*/
- slot_edge_percents = BMO_slot_get(bmop.slots_in, "edge_percents");
- BM_ITER_MESH (be, &iter, bm, BM_EDGES_OF_MESH) {
- bool is_cut = false;
- if (BM_elem_flag_test(be, BM_ELEM_SELECT)) {
- const float *sco_a = screen_vert_coords[BM_elem_index_get(be->v1)];
- const float *sco_b = screen_vert_coords[BM_elem_index_get(be->v2)];
-
- /* check for error value (vert cant be projected) */
- if ((sco_a[0] != FLT_MAX) && (sco_b[0] != FLT_MAX)) {
- isect = bm_edge_seg_isect(sco_a, sco_b, mouse_path, len, mode, &isected);
-
- if (isect != 0.0f) {
- if (mode != KNIFE_MULTICUT && mode != KNIFE_MIDPOINT) {
- BMO_slot_map_float_insert(&bmop, slot_edge_percents, be, isect);
- }
- }
- }
- }
-
- BMO_edge_flag_set(bm, be, ELE_EDGE_CUT, is_cut);
- }
-
-
- /* free all allocs */
- MEM_freeN(screen_vert_coords);
- MEM_freeN(mouse_path);
-
-
- BMO_slot_buffer_from_enabled_flag(bm, &bmop, bmop.slots_in, "edges", BM_EDGE, ELE_EDGE_CUT);
-
- if (mode == KNIFE_MIDPOINT) numcuts = 1;
- BMO_slot_int_set(bmop.slots_in, "cuts", numcuts);
-
- BMO_slot_int_set(bmop.slots_in, "quad_corner_type", SUBD_CORNER_STRAIGHT_CUT);
- BMO_slot_bool_set(bmop.slots_in, "use_single_edge", false);
- BMO_slot_bool_set(bmop.slots_in, "use_grid_fill", false);
-
- BMO_slot_float_set(bmop.slots_in, "radius", 0);
-
- BMO_op_exec(bm, &bmop);
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- return OPERATOR_CANCELLED;
- }
-
- EDBM_update_generic(em, true, true);
-
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
#undef ELE_EDGE_CUT
void MESH_OT_knife_cut(wmOperatorType *ot)
{
- ot->name = "Knife Cut";
- ot->description = "Cut selected edges and faces into parts";
- ot->idname = "MESH_OT_knife_cut";
+ ot->name = "Knife Cut";
+ ot->description = "Cut selected edges and faces into parts";
+ ot->idname = "MESH_OT_knife_cut";
- ot->invoke = WM_gesture_lines_invoke;
- ot->modal = WM_gesture_lines_modal;
- ot->exec = edbm_knife_cut_exec;
+ ot->invoke = WM_gesture_lines_invoke;
+ ot->modal = WM_gesture_lines_modal;
+ ot->exec = edbm_knife_cut_exec;
- ot->poll = EDBM_view3d_poll;
+ ot->poll = EDBM_view3d_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- PropertyRNA *prop;
- prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ /* properties */
+ PropertyRNA *prop;
+ prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- RNA_def_enum(ot->srna, "type", knife_items, KNIFE_EXACT, "Type", "");
+ RNA_def_enum(ot->srna, "type", knife_items, KNIFE_EXACT, "Type", "");
- /* internal */
- RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, BC_NUMCURSORS, "Cursor", "", 0, BC_NUMCURSORS);
+ /* internal */
+ RNA_def_int(
+ ot->srna, "cursor", BC_KNIFECURSOR, 0, BC_NUMCURSORS, "Cursor", "", 0, BC_NUMCURSORS);
}
/** \} */
@@ -3692,108 +3850,116 @@ void MESH_OT_knife_cut(wmOperatorType *ot)
* \{ */
enum {
- MESH_SEPARATE_SELECTED = 0,
- MESH_SEPARATE_MATERIAL = 1,
- MESH_SEPARATE_LOOSE = 2,
+ MESH_SEPARATE_SELECTED = 0,
+ MESH_SEPARATE_MATERIAL = 1,
+ MESH_SEPARATE_LOOSE = 2,
};
-static Base *mesh_separate_tagged(Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_old, BMesh *bm_old)
+static Base *mesh_separate_tagged(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_old, BMesh *bm_old)
{
- Base *base_new;
- Object *obedit = base_old->object;
- BMesh *bm_new;
+ Base *base_new;
+ Object *obedit = base_old->object;
+ BMesh *bm_new;
- bm_new = BM_mesh_create(
- &bm_mesh_allocsize_default,
- &((struct BMeshCreateParams){.use_toolflags = true,}));
- BM_mesh_elem_toolflags_ensure(bm_new); /* needed for 'duplicate' bmo */
+ bm_new = BM_mesh_create(&bm_mesh_allocsize_default,
+ &((struct BMeshCreateParams){
+ .use_toolflags = true,
+ }));
+ BM_mesh_elem_toolflags_ensure(bm_new); /* needed for 'duplicate' bmo */
- CustomData_copy(&bm_old->vdata, &bm_new->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0);
- CustomData_copy(&bm_old->edata, &bm_new->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0);
- CustomData_copy(&bm_old->ldata, &bm_new->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0);
- CustomData_copy(&bm_old->pdata, &bm_new->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0);
+ CustomData_copy(&bm_old->vdata, &bm_new->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0);
+ CustomData_copy(&bm_old->edata, &bm_new->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0);
+ CustomData_copy(&bm_old->ldata, &bm_new->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0);
+ CustomData_copy(&bm_old->pdata, &bm_new->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0);
- CustomData_bmesh_init_pool(&bm_new->vdata, bm_mesh_allocsize_default.totvert, BM_VERT);
- CustomData_bmesh_init_pool(&bm_new->edata, bm_mesh_allocsize_default.totedge, BM_EDGE);
- 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);
+ CustomData_bmesh_init_pool(&bm_new->vdata, bm_mesh_allocsize_default.totvert, BM_VERT);
+ CustomData_bmesh_init_pool(&bm_new->edata, bm_mesh_allocsize_default.totedge, BM_EDGE);
+ 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);
+ base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_old, USER_DUP_MESH);
- /* normally would call directly after but in this case delay recalc */
- /* DAG_relations_tag_update(bmain); */
+ /* 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));
+ /* new in 2.5 */
+ assign_matarar(bmain, base_new->object, give_matarar(obedit), *give_totcolp(obedit));
- ED_object_base_select(base_new, BA_SELECT);
+ ED_object_base_select(base_new, BA_SELECT);
- BMO_op_callf(bm_old, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
- "duplicate geom=%hvef dest=%p", BM_ELEM_TAG, bm_new);
- BMO_op_callf(bm_old, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
- "delete geom=%hvef context=%i", BM_ELEM_TAG, DEL_FACES);
+ BMO_op_callf(bm_old,
+ (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
+ "duplicate geom=%hvef dest=%p",
+ BM_ELEM_TAG,
+ bm_new);
+ BMO_op_callf(bm_old,
+ (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
+ "delete geom=%hvef context=%i",
+ BM_ELEM_TAG,
+ DEL_FACES);
- /* deselect loose data - this used to get deleted,
- * we could de-select edges and verts only, but this turns out to be less complicated
- * since de-selecting all skips selection flushing logic */
- BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
+ /* deselect loose data - this used to get deleted,
+ * we could de-select edges and verts only, but this turns out to be less complicated
+ * since de-selecting all skips selection flushing logic */
+ BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
- BM_mesh_normals_update(bm_new);
+ BM_mesh_normals_update(bm_new);
- BM_mesh_bm_to_me(bmain, bm_new, base_new->object->data, (&(struct BMeshToMeshParams){0}));
+ BM_mesh_bm_to_me(bmain, bm_new, base_new->object->data, (&(struct BMeshToMeshParams){0}));
- BM_mesh_free(bm_new);
- ((Mesh *)base_new->object->data)->edit_mesh = NULL;
+ BM_mesh_free(bm_new);
+ ((Mesh *)base_new->object->data)->edit_mesh = NULL;
- return base_new;
+ return base_new;
}
-static bool mesh_separate_selected(Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_old, BMesh *bm_old)
+static bool mesh_separate_selected(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_old, BMesh *bm_old)
{
- /* we may have tags from previous operators */
- BM_mesh_elem_hflag_disable_all(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, false);
+ /* we may have tags from previous operators */
+ BM_mesh_elem_hflag_disable_all(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, false);
- /* sel -> tag */
- BM_mesh_elem_hflag_enable_test(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, true, false, BM_ELEM_SELECT);
+ /* sel -> tag */
+ BM_mesh_elem_hflag_enable_test(
+ bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, true, false, BM_ELEM_SELECT);
- return (mesh_separate_tagged(bmain, scene, view_layer, base_old, bm_old) != NULL);
+ return (mesh_separate_tagged(bmain, scene, view_layer, base_old, bm_old) != NULL);
}
/* flush a hflag to from verts to edges/faces */
static void bm_mesh_hflag_flush_vert(BMesh *bm, const char hflag)
{
- BMEdge *e;
- BMLoop *l_iter;
- BMLoop *l_first;
- BMFace *f;
-
- BMIter eiter;
- BMIter fiter;
-
- bool ok;
-
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e->v1, hflag) &&
- BM_elem_flag_test(e->v2, hflag))
- {
- BM_elem_flag_enable(e, hflag);
- }
- else {
- BM_elem_flag_disable(e, hflag);
- }
- }
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- ok = true;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (!BM_elem_flag_test(l_iter->v, hflag)) {
- ok = false;
- break;
- }
- } while ((l_iter = l_iter->next) != l_first);
-
- BM_elem_flag_set(f, hflag, ok);
- }
+ BMEdge *e;
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ BMFace *f;
+
+ BMIter eiter;
+ BMIter fiter;
+
+ bool ok;
+
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e->v1, hflag) && BM_elem_flag_test(e->v2, hflag)) {
+ BM_elem_flag_enable(e, hflag);
+ }
+ else {
+ BM_elem_flag_disable(e, hflag);
+ }
+ }
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ ok = true;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (!BM_elem_flag_test(l_iter->v, hflag)) {
+ ok = false;
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ BM_elem_flag_set(f, hflag, ok);
+ }
}
/**
@@ -3804,307 +3970,322 @@ static void bm_mesh_hflag_flush_vert(BMesh *bm, const char hflag)
*/
static void mesh_separate_material_assign_mat_nr(Main *bmain, Object *ob, const short mat_nr)
{
- ID *obdata = ob->data;
-
- Material ***matarar;
- const short *totcolp;
-
- totcolp = give_totcolp_id(obdata);
- matarar = give_matarar_id(obdata);
-
- if ((totcolp && matarar) == 0) {
- BLI_assert(0);
- return;
- }
-
- if (*totcolp) {
- Material *ma_ob;
- Material *ma_obdata;
- char matbit;
-
- if (mat_nr < ob->totcol) {
- ma_ob = ob->mat[mat_nr];
- matbit = ob->matbits[mat_nr];
- }
- else {
- ma_ob = NULL;
- matbit = 0;
- }
-
- if (mat_nr < *totcolp) {
- ma_obdata = (*matarar)[mat_nr];
- }
- else {
- ma_obdata = NULL;
- }
-
- BKE_material_clear_id(bmain, obdata, true);
- BKE_material_resize_object(bmain, ob, 1, true);
- BKE_material_resize_id(bmain, obdata, 1, true);
-
- ob->mat[0] = ma_ob;
- id_us_plus((ID *)ma_ob);
- ob->matbits[0] = matbit;
- (*matarar)[0] = ma_obdata;
- id_us_plus((ID *)ma_obdata);
- }
- else {
- BKE_material_clear_id(bmain, obdata, true);
- BKE_material_resize_object(bmain, ob, 0, true);
- BKE_material_resize_id(bmain, obdata, 0, true);
- }
-}
-
-static bool mesh_separate_material(Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_old, BMesh *bm_old)
-{
- BMFace *f_cmp, *f;
- BMIter iter;
- bool result = false;
-
- while ((f_cmp = BM_iter_at_index(bm_old, BM_FACES_OF_MESH, NULL, 0))) {
- Base *base_new;
- const short mat_nr = f_cmp->mat_nr;
- int tot = 0;
-
- BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
-
- BM_ITER_MESH (f, &iter, bm_old, BM_FACES_OF_MESH) {
- if (f->mat_nr == mat_nr) {
- BMLoop *l_iter;
- BMLoop *l_first;
-
- BM_elem_flag_enable(f, BM_ELEM_TAG);
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG);
- BM_elem_flag_enable(l_iter->e, BM_ELEM_TAG);
- } while ((l_iter = l_iter->next) != l_first);
-
- tot++;
- }
- }
-
- /* leave the current object with some materials */
- if (tot == bm_old->totface) {
- mesh_separate_material_assign_mat_nr(bmain, base_old->object, mat_nr);
-
- /* since we're in editmode, must set faces here */
- BM_ITER_MESH (f, &iter, bm_old, BM_FACES_OF_MESH) {
- f->mat_nr = 0;
- }
- break;
- }
-
- /* Move selection into a separate object */
- base_new = mesh_separate_tagged(bmain, scene, view_layer, base_old, bm_old);
- if (base_new) {
- mesh_separate_material_assign_mat_nr(bmain, base_new->object, mat_nr);
- }
-
- result |= (base_new != NULL);
- }
-
- return result;
-}
-
-static bool mesh_separate_loose(Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_old, BMesh *bm_old)
-{
- int i;
- BMEdge *e;
- BMVert *v_seed;
- BMWalker walker;
- bool result = false;
- int max_iter = bm_old->totvert;
-
- /* Clear all selected vertices */
- BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
-
- /* A "while (true)" loop should work here as each iteration should
- * select and remove at least one vertex and when all vertices
- * are selected the loop will break out. But guard against bad
- * behavior by limiting iterations to the number of vertices in the
- * original mesh.*/
- for (i = 0; i < max_iter; i++) {
- int tot = 0;
- /* Get a seed vertex to start the walk */
- v_seed = BM_iter_at_index(bm_old, BM_VERTS_OF_MESH, NULL, 0);
-
- /* No vertices available, can't do anything */
- if (v_seed == NULL) {
- break;
- }
-
- /* Select the seed explicitly, in case it has no edges */
- if (!BM_elem_flag_test(v_seed, BM_ELEM_TAG)) { BM_elem_flag_enable(v_seed, BM_ELEM_TAG); tot++; }
-
- /* Walk from the single vertex, selecting everything connected
- * to it */
- BMW_init(&walker, bm_old, BMW_VERT_SHELL,
- BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_NOP,
- BMW_NIL_LAY);
-
- for (e = BMW_begin(&walker, v_seed); e; e = BMW_step(&walker)) {
- if (!BM_elem_flag_test(e->v1, BM_ELEM_TAG)) { BM_elem_flag_enable(e->v1, BM_ELEM_TAG); tot++; }
- if (!BM_elem_flag_test(e->v2, BM_ELEM_TAG)) { BM_elem_flag_enable(e->v2, BM_ELEM_TAG); tot++; }
- }
- BMW_end(&walker);
-
- if (bm_old->totvert == tot) {
- /* Every vertex selected, nothing to separate, work is done */
- break;
- }
-
- /* Flush the selection to get edge/face selections matching
- * the vertex selection */
- bm_mesh_hflag_flush_vert(bm_old, BM_ELEM_TAG);
-
- /* Move selection into a separate object */
- result |= (mesh_separate_tagged(bmain, scene, view_layer, base_old, bm_old) != NULL);
- }
-
- return result;
+ ID *obdata = ob->data;
+
+ Material ***matarar;
+ const short *totcolp;
+
+ totcolp = give_totcolp_id(obdata);
+ matarar = give_matarar_id(obdata);
+
+ if ((totcolp && matarar) == 0) {
+ BLI_assert(0);
+ return;
+ }
+
+ if (*totcolp) {
+ Material *ma_ob;
+ Material *ma_obdata;
+ char matbit;
+
+ if (mat_nr < ob->totcol) {
+ ma_ob = ob->mat[mat_nr];
+ matbit = ob->matbits[mat_nr];
+ }
+ else {
+ ma_ob = NULL;
+ matbit = 0;
+ }
+
+ if (mat_nr < *totcolp) {
+ ma_obdata = (*matarar)[mat_nr];
+ }
+ else {
+ ma_obdata = NULL;
+ }
+
+ BKE_material_clear_id(bmain, obdata, true);
+ BKE_material_resize_object(bmain, ob, 1, true);
+ BKE_material_resize_id(bmain, obdata, 1, true);
+
+ ob->mat[0] = ma_ob;
+ id_us_plus((ID *)ma_ob);
+ ob->matbits[0] = matbit;
+ (*matarar)[0] = ma_obdata;
+ id_us_plus((ID *)ma_obdata);
+ }
+ else {
+ BKE_material_clear_id(bmain, obdata, true);
+ BKE_material_resize_object(bmain, ob, 0, true);
+ BKE_material_resize_id(bmain, obdata, 0, true);
+ }
+}
+
+static bool mesh_separate_material(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_old, BMesh *bm_old)
+{
+ BMFace *f_cmp, *f;
+ BMIter iter;
+ bool result = false;
+
+ while ((f_cmp = BM_iter_at_index(bm_old, BM_FACES_OF_MESH, NULL, 0))) {
+ Base *base_new;
+ const short mat_nr = f_cmp->mat_nr;
+ int tot = 0;
+
+ BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+
+ BM_ITER_MESH (f, &iter, bm_old, BM_FACES_OF_MESH) {
+ if (f->mat_nr == mat_nr) {
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG);
+ BM_elem_flag_enable(l_iter->e, BM_ELEM_TAG);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ tot++;
+ }
+ }
+
+ /* leave the current object with some materials */
+ if (tot == bm_old->totface) {
+ mesh_separate_material_assign_mat_nr(bmain, base_old->object, mat_nr);
+
+ /* since we're in editmode, must set faces here */
+ BM_ITER_MESH (f, &iter, bm_old, BM_FACES_OF_MESH) {
+ f->mat_nr = 0;
+ }
+ break;
+ }
+
+ /* Move selection into a separate object */
+ base_new = mesh_separate_tagged(bmain, scene, view_layer, base_old, bm_old);
+ if (base_new) {
+ mesh_separate_material_assign_mat_nr(bmain, base_new->object, mat_nr);
+ }
+
+ result |= (base_new != NULL);
+ }
+
+ return result;
+}
+
+static bool mesh_separate_loose(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_old, BMesh *bm_old)
+{
+ int i;
+ BMEdge *e;
+ BMVert *v_seed;
+ BMWalker walker;
+ bool result = false;
+ int max_iter = bm_old->totvert;
+
+ /* Clear all selected vertices */
+ BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+
+ /* A "while (true)" loop should work here as each iteration should
+ * select and remove at least one vertex and when all vertices
+ * are selected the loop will break out. But guard against bad
+ * behavior by limiting iterations to the number of vertices in the
+ * original mesh.*/
+ for (i = 0; i < max_iter; i++) {
+ int tot = 0;
+ /* Get a seed vertex to start the walk */
+ v_seed = BM_iter_at_index(bm_old, BM_VERTS_OF_MESH, NULL, 0);
+
+ /* No vertices available, can't do anything */
+ if (v_seed == NULL) {
+ break;
+ }
+
+ /* Select the seed explicitly, in case it has no edges */
+ if (!BM_elem_flag_test(v_seed, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(v_seed, BM_ELEM_TAG);
+ tot++;
+ }
+
+ /* Walk from the single vertex, selecting everything connected
+ * to it */
+ BMW_init(&walker,
+ bm_old,
+ BMW_VERT_SHELL,
+ BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_NOP,
+ BMW_NIL_LAY);
+
+ for (e = BMW_begin(&walker, v_seed); e; e = BMW_step(&walker)) {
+ if (!BM_elem_flag_test(e->v1, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
+ tot++;
+ }
+ if (!BM_elem_flag_test(e->v2, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
+ tot++;
+ }
+ }
+ BMW_end(&walker);
+
+ if (bm_old->totvert == tot) {
+ /* Every vertex selected, nothing to separate, work is done */
+ break;
+ }
+
+ /* Flush the selection to get edge/face selections matching
+ * the vertex selection */
+ bm_mesh_hflag_flush_vert(bm_old, BM_ELEM_TAG);
+
+ /* Move selection into a separate object */
+ result |= (mesh_separate_tagged(bmain, scene, view_layer, base_old, bm_old) != NULL);
+ }
+
+ return result;
}
static int edbm_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);
- const int type = RNA_enum_get(op->ptr, "type");
- int retval = 0;
-
- if (ED_operator_editmesh(C)) {
- uint bases_len = 0;
- uint empty_selection_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 bs_index = 0; bs_index < bases_len; bs_index++) {
- Base *base = bases[bs_index];
- BMEditMesh *em = BKE_editmesh_from_object(base->object);
-
- if (type == 0) {
- if ((em->bm->totvertsel == 0) &&
- (em->bm->totedgesel == 0) &&
- (em->bm->totfacesel == 0))
- {
- /* when all objects has no selection */
- if (++empty_selection_len == bases_len) {
- BKE_report(op->reports, RPT_ERROR, "Nothing selected");
- }
- continue;
- }
- }
-
- /* editmode separate */
- switch (type) {
- case MESH_SEPARATE_SELECTED:
- retval = mesh_separate_selected(bmain, scene, view_layer, base, em->bm);
- break;
- case MESH_SEPARATE_MATERIAL:
- retval = mesh_separate_material(bmain, scene, view_layer, base, em->bm);
- break;
- case MESH_SEPARATE_LOOSE:
- retval = mesh_separate_loose(bmain, scene, view_layer, base, em->bm);
- break;
- default:
- BLI_assert(0);
- break;
- }
-
- if (retval) {
- EDBM_update_generic(em, true, true);
- }
- }
- MEM_freeN(bases);
- }
- else {
- if (type == MESH_SEPARATE_SELECTED) {
- BKE_report(op->reports, RPT_ERROR, "Selection not supported in object mode");
- return OPERATOR_CANCELLED;
- }
-
- /* object mode separate */
- CTX_DATA_BEGIN(C, Base *, base_iter, selected_editable_bases)
- {
- Object *ob = base_iter->object;
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
- if (!ID_IS_LINKED(me)) {
- BMesh *bm_old = NULL;
- int retval_iter = 0;
-
- bm_old = BM_mesh_create(
- &bm_mesh_allocsize_default,
- &((struct BMeshCreateParams){.use_toolflags = true,}));
-
- BM_mesh_bm_from_me(bm_old, me, (&(struct BMeshFromMeshParams){0}));
-
- switch (type) {
- case MESH_SEPARATE_MATERIAL:
- retval_iter = mesh_separate_material(bmain, scene, view_layer, base_iter, bm_old);
- break;
- case MESH_SEPARATE_LOOSE:
- retval_iter = mesh_separate_loose(bmain, scene, view_layer, base_iter, bm_old);
- break;
- default:
- BLI_assert(0);
- break;
- }
-
- if (retval_iter) {
- BM_mesh_bm_to_me(
- bmain, bm_old, me,
- (&(struct BMeshToMeshParams){
- .calc_object_remap = true,
- }));
-
- DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
- }
-
- BM_mesh_free(bm_old);
-
- retval |= retval_iter;
- }
- }
- }
- CTX_DATA_END;
- }
-
- if (retval) {
- /* delay depsgraph recalc until all objects are duplicated */
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
-
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_CANCELLED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const int type = RNA_enum_get(op->ptr, "type");
+ int retval = 0;
+
+ if (ED_operator_editmesh(C)) {
+ uint bases_len = 0;
+ uint empty_selection_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 bs_index = 0; bs_index < bases_len; bs_index++) {
+ Base *base = bases[bs_index];
+ BMEditMesh *em = BKE_editmesh_from_object(base->object);
+
+ if (type == 0) {
+ if ((em->bm->totvertsel == 0) && (em->bm->totedgesel == 0) && (em->bm->totfacesel == 0)) {
+ /* when all objects has no selection */
+ if (++empty_selection_len == bases_len) {
+ BKE_report(op->reports, RPT_ERROR, "Nothing selected");
+ }
+ continue;
+ }
+ }
+
+ /* editmode separate */
+ switch (type) {
+ case MESH_SEPARATE_SELECTED:
+ retval = mesh_separate_selected(bmain, scene, view_layer, base, em->bm);
+ break;
+ case MESH_SEPARATE_MATERIAL:
+ retval = mesh_separate_material(bmain, scene, view_layer, base, em->bm);
+ break;
+ case MESH_SEPARATE_LOOSE:
+ retval = mesh_separate_loose(bmain, scene, view_layer, base, em->bm);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ if (retval) {
+ EDBM_update_generic(em, true, true);
+ }
+ }
+ MEM_freeN(bases);
+ }
+ else {
+ if (type == MESH_SEPARATE_SELECTED) {
+ BKE_report(op->reports, RPT_ERROR, "Selection not supported in object mode");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* object mode separate */
+ CTX_DATA_BEGIN (C, Base *, base_iter, selected_editable_bases) {
+ Object *ob = base_iter->object;
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ if (!ID_IS_LINKED(me)) {
+ BMesh *bm_old = NULL;
+ int retval_iter = 0;
+
+ bm_old = BM_mesh_create(&bm_mesh_allocsize_default,
+ &((struct BMeshCreateParams){
+ .use_toolflags = true,
+ }));
+
+ BM_mesh_bm_from_me(bm_old, me, (&(struct BMeshFromMeshParams){0}));
+
+ switch (type) {
+ case MESH_SEPARATE_MATERIAL:
+ retval_iter = mesh_separate_material(bmain, scene, view_layer, base_iter, bm_old);
+ break;
+ case MESH_SEPARATE_LOOSE:
+ retval_iter = mesh_separate_loose(bmain, scene, view_layer, base_iter, bm_old);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ if (retval_iter) {
+ BM_mesh_bm_to_me(bmain,
+ bm_old,
+ me,
+ (&(struct BMeshToMeshParams){
+ .calc_object_remap = true,
+ }));
+
+ DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+ }
+
+ BM_mesh_free(bm_old);
+
+ retval |= retval_iter;
+ }
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ if (retval) {
+ /* delay depsgraph recalc until all objects are duplicated */
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
}
void MESH_OT_separate(wmOperatorType *ot)
{
- static const EnumPropertyItem prop_separate_types[] = {
- {MESH_SEPARATE_SELECTED, "SELECTED", 0, "Selection", ""},
- {MESH_SEPARATE_MATERIAL, "MATERIAL", 0, "By Material", ""},
- {MESH_SEPARATE_LOOSE, "LOOSE", 0, "By loose parts", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem prop_separate_types[] = {
+ {MESH_SEPARATE_SELECTED, "SELECTED", 0, "Selection", ""},
+ {MESH_SEPARATE_MATERIAL, "MATERIAL", 0, "By Material", ""},
+ {MESH_SEPARATE_LOOSE, "LOOSE", 0, "By loose parts", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Separate";
- ot->description = "Separate selected geometry into a new mesh";
- ot->idname = "MESH_OT_separate";
+ /* identifiers */
+ ot->name = "Separate";
+ ot->description = "Separate selected geometry into a new mesh";
+ ot->idname = "MESH_OT_separate";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = edbm_separate_exec;
- ot->poll = ED_operator_scene_editable; /* object and editmode */
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = edbm_separate_exec;
+ ot->poll = ED_operator_scene_editable; /* object and editmode */
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "type", prop_separate_types, MESH_SEPARATE_SELECTED, "Type", "");
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", prop_separate_types, MESH_SEPARATE_SELECTED, "Type", "");
}
/** \} */
@@ -4115,81 +4296,80 @@ void MESH_OT_separate(wmOperatorType *ot)
static int edbm_fill_exec(bContext *C, wmOperator *op)
{
- const bool use_beauty = RNA_boolean_get(op->ptr, "use_beauty");
+ const bool use_beauty = RNA_boolean_get(op->ptr, "use_beauty");
- bool has_selected_edges = false, has_faces_filled = false;
+ bool has_selected_edges = false, has_faces_filled = 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 *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- const int totface_orig = em->bm->totface;
+ const int totface_orig = em->bm->totface;
- if (em->bm->totedgesel == 0) {
- continue;
- }
- has_selected_edges = true;
+ if (em->bm->totedgesel == 0) {
+ continue;
+ }
+ has_selected_edges = true;
- BMOperator bmop;
- if (!EDBM_op_init(
- em, &bmop, op,
- "triangle_fill edges=%he use_beauty=%b",
- BM_ELEM_SELECT, use_beauty))
- {
- continue;
- }
+ BMOperator bmop;
+ if (!EDBM_op_init(
+ em, &bmop, op, "triangle_fill edges=%he use_beauty=%b", BM_ELEM_SELECT, use_beauty)) {
+ continue;
+ }
- BMO_op_exec(em->bm, &bmop);
+ BMO_op_exec(em->bm, &bmop);
- /* cancel if nothing was done */
- if (totface_orig == em->bm->totface) {
- EDBM_op_finish(em, &bmop, op, true);
- continue;
- }
- has_faces_filled = true;
+ /* cancel if nothing was done */
+ if (totface_orig == em->bm->totface) {
+ EDBM_op_finish(em, &bmop, op, true);
+ continue;
+ }
+ has_faces_filled = true;
- /* select new geometry */
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_FACE | BM_EDGE, BM_ELEM_SELECT, true);
+ /* select new geometry */
+ BMO_slot_buffer_hflag_enable(
+ em->bm, bmop.slots_out, "geom.out", BM_FACE | BM_EDGE, BM_ELEM_SELECT, true);
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
- if (!has_selected_edges) {
- BKE_report(op->reports, RPT_ERROR, "No edges selected");
- return OPERATOR_CANCELLED;
- }
+ if (!has_selected_edges) {
+ BKE_report(op->reports, RPT_ERROR, "No edges selected");
+ return OPERATOR_CANCELLED;
+ }
- if (!has_faces_filled) {
- BKE_report(op->reports, RPT_WARNING, "No faces filled");
- return OPERATOR_CANCELLED;
- }
+ if (!has_faces_filled) {
+ BKE_report(op->reports, RPT_WARNING, "No faces filled");
+ return OPERATOR_CANCELLED;
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_fill(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Fill";
- ot->idname = "MESH_OT_fill";
- ot->description = "Fill a selected edge loop with faces";
+ /* identifiers */
+ ot->name = "Fill";
+ ot->idname = "MESH_OT_fill";
+ ot->description = "Fill a selected edge loop with faces";
- /* api callbacks */
- ot->exec = edbm_fill_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_fill_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "use_beauty", true, "Beauty", "Use best triangulation division");
+ RNA_def_boolean(ot->srna, "use_beauty", true, "Beauty", "Use best triangulation division");
}
/** \} */
@@ -4200,23 +4380,23 @@ 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_TAG);
}
static float edbm_fill_grid_vert_tag_angle(BMVert *v)
{
- BMIter iter;
- BMEdge *e_iter;
- BMVert *v_pair[2];
- int i = 0;
- BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e_iter, BM_ELEM_TAG)) {
- v_pair[i++] = BM_edge_other_vert(e_iter, v);
- }
- }
- BLI_assert(i == 2);
+ BMIter iter;
+ BMEdge *e_iter;
+ BMVert *v_pair[2];
+ int i = 0;
+ BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e_iter, BM_ELEM_TAG)) {
+ v_pair[i++] = BM_edge_other_vert(e_iter, v);
+ }
+ }
+ BLI_assert(i == 2);
- return fabsf((float)M_PI - angle_v3v3v3(v_pair[0]->co, v->co, v_pair[1]->co));
+ return fabsf((float)M_PI - angle_v3v3v3(v_pair[0]->co, v->co, v_pair[1]->co));
}
/**
@@ -4224,245 +4404,254 @@ static float edbm_fill_grid_vert_tag_angle(BMVert *v)
*/
static void edbm_fill_grid_prepare(BMesh *bm, int offset, int *r_span, 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' */
- const float eps_even = 1e-3f;
- BMEdge *e;
- BMIter iter;
- int count;
- int span = *r_span;
-
- ListBase eloops = {NULL};
- struct BMEdgeLoopStore *el_store;
- // LinkData *el_store;
-
- /* select -> tag */
- 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));
- }
-
- count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_fill_grid_cb, bm);
- el_store = eloops.first;
-
- 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)))) {
- /* pass */
- }
- else {
- /* find the vertex with the best angle (a corner vertex) */
- LinkData *v_link, *v_link_best = NULL;
- float angle_best = -1.0f;
- for (v_link = verts->first; v_link; v_link = v_link->next) {
- const float angle = edbm_fill_grid_vert_tag_angle(v_link->data);
- if ((angle > angle_best) || (v_link_best == NULL)) {
- angle_best = angle;
- v_link_best = v_link;
- }
- }
-
- v_act_link = v_link_best;
- v_act = v_act_link->data;
- }
-
- /* set this vertex first */
- BLI_listbase_rotate_first(verts, v_act_link);
-
- if (offset != 0) {
- v_act_link = BLI_findlink(verts, offset);
- v_act = v_act_link->data;
- BLI_listbase_rotate_first(verts, v_act_link);
- }
-
- BM_edgeloop_edges_get(el_store, edges);
-
-
- if (span_calc) {
- /* calculate the span by finding the next corner in 'verts'
- * we dont know what defines a corner exactly so find the 4 verts
- * in the loop with the greatest angle.
- * Tag them and use the first tagged vertex to calculate the span.
- *
- * note: we may have already checked 'edbm_fill_grid_vert_tag_angle()' on each
- * vert, but advantage of de-duplicating is minimal. */
- struct SortPtrByFloat *ele_sort = MEM_mallocN(sizeof(*ele_sort) * verts_len, __func__);
- LinkData *v_link;
- for (v_link = verts->first, i = 0; v_link; v_link = v_link->next, i++) {
- BMVert *v = v_link->data;
- const float angle = edbm_fill_grid_vert_tag_angle(v);
- ele_sort[i].sort_value = angle;
- ele_sort[i].data = v;
-
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- }
-
- qsort(ele_sort, verts_len, sizeof(*ele_sort), BLI_sortutil_cmp_float_reverse);
-
- /* check that we have at least 3 corners,
- * if the angle on the 3rd angle is roughly the same as the last,
- * then we can't calculate 3+ corners - fallback to the even span. */
- if ((ele_sort[2].sort_value - ele_sort[verts_len - 1].sort_value) > eps_even) {
- for (i = 0; i < 4; i++) {
- BMVert *v = ele_sort[i].data;
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- }
-
- /* now find the first... */
- for (v_link = verts->first, i = 0; i < verts_len / 2; v_link = v_link->next, i++) {
- BMVert *v = v_link->data;
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- if (v != v_act) {
- span = i;
- break;
- }
- }
- }
- }
- MEM_freeN(ele_sort);
- }
- /* end span calc */
-
-
- /* un-flag 'rails' */
- for (i = 0; i < span; i++) {
- 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);
-
- *r_span = span;
+ /* angle differences below this value are considered 'even'
+ * in that they shouldn't be used to calculate corners used for the 'span' */
+ const float eps_even = 1e-3f;
+ BMEdge *e;
+ BMIter iter;
+ int count;
+ int span = *r_span;
+
+ ListBase eloops = {NULL};
+ struct BMEdgeLoopStore *el_store;
+ // LinkData *el_store;
+
+ /* select -> tag */
+ 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));
+ }
+
+ count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_fill_grid_cb, bm);
+ el_store = eloops.first;
+
+ 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)))) {
+ /* pass */
+ }
+ else {
+ /* find the vertex with the best angle (a corner vertex) */
+ LinkData *v_link, *v_link_best = NULL;
+ float angle_best = -1.0f;
+ for (v_link = verts->first; v_link; v_link = v_link->next) {
+ const float angle = edbm_fill_grid_vert_tag_angle(v_link->data);
+ if ((angle > angle_best) || (v_link_best == NULL)) {
+ angle_best = angle;
+ v_link_best = v_link;
+ }
+ }
+
+ v_act_link = v_link_best;
+ v_act = v_act_link->data;
+ }
+
+ /* set this vertex first */
+ BLI_listbase_rotate_first(verts, v_act_link);
+
+ if (offset != 0) {
+ v_act_link = BLI_findlink(verts, offset);
+ v_act = v_act_link->data;
+ BLI_listbase_rotate_first(verts, v_act_link);
+ }
+
+ BM_edgeloop_edges_get(el_store, edges);
+
+ if (span_calc) {
+ /* calculate the span by finding the next corner in 'verts'
+ * we dont know what defines a corner exactly so find the 4 verts
+ * in the loop with the greatest angle.
+ * Tag them and use the first tagged vertex to calculate the span.
+ *
+ * note: we may have already checked 'edbm_fill_grid_vert_tag_angle()' on each
+ * vert, but advantage of de-duplicating is minimal. */
+ struct SortPtrByFloat *ele_sort = MEM_mallocN(sizeof(*ele_sort) * verts_len, __func__);
+ LinkData *v_link;
+ for (v_link = verts->first, i = 0; v_link; v_link = v_link->next, i++) {
+ BMVert *v = v_link->data;
+ const float angle = edbm_fill_grid_vert_tag_angle(v);
+ ele_sort[i].sort_value = angle;
+ ele_sort[i].data = v;
+
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ }
+
+ qsort(ele_sort, verts_len, sizeof(*ele_sort), BLI_sortutil_cmp_float_reverse);
+
+ /* check that we have at least 3 corners,
+ * if the angle on the 3rd angle is roughly the same as the last,
+ * then we can't calculate 3+ corners - fallback to the even span. */
+ if ((ele_sort[2].sort_value - ele_sort[verts_len - 1].sort_value) > eps_even) {
+ for (i = 0; i < 4; i++) {
+ BMVert *v = ele_sort[i].data;
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ }
+
+ /* now find the first... */
+ for (v_link = verts->first, i = 0; i < verts_len / 2; v_link = v_link->next, i++) {
+ BMVert *v = v_link->data;
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ if (v != v_act) {
+ span = i;
+ break;
+ }
+ }
+ }
+ }
+ MEM_freeN(ele_sort);
+ }
+ /* end span calc */
+
+ /* un-flag 'rails' */
+ for (i = 0; i < span; i++) {
+ 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);
+
+ *r_span = span;
}
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);
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- 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;
-
- if (em->bm->totedgesel == 0) {
- continue;
- }
-
- if (use_prepare) {
- /* use when we have a single loop selected */
- PropertyRNA *prop_span = RNA_struct_find_property(op->ptr, "span");
- PropertyRNA *prop_offset = RNA_struct_find_property(op->ptr, "offset");
- bool calc_span;
-
- const int clamp = em->bm->totvertsel;
- int span;
- int offset;
-
- /* Only reuse on redo because these settings need to match the current selection.
- * We never want to use them on other geometry, repeat last for eg, see: T60777. */
- if ((op->flag & OP_IS_REPEAT) &&
- 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;
- 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);
-
- RNA_property_int_set(op->ptr, prop_span, span);
- }
- /* end tricky prepare code */
-
- BMOperator bmop;
- if (!EDBM_op_init(
- em, &bmop, op,
- "grid_fill edges=%he mat_nr=%i use_smooth=%b use_interp_simple=%b",
- use_prepare ? BM_ELEM_TAG : BM_ELEM_SELECT,
- em->mat_nr, use_smooth, use_interp_simple))
- {
- continue;
- }
-
- BMO_op_exec(em->bm, &bmop);
-
- /* NOTE: EDBM_op_finish() will change bmesh pointer inside of edit mesh,
- * so need to tell evaluated objects to sync new bmesh pointer to their
- * edit mesh structures.
- */
- DEG_id_tag_update(&obedit->id, 0);
-
- /* cancel if nothing was done */
- if ((totedge_orig == em->bm->totedge) &&
- (totface_orig == em->bm->totface))
- {
- EDBM_op_finish(em, &bmop, op, true);
- continue;
- }
-
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
-
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
-
- EDBM_update_generic(em, true, true);
- }
-
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ 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);
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ 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;
+
+ if (em->bm->totedgesel == 0) {
+ continue;
+ }
+
+ if (use_prepare) {
+ /* use when we have a single loop selected */
+ PropertyRNA *prop_span = RNA_struct_find_property(op->ptr, "span");
+ PropertyRNA *prop_offset = RNA_struct_find_property(op->ptr, "offset");
+ bool calc_span;
+
+ const int clamp = em->bm->totvertsel;
+ int span;
+ int offset;
+
+ /* Only reuse on redo because these settings need to match the current selection.
+ * We never want to use them on other geometry, repeat last for eg, see: T60777. */
+ if ((op->flag & OP_IS_REPEAT) && 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;
+ 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);
+
+ RNA_property_int_set(op->ptr, prop_span, span);
+ }
+ /* end tricky prepare code */
+
+ BMOperator bmop;
+ if (!EDBM_op_init(em,
+ &bmop,
+ op,
+ "grid_fill edges=%he mat_nr=%i use_smooth=%b use_interp_simple=%b",
+ use_prepare ? BM_ELEM_TAG : BM_ELEM_SELECT,
+ em->mat_nr,
+ use_smooth,
+ use_interp_simple)) {
+ continue;
+ }
+
+ BMO_op_exec(em->bm, &bmop);
+
+ /* NOTE: EDBM_op_finish() will change bmesh pointer inside of edit mesh,
+ * so need to tell evaluated objects to sync new bmesh pointer to their
+ * edit mesh structures.
+ */
+ DEG_id_tag_update(&obedit->id, 0);
+
+ /* cancel if nothing was done */
+ if ((totedge_orig == em->bm->totedge) && (totface_orig == em->bm->totface)) {
+ EDBM_op_finish(em, &bmop, op, true);
+ continue;
+ }
+
+ BMO_slot_buffer_hflag_enable(
+ em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
+
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
+
+ EDBM_update_generic(em, true, true);
+ }
+
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_fill_grid(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Grid Fill";
- ot->description = "Fill grid from two loops";
- ot->idname = "MESH_OT_fill_grid";
-
- /* api callbacks */
- ot->exec = edbm_fill_grid_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_int(ot->srna, "span", 1, 1, 1000, "Span", "Number of grid columns", 1, 100);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_int(ot->srna, "offset", 0, -1000, 1000, "Offset",
- "Vertex that is the corner of the grid", -100, 100);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- RNA_def_boolean(ot->srna, "use_interp_simple", false, "Simple Blending",
- "Use simple interpolation of grid vertices");
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Grid Fill";
+ ot->description = "Fill grid from two loops";
+ ot->idname = "MESH_OT_fill_grid";
+
+ /* api callbacks */
+ ot->exec = edbm_fill_grid_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_int(ot->srna, "span", 1, 1, 1000, "Span", "Number of grid columns", 1, 100);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_int(ot->srna,
+ "offset",
+ 0,
+ -1000,
+ 1000,
+ "Offset",
+ "Vertex that is the corner of the grid",
+ -100,
+ 100);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_boolean(ot->srna,
+ "use_interp_simple",
+ false,
+ "Simple Blending",
+ "Use simple interpolation of grid vertices");
}
/** \} */
@@ -4473,53 +4662,56 @@ void MESH_OT_fill_grid(wmOperatorType *ot)
static int edbm_fill_holes_exec(bContext *C, wmOperator *op)
{
- const int sides = RNA_int_get(op->ptr, "sides");
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
+ const int sides = RNA_int_get(op->ptr, "sides");
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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);
- if (em->bm->totedgesel == 0) {
- continue;
- }
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (!EDBM_op_call_and_selectf(
- em, op,
- "faces.out", true,
- "holes_fill edges=%he sides=%i",
- BM_ELEM_SELECT, sides))
- {
- continue;
- }
+ if (em->bm->totedgesel == 0) {
+ continue;
+ }
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
+ if (!EDBM_op_call_and_selectf(
+ em, op, "faces.out", true, "holes_fill edges=%he sides=%i", BM_ELEM_SELECT, sides)) {
+ continue;
+ }
- return OPERATOR_FINISHED;
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_fill_holes(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Fill Holes";
- ot->idname = "MESH_OT_fill_holes";
- ot->description = "Fill in holes (boundary edge loops)";
+ /* identifiers */
+ ot->name = "Fill Holes";
+ ot->idname = "MESH_OT_fill_holes";
+ ot->description = "Fill in holes (boundary edge loops)";
- /* api callbacks */
- ot->exec = edbm_fill_holes_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_fill_holes_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_int(ot->srna, "sides", 4, 0, 1000,
- "Sides", "Number of sides in hole required to fill (zero fills all holes)", 0, 100);
+ RNA_def_int(ot->srna,
+ "sides",
+ 4,
+ 0,
+ 1000,
+ "Sides",
+ "Number of sides in hole required to fill (zero fills all holes)",
+ 0,
+ 100);
}
/** \} */
@@ -4530,75 +4722,85 @@ void MESH_OT_fill_holes(wmOperatorType *ot)
static int edbm_beautify_fill_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
-
- const float angle_max = M_PI;
- const float angle_limit = RNA_float_get(op->ptr, "angle_limit");
- char hflag;
-
- 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->totfacesel == 0) {
- continue;
- }
-
- if (angle_limit >= angle_max) {
- hflag = BM_ELEM_SELECT;
- }
- else {
- BMIter iter;
- BMEdge *e;
-
- 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) &&
- BM_edge_calc_face_angle_ex(e, angle_max) < angle_limit));
-
- }
- hflag = BM_ELEM_TAG;
- }
-
- if (!EDBM_op_call_and_selectf(
- em, op, "geom.out", true,
- "beautify_fill faces=%hf edges=%he",
- BM_ELEM_SELECT, hflag))
- {
- continue;
- }
-
- EDBM_update_generic(em, true, true);
- }
-
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ const float angle_max = M_PI;
+ const float angle_limit = RNA_float_get(op->ptr, "angle_limit");
+ char hflag;
+
+ 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->totfacesel == 0) {
+ continue;
+ }
+
+ if (angle_limit >= angle_max) {
+ hflag = BM_ELEM_SELECT;
+ }
+ else {
+ BMIter iter;
+ BMEdge *e;
+
+ 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) &&
+ BM_edge_calc_face_angle_ex(e, angle_max) < angle_limit));
+ }
+ hflag = BM_ELEM_TAG;
+ }
+
+ if (!EDBM_op_call_and_selectf(em,
+ op,
+ "geom.out",
+ true,
+ "beautify_fill faces=%hf edges=%he",
+ BM_ELEM_SELECT,
+ hflag)) {
+ continue;
+ }
+
+ EDBM_update_generic(em, true, true);
+ }
+
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_beautify_fill(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Beautify Faces";
- ot->idname = "MESH_OT_beautify_fill";
- ot->description = "Rearrange some faces to try to get less degenerated geometry";
+ /* identifiers */
+ ot->name = "Beautify Faces";
+ ot->idname = "MESH_OT_beautify_fill";
+ ot->description = "Rearrange some faces to try to get less degenerated geometry";
- /* api callbacks */
- ot->exec = edbm_beautify_fill_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_beautify_fill_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- prop = RNA_def_float_rotation(ot->srna, "angle_limit", 0, NULL, 0.0f, DEG2RADF(180.0f),
- "Max Angle", "Angle limit", 0.0f, DEG2RADF(180.0f));
- RNA_def_property_float_default(prop, DEG2RADF(180.0f));
+ /* props */
+ prop = RNA_def_float_rotation(ot->srna,
+ "angle_limit",
+ 0,
+ NULL,
+ 0.0f,
+ DEG2RADF(180.0f),
+ "Max Angle",
+ "Angle limit",
+ 0.0f,
+ DEG2RADF(180.0f));
+ RNA_def_property_float_default(prop, DEG2RADF(180.0f));
}
/** \} */
@@ -4609,71 +4811,91 @@ void MESH_OT_beautify_fill(wmOperatorType *ot)
static int edbm_poke_face_exec(bContext *C, wmOperator *op)
{
- const float offset = RNA_float_get(op->ptr, "offset");
- const bool use_relative_offset = RNA_boolean_get(op->ptr, "use_relative_offset");
- const int center_mode = RNA_enum_get(op->ptr, "center_mode");
+ const float offset = RNA_float_get(op->ptr, "offset");
+ const bool use_relative_offset = RNA_boolean_get(op->ptr, "use_relative_offset");
+ const int center_mode = RNA_enum_get(op->ptr, "center_mode");
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totfacesel == 0) {
- continue;
- }
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
- BMOperator bmop;
- EDBM_op_init(em, &bmop, op, "poke faces=%hf offset=%f use_relative_offset=%b center_mode=%i",
- BM_ELEM_SELECT, offset, use_relative_offset, center_mode);
- BMO_op_exec(em->bm, &bmop);
+ BMOperator bmop;
+ EDBM_op_init(em,
+ &bmop,
+ op,
+ "poke faces=%hf offset=%f use_relative_offset=%b center_mode=%i",
+ BM_ELEM_SELECT,
+ offset,
+ use_relative_offset,
+ center_mode);
+ BMO_op_exec(em->bm, &bmop);
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, true);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
+ BMO_slot_buffer_hflag_enable(
+ em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, true);
+ BMO_slot_buffer_hflag_enable(
+ em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
- EDBM_mesh_normals_update(em);
+ EDBM_mesh_normals_update(em);
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_poke(wmOperatorType *ot)
{
- static const EnumPropertyItem poke_center_modes[] = {
- {BMOP_POKE_MEDIAN_WEIGHTED, "MEDIAN_WEIGHTED", 0, "Weighted Median", "Weighted median face center"},
- {BMOP_POKE_MEDIAN, "MEDIAN", 0, "Median", "Median face center"},
- {BMOP_POKE_BOUNDS, "BOUNDS", 0, "Bounds", "Face bounds center"},
- {0, NULL, 0, NULL, NULL},
- };
-
-
- /* identifiers */
- ot->name = "Poke Faces";
- ot->idname = "MESH_OT_poke";
- ot->description = "Split a face into a fan";
-
- /* api callbacks */
- ot->exec = edbm_poke_face_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_float_distance(ot->srna, "offset", 0.0f, -1e3f, 1e3f, "Poke Offset", "Poke Offset", -1.0f, 1.0f);
- RNA_def_boolean(ot->srna, "use_relative_offset", false, "Offset Relative", "Scale the offset by surrounding geometry");
- RNA_def_enum(ot->srna, "center_mode", poke_center_modes, BMOP_POKE_MEDIAN_WEIGHTED,
- "Poke Center", "Poke Face Center Calculation");
+ static const EnumPropertyItem poke_center_modes[] = {
+ {BMOP_POKE_MEDIAN_WEIGHTED,
+ "MEDIAN_WEIGHTED",
+ 0,
+ "Weighted Median",
+ "Weighted median face center"},
+ {BMOP_POKE_MEDIAN, "MEDIAN", 0, "Median", "Median face center"},
+ {BMOP_POKE_BOUNDS, "BOUNDS", 0, "Bounds", "Face bounds center"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Poke Faces";
+ ot->idname = "MESH_OT_poke";
+ ot->description = "Split a face into a fan";
+
+ /* api callbacks */
+ ot->exec = edbm_poke_face_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_float_distance(
+ ot->srna, "offset", 0.0f, -1e3f, 1e3f, "Poke Offset", "Poke Offset", -1.0f, 1.0f);
+ RNA_def_boolean(ot->srna,
+ "use_relative_offset",
+ false,
+ "Offset Relative",
+ "Scale the offset by surrounding geometry");
+ RNA_def_enum(ot->srna,
+ "center_mode",
+ poke_center_modes,
+ BMOP_POKE_MEDIAN_WEIGHTED,
+ "Poke Center",
+ "Poke Face Center Calculation");
}
/** \} */
@@ -4684,71 +4906,83 @@ void MESH_OT_poke(wmOperatorType *ot)
static int edbm_quads_convert_to_tris_exec(bContext *C, wmOperator *op)
{
- const int quad_method = RNA_enum_get(op->ptr, "quad_method");
- const int ngon_method = RNA_enum_get(op->ptr, "ngon_method");
- ViewLayer *view_layer = CTX_data_view_layer(C);
+ const int quad_method = RNA_enum_get(op->ptr, "quad_method");
+ const int ngon_method = RNA_enum_get(op->ptr, "ngon_method");
+ 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totfacesel == 0) {
- continue;
- }
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
- BMOperator bmop;
- BMOIter oiter;
- BMFace *f;
+ BMOperator bmop;
+ BMOIter oiter;
+ BMFace *f;
- EDBM_op_init(
- em, &bmop, op,
- "triangulate faces=%hf quad_method=%i ngon_method=%i",
- BM_ELEM_SELECT, quad_method, ngon_method);
- BMO_op_exec(em->bm, &bmop);
+ EDBM_op_init(em,
+ &bmop,
+ op,
+ "triangulate faces=%hf quad_method=%i ngon_method=%i",
+ BM_ELEM_SELECT,
+ quad_method,
+ ngon_method);
+ BMO_op_exec(em->bm, &bmop);
- /* select the output */
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
+ /* select the output */
+ BMO_slot_buffer_hflag_enable(
+ em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
- /* remove the doubles */
- BMO_ITER (f, &oiter, bmop.slots_out, "face_map_double.out", BM_FACE) {
- BM_face_kill(em->bm, f);
- }
+ /* remove the doubles */
+ BMO_ITER (f, &oiter, bmop.slots_out, "face_map_double.out", BM_FACE) {
+ BM_face_kill(em->bm, f);
+ }
- EDBM_selectmode_flush(em);
+ EDBM_selectmode_flush(em);
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
- EDBM_update_generic(em, true, true);
- }
+ EDBM_update_generic(em, true, true);
+ }
- MEM_freeN(objects);
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
void MESH_OT_quads_convert_to_tris(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Triangulate Faces";
- ot->idname = "MESH_OT_quads_convert_to_tris";
- ot->description = "Triangulate selected faces";
+ /* identifiers */
+ ot->name = "Triangulate Faces";
+ ot->idname = "MESH_OT_quads_convert_to_tris";
+ ot->description = "Triangulate selected faces";
- /* api callbacks */
- ot->exec = edbm_quads_convert_to_tris_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_quads_convert_to_tris_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_enum(ot->srna, "quad_method", rna_enum_modifier_triangulate_quad_method_items, MOD_TRIANGULATE_QUAD_BEAUTY,
- "Quad Method", "Method for splitting the quads into triangles");
- RNA_def_enum(ot->srna, "ngon_method", rna_enum_modifier_triangulate_ngon_method_items, MOD_TRIANGULATE_NGON_BEAUTY,
- "Polygon Method", "Method for splitting the polygons into triangles");
+ RNA_def_enum(ot->srna,
+ "quad_method",
+ rna_enum_modifier_triangulate_quad_method_items,
+ MOD_TRIANGULATE_QUAD_BEAUTY,
+ "Quad Method",
+ "Method for splitting the quads into triangles");
+ RNA_def_enum(ot->srna,
+ "ngon_method",
+ rna_enum_modifier_triangulate_ngon_method_items,
+ MOD_TRIANGULATE_NGON_BEAUTY,
+ "Polygon Method",
+ "Method for splitting the polygons into triangles");
}
/** \} */
@@ -4759,109 +4993,127 @@ void MESH_OT_quads_convert_to_tris(wmOperatorType *ot)
static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op)
{
- 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);
-
- bool is_face_pair;
-
- {
- int totelem_sel[3];
- EDBM_mesh_stats_multi(objects, objects_len, NULL, totelem_sel);
- is_face_pair = (totelem_sel[2] == 2);
- }
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
-
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- bool do_seam, do_sharp, do_uvs, do_vcols, do_materials;
- float angle_face_threshold, angle_shape_threshold;
- PropertyRNA *prop;
-
- /* When joining exactly 2 faces, no limit.
- * this is useful for one off joins while editing. */
- prop = RNA_struct_find_property(op->ptr, "face_threshold");
- if (is_face_pair &&
- (RNA_property_is_set(op->ptr, prop) == false))
- {
- angle_face_threshold = DEG2RADF(180.0f);
- }
- else {
- angle_face_threshold = RNA_property_float_get(op->ptr, prop);
- }
-
- prop = RNA_struct_find_property(op->ptr, "shape_threshold");
- if (is_face_pair &&
- (RNA_property_is_set(op->ptr, prop) == false))
- {
- angle_shape_threshold = DEG2RADF(180.0f);
- }
- else {
- angle_shape_threshold = RNA_property_float_get(op->ptr, prop);
- }
-
- do_seam = RNA_boolean_get(op->ptr, "seam");
- do_sharp = RNA_boolean_get(op->ptr, "sharp");
- do_uvs = RNA_boolean_get(op->ptr, "uvs");
- do_vcols = RNA_boolean_get(op->ptr, "vcols");
- do_materials = RNA_boolean_get(op->ptr, "materials");
-
- if (!EDBM_op_call_and_selectf(
- em, op,
- "faces.out", true,
- "join_triangles faces=%hf angle_face_threshold=%f angle_shape_threshold=%f "
- "cmp_seam=%b cmp_sharp=%b cmp_uvs=%b cmp_vcols=%b cmp_materials=%b",
- BM_ELEM_SELECT, angle_face_threshold, angle_shape_threshold,
- do_seam, do_sharp, do_uvs, do_vcols, do_materials))
- {
- continue;
- }
-
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ 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);
+
+ bool is_face_pair;
+
+ {
+ int totelem_sel[3];
+ EDBM_mesh_stats_multi(objects, objects_len, NULL, totelem_sel);
+ is_face_pair = (totelem_sel[2] == 2);
+ }
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ bool do_seam, do_sharp, do_uvs, do_vcols, do_materials;
+ float angle_face_threshold, angle_shape_threshold;
+ PropertyRNA *prop;
+
+ /* When joining exactly 2 faces, no limit.
+ * this is useful for one off joins while editing. */
+ prop = RNA_struct_find_property(op->ptr, "face_threshold");
+ if (is_face_pair && (RNA_property_is_set(op->ptr, prop) == false)) {
+ angle_face_threshold = DEG2RADF(180.0f);
+ }
+ else {
+ angle_face_threshold = RNA_property_float_get(op->ptr, prop);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "shape_threshold");
+ if (is_face_pair && (RNA_property_is_set(op->ptr, prop) == false)) {
+ angle_shape_threshold = DEG2RADF(180.0f);
+ }
+ else {
+ angle_shape_threshold = RNA_property_float_get(op->ptr, prop);
+ }
+
+ do_seam = RNA_boolean_get(op->ptr, "seam");
+ do_sharp = RNA_boolean_get(op->ptr, "sharp");
+ do_uvs = RNA_boolean_get(op->ptr, "uvs");
+ do_vcols = RNA_boolean_get(op->ptr, "vcols");
+ do_materials = RNA_boolean_get(op->ptr, "materials");
+
+ if (!EDBM_op_call_and_selectf(
+ em,
+ op,
+ "faces.out",
+ true,
+ "join_triangles faces=%hf angle_face_threshold=%f angle_shape_threshold=%f "
+ "cmp_seam=%b cmp_sharp=%b cmp_uvs=%b cmp_vcols=%b cmp_materials=%b",
+ BM_ELEM_SELECT,
+ angle_face_threshold,
+ angle_shape_threshold,
+ do_seam,
+ do_sharp,
+ do_uvs,
+ do_vcols,
+ do_materials)) {
+ continue;
+ }
+
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
static void join_triangle_props(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- prop = RNA_def_float_rotation(
- ot->srna, "face_threshold", 0, NULL, 0.0f, DEG2RADF(180.0f),
- "Max Face Angle", "Face angle limit", 0.0f, DEG2RADF(180.0f));
- RNA_def_property_float_default(prop, DEG2RADF(40.0f));
-
- prop = RNA_def_float_rotation(
- ot->srna, "shape_threshold", 0, NULL, 0.0f, DEG2RADF(180.0f),
- "Max Shape Angle", "Shape angle limit", 0.0f, DEG2RADF(180.0f));
- RNA_def_property_float_default(prop, DEG2RADF(40.0f));
-
- RNA_def_boolean(ot->srna, "uvs", false, "Compare UVs", "");
- RNA_def_boolean(ot->srna, "vcols", false, "Compare VCols", "");
- RNA_def_boolean(ot->srna, "seam", false, "Compare Seam", "");
- RNA_def_boolean(ot->srna, "sharp", false, "Compare Sharp", "");
- RNA_def_boolean(ot->srna, "materials", false, "Compare Materials", "");
+ PropertyRNA *prop;
+
+ prop = RNA_def_float_rotation(ot->srna,
+ "face_threshold",
+ 0,
+ NULL,
+ 0.0f,
+ DEG2RADF(180.0f),
+ "Max Face Angle",
+ "Face angle limit",
+ 0.0f,
+ DEG2RADF(180.0f));
+ RNA_def_property_float_default(prop, DEG2RADF(40.0f));
+
+ prop = RNA_def_float_rotation(ot->srna,
+ "shape_threshold",
+ 0,
+ NULL,
+ 0.0f,
+ DEG2RADF(180.0f),
+ "Max Shape Angle",
+ "Shape angle limit",
+ 0.0f,
+ DEG2RADF(180.0f));
+ RNA_def_property_float_default(prop, DEG2RADF(40.0f));
+
+ RNA_def_boolean(ot->srna, "uvs", false, "Compare UVs", "");
+ RNA_def_boolean(ot->srna, "vcols", false, "Compare VCols", "");
+ RNA_def_boolean(ot->srna, "seam", false, "Compare Seam", "");
+ RNA_def_boolean(ot->srna, "sharp", false, "Compare Sharp", "");
+ RNA_def_boolean(ot->srna, "materials", false, "Compare Materials", "");
}
void MESH_OT_tris_convert_to_quads(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Tris to Quads";
- ot->idname = "MESH_OT_tris_convert_to_quads";
- ot->description = "Join triangles into quads";
+ /* identifiers */
+ ot->name = "Tris to Quads";
+ ot->idname = "MESH_OT_tris_convert_to_quads";
+ ot->description = "Join triangles into quads";
- /* api callbacks */
- ot->exec = edbm_tris_convert_to_quads_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_tris_convert_to_quads_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- join_triangle_props(ot);
+ join_triangle_props(ot);
}
/** \} */
@@ -4877,187 +5129,192 @@ void MESH_OT_tris_convert_to_quads(wmOperatorType *ot)
static int edbm_decimate_exec(bContext *C, wmOperator *op)
{
- const float ratio = RNA_float_get(op->ptr, "ratio");
- bool use_vertex_group = RNA_boolean_get(op->ptr, "use_vertex_group");
- const float vertex_group_factor = RNA_float_get(op->ptr, "vertex_group_factor");
- const bool invert_vertex_group = RNA_boolean_get(op->ptr, "invert_vertex_group");
- const bool use_symmetry = RNA_boolean_get(op->ptr, "use_symmetry");
- const float symmetry_eps = 0.00002f;
- const int symmetry_axis = use_symmetry ? RNA_enum_get(op->ptr, "symmetry_axis") : -1;
-
- /* nop */
- if (ratio == 1.0f) {
- return OPERATOR_FINISHED;
- }
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- if (bm->totedgesel == 0) {
- continue;
- }
-
- float *vweights = MEM_mallocN(sizeof(*vweights) * bm->totvert, __func__);
- {
- const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
- const int defbase_act = obedit->actdef - 1;
-
- if (use_vertex_group && (cd_dvert_offset == -1)) {
- BKE_report(op->reports, RPT_WARNING, "No active vertex group");
- use_vertex_group = false;
- }
-
- BMIter iter;
- BMVert *v;
- int i;
- BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
- float weight = 0.0f;
- 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);
- if (invert_vertex_group) {
- weight = 1.0f - weight;
- }
- }
- else {
- weight = 1.0f;
- }
- }
-
- vweights[i] = weight;
- BM_elem_index_set(v, i); /* set_inline */
- }
- bm->elem_index_dirty &= ~BM_VERT;
- }
-
- float ratio_adjust;
-
- if ((bm->totface == bm->totfacesel) || (ratio == 0.0f)) {
- ratio_adjust = ratio;
- }
- else {
- /**
- * Calculate a new ratio based on faces that could be removed during decimation.
- * needed so 0..1 has a meaningful range when operating on the selection.
- *
- * This doesn't have to be totally accurate,
- * but needs to be greater than the number of selected faces
- */
-
- int totface_basis = 0;
- int totface_adjacent = 0;
- BMIter iter;
- BMFace *f;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- /* count faces during decimation, ngons are triangulated */
- const int f_len = f->len > 4 ? (f->len - 2) : 1;
- totface_basis += f_len;
-
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (vweights[BM_elem_index_get(l_iter->v)] != 0.0f) {
- totface_adjacent += f_len;
- break;
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- ratio_adjust = ratio;
- ratio_adjust = 1.0f - ratio_adjust;
- ratio_adjust *= (float)totface_adjacent / (float)totface_basis;
- ratio_adjust = 1.0f - ratio_adjust;
- }
-
- BM_mesh_decimate_collapse(
- em->bm, ratio_adjust, vweights, vertex_group_factor, false,
- symmetry_axis, symmetry_eps);
-
- MEM_freeN(vweights);
-
- {
- short selectmode = em->selectmode;
- if ((selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) == 0) {
- /* ensure we flush edges -> faces */
- selectmode |= SCE_SELECT_EDGE;
- }
- EDBM_selectmode_flush_ex(em, selectmode);
- }
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ const float ratio = RNA_float_get(op->ptr, "ratio");
+ bool use_vertex_group = RNA_boolean_get(op->ptr, "use_vertex_group");
+ const float vertex_group_factor = RNA_float_get(op->ptr, "vertex_group_factor");
+ const bool invert_vertex_group = RNA_boolean_get(op->ptr, "invert_vertex_group");
+ const bool use_symmetry = RNA_boolean_get(op->ptr, "use_symmetry");
+ const float symmetry_eps = 0.00002f;
+ const int symmetry_axis = use_symmetry ? RNA_enum_get(op->ptr, "symmetry_axis") : -1;
+
+ /* nop */
+ if (ratio == 1.0f) {
+ return OPERATOR_FINISHED;
+ }
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ if (bm->totedgesel == 0) {
+ continue;
+ }
+
+ float *vweights = MEM_mallocN(sizeof(*vweights) * bm->totvert, __func__);
+ {
+ const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
+ const int defbase_act = obedit->actdef - 1;
+
+ if (use_vertex_group && (cd_dvert_offset == -1)) {
+ BKE_report(op->reports, RPT_WARNING, "No active vertex group");
+ use_vertex_group = false;
+ }
+
+ BMIter iter;
+ BMVert *v;
+ int i;
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ float weight = 0.0f;
+ 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);
+ if (invert_vertex_group) {
+ weight = 1.0f - weight;
+ }
+ }
+ else {
+ weight = 1.0f;
+ }
+ }
+
+ vweights[i] = weight;
+ BM_elem_index_set(v, i); /* set_inline */
+ }
+ bm->elem_index_dirty &= ~BM_VERT;
+ }
+
+ float ratio_adjust;
+
+ if ((bm->totface == bm->totfacesel) || (ratio == 0.0f)) {
+ ratio_adjust = ratio;
+ }
+ else {
+ /**
+ * Calculate a new ratio based on faces that could be removed during decimation.
+ * needed so 0..1 has a meaningful range when operating on the selection.
+ *
+ * This doesn't have to be totally accurate,
+ * but needs to be greater than the number of selected faces
+ */
+
+ int totface_basis = 0;
+ int totface_adjacent = 0;
+ BMIter iter;
+ BMFace *f;
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ /* count faces during decimation, ngons are triangulated */
+ const int f_len = f->len > 4 ? (f->len - 2) : 1;
+ totface_basis += f_len;
+
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (vweights[BM_elem_index_get(l_iter->v)] != 0.0f) {
+ totface_adjacent += f_len;
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ ratio_adjust = ratio;
+ ratio_adjust = 1.0f - ratio_adjust;
+ ratio_adjust *= (float)totface_adjacent / (float)totface_basis;
+ ratio_adjust = 1.0f - ratio_adjust;
+ }
+
+ BM_mesh_decimate_collapse(
+ em->bm, ratio_adjust, vweights, vertex_group_factor, false, symmetry_axis, symmetry_eps);
+
+ MEM_freeN(vweights);
+
+ {
+ short selectmode = em->selectmode;
+ if ((selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) == 0) {
+ /* ensure we flush edges -> faces */
+ selectmode |= SCE_SELECT_EDGE;
+ }
+ EDBM_selectmode_flush_ex(em, selectmode);
+ }
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
-
static bool edbm_decimate_check(bContext *UNUSED(C), wmOperator *UNUSED(op))
{
- return true;
+ return true;
}
-
static void edbm_decimate_ui(bContext *UNUSED(C), wmOperator *op)
{
- uiLayout *layout = op->layout, *box, *row, *col;
- PointerRNA ptr;
+ uiLayout *layout = op->layout, *box, *row, *col;
+ PointerRNA ptr;
- RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
- uiItemR(layout, &ptr, "ratio", 0, NULL, ICON_NONE);
+ uiItemR(layout, &ptr, "ratio", 0, NULL, ICON_NONE);
- box = uiLayoutBox(layout);
- uiItemR(box, &ptr, "use_vertex_group", 0, NULL, ICON_NONE);
- col = uiLayoutColumn(box, false);
- uiLayoutSetActive(col, RNA_boolean_get(&ptr, "use_vertex_group"));
- uiItemR(col, &ptr, "vertex_group_factor", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "invert_vertex_group", 0, NULL, ICON_NONE);
+ box = uiLayoutBox(layout);
+ uiItemR(box, &ptr, "use_vertex_group", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(box, false);
+ uiLayoutSetActive(col, RNA_boolean_get(&ptr, "use_vertex_group"));
+ uiItemR(col, &ptr, "vertex_group_factor", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "invert_vertex_group", 0, NULL, ICON_NONE);
- box = uiLayoutBox(layout);
- uiItemR(box, &ptr, "use_symmetry", 0, NULL, ICON_NONE);
- row = uiLayoutRow(box, true);
- uiLayoutSetActive(row, RNA_boolean_get(&ptr, "use_symmetry"));
- uiItemR(row, &ptr, "symmetry_axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ box = uiLayoutBox(layout);
+ uiItemR(box, &ptr, "use_symmetry", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, true);
+ uiLayoutSetActive(row, RNA_boolean_get(&ptr, "use_symmetry"));
+ uiItemR(row, &ptr, "symmetry_axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
}
-
void MESH_OT_decimate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Decimate Geometry";
- ot->idname = "MESH_OT_decimate";
- ot->description = "Simplify geometry by collapsing edges";
-
- /* api callbacks */
- ot->exec = edbm_decimate_exec;
- ot->check = edbm_decimate_check;
- ot->ui = edbm_decimate_ui;
- ot->poll = ED_operator_editmesh;
-
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* Note, keep in sync with 'rna_def_modifier_decimate' */
- RNA_def_float(ot->srna, "ratio", 1.0f, 0.0f, 1.0f, "Ratio", "", 0.0f, 1.0f);
-
- RNA_def_boolean(ot->srna, "use_vertex_group", false, "Vertex Group",
- "Use active vertex group as an influence");
- RNA_def_float(ot->srna, "vertex_group_factor", 1.0f, 0.0f, 1000.0f, "Weight",
- "Vertex group strength", 0.0f, 10.0f);
- RNA_def_boolean(ot->srna, "invert_vertex_group", false, "Invert",
- "Invert vertex group influence");
-
- RNA_def_boolean(ot->srna, "use_symmetry", false, "Symmetry",
- "Maintain symmetry on an axis");
-
- RNA_def_enum(ot->srna, "symmetry_axis", rna_enum_axis_xyz_items, 1, "Axis", "Axis of symmetry");
+ /* identifiers */
+ ot->name = "Decimate Geometry";
+ ot->idname = "MESH_OT_decimate";
+ ot->description = "Simplify geometry by collapsing edges";
+
+ /* api callbacks */
+ ot->exec = edbm_decimate_exec;
+ ot->check = edbm_decimate_check;
+ ot->ui = edbm_decimate_ui;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* Note, keep in sync with 'rna_def_modifier_decimate' */
+ RNA_def_float(ot->srna, "ratio", 1.0f, 0.0f, 1.0f, "Ratio", "", 0.0f, 1.0f);
+
+ RNA_def_boolean(ot->srna,
+ "use_vertex_group",
+ false,
+ "Vertex Group",
+ "Use active vertex group as an influence");
+ RNA_def_float(ot->srna,
+ "vertex_group_factor",
+ 1.0f,
+ 0.0f,
+ 1000.0f,
+ "Weight",
+ "Vertex group strength",
+ 0.0f,
+ 10.0f);
+ RNA_def_boolean(
+ ot->srna, "invert_vertex_group", false, "Invert", "Invert vertex group influence");
+
+ RNA_def_boolean(ot->srna, "use_symmetry", false, "Symmetry", "Maintain symmetry on an axis");
+
+ RNA_def_enum(ot->srna, "symmetry_axis", rna_enum_axis_xyz_items, 1, "Axis", "Axis of symmetry");
}
/** \} */
@@ -5068,73 +5325,81 @@ void MESH_OT_decimate(wmOperatorType *ot)
static void edbm_dissolve_prop__use_verts(wmOperatorType *ot, bool value, int flag)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- prop = RNA_def_boolean(ot->srna, "use_verts", value, "Dissolve Verts",
- "Dissolve remaining vertices");
+ prop = RNA_def_boolean(
+ ot->srna, "use_verts", value, "Dissolve Verts", "Dissolve remaining vertices");
- if (flag) {
- RNA_def_property_flag(prop, flag);
- }
+ if (flag) {
+ RNA_def_property_flag(prop, flag);
+ }
}
static void edbm_dissolve_prop__use_face_split(wmOperatorType *ot)
{
- RNA_def_boolean(ot->srna, "use_face_split", false, "Face Split",
- "Split off face corners to maintain surrounding geometry");
+ RNA_def_boolean(ot->srna,
+ "use_face_split",
+ false,
+ "Face Split",
+ "Split off face corners to maintain surrounding geometry");
}
static void edbm_dissolve_prop__use_boundary_tear(wmOperatorType *ot)
{
- RNA_def_boolean(ot->srna, "use_boundary_tear", false, "Tear Boundary",
- "Split off face corners instead of merging faces");
+ RNA_def_boolean(ot->srna,
+ "use_boundary_tear",
+ false,
+ "Tear Boundary",
+ "Split off face corners instead of merging faces");
}
static int edbm_dissolve_verts_exec(bContext *C, wmOperator *op)
{
- const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split");
- const bool use_boundary_tear = RNA_boolean_get(op->ptr, "use_boundary_tear");
+ const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split");
+ const bool use_boundary_tear = RNA_boolean_get(op->ptr, "use_boundary_tear");
- 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);
+ 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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->totvertsel == 0) {
- continue;
- }
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
- if (!EDBM_op_callf(
- em, op,
- "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
- BM_ELEM_SELECT, use_face_split, use_boundary_tear))
- {
- continue;
- }
- EDBM_update_generic(em, true, true);
- }
+ if (!EDBM_op_callf(em,
+ op,
+ "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
+ BM_ELEM_SELECT,
+ use_face_split,
+ use_boundary_tear)) {
+ continue;
+ }
+ EDBM_update_generic(em, true, true);
+ }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_dissolve_verts(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Dissolve Vertices";
- ot->description = "Dissolve verts, merge edges and faces";
- ot->idname = "MESH_OT_dissolve_verts";
+ /* identifiers */
+ ot->name = "Dissolve Vertices";
+ ot->description = "Dissolve verts, merge edges and faces";
+ ot->idname = "MESH_OT_dissolve_verts";
- /* api callbacks */
- ot->exec = edbm_dissolve_verts_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_dissolve_verts_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- edbm_dissolve_prop__use_face_split(ot);
- edbm_dissolve_prop__use_boundary_tear(ot);
+ edbm_dissolve_prop__use_face_split(ot);
+ edbm_dissolve_prop__use_boundary_tear(ot);
}
/** \} */
@@ -5145,52 +5410,54 @@ void MESH_OT_dissolve_verts(wmOperatorType *ot)
static int edbm_dissolve_edges_exec(bContext *C, wmOperator *op)
{
- const bool use_verts = RNA_boolean_get(op->ptr, "use_verts");
- const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split");
+ const bool use_verts = RNA_boolean_get(op->ptr, "use_verts");
+ const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split");
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totedgesel == 0) {
- continue;
- }
+ if (em->bm->totedgesel == 0) {
+ continue;
+ }
- if (!EDBM_op_callf(
- em, op,
- "dissolve_edges edges=%he use_verts=%b use_face_split=%b",
- BM_ELEM_SELECT, use_verts, use_face_split))
- {
- continue;
- }
+ if (!EDBM_op_callf(em,
+ op,
+ "dissolve_edges edges=%he use_verts=%b use_face_split=%b",
+ BM_ELEM_SELECT,
+ use_verts,
+ use_face_split)) {
+ continue;
+ }
- EDBM_update_generic(em, true, true);
- }
+ EDBM_update_generic(em, true, true);
+ }
- MEM_freeN(objects);
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_dissolve_edges(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Dissolve Edges";
- ot->description = "Dissolve edges, merging faces";
- ot->idname = "MESH_OT_dissolve_edges";
+ /* identifiers */
+ ot->name = "Dissolve Edges";
+ ot->description = "Dissolve edges, merging faces";
+ ot->idname = "MESH_OT_dissolve_edges";
- /* api callbacks */
- ot->exec = edbm_dissolve_edges_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_dissolve_edges_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- edbm_dissolve_prop__use_verts(ot, true, 0);
- edbm_dissolve_prop__use_face_split(ot);
+ edbm_dissolve_prop__use_verts(ot, true, 0);
+ edbm_dissolve_prop__use_face_split(ot);
}
/** \} */
@@ -5201,49 +5468,51 @@ void MESH_OT_dissolve_edges(wmOperatorType *ot)
static int edbm_dissolve_faces_exec(bContext *C, wmOperator *op)
{
- const bool use_verts = RNA_boolean_get(op->ptr, "use_verts");
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ const bool use_verts = RNA_boolean_get(op->ptr, "use_verts");
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totfacesel == 0) {
- continue;
- }
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
- if (!EDBM_op_call_and_selectf(
- em, op,
- "region.out", true,
- "dissolve_faces faces=%hf use_verts=%b",
- BM_ELEM_SELECT, use_verts))
- {
- continue;
- }
+ if (!EDBM_op_call_and_selectf(em,
+ op,
+ "region.out",
+ true,
+ "dissolve_faces faces=%hf use_verts=%b",
+ BM_ELEM_SELECT,
+ use_verts)) {
+ continue;
+ }
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_dissolve_faces(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Dissolve Faces";
- ot->description = "Dissolve faces";
- ot->idname = "MESH_OT_dissolve_faces";
+ /* identifiers */
+ ot->name = "Dissolve Faces";
+ ot->description = "Dissolve faces";
+ ot->idname = "MESH_OT_dissolve_faces";
- /* api callbacks */
- ot->exec = edbm_dissolve_faces_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_dissolve_faces_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- edbm_dissolve_prop__use_verts(ot, false, 0);
+ edbm_dissolve_prop__use_verts(ot, false, 0);
}
/** \} */
@@ -5254,46 +5523,46 @@ void MESH_OT_dissolve_faces(wmOperatorType *ot)
static int edbm_dissolve_mode_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- PropertyRNA *prop;
-
- prop = RNA_struct_find_property(op->ptr, "use_verts");
- if (!RNA_property_is_set(op->ptr, prop)) {
- /* always enable in edge-mode */
- if ((em->selectmode & SCE_SELECT_FACE) == 0) {
- RNA_property_boolean_set(op->ptr, prop, true);
- }
- }
-
- if (em->selectmode & SCE_SELECT_VERTEX) {
- return edbm_dissolve_verts_exec(C, op);
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- return edbm_dissolve_edges_exec(C, op);
- }
- else {
- return edbm_dissolve_faces_exec(C, op);
- }
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ PropertyRNA *prop;
+
+ prop = RNA_struct_find_property(op->ptr, "use_verts");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ /* always enable in edge-mode */
+ if ((em->selectmode & SCE_SELECT_FACE) == 0) {
+ RNA_property_boolean_set(op->ptr, prop, true);
+ }
+ }
+
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ return edbm_dissolve_verts_exec(C, op);
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ return edbm_dissolve_edges_exec(C, op);
+ }
+ else {
+ return edbm_dissolve_faces_exec(C, op);
+ }
}
void MESH_OT_dissolve_mode(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Dissolve Selection";
- ot->description = "Dissolve geometry based on the selection mode";
- ot->idname = "MESH_OT_dissolve_mode";
+ /* identifiers */
+ ot->name = "Dissolve Selection";
+ ot->description = "Dissolve geometry based on the selection mode";
+ ot->idname = "MESH_OT_dissolve_mode";
- /* api callbacks */
- ot->exec = edbm_dissolve_mode_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_dissolve_mode_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- edbm_dissolve_prop__use_verts(ot, false, PROP_SKIP_SAVE);
- edbm_dissolve_prop__use_face_split(ot);
- edbm_dissolve_prop__use_boundary_tear(ot);
+ edbm_dissolve_prop__use_verts(ot, false, PROP_SKIP_SAVE);
+ edbm_dissolve_prop__use_face_split(ot);
+ edbm_dissolve_prop__use_boundary_tear(ot);
}
/** \} */
@@ -5304,92 +5573,113 @@ void MESH_OT_dissolve_mode(wmOperatorType *ot)
static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op)
{
- const float angle_limit = RNA_float_get(op->ptr, "angle_limit");
- const bool use_dissolve_boundaries = RNA_boolean_get(op->ptr, "use_dissolve_boundaries");
- const int delimit = RNA_enum_get(op->ptr, "delimit");
- char dissolve_flag;
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- if ((bm->totvertsel == 0) &&
- (bm->totedgesel == 0) &&
- (bm->totfacesel == 0))
- {
- continue;
- }
-
- if (em->selectmode == SCE_SELECT_FACE) {
- /* flush selection to tags and untag edges/verts with partially selected faces */
- BMIter iter;
- BMIter liter;
-
- BMElem *ele;
- BMFace *f;
- BMLoop *l;
-
- BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_set(ele, BM_ELEM_TAG, BM_elem_flag_test(ele, BM_ELEM_SELECT));
- }
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_set(ele, BM_ELEM_TAG, BM_elem_flag_test(ele, BM_ELEM_SELECT));
- }
-
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- BM_elem_flag_disable(l->v, BM_ELEM_TAG);
- BM_elem_flag_disable(l->e, BM_ELEM_TAG);
- }
- }
- }
-
- dissolve_flag = BM_ELEM_TAG;
- }
- else {
- dissolve_flag = BM_ELEM_SELECT;
- }
-
- EDBM_op_call_and_selectf(
- em, op, "region.out", true,
- "dissolve_limit edges=%he verts=%hv angle_limit=%f use_dissolve_boundaries=%b delimit=%i",
- dissolve_flag, dissolve_flag, angle_limit, use_dissolve_boundaries, delimit);
-
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ const float angle_limit = RNA_float_get(op->ptr, "angle_limit");
+ const bool use_dissolve_boundaries = RNA_boolean_get(op->ptr, "use_dissolve_boundaries");
+ const int delimit = RNA_enum_get(op->ptr, "delimit");
+ char dissolve_flag;
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ if ((bm->totvertsel == 0) && (bm->totedgesel == 0) && (bm->totfacesel == 0)) {
+ continue;
+ }
+
+ if (em->selectmode == SCE_SELECT_FACE) {
+ /* flush selection to tags and untag edges/verts with partially selected faces */
+ BMIter iter;
+ BMIter liter;
+
+ BMElem *ele;
+ BMFace *f;
+ BMLoop *l;
+
+ BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_set(ele, BM_ELEM_TAG, BM_elem_flag_test(ele, BM_ELEM_SELECT));
+ }
+ BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_set(ele, BM_ELEM_TAG, BM_elem_flag_test(ele, BM_ELEM_SELECT));
+ }
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ BM_elem_flag_disable(l->v, BM_ELEM_TAG);
+ BM_elem_flag_disable(l->e, BM_ELEM_TAG);
+ }
+ }
+ }
+
+ dissolve_flag = BM_ELEM_TAG;
+ }
+ else {
+ dissolve_flag = BM_ELEM_SELECT;
+ }
+
+ EDBM_op_call_and_selectf(
+ em,
+ op,
+ "region.out",
+ true,
+ "dissolve_limit edges=%he verts=%hv angle_limit=%f use_dissolve_boundaries=%b delimit=%i",
+ dissolve_flag,
+ dissolve_flag,
+ angle_limit,
+ use_dissolve_boundaries,
+ delimit);
+
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_dissolve_limited(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Limited Dissolve";
- ot->idname = "MESH_OT_dissolve_limited";
- ot->description = "Dissolve selected edges and verts, limited by the angle of surrounding geometry";
-
- /* api callbacks */
- ot->exec = edbm_dissolve_limited_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- prop = RNA_def_float_rotation(ot->srna, "angle_limit", 0, NULL, 0.0f, DEG2RADF(180.0f),
- "Max Angle", "Angle limit", 0.0f, DEG2RADF(180.0f));
- RNA_def_property_float_default(prop, DEG2RADF(5.0f));
- RNA_def_boolean(ot->srna, "use_dissolve_boundaries", false, "All Boundaries",
- "Dissolve all vertices inbetween face boundaries");
- RNA_def_enum_flag(ot->srna, "delimit", rna_enum_mesh_delimit_mode_items, BMO_DELIM_NORMAL, "Delimit",
- "Delimit dissolve operation");
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Limited Dissolve";
+ ot->idname = "MESH_OT_dissolve_limited";
+ ot->description =
+ "Dissolve selected edges and verts, limited by the angle of surrounding geometry";
+
+ /* api callbacks */
+ ot->exec = edbm_dissolve_limited_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_float_rotation(ot->srna,
+ "angle_limit",
+ 0,
+ NULL,
+ 0.0f,
+ DEG2RADF(180.0f),
+ "Max Angle",
+ "Angle limit",
+ 0.0f,
+ DEG2RADF(180.0f));
+ RNA_def_property_float_default(prop, DEG2RADF(5.0f));
+ RNA_def_boolean(ot->srna,
+ "use_dissolve_boundaries",
+ false,
+ "All Boundaries",
+ "Dissolve all vertices inbetween face boundaries");
+ RNA_def_enum_flag(ot->srna,
+ "delimit",
+ rna_enum_mesh_delimit_mode_items,
+ BMO_DELIM_NORMAL,
+ "Delimit",
+ "Delimit dissolve operation");
}
/** \} */
@@ -5400,69 +5690,73 @@ void MESH_OT_dissolve_limited(wmOperatorType *ot)
static int edbm_dissolve_degenerate_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- int totelem_old[3] = {0, 0, 0};
- int totelem_new[3] = {0, 0, 0};
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ int totelem_old[3] = {0, 0, 0};
+ int totelem_new[3] = {0, 0, 0};
- 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);
+ 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- totelem_old[0] += bm->totvert;
- totelem_old[1] += bm->totedge;
- totelem_old[2] += bm->totface;
- } /* objects */
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ totelem_old[0] += bm->totvert;
+ totelem_old[1] += bm->totedge;
+ totelem_old[2] += bm->totface;
+ } /* objects */
- const float thresh = RNA_float_get(op->ptr, "threshold");
+ const float thresh = RNA_float_get(op->ptr, "threshold");
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
- if (!EDBM_op_callf(
- em, op,
- "dissolve_degenerate edges=%he dist=%f",
- BM_ELEM_SELECT, thresh))
- {
- return OPERATOR_CANCELLED;
- }
+ if (!EDBM_op_callf(em, op, "dissolve_degenerate edges=%he dist=%f", BM_ELEM_SELECT, thresh)) {
+ return OPERATOR_CANCELLED;
+ }
- /* tricky to maintain correct selection here, so just flush up from verts */
- EDBM_select_flush(em);
+ /* tricky to maintain correct selection here, so just flush up from verts */
+ EDBM_select_flush(em);
- EDBM_update_generic(em, true, true);
+ EDBM_update_generic(em, true, true);
- totelem_new[0] += bm->totvert;
- totelem_new[1] += bm->totedge;
- totelem_new[2] += bm->totface;
- }
- MEM_freeN(objects);
+ totelem_new[0] += bm->totvert;
+ totelem_new[1] += bm->totedge;
+ totelem_new[2] += bm->totface;
+ }
+ MEM_freeN(objects);
- edbm_report_delete_info(op->reports, totelem_old, totelem_new);
+ edbm_report_delete_info(op->reports, totelem_old, totelem_new);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_dissolve_degenerate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Degenerate Dissolve";
- ot->idname = "MESH_OT_dissolve_degenerate";
- ot->description = "Dissolve zero area faces and zero length edges";
+ /* identifiers */
+ ot->name = "Degenerate Dissolve";
+ ot->idname = "MESH_OT_dissolve_degenerate";
+ ot->description = "Dissolve zero area faces and zero length edges";
- /* api callbacks */
- ot->exec = edbm_dissolve_degenerate_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_dissolve_degenerate_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_float_distance(ot->srna, "threshold", 1e-4f, 1e-6f, 50.0f, "Merge Distance",
- "Minimum distance between elements to merge", 1e-5f, 10.0f);
+ RNA_def_float_distance(ot->srna,
+ "threshold",
+ 1e-4f,
+ 1e-6f,
+ 50.0f,
+ "Merge Distance",
+ "Minimum distance between elements to merge",
+ 1e-5f,
+ 10.0f);
}
/** \} */
@@ -5474,71 +5768,76 @@ void MESH_OT_dissolve_degenerate(wmOperatorType *ot)
/* internally uses dissolve */
static int edbm_delete_edgeloop_exec(bContext *C, wmOperator *op)
{
- const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split");
- ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split");
+ 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totedgesel == 0) {
- continue;
- }
+ if (em->bm->totedgesel == 0) {
+ continue;
+ }
- /* deal with selection */
- {
- BMEdge *e;
- BMIter iter;
+ /* deal with selection */
+ {
+ BMEdge *e;
+ BMIter iter;
- BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT) && e->l) {
- BMLoop *l_iter = e->l;
- do {
- BM_elem_flag_enable(l_iter->f, BM_ELEM_TAG);
- } while ((l_iter = l_iter->radial_next) != e->l);
- }
- }
- }
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT) && e->l) {
+ BMLoop *l_iter = e->l;
+ do {
+ BM_elem_flag_enable(l_iter->f, BM_ELEM_TAG);
+ } while ((l_iter = l_iter->radial_next) != e->l);
+ }
+ }
+ }
- if (!EDBM_op_callf(
- em, op,
- "dissolve_edges edges=%he use_verts=%b use_face_split=%b",
- BM_ELEM_SELECT, true, use_face_split))
- {
- continue;
- }
+ if (!EDBM_op_callf(em,
+ op,
+ "dissolve_edges edges=%he use_verts=%b use_face_split=%b",
+ BM_ELEM_SELECT,
+ true,
+ use_face_split)) {
+ continue;
+ }
- BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG);
+ BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG);
- EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX);
+ EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX);
- EDBM_update_generic(em, true, true);
- }
+ EDBM_update_generic(em, true, true);
+ }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_delete_edgeloop(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Edge Loop";
- ot->description = "Delete an edge loop by merging the faces on each side";
- ot->idname = "MESH_OT_delete_edgeloop";
+ /* identifiers */
+ ot->name = "Delete Edge Loop";
+ ot->description = "Delete an edge loop by merging the faces on each side";
+ ot->idname = "MESH_OT_delete_edgeloop";
- /* api callbacks */
- ot->exec = edbm_delete_edgeloop_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_delete_edgeloop_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "use_face_split", true, "Face Split",
- "Split off face corners to maintain surrounding geometry");
+ RNA_def_boolean(ot->srna,
+ "use_face_split",
+ true,
+ "Face Split",
+ "Split off face corners to maintain surrounding geometry");
}
/** \} */
@@ -5549,51 +5848,50 @@ void MESH_OT_delete_edgeloop(wmOperatorType *ot)
static int edbm_split_exec(bContext *C, wmOperator *op)
{
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if ((em->bm->totvertsel == 0) &&
- (em->bm->totedgesel == 0) &&
- (em->bm->totfacesel == 0))
- {
- continue;
- }
- BMOperator bmop;
- EDBM_op_init(em, &bmop, op, "split geom=%hvef use_only_faces=%b", BM_ELEM_SELECT, false);
- BMO_op_exec(em->bm, &bmop);
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
-
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
-
- /* Geometry has changed, need to recalc normals and looptris */
- EDBM_mesh_normals_update(em);
-
- EDBM_update_generic(em, true, true);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ if ((em->bm->totvertsel == 0) && (em->bm->totedgesel == 0) && (em->bm->totfacesel == 0)) {
+ continue;
+ }
+ BMOperator bmop;
+ EDBM_op_init(em, &bmop, op, "split geom=%hvef use_only_faces=%b", BM_ELEM_SELECT, false);
+ BMO_op_exec(em->bm, &bmop);
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
+ BMO_slot_buffer_hflag_enable(
+ em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
+
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
+
+ /* Geometry has changed, need to recalc normals and looptris */
+ EDBM_mesh_normals_update(em);
+
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_split(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Split";
- ot->idname = "MESH_OT_split";
- ot->description = "Split off selected geometry from connected unselected geometry";
+ /* identifiers */
+ ot->name = "Split";
+ ot->idname = "MESH_OT_split";
+ ot->description = "Split off selected geometry from connected unselected geometry";
- /* api callbacks */
- ot->exec = edbm_split_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_split_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -5606,603 +5904,631 @@ void MESH_OT_split(wmOperatorType *ot)
* \{ */
enum {
- SRT_VIEW_ZAXIS = 1, /* Use view Z (deep) axis. */
- SRT_VIEW_XAXIS, /* Use view X (left to right) axis. */
- SRT_CURSOR_DISTANCE, /* Use distance from element to 3D cursor. */
- SRT_MATERIAL, /* Face only: use mat number. */
- SRT_SELECTED, /* Move selected elements in first, without modifying
- * relative order of selected and unselected elements. */
- SRT_RANDOMIZE, /* Randomize selected elements. */
- SRT_REVERSE, /* Reverse current order of selected elements. */
+ SRT_VIEW_ZAXIS = 1, /* Use view Z (deep) axis. */
+ SRT_VIEW_XAXIS, /* Use view X (left to right) axis. */
+ SRT_CURSOR_DISTANCE, /* Use distance from element to 3D cursor. */
+ SRT_MATERIAL, /* Face only: use mat number. */
+ SRT_SELECTED, /* Move selected elements in first, without modifying
+ * relative order of selected and unselected elements. */
+ SRT_RANDOMIZE, /* Randomize selected elements. */
+ SRT_REVERSE, /* Reverse current order of selected elements. */
};
typedef struct BMElemSort {
- float srt; /* Sort factor */
- int org_idx; /* Original index of this element _in its mempool_ */
+ float srt; /* Sort factor */
+ int org_idx; /* Original index of this element _in its mempool_ */
} BMElemSort;
static int bmelemsort_comp(const void *v1, const void *v2)
{
- const BMElemSort *x1 = v1, *x2 = v2;
+ const BMElemSort *x1 = v1, *x2 = v2;
- return (x1->srt > x2->srt) - (x1->srt < x2->srt);
+ return (x1->srt > x2->srt) - (x1->srt < x2->srt);
}
/* Reorders vertices/edges/faces using a given methods. Loops are not supported. */
-static void sort_bmelem_flag(
- bContext *C,
- Scene *scene, Object *ob,
- RegionView3D *rv3d,
- const int types, const int flag, const int action,
- const int reverse, const unsigned int seed)
-{
- BMEditMesh *em = BKE_editmesh_from_object(ob);
-
- BMVert *ve;
- BMEdge *ed;
- BMFace *fa;
- BMIter iter;
-
- /* In all five elements below, 0 = vertices, 1 = edges, 2 = faces. */
- /* 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;
- int totelem[3] = {0, 0, 0};
- int affected[3] = {0, 0, 0};
- int i, j;
-
- if (!(types && flag && action))
- return;
-
- if (types & BM_VERT)
- totelem[0] = em->bm->totvert;
- if (types & BM_EDGE)
- totelem[1] = em->bm->totedge;
- if (types & BM_FACE)
- totelem[2] = em->bm->totface;
-
- if (ELEM(action, SRT_VIEW_ZAXIS, SRT_VIEW_XAXIS)) {
- float mat[4][4];
- float fact = reverse ? -1.0 : 1.0;
- int coidx = (action == SRT_VIEW_ZAXIS) ? 2 : 0;
-
- /* Apply the view matrix to the object matrix. */
- mul_m4_m4m4(mat, rv3d->viewmat, ob->obmat);
-
- if (totelem[0]) {
- pb = pblock[0] = MEM_callocN(sizeof(char) * totelem[0], "sort_bmelem vert pblock");
- sb = sblock[0] = MEM_callocN(sizeof(BMElemSort) * totelem[0], "sort_bmelem vert sblock");
-
- BM_ITER_MESH_INDEX (ve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(ve, flag)) {
- float co[3];
- mul_v3_m4v3(co, mat, ve->co);
-
- pb[i] = false;
- sb[affected[0]].org_idx = i;
- sb[affected[0]++].srt = co[coidx] * fact;
- }
- else {
- pb[i] = true;
- }
- }
- }
-
- if (totelem[1]) {
- pb = pblock[1] = MEM_callocN(sizeof(char) * totelem[1], "sort_bmelem edge pblock");
- sb = sblock[1] = MEM_callocN(sizeof(BMElemSort) * totelem[1], "sort_bmelem edge sblock");
-
- BM_ITER_MESH_INDEX (ed, &iter, em->bm, BM_EDGES_OF_MESH, i) {
- if (BM_elem_flag_test(ed, flag)) {
- float co[3];
- mid_v3_v3v3(co, ed->v1->co, ed->v2->co);
- mul_m4_v3(mat, co);
-
- pb[i] = false;
- sb[affected[1]].org_idx = i;
- sb[affected[1]++].srt = co[coidx] * fact;
- }
- else {
- pb[i] = true;
- }
- }
- }
-
- if (totelem[2]) {
- pb = pblock[2] = MEM_callocN(sizeof(char) * totelem[2], "sort_bmelem face pblock");
- sb = sblock[2] = MEM_callocN(sizeof(BMElemSort) * totelem[2], "sort_bmelem face sblock");
-
- BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) {
- if (BM_elem_flag_test(fa, flag)) {
- float co[3];
- BM_face_calc_center_median(fa, co);
- mul_m4_v3(mat, co);
-
- pb[i] = false;
- sb[affected[2]].org_idx = i;
- sb[affected[2]++].srt = co[coidx] * fact;
- }
- else {
- pb[i] = true;
- }
- }
- }
- }
-
- else if (action == SRT_CURSOR_DISTANCE) {
- float cur[3];
- float mat[4][4];
- float fact = reverse ? -1.0 : 1.0;
-
- copy_v3_v3(cur, scene->cursor.location);
-
- invert_m4_m4(mat, ob->obmat);
- mul_m4_v3(mat, cur);
-
- if (totelem[0]) {
- pb = pblock[0] = MEM_callocN(sizeof(char) * totelem[0], "sort_bmelem vert pblock");
- sb = sblock[0] = MEM_callocN(sizeof(BMElemSort) * totelem[0], "sort_bmelem vert sblock");
-
- BM_ITER_MESH_INDEX (ve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(ve, flag)) {
- pb[i] = false;
- sb[affected[0]].org_idx = i;
- sb[affected[0]++].srt = len_squared_v3v3(cur, ve->co) * fact;
- }
- else {
- pb[i] = true;
- }
- }
- }
-
- if (totelem[1]) {
- pb = pblock[1] = MEM_callocN(sizeof(char) * totelem[1], "sort_bmelem edge pblock");
- sb = sblock[1] = MEM_callocN(sizeof(BMElemSort) * totelem[1], "sort_bmelem edge sblock");
-
- BM_ITER_MESH_INDEX (ed, &iter, em->bm, BM_EDGES_OF_MESH, i) {
- if (BM_elem_flag_test(ed, flag)) {
- float co[3];
- mid_v3_v3v3(co, ed->v1->co, ed->v2->co);
-
- pb[i] = false;
- sb[affected[1]].org_idx = i;
- sb[affected[1]++].srt = len_squared_v3v3(cur, co) * fact;
- }
- else {
- pb[i] = true;
- }
- }
- }
-
- if (totelem[2]) {
- pb = pblock[2] = MEM_callocN(sizeof(char) * totelem[2], "sort_bmelem face pblock");
- sb = sblock[2] = MEM_callocN(sizeof(BMElemSort) * totelem[2], "sort_bmelem face sblock");
-
- BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) {
- if (BM_elem_flag_test(fa, flag)) {
- float co[3];
- BM_face_calc_center_median(fa, co);
-
- pb[i] = false;
- sb[affected[2]].org_idx = i;
- sb[affected[2]++].srt = len_squared_v3v3(cur, co) * fact;
- }
- else {
- pb[i] = true;
- }
- }
- }
- }
-
- /* Faces only! */
- else if (action == SRT_MATERIAL && totelem[2]) {
- pb = pblock[2] = MEM_callocN(sizeof(char) * totelem[2], "sort_bmelem face pblock");
- sb = sblock[2] = MEM_callocN(sizeof(BMElemSort) * totelem[2], "sort_bmelem face sblock");
-
- BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) {
- if (BM_elem_flag_test(fa, flag)) {
- /* Reverse materials' order, not order of faces inside each mat! */
- /* Note: cannot use totcol, as mat_nr may sometimes be greater... */
- float srt = reverse ? (float)(MAXMAT - fa->mat_nr) : (float)fa->mat_nr;
- pb[i] = false;
- sb[affected[2]].org_idx = i;
- /* Multiplying with totface and adding i ensures us
- * we keep current order for all faces of same mat. */
- sb[affected[2]++].srt = srt * ((float)totelem[2]) + ((float)i);
- // printf("e: %d; srt: %f; final: %f\n",
- // i, srt, srt * ((float)totface) + ((float)i));
- }
- else {
- pb[i] = true;
- }
- }
- }
-
- else if (action == SRT_SELECTED) {
- unsigned int *tbuf[3] = {NULL, NULL, NULL}, *tb;
-
- if (totelem[0]) {
- tb = tbuf[0] = MEM_callocN(sizeof(int) * totelem[0], "sort_bmelem vert tbuf");
- mp = map[0] = MEM_callocN(sizeof(int) * totelem[0], "sort_bmelem vert map");
-
- BM_ITER_MESH_INDEX (ve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(ve, flag)) {
- mp[affected[0]++] = i;
- }
- else {
- *tb = i;
- tb++;
- }
- }
- }
-
- if (totelem[1]) {
- tb = tbuf[1] = MEM_callocN(sizeof(int) * totelem[1], "sort_bmelem edge tbuf");
- mp = map[1] = MEM_callocN(sizeof(int) * totelem[1], "sort_bmelem edge map");
-
- BM_ITER_MESH_INDEX (ed, &iter, em->bm, BM_EDGES_OF_MESH, i) {
- if (BM_elem_flag_test(ed, flag)) {
- mp[affected[1]++] = i;
- }
- else {
- *tb = i;
- tb++;
- }
- }
- }
-
- if (totelem[2]) {
- tb = tbuf[2] = MEM_callocN(sizeof(int) * totelem[2], "sort_bmelem face tbuf");
- mp = map[2] = MEM_callocN(sizeof(int) * totelem[2], "sort_bmelem face map");
-
- BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) {
- if (BM_elem_flag_test(fa, flag)) {
- mp[affected[2]++] = i;
- }
- else {
- *tb = i;
- tb++;
- }
- }
- }
-
- for (j = 3; j--; ) {
- int tot = totelem[j];
- int aff = affected[j];
- tb = tbuf[j];
- mp = map[j];
- if (!(tb && mp))
- continue;
- if (ELEM(aff, 0, tot)) {
- MEM_freeN(tb);
- MEM_freeN(mp);
- map[j] = NULL;
- continue;
- }
- if (reverse) {
- memcpy(tb + (tot - aff), mp, aff * sizeof(int));
- }
- else {
- memcpy(mp + aff, tb, (tot - aff) * sizeof(int));
- tb = mp;
- mp = map[j] = tbuf[j];
- tbuf[j] = tb;
- }
-
- /* Reverse mapping, we want an org2new one! */
- for (i = tot, tb = tbuf[j] + tot - 1; i--; tb--) {
- mp[*tb] = i;
- }
- MEM_freeN(tbuf[j]);
- }
- }
-
- else if (action == SRT_RANDOMIZE) {
- if (totelem[0]) {
- /* Re-init random generator for each element type, to get consistent random when
- * enabling/disabling an element type. */
- RNG *rng = BLI_rng_new_srandom(seed);
- pb = pblock[0] = MEM_callocN(sizeof(char) * totelem[0], "sort_bmelem vert pblock");
- sb = sblock[0] = MEM_callocN(sizeof(BMElemSort) * totelem[0], "sort_bmelem vert sblock");
-
- BM_ITER_MESH_INDEX (ve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(ve, flag)) {
- pb[i] = false;
- sb[affected[0]].org_idx = i;
- sb[affected[0]++].srt = BLI_rng_get_float(rng);
- }
- else {
- pb[i] = true;
- }
- }
-
- BLI_rng_free(rng);
- }
-
- if (totelem[1]) {
- RNG *rng = BLI_rng_new_srandom(seed);
- pb = pblock[1] = MEM_callocN(sizeof(char) * totelem[1], "sort_bmelem edge pblock");
- sb = sblock[1] = MEM_callocN(sizeof(BMElemSort) * totelem[1], "sort_bmelem edge sblock");
-
- BM_ITER_MESH_INDEX (ed, &iter, em->bm, BM_EDGES_OF_MESH, i) {
- if (BM_elem_flag_test(ed, flag)) {
- pb[i] = false;
- sb[affected[1]].org_idx = i;
- sb[affected[1]++].srt = BLI_rng_get_float(rng);
- }
- else {
- pb[i] = true;
- }
- }
-
- BLI_rng_free(rng);
- }
-
- if (totelem[2]) {
- RNG *rng = BLI_rng_new_srandom(seed);
- pb = pblock[2] = MEM_callocN(sizeof(char) * totelem[2], "sort_bmelem face pblock");
- sb = sblock[2] = MEM_callocN(sizeof(BMElemSort) * totelem[2], "sort_bmelem face sblock");
-
- BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) {
- if (BM_elem_flag_test(fa, flag)) {
- pb[i] = false;
- sb[affected[2]].org_idx = i;
- sb[affected[2]++].srt = BLI_rng_get_float(rng);
- }
- else {
- pb[i] = true;
- }
- }
-
- BLI_rng_free(rng);
- }
- }
-
- else if (action == SRT_REVERSE) {
- if (totelem[0]) {
- pb = pblock[0] = MEM_callocN(sizeof(char) * totelem[0], "sort_bmelem vert pblock");
- sb = sblock[0] = MEM_callocN(sizeof(BMElemSort) * totelem[0], "sort_bmelem vert sblock");
-
- BM_ITER_MESH_INDEX (ve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(ve, flag)) {
- pb[i] = false;
- sb[affected[0]].org_idx = i;
- sb[affected[0]++].srt = (float)-i;
- }
- else {
- pb[i] = true;
- }
- }
- }
-
- if (totelem[1]) {
- pb = pblock[1] = MEM_callocN(sizeof(char) * totelem[1], "sort_bmelem edge pblock");
- sb = sblock[1] = MEM_callocN(sizeof(BMElemSort) * totelem[1], "sort_bmelem edge sblock");
-
- BM_ITER_MESH_INDEX (ed, &iter, em->bm, BM_EDGES_OF_MESH, i) {
- if (BM_elem_flag_test(ed, flag)) {
- pb[i] = false;
- sb[affected[1]].org_idx = i;
- sb[affected[1]++].srt = (float)-i;
- }
- else {
- pb[i] = true;
- }
- }
- }
-
- if (totelem[2]) {
- pb = pblock[2] = MEM_callocN(sizeof(char) * totelem[2], "sort_bmelem face pblock");
- sb = sblock[2] = MEM_callocN(sizeof(BMElemSort) * totelem[2], "sort_bmelem face sblock");
-
- BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) {
- if (BM_elem_flag_test(fa, flag)) {
- pb[i] = false;
- sb[affected[2]].org_idx = i;
- sb[affected[2]++].srt = (float)-i;
- }
- else {
- pb[i] = true;
- }
- }
- }
- }
-
-/* printf("%d vertices: %d to be affected...\n", totelem[0], affected[0]);*/
-/* printf("%d edges: %d to be affected...\n", totelem[1], affected[1]);*/
-/* printf("%d faces: %d to be affected...\n", totelem[2], affected[2]);*/
- if (affected[0] == 0 && affected[1] == 0 && affected[2] == 0) {
- for (j = 3; j--; ) {
- if (pblock[j])
- MEM_freeN(pblock[j]);
- if (sblock[j])
- MEM_freeN(sblock[j]);
- if (map[j])
- MEM_freeN(map[j]);
- }
- return;
- }
-
- /* Sort affected elements, and populate mapping arrays, if needed. */
- for (j = 3; j--; ) {
- pb = pblock[j];
- sb = sblock[j];
- if (pb && sb && !map[j]) {
- const char *p_blk;
- BMElemSort *s_blk;
- int tot = totelem[j];
- int aff = affected[j];
-
- qsort(sb, aff, sizeof(BMElemSort), bmelemsort_comp);
-
- mp = map[j] = MEM_mallocN(sizeof(int) * tot, "sort_bmelem map");
- p_blk = pb + tot - 1;
- s_blk = sb + aff - 1;
- for (i = tot; i--; p_blk--) {
- if (*p_blk) { /* Protected! */
- mp[i] = i;
- }
- else {
- mp[s_blk->org_idx] = i;
- s_blk--;
- }
- }
- }
- if (pb)
- MEM_freeN(pb);
- if (sb)
- MEM_freeN(sb);
- }
-
- BM_mesh_remap(em->bm, map[0], map[1], map[2]);
- DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
-
- for (j = 3; j--; ) {
- if (map[j])
- MEM_freeN(map[j]);
- }
+static void sort_bmelem_flag(bContext *C,
+ Scene *scene,
+ Object *ob,
+ RegionView3D *rv3d,
+ const int types,
+ const int flag,
+ const int action,
+ const int reverse,
+ const unsigned int seed)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+
+ BMVert *ve;
+ BMEdge *ed;
+ BMFace *fa;
+ BMIter iter;
+
+ /* In all five elements below, 0 = vertices, 1 = edges, 2 = faces. */
+ /* 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;
+ int totelem[3] = {0, 0, 0};
+ int affected[3] = {0, 0, 0};
+ int i, j;
+
+ if (!(types && flag && action))
+ return;
+
+ if (types & BM_VERT)
+ totelem[0] = em->bm->totvert;
+ if (types & BM_EDGE)
+ totelem[1] = em->bm->totedge;
+ if (types & BM_FACE)
+ totelem[2] = em->bm->totface;
+
+ if (ELEM(action, SRT_VIEW_ZAXIS, SRT_VIEW_XAXIS)) {
+ float mat[4][4];
+ float fact = reverse ? -1.0 : 1.0;
+ int coidx = (action == SRT_VIEW_ZAXIS) ? 2 : 0;
+
+ /* Apply the view matrix to the object matrix. */
+ mul_m4_m4m4(mat, rv3d->viewmat, ob->obmat);
+
+ if (totelem[0]) {
+ pb = pblock[0] = MEM_callocN(sizeof(char) * totelem[0], "sort_bmelem vert pblock");
+ sb = sblock[0] = MEM_callocN(sizeof(BMElemSort) * totelem[0], "sort_bmelem vert sblock");
+
+ BM_ITER_MESH_INDEX (ve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(ve, flag)) {
+ float co[3];
+ mul_v3_m4v3(co, mat, ve->co);
+
+ pb[i] = false;
+ sb[affected[0]].org_idx = i;
+ sb[affected[0]++].srt = co[coidx] * fact;
+ }
+ else {
+ pb[i] = true;
+ }
+ }
+ }
+
+ if (totelem[1]) {
+ pb = pblock[1] = MEM_callocN(sizeof(char) * totelem[1], "sort_bmelem edge pblock");
+ sb = sblock[1] = MEM_callocN(sizeof(BMElemSort) * totelem[1], "sort_bmelem edge sblock");
+
+ BM_ITER_MESH_INDEX (ed, &iter, em->bm, BM_EDGES_OF_MESH, i) {
+ if (BM_elem_flag_test(ed, flag)) {
+ float co[3];
+ mid_v3_v3v3(co, ed->v1->co, ed->v2->co);
+ mul_m4_v3(mat, co);
+
+ pb[i] = false;
+ sb[affected[1]].org_idx = i;
+ sb[affected[1]++].srt = co[coidx] * fact;
+ }
+ else {
+ pb[i] = true;
+ }
+ }
+ }
+
+ if (totelem[2]) {
+ pb = pblock[2] = MEM_callocN(sizeof(char) * totelem[2], "sort_bmelem face pblock");
+ sb = sblock[2] = MEM_callocN(sizeof(BMElemSort) * totelem[2], "sort_bmelem face sblock");
+
+ BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) {
+ if (BM_elem_flag_test(fa, flag)) {
+ float co[3];
+ BM_face_calc_center_median(fa, co);
+ mul_m4_v3(mat, co);
+
+ pb[i] = false;
+ sb[affected[2]].org_idx = i;
+ sb[affected[2]++].srt = co[coidx] * fact;
+ }
+ else {
+ pb[i] = true;
+ }
+ }
+ }
+ }
+
+ else if (action == SRT_CURSOR_DISTANCE) {
+ float cur[3];
+ float mat[4][4];
+ float fact = reverse ? -1.0 : 1.0;
+
+ copy_v3_v3(cur, scene->cursor.location);
+
+ invert_m4_m4(mat, ob->obmat);
+ mul_m4_v3(mat, cur);
+
+ if (totelem[0]) {
+ pb = pblock[0] = MEM_callocN(sizeof(char) * totelem[0], "sort_bmelem vert pblock");
+ sb = sblock[0] = MEM_callocN(sizeof(BMElemSort) * totelem[0], "sort_bmelem vert sblock");
+
+ BM_ITER_MESH_INDEX (ve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(ve, flag)) {
+ pb[i] = false;
+ sb[affected[0]].org_idx = i;
+ sb[affected[0]++].srt = len_squared_v3v3(cur, ve->co) * fact;
+ }
+ else {
+ pb[i] = true;
+ }
+ }
+ }
+
+ if (totelem[1]) {
+ pb = pblock[1] = MEM_callocN(sizeof(char) * totelem[1], "sort_bmelem edge pblock");
+ sb = sblock[1] = MEM_callocN(sizeof(BMElemSort) * totelem[1], "sort_bmelem edge sblock");
+
+ BM_ITER_MESH_INDEX (ed, &iter, em->bm, BM_EDGES_OF_MESH, i) {
+ if (BM_elem_flag_test(ed, flag)) {
+ float co[3];
+ mid_v3_v3v3(co, ed->v1->co, ed->v2->co);
+
+ pb[i] = false;
+ sb[affected[1]].org_idx = i;
+ sb[affected[1]++].srt = len_squared_v3v3(cur, co) * fact;
+ }
+ else {
+ pb[i] = true;
+ }
+ }
+ }
+
+ if (totelem[2]) {
+ pb = pblock[2] = MEM_callocN(sizeof(char) * totelem[2], "sort_bmelem face pblock");
+ sb = sblock[2] = MEM_callocN(sizeof(BMElemSort) * totelem[2], "sort_bmelem face sblock");
+
+ BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) {
+ if (BM_elem_flag_test(fa, flag)) {
+ float co[3];
+ BM_face_calc_center_median(fa, co);
+
+ pb[i] = false;
+ sb[affected[2]].org_idx = i;
+ sb[affected[2]++].srt = len_squared_v3v3(cur, co) * fact;
+ }
+ else {
+ pb[i] = true;
+ }
+ }
+ }
+ }
+
+ /* Faces only! */
+ else if (action == SRT_MATERIAL && totelem[2]) {
+ pb = pblock[2] = MEM_callocN(sizeof(char) * totelem[2], "sort_bmelem face pblock");
+ sb = sblock[2] = MEM_callocN(sizeof(BMElemSort) * totelem[2], "sort_bmelem face sblock");
+
+ BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) {
+ if (BM_elem_flag_test(fa, flag)) {
+ /* Reverse materials' order, not order of faces inside each mat! */
+ /* Note: cannot use totcol, as mat_nr may sometimes be greater... */
+ float srt = reverse ? (float)(MAXMAT - fa->mat_nr) : (float)fa->mat_nr;
+ pb[i] = false;
+ sb[affected[2]].org_idx = i;
+ /* Multiplying with totface and adding i ensures us
+ * we keep current order for all faces of same mat. */
+ sb[affected[2]++].srt = srt * ((float)totelem[2]) + ((float)i);
+ // printf("e: %d; srt: %f; final: %f\n",
+ // i, srt, srt * ((float)totface) + ((float)i));
+ }
+ else {
+ pb[i] = true;
+ }
+ }
+ }
+
+ else if (action == SRT_SELECTED) {
+ unsigned int *tbuf[3] = {NULL, NULL, NULL}, *tb;
+
+ if (totelem[0]) {
+ tb = tbuf[0] = MEM_callocN(sizeof(int) * totelem[0], "sort_bmelem vert tbuf");
+ mp = map[0] = MEM_callocN(sizeof(int) * totelem[0], "sort_bmelem vert map");
+
+ BM_ITER_MESH_INDEX (ve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(ve, flag)) {
+ mp[affected[0]++] = i;
+ }
+ else {
+ *tb = i;
+ tb++;
+ }
+ }
+ }
+
+ if (totelem[1]) {
+ tb = tbuf[1] = MEM_callocN(sizeof(int) * totelem[1], "sort_bmelem edge tbuf");
+ mp = map[1] = MEM_callocN(sizeof(int) * totelem[1], "sort_bmelem edge map");
+
+ BM_ITER_MESH_INDEX (ed, &iter, em->bm, BM_EDGES_OF_MESH, i) {
+ if (BM_elem_flag_test(ed, flag)) {
+ mp[affected[1]++] = i;
+ }
+ else {
+ *tb = i;
+ tb++;
+ }
+ }
+ }
+
+ if (totelem[2]) {
+ tb = tbuf[2] = MEM_callocN(sizeof(int) * totelem[2], "sort_bmelem face tbuf");
+ mp = map[2] = MEM_callocN(sizeof(int) * totelem[2], "sort_bmelem face map");
+
+ BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) {
+ if (BM_elem_flag_test(fa, flag)) {
+ mp[affected[2]++] = i;
+ }
+ else {
+ *tb = i;
+ tb++;
+ }
+ }
+ }
+
+ for (j = 3; j--;) {
+ int tot = totelem[j];
+ int aff = affected[j];
+ tb = tbuf[j];
+ mp = map[j];
+ if (!(tb && mp))
+ continue;
+ if (ELEM(aff, 0, tot)) {
+ MEM_freeN(tb);
+ MEM_freeN(mp);
+ map[j] = NULL;
+ continue;
+ }
+ if (reverse) {
+ memcpy(tb + (tot - aff), mp, aff * sizeof(int));
+ }
+ else {
+ memcpy(mp + aff, tb, (tot - aff) * sizeof(int));
+ tb = mp;
+ mp = map[j] = tbuf[j];
+ tbuf[j] = tb;
+ }
+
+ /* Reverse mapping, we want an org2new one! */
+ for (i = tot, tb = tbuf[j] + tot - 1; i--; tb--) {
+ mp[*tb] = i;
+ }
+ MEM_freeN(tbuf[j]);
+ }
+ }
+
+ else if (action == SRT_RANDOMIZE) {
+ if (totelem[0]) {
+ /* Re-init random generator for each element type, to get consistent random when
+ * enabling/disabling an element type. */
+ RNG *rng = BLI_rng_new_srandom(seed);
+ pb = pblock[0] = MEM_callocN(sizeof(char) * totelem[0], "sort_bmelem vert pblock");
+ sb = sblock[0] = MEM_callocN(sizeof(BMElemSort) * totelem[0], "sort_bmelem vert sblock");
+
+ BM_ITER_MESH_INDEX (ve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(ve, flag)) {
+ pb[i] = false;
+ sb[affected[0]].org_idx = i;
+ sb[affected[0]++].srt = BLI_rng_get_float(rng);
+ }
+ else {
+ pb[i] = true;
+ }
+ }
+
+ BLI_rng_free(rng);
+ }
+
+ if (totelem[1]) {
+ RNG *rng = BLI_rng_new_srandom(seed);
+ pb = pblock[1] = MEM_callocN(sizeof(char) * totelem[1], "sort_bmelem edge pblock");
+ sb = sblock[1] = MEM_callocN(sizeof(BMElemSort) * totelem[1], "sort_bmelem edge sblock");
+
+ BM_ITER_MESH_INDEX (ed, &iter, em->bm, BM_EDGES_OF_MESH, i) {
+ if (BM_elem_flag_test(ed, flag)) {
+ pb[i] = false;
+ sb[affected[1]].org_idx = i;
+ sb[affected[1]++].srt = BLI_rng_get_float(rng);
+ }
+ else {
+ pb[i] = true;
+ }
+ }
+
+ BLI_rng_free(rng);
+ }
+
+ if (totelem[2]) {
+ RNG *rng = BLI_rng_new_srandom(seed);
+ pb = pblock[2] = MEM_callocN(sizeof(char) * totelem[2], "sort_bmelem face pblock");
+ sb = sblock[2] = MEM_callocN(sizeof(BMElemSort) * totelem[2], "sort_bmelem face sblock");
+
+ BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) {
+ if (BM_elem_flag_test(fa, flag)) {
+ pb[i] = false;
+ sb[affected[2]].org_idx = i;
+ sb[affected[2]++].srt = BLI_rng_get_float(rng);
+ }
+ else {
+ pb[i] = true;
+ }
+ }
+
+ BLI_rng_free(rng);
+ }
+ }
+
+ else if (action == SRT_REVERSE) {
+ if (totelem[0]) {
+ pb = pblock[0] = MEM_callocN(sizeof(char) * totelem[0], "sort_bmelem vert pblock");
+ sb = sblock[0] = MEM_callocN(sizeof(BMElemSort) * totelem[0], "sort_bmelem vert sblock");
+
+ BM_ITER_MESH_INDEX (ve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(ve, flag)) {
+ pb[i] = false;
+ sb[affected[0]].org_idx = i;
+ sb[affected[0]++].srt = (float)-i;
+ }
+ else {
+ pb[i] = true;
+ }
+ }
+ }
+
+ if (totelem[1]) {
+ pb = pblock[1] = MEM_callocN(sizeof(char) * totelem[1], "sort_bmelem edge pblock");
+ sb = sblock[1] = MEM_callocN(sizeof(BMElemSort) * totelem[1], "sort_bmelem edge sblock");
+
+ BM_ITER_MESH_INDEX (ed, &iter, em->bm, BM_EDGES_OF_MESH, i) {
+ if (BM_elem_flag_test(ed, flag)) {
+ pb[i] = false;
+ sb[affected[1]].org_idx = i;
+ sb[affected[1]++].srt = (float)-i;
+ }
+ else {
+ pb[i] = true;
+ }
+ }
+ }
+
+ if (totelem[2]) {
+ pb = pblock[2] = MEM_callocN(sizeof(char) * totelem[2], "sort_bmelem face pblock");
+ sb = sblock[2] = MEM_callocN(sizeof(BMElemSort) * totelem[2], "sort_bmelem face sblock");
+
+ BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) {
+ if (BM_elem_flag_test(fa, flag)) {
+ pb[i] = false;
+ sb[affected[2]].org_idx = i;
+ sb[affected[2]++].srt = (float)-i;
+ }
+ else {
+ pb[i] = true;
+ }
+ }
+ }
+ }
+
+ /* printf("%d vertices: %d to be affected...\n", totelem[0], affected[0]);*/
+ /* printf("%d edges: %d to be affected...\n", totelem[1], affected[1]);*/
+ /* printf("%d faces: %d to be affected...\n", totelem[2], affected[2]);*/
+ if (affected[0] == 0 && affected[1] == 0 && affected[2] == 0) {
+ for (j = 3; j--;) {
+ if (pblock[j])
+ MEM_freeN(pblock[j]);
+ if (sblock[j])
+ MEM_freeN(sblock[j]);
+ if (map[j])
+ MEM_freeN(map[j]);
+ }
+ return;
+ }
+
+ /* Sort affected elements, and populate mapping arrays, if needed. */
+ for (j = 3; j--;) {
+ pb = pblock[j];
+ sb = sblock[j];
+ if (pb && sb && !map[j]) {
+ const char *p_blk;
+ BMElemSort *s_blk;
+ int tot = totelem[j];
+ int aff = affected[j];
+
+ qsort(sb, aff, sizeof(BMElemSort), bmelemsort_comp);
+
+ mp = map[j] = MEM_mallocN(sizeof(int) * tot, "sort_bmelem map");
+ p_blk = pb + tot - 1;
+ s_blk = sb + aff - 1;
+ for (i = tot; i--; p_blk--) {
+ if (*p_blk) { /* Protected! */
+ mp[i] = i;
+ }
+ else {
+ mp[s_blk->org_idx] = i;
+ s_blk--;
+ }
+ }
+ }
+ if (pb)
+ MEM_freeN(pb);
+ if (sb)
+ MEM_freeN(sb);
+ }
+
+ BM_mesh_remap(em->bm, map[0], map[1], map[2]);
+ DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+
+ for (j = 3; j--;) {
+ if (map[j])
+ MEM_freeN(map[j]);
+ }
}
static int edbm_sort_elements_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob_active = CTX_data_edit_object(C);
-
- /* may be NULL */
- RegionView3D *rv3d = ED_view3d_context_rv3d(C);
-
- 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");
- int elem_types = 0;
-
- if (ELEM(action, SRT_VIEW_ZAXIS, SRT_VIEW_XAXIS)) {
- if (rv3d == NULL) {
- BKE_report(op->reports, RPT_ERROR, "View not found, cannot sort by view axis");
- return OPERATOR_CANCELLED;
- }
- }
-
- /* If no elem_types set, use current selection mode to set it! */
- if (RNA_property_is_set(op->ptr, prop_elem_types)) {
- elem_types = RNA_property_enum_get(op->ptr, prop_elem_types);
- }
- else {
- BMEditMesh *em = BKE_editmesh_from_object(ob_active);
- if (em->selectmode & SCE_SELECT_VERTEX)
- elem_types |= BM_VERT;
- if (em->selectmode & SCE_SELECT_EDGE)
- elem_types |= BM_EDGE;
- if (em->selectmode & SCE_SELECT_FACE)
- elem_types |= BM_FACE;
- RNA_enum_set(op->ptr, "elements", elem_types);
- }
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em->bm;
-
- if (!((elem_types & BM_VERT && bm->totvertsel > 0) ||
- (elem_types & BM_EDGE && bm->totedgesel > 0) ||
- (elem_types & BM_FACE && bm->totfacesel > 0)))
- {
- continue;
- }
-
- int seed_iter = seed;
-
- /* This gives a consistent result regardless of object order */
- if (ob_index) {
- seed_iter += BLI_ghashutil_strhash_p(ob->id.name);
- }
-
- sort_bmelem_flag(
- C, scene, ob, rv3d,
- elem_types, BM_ELEM_SELECT, action, use_reverse, seed_iter);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
-}
-
-static bool edbm_sort_elements_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop)
-{
- const char *prop_id = RNA_property_identifier(prop);
- const int action = RNA_enum_get(op->ptr, "type");
-
- /* Only show seed for randomize action! */
- if (STREQ(prop_id, "seed")) {
- if (action == SRT_RANDOMIZE)
- return true;
- else
- return false;
- }
-
- /* Hide seed for reverse and randomize actions! */
- if (STREQ(prop_id, "reverse")) {
- if (ELEM(action, SRT_RANDOMIZE, SRT_REVERSE))
- return false;
- else
- return true;
- }
-
- return true;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob_active = CTX_data_edit_object(C);
+
+ /* may be NULL */
+ RegionView3D *rv3d = ED_view3d_context_rv3d(C);
+
+ 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");
+ int elem_types = 0;
+
+ if (ELEM(action, SRT_VIEW_ZAXIS, SRT_VIEW_XAXIS)) {
+ if (rv3d == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "View not found, cannot sort by view axis");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ /* If no elem_types set, use current selection mode to set it! */
+ if (RNA_property_is_set(op->ptr, prop_elem_types)) {
+ elem_types = RNA_property_enum_get(op->ptr, prop_elem_types);
+ }
+ else {
+ BMEditMesh *em = BKE_editmesh_from_object(ob_active);
+ if (em->selectmode & SCE_SELECT_VERTEX)
+ elem_types |= BM_VERT;
+ if (em->selectmode & SCE_SELECT_EDGE)
+ elem_types |= BM_EDGE;
+ if (em->selectmode & SCE_SELECT_FACE)
+ elem_types |= BM_FACE;
+ RNA_enum_set(op->ptr, "elements", elem_types);
+ }
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
+
+ if (!((elem_types & BM_VERT && bm->totvertsel > 0) ||
+ (elem_types & BM_EDGE && bm->totedgesel > 0) ||
+ (elem_types & BM_FACE && bm->totfacesel > 0))) {
+ continue;
+ }
+
+ int seed_iter = seed;
+
+ /* This gives a consistent result regardless of object order */
+ if (ob_index) {
+ seed_iter += BLI_ghashutil_strhash_p(ob->id.name);
+ }
+
+ sort_bmelem_flag(
+ C, scene, ob, rv3d, elem_types, BM_ELEM_SELECT, action, use_reverse, seed_iter);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
+}
+
+static bool edbm_sort_elements_poll_property(const bContext *UNUSED(C),
+ wmOperator *op,
+ const PropertyRNA *prop)
+{
+ const char *prop_id = RNA_property_identifier(prop);
+ const int action = RNA_enum_get(op->ptr, "type");
+
+ /* Only show seed for randomize action! */
+ if (STREQ(prop_id, "seed")) {
+ if (action == SRT_RANDOMIZE)
+ return true;
+ else
+ return false;
+ }
+
+ /* Hide seed for reverse and randomize actions! */
+ if (STREQ(prop_id, "reverse")) {
+ if (ELEM(action, SRT_RANDOMIZE, SRT_REVERSE))
+ return false;
+ else
+ return true;
+ }
+
+ return true;
}
void MESH_OT_sort_elements(wmOperatorType *ot)
{
- static const EnumPropertyItem type_items[] = {
- {SRT_VIEW_ZAXIS, "VIEW_ZAXIS", 0, "View Z Axis",
- "Sort selected elements from farthest to nearest one in current view"},
- {SRT_VIEW_XAXIS, "VIEW_XAXIS", 0, "View X Axis",
- "Sort selected elements from left to right one in current view"},
- {SRT_CURSOR_DISTANCE, "CURSOR_DISTANCE", 0, "Cursor Distance",
- "Sort selected elements from nearest to farthest from 3D cursor"},
- {SRT_MATERIAL, "MATERIAL", 0, "Material",
- "Sort selected elements from smallest to greatest material index (faces only!)"},
- {SRT_SELECTED, "SELECTED", 0, "Selected",
- "Move all selected elements in first places, preserving their relative order "
- "(WARNING: this will affect unselected elements' indices as well!)"},
- {SRT_RANDOMIZE, "RANDOMIZE", 0, "Randomize", "Randomize order of selected elements"},
- {SRT_REVERSE, "REVERSE", 0, "Reverse", "Reverse current order of selected elements"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem elem_items[] = {
- {BM_VERT, "VERT", 0, "Vertices", ""},
- {BM_EDGE, "EDGE", 0, "Edges", ""},
- {BM_FACE, "FACE", 0, "Faces", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Sort Mesh Elements";
- ot->description = "The order of selected vertices/edges/faces is modified, based on a given method";
- ot->idname = "MESH_OT_sort_elements";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = edbm_sort_elements_exec;
- ot->poll = ED_operator_editmesh;
- ot->poll_property = edbm_sort_elements_poll_property;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", type_items, SRT_VIEW_ZAXIS,
- "Type", "Type of re-ordering operation to apply");
- RNA_def_enum_flag(ot->srna, "elements", elem_items, BM_VERT, "Elements",
- "Which elements to affect (vertices, edges and/or faces)");
- RNA_def_boolean(ot->srna, "reverse", false, "Reverse", "Reverse the sorting effect");
- RNA_def_int(ot->srna, "seed", 0, 0, INT_MAX, "Seed", "Seed for random-based operations", 0, 255);
+ static const EnumPropertyItem type_items[] = {
+ {SRT_VIEW_ZAXIS,
+ "VIEW_ZAXIS",
+ 0,
+ "View Z Axis",
+ "Sort selected elements from farthest to nearest one in current view"},
+ {SRT_VIEW_XAXIS,
+ "VIEW_XAXIS",
+ 0,
+ "View X Axis",
+ "Sort selected elements from left to right one in current view"},
+ {SRT_CURSOR_DISTANCE,
+ "CURSOR_DISTANCE",
+ 0,
+ "Cursor Distance",
+ "Sort selected elements from nearest to farthest from 3D cursor"},
+ {SRT_MATERIAL,
+ "MATERIAL",
+ 0,
+ "Material",
+ "Sort selected elements from smallest to greatest material index (faces only!)"},
+ {SRT_SELECTED,
+ "SELECTED",
+ 0,
+ "Selected",
+ "Move all selected elements in first places, preserving their relative order "
+ "(WARNING: this will affect unselected elements' indices as well!)"},
+ {SRT_RANDOMIZE, "RANDOMIZE", 0, "Randomize", "Randomize order of selected elements"},
+ {SRT_REVERSE, "REVERSE", 0, "Reverse", "Reverse current order of selected elements"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem elem_items[] = {
+ {BM_VERT, "VERT", 0, "Vertices", ""},
+ {BM_EDGE, "EDGE", 0, "Edges", ""},
+ {BM_FACE, "FACE", 0, "Faces", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Sort Mesh Elements";
+ ot->description =
+ "The order of selected vertices/edges/faces is modified, based on a given method";
+ ot->idname = "MESH_OT_sort_elements";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = edbm_sort_elements_exec;
+ ot->poll = ED_operator_editmesh;
+ ot->poll_property = edbm_sort_elements_poll_property;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna,
+ "type",
+ type_items,
+ SRT_VIEW_ZAXIS,
+ "Type",
+ "Type of re-ordering operation to apply");
+ RNA_def_enum_flag(ot->srna,
+ "elements",
+ elem_items,
+ BM_VERT,
+ "Elements",
+ "Which elements to affect (vertices, edges and/or faces)");
+ RNA_def_boolean(ot->srna, "reverse", false, "Reverse", "Reverse the sorting effect");
+ RNA_def_int(ot->srna, "seed", 0, 0, INT_MAX, "Seed", "Seed for random-based operations", 0, 255);
}
/** \} */
@@ -6212,210 +6538,232 @@ void MESH_OT_sort_elements(wmOperatorType *ot)
* \{ */
enum {
- MESH_BRIDGELOOP_SINGLE = 0,
- MESH_BRIDGELOOP_CLOSED = 1,
- MESH_BRIDGELOOP_PAIRS = 2,
+ MESH_BRIDGELOOP_SINGLE = 0,
+ MESH_BRIDGELOOP_CLOSED = 1,
+ MESH_BRIDGELOOP_PAIRS = 2,
};
static int edbm_bridge_tag_boundary_edges(BMesh *bm)
{
- /* tags boundary edges from a face selection */
- BMIter iter;
- BMFace *f;
- BMEdge *e;
- int totface_del = 0;
-
- BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
-
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- if (BM_edge_is_wire(e) || BM_edge_is_boundary(e)) {
- BM_elem_flag_enable(e, BM_ELEM_TAG);
- }
- else {
- BMIter fiter;
- bool is_all_sel = true;
- /* check if its only used by selected faces */
- BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- /* tag face for removal*/
- if (!BM_elem_flag_test(f, BM_ELEM_TAG)) {
- BM_elem_flag_enable(f, BM_ELEM_TAG);
- totface_del++;
- }
- }
- else {
- is_all_sel = false;
- }
- }
-
- if (is_all_sel == false) {
- BM_elem_flag_enable(e, BM_ELEM_TAG);
- }
- }
- }
- }
-
- return totface_del;
-}
-
-static int edbm_bridge_edge_loops_for_single_editmesh(
- wmOperator *op,
- BMEditMesh *em,
- const bool use_pairs,
- const bool use_cyclic,
- const bool use_merge,
- const float merge_factor,
- const int twist_offset)
-{
- BMOperator bmop;
- char edge_hflag;
- int totface_del = 0;
- BMFace **totface_del_arr = NULL;
- const bool use_faces = (em->bm->totfacesel != 0);
-
- if (use_faces) {
- BMIter iter;
- BMFace *f;
- int i;
-
- totface_del = edbm_bridge_tag_boundary_edges(em->bm);
- totface_del_arr = MEM_mallocN(sizeof(*totface_del_arr) * totface_del, __func__);
-
- i = 0;
- BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_TAG)) {
- totface_del_arr[i++] = f;
- }
- }
- edge_hflag = BM_ELEM_TAG;
- }
- else {
- edge_hflag = BM_ELEM_SELECT;
- }
-
- EDBM_op_init(
- em, &bmop, op,
- "bridge_loops edges=%he use_pairs=%b use_cyclic=%b use_merge=%b merge_factor=%f twist_offset=%i",
- edge_hflag, use_pairs, use_cyclic, use_merge, merge_factor, twist_offset);
-
- if (use_faces && totface_del) {
- int i;
- BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
- for (i = 0; i < totface_del; i++) {
- BM_elem_flag_enable(totface_del_arr[i], BM_ELEM_TAG);
- }
- BMO_op_callf(
- em->bm, BMO_FLAG_DEFAULTS,
- "delete geom=%hf context=%i",
- BM_ELEM_TAG, DEL_FACES_KEEP_BOUNDARY);
- }
-
- BMO_op_exec(em->bm, &bmop);
-
- if (!BMO_error_occurred(em->bm)) {
- /* when merge is used the edges are joined and remain selected */
- if (use_merge == false) {
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
- }
-
- if (use_merge == false) {
- struct EdgeRingOpSubdProps op_props;
- mesh_operator_edgering_props_get(op, &op_props);
-
- if (op_props.cuts) {
- BMOperator bmop_subd;
- /* we only need face normals updated */
- EDBM_mesh_normals_update(em);
-
- BMO_op_initf(
- em->bm, &bmop_subd, 0,
- "subdivide_edgering edges=%S interp_mode=%i cuts=%i smooth=%f "
- "profile_shape=%i profile_shape_factor=%f",
- &bmop, "edges.out", op_props.interp_mode, op_props.cuts, op_props.smooth,
- op_props.profile_shape, op_props.profile_shape_factor
- );
- BMO_op_exec(em->bm, &bmop_subd);
- BMO_slot_buffer_hflag_enable(em->bm, bmop_subd.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
- BMO_op_finish(em->bm, &bmop_subd);
- }
- }
- }
-
- if (totface_del_arr) {
- MEM_freeN(totface_del_arr);
- }
-
- if (EDBM_op_finish(em, &bmop, op, true)) {
- EDBM_update_generic(em, true, true);
- }
-
- /* Always return finished so the user can select different options. */
- return OPERATOR_FINISHED;
+ /* tags boundary edges from a face selection */
+ BMIter iter;
+ BMFace *f;
+ BMEdge *e;
+ int totface_del = 0;
+
+ BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ if (BM_edge_is_wire(e) || BM_edge_is_boundary(e)) {
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ }
+ else {
+ BMIter fiter;
+ bool is_all_sel = true;
+ /* check if its only used by selected faces */
+ BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ /* tag face for removal*/
+ if (!BM_elem_flag_test(f, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+ totface_del++;
+ }
+ }
+ else {
+ is_all_sel = false;
+ }
+ }
+
+ if (is_all_sel == false) {
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ }
+ }
+ }
+ }
+
+ return totface_del;
+}
+
+static int edbm_bridge_edge_loops_for_single_editmesh(wmOperator *op,
+ BMEditMesh *em,
+ const bool use_pairs,
+ const bool use_cyclic,
+ const bool use_merge,
+ const float merge_factor,
+ const int twist_offset)
+{
+ BMOperator bmop;
+ char edge_hflag;
+ int totface_del = 0;
+ BMFace **totface_del_arr = NULL;
+ const bool use_faces = (em->bm->totfacesel != 0);
+
+ if (use_faces) {
+ BMIter iter;
+ BMFace *f;
+ int i;
+
+ totface_del = edbm_bridge_tag_boundary_edges(em->bm);
+ totface_del_arr = MEM_mallocN(sizeof(*totface_del_arr) * totface_del, __func__);
+
+ i = 0;
+ BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_TAG)) {
+ totface_del_arr[i++] = f;
+ }
+ }
+ edge_hflag = BM_ELEM_TAG;
+ }
+ else {
+ edge_hflag = BM_ELEM_SELECT;
+ }
+
+ EDBM_op_init(em,
+ &bmop,
+ op,
+ "bridge_loops edges=%he use_pairs=%b use_cyclic=%b use_merge=%b merge_factor=%f "
+ "twist_offset=%i",
+ edge_hflag,
+ use_pairs,
+ use_cyclic,
+ use_merge,
+ merge_factor,
+ twist_offset);
+
+ if (use_faces && totface_del) {
+ int i;
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
+ for (i = 0; i < totface_del; i++) {
+ BM_elem_flag_enable(totface_del_arr[i], BM_ELEM_TAG);
+ }
+ BMO_op_callf(em->bm,
+ BMO_FLAG_DEFAULTS,
+ "delete geom=%hf context=%i",
+ BM_ELEM_TAG,
+ DEL_FACES_KEEP_BOUNDARY);
+ }
+
+ BMO_op_exec(em->bm, &bmop);
+
+ if (!BMO_error_occurred(em->bm)) {
+ /* when merge is used the edges are joined and remain selected */
+ if (use_merge == false) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BMO_slot_buffer_hflag_enable(
+ em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
+ }
+
+ if (use_merge == false) {
+ struct EdgeRingOpSubdProps op_props;
+ mesh_operator_edgering_props_get(op, &op_props);
+
+ if (op_props.cuts) {
+ BMOperator bmop_subd;
+ /* we only need face normals updated */
+ EDBM_mesh_normals_update(em);
+
+ BMO_op_initf(em->bm,
+ &bmop_subd,
+ 0,
+ "subdivide_edgering edges=%S interp_mode=%i cuts=%i smooth=%f "
+ "profile_shape=%i profile_shape_factor=%f",
+ &bmop,
+ "edges.out",
+ op_props.interp_mode,
+ op_props.cuts,
+ op_props.smooth,
+ op_props.profile_shape,
+ op_props.profile_shape_factor);
+ BMO_op_exec(em->bm, &bmop_subd);
+ BMO_slot_buffer_hflag_enable(
+ em->bm, bmop_subd.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
+ BMO_op_finish(em->bm, &bmop_subd);
+ }
+ }
+ }
+
+ if (totface_del_arr) {
+ MEM_freeN(totface_del_arr);
+ }
+
+ if (EDBM_op_finish(em, &bmop, op, true)) {
+ EDBM_update_generic(em, true, true);
+ }
+
+ /* Always return finished so the user can select different options. */
+ return OPERATOR_FINISHED;
}
static int edbm_bridge_edge_loops_exec(bContext *C, wmOperator *op)
{
- const int type = RNA_enum_get(op->ptr, "type");
- const bool use_pairs = (type == MESH_BRIDGELOOP_PAIRS);
- const bool use_cyclic = (type == MESH_BRIDGELOOP_CLOSED);
- const bool use_merge = RNA_boolean_get(op->ptr, "use_merge");
- const float merge_factor = RNA_float_get(op->ptr, "merge_factor");
- const int twist_offset = RNA_int_get(op->ptr, "twist_offset");
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totvertsel == 0) {
- continue;
- }
-
- edbm_bridge_edge_loops_for_single_editmesh(op,
- em,
- use_pairs,
- use_cyclic,
- use_merge,
- merge_factor,
- twist_offset);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_bridge_edge_loops(wmOperatorType *ot)
-{
- static const EnumPropertyItem type_items[] = {
- {MESH_BRIDGELOOP_SINGLE, "SINGLE", 0, "Open Loop", ""},
- {MESH_BRIDGELOOP_CLOSED, "CLOSED", 0, "Closed Loop", ""},
- {MESH_BRIDGELOOP_PAIRS, "PAIRS", 0, "Loop Pairs", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Bridge Edge Loops";
- ot->description = "Make faces between two or more edge loops";
- ot->idname = "MESH_OT_bridge_edge_loops";
+ const int type = RNA_enum_get(op->ptr, "type");
+ const bool use_pairs = (type == MESH_BRIDGELOOP_PAIRS);
+ const bool use_cyclic = (type == MESH_BRIDGELOOP_CLOSED);
+ const bool use_merge = RNA_boolean_get(op->ptr, "use_merge");
+ const float merge_factor = RNA_float_get(op->ptr, "merge_factor");
+ const int twist_offset = RNA_int_get(op->ptr, "twist_offset");
+ ViewLayer *view_layer = CTX_data_view_layer(C);
- /* api callbacks */
- ot->exec = edbm_bridge_edge_loops_exec;
- ot->poll = ED_operator_editmesh;
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
- ot->prop = RNA_def_enum(ot->srna, "type", type_items, MESH_BRIDGELOOP_SINGLE,
- "Connect Loops", "Method of bridging multiple loops");
-
- RNA_def_boolean(ot->srna, "use_merge", false, "Merge", "Merge rather than creating faces");
- RNA_def_float(ot->srna, "merge_factor", 0.5f, 0.0f, 1.0f, "Merge Factor", "", 0.0f, 1.0f);
- RNA_def_int(ot->srna, "twist_offset", 0, -1000, 1000, "Twist", "Twist offset for closed loops", -1000, 1000);
+ edbm_bridge_edge_loops_for_single_editmesh(
+ op, em, use_pairs, use_cyclic, use_merge, merge_factor, twist_offset);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
+}
- mesh_operator_edgering_props(ot, 0, 0);
+void MESH_OT_bridge_edge_loops(wmOperatorType *ot)
+{
+ static const EnumPropertyItem type_items[] = {
+ {MESH_BRIDGELOOP_SINGLE, "SINGLE", 0, "Open Loop", ""},
+ {MESH_BRIDGELOOP_CLOSED, "CLOSED", 0, "Closed Loop", ""},
+ {MESH_BRIDGELOOP_PAIRS, "PAIRS", 0, "Loop Pairs", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Bridge Edge Loops";
+ ot->description = "Make faces between two or more edge loops";
+ ot->idname = "MESH_OT_bridge_edge_loops";
+
+ /* api callbacks */
+ ot->exec = edbm_bridge_edge_loops_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna,
+ "type",
+ type_items,
+ MESH_BRIDGELOOP_SINGLE,
+ "Connect Loops",
+ "Method of bridging multiple loops");
+
+ RNA_def_boolean(ot->srna, "use_merge", false, "Merge", "Merge rather than creating faces");
+ RNA_def_float(ot->srna, "merge_factor", 0.5f, 0.0f, 1.0f, "Merge Factor", "", 0.0f, 1.0f);
+ RNA_def_int(ot->srna,
+ "twist_offset",
+ 0,
+ -1000,
+ 1000,
+ "Twist",
+ "Twist offset for closed loops",
+ -1000,
+ 1000);
+
+ mesh_operator_edgering_props(ot, 0, 0);
}
/** \} */
@@ -6426,80 +6774,102 @@ void MESH_OT_bridge_edge_loops(wmOperatorType *ot)
static int edbm_wireframe_exec(bContext *C, wmOperator *op)
{
- const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary");
- const bool use_even_offset = RNA_boolean_get(op->ptr, "use_even_offset");
- const bool use_replace = RNA_boolean_get(op->ptr, "use_replace");
- const bool use_relative_offset = RNA_boolean_get(op->ptr, "use_relative_offset");
- const bool use_crease = RNA_boolean_get(op->ptr, "use_crease");
- const float crease_weight = RNA_float_get(op->ptr, "crease_weight");
- const float thickness = RNA_float_get(op->ptr, "thickness");
- const float offset = RNA_float_get(op->ptr, "offset");
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totfacesel == 0) {
- continue;
- }
-
- BMOperator bmop;
-
- EDBM_op_init(
- em, &bmop, op,
- "wireframe faces=%hf use_replace=%b use_boundary=%b use_even_offset=%b use_relative_offset=%b "
- "use_crease=%b crease_weight=%f thickness=%f offset=%f",
- BM_ELEM_SELECT, use_replace, use_boundary, use_even_offset, use_relative_offset,
- use_crease, crease_weight, thickness, offset);
-
- BMO_op_exec(em->bm, &bmop);
-
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
-
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
-
- EDBM_update_generic(em, true, true);
- }
-
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary");
+ const bool use_even_offset = RNA_boolean_get(op->ptr, "use_even_offset");
+ const bool use_replace = RNA_boolean_get(op->ptr, "use_replace");
+ const bool use_relative_offset = RNA_boolean_get(op->ptr, "use_relative_offset");
+ const bool use_crease = RNA_boolean_get(op->ptr, "use_crease");
+ const float crease_weight = RNA_float_get(op->ptr, "crease_weight");
+ const float thickness = RNA_float_get(op->ptr, "thickness");
+ const float offset = RNA_float_get(op->ptr, "offset");
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
+
+ BMOperator bmop;
+
+ EDBM_op_init(em,
+ &bmop,
+ op,
+ "wireframe faces=%hf use_replace=%b use_boundary=%b use_even_offset=%b "
+ "use_relative_offset=%b "
+ "use_crease=%b crease_weight=%f thickness=%f offset=%f",
+ BM_ELEM_SELECT,
+ use_replace,
+ use_boundary,
+ use_even_offset,
+ use_relative_offset,
+ use_crease,
+ crease_weight,
+ thickness,
+ offset);
+
+ BMO_op_exec(em->bm, &bmop);
+
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
+ BMO_slot_buffer_hflag_enable(
+ em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
+
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
+
+ EDBM_update_generic(em, true, true);
+ }
+
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_wireframe(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Wire Frame";
- ot->idname = "MESH_OT_wireframe";
- ot->description = "Create a solid wire-frame from faces";
-
- /* api callbacks */
- ot->exec = edbm_wireframe_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "use_boundary", true, "Boundary", "Inset face boundaries");
- RNA_def_boolean(ot->srna, "use_even_offset", true, "Offset Even", "Scale the offset to give more even thickness");
- RNA_def_boolean(ot->srna, "use_relative_offset", false, "Offset Relative", "Scale the offset by surrounding geometry");
- RNA_def_boolean(ot->srna, "use_replace", true, "Replace", "Remove original faces");
- prop = RNA_def_float_distance(ot->srna, "thickness", 0.01f, 0.0f, 1e4f, "Thickness", "", 0.0f, 10.0f);
- /* use 1 rather then 10 for max else dragging the button moves too far */
- RNA_def_property_ui_range(prop, 0.0, 1.0, 0.01, 4);
- RNA_def_float_distance(ot->srna, "offset", 0.01f, 0.0f, 1e4f, "Offset", "", 0.0f, 10.0f);
- RNA_def_boolean(ot->srna, "use_crease", false, "Crease", "Crease hub edges for improved subsurf");
- prop = RNA_def_float(ot->srna, "crease_weight", 0.01f, 0.0f, 1e3f, "Crease weight", "", 0.0f, 1.0f);
- RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 2);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Wire Frame";
+ ot->idname = "MESH_OT_wireframe";
+ ot->description = "Create a solid wire-frame from faces";
+
+ /* api callbacks */
+ ot->exec = edbm_wireframe_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "use_boundary", true, "Boundary", "Inset face boundaries");
+ RNA_def_boolean(ot->srna,
+ "use_even_offset",
+ true,
+ "Offset Even",
+ "Scale the offset to give more even thickness");
+ RNA_def_boolean(ot->srna,
+ "use_relative_offset",
+ false,
+ "Offset Relative",
+ "Scale the offset by surrounding geometry");
+ RNA_def_boolean(ot->srna, "use_replace", true, "Replace", "Remove original faces");
+ prop = RNA_def_float_distance(
+ ot->srna, "thickness", 0.01f, 0.0f, 1e4f, "Thickness", "", 0.0f, 10.0f);
+ /* use 1 rather then 10 for max else dragging the button moves too far */
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 0.01, 4);
+ RNA_def_float_distance(ot->srna, "offset", 0.01f, 0.0f, 1e4f, "Offset", "", 0.0f, 10.0f);
+ RNA_def_boolean(
+ ot->srna, "use_crease", false, "Crease", "Crease hub edges for improved subsurf");
+ prop = RNA_def_float(
+ ot->srna, "crease_weight", 0.01f, 0.0f, 1e3f, "Crease weight", "", 0.0f, 1.0f);
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 2);
}
/** \} */
@@ -6510,81 +6880,86 @@ 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;
- }
- }
-
- 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];
- 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;
- }
-
- BMOperator bmop;
- EDBM_op_init(
- em, &bmop, op,
- "offset_edgeloops edges=%he use_cap_endpoint=%b",
- BM_ELEM_SELECT, use_cap_endpoint);
-
- BMO_op_exec(em->bm, &bmop);
-
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
-
- 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 {
- EDBM_update_generic(em, true, true);
- ret = OPERATOR_FINISHED;
- }
- }
- MEM_freeN(objects);
- return ret;
+ 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;
+ }
+ }
+
+ 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];
+ 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;
+ }
+
+ BMOperator bmop;
+ EDBM_op_init(em,
+ &bmop,
+ op,
+ "offset_edgeloops edges=%he use_cap_endpoint=%b",
+ BM_ELEM_SELECT,
+ use_cap_endpoint);
+
+ BMO_op_exec(em->bm, &bmop);
+
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
+
+ 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 {
+ EDBM_update_generic(em, true, true);
+ ret = OPERATOR_FINISHED;
+ }
+ }
+ MEM_freeN(objects);
+ return ret;
}
void MESH_OT_offset_edge_loops(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Offset Edge Loop";
- ot->idname = "MESH_OT_offset_edge_loops";
- ot->description = "Create offset edge loop from the current selection";
+ /* identifiers */
+ ot->name = "Offset Edge Loop";
+ ot->idname = "MESH_OT_offset_edge_loops";
+ ot->description = "Create offset edge loop from the current selection";
- /* api callbacks */
- ot->exec = edbm_offset_edgeloop_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_offset_edgeloop_exec;
+ ot->poll = ED_operator_editmesh;
- /* Keep internal, since this is only meant to be accessed via 'MESH_OT_offset_edge_loops_slide' */
+ /* Keep internal, since this is only meant to be accessed via 'MESH_OT_offset_edge_loops_slide' */
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- RNA_def_boolean(ot->srna, "use_cap_endpoint", false, "Cap Endpoint", "Extend loop around end-points");
+ RNA_def_boolean(
+ ot->srna, "use_cap_endpoint", false, "Cap Endpoint", "Extend loop around end-points");
}
/** \} */
@@ -6596,125 +6971,132 @@ void MESH_OT_offset_edge_loops(wmOperatorType *ot)
#ifdef WITH_BULLET
static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
{
- const bool use_existing_faces = RNA_boolean_get(op->ptr, "use_existing_faces");
- const bool delete_unused = RNA_boolean_get(op->ptr, "delete_unused");
- const bool make_holes = RNA_boolean_get(op->ptr, "make_holes");
- const bool join_triangles = RNA_boolean_get(op->ptr, "join_triangles");
-
- float angle_face_threshold = RNA_float_get(op->ptr, "face_threshold");
- float angle_shape_threshold = RNA_float_get(op->ptr, "shape_threshold");
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totvertsel == 0) {
- continue;
- }
-
- BMOperator bmop;
-
- EDBM_op_init(
- em, &bmop, op, "convex_hull input=%hvef "
- "use_existing_faces=%b",
- BM_ELEM_SELECT,
- use_existing_faces);
- BMO_op_exec(em->bm, &bmop);
-
- /* Hull fails if input is coplanar */
- if (BMO_error_occurred(em->bm)) {
- EDBM_op_finish(em, &bmop, op, true);
- continue;
- }
-
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
-
- /* Delete unused vertices, edges, and faces */
- if (delete_unused) {
- if (!EDBM_op_callf(
- em, op, "delete geom=%S context=%i",
- &bmop, "geom_unused.out", DEL_ONLYTAGGED))
- {
- EDBM_op_finish(em, &bmop, op, true);
- continue;
- }
- }
-
- /* Delete hole edges/faces */
- if (make_holes) {
- if (!EDBM_op_callf(
- em, op, "delete geom=%S context=%i",
- &bmop, "geom_holes.out", DEL_ONLYTAGGED))
- {
- EDBM_op_finish(em, &bmop, op, true);
- continue;
- }
- }
-
- /* Merge adjacent triangles */
- if (join_triangles) {
- if (!EDBM_op_call_and_selectf(
- em, op,
- "faces.out", true,
- "join_triangles faces=%S "
- "angle_face_threshold=%f angle_shape_threshold=%f",
- &bmop, "geom.out",
- angle_face_threshold, angle_shape_threshold))
- {
- EDBM_op_finish(em, &bmop, op, true);
- continue;
- }
- }
-
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
-
- EDBM_update_generic(em, true, true);
- EDBM_selectmode_flush(em);
- }
-
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ const bool use_existing_faces = RNA_boolean_get(op->ptr, "use_existing_faces");
+ const bool delete_unused = RNA_boolean_get(op->ptr, "delete_unused");
+ const bool make_holes = RNA_boolean_get(op->ptr, "make_holes");
+ const bool join_triangles = RNA_boolean_get(op->ptr, "join_triangles");
+
+ float angle_face_threshold = RNA_float_get(op->ptr, "face_threshold");
+ float angle_shape_threshold = RNA_float_get(op->ptr, "shape_threshold");
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
+
+ BMOperator bmop;
+
+ EDBM_op_init(em,
+ &bmop,
+ op,
+ "convex_hull input=%hvef "
+ "use_existing_faces=%b",
+ BM_ELEM_SELECT,
+ use_existing_faces);
+ BMO_op_exec(em->bm, &bmop);
+
+ /* Hull fails if input is coplanar */
+ if (BMO_error_occurred(em->bm)) {
+ EDBM_op_finish(em, &bmop, op, true);
+ continue;
+ }
+
+ BMO_slot_buffer_hflag_enable(
+ em->bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
+
+ /* Delete unused vertices, edges, and faces */
+ if (delete_unused) {
+ if (!EDBM_op_callf(
+ em, op, "delete geom=%S context=%i", &bmop, "geom_unused.out", DEL_ONLYTAGGED)) {
+ EDBM_op_finish(em, &bmop, op, true);
+ continue;
+ }
+ }
+
+ /* Delete hole edges/faces */
+ if (make_holes) {
+ if (!EDBM_op_callf(
+ em, op, "delete geom=%S context=%i", &bmop, "geom_holes.out", DEL_ONLYTAGGED)) {
+ EDBM_op_finish(em, &bmop, op, true);
+ continue;
+ }
+ }
+
+ /* Merge adjacent triangles */
+ if (join_triangles) {
+ if (!EDBM_op_call_and_selectf(em,
+ op,
+ "faces.out",
+ true,
+ "join_triangles faces=%S "
+ "angle_face_threshold=%f angle_shape_threshold=%f",
+ &bmop,
+ "geom.out",
+ angle_face_threshold,
+ angle_shape_threshold)) {
+ EDBM_op_finish(em, &bmop, op, true);
+ continue;
+ }
+ }
+
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
+
+ EDBM_update_generic(em, true, true);
+ EDBM_selectmode_flush(em);
+ }
+
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_convex_hull(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Convex Hull";
- ot->description = "Enclose selected vertices in a convex polyhedron";
- ot->idname = "MESH_OT_convex_hull";
+ /* identifiers */
+ ot->name = "Convex Hull";
+ ot->description = "Enclose selected vertices in a convex polyhedron";
+ ot->idname = "MESH_OT_convex_hull";
- /* api callbacks */
- ot->exec = edbm_convex_hull_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_convex_hull_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "delete_unused", true,
- "Delete Unused",
- "Delete selected elements that are not used by the hull");
+ /* props */
+ RNA_def_boolean(ot->srna,
+ "delete_unused",
+ true,
+ "Delete Unused",
+ "Delete selected elements that are not used by the hull");
- RNA_def_boolean(ot->srna, "use_existing_faces", true,
- "Use Existing Faces",
- "Skip hull triangles that are covered by a pre-existing face");
+ RNA_def_boolean(ot->srna,
+ "use_existing_faces",
+ true,
+ "Use Existing Faces",
+ "Skip hull triangles that are covered by a pre-existing face");
- RNA_def_boolean(ot->srna, "make_holes", false,
- "Make Holes",
- "Delete selected faces that are used by the hull");
+ RNA_def_boolean(ot->srna,
+ "make_holes",
+ false,
+ "Make Holes",
+ "Delete selected faces that are used by the hull");
- RNA_def_boolean(ot->srna, "join_triangles", true,
- "Join Triangles",
- "Merge adjacent triangles into quads");
+ RNA_def_boolean(
+ ot->srna, "join_triangles", true, "Join Triangles", "Merge adjacent triangles into quads");
- join_triangle_props(ot);
+ join_triangle_props(ot);
}
-#endif /* WITH_BULLET */
+#endif /* WITH_BULLET */
/** \} */
@@ -6724,63 +7106,77 @@ void MESH_OT_convex_hull(wmOperatorType *ot)
static int mesh_symmetrize_exec(bContext *C, wmOperator *op)
{
- const float thresh = RNA_float_get(op->ptr, "threshold");
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
+ const float thresh = RNA_float_get(op->ptr, "threshold");
+ 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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->totvertsel == 0 ) {
- continue;
- }
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
- BMOperator bmop;
- EDBM_op_init(
- em, &bmop, op,
- "symmetrize input=%hvef direction=%i dist=%f",
- BM_ELEM_SELECT, RNA_enum_get(op->ptr, "direction"), thresh);
- BMO_op_exec(em->bm, &bmop);
+ BMOperator bmop;
+ EDBM_op_init(em,
+ &bmop,
+ op,
+ "symmetrize input=%hvef direction=%i dist=%f",
+ BM_ELEM_SELECT,
+ RNA_enum_get(op->ptr, "direction"),
+ thresh);
+ BMO_op_exec(em->bm, &bmop);
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
+ BMO_slot_buffer_hflag_enable(
+ em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
- else {
- EDBM_update_generic(em, true, true);
- EDBM_selectmode_flush(em);
- }
- }
- MEM_freeN(objects);
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
+ else {
+ EDBM_update_generic(em, true, true);
+ EDBM_selectmode_flush(em);
+ }
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_symmetrize(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Symmetrize";
- ot->description = "Enforce symmetry (both form and topological) across an axis";
- ot->idname = "MESH_OT_symmetrize";
-
- /* api callbacks */
- ot->exec = mesh_symmetrize_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ot->prop = RNA_def_enum(
- ot->srna, "direction", rna_enum_symmetrize_direction_items,
- BMO_SYMMETRIZE_NEGATIVE_X,
- "Direction", "Which sides to copy from and to");
- RNA_def_float(ot->srna, "threshold", 1e-4f, 0.0f, 10.0f, "Threshold",
- "Limit for snap middle vertices to the axis center", 1e-5f, 0.1f);
+ /* identifiers */
+ ot->name = "Symmetrize";
+ ot->description = "Enforce symmetry (both form and topological) across an axis";
+ ot->idname = "MESH_OT_symmetrize";
+
+ /* api callbacks */
+ ot->exec = mesh_symmetrize_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna,
+ "direction",
+ rna_enum_symmetrize_direction_items,
+ BMO_SYMMETRIZE_NEGATIVE_X,
+ "Direction",
+ "Which sides to copy from and to");
+ RNA_def_float(ot->srna,
+ "threshold",
+ 1e-4f,
+ 0.0f,
+ 10.0f,
+ "Threshold",
+ "Limit for snap middle vertices to the axis center",
+ 1e-5f,
+ 0.1f);
}
/** \} */
@@ -6791,142 +7187,166 @@ void MESH_OT_symmetrize(struct wmOperatorType *ot)
static int mesh_symmetry_snap_exec(bContext *C, wmOperator *op)
{
- const float eps = 0.00001f;
- const float eps_sq = eps * eps;
- const bool use_topology = false;
-
- const float thresh = RNA_float_get(op->ptr, "threshold");
- const float fac = RNA_float_get(op->ptr, "factor");
- const bool use_center = RNA_boolean_get(op->ptr, "use_center");
- const int axis_dir = RNA_enum_get(op->ptr, "direction");
-
- /* Vertices stats (total over all selected objects). */
- int totvertfound = 0, totvertmirr = 0, totvertfail = 0;
-
- /* Axis. */
- int axis = axis_dir % 3;
- bool axis_sign = axis != axis_dir;
-
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- if (em->bm->totvertsel == 0) {
- continue;
- }
-
- /* Only allocate memory after checking whether to skip object. */
- int *index = MEM_mallocN(bm->totvert * sizeof(*index), __func__);
-
- /* Vertex iter. */
- BMIter iter;
- BMVert *v;
- int i;
-
- EDBM_verts_mirror_cache_begin_ex(em, axis, true, true, use_topology, thresh, index);
-
- BM_mesh_elem_table_ensure(bm, BM_VERT);
-
- BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
-
- BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
- if ((BM_elem_flag_test(v, BM_ELEM_SELECT) != false) &&
- (BM_elem_flag_test(v, BM_ELEM_TAG) == false))
- {
- int i_mirr = index[i];
- if (i_mirr != -1) {
-
- BMVert *v_mirr = BM_vert_at_index(bm, index[i]);
-
- if (v != v_mirr) {
- float co[3], co_mirr[3];
-
- if ((v->co[axis] > v_mirr->co[axis]) == axis_sign) {
- SWAP(BMVert *, v, v_mirr);
- }
-
- copy_v3_v3(co_mirr, v_mirr->co);
- co_mirr[axis] *= -1.0f;
-
- if (len_squared_v3v3(v->co, co_mirr) > eps_sq) {
- totvertmirr++;
- }
-
- interp_v3_v3v3(co, v->co, co_mirr, fac);
+ const float eps = 0.00001f;
+ const float eps_sq = eps * eps;
+ const bool use_topology = false;
- copy_v3_v3(v->co, co);
-
- co[axis] *= -1.0f;
- copy_v3_v3(v_mirr->co, co);
-
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- BM_elem_flag_enable(v_mirr, BM_ELEM_TAG);
- totvertfound++;
- }
- else {
- if (use_center) {
-
- if (fabsf(v->co[axis]) > eps) {
- totvertmirr++;
- }
-
- v->co[axis] = 0.0f;
- }
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- totvertfound++;
- }
- }
- else {
- totvertfail++;
- }
- }
- }
-
- /* No need to end cache, just free the array. */
- MEM_freeN(index);
- }
- MEM_freeN(objects);
-
- if (totvertfail) {
- BKE_reportf(op->reports, RPT_WARNING, "%d already symmetrical, %d pairs mirrored, %d failed",
- totvertfound - totvertmirr, totvertmirr, totvertfail);
- }
- else {
- BKE_reportf(op->reports, RPT_INFO, "%d already symmetrical, %d pairs mirrored",
- totvertfound - totvertmirr, totvertmirr);
- }
-
- return OPERATOR_FINISHED;
+ const float thresh = RNA_float_get(op->ptr, "threshold");
+ const float fac = RNA_float_get(op->ptr, "factor");
+ const bool use_center = RNA_boolean_get(op->ptr, "use_center");
+ const int axis_dir = RNA_enum_get(op->ptr, "direction");
+
+ /* Vertices stats (total over all selected objects). */
+ int totvertfound = 0, totvertmirr = 0, totvertfail = 0;
+
+ /* Axis. */
+ int axis = axis_dir % 3;
+ bool axis_sign = axis != axis_dir;
+
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
+
+ /* Only allocate memory after checking whether to skip object. */
+ int *index = MEM_mallocN(bm->totvert * sizeof(*index), __func__);
+
+ /* Vertex iter. */
+ BMIter iter;
+ BMVert *v;
+ int i;
+
+ EDBM_verts_mirror_cache_begin_ex(em, axis, true, true, use_topology, thresh, index);
+
+ BM_mesh_elem_table_ensure(bm, BM_VERT);
+
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
+
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ if ((BM_elem_flag_test(v, BM_ELEM_SELECT) != false) &&
+ (BM_elem_flag_test(v, BM_ELEM_TAG) == false)) {
+ int i_mirr = index[i];
+ if (i_mirr != -1) {
+
+ BMVert *v_mirr = BM_vert_at_index(bm, index[i]);
+
+ if (v != v_mirr) {
+ float co[3], co_mirr[3];
+
+ if ((v->co[axis] > v_mirr->co[axis]) == axis_sign) {
+ SWAP(BMVert *, v, v_mirr);
+ }
+
+ copy_v3_v3(co_mirr, v_mirr->co);
+ co_mirr[axis] *= -1.0f;
+
+ if (len_squared_v3v3(v->co, co_mirr) > eps_sq) {
+ totvertmirr++;
+ }
+
+ interp_v3_v3v3(co, v->co, co_mirr, fac);
+
+ copy_v3_v3(v->co, co);
+
+ co[axis] *= -1.0f;
+ copy_v3_v3(v_mirr->co, co);
+
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ BM_elem_flag_enable(v_mirr, BM_ELEM_TAG);
+ totvertfound++;
+ }
+ else {
+ if (use_center) {
+
+ if (fabsf(v->co[axis]) > eps) {
+ totvertmirr++;
+ }
+
+ v->co[axis] = 0.0f;
+ }
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ totvertfound++;
+ }
+ }
+ else {
+ totvertfail++;
+ }
+ }
+ }
+
+ /* No need to end cache, just free the array. */
+ MEM_freeN(index);
+ }
+ MEM_freeN(objects);
+
+ if (totvertfail) {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "%d already symmetrical, %d pairs mirrored, %d failed",
+ totvertfound - totvertmirr,
+ totvertmirr,
+ totvertfail);
+ }
+ else {
+ BKE_reportf(op->reports,
+ RPT_INFO,
+ "%d already symmetrical, %d pairs mirrored",
+ totvertfound - totvertmirr,
+ totvertmirr);
+ }
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_symmetry_snap(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Snap to Symmetry";
- ot->description = "Snap vertex pairs to their mirrored locations";
- ot->idname = "MESH_OT_symmetry_snap";
-
- /* api callbacks */
- ot->exec = mesh_symmetry_snap_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ot->prop = RNA_def_enum(
- ot->srna, "direction", rna_enum_symmetrize_direction_items,
- BMO_SYMMETRIZE_NEGATIVE_X,
- "Direction", "Which sides to copy from and to");
- RNA_def_float_distance(ot->srna, "threshold", 0.05f, 0.0f, 10.0f, "Threshold",
- "Distance within which matching vertices are searched", 1e-4f, 1.0f);
- RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0f, "Factor",
- "Mix factor of the locations of the vertices", 0.0f, 1.0f);
- RNA_def_boolean(ot->srna, "use_center", true, "Center", "Snap middle vertices to the axis center");
+ /* identifiers */
+ ot->name = "Snap to Symmetry";
+ ot->description = "Snap vertex pairs to their mirrored locations";
+ ot->idname = "MESH_OT_symmetry_snap";
+
+ /* api callbacks */
+ ot->exec = mesh_symmetry_snap_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna,
+ "direction",
+ rna_enum_symmetrize_direction_items,
+ BMO_SYMMETRIZE_NEGATIVE_X,
+ "Direction",
+ "Which sides to copy from and to");
+ RNA_def_float_distance(ot->srna,
+ "threshold",
+ 0.05f,
+ 0.0f,
+ 10.0f,
+ "Threshold",
+ "Distance within which matching vertices are searched",
+ 1e-4f,
+ 1.0f);
+ RNA_def_float(ot->srna,
+ "factor",
+ 0.5f,
+ 0.0f,
+ 1.0f,
+ "Factor",
+ "Mix factor of the locations of the vertices",
+ 0.0f,
+ 1.0f);
+ RNA_def_boolean(
+ ot->srna, "use_center", true, "Center", "Snap middle vertices to the axis center");
}
/** \} */
@@ -6939,75 +7359,76 @@ void MESH_OT_symmetry_snap(struct wmOperatorType *ot)
static int edbm_mark_freestyle_edge_exec(bContext *C, wmOperator *op)
{
- BMEdge *eed;
- BMIter iter;
- FreestyleEdge *fed;
- const bool clear = RNA_boolean_get(op->ptr, "clear");
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em == NULL) {
- continue;
- }
-
- BMesh *bm = em->bm;
-
- if (bm->totedgesel == 0) {
- continue;
- }
-
- if (!CustomData_has_layer(&em->bm->edata, CD_FREESTYLE_EDGE)) {
- BM_data_layer_add(em->bm, &em->bm->edata, CD_FREESTYLE_EDGE);
- }
-
- if (clear) {
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT) && !BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- fed = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_FREESTYLE_EDGE);
- fed->flag &= ~FREESTYLE_EDGE_MARK;
- }
- }
- }
- else {
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT) && !BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- fed = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_FREESTYLE_EDGE);
- fed->flag |= FREESTYLE_EDGE_MARK;
- }
- }
- }
-
- DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ BMEdge *eed;
+ BMIter iter;
+ FreestyleEdge *fed;
+ const bool clear = RNA_boolean_get(op->ptr, "clear");
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em == NULL) {
+ continue;
+ }
+
+ BMesh *bm = em->bm;
+
+ if (bm->totedgesel == 0) {
+ continue;
+ }
+
+ if (!CustomData_has_layer(&em->bm->edata, CD_FREESTYLE_EDGE)) {
+ BM_data_layer_add(em->bm, &em->bm->edata, CD_FREESTYLE_EDGE);
+ }
+
+ if (clear) {
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT) && !BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+ fed = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_FREESTYLE_EDGE);
+ fed->flag &= ~FREESTYLE_EDGE_MARK;
+ }
+ }
+ }
+ else {
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT) && !BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+ fed = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_FREESTYLE_EDGE);
+ fed->flag |= FREESTYLE_EDGE_MARK;
+ }
+ }
+ }
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_mark_freestyle_edge(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Mark Freestyle Edge";
- ot->description = "(Un)mark selected edges as Freestyle feature edges";
- ot->idname = "MESH_OT_mark_freestyle_edge";
+ /* identifiers */
+ ot->name = "Mark Freestyle Edge";
+ ot->description = "(Un)mark selected edges as Freestyle feature edges";
+ ot->idname = "MESH_OT_mark_freestyle_edge";
- /* api callbacks */
- ot->exec = edbm_mark_freestyle_edge_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_mark_freestyle_edge_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/** \} */
@@ -7018,78 +7439,79 @@ void MESH_OT_mark_freestyle_edge(wmOperatorType *ot)
static int edbm_mark_freestyle_face_exec(bContext *C, wmOperator *op)
{
- BMFace *efa;
- BMIter iter;
- FreestyleFace *ffa;
- const bool clear = RNA_boolean_get(op->ptr, "clear");
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em == NULL) {
- continue;
- }
-
- if (em->bm->totfacesel == 0) {
- continue;
- }
-
- if (!CustomData_has_layer(&em->bm->pdata, CD_FREESTYLE_FACE)) {
- BM_data_layer_add(em->bm, &em->bm->pdata, CD_FREESTYLE_FACE);
- }
-
- if (clear) {
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- ffa = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_FREESTYLE_FACE);
- ffa->flag &= ~FREESTYLE_FACE_MARK;
- }
- }
- }
- else {
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- ffa = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_FREESTYLE_FACE);
- ffa->flag |= FREESTYLE_FACE_MARK;
- }
- }
- }
-
- DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ BMFace *efa;
+ BMIter iter;
+ FreestyleFace *ffa;
+ const bool clear = RNA_boolean_get(op->ptr, "clear");
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em == NULL) {
+ continue;
+ }
+
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
+
+ if (!CustomData_has_layer(&em->bm->pdata, CD_FREESTYLE_FACE)) {
+ BM_data_layer_add(em->bm, &em->bm->pdata, CD_FREESTYLE_FACE);
+ }
+
+ if (clear) {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ ffa = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_FREESTYLE_FACE);
+ ffa->flag &= ~FREESTYLE_FACE_MARK;
+ }
+ }
+ }
+ else {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ ffa = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_FREESTYLE_FACE);
+ ffa->flag |= FREESTYLE_FACE_MARK;
+ }
+ }
+ }
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_mark_freestyle_face(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Mark Freestyle Face";
- ot->description = "(Un)mark selected faces for exclusion from Freestyle feature edge detection";
- ot->idname = "MESH_OT_mark_freestyle_face";
+ /* identifiers */
+ ot->name = "Mark Freestyle Face";
+ ot->description = "(Un)mark selected faces for exclusion from Freestyle feature edge detection";
+ ot->idname = "MESH_OT_mark_freestyle_face";
- /* api callbacks */
- ot->exec = edbm_mark_freestyle_face_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_mark_freestyle_face_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/** \} */
-#endif /* WITH_FREESTYLE */
+#endif /* WITH_FREESTYLE */
/********************** Loop normals editing tools modal map. **********************/
@@ -7097,59 +7519,84 @@ void MESH_OT_mark_freestyle_face(wmOperatorType *ot)
/* NOTE: We could add more here, like e.g. a switch between local or global coordinates of target,
* use numinput to type in explicit vector values... */
enum {
- /* Generic commands. */
- EDBM_CLNOR_MODAL_CANCEL = 1,
- EDBM_CLNOR_MODAL_CONFIRM = 2,
-
- /* Point To operator. */
- EDBM_CLNOR_MODAL_POINTTO_RESET = 101,
- EDBM_CLNOR_MODAL_POINTTO_INVERT = 102,
- EDBM_CLNOR_MODAL_POINTTO_SPHERIZE = 103,
- EDBM_CLNOR_MODAL_POINTTO_ALIGN = 104,
-
- EDBM_CLNOR_MODAL_POINTTO_USE_MOUSE = 110,
- EDBM_CLNOR_MODAL_POINTTO_USE_PIVOT = 111,
- EDBM_CLNOR_MODAL_POINTTO_USE_OBJECT = 112,
- EDBM_CLNOR_MODAL_POINTTO_SET_USE_3DCURSOR = 113,
- EDBM_CLNOR_MODAL_POINTTO_SET_USE_SELECTED = 114,
+ /* Generic commands. */
+ EDBM_CLNOR_MODAL_CANCEL = 1,
+ EDBM_CLNOR_MODAL_CONFIRM = 2,
+
+ /* Point To operator. */
+ EDBM_CLNOR_MODAL_POINTTO_RESET = 101,
+ EDBM_CLNOR_MODAL_POINTTO_INVERT = 102,
+ EDBM_CLNOR_MODAL_POINTTO_SPHERIZE = 103,
+ EDBM_CLNOR_MODAL_POINTTO_ALIGN = 104,
+
+ EDBM_CLNOR_MODAL_POINTTO_USE_MOUSE = 110,
+ EDBM_CLNOR_MODAL_POINTTO_USE_PIVOT = 111,
+ EDBM_CLNOR_MODAL_POINTTO_USE_OBJECT = 112,
+ EDBM_CLNOR_MODAL_POINTTO_SET_USE_3DCURSOR = 113,
+ EDBM_CLNOR_MODAL_POINTTO_SET_USE_SELECTED = 114,
};
/* called in transform_ops.c, on each regeneration of keymaps */
wmKeyMap *point_normals_modal_keymap(wmKeyConfig *keyconf)
{
- static const EnumPropertyItem modal_items[] = {
- {EDBM_CLNOR_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
- {EDBM_CLNOR_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
-
- /* Point To operator. */
- {EDBM_CLNOR_MODAL_POINTTO_RESET, "RESET", 0, "Reset", "Reset normals to initial ones"},
- {EDBM_CLNOR_MODAL_POINTTO_INVERT, "INVERT", 0, "Invert", "Toggle inversion of affected normals"},
- {EDBM_CLNOR_MODAL_POINTTO_SPHERIZE, "SPHERIZE", 0, "Spherize", "Interpolate between new and original normals"},
- {EDBM_CLNOR_MODAL_POINTTO_ALIGN, "ALIGN", 0, "Align", "Make all affected normals parallel"},
-
- {EDBM_CLNOR_MODAL_POINTTO_USE_MOUSE, "USE_MOUSE", 0, "Use Mouse", "Follow mouse cursor position"},
- {EDBM_CLNOR_MODAL_POINTTO_USE_PIVOT, "USE_PIVOT", 0, "Use Pivot",
- "Use current rotation/scaling pivot point coordinates"},
- {EDBM_CLNOR_MODAL_POINTTO_USE_OBJECT, "USE_OBJECT", 0, "Use Object", "Use current edited object's location"},
- {EDBM_CLNOR_MODAL_POINTTO_SET_USE_3DCURSOR, "SET_USE_3DCURSOR", 0, "Set and Use 3D Cursor",
- "Set new 3D cursor position and use it"},
- {EDBM_CLNOR_MODAL_POINTTO_SET_USE_SELECTED, "SET_USE_SELECTED", 0, "Select and Use Mesh Item",
- "Select new active mesh element and use its location"},
- {0, NULL, 0, NULL, NULL},
- };
- static const char *keymap_name = "Custom Normals Modal Map";
-
- wmKeyMap *keymap = WM_modalkeymap_get(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);
-
- WM_modalkeymap_assign(keymap, "MESH_OT_point_normals");
-
- return keymap;
+ static const EnumPropertyItem modal_items[] = {
+ {EDBM_CLNOR_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
+ {EDBM_CLNOR_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+
+ /* Point To operator. */
+ {EDBM_CLNOR_MODAL_POINTTO_RESET, "RESET", 0, "Reset", "Reset normals to initial ones"},
+ {EDBM_CLNOR_MODAL_POINTTO_INVERT,
+ "INVERT",
+ 0,
+ "Invert",
+ "Toggle inversion of affected normals"},
+ {EDBM_CLNOR_MODAL_POINTTO_SPHERIZE,
+ "SPHERIZE",
+ 0,
+ "Spherize",
+ "Interpolate between new and original normals"},
+ {EDBM_CLNOR_MODAL_POINTTO_ALIGN, "ALIGN", 0, "Align", "Make all affected normals parallel"},
+
+ {EDBM_CLNOR_MODAL_POINTTO_USE_MOUSE,
+ "USE_MOUSE",
+ 0,
+ "Use Mouse",
+ "Follow mouse cursor position"},
+ {EDBM_CLNOR_MODAL_POINTTO_USE_PIVOT,
+ "USE_PIVOT",
+ 0,
+ "Use Pivot",
+ "Use current rotation/scaling pivot point coordinates"},
+ {EDBM_CLNOR_MODAL_POINTTO_USE_OBJECT,
+ "USE_OBJECT",
+ 0,
+ "Use Object",
+ "Use current edited object's location"},
+ {EDBM_CLNOR_MODAL_POINTTO_SET_USE_3DCURSOR,
+ "SET_USE_3DCURSOR",
+ 0,
+ "Set and Use 3D Cursor",
+ "Set new 3D cursor position and use it"},
+ {EDBM_CLNOR_MODAL_POINTTO_SET_USE_SELECTED,
+ "SET_USE_SELECTED",
+ 0,
+ "Select and Use Mesh Item",
+ "Select new active mesh element and use its location"},
+ {0, NULL, 0, NULL, NULL},
+ };
+ static const char *keymap_name = "Custom Normals Modal Map";
+
+ wmKeyMap *keymap = WM_modalkeymap_get(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);
+
+ WM_modalkeymap_assign(keymap, "MESH_OT_point_normals");
+
+ return keymap;
}
#define CLNORS_VALID_VEC_LEN (1e-4f)
@@ -7157,1260 +7604,1354 @@ wmKeyMap *point_normals_modal_keymap(wmKeyConfig *keyconf)
/********************** 'Point to' Loop Normals **********************/
enum {
- EDBM_CLNOR_POINTTO_MODE_COORDINATES = 1,
- EDBM_CLNOR_POINTTO_MODE_MOUSE = 2,
+ EDBM_CLNOR_POINTTO_MODE_COORDINATES = 1,
+ EDBM_CLNOR_POINTTO_MODE_MOUSE = 2,
};
static EnumPropertyItem clnors_pointto_mode_items[] = {
- {EDBM_CLNOR_POINTTO_MODE_COORDINATES, "COORDINATES", 0, "Coordinates",
- "Use static coordinates (defined by various means)"},
- {EDBM_CLNOR_POINTTO_MODE_MOUSE, "MOUSE", 0, "Mouse", "Follow mouse cursor"},
- {0, NULL, 0, NULL, NULL},
+ {EDBM_CLNOR_POINTTO_MODE_COORDINATES,
+ "COORDINATES",
+ 0,
+ "Coordinates",
+ "Use static coordinates (defined by various means)"},
+ {EDBM_CLNOR_POINTTO_MODE_MOUSE, "MOUSE", 0, "Mouse", "Follow mouse cursor"},
+ {0, NULL, 0, NULL, NULL},
};
/* Initialize loop normal data */
static int point_normals_init(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
- BKE_editmesh_lnorspace_update(em);
- BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
+ BKE_editmesh_lnorspace_update(em);
+ BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
- op->customdata = lnors_ed_arr;
+ op->customdata = lnors_ed_arr;
- return lnors_ed_arr->totloop;
+ return lnors_ed_arr->totloop;
}
static void point_normals_free(bContext *C, wmOperator *op)
{
- BMLoopNorEditDataArray *lnors_ed_arr = op->customdata;
- BM_loop_normal_editdata_array_free(lnors_ed_arr);
- op->customdata = NULL;
- ED_area_status_text(CTX_wm_area(C), NULL);
+ BMLoopNorEditDataArray *lnors_ed_arr = op->customdata;
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ op->customdata = NULL;
+ ED_area_status_text(CTX_wm_area(C), NULL);
}
static void point_normals_update_header(bContext *C, wmOperator *op)
{
- char header[UI_MAX_DRAW_STR];
- char buf[UI_MAX_DRAW_STR];
+ char header[UI_MAX_DRAW_STR];
+ char buf[UI_MAX_DRAW_STR];
- char *p = buf;
- int available_len = sizeof(buf);
+ char *p = buf;
+ int available_len = sizeof(buf);
#define WM_MODALKEY(_id) \
- WM_modalkeymap_operator_items_to_string_buf(op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p)
-
- BLI_snprintf(header, sizeof(header), IFACE_("%s: confirm, %s: cancel, "
- "%s: point to mouse (%s), %s: point to Pivot, "
- "%s: point to object origin, %s: reset normals, "
- "%s: set & point to 3D cursor, %s: select & point to mesh item, "
- "%s: invert normals (%s), %s: spherize (%s), %s: align (%s)"),
- WM_MODALKEY(EDBM_CLNOR_MODAL_CONFIRM), WM_MODALKEY(EDBM_CLNOR_MODAL_CANCEL),
- WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_USE_MOUSE),
- WM_bool_as_string(RNA_enum_get(op->ptr, "mode") == EDBM_CLNOR_POINTTO_MODE_MOUSE),
- WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_USE_PIVOT), WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_USE_OBJECT),
- WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_RESET), WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_SET_USE_3DCURSOR),
- WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_SET_USE_SELECTED),
- WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_INVERT), WM_bool_as_string(RNA_boolean_get(op->ptr, "invert")),
- WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_SPHERIZE),
- WM_bool_as_string(RNA_boolean_get(op->ptr, "spherize")),
- WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_ALIGN), WM_bool_as_string(RNA_boolean_get(op->ptr, "align")));
+ WM_modalkeymap_operator_items_to_string_buf( \
+ op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p)
+
+ BLI_snprintf(header,
+ sizeof(header),
+ IFACE_("%s: confirm, %s: cancel, "
+ "%s: point to mouse (%s), %s: point to Pivot, "
+ "%s: point to object origin, %s: reset normals, "
+ "%s: set & point to 3D cursor, %s: select & point to mesh item, "
+ "%s: invert normals (%s), %s: spherize (%s), %s: align (%s)"),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_CONFIRM),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_CANCEL),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_USE_MOUSE),
+ WM_bool_as_string(RNA_enum_get(op->ptr, "mode") == EDBM_CLNOR_POINTTO_MODE_MOUSE),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_USE_PIVOT),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_USE_OBJECT),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_RESET),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_SET_USE_3DCURSOR),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_SET_USE_SELECTED),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_INVERT),
+ WM_bool_as_string(RNA_boolean_get(op->ptr, "invert")),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_SPHERIZE),
+ WM_bool_as_string(RNA_boolean_get(op->ptr, "spherize")),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_ALIGN),
+ WM_bool_as_string(RNA_boolean_get(op->ptr, "align")));
#undef WM_MODALKEY
- ED_area_status_text(CTX_wm_area(C), header);
+ ED_area_status_text(CTX_wm_area(C), header);
}
/* TODO move that to generic function in BMesh? */
static void bmesh_selected_verts_center_calc(BMesh *bm, float *r_center)
{
- BMVert *v;
- BMIter viter;
- int i = 0;
+ BMVert *v;
+ BMIter viter;
+ int i = 0;
- zero_v3(r_center);
- BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- add_v3_v3(r_center, v->co);
- i++;
- }
- }
- mul_v3_fl(r_center, 1.0f / (float)i);
+ zero_v3(r_center);
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ add_v3_v3(r_center, v->co);
+ i++;
+ }
+ }
+ mul_v3_fl(r_center, 1.0f / (float)i);
}
static void point_normals_apply(bContext *C, wmOperator *op, float target[3], const bool do_reset)
{
- Object *obedit = CTX_data_edit_object(C);
- BMesh *bm = BKE_editmesh_from_object(obedit)->bm;
- BMLoopNorEditDataArray *lnors_ed_arr = op->customdata;
-
- const bool do_invert = RNA_boolean_get(op->ptr, "invert");
- const bool do_spherize = RNA_boolean_get(op->ptr, "spherize");
- const bool do_align = RNA_boolean_get(op->ptr, "align");
- float center[3];
-
- if (do_align && !do_reset) {
- bmesh_selected_verts_center_calc(bm, center);
- }
-
- sub_v3_v3(target, obedit->loc); /* Move target to local coordinates. */
-
- BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- if (do_reset) {
- copy_v3_v3(lnor_ed->nloc, lnor_ed->niloc);
- }
- else if (do_spherize) {
- /* Note that this is *not* real spherical interpolation. Probably good enough in this case though? */
- const float strength = RNA_float_get(op->ptr, "spherize_strength");
- float spherized_normal[3];
-
- sub_v3_v3v3(spherized_normal, target, lnor_ed->loc);
-
- /* otherwise, multiplication by strength is meaningless... */
- normalize_v3(spherized_normal);
-
- mul_v3_fl(spherized_normal, strength);
- mul_v3_v3fl(lnor_ed->nloc, lnor_ed->niloc, 1.0f - strength);
- add_v3_v3(lnor_ed->nloc, spherized_normal);
- }
- else if (do_align) {
- sub_v3_v3v3(lnor_ed->nloc, target, center);
- }
- else {
- sub_v3_v3v3(lnor_ed->nloc, target, lnor_ed->loc);
- }
-
- if (do_invert && !do_reset) {
- negate_v3(lnor_ed->nloc);
- }
- if (normalize_v3(lnor_ed->nloc) >= CLNORS_VALID_VEC_LEN) {
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->nloc, lnor_ed->clnors_data);
- }
- }
+ Object *obedit = CTX_data_edit_object(C);
+ BMesh *bm = BKE_editmesh_from_object(obedit)->bm;
+ BMLoopNorEditDataArray *lnors_ed_arr = op->customdata;
+
+ const bool do_invert = RNA_boolean_get(op->ptr, "invert");
+ const bool do_spherize = RNA_boolean_get(op->ptr, "spherize");
+ const bool do_align = RNA_boolean_get(op->ptr, "align");
+ float center[3];
+
+ if (do_align && !do_reset) {
+ bmesh_selected_verts_center_calc(bm, center);
+ }
+
+ sub_v3_v3(target, obedit->loc); /* Move target to local coordinates. */
+
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ if (do_reset) {
+ copy_v3_v3(lnor_ed->nloc, lnor_ed->niloc);
+ }
+ else if (do_spherize) {
+ /* Note that this is *not* real spherical interpolation. Probably good enough in this case though? */
+ const float strength = RNA_float_get(op->ptr, "spherize_strength");
+ float spherized_normal[3];
+
+ sub_v3_v3v3(spherized_normal, target, lnor_ed->loc);
+
+ /* otherwise, multiplication by strength is meaningless... */
+ normalize_v3(spherized_normal);
+
+ mul_v3_fl(spherized_normal, strength);
+ mul_v3_v3fl(lnor_ed->nloc, lnor_ed->niloc, 1.0f - strength);
+ add_v3_v3(lnor_ed->nloc, spherized_normal);
+ }
+ else if (do_align) {
+ sub_v3_v3v3(lnor_ed->nloc, target, center);
+ }
+ else {
+ sub_v3_v3v3(lnor_ed->nloc, target, lnor_ed->loc);
+ }
+
+ if (do_invert && !do_reset) {
+ negate_v3(lnor_ed->nloc);
+ }
+ if (normalize_v3(lnor_ed->nloc) >= CLNORS_VALID_VEC_LEN) {
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->nloc, lnor_ed->clnors_data);
+ }
+ }
}
static int edbm_point_normals_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- View3D *v3d = CTX_wm_view3d(C);
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- float target[3];
-
- int ret = OPERATOR_PASS_THROUGH;
- int mode = RNA_enum_get(op->ptr, "mode");
- int new_mode = mode;
- bool force_mousemove = false;
- bool do_reset = false;
-
- PropertyRNA *prop_target = RNA_struct_find_property(op->ptr, "target_location");
-
- if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case EDBM_CLNOR_MODAL_CONFIRM:
- RNA_property_float_get_array(op->ptr, prop_target, target);
- ret = OPERATOR_FINISHED;
- break;
-
- case EDBM_CLNOR_MODAL_CANCEL:
- do_reset = true;
- ret = OPERATOR_CANCELLED;
- break;
-
- case EDBM_CLNOR_MODAL_POINTTO_RESET:
- do_reset = true;
- ret = OPERATOR_RUNNING_MODAL;
- break;
-
- case EDBM_CLNOR_MODAL_POINTTO_INVERT:
- {
- PropertyRNA *prop_invert = RNA_struct_find_property(op->ptr, "invert");
- RNA_property_boolean_set(op->ptr, prop_invert, !RNA_property_boolean_get(op->ptr, prop_invert));
- RNA_property_float_get_array(op->ptr, prop_target, target);
- ret = OPERATOR_RUNNING_MODAL;
- break;
- }
-
- case EDBM_CLNOR_MODAL_POINTTO_SPHERIZE:
- {
- PropertyRNA *prop_spherize = RNA_struct_find_property(op->ptr, "spherize");
- RNA_property_boolean_set(op->ptr, prop_spherize, !RNA_property_boolean_get(op->ptr, prop_spherize));
- RNA_property_float_get_array(op->ptr, prop_target, target);
- ret = OPERATOR_RUNNING_MODAL;
- break;
- }
-
- case EDBM_CLNOR_MODAL_POINTTO_ALIGN:
- {
- PropertyRNA *prop_align = RNA_struct_find_property(op->ptr, "align");
- RNA_property_boolean_set(op->ptr, prop_align, !RNA_property_boolean_get(op->ptr, prop_align));
- RNA_property_float_get_array(op->ptr, prop_target, target);
- ret = OPERATOR_RUNNING_MODAL;
- break;
- }
-
- case EDBM_CLNOR_MODAL_POINTTO_USE_MOUSE:
- new_mode = EDBM_CLNOR_POINTTO_MODE_MOUSE;
- /* We want to immediately update to mouse cursor position... */
- force_mousemove = true;
- ret = OPERATOR_RUNNING_MODAL;
- break;
-
- case EDBM_CLNOR_MODAL_POINTTO_USE_OBJECT:
- new_mode = EDBM_CLNOR_POINTTO_MODE_COORDINATES;
- copy_v3_v3(target, obedit->loc);
- ret = OPERATOR_RUNNING_MODAL;
- break;
-
- case EDBM_CLNOR_MODAL_POINTTO_SET_USE_3DCURSOR:
- new_mode = EDBM_CLNOR_POINTTO_MODE_COORDINATES;
- ED_view3d_cursor3d_update(C, event->mval, false, V3D_CURSOR_ORIENT_NONE);
- copy_v3_v3(target, scene->cursor.location);
- ret = OPERATOR_RUNNING_MODAL;
- break;
-
- case EDBM_CLNOR_MODAL_POINTTO_SET_USE_SELECTED:
- new_mode = EDBM_CLNOR_POINTTO_MODE_COORDINATES;
- view3d_operator_needs_opengl(C);
- if (EDBM_select_pick(C, event->mval, false, false, false)) {
- /* Point to newly selected active. */
- ED_object_calc_active_center_for_editmode(obedit, false, target);
-
- add_v3_v3(target, obedit->loc);
- ret = OPERATOR_RUNNING_MODAL;
- }
- break;
-
- case EDBM_CLNOR_MODAL_POINTTO_USE_PIVOT:
- new_mode = EDBM_CLNOR_POINTTO_MODE_COORDINATES;
- switch (scene->toolsettings->transform_pivot_point) {
- case V3D_AROUND_CENTER_BOUNDS: /* calculateCenterBound */
- {
- BMVert *v;
- BMIter viter;
- float min[3], max[3];
- int i = 0;
-
- BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- if (i) {
- minmax_v3v3_v3(min, max, v->co);
- }
- else {
- copy_v3_v3(min, v->co);
- copy_v3_v3(max, v->co);
- }
- i++;
- }
- }
- mid_v3_v3v3(target, min, max);
- add_v3_v3(target, obedit->loc);
- break;
- }
-
- case V3D_AROUND_CENTER_MEDIAN:
- {
- bmesh_selected_verts_center_calc(bm, target);
- add_v3_v3(target, obedit->loc);
- break;
- }
-
- case V3D_AROUND_CURSOR:
- copy_v3_v3(target, scene->cursor.location);
- break;
-
- case V3D_AROUND_ACTIVE:
- if (!ED_object_calc_active_center_for_editmode(obedit, false, target)) {
- zero_v3(target);
- }
- add_v3_v3(target, obedit->loc);
- break;
-
- default:
- BKE_report(op->reports, RPT_WARNING, "Does not support Individual Origin as pivot");
- copy_v3_v3(target, obedit->loc);
- }
- ret = OPERATOR_RUNNING_MODAL;
- break;
- default:
- break;
- }
- }
-
- if (new_mode != mode) {
- mode = new_mode;
- RNA_enum_set(op->ptr, "mode", mode);
- }
-
- /* 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);
- float center[3];
-
- bmesh_selected_verts_center_calc(bm, center);
-
- ED_view3d_win_to_3d_int(v3d, ar, center, event->mval, target);
-
- ret = OPERATOR_RUNNING_MODAL;
- }
- }
-
- if (ret != OPERATOR_PASS_THROUGH) {
- 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(em, true, false); /* Recheck bools. */
-
- point_normals_update_header(C, op);
- }
-
- if (ELEM(ret, OPERATOR_CANCELLED, OPERATOR_FINISHED)) {
- point_normals_free(C, op);
- }
-
- return ret;
+ View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ float target[3];
+
+ int ret = OPERATOR_PASS_THROUGH;
+ int mode = RNA_enum_get(op->ptr, "mode");
+ int new_mode = mode;
+ bool force_mousemove = false;
+ bool do_reset = false;
+
+ PropertyRNA *prop_target = RNA_struct_find_property(op->ptr, "target_location");
+
+ if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case EDBM_CLNOR_MODAL_CONFIRM:
+ RNA_property_float_get_array(op->ptr, prop_target, target);
+ ret = OPERATOR_FINISHED;
+ break;
+
+ case EDBM_CLNOR_MODAL_CANCEL:
+ do_reset = true;
+ ret = OPERATOR_CANCELLED;
+ break;
+
+ case EDBM_CLNOR_MODAL_POINTTO_RESET:
+ do_reset = true;
+ ret = OPERATOR_RUNNING_MODAL;
+ break;
+
+ case EDBM_CLNOR_MODAL_POINTTO_INVERT: {
+ PropertyRNA *prop_invert = RNA_struct_find_property(op->ptr, "invert");
+ RNA_property_boolean_set(
+ op->ptr, prop_invert, !RNA_property_boolean_get(op->ptr, prop_invert));
+ RNA_property_float_get_array(op->ptr, prop_target, target);
+ ret = OPERATOR_RUNNING_MODAL;
+ break;
+ }
+
+ case EDBM_CLNOR_MODAL_POINTTO_SPHERIZE: {
+ PropertyRNA *prop_spherize = RNA_struct_find_property(op->ptr, "spherize");
+ RNA_property_boolean_set(
+ op->ptr, prop_spherize, !RNA_property_boolean_get(op->ptr, prop_spherize));
+ RNA_property_float_get_array(op->ptr, prop_target, target);
+ ret = OPERATOR_RUNNING_MODAL;
+ break;
+ }
+
+ case EDBM_CLNOR_MODAL_POINTTO_ALIGN: {
+ PropertyRNA *prop_align = RNA_struct_find_property(op->ptr, "align");
+ RNA_property_boolean_set(
+ op->ptr, prop_align, !RNA_property_boolean_get(op->ptr, prop_align));
+ RNA_property_float_get_array(op->ptr, prop_target, target);
+ ret = OPERATOR_RUNNING_MODAL;
+ break;
+ }
+
+ case EDBM_CLNOR_MODAL_POINTTO_USE_MOUSE:
+ new_mode = EDBM_CLNOR_POINTTO_MODE_MOUSE;
+ /* We want to immediately update to mouse cursor position... */
+ force_mousemove = true;
+ ret = OPERATOR_RUNNING_MODAL;
+ break;
+
+ case EDBM_CLNOR_MODAL_POINTTO_USE_OBJECT:
+ new_mode = EDBM_CLNOR_POINTTO_MODE_COORDINATES;
+ copy_v3_v3(target, obedit->loc);
+ ret = OPERATOR_RUNNING_MODAL;
+ break;
+
+ case EDBM_CLNOR_MODAL_POINTTO_SET_USE_3DCURSOR:
+ new_mode = EDBM_CLNOR_POINTTO_MODE_COORDINATES;
+ ED_view3d_cursor3d_update(C, event->mval, false, V3D_CURSOR_ORIENT_NONE);
+ copy_v3_v3(target, scene->cursor.location);
+ ret = OPERATOR_RUNNING_MODAL;
+ break;
+
+ case EDBM_CLNOR_MODAL_POINTTO_SET_USE_SELECTED:
+ new_mode = EDBM_CLNOR_POINTTO_MODE_COORDINATES;
+ view3d_operator_needs_opengl(C);
+ if (EDBM_select_pick(C, event->mval, false, false, false)) {
+ /* Point to newly selected active. */
+ ED_object_calc_active_center_for_editmode(obedit, false, target);
+
+ add_v3_v3(target, obedit->loc);
+ ret = OPERATOR_RUNNING_MODAL;
+ }
+ break;
+
+ case EDBM_CLNOR_MODAL_POINTTO_USE_PIVOT:
+ new_mode = EDBM_CLNOR_POINTTO_MODE_COORDINATES;
+ switch (scene->toolsettings->transform_pivot_point) {
+ case V3D_AROUND_CENTER_BOUNDS: /* calculateCenterBound */
+ {
+ BMVert *v;
+ BMIter viter;
+ float min[3], max[3];
+ int i = 0;
+
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ if (i) {
+ minmax_v3v3_v3(min, max, v->co);
+ }
+ else {
+ copy_v3_v3(min, v->co);
+ copy_v3_v3(max, v->co);
+ }
+ i++;
+ }
+ }
+ mid_v3_v3v3(target, min, max);
+ add_v3_v3(target, obedit->loc);
+ break;
+ }
+
+ case V3D_AROUND_CENTER_MEDIAN: {
+ bmesh_selected_verts_center_calc(bm, target);
+ add_v3_v3(target, obedit->loc);
+ break;
+ }
+
+ case V3D_AROUND_CURSOR:
+ copy_v3_v3(target, scene->cursor.location);
+ break;
+
+ case V3D_AROUND_ACTIVE:
+ if (!ED_object_calc_active_center_for_editmode(obedit, false, target)) {
+ zero_v3(target);
+ }
+ add_v3_v3(target, obedit->loc);
+ break;
+
+ default:
+ BKE_report(op->reports, RPT_WARNING, "Does not support Individual Origin as pivot");
+ copy_v3_v3(target, obedit->loc);
+ }
+ ret = OPERATOR_RUNNING_MODAL;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (new_mode != mode) {
+ mode = new_mode;
+ RNA_enum_set(op->ptr, "mode", mode);
+ }
+
+ /* 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);
+ float center[3];
+
+ bmesh_selected_verts_center_calc(bm, center);
+
+ ED_view3d_win_to_3d_int(v3d, ar, center, event->mval, target);
+
+ ret = OPERATOR_RUNNING_MODAL;
+ }
+ }
+
+ if (ret != OPERATOR_PASS_THROUGH) {
+ 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(em, true, false); /* Recheck bools. */
+
+ point_normals_update_header(C, op);
+ }
+
+ if (ELEM(ret, OPERATOR_CANCELLED, OPERATOR_FINISHED)) {
+ point_normals_free(C, op);
+ }
+
+ return ret;
}
static int edbm_point_normals_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (!point_normals_init(C, op, event)) {
- point_normals_free(C, op);
- return OPERATOR_CANCELLED;
- }
+ if (!point_normals_init(C, op, event)) {
+ point_normals_free(C, op);
+ return OPERATOR_CANCELLED;
+ }
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
- point_normals_update_header(C, op);
+ point_normals_update_header(C, op);
- op->flag |= OP_IS_MODAL_GRAB_CURSOR;
- return OPERATOR_RUNNING_MODAL;
+ op->flag |= OP_IS_MODAL_GRAB_CURSOR;
+ return OPERATOR_RUNNING_MODAL;
}
static int edbm_point_normals_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (!point_normals_init(C, op, NULL)) {
- point_normals_free(C, op);
- return OPERATOR_CANCELLED;
- }
+ if (!point_normals_init(C, op, NULL)) {
+ point_normals_free(C, op);
+ return OPERATOR_CANCELLED;
+ }
- /* Note that 'mode' is ignored in exec case,
- * we directly use vector stored in target_location, whatever that is. */
+ /* Note that 'mode' is ignored in exec case,
+ * we directly use vector stored in target_location, whatever that is. */
- float target[3];
- RNA_float_get_array(op->ptr, "target_location", target);
+ float target[3];
+ RNA_float_get_array(op->ptr, "target_location", target);
- point_normals_apply(C, op, target, false);
+ point_normals_apply(C, op, target, false);
- EDBM_update_generic(em, true, false);
- point_normals_free(C, op);
+ EDBM_update_generic(em, true, false);
+ point_normals_free(C, op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static bool point_normals_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop, void *UNUSED(user_data))
+static bool point_normals_draw_check_prop(PointerRNA *ptr,
+ PropertyRNA *prop,
+ void *UNUSED(user_data))
{
- const char *prop_id = RNA_property_identifier(prop);
+ const char *prop_id = RNA_property_identifier(prop);
- /* Only show strength option if spherize is enabled. */
- if (STREQ(prop_id, "spherize_strength")) {
- return (bool)RNA_boolean_get(ptr, "spherize");
- }
+ /* Only show strength option if spherize is enabled. */
+ if (STREQ(prop_id, "spherize_strength")) {
+ return (bool)RNA_boolean_get(ptr, "spherize");
+ }
- /* Else, show it! */
- return true;
+ /* Else, show it! */
+ return true;
}
static void edbm_point_normals_ui(bContext *C, wmOperator *op)
{
- uiLayout *layout = op->layout;
- wmWindowManager *wm = CTX_wm_manager(C);
- PointerRNA ptr;
+ uiLayout *layout = op->layout;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ PointerRNA ptr;
- RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+ RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
- /* Main auto-draw call */
- uiDefAutoButsRNA(layout, &ptr, point_normals_draw_check_prop, NULL, NULL, '\0', false);
+ /* Main auto-draw call */
+ uiDefAutoButsRNA(layout, &ptr, point_normals_draw_check_prop, NULL, NULL, '\0', false);
}
void MESH_OT_point_normals(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Point Normals to Target";
- ot->description = "Point selected custom normals to specified Target";
- ot->idname = "MESH_OT_point_normals";
-
- /* api callbacks */
- ot->exec = edbm_point_normals_exec;
- ot->invoke = edbm_point_normals_invoke;
- ot->modal = edbm_point_normals_modal;
- ot->poll = ED_operator_editmesh_auto_smooth;
- ot->ui = edbm_point_normals_ui;
- ot->cancel = point_normals_free;
-
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ot->prop = RNA_def_enum(ot->srna, "mode", clnors_pointto_mode_items, EDBM_CLNOR_POINTTO_MODE_COORDINATES,
- "Mode", "How to define coordinates to point custom normals to");
- RNA_def_property_flag(ot->prop, PROP_HIDDEN);
-
- RNA_def_boolean(ot->srna, "invert", false, "Invert", "Invert affected normals");
-
- RNA_def_boolean(ot->srna, "align", false, "Align", "Make all affected normals parallel");
-
- RNA_def_float_vector_xyz(ot->srna, "target_location", 3, NULL, -FLT_MAX, FLT_MAX,
- "Target", "Target location to which normals will point", -1000.0f, 1000.0f);
-
- RNA_def_boolean(ot->srna, "spherize", false,
- "Spherize", "Interpolate between original and new normals");
-
- RNA_def_float(ot->srna, "spherize_strength", 0.1, 0.0f, 1.0f,
- "Spherize Strength", "Ratio of spherized normal to original normal", 0.0f, 1.0f);
+ /* identifiers */
+ ot->name = "Point Normals to Target";
+ ot->description = "Point selected custom normals to specified Target";
+ ot->idname = "MESH_OT_point_normals";
+
+ /* api callbacks */
+ ot->exec = edbm_point_normals_exec;
+ ot->invoke = edbm_point_normals_invoke;
+ ot->modal = edbm_point_normals_modal;
+ ot->poll = ED_operator_editmesh_auto_smooth;
+ ot->ui = edbm_point_normals_ui;
+ ot->cancel = point_normals_free;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna,
+ "mode",
+ clnors_pointto_mode_items,
+ EDBM_CLNOR_POINTTO_MODE_COORDINATES,
+ "Mode",
+ "How to define coordinates to point custom normals to");
+ RNA_def_property_flag(ot->prop, PROP_HIDDEN);
+
+ RNA_def_boolean(ot->srna, "invert", false, "Invert", "Invert affected normals");
+
+ RNA_def_boolean(ot->srna, "align", false, "Align", "Make all affected normals parallel");
+
+ RNA_def_float_vector_xyz(ot->srna,
+ "target_location",
+ 3,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Target",
+ "Target location to which normals will point",
+ -1000.0f,
+ 1000.0f);
+
+ RNA_def_boolean(
+ ot->srna, "spherize", false, "Spherize", "Interpolate between original and new normals");
+
+ RNA_def_float(ot->srna,
+ "spherize_strength",
+ 0.1,
+ 0.0f,
+ 1.0f,
+ "Spherize Strength",
+ "Ratio of spherized normal to original normal",
+ 0.0f,
+ 1.0f);
}
/********************** Split/Merge Loop Normals **********************/
static void normals_merge(BMesh *bm, BMLoopNorEditDataArray *lnors_ed_arr)
{
- BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
- BLI_SMALLSTACK_DECLARE(clnors, short *);
+ BLI_SMALLSTACK_DECLARE(clnors, short *);
- BLI_assert(bm->lnor_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR);
+ BLI_assert(bm->lnor_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR);
- BM_normals_loops_edges_tag(bm, false);
+ BM_normals_loops_edges_tag(bm, false);
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- if (BM_elem_flag_test(lnor_ed->loop, BM_ELEM_TAG)) {
- continue;
- }
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ if (BM_elem_flag_test(lnor_ed->loop, BM_ELEM_TAG)) {
+ continue;
+ }
- MLoopNorSpace *lnor_space = bm->lnor_spacearr->lspacearr[lnor_ed->loop_index];
+ MLoopNorSpace *lnor_space = bm->lnor_spacearr->lspacearr[lnor_ed->loop_index];
- if ((lnor_space->flags & MLNOR_SPACE_IS_SINGLE) == 0) {
- LinkNode *loops = lnor_space->loops;
- float avg_normal[3] = {0.0f, 0.0f, 0.0f};
- short *clnors_data;
+ if ((lnor_space->flags & MLNOR_SPACE_IS_SINGLE) == 0) {
+ LinkNode *loops = lnor_space->loops;
+ float avg_normal[3] = {0.0f, 0.0f, 0.0f};
+ short *clnors_data;
- for (; loops; loops = loops->next) {
- BMLoop *l = loops->link;
- const int loop_index = BM_elem_index_get(l);
+ for (; loops; loops = loops->next) {
+ BMLoop *l = loops->link;
+ const int loop_index = BM_elem_index_get(l);
- BMLoopNorEditData *lnor_ed_tmp = lnors_ed_arr->lidx_to_lnor_editdata[loop_index];
- BLI_assert(lnor_ed_tmp->loop_index == loop_index && lnor_ed_tmp->loop == l);
- add_v3_v3(avg_normal, lnor_ed_tmp->nloc);
- BLI_SMALLSTACK_PUSH(clnors, lnor_ed_tmp->clnors_data);
- BM_elem_flag_enable(l, BM_ELEM_TAG);
- }
- if (normalize_v3(avg_normal) < CLNORS_VALID_VEC_LEN) {
- /* If avg normal is nearly 0, set clnor to default value. */
- zero_v3(avg_normal);
- }
- while ((clnors_data = BLI_SMALLSTACK_POP(clnors))) {
- BKE_lnor_space_custom_normal_to_data(lnor_space, avg_normal, clnors_data);
- }
- }
- }
+ BMLoopNorEditData *lnor_ed_tmp = lnors_ed_arr->lidx_to_lnor_editdata[loop_index];
+ BLI_assert(lnor_ed_tmp->loop_index == loop_index && lnor_ed_tmp->loop == l);
+ add_v3_v3(avg_normal, lnor_ed_tmp->nloc);
+ BLI_SMALLSTACK_PUSH(clnors, lnor_ed_tmp->clnors_data);
+ BM_elem_flag_enable(l, BM_ELEM_TAG);
+ }
+ if (normalize_v3(avg_normal) < CLNORS_VALID_VEC_LEN) {
+ /* If avg normal is nearly 0, set clnor to default value. */
+ zero_v3(avg_normal);
+ }
+ while ((clnors_data = BLI_SMALLSTACK_POP(clnors))) {
+ BKE_lnor_space_custom_normal_to_data(lnor_space, avg_normal, clnors_data);
+ }
+ }
+ }
}
static void normals_split(BMesh *bm)
{
- BMFace *f;
- BMLoop *l, *l_curr, *l_first;
- BMIter fiter;
-
- BLI_assert(bm->lnor_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR);
-
- BM_normals_loops_edges_tag(bm, true);
-
- const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
- BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
- l_curr = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (BM_elem_flag_test(l_curr->v, BM_ELEM_SELECT) && (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) ||
- (!BM_elem_flag_test(l_curr, BM_ELEM_TAG) && BM_loop_check_cyclic_smooth_fan(l_curr))))
- {
- if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) && !BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG)) {
- const int loop_index = BM_elem_index_get(l_curr);
- short *clnors = BM_ELEM_CD_GET_VOID_P(l_curr, cd_clnors_offset);
- BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[loop_index], f->no, clnors);
- }
- else {
- BMVert *v_pivot = l_curr->v;
- UNUSED_VARS_NDEBUG(v_pivot);
- BMEdge *e_next;
- const BMEdge *e_org = l_curr->e;
- BMLoop *lfan_pivot, *lfan_pivot_next;
-
- lfan_pivot = l_curr;
- e_next = lfan_pivot->e;
- BLI_SMALLSTACK_DECLARE(loops, BMLoop *);
- float avg_normal[3] = { 0.0f };
-
- while (true) {
- lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot, &e_next);
- if (lfan_pivot_next) {
- BLI_assert(lfan_pivot_next->v == v_pivot);
- }
- else {
- e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
- }
-
- BLI_SMALLSTACK_PUSH(loops, 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)) {
- break;
- }
- lfan_pivot = lfan_pivot_next;
- }
- if (normalize_v3(avg_normal) < CLNORS_VALID_VEC_LEN) {
- /* If avg normal is nearly 0, set clnor to default value. */
- zero_v3(avg_normal);
- }
- while ((l = BLI_SMALLSTACK_POP(loops))) {
- const int l_index = BM_elem_index_get(l);
- short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
- BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[l_index], avg_normal, clnors);
- }
- }
- }
- } while ((l_curr = l_curr->next) != l_first);
- }
+ BMFace *f;
+ BMLoop *l, *l_curr, *l_first;
+ BMIter fiter;
+
+ BLI_assert(bm->lnor_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR);
+
+ BM_normals_loops_edges_tag(bm, true);
+
+ const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ l_curr = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BM_elem_flag_test(l_curr->v, BM_ELEM_SELECT) &&
+ (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) ||
+ (!BM_elem_flag_test(l_curr, BM_ELEM_TAG) && BM_loop_check_cyclic_smooth_fan(l_curr)))) {
+ if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
+ !BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG)) {
+ const int loop_index = BM_elem_index_get(l_curr);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l_curr, cd_clnors_offset);
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[loop_index], f->no, clnors);
+ }
+ else {
+ BMVert *v_pivot = l_curr->v;
+ UNUSED_VARS_NDEBUG(v_pivot);
+ BMEdge *e_next;
+ const BMEdge *e_org = l_curr->e;
+ BMLoop *lfan_pivot, *lfan_pivot_next;
+
+ lfan_pivot = l_curr;
+ e_next = lfan_pivot->e;
+ BLI_SMALLSTACK_DECLARE(loops, BMLoop *);
+ float avg_normal[3] = {0.0f};
+
+ while (true) {
+ lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot, &e_next);
+ if (lfan_pivot_next) {
+ BLI_assert(lfan_pivot_next->v == v_pivot);
+ }
+ else {
+ e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
+ }
+
+ BLI_SMALLSTACK_PUSH(loops, 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)) {
+ break;
+ }
+ lfan_pivot = lfan_pivot_next;
+ }
+ if (normalize_v3(avg_normal) < CLNORS_VALID_VEC_LEN) {
+ /* If avg normal is nearly 0, set clnor to default value. */
+ zero_v3(avg_normal);
+ }
+ while ((l = BLI_SMALLSTACK_POP(loops))) {
+ const int l_index = BM_elem_index_get(l);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[l_index], avg_normal, clnors);
+ }
+ }
+ }
+ } while ((l_curr = l_curr->next) != l_first);
+ }
}
static int normals_split_merge(bContext *C, const bool do_merge)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMEdge *e;
- BMIter eiter;
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMEdge *e;
+ BMIter eiter;
- BKE_editmesh_lnorspace_update(em);
+ BKE_editmesh_lnorspace_update(em);
- BMLoopNorEditDataArray *lnors_ed_arr = do_merge ? BM_loop_normal_editdata_array_init(bm) : NULL;
+ BMLoopNorEditDataArray *lnors_ed_arr = do_merge ? BM_loop_normal_editdata_array_init(bm) : NULL;
- mesh_set_smooth_faces(em, do_merge);
+ mesh_set_smooth_faces(em, do_merge);
- BM_ITER_MESH(e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- BM_elem_flag_set(e, BM_ELEM_SMOOTH, do_merge);
- }
- }
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ BM_elem_flag_set(e, BM_ELEM_SMOOTH, do_merge);
+ }
+ }
- bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
- BKE_editmesh_lnorspace_update(em);
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+ BKE_editmesh_lnorspace_update(em);
- if (do_merge) {
- normals_merge(bm, lnors_ed_arr);
- }
- else {
- normals_split(bm);
- }
+ if (do_merge) {
+ normals_merge(bm, lnors_ed_arr);
+ }
+ else {
+ normals_split(bm);
+ }
- if (lnors_ed_arr) {
- BM_loop_normal_editdata_array_free(lnors_ed_arr);
- }
+ if (lnors_ed_arr) {
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ }
- EDBM_update_generic(em, true, false);
+ EDBM_update_generic(em, true, false);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int edbm_merge_normals_exec(bContext *C, wmOperator *UNUSED(op))
{
- return normals_split_merge(C, true);
+ return normals_split_merge(C, true);
}
void MESH_OT_merge_normals(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Merge Normals";
- ot->description = "Merge custom normals of selected vertices";
- ot->idname = "MESH_OT_merge_normals";
+ /* identifiers */
+ ot->name = "Merge Normals";
+ ot->description = "Merge custom normals of selected vertices";
+ ot->idname = "MESH_OT_merge_normals";
- /* api callbacks */
- ot->exec = edbm_merge_normals_exec;
- ot->poll = ED_operator_editmesh_auto_smooth;
+ /* api callbacks */
+ ot->exec = edbm_merge_normals_exec;
+ ot->poll = ED_operator_editmesh_auto_smooth;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int edbm_split_normals_exec(bContext *C, wmOperator *UNUSED(op))
{
- return normals_split_merge(C, false);
+ return normals_split_merge(C, false);
}
void MESH_OT_split_normals(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Split Normals";
- ot->description = "Split custom normals of selected vertices";
- ot->idname = "MESH_OT_split_normals";
+ /* identifiers */
+ ot->name = "Split Normals";
+ ot->description = "Split custom normals of selected vertices";
+ ot->idname = "MESH_OT_split_normals";
- /* api callbacks */
- ot->exec = edbm_split_normals_exec;
- ot->poll = ED_operator_editmesh_auto_smooth;
+ /* api callbacks */
+ ot->exec = edbm_split_normals_exec;
+ ot->poll = ED_operator_editmesh_auto_smooth;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** Average Loop Normals **********************/
enum {
- EDBM_CLNOR_AVERAGE_LOOP = 1,
- EDBM_CLNOR_AVERAGE_FACE_AREA = 2,
- EDBM_CLNOR_AVERAGE_ANGLE = 3,
+ EDBM_CLNOR_AVERAGE_LOOP = 1,
+ EDBM_CLNOR_AVERAGE_FACE_AREA = 2,
+ EDBM_CLNOR_AVERAGE_ANGLE = 3,
};
static EnumPropertyItem average_method_items[] = {
- {EDBM_CLNOR_AVERAGE_LOOP, "CUSTOM_NORMAL", 0, "Custom Normal", "Take Average of vert Normals"},
- {EDBM_CLNOR_AVERAGE_FACE_AREA, "FACE_AREA", 0, "Face Area", "Set all vert normals by Face Area"},
- {EDBM_CLNOR_AVERAGE_ANGLE, "CORNER_ANGLE", 0, "Corner Angle", "Set all vert normals by Corner Angle"},
- {0, NULL, 0, NULL, NULL},
+ {EDBM_CLNOR_AVERAGE_LOOP, "CUSTOM_NORMAL", 0, "Custom Normal", "Take Average of vert Normals"},
+ {EDBM_CLNOR_AVERAGE_FACE_AREA,
+ "FACE_AREA",
+ 0,
+ "Face Area",
+ "Set all vert normals by Face Area"},
+ {EDBM_CLNOR_AVERAGE_ANGLE,
+ "CORNER_ANGLE",
+ 0,
+ "Corner Angle",
+ "Set all vert normals by Corner Angle"},
+ {0, NULL, 0, NULL, NULL},
};
static int edbm_average_normals_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMFace *f;
- BMLoop *l, *l_curr, *l_first;
- BMIter fiter;
-
- bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
- BKE_editmesh_lnorspace_update(em);
-
- const int average_type = RNA_enum_get(op->ptr, "average_type");
- const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
- const float absweight = (float) RNA_int_get(op->ptr, "weight");
- const float threshold = RNA_float_get(op->ptr, "threshold");
-
- float weight = absweight / 50.0f;
- if (absweight == 100.0f) {
- weight = (float)SHRT_MAX;
- }
- else if (absweight == 1.0f) {
- weight = 1 / (float)SHRT_MAX;
- }
- else if ((weight - 1) * 25 > 1) {
- weight = (weight - 1) * 25;
- }
-
- 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 {
- if (BM_elem_flag_test(l_curr->v, BM_ELEM_SELECT) && (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) ||
- (!BM_elem_flag_test(l_curr, BM_ELEM_TAG) && BM_loop_check_cyclic_smooth_fan(l_curr))))
- {
- if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) && !BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG)) {
- const int loop_index = BM_elem_index_get(l_curr);
- short *clnors = BM_ELEM_CD_GET_VOID_P(l_curr, cd_clnors_offset);
- BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[loop_index], f->no, clnors);
- }
- else {
- BMVert *v_pivot = l_curr->v;
- UNUSED_VARS_NDEBUG(v_pivot);
- BMEdge *e_next;
- const BMEdge *e_org = l_curr->e;
- BMLoop *lfan_pivot, *lfan_pivot_next;
-
- lfan_pivot = l_curr;
- e_next = lfan_pivot->e;
-
- while (true) {
- lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot, &e_next);
- if (lfan_pivot_next) {
- BLI_assert(lfan_pivot_next->v == v_pivot);
- }
- else {
- e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
- }
-
- float val = 1.0f;
- if (average_type == EDBM_CLNOR_AVERAGE_FACE_AREA) {
- val = 1.0f / BM_face_calc_area(lfan_pivot->f);
- }
- else if (average_type == EDBM_CLNOR_AVERAGE_ANGLE) {
- val = 1.0f / BM_loop_calc_face_angle(lfan_pivot);
- }
-
- BLI_heapsimple_insert(loop_weight, val, lfan_pivot);
-
- if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) {
- break;
- }
- 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);
-
- while (!BLI_heapsimple_is_empty(loop_weight)) {
- const float cur_val = BLI_heapsimple_top_value(loop_weight);
- if (!compare_ff(val, cur_val, threshold)) {
- count++;
- val = cur_val;
- }
- l = BLI_heapsimple_pop_min(loop_weight);
- BLI_SMALLSTACK_PUSH(loops, l);
-
- const float n_weight = pow(weight, count);
-
- if (average_type == EDBM_CLNOR_AVERAGE_LOOP) {
- const int l_index = BM_elem_index_get(l);
- short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
- BKE_lnor_space_custom_data_to_normal(bm->lnor_spacearr->lspacearr[l_index], clnors, wnor);
- }
- else {
- copy_v3_v3(wnor, l->f->no);
- }
- mul_v3_fl(wnor, (1.0f / cur_val) * (1.0f / n_weight));
- add_v3_v3(avg_normal, wnor);
- }
-
- if (normalize_v3(avg_normal) < CLNORS_VALID_VEC_LEN) {
- /* If avg normal is nearly 0, set clnor to default value. */
- zero_v3(avg_normal);
- }
- while ((l = BLI_SMALLSTACK_POP(loops))) {
- const int l_index = BM_elem_index_get(l);
- short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
- BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[l_index], avg_normal, clnors);
- }
- }
- }
- } while ((l_curr = l_curr->next) != l_first);
- }
-
- BLI_heapsimple_free(loop_weight, NULL);
- EDBM_update_generic(em, true, false);
-
- return OPERATOR_FINISHED;
-}
-
-static bool average_normals_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop, void *UNUSED(user_data))
-{
- const char *prop_id = RNA_property_identifier(prop);
- const int average_type = RNA_enum_get(ptr, "average_type");
-
- /* Only show weight/threshold options in loop average type. */
- if (STREQ(prop_id, "weight")) {
- return (average_type == EDBM_CLNOR_AVERAGE_LOOP);
- }
- else if (STREQ(prop_id, "threshold")) {
- return (average_type == EDBM_CLNOR_AVERAGE_LOOP);
- }
-
- /* Else, show it! */
- return true;
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMFace *f;
+ BMLoop *l, *l_curr, *l_first;
+ BMIter fiter;
+
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+ BKE_editmesh_lnorspace_update(em);
+
+ const int average_type = RNA_enum_get(op->ptr, "average_type");
+ const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+ const float absweight = (float)RNA_int_get(op->ptr, "weight");
+ const float threshold = RNA_float_get(op->ptr, "threshold");
+
+ float weight = absweight / 50.0f;
+ if (absweight == 100.0f) {
+ weight = (float)SHRT_MAX;
+ }
+ else if (absweight == 1.0f) {
+ weight = 1 / (float)SHRT_MAX;
+ }
+ else if ((weight - 1) * 25 > 1) {
+ weight = (weight - 1) * 25;
+ }
+
+ 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 {
+ if (BM_elem_flag_test(l_curr->v, BM_ELEM_SELECT) &&
+ (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) ||
+ (!BM_elem_flag_test(l_curr, BM_ELEM_TAG) && BM_loop_check_cyclic_smooth_fan(l_curr)))) {
+ if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
+ !BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG)) {
+ const int loop_index = BM_elem_index_get(l_curr);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l_curr, cd_clnors_offset);
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[loop_index], f->no, clnors);
+ }
+ else {
+ BMVert *v_pivot = l_curr->v;
+ UNUSED_VARS_NDEBUG(v_pivot);
+ BMEdge *e_next;
+ const BMEdge *e_org = l_curr->e;
+ BMLoop *lfan_pivot, *lfan_pivot_next;
+
+ lfan_pivot = l_curr;
+ e_next = lfan_pivot->e;
+
+ while (true) {
+ lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot, &e_next);
+ if (lfan_pivot_next) {
+ BLI_assert(lfan_pivot_next->v == v_pivot);
+ }
+ else {
+ e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
+ }
+
+ float val = 1.0f;
+ if (average_type == EDBM_CLNOR_AVERAGE_FACE_AREA) {
+ val = 1.0f / BM_face_calc_area(lfan_pivot->f);
+ }
+ else if (average_type == EDBM_CLNOR_AVERAGE_ANGLE) {
+ val = 1.0f / BM_loop_calc_face_angle(lfan_pivot);
+ }
+
+ BLI_heapsimple_insert(loop_weight, val, lfan_pivot);
+
+ if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) {
+ break;
+ }
+ 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);
+
+ while (!BLI_heapsimple_is_empty(loop_weight)) {
+ const float cur_val = BLI_heapsimple_top_value(loop_weight);
+ if (!compare_ff(val, cur_val, threshold)) {
+ count++;
+ val = cur_val;
+ }
+ l = BLI_heapsimple_pop_min(loop_weight);
+ BLI_SMALLSTACK_PUSH(loops, l);
+
+ const float n_weight = pow(weight, count);
+
+ if (average_type == EDBM_CLNOR_AVERAGE_LOOP) {
+ const int l_index = BM_elem_index_get(l);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+ BKE_lnor_space_custom_data_to_normal(
+ bm->lnor_spacearr->lspacearr[l_index], clnors, wnor);
+ }
+ else {
+ copy_v3_v3(wnor, l->f->no);
+ }
+ mul_v3_fl(wnor, (1.0f / cur_val) * (1.0f / n_weight));
+ add_v3_v3(avg_normal, wnor);
+ }
+
+ if (normalize_v3(avg_normal) < CLNORS_VALID_VEC_LEN) {
+ /* If avg normal is nearly 0, set clnor to default value. */
+ zero_v3(avg_normal);
+ }
+ while ((l = BLI_SMALLSTACK_POP(loops))) {
+ const int l_index = BM_elem_index_get(l);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[l_index], avg_normal, clnors);
+ }
+ }
+ }
+ } while ((l_curr = l_curr->next) != l_first);
+ }
+
+ BLI_heapsimple_free(loop_weight, NULL);
+ EDBM_update_generic(em, true, false);
+
+ return OPERATOR_FINISHED;
+}
+
+static bool average_normals_draw_check_prop(PointerRNA *ptr,
+ PropertyRNA *prop,
+ void *UNUSED(user_data))
+{
+ const char *prop_id = RNA_property_identifier(prop);
+ const int average_type = RNA_enum_get(ptr, "average_type");
+
+ /* Only show weight/threshold options in loop average type. */
+ if (STREQ(prop_id, "weight")) {
+ return (average_type == EDBM_CLNOR_AVERAGE_LOOP);
+ }
+ else if (STREQ(prop_id, "threshold")) {
+ return (average_type == EDBM_CLNOR_AVERAGE_LOOP);
+ }
+
+ /* Else, show it! */
+ return true;
}
static void edbm_average_normals_ui(bContext *C, wmOperator *op)
{
- uiLayout *layout = op->layout;
- wmWindowManager *wm = CTX_wm_manager(C);
- PointerRNA ptr;
+ uiLayout *layout = op->layout;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ PointerRNA ptr;
- RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+ RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
- /* Main auto-draw call */
- uiDefAutoButsRNA(layout, &ptr, average_normals_draw_check_prop, NULL, NULL, '\0', false);
+ /* Main auto-draw call */
+ uiDefAutoButsRNA(layout, &ptr, average_normals_draw_check_prop, NULL, NULL, '\0', false);
}
void MESH_OT_average_normals(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Average Normals";
- ot->description = "Average custom normals of selected vertices";
- ot->idname = "MESH_OT_average_normals";
+ /* identifiers */
+ ot->name = "Average Normals";
+ ot->description = "Average custom normals of selected vertices";
+ ot->idname = "MESH_OT_average_normals";
- /* api callbacks */
- ot->exec = edbm_average_normals_exec;
- ot->poll = ED_operator_editmesh_auto_smooth;
- ot->ui = edbm_average_normals_ui;
+ /* api callbacks */
+ ot->exec = edbm_average_normals_exec;
+ ot->poll = ED_operator_editmesh_auto_smooth;
+ ot->ui = edbm_average_normals_ui;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "average_type", average_method_items, EDBM_CLNOR_AVERAGE_LOOP,
- "Type", "Averaging method");
+ ot->prop = RNA_def_enum(ot->srna,
+ "average_type",
+ average_method_items,
+ EDBM_CLNOR_AVERAGE_LOOP,
+ "Type",
+ "Averaging method");
- RNA_def_int(ot->srna, "weight", 50, 1, 100, "Weight", "Weight applied per face", 1, 100);
+ RNA_def_int(ot->srna, "weight", 50, 1, 100, "Weight", "Weight applied per face", 1, 100);
- RNA_def_float(ot->srna, "threshold", 0.01f, 0, 10, "Threshold",
- "Threshold value for different weights to be considered equal", 0, 5);
+ RNA_def_float(ot->srna,
+ "threshold",
+ 0.01f,
+ 0,
+ 10,
+ "Threshold",
+ "Threshold value for different weights to be considered equal",
+ 0,
+ 5);
}
/********************** Custom Normal Interface Tools **********************/
enum {
- EDBM_CLNOR_TOOLS_COPY = 1,
- EDBM_CLNOR_TOOLS_PASTE = 2,
- EDBM_CLNOR_TOOLS_MULTIPLY = 3,
- EDBM_CLNOR_TOOLS_ADD = 4,
- EDBM_CLNOR_TOOLS_RESET = 5,
+ EDBM_CLNOR_TOOLS_COPY = 1,
+ EDBM_CLNOR_TOOLS_PASTE = 2,
+ EDBM_CLNOR_TOOLS_MULTIPLY = 3,
+ EDBM_CLNOR_TOOLS_ADD = 4,
+ EDBM_CLNOR_TOOLS_RESET = 5,
};
static EnumPropertyItem normal_vector_tool_items[] = {
- {EDBM_CLNOR_TOOLS_COPY, "COPY", 0, "Copy Normal", "Copy normal to buffer"},
- {EDBM_CLNOR_TOOLS_PASTE, "PASTE", 0, "Paste Normal", "Paste normal from buffer"},
- {EDBM_CLNOR_TOOLS_ADD, "ADD", 0, "Add Normal", "Add normal vector with selection"},
- {EDBM_CLNOR_TOOLS_MULTIPLY, "MULTIPLY", 0, "Multiply Normal", "Multiply normal vector with selection"},
- {EDBM_CLNOR_TOOLS_RESET, "RESET", 0, "Reset Normal", "Reset buffer and/or normal of selected element"},
- {0, NULL, 0, NULL, NULL},
+ {EDBM_CLNOR_TOOLS_COPY, "COPY", 0, "Copy Normal", "Copy normal to buffer"},
+ {EDBM_CLNOR_TOOLS_PASTE, "PASTE", 0, "Paste Normal", "Paste normal from buffer"},
+ {EDBM_CLNOR_TOOLS_ADD, "ADD", 0, "Add Normal", "Add normal vector with selection"},
+ {EDBM_CLNOR_TOOLS_MULTIPLY,
+ "MULTIPLY",
+ 0,
+ "Multiply Normal",
+ "Multiply normal vector with selection"},
+ {EDBM_CLNOR_TOOLS_RESET,
+ "RESET",
+ 0,
+ "Reset Normal",
+ "Reset buffer and/or normal of selected element"},
+ {0, NULL, 0, NULL, NULL},
};
static int edbm_normals_tools_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- Scene *scene = CTX_data_scene(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- const int mode = RNA_enum_get(op->ptr, "mode");
- const bool absolute = RNA_boolean_get(op->ptr, "absolute");
-
- BKE_editmesh_lnorspace_update(em);
- BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
- BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
-
- float *normal_vector = scene->toolsettings->normal_vector;
-
- switch (mode) {
- case EDBM_CLNOR_TOOLS_COPY:
- if (bm->totfacesel != 1 && lnors_ed_arr->totloop != 1 && bm->totvertsel != 1) {
- BKE_report(op->reports, RPT_ERROR, "Can only copy one custom normal, vertex normal or face normal");
- BM_loop_normal_editdata_array_free(lnors_ed_arr);
- return OPERATOR_CANCELLED;
- }
- if (lnors_ed_arr->totloop == 1) {
- copy_v3_v3(scene->toolsettings->normal_vector, lnors_ed_arr->lnor_editdata->nloc);
- }
- else if (bm->totfacesel == 1) {
- BMFace *f;
- BMIter fiter;
- BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- copy_v3_v3(scene->toolsettings->normal_vector, f->no);
- }
- }
- }
- else {
- /* 'Vertex' normal, i.e. common set of loop normals on the same vertex,
- * only if they are all the same. */
- bool are_same_lnors = true;
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- if (!compare_v3v3(lnors_ed_arr->lnor_editdata->nloc, lnor_ed->nloc, 1e-4f)) {
- are_same_lnors = false;
- }
- }
- if (are_same_lnors) {
- copy_v3_v3(scene->toolsettings->normal_vector, lnors_ed_arr->lnor_editdata->nloc);
- }
- }
- break;
-
- case EDBM_CLNOR_TOOLS_PASTE:
- if (!absolute) {
- if (normalize_v3(normal_vector) < CLNORS_VALID_VEC_LEN) {
- /* If normal is nearly 0, do nothing. */
- break;
- }
- }
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- if (absolute) {
- float abs_normal[3];
- copy_v3_v3(abs_normal, lnor_ed->loc);
- negate_v3(abs_normal);
- add_v3_v3(abs_normal, normal_vector);
-
- if (normalize_v3(abs_normal) < CLNORS_VALID_VEC_LEN) {
- /* If abs normal is nearly 0, set clnor to initial value. */
- copy_v3_v3(abs_normal, lnor_ed->niloc);
- }
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], abs_normal, lnor_ed->clnors_data);
- }
- else {
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], normal_vector, lnor_ed->clnors_data);
- }
- }
- break;
-
- case EDBM_CLNOR_TOOLS_MULTIPLY:
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- mul_v3_v3(lnor_ed->nloc, normal_vector);
-
- if (normalize_v3(lnor_ed->nloc) < CLNORS_VALID_VEC_LEN) {
- /* If abs normal is nearly 0, set clnor to initial value. */
- copy_v3_v3(lnor_ed->nloc, lnor_ed->niloc);
- }
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->nloc, lnor_ed->clnors_data);
- }
- break;
-
- case EDBM_CLNOR_TOOLS_ADD:
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- add_v3_v3(lnor_ed->nloc, normal_vector);
-
- if (normalize_v3(lnor_ed->nloc) < CLNORS_VALID_VEC_LEN) {
- /* If abs normal is nearly 0, set clnor to initial value. */
- copy_v3_v3(lnor_ed->nloc, lnor_ed->niloc);
- }
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->nloc, lnor_ed->clnors_data);
- }
- break;
-
- case EDBM_CLNOR_TOOLS_RESET:
- zero_v3(normal_vector);
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], normal_vector, lnor_ed->clnors_data);
- }
- break;
-
- default:
- BLI_assert(0);
- break;
- }
-
- BM_loop_normal_editdata_array_free(lnors_ed_arr);
-
- EDBM_update_generic(em, true, false);
- return OPERATOR_FINISHED;
-}
-
-static bool normals_tools_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop, void *UNUSED(user_data))
-{
- const char *prop_id = RNA_property_identifier(prop);
- const int mode = RNA_enum_get(ptr, "mode");
-
- /* Only show absolute option in paste mode. */
- if (STREQ(prop_id, "absolute")) {
- return (mode == EDBM_CLNOR_TOOLS_PASTE);
- }
-
- /* Else, show it! */
- return true;
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ const int mode = RNA_enum_get(op->ptr, "mode");
+ const bool absolute = RNA_boolean_get(op->ptr, "absolute");
+
+ BKE_editmesh_lnorspace_update(em);
+ BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+
+ float *normal_vector = scene->toolsettings->normal_vector;
+
+ switch (mode) {
+ case EDBM_CLNOR_TOOLS_COPY:
+ if (bm->totfacesel != 1 && lnors_ed_arr->totloop != 1 && bm->totvertsel != 1) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Can only copy one custom normal, vertex normal or face normal");
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ return OPERATOR_CANCELLED;
+ }
+ if (lnors_ed_arr->totloop == 1) {
+ copy_v3_v3(scene->toolsettings->normal_vector, lnors_ed_arr->lnor_editdata->nloc);
+ }
+ else if (bm->totfacesel == 1) {
+ BMFace *f;
+ BMIter fiter;
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ copy_v3_v3(scene->toolsettings->normal_vector, f->no);
+ }
+ }
+ }
+ else {
+ /* 'Vertex' normal, i.e. common set of loop normals on the same vertex,
+ * only if they are all the same. */
+ bool are_same_lnors = true;
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ if (!compare_v3v3(lnors_ed_arr->lnor_editdata->nloc, lnor_ed->nloc, 1e-4f)) {
+ are_same_lnors = false;
+ }
+ }
+ if (are_same_lnors) {
+ copy_v3_v3(scene->toolsettings->normal_vector, lnors_ed_arr->lnor_editdata->nloc);
+ }
+ }
+ break;
+
+ case EDBM_CLNOR_TOOLS_PASTE:
+ if (!absolute) {
+ if (normalize_v3(normal_vector) < CLNORS_VALID_VEC_LEN) {
+ /* If normal is nearly 0, do nothing. */
+ break;
+ }
+ }
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ if (absolute) {
+ float abs_normal[3];
+ copy_v3_v3(abs_normal, lnor_ed->loc);
+ negate_v3(abs_normal);
+ add_v3_v3(abs_normal, normal_vector);
+
+ if (normalize_v3(abs_normal) < CLNORS_VALID_VEC_LEN) {
+ /* If abs normal is nearly 0, set clnor to initial value. */
+ copy_v3_v3(abs_normal, lnor_ed->niloc);
+ }
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], abs_normal, lnor_ed->clnors_data);
+ }
+ else {
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
+ normal_vector,
+ lnor_ed->clnors_data);
+ }
+ }
+ break;
+
+ case EDBM_CLNOR_TOOLS_MULTIPLY:
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ mul_v3_v3(lnor_ed->nloc, normal_vector);
+
+ if (normalize_v3(lnor_ed->nloc) < CLNORS_VALID_VEC_LEN) {
+ /* If abs normal is nearly 0, set clnor to initial value. */
+ copy_v3_v3(lnor_ed->nloc, lnor_ed->niloc);
+ }
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
+ lnor_ed->nloc,
+ lnor_ed->clnors_data);
+ }
+ break;
+
+ case EDBM_CLNOR_TOOLS_ADD:
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ add_v3_v3(lnor_ed->nloc, normal_vector);
+
+ if (normalize_v3(lnor_ed->nloc) < CLNORS_VALID_VEC_LEN) {
+ /* If abs normal is nearly 0, set clnor to initial value. */
+ copy_v3_v3(lnor_ed->nloc, lnor_ed->niloc);
+ }
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
+ lnor_ed->nloc,
+ lnor_ed->clnors_data);
+ }
+ break;
+
+ case EDBM_CLNOR_TOOLS_RESET:
+ zero_v3(normal_vector);
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
+ normal_vector,
+ lnor_ed->clnors_data);
+ }
+ break;
+
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+
+ EDBM_update_generic(em, true, false);
+ return OPERATOR_FINISHED;
+}
+
+static bool normals_tools_draw_check_prop(PointerRNA *ptr,
+ PropertyRNA *prop,
+ void *UNUSED(user_data))
+{
+ const char *prop_id = RNA_property_identifier(prop);
+ const int mode = RNA_enum_get(ptr, "mode");
+
+ /* Only show absolute option in paste mode. */
+ if (STREQ(prop_id, "absolute")) {
+ return (mode == EDBM_CLNOR_TOOLS_PASTE);
+ }
+
+ /* Else, show it! */
+ return true;
}
static void edbm_normals_tools_ui(bContext *C, wmOperator *op)
{
- uiLayout *layout = op->layout;
- wmWindowManager *wm = CTX_wm_manager(C);
- PointerRNA ptr;
+ uiLayout *layout = op->layout;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ PointerRNA ptr;
- RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+ RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
- /* Main auto-draw call */
- uiDefAutoButsRNA(layout, &ptr, normals_tools_draw_check_prop, NULL, NULL, '\0', false);
+ /* Main auto-draw call */
+ uiDefAutoButsRNA(layout, &ptr, normals_tools_draw_check_prop, NULL, NULL, '\0', false);
}
void MESH_OT_normals_tools(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Normals Vector Tools";
- ot->description = "Custom normals tools using Normal Vector of UI";
- ot->idname = "MESH_OT_normals_tools";
+ /* identifiers */
+ ot->name = "Normals Vector Tools";
+ ot->description = "Custom normals tools using Normal Vector of UI";
+ ot->idname = "MESH_OT_normals_tools";
- /* api callbacks */
- ot->exec = edbm_normals_tools_exec;
- ot->poll = ED_operator_editmesh_auto_smooth;
- ot->ui = edbm_normals_tools_ui;
+ /* api callbacks */
+ ot->exec = edbm_normals_tools_exec;
+ ot->poll = ED_operator_editmesh_auto_smooth;
+ ot->ui = edbm_normals_tools_ui;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "mode", normal_vector_tool_items, EDBM_CLNOR_TOOLS_COPY,
- "Mode", "Mode of tools taking input from Interface");
- RNA_def_property_flag(ot->prop, PROP_HIDDEN);
+ ot->prop = RNA_def_enum(ot->srna,
+ "mode",
+ normal_vector_tool_items,
+ EDBM_CLNOR_TOOLS_COPY,
+ "Mode",
+ "Mode of tools taking input from Interface");
+ RNA_def_property_flag(ot->prop, PROP_HIDDEN);
- RNA_def_boolean(ot->srna, "absolute", false, "Absolute Coordinates", "Copy Absolute coordinates or Normal vector");
+ RNA_def_boolean(ot->srna,
+ "absolute",
+ false,
+ "Absolute Coordinates",
+ "Copy Absolute coordinates or Normal vector");
}
static int edbm_set_normals_from_faces_exec(bContext *C, wmOperator *op)
{
- 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];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMFace *f;
- BMVert *v;
- BMEdge *e;
- BMLoop *l;
- BMIter fiter, viter, eiter, liter;
-
- const bool keep_sharp = RNA_boolean_get(op->ptr, "keep_sharp");
-
- BKE_editmesh_lnorspace_update(em);
-
- float(*vnors)[3] = MEM_callocN(sizeof(*vnors) * bm->totvert, __func__);
- BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- BM_ITER_ELEM(v, &viter, f, BM_VERTS_OF_FACE) {
- const int v_index = BM_elem_index_get(v);
- add_v3_v3(vnors[v_index], f->no);
- }
- }
- }
- for (int i = 0; i < bm->totvert; i++) {
- if (!is_zero_v3(vnors[i]) && normalize_v3(vnors[i]) < CLNORS_VALID_VEC_LEN) {
- zero_v3(vnors[i]);
- }
- }
-
- BLI_bitmap *loop_set = BLI_BITMAP_NEW(bm->totloop, __func__);
- const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
-
- BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM(e, &eiter, f, BM_EDGES_OF_FACE) {
- if (!keep_sharp || (BM_elem_flag_test(e, BM_ELEM_SMOOTH) && BM_elem_flag_test(e, BM_ELEM_SELECT))) {
- BM_ITER_ELEM(v, &viter, e, BM_VERTS_OF_EDGE) {
- l = BM_face_vert_share_loop(f, v);
- const int l_index = BM_elem_index_get(l);
- const int v_index = BM_elem_index_get(l->v);
-
- if (!is_zero_v3(vnors[v_index])) {
- short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[l_index], vnors[v_index], clnors);
-
- if (bm->lnor_spacearr->lspacearr[l_index]->flags & MLNOR_SPACE_IS_SINGLE) {
- BLI_BITMAP_ENABLE(loop_set, l_index);
- }
- else {
- LinkNode *loops = bm->lnor_spacearr->lspacearr[l_index]->loops;
- for (; loops; loops = loops->next) {
- BLI_BITMAP_ENABLE(loop_set, BM_elem_index_get((BMLoop *)loops->link));
- }
- }
- }
- }
- }
- }
- }
-
- int v_index;
- BM_ITER_MESH_INDEX(v, &viter, bm, BM_VERTS_OF_MESH, v_index) {
- BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) {
- if (BLI_BITMAP_TEST(loop_set, BM_elem_index_get(l))) {
- const int loop_index = BM_elem_index_get(l);
- short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[loop_index], vnors[v_index], clnors);
- }
- }
- }
-
- MEM_freeN(loop_set);
- MEM_freeN(vnors);
- EDBM_update_generic(em, true, false);
- }
-
- return OPERATOR_FINISHED;
+ 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];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMFace *f;
+ BMVert *v;
+ BMEdge *e;
+ BMLoop *l;
+ BMIter fiter, viter, eiter, liter;
+
+ const bool keep_sharp = RNA_boolean_get(op->ptr, "keep_sharp");
+
+ BKE_editmesh_lnorspace_update(em);
+
+ float(*vnors)[3] = MEM_callocN(sizeof(*vnors) * bm->totvert, __func__);
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) {
+ const int v_index = BM_elem_index_get(v);
+ add_v3_v3(vnors[v_index], f->no);
+ }
+ }
+ }
+ for (int i = 0; i < bm->totvert; i++) {
+ if (!is_zero_v3(vnors[i]) && normalize_v3(vnors[i]) < CLNORS_VALID_VEC_LEN) {
+ zero_v3(vnors[i]);
+ }
+ }
+
+ BLI_bitmap *loop_set = BLI_BITMAP_NEW(bm->totloop, __func__);
+ const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (e, &eiter, f, BM_EDGES_OF_FACE) {
+ if (!keep_sharp ||
+ (BM_elem_flag_test(e, BM_ELEM_SMOOTH) && BM_elem_flag_test(e, BM_ELEM_SELECT))) {
+ BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
+ l = BM_face_vert_share_loop(f, v);
+ const int l_index = BM_elem_index_get(l);
+ const int v_index = BM_elem_index_get(l->v);
+
+ if (!is_zero_v3(vnors[v_index])) {
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[l_index], vnors[v_index], clnors);
+
+ if (bm->lnor_spacearr->lspacearr[l_index]->flags & MLNOR_SPACE_IS_SINGLE) {
+ BLI_BITMAP_ENABLE(loop_set, l_index);
+ }
+ else {
+ LinkNode *loops = bm->lnor_spacearr->lspacearr[l_index]->loops;
+ for (; loops; loops = loops->next) {
+ BLI_BITMAP_ENABLE(loop_set, BM_elem_index_get((BMLoop *)loops->link));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ int v_index;
+ BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, v_index) {
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ if (BLI_BITMAP_TEST(loop_set, BM_elem_index_get(l))) {
+ const int loop_index = BM_elem_index_get(l);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[loop_index], vnors[v_index], clnors);
+ }
+ }
+ }
+
+ MEM_freeN(loop_set);
+ MEM_freeN(vnors);
+ EDBM_update_generic(em, true, false);
+ }
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_set_normals_from_faces(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Normals From Faces";
- ot->description = "Set the custom normals from the selected faces ones";
- ot->idname = "MESH_OT_set_normals_from_faces";
+ /* identifiers */
+ ot->name = "Set Normals From Faces";
+ ot->description = "Set the custom normals from the selected faces ones";
+ ot->idname = "MESH_OT_set_normals_from_faces";
- /* api callbacks */
- ot->exec = edbm_set_normals_from_faces_exec;
- ot->poll = ED_operator_editmesh_auto_smooth;
+ /* api callbacks */
+ ot->exec = edbm_set_normals_from_faces_exec;
+ ot->poll = ED_operator_editmesh_auto_smooth;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "keep_sharp", 0, "Keep Sharp Edges", "Do not set sharp edges to face");
+ 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)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMFace *f;
- BMLoop *l;
- BMIter fiter, liter;
-
- BKE_editmesh_lnorspace_update(em);
- BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
-
- float(*smooth_normal)[3] = MEM_callocN(sizeof(*smooth_normal) * lnors_ed_arr->totloop, __func__);
-
- /* This is weird choice of operation, taking all loops of faces of current vertex... Could lead to some rather
- * far away loops weighting as much as very close ones (topologically speaking), with complex polygons.
- * Using topological distance here (rather than geometrical one) makes sense imho, but would rather go with
- * a more consistent and flexible code, we could even add max topological distance to take into account,
- * and a weighting curve...
- * Would do that later though, think for now we can live with that choice. --mont29 */
- BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- l = lnor_ed->loop;
- float loop_normal[3];
-
- BM_ITER_ELEM(f, &fiter, l->v, BM_FACES_OF_VERT) {
- BMLoop *l_other;
- BM_ITER_ELEM(l_other, &liter, f, BM_LOOPS_OF_FACE) {
- const int l_index_other = BM_elem_index_get(l_other);
- short *clnors = BM_ELEM_CD_GET_VOID_P(l_other, lnors_ed_arr->cd_custom_normal_offset);
- BKE_lnor_space_custom_data_to_normal(bm->lnor_spacearr->lspacearr[l_index_other], clnors, loop_normal);
- add_v3_v3(smooth_normal[i], loop_normal);
- }
- }
- }
-
- const float factor = RNA_float_get(op->ptr, "factor");
-
- lnor_ed = lnors_ed_arr->lnor_editdata;
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- float current_normal[3];
-
- if (normalize_v3(smooth_normal[i]) < CLNORS_VALID_VEC_LEN) {
- /* Skip in case smoothen normal is invalid... */
- continue;
- }
-
- BKE_lnor_space_custom_data_to_normal(
- bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->clnors_data, current_normal);
-
- /* Note: again, this is not true spherical interpolation that normals would need...
- * But it's probably good enough for now. */
- mul_v3_fl(current_normal, 1.0f - factor);
- mul_v3_fl(smooth_normal[i], factor);
- add_v3_v3(current_normal, smooth_normal[i]);
-
- if (normalize_v3(current_normal) < CLNORS_VALID_VEC_LEN) {
- /* Skip in case smoothen normal is invalid... */
- continue;
- }
-
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], current_normal, lnor_ed->clnors_data);
- }
-
- BM_loop_normal_editdata_array_free(lnors_ed_arr);
- MEM_freeN(smooth_normal);
-
- EDBM_update_generic(em, true, false);
-
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMFace *f;
+ BMLoop *l;
+ BMIter fiter, liter;
+
+ BKE_editmesh_lnorspace_update(em);
+ BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
+
+ float(*smooth_normal)[3] = MEM_callocN(sizeof(*smooth_normal) * lnors_ed_arr->totloop, __func__);
+
+ /* This is weird choice of operation, taking all loops of faces of current vertex... Could lead to some rather
+ * far away loops weighting as much as very close ones (topologically speaking), with complex polygons.
+ * Using topological distance here (rather than geometrical one) makes sense imho, but would rather go with
+ * a more consistent and flexible code, we could even add max topological distance to take into account,
+ * and a weighting curve...
+ * Would do that later though, think for now we can live with that choice. --mont29 */
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ l = lnor_ed->loop;
+ float loop_normal[3];
+
+ BM_ITER_ELEM (f, &fiter, l->v, BM_FACES_OF_VERT) {
+ BMLoop *l_other;
+ BM_ITER_ELEM (l_other, &liter, f, BM_LOOPS_OF_FACE) {
+ const int l_index_other = BM_elem_index_get(l_other);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l_other, lnors_ed_arr->cd_custom_normal_offset);
+ BKE_lnor_space_custom_data_to_normal(
+ bm->lnor_spacearr->lspacearr[l_index_other], clnors, loop_normal);
+ add_v3_v3(smooth_normal[i], loop_normal);
+ }
+ }
+ }
+
+ const float factor = RNA_float_get(op->ptr, "factor");
+
+ lnor_ed = lnors_ed_arr->lnor_editdata;
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ float current_normal[3];
+
+ if (normalize_v3(smooth_normal[i]) < CLNORS_VALID_VEC_LEN) {
+ /* Skip in case smoothen normal is invalid... */
+ continue;
+ }
+
+ BKE_lnor_space_custom_data_to_normal(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->clnors_data, current_normal);
+
+ /* Note: again, this is not true spherical interpolation that normals would need...
+ * But it's probably good enough for now. */
+ mul_v3_fl(current_normal, 1.0f - factor);
+ mul_v3_fl(smooth_normal[i], factor);
+ add_v3_v3(current_normal, smooth_normal[i]);
+
+ if (normalize_v3(current_normal) < CLNORS_VALID_VEC_LEN) {
+ /* Skip in case smoothen normal is invalid... */
+ continue;
+ }
+
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], current_normal, lnor_ed->clnors_data);
+ }
+
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ MEM_freeN(smooth_normal);
+
+ EDBM_update_generic(em, true, false);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_smoothen_normals(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Smoothen Normals";
- ot->description = "Smoothen custom normals based on adjacent vertex normals";
- ot->idname = "MESH_OT_smoothen_normals";
+ /* identifiers */
+ ot->name = "Smoothen Normals";
+ ot->description = "Smoothen custom normals based on adjacent vertex normals";
+ ot->idname = "MESH_OT_smoothen_normals";
- /* api callbacks */
- ot->exec = edbm_smoothen_normals_exec;
- ot->poll = ED_operator_editmesh_auto_smooth;
+ /* api callbacks */
+ ot->exec = edbm_smoothen_normals_exec;
+ ot->poll = ED_operator_editmesh_auto_smooth;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0f, "Factor",
- "Specifies weight of smooth vs original normal", 0.0f, 1.0f);
+ RNA_def_float(ot->srna,
+ "factor",
+ 0.5f,
+ 0.0f,
+ 1.0f,
+ "Factor",
+ "Specifies weight of smooth vs original normal",
+ 0.0f,
+ 1.0f);
}
/********************** Weighted Normal Modifier Face Strength **********************/
static int edbm_mod_weighted_strength_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMFace *f;
- BMIter fiter;
-
- BM_select_history_clear(bm);
-
- const char *layer_id = MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID;
- int cd_prop_int_index = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, layer_id);
- if (cd_prop_int_index == -1) {
- BM_data_layer_add_named(bm, &bm->pdata, CD_PROP_INT, layer_id);
- cd_prop_int_index = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, layer_id);
- }
- cd_prop_int_index -= CustomData_get_layer_index(&bm->pdata, CD_PROP_INT);
- const int cd_prop_int_offset = CustomData_get_n_offset(&bm->pdata, CD_PROP_INT, cd_prop_int_index);
-
- const int face_strength = scene->toolsettings->face_strength;
- const bool set = RNA_boolean_get(op->ptr, "set");
- BM_mesh_elem_index_ensure(bm, BM_FACE);
-
- if (set) {
- BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- int *strength = BM_ELEM_CD_GET_VOID_P(f, cd_prop_int_offset);
- *strength = face_strength;
- }
- }
- }
- else {
- BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
- int *strength = BM_ELEM_CD_GET_VOID_P(f, cd_prop_int_offset);
- if (*strength == face_strength) {
- BM_face_select_set(bm, f, true);
- BM_select_history_store(bm, f);
- }
- else {
- BM_face_select_set(bm, f, false);
- }
- }
- }
-
- EDBM_update_generic(em, false, false);
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMFace *f;
+ BMIter fiter;
+
+ BM_select_history_clear(bm);
+
+ const char *layer_id = MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID;
+ int cd_prop_int_index = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, layer_id);
+ if (cd_prop_int_index == -1) {
+ BM_data_layer_add_named(bm, &bm->pdata, CD_PROP_INT, layer_id);
+ cd_prop_int_index = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, layer_id);
+ }
+ cd_prop_int_index -= CustomData_get_layer_index(&bm->pdata, CD_PROP_INT);
+ const int cd_prop_int_offset = CustomData_get_n_offset(
+ &bm->pdata, CD_PROP_INT, cd_prop_int_index);
+
+ const int face_strength = scene->toolsettings->face_strength;
+ const bool set = RNA_boolean_get(op->ptr, "set");
+ BM_mesh_elem_index_ensure(bm, BM_FACE);
+
+ if (set) {
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ int *strength = BM_ELEM_CD_GET_VOID_P(f, cd_prop_int_offset);
+ *strength = face_strength;
+ }
+ }
+ }
+ else {
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ int *strength = BM_ELEM_CD_GET_VOID_P(f, cd_prop_int_offset);
+ if (*strength == face_strength) {
+ BM_face_select_set(bm, f, true);
+ BM_select_history_store(bm, f);
+ }
+ else {
+ BM_face_select_set(bm, f, false);
+ }
+ }
+ }
+
+ EDBM_update_generic(em, false, false);
+ return OPERATOR_FINISHED;
}
void MESH_OT_mod_weighted_strength(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Face Strength";
- ot->description = "Set/Get strength of face (used in Weighted Normal modifier)";
- ot->idname = "MESH_OT_mod_weighted_strength";
+ /* identifiers */
+ ot->name = "Face Strength";
+ ot->description = "Set/Get strength of face (used in Weighted Normal modifier)";
+ ot->idname = "MESH_OT_mod_weighted_strength";
- /* api callbacks */
- ot->exec = edbm_mod_weighted_strength_exec;
- ot->poll = ED_operator_editmesh_auto_smooth;
+ /* api callbacks */
+ ot->exec = edbm_mod_weighted_strength_exec;
+ ot->poll = ED_operator_editmesh_auto_smooth;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_boolean(ot->srna, "set", 0, "Set value", "Set Value of faces");
- RNA_def_property_flag(ot->prop, PROP_HIDDEN);
+ ot->prop = RNA_def_boolean(ot->srna, "set", 0, "Set value", "Set Value of faces");
+ RNA_def_property_flag(ot->prop, PROP_HIDDEN);
}
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index 5ea3fa784a5..2e855d9c5de 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -59,7 +59,7 @@
# include "BLI_array_store.h"
# include "BLI_array_store_utils.h"
- /* check on best size later... */
+/* check on best size later... */
# define ARRAY_CHUNK_SIZE 256
# define USE_ARRAY_STORE_THREAD
@@ -80,198 +80,199 @@ static CLG_LogRef LOG = {"ed.undo.mesh"};
/* Single linked list of layers stored per type */
typedef struct BArrayCustomData {
- struct BArrayCustomData *next;
- CustomDataType type;
- int states_len; /* number of layers for each type */
- BArrayState *states[0];
+ struct BArrayCustomData *next;
+ CustomDataType type;
+ int states_len; /* number of layers for each type */
+ BArrayState *states[0];
} BArrayCustomData;
#endif
typedef struct UndoMesh {
- Mesh me;
- int selectmode;
-
- /** \note
- * this isn't a prefect solution, if you edit keys and change shapes this works well (fixing [#32442]),
- * but editing shape keys, going into object mode, removing or changing their order,
- * then go back into editmode and undo will give issues - where the old index will be out of sync
- * with the new object index.
- *
- * There are a few ways this could be made to work but for now its a known limitation with mixing
- * object and editmode operations - Campbell */
- int shapenr;
+ Mesh me;
+ int selectmode;
+
+ /** \note
+ * this isn't a prefect solution, if you edit keys and change shapes this works well (fixing [#32442]),
+ * but editing shape keys, going into object mode, removing or changing their order,
+ * then go back into editmode and undo will give issues - where the old index will be out of sync
+ * with the new object index.
+ *
+ * There are a few ways this could be made to work but for now its a known limitation with mixing
+ * object and editmode operations - Campbell */
+ int shapenr;
#ifdef USE_ARRAY_STORE
- /* NULL arrays are considered empty */
- struct { /* most data is stored as 'custom' data */
- BArrayCustomData *vdata, *edata, *ldata, *pdata;
- BArrayState **keyblocks;
- BArrayState *mselect;
- } store;
-#endif /* USE_ARRAY_STORE */
-
- size_t undo_size;
+ /* NULL arrays are considered empty */
+ struct { /* most data is stored as 'custom' data */
+ BArrayCustomData *vdata, *edata, *ldata, *pdata;
+ BArrayState **keyblocks;
+ BArrayState *mselect;
+ } store;
+#endif /* USE_ARRAY_STORE */
+
+ size_t undo_size;
} UndoMesh;
-
#ifdef USE_ARRAY_STORE
/** \name Array Store
* \{ */
static struct {
- struct BArrayStore_AtSize bs_stride;
- int users;
+ struct BArrayStore_AtSize bs_stride;
+ int users;
- /* We could have the undo API pass in the previous state, for now store a local list */
- ListBase local_links;
+ /* We could have the undo API pass in the previous state, for now store a local list */
+ ListBase local_links;
-#ifdef USE_ARRAY_STORE_THREAD
- TaskPool *task_pool;
-#endif
+# ifdef USE_ARRAY_STORE_THREAD
+ TaskPool *task_pool;
+# endif
} um_arraystore = {{NULL}};
-static void um_arraystore_cd_compact(
- struct CustomData *cdata, const size_t data_len,
- bool create,
- const BArrayCustomData *bcd_reference,
- BArrayCustomData **r_bcd_first)
+static void um_arraystore_cd_compact(struct CustomData *cdata,
+ const size_t data_len,
+ bool create,
+ const BArrayCustomData *bcd_reference,
+ BArrayCustomData **r_bcd_first)
{
- if (data_len == 0) {
- if (create) {
- *r_bcd_first = NULL;
- }
- }
-
- const BArrayCustomData *bcd_reference_current = bcd_reference;
- BArrayCustomData *bcd = NULL, *bcd_first = NULL, *bcd_prev = NULL;
- for (int layer_start = 0, layer_end; layer_start < cdata->totlayer; layer_start = layer_end) {
- const CustomDataType type = cdata->layers[layer_start].type;
-
- layer_end = layer_start + 1;
- while ((layer_end < cdata->totlayer) &&
- (type == cdata->layers[layer_end].type))
- {
- layer_end++;
- }
-
- const int stride = CustomData_sizeof(type);
- BArrayStore *bs = create ? BLI_array_store_at_size_ensure(&um_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE) : NULL;
- const int layer_len = layer_end - layer_start;
-
- if (create) {
- if (bcd_reference_current && (bcd_reference_current->type == type)) {
- /* common case, the reference is aligned */
- }
- else {
- bcd_reference_current = NULL;
-
- /* do a full lookup when un-alligned */
- if (bcd_reference) {
- const BArrayCustomData *bcd_iter = bcd_reference;
- while (bcd_iter) {
- if (bcd_iter->type == type) {
- bcd_reference_current = bcd_iter;
- break;
- }
- bcd_iter = bcd_iter->next;
- }
- }
- }
- }
-
- if (create) {
- bcd = MEM_callocN(sizeof(BArrayCustomData) + (layer_len * sizeof(BArrayState *)), __func__);
- bcd->next = NULL;
- bcd->type = type;
- bcd->states_len = layer_end - layer_start;
-
- if (bcd_prev) {
- bcd_prev->next = bcd;
- bcd_prev = bcd;
- }
- else {
- bcd_first = bcd;
- bcd_prev = bcd;
- }
- }
-
- CustomDataLayer *layer = &cdata->layers[layer_start];
- for (int i = 0; i < layer_len; i++, layer++) {
- if (create) {
- if (layer->data) {
- BArrayState *state_reference =
- (bcd_reference_current && i < bcd_reference_current->states_len) ?
- bcd_reference_current->states[i] : NULL;
- bcd->states[i] = BLI_array_store_state_add(
- bs, layer->data, (size_t)data_len * stride, state_reference);
- }
- else {
- bcd->states[i] = NULL;
- }
- }
-
- if (layer->data) {
- MEM_freeN(layer->data);
- layer->data = NULL;
- }
- }
-
- if (create) {
- if (bcd_reference_current) {
- bcd_reference_current = bcd_reference_current->next;
- }
- }
- }
-
- if (create) {
- *r_bcd_first = bcd_first;
- }
+ if (data_len == 0) {
+ if (create) {
+ *r_bcd_first = NULL;
+ }
+ }
+
+ const BArrayCustomData *bcd_reference_current = bcd_reference;
+ BArrayCustomData *bcd = NULL, *bcd_first = NULL, *bcd_prev = NULL;
+ for (int layer_start = 0, layer_end; layer_start < cdata->totlayer; layer_start = layer_end) {
+ const CustomDataType type = cdata->layers[layer_start].type;
+
+ layer_end = layer_start + 1;
+ while ((layer_end < cdata->totlayer) && (type == cdata->layers[layer_end].type)) {
+ layer_end++;
+ }
+
+ const int stride = CustomData_sizeof(type);
+ BArrayStore *bs = create ? BLI_array_store_at_size_ensure(
+ &um_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE) :
+ NULL;
+ const int layer_len = layer_end - layer_start;
+
+ if (create) {
+ if (bcd_reference_current && (bcd_reference_current->type == type)) {
+ /* common case, the reference is aligned */
+ }
+ else {
+ bcd_reference_current = NULL;
+
+ /* do a full lookup when un-alligned */
+ if (bcd_reference) {
+ const BArrayCustomData *bcd_iter = bcd_reference;
+ while (bcd_iter) {
+ if (bcd_iter->type == type) {
+ bcd_reference_current = bcd_iter;
+ break;
+ }
+ bcd_iter = bcd_iter->next;
+ }
+ }
+ }
+ }
+
+ if (create) {
+ bcd = MEM_callocN(sizeof(BArrayCustomData) + (layer_len * sizeof(BArrayState *)), __func__);
+ bcd->next = NULL;
+ bcd->type = type;
+ bcd->states_len = layer_end - layer_start;
+
+ if (bcd_prev) {
+ bcd_prev->next = bcd;
+ bcd_prev = bcd;
+ }
+ else {
+ bcd_first = bcd;
+ bcd_prev = bcd;
+ }
+ }
+
+ CustomDataLayer *layer = &cdata->layers[layer_start];
+ for (int i = 0; i < layer_len; i++, layer++) {
+ if (create) {
+ if (layer->data) {
+ BArrayState *state_reference = (bcd_reference_current &&
+ i < bcd_reference_current->states_len) ?
+ bcd_reference_current->states[i] :
+ NULL;
+ bcd->states[i] = BLI_array_store_state_add(
+ bs, layer->data, (size_t)data_len * stride, state_reference);
+ }
+ else {
+ bcd->states[i] = NULL;
+ }
+ }
+
+ if (layer->data) {
+ MEM_freeN(layer->data);
+ layer->data = NULL;
+ }
+ }
+
+ if (create) {
+ if (bcd_reference_current) {
+ bcd_reference_current = bcd_reference_current->next;
+ }
+ }
+ }
+
+ if (create) {
+ *r_bcd_first = bcd_first;
+ }
}
/**
* \note There is no room for data going out of sync here.
* The layers and the states are stored together so this can be kept working.
*/
-static void um_arraystore_cd_expand(
- const BArrayCustomData *bcd, struct CustomData *cdata, const size_t data_len)
+static void um_arraystore_cd_expand(const BArrayCustomData *bcd,
+ struct CustomData *cdata,
+ const size_t data_len)
{
- CustomDataLayer *layer = cdata->layers;
- while (bcd) {
- const int stride = CustomData_sizeof(bcd->type);
- for (int i = 0; i < bcd->states_len; i++) {
- BLI_assert(bcd->type == layer->type);
- if (bcd->states[i]) {
- size_t state_len;
- layer->data = BLI_array_store_state_data_get_alloc(bcd->states[i], &state_len);
- BLI_assert(stride * data_len == state_len);
- UNUSED_VARS_NDEBUG(stride, data_len);
- }
- else {
- layer->data = NULL;
- }
- layer++;
- }
- bcd = bcd->next;
- }
+ CustomDataLayer *layer = cdata->layers;
+ while (bcd) {
+ const int stride = CustomData_sizeof(bcd->type);
+ for (int i = 0; i < bcd->states_len; i++) {
+ BLI_assert(bcd->type == layer->type);
+ if (bcd->states[i]) {
+ size_t state_len;
+ layer->data = BLI_array_store_state_data_get_alloc(bcd->states[i], &state_len);
+ BLI_assert(stride * data_len == state_len);
+ UNUSED_VARS_NDEBUG(stride, data_len);
+ }
+ else {
+ layer->data = NULL;
+ }
+ layer++;
+ }
+ bcd = bcd->next;
+ }
}
static void um_arraystore_cd_free(BArrayCustomData *bcd)
{
- while (bcd) {
- BArrayCustomData *bcd_next = bcd->next;
- const int stride = CustomData_sizeof(bcd->type);
- BArrayStore *bs = BLI_array_store_at_size_get(&um_arraystore.bs_stride, stride);
- for (int i = 0; i < bcd->states_len; i++) {
- if (bcd->states[i]) {
- BLI_array_store_state_remove(bs, bcd->states[i]);
- }
- }
- MEM_freeN(bcd);
- bcd = bcd_next;
- }
+ while (bcd) {
+ BArrayCustomData *bcd_next = bcd->next;
+ const int stride = CustomData_sizeof(bcd->type);
+ BArrayStore *bs = BLI_array_store_at_size_get(&um_arraystore.bs_stride, stride);
+ for (int i = 0; i < bcd->states_len; i++) {
+ if (bcd->states[i]) {
+ BLI_array_store_state_remove(bs, bcd->states[i]);
+ }
+ }
+ MEM_freeN(bcd);
+ bcd = bcd_next;
+ }
}
/**
@@ -279,61 +280,65 @@ static void um_arraystore_cd_free(BArrayCustomData *bcd)
* This is done since when reading from an undo state, they must be temporarily expanded.
* then discarded afterwards, having this argument avoids having 2x code paths.
*/
-static void um_arraystore_compact_ex(
- UndoMesh *um, const UndoMesh *um_ref,
- bool create)
+static void um_arraystore_compact_ex(UndoMesh *um, const UndoMesh *um_ref, bool create)
{
- Mesh *me = &um->me;
-
- um_arraystore_cd_compact(&me->vdata, me->totvert, create, um_ref ? um_ref->store.vdata : NULL, &um->store.vdata);
- um_arraystore_cd_compact(&me->edata, me->totedge, create, um_ref ? um_ref->store.edata : NULL, &um->store.edata);
- um_arraystore_cd_compact(&me->ldata, me->totloop, create, um_ref ? um_ref->store.ldata : NULL, &um->store.ldata);
- um_arraystore_cd_compact(&me->pdata, me->totpoly, create, um_ref ? um_ref->store.pdata : NULL, &um->store.pdata);
-
- if (me->key && me->key->totkey) {
- const size_t stride = me->key->elemsize;
- BArrayStore *bs = create ? BLI_array_store_at_size_ensure(&um_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE) : NULL;
- if (create) {
- um->store.keyblocks = MEM_mallocN(me->key->totkey * sizeof(*um->store.keyblocks), __func__);
- }
- KeyBlock *keyblock = me->key->block.first;
- for (int i = 0; i < me->key->totkey; i++, keyblock = keyblock->next) {
- if (create) {
- BArrayState *state_reference =
- (um_ref && um_ref->me.key && (i < um_ref->me.key->totkey)) ?
- um_ref->store.keyblocks[i] : NULL;
- um->store.keyblocks[i] = BLI_array_store_state_add(
- bs, keyblock->data, (size_t)keyblock->totelem * stride,
- state_reference);
- }
-
- if (keyblock->data) {
- MEM_freeN(keyblock->data);
- keyblock->data = NULL;
- }
- }
- }
-
- if (me->mselect && me->totselect) {
- BLI_assert(create == (um->store.mselect == NULL));
- if (create) {
- BArrayState *state_reference = um_ref ? um_ref->store.mselect : NULL;
- const size_t stride = sizeof(*me->mselect);
- BArrayStore *bs = BLI_array_store_at_size_ensure(&um_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE);
- um->store.mselect = BLI_array_store_state_add(
- bs, me->mselect, (size_t)me->totselect * stride, state_reference);
- }
-
- /* keep me->totselect for validation */
- MEM_freeN(me->mselect);
- me->mselect = NULL;
- }
-
- if (create) {
- um_arraystore.users += 1;
- }
-
- BKE_mesh_update_customdata_pointers(me, false);
+ Mesh *me = &um->me;
+
+ um_arraystore_cd_compact(
+ &me->vdata, me->totvert, create, um_ref ? um_ref->store.vdata : NULL, &um->store.vdata);
+ um_arraystore_cd_compact(
+ &me->edata, me->totedge, create, um_ref ? um_ref->store.edata : NULL, &um->store.edata);
+ um_arraystore_cd_compact(
+ &me->ldata, me->totloop, create, um_ref ? um_ref->store.ldata : NULL, &um->store.ldata);
+ um_arraystore_cd_compact(
+ &me->pdata, me->totpoly, create, um_ref ? um_ref->store.pdata : NULL, &um->store.pdata);
+
+ if (me->key && me->key->totkey) {
+ const size_t stride = me->key->elemsize;
+ BArrayStore *bs = create ? BLI_array_store_at_size_ensure(
+ &um_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE) :
+ NULL;
+ if (create) {
+ um->store.keyblocks = MEM_mallocN(me->key->totkey * sizeof(*um->store.keyblocks), __func__);
+ }
+ KeyBlock *keyblock = me->key->block.first;
+ for (int i = 0; i < me->key->totkey; i++, keyblock = keyblock->next) {
+ if (create) {
+ BArrayState *state_reference = (um_ref && um_ref->me.key && (i < um_ref->me.key->totkey)) ?
+ um_ref->store.keyblocks[i] :
+ NULL;
+ um->store.keyblocks[i] = BLI_array_store_state_add(
+ bs, keyblock->data, (size_t)keyblock->totelem * stride, state_reference);
+ }
+
+ if (keyblock->data) {
+ MEM_freeN(keyblock->data);
+ keyblock->data = NULL;
+ }
+ }
+ }
+
+ if (me->mselect && me->totselect) {
+ BLI_assert(create == (um->store.mselect == NULL));
+ if (create) {
+ BArrayState *state_reference = um_ref ? um_ref->store.mselect : NULL;
+ const size_t stride = sizeof(*me->mselect);
+ BArrayStore *bs = BLI_array_store_at_size_ensure(
+ &um_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE);
+ um->store.mselect = BLI_array_store_state_add(
+ bs, me->mselect, (size_t)me->totselect * stride, state_reference);
+ }
+
+ /* keep me->totselect for validation */
+ MEM_freeN(me->mselect);
+ me->mselect = NULL;
+ }
+
+ if (create) {
+ um_arraystore.users += 1;
+ }
+
+ BKE_mesh_update_customdata_pointers(me, false);
}
/**
@@ -341,332 +346,341 @@ static void um_arraystore_compact_ex(
*/
static void um_arraystore_compact(UndoMesh *um, const UndoMesh *um_ref)
{
- um_arraystore_compact_ex(um, um_ref, true);
+ um_arraystore_compact_ex(um, um_ref, true);
}
static void um_arraystore_compact_with_info(UndoMesh *um, const UndoMesh *um_ref)
{
-#ifdef DEBUG_PRINT
- size_t size_expanded_prev, size_compacted_prev;
- BLI_array_store_at_size_calc_memory_usage(&um_arraystore.bs_stride, &size_expanded_prev, &size_compacted_prev);
-#endif
-
-#ifdef DEBUG_TIME
- TIMEIT_START(mesh_undo_compact);
-#endif
-
- um_arraystore_compact(um, um_ref);
-
-#ifdef DEBUG_TIME
- TIMEIT_END(mesh_undo_compact);
-#endif
+# ifdef DEBUG_PRINT
+ size_t size_expanded_prev, size_compacted_prev;
+ BLI_array_store_at_size_calc_memory_usage(
+ &um_arraystore.bs_stride, &size_expanded_prev, &size_compacted_prev);
+# endif
-#ifdef DEBUG_PRINT
- {
- size_t size_expanded, size_compacted;
- BLI_array_store_at_size_calc_memory_usage(&um_arraystore.bs_stride, &size_expanded, &size_compacted);
+# ifdef DEBUG_TIME
+ TIMEIT_START(mesh_undo_compact);
+# endif
- const double percent_total = size_expanded ?
- (((double)size_compacted / (double)size_expanded) * 100.0) : -1.0;
+ um_arraystore_compact(um, um_ref);
- size_t size_expanded_step = size_expanded - size_expanded_prev;
- size_t size_compacted_step = size_compacted - size_compacted_prev;
- const double percent_step = size_expanded_step ?
- (((double)size_compacted_step / (double)size_expanded_step) * 100.0) : -1.0;
+# ifdef DEBUG_TIME
+ TIMEIT_END(mesh_undo_compact);
+# endif
- printf("overall memory use: %.8f%% of expanded size\n", percent_total);
- printf("step memory use: %.8f%% of expanded size\n", percent_step);
- }
-#endif
+# ifdef DEBUG_PRINT
+ {
+ size_t size_expanded, size_compacted;
+ BLI_array_store_at_size_calc_memory_usage(
+ &um_arraystore.bs_stride, &size_expanded, &size_compacted);
+
+ const double percent_total = size_expanded ?
+ (((double)size_compacted / (double)size_expanded) * 100.0) :
+ -1.0;
+
+ size_t size_expanded_step = size_expanded - size_expanded_prev;
+ size_t size_compacted_step = size_compacted - size_compacted_prev;
+ const double percent_step = size_expanded_step ?
+ (((double)size_compacted_step / (double)size_expanded_step) *
+ 100.0) :
+ -1.0;
+
+ printf("overall memory use: %.8f%% of expanded size\n", percent_total);
+ printf("step memory use: %.8f%% of expanded size\n", percent_step);
+ }
+# endif
}
-#ifdef USE_ARRAY_STORE_THREAD
+# ifdef USE_ARRAY_STORE_THREAD
struct UMArrayData {
- UndoMesh *um;
- const UndoMesh *um_ref; /* can be NULL */
+ UndoMesh *um;
+ const UndoMesh *um_ref; /* can be NULL */
};
static void um_arraystore_compact_cb(TaskPool *__restrict UNUSED(pool),
void *taskdata,
int UNUSED(threadid))
{
- struct UMArrayData *um_data = taskdata;
- um_arraystore_compact_with_info(um_data->um, um_data->um_ref);
+ struct UMArrayData *um_data = taskdata;
+ um_arraystore_compact_with_info(um_data->um, um_data->um_ref);
}
-#endif /* USE_ARRAY_STORE_THREAD */
+# endif /* USE_ARRAY_STORE_THREAD */
/**
* Remove data we only expanded for temporary use.
*/
static void um_arraystore_expand_clear(UndoMesh *um)
{
- um_arraystore_compact_ex(um, NULL, false);
+ um_arraystore_compact_ex(um, NULL, false);
}
static void um_arraystore_expand(UndoMesh *um)
{
- Mesh *me = &um->me;
-
- um_arraystore_cd_expand(um->store.vdata, &me->vdata, me->totvert);
- um_arraystore_cd_expand(um->store.edata, &me->edata, me->totedge);
- um_arraystore_cd_expand(um->store.ldata, &me->ldata, me->totloop);
- um_arraystore_cd_expand(um->store.pdata, &me->pdata, me->totpoly);
-
- if (um->store.keyblocks) {
- const size_t stride = me->key->elemsize;
- KeyBlock *keyblock = me->key->block.first;
- for (int i = 0; i < me->key->totkey; i++, keyblock = keyblock->next) {
- BArrayState *state = um->store.keyblocks[i];
- size_t state_len;
- keyblock->data = BLI_array_store_state_data_get_alloc(state, &state_len);
- BLI_assert(keyblock->totelem == (state_len / stride));
- UNUSED_VARS_NDEBUG(stride);
- }
- }
-
- if (um->store.mselect) {
- const size_t stride = sizeof(*me->mselect);
- BArrayState *state = um->store.mselect;
- size_t state_len;
- me->mselect = BLI_array_store_state_data_get_alloc(state, &state_len);
- BLI_assert(me->totselect == (state_len / stride));
- UNUSED_VARS_NDEBUG(stride);
- }
-
- /* not essential, but prevents accidental dangling pointer access */
- BKE_mesh_update_customdata_pointers(me, false);
+ Mesh *me = &um->me;
+
+ um_arraystore_cd_expand(um->store.vdata, &me->vdata, me->totvert);
+ um_arraystore_cd_expand(um->store.edata, &me->edata, me->totedge);
+ um_arraystore_cd_expand(um->store.ldata, &me->ldata, me->totloop);
+ um_arraystore_cd_expand(um->store.pdata, &me->pdata, me->totpoly);
+
+ if (um->store.keyblocks) {
+ const size_t stride = me->key->elemsize;
+ KeyBlock *keyblock = me->key->block.first;
+ for (int i = 0; i < me->key->totkey; i++, keyblock = keyblock->next) {
+ BArrayState *state = um->store.keyblocks[i];
+ size_t state_len;
+ keyblock->data = BLI_array_store_state_data_get_alloc(state, &state_len);
+ BLI_assert(keyblock->totelem == (state_len / stride));
+ UNUSED_VARS_NDEBUG(stride);
+ }
+ }
+
+ if (um->store.mselect) {
+ const size_t stride = sizeof(*me->mselect);
+ BArrayState *state = um->store.mselect;
+ size_t state_len;
+ me->mselect = BLI_array_store_state_data_get_alloc(state, &state_len);
+ BLI_assert(me->totselect == (state_len / stride));
+ UNUSED_VARS_NDEBUG(stride);
+ }
+
+ /* not essential, but prevents accidental dangling pointer access */
+ BKE_mesh_update_customdata_pointers(me, false);
}
static void um_arraystore_free(UndoMesh *um)
{
- Mesh *me = &um->me;
-
- um_arraystore_cd_free(um->store.vdata);
- um_arraystore_cd_free(um->store.edata);
- um_arraystore_cd_free(um->store.ldata);
- um_arraystore_cd_free(um->store.pdata);
-
- if (um->store.keyblocks) {
- const size_t stride = me->key->elemsize;
- BArrayStore *bs = BLI_array_store_at_size_get(&um_arraystore.bs_stride, stride);
- for (int i = 0; i < me->key->totkey; i++) {
- BArrayState *state = um->store.keyblocks[i];
- BLI_array_store_state_remove(bs, state);
- }
- MEM_freeN(um->store.keyblocks);
- um->store.keyblocks = NULL;
- }
-
- if (um->store.mselect) {
- const size_t stride = sizeof(*me->mselect);
- BArrayStore *bs = BLI_array_store_at_size_get(&um_arraystore.bs_stride, stride);
- BArrayState *state = um->store.mselect;
- BLI_array_store_state_remove(bs, state);
- um->store.mselect = NULL;
- }
-
- um_arraystore.users -= 1;
-
- BLI_assert(um_arraystore.users >= 0);
-
- if (um_arraystore.users == 0) {
-#ifdef DEBUG_PRINT
- printf("mesh undo store: freeing all data!\n");
-#endif
- BLI_array_store_at_size_clear(&um_arraystore.bs_stride);
-
-#ifdef USE_ARRAY_STORE_THREAD
- BLI_task_pool_free(um_arraystore.task_pool);
- um_arraystore.task_pool = NULL;
-#endif
- }
+ Mesh *me = &um->me;
+
+ um_arraystore_cd_free(um->store.vdata);
+ um_arraystore_cd_free(um->store.edata);
+ um_arraystore_cd_free(um->store.ldata);
+ um_arraystore_cd_free(um->store.pdata);
+
+ if (um->store.keyblocks) {
+ const size_t stride = me->key->elemsize;
+ BArrayStore *bs = BLI_array_store_at_size_get(&um_arraystore.bs_stride, stride);
+ for (int i = 0; i < me->key->totkey; i++) {
+ BArrayState *state = um->store.keyblocks[i];
+ BLI_array_store_state_remove(bs, state);
+ }
+ MEM_freeN(um->store.keyblocks);
+ um->store.keyblocks = NULL;
+ }
+
+ if (um->store.mselect) {
+ const size_t stride = sizeof(*me->mselect);
+ BArrayStore *bs = BLI_array_store_at_size_get(&um_arraystore.bs_stride, stride);
+ BArrayState *state = um->store.mselect;
+ BLI_array_store_state_remove(bs, state);
+ um->store.mselect = NULL;
+ }
+
+ um_arraystore.users -= 1;
+
+ BLI_assert(um_arraystore.users >= 0);
+
+ if (um_arraystore.users == 0) {
+# ifdef DEBUG_PRINT
+ printf("mesh undo store: freeing all data!\n");
+# endif
+ BLI_array_store_at_size_clear(&um_arraystore.bs_stride);
+# ifdef USE_ARRAY_STORE_THREAD
+ BLI_task_pool_free(um_arraystore.task_pool);
+ um_arraystore.task_pool = NULL;
+# endif
+ }
}
/** \} */
-#endif /* USE_ARRAY_STORE */
-
+#endif /* USE_ARRAY_STORE */
/* for callbacks */
/* undo simply makes copies of a bmesh */
static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key)
{
- BLI_assert(BLI_array_is_zeroed(um, 1));
+ BLI_assert(BLI_array_is_zeroed(um, 1));
#ifdef USE_ARRAY_STORE_THREAD
- /* changes this waits is low, but must have finished */
- if (um_arraystore.task_pool) {
- BLI_task_pool_work_and_wait(um_arraystore.task_pool);
- }
+ /* changes this waits is low, but must have finished */
+ if (um_arraystore.task_pool) {
+ BLI_task_pool_work_and_wait(um_arraystore.task_pool);
+ }
#endif
- /* make sure shape keys work */
- um->me.key = key ? BKE_key_copy_nolib(key) : NULL;
+ /* make sure shape keys work */
+ um->me.key = key ? BKE_key_copy_nolib(key) : NULL;
- /* BM_mesh_validate(em->bm); */ /* for troubleshooting */
+ /* BM_mesh_validate(em->bm); */ /* for troubleshooting */
- BM_mesh_bm_to_me(
- NULL, em->bm, &um->me, (&(struct BMeshToMeshParams){
- /* Undo code should not be manipulating 'G_MAIN->object' hooks/vertex-parent. */
- .calc_object_remap = false,
- .cd_mask_extra = {.vmask = CD_MASK_SHAPE_KEYINDEX},
- }));
+ BM_mesh_bm_to_me(
+ NULL,
+ em->bm,
+ &um->me,
+ (&(struct BMeshToMeshParams){
+ /* Undo code should not be manipulating 'G_MAIN->object' hooks/vertex-parent. */
+ .calc_object_remap = false,
+ .cd_mask_extra = {.vmask = CD_MASK_SHAPE_KEYINDEX},
+ }));
- um->selectmode = em->selectmode;
- um->shapenr = em->bm->shapenr;
+ um->selectmode = em->selectmode;
+ um->shapenr = em->bm->shapenr;
#ifdef USE_ARRAY_STORE
- {
- /* We could be more clever here,
- * the previous undo state may be from a separate mesh. */
- const UndoMesh *um_ref = um_arraystore.local_links.last ?
- ((LinkData *)um_arraystore.local_links.last)->data : NULL;
-
- /* add oursrlves */
- BLI_addtail(&um_arraystore.local_links, BLI_genericNodeN(um));
-
-#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);
- }
-
- 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);
-#else
- um_arraystore_compact_with_info(um, um_ref);
-#endif
- }
+ {
+ /* We could be more clever here,
+ * the previous undo state may be from a separate mesh. */
+ const UndoMesh *um_ref = um_arraystore.local_links.last ?
+ ((LinkData *)um_arraystore.local_links.last)->data :
+ NULL;
+
+ /* add oursrlves */
+ BLI_addtail(&um_arraystore.local_links, BLI_genericNodeN(um));
+
+# 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);
+ }
+
+ 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);
+# else
+ um_arraystore_compact_with_info(um, um_ref);
+# endif
+ }
#endif
- return um;
+ return um;
}
static void undomesh_to_editmesh(UndoMesh *um, BMEditMesh *em, Mesh *obmesh)
{
- BMEditMesh *em_tmp;
- Object *ob = em->ob;
- BMesh *bm;
- Key *key = obmesh->key;
+ BMEditMesh *em_tmp;
+ Object *ob = em->ob;
+ BMesh *bm;
+ Key *key = obmesh->key;
#ifdef USE_ARRAY_STORE
-#ifdef USE_ARRAY_STORE_THREAD
- /* changes this waits is low, but must have finished */
- BLI_task_pool_work_and_wait(um_arraystore.task_pool);
-#endif
+# ifdef USE_ARRAY_STORE_THREAD
+ /* changes this waits is low, but must have finished */
+ BLI_task_pool_work_and_wait(um_arraystore.task_pool);
+# endif
-#ifdef DEBUG_TIME
- TIMEIT_START(mesh_undo_expand);
-#endif
+# ifdef DEBUG_TIME
+ TIMEIT_START(mesh_undo_expand);
+# endif
- um_arraystore_expand(um);
+ um_arraystore_expand(um);
-#ifdef DEBUG_TIME
- TIMEIT_END(mesh_undo_expand);
-#endif
-#endif /* USE_ARRAY_STORE */
+# ifdef DEBUG_TIME
+ TIMEIT_END(mesh_undo_expand);
+# endif
+#endif /* USE_ARRAY_STORE */
- const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(&um->me);
+ const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(&um->me);
- em->bm->shapenr = um->shapenr;
+ em->bm->shapenr = um->shapenr;
- EDBM_mesh_free(em);
+ EDBM_mesh_free(em);
- bm = BM_mesh_create(
- &allocsize,
- &((struct BMeshCreateParams){.use_toolflags = true,}));
+ bm = BM_mesh_create(&allocsize,
+ &((struct BMeshCreateParams){
+ .use_toolflags = true,
+ }));
- BM_mesh_bm_from_me(
- bm, &um->me, (&(struct BMeshFromMeshParams){
- .calc_face_normal = true, .active_shapekey = um->shapenr,
- }));
+ BM_mesh_bm_from_me(bm,
+ &um->me,
+ (&(struct BMeshFromMeshParams){
+ .calc_face_normal = true,
+ .active_shapekey = um->shapenr,
+ }));
- em_tmp = BKE_editmesh_create(bm, true);
- *em = *em_tmp;
+ em_tmp = BKE_editmesh_create(bm, true);
+ *em = *em_tmp;
- em->selectmode = um->selectmode;
- bm->selectmode = um->selectmode;
- em->ob = ob;
+ em->selectmode = um->selectmode;
+ bm->selectmode = um->selectmode;
+ em->ob = ob;
- bm->spacearr_dirty = BM_SPACEARR_DIRTY_ALL;
+ bm->spacearr_dirty = BM_SPACEARR_DIRTY_ALL;
- /* T35170: Restore the active key on the RealMesh. Otherwise 'fake' offset propagation happens
- * if the active is a basis for any other. */
- if (key && (key->type == KEY_RELATIVE)) {
- /* Since we can't add, remove or reorder keyblocks in editmode, it's safe to assume
- * shapenr from restored bmesh and keyblock indices are in sync. */
- const int kb_act_idx = ob->shapenr - 1;
+ /* T35170: Restore the active key on the RealMesh. Otherwise 'fake' offset propagation happens
+ * if the active is a basis for any other. */
+ if (key && (key->type == KEY_RELATIVE)) {
+ /* Since we can't add, remove or reorder keyblocks in editmode, it's safe to assume
+ * shapenr from restored bmesh and keyblock indices are in sync. */
+ const int kb_act_idx = ob->shapenr - 1;
- /* If it is, let's patch the current mesh key block to its restored value.
- * Else, the offsets won't be computed and it won't matter. */
- if (BKE_keyblock_is_basis(key, kb_act_idx)) {
- KeyBlock *kb_act = BLI_findlink(&key->block, kb_act_idx);
+ /* If it is, let's patch the current mesh key block to its restored value.
+ * Else, the offsets won't be computed and it won't matter. */
+ if (BKE_keyblock_is_basis(key, kb_act_idx)) {
+ KeyBlock *kb_act = BLI_findlink(&key->block, kb_act_idx);
- if (kb_act->totelem != um->me.totvert) {
- /* The current mesh has some extra/missing verts compared to the undo, adjust. */
- MEM_SAFE_FREE(kb_act->data);
- kb_act->data = MEM_mallocN((size_t)(key->elemsize * bm->totvert), __func__);
- kb_act->totelem = um->me.totvert;
- }
+ if (kb_act->totelem != um->me.totvert) {
+ /* The current mesh has some extra/missing verts compared to the undo, adjust. */
+ MEM_SAFE_FREE(kb_act->data);
+ kb_act->data = MEM_mallocN((size_t)(key->elemsize * bm->totvert), __func__);
+ kb_act->totelem = um->me.totvert;
+ }
- BKE_keyblock_update_from_mesh(&um->me, kb_act);
- }
- }
+ BKE_keyblock_update_from_mesh(&um->me, kb_act);
+ }
+ }
- ob->shapenr = um->shapenr;
+ ob->shapenr = um->shapenr;
- MEM_freeN(em_tmp);
+ MEM_freeN(em_tmp);
#ifdef USE_ARRAY_STORE
- um_arraystore_expand_clear(um);
+ um_arraystore_expand_clear(um);
#endif
}
static void undomesh_free_data(UndoMesh *um)
{
- Mesh *me = &um->me;
+ Mesh *me = &um->me;
#ifdef USE_ARRAY_STORE
-#ifdef USE_ARRAY_STORE_THREAD
- /* changes this waits is low, but must have finished */
- BLI_task_pool_work_and_wait(um_arraystore.task_pool);
-#endif
+# ifdef USE_ARRAY_STORE_THREAD
+ /* changes this waits is low, but must have finished */
+ BLI_task_pool_work_and_wait(um_arraystore.task_pool);
+# endif
- /* we need to expand so any allocations in custom-data are freed with the mesh */
- um_arraystore_expand(um);
+ /* we need to expand so any allocations in custom-data are freed with the mesh */
+ um_arraystore_expand(um);
- {
- LinkData *link = BLI_findptr(&um_arraystore.local_links, um, offsetof(LinkData, data));
- BLI_remlink(&um_arraystore.local_links, link);
- MEM_freeN(link);
- }
- um_arraystore_free(um);
+ {
+ LinkData *link = BLI_findptr(&um_arraystore.local_links, um, offsetof(LinkData, data));
+ BLI_remlink(&um_arraystore.local_links, link);
+ MEM_freeN(link);
+ }
+ um_arraystore_free(um);
#endif
- if (me->key) {
- BKE_key_free(me->key);
- MEM_freeN(me->key);
- }
+ if (me->key) {
+ BKE_key_free(me->key);
+ MEM_freeN(me->key);
+ }
- BKE_mesh_free(me);
+ BKE_mesh_free(me);
}
static Object *editmesh_object_from_context(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_MESH) {
- Mesh *me = obedit->data;
- if (me->edit_mesh != NULL) {
- return obedit;
- }
- }
- return NULL;
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_MESH) {
+ Mesh *me = obedit->data;
+ if (me->edit_mesh != NULL) {
+ return obedit;
+ }
+ }
+ return NULL;
}
/** \} */
@@ -678,126 +692,137 @@ static Object *editmesh_object_from_context(bContext *C)
* \{ */
typedef struct MeshUndoStep_Elem {
- struct MeshUndoStep_Elem *next, *prev;
- UndoRefID_Object obedit_ref;
- UndoMesh data;
+ struct MeshUndoStep_Elem *next, *prev;
+ UndoRefID_Object obedit_ref;
+ UndoMesh data;
} MeshUndoStep_Elem;
typedef struct MeshUndoStep {
- UndoStep step;
- struct UndoIDPtrMap *id_map;
- MeshUndoStep_Elem *elems;
- uint elems_len;
+ UndoStep step;
+ struct UndoIDPtrMap *id_map;
+ MeshUndoStep_Elem *elems;
+ uint elems_len;
} MeshUndoStep;
static bool mesh_undosys_poll(bContext *C)
{
- return editmesh_object_from_context(C) != NULL;
+ return editmesh_object_from_context(C) != NULL;
}
-static bool mesh_undosys_step_encode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p)
+static bool mesh_undosys_step_encode(struct bContext *C,
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p)
{
- MeshUndoStep *us = (MeshUndoStep *)us_p;
-
- /* Important not to use the 3D view when getting objects because all objects
- * 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);
-
- us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
- us->elems_len = objects_len;
-
- for (uint i = 0; i < objects_len; i++) {
- Object *ob = objects[i];
- MeshUndoStep_Elem *elem = &us->elems[i];
-
- elem->obedit_ref.ptr = ob;
- Mesh *me = elem->obedit_ref.ptr->data;
- undomesh_from_editmesh(&elem->data, me->edit_mesh, me->key);
- us->step.data_size += elem->data.undo_size;
- }
- MEM_freeN(objects);
- return true;
+ MeshUndoStep *us = (MeshUndoStep *)us_p;
+
+ /* Important not to use the 3D view when getting objects because all objects
+ * 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);
+
+ us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
+ us->elems_len = objects_len;
+
+ for (uint i = 0; i < objects_len; i++) {
+ Object *ob = objects[i];
+ MeshUndoStep_Elem *elem = &us->elems[i];
+
+ elem->obedit_ref.ptr = ob;
+ Mesh *me = elem->obedit_ref.ptr->data;
+ undomesh_from_editmesh(&elem->data, me->edit_mesh, me->key);
+ us->step.data_size += elem->data.undo_size;
+ }
+ MEM_freeN(objects);
+ return true;
}
-static void mesh_undosys_step_decode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p, int UNUSED(dir))
+static void mesh_undosys_step_decode(struct bContext *C,
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p,
+ int UNUSED(dir))
{
- MeshUndoStep *us = (MeshUndoStep *)us_p;
-
- /* Load all our objects into edit-mode, clear everything else. */
- ED_undo_object_editmode_restore_helper(C, &us->elems[0].obedit_ref.ptr, us->elems_len, sizeof(*us->elems));
-
- BLI_assert(mesh_undosys_poll(C));
-
- for (uint i = 0; i < us->elems_len; i++) {
- MeshUndoStep_Elem *elem = &us->elems[i];
- Object *obedit = elem->obedit_ref.ptr;
- Mesh *me = obedit->data;
- if (me->edit_mesh == NULL) {
- /* Should never fail, may not crash but can give odd behavior. */
- CLOG_ERROR(&LOG, "name='%s', failed to enter edit-mode for object '%s', undo state invalid",
- us_p->name, obedit->id.name);
- continue;
- }
- BMEditMesh *em = me->edit_mesh;
- undomesh_to_editmesh(&elem->data, em, obedit->data);
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
-
- /* The first element is always active */
- ED_undo_object_set_active_or_warn(CTX_data_view_layer(C), us->elems[0].obedit_ref.ptr, us_p->name, &LOG);
-
- Scene *scene = CTX_data_scene(C);
- scene->toolsettings->selectmode = us->elems[0].data.selectmode;
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+ MeshUndoStep *us = (MeshUndoStep *)us_p;
+
+ /* Load all our objects into edit-mode, clear everything else. */
+ ED_undo_object_editmode_restore_helper(
+ C, &us->elems[0].obedit_ref.ptr, us->elems_len, sizeof(*us->elems));
+
+ BLI_assert(mesh_undosys_poll(C));
+
+ for (uint i = 0; i < us->elems_len; i++) {
+ MeshUndoStep_Elem *elem = &us->elems[i];
+ Object *obedit = elem->obedit_ref.ptr;
+ Mesh *me = obedit->data;
+ if (me->edit_mesh == NULL) {
+ /* Should never fail, may not crash but can give odd behavior. */
+ CLOG_ERROR(&LOG,
+ "name='%s', failed to enter edit-mode for object '%s', undo state invalid",
+ us_p->name,
+ obedit->id.name);
+ continue;
+ }
+ BMEditMesh *em = me->edit_mesh;
+ undomesh_to_editmesh(&elem->data, em, obedit->data);
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ }
+
+ /* The first element is always active */
+ ED_undo_object_set_active_or_warn(
+ CTX_data_view_layer(C), us->elems[0].obedit_ref.ptr, us_p->name, &LOG);
+
+ Scene *scene = CTX_data_scene(C);
+ scene->toolsettings->selectmode = us->elems[0].data.selectmode;
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
}
static void mesh_undosys_step_free(UndoStep *us_p)
{
- MeshUndoStep *us = (MeshUndoStep *)us_p;
+ MeshUndoStep *us = (MeshUndoStep *)us_p;
- for (uint i = 0; i < us->elems_len; i++) {
- MeshUndoStep_Elem *elem = &us->elems[i];
- undomesh_free_data(&elem->data);
- }
- MEM_freeN(us->elems);
+ for (uint i = 0; i < us->elems_len; i++) {
+ MeshUndoStep_Elem *elem = &us->elems[i];
+ undomesh_free_data(&elem->data);
+ }
+ MEM_freeN(us->elems);
- if (us->id_map != NULL) {
- BKE_undosys_ID_map_destroy(us->id_map);
- }
+ if (us->id_map != NULL) {
+ BKE_undosys_ID_map_destroy(us->id_map);
+ }
}
-static void mesh_undosys_foreach_ID_ref(
- UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+static void mesh_undosys_foreach_ID_ref(UndoStep *us_p,
+ UndoTypeForEachIDRefFn foreach_ID_ref_fn,
+ void *user_data)
{
- MeshUndoStep *us = (MeshUndoStep *)us_p;
+ MeshUndoStep *us = (MeshUndoStep *)us_p;
- for (uint i = 0; i < us->elems_len; i++) {
- MeshUndoStep_Elem *elem = &us->elems[i];
- foreach_ID_ref_fn(user_data, ((UndoRefID *)&elem->obedit_ref));
- }
+ for (uint i = 0; i < us->elems_len; i++) {
+ MeshUndoStep_Elem *elem = &us->elems[i];
+ foreach_ID_ref_fn(user_data, ((UndoRefID *)&elem->obedit_ref));
+ }
- if (us->id_map != NULL) {
- BKE_undosys_ID_map_foreach_ID_ref(us->id_map, foreach_ID_ref_fn, user_data);
- }
+ if (us->id_map != NULL) {
+ BKE_undosys_ID_map_foreach_ID_ref(us->id_map, foreach_ID_ref_fn, user_data);
+ }
}
/* Export for ED_undo_sys. */
void ED_mesh_undosys_type(UndoType *ut)
{
- ut->name = "Edit Mesh";
- ut->poll = mesh_undosys_poll;
- ut->step_encode = mesh_undosys_step_encode;
- ut->step_decode = mesh_undosys_step_decode;
- ut->step_free = mesh_undosys_step_free;
+ ut->name = "Edit Mesh";
+ ut->poll = mesh_undosys_poll;
+ ut->step_encode = mesh_undosys_step_encode;
+ ut->step_decode = mesh_undosys_step_decode;
+ ut->step_free = mesh_undosys_step_free;
- ut->step_foreach_ID_ref = mesh_undosys_foreach_ID_ref;
+ ut->step_foreach_ID_ref = mesh_undosys_foreach_ID_ref;
- ut->use_context = true;
+ ut->use_context = true;
- ut->step_size = sizeof(MeshUndoStep);
+ ut->step_size = sizeof(MeshUndoStep);
}
/** \} */
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index f86a2388f87..1cb550fccc4 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -44,7 +44,7 @@
#include "DEG_depsgraph.h"
-#include "BKE_object.h" /* XXX. only for EDBM_mesh_load(). */
+#include "BKE_object.h" /* XXX. only for EDBM_mesh_load(). */
#include "WM_api.h"
#include "WM_types.h"
@@ -53,7 +53,7 @@
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Redo API
@@ -66,47 +66,47 @@
BMBackup EDBM_redo_state_store(BMEditMesh *em)
{
- BMBackup backup;
- backup.bmcopy = BM_mesh_copy(em->bm);
- return backup;
+ BMBackup backup;
+ backup.bmcopy = BM_mesh_copy(em->bm);
+ return backup;
}
void EDBM_redo_state_restore(BMBackup backup, BMEditMesh *em, int recalctess)
{
- BMesh *tmpbm;
- if (!em || !backup.bmcopy) {
- return;
- }
-
- BM_mesh_data_free(em->bm);
- tmpbm = BM_mesh_copy(backup.bmcopy);
- *em->bm = *tmpbm;
- MEM_freeN(tmpbm);
- tmpbm = NULL;
-
- if (recalctess) {
- BKE_editmesh_tessface_calc(em);
- }
+ BMesh *tmpbm;
+ if (!em || !backup.bmcopy) {
+ return;
+ }
+
+ BM_mesh_data_free(em->bm);
+ tmpbm = BM_mesh_copy(backup.bmcopy);
+ *em->bm = *tmpbm;
+ MEM_freeN(tmpbm);
+ tmpbm = NULL;
+
+ if (recalctess) {
+ BKE_editmesh_tessface_calc(em);
+ }
}
void EDBM_redo_state_free(BMBackup *backup, BMEditMesh *em, int recalctess)
{
- if (em && backup->bmcopy) {
- BM_mesh_data_free(em->bm);
- *em->bm = *backup->bmcopy;
- }
- else if (backup->bmcopy) {
- BM_mesh_data_free(backup->bmcopy);
- }
-
- if (backup->bmcopy) {
- MEM_freeN(backup->bmcopy);
- }
- backup->bmcopy = NULL;
-
- if (recalctess && em) {
- BKE_editmesh_tessface_calc(em);
- }
+ if (em && backup->bmcopy) {
+ BM_mesh_data_free(em->bm);
+ *em->bm = *backup->bmcopy;
+ }
+ else if (backup->bmcopy) {
+ BM_mesh_data_free(backup->bmcopy);
+ }
+
+ if (backup->bmcopy) {
+ MEM_freeN(backup->bmcopy);
+ }
+ backup->bmcopy = NULL;
+
+ if (recalctess && em) {
+ BKE_editmesh_tessface_calc(em);
+ }
}
/** \} */
@@ -117,163 +117,166 @@ void EDBM_redo_state_free(BMBackup *backup, BMEditMesh *em, int recalctess)
bool EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char *fmt, ...)
{
- BMesh *bm = em->bm;
- va_list list;
+ BMesh *bm = em->bm;
+ va_list list;
- va_start(list, fmt);
+ va_start(list, fmt);
- if (!BMO_op_vinitf(bm, bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
- BKE_reportf(op->reports, RPT_ERROR, "Parse error in %s", __func__);
- va_end(list);
- return false;
- }
+ if (!BMO_op_vinitf(bm, bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
+ BKE_reportf(op->reports, RPT_ERROR, "Parse error in %s", __func__);
+ va_end(list);
+ return false;
+ }
- if (!em->emcopy) {
- em->emcopy = BKE_editmesh_copy(em);
- }
- em->emcopyusers++;
+ if (!em->emcopy) {
+ em->emcopy = BKE_editmesh_copy(em);
+ }
+ em->emcopyusers++;
- va_end(list);
+ va_end(list);
- return true;
+ return true;
}
/* returns 0 on error, 1 on success. executes and finishes a bmesh operator */
bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool do_report)
{
- const char *errmsg;
-
- BMO_op_finish(em->bm, bmop);
-
- if (BMO_error_get(em->bm, &errmsg, NULL)) {
- BMEditMesh *emcopy = em->emcopy;
-
- if (do_report) {
- BKE_report(op->reports, RPT_ERROR, errmsg);
- }
-
- EDBM_mesh_free(em);
- *em = *emcopy;
-
- MEM_freeN(emcopy);
- em->emcopyusers = 0;
- em->emcopy = NULL;
-
- /* when copying, tessellation isn't to for faster copying,
- * but means we need to re-tessellate here */
- if (em->looptris == NULL) {
- BKE_editmesh_tessface_calc(em);
- }
-
- if (em->ob) {
- DEG_id_tag_update(&((Mesh *)em->ob->data)->id, ID_RECALC_COPY_ON_WRITE);
- }
-
- return false;
- }
- else {
- em->emcopyusers--;
- if (em->emcopyusers < 0) {
- printf("warning: em->emcopyusers was less than zero.\n");
- }
-
- if (em->emcopyusers <= 0) {
- BKE_editmesh_free(em->emcopy);
- MEM_freeN(em->emcopy);
- em->emcopy = NULL;
- }
-
- return true;
- }
+ const char *errmsg;
+
+ BMO_op_finish(em->bm, bmop);
+
+ if (BMO_error_get(em->bm, &errmsg, NULL)) {
+ BMEditMesh *emcopy = em->emcopy;
+
+ if (do_report) {
+ BKE_report(op->reports, RPT_ERROR, errmsg);
+ }
+
+ EDBM_mesh_free(em);
+ *em = *emcopy;
+
+ MEM_freeN(emcopy);
+ em->emcopyusers = 0;
+ em->emcopy = NULL;
+
+ /* when copying, tessellation isn't to for faster copying,
+ * but means we need to re-tessellate here */
+ if (em->looptris == NULL) {
+ BKE_editmesh_tessface_calc(em);
+ }
+
+ if (em->ob) {
+ DEG_id_tag_update(&((Mesh *)em->ob->data)->id, ID_RECALC_COPY_ON_WRITE);
+ }
+
+ return false;
+ }
+ else {
+ em->emcopyusers--;
+ if (em->emcopyusers < 0) {
+ printf("warning: em->emcopyusers was less than zero.\n");
+ }
+
+ if (em->emcopyusers <= 0) {
+ BKE_editmesh_free(em->emcopy);
+ MEM_freeN(em->emcopy);
+ em->emcopy = NULL;
+ }
+
+ return true;
+ }
}
bool EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...)
{
- BMesh *bm = em->bm;
- BMOperator bmop;
- va_list list;
+ BMesh *bm = em->bm;
+ BMOperator bmop;
+ va_list list;
- va_start(list, fmt);
+ va_start(list, fmt);
- if (!BMO_op_vinitf(bm, &bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
- BKE_reportf(op->reports, RPT_ERROR, "Parse error in %s", __func__);
- va_end(list);
- return false;
- }
+ if (!BMO_op_vinitf(bm, &bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
+ BKE_reportf(op->reports, RPT_ERROR, "Parse error in %s", __func__);
+ va_end(list);
+ return false;
+ }
- if (!em->emcopy) {
- em->emcopy = BKE_editmesh_copy(em);
- }
- em->emcopyusers++;
+ if (!em->emcopy) {
+ em->emcopy = BKE_editmesh_copy(em);
+ }
+ em->emcopyusers++;
- BMO_op_exec(bm, &bmop);
+ BMO_op_exec(bm, &bmop);
- va_end(list);
- return EDBM_op_finish(em, &bmop, op, true);
+ va_end(list);
+ return EDBM_op_finish(em, &bmop, op, true);
}
-bool EDBM_op_call_and_selectf(
- BMEditMesh *em, wmOperator *op,
- const char *select_slot_out, const bool select_extend,
- const char *fmt, ...)
+bool EDBM_op_call_and_selectf(BMEditMesh *em,
+ wmOperator *op,
+ const char *select_slot_out,
+ const bool select_extend,
+ const char *fmt,
+ ...)
{
- BMOpSlot *slot_select_out;
- BMesh *bm = em->bm;
- BMOperator bmop;
- va_list list;
- char hflag;
+ BMOpSlot *slot_select_out;
+ BMesh *bm = em->bm;
+ BMOperator bmop;
+ va_list list;
+ char hflag;
- va_start(list, fmt);
+ va_start(list, fmt);
- if (!BMO_op_vinitf(bm, &bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
- BKE_reportf(op->reports, RPT_ERROR, "Parse error in %s", __func__);
- va_end(list);
- return false;
- }
+ if (!BMO_op_vinitf(bm, &bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
+ BKE_reportf(op->reports, RPT_ERROR, "Parse error in %s", __func__);
+ va_end(list);
+ return false;
+ }
- if (!em->emcopy) {
- em->emcopy = BKE_editmesh_copy(em);
- }
- em->emcopyusers++;
+ if (!em->emcopy) {
+ em->emcopy = BKE_editmesh_copy(em);
+ }
+ em->emcopyusers++;
- BMO_op_exec(bm, &bmop);
+ BMO_op_exec(bm, &bmop);
- slot_select_out = BMO_slot_get(bmop.slots_out, select_slot_out);
- hflag = slot_select_out->slot_subtype.elem & BM_ALL_NOLOOP;
- BLI_assert(hflag != 0);
+ slot_select_out = BMO_slot_get(bmop.slots_out, select_slot_out);
+ hflag = slot_select_out->slot_subtype.elem & BM_ALL_NOLOOP;
+ BLI_assert(hflag != 0);
- if (select_extend == false) {
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
- }
+ if (select_extend == false) {
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
+ }
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, select_slot_out, hflag, BM_ELEM_SELECT, true);
+ BMO_slot_buffer_hflag_enable(
+ em->bm, bmop.slots_out, select_slot_out, hflag, BM_ELEM_SELECT, true);
- va_end(list);
- return EDBM_op_finish(em, &bmop, op, true);
+ va_end(list);
+ return EDBM_op_finish(em, &bmop, op, true);
}
bool EDBM_op_call_silentf(BMEditMesh *em, const char *fmt, ...)
{
- BMesh *bm = em->bm;
- BMOperator bmop;
- va_list list;
+ BMesh *bm = em->bm;
+ BMOperator bmop;
+ va_list list;
- va_start(list, fmt);
+ va_start(list, fmt);
- if (!BMO_op_vinitf(bm, &bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
- va_end(list);
- return false;
- }
+ if (!BMO_op_vinitf(bm, &bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
+ va_end(list);
+ return false;
+ }
- if (!em->emcopy) {
- em->emcopy = BKE_editmesh_copy(em);
- }
- em->emcopyusers++;
+ if (!em->emcopy) {
+ em->emcopy = BKE_editmesh_copy(em);
+ }
+ em->emcopyusers++;
- BMO_op_exec(bm, &bmop);
+ BMO_op_exec(bm, &bmop);
- va_end(list);
- return EDBM_op_finish(em, &bmop, NULL, false);
+ va_end(list);
+ return EDBM_op_finish(em, &bmop, NULL, false);
}
/** \} */
@@ -286,37 +289,40 @@ bool EDBM_op_call_silentf(BMEditMesh *em, const char *fmt, ...)
void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index)
{
- Mesh *me = ob->data;
- BMesh *bm;
-
- if (UNLIKELY(!me->mpoly && me->totface)) {
- BKE_mesh_convert_mfaces_to_mpolys(me);
- }
-
- bm = BKE_mesh_to_bmesh(
- me, ob, add_key_index,
- &((struct BMeshCreateParams){.use_toolflags = true,}));
-
- if (me->edit_mesh) {
- /* this happens when switching shape keys */
- EDBM_mesh_free(me->edit_mesh);
- MEM_freeN(me->edit_mesh);
- }
-
- /* currently executing operators re-tessellates, so we can avoid doing here
- * but at some point it may need to be added back. */
+ Mesh *me = ob->data;
+ BMesh *bm;
+
+ if (UNLIKELY(!me->mpoly && me->totface)) {
+ BKE_mesh_convert_mfaces_to_mpolys(me);
+ }
+
+ bm = BKE_mesh_to_bmesh(me,
+ ob,
+ add_key_index,
+ &((struct BMeshCreateParams){
+ .use_toolflags = true,
+ }));
+
+ if (me->edit_mesh) {
+ /* this happens when switching shape keys */
+ EDBM_mesh_free(me->edit_mesh);
+ MEM_freeN(me->edit_mesh);
+ }
+
+ /* currently executing operators re-tessellates, so we can avoid doing here
+ * but at some point it may need to be added back. */
#if 0
- me->edit_mesh = BKE_editmesh_create(bm, true);
+ me->edit_mesh = BKE_editmesh_create(bm, true);
#else
- me->edit_mesh = BKE_editmesh_create(bm, false);
+ me->edit_mesh = BKE_editmesh_create(bm, false);
#endif
- me->edit_mesh->selectmode = me->edit_mesh->bm->selectmode = select_mode;
- me->edit_mesh->mat_nr = (ob->actcol > 0) ? ob->actcol - 1 : 0;
- me->edit_mesh->ob = ob;
+ me->edit_mesh->selectmode = me->edit_mesh->bm->selectmode = select_mode;
+ me->edit_mesh->mat_nr = (ob->actcol > 0) ? ob->actcol - 1 : 0;
+ me->edit_mesh->ob = ob;
- /* we need to flush selection because the mode may have changed from when last in editmode */
- EDBM_selectmode_flush(me->edit_mesh);
+ /* we need to flush selection because the mode may have changed from when last in editmode */
+ EDBM_selectmode_flush(me->edit_mesh);
}
/**
@@ -325,61 +331,63 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index)
*/
void EDBM_mesh_load(Main *bmain, Object *ob)
{
- Mesh *me = ob->data;
- BMesh *bm = me->edit_mesh->bm;
-
- /* Workaround for T42360, 'ob->shapenr' should be 1 in this case.
- * however this isn't synchronized between objects at the moment. */
- if (UNLIKELY((ob->shapenr == 0) && (me->key && !BLI_listbase_is_empty(&me->key->block)))) {
- bm->shapenr = 1;
- }
-
- BM_mesh_bm_to_me(
- bmain, bm, me, (&(struct BMeshToMeshParams){
- .calc_object_remap = true,
- }));
+ Mesh *me = ob->data;
+ BMesh *bm = me->edit_mesh->bm;
+
+ /* Workaround for T42360, 'ob->shapenr' should be 1 in this case.
+ * however this isn't synchronized between objects at the moment. */
+ if (UNLIKELY((ob->shapenr == 0) && (me->key && !BLI_listbase_is_empty(&me->key->block)))) {
+ bm->shapenr = 1;
+ }
+
+ BM_mesh_bm_to_me(bmain,
+ bm,
+ me,
+ (&(struct BMeshToMeshParams){
+ .calc_object_remap = true,
+ }));
#ifdef USE_TESSFACE_DEFAULT
- BKE_mesh_tessface_calc(me);
+ BKE_mesh_tessface_calc(me);
#endif
- /* Free derived mesh. usually this would happen through depsgraph but there
- * are exceptions like file save that will not cause this, and we want to
- * avoid ending up with an invalid derived mesh then.
- *
- * Do it for all objects which shares the same mesh datablock, since their
- * derived meshes might also be referencing data which was just freed,
- *
- * Annoying enough, but currently seems most efficient way to avoid access
- * of freed data on scene update, especially in cases when there are dependency
- * cycles.
- */
+ /* Free derived mesh. usually this would happen through depsgraph but there
+ * are exceptions like file save that will not cause this, and we want to
+ * avoid ending up with an invalid derived mesh then.
+ *
+ * Do it for all objects which shares the same mesh datablock, since their
+ * derived meshes might also be referencing data which was just freed,
+ *
+ * Annoying enough, but currently seems most efficient way to avoid access
+ * of freed data on scene update, especially in cases when there are dependency
+ * cycles.
+ */
#if 0
- 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);
- }
- }
+ 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);
+ }
+ }
#endif
}
void EDBM_mesh_clear(BMEditMesh *em)
{
- /* clear bmesh */
- BM_mesh_clear(em->bm);
-
- /* free derived meshes */
- BKE_editmesh_free_derivedmesh(em);
-
- /* free tessellation data */
- em->tottri = 0;
- if (em->looptris) {
- MEM_freeN(em->looptris);
- em->looptris = NULL;
- }
+ /* clear bmesh */
+ BM_mesh_clear(em->bm);
+
+ /* free derived meshes */
+ BKE_editmesh_free_derivedmesh(em);
+
+ /* free tessellation data */
+ em->tottri = 0;
+ if (em->looptris) {
+ MEM_freeN(em->looptris);
+ em->looptris = NULL;
+ }
}
/**
@@ -387,13 +395,13 @@ void EDBM_mesh_clear(BMEditMesh *em)
*/
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');
+ /* 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');
- BKE_editmesh_free(em);
+ BKE_editmesh_free(em);
}
/** \} */
@@ -404,89 +412,99 @@ void EDBM_mesh_free(BMEditMesh *em)
void EDBM_selectmode_to_scene(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (!em) {
- return;
- }
+ if (!em) {
+ return;
+ }
- scene->toolsettings->selectmode = em->selectmode;
+ scene->toolsettings->selectmode = em->selectmode;
- /* Request redraw of header buttons (to show new select mode) */
- WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, scene);
+ /* Request redraw of header buttons (to show new select mode) */
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, scene);
}
void EDBM_selectmode_flush_ex(BMEditMesh *em, const short selectmode)
{
- BM_mesh_select_mode_flush_ex(em->bm, selectmode);
+ BM_mesh_select_mode_flush_ex(em->bm, selectmode);
}
void EDBM_selectmode_flush(BMEditMesh *em)
{
- EDBM_selectmode_flush_ex(em, em->selectmode);
+ EDBM_selectmode_flush_ex(em, em->selectmode);
}
void EDBM_deselect_flush(BMEditMesh *em)
{
- /* function below doesn't use. just do this to keep the values in sync */
- em->bm->selectmode = em->selectmode;
- BM_mesh_deselect_flush(em->bm);
+ /* function below doesn't use. just do this to keep the values in sync */
+ em->bm->selectmode = em->selectmode;
+ BM_mesh_deselect_flush(em->bm);
}
void EDBM_select_flush(BMEditMesh *em)
{
- /* function below doesn't use. just do this to keep the values in sync */
- em->bm->selectmode = em->selectmode;
- BM_mesh_select_flush(em->bm);
+ /* function below doesn't use. just do this to keep the values in sync */
+ em->bm->selectmode = em->selectmode;
+ BM_mesh_select_flush(em->bm);
}
void EDBM_select_more(BMEditMesh *em, const bool use_face_step)
{
- BMOperator bmop;
- const bool use_faces = (em->selectmode == SCE_SELECT_FACE);
-
- BMO_op_initf(
- em->bm, &bmop, BMO_FLAG_DEFAULTS,
- "region_extend geom=%hvef use_contract=%b use_faces=%b use_face_step=%b",
- BM_ELEM_SELECT, false, use_faces, use_face_step);
- BMO_op_exec(em->bm, &bmop);
- /* don't flush selection in edge/vertex mode */
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? true : false);
- BMO_op_finish(em->bm, &bmop);
-
- EDBM_selectmode_flush(em);
+ BMOperator bmop;
+ const bool use_faces = (em->selectmode == SCE_SELECT_FACE);
+
+ BMO_op_initf(em->bm,
+ &bmop,
+ BMO_FLAG_DEFAULTS,
+ "region_extend geom=%hvef use_contract=%b use_faces=%b use_face_step=%b",
+ BM_ELEM_SELECT,
+ false,
+ use_faces,
+ use_face_step);
+ BMO_op_exec(em->bm, &bmop);
+ /* don't flush selection in edge/vertex mode */
+ BMO_slot_buffer_hflag_enable(
+ em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? true : false);
+ BMO_op_finish(em->bm, &bmop);
+
+ EDBM_selectmode_flush(em);
}
void EDBM_select_less(BMEditMesh *em, const bool use_face_step)
{
- BMOperator bmop;
- const bool use_faces = (em->selectmode == SCE_SELECT_FACE);
-
- BMO_op_initf(
- em->bm, &bmop, BMO_FLAG_DEFAULTS,
- "region_extend geom=%hvef use_contract=%b use_faces=%b use_face_step=%b",
- BM_ELEM_SELECT, true, use_faces, use_face_step);
- BMO_op_exec(em->bm, &bmop);
- /* don't flush selection in edge/vertex mode */
- BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? true : false);
- BMO_op_finish(em->bm, &bmop);
-
- EDBM_selectmode_flush(em);
-
- /* only needed for select less, ensure we don't have isolated elements remaining */
- BM_mesh_select_mode_clean(em->bm);
+ BMOperator bmop;
+ const bool use_faces = (em->selectmode == SCE_SELECT_FACE);
+
+ BMO_op_initf(em->bm,
+ &bmop,
+ BMO_FLAG_DEFAULTS,
+ "region_extend geom=%hvef use_contract=%b use_faces=%b use_face_step=%b",
+ BM_ELEM_SELECT,
+ true,
+ use_faces,
+ use_face_step);
+ BMO_op_exec(em->bm, &bmop);
+ /* don't flush selection in edge/vertex mode */
+ BMO_slot_buffer_hflag_disable(
+ em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? true : false);
+ BMO_op_finish(em->bm, &bmop);
+
+ EDBM_selectmode_flush(em);
+
+ /* only needed for select less, ensure we don't have isolated elements remaining */
+ BM_mesh_select_mode_clean(em->bm);
}
void EDBM_flag_disable_all(BMEditMesh *em, const char hflag)
{
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, hflag, false);
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, hflag, false);
}
void EDBM_flag_enable_all(BMEditMesh *em, const char hflag)
{
- BM_mesh_elem_hflag_enable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, hflag, true);
+ BM_mesh_elem_hflag_enable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, hflag, true);
}
/** \} */
@@ -498,419 +516,431 @@ void EDBM_flag_enable_all(BMEditMesh *em, const char hflag)
/**
* Return a new UVVertMap from the editmesh
*/
-UvVertMap *BM_uv_vert_map_create(
- BMesh *bm,
- const float limit[2], const bool use_select, const bool use_winding)
+UvVertMap *BM_uv_vert_map_create(BMesh *bm,
+ const float limit[2],
+ const bool use_select,
+ const bool use_winding)
{
- BMVert *ev;
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- /* vars from original func */
- UvVertMap *vmap;
- UvMapVert *buf;
- MLoopUV *luv;
- unsigned int a;
- int totverts, i, totuv, totfaces;
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- bool *winding = NULL;
- BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
-
- BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
-
- totfaces = bm->totface;
- totverts = bm->totvert;
- totuv = 0;
-
- /* generate UvMapVert array */
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- totuv += efa->len;
- }
- }
-
- if (totuv == 0) {
- return NULL;
- }
- vmap = (UvVertMap *)MEM_callocN(sizeof(*vmap), "UvVertMap");
- if (!vmap) {
- return NULL;
- }
-
- vmap->vert = (UvMapVert **)MEM_callocN(sizeof(*vmap->vert) * totverts, "UvMapVert_pt");
- buf = vmap->buf = (UvMapVert *)MEM_callocN(sizeof(*vmap->buf) * totuv, "UvMapVert");
- if (use_winding) {
- winding = MEM_callocN(sizeof(*winding) * totfaces, "winding");
- }
-
- if (!vmap->vert || !vmap->buf) {
- BKE_mesh_uv_vert_map_free(vmap);
- return NULL;
- }
-
- BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, a) {
- if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- float (*tf_uv)[2] = NULL;
-
- if (use_winding) {
- tf_uv = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa->len);
- }
-
- BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- buf->loop_of_poly_index = i;
- buf->poly_index = a;
- buf->separate = 0;
-
- buf->next = vmap->vert[BM_elem_index_get(l->v)];
- vmap->vert[BM_elem_index_get(l->v)] = buf;
- buf++;
-
- if (use_winding) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- copy_v2_v2(tf_uv[i], luv->uv);
- }
- }
-
- if (use_winding) {
- winding[a] = cross_poly_v2(tf_uv, efa->len) > 0;
- }
- }
- }
-
- /* sort individual uvs for each vert */
- BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, a) {
- UvMapVert *newvlist = NULL, *vlist = vmap->vert[a];
- UvMapVert *iterv, *v, *lastv, *next;
- float *uv, *uv2, uvdiff[2];
-
- while (vlist) {
- v = vlist;
- vlist = vlist->next;
- v->next = newvlist;
- newvlist = v;
-
- efa = BM_face_at_index(bm, v->poly_index);
-
- l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, v->loop_of_poly_index);
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- uv = luv->uv;
-
- lastv = NULL;
- iterv = vlist;
-
- while (iterv) {
- next = iterv->next;
- efa = BM_face_at_index(bm, iterv->poly_index);
- l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, iterv->loop_of_poly_index);
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- uv2 = luv->uv;
-
- sub_v2_v2v2(uvdiff, uv2, uv);
-
- if (fabsf(uvdiff[0]) < limit[0] && fabsf(uvdiff[1]) < limit[1] &&
- (!use_winding || winding[iterv->poly_index] == winding[v->poly_index]))
- {
- if (lastv) lastv->next = next;
- else vlist = next;
- iterv->next = newvlist;
- newvlist = iterv;
- }
- else {
- lastv = iterv;
- }
-
- iterv = next;
- }
-
- newvlist->separate = 1;
- }
-
- vmap->vert[a] = newvlist;
- }
-
- if (use_winding) {
- MEM_freeN(winding);
- }
-
- BLI_buffer_free(&tf_uv_buf);
-
- return vmap;
+ BMVert *ev;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ /* vars from original func */
+ UvVertMap *vmap;
+ UvMapVert *buf;
+ MLoopUV *luv;
+ unsigned int a;
+ int totverts, i, totuv, totfaces;
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ bool *winding = NULL;
+ BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
+
+ BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
+
+ totfaces = bm->totface;
+ totverts = bm->totvert;
+ totuv = 0;
+
+ /* generate UvMapVert array */
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ totuv += efa->len;
+ }
+ }
+
+ if (totuv == 0) {
+ return NULL;
+ }
+ vmap = (UvVertMap *)MEM_callocN(sizeof(*vmap), "UvVertMap");
+ if (!vmap) {
+ return NULL;
+ }
+
+ vmap->vert = (UvMapVert **)MEM_callocN(sizeof(*vmap->vert) * totverts, "UvMapVert_pt");
+ buf = vmap->buf = (UvMapVert *)MEM_callocN(sizeof(*vmap->buf) * totuv, "UvMapVert");
+ if (use_winding) {
+ winding = MEM_callocN(sizeof(*winding) * totfaces, "winding");
+ }
+
+ if (!vmap->vert || !vmap->buf) {
+ BKE_mesh_uv_vert_map_free(vmap);
+ return NULL;
+ }
+
+ BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, a) {
+ if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ float(*tf_uv)[2] = NULL;
+
+ if (use_winding) {
+ tf_uv = (float(*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa->len);
+ }
+
+ BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i)
+ {
+ buf->loop_of_poly_index = i;
+ buf->poly_index = a;
+ buf->separate = 0;
+
+ buf->next = vmap->vert[BM_elem_index_get(l->v)];
+ vmap->vert[BM_elem_index_get(l->v)] = buf;
+ buf++;
+
+ if (use_winding) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ copy_v2_v2(tf_uv[i], luv->uv);
+ }
+ }
+
+ if (use_winding) {
+ winding[a] = cross_poly_v2(tf_uv, efa->len) > 0;
+ }
+ }
+ }
+
+ /* sort individual uvs for each vert */
+ BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, a) {
+ UvMapVert *newvlist = NULL, *vlist = vmap->vert[a];
+ UvMapVert *iterv, *v, *lastv, *next;
+ float *uv, *uv2, uvdiff[2];
+
+ while (vlist) {
+ v = vlist;
+ vlist = vlist->next;
+ v->next = newvlist;
+ newvlist = v;
+
+ efa = BM_face_at_index(bm, v->poly_index);
+
+ l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, v->loop_of_poly_index);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ uv = luv->uv;
+
+ lastv = NULL;
+ iterv = vlist;
+
+ while (iterv) {
+ next = iterv->next;
+ efa = BM_face_at_index(bm, iterv->poly_index);
+ l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, iterv->loop_of_poly_index);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ uv2 = luv->uv;
+
+ sub_v2_v2v2(uvdiff, uv2, uv);
+
+ if (fabsf(uvdiff[0]) < limit[0] && fabsf(uvdiff[1]) < limit[1] &&
+ (!use_winding || winding[iterv->poly_index] == winding[v->poly_index])) {
+ if (lastv)
+ lastv->next = next;
+ else
+ vlist = next;
+ iterv->next = newvlist;
+ newvlist = iterv;
+ }
+ else {
+ lastv = iterv;
+ }
+
+ iterv = next;
+ }
+
+ newvlist->separate = 1;
+ }
+
+ vmap->vert[a] = newvlist;
+ }
+
+ if (use_winding) {
+ MEM_freeN(winding);
+ }
+
+ BLI_buffer_free(&tf_uv_buf);
+
+ return vmap;
}
UvMapVert *BM_uv_vert_map_at_index(UvVertMap *vmap, unsigned int v)
{
- return vmap->vert[v];
+ return vmap->vert[v];
}
/* A specialized vert map used by stitch operator */
-UvElementMap *BM_uv_element_map_create(
- BMesh *bm,
- const bool selected, const bool use_winding, const bool do_islands)
+UvElementMap *BM_uv_element_map_create(BMesh *bm,
+ const bool selected,
+ const bool use_winding,
+ const bool do_islands)
{
- BMVert *ev;
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- /* vars from original func */
- UvElementMap *element_map;
- UvElement *buf;
- bool *winding = NULL;
- BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
-
- MLoopUV *luv;
- int totverts, totfaces, i, totuv, j;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-
- BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
-
- totfaces = bm->totface;
- totverts = bm->totvert;
- totuv = 0;
-
- /* generate UvElement array */
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if (!selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- totuv += efa->len;
- }
- }
-
- if (totuv == 0) {
- return NULL;
- }
-
- element_map = (UvElementMap *)MEM_callocN(sizeof(*element_map), "UvElementMap");
- element_map->totalUVs = totuv;
- element_map->vert = (UvElement **)MEM_callocN(sizeof(*element_map->vert) * totverts, "UvElementVerts");
- buf = element_map->buf = (UvElement *)MEM_callocN(sizeof(*element_map->buf) * totuv, "UvElement");
-
- if (use_winding) {
- winding = MEM_mallocN(sizeof(*winding) * totfaces, "winding");
- }
-
- BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, j) {
-
- if (use_winding) {
- winding[j] = false;
- }
-
- if (!selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- float (*tf_uv)[2] = NULL;
-
- if (use_winding) {
- tf_uv = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa->len);
- }
-
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- buf->l = l;
- buf->separate = 0;
- buf->island = INVALID_ISLAND;
- buf->loop_of_poly_index = i;
-
- buf->next = element_map->vert[BM_elem_index_get(l->v)];
- element_map->vert[BM_elem_index_get(l->v)] = buf;
-
- if (use_winding) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- copy_v2_v2(tf_uv[i], luv->uv);
- }
-
- buf++;
- }
-
- if (use_winding) {
- winding[j] = cross_poly_v2(tf_uv, efa->len) > 0;
- }
- }
- }
-
- /* sort individual uvs for each vert */
- BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, i) {
- UvElement *newvlist = NULL, *vlist = element_map->vert[i];
- UvElement *iterv, *v, *lastv, *next;
- float *uv, *uv2, uvdiff[2];
-
- while (vlist) {
- v = vlist;
- vlist = vlist->next;
- v->next = newvlist;
- newvlist = v;
-
- l = v->l;
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- uv = luv->uv;
-
- lastv = NULL;
- iterv = vlist;
-
- while (iterv) {
- next = iterv->next;
-
- l = iterv->l;
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- uv2 = luv->uv;
-
- sub_v2_v2v2(uvdiff, uv2, uv);
-
- if (fabsf(uvdiff[0]) < STD_UV_CONNECT_LIMIT && fabsf(uvdiff[1]) < STD_UV_CONNECT_LIMIT &&
- (!use_winding || winding[BM_elem_index_get(iterv->l->f)] == winding[BM_elem_index_get(v->l->f)]))
- {
- if (lastv) lastv->next = next;
- else vlist = next;
- iterv->next = newvlist;
- newvlist = iterv;
- }
- else {
- lastv = iterv;
- }
-
- iterv = next;
- }
-
- newvlist->separate = 1;
- }
-
- element_map->vert[i] = newvlist;
- }
-
- if (use_winding) {
- MEM_freeN(winding);
- }
-
- if (do_islands) {
- unsigned int *map;
- BMFace **stack;
- int stacksize = 0;
- UvElement *islandbuf;
- /* island number for faces */
- int *island_number = NULL;
-
- int nislands = 0, islandbufsize = 0;
-
- /* map holds the map from current vmap->buf to the new, sorted map */
- map = MEM_mallocN(sizeof(*map) * totuv, "uvelement_remap");
- stack = MEM_mallocN(sizeof(*stack) * bm->totface, "uv_island_face_stack");
- islandbuf = MEM_callocN(sizeof(*islandbuf) * totuv, "uvelement_island_buffer");
- island_number = MEM_mallocN(sizeof(*island_number) * totfaces, "uv_island_number_face");
- copy_vn_i(island_number, totfaces, INVALID_ISLAND);
-
- /* at this point, every UvElement in vert points to a UvElement sharing the same vertex.
- * Now we should sort uv's in islands. */
- for (i = 0; i < totuv; i++) {
- if (element_map->buf[i].island == INVALID_ISLAND) {
- element_map->buf[i].island = nislands;
- stack[0] = element_map->buf[i].l->f;
- island_number[BM_elem_index_get(stack[0])] = nislands;
- stacksize = 1;
-
- while (stacksize > 0) {
- efa = stack[--stacksize];
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- UvElement *element, *initelement = element_map->vert[BM_elem_index_get(l->v)];
-
- for (element = initelement; element; element = element->next) {
- if (element->separate)
- initelement = element;
-
- if (element->l->f == efa) {
- /* found the uv corresponding to our face and vertex.
- * Now fill it to the buffer */
- element->island = nislands;
- map[element - element_map->buf] = islandbufsize;
- islandbuf[islandbufsize].l = element->l;
- islandbuf[islandbufsize].separate = element->separate;
- islandbuf[islandbufsize].loop_of_poly_index = element->loop_of_poly_index;
- islandbuf[islandbufsize].island = nislands;
- islandbufsize++;
-
- for (element = initelement; element; element = element->next) {
- if (element->separate && element != initelement)
- break;
-
- if (island_number[BM_elem_index_get(element->l->f)] == INVALID_ISLAND) {
- stack[stacksize++] = element->l->f;
- island_number[BM_elem_index_get(element->l->f)] = nislands;
- }
- }
- break;
- }
- }
- }
- }
-
- nislands++;
- }
- }
-
- MEM_freeN(island_number);
-
- /* remap */
- for (i = 0; i < bm->totvert; i++) {
- /* important since we may do selection only. Some of these may be NULL */
- if (element_map->vert[i])
- element_map->vert[i] = &islandbuf[map[element_map->vert[i] - element_map->buf]];
- }
-
- element_map->islandIndices = MEM_callocN(sizeof(*element_map->islandIndices) * nislands, "UvElementMap_island_indices");
- j = 0;
- for (i = 0; i < totuv; i++) {
- UvElement *element = element_map->buf[i].next;
- if (element == NULL)
- islandbuf[map[i]].next = NULL;
- else
- islandbuf[map[i]].next = &islandbuf[map[element - element_map->buf]];
-
- if (islandbuf[i].island != j) {
- j++;
- element_map->islandIndices[j] = i;
- }
- }
-
- MEM_freeN(element_map->buf);
-
- element_map->buf = islandbuf;
- element_map->totalIslands = nislands;
- MEM_freeN(stack);
- MEM_freeN(map);
- }
-
- BLI_buffer_free(&tf_uv_buf);
-
- return element_map;
+ BMVert *ev;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ /* vars from original func */
+ UvElementMap *element_map;
+ UvElement *buf;
+ bool *winding = NULL;
+ BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
+
+ MLoopUV *luv;
+ int totverts, totfaces, i, totuv, j;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+ BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
+
+ totfaces = bm->totface;
+ totverts = bm->totvert;
+ totuv = 0;
+
+ /* generate UvElement array */
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ if (!selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ totuv += efa->len;
+ }
+ }
+
+ if (totuv == 0) {
+ return NULL;
+ }
+
+ element_map = (UvElementMap *)MEM_callocN(sizeof(*element_map), "UvElementMap");
+ element_map->totalUVs = totuv;
+ element_map->vert = (UvElement **)MEM_callocN(sizeof(*element_map->vert) * totverts,
+ "UvElementVerts");
+ buf = element_map->buf = (UvElement *)MEM_callocN(sizeof(*element_map->buf) * totuv,
+ "UvElement");
+
+ if (use_winding) {
+ winding = MEM_mallocN(sizeof(*winding) * totfaces, "winding");
+ }
+
+ BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, j) {
+
+ if (use_winding) {
+ winding[j] = false;
+ }
+
+ if (!selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ float(*tf_uv)[2] = NULL;
+
+ if (use_winding) {
+ tf_uv = (float(*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa->len);
+ }
+
+ BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i)
+ {
+ buf->l = l;
+ buf->separate = 0;
+ buf->island = INVALID_ISLAND;
+ buf->loop_of_poly_index = i;
+
+ buf->next = element_map->vert[BM_elem_index_get(l->v)];
+ element_map->vert[BM_elem_index_get(l->v)] = buf;
+
+ if (use_winding) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ copy_v2_v2(tf_uv[i], luv->uv);
+ }
+
+ buf++;
+ }
+
+ if (use_winding) {
+ winding[j] = cross_poly_v2(tf_uv, efa->len) > 0;
+ }
+ }
+ }
+
+ /* sort individual uvs for each vert */
+ BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, i) {
+ UvElement *newvlist = NULL, *vlist = element_map->vert[i];
+ UvElement *iterv, *v, *lastv, *next;
+ float *uv, *uv2, uvdiff[2];
+
+ while (vlist) {
+ v = vlist;
+ vlist = vlist->next;
+ v->next = newvlist;
+ newvlist = v;
+
+ l = v->l;
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ uv = luv->uv;
+
+ lastv = NULL;
+ iterv = vlist;
+
+ while (iterv) {
+ next = iterv->next;
+
+ l = iterv->l;
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ uv2 = luv->uv;
+
+ sub_v2_v2v2(uvdiff, uv2, uv);
+
+ if (fabsf(uvdiff[0]) < STD_UV_CONNECT_LIMIT && fabsf(uvdiff[1]) < STD_UV_CONNECT_LIMIT &&
+ (!use_winding ||
+ winding[BM_elem_index_get(iterv->l->f)] == winding[BM_elem_index_get(v->l->f)])) {
+ if (lastv)
+ lastv->next = next;
+ else
+ vlist = next;
+ iterv->next = newvlist;
+ newvlist = iterv;
+ }
+ else {
+ lastv = iterv;
+ }
+
+ iterv = next;
+ }
+
+ newvlist->separate = 1;
+ }
+
+ element_map->vert[i] = newvlist;
+ }
+
+ if (use_winding) {
+ MEM_freeN(winding);
+ }
+
+ if (do_islands) {
+ unsigned int *map;
+ BMFace **stack;
+ int stacksize = 0;
+ UvElement *islandbuf;
+ /* island number for faces */
+ int *island_number = NULL;
+
+ int nislands = 0, islandbufsize = 0;
+
+ /* map holds the map from current vmap->buf to the new, sorted map */
+ map = MEM_mallocN(sizeof(*map) * totuv, "uvelement_remap");
+ stack = MEM_mallocN(sizeof(*stack) * bm->totface, "uv_island_face_stack");
+ islandbuf = MEM_callocN(sizeof(*islandbuf) * totuv, "uvelement_island_buffer");
+ island_number = MEM_mallocN(sizeof(*island_number) * totfaces, "uv_island_number_face");
+ copy_vn_i(island_number, totfaces, INVALID_ISLAND);
+
+ /* at this point, every UvElement in vert points to a UvElement sharing the same vertex.
+ * Now we should sort uv's in islands. */
+ for (i = 0; i < totuv; i++) {
+ if (element_map->buf[i].island == INVALID_ISLAND) {
+ element_map->buf[i].island = nislands;
+ stack[0] = element_map->buf[i].l->f;
+ island_number[BM_elem_index_get(stack[0])] = nislands;
+ stacksize = 1;
+
+ while (stacksize > 0) {
+ efa = stack[--stacksize];
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ UvElement *element, *initelement = element_map->vert[BM_elem_index_get(l->v)];
+
+ for (element = initelement; element; element = element->next) {
+ if (element->separate)
+ initelement = element;
+
+ if (element->l->f == efa) {
+ /* found the uv corresponding to our face and vertex.
+ * Now fill it to the buffer */
+ element->island = nislands;
+ map[element - element_map->buf] = islandbufsize;
+ islandbuf[islandbufsize].l = element->l;
+ islandbuf[islandbufsize].separate = element->separate;
+ islandbuf[islandbufsize].loop_of_poly_index = element->loop_of_poly_index;
+ islandbuf[islandbufsize].island = nislands;
+ islandbufsize++;
+
+ for (element = initelement; element; element = element->next) {
+ if (element->separate && element != initelement)
+ break;
+
+ if (island_number[BM_elem_index_get(element->l->f)] == INVALID_ISLAND) {
+ stack[stacksize++] = element->l->f;
+ island_number[BM_elem_index_get(element->l->f)] = nislands;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ nislands++;
+ }
+ }
+
+ MEM_freeN(island_number);
+
+ /* remap */
+ for (i = 0; i < bm->totvert; i++) {
+ /* important since we may do selection only. Some of these may be NULL */
+ if (element_map->vert[i])
+ element_map->vert[i] = &islandbuf[map[element_map->vert[i] - element_map->buf]];
+ }
+
+ element_map->islandIndices = MEM_callocN(sizeof(*element_map->islandIndices) * nislands,
+ "UvElementMap_island_indices");
+ j = 0;
+ for (i = 0; i < totuv; i++) {
+ UvElement *element = element_map->buf[i].next;
+ if (element == NULL)
+ islandbuf[map[i]].next = NULL;
+ else
+ islandbuf[map[i]].next = &islandbuf[map[element - element_map->buf]];
+
+ if (islandbuf[i].island != j) {
+ j++;
+ element_map->islandIndices[j] = i;
+ }
+ }
+
+ MEM_freeN(element_map->buf);
+
+ element_map->buf = islandbuf;
+ element_map->totalIslands = nislands;
+ MEM_freeN(stack);
+ MEM_freeN(map);
+ }
+
+ BLI_buffer_free(&tf_uv_buf);
+
+ return element_map;
}
void BM_uv_vert_map_free(UvVertMap *vmap)
{
- if (vmap) {
- if (vmap->vert) MEM_freeN(vmap->vert);
- if (vmap->buf) MEM_freeN(vmap->buf);
- MEM_freeN(vmap);
- }
+ if (vmap) {
+ if (vmap->vert)
+ MEM_freeN(vmap->vert);
+ if (vmap->buf)
+ MEM_freeN(vmap->buf);
+ MEM_freeN(vmap);
+ }
}
void BM_uv_element_map_free(UvElementMap *element_map)
{
- if (element_map) {
- if (element_map->vert) MEM_freeN(element_map->vert);
- if (element_map->buf) MEM_freeN(element_map->buf);
- if (element_map->islandIndices) MEM_freeN(element_map->islandIndices);
- MEM_freeN(element_map);
- }
+ if (element_map) {
+ if (element_map->vert)
+ MEM_freeN(element_map->vert);
+ if (element_map->buf)
+ MEM_freeN(element_map->buf);
+ if (element_map->islandIndices)
+ MEM_freeN(element_map->islandIndices);
+ MEM_freeN(element_map);
+ }
}
UvElement *BM_uv_element_get(UvElementMap *map, BMFace *efa, BMLoop *l)
{
- for (UvElement *element = map->vert[BM_elem_index_get(l->v)];
- element;
- element = element->next)
- {
- if (element->l->f == efa) {
- return element;
- }
- }
-
- return NULL;
+ for (UvElement *element = map->vert[BM_elem_index_get(l->v)]; element; element = element->next) {
+ if (element->l->f == efa) {
+ return element;
+ }
+ }
+
+ return NULL;
}
/** \} */
@@ -925,33 +955,32 @@ UvElement *BM_uv_element_get(UvElementMap *map, BMFace *efa, BMLoop *l)
*/
BMFace *EDBM_uv_active_face_get(BMEditMesh *em, const bool sloppy, const bool selected)
{
- BMFace *efa = NULL;
+ BMFace *efa = NULL;
- if (!EDBM_uv_check(em)) {
- return NULL;
- }
+ if (!EDBM_uv_check(em)) {
+ return NULL;
+ }
- efa = BM_mesh_active_face_get(em->bm, sloppy, selected);
+ efa = BM_mesh_active_face_get(em->bm, sloppy, selected);
- if (efa) {
- return efa;
- }
+ if (efa) {
+ return efa;
+ }
- return NULL;
+ return NULL;
}
/* can we edit UV's for this mesh?*/
bool EDBM_uv_check(BMEditMesh *em)
{
- /* some of these checks could be a touch overkill */
- return em && em->bm->totface &&
- CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV);
+ /* some of these checks could be a touch overkill */
+ return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV);
}
bool EDBM_vert_color_check(BMEditMesh *em)
{
- /* some of these checks could be a touch overkill */
- return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_MLOOPCOL);
+ /* some of these checks could be a touch overkill */
+ return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_MLOOPCOL);
}
/** \} */
@@ -962,8 +991,8 @@ bool EDBM_vert_color_check(BMEditMesh *em)
static BMVert *cache_mirr_intptr_as_bmvert(intptr_t *index_lookup, int index)
{
- intptr_t eve_i = index_lookup[index];
- return (eve_i == -1) ? NULL : (BMVert *)eve_i;
+ intptr_t eve_i = index_lookup[index];
+ return (eve_i == -1) ? NULL : (BMVert *)eve_i;
}
/**
@@ -994,203 +1023,212 @@ static BMVert *cache_mirr_intptr_as_bmvert(intptr_t *index_lookup, int index)
* \param maxdist: Distance for close point test.
* \param r_index: Optional array to write into, as an alternative to a customdata layer (length of total verts).
*/
-void EDBM_verts_mirror_cache_begin_ex(
- BMEditMesh *em, const int axis, const bool use_self, const bool use_select,
- /* extra args */
- const bool use_topology, float maxdist, int *r_index)
+void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em,
+ const int axis,
+ const bool use_self,
+ const bool use_select,
+ /* extra args */
+ const bool use_topology,
+ float maxdist,
+ int *r_index)
{
- Mesh *me = (Mesh *)em->ob->data;
- BMesh *bm = em->bm;
- BMIter iter;
- BMVert *v;
- int cd_vmirr_offset = 0;
- int i;
- const float maxdist_sq = SQUARE(maxdist);
-
- /* one or the other is used depending if topo is enabled */
- KDTree_3d *tree = NULL;
- MirrTopoStore_t mesh_topo_store = {NULL, -1, -1, -1};
-
- BM_mesh_elem_table_ensure(bm, BM_VERT);
-
- if (r_index == NULL) {
- const char *layer_id = BM_CD_LAYER_ID;
- em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, layer_id);
- if (em->mirror_cdlayer == -1) {
- BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_INT, layer_id);
- em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, layer_id);
- }
-
- cd_vmirr_offset = CustomData_get_n_offset(
- &bm->vdata, CD_PROP_INT,
- em->mirror_cdlayer - CustomData_get_layer_index(&bm->vdata, CD_PROP_INT));
-
- bm->vdata.layers[em->mirror_cdlayer].flag |= CD_FLAG_TEMPORARY;
- }
-
- BM_mesh_elem_index_ensure(bm, BM_VERT);
-
- if (use_topology) {
- ED_mesh_mirrtopo_init(me, NULL, &mesh_topo_store, true);
- }
- else {
- tree = BLI_kdtree_3d_new(bm->totvert);
- BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
- BLI_kdtree_3d_insert(tree, i, v->co);
- }
- BLI_kdtree_3d_balance(tree);
- }
+ Mesh *me = (Mesh *)em->ob->data;
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMVert *v;
+ int cd_vmirr_offset = 0;
+ int i;
+ const float maxdist_sq = SQUARE(maxdist);
+
+ /* one or the other is used depending if topo is enabled */
+ KDTree_3d *tree = NULL;
+ MirrTopoStore_t mesh_topo_store = {NULL, -1, -1, -1};
+
+ BM_mesh_elem_table_ensure(bm, BM_VERT);
+
+ if (r_index == NULL) {
+ const char *layer_id = BM_CD_LAYER_ID;
+ em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, layer_id);
+ if (em->mirror_cdlayer == -1) {
+ BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_INT, layer_id);
+ em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, layer_id);
+ }
+
+ cd_vmirr_offset = CustomData_get_n_offset(
+ &bm->vdata,
+ CD_PROP_INT,
+ em->mirror_cdlayer - CustomData_get_layer_index(&bm->vdata, CD_PROP_INT));
+
+ bm->vdata.layers[em->mirror_cdlayer].flag |= CD_FLAG_TEMPORARY;
+ }
+
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+ if (use_topology) {
+ ED_mesh_mirrtopo_init(me, NULL, &mesh_topo_store, true);
+ }
+ else {
+ tree = BLI_kdtree_3d_new(bm->totvert);
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ BLI_kdtree_3d_insert(tree, i, v->co);
+ }
+ BLI_kdtree_3d_balance(tree);
+ }
#define VERT_INTPTR(_v, _i) (r_index ? &r_index[_i] : BM_ELEM_CD_GET_VOID_P(_v, cd_vmirr_offset))
- BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
- BLI_assert(BM_elem_index_get(v) == i);
-
- /* temporary for testing, check for selection */
- if (use_select && !BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- /* do nothing */
- }
- else {
- BMVert *v_mirr;
- int *idx = VERT_INTPTR(v, i);
-
- if (use_topology) {
- v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i);
- }
- else {
- int i_mirr;
- float co[3];
- copy_v3_v3(co, v->co);
- co[axis] *= -1.0f;
-
- v_mirr = NULL;
- i_mirr = BLI_kdtree_3d_find_nearest(tree, co, NULL);
- if (i_mirr != -1) {
- BMVert *v_test = BM_vert_at_index(bm, i_mirr);
- if (len_squared_v3v3(co, v_test->co) < maxdist_sq) {
- v_mirr = v_test;
- }
- }
- }
-
- if (v_mirr && (use_self || (v_mirr != v))) {
- const int i_mirr = BM_elem_index_get(v_mirr);
- *idx = i_mirr;
- idx = VERT_INTPTR(v_mirr, i_mirr);
- *idx = i;
- }
- else {
- *idx = -1;
- }
- }
-
- }
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ BLI_assert(BM_elem_index_get(v) == i);
+
+ /* temporary for testing, check for selection */
+ if (use_select && !BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ /* do nothing */
+ }
+ else {
+ BMVert *v_mirr;
+ int *idx = VERT_INTPTR(v, i);
+
+ if (use_topology) {
+ v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i);
+ }
+ else {
+ int i_mirr;
+ float co[3];
+ copy_v3_v3(co, v->co);
+ co[axis] *= -1.0f;
+
+ v_mirr = NULL;
+ i_mirr = BLI_kdtree_3d_find_nearest(tree, co, NULL);
+ if (i_mirr != -1) {
+ BMVert *v_test = BM_vert_at_index(bm, i_mirr);
+ if (len_squared_v3v3(co, v_test->co) < maxdist_sq) {
+ v_mirr = v_test;
+ }
+ }
+ }
+
+ if (v_mirr && (use_self || (v_mirr != v))) {
+ const int i_mirr = BM_elem_index_get(v_mirr);
+ *idx = i_mirr;
+ idx = VERT_INTPTR(v_mirr, i_mirr);
+ *idx = i;
+ }
+ else {
+ *idx = -1;
+ }
+ }
+ }
#undef VERT_INTPTR
- if (use_topology) {
- ED_mesh_mirrtopo_free(&mesh_topo_store);
- }
- else {
- BLI_kdtree_3d_free(tree);
- }
+ if (use_topology) {
+ ED_mesh_mirrtopo_free(&mesh_topo_store);
+ }
+ else {
+ BLI_kdtree_3d_free(tree);
+ }
}
-void EDBM_verts_mirror_cache_begin(
- BMEditMesh *em, const int axis,
- const bool use_self, const bool use_select,
- const bool use_topology)
+void EDBM_verts_mirror_cache_begin(BMEditMesh *em,
+ const int axis,
+ const bool use_self,
+ const bool use_select,
+ const bool use_topology)
{
- EDBM_verts_mirror_cache_begin_ex(
- em, axis,
- use_self, use_select,
- /* extra args */
- use_topology, BM_SEARCH_MAXDIST_MIRR, NULL);
+ EDBM_verts_mirror_cache_begin_ex(em,
+ axis,
+ use_self,
+ use_select,
+ /* extra args */
+ use_topology,
+ BM_SEARCH_MAXDIST_MIRR,
+ NULL);
}
BMVert *EDBM_verts_mirror_get(BMEditMesh *em, BMVert *v)
{
- const int *mirr = CustomData_bmesh_get_layer_n(&em->bm->vdata, v->head.data, em->mirror_cdlayer);
+ const int *mirr = CustomData_bmesh_get_layer_n(&em->bm->vdata, v->head.data, em->mirror_cdlayer);
- BLI_assert(em->mirror_cdlayer != -1); /* invalid use */
+ BLI_assert(em->mirror_cdlayer != -1); /* invalid use */
- if (mirr && *mirr >= 0 && *mirr < em->bm->totvert) {
- if (!em->bm->vtable) {
- printf("err: should only be called between "
- "EDBM_verts_mirror_cache_begin and EDBM_verts_mirror_cache_end");
- return NULL;
- }
+ if (mirr && *mirr >= 0 && *mirr < em->bm->totvert) {
+ if (!em->bm->vtable) {
+ printf(
+ "err: should only be called between "
+ "EDBM_verts_mirror_cache_begin and EDBM_verts_mirror_cache_end");
+ return NULL;
+ }
- return em->bm->vtable[*mirr];
- }
+ return em->bm->vtable[*mirr];
+ }
- return NULL;
+ return NULL;
}
BMEdge *EDBM_verts_mirror_get_edge(BMEditMesh *em, BMEdge *e)
{
- BMVert *v1_mirr = EDBM_verts_mirror_get(em, e->v1);
- if (v1_mirr) {
- BMVert *v2_mirr = EDBM_verts_mirror_get(em, e->v2);
- if (v2_mirr) {
- return BM_edge_exists(v1_mirr, v2_mirr);
- }
- }
-
- return NULL;
+ BMVert *v1_mirr = EDBM_verts_mirror_get(em, e->v1);
+ if (v1_mirr) {
+ BMVert *v2_mirr = EDBM_verts_mirror_get(em, e->v2);
+ if (v2_mirr) {
+ return BM_edge_exists(v1_mirr, v2_mirr);
+ }
+ }
+
+ return NULL;
}
BMFace *EDBM_verts_mirror_get_face(BMEditMesh *em, BMFace *f)
{
- BMVert **v_mirr_arr = BLI_array_alloca(v_mirr_arr, f->len);
+ BMVert **v_mirr_arr = BLI_array_alloca(v_mirr_arr, f->len);
- BMLoop *l_iter, *l_first;
- unsigned int i = 0;
+ BMLoop *l_iter, *l_first;
+ unsigned int i = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if ((v_mirr_arr[i++] = EDBM_verts_mirror_get(em, l_iter->v)) == NULL) {
- return NULL;
- }
- } while ((l_iter = l_iter->next) != l_first);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if ((v_mirr_arr[i++] = EDBM_verts_mirror_get(em, l_iter->v)) == NULL) {
+ return NULL;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
- return BM_face_exists(v_mirr_arr, f->len);
+ return BM_face_exists(v_mirr_arr, f->len);
}
void EDBM_verts_mirror_cache_clear(BMEditMesh *em, BMVert *v)
{
- int *mirr = CustomData_bmesh_get_layer_n(&em->bm->vdata, v->head.data, em->mirror_cdlayer);
+ int *mirr = CustomData_bmesh_get_layer_n(&em->bm->vdata, v->head.data, em->mirror_cdlayer);
- BLI_assert(em->mirror_cdlayer != -1); /* invalid use */
+ BLI_assert(em->mirror_cdlayer != -1); /* invalid use */
- if (mirr) {
- *mirr = -1;
- }
+ if (mirr) {
+ *mirr = -1;
+ }
}
void EDBM_verts_mirror_cache_end(BMEditMesh *em)
{
- em->mirror_cdlayer = -1;
+ em->mirror_cdlayer = -1;
}
void EDBM_verts_mirror_apply(BMEditMesh *em, const int sel_from, const int sel_to)
{
- BMIter iter;
- BMVert *v;
-
- BLI_assert((em->bm->vtable != NULL) && ((em->bm->elem_table_dirty & BM_VERT) == 0));
-
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT) == sel_from) {
- BMVert *mirr = EDBM_verts_mirror_get(em, v);
- if (mirr) {
- if (BM_elem_flag_test(mirr, BM_ELEM_SELECT) == sel_to) {
- copy_v3_v3(mirr->co, v->co);
- mirr->co[0] *= -1.0f;
- }
- }
- }
- }
+ BMIter iter;
+ BMVert *v;
+
+ BLI_assert((em->bm->vtable != NULL) && ((em->bm->elem_table_dirty & BM_VERT) == 0));
+
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT) == sel_from) {
+ BMVert *mirr = EDBM_verts_mirror_get(em, v);
+ if (mirr) {
+ if (BM_elem_flag_test(mirr, BM_ELEM_SELECT) == sel_to) {
+ copy_v3_v3(mirr->co, v->co);
+ mirr->co[0] *= -1.0f;
+ }
+ }
+ }
+ }
}
/** \} */
@@ -1202,105 +1240,105 @@ void EDBM_verts_mirror_apply(BMEditMesh *em, const int sel_from, const int sel_t
/* swap is 0 or 1, if 1 it hides not selected */
bool EDBM_mesh_hide(BMEditMesh *em, bool swap)
{
- BMIter iter;
- BMElem *ele;
- int itermode;
- char hflag_swap = swap ? BM_ELEM_SELECT : 0;
- bool changed = true;
-
- if (em->selectmode & SCE_SELECT_VERTEX)
- itermode = BM_VERTS_OF_MESH;
- else if (em->selectmode & SCE_SELECT_EDGE)
- itermode = BM_EDGES_OF_MESH;
- else
- itermode = BM_FACES_OF_MESH;
-
- BM_ITER_MESH (ele, &iter, em->bm, itermode) {
- if (!BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) {
- if (BM_elem_flag_test(ele, BM_ELEM_SELECT) ^ hflag_swap) {
- BM_elem_hide_set(em->bm, ele, true);
- changed = true;
- }
- }
- }
-
- if (changed) {
- EDBM_selectmode_flush(em);
- }
- return changed;
-
- /* original hide flushing comment (OUTDATED):
- * hide happens on least dominant select mode, and flushes up, not down!
- * (helps preventing errors in subsurf) */
- /* - vertex hidden, always means edge is hidden too
- * - edge hidden, always means face is hidden too
- * - face hidden, only set face hide
- * - then only flush back down what's absolute hidden
- */
+ BMIter iter;
+ BMElem *ele;
+ int itermode;
+ char hflag_swap = swap ? BM_ELEM_SELECT : 0;
+ bool changed = true;
+
+ if (em->selectmode & SCE_SELECT_VERTEX)
+ itermode = BM_VERTS_OF_MESH;
+ else if (em->selectmode & SCE_SELECT_EDGE)
+ itermode = BM_EDGES_OF_MESH;
+ else
+ itermode = BM_FACES_OF_MESH;
+
+ BM_ITER_MESH (ele, &iter, em->bm, itermode) {
+ if (!BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) {
+ if (BM_elem_flag_test(ele, BM_ELEM_SELECT) ^ hflag_swap) {
+ BM_elem_hide_set(em->bm, ele, true);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ EDBM_selectmode_flush(em);
+ }
+ return changed;
+
+ /* original hide flushing comment (OUTDATED):
+ * hide happens on least dominant select mode, and flushes up, not down!
+ * (helps preventing errors in subsurf) */
+ /* - vertex hidden, always means edge is hidden too
+ * - edge hidden, always means face is hidden too
+ * - face hidden, only set face hide
+ * - then only flush back down what's absolute hidden
+ */
}
bool EDBM_mesh_reveal(BMEditMesh *em, bool select)
{
- const char iter_types[3] = {
- BM_VERTS_OF_MESH,
- BM_EDGES_OF_MESH,
- BM_FACES_OF_MESH,
- };
-
- const bool sels[3] = {
- (em->selectmode & SCE_SELECT_VERTEX) != 0,
- (em->selectmode & SCE_SELECT_EDGE) != 0,
- (em->selectmode & SCE_SELECT_FACE) != 0,
- };
- int i;
- bool changed = false;
-
- /* Use tag flag to remember what was hidden before all is revealed.
- * BM_ELEM_HIDDEN --> BM_ELEM_TAG */
- for (i = 0; i < 3; i++) {
- BMIter iter;
- BMElem *ele;
-
- BM_ITER_MESH (ele, &iter, em->bm, iter_types[i]) {
- if (BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) {
- BM_elem_flag_enable(ele, BM_ELEM_TAG);
- changed = true;
- }
- else {
- BM_elem_flag_disable(ele, BM_ELEM_TAG);
- }
- }
- }
-
- if (!changed) {
- return false;
- }
-
- /* Reveal everything */
- EDBM_flag_disable_all(em, BM_ELEM_HIDDEN);
-
- /* Select relevant just-revealed elements */
- for (i = 0; i < 3; i++) {
- BMIter iter;
- BMElem *ele;
-
- if (!sels[i]) {
- continue;
- }
-
- BM_ITER_MESH (ele, &iter, em->bm, iter_types[i]) {
- if (BM_elem_flag_test(ele, BM_ELEM_TAG)) {
- BM_elem_select_set(em->bm, ele, select);
- }
- }
- }
-
- EDBM_selectmode_flush(em);
-
- /* hidden faces can have invalid normals */
- EDBM_mesh_normals_update(em);
-
- return true;
+ const char iter_types[3] = {
+ BM_VERTS_OF_MESH,
+ BM_EDGES_OF_MESH,
+ BM_FACES_OF_MESH,
+ };
+
+ const bool sels[3] = {
+ (em->selectmode & SCE_SELECT_VERTEX) != 0,
+ (em->selectmode & SCE_SELECT_EDGE) != 0,
+ (em->selectmode & SCE_SELECT_FACE) != 0,
+ };
+ int i;
+ bool changed = false;
+
+ /* Use tag flag to remember what was hidden before all is revealed.
+ * BM_ELEM_HIDDEN --> BM_ELEM_TAG */
+ for (i = 0; i < 3; i++) {
+ BMIter iter;
+ BMElem *ele;
+
+ BM_ITER_MESH (ele, &iter, em->bm, iter_types[i]) {
+ if (BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) {
+ BM_elem_flag_enable(ele, BM_ELEM_TAG);
+ changed = true;
+ }
+ else {
+ BM_elem_flag_disable(ele, BM_ELEM_TAG);
+ }
+ }
+ }
+
+ if (!changed) {
+ return false;
+ }
+
+ /* Reveal everything */
+ EDBM_flag_disable_all(em, BM_ELEM_HIDDEN);
+
+ /* Select relevant just-revealed elements */
+ for (i = 0; i < 3; i++) {
+ BMIter iter;
+ BMElem *ele;
+
+ if (!sels[i]) {
+ continue;
+ }
+
+ BM_ITER_MESH (ele, &iter, em->bm, iter_types[i]) {
+ if (BM_elem_flag_test(ele, BM_ELEM_TAG)) {
+ BM_elem_select_set(em->bm, ele, select);
+ }
+ }
+ }
+
+ EDBM_selectmode_flush(em);
+
+ /* hidden faces can have invalid normals */
+ EDBM_mesh_normals_update(em);
+
+ return true;
}
/** \} */
@@ -1311,73 +1349,73 @@ bool EDBM_mesh_reveal(BMEditMesh *em, bool select)
void EDBM_mesh_normals_update(BMEditMesh *em)
{
- BM_mesh_normals_update(em->bm);
+ BM_mesh_normals_update(em->bm);
}
void EDBM_stats_update(BMEditMesh *em)
{
- const char iter_types[3] = {
- BM_VERTS_OF_MESH,
- BM_EDGES_OF_MESH,
- BM_FACES_OF_MESH,
- };
-
- BMIter iter;
- BMElem *ele;
- int *tots[3];
- int i;
-
- tots[0] = &em->bm->totvertsel;
- tots[1] = &em->bm->totedgesel;
- tots[2] = &em->bm->totfacesel;
-
- em->bm->totvertsel = em->bm->totedgesel = em->bm->totfacesel = 0;
-
- for (i = 0; i < 3; i++) {
- ele = BM_iter_new(&iter, em->bm, iter_types[i], NULL);
- for ( ; ele; ele = BM_iter_step(&iter)) {
- if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
- (*tots[i])++;
- }
- }
- }
+ const char iter_types[3] = {
+ BM_VERTS_OF_MESH,
+ BM_EDGES_OF_MESH,
+ BM_FACES_OF_MESH,
+ };
+
+ BMIter iter;
+ BMElem *ele;
+ int *tots[3];
+ int i;
+
+ tots[0] = &em->bm->totvertsel;
+ tots[1] = &em->bm->totedgesel;
+ tots[2] = &em->bm->totfacesel;
+
+ em->bm->totvertsel = em->bm->totedgesel = em->bm->totfacesel = 0;
+
+ for (i = 0; i < 3; i++) {
+ ele = BM_iter_new(&iter, em->bm, iter_types[i], NULL);
+ for (; ele; ele = BM_iter_step(&iter)) {
+ if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+ (*tots[i])++;
+ }
+ }
+ }
}
/* so many tools call these that we better make it a generic function.
*/
void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_destructive)
{
- Object *ob = em->ob;
- /* order of calling isn't important */
- DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY);
- WM_main_add_notifier(NC_GEOM | ND_DATA, ob->data);
-
- if (do_tessface) {
- BKE_editmesh_tessface_calc(em);
- }
-
- if (is_destructive) {
- /* TODO. we may be able to remove this now! - Campbell */
- // BM_mesh_elem_table_free(em->bm, BM_ALL_NOLOOP);
- }
- else {
- /* in debug mode double check we didn't need to recalculate */
- BLI_assert(BM_mesh_elem_table_check(em->bm) == true);
- }
- if (em->bm->spacearr_dirty & BM_SPACEARR_BMO_SET) {
- BM_lnorspace_invalidate(em->bm, false);
- em->bm->spacearr_dirty &= ~BM_SPACEARR_BMO_SET;
- }
- /* don't keep stale derivedMesh data around, see: [#38872] */
- BKE_editmesh_free_derivedmesh(em);
+ Object *ob = em->ob;
+ /* order of calling isn't important */
+ DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, ob->data);
+
+ if (do_tessface) {
+ BKE_editmesh_tessface_calc(em);
+ }
+
+ if (is_destructive) {
+ /* TODO. we may be able to remove this now! - Campbell */
+ // BM_mesh_elem_table_free(em->bm, BM_ALL_NOLOOP);
+ }
+ else {
+ /* in debug mode double check we didn't need to recalculate */
+ BLI_assert(BM_mesh_elem_table_check(em->bm) == true);
+ }
+ if (em->bm->spacearr_dirty & BM_SPACEARR_BMO_SET) {
+ BM_lnorspace_invalidate(em->bm, false);
+ em->bm->spacearr_dirty &= ~BM_SPACEARR_BMO_SET;
+ }
+ /* don't keep stale derivedMesh data around, see: [#38872] */
+ BKE_editmesh_free_derivedmesh(em);
#ifdef DEBUG
- {
- BMEditSelection *ese;
- for (ese = em->bm->selected.first; ese; ese = ese->next) {
- BLI_assert(BM_elem_flag_test(ese->ele, BM_ELEM_SELECT));
- }
- }
+ {
+ BMEditSelection *ese;
+ for (ese = em->bm->selected.first; ese; ese = ese->next) {
+ BLI_assert(BM_elem_flag_test(ese->ele, BM_ELEM_SELECT));
+ }
+ }
#endif
}
@@ -1390,11 +1428,11 @@ void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_d
/* poll call for mesh operators requiring a view3d context */
bool EDBM_view3d_poll(bContext *C)
{
- if (ED_operator_editmesh(C) && ED_operator_view3d_active(C)) {
- return 1;
- }
+ if (ED_operator_editmesh(C) && ED_operator_view3d_active(C)) {
+ return 1;
+ }
- return 0;
+ return 0;
}
/** \} */
@@ -1405,19 +1443,19 @@ bool EDBM_view3d_poll(bContext *C)
BMElem *EDBM_elem_from_selectmode(BMEditMesh *em, BMVert *eve, BMEdge *eed, BMFace *efa)
{
- BMElem *ele = NULL;
-
- if ((em->selectmode & SCE_SELECT_VERTEX) && eve) {
- ele = (BMElem *)eve;
- }
- else if ((em->selectmode & SCE_SELECT_EDGE) && eed) {
- ele = (BMElem *)eed;
- }
- else if ((em->selectmode & SCE_SELECT_FACE) && efa) {
- ele = (BMElem *)efa;
- }
-
- return ele;
+ BMElem *ele = NULL;
+
+ if ((em->selectmode & SCE_SELECT_VERTEX) && eve) {
+ ele = (BMElem *)eve;
+ }
+ else if ((em->selectmode & SCE_SELECT_EDGE) && eed) {
+ ele = (BMElem *)eed;
+ }
+ else if ((em->selectmode & SCE_SELECT_FACE) && efa) {
+ ele = (BMElem *)efa;
+ }
+
+ return ele;
}
/**
@@ -1427,44 +1465,44 @@ BMElem *EDBM_elem_from_selectmode(BMEditMesh *em, BMVert *eve, BMEdge *eed, BMFa
*/
int EDBM_elem_to_index_any(BMEditMesh *em, BMElem *ele)
{
- BMesh *bm = em->bm;
- int index = BM_elem_index_get(ele);
-
- if (ele->head.htype == BM_VERT) {
- BLI_assert(!(bm->elem_index_dirty & BM_VERT));
- }
- else if (ele->head.htype == BM_EDGE) {
- BLI_assert(!(bm->elem_index_dirty & BM_EDGE));
- index += bm->totvert;
- }
- else if (ele->head.htype == BM_FACE) {
- BLI_assert(!(bm->elem_index_dirty & BM_FACE));
- index += bm->totvert + bm->totedge;
- }
- else {
- BLI_assert(0);
- }
-
- return index;
+ BMesh *bm = em->bm;
+ int index = BM_elem_index_get(ele);
+
+ if (ele->head.htype == BM_VERT) {
+ BLI_assert(!(bm->elem_index_dirty & BM_VERT));
+ }
+ else if (ele->head.htype == BM_EDGE) {
+ BLI_assert(!(bm->elem_index_dirty & BM_EDGE));
+ index += bm->totvert;
+ }
+ else if (ele->head.htype == BM_FACE) {
+ BLI_assert(!(bm->elem_index_dirty & BM_FACE));
+ index += bm->totvert + bm->totedge;
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ return index;
}
BMElem *EDBM_elem_from_index_any(BMEditMesh *em, int index)
{
- BMesh *bm = em->bm;
-
- if (index < bm->totvert) {
- return (BMElem *)BM_vert_at_index_find_or_table(bm, index);
- }
- index -= bm->totvert;
- if (index < bm->totedge) {
- return (BMElem *)BM_edge_at_index_find_or_table(bm, index);
- }
- index -= bm->totedge;
- if (index < bm->totface) {
- return (BMElem *)BM_face_at_index_find_or_table(bm, index);
- }
-
- return NULL;
+ BMesh *bm = em->bm;
+
+ if (index < bm->totvert) {
+ return (BMElem *)BM_vert_at_index_find_or_table(bm, index);
+ }
+ index -= bm->totvert;
+ if (index < bm->totedge) {
+ return (BMElem *)BM_edge_at_index_find_or_table(bm, index);
+ }
+ index -= bm->totedge;
+ if (index < bm->totface) {
+ return (BMElem *)BM_face_at_index_find_or_table(bm, index);
+ }
+
+ return NULL;
}
/** \} */
@@ -1473,83 +1511,87 @@ BMElem *EDBM_elem_from_index_any(BMEditMesh *em, int index)
/** \name BMesh BVH API
* \{ */
-static BMFace *edge_ray_cast(struct BMBVHTree *tree, const float co[3], const float dir[3], float *r_hitout, BMEdge *e)
+static BMFace *edge_ray_cast(
+ struct BMBVHTree *tree, const float co[3], const float dir[3], float *r_hitout, BMEdge *e)
{
- BMFace *f = BKE_bmbvh_ray_cast(tree, co, dir, 0.0f, NULL, r_hitout, NULL);
+ BMFace *f = BKE_bmbvh_ray_cast(tree, co, dir, 0.0f, NULL, r_hitout, NULL);
- if (f && BM_edge_in_face(e, f)) {
- return NULL;
- }
+ if (f && BM_edge_in_face(e, f)) {
+ return NULL;
+ }
- return f;
+ return f;
}
static void scale_point(float c1[3], const float p[3], const float s)
{
- sub_v3_v3(c1, p);
- mul_v3_fl(c1, s);
- add_v3_v3(c1, p);
+ sub_v3_v3(c1, p);
+ mul_v3_fl(c1, s);
+ add_v3_v3(c1, p);
}
-bool BMBVH_EdgeVisible(struct BMBVHTree *tree, BMEdge *e,
+bool BMBVH_EdgeVisible(struct BMBVHTree *tree,
+ BMEdge *e,
struct Depsgraph *depsgraph,
- ARegion *ar, View3D *v3d, Object *obedit)
+ ARegion *ar,
+ View3D *v3d,
+ Object *obedit)
{
- BMFace *f;
- float co1[3], co2[3], co3[3], dir1[3], dir2[3], dir3[3];
- float origin[3], invmat[4][4];
- float epsilon = 0.01f;
- float end[3];
- const float mval_f[2] = {
- ar->winx / 2.0f,
- ar->winy / 2.0f,
- };
-
- ED_view3d_win_to_segment_clipped(depsgraph, ar, v3d, mval_f, origin, end, false);
-
- invert_m4_m4(invmat, obedit->obmat);
- mul_m4_v3(invmat, origin);
-
- copy_v3_v3(co1, e->v1->co);
- mid_v3_v3v3(co2, e->v1->co, e->v2->co);
- copy_v3_v3(co3, e->v2->co);
-
- scale_point(co1, co2, 0.99);
- scale_point(co3, co2, 0.99);
-
- /* ok, idea is to generate rays going from the camera origin to the
- * three points on the edge (v1, mid, v2)*/
- sub_v3_v3v3(dir1, origin, co1);
- sub_v3_v3v3(dir2, origin, co2);
- sub_v3_v3v3(dir3, origin, co3);
-
- normalize_v3_length(dir1, epsilon);
- normalize_v3_length(dir2, epsilon);
- normalize_v3_length(dir3, epsilon);
-
- /* offset coordinates slightly along view vectors, to avoid
- * hitting the faces that own the edge.*/
- add_v3_v3v3(co1, co1, dir1);
- add_v3_v3v3(co2, co2, dir2);
- add_v3_v3v3(co3, co3, dir3);
-
- normalize_v3(dir1);
- normalize_v3(dir2);
- normalize_v3(dir3);
-
- /* do three samplings: left, middle, right */
- f = edge_ray_cast(tree, co1, dir1, NULL, e);
- if (f && !edge_ray_cast(tree, co2, dir2, NULL, e)) {
- return true;
- }
- else if (f && !edge_ray_cast(tree, co3, dir3, NULL, e)) {
- return true;
- }
- else if (!f) {
- return true;
- }
-
- return false;
+ BMFace *f;
+ float co1[3], co2[3], co3[3], dir1[3], dir2[3], dir3[3];
+ float origin[3], invmat[4][4];
+ float epsilon = 0.01f;
+ float end[3];
+ const float mval_f[2] = {
+ ar->winx / 2.0f,
+ ar->winy / 2.0f,
+ };
+
+ ED_view3d_win_to_segment_clipped(depsgraph, ar, v3d, mval_f, origin, end, false);
+
+ invert_m4_m4(invmat, obedit->obmat);
+ mul_m4_v3(invmat, origin);
+
+ copy_v3_v3(co1, e->v1->co);
+ mid_v3_v3v3(co2, e->v1->co, e->v2->co);
+ copy_v3_v3(co3, e->v2->co);
+
+ scale_point(co1, co2, 0.99);
+ scale_point(co3, co2, 0.99);
+
+ /* ok, idea is to generate rays going from the camera origin to the
+ * three points on the edge (v1, mid, v2)*/
+ sub_v3_v3v3(dir1, origin, co1);
+ sub_v3_v3v3(dir2, origin, co2);
+ sub_v3_v3v3(dir3, origin, co3);
+
+ normalize_v3_length(dir1, epsilon);
+ normalize_v3_length(dir2, epsilon);
+ normalize_v3_length(dir3, epsilon);
+
+ /* offset coordinates slightly along view vectors, to avoid
+ * hitting the faces that own the edge.*/
+ add_v3_v3v3(co1, co1, dir1);
+ add_v3_v3v3(co2, co2, dir2);
+ add_v3_v3v3(co3, co3, dir3);
+
+ normalize_v3(dir1);
+ normalize_v3(dir2);
+ normalize_v3(dir3);
+
+ /* do three samplings: left, middle, right */
+ f = edge_ray_cast(tree, co1, dir1, NULL, e);
+ if (f && !edge_ray_cast(tree, co2, dir2, NULL, e)) {
+ return true;
+ }
+ else if (f && !edge_ray_cast(tree, co3, dir3, NULL, e)) {
+ return true;
+ }
+ else if (!f) {
+ return true;
+ }
+
+ return false;
}
/** \} */
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index 3d880fc0bfe..2f4fbcab9bc 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -52,651 +52,651 @@
#include "ED_uvedit.h"
#include "ED_view3d.h"
-#include "mesh_intern.h" /* own include */
-
+#include "mesh_intern.h" /* own include */
static CustomData *mesh_customdata_get_type(Mesh *me, const char htype, int *r_tot)
{
- CustomData *data;
- BMesh *bm = (me->edit_mesh) ? me->edit_mesh->bm : NULL;
- int tot;
-
- /* this */
- switch (htype) {
- case BM_VERT:
- if (bm) {
- data = &bm->vdata;
- tot = bm->totvert;
- }
- else {
- data = &me->vdata;
- tot = me->totvert;
- }
- break;
- case BM_EDGE:
- if (bm) {
- data = &bm->edata;
- tot = bm->totedge;
- }
- else {
- data = &me->edata;
- tot = me->totedge;
- }
- break;
- case BM_LOOP:
- if (bm) {
- data = &bm->ldata;
- tot = bm->totloop;
- }
- else {
- data = &me->ldata;
- tot = me->totloop;
- }
- break;
- case BM_FACE:
- if (bm) {
- data = &bm->pdata;
- tot = bm->totface;
- }
- else {
- data = &me->pdata;
- tot = me->totpoly;
- }
- break;
- default:
- BLI_assert(0);
- tot = 0;
- data = NULL;
- break;
- }
-
- *r_tot = tot;
- return data;
+ CustomData *data;
+ BMesh *bm = (me->edit_mesh) ? me->edit_mesh->bm : NULL;
+ int tot;
+
+ /* this */
+ switch (htype) {
+ case BM_VERT:
+ if (bm) {
+ data = &bm->vdata;
+ tot = bm->totvert;
+ }
+ else {
+ data = &me->vdata;
+ tot = me->totvert;
+ }
+ break;
+ case BM_EDGE:
+ if (bm) {
+ data = &bm->edata;
+ tot = bm->totedge;
+ }
+ else {
+ data = &me->edata;
+ tot = me->totedge;
+ }
+ break;
+ case BM_LOOP:
+ if (bm) {
+ data = &bm->ldata;
+ tot = bm->totloop;
+ }
+ else {
+ data = &me->ldata;
+ tot = me->totloop;
+ }
+ break;
+ case BM_FACE:
+ if (bm) {
+ data = &bm->pdata;
+ tot = bm->totface;
+ }
+ else {
+ data = &me->pdata;
+ tot = me->totpoly;
+ }
+ break;
+ default:
+ BLI_assert(0);
+ tot = 0;
+ data = NULL;
+ break;
+ }
+
+ *r_tot = tot;
+ return data;
}
#define GET_CD_DATA(me, data) ((me)->edit_mesh ? &(me)->edit_mesh->bm->data : &(me)->data)
static void delete_customdata_layer(Mesh *me, CustomDataLayer *layer)
{
- const int type = layer->type;
- CustomData *data;
- int layer_index, tot, n;
-
- data = mesh_customdata_get_type(me, (ELEM(type, CD_MLOOPUV, CD_MLOOPCOL)) ? BM_LOOP : BM_FACE, &tot);
- layer_index = CustomData_get_layer_index(data, type);
- n = (layer - &data->layers[layer_index]);
- BLI_assert(n >= 0 && (n + layer_index) < data->totlayer);
-
- if (me->edit_mesh) {
- BM_data_layer_free_n(me->edit_mesh->bm, data, type, n);
- }
- else {
- CustomData_free_layer(data, type, tot, layer_index + n);
- BKE_mesh_update_customdata_pointers(me, true);
- }
+ const int type = layer->type;
+ CustomData *data;
+ int layer_index, tot, n;
+
+ data = mesh_customdata_get_type(
+ me, (ELEM(type, CD_MLOOPUV, CD_MLOOPCOL)) ? BM_LOOP : BM_FACE, &tot);
+ layer_index = CustomData_get_layer_index(data, type);
+ n = (layer - &data->layers[layer_index]);
+ BLI_assert(n >= 0 && (n + layer_index) < data->totlayer);
+
+ if (me->edit_mesh) {
+ BM_data_layer_free_n(me->edit_mesh->bm, data, type, n);
+ }
+ else {
+ CustomData_free_layer(data, type, tot, layer_index + n);
+ BKE_mesh_update_customdata_pointers(me, true);
+ }
}
static void mesh_uv_reset_array(float **fuv, const int len)
{
- if (len == 3) {
- fuv[0][0] = 0.0;
- fuv[0][1] = 0.0;
-
- fuv[1][0] = 1.0;
- fuv[1][1] = 0.0;
-
- fuv[2][0] = 1.0;
- fuv[2][1] = 1.0;
- }
- else if (len == 4) {
- fuv[0][0] = 0.0;
- fuv[0][1] = 0.0;
-
- fuv[1][0] = 1.0;
- fuv[1][1] = 0.0;
-
- fuv[2][0] = 1.0;
- fuv[2][1] = 1.0;
-
- fuv[3][0] = 0.0;
- fuv[3][1] = 1.0;
- /*make sure we ignore 2-sided faces*/
- }
- else if (len > 2) {
- float fac = 0.0f, dfac = 1.0f / (float)len;
- int i;
-
- dfac *= (float)M_PI * 2.0f;
-
- for (i = 0; i < len; i++) {
- fuv[i][0] = 0.5f * sinf(fac) + 0.5f;
- fuv[i][1] = 0.5f * cosf(fac) + 0.5f;
-
- fac += dfac;
- }
- }
+ if (len == 3) {
+ fuv[0][0] = 0.0;
+ fuv[0][1] = 0.0;
+
+ fuv[1][0] = 1.0;
+ fuv[1][1] = 0.0;
+
+ fuv[2][0] = 1.0;
+ fuv[2][1] = 1.0;
+ }
+ else if (len == 4) {
+ fuv[0][0] = 0.0;
+ fuv[0][1] = 0.0;
+
+ fuv[1][0] = 1.0;
+ fuv[1][1] = 0.0;
+
+ fuv[2][0] = 1.0;
+ fuv[2][1] = 1.0;
+
+ fuv[3][0] = 0.0;
+ fuv[3][1] = 1.0;
+ /*make sure we ignore 2-sided faces*/
+ }
+ else if (len > 2) {
+ float fac = 0.0f, dfac = 1.0f / (float)len;
+ int i;
+
+ dfac *= (float)M_PI * 2.0f;
+
+ for (i = 0; i < len; i++) {
+ fuv[i][0] = 0.5f * sinf(fac) + 0.5f;
+ fuv[i][1] = 0.5f * cosf(fac) + 0.5f;
+
+ fac += dfac;
+ }
+ }
}
static void mesh_uv_reset_bmface(BMFace *f, const int cd_loop_uv_offset)
{
- float **fuv = BLI_array_alloca(fuv, f->len);
- BMIter liter;
- BMLoop *l;
- int i;
+ float **fuv = BLI_array_alloca(fuv, f->len);
+ BMIter liter;
+ BMLoop *l;
+ int i;
- BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, i) {
- fuv[i] = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset))->uv;
- }
+ BM_ITER_ELEM_INDEX(l, &liter, f, BM_LOOPS_OF_FACE, i)
+ {
+ fuv[i] = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset))->uv;
+ }
- mesh_uv_reset_array(fuv, f->len);
+ mesh_uv_reset_array(fuv, f->len);
}
static void mesh_uv_reset_mface(MPoly *mp, MLoopUV *mloopuv)
{
- float **fuv = BLI_array_alloca(fuv, mp->totloop);
- int i;
+ float **fuv = BLI_array_alloca(fuv, mp->totloop);
+ int i;
- for (i = 0; i < mp->totloop; i++) {
- fuv[i] = mloopuv[mp->loopstart + i].uv;
- }
+ for (i = 0; i < mp->totloop; i++) {
+ fuv[i] = mloopuv[mp->loopstart + i].uv;
+ }
- mesh_uv_reset_array(fuv, mp->totloop);
+ mesh_uv_reset_array(fuv, mp->totloop);
}
/* without bContext, called in uvedit */
void ED_mesh_uv_loop_reset_ex(struct Mesh *me, const int layernum)
{
- BMEditMesh *em = me->edit_mesh;
+ BMEditMesh *em = me->edit_mesh;
- if (em) {
- /* Collect BMesh UVs */
- const int cd_loop_uv_offset = CustomData_get_n_offset(&em->bm->ldata, CD_MLOOPUV, layernum);
+ if (em) {
+ /* Collect BMesh UVs */
+ const int cd_loop_uv_offset = CustomData_get_n_offset(&em->bm->ldata, CD_MLOOPUV, layernum);
- BMFace *efa;
- BMIter iter;
+ BMFace *efa;
+ BMIter iter;
- BLI_assert(cd_loop_uv_offset != -1);
+ BLI_assert(cd_loop_uv_offset != -1);
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
- continue;
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ continue;
- mesh_uv_reset_bmface(efa, cd_loop_uv_offset);
- }
- }
- else {
- /* Collect Mesh UVs */
- MLoopUV *mloopuv;
- int i;
+ mesh_uv_reset_bmface(efa, cd_loop_uv_offset);
+ }
+ }
+ else {
+ /* Collect Mesh UVs */
+ MLoopUV *mloopuv;
+ int i;
- BLI_assert(CustomData_has_layer(&me->ldata, CD_MLOOPUV));
- mloopuv = CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, layernum);
+ BLI_assert(CustomData_has_layer(&me->ldata, CD_MLOOPUV));
+ mloopuv = CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, layernum);
- for (i = 0; i < me->totpoly; i++) {
- mesh_uv_reset_mface(&me->mpoly[i], mloopuv);
- }
- }
+ for (i = 0; i < me->totpoly; i++) {
+ mesh_uv_reset_mface(&me->mpoly[i], mloopuv);
+ }
+ }
- DEG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
}
void ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me)
{
- /* could be ldata or pdata */
- CustomData *ldata = GET_CD_DATA(me, ldata);
- const int layernum = CustomData_get_active_layer(ldata, CD_MLOOPUV);
- ED_mesh_uv_loop_reset_ex(me, layernum);
+ /* could be ldata or pdata */
+ CustomData *ldata = GET_CD_DATA(me, ldata);
+ const int layernum = CustomData_get_active_layer(ldata, CD_MLOOPUV);
+ ED_mesh_uv_loop_reset_ex(me, layernum);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
}
/* note: keep in sync with ED_mesh_color_add */
int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set, const bool do_init)
{
- BMEditMesh *em;
- int layernum_dst;
-
- bool is_init = false;
-
- if (me->edit_mesh) {
- em = me->edit_mesh;
-
- layernum_dst = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPUV);
- if (layernum_dst >= MAX_MTFACE)
- return -1;
-
- /* CD_MLOOPUV */
- BM_data_layer_add_named(em->bm, &em->bm->ldata, CD_MLOOPUV, name);
- /* copy data from active UV */
- if (layernum_dst && do_init) {
- const int layernum_src = CustomData_get_active_layer(&em->bm->ldata, CD_MLOOPUV);
- BM_data_layer_copy(em->bm, &em->bm->ldata, CD_MLOOPUV, layernum_src, layernum_dst);
-
- is_init = true;
- }
- if (active_set || layernum_dst == 0) {
- CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPUV, layernum_dst);
- }
- }
- else {
- layernum_dst = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
- if (layernum_dst >= MAX_MTFACE)
- return -1;
-
- if (me->mloopuv && do_init) {
- CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DUPLICATE, me->mloopuv, me->totloop, name);
- CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface, name);
- is_init = true;
- }
- else {
- CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, name);
- CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface, name);
- }
-
- if (active_set || layernum_dst == 0) {
- CustomData_set_layer_active(&me->ldata, CD_MLOOPUV, layernum_dst);
- CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum_dst);
- }
-
- BKE_mesh_update_customdata_pointers(me, true);
- }
-
- /* don't overwrite our copied coords */
- if (!is_init && do_init) {
- ED_mesh_uv_loop_reset_ex(me, layernum_dst);
- }
-
- DEG_id_tag_update(&me->id, 0);
- WM_main_add_notifier(NC_GEOM | ND_DATA, me);
-
- return layernum_dst;
+ BMEditMesh *em;
+ int layernum_dst;
+
+ bool is_init = false;
+
+ if (me->edit_mesh) {
+ em = me->edit_mesh;
+
+ layernum_dst = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPUV);
+ if (layernum_dst >= MAX_MTFACE)
+ return -1;
+
+ /* CD_MLOOPUV */
+ BM_data_layer_add_named(em->bm, &em->bm->ldata, CD_MLOOPUV, name);
+ /* copy data from active UV */
+ if (layernum_dst && do_init) {
+ const int layernum_src = CustomData_get_active_layer(&em->bm->ldata, CD_MLOOPUV);
+ BM_data_layer_copy(em->bm, &em->bm->ldata, CD_MLOOPUV, layernum_src, layernum_dst);
+
+ is_init = true;
+ }
+ if (active_set || layernum_dst == 0) {
+ CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPUV, layernum_dst);
+ }
+ }
+ else {
+ layernum_dst = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
+ if (layernum_dst >= MAX_MTFACE)
+ return -1;
+
+ if (me->mloopuv && do_init) {
+ CustomData_add_layer_named(
+ &me->ldata, CD_MLOOPUV, CD_DUPLICATE, me->mloopuv, me->totloop, name);
+ CustomData_add_layer_named(
+ &me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface, name);
+ is_init = true;
+ }
+ else {
+ CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, name);
+ CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface, name);
+ }
+
+ if (active_set || layernum_dst == 0) {
+ CustomData_set_layer_active(&me->ldata, CD_MLOOPUV, layernum_dst);
+ CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum_dst);
+ }
+
+ BKE_mesh_update_customdata_pointers(me, true);
+ }
+
+ /* don't overwrite our copied coords */
+ if (!is_init && do_init) {
+ ED_mesh_uv_loop_reset_ex(me, layernum_dst);
+ }
+
+ DEG_id_tag_update(&me->id, 0);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, me);
+
+ return layernum_dst;
}
void ED_mesh_uv_texture_ensure(struct Mesh *me, const char *name)
{
- BMEditMesh *em;
- int layernum_dst;
-
- if (me->edit_mesh) {
- em = me->edit_mesh;
-
- layernum_dst = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPUV);
- if (layernum_dst == 0)
- ED_mesh_uv_texture_add(me, name, true, true);
- }
- else {
- layernum_dst = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
- if (layernum_dst == 0)
- ED_mesh_uv_texture_add(me, name, true, true);
- }
+ BMEditMesh *em;
+ int layernum_dst;
+
+ if (me->edit_mesh) {
+ em = me->edit_mesh;
+
+ layernum_dst = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPUV);
+ if (layernum_dst == 0)
+ ED_mesh_uv_texture_add(me, name, true, true);
+ }
+ else {
+ layernum_dst = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
+ if (layernum_dst == 0)
+ ED_mesh_uv_texture_add(me, name, true, true);
+ }
}
-
bool ED_mesh_uv_texture_remove_index(Mesh *me, const int n)
{
- CustomData *ldata = GET_CD_DATA(me, ldata);
- CustomDataLayer *cdlu;
- int index;
+ CustomData *ldata = GET_CD_DATA(me, ldata);
+ CustomDataLayer *cdlu;
+ int index;
- index = CustomData_get_layer_index_n(ldata, CD_MLOOPUV, n);
- cdlu = (index == -1) ? NULL : &ldata->layers[index];
+ index = CustomData_get_layer_index_n(ldata, CD_MLOOPUV, n);
+ cdlu = (index == -1) ? NULL : &ldata->layers[index];
- if (!cdlu)
- return false;
+ if (!cdlu)
+ return false;
- delete_customdata_layer(me, cdlu);
+ delete_customdata_layer(me, cdlu);
- DEG_id_tag_update(&me->id, 0);
- WM_main_add_notifier(NC_GEOM | ND_DATA, me);
+ DEG_id_tag_update(&me->id, 0);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, me);
- return true;
+ return true;
}
bool ED_mesh_uv_texture_remove_active(Mesh *me)
{
- /* texpoly/uv are assumed to be in sync */
- CustomData *ldata = GET_CD_DATA(me, ldata);
- const int n = CustomData_get_active_layer(ldata, CD_MLOOPUV);
-
- if (n != -1) {
- return ED_mesh_uv_texture_remove_index(me, n);
- }
- else {
- return false;
- }
+ /* texpoly/uv are assumed to be in sync */
+ CustomData *ldata = GET_CD_DATA(me, ldata);
+ const int n = CustomData_get_active_layer(ldata, CD_MLOOPUV);
+
+ if (n != -1) {
+ return ED_mesh_uv_texture_remove_index(me, n);
+ }
+ else {
+ return false;
+ }
}
bool ED_mesh_uv_texture_remove_named(Mesh *me, const char *name)
{
- /* texpoly/uv are assumed to be in sync */
- CustomData *ldata = GET_CD_DATA(me, ldata);
- const int n = CustomData_get_named_layer(ldata, CD_MLOOPUV, name);
- if (n != -1) {
- return ED_mesh_uv_texture_remove_index(me, n);
- }
- else {
- return false;
- }
+ /* texpoly/uv are assumed to be in sync */
+ CustomData *ldata = GET_CD_DATA(me, ldata);
+ const int n = CustomData_get_named_layer(ldata, CD_MLOOPUV, name);
+ if (n != -1) {
+ return ED_mesh_uv_texture_remove_index(me, n);
+ }
+ else {
+ return false;
+ }
}
/* note: keep in sync with ED_mesh_uv_texture_add */
int ED_mesh_color_add(Mesh *me, const char *name, const bool active_set, const bool do_init)
{
- BMEditMesh *em;
- int layernum;
-
- if (me->edit_mesh) {
- em = me->edit_mesh;
-
- layernum = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPCOL);
- if (layernum >= MAX_MCOL) {
- return -1;
- }
-
- /* CD_MLOOPCOL */
- BM_data_layer_add_named(em->bm, &em->bm->ldata, CD_MLOOPCOL, name);
- /* copy data from active vertex color layer */
- if (layernum && do_init) {
- const int layernum_dst = CustomData_get_active_layer(&em->bm->ldata, CD_MLOOPCOL);
- BM_data_layer_copy(em->bm, &em->bm->ldata, CD_MLOOPCOL, layernum_dst, layernum);
- }
- if (active_set || layernum == 0) {
- CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPCOL, layernum);
- }
- }
- else {
- layernum = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
- if (layernum >= MAX_MCOL) {
- return -1;
- }
-
- if (me->mloopcol && do_init) {
- CustomData_add_layer_named(&me->ldata, CD_MLOOPCOL, CD_DUPLICATE, me->mloopcol, me->totloop, name);
- CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface, name);
- }
- else {
- CustomData_add_layer_named(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop, name);
- CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface, name);
- }
-
- if (active_set || layernum == 0) {
- CustomData_set_layer_active(&me->ldata, CD_MLOOPCOL, layernum);
- CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
- }
-
- BKE_mesh_update_customdata_pointers(me, true);
- }
-
- DEG_id_tag_update(&me->id, 0);
- WM_main_add_notifier(NC_GEOM | ND_DATA, me);
-
- return layernum;
+ BMEditMesh *em;
+ int layernum;
+
+ if (me->edit_mesh) {
+ em = me->edit_mesh;
+
+ layernum = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPCOL);
+ if (layernum >= MAX_MCOL) {
+ return -1;
+ }
+
+ /* CD_MLOOPCOL */
+ BM_data_layer_add_named(em->bm, &em->bm->ldata, CD_MLOOPCOL, name);
+ /* copy data from active vertex color layer */
+ if (layernum && do_init) {
+ const int layernum_dst = CustomData_get_active_layer(&em->bm->ldata, CD_MLOOPCOL);
+ BM_data_layer_copy(em->bm, &em->bm->ldata, CD_MLOOPCOL, layernum_dst, layernum);
+ }
+ if (active_set || layernum == 0) {
+ CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPCOL, layernum);
+ }
+ }
+ else {
+ layernum = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
+ if (layernum >= MAX_MCOL) {
+ return -1;
+ }
+
+ if (me->mloopcol && do_init) {
+ CustomData_add_layer_named(
+ &me->ldata, CD_MLOOPCOL, CD_DUPLICATE, me->mloopcol, me->totloop, name);
+ CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface, name);
+ }
+ else {
+ CustomData_add_layer_named(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop, name);
+ CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface, name);
+ }
+
+ if (active_set || layernum == 0) {
+ CustomData_set_layer_active(&me->ldata, CD_MLOOPCOL, layernum);
+ CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
+ }
+
+ BKE_mesh_update_customdata_pointers(me, true);
+ }
+
+ DEG_id_tag_update(&me->id, 0);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, me);
+
+ return layernum;
}
bool ED_mesh_color_ensure(struct Mesh *me, const char *name)
{
- BLI_assert(me->edit_mesh == NULL);
+ BLI_assert(me->edit_mesh == NULL);
- if (!me->mloopcol && me->totloop) {
- CustomData_add_layer_named(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop, name);
- BKE_mesh_update_customdata_pointers(me, true);
- }
+ if (!me->mloopcol && me->totloop) {
+ CustomData_add_layer_named(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop, name);
+ BKE_mesh_update_customdata_pointers(me, true);
+ }
- DEG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
- return (me->mloopcol != NULL);
+ return (me->mloopcol != NULL);
}
bool ED_mesh_color_remove_index(Mesh *me, const int n)
{
- CustomData *ldata = GET_CD_DATA(me, ldata);
- CustomDataLayer *cdl;
- int index;
+ CustomData *ldata = GET_CD_DATA(me, ldata);
+ CustomDataLayer *cdl;
+ int index;
- index = CustomData_get_layer_index_n(ldata, CD_MLOOPCOL, n);
- cdl = (index == -1) ? NULL : &ldata->layers[index];
+ index = CustomData_get_layer_index_n(ldata, CD_MLOOPCOL, n);
+ cdl = (index == -1) ? NULL : &ldata->layers[index];
- if (!cdl)
- return false;
+ if (!cdl)
+ return false;
- delete_customdata_layer(me, cdl);
- DEG_id_tag_update(&me->id, 0);
- WM_main_add_notifier(NC_GEOM | ND_DATA, me);
+ delete_customdata_layer(me, cdl);
+ DEG_id_tag_update(&me->id, 0);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, me);
- return true;
+ return true;
}
bool ED_mesh_color_remove_active(Mesh *me)
{
- CustomData *ldata = GET_CD_DATA(me, ldata);
- const int n = CustomData_get_active_layer(ldata, CD_MLOOPCOL);
- if (n != -1) {
- return ED_mesh_color_remove_index(me, n);
- }
- else {
- return false;
- }
+ CustomData *ldata = GET_CD_DATA(me, ldata);
+ const int n = CustomData_get_active_layer(ldata, CD_MLOOPCOL);
+ if (n != -1) {
+ return ED_mesh_color_remove_index(me, n);
+ }
+ else {
+ return false;
+ }
}
bool ED_mesh_color_remove_named(Mesh *me, const char *name)
{
- CustomData *ldata = GET_CD_DATA(me, ldata);
- const int n = CustomData_get_named_layer(ldata, CD_MLOOPCOL, name);
- if (n != -1) {
- return ED_mesh_color_remove_index(me, n);
- }
- else {
- return false;
- }
+ CustomData *ldata = GET_CD_DATA(me, ldata);
+ const int n = CustomData_get_named_layer(ldata, CD_MLOOPCOL, name);
+ if (n != -1) {
+ return ED_mesh_color_remove_index(me, n);
+ }
+ else {
+ return false;
+ }
}
/*********************** UV texture operators ************************/
static bool layers_poll(bContext *C)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
- return (ob && !ID_IS_LINKED(ob) && ob->type == OB_MESH && data && !ID_IS_LINKED(data));
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ return (ob && !ID_IS_LINKED(ob) && ob->type == OB_MESH && data && !ID_IS_LINKED(data));
}
static int mesh_uv_texture_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Object *ob = ED_object_context(C);
+ Mesh *me = ob->data;
- if (ED_mesh_uv_texture_add(me, NULL, true, true) == -1)
- return OPERATOR_CANCELLED;
+ if (ED_mesh_uv_texture_add(me, NULL, true, true) == -1)
+ return OPERATOR_CANCELLED;
- if (ob->mode & OB_MODE_TEXTURE_PAINT) {
- Scene *scene = CTX_data_scene(C);
- BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
- WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
- }
+ if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ Scene *scene = CTX_data_scene(C);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_uv_texture_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add UV Map";
- ot->description = "Add UV Map";
- ot->idname = "MESH_OT_uv_texture_add";
+ /* identifiers */
+ ot->name = "Add UV Map";
+ ot->description = "Add UV Map";
+ ot->idname = "MESH_OT_uv_texture_add";
- /* api callbacks */
- ot->poll = layers_poll;
- ot->exec = mesh_uv_texture_add_exec;
+ /* api callbacks */
+ ot->poll = layers_poll;
+ ot->exec = mesh_uv_texture_add_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int mesh_uv_texture_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Object *ob = ED_object_context(C);
+ Mesh *me = ob->data;
- if (!ED_mesh_uv_texture_remove_active(me))
- return OPERATOR_CANCELLED;
+ if (!ED_mesh_uv_texture_remove_active(me))
+ return OPERATOR_CANCELLED;
- if (ob->mode & OB_MODE_TEXTURE_PAINT) {
- Scene *scene = CTX_data_scene(C);
- BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
- WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
- }
+ if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ Scene *scene = CTX_data_scene(C);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_uv_texture_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove UV Map";
- ot->description = "Remove UV Map";
- ot->idname = "MESH_OT_uv_texture_remove";
+ /* identifiers */
+ ot->name = "Remove UV Map";
+ ot->description = "Remove UV Map";
+ ot->idname = "MESH_OT_uv_texture_remove";
- /* api callbacks */
- ot->poll = layers_poll;
- ot->exec = mesh_uv_texture_remove_exec;
+ /* api callbacks */
+ ot->poll = layers_poll;
+ ot->exec = mesh_uv_texture_remove_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/*********************** vertex color operators ************************/
static int mesh_vertex_color_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Object *ob = ED_object_context(C);
+ Mesh *me = ob->data;
- if (ED_mesh_color_add(me, NULL, true, true) == -1)
- return OPERATOR_CANCELLED;
+ if (ED_mesh_color_add(me, NULL, true, true) == -1)
+ return OPERATOR_CANCELLED;
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_vertex_color_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Vertex Color";
- ot->description = "Add vertex color layer";
- ot->idname = "MESH_OT_vertex_color_add";
+ /* identifiers */
+ ot->name = "Add Vertex Color";
+ ot->description = "Add vertex color layer";
+ ot->idname = "MESH_OT_vertex_color_add";
- /* api callbacks */
- ot->poll = layers_poll;
- ot->exec = mesh_vertex_color_add_exec;
+ /* api callbacks */
+ ot->poll = layers_poll;
+ ot->exec = mesh_vertex_color_add_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int mesh_vertex_color_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Object *ob = ED_object_context(C);
+ Mesh *me = ob->data;
- if (!ED_mesh_color_remove_active(me))
- return OPERATOR_CANCELLED;
+ if (!ED_mesh_color_remove_active(me))
+ return OPERATOR_CANCELLED;
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_vertex_color_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Vertex Color";
- ot->description = "Remove vertex color layer";
- ot->idname = "MESH_OT_vertex_color_remove";
+ /* identifiers */
+ ot->name = "Remove Vertex Color";
+ ot->description = "Remove vertex color layer";
+ ot->idname = "MESH_OT_vertex_color_remove";
- /* api callbacks */
- ot->exec = mesh_vertex_color_remove_exec;
- ot->poll = layers_poll;
+ /* api callbacks */
+ ot->exec = mesh_vertex_color_remove_exec;
+ ot->poll = layers_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* *** CustomData clear functions, we need an operator for each *** */
-static int mesh_customdata_clear_exec__internal(bContext *C,
- char htype, int type)
+static int mesh_customdata_clear_exec__internal(bContext *C, char htype, int type)
{
- Object *obedit = ED_object_context(C);
- Mesh *me = obedit->data;
-
- int tot;
- CustomData *data = mesh_customdata_get_type(me, htype, &tot);
-
- BLI_assert(CustomData_layertype_is_singleton(type) == true);
-
- if (CustomData_has_layer(data, type)) {
- if (me->edit_mesh) {
- BM_data_layer_free(me->edit_mesh->bm, data, type);
- }
- else {
- CustomData_free_layers(data, type, tot);
- }
-
- DEG_id_tag_update(&me->id, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Object *obedit = ED_object_context(C);
+ Mesh *me = obedit->data;
+
+ int tot;
+ CustomData *data = mesh_customdata_get_type(me, htype, &tot);
+
+ BLI_assert(CustomData_layertype_is_singleton(type) == true);
+
+ if (CustomData_has_layer(data, type)) {
+ if (me->edit_mesh) {
+ BM_data_layer_free(me->edit_mesh->bm, data, type);
+ }
+ else {
+ CustomData_free_layers(data, type, tot);
+ }
+
+ DEG_id_tag_update(&me->id, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
/* Clear Mask */
static bool mesh_customdata_mask_clear_poll(bContext *C)
{
- Object *ob = ED_object_context(C);
- if (ob && ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- /* special case - can't run this if we're in sculpt mode */
- if (ob->mode & OB_MODE_SCULPT) {
- return false;
- }
-
- if (!ID_IS_LINKED(me)) {
- CustomData *data = GET_CD_DATA(me, vdata);
- if (CustomData_has_layer(data, CD_PAINT_MASK)) {
- return true;
- }
- data = GET_CD_DATA(me, ldata);
- if (CustomData_has_layer(data, CD_GRID_PAINT_MASK)) {
- return true;
- }
- }
- }
- return false;
+ Object *ob = ED_object_context(C);
+ if (ob && ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ /* special case - can't run this if we're in sculpt mode */
+ if (ob->mode & OB_MODE_SCULPT) {
+ return false;
+ }
+
+ if (!ID_IS_LINKED(me)) {
+ CustomData *data = GET_CD_DATA(me, vdata);
+ if (CustomData_has_layer(data, CD_PAINT_MASK)) {
+ return true;
+ }
+ data = GET_CD_DATA(me, ldata);
+ if (CustomData_has_layer(data, CD_GRID_PAINT_MASK)) {
+ return true;
+ }
+ }
+ }
+ return false;
}
static int mesh_customdata_mask_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- int ret_a = mesh_customdata_clear_exec__internal(C, BM_VERT, CD_PAINT_MASK);
- int ret_b = mesh_customdata_clear_exec__internal(C, BM_LOOP, CD_GRID_PAINT_MASK);
-
- if (ret_a == OPERATOR_FINISHED ||
- ret_b == OPERATOR_FINISHED)
- {
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ int ret_a = mesh_customdata_clear_exec__internal(C, BM_VERT, CD_PAINT_MASK);
+ int ret_b = mesh_customdata_clear_exec__internal(C, BM_LOOP, CD_GRID_PAINT_MASK);
+
+ if (ret_a == OPERATOR_FINISHED || ret_b == OPERATOR_FINISHED) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void MESH_OT_customdata_mask_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Sculpt-Mask Data";
- ot->idname = "MESH_OT_customdata_mask_clear";
- ot->description = "Clear vertex sculpt masking data from the mesh";
+ /* identifiers */
+ ot->name = "Clear Sculpt-Mask Data";
+ ot->idname = "MESH_OT_customdata_mask_clear";
+ ot->description = "Clear vertex sculpt masking data from the mesh";
- /* api callbacks */
- ot->exec = mesh_customdata_mask_clear_exec;
- ot->poll = mesh_customdata_mask_clear_poll;
+ /* api callbacks */
+ ot->exec = mesh_customdata_mask_clear_exec;
+ ot->poll = mesh_customdata_mask_clear_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/**
@@ -705,545 +705,554 @@ void MESH_OT_customdata_mask_clear(wmOperatorType *ot)
*/
static int mesh_customdata_skin_state(bContext *C)
{
- Object *ob = ED_object_context(C);
-
- if (ob && ob->type == OB_MESH) {
- Mesh *me = ob->data;
- if (!ID_IS_LINKED(me)) {
- CustomData *data = GET_CD_DATA(me, vdata);
- return CustomData_has_layer(data, CD_MVERT_SKIN);
- }
- }
- return -1;
+ Object *ob = ED_object_context(C);
+
+ if (ob && ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ if (!ID_IS_LINKED(me)) {
+ CustomData *data = GET_CD_DATA(me, vdata);
+ return CustomData_has_layer(data, CD_MVERT_SKIN);
+ }
+ }
+ return -1;
}
static bool mesh_customdata_skin_add_poll(bContext *C)
{
- return (mesh_customdata_skin_state(C) == 0);
+ return (mesh_customdata_skin_state(C) == 0);
}
static int mesh_customdata_skin_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Object *ob = ED_object_context(C);
+ Mesh *me = ob->data;
- BKE_mesh_ensure_skin_customdata(me);
+ BKE_mesh_ensure_skin_customdata(me);
- DEG_id_tag_update(&me->id, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+ DEG_id_tag_update(&me->id, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_customdata_skin_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Skin Data";
- ot->idname = "MESH_OT_customdata_skin_add";
- ot->description = "Add a vertex skin layer";
+ /* identifiers */
+ ot->name = "Add Skin Data";
+ ot->idname = "MESH_OT_customdata_skin_add";
+ ot->description = "Add a vertex skin layer";
- /* api callbacks */
- ot->exec = mesh_customdata_skin_add_exec;
- ot->poll = mesh_customdata_skin_add_poll;
+ /* api callbacks */
+ ot->exec = mesh_customdata_skin_add_exec;
+ ot->poll = mesh_customdata_skin_add_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static bool mesh_customdata_skin_clear_poll(bContext *C)
{
- return (mesh_customdata_skin_state(C) == 1);
+ return (mesh_customdata_skin_state(C) == 1);
}
static int mesh_customdata_skin_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- return mesh_customdata_clear_exec__internal(C, BM_VERT, CD_MVERT_SKIN);
+ return mesh_customdata_clear_exec__internal(C, BM_VERT, CD_MVERT_SKIN);
}
void MESH_OT_customdata_skin_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Skin Data";
- ot->idname = "MESH_OT_customdata_skin_clear";
- ot->description = "Clear vertex skin layer";
+ /* identifiers */
+ ot->name = "Clear Skin Data";
+ ot->idname = "MESH_OT_customdata_skin_clear";
+ ot->description = "Clear vertex skin layer";
- /* api callbacks */
- ot->exec = mesh_customdata_skin_clear_exec;
- ot->poll = mesh_customdata_skin_clear_poll;
+ /* api callbacks */
+ ot->exec = mesh_customdata_skin_clear_exec;
+ ot->poll = mesh_customdata_skin_clear_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* Clear custom loop normals */
static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
-
- if (!BKE_mesh_has_custom_loop_normals(me)) {
- CustomData *data = GET_CD_DATA(me, ldata);
-
- if (me->edit_mesh) {
- /* Tag edges as sharp according to smooth threshold if needed, to preserve autosmooth shading. */
- if (me->flag & ME_AUTOSMOOTH) {
- BM_edges_sharp_from_angle_set(me->edit_mesh->bm, me->smoothresh);
- }
-
- BM_data_layer_add(me->edit_mesh->bm, data, CD_CUSTOMLOOPNORMAL);
- }
- else {
- /* Tag edges as sharp according to smooth threshold if needed, to preserve autosmooth shading. */
- if (me->flag & ME_AUTOSMOOTH) {
- float (*polynors)[3] = MEM_mallocN(sizeof(*polynors) * (size_t)me->totpoly, __func__);
-
- BKE_mesh_calc_normals_poly(
- me->mvert, NULL, me->totvert,
- me->mloop, me->mpoly,
- me->totloop, me->totpoly,
- polynors, true);
-
- BKE_edges_sharp_from_angle_set(
- me->mvert, me->totvert,
- me->medge, me->totedge,
- me->mloop, me->totloop,
- me->mpoly, polynors, me->totpoly,
- me->smoothresh);
-
- MEM_freeN(polynors);
- }
-
- CustomData_add_layer(data, CD_CUSTOMLOOPNORMAL, CD_DEFAULT, NULL, me->totloop);
- }
-
- DEG_id_tag_update(&me->id, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
-
- return OPERATOR_FINISHED;
- }
- return OPERATOR_CANCELLED;
+ Object *ob = ED_object_context(C);
+ Mesh *me = ob->data;
+
+ if (!BKE_mesh_has_custom_loop_normals(me)) {
+ CustomData *data = GET_CD_DATA(me, ldata);
+
+ if (me->edit_mesh) {
+ /* Tag edges as sharp according to smooth threshold if needed, to preserve autosmooth shading. */
+ if (me->flag & ME_AUTOSMOOTH) {
+ BM_edges_sharp_from_angle_set(me->edit_mesh->bm, me->smoothresh);
+ }
+
+ BM_data_layer_add(me->edit_mesh->bm, data, CD_CUSTOMLOOPNORMAL);
+ }
+ else {
+ /* Tag edges as sharp according to smooth threshold if needed, to preserve autosmooth shading. */
+ if (me->flag & ME_AUTOSMOOTH) {
+ float(*polynors)[3] = MEM_mallocN(sizeof(*polynors) * (size_t)me->totpoly, __func__);
+
+ BKE_mesh_calc_normals_poly(me->mvert,
+ NULL,
+ me->totvert,
+ me->mloop,
+ me->mpoly,
+ me->totloop,
+ me->totpoly,
+ polynors,
+ true);
+
+ BKE_edges_sharp_from_angle_set(me->mvert,
+ me->totvert,
+ me->medge,
+ me->totedge,
+ me->mloop,
+ me->totloop,
+ me->mpoly,
+ polynors,
+ me->totpoly,
+ me->smoothresh);
+
+ MEM_freeN(polynors);
+ }
+
+ CustomData_add_layer(data, CD_CUSTOMLOOPNORMAL, CD_DEFAULT, NULL, me->totloop);
+ }
+
+ DEG_id_tag_update(&me->id, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_CANCELLED;
}
void MESH_OT_customdata_custom_splitnormals_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Custom Split Normals Data";
- ot->idname = "MESH_OT_customdata_custom_splitnormals_add";
- ot->description = "Add a custom split normals layer, if none exists yet";
+ /* identifiers */
+ ot->name = "Add Custom Split Normals Data";
+ ot->idname = "MESH_OT_customdata_custom_splitnormals_add";
+ ot->description = "Add a custom split normals layer, if none exists yet";
- /* api callbacks */
- ot->exec = mesh_customdata_custom_splitnormals_add_exec;
- ot->poll = ED_operator_object_active_editable_mesh;
+ /* api callbacks */
+ ot->exec = mesh_customdata_custom_splitnormals_add_exec;
+ ot->poll = ED_operator_object_active_editable_mesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int mesh_customdata_custom_splitnormals_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Object *ob = ED_object_context(C);
+ Mesh *me = ob->data;
- if (BKE_mesh_has_custom_loop_normals(me)) {
- return mesh_customdata_clear_exec__internal(C, BM_LOOP, CD_CUSTOMLOOPNORMAL);
- }
- return OPERATOR_CANCELLED;
+ if (BKE_mesh_has_custom_loop_normals(me)) {
+ return mesh_customdata_clear_exec__internal(C, BM_LOOP, CD_CUSTOMLOOPNORMAL);
+ }
+ return OPERATOR_CANCELLED;
}
void MESH_OT_customdata_custom_splitnormals_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Custom Split Normals Data";
- ot->idname = "MESH_OT_customdata_custom_splitnormals_clear";
- ot->description = "Remove the custom split normals layer, if it exists";
+ /* identifiers */
+ ot->name = "Clear Custom Split Normals Data";
+ ot->idname = "MESH_OT_customdata_custom_splitnormals_clear";
+ ot->description = "Remove the custom split normals layer, if it exists";
- /* api callbacks */
- ot->exec = mesh_customdata_custom_splitnormals_clear_exec;
- ot->poll = ED_operator_object_active_editable_mesh;
+ /* api callbacks */
+ ot->exec = mesh_customdata_custom_splitnormals_clear_exec;
+ ot->poll = ED_operator_object_active_editable_mesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************** Add Geometry Layers *************************/
-void ED_mesh_update(Mesh *mesh, bContext *C, bool calc_edges, bool calc_edges_loose, bool calc_tessface)
+void ED_mesh_update(
+ Mesh *mesh, bContext *C, bool calc_edges, bool calc_edges_loose, bool calc_tessface)
{
- bool tessface_input = false;
+ bool tessface_input = false;
- if (mesh->totface > 0 && mesh->totpoly == 0) {
- BKE_mesh_convert_mfaces_to_mpolys(mesh);
+ if (mesh->totface > 0 && mesh->totpoly == 0) {
+ BKE_mesh_convert_mfaces_to_mpolys(mesh);
- /* would only be converting back again, don't bother */
- tessface_input = true;
- }
+ /* would only be converting back again, don't bother */
+ tessface_input = true;
+ }
- if (calc_edges_loose && mesh->totedge) {
- BKE_mesh_calc_edges_loose(mesh);
- }
+ if (calc_edges_loose && mesh->totedge) {
+ BKE_mesh_calc_edges_loose(mesh);
+ }
- if (calc_edges || ((mesh->totpoly || mesh->totface) && mesh->totedge == 0))
- BKE_mesh_calc_edges(mesh, calc_edges, true);
+ if (calc_edges || ((mesh->totpoly || mesh->totface) && mesh->totedge == 0))
+ BKE_mesh_calc_edges(mesh, calc_edges, true);
- if (calc_tessface) {
- if (tessface_input == false) {
- BKE_mesh_tessface_calc(mesh);
- }
- }
- else {
- /* default state is not to have tessface's so make sure this is the case */
- BKE_mesh_tessface_clear(mesh);
- }
+ if (calc_tessface) {
+ if (tessface_input == false) {
+ BKE_mesh_tessface_calc(mesh);
+ }
+ }
+ else {
+ /* default state is not to have tessface's so make sure this is the case */
+ BKE_mesh_tessface_clear(mesh);
+ }
- BKE_mesh_calc_normals(mesh);
+ BKE_mesh_calc_normals(mesh);
- DEG_id_tag_update(&mesh->id, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, mesh);
+ DEG_id_tag_update(&mesh->id, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, mesh);
}
static void mesh_add_verts(Mesh *mesh, int len)
{
- CustomData vdata;
- MVert *mvert;
- int i, totvert;
+ CustomData vdata;
+ MVert *mvert;
+ int i, totvert;
- if (len == 0)
- return;
+ if (len == 0)
+ return;
- totvert = mesh->totvert + len;
- CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH.vmask, CD_DEFAULT, totvert);
- CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert);
+ totvert = mesh->totvert + len;
+ CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH.vmask, CD_DEFAULT, totvert);
+ CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert);
- if (!CustomData_has_layer(&vdata, CD_MVERT))
- CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
+ if (!CustomData_has_layer(&vdata, CD_MVERT))
+ CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
- CustomData_free(&mesh->vdata, mesh->totvert);
- mesh->vdata = vdata;
- BKE_mesh_update_customdata_pointers(mesh, false);
+ CustomData_free(&mesh->vdata, mesh->totvert);
+ mesh->vdata = vdata;
+ BKE_mesh_update_customdata_pointers(mesh, false);
- /* scan the input list and insert the new vertices */
+ /* scan the input list and insert the new vertices */
- /* set default flags */
- mvert = &mesh->mvert[mesh->totvert];
- for (i = 0; i < len; i++, mvert++)
- mvert->flag |= SELECT;
+ /* set default flags */
+ mvert = &mesh->mvert[mesh->totvert];
+ for (i = 0; i < len; i++, mvert++)
+ mvert->flag |= SELECT;
- /* set final vertex list size */
- mesh->totvert = totvert;
+ /* set final vertex list size */
+ mesh->totvert = totvert;
}
static void mesh_add_edges(Mesh *mesh, int len)
{
- CustomData edata;
- MEdge *medge;
- int i, totedge;
+ CustomData edata;
+ MEdge *medge;
+ int i, totedge;
- if (len == 0)
- return;
+ if (len == 0)
+ return;
- totedge = mesh->totedge + len;
+ totedge = mesh->totedge + len;
- /* update customdata */
- CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_DEFAULT, totedge);
- CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge);
+ /* update customdata */
+ CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_DEFAULT, totedge);
+ CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge);
- if (!CustomData_has_layer(&edata, CD_MEDGE))
- CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
+ if (!CustomData_has_layer(&edata, CD_MEDGE))
+ CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
- CustomData_free(&mesh->edata, mesh->totedge);
- mesh->edata = edata;
- BKE_mesh_update_customdata_pointers(mesh, false); /* new edges don't change tessellation */
+ CustomData_free(&mesh->edata, mesh->totedge);
+ mesh->edata = edata;
+ BKE_mesh_update_customdata_pointers(mesh, false); /* new edges don't change tessellation */
- /* set default flags */
- medge = &mesh->medge[mesh->totedge];
- for (i = 0; i < len; i++, medge++)
- medge->flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT;
+ /* set default flags */
+ medge = &mesh->medge[mesh->totedge];
+ for (i = 0; i < len; i++, medge++)
+ medge->flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT;
- mesh->totedge = totedge;
+ mesh->totedge = totedge;
}
static void mesh_add_tessfaces(Mesh *mesh, int len)
{
- CustomData fdata;
- MFace *mface;
- int i, totface;
+ CustomData fdata;
+ MFace *mface;
+ int i, totface;
- if (len == 0)
- return;
+ if (len == 0)
+ return;
- totface = mesh->totface + len; /* new face count */
+ totface = mesh->totface + len; /* new face count */
- /* update customdata */
- CustomData_copy(&mesh->fdata, &fdata, CD_MASK_MESH.fmask, CD_DEFAULT, totface);
- CustomData_copy_data(&mesh->fdata, &fdata, 0, 0, mesh->totface);
+ /* update customdata */
+ CustomData_copy(&mesh->fdata, &fdata, CD_MASK_MESH.fmask, CD_DEFAULT, totface);
+ CustomData_copy_data(&mesh->fdata, &fdata, 0, 0, mesh->totface);
- if (!CustomData_has_layer(&fdata, CD_MFACE))
- CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface);
+ if (!CustomData_has_layer(&fdata, CD_MFACE))
+ CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface);
- CustomData_free(&mesh->fdata, mesh->totface);
- mesh->fdata = fdata;
- BKE_mesh_update_customdata_pointers(mesh, true);
+ CustomData_free(&mesh->fdata, mesh->totface);
+ mesh->fdata = fdata;
+ BKE_mesh_update_customdata_pointers(mesh, true);
- /* set default flags */
- mface = &mesh->mface[mesh->totface];
- for (i = 0; i < len; i++, mface++)
- mface->flag = ME_FACE_SEL;
+ /* set default flags */
+ mface = &mesh->mface[mesh->totface];
+ for (i = 0; i < len; i++, mface++)
+ mface->flag = ME_FACE_SEL;
- mesh->totface = totface;
+ mesh->totface = totface;
}
static void mesh_add_loops(Mesh *mesh, int len)
{
- CustomData ldata;
- int totloop;
+ CustomData ldata;
+ int totloop;
- if (len == 0)
- return;
+ if (len == 0)
+ return;
- totloop = mesh->totloop + len; /* new face count */
+ totloop = mesh->totloop + len; /* new face count */
- /* update customdata */
- CustomData_copy(&mesh->ldata, &ldata, CD_MASK_MESH.lmask, CD_DEFAULT, totloop);
- CustomData_copy_data(&mesh->ldata, &ldata, 0, 0, mesh->totloop);
+ /* update customdata */
+ CustomData_copy(&mesh->ldata, &ldata, CD_MASK_MESH.lmask, CD_DEFAULT, totloop);
+ CustomData_copy_data(&mesh->ldata, &ldata, 0, 0, mesh->totloop);
- if (!CustomData_has_layer(&ldata, CD_MLOOP))
- CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, NULL, totloop);
+ if (!CustomData_has_layer(&ldata, CD_MLOOP))
+ CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, NULL, totloop);
- CustomData_free(&mesh->ldata, mesh->totloop);
- mesh->ldata = ldata;
- BKE_mesh_update_customdata_pointers(mesh, true);
+ CustomData_free(&mesh->ldata, mesh->totloop);
+ mesh->ldata = ldata;
+ BKE_mesh_update_customdata_pointers(mesh, true);
- mesh->totloop = totloop;
+ mesh->totloop = totloop;
}
static void mesh_add_polys(Mesh *mesh, int len)
{
- CustomData pdata;
- MPoly *mpoly;
- int i, totpoly;
+ CustomData pdata;
+ MPoly *mpoly;
+ int i, totpoly;
- if (len == 0)
- return;
+ if (len == 0)
+ return;
- totpoly = mesh->totpoly + len; /* new face count */
+ totpoly = mesh->totpoly + len; /* new face count */
- /* update customdata */
- CustomData_copy(&mesh->pdata, &pdata, CD_MASK_MESH.pmask, CD_DEFAULT, totpoly);
- CustomData_copy_data(&mesh->pdata, &pdata, 0, 0, mesh->totpoly);
+ /* update customdata */
+ CustomData_copy(&mesh->pdata, &pdata, CD_MASK_MESH.pmask, CD_DEFAULT, totpoly);
+ CustomData_copy_data(&mesh->pdata, &pdata, 0, 0, mesh->totpoly);
- if (!CustomData_has_layer(&pdata, CD_MPOLY))
- CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, NULL, totpoly);
+ if (!CustomData_has_layer(&pdata, CD_MPOLY))
+ CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, NULL, totpoly);
- CustomData_free(&mesh->pdata, mesh->totpoly);
- mesh->pdata = pdata;
- BKE_mesh_update_customdata_pointers(mesh, true);
+ CustomData_free(&mesh->pdata, mesh->totpoly);
+ mesh->pdata = pdata;
+ BKE_mesh_update_customdata_pointers(mesh, true);
- /* set default flags */
- mpoly = &mesh->mpoly[mesh->totpoly];
- for (i = 0; i < len; i++, mpoly++)
- mpoly->flag = ME_FACE_SEL;
+ /* set default flags */
+ mpoly = &mesh->mpoly[mesh->totpoly];
+ for (i = 0; i < len; i++, mpoly++)
+ mpoly->flag = ME_FACE_SEL;
- mesh->totpoly = totpoly;
+ mesh->totpoly = totpoly;
}
static void mesh_remove_verts(Mesh *mesh, int len)
{
- int totvert;
+ int totvert;
- if (len == 0)
- return;
+ if (len == 0)
+ return;
- totvert = mesh->totvert - len;
- CustomData_free_elem(&mesh->vdata, totvert, len);
+ totvert = mesh->totvert - len;
+ CustomData_free_elem(&mesh->vdata, totvert, len);
- /* set final vertex list size */
- mesh->totvert = totvert;
+ /* set final vertex list size */
+ mesh->totvert = totvert;
}
static void mesh_remove_edges(Mesh *mesh, int len)
{
- int totedge;
+ int totedge;
- if (len == 0)
- return;
+ if (len == 0)
+ return;
- totedge = mesh->totedge - len;
- CustomData_free_elem(&mesh->edata, totedge, len);
+ totedge = mesh->totedge - len;
+ CustomData_free_elem(&mesh->edata, totedge, len);
- mesh->totedge = totedge;
+ mesh->totedge = totedge;
}
static void mesh_remove_faces(Mesh *mesh, int len)
{
- int totface;
+ int totface;
- if (len == 0)
- return;
+ if (len == 0)
+ return;
- totface = mesh->totface - len; /* new face count */
- CustomData_free_elem(&mesh->fdata, totface, len);
+ totface = mesh->totface - len; /* new face count */
+ CustomData_free_elem(&mesh->fdata, totface, len);
- mesh->totface = totface;
+ mesh->totface = totface;
}
#if 0
void ED_mesh_geometry_add(Mesh *mesh, ReportList *reports, int verts, int edges, int faces)
{
- if (mesh->edit_mesh) {
- BKE_report(reports, RPT_ERROR, "Cannot add geometry in edit mode");
- return;
- }
-
- if (verts)
- mesh_add_verts(mesh, verts);
- if (edges)
- mesh_add_edges(mesh, edges);
- if (faces)
- mesh_add_faces(mesh, faces);
+ if (mesh->edit_mesh) {
+ BKE_report(reports, RPT_ERROR, "Cannot add geometry in edit mode");
+ return;
+ }
+
+ if (verts)
+ mesh_add_verts(mesh, verts);
+ if (edges)
+ mesh_add_edges(mesh, edges);
+ if (faces)
+ mesh_add_faces(mesh, faces);
}
#endif
void ED_mesh_tessfaces_add(Mesh *mesh, ReportList *reports, int count)
{
- if (mesh->edit_mesh) {
- BKE_report(reports, RPT_ERROR, "Cannot add tessfaces in edit mode");
- return;
- }
+ if (mesh->edit_mesh) {
+ BKE_report(reports, RPT_ERROR, "Cannot add tessfaces in edit mode");
+ return;
+ }
- if (mesh->mpoly) {
- BKE_report(reports, RPT_ERROR, "Cannot add tessfaces to a mesh that already has polygons");
- return;
- }
+ if (mesh->mpoly) {
+ BKE_report(reports, RPT_ERROR, "Cannot add tessfaces to a mesh that already has polygons");
+ return;
+ }
- mesh_add_tessfaces(mesh, count);
+ mesh_add_tessfaces(mesh, count);
}
void ED_mesh_edges_add(Mesh *mesh, ReportList *reports, int count)
{
- if (mesh->edit_mesh) {
- BKE_report(reports, RPT_ERROR, "Cannot add edges in edit mode");
- return;
- }
+ if (mesh->edit_mesh) {
+ BKE_report(reports, RPT_ERROR, "Cannot add edges in edit mode");
+ return;
+ }
- mesh_add_edges(mesh, count);
+ mesh_add_edges(mesh, count);
}
void ED_mesh_vertices_add(Mesh *mesh, ReportList *reports, int count)
{
- if (mesh->edit_mesh) {
- BKE_report(reports, RPT_ERROR, "Cannot add vertices in edit mode");
- return;
- }
+ if (mesh->edit_mesh) {
+ BKE_report(reports, RPT_ERROR, "Cannot add vertices in edit mode");
+ return;
+ }
- mesh_add_verts(mesh, count);
+ mesh_add_verts(mesh, count);
}
void ED_mesh_faces_remove(Mesh *mesh, ReportList *reports, int count)
{
- if (mesh->edit_mesh) {
- BKE_report(reports, RPT_ERROR, "Cannot remove faces in edit mode");
- return;
- }
- else if (count > mesh->totface) {
- BKE_report(reports, RPT_ERROR, "Cannot remove more faces than the mesh contains");
- return;
- }
-
- mesh_remove_faces(mesh, count);
+ if (mesh->edit_mesh) {
+ BKE_report(reports, RPT_ERROR, "Cannot remove faces in edit mode");
+ return;
+ }
+ else if (count > mesh->totface) {
+ BKE_report(reports, RPT_ERROR, "Cannot remove more faces than the mesh contains");
+ return;
+ }
+
+ mesh_remove_faces(mesh, count);
}
void ED_mesh_edges_remove(Mesh *mesh, ReportList *reports, int count)
{
- if (mesh->edit_mesh) {
- BKE_report(reports, RPT_ERROR, "Cannot remove edges in edit mode");
- return;
- }
- else if (count > mesh->totedge) {
- BKE_report(reports, RPT_ERROR, "Cannot remove more edges than the mesh contains");
- return;
- }
-
- mesh_remove_edges(mesh, count);
+ if (mesh->edit_mesh) {
+ BKE_report(reports, RPT_ERROR, "Cannot remove edges in edit mode");
+ return;
+ }
+ else if (count > mesh->totedge) {
+ BKE_report(reports, RPT_ERROR, "Cannot remove more edges than the mesh contains");
+ return;
+ }
+
+ mesh_remove_edges(mesh, count);
}
void ED_mesh_vertices_remove(Mesh *mesh, ReportList *reports, int count)
{
- if (mesh->edit_mesh) {
- BKE_report(reports, RPT_ERROR, "Cannot remove vertices in edit mode");
- return;
- }
- else if (count > mesh->totvert) {
- BKE_report(reports, RPT_ERROR, "Cannot remove more vertices than the mesh contains");
- return;
- }
-
- mesh_remove_verts(mesh, count);
+ if (mesh->edit_mesh) {
+ BKE_report(reports, RPT_ERROR, "Cannot remove vertices in edit mode");
+ return;
+ }
+ else if (count > mesh->totvert) {
+ BKE_report(reports, RPT_ERROR, "Cannot remove more vertices than the mesh contains");
+ return;
+ }
+
+ mesh_remove_verts(mesh, count);
}
void ED_mesh_loops_add(Mesh *mesh, ReportList *reports, int count)
{
- if (mesh->edit_mesh) {
- BKE_report(reports, RPT_ERROR, "Cannot add loops in edit mode");
- return;
- }
+ if (mesh->edit_mesh) {
+ BKE_report(reports, RPT_ERROR, "Cannot add loops in edit mode");
+ return;
+ }
- mesh_add_loops(mesh, count);
+ mesh_add_loops(mesh, count);
}
void ED_mesh_polys_add(Mesh *mesh, ReportList *reports, int count)
{
- if (mesh->edit_mesh) {
- BKE_report(reports, RPT_ERROR, "Cannot add polygons in edit mode");
- return;
- }
+ if (mesh->edit_mesh) {
+ BKE_report(reports, RPT_ERROR, "Cannot add polygons in edit mode");
+ return;
+ }
- mesh_add_polys(mesh, count);
+ mesh_add_polys(mesh, count);
}
void ED_mesh_calc_tessface(Mesh *mesh, bool free_mpoly)
{
- if (mesh->edit_mesh) {
- BKE_editmesh_tessface_calc(mesh->edit_mesh);
- }
- else {
- BKE_mesh_tessface_calc(mesh);
- }
- if (free_mpoly) {
- CustomData_free(&mesh->ldata, mesh->totloop);
- CustomData_free(&mesh->pdata, mesh->totpoly);
- mesh->totloop = 0;
- mesh->totpoly = 0;
- mesh->mloop = NULL;
- mesh->mloopcol = NULL;
- mesh->mloopuv = NULL;
- mesh->mpoly = NULL;
- }
+ if (mesh->edit_mesh) {
+ BKE_editmesh_tessface_calc(mesh->edit_mesh);
+ }
+ else {
+ BKE_mesh_tessface_calc(mesh);
+ }
+ if (free_mpoly) {
+ CustomData_free(&mesh->ldata, mesh->totloop);
+ CustomData_free(&mesh->pdata, mesh->totpoly);
+ mesh->totloop = 0;
+ mesh->totpoly = 0;
+ mesh->mloop = NULL;
+ mesh->mloopcol = NULL;
+ mesh->mloopuv = NULL;
+ mesh->mpoly = NULL;
+ }
}
-void ED_mesh_report_mirror_ex(wmOperator *op, int totmirr, int totfail,
- char selectmode)
+void ED_mesh_report_mirror_ex(wmOperator *op, int totmirr, int totfail, char selectmode)
{
- const char *elem_type;
-
- if (selectmode & SCE_SELECT_VERTEX) {
- elem_type = "vertices";
- }
- else if (selectmode & SCE_SELECT_EDGE) {
- elem_type = "edges";
- }
- else {
- elem_type = "faces";
- }
-
- if (totfail) {
- BKE_reportf(op->reports, RPT_WARNING, "%d %s mirrored, %d failed", totmirr, elem_type, totfail);
- }
- else {
- BKE_reportf(op->reports, RPT_INFO, "%d %s mirrored", totmirr, elem_type);
- }
+ const char *elem_type;
+
+ if (selectmode & SCE_SELECT_VERTEX) {
+ elem_type = "vertices";
+ }
+ else if (selectmode & SCE_SELECT_EDGE) {
+ elem_type = "edges";
+ }
+ else {
+ elem_type = "faces";
+ }
+
+ if (totfail) {
+ BKE_reportf(
+ op->reports, RPT_WARNING, "%d %s mirrored, %d failed", totmirr, elem_type, totfail);
+ }
+ else {
+ BKE_reportf(op->reports, RPT_INFO, "%d %s mirrored", totmirr, elem_type);
+ }
}
void ED_mesh_report_mirror(wmOperator *op, int totmirr, int totfail)
{
- ED_mesh_report_mirror_ex(op, totmirr, totfail, SCE_SELECT_VERTEX);
+ ED_mesh_report_mirror_ex(op, totmirr, totfail, SCE_SELECT_VERTEX);
}
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 06499ace422..1a03879ed17 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -46,9 +46,12 @@ struct wmOperatorType;
/* Calls a bmesh op, reporting errors to the user, etc */
bool EDBM_op_callf(struct BMEditMesh *em, struct wmOperator *op, const char *fmt, ...);
-bool EDBM_op_call_and_selectf(struct BMEditMesh *em, struct wmOperator *op,
- const char *select_slot, const bool select_replace,
- const char *fmt, ...);
+bool EDBM_op_call_and_selectf(struct BMEditMesh *em,
+ struct wmOperator *op,
+ const char *select_slot,
+ const bool select_replace,
+ const char *fmt,
+ ...);
/* Same as above, but doesn't report errors.*/
bool EDBM_op_call_silentf(struct BMEditMesh *em, const char *fmt, ...);
@@ -57,20 +60,23 @@ bool EDBM_op_call_silentf(struct BMEditMesh *em, const char *fmt, ...);
* it.
*
* execute the operator with BM_Exec_Op */
-bool EDBM_op_init(struct BMEditMesh *em, struct BMOperator *bmop,
- struct wmOperator *op, const char *fmt, ...);
+bool EDBM_op_init(
+ struct BMEditMesh *em, struct BMOperator *bmop, struct wmOperator *op, const char *fmt, ...);
/* Cleans up after a bmesh operator */
-bool EDBM_op_finish(struct BMEditMesh *em, struct BMOperator *bmop,
- struct wmOperator *op, const bool do_report);
+bool EDBM_op_finish(struct BMEditMesh *em,
+ struct BMOperator *bmop,
+ struct wmOperator *op,
+ const bool do_report);
void EDBM_stats_update(struct BMEditMesh *em);
bool EDBM_view3d_poll(struct bContext *C);
-struct BMElem *EDBM_elem_from_selectmode(
- struct BMEditMesh *em,
- struct BMVert *eve, struct BMEdge *eed, struct BMFace *efa);
-int EDBM_elem_to_index_any(struct BMEditMesh *em, struct BMElem *ele);
+struct BMElem *EDBM_elem_from_selectmode(struct BMEditMesh *em,
+ struct BMVert *eve,
+ struct BMEdge *eed,
+ struct BMFace *efa);
+int EDBM_elem_to_index_any(struct BMEditMesh *em, struct BMElem *ele);
struct BMElem *EDBM_elem_from_index_any(struct BMEditMesh *em, int index);
/* *** editmesh_add.c *** */
@@ -125,25 +131,20 @@ void MESH_OT_intersect(struct wmOperatorType *ot);
void MESH_OT_intersect_boolean(struct wmOperatorType *ot);
void MESH_OT_face_split_by_edges(struct wmOperatorType *ot);
-
/* *** editmesh_knife.c *** */
void MESH_OT_knife_tool(struct wmOperatorType *ot);
void MESH_OT_knife_project(struct wmOperatorType *ot);
-void EDBM_mesh_knife(struct bContext *C, struct LinkNode *polys,
- bool use_tag, bool cut_through);
+void EDBM_mesh_knife(struct bContext *C, struct LinkNode *polys, bool use_tag, bool cut_through);
struct wmKeyMap *knifetool_modal_keymap(struct wmKeyConfig *keyconf);
-
/* *** editmesh_loopcut.c *** */
void MESH_OT_loopcut(struct wmOperatorType *ot);
-
/* *** editmesh_rip.c *** */
void MESH_OT_rip(struct wmOperatorType *ot);
void MESH_OT_rip_edge(struct wmOperatorType *ot);
-
/* *** editmesh_select.c *** */
void MESH_OT_select_similar(struct wmOperatorType *ot);
void MESH_OT_select_similar_region(struct wmOperatorType *ot);
@@ -174,7 +175,6 @@ void MESH_OT_shortest_path_select(struct wmOperatorType *ot);
extern struct EnumPropertyItem *corner_type_items;
-
/* *** editmesh_tools.c *** */
void MESH_OT_subdivide(struct wmOperatorType *ot);
void MESH_OT_subdivide_edgering(struct wmOperatorType *ot);
@@ -263,5 +263,4 @@ void MESH_OT_customdata_skin_clear(struct wmOperatorType *ot);
void MESH_OT_customdata_custom_splitnormals_add(struct wmOperatorType *ot);
void MESH_OT_customdata_custom_splitnormals_clear(struct wmOperatorType *ot);
-
-#endif /* __MESH_INTERN_H__ */
+#endif /* __MESH_INTERN_H__ */
diff --git a/source/blender/editors/mesh/mesh_mirror.c b/source/blender/editors/mesh/mesh_mirror.c
index 8bfe51d09fa..7d0ee19b5ea 100644
--- a/source/blender/editors/mesh/mesh_mirror.c
+++ b/source/blender/editors/mesh/mesh_mirror.c
@@ -38,74 +38,77 @@
/** \name Mesh Spatial Mirror API
* \{ */
-#define KD_THRESH 0.00002f
+#define KD_THRESH 0.00002f
-static struct { void *tree; } MirrKdStore = {NULL};
+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)
+int ED_mesh_mirror_spatial_table(
+ Object *ob, BMEditMesh *em, Mesh *me_eval, const float co[3], char mode)
{
- 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);
-
- if (i != -1) {
- if (nearest.dist < KD_THRESH) {
- return i;
- }
- }
- }
- return -1;
- }
- 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);
-
- 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);
-
- 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;
-
- for (i = 0; i < totvert; i++, mvert++) {
- BLI_kdtree_3d_insert(MirrKdStore.tree, i, mvert->co);
- }
- }
-
- BLI_kdtree_3d_balance(MirrKdStore.tree);
- }
- else if (mode == 'e') { /* end table */
- if (MirrKdStore.tree) {
- BLI_kdtree_3d_free(MirrKdStore.tree);
- MirrKdStore.tree = NULL;
- }
- }
- else {
- BLI_assert(0);
- }
-
- return 0;
+ 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);
+
+ if (i != -1) {
+ if (nearest.dist < KD_THRESH) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+ 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);
+
+ 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);
+
+ 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;
+
+ for (i = 0; i < totvert; i++, mvert++) {
+ BLI_kdtree_3d_insert(MirrKdStore.tree, i, mvert->co);
+ }
+ }
+
+ BLI_kdtree_3d_balance(MirrKdStore.tree);
+ }
+ else if (mode == 'e') { /* end table */
+ if (MirrKdStore.tree) {
+ BLI_kdtree_3d_free(MirrKdStore.tree);
+ MirrKdStore.tree = NULL;
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ return 0;
}
/** \} */
@@ -117,256 +120,258 @@ int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, Mesh *me_eval, cons
typedef unsigned int MirrTopoHash_t;
typedef struct MirrTopoVert_t {
- MirrTopoHash_t hash;
- int v_index;
+ MirrTopoHash_t hash;
+ int v_index;
} MirrTopoVert_t;
static int mirrtopo_hash_sort(const void *l1, const void *l2)
{
- if ((MirrTopoHash_t)(intptr_t)l1 > (MirrTopoHash_t)(intptr_t)l2) return 1;
- else if ((MirrTopoHash_t)(intptr_t)l1 < (MirrTopoHash_t)(intptr_t)l2) return -1;
- return 0;
+ if ((MirrTopoHash_t)(intptr_t)l1 > (MirrTopoHash_t)(intptr_t)l2)
+ return 1;
+ else if ((MirrTopoHash_t)(intptr_t)l1 < (MirrTopoHash_t)(intptr_t)l2)
+ return -1;
+ return 0;
}
static int mirrtopo_vert_sort(const void *v1, const void *v2)
{
- if (((MirrTopoVert_t *)v1)->hash > ((MirrTopoVert_t *)v2)->hash) return 1;
- else if (((MirrTopoVert_t *)v1)->hash < ((MirrTopoVert_t *)v2)->hash) return -1;
- return 0;
+ if (((MirrTopoVert_t *)v1)->hash > ((MirrTopoVert_t *)v2)->hash)
+ return 1;
+ else if (((MirrTopoVert_t *)v1)->hash < ((MirrTopoVert_t *)v2)->hash)
+ return -1;
+ return 0;
}
bool ED_mesh_mirrtopo_recalc_check(Mesh *me, Mesh *me_eval, MirrTopoStore_t *mesh_topo_store)
{
- const bool is_editmode = (me->edit_mesh != NULL);
- int totvert;
- int totedge;
-
- if (me_eval) {
- totvert = me_eval->totvert;
- totedge = me_eval->totedge;
- }
- else if (me->edit_mesh) {
- totvert = me->edit_mesh->bm->totvert;
- totedge = me->edit_mesh->bm->totedge;
- }
- else {
- totvert = me->totvert;
- totedge = me->totedge;
- }
-
- if ((mesh_topo_store->index_lookup == NULL) ||
- (mesh_topo_store->prev_is_editmode != is_editmode) ||
- (totvert != mesh_topo_store->prev_vert_tot) ||
- (totedge != mesh_topo_store->prev_edge_tot))
- {
- return true;
- }
- else {
- return false;
- }
-
+ const bool is_editmode = (me->edit_mesh != NULL);
+ int totvert;
+ int totedge;
+
+ if (me_eval) {
+ totvert = me_eval->totvert;
+ totedge = me_eval->totedge;
+ }
+ else if (me->edit_mesh) {
+ totvert = me->edit_mesh->bm->totvert;
+ totedge = me->edit_mesh->bm->totedge;
+ }
+ else {
+ totvert = me->totvert;
+ totedge = me->totedge;
+ }
+
+ if ((mesh_topo_store->index_lookup == NULL) ||
+ (mesh_topo_store->prev_is_editmode != is_editmode) ||
+ (totvert != mesh_topo_store->prev_vert_tot) || (totedge != mesh_topo_store->prev_edge_tot)) {
+ return true;
+ }
+ else {
+ return false;
+ }
}
-void ED_mesh_mirrtopo_init(
- Mesh *me, Mesh *me_eval, MirrTopoStore_t *mesh_topo_store,
- const bool skip_em_vert_array_init)
+void ED_mesh_mirrtopo_init(Mesh *me,
+ Mesh *me_eval,
+ MirrTopoStore_t *mesh_topo_store,
+ const bool skip_em_vert_array_init)
{
- const bool is_editmode = (me->edit_mesh != NULL);
- MEdge *medge = NULL, *med;
- BMEditMesh *em = me_eval ? NULL : me->edit_mesh;
-
- /* editmode*/
- BMEdge *eed;
- BMIter iter;
-
- int a, last;
- int totvert, totedge;
- int tot_unique = -1, tot_unique_prev = -1;
- int tot_unique_edges = 0, tot_unique_edges_prev;
-
- MirrTopoHash_t *topo_hash = NULL;
- MirrTopoHash_t *topo_hash_prev = NULL;
- MirrTopoVert_t *topo_pairs;
- MirrTopoHash_t topo_pass = 1;
-
- intptr_t *index_lookup; /* direct access to mesh_topo_store->index_lookup */
-
- /* reallocate if needed */
- ED_mesh_mirrtopo_free(mesh_topo_store);
-
- mesh_topo_store->prev_is_editmode = is_editmode;
-
- if (em) {
- BM_mesh_elem_index_ensure(em->bm, BM_VERT);
-
- totvert = em->bm->totvert;
- }
- else {
- totvert = me_eval ? me_eval->totvert : me->totvert;
- }
-
- topo_hash = MEM_callocN(totvert * sizeof(MirrTopoHash_t), "TopoMirr");
-
- /* Initialize the vert-edge-user counts used to detect unique topology */
- if (em) {
- totedge = me->edit_mesh->bm->totedge;
-
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- const int i1 = BM_elem_index_get(eed->v1), i2 = BM_elem_index_get(eed->v2);
- topo_hash[i1]++;
- topo_hash[i2]++;
- }
- }
- else {
- totedge = me_eval ? me_eval->totedge : me->totedge;
- medge = me_eval ? me_eval->medge : me->medge;
-
- for (a = 0, med = medge; a < totedge; a++, med++) {
- const unsigned int i1 = med->v1, i2 = med->v2;
- topo_hash[i1]++;
- topo_hash[i2]++;
- }
- }
-
- topo_hash_prev = MEM_dupallocN(topo_hash);
-
- tot_unique_prev = -1;
- tot_unique_edges_prev = -1;
- while (1) {
- /* use the number of edges per vert to give verts unique topology IDs */
-
- tot_unique_edges = 0;
-
- /* This can make really big numbers, wrapping around here is fine */
- if (em) {
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- const int i1 = BM_elem_index_get(eed->v1), i2 = BM_elem_index_get(eed->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]);
- }
- }
- else {
- for (a = 0, med = medge; a < totedge; a++, med++) {
- const unsigned int 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]);
- }
- }
- memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert);
-
- /* sort so we can count unique values */
- qsort(topo_hash_prev, totvert, sizeof(MirrTopoHash_t), mirrtopo_hash_sort);
-
- tot_unique = 1; /* account for skipping the first value */
- for (a = 1; a < totvert; a++) {
- if (topo_hash_prev[a - 1] != topo_hash_prev[a]) {
- tot_unique++;
- }
- }
-
- if ((tot_unique <= tot_unique_prev) && (tot_unique_edges <= tot_unique_edges_prev)) {
- /* Finish searching for unique values when 1 loop dosn't give a
- * higher number of unique values compared to the previous loop. */
- break;
- }
- else {
- tot_unique_prev = tot_unique;
- tot_unique_edges_prev = tot_unique_edges;
- }
- /* Copy the hash calculated this iteration, so we can use them next time */
- memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert);
-
- topo_pass++;
- }
-
- /* Hash/Index pairs are needed for sorting to find index pairs */
- topo_pairs = MEM_callocN(sizeof(MirrTopoVert_t) * totvert, "MirrTopoPairs");
-
- /* since we are looping through verts, initialize these values here too */
- index_lookup = MEM_mallocN(totvert * sizeof(*index_lookup), "mesh_topo_lookup");
-
- if (em) {
- if (skip_em_vert_array_init == false) {
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
- }
- }
-
- for (a = 0; a < totvert; a++) {
- topo_pairs[a].hash = topo_hash[a];
- topo_pairs[a].v_index = a;
-
- /* initialize lookup */
- index_lookup[a] = -1;
- }
-
- qsort(topo_pairs, totvert, sizeof(MirrTopoVert_t), mirrtopo_vert_sort);
-
- last = 0;
-
- /* Get the pairs out of the sorted hashes, note, totvert+1 means we can use the previous 2,
- * but you cant ever access the last 'a' index of MirrTopoPairs */
- if (em) {
- BMVert **vtable = em->bm->vtable;
- for (a = 1; a <= totvert; a++) {
- // printf("I %d %ld %d\n",
- // (a - last), MirrTopoPairs[a].hash, MirrTopoPairs[a].v_indexs);
- if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) {
- const int match_count = a - last;
- if (match_count == 2) {
- const int j = topo_pairs[a - 1].v_index, k = topo_pairs[a - 2].v_index;
- index_lookup[j] = (intptr_t)vtable[k];
- index_lookup[k] = (intptr_t)vtable[j];
- }
- else if (match_count == 1) {
- /* Center vertex. */
- const int j = topo_pairs[a - 1].v_index;
- index_lookup[j] = (intptr_t)vtable[j];
- }
- last = a;
- }
- }
- }
- else {
- /* same as above, for mesh */
- for (a = 1; a <= totvert; a++) {
- if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) {
- const int match_count = a - last;
- if (match_count == 2) {
- const int j = topo_pairs[a - 1].v_index, k = topo_pairs[a - 2].v_index;
- index_lookup[j] = k;
- index_lookup[k] = j;
- }
- else if (match_count == 1) {
- /* Center vertex. */
- const int j = topo_pairs[a - 1].v_index;
- index_lookup[j] = j;
- }
- last = a;
- }
- }
- }
-
- MEM_freeN(topo_pairs);
- topo_pairs = NULL;
-
- MEM_freeN(topo_hash);
- MEM_freeN(topo_hash_prev);
-
- mesh_topo_store->index_lookup = index_lookup;
- mesh_topo_store->prev_vert_tot = totvert;
- mesh_topo_store->prev_edge_tot = totedge;
+ const bool is_editmode = (me->edit_mesh != NULL);
+ MEdge *medge = NULL, *med;
+ BMEditMesh *em = me_eval ? NULL : me->edit_mesh;
+
+ /* editmode*/
+ BMEdge *eed;
+ BMIter iter;
+
+ int a, last;
+ int totvert, totedge;
+ int tot_unique = -1, tot_unique_prev = -1;
+ int tot_unique_edges = 0, tot_unique_edges_prev;
+
+ MirrTopoHash_t *topo_hash = NULL;
+ MirrTopoHash_t *topo_hash_prev = NULL;
+ MirrTopoVert_t *topo_pairs;
+ MirrTopoHash_t topo_pass = 1;
+
+ intptr_t *index_lookup; /* direct access to mesh_topo_store->index_lookup */
+
+ /* reallocate if needed */
+ ED_mesh_mirrtopo_free(mesh_topo_store);
+
+ mesh_topo_store->prev_is_editmode = is_editmode;
+
+ if (em) {
+ BM_mesh_elem_index_ensure(em->bm, BM_VERT);
+
+ totvert = em->bm->totvert;
+ }
+ else {
+ totvert = me_eval ? me_eval->totvert : me->totvert;
+ }
+
+ topo_hash = MEM_callocN(totvert * sizeof(MirrTopoHash_t), "TopoMirr");
+
+ /* Initialize the vert-edge-user counts used to detect unique topology */
+ if (em) {
+ totedge = me->edit_mesh->bm->totedge;
+
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ const int i1 = BM_elem_index_get(eed->v1), i2 = BM_elem_index_get(eed->v2);
+ topo_hash[i1]++;
+ topo_hash[i2]++;
+ }
+ }
+ else {
+ totedge = me_eval ? me_eval->totedge : me->totedge;
+ medge = me_eval ? me_eval->medge : me->medge;
+
+ for (a = 0, med = medge; a < totedge; a++, med++) {
+ const unsigned int i1 = med->v1, i2 = med->v2;
+ topo_hash[i1]++;
+ topo_hash[i2]++;
+ }
+ }
+
+ topo_hash_prev = MEM_dupallocN(topo_hash);
+
+ tot_unique_prev = -1;
+ tot_unique_edges_prev = -1;
+ while (1) {
+ /* use the number of edges per vert to give verts unique topology IDs */
+
+ tot_unique_edges = 0;
+
+ /* This can make really big numbers, wrapping around here is fine */
+ if (em) {
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ const int i1 = BM_elem_index_get(eed->v1), i2 = BM_elem_index_get(eed->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]);
+ }
+ }
+ else {
+ for (a = 0, med = medge; a < totedge; a++, med++) {
+ const unsigned int 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]);
+ }
+ }
+ memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert);
+
+ /* sort so we can count unique values */
+ qsort(topo_hash_prev, totvert, sizeof(MirrTopoHash_t), mirrtopo_hash_sort);
+
+ tot_unique = 1; /* account for skipping the first value */
+ for (a = 1; a < totvert; a++) {
+ if (topo_hash_prev[a - 1] != topo_hash_prev[a]) {
+ tot_unique++;
+ }
+ }
+
+ if ((tot_unique <= tot_unique_prev) && (tot_unique_edges <= tot_unique_edges_prev)) {
+ /* Finish searching for unique values when 1 loop dosn't give a
+ * higher number of unique values compared to the previous loop. */
+ break;
+ }
+ else {
+ tot_unique_prev = tot_unique;
+ tot_unique_edges_prev = tot_unique_edges;
+ }
+ /* Copy the hash calculated this iteration, so we can use them next time */
+ memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert);
+
+ topo_pass++;
+ }
+
+ /* Hash/Index pairs are needed for sorting to find index pairs */
+ topo_pairs = MEM_callocN(sizeof(MirrTopoVert_t) * totvert, "MirrTopoPairs");
+
+ /* since we are looping through verts, initialize these values here too */
+ index_lookup = MEM_mallocN(totvert * sizeof(*index_lookup), "mesh_topo_lookup");
+
+ if (em) {
+ if (skip_em_vert_array_init == false) {
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ }
+ }
+
+ for (a = 0; a < totvert; a++) {
+ topo_pairs[a].hash = topo_hash[a];
+ topo_pairs[a].v_index = a;
+
+ /* initialize lookup */
+ index_lookup[a] = -1;
+ }
+
+ qsort(topo_pairs, totvert, sizeof(MirrTopoVert_t), mirrtopo_vert_sort);
+
+ last = 0;
+
+ /* Get the pairs out of the sorted hashes, note, totvert+1 means we can use the previous 2,
+ * but you cant ever access the last 'a' index of MirrTopoPairs */
+ if (em) {
+ BMVert **vtable = em->bm->vtable;
+ for (a = 1; a <= totvert; a++) {
+ // printf("I %d %ld %d\n",
+ // (a - last), MirrTopoPairs[a].hash, MirrTopoPairs[a].v_indexs);
+ if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) {
+ const int match_count = a - last;
+ if (match_count == 2) {
+ const int j = topo_pairs[a - 1].v_index, k = topo_pairs[a - 2].v_index;
+ index_lookup[j] = (intptr_t)vtable[k];
+ index_lookup[k] = (intptr_t)vtable[j];
+ }
+ else if (match_count == 1) {
+ /* Center vertex. */
+ const int j = topo_pairs[a - 1].v_index;
+ index_lookup[j] = (intptr_t)vtable[j];
+ }
+ last = a;
+ }
+ }
+ }
+ else {
+ /* same as above, for mesh */
+ for (a = 1; a <= totvert; a++) {
+ if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) {
+ const int match_count = a - last;
+ if (match_count == 2) {
+ const int j = topo_pairs[a - 1].v_index, k = topo_pairs[a - 2].v_index;
+ index_lookup[j] = k;
+ index_lookup[k] = j;
+ }
+ else if (match_count == 1) {
+ /* Center vertex. */
+ const int j = topo_pairs[a - 1].v_index;
+ index_lookup[j] = j;
+ }
+ last = a;
+ }
+ }
+ }
+
+ MEM_freeN(topo_pairs);
+ topo_pairs = NULL;
+
+ MEM_freeN(topo_hash);
+ MEM_freeN(topo_hash_prev);
+
+ mesh_topo_store->index_lookup = index_lookup;
+ mesh_topo_store->prev_vert_tot = totvert;
+ mesh_topo_store->prev_edge_tot = totedge;
}
void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store)
{
- if (mesh_topo_store->index_lookup) {
- MEM_freeN(mesh_topo_store->index_lookup);
- }
- mesh_topo_store->index_lookup = NULL;
- mesh_topo_store->prev_vert_tot = -1;
- mesh_topo_store->prev_edge_tot = -1;
+ if (mesh_topo_store->index_lookup) {
+ MEM_freeN(mesh_topo_store->index_lookup);
+ }
+ mesh_topo_store->index_lookup = NULL;
+ mesh_topo_store->prev_vert_tot = -1;
+ mesh_topo_store->prev_edge_tot = -1;
}
/** \} */
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 46837889489..8a51b9ba54e 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -34,292 +34,315 @@
#include "ED_screen.h"
#include "ED_select_utils.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
/**************************** registration **********************************/
void ED_operatortypes_mesh(void)
{
- WM_operatortype_append(MESH_OT_select_all);
- WM_operatortype_append(MESH_OT_select_interior_faces);
- WM_operatortype_append(MESH_OT_select_more);
- WM_operatortype_append(MESH_OT_select_less);
- WM_operatortype_append(MESH_OT_select_non_manifold);
- WM_operatortype_append(MESH_OT_select_linked);
- WM_operatortype_append(MESH_OT_select_linked_pick);
- WM_operatortype_append(MESH_OT_select_random);
- WM_operatortype_append(MESH_OT_select_ungrouped);
- WM_operatortype_append(MESH_OT_hide);
- WM_operatortype_append(MESH_OT_reveal);
- WM_operatortype_append(MESH_OT_select_face_by_sides);
- WM_operatortype_append(MESH_OT_select_loose);
- WM_operatortype_append(MESH_OT_select_mirror);
- WM_operatortype_append(MESH_OT_normals_make_consistent);
- WM_operatortype_append(MESH_OT_merge);
- WM_operatortype_append(MESH_OT_subdivide);
- WM_operatortype_append(MESH_OT_subdivide_edgering);
- WM_operatortype_append(MESH_OT_unsubdivide);
- WM_operatortype_append(MESH_OT_faces_select_linked_flat);
- WM_operatortype_append(MESH_OT_edges_select_sharp);
- WM_operatortype_append(MESH_OT_primitive_plane_add);
- WM_operatortype_append(MESH_OT_primitive_cube_add);
- WM_operatortype_append(MESH_OT_primitive_circle_add);
- WM_operatortype_append(MESH_OT_primitive_cylinder_add);
- WM_operatortype_append(MESH_OT_primitive_cone_add);
- WM_operatortype_append(MESH_OT_primitive_grid_add);
- WM_operatortype_append(MESH_OT_primitive_monkey_add);
- WM_operatortype_append(MESH_OT_primitive_uv_sphere_add);
- WM_operatortype_append(MESH_OT_primitive_ico_sphere_add);
-
- WM_operatortype_append(MESH_OT_primitive_cube_add_gizmo);
-
- WM_operatortype_append(MESH_OT_duplicate);
- WM_operatortype_append(MESH_OT_remove_doubles);
- WM_operatortype_append(MESH_OT_spin);
- WM_operatortype_append(MESH_OT_screw);
-
- WM_operatortype_append(MESH_OT_extrude_region);
- WM_operatortype_append(MESH_OT_extrude_context);
- WM_operatortype_append(MESH_OT_extrude_faces_indiv);
- WM_operatortype_append(MESH_OT_extrude_edges_indiv);
- WM_operatortype_append(MESH_OT_extrude_verts_indiv);
-
- WM_operatortype_append(MESH_OT_split);
- WM_operatortype_append(MESH_OT_extrude_repeat);
- WM_operatortype_append(MESH_OT_edge_rotate);
- WM_operatortype_append(MESH_OT_shortest_path_select);
- WM_operatortype_append(MESH_OT_loop_to_region);
- WM_operatortype_append(MESH_OT_region_to_loop);
- WM_operatortype_append(MESH_OT_select_axis);
-
- WM_operatortype_append(MESH_OT_uvs_rotate);
- WM_operatortype_append(MESH_OT_uvs_reverse);
- WM_operatortype_append(MESH_OT_colors_rotate);
- WM_operatortype_append(MESH_OT_colors_reverse);
-
- WM_operatortype_append(MESH_OT_fill);
- WM_operatortype_append(MESH_OT_fill_grid);
- WM_operatortype_append(MESH_OT_fill_holes);
- WM_operatortype_append(MESH_OT_beautify_fill);
- WM_operatortype_append(MESH_OT_quads_convert_to_tris);
- WM_operatortype_append(MESH_OT_tris_convert_to_quads);
- WM_operatortype_append(MESH_OT_decimate);
- WM_operatortype_append(MESH_OT_dissolve_verts);
- WM_operatortype_append(MESH_OT_dissolve_edges);
- WM_operatortype_append(MESH_OT_dissolve_faces);
- WM_operatortype_append(MESH_OT_dissolve_mode);
- WM_operatortype_append(MESH_OT_dissolve_limited);
- WM_operatortype_append(MESH_OT_dissolve_degenerate);
- WM_operatortype_append(MESH_OT_delete_edgeloop);
- WM_operatortype_append(MESH_OT_faces_shade_smooth);
- WM_operatortype_append(MESH_OT_faces_shade_flat);
- WM_operatortype_append(MESH_OT_sort_elements);
+ WM_operatortype_append(MESH_OT_select_all);
+ WM_operatortype_append(MESH_OT_select_interior_faces);
+ WM_operatortype_append(MESH_OT_select_more);
+ WM_operatortype_append(MESH_OT_select_less);
+ WM_operatortype_append(MESH_OT_select_non_manifold);
+ WM_operatortype_append(MESH_OT_select_linked);
+ WM_operatortype_append(MESH_OT_select_linked_pick);
+ WM_operatortype_append(MESH_OT_select_random);
+ WM_operatortype_append(MESH_OT_select_ungrouped);
+ WM_operatortype_append(MESH_OT_hide);
+ WM_operatortype_append(MESH_OT_reveal);
+ WM_operatortype_append(MESH_OT_select_face_by_sides);
+ WM_operatortype_append(MESH_OT_select_loose);
+ WM_operatortype_append(MESH_OT_select_mirror);
+ WM_operatortype_append(MESH_OT_normals_make_consistent);
+ WM_operatortype_append(MESH_OT_merge);
+ WM_operatortype_append(MESH_OT_subdivide);
+ WM_operatortype_append(MESH_OT_subdivide_edgering);
+ WM_operatortype_append(MESH_OT_unsubdivide);
+ WM_operatortype_append(MESH_OT_faces_select_linked_flat);
+ WM_operatortype_append(MESH_OT_edges_select_sharp);
+ WM_operatortype_append(MESH_OT_primitive_plane_add);
+ WM_operatortype_append(MESH_OT_primitive_cube_add);
+ WM_operatortype_append(MESH_OT_primitive_circle_add);
+ WM_operatortype_append(MESH_OT_primitive_cylinder_add);
+ WM_operatortype_append(MESH_OT_primitive_cone_add);
+ WM_operatortype_append(MESH_OT_primitive_grid_add);
+ WM_operatortype_append(MESH_OT_primitive_monkey_add);
+ WM_operatortype_append(MESH_OT_primitive_uv_sphere_add);
+ WM_operatortype_append(MESH_OT_primitive_ico_sphere_add);
+
+ WM_operatortype_append(MESH_OT_primitive_cube_add_gizmo);
+
+ WM_operatortype_append(MESH_OT_duplicate);
+ WM_operatortype_append(MESH_OT_remove_doubles);
+ WM_operatortype_append(MESH_OT_spin);
+ WM_operatortype_append(MESH_OT_screw);
+
+ WM_operatortype_append(MESH_OT_extrude_region);
+ WM_operatortype_append(MESH_OT_extrude_context);
+ WM_operatortype_append(MESH_OT_extrude_faces_indiv);
+ WM_operatortype_append(MESH_OT_extrude_edges_indiv);
+ WM_operatortype_append(MESH_OT_extrude_verts_indiv);
+
+ WM_operatortype_append(MESH_OT_split);
+ WM_operatortype_append(MESH_OT_extrude_repeat);
+ WM_operatortype_append(MESH_OT_edge_rotate);
+ WM_operatortype_append(MESH_OT_shortest_path_select);
+ WM_operatortype_append(MESH_OT_loop_to_region);
+ WM_operatortype_append(MESH_OT_region_to_loop);
+ WM_operatortype_append(MESH_OT_select_axis);
+
+ WM_operatortype_append(MESH_OT_uvs_rotate);
+ WM_operatortype_append(MESH_OT_uvs_reverse);
+ WM_operatortype_append(MESH_OT_colors_rotate);
+ WM_operatortype_append(MESH_OT_colors_reverse);
+
+ WM_operatortype_append(MESH_OT_fill);
+ WM_operatortype_append(MESH_OT_fill_grid);
+ WM_operatortype_append(MESH_OT_fill_holes);
+ WM_operatortype_append(MESH_OT_beautify_fill);
+ WM_operatortype_append(MESH_OT_quads_convert_to_tris);
+ WM_operatortype_append(MESH_OT_tris_convert_to_quads);
+ WM_operatortype_append(MESH_OT_decimate);
+ WM_operatortype_append(MESH_OT_dissolve_verts);
+ WM_operatortype_append(MESH_OT_dissolve_edges);
+ WM_operatortype_append(MESH_OT_dissolve_faces);
+ WM_operatortype_append(MESH_OT_dissolve_mode);
+ WM_operatortype_append(MESH_OT_dissolve_limited);
+ WM_operatortype_append(MESH_OT_dissolve_degenerate);
+ WM_operatortype_append(MESH_OT_delete_edgeloop);
+ WM_operatortype_append(MESH_OT_faces_shade_smooth);
+ WM_operatortype_append(MESH_OT_faces_shade_flat);
+ WM_operatortype_append(MESH_OT_sort_elements);
#ifdef WITH_FREESTYLE
- WM_operatortype_append(MESH_OT_mark_freestyle_face);
+ WM_operatortype_append(MESH_OT_mark_freestyle_face);
#endif
- WM_operatortype_append(MESH_OT_delete);
- WM_operatortype_append(MESH_OT_delete_loose);
- WM_operatortype_append(MESH_OT_edge_collapse);
-
- WM_operatortype_append(MESH_OT_separate);
- WM_operatortype_append(MESH_OT_dupli_extrude_cursor);
- WM_operatortype_append(MESH_OT_loop_select);
- WM_operatortype_append(MESH_OT_edge_face_add);
- WM_operatortype_append(MESH_OT_shortest_path_pick);
- WM_operatortype_append(MESH_OT_select_similar);
- WM_operatortype_append(MESH_OT_select_similar_region);
- WM_operatortype_append(MESH_OT_select_mode);
- WM_operatortype_append(MESH_OT_loop_multi_select);
- WM_operatortype_append(MESH_OT_mark_seam);
- WM_operatortype_append(MESH_OT_mark_sharp);
+ WM_operatortype_append(MESH_OT_delete);
+ WM_operatortype_append(MESH_OT_delete_loose);
+ WM_operatortype_append(MESH_OT_edge_collapse);
+
+ WM_operatortype_append(MESH_OT_separate);
+ WM_operatortype_append(MESH_OT_dupli_extrude_cursor);
+ WM_operatortype_append(MESH_OT_loop_select);
+ WM_operatortype_append(MESH_OT_edge_face_add);
+ WM_operatortype_append(MESH_OT_shortest_path_pick);
+ WM_operatortype_append(MESH_OT_select_similar);
+ WM_operatortype_append(MESH_OT_select_similar_region);
+ WM_operatortype_append(MESH_OT_select_mode);
+ WM_operatortype_append(MESH_OT_loop_multi_select);
+ WM_operatortype_append(MESH_OT_mark_seam);
+ WM_operatortype_append(MESH_OT_mark_sharp);
#ifdef WITH_FREESTYLE
- WM_operatortype_append(MESH_OT_mark_freestyle_edge);
+ WM_operatortype_append(MESH_OT_mark_freestyle_edge);
#endif
- WM_operatortype_append(MESH_OT_vertices_smooth);
- WM_operatortype_append(MESH_OT_vertices_smooth_laplacian);
- WM_operatortype_append(MESH_OT_flip_normals);
- WM_operatortype_append(MESH_OT_rip);
- WM_operatortype_append(MESH_OT_rip_edge);
- WM_operatortype_append(MESH_OT_blend_from_shape);
- WM_operatortype_append(MESH_OT_shape_propagate_to_all);
-
- /* editmesh_polybuild */
- WM_operatortype_append(MESH_OT_polybuild_face_at_cursor);
- WM_operatortype_append(MESH_OT_polybuild_split_at_cursor);
- WM_operatortype_append(MESH_OT_polybuild_dissolve_at_cursor);
-
- WM_operatortype_append(MESH_OT_uv_texture_add);
- WM_operatortype_append(MESH_OT_uv_texture_remove);
- WM_operatortype_append(MESH_OT_vertex_color_add);
- WM_operatortype_append(MESH_OT_vertex_color_remove);
- WM_operatortype_append(MESH_OT_customdata_mask_clear);
- WM_operatortype_append(MESH_OT_customdata_skin_add);
- WM_operatortype_append(MESH_OT_customdata_skin_clear);
- WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_add);
- WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_clear);
-
- WM_operatortype_append(MESH_OT_edgering_select);
- WM_operatortype_append(MESH_OT_loopcut);
-
- WM_operatortype_append(MESH_OT_solidify);
- WM_operatortype_append(MESH_OT_select_nth);
- WM_operatortype_append(MESH_OT_vert_connect);
- WM_operatortype_append(MESH_OT_vert_connect_path);
- WM_operatortype_append(MESH_OT_vert_connect_concave);
- WM_operatortype_append(MESH_OT_vert_connect_nonplanar);
- WM_operatortype_append(MESH_OT_face_make_planar);
- WM_operatortype_append(MESH_OT_knife_tool);
- WM_operatortype_append(MESH_OT_knife_project);
-
- WM_operatortype_append(MESH_OT_bevel);
-
- WM_operatortype_append(MESH_OT_bridge_edge_loops);
- WM_operatortype_append(MESH_OT_inset);
- WM_operatortype_append(MESH_OT_offset_edge_loops);
- WM_operatortype_append(MESH_OT_intersect);
- WM_operatortype_append(MESH_OT_intersect_boolean);
- WM_operatortype_append(MESH_OT_face_split_by_edges);
- WM_operatortype_append(MESH_OT_poke);
- WM_operatortype_append(MESH_OT_wireframe);
- WM_operatortype_append(MESH_OT_edge_split);
+ WM_operatortype_append(MESH_OT_vertices_smooth);
+ WM_operatortype_append(MESH_OT_vertices_smooth_laplacian);
+ WM_operatortype_append(MESH_OT_flip_normals);
+ WM_operatortype_append(MESH_OT_rip);
+ WM_operatortype_append(MESH_OT_rip_edge);
+ WM_operatortype_append(MESH_OT_blend_from_shape);
+ WM_operatortype_append(MESH_OT_shape_propagate_to_all);
+
+ /* editmesh_polybuild */
+ WM_operatortype_append(MESH_OT_polybuild_face_at_cursor);
+ WM_operatortype_append(MESH_OT_polybuild_split_at_cursor);
+ WM_operatortype_append(MESH_OT_polybuild_dissolve_at_cursor);
+
+ WM_operatortype_append(MESH_OT_uv_texture_add);
+ WM_operatortype_append(MESH_OT_uv_texture_remove);
+ WM_operatortype_append(MESH_OT_vertex_color_add);
+ WM_operatortype_append(MESH_OT_vertex_color_remove);
+ WM_operatortype_append(MESH_OT_customdata_mask_clear);
+ WM_operatortype_append(MESH_OT_customdata_skin_add);
+ WM_operatortype_append(MESH_OT_customdata_skin_clear);
+ WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_add);
+ WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_clear);
+
+ WM_operatortype_append(MESH_OT_edgering_select);
+ WM_operatortype_append(MESH_OT_loopcut);
+
+ WM_operatortype_append(MESH_OT_solidify);
+ WM_operatortype_append(MESH_OT_select_nth);
+ WM_operatortype_append(MESH_OT_vert_connect);
+ WM_operatortype_append(MESH_OT_vert_connect_path);
+ WM_operatortype_append(MESH_OT_vert_connect_concave);
+ WM_operatortype_append(MESH_OT_vert_connect_nonplanar);
+ WM_operatortype_append(MESH_OT_face_make_planar);
+ WM_operatortype_append(MESH_OT_knife_tool);
+ WM_operatortype_append(MESH_OT_knife_project);
+
+ WM_operatortype_append(MESH_OT_bevel);
+
+ WM_operatortype_append(MESH_OT_bridge_edge_loops);
+ WM_operatortype_append(MESH_OT_inset);
+ WM_operatortype_append(MESH_OT_offset_edge_loops);
+ WM_operatortype_append(MESH_OT_intersect);
+ WM_operatortype_append(MESH_OT_intersect_boolean);
+ WM_operatortype_append(MESH_OT_face_split_by_edges);
+ WM_operatortype_append(MESH_OT_poke);
+ WM_operatortype_append(MESH_OT_wireframe);
+ WM_operatortype_append(MESH_OT_edge_split);
#ifdef WITH_BULLET
- WM_operatortype_append(MESH_OT_convex_hull);
+ WM_operatortype_append(MESH_OT_convex_hull);
#endif
- WM_operatortype_append(MESH_OT_bisect);
- WM_operatortype_append(MESH_OT_symmetrize);
- WM_operatortype_append(MESH_OT_symmetry_snap);
-
- WM_operatortype_append(MESH_OT_point_normals);
- WM_operatortype_append(MESH_OT_merge_normals);
- WM_operatortype_append(MESH_OT_split_normals);
- 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_mod_weighted_strength);
+ WM_operatortype_append(MESH_OT_bisect);
+ WM_operatortype_append(MESH_OT_symmetrize);
+ WM_operatortype_append(MESH_OT_symmetry_snap);
+
+ WM_operatortype_append(MESH_OT_point_normals);
+ WM_operatortype_append(MESH_OT_merge_normals);
+ WM_operatortype_append(MESH_OT_split_normals);
+ 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_mod_weighted_strength);
}
#if 0 /* UNUSED, remove? */
static int ED_operator_editmesh_face_select(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_MESH) {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em && em->selectmode & SCE_SELECT_FACE) {
- return 1;
- }
- }
- return 0;
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_MESH) {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ if (em && em->selectmode & SCE_SELECT_FACE) {
+ return 1;
+ }
+ }
+ return 0;
}
#endif
void ED_operatormacros_mesh(void)
{
- wmOperatorType *ot;
- wmOperatorTypeMacro *otmacro;
-
- ot = WM_operatortype_append_macro("MESH_OT_loopcut_slide", "Loop Cut and Slide", "Cut mesh loop and slide it",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "MESH_OT_loopcut");
- WM_operatortype_macro_define(ot, "TRANSFORM_OT_edge_slide");
-
- ot = WM_operatortype_append_macro("MESH_OT_offset_edge_loops_slide", "Offset Edge Slide", "Offset edge loop slide",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "MESH_OT_offset_edge_loops");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_edge_slide");
- RNA_boolean_set(otmacro->ptr, "single_side", true);
-
- ot = WM_operatortype_append_macro("MESH_OT_duplicate_move", "Add Duplicate", "Duplicate mesh and move",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "MESH_OT_duplicate");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", false);
-
- ot = WM_operatortype_append_macro("MESH_OT_rip_move", "Rip", "Rip polygons and move the result",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- otmacro = WM_operatortype_macro_define(ot, "MESH_OT_rip");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", false);
-
- ot = WM_operatortype_append_macro("MESH_OT_rip_edge_move", "Extend Vertices", "Extend vertices and move the result",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "MESH_OT_rip_edge");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", false);
-
- ot = WM_operatortype_append_macro("MESH_OT_extrude_region_move", "Extrude Region and Move",
- "Extrude region and move result", OPTYPE_UNDO | OPTYPE_REGISTER);
- otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_region");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", false);
-
- ot = WM_operatortype_append_macro("MESH_OT_extrude_context_move", "Extrude Region and Move",
- "Extrude context and move result", OPTYPE_UNDO | OPTYPE_REGISTER);
- otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_context");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", false);
-
- ot = WM_operatortype_append_macro("MESH_OT_extrude_region_shrink_fatten", "Extrude Region and Shrink/Fatten",
- "Extrude along normals and move result", OPTYPE_UNDO | OPTYPE_REGISTER);
- otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_region");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_shrink_fatten");
- RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", false);
-
- ot = WM_operatortype_append_macro("MESH_OT_extrude_faces_move", "Extrude Individual Faces and Move",
- "Extrude faces and move result", OPTYPE_UNDO | OPTYPE_REGISTER);
- otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_faces_indiv");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_shrink_fatten");
- RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", false);
-
- ot = WM_operatortype_append_macro("MESH_OT_extrude_edges_move", "Extrude Only Edges and Move",
- "Extrude edges and move result", OPTYPE_UNDO | OPTYPE_REGISTER);
- otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_edges_indiv");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", false);
-
- ot = WM_operatortype_append_macro("MESH_OT_extrude_vertices_move", "Extrude Only Vertices and Move",
- "Extrude vertices and move result", OPTYPE_UNDO | OPTYPE_REGISTER);
- otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_verts_indiv");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", false);
-
-
- ot = WM_operatortype_append_macro(
- "MESH_OT_polybuild_face_at_cursor_move", "Face at Cursor Move", "",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "MESH_OT_polybuild_face_at_cursor");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", false);
-
- ot = WM_operatortype_append_macro(
- "MESH_OT_polybuild_split_at_cursor_move", "Split at Cursor Move", "",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "MESH_OT_polybuild_split_at_cursor");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", false);
+ wmOperatorType *ot;
+ wmOperatorTypeMacro *otmacro;
+
+ ot = WM_operatortype_append_macro("MESH_OT_loopcut_slide",
+ "Loop Cut and Slide",
+ "Cut mesh loop and slide it",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "MESH_OT_loopcut");
+ WM_operatortype_macro_define(ot, "TRANSFORM_OT_edge_slide");
+
+ ot = WM_operatortype_append_macro("MESH_OT_offset_edge_loops_slide",
+ "Offset Edge Slide",
+ "Offset edge loop slide",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "MESH_OT_offset_edge_loops");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_edge_slide");
+ RNA_boolean_set(otmacro->ptr, "single_side", true);
+
+ ot = WM_operatortype_append_macro("MESH_OT_duplicate_move",
+ "Add Duplicate",
+ "Duplicate mesh and move",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "MESH_OT_duplicate");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
+
+ ot = WM_operatortype_append_macro("MESH_OT_rip_move",
+ "Rip",
+ "Rip polygons and move the result",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ otmacro = WM_operatortype_macro_define(ot, "MESH_OT_rip");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
+
+ ot = WM_operatortype_append_macro("MESH_OT_rip_edge_move",
+ "Extend Vertices",
+ "Extend vertices and move the result",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "MESH_OT_rip_edge");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
+
+ ot = WM_operatortype_append_macro("MESH_OT_extrude_region_move",
+ "Extrude Region and Move",
+ "Extrude region and move result",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_region");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
+
+ ot = WM_operatortype_append_macro("MESH_OT_extrude_context_move",
+ "Extrude Region and Move",
+ "Extrude context and move result",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_context");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
+
+ ot = WM_operatortype_append_macro("MESH_OT_extrude_region_shrink_fatten",
+ "Extrude Region and Shrink/Fatten",
+ "Extrude along normals and move result",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_region");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_shrink_fatten");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
+
+ ot = WM_operatortype_append_macro("MESH_OT_extrude_faces_move",
+ "Extrude Individual Faces and Move",
+ "Extrude faces and move result",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_faces_indiv");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_shrink_fatten");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
+
+ ot = WM_operatortype_append_macro("MESH_OT_extrude_edges_move",
+ "Extrude Only Edges and Move",
+ "Extrude edges and move result",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_edges_indiv");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
+
+ ot = WM_operatortype_append_macro("MESH_OT_extrude_vertices_move",
+ "Extrude Only Vertices and Move",
+ "Extrude vertices and move result",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_verts_indiv");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
+
+ ot = WM_operatortype_append_macro("MESH_OT_polybuild_face_at_cursor_move",
+ "Face at Cursor Move",
+ "",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "MESH_OT_polybuild_face_at_cursor");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
+
+ ot = WM_operatortype_append_macro("MESH_OT_polybuild_split_at_cursor_move",
+ "Split at Cursor Move",
+ "",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "MESH_OT_polybuild_split_at_cursor");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
}
/* note mesh keymap also for other space? */
void ED_keymap_mesh(wmKeyConfig *keyconf)
{
- wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Mesh", 0, 0);
- keymap->poll = ED_operator_editmesh;
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Mesh", 0, 0);
+ keymap->poll = ED_operator_editmesh;
- knifetool_modal_keymap(keyconf);
- point_normals_modal_keymap(keyconf);
- bevel_modal_keymap(keyconf);
+ knifetool_modal_keymap(keyconf);
+ point_normals_modal_keymap(keyconf);
+ bevel_modal_keymap(keyconf);
}
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index 5339c83d158..ce7908bf0a3 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -74,529 +74,584 @@
/* join selected meshes into the active mesh, context sensitive
* return 0 if no join is made (error) and 1 if the join is done */
-static void join_mesh_single(
- Depsgraph *depsgraph, Main *bmain, Scene *scene,
- Object *ob_dst, Object *ob_src, float imat[4][4],
- MVert **mvert_pp, MEdge **medge_pp, MLoop **mloop_pp, MPoly **mpoly_pp,
- CustomData *vdata, CustomData *edata, CustomData *ldata, CustomData *pdata,
- int totvert, int totedge, int totloop, int totpoly,
- Key *key, Key *nkey,
- Material **matar, int *matmap, int totcol,
- int *vertofs, int *edgeofs, int *loopofs, int *polyofs)
+static void join_mesh_single(Depsgraph *depsgraph,
+ Main *bmain,
+ Scene *scene,
+ Object *ob_dst,
+ Object *ob_src,
+ float imat[4][4],
+ MVert **mvert_pp,
+ MEdge **medge_pp,
+ MLoop **mloop_pp,
+ MPoly **mpoly_pp,
+ CustomData *vdata,
+ CustomData *edata,
+ CustomData *ldata,
+ CustomData *pdata,
+ int totvert,
+ int totedge,
+ int totloop,
+ int totpoly,
+ Key *key,
+ Key *nkey,
+ Material **matar,
+ int *matmap,
+ int totcol,
+ int *vertofs,
+ int *edgeofs,
+ int *loopofs,
+ int *polyofs)
{
- int a, b;
-
- Mesh *me = ob_src->data;
- MVert *mvert = *mvert_pp;
- MEdge *medge = *medge_pp;
- MLoop *mloop = *mloop_pp;
- MPoly *mpoly = *mpoly_pp;
-
- if (me->totvert) {
- /* merge customdata flag */
- ((Mesh *)ob_dst->data)->cd_flag |= me->cd_flag;
-
- /* standard data */
- CustomData_merge(&me->vdata, vdata, CD_MASK_MESH.vmask, CD_DEFAULT, totvert);
- CustomData_copy_data_named(&me->vdata, vdata, 0, *vertofs, me->totvert);
-
- /* vertex groups */
- MDeformVert *dvert = CustomData_get(vdata, *vertofs, CD_MDEFORMVERT);
- MDeformVert *dvert_src = CustomData_get(&me->vdata, 0, CD_MDEFORMVERT);
-
- /* Remap to correct new vgroup indices, if needed. */
- if (dvert_src) {
- BLI_assert(dvert != NULL);
-
- /* Build src to merged mapping of vgroup indices. */
- int *vgroup_index_map;
- int vgroup_index_map_len;
- vgroup_index_map = BKE_object_defgroup_index_map_create(ob_src, ob_dst, &vgroup_index_map_len);
- BKE_object_defgroup_index_map_apply(dvert, me->totvert, vgroup_index_map, vgroup_index_map_len);
- if (vgroup_index_map != NULL) {
- MEM_freeN(vgroup_index_map);
- }
- }
-
- /* if this is the object we're merging into, no need to do anything */
- if (ob_src != ob_dst) {
- float cmat[4][4];
-
- /* watch this: switch matmul order really goes wrong */
- mul_m4_m4m4(cmat, imat, ob_src->obmat);
-
- /* transform vertex coordinates into new space */
- for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, mvert++) {
- mul_m4_v3(cmat, mvert->co);
- }
-
- /* for each shapekey in destination mesh:
- * - if there's a matching one, copy it across (will need to transform vertices into new space...)
- * - otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space)
- */
- if (key) {
- /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */
- for (KeyBlock *kb = key->block.first; kb; kb = kb->next) {
- /* get pointer to where to write data for this mesh in shapekey's data array */
- float (*cos)[3] = ((float (*)[3])kb->data) + *vertofs;
-
- /* check if this mesh has such a shapekey */
- KeyBlock *okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL;
- if (okb) {
- /* copy this mesh's shapekey to the destination shapekey
- * (need to transform first) */
- float (*ocos)[3] = okb->data;
- for (a = 0; a < me->totvert; a++, cos++, ocos++) {
- copy_v3_v3(*cos, *ocos);
- mul_m4_v3(cmat, *cos);
- }
- }
- else {
- /* copy this mesh's vertex coordinates to the destination shapekey */
- for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) {
- copy_v3_v3(*cos, mvert->co);
- }
- }
- }
- }
- }
- else {
- /* for each shapekey in destination mesh:
- * - if it was an 'original', copy the appropriate data from nkey
- * - otherwise, copy across plain coordinates (no need to transform coordinates)
- */
- if (key) {
- for (KeyBlock *kb = key->block.first; kb; kb = kb->next) {
- /* get pointer to where to write data for this mesh in shapekey's data array */
- float (*cos)[3] = ((float (*)[3])kb->data) + *vertofs;
-
- /* check if this was one of the original shapekeys */
- KeyBlock *okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL;
- if (okb) {
- /* copy this mesh's shapekey to the destination shapekey */
- float (*ocos)[3] = okb->data;
- for (a = 0; a < me->totvert; a++, cos++, ocos++) {
- copy_v3_v3(*cos, *ocos);
- }
- }
- else {
- /* copy base-coordinates to the destination shapekey */
- for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) {
- copy_v3_v3(*cos, mvert->co);
- }
- }
- }
- }
- }
- }
-
- if (me->totedge) {
- CustomData_merge(&me->edata, edata, CD_MASK_MESH.emask, CD_DEFAULT, totedge);
- CustomData_copy_data_named(&me->edata, edata, 0, *edgeofs, me->totedge);
-
- for (a = 0; a < me->totedge; a++, medge++) {
- medge->v1 += *vertofs;
- medge->v2 += *vertofs;
- }
- }
-
- if (me->totloop) {
- if (ob_src != ob_dst) {
- MultiresModifierData *mmd;
-
- multiresModifier_prepare_join(depsgraph, scene, ob_src, ob_dst);
-
- if ((mmd = get_multires_modifier(scene, ob_src, true))) {
- ED_object_iter_other(bmain, ob_src, true,
- ED_object_multires_update_totlevels_cb,
- &mmd->totlvl);
- }
- }
-
- CustomData_merge(&me->ldata, ldata, CD_MASK_MESH.lmask, CD_DEFAULT, totloop);
- CustomData_copy_data_named(&me->ldata, ldata, 0, *loopofs, me->totloop);
-
- for (a = 0; a < me->totloop; a++, mloop++) {
- mloop->v += *vertofs;
- mloop->e += *edgeofs;
- }
- }
-
- if (me->totpoly) {
- if (matmap) {
- /* make mapping for materials */
- for (a = 1; a <= ob_src->totcol; a++) {
- Material *ma = give_current_material(ob_src, a);
-
- for (b = 0; b < totcol; b++) {
- if (ma == matar[b]) {
- matmap[a - 1] = b;
- break;
- }
- }
- }
- }
-
- CustomData_merge(&me->pdata, pdata, CD_MASK_MESH.pmask, CD_DEFAULT, totpoly);
- CustomData_copy_data_named(&me->pdata, pdata, 0, *polyofs, me->totpoly);
-
- for (a = 0; a < me->totpoly; a++, mpoly++) {
- mpoly->loopstart += *loopofs;
- mpoly->mat_nr = matmap ? matmap[mpoly->mat_nr] : 0;
- }
- }
-
- /* these are used for relinking (cannot be set earlier, or else reattaching goes wrong) */
- *vertofs += me->totvert;
- *mvert_pp += me->totvert;
- *edgeofs += me->totedge;
- *medge_pp += me->totedge;
- *loopofs += me->totloop;
- *mloop_pp += me->totloop;
- *polyofs += me->totpoly;
- *mpoly_pp += me->totpoly;
+ int a, b;
+
+ Mesh *me = ob_src->data;
+ MVert *mvert = *mvert_pp;
+ MEdge *medge = *medge_pp;
+ MLoop *mloop = *mloop_pp;
+ MPoly *mpoly = *mpoly_pp;
+
+ if (me->totvert) {
+ /* merge customdata flag */
+ ((Mesh *)ob_dst->data)->cd_flag |= me->cd_flag;
+
+ /* standard data */
+ CustomData_merge(&me->vdata, vdata, CD_MASK_MESH.vmask, CD_DEFAULT, totvert);
+ CustomData_copy_data_named(&me->vdata, vdata, 0, *vertofs, me->totvert);
+
+ /* vertex groups */
+ MDeformVert *dvert = CustomData_get(vdata, *vertofs, CD_MDEFORMVERT);
+ MDeformVert *dvert_src = CustomData_get(&me->vdata, 0, CD_MDEFORMVERT);
+
+ /* Remap to correct new vgroup indices, if needed. */
+ if (dvert_src) {
+ BLI_assert(dvert != NULL);
+
+ /* Build src to merged mapping of vgroup indices. */
+ int *vgroup_index_map;
+ int vgroup_index_map_len;
+ vgroup_index_map = BKE_object_defgroup_index_map_create(
+ ob_src, ob_dst, &vgroup_index_map_len);
+ BKE_object_defgroup_index_map_apply(
+ dvert, me->totvert, vgroup_index_map, vgroup_index_map_len);
+ if (vgroup_index_map != NULL) {
+ MEM_freeN(vgroup_index_map);
+ }
+ }
+
+ /* if this is the object we're merging into, no need to do anything */
+ if (ob_src != ob_dst) {
+ float cmat[4][4];
+
+ /* watch this: switch matmul order really goes wrong */
+ mul_m4_m4m4(cmat, imat, ob_src->obmat);
+
+ /* transform vertex coordinates into new space */
+ for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, mvert++) {
+ mul_m4_v3(cmat, mvert->co);
+ }
+
+ /* for each shapekey in destination mesh:
+ * - if there's a matching one, copy it across (will need to transform vertices into new space...)
+ * - otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space)
+ */
+ if (key) {
+ /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */
+ for (KeyBlock *kb = key->block.first; kb; kb = kb->next) {
+ /* get pointer to where to write data for this mesh in shapekey's data array */
+ float(*cos)[3] = ((float(*)[3])kb->data) + *vertofs;
+
+ /* check if this mesh has such a shapekey */
+ KeyBlock *okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL;
+ if (okb) {
+ /* copy this mesh's shapekey to the destination shapekey
+ * (need to transform first) */
+ float(*ocos)[3] = okb->data;
+ for (a = 0; a < me->totvert; a++, cos++, ocos++) {
+ copy_v3_v3(*cos, *ocos);
+ mul_m4_v3(cmat, *cos);
+ }
+ }
+ else {
+ /* copy this mesh's vertex coordinates to the destination shapekey */
+ for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) {
+ copy_v3_v3(*cos, mvert->co);
+ }
+ }
+ }
+ }
+ }
+ else {
+ /* for each shapekey in destination mesh:
+ * - if it was an 'original', copy the appropriate data from nkey
+ * - otherwise, copy across plain coordinates (no need to transform coordinates)
+ */
+ if (key) {
+ for (KeyBlock *kb = key->block.first; kb; kb = kb->next) {
+ /* get pointer to where to write data for this mesh in shapekey's data array */
+ float(*cos)[3] = ((float(*)[3])kb->data) + *vertofs;
+
+ /* check if this was one of the original shapekeys */
+ KeyBlock *okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL;
+ if (okb) {
+ /* copy this mesh's shapekey to the destination shapekey */
+ float(*ocos)[3] = okb->data;
+ for (a = 0; a < me->totvert; a++, cos++, ocos++) {
+ copy_v3_v3(*cos, *ocos);
+ }
+ }
+ else {
+ /* copy base-coordinates to the destination shapekey */
+ for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) {
+ copy_v3_v3(*cos, mvert->co);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (me->totedge) {
+ CustomData_merge(&me->edata, edata, CD_MASK_MESH.emask, CD_DEFAULT, totedge);
+ CustomData_copy_data_named(&me->edata, edata, 0, *edgeofs, me->totedge);
+
+ for (a = 0; a < me->totedge; a++, medge++) {
+ medge->v1 += *vertofs;
+ medge->v2 += *vertofs;
+ }
+ }
+
+ if (me->totloop) {
+ if (ob_src != ob_dst) {
+ MultiresModifierData *mmd;
+
+ multiresModifier_prepare_join(depsgraph, scene, ob_src, ob_dst);
+
+ if ((mmd = get_multires_modifier(scene, ob_src, true))) {
+ ED_object_iter_other(
+ bmain, ob_src, true, ED_object_multires_update_totlevels_cb, &mmd->totlvl);
+ }
+ }
+
+ CustomData_merge(&me->ldata, ldata, CD_MASK_MESH.lmask, CD_DEFAULT, totloop);
+ CustomData_copy_data_named(&me->ldata, ldata, 0, *loopofs, me->totloop);
+
+ for (a = 0; a < me->totloop; a++, mloop++) {
+ mloop->v += *vertofs;
+ mloop->e += *edgeofs;
+ }
+ }
+
+ if (me->totpoly) {
+ if (matmap) {
+ /* make mapping for materials */
+ for (a = 1; a <= ob_src->totcol; a++) {
+ Material *ma = give_current_material(ob_src, a);
+
+ for (b = 0; b < totcol; b++) {
+ if (ma == matar[b]) {
+ matmap[a - 1] = b;
+ break;
+ }
+ }
+ }
+ }
+
+ CustomData_merge(&me->pdata, pdata, CD_MASK_MESH.pmask, CD_DEFAULT, totpoly);
+ CustomData_copy_data_named(&me->pdata, pdata, 0, *polyofs, me->totpoly);
+
+ for (a = 0; a < me->totpoly; a++, mpoly++) {
+ mpoly->loopstart += *loopofs;
+ mpoly->mat_nr = matmap ? matmap[mpoly->mat_nr] : 0;
+ }
+ }
+
+ /* these are used for relinking (cannot be set earlier, or else reattaching goes wrong) */
+ *vertofs += me->totvert;
+ *mvert_pp += me->totvert;
+ *edgeofs += me->totedge;
+ *medge_pp += me->totedge;
+ *loopofs += me->totloop;
+ *mloop_pp += me->totloop;
+ *polyofs += me->totpoly;
+ *mpoly_pp += me->totpoly;
}
int join_mesh_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- Material **matar = NULL, *ma;
- Mesh *me;
- MVert *mvert = NULL;
- MEdge *medge = NULL;
- MPoly *mpoly = NULL;
- MLoop *mloop = NULL;
- Key *key, *nkey = NULL;
- KeyBlock *kb, *kbn;
- float imat[4][4];
- 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;
- bDeformGroup *dg, *odg;
- CustomData vdata, edata, fdata, ldata, pdata;
-
- if (ob->mode & OB_MODE_EDIT) {
- BKE_report(op->reports, RPT_WARNING, "Cannot join while in edit mode");
- return OPERATOR_CANCELLED;
- }
-
- /* ob is the object we are adding geometry to */
- if (!ob || ob->type != OB_MESH) {
- BKE_report(op->reports, RPT_WARNING, "Active object is not a mesh");
- return OPERATOR_CANCELLED;
- }
-
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
-
- /* count & check */
- CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects)
- {
- if (ob_iter->type == OB_MESH) {
- me = ob_iter->data;
-
- totvert += me->totvert;
- totedge += me->totedge;
- totloop += me->totloop;
- totpoly += me->totpoly;
- totmat += ob_iter->totcol;
-
- if (ob_iter == ob)
- ok = true;
-
- /* check for shapekeys */
- if (me->key)
- haskey++;
- }
- }
- CTX_DATA_END;
-
- /* that way the active object is always selected */
- if (ok == false) {
- BKE_report(op->reports, RPT_WARNING, "Active object is not a selected mesh");
- return OPERATOR_CANCELLED;
- }
-
- /* only join meshes if there are verts to join, there aren't too many, and we only had one mesh selected */
- me = (Mesh *)ob->data;
- key = me->key;
-
- if (totvert == 0 || totvert == me->totvert) {
- BKE_report(op->reports, RPT_WARNING, "No mesh data to join");
- return OPERATOR_CANCELLED;
- }
-
- if (totvert > MESH_MAX_VERTS) {
- BKE_reportf(op->reports, RPT_WARNING, "Joining results in %d vertices, limit is %ld", totvert, MESH_MAX_VERTS);
- return OPERATOR_CANCELLED;
- }
-
- /* remove tessface to ensure we don't hold references to invalid faces */
- BKE_mesh_tessface_clear(me);
-
- /* new material indices and material array */
- if (totmat) {
- matar = MEM_callocN(sizeof(*matar) * totmat, "join_mesh matar");
- matmap = MEM_callocN(sizeof(*matmap) * totmat, "join_mesh matmap");
- }
- totcol = ob->totcol;
-
- /* obact materials in new main array, is nicer start! */
- for (a = 0; a < ob->totcol; a++) {
- matar[a] = give_current_material(ob, a + 1);
- id_us_plus((ID *)matar[a]);
- /* increase id->us : will be lowered later */
- }
-
- /* - if destination mesh had shapekeys, move them somewhere safe, and set up placeholders
- * with arrays that are large enough to hold shapekey data for all meshes
- * - if destination mesh didn't have shapekeys, but we encountered some in the meshes we're
- * joining, set up a new keyblock and assign to the mesh
- */
- if (key) {
- /* make a duplicate copy that will only be used here... (must remember to free it!) */
- nkey = BKE_key_copy(bmain, key);
-
- /* for all keys in old block, clear data-arrays */
- for (kb = key->block.first; kb; kb = kb->next) {
- if (kb->data) MEM_freeN(kb->data);
- kb->data = MEM_callocN(sizeof(float) * 3 * totvert, "join_shapekey");
- kb->totelem = totvert;
- }
- }
- else if (haskey) {
- /* add a new key-block and add to the mesh */
- key = me->key = BKE_key_add(bmain, (ID *)me);
- key->type = KEY_RELATIVE;
- }
-
- /* first pass over objects - copying materials and vertexgroups across */
- CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects)
- {
- /* only act if a mesh, and not the one we're joining to */
- if ((ob != ob_iter) && (ob_iter->type == OB_MESH)) {
- me = ob_iter->data;
-
- /* 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");
- memcpy(odg, dg, sizeof(bDeformGroup));
- BLI_addtail(&ob->defbase, odg);
- }
- }
- if (ob->defbase.first && ob->actdef == 0)
- ob->actdef = 1;
-
-
- if (me->totvert) {
- /* Add this object's materials to the base one's if they don't exist already
- * (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);
-
- for (b = 0; b < totcol; b++) {
- if (ma == matar[b]) {
- break;
- }
- }
- if (b == totcol) {
- matar[b] = ma;
- if (ma) {
- id_us_plus(&ma->id);
- }
- totcol++;
- }
- if (totcol >= MAXMAT) {
- break;
- }
- }
- }
-
- /* if this mesh has shapekeys,
- * check if destination mesh already has matching entries too */
- if (me->key && key) {
- /* for remapping KeyBlock.relative */
- int *index_map = MEM_mallocN(sizeof(int) * me->key->totkey, __func__);
- KeyBlock **kb_map = MEM_mallocN(sizeof(KeyBlock *) * me->key->totkey, __func__);
-
- for (kb = me->key->block.first, i = 0; kb; kb = kb->next, i++) {
- BLI_assert(i < me->key->totkey);
-
- kbn = BKE_keyblock_find_name(key, kb->name);
- /* if key doesn't exist in destination mesh, add it */
- if (kbn) {
- index_map[i] = BLI_findindex(&key->block, kbn);
- }
- else {
- index_map[i] = key->totkey;
-
- kbn = BKE_keyblock_add(key, kb->name);
-
- BKE_keyblock_copy_settings(kbn, kb);
-
- /* adjust settings to fit (allocate a new data-array) */
- kbn->data = MEM_callocN(sizeof(float) * 3 * totvert, "joined_shapekey");
- kbn->totelem = totvert;
- }
-
- kb_map[i] = kbn;
- }
-
- /* remap relative index values */
- for (kb = me->key->block.first, i = 0; kb; kb = kb->next, i++) {
- /* sanity check, should always be true */
- if (LIKELY(kb->relative < me->key->totkey)) {
- kb_map[i]->relative = index_map[kb->relative];
- }
- }
-
- MEM_freeN(index_map);
- MEM_freeN(kb_map);
- }
- }
- }
- }
- CTX_DATA_END;
-
-
- /* setup new data for destination mesh */
- CustomData_reset(&vdata);
- CustomData_reset(&edata);
- CustomData_reset(&fdata);
- CustomData_reset(&ldata);
- CustomData_reset(&pdata);
-
- mvert = CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
- medge = CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
- mloop = CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, NULL, totloop);
- mpoly = CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, NULL, totpoly);
-
- vertofs = 0;
- edgeofs = 0;
- loopofs = 0;
- polyofs = 0;
-
- /* inverse transform for all selected meshes in this object */
- invert_m4_m4(imat, ob->obmat);
-
- /* Add back active mesh first.
- * This allows to keep things similar as they were, as much as possible
- * (i.e. data from active mesh will remain first ones in new result of the merge,
- * in same order for CD layers, etc). See also T50084.
- */
- join_mesh_single(
- depsgraph, bmain, scene,
- ob, ob, imat,
- &mvert, &medge, &mloop, &mpoly,
- &vdata, &edata, &ldata, &pdata,
- totvert, totedge, totloop, totpoly,
- key, nkey,
- matar, matmap, totcol,
- &vertofs, &edgeofs, &loopofs, &polyofs);
-
- CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects)
- {
- if (ob_iter == ob) {
- continue;
- }
- /* only join if this is a mesh */
- if (ob_iter->type == OB_MESH) {
- join_mesh_single(
- depsgraph, bmain, scene,
- ob, ob_iter, imat,
- &mvert, &medge, &mloop, &mpoly,
- &vdata, &edata, &ldata, &pdata,
- totvert, totedge, totloop, totpoly,
- key, nkey,
- matar, matmap, totcol,
- &vertofs, &edgeofs, &loopofs, &polyofs);
-
- /* free base, now that data is merged */
- if (ob_iter != ob) {
- ED_object_base_free_and_unlink(bmain, scene, ob_iter);
- }
- }
- }
- CTX_DATA_END;
-
- /* return to mesh we're merging to */
- me = ob->data;
-
- CustomData_free(&me->vdata, me->totvert);
- CustomData_free(&me->edata, me->totedge);
- CustomData_free(&me->ldata, me->totloop);
- CustomData_free(&me->pdata, me->totpoly);
-
- me->totvert = totvert;
- me->totedge = totedge;
- me->totloop = totloop;
- me->totpoly = totpoly;
-
- me->vdata = vdata;
- me->edata = edata;
- me->ldata = ldata;
- me->pdata = pdata;
-
- /* tessface data removed above, no need to update */
- BKE_mesh_update_customdata_pointers(me, false);
-
- /* update normals in case objects with non-uniform scale are joined */
- BKE_mesh_calc_normals(me);
-
- /* old material array */
- for (a = 1; a <= ob->totcol; a++) {
- ma = ob->mat[a - 1];
- if (ma)
- id_us_min(&ma->id);
- }
- for (a = 1; a <= me->totcol; a++) {
- ma = me->mat[a - 1];
- if (ma)
- id_us_min(&ma->id);
- }
- MEM_SAFE_FREE(ob->mat);
- MEM_SAFE_FREE(ob->matbits);
- MEM_SAFE_FREE(me->mat);
-
- if (totcol) {
- me->mat = matar;
- ob->mat = MEM_callocN(sizeof(*ob->mat) * totcol, "join obmatar");
- ob->matbits = MEM_callocN(sizeof(*ob->matbits) * totcol, "join obmatbits");
- MEM_freeN(matmap);
- }
-
- ob->totcol = me->totcol = totcol;
-
- /* other mesh users */
- test_all_objects_materials(bmain, (ID *)me);
-
- /* free temp copy of destination shapekeys (if applicable) */
- if (nkey) {
- /* We can assume nobody is using that ID currently. */
- BKE_id_free_ex(bmain, nkey, LIB_ID_FREE_NO_UI_USER, false);
- }
-
- /* ensure newly inserted keys are time sorted */
- if (key && (key->type != KEY_RELATIVE)) {
- BKE_key_sort(key);
- }
-
- /* Due to dependnecy cycle some other object might access old derived data. */
- BKE_object_free_derived_caches(ob);
-
- DEG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */
-
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
-
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ Material **matar = NULL, *ma;
+ Mesh *me;
+ MVert *mvert = NULL;
+ MEdge *medge = NULL;
+ MPoly *mpoly = NULL;
+ MLoop *mloop = NULL;
+ Key *key, *nkey = NULL;
+ KeyBlock *kb, *kbn;
+ float imat[4][4];
+ 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;
+ bDeformGroup *dg, *odg;
+ CustomData vdata, edata, fdata, ldata, pdata;
+
+ if (ob->mode & OB_MODE_EDIT) {
+ BKE_report(op->reports, RPT_WARNING, "Cannot join while in edit mode");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* ob is the object we are adding geometry to */
+ if (!ob || ob->type != OB_MESH) {
+ BKE_report(op->reports, RPT_WARNING, "Active object is not a mesh");
+ return OPERATOR_CANCELLED;
+ }
+
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
+ /* count & check */
+ CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
+ if (ob_iter->type == OB_MESH) {
+ me = ob_iter->data;
+
+ totvert += me->totvert;
+ totedge += me->totedge;
+ totloop += me->totloop;
+ totpoly += me->totpoly;
+ totmat += ob_iter->totcol;
+
+ if (ob_iter == ob)
+ ok = true;
+
+ /* check for shapekeys */
+ if (me->key)
+ haskey++;
+ }
+ }
+ CTX_DATA_END;
+
+ /* that way the active object is always selected */
+ if (ok == false) {
+ BKE_report(op->reports, RPT_WARNING, "Active object is not a selected mesh");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* only join meshes if there are verts to join, there aren't too many, and we only had one mesh selected */
+ me = (Mesh *)ob->data;
+ key = me->key;
+
+ if (totvert == 0 || totvert == me->totvert) {
+ BKE_report(op->reports, RPT_WARNING, "No mesh data to join");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (totvert > MESH_MAX_VERTS) {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Joining results in %d vertices, limit is %ld",
+ totvert,
+ MESH_MAX_VERTS);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* remove tessface to ensure we don't hold references to invalid faces */
+ BKE_mesh_tessface_clear(me);
+
+ /* new material indices and material array */
+ if (totmat) {
+ matar = MEM_callocN(sizeof(*matar) * totmat, "join_mesh matar");
+ matmap = MEM_callocN(sizeof(*matmap) * totmat, "join_mesh matmap");
+ }
+ totcol = ob->totcol;
+
+ /* obact materials in new main array, is nicer start! */
+ for (a = 0; a < ob->totcol; a++) {
+ matar[a] = give_current_material(ob, a + 1);
+ id_us_plus((ID *)matar[a]);
+ /* increase id->us : will be lowered later */
+ }
+
+ /* - if destination mesh had shapekeys, move them somewhere safe, and set up placeholders
+ * with arrays that are large enough to hold shapekey data for all meshes
+ * - if destination mesh didn't have shapekeys, but we encountered some in the meshes we're
+ * joining, set up a new keyblock and assign to the mesh
+ */
+ if (key) {
+ /* make a duplicate copy that will only be used here... (must remember to free it!) */
+ nkey = BKE_key_copy(bmain, key);
+
+ /* for all keys in old block, clear data-arrays */
+ for (kb = key->block.first; kb; kb = kb->next) {
+ if (kb->data)
+ MEM_freeN(kb->data);
+ kb->data = MEM_callocN(sizeof(float) * 3 * totvert, "join_shapekey");
+ kb->totelem = totvert;
+ }
+ }
+ else if (haskey) {
+ /* add a new key-block and add to the mesh */
+ key = me->key = BKE_key_add(bmain, (ID *)me);
+ key->type = KEY_RELATIVE;
+ }
+
+ /* first pass over objects - copying materials and vertexgroups across */
+ CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
+ /* only act if a mesh, and not the one we're joining to */
+ if ((ob != ob_iter) && (ob_iter->type == OB_MESH)) {
+ me = ob_iter->data;
+
+ /* 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");
+ memcpy(odg, dg, sizeof(bDeformGroup));
+ BLI_addtail(&ob->defbase, odg);
+ }
+ }
+ if (ob->defbase.first && ob->actdef == 0)
+ ob->actdef = 1;
+
+ if (me->totvert) {
+ /* Add this object's materials to the base one's if they don't exist already
+ * (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);
+
+ for (b = 0; b < totcol; b++) {
+ if (ma == matar[b]) {
+ break;
+ }
+ }
+ if (b == totcol) {
+ matar[b] = ma;
+ if (ma) {
+ id_us_plus(&ma->id);
+ }
+ totcol++;
+ }
+ if (totcol >= MAXMAT) {
+ break;
+ }
+ }
+ }
+
+ /* if this mesh has shapekeys,
+ * check if destination mesh already has matching entries too */
+ if (me->key && key) {
+ /* for remapping KeyBlock.relative */
+ int *index_map = MEM_mallocN(sizeof(int) * me->key->totkey, __func__);
+ KeyBlock **kb_map = MEM_mallocN(sizeof(KeyBlock *) * me->key->totkey, __func__);
+
+ for (kb = me->key->block.first, i = 0; kb; kb = kb->next, i++) {
+ BLI_assert(i < me->key->totkey);
+
+ kbn = BKE_keyblock_find_name(key, kb->name);
+ /* if key doesn't exist in destination mesh, add it */
+ if (kbn) {
+ index_map[i] = BLI_findindex(&key->block, kbn);
+ }
+ else {
+ index_map[i] = key->totkey;
+
+ kbn = BKE_keyblock_add(key, kb->name);
+
+ BKE_keyblock_copy_settings(kbn, kb);
+
+ /* adjust settings to fit (allocate a new data-array) */
+ kbn->data = MEM_callocN(sizeof(float) * 3 * totvert, "joined_shapekey");
+ kbn->totelem = totvert;
+ }
+
+ kb_map[i] = kbn;
+ }
+
+ /* remap relative index values */
+ for (kb = me->key->block.first, i = 0; kb; kb = kb->next, i++) {
+ /* sanity check, should always be true */
+ if (LIKELY(kb->relative < me->key->totkey)) {
+ kb_map[i]->relative = index_map[kb->relative];
+ }
+ }
+
+ MEM_freeN(index_map);
+ MEM_freeN(kb_map);
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* setup new data for destination mesh */
+ CustomData_reset(&vdata);
+ CustomData_reset(&edata);
+ CustomData_reset(&fdata);
+ CustomData_reset(&ldata);
+ CustomData_reset(&pdata);
+
+ mvert = CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
+ medge = CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
+ mloop = CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, NULL, totloop);
+ mpoly = CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, NULL, totpoly);
+
+ vertofs = 0;
+ edgeofs = 0;
+ loopofs = 0;
+ polyofs = 0;
+
+ /* inverse transform for all selected meshes in this object */
+ invert_m4_m4(imat, ob->obmat);
+
+ /* Add back active mesh first.
+ * This allows to keep things similar as they were, as much as possible
+ * (i.e. data from active mesh will remain first ones in new result of the merge,
+ * in same order for CD layers, etc). See also T50084.
+ */
+ join_mesh_single(depsgraph,
+ bmain,
+ scene,
+ ob,
+ ob,
+ imat,
+ &mvert,
+ &medge,
+ &mloop,
+ &mpoly,
+ &vdata,
+ &edata,
+ &ldata,
+ &pdata,
+ totvert,
+ totedge,
+ totloop,
+ totpoly,
+ key,
+ nkey,
+ matar,
+ matmap,
+ totcol,
+ &vertofs,
+ &edgeofs,
+ &loopofs,
+ &polyofs);
+
+ CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
+ if (ob_iter == ob) {
+ continue;
+ }
+ /* only join if this is a mesh */
+ if (ob_iter->type == OB_MESH) {
+ join_mesh_single(depsgraph,
+ bmain,
+ scene,
+ ob,
+ ob_iter,
+ imat,
+ &mvert,
+ &medge,
+ &mloop,
+ &mpoly,
+ &vdata,
+ &edata,
+ &ldata,
+ &pdata,
+ totvert,
+ totedge,
+ totloop,
+ totpoly,
+ key,
+ nkey,
+ matar,
+ matmap,
+ totcol,
+ &vertofs,
+ &edgeofs,
+ &loopofs,
+ &polyofs);
+
+ /* free base, now that data is merged */
+ if (ob_iter != ob) {
+ ED_object_base_free_and_unlink(bmain, scene, ob_iter);
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* return to mesh we're merging to */
+ me = ob->data;
+
+ CustomData_free(&me->vdata, me->totvert);
+ CustomData_free(&me->edata, me->totedge);
+ CustomData_free(&me->ldata, me->totloop);
+ CustomData_free(&me->pdata, me->totpoly);
+
+ me->totvert = totvert;
+ me->totedge = totedge;
+ me->totloop = totloop;
+ me->totpoly = totpoly;
+
+ me->vdata = vdata;
+ me->edata = edata;
+ me->ldata = ldata;
+ me->pdata = pdata;
+
+ /* tessface data removed above, no need to update */
+ BKE_mesh_update_customdata_pointers(me, false);
+
+ /* update normals in case objects with non-uniform scale are joined */
+ BKE_mesh_calc_normals(me);
+
+ /* old material array */
+ for (a = 1; a <= ob->totcol; a++) {
+ ma = ob->mat[a - 1];
+ if (ma)
+ id_us_min(&ma->id);
+ }
+ for (a = 1; a <= me->totcol; a++) {
+ ma = me->mat[a - 1];
+ if (ma)
+ id_us_min(&ma->id);
+ }
+ MEM_SAFE_FREE(ob->mat);
+ MEM_SAFE_FREE(ob->matbits);
+ MEM_SAFE_FREE(me->mat);
+
+ if (totcol) {
+ me->mat = matar;
+ ob->mat = MEM_callocN(sizeof(*ob->mat) * totcol, "join obmatar");
+ ob->matbits = MEM_callocN(sizeof(*ob->matbits) * totcol, "join obmatbits");
+ MEM_freeN(matmap);
+ }
+
+ ob->totcol = me->totcol = totcol;
+
+ /* other mesh users */
+ test_all_objects_materials(bmain, (ID *)me);
+
+ /* free temp copy of destination shapekeys (if applicable) */
+ if (nkey) {
+ /* We can assume nobody is using that ID currently. */
+ BKE_id_free_ex(bmain, nkey, LIB_ID_FREE_NO_UI_USER, false);
+ }
+
+ /* ensure newly inserted keys are time sorted */
+ if (key && (key->type != KEY_RELATIVE)) {
+ BKE_key_sort(key);
+ }
+
+ /* Due to dependnecy cycle some other object might access old derived data. */
+ BKE_object_free_derived_caches(ob);
+
+ DEG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+
+ return OPERATOR_FINISHED;
}
/*********************** JOIN AS SHAPES ***************************/
@@ -606,86 +661,85 @@ int join_mesh_exec(bContext *C, wmOperator *op)
int join_mesh_shapes_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob_active = CTX_data_active_object(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Mesh *me = (Mesh *)ob_active->data;
- Mesh *selme = NULL;
- Mesh *me_deformed = NULL;
- Key *key = me->key;
- KeyBlock *kb;
- bool ok = false, nonequal_verts = false;
-
- CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects)
- {
- if (ob_iter == ob_active) {
- continue;
- }
-
- if (ob_iter->type == OB_MESH) {
- selme = (Mesh *)ob_iter->data;
-
- if (selme->totvert == me->totvert)
- ok = true;
- else
- nonequal_verts = 1;
- }
- }
- CTX_DATA_END;
-
- if (!ok) {
- if (nonequal_verts)
- BKE_report(op->reports, RPT_WARNING, "Selected meshes must have equal numbers of vertices");
- else
- BKE_report(op->reports, RPT_WARNING, "No additional selected meshes with equal vertex count to join");
- return OPERATOR_CANCELLED;
- }
-
- if (key == NULL) {
- key = me->key = BKE_key_add(bmain, (ID *)me);
- key->type = KEY_RELATIVE;
-
- /* first key added, so it was the basis. initialize it with the existing mesh */
- kb = BKE_keyblock_add(key, NULL);
- BKE_keyblock_convert_from_mesh(me, key, kb);
- }
-
- /* now ready to add new keys from selected meshes */
- CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects)
- {
- if (ob_iter == ob_active) {
- continue;
- }
-
- if (ob_iter->type == OB_MESH) {
- selme = (Mesh *)ob_iter->data;
-
- if (selme->totvert == me->totvert) {
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter);
-
- me_deformed = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
-
- if (!me_deformed) {
- continue;
- }
-
- kb = BKE_keyblock_add(key, ob_iter->id.name + 2);
-
- BKE_mesh_runtime_eval_to_meshkey(me_deformed, me, kb);
- }
- }
- }
- CTX_DATA_END;
-
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob_active = CTX_data_active_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Mesh *me = (Mesh *)ob_active->data;
+ Mesh *selme = NULL;
+ Mesh *me_deformed = NULL;
+ Key *key = me->key;
+ KeyBlock *kb;
+ bool ok = false, nonequal_verts = false;
+
+ CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
+ if (ob_iter == ob_active) {
+ continue;
+ }
+
+ if (ob_iter->type == OB_MESH) {
+ selme = (Mesh *)ob_iter->data;
+
+ if (selme->totvert == me->totvert)
+ ok = true;
+ else
+ nonequal_verts = 1;
+ }
+ }
+ CTX_DATA_END;
+
+ if (!ok) {
+ if (nonequal_verts)
+ BKE_report(op->reports, RPT_WARNING, "Selected meshes must have equal numbers of vertices");
+ else
+ BKE_report(op->reports,
+ RPT_WARNING,
+ "No additional selected meshes with equal vertex count to join");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (key == NULL) {
+ key = me->key = BKE_key_add(bmain, (ID *)me);
+ key->type = KEY_RELATIVE;
+
+ /* first key added, so it was the basis. initialize it with the existing mesh */
+ kb = BKE_keyblock_add(key, NULL);
+ BKE_keyblock_convert_from_mesh(me, key, kb);
+ }
+
+ /* now ready to add new keys from selected meshes */
+ CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
+ if (ob_iter == ob_active) {
+ continue;
+ }
+
+ if (ob_iter->type == OB_MESH) {
+ selme = (Mesh *)ob_iter->data;
+
+ if (selme->totvert == me->totvert) {
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter);
+
+ me_deformed = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
+
+ if (!me_deformed) {
+ continue;
+ }
+
+ kb = BKE_keyblock_add(key, ob_iter->id.name + 2);
+
+ BKE_mesh_runtime_eval_to_meshkey(me_deformed, me, kb);
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+
+ return OPERATOR_FINISHED;
}
-
/* -------------------------------------------------------------------- */
/* Mesh Mirror (Topology) */
@@ -699,120 +753,124 @@ static MirrTopoStore_t mesh_topo_store = {NULL, -1. - 1, -1};
/* note, 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)
{
- if (mode == 'u') { /* use table */
- if (ED_mesh_mirrtopo_recalc_check(ob->data, me_eval, &mesh_topo_store)) {
- ED_mesh_mirror_topo_table(ob, me_eval, 's');
- }
- }
- else if (mode == 's') { /* start table */
- ED_mesh_mirrtopo_init(ob->data, me_eval, &mesh_topo_store, false);
- }
- else if (mode == 'e') { /* end table */
- ED_mesh_mirrtopo_free(&mesh_topo_store);
- }
- else {
- BLI_assert(0);
- }
-
- return 0;
+ if (mode == 'u') { /* use table */
+ if (ED_mesh_mirrtopo_recalc_check(ob->data, me_eval, &mesh_topo_store)) {
+ ED_mesh_mirror_topo_table(ob, me_eval, 's');
+ }
+ }
+ else if (mode == 's') { /* start table */
+ ED_mesh_mirrtopo_init(ob->data, me_eval, &mesh_topo_store, false);
+ }
+ else if (mode == 'e') { /* end table */
+ ED_mesh_mirrtopo_free(&mesh_topo_store);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ return 0;
}
/** \} */
-
static int mesh_get_x_mirror_vert_spatial(Object *ob, Mesh *mesh, int index)
{
- Mesh *me = ob->data;
- MVert *mvert = mesh ? mesh->mvert : me->mvert;
- float vec[3];
+ Mesh *me = ob->data;
+ MVert *mvert = mesh ? mesh->mvert : me->mvert;
+ float vec[3];
- mvert = &mvert[index];
- vec[0] = -mvert->co[0];
- vec[1] = mvert->co[1];
- vec[2] = mvert->co[2];
+ mvert = &mvert[index];
+ vec[0] = -mvert->co[0];
+ 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(ob, NULL, mesh, vec, 'u');
}
static int mesh_get_x_mirror_vert_topo(Object *ob, Mesh *mesh, int index)
{
- if (ED_mesh_mirror_topo_table(ob, mesh, 'u') == -1)
- return -1;
+ if (ED_mesh_mirror_topo_table(ob, mesh, 'u') == -1)
+ return -1;
- return mesh_topo_store.index_lookup[index];
+ return mesh_topo_store.index_lookup[index];
}
int mesh_get_x_mirror_vert(Object *ob, Mesh *me_eval, int index, const bool use_topology)
{
- if (use_topology) {
- return mesh_get_x_mirror_vert_topo(ob, me_eval, index);
- }
- else {
- return mesh_get_x_mirror_vert_spatial(ob, me_eval, index);
- }
+ if (use_topology) {
+ return mesh_get_x_mirror_vert_topo(ob, me_eval, index);
+ }
+ else {
+ return mesh_get_x_mirror_vert_spatial(ob, me_eval, index);
+ }
}
static BMVert *editbmesh_get_x_mirror_vert_spatial(Object *ob, BMEditMesh *em, const float co[3])
{
- float vec[3];
- int i;
-
- /* ignore nan verts */
- if ((isfinite(co[0]) == false) ||
- (isfinite(co[1]) == false) ||
- (isfinite(co[2]) == false))
- {
- return NULL;
- }
-
- vec[0] = -co[0];
- vec[1] = co[1];
- vec[2] = co[2];
-
- i = ED_mesh_mirror_spatial_table(ob, em, NULL, vec, 'u');
- if (i != -1) {
- return BM_vert_at_index(em->bm, i);
- }
- return NULL;
+ float vec[3];
+ int i;
+
+ /* ignore nan verts */
+ if ((isfinite(co[0]) == false) || (isfinite(co[1]) == false) || (isfinite(co[2]) == false)) {
+ return NULL;
+ }
+
+ vec[0] = -co[0];
+ vec[1] = co[1];
+ vec[2] = co[2];
+
+ i = ED_mesh_mirror_spatial_table(ob, em, NULL, vec, 'u');
+ if (i != -1) {
+ return BM_vert_at_index(em->bm, i);
+ }
+ return NULL;
}
-static BMVert *editbmesh_get_x_mirror_vert_topo(Object *ob, struct BMEditMesh *em, BMVert *eve, int index)
+static BMVert *editbmesh_get_x_mirror_vert_topo(Object *ob,
+ struct BMEditMesh *em,
+ BMVert *eve,
+ int index)
{
- intptr_t poinval;
- if (ED_mesh_mirror_topo_table(ob, NULL, 'u') == -1)
- return NULL;
-
- if (index == -1) {
- BMIter iter;
- BMVert *v;
-
- index = 0;
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (v == eve)
- break;
- index++;
- }
-
- if (index == em->bm->totvert) {
- return NULL;
- }
- }
-
- poinval = mesh_topo_store.index_lookup[index];
-
- if (poinval != -1)
- return (BMVert *)(poinval);
- return NULL;
+ intptr_t poinval;
+ if (ED_mesh_mirror_topo_table(ob, NULL, 'u') == -1)
+ return NULL;
+
+ if (index == -1) {
+ BMIter iter;
+ BMVert *v;
+
+ index = 0;
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (v == eve)
+ break;
+ index++;
+ }
+
+ if (index == em->bm->totvert) {
+ return NULL;
+ }
+ }
+
+ poinval = mesh_topo_store.index_lookup[index];
+
+ if (poinval != -1)
+ return (BMVert *)(poinval);
+ return NULL;
}
-BMVert *editbmesh_get_x_mirror_vert(Object *ob, struct BMEditMesh *em, BMVert *eve, const float co[3], int index, const bool use_topology)
+BMVert *editbmesh_get_x_mirror_vert(Object *ob,
+ struct BMEditMesh *em,
+ BMVert *eve,
+ const float co[3],
+ int index,
+ const bool use_topology)
{
- if (use_topology) {
- return editbmesh_get_x_mirror_vert_topo(ob, em, eve, index);
- }
- else {
- return editbmesh_get_x_mirror_vert_spatial(ob, em, co);
- }
+ if (use_topology) {
+ return editbmesh_get_x_mirror_vert_topo(ob, em, eve, index);
+ }
+ else {
+ return editbmesh_get_x_mirror_vert_spatial(ob, em, co);
+ }
}
/**
@@ -822,187 +880,187 @@ BMVert *editbmesh_get_x_mirror_vert(Object *ob, struct BMEditMesh *em, BMVert *e
*/
int ED_mesh_mirror_get_vert(Object *ob, int index)
{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
- int index_mirr;
-
- if (em) {
- BMVert *eve, *eve_mirr;
- eve = BM_vert_at_index(em->bm, index);
- eve_mirr = editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, index, use_topology);
- index_mirr = eve_mirr ? BM_elem_index_get(eve_mirr) : -1;
- }
- else {
- index_mirr = mesh_get_x_mirror_vert(ob, NULL, index, use_topology);
- }
-
- return index_mirr;
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+ int index_mirr;
+
+ if (em) {
+ BMVert *eve, *eve_mirr;
+ eve = BM_vert_at_index(em->bm, index);
+ eve_mirr = editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, index, use_topology);
+ index_mirr = eve_mirr ? BM_elem_index_get(eve_mirr) : -1;
+ }
+ else {
+ index_mirr = mesh_get_x_mirror_vert(ob, NULL, index, use_topology);
+ }
+
+ return index_mirr;
}
#if 0
static float *editmesh_get_mirror_uv(BMEditMesh *em, int axis, float *uv, float *mirrCent, float *face_cent)
{
- float vec[2];
- float cent_vec[2];
- float cent[2];
-
- /* ignore nan verts */
- if (isnan(uv[0]) || !isfinite(uv[0]) ||
- isnan(uv[1]) || !isfinite(uv[1])
- )
- {
- return NULL;
- }
-
- if (axis) {
- vec[0] = uv[0];
- vec[1] = -((uv[1]) - mirrCent[1]) + mirrCent[1];
-
- cent_vec[0] = face_cent[0];
- cent_vec[1] = -((face_cent[1]) - mirrCent[1]) + mirrCent[1];
- }
- else {
- vec[0] = -((uv[0]) - mirrCent[0]) + mirrCent[0];
- vec[1] = uv[1];
-
- cent_vec[0] = -((face_cent[0]) - mirrCent[0]) + mirrCent[0];
- cent_vec[1] = face_cent[1];
- }
-
- /* TODO - Optimize */
- {
- BMIter iter;
- BMFace *efa;
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- uv_poly_center(efa, cent, cd_loop_uv_offset);
-
- if ( (fabsf(cent[0] - cent_vec[0]) < 0.001f) && (fabsf(cent[1] - cent_vec[1]) < 0.001f) ) {
- BMIter liter;
- BMLoop *l;
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- if ( (fabsf(luv->uv[0] - vec[0]) < 0.001f) && (fabsf(luv->uv[1] - vec[1]) < 0.001f) ) {
- return luv->uv;
-
- }
- }
- }
- }
- }
-
- return NULL;
+ float vec[2];
+ float cent_vec[2];
+ float cent[2];
+
+ /* ignore nan verts */
+ if (isnan(uv[0]) || !isfinite(uv[0]) ||
+ isnan(uv[1]) || !isfinite(uv[1])
+ )
+ {
+ return NULL;
+ }
+
+ if (axis) {
+ vec[0] = uv[0];
+ vec[1] = -((uv[1]) - mirrCent[1]) + mirrCent[1];
+
+ cent_vec[0] = face_cent[0];
+ cent_vec[1] = -((face_cent[1]) - mirrCent[1]) + mirrCent[1];
+ }
+ else {
+ vec[0] = -((uv[0]) - mirrCent[0]) + mirrCent[0];
+ vec[1] = uv[1];
+
+ cent_vec[0] = -((face_cent[0]) - mirrCent[0]) + mirrCent[0];
+ cent_vec[1] = face_cent[1];
+ }
+
+ /* TODO - Optimize */
+ {
+ BMIter iter;
+ BMFace *efa;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ uv_poly_center(efa, cent, cd_loop_uv_offset);
+
+ if ( (fabsf(cent[0] - cent_vec[0]) < 0.001f) && (fabsf(cent[1] - cent_vec[1]) < 0.001f) ) {
+ BMIter liter;
+ BMLoop *l;
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if ( (fabsf(luv->uv[0] - vec[0]) < 0.001f) && (fabsf(luv->uv[1] - vec[1]) < 0.001f) ) {
+ return luv->uv;
+
+ }
+ }
+ }
+ }
+ }
+
+ return NULL;
}
#endif
static unsigned int mirror_facehash(const void *ptr)
{
- const MFace *mf = ptr;
- unsigned int v0, v1;
-
- if (mf->v4) {
- v0 = MIN4(mf->v1, mf->v2, mf->v3, mf->v4);
- v1 = MAX4(mf->v1, mf->v2, mf->v3, mf->v4);
- }
- else {
- v0 = MIN3(mf->v1, mf->v2, mf->v3);
- v1 = MAX3(mf->v1, mf->v2, mf->v3);
- }
-
- return ((v0 * 39) ^ (v1 * 31));
+ const MFace *mf = ptr;
+ unsigned int v0, v1;
+
+ if (mf->v4) {
+ v0 = MIN4(mf->v1, mf->v2, mf->v3, mf->v4);
+ v1 = MAX4(mf->v1, mf->v2, mf->v3, mf->v4);
+ }
+ else {
+ v0 = MIN3(mf->v1, mf->v2, mf->v3);
+ v1 = MAX3(mf->v1, mf->v2, mf->v3);
+ }
+
+ return ((v0 * 39) ^ (v1 * 31));
}
static int mirror_facerotation(MFace *a, MFace *b)
{
- if (b->v4) {
- if (a->v1 == b->v1 && a->v2 == b->v2 && a->v3 == b->v3 && a->v4 == b->v4)
- return 0;
- else if (a->v4 == b->v1 && a->v1 == b->v2 && a->v2 == b->v3 && a->v3 == b->v4)
- return 1;
- else if (a->v3 == b->v1 && a->v4 == b->v2 && a->v1 == b->v3 && a->v2 == b->v4)
- return 2;
- else if (a->v2 == b->v1 && a->v3 == b->v2 && a->v4 == b->v3 && a->v1 == b->v4)
- return 3;
- }
- else {
- if (a->v1 == b->v1 && a->v2 == b->v2 && a->v3 == b->v3)
- return 0;
- else if (a->v3 == b->v1 && a->v1 == b->v2 && a->v2 == b->v3)
- return 1;
- else if (a->v2 == b->v1 && a->v3 == b->v2 && a->v1 == b->v3)
- return 2;
- }
-
- return -1;
+ if (b->v4) {
+ if (a->v1 == b->v1 && a->v2 == b->v2 && a->v3 == b->v3 && a->v4 == b->v4)
+ return 0;
+ else if (a->v4 == b->v1 && a->v1 == b->v2 && a->v2 == b->v3 && a->v3 == b->v4)
+ return 1;
+ else if (a->v3 == b->v1 && a->v4 == b->v2 && a->v1 == b->v3 && a->v2 == b->v4)
+ return 2;
+ else if (a->v2 == b->v1 && a->v3 == b->v2 && a->v4 == b->v3 && a->v1 == b->v4)
+ return 3;
+ }
+ else {
+ if (a->v1 == b->v1 && a->v2 == b->v2 && a->v3 == b->v3)
+ return 0;
+ else if (a->v3 == b->v1 && a->v1 == b->v2 && a->v2 == b->v3)
+ return 1;
+ else if (a->v2 == b->v1 && a->v3 == b->v2 && a->v1 == b->v3)
+ return 2;
+ }
+
+ return -1;
}
static bool mirror_facecmp(const void *a, const void *b)
{
- return (mirror_facerotation((MFace *)a, (MFace *)b) == -1);
+ return (mirror_facerotation((MFace *)a, (MFace *)b) == -1);
}
/* This is a Mesh-based copy of mesh_get_x_mirror_faces() */
int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, Mesh *me_eval)
{
- Mesh *me = ob->data;
- MVert *mv, *mvert;
- MFace mirrormf, *mf, *hashmf, *mface;
- GHash *fhash;
- int *mirrorverts, *mirrorfaces;
+ Mesh *me = ob->data;
+ MVert *mv, *mvert;
+ MFace mirrormf, *mf, *hashmf, *mface;
+ GHash *fhash;
+ int *mirrorverts, *mirrorfaces;
- BLI_assert(em == NULL); /* Does not work otherwise, currently... */
+ BLI_assert(em == NULL); /* Does not work otherwise, currently... */
- const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
- const int totvert = me_eval ? me_eval->totvert : me->totvert;
- const int totface = me_eval ? me_eval->totface : me->totface;
- int a;
+ const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+ const int totvert = me_eval ? me_eval->totvert : me->totvert;
+ const int totface = me_eval ? me_eval->totface : me->totface;
+ int a;
- mirrorverts = MEM_callocN(sizeof(int) * totvert, "MirrorVerts");
- mirrorfaces = MEM_callocN(sizeof(int) * 2 * totface, "MirrorFaces");
+ mirrorverts = MEM_callocN(sizeof(int) * totvert, "MirrorVerts");
+ mirrorfaces = MEM_callocN(sizeof(int) * 2 * totface, "MirrorFaces");
- mvert = me_eval ? me_eval->mvert : me->mvert;
- mface = me_eval ? me_eval->mface : me->mface;
+ 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(ob, em, me_eval, NULL, 's');
- for (a = 0, mv = mvert; a < totvert; a++, mv++)
- mirrorverts[a] = mesh_get_x_mirror_vert(ob, me_eval, a, use_topology);
+ 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(ob, em, me_eval, NULL, 'e');
- fhash = BLI_ghash_new_ex(mirror_facehash, mirror_facecmp, "mirror_facehash gh", me->totface);
- for (a = 0, mf = mface; a < totface; a++, mf++)
- BLI_ghash_insert(fhash, mf, mf);
+ fhash = BLI_ghash_new_ex(mirror_facehash, mirror_facecmp, "mirror_facehash gh", me->totface);
+ for (a = 0, mf = mface; a < totface; a++, mf++)
+ BLI_ghash_insert(fhash, mf, mf);
- for (a = 0, mf = mface; a < totface; a++, mf++) {
- mirrormf.v1 = mirrorverts[mf->v3];
- mirrormf.v2 = mirrorverts[mf->v2];
- mirrormf.v3 = mirrorverts[mf->v1];
- mirrormf.v4 = (mf->v4) ? mirrorverts[mf->v4] : 0;
+ for (a = 0, mf = mface; a < totface; a++, mf++) {
+ mirrormf.v1 = mirrorverts[mf->v3];
+ mirrormf.v2 = mirrorverts[mf->v2];
+ mirrormf.v3 = mirrorverts[mf->v1];
+ mirrormf.v4 = (mf->v4) ? mirrorverts[mf->v4] : 0;
- /* 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);
- }
+ /* 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);
+ }
- hashmf = BLI_ghash_lookup(fhash, &mirrormf);
- if (hashmf) {
- mirrorfaces[a * 2] = hashmf - mface;
- mirrorfaces[a * 2 + 1] = mirror_facerotation(&mirrormf, hashmf);
- }
- else
- mirrorfaces[a * 2] = -1;
- }
+ hashmf = BLI_ghash_lookup(fhash, &mirrormf);
+ if (hashmf) {
+ mirrorfaces[a * 2] = hashmf - mface;
+ mirrorfaces[a * 2 + 1] = mirror_facerotation(&mirrormf, hashmf);
+ }
+ else
+ mirrorfaces[a * 2] = -1;
+ }
- BLI_ghash_free(fhash, NULL, NULL);
- MEM_freeN(mirrorverts);
+ BLI_ghash_free(fhash, NULL, NULL);
+ MEM_freeN(mirrorverts);
- return mirrorfaces;
+ return mirrorfaces;
}
/* selection, vertex and face */
@@ -1014,147 +1072,148 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, Mesh *me_eval)
*
* \return boolean true == Found
*/
-bool ED_mesh_pick_face(
- bContext *C, Object *ob, const int mval[2], uint dist_px,
- uint *r_index)
+bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px, uint *r_index)
{
- ViewContext vc;
- Mesh *me = ob->data;
+ ViewContext vc;
+ Mesh *me = ob->data;
- BLI_assert(me && GS(me->id.name) == ID_ME);
+ BLI_assert(me && GS(me->id.name) == ID_ME);
- if (!me || me->totpoly == 0)
- return false;
+ if (!me || me->totpoly == 0)
+ return false;
- ED_view3d_viewcontext_init(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
- if (dist_px) {
- /* sample rect to increase chances of selecting, so that when clicking
- * on an edge in the backbuf, we can still select a face */
+ if (dist_px) {
+ /* sample rect to increase chances of selecting, so that when clicking
+ * on an edge in the backbuf, we can still select a face */
- ED_view3d_select_id_validate(&vc);
+ ED_view3d_select_id_validate(&vc);
- *r_index = ED_view3d_select_id_read_nearest(
- &vc, mval, 1, me->totpoly + 1, &dist_px);
- }
- else {
- /* sample only on the exact position */
- *r_index = ED_view3d_select_id_sample(&vc, mval[0], mval[1]);
- }
+ *r_index = ED_view3d_select_id_read_nearest(&vc, mval, 1, me->totpoly + 1, &dist_px);
+ }
+ else {
+ /* sample only on the exact position */
+ *r_index = ED_view3d_select_id_sample(&vc, mval[0], mval[1]);
+ }
- if ((*r_index) == 0 || (*r_index) > (unsigned int)me->totpoly) {
- return false;
- }
+ if ((*r_index) == 0 || (*r_index) > (unsigned int)me->totpoly) {
+ return false;
+ }
- (*r_index)--;
+ (*r_index)--;
- return true;
+ return true;
}
static void ed_mesh_pick_face_vert__mpoly_find(
- /* context */
- struct ARegion *ar, const float mval[2],
- /* mesh data (evaluated) */
- const MPoly *mp,
- const MVert *mvert, const MLoop *mloop,
- /* return values */
- float *r_len_best, int *r_v_idx_best)
+ /* context */
+ struct ARegion *ar,
+ const float mval[2],
+ /* mesh data (evaluated) */
+ const MPoly *mp,
+ const MVert *mvert,
+ const MLoop *mloop,
+ /* return values */
+ float *r_len_best,
+ int *r_v_idx_best)
{
- const MLoop *ml;
- int j = mp->totloop;
- for (ml = &mloop[mp->loopstart]; j--; ml++) {
- 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) {
- const float len_test = len_manhattan_v2v2(mval, sco);
- if (len_test < *r_len_best) {
- *r_len_best = len_test;
- *r_v_idx_best = v_idx;
- }
- }
- }
+ const MLoop *ml;
+ int j = mp->totloop;
+ for (ml = &mloop[mp->loopstart]; j--; ml++) {
+ 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) {
+ const float len_test = len_manhattan_v2v2(mval, sco);
+ if (len_test < *r_len_best) {
+ *r_len_best = len_test;
+ *r_v_idx_best = v_idx;
+ }
+ }
+ }
}
/**
* Use when the back buffer stores face index values. but we want a vert.
* This gets the face then finds the closest vertex to mval.
*/
bool ED_mesh_pick_face_vert(
- bContext *C, Object *ob, const int mval[2], uint dist_px,
- uint *r_index)
+ bContext *C, Object *ob, const int mval[2], uint dist_px, uint *r_index)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- unsigned int poly_index;
- Mesh *me = ob->data;
-
- BLI_assert(me && GS(me->id.name) == ID_ME);
-
- 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);
-
- /* derived mesh to find deformed locations */
- Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH_ORIGINDEX);
-
- int v_idx_best = ORIGINDEX_NONE;
-
- /* find the vert closest to 'mval' */
- const float mval_f[2] = {UNPACK2(mval)};
- float len_best = FLT_MAX;
-
- MPoly *me_eval_mpoly;
- MLoop *me_eval_mloop;
- MVert *me_eval_mvert;
- unsigned int me_eval_mpoly_len;
- const int *index_mp_to_orig;
-
- me_eval_mpoly = me_eval->mpoly;
- me_eval_mloop = me_eval->mloop;
- me_eval_mvert = me_eval->mvert;
-
- me_eval_mpoly_len = me_eval->totpoly;
-
- index_mp_to_orig = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX);
-
- /* tag all verts using this face */
- if (index_mp_to_orig) {
- unsigned int 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);
- }
- }
- }
- else {
- if (poly_index < me_eval_mpoly_len) {
- ed_mesh_pick_face_vert__mpoly_find(
- ar, mval_f,
- &me_eval_mpoly[poly_index], me_eval_mvert, me_eval_mloop,
- &len_best, &v_idx_best);
- }
- }
-
- /* map 'dm -> me' r_index if possible */
- if (v_idx_best != ORIGINDEX_NONE) {
- const int *index_mv_to_orig;
- index_mv_to_orig = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
- if (index_mv_to_orig) {
- v_idx_best = index_mv_to_orig[v_idx_best];
- }
- }
-
- if ((v_idx_best != ORIGINDEX_NONE) && (v_idx_best < me->totvert)) {
- *r_index = v_idx_best;
- return true;
- }
- }
-
- return false;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ unsigned int poly_index;
+ Mesh *me = ob->data;
+
+ BLI_assert(me && GS(me->id.name) == ID_ME);
+
+ 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);
+
+ /* derived mesh to find deformed locations */
+ Mesh *me_eval = mesh_get_eval_final(
+ depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH_ORIGINDEX);
+
+ int v_idx_best = ORIGINDEX_NONE;
+
+ /* find the vert closest to 'mval' */
+ const float mval_f[2] = {UNPACK2(mval)};
+ float len_best = FLT_MAX;
+
+ MPoly *me_eval_mpoly;
+ MLoop *me_eval_mloop;
+ MVert *me_eval_mvert;
+ unsigned int me_eval_mpoly_len;
+ const int *index_mp_to_orig;
+
+ me_eval_mpoly = me_eval->mpoly;
+ me_eval_mloop = me_eval->mloop;
+ me_eval_mvert = me_eval->mvert;
+
+ me_eval_mpoly_len = me_eval->totpoly;
+
+ index_mp_to_orig = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX);
+
+ /* tag all verts using this face */
+ if (index_mp_to_orig) {
+ unsigned int 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);
+ }
+ }
+ }
+ else {
+ if (poly_index < me_eval_mpoly_len) {
+ ed_mesh_pick_face_vert__mpoly_find(ar,
+ mval_f,
+ &me_eval_mpoly[poly_index],
+ me_eval_mvert,
+ me_eval_mloop,
+ &len_best,
+ &v_idx_best);
+ }
+ }
+
+ /* map 'dm -> me' r_index if possible */
+ if (v_idx_best != ORIGINDEX_NONE) {
+ const int *index_mv_to_orig;
+ index_mv_to_orig = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
+ if (index_mv_to_orig) {
+ v_idx_best = index_mv_to_orig[v_idx_best];
+ }
+ }
+
+ if ((v_idx_best != ORIGINDEX_NONE) && (v_idx_best < me->totvert)) {
+ *r_index = v_idx_best;
+ return true;
+ }
+ }
+
+ return false;
}
/**
@@ -1164,196 +1223,199 @@ bool ED_mesh_pick_face_vert(
* \return boolean true == Found
*/
typedef struct VertPickData {
- const MVert *mvert;
- const float *mval_f; /* [2] */
- ARegion *ar;
+ const MVert *mvert;
+ const float *mval_f; /* [2] */
+ ARegion *ar;
- /* runtime */
- float len_best;
- int v_idx_best;
+ /* runtime */
+ float len_best;
+ int v_idx_best;
} VertPickData;
-static void ed_mesh_pick_vert__mapFunc(void *userData, int index, const float co[3],
- const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+static void ed_mesh_pick_vert__mapFunc(void *userData,
+ int index,
+ const float co[3],
+ const float UNUSED(no_f[3]),
+ const short UNUSED(no_s[3]))
{
- VertPickData *data = 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) == V3D_PROJ_RET_OK) {
- const float len = len_manhattan_v2v2(data->mval_f, sco);
- if (len < data->len_best) {
- data->len_best = len;
- data->v_idx_best = index;
- }
- }
- }
+ VertPickData *data = 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) ==
+ V3D_PROJ_RET_OK) {
+ const float len = len_manhattan_v2v2(data->mval_f, sco);
+ if (len < data->len_best) {
+ data->len_best = len;
+ data->v_idx_best = index;
+ }
+ }
+ }
}
bool ED_mesh_pick_vert(
- bContext *C, Object *ob, const int mval[2], uint dist_px, bool use_zbuf,
- uint *r_index)
+ bContext *C, Object *ob, const int mval[2], uint dist_px, bool use_zbuf, uint *r_index)
{
- ViewContext vc;
- Mesh *me = ob->data;
+ ViewContext vc;
+ Mesh *me = ob->data;
- BLI_assert(me && GS(me->id.name) == ID_ME);
+ BLI_assert(me && GS(me->id.name) == ID_ME);
- if (!me || me->totvert == 0)
- return false;
+ if (!me || me->totvert == 0)
+ return false;
- ED_view3d_viewcontext_init(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
- if (use_zbuf) {
- if (dist_px > 0) {
- /* sample rect to increase chances of selecting, so that when clicking
- * on an face in the backbuf, we can still select a vert */
+ if (use_zbuf) {
+ if (dist_px > 0) {
+ /* sample rect to increase chances of selecting, so that when clicking
+ * on an face in the backbuf, we can still select a vert */
- ED_view3d_select_id_validate(&vc);
+ ED_view3d_select_id_validate(&vc);
- *r_index = ED_view3d_select_id_read_nearest(
- &vc, mval, 1, me->totvert + 1, &dist_px);
- }
- else {
- /* sample only on the exact position */
- *r_index = ED_view3d_select_id_sample(&vc, mval[0], mval[1]);
- }
+ *r_index = ED_view3d_select_id_read_nearest(&vc, mval, 1, me->totvert + 1, &dist_px);
+ }
+ else {
+ /* sample only on the exact position */
+ *r_index = ED_view3d_select_id_sample(&vc, mval[0], mval[1]);
+ }
- if ((*r_index) == 0 || (*r_index) > (uint)me->totvert) {
- return false;
- }
+ if ((*r_index) == 0 || (*r_index) > (uint)me->totvert) {
+ return false;
+ }
- (*r_index)--;
- }
- else {
- Scene *scene_eval = DEG_get_evaluated_scene(vc.depsgraph);
- Object *ob_eval = DEG_get_evaluated_object(vc.depsgraph, ob);
+ (*r_index)--;
+ }
+ else {
+ Scene *scene_eval = DEG_get_evaluated_scene(vc.depsgraph);
+ Object *ob_eval = DEG_get_evaluated_object(vc.depsgraph, ob);
- /* 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;
+ /* 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;
- /* find the vert closest to 'mval' */
- const float mval_f[2] = {(float)mval[0],
- (float)mval[1]};
+ /* find the vert closest to 'mval' */
+ const float mval_f[2] = {(float)mval[0], (float)mval[1]};
- VertPickData data = {NULL};
+ VertPickData data = {NULL};
- ED_view3d_init_mats_rv3d(ob, rv3d);
+ ED_view3d_init_mats_rv3d(ob, rv3d);
- if (me_eval == NULL) {
- return false;
- }
+ if (me_eval == NULL) {
+ return false;
+ }
- /* setup data */
- data.mvert = me->mvert;
- data.ar = ar;
- data.mval_f = mval_f;
- data.len_best = FLT_MAX;
- data.v_idx_best = -1;
+ /* setup data */
+ data.mvert = me->mvert;
+ data.ar = ar;
+ data.mval_f = mval_f;
+ data.len_best = FLT_MAX;
+ data.v_idx_best = -1;
- BKE_mesh_foreach_mapped_vert(me_eval, ed_mesh_pick_vert__mapFunc, &data, MESH_FOREACH_NOP);
+ BKE_mesh_foreach_mapped_vert(me_eval, ed_mesh_pick_vert__mapFunc, &data, MESH_FOREACH_NOP);
- if (data.v_idx_best == -1) {
- return false;
- }
+ if (data.v_idx_best == -1) {
+ return false;
+ }
- *r_index = data.v_idx_best;
- }
+ *r_index = data.v_idx_best;
+ }
- return true;
+ return true;
}
-
MDeformVert *ED_mesh_active_dvert_get_em(Object *ob, BMVert **r_eve)
{
- if (ob->mode & OB_MODE_EDIT && ob->type == OB_MESH && ob->defbase.first) {
- Mesh *me = ob->data;
- BMesh *bm = me->edit_mesh->bm;
- const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
-
- if (cd_dvert_offset != -1) {
- BMVert *eve = BM_mesh_active_vert_get(bm);
-
- if (eve) {
- if (r_eve) *r_eve = eve;
- return BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- }
- }
- }
-
- if (r_eve) *r_eve = NULL;
- return NULL;
+ if (ob->mode & OB_MODE_EDIT && ob->type == OB_MESH && ob->defbase.first) {
+ Mesh *me = ob->data;
+ BMesh *bm = me->edit_mesh->bm;
+ const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
+
+ if (cd_dvert_offset != -1) {
+ BMVert *eve = BM_mesh_active_vert_get(bm);
+
+ if (eve) {
+ if (r_eve)
+ *r_eve = eve;
+ return BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+ }
+ }
+ }
+
+ if (r_eve)
+ *r_eve = NULL;
+ return NULL;
}
MDeformVert *ED_mesh_active_dvert_get_ob(Object *ob, int *r_index)
{
- Mesh *me = ob->data;
- int index = BKE_mesh_mselect_active_get(me, ME_VSEL);
- if (r_index) *r_index = index;
- if (index == -1 || me->dvert == NULL) {
- return NULL;
- }
- else {
- return me->dvert + index;
- }
+ Mesh *me = ob->data;
+ int index = BKE_mesh_mselect_active_get(me, ME_VSEL);
+ if (r_index)
+ *r_index = index;
+ if (index == -1 || me->dvert == NULL) {
+ return NULL;
+ }
+ else {
+ return me->dvert + index;
+ }
}
MDeformVert *ED_mesh_active_dvert_get_only(Object *ob)
{
- if (ob->type == OB_MESH) {
- if (ob->mode & OB_MODE_EDIT) {
- return ED_mesh_active_dvert_get_em(ob, NULL);
- }
- else {
- return ED_mesh_active_dvert_get_ob(ob, NULL);
- }
- }
- else {
- return NULL;
- }
+ if (ob->type == OB_MESH) {
+ if (ob->mode & OB_MODE_EDIT) {
+ return ED_mesh_active_dvert_get_em(ob, NULL);
+ }
+ else {
+ return ED_mesh_active_dvert_get_ob(ob, NULL);
+ }
+ }
+ else {
+ return NULL;
+ }
}
-void EDBM_mesh_stats_multi(
- struct Object **objects, const uint objects_len,
- int totelem[3], int totelem_sel[3])
+void EDBM_mesh_stats_multi(struct Object **objects,
+ const uint objects_len,
+ int totelem[3],
+ int totelem_sel[3])
{
- if (totelem) {
- totelem[0] = 0;
- totelem[1] = 0;
- totelem[2] = 0;
- }
- if (totelem_sel) {
- totelem_sel[0] = 0;
- totelem_sel[1] = 0;
- totelem_sel[2] = 0;
- }
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- if (totelem) {
- totelem[0] += bm->totvert;
- totelem[1] += bm->totedge;
- totelem[2] += bm->totface;
- }
- if (totelem_sel) {
- totelem_sel[0] += bm->totvertsel;
- totelem_sel[1] += bm->totedgesel;
- totelem_sel[2] += bm->totfacesel;
- }
- }
+ if (totelem) {
+ totelem[0] = 0;
+ totelem[1] = 0;
+ totelem[2] = 0;
+ }
+ if (totelem_sel) {
+ totelem_sel[0] = 0;
+ totelem_sel[1] = 0;
+ totelem_sel[2] = 0;
+ }
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ if (totelem) {
+ totelem[0] += bm->totvert;
+ totelem[1] += bm->totedge;
+ totelem[2] += bm->totface;
+ }
+ if (totelem_sel) {
+ totelem_sel[0] += bm->totvertsel;
+ totelem_sel[1] += bm->totedgesel;
+ totelem_sel[2] += bm->totfacesel;
+ }
+ }
}
-
void EDBM_mesh_elem_index_ensure_multi(Object **objects, const uint objects_len, const char htype)
{
- int elem_offset[4] = {0, 0, 0, 0};
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BM_mesh_elem_index_ensure_ex(bm, htype, elem_offset);
- }
+ int elem_offset[4] = {0, 0, 0, 0};
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BM_mesh_elem_index_ensure_ex(bm, htype, elem_offset);
+ }
}
diff --git a/source/blender/editors/metaball/CMakeLists.txt b/source/blender/editors/metaball/CMakeLists.txt
index 11547a0af6f..72105ddb00a 100644
--- a/source/blender/editors/metaball/CMakeLists.txt
+++ b/source/blender/editors/metaball/CMakeLists.txt
@@ -16,16 +16,16 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../depsgraph
- ../../makesdna
- ../../makesrna
- ../../render/extern/include
- ../../windowmanager
- ../../../../intern/clog
- ../../../../intern/guardedalloc
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../depsgraph
+ ../../makesdna
+ ../../makesrna
+ ../../render/extern/include
+ ../../windowmanager
+ ../../../../intern/clog
+ ../../../../intern/guardedalloc
)
set(INC_SYS
@@ -33,11 +33,11 @@ set(INC_SYS
)
set(SRC
- editmball_undo.c
- mball_edit.c
- mball_ops.c
+ editmball_undo.c
+ mball_edit.c
+ mball_ops.c
- mball_intern.h
+ mball_intern.h
)
set(LIB
diff --git a/source/blender/editors/metaball/editmball_undo.c b/source/blender/editors/metaball/editmball_undo.c
index af6f78c7bcb..d255fac26ad 100644
--- a/source/blender/editors/metaball/editmball_undo.c
+++ b/source/blender/editors/metaball/editmball_undo.c
@@ -55,78 +55,78 @@ static CLG_LogRef LOG = {"ed.undo.mball"};
* \{ */
typedef struct UndoMBall {
- ListBase editelems;
- int lastelem_index;
- size_t undo_size;
+ ListBase editelems;
+ int lastelem_index;
+ size_t undo_size;
} UndoMBall;
/* free all MetaElems from ListBase */
static void freeMetaElemlist(ListBase *lb)
{
- MetaElem *ml;
+ MetaElem *ml;
- if (lb == NULL) {
- return;
- }
+ if (lb == NULL) {
+ return;
+ }
- while ((ml = BLI_pophead(lb))) {
- MEM_freeN(ml);
- }
+ while ((ml = BLI_pophead(lb))) {
+ MEM_freeN(ml);
+ }
}
static void undomball_to_editmball(UndoMBall *umb, MetaBall *mb)
{
- freeMetaElemlist(mb->editelems);
- mb->lastelem = NULL;
-
- /* copy 'undo' MetaElems to 'edit' MetaElems */
- int index = 0;
- for (MetaElem *ml_undo = umb->editelems.first; ml_undo; ml_undo = ml_undo->next, index += 1) {
- MetaElem *ml_edit = MEM_dupallocN(ml_undo);
- BLI_addtail(mb->editelems, ml_edit);
- if (index == umb->lastelem_index) {
- mb->lastelem = ml_edit;
- }
- }
+ freeMetaElemlist(mb->editelems);
+ mb->lastelem = NULL;
+
+ /* copy 'undo' MetaElems to 'edit' MetaElems */
+ int index = 0;
+ for (MetaElem *ml_undo = umb->editelems.first; ml_undo; ml_undo = ml_undo->next, index += 1) {
+ MetaElem *ml_edit = MEM_dupallocN(ml_undo);
+ BLI_addtail(mb->editelems, ml_edit);
+ if (index == umb->lastelem_index) {
+ mb->lastelem = ml_edit;
+ }
+ }
}
static void *editmball_from_undomball(UndoMBall *umb, MetaBall *mb)
{
- BLI_assert(BLI_array_is_zeroed(umb, 1));
-
- /* allocate memory for undo ListBase */
- umb->lastelem_index = -1;
-
- /* copy contents of current ListBase to the undo ListBase */
- int index = 0;
- for (MetaElem *ml_edit = mb->editelems->first; ml_edit; ml_edit = ml_edit->next, index += 1) {
- MetaElem *ml_undo = MEM_dupallocN(ml_edit);
- BLI_addtail(&umb->editelems, ml_undo);
- if (ml_edit == mb->lastelem) {
- umb->lastelem_index = index;
- }
- umb->undo_size += sizeof(MetaElem);
- }
-
- return umb;
+ BLI_assert(BLI_array_is_zeroed(umb, 1));
+
+ /* allocate memory for undo ListBase */
+ umb->lastelem_index = -1;
+
+ /* copy contents of current ListBase to the undo ListBase */
+ int index = 0;
+ for (MetaElem *ml_edit = mb->editelems->first; ml_edit; ml_edit = ml_edit->next, index += 1) {
+ MetaElem *ml_undo = MEM_dupallocN(ml_edit);
+ BLI_addtail(&umb->editelems, ml_undo);
+ if (ml_edit == mb->lastelem) {
+ umb->lastelem_index = index;
+ }
+ umb->undo_size += sizeof(MetaElem);
+ }
+
+ return umb;
}
/* free undo ListBase of MetaElems */
static void undomball_free_data(UndoMBall *umb)
{
- freeMetaElemlist(&umb->editelems);
+ freeMetaElemlist(&umb->editelems);
}
static Object *editmball_object_from_context(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_MBALL) {
- MetaBall *mb = obedit->data;
- if (mb->editelems != NULL) {
- return obedit;
- }
- }
- return NULL;
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_MBALL) {
+ MetaBall *mb = obedit->data;
+ if (mb->editelems != NULL) {
+ return obedit;
+ }
+ }
+ return NULL;
}
/** \} */
@@ -138,112 +138,123 @@ static Object *editmball_object_from_context(bContext *C)
* \{ */
typedef struct MBallUndoStep_Elem {
- UndoRefID_Object obedit_ref;
- UndoMBall data;
+ UndoRefID_Object obedit_ref;
+ UndoMBall data;
} MBallUndoStep_Elem;
typedef struct MBallUndoStep {
- UndoStep step;
- MBallUndoStep_Elem *elems;
- uint elems_len;
+ UndoStep step;
+ MBallUndoStep_Elem *elems;
+ uint elems_len;
} MBallUndoStep;
static bool mball_undosys_poll(bContext *C)
{
- return editmball_object_from_context(C) != NULL;
+ return editmball_object_from_context(C) != NULL;
}
-static bool mball_undosys_step_encode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p)
+static bool mball_undosys_step_encode(struct bContext *C,
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p)
{
- MBallUndoStep *us = (MBallUndoStep *)us_p;
-
- /* Important not to use the 3D view when getting objects because all objects
- * 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);
-
- us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
- us->elems_len = objects_len;
-
- for (uint i = 0; i < objects_len; i++) {
- Object *ob = objects[i];
- MBallUndoStep_Elem *elem = &us->elems[i];
-
- elem->obedit_ref.ptr = ob;
- MetaBall *mb = ob->data;
- editmball_from_undomball(&elem->data, mb);
- us->step.data_size += elem->data.undo_size;
- }
- MEM_freeN(objects);
- return true;
+ MBallUndoStep *us = (MBallUndoStep *)us_p;
+
+ /* Important not to use the 3D view when getting objects because all objects
+ * 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);
+
+ us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
+ us->elems_len = objects_len;
+
+ for (uint i = 0; i < objects_len; i++) {
+ Object *ob = objects[i];
+ MBallUndoStep_Elem *elem = &us->elems[i];
+
+ elem->obedit_ref.ptr = ob;
+ MetaBall *mb = ob->data;
+ editmball_from_undomball(&elem->data, mb);
+ us->step.data_size += elem->data.undo_size;
+ }
+ MEM_freeN(objects);
+ return true;
}
-static void mball_undosys_step_decode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p, int UNUSED(dir))
+static void mball_undosys_step_decode(struct bContext *C,
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p,
+ int UNUSED(dir))
{
- MBallUndoStep *us = (MBallUndoStep *)us_p;
-
- /* Load all our objects into edit-mode, clear everything else. */
- ED_undo_object_editmode_restore_helper(C, &us->elems[0].obedit_ref.ptr, us->elems_len, sizeof(*us->elems));
-
- BLI_assert(mball_undosys_poll(C));
-
- for (uint i = 0; i < us->elems_len; i++) {
- MBallUndoStep_Elem *elem = &us->elems[i];
- Object *obedit = elem->obedit_ref.ptr;
- MetaBall *mb = obedit->data;
- if (mb->editelems == NULL) {
- /* Should never fail, may not crash but can give odd behavior. */
- CLOG_ERROR(&LOG, "name='%s', failed to enter edit-mode for object '%s', undo state invalid", us_p->name, obedit->id.name);
- continue;
- }
- undomball_to_editmball(&elem->data, mb);
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
-
- /* The first element is always active */
- ED_undo_object_set_active_or_warn(CTX_data_view_layer(C), us->elems[0].obedit_ref.ptr, us_p->name, &LOG);
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+ MBallUndoStep *us = (MBallUndoStep *)us_p;
+
+ /* Load all our objects into edit-mode, clear everything else. */
+ ED_undo_object_editmode_restore_helper(
+ C, &us->elems[0].obedit_ref.ptr, us->elems_len, sizeof(*us->elems));
+
+ BLI_assert(mball_undosys_poll(C));
+
+ for (uint i = 0; i < us->elems_len; i++) {
+ MBallUndoStep_Elem *elem = &us->elems[i];
+ Object *obedit = elem->obedit_ref.ptr;
+ MetaBall *mb = obedit->data;
+ if (mb->editelems == NULL) {
+ /* Should never fail, may not crash but can give odd behavior. */
+ CLOG_ERROR(&LOG,
+ "name='%s', failed to enter edit-mode for object '%s', undo state invalid",
+ us_p->name,
+ obedit->id.name);
+ continue;
+ }
+ undomball_to_editmball(&elem->data, mb);
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ }
+
+ /* The first element is always active */
+ ED_undo_object_set_active_or_warn(
+ CTX_data_view_layer(C), us->elems[0].obedit_ref.ptr, us_p->name, &LOG);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
}
static void mball_undosys_step_free(UndoStep *us_p)
{
- MBallUndoStep *us = (MBallUndoStep *)us_p;
+ MBallUndoStep *us = (MBallUndoStep *)us_p;
- for (uint i = 0; i < us->elems_len; i++) {
- MBallUndoStep_Elem *elem = &us->elems[i];
- undomball_free_data(&elem->data);
- }
- MEM_freeN(us->elems);
+ for (uint i = 0; i < us->elems_len; i++) {
+ MBallUndoStep_Elem *elem = &us->elems[i];
+ undomball_free_data(&elem->data);
+ }
+ MEM_freeN(us->elems);
}
-static void mball_undosys_foreach_ID_ref(
- UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+static void mball_undosys_foreach_ID_ref(UndoStep *us_p,
+ UndoTypeForEachIDRefFn foreach_ID_ref_fn,
+ void *user_data)
{
- MBallUndoStep *us = (MBallUndoStep *)us_p;
+ MBallUndoStep *us = (MBallUndoStep *)us_p;
- for (uint i = 0; i < us->elems_len; i++) {
- MBallUndoStep_Elem *elem = &us->elems[i];
- foreach_ID_ref_fn(user_data, ((UndoRefID *)&elem->obedit_ref));
- }
+ for (uint i = 0; i < us->elems_len; i++) {
+ MBallUndoStep_Elem *elem = &us->elems[i];
+ foreach_ID_ref_fn(user_data, ((UndoRefID *)&elem->obedit_ref));
+ }
}
/* Export for ED_undo_sys. */
void ED_mball_undosys_type(UndoType *ut)
{
- ut->name = "Edit MBall";
- ut->poll = mball_undosys_poll;
- ut->step_encode = mball_undosys_step_encode;
- ut->step_decode = mball_undosys_step_decode;
- ut->step_free = mball_undosys_step_free;
+ ut->name = "Edit MBall";
+ ut->poll = mball_undosys_poll;
+ ut->step_encode = mball_undosys_step_encode;
+ ut->step_decode = mball_undosys_step_decode;
+ ut->step_free = mball_undosys_step_free;
- ut->step_foreach_ID_ref = mball_undosys_foreach_ID_ref;
+ ut->step_foreach_ID_ref = mball_undosys_foreach_ID_ref;
- ut->use_context = true;
-
- ut->step_size = sizeof(MBallUndoStep);
+ ut->use_context = true;
+ ut->step_size = sizeof(MBallUndoStep);
}
/** \} */
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index 5ab6f9e0750..45eb66c228b 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -63,29 +63,29 @@
/* This function is used to free all MetaElems from MetaBall */
void ED_mball_editmball_free(Object *obedit)
{
- MetaBall *mb = (MetaBall *)obedit->data;
+ MetaBall *mb = (MetaBall *)obedit->data;
- mb->editelems = NULL;
- mb->lastelem = NULL;
+ mb->editelems = NULL;
+ mb->lastelem = NULL;
}
/* This function is called, when MetaBall Object is
* switched from object mode to edit mode */
void ED_mball_editmball_make(Object *obedit)
{
- MetaBall *mb = (MetaBall *)obedit->data;
- MetaElem *ml; /*, *newml;*/
+ MetaBall *mb = (MetaBall *)obedit->data;
+ MetaElem *ml; /*, *newml;*/
- ml = mb->elems.first;
+ ml = mb->elems.first;
- while (ml) {
- if (ml->flag & SELECT) {
- mb->lastelem = ml;
- }
- ml = ml->next;
- }
+ while (ml) {
+ if (ml->flag & SELECT) {
+ mb->lastelem = ml;
+ }
+ ml = ml->next;
+ }
- mb->editelems = &mb->elems;
+ mb->editelems = &mb->elems;
}
/* This function is called, when MetaBall Object switched from
@@ -96,27 +96,28 @@ void ED_mball_editmball_load(Object *UNUSED(obedit))
}
/* Add metaelem primitive to metaball object (which is in edit mode) */
-MetaElem *ED_mball_add_primitive(bContext *UNUSED(C), Object *obedit, float mat[4][4], float dia, int type)
+MetaElem *ED_mball_add_primitive(
+ bContext *UNUSED(C), Object *obedit, float mat[4][4], float dia, int type)
{
- MetaBall *mball = (MetaBall *)obedit->data;
- MetaElem *ml;
-
- /* Deselect all existing metaelems */
- ml = mball->editelems->first;
- while (ml) {
- ml->flag &= ~SELECT;
- ml = ml->next;
- }
-
- ml = BKE_mball_element_add(mball, type);
- ml->rad *= dia;
- mball->wiresize *= dia;
- mball->rendersize *= dia;
- copy_v3_v3(&ml->x, mat[3]);
-
- ml->flag |= SELECT;
- mball->lastelem = ml;
- return ml;
+ MetaBall *mball = (MetaBall *)obedit->data;
+ MetaElem *ml;
+
+ /* Deselect all existing metaelems */
+ ml = mball->editelems->first;
+ while (ml) {
+ ml->flag &= ~SELECT;
+ ml = ml->next;
+ }
+
+ ml = BKE_mball_element_add(mball, type);
+ ml->rad *= dia;
+ mball->wiresize *= dia;
+ mball->rendersize *= dia;
+ copy_v3_v3(&ml->x, mat[3]);
+
+ ml->flag |= SELECT;
+ mball->lastelem = ml;
+ return ml;
}
/***************************** Select/Deselect operator *****************************/
@@ -124,384 +125,375 @@ MetaElem *ED_mball_add_primitive(bContext *UNUSED(C), Object *obedit, float mat[
/* Select or deselect all MetaElements */
static int mball_select_all_exec(bContext *C, wmOperator *op)
{
- int action = RNA_enum_get(op->ptr, "action");
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- 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);
-
- if (action == SEL_TOGGLE) {
- action = BKE_mball_is_any_selected_multi(bases, bases_len) ?
- SEL_DESELECT :
- SEL_SELECT;
- }
-
- switch (action) {
- case SEL_SELECT:
- BKE_mball_select_all_multi_ex(bases, bases_len);
- break;
- case SEL_DESELECT:
- BKE_mball_deselect_all_multi_ex(bases, bases_len);
- break;
- case SEL_INVERT:
- BKE_mball_select_swap_multi_ex(bases, bases_len);
- break;
- }
-
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Object *obedit = bases[base_index]->object;
- MetaBall *mb = (MetaBall *)obedit->data;
- DEG_id_tag_update(&mb->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
- }
-
- MEM_freeN(bases);
-
- return OPERATOR_FINISHED;
+ int action = RNA_enum_get(op->ptr, "action");
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ 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);
+
+ if (action == SEL_TOGGLE) {
+ action = BKE_mball_is_any_selected_multi(bases, bases_len) ? SEL_DESELECT : SEL_SELECT;
+ }
+
+ switch (action) {
+ case SEL_SELECT:
+ BKE_mball_select_all_multi_ex(bases, bases_len);
+ break;
+ case SEL_DESELECT:
+ BKE_mball_deselect_all_multi_ex(bases, bases_len);
+ break;
+ case SEL_INVERT:
+ BKE_mball_select_swap_multi_ex(bases, bases_len);
+ break;
+ }
+
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Object *obedit = bases[base_index]->object;
+ MetaBall *mb = (MetaBall *)obedit->data;
+ DEG_id_tag_update(&mb->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
+ }
+
+ MEM_freeN(bases);
+
+ return OPERATOR_FINISHED;
}
void MBALL_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All";
- ot->description = "Change selection of all meta elements";
- ot->idname = "MBALL_OT_select_all";
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->description = "Change selection of all meta elements";
+ ot->idname = "MBALL_OT_select_all";
- /* callback functions */
- ot->exec = mball_select_all_exec;
- ot->poll = ED_operator_editmball;
+ /* callback functions */
+ ot->exec = mball_select_all_exec;
+ ot->poll = ED_operator_editmball;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_select_all(ot);
+ WM_operator_properties_select_all(ot);
}
-
/* -------------------------------------------------------------------- */
/* Select Similar */
enum {
- SIMMBALL_TYPE = 1,
- SIMMBALL_RADIUS,
- SIMMBALL_STIFFNESS,
- SIMMBALL_ROTATION,
+ SIMMBALL_TYPE = 1,
+ SIMMBALL_RADIUS,
+ SIMMBALL_STIFFNESS,
+ SIMMBALL_ROTATION,
};
static const EnumPropertyItem prop_similar_types[] = {
- {SIMMBALL_TYPE, "TYPE", 0, "Type", ""},
- {SIMMBALL_RADIUS, "RADIUS", 0, "Radius", ""},
- {SIMMBALL_STIFFNESS, "STIFFNESS", 0, "Stiffness", ""},
- {SIMMBALL_ROTATION, "ROTATION", 0, "Rotation", ""},
- {0, NULL, 0, NULL, NULL},
+ {SIMMBALL_TYPE, "TYPE", 0, "Type", ""},
+ {SIMMBALL_RADIUS, "RADIUS", 0, "Radius", ""},
+ {SIMMBALL_STIFFNESS, "STIFFNESS", 0, "Stiffness", ""},
+ {SIMMBALL_ROTATION, "ROTATION", 0, "Rotation", ""},
+ {0, NULL, 0, NULL, NULL},
};
static void mball_select_similar_type_get(
- Object *obedit, MetaBall *mb, int type,
- KDTree_1d *tree_1d, KDTree_3d *tree_3d)
+ Object *obedit, MetaBall *mb, int type, KDTree_1d *tree_1d, KDTree_3d *tree_3d)
{
- float tree_entry[3] = {0.0f, 0.0f, 0.0f};
- MetaElem *ml;
- int tree_index = 0;
- for (ml = mb->editelems->first; ml; ml = ml->next) {
- if (ml->flag & SELECT) {
- switch (type) {
- case SIMMBALL_RADIUS:
- {
- float radius = ml->rad;
- /* Radius in world space. */
- float smat[3][3];
- float radius_vec[3] = {radius, radius, radius};
- BKE_object_scale_to_mat3(obedit, smat);
- mul_m3_v3(smat, radius_vec);
- radius = (radius_vec[0] + radius_vec[1] + radius_vec[2]) / 3;
- tree_entry[0] = radius;
- break;
- }
- case SIMMBALL_STIFFNESS:
- {
- tree_entry[0] = ml->s;
- break;
- }
- break;
- case SIMMBALL_ROTATION:
- {
- float dir[3] = {1.0f, 0.0f, 0.0f};
- float rmat[3][3];
- mul_qt_v3(ml->quat, dir);
- BKE_object_rot_to_mat3(obedit, rmat, true);
- mul_m3_v3(rmat, dir);
- copy_v3_v3(tree_entry, dir);
- break;
- }
- }
- if (tree_1d) {
- BLI_kdtree_1d_insert(tree_1d, tree_index++, tree_entry);
- }
- else {
- BLI_kdtree_3d_insert(tree_3d, tree_index++, tree_entry);
- }
- }
- }
+ float tree_entry[3] = {0.0f, 0.0f, 0.0f};
+ MetaElem *ml;
+ int tree_index = 0;
+ for (ml = mb->editelems->first; ml; ml = ml->next) {
+ if (ml->flag & SELECT) {
+ switch (type) {
+ case SIMMBALL_RADIUS: {
+ float radius = ml->rad;
+ /* Radius in world space. */
+ float smat[3][3];
+ float radius_vec[3] = {radius, radius, radius};
+ BKE_object_scale_to_mat3(obedit, smat);
+ mul_m3_v3(smat, radius_vec);
+ radius = (radius_vec[0] + radius_vec[1] + radius_vec[2]) / 3;
+ tree_entry[0] = radius;
+ break;
+ }
+ case SIMMBALL_STIFFNESS: {
+ tree_entry[0] = ml->s;
+ break;
+ } break;
+ case SIMMBALL_ROTATION: {
+ float dir[3] = {1.0f, 0.0f, 0.0f};
+ float rmat[3][3];
+ mul_qt_v3(ml->quat, dir);
+ BKE_object_rot_to_mat3(obedit, rmat, true);
+ mul_m3_v3(rmat, dir);
+ copy_v3_v3(tree_entry, dir);
+ break;
+ }
+ }
+ if (tree_1d) {
+ BLI_kdtree_1d_insert(tree_1d, tree_index++, tree_entry);
+ }
+ else {
+ BLI_kdtree_3d_insert(tree_3d, tree_index++, tree_entry);
+ }
+ }
+ }
}
-static bool mball_select_similar_type(
- Object *obedit, MetaBall *mb, int type,
- const KDTree_1d *tree_1d, const KDTree_3d *tree_3d,
- const float thresh)
+static bool mball_select_similar_type(Object *obedit,
+ MetaBall *mb,
+ int type,
+ const KDTree_1d *tree_1d,
+ const KDTree_3d *tree_3d,
+ const float thresh)
{
- MetaElem *ml;
- bool changed = false;
- for (ml = mb->editelems->first; ml; ml = ml->next) {
- bool select = false;
- switch (type) {
- case SIMMBALL_RADIUS:
- {
- float radius = ml->rad;
- /* Radius in world space is the average of the
- * scaled radius in x, y and z directions. */
- float smat[3][3];
- float radius_vec[3] = {radius, radius, radius};
- BKE_object_scale_to_mat3(obedit, smat);
- mul_m3_v3(smat, radius_vec);
- radius = (radius_vec[0] + radius_vec[1] + radius_vec[2]) / 3;
-
- if (ED_select_similar_compare_float_tree(tree_1d, radius, thresh, SIM_CMP_EQ)) {
- select = true;
- }
- break;
- }
- case SIMMBALL_STIFFNESS:
- {
- float s = ml->s;
- if (ED_select_similar_compare_float_tree(tree_1d, s, thresh, SIM_CMP_EQ)) {
- select = true;
- }
- break;
- }
- case SIMMBALL_ROTATION:
- {
- float dir[3] = {1.0f, 0.0f, 0.0f};
- float rmat[3][3];
- mul_qt_v3(ml->quat, dir);
- BKE_object_rot_to_mat3(obedit, rmat, true);
- mul_m3_v3(rmat, dir);
-
- float thresh_cos = cosf(thresh * (float)M_PI_2);
-
- KDTreeNearest_3d nearest;
- if (BLI_kdtree_3d_find_nearest(tree_3d, dir, &nearest) != -1) {
- float orient = angle_normalized_v3v3(dir, nearest.co);
- /* Map to 0-1 to compare orientation. */
- float delta = thresh_cos - fabsf(cosf(orient));
- if (ED_select_similar_compare_float(delta, thresh, SIM_CMP_EQ)) {
- select = true;
- }
- }
- break;
- }
- }
-
- if (select) {
- changed = true;
- ml->flag |= SELECT;
- }
- }
- return changed;
+ MetaElem *ml;
+ bool changed = false;
+ for (ml = mb->editelems->first; ml; ml = ml->next) {
+ bool select = false;
+ switch (type) {
+ case SIMMBALL_RADIUS: {
+ float radius = ml->rad;
+ /* Radius in world space is the average of the
+ * scaled radius in x, y and z directions. */
+ float smat[3][3];
+ float radius_vec[3] = {radius, radius, radius};
+ BKE_object_scale_to_mat3(obedit, smat);
+ mul_m3_v3(smat, radius_vec);
+ radius = (radius_vec[0] + radius_vec[1] + radius_vec[2]) / 3;
+
+ if (ED_select_similar_compare_float_tree(tree_1d, radius, thresh, SIM_CMP_EQ)) {
+ select = true;
+ }
+ break;
+ }
+ case SIMMBALL_STIFFNESS: {
+ float s = ml->s;
+ if (ED_select_similar_compare_float_tree(tree_1d, s, thresh, SIM_CMP_EQ)) {
+ select = true;
+ }
+ break;
+ }
+ case SIMMBALL_ROTATION: {
+ float dir[3] = {1.0f, 0.0f, 0.0f};
+ float rmat[3][3];
+ mul_qt_v3(ml->quat, dir);
+ BKE_object_rot_to_mat3(obedit, rmat, true);
+ mul_m3_v3(rmat, dir);
+
+ float thresh_cos = cosf(thresh * (float)M_PI_2);
+
+ KDTreeNearest_3d nearest;
+ if (BLI_kdtree_3d_find_nearest(tree_3d, dir, &nearest) != -1) {
+ float orient = angle_normalized_v3v3(dir, nearest.co);
+ /* Map to 0-1 to compare orientation. */
+ float delta = thresh_cos - fabsf(cosf(orient));
+ if (ED_select_similar_compare_float(delta, thresh, SIM_CMP_EQ)) {
+ select = true;
+ }
+ }
+ break;
+ }
+ }
+
+ if (select) {
+ changed = true;
+ ml->flag |= SELECT;
+ }
+ }
+ return changed;
}
static int mball_select_similar_exec(bContext *C, wmOperator *op)
{
- const int type = RNA_enum_get(op->ptr, "type");
- const float thresh = RNA_float_get(op->ptr, "threshold");
- int tot_mball_selected_all = 0;
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- 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);
-
- tot_mball_selected_all = BKE_mball_select_count_multi(bases, bases_len);
-
- short type_ref = 0;
- KDTree_1d *tree_1d = NULL;
- KDTree_3d *tree_3d = NULL;
-
- switch (type) {
- case SIMMBALL_RADIUS:
- case SIMMBALL_STIFFNESS:
- tree_1d = BLI_kdtree_1d_new(tot_mball_selected_all);
- break;
- case SIMMBALL_ROTATION:
- tree_3d = BLI_kdtree_3d_new(tot_mball_selected_all);
- break;
- }
-
- /* Get type of selected MetaBall */
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Object *obedit = bases[base_index]->object;
- MetaBall *mb = (MetaBall *)obedit->data;
-
- switch (type) {
- case SIMMBALL_TYPE:
- {
- MetaElem *ml;
- for (ml = mb->editelems->first; ml; ml = ml->next) {
- if (ml->flag & SELECT) {
- short mball_type = 1 << (ml->type + 1);
- type_ref |= mball_type;
- }
- }
- break;
- }
- case SIMMBALL_RADIUS:
- case SIMMBALL_STIFFNESS:
- case SIMMBALL_ROTATION:
- mball_select_similar_type_get(obedit, mb, type, tree_1d, tree_3d);
- break;
- default:
- BLI_assert(0);
- break;
- }
- }
-
- if (tree_1d != NULL) {
- BLI_kdtree_1d_deduplicate(tree_1d);
- BLI_kdtree_1d_balance(tree_1d);
- }
- if (tree_3d != NULL) {
- BLI_kdtree_3d_deduplicate(tree_3d);
- BLI_kdtree_3d_balance(tree_3d);
- }
- /* Select MetaBalls with desired type. */
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Object *obedit = bases[base_index]->object;
- MetaBall *mb = (MetaBall *)obedit->data;
- bool changed = false;
-
- switch (type) {
- case SIMMBALL_TYPE:
- {
- MetaElem *ml;
- for (ml = mb->editelems->first; ml; ml = ml->next) {
- short mball_type = 1 << (ml->type + 1);
- if (mball_type & type_ref) {
- ml->flag |= SELECT;
- changed = true;
- }
- }
- break;
- }
- case SIMMBALL_RADIUS:
- case SIMMBALL_STIFFNESS:
- case SIMMBALL_ROTATION:
- changed = mball_select_similar_type(obedit, mb, type, tree_1d, tree_3d, thresh);
- break;
- default:
- BLI_assert(0);
- break;
- }
-
- if (changed) {
- DEG_id_tag_update(&mb->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
- }
- }
-
- MEM_freeN(bases);
- if (tree_1d != NULL) {
- BLI_kdtree_1d_free(tree_1d);
- }
- if (tree_3d != NULL) {
- BLI_kdtree_3d_free(tree_3d);
- }
- return OPERATOR_FINISHED;
+ const int type = RNA_enum_get(op->ptr, "type");
+ const float thresh = RNA_float_get(op->ptr, "threshold");
+ int tot_mball_selected_all = 0;
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ 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);
+
+ tot_mball_selected_all = BKE_mball_select_count_multi(bases, bases_len);
+
+ short type_ref = 0;
+ KDTree_1d *tree_1d = NULL;
+ KDTree_3d *tree_3d = NULL;
+
+ switch (type) {
+ case SIMMBALL_RADIUS:
+ case SIMMBALL_STIFFNESS:
+ tree_1d = BLI_kdtree_1d_new(tot_mball_selected_all);
+ break;
+ case SIMMBALL_ROTATION:
+ tree_3d = BLI_kdtree_3d_new(tot_mball_selected_all);
+ break;
+ }
+
+ /* Get type of selected MetaBall */
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Object *obedit = bases[base_index]->object;
+ MetaBall *mb = (MetaBall *)obedit->data;
+
+ switch (type) {
+ case SIMMBALL_TYPE: {
+ MetaElem *ml;
+ for (ml = mb->editelems->first; ml; ml = ml->next) {
+ if (ml->flag & SELECT) {
+ short mball_type = 1 << (ml->type + 1);
+ type_ref |= mball_type;
+ }
+ }
+ break;
+ }
+ case SIMMBALL_RADIUS:
+ case SIMMBALL_STIFFNESS:
+ case SIMMBALL_ROTATION:
+ mball_select_similar_type_get(obedit, mb, type, tree_1d, tree_3d);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+ }
+
+ if (tree_1d != NULL) {
+ BLI_kdtree_1d_deduplicate(tree_1d);
+ BLI_kdtree_1d_balance(tree_1d);
+ }
+ if (tree_3d != NULL) {
+ BLI_kdtree_3d_deduplicate(tree_3d);
+ BLI_kdtree_3d_balance(tree_3d);
+ }
+ /* Select MetaBalls with desired type. */
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Object *obedit = bases[base_index]->object;
+ MetaBall *mb = (MetaBall *)obedit->data;
+ bool changed = false;
+
+ switch (type) {
+ case SIMMBALL_TYPE: {
+ MetaElem *ml;
+ for (ml = mb->editelems->first; ml; ml = ml->next) {
+ short mball_type = 1 << (ml->type + 1);
+ if (mball_type & type_ref) {
+ ml->flag |= SELECT;
+ changed = true;
+ }
+ }
+ break;
+ }
+ case SIMMBALL_RADIUS:
+ case SIMMBALL_STIFFNESS:
+ case SIMMBALL_ROTATION:
+ changed = mball_select_similar_type(obedit, mb, type, tree_1d, tree_3d, thresh);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ if (changed) {
+ DEG_id_tag_update(&mb->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
+ }
+ }
+
+ MEM_freeN(bases);
+ if (tree_1d != NULL) {
+ BLI_kdtree_1d_free(tree_1d);
+ }
+ if (tree_3d != NULL) {
+ BLI_kdtree_3d_free(tree_3d);
+ }
+ return OPERATOR_FINISHED;
}
void MBALL_OT_select_similar(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Similar";
- ot->idname = "MBALL_OT_select_similar";
+ /* identifiers */
+ ot->name = "Select Similar";
+ ot->idname = "MBALL_OT_select_similar";
- /* callback functions */
- ot->invoke = WM_menu_invoke;
- ot->exec = mball_select_similar_exec;
- ot->poll = ED_operator_editmball;
- ot->description = "Select similar metaballs by property types";
+ /* callback functions */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = mball_select_similar_exec;
+ ot->poll = ED_operator_editmball;
+ ot->description = "Select similar metaballs by property types";
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, 0, "Type", "");
- RNA_def_float(ot->srna, "threshold", 0.1, 0.0, FLT_MAX, "Threshold", "", 0.01, 1.0);
+ RNA_def_float(ot->srna, "threshold", 0.1, 0.0, FLT_MAX, "Threshold", "", 0.01, 1.0);
}
-
/***************************** Select random operator *****************************/
/* Random metaball selection */
static int select_random_metaelems_exec(bContext *C, wmOperator *op)
{
- const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
- const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
- const int seed = WM_operator_properties_select_random_seed_increment_get(op);
-
- 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];
- MetaBall *mb = (MetaBall *)obedit->data;
- if (!BKE_mball_is_any_unselected(mb)) {
- continue;
- }
- int seed_iter = seed;
-
- /* This gives a consistent result regardless of object order. */
- if (ob_index) {
- seed_iter += BLI_ghashutil_strhash_p(obedit->id.name);
- }
-
- RNG *rng = BLI_rng_new_srandom(seed_iter);
-
- for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) {
- if (BLI_rng_get_float(rng) < randfac) {
- if (select) {
- ml->flag |= SELECT;
- }
- else {
- ml->flag &= ~SELECT;
- }
- }
- }
-
- BLI_rng_free(rng);
-
- DEG_id_tag_update(&mb->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
+ const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
+ const int seed = WM_operator_properties_select_random_seed_increment_get(op);
+
+ 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];
+ MetaBall *mb = (MetaBall *)obedit->data;
+ if (!BKE_mball_is_any_unselected(mb)) {
+ continue;
+ }
+ int seed_iter = seed;
+
+ /* This gives a consistent result regardless of object order. */
+ if (ob_index) {
+ seed_iter += BLI_ghashutil_strhash_p(obedit->id.name);
+ }
+
+ RNG *rng = BLI_rng_new_srandom(seed_iter);
+
+ for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) {
+ if (BLI_rng_get_float(rng) < randfac) {
+ if (select) {
+ ml->flag |= SELECT;
+ }
+ else {
+ ml->flag &= ~SELECT;
+ }
+ }
+ }
+
+ BLI_rng_free(rng);
+
+ DEG_id_tag_update(&mb->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MBALL_OT_select_random_metaelems(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Random";
- ot->description = "Randomly select metaelements";
- ot->idname = "MBALL_OT_select_random_metaelems";
+ /* identifiers */
+ ot->name = "Select Random";
+ ot->description = "Randomly select metaelements";
+ ot->idname = "MBALL_OT_select_random_metaelems";
- /* callback functions */
- ot->exec = select_random_metaelems_exec;
- ot->poll = ED_operator_editmball;
+ /* callback functions */
+ ot->exec = select_random_metaelems_exec;
+ ot->poll = ED_operator_editmball;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_select_random(ot);
+ /* properties */
+ WM_operator_properties_select_random(ot);
}
/***************************** Duplicate operator *****************************/
@@ -509,50 +501,51 @@ void MBALL_OT_select_random_metaelems(struct wmOperatorType *ot)
/* Duplicate selected MetaElements */
static int duplicate_metaelems_exec(bContext *C, wmOperator *UNUSED(op))
{
- 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];
- MetaBall *mb = (MetaBall *)obedit->data;
- MetaElem *ml, *newml;
-
- if (!BKE_mball_is_any_selected(mb)) {
- continue;
- }
-
- ml = mb->editelems->last;
- if (ml) {
- while (ml) {
- if (ml->flag & SELECT) {
- newml = MEM_dupallocN(ml);
- BLI_addtail(mb->editelems, newml);
- mb->lastelem = newml;
- ml->flag &= ~SELECT;
- }
- ml = ml->prev;
- }
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb);
- DEG_id_tag_update(obedit->data, 0);
- }
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ 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];
+ MetaBall *mb = (MetaBall *)obedit->data;
+ MetaElem *ml, *newml;
+
+ if (!BKE_mball_is_any_selected(mb)) {
+ continue;
+ }
+
+ ml = mb->editelems->last;
+ if (ml) {
+ while (ml) {
+ if (ml->flag & SELECT) {
+ newml = MEM_dupallocN(ml);
+ BLI_addtail(mb->editelems, newml);
+ mb->lastelem = newml;
+ ml->flag &= ~SELECT;
+ }
+ ml = ml->prev;
+ }
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb);
+ DEG_id_tag_update(obedit->data, 0);
+ }
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MBALL_OT_duplicate_metaelems(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Duplicate Metaelements";
- ot->description = "Duplicate selected metaelement(s)";
- ot->idname = "MBALL_OT_duplicate_metaelems";
+ /* identifiers */
+ ot->name = "Duplicate Metaelements";
+ ot->description = "Duplicate selected metaelement(s)";
+ ot->idname = "MBALL_OT_duplicate_metaelems";
- /* callback functions */
- ot->exec = duplicate_metaelems_exec;
- ot->poll = ED_operator_editmball;
+ /* callback functions */
+ ot->exec = duplicate_metaelems_exec;
+ ot->poll = ED_operator_editmball;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/***************************** Delete operator *****************************/
@@ -560,53 +553,54 @@ void MBALL_OT_duplicate_metaelems(wmOperatorType *ot)
/* Delete all selected MetaElems (not MetaBall) */
static int delete_metaelems_exec(bContext *C, wmOperator *UNUSED(op))
{
- 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];
- MetaBall *mb = (MetaBall *)obedit->data;
- MetaElem *ml, *next;
-
- if (!BKE_mball_is_any_selected(mb)) {
- continue;
- }
-
- ml = mb->editelems->first;
- if (ml) {
- while (ml) {
- next = ml->next;
- if (ml->flag & SELECT) {
- if (mb->lastelem == ml) {
- mb->lastelem = NULL;
- }
- BLI_remlink(mb->editelems, ml);
- MEM_freeN(ml);
- }
- ml = next;
- }
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb);
- DEG_id_tag_update(obedit->data, 0);
- }
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ 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];
+ MetaBall *mb = (MetaBall *)obedit->data;
+ MetaElem *ml, *next;
+
+ if (!BKE_mball_is_any_selected(mb)) {
+ continue;
+ }
+
+ ml = mb->editelems->first;
+ if (ml) {
+ while (ml) {
+ next = ml->next;
+ if (ml->flag & SELECT) {
+ if (mb->lastelem == ml) {
+ mb->lastelem = NULL;
+ }
+ BLI_remlink(mb->editelems, ml);
+ MEM_freeN(ml);
+ }
+ ml = next;
+ }
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb);
+ DEG_id_tag_update(obedit->data, 0);
+ }
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MBALL_OT_delete_metaelems(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete";
- ot->description = "Delete selected metaelement(s)";
- ot->idname = "MBALL_OT_delete_metaelems";
-
- /* callback functions */
- ot->invoke = WM_operator_confirm;
- ot->exec = delete_metaelems_exec;
- ot->poll = ED_operator_editmball;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Delete";
+ ot->description = "Delete selected metaelement(s)";
+ ot->idname = "MBALL_OT_delete_metaelems";
+
+ /* callback functions */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = delete_metaelems_exec;
+ ot->poll = ED_operator_editmball;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/***************************** Hide operator *****************************/
@@ -614,43 +608,44 @@ void MBALL_OT_delete_metaelems(wmOperatorType *ot)
/* Hide selected MetaElems */
static int hide_metaelems_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- MetaBall *mb = (MetaBall *)obedit->data;
- MetaElem *ml;
- const bool invert = RNA_boolean_get(op->ptr, "unselected") ? SELECT : 0;
-
- ml = mb->editelems->first;
-
- if (ml) {
- while (ml) {
- if ((ml->flag & SELECT) != invert) {
- ml->flag |= MB_HIDE;
- }
- ml = ml->next;
- }
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb);
- DEG_id_tag_update(obedit->data, 0);
- }
-
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_edit_object(C);
+ MetaBall *mb = (MetaBall *)obedit->data;
+ MetaElem *ml;
+ const bool invert = RNA_boolean_get(op->ptr, "unselected") ? SELECT : 0;
+
+ ml = mb->editelems->first;
+
+ if (ml) {
+ while (ml) {
+ if ((ml->flag & SELECT) != invert) {
+ ml->flag |= MB_HIDE;
+ }
+ ml = ml->next;
+ }
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb);
+ DEG_id_tag_update(obedit->data, 0);
+ }
+
+ return OPERATOR_FINISHED;
}
void MBALL_OT_hide_metaelems(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Selected";
- ot->description = "Hide (un)selected metaelement(s)";
- ot->idname = "MBALL_OT_hide_metaelems";
+ /* identifiers */
+ ot->name = "Hide Selected";
+ ot->description = "Hide (un)selected metaelement(s)";
+ ot->idname = "MBALL_OT_hide_metaelems";
- /* callback functions */
- ot->exec = hide_metaelems_exec;
- ot->poll = ED_operator_editmball;
+ /* callback functions */
+ ot->exec = hide_metaelems_exec;
+ ot->poll = ED_operator_editmball;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected");
+ /* props */
+ RNA_def_boolean(
+ ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected");
}
/***************************** Unhide operator *****************************/
@@ -658,194 +653,196 @@ void MBALL_OT_hide_metaelems(wmOperatorType *ot)
/* Unhide all edited MetaElems */
static int reveal_metaelems_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- MetaBall *mb = (MetaBall *)obedit->data;
- const bool select = RNA_boolean_get(op->ptr, "select");
- bool changed = false;
-
- for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) {
- if (ml->flag & MB_HIDE) {
- SET_FLAG_FROM_TEST(ml->flag, select, SELECT);
- ml->flag &= ~MB_HIDE;
- changed = true;
- }
- }
- if (changed) {
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb);
- DEG_id_tag_update(obedit->data, 0);
- }
-
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_edit_object(C);
+ MetaBall *mb = (MetaBall *)obedit->data;
+ const bool select = RNA_boolean_get(op->ptr, "select");
+ bool changed = false;
+
+ for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) {
+ if (ml->flag & MB_HIDE) {
+ SET_FLAG_FROM_TEST(ml->flag, select, SELECT);
+ ml->flag &= ~MB_HIDE;
+ changed = true;
+ }
+ }
+ if (changed) {
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb);
+ DEG_id_tag_update(obedit->data, 0);
+ }
+
+ return OPERATOR_FINISHED;
}
void MBALL_OT_reveal_metaelems(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reveal Hidden";
- ot->description = "Reveal all hidden metaelements";
- ot->idname = "MBALL_OT_reveal_metaelems";
+ /* identifiers */
+ ot->name = "Reveal Hidden";
+ ot->description = "Reveal all hidden metaelements";
+ ot->idname = "MBALL_OT_reveal_metaelems";
- /* callback functions */
- ot->exec = reveal_metaelems_exec;
- ot->poll = ED_operator_editmball;
+ /* callback functions */
+ ot->exec = reveal_metaelems_exec;
+ ot->poll = ED_operator_editmball;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "select", true, "Select", "");
+ /* props */
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
/* Select MetaElement with mouse click (user can select radius circle or
* stiffness circle) */
bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
{
- static MetaElem *startelem = NULL;
- ViewContext vc;
- int a, hits;
- unsigned int buffer[MAXPICKBUF];
- rcti rect;
-
- ED_view3d_viewcontext_init(C, &vc);
-
- BLI_rcti_init_pt_radius(&rect, mval, 12);
-
- hits = view3d_opengl_select(
- &vc, buffer, MAXPICKBUF, &rect,
- VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP);
-
- FOREACH_BASE_IN_EDIT_MODE_BEGIN (vc.view_layer, vc.v3d, base) {
- ED_view3d_viewcontext_init_object(&vc, base->object);
- MetaBall *mb = (MetaBall *)base->object->data;
- MetaElem *ml, *ml_act = NULL;
-
- /* does startelem exist? */
- ml = mb->editelems->first;
- while (ml) {
- if (ml == startelem) {
- break;
- }
- ml = ml->next;
- }
-
- if (ml == NULL) {
- startelem = mb->editelems->first;
- }
-
- if (hits > 0) {
- int metaelem_id = 0;
- ml = startelem;
- while (ml) {
- for (a = 0; a < hits; a++) {
- int hitresult = buffer[(4 * a) + 3];
- if (hitresult == -1) {
- continue;
- }
- else if (hitresult & MBALL_NOSEL) {
- continue;
- }
-
- const uint hit_object = hitresult & 0xFFFF;
- if (vc.obedit->select_id != hit_object) {
- continue;
- }
-
- if (metaelem_id != (hitresult & 0xFFFF0000 & ~(MBALLSEL_ANY))) {
- continue;
- }
-
- if (hitresult & MBALLSEL_RADIUS) {
- ml->flag |= MB_SCALE_RAD;
- ml_act = ml;
- break;
- }
-
- if (hitresult & MBALLSEL_STIFF) {
- ml->flag &= ~MB_SCALE_RAD;
- ml_act = ml;
- break;
- }
- }
-
- if (ml_act) {
- break;
- }
- ml = ml->next;
- if (ml == NULL) {
- ml = mb->editelems->first;
- }
- if (ml == startelem) {
- break;
- }
-
- metaelem_id += 0x10000;
- }
-
- /* When some metaelem was found, then it is necessary to select or deselect it. */
- if (ml_act) {
- if (!extend && !deselect && !toggle) {
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob_iter = objects[ob_index];
-
- if (ob_iter == base->object) {
- continue;
- }
-
- BKE_mball_deselect_all((MetaBall *)ob_iter->data);
- DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
- }
- MEM_freeN(objects);
- }
-
- if (extend) {
- ml_act->flag |= SELECT;
- }
- else if (deselect) {
- ml_act->flag &= ~SELECT;
- }
- else if (toggle) {
- if (ml_act->flag & SELECT) {
- ml_act->flag &= ~SELECT;
- }
- else {
- ml_act->flag |= SELECT;
- }
- }
- else {
- /* Deselect all existing metaelems */
- BKE_mball_deselect_all(mb);
-
- /* Select only metaelem clicked on */
- ml_act->flag |= SELECT;
- }
-
- mb->lastelem = ml_act;
-
- DEG_id_tag_update(&mb->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
-
- if (vc.view_layer->basact != base) {
- ED_object_base_activate(C, base);
- }
-
- return true;
- }
- }
- } FOREACH_BASE_IN_EDIT_MODE_END;
-
- return false;
+ static MetaElem *startelem = NULL;
+ ViewContext vc;
+ int a, hits;
+ unsigned int buffer[MAXPICKBUF];
+ rcti rect;
+
+ ED_view3d_viewcontext_init(C, &vc);
+
+ BLI_rcti_init_pt_radius(&rect, mval, 12);
+
+ hits = view3d_opengl_select(
+ &vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP);
+
+ FOREACH_BASE_IN_EDIT_MODE_BEGIN (vc.view_layer, vc.v3d, base) {
+ ED_view3d_viewcontext_init_object(&vc, base->object);
+ MetaBall *mb = (MetaBall *)base->object->data;
+ MetaElem *ml, *ml_act = NULL;
+
+ /* does startelem exist? */
+ ml = mb->editelems->first;
+ while (ml) {
+ if (ml == startelem) {
+ break;
+ }
+ ml = ml->next;
+ }
+
+ if (ml == NULL) {
+ startelem = mb->editelems->first;
+ }
+
+ if (hits > 0) {
+ int metaelem_id = 0;
+ ml = startelem;
+ while (ml) {
+ for (a = 0; a < hits; a++) {
+ int hitresult = buffer[(4 * a) + 3];
+ if (hitresult == -1) {
+ continue;
+ }
+ else if (hitresult & MBALL_NOSEL) {
+ continue;
+ }
+
+ const uint hit_object = hitresult & 0xFFFF;
+ if (vc.obedit->select_id != hit_object) {
+ continue;
+ }
+
+ if (metaelem_id != (hitresult & 0xFFFF0000 & ~(MBALLSEL_ANY))) {
+ continue;
+ }
+
+ if (hitresult & MBALLSEL_RADIUS) {
+ ml->flag |= MB_SCALE_RAD;
+ ml_act = ml;
+ break;
+ }
+
+ if (hitresult & MBALLSEL_STIFF) {
+ ml->flag &= ~MB_SCALE_RAD;
+ ml_act = ml;
+ break;
+ }
+ }
+
+ if (ml_act) {
+ break;
+ }
+ ml = ml->next;
+ if (ml == NULL) {
+ ml = mb->editelems->first;
+ }
+ if (ml == startelem) {
+ break;
+ }
+
+ metaelem_id += 0x10000;
+ }
+
+ /* When some metaelem was found, then it is necessary to select or deselect it. */
+ if (ml_act) {
+ if (!extend && !deselect && !toggle) {
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ vc.view_layer, vc.v3d, &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob_iter = objects[ob_index];
+
+ if (ob_iter == base->object) {
+ continue;
+ }
+
+ BKE_mball_deselect_all((MetaBall *)ob_iter->data);
+ DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
+ }
+ MEM_freeN(objects);
+ }
+
+ if (extend) {
+ ml_act->flag |= SELECT;
+ }
+ else if (deselect) {
+ ml_act->flag &= ~SELECT;
+ }
+ else if (toggle) {
+ if (ml_act->flag & SELECT) {
+ ml_act->flag &= ~SELECT;
+ }
+ else {
+ ml_act->flag |= SELECT;
+ }
+ }
+ else {
+ /* Deselect all existing metaelems */
+ BKE_mball_deselect_all(mb);
+
+ /* Select only metaelem clicked on */
+ ml_act->flag |= SELECT;
+ }
+
+ mb->lastelem = ml_act;
+
+ DEG_id_tag_update(&mb->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
+
+ if (vc.view_layer->basact != base) {
+ ED_object_base_activate(C, base);
+ }
+
+ return true;
+ }
+ }
+ }
+ FOREACH_BASE_IN_EDIT_MODE_END;
+
+ return false;
}
bool ED_mball_deselect_all_multi(bContext *C)
{
- ViewContext vc;
- ED_view3d_viewcontext_init(C, &vc);
- uint bases_len = 0;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &bases_len);
- bool changed_multi = BKE_mball_deselect_all_multi_ex(bases, bases_len);
- MEM_freeN(bases);
- return changed_multi;
+ ViewContext vc;
+ ED_view3d_viewcontext_init(C, &vc);
+ uint bases_len = 0;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
+ vc.view_layer, vc.v3d, &bases_len);
+ bool changed_multi = BKE_mball_deselect_all_multi_ex(bases, bases_len);
+ MEM_freeN(bases);
+ return changed_multi;
}
diff --git a/source/blender/editors/metaball/mball_intern.h b/source/blender/editors/metaball/mball_intern.h
index dad1fa172fa..dec94f97b8a 100644
--- a/source/blender/editors/metaball/mball_intern.h
+++ b/source/blender/editors/metaball/mball_intern.h
@@ -21,7 +21,6 @@
* \ingroup edmeta
*/
-
#ifndef __MBALL_INTERN_H__
#define __MBALL_INTERN_H__
diff --git a/source/blender/editors/metaball/mball_ops.c b/source/blender/editors/metaball/mball_ops.c
index b8a209dc5eb..4de277901f4 100644
--- a/source/blender/editors/metaball/mball_ops.c
+++ b/source/blender/editors/metaball/mball_ops.c
@@ -37,32 +37,33 @@
void ED_operatortypes_metaball(void)
{
- WM_operatortype_append(MBALL_OT_delete_metaelems);
- WM_operatortype_append(MBALL_OT_duplicate_metaelems);
+ WM_operatortype_append(MBALL_OT_delete_metaelems);
+ WM_operatortype_append(MBALL_OT_duplicate_metaelems);
- WM_operatortype_append(MBALL_OT_hide_metaelems);
- WM_operatortype_append(MBALL_OT_reveal_metaelems);
+ WM_operatortype_append(MBALL_OT_hide_metaelems);
+ WM_operatortype_append(MBALL_OT_reveal_metaelems);
- WM_operatortype_append(MBALL_OT_select_all);
- WM_operatortype_append(MBALL_OT_select_similar);
- WM_operatortype_append(MBALL_OT_select_random_metaelems);
+ WM_operatortype_append(MBALL_OT_select_all);
+ WM_operatortype_append(MBALL_OT_select_similar);
+ WM_operatortype_append(MBALL_OT_select_random_metaelems);
}
void ED_operatormacros_metaball(void)
{
- wmOperatorType *ot;
- wmOperatorTypeMacro *otmacro;
+ wmOperatorType *ot;
+ wmOperatorTypeMacro *otmacro;
- ot = WM_operatortype_append_macro("MBALL_OT_duplicate_move", "Duplicate",
- "Make copies of the selected metaelements and move them",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "MBALL_OT_duplicate_metaelems");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", 0);
+ ot = WM_operatortype_append_macro("MBALL_OT_duplicate_move",
+ "Duplicate",
+ "Make copies of the selected metaelements and move them",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "MBALL_OT_duplicate_metaelems");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
}
void ED_keymap_metaball(wmKeyConfig *keyconf)
{
- wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Metaball", 0, 0);
- keymap->poll = ED_operator_editmball;
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Metaball", 0, 0);
+ keymap->poll = ED_operator_editmball;
}
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt
index 75d2fada7f3..8ef0d85bcfd 100644
--- a/source/blender/editors/object/CMakeLists.txt
+++ b/source/blender/editors/object/CMakeLists.txt
@@ -16,72 +16,72 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../bmesh
- ../../depsgraph
- ../../gpu
- ../../ikplugin
- ../../imbuf
- ../../makesdna
- ../../makesrna
- ../../modifiers
- ../../gpencil_modifiers
- ../../shader_fx
- ../../python
- ../../render/extern/include
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../bmesh
+ ../../depsgraph
+ ../../gpu
+ ../../ikplugin
+ ../../imbuf
+ ../../makesdna
+ ../../makesrna
+ ../../modifiers
+ ../../gpencil_modifiers
+ ../../shader_fx
+ ../../python
+ ../../render/extern/include
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- object_add.c
- object_bake.c
- object_bake_api.c
- object_collection.c
- object_constraint.c
- object_data_transfer.c
- object_edit.c
- object_facemap_ops.c
- object_gpencil_modifier.c
- object_hook.c
- object_modes.c
- object_modifier.c
- object_ops.c
- object_random.c
- object_relations.c
- object_select.c
- object_shader_fx.c
- object_shapekey.c
- object_transform.c
- object_utils.c
- object_vgroup.c
- object_warp.c
+ object_add.c
+ object_bake.c
+ object_bake_api.c
+ object_collection.c
+ object_constraint.c
+ object_data_transfer.c
+ object_edit.c
+ object_facemap_ops.c
+ object_gpencil_modifier.c
+ object_hook.c
+ object_modes.c
+ object_modifier.c
+ object_ops.c
+ object_random.c
+ object_relations.c
+ object_select.c
+ object_shader_fx.c
+ object_shapekey.c
+ object_transform.c
+ object_utils.c
+ object_vgroup.c
+ object_warp.c
- object_intern.h
+ object_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
- bf_render
+ bf_blenkernel
+ bf_blenlib
+ bf_render
)
add_definitions(${GL_DEFINITIONS})
if(WITH_PYTHON)
- add_definitions(-DWITH_PYTHON)
+ add_definitions(-DWITH_PYTHON)
endif()
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
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 9269c25f54b..c050b579aa6 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
@@ -118,357 +117,392 @@
* kept here because of linking order.
* Icons are only defined here */
const EnumPropertyItem rna_enum_light_type_items[] = {
- {LA_LOCAL, "POINT", ICON_LIGHT_POINT, "Point", "Omnidirectional point light source"},
- {LA_SUN, "SUN", ICON_LIGHT_SUN, "Sun", "Constant direction parallel ray light source"},
- {LA_SPOT, "SPOT", ICON_LIGHT_SPOT, "Spot", "Directional cone light source"},
- {LA_AREA, "AREA", ICON_LIGHT_AREA, "Area", "Directional area light source"},
- {0, NULL, 0, NULL, NULL},
+ {LA_LOCAL, "POINT", ICON_LIGHT_POINT, "Point", "Omnidirectional point light source"},
+ {LA_SUN, "SUN", ICON_LIGHT_SUN, "Sun", "Constant direction parallel ray light source"},
+ {LA_SPOT, "SPOT", ICON_LIGHT_SPOT, "Spot", "Directional cone light source"},
+ {LA_AREA, "AREA", ICON_LIGHT_AREA, "Area", "Directional area light source"},
+ {0, NULL, 0, NULL, NULL},
};
/* copy from rna_object_force.c */
static const EnumPropertyItem field_type_items[] = {
- {PFIELD_FORCE, "FORCE", ICON_FORCE_FORCE, "Force", ""},
- {PFIELD_WIND, "WIND", ICON_FORCE_WIND, "Wind", ""},
- {PFIELD_VORTEX, "VORTEX", ICON_FORCE_VORTEX, "Vortex", ""},
- {PFIELD_MAGNET, "MAGNET", ICON_FORCE_MAGNETIC, "Magnetic", ""},
- {PFIELD_HARMONIC, "HARMONIC", ICON_FORCE_HARMONIC, "Harmonic", ""},
- {PFIELD_CHARGE, "CHARGE", ICON_FORCE_CHARGE, "Charge", ""},
- {PFIELD_LENNARDJ, "LENNARDJ", ICON_FORCE_LENNARDJONES, "Lennard-Jones", ""},
- {PFIELD_TEXTURE, "TEXTURE", ICON_FORCE_TEXTURE, "Texture", ""},
- {PFIELD_GUIDE, "GUIDE", ICON_FORCE_CURVE, "Curve Guide", ""},
- {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", ""},
- {0, NULL, 0, NULL, NULL},
+ {PFIELD_FORCE, "FORCE", ICON_FORCE_FORCE, "Force", ""},
+ {PFIELD_WIND, "WIND", ICON_FORCE_WIND, "Wind", ""},
+ {PFIELD_VORTEX, "VORTEX", ICON_FORCE_VORTEX, "Vortex", ""},
+ {PFIELD_MAGNET, "MAGNET", ICON_FORCE_MAGNETIC, "Magnetic", ""},
+ {PFIELD_HARMONIC, "HARMONIC", ICON_FORCE_HARMONIC, "Harmonic", ""},
+ {PFIELD_CHARGE, "CHARGE", ICON_FORCE_CHARGE, "Charge", ""},
+ {PFIELD_LENNARDJ, "LENNARDJ", ICON_FORCE_LENNARDJONES, "Lennard-Jones", ""},
+ {PFIELD_TEXTURE, "TEXTURE", ICON_FORCE_TEXTURE, "Texture", ""},
+ {PFIELD_GUIDE, "GUIDE", ICON_FORCE_CURVE, "Curve Guide", ""},
+ {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", ""},
+ {0, NULL, 0, NULL, NULL},
};
static EnumPropertyItem lightprobe_type_items[] = {
- {LIGHTPROBE_TYPE_CUBE, "CUBEMAP", ICON_LIGHTPROBE_CUBEMAP, "Reflection Cubemap",
+ {LIGHTPROBE_TYPE_CUBE,
+ "CUBEMAP",
+ ICON_LIGHTPROBE_CUBEMAP,
+ "Reflection Cubemap",
"Reflection probe with spherical or cubic attenuation"},
- {LIGHTPROBE_TYPE_PLANAR, "PLANAR", ICON_LIGHTPROBE_PLANAR, "Reflection Plane",
+ {LIGHTPROBE_TYPE_PLANAR,
+ "PLANAR",
+ ICON_LIGHTPROBE_PLANAR,
+ "Reflection Plane",
"Planar reflection probe"},
- {LIGHTPROBE_TYPE_GRID, "GRID", ICON_LIGHTPROBE_GRID, "Irradiance Volume",
+ {LIGHTPROBE_TYPE_GRID,
+ "GRID",
+ ICON_LIGHTPROBE_GRID,
+ "Irradiance Volume",
"Irradiance probe to capture diffuse indirect lighting"},
- {0, NULL, 0, NULL, NULL},
+ {0, NULL, 0, NULL, NULL},
};
/************************** Exported *****************************/
void ED_object_location_from_view(bContext *C, float loc[3])
{
- const Scene *scene = CTX_data_scene(C);
- copy_v3_v3(loc, scene->cursor.location);
+ const Scene *scene = CTX_data_scene(C);
+ copy_v3_v3(loc, scene->cursor.location);
}
void ED_object_rotation_from_quat(float rot[3], const float viewquat[4], const char align_axis)
{
- BLI_assert(align_axis >= 'X' && align_axis <= 'Z');
-
- switch (align_axis) {
- case 'X':
- {
- /* Same as 'rv3d->viewinv[1]' */
- float axis_y[4] = {0.0f, 1.0f, 0.0f};
- float quat_y[4], quat[4];
- axis_angle_to_quat(quat_y, axis_y, M_PI_2);
- mul_qt_qtqt(quat, viewquat, quat_y);
- quat_to_eul(rot, quat);
- break;
- }
- case 'Y':
- {
- quat_to_eul(rot, viewquat);
- rot[0] -= (float)M_PI_2;
- break;
- }
- case 'Z':
- {
- quat_to_eul(rot, viewquat);
- break;
- }
- }
+ BLI_assert(align_axis >= 'X' && align_axis <= 'Z');
+
+ switch (align_axis) {
+ case 'X': {
+ /* Same as 'rv3d->viewinv[1]' */
+ float axis_y[4] = {0.0f, 1.0f, 0.0f};
+ float quat_y[4], quat[4];
+ axis_angle_to_quat(quat_y, axis_y, M_PI_2);
+ mul_qt_qtqt(quat, viewquat, quat_y);
+ quat_to_eul(rot, quat);
+ break;
+ }
+ case 'Y': {
+ quat_to_eul(rot, viewquat);
+ rot[0] -= (float)M_PI_2;
+ break;
+ }
+ case 'Z': {
+ quat_to_eul(rot, viewquat);
+ break;
+ }
+ }
}
void ED_object_rotation_from_view(bContext *C, float rot[3], const char align_axis)
{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- BLI_assert(align_axis >= 'X' && align_axis <= 'Z');
- if (rv3d) {
- float viewquat[4];
- copy_qt_qt(viewquat, rv3d->viewquat);
- viewquat[0] *= -1.0f;
- ED_object_rotation_from_quat(rot, viewquat, align_axis);
- }
- else {
- zero_v3(rot);
- }
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ BLI_assert(align_axis >= 'X' && align_axis <= 'Z');
+ if (rv3d) {
+ float viewquat[4];
+ copy_qt_qt(viewquat, rv3d->viewquat);
+ viewquat[0] *= -1.0f;
+ ED_object_rotation_from_quat(rot, viewquat, align_axis);
+ }
+ else {
+ zero_v3(rot);
+ }
}
void ED_object_base_init_transform(bContext *C, Base *base, const float loc[3], const float rot[3])
{
- Object *ob = base->object;
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob = base->object;
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
- if (!scene) return;
+ if (!scene)
+ return;
- if (loc)
- copy_v3_v3(ob->loc, loc);
+ if (loc)
+ copy_v3_v3(ob->loc, loc);
- if (rot)
- copy_v3_v3(ob->rot, rot);
+ if (rot)
+ copy_v3_v3(ob->rot, rot);
- BKE_object_where_is_calc(depsgraph, scene, ob);
+ BKE_object_where_is_calc(depsgraph, scene, ob);
}
/* Uses context to figure out transform for primitive.
* Returns standard diameter. */
float ED_object_new_primitive_matrix(
- bContext *C, Object *obedit,
- const float loc[3], const float rot[3], float primmat[4][4])
+ bContext *C, Object *obedit, const float loc[3], const float rot[3], float primmat[4][4])
{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- float mat[3][3], rmat[3][3], cmat[3][3], imat[3][3];
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ float mat[3][3], rmat[3][3], cmat[3][3], imat[3][3];
- unit_m4(primmat);
+ unit_m4(primmat);
- eul_to_mat3(rmat, rot);
- invert_m3(rmat);
+ eul_to_mat3(rmat, rot);
+ invert_m3(rmat);
- /* inverse transform for initial rotation and object */
- copy_m3_m4(mat, obedit->obmat);
- mul_m3_m3m3(cmat, rmat, mat);
- invert_m3_m3(imat, cmat);
- copy_m4_m3(primmat, imat);
+ /* inverse transform for initial rotation and object */
+ copy_m3_m4(mat, obedit->obmat);
+ mul_m3_m3m3(cmat, rmat, mat);
+ invert_m3_m3(imat, cmat);
+ copy_m4_m3(primmat, imat);
- /* center */
- copy_v3_v3(primmat[3], loc);
- sub_v3_v3v3(primmat[3], primmat[3], obedit->obmat[3]);
- invert_m3_m3(imat, mat);
- mul_m3_v3(imat, primmat[3]);
+ /* center */
+ copy_v3_v3(primmat[3], loc);
+ sub_v3_v3v3(primmat[3], primmat[3], obedit->obmat[3]);
+ invert_m3_m3(imat, mat);
+ mul_m3_v3(imat, primmat[3]);
- {
- const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : ED_scene_grid_scale(scene, NULL);
- return dia;
- }
+ {
+ const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) :
+ ED_scene_grid_scale(scene, NULL);
+ return dia;
+ }
- // return 1.0f;
+ // return 1.0f;
}
/********************* Add Object Operator ********************/
-static void view_align_update(struct Main *UNUSED(main), struct Scene *UNUSED(scene), struct PointerRNA *ptr)
+static void view_align_update(struct Main *UNUSED(main),
+ struct Scene *UNUSED(scene),
+ struct PointerRNA *ptr)
{
- RNA_struct_idprops_unset(ptr, "rotation");
+ RNA_struct_idprops_unset(ptr, "rotation");
}
void ED_object_add_unit_props_size(wmOperatorType *ot)
{
- RNA_def_float_distance(ot->srna, "size", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Size", "", 0.001, 100.00);
+ RNA_def_float_distance(
+ ot->srna, "size", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Size", "", 0.001, 100.00);
}
void ED_object_add_unit_props_radius(wmOperatorType *ot)
{
- RNA_def_float_distance(ot->srna, "radius", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.001, 100.00);
+ RNA_def_float_distance(
+ ot->srna, "radius", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.001, 100.00);
}
void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode)
{
- PropertyRNA *prop;
-
- /* note: this property gets hidden for add-camera operator */
- prop = RNA_def_boolean(ot->srna, "view_align", 0, "Align to View", "Align the new object to the view");
- RNA_def_property_update_runtime(prop, view_align_update);
-
- if (do_editmode) {
- prop = RNA_def_boolean(ot->srna, "enter_editmode", 0, "Enter Editmode",
- "Enter editmode when adding this object");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- }
-
- prop = RNA_def_float_vector_xyz(ot->srna, "location", 3, NULL, -OBJECT_ADD_SIZE_MAXF, OBJECT_ADD_SIZE_MAXF,
- "Location", "Location for the newly added object", -1000.0f, 1000.0f);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_float_rotation(ot->srna, "rotation", 3, NULL, -OBJECT_ADD_SIZE_MAXF, OBJECT_ADD_SIZE_MAXF,
- "Rotation", "Rotation for the newly added object",
- DEG2RADF(-360.0f), DEG2RADF(360.0f));
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* note: this property gets hidden for add-camera operator */
+ prop = RNA_def_boolean(
+ ot->srna, "view_align", 0, "Align to View", "Align the new object to the view");
+ RNA_def_property_update_runtime(prop, view_align_update);
+
+ if (do_editmode) {
+ prop = RNA_def_boolean(
+ ot->srna, "enter_editmode", 0, "Enter Editmode", "Enter editmode when adding this object");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ }
+
+ prop = RNA_def_float_vector_xyz(ot->srna,
+ "location",
+ 3,
+ NULL,
+ -OBJECT_ADD_SIZE_MAXF,
+ OBJECT_ADD_SIZE_MAXF,
+ "Location",
+ "Location for the newly added object",
+ -1000.0f,
+ 1000.0f);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_float_rotation(ot->srna,
+ "rotation",
+ 3,
+ NULL,
+ -OBJECT_ADD_SIZE_MAXF,
+ OBJECT_ADD_SIZE_MAXF,
+ "Rotation",
+ "Rotation for the newly added object",
+ DEG2RADF(-360.0f),
+ DEG2RADF(360.0f));
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
void ED_object_add_mesh_props(wmOperatorType *ot)
{
- RNA_def_boolean(ot->srna, "calc_uvs", true, "Generate UVs", "Generate a default UV map");
-}
-
-bool ED_object_add_generic_get_opts(
- bContext *C, wmOperator *op, const char view_align_axis,
- float loc[3], float rot[3],
- bool *enter_editmode, ushort *local_view_bits, bool *is_view_aligned)
-{
- PropertyRNA *prop;
-
- /* Switch to Edit mode? optional prop */
- if ((prop = RNA_struct_find_property(op->ptr, "enter_editmode"))) {
- bool _enter_editmode;
- if (!enter_editmode)
- enter_editmode = &_enter_editmode;
-
- if (RNA_property_is_set(op->ptr, prop) && enter_editmode)
- *enter_editmode = RNA_property_boolean_get(op->ptr, prop);
- else {
- *enter_editmode = (U.flag & USER_ADD_EDITMODE) != 0;
- RNA_property_boolean_set(op->ptr, prop, *enter_editmode);
- }
- }
-
- if (local_view_bits) {
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d && v3d->localvd) {
- *local_view_bits = v3d->local_view_uuid;
- }
- }
-
- /* Location! */
- {
- float _loc[3];
- if (!loc)
- loc = _loc;
-
- if (RNA_struct_property_is_set(op->ptr, "location")) {
- RNA_float_get_array(op->ptr, "location", loc);
- }
- else {
- ED_object_location_from_view(C, loc);
- RNA_float_set_array(op->ptr, "location", loc);
- }
- }
-
- /* Rotation! */
- {
- bool _is_view_aligned;
- float _rot[3];
- if (!is_view_aligned)
- is_view_aligned = &_is_view_aligned;
- if (!rot)
- rot = _rot;
-
- if (RNA_struct_property_is_set(op->ptr, "rotation"))
- *is_view_aligned = false;
- else if (RNA_struct_property_is_set(op->ptr, "view_align"))
- *is_view_aligned = RNA_boolean_get(op->ptr, "view_align");
- else {
- *is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0;
- RNA_boolean_set(op->ptr, "view_align", *is_view_aligned);
- }
-
- if (*is_view_aligned) {
- ED_object_rotation_from_view(C, rot, view_align_axis);
- RNA_float_set_array(op->ptr, "rotation", rot);
- }
- else
- RNA_float_get_array(op->ptr, "rotation", rot);
- }
-
- return true;
+ RNA_def_boolean(ot->srna, "calc_uvs", true, "Generate UVs", "Generate a default UV map");
+}
+
+bool ED_object_add_generic_get_opts(bContext *C,
+ wmOperator *op,
+ const char view_align_axis,
+ float loc[3],
+ float rot[3],
+ bool *enter_editmode,
+ ushort *local_view_bits,
+ bool *is_view_aligned)
+{
+ PropertyRNA *prop;
+
+ /* Switch to Edit mode? optional prop */
+ if ((prop = RNA_struct_find_property(op->ptr, "enter_editmode"))) {
+ bool _enter_editmode;
+ if (!enter_editmode)
+ enter_editmode = &_enter_editmode;
+
+ if (RNA_property_is_set(op->ptr, prop) && enter_editmode)
+ *enter_editmode = RNA_property_boolean_get(op->ptr, prop);
+ else {
+ *enter_editmode = (U.flag & USER_ADD_EDITMODE) != 0;
+ RNA_property_boolean_set(op->ptr, prop, *enter_editmode);
+ }
+ }
+
+ if (local_view_bits) {
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d && v3d->localvd) {
+ *local_view_bits = v3d->local_view_uuid;
+ }
+ }
+
+ /* Location! */
+ {
+ float _loc[3];
+ if (!loc)
+ loc = _loc;
+
+ if (RNA_struct_property_is_set(op->ptr, "location")) {
+ RNA_float_get_array(op->ptr, "location", loc);
+ }
+ else {
+ ED_object_location_from_view(C, loc);
+ RNA_float_set_array(op->ptr, "location", loc);
+ }
+ }
+
+ /* Rotation! */
+ {
+ bool _is_view_aligned;
+ float _rot[3];
+ if (!is_view_aligned)
+ is_view_aligned = &_is_view_aligned;
+ if (!rot)
+ rot = _rot;
+
+ if (RNA_struct_property_is_set(op->ptr, "rotation"))
+ *is_view_aligned = false;
+ else if (RNA_struct_property_is_set(op->ptr, "view_align"))
+ *is_view_aligned = RNA_boolean_get(op->ptr, "view_align");
+ else {
+ *is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0;
+ RNA_boolean_set(op->ptr, "view_align", *is_view_aligned);
+ }
+
+ if (*is_view_aligned) {
+ ED_object_rotation_from_view(C, rot, view_align_axis);
+ RNA_float_set_array(op->ptr, "rotation", rot);
+ }
+ else
+ RNA_float_get_array(op->ptr, "rotation", rot);
+ }
+
+ return true;
}
/* For object add primitive operators.
* Do not call undo push in this function (users of this function have to). */
-Object *ED_object_add_type(
- bContext *C,
- int type, const char *name,
- const float loc[3], const float rot[3],
- bool enter_editmode, ushort local_view_bits)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob;
-
- /* for as long scene has editmode... */
- if (CTX_data_edit_object(C)) {
- ED_object_editmode_exit(C, EM_FREEDATA);
- }
-
- /* deselects all, sets active object */
- ob = BKE_object_add(bmain, scene, view_layer, type, name);
- BASACT(view_layer)->local_view_bits = local_view_bits;
- /* editor level activate, notifiers */
- ED_object_base_activate(C, view_layer->basact);
-
- /* more editor stuff */
- ED_object_base_init_transform(C, view_layer->basact, loc, rot);
-
- /* TODO(sergey): This is weird to manually tag objects for update, better to
- * use DEG_id_tag_update here perhaps.
- */
- DEG_id_type_tag(bmain, ID_OB);
- DEG_relations_tag_update(bmain);
- if (ob->data != NULL) {
- DEG_id_tag_update_ex(bmain, (ID *)ob->data, ID_RECALC_EDITORS);
- }
-
- if (enter_editmode) {
- ED_object_editmode_enter_ex(bmain, scene, ob, 0);
- }
-
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
-
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
-
- return ob;
+Object *ED_object_add_type(bContext *C,
+ int type,
+ const char *name,
+ const float loc[3],
+ const float rot[3],
+ bool enter_editmode,
+ ushort local_view_bits)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob;
+
+ /* for as long scene has editmode... */
+ if (CTX_data_edit_object(C)) {
+ ED_object_editmode_exit(C, EM_FREEDATA);
+ }
+
+ /* deselects all, sets active object */
+ ob = BKE_object_add(bmain, scene, view_layer, type, name);
+ BASACT(view_layer)->local_view_bits = local_view_bits;
+ /* editor level activate, notifiers */
+ ED_object_base_activate(C, view_layer->basact);
+
+ /* more editor stuff */
+ ED_object_base_init_transform(C, view_layer->basact, loc, rot);
+
+ /* TODO(sergey): This is weird to manually tag objects for update, better to
+ * use DEG_id_tag_update here perhaps.
+ */
+ DEG_id_type_tag(bmain, ID_OB);
+ DEG_relations_tag_update(bmain);
+ if (ob->data != NULL) {
+ DEG_id_tag_update_ex(bmain, (ID *)ob->data, ID_RECALC_EDITORS);
+ }
+
+ if (enter_editmode) {
+ ED_object_editmode_enter_ex(bmain, scene, ob, 0);
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
+
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+
+ return ob;
}
/* for object add operator */
static int object_add_exec(bContext *C, wmOperator *op)
{
- Object *ob;
- bool enter_editmode;
- ushort local_view_bits;
- float loc[3], rot[3], radius;
+ Object *ob;
+ bool enter_editmode;
+ ushort local_view_bits;
+ float loc[3], rot[3], radius;
- WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- radius = RNA_float_get(op->ptr, "radius");
- ob = ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), NULL, loc, rot, enter_editmode, local_view_bits);
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ radius = RNA_float_get(op->ptr, "radius");
+ ob = ED_object_add_type(
+ C, RNA_enum_get(op->ptr, "type"), NULL, loc, rot, enter_editmode, local_view_bits);
- if (ob->type == OB_LATTICE) {
- /* lattice is a special case!
- * we never want to scale the obdata since that is the rest-state */
- copy_v3_fl(ob->scale, radius);
- }
- else {
- BKE_object_obdata_size_init(ob, radius);
- }
+ if (ob->type == OB_LATTICE) {
+ /* lattice is a special case!
+ * we never want to scale the obdata since that is the rest-state */
+ copy_v3_fl(ob->scale, radius);
+ }
+ else {
+ BKE_object_obdata_size_init(ob, radius);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Object";
- ot->description = "Add an object to the scene";
- ot->idname = "OBJECT_OT_add";
+ /* identifiers */
+ ot->name = "Add Object";
+ ot->description = "Add an object to the scene";
+ ot->idname = "OBJECT_OT_add";
- /* api callbacks */
- ot->exec = object_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = object_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ED_object_add_unit_props_radius(ot);
- PropertyRNA *prop = RNA_def_enum(ot->srna, "type", rna_enum_object_type_items, 0, "Type", "");
- RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
+ /* properties */
+ ED_object_add_unit_props_radius(ot);
+ PropertyRNA *prop = RNA_def_enum(ot->srna, "type", rna_enum_object_type_items, 0, "Type", "");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_generic_props(ot, true);
}
/********************** Add Probe Operator **********************/
@@ -476,82 +510,87 @@ void OBJECT_OT_add(wmOperatorType *ot)
/* for object add operator */
static const char *get_lightprobe_defname(int type)
{
- switch (type) {
- case LIGHTPROBE_TYPE_GRID: return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "IrradianceVolume");
- case LIGHTPROBE_TYPE_PLANAR: return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "ReflectionPlane");
- case LIGHTPROBE_TYPE_CUBE: return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "ReflectionCubemap");
- default:
- return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "LightProbe");
- }
+ switch (type) {
+ case LIGHTPROBE_TYPE_GRID:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "IrradianceVolume");
+ case LIGHTPROBE_TYPE_PLANAR:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "ReflectionPlane");
+ case LIGHTPROBE_TYPE_CUBE:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "ReflectionCubemap");
+ default:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "LightProbe");
+ }
}
static int lightprobe_add_exec(bContext *C, wmOperator *op)
{
- Object *ob;
- LightProbe *probe;
- int type;
- bool enter_editmode;
- ushort local_view_bits;
- float loc[3], rot[3];
- float radius;
-
- WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- type = RNA_enum_get(op->ptr, "type");
- radius = RNA_float_get(op->ptr, "radius");
-
- ob = ED_object_add_type(C, OB_LIGHTPROBE, get_lightprobe_defname(type), loc, rot, false, local_view_bits);
- copy_v3_fl(ob->scale, radius);
-
- probe = (LightProbe *)ob->data;
- probe->type = type;
-
- switch (type) {
- case LIGHTPROBE_TYPE_GRID:
- probe->distinf = 0.3f;
- probe->falloff = 1.0f;
- probe->clipsta = 0.01f;
- break;
- case LIGHTPROBE_TYPE_PLANAR:
- probe->distinf = 0.1f;
- probe->falloff = 0.5f;
- probe->clipsta = 0.001f;
- ob->empty_drawsize = 0.5f;
- break;
- case LIGHTPROBE_TYPE_CUBE:
- probe->attenuation_type = LIGHTPROBE_SHAPE_ELIPSOID;
- break;
- default:
- BLI_assert(!"LightProbe type not configured.");
- break;
- }
-
- DEG_relations_tag_update(CTX_data_main(C));
-
- return OPERATOR_FINISHED;
+ Object *ob;
+ LightProbe *probe;
+ int type;
+ bool enter_editmode;
+ ushort local_view_bits;
+ float loc[3], rot[3];
+ float radius;
+
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ type = RNA_enum_get(op->ptr, "type");
+ radius = RNA_float_get(op->ptr, "radius");
+
+ ob = ED_object_add_type(
+ C, OB_LIGHTPROBE, get_lightprobe_defname(type), loc, rot, false, local_view_bits);
+ copy_v3_fl(ob->scale, radius);
+
+ probe = (LightProbe *)ob->data;
+ probe->type = type;
+
+ switch (type) {
+ case LIGHTPROBE_TYPE_GRID:
+ probe->distinf = 0.3f;
+ probe->falloff = 1.0f;
+ probe->clipsta = 0.01f;
+ break;
+ case LIGHTPROBE_TYPE_PLANAR:
+ probe->distinf = 0.1f;
+ probe->falloff = 0.5f;
+ probe->clipsta = 0.001f;
+ ob->empty_drawsize = 0.5f;
+ break;
+ case LIGHTPROBE_TYPE_CUBE:
+ probe->attenuation_type = LIGHTPROBE_SHAPE_ELIPSOID;
+ break;
+ default:
+ BLI_assert(!"LightProbe type not configured.");
+ break;
+ }
+
+ DEG_relations_tag_update(CTX_data_main(C));
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_lightprobe_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Light Probe";
- ot->description = "Add a light probe object";
- ot->idname = "OBJECT_OT_lightprobe_add";
+ /* identifiers */
+ ot->name = "Add Light Probe";
+ ot->description = "Add a light probe object";
+ ot->idname = "OBJECT_OT_lightprobe_add";
- /* api callbacks */
- ot->exec = lightprobe_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = lightprobe_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", lightprobe_type_items, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", lightprobe_type_items, 0, "Type", "");
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
/********************* Add Effector Operator ********************/
@@ -559,759 +598,768 @@ void OBJECT_OT_lightprobe_add(wmOperatorType *ot)
/* for object add operator */
static int effector_add_exec(bContext *C, wmOperator *op)
{
- Object *ob;
- int type;
- bool enter_editmode;
- ushort local_view_bits;
- float loc[3], rot[3];
- float mat[4][4];
- float dia;
-
- WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- type = RNA_enum_get(op->ptr, "type");
- dia = RNA_float_get(op->ptr, "radius");
-
- if (type == PFIELD_GUIDE) {
- Curve *cu;
- const char *name = CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "CurveGuide");
- ob = ED_object_add_type(C, OB_CURVE, name, loc, rot, false, local_view_bits);
-
- cu = ob->data;
- cu->flag |= CU_PATH | CU_3D;
- ED_object_editmode_enter(C, 0);
- ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
- BLI_addtail(&cu->editnurb->nurbs, ED_curve_add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, dia));
- if (!enter_editmode)
- ED_object_editmode_exit(C, EM_FREEDATA);
- }
- else {
- const char *name = CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Field");
- ob = ED_object_add_type(C, OB_EMPTY, name, loc, rot, false, local_view_bits);
- BKE_object_obdata_size_init(ob, dia);
- if (ELEM(type, PFIELD_WIND, PFIELD_VORTEX))
- ob->empty_drawtype = OB_SINGLE_ARROW;
- }
-
- ob->pd = BKE_partdeflect_new(type);
-
- DEG_relations_tag_update(CTX_data_main(C));
-
- return OPERATOR_FINISHED;
+ Object *ob;
+ int type;
+ bool enter_editmode;
+ ushort local_view_bits;
+ float loc[3], rot[3];
+ float mat[4][4];
+ float dia;
+
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ type = RNA_enum_get(op->ptr, "type");
+ dia = RNA_float_get(op->ptr, "radius");
+
+ if (type == PFIELD_GUIDE) {
+ Curve *cu;
+ const char *name = CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "CurveGuide");
+ ob = ED_object_add_type(C, OB_CURVE, name, loc, rot, false, local_view_bits);
+
+ cu = ob->data;
+ cu->flag |= CU_PATH | CU_3D;
+ ED_object_editmode_enter(C, 0);
+ ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
+ BLI_addtail(&cu->editnurb->nurbs,
+ ED_curve_add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, dia));
+ if (!enter_editmode)
+ ED_object_editmode_exit(C, EM_FREEDATA);
+ }
+ else {
+ const char *name = CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Field");
+ ob = ED_object_add_type(C, OB_EMPTY, name, loc, rot, false, local_view_bits);
+ BKE_object_obdata_size_init(ob, dia);
+ if (ELEM(type, PFIELD_WIND, PFIELD_VORTEX))
+ ob->empty_drawtype = OB_SINGLE_ARROW;
+ }
+
+ ob->pd = BKE_partdeflect_new(type);
+
+ DEG_relations_tag_update(CTX_data_main(C));
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_effector_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Effector";
- ot->description = "Add an empty object with a physics effector to the scene";
- ot->idname = "OBJECT_OT_effector_add";
+ /* identifiers */
+ ot->name = "Add Effector";
+ ot->description = "Add an empty object with a physics effector to the scene";
+ ot->idname = "OBJECT_OT_effector_add";
- /* api callbacks */
- ot->exec = effector_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = effector_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", field_type_items, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", field_type_items, 0, "Type", "");
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
/********************* Add Camera Operator ********************/
static int object_camera_add_exec(bContext *C, wmOperator *op)
{
- View3D *v3d = CTX_wm_view3d(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob;
- Camera *cam;
- bool enter_editmode;
- ushort local_view_bits;
- float loc[3], rot[3];
+ View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob;
+ Camera *cam;
+ bool enter_editmode;
+ ushort local_view_bits;
+ float loc[3], rot[3];
- /* force view align for cameras */
- RNA_boolean_set(op->ptr, "view_align", true);
+ /* force view align for cameras */
+ RNA_boolean_set(op->ptr, "view_align", true);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- ob = ED_object_add_type(C, OB_CAMERA, NULL, loc, rot, false, local_view_bits);
+ if (!ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ ob = ED_object_add_type(C, OB_CAMERA, NULL, loc, rot, false, local_view_bits);
- if (v3d) {
- if (v3d->camera == NULL)
- v3d->camera = ob;
- if (v3d->scenelock && scene->camera == NULL) {
- scene->camera = ob;
- }
- }
+ if (v3d) {
+ if (v3d->camera == NULL)
+ v3d->camera = ob;
+ if (v3d->scenelock && scene->camera == NULL) {
+ scene->camera = ob;
+ }
+ }
- cam = ob->data;
- cam->drawsize = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : ED_scene_grid_scale(scene, NULL);
+ cam = ob->data;
+ cam->drawsize = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : ED_scene_grid_scale(scene, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_camera_add(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Add Camera";
- ot->description = "Add a camera object to the scene";
- ot->idname = "OBJECT_OT_camera_add";
+ /* identifiers */
+ ot->name = "Add Camera";
+ ot->description = "Add a camera object to the scene";
+ ot->idname = "OBJECT_OT_camera_add";
- /* api callbacks */
- ot->exec = object_camera_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = object_camera_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_generic_props(ot, true);
+ ED_object_add_generic_props(ot, true);
- /* hide this for cameras, default */
- prop = RNA_struct_type_find_property(ot->srna, "view_align");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ /* hide this for cameras, default */
+ prop = RNA_struct_type_find_property(ot->srna, "view_align");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
-
/********************* Add Metaball Operator ********************/
static int object_metaball_add_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- bool newob = false;
- bool enter_editmode;
- ushort local_view_bits;
- float loc[3], rot[3];
- float mat[4][4];
- float dia;
+ Object *obedit = CTX_data_edit_object(C);
+ bool newob = false;
+ bool enter_editmode;
+ ushort local_view_bits;
+ float loc[3], rot[3];
+ float mat[4][4];
+ float dia;
- WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- if (obedit == NULL || obedit->type != OB_MBALL) {
- obedit = ED_object_add_type(C, OB_MBALL, NULL, loc, rot, true, local_view_bits);
- newob = true;
- }
- else {
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ if (obedit == NULL || obedit->type != OB_MBALL) {
+ obedit = ED_object_add_type(C, OB_MBALL, NULL, loc, rot, true, local_view_bits);
+ newob = true;
+ }
+ else {
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ }
- ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
- dia = RNA_float_get(op->ptr, "radius");
+ ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
+ dia = RNA_float_get(op->ptr, "radius");
- ED_mball_add_primitive(C, obedit, mat, dia, RNA_enum_get(op->ptr, "type"));
+ ED_mball_add_primitive(C, obedit, mat, dia, RNA_enum_get(op->ptr, "type"));
- /* userdef */
- if (newob && !enter_editmode) {
- ED_object_editmode_exit(C, EM_FREEDATA);
- }
+ /* userdef */
+ if (newob && !enter_editmode) {
+ ED_object_editmode_exit(C, EM_FREEDATA);
+ }
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_metaball_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Metaball";
- ot->description = "Add an metaball object to the scene";
- ot->idname = "OBJECT_OT_metaball_add";
+ /* identifiers */
+ ot->name = "Add Metaball";
+ ot->description = "Add an metaball object to the scene";
+ ot->idname = "OBJECT_OT_metaball_add";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_metaball_add_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_metaball_add_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_metaelem_type_items, 0, "Primitive", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_metaelem_type_items, 0, "Primitive", "");
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
/********************* Add Text Operator ********************/
static int object_add_text_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- bool enter_editmode;
- ushort local_view_bits;
- float loc[3], rot[3];
+ Object *obedit = CTX_data_edit_object(C);
+ bool enter_editmode;
+ ushort local_view_bits;
+ float loc[3], rot[3];
- WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- if (obedit && obedit->type == OB_FONT)
- return OPERATOR_CANCELLED;
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ if (obedit && obedit->type == OB_FONT)
+ return OPERATOR_CANCELLED;
- obedit = ED_object_add_type(C, OB_FONT, NULL, loc, rot, enter_editmode, local_view_bits);
- BKE_object_obdata_size_init(obedit, RNA_float_get(op->ptr, "radius"));
+ obedit = ED_object_add_type(C, OB_FONT, NULL, loc, rot, enter_editmode, local_view_bits);
+ BKE_object_obdata_size_init(obedit, RNA_float_get(op->ptr, "radius"));
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_text_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Text";
- ot->description = "Add a text object to the scene";
- ot->idname = "OBJECT_OT_text_add";
+ /* identifiers */
+ ot->name = "Add Text";
+ ot->description = "Add a text object to the scene";
+ ot->idname = "OBJECT_OT_text_add";
- /* api callbacks */
- ot->exec = object_add_text_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = object_add_text_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ /* properties */
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
/********************* Add Armature Operator ********************/
static int object_armature_add_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- bool newob = false;
- bool enter_editmode;
- ushort local_view_bits;
- float loc[3], rot[3], dia;
- bool view_aligned = rv3d && (U.flag & USER_ADD_VIEWALIGNED);
-
- WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- if ((obedit == NULL) || (obedit->type != OB_ARMATURE)) {
- obedit = ED_object_add_type(C, OB_ARMATURE, NULL, loc, rot, true, local_view_bits);
- ED_object_editmode_enter(C, 0);
- newob = true;
- }
- else {
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
-
- if (obedit == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Cannot create editmode armature");
- return OPERATOR_CANCELLED;
- }
-
- dia = RNA_float_get(op->ptr, "radius");
- ED_armature_ebone_add_primitive(obedit, dia, view_aligned);
-
- /* userdef */
- if (newob && !enter_editmode)
- ED_object_editmode_exit(C, EM_FREEDATA);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
-
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_edit_object(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ bool newob = false;
+ bool enter_editmode;
+ ushort local_view_bits;
+ float loc[3], rot[3], dia;
+ bool view_aligned = rv3d && (U.flag & USER_ADD_VIEWALIGNED);
+
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ if ((obedit == NULL) || (obedit->type != OB_ARMATURE)) {
+ obedit = ED_object_add_type(C, OB_ARMATURE, NULL, loc, rot, true, local_view_bits);
+ ED_object_editmode_enter(C, 0);
+ newob = true;
+ }
+ else {
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ }
+
+ if (obedit == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot create editmode armature");
+ return OPERATOR_CANCELLED;
+ }
+
+ dia = RNA_float_get(op->ptr, "radius");
+ ED_armature_ebone_add_primitive(obedit, dia, view_aligned);
+
+ /* userdef */
+ if (newob && !enter_editmode)
+ ED_object_editmode_exit(C, EM_FREEDATA);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_armature_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Armature";
- ot->description = "Add an armature object to the scene";
- ot->idname = "OBJECT_OT_armature_add";
+ /* identifiers */
+ ot->name = "Add Armature";
+ ot->description = "Add an armature object to the scene";
+ ot->idname = "OBJECT_OT_armature_add";
- /* api callbacks */
- ot->exec = object_armature_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = object_armature_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ /* properties */
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
/********************* Add Empty Operator ********************/
static int object_empty_add_exec(bContext *C, wmOperator *op)
{
- Object *ob;
- int type = RNA_enum_get(op->ptr, "type");
- ushort local_view_bits;
- float loc[3], rot[3];
+ Object *ob;
+ int type = RNA_enum_get(op->ptr, "type");
+ ushort local_view_bits;
+ float loc[3], rot[3];
- WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- ob = ED_object_add_type(C, OB_EMPTY, NULL, loc, rot, false, local_view_bits);
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ ob = ED_object_add_type(C, OB_EMPTY, NULL, loc, rot, false, local_view_bits);
- BKE_object_empty_draw_type_set(ob, type);
- BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius"));
+ BKE_object_empty_draw_type_set(ob, type);
+ BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius"));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_empty_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Empty";
- ot->description = "Add an empty object to the scene";
- ot->idname = "OBJECT_OT_empty_add";
+ /* identifiers */
+ ot->name = "Add Empty";
+ ot->description = "Add an empty object to the scene";
+ ot->idname = "OBJECT_OT_empty_add";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_empty_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_empty_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_empty_drawtype_items, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_empty_drawtype_items, 0, "Type", "");
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, false);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, false);
}
static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- Image *ima = NULL;
+ Image *ima = NULL;
- ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
- if (!ima) {
- return OPERATOR_CANCELLED;
- }
- /* handled below */
- id_us_min((ID *)ima);
+ ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
+ if (!ima) {
+ return OPERATOR_CANCELLED;
+ }
+ /* handled below */
+ id_us_min((ID *)ima);
- Object *ob = NULL;
- Object *ob_cursor = ED_view3d_give_object_under_cursor(C, event->mval);
+ Object *ob = NULL;
+ Object *ob_cursor = ED_view3d_give_object_under_cursor(C, event->mval);
- /* either change empty under cursor or create a new empty */
- if (ob_cursor && ob_cursor->type == OB_EMPTY) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
- DEG_id_tag_update((ID *)ob_cursor, ID_RECALC_TRANSFORM);
- ob = ob_cursor;
- }
- else {
- /* add new empty */
- ushort local_view_bits;
- float rot[3];
+ /* either change empty under cursor or create a new empty */
+ if (ob_cursor && ob_cursor->type == OB_EMPTY) {
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+ DEG_id_tag_update((ID *)ob_cursor, ID_RECALC_TRANSFORM);
+ ob = ob_cursor;
+ }
+ else {
+ /* add new empty */
+ ushort local_view_bits;
+ float rot[3];
- if (!ED_object_add_generic_get_opts(C, op, 'Z', NULL, rot, NULL, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- ob = ED_object_add_type(C, OB_EMPTY, NULL, NULL, rot, false, local_view_bits);
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', NULL, rot, NULL, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ ob = ED_object_add_type(C, OB_EMPTY, NULL, NULL, rot, false, local_view_bits);
- ED_object_location_from_view(C, ob->loc);
- ED_view3d_cursor3d_position(C, event->mval, false, ob->loc);
- ED_object_rotation_from_view(C, ob->rot, 'Z');
- ob->empty_drawsize = 5.0f;
- }
+ ED_object_location_from_view(C, ob->loc);
+ ED_view3d_cursor3d_position(C, event->mval, false, ob->loc);
+ ED_object_rotation_from_view(C, ob->rot, 'Z');
+ ob->empty_drawsize = 5.0f;
+ }
- BKE_object_empty_draw_type_set(ob, OB_EMPTY_IMAGE);
+ BKE_object_empty_draw_type_set(ob, OB_EMPTY_IMAGE);
- id_us_min(ob->data);
- ob->data = ima;
- id_us_plus(ob->data);
+ id_us_min(ob->data);
+ ob->data = ima;
+ id_us_plus(ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_drop_named_image(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Add Empty Image/Drop Image To Empty";
- ot->description = "Add an empty image type to scene with data";
- ot->idname = "OBJECT_OT_drop_named_image";
+ /* identifiers */
+ ot->name = "Add Empty Image/Drop Image To Empty";
+ ot->description = "Add an empty image type to scene with data";
+ ot->idname = "OBJECT_OT_drop_named_image";
- /* api callbacks */
- ot->invoke = empty_drop_named_image_invoke;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->invoke = empty_drop_named_image_invoke;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- prop = RNA_def_string(ot->srna, "filepath", NULL, FILE_MAX, "Filepath", "Path to image file");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- RNA_def_boolean(ot->srna, "relative_path", true, "Relative Path", "Select the file relative to the blend file");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Image name to assign");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- ED_object_add_generic_props(ot, false);
+ /* properties */
+ prop = RNA_def_string(ot->srna, "filepath", NULL, FILE_MAX, "Filepath", "Path to image file");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ RNA_def_boolean(ot->srna,
+ "relative_path",
+ true,
+ "Relative Path",
+ "Select the file relative to the blend file");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Image name to assign");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ ED_object_add_generic_props(ot, false);
}
/********************* Add Gpencil Operator ********************/
static bool object_gpencil_add_poll(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- Object *obact = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obact = CTX_data_active_object(C);
- if ((scene == NULL) || (ID_IS_LINKED(scene))) {
- return false;
- }
+ if ((scene == NULL) || (ID_IS_LINKED(scene))) {
+ return false;
+ }
- if (obact && obact->type == OB_GPENCIL) {
- if (obact->mode != OB_MODE_OBJECT) {
- return false;
- }
- }
+ if (obact && obact->type == OB_GPENCIL) {
+ if (obact->mode != OB_MODE_OBJECT) {
+ return false;
+ }
+ }
- return true;
+ return true;
}
static int object_gpencil_add_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
- bGPdata *gpd = (ob && (ob->type == OB_GPENCIL)) ? ob->data : NULL;
-
- const int type = RNA_enum_get(op->ptr, "type");
-
- ushort local_view_bits;
- float loc[3], rot[3];
- bool newob = false;
-
- /* Note: We use 'Y' here (not 'Z'), as */
- WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Y', loc, rot, NULL, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- /* add new object if not currently editing a GP object,
- * or if "empty" was chosen (i.e. user wants a blank GP canvas)
- */
- if ((gpd == NULL) || (GPENCIL_ANY_MODE(gpd) == false) || (type == GP_EMPTY)) {
- const char *ob_name = NULL;
- switch (type) {
- case GP_MONKEY:
- {
- ob_name = "Suzanne";
- break;
- }
- case GP_STROKE:
- {
- ob_name = "Stroke";
- break;
- }
- default:
- {
- break;
- }
- }
-
- ob = ED_object_add_type(C, OB_GPENCIL, ob_name, loc, rot, true, local_view_bits);
- gpd = ob->data;
- newob = true;
- }
- else {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_ADDED, NULL);
- }
-
- /* create relevant geometry */
- switch (type) {
- case GP_STROKE:
- {
- float radius = RNA_float_get(op->ptr, "radius");
- float mat[4][4];
-
- ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
- mul_v3_fl(mat[0], radius);
- mul_v3_fl(mat[1], radius);
- mul_v3_fl(mat[2], radius);
-
- ED_gpencil_create_stroke(C, ob, mat);
- break;
- }
- case GP_MONKEY:
- {
- float radius = RNA_float_get(op->ptr, "radius");
- float mat[4][4];
-
- ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
- mul_v3_fl(mat[0], radius);
- mul_v3_fl(mat[1], radius);
- mul_v3_fl(mat[2], radius);
-
- ED_gpencil_create_monkey(C, ob, mat);
- break;
- }
- case GP_EMPTY:
- /* do nothing */
- break;
-
- default:
- BKE_report(op->reports, RPT_WARNING, "Not implemented");
- break;
- }
-
- /* if this is a new object, initialise default stuff (colors, etc.) */
- if (newob) {
- /* set default viewport color to black */
- copy_v3_fl(ob->color, 0.0f);
-
- ED_gpencil_add_defaults(C, ob);
- }
-
- return OPERATOR_FINISHED;
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (ob && (ob->type == OB_GPENCIL)) ? ob->data : NULL;
+
+ const int type = RNA_enum_get(op->ptr, "type");
+
+ ushort local_view_bits;
+ float loc[3], rot[3];
+ bool newob = false;
+
+ /* Note: We use 'Y' here (not 'Z'), as */
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(C, op, 'Y', loc, rot, NULL, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ /* add new object if not currently editing a GP object,
+ * or if "empty" was chosen (i.e. user wants a blank GP canvas)
+ */
+ if ((gpd == NULL) || (GPENCIL_ANY_MODE(gpd) == false) || (type == GP_EMPTY)) {
+ const char *ob_name = NULL;
+ switch (type) {
+ case GP_MONKEY: {
+ ob_name = "Suzanne";
+ break;
+ }
+ case GP_STROKE: {
+ ob_name = "Stroke";
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+
+ ob = ED_object_add_type(C, OB_GPENCIL, ob_name, loc, rot, true, local_view_bits);
+ gpd = ob->data;
+ newob = true;
+ }
+ else {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_ADDED, NULL);
+ }
+
+ /* create relevant geometry */
+ switch (type) {
+ case GP_STROKE: {
+ float radius = RNA_float_get(op->ptr, "radius");
+ float mat[4][4];
+
+ ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
+ mul_v3_fl(mat[0], radius);
+ mul_v3_fl(mat[1], radius);
+ mul_v3_fl(mat[2], radius);
+
+ ED_gpencil_create_stroke(C, ob, mat);
+ break;
+ }
+ case GP_MONKEY: {
+ float radius = RNA_float_get(op->ptr, "radius");
+ float mat[4][4];
+
+ ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
+ mul_v3_fl(mat[0], radius);
+ mul_v3_fl(mat[1], radius);
+ mul_v3_fl(mat[2], radius);
+
+ ED_gpencil_create_monkey(C, ob, mat);
+ break;
+ }
+ case GP_EMPTY:
+ /* do nothing */
+ break;
+
+ default:
+ BKE_report(op->reports, RPT_WARNING, "Not implemented");
+ break;
+ }
+
+ /* if this is a new object, initialise default stuff (colors, etc.) */
+ if (newob) {
+ /* set default viewport color to black */
+ copy_v3_fl(ob->color, 0.0f);
+
+ ED_gpencil_add_defaults(C, ob);
+ }
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_gpencil_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Grease Pencil";
- ot->description = "Add a Grease Pencil object to the scene";
- ot->idname = "OBJECT_OT_gpencil_add";
+ /* identifiers */
+ ot->name = "Add Grease Pencil";
+ ot->description = "Add a Grease Pencil object to the scene";
+ ot->idname = "OBJECT_OT_gpencil_add";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_gpencil_add_exec;
- ot->poll = object_gpencil_add_poll;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_gpencil_add_exec;
+ ot->poll = object_gpencil_add_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, false);
+ /* properties */
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, false);
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_gpencil_type_items, 0, "Type", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_gpencil_type_items, 0, "Type", "");
}
/********************* Add Light Operator ********************/
static const char *get_light_defname(int type)
{
- switch (type) {
- case LA_LOCAL: return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Point");
- case LA_SUN: return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Sun");
- case LA_SPOT: return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Spot");
- case LA_AREA: return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Area");
- default:
- return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Light");
- }
+ switch (type) {
+ case LA_LOCAL:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Point");
+ case LA_SUN:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Sun");
+ case LA_SPOT:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Spot");
+ case LA_AREA:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Area");
+ default:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Light");
+ }
}
static int object_light_add_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob;
- Light *la;
- int type = RNA_enum_get(op->ptr, "type");
- ushort local_view_bits;
- float loc[3], rot[3];
-
- WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- ob = ED_object_add_type(C, OB_LAMP, get_light_defname(type), loc, rot, false, local_view_bits);
-
- float size = RNA_float_get(op->ptr, "radius");
- /* Better defaults for light size. */
- switch (type) {
- case LA_LOCAL:
- case LA_SPOT:
- break;
- case LA_AREA:
- size *= 4.0f;
- break;
- default:
- size *= 0.5f;
- break;
- }
- BKE_object_obdata_size_init(ob, size);
-
- la = (Light *)ob->data;
- la->type = type;
-
- if (BKE_scene_uses_cycles(scene)) {
- ED_node_shader_default(C, &la->id);
- la->use_nodes = true;
- }
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Object *ob;
+ Light *la;
+ int type = RNA_enum_get(op->ptr, "type");
+ ushort local_view_bits;
+ float loc[3], rot[3];
+
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ ob = ED_object_add_type(C, OB_LAMP, get_light_defname(type), loc, rot, false, local_view_bits);
+
+ float size = RNA_float_get(op->ptr, "radius");
+ /* Better defaults for light size. */
+ switch (type) {
+ case LA_LOCAL:
+ case LA_SPOT:
+ break;
+ case LA_AREA:
+ size *= 4.0f;
+ break;
+ default:
+ size *= 0.5f;
+ break;
+ }
+ BKE_object_obdata_size_init(ob, size);
+
+ la = (Light *)ob->data;
+ la->type = type;
+
+ if (BKE_scene_uses_cycles(scene)) {
+ ED_node_shader_default(C, &la->id);
+ la->use_nodes = true;
+ }
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_light_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Light";
- ot->description = "Add a light object to the scene";
- ot->idname = "OBJECT_OT_light_add";
+ /* identifiers */
+ ot->name = "Add Light";
+ ot->description = "Add a light object to the scene";
+ ot->idname = "OBJECT_OT_light_add";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_light_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_light_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_light_type_items, 0, "Type", "");
- RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_LIGHT);
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_light_type_items, 0, "Type", "");
+ RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_LIGHT);
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, false);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, false);
}
/********************* Add Collection Instance Operator ********************/
static int collection_instance_add_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Collection *collection;
- ushort local_view_bits;
- float loc[3], rot[3];
-
- if (RNA_struct_property_is_set(op->ptr, "name")) {
- char name[MAX_ID_NAME - 2];
-
- RNA_string_get(op->ptr, "name", name);
- collection = (Collection *)BKE_libblock_find_name(bmain, ID_GR, name);
-
- 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};
- 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"));
-
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- if (collection) {
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- /* Avoid dependency cycles. */
- LayerCollection *active_lc = BKE_layer_collection_get_active(view_layer);
- while (BKE_collection_find_cycle(active_lc->collection, collection)) {
- active_lc = BKE_layer_collection_activate_parent(view_layer, active_lc);
- }
-
- Object *ob = ED_object_add_type(C, OB_EMPTY, collection->id.name + 2, loc, rot, false, local_view_bits);
- ob->instance_collection = collection;
- ob->transflag |= OB_DUPLICOLLECTION;
- id_us_plus(&collection->id);
-
- /* works without this except if you try render right after, see: 22027 */
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
-
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_CANCELLED;
+ Main *bmain = CTX_data_main(C);
+ Collection *collection;
+ ushort local_view_bits;
+ float loc[3], rot[3];
+
+ if (RNA_struct_property_is_set(op->ptr, "name")) {
+ char name[MAX_ID_NAME - 2];
+
+ RNA_string_get(op->ptr, "name", name);
+ collection = (Collection *)BKE_libblock_find_name(bmain, ID_GR, name);
+
+ 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};
+ 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"));
+
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ if (collection) {
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ /* Avoid dependency cycles. */
+ LayerCollection *active_lc = BKE_layer_collection_get_active(view_layer);
+ while (BKE_collection_find_cycle(active_lc->collection, collection)) {
+ active_lc = BKE_layer_collection_activate_parent(view_layer, active_lc);
+ }
+
+ Object *ob = ED_object_add_type(
+ C, OB_EMPTY, collection->id.name + 2, loc, rot, false, local_view_bits);
+ ob->instance_collection = collection;
+ ob->transflag |= OB_DUPLICOLLECTION;
+ id_us_plus(&collection->id);
+
+ /* works without this except if you try render right after, see: 22027 */
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
}
/* only used as menu */
void OBJECT_OT_collection_instance_add(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Add Collection Instance";
- ot->description = "Add a collection instance";
- ot->idname = "OBJECT_OT_collection_instance_add";
+ /* identifiers */
+ ot->name = "Add Collection Instance";
+ ot->description = "Add a collection instance";
+ ot->idname = "OBJECT_OT_collection_instance_add";
- /* api callbacks */
- ot->invoke = WM_enum_search_invoke;
- ot->exec = collection_instance_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->invoke = WM_enum_search_invoke;
+ ot->exec = collection_instance_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_string(ot->srna, "name", "Collection", MAX_ID_NAME - 2, "Name", "Collection name to add");
- prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "");
- RNA_def_enum_funcs(prop, RNA_collection_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
- ED_object_add_generic_props(ot, false);
+ /* properties */
+ RNA_def_string(
+ ot->srna, "name", "Collection", MAX_ID_NAME - 2, "Name", "Collection name to add");
+ prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "");
+ RNA_def_enum_funcs(prop, RNA_collection_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
+ ED_object_add_generic_props(ot, false);
}
/********************* Add Speaker Operator ********************/
static int object_speaker_add_exec(bContext *C, wmOperator *op)
{
- Object *ob;
- ushort local_view_bits;
- float loc[3], rot[3];
- Scene *scene = CTX_data_scene(C);
+ Object *ob;
+ ushort local_view_bits;
+ float loc[3], rot[3];
+ Scene *scene = CTX_data_scene(C);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- ob = ED_object_add_type(C, OB_SPEAKER, NULL, loc, rot, false, local_view_bits);
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ ob = ED_object_add_type(C, OB_SPEAKER, NULL, loc, rot, false, local_view_bits);
- /* to make it easier to start using this immediately in NLA, a default sound clip is created
- * ready to be moved around to retime the sound and/or make new sound clips
- */
- {
- /* create new data for NLA hierarchy */
- AnimData *adt = BKE_animdata_add_id(&ob->id);
- NlaTrack *nlt = BKE_nlatrack_add(adt, NULL);
- NlaStrip *strip = BKE_nla_add_soundstrip(scene, ob->data);
- strip->start = CFRA;
- strip->end += strip->start;
+ /* to make it easier to start using this immediately in NLA, a default sound clip is created
+ * ready to be moved around to retime the sound and/or make new sound clips
+ */
+ {
+ /* create new data for NLA hierarchy */
+ AnimData *adt = BKE_animdata_add_id(&ob->id);
+ NlaTrack *nlt = BKE_nlatrack_add(adt, NULL);
+ NlaStrip *strip = BKE_nla_add_soundstrip(scene, ob->data);
+ strip->start = CFRA;
+ strip->end += strip->start;
- /* hook them up */
- BKE_nlatrack_add_strip(nlt, strip);
+ /* hook them up */
+ BKE_nlatrack_add_strip(nlt, strip);
- /* auto-name the strip, and give the track an interesting name */
- BLI_strncpy(nlt->name, DATA_("SoundTrack"), sizeof(nlt->name));
- BKE_nlastrip_validate_name(adt, strip);
+ /* auto-name the strip, and give the track an interesting name */
+ BLI_strncpy(nlt->name, DATA_("SoundTrack"), sizeof(nlt->name));
+ BKE_nlastrip_validate_name(adt, strip);
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
- }
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_speaker_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Speaker";
- ot->description = "Add a speaker object to the scene";
- ot->idname = "OBJECT_OT_speaker_add";
+ /* identifiers */
+ ot->name = "Add Speaker";
+ ot->description = "Add a speaker object to the scene";
+ ot->idname = "OBJECT_OT_speaker_add";
- /* api callbacks */
- ot->exec = object_speaker_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = object_speaker_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_generic_props(ot, true);
+ ED_object_add_generic_props(ot, true);
}
/**************************** Delete Object *************************/
@@ -1320,143 +1368,153 @@ void OBJECT_OT_speaker_add(wmOperatorType *ot)
/* note: now unlinks constraints as well */
void ED_object_base_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
{
- if (BKE_library_ID_is_indirectly_used(bmain, ob) &&
- ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0)
- {
- /* We cannot delete indirectly used object... */
- printf("WARNING, undeletable object '%s', should have been catched before reaching this function!",
- ob->id.name + 2);
- return;
- }
+ if (BKE_library_ID_is_indirectly_used(bmain, ob) && ID_REAL_USERS(ob) <= 1 &&
+ ID_EXTRA_USERS(ob) == 0) {
+ /* We cannot delete indirectly used object... */
+ printf(
+ "WARNING, undeletable object '%s', should have been catched before reaching this "
+ "function!",
+ ob->id.name + 2);
+ return;
+ }
- DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_BASE_FLAGS);
+ DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_BASE_FLAGS);
- BKE_scene_collections_object_remove(bmain, scene, ob, true);
+ BKE_scene_collections_object_remove(bmain, scene, ob, true);
}
static int object_delete_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win;
- const bool use_global = RNA_boolean_get(op->ptr, "use_global");
- uint changed_count = 0;
-
- if (CTX_data_edit_object(C))
- return OPERATOR_CANCELLED;
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- const bool is_indirectly_used = BKE_library_ID_is_indirectly_used(bmain, ob);
- if (ob->id.tag & LIB_TAG_INDIRECT) {
- /* Can this case ever happen? */
- BKE_reportf(op->reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", ob->id.name + 2);
- continue;
- }
- else if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) {
- BKE_reportf(op->reports, RPT_WARNING,
- "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
- ob->id.name + 2, scene->id.name + 2);
- continue;
- }
-
- /* if grease pencil object, set cache as dirty */
- if (ob->type == OB_GPENCIL) {
- bGPdata *gpd = (bGPdata *)ob->data;
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- }
-
- /* This is sort of a quick hack to address T51243 - Proper thing to do here would be to nuke most of all this
- * custom scene/object/base handling, and use generic lib remap/query for that.
- * But this is for later (aka 2.8, once layers & co are settled and working).
- */
- if (use_global && ob->id.lib == NULL) {
- /* We want to nuke the object, let's nuke it the easy way (not for linked data though)... */
- BKE_id_delete(bmain, &ob->id);
- changed_count += 1;
- continue;
- }
-
- /* remove from Grease Pencil parent */
- /* XXX This is likely not correct? 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) {
- if (gpl->parent != NULL) {
- if (gpl->parent == ob) {
- gpl->parent = NULL;
- }
- }
- }
- }
-
- /* remove from current scene only */
- ED_object_base_free_and_unlink(bmain, scene, ob);
- changed_count += 1;
-
- if (use_global) {
- Scene *scene_iter;
- for (scene_iter = bmain->scenes.first; scene_iter; scene_iter = scene_iter->id.next) {
- if (scene_iter != scene && !ID_IS_LINKED(scene_iter)) {
- if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) {
- BKE_reportf(op->reports, RPT_WARNING,
- "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
- ob->id.name + 2, scene_iter->id.name + 2);
- break;
- }
- ED_object_base_free_and_unlink(bmain, scene_iter, ob);
- }
- }
- }
- /* end global */
- }
- CTX_DATA_END;
-
- BKE_reportf(op->reports, RPT_INFO, "Deleted %u object(s)", changed_count);
-
- if (changed_count == 0) {
- return OPERATOR_CANCELLED;
- }
-
- /* delete has to handle all open scenes */
- BKE_main_id_tag_listbase(&bmain->scenes, LIB_TAG_DOIT, true);
- for (win = wm->windows.first; win; win = win->next) {
- scene = WM_window_get_active_scene(win);
-
- if (scene->id.tag & LIB_TAG_DOIT) {
- scene->id.tag &= ~LIB_TAG_DOIT;
-
- DEG_relations_tag_update(bmain);
-
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
- }
- }
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win;
+ const bool use_global = RNA_boolean_get(op->ptr, "use_global");
+ uint changed_count = 0;
+
+ if (CTX_data_edit_object(C))
+ return OPERATOR_CANCELLED;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ const bool is_indirectly_used = BKE_library_ID_is_indirectly_used(bmain, ob);
+ if (ob->id.tag & LIB_TAG_INDIRECT) {
+ /* Can this case ever happen? */
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Cannot delete indirectly linked object '%s'",
+ ob->id.name + 2);
+ continue;
+ }
+ else if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Cannot delete object '%s' from scene '%s', indirectly used objects need at "
+ "least one user",
+ ob->id.name + 2,
+ scene->id.name + 2);
+ continue;
+ }
+
+ /* if grease pencil object, set cache as dirty */
+ if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = (bGPdata *)ob->data;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ }
+
+ /* This is sort of a quick hack to address T51243 - Proper thing to do here would be to nuke most of all this
+ * custom scene/object/base handling, and use generic lib remap/query for that.
+ * But this is for later (aka 2.8, once layers & co are settled and working).
+ */
+ if (use_global && ob->id.lib == NULL) {
+ /* We want to nuke the object, let's nuke it the easy way (not for linked data though)... */
+ BKE_id_delete(bmain, &ob->id);
+ changed_count += 1;
+ continue;
+ }
+
+ /* remove from Grease Pencil parent */
+ /* XXX This is likely not correct? 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) {
+ if (gpl->parent != NULL) {
+ if (gpl->parent == ob) {
+ gpl->parent = NULL;
+ }
+ }
+ }
+ }
+
+ /* remove from current scene only */
+ ED_object_base_free_and_unlink(bmain, scene, ob);
+ changed_count += 1;
+
+ if (use_global) {
+ Scene *scene_iter;
+ for (scene_iter = bmain->scenes.first; scene_iter; scene_iter = scene_iter->id.next) {
+ if (scene_iter != scene && !ID_IS_LINKED(scene_iter)) {
+ if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Cannot delete object '%s' from scene '%s', indirectly used objects need "
+ "at least one user",
+ ob->id.name + 2,
+ scene_iter->id.name + 2);
+ break;
+ }
+ ED_object_base_free_and_unlink(bmain, scene_iter, ob);
+ }
+ }
+ }
+ /* end global */
+ }
+ CTX_DATA_END;
+
+ BKE_reportf(op->reports, RPT_INFO, "Deleted %u object(s)", changed_count);
+
+ if (changed_count == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* delete has to handle all open scenes */
+ BKE_main_id_tag_listbase(&bmain->scenes, LIB_TAG_DOIT, true);
+ for (win = wm->windows.first; win; win = win->next) {
+ scene = WM_window_get_active_scene(win);
+
+ if (scene->id.tag & LIB_TAG_DOIT) {
+ scene->id.tag &= ~LIB_TAG_DOIT;
+
+ DEG_relations_tag_update(bmain);
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete";
- ot->description = "Delete selected objects";
- ot->idname = "OBJECT_OT_delete";
+ /* identifiers */
+ ot->name = "Delete";
+ ot->description = "Delete selected objects";
+ ot->idname = "OBJECT_OT_delete";
- /* api callbacks */
- ot->invoke = WM_operator_confirm_or_exec;
- ot->exec = object_delete_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm_or_exec;
+ ot->exec = object_delete_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- PropertyRNA *prop;
- prop = RNA_def_boolean(ot->srna, "use_global", 0, "Delete Globally", "Remove object from all scenes");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- WM_operator_properties_confirm_or_exec(ot);
+ PropertyRNA *prop;
+ prop = RNA_def_boolean(
+ ot->srna, "use_global", 0, "Delete Globally", "Remove object from all scenes");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ WM_operator_properties_confirm_or_exec(ot);
}
/**************************** Copy Utilities ******************************/
@@ -1464,15 +1522,14 @@ void OBJECT_OT_delete(wmOperatorType *ot)
/* after copying objects, copied data should get new pointers */
static void copy_object_set_idnew(bContext *C)
{
- Main *bmain = CTX_data_main(C);
+ Main *bmain = CTX_data_main(C);
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- BKE_libblock_relink_to_newid(&ob->id);
- }
- CTX_DATA_END;
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ BKE_libblock_relink_to_newid(&ob->id);
+ }
+ CTX_DATA_END;
- BKE_main_id_clear_newpoins(bmain);
+ BKE_main_id_clear_newpoins(bmain);
}
/********************* Make Duplicates Real ************************/
@@ -1483,13 +1540,13 @@ static void copy_object_set_idnew(bContext *C)
*/
static unsigned int dupliobject_group_hash(const void *ptr)
{
- const DupliObject *dob = ptr;
- unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
- unsigned int i;
- for (i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
- hash ^= (dob->persistent_id[i] ^ i);
- }
- return hash;
+ const DupliObject *dob = ptr;
+ unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
+ unsigned int i;
+ for (i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
+ hash ^= (dob->persistent_id[i] ^ i);
+ }
+ return hash;
}
/**
@@ -1498,704 +1555,714 @@ static unsigned int dupliobject_group_hash(const void *ptr)
*/
static unsigned int dupliobject_hash(const void *ptr)
{
- const DupliObject *dob = ptr;
- unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
- hash ^= (dob->persistent_id[0] ^ 0);
- return hash;
+ const DupliObject *dob = ptr;
+ unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
+ hash ^= (dob->persistent_id[0] ^ 0);
+ return hash;
}
/* Compare function that matches dupliobject_group_hash */
static bool dupliobject_group_cmp(const void *a_, const void *b_)
{
- const DupliObject *a = a_;
- const DupliObject *b = b_;
- unsigned int i;
+ const DupliObject *a = a_;
+ const DupliObject *b = b_;
+ unsigned int i;
- if (a->ob != b->ob) {
- return true;
- }
+ if (a->ob != b->ob) {
+ return true;
+ }
- for (i = 1; (i < MAX_DUPLI_RECUR); i++) {
- if (a->persistent_id[i] != b->persistent_id[i]) {
- return true;
- }
- else if (a->persistent_id[i] == INT_MAX) {
- break;
- }
- }
+ for (i = 1; (i < MAX_DUPLI_RECUR); i++) {
+ if (a->persistent_id[i] != b->persistent_id[i]) {
+ return true;
+ }
+ else if (a->persistent_id[i] == INT_MAX) {
+ break;
+ }
+ }
- /* matching */
- return false;
+ /* matching */
+ return false;
}
/* Compare function that matches dupliobject_hash */
static bool dupliobject_cmp(const void *a_, const void *b_)
{
- const DupliObject *a = a_;
- const DupliObject *b = b_;
-
- if (a->ob != b->ob) {
- return true;
- }
-
- if (a->persistent_id[0] != b->persistent_id[0]) {
- return true;
- }
-
- /* matching */
- return false;
-}
-
-static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
- const bool use_base_parent,
- const bool use_hierarchy)
-{
- Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ListBase *lb_duplis;
- DupliObject *dob;
- GHash *dupli_gh, *parent_gh = NULL;
-
- if (!(base->object->transflag & OB_DUPLI)) {
- return;
- }
-
- Object *object_eval = DEG_get_evaluated_object(depsgraph, base->object);
- lb_duplis = object_duplilist(depsgraph, scene, object_eval);
-
- dupli_gh = BLI_ghash_ptr_new(__func__);
- if (use_hierarchy) {
- if (base->object->transflag & OB_DUPLICOLLECTION) {
- parent_gh = BLI_ghash_new(dupliobject_group_hash, dupliobject_group_cmp, __func__);
- }
- else {
- parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
- }
- }
-
- for (dob = lb_duplis->first; dob; dob = dob->next) {
- Object *ob_src = DEG_get_original_object(dob->ob);
- Object *ob_dst = ID_NEW_SET(dob->ob, BKE_object_copy(bmain, ob_src));
- Base *base_dst;
-
- /* font duplis can have a totcol without material, we get them from parent
- * should be implemented better...
- */
- if (ob_dst->mat == NULL) {
- ob_dst->totcol = 0;
- }
-
- BKE_collection_object_add_from(bmain, scene, base->object, ob_dst);
- base_dst = BKE_view_layer_base_find(view_layer, ob_dst);
- BLI_assert(base_dst != NULL);
-
- BKE_scene_object_base_flag_sync_from_base(base_dst);
-
- /* make sure apply works */
- BKE_animdata_free(&ob_dst->id, true);
- ob_dst->adt = NULL;
-
- /* Proxies are not to be copied. */
- ob_dst->proxy_from = NULL;
- ob_dst->proxy_group = NULL;
- ob_dst->proxy = NULL;
-
- ob_dst->parent = NULL;
- BKE_constraints_free(&ob_dst->constraints);
- ob_dst->runtime.curve_cache = NULL;
- ob_dst->transflag &= ~OB_DUPLI;
-
- copy_m4_m4(ob_dst->obmat, dob->mat);
- BKE_object_apply_mat4(ob_dst, ob_dst->obmat, false, false);
-
- BLI_ghash_insert(dupli_gh, dob, ob_dst);
- if (parent_gh) {
- void **val;
- /* Due to nature of hash/comparison of this ghash, a lot of duplis may be considered as
- * 'the same', this avoids trying to insert same key several time and
- * raise asserts in debug builds... */
- if (!BLI_ghash_ensure_p(parent_gh, dob, &val)) {
- *val = ob_dst;
- }
- }
- }
-
- for (dob = lb_duplis->first; dob; dob = dob->next) {
- Object *ob_src = dob->ob;
- Object *ob_dst = BLI_ghash_lookup(dupli_gh, dob);
-
- /* Remap new object to itself, and clear again newid pointer of orig object. */
- BKE_libblock_relink_to_newid(&ob_dst->id);
-
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
-
- if (use_hierarchy) {
- /* original parents */
- Object *ob_src_par = ob_src->parent;
- Object *ob_dst_par = NULL;
-
- /* find parent that was also made real */
- if (ob_src_par) {
- /* OK to keep most of the members uninitialized,
- * they won't be read, this is simply for a hash lookup. */
- DupliObject dob_key;
- dob_key.ob = ob_src_par;
- if (base->object->transflag & OB_DUPLICOLLECTION) {
- memcpy(&dob_key.persistent_id[1],
- &dob->persistent_id[1],
- sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
- }
- else {
- dob_key.persistent_id[0] = dob->persistent_id[0];
- }
- ob_dst_par = BLI_ghash_lookup(parent_gh, &dob_key);
- }
-
- if (ob_dst_par) {
- /* allow for all possible parent types */
- ob_dst->partype = ob_src->partype;
- BLI_strncpy(ob_dst->parsubstr, ob_src->parsubstr, sizeof(ob_dst->parsubstr));
- ob_dst->par1 = ob_src->par1;
- ob_dst->par2 = ob_src->par2;
- ob_dst->par3 = ob_src->par3;
-
- copy_m4_m4(ob_dst->parentinv, ob_src->parentinv);
-
- ob_dst->parent = ob_dst_par;
- }
- else if (use_base_parent) {
- ob_dst->parent = base->object;
- ob_dst->partype = PAROBJECT;
- }
- }
- else if (use_base_parent) {
- /* since we are ignoring the internal hierarchy - parent all to the
- * base object */
- ob_dst->parent = base->object;
- ob_dst->partype = PAROBJECT;
- }
-
- if (ob_dst->parent) {
- /* note, this may be the parent of other objects, but it should
- * still work out ok */
- BKE_object_apply_mat4(ob_dst, dob->mat, false, true);
-
- /* to set ob_dst->orig and in case there's any other discrepancies */
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM);
- }
- }
-
- if (base->object->transflag & OB_DUPLICOLLECTION && base->object->instance_collection) {
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- if (ob->proxy_group == base->object) {
- ob->proxy = NULL;
- ob->proxy_from = NULL;
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
- }
- }
-
- BLI_ghash_free(dupli_gh, NULL, NULL);
- if (parent_gh) {
- BLI_ghash_free(parent_gh, NULL, NULL);
- }
-
- free_object_duplilist(lb_duplis);
-
- BKE_main_id_clear_newpoins(bmain);
-
- base->object->transflag &= ~OB_DUPLI;
- DEG_id_tag_update(&base->object->id, ID_RECALC_COPY_ON_WRITE);
+ const DupliObject *a = a_;
+ const DupliObject *b = b_;
+
+ if (a->ob != b->ob) {
+ return true;
+ }
+
+ if (a->persistent_id[0] != b->persistent_id[0]) {
+ return true;
+ }
+
+ /* matching */
+ return false;
+}
+
+static void make_object_duplilist_real(
+ bContext *C, Scene *scene, Base *base, const bool use_base_parent, const bool use_hierarchy)
+{
+ Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ListBase *lb_duplis;
+ DupliObject *dob;
+ GHash *dupli_gh, *parent_gh = NULL;
+
+ if (!(base->object->transflag & OB_DUPLI)) {
+ return;
+ }
+
+ Object *object_eval = DEG_get_evaluated_object(depsgraph, base->object);
+ lb_duplis = object_duplilist(depsgraph, scene, object_eval);
+
+ dupli_gh = BLI_ghash_ptr_new(__func__);
+ if (use_hierarchy) {
+ if (base->object->transflag & OB_DUPLICOLLECTION) {
+ parent_gh = BLI_ghash_new(dupliobject_group_hash, dupliobject_group_cmp, __func__);
+ }
+ else {
+ parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
+ }
+ }
+
+ for (dob = lb_duplis->first; dob; dob = dob->next) {
+ Object *ob_src = DEG_get_original_object(dob->ob);
+ Object *ob_dst = ID_NEW_SET(dob->ob, BKE_object_copy(bmain, ob_src));
+ Base *base_dst;
+
+ /* font duplis can have a totcol without material, we get them from parent
+ * should be implemented better...
+ */
+ if (ob_dst->mat == NULL) {
+ ob_dst->totcol = 0;
+ }
+
+ BKE_collection_object_add_from(bmain, scene, base->object, ob_dst);
+ base_dst = BKE_view_layer_base_find(view_layer, ob_dst);
+ BLI_assert(base_dst != NULL);
+
+ BKE_scene_object_base_flag_sync_from_base(base_dst);
+
+ /* make sure apply works */
+ BKE_animdata_free(&ob_dst->id, true);
+ ob_dst->adt = NULL;
+
+ /* Proxies are not to be copied. */
+ ob_dst->proxy_from = NULL;
+ ob_dst->proxy_group = NULL;
+ ob_dst->proxy = NULL;
+
+ ob_dst->parent = NULL;
+ BKE_constraints_free(&ob_dst->constraints);
+ ob_dst->runtime.curve_cache = NULL;
+ ob_dst->transflag &= ~OB_DUPLI;
+
+ copy_m4_m4(ob_dst->obmat, dob->mat);
+ BKE_object_apply_mat4(ob_dst, ob_dst->obmat, false, false);
+
+ BLI_ghash_insert(dupli_gh, dob, ob_dst);
+ if (parent_gh) {
+ void **val;
+ /* Due to nature of hash/comparison of this ghash, a lot of duplis may be considered as
+ * 'the same', this avoids trying to insert same key several time and
+ * raise asserts in debug builds... */
+ if (!BLI_ghash_ensure_p(parent_gh, dob, &val)) {
+ *val = ob_dst;
+ }
+ }
+ }
+
+ for (dob = lb_duplis->first; dob; dob = dob->next) {
+ Object *ob_src = dob->ob;
+ Object *ob_dst = BLI_ghash_lookup(dupli_gh, dob);
+
+ /* Remap new object to itself, and clear again newid pointer of orig object. */
+ BKE_libblock_relink_to_newid(&ob_dst->id);
+
+ DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
+
+ if (use_hierarchy) {
+ /* original parents */
+ Object *ob_src_par = ob_src->parent;
+ Object *ob_dst_par = NULL;
+
+ /* find parent that was also made real */
+ if (ob_src_par) {
+ /* OK to keep most of the members uninitialized,
+ * they won't be read, this is simply for a hash lookup. */
+ DupliObject dob_key;
+ dob_key.ob = ob_src_par;
+ if (base->object->transflag & OB_DUPLICOLLECTION) {
+ memcpy(&dob_key.persistent_id[1],
+ &dob->persistent_id[1],
+ sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
+ }
+ else {
+ dob_key.persistent_id[0] = dob->persistent_id[0];
+ }
+ ob_dst_par = BLI_ghash_lookup(parent_gh, &dob_key);
+ }
+
+ if (ob_dst_par) {
+ /* allow for all possible parent types */
+ ob_dst->partype = ob_src->partype;
+ BLI_strncpy(ob_dst->parsubstr, ob_src->parsubstr, sizeof(ob_dst->parsubstr));
+ ob_dst->par1 = ob_src->par1;
+ ob_dst->par2 = ob_src->par2;
+ ob_dst->par3 = ob_src->par3;
+
+ copy_m4_m4(ob_dst->parentinv, ob_src->parentinv);
+
+ ob_dst->parent = ob_dst_par;
+ }
+ else if (use_base_parent) {
+ ob_dst->parent = base->object;
+ ob_dst->partype = PAROBJECT;
+ }
+ }
+ else if (use_base_parent) {
+ /* since we are ignoring the internal hierarchy - parent all to the
+ * base object */
+ ob_dst->parent = base->object;
+ ob_dst->partype = PAROBJECT;
+ }
+
+ if (ob_dst->parent) {
+ /* note, this may be the parent of other objects, but it should
+ * still work out ok */
+ BKE_object_apply_mat4(ob_dst, dob->mat, false, true);
+
+ /* to set ob_dst->orig and in case there's any other discrepancies */
+ DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM);
+ }
+ }
+
+ if (base->object->transflag & OB_DUPLICOLLECTION && base->object->instance_collection) {
+ for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
+ if (ob->proxy_group == base->object) {
+ ob->proxy = NULL;
+ ob->proxy_from = NULL;
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+ }
+ }
+
+ BLI_ghash_free(dupli_gh, NULL, NULL);
+ if (parent_gh) {
+ BLI_ghash_free(parent_gh, NULL, NULL);
+ }
+
+ free_object_duplilist(lb_duplis);
+
+ BKE_main_id_clear_newpoins(bmain);
+
+ base->object->transflag &= ~OB_DUPLI;
+ DEG_id_tag_update(&base->object->id, ID_RECALC_COPY_ON_WRITE);
}
static int object_duplicates_make_real_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
- const bool use_base_parent = RNA_boolean_get(op->ptr, "use_base_parent");
- const bool use_hierarchy = RNA_boolean_get(op->ptr, "use_hierarchy");
+ const bool use_base_parent = RNA_boolean_get(op->ptr, "use_base_parent");
+ const bool use_hierarchy = RNA_boolean_get(op->ptr, "use_hierarchy");
- BKE_main_id_clear_newpoins(bmain);
+ BKE_main_id_clear_newpoins(bmain);
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
- {
- make_object_duplilist_real(C, scene, base, use_base_parent, use_hierarchy);
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
+ make_object_duplilist_real(C, scene, base, use_base_parent, use_hierarchy);
- /* dependencies were changed */
- WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, base->object);
- }
- CTX_DATA_END;
+ /* dependencies were changed */
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, base->object);
+ }
+ CTX_DATA_END;
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_SCENE, scene);
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_SCENE, scene);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_duplicates_make_real(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Duplicates Real";
- ot->description = "Make dupli objects attached to this object real";
- ot->idname = "OBJECT_OT_duplicates_make_real";
+ /* identifiers */
+ ot->name = "Make Duplicates Real";
+ ot->description = "Make dupli objects attached to this object real";
+ ot->idname = "OBJECT_OT_duplicates_make_real";
- /* api callbacks */
- ot->exec = object_duplicates_make_real_exec;
+ /* api callbacks */
+ ot->exec = object_duplicates_make_real_exec;
- ot->poll = ED_operator_objectmode;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
- RNA_def_boolean(ot->srna, "use_base_parent", 0, "Parent", "Parent newly created objects to the original duplicator");
- RNA_def_boolean(ot->srna, "use_hierarchy", 0, "Keep Hierarchy", "Maintain parent child relationships");
+ RNA_def_boolean(ot->srna,
+ "use_base_parent",
+ 0,
+ "Parent",
+ "Parent newly created objects to the original duplicator");
+ RNA_def_boolean(
+ ot->srna, "use_hierarchy", 0, "Keep Hierarchy", "Maintain parent child relationships");
}
/**************************** Convert **************************/
static const EnumPropertyItem convert_target_items[] = {
- {OB_CURVE, "CURVE", ICON_OUTLINER_OB_CURVE, "Curve from Mesh/Text", ""},
- {OB_MESH, "MESH", ICON_OUTLINER_OB_MESH, "Mesh from Curve/Meta/Surf/Text", ""},
- {0, NULL, 0, NULL, NULL},
+ {OB_CURVE, "CURVE", ICON_OUTLINER_OB_CURVE, "Curve from Mesh/Text", ""},
+ {OB_MESH, "MESH", ICON_OUTLINER_OB_MESH, "Mesh from Curve/Meta/Surf/Text", ""},
+ {0, NULL, 0, NULL, NULL},
};
static void convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- if (ob->runtime.curve_cache == NULL) {
- /* Force creation. This is normally not needed but on operator
- * redo we might end up with an object which isn't evaluated yet.
- * Also happens in case we are working on a copy of the object (all its caches have been nuked then).
- */
- if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
- /* We need 'for render' ON here, to enable computing bevel dipslist if needed.
- * Also makes sense anyway, we would not want e.g. to loose hidden parts etc. */
- BKE_displist_make_curveTypes(depsgraph, scene, ob, true, false, NULL);
- }
- else if (ob->type == OB_MBALL) {
- BKE_displist_make_mball(depsgraph, scene, ob);
- }
- }
+ if (ob->runtime.curve_cache == NULL) {
+ /* Force creation. This is normally not needed but on operator
+ * redo we might end up with an object which isn't evaluated yet.
+ * Also happens in case we are working on a copy of the object (all its caches have been nuked then).
+ */
+ if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
+ /* We need 'for render' ON here, to enable computing bevel dipslist if needed.
+ * Also makes sense anyway, we would not want e.g. to loose hidden parts etc. */
+ BKE_displist_make_curveTypes(depsgraph, scene, ob, true, false, NULL);
+ }
+ else if (ob->type == OB_MBALL) {
+ BKE_displist_make_mball(depsgraph, scene, ob);
+ }
+ }
}
static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- convert_ensure_curve_cache(depsgraph, scene, ob);
- BKE_mesh_from_nurbs(bmain, ob); /* also does users */
+ convert_ensure_curve_cache(depsgraph, scene, ob);
+ BKE_mesh_from_nurbs(bmain, ob); /* also does users */
- if (ob->type == OB_MESH) {
- BKE_object_free_modifiers(ob, 0);
- }
+ if (ob->type == OB_MESH) {
+ BKE_object_free_modifiers(ob, 0);
+ }
}
static bool convert_poll(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- Base *base_act = CTX_data_active_base(C);
- Object *obact = base_act ? base_act->object : NULL;
+ Scene *scene = CTX_data_scene(C);
+ Base *base_act = CTX_data_active_base(C);
+ Object *obact = base_act ? base_act->object : NULL;
- return (!ID_IS_LINKED(scene) && obact && (BKE_object_is_in_editmode(obact) == false) &&
- (base_act->flag & BASE_SELECTED) && !ID_IS_LINKED(obact));
+ return (!ID_IS_LINKED(scene) && obact && (BKE_object_is_in_editmode(obact) == false) &&
+ (base_act->flag & BASE_SELECTED) && !ID_IS_LINKED(obact));
}
/* Helper for convert_exec */
-static Base *duplibase_for_convert(Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, Object *ob)
+static Base *duplibase_for_convert(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, Object *ob)
{
- Object *obn;
- Base *basen;
+ Object *obn;
+ Base *basen;
- if (ob == NULL) {
- ob = base->object;
- }
+ if (ob == NULL) {
+ ob = base->object;
+ }
- obn = BKE_object_copy(bmain, ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- BKE_collection_object_add_from(bmain, scene, ob, obn);
+ obn = BKE_object_copy(bmain, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ BKE_collection_object_add_from(bmain, scene, ob, obn);
- basen = BKE_view_layer_base_find(view_layer, obn);
- ED_object_base_select(basen, BA_SELECT);
- ED_object_base_select(basen, BA_DESELECT);
- return basen;
+ basen = BKE_view_layer_base_find(view_layer, obn);
+ ED_object_base_select(basen, BA_SELECT);
+ ED_object_base_select(basen, BA_DESELECT);
+ return basen;
}
static int convert_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *basen = NULL, *basact = NULL;
- Object *ob1, *obact = CTX_data_active_object(C);
- Curve *cu;
- Nurb *nu;
- MetaBall *mb;
- Mesh *me;
- const short target = RNA_enum_get(op->ptr, "target");
- bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
- int a, mballConverted = 0;
-
- /* don't forget multiple users! */
-
- {
- FOREACH_SCENE_OBJECT_BEGIN(scene, ob)
- {
- ob->flag &= ~OB_DONE;
-
- /* flag data that's not been edited (only needed for !keep_original) */
- if (ob->data) {
- ((ID *)ob->data)->tag |= LIB_TAG_DOIT;
- }
-
- /* possible metaball basis is not in this scene */
- if (ob->type == OB_MBALL && target == OB_MESH) {
- if (BKE_mball_is_basis(ob) == false) {
- Object *ob_basis;
- ob_basis = BKE_mball_basis_find(scene, ob);
- if (ob_basis) {
- ob_basis->flag &= ~OB_DONE;
- }
- }
- }
- }
- FOREACH_SCENE_OBJECT_END;
- }
-
- ListBase selected_editable_bases = CTX_data_collection_get(C, "selected_editable_bases");
-
- /* Ensure we get all meshes calculated with a sufficient data-mask,
- * needed since re-evaluating single modifiers causes bugs if they depend
- * on other objects data masks too, see: T50950. */
- {
- for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
- Base *base = link->ptr.data;
- Object *ob = base->object;
-
- /* The way object type conversion works currently (enforcing conversion of *all* objects using converted
- * object-data, even some un-selected/hidden/another scene ones, sounds totally bad to me.
- * However, changing this is more design than bug-fix, not to mention convoluted code below,
- * so that will be for later.
- * But at the very least, do not do that with linked IDs! */
- if ((ID_IS_LINKED(ob) || (ob->data && ID_IS_LINKED(ob->data))) && !keep_original) {
- keep_original = true;
- BKE_report(op->reports, RPT_INFO,
- "Converting some linked object/object data, enforcing 'Keep Original' option to True");
- }
-
- DEG_id_tag_update(&base->object->id, ID_RECALC_GEOMETRY);
- }
-
- CustomData_MeshMasks customdata_mask_prev = scene->customdata_mask;
- CustomData_MeshMasks_update(&scene->customdata_mask, &CD_MASK_MESH);
- BKE_scene_graph_update_tagged(depsgraph, bmain);
- scene->customdata_mask = customdata_mask_prev;
- }
-
- for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
- Object *newob = NULL;
- Base *base = link->ptr.data;
- Object *ob = base->object;
-
- if (ob->flag & OB_DONE || !IS_TAGGED(ob->data)) {
- if (ob->type != target) {
- base->flag &= ~SELECT;
- ob->flag &= ~SELECT;
- }
-
- /* obdata already modified */
- if (!IS_TAGGED(ob->data)) {
- /* When 2 objects with linked data are selected, converting both
- * would keep modifiers on all but the converted object [#26003] */
- if (ob->type == OB_MESH) {
- BKE_object_free_modifiers(ob, 0); /* after derivedmesh calls! */
- }
- if (ob->type == OB_GPENCIL) {
- BKE_object_free_modifiers(ob, 0); /* after derivedmesh calls! */
- BKE_object_free_shaderfx(ob, 0);
- }
- }
- }
- else if (ob->type == OB_MESH && target == OB_CURVE) {
- ob->flag |= OB_DONE;
-
- if (keep_original) {
- basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
- newob = basen->object;
-
- /* decrement original mesh's usage count */
- me = newob->data;
- id_us_min(&me->id);
-
- /* make a new copy of the mesh */
- newob->data = BKE_mesh_copy(bmain, me);
- }
- else {
- newob = ob;
- }
-
- BKE_mesh_to_curve(bmain, depsgraph, scene, newob);
-
- if (newob->type == OB_CURVE) {
- BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
- ED_rigidbody_object_remove(bmain, scene, newob);
- }
- }
- else if (ob->type == OB_MESH) {
- ob->flag |= OB_DONE;
-
- if (keep_original) {
- basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
- newob = basen->object;
-
- /* decrement original mesh's usage count */
- me = newob->data;
- id_us_min(&me->id);
-
- /* make a new copy of the mesh */
- newob->data = BKE_mesh_copy(bmain, me);
- }
- else {
- newob = ob;
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- }
-
- /* make new mesh data from the original copy */
- /* note: get the mesh from the original, not from the copy in some
- * cases this doesn't give correct results (when MDEF is used for eg)
- */
- Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_MESH);
- me_eval = BKE_mesh_copy_for_eval(me_eval, false);
- BKE_mesh_nomain_to_mesh(me_eval, newob->data, newob, &CD_MASK_MESH, true);
- BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
- }
- else if (ob->type == OB_FONT) {
- ob->flag |= OB_DONE;
-
- if (keep_original) {
- basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
- newob = basen->object;
-
- /* decrement original curve's usage count */
- id_us_min(&((Curve *)newob->data)->id);
-
- /* make a new copy of the curve */
- newob->data = BKE_curve_copy(bmain, ob->data);
- }
- else {
- newob = ob;
- }
-
- 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);
-
- newob->type = OB_CURVE;
- cu->type = OB_CURVE;
-
- if (cu->vfont) {
- id_us_min(&cu->vfont->id);
- cu->vfont = NULL;
- }
- if (cu->vfontb) {
- id_us_min(&cu->vfontb->id);
- cu->vfontb = NULL;
- }
- if (cu->vfonti) {
- id_us_min(&cu->vfonti->id);
- cu->vfonti = NULL;
- }
- if (cu->vfontbi) {
- id_us_min(&cu->vfontbi->id);
- cu->vfontbi = NULL;
- }
-
- if (!keep_original) {
- /* other users */
- if (cu->id.us > 1) {
- for (ob1 = bmain->objects.first; ob1; ob1 = ob1->id.next) {
- if (ob1->data == ob->data) {
- ob1->type = OB_CURVE;
- DEG_id_tag_update(&ob1->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- }
- }
- }
- }
-
- for (nu = cu->nurb.first; nu; nu = nu->next)
- nu->charidx = 0;
-
- cu->flag &= ~CU_3D;
- BKE_curve_curve_dimension_update(cu);
-
- if (target == OB_MESH) {
- curvetomesh(bmain, depsgraph, scene, newob);
-
- /* meshes doesn't use displist */
- BKE_object_free_curve_cache(newob);
- }
- }
- else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
- ob->flag |= OB_DONE;
-
- if (target == OB_MESH) {
- if (keep_original) {
- basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
- newob = basen->object;
-
- /* decrement original curve's usage count */
- id_us_min(&((Curve *)newob->data)->id);
-
- /* make a new copy of the curve */
- newob->data = BKE_curve_copy(bmain, ob->data);
- }
- else {
- newob = ob;
- }
-
- curvetomesh(bmain, depsgraph, scene, newob);
-
- /* meshes doesn't use displist */
- BKE_object_free_curve_cache(newob);
- }
- }
- else if (ob->type == OB_MBALL && target == OB_MESH) {
- Object *baseob;
-
- base->flag &= ~BASE_SELECTED;
- ob->base_flag &= ~BASE_SELECTED;
-
- baseob = BKE_mball_basis_find(scene, ob);
-
- if (ob != baseob) {
- /* if motherball is converting it would be marked as done later */
- ob->flag |= OB_DONE;
- }
-
- if (!(baseob->flag & OB_DONE)) {
- baseob->flag |= OB_DONE;
-
- basen = duplibase_for_convert(bmain, scene, view_layer, base, baseob);
- newob = basen->object;
-
- mb = newob->data;
- id_us_min(&mb->id);
-
- newob->data = BKE_mesh_add(bmain, "Mesh");
- newob->type = OB_MESH;
-
- me = newob->data;
- me->totcol = mb->totcol;
- if (newob->totcol) {
- me->mat = MEM_dupallocN(mb->mat);
- for (a = 0; a < newob->totcol; a++) id_us_plus((ID *)me->mat[a]);
- }
-
- convert_ensure_curve_cache(depsgraph, scene, baseob);
- BKE_mesh_from_metaball(&baseob->runtime.curve_cache->disp, newob->data);
-
- if (obact->type == OB_MBALL) {
- basact = basen;
- }
-
- mballConverted = 1;
- }
- }
- else {
- continue;
- }
-
- /* Ensure new object has consistent material data with its new obdata. */
- if (newob) {
- test_object_materials(bmain, newob, newob->data);
- }
-
- /* tag obdata if it was been changed */
-
- /* If the original object is active then make this object active */
- if (basen) {
- if (ob == obact) {
- /* store new active base to update BASACT */
- basact = basen;
- }
-
- basen = NULL;
- }
-
- if (!keep_original && (ob->flag & OB_DONE)) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- ((ID *)ob->data)->tag &= ~LIB_TAG_DOIT; /* flag not to convert this datablock again */
- }
- }
- BLI_freelistN(&selected_editable_bases);
-
- if (!keep_original) {
- if (mballConverted) {
- FOREACH_SCENE_OBJECT_BEGIN(scene, ob_mball)
- {
- if (ob_mball->type == OB_MBALL) {
- if (ob_mball->flag & OB_DONE) {
- Object *ob_basis = NULL;
- if (BKE_mball_is_basis(ob_mball) ||
- ((ob_basis = BKE_mball_basis_find(scene, ob_mball)) && (ob_basis->flag & OB_DONE)))
- {
- ED_object_base_free_and_unlink(bmain, scene, ob_mball);
- }
- }
- }
- }
- FOREACH_SCENE_OBJECT_END;
- }
- }
-
-// XXX ED_object_editmode_enter(C, 0);
-// XXX exit_editmode(C, EM_FREEDATA|); /* freedata, but no undo */
-
- if (basact) {
- /* active base was changed */
- ED_object_base_activate(C, basact);
- BASACT(view_layer) = basact;
- }
- else if (BASACT(view_layer)->object->flag & OB_DONE) {
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT(view_layer)->object);
- WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT(view_layer)->object);
- }
-
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *basen = NULL, *basact = NULL;
+ Object *ob1, *obact = CTX_data_active_object(C);
+ Curve *cu;
+ Nurb *nu;
+ MetaBall *mb;
+ Mesh *me;
+ const short target = RNA_enum_get(op->ptr, "target");
+ bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
+ int a, mballConverted = 0;
+
+ /* don't forget multiple users! */
+
+ {
+ FOREACH_SCENE_OBJECT_BEGIN (scene, ob) {
+ ob->flag &= ~OB_DONE;
+
+ /* flag data that's not been edited (only needed for !keep_original) */
+ if (ob->data) {
+ ((ID *)ob->data)->tag |= LIB_TAG_DOIT;
+ }
+
+ /* possible metaball basis is not in this scene */
+ if (ob->type == OB_MBALL && target == OB_MESH) {
+ if (BKE_mball_is_basis(ob) == false) {
+ Object *ob_basis;
+ ob_basis = BKE_mball_basis_find(scene, ob);
+ if (ob_basis) {
+ ob_basis->flag &= ~OB_DONE;
+ }
+ }
+ }
+ }
+ FOREACH_SCENE_OBJECT_END;
+ }
+
+ ListBase selected_editable_bases = CTX_data_collection_get(C, "selected_editable_bases");
+
+ /* Ensure we get all meshes calculated with a sufficient data-mask,
+ * needed since re-evaluating single modifiers causes bugs if they depend
+ * on other objects data masks too, see: T50950. */
+ {
+ for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
+ Base *base = link->ptr.data;
+ Object *ob = base->object;
+
+ /* The way object type conversion works currently (enforcing conversion of *all* objects using converted
+ * object-data, even some un-selected/hidden/another scene ones, sounds totally bad to me.
+ * However, changing this is more design than bug-fix, not to mention convoluted code below,
+ * so that will be for later.
+ * But at the very least, do not do that with linked IDs! */
+ if ((ID_IS_LINKED(ob) || (ob->data && ID_IS_LINKED(ob->data))) && !keep_original) {
+ keep_original = true;
+ BKE_report(
+ op->reports,
+ RPT_INFO,
+ "Converting some linked object/object data, enforcing 'Keep Original' option to True");
+ }
+
+ DEG_id_tag_update(&base->object->id, ID_RECALC_GEOMETRY);
+ }
+
+ CustomData_MeshMasks customdata_mask_prev = scene->customdata_mask;
+ CustomData_MeshMasks_update(&scene->customdata_mask, &CD_MASK_MESH);
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
+ scene->customdata_mask = customdata_mask_prev;
+ }
+
+ for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
+ Object *newob = NULL;
+ Base *base = link->ptr.data;
+ Object *ob = base->object;
+
+ if (ob->flag & OB_DONE || !IS_TAGGED(ob->data)) {
+ if (ob->type != target) {
+ base->flag &= ~SELECT;
+ ob->flag &= ~SELECT;
+ }
+
+ /* obdata already modified */
+ if (!IS_TAGGED(ob->data)) {
+ /* When 2 objects with linked data are selected, converting both
+ * would keep modifiers on all but the converted object [#26003] */
+ if (ob->type == OB_MESH) {
+ BKE_object_free_modifiers(ob, 0); /* after derivedmesh calls! */
+ }
+ if (ob->type == OB_GPENCIL) {
+ BKE_object_free_modifiers(ob, 0); /* after derivedmesh calls! */
+ BKE_object_free_shaderfx(ob, 0);
+ }
+ }
+ }
+ else if (ob->type == OB_MESH && target == OB_CURVE) {
+ ob->flag |= OB_DONE;
+
+ if (keep_original) {
+ basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
+ newob = basen->object;
+
+ /* decrement original mesh's usage count */
+ me = newob->data;
+ id_us_min(&me->id);
+
+ /* make a new copy of the mesh */
+ newob->data = BKE_mesh_copy(bmain, me);
+ }
+ else {
+ newob = ob;
+ }
+
+ BKE_mesh_to_curve(bmain, depsgraph, scene, newob);
+
+ if (newob->type == OB_CURVE) {
+ BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
+ ED_rigidbody_object_remove(bmain, scene, newob);
+ }
+ }
+ else if (ob->type == OB_MESH) {
+ ob->flag |= OB_DONE;
+
+ if (keep_original) {
+ basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
+ newob = basen->object;
+
+ /* decrement original mesh's usage count */
+ me = newob->data;
+ id_us_min(&me->id);
+
+ /* make a new copy of the mesh */
+ newob->data = BKE_mesh_copy(bmain, me);
+ }
+ else {
+ newob = ob;
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ }
+
+ /* make new mesh data from the original copy */
+ /* note: get the mesh from the original, not from the copy in some
+ * cases this doesn't give correct results (when MDEF is used for eg)
+ */
+ Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_MESH);
+ me_eval = BKE_mesh_copy_for_eval(me_eval, false);
+ BKE_mesh_nomain_to_mesh(me_eval, newob->data, newob, &CD_MASK_MESH, true);
+ BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
+ }
+ else if (ob->type == OB_FONT) {
+ ob->flag |= OB_DONE;
+
+ if (keep_original) {
+ basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
+ newob = basen->object;
+
+ /* decrement original curve's usage count */
+ id_us_min(&((Curve *)newob->data)->id);
+
+ /* make a new copy of the curve */
+ newob->data = BKE_curve_copy(bmain, ob->data);
+ }
+ else {
+ newob = ob;
+ }
+
+ 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);
+
+ newob->type = OB_CURVE;
+ cu->type = OB_CURVE;
+
+ if (cu->vfont) {
+ id_us_min(&cu->vfont->id);
+ cu->vfont = NULL;
+ }
+ if (cu->vfontb) {
+ id_us_min(&cu->vfontb->id);
+ cu->vfontb = NULL;
+ }
+ if (cu->vfonti) {
+ id_us_min(&cu->vfonti->id);
+ cu->vfonti = NULL;
+ }
+ if (cu->vfontbi) {
+ id_us_min(&cu->vfontbi->id);
+ cu->vfontbi = NULL;
+ }
+
+ if (!keep_original) {
+ /* other users */
+ if (cu->id.us > 1) {
+ for (ob1 = bmain->objects.first; ob1; ob1 = ob1->id.next) {
+ if (ob1->data == ob->data) {
+ ob1->type = OB_CURVE;
+ DEG_id_tag_update(&ob1->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ }
+ }
+ }
+ }
+
+ for (nu = cu->nurb.first; nu; nu = nu->next)
+ nu->charidx = 0;
+
+ cu->flag &= ~CU_3D;
+ BKE_curve_curve_dimension_update(cu);
+
+ if (target == OB_MESH) {
+ curvetomesh(bmain, depsgraph, scene, newob);
+
+ /* meshes doesn't use displist */
+ BKE_object_free_curve_cache(newob);
+ }
+ }
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ ob->flag |= OB_DONE;
+
+ if (target == OB_MESH) {
+ if (keep_original) {
+ basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
+ newob = basen->object;
+
+ /* decrement original curve's usage count */
+ id_us_min(&((Curve *)newob->data)->id);
+
+ /* make a new copy of the curve */
+ newob->data = BKE_curve_copy(bmain, ob->data);
+ }
+ else {
+ newob = ob;
+ }
+
+ curvetomesh(bmain, depsgraph, scene, newob);
+
+ /* meshes doesn't use displist */
+ BKE_object_free_curve_cache(newob);
+ }
+ }
+ else if (ob->type == OB_MBALL && target == OB_MESH) {
+ Object *baseob;
+
+ base->flag &= ~BASE_SELECTED;
+ ob->base_flag &= ~BASE_SELECTED;
+
+ baseob = BKE_mball_basis_find(scene, ob);
+
+ if (ob != baseob) {
+ /* if motherball is converting it would be marked as done later */
+ ob->flag |= OB_DONE;
+ }
+
+ if (!(baseob->flag & OB_DONE)) {
+ baseob->flag |= OB_DONE;
+
+ basen = duplibase_for_convert(bmain, scene, view_layer, base, baseob);
+ newob = basen->object;
+
+ mb = newob->data;
+ id_us_min(&mb->id);
+
+ newob->data = BKE_mesh_add(bmain, "Mesh");
+ newob->type = OB_MESH;
+
+ me = newob->data;
+ me->totcol = mb->totcol;
+ if (newob->totcol) {
+ me->mat = MEM_dupallocN(mb->mat);
+ for (a = 0; a < newob->totcol; a++)
+ id_us_plus((ID *)me->mat[a]);
+ }
+
+ convert_ensure_curve_cache(depsgraph, scene, baseob);
+ BKE_mesh_from_metaball(&baseob->runtime.curve_cache->disp, newob->data);
+
+ if (obact->type == OB_MBALL) {
+ basact = basen;
+ }
+
+ mballConverted = 1;
+ }
+ }
+ else {
+ continue;
+ }
+
+ /* Ensure new object has consistent material data with its new obdata. */
+ if (newob) {
+ test_object_materials(bmain, newob, newob->data);
+ }
+
+ /* tag obdata if it was been changed */
+
+ /* If the original object is active then make this object active */
+ if (basen) {
+ if (ob == obact) {
+ /* store new active base to update BASACT */
+ basact = basen;
+ }
+
+ basen = NULL;
+ }
+
+ if (!keep_original && (ob->flag & OB_DONE)) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ ((ID *)ob->data)->tag &= ~LIB_TAG_DOIT; /* flag not to convert this datablock again */
+ }
+ }
+ BLI_freelistN(&selected_editable_bases);
+
+ if (!keep_original) {
+ if (mballConverted) {
+ FOREACH_SCENE_OBJECT_BEGIN (scene, ob_mball) {
+ if (ob_mball->type == OB_MBALL) {
+ if (ob_mball->flag & OB_DONE) {
+ Object *ob_basis = NULL;
+ if (BKE_mball_is_basis(ob_mball) ||
+ ((ob_basis = BKE_mball_basis_find(scene, ob_mball)) &&
+ (ob_basis->flag & OB_DONE))) {
+ ED_object_base_free_and_unlink(bmain, scene, ob_mball);
+ }
+ }
+ }
+ }
+ FOREACH_SCENE_OBJECT_END;
+ }
+ }
+
+ // XXX ED_object_editmode_enter(C, 0);
+ // XXX exit_editmode(C, EM_FREEDATA|); /* freedata, but no undo */
+
+ if (basact) {
+ /* active base was changed */
+ ED_object_base_activate(C, basact);
+ BASACT(view_layer) = basact;
+ }
+ else if (BASACT(view_layer)->object->flag & OB_DONE) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT(view_layer)->object);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT(view_layer)->object);
+ }
+
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
}
-
void OBJECT_OT_convert(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Convert to";
- ot->description = "Convert selected objects to another type";
- ot->idname = "OBJECT_OT_convert";
+ /* identifiers */
+ ot->name = "Convert to";
+ ot->description = "Convert selected objects to another type";
+ ot->idname = "OBJECT_OT_convert";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = convert_exec;
- ot->poll = convert_poll;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = convert_exec;
+ ot->poll = convert_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "target", convert_target_items, OB_MESH, "Target", "Type of object to convert to");
- RNA_def_boolean(ot->srna, "keep_original", 0, "Keep Original", "Keep original objects instead of replacing them");
+ /* properties */
+ ot->prop = RNA_def_enum(
+ ot->srna, "target", convert_target_items, OB_MESH, "Target", "Type of object to convert to");
+ RNA_def_boolean(ot->srna,
+ "keep_original",
+ 0,
+ "Keep Original",
+ "Keep original objects instead of replacing them");
}
/**************************** Duplicate ************************/
@@ -2209,45 +2276,46 @@ void OBJECT_OT_convert(wmOperatorType *ot)
/* used below, assumes id.new is correct */
/* leaves selection of base/object unaltered */
/* Does set ID->newid pointers. */
-static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer *view_layer, Object *ob, int dupflag)
-{
- Base *base, *basen = NULL;
- Object *obn;
-
- if (ob->mode & OB_MODE_POSE) {
- /* nothing? */
- }
- else {
- obn = ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag));
- DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
-
- base = BKE_view_layer_base_find(view_layer, ob);
- if ((base != NULL) && (base->flag & BASE_VISIBLE)) {
- BKE_collection_object_add_from(bmain, scene, ob, obn);
- }
- else {
- LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
- BKE_collection_object_add(bmain, layer_collection->collection, obn);
- }
-
- basen = BKE_view_layer_base_find(view_layer, obn);
- if (base != NULL) {
- basen->local_view_bits = base->local_view_bits;
- }
-
- /* 1) duplis should end up in same collection as the original
- * 2) Rigid Body sim participants MUST always be part of a collection...
- */
- // XXX: is 2) really a good measure here?
- if (ob->rigidbody_object || ob->rigidbody_constraint) {
- Collection *collection;
- for (collection = bmain->collections.first; collection; collection = collection->id.next) {
- if (BKE_collection_has_object(collection, ob))
- BKE_collection_object_add(bmain, collection, obn);
- }
- }
- }
- return basen;
+static Base *object_add_duplicate_internal(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, Object *ob, int dupflag)
+{
+ Base *base, *basen = NULL;
+ Object *obn;
+
+ if (ob->mode & OB_MODE_POSE) {
+ /* nothing? */
+ }
+ else {
+ obn = ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag));
+ DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ base = BKE_view_layer_base_find(view_layer, ob);
+ if ((base != NULL) && (base->flag & BASE_VISIBLE)) {
+ BKE_collection_object_add_from(bmain, scene, ob, obn);
+ }
+ else {
+ LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
+ BKE_collection_object_add(bmain, layer_collection->collection, obn);
+ }
+
+ basen = BKE_view_layer_base_find(view_layer, obn);
+ if (base != NULL) {
+ basen->local_view_bits = base->local_view_bits;
+ }
+
+ /* 1) duplis should end up in same collection as the original
+ * 2) Rigid Body sim participants MUST always be part of a collection...
+ */
+ // XXX: is 2) really a good measure here?
+ if (ob->rigidbody_object || ob->rigidbody_constraint) {
+ Collection *collection;
+ for (collection = bmain->collections.first; collection; collection = collection->id.next) {
+ if (BKE_collection_has_object(collection, ob))
+ BKE_collection_object_add(bmain, collection, obn);
+ }
+ }
+ }
+ return basen;
}
/* single object duplicate, if dupflag==0, fully linked, else it uses the flags given */
@@ -2255,278 +2323,288 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer
* note: don't call this within a loop since clear_* funcs loop over the entire database.
* note: caller must do DAG_relations_tag_update(bmain);
* this is not done automatic since we may duplicate many objects in a batch */
-Base *ED_object_add_duplicate(Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, int dupflag)
+Base *ED_object_add_duplicate(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, int dupflag)
{
- Base *basen;
- Object *ob;
+ Base *basen;
+ Object *ob;
- basen = object_add_duplicate_internal(bmain, scene, view_layer, base->object, dupflag);
- if (basen == NULL) {
- return NULL;
- }
+ basen = object_add_duplicate_internal(bmain, scene, view_layer, base->object, dupflag);
+ if (basen == NULL) {
+ return NULL;
+ }
- ob = basen->object;
+ ob = basen->object;
- /* link own references to the newly duplicated data [#26816] */
- BKE_libblock_relink_to_newid(&ob->id);
+ /* link own references to the newly duplicated data [#26816] */
+ BKE_libblock_relink_to_newid(&ob->id);
- /* DAG_relations_tag_update(bmain); */ /* caller must do */
+ /* DAG_relations_tag_update(bmain); */ /* caller must do */
- if (ob->data != NULL) {
- DEG_id_tag_update_ex(bmain, (ID *)ob->data, ID_RECALC_EDITORS);
- }
+ if (ob->data != NULL) {
+ DEG_id_tag_update_ex(bmain, (ID *)ob->data, ID_RECALC_EDITORS);
+ }
- BKE_main_id_clear_newpoins(bmain);
+ BKE_main_id_clear_newpoins(bmain);
- return basen;
+ return basen;
}
/* contextual operator dupli */
static int duplicate_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);
- const bool linked = RNA_boolean_get(op->ptr, "linked");
- int dupflag = (linked) ? 0 : U.dupflag;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool linked = RNA_boolean_get(op->ptr, "linked");
+ int dupflag = (linked) ? 0 : U.dupflag;
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
- {
- Base *basen = object_add_duplicate_internal(bmain, scene, view_layer, base->object, dupflag);
+ CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
+ Base *basen = object_add_duplicate_internal(bmain, scene, view_layer, base->object, dupflag);
- /* note that this is safe to do with this context iterator,
- * the list is made in advance */
- ED_object_base_select(base, BA_DESELECT);
- ED_object_base_select(basen, BA_SELECT);
+ /* note that this is safe to do with this context iterator,
+ * the list is made in advance */
+ ED_object_base_select(base, BA_DESELECT);
+ ED_object_base_select(basen, BA_SELECT);
- if (basen == NULL) {
- continue;
- }
+ if (basen == NULL) {
+ continue;
+ }
- /* new object becomes active */
- if (BASACT(view_layer) == base)
- ED_object_base_activate(C, basen);
+ /* new object becomes active */
+ if (BASACT(view_layer) == base)
+ ED_object_base_activate(C, basen);
- if (basen->object->data) {
- DEG_id_tag_update(basen->object->data, 0);
- }
- }
- CTX_DATA_END;
+ if (basen->object->data) {
+ DEG_id_tag_update(basen->object->data, 0);
+ }
+ }
+ CTX_DATA_END;
- copy_object_set_idnew(C);
+ copy_object_set_idnew(C);
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_duplicate(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Duplicate Objects";
- ot->description = "Duplicate selected objects";
- ot->idname = "OBJECT_OT_duplicate";
+ /* identifiers */
+ ot->name = "Duplicate Objects";
+ ot->description = "Duplicate selected objects";
+ ot->idname = "OBJECT_OT_duplicate";
- /* api callbacks */
- ot->exec = duplicate_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = duplicate_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* to give to transform */
- RNA_def_boolean(ot->srna, "linked", 0, "Linked", "Duplicate object but not object data, linking to the original data");
- prop = RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ /* to give to transform */
+ RNA_def_boolean(ot->srna,
+ "linked",
+ 0,
+ "Linked",
+ "Duplicate object but not object data, linking to the original data");
+ prop = RNA_def_enum(
+ ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/* **************** add named object, for dragdrop ************* */
static int add_named_exec(bContext *C, wmOperator *op)
{
- wmWindow *win = CTX_wm_window(C);
- const wmEvent *event = win ? win->eventstate : NULL;
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *basen;
- Object *ob;
- const bool linked = RNA_boolean_get(op->ptr, "linked");
- int dupflag = (linked) ? 0 : U.dupflag;
- char name[MAX_ID_NAME - 2];
+ wmWindow *win = CTX_wm_window(C);
+ const wmEvent *event = win ? win->eventstate : NULL;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *basen;
+ Object *ob;
+ const bool linked = RNA_boolean_get(op->ptr, "linked");
+ int dupflag = (linked) ? 0 : U.dupflag;
+ char name[MAX_ID_NAME - 2];
- /* find object, create fake base */
- RNA_string_get(op->ptr, "name", name);
- ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name);
+ /* find object, create fake base */
+ RNA_string_get(op->ptr, "name", name);
+ ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name);
- if (ob == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Object not found");
- return OPERATOR_CANCELLED;
- }
+ if (ob == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Object not found");
+ return OPERATOR_CANCELLED;
+ }
- /* prepare dupli */
- basen = object_add_duplicate_internal(bmain, scene, view_layer, ob, dupflag);
+ /* prepare dupli */
+ basen = object_add_duplicate_internal(bmain, scene, view_layer, ob, dupflag);
- if (basen == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated");
- return OPERATOR_CANCELLED;
- }
+ if (basen == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated");
+ return OPERATOR_CANCELLED;
+ }
- BKE_scene_object_base_flag_sync_from_object(basen);
- basen->object->restrictflag &= ~OB_RESTRICT_VIEW;
+ BKE_scene_object_base_flag_sync_from_object(basen);
+ basen->object->restrictflag &= ~OB_RESTRICT_VIEW;
- if (event) {
- ARegion *ar = CTX_wm_region(C);
- const int mval[2] = {event->x - ar->winrct.xmin,
- event->y - ar->winrct.ymin};
- ED_object_location_from_view(C, basen->object->loc);
- ED_view3d_cursor3d_position(C, mval, false, basen->object->loc);
- }
+ if (event) {
+ ARegion *ar = CTX_wm_region(C);
+ const int mval[2] = {event->x - ar->winrct.xmin, event->y - ar->winrct.ymin};
+ ED_object_location_from_view(C, basen->object->loc);
+ ED_view3d_cursor3d_position(C, mval, false, basen->object->loc);
+ }
- ED_object_base_select(basen, BA_SELECT);
- ED_object_base_activate(C, basen);
+ ED_object_base_select(basen, BA_SELECT);
+ ED_object_base_activate(C, basen);
- copy_object_set_idnew(C);
+ copy_object_set_idnew(C);
- /* TODO(sergey): Only update relations for the current scene. */
- DEG_relations_tag_update(bmain);
+ /* TODO(sergey): Only update relations for the current scene. */
+ DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_add_named(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Named Object";
- ot->description = "Add named object";
- ot->idname = "OBJECT_OT_add_named";
+ /* identifiers */
+ ot->name = "Add Named Object";
+ ot->description = "Add named object";
+ ot->idname = "OBJECT_OT_add_named";
- /* api callbacks */
- ot->exec = add_named_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = add_named_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "linked", 0, "Linked", "Duplicate object but not object data, linking to the original data");
- RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Object name to add");
+ RNA_def_boolean(ot->srna,
+ "linked",
+ 0,
+ "Linked",
+ "Duplicate object but not object data, linking to the original data");
+ RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Object name to add");
}
/**************************** Join *************************/
static bool join_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if (!ob || ID_IS_LINKED(ob)) return 0;
+ if (!ob || ID_IS_LINKED(ob))
+ return 0;
- if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE, OB_GPENCIL))
- return ED_operator_screenactive(C);
- else
- return 0;
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE, OB_GPENCIL))
+ return ED_operator_screenactive(C);
+ else
+ return 0;
}
static int join_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
-
- if (ob->mode & OB_MODE_EDIT) {
- BKE_report(op->reports, RPT_ERROR, "This data does not support joining in edit mode");
- return OPERATOR_CANCELLED;
- }
- else if (BKE_object_obdata_is_libdata(ob)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
- return OPERATOR_CANCELLED;
- }
- else if (ob->type == OB_GPENCIL) {
- bGPdata *gpd = (bGPdata *)ob->data;
- if ((!gpd) || GPENCIL_ANY_MODE(gpd)) {
- BKE_report(op->reports, RPT_ERROR, "This data does not support joining in this mode");
- return OPERATOR_CANCELLED;
- }
- }
-
- if (ob->type == OB_MESH)
- return join_mesh_exec(C, op);
- else if (ELEM(ob->type, OB_CURVE, OB_SURF))
- return join_curve_exec(C, op);
- else if (ob->type == OB_ARMATURE)
- return join_armature_exec(C, op);
- else if (ob->type == OB_GPENCIL)
- return ED_gpencil_join_objects_exec(C, op);
-
- return OPERATOR_CANCELLED;
+ Object *ob = CTX_data_active_object(C);
+
+ if (ob->mode & OB_MODE_EDIT) {
+ BKE_report(op->reports, RPT_ERROR, "This data does not support joining in edit mode");
+ return OPERATOR_CANCELLED;
+ }
+ else if (BKE_object_obdata_is_libdata(ob)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
+ return OPERATOR_CANCELLED;
+ }
+ else if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = (bGPdata *)ob->data;
+ if ((!gpd) || GPENCIL_ANY_MODE(gpd)) {
+ BKE_report(op->reports, RPT_ERROR, "This data does not support joining in this mode");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ if (ob->type == OB_MESH)
+ return join_mesh_exec(C, op);
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF))
+ return join_curve_exec(C, op);
+ else if (ob->type == OB_ARMATURE)
+ return join_armature_exec(C, op);
+ else if (ob->type == OB_GPENCIL)
+ return ED_gpencil_join_objects_exec(C, op);
+
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_join(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Join";
- ot->description = "Join selected objects into active object";
- ot->idname = "OBJECT_OT_join";
+ /* identifiers */
+ ot->name = "Join";
+ ot->description = "Join selected objects into active object";
+ ot->idname = "OBJECT_OT_join";
- /* api callbacks */
- ot->exec = join_exec;
- ot->poll = join_poll;
+ /* api callbacks */
+ ot->exec = join_exec;
+ ot->poll = join_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/**************************** Join as Shape Key*************************/
static bool join_shapes_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if (!ob || ID_IS_LINKED(ob)) return 0;
+ if (!ob || ID_IS_LINKED(ob))
+ return 0;
- /* only meshes supported at the moment */
- if (ob->type == OB_MESH)
- return ED_operator_screenactive(C);
- else
- return 0;
+ /* only meshes supported at the moment */
+ if (ob->type == OB_MESH)
+ return ED_operator_screenactive(C);
+ else
+ return 0;
}
static int join_shapes_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if (ob->mode & OB_MODE_EDIT) {
- BKE_report(op->reports, RPT_ERROR, "This data does not support joining in edit mode");
- return OPERATOR_CANCELLED;
- }
- else if (BKE_object_obdata_is_libdata(ob)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
- return OPERATOR_CANCELLED;
- }
+ if (ob->mode & OB_MODE_EDIT) {
+ BKE_report(op->reports, RPT_ERROR, "This data does not support joining in edit mode");
+ return OPERATOR_CANCELLED;
+ }
+ else if (BKE_object_obdata_is_libdata(ob)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
+ return OPERATOR_CANCELLED;
+ }
- if (ob->type == OB_MESH)
- return join_mesh_shapes_exec(C, op);
+ if (ob->type == OB_MESH)
+ return join_mesh_shapes_exec(C, op);
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_join_shapes(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Join as Shapes";
- ot->description = "Merge selected objects to shapes of active object";
- ot->idname = "OBJECT_OT_join_shapes";
+ /* identifiers */
+ ot->name = "Join as Shapes";
+ ot->description = "Merge selected objects to shapes of active object";
+ ot->idname = "OBJECT_OT_join_shapes";
- /* api callbacks */
- ot->exec = join_shapes_exec;
- ot->poll = join_shapes_poll;
+ /* api callbacks */
+ ot->exec = join_shapes_exec;
+ ot->poll = join_shapes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index ac1f31d0b48..f3138c5afec 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -73,18 +73,18 @@
static Image *bake_object_image_get(Object *ob, int mat_nr)
{
- Image *image = NULL;
- ED_object_get_active_image(ob, mat_nr + 1, &image, NULL, NULL, NULL);
- return image;
+ Image *image = NULL;
+ ED_object_get_active_image(ob, mat_nr + 1, &image, NULL, NULL, NULL);
+ return image;
}
static Image **bake_object_image_get_array(Object *ob)
{
- Image **image_array = MEM_mallocN(sizeof(Material *) * ob->totcol, __func__);
- for (int i = 0; i < ob->totcol; i++) {
- image_array[i] = bake_object_image_get(ob, i);
- }
- return image_array;
+ Image **image_array = MEM_mallocN(sizeof(Material *) * ob->totcol, __func__);
+ for (int i = 0; i < ob->totcol; i++) {
+ image_array[i] = bake_object_image_get(ob, i);
+ }
+ return image_array;
}
/* ****************** multires BAKING ********************** */
@@ -92,485 +92,486 @@ static Image **bake_object_image_get_array(Object *ob)
/* holder of per-object data needed for bake job
* needed to make job totally thread-safe */
typedef struct MultiresBakerJobData {
- struct MultiresBakerJobData *next, *prev;
- /* material aligned image array (for per-face bake image) */
- struct {
- Image **array;
- int len;
- } ob_image;
- DerivedMesh *lores_dm, *hires_dm;
- bool simple;
- int lvl, tot_lvl;
- ListBase images;
+ struct MultiresBakerJobData *next, *prev;
+ /* material aligned image array (for per-face bake image) */
+ struct {
+ Image **array;
+ int len;
+ } ob_image;
+ DerivedMesh *lores_dm, *hires_dm;
+ bool simple;
+ int lvl, tot_lvl;
+ ListBase images;
} MultiresBakerJobData;
/* data passing to multires-baker job */
typedef struct {
- Scene *scene;
- ListBase data;
- /** Clear the images before baking */
- bool bake_clear;
- /** Bake-filter, aka margin */
- int bake_filter;
- /** mode of baking (displacement, normals, AO) */
- short mode;
- /** Use low-resolution mesh when baking displacement maps */
- bool use_lores_mesh;
- /** Number of rays to be cast when doing AO baking */
- int number_of_rays;
- /** Bias between object and start ray point when doing AO baking */
- float bias;
- /** Number of threads to be used for baking */
- int threads;
- /** User scale used to scale displacement when baking derivative map. */
- float user_scale;
+ Scene *scene;
+ ListBase data;
+ /** Clear the images before baking */
+ bool bake_clear;
+ /** Bake-filter, aka margin */
+ int bake_filter;
+ /** mode of baking (displacement, normals, AO) */
+ short mode;
+ /** Use low-resolution mesh when baking displacement maps */
+ bool use_lores_mesh;
+ /** Number of rays to be cast when doing AO baking */
+ int number_of_rays;
+ /** Bias between object and start ray point when doing AO baking */
+ float bias;
+ /** Number of threads to be used for baking */
+ int threads;
+ /** User scale used to scale displacement when baking derivative map. */
+ float user_scale;
} MultiresBakeJob;
static bool multiresbake_check(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob;
- Mesh *me;
- MultiresModifierData *mmd;
- bool ok = true;
- int a;
-
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
- {
- ob = base->object;
-
- if (ob->type != OB_MESH) {
- BKE_report(op->reports, RPT_ERROR, "Baking of multires data only works with an active mesh object");
-
- ok = false;
- break;
- }
-
- me = (Mesh *)ob->data;
- mmd = get_multires_modifier(scene, ob, 0);
-
- /* Multi-resolution should be and be last in the stack */
- if (ok && mmd) {
- ModifierData *md;
-
- ok = mmd->totlvl > 0;
-
- for (md = (ModifierData *)mmd->modifier.next; md && ok; md = md->next) {
- if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) {
- ok = false;
- }
- }
- }
- else {
- ok = false;
- }
-
- if (!ok) {
- BKE_report(op->reports, RPT_ERROR, "Multires data baking requires multi-resolution object");
-
- break;
- }
-
- if (!me->mloopuv) {
- BKE_report(op->reports, RPT_ERROR, "Mesh should be unwrapped before multires data baking");
-
- ok = false;
- }
- else {
- a = me->totpoly;
- while (ok && a--) {
- Image *ima = bake_object_image_get(ob, me->mpoly[a].mat_nr);
-
- if (!ima) {
- BKE_report(op->reports, RPT_ERROR, "You should have active texture to use multires baker");
-
- ok = false;
- }
- else {
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
-
- if (!ibuf) {
- BKE_report(op->reports, RPT_ERROR, "Baking should happen to image with image buffer");
-
- ok = false;
- }
- else {
- if (ibuf->rect == NULL && ibuf->rect_float == NULL)
- ok = false;
-
- if (ibuf->rect_float && !(ibuf->channels == 0 || ibuf->channels == 4))
- ok = false;
-
- if (!ok)
- BKE_report(op->reports, RPT_ERROR, "Baking to unsupported image type");
- }
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
- }
- }
-
- if (!ok)
- break;
- }
- CTX_DATA_END;
-
- return ok;
+ Scene *scene = CTX_data_scene(C);
+ Object *ob;
+ Mesh *me;
+ MultiresModifierData *mmd;
+ bool ok = true;
+ int a;
+
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
+ ob = base->object;
+
+ if (ob->type != OB_MESH) {
+ BKE_report(
+ op->reports, RPT_ERROR, "Baking of multires data only works with an active mesh object");
+
+ ok = false;
+ break;
+ }
+
+ me = (Mesh *)ob->data;
+ mmd = get_multires_modifier(scene, ob, 0);
+
+ /* Multi-resolution should be and be last in the stack */
+ if (ok && mmd) {
+ ModifierData *md;
+
+ ok = mmd->totlvl > 0;
+
+ for (md = (ModifierData *)mmd->modifier.next; md && ok; md = md->next) {
+ if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) {
+ ok = false;
+ }
+ }
+ }
+ else {
+ ok = false;
+ }
+
+ if (!ok) {
+ BKE_report(op->reports, RPT_ERROR, "Multires data baking requires multi-resolution object");
+
+ break;
+ }
+
+ if (!me->mloopuv) {
+ BKE_report(op->reports, RPT_ERROR, "Mesh should be unwrapped before multires data baking");
+
+ ok = false;
+ }
+ else {
+ a = me->totpoly;
+ while (ok && a--) {
+ Image *ima = bake_object_image_get(ob, me->mpoly[a].mat_nr);
+
+ if (!ima) {
+ BKE_report(
+ op->reports, RPT_ERROR, "You should have active texture to use multires baker");
+
+ ok = false;
+ }
+ else {
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+
+ if (!ibuf) {
+ BKE_report(op->reports, RPT_ERROR, "Baking should happen to image with image buffer");
+
+ ok = false;
+ }
+ else {
+ if (ibuf->rect == NULL && ibuf->rect_float == NULL)
+ ok = false;
+
+ if (ibuf->rect_float && !(ibuf->channels == 0 || ibuf->channels == 4))
+ ok = false;
+
+ if (!ok)
+ BKE_report(op->reports, RPT_ERROR, "Baking to unsupported image type");
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+ }
+ }
+
+ if (!ok)
+ break;
+ }
+ CTX_DATA_END;
+
+ return ok;
}
static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *lvl)
{
- DerivedMesh *dm;
- MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
- Mesh *me = (Mesh *)ob->data;
- MultiresModifierData tmp_mmd = *mmd;
- DerivedMesh *cddm = CDDM_from_mesh(me);
+ DerivedMesh *dm;
+ MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
+ Mesh *me = (Mesh *)ob->data;
+ MultiresModifierData tmp_mmd = *mmd;
+ DerivedMesh *cddm = CDDM_from_mesh(me);
- DM_set_only_copy(cddm, &CD_MASK_BAREMESH);
+ DM_set_only_copy(cddm, &CD_MASK_BAREMESH);
- if (mmd->lvl == 0) {
- dm = CDDM_copy(cddm);
- }
- else {
- tmp_mmd.lvl = mmd->lvl;
- tmp_mmd.sculptlvl = mmd->lvl;
- dm = multires_make_derived_from_derived(cddm, &tmp_mmd, scene, ob, 0);
- }
+ if (mmd->lvl == 0) {
+ dm = CDDM_copy(cddm);
+ }
+ else {
+ tmp_mmd.lvl = mmd->lvl;
+ tmp_mmd.sculptlvl = mmd->lvl;
+ dm = multires_make_derived_from_derived(cddm, &tmp_mmd, scene, ob, 0);
+ }
- cddm->release(cddm);
+ cddm->release(cddm);
- *lvl = mmd->lvl;
+ *lvl = mmd->lvl;
- return dm;
+ return dm;
}
static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *lvl, bool *simple)
{
- Mesh *me = (Mesh *)ob->data;
- MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
- MultiresModifierData tmp_mmd = *mmd;
- DerivedMesh *cddm = CDDM_from_mesh(me);
- DerivedMesh *dm;
+ Mesh *me = (Mesh *)ob->data;
+ MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
+ MultiresModifierData tmp_mmd = *mmd;
+ DerivedMesh *cddm = CDDM_from_mesh(me);
+ DerivedMesh *dm;
- DM_set_only_copy(cddm, &CD_MASK_BAREMESH);
+ DM_set_only_copy(cddm, &CD_MASK_BAREMESH);
- /* TODO: DM_set_only_copy wouldn't set mask for loop and poly data,
- * but we really need BAREMESH only to save lots of memory
- */
- CustomData_set_only_copy(&cddm->loopData, CD_MASK_BAREMESH.lmask);
- CustomData_set_only_copy(&cddm->polyData, CD_MASK_BAREMESH.pmask);
+ /* TODO: DM_set_only_copy wouldn't set mask for loop and poly data,
+ * but we really need BAREMESH only to save lots of memory
+ */
+ CustomData_set_only_copy(&cddm->loopData, CD_MASK_BAREMESH.lmask);
+ CustomData_set_only_copy(&cddm->polyData, CD_MASK_BAREMESH.pmask);
- *lvl = mmd->totlvl;
- *simple = mmd->simple != 0;
+ *lvl = mmd->totlvl;
+ *simple = mmd->simple != 0;
- tmp_mmd.lvl = mmd->totlvl;
- tmp_mmd.sculptlvl = mmd->totlvl;
- dm = multires_make_derived_from_derived(cddm, &tmp_mmd, scene, ob, 0);
- cddm->release(cddm);
+ tmp_mmd.lvl = mmd->totlvl;
+ tmp_mmd.sculptlvl = mmd->totlvl;
+ dm = multires_make_derived_from_derived(cddm, &tmp_mmd, scene, ob, 0);
+ cddm->release(cddm);
- return dm;
+ return dm;
}
typedef enum ClearFlag {
- CLEAR_TANGENT_NORMAL = 1,
- CLEAR_DISPLACEMENT = 2,
+ CLEAR_TANGENT_NORMAL = 1,
+ CLEAR_DISPLACEMENT = 2,
} ClearFlag;
-
static void clear_single_image(Image *image, ClearFlag flag)
{
- const float vec_alpha[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- const float vec_solid[4] = {0.0f, 0.0f, 0.0f, 1.0f};
- const float nor_alpha[4] = {0.5f, 0.5f, 1.0f, 0.0f};
- const float nor_solid[4] = {0.5f, 0.5f, 1.0f, 1.0f};
- const float disp_alpha[4] = {0.5f, 0.5f, 0.5f, 0.0f};
- const float disp_solid[4] = {0.5f, 0.5f, 0.5f, 1.0f};
-
- if ((image->id.tag & LIB_TAG_DOIT) == 0) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
-
- if (flag == CLEAR_TANGENT_NORMAL)
- IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid);
- else if (flag == CLEAR_DISPLACEMENT)
- IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? disp_alpha : disp_solid);
- else
- IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
-
- image->id.tag |= LIB_TAG_DOIT;
-
- BKE_image_release_ibuf(image, ibuf, NULL);
- }
+ const float vec_alpha[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ const float vec_solid[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ const float nor_alpha[4] = {0.5f, 0.5f, 1.0f, 0.0f};
+ const float nor_solid[4] = {0.5f, 0.5f, 1.0f, 1.0f};
+ const float disp_alpha[4] = {0.5f, 0.5f, 0.5f, 0.0f};
+ const float disp_solid[4] = {0.5f, 0.5f, 0.5f, 1.0f};
+
+ if ((image->id.tag & LIB_TAG_DOIT) == 0) {
+ ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
+
+ if (flag == CLEAR_TANGENT_NORMAL)
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid);
+ else if (flag == CLEAR_DISPLACEMENT)
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? disp_alpha : disp_solid);
+ else
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
+
+ image->id.tag |= LIB_TAG_DOIT;
+
+ BKE_image_release_ibuf(image, ibuf, NULL);
+ }
}
static void clear_images_poly(Image **ob_image_array, int ob_image_array_len, ClearFlag flag)
{
- for (int i = 0; i < ob_image_array_len; i++) {
- Image *image = ob_image_array[i];
- if (image) {
- image->id.tag &= ~LIB_TAG_DOIT;
- }
- }
-
- for (int i = 0; i < ob_image_array_len; i++) {
- Image *image = ob_image_array[i];
- if (image) {
- clear_single_image(image, flag);
- }
- }
-
- for (int i = 0; i < ob_image_array_len; i++) {
- Image *image = ob_image_array[i];
- if (image) {
- image->id.tag &= ~LIB_TAG_DOIT;
- }
- }
+ for (int i = 0; i < ob_image_array_len; i++) {
+ Image *image = ob_image_array[i];
+ if (image) {
+ image->id.tag &= ~LIB_TAG_DOIT;
+ }
+ }
+
+ for (int i = 0; i < ob_image_array_len; i++) {
+ Image *image = ob_image_array[i];
+ if (image) {
+ clear_single_image(image, flag);
+ }
+ }
+
+ for (int i = 0; i < ob_image_array_len; i++) {
+ Image *image = ob_image_array[i];
+ if (image) {
+ image->id.tag &= ~LIB_TAG_DOIT;
+ }
+ }
}
static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
{
- Object *ob;
- Scene *scene = CTX_data_scene(C);
- int objects_baked = 0;
+ Object *ob;
+ Scene *scene = CTX_data_scene(C);
+ int objects_baked = 0;
- if (!multiresbake_check(C, op))
- return OPERATOR_CANCELLED;
+ if (!multiresbake_check(C, op))
+ return OPERATOR_CANCELLED;
- if (scene->r.bake_flag & R_BAKE_CLEAR) { /* clear images */
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
- {
- ClearFlag clear_flag = 0;
+ if (scene->r.bake_flag & R_BAKE_CLEAR) { /* clear images */
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
+ ClearFlag clear_flag = 0;
- ob = base->object;
- // me = (Mesh *)ob->data;
+ ob = base->object;
+ // me = (Mesh *)ob->data;
- if (scene->r.bake_mode == RE_BAKE_NORMALS) {
- clear_flag = CLEAR_TANGENT_NORMAL;
- }
- else if (scene->r.bake_mode == RE_BAKE_DISPLACEMENT) {
- clear_flag = CLEAR_DISPLACEMENT;
- }
+ if (scene->r.bake_mode == RE_BAKE_NORMALS) {
+ clear_flag = CLEAR_TANGENT_NORMAL;
+ }
+ else if (scene->r.bake_mode == RE_BAKE_DISPLACEMENT) {
+ clear_flag = CLEAR_DISPLACEMENT;
+ }
- {
- Image **ob_image_array = bake_object_image_get_array(ob);
- clear_images_poly(ob_image_array, ob->totcol, clear_flag);
- MEM_freeN(ob_image_array);
- }
- }
- CTX_DATA_END;
- }
+ {
+ Image **ob_image_array = bake_object_image_get_array(ob);
+ clear_images_poly(ob_image_array, ob->totcol, clear_flag);
+ MEM_freeN(ob_image_array);
+ }
+ }
+ CTX_DATA_END;
+ }
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
- {
- MultiresBakeRender bkr = {NULL};
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
+ MultiresBakeRender bkr = {NULL};
- ob = base->object;
+ ob = base->object;
- multires_force_update(ob);
+ multires_force_update(ob);
- /* copy data stored in job descriptor */
- bkr.scene = scene;
- bkr.bake_filter = scene->r.bake_filter;
- bkr.mode = scene->r.bake_mode;
- bkr.use_lores_mesh = scene->r.bake_flag & R_BAKE_LORES_MESH;
- bkr.bias = scene->r.bake_biasdist;
- bkr.number_of_rays = scene->r.bake_samples;
- bkr.threads = BKE_scene_num_threads(scene);
- bkr.user_scale = (scene->r.bake_flag & R_BAKE_USERSCALE) ? scene->r.bake_user_scale : -1.0f;
- //bkr.reports= op->reports;
+ /* copy data stored in job descriptor */
+ bkr.scene = scene;
+ bkr.bake_filter = scene->r.bake_filter;
+ bkr.mode = scene->r.bake_mode;
+ bkr.use_lores_mesh = scene->r.bake_flag & R_BAKE_LORES_MESH;
+ bkr.bias = scene->r.bake_biasdist;
+ bkr.number_of_rays = scene->r.bake_samples;
+ bkr.threads = BKE_scene_num_threads(scene);
+ bkr.user_scale = (scene->r.bake_flag & R_BAKE_USERSCALE) ? scene->r.bake_user_scale : -1.0f;
+ //bkr.reports= op->reports;
- /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
- bkr.ob_image.array = bake_object_image_get_array(ob);
- bkr.ob_image.len = ob->totcol;
+ /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
+ bkr.ob_image.array = bake_object_image_get_array(ob);
+ bkr.ob_image.len = ob->totcol;
- bkr.hires_dm = multiresbake_create_hiresdm(scene, ob, &bkr.tot_lvl, &bkr.simple);
- bkr.lores_dm = multiresbake_create_loresdm(scene, ob, &bkr.lvl);
+ bkr.hires_dm = multiresbake_create_hiresdm(scene, ob, &bkr.tot_lvl, &bkr.simple);
+ bkr.lores_dm = multiresbake_create_loresdm(scene, ob, &bkr.lvl);
- RE_multires_bake_images(&bkr);
+ RE_multires_bake_images(&bkr);
- MEM_freeN(bkr.ob_image.array);
+ MEM_freeN(bkr.ob_image.array);
- BLI_freelistN(&bkr.image);
+ BLI_freelistN(&bkr.image);
- bkr.lores_dm->release(bkr.lores_dm);
- bkr.hires_dm->release(bkr.hires_dm);
+ bkr.lores_dm->release(bkr.lores_dm);
+ bkr.hires_dm->release(bkr.hires_dm);
- objects_baked++;
- }
- CTX_DATA_END;
+ objects_baked++;
+ }
+ CTX_DATA_END;
- if (!objects_baked)
- BKE_report(op->reports, RPT_ERROR, "No objects found to bake from");
+ if (!objects_baked)
+ BKE_report(op->reports, RPT_ERROR, "No objects found to bake from");
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* Multiresbake adopted for job-system executing */
static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob;
-
- /* backup scene settings, so their changing in UI would take no effect on baker */
- bkj->scene = scene;
- bkj->bake_filter = scene->r.bake_filter;
- bkj->mode = scene->r.bake_mode;
- bkj->use_lores_mesh = scene->r.bake_flag & R_BAKE_LORES_MESH;
- bkj->bake_clear = scene->r.bake_flag & R_BAKE_CLEAR;
- bkj->bias = scene->r.bake_biasdist;
- bkj->number_of_rays = scene->r.bake_samples;
- bkj->threads = BKE_scene_num_threads(scene);
- bkj->user_scale = (scene->r.bake_flag & R_BAKE_USERSCALE) ? scene->r.bake_user_scale : -1.0f;
- //bkj->reports = op->reports;
-
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
- {
- MultiresBakerJobData *data;
- int lvl;
-
- ob = base->object;
-
- multires_force_update(ob);
-
- data = MEM_callocN(sizeof(MultiresBakerJobData), "multiresBaker derivedMesh_data");
-
- data->ob_image.array = bake_object_image_get_array(ob);
- data->ob_image.len = ob->totcol;
-
- /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
- data->hires_dm = multiresbake_create_hiresdm(scene, ob, &data->tot_lvl, &data->simple);
- data->lores_dm = multiresbake_create_loresdm(scene, ob, &lvl);
- data->lvl = lvl;
-
- BLI_addtail(&bkj->data, data);
- }
- CTX_DATA_END;
+ Scene *scene = CTX_data_scene(C);
+ Object *ob;
+
+ /* backup scene settings, so their changing in UI would take no effect on baker */
+ bkj->scene = scene;
+ bkj->bake_filter = scene->r.bake_filter;
+ bkj->mode = scene->r.bake_mode;
+ bkj->use_lores_mesh = scene->r.bake_flag & R_BAKE_LORES_MESH;
+ bkj->bake_clear = scene->r.bake_flag & R_BAKE_CLEAR;
+ bkj->bias = scene->r.bake_biasdist;
+ bkj->number_of_rays = scene->r.bake_samples;
+ bkj->threads = BKE_scene_num_threads(scene);
+ bkj->user_scale = (scene->r.bake_flag & R_BAKE_USERSCALE) ? scene->r.bake_user_scale : -1.0f;
+ //bkj->reports = op->reports;
+
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
+ MultiresBakerJobData *data;
+ int lvl;
+
+ ob = base->object;
+
+ multires_force_update(ob);
+
+ data = MEM_callocN(sizeof(MultiresBakerJobData), "multiresBaker derivedMesh_data");
+
+ data->ob_image.array = bake_object_image_get_array(ob);
+ data->ob_image.len = ob->totcol;
+
+ /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
+ data->hires_dm = multiresbake_create_hiresdm(scene, ob, &data->tot_lvl, &data->simple);
+ data->lores_dm = multiresbake_create_loresdm(scene, ob, &lvl);
+ data->lvl = lvl;
+
+ BLI_addtail(&bkj->data, data);
+ }
+ CTX_DATA_END;
}
static void multiresbake_startjob(void *bkv, short *stop, short *do_update, float *progress)
{
- MultiresBakerJobData *data;
- MultiresBakeJob *bkj = bkv;
- int baked_objects = 0, tot_obj;
-
- tot_obj = BLI_listbase_count(&bkj->data);
-
- if (bkj->bake_clear) { /* clear images */
- for (data = bkj->data.first; data; data = data->next) {
- ClearFlag clear_flag = 0;
-
- if (bkj->mode == RE_BAKE_NORMALS) {
- clear_flag = CLEAR_TANGENT_NORMAL;
- }
- else if (bkj->mode == RE_BAKE_DISPLACEMENT) {
- clear_flag = CLEAR_DISPLACEMENT;
- }
-
- clear_images_poly(data->ob_image.array, data->ob_image.len, clear_flag);
- }
- }
-
- for (data = bkj->data.first; data; data = data->next) {
- MultiresBakeRender bkr = {NULL};
-
- /* copy data stored in job descriptor */
- bkr.scene = bkj->scene;
- bkr.bake_filter = bkj->bake_filter;
- bkr.mode = bkj->mode;
- bkr.use_lores_mesh = bkj->use_lores_mesh;
- bkr.user_scale = bkj->user_scale;
- //bkr.reports = bkj->reports;
- bkr.ob_image.array = data->ob_image.array;
- bkr.ob_image.len = data->ob_image.len;
-
- /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
- bkr.lores_dm = data->lores_dm;
- bkr.hires_dm = data->hires_dm;
- bkr.tot_lvl = data->tot_lvl;
- bkr.lvl = data->lvl;
- bkr.simple = data->simple;
-
- /* needed for proper progress bar */
- bkr.tot_obj = tot_obj;
- bkr.baked_objects = baked_objects;
-
- bkr.stop = stop;
- bkr.do_update = do_update;
- bkr.progress = progress;
-
- bkr.bias = bkj->bias;
- bkr.number_of_rays = bkj->number_of_rays;
- bkr.threads = bkj->threads;
-
- RE_multires_bake_images(&bkr);
-
- data->images = bkr.image;
-
- baked_objects++;
- }
+ MultiresBakerJobData *data;
+ MultiresBakeJob *bkj = bkv;
+ int baked_objects = 0, tot_obj;
+
+ tot_obj = BLI_listbase_count(&bkj->data);
+
+ if (bkj->bake_clear) { /* clear images */
+ for (data = bkj->data.first; data; data = data->next) {
+ ClearFlag clear_flag = 0;
+
+ if (bkj->mode == RE_BAKE_NORMALS) {
+ clear_flag = CLEAR_TANGENT_NORMAL;
+ }
+ else if (bkj->mode == RE_BAKE_DISPLACEMENT) {
+ clear_flag = CLEAR_DISPLACEMENT;
+ }
+
+ clear_images_poly(data->ob_image.array, data->ob_image.len, clear_flag);
+ }
+ }
+
+ for (data = bkj->data.first; data; data = data->next) {
+ MultiresBakeRender bkr = {NULL};
+
+ /* copy data stored in job descriptor */
+ bkr.scene = bkj->scene;
+ bkr.bake_filter = bkj->bake_filter;
+ bkr.mode = bkj->mode;
+ bkr.use_lores_mesh = bkj->use_lores_mesh;
+ bkr.user_scale = bkj->user_scale;
+ //bkr.reports = bkj->reports;
+ bkr.ob_image.array = data->ob_image.array;
+ bkr.ob_image.len = data->ob_image.len;
+
+ /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
+ bkr.lores_dm = data->lores_dm;
+ bkr.hires_dm = data->hires_dm;
+ bkr.tot_lvl = data->tot_lvl;
+ bkr.lvl = data->lvl;
+ bkr.simple = data->simple;
+
+ /* needed for proper progress bar */
+ bkr.tot_obj = tot_obj;
+ bkr.baked_objects = baked_objects;
+
+ bkr.stop = stop;
+ bkr.do_update = do_update;
+ bkr.progress = progress;
+
+ bkr.bias = bkj->bias;
+ bkr.number_of_rays = bkj->number_of_rays;
+ bkr.threads = bkj->threads;
+
+ RE_multires_bake_images(&bkr);
+
+ data->images = bkr.image;
+
+ baked_objects++;
+ }
}
static void multiresbake_freejob(void *bkv)
{
- MultiresBakeJob *bkj = bkv;
- MultiresBakerJobData *data, *next;
- LinkData *link;
+ MultiresBakeJob *bkj = bkv;
+ MultiresBakerJobData *data, *next;
+ LinkData *link;
- data = bkj->data.first;
- while (data) {
- next = data->next;
- data->lores_dm->release(data->lores_dm);
- data->hires_dm->release(data->hires_dm);
+ data = bkj->data.first;
+ while (data) {
+ next = data->next;
+ data->lores_dm->release(data->lores_dm);
+ data->hires_dm->release(data->hires_dm);
- /* delete here, since this delete will be called from main thread */
- for (link = data->images.first; link; link = link->next) {
- Image *ima = (Image *)link->data;
- GPU_free_image(ima);
- }
+ /* delete here, since this delete will be called from main thread */
+ for (link = data->images.first; link; link = link->next) {
+ Image *ima = (Image *)link->data;
+ GPU_free_image(ima);
+ }
- MEM_freeN(data->ob_image.array);
+ MEM_freeN(data->ob_image.array);
- BLI_freelistN(&data->images);
+ BLI_freelistN(&data->images);
- MEM_freeN(data);
- data = next;
- }
+ MEM_freeN(data);
+ data = next;
+ }
- MEM_freeN(bkj);
+ MEM_freeN(bkj);
}
static int multiresbake_image_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- MultiresBakeJob *bkr;
- wmJob *wm_job;
+ Scene *scene = CTX_data_scene(C);
+ MultiresBakeJob *bkr;
+ wmJob *wm_job;
- if (!multiresbake_check(C, op))
- return OPERATOR_CANCELLED;
+ if (!multiresbake_check(C, op))
+ return OPERATOR_CANCELLED;
- bkr = MEM_callocN(sizeof(MultiresBakeJob), "MultiresBakeJob data");
- init_multiresbake_job(C, bkr);
+ bkr = MEM_callocN(sizeof(MultiresBakeJob), "MultiresBakeJob data");
+ init_multiresbake_job(C, bkr);
- if (!bkr->data.first) {
- BKE_report(op->reports, RPT_ERROR, "No objects found to bake from");
- return OPERATOR_CANCELLED;
- }
+ if (!bkr->data.first) {
+ BKE_report(op->reports, RPT_ERROR, "No objects found to bake from");
+ return OPERATOR_CANCELLED;
+ }
- /* setup job */
- wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Multires Bake",
- WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_BAKE_TEXTURE);
- WM_jobs_customdata_set(wm_job, bkr, multiresbake_freejob);
- WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */
- WM_jobs_callbacks(wm_job, multiresbake_startjob, NULL, NULL, NULL);
+ /* setup job */
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ scene,
+ "Multires Bake",
+ WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS,
+ WM_JOB_TYPE_OBJECT_BAKE_TEXTURE);
+ WM_jobs_customdata_set(wm_job, bkr, multiresbake_freejob);
+ WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */
+ WM_jobs_callbacks(wm_job, multiresbake_startjob, NULL, NULL, NULL);
- G.is_break = false;
+ G.is_break = false;
- WM_jobs_start(CTX_wm_manager(C), wm_job);
- WM_cursor_wait(0);
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+ WM_cursor_wait(0);
- /* add modal handler for ESC */
- WM_event_add_modal_handler(C, op);
+ /* add modal handler for ESC */
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
/* ****************** render BAKING ********************** */
@@ -578,66 +579,65 @@ static int multiresbake_image_exec(bContext *C, wmOperator *op)
/* catch esc */
static int objects_bake_render_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- /* no running blender, remove handler and pass through */
- if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_BAKE_TEXTURE))
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
-
- /* running render */
- switch (event->type) {
- case ESCKEY:
- return OPERATOR_RUNNING_MODAL;
- }
- return OPERATOR_PASS_THROUGH;
+ /* no running blender, remove handler and pass through */
+ if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_BAKE_TEXTURE))
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+
+ /* running render */
+ switch (event->type) {
+ case ESCKEY:
+ return OPERATOR_RUNNING_MODAL;
+ }
+ return OPERATOR_PASS_THROUGH;
}
static bool is_multires_bake(Scene *scene)
{
- if (ELEM(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT, RE_BAKE_AO))
- return scene->r.bake_flag & R_BAKE_MULTIRES;
+ if (ELEM(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT, RE_BAKE_AO))
+ return scene->r.bake_flag & R_BAKE_MULTIRES;
- return 0;
+ return 0;
}
static int objects_bake_render_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(_event))
{
- Scene *scene = CTX_data_scene(C);
- int result = OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ int result = OPERATOR_CANCELLED;
- result = multiresbake_image_exec(C, op);
+ result = multiresbake_image_exec(C, op);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
- return result;
+ return result;
}
-
static int bake_image_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- int result = OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ int result = OPERATOR_CANCELLED;
- if (!is_multires_bake(scene)) {
- BLI_assert(0);
- return result;
- }
+ if (!is_multires_bake(scene)) {
+ BLI_assert(0);
+ return result;
+ }
- result = multiresbake_image_exec_locked(C, op);
+ result = multiresbake_image_exec_locked(C, op);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
- return result;
+ return result;
}
void OBJECT_OT_bake_image(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Bake";
- ot->description = "Bake image textures of selected objects";
- ot->idname = "OBJECT_OT_bake_image";
-
- /* api callbacks */
- ot->exec = bake_image_exec;
- ot->invoke = objects_bake_render_invoke;
- ot->modal = objects_bake_render_modal;
- ot->poll = ED_operator_object_active;
+ /* identifiers */
+ ot->name = "Bake";
+ ot->description = "Bake image textures of selected objects";
+ ot->idname = "OBJECT_OT_bake_image";
+
+ /* api callbacks */
+ ot->exec = bake_image_exec;
+ ot->invoke = objects_bake_render_invoke;
+ ot->modal = objects_bake_render_modal;
+ ot->poll = ED_operator_object_active;
}
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index e3e3f3d10ef..fba5a4e281e 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include "MEM_guardedalloc.h"
#include "DNA_object_types.h"
@@ -77,517 +76,584 @@
static void bake_set_props(wmOperator *op, Scene *scene);
typedef struct BakeAPIRender {
- Object *ob;
- Main *main;
- Scene *scene;
- ViewLayer *view_layer;
- ReportList *reports;
- ListBase selected_objects;
-
- eScenePassType pass_type;
- int pass_filter;
- int margin;
-
- int save_mode;
-
- bool is_clear;
- bool is_split_materials;
- bool is_automatic_name;
- bool is_selected_to_active;
- bool is_cage;
-
- float cage_extrusion;
- int normal_space;
- eBakeNormalSwizzle normal_swizzle[3];
-
- char uv_layer[MAX_CUSTOMDATA_LAYER_NAME];
- char custom_cage[MAX_NAME];
- char filepath[FILE_MAX];
-
- int width;
- int height;
- const char *identifier;
-
- int result;
- bool ready;
-
- /* callbacks */
- Render *render;
- float *progress;
- short *do_update;
-
- /* for redrawing */
- ScrArea *sa;
+ Object *ob;
+ Main *main;
+ Scene *scene;
+ ViewLayer *view_layer;
+ ReportList *reports;
+ ListBase selected_objects;
+
+ eScenePassType pass_type;
+ int pass_filter;
+ int margin;
+
+ int save_mode;
+
+ bool is_clear;
+ bool is_split_materials;
+ bool is_automatic_name;
+ bool is_selected_to_active;
+ bool is_cage;
+
+ float cage_extrusion;
+ int normal_space;
+ eBakeNormalSwizzle normal_swizzle[3];
+
+ char uv_layer[MAX_CUSTOMDATA_LAYER_NAME];
+ char custom_cage[MAX_NAME];
+ char filepath[FILE_MAX];
+
+ int width;
+ int height;
+ const char *identifier;
+
+ int result;
+ bool ready;
+
+ /* callbacks */
+ Render *render;
+ float *progress;
+ short *do_update;
+
+ /* for redrawing */
+ ScrArea *sa;
} BakeAPIRender;
/* callbacks */
static void bake_progress_update(void *bjv, float progress)
{
- BakeAPIRender *bj = bjv;
+ BakeAPIRender *bj = bjv;
- if (bj->progress && *bj->progress != progress) {
- *bj->progress = progress;
+ if (bj->progress && *bj->progress != progress) {
+ *bj->progress = progress;
- /* make jobs timer to send notifier */
- *(bj->do_update) = true;
- }
+ /* make jobs timer to send notifier */
+ *(bj->do_update) = true;
+ }
}
/* catch esc */
static int bake_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- /* no running blender, remove handler and pass through */
- if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_BAKE))
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
-
- /* running render */
- switch (event->type) {
- case ESCKEY:
- {
- G.is_break = true;
- return OPERATOR_RUNNING_MODAL;
- }
- }
- return OPERATOR_PASS_THROUGH;
+ /* no running blender, remove handler and pass through */
+ if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_BAKE))
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+
+ /* running render */
+ switch (event->type) {
+ case ESCKEY: {
+ G.is_break = true;
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+ return OPERATOR_PASS_THROUGH;
}
/* for exec() when there is no render job
* note: this wont check for the escape key being pressed, but doing so isnt threadsafe */
static int bake_break(void *UNUSED(rjv))
{
- if (G.is_break)
- return 1;
- return 0;
+ if (G.is_break)
+ return 1;
+ return 0;
}
-
static void bake_update_image(ScrArea *sa, Image *image)
{
- if (sa && sa->spacetype == SPACE_IMAGE) { /* in case the user changed while baking */
- SpaceImage *sima = sa->spacedata.first;
- if (sima)
- sima->image = image;
- }
+ if (sa && sa->spacetype == SPACE_IMAGE) { /* in case the user changed while baking */
+ SpaceImage *sima = sa->spacedata.first;
+ if (sima)
+ sima->image = image;
+ }
}
-static bool write_internal_bake_pixels(
- Image *image, BakePixel pixel_array[], float *buffer,
- const int width, const int height, const int margin,
- const bool is_clear, const bool is_noncolor)
+static bool write_internal_bake_pixels(Image *image,
+ BakePixel pixel_array[],
+ float *buffer,
+ const int width,
+ const int height,
+ const int margin,
+ const bool is_clear,
+ const bool is_noncolor)
{
- ImBuf *ibuf;
- void *lock;
- bool is_float;
- char *mask_buffer = NULL;
- const size_t num_pixels = (size_t)width * (size_t)height;
-
- ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
-
- if (!ibuf)
- return false;
-
- if (margin > 0 || !is_clear) {
- mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask");
- RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer);
- }
-
- is_float = (ibuf->rect_float != NULL);
-
- /* colormanagement conversions */
- if (!is_noncolor) {
- const char *from_colorspace;
- const char *to_colorspace;
-
- from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
-
- if (is_float)
- to_colorspace = IMB_colormanagement_get_float_colorspace(ibuf);
- else
- to_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
-
- if (from_colorspace != to_colorspace)
- IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false);
- }
-
- /* populates the ImBuf */
- if (is_clear) {
- if (is_float) {
- IMB_buffer_float_from_float(
- ibuf->rect_float, buffer, ibuf->channels,
- IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false,
- ibuf->x, ibuf->y, ibuf->x, ibuf->x);
- }
- else {
- IMB_buffer_byte_from_float(
- (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither,
- IB_PROFILE_SRGB, IB_PROFILE_SRGB,
- false, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
- }
- }
- else {
- if (is_float) {
- IMB_buffer_float_from_float_mask(
- ibuf->rect_float, buffer, ibuf->channels,
- ibuf->x, ibuf->y, ibuf->x, ibuf->x, mask_buffer);
- }
- else {
- IMB_buffer_byte_from_float_mask(
- (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither,
- false, ibuf->x, ibuf->y, ibuf->x, ibuf->x, mask_buffer);
- }
- }
-
- /* margins */
- if (margin > 0)
- RE_bake_margin(ibuf, mask_buffer, margin);
-
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID | IB_BITMAPDIRTY;
-
- if (ibuf->rect_float)
- ibuf->userflags |= IB_RECT_INVALID;
-
- /* force mipmap recalc */
- if (ibuf->mipmap[0]) {
- ibuf->userflags |= IB_MIPMAP_INVALID;
- imb_freemipmapImBuf(ibuf);
- }
-
- BKE_image_release_ibuf(image, ibuf, NULL);
-
- if (mask_buffer)
- MEM_freeN(mask_buffer);
-
- return true;
+ ImBuf *ibuf;
+ void *lock;
+ bool is_float;
+ char *mask_buffer = NULL;
+ const size_t num_pixels = (size_t)width * (size_t)height;
+
+ ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
+
+ if (!ibuf)
+ return false;
+
+ if (margin > 0 || !is_clear) {
+ mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask");
+ RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer);
+ }
+
+ is_float = (ibuf->rect_float != NULL);
+
+ /* colormanagement conversions */
+ if (!is_noncolor) {
+ const char *from_colorspace;
+ const char *to_colorspace;
+
+ from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
+
+ if (is_float)
+ to_colorspace = IMB_colormanagement_get_float_colorspace(ibuf);
+ else
+ to_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
+
+ if (from_colorspace != to_colorspace)
+ IMB_colormanagement_transform(
+ buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false);
+ }
+
+ /* populates the ImBuf */
+ if (is_clear) {
+ if (is_float) {
+ IMB_buffer_float_from_float(ibuf->rect_float,
+ buffer,
+ ibuf->channels,
+ IB_PROFILE_LINEAR_RGB,
+ IB_PROFILE_LINEAR_RGB,
+ false,
+ ibuf->x,
+ ibuf->y,
+ ibuf->x,
+ ibuf->x);
+ }
+ else {
+ IMB_buffer_byte_from_float((unsigned char *)ibuf->rect,
+ buffer,
+ ibuf->channels,
+ ibuf->dither,
+ IB_PROFILE_SRGB,
+ IB_PROFILE_SRGB,
+ false,
+ ibuf->x,
+ ibuf->y,
+ ibuf->x,
+ ibuf->x);
+ }
+ }
+ else {
+ if (is_float) {
+ IMB_buffer_float_from_float_mask(ibuf->rect_float,
+ buffer,
+ ibuf->channels,
+ ibuf->x,
+ ibuf->y,
+ ibuf->x,
+ ibuf->x,
+ mask_buffer);
+ }
+ else {
+ IMB_buffer_byte_from_float_mask((unsigned char *)ibuf->rect,
+ buffer,
+ ibuf->channels,
+ ibuf->dither,
+ false,
+ ibuf->x,
+ ibuf->y,
+ ibuf->x,
+ ibuf->x,
+ mask_buffer);
+ }
+ }
+
+ /* margins */
+ if (margin > 0)
+ RE_bake_margin(ibuf, mask_buffer, margin);
+
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID | IB_BITMAPDIRTY;
+
+ if (ibuf->rect_float)
+ ibuf->userflags |= IB_RECT_INVALID;
+
+ /* force mipmap recalc */
+ if (ibuf->mipmap[0]) {
+ ibuf->userflags |= IB_MIPMAP_INVALID;
+ imb_freemipmapImBuf(ibuf);
+ }
+
+ BKE_image_release_ibuf(image, ibuf, NULL);
+
+ if (mask_buffer)
+ MEM_freeN(mask_buffer);
+
+ return true;
}
/* force OpenGL reload */
static void refresh_images(BakeImages *bake_images)
{
- int i;
- for (i = 0; i < bake_images->size; i++) {
- Image *ima = bake_images->data[i].image;
- if (ima->ok == IMA_OK_LOADED) {
- GPU_free_image(ima);
- DEG_id_tag_update(&ima->id, 0);
- }
- }
+ int i;
+ for (i = 0; i < bake_images->size; i++) {
+ Image *ima = bake_images->data[i].image;
+ if (ima->ok == IMA_OK_LOADED) {
+ GPU_free_image(ima);
+ DEG_id_tag_update(&ima->id, 0);
+ }
+ }
}
-static bool write_external_bake_pixels(
- const char *filepath, BakePixel pixel_array[], float *buffer,
- const int width, const int height, const int margin,
- ImageFormatData *im_format, const bool is_noncolor)
+static bool write_external_bake_pixels(const char *filepath,
+ BakePixel pixel_array[],
+ float *buffer,
+ const int width,
+ const int height,
+ const int margin,
+ ImageFormatData *im_format,
+ const bool is_noncolor)
{
- ImBuf *ibuf = NULL;
- bool ok = false;
- bool is_float;
-
- is_float = im_format->depth > 8;
-
- /* create a new ImBuf */
- ibuf = IMB_allocImBuf(width, height, im_format->planes, (is_float ? IB_rectfloat : IB_rect));
-
- if (!ibuf)
- return false;
-
- /* populates the ImBuf */
- if (is_float) {
- IMB_buffer_float_from_float(
- ibuf->rect_float, buffer, ibuf->channels,
- IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false,
- ibuf->x, ibuf->y, ibuf->x, ibuf->x);
- }
- else {
- if (!is_noncolor) {
- const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
- const char *to_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
- IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false);
- }
-
- IMB_buffer_byte_from_float(
- (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither,
- IB_PROFILE_SRGB, IB_PROFILE_SRGB,
- false, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
- }
-
- /* margins */
- if (margin > 0) {
- char *mask_buffer = NULL;
- const size_t num_pixels = (size_t)width * (size_t)height;
-
- mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask");
- RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer);
- RE_bake_margin(ibuf, mask_buffer, margin);
-
- if (mask_buffer)
- MEM_freeN(mask_buffer);
- }
-
- if ((ok = BKE_imbuf_write(ibuf, filepath, im_format))) {
+ ImBuf *ibuf = NULL;
+ bool ok = false;
+ bool is_float;
+
+ is_float = im_format->depth > 8;
+
+ /* create a new ImBuf */
+ ibuf = IMB_allocImBuf(width, height, im_format->planes, (is_float ? IB_rectfloat : IB_rect));
+
+ if (!ibuf)
+ return false;
+
+ /* populates the ImBuf */
+ if (is_float) {
+ IMB_buffer_float_from_float(ibuf->rect_float,
+ buffer,
+ ibuf->channels,
+ IB_PROFILE_LINEAR_RGB,
+ IB_PROFILE_LINEAR_RGB,
+ false,
+ ibuf->x,
+ ibuf->y,
+ ibuf->x,
+ ibuf->x);
+ }
+ else {
+ if (!is_noncolor) {
+ const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(
+ COLOR_ROLE_SCENE_LINEAR);
+ const char *to_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
+ IMB_colormanagement_transform(
+ buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false);
+ }
+
+ IMB_buffer_byte_from_float((unsigned char *)ibuf->rect,
+ buffer,
+ ibuf->channels,
+ ibuf->dither,
+ IB_PROFILE_SRGB,
+ IB_PROFILE_SRGB,
+ false,
+ ibuf->x,
+ ibuf->y,
+ ibuf->x,
+ ibuf->x);
+ }
+
+ /* margins */
+ if (margin > 0) {
+ char *mask_buffer = NULL;
+ const size_t num_pixels = (size_t)width * (size_t)height;
+
+ mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask");
+ RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer);
+ RE_bake_margin(ibuf, mask_buffer, margin);
+
+ if (mask_buffer)
+ MEM_freeN(mask_buffer);
+ }
+
+ if ((ok = BKE_imbuf_write(ibuf, filepath, im_format))) {
#ifndef WIN32
- chmod(filepath, S_IRUSR | S_IWUSR);
+ chmod(filepath, S_IRUSR | S_IWUSR);
#endif
- //printf("%s saving bake map: '%s'\n", __func__, filepath);
- }
+ //printf("%s saving bake map: '%s'\n", __func__, filepath);
+ }
- /* garbage collection */
- IMB_freeImBuf(ibuf);
+ /* garbage collection */
+ IMB_freeImBuf(ibuf);
- return ok;
+ return ok;
}
static bool is_noncolor_pass(eScenePassType pass_type)
{
- return ELEM(pass_type,
- SCE_PASS_Z,
- SCE_PASS_NORMAL,
- SCE_PASS_VECTOR,
- SCE_PASS_INDEXOB,
- SCE_PASS_UV,
- SCE_PASS_RAYHITS,
- SCE_PASS_INDEXMA);
+ return ELEM(pass_type,
+ SCE_PASS_Z,
+ SCE_PASS_NORMAL,
+ SCE_PASS_VECTOR,
+ SCE_PASS_INDEXOB,
+ SCE_PASS_UV,
+ SCE_PASS_RAYHITS,
+ SCE_PASS_INDEXMA);
}
/* if all is good tag image and return true */
static bool bake_object_check(ViewLayer *view_layer, Object *ob, ReportList *reports)
{
- Image *image;
- Base *base = BKE_view_layer_base_find(view_layer, ob);
- void *lock;
- int i;
-
- if (base == NULL) {
- BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not in view layer", ob->id.name + 2);
- return false;
- }
-
- if (!(base->flag & BASE_ENABLED_RENDER)) {
- BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not enabled for rendering", ob->id.name + 2);
- return false;
- }
-
-
- if (ob->type != OB_MESH) {
- BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not a mesh", ob->id.name + 2);
- return false;
- }
- else {
- Mesh *me = (Mesh *)ob->data;
-
- if (CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV) == -1) {
- BKE_reportf(reports, RPT_ERROR,
- "No active UV layer found in the object \"%s\"", ob->id.name + 2);
- return false;
- }
- }
-
- 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);
-
- if (image) {
- ImBuf *ibuf;
-
- if (node) {
- if (BKE_node_is_connected_to_output(ntree, node)) {
- /* we don't return false since this may be a false positive
- * this can't be RPT_ERROR though, otherwise it prevents
- * multiple highpoly objects to be baked at once */
- BKE_reportf(reports, RPT_INFO,
- "Circular dependency for image \"%s\" from object \"%s\"",
- image->id.name + 2, ob->id.name + 2);
- }
- }
-
- ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
-
- if (ibuf) {
- BKE_image_release_ibuf(image, ibuf, lock);
- }
- else {
- BKE_reportf(reports, RPT_ERROR,
- "Uninitialized image \"%s\" from object \"%s\"",
- image->id.name + 2, ob->id.name + 2);
-
- BKE_image_release_ibuf(image, ibuf, lock);
- return false;
- }
- }
- else {
- Material *mat = give_current_material(ob, i);
- if (mat != NULL) {
- BKE_reportf(reports, RPT_INFO,
- "No active image found in material \"%s\" (%d) for object \"%s\"",
- mat->id.name + 2, i, ob->id.name + 2);
- }
- else {
- BKE_reportf(reports, RPT_INFO,
- "No active image found in material slot (%d) for object \"%s\"",
- i, ob->id.name + 2);
- }
- continue;
- }
-
- image->id.tag |= LIB_TAG_DOIT;
- }
- return true;
+ Image *image;
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+ void *lock;
+ int i;
+
+ if (base == NULL) {
+ BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not in view layer", ob->id.name + 2);
+ return false;
+ }
+
+ if (!(base->flag & BASE_ENABLED_RENDER)) {
+ BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not enabled for rendering", ob->id.name + 2);
+ return false;
+ }
+
+ if (ob->type != OB_MESH) {
+ BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not a mesh", ob->id.name + 2);
+ return false;
+ }
+ else {
+ Mesh *me = (Mesh *)ob->data;
+
+ if (CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV) == -1) {
+ BKE_reportf(
+ reports, RPT_ERROR, "No active UV layer found in the object \"%s\"", ob->id.name + 2);
+ return false;
+ }
+ }
+
+ 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);
+
+ if (image) {
+ ImBuf *ibuf;
+
+ if (node) {
+ if (BKE_node_is_connected_to_output(ntree, node)) {
+ /* we don't return false since this may be a false positive
+ * this can't be RPT_ERROR though, otherwise it prevents
+ * multiple highpoly objects to be baked at once */
+ BKE_reportf(reports,
+ RPT_INFO,
+ "Circular dependency for image \"%s\" from object \"%s\"",
+ image->id.name + 2,
+ ob->id.name + 2);
+ }
+ }
+
+ ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
+
+ if (ibuf) {
+ BKE_image_release_ibuf(image, ibuf, lock);
+ }
+ else {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Uninitialized image \"%s\" from object \"%s\"",
+ image->id.name + 2,
+ ob->id.name + 2);
+
+ BKE_image_release_ibuf(image, ibuf, lock);
+ return false;
+ }
+ }
+ else {
+ Material *mat = give_current_material(ob, i);
+ if (mat != NULL) {
+ BKE_reportf(reports,
+ RPT_INFO,
+ "No active image found in material \"%s\" (%d) for object \"%s\"",
+ mat->id.name + 2,
+ i,
+ ob->id.name + 2);
+ }
+ else {
+ BKE_reportf(reports,
+ RPT_INFO,
+ "No active image found in material slot (%d) for object \"%s\"",
+ i,
+ ob->id.name + 2);
+ }
+ continue;
+ }
+
+ image->id.tag |= LIB_TAG_DOIT;
+ }
+ return true;
}
-static bool bake_pass_filter_check(eScenePassType pass_type, const int pass_filter, ReportList *reports)
+static bool bake_pass_filter_check(eScenePassType pass_type,
+ const int pass_filter,
+ ReportList *reports)
{
- switch (pass_type) {
- case SCE_PASS_COMBINED:
- if ((pass_filter & R_BAKE_PASS_FILTER_EMIT) != 0) {
- return true;
- }
-
- if (((pass_filter & R_BAKE_PASS_FILTER_DIRECT) != 0) ||
- ((pass_filter & R_BAKE_PASS_FILTER_INDIRECT) != 0))
- {
- if (((pass_filter & R_BAKE_PASS_FILTER_DIFFUSE) != 0) ||
- ((pass_filter & R_BAKE_PASS_FILTER_GLOSSY) != 0) ||
- ((pass_filter & R_BAKE_PASS_FILTER_TRANSM) != 0) ||
- ((pass_filter & R_BAKE_PASS_FILTER_SUBSURFACE) != 0))
- {
- return true;
- }
-
- if ((pass_filter & R_BAKE_PASS_FILTER_AO) != 0) {
- BKE_report(reports, RPT_ERROR,
- "Combined bake pass Ambient Occlusion contribution requires an enabled light pass "
- "(bake the Ambient Occlusion pass type instead)");
- }
- else {
- BKE_report(reports, RPT_ERROR,
- "Combined bake pass requires Emit, or a light pass with "
- "Direct or Indirect contributions enabled");
- }
-
- return false;
- }
- else {
- BKE_report(reports, RPT_ERROR,
- "Combined bake pass requires Emit, or a light pass with "
- "Direct or Indirect contributions enabled");
- return false;
- }
- break;
- case SCE_PASS_DIFFUSE_COLOR:
- case SCE_PASS_GLOSSY_COLOR:
- case SCE_PASS_TRANSM_COLOR:
- case SCE_PASS_SUBSURFACE_COLOR:
- if (((pass_filter & R_BAKE_PASS_FILTER_COLOR) != 0) ||
- ((pass_filter & R_BAKE_PASS_FILTER_DIRECT) != 0) ||
- ((pass_filter & R_BAKE_PASS_FILTER_INDIRECT) != 0))
- {
- return true;
- }
- else {
- BKE_report(reports, RPT_ERROR,
- "Bake pass requires Direct, Indirect, or Color contributions to be enabled");
- return false;
- }
- break;
- default:
- return true;
- break;
- }
+ switch (pass_type) {
+ case SCE_PASS_COMBINED:
+ if ((pass_filter & R_BAKE_PASS_FILTER_EMIT) != 0) {
+ return true;
+ }
+
+ if (((pass_filter & R_BAKE_PASS_FILTER_DIRECT) != 0) ||
+ ((pass_filter & R_BAKE_PASS_FILTER_INDIRECT) != 0)) {
+ if (((pass_filter & R_BAKE_PASS_FILTER_DIFFUSE) != 0) ||
+ ((pass_filter & R_BAKE_PASS_FILTER_GLOSSY) != 0) ||
+ ((pass_filter & R_BAKE_PASS_FILTER_TRANSM) != 0) ||
+ ((pass_filter & R_BAKE_PASS_FILTER_SUBSURFACE) != 0)) {
+ return true;
+ }
+
+ if ((pass_filter & R_BAKE_PASS_FILTER_AO) != 0) {
+ BKE_report(
+ reports,
+ RPT_ERROR,
+ "Combined bake pass Ambient Occlusion contribution requires an enabled light pass "
+ "(bake the Ambient Occlusion pass type instead)");
+ }
+ else {
+ BKE_report(reports,
+ RPT_ERROR,
+ "Combined bake pass requires Emit, or a light pass with "
+ "Direct or Indirect contributions enabled");
+ }
+
+ return false;
+ }
+ else {
+ BKE_report(reports,
+ RPT_ERROR,
+ "Combined bake pass requires Emit, or a light pass with "
+ "Direct or Indirect contributions enabled");
+ return false;
+ }
+ break;
+ case SCE_PASS_DIFFUSE_COLOR:
+ case SCE_PASS_GLOSSY_COLOR:
+ case SCE_PASS_TRANSM_COLOR:
+ case SCE_PASS_SUBSURFACE_COLOR:
+ if (((pass_filter & R_BAKE_PASS_FILTER_COLOR) != 0) ||
+ ((pass_filter & R_BAKE_PASS_FILTER_DIRECT) != 0) ||
+ ((pass_filter & R_BAKE_PASS_FILTER_INDIRECT) != 0)) {
+ return true;
+ }
+ else {
+ BKE_report(reports,
+ RPT_ERROR,
+ "Bake pass requires Direct, Indirect, or Color contributions to be enabled");
+ return false;
+ }
+ break;
+ default:
+ return true;
+ break;
+ }
}
/* before even getting in the bake function we check for some basic errors */
-static bool bake_objects_check(Main *bmain, ViewLayer *view_layer, Object *ob, ListBase *selected_objects,
- ReportList *reports, const bool is_selected_to_active)
+static bool bake_objects_check(Main *bmain,
+ ViewLayer *view_layer,
+ Object *ob,
+ ListBase *selected_objects,
+ ReportList *reports,
+ const bool is_selected_to_active)
{
- CollectionPointerLink *link;
-
- /* error handling and tag (in case multiple materials share the same image) */
- BKE_main_id_tag_idcode(bmain, ID_IM, LIB_TAG_DOIT, false);
-
- if (is_selected_to_active) {
- int tot_objects = 0;
-
- if (!bake_object_check(view_layer, ob, reports))
- return false;
-
- for (link = selected_objects->first; link; link = link->next) {
- Object *ob_iter = (Object *)link->ptr.data;
-
- if (ob_iter == ob)
- continue;
-
- if (ELEM(ob_iter->type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL) == false) {
- BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not a mesh or can't be converted to a mesh (Curve, Text, Surface or Metaball)", ob_iter->id.name + 2);
- return false;
- }
- tot_objects += 1;
- }
-
- if (tot_objects == 0) {
- BKE_report(reports, RPT_ERROR, "No valid selected objects");
- return false;
- }
- }
- else {
- if (BLI_listbase_is_empty(selected_objects)) {
- BKE_report(reports, RPT_ERROR, "No valid selected objects");
- return false;
- }
-
- for (link = selected_objects->first; link; link = link->next) {
- if (!bake_object_check(view_layer, link->ptr.data, reports))
- return false;
- }
- }
- return true;
+ CollectionPointerLink *link;
+
+ /* error handling and tag (in case multiple materials share the same image) */
+ BKE_main_id_tag_idcode(bmain, ID_IM, LIB_TAG_DOIT, false);
+
+ if (is_selected_to_active) {
+ int tot_objects = 0;
+
+ if (!bake_object_check(view_layer, ob, reports))
+ return false;
+
+ for (link = selected_objects->first; link; link = link->next) {
+ Object *ob_iter = (Object *)link->ptr.data;
+
+ if (ob_iter == ob)
+ continue;
+
+ if (ELEM(ob_iter->type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL) == false) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Object \"%s\" is not a mesh or can't be converted to a mesh (Curve, Text, "
+ "Surface or Metaball)",
+ ob_iter->id.name + 2);
+ return false;
+ }
+ tot_objects += 1;
+ }
+
+ if (tot_objects == 0) {
+ BKE_report(reports, RPT_ERROR, "No valid selected objects");
+ return false;
+ }
+ }
+ else {
+ if (BLI_listbase_is_empty(selected_objects)) {
+ BKE_report(reports, RPT_ERROR, "No valid selected objects");
+ return false;
+ }
+
+ for (link = selected_objects->first; link; link = link->next) {
+ if (!bake_object_check(view_layer, link->ptr.data, reports))
+ return false;
+ }
+ }
+ return true;
}
/* it needs to be called after bake_objects_check since the image tagging happens there */
static void bake_images_clear(Main *bmain, const bool is_tangent)
{
- Image *image;
- for (image = bmain->images.first; image; image = image->id.next) {
- if ((image->id.tag & LIB_TAG_DOIT) != 0) {
- RE_bake_ibuf_clear(image, is_tangent);
- }
- }
+ Image *image;
+ for (image = bmain->images.first; image; image = image->id.next) {
+ if ((image->id.tag & LIB_TAG_DOIT) != 0) {
+ RE_bake_ibuf_clear(image, is_tangent);
+ }
+ }
}
static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images)
{
- const int tot_mat = ob->totcol;
- int i, j;
- int tot_images = 0;
-
- /* error handling and tag (in case multiple materials share the same image) */
- BKE_main_id_tag_idcode(bmain, ID_IM, LIB_TAG_DOIT, false);
-
- for (i = 0; i < tot_mat; i++) {
- Image *image;
- ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
-
- /* Some materials have no image, we just ignore those cases. */
- if (image == NULL) {
- bake_images->lookup[i] = -1;
- }
- else if (image->id.tag & LIB_TAG_DOIT) {
- for (j = 0; j < i; j++) {
- if (bake_images->data[j].image == image) {
- bake_images->lookup[i] = j;
- break;
- }
- }
- }
- else {
- bake_images->lookup[i] = tot_images;
- bake_images->data[tot_images].image = image;
- image->id.tag |= LIB_TAG_DOIT;
- tot_images++;
- }
- }
-
- bake_images->size = tot_images;
+ const int tot_mat = ob->totcol;
+ int i, j;
+ int tot_images = 0;
+
+ /* error handling and tag (in case multiple materials share the same image) */
+ BKE_main_id_tag_idcode(bmain, ID_IM, LIB_TAG_DOIT, false);
+
+ for (i = 0; i < tot_mat; i++) {
+ Image *image;
+ ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
+
+ /* Some materials have no image, we just ignore those cases. */
+ if (image == NULL) {
+ bake_images->lookup[i] = -1;
+ }
+ else if (image->id.tag & LIB_TAG_DOIT) {
+ for (j = 0; j < i; j++) {
+ if (bake_images->data[j].image == image) {
+ bake_images->lookup[i] = j;
+ break;
+ }
+ }
+ }
+ else {
+ bake_images->lookup[i] = tot_images;
+ bake_images->data[tot_images].image = image;
+ image->id.tag |= LIB_TAG_DOIT;
+ tot_images++;
+ }
+ }
+
+ bake_images->size = tot_images;
}
/*
@@ -595,881 +661,1130 @@ static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images)
*/
static size_t initialize_internal_images(BakeImages *bake_images, ReportList *reports)
{
- int i;
- size_t tot_size = 0;
-
- for (i = 0; i < bake_images->size; i++) {
- ImBuf *ibuf;
- void *lock;
-
- BakeImage *bk_image = &bake_images->data[i];
- ibuf = BKE_image_acquire_ibuf(bk_image->image, NULL, &lock);
-
- if (ibuf) {
- bk_image->width = ibuf->x;
- bk_image->height = ibuf->y;
- bk_image->offset = tot_size;
-
- tot_size += (size_t)ibuf->x * (size_t)ibuf->y;
- }
- else {
- BKE_image_release_ibuf(bk_image->image, ibuf, lock);
- BKE_reportf(reports, RPT_ERROR, "Uninitialized image %s", bk_image->image->id.name + 2);
- return 0;
- }
- BKE_image_release_ibuf(bk_image->image, ibuf, lock);
- }
- return tot_size;
+ int i;
+ size_t tot_size = 0;
+
+ for (i = 0; i < bake_images->size; i++) {
+ ImBuf *ibuf;
+ void *lock;
+
+ BakeImage *bk_image = &bake_images->data[i];
+ ibuf = BKE_image_acquire_ibuf(bk_image->image, NULL, &lock);
+
+ if (ibuf) {
+ bk_image->width = ibuf->x;
+ bk_image->height = ibuf->y;
+ bk_image->offset = tot_size;
+
+ tot_size += (size_t)ibuf->x * (size_t)ibuf->y;
+ }
+ else {
+ BKE_image_release_ibuf(bk_image->image, ibuf, lock);
+ BKE_reportf(reports, RPT_ERROR, "Uninitialized image %s", bk_image->image->id.name + 2);
+ return 0;
+ }
+ BKE_image_release_ibuf(bk_image->image, ibuf, lock);
+ }
+ return tot_size;
}
/* create new mesh with edit mode changes and modifiers applied */
static Mesh *bake_mesh_new_from_object(Depsgraph *depsgraph, Main *bmain, Scene *scene, Object *ob)
{
- bool apply_modifiers = (ob->type != OB_MESH);
- Mesh *me = BKE_mesh_new_from_object(depsgraph, bmain, scene, ob, apply_modifiers, false);
+ bool apply_modifiers = (ob->type != OB_MESH);
+ Mesh *me = BKE_mesh_new_from_object(depsgraph, bmain, scene, ob, apply_modifiers, false);
- if (me->flag & ME_AUTOSMOOTH) {
- BKE_mesh_split_faces(me, true);
- }
+ if (me->flag & ME_AUTOSMOOTH) {
+ BKE_mesh_split_faces(me, true);
+ }
- return me;
+ return me;
}
-static int bake(
- Render *re, Main *bmain, Scene *scene, ViewLayer *view_layer, Object *ob_low, ListBase *selected_objects,
- ReportList *reports,
- const eScenePassType pass_type, const int pass_filter, const int margin,
- const eBakeSaveMode save_mode, const bool is_clear, const bool is_split_materials,
- const bool is_automatic_name, const bool is_selected_to_active, const bool is_cage,
- const float cage_extrusion, const int normal_space, const eBakeNormalSwizzle normal_swizzle[],
- const char *custom_cage, const char *filepath, const int width, const int height,
- const char *identifier, ScrArea *sa, const char *uv_layer)
+static int bake(Render *re,
+ Main *bmain,
+ Scene *scene,
+ ViewLayer *view_layer,
+ Object *ob_low,
+ ListBase *selected_objects,
+ ReportList *reports,
+ const eScenePassType pass_type,
+ const int pass_filter,
+ const int margin,
+ const eBakeSaveMode save_mode,
+ const bool is_clear,
+ const bool is_split_materials,
+ const bool is_automatic_name,
+ const bool is_selected_to_active,
+ const bool is_cage,
+ const float cage_extrusion,
+ const int normal_space,
+ const eBakeNormalSwizzle normal_swizzle[],
+ const char *custom_cage,
+ const char *filepath,
+ const int width,
+ const int height,
+ const char *identifier,
+ ScrArea *sa,
+ const char *uv_layer)
{
- /* We build a depsgraph for the baking,
- * so we don't need to change the original data to adjust visibility and modifiers. */
- Depsgraph *depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER);
- DEG_graph_build_from_view_layer(depsgraph, bmain, scene, view_layer);
-
- int op_result = OPERATOR_CANCELLED;
- bool ok = false;
-
- Object *ob_cage = NULL;
- Object *ob_cage_eval = NULL;
- Object *ob_low_eval = NULL;
-
- BakeHighPolyData *highpoly = NULL;
- int tot_highpoly = 0;
-
- Mesh *me_low = NULL;
- Mesh *me_cage = NULL;
-
- MultiresModifierData *mmd_low = NULL;
- int mmd_flags_low = 0;
-
- float *result = NULL;
-
- BakePixel *pixel_array_low = NULL;
- BakePixel *pixel_array_high = NULL;
-
- const bool is_save_internal = (save_mode == R_BAKE_SAVE_INTERNAL);
- const bool is_noncolor = is_noncolor_pass(pass_type);
- const int depth = RE_pass_depth(pass_type);
-
- BakeImages bake_images = {NULL};
-
- size_t num_pixels;
- int tot_materials;
-
- RE_bake_engine_set_engine_parameters(re, bmain, scene);
-
- if (!RE_bake_has_engine(re)) {
- BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
- goto cleanup;
- }
-
- tot_materials = ob_low->totcol;
-
- if (uv_layer && uv_layer[0] != '\0') {
- Mesh *me = (Mesh *)ob_low->data;
- if (CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, uv_layer) == -1) {
- BKE_reportf(reports, RPT_ERROR,
- "No UV layer named \"%s\" found in the object \"%s\"", uv_layer, ob_low->id.name + 2);
- goto cleanup;
- }
- }
-
- if (tot_materials == 0) {
- if (is_save_internal) {
- BKE_report(reports, RPT_ERROR,
- "No active image found, add a material or bake to an external file");
-
- goto cleanup;
- }
- else if (is_split_materials) {
- BKE_report(reports, RPT_ERROR,
- "No active image found, add a material or bake without the Split Materials option");
-
- goto cleanup;
- }
- else {
- /* baking externally without splitting materials */
- tot_materials = 1;
- }
- }
-
- /* we overallocate in case there is more materials than images */
- bake_images.data = MEM_mallocN(sizeof(BakeImage) * tot_materials, "bake images dimensions (width, height, offset)");
- bake_images.lookup = MEM_mallocN(sizeof(int) * tot_materials, "bake images lookup (from material to BakeImage)");
-
- build_image_lookup(bmain, ob_low, &bake_images);
-
- if (is_save_internal) {
- num_pixels = initialize_internal_images(&bake_images, reports);
-
- if (num_pixels == 0) {
- goto cleanup;
- }
- }
- else {
- /* when saving externally always use the size specified in the UI */
-
- num_pixels = (size_t)width * (size_t)height * bake_images.size;
-
- for (int i = 0; i < bake_images.size; i++) {
- bake_images.data[i].width = width;
- bake_images.data[i].height = height;
- bake_images.data[i].offset = (is_split_materials ? num_pixels : 0);
- bake_images.data[i].image = NULL;
- }
-
- if (!is_split_materials) {
- /* saving a single image */
- for (int i = 0; i < tot_materials; i++) {
- bake_images.lookup[i] = 0;
- }
- }
- }
-
- if (is_selected_to_active) {
- CollectionPointerLink *link;
- tot_highpoly = 0;
-
- for (link = selected_objects->first; link; link = link->next) {
- Object *ob_iter = link->ptr.data;
-
- if (ob_iter == ob_low)
- continue;
-
- tot_highpoly ++;
- }
-
- if (is_cage && custom_cage[0] != '\0') {
- ob_cage = BLI_findstring(&bmain->objects, custom_cage, offsetof(ID, name) + 2);
-
- if (ob_cage == NULL || ob_cage->type != OB_MESH) {
- BKE_report(reports, RPT_ERROR, "No valid cage object");
- goto cleanup;
- }
- else {
- ob_cage_eval = DEG_get_evaluated_object(depsgraph, ob_cage);
- ob_cage_eval->restrictflag |= OB_RESTRICT_RENDER;
- ob_cage_eval->base_flag &= ~(BASE_VISIBLE | BASE_ENABLED_RENDER);
- }
- }
- }
-
- pixel_array_low = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels low poly");
- pixel_array_high = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels high poly");
- result = MEM_callocN(sizeof(float) * depth * num_pixels, "bake return pixels");
-
- /* 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);
- if (mmd_low) {
- mmd_flags_low = mmd_low->flags;
- mmd_low->uv_smooth = SUBSURF_UV_SMOOTH_NONE;
- }
- }
-
- /* Make sure depsgraph is up to date. */
- BKE_scene_graph_update_tagged(depsgraph, bmain);
- ob_low_eval = DEG_get_evaluated_object(depsgraph, ob_low);
-
- /* get the mesh as it arrives in the renderer */
- me_low = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval);
-
- /* populate the pixel array with the face data */
- if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false)
- RE_bake_pixels_populate(me_low, pixel_array_low, num_pixels, &bake_images, uv_layer);
- /* else populate the pixel array with the 'cage' mesh (the smooth version of the mesh) */
-
- if (is_selected_to_active) {
- CollectionPointerLink *link;
- int i = 0;
-
- /* prepare cage mesh */
- if (ob_cage) {
- me_cage = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_cage_eval);
- if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) {
- BKE_report(reports, RPT_ERROR,
- "Invalid cage object, the cage mesh must have the same number "
- "of faces as the active object");
- goto cleanup;
- }
- }
- else if (is_cage) {
- BKE_object_eval_reset(ob_low_eval);
-
- ModifierData *md = ob_low_eval->modifiers.first;
- while (md) {
- ModifierData *md_next = md->next;
-
- /* Edge Split cannot be applied in the cage,
- * the cage is supposed to have interpolated normals
- * between the faces unless the geometry is physically
- * split. So we create a copy of the low poly mesh without
- * the eventual edge split.*/
-
- if (md->type == eModifierType_EdgeSplit) {
- BLI_remlink(&ob_low_eval->modifiers, md);
- modifier_free(md);
- }
- md = md_next;
- }
-
- me_cage = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval);
- RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
- }
-
- highpoly = MEM_callocN(sizeof(BakeHighPolyData) * tot_highpoly, "bake high poly objects");
-
- /* populate highpoly array */
- for (link = selected_objects->first; link; link = link->next) {
- Object *ob_iter = link->ptr.data;
-
- if (ob_iter == ob_low)
- continue;
-
- /* initialize highpoly_data */
- highpoly[i].ob = ob_iter;
- highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter);
- highpoly[i].ob_eval->restrictflag &= ~OB_RESTRICT_RENDER;
- highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE | BASE_ENABLED_RENDER);
- highpoly[i].me = bake_mesh_new_from_object(depsgraph, bmain, scene, highpoly[i].ob_eval);
-
- /* lowpoly to highpoly transformation matrix */
- copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
- invert_m4_m4(highpoly[i].imat, highpoly[i].obmat);
-
- highpoly[i].is_flip_object = is_negative_m4(highpoly[i].ob->obmat);
-
- i++;
- }
-
- BLI_assert(i == tot_highpoly);
-
-
- if (ob_cage != NULL) {
- ob_cage_eval->restrictflag |= OB_RESTRICT_RENDER;
- ob_cage_eval->base_flag &= ~(BASE_VISIBLE | BASE_ENABLED_RENDER);
- }
- ob_low_eval->restrictflag |= OB_RESTRICT_RENDER;
- ob_low_eval->base_flag &= ~(BASE_VISIBLE | BASE_ENABLED_RENDER);
-
- /* populate the pixel arrays with the corresponding face data for each high poly object */
- if (!RE_bake_pixels_populate_from_objects(
- me_low, pixel_array_low, pixel_array_high, highpoly, tot_highpoly, num_pixels, ob_cage != NULL,
- cage_extrusion, ob_low_eval->obmat, (ob_cage ? ob_cage->obmat : ob_low_eval->obmat), me_cage))
- {
- BKE_report(reports, RPT_ERROR, "Error handling selected objects");
- goto cleanup;
- }
-
- /* the baking itself */
- for (i = 0; i < tot_highpoly; i++) {
- ok = RE_bake_engine(re, depsgraph, highpoly[i].ob, i, pixel_array_high,
- num_pixels, depth, pass_type, pass_filter, result);
- if (!ok) {
- BKE_reportf(reports, RPT_ERROR, "Error baking from object \"%s\"", highpoly[i].ob->id.name + 2);
- goto cleanup;
- }
- }
- }
- else {
- /* If low poly is not renderable it should have failed long ago. */
- BLI_assert((ob_low_eval->restrictflag & OB_RESTRICT_RENDER) == 0);
-
- if (RE_bake_has_engine(re)) {
- ok = RE_bake_engine(re, depsgraph, ob_low_eval, 0, pixel_array_low, num_pixels, depth, pass_type, pass_filter, result);
- }
- else {
- BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
- goto cleanup;
- }
- }
-
- /* normal space conversion
- * the normals are expected to be in world space, +X +Y +Z */
- if (ok && pass_type == SCE_PASS_NORMAL) {
- switch (normal_space) {
- case R_BAKE_SPACE_WORLD:
- {
- /* Cycles internal format */
- if ((normal_swizzle[0] == R_BAKE_POSX) &&
- (normal_swizzle[1] == R_BAKE_POSY) &&
- (normal_swizzle[2] == R_BAKE_POSZ))
- {
- break;
- }
- else {
- RE_bake_normal_world_to_world(pixel_array_low, num_pixels, depth, result, normal_swizzle);
- }
- break;
- }
- case R_BAKE_SPACE_OBJECT:
- {
- RE_bake_normal_world_to_object(pixel_array_low, num_pixels, depth, result, ob_low_eval, normal_swizzle);
- break;
- }
- case R_BAKE_SPACE_TANGENT:
- {
- if (is_selected_to_active) {
- RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_low, normal_swizzle, ob_low_eval->obmat);
- }
- else {
- /* from multiresolution */
- Mesh *me_nores = NULL;
- ModifierData *md = NULL;
- int mode;
-
- BKE_object_eval_reset(ob_low_eval);
- md = modifiers_findByType(ob_low_eval, eModifierType_Multires);
-
- if (md) {
- mode = md->mode;
- md->mode &= ~eModifierMode_Render;
- }
-
- /* Evaluate modifiers again. */
- me_nores = BKE_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval, true, false);
- RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);
-
- RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_nores, normal_swizzle, ob_low_eval->obmat);
- BKE_id_free(bmain, me_nores);
-
- if (md)
- md->mode = mode;
- }
- break;
- }
- default:
- break;
- }
- }
-
- if (!ok) {
- BKE_reportf(reports, RPT_ERROR, "Problem baking object \"%s\"", ob_low->id.name + 2);
- op_result = OPERATOR_CANCELLED;
- }
- else {
- /* save the results */
- for (int i = 0; i < bake_images.size; i++) {
- BakeImage *bk_image = &bake_images.data[i];
-
- if (is_save_internal) {
- ok = write_internal_bake_pixels(
- bk_image->image,
- pixel_array_low + bk_image->offset,
- result + bk_image->offset * depth,
- bk_image->width, bk_image->height,
- margin, is_clear, is_noncolor);
-
- /* might be read by UI to set active image for display */
- bake_update_image(sa, bk_image->image);
-
- if (!ok) {
- BKE_reportf(reports, RPT_ERROR,
- "Problem saving the bake map internally for object \"%s\"", ob_low->id.name + 2);
- op_result = OPERATOR_CANCELLED;
- }
- else {
- BKE_report(reports, RPT_INFO,
- "Baking map saved to internal image, save it externally or pack it");
- op_result = OPERATOR_FINISHED;
- }
- }
- /* save externally */
- else {
- BakeData *bake = &scene->r.bake;
- char name[FILE_MAX];
-
- BKE_image_path_from_imtype(name, filepath, BKE_main_blendfile_path(bmain),
- 0, bake->im_format.imtype, true, false, NULL);
-
- if (is_automatic_name) {
- BLI_path_suffix(name, FILE_MAX, ob_low->id.name + 2, "_");
- BLI_path_suffix(name, FILE_MAX, identifier, "_");
- }
-
- if (is_split_materials) {
- if (bk_image->image) {
- BLI_path_suffix(name, FILE_MAX, bk_image->image->id.name + 2, "_");
- }
- else {
- if (ob_low_eval->mat[i]) {
- BLI_path_suffix(name, FILE_MAX, ob_low_eval->mat[i]->id.name + 2, "_");
- }
- else if (me_low->mat[i]) {
- BLI_path_suffix(name, FILE_MAX, me_low->mat[i]->id.name + 2, "_");
- }
- else {
- /* if everything else fails, use the material index */
- char tmp[5];
- sprintf(tmp, "%d", i % 1000);
- BLI_path_suffix(name, FILE_MAX, tmp, "_");
- }
- }
- }
-
- /* save it externally */
- ok = write_external_bake_pixels(
- name,
- pixel_array_low + bk_image->offset,
- result + bk_image->offset * depth,
- bk_image->width, bk_image->height,
- margin, &bake->im_format, is_noncolor);
-
- if (!ok) {
- BKE_reportf(reports, RPT_ERROR, "Problem saving baked map in \"%s\"", name);
- op_result = OPERATOR_CANCELLED;
- }
- else {
- BKE_reportf(reports, RPT_INFO, "Baking map written to \"%s\"", name);
- op_result = OPERATOR_FINISHED;
- }
-
- if (!is_split_materials) {
- break;
- }
- }
- }
- }
-
- if (is_save_internal)
- refresh_images(&bake_images);
+ /* We build a depsgraph for the baking,
+ * so we don't need to change the original data to adjust visibility and modifiers. */
+ Depsgraph *depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER);
+ DEG_graph_build_from_view_layer(depsgraph, bmain, scene, view_layer);
+
+ int op_result = OPERATOR_CANCELLED;
+ bool ok = false;
+
+ Object *ob_cage = NULL;
+ Object *ob_cage_eval = NULL;
+ Object *ob_low_eval = NULL;
+
+ BakeHighPolyData *highpoly = NULL;
+ int tot_highpoly = 0;
+
+ Mesh *me_low = NULL;
+ Mesh *me_cage = NULL;
+
+ MultiresModifierData *mmd_low = NULL;
+ int mmd_flags_low = 0;
+
+ float *result = NULL;
+
+ BakePixel *pixel_array_low = NULL;
+ BakePixel *pixel_array_high = NULL;
+
+ const bool is_save_internal = (save_mode == R_BAKE_SAVE_INTERNAL);
+ const bool is_noncolor = is_noncolor_pass(pass_type);
+ const int depth = RE_pass_depth(pass_type);
+
+ BakeImages bake_images = {NULL};
+
+ size_t num_pixels;
+ int tot_materials;
+
+ RE_bake_engine_set_engine_parameters(re, bmain, scene);
+
+ if (!RE_bake_has_engine(re)) {
+ BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
+ goto cleanup;
+ }
+
+ tot_materials = ob_low->totcol;
+
+ if (uv_layer && uv_layer[0] != '\0') {
+ Mesh *me = (Mesh *)ob_low->data;
+ if (CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, uv_layer) == -1) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "No UV layer named \"%s\" found in the object \"%s\"",
+ uv_layer,
+ ob_low->id.name + 2);
+ goto cleanup;
+ }
+ }
+
+ if (tot_materials == 0) {
+ if (is_save_internal) {
+ BKE_report(
+ reports, RPT_ERROR, "No active image found, add a material or bake to an external file");
+
+ goto cleanup;
+ }
+ else if (is_split_materials) {
+ BKE_report(
+ reports,
+ RPT_ERROR,
+ "No active image found, add a material or bake without the Split Materials option");
+
+ goto cleanup;
+ }
+ else {
+ /* baking externally without splitting materials */
+ tot_materials = 1;
+ }
+ }
+
+ /* we overallocate in case there is more materials than images */
+ bake_images.data = MEM_mallocN(sizeof(BakeImage) * tot_materials,
+ "bake images dimensions (width, height, offset)");
+ bake_images.lookup = MEM_mallocN(sizeof(int) * tot_materials,
+ "bake images lookup (from material to BakeImage)");
+
+ build_image_lookup(bmain, ob_low, &bake_images);
+
+ if (is_save_internal) {
+ num_pixels = initialize_internal_images(&bake_images, reports);
+
+ if (num_pixels == 0) {
+ goto cleanup;
+ }
+ }
+ else {
+ /* when saving externally always use the size specified in the UI */
+
+ num_pixels = (size_t)width * (size_t)height * bake_images.size;
+
+ for (int i = 0; i < bake_images.size; i++) {
+ bake_images.data[i].width = width;
+ bake_images.data[i].height = height;
+ bake_images.data[i].offset = (is_split_materials ? num_pixels : 0);
+ bake_images.data[i].image = NULL;
+ }
+
+ if (!is_split_materials) {
+ /* saving a single image */
+ for (int i = 0; i < tot_materials; i++) {
+ bake_images.lookup[i] = 0;
+ }
+ }
+ }
+
+ if (is_selected_to_active) {
+ CollectionPointerLink *link;
+ tot_highpoly = 0;
+
+ for (link = selected_objects->first; link; link = link->next) {
+ Object *ob_iter = link->ptr.data;
+
+ if (ob_iter == ob_low)
+ continue;
+
+ tot_highpoly++;
+ }
+
+ if (is_cage && custom_cage[0] != '\0') {
+ ob_cage = BLI_findstring(&bmain->objects, custom_cage, offsetof(ID, name) + 2);
+
+ if (ob_cage == NULL || ob_cage->type != OB_MESH) {
+ BKE_report(reports, RPT_ERROR, "No valid cage object");
+ goto cleanup;
+ }
+ else {
+ ob_cage_eval = DEG_get_evaluated_object(depsgraph, ob_cage);
+ ob_cage_eval->restrictflag |= OB_RESTRICT_RENDER;
+ ob_cage_eval->base_flag &= ~(BASE_VISIBLE | BASE_ENABLED_RENDER);
+ }
+ }
+ }
+
+ pixel_array_low = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels low poly");
+ pixel_array_high = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels high poly");
+ result = MEM_callocN(sizeof(float) * depth * num_pixels, "bake return pixels");
+
+ /* 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);
+ if (mmd_low) {
+ mmd_flags_low = mmd_low->flags;
+ mmd_low->uv_smooth = SUBSURF_UV_SMOOTH_NONE;
+ }
+ }
+
+ /* Make sure depsgraph is up to date. */
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
+ ob_low_eval = DEG_get_evaluated_object(depsgraph, ob_low);
+
+ /* get the mesh as it arrives in the renderer */
+ me_low = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval);
+
+ /* populate the pixel array with the face data */
+ if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false)
+ RE_bake_pixels_populate(me_low, pixel_array_low, num_pixels, &bake_images, uv_layer);
+ /* else populate the pixel array with the 'cage' mesh (the smooth version of the mesh) */
+
+ if (is_selected_to_active) {
+ CollectionPointerLink *link;
+ int i = 0;
+
+ /* prepare cage mesh */
+ if (ob_cage) {
+ me_cage = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_cage_eval);
+ if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) {
+ BKE_report(reports,
+ RPT_ERROR,
+ "Invalid cage object, the cage mesh must have the same number "
+ "of faces as the active object");
+ goto cleanup;
+ }
+ }
+ else if (is_cage) {
+ BKE_object_eval_reset(ob_low_eval);
+
+ ModifierData *md = ob_low_eval->modifiers.first;
+ while (md) {
+ ModifierData *md_next = md->next;
+
+ /* Edge Split cannot be applied in the cage,
+ * the cage is supposed to have interpolated normals
+ * between the faces unless the geometry is physically
+ * split. So we create a copy of the low poly mesh without
+ * the eventual edge split.*/
+
+ if (md->type == eModifierType_EdgeSplit) {
+ BLI_remlink(&ob_low_eval->modifiers, md);
+ modifier_free(md);
+ }
+ md = md_next;
+ }
+
+ me_cage = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval);
+ RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
+ }
+
+ highpoly = MEM_callocN(sizeof(BakeHighPolyData) * tot_highpoly, "bake high poly objects");
+
+ /* populate highpoly array */
+ for (link = selected_objects->first; link; link = link->next) {
+ Object *ob_iter = link->ptr.data;
+
+ if (ob_iter == ob_low)
+ continue;
+
+ /* initialize highpoly_data */
+ highpoly[i].ob = ob_iter;
+ highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter);
+ highpoly[i].ob_eval->restrictflag &= ~OB_RESTRICT_RENDER;
+ highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE | BASE_ENABLED_RENDER);
+ highpoly[i].me = bake_mesh_new_from_object(depsgraph, bmain, scene, highpoly[i].ob_eval);
+
+ /* lowpoly to highpoly transformation matrix */
+ copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
+ invert_m4_m4(highpoly[i].imat, highpoly[i].obmat);
+
+ highpoly[i].is_flip_object = is_negative_m4(highpoly[i].ob->obmat);
+
+ i++;
+ }
+
+ BLI_assert(i == tot_highpoly);
+
+ if (ob_cage != NULL) {
+ ob_cage_eval->restrictflag |= OB_RESTRICT_RENDER;
+ ob_cage_eval->base_flag &= ~(BASE_VISIBLE | BASE_ENABLED_RENDER);
+ }
+ ob_low_eval->restrictflag |= OB_RESTRICT_RENDER;
+ ob_low_eval->base_flag &= ~(BASE_VISIBLE | BASE_ENABLED_RENDER);
+
+ /* populate the pixel arrays with the corresponding face data for each high poly object */
+ if (!RE_bake_pixels_populate_from_objects(me_low,
+ pixel_array_low,
+ pixel_array_high,
+ highpoly,
+ tot_highpoly,
+ num_pixels,
+ ob_cage != NULL,
+ cage_extrusion,
+ ob_low_eval->obmat,
+ (ob_cage ? ob_cage->obmat : ob_low_eval->obmat),
+ me_cage)) {
+ BKE_report(reports, RPT_ERROR, "Error handling selected objects");
+ goto cleanup;
+ }
+
+ /* the baking itself */
+ for (i = 0; i < tot_highpoly; i++) {
+ ok = RE_bake_engine(re,
+ depsgraph,
+ highpoly[i].ob,
+ i,
+ pixel_array_high,
+ num_pixels,
+ depth,
+ pass_type,
+ pass_filter,
+ result);
+ if (!ok) {
+ BKE_reportf(
+ reports, RPT_ERROR, "Error baking from object \"%s\"", highpoly[i].ob->id.name + 2);
+ goto cleanup;
+ }
+ }
+ }
+ else {
+ /* If low poly is not renderable it should have failed long ago. */
+ BLI_assert((ob_low_eval->restrictflag & OB_RESTRICT_RENDER) == 0);
+
+ if (RE_bake_has_engine(re)) {
+ ok = RE_bake_engine(re,
+ depsgraph,
+ ob_low_eval,
+ 0,
+ pixel_array_low,
+ num_pixels,
+ depth,
+ pass_type,
+ pass_filter,
+ result);
+ }
+ else {
+ BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
+ goto cleanup;
+ }
+ }
+
+ /* normal space conversion
+ * the normals are expected to be in world space, +X +Y +Z */
+ if (ok && pass_type == SCE_PASS_NORMAL) {
+ switch (normal_space) {
+ case R_BAKE_SPACE_WORLD: {
+ /* Cycles internal format */
+ if ((normal_swizzle[0] == R_BAKE_POSX) && (normal_swizzle[1] == R_BAKE_POSY) &&
+ (normal_swizzle[2] == R_BAKE_POSZ)) {
+ break;
+ }
+ else {
+ RE_bake_normal_world_to_world(
+ pixel_array_low, num_pixels, depth, result, normal_swizzle);
+ }
+ break;
+ }
+ case R_BAKE_SPACE_OBJECT: {
+ RE_bake_normal_world_to_object(
+ pixel_array_low, num_pixels, depth, result, ob_low_eval, normal_swizzle);
+ break;
+ }
+ case R_BAKE_SPACE_TANGENT: {
+ if (is_selected_to_active) {
+ RE_bake_normal_world_to_tangent(pixel_array_low,
+ num_pixels,
+ depth,
+ result,
+ me_low,
+ normal_swizzle,
+ ob_low_eval->obmat);
+ }
+ else {
+ /* from multiresolution */
+ Mesh *me_nores = NULL;
+ ModifierData *md = NULL;
+ int mode;
+
+ BKE_object_eval_reset(ob_low_eval);
+ md = modifiers_findByType(ob_low_eval, eModifierType_Multires);
+
+ if (md) {
+ mode = md->mode;
+ md->mode &= ~eModifierMode_Render;
+ }
+
+ /* Evaluate modifiers again. */
+ me_nores = BKE_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval, true, false);
+ RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);
+
+ RE_bake_normal_world_to_tangent(pixel_array_low,
+ num_pixels,
+ depth,
+ result,
+ me_nores,
+ normal_swizzle,
+ ob_low_eval->obmat);
+ BKE_id_free(bmain, me_nores);
+
+ if (md)
+ md->mode = mode;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if (!ok) {
+ BKE_reportf(reports, RPT_ERROR, "Problem baking object \"%s\"", ob_low->id.name + 2);
+ op_result = OPERATOR_CANCELLED;
+ }
+ else {
+ /* save the results */
+ for (int i = 0; i < bake_images.size; i++) {
+ BakeImage *bk_image = &bake_images.data[i];
+
+ if (is_save_internal) {
+ ok = write_internal_bake_pixels(bk_image->image,
+ pixel_array_low + bk_image->offset,
+ result + bk_image->offset * depth,
+ bk_image->width,
+ bk_image->height,
+ margin,
+ is_clear,
+ is_noncolor);
+
+ /* might be read by UI to set active image for display */
+ bake_update_image(sa, bk_image->image);
+
+ if (!ok) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Problem saving the bake map internally for object \"%s\"",
+ ob_low->id.name + 2);
+ op_result = OPERATOR_CANCELLED;
+ }
+ else {
+ BKE_report(reports,
+ RPT_INFO,
+ "Baking map saved to internal image, save it externally or pack it");
+ op_result = OPERATOR_FINISHED;
+ }
+ }
+ /* save externally */
+ else {
+ BakeData *bake = &scene->r.bake;
+ char name[FILE_MAX];
+
+ BKE_image_path_from_imtype(name,
+ filepath,
+ BKE_main_blendfile_path(bmain),
+ 0,
+ bake->im_format.imtype,
+ true,
+ false,
+ NULL);
+
+ if (is_automatic_name) {
+ BLI_path_suffix(name, FILE_MAX, ob_low->id.name + 2, "_");
+ BLI_path_suffix(name, FILE_MAX, identifier, "_");
+ }
+
+ if (is_split_materials) {
+ if (bk_image->image) {
+ BLI_path_suffix(name, FILE_MAX, bk_image->image->id.name + 2, "_");
+ }
+ else {
+ if (ob_low_eval->mat[i]) {
+ BLI_path_suffix(name, FILE_MAX, ob_low_eval->mat[i]->id.name + 2, "_");
+ }
+ else if (me_low->mat[i]) {
+ BLI_path_suffix(name, FILE_MAX, me_low->mat[i]->id.name + 2, "_");
+ }
+ else {
+ /* if everything else fails, use the material index */
+ char tmp[5];
+ sprintf(tmp, "%d", i % 1000);
+ BLI_path_suffix(name, FILE_MAX, tmp, "_");
+ }
+ }
+ }
+
+ /* save it externally */
+ ok = write_external_bake_pixels(name,
+ pixel_array_low + bk_image->offset,
+ result + bk_image->offset * depth,
+ bk_image->width,
+ bk_image->height,
+ margin,
+ &bake->im_format,
+ is_noncolor);
+
+ if (!ok) {
+ BKE_reportf(reports, RPT_ERROR, "Problem saving baked map in \"%s\"", name);
+ op_result = OPERATOR_CANCELLED;
+ }
+ else {
+ BKE_reportf(reports, RPT_INFO, "Baking map written to \"%s\"", name);
+ op_result = OPERATOR_FINISHED;
+ }
+
+ if (!is_split_materials) {
+ break;
+ }
+ }
+ }
+ }
+
+ if (is_save_internal)
+ refresh_images(&bake_images);
cleanup:
- if (highpoly) {
- int i;
- for (i = 0; i < tot_highpoly; i++) {
- if (highpoly[i].me)
- BKE_id_free(bmain, highpoly[i].me);
- }
- MEM_freeN(highpoly);
- }
+ if (highpoly) {
+ int i;
+ for (i = 0; i < tot_highpoly; i++) {
+ if (highpoly[i].me)
+ BKE_id_free(bmain, highpoly[i].me);
+ }
+ MEM_freeN(highpoly);
+ }
- if (mmd_low)
- mmd_low->flags = mmd_flags_low;
+ if (mmd_low)
+ mmd_low->flags = mmd_flags_low;
- if (pixel_array_low)
- MEM_freeN(pixel_array_low);
+ if (pixel_array_low)
+ MEM_freeN(pixel_array_low);
- if (pixel_array_high)
- MEM_freeN(pixel_array_high);
+ if (pixel_array_high)
+ MEM_freeN(pixel_array_high);
- if (bake_images.data)
- MEM_freeN(bake_images.data);
+ if (bake_images.data)
+ MEM_freeN(bake_images.data);
- if (bake_images.lookup)
- MEM_freeN(bake_images.lookup);
+ if (bake_images.lookup)
+ MEM_freeN(bake_images.lookup);
- if (result)
- MEM_freeN(result);
+ if (result)
+ MEM_freeN(result);
- if (me_low)
- BKE_id_free(bmain, me_low);
+ if (me_low)
+ BKE_id_free(bmain, me_low);
- if (me_cage)
- BKE_id_free(bmain, me_cage);
+ if (me_cage)
+ BKE_id_free(bmain, me_cage);
- DEG_graph_free(depsgraph);
+ DEG_graph_free(depsgraph);
- return op_result;
+ return op_result;
}
static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr)
{
- bool is_save_internal;
- bScreen *sc = CTX_wm_screen(C);
+ bool is_save_internal;
+ bScreen *sc = 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->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->pass_type = RNA_enum_get(op->ptr, "type");
- bkr->pass_filter = RNA_enum_get(op->ptr, "pass_filter");
- bkr->margin = RNA_int_get(op->ptr, "margin");
+ bkr->pass_type = RNA_enum_get(op->ptr, "type");
+ bkr->pass_filter = RNA_enum_get(op->ptr, "pass_filter");
+ bkr->margin = RNA_int_get(op->ptr, "margin");
- bkr->save_mode = RNA_enum_get(op->ptr, "save_mode");
- is_save_internal = (bkr->save_mode == R_BAKE_SAVE_INTERNAL);
+ bkr->save_mode = RNA_enum_get(op->ptr, "save_mode");
+ is_save_internal = (bkr->save_mode == R_BAKE_SAVE_INTERNAL);
- bkr->is_clear = RNA_boolean_get(op->ptr, "use_clear");
- bkr->is_split_materials = (!is_save_internal) && RNA_boolean_get(op->ptr, "use_split_materials");
- bkr->is_automatic_name = RNA_boolean_get(op->ptr, "use_automatic_name");
- bkr->is_selected_to_active = RNA_boolean_get(op->ptr, "use_selected_to_active");
- bkr->is_cage = RNA_boolean_get(op->ptr, "use_cage");
- bkr->cage_extrusion = RNA_float_get(op->ptr, "cage_extrusion");
+ bkr->is_clear = RNA_boolean_get(op->ptr, "use_clear");
+ bkr->is_split_materials = (!is_save_internal) && RNA_boolean_get(op->ptr, "use_split_materials");
+ bkr->is_automatic_name = RNA_boolean_get(op->ptr, "use_automatic_name");
+ bkr->is_selected_to_active = RNA_boolean_get(op->ptr, "use_selected_to_active");
+ bkr->is_cage = RNA_boolean_get(op->ptr, "use_cage");
+ bkr->cage_extrusion = RNA_float_get(op->ptr, "cage_extrusion");
- bkr->normal_space = RNA_enum_get(op->ptr, "normal_space");
- bkr->normal_swizzle[0] = RNA_enum_get(op->ptr, "normal_r");
- bkr->normal_swizzle[1] = RNA_enum_get(op->ptr, "normal_g");
- bkr->normal_swizzle[2] = RNA_enum_get(op->ptr, "normal_b");
+ bkr->normal_space = RNA_enum_get(op->ptr, "normal_space");
+ bkr->normal_swizzle[0] = RNA_enum_get(op->ptr, "normal_r");
+ bkr->normal_swizzle[1] = RNA_enum_get(op->ptr, "normal_g");
+ bkr->normal_swizzle[2] = RNA_enum_get(op->ptr, "normal_b");
- bkr->width = RNA_int_get(op->ptr, "width");
- bkr->height = RNA_int_get(op->ptr, "height");
- bkr->identifier = "";
+ bkr->width = RNA_int_get(op->ptr, "width");
+ bkr->height = RNA_int_get(op->ptr, "height");
+ bkr->identifier = "";
- RNA_string_get(op->ptr, "uv_layer", bkr->uv_layer);
+ RNA_string_get(op->ptr, "uv_layer", bkr->uv_layer);
- RNA_string_get(op->ptr, "cage_object", bkr->custom_cage);
+ RNA_string_get(op->ptr, "cage_object", bkr->custom_cage);
- if ((!is_save_internal) && bkr->is_automatic_name) {
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, "type");
- RNA_property_enum_identifier(C, op->ptr, prop, bkr->pass_type, &bkr->identifier);
- }
+ if ((!is_save_internal) && bkr->is_automatic_name) {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "type");
+ RNA_property_enum_identifier(C, op->ptr, prop, bkr->pass_type, &bkr->identifier);
+ }
- CTX_data_selected_objects(C, &bkr->selected_objects);
+ CTX_data_selected_objects(C, &bkr->selected_objects);
- bkr->reports = op->reports;
+ bkr->reports = op->reports;
- bkr->result = OPERATOR_CANCELLED;
+ bkr->result = OPERATOR_CANCELLED;
- bkr->render = RE_NewSceneRender(bkr->scene);
+ bkr->render = RE_NewSceneRender(bkr->scene);
- /* XXX hack to force saving to always be internal. Whether (and how) to support
- * external saving will be addressed later */
- bkr->save_mode = R_BAKE_SAVE_INTERNAL;
+ /* XXX hack to force saving to always be internal. Whether (and how) to support
+ * external saving will be addressed later */
+ bkr->save_mode = R_BAKE_SAVE_INTERNAL;
}
static int bake_exec(bContext *C, wmOperator *op)
{
- Render *re;
- int result = OPERATOR_CANCELLED;
- BakeAPIRender bkr = {NULL};
- Scene *scene = CTX_data_scene(C);
-
- G.is_break = false;
- G.is_rendering = true;
-
- bake_set_props(op, scene);
-
- bake_init_api_data(op, C, &bkr);
- re = bkr.render;
-
- /* setup new render */
- RE_test_break_cb(re, NULL, bake_break);
-
- if (!bake_pass_filter_check(bkr.pass_type, bkr.pass_filter, bkr.reports)) {
- goto finally;
- }
-
- if (!bake_objects_check(bkr.main, bkr.view_layer, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.is_selected_to_active)) {
- goto finally;
- }
-
- if (bkr.is_clear) {
- const bool is_tangent = ((bkr.pass_type == SCE_PASS_NORMAL) && (bkr.normal_space == R_BAKE_SPACE_TANGENT));
- bake_images_clear(bkr.main, is_tangent);
- }
-
- RE_SetReports(re, bkr.reports);
-
- if (bkr.is_selected_to_active) {
- result = bake(
- bkr.render, bkr.main, bkr.scene, bkr.view_layer, bkr.ob, &bkr.selected_objects, bkr.reports,
- bkr.pass_type, bkr.pass_filter, bkr.margin, bkr.save_mode,
- bkr.is_clear, bkr.is_split_materials, bkr.is_automatic_name, true, bkr.is_cage,
- bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle,
- bkr.custom_cage, bkr.filepath, bkr.width, bkr.height, bkr.identifier, bkr.sa,
- bkr.uv_layer);
- }
- else {
- CollectionPointerLink *link;
- const bool is_clear = bkr.is_clear && BLI_listbase_is_single(&bkr.selected_objects);
- for (link = bkr.selected_objects.first; link; link = link->next) {
- Object *ob_iter = link->ptr.data;
- result = bake(
- bkr.render, bkr.main, bkr.scene, bkr.view_layer, ob_iter, NULL, bkr.reports,
- bkr.pass_type, bkr.pass_filter, bkr.margin, bkr.save_mode,
- is_clear, bkr.is_split_materials, bkr.is_automatic_name, false, bkr.is_cage,
- bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle,
- bkr.custom_cage, bkr.filepath, bkr.width, bkr.height, bkr.identifier, bkr.sa,
- bkr.uv_layer);
- }
- }
-
- RE_SetReports(re, NULL);
-
+ Render *re;
+ int result = OPERATOR_CANCELLED;
+ BakeAPIRender bkr = {NULL};
+ Scene *scene = CTX_data_scene(C);
+
+ G.is_break = false;
+ G.is_rendering = true;
+
+ bake_set_props(op, scene);
+
+ bake_init_api_data(op, C, &bkr);
+ re = bkr.render;
+
+ /* setup new render */
+ RE_test_break_cb(re, NULL, bake_break);
+
+ if (!bake_pass_filter_check(bkr.pass_type, bkr.pass_filter, bkr.reports)) {
+ goto finally;
+ }
+
+ if (!bake_objects_check(bkr.main,
+ bkr.view_layer,
+ bkr.ob,
+ &bkr.selected_objects,
+ bkr.reports,
+ bkr.is_selected_to_active)) {
+ goto finally;
+ }
+
+ if (bkr.is_clear) {
+ const bool is_tangent = ((bkr.pass_type == SCE_PASS_NORMAL) &&
+ (bkr.normal_space == R_BAKE_SPACE_TANGENT));
+ bake_images_clear(bkr.main, is_tangent);
+ }
+
+ RE_SetReports(re, bkr.reports);
+
+ if (bkr.is_selected_to_active) {
+ result = bake(bkr.render,
+ bkr.main,
+ bkr.scene,
+ bkr.view_layer,
+ bkr.ob,
+ &bkr.selected_objects,
+ bkr.reports,
+ bkr.pass_type,
+ bkr.pass_filter,
+ bkr.margin,
+ bkr.save_mode,
+ bkr.is_clear,
+ bkr.is_split_materials,
+ bkr.is_automatic_name,
+ true,
+ bkr.is_cage,
+ bkr.cage_extrusion,
+ bkr.normal_space,
+ bkr.normal_swizzle,
+ bkr.custom_cage,
+ bkr.filepath,
+ bkr.width,
+ bkr.height,
+ bkr.identifier,
+ bkr.sa,
+ bkr.uv_layer);
+ }
+ else {
+ CollectionPointerLink *link;
+ const bool is_clear = bkr.is_clear && BLI_listbase_is_single(&bkr.selected_objects);
+ for (link = bkr.selected_objects.first; link; link = link->next) {
+ Object *ob_iter = link->ptr.data;
+ result = bake(bkr.render,
+ bkr.main,
+ bkr.scene,
+ bkr.view_layer,
+ ob_iter,
+ NULL,
+ bkr.reports,
+ bkr.pass_type,
+ bkr.pass_filter,
+ bkr.margin,
+ bkr.save_mode,
+ is_clear,
+ bkr.is_split_materials,
+ bkr.is_automatic_name,
+ false,
+ bkr.is_cage,
+ bkr.cage_extrusion,
+ bkr.normal_space,
+ bkr.normal_swizzle,
+ bkr.custom_cage,
+ bkr.filepath,
+ bkr.width,
+ bkr.height,
+ bkr.identifier,
+ bkr.sa,
+ bkr.uv_layer);
+ }
+ }
+
+ RE_SetReports(re, NULL);
finally:
- G.is_rendering = false;
- BLI_freelistN(&bkr.selected_objects);
- return result;
+ G.is_rendering = false;
+ BLI_freelistN(&bkr.selected_objects);
+ return result;
}
static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, float *progress)
{
- BakeAPIRender *bkr = (BakeAPIRender *)bkv;
-
- /* setup new render */
- bkr->do_update = do_update;
- bkr->progress = progress;
-
- RE_SetReports(bkr->render, bkr->reports);
-
- if (!bake_pass_filter_check(bkr->pass_type, bkr->pass_filter, bkr->reports)) {
- bkr->result = OPERATOR_CANCELLED;
- return;
- }
-
- if (!bake_objects_check(bkr->main, bkr->view_layer, bkr->ob, &bkr->selected_objects, bkr->reports, bkr->is_selected_to_active)) {
- bkr->result = OPERATOR_CANCELLED;
- return;
- }
-
- if (bkr->is_clear) {
- const bool is_tangent = ((bkr->pass_type == SCE_PASS_NORMAL) && (bkr->normal_space == R_BAKE_SPACE_TANGENT));
- bake_images_clear(bkr->main, is_tangent);
- }
-
- if (bkr->is_selected_to_active) {
- bkr->result = bake(
- bkr->render, bkr->main, bkr->scene, bkr->view_layer, bkr->ob, &bkr->selected_objects, bkr->reports,
- bkr->pass_type, bkr->pass_filter, bkr->margin, bkr->save_mode,
- bkr->is_clear, bkr->is_split_materials, bkr->is_automatic_name, true, bkr->is_cage,
- bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle,
- bkr->custom_cage, bkr->filepath, bkr->width, bkr->height, bkr->identifier, bkr->sa,
- bkr->uv_layer);
- }
- else {
- CollectionPointerLink *link;
- const bool is_clear = bkr->is_clear && BLI_listbase_is_single(&bkr->selected_objects);
- for (link = bkr->selected_objects.first; link; link = link->next) {
- Object *ob_iter = link->ptr.data;
- bkr->result = bake(
- bkr->render, bkr->main, bkr->scene, bkr->view_layer, ob_iter, NULL, bkr->reports,
- bkr->pass_type, bkr->pass_filter, bkr->margin, bkr->save_mode,
- is_clear, bkr->is_split_materials, bkr->is_automatic_name, false, bkr->is_cage,
- bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle,
- bkr->custom_cage, bkr->filepath, bkr->width, bkr->height, bkr->identifier, bkr->sa,
- bkr->uv_layer);
-
- if (bkr->result == OPERATOR_CANCELLED)
- return;
- }
- }
-
- RE_SetReports(bkr->render, NULL);
+ BakeAPIRender *bkr = (BakeAPIRender *)bkv;
+
+ /* setup new render */
+ bkr->do_update = do_update;
+ bkr->progress = progress;
+
+ RE_SetReports(bkr->render, bkr->reports);
+
+ if (!bake_pass_filter_check(bkr->pass_type, bkr->pass_filter, bkr->reports)) {
+ bkr->result = OPERATOR_CANCELLED;
+ return;
+ }
+
+ if (!bake_objects_check(bkr->main,
+ bkr->view_layer,
+ bkr->ob,
+ &bkr->selected_objects,
+ bkr->reports,
+ bkr->is_selected_to_active)) {
+ bkr->result = OPERATOR_CANCELLED;
+ return;
+ }
+
+ if (bkr->is_clear) {
+ const bool is_tangent = ((bkr->pass_type == SCE_PASS_NORMAL) &&
+ (bkr->normal_space == R_BAKE_SPACE_TANGENT));
+ bake_images_clear(bkr->main, is_tangent);
+ }
+
+ if (bkr->is_selected_to_active) {
+ bkr->result = bake(bkr->render,
+ bkr->main,
+ bkr->scene,
+ bkr->view_layer,
+ bkr->ob,
+ &bkr->selected_objects,
+ bkr->reports,
+ bkr->pass_type,
+ bkr->pass_filter,
+ bkr->margin,
+ bkr->save_mode,
+ bkr->is_clear,
+ bkr->is_split_materials,
+ bkr->is_automatic_name,
+ true,
+ bkr->is_cage,
+ bkr->cage_extrusion,
+ bkr->normal_space,
+ bkr->normal_swizzle,
+ bkr->custom_cage,
+ bkr->filepath,
+ bkr->width,
+ bkr->height,
+ bkr->identifier,
+ bkr->sa,
+ bkr->uv_layer);
+ }
+ else {
+ CollectionPointerLink *link;
+ const bool is_clear = bkr->is_clear && BLI_listbase_is_single(&bkr->selected_objects);
+ for (link = bkr->selected_objects.first; link; link = link->next) {
+ Object *ob_iter = link->ptr.data;
+ bkr->result = bake(bkr->render,
+ bkr->main,
+ bkr->scene,
+ bkr->view_layer,
+ ob_iter,
+ NULL,
+ bkr->reports,
+ bkr->pass_type,
+ bkr->pass_filter,
+ bkr->margin,
+ bkr->save_mode,
+ is_clear,
+ bkr->is_split_materials,
+ bkr->is_automatic_name,
+ false,
+ bkr->is_cage,
+ bkr->cage_extrusion,
+ bkr->normal_space,
+ bkr->normal_swizzle,
+ bkr->custom_cage,
+ bkr->filepath,
+ bkr->width,
+ bkr->height,
+ bkr->identifier,
+ bkr->sa,
+ bkr->uv_layer);
+
+ if (bkr->result == OPERATOR_CANCELLED)
+ return;
+ }
+ }
+
+ RE_SetReports(bkr->render, NULL);
}
static void bake_freejob(void *bkv)
{
- BakeAPIRender *bkr = (BakeAPIRender *)bkv;
+ BakeAPIRender *bkr = (BakeAPIRender *)bkv;
- BLI_freelistN(&bkr->selected_objects);
- MEM_freeN(bkr);
+ BLI_freelistN(&bkr->selected_objects);
+ MEM_freeN(bkr);
- G.is_rendering = false;
+ G.is_rendering = false;
}
static void bake_set_props(wmOperator *op, Scene *scene)
{
- PropertyRNA *prop;
- BakeData *bake = &scene->r.bake;
-
- prop = RNA_struct_find_property(op->ptr, "filepath");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_string_set(op->ptr, prop, bake->filepath);
- }
-
- prop = RNA_struct_find_property(op->ptr, "width");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_int_set(op->ptr, prop, bake->width);
- }
-
- prop = RNA_struct_find_property(op->ptr, "height");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_int_set(op->ptr, prop, bake->width);
- }
-
- prop = RNA_struct_find_property(op->ptr, "margin");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_int_set(op->ptr, prop, bake->margin);
- }
-
- prop = RNA_struct_find_property(op->ptr, "use_selected_to_active");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_TO_ACTIVE) != 0);
- }
-
- prop = RNA_struct_find_property(op->ptr, "cage_extrusion");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_float_set(op->ptr, prop, bake->cage_extrusion);
- }
-
- prop = RNA_struct_find_property(op->ptr, "cage_object");
- if (!RNA_property_is_set(op->ptr, prop)) {
- if (bake->cage_object) {
- RNA_property_string_set(op->ptr, prop, bake->cage_object->id.name + 2);
- }
- }
-
- prop = RNA_struct_find_property(op->ptr, "normal_space");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_enum_set(op->ptr, prop, bake->normal_space);
- }
-
- prop = RNA_struct_find_property(op->ptr, "normal_r");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[0]);
- }
-
- prop = RNA_struct_find_property(op->ptr, "normal_g");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[1]);
- }
-
- prop = RNA_struct_find_property(op->ptr, "normal_b");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[2]);
- }
-
- prop = RNA_struct_find_property(op->ptr, "save_mode");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_enum_set(op->ptr, prop, bake->save_mode);
- }
-
- prop = RNA_struct_find_property(op->ptr, "use_clear");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CLEAR) != 0);
- }
-
- prop = RNA_struct_find_property(op->ptr, "use_cage");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CAGE) != 0);
- }
-
- prop = RNA_struct_find_property(op->ptr, "use_split_materials");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_SPLIT_MAT) != 0);
- }
-
- prop = RNA_struct_find_property(op->ptr, "use_automatic_name");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_AUTO_NAME) != 0);
- }
-
- prop = RNA_struct_find_property(op->ptr, "pass_filter");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_enum_set(op->ptr, prop, bake->pass_filter);
- }
+ PropertyRNA *prop;
+ BakeData *bake = &scene->r.bake;
+
+ prop = RNA_struct_find_property(op->ptr, "filepath");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_string_set(op->ptr, prop, bake->filepath);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "width");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_int_set(op->ptr, prop, bake->width);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "height");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_int_set(op->ptr, prop, bake->width);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "margin");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_int_set(op->ptr, prop, bake->margin);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "use_selected_to_active");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_TO_ACTIVE) != 0);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "cage_extrusion");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_float_set(op->ptr, prop, bake->cage_extrusion);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "cage_object");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ if (bake->cage_object) {
+ RNA_property_string_set(op->ptr, prop, bake->cage_object->id.name + 2);
+ }
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "normal_space");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_enum_set(op->ptr, prop, bake->normal_space);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "normal_r");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[0]);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "normal_g");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[1]);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "normal_b");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[2]);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "save_mode");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_enum_set(op->ptr, prop, bake->save_mode);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "use_clear");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CLEAR) != 0);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "use_cage");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CAGE) != 0);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "use_split_materials");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_SPLIT_MAT) != 0);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "use_automatic_name");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_AUTO_NAME) != 0);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "pass_filter");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_enum_set(op->ptr, prop, bake->pass_filter);
+ }
}
static int bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- wmJob *wm_job;
- BakeAPIRender *bkr;
- Render *re;
- Scene *scene = CTX_data_scene(C);
+ wmJob *wm_job;
+ BakeAPIRender *bkr;
+ Render *re;
+ Scene *scene = CTX_data_scene(C);
- bake_set_props(op, scene);
+ bake_set_props(op, scene);
- /* only one render job at a time */
- if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_OBJECT_BAKE))
- return OPERATOR_CANCELLED;
+ /* only one render job at a time */
+ if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_OBJECT_BAKE))
+ return OPERATOR_CANCELLED;
- bkr = MEM_mallocN(sizeof(BakeAPIRender), "render bake");
+ bkr = MEM_mallocN(sizeof(BakeAPIRender), "render bake");
- /* init bake render */
- bake_init_api_data(op, C, bkr);
- re = bkr->render;
+ /* init bake render */
+ bake_init_api_data(op, C, bkr);
+ re = bkr->render;
- /* setup new render */
- RE_test_break_cb(re, NULL, bake_break);
- RE_progress_cb(re, bkr, bake_progress_update);
+ /* setup new render */
+ RE_test_break_cb(re, NULL, bake_break);
+ RE_progress_cb(re, bkr, bake_progress_update);
- /* setup job */
- wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Texture Bake",
- WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_BAKE);
- WM_jobs_customdata_set(wm_job, bkr, bake_freejob);
- WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */
- WM_jobs_callbacks(wm_job, bake_startjob, NULL, NULL, NULL);
+ /* setup job */
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ scene,
+ "Texture Bake",
+ WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS,
+ WM_JOB_TYPE_OBJECT_BAKE);
+ WM_jobs_customdata_set(wm_job, bkr, bake_freejob);
+ WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */
+ WM_jobs_callbacks(wm_job, bake_startjob, NULL, NULL, NULL);
- G.is_break = false;
- G.is_rendering = true;
+ G.is_break = false;
+ G.is_rendering = true;
- WM_jobs_start(CTX_wm_manager(C), wm_job);
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
- WM_cursor_wait(0);
+ WM_cursor_wait(0);
- /* add modal handler for ESC */
- WM_event_add_modal_handler(C, op);
+ /* add modal handler for ESC */
+ WM_event_add_modal_handler(C, op);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
- return OPERATOR_RUNNING_MODAL;
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
+ return OPERATOR_RUNNING_MODAL;
}
void OBJECT_OT_bake(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Bake";
- ot->description = "Bake image textures of selected objects";
- ot->idname = "OBJECT_OT_bake";
-
- /* api callbacks */
- ot->exec = bake_exec;
- ot->modal = bake_modal;
- ot->invoke = bake_invoke;
- ot->poll = ED_operator_object_active_editable_mesh;
-
- RNA_def_enum(ot->srna, "type", rna_enum_bake_pass_type_items, SCE_PASS_COMBINED, "Type",
- "Type of pass to bake, some of them may not be supported by the current render engine");
- prop = RNA_def_enum(ot->srna, "pass_filter", rna_enum_bake_pass_filter_type_items, R_BAKE_PASS_FILTER_NONE, "Pass Filter",
- "Filter to combined, diffuse, glossy, transmission and subsurface passes");
- RNA_def_property_flag(prop, PROP_ENUM_FLAG);
- RNA_def_string_file_path(ot->srna, "filepath", NULL, FILE_MAX, "File Path",
- "Image filepath to use when saving externally");
- RNA_def_int(ot->srna, "width", 512, 1, INT_MAX, "Width",
- "Horizontal dimension of the baking map (external only)", 64, 4096);
- RNA_def_int(ot->srna, "height", 512, 1, INT_MAX, "Height",
- "Vertical dimension of the baking map (external only)", 64, 4096);
- RNA_def_int(ot->srna, "margin", 16, 0, INT_MAX, "Margin",
- "Extends the baked result as a post process filter", 0, 64);
- RNA_def_boolean(ot->srna, "use_selected_to_active", false, "Selected to Active",
- "Bake shading on the surface of selected objects to the active object");
- RNA_def_float(ot->srna, "cage_extrusion", 0.0f, 0.0f, FLT_MAX, "Cage Extrusion",
- "Distance to use for the inward ray cast when using selected to active", 0.0f, 1.0f);
- RNA_def_string(ot->srna, "cage_object", NULL, MAX_NAME, "Cage Object",
- "Object to use as cage, instead of calculating the cage from the active object with cage extrusion");
- RNA_def_enum(ot->srna, "normal_space", rna_enum_normal_space_items, R_BAKE_SPACE_TANGENT, "Normal Space",
- "Choose normal space for baking");
- RNA_def_enum(ot->srna, "normal_r", rna_enum_normal_swizzle_items, R_BAKE_POSX, "R", "Axis to bake in red channel");
- RNA_def_enum(ot->srna, "normal_g", rna_enum_normal_swizzle_items, R_BAKE_POSY, "G", "Axis to bake in green channel");
- RNA_def_enum(ot->srna, "normal_b", rna_enum_normal_swizzle_items, R_BAKE_POSZ, "B", "Axis to bake in blue channel");
- RNA_def_enum(ot->srna, "save_mode", rna_enum_bake_save_mode_items, R_BAKE_SAVE_INTERNAL, "Save Mode",
- "Choose how to save the baking map");
- RNA_def_boolean(ot->srna, "use_clear", false, "Clear",
- "Clear Images before baking (only for internal saving)");
- RNA_def_boolean(ot->srna, "use_cage", false, "Cage",
- "Cast rays to active object from a cage");
- RNA_def_boolean(ot->srna, "use_split_materials", false, "Split Materials",
- "Split baked maps per material, using material name in output file (external only)");
- RNA_def_boolean(ot->srna, "use_automatic_name", false, "Automatic Name",
- "Automatically name the output file with the pass type");
- RNA_def_string(ot->srna, "uv_layer", NULL, MAX_CUSTOMDATA_LAYER_NAME, "UV Layer", "UV layer to override active");
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Bake";
+ ot->description = "Bake image textures of selected objects";
+ ot->idname = "OBJECT_OT_bake";
+
+ /* api callbacks */
+ ot->exec = bake_exec;
+ ot->modal = bake_modal;
+ ot->invoke = bake_invoke;
+ ot->poll = ED_operator_object_active_editable_mesh;
+
+ RNA_def_enum(
+ ot->srna,
+ "type",
+ rna_enum_bake_pass_type_items,
+ SCE_PASS_COMBINED,
+ "Type",
+ "Type of pass to bake, some of them may not be supported by the current render engine");
+ prop = RNA_def_enum(ot->srna,
+ "pass_filter",
+ rna_enum_bake_pass_filter_type_items,
+ R_BAKE_PASS_FILTER_NONE,
+ "Pass Filter",
+ "Filter to combined, diffuse, glossy, transmission and subsurface passes");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_string_file_path(ot->srna,
+ "filepath",
+ NULL,
+ FILE_MAX,
+ "File Path",
+ "Image filepath to use when saving externally");
+ RNA_def_int(ot->srna,
+ "width",
+ 512,
+ 1,
+ INT_MAX,
+ "Width",
+ "Horizontal dimension of the baking map (external only)",
+ 64,
+ 4096);
+ RNA_def_int(ot->srna,
+ "height",
+ 512,
+ 1,
+ INT_MAX,
+ "Height",
+ "Vertical dimension of the baking map (external only)",
+ 64,
+ 4096);
+ RNA_def_int(ot->srna,
+ "margin",
+ 16,
+ 0,
+ INT_MAX,
+ "Margin",
+ "Extends the baked result as a post process filter",
+ 0,
+ 64);
+ RNA_def_boolean(ot->srna,
+ "use_selected_to_active",
+ false,
+ "Selected to Active",
+ "Bake shading on the surface of selected objects to the active object");
+ RNA_def_float(ot->srna,
+ "cage_extrusion",
+ 0.0f,
+ 0.0f,
+ FLT_MAX,
+ "Cage Extrusion",
+ "Distance to use for the inward ray cast when using selected to active",
+ 0.0f,
+ 1.0f);
+ RNA_def_string(ot->srna,
+ "cage_object",
+ NULL,
+ MAX_NAME,
+ "Cage Object",
+ "Object to use as cage, instead of calculating the cage from the active object "
+ "with cage extrusion");
+ RNA_def_enum(ot->srna,
+ "normal_space",
+ rna_enum_normal_space_items,
+ R_BAKE_SPACE_TANGENT,
+ "Normal Space",
+ "Choose normal space for baking");
+ RNA_def_enum(ot->srna,
+ "normal_r",
+ rna_enum_normal_swizzle_items,
+ R_BAKE_POSX,
+ "R",
+ "Axis to bake in red channel");
+ RNA_def_enum(ot->srna,
+ "normal_g",
+ rna_enum_normal_swizzle_items,
+ R_BAKE_POSY,
+ "G",
+ "Axis to bake in green channel");
+ RNA_def_enum(ot->srna,
+ "normal_b",
+ rna_enum_normal_swizzle_items,
+ R_BAKE_POSZ,
+ "B",
+ "Axis to bake in blue channel");
+ RNA_def_enum(ot->srna,
+ "save_mode",
+ rna_enum_bake_save_mode_items,
+ R_BAKE_SAVE_INTERNAL,
+ "Save Mode",
+ "Choose how to save the baking map");
+ RNA_def_boolean(ot->srna,
+ "use_clear",
+ false,
+ "Clear",
+ "Clear Images before baking (only for internal saving)");
+ RNA_def_boolean(ot->srna, "use_cage", false, "Cage", "Cast rays to active object from a cage");
+ RNA_def_boolean(
+ ot->srna,
+ "use_split_materials",
+ false,
+ "Split Materials",
+ "Split baked maps per material, using material name in output file (external only)");
+ RNA_def_boolean(ot->srna,
+ "use_automatic_name",
+ false,
+ "Automatic Name",
+ "Automatically name the output file with the pass type");
+ RNA_def_string(ot->srna,
+ "uv_layer",
+ NULL,
+ MAX_CUSTOMDATA_LAYER_NAME,
+ "UV Layer",
+ "UV layer to override active");
}
diff --git a/source/blender/editors/object/object_collection.c b/source/blender/editors/object/object_collection.c
index e8552c823bf..0b22dec99c7 100644
--- a/source/blender/editors/object/object_collection.c
+++ b/source/blender/editors/object/object_collection.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <string.h>
#include "BLI_blenlib.h"
@@ -56,546 +55,566 @@
/********************* 3d view operators ***********************/
/* can be called with C == NULL */
-static const EnumPropertyItem *collection_object_active_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *collection_object_active_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob;
- EnumPropertyItem *item = NULL, item_tmp = {0};
- int totitem = 0;
-
- if (C == NULL) {
- return DummyRNA_NULL_items;
- }
-
- ob = ED_object_context(C);
-
- /* check that the object exists */
- if (ob) {
- Collection *collection;
- int i = 0, count = 0;
-
- /* if 2 or more collections, add option to add to all collections */
- collection = NULL;
- while ((collection = BKE_collection_object_find(bmain, scene, collection, ob)))
- count++;
-
- if (count >= 2) {
- item_tmp.identifier = item_tmp.name = "All Collections";
- item_tmp.value = INT_MAX; /* this will give NULL on lookup */
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- RNA_enum_item_add_separator(&item, &totitem);
- }
-
- /* add collections */
- collection = NULL;
- while ((collection = BKE_collection_object_find(bmain, scene, collection, ob))) {
- item_tmp.identifier = item_tmp.name = collection->id.name + 2;
- /* item_tmp.icon = ICON_ARMATURE_DATA; */
- item_tmp.value = i;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- i++;
- }
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob;
+ EnumPropertyItem *item = NULL, item_tmp = {0};
+ int totitem = 0;
+
+ if (C == NULL) {
+ return DummyRNA_NULL_items;
+ }
+
+ ob = ED_object_context(C);
+
+ /* check that the object exists */
+ if (ob) {
+ Collection *collection;
+ int i = 0, count = 0;
+
+ /* if 2 or more collections, add option to add to all collections */
+ collection = NULL;
+ while ((collection = BKE_collection_object_find(bmain, scene, collection, ob)))
+ count++;
+
+ if (count >= 2) {
+ item_tmp.identifier = item_tmp.name = "All Collections";
+ item_tmp.value = INT_MAX; /* this will give NULL on lookup */
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ RNA_enum_item_add_separator(&item, &totitem);
+ }
+
+ /* add collections */
+ collection = NULL;
+ while ((collection = BKE_collection_object_find(bmain, scene, collection, ob))) {
+ item_tmp.identifier = item_tmp.name = collection->id.name + 2;
+ /* item_tmp.icon = ICON_ARMATURE_DATA; */
+ item_tmp.value = i;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ i++;
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
/* get the collection back from the enum index, quite awkward and UI specific */
-static Collection *collection_object_active_find_index(Main *bmain, Scene *scene, Object *ob, const int collection_object_index)
+static Collection *collection_object_active_find_index(Main *bmain,
+ Scene *scene,
+ Object *ob,
+ const int collection_object_index)
{
- Collection *collection = NULL;
- int i = 0;
- while ((collection = BKE_collection_object_find(bmain, scene, collection, ob))) {
- if (i == collection_object_index) {
- break;
- }
- i++;
- }
-
- return collection;
+ Collection *collection = NULL;
+ int i = 0;
+ while ((collection = BKE_collection_object_find(bmain, scene, collection, ob))) {
+ if (i == collection_object_index) {
+ break;
+ }
+ i++;
+ }
+
+ return collection;
}
static int objects_add_active_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- int single_collection_index = RNA_enum_get(op->ptr, "collection");
- Collection *single_collection = collection_object_active_find_index(bmain, scene, ob, single_collection_index);
- bool is_cycle = false;
- bool updated = false;
-
- if (ob == NULL)
- return OPERATOR_CANCELLED;
-
- /* now add all selected objects to the collection(s) */
- FOREACH_COLLECTION_BEGIN(bmain, scene, Collection *, collection)
- {
- if (single_collection && collection != single_collection)
- continue;
- if (!BKE_collection_has_object(collection, ob))
- continue;
-
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
- {
- if (BKE_collection_has_object(collection, base->object))
- continue;
-
- if (!BKE_collection_object_cyclic_check(bmain, base->object, collection)) {
- BKE_collection_object_add(bmain, collection, base->object);
- DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
- updated = true;
- }
- else {
- is_cycle = true;
- }
- }
- CTX_DATA_END;
- }
- FOREACH_COLLECTION_END;
-
- if (is_cycle)
- BKE_report(op->reports, RPT_WARNING, "Skipped some collections because of cycle detected");
-
- if (!updated)
- return OPERATOR_CANCELLED;
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
+ Object *ob = ED_object_context(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ int single_collection_index = RNA_enum_get(op->ptr, "collection");
+ Collection *single_collection = collection_object_active_find_index(
+ bmain, scene, ob, single_collection_index);
+ bool is_cycle = false;
+ bool updated = false;
+
+ if (ob == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* now add all selected objects to the collection(s) */
+ FOREACH_COLLECTION_BEGIN(bmain, scene, Collection *, collection)
+ {
+ if (single_collection && collection != single_collection)
+ continue;
+ if (!BKE_collection_has_object(collection, ob))
+ continue;
+
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
+ if (BKE_collection_has_object(collection, base->object))
+ continue;
+
+ if (!BKE_collection_object_cyclic_check(bmain, base->object, collection)) {
+ BKE_collection_object_add(bmain, collection, base->object);
+ DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
+ updated = true;
+ }
+ else {
+ is_cycle = true;
+ }
+ }
+ CTX_DATA_END;
+ }
+ FOREACH_COLLECTION_END;
+
+ if (is_cycle)
+ BKE_report(op->reports, RPT_WARNING, "Skipped some collections because of cycle detected");
+
+ if (!updated)
+ return OPERATOR_CANCELLED;
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
}
void COLLECTION_OT_objects_add_active(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Add Selected To Active Collection";
- ot->description = "Add the object to an object collection that contains the active object";
- ot->idname = "COLLECTION_OT_objects_add_active";
-
- /* api callbacks */
- ot->exec = objects_add_active_exec;
- ot->invoke = WM_menu_invoke;
- ot->poll = ED_operator_objectmode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "The collection to add other selected objects to");
- RNA_def_enum_funcs(prop, collection_object_active_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Add Selected To Active Collection";
+ ot->description = "Add the object to an object collection that contains the active object";
+ ot->idname = "COLLECTION_OT_objects_add_active";
+
+ /* api callbacks */
+ ot->exec = objects_add_active_exec;
+ ot->invoke = WM_menu_invoke;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna,
+ "collection",
+ DummyRNA_NULL_items,
+ 0,
+ "Collection",
+ "The collection to add other selected objects to");
+ RNA_def_enum_funcs(prop, collection_object_active_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
static int objects_remove_active_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);
- Object *ob = OBACT(view_layer);
- int single_collection_index = RNA_enum_get(op->ptr, "collection");
- Collection *single_collection = collection_object_active_find_index(bmain, scene, ob, single_collection_index);
- bool ok = false;
-
- if (ob == NULL)
- return OPERATOR_CANCELLED;
-
- /* Linking to same collection requires its own loop so we can avoid
- * looking up the active objects collections each time. */
- FOREACH_COLLECTION_BEGIN(bmain, scene, Collection *, collection)
- {
- if (single_collection && collection != single_collection)
- continue;
-
- if (BKE_collection_has_object(collection, ob)) {
- /* Remove collections from selected objects */
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
- {
- BKE_collection_object_remove(bmain, collection, base->object, false);
- DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
- ok = 1;
- }
- CTX_DATA_END;
- }
- }
- FOREACH_COLLECTION_END;
-
- if (!ok)
- BKE_report(op->reports, RPT_ERROR, "Active object contains no collections");
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ int single_collection_index = RNA_enum_get(op->ptr, "collection");
+ Collection *single_collection = collection_object_active_find_index(
+ bmain, scene, ob, single_collection_index);
+ bool ok = false;
+
+ if (ob == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* Linking to same collection requires its own loop so we can avoid
+ * looking up the active objects collections each time. */
+ FOREACH_COLLECTION_BEGIN(bmain, scene, Collection *, collection)
+ {
+ if (single_collection && collection != single_collection)
+ continue;
+
+ if (BKE_collection_has_object(collection, ob)) {
+ /* Remove collections from selected objects */
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
+ BKE_collection_object_remove(bmain, collection, base->object, false);
+ DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
+ ok = 1;
+ }
+ CTX_DATA_END;
+ }
+ }
+ FOREACH_COLLECTION_END;
+
+ if (!ok)
+ BKE_report(op->reports, RPT_ERROR, "Active object contains no collections");
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
}
void COLLECTION_OT_objects_remove_active(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Remove Selected From Active Collection";
- ot->description = "Remove the object from an object collection that contains the active object";
- ot->idname = "COLLECTION_OT_objects_remove_active";
-
- /* api callbacks */
- ot->exec = objects_remove_active_exec;
- ot->invoke = WM_menu_invoke;
- ot->poll = ED_operator_objectmode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "The collection to remove other selected objects from");
- RNA_def_enum_funcs(prop, collection_object_active_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Remove Selected From Active Collection";
+ ot->description = "Remove the object from an object collection that contains the active object";
+ ot->idname = "COLLECTION_OT_objects_remove_active";
+
+ /* api callbacks */
+ ot->exec = objects_remove_active_exec;
+ ot->invoke = WM_menu_invoke;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna,
+ "collection",
+ DummyRNA_NULL_items,
+ 0,
+ "Collection",
+ "The collection to remove other selected objects from");
+ RNA_def_enum_funcs(prop, collection_object_active_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
static int collection_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
- {
- BKE_object_groups_clear(bmain, scene, base->object);
- }
- CTX_DATA_END;
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
+ BKE_object_groups_clear(bmain, scene, base->object);
+ }
+ CTX_DATA_END;
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
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->idname = "COLLECTION_OT_objects_remove_all";
+ /* identifiers */
+ ot->name = "Remove From All Unlinked Collections";
+ ot->description = "Remove selected objects from all collections not used in a scene";
+ ot->idname = "COLLECTION_OT_objects_remove_all";
- /* api callbacks */
- ot->exec = collection_objects_remove_all_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = collection_objects_remove_all_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int collection_objects_remove_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- int single_collection_index = RNA_enum_get(op->ptr, "collection");
- Collection *single_collection = collection_object_active_find_index(bmain, scene, ob, single_collection_index);
- bool updated = false;
-
- if (ob == NULL)
- return OPERATOR_CANCELLED;
-
- FOREACH_COLLECTION_BEGIN(bmain, scene, Collection *, collection)
- {
- if (single_collection && collection != single_collection)
- continue;
- if (!BKE_collection_has_object(collection, ob))
- continue;
-
- /* now remove all selected objects from the collection */
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
- {
- BKE_collection_object_remove(bmain, collection, base->object, false);
- DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
- updated = true;
- }
- CTX_DATA_END;
- }
- FOREACH_COLLECTION_END;
-
- if (!updated)
- return OPERATOR_CANCELLED;
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
+ Object *ob = ED_object_context(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ int single_collection_index = RNA_enum_get(op->ptr, "collection");
+ Collection *single_collection = collection_object_active_find_index(
+ bmain, scene, ob, single_collection_index);
+ bool updated = false;
+
+ if (ob == NULL)
+ return OPERATOR_CANCELLED;
+
+ FOREACH_COLLECTION_BEGIN(bmain, scene, Collection *, collection)
+ {
+ if (single_collection && collection != single_collection)
+ continue;
+ if (!BKE_collection_has_object(collection, ob))
+ continue;
+
+ /* now remove all selected objects from the collection */
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
+ BKE_collection_object_remove(bmain, collection, base->object, false);
+ DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
+ updated = true;
+ }
+ CTX_DATA_END;
+ }
+ FOREACH_COLLECTION_END;
+
+ if (!updated)
+ return OPERATOR_CANCELLED;
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
}
void COLLECTION_OT_objects_remove(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Remove From Collection";
- ot->description = "Remove selected objects from a collection";
- ot->idname = "COLLECTION_OT_objects_remove";
-
- /* api callbacks */
- ot->exec = collection_objects_remove_exec;
- ot->invoke = WM_menu_invoke;
- ot->poll = ED_operator_objectmode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "The collection to remove this object from");
- RNA_def_enum_funcs(prop, collection_object_active_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Remove From Collection";
+ ot->description = "Remove selected objects from a collection";
+ ot->idname = "COLLECTION_OT_objects_remove";
+
+ /* api callbacks */
+ ot->exec = collection_objects_remove_exec;
+ ot->invoke = WM_menu_invoke;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna,
+ "collection",
+ DummyRNA_NULL_items,
+ 0,
+ "Collection",
+ "The collection to remove this object from");
+ RNA_def_enum_funcs(prop, collection_object_active_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
static int collection_create_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- char name[MAX_ID_NAME - 2]; /* id name */
+ Main *bmain = CTX_data_main(C);
+ char name[MAX_ID_NAME - 2]; /* id name */
- RNA_string_get(op->ptr, "name", name);
+ RNA_string_get(op->ptr, "name", name);
- Collection *collection = BKE_collection_add(bmain, NULL, name);
- id_fake_user_set(&collection->id);
+ Collection *collection = BKE_collection_add(bmain, NULL, name);
+ id_fake_user_set(&collection->id);
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
- {
- BKE_collection_object_add(bmain, collection, base->object);
- DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
- }
- CTX_DATA_END;
+ CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
+ BKE_collection_object_add(bmain, collection, base->object);
+ DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ CTX_DATA_END;
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void COLLECTION_OT_create(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Create New Collection";
- ot->description = "Create an object collection from selected objects";
- ot->idname = "COLLECTION_OT_create";
+ /* identifiers */
+ ot->name = "Create New Collection";
+ ot->description = "Create an object collection from selected objects";
+ ot->idname = "COLLECTION_OT_create";
- /* api callbacks */
- ot->exec = collection_create_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = collection_create_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_string(ot->srna, "name", "Collection", MAX_ID_NAME - 2, "Name", "Name of the new collection");
+ RNA_def_string(
+ ot->srna, "name", "Collection", MAX_ID_NAME - 2, "Name", "Name of the new collection");
}
/****************** properties window operators *********************/
static int collection_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_context(C);
+ Main *bmain = CTX_data_main(C);
- if (ob == NULL)
- return OPERATOR_CANCELLED;
+ if (ob == NULL)
+ return OPERATOR_CANCELLED;
- Collection *collection = BKE_collection_add(bmain, NULL, "Collection");
- id_fake_user_set(&collection->id);
- BKE_collection_object_add(bmain, collection, ob);
+ Collection *collection = BKE_collection_add(bmain, NULL, "Collection");
+ id_fake_user_set(&collection->id);
+ BKE_collection_object_add(bmain, collection, ob);
- DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_collection_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add to Collection";
- ot->idname = "OBJECT_OT_collection_add";
- ot->description = "Add an object to a new collection";
+ /* identifiers */
+ ot->name = "Add to Collection";
+ ot->idname = "OBJECT_OT_collection_add";
+ ot->description = "Add an object to a new collection";
- /* api callbacks */
- ot->exec = collection_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = collection_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int collection_link_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_context(C);
- Collection *collection = BLI_findlink(&bmain->collections, RNA_enum_get(op->ptr, "collection"));
-
- if (ELEM(NULL, ob, collection))
- return OPERATOR_CANCELLED;
-
- /* Early return check, if the object is already in collection
- * we could skip all the dependency check and just consider
- * operator is finished.
- */
- if (BKE_collection_has_object(collection, ob)) {
- return OPERATOR_FINISHED;
- }
-
- /* Adding object to collection which is used as duplicollection for self is bad idea.
- *
- * 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)) {
- BKE_report(op->reports, RPT_ERROR, "Could not add the collection because of dependency cycle detected");
- return OPERATOR_CANCELLED;
- }
-
- BKE_collection_object_add(bmain, collection, ob);
-
- DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_context(C);
+ Collection *collection = BLI_findlink(&bmain->collections, RNA_enum_get(op->ptr, "collection"));
+
+ if (ELEM(NULL, ob, collection))
+ return OPERATOR_CANCELLED;
+
+ /* Early return check, if the object is already in collection
+ * we could skip all the dependency check and just consider
+ * operator is finished.
+ */
+ if (BKE_collection_has_object(collection, ob)) {
+ return OPERATOR_FINISHED;
+ }
+
+ /* Adding object to collection which is used as duplicollection for self is bad idea.
+ *
+ * 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)) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Could not add the collection because of dependency cycle detected");
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_collection_object_add(bmain, collection, ob);
+
+ DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_collection_link(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Link to Collection";
- ot->idname = "OBJECT_OT_collection_link";
- ot->description = "Add an object to an existing collection";
-
- /* api callbacks */
- ot->exec = collection_link_exec;
- ot->invoke = WM_enum_search_invoke;
- ot->poll = ED_operator_objectmode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "");
- RNA_def_enum_funcs(prop, RNA_collection_local_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Link to Collection";
+ ot->idname = "OBJECT_OT_collection_link";
+ ot->description = "Add an object to an existing collection";
+
+ /* api callbacks */
+ ot->exec = collection_link_exec;
+ ot->invoke = WM_enum_search_invoke;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "");
+ RNA_def_enum_funcs(prop, RNA_collection_local_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
static int collection_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_context(C);
- Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_context(C);
+ Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
- if (!ob || !collection)
- return OPERATOR_CANCELLED;
+ if (!ob || !collection)
+ return OPERATOR_CANCELLED;
- BKE_collection_object_remove(bmain, collection, ob, false);
+ BKE_collection_object_remove(bmain, collection, ob, false);
- DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_collection_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Collection";
- ot->idname = "OBJECT_OT_collection_remove";
- ot->description = "Remove the active object from this collection";
+ /* identifiers */
+ ot->name = "Remove Collection";
+ ot->idname = "OBJECT_OT_collection_remove";
+ ot->description = "Remove the active object from this collection";
- /* api callbacks */
- ot->exec = collection_remove_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = collection_remove_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
static int collection_unlink_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
+ Main *bmain = CTX_data_main(C);
+ Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
- if (!collection)
- return OPERATOR_CANCELLED;
+ if (!collection)
+ return OPERATOR_CANCELLED;
- BKE_id_delete(bmain, collection);
+ BKE_id_delete(bmain, collection);
- DEG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_collection_unlink(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unlink Collection";
- ot->idname = "OBJECT_OT_collection_unlink";
- ot->description = "Unlink the collection from all objects";
+ /* identifiers */
+ ot->name = "Unlink Collection";
+ ot->idname = "OBJECT_OT_collection_unlink";
+ ot->description = "Unlink the collection from all objects";
- /* api callbacks */
- ot->exec = collection_unlink_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = collection_unlink_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* Select objects in the same collection as the active */
static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
-
- if (!collection)
- return OPERATOR_CANCELLED;
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
- if (BKE_collection_has_object_recursive(collection, base->object)) {
- ED_object_base_select(base, BA_SELECT);
- }
- }
- }
- CTX_DATA_END;
-
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
+
+ if (!collection)
+ return OPERATOR_CANCELLED;
+
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ if (BKE_collection_has_object_recursive(collection, base->object)) {
+ ED_object_base_select(base, BA_SELECT);
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_collection_objects_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Objects in Collection";
- ot->idname = "OBJECT_OT_collection_objects_select";
- ot->description = "Select all objects in collection";
+ /* identifiers */
+ ot->name = "Select Objects in Collection";
+ ot->idname = "OBJECT_OT_collection_objects_select";
+ ot->description = "Select all objects in collection";
- /* api callbacks */
- ot->exec = select_grouped_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = select_grouped_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 988d9373766..c571fc6821e 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <stdio.h>
#include <string.h>
@@ -56,7 +55,7 @@
#include "DEG_depsgraph_build.h"
#ifdef WITH_PYTHON
-#include "BPY_extern.h"
+# include "BPY_extern.h"
#endif
#include "WM_api.h"
@@ -80,63 +79,63 @@
/* if object in posemode, active bone constraints, else object constraints */
ListBase *get_active_constraints(Object *ob)
{
- if (ob == NULL)
- return NULL;
+ if (ob == NULL)
+ return NULL;
- if (ob->mode & OB_MODE_POSE) {
- bPoseChannel *pchan;
+ if (ob->mode & OB_MODE_POSE) {
+ bPoseChannel *pchan;
- pchan = BKE_pose_channel_active(ob);
- if (pchan)
- return &pchan->constraints;
- }
- else
- return &ob->constraints;
+ pchan = BKE_pose_channel_active(ob);
+ if (pchan)
+ return &pchan->constraints;
+ }
+ else
+ return &ob->constraints;
- return NULL;
+ return NULL;
}
/* Find the list that a given constraint belongs to,
* and/or also get the posechannel this is from (if applicable) */
ListBase *get_constraint_lb(Object *ob, bConstraint *con, bPoseChannel **r_pchan)
{
- if (r_pchan)
- *r_pchan = NULL;
+ if (r_pchan)
+ *r_pchan = NULL;
- if (ELEM(NULL, ob, con))
- return NULL;
+ if (ELEM(NULL, ob, con))
+ return NULL;
- /* try object constraints first */
- if ((BLI_findindex(&ob->constraints, con) != -1)) {
- return &ob->constraints;
- }
+ /* try object constraints first */
+ if ((BLI_findindex(&ob->constraints, con) != -1)) {
+ return &ob->constraints;
+ }
- /* if armature, try pose bones too */
- if (ob->pose) {
- bPoseChannel *pchan;
+ /* if armature, try pose bones too */
+ if (ob->pose) {
+ bPoseChannel *pchan;
- /* try each bone in order
- * NOTE: it's not possible to directly look up the active bone yet, so this will have to do
- */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if ((BLI_findindex(&pchan->constraints, con) != -1)) {
+ /* try each bone in order
+ * NOTE: it's not possible to directly look up the active bone yet, so this will have to do
+ */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if ((BLI_findindex(&pchan->constraints, con) != -1)) {
- if (r_pchan)
- *r_pchan = pchan;
+ if (r_pchan)
+ *r_pchan = pchan;
- return &pchan->constraints;
- }
- }
- }
+ return &pchan->constraints;
+ }
+ }
+ }
- /* done */
- return NULL;
+ /* done */
+ return NULL;
}
/* single constraint */
bConstraint *get_active_constraint(Object *ob)
{
- return BKE_constraints_active_get(get_active_constraints(ob));
+ return BKE_constraints_active_get(get_active_constraints(ob));
}
/* -------------- Constraint Management (Add New, Remove, Rename) -------------------- */
@@ -146,367 +145,377 @@ bConstraint *get_active_constraint(Object *ob)
/* this callback sets the text-file to be used for selected menu item */
static void validate_pyconstraint_cb(Main *bmain, void *arg1, void *arg2)
{
- bPythonConstraint *data = arg1;
- Text *text = NULL;
- int index = *((int *)arg2);
- int i;
+ bPythonConstraint *data = arg1;
+ Text *text = NULL;
+ int index = *((int *)arg2);
+ int i;
- /* exception for no script */
- if (index) {
- /* innovative use of a for...loop to search */
- for (text = bmain->texts.first, i = 1; text && index != i; i++, text = text->id.next) ;
- }
- data->text = text;
+ /* exception for no script */
+ if (index) {
+ /* innovative use of a for...loop to search */
+ for (text = bmain->texts.first, i = 1; text && index != i; i++, text = text->id.next)
+ ;
+ }
+ data->text = text;
}
/* this returns a string for the list of usable pyconstraint script names */
static char *buildmenu_pyconstraints(Main *bmain, Text *con_text, int *pyconindex)
{
- DynStr *pupds = BLI_dynstr_new();
- Text *text;
- char *str;
- char buf[64];
- int i;
+ DynStr *pupds = BLI_dynstr_new();
+ Text *text;
+ char *str;
+ char buf[64];
+ int i;
- /* add title first */
- sprintf(buf, "Scripts: %%t|[None]%%x0|");
- BLI_dynstr_append(pupds, buf);
+ /* add title first */
+ sprintf(buf, "Scripts: %%t|[None]%%x0|");
+ BLI_dynstr_append(pupds, buf);
- /* init active-index first */
- if (con_text == NULL)
- *pyconindex = 0;
+ /* init active-index first */
+ if (con_text == NULL)
+ *pyconindex = 0;
- /* loop through markers, adding them */
- for (text = bmain->texts.first, i = 1; text; i++, text = text->id.next) {
- /* this is important to ensure that right script is shown as active */
- if (text == con_text) *pyconindex = i;
+ /* loop through markers, adding them */
+ for (text = bmain->texts.first, i = 1; text; i++, text = text->id.next) {
+ /* this is important to ensure that right script is shown as active */
+ if (text == con_text)
+ *pyconindex = i;
- /* only include valid pyconstraint scripts */
- if (BPY_is_pyconstraint(text)) {
- BLI_dynstr_append(pupds, text->id.name + 2);
+ /* only include valid pyconstraint scripts */
+ if (BPY_is_pyconstraint(text)) {
+ BLI_dynstr_append(pupds, text->id.name + 2);
- sprintf(buf, "%%x%d", i);
- BLI_dynstr_append(pupds, buf);
+ sprintf(buf, "%%x%d", i);
+ BLI_dynstr_append(pupds, buf);
- if (text->id.next)
- BLI_dynstr_append(pupds, "|");
- }
- }
+ if (text->id.next)
+ BLI_dynstr_append(pupds, "|");
+ }
+ }
- /* convert to normal MEM_malloc'd string */
- str = BLI_dynstr_get_cstring(pupds);
- BLI_dynstr_free(pupds);
+ /* convert to normal MEM_malloc'd string */
+ str = BLI_dynstr_get_cstring(pupds);
+ BLI_dynstr_free(pupds);
- return str;
+ return str;
}
#endif /* WITH_PYTHON */
-#if 0 // UNUSED, until pyconstraints are added back.
+#if 0 // UNUSED, until pyconstraints are added back.
/* this callback gets called when the 'refresh' button of a pyconstraint gets pressed */
static void update_pyconstraint_cb(void *arg1, void *arg2)
{
-#ifndef WITH_PYTHON
- (void)arg1; /* unused */
- (void)arg2; /* unused */
-#else
- Object *owner = (Object *)arg1;
- bConstraint *con = (bConstraint *)arg2;
- if (owner && con)
- BPY_pyconstraint_update(owner, con);
-#endif
+# ifndef WITH_PYTHON
+ (void)arg1; /* unused */
+ (void)arg2; /* unused */
+# else
+ Object *owner = (Object *)arg1;
+ bConstraint *con = (bConstraint *)arg2;
+ if (owner && con)
+ BPY_pyconstraint_update(owner, con);
+# endif
}
-#endif // UNUSED
+#endif // UNUSED
/* helper function for add_constriant - sets the last target for the active constraint */
-static void set_constraint_nth_target(bConstraint *con, Object *target, const char subtarget[], int index)
-{
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
- int num_targets, i;
-
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
- num_targets = BLI_listbase_count(&targets);
-
- if (index < 0) {
- if (abs(index) < num_targets)
- index = num_targets - abs(index);
- else
- index = num_targets - 1;
- }
- else if (index >= num_targets) {
- index = num_targets - 1;
- }
-
- for (ct = targets.first, i = 0; ct; ct = ct->next, i++) {
- if (i == index) {
- ct->tar = target;
- BLI_strncpy(ct->subtarget, subtarget, sizeof(ct->subtarget));
- break;
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 0);
- }
+static void set_constraint_nth_target(bConstraint *con,
+ Object *target,
+ const char subtarget[],
+ int index)
+{
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+ int num_targets, i;
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+ num_targets = BLI_listbase_count(&targets);
+
+ if (index < 0) {
+ if (abs(index) < num_targets)
+ index = num_targets - abs(index);
+ else
+ index = num_targets - 1;
+ }
+ else if (index >= num_targets) {
+ index = num_targets - 1;
+ }
+
+ for (ct = targets.first, i = 0; ct; ct = ct->next, i++) {
+ if (i == index) {
+ ct->tar = target;
+ BLI_strncpy(ct->subtarget, subtarget, sizeof(ct->subtarget));
+ break;
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
}
/* ------------- Constraint Sanity Testing ------------------- */
-static void test_constraint(Main *bmain, Object *owner, bPoseChannel *pchan, bConstraint *con, int type)
-{
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
- bool check_targets = true;
-
- /* clear disabled-flag first */
- con->flag &= ~CONSTRAINT_DISABLE;
-
- if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
- bKinematicConstraint *data = con->data;
-
- /* bad: we need a separate set of checks here as poletarget is
- * optional... otherwise poletarget must exist too or else
- * the constraint is deemed invalid
- */
- /* default IK check ... */
- if (BKE_object_exists_check(bmain, data->tar) == 0) {
- data->tar = NULL;
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (data->tar == owner) {
- if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->subtarget)) {
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
-
- if (data->poletar) {
- if (BKE_object_exists_check(bmain, data->poletar) == 0) {
- data->poletar = NULL;
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (data->poletar == owner) {
- if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->polesubtarget)) {
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
- }
- /* ... can be overwritten here */
- BIK_test_constraint(owner, con);
- /* targets have already been checked for this */
- check_targets = false;
- }
- else if (con->type == CONSTRAINT_TYPE_PIVOT) {
- bPivotConstraint *data = con->data;
-
- /* target doesn't have to exist, but if it is non-null, it must exist! */
- if (data->tar && BKE_object_exists_check(bmain, data->tar) == 0) {
- data->tar = NULL;
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (data->tar == owner) {
- if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->subtarget)) {
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
-
- /* targets have already been checked for this */
- check_targets = false;
- }
- else if (con->type == CONSTRAINT_TYPE_ACTION) {
- bActionConstraint *data = con->data;
-
- /* validate action */
- if (data->act == NULL) {
- /* must have action */
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (data->act->idroot != ID_OB) {
- /* only object-rooted actions can be used */
- data->act = NULL;
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
- else if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) {
- bFollowPathConstraint *data = con->data;
-
- /* don't allow track/up axes to be the same */
- if (data->upflag == data->trackflag)
- con->flag |= CONSTRAINT_DISABLE;
- if (data->upflag + 3 == data->trackflag)
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (con->type == CONSTRAINT_TYPE_TRACKTO) {
- bTrackToConstraint *data = con->data;
-
- /* don't allow track/up axes to be the same */
- if (data->reserved2 == data->reserved1)
- con->flag |= CONSTRAINT_DISABLE;
- if (data->reserved2 + 3 == data->reserved1)
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (con->type == CONSTRAINT_TYPE_LOCKTRACK) {
- bLockTrackConstraint *data = con->data;
-
- if (data->lockflag == data->trackflag)
- con->flag |= CONSTRAINT_DISABLE;
- if (data->lockflag + 3 == data->trackflag)
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (con->type == CONSTRAINT_TYPE_SPLINEIK) {
- bSplineIKConstraint *data = con->data;
-
- /* if the number of points does not match the amount required by the chain length,
- * free the points array and request a rebind...
- */
- if ((data->points == NULL) || (data->numpoints != data->chainlen + 1)) {
- /* free the points array */
- if (data->points) {
- MEM_freeN(data->points);
- data->points = NULL;
- }
-
- /* clear the bound flag, forcing a rebind next time this is evaluated */
- data->flag &= ~CONSTRAINT_SPLINEIK_BOUND;
- }
- }
- else if (con->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
- bFollowTrackConstraint *data = con->data;
-
- if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0) {
- if (data->clip != NULL && data->track[0]) {
- MovieTracking *tracking = &data->clip->tracking;
- MovieTrackingObject *tracking_object;
-
- if (data->object[0])
- tracking_object = BKE_tracking_object_get_named(tracking, data->object);
- else
- tracking_object = BKE_tracking_object_get_camera(tracking);
-
- if (!tracking_object) {
- con->flag |= CONSTRAINT_DISABLE;
- }
- else {
- if (!BKE_tracking_track_get_named(tracking, tracking_object, data->track))
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
- else {
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
- }
- else if (con->type == CONSTRAINT_TYPE_CAMERASOLVER) {
- bCameraSolverConstraint *data = con->data;
-
- if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL))
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
- bObjectSolverConstraint *data = con->data;
-
- if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL))
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (con->type == CONSTRAINT_TYPE_TRANSFORM_CACHE) {
- bTransformCacheConstraint *data = con->data;
-
- if ((data->cache_file == NULL) || (data->object_path[0] == '\0')) {
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
-
- /* Check targets for constraints */
- if (check_targets && cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- /* constraints with empty target list that actually require targets */
- if (!targets.first && ELEM(con->type, CONSTRAINT_TYPE_ARMATURE)) {
- con->flag |= CONSTRAINT_DISABLE;
- }
-
- /* disable and clear constraints targets that are incorrect */
- for (ct = targets.first; ct; ct = ct->next) {
- /* general validity checks (for those constraints that need this) */
- if (BKE_object_exists_check(bmain, ct->tar) == 0) {
- /* object doesn't exist, but constraint requires target */
- ct->tar = NULL;
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (ct->tar == owner) {
- if (type == CONSTRAINT_OBTYPE_BONE) {
- if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), ct->subtarget)) {
- /* bone must exist in armature... */
- /* TODO: clear subtarget? */
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (STREQ(pchan->name, ct->subtarget)) {
- /* cannot target self */
- ct->subtarget[0] = '\0';
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
- else {
- /* cannot use self as target */
- ct->tar = NULL;
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
-
- /* target checks for specific constraints */
- if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) {
- if (ct->tar) {
- if (ct->tar->type != OB_CURVE) {
- ct->tar = NULL;
- con->flag |= CONSTRAINT_DISABLE;
- }
- else {
- Curve *cu = ct->tar->data;
-
- /* auto-set 'Path' setting on curve so this works */
- cu->flag |= CU_PATH;
- }
- }
- }
- else if (con->type == CONSTRAINT_TYPE_ARMATURE) {
- if (ct->tar) {
- if (ct->tar->type != OB_ARMATURE) {
- ct->tar = NULL;
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (!BKE_armature_find_bone_name(BKE_armature_from_object(ct->tar), ct->subtarget)) {
- /* bone must exist in armature... */
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
- }
- }
-
- /* free any temporary targets */
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 0);
- }
+static void test_constraint(
+ Main *bmain, Object *owner, bPoseChannel *pchan, bConstraint *con, int type)
+{
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+ bool check_targets = true;
+
+ /* clear disabled-flag first */
+ con->flag &= ~CONSTRAINT_DISABLE;
+
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
+ bKinematicConstraint *data = con->data;
+
+ /* bad: we need a separate set of checks here as poletarget is
+ * optional... otherwise poletarget must exist too or else
+ * the constraint is deemed invalid
+ */
+ /* default IK check ... */
+ if (BKE_object_exists_check(bmain, data->tar) == 0) {
+ data->tar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (data->tar == owner) {
+ if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->subtarget)) {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+
+ if (data->poletar) {
+ if (BKE_object_exists_check(bmain, data->poletar) == 0) {
+ data->poletar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (data->poletar == owner) {
+ if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->polesubtarget)) {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+ }
+ /* ... can be overwritten here */
+ BIK_test_constraint(owner, con);
+ /* targets have already been checked for this */
+ check_targets = false;
+ }
+ else if (con->type == CONSTRAINT_TYPE_PIVOT) {
+ bPivotConstraint *data = con->data;
+
+ /* target doesn't have to exist, but if it is non-null, it must exist! */
+ if (data->tar && BKE_object_exists_check(bmain, data->tar) == 0) {
+ data->tar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (data->tar == owner) {
+ if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->subtarget)) {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+
+ /* targets have already been checked for this */
+ check_targets = false;
+ }
+ else if (con->type == CONSTRAINT_TYPE_ACTION) {
+ bActionConstraint *data = con->data;
+
+ /* validate action */
+ if (data->act == NULL) {
+ /* must have action */
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (data->act->idroot != ID_OB) {
+ /* only object-rooted actions can be used */
+ data->act = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+ else if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) {
+ bFollowPathConstraint *data = con->data;
+
+ /* don't allow track/up axes to be the same */
+ if (data->upflag == data->trackflag)
+ con->flag |= CONSTRAINT_DISABLE;
+ if (data->upflag + 3 == data->trackflag)
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (con->type == CONSTRAINT_TYPE_TRACKTO) {
+ bTrackToConstraint *data = con->data;
+
+ /* don't allow track/up axes to be the same */
+ if (data->reserved2 == data->reserved1)
+ con->flag |= CONSTRAINT_DISABLE;
+ if (data->reserved2 + 3 == data->reserved1)
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (con->type == CONSTRAINT_TYPE_LOCKTRACK) {
+ bLockTrackConstraint *data = con->data;
+
+ if (data->lockflag == data->trackflag)
+ con->flag |= CONSTRAINT_DISABLE;
+ if (data->lockflag + 3 == data->trackflag)
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (con->type == CONSTRAINT_TYPE_SPLINEIK) {
+ bSplineIKConstraint *data = con->data;
+
+ /* if the number of points does not match the amount required by the chain length,
+ * free the points array and request a rebind...
+ */
+ if ((data->points == NULL) || (data->numpoints != data->chainlen + 1)) {
+ /* free the points array */
+ if (data->points) {
+ MEM_freeN(data->points);
+ data->points = NULL;
+ }
+
+ /* clear the bound flag, forcing a rebind next time this is evaluated */
+ data->flag &= ~CONSTRAINT_SPLINEIK_BOUND;
+ }
+ }
+ else if (con->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
+ bFollowTrackConstraint *data = con->data;
+
+ if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0) {
+ if (data->clip != NULL && data->track[0]) {
+ MovieTracking *tracking = &data->clip->tracking;
+ MovieTrackingObject *tracking_object;
+
+ if (data->object[0])
+ tracking_object = BKE_tracking_object_get_named(tracking, data->object);
+ else
+ tracking_object = BKE_tracking_object_get_camera(tracking);
+
+ if (!tracking_object) {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else {
+ if (!BKE_tracking_track_get_named(tracking, tracking_object, data->track))
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+ else {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+ }
+ else if (con->type == CONSTRAINT_TYPE_CAMERASOLVER) {
+ bCameraSolverConstraint *data = con->data;
+
+ if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL))
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
+ bObjectSolverConstraint *data = con->data;
+
+ if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL))
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (con->type == CONSTRAINT_TYPE_TRANSFORM_CACHE) {
+ bTransformCacheConstraint *data = con->data;
+
+ if ((data->cache_file == NULL) || (data->object_path[0] == '\0')) {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+
+ /* Check targets for constraints */
+ if (check_targets && cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ /* constraints with empty target list that actually require targets */
+ if (!targets.first && ELEM(con->type, CONSTRAINT_TYPE_ARMATURE)) {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+
+ /* disable and clear constraints targets that are incorrect */
+ for (ct = targets.first; ct; ct = ct->next) {
+ /* general validity checks (for those constraints that need this) */
+ if (BKE_object_exists_check(bmain, ct->tar) == 0) {
+ /* object doesn't exist, but constraint requires target */
+ ct->tar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (ct->tar == owner) {
+ if (type == CONSTRAINT_OBTYPE_BONE) {
+ if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), ct->subtarget)) {
+ /* bone must exist in armature... */
+ /* TODO: clear subtarget? */
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (STREQ(pchan->name, ct->subtarget)) {
+ /* cannot target self */
+ ct->subtarget[0] = '\0';
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+ else {
+ /* cannot use self as target */
+ ct->tar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+
+ /* target checks for specific constraints */
+ if (ELEM(con->type,
+ CONSTRAINT_TYPE_FOLLOWPATH,
+ CONSTRAINT_TYPE_CLAMPTO,
+ CONSTRAINT_TYPE_SPLINEIK)) {
+ if (ct->tar) {
+ if (ct->tar->type != OB_CURVE) {
+ ct->tar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else {
+ Curve *cu = ct->tar->data;
+
+ /* auto-set 'Path' setting on curve so this works */
+ cu->flag |= CU_PATH;
+ }
+ }
+ }
+ else if (con->type == CONSTRAINT_TYPE_ARMATURE) {
+ if (ct->tar) {
+ if (ct->tar->type != OB_ARMATURE) {
+ ct->tar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (!BKE_armature_find_bone_name(BKE_armature_from_object(ct->tar),
+ ct->subtarget)) {
+ /* bone must exist in armature... */
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+ }
+ }
+
+ /* free any temporary targets */
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
}
static int constraint_type_get(Object *owner, bPoseChannel *pchan)
{
- int type;
- /* Check parents */
- if (pchan) {
- switch (owner->type) {
- case OB_ARMATURE:
- type = CONSTRAINT_OBTYPE_BONE;
- break;
- default:
- type = CONSTRAINT_OBTYPE_OBJECT;
- break;
- }
- }
- else
- type = CONSTRAINT_OBTYPE_OBJECT;
- return type;
+ int type;
+ /* Check parents */
+ if (pchan) {
+ switch (owner->type) {
+ case OB_ARMATURE:
+ type = CONSTRAINT_OBTYPE_BONE;
+ break;
+ default:
+ type = CONSTRAINT_OBTYPE_OBJECT;
+ break;
+ }
+ }
+ else
+ type = CONSTRAINT_OBTYPE_OBJECT;
+ return type;
}
/* checks validity of object pointers, and NULLs,
@@ -514,185 +523,192 @@ static int constraint_type_get(Object *owner, bPoseChannel *pchan)
*/
static void test_constraints(Main *bmain, Object *owner, bPoseChannel *pchan)
{
- bConstraint *curcon;
- ListBase *conlist = NULL;
- int type;
+ bConstraint *curcon;
+ ListBase *conlist = NULL;
+ int type;
- if (owner == NULL) return;
+ if (owner == NULL)
+ return;
- type = constraint_type_get(owner, pchan);
+ type = constraint_type_get(owner, pchan);
- /* Get the constraint list for this object */
- switch (type) {
- case CONSTRAINT_OBTYPE_OBJECT:
- conlist = &owner->constraints;
- break;
- case CONSTRAINT_OBTYPE_BONE:
- conlist = &pchan->constraints;
- break;
- }
+ /* Get the constraint list for this object */
+ switch (type) {
+ case CONSTRAINT_OBTYPE_OBJECT:
+ conlist = &owner->constraints;
+ break;
+ case CONSTRAINT_OBTYPE_BONE:
+ conlist = &pchan->constraints;
+ break;
+ }
- /* Check all constraints - is constraint valid? */
- if (conlist) {
- for (curcon = conlist->first; curcon; curcon = curcon->next) {
- test_constraint(bmain, owner, pchan, curcon, type);
- }
- }
+ /* Check all constraints - is constraint valid? */
+ if (conlist) {
+ for (curcon = conlist->first; curcon; curcon = curcon->next) {
+ test_constraint(bmain, owner, pchan, curcon, type);
+ }
+ }
}
void object_test_constraints(Main *bmain, Object *owner)
{
- if (owner->constraints.first)
- test_constraints(bmain, owner, NULL);
+ if (owner->constraints.first)
+ test_constraints(bmain, owner, NULL);
- if (owner->type == OB_ARMATURE && owner->pose) {
- bPoseChannel *pchan;
+ if (owner->type == OB_ARMATURE && owner->pose) {
+ bPoseChannel *pchan;
- for (pchan = owner->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->constraints.first)
- test_constraints(bmain, owner, pchan);
- }
- }
+ for (pchan = owner->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->constraints.first)
+ test_constraints(bmain, owner, pchan);
+ }
+ }
}
static void object_test_constraint(Main *bmain, Object *owner, bConstraint *con)
{
- if (owner->type == OB_ARMATURE && owner->pose) {
- if (BLI_findindex(&owner->constraints, con) != -1) {
- test_constraint(bmain, owner, NULL, con, CONSTRAINT_OBTYPE_OBJECT);
- }
- else {
- bPoseChannel *pchan;
- for (pchan = owner->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (BLI_findindex(&pchan->constraints, con) != -1) {
- test_constraint(bmain, owner, pchan, con, CONSTRAINT_OBTYPE_BONE);
- break;
- }
- }
- }
- }
- else {
- test_constraint(bmain, owner, NULL, con, CONSTRAINT_OBTYPE_OBJECT);
- }
+ if (owner->type == OB_ARMATURE && owner->pose) {
+ if (BLI_findindex(&owner->constraints, con) != -1) {
+ test_constraint(bmain, owner, NULL, con, CONSTRAINT_OBTYPE_OBJECT);
+ }
+ else {
+ bPoseChannel *pchan;
+ for (pchan = owner->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (BLI_findindex(&pchan->constraints, con) != -1) {
+ test_constraint(bmain, owner, pchan, con, CONSTRAINT_OBTYPE_BONE);
+ break;
+ }
+ }
+ }
+ }
+ else {
+ test_constraint(bmain, owner, NULL, con, CONSTRAINT_OBTYPE_OBJECT);
+ }
}
/************************ generic functions for operators using constraint names and data context *********************/
-#define EDIT_CONSTRAINT_OWNER_OBJECT 0
-#define EDIT_CONSTRAINT_OWNER_BONE 1
+#define EDIT_CONSTRAINT_OWNER_OBJECT 0
+#define EDIT_CONSTRAINT_OWNER_BONE 1
static const EnumPropertyItem constraint_owner_items[] = {
- {EDIT_CONSTRAINT_OWNER_OBJECT, "OBJECT", 0, "Object", "Edit a constraint on the active object"},
- {EDIT_CONSTRAINT_OWNER_BONE, "BONE", 0, "Bone", "Edit a constraint on the active bone"},
- {0, NULL, 0, NULL, NULL},
+ {EDIT_CONSTRAINT_OWNER_OBJECT,
+ "OBJECT",
+ 0,
+ "Object",
+ "Edit a constraint on the active object"},
+ {EDIT_CONSTRAINT_OWNER_BONE, "BONE", 0, "Bone", "Edit a constraint on the active bone"},
+ {0, NULL, 0, NULL, NULL},
};
-
static bool edit_constraint_poll_generic(bContext *C, StructRNA *rna_type)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", rna_type);
- Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", rna_type);
+ Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
- if (!ptr.data) {
- CTX_wm_operator_poll_msg_set(C, "Context missing 'constraint'");
- return 0;
- }
+ if (!ptr.data) {
+ CTX_wm_operator_poll_msg_set(C, "Context missing 'constraint'");
+ return 0;
+ }
- if (!ob) {
- CTX_wm_operator_poll_msg_set(C, "Context missing active object");
- return 0;
- }
+ if (!ob) {
+ CTX_wm_operator_poll_msg_set(C, "Context missing active object");
+ return 0;
+ }
- if (ID_IS_LINKED(ob) || (ptr.id.data && ID_IS_LINKED(ptr.id.data))) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit library data");
- return 0;
- }
+ if (ID_IS_LINKED(ob) || (ptr.id.data && ID_IS_LINKED(ptr.id.data))) {
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit library data");
+ return 0;
+ }
- if (ID_IS_STATIC_OVERRIDE(ob)) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit constraints coming from static override");
- return (((bConstraint *)ptr.data)->flag & CONSTRAINT_STATICOVERRIDE_LOCAL) != 0;
- }
+ if (ID_IS_STATIC_OVERRIDE(ob)) {
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit constraints coming from static override");
+ return (((bConstraint *)ptr.data)->flag & CONSTRAINT_STATICOVERRIDE_LOCAL) != 0;
+ }
- return 1;
+ return 1;
}
static bool edit_constraint_poll(bContext *C)
{
- return edit_constraint_poll_generic(C, &RNA_Constraint);
+ return edit_constraint_poll_generic(C, &RNA_Constraint);
}
static void edit_constraint_properties(wmOperatorType *ot)
{
- PropertyRNA *prop;
- prop = RNA_def_string(ot->srna, "constraint", NULL, MAX_NAME, "Constraint", "Name of the constraint to edit");
- RNA_def_property_flag(prop, PROP_HIDDEN);
- prop = RNA_def_enum(ot->srna, "owner", constraint_owner_items, 0, "Owner", "The owner of this constraint");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop;
+ prop = RNA_def_string(
+ ot->srna, "constraint", NULL, MAX_NAME, "Constraint", "Name of the constraint to edit");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_enum(
+ ot->srna, "owner", constraint_owner_items, 0, "Owner", "The owner of this constraint");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
static int edit_constraint_invoke_properties(bContext *C, wmOperator *op)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
- Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
- bConstraint *con;
- ListBase *list;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
+ Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
+ bConstraint *con;
+ ListBase *list;
- if (RNA_struct_property_is_set(op->ptr, "constraint") && RNA_struct_property_is_set(op->ptr, "owner"))
- return 1;
+ if (RNA_struct_property_is_set(op->ptr, "constraint") &&
+ RNA_struct_property_is_set(op->ptr, "owner"))
+ return 1;
- if (ptr.data) {
- con = ptr.data;
- RNA_string_set(op->ptr, "constraint", con->name);
+ if (ptr.data) {
+ con = ptr.data;
+ RNA_string_set(op->ptr, "constraint", con->name);
- list = get_constraint_lb(ob, con, NULL);
+ list = get_constraint_lb(ob, con, NULL);
- if (&ob->constraints == list)
- RNA_enum_set(op->ptr, "owner", EDIT_CONSTRAINT_OWNER_OBJECT);
- else
- RNA_enum_set(op->ptr, "owner", EDIT_CONSTRAINT_OWNER_BONE);
+ if (&ob->constraints == list)
+ RNA_enum_set(op->ptr, "owner", EDIT_CONSTRAINT_OWNER_OBJECT);
+ else
+ RNA_enum_set(op->ptr, "owner", EDIT_CONSTRAINT_OWNER_BONE);
- return 1;
- }
+ return 1;
+ }
- return 0;
+ return 0;
}
static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int type)
{
- char constraint_name[MAX_NAME];
- int owner = RNA_enum_get(op->ptr, "owner");
- bConstraint *con;
- ListBase *list = NULL;
-
- RNA_string_get(op->ptr, "constraint", constraint_name);
-
- if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
- list = &ob->constraints;
- }
- else if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
- bPoseChannel *pchan = BKE_pose_channel_active(ob);
- if (pchan)
- list = &pchan->constraints;
- else {
- //if (G.debug & G_DEBUG)
- //printf("edit_constraint_property_get: No active bone for object '%s'\n", (ob) ? ob->id.name + 2 : "<None>");
- return NULL;
- }
- }
- else {
- //if (G.debug & G_DEBUG)
- //printf("edit_constraint_property_get: defaulting to getting list in the standard way\n");
- list = get_active_constraints(ob);
- }
-
- con = BKE_constraints_find_name(list, constraint_name);
- //if (G.debug & G_DEBUG)
- //printf("constraint found = %p, %s\n", (void *)con, (con) ? con->name : "<Not found>");
-
- if (con && (type != 0) && (con->type != type))
- con = NULL;
-
- return con;
+ char constraint_name[MAX_NAME];
+ int owner = RNA_enum_get(op->ptr, "owner");
+ bConstraint *con;
+ ListBase *list = NULL;
+
+ RNA_string_get(op->ptr, "constraint", constraint_name);
+
+ if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
+ list = &ob->constraints;
+ }
+ else if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
+ bPoseChannel *pchan = BKE_pose_channel_active(ob);
+ if (pchan)
+ list = &pchan->constraints;
+ else {
+ //if (G.debug & G_DEBUG)
+ //printf("edit_constraint_property_get: No active bone for object '%s'\n", (ob) ? ob->id.name + 2 : "<None>");
+ return NULL;
+ }
+ }
+ else {
+ //if (G.debug & G_DEBUG)
+ //printf("edit_constraint_property_get: defaulting to getting list in the standard way\n");
+ list = get_active_constraints(ob);
+ }
+
+ con = BKE_constraints_find_name(list, constraint_name);
+ //if (G.debug & G_DEBUG)
+ //printf("constraint found = %p, %s\n", (void *)con, (con) ? con->name : "<Not found>");
+
+ if (con && (type != 0) && (con->type != type))
+ con = NULL;
+
+ return con;
}
/* ********************** CONSTRAINT-SPECIFIC STUFF ********************* */
@@ -702,733 +718,755 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int
static int stretchto_reset_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_STRETCHTO);
- bStretchToConstraint *data = (con) ? (bStretchToConstraint *)con->data : NULL;
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_STRETCHTO);
+ bStretchToConstraint *data = (con) ? (bStretchToConstraint *)con->data : NULL;
- /* despite 3 layers of checks, we may still not be able to find a constraint */
- if (data == NULL)
- return OPERATOR_CANCELLED;
+ /* despite 3 layers of checks, we may still not be able to find a constraint */
+ if (data == NULL)
+ return OPERATOR_CANCELLED;
- /* just set original length to 0.0, which will cause a reset on next recalc */
- data->orglength = 0.0f;
- ED_object_constraint_update(bmain, ob);
+ /* just set original length to 0.0, which will cause a reset on next recalc */
+ data->orglength = 0.0f;
+ ED_object_constraint_update(bmain, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
- return OPERATOR_FINISHED;
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
+ return OPERATOR_FINISHED;
}
static int stretchto_reset_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op))
- return stretchto_reset_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_constraint_invoke_properties(C, op))
+ return stretchto_reset_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void CONSTRAINT_OT_stretchto_reset(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reset Original Length";
- ot->idname = "CONSTRAINT_OT_stretchto_reset";
- ot->description = "Reset original length of bone for Stretch To Constraint";
+ /* identifiers */
+ ot->name = "Reset Original Length";
+ ot->idname = "CONSTRAINT_OT_stretchto_reset";
+ ot->description = "Reset original length of bone for Stretch To Constraint";
- /* callbacks */
- ot->invoke = stretchto_reset_invoke;
- ot->exec = stretchto_reset_exec;
- ot->poll = edit_constraint_poll;
+ /* callbacks */
+ ot->invoke = stretchto_reset_invoke;
+ ot->exec = stretchto_reset_exec;
+ ot->poll = edit_constraint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- edit_constraint_properties(ot);
+ /* properties */
+ edit_constraint_properties(ot);
}
-
static int limitdistance_reset_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_DISTLIMIT);
- bDistLimitConstraint *data = (con) ? (bDistLimitConstraint *)con->data : NULL;
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_DISTLIMIT);
+ bDistLimitConstraint *data = (con) ? (bDistLimitConstraint *)con->data : NULL;
- /* despite 3 layers of checks, we may still not be able to find a constraint */
- if (data == NULL)
- return OPERATOR_CANCELLED;
+ /* despite 3 layers of checks, we may still not be able to find a constraint */
+ if (data == NULL)
+ return OPERATOR_CANCELLED;
- /* just set original length to 0.0, which will cause a reset on next recalc */
- data->dist = 0.0f;
- ED_object_constraint_update(bmain, ob);
+ /* just set original length to 0.0, which will cause a reset on next recalc */
+ data->dist = 0.0f;
+ ED_object_constraint_update(bmain, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
- return OPERATOR_FINISHED;
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
+ return OPERATOR_FINISHED;
}
static int limitdistance_reset_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op))
- return limitdistance_reset_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_constraint_invoke_properties(C, op))
+ return limitdistance_reset_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void CONSTRAINT_OT_limitdistance_reset(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reset Distance";
- ot->idname = "CONSTRAINT_OT_limitdistance_reset";
- ot->description = "Reset limiting distance for Limit Distance Constraint";
+ /* identifiers */
+ ot->name = "Reset Distance";
+ ot->idname = "CONSTRAINT_OT_limitdistance_reset";
+ ot->description = "Reset limiting distance for Limit Distance Constraint";
- /* callbacks */
- ot->invoke = limitdistance_reset_invoke;
- ot->exec = limitdistance_reset_exec;
- ot->poll = edit_constraint_poll;
+ /* callbacks */
+ ot->invoke = limitdistance_reset_invoke;
+ ot->exec = limitdistance_reset_exec;
+ ot->poll = edit_constraint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- edit_constraint_properties(ot);
+ /* properties */
+ edit_constraint_properties(ot);
}
/* ------------- Child-Of Constraint ------------------ */
-static void child_get_inverse_matrix(const bContext *C, Scene *scene, Object *ob, bConstraint *con, float invmat[4][4], const int owner)
-{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
-
- /* nullify inverse matrix first */
- unit_m4(invmat);
-
- if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
- bPoseChannel *pchan;
- /* try to find a pose channel - assume that this is the constraint owner */
- /* TODO: get from context instead? */
- if (ob && ob->pose && (pchan = BKE_pose_channel_active(ob))) {
- bConstraint *con_last;
- /* calculate/set inverse matrix:
- * We just calculate all transform-stack eval up to but not including this constraint.
- * This is because inverse should just inverse correct for just the constraint's influence
- * when it gets applied; that is, at the time of application, we don't know anything about
- * what follows.
- */
- float imat[4][4], tmat[4][4];
- float pmat[4][4];
-
- /* make sure we passed the correct constraint */
- BLI_assert(BLI_findindex(&pchan->constraints, con) != -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);
- copy_m4_m4(pmat, pchan->pose_mat);
-
- /* 2. knock out constraints starting from this one */
- con_last = pchan->constraints.last;
- pchan->constraints.last = con->prev;
-
- if (con->prev) {
- /* new end must not point to this one, else this chain cutting is useless */
- con->prev->next = NULL;
- }
- else {
- /* constraint was first */
- pchan->constraints.first = NULL;
- }
-
- /* 3. solve pose without disabled constraints */
- BKE_pose_where_is(depsgraph, scene, ob);
-
- /* 4. determine effect of constraint by removing the newly calculated
- * pchan->pose_mat from the original pchan->pose_mat, thus determining
- * the effect of the constraint
- */
- invert_m4_m4(imat, pchan->pose_mat);
- mul_m4_m4m4(tmat, pmat, imat);
- invert_m4_m4(invmat, tmat);
-
- /* 5. restore constraints */
- pchan->constraints.last = con_last;
-
- if (con->prev) {
- /* hook up prev to this one again */
- con->prev->next = con;
- }
- else {
- /* set as first again */
- pchan->constraints.first = con;
- }
-
- /* 6. recalculate pose with new inv-mat applied */
- BKE_pose_where_is(depsgraph, scene, ob);
- }
- }
- if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
- if (ob) {
- Object workob;
-
- /* make sure we passed the correct constraint */
- BLI_assert(BLI_findindex(&ob->constraints, con) != -1);
-
- /* 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);
- }
- }
+static void child_get_inverse_matrix(const bContext *C,
+ Scene *scene,
+ Object *ob,
+ bConstraint *con,
+ float invmat[4][4],
+ const int owner)
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
+ /* nullify inverse matrix first */
+ unit_m4(invmat);
+
+ if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
+ bPoseChannel *pchan;
+ /* try to find a pose channel - assume that this is the constraint owner */
+ /* TODO: get from context instead? */
+ if (ob && ob->pose && (pchan = BKE_pose_channel_active(ob))) {
+ bConstraint *con_last;
+ /* calculate/set inverse matrix:
+ * We just calculate all transform-stack eval up to but not including this constraint.
+ * This is because inverse should just inverse correct for just the constraint's influence
+ * when it gets applied; that is, at the time of application, we don't know anything about
+ * what follows.
+ */
+ float imat[4][4], tmat[4][4];
+ float pmat[4][4];
+
+ /* make sure we passed the correct constraint */
+ BLI_assert(BLI_findindex(&pchan->constraints, con) != -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);
+ copy_m4_m4(pmat, pchan->pose_mat);
+
+ /* 2. knock out constraints starting from this one */
+ con_last = pchan->constraints.last;
+ pchan->constraints.last = con->prev;
+
+ if (con->prev) {
+ /* new end must not point to this one, else this chain cutting is useless */
+ con->prev->next = NULL;
+ }
+ else {
+ /* constraint was first */
+ pchan->constraints.first = NULL;
+ }
+
+ /* 3. solve pose without disabled constraints */
+ BKE_pose_where_is(depsgraph, scene, ob);
+
+ /* 4. determine effect of constraint by removing the newly calculated
+ * pchan->pose_mat from the original pchan->pose_mat, thus determining
+ * the effect of the constraint
+ */
+ invert_m4_m4(imat, pchan->pose_mat);
+ mul_m4_m4m4(tmat, pmat, imat);
+ invert_m4_m4(invmat, tmat);
+
+ /* 5. restore constraints */
+ pchan->constraints.last = con_last;
+
+ if (con->prev) {
+ /* hook up prev to this one again */
+ con->prev->next = con;
+ }
+ else {
+ /* set as first again */
+ pchan->constraints.first = con;
+ }
+
+ /* 6. recalculate pose with new inv-mat applied */
+ BKE_pose_where_is(depsgraph, scene, ob);
+ }
+ }
+ if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
+ if (ob) {
+ Object workob;
+
+ /* make sure we passed the correct constraint */
+ BLI_assert(BLI_findindex(&ob->constraints, con) != -1);
+
+ /* 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);
+ }
+ }
}
/* ChildOf Constraint - set inverse callback */
static int childof_set_inverse_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF);
- bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL;
- const int owner = RNA_enum_get(op->ptr, "owner");
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_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) {
- 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");
- return OPERATOR_CANCELLED;
- }
+ /* 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");
+ return OPERATOR_CANCELLED;
+ }
- child_get_inverse_matrix(C, scene, ob, con, data->invmat, owner);
+ child_get_inverse_matrix(C, scene, ob, con, data->invmat, owner);
- ED_object_constraint_update(bmain, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ ED_object_constraint_update(bmain, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int childof_set_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op))
- return childof_set_inverse_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_constraint_invoke_properties(C, op))
+ return childof_set_inverse_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void CONSTRAINT_OT_childof_set_inverse(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Inverse";
- ot->idname = "CONSTRAINT_OT_childof_set_inverse";
- ot->description = "Set inverse correction for ChildOf constraint";
+ /* identifiers */
+ ot->name = "Set Inverse";
+ ot->idname = "CONSTRAINT_OT_childof_set_inverse";
+ ot->description = "Set inverse correction for ChildOf constraint";
- /* callbacks */
- ot->invoke = childof_set_inverse_invoke;
- ot->exec = childof_set_inverse_exec;
- ot->poll = edit_constraint_poll;
+ /* callbacks */
+ ot->invoke = childof_set_inverse_invoke;
+ ot->exec = childof_set_inverse_exec;
+ ot->poll = edit_constraint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- edit_constraint_properties(ot);
+ /* properties */
+ edit_constraint_properties(ot);
}
/* ChildOf Constraint - clear inverse callback */
static int childof_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_CHILDOF);
- bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL;
+ Main *bmain = CTX_data_main(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;
- if (data == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Child Of constraint not found");
- return OPERATOR_CANCELLED;
- }
+ if (data == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Child Of constraint not found");
+ return OPERATOR_CANCELLED;
+ }
- /* simply clear the matrix */
- unit_m4(data->invmat);
+ /* simply clear the matrix */
+ unit_m4(data->invmat);
- ED_object_constraint_update(bmain, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ ED_object_constraint_update(bmain, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int childof_clear_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op))
- return childof_clear_inverse_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_constraint_invoke_properties(C, op))
+ return childof_clear_inverse_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void CONSTRAINT_OT_childof_clear_inverse(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Inverse";
- ot->idname = "CONSTRAINT_OT_childof_clear_inverse";
- ot->description = "Clear inverse correction for ChildOf constraint";
+ /* identifiers */
+ ot->name = "Clear Inverse";
+ ot->idname = "CONSTRAINT_OT_childof_clear_inverse";
+ ot->description = "Clear inverse correction for ChildOf constraint";
- /* callbacks */
- ot->invoke = childof_clear_inverse_invoke;
- ot->exec = childof_clear_inverse_exec;
- ot->poll = edit_constraint_poll;
+ /* callbacks */
+ ot->invoke = childof_clear_inverse_invoke;
+ ot->exec = childof_clear_inverse_exec;
+ ot->poll = edit_constraint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- edit_constraint_properties(ot);
+ /* properties */
+ edit_constraint_properties(ot);
}
/* --------------- Follow Path Constraint ------------------ */
static int followpath_path_animate_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_FOLLOWPATH);
- bFollowPathConstraint *data = (con) ? (bFollowPathConstraint *)con->data : NULL;
-
- bAction *act = NULL;
- FCurve *fcu = NULL;
- int sfra = RNA_int_get(op->ptr, "frame_start");
- int len = RNA_int_get(op->ptr, "length");
- float standardRange = 1.0;
-
- /* nearly impossible sanity check */
- if (data == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Follow Path constraint not found");
- return OPERATOR_CANCELLED;
- }
-
- /* add F-Curve as appropriate */
- if (data->tar) {
- Curve *cu = (Curve *)data->tar->data;
-
- if (ELEM(NULL, cu->adt, cu->adt->action) ||
- (list_find_fcurve(&cu->adt->action->curves, "eval_time", 0) == NULL))
- {
- /* 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);
-
- /* standard vertical range - 1:1 = 100 frames */
- standardRange = 100.0f;
- }
- else {
- /* path anim exists already - abort for now as this may well be what was intended */
- BKE_report(op->reports, RPT_WARNING, "Path is already animated");
- return OPERATOR_CANCELLED;
- }
- }
- else {
- /* animate constraint's "fixed offset" */
- PointerRNA ptr;
- PropertyRNA *prop;
- char *path;
-
- /* get RNA pointer to constraint's "offset_factor" property - to build RNA path */
- RNA_pointer_create(&ob->id, &RNA_FollowPathConstraint, con, &ptr);
- prop = RNA_struct_find_property(&ptr, "offset_factor");
-
- 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);
-
- /* standard vertical range - 0.0 to 1.0 */
- standardRange = 1.0f;
-
- /* enable "Use Fixed Position" so that animating this has effect */
- data->followflag |= FOLLOWPATH_STATIC;
-
- /* path needs to be freed */
- if (path)
- MEM_freeN(path);
- }
-
- /* setup dummy 'generator' modifier here to get 1-1 correspondence still working
- * and define basic slope of this curve based on the properties
- */
- if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first) {
- FModifier *fcm = add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu);
- FMod_Generator *gen = fcm->data;
-
- /* Assume that we have the following equation:
- * y = Ax + B
- * 1 0 <-- coefficients array indices
- */
- float A = standardRange / (float)(len);
- float B = (float)(-sfra) * A;
-
- gen->coefficients[1] = A;
- gen->coefficients[0] = B;
- }
-
- /* updates... */
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
- return OPERATOR_FINISHED;
-}
-
-static int followpath_path_animate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- /* hook up invoke properties for figuring out which constraint we're dealing with */
- if (edit_constraint_invoke_properties(C, op)) {
- return followpath_path_animate_exec(C, op);
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_FOLLOWPATH);
+ bFollowPathConstraint *data = (con) ? (bFollowPathConstraint *)con->data : NULL;
+
+ bAction *act = NULL;
+ FCurve *fcu = NULL;
+ int sfra = RNA_int_get(op->ptr, "frame_start");
+ int len = RNA_int_get(op->ptr, "length");
+ float standardRange = 1.0;
+
+ /* nearly impossible sanity check */
+ if (data == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Follow Path constraint not found");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* add F-Curve as appropriate */
+ if (data->tar) {
+ Curve *cu = (Curve *)data->tar->data;
+
+ if (ELEM(NULL, cu->adt, cu->adt->action) ||
+ (list_find_fcurve(&cu->adt->action->curves, "eval_time", 0) == NULL)) {
+ /* 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);
+
+ /* standard vertical range - 1:1 = 100 frames */
+ standardRange = 100.0f;
+ }
+ else {
+ /* path anim exists already - abort for now as this may well be what was intended */
+ BKE_report(op->reports, RPT_WARNING, "Path is already animated");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ /* animate constraint's "fixed offset" */
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ char *path;
+
+ /* get RNA pointer to constraint's "offset_factor" property - to build RNA path */
+ RNA_pointer_create(&ob->id, &RNA_FollowPathConstraint, con, &ptr);
+ prop = RNA_struct_find_property(&ptr, "offset_factor");
+
+ 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);
+
+ /* standard vertical range - 0.0 to 1.0 */
+ standardRange = 1.0f;
+
+ /* enable "Use Fixed Position" so that animating this has effect */
+ data->followflag |= FOLLOWPATH_STATIC;
+
+ /* path needs to be freed */
+ if (path)
+ MEM_freeN(path);
+ }
+
+ /* setup dummy 'generator' modifier here to get 1-1 correspondence still working
+ * and define basic slope of this curve based on the properties
+ */
+ if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first) {
+ FModifier *fcm = add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu);
+ FMod_Generator *gen = fcm->data;
+
+ /* Assume that we have the following equation:
+ * y = Ax + B
+ * 1 0 <-- coefficients array indices
+ */
+ float A = standardRange / (float)(len);
+ float B = (float)(-sfra) * A;
+
+ gen->coefficients[1] = A;
+ gen->coefficients[0] = B;
+ }
+
+ /* updates... */
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ return OPERATOR_FINISHED;
+}
+
+static int followpath_path_animate_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
+{
+ /* hook up invoke properties for figuring out which constraint we're dealing with */
+ if (edit_constraint_invoke_properties(C, op)) {
+ return followpath_path_animate_exec(C, op);
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void CONSTRAINT_OT_followpath_path_animate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Auto Animate Path";
- ot->idname = "CONSTRAINT_OT_followpath_path_animate";
- ot->description = "Add default animation for path used by constraint if it isn't animated already";
-
- /* callbacks */
- ot->invoke = followpath_path_animate_invoke;
- ot->exec = followpath_path_animate_exec;
- ot->poll = edit_constraint_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- edit_constraint_properties(ot);
- RNA_def_int(ot->srna, "frame_start", 1, MINAFRAME, MAXFRAME, "Start Frame",
- "First frame of path animation", MINAFRAME, MAXFRAME);
- RNA_def_int(ot->srna, "length", 100, 0, MAXFRAME, "Length",
- "Number of frames that path animation should take", 0, MAXFRAME);
+ /* identifiers */
+ ot->name = "Auto Animate Path";
+ ot->idname = "CONSTRAINT_OT_followpath_path_animate";
+ ot->description =
+ "Add default animation for path used by constraint if it isn't animated already";
+
+ /* callbacks */
+ ot->invoke = followpath_path_animate_invoke;
+ ot->exec = followpath_path_animate_exec;
+ ot->poll = edit_constraint_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ edit_constraint_properties(ot);
+ RNA_def_int(ot->srna,
+ "frame_start",
+ 1,
+ MINAFRAME,
+ MAXFRAME,
+ "Start Frame",
+ "First frame of path animation",
+ MINAFRAME,
+ MAXFRAME);
+ RNA_def_int(ot->srna,
+ "length",
+ 100,
+ 0,
+ MAXFRAME,
+ "Length",
+ "Number of frames that path animation should take",
+ 0,
+ MAXFRAME);
}
/* ------------- Object Solver Constraint ------------------ */
static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
{
- 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");
+ 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");
- return OPERATOR_CANCELLED;
- }
+ /* 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");
+ return OPERATOR_CANCELLED;
+ }
- child_get_inverse_matrix(C, scene, ob, con, data->invmat, owner);
+ child_get_inverse_matrix(C, scene, ob, con, data->invmat, owner);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static int objectsolver_set_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int objectsolver_set_inverse_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op))
- return objectsolver_set_inverse_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_constraint_invoke_properties(C, op))
+ return objectsolver_set_inverse_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void CONSTRAINT_OT_objectsolver_set_inverse(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Inverse";
- ot->idname = "CONSTRAINT_OT_objectsolver_set_inverse";
- ot->description = "Set inverse correction for ObjectSolver constraint";
+ /* identifiers */
+ ot->name = "Set Inverse";
+ ot->idname = "CONSTRAINT_OT_objectsolver_set_inverse";
+ ot->description = "Set inverse correction for ObjectSolver constraint";
- /* callbacks */
- ot->invoke = objectsolver_set_inverse_invoke;
- ot->exec = objectsolver_set_inverse_exec;
- ot->poll = edit_constraint_poll;
+ /* callbacks */
+ ot->invoke = objectsolver_set_inverse_invoke;
+ ot->exec = objectsolver_set_inverse_exec;
+ ot->poll = edit_constraint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- edit_constraint_properties(ot);
+ /* properties */
+ edit_constraint_properties(ot);
}
static int objectsolver_clear_inverse_exec(bContext *C, wmOperator *op)
{
- 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;
+ 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;
- if (data == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Child Of constraint not found");
- return OPERATOR_CANCELLED;
- }
+ if (data == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Child Of constraint not found");
+ return OPERATOR_CANCELLED;
+ }
- /* simply clear the matrix */
- unit_m4(data->invmat);
+ /* simply clear the matrix */
+ unit_m4(data->invmat);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static int objectsolver_clear_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int objectsolver_clear_inverse_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op))
- return objectsolver_clear_inverse_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_constraint_invoke_properties(C, op))
+ return objectsolver_clear_inverse_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void CONSTRAINT_OT_objectsolver_clear_inverse(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Inverse";
- ot->idname = "CONSTRAINT_OT_objectsolver_clear_inverse";
- ot->description = "Clear inverse correction for ObjectSolver constraint";
+ /* identifiers */
+ ot->name = "Clear Inverse";
+ ot->idname = "CONSTRAINT_OT_objectsolver_clear_inverse";
+ ot->description = "Clear inverse correction for ObjectSolver constraint";
- /* callbacks */
- ot->invoke = objectsolver_clear_inverse_invoke;
- ot->exec = objectsolver_clear_inverse_exec;
- ot->poll = edit_constraint_poll;
+ /* callbacks */
+ ot->invoke = objectsolver_clear_inverse_invoke;
+ ot->exec = objectsolver_clear_inverse_exec;
+ ot->poll = edit_constraint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- edit_constraint_properties(ot);
+ /* properties */
+ edit_constraint_properties(ot);
}
/***************************** BUTTONS ****************************/
void ED_object_constraint_set_active(Object *ob, bConstraint *con)
{
- ListBase *lb = get_constraint_lb(ob, con, NULL);
+ ListBase *lb = get_constraint_lb(ob, con, NULL);
- /* lets be nice and escape if its active already */
- /* NOTE: this assumes that the stack doesn't have other active ones set... */
- if ((lb && con) && (con->flag & CONSTRAINT_ACTIVE))
- return;
+ /* lets be nice and escape if its active already */
+ /* NOTE: this assumes that the stack doesn't have other active ones set... */
+ if ((lb && con) && (con->flag & CONSTRAINT_ACTIVE))
+ return;
- BKE_constraints_active_set(lb, con);
+ BKE_constraints_active_set(lb, con);
}
void ED_object_constraint_update(Main *bmain, Object *ob)
{
- if (ob->pose) BKE_pose_update_constraint_flags(ob->pose);
+ if (ob->pose)
+ BKE_pose_update_constraint_flags(ob->pose);
- object_test_constraints(bmain, ob);
+ object_test_constraints(bmain, ob);
- if (ob->type == OB_ARMATURE)
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
- else
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ if (ob->type == OB_ARMATURE)
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
+ else
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
}
static void object_pose_tag_update(Main *bmain, Object *ob)
{
- BKE_pose_tag_recalc(bmain, ob->pose); /* Checks & sort pose channels. */
- if (ob->proxy && ob->adt) {
- /* We need to make use of ugly POSE_ANIMATION_WORKAROUND here too, else anim data are not reloaded
- * after calling `BKE_pose_rebuild()`, which causes T43872.
- * Note that this is a bit wide here, since we cannot be sure whether there are some locked proxy bones
- * or not...
- * XXX Temp hack until new depsgraph hopefully solves this. */
- DEG_id_tag_update(&ob->id, ID_RECALC_ANIMATION);
- }
+ BKE_pose_tag_recalc(bmain, ob->pose); /* Checks & sort pose channels. */
+ if (ob->proxy && ob->adt) {
+ /* We need to make use of ugly POSE_ANIMATION_WORKAROUND here too, else anim data are not reloaded
+ * after calling `BKE_pose_rebuild()`, which causes T43872.
+ * Note that this is a bit wide here, since we cannot be sure whether there are some locked proxy bones
+ * or not...
+ * XXX Temp hack until new depsgraph hopefully solves this. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_ANIMATION);
+ }
}
void ED_object_constraint_dependency_update(Main *bmain, Object *ob)
{
- ED_object_constraint_update(bmain, ob);
+ ED_object_constraint_update(bmain, ob);
- if (ob->pose) {
- object_pose_tag_update(bmain, ob);
- }
- DEG_relations_tag_update(bmain);
+ if (ob->pose) {
+ object_pose_tag_update(bmain, ob);
+ }
+ DEG_relations_tag_update(bmain);
}
void ED_object_constraint_tag_update(Main *bmain, Object *ob, bConstraint *con)
{
- if (ob->pose) {
- BKE_pose_tag_update_constraint_flags(ob->pose);
- }
+ if (ob->pose) {
+ BKE_pose_tag_update_constraint_flags(ob->pose);
+ }
- if (con) {
- object_test_constraint(bmain, ob, con);
- }
+ if (con) {
+ object_test_constraint(bmain, ob, con);
+ }
- if (ob->type == OB_ARMATURE)
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
- else
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ if (ob->type == OB_ARMATURE)
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
+ else
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- /* Do Copy-on-Write tag here too, otherwise constraint
- * influence/mute buttons in UI have no effect
- */
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ /* Do Copy-on-Write tag here too, otherwise constraint
+ * influence/mute buttons in UI have no effect
+ */
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
}
void ED_object_constraint_dependency_tag_update(Main *bmain, Object *ob, bConstraint *con)
{
- ED_object_constraint_tag_update(bmain, ob, con);
+ ED_object_constraint_tag_update(bmain, ob, con);
- if (ob->pose) {
- object_pose_tag_update(bmain, ob);
- }
- DEG_relations_tag_update(bmain);
+ if (ob->pose) {
+ object_pose_tag_update(bmain, ob);
+ }
+ DEG_relations_tag_update(bmain);
}
static bool constraint_poll(bContext *C)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
- return (ptr.id.data && ptr.data);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
+ return (ptr.id.data && ptr.data);
}
-
static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
- Object *ob = ptr.id.data;
- bConstraint *con = ptr.data;
- ListBase *lb = get_constraint_lb(ob, con, NULL);
+ Main *bmain = CTX_data_main(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
+ Object *ob = ptr.id.data;
+ bConstraint *con = ptr.data;
+ ListBase *lb = get_constraint_lb(ob, con, NULL);
- /* free the constraint */
- if (BKE_constraint_remove_ex(lb, ob, con, true)) {
- /* there's no active constraint now, so make sure this is the case */
- BKE_constraints_active_set(&ob->constraints, NULL);
- /* needed to set the flags on posebones correctly */
- ED_object_constraint_update(bmain, ob);
+ /* free the constraint */
+ if (BKE_constraint_remove_ex(lb, ob, con, true)) {
+ /* there's no active constraint now, so make sure this is the case */
+ BKE_constraints_active_set(&ob->constraints, NULL);
+ /* needed to set the flags on posebones correctly */
+ ED_object_constraint_update(bmain, ob);
- /* relations */
- DEG_relations_tag_update(CTX_data_main(C));
+ /* relations */
+ DEG_relations_tag_update(CTX_data_main(C));
- /* notifiers */
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
+ /* notifiers */
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
- return OPERATOR_FINISHED;
- }
- else {
- /* couldn't remove due to some invalid data */
- return OPERATOR_CANCELLED;
- }
+ return OPERATOR_FINISHED;
+ }
+ else {
+ /* couldn't remove due to some invalid data */
+ return OPERATOR_CANCELLED;
+ }
}
void CONSTRAINT_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Constraint";
- ot->idname = "CONSTRAINT_OT_delete";
- ot->description = "Remove constraint from constraint stack";
+ /* identifiers */
+ ot->name = "Delete Constraint";
+ ot->idname = "CONSTRAINT_OT_delete";
+ ot->description = "Remove constraint from constraint stack";
- /* callbacks */
- ot->exec = constraint_delete_exec;
- ot->poll = constraint_poll;
+ /* callbacks */
+ ot->exec = constraint_delete_exec;
+ ot->poll = constraint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
static int constraint_move_down_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- bConstraint *con = edit_constraint_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(op, ob, 0);
- if (con && con->next) {
- ListBase *conlist = get_constraint_lb(ob, con, NULL);
- bConstraint *nextCon = con->next;
+ if (con && con->next) {
+ ListBase *conlist = get_constraint_lb(ob, con, NULL);
+ bConstraint *nextCon = con->next;
- /* insert the nominated constraint after the one that used to be after it */
- BLI_remlink(conlist, con);
- BLI_insertlinkafter(conlist, nextCon, con);
+ /* insert the nominated constraint after the one that used to be after it */
+ BLI_remlink(conlist, con);
+ BLI_insertlinkafter(conlist, nextCon, con);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
static int constraint_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op))
- return constraint_move_down_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_constraint_invoke_properties(C, op))
+ return constraint_move_down_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void CONSTRAINT_OT_move_down(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move Constraint Down";
- ot->idname = "CONSTRAINT_OT_move_down";
- ot->description = "Move constraint down in constraint stack";
+ /* identifiers */
+ ot->name = "Move Constraint Down";
+ ot->idname = "CONSTRAINT_OT_move_down";
+ ot->description = "Move constraint down in constraint stack";
- /* callbacks */
- ot->invoke = constraint_move_down_invoke;
- ot->exec = constraint_move_down_exec;
- ot->poll = edit_constraint_poll;
+ /* callbacks */
+ ot->invoke = constraint_move_down_invoke;
+ ot->exec = constraint_move_down_exec;
+ ot->poll = edit_constraint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- edit_constraint_properties(ot);
+ /* properties */
+ edit_constraint_properties(ot);
}
-
static int constraint_move_up_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- bConstraint *con = edit_constraint_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(op, ob, 0);
- if (con && con->prev) {
- ListBase *conlist = get_constraint_lb(ob, con, NULL);
- bConstraint *prevCon = con->prev;
+ if (con && con->prev) {
+ ListBase *conlist = get_constraint_lb(ob, con, NULL);
+ bConstraint *prevCon = con->prev;
- /* insert the nominated constraint before the one that used to be before it */
- BLI_remlink(conlist, con);
- BLI_insertlinkbefore(conlist, prevCon, con);
+ /* insert the nominated constraint before the one that used to be before it */
+ BLI_remlink(conlist, con);
+ BLI_insertlinkbefore(conlist, prevCon, con);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
static int constraint_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op))
- return constraint_move_up_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_constraint_invoke_properties(C, op))
+ return constraint_move_up_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void CONSTRAINT_OT_move_up(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move Constraint Up";
- ot->idname = "CONSTRAINT_OT_move_up";
- ot->description = "Move constraint up in constraint stack";
+ /* identifiers */
+ ot->name = "Move Constraint Up";
+ ot->idname = "CONSTRAINT_OT_move_up";
+ ot->description = "Move constraint up in constraint stack";
- /* callbacks */
- ot->exec = constraint_move_up_exec;
- ot->invoke = constraint_move_up_invoke;
- ot->poll = edit_constraint_poll;
+ /* callbacks */
+ ot->exec = constraint_move_up_exec;
+ ot->invoke = constraint_move_up_invoke;
+ ot->poll = edit_constraint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- edit_constraint_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ edit_constraint_properties(ot);
}
/***************************** OPERATORS ****************************/
@@ -1437,433 +1475,428 @@ void CONSTRAINT_OT_move_up(wmOperatorType *ot)
static int pose_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Object *prev_ob = NULL;
+ Main *bmain = CTX_data_main(C);
+ Object *prev_ob = NULL;
- /* free constraints for all selected bones */
- CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob)
- {
- BKE_constraints_free(&pchan->constraints);
- pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_SPLINEIK | PCHAN_HAS_CONST);
+ /* free constraints for all selected bones */
+ CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob)
+ {
+ BKE_constraints_free(&pchan->constraints);
+ pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_SPLINEIK | PCHAN_HAS_CONST);
- if (prev_ob != ob) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
- prev_ob = ob;
- }
- }
- CTX_DATA_END;
+ if (prev_ob != ob) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
+ prev_ob = ob;
+ }
+ }
+ CTX_DATA_END;
- /* force depsgraph to get recalculated since relationships removed */
- DEG_relations_tag_update(bmain);
+ /* force depsgraph to get recalculated since relationships removed */
+ DEG_relations_tag_update(bmain);
- /* note, calling BIK_clear_data() isn't needed here */
+ /* note, calling BIK_clear_data() isn't needed here */
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void POSE_OT_constraints_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Pose Constraints";
- ot->idname = "POSE_OT_constraints_clear";
- ot->description = "Clear all the constraints for the selected bones";
+ /* identifiers */
+ ot->name = "Clear Pose Constraints";
+ ot->idname = "POSE_OT_constraints_clear";
+ ot->description = "Clear all the constraints for the selected bones";
- /* callbacks */
- ot->exec = pose_constraints_clear_exec;
- ot->poll = ED_operator_posemode_exclusive; // XXX - do we want to ensure there are selected bones too?
+ /* callbacks */
+ ot->exec = pose_constraints_clear_exec;
+ ot->poll =
+ ED_operator_posemode_exclusive; // XXX - do we want to ensure there are selected bones too?
}
-
static int object_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
+ Main *bmain = CTX_data_main(C);
- /* do freeing */
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- BKE_constraints_free(&ob->constraints);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
- CTX_DATA_END;
+ /* do freeing */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ BKE_constraints_free(&ob->constraints);
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+ CTX_DATA_END;
- /* force depsgraph to get recalculated since relationships removed */
- DEG_relations_tag_update(bmain);
+ /* force depsgraph to get recalculated since relationships removed */
+ DEG_relations_tag_update(bmain);
- /* do updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, NULL);
+ /* do updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_constraints_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Object Constraints";
- ot->idname = "OBJECT_OT_constraints_clear";
- ot->description = "Clear all the constraints for the active Object only";
+ /* identifiers */
+ ot->name = "Clear Object Constraints";
+ ot->idname = "OBJECT_OT_constraints_clear";
+ ot->description = "Clear all the constraints for the active Object only";
- /* callbacks */
- ot->exec = object_constraints_clear_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* callbacks */
+ ot->exec = object_constraints_clear_exec;
+ ot->poll = ED_operator_object_active_editable;
}
/************************ copy all constraints operators *********************/
static int pose_constraint_copy_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- bPoseChannel *pchan = CTX_data_active_pose_bone(C);
+ Main *bmain = CTX_data_main(C);
+ bPoseChannel *pchan = CTX_data_active_pose_bone(C);
- /* don't do anything if bone doesn't exist or doesn't have any constraints */
- if (ELEM(NULL, pchan, pchan->constraints.first)) {
- BKE_report(op->reports, RPT_ERROR, "No active bone with constraints for copying");
- return OPERATOR_CANCELLED;
- }
+ /* don't do anything if bone doesn't exist or doesn't have any constraints */
+ if (ELEM(NULL, pchan, pchan->constraints.first)) {
+ BKE_report(op->reports, RPT_ERROR, "No active bone with constraints for copying");
+ return OPERATOR_CANCELLED;
+ }
- Object *prev_ob = NULL;
+ Object *prev_ob = NULL;
- /* copy all constraints from active posebone to all selected posebones */
- CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, chan, selected_pose_bones, Object *, ob)
- {
- /* if we're not handling the object we're copying from, copy all constraints over */
- if (pchan != chan) {
- BKE_constraints_copy(&chan->constraints, &pchan->constraints, true);
- /* update flags (need to add here, not just copy) */
- chan->constflag |= pchan->constflag;
+ /* copy all constraints from active posebone to all selected posebones */
+ CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, chan, selected_pose_bones, Object *, ob)
+ {
+ /* if we're not handling the object we're copying from, copy all constraints over */
+ if (pchan != chan) {
+ BKE_constraints_copy(&chan->constraints, &pchan->constraints, true);
+ /* update flags (need to add here, not just copy) */
+ chan->constflag |= pchan->constflag;
- if (prev_ob != ob) {
- BKE_pose_tag_recalc(bmain, ob->pose);
- DEG_id_tag_update((ID *)ob, ID_RECALC_GEOMETRY);
- prev_ob = ob;
- }
- }
- }
- CTX_DATA_END;
+ if (prev_ob != ob) {
+ BKE_pose_tag_recalc(bmain, ob->pose);
+ DEG_id_tag_update((ID *)ob, ID_RECALC_GEOMETRY);
+ prev_ob = ob;
+ }
+ }
+ }
+ CTX_DATA_END;
- /* force depsgraph to get recalculated since new relationships added */
- DEG_relations_tag_update(bmain);
+ /* force depsgraph to get recalculated since new relationships added */
+ DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void POSE_OT_constraints_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Constraints to Selected Bones";
- ot->idname = "POSE_OT_constraints_copy";
- ot->description = "Copy constraints to other selected bones";
+ /* identifiers */
+ ot->name = "Copy Constraints to Selected Bones";
+ ot->idname = "POSE_OT_constraints_copy";
+ ot->description = "Copy constraints to other selected bones";
- /* api callbacks */
- ot->exec = pose_constraint_copy_exec;
- ot->poll = ED_operator_posemode_exclusive;
+ /* api callbacks */
+ ot->exec = pose_constraint_copy_exec;
+ ot->poll = ED_operator_posemode_exclusive;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int object_constraint_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Object *obact = ED_object_active_context(C);
+ Main *bmain = CTX_data_main(C);
+ Object *obact = ED_object_active_context(C);
- /* copy all constraints from active object to all selected objects */
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- /* if we're not handling the object we're copying from, copy all constraints over */
- if (obact != ob) {
- BKE_constraints_copy(&ob->constraints, &obact->constraints, true);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
- }
- }
- CTX_DATA_END;
+ /* copy all constraints from active object to all selected objects */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ /* if we're not handling the object we're copying from, copy all constraints over */
+ if (obact != ob) {
+ BKE_constraints_copy(&ob->constraints, &obact->constraints, true);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
+ }
+ }
+ CTX_DATA_END;
- /* force depsgraph to get recalculated since new relationships added */
- DEG_relations_tag_update(bmain);
+ /* force depsgraph to get recalculated since new relationships added */
+ DEG_relations_tag_update(bmain);
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_ADDED, NULL);
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_ADDED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_constraints_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Constraints to Selected Objects";
- ot->idname = "OBJECT_OT_constraints_copy";
- ot->description = "Copy constraints to other selected objects";
+ /* identifiers */
+ ot->name = "Copy Constraints to Selected Objects";
+ ot->idname = "OBJECT_OT_constraints_copy";
+ ot->description = "Copy constraints to other selected objects";
- /* api callbacks */
- ot->exec = object_constraint_copy_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->exec = object_constraint_copy_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************ add constraint operators *********************/
/* get the Object and/or PoseChannel to use as target */
-static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob, bPoseChannel **tar_pchan, bool add)
-{
- Object *obact = ED_object_active_context(C);
- bPoseChannel *pchanact = BKE_pose_channel_active(obact);
- bool only_curve = false, only_mesh = false, only_ob = false;
- bool found = false;
-
- /* clear tar_ob and tar_pchan fields before use
- * - assume for now that both always exist...
- */
- *tar_ob = NULL;
- *tar_pchan = NULL;
-
- /* check if constraint type doesn't requires a target
- * - if so, no need to get any targets
- */
- switch (con_type) {
- /* no-target constraints --------------------------- */
- /* null constraint - shouldn't even be added! */
- case CONSTRAINT_TYPE_NULL:
- /* limit constraints - no targets needed */
- case CONSTRAINT_TYPE_LOCLIMIT:
- case CONSTRAINT_TYPE_ROTLIMIT:
- case CONSTRAINT_TYPE_SIZELIMIT:
- case CONSTRAINT_TYPE_SAMEVOL:
- return false;
-
- /* restricted target-type constraints -------------- */
- /* NOTE: for these, we cannot try to add a target object if no valid ones are found,
- * since that doesn't work */
- /* curve-based constraints - set the only_curve and only_ob flags */
- case CONSTRAINT_TYPE_CLAMPTO:
- case CONSTRAINT_TYPE_FOLLOWPATH:
- case CONSTRAINT_TYPE_SPLINEIK:
- only_curve = true;
- only_ob = true;
- add = false;
- break;
-
- /* mesh only? */
- case CONSTRAINT_TYPE_SHRINKWRAP:
- only_mesh = true;
- only_ob = true;
- add = false;
- break;
- }
-
- /* if the active Object is Armature, and we can search for bones, do so... */
- if ((obact->type == OB_ARMATURE) && (only_ob == false)) {
- /* search in list of selected Pose-Channels for target */
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones_from_active_object)
- {
- /* just use the first one that we encounter, as long as it is not the active one */
- if (pchan != pchanact) {
- *tar_ob = obact;
- *tar_pchan = pchan;
- found = true;
-
- break;
- }
- }
- CTX_DATA_END;
- }
-
- /* if not yet found, try selected Objects... */
- if (found == false) {
- /* search in selected objects context */
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- /* just use the first object we encounter (that isn't the active object)
- * and which fulfills the criteria for the object-target that we've got
- */
- if (ob != obact) {
- /* for armatures in pose mode, look inside the armature for the active bone
- * so that we set up cross-armature constraints with less effort
- */
- if ((ob->type == OB_ARMATURE) && (ob->mode & OB_MODE_POSE) &&
- (!only_curve && !only_mesh))
- {
- /* just use the active bone, and assume that it is visible + usable */
- *tar_ob = ob;
- *tar_pchan = BKE_pose_channel_active(ob);
- found = true;
-
- break;
- }
- else if (((!only_curve) || (ob->type == OB_CURVE)) &&
- ((!only_mesh) || (ob->type == OB_MESH)))
- {
- /* set target */
- *tar_ob = ob;
- found = true;
-
- /* perform some special operations on the target */
- if (only_curve) {
- /* Curve-Path option must be enabled for follow-path constraints to be able to work */
- Curve *cu = (Curve *)ob->data;
- cu->flag |= CU_PATH;
- }
-
- break;
- }
- }
- }
- CTX_DATA_END;
- }
-
- /* if still not found, add a new empty to act as a target (if allowed) */
- if ((found == false) && (add)) {
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base = BASACT(view_layer);
- Object *obt;
-
- /* add new target object */
- obt = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, NULL);
-
- /* transform cent to global coords for loc */
- if (pchanact) {
- /* since by default, IK targets the tip of the last bone, use the tip of the active PoseChannel
- * if adding a target for an IK Constraint
- */
- if (con_type == CONSTRAINT_TYPE_KINEMATIC)
- mul_v3_m4v3(obt->loc, obact->obmat, pchanact->pose_tail);
- else
- mul_v3_m4v3(obt->loc, obact->obmat, pchanact->pose_head);
- }
- else {
- copy_v3_v3(obt->loc, obact->obmat[3]);
- }
-
- /* restore, BKE_object_add sets active */
- BASACT(view_layer) = base;
- base->flag |= BASE_SELECTED;
-
- /* make our new target the new object */
- *tar_ob = obt;
- found = true;
- }
-
- /* return whether there's any target */
- return found;
+static bool get_new_constraint_target(
+ bContext *C, int con_type, Object **tar_ob, bPoseChannel **tar_pchan, bool add)
+{
+ Object *obact = ED_object_active_context(C);
+ bPoseChannel *pchanact = BKE_pose_channel_active(obact);
+ bool only_curve = false, only_mesh = false, only_ob = false;
+ bool found = false;
+
+ /* clear tar_ob and tar_pchan fields before use
+ * - assume for now that both always exist...
+ */
+ *tar_ob = NULL;
+ *tar_pchan = NULL;
+
+ /* check if constraint type doesn't requires a target
+ * - if so, no need to get any targets
+ */
+ switch (con_type) {
+ /* no-target constraints --------------------------- */
+ /* null constraint - shouldn't even be added! */
+ case CONSTRAINT_TYPE_NULL:
+ /* limit constraints - no targets needed */
+ case CONSTRAINT_TYPE_LOCLIMIT:
+ case CONSTRAINT_TYPE_ROTLIMIT:
+ case CONSTRAINT_TYPE_SIZELIMIT:
+ case CONSTRAINT_TYPE_SAMEVOL:
+ return false;
+
+ /* restricted target-type constraints -------------- */
+ /* NOTE: for these, we cannot try to add a target object if no valid ones are found,
+ * since that doesn't work */
+ /* curve-based constraints - set the only_curve and only_ob flags */
+ case CONSTRAINT_TYPE_CLAMPTO:
+ case CONSTRAINT_TYPE_FOLLOWPATH:
+ case CONSTRAINT_TYPE_SPLINEIK:
+ only_curve = true;
+ only_ob = true;
+ add = false;
+ break;
+
+ /* mesh only? */
+ case CONSTRAINT_TYPE_SHRINKWRAP:
+ only_mesh = true;
+ only_ob = true;
+ add = false;
+ break;
+ }
+
+ /* if the active Object is Armature, and we can search for bones, do so... */
+ if ((obact->type == OB_ARMATURE) && (only_ob == false)) {
+ /* search in list of selected Pose-Channels for target */
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones_from_active_object) {
+ /* just use the first one that we encounter, as long as it is not the active one */
+ if (pchan != pchanact) {
+ *tar_ob = obact;
+ *tar_pchan = pchan;
+ found = true;
+
+ break;
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ /* if not yet found, try selected Objects... */
+ if (found == false) {
+ /* search in selected objects context */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ /* just use the first object we encounter (that isn't the active object)
+ * and which fulfills the criteria for the object-target that we've got
+ */
+ if (ob != obact) {
+ /* for armatures in pose mode, look inside the armature for the active bone
+ * so that we set up cross-armature constraints with less effort
+ */
+ if ((ob->type == OB_ARMATURE) && (ob->mode & OB_MODE_POSE) &&
+ (!only_curve && !only_mesh)) {
+ /* just use the active bone, and assume that it is visible + usable */
+ *tar_ob = ob;
+ *tar_pchan = BKE_pose_channel_active(ob);
+ found = true;
+
+ break;
+ }
+ else if (((!only_curve) || (ob->type == OB_CURVE)) &&
+ ((!only_mesh) || (ob->type == OB_MESH))) {
+ /* set target */
+ *tar_ob = ob;
+ found = true;
+
+ /* perform some special operations on the target */
+ if (only_curve) {
+ /* Curve-Path option must be enabled for follow-path constraints to be able to work */
+ Curve *cu = (Curve *)ob->data;
+ cu->flag |= CU_PATH;
+ }
+
+ break;
+ }
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ /* if still not found, add a new empty to act as a target (if allowed) */
+ if ((found == false) && (add)) {
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base = BASACT(view_layer);
+ Object *obt;
+
+ /* add new target object */
+ obt = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, NULL);
+
+ /* transform cent to global coords for loc */
+ if (pchanact) {
+ /* since by default, IK targets the tip of the last bone, use the tip of the active PoseChannel
+ * if adding a target for an IK Constraint
+ */
+ if (con_type == CONSTRAINT_TYPE_KINEMATIC)
+ mul_v3_m4v3(obt->loc, obact->obmat, pchanact->pose_tail);
+ else
+ mul_v3_m4v3(obt->loc, obact->obmat, pchanact->pose_head);
+ }
+ else {
+ copy_v3_v3(obt->loc, obact->obmat[3]);
+ }
+
+ /* restore, BKE_object_add sets active */
+ BASACT(view_layer) = base;
+ base->flag |= BASE_SELECTED;
+
+ /* make our new target the new object */
+ *tar_ob = obt;
+ found = true;
+ }
+
+ /* return whether there's any target */
+ return found;
}
/* used by add constraint operators to add the constraint required */
-static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase *list, int type, const bool setTarget)
-{
- Main *bmain = CTX_data_main(C);
- bPoseChannel *pchan;
- bConstraint *con;
-
- if (list == &ob->constraints) {
- pchan = NULL;
- }
- else {
- pchan = BKE_pose_channel_active(ob);
-
- /* ensure not to confuse object/pose adding */
- if (pchan == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active pose bone to add a constraint to");
- return OPERATOR_CANCELLED;
- }
- }
- /* check if constraint to be added is valid for the given constraints stack */
- if (type == CONSTRAINT_TYPE_NULL) {
- return OPERATOR_CANCELLED;
- }
- if ((type == CONSTRAINT_TYPE_KINEMATIC) && ((!pchan) || (list != &pchan->constraints))) {
- BKE_report(op->reports, RPT_ERROR, "IK constraint can only be added to bones");
- return OPERATOR_CANCELLED;
- }
- if ((type == CONSTRAINT_TYPE_SPLINEIK) && ((!pchan) || (list != &pchan->constraints))) {
- BKE_report(op->reports, RPT_ERROR, "Spline IK constraint can only be added to bones");
- return OPERATOR_CANCELLED;
- }
-
- /* create a new constraint of the type required, and add it to the active/given constraints list */
- if (pchan)
- con = BKE_constraint_add_for_pose(ob, pchan, NULL, type);
- else
- con = BKE_constraint_add_for_object(ob, NULL, type);
-
- /* get the first selected object/bone, and make that the target
- * - apart from the buttons-window add buttons, we shouldn't add in this way
- */
- if (setTarget) {
- Object *tar_ob = NULL;
- bPoseChannel *tar_pchan = NULL;
-
- /* get the target objects, adding them as need be */
- if (get_new_constraint_target(C, type, &tar_ob, &tar_pchan, 1)) {
- /* method of setting target depends on the type of target we've got
- * - by default, just set the first target (distinction here is only for multiple-targeted constraints)
- */
- if (tar_pchan)
- set_constraint_nth_target(con, tar_ob, tar_pchan->name, 0);
- else
- set_constraint_nth_target(con, tar_ob, "", 0);
- }
- }
-
- /* do type-specific tweaking to the constraint settings */
- switch (type) {
- case CONSTRAINT_TYPE_PYTHON: /* FIXME: this code is not really valid anymore */
- {
+static int constraint_add_exec(
+ bContext *C, wmOperator *op, Object *ob, ListBase *list, int type, const bool setTarget)
+{
+ Main *bmain = CTX_data_main(C);
+ bPoseChannel *pchan;
+ bConstraint *con;
+
+ if (list == &ob->constraints) {
+ pchan = NULL;
+ }
+ else {
+ pchan = BKE_pose_channel_active(ob);
+
+ /* ensure not to confuse object/pose adding */
+ if (pchan == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active pose bone to add a constraint to");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ /* check if constraint to be added is valid for the given constraints stack */
+ if (type == CONSTRAINT_TYPE_NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ if ((type == CONSTRAINT_TYPE_KINEMATIC) && ((!pchan) || (list != &pchan->constraints))) {
+ BKE_report(op->reports, RPT_ERROR, "IK constraint can only be added to bones");
+ return OPERATOR_CANCELLED;
+ }
+ if ((type == CONSTRAINT_TYPE_SPLINEIK) && ((!pchan) || (list != &pchan->constraints))) {
+ BKE_report(op->reports, RPT_ERROR, "Spline IK constraint can only be added to bones");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* create a new constraint of the type required, and add it to the active/given constraints list */
+ if (pchan)
+ con = BKE_constraint_add_for_pose(ob, pchan, NULL, type);
+ else
+ con = BKE_constraint_add_for_object(ob, NULL, type);
+
+ /* get the first selected object/bone, and make that the target
+ * - apart from the buttons-window add buttons, we shouldn't add in this way
+ */
+ if (setTarget) {
+ Object *tar_ob = NULL;
+ bPoseChannel *tar_pchan = NULL;
+
+ /* get the target objects, adding them as need be */
+ if (get_new_constraint_target(C, type, &tar_ob, &tar_pchan, 1)) {
+ /* method of setting target depends on the type of target we've got
+ * - by default, just set the first target (distinction here is only for multiple-targeted constraints)
+ */
+ if (tar_pchan)
+ set_constraint_nth_target(con, tar_ob, tar_pchan->name, 0);
+ else
+ set_constraint_nth_target(con, tar_ob, "", 0);
+ }
+ }
+
+ /* do type-specific tweaking to the constraint settings */
+ switch (type) {
+ case CONSTRAINT_TYPE_PYTHON: /* FIXME: this code is not really valid anymore */
+ {
#ifdef WITH_PYTHON
- char *menustr;
- int scriptint = 0;
- /* popup a list of usable scripts */
- menustr = buildmenu_pyconstraints(bmain, NULL, &scriptint);
- /* XXX scriptint = pupmenu(menustr); */
- MEM_freeN(menustr);
-
- /* only add constraint if a script was chosen */
- if (scriptint) {
- /* add constraint */
- validate_pyconstraint_cb(bmain, con->data, &scriptint);
-
- /* make sure target allowance is set correctly */
- BPY_pyconstraint_update(ob, con);
- }
+ char *menustr;
+ int scriptint = 0;
+ /* popup a list of usable scripts */
+ menustr = buildmenu_pyconstraints(bmain, NULL, &scriptint);
+ /* XXX scriptint = pupmenu(menustr); */
+ MEM_freeN(menustr);
+
+ /* only add constraint if a script was chosen */
+ if (scriptint) {
+ /* add constraint */
+ validate_pyconstraint_cb(bmain, con->data, &scriptint);
+
+ /* make sure target allowance is set correctly */
+ BPY_pyconstraint_update(ob, con);
+ }
#endif
- break;
- }
-
- default:
- break;
- }
+ break;
+ }
- /* make sure all settings are valid - similar to above checks, but sometimes can be wrong */
- object_test_constraints(bmain, ob);
+ default:
+ break;
+ }
- if (pchan)
- BKE_pose_update_constraint_flags(ob->pose);
+ /* make sure all settings are valid - similar to above checks, but sometimes can be wrong */
+ object_test_constraints(bmain, ob);
+ if (pchan)
+ BKE_pose_update_constraint_flags(ob->pose);
- /* force depsgraph to get recalculated since new relationships added */
- DEG_relations_tag_update(bmain);
+ /* force depsgraph to get recalculated since new relationships added */
+ DEG_relations_tag_update(bmain);
- if ((ob->type == OB_ARMATURE) && (pchan)) {
- BKE_pose_tag_recalc(bmain, ob->pose); /* sort pose channels */
- if (BKE_constraints_proxylocked_owner(ob, pchan) && ob->adt) {
- /* We need to make use of ugly POSE_ANIMATION_WORKAROUND here too, else anim data are not reloaded
- * after calling `BKE_pose_rebuild()`, which causes T43872.
- * XXX Temp hack until new depsgraph hopefully solves this. */
- DEG_id_tag_update(&ob->id, ID_RECALC_ANIMATION);
- }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
- }
- else
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ if ((ob->type == OB_ARMATURE) && (pchan)) {
+ BKE_pose_tag_recalc(bmain, ob->pose); /* sort pose channels */
+ if (BKE_constraints_proxylocked_owner(ob, pchan) && ob->adt) {
+ /* We need to make use of ugly POSE_ANIMATION_WORKAROUND here too, else anim data are not reloaded
+ * after calling `BKE_pose_rebuild()`, which causes T43872.
+ * XXX Temp hack until new depsgraph hopefully solves this. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_ANIMATION);
+ }
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
+ }
+ else
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_ADDED, ob);
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_ADDED, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* ------------------ */
@@ -1871,121 +1904,125 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase
/* dummy operator callback */
static int object_constraint_add_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- int type = RNA_enum_get(op->ptr, "type");
- short with_targets = 0;
+ Object *ob = ED_object_active_context(C);
+ int type = RNA_enum_get(op->ptr, "type");
+ short with_targets = 0;
- if (!ob) {
- BKE_report(op->reports, RPT_ERROR, "No active object to add constraint to");
- return OPERATOR_CANCELLED;
- }
+ if (!ob) {
+ BKE_report(op->reports, RPT_ERROR, "No active object to add constraint to");
+ return OPERATOR_CANCELLED;
+ }
- /* hack: set constraint targets from selected objects in context is allowed when
- * operator name included 'with_targets', since the menu doesn't allow multiple properties
- */
- if (strstr(op->idname, "with_targets"))
- with_targets = 1;
+ /* hack: set constraint targets from selected objects in context is allowed when
+ * operator name included 'with_targets', since the menu doesn't allow multiple properties
+ */
+ if (strstr(op->idname, "with_targets"))
+ with_targets = 1;
- return constraint_add_exec(C, op, ob, &ob->constraints, type, with_targets);
+ return constraint_add_exec(C, op, ob, &ob->constraints, type, with_targets);
}
/* dummy operator callback */
static int pose_constraint_add_exec(bContext *C, wmOperator *op)
{
- Object *ob = BKE_object_pose_armature_get(ED_object_active_context(C));
- int type = RNA_enum_get(op->ptr, "type");
- short with_targets = 0;
+ Object *ob = BKE_object_pose_armature_get(ED_object_active_context(C));
+ int type = RNA_enum_get(op->ptr, "type");
+ short with_targets = 0;
- if (!ob) {
- BKE_report(op->reports, RPT_ERROR, "No active object to add constraint to");
- return OPERATOR_CANCELLED;
- }
+ if (!ob) {
+ BKE_report(op->reports, RPT_ERROR, "No active object to add constraint to");
+ return OPERATOR_CANCELLED;
+ }
- /* hack: set constraint targets from selected objects in context is allowed when
- * operator name included 'with_targets', since the menu doesn't allow multiple properties
- */
- if (strstr(op->idname, "with_targets"))
- with_targets = 1;
+ /* hack: set constraint targets from selected objects in context is allowed when
+ * operator name included 'with_targets', since the menu doesn't allow multiple properties
+ */
+ if (strstr(op->idname, "with_targets"))
+ with_targets = 1;
- return constraint_add_exec(C, op, ob, get_active_constraints(ob), type, with_targets);
+ return constraint_add_exec(C, op, ob, get_active_constraints(ob), type, with_targets);
}
/* ------------------ */
void OBJECT_OT_constraint_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Constraint";
- ot->description = "Add a constraint to the active object";
- ot->idname = "OBJECT_OT_constraint_add";
+ /* identifiers */
+ ot->name = "Add Constraint";
+ ot->description = "Add a constraint to the active object";
+ ot->idname = "OBJECT_OT_constraint_add";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_constraint_add_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_constraint_add_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
}
void OBJECT_OT_constraint_add_with_targets(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Constraint (with Targets)";
- ot->description = "Add a constraint to the active object, with target (where applicable) set to the selected Objects/Bones";
- ot->idname = "OBJECT_OT_constraint_add_with_targets";
+ /* identifiers */
+ ot->name = "Add Constraint (with Targets)";
+ ot->description =
+ "Add a constraint to the active object, with target (where applicable) set to the selected "
+ "Objects/Bones";
+ ot->idname = "OBJECT_OT_constraint_add_with_targets";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_constraint_add_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_constraint_add_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
}
void POSE_OT_constraint_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Constraint";
- ot->description = "Add a constraint to the active bone";
- ot->idname = "POSE_OT_constraint_add";
+ /* identifiers */
+ ot->name = "Add Constraint";
+ ot->description = "Add a constraint to the active bone";
+ ot->idname = "POSE_OT_constraint_add";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = pose_constraint_add_exec;
- ot->poll = ED_operator_posemode_exclusive;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = pose_constraint_add_exec;
+ ot->poll = ED_operator_posemode_exclusive;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
}
void POSE_OT_constraint_add_with_targets(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Constraint (with Targets)";
- ot->description = "Add a constraint to the active bone, with target (where applicable) set to the selected Objects/Bones";
- ot->idname = "POSE_OT_constraint_add_with_targets";
+ /* identifiers */
+ ot->name = "Add Constraint (with Targets)";
+ ot->description =
+ "Add a constraint to the active bone, with target (where applicable) set to the selected "
+ "Objects/Bones";
+ ot->idname = "POSE_OT_constraint_add_with_targets";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = pose_constraint_add_exec;
- ot->poll = ED_operator_posemode_exclusive;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = pose_constraint_add_exec;
+ ot->poll = ED_operator_posemode_exclusive;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
}
/************************ IK Constraint operators *********************/
@@ -1995,83 +2032,93 @@ void POSE_OT_constraint_add_with_targets(wmOperatorType *ot)
/* present menu with options + validation for targets to use */
static int pose_ik_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bPoseChannel *pchan = BKE_pose_channel_active(ob);
- bConstraint *con = NULL;
-
- uiPopupMenu *pup;
- uiLayout *layout;
- Object *tar_ob = NULL;
- bPoseChannel *tar_pchan = NULL;
-
- /* must have active bone */
- if (ELEM(NULL, ob, pchan)) {
- BKE_report(op->reports, RPT_ERROR, "Must have an active bone to add IK constraint to");
- return OPERATOR_CANCELLED;
- }
-
- /* bone must not have any constraints already */
- for (con = pchan->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_KINEMATIC) break;
- }
- if (con) {
- BKE_report(op->reports, RPT_ERROR, "Bone already has an IK constraint");
- return OPERATOR_CANCELLED;
- }
-
- /* prepare popup menu to choose targeting options */
- pup = UI_popup_menu_begin(C, IFACE_("Add IK"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
-
- /* the type of targets we'll set determines the menu entries to show... */
- if (get_new_constraint_target(C, CONSTRAINT_TYPE_KINEMATIC, &tar_ob, &tar_pchan, 0)) {
- /* bone target, or object target?
- * - the only thing that matters is that we want a target...
- */
- if (tar_pchan)
- uiItemBooleanO(layout, IFACE_("To Active Bone"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 1);
- else
- uiItemBooleanO(layout, IFACE_("To Active Object"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 1);
- }
- else {
- /* we have a choice of adding to a new empty, or not setting any target (targetless IK) */
- uiItemBooleanO(layout, IFACE_("To New Empty Object"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 1);
- uiItemBooleanO(layout, IFACE_("Without Targets"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 0);
- }
-
- /* finish building the menu, and process it (should result in calling self again) */
- UI_popup_menu_end(C, pup);
-
- return OPERATOR_INTERFACE;
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ bPoseChannel *pchan = BKE_pose_channel_active(ob);
+ bConstraint *con = NULL;
+
+ uiPopupMenu *pup;
+ uiLayout *layout;
+ Object *tar_ob = NULL;
+ bPoseChannel *tar_pchan = NULL;
+
+ /* must have active bone */
+ if (ELEM(NULL, ob, pchan)) {
+ BKE_report(op->reports, RPT_ERROR, "Must have an active bone to add IK constraint to");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* bone must not have any constraints already */
+ for (con = pchan->constraints.first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC)
+ break;
+ }
+ if (con) {
+ BKE_report(op->reports, RPT_ERROR, "Bone already has an IK constraint");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* prepare popup menu to choose targeting options */
+ pup = UI_popup_menu_begin(C, IFACE_("Add IK"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+
+ /* the type of targets we'll set determines the menu entries to show... */
+ if (get_new_constraint_target(C, CONSTRAINT_TYPE_KINEMATIC, &tar_ob, &tar_pchan, 0)) {
+ /* bone target, or object target?
+ * - the only thing that matters is that we want a target...
+ */
+ if (tar_pchan)
+ uiItemBooleanO(
+ layout, IFACE_("To Active Bone"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 1);
+ else
+ uiItemBooleanO(
+ layout, IFACE_("To Active Object"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 1);
+ }
+ else {
+ /* we have a choice of adding to a new empty, or not setting any target (targetless IK) */
+ uiItemBooleanO(
+ layout, IFACE_("To New Empty Object"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 1);
+ uiItemBooleanO(
+ layout, IFACE_("Without Targets"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 0);
+ }
+
+ /* finish building the menu, and process it (should result in calling self again) */
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
}
/* call constraint_add_exec() to add the IK constraint */
static int pose_ik_add_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
- const bool with_targets = RNA_boolean_get(op->ptr, "with_targets");
+ Object *ob = CTX_data_active_object(C);
+ const bool with_targets = RNA_boolean_get(op->ptr, "with_targets");
- /* add the constraint - all necessary checks should have been done by the invoke() callback already... */
- return constraint_add_exec(C, op, ob, get_active_constraints(ob), CONSTRAINT_TYPE_KINEMATIC, with_targets);
+ /* add the constraint - all necessary checks should have been done by the invoke() callback already... */
+ return constraint_add_exec(
+ C, op, ob, get_active_constraints(ob), CONSTRAINT_TYPE_KINEMATIC, with_targets);
}
void POSE_OT_ik_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add IK to Bone";
- ot->description = "Add IK Constraint to the active Bone";
- ot->idname = "POSE_OT_ik_add";
+ /* identifiers */
+ ot->name = "Add IK to Bone";
+ ot->description = "Add IK Constraint to the active Bone";
+ ot->idname = "POSE_OT_ik_add";
- /* api callbacks */
- ot->invoke = pose_ik_add_invoke;
- ot->exec = pose_ik_add_exec;
- ot->poll = ED_operator_posemode_exclusive;
+ /* api callbacks */
+ ot->invoke = pose_ik_add_invoke;
+ ot->exec = pose_ik_add_exec;
+ ot->poll = ED_operator_posemode_exclusive;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "with_targets", 1, "With Targets", "Assign IK Constraint with targets derived from the select bones/objects");
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "with_targets",
+ 1,
+ "With Targets",
+ "Assign IK Constraint with targets derived from the select bones/objects");
}
/* ------------------ */
@@ -2079,48 +2126,48 @@ void POSE_OT_ik_add(wmOperatorType *ot)
/* remove IK constraints from selected bones */
static int pose_ik_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *prev_ob = NULL;
+ Object *prev_ob = NULL;
- /* only remove IK Constraints */
- CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob)
- {
- bConstraint *con, *next;
+ /* only remove IK Constraints */
+ CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob)
+ {
+ bConstraint *con, *next;
- /* TODO: should we be checking if these constraints were local before we try and remove them? */
- for (con = pchan->constraints.first; con; con = next) {
- next = con->next;
- if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
- BKE_constraint_remove(&pchan->constraints, con);
- }
- }
- pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_TARGET);
+ /* TODO: should we be checking if these constraints were local before we try and remove them? */
+ for (con = pchan->constraints.first; con; con = next) {
+ next = con->next;
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
+ BKE_constraint_remove(&pchan->constraints, con);
+ }
+ }
+ pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_TARGET);
- if (prev_ob != ob) {
- prev_ob = ob;
+ if (prev_ob != ob) {
+ prev_ob = ob;
- /* Refresh depsgraph. */
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ /* Refresh depsgraph. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- /* Note, notifier might evolve. */
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
- }
- }
- CTX_DATA_END;
+ /* Note, notifier might evolve. */
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
+ }
+ }
+ CTX_DATA_END;
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void POSE_OT_ik_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove IK";
- ot->description = "Remove all IK Constraints from selected bones";
- ot->idname = "POSE_OT_ik_clear";
+ /* identifiers */
+ ot->name = "Remove IK";
+ ot->description = "Remove all IK Constraints from selected bones";
+ ot->idname = "POSE_OT_ik_clear";
- /* api callbacks */
- ot->exec = pose_ik_clear_exec;
- ot->poll = ED_operator_posemode_exclusive;
+ /* api callbacks */
+ ot->exec = pose_ik_clear_exec;
+ ot->poll = ED_operator_posemode_exclusive;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* 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 52b60793585..57c7ff1535d 100644
--- a/source/blender/editors/object/object_data_transfer.c
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -58,402 +58,463 @@
* Note some are 'fake' ones, i.e. they are not hold by real CDLayers. */
/* Not shared with modifier, since we use a usual enum here, not a multi-choice one. */
static const EnumPropertyItem DT_layer_items[] = {
- {0, "", 0, "Vertex Data", ""},
- {DT_TYPE_MDEFORMVERT, "VGROUP_WEIGHTS", 0, "Vertex Group(s)", "Transfer active or all vertex groups"},
-#if 0 /* XXX For now, would like to finish/merge work from 2014 gsoc first. */
- {DT_TYPE_SHAPEKEY, "SHAPEKEYS", 0, "Shapekey(s)", "Transfer active or all shape keys"},
+ {0, "", 0, "Vertex Data", ""},
+ {DT_TYPE_MDEFORMVERT,
+ "VGROUP_WEIGHTS",
+ 0,
+ "Vertex Group(s)",
+ "Transfer active or all vertex groups"},
+#if 0 /* XXX For now, would like to finish/merge work from 2014 gsoc first. */
+ {DT_TYPE_SHAPEKEY, "SHAPEKEYS", 0, "Shapekey(s)", "Transfer active or all shape keys"},
#endif
-#if 0 /* XXX When SkinModifier is enabled,
+#if 0 /* XXX When SkinModifier is enabled,
* it seems to erase its own CD_MVERT_SKIN layer from final DM :( */
- {DT_TYPE_SKIN, "SKIN", 0, "Skin Weight", "Transfer skin weights"},
+ {DT_TYPE_SKIN, "SKIN", 0, "Skin Weight", "Transfer skin weights"},
#endif
- {DT_TYPE_BWEIGHT_VERT, "BEVEL_WEIGHT_VERT", 0, "Bevel Weight", "Transfer bevel weights"},
- {0, "", 0, "Edge Data", ""},
- {DT_TYPE_SHARP_EDGE, "SHARP_EDGE", 0, "Sharp", "Transfer sharp mark"},
- {DT_TYPE_SEAM, "SEAM", 0, "UV Seam", "Transfer UV seam mark"},
- {DT_TYPE_CREASE, "CREASE", 0, "Subsurf Crease", "Transfer crease values"},
- {DT_TYPE_BWEIGHT_EDGE, "BEVEL_WEIGHT_EDGE", 0, "Bevel Weight", "Transfer bevel weights"},
- {DT_TYPE_FREESTYLE_EDGE, "FREESTYLE_EDGE", 0, "Freestyle Mark", "Transfer Freestyle edge mark"},
- {0, "", 0, "Face Corner Data", ""},
- {DT_TYPE_LNOR, "CUSTOM_NORMAL", 0, "Custom Normals", "Transfer custom normals"},
- {DT_TYPE_VCOL, "VCOL", 0, "VCol", "Vertex (face corners) colors"},
- {DT_TYPE_UV, "UV", 0, "UVs", "Transfer UV layers"},
- {0, "", 0, "Face Data", ""},
- {DT_TYPE_SHARP_FACE, "SMOOTH", 0, "Smooth", "Transfer flat/smooth mark"},
- {DT_TYPE_FREESTYLE_FACE, "FREESTYLE_FACE", 0, "Freestyle Mark", "Transfer Freestyle face mark"},
- {0, NULL, 0, NULL, NULL},
+ {DT_TYPE_BWEIGHT_VERT, "BEVEL_WEIGHT_VERT", 0, "Bevel Weight", "Transfer bevel weights"},
+ {0, "", 0, "Edge Data", ""},
+ {DT_TYPE_SHARP_EDGE, "SHARP_EDGE", 0, "Sharp", "Transfer sharp mark"},
+ {DT_TYPE_SEAM, "SEAM", 0, "UV Seam", "Transfer UV seam mark"},
+ {DT_TYPE_CREASE, "CREASE", 0, "Subsurf Crease", "Transfer crease values"},
+ {DT_TYPE_BWEIGHT_EDGE, "BEVEL_WEIGHT_EDGE", 0, "Bevel Weight", "Transfer bevel weights"},
+ {DT_TYPE_FREESTYLE_EDGE,
+ "FREESTYLE_EDGE",
+ 0,
+ "Freestyle Mark",
+ "Transfer Freestyle edge mark"},
+ {0, "", 0, "Face Corner Data", ""},
+ {DT_TYPE_LNOR, "CUSTOM_NORMAL", 0, "Custom Normals", "Transfer custom normals"},
+ {DT_TYPE_VCOL, "VCOL", 0, "VCol", "Vertex (face corners) colors"},
+ {DT_TYPE_UV, "UV", 0, "UVs", "Transfer UV layers"},
+ {0, "", 0, "Face Data", ""},
+ {DT_TYPE_SHARP_FACE, "SMOOTH", 0, "Smooth", "Transfer flat/smooth mark"},
+ {DT_TYPE_FREESTYLE_FACE,
+ "FREESTYLE_FACE",
+ 0,
+ "Freestyle Mark",
+ "Transfer Freestyle face mark"},
+ {0, NULL, 0, NULL, NULL},
};
/* Note: rna_enum_dt_layers_select_src_items enum is from rna_modifier.c */
-static const EnumPropertyItem *dt_layers_select_src_itemf(
- bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *dt_layers_select_src_itemf(bContext *C,
+ PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- if (!C) { /* needed for docs and i18n tools */
- return rna_enum_dt_layers_select_src_items;
- }
-
- EnumPropertyItem *item = NULL, tmp_item = {0};
- int totitem = 0;
- const int data_type = RNA_enum_get(ptr, "data_type");
-
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
-
- PropertyRNA *prop = RNA_struct_find_property(ptr, "use_reverse_transfer");
- const bool reverse_transfer = prop != NULL && RNA_property_boolean_get(ptr, prop);
- const int layers_select_dst = reverse_transfer ? RNA_enum_get(ptr, "layers_select_src") :
- RNA_enum_get(ptr, "layers_select_dst");
-
- if (!reverse_transfer || layers_select_dst == DT_LAYERS_ACTIVE_DST || layers_select_dst >= 0) {
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_ACTIVE_SRC);
- }
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_ALL_SRC);
-
-
-
- if (data_type == DT_TYPE_MDEFORMVERT) {
- Object *ob_src = CTX_data_active_object(C);
-
- if (BKE_object_pose_armature_get(ob_src)) {
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_SELECT);
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_DEFORM);
- }
-
- if (ob_src) {
- bDeformGroup *dg;
- int i;
-
- RNA_enum_item_add_separator(&item, &totitem);
-
- for (i = 0, dg = ob_src->defbase.first; dg; i++, dg = dg->next) {
- tmp_item.value = i;
- tmp_item.identifier = tmp_item.name = dg->name;
- RNA_enum_item_add(&item, &totitem, &tmp_item);
- }
- }
- }
- else if (data_type == DT_TYPE_SHAPEKEY) {
- /* TODO */
- }
- else if (data_type == DT_TYPE_UV) {
- Object *ob_src = CTX_data_active_object(C);
-
- if (ob_src) {
- Mesh *me_eval;
- int num_data, i;
-
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
-
- CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH;
- cddata_masks.lmask |= CD_MASK_MLOOPUV;
- me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks);
- num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPUV);
-
- RNA_enum_item_add_separator(&item, &totitem);
-
- for (i = 0; i < num_data; i++) {
- tmp_item.value = i;
- tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(&me_eval->ldata, CD_MLOOPUV, i);
- RNA_enum_item_add(&item, &totitem, &tmp_item);
- }
- }
- }
- else if (data_type == DT_TYPE_VCOL) {
- Object *ob_src = CTX_data_active_object(C);
-
- if (ob_src) {
- Mesh *me_eval;
- int num_data, i;
-
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
-
- CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH;
- cddata_masks.lmask |= CD_MASK_MLOOPCOL;
- me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks);
- num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPCOL);
-
- RNA_enum_item_add_separator(&item, &totitem);
-
- for (i = 0; i < num_data; i++) {
- tmp_item.value = i;
- tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(&me_eval->ldata, CD_MLOOPCOL, i);
- RNA_enum_item_add(&item, &totitem, &tmp_item);
- }
- }
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ if (!C) { /* needed for docs and i18n tools */
+ return rna_enum_dt_layers_select_src_items;
+ }
+
+ EnumPropertyItem *item = NULL, tmp_item = {0};
+ int totitem = 0;
+ const int data_type = RNA_enum_get(ptr, "data_type");
+
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
+ PropertyRNA *prop = RNA_struct_find_property(ptr, "use_reverse_transfer");
+ const bool reverse_transfer = prop != NULL && RNA_property_boolean_get(ptr, prop);
+ const int layers_select_dst = reverse_transfer ? RNA_enum_get(ptr, "layers_select_src") :
+ RNA_enum_get(ptr, "layers_select_dst");
+
+ if (!reverse_transfer || layers_select_dst == DT_LAYERS_ACTIVE_DST || layers_select_dst >= 0) {
+ RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_ACTIVE_SRC);
+ }
+ RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_ALL_SRC);
+
+ if (data_type == DT_TYPE_MDEFORMVERT) {
+ Object *ob_src = CTX_data_active_object(C);
+
+ if (BKE_object_pose_armature_get(ob_src)) {
+ RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_SELECT);
+ RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_DEFORM);
+ }
+
+ if (ob_src) {
+ bDeformGroup *dg;
+ int i;
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0, dg = ob_src->defbase.first; dg; i++, dg = dg->next) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = dg->name;
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+ else if (data_type == DT_TYPE_SHAPEKEY) {
+ /* TODO */
+ }
+ else if (data_type == DT_TYPE_UV) {
+ Object *ob_src = CTX_data_active_object(C);
+
+ if (ob_src) {
+ Mesh *me_eval;
+ int num_data, i;
+
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
+
+ CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH;
+ cddata_masks.lmask |= CD_MASK_MLOOPUV;
+ me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks);
+ num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPUV);
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0; i < num_data; i++) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(
+ &me_eval->ldata, CD_MLOOPUV, i);
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+ else if (data_type == DT_TYPE_VCOL) {
+ Object *ob_src = CTX_data_active_object(C);
+
+ if (ob_src) {
+ Mesh *me_eval;
+ int num_data, i;
+
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
+
+ CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH;
+ cddata_masks.lmask |= CD_MASK_MLOOPCOL;
+ me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks);
+ num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPCOL);
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0; i < num_data; i++) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(
+ &me_eval->ldata, CD_MLOOPCOL, i);
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
/* Note: rna_enum_dt_layers_select_dst_items enum is from rna_modifier.c */
-static const EnumPropertyItem *dt_layers_select_dst_itemf(
- bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *dt_layers_select_dst_itemf(bContext *C,
+ PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- if (!C) { /* needed for docs and i18n tools */
- return rna_enum_dt_layers_select_dst_items;
- }
+ if (!C) { /* needed for docs and i18n tools */
+ return rna_enum_dt_layers_select_dst_items;
+ }
- EnumPropertyItem *item = NULL;
- int totitem = 0;
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
- PropertyRNA *prop = RNA_struct_find_property(ptr, "use_reverse_transfer");
- const bool reverse_transfer = prop != NULL && RNA_property_boolean_get(ptr, prop);
- const int layers_select_src = reverse_transfer ? RNA_enum_get(ptr, "layers_select_dst") :
- RNA_enum_get(ptr, "layers_select_src");
+ PropertyRNA *prop = RNA_struct_find_property(ptr, "use_reverse_transfer");
+ const bool reverse_transfer = prop != NULL && RNA_property_boolean_get(ptr, prop);
+ const int layers_select_src = reverse_transfer ? RNA_enum_get(ptr, "layers_select_dst") :
+ RNA_enum_get(ptr, "layers_select_src");
- if (reverse_transfer || layers_select_src == DT_LAYERS_ACTIVE_SRC || layers_select_src >= 0) {
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_dst_items, DT_LAYERS_ACTIVE_DST);
- }
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_dst_items, DT_LAYERS_NAME_DST);
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_dst_items, DT_LAYERS_INDEX_DST);
+ if (reverse_transfer || layers_select_src == DT_LAYERS_ACTIVE_SRC || layers_select_src >= 0) {
+ RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_dt_layers_select_dst_items, DT_LAYERS_ACTIVE_DST);
+ }
+ RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_dt_layers_select_dst_items, DT_LAYERS_NAME_DST);
+ RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_dt_layers_select_dst_items, DT_LAYERS_INDEX_DST);
- /* No 'specific' to-layers here, since we may transfer to several objects at once! */
+ /* No 'specific' to-layers here, since we may transfer to several objects at once! */
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
- return item;
+ return item;
}
-static const EnumPropertyItem *dt_layers_select_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
+static const EnumPropertyItem *dt_layers_select_itemf(bContext *C,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ bool *r_free)
{
- const bool reverse_transfer = RNA_boolean_get(ptr, "use_reverse_transfer");
-
- if (STREQ(RNA_property_identifier(prop), "layers_select_dst")) {
- if (reverse_transfer) {
- return dt_layers_select_src_itemf(C, ptr, prop, r_free);
- }
- else {
- return dt_layers_select_dst_itemf(C, ptr, prop, r_free);
- }
- }
- else if (reverse_transfer) {
- return dt_layers_select_dst_itemf(C, ptr, prop, r_free);
- }
- else {
- return dt_layers_select_src_itemf(C, ptr, prop, r_free);
- }
+ const bool reverse_transfer = RNA_boolean_get(ptr, "use_reverse_transfer");
+
+ if (STREQ(RNA_property_identifier(prop), "layers_select_dst")) {
+ if (reverse_transfer) {
+ return dt_layers_select_src_itemf(C, ptr, prop, r_free);
+ }
+ else {
+ return dt_layers_select_dst_itemf(C, ptr, prop, r_free);
+ }
+ }
+ else if (reverse_transfer) {
+ return dt_layers_select_dst_itemf(C, ptr, prop, r_free);
+ }
+ else {
+ return dt_layers_select_src_itemf(C, ptr, prop, r_free);
+ }
}
/* Note: rna_enum_dt_mix_mode_items enum is from rna_modifier.c */
-static const EnumPropertyItem *dt_mix_mode_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *dt_mix_mode_itemf(bContext *C,
+ PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- EnumPropertyItem *item = NULL;
- int totitem = 0;
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
- const int dtdata_type = RNA_enum_get(ptr, "data_type");
- bool support_advanced_mixing, support_threshold;
+ const int dtdata_type = RNA_enum_get(ptr, "data_type");
+ bool support_advanced_mixing, support_threshold;
- if (!C) { /* needed for docs and i18n tools */
- return rna_enum_dt_mix_mode_items;
- }
+ if (!C) { /* needed for docs and i18n tools */
+ return rna_enum_dt_mix_mode_items;
+ }
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_TRANSFER);
+ RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_TRANSFER);
- BKE_object_data_transfer_get_dttypes_capacity(dtdata_type, &support_advanced_mixing, &support_threshold);
+ BKE_object_data_transfer_get_dttypes_capacity(
+ dtdata_type, &support_advanced_mixing, &support_threshold);
- if (support_threshold) {
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_REPLACE_ABOVE_THRESHOLD);
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_REPLACE_BELOW_THRESHOLD);
- }
+ if (support_threshold) {
+ RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_REPLACE_ABOVE_THRESHOLD);
+ RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_REPLACE_BELOW_THRESHOLD);
+ }
- if (support_advanced_mixing) {
- RNA_enum_item_add_separator(&item, &totitem);
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_MIX);
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_ADD);
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_SUB);
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_MUL);
- }
+ if (support_advanced_mixing) {
+ RNA_enum_item_add_separator(&item, &totitem);
+ RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_MIX);
+ RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_ADD);
+ RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_SUB);
+ RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_MUL);
+ }
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
- return item;
+ return item;
}
static bool data_transfer_check(bContext *UNUSED(C), wmOperator *op)
{
- const int layers_select_src = RNA_enum_get(op->ptr, "layers_select_src");
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, "layers_select_dst");
- const int layers_select_dst = RNA_property_enum_get(op->ptr, prop);
+ const int layers_select_src = RNA_enum_get(op->ptr, "layers_select_src");
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "layers_select_dst");
+ const int layers_select_dst = RNA_property_enum_get(op->ptr, prop);
- /* TODO: check for invalid layers_src select modes too! */
+ /* TODO: check for invalid layers_src select modes too! */
- if ((layers_select_src != DT_LAYERS_ACTIVE_SRC) && (layers_select_dst == DT_LAYERS_ACTIVE_DST)) {
- RNA_property_enum_set(op->ptr, prop, DT_LAYERS_NAME_DST);
- return true;
- }
+ if ((layers_select_src != DT_LAYERS_ACTIVE_SRC) && (layers_select_dst == DT_LAYERS_ACTIVE_DST)) {
+ RNA_property_enum_set(op->ptr, prop, DT_LAYERS_NAME_DST);
+ return true;
+ }
- return false;
+ return false;
}
/* Helper, used by both data_transfer_exec and datalayout_transfer_exec. */
-static void data_transfer_exec_preprocess_objects(
- bContext *C, wmOperator *op, Object *ob_src, ListBase *ctx_objects, const bool reverse_transfer)
+static void data_transfer_exec_preprocess_objects(bContext *C,
+ wmOperator *op,
+ Object *ob_src,
+ ListBase *ctx_objects,
+ const bool reverse_transfer)
{
- CollectionPointerLink *ctx_ob;
- CTX_data_selected_editable_objects(C, ctx_objects);
-
- if (reverse_transfer) {
- return; /* Nothing else to do in this case... */
- }
-
- for (ctx_ob = ctx_objects->first; ctx_ob; ctx_ob = ctx_ob->next) {
- Object *ob = ctx_ob->ptr.data;
- Mesh *me;
- if ((ob == ob_src) || (ob->type != OB_MESH)) {
- continue;
- }
-
- me = ob->data;
- if (ID_IS_LINKED(me)) {
- /* Do not transfer to linked data, not supported. */
- BKE_reportf(op->reports, RPT_WARNING, "Skipping object '%s', linked data '%s' cannot be modified",
- ob->id.name + 2, me->id.name + 2);
- me->id.tag &= ~LIB_TAG_DOIT;
- continue;
- }
-
- me->id.tag |= LIB_TAG_DOIT;
- }
+ CollectionPointerLink *ctx_ob;
+ CTX_data_selected_editable_objects(C, ctx_objects);
+
+ if (reverse_transfer) {
+ return; /* Nothing else to do in this case... */
+ }
+
+ for (ctx_ob = ctx_objects->first; ctx_ob; ctx_ob = ctx_ob->next) {
+ Object *ob = ctx_ob->ptr.data;
+ Mesh *me;
+ if ((ob == ob_src) || (ob->type != OB_MESH)) {
+ continue;
+ }
+
+ me = ob->data;
+ if (ID_IS_LINKED(me)) {
+ /* Do not transfer to linked data, not supported. */
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Skipping object '%s', linked data '%s' cannot be modified",
+ ob->id.name + 2,
+ me->id.name + 2);
+ me->id.tag &= ~LIB_TAG_DOIT;
+ continue;
+ }
+
+ me->id.tag |= LIB_TAG_DOIT;
+ }
}
/* Helper, used by both data_transfer_exec and datalayout_transfer_exec. */
-static bool data_transfer_exec_is_object_valid(
- wmOperator *op, Object *ob_src, Object *ob_dst, const bool reverse_transfer)
+static bool data_transfer_exec_is_object_valid(wmOperator *op,
+ Object *ob_src,
+ Object *ob_dst,
+ const bool reverse_transfer)
{
- Mesh *me;
- if ((ob_dst == ob_src) || (ob_src->type != OB_MESH) || (ob_dst->type != OB_MESH)) {
- return false;
- }
-
- if (reverse_transfer) {
- return true;
- }
-
- me = ob_dst->data;
- if (me->id.tag & LIB_TAG_DOIT) {
- me->id.tag &= ~LIB_TAG_DOIT;
- return true;
- }
- else if (!ID_IS_LINKED(me)) {
- /* Do not apply transfer operation more than once. */
- /* XXX This is not nice regarding vgroups, which are half-Object data... :/ */
- BKE_reportf(op->reports, RPT_WARNING,
- "Skipping object '%s', data '%s' has already been processed with a previous object",
- ob_dst->id.name + 2, me->id.name + 2);
- }
- return false;
+ Mesh *me;
+ if ((ob_dst == ob_src) || (ob_src->type != OB_MESH) || (ob_dst->type != OB_MESH)) {
+ return false;
+ }
+
+ if (reverse_transfer) {
+ return true;
+ }
+
+ me = ob_dst->data;
+ if (me->id.tag & LIB_TAG_DOIT) {
+ me->id.tag &= ~LIB_TAG_DOIT;
+ return true;
+ }
+ else if (!ID_IS_LINKED(me)) {
+ /* Do not apply transfer operation more than once. */
+ /* XXX This is not nice regarding vgroups, which are half-Object data... :/ */
+ BKE_reportf(
+ op->reports,
+ RPT_WARNING,
+ "Skipping object '%s', data '%s' has already been processed with a previous object",
+ ob_dst->id.name + 2,
+ me->id.name + 2);
+ }
+ return false;
}
static int data_transfer_exec(bContext *C, wmOperator *op)
{
- Object *ob_src = ED_object_active_context(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
-
- ListBase ctx_objects;
- CollectionPointerLink *ctx_ob_dst;
-
- bool changed = false;
-
- const bool is_frozen = RNA_boolean_get(op->ptr, "use_freeze");
-
- const bool reverse_transfer = RNA_boolean_get(op->ptr, "use_reverse_transfer");
-
- const int data_type = RNA_enum_get(op->ptr, "data_type");
- const bool use_create = RNA_boolean_get(op->ptr, "use_create");
-
- const int map_vert_mode = RNA_enum_get(op->ptr, "vert_mapping");
- const int map_edge_mode = RNA_enum_get(op->ptr, "edge_mapping");
- const int map_loop_mode = RNA_enum_get(op->ptr, "loop_mapping");
- const int map_poly_mode = RNA_enum_get(op->ptr, "poly_mapping");
-
- const bool use_auto_transform = RNA_boolean_get(op->ptr, "use_auto_transform");
- const bool use_object_transform = RNA_boolean_get(op->ptr, "use_object_transform");
- const bool use_max_distance = RNA_boolean_get(op->ptr, "use_max_distance");
- const float max_distance = use_max_distance ? RNA_float_get(op->ptr, "max_distance") : FLT_MAX;
- const float ray_radius = RNA_float_get(op->ptr, "ray_radius");
- const float islands_precision = RNA_float_get(op->ptr, "islands_precision");
-
- const int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
- const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
- int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
- int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
- const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);
-
- const int mix_mode = RNA_enum_get(op->ptr, "mix_mode");
- const float mix_factor = RNA_float_get(op->ptr, "mix_factor");
-
- SpaceTransform space_transform_data;
- SpaceTransform *space_transform = (use_object_transform && !use_auto_transform) ? &space_transform_data : NULL;
-
- if (is_frozen) {
- BKE_report(op->reports, RPT_INFO,
- "Operator is frozen, changes to its settings won't take effect until you unfreeze it");
- return OPERATOR_FINISHED;
- }
-
- if (reverse_transfer && ID_IS_LINKED(ob_src->data)) {
- /* Do not transfer to linked data, not supported. */
- return OPERATOR_CANCELLED;
- }
-
- if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
- layers_select_src[fromto_idx] = layers_src;
- layers_select_dst[fromto_idx] = layers_dst;
- }
-
- data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, reverse_transfer);
-
- for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) {
- Object *ob_dst = ctx_ob_dst->ptr.data;
-
- if (reverse_transfer) {
- SWAP(Object *, ob_src, ob_dst);
- }
-
- if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, reverse_transfer)) {
- Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
-
- if (space_transform) {
- Object *ob_dst_eval = DEG_get_evaluated_object(depsgraph, ob_dst);
- BLI_SPACE_TRANSFORM_SETUP(space_transform, ob_dst_eval, ob_src_eval);
- }
-
- if (BKE_object_data_transfer_mesh(
- depsgraph, scene_eval, ob_src_eval, ob_dst, data_type, use_create,
- map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode,
- space_transform, use_auto_transform,
- max_distance, ray_radius, islands_precision,
- layers_select_src, layers_select_dst,
- mix_mode, mix_factor, NULL, false, op->reports))
- {
- changed = true;
- }
- }
-
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
-
- if (reverse_transfer) {
- SWAP(Object *, ob_src, ob_dst);
- }
- }
-
- BLI_freelistN(&ctx_objects);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
-
-#if 0 /* TODO */
- /* Note: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */
- return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ Object *ob_src = ED_object_active_context(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+
+ ListBase ctx_objects;
+ CollectionPointerLink *ctx_ob_dst;
+
+ bool changed = false;
+
+ const bool is_frozen = RNA_boolean_get(op->ptr, "use_freeze");
+
+ const bool reverse_transfer = RNA_boolean_get(op->ptr, "use_reverse_transfer");
+
+ const int data_type = RNA_enum_get(op->ptr, "data_type");
+ const bool use_create = RNA_boolean_get(op->ptr, "use_create");
+
+ const int map_vert_mode = RNA_enum_get(op->ptr, "vert_mapping");
+ const int map_edge_mode = RNA_enum_get(op->ptr, "edge_mapping");
+ const int map_loop_mode = RNA_enum_get(op->ptr, "loop_mapping");
+ const int map_poly_mode = RNA_enum_get(op->ptr, "poly_mapping");
+
+ const bool use_auto_transform = RNA_boolean_get(op->ptr, "use_auto_transform");
+ const bool use_object_transform = RNA_boolean_get(op->ptr, "use_object_transform");
+ const bool use_max_distance = RNA_boolean_get(op->ptr, "use_max_distance");
+ const float max_distance = use_max_distance ? RNA_float_get(op->ptr, "max_distance") : FLT_MAX;
+ const float ray_radius = RNA_float_get(op->ptr, "ray_radius");
+ const float islands_precision = RNA_float_get(op->ptr, "islands_precision");
+
+ const int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
+ const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
+ int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
+ int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
+ const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);
+
+ const int mix_mode = RNA_enum_get(op->ptr, "mix_mode");
+ const float mix_factor = RNA_float_get(op->ptr, "mix_factor");
+
+ SpaceTransform space_transform_data;
+ SpaceTransform *space_transform = (use_object_transform && !use_auto_transform) ?
+ &space_transform_data :
+ NULL;
+
+ if (is_frozen) {
+ BKE_report(
+ op->reports,
+ RPT_INFO,
+ "Operator is frozen, changes to its settings won't take effect until you unfreeze it");
+ return OPERATOR_FINISHED;
+ }
+
+ if (reverse_transfer && ID_IS_LINKED(ob_src->data)) {
+ /* Do not transfer to linked data, not supported. */
+ return OPERATOR_CANCELLED;
+ }
+
+ if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
+ layers_select_src[fromto_idx] = layers_src;
+ layers_select_dst[fromto_idx] = layers_dst;
+ }
+
+ data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, reverse_transfer);
+
+ for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) {
+ Object *ob_dst = ctx_ob_dst->ptr.data;
+
+ if (reverse_transfer) {
+ SWAP(Object *, ob_src, ob_dst);
+ }
+
+ if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, reverse_transfer)) {
+ Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
+
+ if (space_transform) {
+ Object *ob_dst_eval = DEG_get_evaluated_object(depsgraph, ob_dst);
+ BLI_SPACE_TRANSFORM_SETUP(space_transform, ob_dst_eval, ob_src_eval);
+ }
+
+ if (BKE_object_data_transfer_mesh(depsgraph,
+ scene_eval,
+ ob_src_eval,
+ ob_dst,
+ data_type,
+ use_create,
+ map_vert_mode,
+ map_edge_mode,
+ map_loop_mode,
+ map_poly_mode,
+ space_transform,
+ use_auto_transform,
+ max_distance,
+ ray_radius,
+ islands_precision,
+ layers_select_src,
+ layers_select_dst,
+ mix_mode,
+ mix_factor,
+ NULL,
+ false,
+ op->reports)) {
+ changed = true;
+ }
+ }
+
+ DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
+
+ if (reverse_transfer) {
+ SWAP(Object *, ob_src, ob_dst);
+ }
+ }
+
+ BLI_freelistN(&ctx_objects);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+
+#if 0 /* TODO */
+ /* Note: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */
+ return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
#else
- (void)changed;
- return OPERATOR_FINISHED;
+ (void)changed;
+ return OPERATOR_FINISHED;
#endif
}
@@ -461,153 +522,233 @@ static int data_transfer_exec(bContext *C, wmOperator *op)
/* Note this context poll is only really partial, it cannot check for all possible invalid cases. */
static bool data_transfer_poll(bContext *C)
{
- Object *ob = ED_object_active_context(C);
- ID *data = (ob) ? ob->data : NULL;
- return (ob && ob->type == OB_MESH && data);
+ Object *ob = ED_object_active_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ return (ob && ob->type == OB_MESH && data);
}
/* Used by both OBJECT_OT_data_transfer and OBJECT_OT_datalayout_transfer */
-static bool data_transfer_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop)
+static bool data_transfer_poll_property(const bContext *UNUSED(C),
+ wmOperator *op,
+ const PropertyRNA *prop)
{
- PointerRNA *ptr = op->ptr;
- PropertyRNA *prop_other;
-
- const char *prop_id = RNA_property_identifier(prop);
- const int data_type = RNA_enum_get(ptr, "data_type");
- bool use_auto_transform = false;
- bool use_max_distance = false;
- bool use_modifier = false;
-
- if ((prop_other = RNA_struct_find_property(ptr, "use_auto_transform"))) {
- use_auto_transform = RNA_property_boolean_get(ptr, prop_other);
- }
- if ((prop_other = RNA_struct_find_property(ptr, "use_max_distance"))) {
- use_max_distance = RNA_property_boolean_get(ptr, prop_other);
- }
- if ((prop_other = RNA_struct_find_property(ptr, "modifier"))) {
- use_modifier = RNA_property_is_set(ptr, prop_other);
- }
-
- if (STREQ(prop_id, "modifier")) {
- return use_modifier;
- }
-
- if (use_modifier) {
- /* Hide everything but 'modifier' property, if set. */
- return false;
- }
-
- if (STREQ(prop_id, "use_object_transform") && use_auto_transform) {
- return false;
- }
- if (STREQ(prop_id, "max_distance") && !use_max_distance) {
- return false;
- }
- if (STREQ(prop_id, "islands_precision") && !DT_DATATYPE_IS_LOOP(data_type)) {
- return false;
- }
-
- if (STREQ(prop_id, "vert_mapping") && !DT_DATATYPE_IS_VERT(data_type)) {
- return false;
- }
- if (STREQ(prop_id, "edge_mapping") && !DT_DATATYPE_IS_EDGE(data_type)) {
- return false;
- }
- if (STREQ(prop_id, "loop_mapping") && !DT_DATATYPE_IS_LOOP(data_type)) {
- return false;
- }
- if (STREQ(prop_id, "poly_mapping") && !DT_DATATYPE_IS_POLY(data_type)) {
- return false;
- }
-
- if ((STREQ(prop_id, "layers_select_src") || STREQ(prop_id, "layers_select_dst")) &&
- !DT_DATATYPE_IS_MULTILAYERS(data_type))
- {
- return false;
- }
-
- /* Else, show it! */
- return true;
+ PointerRNA *ptr = op->ptr;
+ PropertyRNA *prop_other;
+
+ const char *prop_id = RNA_property_identifier(prop);
+ const int data_type = RNA_enum_get(ptr, "data_type");
+ bool use_auto_transform = false;
+ bool use_max_distance = false;
+ bool use_modifier = false;
+
+ if ((prop_other = RNA_struct_find_property(ptr, "use_auto_transform"))) {
+ use_auto_transform = RNA_property_boolean_get(ptr, prop_other);
+ }
+ if ((prop_other = RNA_struct_find_property(ptr, "use_max_distance"))) {
+ use_max_distance = RNA_property_boolean_get(ptr, prop_other);
+ }
+ if ((prop_other = RNA_struct_find_property(ptr, "modifier"))) {
+ use_modifier = RNA_property_is_set(ptr, prop_other);
+ }
+
+ if (STREQ(prop_id, "modifier")) {
+ return use_modifier;
+ }
+
+ if (use_modifier) {
+ /* Hide everything but 'modifier' property, if set. */
+ return false;
+ }
+
+ if (STREQ(prop_id, "use_object_transform") && use_auto_transform) {
+ return false;
+ }
+ if (STREQ(prop_id, "max_distance") && !use_max_distance) {
+ return false;
+ }
+ if (STREQ(prop_id, "islands_precision") && !DT_DATATYPE_IS_LOOP(data_type)) {
+ return false;
+ }
+
+ if (STREQ(prop_id, "vert_mapping") && !DT_DATATYPE_IS_VERT(data_type)) {
+ return false;
+ }
+ if (STREQ(prop_id, "edge_mapping") && !DT_DATATYPE_IS_EDGE(data_type)) {
+ return false;
+ }
+ if (STREQ(prop_id, "loop_mapping") && !DT_DATATYPE_IS_LOOP(data_type)) {
+ return false;
+ }
+ if (STREQ(prop_id, "poly_mapping") && !DT_DATATYPE_IS_POLY(data_type)) {
+ return false;
+ }
+
+ if ((STREQ(prop_id, "layers_select_src") || STREQ(prop_id, "layers_select_dst")) &&
+ !DT_DATATYPE_IS_MULTILAYERS(data_type)) {
+ return false;
+ }
+
+ /* Else, show it! */
+ return true;
}
/* Transfer mesh data from active to selected objects. */
void OBJECT_OT_data_transfer(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* Identifiers.*/
- ot->name = "Transfer Mesh Data";
- ot->idname = "OBJECT_OT_data_transfer";
- ot->description = "Transfer data layer(s) (weights, edge sharp, ...) from active to selected meshes";
-
- /* API callbacks.*/
- ot->poll = data_transfer_poll;
- ot->poll_property = data_transfer_poll_property;
- ot->invoke = WM_menu_invoke;
- ot->exec = data_transfer_exec;
- ot->check = data_transfer_check;
-
- /* Flags.*/
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
-
- /* Properties.*/
- prop = RNA_def_boolean(ot->srna, "use_reverse_transfer", false, "Reverse Transfer",
- "Transfer from selected objects to active one");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
-
- RNA_def_boolean(ot->srna, "use_freeze", false, "Freeze Operator",
- "Prevent changes to settings to re-run the operator, "
- "handy to change several things at once with heavy geometry");
-
- /* Data type to transfer. */
- ot->prop = RNA_def_enum(ot->srna, "data_type", DT_layer_items, 0, "Data Type", "Which data to transfer");
- RNA_def_boolean(ot->srna, "use_create", true, "Create Data", "Add data layers on destination meshes if needed");
-
- /* Mapping methods. */
- RNA_def_enum(ot->srna, "vert_mapping", rna_enum_dt_method_vertex_items, MREMAP_MODE_VERT_NEAREST, "Vertex Mapping",
- "Method used to map source vertices to destination ones");
- RNA_def_enum(ot->srna, "edge_mapping", rna_enum_dt_method_edge_items, MREMAP_MODE_EDGE_NEAREST, "Edge Mapping",
- "Method used to map source edges to destination ones");
- RNA_def_enum(ot->srna, "loop_mapping", rna_enum_dt_method_loop_items, MREMAP_MODE_LOOP_NEAREST_POLYNOR,
- "Face Corner Mapping", "Method used to map source faces' corners to destination ones");
- RNA_def_enum(ot->srna, "poly_mapping", rna_enum_dt_method_poly_items, MREMAP_MODE_POLY_NEAREST, "Face Mapping",
- "Method used to map source faces to destination ones");
-
- /* Mapping options and filtering. */
- RNA_def_boolean(ot->srna, "use_auto_transform", false, "Auto Transform",
- "Automatically compute transformation to get the best possible match between source and "
- "destination meshes (WARNING: results will never be as good as manual matching of objects)");
- RNA_def_boolean(ot->srna, "use_object_transform", true, "Object Transform",
- "Evaluate source and destination meshes in global space");
- RNA_def_boolean(ot->srna, "use_max_distance", false, "Only Neighbor Geometry",
- "Source elements must be closer than given distance from destination one");
- prop = RNA_def_float(ot->srna, "max_distance", 1.0f, 0.0f, FLT_MAX, "Max Distance",
- "Maximum allowed distance between source and destination element, for non-topology mappings",
- 0.0f, 100.0f);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
- prop = RNA_def_float(ot->srna, "ray_radius", 0.0f, 0.0f, FLT_MAX, "Ray Radius",
- "'Width' of rays (especially useful when raycasting against vertices or edges)",
- 0.0f, 10.0f);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
- prop = RNA_def_float(ot->srna, "islands_precision", 0.1f, 0.0f, 10.0f, "Islands Precision",
- "Factor controlling precision of islands handling (the higher, the better the results)",
- 0.0f, 1.0f);
- RNA_def_property_subtype(prop, PROP_FACTOR);
-
- /* How to handle multi-layers types of data. */
- prop = RNA_def_enum(ot->srna, "layers_select_src", rna_enum_dt_layers_select_src_items, DT_LAYERS_ACTIVE_SRC,
- "Source Layers Selection", "Which layers to transfer, in case of multi-layers types");
- RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_itemf);
-
- prop = RNA_def_enum(ot->srna, "layers_select_dst", rna_enum_dt_layers_select_dst_items, DT_LAYERS_ACTIVE_DST,
- "Destination Layers Matching", "How to match source and destination layers");
- RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_itemf);
-
- prop = RNA_def_enum(ot->srna, "mix_mode", rna_enum_dt_mix_mode_items, CDT_MIX_TRANSFER, "Mix Mode",
- "How to affect destination elements with source values");
- RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_mix_mode_itemf);
- RNA_def_float(ot->srna, "mix_factor", 1.0f, 0.0f, 1.0f, "Mix Factor",
- "Factor to use when applying data to destination (exact behavior depends on mix mode)", 0.0f, 1.0f);
+ PropertyRNA *prop;
+
+ /* Identifiers.*/
+ ot->name = "Transfer Mesh Data";
+ ot->idname = "OBJECT_OT_data_transfer";
+ ot->description =
+ "Transfer data layer(s) (weights, edge sharp, ...) from active to selected meshes";
+
+ /* API callbacks.*/
+ ot->poll = data_transfer_poll;
+ ot->poll_property = data_transfer_poll_property;
+ ot->invoke = WM_menu_invoke;
+ ot->exec = data_transfer_exec;
+ ot->check = data_transfer_check;
+
+ /* Flags.*/
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+
+ /* Properties.*/
+ prop = RNA_def_boolean(ot->srna,
+ "use_reverse_transfer",
+ false,
+ "Reverse Transfer",
+ "Transfer from selected objects to active one");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ RNA_def_boolean(ot->srna,
+ "use_freeze",
+ false,
+ "Freeze Operator",
+ "Prevent changes to settings to re-run the operator, "
+ "handy to change several things at once with heavy geometry");
+
+ /* Data type to transfer. */
+ ot->prop = RNA_def_enum(
+ ot->srna, "data_type", DT_layer_items, 0, "Data Type", "Which data to transfer");
+ RNA_def_boolean(ot->srna,
+ "use_create",
+ true,
+ "Create Data",
+ "Add data layers on destination meshes if needed");
+
+ /* Mapping methods. */
+ RNA_def_enum(ot->srna,
+ "vert_mapping",
+ rna_enum_dt_method_vertex_items,
+ MREMAP_MODE_VERT_NEAREST,
+ "Vertex Mapping",
+ "Method used to map source vertices to destination ones");
+ RNA_def_enum(ot->srna,
+ "edge_mapping",
+ rna_enum_dt_method_edge_items,
+ MREMAP_MODE_EDGE_NEAREST,
+ "Edge Mapping",
+ "Method used to map source edges to destination ones");
+ RNA_def_enum(ot->srna,
+ "loop_mapping",
+ rna_enum_dt_method_loop_items,
+ MREMAP_MODE_LOOP_NEAREST_POLYNOR,
+ "Face Corner Mapping",
+ "Method used to map source faces' corners to destination ones");
+ RNA_def_enum(ot->srna,
+ "poly_mapping",
+ rna_enum_dt_method_poly_items,
+ MREMAP_MODE_POLY_NEAREST,
+ "Face Mapping",
+ "Method used to map source faces to destination ones");
+
+ /* Mapping options and filtering. */
+ RNA_def_boolean(
+ ot->srna,
+ "use_auto_transform",
+ false,
+ "Auto Transform",
+ "Automatically compute transformation to get the best possible match between source and "
+ "destination meshes (WARNING: results will never be as good as manual matching of objects)");
+ RNA_def_boolean(ot->srna,
+ "use_object_transform",
+ true,
+ "Object Transform",
+ "Evaluate source and destination meshes in global space");
+ RNA_def_boolean(ot->srna,
+ "use_max_distance",
+ false,
+ "Only Neighbor Geometry",
+ "Source elements must be closer than given distance from destination one");
+ prop = RNA_def_float(
+ ot->srna,
+ "max_distance",
+ 1.0f,
+ 0.0f,
+ FLT_MAX,
+ "Max Distance",
+ "Maximum allowed distance between source and destination element, for non-topology mappings",
+ 0.0f,
+ 100.0f);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+ prop = RNA_def_float(
+ ot->srna,
+ "ray_radius",
+ 0.0f,
+ 0.0f,
+ FLT_MAX,
+ "Ray Radius",
+ "'Width' of rays (especially useful when raycasting against vertices or edges)",
+ 0.0f,
+ 10.0f);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+ prop = RNA_def_float(
+ ot->srna,
+ "islands_precision",
+ 0.1f,
+ 0.0f,
+ 10.0f,
+ "Islands Precision",
+ "Factor controlling precision of islands handling (the higher, the better the results)",
+ 0.0f,
+ 1.0f);
+ RNA_def_property_subtype(prop, PROP_FACTOR);
+
+ /* How to handle multi-layers types of data. */
+ prop = RNA_def_enum(ot->srna,
+ "layers_select_src",
+ rna_enum_dt_layers_select_src_items,
+ DT_LAYERS_ACTIVE_SRC,
+ "Source Layers Selection",
+ "Which layers to transfer, in case of multi-layers types");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_itemf);
+
+ prop = RNA_def_enum(ot->srna,
+ "layers_select_dst",
+ rna_enum_dt_layers_select_dst_items,
+ DT_LAYERS_ACTIVE_DST,
+ "Destination Layers Matching",
+ "How to match source and destination layers");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_itemf);
+
+ prop = RNA_def_enum(ot->srna,
+ "mix_mode",
+ rna_enum_dt_mix_mode_items,
+ CDT_MIX_TRANSFER,
+ "Mix Mode",
+ "How to affect destination elements with source values");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_mix_mode_itemf);
+ RNA_def_float(
+ ot->srna,
+ "mix_factor",
+ 1.0f,
+ 0.0f,
+ 1.0f,
+ "Mix Factor",
+ "Factor to use when applying data to destination (exact behavior depends on mix mode)",
+ 0.0f,
+ 1.0f);
}
/******************************************************************************/
@@ -617,120 +758,147 @@ void OBJECT_OT_data_transfer(wmOperatorType *ot)
static bool datalayout_transfer_poll(bContext *C)
{
- return (edit_modifier_poll_generic(C, &RNA_DataTransferModifier, (1 << OB_MESH)) || data_transfer_poll(C));
+ return (edit_modifier_poll_generic(C, &RNA_DataTransferModifier, (1 << OB_MESH)) ||
+ data_transfer_poll(C));
}
static int datalayout_transfer_exec(bContext *C, wmOperator *op)
{
- Object *ob_act = ED_object_active_context(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- DataTransferModifierData *dtmd;
-
- dtmd = (DataTransferModifierData *)edit_modifier_property_get(op, ob_act, eModifierType_DataTransfer);
-
- /* If we have a modifier, we transfer data layout from this modifier's source object to active one.
- * Else, we transfer data layout from active object to all selected ones. */
- if (dtmd) {
- Object *ob_src = dtmd->ob_source;
- Object *ob_dst = ob_act;
-
- const bool use_delete = false; /* Never when used from modifier, for now. */
-
- if (!ob_src) {
- return OPERATOR_CANCELLED;
- }
-
- Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
-
- BKE_object_data_transfer_layout(depsgraph, scene_eval, ob_src_eval, ob_dst, dtmd->data_types, use_delete,
- dtmd->layers_select_src, dtmd->layers_select_dst);
-
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
- }
- else {
- Object *ob_src = ob_act;
-
- ListBase ctx_objects;
- CollectionPointerLink *ctx_ob_dst;
-
- const int data_type = RNA_enum_get(op->ptr, "data_type");
- const bool use_delete = RNA_boolean_get(op->ptr, "use_delete");
-
- const int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
- const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
- int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
- int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
- const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);
-
- if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
- layers_select_src[fromto_idx] = layers_src;
- layers_select_dst[fromto_idx] = layers_dst;
- }
-
- Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
-
- data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, false);
-
- for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) {
- Object *ob_dst = ctx_ob_dst->ptr.data;
- if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, false)) {
- BKE_object_data_transfer_layout(depsgraph, scene_eval, ob_src_eval, ob_dst, data_type, use_delete,
- layers_select_src, layers_select_dst);
- }
-
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
- }
-
- BLI_freelistN(&ctx_objects);
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
-
- return OPERATOR_FINISHED;
+ Object *ob_act = ED_object_active_context(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ DataTransferModifierData *dtmd;
+
+ dtmd = (DataTransferModifierData *)edit_modifier_property_get(
+ op, ob_act, eModifierType_DataTransfer);
+
+ /* If we have a modifier, we transfer data layout from this modifier's source object to active one.
+ * Else, we transfer data layout from active object to all selected ones. */
+ if (dtmd) {
+ Object *ob_src = dtmd->ob_source;
+ Object *ob_dst = ob_act;
+
+ const bool use_delete = false; /* Never when used from modifier, for now. */
+
+ if (!ob_src) {
+ return OPERATOR_CANCELLED;
+ }
+
+ Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
+
+ BKE_object_data_transfer_layout(depsgraph,
+ scene_eval,
+ ob_src_eval,
+ ob_dst,
+ dtmd->data_types,
+ use_delete,
+ dtmd->layers_select_src,
+ dtmd->layers_select_dst);
+
+ DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
+ }
+ else {
+ Object *ob_src = ob_act;
+
+ ListBase ctx_objects;
+ CollectionPointerLink *ctx_ob_dst;
+
+ const int data_type = RNA_enum_get(op->ptr, "data_type");
+ const bool use_delete = RNA_boolean_get(op->ptr, "use_delete");
+
+ const int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
+ const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
+ int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
+ int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
+ const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);
+
+ if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
+ layers_select_src[fromto_idx] = layers_src;
+ layers_select_dst[fromto_idx] = layers_dst;
+ }
+
+ Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
+
+ data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, false);
+
+ for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) {
+ Object *ob_dst = ctx_ob_dst->ptr.data;
+ if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, false)) {
+ BKE_object_data_transfer_layout(depsgraph,
+ scene_eval,
+ ob_src_eval,
+ ob_dst,
+ data_type,
+ use_delete,
+ layers_select_src,
+ layers_select_dst);
+ }
+
+ DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
+ }
+
+ BLI_freelistN(&ctx_objects);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+
+ return OPERATOR_FINISHED;
}
static int datalayout_transfer_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (edit_modifier_invoke_properties(C, op)) {
- return datalayout_transfer_exec(C, op);
- }
- else {
- return WM_menu_invoke(C, op, event);
- }
+ if (edit_modifier_invoke_properties(C, op)) {
+ return datalayout_transfer_exec(C, op);
+ }
+ else {
+ return WM_menu_invoke(C, op, event);
+ }
}
void OBJECT_OT_datalayout_transfer(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- ot->name = "Transfer Mesh Data Layout";
- ot->description = "Transfer layout of data layer(s) from active to selected meshes";
- ot->idname = "OBJECT_OT_datalayout_transfer";
-
- ot->poll = datalayout_transfer_poll;
- ot->poll_property = data_transfer_poll_property;
- ot->invoke = datalayout_transfer_invoke;
- ot->exec = datalayout_transfer_exec;
- ot->check = data_transfer_check;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
-
- /* Properties.*/
- edit_modifier_properties(ot);
-
- /* Data type to transfer. */
- ot->prop = RNA_def_enum(ot->srna, "data_type", DT_layer_items, 0, "Data Type", "Which data to transfer");
- RNA_def_boolean(ot->srna, "use_delete", false, "Exact Match",
- "Also delete some data layers from destination if necessary, so that it matches exactly source");
-
- /* How to handle multi-layers types of data. */
- prop = RNA_def_enum(ot->srna, "layers_select_src", rna_enum_dt_layers_select_src_items, DT_LAYERS_ACTIVE_SRC,
- "Source Layers Selection", "Which layers to transfer, in case of multi-layers types");
- RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_src_itemf);
-
- prop = RNA_def_enum(ot->srna, "layers_select_dst", rna_enum_dt_layers_select_dst_items, DT_LAYERS_ACTIVE_DST,
- "Destination Layers Matching", "How to match source and destination layers");
- RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_dst_itemf);
+ PropertyRNA *prop;
+
+ ot->name = "Transfer Mesh Data Layout";
+ ot->description = "Transfer layout of data layer(s) from active to selected meshes";
+ ot->idname = "OBJECT_OT_datalayout_transfer";
+
+ ot->poll = datalayout_transfer_poll;
+ ot->poll_property = data_transfer_poll_property;
+ ot->invoke = datalayout_transfer_invoke;
+ ot->exec = datalayout_transfer_exec;
+ ot->check = data_transfer_check;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+
+ /* Properties.*/
+ edit_modifier_properties(ot);
+
+ /* Data type to transfer. */
+ ot->prop = RNA_def_enum(
+ ot->srna, "data_type", DT_layer_items, 0, "Data Type", "Which data to transfer");
+ RNA_def_boolean(ot->srna,
+ "use_delete",
+ false,
+ "Exact Match",
+ "Also delete some data layers from destination if necessary, so that it matches "
+ "exactly source");
+
+ /* How to handle multi-layers types of data. */
+ prop = RNA_def_enum(ot->srna,
+ "layers_select_src",
+ rna_enum_dt_layers_select_src_items,
+ DT_LAYERS_ACTIVE_SRC,
+ "Source Layers Selection",
+ "Which layers to transfer, in case of multi-layers types");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_src_itemf);
+
+ prop = RNA_def_enum(ot->srna,
+ "layers_select_dst",
+ rna_enum_dt_layers_select_dst_items,
+ DT_LAYERS_ACTIVE_DST,
+ "Destination Layers Matching",
+ "How to match source and destination layers");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_dst_itemf);
}
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index ce1a7306773..4e532b0ab41 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -27,7 +27,7 @@
#include <time.h>
#include <float.h>
#include <ctype.h>
-#include <stddef.h> //for offsetof
+#include <stddef.h> //for offsetof
#include "MEM_guardedalloc.h"
@@ -114,285 +114,298 @@
/* prototypes */
typedef struct MoveToCollectionData MoveToCollectionData;
-static void move_to_collection_menus_items(struct uiLayout *layout, struct MoveToCollectionData *menu);
+static void move_to_collection_menus_items(struct uiLayout *layout,
+ struct MoveToCollectionData *menu);
/* ************* XXX **************** */
-static void error(const char *UNUSED(arg)) {}
+static void error(const char *UNUSED(arg))
+{
+}
/* port over here */
-static void error_libdata(void) {}
+static void error_libdata(void)
+{
+}
Object *ED_object_context(bContext *C)
{
- return CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+ return CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
}
/* find the correct active object per context
* note: context can be NULL when called from a enum with PROP_ENUM_NO_CONTEXT */
Object *ED_object_active_context(bContext *C)
{
- Object *ob = NULL;
- if (C) {
- ob = ED_object_context(C);
- if (!ob) ob = CTX_data_active_object(C);
- }
- return ob;
+ Object *ob = NULL;
+ if (C) {
+ ob = ED_object_context(C);
+ if (!ob)
+ ob = CTX_data_active_object(C);
+ }
+ return ob;
}
/* ********************** object hiding *************************** */
static bool object_hide_poll(bContext *C)
{
- if (CTX_wm_space_outliner(C) != NULL) {
- return ED_outliner_collections_editor_poll(C);
- }
- else {
- return ED_operator_view3d_active(C);
- }
+ if (CTX_wm_space_outliner(C) != NULL) {
+ return ED_outliner_collections_editor_poll(C);
+ }
+ else {
+ return ED_operator_view3d_active(C);
+ }
}
static int object_hide_view_clear_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const bool select = RNA_boolean_get(op->ptr, "select");
- bool changed = false;
-
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (base->flag & BASE_HIDDEN) {
- base->flag &= ~BASE_HIDDEN;
- changed = true;
-
- if (select) {
- /* We cannot call `ED_object_base_select` because
- * base is not selectable while it is hidden. */
- base->flag |= BASE_SELECTED;
- BKE_scene_object_base_flag_sync_from_base(base);
- }
- }
- }
-
- if (!changed) {
- return OPERATOR_CANCELLED;
- }
-
- BKE_layer_collection_sync(scene, view_layer);
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool select = RNA_boolean_get(op->ptr, "select");
+ bool changed = false;
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->flag & BASE_HIDDEN) {
+ base->flag &= ~BASE_HIDDEN;
+ changed = true;
+
+ if (select) {
+ /* We cannot call `ED_object_base_select` because
+ * base is not selectable while it is hidden. */
+ base->flag |= BASE_SELECTED;
+ BKE_scene_object_base_flag_sync_from_base(base);
+ }
+ }
+ }
+
+ if (!changed) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_hide_view_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Show Hidden Objects";
- ot->description = "Reveal temporarily hidden objects";
- ot->idname = "OBJECT_OT_hide_view_clear";
+ /* identifiers */
+ ot->name = "Show Hidden Objects";
+ ot->description = "Reveal temporarily hidden objects";
+ ot->idname = "OBJECT_OT_hide_view_clear";
- /* api callbacks */
- ot->exec = object_hide_view_clear_exec;
- ot->poll = object_hide_poll;
+ /* api callbacks */
+ ot->exec = object_hide_view_clear_exec;
+ ot->poll = object_hide_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- PropertyRNA *prop = RNA_def_boolean(ot->srna, "select", true, "Select", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ PropertyRNA *prop = RNA_def_boolean(ot->srna, "select", true, "Select", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
static int object_hide_view_set_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const bool unselected = RNA_boolean_get(op->ptr, "unselected");
- bool changed = false;
-
- /* Hide selected or unselected objects. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (!(base->flag & BASE_VISIBLE)) {
- continue;
- }
-
- if (!unselected) {
- if (base->flag & BASE_SELECTED) {
- ED_object_base_select(base, BA_DESELECT);
- base->flag |= BASE_HIDDEN;
- changed = true;
- }
- }
- else {
- if (!(base->flag & BASE_SELECTED)) {
- ED_object_base_select(base, BA_DESELECT);
- base->flag |= BASE_HIDDEN;
- changed = true;
- }
- }
- }
- if (!changed) {
- return OPERATOR_CANCELLED;
- }
-
- BKE_layer_collection_sync(scene, view_layer);
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool unselected = RNA_boolean_get(op->ptr, "unselected");
+ bool changed = false;
+
+ /* Hide selected or unselected objects. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (!(base->flag & BASE_VISIBLE)) {
+ continue;
+ }
+
+ if (!unselected) {
+ if (base->flag & BASE_SELECTED) {
+ ED_object_base_select(base, BA_DESELECT);
+ base->flag |= BASE_HIDDEN;
+ changed = true;
+ }
+ }
+ else {
+ if (!(base->flag & BASE_SELECTED)) {
+ ED_object_base_select(base, BA_DESELECT);
+ base->flag |= BASE_HIDDEN;
+ changed = true;
+ }
+ }
+ }
+ if (!changed) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_hide_view_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Objects";
- ot->description = "Temporarily hide objects from the viewport";
- ot->idname = "OBJECT_OT_hide_view_set";
-
- /* api callbacks */
- ot->exec = object_hide_view_set_exec;
- ot->poll = object_hide_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- PropertyRNA *prop;
- prop = RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ /* identifiers */
+ ot->name = "Hide Objects";
+ ot->description = "Temporarily hide objects from the viewport";
+ ot->idname = "OBJECT_OT_hide_view_set";
+
+ /* api callbacks */
+ ot->exec = object_hide_view_set_exec;
+ ot->poll = object_hide_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ PropertyRNA *prop;
+ prop = RNA_def_boolean(
+ ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
static int object_hide_collection_exec(bContext *C, wmOperator *op)
{
- wmWindow *win = CTX_wm_window(C);
+ wmWindow *win = CTX_wm_window(C);
- int index = RNA_int_get(op->ptr, "collection_index");
- const bool extend = (win->eventstate->shift != 0) ||
- RNA_boolean_get(op->ptr, "toggle");
+ int index = RNA_int_get(op->ptr, "collection_index");
+ const bool extend = (win->eventstate->shift != 0) || RNA_boolean_get(op->ptr, "toggle");
- if (win->eventstate->alt != 0) {
- index += 10;
- }
+ if (win->eventstate->alt != 0) {
+ index += 10;
+ }
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- LayerCollection *lc = BKE_layer_collection_from_index(view_layer, index);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *lc = BKE_layer_collection_from_index(view_layer, index);
- if (!lc) {
- return OPERATOR_CANCELLED;
- }
+ if (!lc) {
+ return OPERATOR_CANCELLED;
+ }
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
- if (BKE_layer_collection_isolate(scene, view_layer, lc, extend)) {
- DEG_relations_tag_update(CTX_data_main(C));
- }
+ if (BKE_layer_collection_isolate(scene, view_layer, lc, extend)) {
+ DEG_relations_tag_update(CTX_data_main(C));
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
#define COLLECTION_INVALID_INDEX -1
void ED_collection_hide_menu_draw(const bContext *C, uiLayout *layout)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- LayerCollection *lc_scene = view_layer->layer_collections.first;
-
- uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
-
- for (LayerCollection *lc = lc_scene->layer_collections.first; lc; lc = lc->next) {
- int index = BKE_layer_collection_findindex(view_layer, lc);
- uiLayout *row = uiLayoutRow(layout, false);
-
- if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
- continue;
- }
-
- if (lc->collection->flag & COLLECTION_RESTRICT_VIEW) {
- continue;
- }
-
- int icon = ICON_NONE;
- if (BKE_layer_collection_has_selected_objects(view_layer, lc)) {
- icon = ICON_LAYER_ACTIVE;
- }
- else if (lc->runtime_flag & LAYER_COLLECTION_HAS_OBJECTS) {
- icon = ICON_LAYER_USED;
- }
-
- uiItemIntO(row,
- lc->collection->id.name + 2,
- icon,
- "OBJECT_OT_hide_collection",
- "collection_index",
- index);
- }
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *lc_scene = view_layer->layer_collections.first;
+
+ uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
+
+ for (LayerCollection *lc = lc_scene->layer_collections.first; lc; lc = lc->next) {
+ int index = BKE_layer_collection_findindex(view_layer, lc);
+ uiLayout *row = uiLayoutRow(layout, false);
+
+ if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
+ continue;
+ }
+
+ if (lc->collection->flag & COLLECTION_RESTRICT_VIEW) {
+ continue;
+ }
+
+ int icon = ICON_NONE;
+ if (BKE_layer_collection_has_selected_objects(view_layer, lc)) {
+ icon = ICON_LAYER_ACTIVE;
+ }
+ else if (lc->runtime_flag & LAYER_COLLECTION_HAS_OBJECTS) {
+ icon = ICON_LAYER_USED;
+ }
+
+ uiItemIntO(row,
+ lc->collection->id.name + 2,
+ icon,
+ "OBJECT_OT_hide_collection",
+ "collection_index",
+ index);
+ }
}
static int object_hide_collection_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- /* Immediately execute if collection index was specified. */
- int index = RNA_int_get(op->ptr, "collection_index");
- if (index != COLLECTION_INVALID_INDEX) {
- return object_hide_collection_exec(C, op);
- }
+ /* Immediately execute if collection index was specified. */
+ int index = RNA_int_get(op->ptr, "collection_index");
+ if (index != COLLECTION_INVALID_INDEX) {
+ return object_hide_collection_exec(C, op);
+ }
- /* Open popup menu. */
- const char *title = CTX_IFACE_(op->type->translation_context, op->type->name);
- uiPopupMenu *pup = UI_popup_menu_begin(C, title, ICON_GROUP);
- uiLayout *layout = UI_popup_menu_layout(pup);
+ /* Open popup menu. */
+ const char *title = CTX_IFACE_(op->type->translation_context, op->type->name);
+ uiPopupMenu *pup = UI_popup_menu_begin(C, title, ICON_GROUP);
+ uiLayout *layout = UI_popup_menu_layout(pup);
- ED_collection_hide_menu_draw(C, layout);
+ ED_collection_hide_menu_draw(C, layout);
- UI_popup_menu_end(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
void OBJECT_OT_hide_collection(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Collection";
- ot->description = "Show only objects in collection (Shift to extend)";
- ot->idname = "OBJECT_OT_hide_collection";
-
- /* api callbacks */
- ot->exec = object_hide_collection_exec;
- ot->invoke = object_hide_collection_invoke;
- ot->poll = ED_operator_view3d_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* Properties. */
- PropertyRNA *prop;
- prop = RNA_def_int(ot->srna, "collection_index", COLLECTION_INVALID_INDEX, COLLECTION_INVALID_INDEX, INT_MAX,
- "Collection Index", "Index of the collection to change visibility", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
- prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle visibility");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ /* identifiers */
+ ot->name = "Hide Collection";
+ ot->description = "Show only objects in collection (Shift to extend)";
+ ot->idname = "OBJECT_OT_hide_collection";
+
+ /* api callbacks */
+ ot->exec = object_hide_collection_exec;
+ ot->invoke = object_hide_collection_invoke;
+ ot->poll = ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* Properties. */
+ PropertyRNA *prop;
+ prop = RNA_def_int(ot->srna,
+ "collection_index",
+ COLLECTION_INVALID_INDEX,
+ COLLECTION_INVALID_INDEX,
+ INT_MAX,
+ "Collection Index",
+ "Index of the collection to change visibility",
+ 0,
+ INT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle visibility");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
/* ******************* toggle editmode operator ***************** */
static bool mesh_needs_keyindex(Main *bmain, const Mesh *me)
{
- if (me->key) {
- return false; /* will be added */
- }
-
- for (const Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- if ((ob->parent) && (ob->parent->data == me) && ELEM(ob->partype, PARVERT1, PARVERT3)) {
- return true;
- }
- if (ob->data == me) {
- for (const ModifierData *md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Hook) {
- return true;
- }
- }
- }
- }
- return false;
+ if (me->key) {
+ return false; /* will be added */
+ }
+
+ for (const Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
+ if ((ob->parent) && (ob->parent->data == me) && ELEM(ob->partype, PARVERT1, PARVERT3)) {
+ return true;
+ }
+ if (ob->data == me) {
+ for (const ModifierData *md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Hook) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
}
/**
@@ -401,96 +414,96 @@ static bool mesh_needs_keyindex(Main *bmain, const Mesh *me)
*/
static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool freedata)
{
- if (obedit == NULL) {
- return false;
- }
-
- if (obedit->type == OB_MESH) {
- Mesh *me = obedit->data;
- if (me->edit_mesh == NULL) {
- return false;
- }
-
- if (me->edit_mesh->bm->totvert > MESH_MAX_VERTS) {
- error("Too many vertices");
- return false;
- }
-
- EDBM_mesh_load(bmain, obedit);
-
- if (freedata) {
- EDBM_mesh_free(me->edit_mesh);
- MEM_freeN(me->edit_mesh);
- me->edit_mesh = NULL;
- }
- /* will be recalculated as needed. */
- {
- ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
- ED_mesh_mirror_topo_table(NULL, NULL, 'e');
- }
- }
- else if (obedit->type == OB_ARMATURE) {
- const bArmature *arm = obedit->data;
- if (arm->edbo == NULL) {
- return false;
- }
- ED_armature_from_edit(bmain, obedit->data);
- if (freedata) {
- ED_armature_edit_free(obedit->data);
- }
- /* TODO(sergey): Pose channels might have been changed, so need
- * to inform dependency graph about this. But is it really the
- * best place to do this?
- */
- DEG_relations_tag_update(bmain);
- }
- else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
- const Curve *cu = obedit->data;
- if (cu->editnurb == NULL) {
- return false;
- }
- ED_curve_editnurb_load(bmain, obedit);
- if (freedata) {
- ED_curve_editnurb_free(obedit);
- }
- }
- else if (obedit->type == OB_FONT) {
- const Curve *cu = obedit->data;
- if (cu->editfont == NULL) {
- return false;
- }
- ED_curve_editfont_load(obedit);
- if (freedata) {
- ED_curve_editfont_free(obedit);
- }
- }
- else if (obedit->type == OB_LATTICE) {
- const Lattice *lt = obedit->data;
- if (lt->editlatt == NULL) {
- return false;
- }
- BKE_editlattice_load(obedit);
- if (freedata) {
- BKE_editlattice_free(obedit);
- }
- }
- else if (obedit->type == OB_MBALL) {
- const MetaBall *mb = obedit->data;
- if (mb->editelems == NULL) {
- return false;
- }
- ED_mball_editmball_load(obedit);
- if (freedata) {
- ED_mball_editmball_free(obedit);
- }
- }
-
- return true;
+ if (obedit == NULL) {
+ return false;
+ }
+
+ if (obedit->type == OB_MESH) {
+ Mesh *me = obedit->data;
+ if (me->edit_mesh == NULL) {
+ return false;
+ }
+
+ if (me->edit_mesh->bm->totvert > MESH_MAX_VERTS) {
+ error("Too many vertices");
+ return false;
+ }
+
+ EDBM_mesh_load(bmain, obedit);
+
+ if (freedata) {
+ EDBM_mesh_free(me->edit_mesh);
+ MEM_freeN(me->edit_mesh);
+ me->edit_mesh = NULL;
+ }
+ /* will be recalculated as needed. */
+ {
+ ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
+ ED_mesh_mirror_topo_table(NULL, NULL, 'e');
+ }
+ }
+ else if (obedit->type == OB_ARMATURE) {
+ const bArmature *arm = obedit->data;
+ if (arm->edbo == NULL) {
+ return false;
+ }
+ ED_armature_from_edit(bmain, obedit->data);
+ if (freedata) {
+ ED_armature_edit_free(obedit->data);
+ }
+ /* TODO(sergey): Pose channels might have been changed, so need
+ * to inform dependency graph about this. But is it really the
+ * best place to do this?
+ */
+ DEG_relations_tag_update(bmain);
+ }
+ else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ const Curve *cu = obedit->data;
+ if (cu->editnurb == NULL) {
+ return false;
+ }
+ ED_curve_editnurb_load(bmain, obedit);
+ if (freedata) {
+ ED_curve_editnurb_free(obedit);
+ }
+ }
+ else if (obedit->type == OB_FONT) {
+ const Curve *cu = obedit->data;
+ if (cu->editfont == NULL) {
+ return false;
+ }
+ ED_curve_editfont_load(obedit);
+ if (freedata) {
+ ED_curve_editfont_free(obedit);
+ }
+ }
+ else if (obedit->type == OB_LATTICE) {
+ const Lattice *lt = obedit->data;
+ if (lt->editlatt == NULL) {
+ return false;
+ }
+ BKE_editlattice_load(obedit);
+ if (freedata) {
+ BKE_editlattice_free(obedit);
+ }
+ }
+ else if (obedit->type == OB_MBALL) {
+ const MetaBall *mb = obedit->data;
+ if (mb->editelems == NULL) {
+ return false;
+ }
+ ED_mball_editmball_load(obedit);
+ if (freedata) {
+ ED_mball_editmball_free(obedit);
+ }
+ }
+
+ return true;
}
bool ED_object_editmode_load(Main *bmain, Object *obedit)
{
- return ED_object_editmode_load_ex(bmain, obedit, false);
+ return ED_object_editmode_load_ex(bmain, obedit, false);
}
/**
@@ -499,387 +512,379 @@ bool ED_object_editmode_load(Main *bmain, Object *obedit)
*/
bool ED_object_editmode_exit_ex(Main *bmain, Scene *scene, Object *obedit, int flag)
{
- const bool freedata = (flag & EM_FREEDATA) != 0;
-
- if (ED_object_editmode_load_ex(bmain, obedit, freedata) == false) {
- /* in rare cases (background mode) its possible active object
- * is flagged for editmode, without 'obedit' being set [#35489] */
- if (UNLIKELY(obedit && obedit->mode & OB_MODE_EDIT)) {
- obedit->mode &= ~OB_MODE_EDIT;
- }
- return true;
- }
-
- /* freedata only 0 now on file saves and render */
- if (freedata) {
- ListBase pidlist;
- PTCacheID *pid;
-
- /* flag object caches as outdated */
- BKE_ptcache_ids_from_object(&pidlist, obedit, scene, 0);
- for (pid = pidlist.first; pid; pid = pid->next) {
- /* particles don't need reset on geometry change */
- if (pid->type != PTCACHE_TYPE_PARTICLES) {
- pid->cache->flag |= PTCACHE_OUTDATED;
- }
- }
- BLI_freelistN(&pidlist);
-
- BKE_particlesystem_reset_all(obedit);
- BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED);
-
- /* also flush ob recalc, doesn't take much overhead, but used for particles */
- DEG_id_tag_update(&obedit->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
-
- WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
-
- obedit->mode &= ~OB_MODE_EDIT;
- }
-
- return (obedit->mode & OB_MODE_EDIT) == 0;
+ const bool freedata = (flag & EM_FREEDATA) != 0;
+
+ if (ED_object_editmode_load_ex(bmain, obedit, freedata) == false) {
+ /* in rare cases (background mode) its possible active object
+ * is flagged for editmode, without 'obedit' being set [#35489] */
+ if (UNLIKELY(obedit && obedit->mode & OB_MODE_EDIT)) {
+ obedit->mode &= ~OB_MODE_EDIT;
+ }
+ return true;
+ }
+
+ /* freedata only 0 now on file saves and render */
+ if (freedata) {
+ ListBase pidlist;
+ PTCacheID *pid;
+
+ /* flag object caches as outdated */
+ BKE_ptcache_ids_from_object(&pidlist, obedit, scene, 0);
+ for (pid = pidlist.first; pid; pid = pid->next) {
+ /* particles don't need reset on geometry change */
+ if (pid->type != PTCACHE_TYPE_PARTICLES) {
+ pid->cache->flag |= PTCACHE_OUTDATED;
+ }
+ }
+ BLI_freelistN(&pidlist);
+
+ BKE_particlesystem_reset_all(obedit);
+ BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED);
+
+ /* also flush ob recalc, doesn't take much overhead, but used for particles */
+ DEG_id_tag_update(&obedit->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
+
+ obedit->mode &= ~OB_MODE_EDIT;
+ }
+
+ return (obedit->mode & OB_MODE_EDIT) == 0;
}
bool ED_object_editmode_exit(bContext *C, int flag)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- return ED_object_editmode_exit_ex(bmain, scene, obedit, flag);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ return ED_object_editmode_exit_ex(bmain, scene, obedit, flag);
}
bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag)
{
- bool ok = false;
-
- if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob)) {
- return false;
- }
-
- /* this checks actual object->data, for cases when other scenes have it in editmode context */
- if (BKE_object_is_in_editmode(ob)) {
- return true;
- }
-
- if (BKE_object_obdata_is_libdata(ob)) {
- error_libdata();
- return false;
- }
-
- ob->restore_mode = ob->mode;
-
- ob->mode = OB_MODE_EDIT;
-
- if (ob->type == OB_MESH) {
- BMEditMesh *em;
- ok = 1;
-
- const bool use_key_index = mesh_needs_keyindex(bmain, ob->data);
-
- EDBM_mesh_make(ob, scene->toolsettings->selectmode, use_key_index);
-
- em = BKE_editmesh_from_object(ob);
- if (LIKELY(em)) {
- /* order doesn't matter */
- EDBM_mesh_normals_update(em);
- BKE_editmesh_tessface_calc(em);
- }
-
- WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MESH, NULL);
- }
- else if (ob->type == OB_ARMATURE) {
- ok = 1;
- ED_armature_to_edit(ob->data);
- /* to ensure all goes in restposition and without striding */
-
- /* XXX: should this be ID_RECALC_GEOMETRY? */
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
-
- WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_ARMATURE, scene);
- }
- else if (ob->type == OB_FONT) {
- ok = 1;
- ED_curve_editfont_make(ob);
-
- WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_TEXT, scene);
- }
- else if (ob->type == OB_MBALL) {
- ok = 1;
- ED_mball_editmball_make(ob);
-
- WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MBALL, scene);
- }
- else if (ob->type == OB_LATTICE) {
- ok = 1;
- BKE_editlattice_make(ob);
-
- WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_LATTICE, scene);
- }
- else if (ob->type == OB_SURF || ob->type == OB_CURVE) {
- ok = 1;
- ED_curve_editnurb_make(ob);
-
- WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_CURVE, scene);
- }
-
- if (ok) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- else {
- if ((flag & EM_NO_CONTEXT) == 0) {
- ob->mode &= ~OB_MODE_EDIT;
- }
- WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
- }
-
- return (ob->mode & OB_MODE_EDIT) != 0;
+ bool ok = false;
+
+ if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob)) {
+ return false;
+ }
+
+ /* this checks actual object->data, for cases when other scenes have it in editmode context */
+ if (BKE_object_is_in_editmode(ob)) {
+ return true;
+ }
+
+ if (BKE_object_obdata_is_libdata(ob)) {
+ error_libdata();
+ return false;
+ }
+
+ ob->restore_mode = ob->mode;
+
+ ob->mode = OB_MODE_EDIT;
+
+ if (ob->type == OB_MESH) {
+ BMEditMesh *em;
+ ok = 1;
+
+ const bool use_key_index = mesh_needs_keyindex(bmain, ob->data);
+
+ EDBM_mesh_make(ob, scene->toolsettings->selectmode, use_key_index);
+
+ em = BKE_editmesh_from_object(ob);
+ if (LIKELY(em)) {
+ /* order doesn't matter */
+ EDBM_mesh_normals_update(em);
+ BKE_editmesh_tessface_calc(em);
+ }
+
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MESH, NULL);
+ }
+ else if (ob->type == OB_ARMATURE) {
+ ok = 1;
+ ED_armature_to_edit(ob->data);
+ /* to ensure all goes in restposition and without striding */
+
+ /* XXX: should this be ID_RECALC_GEOMETRY? */
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_ARMATURE, scene);
+ }
+ else if (ob->type == OB_FONT) {
+ ok = 1;
+ ED_curve_editfont_make(ob);
+
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_TEXT, scene);
+ }
+ else if (ob->type == OB_MBALL) {
+ ok = 1;
+ ED_mball_editmball_make(ob);
+
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MBALL, scene);
+ }
+ else if (ob->type == OB_LATTICE) {
+ ok = 1;
+ BKE_editlattice_make(ob);
+
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_LATTICE, scene);
+ }
+ else if (ob->type == OB_SURF || ob->type == OB_CURVE) {
+ ok = 1;
+ ED_curve_editnurb_make(ob);
+
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_CURVE, scene);
+ }
+
+ if (ok) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ else {
+ if ((flag & EM_NO_CONTEXT) == 0) {
+ ob->mode &= ~OB_MODE_EDIT;
+ }
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
+ }
+
+ return (ob->mode & OB_MODE_EDIT) != 0;
}
bool ED_object_editmode_enter(bContext *C, int flag)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob;
-
- /* Active layer checked here for view3d,
- * callers that don't want view context can call the extended version. */
- ob = CTX_data_active_object(C);
- if ((ob == NULL) || ID_IS_LINKED(ob)) {
- return false;
- }
- return ED_object_editmode_enter_ex(bmain, scene, ob, flag);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob;
+
+ /* Active layer checked here for view3d,
+ * callers that don't want view context can call the extended version. */
+ ob = CTX_data_active_object(C);
+ if ((ob == NULL) || ID_IS_LINKED(ob)) {
+ return false;
+ }
+ return ED_object_editmode_enter_ex(bmain, scene, ob, flag);
}
static int editmode_toggle_exec(bContext *C, wmOperator *op)
{
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- const int mode_flag = OB_MODE_EDIT;
- const bool is_mode_set = (CTX_data_edit_object(C) != NULL);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- Object *obact = OBACT(view_layer);
-
- if (!is_mode_set) {
- if (!ED_object_mode_compat_set(C, obact, mode_flag, op->reports)) {
- return OPERATOR_CANCELLED;
- }
- }
-
- if (!is_mode_set) {
- ED_object_editmode_enter(C, 0);
- if (obact->mode & mode_flag) {
- FOREACH_SELECTED_OBJECT_BEGIN(view_layer, v3d, ob)
- {
- if ((ob != obact) && (ob->type == obact->type)) {
- ED_object_editmode_enter_ex(bmain, scene, ob, EM_NO_CONTEXT);
- }
- }
- FOREACH_SELECTED_OBJECT_END;
- }
- }
- else {
- ED_object_editmode_exit(C, EM_FREEDATA);
- if ((obact->mode & mode_flag) == 0) {
- FOREACH_OBJECT_BEGIN(view_layer, ob)
- {
- if ((ob != obact) && (ob->type == obact->type)) {
- ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
- }
- }
- FOREACH_OBJECT_END;
- }
- }
-
- ED_space_image_uv_sculpt_update(bmain, CTX_wm_manager(C), scene);
-
- WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
-
- if (G.background == false) {
- WM_toolsystem_update_from_context_view3d(C);
- }
-
- return OPERATOR_FINISHED;
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ const int mode_flag = OB_MODE_EDIT;
+ const bool is_mode_set = (CTX_data_edit_object(C) != NULL);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Object *obact = OBACT(view_layer);
+
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, obact, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ if (!is_mode_set) {
+ ED_object_editmode_enter(C, 0);
+ if (obact->mode & mode_flag) {
+ FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) {
+ if ((ob != obact) && (ob->type == obact->type)) {
+ ED_object_editmode_enter_ex(bmain, scene, ob, EM_NO_CONTEXT);
+ }
+ }
+ FOREACH_SELECTED_OBJECT_END;
+ }
+ }
+ else {
+ ED_object_editmode_exit(C, EM_FREEDATA);
+ if ((obact->mode & mode_flag) == 0) {
+ FOREACH_OBJECT_BEGIN (view_layer, ob) {
+ if ((ob != obact) && (ob->type == obact->type)) {
+ ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
+ }
+ }
+ FOREACH_OBJECT_END;
+ }
+ }
+
+ ED_space_image_uv_sculpt_update(bmain, CTX_wm_manager(C), scene);
+
+ WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
+
+ if (G.background == false) {
+ WM_toolsystem_update_from_context_view3d(C);
+ }
+
+ return OPERATOR_FINISHED;
}
static bool editmode_toggle_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- /* covers proxies too */
- if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob->data))
- return 0;
+ /* covers proxies too */
+ if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob->data))
+ return 0;
- /* if hidden but in edit mode, we still display */
- if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT)) {
- return 0;
- }
+ /* if hidden but in edit mode, we still display */
+ if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT)) {
+ return 0;
+ }
- return OB_TYPE_SUPPORT_EDITMODE(ob->type);
+ return OB_TYPE_SUPPORT_EDITMODE(ob->type);
}
void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Editmode";
- ot->description = "Toggle object's editmode";
- ot->idname = "OBJECT_OT_editmode_toggle";
+ /* identifiers */
+ ot->name = "Toggle Editmode";
+ ot->description = "Toggle object's editmode";
+ ot->idname = "OBJECT_OT_editmode_toggle";
- /* api callbacks */
- ot->exec = editmode_toggle_exec;
- ot->poll = editmode_toggle_poll;
+ /* api callbacks */
+ ot->exec = editmode_toggle_exec;
+ ot->poll = editmode_toggle_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* *************************** */
static int posemode_exec(bContext *C, wmOperator *op)
{
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- Base *base = CTX_data_active_base(C);
-
- /* If the base is NULL it means we have an active object, but the object itself is hidden. */
- if (base == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- Object *obact = base->object;
- const int mode_flag = OB_MODE_POSE;
- bool is_mode_set = (obact->mode & mode_flag) != 0;
-
- if (!is_mode_set) {
- if (!ED_object_mode_compat_set(C, obact, mode_flag, op->reports)) {
- return OPERATOR_CANCELLED;
- }
- }
-
- if (obact->type != OB_ARMATURE) {
- return OPERATOR_PASS_THROUGH;
- }
-
- if (obact == CTX_data_edit_object(C)) {
- ED_object_editmode_exit(C, EM_FREEDATA);
- is_mode_set = false;
- }
-
- if (is_mode_set) {
- bool ok = ED_object_posemode_exit(C, obact);
- if (ok) {
- struct Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- FOREACH_OBJECT_BEGIN(view_layer, ob)
- {
- if ((ob != obact) &&
- (ob->type == OB_ARMATURE) &&
- (ob->mode & mode_flag))
- {
- ED_object_posemode_exit_ex(bmain, ob);
- }
- }
- FOREACH_OBJECT_END;
- }
- }
- else {
- bool ok = ED_object_posemode_enter(C, obact);
- if (ok) {
- struct Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- FOREACH_SELECTED_OBJECT_BEGIN(view_layer, v3d, ob)
- {
- if ((ob != obact) &&
- (ob->type == OB_ARMATURE) &&
- (ob->mode == OB_MODE_OBJECT) &&
- (!ID_IS_LINKED(ob)))
- {
- ED_object_posemode_enter_ex(bmain, ob);
- }
- }
- FOREACH_SELECTED_OBJECT_END;
- }
- }
-
- WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
-
- if (G.background == false) {
- WM_toolsystem_update_from_context_view3d(C);
- }
-
- return OPERATOR_FINISHED;
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ Base *base = CTX_data_active_base(C);
+
+ /* If the base is NULL it means we have an active object, but the object itself is hidden. */
+ if (base == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ Object *obact = base->object;
+ const int mode_flag = OB_MODE_POSE;
+ bool is_mode_set = (obact->mode & mode_flag) != 0;
+
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, obact, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ if (obact->type != OB_ARMATURE) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ if (obact == CTX_data_edit_object(C)) {
+ ED_object_editmode_exit(C, EM_FREEDATA);
+ is_mode_set = false;
+ }
+
+ if (is_mode_set) {
+ bool ok = ED_object_posemode_exit(C, obact);
+ if (ok) {
+ struct Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ FOREACH_OBJECT_BEGIN (view_layer, ob) {
+ if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode & mode_flag)) {
+ ED_object_posemode_exit_ex(bmain, ob);
+ }
+ }
+ FOREACH_OBJECT_END;
+ }
+ }
+ else {
+ bool ok = ED_object_posemode_enter(C, obact);
+ if (ok) {
+ struct Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) {
+ if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode == OB_MODE_OBJECT) &&
+ (!ID_IS_LINKED(ob))) {
+ ED_object_posemode_enter_ex(bmain, ob);
+ }
+ }
+ FOREACH_SELECTED_OBJECT_END;
+ }
+ }
+
+ WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
+
+ if (G.background == false) {
+ WM_toolsystem_update_from_context_view3d(C);
+ }
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_posemode_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Pose Mode";
- ot->idname = "OBJECT_OT_posemode_toggle";
- ot->description = "Enable or disable posing/selecting bones";
+ /* identifiers */
+ ot->name = "Toggle Pose Mode";
+ ot->idname = "OBJECT_OT_posemode_toggle";
+ ot->description = "Enable or disable posing/selecting bones";
- /* api callbacks */
- ot->exec = posemode_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->exec = posemode_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flag */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flag */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************* 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);
-
- /* add/remove modifier as needed */
- if (!md) {
- if (pd && (pd->shape == PFIELD_SHAPE_SURFACE) && !ELEM(pd->forcefield, 0, PFIELD_GUIDE, PFIELD_TEXTURE)) {
- if (ELEM(object->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE)) {
- ED_object_modifier_add(NULL, bmain, scene, object, NULL, eModifierType_Surface);
- }
- }
- }
- else {
- if (!pd || (pd->shape != PFIELD_SHAPE_SURFACE) || ELEM(pd->forcefield, 0, PFIELD_GUIDE, PFIELD_TEXTURE)) {
- ED_object_modifier_remove(NULL, bmain, object, md);
- }
- }
+ PartDeflect *pd = object->pd;
+ ModifierData *md = modifiers_findByType(object, eModifierType_Surface);
+
+ /* add/remove modifier as needed */
+ if (!md) {
+ if (pd && (pd->shape == PFIELD_SHAPE_SURFACE) &&
+ !ELEM(pd->forcefield, 0, PFIELD_GUIDE, PFIELD_TEXTURE)) {
+ if (ELEM(object->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE)) {
+ ED_object_modifier_add(NULL, bmain, scene, object, NULL, eModifierType_Surface);
+ }
+ }
+ }
+ else {
+ if (!pd || (pd->shape != PFIELD_SHAPE_SURFACE) ||
+ ELEM(pd->forcefield, 0, PFIELD_GUIDE, PFIELD_TEXTURE)) {
+ ED_object_modifier_remove(NULL, bmain, object, md);
+ }
+ }
}
static int forcefield_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if (ob->pd == NULL)
- ob->pd = BKE_partdeflect_new(PFIELD_FORCE);
- else if (ob->pd->forcefield == 0)
- ob->pd->forcefield = PFIELD_FORCE;
- else
- ob->pd->forcefield = 0;
+ if (ob->pd == NULL)
+ ob->pd = BKE_partdeflect_new(PFIELD_FORCE);
+ else if (ob->pd->forcefield == 0)
+ ob->pd->forcefield = PFIELD_FORCE;
+ else
+ ob->pd->forcefield = 0;
- ED_object_check_force_modifiers(CTX_data_main(C), CTX_data_scene(C), ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ ED_object_check_force_modifiers(CTX_data_main(C), CTX_data_scene(C), ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_forcefield_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Force Field";
- ot->description = "Toggle object's force field";
- ot->idname = "OBJECT_OT_forcefield_toggle";
+ /* identifiers */
+ ot->name = "Toggle Force Field";
+ ot->description = "Toggle object's force field";
+ ot->idname = "OBJECT_OT_forcefield_toggle";
- /* api callbacks */
- ot->exec = forcefield_toggle_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->exec = forcefield_toggle_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************************************** */
@@ -892,156 +897,166 @@ void OBJECT_OT_forcefield_toggle(wmOperatorType *ot)
*/
void ED_objects_recalculate_paths(bContext *C, Scene *scene, bool current_frame_only)
{
- /* Transform doesn't always have context available to do update. */
- if (C == NULL) {
- return;
- }
-
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ListBase targets = {NULL, NULL};
-
- /* loop over objects in scene */
- CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
- {
- /* set flag to force recalc, then grab path(s) from object */
- ob->avs.recalc |= ANIMVIZ_RECALC_PATHS;
- animviz_get_object_motionpaths(ob, &targets);
- }
- CTX_DATA_END;
-
- /* recalculate paths, then free */
- animviz_calc_motionpaths(depsgraph, bmain, scene, &targets, true, current_frame_only);
- BLI_freelistN(&targets);
-
- if (!current_frame_only) {
- /* Tag objects for copy on write - so paths will draw/redraw
- * For currently frame only we update evaluated object directly. */
- CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
- {
- if (ob->mpath) {
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
- }
- }
- CTX_DATA_END;
- }
+ /* Transform doesn't always have context available to do update. */
+ if (C == NULL) {
+ return;
+ }
+
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ListBase targets = {NULL, NULL};
+
+ /* loop over objects in scene */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ /* set flag to force recalc, then grab path(s) from object */
+ ob->avs.recalc |= ANIMVIZ_RECALC_PATHS;
+ animviz_get_object_motionpaths(ob, &targets);
+ }
+ CTX_DATA_END;
+
+ /* recalculate paths, then free */
+ animviz_calc_motionpaths(depsgraph, bmain, scene, &targets, true, current_frame_only);
+ BLI_freelistN(&targets);
+
+ if (!current_frame_only) {
+ /* Tag objects for copy on write - so paths will draw/redraw
+ * For currently frame only we update evaluated object directly. */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (ob->mpath) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ }
+ CTX_DATA_END;
+ }
}
-
/* show popup to determine settings */
static int object_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if (ob == NULL)
- return OPERATOR_CANCELLED;
+ if (ob == NULL)
+ return OPERATOR_CANCELLED;
- /* set default settings from existing/stored settings */
- {
- bAnimVizSettings *avs = &ob->avs;
+ /* set default settings from existing/stored settings */
+ {
+ bAnimVizSettings *avs = &ob->avs;
- RNA_int_set(op->ptr, "start_frame", avs->path_sf);
- RNA_int_set(op->ptr, "end_frame", avs->path_ef);
- }
+ RNA_int_set(op->ptr, "start_frame", avs->path_sf);
+ RNA_int_set(op->ptr, "end_frame", avs->path_ef);
+ }
- /* 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);
+ /* 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);
}
/* Calculate/recalculate whole paths (avs.path_sf to avs.path_ef) */
static int object_calculate_paths_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- int start = RNA_int_get(op->ptr, "start_frame");
- int end = RNA_int_get(op->ptr, "end_frame");
+ Scene *scene = CTX_data_scene(C);
+ int start = RNA_int_get(op->ptr, "start_frame");
+ int end = RNA_int_get(op->ptr, "end_frame");
- /* set up path data for bones being calculated */
- CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
- {
- bAnimVizSettings *avs = &ob->avs;
+ /* set up path data for bones being calculated */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ bAnimVizSettings *avs = &ob->avs;
- /* grab baking settings from operator settings */
- avs->path_sf = start;
- avs->path_ef = end;
+ /* grab baking settings from operator settings */
+ avs->path_sf = start;
+ avs->path_ef = end;
- /* verify that the selected object has the appropriate settings */
- animviz_verify_motionpaths(op->reports, scene, ob, NULL);
- }
- CTX_DATA_END;
+ /* verify that the selected object has the appropriate settings */
+ animviz_verify_motionpaths(op->reports, scene, ob, NULL);
+ }
+ CTX_DATA_END;
- /* calculate the paths for objects that have them (and are tagged to get refreshed) */
- ED_objects_recalculate_paths(C, scene, false);
+ /* calculate the paths for objects that have them (and are tagged to get refreshed) */
+ ED_objects_recalculate_paths(C, scene, false);
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_paths_calculate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Calculate Object Paths";
- ot->idname = "OBJECT_OT_paths_calculate";
- ot->description = "Calculate motion paths for the selected objects";
-
- /* api callbacks */
- ot->invoke = object_calculate_paths_invoke;
- ot->exec = object_calculate_paths_exec;
- ot->poll = ED_operator_object_active_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_int(ot->srna, "start_frame", 1, MINAFRAME, MAXFRAME, "Start",
- "First frame to calculate object paths on", MINFRAME, MAXFRAME / 2.0);
- RNA_def_int(ot->srna, "end_frame", 250, MINAFRAME, MAXFRAME, "End",
- "Last frame to calculate object paths on", MINFRAME, MAXFRAME / 2.0);
+ /* identifiers */
+ ot->name = "Calculate Object Paths";
+ ot->idname = "OBJECT_OT_paths_calculate";
+ ot->description = "Calculate motion paths for the selected objects";
+
+ /* api callbacks */
+ ot->invoke = object_calculate_paths_invoke;
+ ot->exec = object_calculate_paths_exec;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna,
+ "start_frame",
+ 1,
+ MINAFRAME,
+ MAXFRAME,
+ "Start",
+ "First frame to calculate object paths on",
+ MINFRAME,
+ MAXFRAME / 2.0);
+ RNA_def_int(ot->srna,
+ "end_frame",
+ 250,
+ MINAFRAME,
+ MAXFRAME,
+ "End",
+ "Last frame to calculate object paths on",
+ MINFRAME,
+ MAXFRAME / 2.0);
}
/* --------- */
static bool object_update_paths_poll(bContext *C)
{
- if (ED_operator_object_active_editable(C)) {
- Object *ob = ED_object_active_context(C);
- return (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
- }
+ if (ED_operator_object_active_editable(C)) {
+ Object *ob = ED_object_active_context(C);
+ return (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
+ }
- return false;
+ return false;
}
static int object_update_paths_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- if (scene == NULL)
- return OPERATOR_CANCELLED;
+ if (scene == NULL)
+ return OPERATOR_CANCELLED;
- /* calculate the paths for objects that have them (and are tagged to get refreshed) */
- ED_objects_recalculate_paths(C, scene, false);
+ /* calculate the paths for objects that have them (and are tagged to get refreshed) */
+ ED_objects_recalculate_paths(C, scene, false);
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_paths_update(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Update Object Paths";
- ot->idname = "OBJECT_OT_paths_update";
- ot->description = "Recalculate paths for selected objects";
+ /* identifiers */
+ ot->name = "Update Object Paths";
+ ot->idname = "OBJECT_OT_paths_update";
+ ot->description = "Recalculate paths for selected objects";
- /* api callbakcs */
- ot->exec = object_update_paths_exec;
- ot->poll = object_update_paths_poll;
+ /* api callbakcs */
+ ot->exec = object_update_paths_exec;
+ ot->poll = object_update_paths_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* --------- */
@@ -1049,578 +1064,568 @@ void OBJECT_OT_paths_update(wmOperatorType *ot)
/* Helper for ED_objects_clear_paths() */
static void object_clear_mpath(Object *ob)
{
- if (ob->mpath) {
- animviz_free_motionpath(ob->mpath);
- ob->mpath = NULL;
- ob->avs.path_bakeflag &= ~MOTIONPATH_BAKE_HAS_PATHS;
-
- /* tag object for copy on write - so removed paths don't still show */
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
- }
+ if (ob->mpath) {
+ animviz_free_motionpath(ob->mpath);
+ ob->mpath = NULL;
+ ob->avs.path_bakeflag &= ~MOTIONPATH_BAKE_HAS_PATHS;
+
+ /* tag object for copy on write - so removed paths don't still show */
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
/* Clear motion paths for all objects */
void ED_objects_clear_paths(bContext *C, bool only_selected)
{
- if (only_selected) {
- /* loop over all selected + sedtiable 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 */
- CTX_DATA_BEGIN(C, Object *, ob, editable_objects)
- {
- object_clear_mpath(ob);
- }
- CTX_DATA_END;
- }
+ if (only_selected) {
+ /* loop over all selected + sedtiable 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 */
+ CTX_DATA_BEGIN (C, Object *, ob, editable_objects) {
+ object_clear_mpath(ob);
+ }
+ CTX_DATA_END;
+ }
}
/* operator callback for this */
static int object_clear_paths_exec(bContext *C, wmOperator *op)
{
- bool only_selected = RNA_boolean_get(op->ptr, "only_selected");
+ bool only_selected = RNA_boolean_get(op->ptr, "only_selected");
- /* use the backend function for this */
- ED_objects_clear_paths(C, only_selected);
+ /* use the backend function for this */
+ ED_objects_clear_paths(C, only_selected);
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* operator callback/wrapper */
static int object_clear_paths_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
{
- if ((evt->shift) && !RNA_struct_property_is_set(op->ptr, "only_selected")) {
- RNA_boolean_set(op->ptr, "only_selected", true);
- }
- return object_clear_paths_exec(C, op);
+ if ((evt->shift) && !RNA_struct_property_is_set(op->ptr, "only_selected")) {
+ RNA_boolean_set(op->ptr, "only_selected", true);
+ }
+ return object_clear_paths_exec(C, op);
}
void OBJECT_OT_paths_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Object Paths";
- ot->idname = "OBJECT_OT_paths_clear";
- ot->description = "Clear path caches for all objects, hold Shift key for selected objects only";
-
- /* api callbacks */
- ot->invoke = object_clear_paths_invoke;
- ot->exec = object_clear_paths_exec;
- ot->poll = ED_operator_object_active_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_boolean(ot->srna, "only_selected", false, "Only Selected",
- "Only clear paths from selected objects");
- RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+ /* identifiers */
+ ot->name = "Clear Object Paths";
+ ot->idname = "OBJECT_OT_paths_clear";
+ ot->description = "Clear path caches for all objects, hold Shift key for selected objects only";
+
+ /* api callbacks */
+ ot->invoke = object_clear_paths_invoke;
+ ot->exec = object_clear_paths_exec;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_boolean(
+ ot->srna, "only_selected", false, "Only Selected", "Only clear paths from selected objects");
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
}
/* --------- */
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 */
- CTX_DATA_BEGIN(C, Object *, ob, editable_objects)
- {
- /* use Preview Range or Full Frame Range - whichever is in use */
- ob->avs.path_sf = PSFRA;
- ob->avs.path_ef = PEFRA;
-
- /* tag for updates */
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- }
- CTX_DATA_END;
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+
+ /* loop over all edtiable 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;
+ ob->avs.path_ef = PEFRA;
+
+ /* tag for updates */
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ }
+ CTX_DATA_END;
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_paths_range_update(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Update Range from Scene";
- ot->idname = "OBJECT_OT_paths_range_update";
- ot->description = "Update frame range for motion paths from the Scene's current frame range";
+ /* identifiers */
+ ot->name = "Update Range from Scene";
+ ot->idname = "OBJECT_OT_paths_range_update";
+ ot->description = "Update frame range for motion paths from the Scene's current frame range";
- /* callbacks */
- ot->exec = object_update_paths_range_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* callbacks */
+ ot->exec = object_update_paths_range_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/********************** Smooth/Flat *********************/
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;
-
- CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
- {
- data = ob->data;
-
- if (data && ID_IS_LINKED(data)) {
- linked_data = true;
- continue;
- }
-
- if (ob->type == OB_MESH) {
- BKE_mesh_smooth_flag_set(ob, !clear);
-
- 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;
- }
- else if (ELEM(ob->type, OB_SURF, OB_CURVE)) {
- cu = ob->data;
-
- for (nu = cu->nurb.first; nu; nu = nu->next) {
- if (!clear) nu->flag |= ME_SMOOTH;
- else nu->flag &= ~ME_SMOOTH;
- }
-
- 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)
- BKE_report(op->reports, RPT_WARNING, "Can't edit linked mesh or curve data");
-
- return (done) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ ID *data;
+ Curve *cu;
+ Nurb *nu;
+ int clear = (STREQ(op->idname, "OBJECT_OT_shade_flat"));
+ bool done = false, linked_data = false;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ data = ob->data;
+
+ if (data && ID_IS_LINKED(data)) {
+ linked_data = true;
+ continue;
+ }
+
+ if (ob->type == OB_MESH) {
+ BKE_mesh_smooth_flag_set(ob, !clear);
+
+ 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;
+ }
+ else if (ELEM(ob->type, OB_SURF, OB_CURVE)) {
+ cu = ob->data;
+
+ for (nu = cu->nurb.first; nu; nu = nu->next) {
+ if (!clear)
+ nu->flag |= ME_SMOOTH;
+ else
+ nu->flag &= ~ME_SMOOTH;
+ }
+
+ 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)
+ BKE_report(op->reports, RPT_WARNING, "Can't edit linked mesh or curve data");
+
+ return (done) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static bool shade_poll(bContext *C)
{
- return (CTX_data_edit_object(C) == NULL);
+ return (CTX_data_edit_object(C) == NULL);
}
void OBJECT_OT_shade_flat(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Shade Flat";
- ot->description = "Render and display faces uniform, using Face Normals";
- ot->idname = "OBJECT_OT_shade_flat";
+ /* identifiers */
+ ot->name = "Shade Flat";
+ ot->description = "Render and display faces uniform, using Face Normals";
+ ot->idname = "OBJECT_OT_shade_flat";
- /* api callbacks */
- ot->poll = shade_poll;
- ot->exec = shade_smooth_exec;
+ /* api callbacks */
+ ot->poll = shade_poll;
+ ot->exec = shade_smooth_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void OBJECT_OT_shade_smooth(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Shade Smooth";
- ot->description = "Render and display faces smooth, using interpolated Vertex Normals";
- ot->idname = "OBJECT_OT_shade_smooth";
+ /* identifiers */
+ ot->name = "Shade Smooth";
+ ot->description = "Render and display faces smooth, using interpolated Vertex Normals";
+ ot->idname = "OBJECT_OT_shade_smooth";
- /* api callbacks */
- ot->poll = shade_poll;
- ot->exec = shade_smooth_exec;
+ /* api callbacks */
+ ot->poll = shade_poll;
+ ot->exec = shade_smooth_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************** */
-static const EnumPropertyItem *object_mode_set_itemsf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *object_mode_set_itemsf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- const EnumPropertyItem *input = rna_enum_object_mode_items;
- EnumPropertyItem *item = NULL;
- Object *ob;
- int totitem = 0;
-
- if (!C) /* needed for docs */
- return rna_enum_object_mode_items;
-
- ob = CTX_data_active_object(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);
- while (input->identifier) {
- if ((input->value == OB_MODE_EDIT && OB_TYPE_SUPPORT_EDITMODE(ob->type)) ||
- (input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) ||
- (input->value == OB_MODE_PARTICLE_EDIT && use_mode_particle_edit) ||
- (ELEM(input->value, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT,
- OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT) && (ob->type == OB_MESH)) ||
- (ELEM(input->value, OB_MODE_EDIT_GPENCIL, OB_MODE_PAINT_GPENCIL,
- OB_MODE_SCULPT_GPENCIL, OB_MODE_WEIGHT_GPENCIL) && (ob->type == OB_GPENCIL)) ||
- (input->value == OB_MODE_OBJECT))
- {
- RNA_enum_item_add(&item, &totitem, input);
- }
- input++;
- }
- }
- else {
- /* We need at least this one! */
- RNA_enum_items_add_value(&item, &totitem, input, OB_MODE_OBJECT);
- }
-
- RNA_enum_item_end(&item, &totitem);
-
- *r_free = true;
-
- return item;
+ const EnumPropertyItem *input = rna_enum_object_mode_items;
+ EnumPropertyItem *item = NULL;
+ Object *ob;
+ int totitem = 0;
+
+ if (!C) /* needed for docs */
+ return rna_enum_object_mode_items;
+
+ ob = CTX_data_active_object(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);
+ while (input->identifier) {
+ if ((input->value == OB_MODE_EDIT && OB_TYPE_SUPPORT_EDITMODE(ob->type)) ||
+ (input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) ||
+ (input->value == OB_MODE_PARTICLE_EDIT && use_mode_particle_edit) ||
+ (ELEM(input->value,
+ OB_MODE_SCULPT,
+ OB_MODE_VERTEX_PAINT,
+ OB_MODE_WEIGHT_PAINT,
+ OB_MODE_TEXTURE_PAINT) &&
+ (ob->type == OB_MESH)) ||
+ (ELEM(input->value,
+ OB_MODE_EDIT_GPENCIL,
+ OB_MODE_PAINT_GPENCIL,
+ OB_MODE_SCULPT_GPENCIL,
+ OB_MODE_WEIGHT_GPENCIL) &&
+ (ob->type == OB_GPENCIL)) ||
+ (input->value == OB_MODE_OBJECT)) {
+ RNA_enum_item_add(&item, &totitem, input);
+ }
+ input++;
+ }
+ }
+ else {
+ /* We need at least this one! */
+ RNA_enum_items_add_value(&item, &totitem, input, OB_MODE_OBJECT);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+
+ *r_free = true;
+
+ 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);
+ /* 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_or_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;
- const bool toggle = RNA_boolean_get(op->ptr, "toggle");
-
- if (use_submode) {
- /* When not changing modes use submodes, see: T55162. */
- if (toggle == false) {
- if (mode == restore_mode) {
- switch (mode) {
- case OB_MODE_EDIT:
- WM_menu_name_call(C, "VIEW3D_MT_edit_mesh_select_mode", WM_OP_INVOKE_REGION_WIN);
- return OPERATOR_INTERFACE;
- default:
- break;
- }
- }
- }
- }
-
- /* 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)) {
- mode = OB_MODE_EDIT_GPENCIL;
- }
-
- if (!ob || !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) {
- /* Special case for Object mode! */
- if (mode == OB_MODE_OBJECT && restore_mode == OB_MODE_OBJECT && ob->restore_mode != OB_MODE_OBJECT) {
- ED_object_mode_toggle(C, ob->restore_mode);
- }
- else if (ob->mode == mode) {
- /* For toggling, store old mode so we know what to go back to */
- ob->restore_mode = restore_mode;
- }
- else if (ob->restore_mode != OB_MODE_OBJECT && ob->restore_mode != mode) {
- ED_object_mode_toggle(C, ob->restore_mode);
- }
- }
-
- /* if type is OB_GPENCIL, set cursor mode */
- if ((ob) && (ob->type == OB_GPENCIL)) {
- if (ob->data) {
- bGPdata *gpd = (bGPdata *)ob->data;
- ED_gpencil_setup_modes(C, gpd, ob->mode);
- }
- }
-
- return OPERATOR_FINISHED;
+ bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_or_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;
+ const bool toggle = RNA_boolean_get(op->ptr, "toggle");
+
+ if (use_submode) {
+ /* When not changing modes use submodes, see: T55162. */
+ if (toggle == false) {
+ if (mode == restore_mode) {
+ switch (mode) {
+ case OB_MODE_EDIT:
+ WM_menu_name_call(C, "VIEW3D_MT_edit_mesh_select_mode", WM_OP_INVOKE_REGION_WIN);
+ return OPERATOR_INTERFACE;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ /* 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)) {
+ mode = OB_MODE_EDIT_GPENCIL;
+ }
+
+ if (!ob || !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) {
+ /* Special case for Object mode! */
+ if (mode == OB_MODE_OBJECT && restore_mode == OB_MODE_OBJECT &&
+ ob->restore_mode != OB_MODE_OBJECT) {
+ ED_object_mode_toggle(C, ob->restore_mode);
+ }
+ else if (ob->mode == mode) {
+ /* For toggling, store old mode so we know what to go back to */
+ ob->restore_mode = restore_mode;
+ }
+ else if (ob->restore_mode != OB_MODE_OBJECT && ob->restore_mode != mode) {
+ ED_object_mode_toggle(C, ob->restore_mode);
+ }
+ }
+
+ /* if type is OB_GPENCIL, set cursor mode */
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ if (ob->data) {
+ bGPdata *gpd = (bGPdata *)ob->data;
+ ED_gpencil_setup_modes(C, gpd, ob->mode);
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_mode_set(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Set Object Mode";
- ot->description = "Sets the object interaction mode";
- ot->idname = "OBJECT_OT_mode_set";
+ /* identifiers */
+ ot->name = "Set Object Mode";
+ ot->description = "Sets the object interaction mode";
+ ot->idname = "OBJECT_OT_mode_set";
- /* api callbacks */
- ot->exec = object_mode_set_exec;
+ /* api callbacks */
+ ot->exec = object_mode_set_exec;
- ot->poll = object_mode_set_poll; //ED_operator_object_active_editable;
+ ot->poll = object_mode_set_poll; //ED_operator_object_active_editable;
- /* flags */
- ot->flag = 0; /* no register/undo here, leave it to operators being called */
+ /* flags */
+ ot->flag = 0; /* no register/undo here, leave it to operators being called */
- ot->prop = RNA_def_enum(ot->srna, "mode", rna_enum_object_mode_items, OB_MODE_OBJECT, "Mode", "");
- RNA_def_enum_funcs(ot->prop, object_mode_set_itemsf);
- RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+ ot->prop = RNA_def_enum(
+ ot->srna, "mode", rna_enum_object_mode_items, OB_MODE_OBJECT, "Mode", "");
+ RNA_def_enum_funcs(ot->prop, object_mode_set_itemsf);
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
void OBJECT_OT_mode_set_or_submode(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Set Object Mode or Submode";
- ot->description = "Sets the object interaction mode";
- ot->idname = "OBJECT_OT_mode_set_or_submode";
+ /* identifiers */
+ ot->name = "Set Object Mode or Submode";
+ ot->description = "Sets the object interaction mode";
+ ot->idname = "OBJECT_OT_mode_set_or_submode";
- /* api callbacks */
- ot->exec = object_mode_set_exec;
+ /* api callbacks */
+ ot->exec = object_mode_set_exec;
- ot->poll = object_mode_set_poll; //ED_operator_object_active_editable;
+ ot->poll = object_mode_set_poll; //ED_operator_object_active_editable;
- /* flags */
- ot->flag = 0; /* no register/undo here, leave it to operators being called */
+ /* flags */
+ ot->flag = 0; /* no register/undo here, leave it to operators being called */
- ot->prop = RNA_def_enum(ot->srna, "mode", rna_enum_object_mode_items, OB_MODE_OBJECT, "Mode", "");
- RNA_def_enum_funcs(ot->prop, object_mode_set_itemsf);
- RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+ ot->prop = RNA_def_enum(
+ ot->srna, "mode", rna_enum_object_mode_items, OB_MODE_OBJECT, "Mode", "");
+ RNA_def_enum_funcs(ot->prop, object_mode_set_itemsf);
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static bool move_to_collection_poll(bContext *C)
{
- if (CTX_wm_space_outliner(C) != NULL) {
- return ED_outliner_collections_editor_poll(C);
- }
- else {
- View3D *v3d = CTX_wm_view3d(C);
-
- if (v3d && v3d->localvd) {
- return false;
- }
-
- return ED_operator_object_active_editable(C);
- }
+ if (CTX_wm_space_outliner(C) != NULL) {
+ return ED_outliner_collections_editor_poll(C);
+ }
+ else {
+ View3D *v3d = CTX_wm_view3d(C);
+
+ if (v3d && v3d->localvd) {
+ return false;
+ }
+
+ return ED_operator_object_active_editable(C);
+ }
}
static int move_to_collection_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, "collection_index");
- const bool is_link = STREQ(op->idname, "OBJECT_OT_link_to_collection");
- const bool is_new = RNA_boolean_get(op->ptr, "is_new");
- Collection *collection;
- ListBase objects = {NULL};
-
- if (!RNA_property_is_set(op->ptr, prop)) {
- BKE_report(op->reports, RPT_ERROR, "No collection selected");
- return OPERATOR_CANCELLED;
- }
-
- int collection_index = RNA_property_int_get(op->ptr, prop);
- collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
- if (collection == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Unexpected error, collection not found");
- return OPERATOR_CANCELLED;
- }
-
- if (CTX_wm_space_outliner(C) != NULL) {
- ED_outliner_selected_objects_get(C, &objects);
- }
- else {
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- BLI_addtail(&objects, BLI_genericNodeN(ob));
- }
- CTX_DATA_END;
- }
-
- if (is_new) {
- char new_collection_name[MAX_NAME];
- RNA_string_get(op->ptr, "new_collection_name", new_collection_name);
- collection = BKE_collection_add(bmain, collection, new_collection_name);
- }
-
- Object *single_object = BLI_listbase_is_single(&objects) ?
- ((LinkData *)objects.first)->data : NULL;
-
- if ((single_object != NULL) &&
- is_link &&
- BLI_findptr(&collection->gobject, single_object, offsetof(CollectionObject, ob)))
- {
- BKE_reportf(op->reports, RPT_ERROR, "%s already in %s", single_object->id.name + 2, collection->id.name + 2);
- BLI_freelistN(&objects);
- return OPERATOR_CANCELLED;
- }
-
- for (LinkData *link = objects.first; link; link = link->next) {
- Object *ob = link->data;
-
- if (!is_link) {
- BKE_collection_object_move(bmain, scene, collection, NULL, ob);
- }
- else {
- BKE_collection_object_add(bmain, collection, ob);
- }
- }
- BLI_freelistN(&objects);
-
- BKE_reportf(op->reports,
- RPT_INFO,
- "%s %s to %s",
- (single_object != NULL) ? single_object->id.name + 2 : "Objects",
- is_link ? "linked" : "moved",
- collection->id.name + 2);
-
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
-
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "collection_index");
+ const bool is_link = STREQ(op->idname, "OBJECT_OT_link_to_collection");
+ const bool is_new = RNA_boolean_get(op->ptr, "is_new");
+ Collection *collection;
+ ListBase objects = {NULL};
+
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ BKE_report(op->reports, RPT_ERROR, "No collection selected");
+ return OPERATOR_CANCELLED;
+ }
+
+ int collection_index = RNA_property_int_get(op->ptr, prop);
+ collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
+ if (collection == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unexpected error, collection not found");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (CTX_wm_space_outliner(C) != NULL) {
+ ED_outliner_selected_objects_get(C, &objects);
+ }
+ else {
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ BLI_addtail(&objects, BLI_genericNodeN(ob));
+ }
+ CTX_DATA_END;
+ }
+
+ if (is_new) {
+ char new_collection_name[MAX_NAME];
+ RNA_string_get(op->ptr, "new_collection_name", new_collection_name);
+ collection = BKE_collection_add(bmain, collection, new_collection_name);
+ }
+
+ Object *single_object = BLI_listbase_is_single(&objects) ? ((LinkData *)objects.first)->data :
+ NULL;
+
+ if ((single_object != NULL) && is_link &&
+ BLI_findptr(&collection->gobject, single_object, offsetof(CollectionObject, ob))) {
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "%s already in %s",
+ single_object->id.name + 2,
+ collection->id.name + 2);
+ BLI_freelistN(&objects);
+ return OPERATOR_CANCELLED;
+ }
+
+ for (LinkData *link = objects.first; link; link = link->next) {
+ Object *ob = link->data;
+
+ if (!is_link) {
+ BKE_collection_object_move(bmain, scene, collection, NULL, ob);
+ }
+ else {
+ BKE_collection_object_add(bmain, collection, ob);
+ }
+ }
+ BLI_freelistN(&objects);
+
+ BKE_reportf(op->reports,
+ RPT_INFO,
+ "%s %s to %s",
+ (single_object != NULL) ? single_object->id.name + 2 : "Objects",
+ is_link ? "linked" : "moved",
+ collection->id.name + 2);
+
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
+
+ return OPERATOR_FINISHED;
}
struct MoveToCollectionData {
- struct MoveToCollectionData *next, *prev;
- int index;
- struct Collection *collection;
- struct ListBase submenus;
- PointerRNA ptr;
- struct wmOperatorType *ot;
+ struct MoveToCollectionData *next, *prev;
+ int index;
+ struct Collection *collection;
+ struct ListBase submenus;
+ PointerRNA ptr;
+ struct wmOperatorType *ot;
};
static int move_to_collection_menus_create(wmOperator *op, MoveToCollectionData *menu)
{
- int index = menu->index;
- for (CollectionChild *child = menu->collection->children.first;
- child != NULL;
- child = child->next)
- {
- Collection *collection = child->collection;
- MoveToCollectionData *submenu = MEM_callocN(sizeof(MoveToCollectionData),
- "MoveToCollectionData submenu - expected memleak");
- BLI_addtail(&menu->submenus, submenu);
- submenu->collection = collection;
- submenu->index = ++index;
- index = move_to_collection_menus_create(op, submenu);
- submenu->ot = op->type;
- }
- return index;
+ int index = menu->index;
+ for (CollectionChild *child = menu->collection->children.first; child != NULL;
+ child = child->next) {
+ Collection *collection = child->collection;
+ MoveToCollectionData *submenu = MEM_callocN(sizeof(MoveToCollectionData),
+ "MoveToCollectionData submenu - expected memleak");
+ BLI_addtail(&menu->submenus, submenu);
+ submenu->collection = collection;
+ submenu->index = ++index;
+ index = move_to_collection_menus_create(op, submenu);
+ submenu->ot = op->type;
+ }
+ return index;
}
static void move_to_collection_menus_free_recursive(MoveToCollectionData *menu)
{
- for (MoveToCollectionData *submenu = menu->submenus.first;
- submenu != NULL;
- submenu = submenu->next)
- {
- move_to_collection_menus_free_recursive(submenu);
- }
- BLI_freelistN(&menu->submenus);
+ for (MoveToCollectionData *submenu = menu->submenus.first; submenu != NULL;
+ submenu = submenu->next) {
+ move_to_collection_menus_free_recursive(submenu);
+ }
+ BLI_freelistN(&menu->submenus);
}
static void move_to_collection_menus_free(MoveToCollectionData **menu)
{
- if (*menu == NULL) {
- return;
- }
+ if (*menu == NULL) {
+ return;
+ }
- move_to_collection_menus_free_recursive(*menu);
- MEM_freeN(*menu);
- *menu = NULL;
+ move_to_collection_menus_free_recursive(*menu);
+ MEM_freeN(*menu);
+ *menu = NULL;
}
static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout, void *menu_v)
{
- MoveToCollectionData *menu = menu_v;
- const char *name = BKE_collection_ui_name_get(menu->collection);
-
- uiItemIntO(layout,
- name,
- ICON_NONE,
- menu->ot->idname,
- "collection_index",
- menu->index);
- uiItemS(layout);
-
- for (MoveToCollectionData *submenu = menu->submenus.first;
- submenu != NULL;
- submenu = submenu->next)
- {
- move_to_collection_menus_items(layout, submenu);
- }
-
- uiItemS(layout);
-
- WM_operator_properties_create_ptr(&menu->ptr, menu->ot);
- RNA_int_set(&menu->ptr, "collection_index", menu->index);
- RNA_boolean_set(&menu->ptr, "is_new", true);
-
- uiItemFullO_ptr(layout,
- menu->ot,
- "New Collection",
- ICON_ADD,
- menu->ptr.data,
- WM_OP_INVOKE_DEFAULT,
- 0,
- NULL);
+ MoveToCollectionData *menu = menu_v;
+ const char *name = BKE_collection_ui_name_get(menu->collection);
+
+ uiItemIntO(layout, name, ICON_NONE, menu->ot->idname, "collection_index", menu->index);
+ uiItemS(layout);
+
+ for (MoveToCollectionData *submenu = menu->submenus.first; submenu != NULL;
+ submenu = submenu->next) {
+ move_to_collection_menus_items(layout, submenu);
+ }
+
+ uiItemS(layout);
+
+ WM_operator_properties_create_ptr(&menu->ptr, menu->ot);
+ RNA_int_set(&menu->ptr, "collection_index", menu->index);
+ RNA_boolean_set(&menu->ptr, "is_new", true);
+
+ uiItemFullO_ptr(
+ layout, menu->ot, "New Collection", ICON_ADD, menu->ptr.data, WM_OP_INVOKE_DEFAULT, 0, NULL);
}
static void move_to_collection_menus_items(uiLayout *layout, MoveToCollectionData *menu)
{
- if (BLI_listbase_is_empty(&menu->submenus)) {
- uiItemIntO(layout,
- menu->collection->id.name + 2,
- ICON_NONE,
- menu->ot->idname,
- "collection_index",
- menu->index);
- }
- else {
- uiItemMenuF(layout,
- menu->collection->id.name + 2,
- ICON_NONE,
- move_to_collection_menu_create,
- menu);
- }
+ if (BLI_listbase_is_empty(&menu->submenus)) {
+ uiItemIntO(layout,
+ menu->collection->id.name + 2,
+ ICON_NONE,
+ menu->ot->idname,
+ "collection_index",
+ menu->index);
+ }
+ else {
+ uiItemMenuF(
+ layout, menu->collection->id.name + 2, ICON_NONE, move_to_collection_menu_create, menu);
+ }
}
/* This is allocated statically because we need this available for the menus creation callback. */
@@ -1628,116 +1633,138 @@ static MoveToCollectionData *master_collection_menu = NULL;
static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- /* Reset the menus data for the current master collection, and free previously allocated data. */
- move_to_collection_menus_free(&master_collection_menu);
+ /* Reset the menus data for the current master collection, and free previously allocated data. */
+ move_to_collection_menus_free(&master_collection_menu);
- PropertyRNA *prop;
- prop = RNA_struct_find_property(op->ptr, "collection_index");
- if (RNA_property_is_set(op->ptr, prop)) {
- int collection_index = RNA_property_int_get(op->ptr, prop);
+ PropertyRNA *prop;
+ prop = RNA_struct_find_property(op->ptr, "collection_index");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ int collection_index = RNA_property_int_get(op->ptr, prop);
- if (RNA_boolean_get(op->ptr, "is_new")) {
- prop = RNA_struct_find_property(op->ptr, "new_collection_name");
- if (!RNA_property_is_set(op->ptr, prop)) {
- char name[MAX_NAME];
- Collection *collection;
+ if (RNA_boolean_get(op->ptr, "is_new")) {
+ prop = RNA_struct_find_property(op->ptr, "new_collection_name");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ char name[MAX_NAME];
+ Collection *collection;
- collection = BKE_collection_from_index(scene, collection_index);
- BKE_collection_new_name_get(collection, name);
+ collection = BKE_collection_from_index(scene, collection_index);
+ 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 move_to_collection_exec(C, op);
- }
+ RNA_property_string_set(op->ptr, prop, name);
+ return WM_operator_props_dialog_popup(C, op, 200, 100);
+ }
+ }
+ return move_to_collection_exec(C, op);
+ }
- Collection *master_collection = BKE_collection_master(scene);
+ Collection *master_collection = BKE_collection_master(scene);
- /* We need the data to be allocated so it's available during menu drawing.
- * Technically we could use wmOperator->customdata. However there is no free callback
- * called to an operator that exit with OPERATOR_INTERFACE to launch a menu.
- *
- * So we are left with a memory that will necessarily leak. It's a small leak though.*/
- if (master_collection_menu == NULL) {
- master_collection_menu = MEM_callocN(sizeof(MoveToCollectionData),
- "MoveToCollectionData menu - expected eventual memleak");
- }
+ /* We need the data to be allocated so it's available during menu drawing.
+ * Technically we could use wmOperator->customdata. However there is no free callback
+ * called to an operator that exit with OPERATOR_INTERFACE to launch a menu.
+ *
+ * So we are left with a memory that will necessarily leak. It's a small leak though.*/
+ if (master_collection_menu == NULL) {
+ master_collection_menu = MEM_callocN(sizeof(MoveToCollectionData),
+ "MoveToCollectionData menu - expected eventual memleak");
+ }
- master_collection_menu->collection = master_collection;
- master_collection_menu->ot = op->type;
- move_to_collection_menus_create(op, master_collection_menu);
+ master_collection_menu->collection = master_collection;
+ master_collection_menu->ot = op->type;
+ move_to_collection_menus_create(op, master_collection_menu);
- uiPopupMenu *pup;
- uiLayout *layout;
+ uiPopupMenu *pup;
+ uiLayout *layout;
- /* Build the menus. */
- const char *title = CTX_IFACE_(op->type->translation_context, op->type->name);
- pup = UI_popup_menu_begin(C, title, ICON_NONE);
- layout = UI_popup_menu_layout(pup);
+ /* Build the menus. */
+ const char *title = CTX_IFACE_(op->type->translation_context, op->type->name);
+ pup = UI_popup_menu_begin(C, title, ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
- uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
- move_to_collection_menu_create(C, layout, master_collection_menu);
+ move_to_collection_menu_create(C, layout, master_collection_menu);
- UI_popup_menu_end(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
void OBJECT_OT_move_to_collection(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Move to Collection";
- ot->description = "Move objects to a scene collection";
- ot->idname = "OBJECT_OT_move_to_collection";
-
- /* api callbacks */
- ot->exec = move_to_collection_exec;
- ot->invoke = move_to_collection_invoke;
- ot->poll = move_to_collection_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- prop = RNA_def_int(ot->srna, "collection_index", COLLECTION_INVALID_INDEX, COLLECTION_INVALID_INDEX, INT_MAX,
- "Collection Index", "Index of the collection to move to", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
- prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
- prop = RNA_def_string(ot->srna, "new_collection_name", NULL, MAX_NAME, "Name",
- "Name of the newly added collection");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Move to Collection";
+ ot->description = "Move objects to a scene collection";
+ ot->idname = "OBJECT_OT_move_to_collection";
+
+ /* api callbacks */
+ ot->exec = move_to_collection_exec;
+ ot->invoke = move_to_collection_invoke;
+ ot->poll = move_to_collection_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_int(ot->srna,
+ "collection_index",
+ COLLECTION_INVALID_INDEX,
+ COLLECTION_INVALID_INDEX,
+ INT_MAX,
+ "Collection Index",
+ "Index of the collection to move to",
+ 0,
+ INT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ prop = RNA_def_string(ot->srna,
+ "new_collection_name",
+ NULL,
+ MAX_NAME,
+ "Name",
+ "Name of the newly added collection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ ot->prop = prop;
}
void OBJECT_OT_link_to_collection(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Link to Collection";
- ot->description = "Link objects to a collection";
- ot->idname = "OBJECT_OT_link_to_collection";
-
- /* api callbacks */
- ot->exec = move_to_collection_exec;
- ot->invoke = move_to_collection_invoke;
- ot->poll = move_to_collection_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- prop = RNA_def_int(ot->srna, "collection_index", COLLECTION_INVALID_INDEX, COLLECTION_INVALID_INDEX, INT_MAX,
- "Collection Index", "Index of the collection to move to", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
- prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
- prop = RNA_def_string(ot->srna, "new_collection_name", NULL, MAX_NAME, "Name",
- "Name of the newly added collection");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Link to Collection";
+ ot->description = "Link objects to a collection";
+ ot->idname = "OBJECT_OT_link_to_collection";
+
+ /* api callbacks */
+ ot->exec = move_to_collection_exec;
+ ot->invoke = move_to_collection_invoke;
+ ot->poll = move_to_collection_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_int(ot->srna,
+ "collection_index",
+ COLLECTION_INVALID_INDEX,
+ COLLECTION_INVALID_INDEX,
+ INT_MAX,
+ "Collection Index",
+ "Index of the collection to move to",
+ 0,
+ INT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ prop = RNA_def_string(ot->srna,
+ "new_collection_name",
+ NULL,
+ MAX_NAME,
+ "Name",
+ "Name of the newly added collection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/object/object_facemap_ops.c b/source/blender/editors/object/object_facemap_ops.c
index c46310c8c9d..a77cfab031d 100644
--- a/source/blender/editors/object/object_facemap_ops.c
+++ b/source/blender/editors/object/object_facemap_ops.c
@@ -55,438 +55,437 @@
/* called while not in editmode */
void ED_object_facemap_face_add(Object *ob, bFaceMap *fmap, int facenum)
{
- int fmap_nr;
- if (GS(((ID *)ob->data)->name) != ID_ME)
- return;
+ int fmap_nr;
+ if (GS(((ID *)ob->data)->name) != ID_ME)
+ return;
- /* get the face map number, exit if it can't be found */
- fmap_nr = BLI_findindex(&ob->fmaps, fmap);
+ /* get the face map number, exit if it can't be found */
+ fmap_nr = BLI_findindex(&ob->fmaps, fmap);
- if (fmap_nr != -1) {
- int *facemap;
- Mesh *me = ob->data;
+ if (fmap_nr != -1) {
+ int *facemap;
+ Mesh *me = ob->data;
- /* if there's is no facemap layer then create one */
- if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL)
- facemap = CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_DEFAULT, NULL, me->totpoly);
+ /* if there's is no facemap layer then create one */
+ if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL)
+ facemap = CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_DEFAULT, NULL, me->totpoly);
- facemap[facenum] = fmap_nr;
- }
+ facemap[facenum] = fmap_nr;
+ }
}
/* called while not in editmode */
void ED_object_facemap_face_remove(Object *ob, bFaceMap *fmap, int facenum)
{
- int fmap_nr;
- if (GS(((ID *)ob->data)->name) != ID_ME)
- return;
+ int fmap_nr;
+ if (GS(((ID *)ob->data)->name) != ID_ME)
+ return;
- /* get the face map number, exit if it can't be found */
- fmap_nr = BLI_findindex(&ob->fmaps, fmap);
+ /* get the face map number, exit if it can't be found */
+ fmap_nr = BLI_findindex(&ob->fmaps, fmap);
- if (fmap_nr != -1) {
- int *facemap;
- Mesh *me = ob->data;
+ if (fmap_nr != -1) {
+ int *facemap;
+ Mesh *me = ob->data;
- if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL)
- return;
+ if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL)
+ return;
- facemap[facenum] = -1;
- }
+ facemap[facenum] = -1;
+ }
}
static void object_fmap_swap_edit_mode(Object *ob, int num1, int num2)
{
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- if (me->edit_mesh) {
- BMEditMesh *em = me->edit_mesh;
- const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
-
- if (cd_fmap_offset != -1) {
- BMFace *efa;
- BMIter iter;
- int *map;
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
-
- if (map) {
- if (num1 != -1) {
- if (*map == num1)
- *map = num2;
- else if (*map == num2)
- *map = num1;
- }
- }
- }
- }
- }
- }
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (me->edit_mesh) {
+ BMEditMesh *em = me->edit_mesh;
+ const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
+
+ if (cd_fmap_offset != -1) {
+ BMFace *efa;
+ BMIter iter;
+ int *map;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
+
+ if (map) {
+ if (num1 != -1) {
+ if (*map == num1)
+ *map = num2;
+ else if (*map == num2)
+ *map = num1;
+ }
+ }
+ }
+ }
+ }
+ }
}
static void object_fmap_swap_object_mode(Object *ob, int num1, int num2)
{
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
- int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP);
- int i;
-
- if (map) {
- for (i = 0; i < me->totpoly; i++) {
- if (num1 != -1) {
- if (map[i] == num1)
- map[i] = num2;
- else if (map[i] == num2)
- map[i] = num1;
- }
- }
- }
- }
- }
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
+ int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP);
+ int i;
+
+ if (map) {
+ for (i = 0; i < me->totpoly; i++) {
+ if (num1 != -1) {
+ if (map[i] == num1)
+ map[i] = num2;
+ else if (map[i] == num2)
+ map[i] = num1;
+ }
+ }
+ }
+ }
+ }
}
static void object_facemap_swap(Object *ob, int num1, int num2)
{
- if (BKE_object_is_in_editmode(ob))
- object_fmap_swap_edit_mode(ob, num1, num2);
- else
- object_fmap_swap_object_mode(ob, num1, num2);
+ if (BKE_object_is_in_editmode(ob))
+ object_fmap_swap_edit_mode(ob, num1, num2);
+ else
+ object_fmap_swap_object_mode(ob, num1, num2);
}
static bool face_map_supported_poll(bContext *C)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
- return (ob && !ob->id.lib && ob->type == OB_MESH && data && !data->lib);
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ return (ob && !ob->id.lib && ob->type == OB_MESH && data && !data->lib);
}
static bool face_map_supported_edit_mode_poll(bContext *C)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
- if (ob && !ob->id.lib && ob->type == OB_MESH && data && !data->lib) {
- if (ob->mode == OB_MODE_EDIT) {
- return true;
- }
- }
- return false;
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ if (ob && !ob->id.lib && ob->type == OB_MESH && data && !data->lib) {
+ if (ob->mode == OB_MODE_EDIT) {
+ return true;
+ }
+ }
+ return false;
}
static int face_map_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- BKE_object_facemap_add(ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ BKE_object_facemap_add(ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_add(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Face Map";
- ot->idname = "OBJECT_OT_face_map_add";
- ot->description = "Add a new face map to the active object";
+ /* identifiers */
+ ot->name = "Add Face Map";
+ ot->idname = "OBJECT_OT_face_map_add";
+ ot->description = "Add a new face map to the active object";
- /* api callbacks */
- ot->poll = face_map_supported_poll;
- ot->exec = face_map_add_exec;
+ /* api callbacks */
+ ot->poll = face_map_supported_poll;
+ ot->exec = face_map_add_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int face_map_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
-
- if (fmap) {
- BKE_object_facemap_remove(ob, fmap);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- }
- return OPERATOR_FINISHED;
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+
+ if (fmap) {
+ BKE_object_facemap_remove(ob, fmap);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_remove(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Face Map";
- ot->idname = "OBJECT_OT_face_map_remove";
- ot->description = "Remove a face map from the active object";
+ /* identifiers */
+ ot->name = "Remove Face Map";
+ ot->idname = "OBJECT_OT_face_map_remove";
+ ot->description = "Remove a face map from the active object";
- /* api callbacks */
- ot->poll = face_map_supported_poll;
- ot->exec = face_map_remove_exec;
+ /* api callbacks */
+ ot->poll = face_map_supported_poll;
+ ot->exec = face_map_remove_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int face_map_assign_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
-
- if (fmap) {
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- BMFace *efa;
- BMIter iter;
- int *map;
- int cd_fmap_offset;
-
- if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP))
- BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
-
- cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
-
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- *map = ob->actfmap - 1;
- }
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- }
- return OPERATOR_FINISHED;
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+
+ if (fmap) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ BMFace *efa;
+ BMIter iter;
+ int *map;
+ int cd_fmap_offset;
+
+ if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP))
+ BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
+
+ cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
+
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ *map = ob->actfmap - 1;
+ }
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_assign(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Assign Face Map";
- ot->idname = "OBJECT_OT_face_map_assign";
- ot->description = "Assign faces to a face map";
+ /* identifiers */
+ ot->name = "Assign Face Map";
+ ot->idname = "OBJECT_OT_face_map_assign";
+ ot->description = "Assign faces to a face map";
- /* api callbacks */
- ot->poll = face_map_supported_edit_mode_poll;
- ot->exec = face_map_assign_exec;
+ /* api callbacks */
+ ot->poll = face_map_supported_edit_mode_poll;
+ ot->exec = face_map_assign_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int face_map_remove_from_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
-
- if (fmap) {
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- BMFace *efa;
- BMIter iter;
- int *map;
- int cd_fmap_offset;
- int mapindex = ob->actfmap - 1;
-
- if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP))
- return OPERATOR_CANCELLED;
-
- cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
-
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && *map == mapindex) {
- *map = -1;
- }
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- }
- return OPERATOR_FINISHED;
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+
+ if (fmap) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ BMFace *efa;
+ BMIter iter;
+ int *map;
+ int cd_fmap_offset;
+ int mapindex = ob->actfmap - 1;
+
+ if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP))
+ return OPERATOR_CANCELLED;
+
+ cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
+
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && *map == mapindex) {
+ *map = -1;
+ }
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_remove_from(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove From Face Map";
- ot->idname = "OBJECT_OT_face_map_remove_from";
- ot->description = "Remove faces from a face map";
+ /* identifiers */
+ ot->name = "Remove From Face Map";
+ ot->idname = "OBJECT_OT_face_map_remove_from";
+ ot->description = "Remove faces from a face map";
- /* api callbacks */
- ot->poll = face_map_supported_edit_mode_poll;
- ot->exec = face_map_remove_from_exec;
+ /* api callbacks */
+ ot->poll = face_map_supported_edit_mode_poll;
+ ot->exec = face_map_remove_from_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static void fmap_select(Object *ob, bool select)
{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- BMFace *efa;
- BMIter iter;
- int *map;
- int cd_fmap_offset;
- int mapindex = ob->actfmap - 1;
-
- if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP))
- BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
-
- cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
-
- if (*map == mapindex) {
- BM_face_select_set(em->bm, efa, select);
- }
- }
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ BMFace *efa;
+ BMIter iter;
+ int *map;
+ int cd_fmap_offset;
+ int mapindex = ob->actfmap - 1;
+
+ if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP))
+ BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
+
+ cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
+
+ if (*map == mapindex) {
+ BM_face_select_set(em->bm, efa, select);
+ }
+ }
}
static int face_map_select_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
- if (fmap) {
- fmap_select(ob, true);
+ if (fmap) {
+ fmap_select(ob, true);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- }
- return OPERATOR_FINISHED;
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_select(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Face Map Faces";
- ot->idname = "OBJECT_OT_face_map_select";
- ot->description = "Select faces belonging to a face map";
+ /* identifiers */
+ ot->name = "Select Face Map Faces";
+ ot->idname = "OBJECT_OT_face_map_select";
+ ot->description = "Select faces belonging to a face map";
- /* api callbacks */
- ot->poll = face_map_supported_edit_mode_poll;
- ot->exec = face_map_select_exec;
+ /* api callbacks */
+ ot->poll = face_map_supported_edit_mode_poll;
+ ot->exec = face_map_select_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int face_map_deselect_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
- if (fmap) {
- fmap_select(ob, false);
+ if (fmap) {
+ fmap_select(ob, false);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- }
- return OPERATOR_FINISHED;
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_deselect(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Deselect Face Map Faces";
- ot->idname = "OBJECT_OT_face_map_deselect";
- ot->description = "Deselect faces belonging to a face map";
+ /* identifiers */
+ ot->name = "Deselect Face Map Faces";
+ ot->idname = "OBJECT_OT_face_map_deselect";
+ ot->description = "Deselect faces belonging to a face map";
- /* api callbacks */
- ot->poll = face_map_supported_edit_mode_poll;
- ot->exec = face_map_deselect_exec;
+ /* api callbacks */
+ ot->poll = face_map_supported_edit_mode_poll;
+ ot->exec = face_map_deselect_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
static int face_map_move_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- bFaceMap *fmap;
- int dir = RNA_enum_get(op->ptr, "direction");
- int pos1, pos2 = -1, count;
-
- fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
- if (!fmap) {
- return OPERATOR_CANCELLED;
- }
-
- count = BLI_listbase_count(&ob->fmaps);
- pos1 = BLI_findindex(&ob->fmaps, fmap);
-
- if (dir == 1) { /*up*/
- void *prev = fmap->prev;
-
- if (prev) {
- pos2 = pos1 - 1;
- }
- else {
- pos2 = count - 1;
- }
-
- BLI_remlink(&ob->fmaps, fmap);
- BLI_insertlinkbefore(&ob->fmaps, prev, fmap);
- }
- else { /*down*/
- void *next = fmap->next;
-
- if (next) {
- pos2 = pos1 + 1;
- }
- else {
- pos2 = 0;
- }
-
- BLI_remlink(&ob->fmaps, fmap);
- BLI_insertlinkafter(&ob->fmaps, next, fmap);
- }
-
- /* iterate through mesh and substitute the indices as necessary */
- object_facemap_swap(ob, pos2, pos1);
-
- ob->actfmap = pos2 + 1;
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
-
- return OPERATOR_FINISHED;
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap;
+ int dir = RNA_enum_get(op->ptr, "direction");
+ int pos1, pos2 = -1, count;
+
+ fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+ if (!fmap) {
+ return OPERATOR_CANCELLED;
+ }
+
+ count = BLI_listbase_count(&ob->fmaps);
+ pos1 = BLI_findindex(&ob->fmaps, fmap);
+
+ if (dir == 1) { /*up*/
+ void *prev = fmap->prev;
+
+ if (prev) {
+ pos2 = pos1 - 1;
+ }
+ else {
+ pos2 = count - 1;
+ }
+
+ BLI_remlink(&ob->fmaps, fmap);
+ BLI_insertlinkbefore(&ob->fmaps, prev, fmap);
+ }
+ else { /*down*/
+ void *next = fmap->next;
+
+ if (next) {
+ pos2 = pos1 + 1;
+ }
+ else {
+ pos2 = 0;
+ }
+
+ BLI_remlink(&ob->fmaps, fmap);
+ BLI_insertlinkafter(&ob->fmaps, next, fmap);
+ }
+
+ /* iterate through mesh and substitute the indices as necessary */
+ object_facemap_swap(ob, pos2, pos1);
+
+ ob->actfmap = pos2 + 1;
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
+
+ return OPERATOR_FINISHED;
}
-
void OBJECT_OT_face_map_move(wmOperatorType *ot)
{
- static EnumPropertyItem fmap_slot_move[] = {
- {1, "UP", 0, "Up", ""},
- {-1, "DOWN", 0, "Down", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Move Face Map";
- ot->idname = "OBJECT_OT_face_map_move";
- ot->description = "Move the active face map up/down in the list";
-
- /* api callbacks */
- ot->poll = face_map_supported_poll;
- ot->exec = face_map_move_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "direction", fmap_slot_move, 0, "Direction", "Direction to move, UP or DOWN");
+ static EnumPropertyItem fmap_slot_move[] = {
+ {1, "UP", 0, "Up", ""},
+ {-1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Move Face Map";
+ ot->idname = "OBJECT_OT_face_map_move";
+ ot->description = "Move the active face map up/down in the list";
+
+ /* api callbacks */
+ ot->poll = face_map_supported_poll;
+ ot->exec = face_map_move_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(
+ ot->srna, "direction", fmap_slot_move, 0, "Direction", "Direction to move, UP or DOWN");
}
diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c
index a1f529b3bde..a726e2c9f00 100644
--- a/source/blender/editors/object/object_gpencil_modifier.c
+++ b/source/blender/editors/object/object_gpencil_modifier.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
@@ -63,572 +62,611 @@
/******************************** API ****************************/
GpencilModifierData *ED_object_gpencil_modifier_add(
- ReportList *reports, Main *bmain, Scene *UNUSED(scene), Object *ob, const char *name, int type)
+ 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);
-
- if (ob->type != OB_GPENCIL) {
- BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2);
- return NULL;
- }
+ GpencilModifierData *new_md = NULL;
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(type);
- if (mti->flags & eGpencilModifierTypeFlag_Single) {
- if (BKE_gpencil_modifiers_findByType(ob, type)) {
- BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
- return NULL;
- }
- }
+ if (ob->type != OB_GPENCIL) {
+ BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2);
+ return NULL;
+ }
- /* get new modifier data to add */
- new_md = BKE_gpencil_modifier_new(type);
+ if (mti->flags & eGpencilModifierTypeFlag_Single) {
+ if (BKE_gpencil_modifiers_findByType(ob, type)) {
+ BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
+ return NULL;
+ }
+ }
- BLI_addtail(&ob->greasepencil_modifiers, new_md);
+ /* get new modifier data to add */
+ new_md = BKE_gpencil_modifier_new(type);
- if (name) {
- BLI_strncpy_utf8(new_md->name, name, sizeof(new_md->name));
- }
+ BLI_addtail(&ob->greasepencil_modifiers, new_md);
- /* make sure modifier data has unique name */
- BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, new_md);
+ if (name) {
+ BLI_strncpy_utf8(new_md->name, name, sizeof(new_md->name));
+ }
+ /* make sure modifier data has unique name */
+ BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, new_md);
- bGPdata *gpd = ob->data;
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
- return new_md;
+ return new_md;
}
/* Return true if the object has a modifier of type 'type' other than
* the modifier pointed to be 'exclude', otherwise returns false. */
-static bool UNUSED_FUNCTION(gpencil_object_has_modifier)(
- const Object *ob, const GpencilModifierData *exclude,
- GpencilModifierType type)
+static bool UNUSED_FUNCTION(gpencil_object_has_modifier)(const Object *ob,
+ const GpencilModifierData *exclude,
+ GpencilModifierType type)
{
- GpencilModifierData *md;
+ GpencilModifierData *md;
- for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
- if ((md != exclude) && (md->type == type))
- return true;
- }
+ for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
+ if ((md != exclude) && (md->type == type))
+ return true;
+ }
- return false;
+ return false;
}
-static bool gpencil_object_modifier_remove(
- Main *bmain, Object *ob, GpencilModifierData *md,
- bool *UNUSED(r_sort_depsgraph))
+static bool gpencil_object_modifier_remove(Main *bmain,
+ Object *ob,
+ GpencilModifierData *md,
+ bool *UNUSED(r_sort_depsgraph))
{
- /* It seems on rapid delete it is possible to
- * get called twice on same modifier, so make
- * sure it is in list. */
- if (BLI_findindex(&ob->greasepencil_modifiers, md) == -1) {
- return 0;
- }
+ /* It seems on rapid delete it is possible to
+ * get called twice on same modifier, so make
+ * sure it is in list. */
+ if (BLI_findindex(&ob->greasepencil_modifiers, md) == -1) {
+ return 0;
+ }
- DEG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
- BLI_remlink(&ob->greasepencil_modifiers, md);
- BKE_gpencil_modifier_free(md);
- BKE_object_free_derived_caches(ob);
+ BLI_remlink(&ob->greasepencil_modifiers, md);
+ BKE_gpencil_modifier_free(md);
+ BKE_object_free_derived_caches(ob);
- return 1;
+ return 1;
}
-bool ED_object_gpencil_modifier_remove(ReportList *reports, Main *bmain, Object *ob, GpencilModifierData *md)
+bool ED_object_gpencil_modifier_remove(ReportList *reports,
+ Main *bmain,
+ Object *ob,
+ GpencilModifierData *md)
{
- bool sort_depsgraph = false;
- bool ok;
+ bool sort_depsgraph = false;
+ bool ok;
- ok = gpencil_object_modifier_remove(bmain, ob, md, &sort_depsgraph);
+ ok = gpencil_object_modifier_remove(bmain, ob, md, &sort_depsgraph);
- if (!ok) {
- BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", md->name, ob->id.name);
- return 0;
- }
+ if (!ok) {
+ BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", md->name, ob->id.name);
+ return 0;
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
- return 1;
+ return 1;
}
void ED_object_gpencil_modifier_clear(Main *bmain, Object *ob)
{
- GpencilModifierData *md = ob->greasepencil_modifiers.first;
- bool sort_depsgraph = false;
+ GpencilModifierData *md = ob->greasepencil_modifiers.first;
+ bool sort_depsgraph = false;
- if (!md)
- return;
+ if (!md)
+ return;
- while (md) {
- GpencilModifierData *next_md;
+ while (md) {
+ GpencilModifierData *next_md;
- next_md = md->next;
+ next_md = md->next;
- gpencil_object_modifier_remove(bmain, ob, md, &sort_depsgraph);
+ gpencil_object_modifier_remove(bmain, ob, md, &sort_depsgraph);
- md = next_md;
- }
+ md = next_md;
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
}
-int ED_object_gpencil_modifier_move_up(ReportList *UNUSED(reports), Object *ob, GpencilModifierData *md)
+int ED_object_gpencil_modifier_move_up(ReportList *UNUSED(reports),
+ Object *ob,
+ GpencilModifierData *md)
{
- if (md->prev) {
- BLI_remlink(&ob->greasepencil_modifiers, md);
- BLI_insertlinkbefore(&ob->greasepencil_modifiers, md->prev, md);
- }
+ if (md->prev) {
+ BLI_remlink(&ob->greasepencil_modifiers, md);
+ BLI_insertlinkbefore(&ob->greasepencil_modifiers, md->prev, md);
+ }
- return 1;
+ return 1;
}
-int ED_object_gpencil_modifier_move_down(ReportList *UNUSED(reports), Object *ob, GpencilModifierData *md)
+int ED_object_gpencil_modifier_move_down(ReportList *UNUSED(reports),
+ Object *ob,
+ GpencilModifierData *md)
{
- if (md->next) {
- BLI_remlink(&ob->greasepencil_modifiers, md);
- BLI_insertlinkafter(&ob->greasepencil_modifiers, md->next, md);
- }
+ if (md->next) {
+ BLI_remlink(&ob->greasepencil_modifiers, md);
+ BLI_insertlinkafter(&ob->greasepencil_modifiers, md->next, md);
+ }
- return 1;
+ return 1;
}
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);
-
- if (mti->isDisabled && mti->isDisabled(md, 0)) {
- BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
- return 0;
- }
-
- if (ob->type == OB_GPENCIL) {
- if (ELEM(NULL, ob, ob->data)) {
- return 0;
- }
- else if (mti->bakeModifier == NULL) {
- BKE_report(reports, RPT_ERROR, "Not implemented");
- return 0;
- }
- mti->bakeModifier(bmain, depsgraph, md, ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- else {
- BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
- return 0;
- }
-
- return 1;
-}
-
-int ED_object_gpencil_modifier_apply(
- Main *bmain, ReportList *reports, Depsgraph *depsgraph,
- Object *ob, GpencilModifierData *md, int UNUSED(mode))
-{
-
- if (ob->type == OB_GPENCIL) {
- if (ob->mode != OB_MODE_OBJECT) {
- BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in paint, sculpt or edit mode");
- return 0;
- }
-
- if (((ID *)ob->data)->us > 1) {
- BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
- return 0;
- }
- }
- else if (((ID *)ob->data)->us > 1) {
- BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
- return 0;
- }
-
- if (md != ob->greasepencil_modifiers.first)
- BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");
-
- if (!gpencil_modifier_apply_obdata(reports, bmain, depsgraph, ob, md)) {
- return 0;
- }
-
- BLI_remlink(&ob->greasepencil_modifiers, md);
- BKE_gpencil_modifier_free(md);
-
- return 1;
+ ReportList *reports, Main *bmain, Depsgraph *depsgraph, Object *ob, GpencilModifierData *md)
+{
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+
+ if (mti->isDisabled && mti->isDisabled(md, 0)) {
+ BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
+ return 0;
+ }
+
+ if (ob->type == OB_GPENCIL) {
+ if (ELEM(NULL, ob, ob->data)) {
+ return 0;
+ }
+ else if (mti->bakeModifier == NULL) {
+ BKE_report(reports, RPT_ERROR, "Not implemented");
+ return 0;
+ }
+ mti->bakeModifier(bmain, depsgraph, md, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ else {
+ BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
+ return 0;
+ }
+
+ return 1;
+}
+
+int ED_object_gpencil_modifier_apply(Main *bmain,
+ ReportList *reports,
+ Depsgraph *depsgraph,
+ Object *ob,
+ GpencilModifierData *md,
+ int UNUSED(mode))
+{
+
+ if (ob->type == OB_GPENCIL) {
+ if (ob->mode != OB_MODE_OBJECT) {
+ BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in paint, sculpt or edit mode");
+ return 0;
+ }
+
+ if (((ID *)ob->data)->us > 1) {
+ BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
+ return 0;
+ }
+ }
+ else if (((ID *)ob->data)->us > 1) {
+ BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
+ return 0;
+ }
+
+ if (md != ob->greasepencil_modifiers.first)
+ BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");
+
+ if (!gpencil_modifier_apply_obdata(reports, bmain, depsgraph, ob, md)) {
+ return 0;
+ }
+
+ BLI_remlink(&ob->greasepencil_modifiers, md);
+ BKE_gpencil_modifier_free(md);
+
+ return 1;
}
int ED_object_gpencil_modifier_copy(ReportList *reports, Object *ob, GpencilModifierData *md)
{
- GpencilModifierData *nmd;
- const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
- GpencilModifierType type = md->type;
+ GpencilModifierData *nmd;
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+ GpencilModifierType type = md->type;
- if (mti->flags & eGpencilModifierTypeFlag_Single) {
- if (BKE_gpencil_modifiers_findByType(ob, type)) {
- BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
- return 0;
- }
- }
+ if (mti->flags & eGpencilModifierTypeFlag_Single) {
+ if (BKE_gpencil_modifiers_findByType(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);
- BLI_insertlinkafter(&ob->greasepencil_modifiers, md, nmd);
- BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, nmd);
+ nmd = BKE_gpencil_modifier_new(md->type);
+ BKE_gpencil_modifier_copyData(md, nmd);
+ BLI_insertlinkafter(&ob->greasepencil_modifiers, md, nmd);
+ BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, nmd);
- return 1;
+ return 1;
}
/************************ add modifier operator *********************/
static int gpencil_modifier_add_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- int type = RNA_enum_get(op->ptr, "type");
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ int type = RNA_enum_get(op->ptr, "type");
- if (!ED_object_gpencil_modifier_add(op->reports, bmain, scene, ob, NULL, type))
- return OPERATOR_CANCELLED;
+ if (!ED_object_gpencil_modifier_add(op->reports, bmain, scene, ob, NULL, type))
+ return OPERATOR_CANCELLED;
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static const EnumPropertyItem *gpencil_modifier_add_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *gpencil_modifier_add_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- Object *ob = ED_object_active_context(C);
- EnumPropertyItem *item = NULL;
- const EnumPropertyItem *md_item, *group_item = NULL;
- const GpencilModifierTypeInfo *mti;
- int totitem = 0, a;
+ Object *ob = ED_object_active_context(C);
+ EnumPropertyItem *item = NULL;
+ const EnumPropertyItem *md_item, *group_item = NULL;
+ const GpencilModifierTypeInfo *mti;
+ int totitem = 0, a;
- if (!ob)
- return rna_enum_object_greasepencil_modifier_type_items;
+ if (!ob)
+ return rna_enum_object_greasepencil_modifier_type_items;
- 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);
+ 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);
- if (mti->flags & eGpencilModifierTypeFlag_NoUserAdd)
- continue;
- }
- else {
- group_item = md_item;
- md_item = NULL;
+ if (mti->flags & eGpencilModifierTypeFlag_NoUserAdd)
+ continue;
+ }
+ else {
+ group_item = md_item;
+ md_item = NULL;
- continue;
- }
+ continue;
+ }
- if (group_item) {
- RNA_enum_item_add(&item, &totitem, group_item);
- group_item = NULL;
- }
+ if (group_item) {
+ RNA_enum_item_add(&item, &totitem, group_item);
+ group_item = NULL;
+ }
- RNA_enum_item_add(&item, &totitem, md_item);
- }
+ RNA_enum_item_add(&item, &totitem, md_item);
+ }
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
- return item;
+ return item;
}
void OBJECT_OT_gpencil_modifier_add(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Add Grease Pencil Modifier";
- ot->description = "Add a procedural operation/effect to the active grease pencil object";
- ot->idname = "OBJECT_OT_gpencil_modifier_add";
+ /* identifiers */
+ ot->name = "Add Grease Pencil Modifier";
+ ot->description = "Add a procedural operation/effect to the active grease pencil object";
+ ot->idname = "OBJECT_OT_gpencil_modifier_add";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = gpencil_modifier_add_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = gpencil_modifier_add_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- prop = RNA_def_enum(ot->srna, "type", rna_enum_object_modifier_type_items, eGpencilModifierType_Thick, "Type", "");
- RNA_def_enum_funcs(prop, gpencil_modifier_add_itemf);
- ot->prop = prop;
+ /* properties */
+ prop = RNA_def_enum(ot->srna,
+ "type",
+ rna_enum_object_modifier_type_items,
+ eGpencilModifierType_Thick,
+ "Type",
+ "");
+ RNA_def_enum_funcs(prop, gpencil_modifier_add_itemf);
+ ot->prop = prop;
}
/************************ generic functions for operators using mod names and data context *********************/
static int gpencil_edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
- Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
+ Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
- if (!ob || ID_IS_LINKED(ob)) return 0;
- if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) return 0;
- if (ptr.id.data && ID_IS_LINKED(ptr.id.data)) return 0;
+ if (!ob || ID_IS_LINKED(ob))
+ return 0;
+ if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0)
+ return 0;
+ if (ptr.id.data && ID_IS_LINKED(ptr.id.data))
+ return 0;
- if (ID_IS_STATIC_OVERRIDE(ob)) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from static override");
- return (((GpencilModifierData *)ptr.data)->flag & eGpencilModifierFlag_StaticOverride_Local) != 0;
- }
+ if (ID_IS_STATIC_OVERRIDE(ob)) {
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from static override");
+ return (((GpencilModifierData *)ptr.data)->flag & eGpencilModifierFlag_StaticOverride_Local) !=
+ 0;
+ }
- return 1;
+ return 1;
}
static bool gpencil_edit_modifier_poll(bContext *C)
{
- return gpencil_edit_modifier_poll_generic(C, &RNA_GpencilModifier, 0);
+ return gpencil_edit_modifier_poll_generic(C, &RNA_GpencilModifier, 0);
}
static void gpencil_edit_modifier_properties(wmOperatorType *ot)
{
- PropertyRNA *prop = RNA_def_string(ot->srna, "modifier", NULL, MAX_NAME, "Modifier", "Name of the modifier to edit");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop = RNA_def_string(
+ ot->srna, "modifier", NULL, MAX_NAME, "Modifier", "Name of the modifier to edit");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
static int gpencil_edit_modifier_invoke_properties(bContext *C, wmOperator *op)
{
- GpencilModifierData *md;
+ GpencilModifierData *md;
- if (RNA_struct_property_is_set(op->ptr, "modifier")) {
- return true;
- }
- else {
- PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_GpencilModifier);
- if (ptr.data) {
- md = ptr.data;
- RNA_string_set(op->ptr, "modifier", md->name);
- return true;
- }
- }
+ if (RNA_struct_property_is_set(op->ptr, "modifier")) {
+ return true;
+ }
+ else {
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_GpencilModifier);
+ if (ptr.data) {
+ md = ptr.data;
+ RNA_string_set(op->ptr, "modifier", md->name);
+ return true;
+ }
+ }
- return false;
+ return false;
}
-static GpencilModifierData *gpencil_edit_modifier_property_get(wmOperator *op, Object *ob, int type)
+static GpencilModifierData *gpencil_edit_modifier_property_get(wmOperator *op,
+ Object *ob,
+ int type)
{
- char modifier_name[MAX_NAME];
- GpencilModifierData *md;
- RNA_string_get(op->ptr, "modifier", modifier_name);
+ char modifier_name[MAX_NAME];
+ GpencilModifierData *md;
+ RNA_string_get(op->ptr, "modifier", modifier_name);
- md = BKE_gpencil_modifiers_findByName(ob, modifier_name);
+ md = BKE_gpencil_modifiers_findByName(ob, modifier_name);
- if (md && type != 0 && md->type != type)
- md = NULL;
+ if (md && type != 0 && md->type != type)
+ md = NULL;
- return md;
+ return md;
}
/************************ remove modifier operator *********************/
static int gpencil_modifier_remove_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_active_context(C);
- GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
+ GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
- if (!md || !ED_object_gpencil_modifier_remove(op->reports, bmain, ob, md))
- return OPERATOR_CANCELLED;
+ if (!md || !ED_object_gpencil_modifier_remove(op->reports, bmain, ob, md))
+ return OPERATOR_CANCELLED;
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static int gpencil_modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int gpencil_modifier_remove_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
{
- if (gpencil_edit_modifier_invoke_properties(C, op))
- return gpencil_modifier_remove_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (gpencil_edit_modifier_invoke_properties(C, op))
+ return gpencil_modifier_remove_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_gpencil_modifier_remove(wmOperatorType *ot)
{
- ot->name = "Remove Grease Pencil Modifier";
- ot->description = "Remove a modifier from the active grease pencil object";
- ot->idname = "OBJECT_OT_gpencil_modifier_remove";
+ ot->name = "Remove Grease Pencil Modifier";
+ ot->description = "Remove a modifier from the active grease pencil object";
+ ot->idname = "OBJECT_OT_gpencil_modifier_remove";
- ot->invoke = gpencil_modifier_remove_invoke;
- ot->exec = gpencil_modifier_remove_exec;
- ot->poll = gpencil_edit_modifier_poll;
+ ot->invoke = gpencil_modifier_remove_invoke;
+ ot->exec = gpencil_modifier_remove_exec;
+ ot->poll = gpencil_edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- gpencil_edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ gpencil_edit_modifier_properties(ot);
}
/************************ move up modifier operator *********************/
static int gpencil_modifier_move_up_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
- if (!md || !ED_object_gpencil_modifier_move_up(op->reports, ob, md))
- return OPERATOR_CANCELLED;
+ if (!md || !ED_object_gpencil_modifier_move_up(op->reports, ob, md))
+ return OPERATOR_CANCELLED;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static int gpencil_modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int gpencil_modifier_move_up_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
{
- if (gpencil_edit_modifier_invoke_properties(C, op))
- return gpencil_modifier_move_up_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (gpencil_edit_modifier_invoke_properties(C, op))
+ return gpencil_modifier_move_up_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_gpencil_modifier_move_up(wmOperatorType *ot)
{
- ot->name = "Move Up Modifier";
- ot->description = "Move modifier up in the stack";
- ot->idname = "OBJECT_OT_gpencil_modifier_move_up";
+ ot->name = "Move Up Modifier";
+ ot->description = "Move modifier up in the stack";
+ ot->idname = "OBJECT_OT_gpencil_modifier_move_up";
- ot->invoke = gpencil_modifier_move_up_invoke;
- ot->exec = gpencil_modifier_move_up_exec;
- ot->poll = gpencil_edit_modifier_poll;
+ ot->invoke = gpencil_modifier_move_up_invoke;
+ ot->exec = gpencil_modifier_move_up_exec;
+ ot->poll = gpencil_edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- gpencil_edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ gpencil_edit_modifier_properties(ot);
}
/************************ move down modifier operator *********************/
static int gpencil_modifier_move_down_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
- if (!md || !ED_object_gpencil_modifier_move_down(op->reports, ob, md))
- return OPERATOR_CANCELLED;
+ if (!md || !ED_object_gpencil_modifier_move_down(op->reports, ob, md))
+ return OPERATOR_CANCELLED;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static int gpencil_modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int gpencil_modifier_move_down_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
{
- if (gpencil_edit_modifier_invoke_properties(C, op))
- return gpencil_modifier_move_down_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (gpencil_edit_modifier_invoke_properties(C, op))
+ return gpencil_modifier_move_down_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_gpencil_modifier_move_down(wmOperatorType *ot)
{
- ot->name = "Move Down Modifier";
- ot->description = "Move modifier down in the stack";
- ot->idname = "OBJECT_OT_gpencil_modifier_move_down";
+ ot->name = "Move Down Modifier";
+ ot->description = "Move modifier down in the stack";
+ ot->idname = "OBJECT_OT_gpencil_modifier_move_down";
- ot->invoke = gpencil_modifier_move_down_invoke;
- ot->exec = gpencil_modifier_move_down_exec;
- ot->poll = gpencil_edit_modifier_poll;
+ ot->invoke = gpencil_modifier_move_down_invoke;
+ ot->exec = gpencil_modifier_move_down_exec;
+ ot->poll = gpencil_edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- gpencil_edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ gpencil_edit_modifier_properties(ot);
}
/************************ apply modifier operator *********************/
static int gpencil_modifier_apply_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *ob = ED_object_active_context(C);
- GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
- int apply_as = RNA_enum_get(op->ptr, "apply_as");
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob = ED_object_active_context(C);
+ GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
+ int apply_as = RNA_enum_get(op->ptr, "apply_as");
- if (!md || !ED_object_gpencil_modifier_apply(bmain, op->reports, depsgraph, ob, md, apply_as)) {
- return OPERATOR_CANCELLED;
- }
+ if (!md || !ED_object_gpencil_modifier_apply(bmain, op->reports, depsgraph, ob, md, apply_as)) {
+ return OPERATOR_CANCELLED;
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int gpencil_modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (gpencil_edit_modifier_invoke_properties(C, op))
- return gpencil_modifier_apply_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (gpencil_edit_modifier_invoke_properties(C, op))
+ return gpencil_modifier_apply_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
static const EnumPropertyItem gpencil_modifier_apply_as_items[] = {
- {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
- {MODIFIER_APPLY_SHAPE, "SHAPE", 0, "New Shape", "Apply deform-only modifier to a new shape on this object"},
- {0, NULL, 0, NULL, NULL},
+ {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
+ {MODIFIER_APPLY_SHAPE,
+ "SHAPE",
+ 0,
+ "New Shape",
+ "Apply deform-only modifier to a new shape on this object"},
+ {0, NULL, 0, NULL, NULL},
};
void OBJECT_OT_gpencil_modifier_apply(wmOperatorType *ot)
{
- ot->name = "Apply Modifier";
- ot->description = "Apply modifier and remove from the stack";
- ot->idname = "OBJECT_OT_gpencil_modifier_apply";
+ ot->name = "Apply Modifier";
+ ot->description = "Apply modifier and remove from the stack";
+ ot->idname = "OBJECT_OT_gpencil_modifier_apply";
- ot->invoke = gpencil_modifier_apply_invoke;
- ot->exec = gpencil_modifier_apply_exec;
- ot->poll = gpencil_edit_modifier_poll;
+ ot->invoke = gpencil_modifier_apply_invoke;
+ ot->exec = gpencil_modifier_apply_exec;
+ ot->poll = gpencil_edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- RNA_def_enum(ot->srna, "apply_as", gpencil_modifier_apply_as_items, MODIFIER_APPLY_DATA, "Apply as", "How to apply the modifier to the geometry");
- gpencil_edit_modifier_properties(ot);
+ RNA_def_enum(ot->srna,
+ "apply_as",
+ gpencil_modifier_apply_as_items,
+ MODIFIER_APPLY_DATA,
+ "Apply as",
+ "How to apply the modifier to the geometry");
+ gpencil_edit_modifier_properties(ot);
}
/************************ copy modifier operator *********************/
static int gpencil_modifier_copy_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
- if (!md || !ED_object_gpencil_modifier_copy(op->reports, ob, md))
- return OPERATOR_CANCELLED;
+ if (!md || !ED_object_gpencil_modifier_copy(op->reports, ob, md))
+ return OPERATOR_CANCELLED;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int gpencil_modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (gpencil_edit_modifier_invoke_properties(C, op))
- return gpencil_modifier_copy_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (gpencil_edit_modifier_invoke_properties(C, op))
+ return gpencil_modifier_copy_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_gpencil_modifier_copy(wmOperatorType *ot)
{
- ot->name = "Copy Modifier";
- ot->description = "Duplicate modifier at the same position in the stack";
- ot->idname = "OBJECT_OT_gpencil_modifier_copy";
+ ot->name = "Copy Modifier";
+ ot->description = "Duplicate modifier at the same position in the stack";
+ ot->idname = "OBJECT_OT_gpencil_modifier_copy";
- ot->invoke = gpencil_modifier_copy_invoke;
- ot->exec = gpencil_modifier_copy_exec;
- ot->poll = gpencil_edit_modifier_poll;
+ ot->invoke = gpencil_modifier_copy_invoke;
+ ot->exec = gpencil_modifier_copy_exec;
+ ot->poll = gpencil_edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- gpencil_edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ gpencil_edit_modifier_properties(ot);
}
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index 401260df406..d4e5ba42be2 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <stdlib.h>
#include <string.h>
@@ -69,857 +68,897 @@
#include "object_intern.h"
-static int return_editmesh_indexar(
- BMEditMesh *em,
- int *r_tot, int **r_indexar, float r_cent[3])
+static int return_editmesh_indexar(BMEditMesh *em, int *r_tot, int **r_indexar, float r_cent[3])
{
- BMVert *eve;
- BMIter iter;
- int *index, nr, totvert = 0;
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) totvert++;
- }
- if (totvert == 0) return 0;
-
- *r_indexar = index = MEM_mallocN(4 * totvert, "hook indexar");
- *r_tot = totvert;
- nr = 0;
- zero_v3(r_cent);
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- *index = nr; index++;
- add_v3_v3(r_cent, eve->co);
- }
- nr++;
- }
-
- mul_v3_fl(r_cent, 1.0f / (float)totvert);
-
- return totvert;
+ BMVert *eve;
+ BMIter iter;
+ int *index, nr, totvert = 0;
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT))
+ totvert++;
+ }
+ if (totvert == 0)
+ return 0;
+
+ *r_indexar = index = MEM_mallocN(4 * totvert, "hook indexar");
+ *r_tot = totvert;
+ nr = 0;
+ zero_v3(r_cent);
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ *index = nr;
+ index++;
+ add_v3_v3(r_cent, eve->co);
+ }
+ nr++;
+ }
+
+ mul_v3_fl(r_cent, 1.0f / (float)totvert);
+
+ return totvert;
}
static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name, float r_cent[3])
{
- const int cd_dvert_offset = obedit->actdef ? CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT) : -1;
-
- zero_v3(r_cent);
-
- if (cd_dvert_offset != -1) {
- const int defgrp_index = obedit->actdef - 1;
- int totvert = 0;
-
- MDeformVert *dvert;
- BMVert *eve;
- BMIter iter;
-
- /* find the vertices */
- 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) {
- add_v3_v3(r_cent, eve->co);
- totvert++;
- }
- }
- if (totvert) {
- bDeformGroup *dg = BLI_findlink(&obedit->defbase, defgrp_index);
- BLI_strncpy(r_name, dg->name, sizeof(dg->name));
- mul_v3_fl(r_cent, 1.0f / (float)totvert);
- return true;
- }
- }
-
- return false;
+ const int cd_dvert_offset = obedit->actdef ?
+ CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT) :
+ -1;
+
+ zero_v3(r_cent);
+
+ if (cd_dvert_offset != -1) {
+ const int defgrp_index = obedit->actdef - 1;
+ int totvert = 0;
+
+ MDeformVert *dvert;
+ BMVert *eve;
+ BMIter iter;
+
+ /* find the vertices */
+ 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) {
+ add_v3_v3(r_cent, eve->co);
+ totvert++;
+ }
+ }
+ if (totvert) {
+ bDeformGroup *dg = BLI_findlink(&obedit->defbase, defgrp_index);
+ BLI_strncpy(r_name, dg->name, sizeof(dg->name));
+ mul_v3_fl(r_cent, 1.0f / (float)totvert);
+ return true;
+ }
+ }
+
+ return false;
}
static void select_editbmesh_hook(Object *ob, HookModifierData *hmd)
{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- BMVert *eve;
- BMIter iter;
- int index = 0, nr = 0;
-
- if (hmd->indexar == NULL)
- return;
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (nr == hmd->indexar[index]) {
- BM_vert_select_set(em->bm, eve, true);
- if (index < hmd->totindex - 1) index++;
- }
-
- nr++;
- }
-
- EDBM_select_flush(em);
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ BMVert *eve;
+ BMIter iter;
+ int index = 0, nr = 0;
+
+ if (hmd->indexar == NULL)
+ return;
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (nr == hmd->indexar[index]) {
+ BM_vert_select_set(em->bm, eve, true);
+ if (index < hmd->totindex - 1)
+ index++;
+ }
+
+ nr++;
+ }
+
+ EDBM_select_flush(em);
}
-static int return_editlattice_indexar(
- Lattice *editlatt,
- int *r_tot, int **r_indexar, float r_cent[3])
+static int return_editlattice_indexar(Lattice *editlatt,
+ int *r_tot,
+ int **r_indexar,
+ float r_cent[3])
{
- BPoint *bp;
- int *index, nr, totvert = 0, a;
-
- /* count */
- a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
- bp = editlatt->def;
- while (a--) {
- if (bp->f1 & SELECT) {
- if (bp->hide == 0) totvert++;
- }
- bp++;
- }
-
- if (totvert == 0) return 0;
-
- *r_indexar = index = MEM_mallocN(4 * totvert, "hook indexar");
- *r_tot = totvert;
- nr = 0;
- zero_v3(r_cent);
-
- a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
- bp = editlatt->def;
- while (a--) {
- if (bp->f1 & SELECT) {
- if (bp->hide == 0) {
- *index = nr; index++;
- add_v3_v3(r_cent, bp->vec);
- }
- }
- bp++;
- nr++;
- }
-
- mul_v3_fl(r_cent, 1.0f / (float)totvert);
-
- return totvert;
+ BPoint *bp;
+ int *index, nr, totvert = 0, a;
+
+ /* count */
+ a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
+ bp = editlatt->def;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ if (bp->hide == 0)
+ totvert++;
+ }
+ bp++;
+ }
+
+ if (totvert == 0)
+ return 0;
+
+ *r_indexar = index = MEM_mallocN(4 * totvert, "hook indexar");
+ *r_tot = totvert;
+ nr = 0;
+ zero_v3(r_cent);
+
+ a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
+ bp = editlatt->def;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ if (bp->hide == 0) {
+ *index = nr;
+ index++;
+ add_v3_v3(r_cent, bp->vec);
+ }
+ }
+ bp++;
+ nr++;
+ }
+
+ mul_v3_fl(r_cent, 1.0f / (float)totvert);
+
+ return totvert;
}
static void select_editlattice_hook(Object *obedit, HookModifierData *hmd)
{
- Lattice *lt = obedit->data, *editlt;
- BPoint *bp;
- int index = 0, nr = 0, a;
-
- editlt = lt->editlatt->latt;
- /* count */
- a = editlt->pntsu * editlt->pntsv * editlt->pntsw;
- bp = editlt->def;
- while (a--) {
- if (hmd->indexar[index] == nr) {
- bp->f1 |= SELECT;
- if (index < hmd->totindex - 1) index++;
- }
- nr++;
- bp++;
- }
+ Lattice *lt = obedit->data, *editlt;
+ BPoint *bp;
+ int index = 0, nr = 0, a;
+
+ editlt = lt->editlatt->latt;
+ /* count */
+ a = editlt->pntsu * editlt->pntsv * editlt->pntsw;
+ bp = editlt->def;
+ while (a--) {
+ if (hmd->indexar[index] == nr) {
+ bp->f1 |= SELECT;
+ if (index < hmd->totindex - 1)
+ index++;
+ }
+ nr++;
+ bp++;
+ }
}
-static int return_editcurve_indexar(
- Object *obedit,
- int *r_tot, int **r_indexar, float r_cent[3])
+static int return_editcurve_indexar(Object *obedit, int *r_tot, int **r_indexar, float r_cent[3])
{
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- int *index, a, nr, totvert = 0;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (bezt->f1 & SELECT) totvert++;
- if (bezt->f2 & SELECT) totvert++;
- if (bezt->f3 & SELECT) totvert++;
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (bp->f1 & SELECT) totvert++;
- bp++;
- }
- }
- }
- if (totvert == 0) return 0;
-
- *r_indexar = index = MEM_mallocN(sizeof(*index) * totvert, "hook indexar");
- *r_tot = totvert;
- nr = 0;
- zero_v3(r_cent);
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (bezt->f1 & SELECT) {
- *index = nr; index++;
- add_v3_v3(r_cent, bezt->vec[0]);
- }
- nr++;
- if (bezt->f2 & SELECT) {
- *index = nr; index++;
- add_v3_v3(r_cent, bezt->vec[1]);
- }
- nr++;
- if (bezt->f3 & SELECT) {
- *index = nr; index++;
- add_v3_v3(r_cent, bezt->vec[2]);
- }
- nr++;
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (bp->f1 & SELECT) {
- *index = nr; index++;
- add_v3_v3(r_cent, bp->vec);
- }
- nr++;
- bp++;
- }
- }
- }
-
- mul_v3_fl(r_cent, 1.0f / (float)totvert);
-
- return totvert;
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int *index, a, nr, totvert = 0;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ if (bezt->f1 & SELECT)
+ totvert++;
+ if (bezt->f2 & SELECT)
+ totvert++;
+ if (bezt->f3 & SELECT)
+ totvert++;
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ if (bp->f1 & SELECT)
+ totvert++;
+ bp++;
+ }
+ }
+ }
+ if (totvert == 0)
+ return 0;
+
+ *r_indexar = index = MEM_mallocN(sizeof(*index) * totvert, "hook indexar");
+ *r_tot = totvert;
+ nr = 0;
+ zero_v3(r_cent);
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ if (bezt->f1 & SELECT) {
+ *index = nr;
+ index++;
+ add_v3_v3(r_cent, bezt->vec[0]);
+ }
+ nr++;
+ if (bezt->f2 & SELECT) {
+ *index = nr;
+ index++;
+ add_v3_v3(r_cent, bezt->vec[1]);
+ }
+ nr++;
+ if (bezt->f3 & SELECT) {
+ *index = nr;
+ index++;
+ add_v3_v3(r_cent, bezt->vec[2]);
+ }
+ nr++;
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ *index = nr;
+ index++;
+ add_v3_v3(r_cent, bp->vec);
+ }
+ nr++;
+ bp++;
+ }
+ }
+ }
+
+ mul_v3_fl(r_cent, 1.0f / (float)totvert);
+
+ return totvert;
}
-static bool object_hook_index_array(Main *bmain, Scene *scene, Object *obedit,
- int *r_tot, int **r_indexar, char *r_name, float r_cent[3])
+static bool object_hook_index_array(Main *bmain,
+ Scene *scene,
+ Object *obedit,
+ int *r_tot,
+ int **r_indexar,
+ char *r_name,
+ float r_cent[3])
{
- *r_indexar = NULL;
- *r_tot = 0;
- r_name[0] = 0;
-
- switch (obedit->type) {
- case OB_MESH:
- {
- Mesh *me = obedit->data;
-
- BMEditMesh *em;
-
- EDBM_mesh_load(bmain, obedit);
- EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
-
- DEG_id_tag_update(obedit->data, 0);
-
- em = me->edit_mesh;
-
- EDBM_mesh_normals_update(em);
- BKE_editmesh_tessface_calc(em);
-
- /* check selected vertices first */
- if (return_editmesh_indexar(em, r_tot, r_indexar, r_cent) == 0) {
- return return_editmesh_vgroup(obedit, em, r_name, r_cent);
- }
- return true;
- }
- case OB_CURVE:
- case OB_SURF:
- ED_curve_editnurb_load(bmain, obedit);
- ED_curve_editnurb_make(obedit);
- return return_editcurve_indexar(obedit, r_tot, r_indexar, r_cent);
- case OB_LATTICE:
- {
- Lattice *lt = obedit->data;
- return return_editlattice_indexar(lt->editlatt->latt, r_tot, r_indexar, r_cent);
- }
- default:
- return false;
- }
+ *r_indexar = NULL;
+ *r_tot = 0;
+ r_name[0] = 0;
+
+ switch (obedit->type) {
+ case OB_MESH: {
+ Mesh *me = obedit->data;
+
+ BMEditMesh *em;
+
+ EDBM_mesh_load(bmain, obedit);
+ EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
+
+ DEG_id_tag_update(obedit->data, 0);
+
+ em = me->edit_mesh;
+
+ EDBM_mesh_normals_update(em);
+ BKE_editmesh_tessface_calc(em);
+
+ /* check selected vertices first */
+ if (return_editmesh_indexar(em, r_tot, r_indexar, r_cent) == 0) {
+ return return_editmesh_vgroup(obedit, em, r_name, r_cent);
+ }
+ return true;
+ }
+ case OB_CURVE:
+ case OB_SURF:
+ ED_curve_editnurb_load(bmain, obedit);
+ ED_curve_editnurb_make(obedit);
+ return return_editcurve_indexar(obedit, r_tot, r_indexar, r_cent);
+ case OB_LATTICE: {
+ Lattice *lt = obedit->data;
+ return return_editlattice_indexar(lt->editlatt->latt, r_tot, r_indexar, r_cent);
+ }
+ default:
+ return false;
+ }
}
static void select_editcurve_hook(Object *obedit, HookModifierData *hmd)
{
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- int index = 0, a, nr = 0;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (nr == hmd->indexar[index]) {
- bezt->f1 |= SELECT;
- if (index < hmd->totindex - 1) index++;
- }
- nr++;
- if (nr == hmd->indexar[index]) {
- bezt->f2 |= SELECT;
- if (index < hmd->totindex - 1) index++;
- }
- nr++;
- if (nr == hmd->indexar[index]) {
- bezt->f3 |= SELECT;
- if (index < hmd->totindex - 1) index++;
- }
- nr++;
-
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (nr == hmd->indexar[index]) {
- bp->f1 |= SELECT;
- if (index < hmd->totindex - 1) index++;
- }
- nr++;
- bp++;
- }
- }
- }
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int index = 0, a, nr = 0;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ if (nr == hmd->indexar[index]) {
+ bezt->f1 |= SELECT;
+ if (index < hmd->totindex - 1)
+ index++;
+ }
+ nr++;
+ if (nr == hmd->indexar[index]) {
+ bezt->f2 |= SELECT;
+ if (index < hmd->totindex - 1)
+ index++;
+ }
+ nr++;
+ if (nr == hmd->indexar[index]) {
+ bezt->f3 |= SELECT;
+ if (index < hmd->totindex - 1)
+ index++;
+ }
+ nr++;
+
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ if (nr == hmd->indexar[index]) {
+ bp->f1 |= SELECT;
+ if (index < hmd->totindex - 1)
+ index++;
+ }
+ nr++;
+ bp++;
+ }
+ }
+ }
}
-static void object_hook_from_context(bContext *C, PointerRNA *ptr, const int num,
- Object **r_ob, HookModifierData **r_hmd)
+static void object_hook_from_context(
+ bContext *C, PointerRNA *ptr, const int num, Object **r_ob, HookModifierData **r_hmd)
{
- Object *ob;
- HookModifierData *hmd;
-
- if (ptr->data) { /* if modifier context is available, use that */
- ob = ptr->id.data;
- hmd = ptr->data;
- }
- else { /* use the provided property */
- ob = CTX_data_edit_object(C);
- hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
- }
-
- if (ob && hmd && (hmd->modifier.type == eModifierType_Hook)) {
- *r_ob = ob;
- *r_hmd = hmd;
- }
- else {
- *r_ob = NULL;
- *r_hmd = NULL;
- }
+ Object *ob;
+ HookModifierData *hmd;
+
+ if (ptr->data) { /* if modifier context is available, use that */
+ ob = ptr->id.data;
+ hmd = ptr->data;
+ }
+ else { /* use the provided property */
+ ob = CTX_data_edit_object(C);
+ hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
+ }
+
+ if (ob && hmd && (hmd->modifier.type == eModifierType_Hook)) {
+ *r_ob = ob;
+ *r_hmd = hmd;
+ }
+ else {
+ *r_ob = NULL;
+ *r_hmd = NULL;
+ }
}
static void object_hook_select(Object *ob, HookModifierData *hmd)
{
- if (hmd->indexar == NULL)
- return;
-
- if (ob->type == OB_MESH) select_editbmesh_hook(ob, hmd);
- else if (ob->type == OB_LATTICE) select_editlattice_hook(ob, hmd);
- else if (ob->type == OB_CURVE) select_editcurve_hook(ob, hmd);
- else if (ob->type == OB_SURF) select_editcurve_hook(ob, hmd);
+ if (hmd->indexar == NULL)
+ return;
+
+ if (ob->type == OB_MESH)
+ select_editbmesh_hook(ob, hmd);
+ else if (ob->type == OB_LATTICE)
+ select_editlattice_hook(ob, hmd);
+ else if (ob->type == OB_CURVE)
+ select_editcurve_hook(ob, hmd);
+ else if (ob->type == OB_SURF)
+ select_editcurve_hook(ob, hmd);
}
/* special poll operators for hook operators */
/* TODO: check for properties window modifier context too as alternative? */
static bool hook_op_edit_poll(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
-
- if (obedit) {
- if (ED_operator_editmesh(C)) return 1;
- if (ED_operator_editsurfcurve(C)) return 1;
- if (ED_operator_editlattice(C)) return 1;
- //if (ED_operator_editmball(C)) return 1;
- }
-
- return 0;
+ Object *obedit = CTX_data_edit_object(C);
+
+ if (obedit) {
+ if (ED_operator_editmesh(C))
+ return 1;
+ if (ED_operator_editsurfcurve(C))
+ return 1;
+ if (ED_operator_editlattice(C))
+ return 1;
+ //if (ED_operator_editmball(C)) return 1;
+ }
+
+ return 0;
}
-static Object *add_hook_object_new(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, Object *obedit)
+static Object *add_hook_object_new(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, Object *obedit)
{
- Base *basedit;
- Object *ob;
+ Base *basedit;
+ Object *ob;
- ob = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, NULL);
+ ob = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, NULL);
- basedit = BKE_view_layer_base_find(view_layer, obedit);
- BLI_assert(view_layer->basact->object == ob);
+ basedit = BKE_view_layer_base_find(view_layer, obedit);
+ BLI_assert(view_layer->basact->object == ob);
- if (v3d && v3d->localvd) {
- view_layer->basact->local_view_bits |= v3d->local_view_uuid;
- }
+ if (v3d && v3d->localvd) {
+ view_layer->basact->local_view_bits |= v3d->local_view_uuid;
+ }
- /* icky, BKE_object_add sets new base as active.
- * so set it back to the original edit object */
- view_layer->basact = basedit;
+ /* icky, BKE_object_add sets new base as active.
+ * so set it back to the original edit object */
+ view_layer->basact = basedit;
- return ob;
+ return ob;
}
-static int add_hook_object(
- const bContext *C,
- Main *bmain,
- Scene *scene,
- ViewLayer *view_layer,
- View3D *v3d,
- Object *obedit,
- Object *ob,
- int mode,
- ReportList *reports)
+static int add_hook_object(const bContext *C,
+ Main *bmain,
+ Scene *scene,
+ ViewLayer *view_layer,
+ View3D *v3d,
+ Object *obedit,
+ Object *ob,
+ int mode,
+ ReportList *reports)
{
- ModifierData *md = NULL;
- HookModifierData *hmd = NULL;
- float cent[3];
- float pose_mat[4][4];
- int tot, ok, *indexar;
- char name[MAX_NAME];
-
- ok = object_hook_index_array(bmain, scene, obedit, &tot, &indexar, name, cent);
-
- if (!ok) {
- BKE_report(reports, RPT_ERROR, "Requires selected vertices or active vertex group");
- return false;
- }
-
- if (mode == OBJECT_ADDHOOK_NEWOB && !ob) {
-
- ob = add_hook_object_new(bmain, scene, view_layer, v3d, obedit);
-
- /* transform cent to global coords for loc */
- mul_v3_m4v3(ob->loc, obedit->obmat, cent);
- }
-
- md = obedit->modifiers.first;
- while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) {
- md = md->next;
- }
-
- hmd = (HookModifierData *) 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);
-
- hmd->object = ob;
- hmd->indexar = indexar;
- copy_v3_v3(hmd->cent, cent);
- hmd->totindex = tot;
- BLI_strncpy(hmd->name, name, sizeof(hmd->name));
-
- unit_m4(pose_mat);
-
- invert_m4_m4(obedit->imat, obedit->obmat);
- if (mode == OBJECT_ADDHOOK_NEWOB) {
- /* pass */
- }
- else {
- /* may overwrite with pose-bone location, below */
- mul_v3_m4v3(cent, obedit->imat, ob->obmat[3]);
- }
-
- if (mode == OBJECT_ADDHOOK_SELOB_BONE) {
- bArmature *arm = ob->data;
- BLI_assert(ob->type == OB_ARMATURE);
- if (arm->act_bone) {
- bPoseChannel *pchan_act;
-
- BLI_strncpy(hmd->subtarget, arm->act_bone->name, sizeof(hmd->subtarget));
-
- pchan_act = BKE_pose_channel_active(ob);
- if (LIKELY(pchan_act)) {
- invert_m4_m4(pose_mat, pchan_act->pose_mat);
- mul_v3_m4v3(cent, ob->obmat, pchan_act->pose_mat[3]);
- mul_v3_m4v3(cent, obedit->imat, cent);
- }
- }
- else {
- BKE_report(reports, RPT_WARNING, "Armature has no active object bone");
- }
- }
-
- copy_v3_v3(hmd->cent, cent);
-
-
- /* matrix calculus */
- /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
- /* (parentinv ) */
- BKE_object_where_is_calc(CTX_data_depsgraph(C), scene, ob);
-
- invert_m4_m4(ob->imat, ob->obmat);
- /* apparently this call goes from right to left... */
- mul_m4_series(hmd->parentinv, pose_mat, ob->imat, obedit->obmat);
-
- DEG_relations_tag_update(bmain);
-
- return true;
+ ModifierData *md = NULL;
+ HookModifierData *hmd = NULL;
+ float cent[3];
+ float pose_mat[4][4];
+ int tot, ok, *indexar;
+ char name[MAX_NAME];
+
+ ok = object_hook_index_array(bmain, scene, obedit, &tot, &indexar, name, cent);
+
+ if (!ok) {
+ BKE_report(reports, RPT_ERROR, "Requires selected vertices or active vertex group");
+ return false;
+ }
+
+ if (mode == OBJECT_ADDHOOK_NEWOB && !ob) {
+
+ ob = add_hook_object_new(bmain, scene, view_layer, v3d, obedit);
+
+ /* transform cent to global coords for loc */
+ mul_v3_m4v3(ob->loc, obedit->obmat, cent);
+ }
+
+ md = obedit->modifiers.first;
+ while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) {
+ md = md->next;
+ }
+
+ hmd = (HookModifierData *)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);
+
+ hmd->object = ob;
+ hmd->indexar = indexar;
+ copy_v3_v3(hmd->cent, cent);
+ hmd->totindex = tot;
+ BLI_strncpy(hmd->name, name, sizeof(hmd->name));
+
+ unit_m4(pose_mat);
+
+ invert_m4_m4(obedit->imat, obedit->obmat);
+ if (mode == OBJECT_ADDHOOK_NEWOB) {
+ /* pass */
+ }
+ else {
+ /* may overwrite with pose-bone location, below */
+ mul_v3_m4v3(cent, obedit->imat, ob->obmat[3]);
+ }
+
+ if (mode == OBJECT_ADDHOOK_SELOB_BONE) {
+ bArmature *arm = ob->data;
+ BLI_assert(ob->type == OB_ARMATURE);
+ if (arm->act_bone) {
+ bPoseChannel *pchan_act;
+
+ BLI_strncpy(hmd->subtarget, arm->act_bone->name, sizeof(hmd->subtarget));
+
+ pchan_act = BKE_pose_channel_active(ob);
+ if (LIKELY(pchan_act)) {
+ invert_m4_m4(pose_mat, pchan_act->pose_mat);
+ mul_v3_m4v3(cent, ob->obmat, pchan_act->pose_mat[3]);
+ mul_v3_m4v3(cent, obedit->imat, cent);
+ }
+ }
+ else {
+ BKE_report(reports, RPT_WARNING, "Armature has no active object bone");
+ }
+ }
+
+ copy_v3_v3(hmd->cent, cent);
+
+ /* matrix calculus */
+ /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
+ /* (parentinv ) */
+ BKE_object_where_is_calc(CTX_data_depsgraph(C), scene, ob);
+
+ invert_m4_m4(ob->imat, ob->obmat);
+ /* apparently this call goes from right to left... */
+ mul_m4_series(hmd->parentinv, pose_mat, ob->imat, obedit->obmat);
+
+ DEG_relations_tag_update(bmain);
+
+ return true;
}
static int object_add_hook_selob_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);
- Object *obedit = CTX_data_edit_object(C);
- Object *obsel = NULL;
- const bool use_bone = RNA_boolean_get(op->ptr, "use_bone");
- const int mode = use_bone ? OBJECT_ADDHOOK_SELOB_BONE : OBJECT_ADDHOOK_SELOB;
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- if (ob != obedit) {
- obsel = ob;
- break;
- }
- }
- CTX_DATA_END;
-
- if (!obsel) {
- BKE_report(op->reports, RPT_ERROR, "Cannot add hook with no other selected objects");
- return OPERATOR_CANCELLED;
- }
-
- if (use_bone && obsel->type != OB_ARMATURE) {
- BKE_report(op->reports, RPT_ERROR, "Cannot add hook bone for a non armature object");
- return OPERATOR_CANCELLED;
- }
-
- if (add_hook_object(C, bmain, scene, view_layer, NULL, obedit, obsel, mode, op->reports)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obedit = CTX_data_edit_object(C);
+ Object *obsel = NULL;
+ const bool use_bone = RNA_boolean_get(op->ptr, "use_bone");
+ const int mode = use_bone ? OBJECT_ADDHOOK_SELOB_BONE : OBJECT_ADDHOOK_SELOB;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ if (ob != obedit) {
+ obsel = ob;
+ break;
+ }
+ }
+ CTX_DATA_END;
+
+ if (!obsel) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot add hook with no other selected objects");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (use_bone && obsel->type != OB_ARMATURE) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot add hook bone for a non armature object");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (add_hook_object(C, bmain, scene, view_layer, NULL, obedit, obsel, mode, op->reports)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void OBJECT_OT_hook_add_selob(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hook to Selected Object";
- ot->description = "Hook selected vertices to the first selected object";
- ot->idname = "OBJECT_OT_hook_add_selob";
-
- /* api callbacks */
- ot->exec = object_add_hook_selob_exec;
- ot->poll = hook_op_edit_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "use_bone", false, "Active Bone",
- "Assign the hook to the hook objects active bone");
+ /* identifiers */
+ ot->name = "Hook to Selected Object";
+ ot->description = "Hook selected vertices to the first selected object";
+ ot->idname = "OBJECT_OT_hook_add_selob";
+
+ /* api callbacks */
+ ot->exec = object_add_hook_selob_exec;
+ ot->poll = hook_op_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna,
+ "use_bone",
+ false,
+ "Active Bone",
+ "Assign the hook to the hook objects active bone");
}
static int object_add_hook_newob_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);
- View3D *v3d = CTX_wm_view3d(C);
- Object *obedit = CTX_data_edit_object(C);
-
- if (add_hook_object(C, bmain, scene, view_layer, v3d, obedit, NULL, OBJECT_ADDHOOK_NEWOB, op->reports)) {
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Object *obedit = CTX_data_edit_object(C);
+
+ if (add_hook_object(
+ C, bmain, scene, view_layer, v3d, obedit, NULL, OBJECT_ADDHOOK_NEWOB, op->reports)) {
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void OBJECT_OT_hook_add_newob(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hook to New Object";
- ot->description = "Hook selected vertices to a newly created object";
- ot->idname = "OBJECT_OT_hook_add_newob";
+ /* identifiers */
+ ot->name = "Hook to New Object";
+ ot->description = "Hook selected vertices to a newly created object";
+ ot->idname = "OBJECT_OT_hook_add_newob";
- /* api callbacks */
- ot->exec = object_add_hook_newob_exec;
- ot->poll = hook_op_edit_poll;
+ /* api callbacks */
+ ot->exec = object_add_hook_newob_exec;
+ ot->poll = hook_op_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int object_hook_remove_exec(bContext *C, wmOperator *op)
{
- int num = RNA_enum_get(op->ptr, "modifier");
- Object *ob = CTX_data_edit_object(C);
- HookModifierData *hmd = NULL;
+ int num = RNA_enum_get(op->ptr, "modifier");
+ Object *ob = CTX_data_edit_object(C);
+ HookModifierData *hmd = NULL;
- hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
- if (!hmd) {
- BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
- return OPERATOR_CANCELLED;
- }
+ hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
+ if (!hmd) {
+ BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
+ return OPERATOR_CANCELLED;
+ }
- /* remove functionality */
+ /* remove functionality */
- BLI_remlink(&ob->modifiers, (ModifierData *)hmd);
- modifier_free((ModifierData *)hmd);
+ BLI_remlink(&ob->modifiers, (ModifierData *)hmd);
+ modifier_free((ModifierData *)hmd);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static const EnumPropertyItem *hook_mod_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *hook_mod_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- Object *ob = CTX_data_edit_object(C);
- EnumPropertyItem tmp = {0, "", 0, "", ""};
- EnumPropertyItem *item = NULL;
- ModifierData *md = NULL;
- int a, totitem = 0;
-
- if (!ob)
- return DummyRNA_NULL_items;
-
- for (a = 0, md = ob->modifiers.first; md; md = md->next, a++) {
- if (md->type == eModifierType_Hook) {
- tmp.value = a;
- tmp.icon = ICON_HOOK;
- tmp.identifier = md->name;
- tmp.name = md->name;
- RNA_enum_item_add(&item, &totitem, &tmp);
- }
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ Object *ob = CTX_data_edit_object(C);
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ EnumPropertyItem *item = NULL;
+ ModifierData *md = NULL;
+ int a, totitem = 0;
+
+ if (!ob)
+ return DummyRNA_NULL_items;
+
+ for (a = 0, md = ob->modifiers.first; md; md = md->next, a++) {
+ if (md->type == eModifierType_Hook) {
+ tmp.value = a;
+ tmp.icon = ICON_HOOK;
+ tmp.identifier = md->name;
+ tmp.name = md->name;
+ RNA_enum_item_add(&item, &totitem, &tmp);
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
void OBJECT_OT_hook_remove(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Remove Hook";
- ot->idname = "OBJECT_OT_hook_remove";
- ot->description = "Remove a hook from the active object";
-
- /* api callbacks */
- ot->exec = object_hook_remove_exec;
- ot->invoke = WM_menu_invoke;
- ot->poll = hook_op_edit_poll;
-
- /* flags */
- /* this operator removes modifier which isn't stored in local undo stack,
- * so redoing it from redo panel gives totally weird results */
- ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to remove");
- RNA_def_enum_funcs(prop, hook_mod_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Remove Hook";
+ ot->idname = "OBJECT_OT_hook_remove";
+ ot->description = "Remove a hook from the active object";
+
+ /* api callbacks */
+ ot->exec = object_hook_remove_exec;
+ ot->invoke = WM_menu_invoke;
+ ot->poll = hook_op_edit_poll;
+
+ /* flags */
+ /* this operator removes modifier which isn't stored in local undo stack,
+ * so redoing it from redo panel gives totally weird results */
+ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(
+ ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to remove");
+ RNA_def_enum_funcs(prop, hook_mod_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
static int object_hook_reset_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
- int num = RNA_enum_get(op->ptr, "modifier");
- Object *ob = NULL;
- HookModifierData *hmd = NULL;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
+ int num = RNA_enum_get(op->ptr, "modifier");
+ Object *ob = NULL;
+ HookModifierData *hmd = NULL;
- object_hook_from_context(C, &ptr, num, &ob, &hmd);
- if (hmd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
- return OPERATOR_CANCELLED;
- }
+ object_hook_from_context(C, &ptr, num, &ob, &hmd);
+ if (hmd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
+ return OPERATOR_CANCELLED;
+ }
- BKE_object_modifier_hook_reset(ob, hmd);
+ BKE_object_modifier_hook_reset(ob, hmd);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_reset(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Reset Hook";
- ot->description = "Recalculate and clear offset transformation";
- ot->idname = "OBJECT_OT_hook_reset";
+ /* identifiers */
+ ot->name = "Reset Hook";
+ ot->description = "Recalculate and clear offset transformation";
+ ot->idname = "OBJECT_OT_hook_reset";
- /* callbacks */
- ot->exec = object_hook_reset_exec;
- ot->poll = hook_op_edit_poll;
+ /* callbacks */
+ ot->exec = object_hook_reset_exec;
+ ot->poll = hook_op_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- prop = RNA_def_enum(ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
- RNA_def_enum_funcs(prop, hook_mod_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ /* properties */
+ prop = RNA_def_enum(
+ ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
+ RNA_def_enum_funcs(prop, hook_mod_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
}
static int object_hook_recenter_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
- int num = RNA_enum_get(op->ptr, "modifier");
- Object *ob = NULL;
- HookModifierData *hmd = NULL;
- Scene *scene = CTX_data_scene(C);
- float bmat[3][3], imat[3][3];
-
- object_hook_from_context(C, &ptr, num, &ob, &hmd);
- if (hmd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
- return OPERATOR_CANCELLED;
- }
-
- /* recenter functionality */
- copy_m3_m4(bmat, ob->obmat);
- invert_m3_m3(imat, bmat);
-
- sub_v3_v3v3(hmd->cent, scene->cursor.location, ob->obmat[3]);
- mul_m3_v3(imat, hmd->cent);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
- return OPERATOR_FINISHED;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
+ int num = RNA_enum_get(op->ptr, "modifier");
+ Object *ob = NULL;
+ HookModifierData *hmd = NULL;
+ Scene *scene = CTX_data_scene(C);
+ float bmat[3][3], imat[3][3];
+
+ object_hook_from_context(C, &ptr, num, &ob, &hmd);
+ if (hmd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* recenter functionality */
+ copy_m3_m4(bmat, ob->obmat);
+ invert_m3_m3(imat, bmat);
+
+ sub_v3_v3v3(hmd->cent, scene->cursor.location, ob->obmat[3]);
+ mul_m3_v3(imat, hmd->cent);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_recenter(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Recenter Hook";
- ot->description = "Set hook center to cursor position";
- ot->idname = "OBJECT_OT_hook_recenter";
+ /* identifiers */
+ ot->name = "Recenter Hook";
+ ot->description = "Set hook center to cursor position";
+ ot->idname = "OBJECT_OT_hook_recenter";
- /* callbacks */
- ot->exec = object_hook_recenter_exec;
- ot->poll = hook_op_edit_poll;
+ /* callbacks */
+ ot->exec = object_hook_recenter_exec;
+ ot->poll = hook_op_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- prop = RNA_def_enum(ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
- RNA_def_enum_funcs(prop, hook_mod_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ /* properties */
+ prop = RNA_def_enum(
+ ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
+ RNA_def_enum_funcs(prop, hook_mod_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
}
static int object_hook_assign_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
- int num = RNA_enum_get(op->ptr, "modifier");
- Object *ob = NULL;
- HookModifierData *hmd = NULL;
- float cent[3];
- char name[MAX_NAME];
- int *indexar, tot;
-
- object_hook_from_context(C, &ptr, num, &ob, &hmd);
- if (hmd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
- return OPERATOR_CANCELLED;
- }
-
- /* assign functionality */
-
- if (!object_hook_index_array(bmain, scene, ob, &tot, &indexar, name, cent)) {
- BKE_report(op->reports, RPT_WARNING, "Requires selected vertices or active vertex group");
- return OPERATOR_CANCELLED;
- }
- if (hmd->indexar)
- MEM_freeN(hmd->indexar);
-
- copy_v3_v3(hmd->cent, cent);
- hmd->indexar = indexar;
- hmd->totindex = tot;
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
+ int num = RNA_enum_get(op->ptr, "modifier");
+ Object *ob = NULL;
+ HookModifierData *hmd = NULL;
+ float cent[3];
+ char name[MAX_NAME];
+ int *indexar, tot;
+
+ object_hook_from_context(C, &ptr, num, &ob, &hmd);
+ if (hmd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* assign functionality */
+
+ if (!object_hook_index_array(bmain, scene, ob, &tot, &indexar, name, cent)) {
+ BKE_report(op->reports, RPT_WARNING, "Requires selected vertices or active vertex group");
+ return OPERATOR_CANCELLED;
+ }
+ if (hmd->indexar)
+ MEM_freeN(hmd->indexar);
+
+ copy_v3_v3(hmd->cent, cent);
+ hmd->indexar = indexar;
+ hmd->totindex = tot;
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_assign(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Assign to Hook";
- ot->description = "Assign the selected vertices to a hook";
- ot->idname = "OBJECT_OT_hook_assign";
-
- /* callbacks */
- ot->exec = object_hook_assign_exec;
- ot->poll = hook_op_edit_poll;
-
- /* flags */
- /* this operator changes data stored in modifier which doesn't get pushed to undo stack,
- * so redoing it from redo panel gives totally weird results */
- ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
- RNA_def_enum_funcs(prop, hook_mod_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Assign to Hook";
+ ot->description = "Assign the selected vertices to a hook";
+ ot->idname = "OBJECT_OT_hook_assign";
+
+ /* callbacks */
+ ot->exec = object_hook_assign_exec;
+ ot->poll = hook_op_edit_poll;
+
+ /* flags */
+ /* this operator changes data stored in modifier which doesn't get pushed to undo stack,
+ * so redoing it from redo panel gives totally weird results */
+ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(
+ ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
+ RNA_def_enum_funcs(prop, hook_mod_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
}
static int object_hook_select_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
- int num = RNA_enum_get(op->ptr, "modifier");
- Object *ob = NULL;
- HookModifierData *hmd = NULL;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
+ int num = RNA_enum_get(op->ptr, "modifier");
+ Object *ob = NULL;
+ HookModifierData *hmd = NULL;
- object_hook_from_context(C, &ptr, num, &ob, &hmd);
- if (hmd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
- return OPERATOR_CANCELLED;
- }
+ object_hook_from_context(C, &ptr, num, &ob, &hmd);
+ if (hmd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
+ return OPERATOR_CANCELLED;
+ }
- /* select functionality */
- object_hook_select(ob, hmd);
+ /* select functionality */
+ object_hook_select(ob, hmd);
- DEG_id_tag_update(ob->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
+ DEG_id_tag_update(ob->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_select(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Select Hook";
- ot->description = "Select affected vertices on mesh";
- ot->idname = "OBJECT_OT_hook_select";
+ /* identifiers */
+ ot->name = "Select Hook";
+ ot->description = "Select affected vertices on mesh";
+ ot->idname = "OBJECT_OT_hook_select";
- /* callbacks */
- ot->exec = object_hook_select_exec;
- ot->poll = hook_op_edit_poll;
+ /* callbacks */
+ ot->exec = object_hook_select_exec;
+ ot->poll = hook_op_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- prop = RNA_def_enum(ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to remove");
- RNA_def_enum_funcs(prop, hook_mod_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ /* properties */
+ prop = RNA_def_enum(
+ ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to remove");
+ RNA_def_enum_funcs(prop, hook_mod_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
}
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 33f821126a2..d17b6515dbb 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -34,9 +34,9 @@ struct ModifierData;
/* add hook menu */
enum eObject_Hook_Add_Mode {
- OBJECT_ADDHOOK_NEWOB = 1,
- OBJECT_ADDHOOK_SELOB,
- OBJECT_ADDHOOK_SELOB_BONE,
+ OBJECT_ADDHOOK_NEWOB = 1,
+ OBJECT_ADDHOOK_SELOB,
+ OBJECT_ADDHOOK_SELOB_BONE,
};
/* internal exports only */
@@ -141,7 +141,9 @@ bool edit_modifier_poll_generic(struct bContext *C, struct StructRNA *rna_type,
bool edit_modifier_poll(struct bContext *C);
void edit_modifier_properties(struct wmOperatorType *ot);
int edit_modifier_invoke_properties(struct bContext *C, struct wmOperator *op);
-struct ModifierData *edit_modifier_property_get(struct wmOperator *op, struct Object *ob, int type);
+struct ModifierData *edit_modifier_property_get(struct wmOperator *op,
+ struct Object *ob,
+ int type);
void OBJECT_OT_modifier_add(struct wmOperatorType *ot);
void OBJECT_OT_modifier_remove(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c
index dd0a37b4498..7c881aa7cab 100644
--- a/source/blender/editors/object/object_modes.c
+++ b/source/blender/editors/object/object_modes.c
@@ -45,7 +45,7 @@
#include "ED_armature.h"
#include "ED_screen.h"
-#include "ED_object.h" /* own include */
+#include "ED_object.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name High Level Mode Operations
@@ -54,29 +54,29 @@
static const char *object_mode_op_string(eObjectMode mode)
{
- if (mode & OB_MODE_EDIT)
- return "OBJECT_OT_editmode_toggle";
- if (mode == OB_MODE_SCULPT)
- return "SCULPT_OT_sculptmode_toggle";
- if (mode == OB_MODE_VERTEX_PAINT)
- return "PAINT_OT_vertex_paint_toggle";
- if (mode == OB_MODE_WEIGHT_PAINT)
- return "PAINT_OT_weight_paint_toggle";
- if (mode == OB_MODE_TEXTURE_PAINT)
- return "PAINT_OT_texture_paint_toggle";
- if (mode == OB_MODE_PARTICLE_EDIT)
- return "PARTICLE_OT_particle_edit_toggle";
- if (mode == OB_MODE_POSE)
- return "OBJECT_OT_posemode_toggle";
- if (mode == OB_MODE_EDIT_GPENCIL)
- return "GPENCIL_OT_editmode_toggle";
- if (mode == OB_MODE_PAINT_GPENCIL)
- return "GPENCIL_OT_paintmode_toggle";
- if (mode == OB_MODE_SCULPT_GPENCIL)
- return "GPENCIL_OT_sculptmode_toggle";
- if (mode == OB_MODE_WEIGHT_GPENCIL)
- return "GPENCIL_OT_weightmode_toggle";
- return NULL;
+ if (mode & OB_MODE_EDIT)
+ return "OBJECT_OT_editmode_toggle";
+ if (mode == OB_MODE_SCULPT)
+ return "SCULPT_OT_sculptmode_toggle";
+ if (mode == OB_MODE_VERTEX_PAINT)
+ return "PAINT_OT_vertex_paint_toggle";
+ if (mode == OB_MODE_WEIGHT_PAINT)
+ return "PAINT_OT_weight_paint_toggle";
+ if (mode == OB_MODE_TEXTURE_PAINT)
+ return "PAINT_OT_texture_paint_toggle";
+ if (mode == OB_MODE_PARTICLE_EDIT)
+ return "PARTICLE_OT_particle_edit_toggle";
+ if (mode == OB_MODE_POSE)
+ return "OBJECT_OT_posemode_toggle";
+ if (mode == OB_MODE_EDIT_GPENCIL)
+ return "GPENCIL_OT_editmode_toggle";
+ if (mode == OB_MODE_PAINT_GPENCIL)
+ return "GPENCIL_OT_paintmode_toggle";
+ if (mode == OB_MODE_SCULPT_GPENCIL)
+ return "GPENCIL_OT_sculptmode_toggle";
+ if (mode == OB_MODE_WEIGHT_GPENCIL)
+ return "GPENCIL_OT_weightmode_toggle";
+ return NULL;
}
/**
@@ -85,44 +85,42 @@ static const char *object_mode_op_string(eObjectMode mode)
*/
bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode)
{
- if (ob) {
- if (mode == OB_MODE_OBJECT)
- return true;
+ if (ob) {
+ if (mode == OB_MODE_OBJECT)
+ return true;
- switch (ob->type) {
- case OB_MESH:
- if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT |
- OB_MODE_TEXTURE_PAINT | OB_MODE_PARTICLE_EDIT))
- {
- return true;
- }
- break;
- case OB_CURVE:
- case OB_SURF:
- case OB_FONT:
- case OB_MBALL:
- if (mode & (OB_MODE_EDIT))
- return true;
- break;
- case OB_LATTICE:
- if (mode & (OB_MODE_EDIT | OB_MODE_WEIGHT_PAINT))
- return true;
- break;
- case OB_ARMATURE:
- if (mode & (OB_MODE_EDIT | OB_MODE_POSE))
- return true;
- 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))
- {
- return true;
- }
- break;
- }
- }
+ switch (ob->type) {
+ case OB_MESH:
+ if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT |
+ OB_MODE_TEXTURE_PAINT | OB_MODE_PARTICLE_EDIT)) {
+ return true;
+ }
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ case OB_FONT:
+ case OB_MBALL:
+ if (mode & (OB_MODE_EDIT))
+ return true;
+ break;
+ case OB_LATTICE:
+ if (mode & (OB_MODE_EDIT | OB_MODE_WEIGHT_PAINT))
+ return true;
+ break;
+ case OB_ARMATURE:
+ if (mode & (OB_MODE_EDIT | OB_MODE_POSE))
+ return true;
+ 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)) {
+ return true;
+ }
+ break;
+ }
+ }
- return false;
+ return false;
}
/**
@@ -132,68 +130,66 @@ bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode)
*/
bool ED_object_mode_compat_set(bContext *C, Object *ob, eObjectMode mode, ReportList *reports)
{
- bool ok;
- if (!ELEM(ob->mode, mode, OB_MODE_OBJECT)) {
- const char *opstring = object_mode_op_string(ob->mode);
+ bool ok;
+ if (!ELEM(ob->mode, mode, OB_MODE_OBJECT)) {
+ const char *opstring = object_mode_op_string(ob->mode);
- WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
- ok = ELEM(ob->mode, mode, OB_MODE_OBJECT);
- if (!ok) {
- wmOperatorType *ot = WM_operatortype_find(opstring, false);
- BKE_reportf(reports, RPT_ERROR, "Unable to execute '%s', error changing modes", ot->name);
- }
- }
- else {
- ok = true;
- }
+ WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
+ ok = ELEM(ob->mode, mode, OB_MODE_OBJECT);
+ if (!ok) {
+ wmOperatorType *ot = WM_operatortype_find(opstring, false);
+ BKE_reportf(reports, RPT_ERROR, "Unable to execute '%s', error changing modes", ot->name);
+ }
+ }
+ else {
+ ok = true;
+ }
- return ok;
+ return ok;
}
void ED_object_mode_toggle(bContext *C, eObjectMode mode)
{
- if (mode != OB_MODE_OBJECT) {
- const char *opstring = object_mode_op_string(mode);
+ if (mode != OB_MODE_OBJECT) {
+ const char *opstring = object_mode_op_string(mode);
- if (opstring) {
- wmOperatorType *ot = WM_operatortype_find(opstring, false);
- if (ot->flag & OPTYPE_USE_EVAL_DATA) {
- /* We need to force refresh of depsgraph after undo step,
- * redoing the operator *may* rely on some valid evaluated data. */
- struct Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- BKE_scene_view_layer_graph_evaluated_ensure(bmain, scene, view_layer);
- }
- WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_REGION_WIN, NULL);
- }
- }
+ if (opstring) {
+ wmOperatorType *ot = WM_operatortype_find(opstring, false);
+ if (ot->flag & OPTYPE_USE_EVAL_DATA) {
+ /* We need to force refresh of depsgraph after undo step,
+ * redoing the operator *may* rely on some valid evaluated data. */
+ struct Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_scene_view_layer_graph_evaluated_ensure(bmain, scene, view_layer);
+ }
+ WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_REGION_WIN, NULL);
+ }
+ }
}
-
/* Wrapper for operator */
void ED_object_mode_set(bContext *C, eObjectMode mode)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- wm->op_undo_depth++;
- /* needed so we don't do undo pushes. */
- ED_object_mode_generic_enter(C, mode);
- wm->op_undo_depth--;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wm->op_undo_depth++;
+ /* needed so we don't do undo pushes. */
+ ED_object_mode_generic_enter(C, mode);
+ wm->op_undo_depth--;
}
void ED_object_mode_exit(bContext *C)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- struct Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- FOREACH_OBJECT_BEGIN(view_layer, ob)
- {
- if (ob->mode & OB_MODE_ALL_MODE_DATA) {
- ED_object_mode_generic_exit(bmain, depsgraph, scene, ob);
- }
- }
- FOREACH_OBJECT_END;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ struct Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ FOREACH_OBJECT_BEGIN (view_layer, ob) {
+ if (ob->mode & OB_MODE_ALL_MODE_DATA) {
+ ED_object_mode_generic_exit(bmain, depsgraph, scene, ob);
+ }
+ }
+ FOREACH_OBJECT_END;
}
/** \} */
@@ -206,100 +202,97 @@ void ED_object_mode_exit(bContext *C)
*
* \{ */
-bool ED_object_mode_generic_enter(
- struct bContext *C, eObjectMode object_mode)
+bool ED_object_mode_generic_enter(struct bContext *C, eObjectMode object_mode)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- if (ob == NULL) {
- return (object_mode == OB_MODE_OBJECT);
- }
- if (ob->mode == object_mode) {
- return true;
- }
- wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_mode_set", false);
- PointerRNA ptr;
- WM_operator_properties_create_ptr(&ptr, ot);
- RNA_enum_set(&ptr, "mode", object_mode);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
- WM_operator_properties_free(&ptr);
- return (ob->mode == object_mode);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ if (ob == NULL) {
+ return (object_mode == OB_MODE_OBJECT);
+ }
+ if (ob->mode == object_mode) {
+ return true;
+ }
+ wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_mode_set", false);
+ PointerRNA ptr;
+ WM_operator_properties_create_ptr(&ptr, ot);
+ RNA_enum_set(&ptr, "mode", object_mode);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
+ WM_operator_properties_free(&ptr);
+ return (ob->mode == object_mode);
}
/**
* Use for changing works-paces or changing active object.
* Caller can check #OB_MODE_ALL_MODE_DATA to test if this needs to be run.
*/
-static bool ed_object_mode_generic_exit_ex(
- struct Main *bmain,
- struct Depsgraph *depsgraph,
- struct Scene *scene, struct Object *ob,
- bool only_test)
+static bool ed_object_mode_generic_exit_ex(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob,
+ bool only_test)
{
- BLI_assert((bmain == NULL) == only_test);
- if (ob->mode & OB_MODE_EDIT) {
- if (BKE_object_is_in_editmode(ob)) {
- if (only_test) {
- return true;
- }
- ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
- }
- }
- else if (ob->mode & OB_MODE_VERTEX_PAINT) {
- if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_VERTEX_PAINT)) {
- if (only_test) {
- return true;
- }
- ED_object_vpaintmode_exit_ex(ob);
- }
- }
- else if (ob->mode & OB_MODE_WEIGHT_PAINT) {
- if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_WEIGHT_PAINT)) {
- if (only_test) {
- return true;
- }
- ED_object_wpaintmode_exit_ex(ob);
- }
- }
- else if (ob->mode & OB_MODE_SCULPT) {
- if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_SCULPT)) {
- if (only_test) {
- return true;
- }
- ED_object_sculptmode_exit_ex(depsgraph, scene, ob);
- }
- }
- else if (ob->mode & OB_MODE_POSE) {
- if (ob->pose != NULL) {
- if (only_test) {
- return true;
- }
- ED_object_posemode_exit_ex(bmain, ob);
- }
- }
- else {
- if (only_test) {
- return false;
- }
- BLI_assert((ob->mode & OB_MODE_ALL_MODE_DATA) == 0);
- }
+ BLI_assert((bmain == NULL) == only_test);
+ if (ob->mode & OB_MODE_EDIT) {
+ if (BKE_object_is_in_editmode(ob)) {
+ if (only_test) {
+ return true;
+ }
+ ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
+ }
+ }
+ else if (ob->mode & OB_MODE_VERTEX_PAINT) {
+ if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_VERTEX_PAINT)) {
+ if (only_test) {
+ return true;
+ }
+ ED_object_vpaintmode_exit_ex(ob);
+ }
+ }
+ else if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_WEIGHT_PAINT)) {
+ if (only_test) {
+ return true;
+ }
+ ED_object_wpaintmode_exit_ex(ob);
+ }
+ }
+ else if (ob->mode & OB_MODE_SCULPT) {
+ if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_SCULPT)) {
+ if (only_test) {
+ return true;
+ }
+ ED_object_sculptmode_exit_ex(depsgraph, scene, ob);
+ }
+ }
+ else if (ob->mode & OB_MODE_POSE) {
+ if (ob->pose != NULL) {
+ if (only_test) {
+ return true;
+ }
+ ED_object_posemode_exit_ex(bmain, ob);
+ }
+ }
+ else {
+ if (only_test) {
+ return false;
+ }
+ BLI_assert((ob->mode & OB_MODE_ALL_MODE_DATA) == 0);
+ }
- return false;
+ return false;
}
-void ED_object_mode_generic_exit(
- struct Main *bmain,
- struct Depsgraph *depsgraph,
- struct Scene *scene, struct Object *ob)
+void ED_object_mode_generic_exit(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob)
{
- ed_object_mode_generic_exit_ex(bmain, depsgraph, scene, ob, false);
+ ed_object_mode_generic_exit_ex(bmain, depsgraph, scene, ob, false);
}
-bool ED_object_mode_generic_has_data(
- struct Depsgraph *depsgraph,
- struct Object *ob)
+bool ED_object_mode_generic_has_data(struct Depsgraph *depsgraph, struct Object *ob)
{
- return ed_object_mode_generic_exit_ex(NULL, depsgraph, NULL, ob, true);
+ return ed_object_mode_generic_exit_ex(NULL, depsgraph, NULL, ob, true);
}
/** \} */
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 9576cbe6fa1..7aae0a41c85 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
@@ -95,133 +94,132 @@ static void modifier_skin_customdata_delete(struct Object *ob);
static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object *ob)
{
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- BKE_object_eval_reset(ob_eval);
- if (ob->type == OB_MESH) {
- Mesh *me_eval = mesh_create_eval_final_view(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
- BKE_id_free(NULL, me_eval);
- }
- else if (ob->type == OB_LATTICE) {
- BKE_lattice_modifiers_calc(depsgraph, scene_eval, ob_eval);
- }
- else if (ob->type == OB_MBALL) {
- BKE_displist_make_mball(depsgraph, scene_eval, ob_eval);
- }
- else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
- BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false, false, NULL);
- }
-}
-
-static void object_force_modifier_bind_simple_options(
- Depsgraph *depsgraph,
- Object *object,
- ModifierData *md)
-{
- ModifierData *md_eval = (ModifierData *)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;
-}
-
-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);
-
- /* Check compatibility of modifier [T25291, T50373]. */
- if (!BKE_object_support_modifier_type_check(ob, type)) {
- BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2);
- return NULL;
- }
-
- if (mti->flags & eModifierTypeFlag_Single) {
- if (modifiers_findByType(ob, type)) {
- BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
- return NULL;
- }
- }
-
- if (type == eModifierType_ParticleSystem) {
- /* don't need to worry about the new modifier's name, since that is set to the number
- * of particle systems which shouldn't have too many duplicates
- */
- new_md = object_add_particle_system(bmain, scene, ob, name);
- }
- else {
- /* get new modifier data to add */
- new_md = modifier_new(type);
-
- if (mti->flags & eModifierTypeFlag_RequiresOriginalData) {
- md = ob->modifiers.first;
-
- while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform)
- md = md->next;
-
- BLI_insertlinkbefore(&ob->modifiers, md, new_md);
- }
- else
- BLI_addtail(&ob->modifiers, new_md);
-
- if (name) {
- BLI_strncpy_utf8(new_md->name, name, sizeof(new_md->name));
- }
-
- /* make sure modifier data has unique name */
-
- modifier_unique_name(&ob->modifiers, new_md);
-
- /* special cases */
- if (type == eModifierType_Softbody) {
- if (!ob->soft) {
- ob->soft = sbNew(scene);
- ob->softflag |= OB_SB_GOAL | OB_SB_EDGES;
- }
- }
- else if (type == eModifierType_Collision) {
- if (!ob->pd)
- ob->pd = BKE_partdeflect_new(0);
-
- ob->pd->deflect = 1;
- }
- else if (type == eModifierType_Surface) {
- /* pass */
- }
- else if (type == eModifierType_Multires) {
- /* set totlvl from existing MDISPS layer if object already had it */
- multiresModifier_set_levels_from_disps((MultiresModifierData *)new_md, ob);
-
- if (ob->mode & OB_MODE_SCULPT) {
- /* ensure that grid paint mask layer is created */
- BKE_sculpt_mask_layers_ensure(ob, (MultiresModifierData *)new_md);
- }
- }
- else if (type == eModifierType_Skin) {
- /* ensure skin-node customdata exists */
- BKE_mesh_ensure_skin_customdata(ob->data);
- }
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(bmain);
-
- return new_md;
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ BKE_object_eval_reset(ob_eval);
+ if (ob->type == OB_MESH) {
+ Mesh *me_eval = mesh_create_eval_final_view(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
+ BKE_id_free(NULL, me_eval);
+ }
+ else if (ob->type == OB_LATTICE) {
+ BKE_lattice_modifiers_calc(depsgraph, scene_eval, ob_eval);
+ }
+ else if (ob->type == OB_MBALL) {
+ BKE_displist_make_mball(depsgraph, scene_eval, ob_eval);
+ }
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false, false, NULL);
+ }
+}
+
+static void object_force_modifier_bind_simple_options(Depsgraph *depsgraph,
+ Object *object,
+ ModifierData *md)
+{
+ ModifierData *md_eval = (ModifierData *)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;
+}
+
+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);
+
+ /* Check compatibility of modifier [T25291, T50373]. */
+ if (!BKE_object_support_modifier_type_check(ob, type)) {
+ BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2);
+ return NULL;
+ }
+
+ if (mti->flags & eModifierTypeFlag_Single) {
+ if (modifiers_findByType(ob, type)) {
+ BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
+ return NULL;
+ }
+ }
+
+ if (type == eModifierType_ParticleSystem) {
+ /* don't need to worry about the new modifier's name, since that is set to the number
+ * of particle systems which shouldn't have too many duplicates
+ */
+ new_md = object_add_particle_system(bmain, scene, ob, name);
+ }
+ else {
+ /* get new modifier data to add */
+ new_md = modifier_new(type);
+
+ if (mti->flags & eModifierTypeFlag_RequiresOriginalData) {
+ md = ob->modifiers.first;
+
+ while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform)
+ md = md->next;
+
+ BLI_insertlinkbefore(&ob->modifiers, md, new_md);
+ }
+ else
+ BLI_addtail(&ob->modifiers, new_md);
+
+ if (name) {
+ BLI_strncpy_utf8(new_md->name, name, sizeof(new_md->name));
+ }
+
+ /* make sure modifier data has unique name */
+
+ modifier_unique_name(&ob->modifiers, new_md);
+
+ /* special cases */
+ if (type == eModifierType_Softbody) {
+ if (!ob->soft) {
+ ob->soft = sbNew(scene);
+ ob->softflag |= OB_SB_GOAL | OB_SB_EDGES;
+ }
+ }
+ else if (type == eModifierType_Collision) {
+ if (!ob->pd)
+ ob->pd = BKE_partdeflect_new(0);
+
+ ob->pd->deflect = 1;
+ }
+ else if (type == eModifierType_Surface) {
+ /* pass */
+ }
+ else if (type == eModifierType_Multires) {
+ /* set totlvl from existing MDISPS layer if object already had it */
+ multiresModifier_set_levels_from_disps((MultiresModifierData *)new_md, ob);
+
+ if (ob->mode & OB_MODE_SCULPT) {
+ /* ensure that grid paint mask layer is created */
+ BKE_sculpt_mask_layers_ensure(ob, (MultiresModifierData *)new_md);
+ }
+ }
+ else if (type == eModifierType_Skin) {
+ /* ensure skin-node customdata exists */
+ BKE_mesh_ensure_skin_customdata(ob->data);
+ }
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
+
+ return new_md;
}
/* Return true if the object has a modifier of type 'type' other than
* the modifier pointed to be 'exclude', otherwise returns false. */
-static bool object_has_modifier(const Object *ob, const ModifierData *exclude,
- ModifierType type)
+static bool object_has_modifier(const Object *ob, const ModifierData *exclude, ModifierType type)
{
- ModifierData *md;
+ ModifierData *md;
- for (md = ob->modifiers.first; md; md = md->next) {
- if ((md != exclude) && (md->type == type))
- return true;
- }
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if ((md != exclude) && (md->type == type))
+ return true;
+ }
- return false;
+ return false;
}
/* If the object data of 'orig_ob' has other users, run 'callback' on
@@ -232,47 +230,44 @@ static bool object_has_modifier(const Object *ob, const ModifierData *exclude,
* If the callback ever returns true, iteration will stop and the
* function value will be true. Otherwise the function returns false.
*/
-bool ED_object_iter_other(
- Main *bmain, Object *orig_ob, const bool include_orig,
- bool (*callback)(Object *ob, void *callback_data),
- void *callback_data)
-{
- ID *ob_data_id = orig_ob->data;
- int users = ob_data_id->us;
-
- if (ob_data_id->flag & LIB_FAKEUSER)
- users--;
-
- /* First check that the object's data has multiple users */
- if (users > 1) {
- Object *ob;
- int totfound = include_orig ? 0 : 1;
-
- for (ob = bmain->objects.first; ob && totfound < users;
- ob = ob->id.next)
- {
- if (((ob != orig_ob) || include_orig) &&
- (ob->data == orig_ob->data))
- {
- if (callback(ob, callback_data))
- return true;
-
- totfound++;
- }
- }
- }
- else if (include_orig) {
- return callback(orig_ob, callback_data);
- }
-
- return false;
+bool ED_object_iter_other(Main *bmain,
+ Object *orig_ob,
+ const bool include_orig,
+ bool (*callback)(Object *ob, void *callback_data),
+ void *callback_data)
+{
+ ID *ob_data_id = orig_ob->data;
+ int users = ob_data_id->us;
+
+ if (ob_data_id->flag & LIB_FAKEUSER)
+ users--;
+
+ /* First check that the object's data has multiple users */
+ if (users > 1) {
+ Object *ob;
+ int totfound = include_orig ? 0 : 1;
+
+ for (ob = bmain->objects.first; ob && totfound < users; ob = ob->id.next) {
+ if (((ob != orig_ob) || include_orig) && (ob->data == orig_ob->data)) {
+ if (callback(ob, callback_data))
+ return true;
+
+ totfound++;
+ }
+ }
+ }
+ else if (include_orig) {
+ return callback(orig_ob, callback_data);
+ }
+
+ return false;
}
static bool object_has_modifier_cb(Object *ob, void *data)
{
- ModifierType type = *((ModifierType *)data);
+ ModifierType type = *((ModifierType *)data);
- return object_has_modifier(ob, NULL, type);
+ return object_has_modifier(ob, NULL, type);
}
/* Use with ED_object_iter_other(). Sets the total number of levels
@@ -280,2145 +275,2167 @@ static bool object_has_modifier_cb(Object *ob, void *data)
* callback_data. */
bool ED_object_multires_update_totlevels_cb(Object *ob, void *totlevel_v)
{
- ModifierData *md;
- int totlevel = *((char *)totlevel_v);
+ ModifierData *md;
+ int totlevel = *((char *)totlevel_v);
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Multires) {
- multires_set_tot_level(ob, (MultiresModifierData *)md, totlevel);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- }
- return false;
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Multires) {
+ multires_set_tot_level(ob, (MultiresModifierData *)md, totlevel);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ }
+ return false;
}
/* Return true if no modifier of type 'type' other than 'exclude' */
-static bool object_modifier_safe_to_delete(Main *bmain, Object *ob,
- ModifierData *exclude,
- ModifierType type)
-{
- return (!object_has_modifier(ob, exclude, type) &&
- !ED_object_iter_other(bmain, ob, false, object_has_modifier_cb, &type));
-}
-
-static bool object_modifier_remove(Main *bmain, Object *ob, ModifierData *md,
- bool *r_sort_depsgraph)
-{
- /* It seems on rapid delete it is possible to
- * get called twice on same modifier, so make
- * sure it is in list. */
- if (BLI_findindex(&ob->modifiers, md) == -1) {
- return 0;
- }
-
- /* special cases */
- if (md->type == eModifierType_ParticleSystem) {
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
-
- BLI_remlink(&ob->particlesystem, psmd->psys);
- psys_free(ob, psmd->psys);
- psmd->psys = NULL;
- }
- else if (md->type == eModifierType_Softbody) {
- if (ob->soft) {
- sbFree(ob);
- ob->softflag = 0; /* TODO(Sybren): this should probably be moved into sbFree() */
- }
- }
- else if (md->type == eModifierType_Collision) {
- if (ob->pd)
- ob->pd->deflect = 0;
-
- *r_sort_depsgraph = true;
- }
- else if (md->type == eModifierType_Surface) {
- *r_sort_depsgraph = true;
- }
- else if (md->type == eModifierType_Multires) {
- /* Delete MDisps layer if not used by another multires modifier */
- if (object_modifier_safe_to_delete(bmain, ob, md, eModifierType_Multires))
- multires_customdata_delete(ob->data);
- }
- else if (md->type == eModifierType_Skin) {
- /* Delete MVertSkin layer if not used by another skin modifier */
- if (object_modifier_safe_to_delete(bmain, ob, md, eModifierType_Skin))
- modifier_skin_customdata_delete(ob);
- }
-
- if (ELEM(md->type, eModifierType_Softbody, eModifierType_Cloth) &&
- BLI_listbase_is_empty(&ob->particlesystem))
- {
- ob->mode &= ~OB_MODE_PARTICLE_EDIT;
- }
-
- BLI_remlink(&ob->modifiers, md);
- modifier_free(md);
- BKE_object_free_derived_caches(ob);
-
- return 1;
+static bool object_modifier_safe_to_delete(Main *bmain,
+ Object *ob,
+ ModifierData *exclude,
+ ModifierType type)
+{
+ return (!object_has_modifier(ob, exclude, type) &&
+ !ED_object_iter_other(bmain, ob, false, object_has_modifier_cb, &type));
+}
+
+static bool object_modifier_remove(Main *bmain,
+ Object *ob,
+ ModifierData *md,
+ bool *r_sort_depsgraph)
+{
+ /* It seems on rapid delete it is possible to
+ * get called twice on same modifier, so make
+ * sure it is in list. */
+ if (BLI_findindex(&ob->modifiers, md) == -1) {
+ return 0;
+ }
+
+ /* special cases */
+ if (md->type == eModifierType_ParticleSystem) {
+ ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
+
+ BLI_remlink(&ob->particlesystem, psmd->psys);
+ psys_free(ob, psmd->psys);
+ psmd->psys = NULL;
+ }
+ else if (md->type == eModifierType_Softbody) {
+ if (ob->soft) {
+ sbFree(ob);
+ ob->softflag = 0; /* TODO(Sybren): this should probably be moved into sbFree() */
+ }
+ }
+ else if (md->type == eModifierType_Collision) {
+ if (ob->pd)
+ ob->pd->deflect = 0;
+
+ *r_sort_depsgraph = true;
+ }
+ else if (md->type == eModifierType_Surface) {
+ *r_sort_depsgraph = true;
+ }
+ else if (md->type == eModifierType_Multires) {
+ /* Delete MDisps layer if not used by another multires modifier */
+ if (object_modifier_safe_to_delete(bmain, ob, md, eModifierType_Multires))
+ multires_customdata_delete(ob->data);
+ }
+ else if (md->type == eModifierType_Skin) {
+ /* Delete MVertSkin layer if not used by another skin modifier */
+ if (object_modifier_safe_to_delete(bmain, ob, md, eModifierType_Skin))
+ modifier_skin_customdata_delete(ob);
+ }
+
+ if (ELEM(md->type, eModifierType_Softbody, eModifierType_Cloth) &&
+ BLI_listbase_is_empty(&ob->particlesystem)) {
+ ob->mode &= ~OB_MODE_PARTICLE_EDIT;
+ }
+
+ BLI_remlink(&ob->modifiers, md);
+ modifier_free(md);
+ BKE_object_free_derived_caches(ob);
+
+ return 1;
}
bool ED_object_modifier_remove(ReportList *reports, Main *bmain, Object *ob, ModifierData *md)
{
- bool sort_depsgraph = false;
- bool ok;
+ bool sort_depsgraph = false;
+ bool ok;
- ok = object_modifier_remove(bmain, ob, md, &sort_depsgraph);
+ ok = object_modifier_remove(bmain, ob, md, &sort_depsgraph);
- if (!ok) {
- BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", md->name, ob->id.name);
- return 0;
- }
+ if (!ok) {
+ BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", md->name, ob->id.name);
+ return 0;
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
- return 1;
+ return 1;
}
void ED_object_modifier_clear(Main *bmain, Object *ob)
{
- ModifierData *md = ob->modifiers.first;
- bool sort_depsgraph = false;
+ ModifierData *md = ob->modifiers.first;
+ bool sort_depsgraph = false;
- if (!md)
- return;
+ if (!md)
+ return;
- while (md) {
- ModifierData *next_md;
+ while (md) {
+ ModifierData *next_md;
- next_md = md->next;
+ next_md = md->next;
- object_modifier_remove(bmain, ob, md, &sort_depsgraph);
+ object_modifier_remove(bmain, ob, md, &sort_depsgraph);
- md = next_md;
- }
+ md = next_md;
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
}
int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md)
{
- if (md->prev) {
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ if (md->prev) {
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if (mti->type != eModifierTypeType_OnlyDeform) {
- const ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
+ if (mti->type != eModifierTypeType_OnlyDeform) {
+ const ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
- if (nmti->flags & eModifierTypeFlag_RequiresOriginalData) {
- BKE_report(reports, RPT_WARNING, "Cannot move above a modifier requiring original data");
- return 0;
- }
- }
+ if (nmti->flags & eModifierTypeFlag_RequiresOriginalData) {
+ BKE_report(reports, RPT_WARNING, "Cannot move above a modifier requiring original data");
+ return 0;
+ }
+ }
- BLI_remlink(&ob->modifiers, md);
- BLI_insertlinkbefore(&ob->modifiers, md->prev, md);
- }
+ BLI_remlink(&ob->modifiers, md);
+ BLI_insertlinkbefore(&ob->modifiers, md->prev, md);
+ }
- return 1;
+ return 1;
}
int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData *md)
{
- if (md->next) {
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ if (md->next) {
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if (mti->flags & eModifierTypeFlag_RequiresOriginalData) {
- const ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
+ if (mti->flags & eModifierTypeFlag_RequiresOriginalData) {
+ const ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
- if (nmti->type != eModifierTypeType_OnlyDeform) {
- BKE_report(reports, RPT_WARNING, "Cannot move beyond a non-deforming modifier");
- return 0;
- }
- }
+ if (nmti->type != eModifierTypeType_OnlyDeform) {
+ BKE_report(reports, RPT_WARNING, "Cannot move beyond a non-deforming modifier");
+ return 0;
+ }
+ }
- BLI_remlink(&ob->modifiers, md);
- BLI_insertlinkafter(&ob->modifiers, md->next, md);
- }
+ BLI_remlink(&ob->modifiers, md);
+ BLI_insertlinkafter(&ob->modifiers, md->next, md);
+ }
- return 1;
+ return 1;
}
int ED_object_modifier_convert(ReportList *UNUSED(reports),
- Main *bmain, Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer,
- Object *ob, ModifierData *md)
-{
- Object *obn;
- ParticleSystem *psys_orig, *psys_eval;
- ParticleCacheKey *key, **cache;
- ParticleSettings *part;
- Mesh *me;
- MVert *mvert;
- MEdge *medge;
- int a, k, kmax;
- int totvert = 0, totedge = 0, cvert = 0;
- int totpart = 0, totchild = 0;
-
- if (md->type != eModifierType_ParticleSystem) return 0;
- if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) return 0;
-
- psys_orig = ((ParticleSystemModifierData *)md)->psys;
- part = psys_orig->part;
-
- if (part->ren_as != PART_DRAW_PATH) {
- return 0;
- }
- psys_eval = psys_eval_get(depsgraph, ob, psys_orig);
- if (psys_eval->pathcache == NULL) {
- return 0;
- }
-
- totpart = psys_eval->totcached;
- totchild = psys_eval->totchildcache;
-
- if (totchild && (part->draw & PART_DRAW_PARENT) == 0)
- totpart = 0;
-
- /* count */
- cache = psys_eval->pathcache;
- for (a = 0; a < totpart; a++) {
- key = cache[a];
-
- if (key->segments > 0) {
- totvert += key->segments + 1;
- totedge += key->segments;
- }
- }
-
- cache = psys_eval->childcache;
- for (a = 0; a < totchild; a++) {
- key = cache[a];
-
- if (key->segments > 0) {
- totvert += key->segments + 1;
- totedge += key->segments;
- }
- }
-
- if (totvert == 0) return 0;
-
- /* add new mesh */
- obn = BKE_object_add(bmain, scene, view_layer, OB_MESH, NULL);
- me = obn->data;
-
- me->totvert = totvert;
- me->totedge = totedge;
-
- me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
- me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
- me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
-
- mvert = me->mvert;
- medge = me->medge;
-
- /* copy coordinates */
- cache = psys_eval->pathcache;
- for (a = 0; a < totpart; a++) {
- key = cache[a];
- kmax = key->segments;
- for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
- copy_v3_v3(mvert->co, key->co);
- if (k) {
- medge->v1 = cvert - 1;
- medge->v2 = cvert;
- medge->flag = ME_EDGEDRAW | ME_EDGERENDER | ME_LOOSEEDGE;
- medge++;
- }
- else {
- /* cheap trick to select the roots */
- mvert->flag |= SELECT;
- }
- }
- }
-
- cache = psys_eval->childcache;
- for (a = 0; a < totchild; a++) {
- key = cache[a];
- kmax = key->segments;
- for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
- copy_v3_v3(mvert->co, key->co);
- if (k) {
- medge->v1 = cvert - 1;
- medge->v2 = cvert;
- medge->flag = ME_EDGEDRAW | ME_EDGERENDER | ME_LOOSEEDGE;
- medge++;
- }
- else {
- /* cheap trick to select the roots */
- mvert->flag |= SELECT;
- }
- }
- }
-
- DEG_relations_tag_update(bmain);
-
- return 1;
+ Main *bmain,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ ViewLayer *view_layer,
+ Object *ob,
+ ModifierData *md)
+{
+ Object *obn;
+ ParticleSystem *psys_orig, *psys_eval;
+ ParticleCacheKey *key, **cache;
+ ParticleSettings *part;
+ Mesh *me;
+ MVert *mvert;
+ MEdge *medge;
+ int a, k, kmax;
+ int totvert = 0, totedge = 0, cvert = 0;
+ int totpart = 0, totchild = 0;
+
+ if (md->type != eModifierType_ParticleSystem)
+ return 0;
+ if (ob && ob->mode & OB_MODE_PARTICLE_EDIT)
+ return 0;
+
+ psys_orig = ((ParticleSystemModifierData *)md)->psys;
+ part = psys_orig->part;
+
+ if (part->ren_as != PART_DRAW_PATH) {
+ return 0;
+ }
+ psys_eval = psys_eval_get(depsgraph, ob, psys_orig);
+ if (psys_eval->pathcache == NULL) {
+ return 0;
+ }
+
+ totpart = psys_eval->totcached;
+ totchild = psys_eval->totchildcache;
+
+ if (totchild && (part->draw & PART_DRAW_PARENT) == 0)
+ totpart = 0;
+
+ /* count */
+ cache = psys_eval->pathcache;
+ for (a = 0; a < totpart; a++) {
+ key = cache[a];
+
+ if (key->segments > 0) {
+ totvert += key->segments + 1;
+ totedge += key->segments;
+ }
+ }
+
+ cache = psys_eval->childcache;
+ for (a = 0; a < totchild; a++) {
+ key = cache[a];
+
+ if (key->segments > 0) {
+ totvert += key->segments + 1;
+ totedge += key->segments;
+ }
+ }
+
+ if (totvert == 0)
+ return 0;
+
+ /* add new mesh */
+ obn = BKE_object_add(bmain, scene, view_layer, OB_MESH, NULL);
+ me = obn->data;
+
+ me->totvert = totvert;
+ me->totedge = totedge;
+
+ me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
+ me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
+ me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
+
+ mvert = me->mvert;
+ medge = me->medge;
+
+ /* copy coordinates */
+ cache = psys_eval->pathcache;
+ for (a = 0; a < totpart; a++) {
+ key = cache[a];
+ kmax = key->segments;
+ for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
+ copy_v3_v3(mvert->co, key->co);
+ if (k) {
+ medge->v1 = cvert - 1;
+ medge->v2 = cvert;
+ medge->flag = ME_EDGEDRAW | ME_EDGERENDER | ME_LOOSEEDGE;
+ medge++;
+ }
+ else {
+ /* cheap trick to select the roots */
+ mvert->flag |= SELECT;
+ }
+ }
+ }
+
+ cache = psys_eval->childcache;
+ for (a = 0; a < totchild; a++) {
+ key = cache[a];
+ kmax = key->segments;
+ for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
+ copy_v3_v3(mvert->co, key->co);
+ if (k) {
+ medge->v1 = cvert - 1;
+ medge->v2 = cvert;
+ medge->flag = ME_EDGEDRAW | ME_EDGERENDER | ME_LOOSEEDGE;
+ medge++;
+ }
+ else {
+ /* cheap trick to select the roots */
+ mvert->flag |= SELECT;
+ }
+ }
+ }
+
+ DEG_relations_tag_update(bmain);
+
+ return 1;
}
/* Gets mesh for the modifier which corresponds to an evaluated state. */
-static Mesh *modifier_apply_create_mesh_for_modifier(
- Depsgraph *depsgraph,
- Scene *UNUSED(scene),
- Object *object,
- ModifierData *md,
- bool build_shapekey_layers)
-{
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
- ModifierData *md_eval = modifiers_findByName(object_eval, md->name);
- Mesh *mesh_applied = BKE_mesh_create_derived_for_modifier(
- depsgraph, scene_eval, object_eval, md_eval, build_shapekey_layers);
- return mesh_applied;
-}
-
-static int modifier_apply_shape(
- Main *bmain, ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md)
-{
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
-
- if (mti->isDisabled && mti->isDisabled(scene, md, 0)) {
- BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
- return 0;
- }
-
- /*
- * It should be ridiculously easy to extract the original verts that we want
- * and form the shape data. We can probably use the CD KEYINDEX layer (or
- * whatever I ended up calling it, too tired to check now), though this would
- * by necessity have to make some potentially ugly assumptions about the order
- * of the mesh data :-/ you can probably assume in 99% of cases that the first
- * element of a given index is the original, and any subsequent duplicates are
- * copies/interpolates, but that's an assumption that would need to be tested
- * and then predominantly stated in comments in a half dozen headers.
- */
-
- if (ob->type == OB_MESH) {
- Mesh *mesh_applied;
- Mesh *me = ob->data;
- Key *key = me->key;
- KeyBlock *kb;
-
- if (!modifier_isSameTopology(md) || mti->type == eModifierTypeType_NonGeometrical) {
- BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to shapes");
- return 0;
- }
-
- mesh_applied = modifier_apply_create_mesh_for_modifier(depsgraph, scene, ob, md, false);
- if (!mesh_applied) {
- BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
- return 0;
- }
-
- if (key == NULL) {
- key = me->key = BKE_key_add(bmain, (ID *)me);
- key->type = KEY_RELATIVE;
- /* if that was the first key block added, then it was the basis.
- * Initialize it with the mesh, and add another for the modifier */
- kb = BKE_keyblock_add(key, NULL);
- BKE_keyblock_convert_from_mesh(me, key, kb);
- }
-
- kb = BKE_keyblock_add(key, md->name);
- BKE_mesh_nomain_to_meshkey(mesh_applied, me, kb);
-
- BKE_id_free(NULL, mesh_applied);
- }
- else {
- BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
- return 0;
- }
- return 1;
-}
-
-static int modifier_apply_obdata(ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md)
-{
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
-
- if (mti->isDisabled && mti->isDisabled(scene, md, 0)) {
- BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
- return 0;
- }
-
- if (ob->type == OB_MESH) {
- Mesh *mesh_applied;
- Mesh *me = ob->data;
- MultiresModifierData *mmd = find_multires_modifier_before(scene, md);
-
- if (me->key && mti->type != eModifierTypeType_NonGeometrical) {
- BKE_report(reports, RPT_ERROR, "Modifier cannot be applied to a mesh with shape keys");
- return 0;
- }
-
- /* Multires: ensure that recent sculpting is applied */
- if (md->type == eModifierType_Multires)
- multires_force_update(ob);
-
- if (mmd && mmd->totlvl && mti->type == eModifierTypeType_OnlyDeform) {
- if (!multiresModifier_reshapeFromDeformModifier(depsgraph, mmd, ob, md)) {
- BKE_report(reports, RPT_ERROR, "Multires modifier returned error, skipping apply");
- return 0;
- }
- }
- else {
- mesh_applied = modifier_apply_create_mesh_for_modifier(depsgraph, scene, ob, md, true);
- if (!mesh_applied) {
- BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply");
- return 0;
- }
-
- BKE_mesh_nomain_to_mesh(mesh_applied, me, ob, &CD_MASK_MESH, true);
-
- if (md->type == eModifierType_Multires)
- multires_customdata_delete(me);
- }
- }
- else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
- Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
- Curve *curve = ob->data;
- Curve *curve_eval = (Curve *)object_eval->data;
- int numVerts;
- float (*vertexCos)[3];
- ModifierEvalContext mectx = {depsgraph, object_eval, 0};
-
- if (ELEM(mti->type, eModifierTypeType_Constructive, eModifierTypeType_Nonconstructive)) {
- BKE_report(reports, RPT_ERROR, "Transform curve to mesh in order to apply constructive modifiers");
- return 0;
- }
-
- BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tessellated/bevel vertices");
-
- vertexCos = BKE_curve_nurbs_vertexCos_get(&curve_eval->nurb, &numVerts);
- mti->deformVerts(md, &mectx, NULL, vertexCos, numVerts);
- BK_curve_nurbs_vertexCos_apply(&curve->nurb, vertexCos);
-
- MEM_freeN(vertexCos);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- else {
- BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
- return 0;
- }
-
- /* lattice modifier can be applied to particle system too */
- if (ob->particlesystem.first) {
-
- ParticleSystem *psys = ob->particlesystem.first;
-
- for (; psys; psys = psys->next) {
-
- if (psys->part->type != PART_HAIR)
- continue;
-
- psys_apply_hair_lattice(depsgraph, scene, ob, psys);
- }
- }
-
- return 1;
-}
-
-int 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;
- }
- else if (((ID *) ob->data)->us > 1) {
- BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
- return 0;
- }
- else if ((ob->mode & OB_MODE_SCULPT) &&
- (find_multires_modifier_before(scene, md)) &&
- (modifier_isSameTopology(md) == false))
- {
- BKE_report(reports, RPT_ERROR, "Constructive modifier cannot be applied to multi-res data in sculpt mode");
- return 0;
- }
-
- if (md != ob->modifiers.first)
- BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");
-
- /* 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;
-
- /* allow apply of a not-realtime modifier, by first re-enabling realtime. */
- prev_mode = md_eval->mode;
- md_eval->mode |= eModifierMode_Realtime;
-
- if (mode == MODIFIER_APPLY_SHAPE) {
- if (!modifier_apply_shape(bmain, reports, depsgraph, scene, ob, md_eval)) {
- md_eval->mode = prev_mode;
- return 0;
- }
- }
- else {
- if (!modifier_apply_obdata(reports, depsgraph, scene, ob, md_eval)) {
- md_eval->mode = prev_mode;
- return 0;
- }
- }
-
- md_eval->mode = prev_mode;
- BLI_remlink(&ob->modifiers, md);
- modifier_free(md);
-
- BKE_object_free_derived_caches(ob);
-
- return 1;
+static Mesh *modifier_apply_create_mesh_for_modifier(Depsgraph *depsgraph,
+ Scene *UNUSED(scene),
+ Object *object,
+ ModifierData *md,
+ bool build_shapekey_layers)
+{
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
+ ModifierData *md_eval = modifiers_findByName(object_eval, md->name);
+ Mesh *mesh_applied = BKE_mesh_create_derived_for_modifier(
+ depsgraph, scene_eval, object_eval, md_eval, build_shapekey_layers);
+ return mesh_applied;
+}
+
+static int modifier_apply_shape(Main *bmain,
+ ReportList *reports,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ ModifierData *md)
+{
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+
+ if (mti->isDisabled && mti->isDisabled(scene, md, 0)) {
+ BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
+ return 0;
+ }
+
+ /*
+ * It should be ridiculously easy to extract the original verts that we want
+ * and form the shape data. We can probably use the CD KEYINDEX layer (or
+ * whatever I ended up calling it, too tired to check now), though this would
+ * by necessity have to make some potentially ugly assumptions about the order
+ * of the mesh data :-/ you can probably assume in 99% of cases that the first
+ * element of a given index is the original, and any subsequent duplicates are
+ * copies/interpolates, but that's an assumption that would need to be tested
+ * and then predominantly stated in comments in a half dozen headers.
+ */
+
+ if (ob->type == OB_MESH) {
+ Mesh *mesh_applied;
+ Mesh *me = ob->data;
+ Key *key = me->key;
+ KeyBlock *kb;
+
+ if (!modifier_isSameTopology(md) || mti->type == eModifierTypeType_NonGeometrical) {
+ BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to shapes");
+ return 0;
+ }
+
+ mesh_applied = modifier_apply_create_mesh_for_modifier(depsgraph, scene, ob, md, false);
+ if (!mesh_applied) {
+ BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
+ return 0;
+ }
+
+ if (key == NULL) {
+ key = me->key = BKE_key_add(bmain, (ID *)me);
+ key->type = KEY_RELATIVE;
+ /* if that was the first key block added, then it was the basis.
+ * Initialize it with the mesh, and add another for the modifier */
+ kb = BKE_keyblock_add(key, NULL);
+ BKE_keyblock_convert_from_mesh(me, key, kb);
+ }
+
+ kb = BKE_keyblock_add(key, md->name);
+ BKE_mesh_nomain_to_meshkey(mesh_applied, me, kb);
+
+ BKE_id_free(NULL, mesh_applied);
+ }
+ else {
+ BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
+ return 0;
+ }
+ return 1;
+}
+
+static int modifier_apply_obdata(
+ ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md)
+{
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+
+ if (mti->isDisabled && mti->isDisabled(scene, md, 0)) {
+ BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
+ return 0;
+ }
+
+ if (ob->type == OB_MESH) {
+ Mesh *mesh_applied;
+ Mesh *me = ob->data;
+ MultiresModifierData *mmd = find_multires_modifier_before(scene, md);
+
+ if (me->key && mti->type != eModifierTypeType_NonGeometrical) {
+ BKE_report(reports, RPT_ERROR, "Modifier cannot be applied to a mesh with shape keys");
+ return 0;
+ }
+
+ /* Multires: ensure that recent sculpting is applied */
+ if (md->type == eModifierType_Multires)
+ multires_force_update(ob);
+
+ if (mmd && mmd->totlvl && mti->type == eModifierTypeType_OnlyDeform) {
+ if (!multiresModifier_reshapeFromDeformModifier(depsgraph, mmd, ob, md)) {
+ BKE_report(reports, RPT_ERROR, "Multires modifier returned error, skipping apply");
+ return 0;
+ }
+ }
+ else {
+ mesh_applied = modifier_apply_create_mesh_for_modifier(depsgraph, scene, ob, md, true);
+ if (!mesh_applied) {
+ BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply");
+ return 0;
+ }
+
+ BKE_mesh_nomain_to_mesh(mesh_applied, me, ob, &CD_MASK_MESH, true);
+
+ if (md->type == eModifierType_Multires)
+ multires_customdata_delete(me);
+ }
+ }
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
+ Curve *curve = ob->data;
+ Curve *curve_eval = (Curve *)object_eval->data;
+ int numVerts;
+ float(*vertexCos)[3];
+ ModifierEvalContext mectx = {depsgraph, object_eval, 0};
+
+ if (ELEM(mti->type, eModifierTypeType_Constructive, eModifierTypeType_Nonconstructive)) {
+ BKE_report(
+ reports, RPT_ERROR, "Transform curve to mesh in order to apply constructive modifiers");
+ return 0;
+ }
+
+ BKE_report(reports,
+ RPT_INFO,
+ "Applied modifier only changed CV points, not tessellated/bevel vertices");
+
+ vertexCos = BKE_curve_nurbs_vertexCos_get(&curve_eval->nurb, &numVerts);
+ mti->deformVerts(md, &mectx, NULL, vertexCos, numVerts);
+ BK_curve_nurbs_vertexCos_apply(&curve->nurb, vertexCos);
+
+ MEM_freeN(vertexCos);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ else {
+ BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
+ return 0;
+ }
+
+ /* lattice modifier can be applied to particle system too */
+ if (ob->particlesystem.first) {
+
+ ParticleSystem *psys = ob->particlesystem.first;
+
+ for (; psys; psys = psys->next) {
+
+ if (psys->part->type != PART_HAIR)
+ continue;
+
+ psys_apply_hair_lattice(depsgraph, scene, ob, psys);
+ }
+ }
+
+ return 1;
+}
+
+int 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;
+ }
+ else if (((ID *)ob->data)->us > 1) {
+ BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
+ return 0;
+ }
+ else if ((ob->mode & OB_MODE_SCULPT) && (find_multires_modifier_before(scene, md)) &&
+ (modifier_isSameTopology(md) == false)) {
+ BKE_report(reports,
+ RPT_ERROR,
+ "Constructive modifier cannot be applied to multi-res data in sculpt mode");
+ return 0;
+ }
+
+ if (md != ob->modifiers.first)
+ BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");
+
+ /* 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;
+
+ /* allow apply of a not-realtime modifier, by first re-enabling realtime. */
+ prev_mode = md_eval->mode;
+ md_eval->mode |= eModifierMode_Realtime;
+
+ if (mode == MODIFIER_APPLY_SHAPE) {
+ if (!modifier_apply_shape(bmain, reports, depsgraph, scene, ob, md_eval)) {
+ md_eval->mode = prev_mode;
+ return 0;
+ }
+ }
+ else {
+ if (!modifier_apply_obdata(reports, depsgraph, scene, ob, md_eval)) {
+ md_eval->mode = prev_mode;
+ return 0;
+ }
+ }
+
+ md_eval->mode = prev_mode;
+ BLI_remlink(&ob->modifiers, md);
+ modifier_free(md);
+
+ BKE_object_free_derived_caches(ob);
+
+ return 1;
}
int ED_object_modifier_copy(ReportList *UNUSED(reports), Object *ob, ModifierData *md)
{
- ModifierData *nmd;
+ ModifierData *nmd;
- nmd = modifier_new(md->type);
- modifier_copyData(md, nmd);
- BLI_insertlinkafter(&ob->modifiers, md, nmd);
- modifier_unique_name(&ob->modifiers, nmd);
+ nmd = modifier_new(md->type);
+ modifier_copyData(md, nmd);
+ BLI_insertlinkafter(&ob->modifiers, md, nmd);
+ modifier_unique_name(&ob->modifiers, nmd);
- return 1;
+ return 1;
}
/************************ add modifier operator *********************/
static int modifier_add_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- int type = RNA_enum_get(op->ptr, "type");
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ int type = RNA_enum_get(op->ptr, "type");
- if (!ED_object_modifier_add(op->reports, bmain, scene, ob, NULL, type))
- return OPERATOR_CANCELLED;
+ if (!ED_object_modifier_add(op->reports, bmain, scene, ob, NULL, type))
+ return OPERATOR_CANCELLED;
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static const EnumPropertyItem *modifier_add_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *modifier_add_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- Object *ob = ED_object_active_context(C);
- EnumPropertyItem *item = NULL;
- const EnumPropertyItem *md_item, *group_item = NULL;
- const ModifierTypeInfo *mti;
- int totitem = 0, a;
+ Object *ob = ED_object_active_context(C);
+ EnumPropertyItem *item = NULL;
+ const EnumPropertyItem *md_item, *group_item = NULL;
+ const ModifierTypeInfo *mti;
+ int totitem = 0, a;
- if (!ob)
- return rna_enum_object_modifier_type_items;
+ if (!ob)
+ return rna_enum_object_modifier_type_items;
- for (a = 0; rna_enum_object_modifier_type_items[a].identifier; a++) {
- md_item = &rna_enum_object_modifier_type_items[a];
+ for (a = 0; rna_enum_object_modifier_type_items[a].identifier; a++) {
+ md_item = &rna_enum_object_modifier_type_items[a];
- if (md_item->identifier[0]) {
- mti = modifierType_getInfo(md_item->value);
+ if (md_item->identifier[0]) {
+ mti = modifierType_getInfo(md_item->value);
- if (mti->flags & eModifierTypeFlag_NoUserAdd)
- continue;
+ if (mti->flags & eModifierTypeFlag_NoUserAdd)
+ continue;
- if (!BKE_object_support_modifier_type_check(ob, md_item->value))
- continue;
- }
- else {
- group_item = md_item;
- md_item = NULL;
+ if (!BKE_object_support_modifier_type_check(ob, md_item->value))
+ continue;
+ }
+ else {
+ group_item = md_item;
+ md_item = NULL;
- continue;
- }
+ continue;
+ }
- if (group_item) {
- RNA_enum_item_add(&item, &totitem, group_item);
- group_item = NULL;
- }
+ if (group_item) {
+ RNA_enum_item_add(&item, &totitem, group_item);
+ group_item = NULL;
+ }
- RNA_enum_item_add(&item, &totitem, md_item);
- }
+ RNA_enum_item_add(&item, &totitem, md_item);
+ }
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
- return item;
+ return item;
}
void OBJECT_OT_modifier_add(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Add Modifier";
- ot->description = "Add a procedural operation/effect to the active object";
- ot->idname = "OBJECT_OT_modifier_add";
+ /* identifiers */
+ ot->name = "Add Modifier";
+ ot->description = "Add a procedural operation/effect to the active object";
+ ot->idname = "OBJECT_OT_modifier_add";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = modifier_add_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = modifier_add_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- prop = RNA_def_enum(ot->srna, "type", rna_enum_object_modifier_type_items, eModifierType_Subsurf, "Type", "");
- RNA_def_enum_funcs(prop, modifier_add_itemf);
- ot->prop = prop;
+ /* properties */
+ prop = RNA_def_enum(
+ ot->srna, "type", rna_enum_object_modifier_type_items, eModifierType_Subsurf, "Type", "");
+ RNA_def_enum_funcs(prop, modifier_add_itemf);
+ ot->prop = prop;
}
/************************ generic functions for operators using mod names and data context *********************/
bool edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
- Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
+ Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
- if (!ob || ID_IS_LINKED(ob)) return 0;
- if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) return 0;
- if (ptr.id.data && ID_IS_LINKED(ptr.id.data)) return 0;
+ if (!ob || ID_IS_LINKED(ob))
+ return 0;
+ if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0)
+ return 0;
+ if (ptr.id.data && ID_IS_LINKED(ptr.id.data))
+ return 0;
- if (ID_IS_STATIC_OVERRIDE(ob)) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from static override");
- return (((ModifierData *)ptr.data)->flag & eModifierFlag_StaticOverride_Local) != 0;
- }
+ if (ID_IS_STATIC_OVERRIDE(ob)) {
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from static override");
+ return (((ModifierData *)ptr.data)->flag & eModifierFlag_StaticOverride_Local) != 0;
+ }
- return 1;
+ return 1;
}
bool edit_modifier_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_Modifier, 0);
+ return edit_modifier_poll_generic(C, &RNA_Modifier, 0);
}
void edit_modifier_properties(wmOperatorType *ot)
{
- PropertyRNA *prop = RNA_def_string(ot->srna, "modifier", NULL, MAX_NAME, "Modifier", "Name of the modifier to edit");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop = RNA_def_string(
+ ot->srna, "modifier", NULL, MAX_NAME, "Modifier", "Name of the modifier to edit");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
{
- ModifierData *md;
+ ModifierData *md;
- if (RNA_struct_property_is_set(op->ptr, "modifier")) {
- return true;
- }
- else {
- PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
- if (ptr.data) {
- md = ptr.data;
- RNA_string_set(op->ptr, "modifier", md->name);
- return true;
- }
- }
+ if (RNA_struct_property_is_set(op->ptr, "modifier")) {
+ return true;
+ }
+ else {
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
+ if (ptr.data) {
+ md = ptr.data;
+ RNA_string_set(op->ptr, "modifier", md->name);
+ return true;
+ }
+ }
- return false;
+ return false;
}
ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
{
- char modifier_name[MAX_NAME];
- ModifierData *md;
- RNA_string_get(op->ptr, "modifier", modifier_name);
+ char modifier_name[MAX_NAME];
+ ModifierData *md;
+ RNA_string_get(op->ptr, "modifier", modifier_name);
- md = modifiers_findByName(ob, modifier_name);
+ md = modifiers_findByName(ob, modifier_name);
- if (md && type != 0 && md->type != type)
- md = NULL;
+ if (md && type != 0 && md->type != type)
+ md = NULL;
- return md;
+ return md;
}
/************************ remove modifier operator *********************/
static int modifier_remove_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = ED_object_active_context(C);
- ModifierData *md = edit_modifier_property_get(op, ob, 0);
- int mode_orig = ob->mode;
+ Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = ED_object_active_context(C);
+ ModifierData *md = edit_modifier_property_get(op, ob, 0);
+ int mode_orig = ob->mode;
- if (!md || !ED_object_modifier_remove(op->reports, bmain, ob, md))
- return OPERATOR_CANCELLED;
+ if (!md || !ED_object_modifier_remove(op->reports, bmain, ob, md))
+ return OPERATOR_CANCELLED;
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- /* if cloth/softbody was removed, particle mode could be cleared */
- if (mode_orig & OB_MODE_PARTICLE_EDIT) {
- if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) {
- if (ob == OBACT(view_layer)) {
- WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
- }
- }
- }
- return OPERATOR_FINISHED;
+ /* if cloth/softbody was removed, particle mode could be cleared */
+ if (mode_orig & OB_MODE_PARTICLE_EDIT) {
+ if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) {
+ if (ob == OBACT(view_layer)) {
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
+ }
+ }
+ }
+ return OPERATOR_FINISHED;
}
static int modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return modifier_remove_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return modifier_remove_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_modifier_remove(wmOperatorType *ot)
{
- ot->name = "Remove Modifier";
- ot->description = "Remove a modifier from the active object";
- ot->idname = "OBJECT_OT_modifier_remove";
+ ot->name = "Remove Modifier";
+ ot->description = "Remove a modifier from the active object";
+ ot->idname = "OBJECT_OT_modifier_remove";
- ot->invoke = modifier_remove_invoke;
- ot->exec = modifier_remove_exec;
- ot->poll = edit_modifier_poll;
+ ot->invoke = modifier_remove_invoke;
+ ot->exec = modifier_remove_exec;
+ ot->poll = edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/************************ move up modifier operator *********************/
static int modifier_move_up_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- ModifierData *md = edit_modifier_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ ModifierData *md = edit_modifier_property_get(op, ob, 0);
- if (!md || !ED_object_modifier_move_up(op->reports, ob, md))
- return OPERATOR_CANCELLED;
+ if (!md || !ED_object_modifier_move_up(op->reports, ob, md))
+ return OPERATOR_CANCELLED;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return modifier_move_up_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return modifier_move_up_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_modifier_move_up(wmOperatorType *ot)
{
- ot->name = "Move Up Modifier";
- ot->description = "Move modifier up in the stack";
- ot->idname = "OBJECT_OT_modifier_move_up";
+ ot->name = "Move Up Modifier";
+ ot->description = "Move modifier up in the stack";
+ ot->idname = "OBJECT_OT_modifier_move_up";
- ot->invoke = modifier_move_up_invoke;
- ot->exec = modifier_move_up_exec;
- ot->poll = edit_modifier_poll;
+ ot->invoke = modifier_move_up_invoke;
+ ot->exec = modifier_move_up_exec;
+ ot->poll = edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/************************ move down modifier operator *********************/
static int modifier_move_down_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- ModifierData *md = edit_modifier_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ ModifierData *md = edit_modifier_property_get(op, ob, 0);
- if (!md || !ED_object_modifier_move_down(op->reports, ob, md))
- return OPERATOR_CANCELLED;
+ if (!md || !ED_object_modifier_move_down(op->reports, ob, md))
+ return OPERATOR_CANCELLED;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return modifier_move_down_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return modifier_move_down_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
{
- ot->name = "Move Down Modifier";
- ot->description = "Move modifier down in the stack";
- ot->idname = "OBJECT_OT_modifier_move_down";
+ ot->name = "Move Down Modifier";
+ ot->description = "Move modifier down in the stack";
+ ot->idname = "OBJECT_OT_modifier_move_down";
- ot->invoke = modifier_move_down_invoke;
- ot->exec = modifier_move_down_exec;
- ot->poll = edit_modifier_poll;
+ ot->invoke = modifier_move_down_invoke;
+ ot->exec = modifier_move_down_exec;
+ ot->poll = edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/************************ apply modifier operator *********************/
static int modifier_apply_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- ModifierData *md = edit_modifier_property_get(op, ob, 0);
- int apply_as = RNA_enum_get(op->ptr, "apply_as");
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ ModifierData *md = edit_modifier_property_get(op, ob, 0);
+ int apply_as = RNA_enum_get(op->ptr, "apply_as");
- if (!md || !ED_object_modifier_apply(bmain, op->reports, depsgraph, scene, ob, md, apply_as)) {
- return OPERATOR_CANCELLED;
- }
+ if (!md || !ED_object_modifier_apply(bmain, op->reports, depsgraph, scene, ob, md, apply_as)) {
+ return OPERATOR_CANCELLED;
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return modifier_apply_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return modifier_apply_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
static const EnumPropertyItem modifier_apply_as_items[] = {
- {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
- {MODIFIER_APPLY_SHAPE, "SHAPE", 0, "New Shape", "Apply deform-only modifier to a new shape on this object"},
- {0, NULL, 0, NULL, NULL},
+ {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
+ {MODIFIER_APPLY_SHAPE,
+ "SHAPE",
+ 0,
+ "New Shape",
+ "Apply deform-only modifier to a new shape on this object"},
+ {0, NULL, 0, NULL, NULL},
};
void OBJECT_OT_modifier_apply(wmOperatorType *ot)
{
- ot->name = "Apply Modifier";
- ot->description = "Apply modifier and remove from the stack";
- ot->idname = "OBJECT_OT_modifier_apply";
+ ot->name = "Apply Modifier";
+ ot->description = "Apply modifier and remove from the stack";
+ ot->idname = "OBJECT_OT_modifier_apply";
- ot->invoke = modifier_apply_invoke;
- ot->exec = modifier_apply_exec;
- ot->poll = edit_modifier_poll;
+ ot->invoke = modifier_apply_invoke;
+ ot->exec = modifier_apply_exec;
+ ot->poll = edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- RNA_def_enum(ot->srna, "apply_as", modifier_apply_as_items, MODIFIER_APPLY_DATA, "Apply as", "How to apply the modifier to the geometry");
- edit_modifier_properties(ot);
+ RNA_def_enum(ot->srna,
+ "apply_as",
+ modifier_apply_as_items,
+ MODIFIER_APPLY_DATA,
+ "Apply as",
+ "How to apply the modifier to the geometry");
+ edit_modifier_properties(ot);
}
/************************ convert modifier operator *********************/
static int modifier_convert_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = ED_object_active_context(C);
- ModifierData *md = edit_modifier_property_get(op, ob, 0);
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = ED_object_active_context(C);
+ ModifierData *md = edit_modifier_property_get(op, ob, 0);
- if (!md || !ED_object_modifier_convert(op->reports, bmain, depsgraph, scene, view_layer, ob, md))
- return OPERATOR_CANCELLED;
+ if (!md || !ED_object_modifier_convert(op->reports, bmain, depsgraph, scene, view_layer, ob, md))
+ return OPERATOR_CANCELLED;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int modifier_convert_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return modifier_convert_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return modifier_convert_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_modifier_convert(wmOperatorType *ot)
{
- ot->name = "Convert Modifier";
- ot->description = "Convert particles to a mesh object";
- ot->idname = "OBJECT_OT_modifier_convert";
+ ot->name = "Convert Modifier";
+ ot->description = "Convert particles to a mesh object";
+ ot->idname = "OBJECT_OT_modifier_convert";
- ot->invoke = modifier_convert_invoke;
- ot->exec = modifier_convert_exec;
- ot->poll = edit_modifier_poll;
+ ot->invoke = modifier_convert_invoke;
+ ot->exec = modifier_convert_exec;
+ ot->poll = edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/************************ copy modifier operator *********************/
static int modifier_copy_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- ModifierData *md = edit_modifier_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ ModifierData *md = edit_modifier_property_get(op, ob, 0);
- if (!md || !ED_object_modifier_copy(op->reports, ob, md))
- return OPERATOR_CANCELLED;
+ if (!md || !ED_object_modifier_copy(op->reports, ob, md))
+ return OPERATOR_CANCELLED;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return modifier_copy_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return modifier_copy_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_modifier_copy(wmOperatorType *ot)
{
- ot->name = "Copy Modifier";
- ot->description = "Duplicate modifier at the same position in the stack";
- ot->idname = "OBJECT_OT_modifier_copy";
+ ot->name = "Copy Modifier";
+ ot->description = "Duplicate modifier at the same position in the stack";
+ ot->idname = "OBJECT_OT_modifier_copy";
- ot->invoke = modifier_copy_invoke;
- ot->exec = modifier_copy_exec;
- ot->poll = edit_modifier_poll;
+ ot->invoke = modifier_copy_invoke;
+ ot->exec = modifier_copy_exec;
+ ot->poll = edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/************* multires delete higher levels operator ****************/
static bool multires_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_MultiresModifier, (1 << OB_MESH));
+ return edit_modifier_poll_generic(C, &RNA_MultiresModifier, (1 << OB_MESH));
}
static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_Multires);
- if (!mmd)
- return OPERATOR_CANCELLED;
+ if (!mmd)
+ return OPERATOR_CANCELLED;
- multiresModifier_del_levels(mmd, scene, ob, 1);
+ multiresModifier_del_levels(mmd, scene, ob, 1);
- ED_object_iter_other(
- CTX_data_main(C), ob, true,
- ED_object_multires_update_totlevels_cb,
- &mmd->totlvl);
+ ED_object_iter_other(
+ CTX_data_main(C), ob, true, ED_object_multires_update_totlevels_cb, &mmd->totlvl);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int multires_higher_levels_delete_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return multires_higher_levels_delete_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return multires_higher_levels_delete_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot)
{
- ot->name = "Delete Higher Levels";
- ot->description = "Deletes the higher resolution mesh, potential loss of detail";
- ot->idname = "OBJECT_OT_multires_higher_levels_delete";
+ ot->name = "Delete Higher Levels";
+ ot->description = "Deletes the higher resolution mesh, potential loss of detail";
+ ot->idname = "OBJECT_OT_multires_higher_levels_delete";
- ot->poll = multires_poll;
- ot->invoke = multires_higher_levels_delete_invoke;
- ot->exec = multires_higher_levels_delete_exec;
+ ot->poll = multires_poll;
+ ot->invoke = multires_higher_levels_delete_invoke;
+ ot->exec = multires_higher_levels_delete_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/****************** multires subdivide operator *********************/
static int multires_subdivide_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_Multires);
- if (!mmd)
- return OPERATOR_CANCELLED;
+ if (!mmd)
+ return OPERATOR_CANCELLED;
- multiresModifier_subdivide(mmd, scene, ob, 0, mmd->simple);
+ multiresModifier_subdivide(mmd, scene, ob, 0, mmd->simple);
- ED_object_iter_other(
- CTX_data_main(C), ob, true,
- ED_object_multires_update_totlevels_cb,
- &mmd->totlvl);
+ ED_object_iter_other(
+ CTX_data_main(C), ob, 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(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- if (ob->mode & OB_MODE_SCULPT) {
- /* ensure that grid paint mask layer is created */
- BKE_sculpt_mask_layers_ensure(ob, mmd);
- }
+ if (ob->mode & OB_MODE_SCULPT) {
+ /* ensure that grid paint mask layer is created */
+ BKE_sculpt_mask_layers_ensure(ob, mmd);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int multires_subdivide_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return multires_subdivide_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return multires_subdivide_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_multires_subdivide(wmOperatorType *ot)
{
- ot->name = "Multires Subdivide";
- ot->description = "Add a new level of subdivision";
- ot->idname = "OBJECT_OT_multires_subdivide";
+ ot->name = "Multires Subdivide";
+ ot->description = "Add a new level of subdivision";
+ ot->idname = "OBJECT_OT_multires_subdivide";
- ot->poll = multires_poll;
- ot->invoke = multires_subdivide_invoke;
- ot->exec = multires_subdivide_exec;
+ ot->poll = multires_poll;
+ ot->invoke = multires_subdivide_invoke;
+ ot->exec = multires_subdivide_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/****************** multires reshape operator *********************/
static int multires_reshape_exec(bContext *C, wmOperator *op)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *ob = ED_object_active_context(C), *secondob = NULL;
- MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob = ED_object_active_context(C), *secondob = NULL;
+ MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_Multires);
- if (!mmd)
- return OPERATOR_CANCELLED;
+ if (!mmd)
+ return OPERATOR_CANCELLED;
- if (mmd->lvl == 0) {
- BKE_report(op->reports, RPT_ERROR, "Reshape can work only with higher levels of subdivisions");
- return OPERATOR_CANCELLED;
- }
+ if (mmd->lvl == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Reshape can work only with higher levels of subdivisions");
+ return OPERATOR_CANCELLED;
+ }
- CTX_DATA_BEGIN(C, Object *, selob, selected_editable_objects)
- {
- if (selob->type == OB_MESH && selob != ob) {
- secondob = selob;
- break;
- }
- }
- CTX_DATA_END;
+ CTX_DATA_BEGIN (C, Object *, selob, selected_editable_objects) {
+ if (selob->type == OB_MESH && selob != ob) {
+ secondob = selob;
+ break;
+ }
+ }
+ CTX_DATA_END;
- if (!secondob) {
- BKE_report(op->reports, RPT_ERROR, "Second selected mesh object required to copy shape from");
- return OPERATOR_CANCELLED;
- }
+ if (!secondob) {
+ BKE_report(op->reports, RPT_ERROR, "Second selected mesh object required to copy shape from");
+ return OPERATOR_CANCELLED;
+ }
- if (!multiresModifier_reshapeFromObject(depsgraph, mmd, ob, secondob)) {
- BKE_report(op->reports, RPT_ERROR, "Objects do not have the same number of vertices");
- return OPERATOR_CANCELLED;
- }
+ if (!multiresModifier_reshapeFromObject(depsgraph, mmd, ob, secondob)) {
+ BKE_report(op->reports, RPT_ERROR, "Objects do not have the same number of vertices");
+ return OPERATOR_CANCELLED;
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int multires_reshape_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return multires_reshape_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return multires_reshape_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_multires_reshape(wmOperatorType *ot)
{
- ot->name = "Multires Reshape";
- ot->description = "Copy vertex coordinates from other object";
- ot->idname = "OBJECT_OT_multires_reshape";
+ ot->name = "Multires Reshape";
+ ot->description = "Copy vertex coordinates from other object";
+ ot->idname = "OBJECT_OT_multires_reshape";
- ot->poll = multires_poll;
- ot->invoke = multires_reshape_invoke;
- ot->exec = multires_reshape_exec;
+ ot->poll = multires_poll;
+ ot->invoke = multires_reshape_invoke;
+ ot->exec = multires_reshape_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
-
-
/****************** multires save external operator *********************/
static int multires_external_save_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_active_context(C);
- Mesh *me = (ob) ? ob->data : op->customdata;
- char path[FILE_MAX];
- const bool relative = RNA_boolean_get(op->ptr, "relative_path");
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
+ Mesh *me = (ob) ? ob->data : op->customdata;
+ char path[FILE_MAX];
+ const bool relative = RNA_boolean_get(op->ptr, "relative_path");
- if (!me)
- return OPERATOR_CANCELLED;
+ if (!me)
+ return OPERATOR_CANCELLED;
- if (CustomData_external_test(&me->ldata, CD_MDISPS))
- return OPERATOR_CANCELLED;
+ if (CustomData_external_test(&me->ldata, CD_MDISPS))
+ return OPERATOR_CANCELLED;
- RNA_string_get(op->ptr, "filepath", path);
+ RNA_string_get(op->ptr, "filepath", path);
- if (relative)
- BLI_path_rel(path, BKE_main_blendfile_path(bmain));
+ if (relative)
+ BLI_path_rel(path, BKE_main_blendfile_path(bmain));
- CustomData_external_add(&me->ldata, &me->id, CD_MDISPS, me->totloop, path);
- CustomData_external_write(&me->ldata, &me->id, CD_MASK_MESH.lmask, me->totloop, 0);
+ CustomData_external_add(&me->ldata, &me->id, CD_MDISPS, me->totloop, path);
+ CustomData_external_write(&me->ldata, &me->id, CD_MASK_MESH.lmask, me->totloop, 0);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int multires_external_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Object *ob = ED_object_active_context(C);
- MultiresModifierData *mmd;
- Mesh *me = ob->data;
- char path[FILE_MAX];
+ Object *ob = ED_object_active_context(C);
+ MultiresModifierData *mmd;
+ Mesh *me = ob->data;
+ char path[FILE_MAX];
- if (!edit_modifier_invoke_properties(C, op))
- return OPERATOR_CANCELLED;
+ if (!edit_modifier_invoke_properties(C, op))
+ return OPERATOR_CANCELLED;
- mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
+ mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
- if (!mmd)
- return OPERATOR_CANCELLED;
+ if (!mmd)
+ return OPERATOR_CANCELLED;
- if (CustomData_external_test(&me->ldata, CD_MDISPS))
- return OPERATOR_CANCELLED;
+ if (CustomData_external_test(&me->ldata, CD_MDISPS))
+ return OPERATOR_CANCELLED;
- if (RNA_struct_property_is_set(op->ptr, "filepath"))
- return multires_external_save_exec(C, op);
+ if (RNA_struct_property_is_set(op->ptr, "filepath"))
+ return multires_external_save_exec(C, op);
- op->customdata = me;
+ op->customdata = me;
- BLI_snprintf(path, sizeof(path), "//%s.btx", me->id.name + 2);
- RNA_string_set(op->ptr, "filepath", path);
+ BLI_snprintf(path, sizeof(path), "//%s.btx", me->id.name + 2);
+ RNA_string_set(op->ptr, "filepath", path);
- WM_event_add_fileselect(C, op);
+ WM_event_add_fileselect(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void OBJECT_OT_multires_external_save(wmOperatorType *ot)
{
- ot->name = "Multires Save External";
- ot->description = "Save displacements to an external file";
- ot->idname = "OBJECT_OT_multires_external_save";
+ ot->name = "Multires Save External";
+ ot->description = "Save displacements to an external file";
+ ot->idname = "OBJECT_OT_multires_external_save";
- /* XXX modifier no longer in context after file browser .. ot->poll = multires_poll; */
- ot->exec = multires_external_save_exec;
- ot->invoke = multires_external_save_invoke;
- ot->poll = multires_poll;
+ /* XXX modifier no longer in context after file browser .. ot->poll = multires_poll; */
+ ot->exec = multires_external_save_exec;
+ ot->invoke = multires_external_save_invoke;
+ ot->poll = multires_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_BTX, FILE_SPECIAL, FILE_SAVE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
- edit_modifier_properties(ot);
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_BTX,
+ FILE_SPECIAL,
+ FILE_SAVE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
+ edit_modifier_properties(ot);
}
/****************** multires pack operator *********************/
static int multires_external_pack_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_active_context(C);
- Mesh *me = ob->data;
+ Object *ob = ED_object_active_context(C);
+ Mesh *me = ob->data;
- if (!CustomData_external_test(&me->ldata, CD_MDISPS))
- return OPERATOR_CANCELLED;
+ if (!CustomData_external_test(&me->ldata, CD_MDISPS))
+ return OPERATOR_CANCELLED;
- /* XXX don't remove.. */
- CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop);
+ /* XXX don't remove.. */
+ CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_multires_external_pack(wmOperatorType *ot)
{
- ot->name = "Multires Pack External";
- ot->description = "Pack displacements from an external file";
- ot->idname = "OBJECT_OT_multires_external_pack";
+ ot->name = "Multires Pack External";
+ ot->description = "Pack displacements from an external file";
+ ot->idname = "OBJECT_OT_multires_external_pack";
- ot->poll = multires_poll;
- ot->exec = multires_external_pack_exec;
+ ot->poll = multires_poll;
+ ot->exec = multires_external_pack_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************* 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);
- MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_Multires);
- if (!mmd)
- return OPERATOR_CANCELLED;
+ if (!mmd)
+ return OPERATOR_CANCELLED;
- multiresModifier_base_apply(mmd, scene, ob);
+ multiresModifier_base_apply(mmd, scene, ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int multires_base_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return multires_base_apply_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return multires_base_apply_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
-
void OBJECT_OT_multires_base_apply(wmOperatorType *ot)
{
- ot->name = "Multires Apply Base";
- ot->description = "Modify the base mesh to conform to the displaced mesh";
- ot->idname = "OBJECT_OT_multires_base_apply";
+ ot->name = "Multires Apply Base";
+ ot->description = "Modify the base mesh to conform to the displaced mesh";
+ ot->idname = "OBJECT_OT_multires_base_apply";
- ot->poll = multires_poll;
- ot->invoke = multires_base_apply_invoke;
- ot->exec = multires_base_apply_exec;
+ ot->poll = multires_poll;
+ ot->invoke = multires_base_apply_invoke;
+ ot->exec = multires_base_apply_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
-
/************************** skin modifier ***********************/
static void modifier_skin_customdata_delete(Object *ob)
{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
- if (em)
- BM_data_layer_free(em->bm, &em->bm->vdata, CD_MVERT_SKIN);
- else
- CustomData_free_layer_active(&me->vdata, CD_MVERT_SKIN, me->totvert);
+ if (em)
+ BM_data_layer_free(em->bm, &em->bm->vdata, CD_MVERT_SKIN);
+ else
+ CustomData_free_layer_active(&me->vdata, CD_MVERT_SKIN, me->totvert);
}
static bool skin_poll(bContext *C)
{
- return (!CTX_data_edit_object(C) &&
- edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH)));
+ return (!CTX_data_edit_object(C) &&
+ edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH)));
}
static bool skin_edit_poll(bContext *C)
{
- return (CTX_data_edit_object(C) &&
- edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH)));
+ return (CTX_data_edit_object(C) &&
+ edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH)));
}
static void skin_root_clear(BMVert *bm_vert, GSet *visited, const int cd_vert_skin_offset)
{
- BMEdge *bm_edge;
- BMIter bm_iter;
+ BMEdge *bm_edge;
+ BMIter bm_iter;
- BM_ITER_ELEM (bm_edge, &bm_iter, bm_vert, BM_EDGES_OF_VERT) {
- BMVert *v2 = BM_edge_other_vert(bm_edge, bm_vert);
+ BM_ITER_ELEM (bm_edge, &bm_iter, bm_vert, BM_EDGES_OF_VERT) {
+ BMVert *v2 = BM_edge_other_vert(bm_edge, bm_vert);
- if (BLI_gset_add(visited, v2)) {
- MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(v2, cd_vert_skin_offset);
+ if (BLI_gset_add(visited, v2)) {
+ MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(v2, cd_vert_skin_offset);
- /* clear vertex root flag and add to visited set */
- vs->flag &= ~MVERT_SKIN_ROOT;
+ /* clear vertex root flag and add to visited set */
+ vs->flag &= ~MVERT_SKIN_ROOT;
- skin_root_clear(v2, visited, cd_vert_skin_offset);
- }
- }
+ skin_root_clear(v2, visited, cd_vert_skin_offset);
+ }
+ }
}
static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em->bm;
- BMVert *bm_vert;
- BMIter bm_iter;
- GSet *visited;
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
+ BMVert *bm_vert;
+ BMIter bm_iter;
+ GSet *visited;
- visited = BLI_gset_ptr_new(__func__);
+ visited = BLI_gset_ptr_new(__func__);
- BKE_mesh_ensure_skin_customdata(ob->data);
+ BKE_mesh_ensure_skin_customdata(ob->data);
- const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
+ const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
- BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT) &&
- BLI_gset_add(visited, bm_vert))
- {
- MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(bm_vert, cd_vert_skin_offset);
+ BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT) && BLI_gset_add(visited, bm_vert)) {
+ MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(bm_vert, cd_vert_skin_offset);
- /* mark vertex as root and add to visited set */
- vs->flag |= MVERT_SKIN_ROOT;
+ /* mark vertex as root and add to visited set */
+ vs->flag |= MVERT_SKIN_ROOT;
- /* clear root flag from all connected vertices (recursively) */
- skin_root_clear(bm_vert, visited, cd_vert_skin_offset);
- }
- }
+ /* clear root flag from all connected vertices (recursively) */
+ skin_root_clear(bm_vert, visited, cd_vert_skin_offset);
+ }
+ }
- BLI_gset_free(visited, NULL);
+ BLI_gset_free(visited, NULL);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_skin_root_mark(wmOperatorType *ot)
{
- ot->name = "Skin Root Mark";
- ot->description = "Mark selected vertices as roots";
- ot->idname = "OBJECT_OT_skin_root_mark";
+ ot->name = "Skin Root Mark";
+ ot->description = "Mark selected vertices as roots";
+ ot->idname = "OBJECT_OT_skin_root_mark";
- ot->poll = skin_edit_poll;
- ot->exec = skin_root_mark_exec;
+ ot->poll = skin_edit_poll;
+ ot->exec = skin_root_mark_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
typedef enum {
- SKIN_LOOSE_MARK,
- SKIN_LOOSE_CLEAR,
+ SKIN_LOOSE_MARK,
+ SKIN_LOOSE_CLEAR,
} SkinLooseAction;
static int skin_loose_mark_clear_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em->bm;
- BMVert *bm_vert;
- BMIter bm_iter;
- SkinLooseAction action = RNA_enum_get(op->ptr, "action");
-
- if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
- return OPERATOR_CANCELLED;
- }
-
- BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) {
- MVertSkin *vs = CustomData_bmesh_get(
- &bm->vdata,
- bm_vert->head.data,
- CD_MVERT_SKIN);
-
- switch (action) {
- case SKIN_LOOSE_MARK:
- vs->flag |= MVERT_SKIN_LOOSE;
- break;
- case SKIN_LOOSE_CLEAR:
- vs->flag &= ~MVERT_SKIN_LOOSE;
- break;
- }
- }
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
- return OPERATOR_FINISHED;
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
+ BMVert *bm_vert;
+ BMIter bm_iter;
+ SkinLooseAction action = RNA_enum_get(op->ptr, "action");
+
+ if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) {
+ MVertSkin *vs = CustomData_bmesh_get(&bm->vdata, bm_vert->head.data, CD_MVERT_SKIN);
+
+ switch (action) {
+ case SKIN_LOOSE_MARK:
+ vs->flag |= MVERT_SKIN_LOOSE;
+ break;
+ case SKIN_LOOSE_CLEAR:
+ vs->flag &= ~MVERT_SKIN_LOOSE;
+ break;
+ }
+ }
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_skin_loose_mark_clear(wmOperatorType *ot)
{
- static const EnumPropertyItem action_items[] = {
- {SKIN_LOOSE_MARK, "MARK", 0, "Mark", "Mark selected vertices as loose"},
- {SKIN_LOOSE_CLEAR, "CLEAR", 0, "Clear", "Set selected vertices as not loose"},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem action_items[] = {
+ {SKIN_LOOSE_MARK, "MARK", 0, "Mark", "Mark selected vertices as loose"},
+ {SKIN_LOOSE_CLEAR, "CLEAR", 0, "Clear", "Set selected vertices as not loose"},
+ {0, NULL, 0, NULL, NULL},
+ };
- ot->name = "Skin Mark/Clear Loose";
- ot->description = "Mark/clear selected vertices as loose";
- ot->idname = "OBJECT_OT_skin_loose_mark_clear";
+ ot->name = "Skin Mark/Clear Loose";
+ ot->description = "Mark/clear selected vertices as loose";
+ ot->idname = "OBJECT_OT_skin_loose_mark_clear";
- ot->poll = skin_edit_poll;
- ot->exec = skin_loose_mark_clear_exec;
+ ot->poll = skin_edit_poll;
+ ot->exec = skin_loose_mark_clear_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_enum(ot->srna, "action", action_items, SKIN_LOOSE_MARK, "Action", NULL);
+ RNA_def_enum(ot->srna, "action", action_items, SKIN_LOOSE_MARK, "Action", NULL);
}
static int skin_radii_equalize_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em->bm;
- BMVert *bm_vert;
- BMIter bm_iter;
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
+ BMVert *bm_vert;
+ BMIter bm_iter;
- if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
- return OPERATOR_CANCELLED;
- }
+ if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
+ return OPERATOR_CANCELLED;
+ }
- BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) {
- MVertSkin *vs = CustomData_bmesh_get(
- &bm->vdata,
- bm_vert->head.data,
- CD_MVERT_SKIN);
- float avg = (vs->radius[0] + vs->radius[1]) * 0.5f;
+ BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) {
+ MVertSkin *vs = CustomData_bmesh_get(&bm->vdata, bm_vert->head.data, CD_MVERT_SKIN);
+ float avg = (vs->radius[0] + vs->radius[1]) * 0.5f;
- vs->radius[0] = vs->radius[1] = avg;
- }
- }
+ vs->radius[0] = vs->radius[1] = avg;
+ }
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_skin_radii_equalize(wmOperatorType *ot)
{
- ot->name = "Skin Radii Equalize";
- ot->description = "Make skin radii of selected vertices equal on each axis";
- ot->idname = "OBJECT_OT_skin_radii_equalize";
+ ot->name = "Skin Radii Equalize";
+ ot->description = "Make skin radii of selected vertices equal on each axis";
+ ot->idname = "OBJECT_OT_skin_radii_equalize";
- ot->poll = skin_edit_poll;
- ot->exec = skin_radii_equalize_exec;
+ ot->poll = skin_edit_poll;
+ ot->exec = skin_radii_equalize_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static void skin_armature_bone_create(Object *skin_ob,
- MVert *mvert, MEdge *medge,
- bArmature *arm,
- BLI_bitmap *edges_visited,
- const MeshElemMap *emap,
- EditBone *parent_bone,
- int parent_v)
-{
- int i;
-
- for (i = 0; i < emap[parent_v].count; i++) {
- int endx = emap[parent_v].indices[i];
- const MEdge *e = &medge[endx];
- EditBone *bone;
- bDeformGroup *dg;
- int v;
-
- /* ignore edge if already visited */
- if (BLI_BITMAP_TEST(edges_visited, endx))
- continue;
- BLI_BITMAP_ENABLE(edges_visited, endx);
-
- v = (e->v1 == parent_v ? e->v2 : e->v1);
-
- bone = ED_armature_ebone_add(arm, "Bone");
-
- bone->parent = parent_bone;
- bone->flag |= BONE_CONNECTED;
-
- copy_v3_v3(bone->head, mvert[parent_v].co);
- copy_v3_v3(bone->tail, mvert[v].co);
- bone->rad_head = bone->rad_tail = 0.25;
- BLI_snprintf(bone->name, sizeof(bone->name), "Bone.%.2d", endx);
-
- /* add bDeformGroup */
- if ((dg = BKE_object_defgroup_add_name(skin_ob, bone->name))) {
- ED_vgroup_vert_add(skin_ob, dg, parent_v, 1, WEIGHT_REPLACE);
- ED_vgroup_vert_add(skin_ob, dg, v, 1, WEIGHT_REPLACE);
- }
-
- skin_armature_bone_create(
- skin_ob,
- mvert, medge,
- arm,
- edges_visited,
- emap,
- bone,
- v);
- }
-}
-
-static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, Scene *scene, Object *skin_ob)
-{
- BLI_bitmap *edges_visited;
- Mesh *me_eval_deform;
- MVert *mvert;
- Mesh *me = skin_ob->data;
- Object *arm_ob;
- bArmature *arm;
- MVertSkin *mvert_skin;
- MeshElemMap *emap;
- int *emap_mem;
- int v;
-
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, skin_ob);
-
- me_eval_deform = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
- mvert = me_eval_deform->mvert;
-
- /* add vertex weights to original mesh */
- CustomData_add_layer(
- &me->vdata,
- CD_MDEFORMVERT,
- CD_CALLOC,
- NULL,
- me->totvert);
-
- ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
- arm_ob = BKE_object_add(bmain, scene, view_layer, OB_ARMATURE, NULL);
- BKE_object_transform_copy(arm_ob, skin_ob);
- arm = arm_ob->data;
- arm->layer = 1;
- arm_ob->dtx |= OB_DRAWXRAY;
- arm->drawtype = ARM_LINE;
- arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature");
-
- mvert_skin = CustomData_get_layer(&me->vdata, CD_MVERT_SKIN);
- BKE_mesh_vert_edge_map_create(
- &emap, &emap_mem,
- me->medge, me->totvert, me->totedge);
-
- edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited");
-
- /* note: we use EditBones here, easier to set them up and use
- * edit-armature functions to convert back to regular bones */
- for (v = 0; v < me->totvert; v++) {
- if (mvert_skin[v].flag & MVERT_SKIN_ROOT) {
- EditBone *bone = NULL;
-
- /* Unless the skin root has just one adjacent edge, create
- * a fake root bone (have it going off in the Y direction
- * (arbitrary) */
- if (emap[v].count > 1) {
- bone = ED_armature_ebone_add(arm, "Bone");
-
- copy_v3_v3(bone->head, me->mvert[v].co);
- copy_v3_v3(bone->tail, me->mvert[v].co);
-
- bone->head[1] = 1.0f;
- bone->rad_head = bone->rad_tail = 0.25;
- }
-
- if (emap[v].count >= 1) {
- skin_armature_bone_create(
- skin_ob,
- mvert, me->medge,
- arm,
- edges_visited,
- emap,
- bone,
- v);
- }
- }
- }
-
- MEM_freeN(edges_visited);
- MEM_freeN(emap);
- MEM_freeN(emap_mem);
-
- ED_armature_from_edit(bmain, arm);
- ED_armature_edit_free(arm);
-
- return arm_ob;
+ MVert *mvert,
+ MEdge *medge,
+ bArmature *arm,
+ BLI_bitmap *edges_visited,
+ const MeshElemMap *emap,
+ EditBone *parent_bone,
+ int parent_v)
+{
+ int i;
+
+ for (i = 0; i < emap[parent_v].count; i++) {
+ int endx = emap[parent_v].indices[i];
+ const MEdge *e = &medge[endx];
+ EditBone *bone;
+ bDeformGroup *dg;
+ int v;
+
+ /* ignore edge if already visited */
+ if (BLI_BITMAP_TEST(edges_visited, endx))
+ continue;
+ BLI_BITMAP_ENABLE(edges_visited, endx);
+
+ v = (e->v1 == parent_v ? e->v2 : e->v1);
+
+ bone = ED_armature_ebone_add(arm, "Bone");
+
+ bone->parent = parent_bone;
+ bone->flag |= BONE_CONNECTED;
+
+ copy_v3_v3(bone->head, mvert[parent_v].co);
+ copy_v3_v3(bone->tail, mvert[v].co);
+ bone->rad_head = bone->rad_tail = 0.25;
+ BLI_snprintf(bone->name, sizeof(bone->name), "Bone.%.2d", endx);
+
+ /* add bDeformGroup */
+ if ((dg = BKE_object_defgroup_add_name(skin_ob, bone->name))) {
+ ED_vgroup_vert_add(skin_ob, dg, parent_v, 1, WEIGHT_REPLACE);
+ ED_vgroup_vert_add(skin_ob, dg, v, 1, WEIGHT_REPLACE);
+ }
+
+ skin_armature_bone_create(skin_ob, mvert, medge, arm, edges_visited, emap, bone, v);
+ }
+}
+
+static Object *modifier_skin_armature_create(Depsgraph *depsgraph,
+ Main *bmain,
+ Scene *scene,
+ Object *skin_ob)
+{
+ BLI_bitmap *edges_visited;
+ Mesh *me_eval_deform;
+ MVert *mvert;
+ Mesh *me = skin_ob->data;
+ Object *arm_ob;
+ bArmature *arm;
+ MVertSkin *mvert_skin;
+ MeshElemMap *emap;
+ int *emap_mem;
+ int v;
+
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, skin_ob);
+
+ me_eval_deform = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
+ mvert = me_eval_deform->mvert;
+
+ /* add vertex weights to original mesh */
+ CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert);
+
+ ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
+ arm_ob = BKE_object_add(bmain, scene, view_layer, OB_ARMATURE, NULL);
+ BKE_object_transform_copy(arm_ob, skin_ob);
+ arm = arm_ob->data;
+ arm->layer = 1;
+ arm_ob->dtx |= OB_DRAWXRAY;
+ arm->drawtype = ARM_LINE;
+ arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature");
+
+ mvert_skin = CustomData_get_layer(&me->vdata, CD_MVERT_SKIN);
+ BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me->medge, me->totvert, me->totedge);
+
+ edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited");
+
+ /* note: we use EditBones here, easier to set them up and use
+ * edit-armature functions to convert back to regular bones */
+ for (v = 0; v < me->totvert; v++) {
+ if (mvert_skin[v].flag & MVERT_SKIN_ROOT) {
+ EditBone *bone = NULL;
+
+ /* Unless the skin root has just one adjacent edge, create
+ * a fake root bone (have it going off in the Y direction
+ * (arbitrary) */
+ if (emap[v].count > 1) {
+ bone = ED_armature_ebone_add(arm, "Bone");
+
+ copy_v3_v3(bone->head, me->mvert[v].co);
+ copy_v3_v3(bone->tail, me->mvert[v].co);
+
+ bone->head[1] = 1.0f;
+ bone->rad_head = bone->rad_tail = 0.25;
+ }
+
+ if (emap[v].count >= 1) {
+ skin_armature_bone_create(skin_ob, mvert, me->medge, arm, edges_visited, emap, bone, v);
+ }
+ }
+ }
+
+ MEM_freeN(edges_visited);
+ MEM_freeN(emap);
+ MEM_freeN(emap_mem);
+
+ ED_armature_from_edit(bmain, arm);
+ ED_armature_edit_free(arm);
+
+ return arm_ob;
}
static int skin_armature_create_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C), *arm_ob;
- Mesh *me = ob->data;
- ModifierData *skin_md;
- ArmatureModifierData *arm_md;
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C), *arm_ob;
+ Mesh *me = ob->data;
+ ModifierData *skin_md;
+ ArmatureModifierData *arm_md;
- if (!CustomData_has_layer(&me->vdata, CD_MVERT_SKIN)) {
- BKE_reportf(op->reports, RPT_WARNING, "Mesh '%s' has no skin vertex data", me->id.name + 2);
- return OPERATOR_CANCELLED;
- }
+ if (!CustomData_has_layer(&me->vdata, CD_MVERT_SKIN)) {
+ BKE_reportf(op->reports, RPT_WARNING, "Mesh '%s' has no skin vertex data", me->id.name + 2);
+ return OPERATOR_CANCELLED;
+ }
- /* create new armature */
- arm_ob = modifier_skin_armature_create(depsgraph, bmain, scene, ob);
+ /* create new armature */
+ 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);
- if (arm_md) {
- skin_md = edit_modifier_property_get(op, ob, eModifierType_Skin);
- BLI_insertlinkafter(&ob->modifiers, skin_md, arm_md);
+ /* add a modifier to connect the new armature to the mesh */
+ arm_md = (ArmatureModifierData *)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);
- arm_md->object = arm_ob;
- arm_md->deformflag = ARM_DEF_VGROUP | ARM_DEF_QUATERNION;
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
+ arm_md->object = arm_ob;
+ arm_md->deformflag = ARM_DEF_VGROUP | ARM_DEF_QUATERNION;
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int skin_armature_create_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return skin_armature_create_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return skin_armature_create_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_skin_armature_create(wmOperatorType *ot)
{
- ot->name = "Skin Armature Create";
- ot->description = "Create an armature that parallels the skin layout";
- ot->idname = "OBJECT_OT_skin_armature_create";
+ ot->name = "Skin Armature Create";
+ ot->description = "Create an armature that parallels the skin layout";
+ ot->idname = "OBJECT_OT_skin_armature_create";
- ot->poll = skin_poll;
- ot->invoke = skin_armature_create_invoke;
- ot->exec = skin_armature_create_exec;
+ ot->poll = skin_poll;
+ ot->invoke = skin_armature_create_invoke;
+ ot->exec = skin_armature_create_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/************************ delta mush bind operator *********************/
static bool correctivesmooth_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_CorrectiveSmoothModifier, 0);
+ return edit_modifier_poll_generic(C, &RNA_CorrectiveSmoothModifier, 0);
}
static int correctivesmooth_bind_exec(bContext *C, wmOperator *op)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)edit_modifier_property_get(op, ob, eModifierType_CorrectiveSmooth);
- bool is_bind;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_CorrectiveSmooth);
+ bool is_bind;
- if (!csmd) {
- return OPERATOR_CANCELLED;
- }
+ if (!csmd) {
+ return OPERATOR_CANCELLED;
+ }
- if (!modifier_isEnabled(scene, &csmd->modifier, eModifierMode_Realtime)) {
- BKE_report(op->reports, RPT_ERROR, "Modifier is disabled");
- return OPERATOR_CANCELLED;
- }
+ if (!modifier_isEnabled(scene, &csmd->modifier, eModifierMode_Realtime)) {
+ BKE_report(op->reports, RPT_ERROR, "Modifier is disabled");
+ return OPERATOR_CANCELLED;
+ }
- is_bind = (csmd->bind_coords != NULL);
+ is_bind = (csmd->bind_coords != NULL);
- MEM_SAFE_FREE(csmd->bind_coords);
- MEM_SAFE_FREE(csmd->delta_cache);
+ MEM_SAFE_FREE(csmd->bind_coords);
+ MEM_SAFE_FREE(csmd->delta_cache);
- if (is_bind) {
- /* toggle off */
- csmd->bind_coords_num = 0;
- }
- 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;
+ if (is_bind) {
+ /* toggle off */
+ csmd->bind_coords_num = 0;
+ }
+ 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;
- /* Force modifier to run, it will call binding routine
- * (this has to happen outside of depsgraph evaluation). */
- object_force_modifier_bind_simple_options(depsgraph, ob, &csmd->modifier);
- }
+ /* Force modifier to run, it will call binding routine
+ * (this has to happen outside of depsgraph evaluation). */
+ object_force_modifier_bind_simple_options(depsgraph, ob, &csmd->modifier);
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int correctivesmooth_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return correctivesmooth_bind_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return correctivesmooth_bind_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_correctivesmooth_bind(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Corrective Smooth Bind";
- ot->description = "Bind base pose in Corrective Smooth modifier";
- ot->idname = "OBJECT_OT_correctivesmooth_bind";
+ /* identifiers */
+ ot->name = "Corrective Smooth Bind";
+ ot->description = "Bind base pose in Corrective Smooth modifier";
+ ot->idname = "OBJECT_OT_correctivesmooth_bind";
- /* api callbacks */
- ot->poll = correctivesmooth_poll;
- ot->invoke = correctivesmooth_bind_invoke;
- ot->exec = correctivesmooth_bind_exec;
+ /* api callbacks */
+ ot->poll = correctivesmooth_poll;
+ ot->invoke = correctivesmooth_bind_invoke;
+ ot->exec = correctivesmooth_bind_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/************************ mdef bind operator *********************/
static bool meshdeform_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_MeshDeformModifier, 0);
+ return edit_modifier_poll_generic(C, &RNA_MeshDeformModifier, 0);
}
static int meshdeform_bind_exec(bContext *C, wmOperator *op)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *ob = ED_object_active_context(C);
- MeshDeformModifierData *mmd = (MeshDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_MeshDeform);
-
- if (mmd == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- if (mmd->bindcagecos != NULL) {
- MEM_SAFE_FREE(mmd->bindcagecos);
- MEM_SAFE_FREE(mmd->dyngrid);
- MEM_SAFE_FREE(mmd->dyninfluences);
- MEM_SAFE_FREE(mmd->bindinfluences);
- MEM_SAFE_FREE(mmd->bindoffsets);
- MEM_SAFE_FREE(mmd->dynverts);
- MEM_SAFE_FREE(mmd->bindweights); /* Deprecated */
- MEM_SAFE_FREE(mmd->bindcos); /* Deprecated */
- mmd->totvert = 0;
- mmd->totcagevert = 0;
- mmd->totinfluence = 0;
- }
- 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(depsgraph, ob, &mmd->modifier);
- mmd_eval->bindfunc = ED_mesh_deform_bind_callback;
- object_force_modifier_bind_simple_options(depsgraph, ob, &mmd->modifier);
- mmd_eval->bindfunc = NULL;
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob = ED_object_active_context(C);
+ MeshDeformModifierData *mmd = (MeshDeformModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_MeshDeform);
+
+ if (mmd == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (mmd->bindcagecos != NULL) {
+ MEM_SAFE_FREE(mmd->bindcagecos);
+ MEM_SAFE_FREE(mmd->dyngrid);
+ MEM_SAFE_FREE(mmd->dyninfluences);
+ MEM_SAFE_FREE(mmd->bindinfluences);
+ MEM_SAFE_FREE(mmd->bindoffsets);
+ MEM_SAFE_FREE(mmd->dynverts);
+ MEM_SAFE_FREE(mmd->bindweights); /* Deprecated */
+ MEM_SAFE_FREE(mmd->bindcos); /* Deprecated */
+ mmd->totvert = 0;
+ mmd->totcagevert = 0;
+ mmd->totinfluence = 0;
+ }
+ 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(
+ depsgraph, ob, &mmd->modifier);
+ mmd_eval->bindfunc = ED_mesh_deform_bind_callback;
+ object_force_modifier_bind_simple_options(depsgraph, ob, &mmd->modifier);
+ mmd_eval->bindfunc = NULL;
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ return OPERATOR_FINISHED;
}
static int meshdeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return meshdeform_bind_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return meshdeform_bind_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_meshdeform_bind(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Mesh Deform Bind";
- ot->description = "Bind mesh to cage in mesh deform modifier";
- ot->idname = "OBJECT_OT_meshdeform_bind";
+ /* identifiers */
+ ot->name = "Mesh Deform Bind";
+ ot->description = "Bind mesh to cage in mesh deform modifier";
+ ot->idname = "OBJECT_OT_meshdeform_bind";
- /* api callbacks */
- ot->poll = meshdeform_poll;
- ot->invoke = meshdeform_bind_invoke;
- ot->exec = meshdeform_bind_exec;
+ /* api callbacks */
+ ot->poll = meshdeform_poll;
+ ot->invoke = meshdeform_bind_invoke;
+ ot->exec = meshdeform_bind_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/****************** explode refresh operator *********************/
static bool explode_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_ExplodeModifier, 0);
+ return edit_modifier_poll_generic(C, &RNA_ExplodeModifier, 0);
}
static int explode_refresh_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- ExplodeModifierData *emd = (ExplodeModifierData *)edit_modifier_property_get(op, ob, eModifierType_Explode);
+ Object *ob = ED_object_active_context(C);
+ ExplodeModifierData *emd = (ExplodeModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_Explode);
- if (!emd)
- return OPERATOR_CANCELLED;
+ if (!emd)
+ return OPERATOR_CANCELLED;
- emd->flag |= eExplodeFlag_CalcFaces;
+ emd->flag |= eExplodeFlag_CalcFaces;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int explode_refresh_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return explode_refresh_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return explode_refresh_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
-
void OBJECT_OT_explode_refresh(wmOperatorType *ot)
{
- ot->name = "Explode Refresh";
- ot->description = "Refresh data in the Explode modifier";
- ot->idname = "OBJECT_OT_explode_refresh";
+ ot->name = "Explode Refresh";
+ ot->description = "Refresh data in the Explode modifier";
+ ot->idname = "OBJECT_OT_explode_refresh";
- ot->poll = explode_poll;
- ot->invoke = explode_refresh_invoke;
- ot->exec = explode_refresh_exec;
+ ot->poll = explode_poll;
+ ot->invoke = explode_refresh_invoke;
+ ot->exec = explode_refresh_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
-
/****************** ocean bake operator *********************/
static bool ocean_bake_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_OceanModifier, 0);
+ return edit_modifier_poll_generic(C, &RNA_OceanModifier, 0);
}
typedef struct OceanBakeJob {
- /* from wmJob */
- struct Object *owner;
- short *stop, *do_update;
- float *progress;
- int current_frame;
- struct OceanCache *och;
- struct Ocean *ocean;
- struct OceanModifierData *omd;
+ /* from wmJob */
+ struct Object *owner;
+ short *stop, *do_update;
+ float *progress;
+ int current_frame;
+ struct OceanCache *och;
+ struct Ocean *ocean;
+ struct OceanModifierData *omd;
} OceanBakeJob;
static void oceanbake_free(void *customdata)
{
- OceanBakeJob *oj = customdata;
- MEM_freeN(oj);
+ OceanBakeJob *oj = customdata;
+ MEM_freeN(oj);
}
/* called by oceanbake, only to check job 'stop' value */
static int oceanbake_breakjob(void *UNUSED(customdata))
{
- //OceanBakeJob *ob = (OceanBakeJob *)customdata;
- //return *(ob->stop);
+ //OceanBakeJob *ob = (OceanBakeJob *)customdata;
+ //return *(ob->stop);
- /* this is not nice yet, need to make the jobs list template better
- * for identifying/acting upon various different jobs */
- /* but for now we'll reuse the render break... */
- return (G.is_break);
+ /* this is not nice yet, need to make the jobs list template better
+ * for identifying/acting upon various different jobs */
+ /* but for now we'll reuse the render break... */
+ return (G.is_break);
}
/* called by oceanbake, wmJob sends notifier */
static void oceanbake_update(void *customdata, float progress, int *cancel)
{
- OceanBakeJob *oj = customdata;
+ OceanBakeJob *oj = customdata;
- if (oceanbake_breakjob(oj))
- *cancel = 1;
+ if (oceanbake_breakjob(oj))
+ *cancel = 1;
- *(oj->do_update) = true;
- *(oj->progress) = progress;
+ *(oj->do_update) = true;
+ *(oj->progress) = progress;
}
static void oceanbake_startjob(void *customdata, short *stop, short *do_update, float *progress)
{
- OceanBakeJob *oj = customdata;
+ OceanBakeJob *oj = customdata;
- oj->stop = stop;
- oj->do_update = do_update;
- oj->progress = progress;
+ oj->stop = stop;
+ oj->do_update = do_update;
+ oj->progress = progress;
- G.is_break = false; /* XXX shared with render - replace with job 'stop' switch */
+ G.is_break = false; /* XXX shared with render - replace with job 'stop' switch */
- BKE_ocean_bake(oj->ocean, oj->och, oceanbake_update, (void *)oj);
+ BKE_ocean_bake(oj->ocean, oj->och, oceanbake_update, (void *)oj);
- *do_update = true;
- *stop = 0;
+ *do_update = true;
+ *stop = 0;
}
static void oceanbake_endjob(void *customdata)
{
- OceanBakeJob *oj = customdata;
+ OceanBakeJob *oj = customdata;
- if (oj->ocean) {
- BKE_ocean_free(oj->ocean);
- oj->ocean = NULL;
- }
+ if (oj->ocean) {
+ BKE_ocean_free(oj->ocean);
+ oj->ocean = NULL;
+ }
- oj->omd->oceancache = oj->och;
- oj->omd->cached = true;
+ oj->omd->oceancache = oj->och;
+ oj->omd->cached = true;
- Object *ob = oj->owner;
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ Object *ob = oj->owner;
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
}
static int ocean_bake_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_active_context(C);
- OceanModifierData *omd = (OceanModifierData *)edit_modifier_property_get(op, ob, eModifierType_Ocean);
- Scene *scene = CTX_data_scene(C);
- OceanCache *och;
- struct Ocean *ocean;
- int f, cfra, i = 0;
- const bool free = RNA_boolean_get(op->ptr, "free");
-
- wmJob *wm_job;
- OceanBakeJob *oj;
-
- if (!omd)
- return OPERATOR_CANCELLED;
-
- if (free) {
- BKE_ocean_free_modifier_cache(omd);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
- }
-
- och = BKE_ocean_init_cache(
- omd->cachepath, modifier_path_relbase(bmain, ob),
- omd->bakestart, omd->bakeend, omd->wave_scale,
- omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution);
-
- och->time = MEM_mallocN(och->duration * sizeof(float), "foam bake time");
-
- cfra = scene->r.cfra;
-
- /* precalculate time variable before baking */
- for (f = omd->bakestart; f <= omd->bakeend; f++) {
- /* For now only simple animation of time value is supported, nothing else.
- * No drivers or other modifier parameters. */
- BKE_animsys_evaluate_animdata(CTX_data_depsgraph(C), scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM);
-
- och->time[i] = omd->time;
- i++;
- }
-
- /* make a copy of ocean to use for baking - threadsafety */
- ocean = BKE_ocean_add();
- BKE_ocean_init_from_modifier(ocean, omd);
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
+ OceanModifierData *omd = (OceanModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_Ocean);
+ Scene *scene = CTX_data_scene(C);
+ OceanCache *och;
+ struct Ocean *ocean;
+ int f, cfra, i = 0;
+ const bool free = RNA_boolean_get(op->ptr, "free");
+
+ wmJob *wm_job;
+ OceanBakeJob *oj;
+
+ if (!omd)
+ return OPERATOR_CANCELLED;
+
+ if (free) {
+ BKE_ocean_free_modifier_cache(omd);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ return OPERATOR_FINISHED;
+ }
+
+ och = BKE_ocean_init_cache(omd->cachepath,
+ modifier_path_relbase(bmain, ob),
+ omd->bakestart,
+ omd->bakeend,
+ omd->wave_scale,
+ omd->chop_amount,
+ omd->foam_coverage,
+ omd->foam_fade,
+ omd->resolution);
+
+ och->time = MEM_mallocN(och->duration * sizeof(float), "foam bake time");
+
+ cfra = scene->r.cfra;
+
+ /* precalculate time variable before baking */
+ for (f = omd->bakestart; f <= omd->bakeend; f++) {
+ /* For now only simple animation of time value is supported, nothing else.
+ * No drivers or other modifier parameters. */
+ BKE_animsys_evaluate_animdata(
+ CTX_data_depsgraph(C), scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM);
+
+ och->time[i] = omd->time;
+ i++;
+ }
+
+ /* make a copy of ocean to use for baking - threadsafety */
+ ocean = BKE_ocean_add();
+ BKE_ocean_init_from_modifier(ocean, omd);
#if 0
- BKE_ocean_bake(ocean, och);
+ BKE_ocean_bake(ocean, och);
- omd->oceancache = och;
- omd->cached = true;
+ omd->oceancache = och;
+ omd->cached = true;
- scene->r.cfra = cfra;
+ scene->r.cfra = cfra;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
#endif
- /* job stuff */
+ /* job stuff */
- scene->r.cfra = cfra;
+ scene->r.cfra = cfra;
- /* setup job */
- wm_job = WM_jobs_get(
- CTX_wm_manager(C), CTX_wm_window(C), scene, "Ocean Simulation",
- WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_SIM_OCEAN);
- oj = MEM_callocN(sizeof(OceanBakeJob), "ocean bake job");
- oj->owner = ob;
- oj->ocean = ocean;
- oj->och = och;
- oj->omd = omd;
+ /* setup job */
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ scene,
+ "Ocean Simulation",
+ WM_JOB_PROGRESS,
+ WM_JOB_TYPE_OBJECT_SIM_OCEAN);
+ oj = MEM_callocN(sizeof(OceanBakeJob), "ocean bake job");
+ oj->owner = ob;
+ oj->ocean = ocean;
+ oj->och = och;
+ oj->omd = omd;
- WM_jobs_customdata_set(wm_job, oj, oceanbake_free);
- WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_MODIFIER, NC_OBJECT | ND_MODIFIER);
- WM_jobs_callbacks(wm_job, oceanbake_startjob, NULL, NULL, oceanbake_endjob);
+ WM_jobs_customdata_set(wm_job, oj, oceanbake_free);
+ WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_MODIFIER, NC_OBJECT | ND_MODIFIER);
+ WM_jobs_callbacks(wm_job, oceanbake_startjob, NULL, NULL, oceanbake_endjob);
- WM_jobs_start(CTX_wm_manager(C), wm_job);
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
-
-
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int ocean_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return ocean_bake_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return ocean_bake_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
-
void OBJECT_OT_ocean_bake(wmOperatorType *ot)
{
- ot->name = "Bake Ocean";
- ot->description = "Bake an image sequence of ocean data";
- ot->idname = "OBJECT_OT_ocean_bake";
+ ot->name = "Bake Ocean";
+ ot->description = "Bake an image sequence of ocean data";
+ ot->idname = "OBJECT_OT_ocean_bake";
- ot->poll = ocean_bake_poll;
- ot->invoke = ocean_bake_invoke;
- ot->exec = ocean_bake_exec;
+ ot->poll = ocean_bake_poll;
+ ot->invoke = ocean_bake_invoke;
+ ot->exec = ocean_bake_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
- RNA_def_boolean(ot->srna, "free", false, "Free", "Free the bake, rather than generating it");
+ RNA_def_boolean(ot->srna, "free", false, "Free", "Free the bake, rather than generating it");
}
/************************ LaplacianDeform bind operator *********************/
static bool laplaciandeform_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_LaplacianDeformModifier, 0);
+ return edit_modifier_poll_generic(C, &RNA_LaplacianDeformModifier, 0);
}
static int laplaciandeform_bind_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_LaplacianDeform);
-
- if (lmd == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- if (lmd->flag & MOD_LAPLACIANDEFORM_BIND) {
- lmd->flag &= ~MOD_LAPLACIANDEFORM_BIND;
- }
- else {
- lmd->flag |= MOD_LAPLACIANDEFORM_BIND;
- }
-
- LaplacianDeformModifierData *lmd_eval =
- (LaplacianDeformModifierData *)modifier_get_evaluated(depsgraph, ob, &lmd->modifier);
- lmd_eval->flag = lmd->flag;
-
- /* Force modifier to run, it will call binding routine
- * (this has to happen outside of depsgraph evaluation). */
- object_force_modifier_bind_simple_options(depsgraph, ob, &lmd->modifier);
-
- /* This is hard to know from the modifier itself whether the evaluation is
- * happening for binding or not. So we copy all the required data here. */
- lmd->total_verts = lmd_eval->total_verts;
- if (lmd_eval->vertexco == NULL) {
- MEM_SAFE_FREE(lmd->vertexco);
- }
- else {
- lmd->vertexco = MEM_dupallocN(lmd_eval->vertexco);
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ Object *ob = ED_object_active_context(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_LaplacianDeform);
+
+ if (lmd == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (lmd->flag & MOD_LAPLACIANDEFORM_BIND) {
+ lmd->flag &= ~MOD_LAPLACIANDEFORM_BIND;
+ }
+ else {
+ lmd->flag |= MOD_LAPLACIANDEFORM_BIND;
+ }
+
+ LaplacianDeformModifierData *lmd_eval = (LaplacianDeformModifierData *)modifier_get_evaluated(
+ depsgraph, ob, &lmd->modifier);
+ lmd_eval->flag = lmd->flag;
+
+ /* Force modifier to run, it will call binding routine
+ * (this has to happen outside of depsgraph evaluation). */
+ object_force_modifier_bind_simple_options(depsgraph, ob, &lmd->modifier);
+
+ /* This is hard to know from the modifier itself whether the evaluation is
+ * happening for binding or not. So we copy all the required data here. */
+ lmd->total_verts = lmd_eval->total_verts;
+ if (lmd_eval->vertexco == NULL) {
+ MEM_SAFE_FREE(lmd->vertexco);
+ }
+ else {
+ lmd->vertexco = MEM_dupallocN(lmd_eval->vertexco);
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ return OPERATOR_FINISHED;
}
static int laplaciandeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return laplaciandeform_bind_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return laplaciandeform_bind_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_laplaciandeform_bind(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Laplacian Deform Bind";
- ot->description = "Bind mesh to system in laplacian deform modifier";
- ot->idname = "OBJECT_OT_laplaciandeform_bind";
+ /* identifiers */
+ ot->name = "Laplacian Deform Bind";
+ ot->description = "Bind mesh to system in laplacian deform modifier";
+ ot->idname = "OBJECT_OT_laplaciandeform_bind";
- /* api callbacks */
- ot->poll = laplaciandeform_poll;
- ot->invoke = laplaciandeform_bind_invoke;
- ot->exec = laplaciandeform_bind_exec;
+ /* api callbacks */
+ ot->poll = laplaciandeform_poll;
+ ot->invoke = laplaciandeform_bind_invoke;
+ ot->exec = laplaciandeform_bind_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/************************ sdef bind operator *********************/
static bool surfacedeform_bind_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_SurfaceDeformModifier, 0);
+ return edit_modifier_poll_generic(C, &RNA_SurfaceDeformModifier, 0);
}
static int surfacedeform_bind_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_SurfaceDeform);
+ Object *ob = ED_object_active_context(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_SurfaceDeform);
- if (smd == NULL) {
- return OPERATOR_CANCELLED;
- }
+ if (smd == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- if (smd->flags & MOD_SDEF_BIND) {
- smd->flags &= ~MOD_SDEF_BIND;
- }
- else if (smd->target) {
- smd->flags |= MOD_SDEF_BIND;
- }
+ if (smd->flags & MOD_SDEF_BIND) {
+ smd->flags &= ~MOD_SDEF_BIND;
+ }
+ else if (smd->target) {
+ smd->flags |= MOD_SDEF_BIND;
+ }
- SurfaceDeformModifierData *smd_eval =
- (SurfaceDeformModifierData *)modifier_get_evaluated(depsgraph, ob, &smd->modifier);
- smd_eval->flags = smd->flags;
+ SurfaceDeformModifierData *smd_eval = (SurfaceDeformModifierData *)modifier_get_evaluated(
+ depsgraph, ob, &smd->modifier);
+ smd_eval->flags = smd->flags;
- /* Force modifier to run, it will call binding routine
- * (this has to happen outside of depsgraph evaluation). */
- object_force_modifier_bind_simple_options(depsgraph, ob, &smd->modifier);
+ /* Force modifier to run, it will call binding routine
+ * (this has to happen outside of depsgraph evaluation). */
+ object_force_modifier_bind_simple_options(depsgraph, ob, &smd->modifier);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ return OPERATOR_FINISHED;
}
static int surfacedeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return surfacedeform_bind_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return surfacedeform_bind_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_surfacedeform_bind(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Surface Deform Bind";
- ot->description = "Bind mesh to target in surface deform modifier";
- ot->idname = "OBJECT_OT_surfacedeform_bind";
+ /* identifiers */
+ ot->name = "Surface Deform Bind";
+ ot->description = "Bind mesh to target in surface deform modifier";
+ ot->idname = "OBJECT_OT_surfacedeform_bind";
- /* api callbacks */
- ot->poll = surfacedeform_bind_poll;
- ot->invoke = surfacedeform_bind_invoke;
- ot->exec = surfacedeform_bind_exec;
+ /* api callbacks */
+ ot->poll = surfacedeform_bind_poll;
+ ot->invoke = surfacedeform_bind_invoke;
+ ot->exec = surfacedeform_bind_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ 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 024fa24480a..8e3f916b2e4 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <stdlib.h>
#include <math.h>
@@ -46,262 +45,263 @@
#include "object_intern.h"
-
/* ************************** registration **********************************/
-
void ED_operatortypes_object(void)
{
- WM_operatortype_append(OBJECT_OT_location_clear);
- WM_operatortype_append(OBJECT_OT_rotation_clear);
- WM_operatortype_append(OBJECT_OT_scale_clear);
- WM_operatortype_append(OBJECT_OT_origin_clear);
- WM_operatortype_append(OBJECT_OT_visual_transform_apply);
- WM_operatortype_append(OBJECT_OT_transform_apply);
- WM_operatortype_append(OBJECT_OT_transform_axis_target);
- WM_operatortype_append(OBJECT_OT_origin_set);
-
- WM_operatortype_append(OBJECT_OT_mode_set);
- WM_operatortype_append(OBJECT_OT_mode_set_or_submode);
- WM_operatortype_append(OBJECT_OT_editmode_toggle);
- WM_operatortype_append(OBJECT_OT_posemode_toggle);
- WM_operatortype_append(OBJECT_OT_proxy_make);
- WM_operatortype_append(OBJECT_OT_shade_smooth);
- WM_operatortype_append(OBJECT_OT_shade_flat);
- WM_operatortype_append(OBJECT_OT_paths_calculate);
- WM_operatortype_append(OBJECT_OT_paths_update);
- WM_operatortype_append(OBJECT_OT_paths_clear);
- WM_operatortype_append(OBJECT_OT_paths_range_update);
- WM_operatortype_append(OBJECT_OT_forcefield_toggle);
-
- WM_operatortype_append(OBJECT_OT_parent_set);
- WM_operatortype_append(OBJECT_OT_parent_no_inverse_set);
- WM_operatortype_append(OBJECT_OT_parent_clear);
- WM_operatortype_append(OBJECT_OT_vertex_parent_set);
- WM_operatortype_append(OBJECT_OT_track_set);
- WM_operatortype_append(OBJECT_OT_track_clear);
- WM_operatortype_append(OBJECT_OT_make_local);
- WM_operatortype_append(OBJECT_OT_make_override_static);
- WM_operatortype_append(OBJECT_OT_make_single_user);
- WM_operatortype_append(OBJECT_OT_make_links_scene);
- WM_operatortype_append(OBJECT_OT_make_links_data);
-
- WM_operatortype_append(OBJECT_OT_select_random);
- WM_operatortype_append(OBJECT_OT_select_all);
- WM_operatortype_append(OBJECT_OT_select_same_collection);
- WM_operatortype_append(OBJECT_OT_select_by_type);
- WM_operatortype_append(OBJECT_OT_select_linked);
- WM_operatortype_append(OBJECT_OT_select_grouped);
- WM_operatortype_append(OBJECT_OT_select_mirror);
- WM_operatortype_append(OBJECT_OT_select_more);
- WM_operatortype_append(OBJECT_OT_select_less);
-
- WM_operatortype_append(COLLECTION_OT_create);
- WM_operatortype_append(COLLECTION_OT_objects_remove_all);
- WM_operatortype_append(COLLECTION_OT_objects_remove);
- WM_operatortype_append(COLLECTION_OT_objects_add_active);
- WM_operatortype_append(COLLECTION_OT_objects_remove_active);
-
- WM_operatortype_append(OBJECT_OT_delete);
- WM_operatortype_append(OBJECT_OT_text_add);
- WM_operatortype_append(OBJECT_OT_armature_add);
- WM_operatortype_append(OBJECT_OT_empty_add);
- WM_operatortype_append(OBJECT_OT_lightprobe_add);
- WM_operatortype_append(OBJECT_OT_drop_named_image);
- WM_operatortype_append(OBJECT_OT_gpencil_add);
- WM_operatortype_append(OBJECT_OT_light_add);
- WM_operatortype_append(OBJECT_OT_camera_add);
- WM_operatortype_append(OBJECT_OT_speaker_add);
- WM_operatortype_append(OBJECT_OT_add);
- WM_operatortype_append(OBJECT_OT_add_named);
- WM_operatortype_append(OBJECT_OT_effector_add);
- WM_operatortype_append(OBJECT_OT_collection_instance_add);
- WM_operatortype_append(OBJECT_OT_metaball_add);
- WM_operatortype_append(OBJECT_OT_duplicates_make_real);
- WM_operatortype_append(OBJECT_OT_duplicate);
- WM_operatortype_append(OBJECT_OT_join);
- WM_operatortype_append(OBJECT_OT_join_shapes);
- WM_operatortype_append(OBJECT_OT_convert);
-
- WM_operatortype_append(OBJECT_OT_modifier_add);
- WM_operatortype_append(OBJECT_OT_modifier_remove);
- WM_operatortype_append(OBJECT_OT_modifier_move_up);
- WM_operatortype_append(OBJECT_OT_modifier_move_down);
- WM_operatortype_append(OBJECT_OT_modifier_apply);
- WM_operatortype_append(OBJECT_OT_modifier_convert);
- WM_operatortype_append(OBJECT_OT_modifier_copy);
- WM_operatortype_append(OBJECT_OT_multires_subdivide);
- 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_external_save);
- WM_operatortype_append(OBJECT_OT_multires_external_pack);
- WM_operatortype_append(OBJECT_OT_skin_root_mark);
- WM_operatortype_append(OBJECT_OT_skin_loose_mark_clear);
- WM_operatortype_append(OBJECT_OT_skin_radii_equalize);
- WM_operatortype_append(OBJECT_OT_skin_armature_create);
-
- /* grease pencil modifiers */
- WM_operatortype_append(OBJECT_OT_gpencil_modifier_add);
- WM_operatortype_append(OBJECT_OT_gpencil_modifier_remove);
- WM_operatortype_append(OBJECT_OT_gpencil_modifier_move_up);
- WM_operatortype_append(OBJECT_OT_gpencil_modifier_move_down);
- WM_operatortype_append(OBJECT_OT_gpencil_modifier_apply);
- WM_operatortype_append(OBJECT_OT_gpencil_modifier_copy);
-
- /* shader fx */
- WM_operatortype_append(OBJECT_OT_shaderfx_add);
- WM_operatortype_append(OBJECT_OT_shaderfx_remove);
- WM_operatortype_append(OBJECT_OT_shaderfx_move_up);
- WM_operatortype_append(OBJECT_OT_shaderfx_move_down);
-
- WM_operatortype_append(OBJECT_OT_correctivesmooth_bind);
- WM_operatortype_append(OBJECT_OT_meshdeform_bind);
- WM_operatortype_append(OBJECT_OT_explode_refresh);
- WM_operatortype_append(OBJECT_OT_ocean_bake);
-
- WM_operatortype_append(OBJECT_OT_constraint_add);
- WM_operatortype_append(OBJECT_OT_constraint_add_with_targets);
- WM_operatortype_append(POSE_OT_constraint_add);
- WM_operatortype_append(POSE_OT_constraint_add_with_targets);
- WM_operatortype_append(OBJECT_OT_constraints_copy);
- WM_operatortype_append(POSE_OT_constraints_copy);
- WM_operatortype_append(OBJECT_OT_constraints_clear);
- WM_operatortype_append(POSE_OT_constraints_clear);
- WM_operatortype_append(POSE_OT_ik_add);
- WM_operatortype_append(POSE_OT_ik_clear);
- WM_operatortype_append(CONSTRAINT_OT_delete);
- WM_operatortype_append(CONSTRAINT_OT_move_up);
- WM_operatortype_append(CONSTRAINT_OT_move_down);
- WM_operatortype_append(CONSTRAINT_OT_stretchto_reset);
- WM_operatortype_append(CONSTRAINT_OT_limitdistance_reset);
- WM_operatortype_append(CONSTRAINT_OT_childof_set_inverse);
- WM_operatortype_append(CONSTRAINT_OT_childof_clear_inverse);
- WM_operatortype_append(CONSTRAINT_OT_objectsolver_set_inverse);
- WM_operatortype_append(CONSTRAINT_OT_objectsolver_clear_inverse);
- WM_operatortype_append(CONSTRAINT_OT_followpath_path_animate);
-
- WM_operatortype_append(OBJECT_OT_vertex_group_add);
- WM_operatortype_append(OBJECT_OT_vertex_group_remove);
- WM_operatortype_append(OBJECT_OT_vertex_group_assign);
- WM_operatortype_append(OBJECT_OT_vertex_group_assign_new);
- WM_operatortype_append(OBJECT_OT_vertex_group_remove_from);
- WM_operatortype_append(OBJECT_OT_vertex_group_select);
- WM_operatortype_append(OBJECT_OT_vertex_group_deselect);
- WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_linked);
- WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_selected);
- WM_operatortype_append(OBJECT_OT_vertex_group_copy);
- WM_operatortype_append(OBJECT_OT_vertex_group_normalize);
- WM_operatortype_append(OBJECT_OT_vertex_group_normalize_all);
- WM_operatortype_append(OBJECT_OT_vertex_group_lock);
- WM_operatortype_append(OBJECT_OT_vertex_group_fix);
- WM_operatortype_append(OBJECT_OT_vertex_group_invert);
- WM_operatortype_append(OBJECT_OT_vertex_group_levels);
- WM_operatortype_append(OBJECT_OT_vertex_group_smooth);
- WM_operatortype_append(OBJECT_OT_vertex_group_clean);
- WM_operatortype_append(OBJECT_OT_vertex_group_quantize);
- WM_operatortype_append(OBJECT_OT_vertex_group_limit_total);
- WM_operatortype_append(OBJECT_OT_vertex_group_mirror);
- WM_operatortype_append(OBJECT_OT_vertex_group_set_active);
- WM_operatortype_append(OBJECT_OT_vertex_group_sort);
- WM_operatortype_append(OBJECT_OT_vertex_group_move);
- WM_operatortype_append(OBJECT_OT_vertex_weight_paste);
- WM_operatortype_append(OBJECT_OT_vertex_weight_delete);
- WM_operatortype_append(OBJECT_OT_vertex_weight_set_active);
- WM_operatortype_append(OBJECT_OT_vertex_weight_normalize_active_vertex);
- WM_operatortype_append(OBJECT_OT_vertex_weight_copy);
-
- WM_operatortype_append(OBJECT_OT_face_map_add);
- WM_operatortype_append(OBJECT_OT_face_map_remove);
- WM_operatortype_append(OBJECT_OT_face_map_assign);
- WM_operatortype_append(OBJECT_OT_face_map_remove_from);
- WM_operatortype_append(OBJECT_OT_face_map_select);
- WM_operatortype_append(OBJECT_OT_face_map_deselect);
- WM_operatortype_append(OBJECT_OT_face_map_move);
-
- WM_operatortype_append(TRANSFORM_OT_vertex_warp);
-
- WM_operatortype_append(OBJECT_OT_move_to_collection);
- WM_operatortype_append(OBJECT_OT_link_to_collection);
-
- WM_operatortype_append(OBJECT_OT_shape_key_add);
- WM_operatortype_append(OBJECT_OT_shape_key_remove);
- WM_operatortype_append(OBJECT_OT_shape_key_clear);
- WM_operatortype_append(OBJECT_OT_shape_key_retime);
- WM_operatortype_append(OBJECT_OT_shape_key_mirror);
- WM_operatortype_append(OBJECT_OT_shape_key_move);
-
- WM_operatortype_append(OBJECT_OT_collection_add);
- WM_operatortype_append(OBJECT_OT_collection_link);
- WM_operatortype_append(OBJECT_OT_collection_remove);
- WM_operatortype_append(OBJECT_OT_collection_unlink);
- WM_operatortype_append(OBJECT_OT_collection_objects_select);
-
- WM_operatortype_append(OBJECT_OT_hook_add_selob);
- WM_operatortype_append(OBJECT_OT_hook_add_newob);
- WM_operatortype_append(OBJECT_OT_hook_remove);
- WM_operatortype_append(OBJECT_OT_hook_select);
- WM_operatortype_append(OBJECT_OT_hook_assign);
- WM_operatortype_append(OBJECT_OT_hook_reset);
- WM_operatortype_append(OBJECT_OT_hook_recenter);
-
- WM_operatortype_append(OBJECT_OT_bake_image);
- WM_operatortype_append(OBJECT_OT_bake);
- WM_operatortype_append(OBJECT_OT_drop_named_material);
- WM_operatortype_append(OBJECT_OT_unlink_data);
- WM_operatortype_append(OBJECT_OT_laplaciandeform_bind);
-
- WM_operatortype_append(TRANSFORM_OT_vertex_random);
-
- WM_operatortype_append(OBJECT_OT_data_transfer);
- WM_operatortype_append(OBJECT_OT_datalayout_transfer);
- WM_operatortype_append(OBJECT_OT_surfacedeform_bind);
-
- WM_operatortype_append(OBJECT_OT_hide_view_clear);
- WM_operatortype_append(OBJECT_OT_hide_view_set);
- WM_operatortype_append(OBJECT_OT_hide_collection);
+ WM_operatortype_append(OBJECT_OT_location_clear);
+ WM_operatortype_append(OBJECT_OT_rotation_clear);
+ WM_operatortype_append(OBJECT_OT_scale_clear);
+ WM_operatortype_append(OBJECT_OT_origin_clear);
+ WM_operatortype_append(OBJECT_OT_visual_transform_apply);
+ WM_operatortype_append(OBJECT_OT_transform_apply);
+ WM_operatortype_append(OBJECT_OT_transform_axis_target);
+ WM_operatortype_append(OBJECT_OT_origin_set);
+
+ WM_operatortype_append(OBJECT_OT_mode_set);
+ WM_operatortype_append(OBJECT_OT_mode_set_or_submode);
+ WM_operatortype_append(OBJECT_OT_editmode_toggle);
+ WM_operatortype_append(OBJECT_OT_posemode_toggle);
+ WM_operatortype_append(OBJECT_OT_proxy_make);
+ WM_operatortype_append(OBJECT_OT_shade_smooth);
+ WM_operatortype_append(OBJECT_OT_shade_flat);
+ WM_operatortype_append(OBJECT_OT_paths_calculate);
+ WM_operatortype_append(OBJECT_OT_paths_update);
+ WM_operatortype_append(OBJECT_OT_paths_clear);
+ WM_operatortype_append(OBJECT_OT_paths_range_update);
+ WM_operatortype_append(OBJECT_OT_forcefield_toggle);
+
+ WM_operatortype_append(OBJECT_OT_parent_set);
+ WM_operatortype_append(OBJECT_OT_parent_no_inverse_set);
+ WM_operatortype_append(OBJECT_OT_parent_clear);
+ WM_operatortype_append(OBJECT_OT_vertex_parent_set);
+ WM_operatortype_append(OBJECT_OT_track_set);
+ WM_operatortype_append(OBJECT_OT_track_clear);
+ WM_operatortype_append(OBJECT_OT_make_local);
+ WM_operatortype_append(OBJECT_OT_make_override_static);
+ WM_operatortype_append(OBJECT_OT_make_single_user);
+ WM_operatortype_append(OBJECT_OT_make_links_scene);
+ WM_operatortype_append(OBJECT_OT_make_links_data);
+
+ WM_operatortype_append(OBJECT_OT_select_random);
+ WM_operatortype_append(OBJECT_OT_select_all);
+ WM_operatortype_append(OBJECT_OT_select_same_collection);
+ WM_operatortype_append(OBJECT_OT_select_by_type);
+ WM_operatortype_append(OBJECT_OT_select_linked);
+ WM_operatortype_append(OBJECT_OT_select_grouped);
+ WM_operatortype_append(OBJECT_OT_select_mirror);
+ WM_operatortype_append(OBJECT_OT_select_more);
+ WM_operatortype_append(OBJECT_OT_select_less);
+
+ WM_operatortype_append(COLLECTION_OT_create);
+ WM_operatortype_append(COLLECTION_OT_objects_remove_all);
+ WM_operatortype_append(COLLECTION_OT_objects_remove);
+ WM_operatortype_append(COLLECTION_OT_objects_add_active);
+ WM_operatortype_append(COLLECTION_OT_objects_remove_active);
+
+ WM_operatortype_append(OBJECT_OT_delete);
+ WM_operatortype_append(OBJECT_OT_text_add);
+ WM_operatortype_append(OBJECT_OT_armature_add);
+ WM_operatortype_append(OBJECT_OT_empty_add);
+ WM_operatortype_append(OBJECT_OT_lightprobe_add);
+ WM_operatortype_append(OBJECT_OT_drop_named_image);
+ WM_operatortype_append(OBJECT_OT_gpencil_add);
+ WM_operatortype_append(OBJECT_OT_light_add);
+ WM_operatortype_append(OBJECT_OT_camera_add);
+ WM_operatortype_append(OBJECT_OT_speaker_add);
+ WM_operatortype_append(OBJECT_OT_add);
+ WM_operatortype_append(OBJECT_OT_add_named);
+ WM_operatortype_append(OBJECT_OT_effector_add);
+ WM_operatortype_append(OBJECT_OT_collection_instance_add);
+ WM_operatortype_append(OBJECT_OT_metaball_add);
+ WM_operatortype_append(OBJECT_OT_duplicates_make_real);
+ WM_operatortype_append(OBJECT_OT_duplicate);
+ WM_operatortype_append(OBJECT_OT_join);
+ WM_operatortype_append(OBJECT_OT_join_shapes);
+ WM_operatortype_append(OBJECT_OT_convert);
+
+ WM_operatortype_append(OBJECT_OT_modifier_add);
+ WM_operatortype_append(OBJECT_OT_modifier_remove);
+ WM_operatortype_append(OBJECT_OT_modifier_move_up);
+ WM_operatortype_append(OBJECT_OT_modifier_move_down);
+ WM_operatortype_append(OBJECT_OT_modifier_apply);
+ WM_operatortype_append(OBJECT_OT_modifier_convert);
+ WM_operatortype_append(OBJECT_OT_modifier_copy);
+ WM_operatortype_append(OBJECT_OT_multires_subdivide);
+ 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_external_save);
+ WM_operatortype_append(OBJECT_OT_multires_external_pack);
+ WM_operatortype_append(OBJECT_OT_skin_root_mark);
+ WM_operatortype_append(OBJECT_OT_skin_loose_mark_clear);
+ WM_operatortype_append(OBJECT_OT_skin_radii_equalize);
+ WM_operatortype_append(OBJECT_OT_skin_armature_create);
+
+ /* grease pencil modifiers */
+ WM_operatortype_append(OBJECT_OT_gpencil_modifier_add);
+ WM_operatortype_append(OBJECT_OT_gpencil_modifier_remove);
+ WM_operatortype_append(OBJECT_OT_gpencil_modifier_move_up);
+ WM_operatortype_append(OBJECT_OT_gpencil_modifier_move_down);
+ WM_operatortype_append(OBJECT_OT_gpencil_modifier_apply);
+ WM_operatortype_append(OBJECT_OT_gpencil_modifier_copy);
+
+ /* shader fx */
+ WM_operatortype_append(OBJECT_OT_shaderfx_add);
+ WM_operatortype_append(OBJECT_OT_shaderfx_remove);
+ WM_operatortype_append(OBJECT_OT_shaderfx_move_up);
+ WM_operatortype_append(OBJECT_OT_shaderfx_move_down);
+
+ WM_operatortype_append(OBJECT_OT_correctivesmooth_bind);
+ WM_operatortype_append(OBJECT_OT_meshdeform_bind);
+ WM_operatortype_append(OBJECT_OT_explode_refresh);
+ WM_operatortype_append(OBJECT_OT_ocean_bake);
+
+ WM_operatortype_append(OBJECT_OT_constraint_add);
+ WM_operatortype_append(OBJECT_OT_constraint_add_with_targets);
+ WM_operatortype_append(POSE_OT_constraint_add);
+ WM_operatortype_append(POSE_OT_constraint_add_with_targets);
+ WM_operatortype_append(OBJECT_OT_constraints_copy);
+ WM_operatortype_append(POSE_OT_constraints_copy);
+ WM_operatortype_append(OBJECT_OT_constraints_clear);
+ WM_operatortype_append(POSE_OT_constraints_clear);
+ WM_operatortype_append(POSE_OT_ik_add);
+ WM_operatortype_append(POSE_OT_ik_clear);
+ WM_operatortype_append(CONSTRAINT_OT_delete);
+ WM_operatortype_append(CONSTRAINT_OT_move_up);
+ WM_operatortype_append(CONSTRAINT_OT_move_down);
+ WM_operatortype_append(CONSTRAINT_OT_stretchto_reset);
+ WM_operatortype_append(CONSTRAINT_OT_limitdistance_reset);
+ WM_operatortype_append(CONSTRAINT_OT_childof_set_inverse);
+ WM_operatortype_append(CONSTRAINT_OT_childof_clear_inverse);
+ WM_operatortype_append(CONSTRAINT_OT_objectsolver_set_inverse);
+ WM_operatortype_append(CONSTRAINT_OT_objectsolver_clear_inverse);
+ WM_operatortype_append(CONSTRAINT_OT_followpath_path_animate);
+
+ WM_operatortype_append(OBJECT_OT_vertex_group_add);
+ WM_operatortype_append(OBJECT_OT_vertex_group_remove);
+ WM_operatortype_append(OBJECT_OT_vertex_group_assign);
+ WM_operatortype_append(OBJECT_OT_vertex_group_assign_new);
+ WM_operatortype_append(OBJECT_OT_vertex_group_remove_from);
+ WM_operatortype_append(OBJECT_OT_vertex_group_select);
+ WM_operatortype_append(OBJECT_OT_vertex_group_deselect);
+ WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_linked);
+ WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_selected);
+ WM_operatortype_append(OBJECT_OT_vertex_group_copy);
+ WM_operatortype_append(OBJECT_OT_vertex_group_normalize);
+ WM_operatortype_append(OBJECT_OT_vertex_group_normalize_all);
+ WM_operatortype_append(OBJECT_OT_vertex_group_lock);
+ WM_operatortype_append(OBJECT_OT_vertex_group_fix);
+ WM_operatortype_append(OBJECT_OT_vertex_group_invert);
+ WM_operatortype_append(OBJECT_OT_vertex_group_levels);
+ WM_operatortype_append(OBJECT_OT_vertex_group_smooth);
+ WM_operatortype_append(OBJECT_OT_vertex_group_clean);
+ WM_operatortype_append(OBJECT_OT_vertex_group_quantize);
+ WM_operatortype_append(OBJECT_OT_vertex_group_limit_total);
+ WM_operatortype_append(OBJECT_OT_vertex_group_mirror);
+ WM_operatortype_append(OBJECT_OT_vertex_group_set_active);
+ WM_operatortype_append(OBJECT_OT_vertex_group_sort);
+ WM_operatortype_append(OBJECT_OT_vertex_group_move);
+ WM_operatortype_append(OBJECT_OT_vertex_weight_paste);
+ WM_operatortype_append(OBJECT_OT_vertex_weight_delete);
+ WM_operatortype_append(OBJECT_OT_vertex_weight_set_active);
+ WM_operatortype_append(OBJECT_OT_vertex_weight_normalize_active_vertex);
+ WM_operatortype_append(OBJECT_OT_vertex_weight_copy);
+
+ WM_operatortype_append(OBJECT_OT_face_map_add);
+ WM_operatortype_append(OBJECT_OT_face_map_remove);
+ WM_operatortype_append(OBJECT_OT_face_map_assign);
+ WM_operatortype_append(OBJECT_OT_face_map_remove_from);
+ WM_operatortype_append(OBJECT_OT_face_map_select);
+ WM_operatortype_append(OBJECT_OT_face_map_deselect);
+ WM_operatortype_append(OBJECT_OT_face_map_move);
+
+ WM_operatortype_append(TRANSFORM_OT_vertex_warp);
+
+ WM_operatortype_append(OBJECT_OT_move_to_collection);
+ WM_operatortype_append(OBJECT_OT_link_to_collection);
+
+ WM_operatortype_append(OBJECT_OT_shape_key_add);
+ WM_operatortype_append(OBJECT_OT_shape_key_remove);
+ WM_operatortype_append(OBJECT_OT_shape_key_clear);
+ WM_operatortype_append(OBJECT_OT_shape_key_retime);
+ WM_operatortype_append(OBJECT_OT_shape_key_mirror);
+ WM_operatortype_append(OBJECT_OT_shape_key_move);
+
+ WM_operatortype_append(OBJECT_OT_collection_add);
+ WM_operatortype_append(OBJECT_OT_collection_link);
+ WM_operatortype_append(OBJECT_OT_collection_remove);
+ WM_operatortype_append(OBJECT_OT_collection_unlink);
+ WM_operatortype_append(OBJECT_OT_collection_objects_select);
+
+ WM_operatortype_append(OBJECT_OT_hook_add_selob);
+ WM_operatortype_append(OBJECT_OT_hook_add_newob);
+ WM_operatortype_append(OBJECT_OT_hook_remove);
+ WM_operatortype_append(OBJECT_OT_hook_select);
+ WM_operatortype_append(OBJECT_OT_hook_assign);
+ WM_operatortype_append(OBJECT_OT_hook_reset);
+ WM_operatortype_append(OBJECT_OT_hook_recenter);
+
+ WM_operatortype_append(OBJECT_OT_bake_image);
+ WM_operatortype_append(OBJECT_OT_bake);
+ WM_operatortype_append(OBJECT_OT_drop_named_material);
+ WM_operatortype_append(OBJECT_OT_unlink_data);
+ WM_operatortype_append(OBJECT_OT_laplaciandeform_bind);
+
+ WM_operatortype_append(TRANSFORM_OT_vertex_random);
+
+ WM_operatortype_append(OBJECT_OT_data_transfer);
+ WM_operatortype_append(OBJECT_OT_datalayout_transfer);
+ WM_operatortype_append(OBJECT_OT_surfacedeform_bind);
+
+ WM_operatortype_append(OBJECT_OT_hide_view_clear);
+ WM_operatortype_append(OBJECT_OT_hide_view_set);
+ WM_operatortype_append(OBJECT_OT_hide_collection);
}
void ED_operatormacros_object(void)
{
- wmOperatorType *ot;
- wmOperatorTypeMacro *otmacro;
-
- ot = WM_operatortype_append_macro("OBJECT_OT_duplicate_move", "Duplicate Objects",
- "Duplicate selected objects and move them", OPTYPE_UNDO | OPTYPE_REGISTER);
- if (ot) {
- WM_operatortype_macro_define(ot, "OBJECT_OT_duplicate");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
- }
-
- /* grr, should be able to pass options on... */
- ot = WM_operatortype_append_macro("OBJECT_OT_duplicate_move_linked", "Duplicate Linked",
- "Duplicate selected objects and move them", OPTYPE_UNDO | OPTYPE_REGISTER);
- if (ot) {
- otmacro = WM_operatortype_macro_define(ot, "OBJECT_OT_duplicate");
- RNA_boolean_set(otmacro->ptr, "linked", true);
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
- }
-
+ wmOperatorType *ot;
+ wmOperatorTypeMacro *otmacro;
+
+ ot = WM_operatortype_append_macro("OBJECT_OT_duplicate_move",
+ "Duplicate Objects",
+ "Duplicate selected objects and move them",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ if (ot) {
+ WM_operatortype_macro_define(ot, "OBJECT_OT_duplicate");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
+ }
+
+ /* grr, should be able to pass options on... */
+ ot = WM_operatortype_append_macro("OBJECT_OT_duplicate_move_linked",
+ "Duplicate Linked",
+ "Duplicate selected objects and move them",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ if (ot) {
+ otmacro = WM_operatortype_macro_define(ot, "OBJECT_OT_duplicate");
+ RNA_boolean_set(otmacro->ptr, "linked", true);
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
+ }
}
static bool object_mode_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
- return (!ob || ob->mode == OB_MODE_OBJECT);
+ Object *ob = CTX_data_active_object(C);
+ return (!ob || ob->mode == OB_MODE_OBJECT);
}
void ED_keymap_object(wmKeyConfig *keyconf)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- /* Objects, Regardless of Mode -------------------------------------------------- */
- keymap = WM_keymap_ensure(keyconf, "Object Non-modal", 0, 0);
+ /* Objects, Regardless of Mode -------------------------------------------------- */
+ keymap = WM_keymap_ensure(keyconf, "Object Non-modal", 0, 0);
- /* Object Mode ---------------------------------------------------------------- */
- /* Note: this keymap gets disabled in non-objectmode, */
- keymap = WM_keymap_ensure(keyconf, "Object Mode", 0, 0);
- keymap->poll = object_mode_poll;
+ /* Object Mode ---------------------------------------------------------------- */
+ /* Note: this keymap gets disabled in non-objectmode, */
+ keymap = WM_keymap_ensure(keyconf, "Object Mode", 0, 0);
+ keymap->poll = object_mode_poll;
}
diff --git a/source/blender/editors/object/object_random.c b/source/blender/editors/object/object_random.c
index 7c176318c57..c151f565ecb 100644
--- a/source/blender/editors/object/object_random.c
+++ b/source/blender/editors/object/object_random.c
@@ -29,7 +29,6 @@
#include "BLI_math.h"
#include "BLI_rand.h"
-
#include "BKE_context.h"
#include "BKE_layer.h"
@@ -43,127 +42,142 @@
#include "object_intern.h"
-
/**
* Generic randomize vertices function
*/
-static bool object_rand_transverts(
- TransVertStore *tvs,
- const float offset, const float uniform, const float normal_factor,
- const unsigned int seed)
+static bool object_rand_transverts(TransVertStore *tvs,
+ const float offset,
+ const float uniform,
+ const float normal_factor,
+ const unsigned int seed)
{
- bool use_normal = (normal_factor != 0.0f);
- struct RNG *rng;
- TransVert *tv;
- int a;
+ bool use_normal = (normal_factor != 0.0f);
+ struct RNG *rng;
+ TransVert *tv;
+ int a;
- if (!tvs || !(tvs->transverts)) {
- return false;
- }
+ if (!tvs || !(tvs->transverts)) {
+ return false;
+ }
- rng = BLI_rng_new(seed);
+ rng = BLI_rng_new(seed);
- tv = tvs->transverts;
- for (a = 0; a < tvs->transverts_tot; a++, tv++) {
- const float t = max_ff(0.0f, uniform + ((1.0f - uniform) * BLI_rng_get_float(rng)));
- float vec[3];
- BLI_rng_get_float_unit_v3(rng, vec);
+ tv = tvs->transverts;
+ for (a = 0; a < tvs->transverts_tot; a++, tv++) {
+ const float t = max_ff(0.0f, uniform + ((1.0f - uniform) * BLI_rng_get_float(rng)));
+ float vec[3];
+ BLI_rng_get_float_unit_v3(rng, vec);
- if (use_normal && (tv->flag & TX_VERT_USE_NORMAL)) {
- float no[3];
+ if (use_normal && (tv->flag & TX_VERT_USE_NORMAL)) {
+ float no[3];
- /* avoid >90d rotation to align with normal */
- if (dot_v3v3(vec, tv->normal) < 0.0f) {
- negate_v3_v3(no, tv->normal);
- }
- else {
- copy_v3_v3(no, tv->normal);
- }
+ /* avoid >90d rotation to align with normal */
+ if (dot_v3v3(vec, tv->normal) < 0.0f) {
+ negate_v3_v3(no, tv->normal);
+ }
+ else {
+ copy_v3_v3(no, tv->normal);
+ }
- interp_v3_v3v3_slerp_safe(vec, vec, no, normal_factor);
- }
+ interp_v3_v3v3_slerp_safe(vec, vec, no, normal_factor);
+ }
- madd_v3_v3fl(tv->loc, vec, offset * t);
- }
+ madd_v3_v3fl(tv->loc, vec, offset * t);
+ }
- BLI_rng_free(rng);
+ BLI_rng_free(rng);
- return true;
+ return true;
}
static int object_rand_verts_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob_active = CTX_data_edit_object(C);
- const int ob_mode = ob_active->mode;
-
- 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");
-
- bool changed_multi = false;
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len, ob_mode);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob_iter = objects[ob_index];
-
- TransVertStore tvs = { NULL };
-
- if (ob_iter) {
- int mode = TM_ALL_JOINTS;
-
- if (normal_factor != 0.0f) {
- mode |= TX_VERT_USE_NORMAL;
- }
-
- ED_transverts_create_from_obedit(&tvs, ob_iter, mode);
- if (tvs.transverts_tot == 0) {
- continue;
- }
-
- int seed_iter = seed;
- /* This gives a consistent result regardless of object order. */
- if (ob_index) {
- seed_iter += BLI_ghashutil_strhash_p(ob_iter->id.name);
- }
-
- object_rand_transverts(&tvs, offset, uniform, normal_factor, seed_iter);
-
- ED_transverts_update_obedit(&tvs, ob_iter);
- ED_transverts_free(&tvs);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
- changed_multi = true;
- }
- }
- MEM_freeN(objects);
-
- return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob_active = CTX_data_edit_object(C);
+ const int ob_mode = ob_active->mode;
+
+ 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");
+
+ bool changed_multi = false;
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len, ob_mode);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob_iter = objects[ob_index];
+
+ TransVertStore tvs = {NULL};
+
+ if (ob_iter) {
+ int mode = TM_ALL_JOINTS;
+
+ if (normal_factor != 0.0f) {
+ mode |= TX_VERT_USE_NORMAL;
+ }
+
+ ED_transverts_create_from_obedit(&tvs, ob_iter, mode);
+ if (tvs.transverts_tot == 0) {
+ continue;
+ }
+
+ int seed_iter = seed;
+ /* This gives a consistent result regardless of object order. */
+ if (ob_index) {
+ seed_iter += BLI_ghashutil_strhash_p(ob_iter->id.name);
+ }
+
+ object_rand_transverts(&tvs, offset, uniform, normal_factor, seed_iter);
+
+ ED_transverts_update_obedit(&tvs, ob_iter);
+ ED_transverts_free(&tvs);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
+ changed_multi = true;
+ }
+ }
+ MEM_freeN(objects);
+
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void TRANSFORM_OT_vertex_random(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Randomize";
- ot->description = "Randomize vertices";
- ot->idname = "TRANSFORM_OT_vertex_random";
-
- /* api callbacks */
- ot->exec = object_rand_verts_exec;
- ot->poll = ED_transverts_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- ot->prop = RNA_def_float_distance(
- ot->srna, "offset", 0.1f, -FLT_MAX, FLT_MAX,
- "Amount", "Distance to offset", -10.0f, 10.0f);
- RNA_def_float_factor(ot->srna, "uniform", 0.0f, 0.0f, 1.0f, "Uniform",
- "Increase for uniform offset distance", 0.0f, 1.0f);
- RNA_def_float_factor(ot->srna, "normal", 0.0f, 0.0f, 1.0f, "Normal",
- "Align offset direction to normals", 0.0f, 1.0f);
- RNA_def_int(ot->srna, "seed", 0, 0, 10000, "Random Seed", "Seed for the random number generator", 0, 50);
+ /* identifiers */
+ ot->name = "Randomize";
+ ot->description = "Randomize vertices";
+ ot->idname = "TRANSFORM_OT_vertex_random";
+
+ /* api callbacks */
+ ot->exec = object_rand_verts_exec;
+ ot->poll = ED_transverts_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ ot->prop = RNA_def_float_distance(
+ ot->srna, "offset", 0.1f, -FLT_MAX, FLT_MAX, "Amount", "Distance to offset", -10.0f, 10.0f);
+ RNA_def_float_factor(ot->srna,
+ "uniform",
+ 0.0f,
+ 0.0f,
+ 1.0f,
+ "Uniform",
+ "Increase for uniform offset distance",
+ 0.0f,
+ 1.0f);
+ RNA_def_float_factor(ot->srna,
+ "normal",
+ 0.0f,
+ 0.0f,
+ 1.0f,
+ "Normal",
+ "Align offset direction to normals",
+ 0.0f,
+ 1.0f);
+ RNA_def_int(
+ ot->srna, "seed", 0, 0, 10000, "Random Seed", "Seed for the random number generator", 0, 50);
}
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index a9b00e7bbdd..3744632be3d 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -116,177 +115,196 @@
static bool vertex_parent_set_poll(bContext *C)
{
- return ED_operator_editmesh(C) || ED_operator_editsurfcurve(C) || ED_operator_editlattice(C);
+ return ED_operator_editmesh(C) || ED_operator_editsurfcurve(C) || ED_operator_editlattice(C);
}
static int vertex_parent_set_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *obedit = CTX_data_edit_object(C);
- BMVert *eve;
- BMIter iter;
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- Object *par;
- int a, v1 = 0, v2 = 0, v3 = 0, v4 = 0, nr = 1;
-
- /* we need 1 to 3 selected vertices */
-
- if (obedit->type == OB_MESH) {
- Mesh *me = obedit->data;
- BMEditMesh *em;
-
- EDBM_mesh_load(bmain, obedit);
- EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
-
- DEG_id_tag_update(obedit->data, 0);
-
- em = me->edit_mesh;
-
- EDBM_mesh_normals_update(em);
- BKE_editmesh_tessface_calc(em);
-
- /* Make sure the evaluated mesh is updated.
- *
- * Most reliable way is to update the tagged objects, which will ensure
- * proper copy-on-write update, but also will make sure all dependent
- * objects are also up to date. */
- BKE_scene_graph_update_tagged(depsgraph, bmain);
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- if (v1 == 0) v1 = nr;
- else if (v2 == 0) v2 = nr;
- else if (v3 == 0) v3 = nr;
- else if (v4 == 0) v4 = nr;
- else break;
- }
- nr++;
- }
- }
- else if (ELEM(obedit->type, OB_SURF, OB_CURVE)) {
- ListBase *editnurb = object_editcurve_get(obedit);
-
- nu = editnurb->first;
- while (nu) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
- if (v1 == 0) v1 = nr;
- else if (v2 == 0) v2 = nr;
- else if (v3 == 0) v3 = nr;
- else if (v4 == 0) v4 = nr;
- else break;
- }
- nr++;
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (bp->f1 & SELECT) {
- if (v1 == 0) v1 = nr;
- else if (v2 == 0) v2 = nr;
- else if (v3 == 0) v3 = nr;
- else if (v4 == 0) v4 = nr;
- else break;
- }
- nr++;
- bp++;
- }
- }
- nu = nu->next;
- }
- }
- else if (obedit->type == OB_LATTICE) {
- Lattice *lt = obedit->data;
-
- a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
- bp = lt->editlatt->latt->def;
- while (a--) {
- if (bp->f1 & SELECT) {
- if (v1 == 0) v1 = nr;
- else if (v2 == 0) v2 = nr;
- else if (v3 == 0) v3 = nr;
- else if (v4 == 0) v4 = nr;
- else break;
- }
- nr++;
- bp++;
- }
- }
-
- if (v4 || !((v1 && v2 == 0 && v3 == 0) || (v1 && v2 && v3))) {
- BKE_report(op->reports, RPT_ERROR, "Select either 1 or 3 vertices to parent to");
- return OPERATOR_CANCELLED;
- }
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (ob != obedit) {
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- par = obedit->parent;
-
- if (BKE_object_parent_loop_check(par, ob)) {
- BKE_report(op->reports, RPT_ERROR, "Loop in parents");
- }
- else {
- Object workob;
-
- ob->parent = BASACT(view_layer)->object;
- if (v3) {
- ob->partype = PARVERT3;
- ob->par1 = v1 - 1;
- ob->par2 = v2 - 1;
- ob->par3 = v3 - 1;
-
- /* inverse parent matrix */
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
- }
- else {
- ob->partype = PARVERT1;
- ob->par1 = v1 - 1;
-
- /* inverse parent matrix */
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
- }
- }
- }
- }
- CTX_DATA_END;
-
- DEG_relations_tag_update(bmain);
-
- WM_event_add_notifier(C, NC_OBJECT, NULL);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obedit = CTX_data_edit_object(C);
+ BMVert *eve;
+ BMIter iter;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ Object *par;
+ int a, v1 = 0, v2 = 0, v3 = 0, v4 = 0, nr = 1;
+
+ /* we need 1 to 3 selected vertices */
+
+ if (obedit->type == OB_MESH) {
+ Mesh *me = obedit->data;
+ BMEditMesh *em;
+
+ EDBM_mesh_load(bmain, obedit);
+ EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
+
+ DEG_id_tag_update(obedit->data, 0);
+
+ em = me->edit_mesh;
+
+ EDBM_mesh_normals_update(em);
+ BKE_editmesh_tessface_calc(em);
+
+ /* Make sure the evaluated mesh is updated.
+ *
+ * Most reliable way is to update the tagged objects, which will ensure
+ * proper copy-on-write update, but also will make sure all dependent
+ * objects are also up to date. */
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ if (v1 == 0)
+ v1 = nr;
+ else if (v2 == 0)
+ v2 = nr;
+ else if (v3 == 0)
+ v3 = nr;
+ else if (v4 == 0)
+ v4 = nr;
+ else
+ break;
+ }
+ nr++;
+ }
+ }
+ else if (ELEM(obedit->type, OB_SURF, OB_CURVE)) {
+ ListBase *editnurb = object_editcurve_get(obedit);
+
+ nu = editnurb->first;
+ while (nu) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
+ if (v1 == 0)
+ v1 = nr;
+ else if (v2 == 0)
+ v2 = nr;
+ else if (v3 == 0)
+ v3 = nr;
+ else if (v4 == 0)
+ v4 = nr;
+ else
+ break;
+ }
+ nr++;
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ if (v1 == 0)
+ v1 = nr;
+ else if (v2 == 0)
+ v2 = nr;
+ else if (v3 == 0)
+ v3 = nr;
+ else if (v4 == 0)
+ v4 = nr;
+ else
+ break;
+ }
+ nr++;
+ bp++;
+ }
+ }
+ nu = nu->next;
+ }
+ }
+ else if (obedit->type == OB_LATTICE) {
+ Lattice *lt = obedit->data;
+
+ a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
+ bp = lt->editlatt->latt->def;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ if (v1 == 0)
+ v1 = nr;
+ else if (v2 == 0)
+ v2 = nr;
+ else if (v3 == 0)
+ v3 = nr;
+ else if (v4 == 0)
+ v4 = nr;
+ else
+ break;
+ }
+ nr++;
+ bp++;
+ }
+ }
+
+ if (v4 || !((v1 && v2 == 0 && v3 == 0) || (v1 && v2 && v3))) {
+ BKE_report(op->reports, RPT_ERROR, "Select either 1 or 3 vertices to parent to");
+ return OPERATOR_CANCELLED;
+ }
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (ob != obedit) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ par = obedit->parent;
+
+ if (BKE_object_parent_loop_check(par, ob)) {
+ BKE_report(op->reports, RPT_ERROR, "Loop in parents");
+ }
+ else {
+ Object workob;
+
+ ob->parent = BASACT(view_layer)->object;
+ if (v3) {
+ ob->partype = PARVERT3;
+ ob->par1 = v1 - 1;
+ ob->par2 = v2 - 1;
+ ob->par3 = v3 - 1;
+
+ /* inverse parent matrix */
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
+ invert_m4_m4(ob->parentinv, workob.obmat);
+ }
+ else {
+ ob->partype = PARVERT1;
+ ob->par1 = v1 - 1;
+
+ /* inverse parent matrix */
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
+ invert_m4_m4(ob->parentinv, workob.obmat);
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ DEG_relations_tag_update(bmain);
+
+ WM_event_add_notifier(C, NC_OBJECT, NULL);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_parent_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Vertex Parent";
- ot->description = "Parent selected objects to the selected vertices";
- ot->idname = "OBJECT_OT_vertex_parent_set";
-
- /* api callbacks */
- ot->invoke = WM_operator_confirm;
- ot->poll = vertex_parent_set_poll;
- ot->exec = vertex_parent_set_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Make Vertex Parent";
+ ot->description = "Parent selected objects to the selected vertices";
+ ot->idname = "OBJECT_OT_vertex_parent_set";
+
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->poll = vertex_parent_set_poll;
+ ot->exec = vertex_parent_set_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** Make Proxy Operator *************************/
@@ -294,991 +312,1026 @@ void OBJECT_OT_vertex_parent_set(wmOperatorType *ot)
/* set the object to proxify */
static int make_proxy_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
-
- /* sanity checks */
- if (!scene || ID_IS_LINKED(scene) || !ob)
- return OPERATOR_CANCELLED;
-
- /* Get object to work on - use a menu if we need to... */
- if (ob->instance_collection && ID_IS_LINKED(ob->instance_collection)) {
- /* gives menu with list of objects in group */
- /* proxy_group_objects_menu(C, op, ob, ob->instance_collection); */
- WM_enum_search_invoke(C, op, event);
- return OPERATOR_CANCELLED;
- }
- else if (ID_IS_LINKED(ob)) {
- uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("OK?"), ICON_QUESTION);
- uiLayout *layout = UI_popup_menu_layout(pup);
-
- /* create operator menu item with relevant properties filled in */
- PointerRNA opptr_dummy;
- uiItemFullO_ptr(layout, op->type, op->type->name, ICON_NONE, NULL,
- WM_OP_EXEC_REGION_WIN, 0, &opptr_dummy);
-
- /* present the menu and be done... */
- UI_popup_menu_end(C, pup);
-
- /* this invoke just calls another instance of this operator... */
- return OPERATOR_INTERFACE;
- }
- else {
- /* error.. cannot continue */
- BKE_report(op->reports, RPT_ERROR, "Can only make proxy for a referenced object or collection");
- return OPERATOR_CANCELLED;
- }
-
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+
+ /* sanity checks */
+ if (!scene || ID_IS_LINKED(scene) || !ob)
+ return OPERATOR_CANCELLED;
+
+ /* Get object to work on - use a menu if we need to... */
+ if (ob->instance_collection && ID_IS_LINKED(ob->instance_collection)) {
+ /* gives menu with list of objects in group */
+ /* proxy_group_objects_menu(C, op, ob, ob->instance_collection); */
+ WM_enum_search_invoke(C, op, event);
+ return OPERATOR_CANCELLED;
+ }
+ else if (ID_IS_LINKED(ob)) {
+ uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("OK?"), ICON_QUESTION);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+
+ /* create operator menu item with relevant properties filled in */
+ PointerRNA opptr_dummy;
+ uiItemFullO_ptr(
+ layout, op->type, op->type->name, ICON_NONE, NULL, WM_OP_EXEC_REGION_WIN, 0, &opptr_dummy);
+
+ /* present the menu and be done... */
+ UI_popup_menu_end(C, pup);
+
+ /* this invoke just calls another instance of this operator... */
+ return OPERATOR_INTERFACE;
+ }
+ else {
+ /* error.. cannot continue */
+ BKE_report(
+ op->reports, RPT_ERROR, "Can only make proxy for a referenced object or collection");
+ return OPERATOR_CANCELLED;
+ }
}
static int make_proxy_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob, *gob = ED_object_active_context(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- if (gob->instance_collection != NULL) {
- const ListBase instance_collection_objects = BKE_collection_object_cache_get(gob->instance_collection);
- Base *base = BLI_findlink(&instance_collection_objects, RNA_enum_get(op->ptr, "object"));
- ob = base->object;
- }
- else {
- ob = gob;
- }
-
- if (ob) {
- Object *newob;
- char name[MAX_ID_NAME + 4];
-
- BLI_snprintf(name, sizeof(name), "%s_proxy", ((ID *)(gob ? gob : ob))->name + 2);
-
- /* Add new object for the proxy */
- newob = BKE_object_add_from(bmain, scene, view_layer, OB_EMPTY, name, gob ? gob : ob);
-
- /* set layers OK */
- BKE_object_make_proxy(bmain, newob, ob, gob);
-
- /* Set back pointer immediately so dependency graph knows that this is
- * is a proxy and will act accordingly. Otherwise correctness of graph
- * will depend on order of bases.
- *
- * TODO(sergey): We really need to get rid of this bi-directional links
- * in proxies with something like static overrides.
- */
- newob->proxy->proxy_from = newob;
-
- /* depsgraph flushes are needed for the new data */
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&newob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, newob);
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "No object to make proxy for");
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Object *ob, *gob = ED_object_active_context(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ if (gob->instance_collection != NULL) {
+ const ListBase instance_collection_objects = BKE_collection_object_cache_get(
+ gob->instance_collection);
+ Base *base = BLI_findlink(&instance_collection_objects, RNA_enum_get(op->ptr, "object"));
+ ob = base->object;
+ }
+ else {
+ ob = gob;
+ }
+
+ if (ob) {
+ Object *newob;
+ char name[MAX_ID_NAME + 4];
+
+ BLI_snprintf(name, sizeof(name), "%s_proxy", ((ID *)(gob ? gob : ob))->name + 2);
+
+ /* Add new object for the proxy */
+ newob = BKE_object_add_from(bmain, scene, view_layer, OB_EMPTY, name, gob ? gob : ob);
+
+ /* set layers OK */
+ BKE_object_make_proxy(bmain, newob, ob, gob);
+
+ /* Set back pointer immediately so dependency graph knows that this is
+ * is a proxy and will act accordingly. Otherwise correctness of graph
+ * will depend on order of bases.
+ *
+ * TODO(sergey): We really need to get rid of this bi-directional links
+ * in proxies with something like static overrides.
+ */
+ newob->proxy->proxy_from = newob;
+
+ /* depsgraph flushes are needed for the new data */
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&newob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, newob);
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No object to make proxy for");
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
/* Generic itemf's for operators that take library args */
-static const EnumPropertyItem *proxy_collection_object_itemf(
- bContext *C, PointerRNA *UNUSED(ptr),
- PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *proxy_collection_object_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- EnumPropertyItem item_tmp = {0}, *item = NULL;
- int totitem = 0;
- int i = 0;
- Object *ob = ED_object_active_context(C);
-
- if (!ob || !ob->instance_collection)
- return DummyRNA_DEFAULT_items;
-
- /* find the object to affect */
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(ob->instance_collection, object)
- {
- item_tmp.identifier = item_tmp.name = object->id.name + 2;
- item_tmp.value = i++;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ EnumPropertyItem item_tmp = {0}, *item = NULL;
+ int totitem = 0;
+ int i = 0;
+ Object *ob = ED_object_active_context(C);
+
+ if (!ob || !ob->instance_collection)
+ return DummyRNA_DEFAULT_items;
+
+ /* find the object to affect */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (ob->instance_collection, object) {
+ item_tmp.identifier = item_tmp.name = object->id.name + 2;
+ item_tmp.value = i++;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
void OBJECT_OT_proxy_make(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Make Proxy";
- ot->idname = "OBJECT_OT_proxy_make";
- ot->description = "Add empty object to become local replacement data of a library-linked object";
-
- /* callbacks */
- ot->invoke = make_proxy_invoke;
- ot->exec = make_proxy_exec;
- ot->poll = ED_operator_object_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- /* XXX, relies on hard coded ID at the moment */
- prop = RNA_def_enum(ot->srna, "object", DummyRNA_DEFAULT_items, 0, "Proxy Object",
- "Name of lib-linked/collection object to make a proxy for");
- RNA_def_enum_funcs(prop, proxy_collection_object_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Make Proxy";
+ ot->idname = "OBJECT_OT_proxy_make";
+ ot->description = "Add empty object to become local replacement data of a library-linked object";
+
+ /* callbacks */
+ ot->invoke = make_proxy_invoke;
+ ot->exec = make_proxy_exec;
+ ot->poll = ED_operator_object_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ /* XXX, relies on hard coded ID at the moment */
+ prop = RNA_def_enum(ot->srna,
+ "object",
+ DummyRNA_DEFAULT_items,
+ 0,
+ "Proxy Object",
+ "Name of lib-linked/collection object to make a proxy for");
+ RNA_def_enum_funcs(prop, proxy_collection_object_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
/********************** Clear Parent Operator ******************* */
typedef enum eObClearParentTypes {
- CLEAR_PARENT_ALL = 0,
- CLEAR_PARENT_KEEP_TRANSFORM,
- CLEAR_PARENT_INVERSE,
+ CLEAR_PARENT_ALL = 0,
+ CLEAR_PARENT_KEEP_TRANSFORM,
+ CLEAR_PARENT_INVERSE,
} eObClearParentTypes;
EnumPropertyItem prop_clear_parent_types[] = {
- {CLEAR_PARENT_ALL, "CLEAR", 0, "Clear Parent",
- "Completely clear the parenting relationship, including involved modifiers if any"},
- {CLEAR_PARENT_KEEP_TRANSFORM, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation",
- "As 'Clear Parent', but keep the current visual transformations of the object"},
- {CLEAR_PARENT_INVERSE, "CLEAR_INVERSE", 0, "Clear Parent Inverse",
- "Reset the transform corrections applied to the parenting relationship, does not remove parenting itself"},
- {0, NULL, 0, NULL, NULL},
+ {CLEAR_PARENT_ALL,
+ "CLEAR",
+ 0,
+ "Clear Parent",
+ "Completely clear the parenting relationship, including involved modifiers if any"},
+ {CLEAR_PARENT_KEEP_TRANSFORM,
+ "CLEAR_KEEP_TRANSFORM",
+ 0,
+ "Clear and Keep Transformation",
+ "As 'Clear Parent', but keep the current visual transformations of the object"},
+ {CLEAR_PARENT_INVERSE,
+ "CLEAR_INVERSE",
+ 0,
+ "Clear Parent Inverse",
+ "Reset the transform corrections applied to the parenting relationship, does not remove "
+ "parenting itself"},
+ {0, NULL, 0, NULL, NULL},
};
/* Helper for ED_object_parent_clear() - Remove deform-modifiers associated with parent */
static void object_remove_parent_deform_modifiers(Object *ob, const Object *par)
{
- if (ELEM(par->type, OB_ARMATURE, OB_LATTICE, OB_CURVE)) {
- ModifierData *md, *mdn;
-
- /* assume that we only need to remove the first instance of matching deform modifier here */
- for (md = ob->modifiers.first; md; md = mdn) {
- bool free = false;
-
- mdn = md->next;
-
- /* need to match types (modifier + parent) and references */
- if ((md->type == eModifierType_Armature) && (par->type == OB_ARMATURE)) {
- ArmatureModifierData *amd = (ArmatureModifierData *)md;
- if (amd->object == par) {
- free = true;
- }
- }
- else if ((md->type == eModifierType_Lattice) && (par->type == OB_LATTICE)) {
- LatticeModifierData *lmd = (LatticeModifierData *)md;
- if (lmd->object == par) {
- free = true;
- }
- }
- else if ((md->type == eModifierType_Curve) && (par->type == OB_CURVE)) {
- CurveModifierData *cmd = (CurveModifierData *)md;
- if (cmd->object == par) {
- free = true;
- }
- }
-
- /* free modifier if match */
- if (free) {
- BLI_remlink(&ob->modifiers, md);
- modifier_free(md);
- }
- }
- }
+ if (ELEM(par->type, OB_ARMATURE, OB_LATTICE, OB_CURVE)) {
+ ModifierData *md, *mdn;
+
+ /* assume that we only need to remove the first instance of matching deform modifier here */
+ for (md = ob->modifiers.first; md; md = mdn) {
+ bool free = false;
+
+ mdn = md->next;
+
+ /* need to match types (modifier + parent) and references */
+ if ((md->type == eModifierType_Armature) && (par->type == OB_ARMATURE)) {
+ ArmatureModifierData *amd = (ArmatureModifierData *)md;
+ if (amd->object == par) {
+ free = true;
+ }
+ }
+ else if ((md->type == eModifierType_Lattice) && (par->type == OB_LATTICE)) {
+ LatticeModifierData *lmd = (LatticeModifierData *)md;
+ if (lmd->object == par) {
+ free = true;
+ }
+ }
+ else if ((md->type == eModifierType_Curve) && (par->type == OB_CURVE)) {
+ CurveModifierData *cmd = (CurveModifierData *)md;
+ if (cmd->object == par) {
+ free = true;
+ }
+ }
+
+ /* free modifier if match */
+ if (free) {
+ BLI_remlink(&ob->modifiers, md);
+ modifier_free(md);
+ }
+ }
+ }
}
void ED_object_parent_clear(Object *ob, const int type)
{
- if (ob->parent == NULL)
- return;
-
- switch (type) {
- case CLEAR_PARENT_ALL:
- {
- /* for deformers, remove corresponding modifiers to prevent
- * a large number of modifiers building up */
- object_remove_parent_deform_modifiers(ob, ob->parent);
-
- /* clear parenting relationship completely */
- ob->parent = NULL;
- break;
- }
- case CLEAR_PARENT_KEEP_TRANSFORM:
- {
- /* remove parent, and apply the parented transform
- * result as object's local transforms */
- ob->parent = NULL;
- BKE_object_apply_mat4(ob, ob->obmat, true, false);
- break;
- }
- case CLEAR_PARENT_INVERSE:
- {
- /* object stays parented, but the parent inverse
- * (i.e. offset from parent to retain binding state)
- * is cleared. In other words: nothing to do here! */
- break;
- }
- }
-
- /* Always clear parentinv matrix for sake of consistency, see T41950. */
- unit_m4(ob->parentinv);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ if (ob->parent == NULL)
+ return;
+
+ switch (type) {
+ case CLEAR_PARENT_ALL: {
+ /* for deformers, remove corresponding modifiers to prevent
+ * a large number of modifiers building up */
+ object_remove_parent_deform_modifiers(ob, ob->parent);
+
+ /* clear parenting relationship completely */
+ ob->parent = NULL;
+ break;
+ }
+ case CLEAR_PARENT_KEEP_TRANSFORM: {
+ /* remove parent, and apply the parented transform
+ * result as object's local transforms */
+ ob->parent = NULL;
+ BKE_object_apply_mat4(ob, ob->obmat, true, false);
+ break;
+ }
+ case CLEAR_PARENT_INVERSE: {
+ /* object stays parented, but the parent inverse
+ * (i.e. offset from parent to retain binding state)
+ * is cleared. In other words: nothing to do here! */
+ break;
+ }
+ }
+
+ /* Always clear parentinv matrix for sake of consistency, see T41950. */
+ unit_m4(ob->parentinv);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
}
/* note, poll should check for editable scene */
static int parent_clear_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- const int type = RNA_enum_get(op->ptr, "type");
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- ED_object_parent_clear(ob, type);
- }
- CTX_DATA_END;
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ const int type = RNA_enum_get(op->ptr, "type");
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ ED_object_parent_clear(ob, type);
+ }
+ CTX_DATA_END;
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_parent_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Parent";
- ot->description = "Clear the object's parenting";
- ot->idname = "OBJECT_OT_parent_clear";
+ /* identifiers */
+ ot->name = "Clear Parent";
+ ot->description = "Clear the object's parenting";
+ ot->idname = "OBJECT_OT_parent_clear";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = parent_clear_exec;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = parent_clear_exec;
- ot->poll = ED_operator_object_active_editable;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_parent_types, CLEAR_PARENT_ALL, "Type", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_parent_types, CLEAR_PARENT_ALL, "Type", "");
}
/* ******************** Make Parent Operator *********************** */
void ED_object_parent(Object *ob, Object *par, const int type, const char *substr)
{
- /* Always clear parentinv matrix for sake of consistency, see T41950. */
- unit_m4(ob->parentinv);
+ /* Always clear parentinv matrix for sake of consistency, see T41950. */
+ unit_m4(ob->parentinv);
- if (!par || BKE_object_parent_loop_check(par, ob)) {
- ob->parent = NULL;
- ob->partype = PAROBJECT;
- ob->parsubstr[0] = 0;
- return;
- }
+ if (!par || BKE_object_parent_loop_check(par, ob)) {
+ ob->parent = NULL;
+ ob->partype = PAROBJECT;
+ ob->parsubstr[0] = 0;
+ return;
+ }
- /* Other partypes are deprecated, do not use here! */
- BLI_assert(ELEM(type & PARTYPE, PAROBJECT, PARSKEL, PARVERT1, PARVERT3, PARBONE));
+ /* Other partypes are deprecated, do not use here! */
+ BLI_assert(ELEM(type & PARTYPE, PAROBJECT, PARSKEL, PARVERT1, PARVERT3, PARBONE));
- /* this could use some more checks */
+ /* this could use some more checks */
- ob->parent = par;
- ob->partype &= ~PARTYPE;
- ob->partype |= type;
- BLI_strncpy(ob->parsubstr, substr, sizeof(ob->parsubstr));
+ ob->parent = par;
+ ob->partype &= ~PARTYPE;
+ ob->partype |= type;
+ BLI_strncpy(ob->parsubstr, substr, sizeof(ob->parsubstr));
}
/* Operator Property */
EnumPropertyItem prop_make_parent_types[] = {
- {PAR_OBJECT, "OBJECT", 0, "Object", ""},
- {PAR_ARMATURE, "ARMATURE", 0, "Armature Deform", ""},
- {PAR_ARMATURE_NAME, "ARMATURE_NAME", 0, " With Empty Groups", ""},
- {PAR_ARMATURE_AUTO, "ARMATURE_AUTO", 0, " With Automatic Weights", ""},
- {PAR_ARMATURE_ENVELOPE, "ARMATURE_ENVELOPE", 0, " With Envelope Weights", ""},
- {PAR_BONE, "BONE", 0, "Bone", ""},
- {PAR_BONE_RELATIVE, "BONE_RELATIVE", 0, "Bone Relative", ""},
- {PAR_CURVE, "CURVE", 0, "Curve Deform", ""},
- {PAR_FOLLOW, "FOLLOW", 0, "Follow Path", ""},
- {PAR_PATH_CONST, "PATH_CONST", 0, "Path Constraint", ""},
- {PAR_LATTICE, "LATTICE", 0, "Lattice Deform", ""},
- {PAR_VERTEX, "VERTEX", 0, "Vertex", ""},
- {PAR_VERTEX_TRI, "VERTEX_TRI", 0, "Vertex (Triangle)", ""},
- {0, NULL, 0, NULL, NULL},
+ {PAR_OBJECT, "OBJECT", 0, "Object", ""},
+ {PAR_ARMATURE, "ARMATURE", 0, "Armature Deform", ""},
+ {PAR_ARMATURE_NAME, "ARMATURE_NAME", 0, " With Empty Groups", ""},
+ {PAR_ARMATURE_AUTO, "ARMATURE_AUTO", 0, " With Automatic Weights", ""},
+ {PAR_ARMATURE_ENVELOPE, "ARMATURE_ENVELOPE", 0, " With Envelope Weights", ""},
+ {PAR_BONE, "BONE", 0, "Bone", ""},
+ {PAR_BONE_RELATIVE, "BONE_RELATIVE", 0, "Bone Relative", ""},
+ {PAR_CURVE, "CURVE", 0, "Curve Deform", ""},
+ {PAR_FOLLOW, "FOLLOW", 0, "Follow Path", ""},
+ {PAR_PATH_CONST, "PATH_CONST", 0, "Path Constraint", ""},
+ {PAR_LATTICE, "LATTICE", 0, "Lattice Deform", ""},
+ {PAR_VERTEX, "VERTEX", 0, "Vertex", ""},
+ {PAR_VERTEX_TRI, "VERTEX_TRI", 0, "Vertex (Triangle)", ""},
+ {0, NULL, 0, NULL, NULL},
};
-bool ED_object_parent_set(ReportList *reports, const bContext *C, Scene *scene, Object *ob, Object *par,
- int partype, const bool xmirror, const bool keep_transform, const int vert_par[3])
+bool ED_object_parent_set(ReportList *reports,
+ const bContext *C,
+ Scene *scene,
+ Object *ob,
+ Object *par,
+ int partype,
+ const bool xmirror,
+ const bool keep_transform,
+ const int vert_par[3])
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- bPoseChannel *pchan = NULL;
- bPoseChannel *pchan_eval = NULL;
- const bool pararm = ELEM(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
- Object *parent_eval = DEG_get_evaluated_object(depsgraph, par);
-
- DEG_id_tag_update(&par->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
-
- /* preconditions */
- if (partype == PAR_FOLLOW || partype == PAR_PATH_CONST) {
- if (par->type != OB_CURVE)
- return 0;
- else {
- Curve *cu = par->data;
- Curve *cu_eval = parent_eval->data;
- if ((cu->flag & CU_PATH) == 0) {
- cu->flag |= CU_PATH | CU_FOLLOW;
- cu_eval->flag |= CU_PATH | CU_FOLLOW;
- /* force creation of path data */
- BKE_displist_make_curveTypes(depsgraph, scene, par, false, false, NULL);
- }
- else {
- cu->flag |= CU_FOLLOW;
- cu_eval->flag |= CU_FOLLOW;
- }
-
- /* 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);
-
- /* setup dummy 'generator' modifier here to get 1-1 correspondence still working */
- if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first)
- add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu);
- }
-
- /* fall back on regular parenting now (for follow only) */
- if (partype == PAR_FOLLOW)
- partype = PAR_OBJECT;
- }
- }
- else if (ELEM(partype, PAR_BONE, PAR_BONE_RELATIVE)) {
- pchan = BKE_pose_channel_active(par);
- pchan_eval = BKE_pose_channel_active(parent_eval);
-
- if (pchan == NULL) {
- BKE_report(reports, RPT_ERROR, "No active bone");
- return false;
- }
- }
-
- if (ob != par) {
- if (BKE_object_parent_loop_check(par, ob)) {
- BKE_report(reports, RPT_ERROR, "Loop in parents");
- return false;
- }
- else {
- Object workob;
-
- /* apply transformation of previous parenting */
- if (keep_transform) {
- /* was removed because of bug [#23577],
- * but this can be handy in some cases too [#32616], so make optional */
- BKE_object_apply_mat4(ob, ob->obmat, false, false);
- }
-
- /* set the parent (except for follow-path constraint option) */
- if (partype != PAR_PATH_CONST) {
- ob->parent = par;
- /* Always clear parentinv matrix for sake of consistency, see T41950. */
- unit_m4(ob->parentinv);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
-
- /* handle types */
- if (pchan)
- BLI_strncpy(ob->parsubstr, pchan->name, sizeof(ob->parsubstr));
- else
- ob->parsubstr[0] = 0;
-
- if (partype == PAR_PATH_CONST) {
- /* don't do anything here, since this is not technically "parenting" */
- }
- else if (ELEM(partype, PAR_CURVE, PAR_LATTICE) || (pararm)) {
- /* partype is now set to PAROBJECT so that invisible 'virtual' modifiers don't need to be created
- * NOTE: the old (2.4x) method was to set ob->partype = PARSKEL, creating the virtual modifiers
- */
- ob->partype = PAROBJECT; /* note, dna define, not operator property */
- /* ob->partype = PARSKEL; */ /* note, dna define, not operator property */
-
- /* BUT, to keep the deforms, we need a modifier, and then we need to set the object that it uses
- * - We need to ensure that the modifier we're adding doesn't already exist, so we check this by
- * assuming that the parent is selected too...
- */
- /* XXX currently this should only happen for meshes, curves, surfaces,
- * and lattices - this stuff isn't available for metas yet */
- if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
- ModifierData *md;
-
- switch (partype) {
- case PAR_CURVE: /* curve deform */
- if (modifiers_isDeformedByCurve(ob) != par) {
- md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Curve);
- if (md) {
- ((CurveModifierData *)md)->object = par;
- }
- if (par->runtime.curve_cache && par->runtime.curve_cache->path == NULL) {
- DEG_id_tag_update(&par->id, ID_RECALC_GEOMETRY);
- }
- }
- break;
- case PAR_LATTICE: /* lattice deform */
- if (modifiers_isDeformedByLattice(ob) != par) {
- md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Lattice);
- if (md) {
- ((LatticeModifierData *)md)->object = par;
- }
- }
- break;
- default: /* armature deform */
- if (modifiers_isDeformedByArmature(ob) != par) {
- md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Armature);
- if (md) {
- ((ArmatureModifierData *)md)->object = par;
- }
- }
- break;
- }
- }
- }
- else if (partype == PAR_BONE) {
- ob->partype = PARBONE; /* note, dna define, not operator property */
- if (pchan->bone) {
- pchan->bone->flag &= ~BONE_RELATIVE_PARENTING;
- pchan_eval->bone->flag &= ~BONE_RELATIVE_PARENTING;
- }
- }
- else if (partype == PAR_BONE_RELATIVE) {
- ob->partype = PARBONE; /* note, dna define, not operator property */
- if (pchan->bone) {
- pchan->bone->flag |= BONE_RELATIVE_PARENTING;
- pchan_eval->bone->flag |= BONE_RELATIVE_PARENTING;
- }
- }
- else if (partype == PAR_VERTEX) {
- ob->partype = PARVERT1;
- ob->par1 = vert_par[0];
- }
- else if (partype == PAR_VERTEX_TRI) {
- ob->partype = PARVERT3;
- copy_v3_v3_int(&ob->par1, vert_par);
- }
- else {
- ob->partype = PAROBJECT; /* note, dna define, not operator property */
- }
-
- /* constraint */
- if (partype == PAR_PATH_CONST) {
- bConstraint *con;
- bFollowPathConstraint *data;
- float cmat[4][4], vec[3];
-
- con = BKE_constraint_add_for_object(ob, "AutoPath", CONSTRAINT_TYPE_FOLLOWPATH);
-
- data = con->data;
- data->tar = par;
-
- BKE_constraint_target_matrix_get(depsgraph, scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra);
- sub_v3_v3v3(vec, ob->obmat[3], cmat[3]);
-
- copy_v3_v3(ob->loc, vec);
- }
- else if (pararm && (ob->type == OB_MESH) && (par->type == OB_ARMATURE)) {
- if (partype == PAR_ARMATURE_NAME) {
- ED_object_vgroup_calc_from_armature(reports, depsgraph, scene, ob, par, ARM_GROUPS_NAME, false);
- }
- else if (partype == PAR_ARMATURE_ENVELOPE) {
- ED_object_vgroup_calc_from_armature(reports, depsgraph, scene, ob, par, ARM_GROUPS_ENVELOPE, xmirror);
- }
- else if (partype == PAR_ARMATURE_AUTO) {
- WM_cursor_wait(1);
- ED_object_vgroup_calc_from_armature(reports, depsgraph, scene, ob, par, ARM_GROUPS_AUTO, xmirror);
- WM_cursor_wait(0);
- }
- /* get corrected inverse */
- ob->partype = PAROBJECT;
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
-
- invert_m4_m4(ob->parentinv, workob.obmat);
- }
- else if (pararm && (ob->type == OB_GPENCIL) && (par->type == OB_ARMATURE)) {
- 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))
- {
- WM_cursor_wait(1);
- ED_gpencil_add_armature_weights(C, reports, ob, par, GP_PAR_ARMATURE_AUTO);
- WM_cursor_wait(0);
- }
- /* get corrected inverse */
- ob->partype = PAROBJECT;
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
-
- invert_m4_m4(ob->parentinv, workob.obmat);
- }
- else {
- /* calculate inverse parent matrix */
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- }
- }
-
- return true;
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ bPoseChannel *pchan = NULL;
+ bPoseChannel *pchan_eval = NULL;
+ const bool pararm = ELEM(
+ partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
+ Object *parent_eval = DEG_get_evaluated_object(depsgraph, par);
+
+ DEG_id_tag_update(&par->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ /* preconditions */
+ if (partype == PAR_FOLLOW || partype == PAR_PATH_CONST) {
+ if (par->type != OB_CURVE)
+ return 0;
+ else {
+ Curve *cu = par->data;
+ Curve *cu_eval = parent_eval->data;
+ if ((cu->flag & CU_PATH) == 0) {
+ cu->flag |= CU_PATH | CU_FOLLOW;
+ cu_eval->flag |= CU_PATH | CU_FOLLOW;
+ /* force creation of path data */
+ BKE_displist_make_curveTypes(depsgraph, scene, par, false, false, NULL);
+ }
+ else {
+ cu->flag |= CU_FOLLOW;
+ cu_eval->flag |= CU_FOLLOW;
+ }
+
+ /* 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);
+
+ /* setup dummy 'generator' modifier here to get 1-1 correspondence still working */
+ if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first)
+ add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu);
+ }
+
+ /* fall back on regular parenting now (for follow only) */
+ if (partype == PAR_FOLLOW)
+ partype = PAR_OBJECT;
+ }
+ }
+ else if (ELEM(partype, PAR_BONE, PAR_BONE_RELATIVE)) {
+ pchan = BKE_pose_channel_active(par);
+ pchan_eval = BKE_pose_channel_active(parent_eval);
+
+ if (pchan == NULL) {
+ BKE_report(reports, RPT_ERROR, "No active bone");
+ return false;
+ }
+ }
+
+ if (ob != par) {
+ if (BKE_object_parent_loop_check(par, ob)) {
+ BKE_report(reports, RPT_ERROR, "Loop in parents");
+ return false;
+ }
+ else {
+ Object workob;
+
+ /* apply transformation of previous parenting */
+ if (keep_transform) {
+ /* was removed because of bug [#23577],
+ * but this can be handy in some cases too [#32616], so make optional */
+ BKE_object_apply_mat4(ob, ob->obmat, false, false);
+ }
+
+ /* set the parent (except for follow-path constraint option) */
+ if (partype != PAR_PATH_CONST) {
+ ob->parent = par;
+ /* Always clear parentinv matrix for sake of consistency, see T41950. */
+ unit_m4(ob->parentinv);
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+
+ /* handle types */
+ if (pchan)
+ BLI_strncpy(ob->parsubstr, pchan->name, sizeof(ob->parsubstr));
+ else
+ ob->parsubstr[0] = 0;
+
+ if (partype == PAR_PATH_CONST) {
+ /* don't do anything here, since this is not technically "parenting" */
+ }
+ else if (ELEM(partype, PAR_CURVE, PAR_LATTICE) || (pararm)) {
+ /* partype is now set to PAROBJECT so that invisible 'virtual' modifiers don't need to be created
+ * NOTE: the old (2.4x) method was to set ob->partype = PARSKEL, creating the virtual modifiers
+ */
+ ob->partype = PAROBJECT; /* note, dna define, not operator property */
+ /* ob->partype = PARSKEL; */ /* note, dna define, not operator property */
+
+ /* BUT, to keep the deforms, we need a modifier, and then we need to set the object that it uses
+ * - We need to ensure that the modifier we're adding doesn't already exist, so we check this by
+ * assuming that the parent is selected too...
+ */
+ /* XXX currently this should only happen for meshes, curves, surfaces,
+ * and lattices - this stuff isn't available for metas yet */
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
+ ModifierData *md;
+
+ switch (partype) {
+ case PAR_CURVE: /* curve deform */
+ if (modifiers_isDeformedByCurve(ob) != par) {
+ md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Curve);
+ if (md) {
+ ((CurveModifierData *)md)->object = par;
+ }
+ if (par->runtime.curve_cache && par->runtime.curve_cache->path == NULL) {
+ DEG_id_tag_update(&par->id, ID_RECALC_GEOMETRY);
+ }
+ }
+ break;
+ case PAR_LATTICE: /* lattice deform */
+ if (modifiers_isDeformedByLattice(ob) != par) {
+ md = ED_object_modifier_add(
+ reports, bmain, scene, ob, NULL, eModifierType_Lattice);
+ if (md) {
+ ((LatticeModifierData *)md)->object = par;
+ }
+ }
+ break;
+ default: /* armature deform */
+ if (modifiers_isDeformedByArmature(ob) != par) {
+ md = ED_object_modifier_add(
+ reports, bmain, scene, ob, NULL, eModifierType_Armature);
+ if (md) {
+ ((ArmatureModifierData *)md)->object = par;
+ }
+ }
+ break;
+ }
+ }
+ }
+ else if (partype == PAR_BONE) {
+ ob->partype = PARBONE; /* note, dna define, not operator property */
+ if (pchan->bone) {
+ pchan->bone->flag &= ~BONE_RELATIVE_PARENTING;
+ pchan_eval->bone->flag &= ~BONE_RELATIVE_PARENTING;
+ }
+ }
+ else if (partype == PAR_BONE_RELATIVE) {
+ ob->partype = PARBONE; /* note, dna define, not operator property */
+ if (pchan->bone) {
+ pchan->bone->flag |= BONE_RELATIVE_PARENTING;
+ pchan_eval->bone->flag |= BONE_RELATIVE_PARENTING;
+ }
+ }
+ else if (partype == PAR_VERTEX) {
+ ob->partype = PARVERT1;
+ ob->par1 = vert_par[0];
+ }
+ else if (partype == PAR_VERTEX_TRI) {
+ ob->partype = PARVERT3;
+ copy_v3_v3_int(&ob->par1, vert_par);
+ }
+ else {
+ ob->partype = PAROBJECT; /* note, dna define, not operator property */
+ }
+
+ /* constraint */
+ if (partype == PAR_PATH_CONST) {
+ bConstraint *con;
+ bFollowPathConstraint *data;
+ float cmat[4][4], vec[3];
+
+ con = BKE_constraint_add_for_object(ob, "AutoPath", CONSTRAINT_TYPE_FOLLOWPATH);
+
+ data = con->data;
+ data->tar = par;
+
+ BKE_constraint_target_matrix_get(
+ depsgraph, scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra);
+ sub_v3_v3v3(vec, ob->obmat[3], cmat[3]);
+
+ copy_v3_v3(ob->loc, vec);
+ }
+ else if (pararm && (ob->type == OB_MESH) && (par->type == OB_ARMATURE)) {
+ if (partype == PAR_ARMATURE_NAME) {
+ ED_object_vgroup_calc_from_armature(
+ reports, depsgraph, scene, ob, par, ARM_GROUPS_NAME, false);
+ }
+ else if (partype == PAR_ARMATURE_ENVELOPE) {
+ ED_object_vgroup_calc_from_armature(
+ reports, depsgraph, scene, ob, par, ARM_GROUPS_ENVELOPE, xmirror);
+ }
+ else if (partype == PAR_ARMATURE_AUTO) {
+ WM_cursor_wait(1);
+ ED_object_vgroup_calc_from_armature(
+ reports, depsgraph, scene, ob, par, ARM_GROUPS_AUTO, xmirror);
+ WM_cursor_wait(0);
+ }
+ /* get corrected inverse */
+ ob->partype = PAROBJECT;
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
+
+ invert_m4_m4(ob->parentinv, workob.obmat);
+ }
+ else if (pararm && (ob->type == OB_GPENCIL) && (par->type == OB_ARMATURE)) {
+ 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)) {
+ WM_cursor_wait(1);
+ ED_gpencil_add_armature_weights(C, reports, ob, par, GP_PAR_ARMATURE_AUTO);
+ WM_cursor_wait(0);
+ }
+ /* get corrected inverse */
+ ob->partype = PAROBJECT;
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
+
+ invert_m4_m4(ob->parentinv, workob.obmat);
+ }
+ else {
+ /* calculate inverse parent matrix */
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
+ invert_m4_m4(ob->parentinv, workob.obmat);
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ }
+ }
+
+ return true;
}
-
-
static void parent_set_vert_find(KDTree_3d *tree, Object *child, int vert_par[3], bool is_tri)
{
- const float *co_find = child->obmat[3];
- if (is_tri) {
- KDTreeNearest_3d nearest[3];
- int tot;
-
- tot = BLI_kdtree_3d_find_nearest_n(tree, co_find, nearest, 3);
- BLI_assert(tot == 3);
- UNUSED_VARS(tot);
-
- vert_par[0] = nearest[0].index;
- vert_par[1] = nearest[1].index;
- vert_par[2] = nearest[2].index;
-
- BLI_assert(min_iii(UNPACK3(vert_par)) >= 0);
- }
- else {
- vert_par[0] = BLI_kdtree_3d_find_nearest(tree, co_find, NULL);
- BLI_assert(vert_par[0] >= 0);
- vert_par[1] = 0;
- vert_par[2] = 0;
- }
+ const float *co_find = child->obmat[3];
+ if (is_tri) {
+ KDTreeNearest_3d nearest[3];
+ int tot;
+
+ tot = BLI_kdtree_3d_find_nearest_n(tree, co_find, nearest, 3);
+ BLI_assert(tot == 3);
+ UNUSED_VARS(tot);
+
+ vert_par[0] = nearest[0].index;
+ vert_par[1] = nearest[1].index;
+ vert_par[2] = nearest[2].index;
+
+ BLI_assert(min_iii(UNPACK3(vert_par)) >= 0);
+ }
+ else {
+ vert_par[0] = BLI_kdtree_3d_find_nearest(tree, co_find, NULL);
+ BLI_assert(vert_par[0] >= 0);
+ vert_par[1] = 0;
+ vert_par[2] = 0;
+ }
}
static int parent_set_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *par = ED_object_active_context(C);
- int partype = RNA_enum_get(op->ptr, "type");
- const bool xmirror = RNA_boolean_get(op->ptr, "xmirror");
- const bool keep_transform = RNA_boolean_get(op->ptr, "keep_transform");
- bool ok = true;
-
- /* vertex parent (kdtree) */
- const bool is_vert_par = ELEM(partype, PAR_VERTEX, PAR_VERTEX_TRI);
- const bool is_tri = partype == PAR_VERTEX_TRI;
- int tree_tot;
- struct KDTree_3d *tree = NULL;
- int vert_par[3] = {0, 0, 0};
- const int *vert_par_p = is_vert_par ? vert_par : NULL;
-
-
- if (is_vert_par) {
- tree = BKE_object_as_kdtree(par, &tree_tot);
- BLI_assert(tree != NULL);
-
- if (tree_tot < (is_tri ? 3 : 1)) {
- BKE_report(op->reports, RPT_ERROR, "Not enough vertices for vertex-parent");
- ok = false;
- }
- }
-
- if (ok) {
- /* Non vertex-parent */
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (is_vert_par) {
- parent_set_vert_find(tree, ob, vert_par, is_tri);
- }
-
- if (!ED_object_parent_set(op->reports, C, scene, ob, par, partype, xmirror, keep_transform, vert_par_p)) {
- ok = false;
- break;
- }
- }
- CTX_DATA_END;
- }
-
- if (is_vert_par) {
- BLI_kdtree_3d_free(tree);
- }
-
- if (!ok)
- return OPERATOR_CANCELLED;
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *par = ED_object_active_context(C);
+ int partype = RNA_enum_get(op->ptr, "type");
+ const bool xmirror = RNA_boolean_get(op->ptr, "xmirror");
+ const bool keep_transform = RNA_boolean_get(op->ptr, "keep_transform");
+ bool ok = true;
+
+ /* vertex parent (kdtree) */
+ const bool is_vert_par = ELEM(partype, PAR_VERTEX, PAR_VERTEX_TRI);
+ const bool is_tri = partype == PAR_VERTEX_TRI;
+ int tree_tot;
+ struct KDTree_3d *tree = NULL;
+ int vert_par[3] = {0, 0, 0};
+ const int *vert_par_p = is_vert_par ? vert_par : NULL;
+
+ if (is_vert_par) {
+ tree = BKE_object_as_kdtree(par, &tree_tot);
+ BLI_assert(tree != NULL);
+
+ if (tree_tot < (is_tri ? 3 : 1)) {
+ BKE_report(op->reports, RPT_ERROR, "Not enough vertices for vertex-parent");
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ /* Non vertex-parent */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (is_vert_par) {
+ parent_set_vert_find(tree, ob, vert_par, is_tri);
+ }
+
+ if (!ED_object_parent_set(
+ op->reports, C, scene, ob, par, partype, xmirror, keep_transform, vert_par_p)) {
+ ok = false;
+ break;
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ if (is_vert_par) {
+ BLI_kdtree_3d_free(tree);
+ }
+
+ if (!ok)
+ return OPERATOR_CANCELLED;
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
+
+ return OPERATOR_FINISHED;
}
-
static int parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
- Object *parent = ED_object_active_context(C);
- uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Set Parent To"), ICON_NONE);
- uiLayout *layout = UI_popup_menu_layout(pup);
+ Object *parent = ED_object_active_context(C);
+ uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Set Parent To"), ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
- wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_parent_set", true);
- PointerRNA opptr;
+ wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_parent_set", true);
+ PointerRNA opptr;
#if 0
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_OBJECT);
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_OBJECT);
#else
- uiItemFullO_ptr(layout, ot, IFACE_("Object"), ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
- RNA_enum_set(&opptr, "type", PAR_OBJECT);
- RNA_boolean_set(&opptr, "keep_transform", false);
-
- uiItemFullO_ptr(
- layout, ot, IFACE_("Object (Keep Transform)"), ICON_NONE,
- NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
- RNA_enum_set(&opptr, "type", PAR_OBJECT);
- RNA_boolean_set(&opptr, "keep_transform", true);
+ uiItemFullO_ptr(layout, ot, IFACE_("Object"), ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
+ RNA_enum_set(&opptr, "type", PAR_OBJECT);
+ RNA_boolean_set(&opptr, "keep_transform", false);
+
+ uiItemFullO_ptr(layout,
+ ot,
+ IFACE_("Object (Keep Transform)"),
+ ICON_NONE,
+ NULL,
+ WM_OP_EXEC_DEFAULT,
+ 0,
+ &opptr);
+ RNA_enum_set(&opptr, "type", PAR_OBJECT);
+ RNA_boolean_set(&opptr, "keep_transform", true);
#endif
- uiItemO(layout, IFACE_("Object (Without Inverse)"), ICON_NONE, "OBJECT_OT_parent_no_inverse_set");
-
- struct {
- bool mesh, gpencil;
- } has_children_of_type = { 0 };
-
- CTX_DATA_BEGIN (C, Object *, child, selected_editable_objects)
- {
- if (child == parent) {
- continue;
- }
- if (child->type == OB_MESH) {
- has_children_of_type.mesh = true;
- }
- if (child->type == OB_GPENCIL) {
- has_children_of_type.gpencil = true;
- }
- }
- CTX_DATA_END;
-
- 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.mesh || has_children_of_type.gpencil) {
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_AUTO);
- }
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_BONE);
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_BONE_RELATIVE);
- }
- else if (parent->type == OB_CURVE) {
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_CURVE);
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_FOLLOW);
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_PATH_CONST);
- }
- else if (parent->type == OB_LATTICE) {
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_LATTICE);
- }
-
- /* vertex parenting */
- if (OB_TYPE_SUPPORT_PARVERT(parent->type)) {
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_VERTEX);
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_VERTEX_TRI);
- }
-
- UI_popup_menu_end(C, pup);
-
- return OPERATOR_INTERFACE;
+ uiItemO(
+ layout, IFACE_("Object (Without Inverse)"), ICON_NONE, "OBJECT_OT_parent_no_inverse_set");
+
+ struct {
+ bool mesh, gpencil;
+ } has_children_of_type = {0};
+
+ CTX_DATA_BEGIN (C, Object *, child, selected_editable_objects) {
+ if (child == parent) {
+ continue;
+ }
+ if (child->type == OB_MESH) {
+ has_children_of_type.mesh = true;
+ }
+ if (child->type == OB_GPENCIL) {
+ has_children_of_type.gpencil = true;
+ }
+ }
+ CTX_DATA_END;
+
+ 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.mesh || has_children_of_type.gpencil) {
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_AUTO);
+ }
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_BONE);
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_BONE_RELATIVE);
+ }
+ else if (parent->type == OB_CURVE) {
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_CURVE);
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_FOLLOW);
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_PATH_CONST);
+ }
+ else if (parent->type == OB_LATTICE) {
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_LATTICE);
+ }
+
+ /* vertex parenting */
+ if (OB_TYPE_SUPPORT_PARVERT(parent->type)) {
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_VERTEX);
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_VERTEX_TRI);
+ }
+
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
}
-static bool parent_set_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop)
+static bool parent_set_poll_property(const bContext *UNUSED(C),
+ wmOperator *op,
+ const PropertyRNA *prop)
{
- const char *prop_id = RNA_property_identifier(prop);
-
- /* Only show XMirror for PAR_ARMATURE_ENVELOPE and PAR_ARMATURE_AUTO! */
- if (STREQ(prop_id, "xmirror")) {
- const int type = RNA_enum_get(op->ptr, "type");
- if (ELEM(type, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO))
- return true;
- else
- return false;
- }
-
- return true;
+ const char *prop_id = RNA_property_identifier(prop);
+
+ /* Only show XMirror for PAR_ARMATURE_ENVELOPE and PAR_ARMATURE_AUTO! */
+ if (STREQ(prop_id, "xmirror")) {
+ const int type = RNA_enum_get(op->ptr, "type");
+ if (ELEM(type, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO))
+ return true;
+ else
+ return false;
+ }
+
+ return true;
}
void OBJECT_OT_parent_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Parent";
- ot->description = "Set the object's parenting";
- ot->idname = "OBJECT_OT_parent_set";
-
- /* api callbacks */
- ot->invoke = parent_set_invoke;
- ot->exec = parent_set_exec;
- ot->poll = ED_operator_object_active;
- ot->poll_property = parent_set_poll_property;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ot->prop = RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
- RNA_def_boolean(ot->srna, "xmirror", false, "X Mirror",
- "Apply weights symmetrically along X axis, for Envelope/Automatic vertex groups creation");
- RNA_def_boolean(ot->srna, "keep_transform", false, "Keep Transform",
- "Apply transformation before parenting");
+ /* identifiers */
+ ot->name = "Make Parent";
+ ot->description = "Set the object's parenting";
+ ot->idname = "OBJECT_OT_parent_set";
+
+ /* api callbacks */
+ ot->invoke = parent_set_invoke;
+ ot->exec = parent_set_exec;
+ ot->poll = ED_operator_object_active;
+ ot->poll_property = parent_set_poll_property;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
+ RNA_def_boolean(
+ ot->srna,
+ "xmirror",
+ false,
+ "X Mirror",
+ "Apply weights symmetrically along X axis, for Envelope/Automatic vertex groups creation");
+ RNA_def_boolean(ot->srna,
+ "keep_transform",
+ false,
+ "Keep Transform",
+ "Apply transformation before parenting");
}
/* ************ Make Parent Without Inverse Operator ******************* */
static int parent_noinv_set_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *par = ED_object_active_context(C);
-
- DEG_id_tag_update(&par->id, ID_RECALC_TRANSFORM);
-
- /* context iterator */
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (ob != par) {
- if (BKE_object_parent_loop_check(par, ob)) {
- BKE_report(op->reports, RPT_ERROR, "Loop in parents");
- }
- else {
- /* clear inverse matrix and also the object location */
- unit_m4(ob->parentinv);
- memset(ob->loc, 0, 3 * sizeof(float));
-
- /* set recalc flags */
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
-
- /* set parenting type for object - object only... */
- ob->parent = par;
- ob->partype = PAROBJECT; /* note, dna define, not operator property */
- }
- }
- }
- CTX_DATA_END;
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Object *par = ED_object_active_context(C);
+
+ DEG_id_tag_update(&par->id, ID_RECALC_TRANSFORM);
+
+ /* context iterator */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (ob != par) {
+ if (BKE_object_parent_loop_check(par, ob)) {
+ BKE_report(op->reports, RPT_ERROR, "Loop in parents");
+ }
+ else {
+ /* clear inverse matrix and also the object location */
+ unit_m4(ob->parentinv);
+ memset(ob->loc, 0, 3 * sizeof(float));
+
+ /* set recalc flags */
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ /* set parenting type for object - object only... */
+ ob->parent = par;
+ ob->partype = PAROBJECT; /* note, dna define, not operator property */
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_parent_no_inverse_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Parent without Inverse";
- ot->description = "Set the object's parenting without setting the inverse parent correction";
- ot->idname = "OBJECT_OT_parent_no_inverse_set";
-
- /* api callbacks */
- ot->invoke = WM_operator_confirm;
- ot->exec = parent_noinv_set_exec;
- ot->poll = ED_operator_object_active_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Make Parent without Inverse";
+ ot->description = "Set the object's parenting without setting the inverse parent correction";
+ ot->idname = "OBJECT_OT_parent_no_inverse_set";
+
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = parent_noinv_set_exec;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Clear Track Operator ******************* */
enum {
- CLEAR_TRACK = 1,
- CLEAR_TRACK_KEEP_TRANSFORM = 2,
+ CLEAR_TRACK = 1,
+ CLEAR_TRACK_KEEP_TRANSFORM = 2,
};
static const EnumPropertyItem prop_clear_track_types[] = {
- {CLEAR_TRACK, "CLEAR", 0, "Clear Track", ""},
- {CLEAR_TRACK_KEEP_TRANSFORM, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation (Clear Track)", ""},
- {0, NULL, 0, NULL, NULL},
+ {CLEAR_TRACK, "CLEAR", 0, "Clear Track", ""},
+ {CLEAR_TRACK_KEEP_TRANSFORM,
+ "CLEAR_KEEP_TRANSFORM",
+ 0,
+ "Clear and Keep Transformation (Clear Track)",
+ ""},
+ {0, NULL, 0, NULL, NULL},
};
/* note, poll should check for editable scene */
static int object_track_clear_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- const int type = RNA_enum_get(op->ptr, "type");
-
- if (CTX_data_edit_object(C)) {
- BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in edit mode");
- return OPERATOR_CANCELLED;
- }
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- bConstraint *con, *pcon;
-
- /* remove track-object for old track */
- ob->track = NULL;
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
-
- /* also remove all tracking constraints */
- for (con = ob->constraints.last; con; con = pcon) {
- pcon = con->prev;
- if (ELEM(con->type, CONSTRAINT_TYPE_TRACKTO, CONSTRAINT_TYPE_LOCKTRACK, CONSTRAINT_TYPE_DAMPTRACK))
- BKE_constraint_remove(&ob->constraints, con);
- }
-
- if (type == CLEAR_TRACK_KEEP_TRANSFORM)
- BKE_object_apply_mat4(ob, ob->obmat, true, true);
- }
- CTX_DATA_END;
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ const int type = RNA_enum_get(op->ptr, "type");
+
+ if (CTX_data_edit_object(C)) {
+ BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in edit mode");
+ return OPERATOR_CANCELLED;
+ }
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ bConstraint *con, *pcon;
+
+ /* remove track-object for old track */
+ ob->track = NULL;
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+
+ /* also remove all tracking constraints */
+ for (con = ob->constraints.last; con; con = pcon) {
+ pcon = con->prev;
+ if (ELEM(con->type,
+ CONSTRAINT_TYPE_TRACKTO,
+ CONSTRAINT_TYPE_LOCKTRACK,
+ CONSTRAINT_TYPE_DAMPTRACK))
+ BKE_constraint_remove(&ob->constraints, con);
+ }
+
+ if (type == CLEAR_TRACK_KEEP_TRANSFORM)
+ BKE_object_apply_mat4(ob, ob->obmat, true, true);
+ }
+ CTX_DATA_END;
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_track_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Track";
- ot->description = "Clear tracking constraint or flag from object";
- ot->idname = "OBJECT_OT_track_clear";
+ /* identifiers */
+ ot->name = "Clear Track";
+ ot->description = "Clear tracking constraint or flag from object";
+ ot->idname = "OBJECT_OT_track_clear";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_track_clear_exec;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_track_clear_exec;
- ot->poll = ED_operator_objectmode;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_track_types, 0, "Type", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_track_types, 0, "Type", "");
}
/************************** Make Track Operator *****************************/
enum {
- CREATE_TRACK_DAMPTRACK = 1,
- CREATE_TRACK_TRACKTO = 2,
- CREATE_TRACK_LOCKTRACK = 3,
+ CREATE_TRACK_DAMPTRACK = 1,
+ CREATE_TRACK_TRACKTO = 2,
+ CREATE_TRACK_LOCKTRACK = 3,
};
static const EnumPropertyItem prop_make_track_types[] = {
- {CREATE_TRACK_DAMPTRACK, "DAMPTRACK", 0, "Damped Track Constraint", ""},
- {CREATE_TRACK_TRACKTO, "TRACKTO", 0, "Track To Constraint", ""},
- {CREATE_TRACK_LOCKTRACK, "LOCKTRACK", 0, "Lock Track Constraint", ""},
- {0, NULL, 0, NULL, NULL},
+ {CREATE_TRACK_DAMPTRACK, "DAMPTRACK", 0, "Damped Track Constraint", ""},
+ {CREATE_TRACK_TRACKTO, "TRACKTO", 0, "Track To Constraint", ""},
+ {CREATE_TRACK_LOCKTRACK, "LOCKTRACK", 0, "Lock Track Constraint", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int track_set_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *obact = ED_object_active_context(C);
-
- const int type = RNA_enum_get(op->ptr, "type");
-
- switch (type) {
- case CREATE_TRACK_DAMPTRACK:
- {
- bConstraint *con;
- bDampTrackConstraint *data;
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (ob != obact) {
- con = BKE_constraint_add_for_object(ob, "AutoTrack", CONSTRAINT_TYPE_DAMPTRACK);
-
- data = con->data;
- data->tar = obact;
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
-
- /* Light, Camera and Speaker track differently by default */
- if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
- data->trackflag = TRACK_nZ;
- }
- }
- }
- CTX_DATA_END;
- break;
- }
- case CREATE_TRACK_TRACKTO:
- {
- bConstraint *con;
- bTrackToConstraint *data;
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (ob != obact) {
- con = BKE_constraint_add_for_object(ob, "AutoTrack", CONSTRAINT_TYPE_TRACKTO);
-
- data = con->data;
- data->tar = obact;
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
-
- /* Light, Camera and Speaker track differently by default */
- if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
- data->reserved1 = TRACK_nZ;
- data->reserved2 = UP_Y;
- }
- }
- }
- CTX_DATA_END;
- break;
- }
- case CREATE_TRACK_LOCKTRACK:
- {
- bConstraint *con;
- bLockTrackConstraint *data;
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (ob != obact) {
- con = BKE_constraint_add_for_object(ob, "AutoTrack", CONSTRAINT_TYPE_LOCKTRACK);
-
- data = con->data;
- data->tar = obact;
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
-
- /* Light, Camera and Speaker track differently by default */
- if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
- data->trackflag = TRACK_nZ;
- data->lockflag = LOCK_Y;
- }
- }
- }
- CTX_DATA_END;
- break;
- }
- }
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Object *obact = ED_object_active_context(C);
+
+ const int type = RNA_enum_get(op->ptr, "type");
+
+ switch (type) {
+ case CREATE_TRACK_DAMPTRACK: {
+ bConstraint *con;
+ bDampTrackConstraint *data;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (ob != obact) {
+ con = BKE_constraint_add_for_object(ob, "AutoTrack", CONSTRAINT_TYPE_DAMPTRACK);
+
+ data = con->data;
+ data->tar = obact;
+ DEG_id_tag_update(&ob->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+
+ /* Light, Camera and Speaker track differently by default */
+ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ data->trackflag = TRACK_nZ;
+ }
+ }
+ }
+ CTX_DATA_END;
+ break;
+ }
+ case CREATE_TRACK_TRACKTO: {
+ bConstraint *con;
+ bTrackToConstraint *data;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (ob != obact) {
+ con = BKE_constraint_add_for_object(ob, "AutoTrack", CONSTRAINT_TYPE_TRACKTO);
+
+ data = con->data;
+ data->tar = obact;
+ DEG_id_tag_update(&ob->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+
+ /* Light, Camera and Speaker track differently by default */
+ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ data->reserved1 = TRACK_nZ;
+ data->reserved2 = UP_Y;
+ }
+ }
+ }
+ CTX_DATA_END;
+ break;
+ }
+ case CREATE_TRACK_LOCKTRACK: {
+ bConstraint *con;
+ bLockTrackConstraint *data;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (ob != obact) {
+ con = BKE_constraint_add_for_object(ob, "AutoTrack", CONSTRAINT_TYPE_LOCKTRACK);
+
+ data = con->data;
+ data->tar = obact;
+ DEG_id_tag_update(&ob->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+
+ /* Light, Camera and Speaker track differently by default */
+ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ data->trackflag = TRACK_nZ;
+ data->lockflag = LOCK_Y;
+ }
+ }
+ }
+ CTX_DATA_END;
+ break;
+ }
+ }
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_track_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Track";
- ot->description = "Make the object track another object, using various methods/constraints";
- ot->idname = "OBJECT_OT_track_set";
+ /* identifiers */
+ ot->name = "Make Track";
+ ot->description = "Make the object track another object, using various methods/constraints";
+ ot->idname = "OBJECT_OT_track_set";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = track_set_exec;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = track_set_exec;
- ot->poll = ED_operator_objectmode;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", "");
}
/************************** Link to Scene Operator *****************************/
@@ -1286,1296 +1339,1315 @@ void OBJECT_OT_track_set(wmOperatorType *ot)
#if 0
static void link_to_scene(Main *UNUSED(bmain), unsigned short UNUSED(nr))
{
- Scene *sce = (Scene *) BLI_findlink(&bmain->scene, G.curscreen->scenenr - 1);
- Base *base, *nbase;
-
- if (sce == NULL) return;
- if (sce->id.lib) return;
-
- for (base = FIRSTBASE; base; base = base->next) {
- if (BASE_SELECTED(v3d, base)) {
- nbase = MEM_mallocN(sizeof(Base), "newbase");
- *nbase = *base;
- BLI_addhead(&(sce->base), nbase);
- id_us_plus((ID *)base->object);
- }
- }
+ Scene *sce = (Scene *) BLI_findlink(&bmain->scene, G.curscreen->scenenr - 1);
+ Base *base, *nbase;
+
+ if (sce == NULL) return;
+ if (sce->id.lib) return;
+
+ for (base = FIRSTBASE; base; base = base->next) {
+ if (BASE_SELECTED(v3d, base)) {
+ nbase = MEM_mallocN(sizeof(Base), "newbase");
+ *nbase = *base;
+ BLI_addhead(&(sce->base), nbase);
+ id_us_plus((ID *)base->object);
+ }
+ }
}
#endif
static int make_links_scene_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene_to = BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene"));
-
- if (scene_to == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Could not find scene");
- return OPERATOR_CANCELLED;
- }
-
- if (scene_to == CTX_data_scene(C)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot link objects into the same scene");
- return OPERATOR_CANCELLED;
- }
-
- if (ID_IS_LINKED(scene_to)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot link objects into a linked scene");
- return OPERATOR_CANCELLED;
- }
-
- Collection *collection_to = BKE_collection_master(scene_to);
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
- {
- BKE_collection_object_add(bmain, collection_to, base->object);
- }
- CTX_DATA_END;
-
- DEG_relations_tag_update(bmain);
-
- /* redraw the 3D view because the object center points are colored differently */
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
-
- /* one day multiple scenes will be visible, then we should have some update function for them */
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene_to = BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene"));
+
+ if (scene_to == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Could not find scene");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (scene_to == CTX_data_scene(C)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot link objects into the same scene");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (ID_IS_LINKED(scene_to)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot link objects into a linked scene");
+ return OPERATOR_CANCELLED;
+ }
+
+ Collection *collection_to = BKE_collection_master(scene_to);
+ CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
+ BKE_collection_object_add(bmain, collection_to, base->object);
+ }
+ CTX_DATA_END;
+
+ DEG_relations_tag_update(bmain);
+
+ /* redraw the 3D view because the object center points are colored differently */
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+
+ /* one day multiple scenes will be visible, then we should have some update function for them */
+ return OPERATOR_FINISHED;
}
enum {
- MAKE_LINKS_OBDATA = 1,
- MAKE_LINKS_MATERIALS = 2,
- MAKE_LINKS_ANIMDATA = 3,
- MAKE_LINKS_GROUP = 4,
- MAKE_LINKS_DUPLICOLLECTION = 5,
- MAKE_LINKS_MODIFIERS = 6,
- MAKE_LINKS_FONTS = 7,
+ MAKE_LINKS_OBDATA = 1,
+ MAKE_LINKS_MATERIALS = 2,
+ MAKE_LINKS_ANIMDATA = 3,
+ MAKE_LINKS_GROUP = 4,
+ MAKE_LINKS_DUPLICOLLECTION = 5,
+ MAKE_LINKS_MODIFIERS = 6,
+ MAKE_LINKS_FONTS = 7,
};
/* Return true if make link data is allowed, false otherwise */
static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst)
{
- switch (type) {
- case MAKE_LINKS_OBDATA:
- if (ob_src->type == ob_dst->type && ob_src->type != OB_EMPTY) {
- return true;
- }
- break;
- case MAKE_LINKS_MATERIALS:
- if (OB_TYPE_SUPPORT_MATERIAL(ob_src->type) && OB_TYPE_SUPPORT_MATERIAL(ob_dst->type)) {
- return true;
- }
- break;
- case MAKE_LINKS_DUPLICOLLECTION:
- if (ob_dst->type == OB_EMPTY) {
- return true;
- }
- break;
- case MAKE_LINKS_ANIMDATA:
- case MAKE_LINKS_GROUP:
- return true;
- case MAKE_LINKS_MODIFIERS:
- if (!ELEM(OB_EMPTY, ob_src->type, ob_dst->type)) {
- return true;
- }
- break;
- case MAKE_LINKS_FONTS:
- if ((ob_src->data != ob_dst->data) && (ob_src->type == OB_FONT) && (ob_dst->type == OB_FONT)) {
- return true;
- }
- break;
- }
- return false;
+ switch (type) {
+ case MAKE_LINKS_OBDATA:
+ if (ob_src->type == ob_dst->type && ob_src->type != OB_EMPTY) {
+ return true;
+ }
+ break;
+ case MAKE_LINKS_MATERIALS:
+ if (OB_TYPE_SUPPORT_MATERIAL(ob_src->type) && OB_TYPE_SUPPORT_MATERIAL(ob_dst->type)) {
+ return true;
+ }
+ break;
+ case MAKE_LINKS_DUPLICOLLECTION:
+ if (ob_dst->type == OB_EMPTY) {
+ return true;
+ }
+ break;
+ case MAKE_LINKS_ANIMDATA:
+ case MAKE_LINKS_GROUP:
+ return true;
+ case MAKE_LINKS_MODIFIERS:
+ if (!ELEM(OB_EMPTY, ob_src->type, ob_dst->type)) {
+ return true;
+ }
+ break;
+ case MAKE_LINKS_FONTS:
+ if ((ob_src->data != ob_dst->data) && (ob_src->type == OB_FONT) &&
+ (ob_dst->type == OB_FONT)) {
+ return true;
+ }
+ break;
+ }
+ return false;
}
static int make_links_data_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Main *bmain = CTX_data_main(C);
- const int type = RNA_enum_get(op->ptr, "type");
- Object *ob_src;
- ID *obdata_id;
- int a;
-
- /* collection */
- LinkNode *ob_collections = NULL;
- bool is_cycle = false;
- bool is_lib = false;
-
- ob_src = ED_object_active_context(C);
-
- /* avoid searching all collections in source object each time */
- if (type == MAKE_LINKS_GROUP) {
- ob_collections = BKE_object_groups(bmain, scene, ob_src);
- }
-
- CTX_DATA_BEGIN (C, Base *, base_dst, selected_editable_bases)
- {
- Object *ob_dst = base_dst->object;
-
- if (ob_src != ob_dst) {
- if (allow_make_links_data(type, ob_src, ob_dst)) {
- obdata_id = ob_dst->data;
-
- switch (type) {
- case MAKE_LINKS_OBDATA: /* obdata */
- id_us_min(obdata_id);
-
- obdata_id = ob_src->data;
- id_us_plus(obdata_id);
- ob_dst->data = obdata_id;
-
- /* if amount of material indices changed: */
- test_object_materials(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);
- /* also works with `ma == NULL` */
- assign_material(bmain, ob_dst, ma, a + 1, BKE_MAT_ASSIGN_USERPREF);
- }
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
- break;
- case MAKE_LINKS_ANIMDATA:
- BKE_animdata_copy_id(bmain, (ID *)ob_dst, (ID *)ob_src, 0);
- if (ob_dst->data && ob_src->data) {
- if (ID_IS_LINKED(obdata_id)) {
- is_lib = true;
- break;
- }
- BKE_animdata_copy_id(bmain, (ID *)ob_dst->data, (ID *)ob_src->data, 0);
- }
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- break;
- case MAKE_LINKS_GROUP:
- {
- LinkNode *collection_node;
-
- /* first clear collections */
- BKE_object_groups_clear(bmain, scene, ob_dst);
-
- /* now add in the collections from the link nodes */
- for (collection_node = ob_collections; collection_node; collection_node = collection_node->next) {
- if (ob_dst->instance_collection != collection_node->link) {
- BKE_collection_object_add(bmain, collection_node->link, ob_dst);
- }
- else {
- is_cycle = true;
- }
- }
- break;
- }
- case MAKE_LINKS_DUPLICOLLECTION:
- ob_dst->instance_collection = ob_src->instance_collection;
- if (ob_dst->instance_collection) {
- id_us_plus(&ob_dst->instance_collection->id);
- ob_dst->transflag |= OB_DUPLICOLLECTION;
- }
- break;
- case MAKE_LINKS_MODIFIERS:
- BKE_object_link_modifiers(scene, ob_dst, ob_src);
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- break;
- case MAKE_LINKS_FONTS:
- {
- Curve *cu_src = ob_src->data;
- Curve *cu_dst = ob_dst->data;
-
- if (ID_IS_LINKED(obdata_id)) {
- is_lib = true;
- break;
- }
-
- if (cu_dst->vfont)
- id_us_min(&cu_dst->vfont->id);
- cu_dst->vfont = cu_src->vfont;
- id_us_plus((ID *)cu_dst->vfont);
- if (cu_dst->vfontb)
- id_us_min(&cu_dst->vfontb->id);
- cu_dst->vfontb = cu_src->vfontb;
- id_us_plus((ID *)cu_dst->vfontb);
- if (cu_dst->vfonti)
- id_us_min(&cu_dst->vfonti->id);
- cu_dst->vfonti = cu_src->vfonti;
- id_us_plus((ID *)cu_dst->vfonti);
- if (cu_dst->vfontbi)
- id_us_min(&cu_dst->vfontbi->id);
- cu_dst->vfontbi = cu_src->vfontbi;
- id_us_plus((ID *)cu_dst->vfontbi);
-
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- break;
- }
- }
- }
- }
- }
- CTX_DATA_END;
-
- if (type == MAKE_LINKS_GROUP) {
- if (ob_collections) {
- BLI_linklist_free(ob_collections, NULL);
- }
-
- if (is_cycle) {
- BKE_report(op->reports, RPT_WARNING, "Skipped some collections because of cycle detected");
- }
- }
-
- if (is_lib) {
- BKE_report(op->reports, RPT_WARNING, "Skipped editing library object data");
- }
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, CTX_wm_view3d(C));
- WM_event_add_notifier(C, NC_OBJECT, NULL);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Main *bmain = CTX_data_main(C);
+ const int type = RNA_enum_get(op->ptr, "type");
+ Object *ob_src;
+ ID *obdata_id;
+ int a;
+
+ /* collection */
+ LinkNode *ob_collections = NULL;
+ bool is_cycle = false;
+ bool is_lib = false;
+
+ ob_src = ED_object_active_context(C);
+
+ /* avoid searching all collections in source object each time */
+ if (type == MAKE_LINKS_GROUP) {
+ ob_collections = BKE_object_groups(bmain, scene, ob_src);
+ }
+
+ CTX_DATA_BEGIN (C, Base *, base_dst, selected_editable_bases) {
+ Object *ob_dst = base_dst->object;
+
+ if (ob_src != ob_dst) {
+ if (allow_make_links_data(type, ob_src, ob_dst)) {
+ obdata_id = ob_dst->data;
+
+ switch (type) {
+ case MAKE_LINKS_OBDATA: /* obdata */
+ id_us_min(obdata_id);
+
+ obdata_id = ob_src->data;
+ id_us_plus(obdata_id);
+ ob_dst->data = obdata_id;
+
+ /* if amount of material indices changed: */
+ test_object_materials(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);
+ /* also works with `ma == NULL` */
+ assign_material(bmain, ob_dst, ma, a + 1, BKE_MAT_ASSIGN_USERPREF);
+ }
+ DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
+ break;
+ case MAKE_LINKS_ANIMDATA:
+ BKE_animdata_copy_id(bmain, (ID *)ob_dst, (ID *)ob_src, 0);
+ if (ob_dst->data && ob_src->data) {
+ if (ID_IS_LINKED(obdata_id)) {
+ is_lib = true;
+ break;
+ }
+ BKE_animdata_copy_id(bmain, (ID *)ob_dst->data, (ID *)ob_src->data, 0);
+ }
+ DEG_id_tag_update(&ob_dst->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ break;
+ case MAKE_LINKS_GROUP: {
+ LinkNode *collection_node;
+
+ /* first clear collections */
+ BKE_object_groups_clear(bmain, scene, ob_dst);
+
+ /* now add in the collections from the link nodes */
+ for (collection_node = ob_collections; collection_node;
+ collection_node = collection_node->next) {
+ if (ob_dst->instance_collection != collection_node->link) {
+ BKE_collection_object_add(bmain, collection_node->link, ob_dst);
+ }
+ else {
+ is_cycle = true;
+ }
+ }
+ break;
+ }
+ case MAKE_LINKS_DUPLICOLLECTION:
+ ob_dst->instance_collection = ob_src->instance_collection;
+ if (ob_dst->instance_collection) {
+ id_us_plus(&ob_dst->instance_collection->id);
+ ob_dst->transflag |= OB_DUPLICOLLECTION;
+ }
+ break;
+ case MAKE_LINKS_MODIFIERS:
+ BKE_object_link_modifiers(scene, ob_dst, ob_src);
+ DEG_id_tag_update(&ob_dst->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ break;
+ case MAKE_LINKS_FONTS: {
+ Curve *cu_src = ob_src->data;
+ Curve *cu_dst = ob_dst->data;
+
+ if (ID_IS_LINKED(obdata_id)) {
+ is_lib = true;
+ break;
+ }
+
+ if (cu_dst->vfont)
+ id_us_min(&cu_dst->vfont->id);
+ cu_dst->vfont = cu_src->vfont;
+ id_us_plus((ID *)cu_dst->vfont);
+ if (cu_dst->vfontb)
+ id_us_min(&cu_dst->vfontb->id);
+ cu_dst->vfontb = cu_src->vfontb;
+ id_us_plus((ID *)cu_dst->vfontb);
+ if (cu_dst->vfonti)
+ id_us_min(&cu_dst->vfonti->id);
+ cu_dst->vfonti = cu_src->vfonti;
+ id_us_plus((ID *)cu_dst->vfonti);
+ if (cu_dst->vfontbi)
+ id_us_min(&cu_dst->vfontbi->id);
+ cu_dst->vfontbi = cu_src->vfontbi;
+ id_us_plus((ID *)cu_dst->vfontbi);
+
+ DEG_id_tag_update(&ob_dst->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ break;
+ }
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ if (type == MAKE_LINKS_GROUP) {
+ if (ob_collections) {
+ BLI_linklist_free(ob_collections, NULL);
+ }
+
+ if (is_cycle) {
+ BKE_report(op->reports, RPT_WARNING, "Skipped some collections because of cycle detected");
+ }
+ }
+
+ if (is_lib) {
+ BKE_report(op->reports, RPT_WARNING, "Skipped editing library object data");
+ }
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, CTX_wm_view3d(C));
+ WM_event_add_notifier(C, NC_OBJECT, NULL);
+
+ return OPERATOR_FINISHED;
}
-
void OBJECT_OT_make_links_scene(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Link Objects to Scene";
- ot->description = "Link selection to another scene";
- ot->idname = "OBJECT_OT_make_links_scene";
-
- /* api callbacks */
- ot->invoke = WM_enum_search_invoke;
- ot->exec = make_links_scene_exec;
- /* better not run the poll check */
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "scene", DummyRNA_NULL_items, 0, "Scene", "");
- RNA_def_enum_funcs(prop, RNA_scene_local_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Link Objects to Scene";
+ ot->description = "Link selection to another scene";
+ ot->idname = "OBJECT_OT_make_links_scene";
+
+ /* api callbacks */
+ ot->invoke = WM_enum_search_invoke;
+ ot->exec = make_links_scene_exec;
+ /* better not run the poll check */
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna, "scene", DummyRNA_NULL_items, 0, "Scene", "");
+ RNA_def_enum_funcs(prop, RNA_scene_local_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
void OBJECT_OT_make_links_data(wmOperatorType *ot)
{
- static const EnumPropertyItem make_links_items[] = {
- {MAKE_LINKS_OBDATA, "OBDATA", 0, "Object Data", ""},
- {MAKE_LINKS_MATERIALS, "MATERIAL", 0, "Materials", ""},
- {MAKE_LINKS_ANIMDATA, "ANIMATION", 0, "Animation Data", ""},
- {MAKE_LINKS_GROUP, "GROUPS", 0, "Collection", ""},
- {MAKE_LINKS_DUPLICOLLECTION, "DUPLICOLLECTION", 0, "Instance Collection", ""},
- {MAKE_LINKS_MODIFIERS, "MODIFIERS", 0, "Modifiers", ""},
- {MAKE_LINKS_FONTS, "FONTS", 0, "Fonts", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Link Data";
- ot->description = "Apply active object links to other selected objects";
- ot->idname = "OBJECT_OT_make_links_data";
-
- /* api callbacks */
- ot->exec = make_links_data_exec;
- ot->poll = ED_operator_object_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", make_links_items, 0, "Type", "");
+ static const EnumPropertyItem make_links_items[] = {
+ {MAKE_LINKS_OBDATA, "OBDATA", 0, "Object Data", ""},
+ {MAKE_LINKS_MATERIALS, "MATERIAL", 0, "Materials", ""},
+ {MAKE_LINKS_ANIMDATA, "ANIMATION", 0, "Animation Data", ""},
+ {MAKE_LINKS_GROUP, "GROUPS", 0, "Collection", ""},
+ {MAKE_LINKS_DUPLICOLLECTION, "DUPLICOLLECTION", 0, "Instance Collection", ""},
+ {MAKE_LINKS_MODIFIERS, "MODIFIERS", 0, "Modifiers", ""},
+ {MAKE_LINKS_FONTS, "FONTS", 0, "Fonts", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Link Data";
+ ot->description = "Apply active object links to other selected objects";
+ ot->idname = "OBJECT_OT_make_links_data";
+
+ /* api callbacks */
+ ot->exec = make_links_data_exec;
+ ot->poll = ED_operator_object_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", make_links_items, 0, "Type", "");
}
-
/**************************** Make Single User ********************************/
static void libblock_relink_collection(Collection *collection)
{
- BKE_libblock_relink_to_newid(&collection->id);
+ BKE_libblock_relink_to_newid(&collection->id);
- for (CollectionObject *cob = collection->gobject.first; cob != NULL; cob = cob->next) {
- BKE_libblock_relink_to_newid(&cob->ob->id);
- }
+ for (CollectionObject *cob = collection->gobject.first; cob != NULL; cob = cob->next) {
+ BKE_libblock_relink_to_newid(&cob->ob->id);
+ }
- for (CollectionChild *child = collection->children.first; child; child = child->next) {
- libblock_relink_collection(child->collection);
- }
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ libblock_relink_collection(child->collection);
+ }
}
-static Collection *single_object_users_collection(
- Main *bmain, Scene *scene, Collection *collection,
- const int flag, const bool copy_collections, const bool is_master_collection)
+static Collection *single_object_users_collection(Main *bmain,
+ Scene *scene,
+ Collection *collection,
+ const int flag,
+ const bool copy_collections,
+ const bool is_master_collection)
{
- /* Generate new copies for objects in given collection and all its children,
- * and optionnaly also copy collections themselves. */
- if (copy_collections && !is_master_collection) {
- collection = ID_NEW_SET(collection, BKE_collection_copy(bmain, NULL, collection));
- }
-
- /* We do not remap to new objects here, this is done in separate step. */
- for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
- Object *ob = cob->ob;
- /* an object may be in more than one collection */
- if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) {
- if (!ID_IS_LINKED(ob) && BKE_object_scenes_users_get(bmain, ob) > 1) {
- ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
- }
- }
- }
-
- /* Since master collection has already be duplicated as part of scene copy, we do not duplictae it here.
- * However, this means its children need to be re-added manually here, otherwise their parent lists are empty
- * (which will lead to crashes, see T63101). */
- CollectionChild *child_next, *child = collection->children.first;
- CollectionChild *orig_child_last = collection->children.last;
- for (; child != NULL; child = child_next) {
- child_next = child->next;
- Collection *collection_child_new = single_object_users_collection(
- bmain, scene, child->collection, flag, copy_collections, false);
- if (is_master_collection && copy_collections && child->collection != collection_child_new) {
- BKE_collection_child_add(bmain, collection, collection_child_new);
- BLI_remlink(&collection->children, child);
- MEM_freeN(child);
- if (child == orig_child_last) {
- break;
- }
- }
- }
-
- return collection;
+ /* Generate new copies for objects in given collection and all its children,
+ * and optionnaly also copy collections themselves. */
+ if (copy_collections && !is_master_collection) {
+ collection = ID_NEW_SET(collection, BKE_collection_copy(bmain, NULL, collection));
+ }
+
+ /* We do not remap to new objects here, this is done in separate step. */
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ Object *ob = cob->ob;
+ /* an object may be in more than one collection */
+ if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) {
+ if (!ID_IS_LINKED(ob) && BKE_object_scenes_users_get(bmain, ob) > 1) {
+ ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
+ }
+ }
+ }
+
+ /* Since master collection has already be duplicated as part of scene copy, we do not duplictae it here.
+ * However, this means its children need to be re-added manually here, otherwise their parent lists are empty
+ * (which will lead to crashes, see T63101). */
+ CollectionChild *child_next, *child = collection->children.first;
+ CollectionChild *orig_child_last = collection->children.last;
+ for (; child != NULL; child = child_next) {
+ child_next = child->next;
+ Collection *collection_child_new = single_object_users_collection(
+ bmain, scene, child->collection, flag, copy_collections, false);
+ if (is_master_collection && copy_collections && child->collection != collection_child_new) {
+ BKE_collection_child_add(bmain, collection, collection_child_new);
+ BLI_remlink(&collection->children, child);
+ MEM_freeN(child);
+ if (child == orig_child_last) {
+ break;
+ }
+ }
+ }
+
+ return collection;
}
/* Warning, sets ID->newid pointers of objects and collections, but does not clear them. */
-static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_collections)
+static void single_object_users(
+ Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_collections)
{
- /* duplicate all the objects of the scene (and matching collections, if required). */
- Collection *master_collection = BKE_collection_master(scene);
- single_object_users_collection(bmain, scene, master_collection, flag, copy_collections, true);
-
- /* duplicate collections that consist entirely of duplicated objects */
- /* XXX I guess that was designed for calls from 'make single user' operator... But since copy_collection is
- * always false then, was not doing anything. And that kind of behavior should be added at operator level,
- * not in a utility function also used by rather different code... */
+ /* duplicate all the objects of the scene (and matching collections, if required). */
+ Collection *master_collection = BKE_collection_master(scene);
+ single_object_users_collection(bmain, scene, master_collection, flag, copy_collections, true);
+
+ /* duplicate collections that consist entirely of duplicated objects */
+ /* XXX I guess that was designed for calls from 'make single user' operator... But since copy_collection is
+ * always false then, was not doing anything. And that kind of behavior should be added at operator level,
+ * not in a utility function also used by rather different code... */
#if 0
- if (copy_collections) {
- Collection *collection, *collectionn;
- for (collection = bmain->collections.first; collection; collection = collection->id.next) {
- bool all_duplicated = true;
- bool any_duplicated = false;
-
- for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
- any_duplicated = true;
- if (cob->ob->id.newid == NULL) {
- all_duplicated = false;
- break;
- }
- }
-
- if (any_duplicated && all_duplicated) {
- // TODO: test if this works, with child collections ..
- collectionn = ID_NEW_SET(collection, BKE_collection_copy(bmain, NULL, collection));
-
- for (CollectionObject *cob = collectionn->gobject.first; cob; cob = cob->next) {
- cob->ob = (Object *)cob->ob->id.newid;
- }
- }
- }
- }
+ if (copy_collections) {
+ Collection *collection, *collectionn;
+ for (collection = bmain->collections.first; collection; collection = collection->id.next) {
+ bool all_duplicated = true;
+ bool any_duplicated = false;
+
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ any_duplicated = true;
+ if (cob->ob->id.newid == NULL) {
+ all_duplicated = false;
+ break;
+ }
+ }
+
+ if (any_duplicated && all_duplicated) {
+ // TODO: test if this works, with child collections ..
+ collectionn = ID_NEW_SET(collection, BKE_collection_copy(bmain, NULL, collection));
+
+ for (CollectionObject *cob = collectionn->gobject.first; cob; cob = cob->next) {
+ cob->ob = (Object *)cob->ob->id.newid;
+ }
+ }
+ }
+ }
#endif
- /* Collection and object pointers in collections */
- libblock_relink_collection(master_collection);
+ /* Collection and object pointers in collections */
+ libblock_relink_collection(master_collection);
- /* collection pointers in scene */
- BKE_scene_groups_relink(scene);
+ /* collection pointers in scene */
+ BKE_scene_groups_relink(scene);
- /* active camera */
- ID_NEW_REMAP(scene->camera);
- if (v3d) {
- ID_NEW_REMAP(v3d->camera);
- }
+ /* active camera */
+ ID_NEW_REMAP(scene->camera);
+ if (v3d) {
+ ID_NEW_REMAP(v3d->camera);
+ }
- /* Making single user may affect other scenes if they share with current one some collections in their ViewLayer. */
- BKE_main_collection_sync(bmain);
+ /* Making single user may affect other scenes if they share with current one some collections in their ViewLayer. */
+ BKE_main_collection_sync(bmain);
}
/* not an especially efficient function, only added so the single user
* button can be functional.*/
void ED_object_single_user(Main *bmain, Scene *scene, Object *ob)
{
- FOREACH_SCENE_OBJECT_BEGIN(scene, ob_iter)
- {
- ob_iter->flag &= ~OB_DONE;
- }
- FOREACH_SCENE_OBJECT_END;
+ FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) {
+ ob_iter->flag &= ~OB_DONE;
+ }
+ FOREACH_SCENE_OBJECT_END;
- /* tag only the one object */
- ob->flag |= OB_DONE;
+ /* tag only the one object */
+ ob->flag |= OB_DONE;
- single_object_users(bmain, scene, NULL, OB_DONE, false);
- BKE_main_id_clear_newpoins(bmain);
+ single_object_users(bmain, scene, NULL, OB_DONE, false);
+ BKE_main_id_clear_newpoins(bmain);
}
static void new_id_matar(Main *bmain, Material **matar, const int totcol)
{
- ID *id;
- int a;
-
- for (a = 0; a < totcol; a++) {
- id = (ID *)matar[a];
- if (id && !ID_IS_LINKED(id)) {
- if (id->newid) {
- matar[a] = (Material *)id->newid;
- id_us_plus(id->newid);
- id_us_min(id);
- }
- else if (id->us > 1) {
- matar[a] = ID_NEW_SET(id, BKE_material_copy(bmain, matar[a]));
- id_us_min(id);
- }
- }
- }
+ ID *id;
+ int a;
+
+ for (a = 0; a < totcol; a++) {
+ id = (ID *)matar[a];
+ if (id && !ID_IS_LINKED(id)) {
+ if (id->newid) {
+ matar[a] = (Material *)id->newid;
+ id_us_plus(id->newid);
+ id_us_min(id);
+ }
+ else if (id->us > 1) {
+ matar[a] = ID_NEW_SET(id, BKE_material_copy(bmain, matar[a]));
+ id_us_min(id);
+ }
+ }
+ }
}
-static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
+static void single_obdata_users(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
{
- Light *la;
- Curve *cu;
- /* Camera *cam; */
- Mesh *me;
- Lattice *lat;
- ID *id;
-
- FOREACH_OBJECT_FLAG_BEGIN(scene, view_layer, v3d, flag, ob)
- {
- if (!ID_IS_LINKED(ob)) {
- id = ob->data;
-
- if (id && id->us > 1 && !ID_IS_LINKED(id)) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
-
- switch (ob->type) {
- case OB_LAMP:
- ob->data = la = ID_NEW_SET(ob->data, BKE_light_copy(bmain, ob->data));
- break;
- case OB_CAMERA:
- ob->data = ID_NEW_SET(ob->data, BKE_camera_copy(bmain, ob->data));
- break;
- case OB_MESH:
- /* Needed to remap texcomesh below. */
- me = ob->data = ID_NEW_SET(ob->data, BKE_mesh_copy(bmain, ob->data));
- if (me->key) /* We do not need to set me->key->id.newid here... */
- BKE_animdata_copy_id_action(bmain, (ID *)me->key, false);
- break;
- case OB_MBALL:
- ob->data = ID_NEW_SET(ob->data, BKE_mball_copy(bmain, ob->data));
- break;
- case OB_CURVE:
- case OB_SURF:
- case OB_FONT:
- ob->data = cu = ID_NEW_SET(ob->data, BKE_curve_copy(bmain, ob->data));
- ID_NEW_REMAP(cu->bevobj);
- ID_NEW_REMAP(cu->taperobj);
- if (cu->key) /* We do not need to set cu->key->id.newid here... */
- BKE_animdata_copy_id_action(bmain, (ID *)cu->key, false);
- break;
- case OB_LATTICE:
- ob->data = lat = ID_NEW_SET(ob->data, BKE_lattice_copy(bmain, ob->data));
- if (lat->key) /* We do not need to set lat->key->id.newid here... */
- BKE_animdata_copy_id_action(bmain, (ID *)lat->key, false);
- break;
- case OB_ARMATURE:
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- ob->data = ID_NEW_SET(ob->data, BKE_armature_copy(bmain, ob->data));
- BKE_pose_rebuild(bmain, ob, ob->data, true);
- break;
- case OB_SPEAKER:
- ob->data = ID_NEW_SET(ob->data, BKE_speaker_copy(bmain, ob->data));
- break;
- case OB_LIGHTPROBE:
- ob->data = ID_NEW_SET(ob->data, BKE_lightprobe_copy(bmain, ob->data));
- break;
- case OB_GPENCIL:
- ob->data = ID_NEW_SET(ob->data, BKE_gpencil_copy(bmain, ob->data));
- break;
- default:
- printf("ERROR %s: can't copy %s\n", __func__, id->name);
- BLI_assert(!"This should never happen.");
-
- /* We need to end the FOREACH_OBJECT_FLAG_BEGIN iterator to prevent memory leak. */
- BKE_scene_objects_iterator_end(&iter_macro);
- return;
- }
-
- /* Copy animation data after object data became local,
- * otherwise old and new object data will share the same
- * AnimData structure, which is not what we want.
- * (sergey)
- */
- BKE_animdata_copy_id_action(bmain, (ID *)ob->data, false);
-
- id_us_min(id);
- }
- }
- }
- FOREACH_OBJECT_FLAG_END;
-
- me = bmain->meshes.first;
- while (me) {
- ID_NEW_REMAP(me->texcomesh);
- me = me->id.next;
- }
+ Light *la;
+ Curve *cu;
+ /* Camera *cam; */
+ Mesh *me;
+ Lattice *lat;
+ ID *id;
+
+ FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
+ if (!ID_IS_LINKED(ob)) {
+ id = ob->data;
+
+ if (id && id->us > 1 && !ID_IS_LINKED(id)) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+
+ switch (ob->type) {
+ case OB_LAMP:
+ ob->data = la = ID_NEW_SET(ob->data, BKE_light_copy(bmain, ob->data));
+ break;
+ case OB_CAMERA:
+ ob->data = ID_NEW_SET(ob->data, BKE_camera_copy(bmain, ob->data));
+ break;
+ case OB_MESH:
+ /* Needed to remap texcomesh below. */
+ me = ob->data = ID_NEW_SET(ob->data, BKE_mesh_copy(bmain, ob->data));
+ if (me->key) /* We do not need to set me->key->id.newid here... */
+ BKE_animdata_copy_id_action(bmain, (ID *)me->key, false);
+ break;
+ case OB_MBALL:
+ ob->data = ID_NEW_SET(ob->data, BKE_mball_copy(bmain, ob->data));
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ case OB_FONT:
+ ob->data = cu = ID_NEW_SET(ob->data, BKE_curve_copy(bmain, ob->data));
+ ID_NEW_REMAP(cu->bevobj);
+ ID_NEW_REMAP(cu->taperobj);
+ if (cu->key) /* We do not need to set cu->key->id.newid here... */
+ BKE_animdata_copy_id_action(bmain, (ID *)cu->key, false);
+ break;
+ case OB_LATTICE:
+ ob->data = lat = ID_NEW_SET(ob->data, BKE_lattice_copy(bmain, ob->data));
+ if (lat->key) /* We do not need to set lat->key->id.newid here... */
+ BKE_animdata_copy_id_action(bmain, (ID *)lat->key, false);
+ break;
+ case OB_ARMATURE:
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ ob->data = ID_NEW_SET(ob->data, BKE_armature_copy(bmain, ob->data));
+ BKE_pose_rebuild(bmain, ob, ob->data, true);
+ break;
+ case OB_SPEAKER:
+ ob->data = ID_NEW_SET(ob->data, BKE_speaker_copy(bmain, ob->data));
+ break;
+ case OB_LIGHTPROBE:
+ ob->data = ID_NEW_SET(ob->data, BKE_lightprobe_copy(bmain, ob->data));
+ break;
+ case OB_GPENCIL:
+ ob->data = ID_NEW_SET(ob->data, BKE_gpencil_copy(bmain, ob->data));
+ break;
+ default:
+ printf("ERROR %s: can't copy %s\n", __func__, id->name);
+ BLI_assert(!"This should never happen.");
+
+ /* We need to end the FOREACH_OBJECT_FLAG_BEGIN iterator to prevent memory leak. */
+ BKE_scene_objects_iterator_end(&iter_macro);
+ return;
+ }
+
+ /* Copy animation data after object data became local,
+ * otherwise old and new object data will share the same
+ * AnimData structure, which is not what we want.
+ * (sergey)
+ */
+ BKE_animdata_copy_id_action(bmain, (ID *)ob->data, false);
+
+ id_us_min(id);
+ }
+ }
+ }
+ FOREACH_OBJECT_FLAG_END;
+
+ me = bmain->meshes.first;
+ while (me) {
+ ID_NEW_REMAP(me->texcomesh);
+ me = me->id.next;
+ }
}
-static void single_object_action_users(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
+static void single_object_action_users(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
{
- FOREACH_OBJECT_FLAG_BEGIN(scene, view_layer, v3d, flag, ob)
- {
- if (!ID_IS_LINKED(ob)) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- BKE_animdata_copy_id_action(bmain, &ob->id, false);
- }
- }
- FOREACH_OBJECT_FLAG_END;
+ FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
+ if (!ID_IS_LINKED(ob)) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ BKE_animdata_copy_id_action(bmain, &ob->id, false);
+ }
+ }
+ FOREACH_OBJECT_FLAG_END;
}
-static void single_mat_users(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
+static void single_mat_users(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
{
- Material *ma, *man;
- int a;
-
- 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);
- if (ma) {
- /* do not test for LIB_TAG_NEW or use newid:
- * this functions guaranteed delivers single_users! */
-
- if (ma->id.us > 1) {
- man = BKE_material_copy(bmain, ma);
- BKE_animdata_copy_id_action(bmain, &man->id, false);
- if (man->nodetree != NULL) {
- BKE_animdata_copy_id_action(bmain, &man->nodetree->id, false);
- }
-
- man->id.us = 0;
- assign_material(bmain, ob, man, a, BKE_MAT_ASSIGN_USERPREF);
- }
- }
- }
- }
- }
- FOREACH_OBJECT_FLAG_END;
+ Material *ma, *man;
+ int a;
+
+ 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);
+ if (ma) {
+ /* do not test for LIB_TAG_NEW or use newid:
+ * this functions guaranteed delivers single_users! */
+
+ if (ma->id.us > 1) {
+ man = BKE_material_copy(bmain, ma);
+ BKE_animdata_copy_id_action(bmain, &man->id, false);
+ if (man->nodetree != NULL) {
+ BKE_animdata_copy_id_action(bmain, &man->nodetree->id, false);
+ }
+
+ man->id.us = 0;
+ assign_material(bmain, ob, man, a, BKE_MAT_ASSIGN_USERPREF);
+ }
+ }
+ }
+ }
+ }
+ FOREACH_OBJECT_FLAG_END;
}
static void single_mat_users_expand(Main *bmain)
{
- /* only when 'parent' blocks are LIB_TAG_NEW */
- Object *ob;
- Mesh *me;
- Curve *cu;
- MetaBall *mb;
- bGPdata *gpd;
-
- for (ob = bmain->objects.first; ob; ob = ob->id.next)
- if (ob->id.tag & LIB_TAG_NEW)
- new_id_matar(bmain, ob->mat, ob->totcol);
-
- for (me = bmain->meshes.first; me; me = me->id.next)
- if (me->id.tag & LIB_TAG_NEW)
- new_id_matar(bmain, me->mat, me->totcol);
-
- for (cu = bmain->curves.first; cu; cu = cu->id.next)
- if (cu->id.tag & LIB_TAG_NEW)
- new_id_matar(bmain, cu->mat, cu->totcol);
-
- for (mb = bmain->metaballs.first; mb; mb = mb->id.next)
- if (mb->id.tag & LIB_TAG_NEW)
- new_id_matar(bmain, mb->mat, mb->totcol);
-
- for (gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next)
- if (gpd->id.tag & LIB_TAG_NEW)
- new_id_matar(bmain, gpd->mat, gpd->totcol);
+ /* only when 'parent' blocks are LIB_TAG_NEW */
+ Object *ob;
+ Mesh *me;
+ Curve *cu;
+ MetaBall *mb;
+ bGPdata *gpd;
+
+ for (ob = bmain->objects.first; ob; ob = ob->id.next)
+ if (ob->id.tag & LIB_TAG_NEW)
+ new_id_matar(bmain, ob->mat, ob->totcol);
+
+ for (me = bmain->meshes.first; me; me = me->id.next)
+ if (me->id.tag & LIB_TAG_NEW)
+ new_id_matar(bmain, me->mat, me->totcol);
+
+ for (cu = bmain->curves.first; cu; cu = cu->id.next)
+ if (cu->id.tag & LIB_TAG_NEW)
+ new_id_matar(bmain, cu->mat, cu->totcol);
+
+ for (mb = bmain->metaballs.first; mb; mb = mb->id.next)
+ if (mb->id.tag & LIB_TAG_NEW)
+ new_id_matar(bmain, mb->mat, mb->totcol);
+
+ for (gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next)
+ if (gpd->id.tag & LIB_TAG_NEW)
+ new_id_matar(bmain, gpd->mat, gpd->totcol);
}
/* used for copying scenes */
-void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bool copy_collections)
+void ED_object_single_users(Main *bmain,
+ Scene *scene,
+ const bool full,
+ const bool copy_collections)
{
- single_object_users(bmain, scene, NULL, 0, copy_collections);
-
- if (full) {
- single_obdata_users(bmain, scene, NULL, NULL, 0);
- single_object_action_users(bmain, scene, NULL, NULL, 0);
- single_mat_users_expand(bmain);
- }
-
- /* Relink nodetrees' pointers that have been duplicated. */
- FOREACH_NODETREE_BEGIN(bmain, ntree, id)
- {
- /* This is a bit convoluted, we want to root ntree of copied IDs and only those,
- * so we first check that old ID has been copied and that ntree is root tree of old ID,
- * then get root tree of new ID and remap its pointers to new ID... */
- if (id->newid && (&ntree->id != id)) {
- ntree = ntreeFromID(id->newid);
- BKE_libblock_relink_to_newid(&ntree->id);
- }
- } FOREACH_NODETREE_END;
-
- /* Relink datablock pointer properties */
- {
- IDP_RelinkProperty(scene->id.properties);
-
- FOREACH_SCENE_OBJECT_BEGIN(scene, ob)
- {
- if (!ID_IS_LINKED(ob)) {
- IDP_RelinkProperty(ob->id.properties);
- }
- }
- FOREACH_SCENE_OBJECT_END;
-
- if (scene->nodetree) {
- IDP_RelinkProperty(scene->nodetree->id.properties);
- for (bNode *node = scene->nodetree->nodes.first; node; node = node->next) {
- IDP_RelinkProperty(node->prop);
- }
- }
-
- if (scene->world) {
- IDP_RelinkProperty(scene->world->id.properties);
- }
-
- if (scene->clip) {
- IDP_RelinkProperty(scene->clip->id.properties);
- }
- }
- BKE_main_id_clear_newpoins(bmain);
- DEG_relations_tag_update(bmain);
+ single_object_users(bmain, scene, NULL, 0, copy_collections);
+
+ if (full) {
+ single_obdata_users(bmain, scene, NULL, NULL, 0);
+ single_object_action_users(bmain, scene, NULL, NULL, 0);
+ single_mat_users_expand(bmain);
+ }
+
+ /* Relink nodetrees' pointers that have been duplicated. */
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ /* This is a bit convoluted, we want to root ntree of copied IDs and only those,
+ * so we first check that old ID has been copied and that ntree is root tree of old ID,
+ * then get root tree of new ID and remap its pointers to new ID... */
+ if (id->newid && (&ntree->id != id)) {
+ ntree = ntreeFromID(id->newid);
+ BKE_libblock_relink_to_newid(&ntree->id);
+ }
+ }
+ FOREACH_NODETREE_END;
+
+ /* Relink datablock pointer properties */
+ {
+ IDP_RelinkProperty(scene->id.properties);
+
+ FOREACH_SCENE_OBJECT_BEGIN (scene, ob) {
+ if (!ID_IS_LINKED(ob)) {
+ IDP_RelinkProperty(ob->id.properties);
+ }
+ }
+ FOREACH_SCENE_OBJECT_END;
+
+ if (scene->nodetree) {
+ IDP_RelinkProperty(scene->nodetree->id.properties);
+ for (bNode *node = scene->nodetree->nodes.first; node; node = node->next) {
+ IDP_RelinkProperty(node->prop);
+ }
+ }
+
+ if (scene->world) {
+ IDP_RelinkProperty(scene->world->id.properties);
+ }
+
+ if (scene->clip) {
+ IDP_RelinkProperty(scene->clip->id.properties);
+ }
+ }
+ BKE_main_id_clear_newpoins(bmain);
+ DEG_relations_tag_update(bmain);
}
/******************************* Make Local ***********************************/
enum {
- MAKE_LOCAL_SELECT_OB = 1,
- MAKE_LOCAL_SELECT_OBDATA = 2,
- MAKE_LOCAL_SELECT_OBDATA_MATERIAL = 3,
- MAKE_LOCAL_ALL = 4,
+ MAKE_LOCAL_SELECT_OB = 1,
+ MAKE_LOCAL_SELECT_OBDATA = 2,
+ MAKE_LOCAL_SELECT_OBDATA_MATERIAL = 3,
+ 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(void *UNUSED(user_data),
+ ID *UNUSED(self_id),
+ ID **id_pointer,
+ const int UNUSED(cb_flag))
{
- if (*id_pointer) {
- (*id_pointer)->tag &= ~LIB_TAG_DOIT;
- }
+ if (*id_pointer) {
+ (*id_pointer)->tag &= ~LIB_TAG_DOIT;
+ }
- return IDWALK_RET_NOP;
+ return IDWALK_RET_NOP;
}
static void tag_localizable_objects(bContext *C, const int mode)
{
- Main *bmain = CTX_data_main(C);
-
- BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
-
- /* Set LIB_TAG_DOIT flag for all selected objects, so next we can check whether
- * object is gonna to become local or not.
- */
- CTX_DATA_BEGIN (C, Object *, object, selected_objects)
- {
- object->id.tag |= LIB_TAG_DOIT;
-
- /* If data is also gonna to become local, mark data we're interested in
- * as gonna-to-be-local.
- */
- if (mode == MAKE_LOCAL_SELECT_OBDATA && object->data) {
- ID *data_id = (ID *) object->data;
- data_id->tag |= LIB_TAG_DOIT;
- }
- }
- CTX_DATA_END;
-
- /* Also forbid making objects local if other library objects are using
- * them for modifiers or constraints.
- */
- for (Object *object = bmain->objects.first; object; object = object->id.next) {
- if ((object->id.tag & LIB_TAG_DOIT) == 0) {
- BKE_library_foreach_ID_link(NULL, &object->id, tag_localizable_looper, NULL, IDWALK_READONLY);
- }
- if (object->data) {
- ID *data_id = (ID *) object->data;
- if ((data_id->tag & LIB_TAG_DOIT) == 0) {
- BKE_library_foreach_ID_link(NULL, data_id, tag_localizable_looper, NULL, IDWALK_READONLY);
- }
- }
- }
-
- /* TODO(sergey): Drivers targets? */
+ Main *bmain = CTX_data_main(C);
+
+ BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+
+ /* Set LIB_TAG_DOIT flag for all selected objects, so next we can check whether
+ * object is gonna to become local or not.
+ */
+ CTX_DATA_BEGIN (C, Object *, object, selected_objects) {
+ object->id.tag |= LIB_TAG_DOIT;
+
+ /* If data is also gonna to become local, mark data we're interested in
+ * as gonna-to-be-local.
+ */
+ if (mode == MAKE_LOCAL_SELECT_OBDATA && object->data) {
+ ID *data_id = (ID *)object->data;
+ data_id->tag |= LIB_TAG_DOIT;
+ }
+ }
+ CTX_DATA_END;
+
+ /* Also forbid making objects local if other library objects are using
+ * them for modifiers or constraints.
+ */
+ for (Object *object = bmain->objects.first; object; object = object->id.next) {
+ if ((object->id.tag & LIB_TAG_DOIT) == 0) {
+ BKE_library_foreach_ID_link(
+ NULL, &object->id, tag_localizable_looper, NULL, IDWALK_READONLY);
+ }
+ if (object->data) {
+ ID *data_id = (ID *)object->data;
+ if ((data_id->tag & LIB_TAG_DOIT) == 0) {
+ BKE_library_foreach_ID_link(NULL, data_id, tag_localizable_looper, NULL, IDWALK_READONLY);
+ }
+ }
+ }
+
+ /* TODO(sergey): Drivers targets? */
}
/**
* Instance indirectly referenced zero user objects,
* otherwise they're lost on reload, see T40595.
*/
-static bool make_local_all__instance_indirect_unused(Main *bmain, ViewLayer *view_layer, Collection *collection)
+static bool make_local_all__instance_indirect_unused(Main *bmain,
+ ViewLayer *view_layer,
+ Collection *collection)
{
- Object *ob;
- bool changed = false;
+ Object *ob;
+ bool changed = false;
- for (ob = bmain->objects.first; ob; ob = ob->id.next) {
- if (ID_IS_LINKED(ob) && (ob->id.us == 0)) {
- Base *base;
+ for (ob = bmain->objects.first; ob; ob = ob->id.next) {
+ if (ID_IS_LINKED(ob) && (ob->id.us == 0)) {
+ Base *base;
- id_us_plus(&ob->id);
+ id_us_plus(&ob->id);
- BKE_collection_object_add(bmain, collection, ob);
- base = BKE_view_layer_base_find(view_layer, ob);
- base->flag |= BASE_SELECTED;
- BKE_scene_object_base_flag_sync_from_base(base);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ BKE_collection_object_add(bmain, collection, ob);
+ base = BKE_view_layer_base_find(view_layer, ob);
+ base->flag |= BASE_SELECTED;
+ BKE_scene_object_base_flag_sync_from_base(base);
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- changed = true;
- }
- }
+ changed = true;
+ }
+ }
- return changed;
+ return changed;
}
static void make_local_animdata_tag_strips(ListBase *strips)
{
- NlaStrip *strip;
+ NlaStrip *strip;
- for (strip = strips->first; strip; strip = strip->next) {
- if (strip->act) {
- strip->act->id.tag &= ~LIB_TAG_PRE_EXISTING;
- }
+ for (strip = strips->first; strip; strip = strip->next) {
+ if (strip->act) {
+ strip->act->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ }
- make_local_animdata_tag_strips(&strip->strips);
- }
+ make_local_animdata_tag_strips(&strip->strips);
+ }
}
/* Tag all actions used by given animdata to be made local. */
static void make_local_animdata_tag(AnimData *adt)
{
- if (adt) {
- /* Actions - Active and Temp */
- if (adt->action) {
- adt->action->id.tag &= ~LIB_TAG_PRE_EXISTING;
- }
- if (adt->tmpact) {
- adt->tmpact->id.tag &= ~LIB_TAG_PRE_EXISTING;
- }
-
- /* Drivers */
- /* TODO: need to handle the ID-targets too? */
-
- /* NLA Data */
- for (NlaTrack *nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
- make_local_animdata_tag_strips(&nlt->strips);
- }
- }
+ if (adt) {
+ /* Actions - Active and Temp */
+ if (adt->action) {
+ adt->action->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ }
+ if (adt->tmpact) {
+ adt->tmpact->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ }
+
+ /* Drivers */
+ /* TODO: need to handle the ID-targets too? */
+
+ /* NLA Data */
+ for (NlaTrack *nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+ make_local_animdata_tag_strips(&nlt->strips);
+ }
+ }
}
static void make_local_material_tag(Material *ma)
{
- if (ma) {
- ma->id.tag &= ~LIB_TAG_PRE_EXISTING;
- make_local_animdata_tag(BKE_animdata_from_id(&ma->id));
+ if (ma) {
+ ma->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ make_local_animdata_tag(BKE_animdata_from_id(&ma->id));
- /* About nodetrees: root one is made local together with material, others we keep linked for now... */
- }
+ /* About nodetrees: root one is made local together with material, others we keep linked for now... */
+ }
}
static int make_local_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- ParticleSystem *psys;
- Material *ma, ***matarar;
- const int mode = RNA_enum_get(op->ptr, "type");
- int a;
-
- /* Note: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */
- if (mode == MAKE_LOCAL_ALL) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Collection *collection = CTX_data_collection(C);
-
- BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
-
- /* De-select so the user can differentiate newly instanced from existing objects. */
- BKE_view_layer_base_deselect_all(view_layer);
-
- if (make_local_all__instance_indirect_unused(bmain, view_layer, collection)) {
- BKE_report(op->reports, RPT_INFO, "Orphan library objects added to the current scene to avoid loss");
- }
- }
- else {
- BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
- tag_localizable_objects(C, mode);
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
- continue;
- }
-
- ob->id.tag &= ~LIB_TAG_PRE_EXISTING;
- make_local_animdata_tag(BKE_animdata_from_id(&ob->id));
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- psys->part->id.tag &= ~LIB_TAG_PRE_EXISTING;
- }
-
- if (mode == MAKE_LOCAL_SELECT_OBDATA_MATERIAL) {
- for (a = 0; a < ob->totcol; a++) {
- ma = ob->mat[a];
- if (ma) {
- make_local_material_tag(ma);
- }
- }
-
- matarar = (Material ***)give_matarar(ob);
- if (matarar) {
- for (a = 0; a < ob->totcol; a++) {
- ma = (*matarar)[a];
- if (ma) {
- make_local_material_tag(ma);
- }
- }
- }
- }
-
- if (ELEM(mode, MAKE_LOCAL_SELECT_OBDATA, MAKE_LOCAL_SELECT_OBDATA_MATERIAL) && ob->data != NULL) {
- ID *ob_data = ob->data;
- ob_data->tag &= ~LIB_TAG_PRE_EXISTING;
- make_local_animdata_tag(BKE_animdata_from_id(ob_data));
- }
- }
- CTX_DATA_END;
- }
-
- BKE_library_make_local(bmain, NULL, NULL, true, false); /* NULL is all libs */
-
- WM_event_add_notifier(C, NC_WINDOW, NULL);
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ ParticleSystem *psys;
+ Material *ma, ***matarar;
+ const int mode = RNA_enum_get(op->ptr, "type");
+ int a;
+
+ /* Note: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */
+ if (mode == MAKE_LOCAL_ALL) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Collection *collection = CTX_data_collection(C);
+
+ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
+
+ /* De-select so the user can differentiate newly instanced from existing objects. */
+ BKE_view_layer_base_deselect_all(view_layer);
+
+ if (make_local_all__instance_indirect_unused(bmain, view_layer, collection)) {
+ BKE_report(op->reports,
+ RPT_INFO,
+ "Orphan library objects added to the current scene to avoid loss");
+ }
+ }
+ else {
+ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
+ tag_localizable_objects(C, mode);
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
+ continue;
+ }
+
+ ob->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ make_local_animdata_tag(BKE_animdata_from_id(&ob->id));
+ for (psys = ob->particlesystem.first; psys; psys = psys->next) {
+ psys->part->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ }
+
+ if (mode == MAKE_LOCAL_SELECT_OBDATA_MATERIAL) {
+ for (a = 0; a < ob->totcol; a++) {
+ ma = ob->mat[a];
+ if (ma) {
+ make_local_material_tag(ma);
+ }
+ }
+
+ matarar = (Material ***)give_matarar(ob);
+ if (matarar) {
+ for (a = 0; a < ob->totcol; a++) {
+ ma = (*matarar)[a];
+ if (ma) {
+ make_local_material_tag(ma);
+ }
+ }
+ }
+ }
+
+ if (ELEM(mode, MAKE_LOCAL_SELECT_OBDATA, MAKE_LOCAL_SELECT_OBDATA_MATERIAL) &&
+ ob->data != NULL) {
+ ID *ob_data = ob->data;
+ ob_data->tag &= ~LIB_TAG_PRE_EXISTING;
+ make_local_animdata_tag(BKE_animdata_from_id(ob_data));
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ BKE_library_make_local(bmain, NULL, NULL, true, false); /* NULL is all libs */
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_make_local(wmOperatorType *ot)
{
- static const EnumPropertyItem type_items[] = {
- {MAKE_LOCAL_SELECT_OB, "SELECT_OBJECT", 0, "Selected Objects", ""},
- {MAKE_LOCAL_SELECT_OBDATA, "SELECT_OBDATA", 0, "Selected Objects and Data", ""},
- {MAKE_LOCAL_SELECT_OBDATA_MATERIAL, "SELECT_OBDATA_MATERIAL", 0, "Selected Objects, Data and Materials", ""},
- {MAKE_LOCAL_ALL, "ALL", 0, "All", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Make Local";
- ot->description = "Make library linked data-blocks local to this file";
- ot->idname = "OBJECT_OT_make_local";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = make_local_exec;
- ot->poll = ED_operator_objectmode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
+ static const EnumPropertyItem type_items[] = {
+ {MAKE_LOCAL_SELECT_OB, "SELECT_OBJECT", 0, "Selected Objects", ""},
+ {MAKE_LOCAL_SELECT_OBDATA, "SELECT_OBDATA", 0, "Selected Objects and Data", ""},
+ {MAKE_LOCAL_SELECT_OBDATA_MATERIAL,
+ "SELECT_OBDATA_MATERIAL",
+ 0,
+ "Selected Objects, Data and Materials",
+ ""},
+ {MAKE_LOCAL_ALL, "ALL", 0, "All", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Make Local";
+ ot->description = "Make library linked data-blocks local to this file";
+ ot->idname = "OBJECT_OT_make_local";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = make_local_exec;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
}
-
static void make_override_static_tag_object(Object *obact, Object *ob)
{
- if (ob == obact) {
- return;
- }
-
- if (!ID_IS_LINKED(ob)) {
- return;
- }
-
- /* Note: all this is very case-by-case bad handling, ultimately we'll want a real full
- * 'automatic', generic handling of all this,
- * will probably require adding some override-aware stuff to library_query code... */
-
- if (obact->type == OB_ARMATURE && ob->modifiers.first != NULL) {
- for (ModifierData *md = ob->modifiers.first; md != NULL; md = md->next) {
- if (md->type == eModifierType_Armature) {
- ArmatureModifierData *amd = (ArmatureModifierData *)md;
- if (amd->object == obact) {
- ob->id.tag |= LIB_TAG_DOIT;
- break;
- }
- }
- }
- }
- else if (ob->parent == obact) {
- ob->id.tag |= LIB_TAG_DOIT;
- }
-
- if (ob->id.tag & LIB_TAG_DOIT) {
- printf("Indirectly overriding %s for %s\n", ob->id.name, obact->id.name);
- }
+ if (ob == obact) {
+ return;
+ }
+
+ if (!ID_IS_LINKED(ob)) {
+ return;
+ }
+
+ /* Note: all this is very case-by-case bad handling, ultimately we'll want a real full
+ * 'automatic', generic handling of all this,
+ * will probably require adding some override-aware stuff to library_query code... */
+
+ if (obact->type == OB_ARMATURE && ob->modifiers.first != NULL) {
+ for (ModifierData *md = ob->modifiers.first; md != NULL; md = md->next) {
+ if (md->type == eModifierType_Armature) {
+ ArmatureModifierData *amd = (ArmatureModifierData *)md;
+ if (amd->object == obact) {
+ ob->id.tag |= LIB_TAG_DOIT;
+ break;
+ }
+ }
+ }
+ }
+ else if (ob->parent == obact) {
+ ob->id.tag |= LIB_TAG_DOIT;
+ }
+
+ if (ob->id.tag & LIB_TAG_DOIT) {
+ printf("Indirectly overriding %s for %s\n", ob->id.name, obact->id.name);
+ }
}
static void make_override_static_tag_collections(Collection *collection)
{
- collection->id.tag |= LIB_TAG_DOIT;
- for (CollectionChild *coll_child = collection->children.first; coll_child != NULL; coll_child = coll_child->next) {
- make_override_static_tag_collections(coll_child->collection);
- }
+ collection->id.tag |= LIB_TAG_DOIT;
+ for (CollectionChild *coll_child = collection->children.first; coll_child != NULL;
+ coll_child = coll_child->next) {
+ make_override_static_tag_collections(coll_child->collection);
+ }
}
/* Set the object to override. */
static int make_override_static_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Scene *scene = CTX_data_scene(C);
- Object *obact = ED_object_active_context(C);
-
- /* Sanity checks. */
- if (!scene || ID_IS_LINKED(scene) || !obact) {
- return OPERATOR_CANCELLED;
- }
-
- /* Get object to work on - use a menu if we need to... */
- if (!ID_IS_LINKED(obact) && obact->instance_collection != NULL && ID_IS_LINKED(obact->instance_collection)) {
- /* Gives menu with list of objects in group. */
- WM_enum_search_invoke(C, op, event);
- return OPERATOR_CANCELLED;
- }
- else if (ID_IS_LINKED(obact)) {
- uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("OK?"), ICON_QUESTION);
- uiLayout *layout = UI_popup_menu_layout(pup);
-
- /* Create operator menu item with relevant properties filled in. */
- PointerRNA opptr_dummy;
- uiItemFullO_ptr(layout, op->type, op->type->name, ICON_NONE, NULL,
- WM_OP_EXEC_REGION_WIN, 0, &opptr_dummy);
-
- /* Present the menu and be done... */
- UI_popup_menu_end(C, pup);
-
- /* This invoke just calls another instance of this operator... */
- return OPERATOR_INTERFACE;
- }
- else {
- /* Error.. cannot continue. */
- BKE_report(op->reports, RPT_ERROR, "Can only make static override for a referenced object or collection");
- return OPERATOR_CANCELLED;
- }
-
+ Scene *scene = CTX_data_scene(C);
+ Object *obact = ED_object_active_context(C);
+
+ /* Sanity checks. */
+ if (!scene || ID_IS_LINKED(scene) || !obact) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Get object to work on - use a menu if we need to... */
+ if (!ID_IS_LINKED(obact) && obact->instance_collection != NULL &&
+ ID_IS_LINKED(obact->instance_collection)) {
+ /* Gives menu with list of objects in group. */
+ WM_enum_search_invoke(C, op, event);
+ return OPERATOR_CANCELLED;
+ }
+ else if (ID_IS_LINKED(obact)) {
+ uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("OK?"), ICON_QUESTION);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+
+ /* Create operator menu item with relevant properties filled in. */
+ PointerRNA opptr_dummy;
+ uiItemFullO_ptr(
+ layout, op->type, op->type->name, ICON_NONE, NULL, WM_OP_EXEC_REGION_WIN, 0, &opptr_dummy);
+
+ /* Present the menu and be done... */
+ UI_popup_menu_end(C, pup);
+
+ /* This invoke just calls another instance of this operator... */
+ return OPERATOR_INTERFACE;
+ }
+ else {
+ /* Error.. cannot continue. */
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Can only make static override for a referenced object or collection");
+ return OPERATOR_CANCELLED;
+ }
}
static int make_override_static_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *obact = CTX_data_active_object(C);
-
- bool success = false;
-
- if (!ID_IS_LINKED(obact) && obact->instance_collection != NULL && ID_IS_LINKED(obact->instance_collection)) {
- Object *obcollection = obact;
- Collection *collection = obcollection->instance_collection;
-
- const ListBase dup_collection_objects = BKE_collection_object_cache_get(collection);
- Base *base = BLI_findlink(&dup_collection_objects, RNA_enum_get(op->ptr, "object"));
- obact = base->object;
-
- /* First, we make a static override of the linked collection itself, and all its children. */
- make_override_static_tag_collections(collection);
-
- /* Then, we make static override of the whole set of objects in the Collection. */
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, ob)
- {
- ob->id.tag |= LIB_TAG_DOIT;
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
-
- /* Then, we remove (untag) bone shape objects, you shall never want to override those (hopefully)... */
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, ob)
- {
- if (ob->type == OB_ARMATURE && ob->pose != NULL) {
- for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
- if (pchan->custom != NULL) {
- pchan->custom->id.tag &= ~ LIB_TAG_DOIT;
- }
- }
- }
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
-
- success = BKE_override_static_create_from_tag(bmain);
-
- /* Instantiate our newly overridden objects in scene, if not yet done. */
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Collection *new_collection = (Collection *)collection->id.newid;
-
- BKE_collection_child_add(bmain, scene->master_collection, new_collection);
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(new_collection, new_ob)
- {
- if (new_ob != NULL && new_ob->id.override_static != NULL) {
- if ((base = BKE_view_layer_base_find(view_layer, new_ob)) == NULL) {
- BKE_collection_object_add_from(bmain, scene, obcollection, new_ob);
- base = BKE_view_layer_base_find(view_layer, new_ob);
- DEG_id_tag_update_ex(bmain, &new_ob->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS);
- }
- /* parent to 'collection' empty */
- if (new_ob->parent == NULL) {
- new_ob->parent = obcollection;
- }
- if (new_ob == (Object *)obact->id.newid) {
- /* TODO: is setting active needed? */
- BKE_view_layer_base_select_and_set_active(view_layer, base);
- }
- else {
- /* Disable auto-override tags for non-active objects, will help with performaces... */
- new_ob->id.override_static->flag &= ~STATICOVERRIDE_AUTO;
- }
- /* We still want to store all objects' current override status (i.e. change of parent). */
- BKE_override_static_operations_create(bmain, &new_ob->id, true);
- }
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
-
- /* obcollection is no more duplicollection-ing,
- * it merely parents whole collection of overriding instantiated objects. */
- obcollection->instance_collection = NULL;
-
- /* Also, we'd likely want to lock by default things like
- * transformations of implicitly overridden objects? */
-
- DEG_id_tag_update(&scene->id, 0);
-
- /* Cleanup. */
- BKE_main_id_clear_newpoins(bmain);
- BKE_main_id_tag_listbase(&bmain->objects, LIB_TAG_DOIT, false);
- }
- /* Else, poll func ensures us that ID_IS_LINKED(obact) is true. */
- else if (obact->type == OB_ARMATURE) {
- BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
-
- obact->id.tag |= LIB_TAG_DOIT;
-
- for (Object *ob = bmain->objects.first; ob != NULL; ob = ob->id.next) {
- make_override_static_tag_object(obact, ob);
- }
-
- success = BKE_override_static_create_from_tag(bmain);
-
- /* Also, we'd likely want to lock by default things like
- * transformations of implicitly overridden objects? */
-
- /* Cleanup. */
- BKE_main_id_clear_newpoins(bmain);
- BKE_main_id_tag_listbase(&bmain->objects, LIB_TAG_DOIT, false);
- }
- /* TODO: probably more cases where we want to do automated smart things in the future! */
- else {
- success = (BKE_override_static_create_from_id(bmain, &obact->id) != NULL);
- }
-
- WM_event_add_notifier(C, NC_WINDOW, NULL);
-
- return success ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ Main *bmain = CTX_data_main(C);
+ Object *obact = CTX_data_active_object(C);
+
+ bool success = false;
+
+ if (!ID_IS_LINKED(obact) && obact->instance_collection != NULL &&
+ ID_IS_LINKED(obact->instance_collection)) {
+ Object *obcollection = obact;
+ Collection *collection = obcollection->instance_collection;
+
+ const ListBase dup_collection_objects = BKE_collection_object_cache_get(collection);
+ Base *base = BLI_findlink(&dup_collection_objects, RNA_enum_get(op->ptr, "object"));
+ obact = base->object;
+
+ /* First, we make a static override of the linked collection itself, and all its children. */
+ make_override_static_tag_collections(collection);
+
+ /* Then, we make static override of the whole set of objects in the Collection. */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, ob) {
+ ob->id.tag |= LIB_TAG_DOIT;
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+
+ /* Then, we remove (untag) bone shape objects, you shall never want to override those (hopefully)... */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, ob) {
+ if (ob->type == OB_ARMATURE && ob->pose != NULL) {
+ for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
+ if (pchan->custom != NULL) {
+ pchan->custom->id.tag &= ~LIB_TAG_DOIT;
+ }
+ }
+ }
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+
+ success = BKE_override_static_create_from_tag(bmain);
+
+ /* Instantiate our newly overridden objects in scene, if not yet done. */
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Collection *new_collection = (Collection *)collection->id.newid;
+
+ BKE_collection_child_add(bmain, scene->master_collection, new_collection);
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (new_collection, new_ob) {
+ if (new_ob != NULL && new_ob->id.override_static != NULL) {
+ if ((base = BKE_view_layer_base_find(view_layer, new_ob)) == NULL) {
+ BKE_collection_object_add_from(bmain, scene, obcollection, new_ob);
+ base = BKE_view_layer_base_find(view_layer, new_ob);
+ DEG_id_tag_update_ex(bmain, &new_ob->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS);
+ }
+ /* parent to 'collection' empty */
+ if (new_ob->parent == NULL) {
+ new_ob->parent = obcollection;
+ }
+ if (new_ob == (Object *)obact->id.newid) {
+ /* TODO: is setting active needed? */
+ BKE_view_layer_base_select_and_set_active(view_layer, base);
+ }
+ else {
+ /* Disable auto-override tags for non-active objects, will help with performaces... */
+ new_ob->id.override_static->flag &= ~STATICOVERRIDE_AUTO;
+ }
+ /* We still want to store all objects' current override status (i.e. change of parent). */
+ BKE_override_static_operations_create(bmain, &new_ob->id, true);
+ }
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+
+ /* obcollection is no more duplicollection-ing,
+ * it merely parents whole collection of overriding instantiated objects. */
+ obcollection->instance_collection = NULL;
+
+ /* Also, we'd likely want to lock by default things like
+ * transformations of implicitly overridden objects? */
+
+ DEG_id_tag_update(&scene->id, 0);
+
+ /* Cleanup. */
+ BKE_main_id_clear_newpoins(bmain);
+ BKE_main_id_tag_listbase(&bmain->objects, LIB_TAG_DOIT, false);
+ }
+ /* Else, poll func ensures us that ID_IS_LINKED(obact) is true. */
+ else if (obact->type == OB_ARMATURE) {
+ BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+
+ obact->id.tag |= LIB_TAG_DOIT;
+
+ for (Object *ob = bmain->objects.first; ob != NULL; ob = ob->id.next) {
+ make_override_static_tag_object(obact, ob);
+ }
+
+ success = BKE_override_static_create_from_tag(bmain);
+
+ /* Also, we'd likely want to lock by default things like
+ * transformations of implicitly overridden objects? */
+
+ /* Cleanup. */
+ BKE_main_id_clear_newpoins(bmain);
+ BKE_main_id_tag_listbase(&bmain->objects, LIB_TAG_DOIT, false);
+ }
+ /* TODO: probably more cases where we want to do automated smart things in the future! */
+ else {
+ success = (BKE_override_static_create_from_id(bmain, &obact->id) != NULL);
+ }
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+ return success ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static bool make_override_static_poll(bContext *C)
{
- Object *obact = CTX_data_active_object(C);
+ Object *obact = CTX_data_active_object(C);
- /* Object must be directly linked to be overridable. */
- return (BKE_override_static_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))));
+ /* Object must be directly linked to be overridable. */
+ return (BKE_override_static_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))));
}
void OBJECT_OT_make_override_static(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Static Override";
- ot->description = "Make local override of this library linked data-block";
- ot->idname = "OBJECT_OT_make_override_static";
-
- /* api callbacks */
- ot->invoke = make_override_static_invoke;
- ot->exec = make_override_static_exec;
- ot->poll = make_override_static_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- PropertyRNA *prop;
- prop = RNA_def_enum(ot->srna, "object", DummyRNA_DEFAULT_items, 0, "Override Object",
- "Name of lib-linked/collection object to make an override from");
- RNA_def_enum_funcs(prop, proxy_collection_object_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ /* identifiers */
+ ot->name = "Make Static Override";
+ ot->description = "Make local override of this library linked data-block";
+ ot->idname = "OBJECT_OT_make_override_static";
+
+ /* api callbacks */
+ ot->invoke = make_override_static_invoke;
+ ot->exec = make_override_static_exec;
+ ot->poll = make_override_static_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ PropertyRNA *prop;
+ prop = RNA_def_enum(ot->srna,
+ "object",
+ DummyRNA_DEFAULT_items,
+ 0,
+ "Override Object",
+ "Name of lib-linked/collection object to make an override from");
+ RNA_def_enum_funcs(prop, proxy_collection_object_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
enum {
- MAKE_SINGLE_USER_ALL = 1,
- MAKE_SINGLE_USER_SELECTED = 2,
+ MAKE_SINGLE_USER_ALL = 1,
+ MAKE_SINGLE_USER_SELECTED = 2,
};
static int make_single_user_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);
- View3D *v3d = CTX_wm_view3d(C); /* ok if this is NULL */
- const int flag = (RNA_enum_get(op->ptr, "type") == MAKE_SINGLE_USER_SELECTED) ? SELECT : 0;
- const bool copy_collections = false;
- bool update_deps = false;
-
- if (RNA_boolean_get(op->ptr, "object")) {
- if (flag == SELECT) {
- BKE_view_layer_selected_objects_tag(view_layer, OB_DONE);
- single_object_users(bmain, scene, v3d, OB_DONE, copy_collections);
- }
- else {
- single_object_users(bmain, scene, v3d, 0, copy_collections);
- }
-
- /* needed since object relationships may have changed */
- update_deps = true;
- }
-
- if (RNA_boolean_get(op->ptr, "obdata")) {
- single_obdata_users(bmain, scene, view_layer, v3d, flag);
- }
-
- if (RNA_boolean_get(op->ptr, "material")) {
- single_mat_users(bmain, scene, view_layer, v3d, flag);
- }
-
- if (RNA_boolean_get(op->ptr, "animation")) {
- single_object_action_users(bmain, scene, view_layer, v3d, flag);
- }
-
- BKE_main_id_clear_newpoins(bmain);
-
- WM_event_add_notifier(C, NC_WINDOW, NULL);
-
- if (update_deps) {
- DEG_relations_tag_update(bmain);
- }
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C); /* ok if this is NULL */
+ const int flag = (RNA_enum_get(op->ptr, "type") == MAKE_SINGLE_USER_SELECTED) ? SELECT : 0;
+ const bool copy_collections = false;
+ bool update_deps = false;
+
+ if (RNA_boolean_get(op->ptr, "object")) {
+ if (flag == SELECT) {
+ BKE_view_layer_selected_objects_tag(view_layer, OB_DONE);
+ single_object_users(bmain, scene, v3d, OB_DONE, copy_collections);
+ }
+ else {
+ single_object_users(bmain, scene, v3d, 0, copy_collections);
+ }
+
+ /* needed since object relationships may have changed */
+ update_deps = true;
+ }
+
+ if (RNA_boolean_get(op->ptr, "obdata")) {
+ single_obdata_users(bmain, scene, view_layer, v3d, flag);
+ }
+
+ if (RNA_boolean_get(op->ptr, "material")) {
+ single_mat_users(bmain, scene, view_layer, v3d, flag);
+ }
+
+ if (RNA_boolean_get(op->ptr, "animation")) {
+ single_object_action_users(bmain, scene, view_layer, v3d, flag);
+ }
+
+ BKE_main_id_clear_newpoins(bmain);
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+ if (update_deps) {
+ DEG_relations_tag_update(bmain);
+ }
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_make_single_user(wmOperatorType *ot)
{
- static const EnumPropertyItem type_items[] = {
- {MAKE_SINGLE_USER_SELECTED, "SELECTED_OBJECTS", 0, "Selected Objects", ""},
- {MAKE_SINGLE_USER_ALL, "ALL", 0, "All", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Make Single User";
- ot->description = "Make linked data local to each object";
- ot->idname = "OBJECT_OT_make_single_user";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = make_single_user_exec;
- ot->poll = ED_operator_objectmode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", type_items, MAKE_SINGLE_USER_SELECTED, "Type", "");
-
- RNA_def_boolean(ot->srna, "object", 0, "Object", "Make single user objects");
- RNA_def_boolean(ot->srna, "obdata", 0, "Object Data", "Make single user object data");
- RNA_def_boolean(ot->srna, "material", 0, "Materials", "Make materials local to each data-block");
- RNA_def_boolean(ot->srna, "animation", 0, "Object Animation", "Make animation data local to each object");
+ static const EnumPropertyItem type_items[] = {
+ {MAKE_SINGLE_USER_SELECTED, "SELECTED_OBJECTS", 0, "Selected Objects", ""},
+ {MAKE_SINGLE_USER_ALL, "ALL", 0, "All", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Make Single User";
+ ot->description = "Make linked data local to each object";
+ ot->idname = "OBJECT_OT_make_single_user";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = make_single_user_exec;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", type_items, MAKE_SINGLE_USER_SELECTED, "Type", "");
+
+ RNA_def_boolean(ot->srna, "object", 0, "Object", "Make single user objects");
+ RNA_def_boolean(ot->srna, "obdata", 0, "Object Data", "Make single user object data");
+ RNA_def_boolean(ot->srna, "material", 0, "Materials", "Make materials local to each data-block");
+ RNA_def_boolean(
+ ot->srna, "animation", 0, "Object Animation", "Make animation data local to each object");
}
static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Main *bmain = CTX_data_main(C);
- Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
- Material *ma;
- char name[MAX_ID_NAME - 2];
+ Main *bmain = CTX_data_main(C);
+ Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
+ Material *ma;
+ char name[MAX_ID_NAME - 2];
- RNA_string_get(op->ptr, "name", name);
- ma = (Material *)BKE_libblock_find_name(bmain, ID_MA, name);
- if (base == NULL || ma == NULL)
- return OPERATOR_CANCELLED;
+ RNA_string_get(op->ptr, "name", name);
+ ma = (Material *)BKE_libblock_find_name(bmain, ID_MA, name);
+ if (base == NULL || ma == NULL)
+ return OPERATOR_CANCELLED;
- assign_material(CTX_data_main(C), base->object, ma, 1, BKE_MAT_ASSIGN_USERPREF);
+ assign_material(CTX_data_main(C), base->object, ma, 1, BKE_MAT_ASSIGN_USERPREF);
- DEG_id_tag_update(&base->object->id, ID_RECALC_TRANSFORM);
+ DEG_id_tag_update(&base->object->id, ID_RECALC_TRANSFORM);
- WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, base->object);
- 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);
+ WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, base->object);
+ 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);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* used for dropbox */
/* assigns to object under cursor, only first material slot */
void OBJECT_OT_drop_named_material(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Drop Named Material on Object";
- ot->idname = "OBJECT_OT_drop_named_material";
+ /* identifiers */
+ ot->name = "Drop Named Material on Object";
+ ot->idname = "OBJECT_OT_drop_named_material";
- /* api callbacks */
- ot->invoke = drop_named_material_invoke;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->invoke = drop_named_material_invoke;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
- /* properties */
- RNA_def_string(ot->srna, "name", "Material", MAX_ID_NAME - 2, "Name", "Material name to assign");
+ /* properties */
+ RNA_def_string(ot->srna, "name", "Material", MAX_ID_NAME - 2, "Name", "Material name to assign");
}
static int object_unlink_data_exec(bContext *C, wmOperator *op)
{
- ID *id;
- PropertyPointerRNA pprop;
+ ID *id;
+ PropertyPointerRNA pprop;
- UI_context_active_but_prop_get_templateID(C, &pprop.ptr, &pprop.prop);
+ UI_context_active_but_prop_get_templateID(C, &pprop.ptr, &pprop.prop);
- if (pprop.prop == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Incorrect context for running object data unlink");
- return OPERATOR_CANCELLED;
- }
+ if (pprop.prop == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Incorrect context for running object data unlink");
+ return OPERATOR_CANCELLED;
+ }
- id = pprop.ptr.id.data;
+ id = pprop.ptr.id.data;
- if (GS(id->name) == ID_OB) {
- Object *ob = (Object *)id;
- if (ob->data) {
- ID *id_data = ob->data;
+ if (GS(id->name) == ID_OB) {
+ Object *ob = (Object *)id;
+ if (ob->data) {
+ ID *id_data = ob->data;
- if (GS(id_data->name) == ID_IM) {
- id_us_min(id_data);
- ob->data = NULL;
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Can't unlink this object data");
- return OPERATOR_CANCELLED;
- }
- }
- }
+ if (GS(id_data->name) == ID_IM) {
+ id_us_min(id_data);
+ ob->data = NULL;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Can't unlink this object data");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ }
- RNA_property_update(C, &pprop.ptr, pprop.prop);
+ RNA_property_update(C, &pprop.ptr, pprop.prop);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/**
@@ -2583,13 +2655,13 @@ static int object_unlink_data_exec(bContext *C, wmOperator *op)
*/
void OBJECT_OT_unlink_data(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unlink";
- ot->idname = "OBJECT_OT_unlink_data";
+ /* identifiers */
+ ot->name = "Unlink";
+ ot->idname = "OBJECT_OT_unlink_data";
- /* api callbacks */
- ot->exec = object_unlink_data_exec;
+ /* api callbacks */
+ ot->exec = object_unlink_data_exec;
- /* flags */
- ot->flag = OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_INTERNAL;
}
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 919055aa668..06bd4d76973 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -96,26 +96,26 @@
*/
void ED_object_base_select(Base *base, eObjectSelect_Mode mode)
{
- if (mode == BA_INVERT) {
- mode = (base->flag & BASE_SELECTED) != 0 ? BA_DESELECT : BA_SELECT;
- }
-
- if (base) {
- switch (mode) {
- case BA_SELECT:
- if ((base->flag & BASE_SELECTABLE) != 0) {
- base->flag |= BASE_SELECTED;
- }
- break;
- case BA_DESELECT:
- base->flag &= ~BASE_SELECTED;
- break;
- case BA_INVERT:
- /* Never happens. */
- break;
- }
- BKE_scene_object_base_flag_sync_from_base(base);
- }
+ if (mode == BA_INVERT) {
+ mode = (base->flag & BASE_SELECTED) != 0 ? BA_DESELECT : BA_SELECT;
+ }
+
+ if (base) {
+ switch (mode) {
+ case BA_SELECT:
+ if ((base->flag & BASE_SELECTABLE) != 0) {
+ base->flag |= BASE_SELECTED;
+ }
+ break;
+ case BA_DESELECT:
+ base->flag &= ~BASE_SELECTED;
+ break;
+ case BA_INVERT:
+ /* Never happens. */
+ break;
+ }
+ BKE_scene_object_base_flag_sync_from_base(base);
+ }
}
/**
@@ -123,75 +123,77 @@ void ED_object_base_select(Base *base, eObjectSelect_Mode mode)
*/
void ED_object_base_activate(bContext *C, Base *base)
{
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- view_layer->basact = base;
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
- WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active);
- DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_SELECT);
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ view_layer->basact = base;
+
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+ WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active);
+ DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_SELECT);
}
-bool ED_object_base_deselect_all_ex(ViewLayer *view_layer, View3D *v3d, int action, bool *r_any_visible)
+bool ED_object_base_deselect_all_ex(ViewLayer *view_layer,
+ View3D *v3d,
+ int action,
+ bool *r_any_visible)
{
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
- FOREACH_VISIBLE_BASE_BEGIN(view_layer, v3d, base) {
- if (v3d && ((v3d->object_type_exclude_select & (1 << base->object->type)) != 0)) {
- continue;
- }
- if ((base->flag & BASE_SELECTED) != 0) {
- action = SEL_DESELECT;
- break;
- }
- }
- FOREACH_VISIBLE_BASE_END;
- }
-
- bool any_visible = false;
- bool changed = false;
- FOREACH_VISIBLE_BASE_BEGIN(view_layer, v3d, base) {
- if (v3d && ((v3d->object_type_exclude_select & (1 << base->object->type)) != 0)) {
- continue;
- }
- switch (action) {
- case SEL_SELECT:
- if ((base->flag & BASE_SELECTED) == 0) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- break;
- case SEL_DESELECT:
- if ((base->flag & BASE_SELECTED) != 0) {
- ED_object_base_select(base, BA_DESELECT);
- changed = true;
- }
- break;
- case SEL_INVERT:
- if ((base->flag & BASE_SELECTED) != 0) {
- ED_object_base_select(base, BA_DESELECT);
- changed = true;
- }
- else {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- break;
- }
- any_visible = true;
- }
- FOREACH_VISIBLE_BASE_END;
- if (r_any_visible) {
- *r_any_visible = any_visible;
- }
- return changed;
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+ FOREACH_VISIBLE_BASE_BEGIN (view_layer, v3d, base) {
+ if (v3d && ((v3d->object_type_exclude_select & (1 << base->object->type)) != 0)) {
+ continue;
+ }
+ if ((base->flag & BASE_SELECTED) != 0) {
+ action = SEL_DESELECT;
+ break;
+ }
+ }
+ FOREACH_VISIBLE_BASE_END;
+ }
+
+ bool any_visible = false;
+ bool changed = false;
+ FOREACH_VISIBLE_BASE_BEGIN (view_layer, v3d, base) {
+ if (v3d && ((v3d->object_type_exclude_select & (1 << base->object->type)) != 0)) {
+ continue;
+ }
+ switch (action) {
+ case SEL_SELECT:
+ if ((base->flag & BASE_SELECTED) == 0) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ break;
+ case SEL_DESELECT:
+ if ((base->flag & BASE_SELECTED) != 0) {
+ ED_object_base_select(base, BA_DESELECT);
+ changed = true;
+ }
+ break;
+ case SEL_INVERT:
+ if ((base->flag & BASE_SELECTED) != 0) {
+ ED_object_base_select(base, BA_DESELECT);
+ changed = true;
+ }
+ else {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ break;
+ }
+ any_visible = true;
+ }
+ FOREACH_VISIBLE_BASE_END;
+ if (r_any_visible) {
+ *r_any_visible = any_visible;
+ }
+ return changed;
}
-
bool ED_object_base_deselect_all(ViewLayer *view_layer, View3D *v3d, int action)
{
- return ED_object_base_deselect_all_ex(view_layer, v3d, action, NULL);
+ return ED_object_base_deselect_all_ex(view_layer, v3d, action, NULL);
}
/** \} */
@@ -202,17 +204,17 @@ bool ED_object_base_deselect_all(ViewLayer *view_layer, View3D *v3d, int action)
static int get_base_select_priority(Base *base)
{
- if (base->flag & BASE_VISIBLE) {
- if (base->flag & BASE_SELECTABLE) {
- return 3;
- }
- else {
- return 2;
- }
- }
- else {
- return 1;
- }
+ if (base->flag & BASE_VISIBLE) {
+ if (base->flag & BASE_SELECTABLE) {
+ return 3;
+ }
+ else {
+ return 2;
+ }
+ }
+ else {
+ return 1;
+ }
}
/**
@@ -221,36 +223,36 @@ static int get_base_select_priority(Base *base)
*/
Base *ED_object_find_first_by_data_id(ViewLayer *view_layer, ID *id)
{
- BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
-
- /* Try active object. */
- Base *basact = view_layer->basact;
-
- if (basact && basact->object && basact->object->data == id) {
- return basact;
- }
-
- /* Try all objects. */
- Base *base_best = NULL;
- int priority_best = 0;
-
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (base->object && base->object->data == id) {
- if (base->flag & BASE_SELECTED) {
- return base;
- }
- else {
- int priority_test = get_base_select_priority(base);
-
- if (priority_test > priority_best) {
- priority_best = priority_test;
- base_best = base;
- }
- }
- }
- }
-
- return base_best;
+ BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
+
+ /* Try active object. */
+ Base *basact = view_layer->basact;
+
+ if (basact && basact->object && basact->object->data == id) {
+ return basact;
+ }
+
+ /* Try all objects. */
+ Base *base_best = NULL;
+ int priority_best = 0;
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->object && base->object->data == id) {
+ if (base->flag & BASE_SELECTED) {
+ return base;
+ }
+ else {
+ int priority_test = get_base_select_priority(base);
+
+ if (priority_test > priority_best) {
+ priority_best = priority_test;
+ base_best = base;
+ }
+ }
+ }
+ }
+
+ return base_best;
}
/**
@@ -259,36 +261,35 @@ Base *ED_object_find_first_by_data_id(ViewLayer *view_layer, ID *id)
*
* \returns false if not found in current view layer
*/
-bool ED_object_jump_to_object(
- bContext *C, Object *ob, const bool UNUSED(reveal_hidden))
+bool ED_object_jump_to_object(bContext *C, Object *ob, const bool UNUSED(reveal_hidden))
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- Base *base = BKE_view_layer_base_find(view_layer, ob);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
- if (base == NULL) {
- return false;
- }
+ if (base == NULL) {
+ return false;
+ }
- /* TODO, use 'reveal_hidden', as is done with bones. */
+ /* TODO, use 'reveal_hidden', as is done with bones. */
- if (view_layer->basact != base || !(base->flag & BASE_SELECTED)) {
- /* Select if not selected. */
- if (!(base->flag & BASE_SELECTED)) {
- ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT);
+ if (view_layer->basact != base || !(base->flag & BASE_SELECTED)) {
+ /* Select if not selected. */
+ if (!(base->flag & BASE_SELECTED)) {
+ ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT);
- if (base->flag & BASE_VISIBLE) {
- ED_object_base_select(base, BA_SELECT);
- }
+ if (base->flag & BASE_VISIBLE) {
+ ED_object_base_select(base, BA_SELECT);
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
- }
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ }
- /* Make active if not active. */
- ED_object_base_activate(C, base);
- }
+ /* Make active if not active. */
+ ED_object_base_activate(C, base);
+ }
- return true;
+ return true;
}
/**
@@ -298,79 +299,80 @@ bool ED_object_jump_to_object(
*
* \returns false if object not in layer, bone not found, or other error
*/
-bool ED_object_jump_to_bone(
- bContext *C, Object *ob, const char *bone_name,
- const bool reveal_hidden)
+bool ED_object_jump_to_bone(bContext *C,
+ Object *ob,
+ const char *bone_name,
+ const bool reveal_hidden)
{
- /* Verify it's a valid armature object. */
- if (ob == NULL || ob->type != OB_ARMATURE) {
- return false;
- }
-
- bArmature *arm = ob->data;
-
- /* Activate the armature object. */
- if (!ED_object_jump_to_object(C, ob, reveal_hidden)) {
- return false;
- }
-
- /* Switch to pose mode from object mode. */
- if (!ELEM(ob->mode, OB_MODE_EDIT, OB_MODE_POSE)) {
- ED_object_mode_set(C, OB_MODE_POSE);
- }
-
- if (ob->mode == OB_MODE_EDIT && arm->edbo != NULL) {
- /* In Edit mode select and activate the target Edit-Bone. */
- EditBone *ebone = ED_armature_ebone_find_name(arm->edbo, bone_name);
- if (ebone != NULL) {
- if (reveal_hidden) {
- /* Unhide the bone. */
- ebone->flag &= ~BONE_HIDDEN_A;
-
- if ((arm->layer & ebone->layer) == 0) {
- arm->layer |= 1U << bitscan_forward_uint(ebone->layer);
- }
- }
-
- /* Select it. */
- ED_armature_edit_deselect_all(ob);
-
- if (EBONE_SELECTABLE(arm, ebone)) {
- ED_armature_ebone_select_set(ebone, true);
- ED_armature_edit_sync_selection(arm->edbo);
- }
-
- arm->act_edbone = ebone;
-
- ED_pose_bone_select_tag_update(ob);
- return true;
- }
- }
- else if (ob->mode == OB_MODE_POSE && ob->pose != NULL) {
- /* In Pose mode select and activate the target Bone/Pose-Channel. */
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
- if (pchan != NULL) {
- if (reveal_hidden) {
- /* Unhide the bone. */
- pchan->bone->flag &= ~BONE_HIDDEN_P;
-
- if ((arm->layer & pchan->bone->layer) == 0) {
- arm->layer |= 1U << bitscan_forward_uint(pchan->bone->layer);
- }
- }
-
- /* Select it. */
- ED_pose_deselect_all(ob, SEL_DESELECT, true);
- ED_pose_bone_select(ob, pchan, true);
-
- arm->act_bone = pchan->bone;
-
- ED_pose_bone_select_tag_update(ob);
- return true;
- }
- }
-
- return false;
+ /* Verify it's a valid armature object. */
+ if (ob == NULL || ob->type != OB_ARMATURE) {
+ return false;
+ }
+
+ bArmature *arm = ob->data;
+
+ /* Activate the armature object. */
+ if (!ED_object_jump_to_object(C, ob, reveal_hidden)) {
+ return false;
+ }
+
+ /* Switch to pose mode from object mode. */
+ if (!ELEM(ob->mode, OB_MODE_EDIT, OB_MODE_POSE)) {
+ ED_object_mode_set(C, OB_MODE_POSE);
+ }
+
+ if (ob->mode == OB_MODE_EDIT && arm->edbo != NULL) {
+ /* In Edit mode select and activate the target Edit-Bone. */
+ EditBone *ebone = ED_armature_ebone_find_name(arm->edbo, bone_name);
+ if (ebone != NULL) {
+ if (reveal_hidden) {
+ /* Unhide the bone. */
+ ebone->flag &= ~BONE_HIDDEN_A;
+
+ if ((arm->layer & ebone->layer) == 0) {
+ arm->layer |= 1U << bitscan_forward_uint(ebone->layer);
+ }
+ }
+
+ /* Select it. */
+ ED_armature_edit_deselect_all(ob);
+
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ ED_armature_ebone_select_set(ebone, true);
+ ED_armature_edit_sync_selection(arm->edbo);
+ }
+
+ arm->act_edbone = ebone;
+
+ ED_pose_bone_select_tag_update(ob);
+ return true;
+ }
+ }
+ else if (ob->mode == OB_MODE_POSE && ob->pose != NULL) {
+ /* In Pose mode select and activate the target Bone/Pose-Channel. */
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
+ if (pchan != NULL) {
+ if (reveal_hidden) {
+ /* Unhide the bone. */
+ pchan->bone->flag &= ~BONE_HIDDEN_P;
+
+ if ((arm->layer & pchan->bone->layer) == 0) {
+ arm->layer |= 1U << bitscan_forward_uint(pchan->bone->layer);
+ }
+ }
+
+ /* Select it. */
+ ED_pose_deselect_all(ob, SEL_DESELECT, true);
+ ED_pose_bone_select(ob, pchan, true);
+
+ arm->act_bone = pchan->bone;
+
+ ED_pose_bone_select_tag_update(ob);
+ return true;
+ }
+ }
+
+ return false;
}
/** \} */
@@ -381,16 +383,16 @@ bool ED_object_jump_to_bone(
static bool objects_selectable_poll(bContext *C)
{
- /* we don't check for linked scenes here, selection is
- * still allowed then for inspection of scene */
- Object *obact = CTX_data_active_object(C);
+ /* we don't check for linked scenes here, selection is
+ * still allowed then for inspection of scene */
+ Object *obact = CTX_data_active_object(C);
- if (CTX_data_edit_object(C))
- return 0;
- if (obact && obact->mode)
- return 0;
+ if (CTX_data_edit_object(C))
+ return 0;
+ if (obact && obact->mode)
+ return 0;
- return 1;
+ return 1;
}
/** \} */
@@ -401,51 +403,54 @@ static bool objects_selectable_poll(bContext *C)
static int object_select_by_type_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- short obtype, extend;
-
- obtype = RNA_enum_get(op->ptr, "type");
- extend = RNA_boolean_get(op->ptr, "extend");
-
- if (extend == 0) {
- ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT);
- }
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (base->object->type == obtype) {
- ED_object_base_select(base, BA_SELECT);
- }
- }
- CTX_DATA_END;
-
- Scene *scene = CTX_data_scene(C);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ short obtype, extend;
+
+ obtype = RNA_enum_get(op->ptr, "type");
+ extend = RNA_boolean_get(op->ptr, "extend");
+
+ if (extend == 0) {
+ ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT);
+ }
+
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (base->object->type == obtype) {
+ ED_object_base_select(base, BA_SELECT);
+ }
+ }
+ CTX_DATA_END;
+
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_select_by_type(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select By Type";
- ot->description = "Select all visible objects that are of a type";
- ot->idname = "OBJECT_OT_select_by_type";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_select_by_type_exec;
- ot->poll = objects_selectable_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_type_items, 1, "Type", "");
- RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_ID);
+ /* identifiers */
+ ot->name = "Select By Type";
+ ot->description = "Select all visible objects that are of a type";
+ ot->idname = "OBJECT_OT_select_by_type";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_select_by_type_exec;
+ ot->poll = objects_selectable_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "extend",
+ false,
+ "Extend",
+ "Extend selection instead of deselecting everything first");
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_type_items, 1, "Type", "");
+ RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_ID);
}
/** \} */
@@ -455,270 +460,273 @@ void OBJECT_OT_select_by_type(wmOperatorType *ot)
* \{ */
enum {
- OBJECT_SELECT_LINKED_IPO = 1,
- OBJECT_SELECT_LINKED_OBDATA,
- OBJECT_SELECT_LINKED_MATERIAL,
- OBJECT_SELECT_LINKED_DUPGROUP,
- OBJECT_SELECT_LINKED_PARTICLE,
- OBJECT_SELECT_LINKED_LIBRARY,
- OBJECT_SELECT_LINKED_LIBRARY_OBDATA,
+ OBJECT_SELECT_LINKED_IPO = 1,
+ OBJECT_SELECT_LINKED_OBDATA,
+ OBJECT_SELECT_LINKED_MATERIAL,
+ OBJECT_SELECT_LINKED_DUPGROUP,
+ OBJECT_SELECT_LINKED_PARTICLE,
+ OBJECT_SELECT_LINKED_LIBRARY,
+ OBJECT_SELECT_LINKED_LIBRARY_OBDATA,
};
static const EnumPropertyItem prop_select_linked_types[] = {
- //{OBJECT_SELECT_LINKED_IPO, "IPO", 0, "Object IPO", ""}, // XXX deprecated animation system stuff...
- {OBJECT_SELECT_LINKED_OBDATA, "OBDATA", 0, "Object Data", ""},
- {OBJECT_SELECT_LINKED_MATERIAL, "MATERIAL", 0, "Material", ""},
- {OBJECT_SELECT_LINKED_DUPGROUP, "DUPGROUP", 0, "Instanced Collection", ""},
- {OBJECT_SELECT_LINKED_PARTICLE, "PARTICLE", 0, "Particle System", ""},
- {OBJECT_SELECT_LINKED_LIBRARY, "LIBRARY", 0, "Library", ""},
- {OBJECT_SELECT_LINKED_LIBRARY_OBDATA, "LIBRARY_OBDATA", 0, "Library (Object Data)", ""},
- {0, NULL, 0, NULL, NULL},
+ //{OBJECT_SELECT_LINKED_IPO, "IPO", 0, "Object IPO", ""}, // XXX deprecated animation system stuff...
+ {OBJECT_SELECT_LINKED_OBDATA, "OBDATA", 0, "Object Data", ""},
+ {OBJECT_SELECT_LINKED_MATERIAL, "MATERIAL", 0, "Material", ""},
+ {OBJECT_SELECT_LINKED_DUPGROUP, "DUPGROUP", 0, "Instanced Collection", ""},
+ {OBJECT_SELECT_LINKED_PARTICLE, "PARTICLE", 0, "Particle System", ""},
+ {OBJECT_SELECT_LINKED_LIBRARY, "LIBRARY", 0, "Library", ""},
+ {OBJECT_SELECT_LINKED_LIBRARY_OBDATA, "LIBRARY_OBDATA", 0, "Library (Object Data)", ""},
+ {0, NULL, 0, NULL, NULL},
};
static bool object_select_all_by_obdata(bContext *C, void *obdata)
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
- if (base->object->data == obdata) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- }
- CTX_DATA_END;
-
- return changed;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ if (base->object->data == obdata) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ return changed;
}
static bool object_select_all_by_material(bContext *C, Material *mat)
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
- Object *ob = base->object;
- Material *mat1;
- int a;
-
- for (a = 1; a <= ob->totcol; a++) {
- mat1 = give_current_material(ob, a);
-
- if (mat1 == mat) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- }
- }
- CTX_DATA_END;
-
- return changed;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ Object *ob = base->object;
+ Material *mat1;
+ int a;
+
+ for (a = 1; a <= ob->totcol; a++) {
+ mat1 = give_current_material(ob, a);
+
+ if (mat1 == mat) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ return changed;
}
static bool object_select_all_by_instance_collection(bContext *C, Object *ob)
{
- bool changed = false;
- Collection *instance_collection = (ob->transflag & OB_DUPLICOLLECTION) ? ob->instance_collection : NULL;
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
- Collection *instance_collection_other = (base->object->transflag & OB_DUPLICOLLECTION) ? base->object->instance_collection : NULL;
- if (instance_collection == instance_collection_other) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- }
- CTX_DATA_END;
-
- return changed;
+ bool changed = false;
+ Collection *instance_collection = (ob->transflag & OB_DUPLICOLLECTION) ?
+ ob->instance_collection :
+ NULL;
+
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ Collection *instance_collection_other = (base->object->transflag & OB_DUPLICOLLECTION) ?
+ base->object->instance_collection :
+ NULL;
+ if (instance_collection == instance_collection_other) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ return changed;
}
static bool object_select_all_by_particle(bContext *C, Object *ob)
{
- ParticleSystem *psys_act = psys_get_current(ob);
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
- /* loop through other particles*/
- ParticleSystem *psys;
-
- for (psys = base->object->particlesystem.first; psys; psys = psys->next) {
- if (psys->part == psys_act->part) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- break;
- }
-
- if (base->flag & BASE_SELECTED) {
- break;
- }
- }
- }
- }
- CTX_DATA_END;
-
- return changed;
+ ParticleSystem *psys_act = psys_get_current(ob);
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ /* loop through other particles*/
+ ParticleSystem *psys;
+
+ for (psys = base->object->particlesystem.first; psys; psys = psys->next) {
+ if (psys->part == psys_act->part) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ break;
+ }
+
+ if (base->flag & BASE_SELECTED) {
+ break;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ return changed;
}
static bool object_select_all_by_library(bContext *C, Library *lib)
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
- if (lib == base->object->id.lib) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- }
- CTX_DATA_END;
-
- return changed;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ if (lib == base->object->id.lib) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ return changed;
}
static bool object_select_all_by_library_obdata(bContext *C, Library *lib)
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
- if (base->object->data && lib == ((ID *)base->object->data)->lib) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- }
- CTX_DATA_END;
-
- return changed;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ if (base->object->data && lib == ((ID *)base->object->data)->lib) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ return changed;
}
void ED_object_select_linked_by_id(bContext *C, ID *id)
{
- int idtype = GS(id->name);
- bool changed = false;
-
- if (OB_DATA_SUPPORT_ID(idtype)) {
- changed = object_select_all_by_obdata(C, id);
- }
- else if (idtype == ID_MA) {
- changed = object_select_all_by_material(C, (Material *)id);
- }
- else if (idtype == ID_LI) {
- changed = object_select_all_by_library(C, (Library *) id);
- }
-
- if (changed) {
- Scene *scene = CTX_data_scene(C);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
+ int idtype = GS(id->name);
+ bool changed = false;
+
+ if (OB_DATA_SUPPORT_ID(idtype)) {
+ changed = object_select_all_by_obdata(C, id);
+ }
+ else if (idtype == ID_MA) {
+ changed = object_select_all_by_material(C, (Material *)id);
+ }
+ else if (idtype == ID_LI) {
+ changed = object_select_all_by_library(C, (Library *)id);
+ }
+
+ if (changed) {
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ }
}
static int object_select_linked_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- Object *ob;
- int nr = RNA_enum_get(op->ptr, "type");
- bool changed = false, extend;
-
- extend = RNA_boolean_get(op->ptr, "extend");
-
- if (extend == 0) {
- ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT);
- }
-
- ob = OBACT(view_layer);
- if (ob == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active object");
- return OPERATOR_CANCELLED;
- }
-
- if (nr == OBJECT_SELECT_LINKED_IPO) {
- // XXX old animation system
- //if (ob->ipo == 0) return OPERATOR_CANCELLED;
- //object_select_all_by_ipo(C, ob->ipo)
- return OPERATOR_CANCELLED;
- }
- else if (nr == OBJECT_SELECT_LINKED_OBDATA) {
- if (ob->data == NULL)
- return OPERATOR_CANCELLED;
-
- changed = object_select_all_by_obdata(C, ob->data);
- }
- else if (nr == OBJECT_SELECT_LINKED_MATERIAL) {
- Material *mat = NULL;
-
- mat = give_current_material(ob, ob->actcol);
- if (mat == NULL) return OPERATOR_CANCELLED;
-
- changed = object_select_all_by_material(C, mat);
- }
- else if (nr == OBJECT_SELECT_LINKED_DUPGROUP) {
- if (ob->instance_collection == NULL)
- return OPERATOR_CANCELLED;
-
- changed = object_select_all_by_instance_collection(C, ob);
- }
- else if (nr == OBJECT_SELECT_LINKED_PARTICLE) {
- if (BLI_listbase_is_empty(&ob->particlesystem))
- return OPERATOR_CANCELLED;
-
- changed = object_select_all_by_particle(C, ob);
- }
- else if (nr == OBJECT_SELECT_LINKED_LIBRARY) {
- /* do nothing */
- changed = object_select_all_by_library(C, ob->id.lib);
- }
- else if (nr == OBJECT_SELECT_LINKED_LIBRARY_OBDATA) {
- if (ob->data == NULL)
- return OPERATOR_CANCELLED;
-
- changed = object_select_all_by_library_obdata(C, ((ID *) ob->data)->lib);
- }
- else
- return OPERATOR_CANCELLED;
-
- if (changed) {
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Object *ob;
+ int nr = RNA_enum_get(op->ptr, "type");
+ bool changed = false, extend;
+
+ extend = RNA_boolean_get(op->ptr, "extend");
+
+ if (extend == 0) {
+ ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT);
+ }
+
+ ob = OBACT(view_layer);
+ if (ob == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active object");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (nr == OBJECT_SELECT_LINKED_IPO) {
+ // XXX old animation system
+ //if (ob->ipo == 0) return OPERATOR_CANCELLED;
+ //object_select_all_by_ipo(C, ob->ipo)
+ return OPERATOR_CANCELLED;
+ }
+ else if (nr == OBJECT_SELECT_LINKED_OBDATA) {
+ if (ob->data == NULL)
+ return OPERATOR_CANCELLED;
+
+ changed = object_select_all_by_obdata(C, ob->data);
+ }
+ else if (nr == OBJECT_SELECT_LINKED_MATERIAL) {
+ Material *mat = NULL;
+
+ mat = give_current_material(ob, ob->actcol);
+ if (mat == NULL)
+ return OPERATOR_CANCELLED;
+
+ changed = object_select_all_by_material(C, mat);
+ }
+ else if (nr == OBJECT_SELECT_LINKED_DUPGROUP) {
+ if (ob->instance_collection == NULL)
+ return OPERATOR_CANCELLED;
+
+ changed = object_select_all_by_instance_collection(C, ob);
+ }
+ else if (nr == OBJECT_SELECT_LINKED_PARTICLE) {
+ if (BLI_listbase_is_empty(&ob->particlesystem))
+ return OPERATOR_CANCELLED;
+
+ changed = object_select_all_by_particle(C, ob);
+ }
+ else if (nr == OBJECT_SELECT_LINKED_LIBRARY) {
+ /* do nothing */
+ changed = object_select_all_by_library(C, ob->id.lib);
+ }
+ else if (nr == OBJECT_SELECT_LINKED_LIBRARY_OBDATA) {
+ if (ob->data == NULL)
+ return OPERATOR_CANCELLED;
+
+ changed = object_select_all_by_library_obdata(C, ((ID *)ob->data)->lib);
+ }
+ else
+ return OPERATOR_CANCELLED;
+
+ if (changed) {
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_select_linked(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Linked";
- ot->description = "Select all visible objects that are linked";
- ot->idname = "OBJECT_OT_select_linked";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_select_linked_exec;
- ot->poll = objects_selectable_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
- ot->prop = RNA_def_enum(ot->srna, "type", prop_select_linked_types, 0, "Type", "");
+ /* identifiers */
+ ot->name = "Select Linked";
+ ot->description = "Select all visible objects that are linked";
+ ot->idname = "OBJECT_OT_select_linked";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_select_linked_exec;
+ ot->poll = objects_selectable_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "extend",
+ false,
+ "Extend",
+ "Extend selection instead of deselecting everything first");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_select_linked_types, 0, "Type", "");
}
/** \} */
@@ -728,371 +736,379 @@ void OBJECT_OT_select_linked(wmOperatorType *ot)
* \{ */
enum {
- OBJECT_GRPSEL_CHILDREN_RECURSIVE = 0,
- OBJECT_GRPSEL_CHILDREN = 1,
- OBJECT_GRPSEL_PARENT = 2,
- OBJECT_GRPSEL_SIBLINGS = 3,
- OBJECT_GRPSEL_TYPE = 4,
- OBJECT_GRPSEL_COLLECTION = 5,
- OBJECT_GRPSEL_HOOK = 7,
- OBJECT_GRPSEL_PASS = 8,
- OBJECT_GRPSEL_COLOR = 9,
- OBJECT_GRPSEL_KEYINGSET = 10,
- OBJECT_GRPSEL_LIGHT_TYPE = 11,
+ OBJECT_GRPSEL_CHILDREN_RECURSIVE = 0,
+ OBJECT_GRPSEL_CHILDREN = 1,
+ OBJECT_GRPSEL_PARENT = 2,
+ OBJECT_GRPSEL_SIBLINGS = 3,
+ OBJECT_GRPSEL_TYPE = 4,
+ OBJECT_GRPSEL_COLLECTION = 5,
+ OBJECT_GRPSEL_HOOK = 7,
+ OBJECT_GRPSEL_PASS = 8,
+ OBJECT_GRPSEL_COLOR = 9,
+ OBJECT_GRPSEL_KEYINGSET = 10,
+ OBJECT_GRPSEL_LIGHT_TYPE = 11,
};
static const EnumPropertyItem prop_select_grouped_types[] = {
- {OBJECT_GRPSEL_CHILDREN_RECURSIVE, "CHILDREN_RECURSIVE", 0, "Children", ""},
- {OBJECT_GRPSEL_CHILDREN, "CHILDREN", 0, "Immediate Children", ""},
- {OBJECT_GRPSEL_PARENT, "PARENT", 0, "Parent", ""},
- {OBJECT_GRPSEL_SIBLINGS, "SIBLINGS", 0, "Siblings", "Shared Parent"},
- {OBJECT_GRPSEL_TYPE, "TYPE", 0, "Type", "Shared object type"},
- {OBJECT_GRPSEL_COLLECTION, "COLLECTION", 0, "Collection", "Shared collection"},
- {OBJECT_GRPSEL_HOOK, "HOOK", 0, "Hook", ""},
- {OBJECT_GRPSEL_PASS, "PASS", 0, "Pass", "Render pass Index"},
- {OBJECT_GRPSEL_COLOR, "COLOR", 0, "Color", "Object Color"},
- {OBJECT_GRPSEL_KEYINGSET, "KEYINGSET", 0, "Keying Set", "Objects included in active Keying Set"},
- {OBJECT_GRPSEL_LIGHT_TYPE, "LIGHT_TYPE", 0, "Light Type", "Matching light types"},
- {0, NULL, 0, NULL, NULL},
+ {OBJECT_GRPSEL_CHILDREN_RECURSIVE, "CHILDREN_RECURSIVE", 0, "Children", ""},
+ {OBJECT_GRPSEL_CHILDREN, "CHILDREN", 0, "Immediate Children", ""},
+ {OBJECT_GRPSEL_PARENT, "PARENT", 0, "Parent", ""},
+ {OBJECT_GRPSEL_SIBLINGS, "SIBLINGS", 0, "Siblings", "Shared Parent"},
+ {OBJECT_GRPSEL_TYPE, "TYPE", 0, "Type", "Shared object type"},
+ {OBJECT_GRPSEL_COLLECTION, "COLLECTION", 0, "Collection", "Shared collection"},
+ {OBJECT_GRPSEL_HOOK, "HOOK", 0, "Hook", ""},
+ {OBJECT_GRPSEL_PASS, "PASS", 0, "Pass", "Render pass Index"},
+ {OBJECT_GRPSEL_COLOR, "COLOR", 0, "Color", "Object Color"},
+ {OBJECT_GRPSEL_KEYINGSET,
+ "KEYINGSET",
+ 0,
+ "Keying Set",
+ "Objects included in active Keying Set"},
+ {OBJECT_GRPSEL_LIGHT_TYPE, "LIGHT_TYPE", 0, "Light Type", "Matching light types"},
+ {0, NULL, 0, NULL, NULL},
};
static bool select_grouped_children(bContext *C, Object *ob, const bool recursive)
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- if (ob == base->object->parent) {
- if ((base->flag & BASE_SELECTED) == 0) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
-
- if (recursive) {
- changed |= select_grouped_children(C, base->object, 1);
- }
- }
- }
- CTX_DATA_END;
- return changed;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ if (ob == base->object->parent) {
+ if ((base->flag & BASE_SELECTED) == 0) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+
+ if (recursive) {
+ changed |= select_grouped_children(C, base->object, 1);
+ }
+ }
+ }
+ CTX_DATA_END;
+ return changed;
}
static bool select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- Base *baspar, *basact = CTX_data_active_base(C);
- bool changed = false;
-
- if (!basact || !(basact->object->parent)) {
- return 0; /* we know OBACT is valid */
- }
-
- baspar = BKE_view_layer_base_find(view_layer, basact->object->parent);
-
- /* can be NULL if parent in other scene */
- if (baspar && BASE_SELECTABLE(v3d, baspar)) {
- ED_object_base_select(baspar, BA_SELECT);
- ED_object_base_activate(C, baspar);
- changed = true;
- }
- return changed;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Base *baspar, *basact = CTX_data_active_base(C);
+ bool changed = false;
+
+ if (!basact || !(basact->object->parent)) {
+ return 0; /* we know OBACT is valid */
+ }
+
+ baspar = BKE_view_layer_base_find(view_layer, basact->object->parent);
+
+ /* can be NULL if parent in other scene */
+ if (baspar && BASE_SELECTABLE(v3d, baspar)) {
+ ED_object_base_select(baspar, BA_SELECT);
+ ED_object_base_activate(C, baspar);
+ changed = true;
+ }
+ return changed;
}
-
-#define COLLECTION_MENU_MAX 24
+#define COLLECTION_MENU_MAX 24
/* Select objects in the same group as the active */
static bool select_grouped_collection(bContext *C, Object *ob)
{
- 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; collection = collection->id.next) {
- if (BKE_collection_has_object(collection, ob)) {
- ob_collections[collection_count] = collection;
- collection_count++;
- }
- }
-
- if (!collection_count)
- return 0;
- else if (collection_count == 1) {
- collection = ob_collections[0];
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
- if (BKE_collection_has_object(collection, base->object)) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- }
- CTX_DATA_END;
- return changed;
- }
-
- /* build the menu. */
- pup = UI_popup_menu_begin(C, IFACE_("Select Collection"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
-
- for (i = 0; i < collection_count; i++) {
- collection = ob_collections[i];
- uiItemStringO(layout, collection->id.name + 2, 0, "OBJECT_OT_select_same_collection", "collection", collection->id.name + 2);
- }
-
- UI_popup_menu_end(C, pup);
- return changed; /* The operator already handle this! */
+ 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;
+ collection = collection->id.next) {
+ if (BKE_collection_has_object(collection, ob)) {
+ ob_collections[collection_count] = collection;
+ collection_count++;
+ }
+ }
+
+ if (!collection_count)
+ return 0;
+ else if (collection_count == 1) {
+ collection = ob_collections[0];
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ if (BKE_collection_has_object(collection, base->object)) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ }
+ CTX_DATA_END;
+ return changed;
+ }
+
+ /* build the menu. */
+ pup = UI_popup_menu_begin(C, IFACE_("Select Collection"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+
+ for (i = 0; i < collection_count; i++) {
+ collection = ob_collections[i];
+ uiItemStringO(layout,
+ collection->id.name + 2,
+ 0,
+ "OBJECT_OT_select_same_collection",
+ "collection",
+ collection->id.name + 2);
+ }
+
+ UI_popup_menu_end(C, pup);
+ return changed; /* The operator already handle this! */
}
static bool select_grouped_object_hooks(bContext *C, Object *ob)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
-
- bool changed = false;
- Base *base;
- ModifierData *md;
- HookModifierData *hmd;
-
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Hook) {
- hmd = (HookModifierData *) md;
- if (hmd->object) {
- base = BKE_view_layer_base_find(view_layer, hmd->object);
- if (base && ((base->flag & BASE_SELECTED) == 0) && (BASE_SELECTABLE(v3d, base))) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- }
- }
- return changed;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ bool changed = false;
+ Base *base;
+ ModifierData *md;
+ HookModifierData *hmd;
+
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Hook) {
+ hmd = (HookModifierData *)md;
+ if (hmd->object) {
+ base = BKE_view_layer_base_find(view_layer, hmd->object);
+ if (base && ((base->flag & BASE_SELECTED) == 0) && (BASE_SELECTABLE(v3d, base))) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ }
+ }
+ return changed;
}
/* Select objects with the same parent as the active (siblings),
* parent can be NULL also */
static bool select_grouped_siblings(bContext *C, Object *ob)
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- if ((base->object->parent == ob->parent) && ((base->flag & BASE_SELECTED) == 0)) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- CTX_DATA_END;
- return changed;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ if ((base->object->parent == ob->parent) && ((base->flag & BASE_SELECTED) == 0)) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ CTX_DATA_END;
+ return changed;
}
static bool select_grouped_lighttype(bContext *C, Object *ob)
{
- Light *la = ob->data;
-
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- if (base->object->type == OB_LAMP) {
- Light *la_test = base->object->data;
- if ((la->type == la_test->type) && ((base->flag & BASE_SELECTED) == 0)) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- }
- CTX_DATA_END;
- return changed;
+ Light *la = ob->data;
+
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ if (base->object->type == OB_LAMP) {
+ Light *la_test = base->object->data;
+ if ((la->type == la_test->type) && ((base->flag & BASE_SELECTED) == 0)) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ }
+ CTX_DATA_END;
+ return changed;
}
static bool select_grouped_type(bContext *C, Object *ob)
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- if ((base->object->type == ob->type) && ((base->flag & BASE_SELECTED) == 0)) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- CTX_DATA_END;
- return changed;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ if ((base->object->type == ob->type) && ((base->flag & BASE_SELECTED) == 0)) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ CTX_DATA_END;
+ return changed;
}
static bool select_grouped_index_object(bContext *C, Object *ob)
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- if ((base->object->index == ob->index) && ((base->flag & BASE_SELECTED) == 0)) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- CTX_DATA_END;
- return changed;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ if ((base->object->index == ob->index) && ((base->flag & BASE_SELECTED) == 0)) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ CTX_DATA_END;
+ return changed;
}
static bool select_grouped_color(bContext *C, Object *ob)
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && (compare_v3v3(base->object->color, ob->color, 0.005f))) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- CTX_DATA_END;
- return changed;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) &&
+ (compare_v3v3(base->object->color, ob->color, 0.005f))) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ CTX_DATA_END;
+ return changed;
}
static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList *reports)
{
- KeyingSet *ks = ANIM_scene_get_active_keyingset(CTX_data_scene(C));
- bool changed = false;
-
- /* firstly, validate KeyingSet */
- if (ks == NULL) {
- BKE_report(reports, RPT_ERROR, "No active Keying Set to use");
- return false;
- }
- else if (ANIM_validate_keyingset(C, NULL, ks) != 0) {
- if (ks->paths.first == NULL) {
- if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
- BKE_report(reports, RPT_ERROR,
- "Use another Keying Set, as the active one depends on the currently "
- "selected objects or cannot find any targets due to unsuitable context");
- }
- else {
- BKE_report(reports, RPT_ERROR, "Keying Set does not contain any paths");
- }
- }
- return false;
- }
-
- /* select each object that Keying Set refers to */
- /* TODO: perhaps to be more in line with the rest of these, we should only take objects
- * if the passed in object is included in this too */
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- /* only check for this object if it isn't selected already, to limit time wasted */
- if ((base->flag & BASE_SELECTED) == 0) {
- KS_Path *ksp;
-
- /* this is the slow way... we could end up with > 500 items here,
- * with none matching, but end up doing this on 1000 objects...
- */
- for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
- /* if id matches, select then stop looping (match found) */
- if (ksp->id == (ID *)base->object) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- break;
- }
- }
- }
- }
- CTX_DATA_END;
-
- return changed;
+ KeyingSet *ks = ANIM_scene_get_active_keyingset(CTX_data_scene(C));
+ bool changed = false;
+
+ /* firstly, validate KeyingSet */
+ if (ks == NULL) {
+ BKE_report(reports, RPT_ERROR, "No active Keying Set to use");
+ return false;
+ }
+ else if (ANIM_validate_keyingset(C, NULL, ks) != 0) {
+ if (ks->paths.first == NULL) {
+ if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
+ BKE_report(reports,
+ RPT_ERROR,
+ "Use another Keying Set, as the active one depends on the currently "
+ "selected objects or cannot find any targets due to unsuitable context");
+ }
+ else {
+ BKE_report(reports, RPT_ERROR, "Keying Set does not contain any paths");
+ }
+ }
+ return false;
+ }
+
+ /* select each object that Keying Set refers to */
+ /* TODO: perhaps to be more in line with the rest of these, we should only take objects
+ * if the passed in object is included in this too */
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ /* only check for this object if it isn't selected already, to limit time wasted */
+ if ((base->flag & BASE_SELECTED) == 0) {
+ KS_Path *ksp;
+
+ /* this is the slow way... we could end up with > 500 items here,
+ * with none matching, but end up doing this on 1000 objects...
+ */
+ for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
+ /* if id matches, select then stop looping (match found) */
+ if (ksp->id == (ID *)base->object) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ break;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ return changed;
}
static int object_select_grouped_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- Object *ob;
- const int type = RNA_enum_get(op->ptr, "type");
- bool changed = false, extend;
-
- extend = RNA_boolean_get(op->ptr, "extend");
-
- if (extend == 0) {
- changed = ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT);
- }
-
- ob = OBACT(view_layer);
- if (ob == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active object");
- return OPERATOR_CANCELLED;
- }
-
- switch (type) {
- case OBJECT_GRPSEL_CHILDREN_RECURSIVE:
- changed |= select_grouped_children(C, ob, true);
- break;
- case OBJECT_GRPSEL_CHILDREN:
- changed |= select_grouped_children(C, ob, false);
- break;
- case OBJECT_GRPSEL_PARENT:
- changed |= select_grouped_parent(C);
- break;
- case OBJECT_GRPSEL_SIBLINGS:
- changed |= select_grouped_siblings(C, ob);
- break;
- case OBJECT_GRPSEL_TYPE:
- changed |= select_grouped_type(C, ob);
- break;
- case OBJECT_GRPSEL_COLLECTION:
- changed |= select_grouped_collection(C, ob);
- break;
- case OBJECT_GRPSEL_HOOK:
- changed |= select_grouped_object_hooks(C, ob);
- break;
- case OBJECT_GRPSEL_PASS:
- changed |= select_grouped_index_object(C, ob);
- break;
- case OBJECT_GRPSEL_COLOR:
- changed |= select_grouped_color(C, ob);
- break;
- case OBJECT_GRPSEL_KEYINGSET:
- changed |= select_grouped_keyingset(C, ob, op->reports);
- break;
- case OBJECT_GRPSEL_LIGHT_TYPE:
- if (ob->type != OB_LAMP) {
- BKE_report(op->reports, RPT_ERROR, "Active object must be a light");
- break;
- }
- changed |= select_grouped_lighttype(C, ob);
- break;
- default:
- break;
- }
-
- if (changed) {
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Object *ob;
+ const int type = RNA_enum_get(op->ptr, "type");
+ bool changed = false, extend;
+
+ extend = RNA_boolean_get(op->ptr, "extend");
+
+ if (extend == 0) {
+ changed = ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT);
+ }
+
+ ob = OBACT(view_layer);
+ if (ob == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active object");
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (type) {
+ case OBJECT_GRPSEL_CHILDREN_RECURSIVE:
+ changed |= select_grouped_children(C, ob, true);
+ break;
+ case OBJECT_GRPSEL_CHILDREN:
+ changed |= select_grouped_children(C, ob, false);
+ break;
+ case OBJECT_GRPSEL_PARENT:
+ changed |= select_grouped_parent(C);
+ break;
+ case OBJECT_GRPSEL_SIBLINGS:
+ changed |= select_grouped_siblings(C, ob);
+ break;
+ case OBJECT_GRPSEL_TYPE:
+ changed |= select_grouped_type(C, ob);
+ break;
+ case OBJECT_GRPSEL_COLLECTION:
+ changed |= select_grouped_collection(C, ob);
+ break;
+ case OBJECT_GRPSEL_HOOK:
+ changed |= select_grouped_object_hooks(C, ob);
+ break;
+ case OBJECT_GRPSEL_PASS:
+ changed |= select_grouped_index_object(C, ob);
+ break;
+ case OBJECT_GRPSEL_COLOR:
+ changed |= select_grouped_color(C, ob);
+ break;
+ case OBJECT_GRPSEL_KEYINGSET:
+ changed |= select_grouped_keyingset(C, ob, op->reports);
+ break;
+ case OBJECT_GRPSEL_LIGHT_TYPE:
+ if (ob->type != OB_LAMP) {
+ BKE_report(op->reports, RPT_ERROR, "Active object must be a light");
+ break;
+ }
+ changed |= select_grouped_lighttype(C, ob);
+ break;
+ default:
+ break;
+ }
+
+ if (changed) {
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_select_grouped(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Grouped";
- ot->description = "Select all visible objects grouped by various properties";
- ot->idname = "OBJECT_OT_select_grouped";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_select_grouped_exec;
- ot->poll = objects_selectable_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
- ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
+ /* identifiers */
+ ot->name = "Select Grouped";
+ ot->description = "Select all visible objects grouped by various properties";
+ ot->idname = "OBJECT_OT_select_grouped";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_select_grouped_exec;
+ ot->poll = objects_selectable_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "extend",
+ false,
+ "Extend",
+ "Extend selection instead of deselecting everything first");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
}
/** \} */
@@ -1103,46 +1119,46 @@ void OBJECT_OT_select_grouped(wmOperatorType *ot)
static int object_select_all_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- int action = RNA_enum_get(op->ptr, "action");
- bool any_visible = false;
-
- bool changed = ED_object_base_deselect_all_ex(view_layer, v3d, action, &any_visible);
-
- if (changed) {
- Scene *scene = CTX_data_scene(C);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-
- return OPERATOR_FINISHED;
- }
- else if (any_visible == false) {
- /* TODO(campbell): Looks like we could remove this,
- * if not comment should say why its needed. */
- return OPERATOR_PASS_THROUGH;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ int action = RNA_enum_get(op->ptr, "action");
+ bool any_visible = false;
+
+ bool changed = ED_object_base_deselect_all_ex(view_layer, v3d, action, &any_visible);
+
+ if (changed) {
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
+ }
+ else if (any_visible == false) {
+ /* TODO(campbell): Looks like we could remove this,
+ * if not comment should say why its needed. */
+ return OPERATOR_PASS_THROUGH;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void OBJECT_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All";
- ot->description = "Change selection of all visible objects in scene";
- ot->idname = "OBJECT_OT_select_all";
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->description = "Change selection of all visible objects in scene";
+ ot->idname = "OBJECT_OT_select_all";
- /* api callbacks */
- ot->exec = object_select_all_exec;
- ot->poll = objects_selectable_poll;
+ /* api callbacks */
+ ot->exec = object_select_all_exec;
+ ot->poll = objects_selectable_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_select_all(ot);
+ WM_operator_properties_select_all(ot);
}
/** \} */
@@ -1153,54 +1169,55 @@ void OBJECT_OT_select_all(wmOperatorType *ot)
static int object_select_same_collection_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Collection *collection;
- char collection_name[MAX_ID_NAME];
+ Main *bmain = CTX_data_main(C);
+ Collection *collection;
+ char collection_name[MAX_ID_NAME];
- /* passthrough if no objects are visible */
- if (CTX_DATA_COUNT(C, visible_bases) == 0) return OPERATOR_PASS_THROUGH;
+ /* passthrough if no objects are visible */
+ if (CTX_DATA_COUNT(C, visible_bases) == 0)
+ return OPERATOR_PASS_THROUGH;
- RNA_string_get(op->ptr, "collection", collection_name);
+ RNA_string_get(op->ptr, "collection", collection_name);
- collection = (Collection *)BKE_libblock_find_name(bmain, ID_GR, collection_name);
+ collection = (Collection *)BKE_libblock_find_name(bmain, ID_GR, collection_name);
- if (!collection) {
- return OPERATOR_PASS_THROUGH;
- }
+ if (!collection) {
+ return OPERATOR_PASS_THROUGH;
+ }
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
- if (BKE_collection_has_object(collection, base->object)) {
- ED_object_base_select(base, BA_SELECT);
- }
- }
- }
- CTX_DATA_END;
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ if (BKE_collection_has_object(collection, base->object)) {
+ ED_object_base_select(base, BA_SELECT);
+ }
+ }
+ }
+ CTX_DATA_END;
- Scene *scene = CTX_data_scene(C);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_select_same_collection(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Same Collection";
- ot->description = "Select object in the same collection";
- ot->idname = "OBJECT_OT_select_same_collection";
+ /* identifiers */
+ ot->name = "Select Same Collection";
+ ot->description = "Select object in the same collection";
+ ot->idname = "OBJECT_OT_select_same_collection";
- /* api callbacks */
- ot->exec = object_select_same_collection_exec;
- ot->poll = objects_selectable_poll;
+ /* api callbacks */
+ ot->exec = object_select_same_collection_exec;
+ ot->poll = objects_selectable_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_string(ot->srna, "collection", NULL, MAX_ID_NAME, "Collection", "Name of the collection to select");
+ RNA_def_string(
+ ot->srna, "collection", NULL, MAX_ID_NAME, "Collection", "Name of the collection to select");
}
/** \} */
@@ -1211,58 +1228,58 @@ void OBJECT_OT_select_same_collection(wmOperatorType *ot)
static int object_select_mirror_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);
- bool extend;
-
- extend = RNA_boolean_get(op->ptr, "extend");
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ bool extend;
- CTX_DATA_BEGIN (C, Base *, primbase, selected_bases)
- {
- char name_flip[MAXBONENAME];
+ extend = RNA_boolean_get(op->ptr, "extend");
- BLI_string_flip_side_name(name_flip, primbase->object->id.name + 2, true, sizeof(name_flip));
+ CTX_DATA_BEGIN (C, Base *, primbase, selected_bases) {
+ char name_flip[MAXBONENAME];
- if (!STREQ(name_flip, primbase->object->id.name + 2)) {
- Object *ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name_flip);
- if (ob) {
- Base *secbase = BKE_view_layer_base_find(view_layer, ob);
+ BLI_string_flip_side_name(name_flip, primbase->object->id.name + 2, true, sizeof(name_flip));
- if (secbase) {
- ED_object_base_select(secbase, BA_SELECT);
- }
- }
- }
+ if (!STREQ(name_flip, primbase->object->id.name + 2)) {
+ Object *ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name_flip);
+ if (ob) {
+ Base *secbase = BKE_view_layer_base_find(view_layer, ob);
- if (extend == false) ED_object_base_select(primbase, BA_DESELECT);
+ if (secbase) {
+ ED_object_base_select(secbase, BA_SELECT);
+ }
+ }
+ }
- }
- CTX_DATA_END;
+ if (extend == false)
+ ED_object_base_select(primbase, BA_DESELECT);
+ }
+ CTX_DATA_END;
- /* undo? */
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ /* undo? */
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_select_mirror(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Mirror";
- ot->description = "Select the Mirror objects of the selected object eg. L.sword -> R.sword";
- ot->idname = "OBJECT_OT_select_mirror";
+ /* identifiers */
+ ot->name = "Select Mirror";
+ ot->description = "Select the Mirror objects of the selected object eg. L.sword -> R.sword";
+ ot->idname = "OBJECT_OT_select_mirror";
- /* api callbacks */
- ot->exec = object_select_mirror_exec;
- ot->poll = objects_selectable_poll;
+ /* api callbacks */
+ ot->exec = object_select_mirror_exec;
+ ot->poll = objects_selectable_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first");
+ RNA_def_boolean(
+ ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first");
}
/** \} */
@@ -1273,116 +1290,114 @@ void OBJECT_OT_select_mirror(wmOperatorType *ot)
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) {
- Object *ob = base->object;
- ob->flag &= ~OB_DONE;
- ob->id.tag &= ~LIB_TAG_DOIT;
- /* parent may be in another scene */
- if (ob->parent) {
- ob->parent->flag &= ~OB_DONE;
- ob->parent->id.tag &= ~LIB_TAG_DOIT;
- }
- }
-
- ListBase ctx_base_list;
- CollectionPointerLink *ctx_base;
- CTX_data_selectable_bases(C, &ctx_base_list);
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- ob->flag |= OB_DONE;
- }
- CTX_DATA_END;
-
-
- for (ctx_base = ctx_base_list.first; ctx_base; ctx_base = ctx_base->next) {
- Object *ob = ((Base *)ctx_base->ptr.data)->object;
- if (ob->parent) {
- if ((ob->flag & OB_DONE) != (ob->parent->flag & OB_DONE)) {
- ob->id.tag |= LIB_TAG_DOIT;
- ob->parent->id.tag |= LIB_TAG_DOIT;
- }
- }
- }
-
- bool changed = false;
- const short select_mode = select ? BA_SELECT : BA_DESELECT;
- const short select_flag = select ? BASE_SELECTED : 0;
-
- for (ctx_base = ctx_base_list.first; ctx_base; ctx_base = ctx_base->next) {
- Base *base = ctx_base->ptr.data;
- Object *ob = base->object;
- if ((ob->id.tag & LIB_TAG_DOIT) && ((base->flag & BASE_SELECTED) != select_flag)) {
- ED_object_base_select(base, select_mode);
- changed = true;
- }
- }
-
- BLI_freelistN(&ctx_base_list);
-
- return changed;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ Object *ob = base->object;
+ ob->flag &= ~OB_DONE;
+ ob->id.tag &= ~LIB_TAG_DOIT;
+ /* parent may be in another scene */
+ if (ob->parent) {
+ ob->parent->flag &= ~OB_DONE;
+ ob->parent->id.tag &= ~LIB_TAG_DOIT;
+ }
+ }
+
+ ListBase ctx_base_list;
+ CollectionPointerLink *ctx_base;
+ CTX_data_selectable_bases(C, &ctx_base_list);
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ ob->flag |= OB_DONE;
+ }
+ CTX_DATA_END;
+
+ for (ctx_base = ctx_base_list.first; ctx_base; ctx_base = ctx_base->next) {
+ Object *ob = ((Base *)ctx_base->ptr.data)->object;
+ if (ob->parent) {
+ if ((ob->flag & OB_DONE) != (ob->parent->flag & OB_DONE)) {
+ ob->id.tag |= LIB_TAG_DOIT;
+ ob->parent->id.tag |= LIB_TAG_DOIT;
+ }
+ }
+ }
+
+ bool changed = false;
+ const short select_mode = select ? BA_SELECT : BA_DESELECT;
+ const short select_flag = select ? BASE_SELECTED : 0;
+
+ for (ctx_base = ctx_base_list.first; ctx_base; ctx_base = ctx_base->next) {
+ Base *base = ctx_base->ptr.data;
+ Object *ob = base->object;
+ if ((ob->id.tag & LIB_TAG_DOIT) && ((base->flag & BASE_SELECTED) != select_flag)) {
+ ED_object_base_select(base, select_mode);
+ changed = true;
+ }
+ }
+
+ BLI_freelistN(&ctx_base_list);
+
+ return changed;
}
static int object_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
- bool changed = object_select_more_less(C, true);
-
- if (changed) {
- Scene *scene = CTX_data_scene(C);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ bool changed = object_select_more_less(C, true);
+
+ if (changed) {
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void OBJECT_OT_select_more(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select More";
- ot->idname = "OBJECT_OT_select_more";
- ot->description = "Select connected parent/child objects";
+ /* identifiers */
+ ot->name = "Select More";
+ ot->idname = "OBJECT_OT_select_more";
+ ot->description = "Select connected parent/child objects";
- /* api callbacks */
- ot->exec = object_select_more_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = object_select_more_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int object_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
- bool changed = object_select_more_less(C, false);
-
- if (changed) {
- Scene *scene = CTX_data_scene(C);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ bool changed = object_select_more_less(C, false);
+
+ if (changed) {
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void OBJECT_OT_select_less(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Less";
- ot->idname = "OBJECT_OT_select_less";
- ot->description = "Deselect objects at the boundaries of parent/child relationships";
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->idname = "OBJECT_OT_select_less";
+ ot->description = "Deselect objects at the boundaries of parent/child relationships";
- /* api callbacks */
- ot->exec = object_select_less_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = object_select_less_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -1393,46 +1408,45 @@ void OBJECT_OT_select_less(wmOperatorType *ot)
static int object_select_random_exec(bContext *C, wmOperator *op)
{
- const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
- const int seed = WM_operator_properties_select_random_seed_increment_get(op);
- const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
+ const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
+ const int seed = WM_operator_properties_select_random_seed_increment_get(op);
+ const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
- RNG *rng = BLI_rng_new_srandom(seed);
+ RNG *rng = BLI_rng_new_srandom(seed);
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- if (BLI_rng_get_float(rng) < randfac) {
- ED_object_base_select(base, select);
- }
- }
- CTX_DATA_END;
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ if (BLI_rng_get_float(rng) < randfac) {
+ ED_object_base_select(base, select);
+ }
+ }
+ CTX_DATA_END;
- BLI_rng_free(rng);
+ BLI_rng_free(rng);
- Scene *scene = CTX_data_scene(C);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_select_random(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Random";
- ot->description = "Set select on random visible objects";
- ot->idname = "OBJECT_OT_select_random";
+ /* identifiers */
+ ot->name = "Select Random";
+ ot->description = "Set select on random visible objects";
+ ot->idname = "OBJECT_OT_select_random";
- /* api callbacks */
- /*ot->invoke = object_select_random_invoke XXX - need a number popup ;*/
- ot->exec = object_select_random_exec;
- ot->poll = objects_selectable_poll;
+ /* api callbacks */
+ /*ot->invoke = object_select_random_invoke XXX - need a number popup ;*/
+ ot->exec = object_select_random_exec;
+ ot->poll = objects_selectable_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_select_random(ot);
+ /* properties */
+ WM_operator_properties_select_random(ot);
}
/** \} */
diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c
index 8580ea10d35..64535d8f281 100644
--- a/source/blender/editors/object/object_shader_fx.c
+++ b/source/blender/editors/object/object_shader_fx.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
@@ -63,400 +62,410 @@
/******************************** API ****************************/
-ShaderFxData *ED_object_shaderfx_add(ReportList *reports, Main *bmain, Scene *UNUSED(scene), Object *ob, const char *name, int type)
+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);
+ ShaderFxData *new_fx = NULL;
+ const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(type);
- if (ob->type != OB_GPENCIL) {
- BKE_reportf(reports, RPT_WARNING, "Effect cannot be added to object '%s'", ob->id.name + 2);
- return NULL;
- }
+ if (ob->type != OB_GPENCIL) {
+ BKE_reportf(reports, RPT_WARNING, "Effect cannot be added to object '%s'", ob->id.name + 2);
+ return NULL;
+ }
- if (fxi->flags & eShaderFxTypeFlag_Single) {
- if (BKE_shaderfx_findByType(ob, type)) {
- BKE_report(reports, RPT_WARNING, "Only one Effect of this type is allowed");
- return NULL;
- }
- }
+ if (fxi->flags & eShaderFxTypeFlag_Single) {
+ if (BKE_shaderfx_findByType(ob, type)) {
+ BKE_report(reports, RPT_WARNING, "Only one Effect of this type is allowed");
+ return NULL;
+ }
+ }
- /* get new effect data to add */
- new_fx = BKE_shaderfx_new(type);
+ /* get new effect data to add */
+ new_fx = BKE_shaderfx_new(type);
- BLI_addtail(&ob->shader_fx, new_fx);
+ BLI_addtail(&ob->shader_fx, new_fx);
- if (name) {
- BLI_strncpy_utf8(new_fx->name, name, sizeof(new_fx->name));
- }
+ if (name) {
+ BLI_strncpy_utf8(new_fx->name, name, sizeof(new_fx->name));
+ }
- /* make sure effect data has unique name */
- BKE_shaderfx_unique_name(&ob->shader_fx, new_fx);
+ /* make sure effect data has unique name */
+ BKE_shaderfx_unique_name(&ob->shader_fx, new_fx);
- bGPdata *gpd = ob->data;
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
- return new_fx;
+ return new_fx;
}
/* Return true if the object has a effect of type 'type' other than
* the shaderfx pointed to be 'exclude', otherwise returns false. */
-static bool UNUSED_FUNCTION(object_has_shaderfx)(
- const Object *ob, const ShaderFxData *exclude,
- ShaderFxType type)
+static bool UNUSED_FUNCTION(object_has_shaderfx)(const Object *ob,
+ const ShaderFxData *exclude,
+ ShaderFxType type)
{
- ShaderFxData *fx;
+ ShaderFxData *fx;
- for (fx = ob->shader_fx.first; fx; fx = fx->next) {
- if ((fx != exclude) && (fx->type == type))
- return true;
- }
+ for (fx = ob->shader_fx.first; fx; fx = fx->next) {
+ if ((fx != exclude) && (fx->type == type))
+ return true;
+ }
- return false;
+ return false;
}
-static bool object_shaderfx_remove(
- Main *bmain, Object *ob, ShaderFxData *fx,
- bool *UNUSED(r_sort_depsgraph))
+static bool object_shaderfx_remove(Main *bmain,
+ Object *ob,
+ ShaderFxData *fx,
+ bool *UNUSED(r_sort_depsgraph))
{
- /* It seems on rapid delete it is possible to
- * get called twice on same effect, so make
- * sure it is in list. */
- if (BLI_findindex(&ob->shader_fx, fx) == -1) {
- return 0;
- }
+ /* It seems on rapid delete it is possible to
+ * get called twice on same effect, so make
+ * sure it is in list. */
+ if (BLI_findindex(&ob->shader_fx, fx) == -1) {
+ return 0;
+ }
- DEG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
- BLI_remlink(&ob->shader_fx, fx);
- BKE_shaderfx_free(fx);
- BKE_object_free_derived_caches(ob);
+ BLI_remlink(&ob->shader_fx, fx);
+ BKE_shaderfx_free(fx);
+ BKE_object_free_derived_caches(ob);
- return 1;
+ return 1;
}
bool ED_object_shaderfx_remove(ReportList *reports, Main *bmain, Object *ob, ShaderFxData *fx)
{
- bool sort_depsgraph = false;
- bool ok;
+ bool sort_depsgraph = false;
+ bool ok;
- ok = object_shaderfx_remove(bmain, ob, fx, &sort_depsgraph);
+ ok = object_shaderfx_remove(bmain, ob, fx, &sort_depsgraph);
- if (!ok) {
- BKE_reportf(reports, RPT_ERROR, "Effect '%s' not in object '%s'", fx->name, ob->id.name);
- return 0;
- }
+ if (!ok) {
+ BKE_reportf(reports, RPT_ERROR, "Effect '%s' not in object '%s'", fx->name, ob->id.name);
+ return 0;
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
- return 1;
+ return 1;
}
void ED_object_shaderfx_clear(Main *bmain, Object *ob)
{
- ShaderFxData *fx = ob->shader_fx.first;
- bool sort_depsgraph = false;
+ ShaderFxData *fx = ob->shader_fx.first;
+ bool sort_depsgraph = false;
- if (!fx)
- return;
+ if (!fx)
+ return;
- while (fx) {
- ShaderFxData *next_fx;
+ while (fx) {
+ ShaderFxData *next_fx;
- next_fx = fx->next;
+ next_fx = fx->next;
- object_shaderfx_remove(bmain, ob, fx, &sort_depsgraph);
+ object_shaderfx_remove(bmain, ob, fx, &sort_depsgraph);
- fx = next_fx;
- }
+ fx = next_fx;
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
}
int ED_object_shaderfx_move_up(ReportList *UNUSED(reports), Object *ob, ShaderFxData *fx)
{
- if (fx->prev) {
- BLI_remlink(&ob->shader_fx, fx);
- BLI_insertlinkbefore(&ob->shader_fx, fx->prev, fx);
- }
+ if (fx->prev) {
+ BLI_remlink(&ob->shader_fx, fx);
+ BLI_insertlinkbefore(&ob->shader_fx, fx->prev, fx);
+ }
- return 1;
+ return 1;
}
int ED_object_shaderfx_move_down(ReportList *UNUSED(reports), Object *ob, ShaderFxData *fx)
{
- if (fx->next) {
- BLI_remlink(&ob->shader_fx, fx);
- BLI_insertlinkafter(&ob->shader_fx, fx->next, fx);
- }
+ if (fx->next) {
+ BLI_remlink(&ob->shader_fx, fx);
+ BLI_insertlinkafter(&ob->shader_fx, fx->next, fx);
+ }
- return 1;
+ return 1;
}
/************************ add effect operator *********************/
static int shaderfx_add_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- int type = RNA_enum_get(op->ptr, "type");
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ int type = RNA_enum_get(op->ptr, "type");
- if (!ED_object_shaderfx_add(op->reports, bmain, scene, ob, NULL, type))
- return OPERATOR_CANCELLED;
+ if (!ED_object_shaderfx_add(op->reports, bmain, scene, ob, NULL, type))
+ return OPERATOR_CANCELLED;
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static const EnumPropertyItem *shaderfx_add_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *shaderfx_add_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- Object *ob = ED_object_active_context(C);
- EnumPropertyItem *item = NULL;
- const EnumPropertyItem *fx_item, *group_item = NULL;
- const ShaderFxTypeInfo *mti;
- int totitem = 0, a;
-
- if (!ob)
- return rna_enum_object_shaderfx_type_items;
-
- 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);
-
- if (mti->flags & eShaderFxTypeFlag_NoUserAdd)
- continue;
- }
- else {
- group_item = fx_item;
- fx_item = NULL;
-
- continue;
- }
-
- if (group_item) {
- RNA_enum_item_add(&item, &totitem, group_item);
- group_item = NULL;
- }
-
- RNA_enum_item_add(&item, &totitem, fx_item);
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ Object *ob = ED_object_active_context(C);
+ EnumPropertyItem *item = NULL;
+ const EnumPropertyItem *fx_item, *group_item = NULL;
+ const ShaderFxTypeInfo *mti;
+ int totitem = 0, a;
+
+ if (!ob)
+ return rna_enum_object_shaderfx_type_items;
+
+ 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);
+
+ if (mti->flags & eShaderFxTypeFlag_NoUserAdd)
+ continue;
+ }
+ else {
+ group_item = fx_item;
+ fx_item = NULL;
+
+ continue;
+ }
+
+ if (group_item) {
+ RNA_enum_item_add(&item, &totitem, group_item);
+ group_item = NULL;
+ }
+
+ RNA_enum_item_add(&item, &totitem, fx_item);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
void OBJECT_OT_shaderfx_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Effect";
- ot->description = "Add a visual effect to the active object";
- ot->idname = "OBJECT_OT_shaderfx_add";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = shaderfx_add_exec;
- ot->poll = ED_operator_object_active_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_shaderfx_type_items, eShaderFxType_Blur, "Type", "");
- RNA_def_enum_funcs(ot->prop, shaderfx_add_itemf);
- RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_ID); /* Abused, for "Light"... */
+ /* identifiers */
+ ot->name = "Add Effect";
+ ot->description = "Add a visual effect to the active object";
+ ot->idname = "OBJECT_OT_shaderfx_add";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = shaderfx_add_exec;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", rna_enum_object_shaderfx_type_items, eShaderFxType_Blur, "Type", "");
+ RNA_def_enum_funcs(ot->prop, shaderfx_add_itemf);
+ RNA_def_property_translation_context(ot->prop,
+ BLT_I18NCONTEXT_ID_ID); /* Abused, for "Light"... */
}
/************************ generic functions for operators using names and data context *********************/
static bool edit_shaderfx_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "shaderfx", rna_type);
- Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
-
- if (!ptr.data) {
- CTX_wm_operator_poll_msg_set(C, "Context missing 'shaderfx'");
- return 0;
- }
-
- if (!ob || ID_IS_LINKED(ob)) return 0;
- if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) return 0;
- if (ptr.id.data && ID_IS_LINKED(ptr.id.data)) return 0;
-
- if (ID_IS_STATIC_OVERRIDE(ob)) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit shaderfxs coming from static override");
- return (((ShaderFxData *)ptr.data)->flag & eShaderFxFlag_StaticOverride_Local) != 0;
- }
-
- return 1;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "shaderfx", rna_type);
+ Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
+
+ if (!ptr.data) {
+ CTX_wm_operator_poll_msg_set(C, "Context missing 'shaderfx'");
+ return 0;
+ }
+
+ if (!ob || ID_IS_LINKED(ob))
+ return 0;
+ if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0)
+ return 0;
+ if (ptr.id.data && ID_IS_LINKED(ptr.id.data))
+ return 0;
+
+ if (ID_IS_STATIC_OVERRIDE(ob)) {
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit shaderfxs coming from static override");
+ return (((ShaderFxData *)ptr.data)->flag & eShaderFxFlag_StaticOverride_Local) != 0;
+ }
+
+ return 1;
}
static bool edit_shaderfx_poll(bContext *C)
{
- return edit_shaderfx_poll_generic(C, &RNA_ShaderFx, 0);
+ return edit_shaderfx_poll_generic(C, &RNA_ShaderFx, 0);
}
static void edit_shaderfx_properties(wmOperatorType *ot)
{
- PropertyRNA *prop = RNA_def_string(ot->srna, "shaderfx", NULL, MAX_NAME, "Shader", "Name of the shaderfx to edit");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop = RNA_def_string(
+ ot->srna, "shaderfx", NULL, MAX_NAME, "Shader", "Name of the shaderfx to edit");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
static int edit_shaderfx_invoke_properties(bContext *C, wmOperator *op)
{
- ShaderFxData *fx;
-
- if (RNA_struct_property_is_set(op->ptr, "shaderfx")) {
- return true;
- }
- else {
- PointerRNA ptr = CTX_data_pointer_get_type(C, "shaderfx", &RNA_ShaderFx);
- if (ptr.data) {
- fx = ptr.data;
- RNA_string_set(op->ptr, "shaderfx", fx->name);
- return true;
- }
- }
-
- return false;
+ ShaderFxData *fx;
+
+ if (RNA_struct_property_is_set(op->ptr, "shaderfx")) {
+ return true;
+ }
+ else {
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "shaderfx", &RNA_ShaderFx);
+ if (ptr.data) {
+ fx = ptr.data;
+ RNA_string_set(op->ptr, "shaderfx", fx->name);
+ return true;
+ }
+ }
+
+ return false;
}
static ShaderFxData *edit_shaderfx_property_get(wmOperator *op, Object *ob, int type)
{
- char shaderfx_name[MAX_NAME];
- ShaderFxData *fx;
- RNA_string_get(op->ptr, "shaderfx", shaderfx_name);
+ char shaderfx_name[MAX_NAME];
+ ShaderFxData *fx;
+ RNA_string_get(op->ptr, "shaderfx", shaderfx_name);
- fx = BKE_shaderfx_findByName(ob, shaderfx_name);
+ fx = BKE_shaderfx_findByName(ob, shaderfx_name);
- if (fx && type != 0 && fx->type != type)
- fx = NULL;
+ if (fx && type != 0 && fx->type != type)
+ fx = NULL;
- return fx;
+ return fx;
}
/************************ remove shaderfx operator *********************/
static int shaderfx_remove_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_active_context(C);
- ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0);
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
+ ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0);
- if (!fx || !ED_object_shaderfx_remove(op->reports, bmain, ob, fx))
- return OPERATOR_CANCELLED;
+ if (!fx || !ED_object_shaderfx_remove(op->reports, bmain, ob, fx))
+ return OPERATOR_CANCELLED;
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int shaderfx_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_shaderfx_invoke_properties(C, op))
- return shaderfx_remove_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_shaderfx_invoke_properties(C, op))
+ return shaderfx_remove_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_shaderfx_remove(wmOperatorType *ot)
{
- ot->name = "Remove Grease Pencil Modifier";
- ot->description = "Remove a shaderfx from the active grease pencil object";
- ot->idname = "OBJECT_OT_shaderfx_remove";
+ ot->name = "Remove Grease Pencil Modifier";
+ ot->description = "Remove a shaderfx from the active grease pencil object";
+ ot->idname = "OBJECT_OT_shaderfx_remove";
- ot->invoke = shaderfx_remove_invoke;
- ot->exec = shaderfx_remove_exec;
- ot->poll = edit_shaderfx_poll;
+ ot->invoke = shaderfx_remove_invoke;
+ ot->exec = shaderfx_remove_exec;
+ ot->poll = edit_shaderfx_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_shaderfx_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_shaderfx_properties(ot);
}
/************************ move up shaderfx operator *********************/
static int shaderfx_move_up_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0);
- if (!fx || !ED_object_shaderfx_move_up(op->reports, ob, fx))
- return OPERATOR_CANCELLED;
+ if (!fx || !ED_object_shaderfx_move_up(op->reports, ob, fx))
+ return OPERATOR_CANCELLED;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int shaderfx_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_shaderfx_invoke_properties(C, op))
- return shaderfx_move_up_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_shaderfx_invoke_properties(C, op))
+ return shaderfx_move_up_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_shaderfx_move_up(wmOperatorType *ot)
{
- ot->name = "Move Up Modifier";
- ot->description = "Move shaderfx up in the stack";
- ot->idname = "OBJECT_OT_shaderfx_move_up";
+ ot->name = "Move Up Modifier";
+ ot->description = "Move shaderfx up in the stack";
+ ot->idname = "OBJECT_OT_shaderfx_move_up";
- ot->invoke = shaderfx_move_up_invoke;
- ot->exec = shaderfx_move_up_exec;
- ot->poll = edit_shaderfx_poll;
+ ot->invoke = shaderfx_move_up_invoke;
+ ot->exec = shaderfx_move_up_exec;
+ ot->poll = edit_shaderfx_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_shaderfx_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_shaderfx_properties(ot);
}
/************************ move down shaderfx operator *********************/
static int shaderfx_move_down_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0);
- if (!fx || !ED_object_shaderfx_move_down(op->reports, ob, fx))
- return OPERATOR_CANCELLED;
+ if (!fx || !ED_object_shaderfx_move_down(op->reports, ob, fx))
+ return OPERATOR_CANCELLED;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int shaderfx_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_shaderfx_invoke_properties(C, op))
- return shaderfx_move_down_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_shaderfx_invoke_properties(C, op))
+ return shaderfx_move_down_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_shaderfx_move_down(wmOperatorType *ot)
{
- ot->name = "Move Down Modifier";
- ot->description = "Move shaderfx down in the stack";
- ot->idname = "OBJECT_OT_shaderfx_move_down";
+ ot->name = "Move Down Modifier";
+ ot->description = "Move shaderfx down in the stack";
+ ot->idname = "OBJECT_OT_shaderfx_move_down";
- ot->invoke = shaderfx_move_down_invoke;
- ot->exec = shaderfx_move_down_exec;
- ot->poll = edit_shaderfx_poll;
+ ot->invoke = shaderfx_move_down_invoke;
+ ot->exec = shaderfx_move_down_exec;
+ ot->poll = edit_shaderfx_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_shaderfx_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_shaderfx_properties(ot);
}
diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c
index d445177f236..aa0c6cbeef4 100644
--- a/source/blender/editors/object/object_shapekey.c
+++ b/source/blender/editors/object/object_shapekey.c
@@ -21,14 +21,13 @@
* \ingroup edobj
*/
-
#include <math.h>
#include <string.h>
#ifndef WIN32
-#include <unistd.h>
+# include <unistd.h>
#else
-#include <io.h>
+# include <io.h>
#endif
#include "MEM_guardedalloc.h"
@@ -54,7 +53,7 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-#include "BLI_sys_types.h" // for intptr_t support
+#include "BLI_sys_types.h" // for intptr_t support
#include "ED_object.h"
#include "ED_mesh.h"
@@ -71,429 +70,434 @@
static void ED_object_shape_key_add(bContext *C, Object *ob, const bool from_mix)
{
- Main *bmain = CTX_data_main(C);
- KeyBlock *kb;
- if ((kb = BKE_object_shapekey_insert(bmain, ob, NULL, from_mix))) {
- Key *key = BKE_key_from_object(ob);
- /* for absolute shape keys, new keys may not be added last */
- ob->shapenr = BLI_findindex(&key->block, kb) + 1;
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- }
+ Main *bmain = CTX_data_main(C);
+ KeyBlock *kb;
+ if ((kb = BKE_object_shapekey_insert(bmain, ob, NULL, from_mix))) {
+ Key *key = BKE_key_from_object(ob);
+ /* for absolute shape keys, new keys may not be added last */
+ ob->shapenr = BLI_findindex(&key->block, kb) + 1;
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
}
/*********************** remove shape key ***********************/
static bool object_shapekey_remove(Main *bmain, Object *ob)
{
- KeyBlock *kb;
- Key *key = BKE_key_from_object(ob);
+ KeyBlock *kb;
+ Key *key = BKE_key_from_object(ob);
- if (key == NULL) {
- return false;
- }
+ if (key == NULL) {
+ return false;
+ }
- kb = BLI_findlink(&key->block, ob->shapenr - 1);
- if (kb) {
- return BKE_object_shapekey_remove(bmain, ob, kb);
- }
+ kb = BLI_findlink(&key->block, ob->shapenr - 1);
+ if (kb) {
+ return BKE_object_shapekey_remove(bmain, ob, kb);
+ }
- return false;
+ return false;
}
-static bool object_shape_key_mirror(bContext *C, Object *ob,
- int *r_totmirr, int *r_totfail, bool use_topology)
+static bool object_shape_key_mirror(
+ bContext *C, Object *ob, int *r_totmirr, int *r_totfail, bool use_topology)
{
- KeyBlock *kb;
- Key *key;
- int totmirr = 0, totfail = 0;
-
- *r_totmirr = *r_totfail = 0;
-
- key = BKE_key_from_object(ob);
- if (key == NULL)
- return 0;
-
- kb = BLI_findlink(&key->block, ob->shapenr - 1);
-
- if (kb) {
- char *tag_elem = MEM_callocN(sizeof(char) * kb->totelem, "shape_key_mirror");
-
-
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
- MVert *mv;
- int i1, i2;
- float *fp1, *fp2;
- float tvec[3];
-
- ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 's');
-
- for (i1 = 0, mv = me->mvert; i1 < me->totvert; i1++, mv++) {
- i2 = mesh_get_x_mirror_vert(ob, NULL, i1, use_topology);
- if (i2 == i1) {
- fp1 = ((float *)kb->data) + i1 * 3;
- fp1[0] = -fp1[0];
- tag_elem[i1] = 1;
- totmirr++;
- }
- else if (i2 != -1) {
- if (tag_elem[i1] == 0 && tag_elem[i2] == 0) {
- fp1 = ((float *)kb->data) + i1 * 3;
- fp2 = ((float *)kb->data) + i2 * 3;
-
- copy_v3_v3(tvec, fp1);
- copy_v3_v3(fp1, fp2);
- copy_v3_v3(fp2, tvec);
-
- /* flip x axis */
- fp1[0] = -fp1[0];
- fp2[0] = -fp2[0];
- totmirr++;
- }
- tag_elem[i1] = tag_elem[i2] = 1;
- }
- else {
- totfail++;
- }
- }
-
- ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 'e');
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = ob->data;
- int i1, i2;
- float *fp1, *fp2;
- int u, v, w;
- /* half but found up odd value */
- const int pntsu_half = (lt->pntsu / 2) + (lt->pntsu % 2);
-
- /* currently editmode isn't supported by mesh so
- * ignore here for now too */
-
- /* if (lt->editlatt) lt = lt->editlatt->latt; */
-
- for (w = 0; w < lt->pntsw; w++) {
- for (v = 0; v < lt->pntsv; v++) {
- for (u = 0; u < pntsu_half; u++) {
- int u_inv = (lt->pntsu - 1) - u;
- float tvec[3];
- if (u == u_inv) {
- i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
- fp1 = ((float *)kb->data) + i1 * 3;
- fp1[0] = -fp1[0];
- totmirr++;
- }
- else {
- i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
- i2 = BKE_lattice_index_from_uvw(lt, u_inv, v, w);
-
- fp1 = ((float *)kb->data) + i1 * 3;
- fp2 = ((float *)kb->data) + i2 * 3;
-
- copy_v3_v3(tvec, fp1);
- copy_v3_v3(fp1, fp2);
- copy_v3_v3(fp2, tvec);
- fp1[0] = -fp1[0];
- fp2[0] = -fp2[0];
- totmirr++;
- }
- }
- }
- }
- }
-
- MEM_freeN(tag_elem);
- }
-
- *r_totmirr = totmirr;
- *r_totfail = totfail;
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- return 1;
+ KeyBlock *kb;
+ Key *key;
+ int totmirr = 0, totfail = 0;
+
+ *r_totmirr = *r_totfail = 0;
+
+ key = BKE_key_from_object(ob);
+ if (key == NULL)
+ return 0;
+
+ kb = BLI_findlink(&key->block, ob->shapenr - 1);
+
+ if (kb) {
+ char *tag_elem = MEM_callocN(sizeof(char) * kb->totelem, "shape_key_mirror");
+
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ MVert *mv;
+ int i1, i2;
+ float *fp1, *fp2;
+ float tvec[3];
+
+ ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 's');
+
+ for (i1 = 0, mv = me->mvert; i1 < me->totvert; i1++, mv++) {
+ i2 = mesh_get_x_mirror_vert(ob, NULL, i1, use_topology);
+ if (i2 == i1) {
+ fp1 = ((float *)kb->data) + i1 * 3;
+ fp1[0] = -fp1[0];
+ tag_elem[i1] = 1;
+ totmirr++;
+ }
+ else if (i2 != -1) {
+ if (tag_elem[i1] == 0 && tag_elem[i2] == 0) {
+ fp1 = ((float *)kb->data) + i1 * 3;
+ fp2 = ((float *)kb->data) + i2 * 3;
+
+ copy_v3_v3(tvec, fp1);
+ copy_v3_v3(fp1, fp2);
+ copy_v3_v3(fp2, tvec);
+
+ /* flip x axis */
+ fp1[0] = -fp1[0];
+ fp2[0] = -fp2[0];
+ totmirr++;
+ }
+ tag_elem[i1] = tag_elem[i2] = 1;
+ }
+ else {
+ totfail++;
+ }
+ }
+
+ ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 'e');
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = ob->data;
+ int i1, i2;
+ float *fp1, *fp2;
+ int u, v, w;
+ /* half but found up odd value */
+ const int pntsu_half = (lt->pntsu / 2) + (lt->pntsu % 2);
+
+ /* currently editmode isn't supported by mesh so
+ * ignore here for now too */
+
+ /* if (lt->editlatt) lt = lt->editlatt->latt; */
+
+ for (w = 0; w < lt->pntsw; w++) {
+ for (v = 0; v < lt->pntsv; v++) {
+ for (u = 0; u < pntsu_half; u++) {
+ int u_inv = (lt->pntsu - 1) - u;
+ float tvec[3];
+ if (u == u_inv) {
+ i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
+ fp1 = ((float *)kb->data) + i1 * 3;
+ fp1[0] = -fp1[0];
+ totmirr++;
+ }
+ else {
+ i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
+ i2 = BKE_lattice_index_from_uvw(lt, u_inv, v, w);
+
+ fp1 = ((float *)kb->data) + i1 * 3;
+ fp2 = ((float *)kb->data) + i2 * 3;
+
+ copy_v3_v3(tvec, fp1);
+ copy_v3_v3(fp1, fp2);
+ copy_v3_v3(fp2, tvec);
+ fp1[0] = -fp1[0];
+ fp2[0] = -fp2[0];
+ totmirr++;
+ }
+ }
+ }
+ }
+ }
+
+ MEM_freeN(tag_elem);
+ }
+
+ *r_totmirr = totmirr;
+ *r_totfail = totfail;
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return 1;
}
/********************** shape key operators *********************/
static bool shape_key_mode_poll(bContext *C)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
- return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) && ob->mode != OB_MODE_EDIT);
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) && ob->mode != OB_MODE_EDIT);
}
static bool shape_key_mode_exists_poll(bContext *C)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
- /* same as shape_key_mode_poll */
- return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) && ob->mode != OB_MODE_EDIT) &&
- /* check a keyblock exists */
- (BKE_keyblock_from_object(ob) != NULL);
+ /* same as shape_key_mode_poll */
+ return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) && ob->mode != OB_MODE_EDIT) &&
+ /* check a keyblock exists */
+ (BKE_keyblock_from_object(ob) != NULL);
}
static bool shape_key_move_poll(bContext *C)
{
- /* Same as shape_key_mode_exists_poll above, but ensure we have at least two shapes! */
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
- Key *key = BKE_key_from_object(ob);
+ /* Same as shape_key_mode_exists_poll above, but ensure we have at least two shapes! */
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ Key *key = BKE_key_from_object(ob);
- return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) &&
- ob->mode != OB_MODE_EDIT && key && key->totkey > 1);
+ return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) && ob->mode != OB_MODE_EDIT &&
+ key && key->totkey > 1);
}
static bool shape_key_poll(bContext *C)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
- return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data));
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data));
}
static int shape_key_add_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- const bool from_mix = RNA_boolean_get(op->ptr, "from_mix");
+ Object *ob = ED_object_context(C);
+ const bool from_mix = RNA_boolean_get(op->ptr, "from_mix");
- ED_object_shape_key_add(C, ob, from_mix);
+ ED_object_shape_key_add(C, ob, from_mix);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(CTX_data_main(C));
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(CTX_data_main(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_shape_key_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Shape Key";
- ot->idname = "OBJECT_OT_shape_key_add";
- ot->description = "Add shape key to the object";
-
- /* api callbacks */
- ot->poll = shape_key_mode_poll;
- ot->exec = shape_key_add_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "from_mix", true, "From Mix", "Create the new shape key from the existing mix of keys");
+ /* identifiers */
+ ot->name = "Add Shape Key";
+ ot->idname = "OBJECT_OT_shape_key_add";
+ ot->description = "Add shape key to the object";
+
+ /* api callbacks */
+ ot->poll = shape_key_mode_poll;
+ ot->exec = shape_key_add_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "from_mix",
+ true,
+ "From Mix",
+ "Create the new shape key from the existing mix of keys");
}
static int shape_key_remove_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_context(C);
- bool changed = false;
-
- if (RNA_boolean_get(op->ptr, "all")) {
- changed = BKE_object_shapekey_free(bmain, ob);
- }
- else {
- changed = object_shapekey_remove(bmain, ob);
- }
-
- if (changed) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(CTX_data_main(C));
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_context(C);
+ bool changed = false;
+
+ if (RNA_boolean_get(op->ptr, "all")) {
+ changed = BKE_object_shapekey_free(bmain, ob);
+ }
+ else {
+ changed = object_shapekey_remove(bmain, ob);
+ }
+
+ if (changed) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(CTX_data_main(C));
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void OBJECT_OT_shape_key_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Shape Key";
- ot->idname = "OBJECT_OT_shape_key_remove";
- ot->description = "Remove shape key from the object";
+ /* identifiers */
+ ot->name = "Remove Shape Key";
+ ot->idname = "OBJECT_OT_shape_key_remove";
+ ot->description = "Remove shape key from the object";
- /* api callbacks */
- ot->poll = shape_key_mode_exists_poll;
- ot->exec = shape_key_remove_exec;
+ /* api callbacks */
+ ot->poll = shape_key_mode_exists_poll;
+ ot->exec = shape_key_remove_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "all", 0, "All", "Remove all shape keys");
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 0, "All", "Remove all shape keys");
}
static int shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- Key *key = BKE_key_from_object(ob);
- KeyBlock *kb = BKE_keyblock_from_object(ob);
+ Object *ob = ED_object_context(C);
+ Key *key = BKE_key_from_object(ob);
+ KeyBlock *kb = BKE_keyblock_from_object(ob);
- if (!key || !kb)
- return OPERATOR_CANCELLED;
+ if (!key || !kb)
+ return OPERATOR_CANCELLED;
- for (kb = key->block.first; kb; kb = kb->next)
- kb->curval = 0.0f;
+ for (kb = key->block.first; kb; kb = kb->next)
+ kb->curval = 0.0f;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_shape_key_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Shape Keys";
- ot->description = "Clear weights for all shape keys";
- ot->idname = "OBJECT_OT_shape_key_clear";
+ /* identifiers */
+ ot->name = "Clear Shape Keys";
+ ot->description = "Clear weights for all shape keys";
+ ot->idname = "OBJECT_OT_shape_key_clear";
- /* api callbacks */
- ot->poll = shape_key_poll;
- ot->exec = shape_key_clear_exec;
+ /* api callbacks */
+ ot->poll = shape_key_poll;
+ ot->exec = shape_key_clear_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* starting point and step size could be optional */
static int shape_key_retime_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- Key *key = BKE_key_from_object(ob);
- KeyBlock *kb = BKE_keyblock_from_object(ob);
- float cfra = 0.0f;
+ Object *ob = ED_object_context(C);
+ Key *key = BKE_key_from_object(ob);
+ KeyBlock *kb = BKE_keyblock_from_object(ob);
+ float cfra = 0.0f;
- if (!key || !kb)
- return OPERATOR_CANCELLED;
+ if (!key || !kb)
+ return OPERATOR_CANCELLED;
- for (kb = key->block.first; kb; kb = kb->next) {
- kb->pos = cfra;
- cfra += 0.1f;
- }
+ for (kb = key->block.first; kb; kb = kb->next) {
+ kb->pos = cfra;
+ cfra += 0.1f;
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_shape_key_retime(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Re-Time Shape Keys";
- ot->description = "Resets the timing for absolute shape keys";
- ot->idname = "OBJECT_OT_shape_key_retime";
+ /* identifiers */
+ ot->name = "Re-Time Shape Keys";
+ ot->description = "Resets the timing for absolute shape keys";
+ ot->idname = "OBJECT_OT_shape_key_retime";
- /* api callbacks */
- ot->poll = shape_key_poll;
- ot->exec = shape_key_retime_exec;
+ /* api callbacks */
+ ot->poll = shape_key_poll;
+ ot->exec = shape_key_retime_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int shape_key_mirror_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- int totmirr = 0, totfail = 0;
- bool use_topology = RNA_boolean_get(op->ptr, "use_topology");
+ Object *ob = ED_object_context(C);
+ int totmirr = 0, totfail = 0;
+ bool use_topology = RNA_boolean_get(op->ptr, "use_topology");
- if (!object_shape_key_mirror(C, ob, &totmirr, &totfail, use_topology))
- return OPERATOR_CANCELLED;
+ if (!object_shape_key_mirror(C, ob, &totmirr, &totfail, use_topology))
+ return OPERATOR_CANCELLED;
- ED_mesh_report_mirror(op, totmirr, totfail);
+ ED_mesh_report_mirror(op, totmirr, totfail);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_shape_key_mirror(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Mirror Shape Key";
- ot->idname = "OBJECT_OT_shape_key_mirror";
- ot->description = "Mirror the current shape key along the local X axis";
-
- /* api callbacks */
- ot->poll = shape_key_mode_poll;
- ot->exec = shape_key_mirror_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "use_topology", 0, "Topology Mirror",
- "Use topology based mirroring (for when both sides of mesh have matching, unique topology)");
+ /* identifiers */
+ ot->name = "Mirror Shape Key";
+ ot->idname = "OBJECT_OT_shape_key_mirror";
+ ot->description = "Mirror the current shape key along the local X axis";
+
+ /* api callbacks */
+ ot->poll = shape_key_mode_poll;
+ ot->exec = shape_key_mirror_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(
+ ot->srna,
+ "use_topology",
+ 0,
+ "Topology Mirror",
+ "Use topology based mirroring (for when both sides of mesh have matching, unique topology)");
}
-
enum {
- KB_MOVE_TOP = -2,
- KB_MOVE_UP = -1,
- KB_MOVE_DOWN = 1,
- KB_MOVE_BOTTOM = 2,
+ KB_MOVE_TOP = -2,
+ KB_MOVE_UP = -1,
+ KB_MOVE_DOWN = 1,
+ KB_MOVE_BOTTOM = 2,
};
static int shape_key_move_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
-
- Key *key = BKE_key_from_object(ob);
- const int type = RNA_enum_get(op->ptr, "type");
- const int totkey = key->totkey;
- const int act_index = ob->shapenr - 1;
- int new_index;
-
- switch (type) {
- case KB_MOVE_TOP:
- /* Replace the ref key only if we're at the top already (only for relative keys) */
- new_index = (ELEM(act_index, 0, 1) || key->type == KEY_NORMAL) ? 0 : 1;
- break;
- case KB_MOVE_BOTTOM:
- new_index = totkey - 1;
- break;
- case KB_MOVE_UP:
- case KB_MOVE_DOWN:
- default:
- new_index = (totkey + act_index + type) % totkey;
- break;
- }
-
- if (!BKE_keyblock_move(ob, act_index, new_index)) {
- return OPERATOR_CANCELLED;
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- return OPERATOR_FINISHED;
+ Object *ob = ED_object_context(C);
+
+ Key *key = BKE_key_from_object(ob);
+ const int type = RNA_enum_get(op->ptr, "type");
+ const int totkey = key->totkey;
+ const int act_index = ob->shapenr - 1;
+ int new_index;
+
+ switch (type) {
+ case KB_MOVE_TOP:
+ /* Replace the ref key only if we're at the top already (only for relative keys) */
+ new_index = (ELEM(act_index, 0, 1) || key->type == KEY_NORMAL) ? 0 : 1;
+ break;
+ case KB_MOVE_BOTTOM:
+ new_index = totkey - 1;
+ break;
+ case KB_MOVE_UP:
+ case KB_MOVE_DOWN:
+ default:
+ new_index = (totkey + act_index + type) % totkey;
+ break;
+ }
+
+ if (!BKE_keyblock_move(ob, act_index, new_index)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_shape_key_move(wmOperatorType *ot)
{
- static const EnumPropertyItem slot_move[] = {
- {KB_MOVE_TOP, "TOP", 0, "Top", "Top of the list"},
- {KB_MOVE_UP, "UP", 0, "Up", ""},
- {KB_MOVE_DOWN, "DOWN", 0, "Down", ""},
- {KB_MOVE_BOTTOM, "BOTTOM", 0, "Bottom", "Bottom of the list"},
- { 0, NULL, 0, NULL, NULL }
- };
-
- /* identifiers */
- ot->name = "Move Shape Key";
- ot->idname = "OBJECT_OT_shape_key_move";
- ot->description = "Move the active shape key up/down in the list";
-
- /* api callbacks */
- ot->poll = shape_key_move_poll;
- ot->exec = shape_key_move_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
+ static const EnumPropertyItem slot_move[] = {
+ {KB_MOVE_TOP, "TOP", 0, "Top", "Top of the list"},
+ {KB_MOVE_UP, "UP", 0, "Up", ""},
+ {KB_MOVE_DOWN, "DOWN", 0, "Down", ""},
+ {KB_MOVE_BOTTOM, "BOTTOM", 0, "Bottom", "Bottom of the list"},
+ {0, NULL, 0, NULL, NULL}};
+
+ /* identifiers */
+ ot->name = "Move Shape Key";
+ ot->idname = "OBJECT_OT_shape_key_move";
+ ot->description = "Move the active shape key up/down in the list";
+
+ /* api callbacks */
+ ot->poll = shape_key_move_poll;
+ ot->exec = shape_key_move_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
}
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index f7a49f3fcb7..f2f6afcac81 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <stdlib.h>
#include <string.h>
@@ -80,321 +79,353 @@
/* clear location of object */
static void object_clear_loc(Object *ob, const bool clear_delta)
{
- /* clear location if not locked */
- if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
- ob->loc[0] = 0.0f;
- if (clear_delta) ob->dloc[0] = 0.0f;
- }
- if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
- ob->loc[1] = 0.0f;
- if (clear_delta) ob->dloc[1] = 0.0f;
- }
- if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
- ob->loc[2] = 0.0f;
- if (clear_delta) ob->dloc[2] = 0.0f;
- }
+ /* clear location if not locked */
+ if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
+ ob->loc[0] = 0.0f;
+ if (clear_delta)
+ ob->dloc[0] = 0.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
+ ob->loc[1] = 0.0f;
+ if (clear_delta)
+ ob->dloc[1] = 0.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
+ ob->loc[2] = 0.0f;
+ if (clear_delta)
+ ob->dloc[2] = 0.0f;
+ }
}
/* clear rotation of object */
static void object_clear_rot(Object *ob, const bool clear_delta)
{
- /* clear rotations that aren't locked */
- if (ob->protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) {
- if (ob->protectflag & OB_LOCK_ROT4D) {
- /* perform clamping on a component by component basis */
- if (ob->rotmode == ROT_MODE_AXISANGLE) {
- if ((ob->protectflag & OB_LOCK_ROTW) == 0) {
- ob->rotAngle = 0.0f;
- if (clear_delta) ob->drotAngle = 0.0f;
- }
- if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
- ob->rotAxis[0] = 0.0f;
- if (clear_delta) ob->drotAxis[0] = 0.0f;
- }
- if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
- ob->rotAxis[1] = 0.0f;
- if (clear_delta) ob->drotAxis[1] = 0.0f;
- }
- if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
- ob->rotAxis[2] = 0.0f;
- if (clear_delta) ob->drotAxis[2] = 0.0f;
- }
-
- /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */
- if (IS_EQF(ob->rotAxis[0], ob->rotAxis[1]) && IS_EQF(ob->rotAxis[1], ob->rotAxis[2]))
- ob->rotAxis[1] = 1.0f;
- if (IS_EQF(ob->drotAxis[0], ob->drotAxis[1]) && IS_EQF(ob->drotAxis[1], ob->drotAxis[2]) && clear_delta)
- ob->drotAxis[1] = 1.0f;
- }
- else if (ob->rotmode == ROT_MODE_QUAT) {
- if ((ob->protectflag & OB_LOCK_ROTW) == 0) {
- ob->quat[0] = 1.0f;
- if (clear_delta) ob->dquat[0] = 1.0f;
- }
- if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
- ob->quat[1] = 0.0f;
- if (clear_delta) ob->dquat[1] = 0.0f;
- }
- if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
- ob->quat[2] = 0.0f;
- if (clear_delta) ob->dquat[2] = 0.0f;
- }
- if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
- ob->quat[3] = 0.0f;
- if (clear_delta) ob->dquat[3] = 0.0f;
- }
- /* TODO: does this quat need normalizing now? */
- }
- else {
- /* the flag may have been set for the other modes, so just ignore the extra flag... */
- if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
- ob->rot[0] = 0.0f;
- if (clear_delta) ob->drot[0] = 0.0f;
- }
- if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
- ob->rot[1] = 0.0f;
- if (clear_delta) ob->drot[1] = 0.0f;
- }
- if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
- ob->rot[2] = 0.0f;
- if (clear_delta) ob->drot[2] = 0.0f;
- }
- }
- }
- else {
- /* perform clamping using euler form (3-components) */
- /* FIXME: deltas are not handled for these cases yet... */
- float eul[3], oldeul[3], quat1[4] = {0};
-
- if (ob->rotmode == ROT_MODE_QUAT) {
- copy_qt_qt(quat1, ob->quat);
- quat_to_eul(oldeul, ob->quat);
- }
- else if (ob->rotmode == ROT_MODE_AXISANGLE) {
- axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, ob->rotAxis, ob->rotAngle);
- }
- else {
- copy_v3_v3(oldeul, ob->rot);
- }
-
- eul[0] = eul[1] = eul[2] = 0.0f;
-
- if (ob->protectflag & OB_LOCK_ROTX)
- eul[0] = oldeul[0];
- if (ob->protectflag & OB_LOCK_ROTY)
- eul[1] = oldeul[1];
- if (ob->protectflag & OB_LOCK_ROTZ)
- eul[2] = oldeul[2];
-
- if (ob->rotmode == ROT_MODE_QUAT) {
- eul_to_quat(ob->quat, eul);
- /* quaternions flip w sign to accumulate rotations correctly */
- if ((quat1[0] < 0.0f && ob->quat[0] > 0.0f) || (quat1[0] > 0.0f && ob->quat[0] < 0.0f)) {
- mul_qt_fl(ob->quat, -1.0f);
- }
- }
- else if (ob->rotmode == ROT_MODE_AXISANGLE) {
- eulO_to_axis_angle(ob->rotAxis, &ob->rotAngle, eul, EULER_ORDER_DEFAULT);
- }
- else {
- copy_v3_v3(ob->rot, eul);
- }
- }
- } // Duplicated in source/blender/editors/armature/editarmature.c
- else {
- if (ob->rotmode == ROT_MODE_QUAT) {
- unit_qt(ob->quat);
- if (clear_delta) unit_qt(ob->dquat);
- }
- else if (ob->rotmode == ROT_MODE_AXISANGLE) {
- unit_axis_angle(ob->rotAxis, &ob->rotAngle);
- if (clear_delta) unit_axis_angle(ob->drotAxis, &ob->drotAngle);
- }
- else {
- zero_v3(ob->rot);
- if (clear_delta) zero_v3(ob->drot);
- }
- }
+ /* clear rotations that aren't locked */
+ if (ob->protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) {
+ if (ob->protectflag & OB_LOCK_ROT4D) {
+ /* perform clamping on a component by component basis */
+ if (ob->rotmode == ROT_MODE_AXISANGLE) {
+ if ((ob->protectflag & OB_LOCK_ROTW) == 0) {
+ ob->rotAngle = 0.0f;
+ if (clear_delta)
+ ob->drotAngle = 0.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
+ ob->rotAxis[0] = 0.0f;
+ if (clear_delta)
+ ob->drotAxis[0] = 0.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
+ ob->rotAxis[1] = 0.0f;
+ if (clear_delta)
+ ob->drotAxis[1] = 0.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
+ ob->rotAxis[2] = 0.0f;
+ if (clear_delta)
+ ob->drotAxis[2] = 0.0f;
+ }
+
+ /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */
+ if (IS_EQF(ob->rotAxis[0], ob->rotAxis[1]) && IS_EQF(ob->rotAxis[1], ob->rotAxis[2]))
+ ob->rotAxis[1] = 1.0f;
+ if (IS_EQF(ob->drotAxis[0], ob->drotAxis[1]) && IS_EQF(ob->drotAxis[1], ob->drotAxis[2]) &&
+ clear_delta)
+ ob->drotAxis[1] = 1.0f;
+ }
+ else if (ob->rotmode == ROT_MODE_QUAT) {
+ if ((ob->protectflag & OB_LOCK_ROTW) == 0) {
+ ob->quat[0] = 1.0f;
+ if (clear_delta)
+ ob->dquat[0] = 1.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
+ ob->quat[1] = 0.0f;
+ if (clear_delta)
+ ob->dquat[1] = 0.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
+ ob->quat[2] = 0.0f;
+ if (clear_delta)
+ ob->dquat[2] = 0.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
+ ob->quat[3] = 0.0f;
+ if (clear_delta)
+ ob->dquat[3] = 0.0f;
+ }
+ /* TODO: does this quat need normalizing now? */
+ }
+ else {
+ /* the flag may have been set for the other modes, so just ignore the extra flag... */
+ if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
+ ob->rot[0] = 0.0f;
+ if (clear_delta)
+ ob->drot[0] = 0.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
+ ob->rot[1] = 0.0f;
+ if (clear_delta)
+ ob->drot[1] = 0.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
+ ob->rot[2] = 0.0f;
+ if (clear_delta)
+ ob->drot[2] = 0.0f;
+ }
+ }
+ }
+ else {
+ /* perform clamping using euler form (3-components) */
+ /* FIXME: deltas are not handled for these cases yet... */
+ float eul[3], oldeul[3], quat1[4] = {0};
+
+ if (ob->rotmode == ROT_MODE_QUAT) {
+ copy_qt_qt(quat1, ob->quat);
+ quat_to_eul(oldeul, ob->quat);
+ }
+ else if (ob->rotmode == ROT_MODE_AXISANGLE) {
+ axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, ob->rotAxis, ob->rotAngle);
+ }
+ else {
+ copy_v3_v3(oldeul, ob->rot);
+ }
+
+ eul[0] = eul[1] = eul[2] = 0.0f;
+
+ if (ob->protectflag & OB_LOCK_ROTX)
+ eul[0] = oldeul[0];
+ if (ob->protectflag & OB_LOCK_ROTY)
+ eul[1] = oldeul[1];
+ if (ob->protectflag & OB_LOCK_ROTZ)
+ eul[2] = oldeul[2];
+
+ if (ob->rotmode == ROT_MODE_QUAT) {
+ eul_to_quat(ob->quat, eul);
+ /* quaternions flip w sign to accumulate rotations correctly */
+ if ((quat1[0] < 0.0f && ob->quat[0] > 0.0f) || (quat1[0] > 0.0f && ob->quat[0] < 0.0f)) {
+ mul_qt_fl(ob->quat, -1.0f);
+ }
+ }
+ else if (ob->rotmode == ROT_MODE_AXISANGLE) {
+ eulO_to_axis_angle(ob->rotAxis, &ob->rotAngle, eul, EULER_ORDER_DEFAULT);
+ }
+ else {
+ copy_v3_v3(ob->rot, eul);
+ }
+ }
+ } // Duplicated in source/blender/editors/armature/editarmature.c
+ else {
+ if (ob->rotmode == ROT_MODE_QUAT) {
+ unit_qt(ob->quat);
+ if (clear_delta)
+ unit_qt(ob->dquat);
+ }
+ else if (ob->rotmode == ROT_MODE_AXISANGLE) {
+ unit_axis_angle(ob->rotAxis, &ob->rotAngle);
+ if (clear_delta)
+ unit_axis_angle(ob->drotAxis, &ob->drotAngle);
+ }
+ else {
+ zero_v3(ob->rot);
+ if (clear_delta)
+ zero_v3(ob->drot);
+ }
+ }
}
/* clear scale of object */
static void object_clear_scale(Object *ob, const bool clear_delta)
{
- /* clear scale factors which are not locked */
- if ((ob->protectflag & OB_LOCK_SCALEX) == 0) {
- ob->scale[0] = 1.0f;
- if (clear_delta) ob->dscale[0] = 1.0f;
- }
- if ((ob->protectflag & OB_LOCK_SCALEY) == 0) {
- ob->scale[1] = 1.0f;
- if (clear_delta) ob->dscale[1] = 1.0f;
- }
- if ((ob->protectflag & OB_LOCK_SCALEZ) == 0) {
- ob->scale[2] = 1.0f;
- if (clear_delta) ob->dscale[2] = 1.0f;
- }
+ /* clear scale factors which are not locked */
+ if ((ob->protectflag & OB_LOCK_SCALEX) == 0) {
+ ob->scale[0] = 1.0f;
+ if (clear_delta)
+ ob->dscale[0] = 1.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_SCALEY) == 0) {
+ ob->scale[1] = 1.0f;
+ if (clear_delta)
+ ob->dscale[1] = 1.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_SCALEZ) == 0) {
+ ob->scale[2] = 1.0f;
+ if (clear_delta)
+ ob->dscale[2] = 1.0f;
+ }
}
/* --------------- */
/* generic exec for clear-transform operators */
-static int object_clear_transform_generic_exec(bContext *C, wmOperator *op,
+static int object_clear_transform_generic_exec(bContext *C,
+ wmOperator *op,
void (*clear_func)(Object *, const bool),
const char default_ksName[])
{
- Scene *scene = CTX_data_scene(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");
- return OPERATOR_CANCELLED;
- }
-
- /* 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)) {
- /* run provided clearing function */
- clear_func(ob, clear_delta);
-
- ED_autokeyframe_object(C, scene, ob, ks);
-
- /* tag for updates */
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
- }
- CTX_DATA_END;
-
- /* this is needed so children are also updated */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(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");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* 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)) {
+ /* run provided clearing function */
+ clear_func(ob, clear_delta);
+
+ ED_autokeyframe_object(C, scene, ob, ks);
+
+ /* tag for updates */
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+ }
+ CTX_DATA_END;
+
+ /* this is needed so children are also updated */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
}
/* --------------- */
-
static int object_location_clear_exec(bContext *C, wmOperator *op)
{
- return object_clear_transform_generic_exec(C, op, object_clear_loc, ANIM_KS_LOCATION_ID);
+ return object_clear_transform_generic_exec(C, op, object_clear_loc, ANIM_KS_LOCATION_ID);
}
void OBJECT_OT_location_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Location";
- ot->description = "Clear the object's location";
- ot->idname = "OBJECT_OT_location_clear";
-
- /* api callbacks */
- ot->exec = object_location_clear_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
-
- /* properties */
- ot->prop = RNA_def_boolean(ot->srna, "clear_delta", false, "Clear Delta",
- "Clear delta location in addition to clearing the normal location transform");
+ /* identifiers */
+ ot->name = "Clear Location";
+ ot->description = "Clear the object's location";
+ ot->idname = "OBJECT_OT_location_clear";
+
+ /* api callbacks */
+ ot->exec = object_location_clear_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_boolean(
+ ot->srna,
+ "clear_delta",
+ false,
+ "Clear Delta",
+ "Clear delta location in addition to clearing the normal location transform");
}
static int object_rotation_clear_exec(bContext *C, wmOperator *op)
{
- return object_clear_transform_generic_exec(C, op, object_clear_rot, ANIM_KS_ROTATION_ID);
+ return object_clear_transform_generic_exec(C, op, object_clear_rot, ANIM_KS_ROTATION_ID);
}
void OBJECT_OT_rotation_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Rotation";
- ot->description = "Clear the object's rotation";
- ot->idname = "OBJECT_OT_rotation_clear";
-
- /* api callbacks */
- ot->exec = object_rotation_clear_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_boolean(ot->srna, "clear_delta", false, "Clear Delta",
- "Clear delta rotation in addition to clearing the normal rotation transform");
+ /* identifiers */
+ ot->name = "Clear Rotation";
+ ot->description = "Clear the object's rotation";
+ ot->idname = "OBJECT_OT_rotation_clear";
+
+ /* api callbacks */
+ ot->exec = object_rotation_clear_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_boolean(
+ ot->srna,
+ "clear_delta",
+ false,
+ "Clear Delta",
+ "Clear delta rotation in addition to clearing the normal rotation transform");
}
static int object_scale_clear_exec(bContext *C, wmOperator *op)
{
- return object_clear_transform_generic_exec(C, op, object_clear_scale, ANIM_KS_SCALING_ID);
+ return object_clear_transform_generic_exec(C, op, object_clear_scale, ANIM_KS_SCALING_ID);
}
void OBJECT_OT_scale_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Scale";
- ot->description = "Clear the object's scale";
- ot->idname = "OBJECT_OT_scale_clear";
-
- /* api callbacks */
- ot->exec = object_scale_clear_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_boolean(ot->srna, "clear_delta", false, "Clear Delta",
- "Clear delta scale in addition to clearing the normal scale transform");
+ /* identifiers */
+ ot->name = "Clear Scale";
+ ot->description = "Clear the object's scale";
+ ot->idname = "OBJECT_OT_scale_clear";
+
+ /* api callbacks */
+ ot->exec = object_scale_clear_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_boolean(
+ ot->srna,
+ "clear_delta",
+ false,
+ "Clear Delta",
+ "Clear delta scale in addition to clearing the normal scale transform");
}
/* --------------- */
static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- float *v1, *v3;
- float mat[3][3];
+ float *v1, *v3;
+ float mat[3][3];
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (ob->parent) {
- /* vectors pointed to by v1 and v3 will get modified */
- v1 = ob->loc;
- v3 = ob->parentinv[3];
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (ob->parent) {
+ /* vectors pointed to by v1 and v3 will get modified */
+ v1 = ob->loc;
+ v3 = ob->parentinv[3];
- copy_m3_m4(mat, ob->parentinv);
- negate_v3_v3(v3, v1);
- mul_m3_v3(mat, v3);
- }
+ copy_m3_m4(mat, ob->parentinv);
+ negate_v3_v3(v3, v1);
+ mul_m3_v3(mat, v3);
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
- CTX_DATA_END;
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+ CTX_DATA_END;
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_origin_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Origin";
- ot->description = "Clear the object's origin";
- ot->idname = "OBJECT_OT_origin_clear";
+ /* identifiers */
+ ot->name = "Clear Origin";
+ ot->description = "Clear the object's origin";
+ ot->idname = "OBJECT_OT_origin_clear";
- /* api callbacks */
- ot->exec = object_origin_clear_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = object_origin_clear_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/*************************** Apply Transformation ****************************/
@@ -403,885 +434,947 @@ void OBJECT_OT_origin_clear(wmOperatorType *ot)
* should stay in the same place, e.g. for apply-size-rot or object center */
static void ignore_parent_tx(const bContext *C, Main *bmain, Scene *scene, Object *ob)
{
- Object workob;
- Object *ob_child;
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
-
- /* a change was made, adjust the children to compensate */
- for (ob_child = bmain->objects.first; ob_child; ob_child = ob_child->id.next) {
- if (ob_child->parent == ob) {
- BKE_object_apply_mat4(ob_child, ob_child->obmat, true, false);
- BKE_object_workob_calc_parent(depsgraph, scene, ob_child, &workob);
- invert_m4_m4(ob_child->parentinv, workob.obmat);
- }
- }
+ Object workob;
+ Object *ob_child;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
+ /* a change was made, adjust the children to compensate */
+ for (ob_child = bmain->objects.first; ob_child; ob_child = ob_child->id.next) {
+ if (ob_child->parent == ob) {
+ BKE_object_apply_mat4(ob_child, ob_child->obmat, true, false);
+ BKE_object_workob_calc_parent(depsgraph, scene, ob_child, &workob);
+ invert_m4_m4(ob_child->parentinv, workob.obmat);
+ }
+ }
}
-static int apply_objects_internal(
- bContext *C, ReportList *reports,
- bool apply_loc, bool apply_rot, bool apply_scale,
- bool do_props)
+static int apply_objects_internal(bContext *C,
+ ReportList *reports,
+ bool apply_loc,
+ bool apply_rot,
+ bool apply_scale,
+ bool do_props)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale;
- bool changed = true;
-
- /* first check if we can execute */
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (ELEM(ob->type, OB_MESH, OB_ARMATURE, OB_LATTICE, OB_MBALL, OB_CURVE, OB_SURF, OB_FONT, OB_GPENCIL)) {
- ID *obdata = ob->data;
- if (ID_REAL_USERS(obdata) > 1) {
- BKE_reportf(reports, RPT_ERROR,
- "Cannot apply to a multi user: Object \"%s\", %s \"%s\", aborting",
- ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
- changed = false;
- }
-
- if (ID_IS_LINKED(obdata)) {
- BKE_reportf(reports, RPT_ERROR,
- "Cannot apply to library data: Object \"%s\", %s \"%s\", aborting",
- ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
- changed = false;
- }
- }
-
- if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
- ID *obdata = ob->data;
- Curve *cu;
-
- cu = ob->data;
-
- if (((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) && (apply_rot || apply_loc)) {
- BKE_reportf(reports, 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)), obdata->name + 2);
- changed = false;
- }
- if (cu->key) {
- BKE_reportf(reports, 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)), obdata->name + 2);
- changed = false;
- }
- }
-
- if (ob->type == OB_FONT) {
- if (apply_rot || apply_loc) {
- BKE_reportf(reports, RPT_ERROR,
- "Font's can only have scale applied: \"%s\"",
- ob->id.name + 2);
- changed = false;
- }
- }
-
- if (ob->type == OB_GPENCIL) {
- bGPdata *gpd = ob->data;
- if (gpd) {
- if (gpd->layers.first) {
- /* Unsupported configuration */
- bool has_unparented_layers = false;
-
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* Parented layers aren't supported as we can't easily re-evaluate
- * the scene to sample parent movement */
- if (gpl->parent == NULL) {
- has_unparented_layers = true;
- break;
- }
- }
-
- if (has_unparented_layers == false) {
- BKE_reportf(reports, RPT_ERROR,
- "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), gpd->id.name + 2);
- changed = false;
- }
- }
- else {
- /* No layers/data */
- BKE_reportf(reports, 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), gpd->id.name + 2);
- }
- }
- }
-
- if (ob->type == OB_LAMP) {
- Light *la = ob->data;
- if (la->type == LA_AREA) {
- if (apply_rot || apply_loc) {
- BKE_reportf(reports, RPT_ERROR,
- "Area Lights can only have scale applied: \"%s\"",
- ob->id.name + 2);
- changed = false;
- }
- }
- }
- }
- CTX_DATA_END;
-
- if (!changed)
- return OPERATOR_CANCELLED;
-
- changed = false;
-
- /* now execute */
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
-
- /* calculate rotation/scale matrix */
- if (apply_scale && apply_rot)
- BKE_object_to_mat3(ob, rsmat);
- else if (apply_scale)
- BKE_object_scale_to_mat3(ob, rsmat);
- else if (apply_rot) {
- float tmat[3][3], timat[3][3];
-
- /* simple rotation matrix */
- BKE_object_rot_to_mat3(ob, rsmat, true);
-
- /* correct for scale, note mul_m3_m3m3 has swapped args! */
- BKE_object_scale_to_mat3(ob, tmat);
- invert_m3_m3(timat, tmat);
- mul_m3_m3m3(rsmat, timat, rsmat);
- mul_m3_m3m3(rsmat, rsmat, tmat);
- }
- else
- unit_m3(rsmat);
-
- copy_m4_m3(mat, rsmat);
-
- /* calculate translation */
- if (apply_loc) {
- copy_v3_v3(mat[3], ob->loc);
-
- if (!(apply_scale && apply_rot)) {
- float tmat[3][3];
- /* correct for scale and rotation that is still applied */
- BKE_object_to_mat3(ob, obmat);
- invert_m3_m3(iobmat, obmat);
- mul_m3_m3m3(tmat, rsmat, iobmat);
- mul_m3_v3(tmat, mat[3]);
- }
- }
-
- /* apply to object data */
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- if (apply_scale)
- multiresModifier_scale_disp(depsgraph, scene, ob);
-
- /* adjust data */
- BKE_mesh_transform(me, mat, true);
-
- /* update normals */
- BKE_mesh_calc_normals(me);
- }
- else if (ob->type == OB_ARMATURE) {
- ED_armature_transform_apply(bmain, ob, mat, do_props);
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = ob->data;
-
- BKE_lattice_transform(lt, mat, true);
- }
- else if (ob->type == OB_MBALL) {
- MetaBall *mb = ob->data;
- BKE_mball_transform(mb, mat, do_props);
- }
- else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
- Curve *cu = ob->data;
- scale = mat3_to_scale(rsmat);
- BKE_curve_transform_ex(cu, mat, true, do_props, scale);
- }
- else if (ob->type == OB_FONT) {
- Curve *cu = ob->data;
- int i;
-
- scale = mat3_to_scale(rsmat);
-
- for (i = 0; i < cu->totbox; i++) {
- TextBox *tb = &cu->tb[i];
- tb->x *= scale;
- tb->y *= scale;
- tb->w *= scale;
- tb->h *= scale;
- }
-
- if (do_props) {
- cu->fsize *= scale;
- }
- }
- else if (ob->type == OB_GPENCIL) {
- bGPdata *gpd = ob->data;
- BKE_gpencil_transform(gpd, mat);
- }
- else if (ob->type == OB_CAMERA) {
- MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
-
- /* applying scale on camera actually scales clip's reconstruction.
- * of there's clip assigned to camera nothing to do actually.
- */
- if (!clip)
- continue;
-
- if (apply_scale)
- BKE_tracking_reconstruction_scale(&clip->tracking, ob->scale);
- }
- else if (ob->type == OB_EMPTY) {
- /* It's possible for empties too, even though they don't
- * really have obdata, since we can simply apply the maximum
- * scaling to the empty's drawsize.
- *
- * Core Assumptions:
- * 1) Most scaled empties have uniform scaling
- * (i.e. for visibility reasons), AND/OR
- * 2) Preserving non-uniform scaling is not that important,
- * and is something that many users would be willing to
- * sacrifice for having an easy way to do this.
- */
-
- if ((apply_loc == false) &&
- (apply_rot == false) &&
- (apply_scale == true))
- {
- float max_scale = max_fff(fabsf(ob->scale[0]), fabsf(ob->scale[1]), fabsf(ob->scale[2]));
- ob->empty_drawsize *= max_scale;
- }
- }
- else if (ob->type == OB_LAMP) {
- Light *la = ob->data;
- if (la->type != LA_AREA) {
- continue;
- }
-
- bool keeps_aspect_ratio = compare_ff_relative(rsmat[0][0], rsmat[1][1], FLT_EPSILON, 64);
- if ((la->area_shape == LA_AREA_SQUARE) && !keeps_aspect_ratio) {
- la->area_shape = LA_AREA_RECT;
- la->area_sizey = la->area_size;
- }
- else if ((la->area_shape == LA_AREA_DISK) && !keeps_aspect_ratio) {
- la->area_shape = LA_AREA_ELLIPSE;
- la->area_sizey = la->area_size;
- }
-
- la->area_size *= rsmat[0][0];
- la->area_sizey *= rsmat[1][1];
- la->area_sizez *= rsmat[2][2];
- }
- else {
- continue;
- }
-
- if (apply_loc)
- zero_v3(ob->loc);
- if (apply_scale)
- ob->scale[0] = ob->scale[1] = ob->scale[2] = 1.0f;
- if (apply_rot) {
- zero_v3(ob->rot);
- unit_qt(ob->quat);
- unit_axis_angle(ob->rotAxis, &ob->rotAngle);
- }
-
- BKE_object_where_is_calc(depsgraph, scene, ob);
- if (ob->type == OB_ARMATURE) {
- BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
- }
-
- ignore_parent_tx(C, bmain, scene, ob);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
-
- changed = true;
- }
- CTX_DATA_END;
-
- if (!changed) {
- BKE_report(reports, RPT_WARNING, "Objects have no data to transform");
- return OPERATOR_CANCELLED;
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale;
+ bool changed = true;
+
+ /* first check if we can execute */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (ELEM(ob->type,
+ OB_MESH,
+ OB_ARMATURE,
+ OB_LATTICE,
+ OB_MBALL,
+ OB_CURVE,
+ OB_SURF,
+ OB_FONT,
+ OB_GPENCIL)) {
+ ID *obdata = ob->data;
+ if (ID_REAL_USERS(obdata) > 1) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Cannot apply to a multi user: Object \"%s\", %s \"%s\", aborting",
+ ob->id.name + 2,
+ BKE_idcode_to_name(GS(obdata->name)),
+ obdata->name + 2);
+ changed = false;
+ }
+
+ if (ID_IS_LINKED(obdata)) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Cannot apply to library data: Object \"%s\", %s \"%s\", aborting",
+ ob->id.name + 2,
+ BKE_idcode_to_name(GS(obdata->name)),
+ obdata->name + 2);
+ changed = false;
+ }
+ }
+
+ if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ ID *obdata = ob->data;
+ Curve *cu;
+
+ cu = ob->data;
+
+ if (((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) && (apply_rot || apply_loc)) {
+ BKE_reportf(
+ reports,
+ 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)),
+ obdata->name + 2);
+ changed = false;
+ }
+ if (cu->key) {
+ BKE_reportf(reports,
+ 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)),
+ obdata->name + 2);
+ changed = false;
+ }
+ }
+
+ if (ob->type == OB_FONT) {
+ if (apply_rot || apply_loc) {
+ BKE_reportf(
+ reports, RPT_ERROR, "Font's can only have scale applied: \"%s\"", ob->id.name + 2);
+ changed = false;
+ }
+ }
+
+ if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = ob->data;
+ if (gpd) {
+ if (gpd->layers.first) {
+ /* Unsupported configuration */
+ bool has_unparented_layers = false;
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* Parented layers aren't supported as we can't easily re-evaluate
+ * the scene to sample parent movement */
+ if (gpl->parent == NULL) {
+ has_unparented_layers = true;
+ break;
+ }
+ }
+
+ if (has_unparented_layers == false) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "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),
+ gpd->id.name + 2);
+ changed = false;
+ }
+ }
+ else {
+ /* No layers/data */
+ BKE_reportf(
+ reports,
+ 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),
+ gpd->id.name + 2);
+ }
+ }
+ }
+
+ if (ob->type == OB_LAMP) {
+ Light *la = ob->data;
+ if (la->type == LA_AREA) {
+ if (apply_rot || apply_loc) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Area Lights can only have scale applied: \"%s\"",
+ ob->id.name + 2);
+ changed = false;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ if (!changed)
+ return OPERATOR_CANCELLED;
+
+ changed = false;
+
+ /* now execute */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+
+ /* calculate rotation/scale matrix */
+ if (apply_scale && apply_rot)
+ BKE_object_to_mat3(ob, rsmat);
+ else if (apply_scale)
+ BKE_object_scale_to_mat3(ob, rsmat);
+ else if (apply_rot) {
+ float tmat[3][3], timat[3][3];
+
+ /* simple rotation matrix */
+ BKE_object_rot_to_mat3(ob, rsmat, true);
+
+ /* correct for scale, note mul_m3_m3m3 has swapped args! */
+ BKE_object_scale_to_mat3(ob, tmat);
+ invert_m3_m3(timat, tmat);
+ mul_m3_m3m3(rsmat, timat, rsmat);
+ mul_m3_m3m3(rsmat, rsmat, tmat);
+ }
+ else
+ unit_m3(rsmat);
+
+ copy_m4_m3(mat, rsmat);
+
+ /* calculate translation */
+ if (apply_loc) {
+ copy_v3_v3(mat[3], ob->loc);
+
+ if (!(apply_scale && apply_rot)) {
+ float tmat[3][3];
+ /* correct for scale and rotation that is still applied */
+ BKE_object_to_mat3(ob, obmat);
+ invert_m3_m3(iobmat, obmat);
+ mul_m3_m3m3(tmat, rsmat, iobmat);
+ mul_m3_v3(tmat, mat[3]);
+ }
+ }
+
+ /* apply to object data */
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (apply_scale)
+ multiresModifier_scale_disp(depsgraph, scene, ob);
+
+ /* adjust data */
+ BKE_mesh_transform(me, mat, true);
+
+ /* update normals */
+ BKE_mesh_calc_normals(me);
+ }
+ else if (ob->type == OB_ARMATURE) {
+ ED_armature_transform_apply(bmain, ob, mat, do_props);
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = ob->data;
+
+ BKE_lattice_transform(lt, mat, true);
+ }
+ else if (ob->type == OB_MBALL) {
+ MetaBall *mb = ob->data;
+ BKE_mball_transform(mb, mat, do_props);
+ }
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ Curve *cu = ob->data;
+ scale = mat3_to_scale(rsmat);
+ BKE_curve_transform_ex(cu, mat, true, do_props, scale);
+ }
+ else if (ob->type == OB_FONT) {
+ Curve *cu = ob->data;
+ int i;
+
+ scale = mat3_to_scale(rsmat);
+
+ for (i = 0; i < cu->totbox; i++) {
+ TextBox *tb = &cu->tb[i];
+ tb->x *= scale;
+ tb->y *= scale;
+ tb->w *= scale;
+ tb->h *= scale;
+ }
+
+ if (do_props) {
+ cu->fsize *= scale;
+ }
+ }
+ else if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = ob->data;
+ BKE_gpencil_transform(gpd, mat);
+ }
+ else if (ob->type == OB_CAMERA) {
+ MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
+
+ /* applying scale on camera actually scales clip's reconstruction.
+ * of there's clip assigned to camera nothing to do actually.
+ */
+ if (!clip)
+ continue;
+
+ if (apply_scale)
+ BKE_tracking_reconstruction_scale(&clip->tracking, ob->scale);
+ }
+ else if (ob->type == OB_EMPTY) {
+ /* It's possible for empties too, even though they don't
+ * really have obdata, since we can simply apply the maximum
+ * scaling to the empty's drawsize.
+ *
+ * Core Assumptions:
+ * 1) Most scaled empties have uniform scaling
+ * (i.e. for visibility reasons), AND/OR
+ * 2) Preserving non-uniform scaling is not that important,
+ * and is something that many users would be willing to
+ * sacrifice for having an easy way to do this.
+ */
+
+ if ((apply_loc == false) && (apply_rot == false) && (apply_scale == true)) {
+ float max_scale = max_fff(fabsf(ob->scale[0]), fabsf(ob->scale[1]), fabsf(ob->scale[2]));
+ ob->empty_drawsize *= max_scale;
+ }
+ }
+ else if (ob->type == OB_LAMP) {
+ Light *la = ob->data;
+ if (la->type != LA_AREA) {
+ continue;
+ }
+
+ bool keeps_aspect_ratio = compare_ff_relative(rsmat[0][0], rsmat[1][1], FLT_EPSILON, 64);
+ if ((la->area_shape == LA_AREA_SQUARE) && !keeps_aspect_ratio) {
+ la->area_shape = LA_AREA_RECT;
+ la->area_sizey = la->area_size;
+ }
+ else if ((la->area_shape == LA_AREA_DISK) && !keeps_aspect_ratio) {
+ la->area_shape = LA_AREA_ELLIPSE;
+ la->area_sizey = la->area_size;
+ }
+
+ la->area_size *= rsmat[0][0];
+ la->area_sizey *= rsmat[1][1];
+ la->area_sizez *= rsmat[2][2];
+ }
+ else {
+ continue;
+ }
+
+ if (apply_loc)
+ zero_v3(ob->loc);
+ if (apply_scale)
+ ob->scale[0] = ob->scale[1] = ob->scale[2] = 1.0f;
+ if (apply_rot) {
+ zero_v3(ob->rot);
+ unit_qt(ob->quat);
+ unit_axis_angle(ob->rotAxis, &ob->rotAngle);
+ }
+
+ BKE_object_where_is_calc(depsgraph, scene, ob);
+ if (ob->type == OB_ARMATURE) {
+ BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
+ }
+
+ ignore_parent_tx(C, bmain, scene, ob);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ changed = true;
+ }
+ CTX_DATA_END;
+
+ if (!changed) {
+ BKE_report(reports, RPT_WARNING, "Objects have no data to transform");
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ return OPERATOR_FINISHED;
}
static int visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- bool changed = false;
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ bool changed = false;
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- BKE_object_where_is_calc(depsgraph, scene, ob);
- BKE_object_apply_mat4(ob, ob->obmat, true, true);
- BKE_object_where_is_calc(depsgraph, scene, ob);
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ BKE_object_where_is_calc(depsgraph, scene, ob);
+ BKE_object_apply_mat4(ob, ob->obmat, true, true);
+ BKE_object_where_is_calc(depsgraph, scene, ob);
- /* update for any children that may get moved */
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ /* update for any children that may get moved */
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- changed = true;
- }
- CTX_DATA_END;
+ changed = true;
+ }
+ CTX_DATA_END;
- if (!changed)
- return OPERATOR_CANCELLED;
+ if (!changed)
+ return OPERATOR_CANCELLED;
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- return OPERATOR_FINISHED;
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_visual_transform_apply(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Apply Visual Transform";
- ot->description = "Apply the object's visual transformation to its data";
- ot->idname = "OBJECT_OT_visual_transform_apply";
+ /* identifiers */
+ ot->name = "Apply Visual Transform";
+ ot->description = "Apply the object's visual transformation to its data";
+ ot->idname = "OBJECT_OT_visual_transform_apply";
- /* api callbacks */
- ot->exec = visual_transform_apply_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = visual_transform_apply_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int object_transform_apply_exec(bContext *C, wmOperator *op)
{
- const bool loc = RNA_boolean_get(op->ptr, "location");
- const bool rot = RNA_boolean_get(op->ptr, "rotation");
- const bool sca = RNA_boolean_get(op->ptr, "scale");
- const bool do_props = RNA_boolean_get(op->ptr, "properties");
-
- if (loc || rot || sca) {
- return apply_objects_internal(C, op->reports, loc, rot, sca, do_props);
- }
- else {
- /* allow for redo */
- return OPERATOR_FINISHED;
- }
+ const bool loc = RNA_boolean_get(op->ptr, "location");
+ const bool rot = RNA_boolean_get(op->ptr, "rotation");
+ const bool sca = RNA_boolean_get(op->ptr, "scale");
+ const bool do_props = RNA_boolean_get(op->ptr, "properties");
+
+ if (loc || rot || sca) {
+ return apply_objects_internal(C, op->reports, loc, rot, sca, do_props);
+ }
+ else {
+ /* allow for redo */
+ return OPERATOR_FINISHED;
+ }
}
void OBJECT_OT_transform_apply(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Apply Object Transform";
- ot->description = "Apply the object's transformation to its data";
- ot->idname = "OBJECT_OT_transform_apply";
-
- /* api callbacks */
- ot->exec = object_transform_apply_exec;
- ot->poll = ED_operator_objectmode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "location", true, "Location", "");
- RNA_def_boolean(ot->srna, "rotation", true, "Rotation", "");
- RNA_def_boolean(ot->srna, "scale", true, "Scale", "");
- RNA_def_boolean(ot->srna, "properties", true, "Apply Properties",
- "Modify properties such as curve vertex radius, font size and bone envelope");
+ /* identifiers */
+ ot->name = "Apply Object Transform";
+ ot->description = "Apply the object's transformation to its data";
+ ot->idname = "OBJECT_OT_transform_apply";
+
+ /* api callbacks */
+ ot->exec = object_transform_apply_exec;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "location", true, "Location", "");
+ RNA_def_boolean(ot->srna, "rotation", true, "Rotation", "");
+ RNA_def_boolean(ot->srna, "scale", true, "Scale", "");
+ RNA_def_boolean(ot->srna,
+ "properties",
+ true,
+ "Apply Properties",
+ "Modify properties such as curve vertex radius, font size and bone envelope");
}
/********************* Set Object Center ************************/
enum {
- GEOMETRY_TO_ORIGIN = 0,
- ORIGIN_TO_GEOMETRY,
- ORIGIN_TO_CURSOR,
- ORIGIN_TO_CENTER_OF_MASS_SURFACE,
- ORIGIN_TO_CENTER_OF_MASS_VOLUME,
+ GEOMETRY_TO_ORIGIN = 0,
+ ORIGIN_TO_GEOMETRY,
+ ORIGIN_TO_CURSOR,
+ ORIGIN_TO_CENTER_OF_MASS_SURFACE,
+ ORIGIN_TO_CENTER_OF_MASS_VOLUME,
};
static int object_origin_set_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *obact = CTX_data_active_object(C);
- Object *obedit = CTX_data_edit_object(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *tob;
- float cent[3], cent_neg[3], centn[3];
- const float *cursor = scene->cursor.location;
- int centermode = RNA_enum_get(op->ptr, "type");
-
- ListBase ctx_data_list;
- CollectionPointerLink *ctx_ob;
- CollectionPointerLink *ctx_ob_act = NULL;
-
- /* keep track of what is changed */
- int tot_change = 0, tot_lib_error = 0, tot_multiuser_arm_error = 0;
-
- if (obedit && centermode != GEOMETRY_TO_ORIGIN) {
- BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in edit mode");
- return OPERATOR_CANCELLED;
- }
-
- int around;
- {
- PropertyRNA *prop_center = RNA_struct_find_property(op->ptr, "center");
- if (RNA_property_is_set(op->ptr, prop_center)) {
- around = RNA_property_enum_get(op->ptr, prop_center);
- }
- else {
- if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_BOUNDS) {
- around = V3D_AROUND_CENTER_BOUNDS;
- }
- else {
- around = V3D_AROUND_CENTER_MEDIAN;
- }
- RNA_property_enum_set(op->ptr, prop_center, around);
- }
- }
-
- zero_v3(cent);
-
- if (obedit) {
- if (obedit->type == OB_MESH) {
- Mesh *me = obedit->data;
- BMEditMesh *em = me->edit_mesh;
- BMVert *eve;
- BMIter iter;
-
- if (centermode == ORIGIN_TO_CURSOR) {
- copy_v3_v3(cent, cursor);
- invert_m4_m4(obedit->imat, obedit->obmat);
- mul_m4_v3(obedit->imat, cent);
- }
- else {
- if (around == V3D_AROUND_CENTER_MEDIAN) {
- if (em->bm->totvert) {
- const float total_div = 1.0f / (float)em->bm->totvert;
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- madd_v3_v3fl(cent, eve->co, total_div);
- }
- }
- }
- else {
- float min[3], max[3];
- INIT_MINMAX(min, max);
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- minmax_v3v3_v3(min, max, eve->co);
- }
- mid_v3_v3v3(cent, min, max);
- }
- }
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- sub_v3_v3(eve->co, cent);
- }
-
- EDBM_mesh_normals_update(em);
- tot_change++;
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
- }
-
- CTX_data_selected_editable_objects(C, &ctx_data_list);
-
- /* reset flags */
- for (ctx_ob = ctx_data_list.first;
- ctx_ob;
- ctx_ob = ctx_ob->next)
- {
- Object *ob = ctx_ob->ptr.data;
- ob->flag &= ~OB_DONE;
-
- /* move active first */
- if (ob == obact) {
- ctx_ob_act = ctx_ob;
- }
- }
-
- if (ctx_ob_act) {
- BLI_listbase_rotate_first(&ctx_data_list, (LinkData *)ctx_ob_act);
- }
-
- for (tob = bmain->objects.first; tob; tob = tob->id.next) {
- if (tob->data)
- ((ID *)tob->data)->tag &= ~LIB_TAG_DOIT;
- if (tob->instance_collection)
- ((ID *)tob->instance_collection)->tag &= ~LIB_TAG_DOIT;
- }
-
- for (ctx_ob = ctx_data_list.first;
- ctx_ob;
- ctx_ob = ctx_ob->next)
- {
- Object *ob = ctx_ob->ptr.data;
-
- if ((ob->flag & OB_DONE) == 0) {
- bool do_inverse_offset = false;
- ob->flag |= OB_DONE;
-
- if (centermode == ORIGIN_TO_CURSOR) {
- copy_v3_v3(cent, cursor);
- invert_m4_m4(ob->imat, ob->obmat);
- mul_m4_v3(ob->imat, cent);
- }
-
- if (ob->data == NULL) {
- /* special support for dupligroups */
- if ((ob->transflag & OB_DUPLICOLLECTION) && ob->instance_collection && (ob->instance_collection->id.tag & LIB_TAG_DOIT) == 0) {
- if (ID_IS_LINKED(ob->instance_collection)) {
- tot_lib_error++;
- }
- else {
- if (centermode == ORIGIN_TO_CURSOR) {
- /* done */
- }
- else {
- float min[3], max[3];
- /* only bounds support */
- INIT_MINMAX(min, max);
- BKE_object_minmax_dupli(depsgraph, scene, ob, min, max, true);
- mid_v3_v3v3(cent, min, max);
- invert_m4_m4(ob->imat, ob->obmat);
- mul_m4_v3(ob->imat, cent);
- }
-
- add_v3_v3(ob->instance_collection->instance_offset, cent);
-
- tot_change++;
- ob->instance_collection->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
- }
- }
- }
- else if (ID_IS_LINKED(ob->data)) {
- tot_lib_error++;
- }
-
- if (obedit == NULL && ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- if (centermode == ORIGIN_TO_CURSOR) {
- /* done */
- }
- else if (centermode == ORIGIN_TO_CENTER_OF_MASS_SURFACE) {
- BKE_mesh_center_of_surface(me, cent);
- }
- else if (centermode == ORIGIN_TO_CENTER_OF_MASS_VOLUME) {
- BKE_mesh_center_of_volume(me, cent);
- }
- else if (around == V3D_AROUND_CENTER_MEDIAN) {
- BKE_mesh_center_median(me, cent);
- }
- else {
- BKE_mesh_center_bounds(me, cent);
- }
-
- negate_v3_v3(cent_neg, cent);
- BKE_mesh_translate(me, cent_neg, 1);
-
- tot_change++;
- me->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
- }
- else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
- Curve *cu = ob->data;
-
- if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
- else if (around == V3D_AROUND_CENTER_MEDIAN) { BKE_curve_center_median(cu, cent); }
- else { BKE_curve_center_bounds(cu, cent); }
-
- /* don't allow Z change if curve is 2D */
- if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D))
- cent[2] = 0.0;
-
- negate_v3_v3(cent_neg, cent);
- BKE_curve_translate(cu, cent_neg, 1);
-
- tot_change++;
- cu->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
-
- if (obedit) {
- if (centermode == GEOMETRY_TO_ORIGIN) {
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
- break;
- }
- }
- else if (ob->type == OB_FONT) {
- /* get from bb */
-
- Curve *cu = ob->data;
-
- if (ob->runtime.bb == NULL && (centermode != ORIGIN_TO_CURSOR)) {
- /* do nothing*/
- }
- else {
- if (centermode == ORIGIN_TO_CURSOR) {
- /* done */
- }
- else {
- /* extra 0.5 is the height o above line */
- cent[0] = 0.5f * (ob->runtime.bb->vec[4][0] + ob->runtime.bb->vec[0][0]);
- cent[1] = 0.5f * (ob->runtime.bb->vec[0][1] + ob->runtime.bb->vec[2][1]);
- }
-
- cent[2] = 0.0f;
-
- cu->xof = cu->xof - cent[0];
- cu->yof = cu->yof - cent[1];
-
- tot_change++;
- cu->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
- }
- }
- else if (ob->type == OB_ARMATURE) {
- bArmature *arm = ob->data;
-
- if (ID_REAL_USERS(arm) > 1) {
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obact = CTX_data_active_object(C);
+ Object *obedit = CTX_data_edit_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *tob;
+ float cent[3], cent_neg[3], centn[3];
+ const float *cursor = scene->cursor.location;
+ int centermode = RNA_enum_get(op->ptr, "type");
+
+ ListBase ctx_data_list;
+ CollectionPointerLink *ctx_ob;
+ CollectionPointerLink *ctx_ob_act = NULL;
+
+ /* keep track of what is changed */
+ int tot_change = 0, tot_lib_error = 0, tot_multiuser_arm_error = 0;
+
+ if (obedit && centermode != GEOMETRY_TO_ORIGIN) {
+ BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in edit mode");
+ return OPERATOR_CANCELLED;
+ }
+
+ int around;
+ {
+ PropertyRNA *prop_center = RNA_struct_find_property(op->ptr, "center");
+ if (RNA_property_is_set(op->ptr, prop_center)) {
+ around = RNA_property_enum_get(op->ptr, prop_center);
+ }
+ else {
+ if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_BOUNDS) {
+ around = V3D_AROUND_CENTER_BOUNDS;
+ }
+ else {
+ around = V3D_AROUND_CENTER_MEDIAN;
+ }
+ RNA_property_enum_set(op->ptr, prop_center, around);
+ }
+ }
+
+ zero_v3(cent);
+
+ if (obedit) {
+ if (obedit->type == OB_MESH) {
+ Mesh *me = obedit->data;
+ BMEditMesh *em = me->edit_mesh;
+ BMVert *eve;
+ BMIter iter;
+
+ if (centermode == ORIGIN_TO_CURSOR) {
+ copy_v3_v3(cent, cursor);
+ invert_m4_m4(obedit->imat, obedit->obmat);
+ mul_m4_v3(obedit->imat, cent);
+ }
+ else {
+ if (around == V3D_AROUND_CENTER_MEDIAN) {
+ if (em->bm->totvert) {
+ const float total_div = 1.0f / (float)em->bm->totvert;
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ madd_v3_v3fl(cent, eve->co, total_div);
+ }
+ }
+ }
+ else {
+ float min[3], max[3];
+ INIT_MINMAX(min, max);
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ minmax_v3v3_v3(min, max, eve->co);
+ }
+ mid_v3_v3v3(cent, min, max);
+ }
+ }
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ sub_v3_v3(eve->co, cent);
+ }
+
+ EDBM_mesh_normals_update(em);
+ tot_change++;
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ }
+ }
+
+ CTX_data_selected_editable_objects(C, &ctx_data_list);
+
+ /* reset flags */
+ for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
+ Object *ob = ctx_ob->ptr.data;
+ ob->flag &= ~OB_DONE;
+
+ /* move active first */
+ if (ob == obact) {
+ ctx_ob_act = ctx_ob;
+ }
+ }
+
+ if (ctx_ob_act) {
+ BLI_listbase_rotate_first(&ctx_data_list, (LinkData *)ctx_ob_act);
+ }
+
+ for (tob = bmain->objects.first; tob; tob = tob->id.next) {
+ if (tob->data)
+ ((ID *)tob->data)->tag &= ~LIB_TAG_DOIT;
+ if (tob->instance_collection)
+ ((ID *)tob->instance_collection)->tag &= ~LIB_TAG_DOIT;
+ }
+
+ for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
+ Object *ob = ctx_ob->ptr.data;
+
+ if ((ob->flag & OB_DONE) == 0) {
+ bool do_inverse_offset = false;
+ ob->flag |= OB_DONE;
+
+ if (centermode == ORIGIN_TO_CURSOR) {
+ copy_v3_v3(cent, cursor);
+ invert_m4_m4(ob->imat, ob->obmat);
+ mul_m4_v3(ob->imat, cent);
+ }
+
+ if (ob->data == NULL) {
+ /* special support for dupligroups */
+ if ((ob->transflag & OB_DUPLICOLLECTION) && ob->instance_collection &&
+ (ob->instance_collection->id.tag & LIB_TAG_DOIT) == 0) {
+ if (ID_IS_LINKED(ob->instance_collection)) {
+ tot_lib_error++;
+ }
+ else {
+ if (centermode == ORIGIN_TO_CURSOR) {
+ /* done */
+ }
+ else {
+ float min[3], max[3];
+ /* only bounds support */
+ INIT_MINMAX(min, max);
+ BKE_object_minmax_dupli(depsgraph, scene, ob, min, max, true);
+ mid_v3_v3v3(cent, min, max);
+ invert_m4_m4(ob->imat, ob->obmat);
+ mul_m4_v3(ob->imat, cent);
+ }
+
+ add_v3_v3(ob->instance_collection->instance_offset, cent);
+
+ tot_change++;
+ ob->instance_collection->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
+ }
+ }
+ }
+ else if (ID_IS_LINKED(ob->data)) {
+ tot_lib_error++;
+ }
+
+ if (obedit == NULL && ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (centermode == ORIGIN_TO_CURSOR) {
+ /* done */
+ }
+ else if (centermode == ORIGIN_TO_CENTER_OF_MASS_SURFACE) {
+ BKE_mesh_center_of_surface(me, cent);
+ }
+ else if (centermode == ORIGIN_TO_CENTER_OF_MASS_VOLUME) {
+ BKE_mesh_center_of_volume(me, cent);
+ }
+ else if (around == V3D_AROUND_CENTER_MEDIAN) {
+ BKE_mesh_center_median(me, cent);
+ }
+ else {
+ BKE_mesh_center_bounds(me, cent);
+ }
+
+ negate_v3_v3(cent_neg, cent);
+ BKE_mesh_translate(me, cent_neg, 1);
+
+ tot_change++;
+ me->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
+ }
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ Curve *cu = ob->data;
+
+ if (centermode == ORIGIN_TO_CURSOR) { /* done */
+ }
+ else if (around == V3D_AROUND_CENTER_MEDIAN) {
+ BKE_curve_center_median(cu, cent);
+ }
+ else {
+ BKE_curve_center_bounds(cu, cent);
+ }
+
+ /* don't allow Z change if curve is 2D */
+ if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D))
+ cent[2] = 0.0;
+
+ negate_v3_v3(cent_neg, cent);
+ BKE_curve_translate(cu, cent_neg, 1);
+
+ tot_change++;
+ cu->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
+
+ if (obedit) {
+ if (centermode == GEOMETRY_TO_ORIGIN) {
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ }
+ break;
+ }
+ }
+ else if (ob->type == OB_FONT) {
+ /* get from bb */
+
+ Curve *cu = ob->data;
+
+ if (ob->runtime.bb == NULL && (centermode != ORIGIN_TO_CURSOR)) {
+ /* do nothing*/
+ }
+ else {
+ if (centermode == ORIGIN_TO_CURSOR) {
+ /* done */
+ }
+ else {
+ /* extra 0.5 is the height o above line */
+ cent[0] = 0.5f * (ob->runtime.bb->vec[4][0] + ob->runtime.bb->vec[0][0]);
+ cent[1] = 0.5f * (ob->runtime.bb->vec[0][1] + ob->runtime.bb->vec[2][1]);
+ }
+
+ cent[2] = 0.0f;
+
+ cu->xof = cu->xof - cent[0];
+ cu->yof = cu->yof - cent[1];
+
+ tot_change++;
+ cu->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
+ }
+ }
+ else if (ob->type == OB_ARMATURE) {
+ bArmature *arm = ob->data;
+
+ if (ID_REAL_USERS(arm) > 1) {
#if 0
- BKE_report(op->reports, RPT_ERROR, "Cannot apply to a multi user armature");
- return;
+ BKE_report(op->reports, RPT_ERROR, "Cannot apply to a multi user armature");
+ return;
#endif
- tot_multiuser_arm_error++;
- }
- else {
- /* Function to recenter armatures in editarmature.c
- * Bone + object locations are handled there.
- */
- ED_armature_origin_set(bmain, ob, cursor, centermode, around);
-
- tot_change++;
- arm->id.tag |= LIB_TAG_DOIT;
- /* do_inverse_offset = true; */ /* docenter_armature() handles this */
-
- BKE_object_where_is_calc(depsgraph, scene, ob);
- BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
-
- ignore_parent_tx(C, bmain, scene, ob);
-
- if (obedit)
- break;
- }
- }
- else if (ob->type == OB_MBALL) {
- MetaBall *mb = ob->data;
-
- if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
- else if (around == V3D_AROUND_CENTER_MEDIAN) { BKE_mball_center_median(mb, cent); }
- else { BKE_mball_center_bounds(mb, cent); }
-
- negate_v3_v3(cent_neg, cent);
- BKE_mball_translate(mb, cent_neg);
-
- tot_change++;
- mb->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
-
- if (obedit) {
- if (centermode == GEOMETRY_TO_ORIGIN) {
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
- break;
- }
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = ob->data;
-
- if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
- else if (around == V3D_AROUND_CENTER_MEDIAN) { BKE_lattice_center_median(lt, cent); }
- else { BKE_lattice_center_bounds(lt, cent); }
-
- negate_v3_v3(cent_neg, cent);
- BKE_lattice_translate(lt, cent_neg, 1);
-
- tot_change++;
- lt->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
- }
- else if (ob->type == OB_GPENCIL) {
- bGPdata *gpd = ob->data;
- float gpcenter[3];
- if (gpd) {
- if (centermode == ORIGIN_TO_GEOMETRY) {
- zero_v3(gpcenter);
- BKE_gpencil_centroid_3d(gpd, gpcenter);
- add_v3_v3(gpcenter, ob->obmat[3]);
- }
- if (centermode == ORIGIN_TO_CURSOR) {
- copy_v3_v3(gpcenter, cursor);
- }
- if ((centermode == ORIGIN_TO_GEOMETRY) || (centermode == ORIGIN_TO_CURSOR)) {
- bGPDspoint *pt;
- float imat[3][3], bmat[3][3];
- float offset_global[3];
- float offset_local[3];
- int i;
-
- sub_v3_v3v3(offset_global, gpcenter, ob->obmat[3]);
- copy_m3_m4(bmat, obact->obmat);
- invert_m3_m3(imat, bmat);
- mul_m3_v3(imat, offset_global);
- mul_v3_m3v3(offset_local, imat, offset_global);
-
- float diff_mat[4][4];
- float inverse_diff_mat[4][4];
-
- /* recalculate all strokes
- * (all layers are considered without evaluating lock attributes) */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* calculate difference matrix */
- ED_gpencil_parent_location(depsgraph, obact, gpd, 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) {
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps) == false)
- continue;
-
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- float mpt[3];
- mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
- sub_v3_v3(mpt, offset_local);
- mul_v3_m4v3(&pt->x, diff_mat, mpt);
- }
- }
- }
- }
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
-
- tot_change++;
- if (centermode == ORIGIN_TO_GEOMETRY) {
- copy_v3_v3(ob->loc, gpcenter);
- }
- ob->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
- }
- else {
- BKE_report(op->reports, RPT_WARNING, "Grease Pencil Object does not support this set origin option");
- }
- }
- }
-
- /* offset other selected objects */
- if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) {
- CollectionPointerLink *ctx_link_other;
- float obmat[4][4];
-
- /* was the object data modified
- * note: the functions above must set 'cent' */
-
- /* convert the offset to parent space */
- BKE_object_to_mat4(ob, obmat);
- mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */
-
- add_v3_v3(ob->loc, centn);
-
- BKE_object_where_is_calc(depsgraph, scene, ob);
- if (ob->type == OB_ARMATURE) {
- BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
- }
-
- ignore_parent_tx(C, bmain, scene, ob);
-
- /* other users? */
- //CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects)
- //{
-
- /* use existing context looper */
- for (ctx_link_other = ctx_data_list.first;
- ctx_link_other;
- ctx_link_other = ctx_link_other->next)
- {
- Object *ob_other = ctx_link_other->ptr.data;
-
- if ((ob_other->flag & OB_DONE) == 0 &&
- ((ob->data && (ob->data == ob_other->data)) ||
- (ob->instance_collection == ob_other->instance_collection &&
- (ob->transflag | ob_other->transflag) & OB_DUPLICOLLECTION)))
- {
- ob_other->flag |= OB_DONE;
- DEG_id_tag_update(&ob_other->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
-
- mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */
- add_v3_v3(ob_other->loc, centn);
-
- BKE_object_where_is_calc(depsgraph, scene, ob_other);
- if (ob_other->type == OB_ARMATURE) {
- /* needed for bone parents */
- BKE_pose_where_is(depsgraph, scene, ob_other);
- }
- ignore_parent_tx(C, bmain, scene, ob_other);
- }
- }
- //CTX_DATA_END;
- }
- }
- }
- BLI_freelistN(&ctx_data_list);
-
- for (tob = bmain->objects.first; tob; tob = tob->id.next) {
- if (tob->data && (((ID *)tob->data)->tag & LIB_TAG_DOIT)) {
- BKE_object_batch_cache_dirty_tag(tob);
- DEG_id_tag_update(&tob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- }
- }
-
- if (tot_change) {
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- }
-
- /* Warn if any errors occurred */
- if (tot_lib_error + tot_multiuser_arm_error) {
- BKE_reportf(op->reports, RPT_WARNING, "%i object(s) not centered, %i changed:", tot_lib_error + tot_multiuser_arm_error, tot_change);
- if (tot_lib_error)
- BKE_reportf(op->reports, RPT_WARNING, "|%i linked library object(s)", tot_lib_error);
- if (tot_multiuser_arm_error)
- BKE_reportf(op->reports, RPT_WARNING, "|%i multiuser armature object(s)", tot_multiuser_arm_error);
- }
-
- return OPERATOR_FINISHED;
+ tot_multiuser_arm_error++;
+ }
+ else {
+ /* Function to recenter armatures in editarmature.c
+ * Bone + object locations are handled there.
+ */
+ ED_armature_origin_set(bmain, ob, cursor, centermode, around);
+
+ tot_change++;
+ arm->id.tag |= LIB_TAG_DOIT;
+ /* do_inverse_offset = true; */ /* docenter_armature() handles this */
+
+ BKE_object_where_is_calc(depsgraph, scene, ob);
+ BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
+
+ ignore_parent_tx(C, bmain, scene, ob);
+
+ if (obedit)
+ break;
+ }
+ }
+ else if (ob->type == OB_MBALL) {
+ MetaBall *mb = ob->data;
+
+ if (centermode == ORIGIN_TO_CURSOR) { /* done */
+ }
+ else if (around == V3D_AROUND_CENTER_MEDIAN) {
+ BKE_mball_center_median(mb, cent);
+ }
+ else {
+ BKE_mball_center_bounds(mb, cent);
+ }
+
+ negate_v3_v3(cent_neg, cent);
+ BKE_mball_translate(mb, cent_neg);
+
+ tot_change++;
+ mb->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
+
+ if (obedit) {
+ if (centermode == GEOMETRY_TO_ORIGIN) {
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ }
+ break;
+ }
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = ob->data;
+
+ if (centermode == ORIGIN_TO_CURSOR) { /* done */
+ }
+ else if (around == V3D_AROUND_CENTER_MEDIAN) {
+ BKE_lattice_center_median(lt, cent);
+ }
+ else {
+ BKE_lattice_center_bounds(lt, cent);
+ }
+
+ negate_v3_v3(cent_neg, cent);
+ BKE_lattice_translate(lt, cent_neg, 1);
+
+ tot_change++;
+ lt->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
+ }
+ else if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = ob->data;
+ float gpcenter[3];
+ if (gpd) {
+ if (centermode == ORIGIN_TO_GEOMETRY) {
+ zero_v3(gpcenter);
+ BKE_gpencil_centroid_3d(gpd, gpcenter);
+ add_v3_v3(gpcenter, ob->obmat[3]);
+ }
+ if (centermode == ORIGIN_TO_CURSOR) {
+ copy_v3_v3(gpcenter, cursor);
+ }
+ if ((centermode == ORIGIN_TO_GEOMETRY) || (centermode == ORIGIN_TO_CURSOR)) {
+ bGPDspoint *pt;
+ float imat[3][3], bmat[3][3];
+ float offset_global[3];
+ float offset_local[3];
+ int i;
+
+ sub_v3_v3v3(offset_global, gpcenter, ob->obmat[3]);
+ copy_m3_m4(bmat, obact->obmat);
+ invert_m3_m3(imat, bmat);
+ mul_m3_v3(imat, offset_global);
+ mul_v3_m3v3(offset_local, imat, offset_global);
+
+ float diff_mat[4][4];
+ float inverse_diff_mat[4][4];
+
+ /* recalculate all strokes
+ * (all layers are considered without evaluating lock attributes) */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* calculate difference matrix */
+ ED_gpencil_parent_location(depsgraph, obact, gpd, 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) {
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ float mpt[3];
+ mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
+ sub_v3_v3(mpt, offset_local);
+ mul_v3_m4v3(&pt->x, diff_mat, mpt);
+ }
+ }
+ }
+ }
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ tot_change++;
+ if (centermode == ORIGIN_TO_GEOMETRY) {
+ copy_v3_v3(ob->loc, gpcenter);
+ }
+ ob->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
+ }
+ else {
+ BKE_report(op->reports,
+ RPT_WARNING,
+ "Grease Pencil Object does not support this set origin option");
+ }
+ }
+ }
+
+ /* offset other selected objects */
+ if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) {
+ CollectionPointerLink *ctx_link_other;
+ float obmat[4][4];
+
+ /* was the object data modified
+ * note: the functions above must set 'cent' */
+
+ /* convert the offset to parent space */
+ BKE_object_to_mat4(ob, obmat);
+ mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */
+
+ add_v3_v3(ob->loc, centn);
+
+ BKE_object_where_is_calc(depsgraph, scene, ob);
+ if (ob->type == OB_ARMATURE) {
+ BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
+ }
+
+ ignore_parent_tx(C, bmain, scene, ob);
+
+ /* other users? */
+ //CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects)
+ //{
+
+ /* use existing context looper */
+ for (ctx_link_other = ctx_data_list.first; ctx_link_other;
+ ctx_link_other = ctx_link_other->next) {
+ Object *ob_other = ctx_link_other->ptr.data;
+
+ if ((ob_other->flag & OB_DONE) == 0 &&
+ ((ob->data && (ob->data == ob_other->data)) ||
+ (ob->instance_collection == ob_other->instance_collection &&
+ (ob->transflag | ob_other->transflag) & OB_DUPLICOLLECTION))) {
+ ob_other->flag |= OB_DONE;
+ DEG_id_tag_update(&ob_other->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */
+ add_v3_v3(ob_other->loc, centn);
+
+ BKE_object_where_is_calc(depsgraph, scene, ob_other);
+ if (ob_other->type == OB_ARMATURE) {
+ /* needed for bone parents */
+ BKE_pose_where_is(depsgraph, scene, ob_other);
+ }
+ ignore_parent_tx(C, bmain, scene, ob_other);
+ }
+ }
+ //CTX_DATA_END;
+ }
+ }
+ }
+ BLI_freelistN(&ctx_data_list);
+
+ for (tob = bmain->objects.first; tob; tob = tob->id.next) {
+ if (tob->data && (((ID *)tob->data)->tag & LIB_TAG_DOIT)) {
+ BKE_object_batch_cache_dirty_tag(tob);
+ DEG_id_tag_update(&tob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ }
+ }
+
+ if (tot_change) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ }
+
+ /* Warn if any errors occurred */
+ if (tot_lib_error + tot_multiuser_arm_error) {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "%i object(s) not centered, %i changed:",
+ tot_lib_error + tot_multiuser_arm_error,
+ tot_change);
+ if (tot_lib_error)
+ BKE_reportf(op->reports, RPT_WARNING, "|%i linked library object(s)", tot_lib_error);
+ if (tot_multiuser_arm_error)
+ BKE_reportf(
+ op->reports, RPT_WARNING, "|%i multiuser armature object(s)", tot_multiuser_arm_error);
+ }
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_origin_set(wmOperatorType *ot)
{
- static const EnumPropertyItem prop_set_center_types[] = {
- {GEOMETRY_TO_ORIGIN, "GEOMETRY_ORIGIN", 0, "Geometry to Origin", "Move object geometry to object origin"},
- {ORIGIN_TO_GEOMETRY, "ORIGIN_GEOMETRY", 0, "Origin to Geometry",
- "Calculate the center of geometry based on the current pivot point (median, otherwise bounding-box)"},
- {ORIGIN_TO_CURSOR, "ORIGIN_CURSOR", 0, "Origin to 3D Cursor",
- "Move object origin to position of the 3D cursor"},
- /* Intentional naming mismatch since some scripts refer to this. */
- {ORIGIN_TO_CENTER_OF_MASS_SURFACE, "ORIGIN_CENTER_OF_MASS", 0, "Origin to Center of Mass (Surface)",
- "Calculate the center of mass from the surface area"},
- {ORIGIN_TO_CENTER_OF_MASS_VOLUME, "ORIGIN_CENTER_OF_VOLUME", 0, "Origin to Center of Mass (Volume)",
- "Calculate the center of mass from the volume (must be manifold geometry with consistent normals)"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem prop_set_bounds_types[] = {
- {V3D_AROUND_CENTER_MEDIAN, "MEDIAN", 0, "Median Center", ""},
- {V3D_AROUND_CENTER_BOUNDS, "BOUNDS", 0, "Bounds Center", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Set Origin";
- ot->description = "Set the object's origin, by either moving the data, or set to center of data, or use 3D cursor";
- ot->idname = "OBJECT_OT_origin_set";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_origin_set_exec;
-
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ot->prop = RNA_def_enum(ot->srna, "type", prop_set_center_types, 0, "Type", "");
- RNA_def_enum(ot->srna, "center", prop_set_bounds_types, V3D_AROUND_CENTER_MEDIAN, "Center", "");
+ static const EnumPropertyItem prop_set_center_types[] = {
+ {GEOMETRY_TO_ORIGIN,
+ "GEOMETRY_ORIGIN",
+ 0,
+ "Geometry to Origin",
+ "Move object geometry to object origin"},
+ {ORIGIN_TO_GEOMETRY,
+ "ORIGIN_GEOMETRY",
+ 0,
+ "Origin to Geometry",
+ "Calculate the center of geometry based on the current pivot point (median, otherwise "
+ "bounding-box)"},
+ {ORIGIN_TO_CURSOR,
+ "ORIGIN_CURSOR",
+ 0,
+ "Origin to 3D Cursor",
+ "Move object origin to position of the 3D cursor"},
+ /* Intentional naming mismatch since some scripts refer to this. */
+ {ORIGIN_TO_CENTER_OF_MASS_SURFACE,
+ "ORIGIN_CENTER_OF_MASS",
+ 0,
+ "Origin to Center of Mass (Surface)",
+ "Calculate the center of mass from the surface area"},
+ {ORIGIN_TO_CENTER_OF_MASS_VOLUME,
+ "ORIGIN_CENTER_OF_VOLUME",
+ 0,
+ "Origin to Center of Mass (Volume)",
+ "Calculate the center of mass from the volume (must be manifold geometry with consistent "
+ "normals)"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem prop_set_bounds_types[] = {
+ {V3D_AROUND_CENTER_MEDIAN, "MEDIAN", 0, "Median Center", ""},
+ {V3D_AROUND_CENTER_BOUNDS, "BOUNDS", 0, "Bounds Center", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Set Origin";
+ ot->description =
+ "Set the object's origin, by either moving the data, or set to center of data, or use 3D "
+ "cursor";
+ ot->idname = "OBJECT_OT_origin_set";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_origin_set_exec;
+
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_set_center_types, 0, "Type", "");
+ RNA_def_enum(ot->srna, "center", prop_set_bounds_types, V3D_AROUND_CENTER_MEDIAN, "Center", "");
}
/* -------------------------------------------------------------------- */
@@ -1300,431 +1393,429 @@ void OBJECT_OT_origin_set(wmOperatorType *ot)
#define USE_FAKE_DEPTH_INIT
struct XFormAxisItem {
- Object *ob;
- float rot_mat[3][3];
- void *obtfm;
- float xform_dist;
+ Object *ob;
+ float rot_mat[3][3];
+ void *obtfm;
+ float xform_dist;
#ifdef USE_RELATIVE_ROTATION
- /* use when translating multiple */
- float xform_rot_offset[3][3];
+ /* use when translating multiple */
+ float xform_rot_offset[3][3];
#endif
};
struct XFormAxisData {
- ViewContext vc;
- struct {
- float depth;
- float normal[3];
- bool is_depth_valid;
- bool is_normal_valid;
- } prev;
-
- struct XFormAxisItem *object_data;
- uint object_data_len;
- bool is_translate;
-
- int init_event;
+ ViewContext vc;
+ struct {
+ float depth;
+ float normal[3];
+ bool is_depth_valid;
+ bool is_normal_valid;
+ } prev;
+
+ struct XFormAxisItem *object_data;
+ uint object_data_len;
+ bool is_translate;
+
+ int init_event;
};
#ifdef USE_FAKE_DEPTH_INIT
-static void object_transform_axis_target_calc_depth_init(struct XFormAxisData *xfd, const int mval[2])
+static void object_transform_axis_target_calc_depth_init(struct XFormAxisData *xfd,
+ const int mval[2])
{
- 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);
- add_v3_v3(view_co_b, view_co_a);
- float center[3] = {0.0f};
- int center_tot = 0;
- for (int i = 0; i < xfd->object_data_len; i++, item++) {
- const Object *ob = item->ob;
- const float *ob_co_a = ob->obmat[3];
- float ob_co_b[3];
- add_v3_v3v3(ob_co_b, ob->obmat[3], ob->obmat[2]);
- float view_isect[3], ob_isect[3];
- if (isect_line_line_v3(view_co_a, view_co_b, ob_co_a, ob_co_b, view_isect, ob_isect)) {
- add_v3_v3(center, view_isect);
- center_tot += 1;
- }
- }
- if (center_tot) {
- mul_v3_fl(center, 1.0f / center_tot);
- float center_proj[3];
- ED_view3d_project(xfd->vc.ar, center, center_proj);
- xfd->prev.depth = center_proj[2];
- xfd->prev.is_depth_valid = true;
- }
+ 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);
+ add_v3_v3(view_co_b, view_co_a);
+ float center[3] = {0.0f};
+ int center_tot = 0;
+ for (int i = 0; i < xfd->object_data_len; i++, item++) {
+ const Object *ob = item->ob;
+ const float *ob_co_a = ob->obmat[3];
+ float ob_co_b[3];
+ add_v3_v3v3(ob_co_b, ob->obmat[3], ob->obmat[2]);
+ float view_isect[3], ob_isect[3];
+ if (isect_line_line_v3(view_co_a, view_co_b, ob_co_a, ob_co_b, view_isect, ob_isect)) {
+ add_v3_v3(center, view_isect);
+ center_tot += 1;
+ }
+ }
+ if (center_tot) {
+ mul_v3_fl(center, 1.0f / center_tot);
+ float center_proj[3];
+ ED_view3d_project(xfd->vc.ar, center, center_proj);
+ xfd->prev.depth = center_proj[2];
+ xfd->prev.is_depth_valid = true;
+ }
}
-#endif /* USE_FAKE_DEPTH_INIT */
+#endif /* USE_FAKE_DEPTH_INIT */
static bool object_is_target_compat(const Object *ob)
{
- if (ob->type == OB_LAMP) {
- const Light *la = ob->data;
- if (ELEM(la->type, LA_SUN, LA_SPOT, LA_AREA)) {
- return true;
- }
- }
- /* We might want to enable this later, for now just lights. */
+ if (ob->type == OB_LAMP) {
+ const Light *la = ob->data;
+ if (ELEM(la->type, LA_SUN, LA_SPOT, LA_AREA)) {
+ return true;
+ }
+ }
+ /* We might want to enable this later, for now just lights. */
#if 0
- else if (ob->type == OB_CAMERA) {
- return true;
- }
+ else if (ob->type == OB_CAMERA) {
+ return true;
+ }
#endif
- return false;
+ return false;
}
static void object_transform_axis_target_free_data(wmOperator *op)
{
- struct XFormAxisData *xfd = op->customdata;
- struct XFormAxisItem *item = xfd->object_data;
+ struct XFormAxisData *xfd = op->customdata;
+ struct XFormAxisItem *item = xfd->object_data;
#ifdef USE_RENDER_OVERRIDE
- if (xfd->vc.rv3d->depths) {
- xfd->vc.rv3d->depths->damaged = true;
- }
+ if (xfd->vc.rv3d->depths) {
+ xfd->vc.rv3d->depths->damaged = true;
+ }
#endif
- for (int i = 0; i < xfd->object_data_len; i++, item++) {
- MEM_freeN(item->obtfm);
- }
- MEM_freeN(xfd->object_data);
- MEM_freeN(xfd);
- op->customdata = NULL;
+ for (int i = 0; i < xfd->object_data_len; i++, item++) {
+ MEM_freeN(item->obtfm);
+ }
+ MEM_freeN(xfd->object_data);
+ MEM_freeN(xfd);
+ op->customdata = NULL;
}
/* We may want to expose as alternative to: BKE_object_apply_rotation */
static void object_apply_rotation(Object *ob, const float rmat[3][3])
{
- float size[3];
- float loc[3];
- float rmat4[4][4];
- copy_m4_m3(rmat4, rmat);
-
- copy_v3_v3(size, ob->scale);
- copy_v3_v3(loc, ob->loc);
- BKE_object_apply_mat4(ob, rmat4, true, true);
- copy_v3_v3(ob->scale, size);
- copy_v3_v3(ob->loc, loc);
+ float size[3];
+ float loc[3];
+ float rmat4[4][4];
+ copy_m4_m3(rmat4, rmat);
+
+ copy_v3_v3(size, ob->scale);
+ copy_v3_v3(loc, ob->loc);
+ BKE_object_apply_mat4(ob, rmat4, true, true);
+ copy_v3_v3(ob->scale, size);
+ copy_v3_v3(ob->loc, loc);
}
/* We may want to extract this to: BKE_object_apply_location */
static void object_apply_location(Object *ob, const float loc[3])
{
- /* quick but weak */
- Object ob_prev = *ob;
- float mat[4][4];
- copy_m4_m4(mat, ob->obmat);
- copy_v3_v3(mat[3], loc);
- BKE_object_apply_mat4(ob, mat, true, true);
- copy_v3_v3(mat[3], ob->loc);
- *ob = ob_prev;
- copy_v3_v3(ob->loc, mat[3]);
+ /* quick but weak */
+ Object ob_prev = *ob;
+ float mat[4][4];
+ copy_m4_m4(mat, ob->obmat);
+ copy_v3_v3(mat[3], loc);
+ BKE_object_apply_mat4(ob, mat, true, true);
+ copy_v3_v3(mat[3], ob->loc);
+ *ob = ob_prev;
+ copy_v3_v3(ob->loc, mat[3]);
}
-static void object_orient_to_location(
- Object *ob, float rot_orig[3][3], const float axis[3], const float location[3])
+static void object_orient_to_location(Object *ob,
+ float rot_orig[3][3],
+ const float axis[3],
+ const float location[3])
{
- float delta[3];
- sub_v3_v3v3(delta, ob->obmat[3], location);
- if (normalize_v3(delta) != 0.0f) {
- if (len_squared_v3v3(delta, axis) > FLT_EPSILON) {
- float delta_rot[3][3];
- float final_rot[3][3];
- rotation_between_vecs_to_mat3(delta_rot, axis, delta);
+ float delta[3];
+ sub_v3_v3v3(delta, ob->obmat[3], location);
+ if (normalize_v3(delta) != 0.0f) {
+ if (len_squared_v3v3(delta, axis) > FLT_EPSILON) {
+ float delta_rot[3][3];
+ float final_rot[3][3];
+ rotation_between_vecs_to_mat3(delta_rot, axis, delta);
- mul_m3_m3m3(final_rot, delta_rot, rot_orig);
+ mul_m3_m3m3(final_rot, delta_rot, rot_orig);
- object_apply_rotation(ob, final_rot);
+ object_apply_rotation(ob, final_rot);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
- }
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+ }
}
static void object_transform_axis_target_cancel(bContext *C, wmOperator *op)
{
- struct XFormAxisData *xfd = op->customdata;
- struct XFormAxisItem *item = xfd->object_data;
- for (int i = 0; i < xfd->object_data_len; i++, item++) {
- BKE_object_tfm_restore(item->ob, item->obtfm);
- DEG_id_tag_update(&item->ob->id, ID_RECALC_TRANSFORM);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
- }
-
- object_transform_axis_target_free_data(op);
+ struct XFormAxisData *xfd = op->customdata;
+ struct XFormAxisItem *item = xfd->object_data;
+ for (int i = 0; i < xfd->object_data_len; i++, item++) {
+ BKE_object_tfm_restore(item->ob, item->obtfm);
+ DEG_id_tag_update(&item->ob->id, ID_RECALC_TRANSFORM);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
+ }
+
+ object_transform_axis_target_free_data(op);
}
static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewContext vc;
- ED_view3d_viewcontext_init(C, &vc);
-
- if (vc.obact == NULL || !object_is_target_compat(vc.obact)) {
- /* Falls back to texture space transform. */
- return OPERATOR_PASS_THROUGH;
- }
+ ViewContext vc;
+ ED_view3d_viewcontext_init(C, &vc);
+ if (vc.obact == NULL || !object_is_target_compat(vc.obact)) {
+ /* Falls back to texture space transform. */
+ return OPERATOR_PASS_THROUGH;
+ }
#ifdef USE_RENDER_OVERRIDE
- int flag2_prev = vc.v3d->flag2;
- vc.v3d->flag2 |= V3D_HIDE_OVERLAYS;
+ int flag2_prev = vc.v3d->flag2;
+ 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.ar, vc.v3d, 0);
- if (vc.rv3d->depths != NULL) {
- vc.rv3d->depths->damaged = true;
- }
- ED_view3d_depth_update(vc.ar);
+ if (vc.rv3d->depths != NULL) {
+ vc.rv3d->depths->damaged = true;
+ }
+ ED_view3d_depth_update(vc.ar);
#ifdef USE_RENDER_OVERRIDE
- vc.v3d->flag2 = flag2_prev;
+ vc.v3d->flag2 = flag2_prev;
#endif
- if (vc.rv3d->depths == NULL) {
- BKE_report(op->reports, RPT_WARNING, "Unable to access depth buffer, using view plane");
- return OPERATOR_CANCELLED;
- }
+ if (vc.rv3d->depths == NULL) {
+ BKE_report(op->reports, RPT_WARNING, "Unable to access depth buffer, using view plane");
+ return OPERATOR_CANCELLED;
+ }
- ED_region_tag_redraw(vc.ar);
+ ED_region_tag_redraw(vc.ar);
- struct XFormAxisData *xfd;
- xfd = op->customdata = MEM_callocN(sizeof(struct XFormAxisData), __func__);
+ struct XFormAxisData *xfd;
+ xfd = op->customdata = MEM_callocN(sizeof(struct XFormAxisData), __func__);
- /* Don't change this at runtime. */
- xfd->vc = vc;
- xfd->vc.mval[0] = event->mval[0];
- xfd->vc.mval[1] = event->mval[1];
+ /* Don't change this at runtime. */
+ xfd->vc = vc;
+ xfd->vc.mval[0] = event->mval[0];
+ xfd->vc.mval[1] = event->mval[1];
- xfd->prev.depth = 1.0f;
- xfd->prev.is_depth_valid = false;
- xfd->prev.is_normal_valid = false;
- xfd->is_translate = false;
+ xfd->prev.depth = 1.0f;
+ xfd->prev.is_depth_valid = false;
+ xfd->prev.is_normal_valid = false;
+ xfd->is_translate = false;
- xfd->init_event = WM_userdef_event_type_from_keymap_type(event->type);
+ xfd->init_event = WM_userdef_event_type_from_keymap_type(event->type);
- {
- struct XFormAxisItem *object_data = NULL;
- BLI_array_declare(object_data);
+ {
+ struct XFormAxisItem *object_data = NULL;
+ BLI_array_declare(object_data);
- struct XFormAxisItem *item = BLI_array_append_ret(object_data);
- item->ob = xfd->vc.obact;
+ struct XFormAxisItem *item = BLI_array_append_ret(object_data);
+ item->ob = xfd->vc.obact;
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if ((ob != xfd->vc.obact) && object_is_target_compat(ob)) {
- item = BLI_array_append_ret(object_data);
- item->ob = ob;
- }
- }
- CTX_DATA_END;
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if ((ob != xfd->vc.obact) && object_is_target_compat(ob)) {
+ item = BLI_array_append_ret(object_data);
+ item->ob = ob;
+ }
+ }
+ CTX_DATA_END;
- xfd->object_data = object_data;
- xfd->object_data_len = BLI_array_len(object_data);
+ xfd->object_data = object_data;
+ xfd->object_data_len = BLI_array_len(object_data);
- if (xfd->object_data_len != BLI_array_len(object_data)) {
- xfd->object_data = MEM_reallocN(xfd->object_data, xfd->object_data_len * sizeof(*xfd->object_data));
- }
- }
+ if (xfd->object_data_len != BLI_array_len(object_data)) {
+ xfd->object_data = MEM_reallocN(xfd->object_data,
+ xfd->object_data_len * sizeof(*xfd->object_data));
+ }
+ }
- {
- struct XFormAxisItem *item = xfd->object_data;
- 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);
- }
- }
+ {
+ struct XFormAxisItem *item = xfd->object_data;
+ 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);
+ }
+ }
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- struct XFormAxisData *xfd = op->customdata;
- ARegion *ar = xfd->vc.ar;
-
- view3d_operator_needs_opengl(C);
-
- const bool is_translate = (event->ctrl != 0);
- const bool is_translate_init = is_translate && (xfd->is_translate != is_translate);
-
- 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))
- {
- double depth = (double)ED_view3d_depth_read_cached(&xfd->vc, event->mval);
- float location_world[3];
- if (depth == 1.0f) {
- if (xfd->prev.is_depth_valid) {
- depth = (double)xfd->prev.depth;
- }
- }
+ struct XFormAxisData *xfd = op->customdata;
+ ARegion *ar = xfd->vc.ar;
+
+ view3d_operator_needs_opengl(C);
+
+ const bool is_translate = (event->ctrl != 0);
+ const bool is_translate_init = is_translate && (xfd->is_translate != is_translate);
+
+ 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)) {
+ double depth = (double)ED_view3d_depth_read_cached(&xfd->vc, event->mval);
+ float location_world[3];
+ if (depth == 1.0f) {
+ if (xfd->prev.is_depth_valid) {
+ depth = (double)xfd->prev.depth;
+ }
+ }
#ifdef USE_FAKE_DEPTH_INIT
- /* First time only. */
- if (depth == 1.0f) {
- if (xfd->prev.is_depth_valid == false) {
- object_transform_axis_target_calc_depth_init(xfd, event->mval);
- if (xfd->prev.is_depth_valid) {
- depth = (double)xfd->prev.depth;
- }
- }
- }
+ /* First time only. */
+ if (depth == 1.0f) {
+ if (xfd->prev.is_depth_valid == false) {
+ object_transform_axis_target_calc_depth_init(xfd, event->mval);
+ if (xfd->prev.is_depth_valid) {
+ depth = (double)xfd->prev.depth;
+ }
+ }
+ }
#endif
- 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 (is_translate) {
-
- float normal[3];
- bool normal_found = false;
- if (ED_view3d_depth_read_cached_normal(&xfd->vc, event->mval, normal)) {
- 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) {
- if (x != 0 && y != 0) {
- int mval_ofs[2] = {event->mval[0] + x, event->mval[1] + y};
- float n[3];
- if (ED_view3d_depth_read_cached_normal(
- &xfd->vc, mval_ofs, n))
- {
- add_v3_v3(normal, n);
- }
- }
- }
- }
- normalize_v3(normal);
- }
- else if (xfd->prev.is_normal_valid) {
- copy_v3_v3(normal, xfd->prev.normal);
- normal_found = true;
- }
-
- if (normal_found) {
+ 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 (is_translate) {
+
+ float normal[3];
+ bool normal_found = false;
+ if (ED_view3d_depth_read_cached_normal(&xfd->vc, event->mval, normal)) {
+ 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) {
+ if (x != 0 && y != 0) {
+ int mval_ofs[2] = {event->mval[0] + x, event->mval[1] + y};
+ float n[3];
+ if (ED_view3d_depth_read_cached_normal(&xfd->vc, mval_ofs, n)) {
+ add_v3_v3(normal, n);
+ }
+ }
+ }
+ }
+ normalize_v3(normal);
+ }
+ else if (xfd->prev.is_normal_valid) {
+ copy_v3_v3(normal, xfd->prev.normal);
+ 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];
- struct XFormAxisItem *item = xfd->object_data;
- for (int i = 0; i < xfd->object_data_len; i++, item++) {
- copy_m3_m4(item->xform_rot_offset, item->ob->obmat);
- normalize_m3(item->xform_rot_offset);
-
- if (i == 0) {
- invert_m3_m3(xform_rot_offset_inv_first, xfd->object_data[0].xform_rot_offset);
- }
- else {
- mul_m3_m3m3(item->xform_rot_offset,
- item->xform_rot_offset,
- xform_rot_offset_inv_first);
- }
- }
- }
+ if (is_translate_init && xfd->object_data_len > 1) {
+ float xform_rot_offset_inv_first[3][3];
+ struct XFormAxisItem *item = xfd->object_data;
+ for (int i = 0; i < xfd->object_data_len; i++, item++) {
+ copy_m3_m4(item->xform_rot_offset, item->ob->obmat);
+ normalize_m3(item->xform_rot_offset);
+
+ if (i == 0) {
+ invert_m3_m3(xform_rot_offset_inv_first, xfd->object_data[0].xform_rot_offset);
+ }
+ else {
+ mul_m3_m3m3(item->xform_rot_offset,
+ item->xform_rot_offset,
+ xform_rot_offset_inv_first);
+ }
+ }
+ }
#endif
- struct XFormAxisItem *item = xfd->object_data;
- for (int i = 0; i < xfd->object_data_len; i++, item++) {
- if (is_translate_init) {
- float ob_axis[3];
- 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;
- }
+ struct XFormAxisItem *item = xfd->object_data;
+ for (int i = 0; i < xfd->object_data_len; i++, item++) {
+ if (is_translate_init) {
+ float ob_axis[3];
+ 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;
+ }
- float target_normal[3];
- copy_v3_v3(target_normal, normal);
+ float target_normal[3];
+ copy_v3_v3(target_normal, normal);
#ifdef USE_RELATIVE_ROTATION
- if (i != 0) {
- mul_m3_v3(item->xform_rot_offset, target_normal);
- }
+ if (i != 0) {
+ mul_m3_v3(item->xform_rot_offset, target_normal);
+ }
#endif
- {
- float loc[3];
-
- copy_v3_v3(loc, location_world);
- madd_v3_v3fl(loc, target_normal, item->xform_dist);
- object_apply_location(item->ob, loc);
- /* so orient behaves as expected */
- copy_v3_v3(item->ob->obmat[3], loc);
- }
-
- 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);
- }
- 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);
- }
- xfd->prev.is_normal_valid = false;
- }
- }
- }
- }
- xfd->is_translate = is_translate;
-
- ED_region_tag_redraw(xfd->vc.ar);
- }
-
- bool is_finished = false;
-
- if (ISMOUSE(xfd->init_event)) {
- if ((event->type == xfd->init_event) && (event->val == KM_RELEASE)) {
- is_finished = true;
- }
- }
- else {
- if (ELEM(event->type, LEFTMOUSE, RETKEY, PADENTER)) {
- is_finished = true;
- }
- }
-
- if (is_finished) {
- object_transform_axis_target_free_data(op);
- return OPERATOR_FINISHED;
- }
- else if (ELEM(event->type, ESCKEY, RIGHTMOUSE)) {
- object_transform_axis_target_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
-
-
- return OPERATOR_RUNNING_MODAL;
+ {
+ float loc[3];
+
+ copy_v3_v3(loc, location_world);
+ madd_v3_v3fl(loc, target_normal, item->xform_dist);
+ object_apply_location(item->ob, loc);
+ /* so orient behaves as expected */
+ copy_v3_v3(item->ob->obmat[3], loc);
+ }
+
+ 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);
+ }
+ 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);
+ }
+ xfd->prev.is_normal_valid = false;
+ }
+ }
+ }
+ }
+ xfd->is_translate = is_translate;
+
+ ED_region_tag_redraw(xfd->vc.ar);
+ }
+
+ bool is_finished = false;
+
+ if (ISMOUSE(xfd->init_event)) {
+ if ((event->type == xfd->init_event) && (event->val == KM_RELEASE)) {
+ is_finished = true;
+ }
+ }
+ else {
+ if (ELEM(event->type, LEFTMOUSE, RETKEY, PADENTER)) {
+ is_finished = true;
+ }
+ }
+
+ if (is_finished) {
+ object_transform_axis_target_free_data(op);
+ return OPERATOR_FINISHED;
+ }
+ else if (ELEM(event->type, ESCKEY, RIGHTMOUSE)) {
+ object_transform_axis_target_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
void OBJECT_OT_transform_axis_target(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Interactive Light Track to Cursor";
- ot->description = "Interactively point cameras and lights to a location (Ctrl translates)";
- ot->idname = "OBJECT_OT_transform_axis_target";
-
- /* api callbacks */
- ot->invoke = object_transform_axis_target_invoke;
- ot->cancel = object_transform_axis_target_cancel;
- ot->modal = object_transform_axis_target_modal;
- ot->poll = ED_operator_region_view3d_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ /* identifiers */
+ ot->name = "Interactive Light Track to Cursor";
+ ot->description = "Interactively point cameras and lights to a location (Ctrl translates)";
+ ot->idname = "OBJECT_OT_transform_axis_target";
+
+ /* api callbacks */
+ ot->invoke = object_transform_axis_target_invoke;
+ ot->cancel = object_transform_axis_target_cancel;
+ ot->modal = object_transform_axis_target_modal;
+ ot->poll = ED_operator_region_view3d_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
}
#undef USE_RELATIVE_ROTATION
diff --git a/source/blender/editors/object/object_utils.c b/source/blender/editors/object/object_utils.c
index 39f5dad7698..06a755c30bd 100644
--- a/source/blender/editors/object/object_utils.c
+++ b/source/blender/editors/object/object_utils.c
@@ -39,111 +39,106 @@
#include "ED_armature.h"
#include "ED_curve.h"
-#include "ED_object.h" /* own include */
-
+#include "ED_object.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Active Element Center
* \{ */
-bool ED_object_calc_active_center_for_editmode(
- Object *obedit, const bool select_only, float r_center[3])
+bool ED_object_calc_active_center_for_editmode(Object *obedit,
+ const bool select_only,
+ float r_center[3])
{
- switch (obedit->type) {
- case OB_MESH:
- {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMEditSelection ese;
-
- if (BM_select_history_active_get(em->bm, &ese)) {
- BM_editselection_center(&ese, r_center);
- return true;
- }
- break;
- }
- case OB_ARMATURE:
- {
- bArmature *arm = obedit->data;
- EditBone *ebo = arm->act_edbone;
-
- if (ebo && (!select_only || (ebo->flag & (BONE_SELECTED | BONE_ROOTSEL)))) {
- copy_v3_v3(r_center, ebo->head);
- return true;
- }
-
- break;
- }
- case OB_CURVE:
- case OB_SURF:
- {
- Curve *cu = obedit->data;
-
- if (ED_curve_active_center(cu, r_center)) {
- return true;
- }
- break;
- }
- case OB_MBALL:
- {
- MetaBall *mb = obedit->data;
- MetaElem *ml_act = mb->lastelem;
-
- if (ml_act && (!select_only || (ml_act->flag & SELECT))) {
- copy_v3_v3(r_center, &ml_act->x);
- return true;
- }
- break;
- }
- case OB_LATTICE:
- {
- BPoint *actbp = BKE_lattice_active_point_get(obedit->data);
-
- if (actbp) {
- copy_v3_v3(r_center, actbp->vec);
- return true;
- }
- break;
- }
- }
-
- return false;
+ switch (obedit->type) {
+ case OB_MESH: {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMEditSelection ese;
+
+ if (BM_select_history_active_get(em->bm, &ese)) {
+ BM_editselection_center(&ese, r_center);
+ return true;
+ }
+ break;
+ }
+ case OB_ARMATURE: {
+ bArmature *arm = obedit->data;
+ EditBone *ebo = arm->act_edbone;
+
+ if (ebo && (!select_only || (ebo->flag & (BONE_SELECTED | BONE_ROOTSEL)))) {
+ copy_v3_v3(r_center, ebo->head);
+ return true;
+ }
+
+ break;
+ }
+ case OB_CURVE:
+ case OB_SURF: {
+ Curve *cu = obedit->data;
+
+ if (ED_curve_active_center(cu, r_center)) {
+ return true;
+ }
+ break;
+ }
+ case OB_MBALL: {
+ MetaBall *mb = obedit->data;
+ MetaElem *ml_act = mb->lastelem;
+
+ if (ml_act && (!select_only || (ml_act->flag & SELECT))) {
+ copy_v3_v3(r_center, &ml_act->x);
+ return true;
+ }
+ break;
+ }
+ case OB_LATTICE: {
+ BPoint *actbp = BKE_lattice_active_point_get(obedit->data);
+
+ if (actbp) {
+ copy_v3_v3(r_center, actbp->vec);
+ return true;
+ }
+ break;
+ }
+ }
+
+ return false;
}
-bool ED_object_calc_active_center_for_posemode(
- Object *ob, const bool select_only, float r_center[3])
+bool ED_object_calc_active_center_for_posemode(Object *ob,
+ const bool select_only,
+ float r_center[3])
{
- bPoseChannel *pchan = BKE_pose_channel_active(ob);
- if (pchan && (!select_only || (pchan->bone->flag & BONE_SELECTED))) {
- copy_v3_v3(r_center, pchan->pose_head);
- return true;
- }
- return false;
+ bPoseChannel *pchan = BKE_pose_channel_active(ob);
+ if (pchan && (!select_only || (pchan->bone->flag & BONE_SELECTED))) {
+ copy_v3_v3(r_center, pchan->pose_head);
+ return true;
+ }
+ return false;
}
-bool ED_object_calc_active_center(
- Object *ob, const bool select_only, float r_center[3])
+bool ED_object_calc_active_center(Object *ob, const bool select_only, float r_center[3])
{
- if (ob->mode & OB_MODE_EDIT) {
- if (ED_object_calc_active_center_for_editmode(ob, select_only, r_center)) {
- mul_m4_v3(ob->obmat, r_center);
- return true;
- }
- return false;
- }
- else if (ob->mode & OB_MODE_POSE) {
- if (ED_object_calc_active_center_for_posemode(ob, select_only, r_center)) {
- mul_m4_v3(ob->obmat, r_center);
- return true;
- }
- return false;
- }
- else {
- if (!select_only || (ob->flag & SELECT)) {
- copy_v3_v3(r_center, ob->obmat[3]);
- return true;
- }
- return false;
- }
+ if (ob->mode & OB_MODE_EDIT) {
+ if (ED_object_calc_active_center_for_editmode(ob, select_only, r_center)) {
+ mul_m4_v3(ob->obmat, r_center);
+ return true;
+ }
+ return false;
+ }
+ else if (ob->mode & OB_MODE_POSE) {
+ if (ED_object_calc_active_center_for_posemode(ob, select_only, r_center)) {
+ mul_m4_v3(ob->obmat, r_center);
+ return true;
+ }
+ return false;
+ }
+ else {
+ if (!select_only || (ob->flag & SELECT)) {
+ copy_v3_v3(r_center, ob->obmat[3]);
+ return true;
+ }
+ return false;
+ }
}
/** \} */
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index cd8b7d082ef..9af0b64bde2 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -44,7 +44,6 @@
#include "BLI_utildefines.h"
#include "BLI_utildefines_stack.h"
-
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_deform.h"
@@ -78,40 +77,39 @@
/************************ Exported Functions **********************/
static bool vertex_group_use_vert_sel(Object *ob)
{
- if (ob->mode == OB_MODE_EDIT) {
- return true;
- }
- else if ((ob->type == OB_MESH) &&
- ((Mesh *)ob->data)->editflag & (ME_EDIT_PAINT_VERT_SEL | ME_EDIT_PAINT_FACE_SEL))
- {
- return true;
- }
- else {
- return false;
- }
+ if (ob->mode == OB_MODE_EDIT) {
+ return true;
+ }
+ else if ((ob->type == OB_MESH) &&
+ ((Mesh *)ob->data)->editflag & (ME_EDIT_PAINT_VERT_SEL | ME_EDIT_PAINT_FACE_SEL)) {
+ return true;
+ }
+ else {
+ return false;
+ }
}
static Lattice *vgroup_edit_lattice(Object *ob)
{
- Lattice *lt = ob->data;
- BLI_assert(ob->type == OB_LATTICE);
- return (lt->editlatt) ? lt->editlatt->latt : lt;
+ Lattice *lt = ob->data;
+ BLI_assert(ob->type == OB_LATTICE);
+ return (lt->editlatt) ? lt->editlatt->latt : lt;
}
bool ED_vgroup_sync_from_pose(Object *ob)
{
- Object *armobj = BKE_object_pose_armature_get(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);
- if (def_num != -1) {
- ob->actdef = def_num + 1;
- return true;
- }
- }
- }
- return false;
+ Object *armobj = BKE_object_pose_armature_get(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);
+ if (def_num != -1) {
+ ob->actdef = def_num + 1;
+ return true;
+ }
+ }
+ }
+ return false;
}
/**
@@ -119,128 +117,128 @@ bool ED_vgroup_sync_from_pose(Object *ob)
*/
void ED_vgroup_data_clamp_range(ID *id, const int total)
{
- MDeformVert **dvert_arr;
- int dvert_tot;
-
- if (ED_vgroup_parray_alloc(id, &dvert_arr, &dvert_tot, false)) {
- int i;
- for (i = 0; i < dvert_tot; i++) {
- MDeformVert *dv = dvert_arr[i];
- int j;
- for (j = 0; j < dv->totweight; j++) {
- if (dv->dw[j].def_nr >= total) {
- defvert_remove_group(dv, &dv->dw[j]);
- j--;
- }
- }
- }
- }
-}
-
-bool ED_vgroup_parray_alloc(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, const bool use_vert_sel)
-{
- *dvert_tot = 0;
- *dvert_arr = NULL;
-
- if (id) {
- switch (GS(id->name)) {
- case ID_ME:
- {
- Mesh *me = (Mesh *)id;
-
- if (me->edit_mesh) {
- BMEditMesh *em = me->edit_mesh;
- BMesh *bm = em->bm;
- const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
- BMIter iter;
- BMVert *eve;
- int i;
-
- if (cd_dvert_offset == -1) {
- return false;
- }
-
- i = em->bm->totvert;
-
- *dvert_arr = MEM_mallocN(sizeof(void *) * i, "vgroup parray from me");
- *dvert_tot = i;
-
- i = 0;
- if (use_vert_sel) {
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- (*dvert_arr)[i] = BM_elem_flag_test(eve, BM_ELEM_SELECT) ?
- BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset) : NULL;
- i++;
- }
- }
- else {
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- (*dvert_arr)[i] = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- i++;
- }
- }
-
- return true;
- }
- else if (me->dvert) {
- MVert *mvert = me->mvert;
- MDeformVert *dvert = me->dvert;
- int i;
-
- *dvert_tot = me->totvert;
- *dvert_arr = MEM_mallocN(sizeof(void *) * me->totvert, "vgroup parray from me");
-
- if (use_vert_sel) {
- for (i = 0; i < me->totvert; i++) {
- (*dvert_arr)[i] = (mvert[i].flag & SELECT) ?
- &dvert[i] : NULL;
- }
- }
- else {
- for (i = 0; i < me->totvert; i++) {
- (*dvert_arr)[i] = me->dvert + i;
- }
- }
-
- return true;
- }
- return false;
- }
- case ID_LT:
- {
- int i = 0;
-
- Lattice *lt = (Lattice *)id;
- lt = (lt->editlatt) ? lt->editlatt->latt : lt;
-
- if (lt->dvert) {
- BPoint *def = lt->def;
- *dvert_tot = lt->pntsu * lt->pntsv * lt->pntsw;
- *dvert_arr = MEM_mallocN(sizeof(void *) * (*dvert_tot), "vgroup parray from me");
-
- if (use_vert_sel) {
- for (i = 0; i < *dvert_tot; i++) {
- (*dvert_arr)[i] = (def->f1 & SELECT) ?
- &lt->dvert[i] : NULL;
- }
- }
- else {
- for (i = 0; i < *dvert_tot; i++) {
- (*dvert_arr)[i] = lt->dvert + i;
- }
- }
-
- return true;
- }
- return false;
- }
-
- default:
- break;
- }
- }
-
- return false;
+ MDeformVert **dvert_arr;
+ int dvert_tot;
+
+ if (ED_vgroup_parray_alloc(id, &dvert_arr, &dvert_tot, false)) {
+ int i;
+ for (i = 0; i < dvert_tot; i++) {
+ MDeformVert *dv = dvert_arr[i];
+ int j;
+ for (j = 0; j < dv->totweight; j++) {
+ if (dv->dw[j].def_nr >= total) {
+ defvert_remove_group(dv, &dv->dw[j]);
+ j--;
+ }
+ }
+ }
+ }
+}
+
+bool ED_vgroup_parray_alloc(ID *id,
+ MDeformVert ***dvert_arr,
+ int *dvert_tot,
+ const bool use_vert_sel)
+{
+ *dvert_tot = 0;
+ *dvert_arr = NULL;
+
+ if (id) {
+ switch (GS(id->name)) {
+ case ID_ME: {
+ Mesh *me = (Mesh *)id;
+
+ if (me->edit_mesh) {
+ BMEditMesh *em = me->edit_mesh;
+ BMesh *bm = em->bm;
+ const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
+ BMIter iter;
+ BMVert *eve;
+ int i;
+
+ if (cd_dvert_offset == -1) {
+ return false;
+ }
+
+ i = em->bm->totvert;
+
+ *dvert_arr = MEM_mallocN(sizeof(void *) * i, "vgroup parray from me");
+ *dvert_tot = i;
+
+ i = 0;
+ if (use_vert_sel) {
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ (*dvert_arr)[i] = BM_elem_flag_test(eve, BM_ELEM_SELECT) ?
+ BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset) :
+ NULL;
+ i++;
+ }
+ }
+ else {
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ (*dvert_arr)[i] = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+ i++;
+ }
+ }
+
+ return true;
+ }
+ else if (me->dvert) {
+ MVert *mvert = me->mvert;
+ MDeformVert *dvert = me->dvert;
+ int i;
+
+ *dvert_tot = me->totvert;
+ *dvert_arr = MEM_mallocN(sizeof(void *) * me->totvert, "vgroup parray from me");
+
+ if (use_vert_sel) {
+ for (i = 0; i < me->totvert; i++) {
+ (*dvert_arr)[i] = (mvert[i].flag & SELECT) ? &dvert[i] : NULL;
+ }
+ }
+ else {
+ for (i = 0; i < me->totvert; i++) {
+ (*dvert_arr)[i] = me->dvert + i;
+ }
+ }
+
+ return true;
+ }
+ return false;
+ }
+ case ID_LT: {
+ int i = 0;
+
+ Lattice *lt = (Lattice *)id;
+ lt = (lt->editlatt) ? lt->editlatt->latt : lt;
+
+ if (lt->dvert) {
+ BPoint *def = lt->def;
+ *dvert_tot = lt->pntsu * lt->pntsv * lt->pntsw;
+ *dvert_arr = MEM_mallocN(sizeof(void *) * (*dvert_tot), "vgroup parray from me");
+
+ if (use_vert_sel) {
+ for (i = 0; i < *dvert_tot; i++) {
+ (*dvert_arr)[i] = (def->f1 & SELECT) ? &lt->dvert[i] : NULL;
+ }
+ }
+ else {
+ for (i = 0; i < *dvert_tot; i++) {
+ (*dvert_arr)[i] = lt->dvert + i;
+ }
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ return false;
}
/**
@@ -249,45 +247,46 @@ bool ED_vgroup_parray_alloc(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, co
*
* \note \a dvert_array has mirrored weights filled in, in case cleanup operations are needed on both.
*/
-void ED_vgroup_parray_mirror_sync(
- Object *ob,
- MDeformVert **dvert_array, const int dvert_tot,
- const bool *vgroup_validmap, const int vgroup_tot)
-{
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- MDeformVert **dvert_array_all = NULL;
- int dvert_tot_all;
-
- /* get an array of all verts, not only selected */
- if (ED_vgroup_parray_alloc(ob->data, &dvert_array_all, &dvert_tot_all, false) == false) {
- BLI_assert(0);
- return;
- }
- if (em) {
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
- }
-
- int flip_map_len;
- const int *flip_map = 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) {
- /* its selected, check if its mirror exists */
- int i_dst = ED_mesh_mirror_get_vert(ob, i_src);
- if (i_dst != -1 && dvert_array_all[i_dst] != NULL) {
- /* we found a match! */
- 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);
-
- dvert_array[i_dst] = dvert_array_all[i_dst];
- }
- }
- }
-
- MEM_freeN((void *)flip_map);
- MEM_freeN(dvert_array_all);
+void ED_vgroup_parray_mirror_sync(Object *ob,
+ MDeformVert **dvert_array,
+ const int dvert_tot,
+ const bool *vgroup_validmap,
+ const int vgroup_tot)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ MDeformVert **dvert_array_all = NULL;
+ int dvert_tot_all;
+
+ /* get an array of all verts, not only selected */
+ if (ED_vgroup_parray_alloc(ob->data, &dvert_array_all, &dvert_tot_all, false) == false) {
+ BLI_assert(0);
+ return;
+ }
+ if (em) {
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ }
+
+ int flip_map_len;
+ const int *flip_map = 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) {
+ /* its selected, check if its mirror exists */
+ int i_dst = ED_mesh_mirror_get_vert(ob, i_src);
+ if (i_dst != -1 && dvert_array_all[i_dst] != NULL) {
+ /* we found a match! */
+ 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);
+
+ dvert_array[i_dst] = dvert_array_all[i_dst];
+ }
+ }
+ }
+
+ MEM_freeN((void *)flip_map);
+ MEM_freeN(dvert_array_all);
}
/**
@@ -295,247 +294,252 @@ void ED_vgroup_parray_mirror_sync(
*
* similar to #ED_vgroup_parray_mirror_sync but only fill in mirror points.
*/
-void ED_vgroup_parray_mirror_assign(
- Object *ob,
- MDeformVert **dvert_array, const int dvert_tot)
-{
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- MDeformVert **dvert_array_all = NULL;
- int dvert_tot_all;
- int i;
-
- /* get an array of all verts, not only selected */
- if (ED_vgroup_parray_alloc(ob->data, &dvert_array_all, &dvert_tot_all, false) == false) {
- BLI_assert(0);
- return;
- }
- BLI_assert(dvert_tot == dvert_tot_all);
- if (em) {
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
- }
-
- for (i = 0; i < dvert_tot; i++) {
- if (dvert_array[i] == NULL) {
- /* its unselected, check if its mirror is */
- int i_sel = ED_mesh_mirror_get_vert(ob, i);
- if ((i_sel != -1) && (i_sel != i) && (dvert_array[i_sel])) {
- /* we found a match! */
- dvert_array[i] = dvert_array_all[i];
- }
- }
- }
-
- MEM_freeN(dvert_array_all);
-}
-
-void ED_vgroup_parray_remove_zero(
- MDeformVert **dvert_array, const int dvert_tot,
- const bool *vgroup_validmap, const int vgroup_tot,
- const float epsilon, const bool keep_single)
-{
- MDeformVert *dv;
- int i;
-
- for (i = 0; i < dvert_tot; i++) {
- int j;
-
- /* in case its not selected */
- if (!(dv = dvert_array[i])) {
- continue;
- }
-
- j = dv->totweight;
-
- while (j--) {
- MDeformWeight *dw;
-
- if (keep_single && dv->totweight == 1)
- break;
-
- dw = dv->dw + j;
- if ((dw->def_nr < vgroup_tot) && vgroup_validmap[dw->def_nr]) {
- if (dw->weight <= epsilon) {
- defvert_remove_group(dv, dw);
- }
- }
- }
- }
+void ED_vgroup_parray_mirror_assign(Object *ob, MDeformVert **dvert_array, const int dvert_tot)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ MDeformVert **dvert_array_all = NULL;
+ int dvert_tot_all;
+ int i;
+
+ /* get an array of all verts, not only selected */
+ if (ED_vgroup_parray_alloc(ob->data, &dvert_array_all, &dvert_tot_all, false) == false) {
+ BLI_assert(0);
+ return;
+ }
+ BLI_assert(dvert_tot == dvert_tot_all);
+ if (em) {
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ }
+
+ for (i = 0; i < dvert_tot; i++) {
+ if (dvert_array[i] == NULL) {
+ /* its unselected, check if its mirror is */
+ int i_sel = ED_mesh_mirror_get_vert(ob, i);
+ if ((i_sel != -1) && (i_sel != i) && (dvert_array[i_sel])) {
+ /* we found a match! */
+ dvert_array[i] = dvert_array_all[i];
+ }
+ }
+ }
+
+ MEM_freeN(dvert_array_all);
+}
+
+void ED_vgroup_parray_remove_zero(MDeformVert **dvert_array,
+ const int dvert_tot,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const float epsilon,
+ const bool keep_single)
+{
+ MDeformVert *dv;
+ int i;
+
+ for (i = 0; i < dvert_tot; i++) {
+ int j;
+
+ /* in case its not selected */
+ if (!(dv = dvert_array[i])) {
+ continue;
+ }
+
+ j = dv->totweight;
+
+ while (j--) {
+ MDeformWeight *dw;
+
+ if (keep_single && dv->totweight == 1)
+ break;
+
+ dw = dv->dw + j;
+ if ((dw->def_nr < vgroup_tot) && vgroup_validmap[dw->def_nr]) {
+ if (dw->weight <= epsilon) {
+ defvert_remove_group(dv, dw);
+ }
+ }
+ }
+ }
}
/* matching index only */
bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
{
- MDeformVert **dvert_array_from = NULL, **dvf;
- MDeformVert **dvert_array = NULL, **dv;
- int dvert_tot_from;
- int dvert_tot;
- int i;
- int defbase_tot_from = BLI_listbase_count(&ob_from->defbase);
- int defbase_tot = BLI_listbase_count(&ob->defbase);
- bool new_vgroup = false;
-
- if (ob == ob_from)
- return true;
-
- /* in case we copy vgroup between two objects using same data, we only have to care about object side of things. */
- if (ob->data != ob_from->data) {
- ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false);
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
-
- if ((dvert_array == NULL) && (dvert_array_from != NULL) && BKE_object_defgroup_data_create(ob->data)) {
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
- new_vgroup = true;
- }
-
- if (dvert_tot == 0 || (dvert_tot != dvert_tot_from) || dvert_array_from == NULL || dvert_array == NULL) {
- if (dvert_array)
- MEM_freeN(dvert_array);
- if (dvert_array_from)
- MEM_freeN(dvert_array_from);
-
- if (new_vgroup == true) {
- /* free the newly added vgroup since it wasn't compatible */
- BKE_object_defgroup_remove_all(ob);
- }
-
- /* if true: both are 0 and nothing needs changing, consider this a success */
- return (dvert_tot == dvert_tot_from);
- }
- }
-
- /* do the copy */
- BLI_freelistN(&ob->defbase);
- BLI_duplicatelist(&ob->defbase, &ob_from->defbase);
- ob->actdef = ob_from->actdef;
-
- if (defbase_tot_from < defbase_tot) {
- /* correct vgroup indices because the number of vgroups is being reduced. */
- int *remap = MEM_mallocN(sizeof(int) * (defbase_tot + 1), __func__);
- for (i = 0; i <= defbase_tot_from; i++) remap[i] = i;
- for (; i <= defbase_tot; i++) remap[i] = 0; /* can't use these, so disable */
-
- BKE_object_defgroup_remap_update_users(ob, remap);
- MEM_freeN(remap);
- }
-
- if (dvert_array_from != NULL && dvert_array != NULL) {
- dvf = dvert_array_from;
- dv = dvert_array;
-
- for (i = 0; i < dvert_tot; i++, dvf++, dv++) {
- MEM_SAFE_FREE((*dv)->dw);
- *(*dv) = *(*dvf);
-
- if ((*dv)->dw) {
- (*dv)->dw = MEM_dupallocN((*dv)->dw);
- }
- }
-
- MEM_freeN(dvert_array);
- MEM_freeN(dvert_array_from);
- }
-
- return true;
-}
-
-void ED_vgroup_parray_to_weight_array(
- const MDeformVert **dvert_array, const int dvert_tot,
- float *dvert_weights, const int def_nr)
-{
- int i;
-
- 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;
- }
-}
-
-void ED_vgroup_parray_from_weight_array(
- MDeformVert **dvert_array, const int dvert_tot,
- const float *dvert_weights, const int def_nr, const bool remove_zero)
-{
- int i;
-
- for (i = 0; i < dvert_tot; i++) {
- MDeformVert *dv = dvert_array[i];
- if (dv) {
- if (dvert_weights[i] > 0.0f) {
- MDeformWeight *dw = defvert_verify_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);
- if (dw) {
- if (remove_zero) {
- defvert_remove_group(dv, dw);
- }
- else {
- dw->weight = 0.0f;
- }
- }
- }
- }
- }
+ MDeformVert **dvert_array_from = NULL, **dvf;
+ MDeformVert **dvert_array = NULL, **dv;
+ int dvert_tot_from;
+ int dvert_tot;
+ int i;
+ int defbase_tot_from = BLI_listbase_count(&ob_from->defbase);
+ int defbase_tot = BLI_listbase_count(&ob->defbase);
+ bool new_vgroup = false;
+
+ if (ob == ob_from)
+ return true;
+
+ /* in case we copy vgroup between two objects using same data, we only have to care about object side of things. */
+ if (ob->data != ob_from->data) {
+ ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false);
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
+
+ if ((dvert_array == NULL) && (dvert_array_from != NULL) &&
+ BKE_object_defgroup_data_create(ob->data)) {
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
+ new_vgroup = true;
+ }
+
+ if (dvert_tot == 0 || (dvert_tot != dvert_tot_from) || dvert_array_from == NULL ||
+ dvert_array == NULL) {
+ if (dvert_array)
+ MEM_freeN(dvert_array);
+ if (dvert_array_from)
+ MEM_freeN(dvert_array_from);
+
+ if (new_vgroup == true) {
+ /* free the newly added vgroup since it wasn't compatible */
+ BKE_object_defgroup_remove_all(ob);
+ }
+
+ /* if true: both are 0 and nothing needs changing, consider this a success */
+ return (dvert_tot == dvert_tot_from);
+ }
+ }
+
+ /* do the copy */
+ BLI_freelistN(&ob->defbase);
+ BLI_duplicatelist(&ob->defbase, &ob_from->defbase);
+ ob->actdef = ob_from->actdef;
+
+ if (defbase_tot_from < defbase_tot) {
+ /* correct vgroup indices because the number of vgroups is being reduced. */
+ int *remap = MEM_mallocN(sizeof(int) * (defbase_tot + 1), __func__);
+ for (i = 0; i <= defbase_tot_from; i++)
+ remap[i] = i;
+ for (; i <= defbase_tot; i++)
+ remap[i] = 0; /* can't use these, so disable */
+
+ BKE_object_defgroup_remap_update_users(ob, remap);
+ MEM_freeN(remap);
+ }
+
+ if (dvert_array_from != NULL && dvert_array != NULL) {
+ dvf = dvert_array_from;
+ dv = dvert_array;
+
+ for (i = 0; i < dvert_tot; i++, dvf++, dv++) {
+ MEM_SAFE_FREE((*dv)->dw);
+ *(*dv) = *(*dvf);
+
+ if ((*dv)->dw) {
+ (*dv)->dw = MEM_dupallocN((*dv)->dw);
+ }
+ }
+
+ MEM_freeN(dvert_array);
+ MEM_freeN(dvert_array_from);
+ }
+
+ return true;
}
+void ED_vgroup_parray_to_weight_array(const MDeformVert **dvert_array,
+ const int dvert_tot,
+ float *dvert_weights,
+ const int def_nr)
+{
+ int i;
-/* TODO, cache flip data to speedup calls within a loop. */
-static void mesh_defvert_mirror_update_internal(
- Object *ob,
- MDeformVert *dvert_dst, MDeformVert *dvert_src,
- const int def_nr)
-{
- 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);
- MEM_freeN(flip_map);
- }
- else {
- /* single vgroup */
- MDeformWeight *dw = defvert_verify_index(dvert_dst, defgroup_flip_index(ob, def_nr, 1));
- if (dw) {
- dw->weight = defvert_find_weight(dvert_src, def_nr);
- }
- }
+ 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;
+ }
}
-static void ED_mesh_defvert_mirror_update_em(
- Object *ob, BMVert *eve, int def_nr, int vidx,
- const int cd_dvert_offset)
+void ED_vgroup_parray_from_weight_array(MDeformVert **dvert_array,
+ const int dvert_tot,
+ const float *dvert_weights,
+ const int def_nr,
+ const bool remove_zero)
{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- BMVert *eve_mirr;
- bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+ int i;
+
+ for (i = 0; i < dvert_tot; i++) {
+ MDeformVert *dv = dvert_array[i];
+ if (dv) {
+ if (dvert_weights[i] > 0.0f) {
+ MDeformWeight *dw = defvert_verify_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);
+ if (dw) {
+ if (remove_zero) {
+ defvert_remove_group(dv, dw);
+ }
+ else {
+ dw->weight = 0.0f;
+ }
+ }
+ }
+ }
+ }
+}
- eve_mirr = editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, vidx, use_topology);
+/* TODO, cache flip data to speedup calls within a loop. */
+static void mesh_defvert_mirror_update_internal(Object *ob,
+ MDeformVert *dvert_dst,
+ MDeformVert *dvert_src,
+ const int def_nr)
+{
+ 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);
+ MEM_freeN(flip_map);
+ }
+ else {
+ /* single vgroup */
+ MDeformWeight *dw = defvert_verify_index(dvert_dst, defgroup_flip_index(ob, def_nr, 1));
+ if (dw) {
+ dw->weight = defvert_find_weight(dvert_src, def_nr);
+ }
+ }
+}
- if (eve_mirr && eve_mirr != eve) {
- MDeformVert *dvert_src = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- MDeformVert *dvert_dst = BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset);
- mesh_defvert_mirror_update_internal(ob, dvert_dst, dvert_src, def_nr);
- }
+static void ED_mesh_defvert_mirror_update_em(
+ Object *ob, BMVert *eve, int def_nr, int vidx, const int cd_dvert_offset)
+{
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ BMVert *eve_mirr;
+ bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+
+ eve_mirr = editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, vidx, use_topology);
+
+ if (eve_mirr && eve_mirr != eve) {
+ MDeformVert *dvert_src = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+ MDeformVert *dvert_dst = BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset);
+ mesh_defvert_mirror_update_internal(ob, dvert_dst, dvert_src, def_nr);
+ }
}
static void ED_mesh_defvert_mirror_update_ob(Object *ob, int def_nr, int vidx)
{
- int vidx_mirr;
- Mesh *me = ob->data;
- bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+ int vidx_mirr;
+ Mesh *me = ob->data;
+ bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
- if (vidx == -1)
- return;
+ if (vidx == -1)
+ return;
- vidx_mirr = mesh_get_x_mirror_vert(ob, NULL, vidx, use_topology);
+ vidx_mirr = mesh_get_x_mirror_vert(ob, NULL, vidx, use_topology);
- if ((vidx_mirr) >= 0 && (vidx_mirr != vidx)) {
- MDeformVert *dvert_src = &me->dvert[vidx];
- MDeformVert *dvert_dst = &me->dvert[vidx_mirr];
- mesh_defvert_mirror_update_internal(ob, dvert_dst, dvert_src, def_nr);
- }
+ if ((vidx_mirr) >= 0 && (vidx_mirr != vidx)) {
+ MDeformVert *dvert_src = &me->dvert[vidx];
+ MDeformVert *dvert_dst = &me->dvert[vidx_mirr];
+ mesh_defvert_mirror_update_internal(ob, dvert_dst, dvert_src, def_nr);
+ }
}
/**
@@ -543,420 +547,426 @@ static void ED_mesh_defvert_mirror_update_ob(Object *ob, int def_nr, int vidx)
*/
void ED_vgroup_vert_active_mirror(Object *ob, int def_nr)
{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- MDeformVert *dvert_act;
-
- if (me->editflag & ME_EDIT_MIRROR_X) {
- if (em) {
- BMVert *eve_act;
- dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
- if (dvert_act) {
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
- ED_mesh_defvert_mirror_update_em(ob, eve_act, def_nr, -1, cd_dvert_offset);
- }
- }
- else {
- int v_act;
- dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
- if (dvert_act) {
- ED_mesh_defvert_mirror_update_ob(ob, def_nr, v_act);
- }
- }
- }
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ MDeformVert *dvert_act;
+
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ if (em) {
+ BMVert *eve_act;
+ dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
+ if (dvert_act) {
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+ ED_mesh_defvert_mirror_update_em(ob, eve_act, def_nr, -1, cd_dvert_offset);
+ }
+ }
+ else {
+ int v_act;
+ dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
+ if (dvert_act) {
+ ED_mesh_defvert_mirror_update_ob(ob, def_nr, v_act);
+ }
+ }
+ }
}
static void vgroup_remove_weight(Object *ob, const int def_nr)
{
- MDeformVert *dvert_act;
- MDeformWeight *dw;
-
- dvert_act = ED_mesh_active_dvert_get_only(ob);
+ MDeformVert *dvert_act;
+ MDeformWeight *dw;
- dw = defvert_find_index(dvert_act, def_nr);
- defvert_remove_group(dvert_act, dw);
+ dvert_act = ED_mesh_active_dvert_get_only(ob);
+ dw = defvert_find_index(dvert_act, def_nr);
+ defvert_remove_group(dvert_act, dw);
}
static bool vgroup_normalize_active_vertex(Object *ob, eVGroupSelect subset_type)
{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- BMVert *eve_act;
- int v_act;
- MDeformVert *dvert_act;
- int subset_count, vgroup_tot;
- const bool *vgroup_validmap;
-
-
- if (em) {
- dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
- }
- else {
- dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
- }
-
- if (dvert_act == NULL) {
- return false;
- }
-
- 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);
- MEM_freeN((void *)vgroup_validmap);
-
- if (me->editflag & ME_EDIT_MIRROR_X) {
- if (em) {
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
- ED_mesh_defvert_mirror_update_em(ob, eve_act, -1, -1, cd_dvert_offset);
- }
- else {
- ED_mesh_defvert_mirror_update_ob(ob, -1, v_act);
- }
- }
-
- return true;
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ BMVert *eve_act;
+ int v_act;
+ MDeformVert *dvert_act;
+ int subset_count, vgroup_tot;
+ const bool *vgroup_validmap;
+
+ if (em) {
+ dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
+ }
+ else {
+ dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
+ }
+
+ if (dvert_act == NULL) {
+ return false;
+ }
+
+ 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);
+ MEM_freeN((void *)vgroup_validmap);
+
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ if (em) {
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+ ED_mesh_defvert_mirror_update_em(ob, eve_act, -1, -1, cd_dvert_offset);
+ }
+ else {
+ ED_mesh_defvert_mirror_update_ob(ob, -1, v_act);
+ }
+ }
+
+ return true;
}
static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type)
{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- MDeformVert *dvert_act;
- int i, vgroup_tot, subset_count;
- const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
-
-
- if (em) {
- BMIter iter;
- BMVert *eve, *eve_act;
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
-
- dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
- if (dvert_act) {
- 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);
- if (me->editflag & ME_EDIT_MIRROR_X) {
- ED_mesh_defvert_mirror_update_em(ob, eve, -1, i, cd_dvert_offset);
- }
- }
- }
- }
- }
- else {
- MDeformVert *dv;
- int v_act;
-
- dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
- if (dvert_act) {
- 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);
- if (me->editflag & ME_EDIT_MIRROR_X) {
- ED_mesh_defvert_mirror_update_ob(ob, -1, i);
- }
- }
- }
- }
- }
-
- MEM_freeN((void *)vgroup_validmap);
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ MDeformVert *dvert_act;
+ int i, vgroup_tot, subset_count;
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
+ ob, subset_type, &vgroup_tot, &subset_count);
+
+ if (em) {
+ BMIter iter;
+ BMVert *eve, *eve_act;
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+
+ dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
+ if (dvert_act) {
+ 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);
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ ED_mesh_defvert_mirror_update_em(ob, eve, -1, i, cd_dvert_offset);
+ }
+ }
+ }
+ }
+ }
+ else {
+ MDeformVert *dv;
+ int v_act;
+
+ dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
+ if (dvert_act) {
+ 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);
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ ED_mesh_defvert_mirror_update_ob(ob, -1, i);
+ }
+ }
+ }
+ }
+ }
+
+ MEM_freeN((void *)vgroup_validmap);
}
/***********************Start weight transfer (WT)*********************************/
static const EnumPropertyItem WT_vertex_group_select_item[] = {
- {WT_VGROUP_ACTIVE,
- "ACTIVE", 0, "Active Group", "The active Vertex Group"},
- {WT_VGROUP_BONE_SELECT,
- "BONE_SELECT", 0, "Selected Pose Bones", "All Vertex Groups assigned to Selection"},
- {WT_VGROUP_BONE_DEFORM,
- "BONE_DEFORM", 0, "Deform Pose Bones", "All Vertex Groups assigned to Deform Bones"},
- {WT_VGROUP_ALL,
- "ALL", 0, "All Groups", "All Vertex Groups"},
- {0, NULL, 0, NULL, NULL},
+ {WT_VGROUP_ACTIVE, "ACTIVE", 0, "Active Group", "The active Vertex Group"},
+ {WT_VGROUP_BONE_SELECT,
+ "BONE_SELECT",
+ 0,
+ "Selected Pose Bones",
+ "All Vertex Groups assigned to Selection"},
+ {WT_VGROUP_BONE_DEFORM,
+ "BONE_DEFORM",
+ 0,
+ "Deform Pose Bones",
+ "All Vertex Groups assigned to Deform Bones"},
+ {WT_VGROUP_ALL, "ALL", 0, "All Groups", "All Vertex Groups"},
+ {0, NULL, 0, NULL, NULL},
};
-const EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(
- const bContext *C, PointerRNA *UNUSED(ptr),
- PropertyRNA *UNUSED(prop), bool *r_free, const unsigned int selection_mask)
+const EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(const bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free,
+ const unsigned int selection_mask)
{
- Object *ob;
- EnumPropertyItem *item = NULL;
- int totitem = 0;
-
- if (C == NULL) {
- /* needed for docs and i18n tools */
- return WT_vertex_group_select_item;
- }
-
- ob = CTX_data_active_object(C);
- if (selection_mask & (1 << WT_VGROUP_ACTIVE))
- RNA_enum_items_add_value(&item, &totitem, WT_vertex_group_select_item, WT_VGROUP_ACTIVE);
-
- if (BKE_object_pose_armature_get(ob)) {
- if (selection_mask & (1 << WT_VGROUP_BONE_SELECT))
- RNA_enum_items_add_value(&item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_SELECT);
- if (selection_mask & (1 << WT_VGROUP_BONE_DEFORM))
- RNA_enum_items_add_value(&item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_DEFORM);
- }
-
- if (selection_mask & (1 << WT_VGROUP_ALL))
- RNA_enum_items_add_value(&item, &totitem, WT_vertex_group_select_item, WT_VGROUP_ALL);
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ Object *ob;
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+
+ if (C == NULL) {
+ /* needed for docs and i18n tools */
+ return WT_vertex_group_select_item;
+ }
+
+ ob = CTX_data_active_object(C);
+ if (selection_mask & (1 << WT_VGROUP_ACTIVE))
+ RNA_enum_items_add_value(&item, &totitem, WT_vertex_group_select_item, WT_VGROUP_ACTIVE);
+
+ if (BKE_object_pose_armature_get(ob)) {
+ if (selection_mask & (1 << WT_VGROUP_BONE_SELECT))
+ RNA_enum_items_add_value(
+ &item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_SELECT);
+ if (selection_mask & (1 << WT_VGROUP_BONE_DEFORM))
+ RNA_enum_items_add_value(
+ &item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_DEFORM);
+ }
+
+ if (selection_mask & (1 << WT_VGROUP_ALL))
+ RNA_enum_items_add_value(&item, &totitem, WT_vertex_group_select_item, WT_VGROUP_ALL);
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
-static const EnumPropertyItem *rna_vertex_group_with_single_itemf(
- bContext *C, PointerRNA *ptr,
- PropertyRNA *prop, bool *r_free)
+static const EnumPropertyItem *rna_vertex_group_with_single_itemf(bContext *C,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ bool *r_free)
{
- return ED_object_vgroup_selection_itemf_helper(C, ptr, prop, r_free, WT_VGROUP_MASK_ALL);
+ return ED_object_vgroup_selection_itemf_helper(C, ptr, prop, r_free, WT_VGROUP_MASK_ALL);
}
-static const EnumPropertyItem *rna_vertex_group_select_itemf(
- bContext *C, PointerRNA *ptr,
- PropertyRNA *prop, bool *r_free)
+static const EnumPropertyItem *rna_vertex_group_select_itemf(bContext *C,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ bool *r_free)
{
- return ED_object_vgroup_selection_itemf_helper(
- C, ptr, prop, r_free, WT_VGROUP_MASK_ALL & ~(1 << WT_VGROUP_ACTIVE));
+ return ED_object_vgroup_selection_itemf_helper(
+ C, ptr, prop, r_free, WT_VGROUP_MASK_ALL & ~(1 << WT_VGROUP_ACTIVE));
}
static void vgroup_operator_subset_select_props(wmOperatorType *ot, bool use_active)
{
- PropertyRNA *prop;
-
- prop = RNA_def_enum(
- ot->srna,
- "group_select_mode", DummyRNA_NULL_items,
- use_active ? WT_VGROUP_ACTIVE : WT_VGROUP_ALL, "Subset",
- "Define which subset of Groups shall be used");
-
- if (use_active) {
- RNA_def_enum_funcs(prop, rna_vertex_group_with_single_itemf);
- }
- else {
- RNA_def_enum_funcs(prop, rna_vertex_group_select_itemf);
- }
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ prop = RNA_def_enum(ot->srna,
+ "group_select_mode",
+ DummyRNA_NULL_items,
+ use_active ? WT_VGROUP_ACTIVE : WT_VGROUP_ALL,
+ "Subset",
+ "Define which subset of Groups shall be used");
+
+ if (use_active) {
+ RNA_def_enum_funcs(prop, rna_vertex_group_with_single_itemf);
+ }
+ else {
+ RNA_def_enum_funcs(prop, rna_vertex_group_select_itemf);
+ }
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
-
/***********************End weight transfer (WT)***********************************/
/* for Mesh in Object mode */
/* allows editmode for Lattice */
static void ED_vgroup_nr_vert_add(
- Object *ob,
- const int def_nr, const int vertnum,
- const float weight, const int assignmode)
-{
- /* add the vert to the deform group with the
- * specified number
- */
- MDeformVert *dvert = NULL;
- int tot;
-
- /* get the vert */
- BKE_object_defgroup_array_get(ob->data, &dvert, &tot);
-
- if (dvert == NULL)
- return;
-
- /* check that vertnum is valid before trying to get the relevant dvert */
- if ((vertnum < 0) || (vertnum >= tot))
- return;
-
-
- if (dvert) {
- MDeformVert *dv = &dvert[vertnum];
- 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);
-
- if (dw) {
- switch (assignmode) {
- case WEIGHT_REPLACE:
- dw->weight = weight;
- break;
- case WEIGHT_ADD:
- dw->weight += weight;
- if (dw->weight >= 1.0f)
- dw->weight = 1.0f;
- break;
- case WEIGHT_SUBTRACT:
- 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);
- }
- break;
- }
- }
- else {
- /* if the vert wasn't in the deform group then
- * we must take a different form of action ...
- */
-
- switch (assignmode) {
- case WEIGHT_SUBTRACT:
- /* if we are subtracting then we don't
- * need to do anything
- */
- return;
-
- case WEIGHT_REPLACE:
- case WEIGHT_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);
- break;
- }
- }
- }
+ Object *ob, const int def_nr, const int vertnum, const float weight, const int assignmode)
+{
+ /* add the vert to the deform group with the
+ * specified number
+ */
+ MDeformVert *dvert = NULL;
+ int tot;
+
+ /* get the vert */
+ BKE_object_defgroup_array_get(ob->data, &dvert, &tot);
+
+ if (dvert == NULL)
+ return;
+
+ /* check that vertnum is valid before trying to get the relevant dvert */
+ if ((vertnum < 0) || (vertnum >= tot))
+ return;
+
+ if (dvert) {
+ MDeformVert *dv = &dvert[vertnum];
+ 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);
+
+ if (dw) {
+ switch (assignmode) {
+ case WEIGHT_REPLACE:
+ dw->weight = weight;
+ break;
+ case WEIGHT_ADD:
+ dw->weight += weight;
+ if (dw->weight >= 1.0f)
+ dw->weight = 1.0f;
+ break;
+ case WEIGHT_SUBTRACT:
+ 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);
+ }
+ break;
+ }
+ }
+ else {
+ /* if the vert wasn't in the deform group then
+ * we must take a different form of action ...
+ */
+
+ switch (assignmode) {
+ case WEIGHT_SUBTRACT:
+ /* if we are subtracting then we don't
+ * need to do anything
+ */
+ return;
+
+ case WEIGHT_REPLACE:
+ case WEIGHT_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);
+ break;
+ }
+ }
+ }
}
/* called while not in editmode */
void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, int assignmode)
{
- /* add the vert to the deform group with the
- * specified assign mode
- */
- const int def_nr = BLI_findindex(&ob->defbase, dg);
-
- MDeformVert *dv = NULL;
- int tot;
-
- /* get the deform group number, exit if
- * it can't be found
- */
- if (def_nr != -1) {
-
- /* if there's no deform verts then create some,
- */
- if (BKE_object_defgroup_array_get(ob->data, &dv, &tot) && dv == NULL)
- BKE_object_defgroup_data_create(ob->data);
-
- /* call another function to do the work
- */
- ED_vgroup_nr_vert_add(ob, def_nr, vertnum, weight, assignmode);
- }
+ /* add the vert to the deform group with the
+ * specified assign mode
+ */
+ const int def_nr = BLI_findindex(&ob->defbase, dg);
+
+ MDeformVert *dv = NULL;
+ int tot;
+
+ /* get the deform group number, exit if
+ * it can't be found
+ */
+ if (def_nr != -1) {
+
+ /* if there's no deform verts then create some,
+ */
+ if (BKE_object_defgroup_array_get(ob->data, &dv, &tot) && dv == NULL)
+ BKE_object_defgroup_data_create(ob->data);
+
+ /* call another function to do the work
+ */
+ ED_vgroup_nr_vert_add(ob, def_nr, vertnum, weight, assignmode);
+ }
}
/* mesh object mode, lattice can be in editmode */
void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum)
{
- /* This routine removes the vertex from the specified
- * deform group.
- */
-
- /* TODO, this is slow in a loop, better pass def_nr directly, but leave for later... - campbell */
- const int def_nr = BLI_findindex(&ob->defbase, dg);
-
- if (def_nr != -1) {
- MDeformVert *dvert = NULL;
- int tot;
-
- /* get the deform vertices corresponding to the
- * vertnum
- */
- BKE_object_defgroup_array_get(ob->data, &dvert, &tot);
-
- if (dvert) {
- MDeformVert *dv = &dvert[vertnum];
- MDeformWeight *dw;
-
- dw = defvert_find_index(dv, def_nr);
- defvert_remove_group(dv, dw); /* dw can be NULL */
- }
- }
+ /* This routine removes the vertex from the specified
+ * deform group.
+ */
+
+ /* TODO, this is slow in a loop, better pass def_nr directly, but leave for later... - campbell */
+ const int def_nr = BLI_findindex(&ob->defbase, dg);
+
+ if (def_nr != -1) {
+ MDeformVert *dvert = NULL;
+ int tot;
+
+ /* get the deform vertices corresponding to the
+ * vertnum
+ */
+ BKE_object_defgroup_array_get(ob->data, &dvert, &tot);
+
+ if (dvert) {
+ MDeformVert *dv = &dvert[vertnum];
+ MDeformWeight *dw;
+
+ dw = defvert_find_index(dv, def_nr);
+ defvert_remove_group(dv, dw); /* dw can be NULL */
+ }
+ }
}
static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum)
{
- MDeformVert *dv = NULL;
-
- /* get the deform vertices corresponding to the vertnum */
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- if (me->edit_mesh) {
- BMEditMesh *em = me->edit_mesh;
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
- /* warning, this lookup is _not_ fast */
-
- if (cd_dvert_offset != -1 && vertnum < em->bm->totvert) {
- BMVert *eve;
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
- eve = BM_vert_at_index(em->bm, vertnum);
- dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- }
- else {
- return 0.0f;
- }
- }
- else {
- if (me->dvert) {
- if (vertnum >= me->totvert) {
- return 0.0f;
- }
- dv = &me->dvert[vertnum];
- }
- }
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = vgroup_edit_lattice(ob);
-
- if (lt->dvert) {
- if (vertnum >= lt->pntsu * lt->pntsv * lt->pntsw) {
- return 0.0f;
- }
- dv = &lt->dvert[vertnum];
- }
- }
-
- if (dv) {
- MDeformWeight *dw = defvert_find_index(dv, def_nr);
- if (dw) {
- return dw->weight;
- }
- }
-
- return -1;
+ MDeformVert *dv = NULL;
+
+ /* get the deform vertices corresponding to the vertnum */
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (me->edit_mesh) {
+ BMEditMesh *em = me->edit_mesh;
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+ /* warning, this lookup is _not_ fast */
+
+ if (cd_dvert_offset != -1 && vertnum < em->bm->totvert) {
+ BMVert *eve;
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ eve = BM_vert_at_index(em->bm, vertnum);
+ dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+ }
+ else {
+ return 0.0f;
+ }
+ }
+ else {
+ if (me->dvert) {
+ if (vertnum >= me->totvert) {
+ return 0.0f;
+ }
+ dv = &me->dvert[vertnum];
+ }
+ }
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = vgroup_edit_lattice(ob);
+
+ if (lt->dvert) {
+ if (vertnum >= lt->pntsu * lt->pntsv * lt->pntsw) {
+ return 0.0f;
+ }
+ dv = &lt->dvert[vertnum];
+ }
+ }
+
+ if (dv) {
+ MDeformWeight *dw = defvert_find_index(dv, def_nr);
+ if (dw) {
+ return dw->weight;
+ }
+ }
+
+ return -1;
}
float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum)
{
- const int def_nr = BLI_findindex(&ob->defbase, dg);
+ const int def_nr = BLI_findindex(&ob->defbase, dg);
- if (def_nr == -1) {
- return -1;
- }
+ if (def_nr == -1) {
+ return -1;
+ }
- return get_vert_def_nr(ob, def_nr, vertnum);
+ return get_vert_def_nr(ob, def_nr, vertnum);
}
void ED_vgroup_select_by_name(Object *ob, const char *name)
{
- /* note: ob->actdef==0 signals on painting to create a new one,
+ /* 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 = defgroup_name_index(ob, name) + 1;
}
/********************** Operator Implementations *********************/
@@ -964,186 +974,192 @@ void ED_vgroup_select_by_name(Object *ob, const char *name)
/* only in editmode */
static void vgroup_select_verts(Object *ob, int select)
{
- const int def_nr = ob->actdef - 1;
-
- if (!BLI_findlink(&ob->defbase, def_nr)) {
- return;
- }
-
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- if (me->edit_mesh) {
- BMEditMesh *em = me->edit_mesh;
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
-
- if (cd_dvert_offset != -1) {
- BMIter iter;
- BMVert *eve;
-
- 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)) {
- BM_vert_select_set(em->bm, eve, select);
- }
- }
- }
-
- /* this has to be called, because this function operates on vertices only */
- if (select) EDBM_select_flush(em); /* vertices to edges/faces */
- else EDBM_deselect_flush(em);
- }
- }
- else {
- if (me->dvert) {
- MVert *mv;
- MDeformVert *dv;
- int i;
-
- mv = me->mvert;
- dv = me->dvert;
-
- for (i = 0; i < me->totvert; i++, mv++, dv++) {
- if (!(mv->flag & ME_HIDE)) {
- if (defvert_find_index(dv, def_nr)) {
- if (select) mv->flag |= SELECT;
- else mv->flag &= ~SELECT;
- }
- }
- }
-
- paintvert_flush_flags(ob);
- }
- }
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = vgroup_edit_lattice(ob);
-
- if (lt->dvert) {
- MDeformVert *dv;
- BPoint *bp, *actbp = BKE_lattice_active_point_get(lt);
- int a, tot;
-
- dv = lt->dvert;
-
- 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 (select) bp->f1 |= SELECT;
- else {
- bp->f1 &= ~SELECT;
- if (actbp && bp == actbp) lt->actbp = LT_ACTBP_NONE;
- }
- }
- }
- }
- }
+ const int def_nr = ob->actdef - 1;
+
+ if (!BLI_findlink(&ob->defbase, def_nr)) {
+ return;
+ }
+
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (me->edit_mesh) {
+ BMEditMesh *em = me->edit_mesh;
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+
+ if (cd_dvert_offset != -1) {
+ BMIter iter;
+ BMVert *eve;
+
+ 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)) {
+ BM_vert_select_set(em->bm, eve, select);
+ }
+ }
+ }
+
+ /* this has to be called, because this function operates on vertices only */
+ if (select)
+ EDBM_select_flush(em); /* vertices to edges/faces */
+ else
+ EDBM_deselect_flush(em);
+ }
+ }
+ else {
+ if (me->dvert) {
+ MVert *mv;
+ MDeformVert *dv;
+ int i;
+
+ mv = me->mvert;
+ dv = me->dvert;
+
+ for (i = 0; i < me->totvert; i++, mv++, dv++) {
+ if (!(mv->flag & ME_HIDE)) {
+ if (defvert_find_index(dv, def_nr)) {
+ if (select)
+ mv->flag |= SELECT;
+ else
+ mv->flag &= ~SELECT;
+ }
+ }
+ }
+
+ paintvert_flush_flags(ob);
+ }
+ }
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = vgroup_edit_lattice(ob);
+
+ if (lt->dvert) {
+ MDeformVert *dv;
+ BPoint *bp, *actbp = BKE_lattice_active_point_get(lt);
+ int a, tot;
+
+ dv = lt->dvert;
+
+ 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 (select)
+ bp->f1 |= SELECT;
+ else {
+ bp->f1 &= ~SELECT;
+ if (actbp && bp == actbp)
+ lt->actbp = LT_ACTBP_NONE;
+ }
+ }
+ }
+ }
+ }
}
static void vgroup_duplicate(Object *ob)
{
- bDeformGroup *dg, *cdg;
- char name[sizeof(dg->name)];
- MDeformWeight *dw_org, *dw_cpy;
- MDeformVert **dvert_array = NULL;
- int i, idg, icdg, dvert_tot = 0;
-
- dg = BLI_findlink(&ob->defbase, (ob->actdef - 1));
- if (!dg)
- return;
-
- if (!strstr(dg->name, "_copy")) {
- BLI_snprintf(name, sizeof(name), "%s_copy", dg->name);
- }
- else {
- BLI_strncpy(name, dg->name, sizeof(name));
- }
-
- cdg = defgroup_duplicate(dg);
- BLI_strncpy(cdg->name, name, sizeof(cdg->name));
- defgroup_unique_name(cdg, ob);
-
- BLI_addtail(&ob->defbase, cdg);
-
- idg = (ob->actdef - 1);
- ob->actdef = BLI_listbase_count(&ob->defbase);
- icdg = (ob->actdef - 1);
-
- /* TODO, we might want to allow only copy selected verts here? - campbell */
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
-
- if (dvert_array) {
- for (i = 0; i < dvert_tot; i++) {
- MDeformVert *dv = dvert_array[i];
- dw_org = defvert_find_index(dv, idg);
- if (dw_org) {
- /* defvert_verify_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->weight = weight;
- }
- }
-
- MEM_freeN(dvert_array);
- }
+ bDeformGroup *dg, *cdg;
+ char name[sizeof(dg->name)];
+ MDeformWeight *dw_org, *dw_cpy;
+ MDeformVert **dvert_array = NULL;
+ int i, idg, icdg, dvert_tot = 0;
+
+ dg = BLI_findlink(&ob->defbase, (ob->actdef - 1));
+ if (!dg)
+ return;
+
+ if (!strstr(dg->name, "_copy")) {
+ BLI_snprintf(name, sizeof(name), "%s_copy", dg->name);
+ }
+ else {
+ BLI_strncpy(name, dg->name, sizeof(name));
+ }
+
+ cdg = defgroup_duplicate(dg);
+ BLI_strncpy(cdg->name, name, sizeof(cdg->name));
+ defgroup_unique_name(cdg, ob);
+
+ BLI_addtail(&ob->defbase, cdg);
+
+ idg = (ob->actdef - 1);
+ ob->actdef = BLI_listbase_count(&ob->defbase);
+ icdg = (ob->actdef - 1);
+
+ /* TODO, we might want to allow only copy selected verts here? - campbell */
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
+
+ if (dvert_array) {
+ for (i = 0; i < dvert_tot; i++) {
+ MDeformVert *dv = dvert_array[i];
+ dw_org = defvert_find_index(dv, idg);
+ if (dw_org) {
+ /* defvert_verify_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->weight = weight;
+ }
+ }
+
+ MEM_freeN(dvert_array);
+ }
}
static bool vgroup_normalize(Object *ob)
{
- MDeformWeight *dw;
- MDeformVert *dv, **dvert_array = NULL;
- int i, dvert_tot = 0;
- const int def_nr = ob->actdef - 1;
+ MDeformWeight *dw;
+ MDeformVert *dv, **dvert_array = NULL;
+ int i, dvert_tot = 0;
+ const int def_nr = ob->actdef - 1;
- const int use_vert_sel = vertex_group_use_vert_sel(ob);
+ const int use_vert_sel = vertex_group_use_vert_sel(ob);
- if (!BLI_findlink(&ob->defbase, def_nr)) {
- return false;
- }
+ if (!BLI_findlink(&ob->defbase, def_nr)) {
+ return false;
+ }
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
- if (dvert_array) {
- float weight_max = 0.0f;
+ if (dvert_array) {
+ float weight_max = 0.0f;
- for (i = 0; i < dvert_tot; i++) {
+ for (i = 0; i < dvert_tot; i++) {
- /* in case its not selected */
- if (!(dv = dvert_array[i])) {
- continue;
- }
+ /* in case its not selected */
+ if (!(dv = dvert_array[i])) {
+ continue;
+ }
- dw = defvert_find_index(dv, def_nr);
- if (dw) {
- weight_max = max_ff(dw->weight, weight_max);
- }
- }
+ dw = defvert_find_index(dv, def_nr);
+ if (dw) {
+ weight_max = max_ff(dw->weight, weight_max);
+ }
+ }
- if (weight_max > 0.0f) {
- for (i = 0; i < dvert_tot; i++) {
+ if (weight_max > 0.0f) {
+ for (i = 0; i < dvert_tot; i++) {
- /* in case its not selected */
- if (!(dv = dvert_array[i])) {
- continue;
- }
+ /* in case its not selected */
+ if (!(dv = dvert_array[i])) {
+ continue;
+ }
- dw = defvert_find_index(dv, def_nr);
- if (dw) {
- dw->weight /= weight_max;
+ dw = defvert_find_index(dv, def_nr);
+ if (dw) {
+ dw->weight /= weight_max;
- /* in case of division errors with very low weights */
- CLAMP(dw->weight, 0.0f, 1.0f);
- }
- }
- }
+ /* in case of division errors with very low weights */
+ CLAMP(dw->weight, 0.0f, 1.0f);
+ }
+ }
+ }
- MEM_freeN(dvert_array);
+ MEM_freeN(dvert_array);
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
/* This finds all of the vertices face-connected to vert by an edge and returns a
@@ -1151,64 +1167,64 @@ static bool vgroup_normalize(Object *ob)
* count is an int passed by reference so it can be assigned the value of the length here. */
static int *getSurroundingVerts(Mesh *me, int vert, int *count)
{
- MPoly *mp = me->mpoly;
- int i = me->totpoly;
- /* Instead of looping twice on all polys and loops, and use a temp array, let's rather
- * use a BLI_array, with a reasonable starting/reserved size (typically, there are not
- * many vertices face-linked to another one, even 8 might be too high...). */
- int *verts = NULL;
- BLI_array_declare(verts);
-
- BLI_array_reserve(verts, 8);
- while (i--) {
- int j = mp->totloop;
- int first_l = mp->totloop - 1;
- MLoop *ml = &me->mloop[mp->loopstart];
- while (j--) {
- /* XXX This assume a vert can only be once in a poly, even though
- * it seems logical to me, not totally sure of that. */
- if (ml->v == vert) {
- int a, b, k;
- if (j == first_l) {
- /* We are on the first corner. */
- a = ml[1].v;
- b = ml[j].v;
- }
- else if (!j) {
- /* We are on the last corner. */
- a = (ml - 1)->v;
- b = me->mloop[mp->loopstart].v;
- }
- else {
- a = (ml - 1)->v;
- b = (ml + 1)->v;
- }
-
- /* Append a and b verts to array, if not yet present. */
- k = BLI_array_len(verts);
- /* XXX Maybe a == b is enough? */
- while (k-- && !(a == b && a == -1)) {
- if (verts[k] == a)
- a = -1;
- else if (verts[k] == b)
- b = -1;
- }
- if (a != -1)
- BLI_array_append(verts, a);
- if (b != -1)
- BLI_array_append(verts, b);
-
- /* Vert found in this poly, we can go to next one! */
- break;
- }
- ml++;
- }
- mp++;
- }
-
- /* Do not free the array! */
- *count = BLI_array_len(verts);
- return verts;
+ MPoly *mp = me->mpoly;
+ int i = me->totpoly;
+ /* Instead of looping twice on all polys and loops, and use a temp array, let's rather
+ * use a BLI_array, with a reasonable starting/reserved size (typically, there are not
+ * many vertices face-linked to another one, even 8 might be too high...). */
+ int *verts = NULL;
+ BLI_array_declare(verts);
+
+ BLI_array_reserve(verts, 8);
+ while (i--) {
+ int j = mp->totloop;
+ int first_l = mp->totloop - 1;
+ MLoop *ml = &me->mloop[mp->loopstart];
+ while (j--) {
+ /* XXX This assume a vert can only be once in a poly, even though
+ * it seems logical to me, not totally sure of that. */
+ if (ml->v == vert) {
+ int a, b, k;
+ if (j == first_l) {
+ /* We are on the first corner. */
+ a = ml[1].v;
+ b = ml[j].v;
+ }
+ else if (!j) {
+ /* We are on the last corner. */
+ a = (ml - 1)->v;
+ b = me->mloop[mp->loopstart].v;
+ }
+ else {
+ a = (ml - 1)->v;
+ b = (ml + 1)->v;
+ }
+
+ /* Append a and b verts to array, if not yet present. */
+ k = BLI_array_len(verts);
+ /* XXX Maybe a == b is enough? */
+ while (k-- && !(a == b && a == -1)) {
+ if (verts[k] == a)
+ a = -1;
+ else if (verts[k] == b)
+ b = -1;
+ }
+ if (a != -1)
+ BLI_array_append(verts, a);
+ if (b != -1)
+ BLI_array_append(verts, b);
+
+ /* Vert found in this poly, we can go to next one! */
+ break;
+ }
+ ml++;
+ }
+ mp++;
+ }
+
+ /* Do not free the array! */
+ *count = BLI_array_len(verts);
+ return verts;
}
/* get a single point in space by averaging a point cloud (vectors of size 3)
@@ -1216,40 +1232,45 @@ static int *getSurroundingVerts(Mesh *me, int vert, int *count)
*/
static void getSingleCoordinate(MVert *points, int count, float coord[3])
{
- int i;
- zero_v3(coord);
- for (i = 0; i < count; i++) {
- add_v3_v3(coord, points[i].co);
- }
- mul_v3_fl(coord, 1.0f / count);
+ int i;
+ zero_v3(coord);
+ for (i = 0; i < count; i++) {
+ add_v3_v3(coord, points[i].co);
+ }
+ mul_v3_fl(coord, 1.0f / count);
}
/* given a plane and a start and end position,
* compute the amount of vertical distance relative to the plane and store it in dists,
* then get the horizontal and vertical change and store them in changes
*/
-static void getVerticalAndHorizontalChange(
- const float norm[3], float d, const float coord[3],
- const float start[3], float distToStart,
- float *end, float (*changes)[2], float *dists, int index)
-{
- /* A = Q - ((Q - P).N)N
- * D = (a * x0 + b * y0 +c * z0 + d) */
- float projA[3], projB[3];
- float plane[4];
-
- plane_from_point_normal_v3(plane, coord, norm);
-
- closest_to_plane_normalized_v3(projA, plane, start);
- closest_to_plane_normalized_v3(projB, plane, end);
- /* (vertical and horizontal refer to the plane's y and xz respectively)
- * vertical distance */
- dists[index] = dot_v3v3(norm, end) + d;
- /* vertical change */
- changes[index][0] = dists[index] - distToStart;
- //printf("vc %f %f\n", distance(end, projB, 3) - distance(start, projA, 3), changes[index][0]);
- /* horizontal change */
- changes[index][1] = len_v3v3(projA, projB);
+static void getVerticalAndHorizontalChange(const float norm[3],
+ float d,
+ const float coord[3],
+ const float start[3],
+ float distToStart,
+ float *end,
+ float (*changes)[2],
+ float *dists,
+ int index)
+{
+ /* A = Q - ((Q - P).N)N
+ * D = (a * x0 + b * y0 +c * z0 + d) */
+ float projA[3], projB[3];
+ float plane[4];
+
+ plane_from_point_normal_v3(plane, coord, norm);
+
+ closest_to_plane_normalized_v3(projA, plane, start);
+ closest_to_plane_normalized_v3(projB, plane, end);
+ /* (vertical and horizontal refer to the plane's y and xz respectively)
+ * vertical distance */
+ dists[index] = dot_v3v3(norm, end) + d;
+ /* vertical change */
+ changes[index][0] = dists[index] - distToStart;
+ //printf("vc %f %f\n", distance(end, projB, 3) - distance(start, projA, 3), changes[index][0]);
+ /* horizontal change */
+ changes[index][1] = len_v3v3(projA, projB);
}
/* by changing nonzero weights, try to move a vertex in me->mverts with index 'index' to
@@ -1261,2336 +1282,2435 @@ static void getVerticalAndHorizontalChange(
* norm and d are the plane's properties for the equation: ax + by + cz + d = 0
* coord is a point on the plane
*/
-static void moveCloserToDistanceFromPlane(
- Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *me, int index, float norm[3],
- float coord[3], float d, float distToBe, float strength, float cp)
-{
- Mesh *me_deform;
- MDeformWeight *dw;
- MVert m;
- MDeformVert *dvert = me->dvert + index;
- int totweight = dvert->totweight;
- float oldw = 0;
- float oldPos[3] = {0};
- float vc, hc, dist = 0.0f;
- int i, k;
- float (*changes)[2] = MEM_mallocN(sizeof(float *) * totweight * 2, "vertHorzChange");
- float *dists = MEM_mallocN(sizeof(float) * totweight, "distance");
-
- /* track if up or down moved it closer for each bone */
- int *upDown = MEM_callocN(sizeof(int) * totweight, "upDownTracker");
-
- int *dwIndices = MEM_callocN(sizeof(int) * totweight, "dwIndexTracker");
- float distToStart;
- int bestIndex = 0;
- bool wasChange;
- char wasUp;
- int lastIndex = -1;
- float originalDistToBe = distToBe;
- do {
- wasChange = false;
- me_deform = mesh_get_eval_deform(depsgraph, scene, ob, &CD_MASK_BAREMESH);
- m = me_deform->mvert[index];
- copy_v3_v3(oldPos, m.co);
- distToStart = dot_v3v3(norm, oldPos) + d;
-
- if (distToBe == originalDistToBe) {
- distToBe += distToStart - distToStart * strength;
- }
- for (i = 0; i < totweight; i++) {
- dwIndices[i] = i;
- dw = (dvert->dw + i);
- vc = hc = 0;
- if (!dw->weight) {
- changes[i][0] = 0;
- changes[i][1] = 0;
- dists[i] = distToStart;
- continue;
- }
- for (k = 0; k < 2; k++) {
- if (me_deform) {
- /* DO NOT try to do own cleanup here, this is call for dramatic failures and bugs!
- * Better to over-free and recompute a bit. */
- BKE_object_free_derived_caches(ob);
- }
- oldw = dw->weight;
- if (k) {
- dw->weight *= 1 + cp;
- }
- else {
- dw->weight /= 1 + cp;
- }
- if (dw->weight == oldw) {
- changes[i][0] = 0;
- changes[i][1] = 0;
- dists[i] = distToStart;
- break;
- }
- if (dw->weight > 1) {
- dw->weight = 1;
- }
- me_deform = mesh_get_eval_deform(depsgraph, scene, ob, &CD_MASK_BAREMESH);
- m = me_deform->mvert[index];
- getVerticalAndHorizontalChange(norm, d, coord, oldPos, distToStart, m.co, changes, dists, i);
- dw->weight = oldw;
- if (!k) {
- vc = changes[i][0];
- hc = changes[i][1];
- dist = dists[i];
- }
- else {
- if (fabsf(dist - distToBe) < fabsf(dists[i] - distToBe)) {
- upDown[i] = 0;
- changes[i][0] = vc;
- changes[i][1] = hc;
- dists[i] = dist;
- }
- else {
- upDown[i] = 1;
- }
- if (fabsf(dists[i] - distToBe) > fabsf(distToStart - distToBe)) {
- changes[i][0] = 0;
- changes[i][1] = 0;
- dists[i] = distToStart;
- }
- }
- }
- }
- /* sort the changes by the vertical change */
- for (k = 0; k < totweight; k++) {
- float tf;
- int ti;
- bestIndex = k;
- for (i = k + 1; i < totweight; i++) {
- dist = dists[i];
-
- if (fabsf(dist) > fabsf(dists[i])) {
- bestIndex = i;
- }
- }
- /* switch with k */
- if (bestIndex != k) {
- ti = upDown[k];
- upDown[k] = upDown[bestIndex];
- upDown[bestIndex] = ti;
-
- ti = dwIndices[k];
- dwIndices[k] = dwIndices[bestIndex];
- dwIndices[bestIndex] = ti;
-
- tf = changes[k][0];
- changes[k][0] = changes[bestIndex][0];
- changes[bestIndex][0] = tf;
-
- tf = changes[k][1];
- changes[k][1] = changes[bestIndex][1];
- changes[bestIndex][1] = tf;
-
- tf = dists[k];
- dists[k] = dists[bestIndex];
- dists[bestIndex] = tf;
- }
- }
- bestIndex = -1;
- /* find the best change with an acceptable horizontal change */
- for (i = 0; i < totweight; i++) {
- if (fabsf(changes[i][0]) > fabsf(changes[i][1] * 2.0f)) {
- bestIndex = i;
- break;
- }
- }
- if (bestIndex != -1) {
- wasChange = true;
- /* it is a good place to stop if it tries to move the opposite direction
- * (relative to the plane) of last time */
- if (lastIndex != -1) {
- if (wasUp != upDown[bestIndex]) {
- wasChange = false;
- }
- }
- lastIndex = bestIndex;
- wasUp = upDown[bestIndex];
- dw = (dvert->dw + dwIndices[bestIndex]);
- oldw = dw->weight;
- if (upDown[bestIndex]) {
- dw->weight *= 1 + cp;
- }
- else {
- dw->weight /= 1 + cp;
- }
- if (dw->weight > 1) {
- dw->weight = 1;
- }
- if (oldw == dw->weight) {
- wasChange = false;
- }
- if (me_deform) {
- /* DO NOT try to do own cleanup here, this is call for dramatic failures and bugs!
- * Better to over-free and recompute a bit. */
- BKE_object_free_derived_caches(ob);
- }
- }
- } while (wasChange && ((distToStart - distToBe) / fabsf(distToStart - distToBe) ==
- (dists[bestIndex] - distToBe) / fabsf(dists[bestIndex] - distToBe)));
-
- MEM_freeN(upDown);
- MEM_freeN(changes);
- MEM_freeN(dists);
- MEM_freeN(dwIndices);
+static void moveCloserToDistanceFromPlane(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ Mesh *me,
+ int index,
+ float norm[3],
+ float coord[3],
+ float d,
+ float distToBe,
+ float strength,
+ float cp)
+{
+ Mesh *me_deform;
+ MDeformWeight *dw;
+ MVert m;
+ MDeformVert *dvert = me->dvert + index;
+ int totweight = dvert->totweight;
+ float oldw = 0;
+ float oldPos[3] = {0};
+ float vc, hc, dist = 0.0f;
+ int i, k;
+ float(*changes)[2] = MEM_mallocN(sizeof(float *) * totweight * 2, "vertHorzChange");
+ float *dists = MEM_mallocN(sizeof(float) * totweight, "distance");
+
+ /* track if up or down moved it closer for each bone */
+ int *upDown = MEM_callocN(sizeof(int) * totweight, "upDownTracker");
+
+ int *dwIndices = MEM_callocN(sizeof(int) * totweight, "dwIndexTracker");
+ float distToStart;
+ int bestIndex = 0;
+ bool wasChange;
+ char wasUp;
+ int lastIndex = -1;
+ float originalDistToBe = distToBe;
+ do {
+ wasChange = false;
+ me_deform = mesh_get_eval_deform(depsgraph, scene, ob, &CD_MASK_BAREMESH);
+ m = me_deform->mvert[index];
+ copy_v3_v3(oldPos, m.co);
+ distToStart = dot_v3v3(norm, oldPos) + d;
+
+ if (distToBe == originalDistToBe) {
+ distToBe += distToStart - distToStart * strength;
+ }
+ for (i = 0; i < totweight; i++) {
+ dwIndices[i] = i;
+ dw = (dvert->dw + i);
+ vc = hc = 0;
+ if (!dw->weight) {
+ changes[i][0] = 0;
+ changes[i][1] = 0;
+ dists[i] = distToStart;
+ continue;
+ }
+ for (k = 0; k < 2; k++) {
+ if (me_deform) {
+ /* DO NOT try to do own cleanup here, this is call for dramatic failures and bugs!
+ * Better to over-free and recompute a bit. */
+ BKE_object_free_derived_caches(ob);
+ }
+ oldw = dw->weight;
+ if (k) {
+ dw->weight *= 1 + cp;
+ }
+ else {
+ dw->weight /= 1 + cp;
+ }
+ if (dw->weight == oldw) {
+ changes[i][0] = 0;
+ changes[i][1] = 0;
+ dists[i] = distToStart;
+ break;
+ }
+ if (dw->weight > 1) {
+ dw->weight = 1;
+ }
+ me_deform = mesh_get_eval_deform(depsgraph, scene, ob, &CD_MASK_BAREMESH);
+ m = me_deform->mvert[index];
+ getVerticalAndHorizontalChange(
+ norm, d, coord, oldPos, distToStart, m.co, changes, dists, i);
+ dw->weight = oldw;
+ if (!k) {
+ vc = changes[i][0];
+ hc = changes[i][1];
+ dist = dists[i];
+ }
+ else {
+ if (fabsf(dist - distToBe) < fabsf(dists[i] - distToBe)) {
+ upDown[i] = 0;
+ changes[i][0] = vc;
+ changes[i][1] = hc;
+ dists[i] = dist;
+ }
+ else {
+ upDown[i] = 1;
+ }
+ if (fabsf(dists[i] - distToBe) > fabsf(distToStart - distToBe)) {
+ changes[i][0] = 0;
+ changes[i][1] = 0;
+ dists[i] = distToStart;
+ }
+ }
+ }
+ }
+ /* sort the changes by the vertical change */
+ for (k = 0; k < totweight; k++) {
+ float tf;
+ int ti;
+ bestIndex = k;
+ for (i = k + 1; i < totweight; i++) {
+ dist = dists[i];
+
+ if (fabsf(dist) > fabsf(dists[i])) {
+ bestIndex = i;
+ }
+ }
+ /* switch with k */
+ if (bestIndex != k) {
+ ti = upDown[k];
+ upDown[k] = upDown[bestIndex];
+ upDown[bestIndex] = ti;
+
+ ti = dwIndices[k];
+ dwIndices[k] = dwIndices[bestIndex];
+ dwIndices[bestIndex] = ti;
+
+ tf = changes[k][0];
+ changes[k][0] = changes[bestIndex][0];
+ changes[bestIndex][0] = tf;
+
+ tf = changes[k][1];
+ changes[k][1] = changes[bestIndex][1];
+ changes[bestIndex][1] = tf;
+
+ tf = dists[k];
+ dists[k] = dists[bestIndex];
+ dists[bestIndex] = tf;
+ }
+ }
+ bestIndex = -1;
+ /* find the best change with an acceptable horizontal change */
+ for (i = 0; i < totweight; i++) {
+ if (fabsf(changes[i][0]) > fabsf(changes[i][1] * 2.0f)) {
+ bestIndex = i;
+ break;
+ }
+ }
+ if (bestIndex != -1) {
+ wasChange = true;
+ /* it is a good place to stop if it tries to move the opposite direction
+ * (relative to the plane) of last time */
+ if (lastIndex != -1) {
+ if (wasUp != upDown[bestIndex]) {
+ wasChange = false;
+ }
+ }
+ lastIndex = bestIndex;
+ wasUp = upDown[bestIndex];
+ dw = (dvert->dw + dwIndices[bestIndex]);
+ oldw = dw->weight;
+ if (upDown[bestIndex]) {
+ dw->weight *= 1 + cp;
+ }
+ else {
+ dw->weight /= 1 + cp;
+ }
+ if (dw->weight > 1) {
+ dw->weight = 1;
+ }
+ if (oldw == dw->weight) {
+ wasChange = false;
+ }
+ if (me_deform) {
+ /* DO NOT try to do own cleanup here, this is call for dramatic failures and bugs!
+ * Better to over-free and recompute a bit. */
+ BKE_object_free_derived_caches(ob);
+ }
+ }
+ } while (wasChange && ((distToStart - distToBe) / fabsf(distToStart - distToBe) ==
+ (dists[bestIndex] - distToBe) / fabsf(dists[bestIndex] - distToBe)));
+
+ MEM_freeN(upDown);
+ MEM_freeN(changes);
+ MEM_freeN(dists);
+ MEM_freeN(dwIndices);
}
/* this is used to try to smooth a surface by only adjusting the nonzero weights of a vertex
* but it could be used to raise or lower an existing 'bump.' */
-static void vgroup_fix(const bContext *C, Scene *scene, Object *ob, float distToBe, float strength, float cp)
-{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int i;
-
- Mesh *me = ob->data;
- MVert *mvert = me->mvert;
- int *verts = NULL;
- if (!(me->editflag & ME_EDIT_PAINT_VERT_SEL))
- return;
- for (i = 0; i < me->totvert && mvert; i++, mvert++) {
- if (mvert->flag & SELECT) {
- int count = 0;
- if ((verts = getSurroundingVerts(me, i, &count))) {
- MVert m;
- MVert *p = MEM_callocN(sizeof(MVert) * (count), "deformedPoints");
- int k;
-
- Mesh *me_deform = mesh_get_eval_deform(depsgraph, scene, ob, &CD_MASK_BAREMESH);
- k = count;
- while (k--) {
- p[k] = me_deform->mvert[verts[k]];
- }
-
- if (count >= 3) {
- float d /*, dist */ /* UNUSED */, mag;
- float coord[3];
- float norm[3];
- getSingleCoordinate(p, count, coord);
- m = me_deform->mvert[i];
- sub_v3_v3v3(norm, m.co, coord);
- mag = normalize_v3(norm);
- if (mag) { /* zeros fix */
- d = -dot_v3v3(norm, coord);
- /* dist = (dot_v3v3(norm, m.co) + d); */ /* UNUSED */
- moveCloserToDistanceFromPlane(depsgraph, scene, ob, me, i, norm, coord, d, distToBe, strength, cp);
- }
- }
-
- MEM_freeN(verts);
- MEM_freeN(p);
- }
- }
- }
-}
-
-static void vgroup_levels_subset(
- Object *ob, const bool *vgroup_validmap, const int vgroup_tot,
- const int UNUSED(subset_count),
- const float offset, const float gain)
-{
- MDeformWeight *dw;
- MDeformVert *dv, **dvert_array = NULL;
- int i, dvert_tot = 0;
-
- const bool use_vert_sel = vertex_group_use_vert_sel(ob);
- const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
-
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
-
- if (dvert_array) {
-
- for (i = 0; i < dvert_tot; i++) {
- int j;
-
- /* in case its not selected */
- if (!(dv = dvert_array[i])) {
- continue;
- }
-
- j = vgroup_tot;
- while (j--) {
- if (vgroup_validmap[j]) {
- dw = defvert_find_index(dv, j);
- if (dw) {
- dw->weight = gain * (dw->weight + offset);
-
- CLAMP(dw->weight, 0.0f, 1.0f);
- }
- }
- }
- }
-
- if (use_mirror && use_vert_sel) {
- ED_vgroup_parray_mirror_sync(
- ob, dvert_array, dvert_tot,
- vgroup_validmap, vgroup_tot);
- }
-
- MEM_freeN(dvert_array);
- }
-}
-
-static bool vgroup_normalize_all(
- Object *ob,
- const bool *vgroup_validmap,
- const int vgroup_tot,
- const int subset_count,
- const bool lock_active,
- ReportList *reports)
-{
- MDeformVert *dv, **dvert_array = NULL;
- int i, dvert_tot = 0;
- const int def_nr = ob->actdef - 1;
-
- const int use_vert_sel = vertex_group_use_vert_sel(ob);
-
- if (subset_count == 0) {
- BKE_report(reports, RPT_ERROR, "No vertex groups to operate on");
- return false;
- }
-
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
-
- if (dvert_array) {
- const int defbase_tot = BLI_listbase_count(&ob->defbase);
- bool *lock_flags = BKE_object_defgroup_lock_flags_get(ob, defbase_tot);
- bool changed = false;
-
- if ((lock_active == true) &&
- (lock_flags != NULL) &&
- (def_nr < defbase_tot))
- {
- lock_flags[def_nr] = true;
- }
-
- if (lock_flags) {
- for (i = 0; i < defbase_tot; i++) {
- if (lock_flags[i] == false) {
- break;
- }
- }
-
- if (i == defbase_tot) {
- BKE_report(reports, RPT_ERROR, "All groups are locked");
- goto finally;
- }
- }
-
- for (i = 0; i < dvert_tot; i++) {
- /* 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);
- }
- else if (lock_active) {
- defvert_normalize_lock_single(
- dv, vgroup_validmap, vgroup_tot,
- def_nr);
- }
- else {
- defvert_normalize_subset(dv, vgroup_validmap, vgroup_tot);
- }
- }
- }
-
- changed = true;
-
-finally:
- if (lock_flags) {
- MEM_freeN(lock_flags);
- }
-
- MEM_freeN(dvert_array);
-
- return changed;
- }
-
- return false;
+static void vgroup_fix(
+ const bContext *C, Scene *scene, Object *ob, float distToBe, float strength, float cp)
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int i;
+
+ Mesh *me = ob->data;
+ MVert *mvert = me->mvert;
+ int *verts = NULL;
+ if (!(me->editflag & ME_EDIT_PAINT_VERT_SEL))
+ return;
+ for (i = 0; i < me->totvert && mvert; i++, mvert++) {
+ if (mvert->flag & SELECT) {
+ int count = 0;
+ if ((verts = getSurroundingVerts(me, i, &count))) {
+ MVert m;
+ MVert *p = MEM_callocN(sizeof(MVert) * (count), "deformedPoints");
+ int k;
+
+ Mesh *me_deform = mesh_get_eval_deform(depsgraph, scene, ob, &CD_MASK_BAREMESH);
+ k = count;
+ while (k--) {
+ p[k] = me_deform->mvert[verts[k]];
+ }
+
+ if (count >= 3) {
+ float d /*, dist */ /* UNUSED */, mag;
+ float coord[3];
+ float norm[3];
+ getSingleCoordinate(p, count, coord);
+ m = me_deform->mvert[i];
+ sub_v3_v3v3(norm, m.co, coord);
+ mag = normalize_v3(norm);
+ if (mag) { /* zeros fix */
+ d = -dot_v3v3(norm, coord);
+ /* dist = (dot_v3v3(norm, m.co) + d); */ /* UNUSED */
+ moveCloserToDistanceFromPlane(
+ depsgraph, scene, ob, me, i, norm, coord, d, distToBe, strength, cp);
+ }
+ }
+
+ MEM_freeN(verts);
+ MEM_freeN(p);
+ }
+ }
+ }
+}
+
+static void vgroup_levels_subset(Object *ob,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const int UNUSED(subset_count),
+ const float offset,
+ const float gain)
+{
+ MDeformWeight *dw;
+ MDeformVert *dv, **dvert_array = NULL;
+ int i, dvert_tot = 0;
+
+ const bool use_vert_sel = vertex_group_use_vert_sel(ob);
+ const bool use_mirror = (ob->type == OB_MESH) ?
+ (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 :
+ false;
+
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+
+ if (dvert_array) {
+
+ for (i = 0; i < dvert_tot; i++) {
+ int j;
+
+ /* in case its not selected */
+ if (!(dv = dvert_array[i])) {
+ continue;
+ }
+
+ j = vgroup_tot;
+ while (j--) {
+ if (vgroup_validmap[j]) {
+ dw = defvert_find_index(dv, j);
+ if (dw) {
+ dw->weight = gain * (dw->weight + offset);
+
+ CLAMP(dw->weight, 0.0f, 1.0f);
+ }
+ }
+ }
+ }
+
+ if (use_mirror && use_vert_sel) {
+ ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot, vgroup_validmap, vgroup_tot);
+ }
+
+ MEM_freeN(dvert_array);
+ }
+}
+
+static bool vgroup_normalize_all(Object *ob,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const int subset_count,
+ const bool lock_active,
+ ReportList *reports)
+{
+ MDeformVert *dv, **dvert_array = NULL;
+ int i, dvert_tot = 0;
+ const int def_nr = ob->actdef - 1;
+
+ const int use_vert_sel = vertex_group_use_vert_sel(ob);
+
+ if (subset_count == 0) {
+ BKE_report(reports, RPT_ERROR, "No vertex groups to operate on");
+ return false;
+ }
+
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+
+ if (dvert_array) {
+ const int defbase_tot = BLI_listbase_count(&ob->defbase);
+ bool *lock_flags = BKE_object_defgroup_lock_flags_get(ob, defbase_tot);
+ bool changed = false;
+
+ if ((lock_active == true) && (lock_flags != NULL) && (def_nr < defbase_tot)) {
+ lock_flags[def_nr] = true;
+ }
+
+ if (lock_flags) {
+ for (i = 0; i < defbase_tot; i++) {
+ if (lock_flags[i] == false) {
+ break;
+ }
+ }
+
+ if (i == defbase_tot) {
+ BKE_report(reports, RPT_ERROR, "All groups are locked");
+ goto finally;
+ }
+ }
+
+ for (i = 0; i < dvert_tot; i++) {
+ /* 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);
+ }
+ else if (lock_active) {
+ defvert_normalize_lock_single(dv, vgroup_validmap, vgroup_tot, def_nr);
+ }
+ else {
+ defvert_normalize_subset(dv, vgroup_validmap, vgroup_tot);
+ }
+ }
+ }
+
+ changed = true;
+
+ finally:
+ if (lock_flags) {
+ MEM_freeN(lock_flags);
+ }
+
+ MEM_freeN(dvert_array);
+
+ return changed;
+ }
+
+ return false;
}
enum {
- VGROUP_TOGGLE,
- VGROUP_LOCK,
- VGROUP_UNLOCK,
- VGROUP_INVERT,
+ VGROUP_TOGGLE,
+ VGROUP_LOCK,
+ VGROUP_UNLOCK,
+ VGROUP_INVERT,
};
static const EnumPropertyItem vgroup_lock_actions[] = {
- {VGROUP_TOGGLE, "TOGGLE", 0, "Toggle", "Unlock all vertex groups if there is at least one locked group, lock all in other case"},
- {VGROUP_LOCK, "LOCK", 0, "Lock", "Lock all vertex groups"},
- {VGROUP_UNLOCK, "UNLOCK", 0, "Unlock", "Unlock all vertex groups"},
- {VGROUP_INVERT, "INVERT", 0, "Invert", "Invert the lock state of all vertex groups"},
- {0, NULL, 0, NULL, NULL},
+ {VGROUP_TOGGLE,
+ "TOGGLE",
+ 0,
+ "Toggle",
+ "Unlock all vertex groups if there is at least one locked group, lock all in other case"},
+ {VGROUP_LOCK, "LOCK", 0, "Lock", "Lock all vertex groups"},
+ {VGROUP_UNLOCK, "UNLOCK", 0, "Unlock", "Unlock all vertex groups"},
+ {VGROUP_INVERT, "INVERT", 0, "Invert", "Invert the lock state of all vertex groups"},
+ {0, NULL, 0, NULL, NULL},
};
static void vgroup_lock_all(Object *ob, int action)
{
- bDeformGroup *dg;
-
- if (action == VGROUP_TOGGLE) {
- action = VGROUP_LOCK;
- for (dg = ob->defbase.first; dg; dg = dg->next) {
- if (dg->flag & DG_LOCK_WEIGHT) {
- action = VGROUP_UNLOCK;
- break;
- }
- }
- }
-
- for (dg = ob->defbase.first; dg; dg = dg->next) {
- switch (action) {
- case VGROUP_LOCK:
- dg->flag |= DG_LOCK_WEIGHT;
- break;
- case VGROUP_UNLOCK:
- dg->flag &= ~DG_LOCK_WEIGHT;
- break;
- case VGROUP_INVERT:
- dg->flag ^= DG_LOCK_WEIGHT;
- break;
- }
- }
-}
-
-static void vgroup_invert_subset(
- Object *ob,
- const bool *vgroup_validmap, const int vgroup_tot,
- const int UNUSED(subset_count), const bool auto_assign, const bool auto_remove)
-{
- MDeformWeight *dw;
- MDeformVert *dv, **dvert_array = NULL;
- int i, dvert_tot = 0;
- const bool use_vert_sel = vertex_group_use_vert_sel(ob);
- const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
-
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
-
- if (dvert_array) {
- for (i = 0; i < dvert_tot; i++) {
- int j;
-
- /* in case its not selected */
- if (!(dv = dvert_array[i])) {
- continue;
- }
-
- j = vgroup_tot;
- while (j--) {
-
- if (vgroup_validmap[j]) {
- if (auto_assign) {
- dw = defvert_verify_index(dv, j);
- }
- else {
- dw = defvert_find_index(dv, j);
- }
-
- if (dw) {
- dw->weight = 1.0f - dw->weight;
- CLAMP(dw->weight, 0.0f, 1.0f);
- }
- }
- }
- }
-
- if (use_mirror && use_vert_sel) {
- ED_vgroup_parray_mirror_sync(
- ob, dvert_array, dvert_tot,
- vgroup_validmap, vgroup_tot);
- }
-
- if (auto_remove) {
- ED_vgroup_parray_remove_zero(
- dvert_array, dvert_tot,
- vgroup_validmap, vgroup_tot,
- 0.0f, false);
- }
-
- MEM_freeN(dvert_array);
- }
-}
-
-static void vgroup_smooth_subset(
- Object *ob, const bool *vgroup_validmap, const int vgroup_tot,
- const int subset_count,
- const float fac, const int repeat,
- const float fac_expand)
-{
- const float ifac = 1.0f - fac;
- MDeformVert **dvert_array = NULL;
- int dvert_tot = 0;
- int *vgroup_subset_map = BLI_array_alloca(vgroup_subset_map, subset_count);
- float *vgroup_subset_weights = BLI_array_alloca(vgroup_subset_weights, subset_count);
- const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
- const bool use_select = vertex_group_use_vert_sel(ob);
- const bool use_hide = use_select;
-
- const int expand_sign = signum_i(fac_expand);
- const float expand = fabsf(fac_expand);
- const float iexpand = 1.0f - expand;
-
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em ? em->bm : NULL;
- Mesh *me = em ? NULL : ob->data;
-
- MeshElemMap *emap;
- int *emap_mem;
-
- float *weight_accum_prev;
- float *weight_accum_curr;
-
- unsigned int subset_index;
-
- /* vertex indices that will be smoothed, (only to avoid iterating over verts that do nothing) */
- unsigned int *verts_used;
- STACK_DECLARE(verts_used);
-
-
- BKE_object_defgroup_subset_to_index_array(vgroup_validmap, vgroup_tot, vgroup_subset_map);
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
- memset(vgroup_subset_weights, 0, sizeof(*vgroup_subset_weights) * subset_count);
-
- if (bm) {
- BM_mesh_elem_table_ensure(bm, BM_VERT);
- BM_mesh_elem_index_ensure(bm, BM_VERT);
-
- emap = NULL;
- emap_mem = NULL;
- }
- else {
- BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me->medge, me->totvert, me->totedge);
- }
-
- weight_accum_prev = MEM_mallocN(sizeof(*weight_accum_prev) * dvert_tot, __func__);
- weight_accum_curr = MEM_mallocN(sizeof(*weight_accum_curr) * dvert_tot, __func__);
-
- verts_used = MEM_mallocN(sizeof(*verts_used) * dvert_tot, __func__);
- STACK_INIT(verts_used, dvert_tot);
-
-#define IS_BM_VERT_READ(v) \
- (use_hide ? (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == 0) : true)
-#define IS_BM_VERT_WRITE(v) \
- (use_select ? (BM_elem_flag_test(v, BM_ELEM_SELECT) != 0) : true)
-
-#define IS_ME_VERT_READ(v) \
- (use_hide ? (((v)->flag & ME_HIDE) == 0) : true)
-#define IS_ME_VERT_WRITE(v) \
- (use_select ? (((v)->flag & SELECT) != 0) : true)
-
- /* initialize used verts */
- if (bm) {
- for (int i = 0; i < dvert_tot; i++) {
- BMVert *v = BM_vert_at_index(bm, i);
- if (IS_BM_VERT_WRITE(v)) {
- BMIter eiter;
- BMEdge *e;
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- BMVert *v_other = BM_edge_other_vert(e, v);
- if (IS_BM_VERT_READ(v_other)) {
- STACK_PUSH(verts_used, i);
- break;
- }
- }
- }
- }
- }
- else {
- for (int i = 0; i < dvert_tot; i++) {
- const MVert *v = &me->mvert[i];
- if (IS_ME_VERT_WRITE(v)) {
- for (int j = 0; j < emap[i].count; j++) {
- const MEdge *e = &me->medge[emap[i].indices[j]];
- const MVert *v_other = &me->mvert[(e->v1 == i) ? e->v2 : e->v1];
- if (IS_ME_VERT_READ(v_other)) {
- STACK_PUSH(verts_used, i);
- break;
- }
- }
- }
- }
- }
-
- for (subset_index = 0; subset_index < subset_count; subset_index++) {
- const int def_nr = vgroup_subset_map[subset_index];
- int iter;
-
- ED_vgroup_parray_to_weight_array((const MDeformVert **)dvert_array, dvert_tot, weight_accum_prev, def_nr);
- 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);
-
- /* 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;
- float weight_tot = 0.0f;
- float weight = 0.0f;
+ bDeformGroup *dg;
+
+ if (action == VGROUP_TOGGLE) {
+ action = VGROUP_LOCK;
+ for (dg = ob->defbase.first; dg; dg = dg->next) {
+ if (dg->flag & DG_LOCK_WEIGHT) {
+ action = VGROUP_UNLOCK;
+ break;
+ }
+ }
+ }
+
+ for (dg = ob->defbase.first; dg; dg = dg->next) {
+ switch (action) {
+ case VGROUP_LOCK:
+ dg->flag |= DG_LOCK_WEIGHT;
+ break;
+ case VGROUP_UNLOCK:
+ dg->flag &= ~DG_LOCK_WEIGHT;
+ break;
+ case VGROUP_INVERT:
+ dg->flag ^= DG_LOCK_WEIGHT;
+ break;
+ }
+ }
+}
+
+static void vgroup_invert_subset(Object *ob,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const int UNUSED(subset_count),
+ const bool auto_assign,
+ const bool auto_remove)
+{
+ MDeformWeight *dw;
+ MDeformVert *dv, **dvert_array = NULL;
+ int i, dvert_tot = 0;
+ const bool use_vert_sel = vertex_group_use_vert_sel(ob);
+ const bool use_mirror = (ob->type == OB_MESH) ?
+ (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 :
+ false;
+
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+
+ if (dvert_array) {
+ for (i = 0; i < dvert_tot; i++) {
+ int j;
+
+ /* in case its not selected */
+ if (!(dv = dvert_array[i])) {
+ continue;
+ }
+
+ j = vgroup_tot;
+ while (j--) {
+
+ if (vgroup_validmap[j]) {
+ if (auto_assign) {
+ dw = defvert_verify_index(dv, j);
+ }
+ else {
+ dw = defvert_find_index(dv, j);
+ }
+
+ if (dw) {
+ dw->weight = 1.0f - dw->weight;
+ CLAMP(dw->weight, 0.0f, 1.0f);
+ }
+ }
+ }
+ }
+
+ if (use_mirror && use_vert_sel) {
+ ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot, vgroup_validmap, vgroup_tot);
+ }
+
+ if (auto_remove) {
+ ED_vgroup_parray_remove_zero(
+ dvert_array, dvert_tot, vgroup_validmap, vgroup_tot, 0.0f, false);
+ }
+
+ MEM_freeN(dvert_array);
+ }
+}
+
+static void vgroup_smooth_subset(Object *ob,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const int subset_count,
+ const float fac,
+ const int repeat,
+ const float fac_expand)
+{
+ const float ifac = 1.0f - fac;
+ MDeformVert **dvert_array = NULL;
+ int dvert_tot = 0;
+ int *vgroup_subset_map = BLI_array_alloca(vgroup_subset_map, subset_count);
+ float *vgroup_subset_weights = BLI_array_alloca(vgroup_subset_weights, subset_count);
+ const bool use_mirror = (ob->type == OB_MESH) ?
+ (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 :
+ false;
+ const bool use_select = vertex_group_use_vert_sel(ob);
+ const bool use_hide = use_select;
+
+ const int expand_sign = signum_i(fac_expand);
+ const float expand = fabsf(fac_expand);
+ const float iexpand = 1.0f - expand;
+
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em ? em->bm : NULL;
+ Mesh *me = em ? NULL : ob->data;
+
+ MeshElemMap *emap;
+ int *emap_mem;
+
+ float *weight_accum_prev;
+ float *weight_accum_curr;
+
+ unsigned int subset_index;
+
+ /* vertex indices that will be smoothed, (only to avoid iterating over verts that do nothing) */
+ unsigned int *verts_used;
+ STACK_DECLARE(verts_used);
+
+ BKE_object_defgroup_subset_to_index_array(vgroup_validmap, vgroup_tot, vgroup_subset_map);
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
+ memset(vgroup_subset_weights, 0, sizeof(*vgroup_subset_weights) * subset_count);
+
+ if (bm) {
+ BM_mesh_elem_table_ensure(bm, BM_VERT);
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+ emap = NULL;
+ emap_mem = NULL;
+ }
+ else {
+ BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me->medge, me->totvert, me->totedge);
+ }
+
+ weight_accum_prev = MEM_mallocN(sizeof(*weight_accum_prev) * dvert_tot, __func__);
+ weight_accum_curr = MEM_mallocN(sizeof(*weight_accum_curr) * dvert_tot, __func__);
+
+ verts_used = MEM_mallocN(sizeof(*verts_used) * dvert_tot, __func__);
+ STACK_INIT(verts_used, dvert_tot);
+
+#define IS_BM_VERT_READ(v) (use_hide ? (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == 0) : true)
+#define IS_BM_VERT_WRITE(v) (use_select ? (BM_elem_flag_test(v, BM_ELEM_SELECT) != 0) : true)
+
+#define IS_ME_VERT_READ(v) (use_hide ? (((v)->flag & ME_HIDE) == 0) : true)
+#define IS_ME_VERT_WRITE(v) (use_select ? (((v)->flag & SELECT) != 0) : true)
+
+ /* initialize used verts */
+ if (bm) {
+ for (int i = 0; i < dvert_tot; i++) {
+ BMVert *v = BM_vert_at_index(bm, i);
+ if (IS_BM_VERT_WRITE(v)) {
+ BMIter eiter;
+ BMEdge *e;
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ if (IS_BM_VERT_READ(v_other)) {
+ STACK_PUSH(verts_used, i);
+ break;
+ }
+ }
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < dvert_tot; i++) {
+ const MVert *v = &me->mvert[i];
+ if (IS_ME_VERT_WRITE(v)) {
+ for (int j = 0; j < emap[i].count; j++) {
+ const MEdge *e = &me->medge[emap[i].indices[j]];
+ const MVert *v_other = &me->mvert[(e->v1 == i) ? e->v2 : e->v1];
+ if (IS_ME_VERT_READ(v_other)) {
+ STACK_PUSH(verts_used, i);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ for (subset_index = 0; subset_index < subset_count; subset_index++) {
+ const int def_nr = vgroup_subset_map[subset_index];
+ int iter;
+
+ ED_vgroup_parray_to_weight_array(
+ (const MDeformVert **)dvert_array, dvert_tot, weight_accum_prev, def_nr);
+ 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);
+
+ /* 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;
+ float weight_tot = 0.0f;
+ float weight = 0.0f;
#define WEIGHT_ACCUMULATE \
- { \
- float weight_other = weight_accum_prev[i_other]; \
- float tot_factor = 1.0f; \
- if (expand_sign == 1) { /* expand */ \
- if (weight_other < weight_accum_prev[i]) { \
- weight_other = (weight_accum_prev[i] * expand) + (weight_other * iexpand); \
- tot_factor = iexpand; \
- } \
- } \
- else if (expand_sign == -1) { /* contract */ \
- if (weight_other > weight_accum_prev[i]) { \
- weight_other = (weight_accum_prev[i] * expand) + (weight_other * iexpand); \
- tot_factor = iexpand; \
- } \
- } \
- weight += tot_factor * weight_other; \
- weight_tot += tot_factor; \
- } ((void)0)
-
-
- if (bm) {
- BMVert *v = BM_vert_at_index(bm, i);
- BMIter eiter;
- BMEdge *e;
-
- /* checked already */
- BLI_assert(IS_BM_VERT_WRITE(v));
-
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- BMVert *v_other = BM_edge_other_vert(e, v);
- if (IS_BM_VERT_READ(v_other)) {
- const int i_other = BM_elem_index_get(v_other);
-
- WEIGHT_ACCUMULATE;
- }
- }
- }
- else {
- int j;
-
- /* checked already */
- BLI_assert(IS_ME_VERT_WRITE(&me->mvert[i]));
-
- for (j = 0; j < emap[i].count; j++) {
- MEdge *e = &me->medge[emap[i].indices[j]];
- const int i_other = (e->v1 == i ? e->v2 : e->v1);
- MVert *v_other = &me->mvert[i_other];
-
- if (IS_ME_VERT_READ(v_other)) {
- WEIGHT_ACCUMULATE;
- }
- }
- }
+ { \
+ float weight_other = weight_accum_prev[i_other]; \
+ float tot_factor = 1.0f; \
+ if (expand_sign == 1) { /* expand */ \
+ if (weight_other < weight_accum_prev[i]) { \
+ weight_other = (weight_accum_prev[i] * expand) + (weight_other * iexpand); \
+ tot_factor = iexpand; \
+ } \
+ } \
+ else if (expand_sign == -1) { /* contract */ \
+ if (weight_other > weight_accum_prev[i]) { \
+ weight_other = (weight_accum_prev[i] * expand) + (weight_other * iexpand); \
+ tot_factor = iexpand; \
+ } \
+ } \
+ weight += tot_factor * weight_other; \
+ weight_tot += tot_factor; \
+ } \
+ ((void)0)
+
+ if (bm) {
+ BMVert *v = BM_vert_at_index(bm, i);
+ BMIter eiter;
+ BMEdge *e;
+
+ /* checked already */
+ BLI_assert(IS_BM_VERT_WRITE(v));
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ if (IS_BM_VERT_READ(v_other)) {
+ const int i_other = BM_elem_index_get(v_other);
+
+ WEIGHT_ACCUMULATE;
+ }
+ }
+ }
+ else {
+ int j;
+
+ /* checked already */
+ BLI_assert(IS_ME_VERT_WRITE(&me->mvert[i]));
+
+ for (j = 0; j < emap[i].count; j++) {
+ MEdge *e = &me->medge[emap[i].indices[j]];
+ const int i_other = (e->v1 == i ? e->v2 : e->v1);
+ MVert *v_other = &me->mvert[i_other];
+
+ if (IS_ME_VERT_READ(v_other)) {
+ WEIGHT_ACCUMULATE;
+ }
+ }
+ }
#undef WEIGHT_ACCUMULATE
- if (weight_tot != 0.0f) {
- weight /= weight_tot;
- weight = (weight_accum_prev[i] * ifac) + (weight * fac);
+ if (weight_tot != 0.0f) {
+ weight /= weight_tot;
+ weight = (weight_accum_prev[i] * ifac) + (weight * fac);
- /* should be within range, just clamp because of float precision */
- CLAMP(weight, 0.0f, 1.0f);
- weight_accum_curr[i] = weight;
- }
- }
+ /* should be within range, just clamp because of float precision */
+ CLAMP(weight, 0.0f, 1.0f);
+ weight_accum_curr[i] = weight;
+ }
+ }
- SWAP(float *, weight_accum_curr, weight_accum_prev);
- }
+ SWAP(float *, weight_accum_curr, weight_accum_prev);
+ }
- ED_vgroup_parray_from_weight_array(dvert_array, dvert_tot, weight_accum_prev, def_nr, true);
- }
+ ED_vgroup_parray_from_weight_array(dvert_array, dvert_tot, weight_accum_prev, def_nr, true);
+ }
#undef IS_BM_VERT_READ
#undef IS_BM_VERT_WRITE
#undef IS_ME_VERT_READ
#undef IS_ME_VERT_WRITE
- MEM_freeN(weight_accum_curr);
- MEM_freeN(weight_accum_prev);
- MEM_freeN(verts_used);
-
- if (bm) {
- /* pass */
- }
- else {
- MEM_freeN(emap);
- MEM_freeN(emap_mem);
- }
-
- if (dvert_array)
- MEM_freeN(dvert_array);
-
- /* not so efficient to get 'dvert_array' again just so unselected verts are NULL'd */
- if (use_mirror) {
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, true);
- ED_vgroup_parray_mirror_sync(
- ob, dvert_array, dvert_tot,
- vgroup_validmap, vgroup_tot);
- if (dvert_array)
- MEM_freeN(dvert_array);
- }
+ MEM_freeN(weight_accum_curr);
+ MEM_freeN(weight_accum_prev);
+ MEM_freeN(verts_used);
+
+ if (bm) {
+ /* pass */
+ }
+ else {
+ MEM_freeN(emap);
+ MEM_freeN(emap_mem);
+ }
+
+ if (dvert_array)
+ MEM_freeN(dvert_array);
+
+ /* not so efficient to get 'dvert_array' again just so unselected verts are NULL'd */
+ if (use_mirror) {
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, true);
+ ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot, vgroup_validmap, vgroup_tot);
+ if (dvert_array)
+ MEM_freeN(dvert_array);
+ }
}
static int inv_cmp_mdef_vert_weights(const void *a1, const void *a2)
{
- /* qsort sorts in ascending order. We want descending order to save a memcopy
- * so this compare function is inverted from the standard greater than comparison qsort needs.
- * A normal compare function is called with two pointer arguments and should return an integer
- * less than, equal to, or greater than zero corresponding to whether its first argument is
- * considered less than, equal to, or greater than its second argument.
- * This does the opposite. */
- const struct MDeformWeight *dw1 = a1, *dw2 = a2;
-
- if (dw1->weight < dw2->weight) return 1;
- else if (dw1->weight > dw2->weight) return -1;
- else if (&dw1 < &dw2) return 1; /* compare address for stable sort algorithm */
- else return -1;
+ /* qsort sorts in ascending order. We want descending order to save a memcopy
+ * so this compare function is inverted from the standard greater than comparison qsort needs.
+ * A normal compare function is called with two pointer arguments and should return an integer
+ * less than, equal to, or greater than zero corresponding to whether its first argument is
+ * considered less than, equal to, or greater than its second argument.
+ * This does the opposite. */
+ const struct MDeformWeight *dw1 = a1, *dw2 = a2;
+
+ if (dw1->weight < dw2->weight)
+ return 1;
+ else if (dw1->weight > dw2->weight)
+ return -1;
+ else if (&dw1 < &dw2)
+ return 1; /* compare address for stable sort algorithm */
+ else
+ return -1;
}
/* Used for limiting the number of influencing bones per vertex when exporting
* skinned meshes. if all_deform_weights is True, limit all deform modifiers
* to max_weights regardless of type, otherwise,
* only limit the number of influencing bones per vertex. */
-static int vgroup_limit_total_subset(
- Object *ob,
- const bool *vgroup_validmap,
- const int vgroup_tot,
- const int subset_count,
- const int max_weights)
-{
- MDeformVert *dv, **dvert_array = NULL;
- int i, dvert_tot = 0;
- const int use_vert_sel = vertex_group_use_vert_sel(ob);
- int remove_tot = 0;
-
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
-
- if (dvert_array) {
- int num_to_drop = 0;
-
- for (i = 0; i < dvert_tot; i++) {
-
- MDeformWeight *dw_temp;
- int bone_count = 0, non_bone_count = 0;
- int j;
-
- /* in case its not selected */
- if (!(dv = dvert_array[i])) {
- continue;
- }
-
- num_to_drop = subset_count - max_weights;
-
- /* first check if we even need to test further */
- if (num_to_drop > 0) {
- /* re-pack dw array so that non-bone weights are first, bone-weighted verts at end
- * sort the tail, then copy only the truncated array back to dv->dw */
- dw_temp = MEM_mallocN(sizeof(MDeformWeight) * dv->totweight, __func__);
- bone_count = 0; non_bone_count = 0;
- for (j = 0; j < dv->totweight; j++) {
- if (LIKELY(dv->dw[j].def_nr < vgroup_tot) &&
- vgroup_validmap[dv->dw[j].def_nr])
- {
- dw_temp[dv->totweight - 1 - bone_count] = dv->dw[j];
- bone_count += 1;
- }
- else {
- dw_temp[non_bone_count] = dv->dw[j];
- non_bone_count += 1;
- }
- }
- BLI_assert(bone_count + non_bone_count == dv->totweight);
- num_to_drop = bone_count - max_weights;
- if (num_to_drop > 0) {
- qsort(&dw_temp[non_bone_count], bone_count, sizeof(MDeformWeight), inv_cmp_mdef_vert_weights);
- dv->totweight -= num_to_drop;
- /* Do we want to clean/normalize here? */
- MEM_freeN(dv->dw);
- dv->dw = MEM_reallocN(dw_temp, sizeof(MDeformWeight) * dv->totweight);
- remove_tot += num_to_drop;
- }
- else {
- MEM_freeN(dw_temp);
- }
- }
-
- }
- MEM_freeN(dvert_array);
-
- }
-
- return remove_tot;
-}
-
-
-static void vgroup_clean_subset(
- Object *ob, const bool *vgroup_validmap, const int vgroup_tot, const int UNUSED(subset_count),
- const float epsilon, const bool keep_single)
-{
- MDeformVert **dvert_array = NULL;
- int dvert_tot = 0;
- const bool use_vert_sel = vertex_group_use_vert_sel(ob);
- const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
-
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
-
- if (dvert_array) {
- if (use_mirror && use_vert_sel) {
- /* correct behavior in this case isn't well defined
- * for now assume both sides are mirrored correctly,
- * so cleaning one side also cleans the other */
- ED_vgroup_parray_mirror_assign(ob, dvert_array, dvert_tot);
- }
-
- ED_vgroup_parray_remove_zero(
- dvert_array, dvert_tot,
- vgroup_validmap, vgroup_tot,
- epsilon, keep_single);
-
- MEM_freeN(dvert_array);
- }
-}
-
-static void vgroup_quantize_subset(
- Object *ob, const bool *vgroup_validmap, const int vgroup_tot, const int UNUSED(subset_count),
- const int steps)
-{
- MDeformVert **dvert_array = NULL;
- int dvert_tot = 0;
- const bool use_vert_sel = vertex_group_use_vert_sel(ob);
- const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
-
- if (dvert_array) {
- const float steps_fl = steps;
- MDeformVert *dv;
- int i;
-
- if (use_mirror && use_vert_sel) {
- ED_vgroup_parray_mirror_assign(ob, dvert_array, dvert_tot);
- }
-
- for (i = 0; i < dvert_tot; i++) {
- MDeformWeight *dw;
- int j;
-
- /* in case its not selected */
- if (!(dv = dvert_array[i])) {
- continue;
- }
-
- for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) {
- if ((dw->def_nr < vgroup_tot) && vgroup_validmap[dw->def_nr]) {
- dw->weight = floorf((dw->weight * steps_fl) + 0.5f) / steps_fl;
- CLAMP(dw->weight, 0.0f, 1.0f);
- }
- }
- }
-
- MEM_freeN(dvert_array);
- }
-}
-
-static void dvert_mirror_op(
- MDeformVert *dvert, MDeformVert *dvert_mirr,
- const char sel, const char sel_mirr,
- const int *flip_map, const int flip_map_len,
- const bool mirror_weights, const bool flip_vgroups, const bool all_vgroups,
- const int act_vgroup)
-{
- BLI_assert(sel || sel_mirr);
-
- if (sel_mirr && sel) {
- /* swap */
- if (mirror_weights) {
- if (all_vgroups) {
- SWAP(MDeformVert, *dvert, *dvert_mirr);
- }
- else {
- MDeformWeight *dw = defvert_find_index(dvert, act_vgroup);
- MDeformWeight *dw_mirr = 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->weight = dw->weight;
- defvert_remove_group(dvert, dw);
- }
- else if (dw_mirr) {
- dw = defvert_verify_index(dvert, act_vgroup);
- dw->weight = dw_mirr->weight;
- 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);
- }
- }
- else {
- /* dvert should always be the target, only swaps pointer */
- if (sel_mirr) {
- SWAP(MDeformVert *, dvert, dvert_mirr);
- }
-
- if (mirror_weights) {
- if (all_vgroups) {
- defvert_copy(dvert, dvert_mirr);
- }
- else {
- 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);
- }
- }
+static int vgroup_limit_total_subset(Object *ob,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const int subset_count,
+ const int max_weights)
+{
+ MDeformVert *dv, **dvert_array = NULL;
+ int i, dvert_tot = 0;
+ const int use_vert_sel = vertex_group_use_vert_sel(ob);
+ int remove_tot = 0;
+
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+
+ if (dvert_array) {
+ int num_to_drop = 0;
+
+ for (i = 0; i < dvert_tot; i++) {
+
+ MDeformWeight *dw_temp;
+ int bone_count = 0, non_bone_count = 0;
+ int j;
+
+ /* in case its not selected */
+ if (!(dv = dvert_array[i])) {
+ continue;
+ }
+
+ num_to_drop = subset_count - max_weights;
+
+ /* first check if we even need to test further */
+ if (num_to_drop > 0) {
+ /* re-pack dw array so that non-bone weights are first, bone-weighted verts at end
+ * sort the tail, then copy only the truncated array back to dv->dw */
+ dw_temp = MEM_mallocN(sizeof(MDeformWeight) * dv->totweight, __func__);
+ bone_count = 0;
+ non_bone_count = 0;
+ for (j = 0; j < dv->totweight; j++) {
+ if (LIKELY(dv->dw[j].def_nr < vgroup_tot) && vgroup_validmap[dv->dw[j].def_nr]) {
+ dw_temp[dv->totweight - 1 - bone_count] = dv->dw[j];
+ bone_count += 1;
+ }
+ else {
+ dw_temp[non_bone_count] = dv->dw[j];
+ non_bone_count += 1;
+ }
+ }
+ BLI_assert(bone_count + non_bone_count == dv->totweight);
+ num_to_drop = bone_count - max_weights;
+ if (num_to_drop > 0) {
+ qsort(&dw_temp[non_bone_count],
+ bone_count,
+ sizeof(MDeformWeight),
+ inv_cmp_mdef_vert_weights);
+ dv->totweight -= num_to_drop;
+ /* Do we want to clean/normalize here? */
+ MEM_freeN(dv->dw);
+ dv->dw = MEM_reallocN(dw_temp, sizeof(MDeformWeight) * dv->totweight);
+ remove_tot += num_to_drop;
+ }
+ else {
+ MEM_freeN(dw_temp);
+ }
+ }
+ }
+ MEM_freeN(dvert_array);
+ }
+
+ return remove_tot;
+}
+
+static void vgroup_clean_subset(Object *ob,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const int UNUSED(subset_count),
+ const float epsilon,
+ const bool keep_single)
+{
+ MDeformVert **dvert_array = NULL;
+ int dvert_tot = 0;
+ const bool use_vert_sel = vertex_group_use_vert_sel(ob);
+ const bool use_mirror = (ob->type == OB_MESH) ?
+ (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 :
+ false;
+
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+
+ if (dvert_array) {
+ if (use_mirror && use_vert_sel) {
+ /* correct behavior in this case isn't well defined
+ * for now assume both sides are mirrored correctly,
+ * so cleaning one side also cleans the other */
+ ED_vgroup_parray_mirror_assign(ob, dvert_array, dvert_tot);
+ }
+
+ ED_vgroup_parray_remove_zero(
+ dvert_array, dvert_tot, vgroup_validmap, vgroup_tot, epsilon, keep_single);
+
+ MEM_freeN(dvert_array);
+ }
+}
+
+static void vgroup_quantize_subset(Object *ob,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const int UNUSED(subset_count),
+ const int steps)
+{
+ MDeformVert **dvert_array = NULL;
+ int dvert_tot = 0;
+ const bool use_vert_sel = vertex_group_use_vert_sel(ob);
+ const bool use_mirror = (ob->type == OB_MESH) ?
+ (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 :
+ false;
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+
+ if (dvert_array) {
+ const float steps_fl = steps;
+ MDeformVert *dv;
+ int i;
+
+ if (use_mirror && use_vert_sel) {
+ ED_vgroup_parray_mirror_assign(ob, dvert_array, dvert_tot);
+ }
+
+ for (i = 0; i < dvert_tot; i++) {
+ MDeformWeight *dw;
+ int j;
+
+ /* in case its not selected */
+ if (!(dv = dvert_array[i])) {
+ continue;
+ }
+
+ for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) {
+ if ((dw->def_nr < vgroup_tot) && vgroup_validmap[dw->def_nr]) {
+ dw->weight = floorf((dw->weight * steps_fl) + 0.5f) / steps_fl;
+ CLAMP(dw->weight, 0.0f, 1.0f);
+ }
+ }
+ }
+
+ MEM_freeN(dvert_array);
+ }
+}
+
+static void dvert_mirror_op(MDeformVert *dvert,
+ MDeformVert *dvert_mirr,
+ const char sel,
+ const char sel_mirr,
+ const int *flip_map,
+ const int flip_map_len,
+ const bool mirror_weights,
+ const bool flip_vgroups,
+ const bool all_vgroups,
+ const int act_vgroup)
+{
+ BLI_assert(sel || sel_mirr);
+
+ if (sel_mirr && sel) {
+ /* swap */
+ if (mirror_weights) {
+ if (all_vgroups) {
+ SWAP(MDeformVert, *dvert, *dvert_mirr);
+ }
+ else {
+ MDeformWeight *dw = defvert_find_index(dvert, act_vgroup);
+ MDeformWeight *dw_mirr = 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->weight = dw->weight;
+ defvert_remove_group(dvert, dw);
+ }
+ else if (dw_mirr) {
+ dw = defvert_verify_index(dvert, act_vgroup);
+ dw->weight = dw_mirr->weight;
+ 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);
+ }
+ }
+ else {
+ /* dvert should always be the target, only swaps pointer */
+ if (sel_mirr) {
+ SWAP(MDeformVert *, dvert, dvert_mirr);
+ }
+
+ if (mirror_weights) {
+ if (all_vgroups) {
+ defvert_copy(dvert, dvert_mirr);
+ }
+ else {
+ 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);
+ }
+ }
}
/* TODO, vgroup locking */
/* TODO, face masking */
-void ED_vgroup_mirror(
- Object *ob,
- const bool mirror_weights, const bool flip_vgroups,
- const bool all_vgroups, const bool use_topology,
- int *r_totmirr, int *r_totfail)
-{
-
-#define VGROUP_MIRR_OP \
- dvert_mirror_op(dvert, dvert_mirr, \
- sel, sel_mirr, \
- flip_map, flip_map_len, \
- mirror_weights, flip_vgroups, \
- all_vgroups, def_nr \
- )
-
- BMVert *eve, *eve_mirr;
- MDeformVert *dvert, *dvert_mirr;
- char sel, sel_mirr;
- int *flip_map = NULL, flip_map_len;
- const int def_nr = ob->actdef - 1;
- int totmirr = 0, totfail = 0;
-
- *r_totmirr = *r_totfail = 0;
-
- if ((mirror_weights == false && flip_vgroups == false) ||
- (BLI_findlink(&ob->defbase, def_nr) == NULL))
- {
- return;
- }
-
- 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);
-
- BLI_assert(flip_map != NULL);
-
- if (flip_map == NULL) {
- /* something went wrong!, possibly no groups */
- return;
- }
- }
- else {
- flip_map = NULL;
- flip_map_len = 0;
- }
-
- /* only the active group */
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
-
- if (em) {
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
- BMIter iter;
-
- if (cd_dvert_offset == -1) {
- goto cleanup;
- }
-
- EDBM_verts_mirror_cache_begin(em, 0, true, false, use_topology);
-
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
-
- /* Go through the list of editverts and assign them */
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(eve, BM_ELEM_TAG)) {
- if ((eve_mirr = EDBM_verts_mirror_get(em, eve))) {
- if (eve_mirr != eve) {
- if (!BM_elem_flag_test(eve_mirr, BM_ELEM_TAG)) {
- sel = BM_elem_flag_test(eve, BM_ELEM_SELECT);
- sel_mirr = BM_elem_flag_test(eve_mirr, BM_ELEM_SELECT);
-
- if ((sel || sel_mirr) && (eve != eve_mirr)) {
- dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- dvert_mirr = BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset);
-
- VGROUP_MIRR_OP;
- totmirr++;
- }
-
- /* don't use these again */
- BM_elem_flag_enable(eve, BM_ELEM_TAG);
- BM_elem_flag_enable(eve_mirr, BM_ELEM_TAG);
- }
- }
- }
- else {
- totfail++;
- }
- }
- }
- EDBM_verts_mirror_cache_end(em);
- }
- else {
- /* object mode / weight paint */
- MVert *mv, *mv_mirr;
- int vidx, vidx_mirr;
- const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
-
- if (me->dvert == NULL) {
- goto cleanup;
- }
-
- if (!use_vert_sel) {
- sel = sel_mirr = true;
- }
-
- /* tag verts we have used */
- for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) {
- mv->flag &= ~ME_VERT_TMP_TAG;
- }
-
- for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) {
- if ((mv->flag & ME_VERT_TMP_TAG) == 0) {
- if ((vidx_mirr = mesh_get_x_mirror_vert(ob, NULL, vidx, use_topology)) != -1) {
- if (vidx != vidx_mirr) {
- mv_mirr = &me->mvert[vidx_mirr];
- if ((mv_mirr->flag & ME_VERT_TMP_TAG) == 0) {
-
- if (use_vert_sel) {
- sel = mv->flag & SELECT;
- sel_mirr = mv_mirr->flag & SELECT;
- }
-
- if (sel || sel_mirr) {
- dvert = &me->dvert[vidx];
- dvert_mirr = &me->dvert[vidx_mirr];
-
- VGROUP_MIRR_OP;
- totmirr++;
- }
-
- mv->flag |= ME_VERT_TMP_TAG;
- mv_mirr->flag |= ME_VERT_TMP_TAG;
- }
- }
- }
- else {
- totfail++;
- }
- }
- }
- }
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = vgroup_edit_lattice(ob);
- int i1, i2;
- int u, v, w;
- int pntsu_half;
- /* half but found up odd value */
-
- if (lt->pntsu == 1 || lt->dvert == NULL) {
- goto cleanup;
- }
-
- /* unlike editmesh we know that by only looping over the first half of
- * the 'u' indices it will cover all points except the middle which is
- * ok in this case */
- pntsu_half = lt->pntsu / 2;
-
- for (w = 0; w < lt->pntsw; w++) {
- for (v = 0; v < lt->pntsv; v++) {
- for (u = 0; u < pntsu_half; u++) {
- int u_inv = (lt->pntsu - 1) - u;
- if (u != u_inv) {
- BPoint *bp, *bp_mirr;
-
- i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
- i2 = BKE_lattice_index_from_uvw(lt, u_inv, v, w);
-
- bp = &lt->def[i1];
- bp_mirr = &lt->def[i2];
-
- sel = bp->f1 & SELECT;
- sel_mirr = bp_mirr->f1 & SELECT;
-
- if (sel || sel_mirr) {
- dvert = &lt->dvert[i1];
- dvert_mirr = &lt->dvert[i2];
-
- VGROUP_MIRR_OP;
- totmirr++;
- }
- }
- }
- }
- }
- }
-
- /* disabled, confusing when you have an active pose bone */
+void ED_vgroup_mirror(Object *ob,
+ const bool mirror_weights,
+ const bool flip_vgroups,
+ const bool all_vgroups,
+ const bool use_topology,
+ int *r_totmirr,
+ int *r_totfail)
+{
+
+#define VGROUP_MIRR_OP \
+ dvert_mirror_op(dvert, \
+ dvert_mirr, \
+ sel, \
+ sel_mirr, \
+ flip_map, \
+ flip_map_len, \
+ mirror_weights, \
+ flip_vgroups, \
+ all_vgroups, \
+ def_nr)
+
+ BMVert *eve, *eve_mirr;
+ MDeformVert *dvert, *dvert_mirr;
+ char sel, sel_mirr;
+ int *flip_map = NULL, flip_map_len;
+ const int def_nr = ob->actdef - 1;
+ int totmirr = 0, totfail = 0;
+
+ *r_totmirr = *r_totfail = 0;
+
+ if ((mirror_weights == false && flip_vgroups == false) ||
+ (BLI_findlink(&ob->defbase, def_nr) == NULL)) {
+ return;
+ }
+
+ 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);
+
+ BLI_assert(flip_map != NULL);
+
+ if (flip_map == NULL) {
+ /* something went wrong!, possibly no groups */
+ return;
+ }
+ }
+ else {
+ flip_map = NULL;
+ flip_map_len = 0;
+ }
+
+ /* only the active group */
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+
+ if (em) {
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+ BMIter iter;
+
+ if (cd_dvert_offset == -1) {
+ goto cleanup;
+ }
+
+ EDBM_verts_mirror_cache_begin(em, 0, true, false, use_topology);
+
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
+ /* Go through the list of editverts and assign them */
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_TAG)) {
+ if ((eve_mirr = EDBM_verts_mirror_get(em, eve))) {
+ if (eve_mirr != eve) {
+ if (!BM_elem_flag_test(eve_mirr, BM_ELEM_TAG)) {
+ sel = BM_elem_flag_test(eve, BM_ELEM_SELECT);
+ sel_mirr = BM_elem_flag_test(eve_mirr, BM_ELEM_SELECT);
+
+ if ((sel || sel_mirr) && (eve != eve_mirr)) {
+ dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+ dvert_mirr = BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset);
+
+ VGROUP_MIRR_OP;
+ totmirr++;
+ }
+
+ /* don't use these again */
+ BM_elem_flag_enable(eve, BM_ELEM_TAG);
+ BM_elem_flag_enable(eve_mirr, BM_ELEM_TAG);
+ }
+ }
+ }
+ else {
+ totfail++;
+ }
+ }
+ }
+ EDBM_verts_mirror_cache_end(em);
+ }
+ else {
+ /* object mode / weight paint */
+ MVert *mv, *mv_mirr;
+ int vidx, vidx_mirr;
+ const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+
+ if (me->dvert == NULL) {
+ goto cleanup;
+ }
+
+ if (!use_vert_sel) {
+ sel = sel_mirr = true;
+ }
+
+ /* tag verts we have used */
+ for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) {
+ mv->flag &= ~ME_VERT_TMP_TAG;
+ }
+
+ for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) {
+ if ((mv->flag & ME_VERT_TMP_TAG) == 0) {
+ if ((vidx_mirr = mesh_get_x_mirror_vert(ob, NULL, vidx, use_topology)) != -1) {
+ if (vidx != vidx_mirr) {
+ mv_mirr = &me->mvert[vidx_mirr];
+ if ((mv_mirr->flag & ME_VERT_TMP_TAG) == 0) {
+
+ if (use_vert_sel) {
+ sel = mv->flag & SELECT;
+ sel_mirr = mv_mirr->flag & SELECT;
+ }
+
+ if (sel || sel_mirr) {
+ dvert = &me->dvert[vidx];
+ dvert_mirr = &me->dvert[vidx_mirr];
+
+ VGROUP_MIRR_OP;
+ totmirr++;
+ }
+
+ mv->flag |= ME_VERT_TMP_TAG;
+ mv_mirr->flag |= ME_VERT_TMP_TAG;
+ }
+ }
+ }
+ else {
+ totfail++;
+ }
+ }
+ }
+ }
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = vgroup_edit_lattice(ob);
+ int i1, i2;
+ int u, v, w;
+ int pntsu_half;
+ /* half but found up odd value */
+
+ if (lt->pntsu == 1 || lt->dvert == NULL) {
+ goto cleanup;
+ }
+
+ /* unlike editmesh we know that by only looping over the first half of
+ * the 'u' indices it will cover all points except the middle which is
+ * ok in this case */
+ pntsu_half = lt->pntsu / 2;
+
+ for (w = 0; w < lt->pntsw; w++) {
+ for (v = 0; v < lt->pntsv; v++) {
+ for (u = 0; u < pntsu_half; u++) {
+ int u_inv = (lt->pntsu - 1) - u;
+ if (u != u_inv) {
+ BPoint *bp, *bp_mirr;
+
+ i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
+ i2 = BKE_lattice_index_from_uvw(lt, u_inv, v, w);
+
+ bp = &lt->def[i1];
+ bp_mirr = &lt->def[i2];
+
+ sel = bp->f1 & SELECT;
+ sel_mirr = bp_mirr->f1 & SELECT;
+
+ if (sel || sel_mirr) {
+ dvert = &lt->dvert[i1];
+ dvert_mirr = &lt->dvert[i2];
+
+ VGROUP_MIRR_OP;
+ totmirr++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* disabled, confusing when you have an active pose bone */
#if 0
- /* flip active group index */
- if (flip_vgroups && flip_map[def_nr] >= 0)
- ob->actdef = flip_map[def_nr] + 1;
+ /* flip active group index */
+ if (flip_vgroups && flip_map[def_nr] >= 0)
+ ob->actdef = flip_map[def_nr] + 1;
#endif
cleanup:
- *r_totmirr = totmirr;
- *r_totfail = totfail;
+ *r_totmirr = totmirr;
+ *r_totfail = totfail;
- if (flip_map) MEM_freeN(flip_map);
+ if (flip_map)
+ MEM_freeN(flip_map);
#undef VGROUP_MIRR_OP
-
}
static void vgroup_delete_active(Object *ob)
{
- bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
- if (!dg)
- return;
+ bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
+ if (!dg)
+ return;
- BKE_object_defgroup_remove(ob, dg);
+ BKE_object_defgroup_remove(ob, dg);
}
/* only in editmode */
static void vgroup_assign_verts(Object *ob, const float weight)
{
- const int def_nr = ob->actdef - 1;
-
- if (!BLI_findlink(&ob->defbase, def_nr))
- return;
-
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- if (me->edit_mesh) {
- BMEditMesh *em = me->edit_mesh;
- int cd_dvert_offset;
-
- BMIter iter;
- BMVert *eve;
-
- if (!CustomData_has_layer(&em->bm->vdata, CD_MDEFORMVERT))
- BM_data_layer_add(em->bm, &em->bm->vdata, CD_MDEFORMVERT);
-
- cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
-
- /* Go through the list of editverts and assign them */
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- 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);
- if (dw) {
- dw->weight = weight;
- }
- }
- }
- }
- else {
- MVert *mv;
- MDeformVert *dv;
- int i;
-
- if (!me->dvert) {
- BKE_object_defgroup_data_create(&me->id);
- }
-
- mv = me->mvert;
- dv = me->dvert;
-
- for (i = 0; i < me->totvert; i++, mv++, dv++) {
- if (mv->flag & SELECT) {
- MDeformWeight *dw;
- dw = defvert_verify_index(dv, def_nr);
- if (dw) {
- dw->weight = weight;
- }
- }
- }
- }
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = vgroup_edit_lattice(ob);
- MDeformVert *dv;
- BPoint *bp;
- int a, tot;
-
- if (lt->dvert == NULL)
- BKE_object_defgroup_data_create(&lt->id);
-
- dv = lt->dvert;
-
- tot = lt->pntsu * lt->pntsv * lt->pntsw;
- for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) {
- if (bp->f1 & SELECT) {
- MDeformWeight *dw;
-
- dw = defvert_verify_index(dv, def_nr);
- if (dw) {
- dw->weight = weight;
- }
- }
- }
- }
+ const int def_nr = ob->actdef - 1;
+
+ if (!BLI_findlink(&ob->defbase, def_nr))
+ return;
+
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (me->edit_mesh) {
+ BMEditMesh *em = me->edit_mesh;
+ int cd_dvert_offset;
+
+ BMIter iter;
+ BMVert *eve;
+
+ if (!CustomData_has_layer(&em->bm->vdata, CD_MDEFORMVERT))
+ BM_data_layer_add(em->bm, &em->bm->vdata, CD_MDEFORMVERT);
+
+ cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+
+ /* Go through the list of editverts and assign them */
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ 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);
+ if (dw) {
+ dw->weight = weight;
+ }
+ }
+ }
+ }
+ else {
+ MVert *mv;
+ MDeformVert *dv;
+ int i;
+
+ if (!me->dvert) {
+ BKE_object_defgroup_data_create(&me->id);
+ }
+
+ mv = me->mvert;
+ dv = me->dvert;
+
+ for (i = 0; i < me->totvert; i++, mv++, dv++) {
+ if (mv->flag & SELECT) {
+ MDeformWeight *dw;
+ dw = defvert_verify_index(dv, def_nr);
+ if (dw) {
+ dw->weight = weight;
+ }
+ }
+ }
+ }
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = vgroup_edit_lattice(ob);
+ MDeformVert *dv;
+ BPoint *bp;
+ int a, tot;
+
+ if (lt->dvert == NULL)
+ BKE_object_defgroup_data_create(&lt->id);
+
+ dv = lt->dvert;
+
+ tot = lt->pntsu * lt->pntsv * lt->pntsw;
+ for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) {
+ if (bp->f1 & SELECT) {
+ MDeformWeight *dw;
+
+ dw = defvert_verify_index(dv, def_nr);
+ if (dw) {
+ dw->weight = weight;
+ }
+ }
+ }
+ }
}
/********************** vertex group operators *********************/
static bool vertex_group_poll(bContext *C)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
- return (ob && !ID_IS_LINKED(ob) &&
- data && !ID_IS_LINKED(data) &&
- OB_TYPE_SUPPORT_VGROUP(ob->type) &&
- ob->defbase.first);
+ return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) &&
+ OB_TYPE_SUPPORT_VGROUP(ob->type) && ob->defbase.first);
}
static bool vertex_group_supported_poll(bContext *C)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
- return (ob && !ID_IS_LINKED(ob) && OB_TYPE_SUPPORT_VGROUP(ob->type) &&
- data && !ID_IS_LINKED(data));
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ return (ob && !ID_IS_LINKED(ob) && OB_TYPE_SUPPORT_VGROUP(ob->type) && data &&
+ !ID_IS_LINKED(data));
}
static bool vertex_group_mesh_poll(bContext *C)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
- return (ob && !ID_IS_LINKED(ob) &&
- data && !ID_IS_LINKED(data) &&
- ob->type == OB_MESH &&
- ob->defbase.first);
+ return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) && ob->type == OB_MESH &&
+ ob->defbase.first);
}
static bool UNUSED_FUNCTION(vertex_group_mesh_supported_poll)(bContext *C)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
- return (ob && !ID_IS_LINKED(ob) && ob->type == OB_MESH && data && !ID_IS_LINKED(data));
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ return (ob && !ID_IS_LINKED(ob) && ob->type == OB_MESH && data && !ID_IS_LINKED(data));
}
-
-static bool UNUSED_FUNCTION(vertex_group_poll_edit) (bContext *C)
+static bool UNUSED_FUNCTION(vertex_group_poll_edit)(bContext *C)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
- if (!(ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data)))
- return 0;
+ if (!(ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data)))
+ return 0;
- return BKE_object_is_in_editmode_vgroup(ob);
+ return BKE_object_is_in_editmode_vgroup(ob);
}
/* editmode _or_ weight paint vertex sel */
-static bool vertex_group_vert_poll_ex(bContext *C, const bool needs_select, const short ob_type_flag)
-{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
-
- if (!(ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data)))
- return false;
-
- if (ob_type_flag && (((1 << ob->type) & ob_type_flag)) == 0) {
- return false;
- }
-
- if (BKE_object_is_in_editmode_vgroup(ob)) {
- return true;
- }
- else if (ob->mode & OB_MODE_WEIGHT_PAINT) {
- if (needs_select) {
- if (BKE_object_is_in_wpaint_select_vert(ob)) {
- return true;
- }
- else {
- CTX_wm_operator_poll_msg_set(C, "Vertex select needs to be enabled in weight paint mode");
- return false;
- }
- }
- else {
- return true;
- }
- }
- else {
- return false;
- }
+static bool vertex_group_vert_poll_ex(bContext *C,
+ const bool needs_select,
+ const short ob_type_flag)
+{
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+
+ if (!(ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data)))
+ return false;
+
+ if (ob_type_flag && (((1 << ob->type) & ob_type_flag)) == 0) {
+ return false;
+ }
+
+ if (BKE_object_is_in_editmode_vgroup(ob)) {
+ return true;
+ }
+ else if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ if (needs_select) {
+ if (BKE_object_is_in_wpaint_select_vert(ob)) {
+ return true;
+ }
+ else {
+ CTX_wm_operator_poll_msg_set(C, "Vertex select needs to be enabled in weight paint mode");
+ return false;
+ }
+ }
+ else {
+ return true;
+ }
+ }
+ else {
+ return false;
+ }
}
#if 0
static bool vertex_group_vert_poll(bContext *C)
{
- return vertex_group_vert_poll_ex(C, false, 0);
+ return vertex_group_vert_poll_ex(C, false, 0);
}
#endif
-
static bool vertex_group_mesh_vert_poll(bContext *C)
{
- return vertex_group_vert_poll_ex(C, false, (1 << OB_MESH));
+ return vertex_group_vert_poll_ex(C, false, (1 << OB_MESH));
}
static bool vertex_group_vert_select_poll(bContext *C)
{
- return vertex_group_vert_poll_ex(C, true, 0);
+ return vertex_group_vert_poll_ex(C, true, 0);
}
#if 0
static bool vertex_group_mesh_vert_select_poll(bContext *C)
{
- return vertex_group_vert_poll_ex(C, true, (1 << OB_MESH));
+ return vertex_group_vert_poll_ex(C, true, (1 << OB_MESH));
}
#endif
-
/* editmode _or_ weight paint vertex sel and active group unlocked */
static bool vertex_group_vert_select_unlocked_poll(bContext *C)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
-
- if (!(ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data)))
- return 0;
-
- if (!(BKE_object_is_in_editmode_vgroup(ob) ||
- BKE_object_is_in_wpaint_select_vert(ob)))
- {
- return 0;
- }
-
- if (ob->actdef != 0) {
- bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
- if (dg) {
- return !(dg->flag & DG_LOCK_WEIGHT);
- }
- }
- return 1;
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+
+ if (!(ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data)))
+ return 0;
+
+ if (!(BKE_object_is_in_editmode_vgroup(ob) || BKE_object_is_in_wpaint_select_vert(ob))) {
+ return 0;
+ }
+
+ if (ob->actdef != 0) {
+ bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
+ if (dg) {
+ return !(dg->flag & DG_LOCK_WEIGHT);
+ }
+ }
+ return 1;
}
static bool vertex_group_vert_select_mesh_poll(bContext *C)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
- if (!(ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data)))
- return 0;
+ if (!(ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data)))
+ return 0;
- /* only difference to #vertex_group_vert_select_poll */
- if (ob->type != OB_MESH)
- return 0;
+ /* only difference to #vertex_group_vert_select_poll */
+ if (ob->type != OB_MESH)
+ return 0;
- return (BKE_object_is_in_editmode_vgroup(ob) ||
- BKE_object_is_in_wpaint_select_vert(ob));
+ return (BKE_object_is_in_editmode_vgroup(ob) || BKE_object_is_in_wpaint_select_vert(ob));
}
static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- BKE_object_defgroup_add(ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ BKE_object_defgroup_add(ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_add";
- ot->description = "Add a new vertex group to the active object";
+ /* identifiers */
+ ot->name = "Add Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_add";
+ ot->description = "Add a new vertex group to the active object";
- /* api callbacks */
- ot->poll = vertex_group_supported_poll;
- ot->exec = vertex_group_add_exec;
+ /* api callbacks */
+ ot->poll = vertex_group_supported_poll;
+ ot->exec = vertex_group_add_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int vertex_group_remove_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- if (RNA_boolean_get(op->ptr, "all"))
- BKE_object_defgroup_remove_all(ob);
- else if (RNA_boolean_get(op->ptr, "all_unlocked"))
- BKE_object_defgroup_remove_all_ex(ob, true);
- else
- vgroup_delete_active(ob);
+ if (RNA_boolean_get(op->ptr, "all"))
+ BKE_object_defgroup_remove_all(ob);
+ else if (RNA_boolean_get(op->ptr, "all_unlocked"))
+ BKE_object_defgroup_remove_all_ex(ob, true);
+ else
+ vgroup_delete_active(ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_remove";
- ot->description = "Delete the active or all vertex groups from the active object";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_remove_exec;
-
- /* flags */
- /* redo operator will fail in this case because vertex groups aren't stored
- * in local edit mode stack and toggling "all" property will lead to
- * all groups deleted without way to restore them (see [#29527], sergey) */
- ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
-
- /* properties */
- PropertyRNA *prop = RNA_def_boolean(ot->srna, "all", 0, "All", "Remove all vertex groups");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "all_unlocked", 0, "All Unlocked", "Remove all unlocked vertex groups");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* identifiers */
+ ot->name = "Remove Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_remove";
+ ot->description = "Delete the active or all vertex groups from the active object";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_remove_exec;
+
+ /* flags */
+ /* redo operator will fail in this case because vertex groups aren't stored
+ * in local edit mode stack and toggling "all" property will lead to
+ * all groups deleted without way to restore them (see [#29527], sergey) */
+ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
+
+ /* properties */
+ PropertyRNA *prop = RNA_def_boolean(ot->srna, "all", 0, "All", "Remove all vertex groups");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(
+ ot->srna, "all_unlocked", 0, "All Unlocked", "Remove all unlocked vertex groups");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static int vertex_group_assign_exec(bContext *C, wmOperator *UNUSED(op))
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- Object *ob = ED_object_context(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = ED_object_context(C);
- vgroup_assign_verts(ob, ts->vgroup_weight);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ vgroup_assign_verts(ob, ts->vgroup_weight);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_assign(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Assign to Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_assign";
- ot->description = "Assign the selected vertices to the active vertex group";
-
- /* api callbacks */
- ot->poll = vertex_group_vert_select_unlocked_poll;
- ot->exec = vertex_group_assign_exec;
-
- /* flags */
- /* redo operator will fail in this case because vertex group assignment
- * isn't stored in local edit mode stack and toggling "new" property will
- * lead to creating plenty of new vertex groups (see [#29527], sergey) */
- ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Assign to Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_assign";
+ ot->description = "Assign the selected vertices to the active vertex group";
+
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_unlocked_poll;
+ ot->exec = vertex_group_assign_exec;
+
+ /* flags */
+ /* redo operator will fail in this case because vertex group assignment
+ * isn't stored in local edit mode stack and toggling "new" property will
+ * lead to creating plenty of new vertex groups (see [#29527], sergey) */
+ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
}
/* NOTE: just a wrapper around vertex_group_assign_exec(), except we add these to a new group */
static int vertex_group_assign_new_exec(bContext *C, wmOperator *op)
{
- /* create new group... */
- Object *ob = ED_object_context(C);
- BKE_object_defgroup_add(ob);
+ /* create new group... */
+ Object *ob = ED_object_context(C);
+ BKE_object_defgroup_add(ob);
- /* assign selection to new group */
- return vertex_group_assign_exec(C, op);
+ /* assign selection to new group */
+ return vertex_group_assign_exec(C, op);
}
void OBJECT_OT_vertex_group_assign_new(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Assign to New Group";
- ot->idname = "OBJECT_OT_vertex_group_assign_new";
- ot->description = "Assign the selected vertices to a new vertex group";
-
- /* api callbacks */
- ot->poll = vertex_group_vert_select_poll;
- ot->exec = vertex_group_assign_new_exec;
-
- /* flags */
- /* redo operator will fail in this case because vertex group assignment
- * isn't stored in local edit mode stack and toggling "new" property will
- * lead to creating plenty of new vertex groups (see [#29527], sergey) */
- ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Assign to New Group";
+ ot->idname = "OBJECT_OT_vertex_group_assign_new";
+ ot->description = "Assign the selected vertices to a new vertex group";
+
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_poll;
+ ot->exec = vertex_group_assign_new_exec;
+
+ /* flags */
+ /* redo operator will fail in this case because vertex group assignment
+ * isn't stored in local edit mode stack and toggling "new" property will
+ * lead to creating plenty of new vertex groups (see [#29527], sergey) */
+ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
}
static int vertex_group_remove_from_exec(bContext *C, wmOperator *op)
{
- const bool use_all_groups = RNA_boolean_get(op->ptr, "use_all_groups");
- const bool use_all_verts = RNA_boolean_get(op->ptr, "use_all_verts");
+ const bool use_all_groups = RNA_boolean_get(op->ptr, "use_all_groups");
+ const bool use_all_verts = RNA_boolean_get(op->ptr, "use_all_verts");
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- if (use_all_groups) {
- if (BKE_object_defgroup_clear_all(ob, true) == false) {
- return OPERATOR_CANCELLED;
- }
- }
- else {
- bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
+ if (use_all_groups) {
+ if (BKE_object_defgroup_clear_all(ob, true) == false) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
- if ((dg == NULL) || (BKE_object_defgroup_clear(ob, dg, !use_all_verts) == false)) {
- return OPERATOR_CANCELLED;
- }
- }
+ if ((dg == NULL) || (BKE_object_defgroup_clear(ob, dg, !use_all_verts) == false)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot)
{
- PropertyRNA *prop;
- /* identifiers */
- ot->name = "Remove from Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_remove_from";
- ot->description = "Remove the selected vertices from active or all vertex group(s)";
-
- /* api callbacks */
- ot->poll = vertex_group_vert_select_unlocked_poll;
- ot->exec = vertex_group_remove_from_exec;
-
- /* flags */
- /* redo operator will fail in this case because vertex groups assignment
- * isn't stored in local edit mode stack and toggling "all" property will lead to
- * removing vertices from all groups (see [#29527], sergey) */
- ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_boolean(ot->srna, "use_all_groups", 0, "All Groups", "Remove from all groups");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "use_all_verts", 0, "All Verts", "Clear the active group");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+ /* identifiers */
+ ot->name = "Remove from Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_remove_from";
+ ot->description = "Remove the selected vertices from active or all vertex group(s)";
+
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_unlocked_poll;
+ ot->exec = vertex_group_remove_from_exec;
+
+ /* flags */
+ /* redo operator will fail in this case because vertex groups assignment
+ * isn't stored in local edit mode stack and toggling "all" property will lead to
+ * removing vertices from all groups (see [#29527], sergey) */
+ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "use_all_groups", 0, "All Groups", "Remove from all groups");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "use_all_verts", 0, "All Verts", "Clear the active group");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- if (!ob || ID_IS_LINKED(ob))
- return OPERATOR_CANCELLED;
+ if (!ob || ID_IS_LINKED(ob))
+ return OPERATOR_CANCELLED;
- vgroup_select_verts(ob, 1);
- DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
+ vgroup_select_verts(ob, 1);
+ DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_select";
- ot->description = "Select all the vertices assigned to the active vertex group";
+ /* identifiers */
+ ot->name = "Select Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_select";
+ ot->description = "Select all the vertices assigned to the active vertex group";
- /* api callbacks */
- ot->poll = vertex_group_vert_select_poll;
- ot->exec = vertex_group_select_exec;
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_poll;
+ ot->exec = vertex_group_select_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- vgroup_select_verts(ob, 0);
- DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
+ vgroup_select_verts(ob, 0);
+ DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_deselect(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Deselect Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_deselect";
- ot->description = "Deselect all selected vertices assigned to the active vertex group";
+ /* identifiers */
+ ot->name = "Deselect Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_deselect";
+ ot->description = "Deselect all selected vertices assigned to the active vertex group";
- /* api callbacks */
- ot->poll = vertex_group_vert_select_poll;
- ot->exec = vertex_group_deselect_exec;
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_poll;
+ ot->exec = vertex_group_deselect_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- vgroup_duplicate(ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
+ vgroup_duplicate(ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_copy";
- ot->description = "Make a copy of the active vertex group";
+ /* identifiers */
+ ot->name = "Copy Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_copy";
+ ot->description = "Make a copy of the active vertex group";
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_copy_exec;
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_copy_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int vertex_group_levels_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- float offset = RNA_float_get(op->ptr, "offset");
- float gain = RNA_float_get(op->ptr, "gain");
- eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
+ float offset = RNA_float_get(op->ptr, "offset");
+ float gain = RNA_float_get(op->ptr, "gain");
+ eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
- int subset_count, vgroup_tot;
+ int subset_count, vgroup_tot;
- const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
- vgroup_levels_subset(ob, vgroup_validmap, vgroup_tot, subset_count, offset, gain);
- MEM_freeN((void *)vgroup_validmap);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
+ ob, subset_type, &vgroup_tot, &subset_count);
+ vgroup_levels_subset(ob, vgroup_validmap, vgroup_tot, subset_count, offset, gain);
+ MEM_freeN((void *)vgroup_validmap);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_levels(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Vertex Group Levels";
- ot->idname = "OBJECT_OT_vertex_group_levels";
- ot->description = "Add some offset and multiply with some gain the weights of the active vertex group";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_levels_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- vgroup_operator_subset_select_props(ot, true);
- RNA_def_float(ot->srna, "offset", 0.f, -1.0, 1.0, "Offset", "Value to add to weights", -1.0f, 1.f);
- RNA_def_float(ot->srna, "gain", 1.f, 0.f, FLT_MAX, "Gain", "Value to multiply weights by", 0.0f, 10.f);
+ /* identifiers */
+ ot->name = "Vertex Group Levels";
+ ot->idname = "OBJECT_OT_vertex_group_levels";
+ ot->description =
+ "Add some offset and multiply with some gain the weights of the active vertex group";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_levels_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ vgroup_operator_subset_select_props(ot, true);
+ RNA_def_float(
+ ot->srna, "offset", 0.f, -1.0, 1.0, "Offset", "Value to add to weights", -1.0f, 1.f);
+ RNA_def_float(
+ ot->srna, "gain", 1.f, 0.f, FLT_MAX, "Gain", "Value to multiply weights by", 0.0f, 10.f);
}
static int vertex_group_normalize_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- bool changed;
+ Object *ob = ED_object_context(C);
+ bool changed;
- changed = vgroup_normalize(ob);
+ changed = vgroup_normalize(ob);
- if (changed) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ if (changed) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void OBJECT_OT_vertex_group_normalize(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Normalize Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_normalize";
- ot->description = "Normalize weights of the active vertex group, so that the highest ones are now 1.0";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_normalize_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Normalize Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_normalize";
+ ot->description =
+ "Normalize weights of the active vertex group, so that the highest ones are now 1.0";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_normalize_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- bool lock_active = RNA_boolean_get(op->ptr, "lock_active");
- eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
- bool changed;
- int subset_count, vgroup_tot;
- const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
-
- changed = vgroup_normalize_all(ob, vgroup_validmap, vgroup_tot, subset_count, lock_active, op->reports);
- MEM_freeN((void *)vgroup_validmap);
-
- if (changed) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
-
- return OPERATOR_FINISHED;
- }
- else {
- /* allow to adjust settings */
- return OPERATOR_FINISHED;
- }
+ Object *ob = ED_object_context(C);
+ bool lock_active = RNA_boolean_get(op->ptr, "lock_active");
+ eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
+ bool changed;
+ int subset_count, vgroup_tot;
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
+ ob, subset_type, &vgroup_tot, &subset_count);
+
+ changed = vgroup_normalize_all(
+ ob, vgroup_validmap, vgroup_tot, subset_count, lock_active, op->reports);
+ MEM_freeN((void *)vgroup_validmap);
+
+ if (changed) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ /* allow to adjust settings */
+ return OPERATOR_FINISHED;
+ }
}
void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Normalize All Vertex Groups";
- ot->idname = "OBJECT_OT_vertex_group_normalize_all";
- ot->description = "Normalize all weights of all vertex groups, "
- "so that for each vertex, the sum of all weights is 1.0";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_normalize_all_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- vgroup_operator_subset_select_props(ot, false);
- RNA_def_boolean(ot->srna, "lock_active", true, "Lock Active",
- "Keep the values of the active group while normalizing others");
+ /* identifiers */
+ ot->name = "Normalize All Vertex Groups";
+ ot->idname = "OBJECT_OT_vertex_group_normalize_all";
+ ot->description =
+ "Normalize all weights of all vertex groups, "
+ "so that for each vertex, the sum of all weights is 1.0";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_normalize_all_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ vgroup_operator_subset_select_props(ot, false);
+ RNA_def_boolean(ot->srna,
+ "lock_active",
+ true,
+ "Lock Active",
+ "Keep the values of the active group while normalizing others");
}
static int vertex_group_fix_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
- Scene *scene = CTX_data_scene(C);
-
- float distToBe = RNA_float_get(op->ptr, "dist");
- float strength = RNA_float_get(op->ptr, "strength");
- float cp = RNA_float_get(op->ptr, "accuracy");
- ModifierData *md = ob->modifiers.first;
-
- while (md) {
- if (md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) {
- break;
- }
- md = md->next;
- }
-
- if (md && md->type == eModifierType_Mirror) {
- BKE_report(op->reports, RPT_ERROR_INVALID_CONTEXT, "This operator does not support an active mirror modifier");
- return OPERATOR_CANCELLED;
- }
- vgroup_fix(C, scene, ob, distToBe, strength, cp);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
-
- return OPERATOR_FINISHED;
+ Object *ob = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+
+ float distToBe = RNA_float_get(op->ptr, "dist");
+ float strength = RNA_float_get(op->ptr, "strength");
+ float cp = RNA_float_get(op->ptr, "accuracy");
+ ModifierData *md = ob->modifiers.first;
+
+ while (md) {
+ if (md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) {
+ break;
+ }
+ md = md->next;
+ }
+
+ if (md && md->type == eModifierType_Mirror) {
+ BKE_report(op->reports,
+ RPT_ERROR_INVALID_CONTEXT,
+ "This operator does not support an active mirror modifier");
+ return OPERATOR_CANCELLED;
+ }
+ vgroup_fix(C, scene, ob, distToBe, strength, cp);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_fix(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Fix Vertex Group Deform";
- ot->idname = "OBJECT_OT_vertex_group_fix";
- ot->description = "Modify the position of selected vertices by changing only their respective "
- "groups' weights (this tool may be slow for many vertices)";
-
- /* api callbacks */
- ot->poll = vertex_group_mesh_poll;
- ot->exec = vertex_group_fix_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_float(ot->srna, "dist", 0.0f, -FLT_MAX, FLT_MAX, "Distance", "The distance to move to", -10.0f, 10.0f);
- RNA_def_float(ot->srna, "strength", 1.f, -2.0f, FLT_MAX, "Strength",
- "The distance moved can be changed by this multiplier", -2.0f, 2.0f);
- RNA_def_float(ot->srna, "accuracy", 1.0f, 0.05f, FLT_MAX, "Change Sensitivity",
- "Change the amount weights are altered with each iteration: lower values are slower", 0.05f, 1.f);
+ /* identifiers */
+ ot->name = "Fix Vertex Group Deform";
+ ot->idname = "OBJECT_OT_vertex_group_fix";
+ ot->description =
+ "Modify the position of selected vertices by changing only their respective "
+ "groups' weights (this tool may be slow for many vertices)";
+
+ /* api callbacks */
+ ot->poll = vertex_group_mesh_poll;
+ ot->exec = vertex_group_fix_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ RNA_def_float(ot->srna,
+ "dist",
+ 0.0f,
+ -FLT_MAX,
+ FLT_MAX,
+ "Distance",
+ "The distance to move to",
+ -10.0f,
+ 10.0f);
+ RNA_def_float(ot->srna,
+ "strength",
+ 1.f,
+ -2.0f,
+ FLT_MAX,
+ "Strength",
+ "The distance moved can be changed by this multiplier",
+ -2.0f,
+ 2.0f);
+ RNA_def_float(
+ ot->srna,
+ "accuracy",
+ 1.0f,
+ 0.05f,
+ FLT_MAX,
+ "Change Sensitivity",
+ "Change the amount weights are altered with each iteration: lower values are slower",
+ 0.05f,
+ 1.f);
}
-
static int vertex_group_lock_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- int action = RNA_enum_get(op->ptr, "action");
+ int action = RNA_enum_get(op->ptr, "action");
- vgroup_lock_all(ob, action);
+ vgroup_lock_all(ob, action);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
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";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_lock_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "action", vgroup_lock_actions, VGROUP_TOGGLE, "Action",
- "Lock action to execute on vertex groups");
+ /* 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";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_lock_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna,
+ "action",
+ vgroup_lock_actions,
+ VGROUP_TOGGLE,
+ "Action",
+ "Lock action to execute on vertex groups");
}
static int vertex_group_invert_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- bool auto_assign = RNA_boolean_get(op->ptr, "auto_assign");
- bool auto_remove = RNA_boolean_get(op->ptr, "auto_remove");
+ Object *ob = ED_object_context(C);
+ bool auto_assign = RNA_boolean_get(op->ptr, "auto_assign");
+ bool auto_remove = RNA_boolean_get(op->ptr, "auto_remove");
- eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
+ eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
- int subset_count, vgroup_tot;
+ int subset_count, vgroup_tot;
- const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
- vgroup_invert_subset(ob, vgroup_validmap, vgroup_tot, subset_count, auto_assign, auto_remove);
- MEM_freeN((void *)vgroup_validmap);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
+ ob, subset_type, &vgroup_tot, &subset_count);
+ vgroup_invert_subset(ob, vgroup_validmap, vgroup_tot, subset_count, auto_assign, auto_remove);
+ MEM_freeN((void *)vgroup_validmap);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_invert(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Invert Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_invert";
- ot->description = "Invert active vertex group's weights";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_invert_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- vgroup_operator_subset_select_props(ot, true);
- RNA_def_boolean(ot->srna, "auto_assign", true, "Add Weights",
- "Add verts from groups that have zero weight before inverting");
- RNA_def_boolean(ot->srna, "auto_remove", true, "Remove Weights",
- "Remove verts from groups that have zero weight after inverting");
+ /* identifiers */
+ ot->name = "Invert Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_invert";
+ ot->description = "Invert active vertex group's weights";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_invert_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ vgroup_operator_subset_select_props(ot, true);
+ RNA_def_boolean(ot->srna,
+ "auto_assign",
+ true,
+ "Add Weights",
+ "Add verts from groups that have zero weight before inverting");
+ RNA_def_boolean(ot->srna,
+ "auto_remove",
+ true,
+ "Remove Weights",
+ "Remove verts from groups that have zero weight after inverting");
}
static int vertex_group_smooth_exec(bContext *C, wmOperator *op)
{
- const float fac = RNA_float_get(op->ptr, "factor");
- const int repeat = RNA_int_get(op->ptr, "repeat");
- eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
- const float fac_expand = RNA_float_get(op->ptr, "expand");
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob_ctx = ED_object_context(C);
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len,
- ob_ctx->mode);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
-
- int subset_count, vgroup_tot;
-
- const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob,
- subset_type,
- &vgroup_tot,
- &subset_count);
-
- vgroup_smooth_subset(ob, vgroup_validmap, vgroup_tot, subset_count, fac, repeat, fac_expand);
- MEM_freeN((void *)vgroup_validmap);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ const float fac = RNA_float_get(op->ptr, "factor");
+ const int repeat = RNA_int_get(op->ptr, "repeat");
+ eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
+ const float fac_expand = RNA_float_get(op->ptr, "expand");
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob_ctx = ED_object_context(C);
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len, ob_ctx->mode);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+
+ int subset_count, vgroup_tot;
+
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
+ ob, subset_type, &vgroup_tot, &subset_count);
+
+ vgroup_smooth_subset(ob, vgroup_validmap, vgroup_tot, subset_count, fac, repeat, fac_expand);
+ MEM_freeN((void *)vgroup_validmap);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_smooth(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Smooth Vertex Weights";
- ot->idname = "OBJECT_OT_vertex_group_smooth";
- ot->description = "Smooth weights for selected vertices";
-
- /* api callbacks */
- ot->poll = vertex_group_mesh_vert_poll;
- ot->exec = vertex_group_smooth_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- vgroup_operator_subset_select_props(ot, true);
- RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0, "Factor", "", 0.0f, 1.0f);
- RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
-
- RNA_def_float(ot->srna, "expand", 0.0f, -1.0f, 1.0, "Expand/Contract", "Expand/contract weights", -1.0f, 1.0f);
+ /* identifiers */
+ ot->name = "Smooth Vertex Weights";
+ ot->idname = "OBJECT_OT_vertex_group_smooth";
+ ot->description = "Smooth weights for selected vertices";
+
+ /* api callbacks */
+ ot->poll = vertex_group_mesh_vert_poll;
+ ot->exec = vertex_group_smooth_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ vgroup_operator_subset_select_props(ot, true);
+ RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0, "Factor", "", 0.0f, 1.0f);
+ RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
+
+ RNA_def_float(ot->srna,
+ "expand",
+ 0.0f,
+ -1.0f,
+ 1.0,
+ "Expand/Contract",
+ "Expand/contract weights",
+ -1.0f,
+ 1.0f);
}
static int vertex_group_clean_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- float limit = RNA_float_get(op->ptr, "limit");
- bool keep_single = RNA_boolean_get(op->ptr, "keep_single");
- eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
+ float limit = RNA_float_get(op->ptr, "limit");
+ bool keep_single = RNA_boolean_get(op->ptr, "keep_single");
+ eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
- int subset_count, vgroup_tot;
+ int subset_count, vgroup_tot;
- const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
- vgroup_clean_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit, keep_single);
- MEM_freeN((void *)vgroup_validmap);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
+ ob, subset_type, &vgroup_tot, &subset_count);
+ vgroup_clean_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit, keep_single);
+ MEM_freeN((void *)vgroup_validmap);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_clean(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clean Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_clean";
- ot->description = "Remove vertex group assignments which are not required";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_clean_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- vgroup_operator_subset_select_props(ot, true);
- RNA_def_float(ot->srna, "limit", 0.0f, 0.0f, 1.0, "Limit",
- "Remove vertices which weight is below or equal to this limit", 0.0f, 0.99f);
- RNA_def_boolean(ot->srna, "keep_single", false, "Keep Single",
- "Keep verts assigned to at least one group when cleaning");
+ /* identifiers */
+ ot->name = "Clean Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_clean";
+ ot->description = "Remove vertex group assignments which are not required";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_clean_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ vgroup_operator_subset_select_props(ot, true);
+ RNA_def_float(ot->srna,
+ "limit",
+ 0.0f,
+ 0.0f,
+ 1.0,
+ "Limit",
+ "Remove vertices which weight is below or equal to this limit",
+ 0.0f,
+ 0.99f);
+ RNA_def_boolean(ot->srna,
+ "keep_single",
+ false,
+ "Keep Single",
+ "Keep verts assigned to at least one group when cleaning");
}
static int vertex_group_quantize_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- const int steps = RNA_int_get(op->ptr, "steps");
- eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
+ const int steps = RNA_int_get(op->ptr, "steps");
+ eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
- int subset_count, vgroup_tot;
+ int subset_count, vgroup_tot;
- const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
- vgroup_quantize_subset(ob, vgroup_validmap, vgroup_tot, subset_count, steps);
- MEM_freeN((void *)vgroup_validmap);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
+ ob, subset_type, &vgroup_tot, &subset_count);
+ vgroup_quantize_subset(ob, vgroup_validmap, vgroup_tot, subset_count, steps);
+ MEM_freeN((void *)vgroup_validmap);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_quantize(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Quantize Vertex Weights";
- ot->idname = "OBJECT_OT_vertex_group_quantize";
- ot->description = "Set weights to a fixed number of steps";
+ /* identifiers */
+ ot->name = "Quantize Vertex Weights";
+ ot->idname = "OBJECT_OT_vertex_group_quantize";
+ ot->description = "Set weights to a fixed number of steps";
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_quantize_exec;
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_quantize_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- vgroup_operator_subset_select_props(ot, true);
- RNA_def_int(ot->srna, "steps", 4, 1, 1000, "Steps", "Number of steps between 0 and 1", 1, 100);
+ vgroup_operator_subset_select_props(ot, true);
+ RNA_def_int(ot->srna, "steps", 4, 1, 1000, "Steps", "Number of steps between 0 and 1", 1, 100);
}
static int vertex_group_limit_total_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- const int limit = RNA_int_get(op->ptr, "limit");
- eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
+ const int limit = RNA_int_get(op->ptr, "limit");
+ eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
- int subset_count, vgroup_tot;
+ int subset_count, vgroup_tot;
- const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
- int remove_tot = vgroup_limit_total_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit);
- MEM_freeN((void *)vgroup_validmap);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
+ ob, subset_type, &vgroup_tot, &subset_count);
+ int remove_tot = vgroup_limit_total_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit);
+ MEM_freeN((void *)vgroup_validmap);
- BKE_reportf(op->reports, remove_tot ? RPT_INFO : RPT_WARNING, "%d vertex weights limited", remove_tot);
+ BKE_reportf(
+ op->reports, remove_tot ? RPT_INFO : RPT_WARNING, "%d vertex weights limited", remove_tot);
- if (remove_tot) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ if (remove_tot) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- return OPERATOR_FINISHED;
- }
- else {
- /* note, would normally return canceled, except we want the redo
- * UI to show up for users to change */
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
+ else {
+ /* note, would normally return canceled, except we want the redo
+ * UI to show up for users to change */
+ return OPERATOR_FINISHED;
+ }
}
void OBJECT_OT_vertex_group_limit_total(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Limit Number of Weights per Vertex";
- ot->idname = "OBJECT_OT_vertex_group_limit_total";
- ot->description = "Limit deform weights associated with a vertex to a specified number by removing lowest weights";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_limit_total_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- vgroup_operator_subset_select_props(ot, false);
- RNA_def_int(ot->srna, "limit", 4, 1, 32, "Limit", "Maximum number of deform weights", 1, 32);
+ /* identifiers */
+ ot->name = "Limit Number of Weights per Vertex";
+ ot->idname = "OBJECT_OT_vertex_group_limit_total";
+ ot->description =
+ "Limit deform weights associated with a vertex to a specified number by removing lowest "
+ "weights";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_limit_total_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ vgroup_operator_subset_select_props(ot, false);
+ RNA_def_int(ot->srna, "limit", 4, 1, 32, "Limit", "Maximum number of deform weights", 1, 32);
}
static int vertex_group_mirror_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- int totmirr = 0, totfail = 0;
+ Object *ob = ED_object_context(C);
+ int totmirr = 0, totfail = 0;
- ED_vgroup_mirror(
- ob,
- RNA_boolean_get(op->ptr, "mirror_weights"),
- RNA_boolean_get(op->ptr, "flip_group_names"),
- RNA_boolean_get(op->ptr, "all_groups"),
- RNA_boolean_get(op->ptr, "use_topology"),
- &totmirr, &totfail);
+ ED_vgroup_mirror(ob,
+ RNA_boolean_get(op->ptr, "mirror_weights"),
+ RNA_boolean_get(op->ptr, "flip_group_names"),
+ RNA_boolean_get(op->ptr, "all_groups"),
+ RNA_boolean_get(op->ptr, "use_topology"),
+ &totmirr,
+ &totfail);
- ED_mesh_report_mirror(op, totmirr, totfail);
+ ED_mesh_report_mirror(op, totmirr, totfail);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Mirror Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_mirror";
- ot->description = "Mirror vertex group, flip weights and/or names, editing only selected vertices, "
- "flipping when both sides are selected otherwise copy from unselected";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_mirror_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "mirror_weights", true, "Mirror Weights", "Mirror weights");
- RNA_def_boolean(ot->srna, "flip_group_names", true, "Flip Group Names", "Flip vertex group names");
- RNA_def_boolean(ot->srna, "all_groups", false, "All Groups", "Mirror all vertex groups weights");
- RNA_def_boolean(ot->srna, "use_topology", 0, "Topology Mirror",
- "Use topology based mirroring (for when both sides of mesh have matching, unique topology)");
+ /* identifiers */
+ ot->name = "Mirror Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_mirror";
+ ot->description =
+ "Mirror vertex group, flip weights and/or names, editing only selected vertices, "
+ "flipping when both sides are selected otherwise copy from unselected";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_mirror_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "mirror_weights", true, "Mirror Weights", "Mirror weights");
+ RNA_def_boolean(
+ ot->srna, "flip_group_names", true, "Flip Group Names", "Flip vertex group names");
+ RNA_def_boolean(ot->srna, "all_groups", false, "All Groups", "Mirror all vertex groups weights");
+ RNA_def_boolean(
+ ot->srna,
+ "use_topology",
+ 0,
+ "Topology Mirror",
+ "Use topology based mirroring (for when both sides of mesh have matching, unique topology)");
}
static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Object *ob_active = ED_object_context(C);
- int retval = OPERATOR_CANCELLED;
-
- FOREACH_SCENE_OBJECT_BEGIN(scene, ob_iter)
- {
- if (ob_iter->type == ob_active->type) {
- if (ob_iter != ob_active && ob_iter->data == ob_active->data) {
- BLI_freelistN(&ob_iter->defbase);
- BLI_duplicatelist(&ob_iter->defbase, &ob_active->defbase);
- ob_iter->actdef = ob_active->actdef;
-
- DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob_iter->data);
-
- retval = OPERATOR_FINISHED;
- }
- }
- }
- FOREACH_SCENE_OBJECT_END;
-
- return retval;
+ Scene *scene = CTX_data_scene(C);
+ Object *ob_active = ED_object_context(C);
+ int retval = OPERATOR_CANCELLED;
+
+ FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) {
+ if (ob_iter->type == ob_active->type) {
+ if (ob_iter != ob_active && ob_iter->data == ob_active->data) {
+ BLI_freelistN(&ob_iter->defbase);
+ BLI_duplicatelist(&ob_iter->defbase, &ob_active->defbase);
+ ob_iter->actdef = ob_active->actdef;
+
+ DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob_iter->data);
+
+ retval = OPERATOR_FINISHED;
+ }
+ }
+ }
+ FOREACH_SCENE_OBJECT_END;
+
+ return retval;
}
void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Vertex Groups to Linked";
- ot->idname = "OBJECT_OT_vertex_group_copy_to_linked";
- ot->description = "Replace vertex groups of all users of the same geometry data by vertex groups of active object";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_copy_to_linked_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Copy Vertex Groups to Linked";
+ ot->idname = "OBJECT_OT_vertex_group_copy_to_linked";
+ ot->description =
+ "Replace vertex groups of all users of the same geometry data by vertex groups of active "
+ "object";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_copy_to_linked_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op)
{
- Object *obact = ED_object_context(C);
- int changed_tot = 0;
- int fail = 0;
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (obact != ob) {
- if (ED_vgroup_array_copy(ob, obact)) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
- changed_tot++;
- }
- else {
- fail++;
- }
- }
- }
- CTX_DATA_END;
-
- if ((changed_tot == 0 && fail == 0) || fail) {
- BKE_reportf(op->reports, RPT_ERROR,
- "Copy vertex groups to selected: %d done, %d failed (object data must have matching indices)",
- changed_tot, fail);
- }
-
- return OPERATOR_FINISHED;
+ Object *obact = ED_object_context(C);
+ int changed_tot = 0;
+ int fail = 0;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (obact != ob) {
+ if (ED_vgroup_array_copy(ob, obact)) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
+ changed_tot++;
+ }
+ else {
+ fail++;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ if ((changed_tot == 0 && fail == 0) || fail) {
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "Copy vertex groups to selected: %d done, %d failed (object data must have "
+ "matching indices)",
+ changed_tot,
+ fail);
+ }
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Vertex Group to Selected";
- ot->idname = "OBJECT_OT_vertex_group_copy_to_selected";
- ot->description = "Replace vertex groups of selected objects by vertex groups of active object";
+ /* identifiers */
+ ot->name = "Copy Vertex Group to Selected";
+ ot->idname = "OBJECT_OT_vertex_group_copy_to_selected";
+ ot->description = "Replace vertex groups of selected objects by vertex groups of active object";
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_copy_to_selected_exec;
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_copy_to_selected_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int set_active_group_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- int nr = RNA_enum_get(op->ptr, "group");
+ Object *ob = ED_object_context(C);
+ int nr = RNA_enum_get(op->ptr, "group");
- BLI_assert(nr + 1 >= 0);
- ob->actdef = nr + 1;
+ BLI_assert(nr + 1 >= 0);
+ ob->actdef = nr + 1;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static const EnumPropertyItem *vgroup_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *vgroup_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- Object *ob = ED_object_context(C);
- EnumPropertyItem tmp = {0, "", 0, "", ""};
- EnumPropertyItem *item = NULL;
- bDeformGroup *def;
- int a, totitem = 0;
-
- if (!ob)
- return DummyRNA_NULL_items;
-
- for (a = 0, def = ob->defbase.first; def; def = def->next, a++) {
- tmp.value = a;
- tmp.icon = ICON_GROUP_VERTEX;
- tmp.identifier = def->name;
- tmp.name = def->name;
- RNA_enum_item_add(&item, &totitem, &tmp);
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ Object *ob = ED_object_context(C);
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ EnumPropertyItem *item = NULL;
+ bDeformGroup *def;
+ int a, totitem = 0;
+
+ if (!ob)
+ return DummyRNA_NULL_items;
+
+ for (a = 0, def = ob->defbase.first; def; def = def->next, a++) {
+ tmp.value = a;
+ tmp.icon = ICON_GROUP_VERTEX;
+ tmp.identifier = def->name;
+ tmp.name = def->name;
+ RNA_enum_item_add(&item, &totitem, &tmp);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Set Active Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_set_active";
- ot->description = "Set the active vertex group";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = set_active_group_exec;
- ot->invoke = WM_menu_invoke;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "Vertex group to set as active");
- RNA_def_enum_funcs(prop, vgroup_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Set Active Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_set_active";
+ ot->description = "Set the active vertex group";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = set_active_group_exec;
+ ot->invoke = WM_menu_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(
+ ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "Vertex group to set as active");
+ RNA_def_enum_funcs(prop, vgroup_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
/* creates the name_array parameter for vgroup_do_remap, call this before fiddling
* with the order of vgroups then call vgroup_do_remap after */
static char *vgroup_init_remap(Object *ob)
{
- bDeformGroup *def;
- int defbase_tot = BLI_listbase_count(&ob->defbase);
- char *name_array = MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * defbase_tot, "sort vgroups");
- char *name;
-
- name = name_array;
- for (def = ob->defbase.first; def; def = def->next) {
- BLI_strncpy(name, def->name, MAX_VGROUP_NAME);
- name += MAX_VGROUP_NAME;
- }
-
- return name_array;
+ bDeformGroup *def;
+ int defbase_tot = BLI_listbase_count(&ob->defbase);
+ char *name_array = MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * defbase_tot, "sort vgroups");
+ char *name;
+
+ name = name_array;
+ for (def = ob->defbase.first; def; def = def->next) {
+ BLI_strncpy(name, def->name, MAX_VGROUP_NAME);
+ name += MAX_VGROUP_NAME;
+ }
+
+ return name_array;
}
static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
{
- MDeformVert *dvert = NULL;
- bDeformGroup *def;
- int defbase_tot = BLI_listbase_count(&ob->defbase);
-
- /* needs a dummy index at the start*/
- int *sort_map_update = MEM_mallocN(sizeof(int) * (defbase_tot + 1), "sort vgroups");
- int *sort_map = sort_map_update + 1;
-
- const char *name;
- int i;
-
- name = name_array;
- for (def = ob->defbase.first, i = 0; def; def = def->next, i++) {
- sort_map[i] = BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name));
- name += MAX_VGROUP_NAME;
-
- BLI_assert(sort_map[i] != -1);
- }
-
- if (ob->mode == OB_MODE_EDIT) {
- if (ob->type == OB_MESH) {
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
-
- if (cd_dvert_offset != -1) {
- BMIter iter;
- BMVert *eve;
-
- 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);
- }
- }
- }
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Editmode lattice is not supported yet");
- MEM_freeN(sort_map_update);
- return OPERATOR_CANCELLED;
- }
- }
- else {
- int dvert_tot = 0;
-
- BKE_object_defgroup_array_get(ob->data, &dvert, &dvert_tot);
-
- /*create as necessary*/
- if (dvert) {
- while (dvert_tot--) {
- if (dvert->totweight)
- defvert_remap(dvert, sort_map, defbase_tot);
- dvert++;
- }
- }
- }
-
- /* update users */
- for (i = 0; i < defbase_tot; i++)
- sort_map[i]++;
-
- sort_map_update[0] = 0;
- BKE_object_defgroup_remap_update_users(ob, sort_map_update);
-
- BLI_assert(sort_map_update[ob->actdef] >= 0);
- ob->actdef = sort_map_update[ob->actdef];
-
- MEM_freeN(sort_map_update);
-
- return OPERATOR_FINISHED;
+ MDeformVert *dvert = NULL;
+ bDeformGroup *def;
+ int defbase_tot = BLI_listbase_count(&ob->defbase);
+
+ /* needs a dummy index at the start*/
+ int *sort_map_update = MEM_mallocN(sizeof(int) * (defbase_tot + 1), "sort vgroups");
+ int *sort_map = sort_map_update + 1;
+
+ const char *name;
+ int i;
+
+ name = name_array;
+ for (def = ob->defbase.first, i = 0; def; def = def->next, i++) {
+ sort_map[i] = BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name));
+ name += MAX_VGROUP_NAME;
+
+ BLI_assert(sort_map[i] != -1);
+ }
+
+ if (ob->mode == OB_MODE_EDIT) {
+ if (ob->type == OB_MESH) {
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+
+ if (cd_dvert_offset != -1) {
+ BMIter iter;
+ BMVert *eve;
+
+ 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);
+ }
+ }
+ }
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Editmode lattice is not supported yet");
+ MEM_freeN(sort_map_update);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ int dvert_tot = 0;
+
+ BKE_object_defgroup_array_get(ob->data, &dvert, &dvert_tot);
+
+ /*create as necessary*/
+ if (dvert) {
+ while (dvert_tot--) {
+ if (dvert->totweight)
+ defvert_remap(dvert, sort_map, defbase_tot);
+ dvert++;
+ }
+ }
+ }
+
+ /* update users */
+ for (i = 0; i < defbase_tot; i++)
+ sort_map[i]++;
+
+ sort_map_update[0] = 0;
+ BKE_object_defgroup_remap_update_users(ob, sort_map_update);
+
+ BLI_assert(sort_map_update[ob->actdef] >= 0);
+ ob->actdef = sort_map_update[ob->actdef];
+
+ MEM_freeN(sort_map_update);
+
+ return OPERATOR_FINISHED;
}
static int vgroup_sort_name(const void *def_a_ptr, const void *def_b_ptr)
{
- const bDeformGroup *def_a = def_a_ptr;
- const bDeformGroup *def_b = def_b_ptr;
+ const bDeformGroup *def_a = def_a_ptr;
+ const bDeformGroup *def_b = def_b_ptr;
- return BLI_natstrcmp(def_a->name, def_b->name);
+ return BLI_natstrcmp(def_a->name, def_b->name);
}
/**
@@ -3599,395 +3719,423 @@ 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);
- if (armobj != NULL) {
- bArmature *armature = armobj->data;
- bonebase = &armature->bonebase;
- }
- }
-
- if (bonebase != NULL) {
- Bone *bone;
- for (bone = bonebase->last; bone; bone = bone->prev) {
- bDeformGroup *dg = defgroup_find_name(ob, bone->name);
- vgroup_sort_bone_hierarchy(ob, &bone->childbase);
-
- if (dg != NULL) {
- BLI_remlink(&ob->defbase, dg);
- BLI_addhead(&ob->defbase, dg);
- }
- }
- }
-
- return;
+ if (bonebase == NULL) {
+ Object *armobj = modifiers_isDeformedByArmature(ob);
+ if (armobj != NULL) {
+ bArmature *armature = armobj->data;
+ bonebase = &armature->bonebase;
+ }
+ }
+
+ if (bonebase != NULL) {
+ Bone *bone;
+ for (bone = bonebase->last; bone; bone = bone->prev) {
+ bDeformGroup *dg = defgroup_find_name(ob, bone->name);
+ vgroup_sort_bone_hierarchy(ob, &bone->childbase);
+
+ if (dg != NULL) {
+ BLI_remlink(&ob->defbase, dg);
+ BLI_addhead(&ob->defbase, dg);
+ }
+ }
+ }
+
+ return;
}
enum {
- SORT_TYPE_NAME = 0,
- SORT_TYPE_BONEHIERARCHY = 1,
+ SORT_TYPE_NAME = 0,
+ SORT_TYPE_BONEHIERARCHY = 1,
};
static int vertex_group_sort_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- char *name_array;
- int ret;
- int sort_type = RNA_enum_get(op->ptr, "sort_type");
-
- /*init remapping*/
- name_array = vgroup_init_remap(ob);
-
- /*sort vgroup names*/
- switch (sort_type) {
- case SORT_TYPE_NAME:
- BLI_listbase_sort(&ob->defbase, vgroup_sort_name);
- break;
- case SORT_TYPE_BONEHIERARCHY:
- vgroup_sort_bone_hierarchy(ob, NULL);
- break;
- }
-
- /*remap vgroup data to map to correct names*/
- ret = vgroup_do_remap(ob, name_array, op);
-
- if (ret != OPERATOR_CANCELLED) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
- }
-
- if (name_array) MEM_freeN(name_array);
-
- return ret;
+ Object *ob = ED_object_context(C);
+ char *name_array;
+ int ret;
+ int sort_type = RNA_enum_get(op->ptr, "sort_type");
+
+ /*init remapping*/
+ name_array = vgroup_init_remap(ob);
+
+ /*sort vgroup names*/
+ switch (sort_type) {
+ case SORT_TYPE_NAME:
+ BLI_listbase_sort(&ob->defbase, vgroup_sort_name);
+ break;
+ case SORT_TYPE_BONEHIERARCHY:
+ vgroup_sort_bone_hierarchy(ob, NULL);
+ break;
+ }
+
+ /*remap vgroup data to map to correct names*/
+ ret = vgroup_do_remap(ob, name_array, op);
+
+ if (ret != OPERATOR_CANCELLED) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
+ }
+
+ if (name_array)
+ MEM_freeN(name_array);
+
+ return ret;
}
void OBJECT_OT_vertex_group_sort(wmOperatorType *ot)
{
- static const EnumPropertyItem vgroup_sort_type[] = {
- {SORT_TYPE_NAME, "NAME", 0, "Name", ""},
- {SORT_TYPE_BONEHIERARCHY, "BONE_HIERARCHY", 0, "Bone Hierarchy", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem vgroup_sort_type[] = {
+ {SORT_TYPE_NAME, "NAME", 0, "Name", ""},
+ {SORT_TYPE_BONEHIERARCHY, "BONE_HIERARCHY", 0, "Bone Hierarchy", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- ot->name = "Sort Vertex Groups";
- ot->idname = "OBJECT_OT_vertex_group_sort";
- ot->description = "Sort vertex groups";
+ ot->name = "Sort Vertex Groups";
+ ot->idname = "OBJECT_OT_vertex_group_sort";
+ ot->description = "Sort vertex groups";
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_sort_exec;
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_sort_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_enum(ot->srna, "sort_type", vgroup_sort_type, SORT_TYPE_NAME, "Sort type", "Sort type");
+ RNA_def_enum(ot->srna, "sort_type", vgroup_sort_type, SORT_TYPE_NAME, "Sort type", "Sort type");
}
static int vgroup_move_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- bDeformGroup *def;
- char *name_array;
- int dir = RNA_enum_get(op->ptr, "direction");
- int ret = OPERATOR_FINISHED;
+ Object *ob = ED_object_context(C);
+ bDeformGroup *def;
+ char *name_array;
+ int dir = RNA_enum_get(op->ptr, "direction");
+ int ret = OPERATOR_FINISHED;
- def = BLI_findlink(&ob->defbase, ob->actdef - 1);
- if (!def) {
- return OPERATOR_CANCELLED;
- }
+ def = BLI_findlink(&ob->defbase, ob->actdef - 1);
+ if (!def) {
+ return OPERATOR_CANCELLED;
+ }
- name_array = vgroup_init_remap(ob);
+ name_array = vgroup_init_remap(ob);
- if (BLI_listbase_link_move(&ob->defbase, def, dir)) {
- ret = vgroup_do_remap(ob, name_array, op);
+ if (BLI_listbase_link_move(&ob->defbase, def, dir)) {
+ ret = vgroup_do_remap(ob, name_array, op);
- if (ret != OPERATOR_CANCELLED) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
- }
- }
+ if (ret != OPERATOR_CANCELLED) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
+ }
+ }
- if (name_array) MEM_freeN(name_array);
+ if (name_array)
+ MEM_freeN(name_array);
- return ret;
+ return ret;
}
void OBJECT_OT_vertex_group_move(wmOperatorType *ot)
{
- static const EnumPropertyItem vgroup_slot_move[] = {
- {-1, "UP", 0, "Up", ""},
- {1, "DOWN", 0, "Down", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Move Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_move";
- ot->description = "Move the active vertex group up/down in the list";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vgroup_move_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "direction", vgroup_slot_move, 0, "Direction",
- "Direction to move the active vertex group towards");
+ static const EnumPropertyItem vgroup_slot_move[] = {
+ {-1, "UP", 0, "Up", ""},
+ {1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Move Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_move";
+ ot->description = "Move the active vertex group up/down in the list";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vgroup_move_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna,
+ "direction",
+ vgroup_slot_move,
+ 0,
+ "Direction",
+ "Direction to move the active vertex group towards");
}
static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr)
{
- MDeformVert *dvert_act;
-
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- float weight_act;
- int i;
-
- if (em) {
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
- BMIter iter;
- BMVert *eve, *eve_act;
-
- dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
- if (dvert_act == NULL) {
- return;
- }
- weight_act = 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);
- if (dw) {
- dw->weight = weight_act;
-
- if (me->editflag & ME_EDIT_MIRROR_X) {
- ED_mesh_defvert_mirror_update_em(ob, eve, -1, i, cd_dvert_offset);
- }
- }
- }
- }
-
- if (me->editflag & ME_EDIT_MIRROR_X) {
- ED_mesh_defvert_mirror_update_em(ob, eve_act, -1, -1, cd_dvert_offset);
- }
- }
- else {
- MDeformVert *dv;
- int v_act;
-
- dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
- if (dvert_act == NULL) {
- return;
- }
- weight_act = 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);
- if (dw) {
- dw->weight = weight_act;
- if (me->editflag & ME_EDIT_MIRROR_X) {
- ED_mesh_defvert_mirror_update_ob(ob, -1, i);
- }
- }
- }
- }
-
- if (me->editflag & ME_EDIT_MIRROR_X) {
- ED_mesh_defvert_mirror_update_ob(ob, -1, v_act);
- }
- }
+ MDeformVert *dvert_act;
+
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ float weight_act;
+ int i;
+
+ if (em) {
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+ BMIter iter;
+ BMVert *eve, *eve_act;
+
+ dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
+ if (dvert_act == NULL) {
+ return;
+ }
+ weight_act = 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);
+ if (dw) {
+ dw->weight = weight_act;
+
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ ED_mesh_defvert_mirror_update_em(ob, eve, -1, i, cd_dvert_offset);
+ }
+ }
+ }
+ }
+
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ ED_mesh_defvert_mirror_update_em(ob, eve_act, -1, -1, cd_dvert_offset);
+ }
+ }
+ else {
+ MDeformVert *dv;
+ int v_act;
+
+ dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
+ if (dvert_act == NULL) {
+ return;
+ }
+ weight_act = 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);
+ if (dw) {
+ dw->weight = weight_act;
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ ED_mesh_defvert_mirror_update_ob(ob, -1, i);
+ }
+ }
+ }
+ }
+
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ ED_mesh_defvert_mirror_update_ob(ob, -1, v_act);
+ }
+ }
}
static bool check_vertex_group_accessible(wmOperator *op, Object *ob, int def_nr)
{
- bDeformGroup *dg = BLI_findlink(&ob->defbase, def_nr);
+ bDeformGroup *dg = BLI_findlink(&ob->defbase, def_nr);
- if (!dg) {
- BKE_report(op->reports, RPT_ERROR, "Invalid vertex group index");
- return false;
- }
+ if (!dg) {
+ BKE_report(op->reports, RPT_ERROR, "Invalid vertex group index");
+ return false;
+ }
- if (dg->flag & DG_LOCK_WEIGHT) {
- BKE_report(op->reports, RPT_ERROR, "Vertex group is locked");
- return false;
- }
+ if (dg->flag & DG_LOCK_WEIGHT) {
+ BKE_report(op->reports, RPT_ERROR, "Vertex group is locked");
+ return false;
+ }
- return true;
+ return true;
}
static int vertex_weight_paste_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- const int def_nr = RNA_int_get(op->ptr, "weight_group");
+ Object *ob = ED_object_context(C);
+ const int def_nr = RNA_int_get(op->ptr, "weight_group");
- if (!check_vertex_group_accessible(op, ob, def_nr)) {
- return OPERATOR_CANCELLED;
- }
+ if (!check_vertex_group_accessible(op, ob, def_nr)) {
+ return OPERATOR_CANCELLED;
+ }
- vgroup_copy_active_to_sel_single(ob, def_nr);
+ vgroup_copy_active_to_sel_single(ob, def_nr);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_weight_paste(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- ot->name = "Paste Weight to Selected";
- ot->idname = "OBJECT_OT_vertex_weight_paste";
- ot->description = "Copy this group's weight to other selected verts (disabled if vertex group is locked)";
-
- /* api callbacks */
- ot->poll = vertex_group_vert_select_mesh_poll;
- ot->exec = vertex_weight_paste_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- prop = RNA_def_int(ot->srna, "weight_group", -1, -1, INT_MAX, "Weight Index",
- "Index of source weight in active vertex group", -1, INT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ PropertyRNA *prop;
+
+ ot->name = "Paste Weight to Selected";
+ ot->idname = "OBJECT_OT_vertex_weight_paste";
+ ot->description =
+ "Copy this group's weight to other selected verts (disabled if vertex group is locked)";
+
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_mesh_poll;
+ ot->exec = vertex_weight_paste_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_int(ot->srna,
+ "weight_group",
+ -1,
+ -1,
+ INT_MAX,
+ "Weight Index",
+ "Index of source weight in active vertex group",
+ -1,
+ INT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
static int vertex_weight_delete_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- const int def_nr = RNA_int_get(op->ptr, "weight_group");
+ Object *ob = ED_object_context(C);
+ const int def_nr = RNA_int_get(op->ptr, "weight_group");
- if (!check_vertex_group_accessible(op, ob, def_nr)) {
- return OPERATOR_CANCELLED;
- }
+ if (!check_vertex_group_accessible(op, ob, def_nr)) {
+ return OPERATOR_CANCELLED;
+ }
- vgroup_remove_weight(ob, def_nr);
+ vgroup_remove_weight(ob, def_nr);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_weight_delete(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- ot->name = "Delete Weight";
- ot->idname = "OBJECT_OT_vertex_weight_delete";
- ot->description = "Delete this weight from the vertex (disabled if vertex group is locked)";
-
- /* api callbacks */
- ot->poll = vertex_group_vert_select_mesh_poll;
- ot->exec = vertex_weight_delete_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- prop = RNA_def_int(ot->srna, "weight_group", -1, -1, INT_MAX, "Weight Index",
- "Index of source weight in active vertex group", -1, INT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ PropertyRNA *prop;
+
+ ot->name = "Delete Weight";
+ ot->idname = "OBJECT_OT_vertex_weight_delete";
+ ot->description = "Delete this weight from the vertex (disabled if vertex group is locked)";
+
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_mesh_poll;
+ ot->exec = vertex_weight_delete_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_int(ot->srna,
+ "weight_group",
+ -1,
+ -1,
+ INT_MAX,
+ "Weight Index",
+ "Index of source weight in active vertex group",
+ -1,
+ INT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
static int vertex_weight_set_active_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- const int wg_index = RNA_int_get(op->ptr, "weight_group");
+ Object *ob = ED_object_context(C);
+ const int wg_index = RNA_int_get(op->ptr, "weight_group");
- if (wg_index != -1) {
- ob->actdef = wg_index + 1;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- }
+ if (wg_index != -1) {
+ ob->actdef = wg_index + 1;
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_weight_set_active(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- ot->name = "Set Active Group";
- ot->idname = "OBJECT_OT_vertex_weight_set_active";
- ot->description = "Set as active vertex group";
-
- /* api callbacks */
- ot->poll = vertex_group_vert_select_mesh_poll;
- ot->exec = vertex_weight_set_active_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- prop = RNA_def_int(ot->srna, "weight_group", -1, -1, INT_MAX, "Weight Index",
- "Index of source weight in active vertex group", -1, INT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ PropertyRNA *prop;
+
+ ot->name = "Set Active Group";
+ ot->idname = "OBJECT_OT_vertex_weight_set_active";
+ ot->description = "Set as active vertex group";
+
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_mesh_poll;
+ ot->exec = vertex_weight_set_active_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_int(ot->srna,
+ "weight_group",
+ -1,
+ -1,
+ INT_MAX,
+ "Weight Index",
+ "Index of source weight in active vertex group",
+ -1,
+ INT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
static int vertex_weight_normalize_active_vertex_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- eVGroupSelect subset_type = ts->vgroupsubset;
- bool changed;
-
- changed = vgroup_normalize_active_vertex(ob, subset_type);
-
- if (changed) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Object *ob = ED_object_context(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ eVGroupSelect subset_type = ts->vgroupsubset;
+ bool changed;
+
+ changed = vgroup_normalize_active_vertex(ob, subset_type);
+
+ if (changed) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void OBJECT_OT_vertex_weight_normalize_active_vertex(wmOperatorType *ot)
{
- ot->name = "Normalize Active";
- ot->idname = "OBJECT_OT_vertex_weight_normalize_active_vertex";
- ot->description = "Normalize active vertex's weights";
+ ot->name = "Normalize Active";
+ ot->idname = "OBJECT_OT_vertex_weight_normalize_active_vertex";
+ ot->description = "Normalize active vertex's weights";
- /* api callbacks */
- ot->poll = vertex_group_vert_select_mesh_poll;
- ot->exec = vertex_weight_normalize_active_vertex_exec;
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_mesh_poll;
+ ot->exec = vertex_weight_normalize_active_vertex_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int vertex_weight_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- eVGroupSelect subset_type = ts->vgroupsubset;
+ Object *ob = ED_object_context(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ eVGroupSelect subset_type = ts->vgroupsubset;
- vgroup_copy_active_to_sel(ob, subset_type);
+ vgroup_copy_active_to_sel(ob, subset_type);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_weight_copy(wmOperatorType *ot)
{
- ot->name = "Copy Active";
- ot->idname = "OBJECT_OT_vertex_weight_copy";
- ot->description = "Copy weights from active to selected";
+ ot->name = "Copy Active";
+ ot->idname = "OBJECT_OT_vertex_weight_copy";
+ ot->description = "Copy weights from active to selected";
- /* api callbacks */
- ot->poll = vertex_group_vert_select_mesh_poll;
- ot->exec = vertex_weight_copy_exec;
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_mesh_poll;
+ ot->exec = vertex_weight_copy_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/object/object_warp.c b/source/blender/editors/object/object_warp.c
index 753e29ca9a7..3a089acb330 100644
--- a/source/blender/editors/object/object_warp.c
+++ b/source/blender/editors/object/object_warp.c
@@ -40,264 +40,275 @@
#include "object_intern.h"
-
-static void object_warp_calc_view_matrix(float r_mat_view[4][4], float r_center_view[3],
- Object *obedit, float viewmat[4][4], const float center[3],
+static void object_warp_calc_view_matrix(float r_mat_view[4][4],
+ float r_center_view[3],
+ Object *obedit,
+ float viewmat[4][4],
+ const float center[3],
const float offset_angle)
{
- float mat_offset[4][4];
- float viewmat_roll[4][4];
+ float mat_offset[4][4];
+ float viewmat_roll[4][4];
- /* apply the rotation offset by rolling the view */
- axis_angle_to_mat4_single(mat_offset, 'Z', offset_angle);
- mul_m4_m4m4(viewmat_roll, mat_offset, viewmat);
+ /* apply the rotation offset by rolling the view */
+ axis_angle_to_mat4_single(mat_offset, 'Z', offset_angle);
+ mul_m4_m4m4(viewmat_roll, mat_offset, viewmat);
- /* apply the view and the object matrix */
- mul_m4_m4m4(r_mat_view, viewmat_roll, obedit->obmat);
+ /* apply the view and the object matrix */
+ mul_m4_m4m4(r_mat_view, viewmat_roll, obedit->obmat);
- /* get the view-space cursor */
- mul_v3_m4v3(r_center_view, viewmat_roll, center);
+ /* get the view-space cursor */
+ mul_v3_m4v3(r_center_view, viewmat_roll, center);
}
-
static void object_warp_transverts_minmax_x(TransVertStore *tvs,
- float mat_view[4][4], const float center_view[3],
- float *r_min, float *r_max)
+ float mat_view[4][4],
+ const float center_view[3],
+ float *r_min,
+ float *r_max)
{
- /* no need to apply translation and cursor offset for every vertex, delay this */
- const float x_ofs = (mat_view[3][0] - center_view[0]);
- float min = FLT_MAX, max = -FLT_MAX;
-
- TransVert *tv;
- int i;
+ /* no need to apply translation and cursor offset for every vertex, delay this */
+ const float x_ofs = (mat_view[3][0] - center_view[0]);
+ float min = FLT_MAX, max = -FLT_MAX;
+ TransVert *tv;
+ int i;
- tv = tvs->transverts;
- for (i = 0; i < tvs->transverts_tot; i++, tv++) {
- float val;
+ tv = tvs->transverts;
+ for (i = 0; i < tvs->transverts_tot; i++, tv++) {
+ float val;
- /* convert objectspace->viewspace */
- val = dot_m4_v3_row_x(mat_view, tv->loc);
+ /* convert objectspace->viewspace */
+ val = dot_m4_v3_row_x(mat_view, tv->loc);
- min = min_ff(min, val);
- max = max_ff(max, val);
- }
+ min = min_ff(min, val);
+ max = max_ff(max, val);
+ }
- *r_min = min + x_ofs;
- *r_max = max + x_ofs;
+ *r_min = min + x_ofs;
+ *r_max = max + x_ofs;
}
-
static void object_warp_transverts(TransVertStore *tvs,
- float mat_view[4][4], const float center_view[3],
- const float angle_, const float min, const float max)
+ float mat_view[4][4],
+ const float center_view[3],
+ const float angle_,
+ const float min,
+ const float max)
{
- TransVert *tv;
- int i;
- const float angle = -angle_;
- /* cache vars for tiny speedup */
+ TransVert *tv;
+ int i;
+ const float angle = -angle_;
+ /* cache vars for tiny speedup */
#if 1
- const float range = max - min;
- const float range_inv = 1.0f / range;
- const float min_ofs = min + (0.5f * range);
+ const float range = max - min;
+ const float range_inv = 1.0f / range;
+ const float min_ofs = min + (0.5f * range);
#endif
- float dir_min[2], dir_max[2];
- float imat_view[4][4];
-
+ float dir_min[2], dir_max[2];
+ float imat_view[4][4];
- invert_m4_m4(imat_view, mat_view);
+ invert_m4_m4(imat_view, mat_view);
- /* calculate the direction vectors outside min/max range */
- {
- const float phi = angle * 0.5f;
+ /* calculate the direction vectors outside min/max range */
+ {
+ const float phi = angle * 0.5f;
- dir_max[0] = cosf(phi);
- dir_max[1] = sinf(phi);
+ dir_max[0] = cosf(phi);
+ dir_max[1] = sinf(phi);
- dir_min[0] = -dir_max[0];
- dir_min[1] = dir_max[1];
- }
+ dir_min[0] = -dir_max[0];
+ dir_min[1] = dir_max[1];
+ }
+ tv = tvs->transverts;
+ for (i = 0; i < tvs->transverts_tot; i++, tv++) {
+ float co[3], co_add[2];
+ float val, phi;
- tv = tvs->transverts;
- for (i = 0; i < tvs->transverts_tot; i++, tv++) {
- float co[3], co_add[2];
- float val, phi;
+ /* convert objectspace->viewspace */
+ mul_v3_m4v3(co, mat_view, tv->loc);
+ sub_v2_v2(co, center_view);
- /* convert objectspace->viewspace */
- mul_v3_m4v3(co, mat_view, tv->loc);
- sub_v2_v2(co, center_view);
+ val = co[0];
+ /* is overwritten later anyway */
+ // co[0] = 0.0f;
- val = co[0];
- /* is overwritten later anyway */
- // co[0] = 0.0f;
+ if (val < min) {
+ mul_v2_v2fl(co_add, dir_min, min - val);
+ val = min;
+ }
+ else if (val > max) {
+ mul_v2_v2fl(co_add, dir_max, val - max);
+ val = max;
+ }
+ else {
+ zero_v2(co_add);
+ }
- if (val < min) {
- mul_v2_v2fl(co_add, dir_min, min - val);
- val = min;
- }
- else if (val > max) {
- mul_v2_v2fl(co_add, dir_max, val - max);
- val = max;
- }
- else {
- zero_v2(co_add);
- }
-
- /* map from x axis to (-0.5 - 0.5) */
+ /* map from x axis to (-0.5 - 0.5) */
#if 0
- val = ((val - min) / (max - min)) - 0.5f;
+ val = ((val - min) / (max - min)) - 0.5f;
#else
- val = (val - min_ofs) * range_inv;
+ val = (val - min_ofs) * range_inv;
#endif
- /* convert the x axis into a rotation */
- phi = val * angle;
+ /* convert the x axis into a rotation */
+ phi = val * angle;
- co[0] = -sinf(phi) * co[1];
- co[1] = cosf(phi) * co[1];
+ co[0] = -sinf(phi) * co[1];
+ co[1] = cosf(phi) * co[1];
- add_v2_v2(co, co_add);
+ add_v2_v2(co, co_add);
- /* convert viewspace->objectspace */
- add_v2_v2(co, center_view);
- mul_v3_m4v3(tv->loc, imat_view, co);
- }
+ /* convert viewspace->objectspace */
+ add_v2_v2(co, center_view);
+ mul_v3_m4v3(tv->loc, imat_view, co);
+ }
}
static int object_warp_verts_exec(bContext *C, wmOperator *op)
{
- const float warp_angle = RNA_float_get(op->ptr, "warp_angle");
- const float offset_angle = RNA_float_get(op->ptr, "offset_angle");
-
- TransVertStore tvs = {NULL};
- Object *obedit = CTX_data_edit_object(C);
-
- /* typically from 'rv3d' and 3d cursor */
- float viewmat[4][4];
- float center[3];
-
- /* 'viewmat' relative vars */
- float mat_view[4][4];
- float center_view[3];
-
- float min, max;
-
-
- ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES);
- if (tvs.transverts == NULL) {
- return OPERATOR_CANCELLED;
- }
-
-
- /* get viewmatrix */
- {
- PropertyRNA *prop_viewmat = RNA_struct_find_property(op->ptr, "viewmat");
- if (RNA_property_is_set(op->ptr, prop_viewmat)) {
- RNA_property_float_get_array(op->ptr, prop_viewmat, (float *)viewmat);
- }
- else {
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
-
- if (rv3d) {
- copy_m4_m4(viewmat, rv3d->viewmat);
- }
- else {
- unit_m4(viewmat);
- }
-
- RNA_property_float_set_array(op->ptr, prop_viewmat, (float *)viewmat);
- }
- }
-
-
- /* get center */
- {
- PropertyRNA *prop_center = RNA_struct_find_property(op->ptr, "center");
- if (RNA_property_is_set(op->ptr, prop_center)) {
- RNA_property_float_get_array(op->ptr, prop_center, center);
- }
- else {
- const Scene *scene = CTX_data_scene(C);
- copy_v3_v3(center, scene->cursor.location);
-
- RNA_property_float_set_array(op->ptr, prop_center, center);
- }
- }
-
-
- object_warp_calc_view_matrix(mat_view, center_view, obedit, viewmat, center, offset_angle);
-
-
- /* get minmax */
- {
- PropertyRNA *prop_min = RNA_struct_find_property(op->ptr, "min");
- PropertyRNA *prop_max = RNA_struct_find_property(op->ptr, "max");
-
- if (RNA_property_is_set(op->ptr, prop_min) ||
- RNA_property_is_set(op->ptr, prop_max))
- {
- min = RNA_property_float_get(op->ptr, prop_min);
- max = RNA_property_float_get(op->ptr, prop_max);
- }
- else {
- /* handy to set the bounds of the mesh */
- object_warp_transverts_minmax_x(&tvs, mat_view, center_view, &min, &max);
-
- RNA_property_float_set(op->ptr, prop_min, min);
- RNA_property_float_set(op->ptr, prop_max, max);
- }
-
- if (min > max) {
- SWAP(float, min, max);
- }
- }
-
- if (min != max) {
- object_warp_transverts(&tvs, mat_view, center_view, warp_angle, min, max);
- }
-
- ED_transverts_update_obedit(&tvs, obedit);
- ED_transverts_free(&tvs);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
-
- return OPERATOR_FINISHED;
+ const float warp_angle = RNA_float_get(op->ptr, "warp_angle");
+ const float offset_angle = RNA_float_get(op->ptr, "offset_angle");
+
+ TransVertStore tvs = {NULL};
+ Object *obedit = CTX_data_edit_object(C);
+
+ /* typically from 'rv3d' and 3d cursor */
+ float viewmat[4][4];
+ float center[3];
+
+ /* 'viewmat' relative vars */
+ float mat_view[4][4];
+ float center_view[3];
+
+ float min, max;
+
+ ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES);
+ if (tvs.transverts == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get viewmatrix */
+ {
+ PropertyRNA *prop_viewmat = RNA_struct_find_property(op->ptr, "viewmat");
+ if (RNA_property_is_set(op->ptr, prop_viewmat)) {
+ RNA_property_float_get_array(op->ptr, prop_viewmat, (float *)viewmat);
+ }
+ else {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+
+ if (rv3d) {
+ copy_m4_m4(viewmat, rv3d->viewmat);
+ }
+ else {
+ unit_m4(viewmat);
+ }
+
+ RNA_property_float_set_array(op->ptr, prop_viewmat, (float *)viewmat);
+ }
+ }
+
+ /* get center */
+ {
+ PropertyRNA *prop_center = RNA_struct_find_property(op->ptr, "center");
+ if (RNA_property_is_set(op->ptr, prop_center)) {
+ RNA_property_float_get_array(op->ptr, prop_center, center);
+ }
+ else {
+ const Scene *scene = CTX_data_scene(C);
+ copy_v3_v3(center, scene->cursor.location);
+
+ RNA_property_float_set_array(op->ptr, prop_center, center);
+ }
+ }
+
+ object_warp_calc_view_matrix(mat_view, center_view, obedit, viewmat, center, offset_angle);
+
+ /* get minmax */
+ {
+ PropertyRNA *prop_min = RNA_struct_find_property(op->ptr, "min");
+ PropertyRNA *prop_max = RNA_struct_find_property(op->ptr, "max");
+
+ if (RNA_property_is_set(op->ptr, prop_min) || RNA_property_is_set(op->ptr, prop_max)) {
+ min = RNA_property_float_get(op->ptr, prop_min);
+ max = RNA_property_float_get(op->ptr, prop_max);
+ }
+ else {
+ /* handy to set the bounds of the mesh */
+ object_warp_transverts_minmax_x(&tvs, mat_view, center_view, &min, &max);
+
+ RNA_property_float_set(op->ptr, prop_min, min);
+ RNA_property_float_set(op->ptr, prop_max, max);
+ }
+
+ if (min > max) {
+ SWAP(float, min, max);
+ }
+ }
+
+ if (min != max) {
+ object_warp_transverts(&tvs, mat_view, center_view, warp_angle, min, max);
+ }
+
+ ED_transverts_update_obedit(&tvs, obedit);
+ ED_transverts_free(&tvs);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
+
+ return OPERATOR_FINISHED;
}
void TRANSFORM_OT_vertex_warp(struct wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Warp";
- ot->description = "Warp vertices around the cursor";
- ot->idname = "TRANSFORM_OT_vertex_warp";
-
- /* api callbacks */
- ot->exec = object_warp_verts_exec;
- ot->poll = ED_transverts_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- prop = RNA_def_float(ot->srna, "warp_angle", DEG2RADF(360.0f), -FLT_MAX, FLT_MAX, "Warp Angle",
- "Amount to warp about the cursor", DEG2RADF(-360.0f), DEG2RADF(360.0f));
- RNA_def_property_subtype(prop, PROP_ANGLE);
-
- prop = RNA_def_float(ot->srna, "offset_angle", DEG2RADF(0.0f), -FLT_MAX, FLT_MAX, "Offset Angle",
- "Angle to use as the basis for warping", DEG2RADF(-360.0f), DEG2RADF(360.0f));
- RNA_def_property_subtype(prop, PROP_ANGLE);
-
- prop = RNA_def_float(ot->srna, "min", -1.0f, -FLT_MAX, FLT_MAX, "Min", "", -100.0, 100.0);
- prop = RNA_def_float(ot->srna, "max", 1.0f, -FLT_MAX, FLT_MAX, "Max", "", -100.0, 100.0);
-
- /* hidden props */
- prop = RNA_def_float_matrix(ot->srna, "viewmat", 4, 4, NULL, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
-
- prop = RNA_def_float_vector_xyz(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Warp";
+ ot->description = "Warp vertices around the cursor";
+ ot->idname = "TRANSFORM_OT_vertex_warp";
+
+ /* api callbacks */
+ ot->exec = object_warp_verts_exec;
+ ot->poll = ED_transverts_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ prop = RNA_def_float(ot->srna,
+ "warp_angle",
+ DEG2RADF(360.0f),
+ -FLT_MAX,
+ FLT_MAX,
+ "Warp Angle",
+ "Amount to warp about the cursor",
+ DEG2RADF(-360.0f),
+ DEG2RADF(360.0f));
+ RNA_def_property_subtype(prop, PROP_ANGLE);
+
+ prop = RNA_def_float(ot->srna,
+ "offset_angle",
+ DEG2RADF(0.0f),
+ -FLT_MAX,
+ FLT_MAX,
+ "Offset Angle",
+ "Angle to use as the basis for warping",
+ DEG2RADF(-360.0f),
+ DEG2RADF(360.0f));
+ RNA_def_property_subtype(prop, PROP_ANGLE);
+
+ prop = RNA_def_float(ot->srna, "min", -1.0f, -FLT_MAX, FLT_MAX, "Min", "", -100.0, 100.0);
+ prop = RNA_def_float(ot->srna, "max", 1.0f, -FLT_MAX, FLT_MAX, "Max", "", -100.0, 100.0);
+
+ /* hidden props */
+ prop = RNA_def_float_matrix(
+ ot->srna, "viewmat", 4, 4, NULL, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_float_vector_xyz(
+ ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/physics/CMakeLists.txt b/source/blender/editors/physics/CMakeLists.txt
index 39a34ed7a47..3eb443320c3 100644
--- a/source/blender/editors/physics/CMakeLists.txt
+++ b/source/blender/editors/physics/CMakeLists.txt
@@ -16,70 +16,70 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../depsgraph
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../depsgraph
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- dynamicpaint_ops.c
- particle_boids.c
- particle_edit.c
- particle_edit_undo.c
- particle_object.c
- physics_fluid.c
- physics_ops.c
- physics_pointcache.c
- rigidbody_constraint.c
- rigidbody_object.c
- rigidbody_world.c
+ dynamicpaint_ops.c
+ particle_boids.c
+ particle_edit.c
+ particle_edit_undo.c
+ particle_object.c
+ physics_fluid.c
+ physics_ops.c
+ physics_pointcache.c
+ rigidbody_constraint.c
+ rigidbody_object.c
+ rigidbody_world.c
- particle_edit_utildefines.h
- physics_intern.h
+ particle_edit_utildefines.h
+ physics_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
+ bf_blenkernel
+ bf_blenlib
)
if(WITH_MOD_FLUID)
- list(APPEND INC
- ../../../../intern/elbeem/extern
- )
- list(APPEND LIB
- bf_intern_elbeem
- )
- add_definitions(-DWITH_MOD_FLUID)
+ list(APPEND INC
+ ../../../../intern/elbeem/extern
+ )
+ list(APPEND LIB
+ bf_intern_elbeem
+ )
+ add_definitions(-DWITH_MOD_FLUID)
endif()
if(WITH_MOD_SMOKE)
- list(APPEND LIB
- bf_intern_smoke
- )
+ list(APPEND LIB
+ bf_intern_smoke
+ )
endif()
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
if(WITH_BULLET)
- list(APPEND INC
- ../../../../intern/rigidbody
- )
- add_definitions(-DWITH_BULLET)
+ list(APPEND INC
+ ../../../../intern/rigidbody
+ )
+ add_definitions(-DWITH_BULLET)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c
index a88d2089ea1..e0ea53b06ec 100644
--- a/source/blender/editors/physics/dynamicpaint_ops.c
+++ b/source/blender/editors/physics/dynamicpaint_ops.c
@@ -65,269 +65,280 @@
static int surface_slot_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- DynamicPaintModifierData *pmd = NULL;
- Object *cObject = ED_object_context(C);
- DynamicPaintCanvasSettings *canvas;
- DynamicPaintSurface *surface;
-
- /* Make sure we're dealing with a canvas */
- pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint);
- if (!pmd || !pmd->canvas)
- return OPERATOR_CANCELLED;
-
- canvas = pmd->canvas;
- surface = dynamicPaint_createNewSurface(canvas, CTX_data_scene(C));
-
- if (!surface)
- return OPERATOR_CANCELLED;
-
- /* set preview for this surface only and set active */
- canvas->active_sur = 0;
- for (surface = surface->prev; surface; surface = surface->prev) {
- surface->flags &= ~MOD_DPAINT_PREVIEW;
- canvas->active_sur++;
- }
-
- return OPERATOR_FINISHED;
+ DynamicPaintModifierData *pmd = NULL;
+ Object *cObject = ED_object_context(C);
+ DynamicPaintCanvasSettings *canvas;
+ DynamicPaintSurface *surface;
+
+ /* Make sure we're dealing with a canvas */
+ pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint);
+ if (!pmd || !pmd->canvas)
+ return OPERATOR_CANCELLED;
+
+ canvas = pmd->canvas;
+ surface = dynamicPaint_createNewSurface(canvas, CTX_data_scene(C));
+
+ if (!surface)
+ return OPERATOR_CANCELLED;
+
+ /* set preview for this surface only and set active */
+ canvas->active_sur = 0;
+ for (surface = surface->prev; surface; surface = surface->prev) {
+ surface->flags &= ~MOD_DPAINT_PREVIEW;
+ canvas->active_sur++;
+ }
+
+ return OPERATOR_FINISHED;
}
/* add surface slot */
void DPAINT_OT_surface_slot_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Surface Slot";
- ot->idname = "DPAINT_OT_surface_slot_add";
- ot->description = "Add a new Dynamic Paint surface slot";
+ /* identifiers */
+ ot->name = "Add Surface Slot";
+ ot->idname = "DPAINT_OT_surface_slot_add";
+ ot->description = "Add a new Dynamic Paint surface slot";
- /* api callbacks */
- ot->exec = surface_slot_add_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->exec = surface_slot_add_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int surface_slot_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- DynamicPaintModifierData *pmd = NULL;
- Object *obj_ctx = ED_object_context(C);
- DynamicPaintCanvasSettings *canvas;
- DynamicPaintSurface *surface;
- int id = 0;
-
- /* Make sure we're dealing with a canvas */
- pmd = (DynamicPaintModifierData *)modifiers_findByType(obj_ctx, eModifierType_DynamicPaint);
- if (!pmd || !pmd->canvas) return OPERATOR_CANCELLED;
-
- canvas = pmd->canvas;
- surface = canvas->surfaces.first;
-
- /* find active surface and remove it */
- for (; surface; surface = surface->next) {
- if (id == canvas->active_sur) {
- canvas->active_sur -= 1;
- dynamicPaint_freeSurface(pmd, surface);
- break;
- }
- id++;
- }
-
- dynamicPaint_resetPreview(canvas);
- DEG_id_tag_update(&obj_ctx->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obj_ctx);
-
- return OPERATOR_FINISHED;
+ DynamicPaintModifierData *pmd = NULL;
+ Object *obj_ctx = ED_object_context(C);
+ DynamicPaintCanvasSettings *canvas;
+ DynamicPaintSurface *surface;
+ int id = 0;
+
+ /* Make sure we're dealing with a canvas */
+ pmd = (DynamicPaintModifierData *)modifiers_findByType(obj_ctx, eModifierType_DynamicPaint);
+ if (!pmd || !pmd->canvas)
+ return OPERATOR_CANCELLED;
+
+ canvas = pmd->canvas;
+ surface = canvas->surfaces.first;
+
+ /* find active surface and remove it */
+ for (; surface; surface = surface->next) {
+ if (id == canvas->active_sur) {
+ canvas->active_sur -= 1;
+ dynamicPaint_freeSurface(pmd, surface);
+ break;
+ }
+ id++;
+ }
+
+ dynamicPaint_resetPreview(canvas);
+ DEG_id_tag_update(&obj_ctx->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obj_ctx);
+
+ return OPERATOR_FINISHED;
}
/* remove surface slot */
void DPAINT_OT_surface_slot_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Surface Slot";
- ot->idname = "DPAINT_OT_surface_slot_remove";
- ot->description = "Remove the selected surface slot";
+ /* identifiers */
+ ot->name = "Remove Surface Slot";
+ ot->idname = "DPAINT_OT_surface_slot_remove";
+ ot->description = "Remove the selected surface slot";
- /* api callbacks */
- ot->exec = surface_slot_remove_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->exec = surface_slot_remove_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
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(cObject, eModifierType_DynamicPaint);
- int type = RNA_enum_get(op->ptr, "type");
-
- if (!pmd) return OPERATOR_CANCELLED;
-
- /* if type is already enabled, toggle it off */
- if (type == MOD_DYNAMICPAINT_TYPE_CANVAS && pmd->canvas) {
- dynamicPaint_freeCanvas(pmd);
- }
- else if (type == MOD_DYNAMICPAINT_TYPE_BRUSH && pmd->brush) {
- dynamicPaint_freeBrush(pmd);
- }
- /* else create a new type */
- else {
- if (!dynamicPaint_createType(pmd, type, scene))
- return OPERATOR_CANCELLED;
- }
-
- /* update dependency */
- DEG_id_tag_update(&cObject->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(CTX_data_main(C));
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, cObject);
-
- return OPERATOR_FINISHED;
+ Object *cObject = ED_object_context(C);
+ Scene *scene = CTX_data_scene(C);
+ DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(
+ cObject, eModifierType_DynamicPaint);
+ int type = RNA_enum_get(op->ptr, "type");
+
+ if (!pmd)
+ return OPERATOR_CANCELLED;
+
+ /* if type is already enabled, toggle it off */
+ if (type == MOD_DYNAMICPAINT_TYPE_CANVAS && pmd->canvas) {
+ dynamicPaint_freeCanvas(pmd);
+ }
+ else if (type == MOD_DYNAMICPAINT_TYPE_BRUSH && pmd->brush) {
+ dynamicPaint_freeBrush(pmd);
+ }
+ /* else create a new type */
+ else {
+ if (!dynamicPaint_createType(pmd, type, scene))
+ return OPERATOR_CANCELLED;
+ }
+
+ /* update dependency */
+ DEG_id_tag_update(&cObject->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(CTX_data_main(C));
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, cObject);
+
+ return OPERATOR_FINISHED;
}
void DPAINT_OT_type_toggle(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Toggle Type Active";
- ot->idname = "DPAINT_OT_type_toggle";
- ot->description = "Toggle whether given type is active or not";
-
- /* api callbacks */
- ot->exec = type_toggle_exec;
- ot->poll = ED_operator_object_active_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "type", rna_enum_prop_dynamicpaint_type_items, MOD_DYNAMICPAINT_TYPE_CANVAS, "Type", "");
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Toggle Type Active";
+ ot->idname = "DPAINT_OT_type_toggle";
+ ot->description = "Toggle whether given type is active or not";
+
+ /* api callbacks */
+ ot->exec = type_toggle_exec;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna,
+ "type",
+ rna_enum_prop_dynamicpaint_type_items,
+ MOD_DYNAMICPAINT_TYPE_CANVAS,
+ "Type",
+ "");
+ ot->prop = prop;
}
static int output_toggle_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- DynamicPaintSurface *surface;
- DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
- int output = RNA_enum_get(op->ptr, "output"); /* currently only 1/0 */
-
- if (!pmd || !pmd->canvas) return OPERATOR_CANCELLED;
- surface = get_activeSurface(pmd->canvas);
-
- /* if type is already enabled, toggle it off */
- if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
- int exists = dynamicPaint_outputLayerExists(surface, ob, output);
- const char *name;
-
- if (output == 0)
- name = surface->output_name;
- else
- name = surface->output_name2;
-
- /* Vertex Color Layer */
- if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
- if (!exists)
- ED_mesh_color_add(ob->data, name, true, true);
- else
- ED_mesh_color_remove_named(ob->data, name);
- }
- /* Vertex Weight Layer */
- else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
- if (!exists) {
- BKE_object_defgroup_add_name(ob, name);
- }
- else {
- bDeformGroup *defgroup = defgroup_find_name(ob, name);
- if (defgroup) BKE_object_defgroup_remove(ob, defgroup);
- }
- }
- }
-
- return OPERATOR_FINISHED;
+ Object *ob = ED_object_context(C);
+ DynamicPaintSurface *surface;
+ DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(
+ ob, eModifierType_DynamicPaint);
+ int output = RNA_enum_get(op->ptr, "output"); /* currently only 1/0 */
+
+ if (!pmd || !pmd->canvas)
+ return OPERATOR_CANCELLED;
+ surface = get_activeSurface(pmd->canvas);
+
+ /* if type is already enabled, toggle it off */
+ if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
+ int exists = dynamicPaint_outputLayerExists(surface, ob, output);
+ const char *name;
+
+ if (output == 0)
+ name = surface->output_name;
+ else
+ name = surface->output_name2;
+
+ /* Vertex Color Layer */
+ if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
+ if (!exists)
+ ED_mesh_color_add(ob->data, name, true, true);
+ else
+ ED_mesh_color_remove_named(ob->data, name);
+ }
+ /* Vertex Weight Layer */
+ else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
+ if (!exists) {
+ BKE_object_defgroup_add_name(ob, name);
+ }
+ else {
+ bDeformGroup *defgroup = defgroup_find_name(ob, name);
+ if (defgroup)
+ BKE_object_defgroup_remove(ob, defgroup);
+ }
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void DPAINT_OT_output_toggle(wmOperatorType *ot)
{
- static const EnumPropertyItem prop_output_toggle_types[] = {
- {0, "A", 0, "Output A", ""},
- {1, "B", 0, "Output B", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Toggle Output Layer";
- ot->idname = "DPAINT_OT_output_toggle";
- ot->description = "Add or remove Dynamic Paint output data layer";
-
- /* api callbacks */
- ot->exec = output_toggle_exec;
- ot->poll = ED_operator_object_active_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "output", prop_output_toggle_types, 0, "Output Toggle", "");
+ static const EnumPropertyItem prop_output_toggle_types[] = {
+ {0, "A", 0, "Output A", ""},
+ {1, "B", 0, "Output B", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Toggle Output Layer";
+ ot->idname = "DPAINT_OT_output_toggle";
+ ot->description = "Add or remove Dynamic Paint output data layer";
+
+ /* api callbacks */
+ ot->exec = output_toggle_exec;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "output", prop_output_toggle_types, 0, "Output Toggle", "");
}
-
/***************************** Image Sequence Baking ******************************/
typedef struct DynamicPaintBakeJob {
- /* from wmJob */
- void *owner;
- short *stop, *do_update;
- float *progress;
+ /* from wmJob */
+ void *owner;
+ short *stop, *do_update;
+ float *progress;
- struct Main *bmain;
- Scene *scene;
- Depsgraph *depsgraph;
- Object *ob;
+ struct Main *bmain;
+ Scene *scene;
+ Depsgraph *depsgraph;
+ Object *ob;
- DynamicPaintSurface *surface;
- DynamicPaintCanvasSettings *canvas;
+ DynamicPaintSurface *surface;
+ DynamicPaintCanvasSettings *canvas;
- int success;
- double start;
+ int success;
+ double start;
} DynamicPaintBakeJob;
static void dpaint_bake_free(void *customdata)
{
- DynamicPaintBakeJob *job = customdata;
- MEM_freeN(job);
+ DynamicPaintBakeJob *job = customdata;
+ MEM_freeN(job);
}
static void dpaint_bake_endjob(void *customdata)
{
- DynamicPaintBakeJob *job = customdata;
- DynamicPaintCanvasSettings *canvas = job->canvas;
-
- canvas->flags &= ~MOD_DPAINT_BAKING;
-
- dynamicPaint_freeSurfaceData(job->surface);
-
- G.is_rendering = false;
- BKE_spacedata_draw_locks(false);
-
- WM_set_locked_interface(G_MAIN->wm.first, false);
-
- /* Bake was successful:
- * Report for ended bake and how long it took */
- if (job->success) {
- /* Show bake info */
- WM_reportf(RPT_INFO, "DynamicPaint: Bake complete! (%.2f)", PIL_check_seconds_timer() - job->start);
- }
- else {
- if (strlen(canvas->error)) { /* If an error occurred */
- WM_reportf(RPT_ERROR, "DynamicPaint: Bake failed: %s", canvas->error);
- }
- else { /* User canceled the bake */
- WM_report(RPT_WARNING, "Baking canceled!");
- }
- }
+ DynamicPaintBakeJob *job = customdata;
+ DynamicPaintCanvasSettings *canvas = job->canvas;
+
+ canvas->flags &= ~MOD_DPAINT_BAKING;
+
+ dynamicPaint_freeSurfaceData(job->surface);
+
+ G.is_rendering = false;
+ BKE_spacedata_draw_locks(false);
+
+ WM_set_locked_interface(G_MAIN->wm.first, false);
+
+ /* Bake was successful:
+ * Report for ended bake and how long it took */
+ if (job->success) {
+ /* Show bake info */
+ WM_reportf(
+ RPT_INFO, "DynamicPaint: Bake complete! (%.2f)", PIL_check_seconds_timer() - job->start);
+ }
+ else {
+ if (strlen(canvas->error)) { /* If an error occurred */
+ WM_reportf(RPT_ERROR, "DynamicPaint: Bake failed: %s", canvas->error);
+ }
+ else { /* User canceled the bake */
+ WM_report(RPT_WARNING, "Baking canceled!");
+ }
+ }
}
/*
@@ -336,110 +347,112 @@ static void dpaint_bake_endjob(void *customdata)
*/
static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job)
{
- DynamicPaintSurface *surface = job->surface;
- Object *cObject = job->ob;
- DynamicPaintCanvasSettings *canvas = surface->canvas;
- Scene *scene = job->scene;
- int frame = 1, orig_frame;
- int frames;
-
- frames = surface->end_frame - surface->start_frame + 1;
- if (frames <= 0) {
- BLI_strncpy(canvas->error, N_("No frames to bake"), sizeof(canvas->error));
- return;
- }
-
- /* Show progress bar. */
- *(job->do_update) = true;
-
- /* Set frame to start point (also inits modifier data) */
- frame = surface->start_frame;
- orig_frame = scene->r.cfra;
- scene->r.cfra = (int)frame;
- ED_update_for_newframe(job->bmain, job->depsgraph);
-
- /* Init surface */
- if (!dynamicPaint_createUVSurface(scene, surface, job->progress, job->do_update)) {
- job->success = 0;
- return;
- }
-
- /* Loop through selected frames */
- for (frame = surface->start_frame; frame <= surface->end_frame; frame++) {
- /* The first 10% are for createUVSurface... */
- const float progress = 0.1f + 0.9f * (frame - surface->start_frame) / (float)frames;
- surface->current_frame = frame;
-
- /* If user requested stop, quit baking */
- if (G.is_break) {
- job->success = 0;
- return;
- }
-
- /* Update progress bar */
- *(job->do_update) = true;
- *(job->progress) = progress;
-
- /* calculate a frame */
- scene->r.cfra = (int)frame;
- ED_update_for_newframe(job->bmain, job->depsgraph);
- if (!dynamicPaint_calculateFrame(surface, job->depsgraph, scene, cObject, frame)) {
- job->success = 0;
- return;
- }
-
- /*
- * Save output images
- */
- {
- char filename[FILE_MAX];
-
- /* primary output layer */
- if (surface->flags & MOD_DPAINT_OUT1) {
- /* set filepath */
- BLI_join_dirfile(filename, sizeof(filename), surface->image_output_path, surface->output_name);
- BLI_path_frame(filename, frame, 4);
-
- /* save image */
- dynamicPaint_outputSurfaceImage(surface, filename, 0);
- }
- /* secondary output */
- if (surface->flags & MOD_DPAINT_OUT2 && surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
- /* set filepath */
- BLI_join_dirfile(filename, sizeof(filename), surface->image_output_path, surface->output_name2);
- BLI_path_frame(filename, frame, 4);
-
- /* save image */
- dynamicPaint_outputSurfaceImage(surface, filename, 1);
- }
- }
- }
-
- scene->r.cfra = orig_frame;
+ DynamicPaintSurface *surface = job->surface;
+ Object *cObject = job->ob;
+ DynamicPaintCanvasSettings *canvas = surface->canvas;
+ Scene *scene = job->scene;
+ int frame = 1, orig_frame;
+ int frames;
+
+ frames = surface->end_frame - surface->start_frame + 1;
+ if (frames <= 0) {
+ BLI_strncpy(canvas->error, N_("No frames to bake"), sizeof(canvas->error));
+ return;
+ }
+
+ /* Show progress bar. */
+ *(job->do_update) = true;
+
+ /* Set frame to start point (also inits modifier data) */
+ frame = surface->start_frame;
+ orig_frame = scene->r.cfra;
+ scene->r.cfra = (int)frame;
+ ED_update_for_newframe(job->bmain, job->depsgraph);
+
+ /* Init surface */
+ if (!dynamicPaint_createUVSurface(scene, surface, job->progress, job->do_update)) {
+ job->success = 0;
+ return;
+ }
+
+ /* Loop through selected frames */
+ for (frame = surface->start_frame; frame <= surface->end_frame; frame++) {
+ /* The first 10% are for createUVSurface... */
+ const float progress = 0.1f + 0.9f * (frame - surface->start_frame) / (float)frames;
+ surface->current_frame = frame;
+
+ /* If user requested stop, quit baking */
+ if (G.is_break) {
+ job->success = 0;
+ return;
+ }
+
+ /* Update progress bar */
+ *(job->do_update) = true;
+ *(job->progress) = progress;
+
+ /* calculate a frame */
+ scene->r.cfra = (int)frame;
+ ED_update_for_newframe(job->bmain, job->depsgraph);
+ if (!dynamicPaint_calculateFrame(surface, job->depsgraph, scene, cObject, frame)) {
+ job->success = 0;
+ return;
+ }
+
+ /*
+ * Save output images
+ */
+ {
+ char filename[FILE_MAX];
+
+ /* primary output layer */
+ if (surface->flags & MOD_DPAINT_OUT1) {
+ /* set filepath */
+ BLI_join_dirfile(
+ filename, sizeof(filename), surface->image_output_path, surface->output_name);
+ BLI_path_frame(filename, frame, 4);
+
+ /* save image */
+ dynamicPaint_outputSurfaceImage(surface, filename, 0);
+ }
+ /* secondary output */
+ if (surface->flags & MOD_DPAINT_OUT2 && surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
+ /* set filepath */
+ BLI_join_dirfile(
+ filename, sizeof(filename), surface->image_output_path, surface->output_name2);
+ BLI_path_frame(filename, frame, 4);
+
+ /* save image */
+ dynamicPaint_outputSurfaceImage(surface, filename, 1);
+ }
+ }
+ }
+
+ scene->r.cfra = orig_frame;
}
static void dpaint_bake_startjob(void *customdata, short *stop, short *do_update, float *progress)
{
- DynamicPaintBakeJob *job = customdata;
+ DynamicPaintBakeJob *job = customdata;
- job->stop = stop;
- job->do_update = do_update;
- job->progress = progress;
- job->start = PIL_check_seconds_timer();
- job->success = 1;
+ job->stop = stop;
+ job->do_update = do_update;
+ job->progress = progress;
+ job->start = PIL_check_seconds_timer();
+ job->success = 1;
- G.is_break = false; /* reset BKE_blender_test_break*/
+ G.is_break = false; /* reset BKE_blender_test_break*/
- /* XXX annoying hack: needed to prevent data corruption when changing
- * scene frame in separate threads
- */
- G.is_rendering = true;
- BKE_spacedata_draw_locks(true);
+ /* XXX annoying hack: needed to prevent data corruption when changing
+ * scene frame in separate threads
+ */
+ G.is_rendering = true;
+ BKE_spacedata_draw_locks(true);
- dynamicPaint_bakeImageSequence(job);
+ dynamicPaint_bakeImageSequence(job);
- *do_update = true;
- *stop = 0;
+ *do_update = true;
+ *stop = 0;
}
/*
@@ -447,66 +460,69 @@ static void dpaint_bake_startjob(void *customdata, short *stop, short *do_update
*/
static int dynamicpaint_bake_exec(struct bContext *C, struct wmOperator *op)
{
- DynamicPaintModifierData *pmd = NULL;
- DynamicPaintCanvasSettings *canvas;
- Object *ob = ED_object_context(C);
- Scene *scene = CTX_data_scene(C);
-
- DynamicPaintSurface *surface;
-
- /*
- * Get modifier data
- */
- pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
- if (!pmd) {
- BKE_report(op->reports, RPT_ERROR, "Bake failed: no Dynamic Paint modifier found");
- return OPERATOR_CANCELLED;
- }
-
- /* Make sure we're dealing with a canvas */
- canvas = pmd->canvas;
- if (!canvas) {
- BKE_report(op->reports, RPT_ERROR, "Bake failed: invalid canvas");
- return OPERATOR_CANCELLED;
- }
- surface = get_activeSurface(canvas);
-
- /* Set state to baking and init surface */
- canvas->error[0] = '\0';
- canvas->flags |= MOD_DPAINT_BAKING;
-
- DynamicPaintBakeJob *job = MEM_mallocN(sizeof(DynamicPaintBakeJob), "DynamicPaintBakeJob");
- job->bmain = CTX_data_main(C);
- job->scene = scene;
- job->depsgraph = CTX_data_depsgraph(C);
- job->ob = ob;
- job->canvas = canvas;
- job->surface = surface;
-
- wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene,
- "Dynamic Paint Bake", WM_JOB_PROGRESS,
- WM_JOB_TYPE_DPAINT_BAKE);
-
- WM_jobs_customdata_set(wm_job, job, dpaint_bake_free);
- WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_MODIFIER, NC_OBJECT | ND_MODIFIER);
- WM_jobs_callbacks(wm_job, dpaint_bake_startjob, NULL, NULL, dpaint_bake_endjob);
-
- WM_set_locked_interface(CTX_wm_manager(C), true);
-
- /* Bake Dynamic Paint */
- WM_jobs_start(CTX_wm_manager(C), wm_job);
-
- return OPERATOR_FINISHED;
+ DynamicPaintModifierData *pmd = NULL;
+ DynamicPaintCanvasSettings *canvas;
+ Object *ob = ED_object_context(C);
+ Scene *scene = CTX_data_scene(C);
+
+ DynamicPaintSurface *surface;
+
+ /*
+ * Get modifier data
+ */
+ pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
+ if (!pmd) {
+ BKE_report(op->reports, RPT_ERROR, "Bake failed: no Dynamic Paint modifier found");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Make sure we're dealing with a canvas */
+ canvas = pmd->canvas;
+ if (!canvas) {
+ BKE_report(op->reports, RPT_ERROR, "Bake failed: invalid canvas");
+ return OPERATOR_CANCELLED;
+ }
+ surface = get_activeSurface(canvas);
+
+ /* Set state to baking and init surface */
+ canvas->error[0] = '\0';
+ canvas->flags |= MOD_DPAINT_BAKING;
+
+ DynamicPaintBakeJob *job = MEM_mallocN(sizeof(DynamicPaintBakeJob), "DynamicPaintBakeJob");
+ job->bmain = CTX_data_main(C);
+ job->scene = scene;
+ job->depsgraph = CTX_data_depsgraph(C);
+ job->ob = ob;
+ job->canvas = canvas;
+ job->surface = surface;
+
+ wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ scene,
+ "Dynamic Paint Bake",
+ WM_JOB_PROGRESS,
+ WM_JOB_TYPE_DPAINT_BAKE);
+
+ WM_jobs_customdata_set(wm_job, job, dpaint_bake_free);
+ WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_MODIFIER, NC_OBJECT | ND_MODIFIER);
+ WM_jobs_callbacks(wm_job, dpaint_bake_startjob, NULL, NULL, dpaint_bake_endjob);
+
+ WM_set_locked_interface(CTX_wm_manager(C), true);
+
+ /* Bake Dynamic Paint */
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+
+ return OPERATOR_FINISHED;
}
void DPAINT_OT_bake(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Dynamic Paint Bake";
- ot->description = "Bake dynamic paint image sequence surface";
- ot->idname = "DPAINT_OT_bake";
-
- /* api callbacks */
- ot->exec = dynamicpaint_bake_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* identifiers */
+ ot->name = "Dynamic Paint Bake";
+ ot->description = "Bake dynamic paint image sequence surface";
+ ot->idname = "DPAINT_OT_bake";
+
+ /* api callbacks */
+ ot->exec = dynamicpaint_bake_exec;
+ ot->poll = ED_operator_object_active_editable;
}
diff --git a/source/blender/editors/physics/particle_boids.c b/source/blender/editors/physics/particle_boids.c
index 7ddb193b0e5..cedb7d6cbc1 100644
--- a/source/blender/editors/physics/particle_boids.c
+++ b/source/blender/editors/physics/particle_boids.c
@@ -21,7 +21,6 @@
* \ingroup edphys
*/
-
#include <stdlib.h>
#include "MEM_guardedalloc.h"
@@ -51,316 +50,315 @@
/************************ add/del boid rule operators *********************/
static int rule_add_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
- ParticleSettings *part = ptr.data;
- int type = RNA_enum_get(op->ptr, "type");
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
+ ParticleSettings *part = ptr.data;
+ int type = RNA_enum_get(op->ptr, "type");
- BoidRule *rule;
- BoidState *state;
+ BoidRule *rule;
+ BoidState *state;
- if (!part || part->phystype != PART_PHYS_BOIDS)
- return OPERATOR_CANCELLED;
+ if (!part || part->phystype != PART_PHYS_BOIDS)
+ return OPERATOR_CANCELLED;
- state = boid_get_current_state(part->boids);
+ state = boid_get_current_state(part->boids);
- for (rule = state->rules.first; rule; rule = rule->next)
- rule->flag &= ~BOIDRULE_CURRENT;
+ for (rule = state->rules.first; rule; rule = rule->next)
+ rule->flag &= ~BOIDRULE_CURRENT;
- rule = boid_new_rule(type);
- rule->flag |= BOIDRULE_CURRENT;
+ rule = boid_new_rule(type);
+ rule->flag |= BOIDRULE_CURRENT;
- BLI_addtail(&state->rules, rule);
+ BLI_addtail(&state->rules, rule);
- DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
+ DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void BOID_OT_rule_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Boid Rule";
- ot->description = "Add a boid rule to the current boid state";
- ot->idname = "BOID_OT_rule_add";
+ /* identifiers */
+ ot->name = "Add Boid Rule";
+ ot->description = "Add a boid rule to the current boid state";
+ ot->idname = "BOID_OT_rule_add";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = rule_add_exec;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = rule_add_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_boidrule_type_items, 0, "Type", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_boidrule_type_items, 0, "Type", "");
}
static int rule_del_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
- ParticleSettings *part = ptr.data;
- BoidRule *rule;
- BoidState *state;
+ Main *bmain = CTX_data_main(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
+ ParticleSettings *part = ptr.data;
+ BoidRule *rule;
+ BoidState *state;
- if (!part || part->phystype != PART_PHYS_BOIDS)
- return OPERATOR_CANCELLED;
+ if (!part || part->phystype != PART_PHYS_BOIDS)
+ return OPERATOR_CANCELLED;
- state = boid_get_current_state(part->boids);
+ state = boid_get_current_state(part->boids);
- for (rule = state->rules.first; rule; rule = rule->next) {
- if (rule->flag & BOIDRULE_CURRENT) {
- BLI_remlink(&state->rules, rule);
- MEM_freeN(rule);
- break;
- }
- }
- rule = state->rules.first;
+ for (rule = state->rules.first; rule; rule = rule->next) {
+ if (rule->flag & BOIDRULE_CURRENT) {
+ BLI_remlink(&state->rules, rule);
+ MEM_freeN(rule);
+ break;
+ }
+ }
+ rule = state->rules.first;
- if (rule)
- rule->flag |= BOIDRULE_CURRENT;
+ if (rule)
+ rule->flag |= BOIDRULE_CURRENT;
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void BOID_OT_rule_del(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Boid Rule";
- ot->idname = "BOID_OT_rule_del";
- ot->description = "Delete current boid rule";
+ /* identifiers */
+ ot->name = "Remove Boid Rule";
+ ot->idname = "BOID_OT_rule_del";
+ ot->description = "Delete current boid rule";
- /* api callbacks */
- ot->exec = rule_del_exec;
+ /* api callbacks */
+ ot->exec = rule_del_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************ move up/down boid rule operators *********************/
static int rule_move_up_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
- ParticleSettings *part = ptr.data;
- BoidRule *rule;
- BoidState *state;
-
- if (!part || part->phystype != PART_PHYS_BOIDS)
- return OPERATOR_CANCELLED;
-
- state = boid_get_current_state(part->boids);
- for (rule = state->rules.first; rule; rule = rule->next) {
- if (rule->flag & BOIDRULE_CURRENT && rule->prev) {
- BLI_remlink(&state->rules, rule);
- BLI_insertlinkbefore(&state->rules, rule->prev, rule);
-
- DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
- break;
- }
- }
-
- return OPERATOR_FINISHED;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
+ ParticleSettings *part = ptr.data;
+ BoidRule *rule;
+ BoidState *state;
+
+ if (!part || part->phystype != PART_PHYS_BOIDS)
+ return OPERATOR_CANCELLED;
+
+ state = boid_get_current_state(part->boids);
+ for (rule = state->rules.first; rule; rule = rule->next) {
+ if (rule->flag & BOIDRULE_CURRENT && rule->prev) {
+ BLI_remlink(&state->rules, rule);
+ BLI_insertlinkbefore(&state->rules, rule->prev, rule);
+
+ DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
+ break;
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void BOID_OT_rule_move_up(wmOperatorType *ot)
{
- ot->name = "Move Up Boid Rule";
- ot->description = "Move boid rule up in the list";
- ot->idname = "BOID_OT_rule_move_up";
+ ot->name = "Move Up Boid Rule";
+ ot->description = "Move boid rule up in the list";
+ ot->idname = "BOID_OT_rule_move_up";
- ot->exec = rule_move_up_exec;
+ ot->exec = rule_move_up_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int rule_move_down_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
- ParticleSettings *part = ptr.data;
- BoidRule *rule;
- BoidState *state;
-
- if (!part || part->phystype != PART_PHYS_BOIDS)
- return OPERATOR_CANCELLED;
-
- state = boid_get_current_state(part->boids);
- for (rule = state->rules.first; rule; rule = rule->next) {
- if (rule->flag & BOIDRULE_CURRENT && rule->next) {
- BLI_remlink(&state->rules, rule);
- BLI_insertlinkafter(&state->rules, rule->next, rule);
-
- DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
- break;
- }
- }
-
- return OPERATOR_FINISHED;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
+ ParticleSettings *part = ptr.data;
+ BoidRule *rule;
+ BoidState *state;
+
+ if (!part || part->phystype != PART_PHYS_BOIDS)
+ return OPERATOR_CANCELLED;
+
+ state = boid_get_current_state(part->boids);
+ for (rule = state->rules.first; rule; rule = rule->next) {
+ if (rule->flag & BOIDRULE_CURRENT && rule->next) {
+ BLI_remlink(&state->rules, rule);
+ BLI_insertlinkafter(&state->rules, rule->next, rule);
+
+ DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
+ break;
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void BOID_OT_rule_move_down(wmOperatorType *ot)
{
- ot->name = "Move Down Boid Rule";
- ot->description = "Move boid rule down in the list";
- ot->idname = "BOID_OT_rule_move_down";
+ ot->name = "Move Down Boid Rule";
+ ot->description = "Move boid rule down in the list";
+ ot->idname = "BOID_OT_rule_move_down";
- ot->exec = rule_move_down_exec;
+ ot->exec = rule_move_down_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/************************ add/del boid state operators *********************/
static int state_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
- ParticleSettings *part = ptr.data;
- BoidState *state;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
+ ParticleSettings *part = ptr.data;
+ BoidState *state;
- if (!part || part->phystype != PART_PHYS_BOIDS)
- return OPERATOR_CANCELLED;
+ if (!part || part->phystype != PART_PHYS_BOIDS)
+ return OPERATOR_CANCELLED;
- for (state = part->boids->states.first; state; state = state->next)
- state->flag &= ~BOIDSTATE_CURRENT;
+ for (state = part->boids->states.first; state; state = state->next)
+ state->flag &= ~BOIDSTATE_CURRENT;
- state = boid_new_state(part->boids);
- state->flag |= BOIDSTATE_CURRENT;
+ state = boid_new_state(part->boids);
+ state->flag |= BOIDSTATE_CURRENT;
- BLI_addtail(&part->boids->states, state);
+ BLI_addtail(&part->boids->states, state);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void BOID_OT_state_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Boid State";
- ot->description = "Add a boid state to the particle system";
- ot->idname = "BOID_OT_state_add";
+ /* identifiers */
+ ot->name = "Add Boid State";
+ ot->description = "Add a boid state to the particle system";
+ ot->idname = "BOID_OT_state_add";
- /* api callbacks */
- ot->exec = state_add_exec;
+ /* api callbacks */
+ ot->exec = state_add_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int state_del_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
- ParticleSettings *part = ptr.data;
- BoidState *state;
-
- if (!part || part->phystype != PART_PHYS_BOIDS)
- return OPERATOR_CANCELLED;
-
- for (state = part->boids->states.first; state; state = state->next) {
- if (state->flag & BOIDSTATE_CURRENT) {
- BLI_remlink(&part->boids->states, state);
- MEM_freeN(state);
- break;
- }
- }
-
- /* there must be at least one state */
- if (!part->boids->states.first) {
- state = boid_new_state(part->boids);
- BLI_addtail(&part->boids->states, state);
- }
- else
- state = part->boids->states.first;
-
- state->flag |= BOIDSTATE_CURRENT;
-
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
+ ParticleSettings *part = ptr.data;
+ BoidState *state;
+
+ if (!part || part->phystype != PART_PHYS_BOIDS)
+ return OPERATOR_CANCELLED;
+
+ for (state = part->boids->states.first; state; state = state->next) {
+ if (state->flag & BOIDSTATE_CURRENT) {
+ BLI_remlink(&part->boids->states, state);
+ MEM_freeN(state);
+ break;
+ }
+ }
+
+ /* there must be at least one state */
+ if (!part->boids->states.first) {
+ state = boid_new_state(part->boids);
+ BLI_addtail(&part->boids->states, state);
+ }
+ else
+ state = part->boids->states.first;
+
+ state->flag |= BOIDSTATE_CURRENT;
+
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
+
+ return OPERATOR_FINISHED;
}
void BOID_OT_state_del(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Boid State";
- ot->idname = "BOID_OT_state_del";
- ot->description = "Delete current boid state";
+ /* identifiers */
+ ot->name = "Remove Boid State";
+ ot->idname = "BOID_OT_state_del";
+ ot->description = "Delete current boid state";
- /* api callbacks */
- ot->exec = state_del_exec;
+ /* api callbacks */
+ ot->exec = state_del_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************ move up/down boid state operators *********************/
static int state_move_up_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
- ParticleSettings *part = ptr.data;
- BoidSettings *boids;
- BoidState *state;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
+ ParticleSettings *part = ptr.data;
+ BoidSettings *boids;
+ BoidState *state;
- if (!part || part->phystype != PART_PHYS_BOIDS)
- return OPERATOR_CANCELLED;
+ if (!part || part->phystype != PART_PHYS_BOIDS)
+ return OPERATOR_CANCELLED;
- boids = part->boids;
+ boids = part->boids;
- for (state = boids->states.first; state; state = state->next) {
- if (state->flag & BOIDSTATE_CURRENT && state->prev) {
- BLI_remlink(&boids->states, state);
- BLI_insertlinkbefore(&boids->states, state->prev, state);
- break;
- }
- }
+ for (state = boids->states.first; state; state = state->next) {
+ if (state->flag & BOIDSTATE_CURRENT && state->prev) {
+ BLI_remlink(&boids->states, state);
+ BLI_insertlinkbefore(&boids->states, state->prev, state);
+ break;
+ }
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void BOID_OT_state_move_up(wmOperatorType *ot)
{
- ot->name = "Move Up Boid State";
- ot->description = "Move boid state up in the list";
- ot->idname = "BOID_OT_state_move_up";
+ ot->name = "Move Up Boid State";
+ ot->description = "Move boid state up in the list";
+ ot->idname = "BOID_OT_state_move_up";
- ot->exec = state_move_up_exec;
+ ot->exec = state_move_up_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int state_move_down_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
- ParticleSettings *part = ptr.data;
- BoidSettings *boids;
- BoidState *state;
-
- if (!part || part->phystype != PART_PHYS_BOIDS)
- return OPERATOR_CANCELLED;
-
- boids = part->boids;
-
- for (state = boids->states.first; state; state = state->next) {
- if (state->flag & BOIDSTATE_CURRENT && state->next) {
- BLI_remlink(&boids->states, state);
- BLI_insertlinkafter(&boids->states, state->next, state);
- DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
- break;
- }
- }
-
- return OPERATOR_FINISHED;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
+ ParticleSettings *part = ptr.data;
+ BoidSettings *boids;
+ BoidState *state;
+
+ if (!part || part->phystype != PART_PHYS_BOIDS)
+ return OPERATOR_CANCELLED;
+
+ boids = part->boids;
+
+ for (state = boids->states.first; state; state = state->next) {
+ if (state->flag & BOIDSTATE_CURRENT && state->next) {
+ BLI_remlink(&boids->states, state);
+ BLI_insertlinkafter(&boids->states, state->next, state);
+ DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
+ break;
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void BOID_OT_state_move_down(wmOperatorType *ot)
{
- ot->name = "Move Down Boid State";
- ot->description = "Move boid state down in the list";
- ot->idname = "BOID_OT_state_move_down";
+ ot->name = "Move Down Boid State";
+ ot->description = "Move boid state down in the list";
+ ot->idname = "BOID_OT_state_move_down";
- ot->exec = state_move_down_exec;
+ ot->exec = state_move_down_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index f2d9871a99d..627ffd68bbb 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -59,7 +59,6 @@
#include "DEG_depsgraph.h"
-
#include "ED_object.h"
#include "ED_physics.h"
#include "ED_mesh.h"
@@ -94,118 +93,117 @@
bool PE_poll(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
- if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) {
- return 0;
- }
- return (PE_get_current(scene, ob) != NULL);
+ if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) {
+ return 0;
+ }
+ return (PE_get_current(scene, ob) != NULL);
}
bool PE_hair_poll(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- PTCacheEdit *edit;
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ PTCacheEdit *edit;
- if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) {
- return 0;
- }
- edit = PE_get_current(scene, ob);
+ if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) {
+ return 0;
+ }
+ edit = PE_get_current(scene, ob);
- return (edit && edit->psys);
+ return (edit && edit->psys);
}
bool PE_poll_view3d(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
- return (PE_poll(C) &&
- (sa && sa->spacetype == SPACE_VIEW3D) &&
- (ar && ar->regiontype == RGN_TYPE_WINDOW));
+ return (PE_poll(C) && (sa && sa->spacetype == SPACE_VIEW3D) &&
+ (ar && ar->regiontype == RGN_TYPE_WINDOW));
}
void PE_free_ptcache_edit(PTCacheEdit *edit)
{
- POINT_P;
+ POINT_P;
- if (edit == 0) return;
+ if (edit == 0)
+ return;
- if (edit->points) {
- LOOP_POINTS {
- if (point->keys)
- MEM_freeN(point->keys);
- }
+ if (edit->points) {
+ LOOP_POINTS
+ {
+ if (point->keys)
+ MEM_freeN(point->keys);
+ }
- MEM_freeN(edit->points);
- }
+ MEM_freeN(edit->points);
+ }
- if (edit->mirror_cache)
- MEM_freeN(edit->mirror_cache);
+ if (edit->mirror_cache)
+ MEM_freeN(edit->mirror_cache);
- if (edit->emitter_cosnos) {
- MEM_freeN(edit->emitter_cosnos);
- edit->emitter_cosnos = 0;
- }
+ if (edit->emitter_cosnos) {
+ MEM_freeN(edit->emitter_cosnos);
+ edit->emitter_cosnos = 0;
+ }
- if (edit->emitter_field) {
- BLI_kdtree_3d_free(edit->emitter_field);
- edit->emitter_field = 0;
- }
+ if (edit->emitter_field) {
+ BLI_kdtree_3d_free(edit->emitter_field);
+ edit->emitter_field = 0;
+ }
- psys_free_path_cache(edit->psys, edit);
+ psys_free_path_cache(edit->psys, edit);
- MEM_freeN(edit);
+ MEM_freeN(edit);
}
/************************************************/
-/* Edit Mode Helpers */
+/* Edit Mode Helpers */
/************************************************/
int PE_start_edit(PTCacheEdit *edit)
{
- if (edit) {
- edit->edited = 1;
- if (edit->psys)
- edit->psys->flag |= PSYS_EDITED;
- return 1;
- }
+ if (edit) {
+ edit->edited = 1;
+ if (edit->psys)
+ edit->psys->flag |= PSYS_EDITED;
+ return 1;
+ }
- return 0;
+ return 0;
}
ParticleEditSettings *PE_settings(Scene *scene)
{
- return scene->toolsettings ? &scene->toolsettings->particle : NULL;
+ return scene->toolsettings ? &scene->toolsettings->particle : NULL;
}
static float pe_brush_size_get(const Scene *UNUSED(scene), ParticleBrushData *brush)
{
- // here we can enable unified brush size, needs more work...
- // UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
- // float size = (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size;
+ // here we can enable unified brush size, needs more work...
+ // 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 * U.pixelsize;
}
PTCacheEdit *PE_get_current_from_psys(ParticleSystem *psys)
{
- if (psys->part && psys->part->type == PART_HAIR) {
- if ((psys->flag & PSYS_HAIR_DYNAMICS) != 0 &&
- (psys->pointcache->flag & PTCACHE_BAKED) != 0)
- {
- return psys->pointcache->edit;
- }
- else {
- return psys->edit;
- }
- }
- else if (psys->pointcache->flag & PTCACHE_BAKED) {
- return psys->pointcache->edit;
- }
- return NULL;
+ if (psys->part && psys->part->type == PART_HAIR) {
+ if ((psys->flag & PSYS_HAIR_DYNAMICS) != 0 && (psys->pointcache->flag & PTCACHE_BAKED) != 0) {
+ return psys->pointcache->edit;
+ }
+ else {
+ return psys->edit;
+ }
+ }
+ else if (psys->pointcache->flag & PTCACHE_BAKED) {
+ return psys->pointcache->edit;
+ }
+ return NULL;
}
/* NOTE: Similar to creation of edit, but only updates pointers in the
@@ -213,1678 +211,1722 @@ PTCacheEdit *PE_get_current_from_psys(ParticleSystem *psys)
*/
static void pe_update_hair_particle_edit_pointers(PTCacheEdit *edit)
{
- ParticleSystem *psys = edit->psys;
- ParticleData *pa = psys->particles;
- for (int p = 0; p < edit->totpoint; p++) {
- PTCacheEditPoint *point = &edit->points[p];
- HairKey *hair_key = pa->hair;
- for (int k = 0; k < point->totkey; k++) {
- PTCacheEditKey *key = &point->keys[k];
- key->co = hair_key->co;
- key->time = &hair_key->time;
- key->flag = hair_key->editflag;
- if (!(psys->flag & PSYS_GLOBAL_HAIR)) {
- key->flag |= PEK_USE_WCO;
- hair_key->editflag |= PEK_USE_WCO;
- }
- hair_key++;
- }
- pa++;
- }
+ ParticleSystem *psys = edit->psys;
+ ParticleData *pa = psys->particles;
+ for (int p = 0; p < edit->totpoint; p++) {
+ PTCacheEditPoint *point = &edit->points[p];
+ HairKey *hair_key = pa->hair;
+ for (int k = 0; k < point->totkey; k++) {
+ PTCacheEditKey *key = &point->keys[k];
+ key->co = hair_key->co;
+ key->time = &hair_key->time;
+ key->flag = hair_key->editflag;
+ if (!(psys->flag & PSYS_GLOBAL_HAIR)) {
+ key->flag |= PEK_USE_WCO;
+ hair_key->editflag |= PEK_USE_WCO;
+ }
+ hair_key++;
+ }
+ pa++;
+ }
}
/* always gets at least the first particlesystem even if PSYS_CURRENT flag is not set
*
* note: this function runs on poll, therefor it can runs many times a second
* keep it fast! */
-static PTCacheEdit *pe_get_current(
- Depsgraph *depsgraph, Scene *scene, Object *ob, int create)
-{
- ParticleEditSettings *pset = PE_settings(scene);
- PTCacheEdit *edit = NULL;
- ListBase pidlist;
- PTCacheID *pid;
-
- if (pset == NULL || ob == NULL)
- return NULL;
-
- pset->scene = scene;
- pset->object = ob;
-
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
-
- /* in the case of only one editable thing, set pset->edittype accordingly */
- if (BLI_listbase_is_single(&pidlist)) {
- pid = pidlist.first;
- switch (pid->type) {
- case PTCACHE_TYPE_PARTICLES:
- pset->edittype = PE_TYPE_PARTICLES;
- break;
- case PTCACHE_TYPE_SOFTBODY:
- pset->edittype = PE_TYPE_SOFTBODY;
- break;
- case PTCACHE_TYPE_CLOTH:
- pset->edittype = PE_TYPE_CLOTH;
- break;
- }
- }
-
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pset->edittype == PE_TYPE_PARTICLES && pid->type == PTCACHE_TYPE_PARTICLES) {
- ParticleSystem *psys = pid->calldata;
-
- if (psys->flag & PSYS_CURRENT) {
- if (psys->part && psys->part->type == PART_HAIR) {
- if (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED) {
- if (create && !psys->pointcache->edit)
- PE_create_particle_edit(depsgraph, scene, ob, pid->cache, NULL);
- edit = pid->cache->edit;
- }
- else {
- if (create && !psys->edit) {
- if (psys->flag & PSYS_HAIR_DONE) {
- PE_create_particle_edit(depsgraph, scene, ob, NULL, psys);
- }
- }
- edit = psys->edit;
- }
- }
- else {
- if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit)
- PE_create_particle_edit(depsgraph, scene, ob, pid->cache, psys);
- edit = pid->cache->edit;
- }
-
- break;
- }
- }
- else if (pset->edittype == PE_TYPE_SOFTBODY && pid->type == PTCACHE_TYPE_SOFTBODY) {
- if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) {
- pset->flag |= PE_FADE_TIME;
- // NICE TO HAVE but doesn't work: pset->brushtype = PE_BRUSH_COMB;
- PE_create_particle_edit(depsgraph, scene, ob, pid->cache, NULL);
- }
- edit = pid->cache->edit;
- break;
- }
- else if (pset->edittype == PE_TYPE_CLOTH && pid->type == PTCACHE_TYPE_CLOTH) {
- if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) {
- pset->flag |= PE_FADE_TIME;
- // NICE TO HAVE but doesn't work: pset->brushtype = PE_BRUSH_COMB;
- PE_create_particle_edit(depsgraph, scene, ob, pid->cache, NULL);
- }
- edit = pid->cache->edit;
- break;
- }
- }
-
- if (edit) {
- edit->pid = *pid;
- if (edit->flags & PT_CACHE_EDIT_UPDATE_PARTICLE_FROM_EVAL) {
- if (edit->psys != NULL) {
- psys_copy_particles(edit->psys, edit->psys_eval);
- pe_update_hair_particle_edit_pointers(edit);
- }
- edit->flags &= ~PT_CACHE_EDIT_UPDATE_PARTICLE_FROM_EVAL;
- }
- }
-
- BLI_freelistN(&pidlist);
-
- return edit;
+static PTCacheEdit *pe_get_current(Depsgraph *depsgraph, Scene *scene, Object *ob, int create)
+{
+ ParticleEditSettings *pset = PE_settings(scene);
+ PTCacheEdit *edit = NULL;
+ ListBase pidlist;
+ PTCacheID *pid;
+
+ if (pset == NULL || ob == NULL)
+ return NULL;
+
+ pset->scene = scene;
+ pset->object = ob;
+
+ BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
+
+ /* in the case of only one editable thing, set pset->edittype accordingly */
+ if (BLI_listbase_is_single(&pidlist)) {
+ pid = pidlist.first;
+ switch (pid->type) {
+ case PTCACHE_TYPE_PARTICLES:
+ pset->edittype = PE_TYPE_PARTICLES;
+ break;
+ case PTCACHE_TYPE_SOFTBODY:
+ pset->edittype = PE_TYPE_SOFTBODY;
+ break;
+ case PTCACHE_TYPE_CLOTH:
+ pset->edittype = PE_TYPE_CLOTH;
+ break;
+ }
+ }
+
+ for (pid = pidlist.first; pid; pid = pid->next) {
+ if (pset->edittype == PE_TYPE_PARTICLES && pid->type == PTCACHE_TYPE_PARTICLES) {
+ ParticleSystem *psys = pid->calldata;
+
+ if (psys->flag & PSYS_CURRENT) {
+ if (psys->part && psys->part->type == PART_HAIR) {
+ if (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED) {
+ if (create && !psys->pointcache->edit)
+ PE_create_particle_edit(depsgraph, scene, ob, pid->cache, NULL);
+ edit = pid->cache->edit;
+ }
+ else {
+ if (create && !psys->edit) {
+ if (psys->flag & PSYS_HAIR_DONE) {
+ PE_create_particle_edit(depsgraph, scene, ob, NULL, psys);
+ }
+ }
+ edit = psys->edit;
+ }
+ }
+ else {
+ if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit)
+ PE_create_particle_edit(depsgraph, scene, ob, pid->cache, psys);
+ edit = pid->cache->edit;
+ }
+
+ break;
+ }
+ }
+ else if (pset->edittype == PE_TYPE_SOFTBODY && pid->type == PTCACHE_TYPE_SOFTBODY) {
+ if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) {
+ pset->flag |= PE_FADE_TIME;
+ // NICE TO HAVE but doesn't work: pset->brushtype = PE_BRUSH_COMB;
+ PE_create_particle_edit(depsgraph, scene, ob, pid->cache, NULL);
+ }
+ edit = pid->cache->edit;
+ break;
+ }
+ else if (pset->edittype == PE_TYPE_CLOTH && pid->type == PTCACHE_TYPE_CLOTH) {
+ if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) {
+ pset->flag |= PE_FADE_TIME;
+ // NICE TO HAVE but doesn't work: pset->brushtype = PE_BRUSH_COMB;
+ PE_create_particle_edit(depsgraph, scene, ob, pid->cache, NULL);
+ }
+ edit = pid->cache->edit;
+ break;
+ }
+ }
+
+ if (edit) {
+ edit->pid = *pid;
+ if (edit->flags & PT_CACHE_EDIT_UPDATE_PARTICLE_FROM_EVAL) {
+ if (edit->psys != NULL) {
+ psys_copy_particles(edit->psys, edit->psys_eval);
+ pe_update_hair_particle_edit_pointers(edit);
+ }
+ edit->flags &= ~PT_CACHE_EDIT_UPDATE_PARTICLE_FROM_EVAL;
+ }
+ }
+
+ BLI_freelistN(&pidlist);
+
+ return edit;
}
PTCacheEdit *PE_get_current(Scene *scene, Object *ob)
{
- return pe_get_current(NULL, scene, ob, 0);
+ return pe_get_current(NULL, scene, ob, 0);
}
PTCacheEdit *PE_create_current(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- return pe_get_current(depsgraph, scene, ob, 1);
+ return pe_get_current(depsgraph, scene, ob, 1);
}
void PE_current_changed(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- if (ob->mode == OB_MODE_PARTICLE_EDIT) {
- PE_create_current(depsgraph, scene, ob);
- }
+ if (ob->mode == OB_MODE_PARTICLE_EDIT) {
+ PE_create_current(depsgraph, scene, ob);
+ }
}
void PE_hide_keys_time(Scene *scene, PTCacheEdit *edit, float cfra)
{
- ParticleEditSettings *pset = PE_settings(scene);
- POINT_P; KEY_K;
-
-
- if (pset->flag & PE_FADE_TIME && pset->selectmode == SCE_SELECT_POINT) {
- LOOP_POINTS {
- LOOP_KEYS {
- if (fabsf(cfra - *key->time) < pset->fade_frames)
- key->flag &= ~PEK_HIDE;
- else {
- key->flag |= PEK_HIDE;
- //key->flag &= ~PEK_SELECT;
- }
- }
- }
- }
- else {
- LOOP_POINTS {
- LOOP_KEYS {
- key->flag &= ~PEK_HIDE;
- }
- }
- }
+ ParticleEditSettings *pset = PE_settings(scene);
+ POINT_P;
+ KEY_K;
+
+ if (pset->flag & PE_FADE_TIME && pset->selectmode == SCE_SELECT_POINT) {
+ LOOP_POINTS
+ {
+ LOOP_KEYS
+ {
+ if (fabsf(cfra - *key->time) < pset->fade_frames)
+ key->flag &= ~PEK_HIDE;
+ else {
+ key->flag |= PEK_HIDE;
+ //key->flag &= ~PEK_SELECT;
+ }
+ }
+ }
+ }
+ else {
+ LOOP_POINTS
+ {
+ LOOP_KEYS
+ {
+ key->flag &= ~PEK_HIDE;
+ }
+ }
+ }
}
static int pe_x_mirror(Object *ob)
{
- if (ob->type == OB_MESH)
- return (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X);
+ if (ob->type == OB_MESH)
+ return (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X);
- return 0;
+ return 0;
}
/****************** common struct passed to callbacks ******************/
typedef struct PEData {
- ViewContext vc;
-
- const bContext *context;
- Main *bmain;
- Scene *scene;
- ViewLayer *view_layer;
- Object *ob;
- Mesh *mesh;
- PTCacheEdit *edit;
- BVHTreeFromMesh shape_bvh;
- Depsgraph *depsgraph;
-
- RNG *rng;
-
- const int *mval;
- const rcti *rect;
- float rad;
- float dval;
- int select;
- eSelectOp sel_op;
-
- float *dvec;
- float combfac;
- float pufffac;
- float cutfac;
- float smoothfac;
- float weightfac;
- float growfac;
- int totrekey;
-
- int invert;
- int tot;
- float vec[3];
-
- int select_action;
- int select_toggle_action;
- bool is_changed;
+ ViewContext vc;
+
+ const bContext *context;
+ Main *bmain;
+ Scene *scene;
+ ViewLayer *view_layer;
+ Object *ob;
+ Mesh *mesh;
+ PTCacheEdit *edit;
+ BVHTreeFromMesh shape_bvh;
+ Depsgraph *depsgraph;
+
+ RNG *rng;
+
+ const int *mval;
+ const rcti *rect;
+ float rad;
+ float dval;
+ int select;
+ eSelectOp sel_op;
+
+ float *dvec;
+ float combfac;
+ float pufffac;
+ float cutfac;
+ float smoothfac;
+ float weightfac;
+ float growfac;
+ int totrekey;
+
+ int invert;
+ int tot;
+ float vec[3];
+
+ int select_action;
+ int select_toggle_action;
+ bool is_changed;
} PEData;
static void PE_set_data(bContext *C, PEData *data)
{
- memset(data, 0, sizeof(*data));
+ memset(data, 0, sizeof(*data));
- data->context = C;
- data->bmain = CTX_data_main(C);
- data->scene = CTX_data_scene(C);
- data->view_layer = CTX_data_view_layer(C);
- data->ob = CTX_data_active_object(C);
- data->depsgraph = CTX_data_depsgraph(C);
- data->edit = PE_get_current(data->scene, data->ob);
+ data->context = C;
+ data->bmain = CTX_data_main(C);
+ data->scene = CTX_data_scene(C);
+ data->view_layer = CTX_data_view_layer(C);
+ data->ob = CTX_data_active_object(C);
+ data->depsgraph = CTX_data_depsgraph(C);
+ data->edit = PE_get_current(data->scene, data->ob);
}
static void PE_set_view3d_data(bContext *C, PEData *data)
{
- PE_set_data(C, data);
+ PE_set_data(C, data);
- ED_view3d_viewcontext_init(C, &data->vc);
+ ED_view3d_viewcontext_init(C, &data->vc);
- if (!XRAY_ENABLED(data->vc.v3d)) {
- if (data->vc.v3d->flag & V3D_INVALID_BACKBUF) {
- /* needed or else the draw matrix can be incorrect */
- view3d_operator_needs_opengl(C);
+ if (!XRAY_ENABLED(data->vc.v3d)) {
+ if (data->vc.v3d->flag & V3D_INVALID_BACKBUF) {
+ /* needed or else the draw matrix can be incorrect */
+ view3d_operator_needs_opengl(C);
- ED_view3d_backbuf_depth_validate(&data->vc);
- /* 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_backbuf_depth_validate(&data->vc);
+ /* 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);
+ }
+ }
}
static bool PE_create_shape_tree(PEData *data, Object *shapeob)
{
- Mesh *mesh = BKE_object_get_evaluated_mesh(data->depsgraph, shapeob);
+ Mesh *mesh = BKE_object_get_evaluated_mesh(data->depsgraph, shapeob);
- memset(&data->shape_bvh, 0, sizeof(data->shape_bvh));
+ memset(&data->shape_bvh, 0, sizeof(data->shape_bvh));
- if (!mesh) {
- return false;
- }
+ if (!mesh) {
+ return false;
+ }
- return (BKE_bvhtree_from_mesh_get(&data->shape_bvh, mesh, BVHTREE_FROM_LOOPTRI, 4) != NULL);
+ return (BKE_bvhtree_from_mesh_get(&data->shape_bvh, mesh, BVHTREE_FROM_LOOPTRI, 4) != NULL);
}
static void PE_free_shape_tree(PEData *data)
{
- free_bvhtree_from_mesh(&data->shape_bvh);
+ free_bvhtree_from_mesh(&data->shape_bvh);
}
static void PE_create_random_generator(PEData *data)
{
- uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
- rng_seed ^= POINTER_AS_UINT(data->ob);
- rng_seed ^= POINTER_AS_UINT(data->edit);
- data->rng = BLI_rng_new(rng_seed);
+ uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
+ rng_seed ^= POINTER_AS_UINT(data->ob);
+ rng_seed ^= POINTER_AS_UINT(data->edit);
+ data->rng = BLI_rng_new(rng_seed);
}
static void PE_free_random_generator(PEData *data)
{
- if (data->rng != NULL) {
- BLI_rng_free(data->rng);
- data->rng = NULL;
- }
+ if (data->rng != NULL) {
+ BLI_rng_free(data->rng);
+ data->rng = NULL;
+ }
}
/*************************** selection utilities *******************************/
static bool key_test_depth(const PEData *data, const float co[3], const int screen_co[2])
{
- View3D *v3d = data->vc.v3d;
- ViewDepths *vd = data->vc.rv3d->depths;
- float depth;
+ View3D *v3d = data->vc.v3d;
+ ViewDepths *vd = data->vc.rv3d->depths;
+ float depth;
- /* nothing to do */
- if (XRAY_ENABLED(v3d))
- return true;
+ /* nothing to do */
+ if (XRAY_ENABLED(v3d))
+ return true;
- /* used to calculate here but all callers have the screen_co already, so pass as arg */
+ /* 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, co, screen_co,
- V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) != V3D_PROJ_RET_OK)
- {
- return 0;
- }
+ if (ED_view3d_project_int_global(data->vc.ar, co, screen_co,
+ V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) != V3D_PROJ_RET_OK)
+ {
+ return 0;
+ }
#endif
- /* check if screen_co is within bounds because brush_cut uses out of screen coords */
- if (screen_co[0] >= 0 && screen_co[0] < vd->w && screen_co[1] >= 0 && screen_co[1] < vd->h) {
- BLI_assert(vd && vd->depths);
- /* we know its not clipped */
- depth = vd->depths[screen_co[1] * vd->w + screen_co[0]];
- }
- else
- return 0;
+ /* check if screen_co is within bounds because brush_cut uses out of screen coords */
+ if (screen_co[0] >= 0 && screen_co[0] < vd->w && screen_co[1] >= 0 && screen_co[1] < vd->h) {
+ BLI_assert(vd && vd->depths);
+ /* we know its not clipped */
+ depth = vd->depths[screen_co[1] * vd->w + screen_co[0]];
+ }
+ else
+ return 0;
- float win[3];
- ED_view3d_project(data->vc.ar, co, win);
+ float win[3];
+ ED_view3d_project(data->vc.ar, co, win);
- if (win[2] - 0.00001f > depth)
- return 0;
- else
- return 1;
+ if (win[2] - 0.00001f > depth)
+ return 0;
+ else
+ return 1;
}
static bool key_inside_circle(const PEData *data, float rad, const float co[3], float *distance)
{
- float dx, dy, dist;
- int screen_co[2];
+ float dx, dy, dist;
+ 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) != V3D_PROJ_RET_OK) {
- return 0;
- }
+ /* 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) !=
+ V3D_PROJ_RET_OK) {
+ return 0;
+ }
- dx = data->mval[0] - screen_co[0];
- dy = data->mval[1] - screen_co[1];
- dist = sqrtf(dx * dx + dy * dy);
+ dx = data->mval[0] - screen_co[0];
+ dy = data->mval[1] - screen_co[1];
+ dist = sqrtf(dx * dx + dy * dy);
- if (dist > rad)
- return 0;
+ if (dist > rad)
+ return 0;
- if (key_test_depth(data, co, screen_co)) {
- if (distance)
- *distance = dist;
+ if (key_test_depth(data, co, screen_co)) {
+ if (distance)
+ *distance = dist;
- return 1;
- }
+ return 1;
+ }
- return 0;
+ return 0;
}
static bool key_inside_rect(PEData *data, const float co[3])
{
- int screen_co[2];
+ int screen_co[2];
- if (ED_view3d_project_int_global(data->vc.ar, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) != V3D_PROJ_RET_OK) {
- return 0;
- }
+ if (ED_view3d_project_int_global(data->vc.ar, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) !=
+ V3D_PROJ_RET_OK) {
+ return 0;
+ }
- if (screen_co[0] > data->rect->xmin && screen_co[0] < data->rect->xmax &&
- screen_co[1] > data->rect->ymin && screen_co[1] < data->rect->ymax)
- {
- return key_test_depth(data, co, screen_co);
- }
+ if (screen_co[0] > data->rect->xmin && screen_co[0] < data->rect->xmax &&
+ screen_co[1] > data->rect->ymin && screen_co[1] < data->rect->ymax) {
+ return key_test_depth(data, co, screen_co);
+ }
- return 0;
+ return 0;
}
static bool key_inside_test(PEData *data, const float co[3])
{
- if (data->mval)
- return key_inside_circle(data, data->rad, co, NULL);
- else
- return key_inside_rect(data, co);
+ if (data->mval)
+ return key_inside_circle(data, data->rad, co, NULL);
+ else
+ return key_inside_rect(data, co);
}
static bool point_is_selected(PTCacheEditPoint *point)
{
- KEY_K;
+ KEY_K;
- if (point->flag & PEP_HIDE)
- return 0;
+ if (point->flag & PEP_HIDE)
+ return 0;
- LOOP_SELECTED_KEYS {
- return 1;
- }
+ LOOP_SELECTED_KEYS
+ {
+ return 1;
+ }
- return 0;
+ return 0;
}
/*************************** iterators *******************************/
-typedef void (*ForPointFunc)(
- PEData *data,
- int point_index);
-typedef void (*ForHitPointFunc)(
- PEData *data,
- int point_index,
- float mouse_distance);
-
-typedef void (*ForKeyFunc)(
- PEData *data,
- int point_index,
- int key_index,
- bool is_inside);
-
-typedef void (*ForKeyMatFunc)(
- PEData *data,
- float mat[4][4],
- float imat[4][4],
- int point_index,
- int key_index,
- PTCacheEditKey *key);
-typedef void (*ForHitKeyMatFunc)(
- PEData *data,
- float mat[4][4],
- float imat[4][4],
- int point_index,
- int key_index,
- PTCacheEditKey *key,
- float mouse_distance);
+typedef void (*ForPointFunc)(PEData *data, int point_index);
+typedef void (*ForHitPointFunc)(PEData *data, int point_index, float mouse_distance);
+
+typedef void (*ForKeyFunc)(PEData *data, int point_index, int key_index, bool is_inside);
+
+typedef void (*ForKeyMatFunc)(PEData *data,
+ float mat[4][4],
+ float imat[4][4],
+ int point_index,
+ int key_index,
+ PTCacheEditKey *key);
+typedef void (*ForHitKeyMatFunc)(PEData *data,
+ float mat[4][4],
+ float imat[4][4],
+ int point_index,
+ int key_index,
+ PTCacheEditKey *key,
+ float mouse_distance);
enum eParticleSelectFlag {
- PSEL_NEAREST = (1 << 0),
- PSEL_ALL_KEYS = (1 << 1),
+ PSEL_NEAREST = (1 << 0),
+ PSEL_ALL_KEYS = (1 << 1),
};
static void for_mouse_hit_keys(PEData *data, ForKeyFunc func, const enum eParticleSelectFlag flag)
{
- ParticleEditSettings *pset = PE_settings(data->scene);
- PTCacheEdit *edit = data->edit;
- POINT_P; KEY_K;
- int nearest_point, nearest_key;
- float dist = data->rad;
-
- /* in path select mode we have no keys */
- if (pset->selectmode == SCE_SELECT_PATH)
- return;
-
- nearest_point = -1;
- nearest_key = -1;
-
- LOOP_VISIBLE_POINTS {
- if (pset->selectmode == SCE_SELECT_END) {
- if (point->totkey) {
- /* only do end keys */
- key = point->keys + point->totkey - 1;
-
- if (flag & PSEL_NEAREST) {
- if (key_inside_circle(data, dist, KEY_WCO, &dist)) {
- nearest_point = p;
- nearest_key = point->totkey - 1;
- }
- }
- else {
- const bool is_inside = key_inside_test(data, KEY_WCO);
- if (is_inside || (flag & PSEL_ALL_KEYS)) {
- func(data, p, point->totkey - 1, is_inside);
- }
- }
- }
- }
- else {
- /* do all keys */
- LOOP_VISIBLE_KEYS {
- if (flag & PSEL_NEAREST) {
- if (key_inside_circle(data, dist, KEY_WCO, &dist)) {
- nearest_point = p;
- nearest_key = k;
- }
- }
- else {
- const bool is_inside = key_inside_test(data, KEY_WCO);
- if (is_inside || (flag & PSEL_ALL_KEYS)) {
- func(data, p, k, is_inside);
- }
- }
- }
- }
- }
-
- /* do nearest only */
- if (flag & PSEL_NEAREST) {
- if (nearest_point != -1) {
- func(data, nearest_point, nearest_key, true);
- }
- }
+ ParticleEditSettings *pset = PE_settings(data->scene);
+ PTCacheEdit *edit = data->edit;
+ POINT_P;
+ KEY_K;
+ int nearest_point, nearest_key;
+ float dist = data->rad;
+
+ /* in path select mode we have no keys */
+ if (pset->selectmode == SCE_SELECT_PATH)
+ return;
+
+ nearest_point = -1;
+ nearest_key = -1;
+
+ LOOP_VISIBLE_POINTS
+ {
+ if (pset->selectmode == SCE_SELECT_END) {
+ if (point->totkey) {
+ /* only do end keys */
+ key = point->keys + point->totkey - 1;
+
+ if (flag & PSEL_NEAREST) {
+ if (key_inside_circle(data, dist, KEY_WCO, &dist)) {
+ nearest_point = p;
+ nearest_key = point->totkey - 1;
+ }
+ }
+ else {
+ const bool is_inside = key_inside_test(data, KEY_WCO);
+ if (is_inside || (flag & PSEL_ALL_KEYS)) {
+ func(data, p, point->totkey - 1, is_inside);
+ }
+ }
+ }
+ }
+ else {
+ /* do all keys */
+ LOOP_VISIBLE_KEYS
+ {
+ if (flag & PSEL_NEAREST) {
+ if (key_inside_circle(data, dist, KEY_WCO, &dist)) {
+ nearest_point = p;
+ nearest_key = k;
+ }
+ }
+ else {
+ const bool is_inside = key_inside_test(data, KEY_WCO);
+ if (is_inside || (flag & PSEL_ALL_KEYS)) {
+ func(data, p, k, is_inside);
+ }
+ }
+ }
+ }
+ }
+
+ /* do nearest only */
+ if (flag & PSEL_NEAREST) {
+ if (nearest_point != -1) {
+ func(data, nearest_point, nearest_key, true);
+ }
+ }
}
static void foreach_mouse_hit_point(PEData *data, ForHitPointFunc func, int selected)
{
- ParticleEditSettings *pset = PE_settings(data->scene);
- PTCacheEdit *edit = data->edit;
- POINT_P; KEY_K;
-
- /* all is selected in path mode */
- if (pset->selectmode == SCE_SELECT_PATH)
- selected = 0;
-
- LOOP_VISIBLE_POINTS {
- if (pset->selectmode == SCE_SELECT_END) {
- if (point->totkey) {
- /* only do end keys */
- key = point->keys + point->totkey - 1;
-
- if (selected == 0 || key->flag & PEK_SELECT) {
- float mouse_distance;
- if (key_inside_circle(data, data->rad, KEY_WCO, &mouse_distance)) {
- func(data, p, mouse_distance);
- }
- }
- }
- }
- else {
- /* do all keys */
- LOOP_VISIBLE_KEYS {
- if (selected == 0 || key->flag & PEK_SELECT) {
- float mouse_distance;
- if (key_inside_circle(data, data->rad, KEY_WCO, &mouse_distance)) {
- func(data, p, mouse_distance);
- break;
- }
- }
- }
- }
- }
+ ParticleEditSettings *pset = PE_settings(data->scene);
+ PTCacheEdit *edit = data->edit;
+ POINT_P;
+ KEY_K;
+
+ /* all is selected in path mode */
+ if (pset->selectmode == SCE_SELECT_PATH)
+ selected = 0;
+
+ LOOP_VISIBLE_POINTS
+ {
+ if (pset->selectmode == SCE_SELECT_END) {
+ if (point->totkey) {
+ /* only do end keys */
+ key = point->keys + point->totkey - 1;
+
+ if (selected == 0 || key->flag & PEK_SELECT) {
+ float mouse_distance;
+ if (key_inside_circle(data, data->rad, KEY_WCO, &mouse_distance)) {
+ func(data, p, mouse_distance);
+ }
+ }
+ }
+ }
+ else {
+ /* do all keys */
+ LOOP_VISIBLE_KEYS
+ {
+ if (selected == 0 || key->flag & PEK_SELECT) {
+ float mouse_distance;
+ if (key_inside_circle(data, data->rad, KEY_WCO, &mouse_distance)) {
+ func(data, p, mouse_distance);
+ break;
+ }
+ }
+ }
+ }
+ }
}
typedef struct KeyIterData {
- PEData *data;
- PTCacheEdit *edit;
- int selected;
- ForHitKeyMatFunc func;
+ PEData *data;
+ PTCacheEdit *edit;
+ int selected;
+ ForHitKeyMatFunc func;
} KeyIterData;
-static void foreach_mouse_hit_key_iter(
- void *__restrict iter_data_v,
- const int iter,
- const ParallelRangeTLS *__restrict UNUSED(tls))
-{
- KeyIterData *iter_data = (KeyIterData *)iter_data_v;
- PEData *data = iter_data->data;
- PTCacheEdit *edit = data->edit;
- PTCacheEditPoint *point = &edit->points[iter];
- if (point->flag & PEP_HIDE) {
- return;
- }
- ParticleSystem *psys = edit->psys;
- ParticleSystemModifierData *psmd_eval = iter_data->edit->psmd_eval;
- ParticleEditSettings *pset = PE_settings(data->scene);
- const int selected = iter_data->selected;
- float mat[4][4], imat[4][4];
- unit_m4(mat);
- unit_m4(imat);
- if (pset->selectmode == SCE_SELECT_END) {
- if (point->totkey) {
- /* only do end keys */
- PTCacheEditKey *key = point->keys + point->totkey - 1;
-
- if (selected == 0 || key->flag & PEK_SELECT) {
- float mouse_distance;
- if (key_inside_circle(data, data->rad, KEY_WCO, &mouse_distance)) {
- if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
- psys_mat_hair_to_global(data->ob, psmd_eval->mesh_final, psys->part->from, psys->particles + iter, mat);
- invert_m4_m4(imat, mat);
- }
- iter_data->func(data, mat, imat, iter, point->totkey - 1, key, mouse_distance);
- }
- }
- }
- }
- else {
- /* do all keys */
- PTCacheEditKey *key;
- int k;
- LOOP_VISIBLE_KEYS {
- if (selected == 0 || key->flag & PEK_SELECT) {
- float mouse_distance;
- if (key_inside_circle(data, data->rad, KEY_WCO, &mouse_distance)) {
- if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
- psys_mat_hair_to_global(data->ob, psmd_eval->mesh_final, psys->part->from, psys->particles + iter, mat);
- invert_m4_m4(imat, mat);
- }
- iter_data->func(data, mat, imat, iter, k, key, mouse_distance);
- }
- }
- }
- }
+static void foreach_mouse_hit_key_iter(void *__restrict iter_data_v,
+ const int iter,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ KeyIterData *iter_data = (KeyIterData *)iter_data_v;
+ PEData *data = iter_data->data;
+ PTCacheEdit *edit = data->edit;
+ PTCacheEditPoint *point = &edit->points[iter];
+ if (point->flag & PEP_HIDE) {
+ return;
+ }
+ ParticleSystem *psys = edit->psys;
+ ParticleSystemModifierData *psmd_eval = iter_data->edit->psmd_eval;
+ ParticleEditSettings *pset = PE_settings(data->scene);
+ const int selected = iter_data->selected;
+ float mat[4][4], imat[4][4];
+ unit_m4(mat);
+ unit_m4(imat);
+ if (pset->selectmode == SCE_SELECT_END) {
+ if (point->totkey) {
+ /* only do end keys */
+ PTCacheEditKey *key = point->keys + point->totkey - 1;
+
+ if (selected == 0 || key->flag & PEK_SELECT) {
+ float mouse_distance;
+ if (key_inside_circle(data, data->rad, KEY_WCO, &mouse_distance)) {
+ if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
+ psys_mat_hair_to_global(
+ data->ob, psmd_eval->mesh_final, psys->part->from, psys->particles + iter, mat);
+ invert_m4_m4(imat, mat);
+ }
+ iter_data->func(data, mat, imat, iter, point->totkey - 1, key, mouse_distance);
+ }
+ }
+ }
+ }
+ else {
+ /* do all keys */
+ PTCacheEditKey *key;
+ int k;
+ LOOP_VISIBLE_KEYS
+ {
+ if (selected == 0 || key->flag & PEK_SELECT) {
+ float mouse_distance;
+ if (key_inside_circle(data, data->rad, KEY_WCO, &mouse_distance)) {
+ if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
+ psys_mat_hair_to_global(
+ data->ob, psmd_eval->mesh_final, psys->part->from, psys->particles + iter, mat);
+ invert_m4_m4(imat, mat);
+ }
+ iter_data->func(data, mat, imat, iter, k, key, mouse_distance);
+ }
+ }
+ }
+ }
}
static void foreach_mouse_hit_key(PEData *data, ForHitKeyMatFunc func, int selected)
{
- PTCacheEdit *edit = data->edit;
- ParticleEditSettings *pset = PE_settings(data->scene);
- /* all is selected in path mode */
- if (pset->selectmode == SCE_SELECT_PATH) {
- selected = 0;
- }
+ PTCacheEdit *edit = data->edit;
+ ParticleEditSettings *pset = PE_settings(data->scene);
+ /* all is selected in path mode */
+ if (pset->selectmode == SCE_SELECT_PATH) {
+ selected = 0;
+ }
- KeyIterData iter_data;
- iter_data.data = data;
- iter_data.edit = edit;
- iter_data.selected = selected;
- iter_data.func = func;
+ KeyIterData iter_data;
+ iter_data.data = data;
+ iter_data.edit = edit;
+ iter_data.selected = selected;
+ iter_data.func = func;
- ParallelRangeSettings 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);
+ ParallelRangeSettings 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);
}
static void foreach_selected_point(PEData *data, ForPointFunc func)
{
- PTCacheEdit *edit = data->edit;
- POINT_P;
+ PTCacheEdit *edit = data->edit;
+ POINT_P;
- LOOP_SELECTED_POINTS {
- func(data, p);
- }
+ LOOP_SELECTED_POINTS
+ {
+ func(data, p);
+ }
}
static void foreach_selected_key(PEData *data, ForKeyFunc func)
{
- PTCacheEdit *edit = data->edit;
- POINT_P; KEY_K;
+ PTCacheEdit *edit = data->edit;
+ POINT_P;
+ KEY_K;
- LOOP_VISIBLE_POINTS {
- LOOP_SELECTED_KEYS {
- func(data, p, k, true);
- }
- }
+ LOOP_VISIBLE_POINTS
+ {
+ LOOP_SELECTED_KEYS
+ {
+ func(data, p, k, true);
+ }
+ }
}
static void foreach_point(PEData *data, ForPointFunc func)
{
- PTCacheEdit *edit = data->edit;
- POINT_P;
+ PTCacheEdit *edit = data->edit;
+ POINT_P;
- LOOP_POINTS {
- func(data, p);
- }
+ LOOP_POINTS
+ {
+ func(data, p);
+ }
}
static int count_selected_keys(Scene *scene, PTCacheEdit *edit)
{
- ParticleEditSettings *pset = PE_settings(scene);
- POINT_P; KEY_K;
- int sel = 0;
-
- LOOP_VISIBLE_POINTS {
- if (pset->selectmode == SCE_SELECT_POINT) {
- LOOP_SELECTED_KEYS {
- sel++;
- }
- }
- else if (pset->selectmode == SCE_SELECT_END) {
- if (point->totkey) {
- key = point->keys + point->totkey - 1;
- if (key->flag & PEK_SELECT)
- sel++;
- }
- }
- }
-
- return sel;
+ ParticleEditSettings *pset = PE_settings(scene);
+ POINT_P;
+ KEY_K;
+ int sel = 0;
+
+ LOOP_VISIBLE_POINTS
+ {
+ if (pset->selectmode == SCE_SELECT_POINT) {
+ LOOP_SELECTED_KEYS
+ {
+ sel++;
+ }
+ }
+ else if (pset->selectmode == SCE_SELECT_END) {
+ if (point->totkey) {
+ key = point->keys + point->totkey - 1;
+ if (key->flag & PEK_SELECT)
+ sel++;
+ }
+ }
+ }
+
+ return sel;
}
/************************************************/
-/* Particle Edit Mirroring */
+/* Particle Edit Mirroring */
/************************************************/
static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
{
- PTCacheEdit *edit;
- ParticleSystemModifierData *psmd_eval;
- KDTree_3d *tree;
- KDTreeNearest_3d nearest;
- HairKey *key;
- PARTICLE_P;
- float mat[4][4], co[3];
- int index, totpart;
-
- edit = psys->edit;
- psmd_eval = edit->psmd_eval;
- totpart = psys->totpart;
-
- if (!psmd_eval->mesh_final)
- return;
-
- tree = BLI_kdtree_3d_new(totpart);
-
- /* insert particles into kd tree */
- LOOP_PARTICLES {
- key = pa->hair;
- psys_mat_hair_to_orco(ob, psmd_eval->mesh_final, psys->part->from, pa, mat);
- copy_v3_v3(co, key->co);
- mul_m4_v3(mat, co);
- BLI_kdtree_3d_insert(tree, p, co);
- }
-
- BLI_kdtree_3d_balance(tree);
-
- /* lookup particles and set in mirror cache */
- if (!edit->mirror_cache)
- edit->mirror_cache = MEM_callocN(sizeof(int) * totpart, "PE mirror cache");
-
- LOOP_PARTICLES {
- key = pa->hair;
- psys_mat_hair_to_orco(ob, psmd_eval->mesh_final, psys->part->from, pa, mat);
- copy_v3_v3(co, key->co);
- mul_m4_v3(mat, co);
- co[0] = -co[0];
-
- index = BLI_kdtree_3d_find_nearest(tree, co, &nearest);
-
- /* this needs a custom threshold still, duplicated for editmode mirror */
- if (index != -1 && index != p && (nearest.dist <= 0.0002f))
- edit->mirror_cache[p] = index;
- else
- edit->mirror_cache[p] = -1;
- }
-
- /* make sure mirrors are in two directions */
- LOOP_PARTICLES {
- if (edit->mirror_cache[p]) {
- index = edit->mirror_cache[p];
- if (edit->mirror_cache[index] != p)
- edit->mirror_cache[p] = -1;
- }
- }
-
- BLI_kdtree_3d_free(tree);
-}
-
-static void PE_mirror_particle(Object *ob, Mesh *mesh, ParticleSystem *psys, ParticleData *pa, ParticleData *mpa)
-{
- HairKey *hkey, *mhkey;
- PTCacheEditPoint *point, *mpoint;
- PTCacheEditKey *key, *mkey;
- PTCacheEdit *edit;
- float mat[4][4], mmat[4][4], immat[4][4];
- int i, mi, k;
-
- edit = psys->edit;
- i = pa - psys->particles;
-
- /* find mirrored particle if needed */
- if (!mpa) {
- if (!edit->mirror_cache)
- PE_update_mirror_cache(ob, psys);
-
- if (!edit->mirror_cache)
- return; /* something went wrong! */
-
- mi = edit->mirror_cache[i];
- if (mi == -1)
- return;
- mpa = psys->particles + mi;
- }
- else
- mi = mpa - psys->particles;
-
- point = edit->points + i;
- mpoint = edit->points + mi;
-
- /* make sure they have the same amount of keys */
- if (pa->totkey != mpa->totkey) {
- if (mpa->hair) MEM_freeN(mpa->hair);
- if (mpoint->keys) MEM_freeN(mpoint->keys);
-
- mpa->hair = MEM_dupallocN(pa->hair);
- mpa->totkey = pa->totkey;
- mpoint->keys = MEM_dupallocN(point->keys);
- mpoint->totkey = point->totkey;
-
- mhkey = mpa->hair;
- mkey = mpoint->keys;
- for (k = 0; k < mpa->totkey; k++, mkey++, mhkey++) {
- mkey->co = mhkey->co;
- mkey->time = &mhkey->time;
- mkey->flag &= ~PEK_SELECT;
- }
- }
-
- /* mirror positions and tags */
- psys_mat_hair_to_orco(ob, mesh, psys->part->from, pa, mat);
- psys_mat_hair_to_orco(ob, mesh, psys->part->from, mpa, mmat);
- invert_m4_m4(immat, mmat);
-
- hkey = pa->hair;
- mhkey = mpa->hair;
- key = point->keys;
- mkey = mpoint->keys;
- for (k = 0; k < pa->totkey; k++, hkey++, mhkey++, key++, mkey++) {
- copy_v3_v3(mhkey->co, hkey->co);
- mul_m4_v3(mat, mhkey->co);
- mhkey->co[0] = -mhkey->co[0];
- mul_m4_v3(immat, mhkey->co);
-
- if (key->flag & PEK_TAG)
- mkey->flag |= PEK_TAG;
-
- mkey->length = key->length;
- }
-
- if (point->flag & PEP_TAG)
- mpoint->flag |= PEP_TAG;
- if (point->flag & PEP_EDIT_RECALC)
- mpoint->flag |= PEP_EDIT_RECALC;
+ PTCacheEdit *edit;
+ ParticleSystemModifierData *psmd_eval;
+ KDTree_3d *tree;
+ KDTreeNearest_3d nearest;
+ HairKey *key;
+ PARTICLE_P;
+ float mat[4][4], co[3];
+ int index, totpart;
+
+ edit = psys->edit;
+ psmd_eval = edit->psmd_eval;
+ totpart = psys->totpart;
+
+ if (!psmd_eval->mesh_final)
+ return;
+
+ tree = BLI_kdtree_3d_new(totpart);
+
+ /* insert particles into kd tree */
+ LOOP_PARTICLES
+ {
+ key = pa->hair;
+ psys_mat_hair_to_orco(ob, psmd_eval->mesh_final, psys->part->from, pa, mat);
+ copy_v3_v3(co, key->co);
+ mul_m4_v3(mat, co);
+ BLI_kdtree_3d_insert(tree, p, co);
+ }
+
+ BLI_kdtree_3d_balance(tree);
+
+ /* lookup particles and set in mirror cache */
+ if (!edit->mirror_cache)
+ edit->mirror_cache = MEM_callocN(sizeof(int) * totpart, "PE mirror cache");
+
+ LOOP_PARTICLES
+ {
+ key = pa->hair;
+ psys_mat_hair_to_orco(ob, psmd_eval->mesh_final, psys->part->from, pa, mat);
+ copy_v3_v3(co, key->co);
+ mul_m4_v3(mat, co);
+ co[0] = -co[0];
+
+ index = BLI_kdtree_3d_find_nearest(tree, co, &nearest);
+
+ /* this needs a custom threshold still, duplicated for editmode mirror */
+ if (index != -1 && index != p && (nearest.dist <= 0.0002f))
+ edit->mirror_cache[p] = index;
+ else
+ edit->mirror_cache[p] = -1;
+ }
+
+ /* make sure mirrors are in two directions */
+ LOOP_PARTICLES
+ {
+ if (edit->mirror_cache[p]) {
+ index = edit->mirror_cache[p];
+ if (edit->mirror_cache[index] != p)
+ edit->mirror_cache[p] = -1;
+ }
+ }
+
+ BLI_kdtree_3d_free(tree);
+}
+
+static void PE_mirror_particle(
+ Object *ob, Mesh *mesh, ParticleSystem *psys, ParticleData *pa, ParticleData *mpa)
+{
+ HairKey *hkey, *mhkey;
+ PTCacheEditPoint *point, *mpoint;
+ PTCacheEditKey *key, *mkey;
+ PTCacheEdit *edit;
+ float mat[4][4], mmat[4][4], immat[4][4];
+ int i, mi, k;
+
+ edit = psys->edit;
+ i = pa - psys->particles;
+
+ /* find mirrored particle if needed */
+ if (!mpa) {
+ if (!edit->mirror_cache)
+ PE_update_mirror_cache(ob, psys);
+
+ if (!edit->mirror_cache)
+ return; /* something went wrong! */
+
+ mi = edit->mirror_cache[i];
+ if (mi == -1)
+ return;
+ mpa = psys->particles + mi;
+ }
+ else
+ mi = mpa - psys->particles;
+
+ point = edit->points + i;
+ mpoint = edit->points + mi;
+
+ /* make sure they have the same amount of keys */
+ if (pa->totkey != mpa->totkey) {
+ if (mpa->hair)
+ MEM_freeN(mpa->hair);
+ if (mpoint->keys)
+ MEM_freeN(mpoint->keys);
+
+ mpa->hair = MEM_dupallocN(pa->hair);
+ mpa->totkey = pa->totkey;
+ mpoint->keys = MEM_dupallocN(point->keys);
+ mpoint->totkey = point->totkey;
+
+ mhkey = mpa->hair;
+ mkey = mpoint->keys;
+ for (k = 0; k < mpa->totkey; k++, mkey++, mhkey++) {
+ mkey->co = mhkey->co;
+ mkey->time = &mhkey->time;
+ mkey->flag &= ~PEK_SELECT;
+ }
+ }
+
+ /* mirror positions and tags */
+ psys_mat_hair_to_orco(ob, mesh, psys->part->from, pa, mat);
+ psys_mat_hair_to_orco(ob, mesh, psys->part->from, mpa, mmat);
+ invert_m4_m4(immat, mmat);
+
+ hkey = pa->hair;
+ mhkey = mpa->hair;
+ key = point->keys;
+ mkey = mpoint->keys;
+ for (k = 0; k < pa->totkey; k++, hkey++, mhkey++, key++, mkey++) {
+ copy_v3_v3(mhkey->co, hkey->co);
+ mul_m4_v3(mat, mhkey->co);
+ mhkey->co[0] = -mhkey->co[0];
+ mul_m4_v3(immat, mhkey->co);
+
+ if (key->flag & PEK_TAG)
+ mkey->flag |= PEK_TAG;
+
+ mkey->length = key->length;
+ }
+
+ if (point->flag & PEP_TAG)
+ mpoint->flag |= PEP_TAG;
+ if (point->flag & PEP_EDIT_RECALC)
+ mpoint->flag |= PEP_EDIT_RECALC;
}
static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
{
- PTCacheEdit *edit;
- ParticleSystemModifierData *psmd_eval;
- POINT_P;
+ PTCacheEdit *edit;
+ ParticleSystemModifierData *psmd_eval;
+ POINT_P;
- if (!psys)
- return;
+ if (!psys)
+ return;
- edit = psys->edit;
- psmd_eval = edit->psmd_eval;
+ edit = psys->edit;
+ psmd_eval = edit->psmd_eval;
- if (!psmd_eval->mesh_final)
- return;
+ if (!psmd_eval->mesh_final)
+ return;
- if (!edit->mirror_cache)
- PE_update_mirror_cache(ob, psys);
+ if (!edit->mirror_cache)
+ PE_update_mirror_cache(ob, psys);
- if (!edit->mirror_cache)
- return; /* something went wrong */
+ if (!edit->mirror_cache)
+ return; /* something went wrong */
- /* we delay settings the PARS_EDIT_RECALC for mirrored particles
- * to avoid doing mirror twice */
- LOOP_POINTS {
- if (point->flag & PEP_EDIT_RECALC) {
- PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL);
+ /* we delay settings the PARS_EDIT_RECALC for mirrored particles
+ * to avoid doing mirror twice */
+ LOOP_POINTS
+ {
+ if (point->flag & PEP_EDIT_RECALC) {
+ PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL);
- if (edit->mirror_cache[p] != -1)
- edit->points[edit->mirror_cache[p]].flag &= ~PEP_EDIT_RECALC;
- }
- }
+ if (edit->mirror_cache[p] != -1)
+ edit->points[edit->mirror_cache[p]].flag &= ~PEP_EDIT_RECALC;
+ }
+ }
- LOOP_POINTS {
- if (point->flag & PEP_EDIT_RECALC)
- if (edit->mirror_cache[p] != -1)
- edit->points[edit->mirror_cache[p]].flag |= PEP_EDIT_RECALC;
- }
+ LOOP_POINTS
+ {
+ if (point->flag & PEP_EDIT_RECALC)
+ if (edit->mirror_cache[p] != -1)
+ edit->points[edit->mirror_cache[p]].flag |= PEP_EDIT_RECALC;
+ }
}
/************************************************/
-/* Edit Calculation */
+/* Edit Calculation */
/************************************************/
typedef struct DeflectEmitterIter {
- Object *object;
- ParticleSystem *psys;
- PTCacheEdit *edit;
- float dist;
- float emitterdist;
+ Object *object;
+ ParticleSystem *psys;
+ PTCacheEdit *edit;
+ float dist;
+ float emitterdist;
} DeflectEmitterIter;
-static void deflect_emitter_iter(
- void *__restrict iter_data_v,
- const int iter,
- const ParallelRangeTLS *__restrict UNUSED(tls))
-{
- DeflectEmitterIter *iter_data = (DeflectEmitterIter *)iter_data_v;
- PTCacheEdit *edit = iter_data->edit;
- PTCacheEditPoint *point = &edit->points[iter];
- if ((point->flag & PEP_EDIT_RECALC) == 0) {
- return;
- }
- Object *object = iter_data->object;
- ParticleSystem *psys = iter_data->psys;
- ParticleSystemModifierData *psmd_eval = iter_data->edit->psmd_eval;
- PTCacheEditKey *key;
- int k;
- float hairimat[4][4], hairmat[4][4];
- int index;
- float *vec, *nor, dvec[3], dot, dist_1st = 0.0f;
- const float dist = iter_data->dist;
- const float emitterdist = iter_data->emitterdist;
- psys_mat_hair_to_object(object,
- psmd_eval->mesh_final,
- psys->part->from,
- psys->particles + iter,
- hairmat);
-
- LOOP_KEYS {
- mul_m4_v3(hairmat, key->co);
- }
-
- LOOP_KEYS {
- if (k == 0) {
- dist_1st = len_v3v3((key + 1)->co, key->co);
- dist_1st *= dist * emitterdist;
- }
- else {
- index = BLI_kdtree_3d_find_nearest(edit->emitter_field, key->co, NULL);
-
- vec = edit->emitter_cosnos + index * 6;
- nor = vec + 3;
-
- sub_v3_v3v3(dvec, key->co, vec);
-
- dot = dot_v3v3(dvec, nor);
- copy_v3_v3(dvec, nor);
-
- if (dot > 0.0f) {
- if (dot < dist_1st) {
- normalize_v3(dvec);
- mul_v3_fl(dvec, dist_1st - dot);
- add_v3_v3(key->co, dvec);
- }
- }
- else {
- normalize_v3(dvec);
- mul_v3_fl(dvec, dist_1st - dot);
- add_v3_v3(key->co, dvec);
- }
- if (k == 1) {
- dist_1st *= 1.3333f;
- }
- }
- }
-
- invert_m4_m4(hairimat, hairmat);
-
- LOOP_KEYS {
- mul_m4_v3(hairimat, key->co);
- }
+static void deflect_emitter_iter(void *__restrict iter_data_v,
+ const int iter,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ DeflectEmitterIter *iter_data = (DeflectEmitterIter *)iter_data_v;
+ PTCacheEdit *edit = iter_data->edit;
+ PTCacheEditPoint *point = &edit->points[iter];
+ if ((point->flag & PEP_EDIT_RECALC) == 0) {
+ return;
+ }
+ Object *object = iter_data->object;
+ ParticleSystem *psys = iter_data->psys;
+ ParticleSystemModifierData *psmd_eval = iter_data->edit->psmd_eval;
+ PTCacheEditKey *key;
+ int k;
+ float hairimat[4][4], hairmat[4][4];
+ int index;
+ float *vec, *nor, dvec[3], dot, dist_1st = 0.0f;
+ const float dist = iter_data->dist;
+ const float emitterdist = iter_data->emitterdist;
+ psys_mat_hair_to_object(
+ object, psmd_eval->mesh_final, psys->part->from, psys->particles + iter, hairmat);
+
+ LOOP_KEYS
+ {
+ mul_m4_v3(hairmat, key->co);
+ }
+
+ LOOP_KEYS
+ {
+ if (k == 0) {
+ dist_1st = len_v3v3((key + 1)->co, key->co);
+ dist_1st *= dist * emitterdist;
+ }
+ else {
+ index = BLI_kdtree_3d_find_nearest(edit->emitter_field, key->co, NULL);
+
+ vec = edit->emitter_cosnos + index * 6;
+ nor = vec + 3;
+
+ sub_v3_v3v3(dvec, key->co, vec);
+
+ dot = dot_v3v3(dvec, nor);
+ copy_v3_v3(dvec, nor);
+
+ if (dot > 0.0f) {
+ if (dot < dist_1st) {
+ normalize_v3(dvec);
+ mul_v3_fl(dvec, dist_1st - dot);
+ add_v3_v3(key->co, dvec);
+ }
+ }
+ else {
+ normalize_v3(dvec);
+ mul_v3_fl(dvec, dist_1st - dot);
+ add_v3_v3(key->co, dvec);
+ }
+ if (k == 1) {
+ dist_1st *= 1.3333f;
+ }
+ }
+ }
+
+ invert_m4_m4(hairimat, hairmat);
+
+ LOOP_KEYS
+ {
+ mul_m4_v3(hairimat, key->co);
+ }
}
/* tries to stop edited particles from going through the emitter's surface */
static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit)
{
- ParticleEditSettings *pset = PE_settings(scene);
- ParticleSystem *psys;
- const float dist = ED_view3d_select_dist_px() * 0.01f;
+ ParticleEditSettings *pset = PE_settings(scene);
+ ParticleSystem *psys;
+ const float dist = ED_view3d_select_dist_px() * 0.01f;
- if (edit == NULL || edit->psys == NULL ||
- (pset->flag & PE_DEFLECT_EMITTER) == 0 ||
- (edit->psys->flag & PSYS_GLOBAL_HAIR))
- {
- return;
- }
+ if (edit == NULL || edit->psys == NULL || (pset->flag & PE_DEFLECT_EMITTER) == 0 ||
+ (edit->psys->flag & PSYS_GLOBAL_HAIR)) {
+ return;
+ }
- psys = edit->psys;
+ psys = edit->psys;
- if (!edit->psmd_eval->mesh_final) {
- return;
- }
+ if (!edit->psmd_eval->mesh_final) {
+ return;
+ }
- DeflectEmitterIter iter_data;
- iter_data.object = ob;
- iter_data.psys = psys;
- iter_data.edit = edit;
- iter_data.dist = dist;
- iter_data.emitterdist = pset->emitterdist;
+ DeflectEmitterIter iter_data;
+ iter_data.object = ob;
+ iter_data.psys = psys;
+ iter_data.edit = edit;
+ iter_data.dist = dist;
+ iter_data.emitterdist = pset->emitterdist;
- ParallelRangeSettings 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);
+ ParallelRangeSettings 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);
}
typedef struct ApplyLengthsIterData {
- PTCacheEdit *edit;
+ PTCacheEdit *edit;
} ApplyLengthsIterData;
-static void apply_lengths_iter(
- void *__restrict iter_data_v,
- const int iter,
- const ParallelRangeTLS *__restrict UNUSED(tls))
-{
- ApplyLengthsIterData *iter_data = (ApplyLengthsIterData *)iter_data_v;
- PTCacheEdit *edit = iter_data->edit;
- PTCacheEditPoint *point = &edit->points[iter];
- if ((point->flag & PEP_EDIT_RECALC) == 0) {
- return;
- }
- PTCacheEditKey *key;
- int k;
- LOOP_KEYS {
- if (k) {
- float dv1[3];
- sub_v3_v3v3(dv1, key->co, (key - 1)->co);
- normalize_v3(dv1);
- mul_v3_fl(dv1, (key - 1)->length);
- add_v3_v3v3(key->co, (key - 1)->co, dv1);
- }
- }
+static void apply_lengths_iter(void *__restrict iter_data_v,
+ const int iter,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ ApplyLengthsIterData *iter_data = (ApplyLengthsIterData *)iter_data_v;
+ PTCacheEdit *edit = iter_data->edit;
+ PTCacheEditPoint *point = &edit->points[iter];
+ if ((point->flag & PEP_EDIT_RECALC) == 0) {
+ return;
+ }
+ PTCacheEditKey *key;
+ int k;
+ LOOP_KEYS
+ {
+ if (k) {
+ float dv1[3];
+ sub_v3_v3v3(dv1, key->co, (key - 1)->co);
+ normalize_v3(dv1);
+ mul_v3_fl(dv1, (key - 1)->length);
+ add_v3_v3v3(key->co, (key - 1)->co, dv1);
+ }
+ }
}
/* force set distances between neighboring keys */
static void PE_apply_lengths(Scene *scene, PTCacheEdit *edit)
{
- ParticleEditSettings *pset = PE_settings(scene);
+ ParticleEditSettings *pset = PE_settings(scene);
- if (edit == 0 || (pset->flag & PE_KEEP_LENGTHS) == 0)
- return;
+ if (edit == 0 || (pset->flag & PE_KEEP_LENGTHS) == 0)
+ return;
- if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
- return;
+ if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
+ return;
- ApplyLengthsIterData iter_data;
- iter_data.edit = edit;
+ ApplyLengthsIterData iter_data;
+ iter_data.edit = edit;
- ParallelRangeSettings 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);
+ ParallelRangeSettings 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);
}
typedef struct IterateLengthsIterData {
- PTCacheEdit *edit;
- ParticleEditSettings *pset;
+ PTCacheEdit *edit;
+ ParticleEditSettings *pset;
} IterateLengthsIterData;
-static void iterate_lengths_iter(
- void *__restrict iter_data_v,
- const int iter,
- const ParallelRangeTLS *__restrict UNUSED(tls))
-{
- IterateLengthsIterData *iter_data = (IterateLengthsIterData *)iter_data_v;
- PTCacheEdit *edit = iter_data->edit;
- PTCacheEditPoint *point = &edit->points[iter];
- if ((point->flag & PEP_EDIT_RECALC) == 0) {
- return;
- }
- ParticleEditSettings *pset = iter_data->pset;
- float tlen;
- float dv0[3] = {0.0f, 0.0f, 0.0f};
- float dv1[3] = {0.0f, 0.0f, 0.0f};
- float dv2[3] = {0.0f, 0.0f, 0.0f};
- for (int j = 1; j < point->totkey; j++) {
- PTCacheEditKey *key;
- int k;
- float mul = 1.0f / (float)point->totkey;
- if (pset->flag & PE_LOCK_FIRST) {
- key = point->keys + 1;
- k = 1;
- dv1[0] = dv1[1] = dv1[2] = 0.0;
- }
- else {
- key = point->keys;
- k = 0;
- dv0[0] = dv0[1] = dv0[2] = 0.0;
- }
-
- for (; k < point->totkey; k++, key++) {
- if (k) {
- sub_v3_v3v3(dv0, (key - 1)->co, key->co);
- tlen = normalize_v3(dv0);
- mul_v3_fl(dv0, (mul * (tlen - (key - 1)->length)));
- }
- if (k < point->totkey - 1) {
- sub_v3_v3v3(dv2, (key + 1)->co, key->co);
- tlen = normalize_v3(dv2);
- mul_v3_fl(dv2, mul * (tlen - key->length));
- }
- if (k) {
- add_v3_v3((key - 1)->co, dv1);
- }
- add_v3_v3v3(dv1, dv0, dv2);
- }
- }
+static void iterate_lengths_iter(void *__restrict iter_data_v,
+ const int iter,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ IterateLengthsIterData *iter_data = (IterateLengthsIterData *)iter_data_v;
+ PTCacheEdit *edit = iter_data->edit;
+ PTCacheEditPoint *point = &edit->points[iter];
+ if ((point->flag & PEP_EDIT_RECALC) == 0) {
+ return;
+ }
+ ParticleEditSettings *pset = iter_data->pset;
+ float tlen;
+ float dv0[3] = {0.0f, 0.0f, 0.0f};
+ float dv1[3] = {0.0f, 0.0f, 0.0f};
+ float dv2[3] = {0.0f, 0.0f, 0.0f};
+ for (int j = 1; j < point->totkey; j++) {
+ PTCacheEditKey *key;
+ int k;
+ float mul = 1.0f / (float)point->totkey;
+ if (pset->flag & PE_LOCK_FIRST) {
+ key = point->keys + 1;
+ k = 1;
+ dv1[0] = dv1[1] = dv1[2] = 0.0;
+ }
+ else {
+ key = point->keys;
+ k = 0;
+ dv0[0] = dv0[1] = dv0[2] = 0.0;
+ }
+
+ for (; k < point->totkey; k++, key++) {
+ if (k) {
+ sub_v3_v3v3(dv0, (key - 1)->co, key->co);
+ tlen = normalize_v3(dv0);
+ mul_v3_fl(dv0, (mul * (tlen - (key - 1)->length)));
+ }
+ if (k < point->totkey - 1) {
+ sub_v3_v3v3(dv2, (key + 1)->co, key->co);
+ tlen = normalize_v3(dv2);
+ mul_v3_fl(dv2, mul * (tlen - key->length));
+ }
+ if (k) {
+ add_v3_v3((key - 1)->co, dv1);
+ }
+ add_v3_v3v3(dv1, dv0, dv2);
+ }
+ }
}
/* try to find a nice solution to keep distances between neighboring keys */
static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit)
{
- ParticleEditSettings *pset = PE_settings(scene);
- if (edit == 0 || (pset->flag & PE_KEEP_LENGTHS) == 0) {
- return;
- }
- if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) {
- return;
- }
+ ParticleEditSettings *pset = PE_settings(scene);
+ if (edit == 0 || (pset->flag & PE_KEEP_LENGTHS) == 0) {
+ return;
+ }
+ if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) {
+ return;
+ }
- IterateLengthsIterData iter_data;
- iter_data.edit = edit;
- iter_data.pset = pset;
+ IterateLengthsIterData iter_data;
+ iter_data.edit = edit;
+ iter_data.pset = pset;
- ParallelRangeSettings 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);
+ ParallelRangeSettings 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);
}
/* set current distances to be kept between neighbouting keys */
void recalc_lengths(PTCacheEdit *edit)
{
- POINT_P; KEY_K;
+ POINT_P;
+ KEY_K;
- if (edit == 0)
- return;
+ if (edit == 0)
+ return;
- LOOP_EDITED_POINTS {
- key = point->keys;
- for (k = 0; k < point->totkey - 1; k++, key++) {
- key->length = len_v3v3(key->co, (key + 1)->co);
- }
- }
+ LOOP_EDITED_POINTS
+ {
+ key = point->keys;
+ for (k = 0; k < point->totkey - 1; k++, key++) {
+ key->length = len_v3v3(key->co, (key + 1)->co);
+ }
+ }
}
/* calculate a tree for finding nearest emitter's vertice */
void recalc_emitter_field(Depsgraph *UNUSED(depsgraph), Object *UNUSED(ob), ParticleSystem *psys)
{
- PTCacheEdit *edit = psys->edit;
- Mesh *mesh = edit->psmd_eval->mesh_final;
- float *vec, *nor;
- int i, totface /*, totvert*/;
+ PTCacheEdit *edit = psys->edit;
+ Mesh *mesh = edit->psmd_eval->mesh_final;
+ float *vec, *nor;
+ int i, totface /*, totvert*/;
- if (!mesh)
- return;
+ if (!mesh)
+ return;
- if (edit->emitter_cosnos)
- MEM_freeN(edit->emitter_cosnos);
+ if (edit->emitter_cosnos)
+ MEM_freeN(edit->emitter_cosnos);
- BLI_kdtree_3d_free(edit->emitter_field);
+ BLI_kdtree_3d_free(edit->emitter_field);
- totface = mesh->totface;
- /*totvert=dm->getNumVerts(dm);*/ /*UNUSED*/
+ totface = mesh->totface;
+ /*totvert=dm->getNumVerts(dm);*/ /*UNUSED*/
- edit->emitter_cosnos = MEM_callocN(totface * 6 * sizeof(float), "emitter cosnos");
+ edit->emitter_cosnos = MEM_callocN(totface * 6 * sizeof(float), "emitter cosnos");
- edit->emitter_field = BLI_kdtree_3d_new(totface);
+ edit->emitter_field = BLI_kdtree_3d_new(totface);
- vec = edit->emitter_cosnos;
- nor = vec + 3;
+ vec = edit->emitter_cosnos;
+ nor = vec + 3;
- for (i = 0; i < totface; i++, vec += 6, nor += 6) {
- MFace *mface = &mesh->mface[i];
- MVert *mvert;
+ for (i = 0; i < totface; i++, vec += 6, nor += 6) {
+ MFace *mface = &mesh->mface[i];
+ MVert *mvert;
- mvert = &mesh->mvert[mface->v1];
- copy_v3_v3(vec, mvert->co);
- copy_v3fl_v3s(nor, mvert->no);
+ mvert = &mesh->mvert[mface->v1];
+ copy_v3_v3(vec, mvert->co);
+ copy_v3fl_v3s(nor, mvert->no);
- mvert = &mesh->mvert[mface->v2];
- add_v3_v3v3(vec, vec, mvert->co);
- add_v3fl_v3fl_v3s(nor, nor, mvert->no);
+ mvert = &mesh->mvert[mface->v2];
+ add_v3_v3v3(vec, vec, mvert->co);
+ add_v3fl_v3fl_v3s(nor, nor, mvert->no);
- mvert = &mesh->mvert[mface->v3];
- add_v3_v3v3(vec, vec, mvert->co);
- add_v3fl_v3fl_v3s(nor, nor, mvert->no);
+ mvert = &mesh->mvert[mface->v3];
+ add_v3_v3v3(vec, vec, mvert->co);
+ add_v3fl_v3fl_v3s(nor, nor, mvert->no);
- if (mface->v4) {
- mvert = &mesh->mvert[mface->v4];
- add_v3_v3v3(vec, vec, mvert->co);
- add_v3fl_v3fl_v3s(nor, nor, mvert->no);
+ if (mface->v4) {
+ mvert = &mesh->mvert[mface->v4];
+ add_v3_v3v3(vec, vec, mvert->co);
+ add_v3fl_v3fl_v3s(nor, nor, mvert->no);
- mul_v3_fl(vec, 0.25);
- }
- else {
- mul_v3_fl(vec, 1.0f / 3.0f);
- }
+ mul_v3_fl(vec, 0.25);
+ }
+ else {
+ mul_v3_fl(vec, 1.0f / 3.0f);
+ }
- normalize_v3(nor);
+ normalize_v3(nor);
- BLI_kdtree_3d_insert(edit->emitter_field, i, vec);
- }
+ BLI_kdtree_3d_insert(edit->emitter_field, i, vec);
+ }
- BLI_kdtree_3d_balance(edit->emitter_field);
+ BLI_kdtree_3d_balance(edit->emitter_field);
}
static void PE_update_selection(Depsgraph *depsgraph, Scene *scene, Object *ob, int useflag)
{
- PTCacheEdit *edit = PE_get_current(scene, ob);
- HairKey *hkey;
- POINT_P; KEY_K;
-
- /* flag all particles to be updated if not using flag */
- if (!useflag)
- LOOP_POINTS {
- point->flag |= PEP_EDIT_RECALC;
- }
-
- /* flush edit key flag to hair key flag to preserve selection
- * on save */
- if (edit->psys) {
- LOOP_POINTS {
- hkey = edit->psys->particles[p].hair;
- LOOP_KEYS {
- hkey->editflag = key->flag;
- hkey++;
- }
- }
- }
-
- psys_cache_edit_paths(depsgraph, scene, ob, edit, CFRA, G.is_rendering);
-
-
- /* disable update flag */
- LOOP_POINTS {
- point->flag &= ~PEP_EDIT_RECALC;
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_SELECT);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ HairKey *hkey;
+ POINT_P;
+ KEY_K;
+
+ /* flag all particles to be updated if not using flag */
+ if (!useflag)
+ LOOP_POINTS
+ {
+ point->flag |= PEP_EDIT_RECALC;
+ }
+
+ /* flush edit key flag to hair key flag to preserve selection
+ * on save */
+ if (edit->psys) {
+ LOOP_POINTS
+ {
+ hkey = edit->psys->particles[p].hair;
+ LOOP_KEYS
+ {
+ hkey->editflag = key->flag;
+ hkey++;
+ }
+ }
+ }
+
+ psys_cache_edit_paths(depsgraph, scene, ob, edit, CFRA, G.is_rendering);
+
+ /* disable update flag */
+ LOOP_POINTS
+ {
+ point->flag &= ~PEP_EDIT_RECALC;
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_SELECT);
}
void update_world_cos(Depsgraph *UNUSED(depsgraph), Object *ob, PTCacheEdit *edit)
{
- ParticleSystem *psys = edit->psys;
- ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
- POINT_P; KEY_K;
- float hairmat[4][4];
-
- if (psys == 0 || psys->edit == 0 || psmd_eval->mesh_final == NULL)
- return;
-
- LOOP_POINTS {
- if (!(psys->flag & PSYS_GLOBAL_HAIR))
- psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, hairmat);
-
- LOOP_KEYS {
- copy_v3_v3(key->world_co, key->co);
- if (!(psys->flag & PSYS_GLOBAL_HAIR))
- mul_m4_v3(hairmat, key->world_co);
- }
- }
+ ParticleSystem *psys = edit->psys;
+ ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
+ POINT_P;
+ KEY_K;
+ float hairmat[4][4];
+
+ if (psys == 0 || psys->edit == 0 || psmd_eval->mesh_final == NULL)
+ return;
+
+ LOOP_POINTS
+ {
+ if (!(psys->flag & PSYS_GLOBAL_HAIR))
+ psys_mat_hair_to_global(
+ ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, hairmat);
+
+ LOOP_KEYS
+ {
+ copy_v3_v3(key->world_co, key->co);
+ if (!(psys->flag & PSYS_GLOBAL_HAIR))
+ mul_m4_v3(hairmat, key->world_co);
+ }
+ }
}
static void update_velocities(PTCacheEdit *edit)
{
- /*TODO: get frs_sec properly */
- float vec1[3], vec2[3], frs_sec, dfra;
- POINT_P; KEY_K;
+ /*TODO: get frs_sec properly */
+ float vec1[3], vec2[3], frs_sec, dfra;
+ POINT_P;
+ KEY_K;
- /* hair doesn't use velocities */
- if (edit->psys || !edit->points || !edit->points->keys->vel)
- return;
+ /* hair doesn't use velocities */
+ if (edit->psys || !edit->points || !edit->points->keys->vel)
+ return;
- frs_sec = edit->pid.flag & PTCACHE_VEL_PER_SEC ? 25.0f : 1.0f;
+ frs_sec = edit->pid.flag & PTCACHE_VEL_PER_SEC ? 25.0f : 1.0f;
- LOOP_EDITED_POINTS {
- LOOP_KEYS {
- if (k == 0) {
- dfra = *(key + 1)->time - *key->time;
+ LOOP_EDITED_POINTS
+ {
+ LOOP_KEYS
+ {
+ if (k == 0) {
+ dfra = *(key + 1)->time - *key->time;
- if (dfra <= 0.0f)
- continue;
+ if (dfra <= 0.0f)
+ continue;
- sub_v3_v3v3(key->vel, (key + 1)->co, key->co);
+ sub_v3_v3v3(key->vel, (key + 1)->co, key->co);
- if (point->totkey > 2) {
- sub_v3_v3v3(vec1, (key + 1)->co, (key + 2)->co);
- project_v3_v3v3(vec2, vec1, key->vel);
- sub_v3_v3v3(vec2, vec1, vec2);
- madd_v3_v3fl(key->vel, vec2, 0.5f);
- }
- }
- else if (k == point->totkey - 1) {
- dfra = *key->time - *(key - 1)->time;
+ if (point->totkey > 2) {
+ sub_v3_v3v3(vec1, (key + 1)->co, (key + 2)->co);
+ project_v3_v3v3(vec2, vec1, key->vel);
+ sub_v3_v3v3(vec2, vec1, vec2);
+ madd_v3_v3fl(key->vel, vec2, 0.5f);
+ }
+ }
+ else if (k == point->totkey - 1) {
+ dfra = *key->time - *(key - 1)->time;
- if (dfra <= 0.0f)
- continue;
+ if (dfra <= 0.0f)
+ continue;
- sub_v3_v3v3(key->vel, key->co, (key - 1)->co);
+ sub_v3_v3v3(key->vel, key->co, (key - 1)->co);
- if (point->totkey > 2) {
- sub_v3_v3v3(vec1, (key - 2)->co, (key - 1)->co);
- project_v3_v3v3(vec2, vec1, key->vel);
- sub_v3_v3v3(vec2, vec1, vec2);
- madd_v3_v3fl(key->vel, vec2, 0.5f);
- }
- }
- else {
- dfra = *(key + 1)->time - *(key - 1)->time;
+ if (point->totkey > 2) {
+ sub_v3_v3v3(vec1, (key - 2)->co, (key - 1)->co);
+ project_v3_v3v3(vec2, vec1, key->vel);
+ sub_v3_v3v3(vec2, vec1, vec2);
+ madd_v3_v3fl(key->vel, vec2, 0.5f);
+ }
+ }
+ else {
+ dfra = *(key + 1)->time - *(key - 1)->time;
- if (dfra <= 0.0f)
- continue;
+ if (dfra <= 0.0f)
+ continue;
- sub_v3_v3v3(key->vel, (key + 1)->co, (key - 1)->co);
- }
- mul_v3_fl(key->vel, frs_sec / dfra);
- }
- }
+ sub_v3_v3v3(key->vel, (key + 1)->co, (key - 1)->co);
+ }
+ mul_v3_fl(key->vel, frs_sec / dfra);
+ }
+ }
}
void PE_update_object(Depsgraph *depsgraph, Scene *scene, Object *ob, int useflag)
{
- /* use this to do partial particle updates, not usable when adding or
- * removing, then a full redo is necessary and calling this may crash */
- ParticleEditSettings *pset = PE_settings(scene);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- POINT_P;
-
- if (!edit)
- return;
-
- /* flag all particles to be updated if not using flag */
- if (!useflag)
- LOOP_POINTS {
- point->flag |= PEP_EDIT_RECALC;
- }
-
- /* do post process on particle edit keys */
- pe_iterate_lengths(scene, edit);
- pe_deflect_emitter(scene, ob, edit);
- PE_apply_lengths(scene, edit);
- if (pe_x_mirror(ob))
- PE_apply_mirror(ob, edit->psys);
- if (edit->psys)
- update_world_cos(depsgraph, ob, edit);
- if (pset->flag & PE_AUTO_VELOCITY)
- update_velocities(edit);
- PE_hide_keys_time(scene, edit, CFRA);
-
- /* regenerate path caches */
- psys_cache_edit_paths(depsgraph, scene, ob, edit, CFRA, G.is_rendering);
-
- /* disable update flag */
- LOOP_POINTS {
- point->flag &= ~PEP_EDIT_RECALC;
- }
-
- if (edit->psys)
- edit->psys->flag &= ~PSYS_HAIR_UPDATED;
+ /* use this to do partial particle updates, not usable when adding or
+ * removing, then a full redo is necessary and calling this may crash */
+ ParticleEditSettings *pset = PE_settings(scene);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ POINT_P;
+
+ if (!edit)
+ return;
+
+ /* flag all particles to be updated if not using flag */
+ if (!useflag)
+ LOOP_POINTS
+ {
+ point->flag |= PEP_EDIT_RECALC;
+ }
+
+ /* do post process on particle edit keys */
+ pe_iterate_lengths(scene, edit);
+ pe_deflect_emitter(scene, ob, edit);
+ PE_apply_lengths(scene, edit);
+ if (pe_x_mirror(ob))
+ PE_apply_mirror(ob, edit->psys);
+ if (edit->psys)
+ update_world_cos(depsgraph, ob, edit);
+ if (pset->flag & PE_AUTO_VELOCITY)
+ update_velocities(edit);
+ PE_hide_keys_time(scene, edit, CFRA);
+
+ /* regenerate path caches */
+ psys_cache_edit_paths(depsgraph, scene, ob, edit, CFRA, G.is_rendering);
+
+ /* disable update flag */
+ LOOP_POINTS
+ {
+ point->flag &= ~PEP_EDIT_RECALC;
+ }
+
+ if (edit->psys)
+ edit->psys->flag &= ~PSYS_HAIR_UPDATED;
}
/************************************************/
-/* Edit Selections */
+/* Edit Selections */
/************************************************/
/*-----selection callbacks-----*/
static void select_key(PEData *data, int point_index, int key_index, bool UNUSED(is_inside))
{
- PTCacheEdit *edit = data->edit;
- PTCacheEditPoint *point = edit->points + point_index;
- PTCacheEditKey *key = point->keys + key_index;
+ PTCacheEdit *edit = data->edit;
+ PTCacheEditPoint *point = edit->points + point_index;
+ PTCacheEditKey *key = point->keys + key_index;
- if (data->select)
- key->flag |= PEK_SELECT;
- else
- key->flag &= ~PEK_SELECT;
+ if (data->select)
+ key->flag |= PEK_SELECT;
+ else
+ key->flag &= ~PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- data->is_changed = true;
+ point->flag |= PEP_EDIT_RECALC;
+ data->is_changed = true;
}
static void select_key_op(PEData *data, int point_index, int key_index, bool is_inside)
{
- PTCacheEdit *edit = data->edit;
- PTCacheEditPoint *point = edit->points + point_index;
- PTCacheEditKey *key = point->keys + key_index;
- const bool is_select = key->flag & PEK_SELECT;
- const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(key->flag, sel_op_result, PEK_SELECT);
- point->flag |= PEP_EDIT_RECALC;
- data->is_changed = true;
- }
+ PTCacheEdit *edit = data->edit;
+ PTCacheEditPoint *point = edit->points + point_index;
+ PTCacheEditKey *key = point->keys + key_index;
+ const bool is_select = key->flag & PEK_SELECT;
+ const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ SET_FLAG_FROM_TEST(key->flag, sel_op_result, PEK_SELECT);
+ point->flag |= PEP_EDIT_RECALC;
+ data->is_changed = true;
+ }
}
-static void select_keys(PEData *data, int point_index, int UNUSED(key_index), bool UNUSED(is_inside))
+static void select_keys(PEData *data,
+ int point_index,
+ int UNUSED(key_index),
+ bool UNUSED(is_inside))
{
- PTCacheEdit *edit = data->edit;
- PTCacheEditPoint *point = edit->points + point_index;
- KEY_K;
+ PTCacheEdit *edit = data->edit;
+ PTCacheEditPoint *point = edit->points + point_index;
+ KEY_K;
- LOOP_KEYS {
- if (data->select)
- key->flag |= PEK_SELECT;
- else
- key->flag &= ~PEK_SELECT;
- }
+ LOOP_KEYS
+ {
+ if (data->select)
+ key->flag |= PEK_SELECT;
+ else
+ key->flag &= ~PEK_SELECT;
+ }
- point->flag |= PEP_EDIT_RECALC;
+ point->flag |= PEP_EDIT_RECALC;
}
static void extend_key_select(PEData *data, int point_index, int key_index, bool UNUSED(is_inside))
{
- PTCacheEdit *edit = data->edit;
- PTCacheEditPoint *point = edit->points + point_index;
- PTCacheEditKey *key = point->keys + key_index;
+ PTCacheEdit *edit = data->edit;
+ PTCacheEditPoint *point = edit->points + point_index;
+ PTCacheEditKey *key = point->keys + key_index;
- if ((key->flag & PEK_SELECT) == 0) {
- key->flag |= PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- data->is_changed = true;
- }
+ if ((key->flag & PEK_SELECT) == 0) {
+ key->flag |= PEK_SELECT;
+ point->flag |= PEP_EDIT_RECALC;
+ data->is_changed = true;
+ }
}
-static void deselect_key_select(PEData *data, int point_index, int key_index, bool UNUSED(is_inside))
+static void deselect_key_select(PEData *data,
+ int point_index,
+ int key_index,
+ bool UNUSED(is_inside))
{
- PTCacheEdit *edit = data->edit;
- PTCacheEditPoint *point = edit->points + point_index;
- PTCacheEditKey *key = point->keys + key_index;
+ PTCacheEdit *edit = data->edit;
+ PTCacheEditPoint *point = edit->points + point_index;
+ PTCacheEditKey *key = point->keys + key_index;
- if ((key->flag & PEK_SELECT) != 0) {
- key->flag &= ~PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- data->is_changed = true;
- }
+ if ((key->flag & PEK_SELECT) != 0) {
+ key->flag &= ~PEK_SELECT;
+ point->flag |= PEP_EDIT_RECALC;
+ data->is_changed = true;
+ }
}
static void toggle_key_select(PEData *data, int point_index, int key_index, bool UNUSED(is_inside))
{
- PTCacheEdit *edit = data->edit;
- PTCacheEditPoint *point = edit->points + point_index;
- PTCacheEditKey *key = point->keys + key_index;
+ PTCacheEdit *edit = data->edit;
+ PTCacheEditPoint *point = edit->points + point_index;
+ PTCacheEditKey *key = point->keys + key_index;
- key->flag ^= PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- data->is_changed = true;
+ key->flag ^= PEK_SELECT;
+ point->flag |= PEP_EDIT_RECALC;
+ data->is_changed = true;
}
/************************ de select all operator ************************/
static bool select_action_apply(PTCacheEditPoint *point, PTCacheEditKey *key, int action)
{
- bool changed = false;
- switch (action) {
- case SEL_SELECT:
- if ((key->flag & PEK_SELECT) == 0) {
- key->flag |= PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- changed = true;
- }
- break;
- case SEL_DESELECT:
- if (key->flag & PEK_SELECT) {
- key->flag &= ~PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- changed = true;
- }
- break;
- case SEL_INVERT:
- if ((key->flag & PEK_SELECT) == 0) {
- key->flag |= PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- changed = true;
- }
- else {
- key->flag &= ~PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- changed = true;
- }
- break;
- }
- return changed;
+ bool changed = false;
+ switch (action) {
+ case SEL_SELECT:
+ if ((key->flag & PEK_SELECT) == 0) {
+ key->flag |= PEK_SELECT;
+ point->flag |= PEP_EDIT_RECALC;
+ changed = true;
+ }
+ break;
+ case SEL_DESELECT:
+ if (key->flag & PEK_SELECT) {
+ key->flag &= ~PEK_SELECT;
+ point->flag |= PEP_EDIT_RECALC;
+ changed = true;
+ }
+ break;
+ case SEL_INVERT:
+ if ((key->flag & PEK_SELECT) == 0) {
+ key->flag |= PEK_SELECT;
+ point->flag |= PEP_EDIT_RECALC;
+ changed = true;
+ }
+ else {
+ key->flag &= ~PEK_SELECT;
+ point->flag |= PEP_EDIT_RECALC;
+ changed = true;
+ }
+ break;
+ }
+ return changed;
}
static int pe_select_all_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *ob = CTX_data_active_object(C);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- POINT_P; KEY_K;
- int action = RNA_enum_get(op->ptr, "action");
-
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
- LOOP_VISIBLE_POINTS {
- LOOP_SELECTED_KEYS {
- action = SEL_DESELECT;
- break;
- }
-
- if (action == SEL_DESELECT)
- break;
- }
- }
-
- bool changed = false;
- LOOP_VISIBLE_POINTS {
- LOOP_VISIBLE_KEYS {
- changed |= select_action_apply(point, key, action);
- }
- }
-
- if (changed) {
- PE_update_selection(depsgraph, scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob);
- }
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob = CTX_data_active_object(C);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ POINT_P;
+ KEY_K;
+ int action = RNA_enum_get(op->ptr, "action");
+
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+ LOOP_VISIBLE_POINTS
+ {
+ LOOP_SELECTED_KEYS
+ {
+ action = SEL_DESELECT;
+ break;
+ }
+
+ if (action == SEL_DESELECT)
+ break;
+ }
+ }
+
+ bool changed = false;
+ LOOP_VISIBLE_POINTS
+ {
+ LOOP_VISIBLE_KEYS
+ {
+ changed |= select_action_apply(point, key, action);
+ }
+ }
+
+ if (changed) {
+ PE_update_selection(depsgraph, scene, ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob);
+ }
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All";
- ot->idname = "PARTICLE_OT_select_all";
- ot->description = "(De)select all particles' keys";
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->idname = "PARTICLE_OT_select_all";
+ ot->description = "(De)select all particles' keys";
- /* api callbacks */
- ot->exec = pe_select_all_exec;
- ot->poll = PE_poll;
+ /* api callbacks */
+ ot->exec = pe_select_all_exec;
+ ot->poll = PE_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_select_all(ot);
+ WM_operator_properties_select_all(ot);
}
/************************ pick select operator ************************/
bool PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
{
- PEData data;
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- POINT_P; KEY_K;
-
- if (!PE_start_edit(edit)) {
- return false;
- }
-
- if (!extend && !deselect && !toggle) {
- LOOP_VISIBLE_POINTS {
- LOOP_SELECTED_KEYS {
- key->flag &= ~PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- }
- }
- }
-
- PE_set_view3d_data(C, &data);
- data.mval = mval;
- data.rad = ED_view3d_select_dist_px();
-
- /* 1 = nearest only */
- if (extend) {
- for_mouse_hit_keys(&data, extend_key_select, PSEL_NEAREST);
- }
- else if (deselect) {
- for_mouse_hit_keys(&data, deselect_key_select, PSEL_NEAREST);
- }
- else {
- for_mouse_hit_keys(&data, toggle_key_select, PSEL_NEAREST);
- }
-
- if (data.is_changed) {
- PE_update_selection(data.depsgraph, scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob);
- }
-
- return true;
+ PEData data;
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ POINT_P;
+ KEY_K;
+
+ if (!PE_start_edit(edit)) {
+ return false;
+ }
+
+ if (!extend && !deselect && !toggle) {
+ LOOP_VISIBLE_POINTS
+ {
+ LOOP_SELECTED_KEYS
+ {
+ key->flag &= ~PEK_SELECT;
+ point->flag |= PEP_EDIT_RECALC;
+ }
+ }
+ }
+
+ PE_set_view3d_data(C, &data);
+ data.mval = mval;
+ data.rad = ED_view3d_select_dist_px();
+
+ /* 1 = nearest only */
+ if (extend) {
+ for_mouse_hit_keys(&data, extend_key_select, PSEL_NEAREST);
+ }
+ else if (deselect) {
+ for_mouse_hit_keys(&data, deselect_key_select, PSEL_NEAREST);
+ }
+ else {
+ for_mouse_hit_keys(&data, toggle_key_select, PSEL_NEAREST);
+ }
+
+ if (data.is_changed) {
+ PE_update_selection(data.depsgraph, scene, ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob);
+ }
+
+ return true;
}
/************************ select root operator ************************/
static void select_root(PEData *data, int point_index)
{
- PTCacheEditPoint *point = data->edit->points + point_index;
- PTCacheEditKey *key = point->keys;
+ PTCacheEditPoint *point = data->edit->points + point_index;
+ PTCacheEditKey *key = point->keys;
- if (point->flag & PEP_HIDE)
- return;
+ if (point->flag & PEP_HIDE)
+ return;
- if (data->select_action != SEL_TOGGLE) {
- data->is_changed = select_action_apply(point, key, data->select_action);
- }
- else if (key->flag & PEK_SELECT) {
- data->select_toggle_action = SEL_DESELECT;
- }
+ if (data->select_action != SEL_TOGGLE) {
+ data->is_changed = select_action_apply(point, key, data->select_action);
+ }
+ else if (key->flag & PEK_SELECT) {
+ data->select_toggle_action = SEL_DESELECT;
+ }
}
static int select_roots_exec(bContext *C, wmOperator *op)
{
- PEData data;
- int action = RNA_enum_get(op->ptr, "action");
+ PEData data;
+ int action = RNA_enum_get(op->ptr, "action");
- PE_set_data(C, &data);
+ PE_set_data(C, &data);
- if (action == SEL_TOGGLE) {
- data.select_action = SEL_TOGGLE;
- data.select_toggle_action = SEL_SELECT;
+ if (action == SEL_TOGGLE) {
+ data.select_action = SEL_TOGGLE;
+ data.select_toggle_action = SEL_SELECT;
- foreach_point(&data, select_root);
+ foreach_point(&data, select_root);
- action = data.select_toggle_action;
- }
+ action = data.select_toggle_action;
+ }
- data.select_action = action;
- foreach_point(&data, select_root);
+ data.select_action = action;
+ foreach_point(&data, select_root);
- if (data.is_changed) {
- 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;
+ if (data.is_changed) {
+ 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_roots(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Roots";
- ot->idname = "PARTICLE_OT_select_roots";
- ot->description = "Select roots of all visible particles";
+ /* identifiers */
+ ot->name = "Select Roots";
+ ot->idname = "PARTICLE_OT_select_roots";
+ ot->description = "Select roots of all visible particles";
- /* api callbacks */
- ot->exec = select_roots_exec;
- ot->poll = PE_poll;
+ /* api callbacks */
+ ot->exec = select_roots_exec;
+ ot->poll = PE_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_select_action(ot, SEL_SELECT, true);
+ /* properties */
+ WM_operator_properties_select_action(ot, SEL_SELECT, true);
}
/************************ select tip operator ************************/
static void select_tip(PEData *data, int point_index)
{
- PTCacheEditPoint *point = data->edit->points + point_index;
- PTCacheEditKey *key;
+ PTCacheEditPoint *point = data->edit->points + point_index;
+ PTCacheEditKey *key;
- if (point->totkey == 0) {
- return;
- }
+ if (point->totkey == 0) {
+ return;
+ }
- key = &point->keys[point->totkey - 1];
+ key = &point->keys[point->totkey - 1];
- if (point->flag & PEP_HIDE)
- return;
+ if (point->flag & PEP_HIDE)
+ return;
- if (data->select_action != SEL_TOGGLE) {
- data->is_changed = select_action_apply(point, key, data->select_action);
- }
- else if (key->flag & PEK_SELECT) {
- data->select_toggle_action = SEL_DESELECT;
- }
+ if (data->select_action != SEL_TOGGLE) {
+ data->is_changed = select_action_apply(point, key, data->select_action);
+ }
+ else if (key->flag & PEK_SELECT) {
+ data->select_toggle_action = SEL_DESELECT;
+ }
}
static int select_tips_exec(bContext *C, wmOperator *op)
{
- PEData data;
- int action = RNA_enum_get(op->ptr, "action");
+ PEData data;
+ int action = RNA_enum_get(op->ptr, "action");
- PE_set_data(C, &data);
+ PE_set_data(C, &data);
- if (action == SEL_TOGGLE) {
- data.select_action = SEL_TOGGLE;
- data.select_toggle_action = SEL_SELECT;
+ if (action == SEL_TOGGLE) {
+ data.select_action = SEL_TOGGLE;
+ data.select_toggle_action = SEL_SELECT;
- foreach_point(&data, select_tip);
+ foreach_point(&data, select_tip);
- action = data.select_toggle_action;
- }
+ action = data.select_toggle_action;
+ }
- data.select_action = action;
- foreach_point(&data, select_tip);
+ data.select_action = action;
+ foreach_point(&data, select_tip);
- if (data.is_changed) {
- PE_update_selection(data.depsgraph, data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob);
+ if (data.is_changed) {
+ 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;
- }
- return OPERATOR_CANCELLED;
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_CANCELLED;
}
void PARTICLE_OT_select_tips(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Tips";
- ot->idname = "PARTICLE_OT_select_tips";
- ot->description = "Select tips of all visible particles";
+ /* identifiers */
+ ot->name = "Select Tips";
+ ot->idname = "PARTICLE_OT_select_tips";
+ ot->description = "Select tips of all visible particles";
- /* api callbacks */
- ot->exec = select_tips_exec;
- ot->poll = PE_poll;
+ /* api callbacks */
+ ot->exec = select_tips_exec;
+ ot->poll = PE_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_select_action(ot, SEL_SELECT, true);
+ /* properties */
+ WM_operator_properties_select_action(ot, SEL_SELECT, true);
}
/*********************** select random operator ************************/
@@ -1892,847 +1934,892 @@ void PARTICLE_OT_select_tips(wmOperatorType *ot)
enum { RAN_HAIR, RAN_POINTS };
static const EnumPropertyItem select_random_type_items[] = {
- {RAN_HAIR, "HAIR", 0, "Hair", ""},
- {RAN_POINTS, "POINTS", 0, "Points", ""},
- {0, NULL, 0, NULL, NULL},
+ {RAN_HAIR, "HAIR", 0, "Hair", ""},
+ {RAN_POINTS, "POINTS", 0, "Points", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int select_random_exec(bContext *C, wmOperator *op)
{
- PEData data;
- int type;
-
- /* used by LOOP_VISIBLE_POINTS, LOOP_VISIBLE_KEYS and LOOP_KEYS */
- PTCacheEdit *edit;
- PTCacheEditPoint *point;
- PTCacheEditKey *key;
- int p;
- int k;
-
- const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
- const int seed = WM_operator_properties_select_random_seed_increment_get(op);
- const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
- RNG *rng;
-
- type = RNA_enum_get(op->ptr, "type");
-
- PE_set_data(C, &data);
- data.select_action = SEL_SELECT;
- edit = PE_get_current(data.scene, data.ob);
-
- rng = BLI_rng_new_srandom(seed);
-
- switch (type) {
- case RAN_HAIR:
- LOOP_VISIBLE_POINTS {
- int flag = ((BLI_rng_get_float(rng) < randfac) == select) ? SEL_SELECT : SEL_DESELECT;
- LOOP_KEYS {
- data.is_changed |= select_action_apply(point, key, flag);
- }
- }
- break;
- case RAN_POINTS:
- LOOP_VISIBLE_POINTS {
- LOOP_VISIBLE_KEYS {
- int flag = ((BLI_rng_get_float(rng) < randfac) == select) ? SEL_SELECT : SEL_DESELECT;
- data.is_changed |= select_action_apply(point, key, flag);
- }
- }
- break;
- }
-
- BLI_rng_free(rng);
-
- if (data.is_changed) {
- 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;
+ PEData data;
+ int type;
+
+ /* used by LOOP_VISIBLE_POINTS, LOOP_VISIBLE_KEYS and LOOP_KEYS */
+ PTCacheEdit *edit;
+ PTCacheEditPoint *point;
+ PTCacheEditKey *key;
+ int p;
+ int k;
+
+ const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
+ const int seed = WM_operator_properties_select_random_seed_increment_get(op);
+ const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
+ RNG *rng;
+
+ type = RNA_enum_get(op->ptr, "type");
+
+ PE_set_data(C, &data);
+ data.select_action = SEL_SELECT;
+ edit = PE_get_current(data.scene, data.ob);
+
+ rng = BLI_rng_new_srandom(seed);
+
+ switch (type) {
+ case RAN_HAIR:
+ LOOP_VISIBLE_POINTS
+ {
+ int flag = ((BLI_rng_get_float(rng) < randfac) == select) ? SEL_SELECT : SEL_DESELECT;
+ LOOP_KEYS
+ {
+ data.is_changed |= select_action_apply(point, key, flag);
+ }
+ }
+ break;
+ case RAN_POINTS:
+ LOOP_VISIBLE_POINTS
+ {
+ LOOP_VISIBLE_KEYS
+ {
+ int flag = ((BLI_rng_get_float(rng) < randfac) == select) ? SEL_SELECT : SEL_DESELECT;
+ data.is_changed |= select_action_apply(point, key, flag);
+ }
+ }
+ break;
+ }
+
+ BLI_rng_free(rng);
+
+ if (data.is_changed) {
+ 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_random(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Random";
- ot->idname = "PARTICLE_OT_select_random";
- ot->description = "Select a randomly distributed set of hair or points";
+ /* identifiers */
+ ot->name = "Select Random";
+ ot->idname = "PARTICLE_OT_select_random";
+ ot->description = "Select a randomly distributed set of hair or points";
- /* api callbacks */
- ot->exec = select_random_exec;
- ot->poll = PE_poll;
+ /* api callbacks */
+ ot->exec = select_random_exec;
+ ot->poll = PE_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_select_random(ot);
- ot->prop = RNA_def_enum(ot->srna, "type", select_random_type_items, RAN_HAIR,
- "Type", "Select either hair or points");
+ /* properties */
+ WM_operator_properties_select_random(ot);
+ ot->prop = RNA_def_enum(ot->srna,
+ "type",
+ select_random_type_items,
+ RAN_HAIR,
+ "Type",
+ "Select either hair or points");
}
/************************ select linked operator ************************/
static int select_linked_exec(bContext *C, wmOperator *op)
{
- PEData data;
- int mval[2];
- int location[2];
+ PEData data;
+ int mval[2];
+ int location[2];
- RNA_int_get_array(op->ptr, "location", location);
- mval[0] = location[0];
- mval[1] = location[1];
+ RNA_int_get_array(op->ptr, "location", location);
+ mval[0] = location[0];
+ mval[1] = location[1];
- PE_set_view3d_data(C, &data);
- data.mval = mval;
- data.rad = 75.0f;
- data.select = !RNA_boolean_get(op->ptr, "deselect");
+ PE_set_view3d_data(C, &data);
+ data.mval = mval;
+ data.rad = 75.0f;
+ data.select = !RNA_boolean_get(op->ptr, "deselect");
- for_mouse_hit_keys(&data, select_keys, PSEL_NEAREST);
- PE_update_selection(data.depsgraph, data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob);
+ for_mouse_hit_keys(&data, select_keys, PSEL_NEAREST);
+ 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;
+ return OPERATOR_FINISHED;
}
static int select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- RNA_int_set_array(op->ptr, "location", event->mval);
- return select_linked_exec(C, op);
+ RNA_int_set_array(op->ptr, "location", event->mval);
+ return select_linked_exec(C, op);
}
void PARTICLE_OT_select_linked(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Linked";
- ot->idname = "PARTICLE_OT_select_linked";
- ot->description = "Select nearest particle from mouse pointer";
+ /* identifiers */
+ ot->name = "Select Linked";
+ ot->idname = "PARTICLE_OT_select_linked";
+ ot->description = "Select nearest particle from mouse pointer";
- /* api callbacks */
- ot->exec = select_linked_exec;
- ot->invoke = select_linked_invoke;
- ot->poll = PE_poll_view3d;
+ /* api callbacks */
+ ot->exec = select_linked_exec;
+ ot->invoke = select_linked_invoke;
+ ot->poll = PE_poll_view3d;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect linked keys rather than selecting them");
- RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "", 0, 16384);
+ /* properties */
+ RNA_def_boolean(
+ ot->srna, "deselect", 0, "Deselect", "Deselect linked keys rather than selecting them");
+ RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "", 0, 16384);
}
/************************ box select operator ************************/
bool PE_deselect_all_visible_ex(PTCacheEdit *edit)
{
- bool changed = false;
- POINT_P; KEY_K;
+ bool changed = false;
+ POINT_P;
+ KEY_K;
- LOOP_VISIBLE_POINTS {
- LOOP_SELECTED_KEYS {
- if ((key->flag & PEK_SELECT) != 0) {
- key->flag &= ~PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- changed = true;
- }
- }
- }
- return changed;
+ LOOP_VISIBLE_POINTS
+ {
+ LOOP_SELECTED_KEYS
+ {
+ if ((key->flag & PEK_SELECT) != 0) {
+ key->flag &= ~PEK_SELECT;
+ point->flag |= PEP_EDIT_RECALC;
+ changed = true;
+ }
+ }
+ }
+ return changed;
}
bool PE_deselect_all_visible(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- if (!PE_start_edit(edit)) {
- return false;
- }
- return PE_deselect_all_visible_ex(edit);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ if (!PE_start_edit(edit)) {
+ return false;
+ }
+ return PE_deselect_all_visible_ex(edit);
}
bool PE_box_select(bContext *C, const rcti *rect, const int sel_op)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- PEData data;
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ PEData data;
- if (!PE_start_edit(edit)) {
- return false;
- }
+ if (!PE_start_edit(edit)) {
+ return false;
+ }
- PE_set_view3d_data(C, &data);
- data.rect = rect;
- data.sel_op = sel_op;
+ PE_set_view3d_data(C, &data);
+ data.rect = rect;
+ data.sel_op = sel_op;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- data.is_changed = PE_deselect_all_visible_ex(edit);
- }
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ data.is_changed = PE_deselect_all_visible_ex(edit);
+ }
- if (BLI_rcti_is_empty(rect)) {
- /* pass */
- }
- else {
- for_mouse_hit_keys(&data, select_key_op, PSEL_ALL_KEYS);
- }
+ if (BLI_rcti_is_empty(rect)) {
+ /* pass */
+ }
+ else {
+ for_mouse_hit_keys(&data, select_key_op, PSEL_ALL_KEYS);
+ }
- if (data.is_changed) {
- PE_update_selection(data.depsgraph, scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob);
- }
- return data.is_changed;
+ if (data.is_changed) {
+ PE_update_selection(data.depsgraph, scene, ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob);
+ }
+ return data.is_changed;
}
/************************ circle select operator ************************/
bool PE_circle_select(bContext *C, const int sel_op, const int mval[2], float rad)
{
- BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB));
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- PEData data;
+ BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB));
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ PEData data;
- if (!PE_start_edit(edit)) {
- return false;
- }
+ if (!PE_start_edit(edit)) {
+ return false;
+ }
- const bool select = (sel_op != SEL_OP_SUB);
+ const bool select = (sel_op != SEL_OP_SUB);
- PE_set_view3d_data(C, &data);
- data.mval = mval;
- data.rad = rad;
- data.select = select;
+ PE_set_view3d_data(C, &data);
+ data.mval = mval;
+ data.rad = rad;
+ data.select = select;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- data.is_changed = PE_deselect_all_visible_ex(edit);
- }
- for_mouse_hit_keys(&data, select_key, 0);
- if (data.is_changed) {
- PE_update_selection(data.depsgraph, scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob);
- }
- return data.is_changed;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ data.is_changed = PE_deselect_all_visible_ex(edit);
+ }
+ for_mouse_hit_keys(&data, select_key, 0);
+ if (data.is_changed) {
+ PE_update_selection(data.depsgraph, scene, ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob);
+ }
+ return data.is_changed;
}
/************************ lasso select operator ************************/
int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, const int sel_op)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- ARegion *ar = CTX_wm_region(C);
- ParticleEditSettings *pset = PE_settings(scene);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- ParticleSystem *psys = edit->psys;
- ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
- POINT_P; KEY_K;
- float co[3], mat[4][4];
- int screen_co[2];
-
- PEData data;
-
- unit_m4(mat);
-
- if (!PE_start_edit(edit))
- return OPERATOR_CANCELLED;
-
- /* only for depths */
- PE_set_view3d_data(C, &data);
-
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- data.is_changed |= PE_deselect_all_visible_ex(edit);
- }
-
- LOOP_VISIBLE_POINTS {
- if (edit->psys && !(psys->flag & PSYS_GLOBAL_HAIR))
- psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
-
- if (pset->selectmode == SCE_SELECT_POINT) {
- LOOP_KEYS {
- copy_v3_v3(co, key->co);
- 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) == V3D_PROJ_RET_OK) &&
- BLI_lasso_is_point_inside(mcords, moves, 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) {
- SET_FLAG_FROM_TEST(key->flag, sel_op_result, PEK_SELECT);
- point->flag |= PEP_EDIT_RECALC;
- data.is_changed = true;
- }
- }
- }
- else if (pset->selectmode == SCE_SELECT_END) {
- if (point->totkey) {
- key = point->keys + point->totkey - 1;
- copy_v3_v3(co, key->co);
- 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) == V3D_PROJ_RET_OK) &&
- BLI_lasso_is_point_inside(mcords, moves, 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) {
- SET_FLAG_FROM_TEST(key->flag, sel_op_result, PEK_SELECT);
- point->flag |= PEP_EDIT_RECALC;
- data.is_changed = true;
- }
- }
- }
- }
-
- if (data.is_changed) {
- PE_update_selection(data.depsgraph, scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob);
- return OPERATOR_FINISHED;
- }
- return OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ ARegion *ar = CTX_wm_region(C);
+ ParticleEditSettings *pset = PE_settings(scene);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ ParticleSystem *psys = edit->psys;
+ ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
+ POINT_P;
+ KEY_K;
+ float co[3], mat[4][4];
+ int screen_co[2];
+
+ PEData data;
+
+ unit_m4(mat);
+
+ if (!PE_start_edit(edit))
+ return OPERATOR_CANCELLED;
+
+ /* only for depths */
+ PE_set_view3d_data(C, &data);
+
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ data.is_changed |= PE_deselect_all_visible_ex(edit);
+ }
+
+ LOOP_VISIBLE_POINTS
+ {
+ if (edit->psys && !(psys->flag & PSYS_GLOBAL_HAIR))
+ psys_mat_hair_to_global(
+ ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
+
+ if (pset->selectmode == SCE_SELECT_POINT) {
+ LOOP_KEYS
+ {
+ copy_v3_v3(co, key->co);
+ 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) ==
+ V3D_PROJ_RET_OK) &&
+ BLI_lasso_is_point_inside(mcords, moves, 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) {
+ SET_FLAG_FROM_TEST(key->flag, sel_op_result, PEK_SELECT);
+ point->flag |= PEP_EDIT_RECALC;
+ data.is_changed = true;
+ }
+ }
+ }
+ else if (pset->selectmode == SCE_SELECT_END) {
+ if (point->totkey) {
+ key = point->keys + point->totkey - 1;
+ copy_v3_v3(co, key->co);
+ 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) ==
+ V3D_PROJ_RET_OK) &&
+ BLI_lasso_is_point_inside(mcords, moves, 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) {
+ SET_FLAG_FROM_TEST(key->flag, sel_op_result, PEK_SELECT);
+ point->flag |= PEP_EDIT_RECALC;
+ data.is_changed = true;
+ }
+ }
+ }
+ }
+
+ if (data.is_changed) {
+ PE_update_selection(data.depsgraph, scene, ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob);
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_CANCELLED;
}
/*************************** hide operator **************************/
static int hide_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
-
- PTCacheEdit *edit = PE_get_current(scene, ob);
- POINT_P; KEY_K;
-
-
- if (RNA_enum_get(op->ptr, "unselected")) {
- LOOP_UNSELECTED_POINTS {
- point->flag |= PEP_HIDE;
- point->flag |= PEP_EDIT_RECALC;
-
- LOOP_KEYS {
- key->flag &= ~PEK_SELECT;
- }
- }
- }
- else {
- LOOP_SELECTED_POINTS {
- point->flag |= PEP_HIDE;
- point->flag |= PEP_EDIT_RECALC;
-
- LOOP_KEYS {
- key->flag &= ~PEK_SELECT;
- }
- }
- }
-
- PE_update_selection(depsgraph, scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob);
-
- return OPERATOR_FINISHED;
+ Object *ob = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ POINT_P;
+ KEY_K;
+
+ if (RNA_enum_get(op->ptr, "unselected")) {
+ LOOP_UNSELECTED_POINTS
+ {
+ point->flag |= PEP_HIDE;
+ point->flag |= PEP_EDIT_RECALC;
+
+ LOOP_KEYS
+ {
+ key->flag &= ~PEK_SELECT;
+ }
+ }
+ }
+ else {
+ LOOP_SELECTED_POINTS
+ {
+ point->flag |= PEP_HIDE;
+ point->flag |= PEP_EDIT_RECALC;
+
+ LOOP_KEYS
+ {
+ key->flag &= ~PEK_SELECT;
+ }
+ }
+ }
+
+ PE_update_selection(depsgraph, scene, ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob);
+
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_hide(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Selected";
- ot->idname = "PARTICLE_OT_hide";
- ot->description = "Hide selected particles";
+ /* identifiers */
+ ot->name = "Hide Selected";
+ ot->idname = "PARTICLE_OT_hide";
+ ot->description = "Hide selected particles";
- /* api callbacks */
- ot->exec = hide_exec;
- ot->poll = PE_poll;
+ /* api callbacks */
+ ot->exec = hide_exec;
+ ot->poll = PE_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
}
/*************************** reveal operator **************************/
static int reveal_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- const bool select = RNA_boolean_get(op->ptr, "select");
- POINT_P; KEY_K;
+ Object *ob = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ const bool select = RNA_boolean_get(op->ptr, "select");
+ POINT_P;
+ KEY_K;
- LOOP_POINTS {
- if (point->flag & PEP_HIDE) {
- point->flag &= ~PEP_HIDE;
- point->flag |= PEP_EDIT_RECALC;
+ LOOP_POINTS
+ {
+ if (point->flag & PEP_HIDE) {
+ point->flag &= ~PEP_HIDE;
+ point->flag |= PEP_EDIT_RECALC;
- LOOP_KEYS {
- SET_FLAG_FROM_TEST(key->flag, select, PEK_SELECT);
- }
- }
- }
+ LOOP_KEYS
+ {
+ SET_FLAG_FROM_TEST(key->flag, select, PEK_SELECT);
+ }
+ }
+ }
- PE_update_selection(depsgraph, scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob);
+ PE_update_selection(depsgraph, scene, ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_reveal(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reveal";
- ot->idname = "PARTICLE_OT_reveal";
- ot->description = "Show hidden particles";
+ /* identifiers */
+ ot->name = "Reveal";
+ ot->idname = "PARTICLE_OT_reveal";
+ ot->description = "Show hidden particles";
- /* api callbacks */
- ot->exec = reveal_exec;
- ot->poll = PE_poll;
+ /* api callbacks */
+ ot->exec = reveal_exec;
+ ot->poll = PE_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "select", true, "Select", "");
+ /* props */
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
/************************ select less operator ************************/
static void select_less_keys(PEData *data, int point_index)
{
- PTCacheEdit *edit = data->edit;
- PTCacheEditPoint *point = edit->points + point_index;
- KEY_K;
-
- LOOP_SELECTED_KEYS {
- if (k == 0) {
- if (((key + 1)->flag & PEK_SELECT) == 0)
- key->flag |= PEK_TAG;
- }
- else if (k == point->totkey - 1) {
- if (((key - 1)->flag & PEK_SELECT) == 0)
- key->flag |= PEK_TAG;
- }
- else {
- if ((((key - 1)->flag & (key + 1)->flag) & PEK_SELECT) == 0)
- key->flag |= PEK_TAG;
- }
- }
-
- LOOP_KEYS {
- if ((key->flag & PEK_TAG) && (key->flag & PEK_SELECT)) {
- key->flag &= ~(PEK_TAG | PEK_SELECT);
- point->flag |= PEP_EDIT_RECALC; /* redraw selection only */
- data->is_changed = true;
- }
- }
+ PTCacheEdit *edit = data->edit;
+ PTCacheEditPoint *point = edit->points + point_index;
+ KEY_K;
+
+ LOOP_SELECTED_KEYS
+ {
+ if (k == 0) {
+ if (((key + 1)->flag & PEK_SELECT) == 0)
+ key->flag |= PEK_TAG;
+ }
+ else if (k == point->totkey - 1) {
+ if (((key - 1)->flag & PEK_SELECT) == 0)
+ key->flag |= PEK_TAG;
+ }
+ else {
+ if ((((key - 1)->flag & (key + 1)->flag) & PEK_SELECT) == 0)
+ key->flag |= PEK_TAG;
+ }
+ }
+
+ LOOP_KEYS
+ {
+ if ((key->flag & PEK_TAG) && (key->flag & PEK_SELECT)) {
+ key->flag &= ~(PEK_TAG | PEK_SELECT);
+ point->flag |= PEP_EDIT_RECALC; /* redraw selection only */
+ data->is_changed = true;
+ }
+ }
}
static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
- PEData data;
+ PEData data;
- PE_set_data(C, &data);
- foreach_point(&data, select_less_keys);
+ PE_set_data(C, &data);
+ foreach_point(&data, select_less_keys);
- PE_update_selection(data.depsgraph, data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob);
+ 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;
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_select_less(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Less";
- ot->idname = "PARTICLE_OT_select_less";
- ot->description = "Deselect boundary selected keys of each particle";
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->idname = "PARTICLE_OT_select_less";
+ ot->description = "Deselect boundary selected keys of each particle";
- /* api callbacks */
- ot->exec = select_less_exec;
- ot->poll = PE_poll;
+ /* api callbacks */
+ ot->exec = select_less_exec;
+ ot->poll = PE_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************ select more operator ************************/
static void select_more_keys(PEData *data, int point_index)
{
- PTCacheEdit *edit = data->edit;
- PTCacheEditPoint *point = edit->points + point_index;
- KEY_K;
-
- LOOP_KEYS {
- if (key->flag & PEK_SELECT) continue;
-
- if (k == 0) {
- if ((key + 1)->flag & PEK_SELECT)
- key->flag |= PEK_TAG;
- }
- else if (k == point->totkey - 1) {
- if ((key - 1)->flag & PEK_SELECT)
- key->flag |= PEK_TAG;
- }
- else {
- if (((key - 1)->flag | (key + 1)->flag) & PEK_SELECT)
- key->flag |= PEK_TAG;
- }
- }
-
- LOOP_KEYS {
- if ((key->flag & PEK_TAG) && (key->flag & PEK_SELECT) == 0) {
- key->flag &= ~PEK_TAG;
- key->flag |= PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC; /* redraw selection only */
- data->is_changed = true;
- }
- }
+ PTCacheEdit *edit = data->edit;
+ PTCacheEditPoint *point = edit->points + point_index;
+ KEY_K;
+
+ LOOP_KEYS
+ {
+ if (key->flag & PEK_SELECT)
+ continue;
+
+ if (k == 0) {
+ if ((key + 1)->flag & PEK_SELECT)
+ key->flag |= PEK_TAG;
+ }
+ else if (k == point->totkey - 1) {
+ if ((key - 1)->flag & PEK_SELECT)
+ key->flag |= PEK_TAG;
+ }
+ else {
+ if (((key - 1)->flag | (key + 1)->flag) & PEK_SELECT)
+ key->flag |= PEK_TAG;
+ }
+ }
+
+ LOOP_KEYS
+ {
+ if ((key->flag & PEK_TAG) && (key->flag & PEK_SELECT) == 0) {
+ key->flag &= ~PEK_TAG;
+ key->flag |= PEK_SELECT;
+ point->flag |= PEP_EDIT_RECALC; /* redraw selection only */
+ data->is_changed = true;
+ }
+ }
}
static int select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
- PEData data;
+ PEData data;
- PE_set_data(C, &data);
- foreach_point(&data, select_more_keys);
+ PE_set_data(C, &data);
+ foreach_point(&data, select_more_keys);
- PE_update_selection(data.depsgraph, data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob);
+ 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;
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_select_more(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select More";
- ot->idname = "PARTICLE_OT_select_more";
- ot->description = "Select keys linked to boundary selected keys of each particle";
+ /* identifiers */
+ ot->name = "Select More";
+ ot->idname = "PARTICLE_OT_select_more";
+ ot->description = "Select keys linked to boundary selected keys of each particle";
- /* api callbacks */
- ot->exec = select_more_exec;
- ot->poll = PE_poll;
+ /* api callbacks */
+ ot->exec = select_more_exec;
+ ot->poll = PE_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************ rekey operator ************************/
static void rekey_particle(PEData *data, int pa_index)
{
- PTCacheEdit *edit = data->edit;
- ParticleSystem *psys = edit->psys;
- ParticleSimulationData sim = {0};
- ParticleData *pa = psys->particles + pa_index;
- PTCacheEditPoint *point = edit->points + pa_index;
- ParticleKey state;
- HairKey *key, *new_keys, *okey;
- PTCacheEditKey *ekey;
- float dval, sta, end;
- int k;
-
- sim.depsgraph = data->depsgraph;
- sim.scene = data->scene;
- sim.ob = data->ob;
- sim.psys = edit->psys;
-
- pa->flag |= PARS_REKEY;
-
- key = new_keys = MEM_callocN(data->totrekey * sizeof(HairKey), "Hair re-key keys");
-
- okey = pa->hair;
- /* root and tip stay the same */
- copy_v3_v3(key->co, okey->co);
- copy_v3_v3((key + data->totrekey - 1)->co, (okey + pa->totkey - 1)->co);
-
- sta = key->time = okey->time;
- end = (key + data->totrekey - 1)->time = (okey + pa->totkey - 1)->time;
- dval = (end - sta) / (float)(data->totrekey - 1);
-
- /* interpolate new keys from old ones */
- for (k = 1, key++; k < data->totrekey - 1; k++, key++) {
- state.time = (float)k / (float)(data->totrekey - 1);
- psys_get_particle_on_path(&sim, pa_index, &state, 0);
- copy_v3_v3(key->co, state.co);
- key->time = sta + k * dval;
- }
-
- /* replace keys */
- if (pa->hair)
- MEM_freeN(pa->hair);
- pa->hair = new_keys;
-
- point->totkey = pa->totkey = data->totrekey;
-
-
- if (point->keys)
- MEM_freeN(point->keys);
- ekey = point->keys = MEM_callocN(pa->totkey * sizeof(PTCacheEditKey), "Hair re-key edit keys");
-
- for (k = 0, key = pa->hair; k < pa->totkey; k++, key++, ekey++) {
- ekey->co = key->co;
- ekey->time = &key->time;
- ekey->flag |= PEK_SELECT;
- if (!(psys->flag & PSYS_GLOBAL_HAIR))
- ekey->flag |= PEK_USE_WCO;
- }
-
- pa->flag &= ~PARS_REKEY;
- point->flag |= PEP_EDIT_RECALC;
+ PTCacheEdit *edit = data->edit;
+ ParticleSystem *psys = edit->psys;
+ ParticleSimulationData sim = {0};
+ ParticleData *pa = psys->particles + pa_index;
+ PTCacheEditPoint *point = edit->points + pa_index;
+ ParticleKey state;
+ HairKey *key, *new_keys, *okey;
+ PTCacheEditKey *ekey;
+ float dval, sta, end;
+ int k;
+
+ sim.depsgraph = data->depsgraph;
+ sim.scene = data->scene;
+ sim.ob = data->ob;
+ sim.psys = edit->psys;
+
+ pa->flag |= PARS_REKEY;
+
+ key = new_keys = MEM_callocN(data->totrekey * sizeof(HairKey), "Hair re-key keys");
+
+ okey = pa->hair;
+ /* root and tip stay the same */
+ copy_v3_v3(key->co, okey->co);
+ copy_v3_v3((key + data->totrekey - 1)->co, (okey + pa->totkey - 1)->co);
+
+ sta = key->time = okey->time;
+ end = (key + data->totrekey - 1)->time = (okey + pa->totkey - 1)->time;
+ dval = (end - sta) / (float)(data->totrekey - 1);
+
+ /* interpolate new keys from old ones */
+ for (k = 1, key++; k < data->totrekey - 1; k++, key++) {
+ state.time = (float)k / (float)(data->totrekey - 1);
+ psys_get_particle_on_path(&sim, pa_index, &state, 0);
+ copy_v3_v3(key->co, state.co);
+ key->time = sta + k * dval;
+ }
+
+ /* replace keys */
+ if (pa->hair)
+ MEM_freeN(pa->hair);
+ pa->hair = new_keys;
+
+ point->totkey = pa->totkey = data->totrekey;
+
+ if (point->keys)
+ MEM_freeN(point->keys);
+ ekey = point->keys = MEM_callocN(pa->totkey * sizeof(PTCacheEditKey), "Hair re-key edit keys");
+
+ for (k = 0, key = pa->hair; k < pa->totkey; k++, key++, ekey++) {
+ ekey->co = key->co;
+ ekey->time = &key->time;
+ ekey->flag |= PEK_SELECT;
+ if (!(psys->flag & PSYS_GLOBAL_HAIR))
+ ekey->flag |= PEK_USE_WCO;
+ }
+
+ pa->flag &= ~PARS_REKEY;
+ point->flag |= PEP_EDIT_RECALC;
}
static int rekey_exec(bContext *C, wmOperator *op)
{
- PEData data;
+ PEData data;
- PE_set_data(C, &data);
+ PE_set_data(C, &data);
- data.dval = 1.0f / (float)(data.totrekey - 1);
- data.totrekey = RNA_int_get(op->ptr, "keys_number");
+ data.dval = 1.0f / (float)(data.totrekey - 1);
+ data.totrekey = RNA_int_get(op->ptr, "keys_number");
- foreach_selected_point(&data, rekey_particle);
+ foreach_selected_point(&data, rekey_particle);
- recalc_lengths(data.edit);
- PE_update_object(data.depsgraph, data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, data.ob);
+ recalc_lengths(data.edit);
+ PE_update_object(data.depsgraph, data.scene, data.ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, data.ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_rekey(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Rekey";
- ot->idname = "PARTICLE_OT_rekey";
- ot->description = "Change the number of keys of selected particles (root and tip keys included)";
+ /* identifiers */
+ ot->name = "Rekey";
+ ot->idname = "PARTICLE_OT_rekey";
+ ot->description = "Change the number of keys of selected particles (root and tip keys included)";
- /* api callbacks */
- ot->exec = rekey_exec;
- ot->invoke = WM_operator_props_popup;
- ot->poll = PE_hair_poll;
+ /* api callbacks */
+ ot->exec = rekey_exec;
+ ot->invoke = WM_operator_props_popup;
+ ot->poll = PE_hair_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_int(ot->srna, "keys_number", 2, 2, INT_MAX, "Number of Keys", "", 2, 100);
+ /* properties */
+ RNA_def_int(ot->srna, "keys_number", 2, 2, INT_MAX, "Number of Keys", "", 2, 100);
}
-static void rekey_particle_to_time(const bContext *C, Scene *scene, Object *ob, int pa_index, float path_time)
+static void rekey_particle_to_time(
+ const bContext *C, Scene *scene, Object *ob, int pa_index, float path_time)
{
- PTCacheEdit *edit = PE_get_current(scene, ob);
- ParticleSystem *psys;
- ParticleSimulationData sim = {0};
- ParticleData *pa;
- ParticleKey state;
- HairKey *new_keys, *key;
- PTCacheEditKey *ekey;
- int k;
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ ParticleSystem *psys;
+ ParticleSimulationData sim = {0};
+ ParticleData *pa;
+ ParticleKey state;
+ HairKey *new_keys, *key;
+ PTCacheEditKey *ekey;
+ int k;
- if (!edit || !edit->psys) return;
+ if (!edit || !edit->psys)
+ return;
- psys = edit->psys;
+ psys = edit->psys;
- sim.depsgraph = CTX_data_depsgraph(C);
- sim.scene = scene;
- sim.ob = ob;
- sim.psys = psys;
+ sim.depsgraph = CTX_data_depsgraph(C);
+ sim.scene = scene;
+ sim.ob = ob;
+ sim.psys = psys;
- pa = psys->particles + pa_index;
+ pa = psys->particles + pa_index;
- pa->flag |= PARS_REKEY;
+ pa->flag |= PARS_REKEY;
- key = new_keys = MEM_dupallocN(pa->hair);
+ key = new_keys = MEM_dupallocN(pa->hair);
- /* interpolate new keys from old ones (roots stay the same) */
- for (k = 1, key++; k < pa->totkey; k++, key++) {
- state.time = path_time * (float)k / (float)(pa->totkey - 1);
- psys_get_particle_on_path(&sim, pa_index, &state, 0);
- copy_v3_v3(key->co, state.co);
- }
+ /* interpolate new keys from old ones (roots stay the same) */
+ for (k = 1, key++; k < pa->totkey; k++, key++) {
+ state.time = path_time * (float)k / (float)(pa->totkey - 1);
+ psys_get_particle_on_path(&sim, pa_index, &state, 0);
+ copy_v3_v3(key->co, state.co);
+ }
- /* replace hair keys */
- if (pa->hair)
- MEM_freeN(pa->hair);
- pa->hair = new_keys;
+ /* replace hair keys */
+ if (pa->hair)
+ MEM_freeN(pa->hair);
+ pa->hair = new_keys;
- /* update edit pointers */
- for (k = 0, key = pa->hair, ekey = edit->points[pa_index].keys; k < pa->totkey; k++, key++, ekey++) {
- ekey->co = key->co;
- ekey->time = &key->time;
- }
+ /* update edit pointers */
+ for (k = 0, key = pa->hair, ekey = edit->points[pa_index].keys; k < pa->totkey;
+ k++, key++, ekey++) {
+ ekey->co = key->co;
+ ekey->time = &key->time;
+ }
- pa->flag &= ~PARS_REKEY;
+ pa->flag &= ~PARS_REKEY;
}
/************************* utilities **************************/
static int remove_tagged_particles(Object *ob, ParticleSystem *psys, int mirror)
{
- PTCacheEdit *edit = psys->edit;
- ParticleData *pa, *npa = 0, *new_pars = 0;
- POINT_P;
- PTCacheEditPoint *npoint = 0, *new_points = 0;
- ParticleSystemModifierData *psmd_eval;
- int i, new_totpart = psys->totpart, removed = 0;
-
- if (mirror) {
- /* mirror tags */
- psmd_eval = edit->psmd_eval;
-
- LOOP_TAGGED_POINTS {
- PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL);
- }
- }
-
- LOOP_TAGGED_POINTS {
- new_totpart--;
- removed++;
- }
-
- if (new_totpart != psys->totpart) {
- if (new_totpart) {
- npa = new_pars = MEM_callocN(new_totpart * sizeof(ParticleData), "ParticleData array");
- npoint = new_points = MEM_callocN(new_totpart * sizeof(PTCacheEditPoint), "PTCacheEditKey array");
-
- if (ELEM(NULL, new_pars, new_points)) {
- /* allocation error! */
- if (new_pars)
- MEM_freeN(new_pars);
- if (new_points)
- MEM_freeN(new_points);
- return 0;
- }
- }
-
- pa = psys->particles;
- point = edit->points;
- for (i = 0; i < psys->totpart; i++, pa++, point++) {
- if (point->flag & PEP_TAG) {
- if (point->keys)
- MEM_freeN(point->keys);
- if (pa->hair)
- MEM_freeN(pa->hair);
- }
- else {
- memcpy(npa, pa, sizeof(ParticleData));
- memcpy(npoint, point, sizeof(PTCacheEditPoint));
- npa++;
- npoint++;
- }
- }
-
- if (psys->particles) MEM_freeN(psys->particles);
- psys->particles = new_pars;
-
- if (edit->points) MEM_freeN(edit->points);
- edit->points = new_points;
-
- if (edit->mirror_cache) {
- MEM_freeN(edit->mirror_cache);
- edit->mirror_cache = NULL;
- }
-
- if (psys->child) {
- MEM_freeN(psys->child);
- psys->child = NULL;
- psys->totchild = 0;
- }
-
- edit->totpoint = psys->totpart = new_totpart;
- }
-
- return removed;
+ PTCacheEdit *edit = psys->edit;
+ ParticleData *pa, *npa = 0, *new_pars = 0;
+ POINT_P;
+ PTCacheEditPoint *npoint = 0, *new_points = 0;
+ ParticleSystemModifierData *psmd_eval;
+ int i, new_totpart = psys->totpart, removed = 0;
+
+ if (mirror) {
+ /* mirror tags */
+ psmd_eval = edit->psmd_eval;
+
+ LOOP_TAGGED_POINTS
+ {
+ PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL);
+ }
+ }
+
+ LOOP_TAGGED_POINTS
+ {
+ new_totpart--;
+ removed++;
+ }
+
+ if (new_totpart != psys->totpart) {
+ if (new_totpart) {
+ npa = new_pars = MEM_callocN(new_totpart * sizeof(ParticleData), "ParticleData array");
+ npoint = new_points = MEM_callocN(new_totpart * sizeof(PTCacheEditPoint),
+ "PTCacheEditKey array");
+
+ if (ELEM(NULL, new_pars, new_points)) {
+ /* allocation error! */
+ if (new_pars)
+ MEM_freeN(new_pars);
+ if (new_points)
+ MEM_freeN(new_points);
+ return 0;
+ }
+ }
+
+ pa = psys->particles;
+ point = edit->points;
+ for (i = 0; i < psys->totpart; i++, pa++, point++) {
+ if (point->flag & PEP_TAG) {
+ if (point->keys)
+ MEM_freeN(point->keys);
+ if (pa->hair)
+ MEM_freeN(pa->hair);
+ }
+ else {
+ memcpy(npa, pa, sizeof(ParticleData));
+ memcpy(npoint, point, sizeof(PTCacheEditPoint));
+ npa++;
+ npoint++;
+ }
+ }
+
+ if (psys->particles)
+ MEM_freeN(psys->particles);
+ psys->particles = new_pars;
+
+ if (edit->points)
+ MEM_freeN(edit->points);
+ edit->points = new_points;
+
+ if (edit->mirror_cache) {
+ MEM_freeN(edit->mirror_cache);
+ edit->mirror_cache = NULL;
+ }
+
+ if (psys->child) {
+ MEM_freeN(psys->child);
+ psys->child = NULL;
+ psys->totchild = 0;
+ }
+
+ edit->totpoint = psys->totpart = new_totpart;
+ }
+
+ return removed;
}
static void remove_tagged_keys(Object *ob, ParticleSystem *psys)
{
- PTCacheEdit *edit = psys->edit;
- ParticleData *pa;
- HairKey *hkey, *nhkey, *new_hkeys = 0;
- POINT_P; KEY_K;
- PTCacheEditKey *nkey, *new_keys;
- ParticleSystemModifierData *psmd_eval;
- short new_totkey;
-
- if (pe_x_mirror(ob)) {
- /* mirror key tags */
- psmd_eval = psys_get_modifier(ob, psys);
-
- LOOP_POINTS {
- LOOP_TAGGED_KEYS {
- PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL);
- break;
- }
- }
- }
-
- LOOP_POINTS {
- new_totkey = point->totkey;
- LOOP_TAGGED_KEYS {
- new_totkey--;
- }
- /* we can't have elements with less than two keys*/
- if (new_totkey < 2)
- point->flag |= PEP_TAG;
- }
- remove_tagged_particles(ob, psys, pe_x_mirror(ob));
-
- LOOP_POINTS {
- pa = psys->particles + p;
- new_totkey = pa->totkey;
-
- LOOP_TAGGED_KEYS {
- new_totkey--;
- }
-
- if (new_totkey != pa->totkey) {
- nhkey = new_hkeys = MEM_callocN(new_totkey * sizeof(HairKey), "HairKeys");
- nkey = new_keys = MEM_callocN(new_totkey * sizeof(PTCacheEditKey), "particle edit keys");
-
- hkey = pa->hair;
- LOOP_KEYS {
- while (key->flag & PEK_TAG && hkey < pa->hair + pa->totkey) {
- key++;
- hkey++;
- }
-
- if (hkey < pa->hair + pa->totkey) {
- copy_v3_v3(nhkey->co, hkey->co);
- nhkey->editflag = hkey->editflag;
- nhkey->time = hkey->time;
- nhkey->weight = hkey->weight;
-
- nkey->co = nhkey->co;
- nkey->time = &nhkey->time;
- /* these can be copied from old edit keys */
- nkey->flag = key->flag;
- nkey->ftime = key->ftime;
- nkey->length = key->length;
- copy_v3_v3(nkey->world_co, key->world_co);
- }
- nkey++;
- nhkey++;
- hkey++;
- }
-
- if (pa->hair)
- MEM_freeN(pa->hair);
-
- if (point->keys)
- MEM_freeN(point->keys);
-
- pa->hair = new_hkeys;
- point->keys = new_keys;
-
- point->totkey = pa->totkey = new_totkey;
-
- /* flag for recalculating length */
- point->flag |= PEP_EDIT_RECALC;
- }
- }
+ PTCacheEdit *edit = psys->edit;
+ ParticleData *pa;
+ HairKey *hkey, *nhkey, *new_hkeys = 0;
+ POINT_P;
+ KEY_K;
+ PTCacheEditKey *nkey, *new_keys;
+ ParticleSystemModifierData *psmd_eval;
+ short new_totkey;
+
+ if (pe_x_mirror(ob)) {
+ /* mirror key tags */
+ psmd_eval = psys_get_modifier(ob, psys);
+
+ LOOP_POINTS
+ {
+ LOOP_TAGGED_KEYS
+ {
+ PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL);
+ break;
+ }
+ }
+ }
+
+ LOOP_POINTS
+ {
+ new_totkey = point->totkey;
+ LOOP_TAGGED_KEYS
+ {
+ new_totkey--;
+ }
+ /* we can't have elements with less than two keys*/
+ if (new_totkey < 2)
+ point->flag |= PEP_TAG;
+ }
+ remove_tagged_particles(ob, psys, pe_x_mirror(ob));
+
+ LOOP_POINTS
+ {
+ pa = psys->particles + p;
+ new_totkey = pa->totkey;
+
+ LOOP_TAGGED_KEYS
+ {
+ new_totkey--;
+ }
+
+ if (new_totkey != pa->totkey) {
+ nhkey = new_hkeys = MEM_callocN(new_totkey * sizeof(HairKey), "HairKeys");
+ nkey = new_keys = MEM_callocN(new_totkey * sizeof(PTCacheEditKey), "particle edit keys");
+
+ hkey = pa->hair;
+ LOOP_KEYS
+ {
+ while (key->flag & PEK_TAG && hkey < pa->hair + pa->totkey) {
+ key++;
+ hkey++;
+ }
+
+ if (hkey < pa->hair + pa->totkey) {
+ copy_v3_v3(nhkey->co, hkey->co);
+ nhkey->editflag = hkey->editflag;
+ nhkey->time = hkey->time;
+ nhkey->weight = hkey->weight;
+
+ nkey->co = nhkey->co;
+ nkey->time = &nhkey->time;
+ /* these can be copied from old edit keys */
+ nkey->flag = key->flag;
+ nkey->ftime = key->ftime;
+ nkey->length = key->length;
+ copy_v3_v3(nkey->world_co, key->world_co);
+ }
+ nkey++;
+ nhkey++;
+ hkey++;
+ }
+
+ if (pa->hair)
+ MEM_freeN(pa->hair);
+
+ if (point->keys)
+ MEM_freeN(point->keys);
+
+ pa->hair = new_hkeys;
+ point->keys = new_keys;
+
+ point->totkey = pa->totkey = new_totkey;
+
+ /* flag for recalculating length */
+ point->flag |= PEP_EDIT_RECALC;
+ }
+ }
}
/************************ subdivide opertor *********************/
@@ -2740,308 +2827,326 @@ static void remove_tagged_keys(Object *ob, ParticleSystem *psys)
/* works like normal edit mode subdivide, inserts keys between neighboring selected keys */
static void subdivide_particle(PEData *data, int pa_index)
{
- PTCacheEdit *edit = data->edit;
- ParticleSystem *psys = edit->psys;
- ParticleSimulationData sim = {0};
- ParticleData *pa = psys->particles + pa_index;
- PTCacheEditPoint *point = edit->points + pa_index;
- ParticleKey state;
- HairKey *key, *nkey, *new_keys;
- PTCacheEditKey *ekey, *nekey, *new_ekeys;
+ PTCacheEdit *edit = data->edit;
+ ParticleSystem *psys = edit->psys;
+ ParticleSimulationData sim = {0};
+ ParticleData *pa = psys->particles + pa_index;
+ PTCacheEditPoint *point = edit->points + pa_index;
+ ParticleKey state;
+ HairKey *key, *nkey, *new_keys;
+ PTCacheEditKey *ekey, *nekey, *new_ekeys;
- int k;
- short totnewkey = 0;
- float endtime;
+ int k;
+ short totnewkey = 0;
+ float endtime;
- sim.depsgraph = data->depsgraph;
- sim.scene = data->scene;
- sim.ob = data->ob;
- sim.psys = edit->psys;
+ sim.depsgraph = data->depsgraph;
+ sim.scene = data->scene;
+ sim.ob = data->ob;
+ sim.psys = edit->psys;
- for (k = 0, ekey = point->keys; k < pa->totkey - 1; k++, ekey++) {
- if (ekey->flag & PEK_SELECT && (ekey + 1)->flag & PEK_SELECT)
- totnewkey++;
- }
+ for (k = 0, ekey = point->keys; k < pa->totkey - 1; k++, ekey++) {
+ if (ekey->flag & PEK_SELECT && (ekey + 1)->flag & PEK_SELECT)
+ totnewkey++;
+ }
- if (totnewkey == 0) return;
+ if (totnewkey == 0)
+ return;
- pa->flag |= PARS_REKEY;
+ pa->flag |= PARS_REKEY;
- nkey = new_keys = MEM_callocN((pa->totkey + totnewkey) * (sizeof(HairKey)), "Hair subdivide keys");
- nekey = new_ekeys = MEM_callocN((pa->totkey + totnewkey) * (sizeof(PTCacheEditKey)), "Hair subdivide edit keys");
+ nkey = new_keys = MEM_callocN((pa->totkey + totnewkey) * (sizeof(HairKey)),
+ "Hair subdivide keys");
+ nekey = new_ekeys = MEM_callocN((pa->totkey + totnewkey) * (sizeof(PTCacheEditKey)),
+ "Hair subdivide edit keys");
- key = pa->hair;
- endtime = key[pa->totkey - 1].time;
+ key = pa->hair;
+ endtime = key[pa->totkey - 1].time;
- for (k = 0, ekey = point->keys; k < pa->totkey - 1; k++, key++, ekey++) {
+ for (k = 0, ekey = point->keys; k < pa->totkey - 1; k++, key++, ekey++) {
- memcpy(nkey, key, sizeof(HairKey));
- memcpy(nekey, ekey, sizeof(PTCacheEditKey));
+ memcpy(nkey, key, sizeof(HairKey));
+ memcpy(nekey, ekey, sizeof(PTCacheEditKey));
- nekey->co = nkey->co;
- nekey->time = &nkey->time;
+ nekey->co = nkey->co;
+ nekey->time = &nkey->time;
- nkey++;
- nekey++;
+ nkey++;
+ nekey++;
- if (ekey->flag & PEK_SELECT && (ekey + 1)->flag & PEK_SELECT) {
- nkey->time = (key->time + (key + 1)->time) * 0.5f;
- state.time = (endtime != 0.0f) ? nkey->time / endtime : 0.0f;
- psys_get_particle_on_path(&sim, pa_index, &state, 0);
- copy_v3_v3(nkey->co, state.co);
+ if (ekey->flag & PEK_SELECT && (ekey + 1)->flag & PEK_SELECT) {
+ nkey->time = (key->time + (key + 1)->time) * 0.5f;
+ state.time = (endtime != 0.0f) ? nkey->time / endtime : 0.0f;
+ psys_get_particle_on_path(&sim, pa_index, &state, 0);
+ copy_v3_v3(nkey->co, state.co);
- nekey->co = nkey->co;
- nekey->time = &nkey->time;
- nekey->flag |= PEK_SELECT;
- if (!(psys->flag & PSYS_GLOBAL_HAIR))
- nekey->flag |= PEK_USE_WCO;
+ nekey->co = nkey->co;
+ nekey->time = &nkey->time;
+ nekey->flag |= PEK_SELECT;
+ if (!(psys->flag & PSYS_GLOBAL_HAIR))
+ nekey->flag |= PEK_USE_WCO;
- nekey++;
- nkey++;
- }
- }
- /*tip still not copied*/
- memcpy(nkey, key, sizeof(HairKey));
- memcpy(nekey, ekey, sizeof(PTCacheEditKey));
+ nekey++;
+ nkey++;
+ }
+ }
+ /*tip still not copied*/
+ memcpy(nkey, key, sizeof(HairKey));
+ memcpy(nekey, ekey, sizeof(PTCacheEditKey));
- nekey->co = nkey->co;
- nekey->time = &nkey->time;
+ nekey->co = nkey->co;
+ nekey->time = &nkey->time;
- if (pa->hair)
- MEM_freeN(pa->hair);
- pa->hair = new_keys;
+ if (pa->hair)
+ MEM_freeN(pa->hair);
+ pa->hair = new_keys;
- if (point->keys)
- MEM_freeN(point->keys);
- point->keys = new_ekeys;
+ if (point->keys)
+ MEM_freeN(point->keys);
+ point->keys = new_ekeys;
- point->totkey = pa->totkey = pa->totkey + totnewkey;
- point->flag |= PEP_EDIT_RECALC;
- pa->flag &= ~PARS_REKEY;
+ point->totkey = pa->totkey = pa->totkey + totnewkey;
+ point->flag |= PEP_EDIT_RECALC;
+ pa->flag &= ~PARS_REKEY;
}
static int subdivide_exec(bContext *C, wmOperator *UNUSED(op))
{
- PEData data;
+ PEData data;
- PE_set_data(C, &data);
- foreach_point(&data, subdivide_particle);
+ PE_set_data(C, &data);
+ foreach_point(&data, subdivide_particle);
- recalc_lengths(data.edit);
- PE_update_selection(data.depsgraph, data.scene, data.ob, 1);
- PE_update_object(data.depsgraph, data.scene, data.ob, 1);
- DEG_id_tag_update(&data.ob->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, data.ob);
+ recalc_lengths(data.edit);
+ PE_update_selection(data.depsgraph, data.scene, data.ob, 1);
+ PE_update_object(data.depsgraph, data.scene, data.ob, 1);
+ DEG_id_tag_update(&data.ob->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, data.ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_subdivide(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Subdivide";
- ot->idname = "PARTICLE_OT_subdivide";
- ot->description = "Subdivide selected particles segments (adds keys)";
+ /* identifiers */
+ ot->name = "Subdivide";
+ ot->idname = "PARTICLE_OT_subdivide";
+ ot->description = "Subdivide selected particles segments (adds keys)";
- /* api callbacks */
- ot->exec = subdivide_exec;
- ot->poll = PE_hair_poll;
+ /* api callbacks */
+ ot->exec = subdivide_exec;
+ ot->poll = PE_hair_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************ remove doubles opertor *********************/
static int remove_doubles_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- ParticleSystem *psys = edit->psys;
- ParticleSystemModifierData *psmd_eval;
- KDTree_3d *tree;
- KDTreeNearest_3d nearest[10];
- POINT_P;
- float mat[4][4], co[3], threshold = RNA_float_get(op->ptr, "threshold");
- int n, totn, removed, totremoved;
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ ParticleSystem *psys = edit->psys;
+ ParticleSystemModifierData *psmd_eval;
+ KDTree_3d *tree;
+ KDTreeNearest_3d nearest[10];
+ POINT_P;
+ float mat[4][4], co[3], threshold = RNA_float_get(op->ptr, "threshold");
+ int n, totn, removed, totremoved;
- if (psys->flag & PSYS_GLOBAL_HAIR)
- return OPERATOR_CANCELLED;
+ if (psys->flag & PSYS_GLOBAL_HAIR)
+ return OPERATOR_CANCELLED;
- edit = psys->edit;
- psmd_eval = edit->psmd_eval;
- totremoved = 0;
+ edit = psys->edit;
+ psmd_eval = edit->psmd_eval;
+ totremoved = 0;
- do {
- removed = 0;
+ do {
+ removed = 0;
- tree = BLI_kdtree_3d_new(psys->totpart);
+ tree = BLI_kdtree_3d_new(psys->totpart);
- /* insert particles into kd tree */
- LOOP_SELECTED_POINTS {
- psys_mat_hair_to_object(ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
- copy_v3_v3(co, point->keys->co);
- mul_m4_v3(mat, co);
- BLI_kdtree_3d_insert(tree, p, co);
- }
+ /* insert particles into kd tree */
+ LOOP_SELECTED_POINTS
+ {
+ psys_mat_hair_to_object(
+ ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
+ copy_v3_v3(co, point->keys->co);
+ mul_m4_v3(mat, co);
+ BLI_kdtree_3d_insert(tree, p, co);
+ }
- BLI_kdtree_3d_balance(tree);
+ BLI_kdtree_3d_balance(tree);
- /* tag particles to be removed */
- LOOP_SELECTED_POINTS {
- psys_mat_hair_to_object(ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
- copy_v3_v3(co, point->keys->co);
- mul_m4_v3(mat, co);
+ /* tag particles to be removed */
+ LOOP_SELECTED_POINTS
+ {
+ psys_mat_hair_to_object(
+ ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
+ copy_v3_v3(co, point->keys->co);
+ mul_m4_v3(mat, co);
- totn = BLI_kdtree_3d_find_nearest_n(tree, co, nearest, 10);
+ totn = BLI_kdtree_3d_find_nearest_n(tree, co, nearest, 10);
- for (n = 0; n < totn; n++) {
- /* this needs a custom threshold still */
- if (nearest[n].index > p && nearest[n].dist < threshold) {
- if (!(point->flag & PEP_TAG)) {
- point->flag |= PEP_TAG;
- removed++;
- }
- }
- }
- }
+ for (n = 0; n < totn; n++) {
+ /* this needs a custom threshold still */
+ if (nearest[n].index > p && nearest[n].dist < threshold) {
+ if (!(point->flag & PEP_TAG)) {
+ point->flag |= PEP_TAG;
+ removed++;
+ }
+ }
+ }
+ }
- BLI_kdtree_3d_free(tree);
+ BLI_kdtree_3d_free(tree);
- /* remove tagged particles - don't do mirror here! */
- remove_tagged_particles(ob, psys, 0);
- totremoved += removed;
- } while (removed);
+ /* remove tagged particles - don't do mirror here! */
+ remove_tagged_particles(ob, psys, 0);
+ totremoved += removed;
+ } while (removed);
- if (totremoved == 0)
- return OPERATOR_CANCELLED;
+ if (totremoved == 0)
+ return OPERATOR_CANCELLED;
- BKE_reportf(op->reports, RPT_INFO, "Removed %d double particles", totremoved);
+ BKE_reportf(op->reports, RPT_INFO, "Removed %d double particles", totremoved);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_remove_doubles(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Doubles";
- ot->idname = "PARTICLE_OT_remove_doubles";
- ot->description = "Remove selected particles close enough of others";
+ /* identifiers */
+ ot->name = "Remove Doubles";
+ ot->idname = "PARTICLE_OT_remove_doubles";
+ ot->description = "Remove selected particles close enough of others";
- /* api callbacks */
- ot->exec = remove_doubles_exec;
- ot->poll = PE_hair_poll;
+ /* api callbacks */
+ ot->exec = remove_doubles_exec;
+ ot->poll = PE_hair_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_float(ot->srna, "threshold", 0.0002f, 0.0f, FLT_MAX,
- "Merge Distance", "Threshold distance within which particles are removed", 0.00001f, 0.1f);
+ /* properties */
+ RNA_def_float(ot->srna,
+ "threshold",
+ 0.0002f,
+ 0.0f,
+ FLT_MAX,
+ "Merge Distance",
+ "Threshold distance within which particles are removed",
+ 0.00001f,
+ 0.1f);
}
-
static int weight_set_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ParticleEditSettings *pset = PE_settings(scene);
- Object *ob = CTX_data_active_object(C);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- ParticleSystem *psys = edit->psys;
- POINT_P;
- KEY_K;
- HairKey *hkey;
- float weight;
- ParticleBrushData *brush = &pset->brush[pset->brushtype];
- float factor = RNA_float_get(op->ptr, "factor");
+ Scene *scene = CTX_data_scene(C);
+ ParticleEditSettings *pset = PE_settings(scene);
+ Object *ob = CTX_data_active_object(C);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ ParticleSystem *psys = edit->psys;
+ POINT_P;
+ KEY_K;
+ HairKey *hkey;
+ float weight;
+ ParticleBrushData *brush = &pset->brush[pset->brushtype];
+ float factor = RNA_float_get(op->ptr, "factor");
- weight = brush->strength;
- edit = psys->edit;
+ weight = brush->strength;
+ edit = psys->edit;
- LOOP_SELECTED_POINTS {
- ParticleData *pa = psys->particles + p;
+ LOOP_SELECTED_POINTS
+ {
+ ParticleData *pa = psys->particles + p;
- LOOP_SELECTED_KEYS {
- hkey = pa->hair + k;
- hkey->weight = interpf(weight, hkey->weight, factor);
- }
- }
+ LOOP_SELECTED_KEYS
+ {
+ hkey = pa->hair + k;
+ hkey->weight = interpf(weight, hkey->weight, factor);
+ }
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_weight_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Weight Set";
- ot->idname = "PARTICLE_OT_weight_set";
- ot->description = "Set the weight of selected keys";
+ /* identifiers */
+ ot->name = "Weight Set";
+ ot->idname = "PARTICLE_OT_weight_set";
+ ot->description = "Set the weight of selected keys";
- /* api callbacks */
- ot->exec = weight_set_exec;
- ot->poll = PE_hair_poll;
+ /* api callbacks */
+ ot->exec = weight_set_exec;
+ ot->poll = PE_hair_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_float(ot->srna, "factor", 1, 0, 1, "Factor",
- "Interpolation factor between current brush weight, and keys' weights", 0, 1);
+ RNA_def_float(ot->srna,
+ "factor",
+ 1,
+ 0,
+ 1,
+ "Factor",
+ "Interpolation factor between current brush weight, and keys' weights",
+ 0,
+ 1);
}
/************************ cursor drawing *******************************/
static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata))
{
- Scene *scene = CTX_data_scene(C);
- ParticleEditSettings *pset = PE_settings(scene);
- ParticleBrushData *brush;
+ Scene *scene = CTX_data_scene(C);
+ ParticleEditSettings *pset = PE_settings(scene);
+ ParticleBrushData *brush;
- if (!WM_toolsystem_active_tool_is_brush(C)) {
- return;
- }
+ if (!WM_toolsystem_active_tool_is_brush(C)) {
+ return;
+ }
- brush = &pset->brush[pset->brushtype];
+ brush = &pset->brush[pset->brushtype];
- if (brush) {
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ if (brush) {
+ 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, 128);
+ immUniformColor4ub(255, 255, 255, 128);
- GPU_line_smooth(true);
- GPU_blend(true);
+ GPU_line_smooth(true);
+ GPU_blend(true);
- imm_draw_circle_wire_2d(pos, (float)x, (float)y, pe_brush_size_get(scene, brush), 40);
+ imm_draw_circle_wire_2d(pos, (float)x, (float)y, pe_brush_size_get(scene, brush), 40);
- GPU_blend(false);
- GPU_line_smooth(false);
+ GPU_blend(false);
+ GPU_line_smooth(false);
- immUnbindProgram();
- }
+ immUnbindProgram();
+ }
}
static void toggle_particle_cursor(bContext *C, int enable)
{
- ParticleEditSettings *pset = PE_settings(CTX_data_scene(C));
+ ParticleEditSettings *pset = PE_settings(CTX_data_scene(C));
- if (pset->paintcursor && !enable) {
- WM_paint_cursor_end(CTX_wm_manager(C), pset->paintcursor);
- pset->paintcursor = NULL;
- }
- else if (enable)
- pset->paintcursor = WM_paint_cursor_activate(
- CTX_wm_manager(C),
- SPACE_VIEW3D, RGN_TYPE_WINDOW,
- PE_poll_view3d,
- brush_drawcursor,
- NULL);
+ if (pset->paintcursor && !enable) {
+ WM_paint_cursor_end(CTX_wm_manager(C), pset->paintcursor);
+ pset->paintcursor = NULL;
+ }
+ else if (enable)
+ pset->paintcursor = WM_paint_cursor_activate(
+ CTX_wm_manager(C), SPACE_VIEW3D, RGN_TYPE_WINDOW, PE_poll_view3d, brush_drawcursor, NULL);
}
/*************************** delete operator **************************/
@@ -3049,2126 +3154,2190 @@ static void toggle_particle_cursor(bContext *C, int enable)
enum { DEL_PARTICLE, DEL_KEY };
static const EnumPropertyItem delete_type_items[] = {
- {DEL_PARTICLE, "PARTICLE", 0, "Particle", ""},
- {DEL_KEY, "KEY", 0, "Key", ""},
- {0, NULL, 0, NULL, NULL},
+ {DEL_PARTICLE, "PARTICLE", 0, "Particle", ""},
+ {DEL_KEY, "KEY", 0, "Key", ""},
+ {0, NULL, 0, NULL, NULL},
};
static void set_delete_particle(PEData *data, int pa_index)
{
- PTCacheEdit *edit = data->edit;
+ PTCacheEdit *edit = data->edit;
- edit->points[pa_index].flag |= PEP_TAG;
+ edit->points[pa_index].flag |= PEP_TAG;
}
-static void set_delete_particle_key(PEData *data, int pa_index, int key_index, bool UNUSED(is_inside))
+static void set_delete_particle_key(PEData *data,
+ int pa_index,
+ int key_index,
+ bool UNUSED(is_inside))
{
- PTCacheEdit *edit = data->edit;
+ PTCacheEdit *edit = data->edit;
- edit->points[pa_index].keys[key_index].flag |= PEK_TAG;
+ edit->points[pa_index].keys[key_index].flag |= PEK_TAG;
}
static int delete_exec(bContext *C, wmOperator *op)
{
- PEData data;
- int type = RNA_enum_get(op->ptr, "type");
+ PEData data;
+ int type = RNA_enum_get(op->ptr, "type");
- PE_set_data(C, &data);
+ PE_set_data(C, &data);
- if (type == DEL_KEY) {
- foreach_selected_key(&data, set_delete_particle_key);
- remove_tagged_keys(data.ob, data.edit->psys);
- recalc_lengths(data.edit);
- }
- else if (type == DEL_PARTICLE) {
- foreach_selected_point(&data, set_delete_particle);
- remove_tagged_particles(data.ob, data.edit->psys, pe_x_mirror(data.ob));
- recalc_lengths(data.edit);
- }
+ if (type == DEL_KEY) {
+ foreach_selected_key(&data, set_delete_particle_key);
+ remove_tagged_keys(data.ob, data.edit->psys);
+ recalc_lengths(data.edit);
+ }
+ else if (type == DEL_PARTICLE) {
+ foreach_selected_point(&data, set_delete_particle);
+ remove_tagged_particles(data.ob, data.edit->psys, pe_x_mirror(data.ob));
+ recalc_lengths(data.edit);
+ }
- DEG_id_tag_update(&data.ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, data.ob);
+ DEG_id_tag_update(&data.ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, data.ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete";
- ot->idname = "PARTICLE_OT_delete";
- ot->description = "Delete selected particles or keys";
+ /* identifiers */
+ ot->name = "Delete";
+ ot->idname = "PARTICLE_OT_delete";
+ ot->description = "Delete selected particles or keys";
- /* api callbacks */
- ot->exec = delete_exec;
- ot->invoke = WM_menu_invoke;
- ot->poll = PE_hair_poll;
+ /* api callbacks */
+ ot->exec = delete_exec;
+ ot->invoke = WM_menu_invoke;
+ ot->poll = PE_hair_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", delete_type_items, DEL_PARTICLE, "Type", "Delete a full particle or only keys");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna,
+ "type",
+ delete_type_items,
+ DEL_PARTICLE,
+ "Type",
+ "Delete a full particle or only keys");
}
/*************************** mirror operator **************************/
-static void PE_mirror_x(
- Scene *scene, Object *ob, int tagged)
-{
- Mesh *me = (Mesh *)(ob->data);
- ParticleSystemModifierData *psmd_eval;
- PTCacheEdit *edit = PE_get_current(scene, ob);
- ParticleSystem *psys = edit->psys;
- ParticleData *pa, *newpa, *new_pars;
- PTCacheEditPoint *newpoint, *new_points;
- POINT_P; KEY_K;
- HairKey *hkey;
- int *mirrorfaces = NULL;
- int rotation, totpart, newtotpart;
-
- if (psys->flag & PSYS_GLOBAL_HAIR)
- return;
-
- psmd_eval = edit->psmd_eval;
- if (!psmd_eval->mesh_final)
- return;
-
- const bool use_dm_final_indices = (psys->part->use_modifier_stack && !psmd_eval->mesh_final->runtime.deformed_only);
-
- /* NOTE: this is not nice to use tessfaces but hard to avoid since pa->num uses tessfaces */
- BKE_mesh_tessface_ensure(me);
-
- /* Note: In case psys uses Mesh tessface indices, we mirror final Mesh itself, not orig mesh. Avoids an (impossible)
- * mesh -> orig -> mesh tessface indices conversion... */
- mirrorfaces = mesh_get_x_mirror_faces(ob, NULL, use_dm_final_indices ? psmd_eval->mesh_final : NULL);
-
- if (!edit->mirror_cache)
- PE_update_mirror_cache(ob, psys);
-
- totpart = psys->totpart;
- newtotpart = psys->totpart;
- LOOP_VISIBLE_POINTS {
- pa = psys->particles + p;
-
- if (!tagged) {
- if (point_is_selected(point)) {
- if (edit->mirror_cache[p] != -1) {
- /* already has a mirror, don't need to duplicate */
- PE_mirror_particle(ob, psmd_eval->mesh_final, psys, pa, NULL);
- continue;
- }
- else
- point->flag |= PEP_TAG;
- }
- }
-
- if ((point->flag & PEP_TAG) && mirrorfaces[pa->num * 2] != -1)
- newtotpart++;
- }
-
- if (newtotpart != psys->totpart) {
- MFace *mtessface = use_dm_final_indices ? psmd_eval->mesh_final->mface : me->mface;
-
- /* allocate new arrays and copy existing */
- new_pars = MEM_callocN(newtotpart * sizeof(ParticleData), "ParticleData new");
- new_points = MEM_callocN(newtotpart * sizeof(PTCacheEditPoint), "PTCacheEditPoint new");
-
- if (psys->particles) {
- memcpy(new_pars, psys->particles, totpart * sizeof(ParticleData));
- MEM_freeN(psys->particles);
- }
- psys->particles = new_pars;
-
- if (edit->points) {
- memcpy(new_points, edit->points, totpart * sizeof(PTCacheEditPoint));
- MEM_freeN(edit->points);
- }
- edit->points = new_points;
-
- if (edit->mirror_cache) {
- MEM_freeN(edit->mirror_cache);
- edit->mirror_cache = NULL;
- }
-
- edit->totpoint = psys->totpart = newtotpart;
-
- /* create new elements */
- newpa = psys->particles + totpart;
- newpoint = edit->points + totpart;
-
- for (p = 0, point = edit->points; p < totpart; p++, point++) {
- pa = psys->particles + p;
- const int pa_num = pa->num;
-
- if (point->flag & PEP_HIDE)
- continue;
-
- if (!(point->flag & PEP_TAG) || mirrorfaces[pa_num * 2] == -1)
- continue;
-
- /* duplicate */
- *newpa = *pa;
- *newpoint = *point;
- if (pa->hair) newpa->hair = MEM_dupallocN(pa->hair);
- if (point->keys) newpoint->keys = MEM_dupallocN(point->keys);
-
- /* rotate weights according to vertex index rotation */
- rotation = mirrorfaces[pa_num * 2 + 1];
- newpa->fuv[0] = pa->fuv[2];
- newpa->fuv[1] = pa->fuv[1];
- newpa->fuv[2] = pa->fuv[0];
- newpa->fuv[3] = pa->fuv[3];
- while (rotation--) {
- if (mtessface[pa_num].v4) {
- SHIFT4(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2], newpa->fuv[3]);
- }
- else {
- SHIFT3(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2]);
- }
- }
-
- /* assign face index */
- /* NOTE: mesh_get_x_mirror_faces generates -1 for non-found mirror, same as DMCACHE_NOTFOUND... */
- newpa->num = mirrorfaces[pa_num * 2];
-
- if (use_dm_final_indices) {
- newpa->num_dmcache = DMCACHE_ISCHILD;
- }
- else {
- newpa->num_dmcache = psys_particle_dm_face_lookup(
- psmd_eval->mesh_final, psmd_eval->mesh_original, newpa->num, newpa->fuv, NULL);
- }
-
- /* update edit key pointers */
- key = newpoint->keys;
- for (k = 0, hkey = newpa->hair; k < newpa->totkey; k++, hkey++, key++) {
- key->co = hkey->co;
- key->time = &hkey->time;
- }
-
- /* map key positions as mirror over x axis */
- PE_mirror_particle(ob, psmd_eval->mesh_final, psys, pa, newpa);
-
- newpa++;
- newpoint++;
- }
- }
-
- LOOP_POINTS {
- point->flag &= ~PEP_TAG;
- }
-
- MEM_freeN(mirrorfaces);
+static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
+{
+ Mesh *me = (Mesh *)(ob->data);
+ ParticleSystemModifierData *psmd_eval;
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ ParticleSystem *psys = edit->psys;
+ ParticleData *pa, *newpa, *new_pars;
+ PTCacheEditPoint *newpoint, *new_points;
+ POINT_P;
+ KEY_K;
+ HairKey *hkey;
+ int *mirrorfaces = NULL;
+ int rotation, totpart, newtotpart;
+
+ if (psys->flag & PSYS_GLOBAL_HAIR)
+ return;
+
+ psmd_eval = edit->psmd_eval;
+ if (!psmd_eval->mesh_final)
+ return;
+
+ const bool use_dm_final_indices = (psys->part->use_modifier_stack &&
+ !psmd_eval->mesh_final->runtime.deformed_only);
+
+ /* NOTE: this is not nice to use tessfaces but hard to avoid since pa->num uses tessfaces */
+ BKE_mesh_tessface_ensure(me);
+
+ /* Note: In case psys uses Mesh tessface indices, we mirror final Mesh itself, not orig mesh. Avoids an (impossible)
+ * mesh -> orig -> mesh tessface indices conversion... */
+ mirrorfaces = mesh_get_x_mirror_faces(
+ ob, NULL, use_dm_final_indices ? psmd_eval->mesh_final : NULL);
+
+ if (!edit->mirror_cache)
+ PE_update_mirror_cache(ob, psys);
+
+ totpart = psys->totpart;
+ newtotpart = psys->totpart;
+ LOOP_VISIBLE_POINTS
+ {
+ pa = psys->particles + p;
+
+ if (!tagged) {
+ if (point_is_selected(point)) {
+ if (edit->mirror_cache[p] != -1) {
+ /* already has a mirror, don't need to duplicate */
+ PE_mirror_particle(ob, psmd_eval->mesh_final, psys, pa, NULL);
+ continue;
+ }
+ else
+ point->flag |= PEP_TAG;
+ }
+ }
+
+ if ((point->flag & PEP_TAG) && mirrorfaces[pa->num * 2] != -1)
+ newtotpart++;
+ }
+
+ if (newtotpart != psys->totpart) {
+ MFace *mtessface = use_dm_final_indices ? psmd_eval->mesh_final->mface : me->mface;
+
+ /* allocate new arrays and copy existing */
+ new_pars = MEM_callocN(newtotpart * sizeof(ParticleData), "ParticleData new");
+ new_points = MEM_callocN(newtotpart * sizeof(PTCacheEditPoint), "PTCacheEditPoint new");
+
+ if (psys->particles) {
+ memcpy(new_pars, psys->particles, totpart * sizeof(ParticleData));
+ MEM_freeN(psys->particles);
+ }
+ psys->particles = new_pars;
+
+ if (edit->points) {
+ memcpy(new_points, edit->points, totpart * sizeof(PTCacheEditPoint));
+ MEM_freeN(edit->points);
+ }
+ edit->points = new_points;
+
+ if (edit->mirror_cache) {
+ MEM_freeN(edit->mirror_cache);
+ edit->mirror_cache = NULL;
+ }
+
+ edit->totpoint = psys->totpart = newtotpart;
+
+ /* create new elements */
+ newpa = psys->particles + totpart;
+ newpoint = edit->points + totpart;
+
+ for (p = 0, point = edit->points; p < totpart; p++, point++) {
+ pa = psys->particles + p;
+ const int pa_num = pa->num;
+
+ if (point->flag & PEP_HIDE)
+ continue;
+
+ if (!(point->flag & PEP_TAG) || mirrorfaces[pa_num * 2] == -1)
+ continue;
+
+ /* duplicate */
+ *newpa = *pa;
+ *newpoint = *point;
+ if (pa->hair)
+ newpa->hair = MEM_dupallocN(pa->hair);
+ if (point->keys)
+ newpoint->keys = MEM_dupallocN(point->keys);
+
+ /* rotate weights according to vertex index rotation */
+ rotation = mirrorfaces[pa_num * 2 + 1];
+ newpa->fuv[0] = pa->fuv[2];
+ newpa->fuv[1] = pa->fuv[1];
+ newpa->fuv[2] = pa->fuv[0];
+ newpa->fuv[3] = pa->fuv[3];
+ while (rotation--) {
+ if (mtessface[pa_num].v4) {
+ SHIFT4(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2], newpa->fuv[3]);
+ }
+ else {
+ SHIFT3(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2]);
+ }
+ }
+
+ /* assign face index */
+ /* NOTE: mesh_get_x_mirror_faces generates -1 for non-found mirror, same as DMCACHE_NOTFOUND... */
+ newpa->num = mirrorfaces[pa_num * 2];
+
+ if (use_dm_final_indices) {
+ newpa->num_dmcache = DMCACHE_ISCHILD;
+ }
+ else {
+ newpa->num_dmcache = psys_particle_dm_face_lookup(
+ psmd_eval->mesh_final, psmd_eval->mesh_original, newpa->num, newpa->fuv, NULL);
+ }
+
+ /* update edit key pointers */
+ key = newpoint->keys;
+ for (k = 0, hkey = newpa->hair; k < newpa->totkey; k++, hkey++, key++) {
+ key->co = hkey->co;
+ key->time = &hkey->time;
+ }
+
+ /* map key positions as mirror over x axis */
+ PE_mirror_particle(ob, psmd_eval->mesh_final, psys, pa, newpa);
+
+ newpa++;
+ newpoint++;
+ }
+ }
+
+ LOOP_POINTS
+ {
+ point->flag &= ~PEP_TAG;
+ }
+
+ MEM_freeN(mirrorfaces);
}
static int mirror_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- PTCacheEdit *edit = PE_get_current(scene, ob);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
- PE_mirror_x(scene, ob, 0);
+ PE_mirror_x(scene, ob, 0);
- update_world_cos(CTX_data_depsgraph(C), ob, edit);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ update_world_cos(CTX_data_depsgraph(C), ob, edit);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_mirror(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Mirror";
- ot->idname = "PARTICLE_OT_mirror";
- ot->description = "Duplicate and mirror the selected particles along the local X axis";
+ /* identifiers */
+ ot->name = "Mirror";
+ ot->idname = "PARTICLE_OT_mirror";
+ ot->description = "Duplicate and mirror the selected particles along the local X axis";
- /* api callbacks */
- ot->exec = mirror_exec;
- ot->poll = PE_hair_poll;
+ /* api callbacks */
+ ot->exec = mirror_exec;
+ ot->poll = PE_hair_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************* brush edit callbacks ********************/
-static void brush_comb(
- PEData *data,
- float UNUSED(mat[4][4]),
- float imat[4][4],
- int point_index,
- int key_index,
- PTCacheEditKey *key,
- float mouse_distance)
+static void brush_comb(PEData *data,
+ float UNUSED(mat[4][4]),
+ float imat[4][4],
+ int point_index,
+ int key_index,
+ PTCacheEditKey *key,
+ float mouse_distance)
{
- ParticleEditSettings *pset = PE_settings(data->scene);
- float cvec[3], fac;
+ ParticleEditSettings *pset = PE_settings(data->scene);
+ float cvec[3], fac;
- if (pset->flag & PE_LOCK_FIRST && key_index == 0) return;
+ if (pset->flag & PE_LOCK_FIRST && key_index == 0)
+ return;
- fac = (float)pow((double)(1.0f - mouse_distance / data->rad), (double)data->combfac);
+ fac = (float)pow((double)(1.0f - mouse_distance / data->rad), (double)data->combfac);
- copy_v3_v3(cvec, data->dvec);
- mul_mat3_m4_v3(imat, cvec);
- mul_v3_fl(cvec, fac);
- add_v3_v3(key->co, cvec);
+ copy_v3_v3(cvec, data->dvec);
+ mul_mat3_m4_v3(imat, cvec);
+ mul_v3_fl(cvec, fac);
+ add_v3_v3(key->co, cvec);
- (data->edit->points + point_index)->flag |= PEP_EDIT_RECALC;
+ (data->edit->points + point_index)->flag |= PEP_EDIT_RECALC;
}
static void brush_cut(PEData *data, int pa_index)
{
- PTCacheEdit *edit = data->edit;
- ARegion *ar = data->vc.ar;
- Object *ob = data->ob;
- ParticleEditSettings *pset = PE_settings(data->scene);
- ParticleCacheKey *key = edit->pathcache[pa_index];
- float rad2, cut_time = 1.0;
- float x0, x1, v0, v1, o0, o1, xo0, xo1, d, dv;
- int k, cut, keys = (int)pow(2.0, (double)pset->draw_step);
- int screen_co[2];
+ PTCacheEdit *edit = data->edit;
+ ARegion *ar = data->vc.ar;
+ Object *ob = data->ob;
+ ParticleEditSettings *pset = PE_settings(data->scene);
+ ParticleCacheKey *key = edit->pathcache[pa_index];
+ float rad2, cut_time = 1.0;
+ float x0, x1, v0, v1, o0, o1, xo0, xo1, d, dv;
+ int k, cut, keys = (int)pow(2.0, (double)pset->draw_step);
+ int screen_co[2];
- BLI_assert(data->rng != NULL);
- /* blunt scissors */
- if (BLI_rng_get_float(data->rng) > data->cutfac) {
- return;
- }
+ BLI_assert(data->rng != NULL);
+ /* blunt scissors */
+ if (BLI_rng_get_float(data->rng) > data->cutfac) {
+ return;
+ }
- /* don't cut hidden */
- if (edit->points[pa_index].flag & PEP_HIDE)
- return;
+ /* don't cut hidden */
+ if (edit->points[pa_index].flag & PEP_HIDE)
+ return;
- if (ED_view3d_project_int_global(ar, key->co, screen_co, V3D_PROJ_TEST_CLIP_NEAR) != V3D_PROJ_RET_OK)
- return;
+ if (ED_view3d_project_int_global(ar, key->co, screen_co, V3D_PROJ_TEST_CLIP_NEAR) !=
+ V3D_PROJ_RET_OK)
+ return;
- rad2 = data->rad * data->rad;
+ rad2 = data->rad * data->rad;
- cut = 0;
+ cut = 0;
- x0 = (float)screen_co[0];
- x1 = (float)screen_co[1];
+ x0 = (float)screen_co[0];
+ x1 = (float)screen_co[1];
- o0 = (float)data->mval[0];
- o1 = (float)data->mval[1];
+ o0 = (float)data->mval[0];
+ o1 = (float)data->mval[1];
- xo0 = x0 - o0;
- xo1 = x1 - o1;
+ xo0 = x0 - o0;
+ xo1 = x1 - o1;
- /* check if root is inside circle */
- if (xo0 * xo0 + xo1 * xo1 < rad2 && key_test_depth(data, key->co, screen_co)) {
- cut_time = -1.0f;
- cut = 1;
- }
- else {
- /* calculate path time closest to root that was inside the circle */
- for (k = 1, key++; k <= keys; k++, key++) {
+ /* check if root is inside circle */
+ if (xo0 * xo0 + xo1 * xo1 < rad2 && key_test_depth(data, key->co, screen_co)) {
+ cut_time = -1.0f;
+ cut = 1;
+ }
+ else {
+ /* 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) != V3D_PROJ_RET_OK) ||
- key_test_depth(data, key->co, screen_co) == 0)
- {
- x0 = (float)screen_co[0];
- x1 = (float)screen_co[1];
+ if ((ED_view3d_project_int_global(ar, 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];
+ x1 = (float)screen_co[1];
- xo0 = x0 - o0;
- xo1 = x1 - o1;
- continue;
- }
+ xo0 = x0 - o0;
+ xo1 = x1 - o1;
+ continue;
+ }
- v0 = (float)screen_co[0] - x0;
- v1 = (float)screen_co[1] - x1;
+ v0 = (float)screen_co[0] - x0;
+ v1 = (float)screen_co[1] - x1;
- dv = v0 * v0 + v1 * v1;
+ dv = v0 * v0 + v1 * v1;
- d = (v0 * xo1 - v1 * xo0);
+ d = (v0 * xo1 - v1 * xo0);
- d = dv * rad2 - d * d;
+ d = dv * rad2 - d * d;
- if (d > 0.0f) {
- d = sqrtf(d);
+ if (d > 0.0f) {
+ d = sqrtf(d);
- cut_time = -(v0 * xo0 + v1 * xo1 + d);
+ cut_time = -(v0 * xo0 + v1 * xo1 + d);
- if (cut_time > 0.0f) {
- cut_time /= dv;
+ if (cut_time > 0.0f) {
+ cut_time /= dv;
- if (cut_time < 1.0f) {
- cut_time += (float)(k - 1);
- cut_time /= (float)keys;
- cut = 1;
- break;
- }
- }
- }
+ if (cut_time < 1.0f) {
+ cut_time += (float)(k - 1);
+ cut_time /= (float)keys;
+ cut = 1;
+ break;
+ }
+ }
+ }
- x0 = (float)screen_co[0];
- x1 = (float)screen_co[1];
+ x0 = (float)screen_co[0];
+ x1 = (float)screen_co[1];
- xo0 = x0 - o0;
- xo1 = x1 - o1;
- }
- }
+ xo0 = x0 - o0;
+ xo1 = x1 - o1;
+ }
+ }
- if (cut) {
- if (cut_time < 0.0f) {
- edit->points[pa_index].flag |= PEP_TAG;
- }
- else {
- rekey_particle_to_time(data->context, data->scene, ob, pa_index, cut_time);
- edit->points[pa_index].flag |= PEP_EDIT_RECALC;
- }
- }
+ if (cut) {
+ if (cut_time < 0.0f) {
+ edit->points[pa_index].flag |= PEP_TAG;
+ }
+ else {
+ rekey_particle_to_time(data->context, data->scene, ob, pa_index, cut_time);
+ edit->points[pa_index].flag |= PEP_EDIT_RECALC;
+ }
+ }
}
static void brush_length(PEData *data, int point_index, float UNUSED(mouse_distance))
{
- PTCacheEdit *edit = data->edit;
- PTCacheEditPoint *point = edit->points + point_index;
- KEY_K;
- float dvec[3], pvec[3] = {0.0f, 0.0f, 0.0f};
+ PTCacheEdit *edit = data->edit;
+ PTCacheEditPoint *point = edit->points + point_index;
+ KEY_K;
+ float dvec[3], pvec[3] = {0.0f, 0.0f, 0.0f};
- LOOP_KEYS {
- if (k == 0) {
- copy_v3_v3(pvec, key->co);
- }
- else {
- sub_v3_v3v3(dvec, key->co, pvec);
- copy_v3_v3(pvec, key->co);
- mul_v3_fl(dvec, data->growfac);
- add_v3_v3v3(key->co, (key - 1)->co, dvec);
- }
- }
+ LOOP_KEYS
+ {
+ if (k == 0) {
+ copy_v3_v3(pvec, key->co);
+ }
+ else {
+ sub_v3_v3v3(dvec, key->co, pvec);
+ copy_v3_v3(pvec, key->co);
+ mul_v3_fl(dvec, data->growfac);
+ add_v3_v3v3(key->co, (key - 1)->co, dvec);
+ }
+ }
- point->flag |= PEP_EDIT_RECALC;
+ point->flag |= PEP_EDIT_RECALC;
}
static void brush_puff(PEData *data, int point_index, float mouse_distance)
{
- PTCacheEdit *edit = data->edit;
- ParticleSystem *psys = edit->psys;
- PTCacheEditPoint *point = edit->points + point_index;
- KEY_K;
- float mat[4][4], imat[4][4];
-
- float onor_prev[3]; /* previous normal (particle-space) */
- float ofs_prev[3]; /* accumulate offset for puff_volume (particle-space) */
- float co_root[3], no_root[3]; /* root location and normal (global-space) */
- float co_prev[3], co[3]; /* track key coords as we loop (global-space) */
- float fac = 0.0f, length_accum = 0.0f;
- bool puff_volume = false;
- bool changed = false;
-
- zero_v3(ofs_prev);
-
- {
- ParticleEditSettings *pset = PE_settings(data->scene);
- ParticleBrushData *brush = &pset->brush[pset->brushtype];
- puff_volume = (brush->flag & PE_BRUSH_DATA_PUFF_VOLUME) != 0;
- }
-
- if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- psys_mat_hair_to_global(data->ob, data->mesh, psys->part->from, psys->particles + point_index, mat);
- invert_m4_m4(imat, mat);
- }
- else {
- unit_m4(mat);
- unit_m4(imat);
- }
-
- LOOP_KEYS {
- float kco[3];
-
- if (k == 0) {
- /* find root coordinate and normal on emitter */
- copy_v3_v3(co, key->co);
- mul_m4_v3(mat, co);
-
- /* use 'kco' as the object space version of worldspace 'co',
- * ob->imat is set before calling */
- mul_v3_m4v3(kco, data->ob->imat, co);
-
- point_index = BLI_kdtree_3d_find_nearest(edit->emitter_field, kco, NULL);
- if (point_index == -1) return;
-
- copy_v3_v3(co_root, co);
- copy_v3_v3(no_root, &edit->emitter_cosnos[point_index * 6 + 3]);
- mul_mat3_m4_v3(data->ob->obmat, no_root); /* normal into global-space */
- normalize_v3(no_root);
-
- if (puff_volume) {
- copy_v3_v3(onor_prev, no_root);
- mul_mat3_m4_v3(imat, onor_prev); /* global-space into particle space */
- normalize_v3(onor_prev);
- }
-
- fac = (float)pow((double)(1.0f - mouse_distance / data->rad), (double)data->pufffac);
- fac *= 0.025f;
- if (data->invert)
- fac = -fac;
- }
- else {
- /* compute position as if hair was standing up straight.
- * */
- float length;
- copy_v3_v3(co_prev, co);
- copy_v3_v3(co, key->co);
- mul_m4_v3(mat, co);
- length = len_v3v3(co_prev, co);
- length_accum += length;
-
- if ((data->select == 0 || (key->flag & PEK_SELECT)) && !(key->flag & PEK_HIDE)) {
- float dco[3]; /* delta temp var */
-
- madd_v3_v3v3fl(kco, co_root, no_root, length_accum);
-
- /* blend between the current and straight position */
- sub_v3_v3v3(dco, kco, co);
- madd_v3_v3fl(co, dco, fac);
- /* keep the same distance from the root or we get glitches [#35406] */
- dist_ensure_v3_v3fl(co, co_root, length_accum);
-
- /* re-use dco to compare before and after translation and add to the offset */
- copy_v3_v3(dco, key->co);
-
- mul_v3_m4v3(key->co, imat, co);
-
- if (puff_volume) {
- /* accumulate the total distance moved to apply to unselected
- * keys that come after */
- sub_v3_v3v3(ofs_prev, key->co, dco);
- }
- changed = true;
- }
- else {
-
- if (puff_volume) {
+ PTCacheEdit *edit = data->edit;
+ ParticleSystem *psys = edit->psys;
+ PTCacheEditPoint *point = edit->points + point_index;
+ KEY_K;
+ float mat[4][4], imat[4][4];
+
+ float onor_prev[3]; /* previous normal (particle-space) */
+ float ofs_prev[3]; /* accumulate offset for puff_volume (particle-space) */
+ float co_root[3], no_root[3]; /* root location and normal (global-space) */
+ float co_prev[3], co[3]; /* track key coords as we loop (global-space) */
+ float fac = 0.0f, length_accum = 0.0f;
+ bool puff_volume = false;
+ bool changed = false;
+
+ zero_v3(ofs_prev);
+
+ {
+ ParticleEditSettings *pset = PE_settings(data->scene);
+ ParticleBrushData *brush = &pset->brush[pset->brushtype];
+ puff_volume = (brush->flag & PE_BRUSH_DATA_PUFF_VOLUME) != 0;
+ }
+
+ if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
+ psys_mat_hair_to_global(
+ data->ob, data->mesh, psys->part->from, psys->particles + point_index, mat);
+ invert_m4_m4(imat, mat);
+ }
+ else {
+ unit_m4(mat);
+ unit_m4(imat);
+ }
+
+ LOOP_KEYS
+ {
+ float kco[3];
+
+ if (k == 0) {
+ /* find root coordinate and normal on emitter */
+ copy_v3_v3(co, key->co);
+ mul_m4_v3(mat, co);
+
+ /* use 'kco' as the object space version of worldspace 'co',
+ * ob->imat is set before calling */
+ mul_v3_m4v3(kco, data->ob->imat, co);
+
+ point_index = BLI_kdtree_3d_find_nearest(edit->emitter_field, kco, NULL);
+ if (point_index == -1)
+ return;
+
+ copy_v3_v3(co_root, co);
+ copy_v3_v3(no_root, &edit->emitter_cosnos[point_index * 6 + 3]);
+ mul_mat3_m4_v3(data->ob->obmat, no_root); /* normal into global-space */
+ normalize_v3(no_root);
+
+ if (puff_volume) {
+ copy_v3_v3(onor_prev, no_root);
+ mul_mat3_m4_v3(imat, onor_prev); /* global-space into particle space */
+ normalize_v3(onor_prev);
+ }
+
+ fac = (float)pow((double)(1.0f - mouse_distance / data->rad), (double)data->pufffac);
+ fac *= 0.025f;
+ if (data->invert)
+ fac = -fac;
+ }
+ else {
+ /* compute position as if hair was standing up straight.
+ * */
+ float length;
+ copy_v3_v3(co_prev, co);
+ copy_v3_v3(co, key->co);
+ mul_m4_v3(mat, co);
+ length = len_v3v3(co_prev, co);
+ length_accum += length;
+
+ if ((data->select == 0 || (key->flag & PEK_SELECT)) && !(key->flag & PEK_HIDE)) {
+ float dco[3]; /* delta temp var */
+
+ madd_v3_v3v3fl(kco, co_root, no_root, length_accum);
+
+ /* blend between the current and straight position */
+ sub_v3_v3v3(dco, kco, co);
+ madd_v3_v3fl(co, dco, fac);
+ /* keep the same distance from the root or we get glitches [#35406] */
+ dist_ensure_v3_v3fl(co, co_root, length_accum);
+
+ /* re-use dco to compare before and after translation and add to the offset */
+ copy_v3_v3(dco, key->co);
+
+ mul_v3_m4v3(key->co, imat, co);
+
+ if (puff_volume) {
+ /* accumulate the total distance moved to apply to unselected
+ * keys that come after */
+ sub_v3_v3v3(ofs_prev, key->co, dco);
+ }
+ changed = true;
+ }
+ else {
+
+ if (puff_volume) {
#if 0
- /* this is simple but looks bad, adds annoying kinks */
- add_v3_v3(key->co, ofs);
+ /* this is simple but looks bad, adds annoying kinks */
+ add_v3_v3(key->co, ofs);
#else
- /* translate (not rotate) the rest of the hair if its not selected */
- {
-#if 0 /* kindof works but looks worse then what's below */
-
- /* Move the unselected point on a vector based on the
- * hair direction and the offset */
- float c1[3], c2[3];
- sub_v3_v3v3(dco, lastco, co);
- mul_mat3_m4_v3(imat, dco); /* into particle space */
-
- /* move the point along a vector perpendicular to the
- * hairs direction, reduces odd kinks, */
- cross_v3_v3v3(c1, ofs, dco);
- cross_v3_v3v3(c2, c1, dco);
- normalize_v3(c2);
- mul_v3_fl(c2, len_v3(ofs));
- add_v3_v3(key->co, c2);
-#else
- /* Move the unselected point on a vector based on the
- * the normal of the closest geometry */
- float oco[3], onor[3];
- copy_v3_v3(oco, key->co);
- mul_m4_v3(mat, oco);
-
- /* use 'kco' as the object space version of worldspace 'co',
- * ob->imat is set before calling */
- mul_v3_m4v3(kco, data->ob->imat, oco);
-
- point_index = BLI_kdtree_3d_find_nearest(edit->emitter_field, kco, NULL);
- if (point_index != -1) {
- copy_v3_v3(onor, &edit->emitter_cosnos[point_index * 6 + 3]);
- mul_mat3_m4_v3(data->ob->obmat, onor); /* normal into worldspace */
- mul_mat3_m4_v3(imat, onor); /* worldspace into particle space */
- normalize_v3(onor);
- }
- else {
- copy_v3_v3(onor, onor_prev);
- }
-
- if (!is_zero_v3(ofs_prev)) {
- mul_v3_fl(onor, len_v3(ofs_prev));
-
- add_v3_v3(key->co, onor);
- }
-
- copy_v3_v3(onor_prev, onor);
-#endif
- }
+ /* translate (not rotate) the rest of the hair if its not selected */
+ {
+# if 0 /* kindof works but looks worse then what's below */
+
+ /* Move the unselected point on a vector based on the
+ * hair direction and the offset */
+ float c1[3], c2[3];
+ sub_v3_v3v3(dco, lastco, co);
+ mul_mat3_m4_v3(imat, dco); /* into particle space */
+
+ /* move the point along a vector perpendicular to the
+ * hairs direction, reduces odd kinks, */
+ cross_v3_v3v3(c1, ofs, dco);
+ cross_v3_v3v3(c2, c1, dco);
+ normalize_v3(c2);
+ mul_v3_fl(c2, len_v3(ofs));
+ add_v3_v3(key->co, c2);
+# else
+ /* Move the unselected point on a vector based on the
+ * the normal of the closest geometry */
+ float oco[3], onor[3];
+ copy_v3_v3(oco, key->co);
+ mul_m4_v3(mat, oco);
+
+ /* use 'kco' as the object space version of worldspace 'co',
+ * ob->imat is set before calling */
+ mul_v3_m4v3(kco, data->ob->imat, oco);
+
+ point_index = BLI_kdtree_3d_find_nearest(edit->emitter_field, kco, NULL);
+ if (point_index != -1) {
+ copy_v3_v3(onor, &edit->emitter_cosnos[point_index * 6 + 3]);
+ mul_mat3_m4_v3(data->ob->obmat, onor); /* normal into worldspace */
+ mul_mat3_m4_v3(imat, onor); /* worldspace into particle space */
+ normalize_v3(onor);
+ }
+ else {
+ copy_v3_v3(onor, onor_prev);
+ }
+
+ if (!is_zero_v3(ofs_prev)) {
+ mul_v3_fl(onor, len_v3(ofs_prev));
+
+ add_v3_v3(key->co, onor);
+ }
+
+ copy_v3_v3(onor_prev, onor);
+# endif
+ }
#endif
- }
- }
- }
- }
+ }
+ }
+ }
+ }
- if (changed)
- point->flag |= PEP_EDIT_RECALC;
+ if (changed)
+ point->flag |= PEP_EDIT_RECALC;
}
-
-static void BKE_brush_weight_get(
- PEData *data,
- float UNUSED(mat[4][4]),
- float UNUSED(imat[4][4]),
- int point_index,
- int key_index,
- PTCacheEditKey *UNUSED(key),
- float UNUSED(mouse_distance))
+static void BKE_brush_weight_get(PEData *data,
+ float UNUSED(mat[4][4]),
+ float UNUSED(imat[4][4]),
+ int point_index,
+ int key_index,
+ PTCacheEditKey *UNUSED(key),
+ float UNUSED(mouse_distance))
{
- /* roots have full weight always */
- if (key_index) {
- PTCacheEdit *edit = data->edit;
- ParticleSystem *psys = edit->psys;
+ /* roots have full weight always */
+ if (key_index) {
+ PTCacheEdit *edit = data->edit;
+ ParticleSystem *psys = edit->psys;
- ParticleData *pa = psys->particles + point_index;
- pa->hair[key_index].weight = data->weightfac;
+ ParticleData *pa = psys->particles + point_index;
+ pa->hair[key_index].weight = data->weightfac;
- (data->edit->points + point_index)->flag |= PEP_EDIT_RECALC;
- }
+ (data->edit->points + point_index)->flag |= PEP_EDIT_RECALC;
+ }
}
-static void brush_smooth_get(
- PEData *data,
- float mat[4][4],
- float UNUSED(imat[4][4]),
- int UNUSED(point_index),
- int key_index,
- PTCacheEditKey *key,
- float UNUSED(mouse_distance))
+static void brush_smooth_get(PEData *data,
+ float mat[4][4],
+ float UNUSED(imat[4][4]),
+ int UNUSED(point_index),
+ int key_index,
+ PTCacheEditKey *key,
+ float UNUSED(mouse_distance))
{
- if (key_index) {
- float dvec[3];
+ if (key_index) {
+ float dvec[3];
- sub_v3_v3v3(dvec, key->co, (key - 1)->co);
- mul_mat3_m4_v3(mat, dvec);
- add_v3_v3(data->vec, dvec);
- data->tot++;
- }
+ sub_v3_v3v3(dvec, key->co, (key - 1)->co);
+ mul_mat3_m4_v3(mat, dvec);
+ add_v3_v3(data->vec, dvec);
+ data->tot++;
+ }
}
-static void brush_smooth_do(
- PEData *data,
- float UNUSED(mat[4][4]),
- float imat[4][4],
- int point_index,
- int key_index,
- PTCacheEditKey *key,
- float UNUSED(mouse_distance))
+static void brush_smooth_do(PEData *data,
+ float UNUSED(mat[4][4]),
+ float imat[4][4],
+ int point_index,
+ int key_index,
+ PTCacheEditKey *key,
+ float UNUSED(mouse_distance))
{
- float vec[3], dvec[3];
+ float vec[3], dvec[3];
- if (key_index) {
- copy_v3_v3(vec, data->vec);
- mul_mat3_m4_v3(imat, vec);
+ if (key_index) {
+ copy_v3_v3(vec, data->vec);
+ mul_mat3_m4_v3(imat, vec);
- sub_v3_v3v3(dvec, key->co, (key - 1)->co);
+ sub_v3_v3v3(dvec, key->co, (key - 1)->co);
- sub_v3_v3v3(dvec, vec, dvec);
- mul_v3_fl(dvec, data->smoothfac);
+ sub_v3_v3v3(dvec, vec, dvec);
+ mul_v3_fl(dvec, data->smoothfac);
- add_v3_v3(key->co, dvec);
- }
+ add_v3_v3(key->co, dvec);
+ }
- (data->edit->points + point_index)->flag |= PEP_EDIT_RECALC;
+ (data->edit->points + point_index)->flag |= PEP_EDIT_RECALC;
}
/* convert from triangle barycentric weights to quad mean value weights */
-static void intersect_dm_quad_weights(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float w[4])
+static void intersect_dm_quad_weights(
+ const float v1[3], const float v2[3], const float v3[3], const float v4[3], float w[4])
{
- float co[3], vert[4][3];
+ float co[3], vert[4][3];
- copy_v3_v3(vert[0], v1);
- copy_v3_v3(vert[1], v2);
- copy_v3_v3(vert[2], v3);
- copy_v3_v3(vert[3], v4);
+ copy_v3_v3(vert[0], v1);
+ copy_v3_v3(vert[1], v2);
+ copy_v3_v3(vert[2], v3);
+ copy_v3_v3(vert[3], v4);
- co[0] = v1[0] * w[0] + v2[0] * w[1] + v3[0] * w[2] + v4[0] * w[3];
- co[1] = v1[1] * w[0] + v2[1] * w[1] + v3[1] * w[2] + v4[1] * w[3];
- co[2] = v1[2] * w[0] + v2[2] * w[1] + v3[2] * w[2] + v4[2] * w[3];
+ co[0] = v1[0] * w[0] + v2[0] * w[1] + v3[0] * w[2] + v4[0] * w[3];
+ co[1] = v1[1] * w[0] + v2[1] * w[1] + v3[1] * w[2] + v4[1] * w[3];
+ co[2] = v1[2] * w[0] + v2[2] * w[1] + v3[2] * w[2] + v4[2] * w[3];
- interp_weights_poly_v3(w, vert, 4, co);
+ interp_weights_poly_v3(w, vert, 4, co);
}
/** Check intersection with an evaluated mesh. */
-static int particle_intersect_mesh(Depsgraph *depsgraph, Scene *UNUSED(scene), Object *ob, Mesh *mesh,
+static int particle_intersect_mesh(Depsgraph *depsgraph,
+ Scene *UNUSED(scene),
+ Object *ob,
+ Mesh *mesh,
float *vert_cos,
- const float co1[3], const float co2[3],
- float *min_d, int *min_face, float *min_w,
- float *face_minmax, float *pa_minmax,
- float radius, float *ipoint)
-{
- MFace *mface = NULL;
- MVert *mvert = NULL;
- int i, totface, intersect = 0;
- float cur_d, cur_uv[2], v1[3], v2[3], v3[3], v4[3], min[3], max[3], p_min[3], p_max[3];
- float cur_ipoint[3];
-
- if (mesh == NULL) {
- psys_disable_all(ob);
-
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
-
- mesh = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
- if (mesh == NULL) {
- mesh = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
- }
-
- psys_enable_all(ob);
-
- if (mesh == NULL) {
- return 0;
- }
- }
-
- /* BMESH_ONLY, deform dm may not have tessface */
- BKE_mesh_tessface_ensure(mesh);
-
-
- if (pa_minmax == 0) {
- INIT_MINMAX(p_min, p_max);
- minmax_v3v3_v3(p_min, p_max, co1);
- minmax_v3v3_v3(p_min, p_max, co2);
- }
- else {
- copy_v3_v3(p_min, pa_minmax);
- copy_v3_v3(p_max, pa_minmax + 3);
- }
-
- totface = mesh->totface;
- mface = mesh->mface;
- mvert = mesh->mvert;
-
- /* lets intersect the faces */
- for (i = 0; i < totface; i++, mface++) {
- if (vert_cos) {
- copy_v3_v3(v1, vert_cos + 3 * mface->v1);
- copy_v3_v3(v2, vert_cos + 3 * mface->v2);
- copy_v3_v3(v3, vert_cos + 3 * mface->v3);
- if (mface->v4)
- copy_v3_v3(v4, vert_cos + 3 * mface->v4);
- }
- else {
- copy_v3_v3(v1, mvert[mface->v1].co);
- copy_v3_v3(v2, mvert[mface->v2].co);
- copy_v3_v3(v3, mvert[mface->v3].co);
- if (mface->v4)
- copy_v3_v3(v4, mvert[mface->v4].co);
- }
-
- if (face_minmax == 0) {
- INIT_MINMAX(min, max);
- DO_MINMAX(v1, min, max);
- DO_MINMAX(v2, min, max);
- DO_MINMAX(v3, min, max);
- if (mface->v4)
- DO_MINMAX(v4, min, max);
- if (isect_aabb_aabb_v3(min, max, p_min, p_max) == 0)
- continue;
- }
- else {
- copy_v3_v3(min, face_minmax + 6 * i);
- copy_v3_v3(max, face_minmax + 6 * i + 3);
- if (isect_aabb_aabb_v3(min, max, p_min, p_max) == 0)
- continue;
- }
-
- if (radius > 0.0f) {
- if (isect_sweeping_sphere_tri_v3(co1, co2, radius, v2, v3, v1, &cur_d, cur_ipoint)) {
- if (cur_d < *min_d) {
- *min_d = cur_d;
- copy_v3_v3(ipoint, cur_ipoint);
- *min_face = i;
- intersect = 1;
- }
- }
- if (mface->v4) {
- if (isect_sweeping_sphere_tri_v3(co1, co2, radius, v4, v1, v3, &cur_d, cur_ipoint)) {
- if (cur_d < *min_d) {
- *min_d = cur_d;
- copy_v3_v3(ipoint, cur_ipoint);
- *min_face = i;
- intersect = 1;
- }
- }
- }
- }
- else {
- if (isect_line_segment_tri_v3(co1, co2, v1, v2, v3, &cur_d, cur_uv)) {
- if (cur_d < *min_d) {
- *min_d = cur_d;
- min_w[0] = 1.0f - cur_uv[0] - cur_uv[1];
- min_w[1] = cur_uv[0];
- min_w[2] = cur_uv[1];
- min_w[3] = 0.0f;
- if (mface->v4)
- intersect_dm_quad_weights(v1, v2, v3, v4, min_w);
- *min_face = i;
- intersect = 1;
- }
- }
- if (mface->v4) {
- if (isect_line_segment_tri_v3(co1, co2, v1, v3, v4, &cur_d, cur_uv)) {
- if (cur_d < *min_d) {
- *min_d = cur_d;
- min_w[0] = 1.0f - cur_uv[0] - cur_uv[1];
- min_w[1] = 0.0f;
- min_w[2] = cur_uv[0];
- min_w[3] = cur_uv[1];
- intersect_dm_quad_weights(v1, v2, v3, v4, min_w);
- *min_face = i;
- intersect = 1;
- }
- }
- }
- }
- }
- return intersect;
+ const float co1[3],
+ const float co2[3],
+ float *min_d,
+ int *min_face,
+ float *min_w,
+ float *face_minmax,
+ float *pa_minmax,
+ float radius,
+ float *ipoint)
+{
+ MFace *mface = NULL;
+ MVert *mvert = NULL;
+ int i, totface, intersect = 0;
+ float cur_d, cur_uv[2], v1[3], v2[3], v3[3], v4[3], min[3], max[3], p_min[3], p_max[3];
+ float cur_ipoint[3];
+
+ if (mesh == NULL) {
+ psys_disable_all(ob);
+
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+
+ mesh = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
+ if (mesh == NULL) {
+ mesh = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
+ }
+
+ psys_enable_all(ob);
+
+ if (mesh == NULL) {
+ return 0;
+ }
+ }
+
+ /* BMESH_ONLY, deform dm may not have tessface */
+ BKE_mesh_tessface_ensure(mesh);
+
+ if (pa_minmax == 0) {
+ INIT_MINMAX(p_min, p_max);
+ minmax_v3v3_v3(p_min, p_max, co1);
+ minmax_v3v3_v3(p_min, p_max, co2);
+ }
+ else {
+ copy_v3_v3(p_min, pa_minmax);
+ copy_v3_v3(p_max, pa_minmax + 3);
+ }
+
+ totface = mesh->totface;
+ mface = mesh->mface;
+ mvert = mesh->mvert;
+
+ /* lets intersect the faces */
+ for (i = 0; i < totface; i++, mface++) {
+ if (vert_cos) {
+ copy_v3_v3(v1, vert_cos + 3 * mface->v1);
+ copy_v3_v3(v2, vert_cos + 3 * mface->v2);
+ copy_v3_v3(v3, vert_cos + 3 * mface->v3);
+ if (mface->v4)
+ copy_v3_v3(v4, vert_cos + 3 * mface->v4);
+ }
+ else {
+ copy_v3_v3(v1, mvert[mface->v1].co);
+ copy_v3_v3(v2, mvert[mface->v2].co);
+ copy_v3_v3(v3, mvert[mface->v3].co);
+ if (mface->v4)
+ copy_v3_v3(v4, mvert[mface->v4].co);
+ }
+
+ if (face_minmax == 0) {
+ INIT_MINMAX(min, max);
+ DO_MINMAX(v1, min, max);
+ DO_MINMAX(v2, min, max);
+ DO_MINMAX(v3, min, max);
+ if (mface->v4)
+ DO_MINMAX(v4, min, max);
+ if (isect_aabb_aabb_v3(min, max, p_min, p_max) == 0)
+ continue;
+ }
+ else {
+ copy_v3_v3(min, face_minmax + 6 * i);
+ copy_v3_v3(max, face_minmax + 6 * i + 3);
+ if (isect_aabb_aabb_v3(min, max, p_min, p_max) == 0)
+ continue;
+ }
+
+ if (radius > 0.0f) {
+ if (isect_sweeping_sphere_tri_v3(co1, co2, radius, v2, v3, v1, &cur_d, cur_ipoint)) {
+ if (cur_d < *min_d) {
+ *min_d = cur_d;
+ copy_v3_v3(ipoint, cur_ipoint);
+ *min_face = i;
+ intersect = 1;
+ }
+ }
+ if (mface->v4) {
+ if (isect_sweeping_sphere_tri_v3(co1, co2, radius, v4, v1, v3, &cur_d, cur_ipoint)) {
+ if (cur_d < *min_d) {
+ *min_d = cur_d;
+ copy_v3_v3(ipoint, cur_ipoint);
+ *min_face = i;
+ intersect = 1;
+ }
+ }
+ }
+ }
+ else {
+ if (isect_line_segment_tri_v3(co1, co2, v1, v2, v3, &cur_d, cur_uv)) {
+ if (cur_d < *min_d) {
+ *min_d = cur_d;
+ min_w[0] = 1.0f - cur_uv[0] - cur_uv[1];
+ min_w[1] = cur_uv[0];
+ min_w[2] = cur_uv[1];
+ min_w[3] = 0.0f;
+ if (mface->v4)
+ intersect_dm_quad_weights(v1, v2, v3, v4, min_w);
+ *min_face = i;
+ intersect = 1;
+ }
+ }
+ if (mface->v4) {
+ if (isect_line_segment_tri_v3(co1, co2, v1, v3, v4, &cur_d, cur_uv)) {
+ if (cur_d < *min_d) {
+ *min_d = cur_d;
+ min_w[0] = 1.0f - cur_uv[0] - cur_uv[1];
+ min_w[1] = 0.0f;
+ min_w[2] = cur_uv[0];
+ min_w[3] = cur_uv[1];
+ intersect_dm_quad_weights(v1, v2, v3, v4, min_w);
+ *min_face = i;
+ intersect = 1;
+ }
+ }
+ }
+ }
+ }
+ return intersect;
}
typedef struct BrushAddCountIterData {
- Depsgraph *depsgraph;
- Scene *scene;
- Object *object;
- Mesh *mesh;
- PEData *data;
- int number;
- short size;
- float imat[4][4];
- ParticleData *add_pars;
- int num_added;
+ Depsgraph *depsgraph;
+ Scene *scene;
+ Object *object;
+ Mesh *mesh;
+ PEData *data;
+ int number;
+ short size;
+ float imat[4][4];
+ ParticleData *add_pars;
+ int num_added;
} BrushAddCountIterData;
typedef struct BrushAddCountIterTLSData {
- RNG *rng;
- int num_added;
+ RNG *rng;
+ int num_added;
} BrushAddCountIterTLSData;
-static void brush_add_count_iter(
- void *__restrict iter_data_v,
- const int iter,
- const ParallelRangeTLS *__restrict tls_v)
-{
- BrushAddCountIterData *iter_data = (BrushAddCountIterData *)iter_data_v;
- Depsgraph *depsgraph = iter_data->depsgraph;
- PEData *data = iter_data->data;
- PTCacheEdit *edit = data->edit;
- ParticleSystem *psys = edit->psys;
- ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
- ParticleData *add_pars = iter_data->add_pars;
- BrushAddCountIterTLSData *tls = tls_v->userdata_chunk;
- const int number = iter_data->number;
- const short size = iter_data->size;
- const short size2 = size * size;
- float dmx, dmy;
- if (number > 1) {
- dmx = size;
- dmy = size;
- if (tls->rng == NULL) {
- tls->rng = BLI_rng_new_srandom(
- psys->seed + data->mval[0] + data->mval[1] + tls_v->thread_id);
- }
- /* rejection sampling to get points in circle */
- while (dmx * dmx + dmy * dmy > size2) {
- dmx = (2.0f * BLI_rng_get_float(tls->rng) - 1.0f) * size;
- dmy = (2.0f * BLI_rng_get_float(tls->rng) - 1.0f) * size;
- }
- }
- else {
- dmx = 0.0f;
- dmy = 0.0f;
- }
-
- float mco[2];
- mco[0] = data->mval[0] + dmx;
- 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);
-
- mul_m4_v3(iter_data->imat, co1);
- mul_m4_v3(iter_data->imat, co2);
- float min_d = 2.0;
-
- /* warning, returns the derived mesh face */
- BLI_assert(iter_data->mesh != NULL);
- if (particle_intersect_mesh(depsgraph, iter_data->scene, iter_data->object, iter_data->mesh,
- 0, co1, co2,
- &min_d,
- &add_pars[iter].num_dmcache,
- add_pars[iter].fuv,
- 0, 0, 0, 0))
- {
- if (psys->part->use_modifier_stack && !psmd_eval->mesh_final->runtime.deformed_only) {
- add_pars[iter].num = add_pars[iter].num_dmcache;
- add_pars[iter].num_dmcache = DMCACHE_ISCHILD;
- }
- else if (iter_data->mesh == psmd_eval->mesh_original) {
- /* Final DM is not same topology as orig mesh, we have to map num_dmcache to real final dm. */
- add_pars[iter].num = add_pars[iter].num_dmcache;
- add_pars[iter].num_dmcache = psys_particle_dm_face_lookup(
- psmd_eval->mesh_final, psmd_eval->mesh_original,
- add_pars[iter].num, add_pars[iter].fuv, NULL);
- }
- else {
- add_pars[iter].num = add_pars[iter].num_dmcache;
- }
- if (add_pars[iter].num != DMCACHE_NOTFOUND) {
- tls->num_added++;
- }
- }
+static void brush_add_count_iter(void *__restrict iter_data_v,
+ const int iter,
+ const ParallelRangeTLS *__restrict tls_v)
+{
+ BrushAddCountIterData *iter_data = (BrushAddCountIterData *)iter_data_v;
+ Depsgraph *depsgraph = iter_data->depsgraph;
+ PEData *data = iter_data->data;
+ PTCacheEdit *edit = data->edit;
+ ParticleSystem *psys = edit->psys;
+ ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
+ ParticleData *add_pars = iter_data->add_pars;
+ BrushAddCountIterTLSData *tls = tls_v->userdata_chunk;
+ const int number = iter_data->number;
+ const short size = iter_data->size;
+ const short size2 = size * size;
+ float dmx, dmy;
+ if (number > 1) {
+ dmx = size;
+ dmy = size;
+ if (tls->rng == NULL) {
+ tls->rng = BLI_rng_new_srandom(psys->seed + data->mval[0] + data->mval[1] +
+ tls_v->thread_id);
+ }
+ /* rejection sampling to get points in circle */
+ while (dmx * dmx + dmy * dmy > size2) {
+ dmx = (2.0f * BLI_rng_get_float(tls->rng) - 1.0f) * size;
+ dmy = (2.0f * BLI_rng_get_float(tls->rng) - 1.0f) * size;
+ }
+ }
+ else {
+ dmx = 0.0f;
+ dmy = 0.0f;
+ }
+
+ float mco[2];
+ mco[0] = data->mval[0] + dmx;
+ 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);
+
+ mul_m4_v3(iter_data->imat, co1);
+ mul_m4_v3(iter_data->imat, co2);
+ float min_d = 2.0;
+
+ /* warning, returns the derived mesh face */
+ BLI_assert(iter_data->mesh != NULL);
+ if (particle_intersect_mesh(depsgraph,
+ iter_data->scene,
+ iter_data->object,
+ iter_data->mesh,
+ 0,
+ co1,
+ co2,
+ &min_d,
+ &add_pars[iter].num_dmcache,
+ add_pars[iter].fuv,
+ 0,
+ 0,
+ 0,
+ 0)) {
+ if (psys->part->use_modifier_stack && !psmd_eval->mesh_final->runtime.deformed_only) {
+ add_pars[iter].num = add_pars[iter].num_dmcache;
+ add_pars[iter].num_dmcache = DMCACHE_ISCHILD;
+ }
+ else if (iter_data->mesh == psmd_eval->mesh_original) {
+ /* Final DM is not same topology as orig mesh, we have to map num_dmcache to real final dm. */
+ add_pars[iter].num = add_pars[iter].num_dmcache;
+ add_pars[iter].num_dmcache = psys_particle_dm_face_lookup(psmd_eval->mesh_final,
+ psmd_eval->mesh_original,
+ add_pars[iter].num,
+ add_pars[iter].fuv,
+ NULL);
+ }
+ else {
+ add_pars[iter].num = add_pars[iter].num_dmcache;
+ }
+ if (add_pars[iter].num != DMCACHE_NOTFOUND) {
+ tls->num_added++;
+ }
+ }
}
static void brush_add_count_iter_finalize(void *__restrict userdata_v,
void *__restrict userdata_chunk_v)
{
- BrushAddCountIterData *iter_data = (BrushAddCountIterData *)userdata_v;
- BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)userdata_chunk_v;
- iter_data->num_added += tls->num_added;
- if (tls->rng != NULL) {
- BLI_rng_free(tls->rng);
- }
+ BrushAddCountIterData *iter_data = (BrushAddCountIterData *)userdata_v;
+ BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)userdata_chunk_v;
+ iter_data->num_added += tls->num_added;
+ if (tls->rng != NULL) {
+ BLI_rng_free(tls->rng);
+ }
}
static int brush_add(const bContext *C, PEData *data, short number)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = data->scene;
- Object *ob = data->ob;
- Mesh *mesh;
- PTCacheEdit *edit = data->edit;
- ParticleSystem *psys = edit->psys;
- ParticleData *add_pars;
- ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
- ParticleSimulationData sim = {0};
- ParticleEditSettings *pset = PE_settings(scene);
- int i, k, n = 0, totpart = psys->totpart;
- float co1[3], imat[4][4];
- float framestep, timestep;
- short size = pset->brush[PE_BRUSH_ADD].size;
- RNG *rng;
-
- invert_m4_m4(imat, ob->obmat);
-
- if (psys->flag & PSYS_GLOBAL_HAIR)
- return 0;
-
- add_pars = MEM_callocN(number * sizeof(ParticleData), "ParticleData add");
-
- rng = BLI_rng_new_srandom(psys->seed + data->mval[0] + data->mval[1]);
-
- sim.depsgraph = depsgraph;
- sim.scene = scene;
- sim.ob = ob;
- sim.psys = psys;
- sim.psmd = psmd_eval;
-
- timestep = psys_get_timestep(&sim);
-
- if (psys->part->use_modifier_stack || psmd_eval->mesh_final->runtime.deformed_only) {
- mesh = psmd_eval->mesh_final;
- }
- else {
- mesh = psmd_eval->mesh_original;
- }
- BLI_assert(mesh);
-
- /* Calculate positions of new particles to add, based on brush intersection
- * with object. New particle data is assigned to a corresponding to check
- * index element of add_pars array. This means, that add_pars is a sparse
- * array.
- */
- BrushAddCountIterData iter_data;
- iter_data.depsgraph = depsgraph;
- iter_data.scene = scene;
- iter_data.object = ob;
- iter_data.mesh = mesh;
- iter_data.data = data;
- 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};
-
- ParallelRangeSettings 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;
- 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;
- for (int current_iter = 0, new_index = 0; current_iter < number; current_iter++) {
- if (add_pars[current_iter].num == DMCACHE_NOTFOUND) {
- continue;
- }
- if (new_index != current_iter) {
- new_index++;
- continue;
- }
- memcpy(add_pars + new_index, add_pars + current_iter, sizeof(ParticleData));
- new_index++;
- }
-
- /* TODO(sergey): Consider multi-threading this part as well. */
- if (n) {
- int newtotpart = totpart + n;
- float hairmat[4][4], cur_co[3];
- KDTree_3d *tree = 0;
- ParticleData *pa, *new_pars = MEM_callocN(newtotpart * sizeof(ParticleData), "ParticleData new");
- PTCacheEditPoint *point, *new_points = MEM_callocN(newtotpart * sizeof(PTCacheEditPoint), "PTCacheEditPoint array new");
- PTCacheEditKey *key;
- HairKey *hkey;
-
- /* save existing elements */
- memcpy(new_pars, psys->particles, totpart * sizeof(ParticleData));
- memcpy(new_points, edit->points, totpart * sizeof(PTCacheEditPoint));
-
- /* change old arrays to new ones */
- if (psys->particles) MEM_freeN(psys->particles);
- psys->particles = new_pars;
-
- if (edit->points) MEM_freeN(edit->points);
- edit->points = new_points;
-
- if (edit->mirror_cache) {
- MEM_freeN(edit->mirror_cache);
- edit->mirror_cache = NULL;
- }
-
- /* create tree for interpolation */
- if (pset->flag & PE_INTERPOLATE_ADDED && psys->totpart) {
- tree = BLI_kdtree_3d_new(psys->totpart);
-
- for (i = 0, pa = psys->particles; i < totpart; i++, pa++) {
- psys_particle_on_dm(psmd_eval->mesh_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0);
- BLI_kdtree_3d_insert(tree, i, cur_co);
- }
-
- BLI_kdtree_3d_balance(tree);
- }
-
- edit->totpoint = psys->totpart = newtotpart;
-
- /* create new elements */
- pa = psys->particles + totpart;
- point = edit->points + totpart;
-
- for (i = totpart; i < newtotpart; i++, pa++, point++) {
- memcpy(pa, add_pars + i - totpart, sizeof(ParticleData));
- pa->hair = MEM_callocN(pset->totaddkey * sizeof(HairKey), "BakeKey key add");
- key = point->keys = MEM_callocN(pset->totaddkey * sizeof(PTCacheEditKey), "PTCacheEditKey add");
- point->totkey = pa->totkey = pset->totaddkey;
-
- for (k = 0, hkey = pa->hair; k < pa->totkey; k++, hkey++, key++) {
- key->co = hkey->co;
- key->time = &hkey->time;
-
- if (!(psys->flag & PSYS_GLOBAL_HAIR))
- key->flag |= PEK_USE_WCO;
- }
-
- pa->size = 1.0f;
- initialize_particle(&sim, pa);
- reset_particle(&sim, pa, 0.0, 1.0);
- point->flag |= PEP_EDIT_RECALC;
- if (pe_x_mirror(ob))
- point->flag |= PEP_TAG; /* signal for duplicate */
-
- framestep = pa->lifetime / (float)(pset->totaddkey - 1);
-
- if (tree) {
- ParticleData *ppa;
- HairKey *thkey;
- ParticleKey key3[3];
- KDTreeNearest_3d ptn[3];
- int w, maxw;
- float maxd, totw = 0.0, weight[3];
-
- psys_particle_on_dm(psmd_eval->mesh_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0);
- maxw = BLI_kdtree_3d_find_nearest_n(tree, co1, ptn, 3);
-
- maxd = ptn[maxw - 1].dist;
-
- for (w = 0; w < maxw; w++) {
- weight[w] = (float)pow(2.0, (double)(-6.0f * ptn[w].dist / maxd));
- totw += weight[w];
- }
- for (; w < 3; w++) {
- weight[w] = 0.0f;
- }
-
- if (totw > 0.0f) {
- for (w = 0; w < maxw; w++)
- weight[w] /= totw;
- }
- else {
- for (w = 0; w < maxw; w++)
- weight[w] = 1.0f / maxw;
- }
-
- ppa = psys->particles + ptn[0].index;
-
- for (k = 0; k < pset->totaddkey; k++) {
- thkey = (HairKey *)pa->hair + k;
- thkey->time = pa->time + k * framestep;
-
- key3[0].time = thkey->time / 100.0f;
- psys_get_particle_on_path(&sim, ptn[0].index, key3, 0);
- mul_v3_fl(key3[0].co, weight[0]);
-
- /* TODO: interpolating the weight would be nicer */
- thkey->weight = (ppa->hair + MIN2(k, ppa->totkey - 1))->weight;
-
- if (maxw > 1) {
- key3[1].time = key3[0].time;
- psys_get_particle_on_path(&sim, ptn[1].index, &key3[1], 0);
- mul_v3_fl(key3[1].co, weight[1]);
- add_v3_v3(key3[0].co, key3[1].co);
-
- if (maxw > 2) {
- key3[2].time = key3[0].time;
- psys_get_particle_on_path(&sim, ptn[2].index, &key3[2], 0);
- mul_v3_fl(key3[2].co, weight[2]);
- add_v3_v3(key3[0].co, key3[2].co);
- }
- }
-
- if (k == 0)
- sub_v3_v3v3(co1, pa->state.co, key3[0].co);
-
- add_v3_v3v3(thkey->co, key3[0].co, co1);
-
- thkey->time = key3[0].time;
- }
- }
- else {
- for (k = 0, hkey = pa->hair; k < pset->totaddkey; k++, hkey++) {
- madd_v3_v3v3fl(hkey->co, pa->state.co, pa->state.vel, k * framestep * timestep);
- hkey->time += k * framestep;
- hkey->weight = 1.f - (float)k / (float)(pset->totaddkey - 1);
- }
- }
- for (k = 0, hkey = pa->hair; k < pset->totaddkey; k++, hkey++) {
- psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, pa, hairmat);
- invert_m4_m4(imat, hairmat);
- mul_m4_v3(imat, hkey->co);
- }
- }
-
- if (tree)
- BLI_kdtree_3d_free(tree);
- }
-
- MEM_freeN(add_pars);
-
- BLI_rng_free(rng);
-
- return n;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = data->scene;
+ Object *ob = data->ob;
+ Mesh *mesh;
+ PTCacheEdit *edit = data->edit;
+ ParticleSystem *psys = edit->psys;
+ ParticleData *add_pars;
+ ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
+ ParticleSimulationData sim = {0};
+ ParticleEditSettings *pset = PE_settings(scene);
+ int i, k, n = 0, totpart = psys->totpart;
+ float co1[3], imat[4][4];
+ float framestep, timestep;
+ short size = pset->brush[PE_BRUSH_ADD].size;
+ RNG *rng;
+
+ invert_m4_m4(imat, ob->obmat);
+
+ if (psys->flag & PSYS_GLOBAL_HAIR)
+ return 0;
+
+ add_pars = MEM_callocN(number * sizeof(ParticleData), "ParticleData add");
+
+ rng = BLI_rng_new_srandom(psys->seed + data->mval[0] + data->mval[1]);
+
+ sim.depsgraph = depsgraph;
+ sim.scene = scene;
+ sim.ob = ob;
+ sim.psys = psys;
+ sim.psmd = psmd_eval;
+
+ timestep = psys_get_timestep(&sim);
+
+ if (psys->part->use_modifier_stack || psmd_eval->mesh_final->runtime.deformed_only) {
+ mesh = psmd_eval->mesh_final;
+ }
+ else {
+ mesh = psmd_eval->mesh_original;
+ }
+ BLI_assert(mesh);
+
+ /* Calculate positions of new particles to add, based on brush intersection
+ * with object. New particle data is assigned to a corresponding to check
+ * index element of add_pars array. This means, that add_pars is a sparse
+ * array.
+ */
+ BrushAddCountIterData iter_data;
+ iter_data.depsgraph = depsgraph;
+ iter_data.scene = scene;
+ iter_data.object = ob;
+ iter_data.mesh = mesh;
+ iter_data.data = data;
+ 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};
+
+ ParallelRangeSettings 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;
+ 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;
+ for (int current_iter = 0, new_index = 0; current_iter < number; current_iter++) {
+ if (add_pars[current_iter].num == DMCACHE_NOTFOUND) {
+ continue;
+ }
+ if (new_index != current_iter) {
+ new_index++;
+ continue;
+ }
+ memcpy(add_pars + new_index, add_pars + current_iter, sizeof(ParticleData));
+ new_index++;
+ }
+
+ /* TODO(sergey): Consider multi-threading this part as well. */
+ if (n) {
+ int newtotpart = totpart + n;
+ float hairmat[4][4], cur_co[3];
+ KDTree_3d *tree = 0;
+ ParticleData *pa,
+ *new_pars = MEM_callocN(newtotpart * sizeof(ParticleData), "ParticleData new");
+ PTCacheEditPoint *point, *new_points = MEM_callocN(newtotpart * sizeof(PTCacheEditPoint),
+ "PTCacheEditPoint array new");
+ PTCacheEditKey *key;
+ HairKey *hkey;
+
+ /* save existing elements */
+ memcpy(new_pars, psys->particles, totpart * sizeof(ParticleData));
+ memcpy(new_points, edit->points, totpart * sizeof(PTCacheEditPoint));
+
+ /* change old arrays to new ones */
+ if (psys->particles)
+ MEM_freeN(psys->particles);
+ psys->particles = new_pars;
+
+ if (edit->points)
+ MEM_freeN(edit->points);
+ edit->points = new_points;
+
+ if (edit->mirror_cache) {
+ MEM_freeN(edit->mirror_cache);
+ edit->mirror_cache = NULL;
+ }
+
+ /* create tree for interpolation */
+ if (pset->flag & PE_INTERPOLATE_ADDED && psys->totpart) {
+ tree = BLI_kdtree_3d_new(psys->totpart);
+
+ for (i = 0, pa = psys->particles; i < totpart; i++, pa++) {
+ psys_particle_on_dm(psmd_eval->mesh_final,
+ psys->part->from,
+ pa->num,
+ pa->num_dmcache,
+ pa->fuv,
+ pa->foffset,
+ cur_co,
+ 0,
+ 0,
+ 0,
+ 0);
+ BLI_kdtree_3d_insert(tree, i, cur_co);
+ }
+
+ BLI_kdtree_3d_balance(tree);
+ }
+
+ edit->totpoint = psys->totpart = newtotpart;
+
+ /* create new elements */
+ pa = psys->particles + totpart;
+ point = edit->points + totpart;
+
+ for (i = totpart; i < newtotpart; i++, pa++, point++) {
+ memcpy(pa, add_pars + i - totpart, sizeof(ParticleData));
+ pa->hair = MEM_callocN(pset->totaddkey * sizeof(HairKey), "BakeKey key add");
+ key = point->keys = MEM_callocN(pset->totaddkey * sizeof(PTCacheEditKey),
+ "PTCacheEditKey add");
+ point->totkey = pa->totkey = pset->totaddkey;
+
+ for (k = 0, hkey = pa->hair; k < pa->totkey; k++, hkey++, key++) {
+ key->co = hkey->co;
+ key->time = &hkey->time;
+
+ if (!(psys->flag & PSYS_GLOBAL_HAIR))
+ key->flag |= PEK_USE_WCO;
+ }
+
+ pa->size = 1.0f;
+ initialize_particle(&sim, pa);
+ reset_particle(&sim, pa, 0.0, 1.0);
+ point->flag |= PEP_EDIT_RECALC;
+ if (pe_x_mirror(ob))
+ point->flag |= PEP_TAG; /* signal for duplicate */
+
+ framestep = pa->lifetime / (float)(pset->totaddkey - 1);
+
+ if (tree) {
+ ParticleData *ppa;
+ HairKey *thkey;
+ ParticleKey key3[3];
+ KDTreeNearest_3d ptn[3];
+ int w, maxw;
+ float maxd, totw = 0.0, weight[3];
+
+ psys_particle_on_dm(psmd_eval->mesh_final,
+ psys->part->from,
+ pa->num,
+ pa->num_dmcache,
+ pa->fuv,
+ pa->foffset,
+ co1,
+ 0,
+ 0,
+ 0,
+ 0);
+ maxw = BLI_kdtree_3d_find_nearest_n(tree, co1, ptn, 3);
+
+ maxd = ptn[maxw - 1].dist;
+
+ for (w = 0; w < maxw; w++) {
+ weight[w] = (float)pow(2.0, (double)(-6.0f * ptn[w].dist / maxd));
+ totw += weight[w];
+ }
+ for (; w < 3; w++) {
+ weight[w] = 0.0f;
+ }
+
+ if (totw > 0.0f) {
+ for (w = 0; w < maxw; w++)
+ weight[w] /= totw;
+ }
+ else {
+ for (w = 0; w < maxw; w++)
+ weight[w] = 1.0f / maxw;
+ }
+
+ ppa = psys->particles + ptn[0].index;
+
+ for (k = 0; k < pset->totaddkey; k++) {
+ thkey = (HairKey *)pa->hair + k;
+ thkey->time = pa->time + k * framestep;
+
+ key3[0].time = thkey->time / 100.0f;
+ psys_get_particle_on_path(&sim, ptn[0].index, key3, 0);
+ mul_v3_fl(key3[0].co, weight[0]);
+
+ /* TODO: interpolating the weight would be nicer */
+ thkey->weight = (ppa->hair + MIN2(k, ppa->totkey - 1))->weight;
+
+ if (maxw > 1) {
+ key3[1].time = key3[0].time;
+ psys_get_particle_on_path(&sim, ptn[1].index, &key3[1], 0);
+ mul_v3_fl(key3[1].co, weight[1]);
+ add_v3_v3(key3[0].co, key3[1].co);
+
+ if (maxw > 2) {
+ key3[2].time = key3[0].time;
+ psys_get_particle_on_path(&sim, ptn[2].index, &key3[2], 0);
+ mul_v3_fl(key3[2].co, weight[2]);
+ add_v3_v3(key3[0].co, key3[2].co);
+ }
+ }
+
+ if (k == 0)
+ sub_v3_v3v3(co1, pa->state.co, key3[0].co);
+
+ add_v3_v3v3(thkey->co, key3[0].co, co1);
+
+ thkey->time = key3[0].time;
+ }
+ }
+ else {
+ for (k = 0, hkey = pa->hair; k < pset->totaddkey; k++, hkey++) {
+ madd_v3_v3v3fl(hkey->co, pa->state.co, pa->state.vel, k * framestep * timestep);
+ hkey->time += k * framestep;
+ hkey->weight = 1.f - (float)k / (float)(pset->totaddkey - 1);
+ }
+ }
+ for (k = 0, hkey = pa->hair; k < pset->totaddkey; k++, hkey++) {
+ psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, pa, hairmat);
+ invert_m4_m4(imat, hairmat);
+ mul_m4_v3(imat, hkey->co);
+ }
+ }
+
+ if (tree)
+ BLI_kdtree_3d_free(tree);
+ }
+
+ MEM_freeN(add_pars);
+
+ BLI_rng_free(rng);
+
+ return n;
}
/************************* brush edit operator ********************/
typedef struct BrushEdit {
- Scene *scene;
- ViewLayer *view_layer;
- Object *ob;
- PTCacheEdit *edit;
+ Scene *scene;
+ ViewLayer *view_layer;
+ Object *ob;
+ PTCacheEdit *edit;
- int first;
- int lastmouse[2];
- float zfac;
+ int first;
+ int lastmouse[2];
+ float zfac;
- /* optional cached view settings to avoid setting on every mousemove */
- PEData data;
+ /* optional cached view settings to avoid setting on every mousemove */
+ PEData data;
} BrushEdit;
static int brush_edit_init(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = CTX_data_active_object(C);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- ARegion *ar = CTX_wm_region(C);
- BrushEdit *bedit;
- float min[3], max[3];
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = CTX_data_active_object(C);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ ARegion *ar = CTX_wm_region(C);
+ BrushEdit *bedit;
+ float min[3], max[3];
- if (!WM_toolsystem_active_tool_is_brush(C)) {
- return 0;
- }
+ if (!WM_toolsystem_active_tool_is_brush(C)) {
+ return 0;
+ }
- /* set the 'distance factor' for grabbing (used in comb etc) */
- INIT_MINMAX(min, max);
- PE_minmax(scene, view_layer, min, max);
- mid_v3_v3v3(min, min, max);
+ /* set the 'distance factor' for grabbing (used in comb etc) */
+ INIT_MINMAX(min, max);
+ PE_minmax(scene, view_layer, min, max);
+ mid_v3_v3v3(min, min, max);
- bedit = MEM_callocN(sizeof(BrushEdit), "BrushEdit");
- bedit->first = 1;
- op->customdata = bedit;
+ bedit = MEM_callocN(sizeof(BrushEdit), "BrushEdit");
+ bedit->first = 1;
+ op->customdata = bedit;
- bedit->scene = scene;
- bedit->view_layer = view_layer;
- bedit->ob = ob;
- bedit->edit = edit;
+ bedit->scene = scene;
+ bedit->view_layer = view_layer;
+ bedit->ob = ob;
+ bedit->edit = edit;
- bedit->zfac = ED_view3d_calc_zfac(ar->regiondata, min, NULL);
+ bedit->zfac = ED_view3d_calc_zfac(ar->regiondata, min, NULL);
- /* cache view depths and settings for re-use */
- PE_set_view3d_data(C, &bedit->data);
- PE_create_random_generator(&bedit->data);
+ /* cache view depths and settings for re-use */
+ PE_set_view3d_data(C, &bedit->data);
+ PE_create_random_generator(&bedit->data);
- return 1;
+ return 1;
}
static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
{
- BrushEdit *bedit = op->customdata;
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = bedit->scene;
- Object *ob = bedit->ob;
- PTCacheEdit *edit = bedit->edit;
- ParticleEditSettings *pset = PE_settings(scene);
- ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
- ParticleBrushData *brush = &pset->brush[pset->brushtype];
- ARegion *ar = 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;
- float dx, dy, dmax;
- int lock_root = pset->flag & PE_LOCK_FIRST;
-
- if (!PE_start_edit(edit))
- return;
-
- RNA_float_get_array(itemptr, "mouse", mousef);
- mouse[0] = mousef[0];
- mouse[1] = mousef[1];
- flip = RNA_boolean_get(itemptr, "pen_flip");
-
- if (bedit->first) {
- bedit->lastmouse[0] = mouse[0];
- bedit->lastmouse[1] = mouse[1];
- }
-
- dx = mouse[0] - bedit->lastmouse[0];
- dy = mouse[1] - bedit->lastmouse[1];
-
- mval[0] = mouse[0];
- mval[1] = mouse[1];
-
-
- /* disable locking temporatily for disconnected hair */
- if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
- pset->flag &= ~PE_LOCK_FIRST;
-
- if (((pset->brushtype == PE_BRUSH_ADD) ?
- (sqrtf(dx * dx + dy * dy) > pset->brush[PE_BRUSH_ADD].step) : (dx != 0 || dy != 0)) || bedit->first)
- {
- PEData data = bedit->data;
- data.context = C; // TODO(mai): why isnt this set in bedit->data?
-
- view3d_operator_needs_opengl(C);
- selected = (short)count_selected_keys(scene, edit);
-
- dmax = max_ff(fabsf(dx), fabsf(dy));
- tot_steps = dmax / (0.2f * pe_brush_size_get(scene, brush)) + 1;
-
- dx /= (float)tot_steps;
- dy /= (float)tot_steps;
-
- for (step = 1; step <= tot_steps; step++) {
- mval[0] = bedit->lastmouse[0] + step * dx;
- mval[1] = bedit->lastmouse[1] + step * dy;
-
- switch (pset->brushtype) {
- case PE_BRUSH_COMB:
- {
- const float mval_f[2] = {dx, dy};
- data.mval = mval;
- data.rad = pe_brush_size_get(scene, brush);
-
- data.combfac = (brush->strength - 0.5f) * 2.0f;
- if (data.combfac < 0.0f)
- data.combfac = 1.0f - 9.0f * data.combfac;
- else
- data.combfac = 1.0f - data.combfac;
-
- invert_m4_m4(ob->imat, ob->obmat);
-
- ED_view3d_win_to_delta(ar, mval_f, vec, bedit->zfac);
- data.dvec = vec;
-
- foreach_mouse_hit_key(&data, brush_comb, selected);
- break;
- }
- case PE_BRUSH_CUT:
- {
- if (edit->psys && edit->pathcache) {
- data.mval = mval;
- data.rad = pe_brush_size_get(scene, brush);
- data.cutfac = brush->strength;
-
- if (selected)
- foreach_selected_point(&data, brush_cut);
- else
- foreach_point(&data, brush_cut);
-
- removed = remove_tagged_particles(ob, edit->psys, pe_x_mirror(ob));
- if (pset->flag & PE_KEEP_LENGTHS)
- recalc_lengths(edit);
- }
- else
- removed = 0;
-
- break;
- }
- case PE_BRUSH_LENGTH:
- {
- data.mval = mval;
-
- data.rad = pe_brush_size_get(scene, brush);
- data.growfac = brush->strength / 50.0f;
-
- if (brush->invert ^ flip)
- data.growfac = 1.0f - data.growfac;
- else
- data.growfac = 1.0f + data.growfac;
-
- foreach_mouse_hit_point(&data, brush_length, selected);
-
- if (pset->flag & PE_KEEP_LENGTHS)
- recalc_lengths(edit);
- break;
- }
- case PE_BRUSH_PUFF:
- {
- if (edit->psys) {
- data.mesh = psmd_eval->mesh_final;
- data.mval = mval;
- data.rad = pe_brush_size_get(scene, brush);
- data.select = selected;
-
- data.pufffac = (brush->strength - 0.5f) * 2.0f;
- if (data.pufffac < 0.0f)
- data.pufffac = 1.0f - 9.0f * data.pufffac;
- else
- data.pufffac = 1.0f - data.pufffac;
-
- data.invert = (brush->invert ^ flip);
- invert_m4_m4(ob->imat, ob->obmat);
-
- foreach_mouse_hit_point(&data, brush_puff, selected);
- }
- break;
- }
- case PE_BRUSH_ADD:
- {
- if (edit->psys && edit->psys->part->from == PART_FROM_FACE) {
- data.mval = mval;
-
- added = brush_add(C, &data, brush->count);
-
- if (pset->flag & PE_KEEP_LENGTHS)
- recalc_lengths(edit);
- }
- else
- added = 0;
- break;
- }
- case PE_BRUSH_SMOOTH:
- {
- data.mval = mval;
- data.rad = pe_brush_size_get(scene, brush);
-
- data.vec[0] = data.vec[1] = data.vec[2] = 0.0f;
- data.tot = 0;
-
- data.smoothfac = brush->strength;
-
- invert_m4_m4(ob->imat, ob->obmat);
-
- foreach_mouse_hit_key(&data, brush_smooth_get, selected);
-
- if (data.tot) {
- mul_v3_fl(data.vec, 1.0f / (float)data.tot);
- foreach_mouse_hit_key(&data, brush_smooth_do, selected);
- }
-
- break;
- }
- case PE_BRUSH_WEIGHT:
- {
- if (edit->psys) {
- data.mesh = psmd_eval->mesh_final;
- data.mval = mval;
- data.rad = pe_brush_size_get(scene, brush);
-
- data.weightfac = brush->strength; /* note that this will never be zero */
-
- foreach_mouse_hit_key(&data, BKE_brush_weight_get, selected);
- }
-
- break;
- }
- }
- if ((pset->flag & PE_KEEP_LENGTHS) == 0)
- recalc_lengths(edit);
-
- if (ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_CUT) && (added || removed)) {
- if (pset->brushtype == PE_BRUSH_ADD && pe_x_mirror(ob))
- PE_mirror_x(scene, ob, 1);
-
- update_world_cos(depsgraph, ob, edit);
- psys_free_path_cache(NULL, edit);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- else {
- PE_update_object(depsgraph, scene, ob, 1);
- }
- }
-
- if (edit->psys) {
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
- BKE_particle_batch_cache_dirty_tag(edit->psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
- DEG_id_tag_update(&ob->id, ID_RECALC_PSYS_REDO);
- }
- else {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- }
-
- bedit->lastmouse[0] = mouse[0];
- bedit->lastmouse[1] = mouse[1];
- bedit->first = 0;
- }
-
- pset->flag |= lock_root;
+ BrushEdit *bedit = op->customdata;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = bedit->scene;
+ Object *ob = bedit->ob;
+ PTCacheEdit *edit = bedit->edit;
+ ParticleEditSettings *pset = PE_settings(scene);
+ ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
+ ParticleBrushData *brush = &pset->brush[pset->brushtype];
+ ARegion *ar = 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;
+ float dx, dy, dmax;
+ int lock_root = pset->flag & PE_LOCK_FIRST;
+
+ if (!PE_start_edit(edit))
+ return;
+
+ RNA_float_get_array(itemptr, "mouse", mousef);
+ mouse[0] = mousef[0];
+ mouse[1] = mousef[1];
+ flip = RNA_boolean_get(itemptr, "pen_flip");
+
+ if (bedit->first) {
+ bedit->lastmouse[0] = mouse[0];
+ bedit->lastmouse[1] = mouse[1];
+ }
+
+ dx = mouse[0] - bedit->lastmouse[0];
+ dy = mouse[1] - bedit->lastmouse[1];
+
+ mval[0] = mouse[0];
+ mval[1] = mouse[1];
+
+ /* disable locking temporatily for disconnected hair */
+ if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
+ pset->flag &= ~PE_LOCK_FIRST;
+
+ if (((pset->brushtype == PE_BRUSH_ADD) ?
+ (sqrtf(dx * dx + dy * dy) > pset->brush[PE_BRUSH_ADD].step) :
+ (dx != 0 || dy != 0)) ||
+ bedit->first) {
+ PEData data = bedit->data;
+ data.context = C; // TODO(mai): why isnt this set in bedit->data?
+
+ view3d_operator_needs_opengl(C);
+ selected = (short)count_selected_keys(scene, edit);
+
+ dmax = max_ff(fabsf(dx), fabsf(dy));
+ tot_steps = dmax / (0.2f * pe_brush_size_get(scene, brush)) + 1;
+
+ dx /= (float)tot_steps;
+ dy /= (float)tot_steps;
+
+ for (step = 1; step <= tot_steps; step++) {
+ mval[0] = bedit->lastmouse[0] + step * dx;
+ mval[1] = bedit->lastmouse[1] + step * dy;
+
+ switch (pset->brushtype) {
+ case PE_BRUSH_COMB: {
+ const float mval_f[2] = {dx, dy};
+ data.mval = mval;
+ data.rad = pe_brush_size_get(scene, brush);
+
+ data.combfac = (brush->strength - 0.5f) * 2.0f;
+ if (data.combfac < 0.0f)
+ data.combfac = 1.0f - 9.0f * data.combfac;
+ else
+ data.combfac = 1.0f - data.combfac;
+
+ invert_m4_m4(ob->imat, ob->obmat);
+
+ ED_view3d_win_to_delta(ar, mval_f, vec, bedit->zfac);
+ data.dvec = vec;
+
+ foreach_mouse_hit_key(&data, brush_comb, selected);
+ break;
+ }
+ case PE_BRUSH_CUT: {
+ if (edit->psys && edit->pathcache) {
+ data.mval = mval;
+ data.rad = pe_brush_size_get(scene, brush);
+ data.cutfac = brush->strength;
+
+ if (selected)
+ foreach_selected_point(&data, brush_cut);
+ else
+ foreach_point(&data, brush_cut);
+
+ removed = remove_tagged_particles(ob, edit->psys, pe_x_mirror(ob));
+ if (pset->flag & PE_KEEP_LENGTHS)
+ recalc_lengths(edit);
+ }
+ else
+ removed = 0;
+
+ break;
+ }
+ case PE_BRUSH_LENGTH: {
+ data.mval = mval;
+
+ data.rad = pe_brush_size_get(scene, brush);
+ data.growfac = brush->strength / 50.0f;
+
+ if (brush->invert ^ flip)
+ data.growfac = 1.0f - data.growfac;
+ else
+ data.growfac = 1.0f + data.growfac;
+
+ foreach_mouse_hit_point(&data, brush_length, selected);
+
+ if (pset->flag & PE_KEEP_LENGTHS)
+ recalc_lengths(edit);
+ break;
+ }
+ case PE_BRUSH_PUFF: {
+ if (edit->psys) {
+ data.mesh = psmd_eval->mesh_final;
+ data.mval = mval;
+ data.rad = pe_brush_size_get(scene, brush);
+ data.select = selected;
+
+ data.pufffac = (brush->strength - 0.5f) * 2.0f;
+ if (data.pufffac < 0.0f)
+ data.pufffac = 1.0f - 9.0f * data.pufffac;
+ else
+ data.pufffac = 1.0f - data.pufffac;
+
+ data.invert = (brush->invert ^ flip);
+ invert_m4_m4(ob->imat, ob->obmat);
+
+ foreach_mouse_hit_point(&data, brush_puff, selected);
+ }
+ break;
+ }
+ case PE_BRUSH_ADD: {
+ if (edit->psys && edit->psys->part->from == PART_FROM_FACE) {
+ data.mval = mval;
+
+ added = brush_add(C, &data, brush->count);
+
+ if (pset->flag & PE_KEEP_LENGTHS)
+ recalc_lengths(edit);
+ }
+ else
+ added = 0;
+ break;
+ }
+ case PE_BRUSH_SMOOTH: {
+ data.mval = mval;
+ data.rad = pe_brush_size_get(scene, brush);
+
+ data.vec[0] = data.vec[1] = data.vec[2] = 0.0f;
+ data.tot = 0;
+
+ data.smoothfac = brush->strength;
+
+ invert_m4_m4(ob->imat, ob->obmat);
+
+ foreach_mouse_hit_key(&data, brush_smooth_get, selected);
+
+ if (data.tot) {
+ mul_v3_fl(data.vec, 1.0f / (float)data.tot);
+ foreach_mouse_hit_key(&data, brush_smooth_do, selected);
+ }
+
+ break;
+ }
+ case PE_BRUSH_WEIGHT: {
+ if (edit->psys) {
+ data.mesh = psmd_eval->mesh_final;
+ data.mval = mval;
+ data.rad = pe_brush_size_get(scene, brush);
+
+ data.weightfac = brush->strength; /* note that this will never be zero */
+
+ foreach_mouse_hit_key(&data, BKE_brush_weight_get, selected);
+ }
+
+ break;
+ }
+ }
+ if ((pset->flag & PE_KEEP_LENGTHS) == 0)
+ recalc_lengths(edit);
+
+ if (ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_CUT) && (added || removed)) {
+ if (pset->brushtype == PE_BRUSH_ADD && pe_x_mirror(ob))
+ PE_mirror_x(scene, ob, 1);
+
+ update_world_cos(depsgraph, ob, edit);
+ psys_free_path_cache(NULL, edit);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ else {
+ PE_update_object(depsgraph, scene, ob, 1);
+ }
+ }
+
+ if (edit->psys) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
+ BKE_particle_batch_cache_dirty_tag(edit->psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
+ DEG_id_tag_update(&ob->id, ID_RECALC_PSYS_REDO);
+ }
+ else {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ }
+
+ bedit->lastmouse[0] = mouse[0];
+ bedit->lastmouse[1] = mouse[1];
+ bedit->first = 0;
+ }
+
+ pset->flag |= lock_root;
}
static void brush_edit_exit(wmOperator *op)
{
- BrushEdit *bedit = op->customdata;
+ BrushEdit *bedit = op->customdata;
- PE_free_random_generator(&bedit->data);
- MEM_freeN(bedit);
+ PE_free_random_generator(&bedit->data);
+ MEM_freeN(bedit);
}
static int brush_edit_exec(bContext *C, wmOperator *op)
{
- if (!brush_edit_init(C, op))
- return OPERATOR_CANCELLED;
+ if (!brush_edit_init(C, op))
+ return OPERATOR_CANCELLED;
- RNA_BEGIN(op->ptr, itemptr, "stroke")
- {
- brush_edit_apply(C, op, &itemptr);
- }
- RNA_END;
+ RNA_BEGIN (op->ptr, itemptr, "stroke") {
+ brush_edit_apply(C, op, &itemptr);
+ }
+ RNA_END;
- brush_edit_exit(op);
+ brush_edit_exit(op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void brush_edit_apply_event(bContext *C, wmOperator *op, const wmEvent *event)
{
- PointerRNA itemptr;
- float mouse[2];
+ PointerRNA itemptr;
+ float mouse[2];
- copy_v2fl_v2i(mouse, event->mval);
+ copy_v2fl_v2i(mouse, event->mval);
- /* fill in stroke */
- RNA_collection_add(op->ptr, "stroke", &itemptr);
+ /* fill in stroke */
+ RNA_collection_add(op->ptr, "stroke", &itemptr);
- RNA_float_set_array(&itemptr, "mouse", mouse);
- RNA_boolean_set(&itemptr, "pen_flip", event->shift != false); // XXX hardcoded
+ RNA_float_set_array(&itemptr, "mouse", mouse);
+ RNA_boolean_set(&itemptr, "pen_flip", event->shift != false); // XXX hardcoded
- /* apply */
- brush_edit_apply(C, op, &itemptr);
+ /* apply */
+ brush_edit_apply(C, op, &itemptr);
}
static int brush_edit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (!brush_edit_init(C, op))
- return OPERATOR_CANCELLED;
+ if (!brush_edit_init(C, op))
+ return OPERATOR_CANCELLED;
- brush_edit_apply_event(C, op, event);
+ brush_edit_apply_event(C, op, event);
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static int brush_edit_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- switch (event->type) {
- case LEFTMOUSE:
- case MIDDLEMOUSE:
- case RIGHTMOUSE: // XXX hardcoded
- if (event->val == KM_RELEASE) {
- brush_edit_exit(op);
- return OPERATOR_FINISHED;
- }
- break;
- case MOUSEMOVE:
- brush_edit_apply_event(C, op, event);
- break;
- }
+ switch (event->type) {
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ case RIGHTMOUSE: // XXX hardcoded
+ if (event->val == KM_RELEASE) {
+ brush_edit_exit(op);
+ return OPERATOR_FINISHED;
+ }
+ break;
+ case MOUSEMOVE:
+ brush_edit_apply_event(C, op, event);
+ break;
+ }
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static void brush_edit_cancel(bContext *UNUSED(C), wmOperator *op)
{
- brush_edit_exit(op);
+ brush_edit_exit(op);
}
void PARTICLE_OT_brush_edit(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Brush Edit";
- ot->idname = "PARTICLE_OT_brush_edit";
- ot->description = "Apply a stroke of brush to the particles";
+ /* identifiers */
+ ot->name = "Brush Edit";
+ ot->idname = "PARTICLE_OT_brush_edit";
+ ot->description = "Apply a stroke of brush to the particles";
- /* api callbacks */
- ot->exec = brush_edit_exec;
- ot->invoke = brush_edit_invoke;
- ot->modal = brush_edit_modal;
- ot->cancel = brush_edit_cancel;
- ot->poll = PE_poll_view3d;
+ /* api callbacks */
+ ot->exec = brush_edit_exec;
+ ot->invoke = brush_edit_invoke;
+ ot->modal = brush_edit_modal;
+ ot->cancel = brush_edit_cancel;
+ ot->poll = PE_poll_view3d;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ /* 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);
+ /* properties */
+ PropertyRNA *prop;
+ prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/*********************** cut shape ***************************/
static bool shape_cut_poll(bContext *C)
{
- if (PE_hair_poll(C)) {
- Scene *scene = CTX_data_scene(C);
- ParticleEditSettings *pset = PE_settings(scene);
+ if (PE_hair_poll(C)) {
+ Scene *scene = CTX_data_scene(C);
+ ParticleEditSettings *pset = PE_settings(scene);
- if (pset->shape_object && (pset->shape_object->type == OB_MESH)) {
- return true;
- }
- }
+ if (pset->shape_object && (pset->shape_object->type == OB_MESH)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
typedef struct PointInsideBVH {
- BVHTreeFromMesh bvhdata;
- int num_hits;
+ BVHTreeFromMesh bvhdata;
+ int num_hits;
} PointInsideBVH;
-static void point_inside_bvh_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+static void point_inside_bvh_cb(void *userdata,
+ int index,
+ const BVHTreeRay *ray,
+ BVHTreeRayHit *hit)
{
- PointInsideBVH *data = userdata;
+ PointInsideBVH *data = userdata;
- data->bvhdata.raycast_callback(&data->bvhdata, index, ray, hit);
+ data->bvhdata.raycast_callback(&data->bvhdata, index, ray, hit);
- if (hit->index != -1)
- ++data->num_hits;
+ if (hit->index != -1)
+ ++data->num_hits;
}
/* true if the point is inside the shape mesh */
static bool shape_cut_test_point(PEData *data, ParticleCacheKey *key)
{
- BVHTreeFromMesh *shape_bvh = &data->shape_bvh;
- const float dir[3] = {1.0f, 0.0f, 0.0f};
- PointInsideBVH userdata;
+ BVHTreeFromMesh *shape_bvh = &data->shape_bvh;
+ const float dir[3] = {1.0f, 0.0f, 0.0f};
+ PointInsideBVH userdata;
- userdata.bvhdata = data->shape_bvh;
- userdata.num_hits = 0;
+ userdata.bvhdata = data->shape_bvh;
+ userdata.num_hits = 0;
- BLI_bvhtree_ray_cast_all(
- shape_bvh->tree, key->co, dir, 0.0f, BVH_RAYCAST_DIST_MAX,
- point_inside_bvh_cb, &userdata);
+ BLI_bvhtree_ray_cast_all(
+ shape_bvh->tree, key->co, 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;
+ /* for any point inside a watertight mesh the number of hits is uneven */
+ return (userdata.num_hits % 2) == 1;
}
static void shape_cut(PEData *data, int pa_index)
{
- PTCacheEdit *edit = data->edit;
- Object *ob = data->ob;
- ParticleEditSettings *pset = PE_settings(data->scene);
- ParticleCacheKey *key;
-
- bool cut;
- float cut_time = 1.0;
- int k, totkeys = 1 << pset->draw_step;
-
- /* don't cut hidden */
- if (edit->points[pa_index].flag & PEP_HIDE)
- return;
-
- cut = false;
-
- /* check if root is inside the cut shape */
- key = edit->pathcache[pa_index];
- if (!shape_cut_test_point(data, 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);
-
- memset(&hit, 0, sizeof(hit));
- hit.index = -1;
- hit.dist = len;
- BLI_bvhtree_ray_cast(data->shape_bvh.tree, key->co, dir, 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;
- cut = true;
- break;
- }
- }
- }
- }
-
- if (cut) {
- if (cut_time < 0.0f) {
- edit->points[pa_index].flag |= PEP_TAG;
- }
- else {
- rekey_particle_to_time(data->context, data->scene, ob, pa_index, cut_time);
- edit->points[pa_index].flag |= PEP_EDIT_RECALC;
- }
- }
+ PTCacheEdit *edit = data->edit;
+ Object *ob = data->ob;
+ ParticleEditSettings *pset = PE_settings(data->scene);
+ ParticleCacheKey *key;
+
+ bool cut;
+ float cut_time = 1.0;
+ int k, totkeys = 1 << pset->draw_step;
+
+ /* don't cut hidden */
+ if (edit->points[pa_index].flag & PEP_HIDE)
+ return;
+
+ cut = false;
+
+ /* check if root is inside the cut shape */
+ key = edit->pathcache[pa_index];
+ if (!shape_cut_test_point(data, 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);
+
+ memset(&hit, 0, sizeof(hit));
+ hit.index = -1;
+ hit.dist = len;
+ BLI_bvhtree_ray_cast(data->shape_bvh.tree,
+ key->co,
+ dir,
+ 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;
+ cut = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (cut) {
+ if (cut_time < 0.0f) {
+ edit->points[pa_index].flag |= PEP_TAG;
+ }
+ else {
+ rekey_particle_to_time(data->context, data->scene, ob, pa_index, cut_time);
+ edit->points[pa_index].flag |= PEP_EDIT_RECALC;
+ }
+ }
}
static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op))
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- ParticleEditSettings *pset = PE_settings(scene);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- Object *shapeob = pset->shape_object;
- int selected = count_selected_keys(scene, edit);
- int lock_root = pset->flag & PE_LOCK_FIRST;
-
- if (!PE_start_edit(edit))
- return OPERATOR_CANCELLED;
-
- /* disable locking temporatily for disconnected hair */
- if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
- pset->flag &= ~PE_LOCK_FIRST;
-
- if (edit->psys && edit->pathcache) {
- PEData data;
- int removed;
-
- PE_set_data(C, &data);
- if (!PE_create_shape_tree(&data, shapeob)) {
- /* shapeob may not have faces... */
- return OPERATOR_CANCELLED;
- }
-
- if (selected)
- foreach_selected_point(&data, shape_cut);
- else
- foreach_point(&data, shape_cut);
-
- removed = remove_tagged_particles(ob, edit->psys, pe_x_mirror(ob));
- recalc_lengths(edit);
-
- if (removed) {
- update_world_cos(depsgraph, ob, edit);
- psys_free_path_cache(NULL, edit);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- else {
- PE_update_object(data.depsgraph, scene, ob, 1);
- }
-
- if (edit->psys) {
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
- BKE_particle_batch_cache_dirty_tag(edit->psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
- DEG_id_tag_update(&ob->id, ID_RECALC_PSYS_REDO);
- }
- else {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- }
-
- PE_free_shape_tree(&data);
- }
-
- pset->flag |= lock_root;
-
- return OPERATOR_FINISHED;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ ParticleEditSettings *pset = PE_settings(scene);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ Object *shapeob = pset->shape_object;
+ int selected = count_selected_keys(scene, edit);
+ int lock_root = pset->flag & PE_LOCK_FIRST;
+
+ if (!PE_start_edit(edit))
+ return OPERATOR_CANCELLED;
+
+ /* disable locking temporatily for disconnected hair */
+ if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
+ pset->flag &= ~PE_LOCK_FIRST;
+
+ if (edit->psys && edit->pathcache) {
+ PEData data;
+ int removed;
+
+ PE_set_data(C, &data);
+ if (!PE_create_shape_tree(&data, shapeob)) {
+ /* shapeob may not have faces... */
+ return OPERATOR_CANCELLED;
+ }
+
+ if (selected)
+ foreach_selected_point(&data, shape_cut);
+ else
+ foreach_point(&data, shape_cut);
+
+ removed = remove_tagged_particles(ob, edit->psys, pe_x_mirror(ob));
+ recalc_lengths(edit);
+
+ if (removed) {
+ update_world_cos(depsgraph, ob, edit);
+ psys_free_path_cache(NULL, edit);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ else {
+ PE_update_object(data.depsgraph, scene, ob, 1);
+ }
+
+ if (edit->psys) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
+ BKE_particle_batch_cache_dirty_tag(edit->psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
+ DEG_id_tag_update(&ob->id, ID_RECALC_PSYS_REDO);
+ }
+ else {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ }
+
+ PE_free_shape_tree(&data);
+ }
+
+ pset->flag |= lock_root;
+
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_shape_cut(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Shape Cut";
- ot->idname = "PARTICLE_OT_shape_cut";
- ot->description = "Cut hair to conform to the set shape object";
+ /* identifiers */
+ ot->name = "Shape Cut";
+ ot->idname = "PARTICLE_OT_shape_cut";
+ ot->description = "Cut hair to conform to the set shape object";
- /* api callbacks */
- ot->exec = shape_cut_exec;
- ot->poll = shape_cut_poll;
+ /* api callbacks */
+ ot->exec = shape_cut_exec;
+ ot->poll = shape_cut_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************ utilities ******************************/
int PE_minmax(Scene *scene, ViewLayer *view_layer, float min[3], float max[3])
{
- Object *ob = OBACT(view_layer);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- ParticleSystem *psys;
- ParticleSystemModifierData *psmd_eval = NULL;
- POINT_P; KEY_K;
- float co[3], mat[4][4];
- int ok = 0;
-
- if (!edit) return ok;
-
- if ((psys = edit->psys))
- psmd_eval = edit->psmd_eval;
- else
- unit_m4(mat);
-
- LOOP_VISIBLE_POINTS {
- if (psys)
- psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
-
- LOOP_SELECTED_KEYS {
- copy_v3_v3(co, key->co);
- mul_m4_v3(mat, co);
- DO_MINMAX(co, min, max);
- ok = 1;
- }
- }
-
- if (!ok) {
- BKE_object_minmax(ob, min, max, true);
- ok = 1;
- }
-
- return ok;
+ Object *ob = OBACT(view_layer);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ ParticleSystem *psys;
+ ParticleSystemModifierData *psmd_eval = NULL;
+ POINT_P;
+ KEY_K;
+ float co[3], mat[4][4];
+ int ok = 0;
+
+ if (!edit)
+ return ok;
+
+ if ((psys = edit->psys))
+ psmd_eval = edit->psmd_eval;
+ else
+ unit_m4(mat);
+
+ LOOP_VISIBLE_POINTS
+ {
+ if (psys)
+ psys_mat_hair_to_global(
+ ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
+
+ LOOP_SELECTED_KEYS
+ {
+ copy_v3_v3(co, key->co);
+ mul_m4_v3(mat, co);
+ DO_MINMAX(co, min, max);
+ ok = 1;
+ }
+ }
+
+ if (!ok) {
+ BKE_object_minmax(ob, min, max, true);
+ ok = 1;
+ }
+
+ return ok;
}
/************************ particle edit toggle operator ************************/
/* initialize needed data for bake edit */
void PE_create_particle_edit(
- Depsgraph *depsgraph, Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
-{
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- PTCacheEdit *edit;
- ParticleSystemModifierData *psmd = (psys) ? psys_get_modifier(ob, psys) : NULL;
- ParticleSystemModifierData *psmd_eval = NULL;
- POINT_P; KEY_K;
- ParticleData *pa = NULL;
- HairKey *hkey;
- int totpoint;
-
- if (psmd != NULL) {
- psmd_eval = (ParticleSystemModifierData *)modifiers_findByName(ob_eval, psmd->modifier.name);
- }
-
- /* no psmd->dm happens in case particle system modifier is not enabled */
- if (!(psys && psmd && psmd_eval->mesh_final) && !cache)
- return;
-
- if (cache && cache->flag & PTCACHE_DISK_CACHE)
- return;
-
- if (psys == NULL && (cache && BLI_listbase_is_empty(&cache->mem_cache)))
- return;
-
- edit = (psys) ? psys->edit : cache->edit;
-
- if (!edit) {
- ParticleSystem *psys_eval = NULL;
- if (psys) {
- psys_eval = psys_eval_get(depsgraph, ob, psys);
- psys_copy_particles(psys, psys_eval);
- }
-
- totpoint = psys ? psys->totpart : (int)((PTCacheMem *)cache->mem_cache.first)->totpoint;
-
- edit = MEM_callocN(sizeof(PTCacheEdit), "PE_create_particle_edit");
- edit->points = MEM_callocN(totpoint * sizeof(PTCacheEditPoint), "PTCacheEditPoints");
- edit->totpoint = totpoint;
-
- if (psys && !cache) {
- edit->psmd = psmd;
- edit->psmd_eval = psmd_eval;
- psys->edit = edit;
- edit->psys = psys;
- edit->psys_eval = psys_eval;
-
- psys->free_edit = PE_free_ptcache_edit;
-
- edit->pathcache = NULL;
- BLI_listbase_clear(&edit->pathcachebufs);
-
- pa = psys->particles;
- LOOP_POINTS {
- point->totkey = pa->totkey;
- point->keys = MEM_callocN(point->totkey * sizeof(PTCacheEditKey), "ParticleEditKeys");
- point->flag |= PEP_EDIT_RECALC;
-
- hkey = pa->hair;
- LOOP_KEYS {
- key->co = hkey->co;
- key->time = &hkey->time;
- key->flag = hkey->editflag;
- if (!(psys->flag & PSYS_GLOBAL_HAIR)) {
- key->flag |= PEK_USE_WCO;
- hkey->editflag |= PEK_USE_WCO;
- }
-
- hkey++;
- }
- pa++;
- }
- update_world_cos(depsgraph, ob, edit);
- }
- else {
- PTCacheMem *pm;
- int totframe = 0;
-
- cache->edit = edit;
- cache->free_edit = PE_free_ptcache_edit;
- edit->psys = NULL;
-
- for (pm = cache->mem_cache.first; pm; pm = pm->next)
- totframe++;
-
- for (pm = cache->mem_cache.first; pm; pm = pm->next) {
- LOOP_POINTS {
- if (BKE_ptcache_mem_pointers_seek(p, pm) == 0)
- continue;
-
- if (!point->totkey) {
- key = point->keys = MEM_callocN(totframe * sizeof(PTCacheEditKey), "ParticleEditKeys");
- point->flag |= PEP_EDIT_RECALC;
- }
- else
- key = point->keys + point->totkey;
-
- key->co = pm->cur[BPHYS_DATA_LOCATION];
- key->vel = pm->cur[BPHYS_DATA_VELOCITY];
- key->rot = pm->cur[BPHYS_DATA_ROTATION];
- key->ftime = (float)pm->frame;
- key->time = &key->ftime;
- BKE_ptcache_mem_pointers_incr(pm);
-
- point->totkey++;
- }
- }
- psys = NULL;
- }
-
- /* Causes assert on startup. */
+ Depsgraph *depsgraph, Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
+{
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ PTCacheEdit *edit;
+ ParticleSystemModifierData *psmd = (psys) ? psys_get_modifier(ob, psys) : NULL;
+ ParticleSystemModifierData *psmd_eval = NULL;
+ POINT_P;
+ KEY_K;
+ ParticleData *pa = NULL;
+ HairKey *hkey;
+ int totpoint;
+
+ if (psmd != NULL) {
+ psmd_eval = (ParticleSystemModifierData *)modifiers_findByName(ob_eval, psmd->modifier.name);
+ }
+
+ /* no psmd->dm happens in case particle system modifier is not enabled */
+ if (!(psys && psmd && psmd_eval->mesh_final) && !cache)
+ return;
+
+ if (cache && cache->flag & PTCACHE_DISK_CACHE)
+ return;
+
+ if (psys == NULL && (cache && BLI_listbase_is_empty(&cache->mem_cache)))
+ return;
+
+ edit = (psys) ? psys->edit : cache->edit;
+
+ if (!edit) {
+ ParticleSystem *psys_eval = NULL;
+ if (psys) {
+ psys_eval = psys_eval_get(depsgraph, ob, psys);
+ psys_copy_particles(psys, psys_eval);
+ }
+
+ totpoint = psys ? psys->totpart : (int)((PTCacheMem *)cache->mem_cache.first)->totpoint;
+
+ edit = MEM_callocN(sizeof(PTCacheEdit), "PE_create_particle_edit");
+ edit->points = MEM_callocN(totpoint * sizeof(PTCacheEditPoint), "PTCacheEditPoints");
+ edit->totpoint = totpoint;
+
+ if (psys && !cache) {
+ edit->psmd = psmd;
+ edit->psmd_eval = psmd_eval;
+ psys->edit = edit;
+ edit->psys = psys;
+ edit->psys_eval = psys_eval;
+
+ psys->free_edit = PE_free_ptcache_edit;
+
+ edit->pathcache = NULL;
+ BLI_listbase_clear(&edit->pathcachebufs);
+
+ pa = psys->particles;
+ LOOP_POINTS
+ {
+ point->totkey = pa->totkey;
+ point->keys = MEM_callocN(point->totkey * sizeof(PTCacheEditKey), "ParticleEditKeys");
+ point->flag |= PEP_EDIT_RECALC;
+
+ hkey = pa->hair;
+ LOOP_KEYS
+ {
+ key->co = hkey->co;
+ key->time = &hkey->time;
+ key->flag = hkey->editflag;
+ if (!(psys->flag & PSYS_GLOBAL_HAIR)) {
+ key->flag |= PEK_USE_WCO;
+ hkey->editflag |= PEK_USE_WCO;
+ }
+
+ hkey++;
+ }
+ pa++;
+ }
+ update_world_cos(depsgraph, ob, edit);
+ }
+ else {
+ PTCacheMem *pm;
+ int totframe = 0;
+
+ cache->edit = edit;
+ cache->free_edit = PE_free_ptcache_edit;
+ edit->psys = NULL;
+
+ for (pm = cache->mem_cache.first; pm; pm = pm->next)
+ totframe++;
+
+ for (pm = cache->mem_cache.first; pm; pm = pm->next) {
+ LOOP_POINTS
+ {
+ if (BKE_ptcache_mem_pointers_seek(p, pm) == 0)
+ continue;
+
+ if (!point->totkey) {
+ key = point->keys = MEM_callocN(totframe * sizeof(PTCacheEditKey), "ParticleEditKeys");
+ point->flag |= PEP_EDIT_RECALC;
+ }
+ else
+ key = point->keys + point->totkey;
+
+ key->co = pm->cur[BPHYS_DATA_LOCATION];
+ key->vel = pm->cur[BPHYS_DATA_VELOCITY];
+ key->rot = pm->cur[BPHYS_DATA_ROTATION];
+ key->ftime = (float)pm->frame;
+ key->time = &key->ftime;
+ BKE_ptcache_mem_pointers_incr(pm);
+
+ point->totkey++;
+ }
+ }
+ psys = NULL;
+ }
+
+ /* Causes assert on startup. */
#if 0
- UI_GetThemeColor3ubv(TH_EDGE_SELECT, edit->sel_col);
- UI_GetThemeColor3ubv(TH_WIRE, edit->nosel_col);
+ 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));
+ 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);
+ recalc_lengths(edit);
+ if (psys && !cache)
+ recalc_emitter_field(depsgraph, ob, psys);
- PE_update_object(depsgraph, scene, ob, 1);
- }
+ PE_update_object(depsgraph, scene, ob, 1);
+ }
}
static bool particle_edit_toggle_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if (ob == NULL || ob->type != OB_MESH)
- return 0;
- if (!ob->data || ID_IS_LINKED(ob->data))
- return 0;
- if (CTX_data_edit_object(C))
- return 0;
+ if (ob == NULL || ob->type != OB_MESH)
+ return 0;
+ if (!ob->data || ID_IS_LINKED(ob->data))
+ return 0;
+ if (CTX_data_edit_object(C))
+ return 0;
- return (ob->particlesystem.first ||
- modifiers_findByType(ob, eModifierType_Cloth) ||
- modifiers_findByType(ob, eModifierType_Softbody));
+ return (ob->particlesystem.first || modifiers_findByType(ob, eModifierType_Cloth) ||
+ modifiers_findByType(ob, eModifierType_Softbody));
}
static void free_all_psys_edit(Object *object)
{
- for (ParticleSystem *psys = object->particlesystem.first;
- psys != NULL;
- psys = psys->next)
- {
- if (psys->edit != NULL) {
- BLI_assert(psys->free_edit != NULL);
- psys->free_edit(psys->edit);
- psys->free_edit = NULL;
- psys->edit = NULL;
- }
- }
+ for (ParticleSystem *psys = object->particlesystem.first; psys != NULL; psys = psys->next) {
+ if (psys->edit != NULL) {
+ BLI_assert(psys->free_edit != NULL);
+ psys->free_edit(psys->edit);
+ psys->free_edit = NULL;
+ psys->edit = NULL;
+ }
+ }
}
static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
{
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- const int mode_flag = OB_MODE_PARTICLE_EDIT;
- const bool is_mode_set = (ob->mode & mode_flag) != 0;
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ const int mode_flag = OB_MODE_PARTICLE_EDIT;
+ const bool is_mode_set = (ob->mode & mode_flag) != 0;
- if (!is_mode_set) {
- if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
- return OPERATOR_CANCELLED;
- }
- }
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
- if (!is_mode_set) {
- PTCacheEdit *edit;
+ if (!is_mode_set) {
+ PTCacheEdit *edit;
- ob->mode |= mode_flag;
+ ob->mode |= mode_flag;
- edit = PE_create_current(depsgraph, scene, ob);
+ edit = PE_create_current(depsgraph, scene, ob);
- /* Mesh may have changed since last entering editmode.
- * note, this may have run before if the edit data was just created,
- * so could avoid this and speed up a little. */
- if (edit && edit->psys) {
- /* Make sure pointer to the evaluated modifier data is up to date,
- * with possible changes applied when object was outside of the
- * edit mode. */
- Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
- edit->psmd_eval = (ParticleSystemModifierData *)modifiers_findByName(
- object_eval, edit->psmd->modifier.name);
- recalc_emitter_field(depsgraph, ob, edit->psys);
- }
+ /* Mesh may have changed since last entering editmode.
+ * note, this may have run before if the edit data was just created,
+ * so could avoid this and speed up a little. */
+ if (edit && edit->psys) {
+ /* Make sure pointer to the evaluated modifier data is up to date,
+ * with possible changes applied when object was outside of the
+ * edit mode. */
+ Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
+ edit->psmd_eval = (ParticleSystemModifierData *)modifiers_findByName(
+ object_eval, edit->psmd->modifier.name);
+ recalc_emitter_field(depsgraph, ob, edit->psys);
+ }
- toggle_particle_cursor(C, 1);
- WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_PARTICLE, NULL);
- }
- else {
- ob->mode &= ~mode_flag;
- toggle_particle_cursor(C, 0);
- free_all_psys_edit(ob);
- WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
- }
+ toggle_particle_cursor(C, 1);
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_PARTICLE, NULL);
+ }
+ else {
+ ob->mode &= ~mode_flag;
+ toggle_particle_cursor(C, 0);
+ free_all_psys_edit(ob);
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
- WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
+ WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
- WM_toolsystem_update_from_context_view3d(C);
+ WM_toolsystem_update_from_context_view3d(C);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_particle_edit_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Particle Edit Toggle";
- ot->idname = "PARTICLE_OT_particle_edit_toggle";
- ot->description = "Toggle particle edit mode";
+ /* identifiers */
+ ot->name = "Particle Edit Toggle";
+ ot->idname = "PARTICLE_OT_particle_edit_toggle";
+ ot->description = "Toggle particle edit mode";
- /* api callbacks */
- ot->exec = particle_edit_toggle_exec;
- ot->poll = particle_edit_toggle_poll;
+ /* api callbacks */
+ ot->exec = particle_edit_toggle_exec;
+ ot->poll = particle_edit_toggle_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/************************ set editable operator ************************/
static int clear_edited_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = CTX_data_active_object(C);
- ParticleSystem *psys = psys_get_current(ob);
+ Object *ob = CTX_data_active_object(C);
+ ParticleSystem *psys = psys_get_current(ob);
- if (psys->edit) {
- if (psys->edit->edited || 1) {
- PE_free_ptcache_edit(psys->edit);
+ if (psys->edit) {
+ if (psys->edit->edited || 1) {
+ PE_free_ptcache_edit(psys->edit);
- psys->edit = NULL;
- psys->free_edit = NULL;
+ psys->edit = NULL;
+ psys->free_edit = NULL;
- psys->recalc |= ID_RECALC_PSYS_RESET;
- psys->flag &= ~PSYS_GLOBAL_HAIR;
- psys->flag &= ~PSYS_EDITED;
+ psys->recalc |= ID_RECALC_PSYS_RESET;
+ psys->flag &= ~PSYS_GLOBAL_HAIR;
+ psys->flag &= ~PSYS_EDITED;
- psys_reset(psys, PSYS_RESET_DEPSGRAPH);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- }
- else { /* some operation might have protected hair from editing so let's clear the flag */
- psys->recalc |= ID_RECALC_PSYS_RESET;
- psys->flag &= ~PSYS_GLOBAL_HAIR;
- psys->flag &= ~PSYS_EDITED;
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
+ psys_reset(psys, PSYS_RESET_DEPSGRAPH);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ }
+ else { /* some operation might have protected hair from editing so let's clear the flag */
+ psys->recalc |= ID_RECALC_PSYS_RESET;
+ psys->flag &= ~PSYS_GLOBAL_HAIR;
+ psys->flag &= ~PSYS_EDITED;
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int clear_edited_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- return WM_operator_confirm_message(C, op, "Lose changes done in particle mode? (no undo)");
+ return WM_operator_confirm_message(C, op, "Lose changes done in particle mode? (no undo)");
}
void PARTICLE_OT_edited_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Edited";
- ot->idname = "PARTICLE_OT_edited_clear";
- ot->description = "Undo all edition performed on the particle system";
+ /* identifiers */
+ ot->name = "Clear Edited";
+ ot->idname = "PARTICLE_OT_edited_clear";
+ ot->description = "Undo all edition performed on the particle system";
- /* api callbacks */
- ot->exec = clear_edited_exec;
- ot->poll = particle_edit_toggle_poll;
- ot->invoke = clear_edited_invoke;
+ /* api callbacks */
+ ot->exec = clear_edited_exec;
+ ot->poll = particle_edit_toggle_poll;
+ ot->invoke = clear_edited_invoke;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************ Unify length operator ************************/
static float calculate_point_length(PTCacheEditPoint *point)
{
- float length = 0.0f;
- KEY_K;
- LOOP_KEYS {
- if (k > 0) {
- length += len_v3v3((key - 1)->co, key->co);
- }
- }
- return length;
+ float length = 0.0f;
+ KEY_K;
+ LOOP_KEYS
+ {
+ if (k > 0) {
+ length += len_v3v3((key - 1)->co, key->co);
+ }
+ }
+ return length;
}
static float calculate_average_length(PTCacheEdit *edit)
{
- int num_selected = 0;
- float total_length = 0;
- POINT_P;
- LOOP_SELECTED_POINTS {
- total_length += calculate_point_length(point);
- ++num_selected;
- }
- if (num_selected == 0) {
- return 0.0f;
- }
- return total_length / num_selected;
+ int num_selected = 0;
+ float total_length = 0;
+ POINT_P;
+ LOOP_SELECTED_POINTS
+ {
+ total_length += calculate_point_length(point);
+ ++num_selected;
+ }
+ if (num_selected == 0) {
+ return 0.0f;
+ }
+ return total_length / num_selected;
}
static void scale_point_factor(PTCacheEditPoint *point, float factor)
{
- float orig_prev_co[3], prev_co[3];
- KEY_K;
- LOOP_KEYS {
- if (k == 0) {
- copy_v3_v3(orig_prev_co, key->co);
- copy_v3_v3(prev_co, key->co);
- }
- else {
- float new_co[3];
- float delta[3];
-
- sub_v3_v3v3(delta, key->co, orig_prev_co);
- mul_v3_fl(delta, factor);
- add_v3_v3v3(new_co, prev_co, delta);
-
- copy_v3_v3(orig_prev_co, key->co);
- copy_v3_v3(key->co, new_co);
- copy_v3_v3(prev_co, key->co);
- }
- }
- point->flag |= PEP_EDIT_RECALC;
+ float orig_prev_co[3], prev_co[3];
+ KEY_K;
+ LOOP_KEYS
+ {
+ if (k == 0) {
+ copy_v3_v3(orig_prev_co, key->co);
+ copy_v3_v3(prev_co, key->co);
+ }
+ else {
+ float new_co[3];
+ float delta[3];
+
+ sub_v3_v3v3(delta, key->co, orig_prev_co);
+ mul_v3_fl(delta, factor);
+ add_v3_v3v3(new_co, prev_co, delta);
+
+ copy_v3_v3(orig_prev_co, key->co);
+ copy_v3_v3(key->co, new_co);
+ copy_v3_v3(prev_co, key->co);
+ }
+ }
+ point->flag |= PEP_EDIT_RECALC;
}
static void scale_point_to_length(PTCacheEditPoint *point, float length)
{
- const float point_length = calculate_point_length(point);
- if (point_length != 0.0f) {
- const float factor = length / point_length;
- scale_point_factor(point, factor);
- }
+ const float point_length = calculate_point_length(point);
+ if (point_length != 0.0f) {
+ const float factor = length / point_length;
+ scale_point_factor(point, factor);
+ }
}
static void scale_points_to_length(PTCacheEdit *edit, float length)
{
- POINT_P;
- LOOP_SELECTED_POINTS {
- scale_point_to_length(point, length);
- }
- recalc_lengths(edit);
+ POINT_P;
+ LOOP_SELECTED_POINTS
+ {
+ scale_point_to_length(point, length);
+ }
+ recalc_lengths(edit);
}
static int unify_length_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = CTX_data_active_object(C);
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- float average_length = calculate_average_length(edit);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ float average_length = calculate_average_length(edit);
- if (average_length == 0.0f) {
- return OPERATOR_CANCELLED;
- }
- scale_points_to_length(edit, average_length);
+ if (average_length == 0.0f) {
+ return OPERATOR_CANCELLED;
+ }
+ scale_points_to_length(edit, average_length);
- PE_update_object(depsgraph, scene, ob, 1);
- if (edit->psys) {
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
- }
- else {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- }
+ PE_update_object(depsgraph, scene, ob, 1);
+ if (edit->psys) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
+ }
+ else {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_unify_length(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unify Length";
- ot->idname = "PARTICLE_OT_unify_length";
- ot->description = "Make selected hair the same length";
+ /* identifiers */
+ ot->name = "Unify Length";
+ ot->idname = "PARTICLE_OT_unify_length";
+ ot->description = "Make selected hair the same length";
- /* api callbacks */
- ot->exec = unify_length_exec;
- ot->poll = PE_poll_view3d;
+ /* api callbacks */
+ ot->exec = unify_length_exec;
+ ot->poll = PE_poll_view3d;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/physics/particle_edit_undo.c b/source/blender/editors/physics/particle_edit_undo.c
index 877bfbac953..be625eb939f 100644
--- a/source/blender/editors/physics/particle_edit_undo.c
+++ b/source/blender/editors/physics/particle_edit_undo.c
@@ -56,153 +56,161 @@
static void undoptcache_from_editcache(PTCacheUndo *undo, PTCacheEdit *edit)
{
- PTCacheEditPoint *point;
- int i;
+ PTCacheEditPoint *point;
+ int i;
- size_t mem_used_prev = MEM_get_memory_in_use();
+ size_t mem_used_prev = MEM_get_memory_in_use();
- undo->totpoint = edit->totpoint;
+ undo->totpoint = edit->totpoint;
- if (edit->psys) {
- ParticleData *pa;
+ if (edit->psys) {
+ ParticleData *pa;
- pa = undo->particles = MEM_dupallocN(edit->psys->particles);
+ pa = undo->particles = MEM_dupallocN(edit->psys->particles);
- for (i = 0; i < edit->totpoint; i++, pa++) {
- pa->hair = MEM_dupallocN(pa->hair);
- }
+ for (i = 0; i < edit->totpoint; i++, pa++) {
+ pa->hair = MEM_dupallocN(pa->hair);
+ }
- undo->psys_flag = edit->psys->flag;
- }
- else {
- PTCacheMem *pm;
+ undo->psys_flag = edit->psys->flag;
+ }
+ else {
+ PTCacheMem *pm;
- BLI_duplicatelist(&undo->mem_cache, &edit->pid.cache->mem_cache);
- pm = undo->mem_cache.first;
+ BLI_duplicatelist(&undo->mem_cache, &edit->pid.cache->mem_cache);
+ pm = undo->mem_cache.first;
- for (; pm; pm = pm->next) {
- for (i = 0; i < BPHYS_TOT_DATA; i++) {
- pm->data[i] = MEM_dupallocN(pm->data[i]);
- }
- }
- }
+ for (; pm; pm = pm->next) {
+ for (i = 0; i < BPHYS_TOT_DATA; i++) {
+ pm->data[i] = MEM_dupallocN(pm->data[i]);
+ }
+ }
+ }
- point = undo->points = MEM_dupallocN(edit->points);
- undo->totpoint = edit->totpoint;
+ point = undo->points = MEM_dupallocN(edit->points);
+ undo->totpoint = edit->totpoint;
- for (i = 0; i < edit->totpoint; i++, point++) {
- point->keys = MEM_dupallocN(point->keys);
- /* no need to update edit key->co & key->time pointers here */
- }
+ for (i = 0; i < edit->totpoint; i++, point++) {
+ point->keys = MEM_dupallocN(point->keys);
+ /* no need to update edit key->co & key->time pointers here */
+ }
- size_t mem_used_curr = MEM_get_memory_in_use();
+ size_t mem_used_curr = MEM_get_memory_in_use();
- undo->undo_size = mem_used_prev < mem_used_curr ? mem_used_curr - mem_used_prev : sizeof(PTCacheUndo);
+ undo->undo_size = mem_used_prev < mem_used_curr ? mem_used_curr - mem_used_prev :
+ sizeof(PTCacheUndo);
}
static void undoptcache_to_editcache(PTCacheUndo *undo, PTCacheEdit *edit)
{
- ParticleSystem *psys = edit->psys;
- ParticleData *pa;
- HairKey *hkey;
- POINT_P; KEY_K;
-
- LOOP_POINTS {
- if (psys && psys->particles[p].hair) {
- MEM_freeN(psys->particles[p].hair);
- }
-
- if (point->keys) {
- MEM_freeN(point->keys);
- }
- }
- if (psys && psys->particles) {
- MEM_freeN(psys->particles);
- }
- if (edit->points) {
- MEM_freeN(edit->points);
- }
- if (edit->mirror_cache) {
- MEM_freeN(edit->mirror_cache);
- edit->mirror_cache = NULL;
- }
-
- edit->points = MEM_dupallocN(undo->points);
- edit->totpoint = undo->totpoint;
-
- LOOP_POINTS {
- point->keys = MEM_dupallocN(point->keys);
- }
-
- if (psys) {
- psys->particles = MEM_dupallocN(undo->particles);
-
- psys->totpart = undo->totpoint;
-
- LOOP_POINTS {
- pa = psys->particles + p;
- hkey = pa->hair = MEM_dupallocN(pa->hair);
-
- LOOP_KEYS {
- key->co = hkey->co;
- key->time = &hkey->time;
- hkey++;
- }
- }
-
- psys->flag = undo->psys_flag;
- }
- else {
- PTCacheMem *pm;
- int i;
-
- BKE_ptcache_free_mem(&edit->pid.cache->mem_cache);
-
- BLI_duplicatelist(&edit->pid.cache->mem_cache, &undo->mem_cache);
-
- pm = edit->pid.cache->mem_cache.first;
-
- for (; pm; pm = pm->next) {
- for (i = 0; i < BPHYS_TOT_DATA; i++) {
- pm->data[i] = MEM_dupallocN(pm->data[i]);
- }
- BKE_ptcache_mem_pointers_init(pm);
-
- LOOP_POINTS {
- LOOP_KEYS {
- if ((int)key->ftime == (int)pm->frame) {
- key->co = pm->cur[BPHYS_DATA_LOCATION];
- key->vel = pm->cur[BPHYS_DATA_VELOCITY];
- key->rot = pm->cur[BPHYS_DATA_ROTATION];
- key->time = &key->ftime;
- }
- }
- BKE_ptcache_mem_pointers_incr(pm);
- }
- }
- }
+ ParticleSystem *psys = edit->psys;
+ ParticleData *pa;
+ HairKey *hkey;
+ POINT_P;
+ KEY_K;
+
+ LOOP_POINTS
+ {
+ if (psys && psys->particles[p].hair) {
+ MEM_freeN(psys->particles[p].hair);
+ }
+
+ if (point->keys) {
+ MEM_freeN(point->keys);
+ }
+ }
+ if (psys && psys->particles) {
+ MEM_freeN(psys->particles);
+ }
+ if (edit->points) {
+ MEM_freeN(edit->points);
+ }
+ if (edit->mirror_cache) {
+ MEM_freeN(edit->mirror_cache);
+ edit->mirror_cache = NULL;
+ }
+
+ edit->points = MEM_dupallocN(undo->points);
+ edit->totpoint = undo->totpoint;
+
+ LOOP_POINTS
+ {
+ point->keys = MEM_dupallocN(point->keys);
+ }
+
+ if (psys) {
+ psys->particles = MEM_dupallocN(undo->particles);
+
+ psys->totpart = undo->totpoint;
+
+ LOOP_POINTS
+ {
+ pa = psys->particles + p;
+ hkey = pa->hair = MEM_dupallocN(pa->hair);
+
+ LOOP_KEYS
+ {
+ key->co = hkey->co;
+ key->time = &hkey->time;
+ hkey++;
+ }
+ }
+
+ psys->flag = undo->psys_flag;
+ }
+ else {
+ PTCacheMem *pm;
+ int i;
+
+ BKE_ptcache_free_mem(&edit->pid.cache->mem_cache);
+
+ BLI_duplicatelist(&edit->pid.cache->mem_cache, &undo->mem_cache);
+
+ pm = edit->pid.cache->mem_cache.first;
+
+ for (; pm; pm = pm->next) {
+ for (i = 0; i < BPHYS_TOT_DATA; i++) {
+ pm->data[i] = MEM_dupallocN(pm->data[i]);
+ }
+ BKE_ptcache_mem_pointers_init(pm);
+
+ LOOP_POINTS
+ {
+ LOOP_KEYS
+ {
+ if ((int)key->ftime == (int)pm->frame) {
+ key->co = pm->cur[BPHYS_DATA_LOCATION];
+ key->vel = pm->cur[BPHYS_DATA_VELOCITY];
+ key->rot = pm->cur[BPHYS_DATA_ROTATION];
+ key->time = &key->ftime;
+ }
+ }
+ BKE_ptcache_mem_pointers_incr(pm);
+ }
+ }
+ }
}
static void undoptcache_free_data(PTCacheUndo *undo)
{
- PTCacheEditPoint *point;
- int i;
-
- for (i = 0, point = undo->points; i < undo->totpoint; i++, point++) {
- if (undo->particles && (undo->particles + i)->hair) {
- MEM_freeN((undo->particles + i)->hair);
- }
- if (point->keys) {
- MEM_freeN(point->keys);
- }
- }
- if (undo->points) {
- MEM_freeN(undo->points);
- }
- if (undo->particles) {
- MEM_freeN(undo->particles);
- }
- BKE_ptcache_free_mem(&undo->mem_cache);
+ PTCacheEditPoint *point;
+ int i;
+
+ for (i = 0, point = undo->points; i < undo->totpoint; i++, point++) {
+ if (undo->particles && (undo->particles + i)->hair) {
+ MEM_freeN((undo->particles + i)->hair);
+ }
+ if (point->keys) {
+ MEM_freeN(point->keys);
+ }
+ }
+ if (undo->points) {
+ MEM_freeN(undo->points);
+ }
+ if (undo->particles) {
+ MEM_freeN(undo->particles);
+ }
+ BKE_ptcache_free_mem(&undo->mem_cache);
}
/** \} */
@@ -212,80 +220,86 @@ static void undoptcache_free_data(PTCacheUndo *undo)
* \{ */
typedef struct ParticleUndoStep {
- UndoStep step;
- UndoRefID_Scene scene_ref;
- UndoRefID_Object object_ref;
- PTCacheUndo data;
+ UndoStep step;
+ UndoRefID_Scene scene_ref;
+ UndoRefID_Object object_ref;
+ PTCacheUndo data;
} ParticleUndoStep;
static bool particle_undosys_poll(struct bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- PTCacheEdit *edit = PE_get_current(scene, ob);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
- return (edit != NULL);
+ return (edit != NULL);
}
-static bool particle_undosys_step_encode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p)
+static bool particle_undosys_step_encode(struct bContext *C,
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p)
{
- ParticleUndoStep *us = (ParticleUndoStep *)us_p;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- us->scene_ref.ptr = CTX_data_scene(C);
- us->object_ref.ptr = OBACT(view_layer);
- PTCacheEdit *edit = PE_get_current(us->scene_ref.ptr, us->object_ref.ptr);
- undoptcache_from_editcache(&us->data, edit);
- return true;
+ ParticleUndoStep *us = (ParticleUndoStep *)us_p;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ us->scene_ref.ptr = CTX_data_scene(C);
+ us->object_ref.ptr = OBACT(view_layer);
+ PTCacheEdit *edit = PE_get_current(us->scene_ref.ptr, us->object_ref.ptr);
+ undoptcache_from_editcache(&us->data, edit);
+ return true;
}
-static void particle_undosys_step_decode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p, int UNUSED(dir))
+static void particle_undosys_step_decode(struct bContext *C,
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p,
+ int UNUSED(dir))
{
- /* TODO(campbell): undo_system: use low-level API to set mode. */
- ED_object_mode_set(C, OB_MODE_PARTICLE_EDIT);
- BLI_assert(particle_undosys_poll(C));
-
- ParticleUndoStep *us = (ParticleUndoStep *)us_p;
- Scene *scene = us->scene_ref.ptr;
- Object *ob = us->object_ref.ptr;
- PTCacheEdit *edit = PE_get_current(scene, ob);
- if (edit) {
- undoptcache_to_editcache(&us->data, edit);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- else {
- BLI_assert(0);
- }
+ /* TODO(campbell): undo_system: use low-level API to set mode. */
+ ED_object_mode_set(C, OB_MODE_PARTICLE_EDIT);
+ BLI_assert(particle_undosys_poll(C));
+
+ ParticleUndoStep *us = (ParticleUndoStep *)us_p;
+ Scene *scene = us->scene_ref.ptr;
+ Object *ob = us->object_ref.ptr;
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ if (edit) {
+ undoptcache_to_editcache(&us->data, edit);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ else {
+ BLI_assert(0);
+ }
}
static void particle_undosys_step_free(UndoStep *us_p)
{
- ParticleUndoStep *us = (ParticleUndoStep *)us_p;
- undoptcache_free_data(&us->data);
+ ParticleUndoStep *us = (ParticleUndoStep *)us_p;
+ undoptcache_free_data(&us->data);
}
-static void particle_undosys_foreach_ID_ref(
- UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+static void particle_undosys_foreach_ID_ref(UndoStep *us_p,
+ UndoTypeForEachIDRefFn foreach_ID_ref_fn,
+ void *user_data)
{
- ParticleUndoStep *us = (ParticleUndoStep *)us_p;
- foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->scene_ref));
- foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->object_ref));
+ ParticleUndoStep *us = (ParticleUndoStep *)us_p;
+ foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->scene_ref));
+ foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->object_ref));
}
/* Export for ED_undo_sys. */
void ED_particle_undosys_type(UndoType *ut)
{
- ut->name = "Edit Particle";
- ut->poll = particle_undosys_poll;
- ut->step_encode = particle_undosys_step_encode;
- ut->step_decode = particle_undosys_step_decode;
- ut->step_free = particle_undosys_step_free;
+ ut->name = "Edit Particle";
+ ut->poll = particle_undosys_poll;
+ ut->step_encode = particle_undosys_step_encode;
+ ut->step_decode = particle_undosys_step_decode;
+ ut->step_free = particle_undosys_step_free;
- ut->step_foreach_ID_ref = particle_undosys_foreach_ID_ref;
+ ut->step_foreach_ID_ref = particle_undosys_foreach_ID_ref;
- ut->use_context = true;
+ ut->use_context = true;
- ut->step_size = sizeof(ParticleUndoStep);
+ ut->step_size = sizeof(ParticleUndoStep);
}
/** \} */
diff --git a/source/blender/editors/physics/particle_edit_utildefines.h b/source/blender/editors/physics/particle_edit_utildefines.h
index afdeb5e985c..da27420505f 100644
--- a/source/blender/editors/physics/particle_edit_utildefines.h
+++ b/source/blender/editors/physics/particle_edit_utildefines.h
@@ -24,19 +24,39 @@
#ifndef __PARTICLE_EDIT_UTILDEFNIES_H__
#define __PARTICLE_EDIT_UTILDEFNIES_H__
-#define KEY_K PTCacheEditKey *key; int k
-#define POINT_P PTCacheEditPoint *point; int p
-#define LOOP_POINTS for (p = 0, point = edit->points; p < edit->totpoint; p++, point++)
-#define LOOP_VISIBLE_POINTS for (p = 0, point = edit->points; p < edit->totpoint; p++, point++) if (!(point->flag & PEP_HIDE))
-#define LOOP_SELECTED_POINTS for (p = 0, point = edit->points; p < edit->totpoint; p++, point++) if (point_is_selected(point))
-#define LOOP_UNSELECTED_POINTS for (p = 0, point = edit->points; p < edit->totpoint; p++, point++) if (!point_is_selected(point))
-#define LOOP_EDITED_POINTS for (p = 0, point = edit->points; p < edit->totpoint; p++, point++) if (point->flag & PEP_EDIT_RECALC)
-#define LOOP_TAGGED_POINTS for (p = 0, point = edit->points; p < edit->totpoint; p++, point++) if (point->flag & PEP_TAG)
-#define LOOP_KEYS for (k = 0, key = point->keys; k < point->totkey; k++, key++)
-#define LOOP_VISIBLE_KEYS for (k = 0, key = point->keys; k < point->totkey; k++, key++) if (!(key->flag & PEK_HIDE))
-#define LOOP_SELECTED_KEYS for (k = 0, key = point->keys; k < point->totkey; k++, key++) if ((key->flag & PEK_SELECT) && !(key->flag & PEK_HIDE))
-#define LOOP_TAGGED_KEYS for (k = 0, key = point->keys; k < point->totkey; k++, key++) if (key->flag & PEK_TAG)
+#define KEY_K \
+ PTCacheEditKey *key; \
+ int k
+#define POINT_P \
+ PTCacheEditPoint *point; \
+ int p
+#define LOOP_POINTS for (p = 0, point = edit->points; p < edit->totpoint; p++, point++)
+#define LOOP_VISIBLE_POINTS \
+ for (p = 0, point = edit->points; p < edit->totpoint; p++, point++) \
+ if (!(point->flag & PEP_HIDE))
+#define LOOP_SELECTED_POINTS \
+ for (p = 0, point = edit->points; p < edit->totpoint; p++, point++) \
+ if (point_is_selected(point))
+#define LOOP_UNSELECTED_POINTS \
+ for (p = 0, point = edit->points; p < edit->totpoint; p++, point++) \
+ if (!point_is_selected(point))
+#define LOOP_EDITED_POINTS \
+ for (p = 0, point = edit->points; p < edit->totpoint; p++, point++) \
+ if (point->flag & PEP_EDIT_RECALC)
+#define LOOP_TAGGED_POINTS \
+ for (p = 0, point = edit->points; p < edit->totpoint; p++, point++) \
+ if (point->flag & PEP_TAG)
+#define LOOP_KEYS for (k = 0, key = point->keys; k < point->totkey; k++, key++)
+#define LOOP_VISIBLE_KEYS \
+ for (k = 0, key = point->keys; k < point->totkey; k++, key++) \
+ if (!(key->flag & PEK_HIDE))
+#define LOOP_SELECTED_KEYS \
+ for (k = 0, key = point->keys; k < point->totkey; k++, key++) \
+ if ((key->flag & PEK_SELECT) && !(key->flag & PEK_HIDE))
+#define LOOP_TAGGED_KEYS \
+ for (k = 0, key = point->keys; k < point->totkey; k++, key++) \
+ if (key->flag & PEK_TAG)
-#define KEY_WCO ((key->flag & PEK_USE_WCO) ? key->world_co : key->co)
+#define KEY_WCO ((key->flag & PEK_USE_WCO) ? key->world_co : key->co)
-#endif /* __PARTICLE_EDIT_UTILDEFNIES_H__ */
+#endif /* __PARTICLE_EDIT_UTILDEFNIES_H__ */
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 2287659ef03..92eed9be2f5 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -21,7 +21,6 @@
* \ingroup edphys
*/
-
#include <stdlib.h>
#include <string.h>
@@ -70,956 +69,971 @@
#include "physics_intern.h"
-static float I[4][4] = {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}};
+static float I[4][4] = {{1.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 1.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 1.0f, 0.0f},
+ {0.0f, 0.0f, 0.0f, 1.0f}};
/********************** particle system slot operators *********************/
static int particle_system_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_context(C);
- Scene *scene = CTX_data_scene(C);
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_context(C);
+ Scene *scene = CTX_data_scene(C);
- if (!scene || !ob)
- return OPERATOR_CANCELLED;
+ if (!scene || !ob)
+ return OPERATOR_CANCELLED;
- object_add_particle_system(bmain, scene, ob, NULL);
+ object_add_particle_system(bmain, scene, ob, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_particle_system_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Particle System Slot";
- ot->idname = "OBJECT_OT_particle_system_add";
- ot->description = "Add a particle system";
+ /* identifiers */
+ ot->name = "Add Particle System Slot";
+ ot->idname = "OBJECT_OT_particle_system_add";
+ ot->description = "Add a particle system";
- /* api callbacks */
- ot->poll = ED_operator_object_active_editable;
- ot->exec = particle_system_add_exec;
+ /* api callbacks */
+ ot->poll = ED_operator_object_active_editable;
+ ot->exec = particle_system_add_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_context(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- int mode_orig;
-
- if (!scene || !ob)
- return OPERATOR_CANCELLED;
-
- mode_orig = ob->mode;
- object_remove_particle_system(bmain, scene, ob);
-
- /* possible this isn't the active object
- * object_remove_particle_system() clears the mode on the last psys
- */
- if (mode_orig & OB_MODE_PARTICLE_EDIT) {
- if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) {
- if (view_layer->basact && view_layer->basact->object == ob) {
- WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
- }
- }
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, ob);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_context(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ int mode_orig;
+
+ if (!scene || !ob)
+ return OPERATOR_CANCELLED;
+
+ mode_orig = ob->mode;
+ object_remove_particle_system(bmain, scene, ob);
+
+ /* possible this isn't the active object
+ * object_remove_particle_system() clears the mode on the last psys
+ */
+ if (mode_orig & OB_MODE_PARTICLE_EDIT) {
+ if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) {
+ if (view_layer->basact && view_layer->basact->object == ob) {
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, ob);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_particle_system_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Particle System Slot";
- ot->idname = "OBJECT_OT_particle_system_remove";
- ot->description = "Remove the selected particle system";
+ /* identifiers */
+ ot->name = "Remove Particle System Slot";
+ ot->idname = "OBJECT_OT_particle_system_remove";
+ ot->description = "Remove the selected particle system";
- /* api callbacks */
- ot->poll = ED_operator_object_active_editable;
- ot->exec = particle_system_remove_exec;
+ /* api callbacks */
+ ot->poll = ED_operator_object_active_editable;
+ ot->exec = particle_system_remove_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** new particle settings operator *********************/
static bool psys_poll(bContext *C)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- return (ptr.data != NULL);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+ return (ptr.data != NULL);
}
static int new_particle_settings_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- ParticleSystem *psys;
- ParticleSettings *part = NULL;
- Object *ob;
- PointerRNA ptr;
+ Main *bmain = CTX_data_main(C);
+ ParticleSystem *psys;
+ ParticleSettings *part = NULL;
+ Object *ob;
+ PointerRNA ptr;
- ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+ ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- psys = ptr.data;
+ psys = ptr.data;
- /* add or copy particle setting */
- if (psys->part)
- part = BKE_particlesettings_copy(bmain, psys->part);
- else
- part = BKE_particlesettings_add(bmain, "ParticleSettings");
+ /* add or copy particle setting */
+ if (psys->part)
+ part = BKE_particlesettings_copy(bmain, psys->part);
+ else
+ part = BKE_particlesettings_add(bmain, "ParticleSettings");
- ob = ptr.id.data;
+ ob = ptr.id.data;
- if (psys->part)
- id_us_min(&psys->part->id);
+ if (psys->part)
+ id_us_min(&psys->part->id);
- psys->part = part;
+ psys->part = part;
- psys_check_boid_data(psys);
+ psys_check_boid_data(psys);
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_new(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "New Particle Settings";
- ot->idname = "PARTICLE_OT_new";
- ot->description = "Add new particle settings";
+ /* identifiers */
+ ot->name = "New Particle Settings";
+ ot->idname = "PARTICLE_OT_new";
+ ot->description = "Add new particle settings";
- /* api callbacks */
- ot->exec = new_particle_settings_exec;
- ot->poll = psys_poll;
+ /* api callbacks */
+ ot->exec = new_particle_settings_exec;
+ ot->poll = psys_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** keyed particle target operators *********************/
static int new_particle_target_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- ParticleSystem *psys = ptr.data;
- Object *ob = ptr.id.data;
+ Main *bmain = CTX_data_main(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+ ParticleSystem *psys = ptr.data;
+ Object *ob = ptr.id.data;
- ParticleTarget *pt;
+ ParticleTarget *pt;
- if (!psys)
- return OPERATOR_CANCELLED;
+ if (!psys)
+ return OPERATOR_CANCELLED;
- pt = psys->targets.first;
- for (; pt; pt = pt->next)
- pt->flag &= ~PTARGET_CURRENT;
+ pt = psys->targets.first;
+ for (; pt; pt = pt->next)
+ pt->flag &= ~PTARGET_CURRENT;
- pt = MEM_callocN(sizeof(ParticleTarget), "keyed particle target");
+ pt = MEM_callocN(sizeof(ParticleTarget), "keyed particle target");
- pt->flag |= PTARGET_CURRENT;
- pt->psys = 1;
+ pt->flag |= PTARGET_CURRENT;
+ pt->psys = 1;
- BLI_addtail(&psys->targets, pt);
+ BLI_addtail(&psys->targets, pt);
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_new_target(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "New Particle Target";
- ot->idname = "PARTICLE_OT_new_target";
- ot->description = "Add a new particle target";
+ /* identifiers */
+ ot->name = "New Particle Target";
+ ot->idname = "PARTICLE_OT_new_target";
+ ot->description = "Add a new particle target";
- /* api callbacks */
- ot->exec = new_particle_target_exec;
+ /* api callbacks */
+ ot->exec = new_particle_target_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int remove_particle_target_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- ParticleSystem *psys = ptr.data;
- Object *ob = ptr.id.data;
-
- ParticleTarget *pt;
+ Main *bmain = CTX_data_main(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+ ParticleSystem *psys = ptr.data;
+ Object *ob = ptr.id.data;
- if (!psys)
- return OPERATOR_CANCELLED;
+ ParticleTarget *pt;
- pt = psys->targets.first;
- for (; pt; pt = pt->next) {
- if (pt->flag & PTARGET_CURRENT) {
- BLI_remlink(&psys->targets, pt);
- MEM_freeN(pt);
- break;
- }
+ if (!psys)
+ return OPERATOR_CANCELLED;
- }
- pt = psys->targets.last;
+ pt = psys->targets.first;
+ for (; pt; pt = pt->next) {
+ if (pt->flag & PTARGET_CURRENT) {
+ BLI_remlink(&psys->targets, pt);
+ MEM_freeN(pt);
+ break;
+ }
+ }
+ pt = psys->targets.last;
- if (pt)
- pt->flag |= PTARGET_CURRENT;
+ if (pt)
+ pt->flag |= PTARGET_CURRENT;
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_target_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Particle Target";
- ot->idname = "PARTICLE_OT_target_remove";
- ot->description = "Remove the selected particle target";
+ /* identifiers */
+ ot->name = "Remove Particle Target";
+ ot->idname = "PARTICLE_OT_target_remove";
+ ot->description = "Remove the selected particle target";
- /* api callbacks */
- ot->exec = remove_particle_target_exec;
+ /* api callbacks */
+ ot->exec = remove_particle_target_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************ move up particle target operator *********************/
static int target_move_up_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- ParticleSystem *psys = ptr.data;
- Object *ob = ptr.id.data;
- ParticleTarget *pt;
-
- if (!psys)
- return OPERATOR_CANCELLED;
-
- pt = psys->targets.first;
- for (; pt; pt = pt->next) {
- if (pt->flag & PTARGET_CURRENT && pt->prev) {
- BLI_remlink(&psys->targets, pt);
- BLI_insertlinkbefore(&psys->targets, pt->prev, pt);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
- break;
- }
- }
-
- return OPERATOR_FINISHED;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+ ParticleSystem *psys = ptr.data;
+ Object *ob = ptr.id.data;
+ ParticleTarget *pt;
+
+ if (!psys)
+ return OPERATOR_CANCELLED;
+
+ pt = psys->targets.first;
+ for (; pt; pt = pt->next) {
+ if (pt->flag & PTARGET_CURRENT && pt->prev) {
+ BLI_remlink(&psys->targets, pt);
+ BLI_insertlinkbefore(&psys->targets, pt->prev, pt);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
+ break;
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_target_move_up(wmOperatorType *ot)
{
- ot->name = "Move Up Target";
- ot->idname = "PARTICLE_OT_target_move_up";
- ot->description = "Move particle target up in the list";
+ ot->name = "Move Up Target";
+ ot->idname = "PARTICLE_OT_target_move_up";
+ ot->description = "Move particle target up in the list";
- ot->exec = target_move_up_exec;
+ ot->exec = target_move_up_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************ move down particle target operator *********************/
static int target_move_down_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- ParticleSystem *psys = ptr.data;
- Object *ob = ptr.id.data;
- ParticleTarget *pt;
-
- if (!psys)
- return OPERATOR_CANCELLED;
- pt = psys->targets.first;
- for (; pt; pt = pt->next) {
- if (pt->flag & PTARGET_CURRENT && pt->next) {
- BLI_remlink(&psys->targets, pt);
- BLI_insertlinkafter(&psys->targets, pt->next, pt);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
- break;
- }
- }
-
- return OPERATOR_FINISHED;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+ ParticleSystem *psys = ptr.data;
+ Object *ob = ptr.id.data;
+ ParticleTarget *pt;
+
+ if (!psys)
+ return OPERATOR_CANCELLED;
+ pt = psys->targets.first;
+ for (; pt; pt = pt->next) {
+ if (pt->flag & PTARGET_CURRENT && pt->next) {
+ BLI_remlink(&psys->targets, pt);
+ BLI_insertlinkafter(&psys->targets, pt->next, pt);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
+ break;
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_target_move_down(wmOperatorType *ot)
{
- ot->name = "Move Down Target";
- ot->idname = "PARTICLE_OT_target_move_down";
- ot->description = "Move particle target down in the list";
+ ot->name = "Move Down Target";
+ ot->idname = "PARTICLE_OT_target_move_down";
+ ot->description = "Move particle target down in the list";
- ot->exec = target_move_down_exec;
+ ot->exec = target_move_down_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************ refresh dupli objects *********************/
static int dupliob_refresh_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- ParticleSystem *psys = ptr.data;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+ ParticleSystem *psys = ptr.data;
- if (!psys)
- return OPERATOR_CANCELLED;
+ if (!psys)
+ return OPERATOR_CANCELLED;
- psys_check_group_weights(psys->part);
- DEG_id_tag_update(&psys->part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL);
+ psys_check_group_weights(psys->part);
+ DEG_id_tag_update(&psys->part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_dupliob_refresh(wmOperatorType *ot)
{
- ot->name = "Refresh Dupli Objects";
- ot->idname = "PARTICLE_OT_dupliob_refresh";
- ot->description = "Refresh list of dupli objects and their weights";
+ ot->name = "Refresh Dupli Objects";
+ ot->idname = "PARTICLE_OT_dupliob_refresh";
+ ot->description = "Refresh list of dupli objects and their weights";
- ot->exec = dupliob_refresh_exec;
+ ot->exec = dupliob_refresh_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************ move up particle dupliweight operator *********************/
static int dupliob_move_up_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- ParticleSystem *psys = ptr.data;
- ParticleSettings *part;
- ParticleDupliWeight *dw;
-
- if (!psys)
- return OPERATOR_CANCELLED;
-
- part = psys->part;
- for (dw = part->instance_weights.first; dw; dw = dw->next) {
- if (dw->flag & PART_DUPLIW_CURRENT && dw->prev) {
- BLI_remlink(&part->instance_weights, dw);
- BLI_insertlinkbefore(&part->instance_weights, dw->prev, dw);
-
- DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL);
- break;
- }
- }
-
- return OPERATOR_FINISHED;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+ ParticleSystem *psys = ptr.data;
+ ParticleSettings *part;
+ ParticleDupliWeight *dw;
+
+ if (!psys)
+ return OPERATOR_CANCELLED;
+
+ part = psys->part;
+ for (dw = part->instance_weights.first; dw; dw = dw->next) {
+ if (dw->flag & PART_DUPLIW_CURRENT && dw->prev) {
+ BLI_remlink(&part->instance_weights, dw);
+ BLI_insertlinkbefore(&part->instance_weights, dw->prev, dw);
+
+ DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL);
+ break;
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_dupliob_move_up(wmOperatorType *ot)
{
- ot->name = "Move Up Dupli Object";
- ot->idname = "PARTICLE_OT_dupliob_move_up";
- ot->description = "Move dupli object up in the list";
+ ot->name = "Move Up Dupli Object";
+ ot->idname = "PARTICLE_OT_dupliob_move_up";
+ ot->description = "Move dupli object up in the list";
- ot->exec = dupliob_move_up_exec;
+ ot->exec = dupliob_move_up_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** particle dupliweight operators *********************/
static int copy_particle_dupliob_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- ParticleSystem *psys = ptr.data;
- ParticleSettings *part;
- ParticleDupliWeight *dw;
-
- if (!psys)
- return OPERATOR_CANCELLED;
- part = psys->part;
- for (dw = part->instance_weights.first; dw; dw = dw->next) {
- if (dw->flag & PART_DUPLIW_CURRENT) {
- dw->flag &= ~PART_DUPLIW_CURRENT;
- dw = MEM_dupallocN(dw);
- dw->flag |= PART_DUPLIW_CURRENT;
- BLI_addhead(&part->instance_weights, dw);
-
- DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL);
- break;
- }
- }
-
- return OPERATOR_FINISHED;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+ ParticleSystem *psys = ptr.data;
+ ParticleSettings *part;
+ ParticleDupliWeight *dw;
+
+ if (!psys)
+ return OPERATOR_CANCELLED;
+ part = psys->part;
+ for (dw = part->instance_weights.first; dw; dw = dw->next) {
+ if (dw->flag & PART_DUPLIW_CURRENT) {
+ dw->flag &= ~PART_DUPLIW_CURRENT;
+ dw = MEM_dupallocN(dw);
+ dw->flag |= PART_DUPLIW_CURRENT;
+ BLI_addhead(&part->instance_weights, dw);
+
+ DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL);
+ break;
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_dupliob_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Particle Dupliob";
- ot->idname = "PARTICLE_OT_dupliob_copy";
- ot->description = "Duplicate the current dupliobject";
+ /* identifiers */
+ ot->name = "Copy Particle Dupliob";
+ ot->idname = "PARTICLE_OT_dupliob_copy";
+ ot->description = "Duplicate the current dupliobject";
- /* api callbacks */
- ot->exec = copy_particle_dupliob_exec;
+ /* api callbacks */
+ ot->exec = copy_particle_dupliob_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int remove_particle_dupliob_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- ParticleSystem *psys = ptr.data;
- ParticleSettings *part;
- ParticleDupliWeight *dw;
-
- if (!psys)
- return OPERATOR_CANCELLED;
-
- part = psys->part;
- for (dw = part->instance_weights.first; dw; dw = dw->next) {
- if (dw->flag & PART_DUPLIW_CURRENT) {
- BLI_remlink(&part->instance_weights, dw);
- MEM_freeN(dw);
- break;
- }
-
- }
- dw = part->instance_weights.last;
-
- if (dw)
- dw->flag |= PART_DUPLIW_CURRENT;
-
- DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL);
-
- return OPERATOR_FINISHED;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+ ParticleSystem *psys = ptr.data;
+ ParticleSettings *part;
+ ParticleDupliWeight *dw;
+
+ if (!psys)
+ return OPERATOR_CANCELLED;
+
+ part = psys->part;
+ for (dw = part->instance_weights.first; dw; dw = dw->next) {
+ if (dw->flag & PART_DUPLIW_CURRENT) {
+ BLI_remlink(&part->instance_weights, dw);
+ MEM_freeN(dw);
+ break;
+ }
+ }
+ dw = part->instance_weights.last;
+
+ if (dw)
+ dw->flag |= PART_DUPLIW_CURRENT;
+
+ DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL);
+
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_dupliob_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Particle Dupliobject";
- ot->idname = "PARTICLE_OT_dupliob_remove";
- ot->description = "Remove the selected dupliobject";
+ /* identifiers */
+ ot->name = "Remove Particle Dupliobject";
+ ot->idname = "PARTICLE_OT_dupliob_remove";
+ ot->description = "Remove the selected dupliobject";
- /* api callbacks */
- ot->exec = remove_particle_dupliob_exec;
+ /* api callbacks */
+ ot->exec = remove_particle_dupliob_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************ move down particle dupliweight operator *********************/
static int dupliob_move_down_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- ParticleSystem *psys = ptr.data;
- ParticleSettings *part;
- ParticleDupliWeight *dw;
-
- if (!psys)
- return OPERATOR_CANCELLED;
-
- part = psys->part;
- for (dw = part->instance_weights.first; dw; dw = dw->next) {
- if (dw->flag & PART_DUPLIW_CURRENT && dw->next) {
- BLI_remlink(&part->instance_weights, dw);
- BLI_insertlinkafter(&part->instance_weights, dw->next, dw);
-
- DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL);
- break;
- }
- }
-
- return OPERATOR_FINISHED;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+ ParticleSystem *psys = ptr.data;
+ ParticleSettings *part;
+ ParticleDupliWeight *dw;
+
+ if (!psys)
+ return OPERATOR_CANCELLED;
+
+ part = psys->part;
+ for (dw = part->instance_weights.first; dw; dw = dw->next) {
+ if (dw->flag & PART_DUPLIW_CURRENT && dw->next) {
+ BLI_remlink(&part->instance_weights, dw);
+ BLI_insertlinkafter(&part->instance_weights, dw->next, dw);
+
+ DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL);
+ break;
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_dupliob_move_down(wmOperatorType *ot)
{
- ot->name = "Move Down Dupli Object";
- ot->idname = "PARTICLE_OT_dupliob_move_down";
- ot->description = "Move dupli object down in the list";
+ ot->name = "Move Down Dupli Object";
+ ot->idname = "PARTICLE_OT_dupliob_move_down";
+ ot->description = "Move dupli object down in the list";
- ot->exec = dupliob_move_down_exec;
+ ot->exec = dupliob_move_down_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************ connect/disconnect hair operators *********************/
-static void disconnect_hair(
- Depsgraph *depsgraph, Scene *scene,
- Object *ob, ParticleSystem *psys)
+static void disconnect_hair(Depsgraph *depsgraph, Scene *scene, Object *ob, ParticleSystem *psys)
{
- Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
- ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys);
- ParticleSystemModifierData *psmd_eval =
- psys_get_modifier(object_eval, psys_eval);
- ParticleEditSettings *pset = PE_settings(scene);
- ParticleData *pa;
- PTCacheEdit *edit;
- PTCacheEditPoint *point;
- PTCacheEditKey *ekey = NULL;
- HairKey *key;
- int i, k;
- float hairmat[4][4];
-
- if (!ob || !psys || psys->flag & PSYS_GLOBAL_HAIR)
- return;
-
- if (!psys->part || psys->part->type != PART_HAIR)
- return;
-
- edit = psys->edit;
- point = edit ? edit->points : NULL;
-
- for (i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) {
- if (point) {
- ekey = point->keys;
- point++;
- }
-
- psys_mat_hair_to_global(
- ob, psmd_eval->mesh_final, psys->part->from, pa, hairmat);
-
- for (k = 0, key = pa->hair; k < pa->totkey; k++, key++) {
- mul_m4_v3(hairmat, key->co);
-
- if (ekey) {
- ekey->flag &= ~PEK_USE_WCO;
- ekey++;
- }
- }
- }
-
- psys_free_path_cache(psys, psys->edit);
-
- psys->flag |= PSYS_GLOBAL_HAIR;
-
- if (ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_PUFF)) {
- pset->brushtype = PE_BRUSH_COMB;
- }
-
- PE_update_object(depsgraph, scene, ob, 0);
+ Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
+ ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys);
+ ParticleSystemModifierData *psmd_eval = psys_get_modifier(object_eval, psys_eval);
+ ParticleEditSettings *pset = PE_settings(scene);
+ ParticleData *pa;
+ PTCacheEdit *edit;
+ PTCacheEditPoint *point;
+ PTCacheEditKey *ekey = NULL;
+ HairKey *key;
+ int i, k;
+ float hairmat[4][4];
+
+ if (!ob || !psys || psys->flag & PSYS_GLOBAL_HAIR)
+ return;
+
+ if (!psys->part || psys->part->type != PART_HAIR)
+ return;
+
+ edit = psys->edit;
+ point = edit ? edit->points : NULL;
+
+ for (i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) {
+ if (point) {
+ ekey = point->keys;
+ point++;
+ }
+
+ psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, pa, hairmat);
+
+ for (k = 0, key = pa->hair; k < pa->totkey; k++, key++) {
+ mul_m4_v3(hairmat, key->co);
+
+ if (ekey) {
+ ekey->flag &= ~PEK_USE_WCO;
+ ekey++;
+ }
+ }
+ }
+
+ psys_free_path_cache(psys, psys->edit);
+
+ psys->flag |= PSYS_GLOBAL_HAIR;
+
+ if (ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_PUFF)) {
+ pset->brushtype = PE_BRUSH_COMB;
+ }
+
+ PE_update_object(depsgraph, scene, ob, 0);
}
static int disconnect_hair_exec(bContext *C, wmOperator *op)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_context(C);
- ParticleSystem *psys = NULL;
- const bool all = RNA_boolean_get(op->ptr, "all");
-
- if (!ob)
- return OPERATOR_CANCELLED;
-
- if (all) {
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- disconnect_hair(depsgraph, scene, ob, psys);
- }
- }
- else {
- psys = psys_get_current(ob);
- disconnect_hair(depsgraph, scene, ob, psys);
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
-
- return OPERATOR_FINISHED;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_context(C);
+ ParticleSystem *psys = NULL;
+ const bool all = RNA_boolean_get(op->ptr, "all");
+
+ if (!ob)
+ return OPERATOR_CANCELLED;
+
+ if (all) {
+ for (psys = ob->particlesystem.first; psys; psys = psys->next) {
+ disconnect_hair(depsgraph, scene, ob, psys);
+ }
+ }
+ else {
+ psys = psys_get_current(ob);
+ disconnect_hair(depsgraph, scene, ob, psys);
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
+
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_disconnect_hair(wmOperatorType *ot)
{
- ot->name = "Disconnect Hair";
- ot->description = "Disconnect hair from the emitter mesh";
- ot->idname = "PARTICLE_OT_disconnect_hair";
+ ot->name = "Disconnect Hair";
+ ot->description = "Disconnect hair from the emitter mesh";
+ ot->idname = "PARTICLE_OT_disconnect_hair";
- ot->exec = disconnect_hair_exec;
+ ot->exec = disconnect_hair_exec;
- /* flags */
- /* No REGISTER, redo does not work due to missing update, see T47750. */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ /* No REGISTER, redo does not work due to missing update, see T47750. */
+ ot->flag = OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "all", 0, "All hair", "Disconnect all hair systems from the emitter mesh");
+ RNA_def_boolean(
+ ot->srna, "all", 0, "All hair", "Disconnect all hair systems from the emitter mesh");
}
/* from/to_world_space : whether from/to particles are in world or hair space
* from/to_mat : additional transform for from/to particles (e.g. for using object space copying)
*/
-static bool remap_hair_emitter(
- Depsgraph *depsgraph, Scene *scene, Object *ob, ParticleSystem *psys,
- Object *target_ob, ParticleSystem *target_psys, PTCacheEdit *target_edit,
- float from_mat[4][4], float to_mat[4][4], bool from_global, bool to_global)
+static bool remap_hair_emitter(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ ParticleSystem *psys,
+ Object *target_ob,
+ ParticleSystem *target_psys,
+ PTCacheEdit *target_edit,
+ float from_mat[4][4],
+ float to_mat[4][4],
+ bool from_global,
+ bool to_global)
{
- Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
- ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys);
- ParticleSystemModifierData *target_psmd =
- psys_get_modifier(object_eval, psys_eval);
- ParticleData *pa, *tpa;
- PTCacheEditPoint *edit_point;
- PTCacheEditKey *ekey;
- BVHTreeFromMesh bvhtree = {NULL};
- MFace *mface = NULL, *mf;
- MEdge *medge = NULL, *me;
- MVert *mvert;
- Mesh *mesh, *target_mesh;
- int numverts;
- int i, k;
- float from_ob_imat[4][4], to_ob_imat[4][4];
- float from_imat[4][4], to_imat[4][4];
-
- if (!target_psmd->mesh_final)
- return false;
- if (!psys->part || psys->part->type != PART_HAIR)
- return false;
- if (!target_psys->part || target_psys->part->type != PART_HAIR)
- return false;
-
- edit_point = target_edit ? target_edit->points : NULL;
-
- invert_m4_m4(from_ob_imat, ob->obmat);
- invert_m4_m4(to_ob_imat, target_ob->obmat);
- invert_m4_m4(from_imat, from_mat);
- invert_m4_m4(to_imat, to_mat);
-
- if (target_psmd->mesh_final->runtime.deformed_only) {
- /* we don't want to mess up target_psmd->dm when converting to global coordinates below */
- mesh = target_psmd->mesh_final;
- }
- else {
- mesh = target_psmd->mesh_original;
- }
- target_mesh = target_psmd->mesh_final;
- if (mesh == NULL) {
- return false;
- }
- /* don't modify the original vertices */
- BKE_id_copy_ex(NULL, &mesh->id, (ID **)&mesh, LIB_ID_COPY_LOCALIZE);
-
- /* BMESH_ONLY, deform dm may not have tessface */
- BKE_mesh_tessface_ensure(mesh);
-
- numverts = mesh->totvert;
- mvert = mesh->mvert;
-
- /* convert to global coordinates */
- for (i = 0; i < numverts; i++)
- mul_m4_v3(to_mat, mvert[i].co);
-
- if (mesh->totface != 0) {
- mface = mesh->mface;
- BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_FACES, 2);
- }
- else if (mesh->totedge != 0) {
- medge = mesh->medge;
- BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_EDGES, 2);
- }
- else {
- BKE_id_free(NULL, mesh);
- return false;
- }
-
- for (i = 0, tpa = target_psys->particles, pa = psys->particles;
- i < target_psys->totpart;
- i++, tpa++, pa++)
- {
- float from_co[3];
- BVHTreeNearest nearest;
-
- if (from_global)
- mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].co);
- else
- mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].world_co);
- mul_m4_v3(from_mat, from_co);
-
- nearest.index = -1;
- nearest.dist_sq = FLT_MAX;
-
- BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
-
- if (nearest.index == -1) {
- if (G.debug & G_DEBUG)
- printf("No nearest point found for hair root!");
- continue;
- }
-
- if (mface) {
- float v[4][3];
-
- mf = &mface[nearest.index];
-
- copy_v3_v3(v[0], mvert[mf->v1].co);
- copy_v3_v3(v[1], mvert[mf->v2].co);
- copy_v3_v3(v[2], mvert[mf->v3].co);
- if (mf->v4) {
- copy_v3_v3(v[3], mvert[mf->v4].co);
- interp_weights_poly_v3(tpa->fuv, v, 4, nearest.co);
- }
- else
- interp_weights_poly_v3(tpa->fuv, v, 3, nearest.co);
- tpa->foffset = 0.0f;
-
- tpa->num = nearest.index;
- tpa->num_dmcache = psys_particle_dm_face_lookup(target_mesh, mesh, tpa->num, tpa->fuv, NULL);
- }
- else {
- me = &medge[nearest.index];
-
- tpa->fuv[1] = line_point_factor_v3(nearest.co,
- mvert[me->v1].co,
- mvert[me->v2].co);
- tpa->fuv[0] = 1.0f - tpa->fuv[1];
- tpa->fuv[2] = tpa->fuv[3] = 0.0f;
- tpa->foffset = 0.0f;
-
- tpa->num = nearest.index;
- tpa->num_dmcache = -1;
- }
-
- /* translate hair keys */
- {
- HairKey *key, *tkey;
- float hairmat[4][4], imat[4][4];
- float offset[3];
-
- if (to_global)
- copy_m4_m4(imat, target_ob->obmat);
- else {
- /* note: using target_dm here, which is in target_ob object space and has full modifiers */
- psys_mat_hair_to_object(target_ob, target_mesh, target_psys->part->from, tpa, hairmat);
- invert_m4_m4(imat, hairmat);
- }
- mul_m4_m4m4(imat, imat, to_imat);
-
- /* offset in world space */
- sub_v3_v3v3(offset, nearest.co, from_co);
-
- if (edit_point) {
- for (k = 0, key = pa->hair, tkey = tpa->hair, ekey = edit_point->keys; k < tpa->totkey; k++, key++, tkey++, ekey++) {
- float co_orig[3];
-
- if (from_global)
- mul_v3_m4v3(co_orig, from_ob_imat, key->co);
- else
- mul_v3_m4v3(co_orig, from_ob_imat, key->world_co);
- mul_m4_v3(from_mat, co_orig);
-
- add_v3_v3v3(tkey->co, co_orig, offset);
-
- mul_m4_v3(imat, tkey->co);
-
- ekey->flag |= PEK_USE_WCO;
- }
-
- edit_point++;
- }
- else {
- for (k = 0, key = pa->hair, tkey = tpa->hair; k < tpa->totkey; k++, key++, tkey++) {
- float co_orig[3];
-
- if (from_global)
- mul_v3_m4v3(co_orig, from_ob_imat, key->co);
- else
- mul_v3_m4v3(co_orig, from_ob_imat, key->world_co);
- mul_m4_v3(from_mat, co_orig);
-
- add_v3_v3v3(tkey->co, co_orig, offset);
-
- mul_m4_v3(imat, tkey->co);
- }
- }
- }
- }
-
- free_bvhtree_from_mesh(&bvhtree);
- BKE_id_free(NULL, mesh);
-
- psys_free_path_cache(target_psys, target_edit);
-
- PE_update_object(depsgraph, scene, target_ob, 0);
-
- return true;
+ Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
+ ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys);
+ ParticleSystemModifierData *target_psmd = psys_get_modifier(object_eval, psys_eval);
+ ParticleData *pa, *tpa;
+ PTCacheEditPoint *edit_point;
+ PTCacheEditKey *ekey;
+ BVHTreeFromMesh bvhtree = {NULL};
+ MFace *mface = NULL, *mf;
+ MEdge *medge = NULL, *me;
+ MVert *mvert;
+ Mesh *mesh, *target_mesh;
+ int numverts;
+ int i, k;
+ float from_ob_imat[4][4], to_ob_imat[4][4];
+ float from_imat[4][4], to_imat[4][4];
+
+ if (!target_psmd->mesh_final)
+ return false;
+ if (!psys->part || psys->part->type != PART_HAIR)
+ return false;
+ if (!target_psys->part || target_psys->part->type != PART_HAIR)
+ return false;
+
+ edit_point = target_edit ? target_edit->points : NULL;
+
+ invert_m4_m4(from_ob_imat, ob->obmat);
+ invert_m4_m4(to_ob_imat, target_ob->obmat);
+ invert_m4_m4(from_imat, from_mat);
+ invert_m4_m4(to_imat, to_mat);
+
+ if (target_psmd->mesh_final->runtime.deformed_only) {
+ /* we don't want to mess up target_psmd->dm when converting to global coordinates below */
+ mesh = target_psmd->mesh_final;
+ }
+ else {
+ mesh = target_psmd->mesh_original;
+ }
+ target_mesh = target_psmd->mesh_final;
+ if (mesh == NULL) {
+ return false;
+ }
+ /* don't modify the original vertices */
+ BKE_id_copy_ex(NULL, &mesh->id, (ID **)&mesh, LIB_ID_COPY_LOCALIZE);
+
+ /* BMESH_ONLY, deform dm may not have tessface */
+ BKE_mesh_tessface_ensure(mesh);
+
+ numverts = mesh->totvert;
+ mvert = mesh->mvert;
+
+ /* convert to global coordinates */
+ for (i = 0; i < numverts; i++)
+ mul_m4_v3(to_mat, mvert[i].co);
+
+ if (mesh->totface != 0) {
+ mface = mesh->mface;
+ BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_FACES, 2);
+ }
+ else if (mesh->totedge != 0) {
+ medge = mesh->medge;
+ BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_EDGES, 2);
+ }
+ else {
+ BKE_id_free(NULL, mesh);
+ return false;
+ }
+
+ for (i = 0, tpa = target_psys->particles, pa = psys->particles; i < target_psys->totpart;
+ i++, tpa++, pa++) {
+ float from_co[3];
+ BVHTreeNearest nearest;
+
+ if (from_global)
+ mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].co);
+ else
+ mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].world_co);
+ mul_m4_v3(from_mat, from_co);
+
+ nearest.index = -1;
+ nearest.dist_sq = FLT_MAX;
+
+ BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
+
+ if (nearest.index == -1) {
+ if (G.debug & G_DEBUG)
+ printf("No nearest point found for hair root!");
+ continue;
+ }
+
+ if (mface) {
+ float v[4][3];
+
+ mf = &mface[nearest.index];
+
+ copy_v3_v3(v[0], mvert[mf->v1].co);
+ copy_v3_v3(v[1], mvert[mf->v2].co);
+ copy_v3_v3(v[2], mvert[mf->v3].co);
+ if (mf->v4) {
+ copy_v3_v3(v[3], mvert[mf->v4].co);
+ interp_weights_poly_v3(tpa->fuv, v, 4, nearest.co);
+ }
+ else
+ interp_weights_poly_v3(tpa->fuv, v, 3, nearest.co);
+ tpa->foffset = 0.0f;
+
+ tpa->num = nearest.index;
+ tpa->num_dmcache = psys_particle_dm_face_lookup(target_mesh, mesh, tpa->num, tpa->fuv, NULL);
+ }
+ else {
+ me = &medge[nearest.index];
+
+ tpa->fuv[1] = line_point_factor_v3(nearest.co, mvert[me->v1].co, mvert[me->v2].co);
+ tpa->fuv[0] = 1.0f - tpa->fuv[1];
+ tpa->fuv[2] = tpa->fuv[3] = 0.0f;
+ tpa->foffset = 0.0f;
+
+ tpa->num = nearest.index;
+ tpa->num_dmcache = -1;
+ }
+
+ /* translate hair keys */
+ {
+ HairKey *key, *tkey;
+ float hairmat[4][4], imat[4][4];
+ float offset[3];
+
+ if (to_global)
+ copy_m4_m4(imat, target_ob->obmat);
+ else {
+ /* note: using target_dm here, which is in target_ob object space and has full modifiers */
+ psys_mat_hair_to_object(target_ob, target_mesh, target_psys->part->from, tpa, hairmat);
+ invert_m4_m4(imat, hairmat);
+ }
+ mul_m4_m4m4(imat, imat, to_imat);
+
+ /* offset in world space */
+ sub_v3_v3v3(offset, nearest.co, from_co);
+
+ if (edit_point) {
+ for (k = 0, key = pa->hair, tkey = tpa->hair, ekey = edit_point->keys; k < tpa->totkey;
+ k++, key++, tkey++, ekey++) {
+ float co_orig[3];
+
+ if (from_global)
+ mul_v3_m4v3(co_orig, from_ob_imat, key->co);
+ else
+ mul_v3_m4v3(co_orig, from_ob_imat, key->world_co);
+ mul_m4_v3(from_mat, co_orig);
+
+ add_v3_v3v3(tkey->co, co_orig, offset);
+
+ mul_m4_v3(imat, tkey->co);
+
+ ekey->flag |= PEK_USE_WCO;
+ }
+
+ edit_point++;
+ }
+ else {
+ for (k = 0, key = pa->hair, tkey = tpa->hair; k < tpa->totkey; k++, key++, tkey++) {
+ float co_orig[3];
+
+ if (from_global)
+ mul_v3_m4v3(co_orig, from_ob_imat, key->co);
+ else
+ mul_v3_m4v3(co_orig, from_ob_imat, key->world_co);
+ mul_m4_v3(from_mat, co_orig);
+
+ add_v3_v3v3(tkey->co, co_orig, offset);
+
+ mul_m4_v3(imat, tkey->co);
+ }
+ }
+ }
+ }
+
+ free_bvhtree_from_mesh(&bvhtree);
+ BKE_id_free(NULL, mesh);
+
+ psys_free_path_cache(target_psys, target_edit);
+
+ PE_update_object(depsgraph, scene, target_ob, 0);
+
+ return true;
}
-static bool connect_hair(
- Depsgraph *depsgraph, Scene *scene,
- Object *ob, ParticleSystem *psys)
+static bool connect_hair(Depsgraph *depsgraph, Scene *scene, Object *ob, ParticleSystem *psys)
{
- bool ok;
-
- if (!psys)
- return false;
-
- ok = remap_hair_emitter(
- depsgraph, scene, ob, psys, ob, psys, psys->edit,
- ob->obmat, ob->obmat, psys->flag & PSYS_GLOBAL_HAIR, false);
- psys->flag &= ~PSYS_GLOBAL_HAIR;
-
- return ok;
+ bool ok;
+
+ if (!psys)
+ return false;
+
+ ok = remap_hair_emitter(depsgraph,
+ scene,
+ ob,
+ psys,
+ ob,
+ psys,
+ psys->edit,
+ ob->obmat,
+ ob->obmat,
+ psys->flag & PSYS_GLOBAL_HAIR,
+ false);
+ psys->flag &= ~PSYS_GLOBAL_HAIR;
+
+ return ok;
}
static int connect_hair_exec(bContext *C, wmOperator *op)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_context(C);
- ParticleSystem *psys = NULL;
- const bool all = RNA_boolean_get(op->ptr, "all");
- bool any_connected = false;
-
- if (!ob)
- return OPERATOR_CANCELLED;
-
- if (all) {
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- any_connected |= connect_hair(depsgraph, scene, ob, psys);
- }
- }
- else {
- psys = psys_get_current(ob);
- any_connected |= connect_hair(depsgraph, scene, ob, psys);
- }
-
- if (!any_connected) {
- BKE_report(op->reports, RPT_WARNING,
- "No hair connected (can't connect hair if particle system modifier is disabled)");
- return OPERATOR_CANCELLED;
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
-
- return OPERATOR_FINISHED;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_context(C);
+ ParticleSystem *psys = NULL;
+ const bool all = RNA_boolean_get(op->ptr, "all");
+ bool any_connected = false;
+
+ if (!ob)
+ return OPERATOR_CANCELLED;
+
+ if (all) {
+ for (psys = ob->particlesystem.first; psys; psys = psys->next) {
+ any_connected |= connect_hair(depsgraph, scene, ob, psys);
+ }
+ }
+ else {
+ psys = psys_get_current(ob);
+ any_connected |= connect_hair(depsgraph, scene, ob, psys);
+ }
+
+ if (!any_connected) {
+ BKE_report(op->reports,
+ RPT_WARNING,
+ "No hair connected (can't connect hair if particle system modifier is disabled)");
+ return OPERATOR_CANCELLED;
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
+
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_connect_hair(wmOperatorType *ot)
{
- ot->name = "Connect Hair";
- ot->description = "Connect hair to the emitter mesh";
- ot->idname = "PARTICLE_OT_connect_hair";
+ ot->name = "Connect Hair";
+ ot->description = "Connect hair to the emitter mesh";
+ ot->idname = "PARTICLE_OT_connect_hair";
- ot->exec = connect_hair_exec;
+ ot->exec = connect_hair_exec;
- /* flags */
- /* No REGISTER, redo does not work due to missing update, see T47750. */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ /* No REGISTER, redo does not work due to missing update, see T47750. */
+ ot->flag = OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "all", 0, "All hair", "Connect all hair systems to the emitter mesh");
+ RNA_def_boolean(ot->srna, "all", 0, "All hair", "Connect all hair systems to the emitter mesh");
}
/************************ particle system copy operator *********************/
typedef enum eCopyParticlesSpace {
- PAR_COPY_SPACE_OBJECT = 0,
- PAR_COPY_SPACE_WORLD = 1,
+ PAR_COPY_SPACE_OBJECT = 0,
+ PAR_COPY_SPACE_WORLD = 1,
} eCopyParticlesSpace;
-static void copy_particle_edit(
- Depsgraph *depsgraph, Scene *scene,
- Object *ob, ParticleSystem *psys, ParticleSystem *psys_from)
+static void copy_particle_edit(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ ParticleSystem *psys,
+ ParticleSystem *psys_from)
{
- PTCacheEdit *edit_from = psys_from->edit, *edit;
- ParticleData *pa;
- KEY_K;
- POINT_P;
-
- if (!edit_from)
- return;
-
- edit = MEM_dupallocN(edit_from);
- edit->psys = psys;
- psys->edit = edit;
-
- edit->pathcache = NULL;
- BLI_listbase_clear(&edit->pathcachebufs);
-
- edit->emitter_field = NULL;
- edit->emitter_cosnos = NULL;
-
- edit->points = MEM_dupallocN(edit_from->points);
- pa = psys->particles;
- LOOP_POINTS {
- HairKey *hkey = pa->hair;
-
- point->keys = MEM_dupallocN(point->keys);
- LOOP_KEYS {
- key->co = hkey->co;
- key->time = &hkey->time;
- key->flag = hkey->editflag;
- if (!(psys->flag & PSYS_GLOBAL_HAIR)) {
- key->flag |= PEK_USE_WCO;
- hkey->editflag |= PEK_USE_WCO;
- }
-
- hkey++;
- }
-
- pa++;
- }
- update_world_cos(depsgraph, 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);
+ PTCacheEdit *edit_from = psys_from->edit, *edit;
+ ParticleData *pa;
+ KEY_K;
+ POINT_P;
+
+ if (!edit_from)
+ return;
+
+ edit = MEM_dupallocN(edit_from);
+ edit->psys = psys;
+ psys->edit = edit;
+
+ edit->pathcache = NULL;
+ BLI_listbase_clear(&edit->pathcachebufs);
+
+ edit->emitter_field = NULL;
+ edit->emitter_cosnos = NULL;
+
+ edit->points = MEM_dupallocN(edit_from->points);
+ pa = psys->particles;
+ LOOP_POINTS
+ {
+ HairKey *hkey = pa->hair;
+
+ point->keys = MEM_dupallocN(point->keys);
+ LOOP_KEYS
+ {
+ key->co = hkey->co;
+ key->time = &hkey->time;
+ key->flag = hkey->editflag;
+ if (!(psys->flag & PSYS_GLOBAL_HAIR)) {
+ key->flag |= PEK_USE_WCO;
+ hkey->editflag |= PEK_USE_WCO;
+ }
+
+ hkey++;
+ }
+
+ pa++;
+ }
+ update_world_cos(depsgraph, 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);
}
static void remove_particle_systems_from_object(Object *ob_to)
{
- ModifierData *md, *md_next;
-
- if (ob_to->type != OB_MESH)
- return;
- if (!ob_to->data || ID_IS_LINKED(ob_to->data))
- return;
-
- for (md = ob_to->modifiers.first; md; md = md_next) {
- md_next = md->next;
-
- /* remove all particle system modifiers as well,
- * these need to sync to the particle system list
- */
- if (ELEM(md->type, eModifierType_ParticleSystem, eModifierType_DynamicPaint, eModifierType_Smoke)) {
- BLI_remlink(&ob_to->modifiers, md);
- modifier_free(md);
- }
- }
-
- BKE_object_free_particlesystems(ob_to);
+ ModifierData *md, *md_next;
+
+ if (ob_to->type != OB_MESH)
+ return;
+ if (!ob_to->data || ID_IS_LINKED(ob_to->data))
+ return;
+
+ for (md = ob_to->modifiers.first; md; md = md_next) {
+ md_next = md->next;
+
+ /* remove all particle system modifiers as well,
+ * these need to sync to the particle system list
+ */
+ if (ELEM(md->type,
+ eModifierType_ParticleSystem,
+ eModifierType_DynamicPaint,
+ eModifierType_Smoke)) {
+ BLI_remlink(&ob_to->modifiers, md);
+ modifier_free(md);
+ }
+ }
+
+ BKE_object_free_particlesystems(ob_to);
}
/* single_psys_from is optional, if NULL all psys of ob_from are copied */
@@ -1031,245 +1045,265 @@ static bool copy_particle_systems_to_object(const bContext *C,
int space,
bool duplicate_settings)
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ModifierData *md;
- ParticleSystem *psys_start = NULL, *psys, *psys_from;
- ParticleSystem **tmp_psys;
- Mesh *final_mesh;
- CustomData_MeshMasks cdmask = {0};
- int i, totpsys;
-
- if (ob_to->type != OB_MESH)
- return false;
- if (!ob_to->data || ID_IS_LINKED(ob_to->data))
- return false;
-
- /* For remapping we need a valid DM.
- * Because the modifiers are appended at the end it's safe to use
- * the final DM of the object without particles.
- * However, when evaluating the DM all the particle modifiers must be valid,
- * i.e. have the psys assigned already.
- * To break this hen/egg problem we create all psys separately first (to collect required customdata masks),
- * then create the DM, then add them to the object and make the psys modifiers ...
- */
- #define PSYS_FROM_FIRST (single_psys_from ? single_psys_from : ob_from->particlesystem.first)
- #define PSYS_FROM_NEXT(cur) (single_psys_from ? NULL : (cur)->next)
- totpsys = single_psys_from ? 1 : BLI_listbase_count(&ob_from->particlesystem);
-
- tmp_psys = MEM_mallocN(sizeof(ParticleSystem *) * totpsys, "temporary particle system array");
-
- for (psys_from = PSYS_FROM_FIRST, i = 0;
- psys_from;
- psys_from = PSYS_FROM_NEXT(psys_from), ++i)
- {
- psys = BKE_object_copy_particlesystem(psys_from, 0);
- tmp_psys[i] = psys;
-
- if (psys_start == NULL)
- psys_start = psys;
-
- psys_emitter_customdata_mask(psys, &cdmask);
- }
- /* to iterate source and target psys in sync,
- * we need to know where the newly added psys start
- */
- psys_start = totpsys > 0 ? tmp_psys[0] : NULL;
-
- /* Get the evaluated mesh (psys and their modifiers have not been appended yet) */
- final_mesh = mesh_get_eval_final(depsgraph, scene, ob_to, &cdmask);
-
- /* now append psys to the object and make modifiers */
- for (i = 0, psys_from = PSYS_FROM_FIRST;
- i < totpsys;
- ++i, psys_from = PSYS_FROM_NEXT(psys_from))
- {
- ParticleSystemModifierData *psmd;
-
- psys = tmp_psys[i];
-
- /* append to the object */
- BLI_addtail(&ob_to->particlesystem, psys);
-
- /* add a particle system modifier for each system */
- md = 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);
-
- psmd->psys = psys;
- BKE_id_copy_ex(NULL, &final_mesh->id, (ID **)&psmd->mesh_final, LIB_ID_COPY_LOCALIZE);
-
- BKE_mesh_calc_normals(psmd->mesh_final);
- BKE_mesh_tessface_ensure(psmd->mesh_final);
-
- if (psys_from->edit) {
- copy_particle_edit(depsgraph, scene, ob_to, psys, psys_from);
- }
-
- if (duplicate_settings) {
- id_us_min(&psys->part->id);
- psys->part = BKE_particlesettings_copy(bmain, psys->part);
- }
- }
- MEM_freeN(tmp_psys);
-
- /* note: do this after creating DM copies for all the particle system modifiers,
- * the remapping otherwise makes final_dm invalid!
- */
- for (psys = psys_start, psys_from = PSYS_FROM_FIRST, i = 0;
- psys;
- psys = psys->next, psys_from = PSYS_FROM_NEXT(psys_from), ++i)
- {
- float(*from_mat)[4], (*to_mat)[4];
-
- switch (space) {
- case PAR_COPY_SPACE_OBJECT:
- from_mat = I;
- to_mat = I;
- break;
- case PAR_COPY_SPACE_WORLD:
- from_mat = ob_from->obmat;
- to_mat = ob_to->obmat;
- break;
- default:
- /* should not happen */
- from_mat = to_mat = NULL;
- BLI_assert(false);
- break;
- }
- if (ob_from != ob_to) {
- remap_hair_emitter(
- depsgraph, scene, ob_from, psys_from, ob_to, psys, psys->edit,
- from_mat, to_mat, psys_from->flag & PSYS_GLOBAL_HAIR, psys->flag & PSYS_GLOBAL_HAIR);
- }
-
- /* tag for recalc */
-// psys->recalc |= ID_RECALC_PSYS_RESET;
- }
-
- #undef PSYS_FROM_FIRST
- #undef PSYS_FROM_NEXT
-
- DEG_id_tag_update(&ob_to->id, ID_RECALC_GEOMETRY);
- WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, ob_to);
- return true;
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ModifierData *md;
+ ParticleSystem *psys_start = NULL, *psys, *psys_from;
+ ParticleSystem **tmp_psys;
+ Mesh *final_mesh;
+ CustomData_MeshMasks cdmask = {0};
+ int i, totpsys;
+
+ if (ob_to->type != OB_MESH)
+ return false;
+ if (!ob_to->data || ID_IS_LINKED(ob_to->data))
+ return false;
+
+/* For remapping we need a valid DM.
+ * Because the modifiers are appended at the end it's safe to use
+ * the final DM of the object without particles.
+ * However, when evaluating the DM all the particle modifiers must be valid,
+ * i.e. have the psys assigned already.
+ * To break this hen/egg problem we create all psys separately first (to collect required customdata masks),
+ * then create the DM, then add them to the object and make the psys modifiers ...
+ */
+#define PSYS_FROM_FIRST (single_psys_from ? single_psys_from : ob_from->particlesystem.first)
+#define PSYS_FROM_NEXT(cur) (single_psys_from ? NULL : (cur)->next)
+ totpsys = single_psys_from ? 1 : BLI_listbase_count(&ob_from->particlesystem);
+
+ tmp_psys = MEM_mallocN(sizeof(ParticleSystem *) * totpsys, "temporary particle system array");
+
+ for (psys_from = PSYS_FROM_FIRST, i = 0; psys_from; psys_from = PSYS_FROM_NEXT(psys_from), ++i) {
+ psys = BKE_object_copy_particlesystem(psys_from, 0);
+ tmp_psys[i] = psys;
+
+ if (psys_start == NULL)
+ psys_start = psys;
+
+ psys_emitter_customdata_mask(psys, &cdmask);
+ }
+ /* to iterate source and target psys in sync,
+ * we need to know where the newly added psys start
+ */
+ psys_start = totpsys > 0 ? tmp_psys[0] : NULL;
+
+ /* Get the evaluated mesh (psys and their modifiers have not been appended yet) */
+ final_mesh = mesh_get_eval_final(depsgraph, scene, ob_to, &cdmask);
+
+ /* now append psys to the object and make modifiers */
+ for (i = 0, psys_from = PSYS_FROM_FIRST; i < totpsys;
+ ++i, psys_from = PSYS_FROM_NEXT(psys_from)) {
+ ParticleSystemModifierData *psmd;
+
+ psys = tmp_psys[i];
+
+ /* append to the object */
+ BLI_addtail(&ob_to->particlesystem, psys);
+
+ /* add a particle system modifier for each system */
+ md = 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);
+
+ psmd->psys = psys;
+ BKE_id_copy_ex(NULL, &final_mesh->id, (ID **)&psmd->mesh_final, LIB_ID_COPY_LOCALIZE);
+
+ BKE_mesh_calc_normals(psmd->mesh_final);
+ BKE_mesh_tessface_ensure(psmd->mesh_final);
+
+ if (psys_from->edit) {
+ copy_particle_edit(depsgraph, scene, ob_to, psys, psys_from);
+ }
+
+ if (duplicate_settings) {
+ id_us_min(&psys->part->id);
+ psys->part = BKE_particlesettings_copy(bmain, psys->part);
+ }
+ }
+ MEM_freeN(tmp_psys);
+
+ /* note: do this after creating DM copies for all the particle system modifiers,
+ * the remapping otherwise makes final_dm invalid!
+ */
+ for (psys = psys_start, psys_from = PSYS_FROM_FIRST, i = 0; psys;
+ psys = psys->next, psys_from = PSYS_FROM_NEXT(psys_from), ++i) {
+ float(*from_mat)[4], (*to_mat)[4];
+
+ switch (space) {
+ case PAR_COPY_SPACE_OBJECT:
+ from_mat = I;
+ to_mat = I;
+ break;
+ case PAR_COPY_SPACE_WORLD:
+ from_mat = ob_from->obmat;
+ to_mat = ob_to->obmat;
+ break;
+ default:
+ /* should not happen */
+ from_mat = to_mat = NULL;
+ BLI_assert(false);
+ break;
+ }
+ if (ob_from != ob_to) {
+ remap_hair_emitter(depsgraph,
+ scene,
+ ob_from,
+ psys_from,
+ ob_to,
+ psys,
+ psys->edit,
+ from_mat,
+ to_mat,
+ psys_from->flag & PSYS_GLOBAL_HAIR,
+ psys->flag & PSYS_GLOBAL_HAIR);
+ }
+
+ /* tag for recalc */
+ // psys->recalc |= ID_RECALC_PSYS_RESET;
+ }
+
+#undef PSYS_FROM_FIRST
+#undef PSYS_FROM_NEXT
+
+ DEG_id_tag_update(&ob_to->id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, ob_to);
+ return true;
}
static bool copy_particle_systems_poll(bContext *C)
{
- Object *ob;
- if (!ED_operator_object_active_editable(C))
- return false;
+ Object *ob;
+ if (!ED_operator_object_active_editable(C))
+ return false;
- ob = ED_object_active_context(C);
- if (BLI_listbase_is_empty(&ob->particlesystem))
- return false;
+ ob = ED_object_active_context(C);
+ if (BLI_listbase_is_empty(&ob->particlesystem))
+ return false;
- return true;
+ return true;
}
static int copy_particle_systems_exec(bContext *C, wmOperator *op)
{
- const int space = RNA_enum_get(op->ptr, "space");
- const bool remove_target_particles = RNA_boolean_get(op->ptr, "remove_target_particles");
- const bool use_active = RNA_boolean_get(op->ptr, "use_active");
- Scene *scene = CTX_data_scene(C);
- Object *ob_from = ED_object_active_context(C);
- ParticleSystem *psys_from = use_active ? CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data : NULL;
-
- int changed_tot = 0;
- int fail = 0;
-
- CTX_DATA_BEGIN (C, Object *, ob_to, selected_editable_objects)
- {
- if (ob_from != ob_to) {
- bool changed = false;
- if (remove_target_particles) {
- remove_particle_systems_from_object(ob_to);
- changed = true;
- }
- if (copy_particle_systems_to_object(C, scene, ob_from, psys_from, ob_to, space, false))
- changed = true;
- else
- fail++;
-
- if (changed)
- changed_tot++;
- }
- }
- CTX_DATA_END;
-
- if ((changed_tot == 0 && fail == 0) || fail) {
- BKE_reportf(op->reports, RPT_ERROR,
- "Copy particle systems to selected: %d done, %d failed",
- changed_tot, fail);
- }
-
- return OPERATOR_FINISHED;
+ const int space = RNA_enum_get(op->ptr, "space");
+ const bool remove_target_particles = RNA_boolean_get(op->ptr, "remove_target_particles");
+ const bool use_active = RNA_boolean_get(op->ptr, "use_active");
+ Scene *scene = CTX_data_scene(C);
+ Object *ob_from = ED_object_active_context(C);
+ ParticleSystem *psys_from =
+ use_active ? CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data :
+ NULL;
+
+ int changed_tot = 0;
+ int fail = 0;
+
+ CTX_DATA_BEGIN (C, Object *, ob_to, selected_editable_objects) {
+ if (ob_from != ob_to) {
+ bool changed = false;
+ if (remove_target_particles) {
+ remove_particle_systems_from_object(ob_to);
+ changed = true;
+ }
+ if (copy_particle_systems_to_object(C, scene, ob_from, psys_from, ob_to, space, false))
+ changed = true;
+ else
+ fail++;
+
+ if (changed)
+ changed_tot++;
+ }
+ }
+ CTX_DATA_END;
+
+ if ((changed_tot == 0 && fail == 0) || fail) {
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "Copy particle systems to selected: %d done, %d failed",
+ changed_tot,
+ fail);
+ }
+
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_copy_particle_systems(wmOperatorType *ot)
{
- static const EnumPropertyItem space_items[] = {
- {PAR_COPY_SPACE_OBJECT, "OBJECT", 0, "Object", "Copy inside each object's local space"},
- {PAR_COPY_SPACE_WORLD, "WORLD", 0, "World", "Copy in world space"},
- {0, NULL, 0, NULL, NULL},
- };
-
- ot->name = "Copy Particle Systems";
- ot->description = "Copy particle systems from the active object to selected objects";
- ot->idname = "PARTICLE_OT_copy_particle_systems";
-
- ot->poll = copy_particle_systems_poll;
- ot->exec = copy_particle_systems_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "space", space_items, PAR_COPY_SPACE_OBJECT, "Space", "Space transform for copying from one object to another");
- RNA_def_boolean(ot->srna, "remove_target_particles", true, "Remove Target Particles", "Remove particle systems on the target objects");
- RNA_def_boolean(ot->srna, "use_active", false, "Use Active", "Use the active particle system from the context");
+ static const EnumPropertyItem space_items[] = {
+ {PAR_COPY_SPACE_OBJECT, "OBJECT", 0, "Object", "Copy inside each object's local space"},
+ {PAR_COPY_SPACE_WORLD, "WORLD", 0, "World", "Copy in world space"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ ot->name = "Copy Particle Systems";
+ ot->description = "Copy particle systems from the active object to selected objects";
+ ot->idname = "PARTICLE_OT_copy_particle_systems";
+
+ ot->poll = copy_particle_systems_poll;
+ ot->exec = copy_particle_systems_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna,
+ "space",
+ space_items,
+ PAR_COPY_SPACE_OBJECT,
+ "Space",
+ "Space transform for copying from one object to another");
+ RNA_def_boolean(ot->srna,
+ "remove_target_particles",
+ true,
+ "Remove Target Particles",
+ "Remove particle systems on the target objects");
+ RNA_def_boolean(ot->srna,
+ "use_active",
+ false,
+ "Use Active",
+ "Use the active particle system from the context");
}
static bool duplicate_particle_systems_poll(bContext *C)
{
- if (!ED_operator_object_active_editable(C)) {
- return false;
- }
- Object *ob = ED_object_active_context(C);
- if (BLI_listbase_is_empty(&ob->particlesystem)) {
- return false;
- }
- return true;
+ if (!ED_operator_object_active_editable(C)) {
+ return false;
+ }
+ Object *ob = ED_object_active_context(C);
+ if (BLI_listbase_is_empty(&ob->particlesystem)) {
+ return false;
+ }
+ return true;
}
static int duplicate_particle_systems_exec(bContext *C, wmOperator *op)
{
- const bool duplicate_settings = RNA_boolean_get(op->ptr, "use_duplicate_settings");
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- ParticleSystem *psys = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data;
- copy_particle_systems_to_object(C, scene, ob, psys, ob,
- PAR_COPY_SPACE_OBJECT, duplicate_settings);
- return OPERATOR_FINISHED;
+ const bool duplicate_settings = RNA_boolean_get(op->ptr, "use_duplicate_settings");
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ ParticleSystem *psys = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data;
+ copy_particle_systems_to_object(
+ C, scene, ob, psys, ob, PAR_COPY_SPACE_OBJECT, duplicate_settings);
+ return OPERATOR_FINISHED;
}
void PARTICLE_OT_duplicate_particle_system(wmOperatorType *ot)
{
- ot->name = "Duplicate Particle System";
- ot->description = "Duplicate particle system within the active object";
- ot->idname = "PARTICLE_OT_duplicate_particle_system";
+ ot->name = "Duplicate Particle System";
+ ot->description = "Duplicate particle system within the active object";
+ ot->idname = "PARTICLE_OT_duplicate_particle_system";
- ot->poll = duplicate_particle_systems_poll;
- ot->exec = duplicate_particle_systems_exec;
+ ot->poll = duplicate_particle_systems_poll;
+ ot->exec = duplicate_particle_systems_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "use_duplicate_settings", false, "Duplicate Settings",
- "Duplicate settings as well, so the new particle system uses its own settings");
+ RNA_def_boolean(ot->srna,
+ "use_duplicate_settings",
+ false,
+ "Duplicate Settings",
+ "Duplicate settings as well, so the new particle system uses its own settings");
}
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index d3b57a09a9e..2769d1a9dc3 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -50,156 +50,153 @@
#include "WM_types.h"
#include "WM_api.h"
-#include "physics_intern.h" // own include
+#include "physics_intern.h" // own include
/* enable/disable overall compilation */
#ifdef WITH_MOD_FLUID
-#include "LBM_fluidsim.h"
+# include "LBM_fluidsim.h"
-#include "BLI_blenlib.h"
-#include "BLI_path_util.h"
-#include "BLI_math.h"
+# include "BLI_blenlib.h"
+# include "BLI_path_util.h"
+# include "BLI_math.h"
-#include "BKE_global.h"
-#include "BKE_main.h"
+# include "BKE_global.h"
+# include "BKE_main.h"
-#include "WM_api.h"
-
-#include "DNA_scene_types.h"
-#include "DNA_mesh_types.h"
+# include "WM_api.h"
+# include "DNA_scene_types.h"
+# include "DNA_mesh_types.h"
static float get_fluid_viscosity(FluidsimSettings *settings)
{
- return (1.0f/powf(10.0f, settings->viscosityExponent)) * settings->viscosityValue;
+ return (1.0f / powf(10.0f, settings->viscosityExponent)) * settings->viscosityValue;
}
static float get_fluid_rate(FluidsimSettings *settings)
{
- float rate = 1.0f; /* default rate if not animated... */
+ float rate = 1.0f; /* default rate if not animated... */
- rate = settings->animRate;
+ rate = settings->animRate;
- if (rate < 0.0f)
- rate = 0.0f;
+ if (rate < 0.0f)
+ rate = 0.0f;
- return rate;
+ return rate;
}
static void get_fluid_gravity(float *gravity, Scene *scene, FluidsimSettings *fss)
{
- if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
- copy_v3_v3(gravity, scene->physics_settings.gravity);
- }
- else {
- copy_v3_v3(gravity, fss->grav);
- }
+ if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
+ copy_v3_v3(gravity, scene->physics_settings.gravity);
+ }
+ else {
+ copy_v3_v3(gravity, fss->grav);
+ }
}
static float get_fluid_size_m(Scene *scene, Object *domainob, FluidsimSettings *fss)
{
- if (!scene->unit.system) {
- return fss->realsize;
- }
- else {
- float dim[3];
- float longest_axis;
-
- BKE_object_dimensions_get(domainob, dim);
- longest_axis = max_fff(dim[0], dim[1], dim[2]);
-
- return longest_axis * scene->unit.scale_length;
- }
+ if (!scene->unit.system) {
+ return fss->realsize;
+ }
+ else {
+ float dim[3];
+ float longest_axis;
+
+ BKE_object_dimensions_get(domainob, dim);
+ longest_axis = max_fff(dim[0], dim[1], dim[2]);
+
+ return longest_axis * scene->unit.scale_length;
+ }
}
static bool fluid_is_animated_mesh(FluidsimSettings *fss)
{
- return ((fss->type == OB_FLUIDSIM_CONTROL) || fss->domainNovecgen);
+ return ((fss->type == OB_FLUIDSIM_CONTROL) || fss->domainNovecgen);
}
/* ********************** fluid sim settings struct functions ********************** */
-#if 0
+# if 0
/* helper function */
void fluidsimGetGeometryObjFilename(Object *ob, char *dst) //, char *srcname)
{
- //BLI_snprintf(dst, FILE_MAXFILE, "%s_cfgdata_%s.bobj.gz", srcname, ob->id.name);
- BLI_snprintf(dst, FILE_MAXFILE, "fluidcfgdata_%s.bobj.gz", ob->id.name);
+ //BLI_snprintf(dst, FILE_MAXFILE, "%s_cfgdata_%s.bobj.gz", srcname, ob->id.name);
+ BLI_snprintf(dst, FILE_MAXFILE, "fluidcfgdata_%s.bobj.gz", ob->id.name);
}
-#endif
-
+# endif
/* ********************** fluid sim channel helper functions ********************** */
typedef struct FluidAnimChannels {
- int length;
+ int length;
- double aniFrameTime;
+ double aniFrameTime;
- float *timeAtFrame;
- float *DomainTime;
- float *DomainGravity;
- float *DomainViscosity;
+ float *timeAtFrame;
+ float *DomainTime;
+ float *DomainGravity;
+ float *DomainViscosity;
} FluidAnimChannels;
typedef struct FluidObject {
- struct FluidObject *next, *prev;
+ struct FluidObject *next, *prev;
- struct Object *object;
+ struct Object *object;
- float *Translation;
- float *Rotation;
- float *Scale;
- float *Active;
+ float *Translation;
+ float *Rotation;
+ float *Scale;
+ float *Active;
- float *InitialVelocity;
+ float *InitialVelocity;
- float *AttractforceStrength;
- float *AttractforceRadius;
- float *VelocityforceStrength;
- float *VelocityforceRadius;
+ float *AttractforceStrength;
+ float *AttractforceRadius;
+ float *VelocityforceStrength;
+ float *VelocityforceRadius;
- float *VertexCache;
- int numVerts, numTris;
+ float *VertexCache;
+ int numVerts, numTris;
} FluidObject;
// no. of entries for the two channel sizes
-#define CHANNEL_FLOAT 1
-#define CHANNEL_VEC 3
+# define CHANNEL_FLOAT 1
+# define CHANNEL_VEC 3
// simplify channels before printing
// for API this is done anyway upon init
-#if 0
+# if 0
static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char *str, int entries)
{
- int i, j;
- int channelSize = paramsize;
-
- if (entries == 3) {
- elbeemSimplifyChannelVec3(channel, &channelSize);
- }
- else if (entries == 1) {
- elbeemSimplifyChannelFloat(channel, &channelSize);
- }
- else {
- /* invalid, cant happen? */
- }
-
- fprintf(file, " CHANNEL %s =\n", str);
- for (i=0; i < channelSize; i++) {
- fprintf(file, " ");
- for (j=0;j <= entries;j++) { // also print time value
- fprintf(file, " %f ", channel[i*(entries + 1) + j]);
- if (j == entries-1) { fprintf(file, " "); }
- }
- fprintf(file, "\n");
- }
-
- fprintf(file, " ;\n");
+ int i, j;
+ int channelSize = paramsize;
+
+ if (entries == 3) {
+ elbeemSimplifyChannelVec3(channel, &channelSize);
+ }
+ else if (entries == 1) {
+ elbeemSimplifyChannelFloat(channel, &channelSize);
+ }
+ else {
+ /* invalid, cant happen? */
+ }
+
+ fprintf(file, " CHANNEL %s =\n", str);
+ for (i=0; i < channelSize; i++) {
+ fprintf(file, " ");
+ for (j=0;j <= entries;j++) { // also print time value
+ fprintf(file, " %f ", channel[i*(entries + 1) + j]);
+ if (j == entries-1) { fprintf(file, " "); }
+ }
+ fprintf(file, "\n");
+ }
+
+ fprintf(file, " ;\n");
}
-#endif
-
+# endif
/* Note: fluid anim channel data layout
* ------------------------------------
@@ -214,472 +211,534 @@ static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char
static void init_time(FluidsimSettings *domainSettings, FluidAnimChannels *channels)
{
- int i;
+ int i;
- channels->timeAtFrame = MEM_callocN((channels->length + 1) * sizeof(float), "timeAtFrame channel");
+ channels->timeAtFrame = MEM_callocN((channels->length + 1) * sizeof(float),
+ "timeAtFrame channel");
- channels->timeAtFrame[0] = channels->timeAtFrame[1] = domainSettings->animStart; // start at index 1
+ channels->timeAtFrame[0] = channels->timeAtFrame[1] =
+ domainSettings->animStart; // start at index 1
- for (i=2; i <= channels->length; i++) {
- channels->timeAtFrame[i] = channels->timeAtFrame[i - 1] + (float)channels->aniFrameTime;
- }
+ for (i = 2; i <= channels->length; i++) {
+ channels->timeAtFrame[i] = channels->timeAtFrame[i - 1] + (float)channels->aniFrameTime;
+ }
}
/* if this is slow, can replace with faster, less readable code */
static void set_channel(float *channel, float time, float *value, int i, int size)
{
- if (size == CHANNEL_FLOAT) {
- channel[(i * 2) + 0] = value[0];
- channel[(i * 2) + 1] = time;
- }
- else if (size == CHANNEL_VEC) {
- channel[(i * 4) + 0] = value[0];
- channel[(i * 4) + 1] = value[1];
- channel[(i * 4) + 2] = value[2];
- channel[(i * 4) + 3] = time;
- }
+ if (size == CHANNEL_FLOAT) {
+ channel[(i * 2) + 0] = value[0];
+ channel[(i * 2) + 1] = time;
+ }
+ else if (size == CHANNEL_VEC) {
+ channel[(i * 4) + 0] = value[0];
+ channel[(i * 4) + 1] = value[1];
+ channel[(i * 4) + 2] = value[2];
+ channel[(i * 4) + 3] = time;
+ }
}
-static void set_vertex_channel(Depsgraph *depsgraph, float *channel, float time, struct Scene *scene, struct FluidObject *fobj, int i)
+static void set_vertex_channel(Depsgraph *depsgraph,
+ float *channel,
+ float time,
+ struct Scene *scene,
+ struct FluidObject *fobj,
+ int i)
{
- Object *ob = fobj->object;
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
- float *verts;
- int *tris=NULL, numVerts=0, numTris=0;
- int modifierIndex = BLI_findindex(&ob->modifiers, fluidmd);
- int framesize = (3*fobj->numVerts) + 1;
- int j;
-
- if (channel == NULL)
- return;
-
- initElbeemMesh(depsgraph, scene, ob, &numVerts, &verts, &numTris, &tris, 1, modifierIndex);
-
- /* don't allow mesh to change number of verts in anim sequence */
- if (numVerts != fobj->numVerts) {
- MEM_freeN(channel);
- channel = NULL;
- return;
- }
-
- /* fill frame of channel with vertex locations */
- for (j=0; j < (3*numVerts); j++) {
- channel[i*framesize + j] = verts[j];
- }
- channel[i*framesize + framesize-1] = time;
-
- MEM_freeN(verts);
- MEM_freeN(tris);
+ Object *ob = fobj->object;
+ FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(
+ ob, eModifierType_Fluidsim);
+ float *verts;
+ int *tris = NULL, numVerts = 0, numTris = 0;
+ int modifierIndex = BLI_findindex(&ob->modifiers, fluidmd);
+ int framesize = (3 * fobj->numVerts) + 1;
+ int j;
+
+ if (channel == NULL)
+ return;
+
+ initElbeemMesh(depsgraph, scene, ob, &numVerts, &verts, &numTris, &tris, 1, modifierIndex);
+
+ /* don't allow mesh to change number of verts in anim sequence */
+ if (numVerts != fobj->numVerts) {
+ MEM_freeN(channel);
+ channel = NULL;
+ return;
+ }
+
+ /* fill frame of channel with vertex locations */
+ for (j = 0; j < (3 * numVerts); j++) {
+ channel[i * framesize + j] = verts[j];
+ }
+ channel[i * framesize + framesize - 1] = time;
+
+ MEM_freeN(verts);
+ MEM_freeN(tris);
}
static void free_domain_channels(FluidAnimChannels *channels)
{
- if (!channels->timeAtFrame)
- return;
- MEM_freeN(channels->timeAtFrame);
- channels->timeAtFrame = NULL;
- MEM_freeN(channels->DomainGravity);
- channels->DomainGravity = NULL;
- MEM_freeN(channels->DomainViscosity);
- channels->DomainViscosity = NULL;
- MEM_freeN(channels->DomainTime);
- channels->DomainTime = NULL;
+ if (!channels->timeAtFrame)
+ return;
+ MEM_freeN(channels->timeAtFrame);
+ channels->timeAtFrame = NULL;
+ MEM_freeN(channels->DomainGravity);
+ channels->DomainGravity = NULL;
+ MEM_freeN(channels->DomainViscosity);
+ channels->DomainViscosity = NULL;
+ MEM_freeN(channels->DomainTime);
+ channels->DomainTime = NULL;
}
static void free_all_fluidobject_channels(ListBase *fobjects)
{
- FluidObject *fobj;
-
- for (fobj=fobjects->first; fobj; fobj=fobj->next) {
- if (fobj->Translation) {
- MEM_freeN(fobj->Translation);
- fobj->Translation = NULL;
- MEM_freeN(fobj->Rotation);
- fobj->Rotation = NULL;
- MEM_freeN(fobj->Scale);
- fobj->Scale = NULL;
- MEM_freeN(fobj->Active);
- fobj->Active = NULL;
- MEM_freeN(fobj->InitialVelocity);
- fobj->InitialVelocity = NULL;
- }
-
- if (fobj->AttractforceStrength) {
- MEM_freeN(fobj->AttractforceStrength);
- fobj->AttractforceStrength = NULL;
- MEM_freeN(fobj->AttractforceRadius);
- fobj->AttractforceRadius = NULL;
- MEM_freeN(fobj->VelocityforceStrength);
- fobj->VelocityforceStrength = NULL;
- MEM_freeN(fobj->VelocityforceRadius);
- fobj->VelocityforceRadius = NULL;
- }
-
- if (fobj->VertexCache) {
- MEM_freeN(fobj->VertexCache);
- fobj->VertexCache = NULL;
- }
- }
+ FluidObject *fobj;
+
+ for (fobj = fobjects->first; fobj; fobj = fobj->next) {
+ if (fobj->Translation) {
+ MEM_freeN(fobj->Translation);
+ fobj->Translation = NULL;
+ MEM_freeN(fobj->Rotation);
+ fobj->Rotation = NULL;
+ MEM_freeN(fobj->Scale);
+ fobj->Scale = NULL;
+ MEM_freeN(fobj->Active);
+ fobj->Active = NULL;
+ MEM_freeN(fobj->InitialVelocity);
+ fobj->InitialVelocity = NULL;
+ }
+
+ if (fobj->AttractforceStrength) {
+ MEM_freeN(fobj->AttractforceStrength);
+ fobj->AttractforceStrength = NULL;
+ MEM_freeN(fobj->AttractforceRadius);
+ fobj->AttractforceRadius = NULL;
+ MEM_freeN(fobj->VelocityforceStrength);
+ fobj->VelocityforceStrength = NULL;
+ MEM_freeN(fobj->VelocityforceRadius);
+ fobj->VelocityforceRadius = NULL;
+ }
+
+ if (fobj->VertexCache) {
+ MEM_freeN(fobj->VertexCache);
+ fobj->VertexCache = NULL;
+ }
+ }
}
-static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), FluidsimSettings *domainSettings, FluidAnimChannels *channels, ListBase *fobjects)
+static void fluid_init_all_channels(bContext *C,
+ Object *UNUSED(fsDomain),
+ FluidsimSettings *domainSettings,
+ FluidAnimChannels *channels,
+ ListBase *fobjects)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Base *base;
- int i;
- int length = channels->length;
- float eval_time;
-
- /* init time values (assuming that time moves at a constant speed; may be overridden later) */
- init_time(domainSettings, channels);
-
- /* allocate domain animation channels */
- channels->DomainGravity = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "channel DomainGravity");
- channels->DomainViscosity = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainViscosity");
- channels->DomainTime = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainTime");
-
- /* allocate fluid objects */
- for (base = FIRSTBASE(view_layer); base; base = base->next) {
- Object *ob = base->object;
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
-
- if (fluidmd) {
- FluidObject *fobj = MEM_callocN(sizeof(FluidObject), "Fluid Object");
- fobj->object = ob;
-
- if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE)) {
- BLI_addtail(fobjects, fobj);
- continue;
- }
-
- fobj->Translation = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Translation");
- fobj->Rotation = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Rotation");
- fobj->Scale = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Scale");
- fobj->Active = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject Active");
- fobj->InitialVelocity = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject InitialVelocity");
-
- if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) {
- fobj->AttractforceStrength = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject AttractforceStrength");
- fobj->AttractforceRadius = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject AttractforceRadius");
- fobj->VelocityforceStrength = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject VelocityforceStrength");
- fobj->VelocityforceRadius = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject VelocityforceRadius");
- }
-
- if (fluid_is_animated_mesh(fluidmd->fss)) {
- float *verts=NULL;
- int *tris=NULL, modifierIndex = BLI_findindex(&ob->modifiers, (ModifierData *)fluidmd);
-
- initElbeemMesh(depsgraph, scene, ob, &fobj->numVerts, &verts, &fobj->numTris, &tris, 0, modifierIndex);
- fobj->VertexCache = MEM_callocN(length *((fobj->numVerts*CHANNEL_VEC)+1) * sizeof(float), "fluidobject VertexCache");
-
- MEM_freeN(verts);
- MEM_freeN(tris);
- }
-
- BLI_addtail(fobjects, fobj);
- }
- }
-
- /* now we loop over the frames and fill the allocated channels with data */
- for (i=0; i < channels->length; i++) {
- FluidObject *fobj;
- float viscosity, gravity[3];
- float timeAtFrame, time;
-
- eval_time = domainSettings->bakeStart + i;
-
- /* Modifying the global scene isn't nice, but we can do it in
- * this part of the process before a threaded job is created */
- scene->r.cfra = (int)eval_time;
- ED_update_for_newframe(CTX_data_main(C), depsgraph);
-
- /* now scene data should be current according to animation system, so we fill the channels */
-
- /* Domain time */
- // TODO: have option for not running sim, time mangling, in which case second case comes in handy
- if (channels->DomainTime) {
- time = get_fluid_rate(domainSettings) * (float)channels->aniFrameTime;
- timeAtFrame = channels->timeAtFrame[i] + time;
-
- channels->timeAtFrame[i+1] = timeAtFrame;
- set_channel(channels->DomainTime, i, &time, i, CHANNEL_FLOAT);
- }
- else {
- timeAtFrame = channels->timeAtFrame[i+1];
- }
-
- /* Domain properties - gravity/viscosity */
- get_fluid_gravity(gravity, scene, domainSettings);
- set_channel(channels->DomainGravity, timeAtFrame, gravity, i, CHANNEL_VEC);
- viscosity = get_fluid_viscosity(domainSettings);
- set_channel(channels->DomainViscosity, timeAtFrame, &viscosity, i, CHANNEL_FLOAT);
-
- /* object movement */
- for (fobj=fobjects->first; fobj; fobj=fobj->next) {
- Object *ob = fobj->object;
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
- float active = (float) ((fluidmd->fss->flag & OB_FLUIDSIM_ACTIVE) ? 1 : 0);
- float rot_d[3] = {0.f, 0.f, 0.f}, old_rot[3] = {0.f, 0.f, 0.f};
-
- if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE))
- continue;
-
- /* init euler rotation values and convert to elbeem format */
- /* get the rotation from ob->obmat rather than ob->rot to account for parent animations */
- if (i) {
- copy_v3_v3(old_rot, fobj->Rotation + 4*(i-1));
- mul_v3_fl(old_rot, (float)-M_PI / 180.f);
- }
-
- mat4_to_compatible_eulO(rot_d, old_rot, 0, ob->obmat);
- mul_v3_fl(rot_d, -180.0f / (float)M_PI);
-
- set_channel(fobj->Translation, timeAtFrame, ob->loc, i, CHANNEL_VEC);
- set_channel(fobj->Rotation, timeAtFrame, rot_d, i, CHANNEL_VEC);
- set_channel(fobj->Scale, timeAtFrame, ob->scale, i, CHANNEL_VEC);
- set_channel(fobj->Active, timeAtFrame, &active, i, CHANNEL_FLOAT);
- set_channel(fobj->InitialVelocity, timeAtFrame, &fluidmd->fss->iniVelx, i, CHANNEL_VEC);
-
- // printf("Active: %f, Frame: %f\n", active, timeAtFrame);
-
- if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) {
- set_channel(fobj->AttractforceStrength, timeAtFrame, &fluidmd->fss->attractforceStrength, i, CHANNEL_FLOAT);
- set_channel(fobj->AttractforceRadius, timeAtFrame, &fluidmd->fss->attractforceRadius, i, CHANNEL_FLOAT);
- set_channel(fobj->VelocityforceStrength, timeAtFrame, &fluidmd->fss->velocityforceStrength, i, CHANNEL_FLOAT);
- set_channel(fobj->VelocityforceRadius, timeAtFrame, &fluidmd->fss->velocityforceRadius, i, CHANNEL_FLOAT);
- }
-
- if (fluid_is_animated_mesh(fluidmd->fss)) {
- set_vertex_channel(depsgraph, fobj->VertexCache, timeAtFrame, scene, fobj, i);
- }
- }
- }
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Base *base;
+ int i;
+ int length = channels->length;
+ float eval_time;
+
+ /* init time values (assuming that time moves at a constant speed; may be overridden later) */
+ init_time(domainSettings, channels);
+
+ /* allocate domain animation channels */
+ channels->DomainGravity = MEM_callocN(length * (CHANNEL_VEC + 1) * sizeof(float),
+ "channel DomainGravity");
+ channels->DomainViscosity = MEM_callocN(length * (CHANNEL_FLOAT + 1) * sizeof(float),
+ "channel DomainViscosity");
+ channels->DomainTime = MEM_callocN(length * (CHANNEL_FLOAT + 1) * sizeof(float),
+ "channel DomainTime");
+
+ /* allocate fluid objects */
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
+ Object *ob = base->object;
+ FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(
+ ob, eModifierType_Fluidsim);
+
+ if (fluidmd) {
+ FluidObject *fobj = MEM_callocN(sizeof(FluidObject), "Fluid Object");
+ fobj->object = ob;
+
+ if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE)) {
+ BLI_addtail(fobjects, fobj);
+ continue;
+ }
+
+ fobj->Translation = MEM_callocN(length * (CHANNEL_VEC + 1) * sizeof(float),
+ "fluidobject Translation");
+ fobj->Rotation = MEM_callocN(length * (CHANNEL_VEC + 1) * sizeof(float),
+ "fluidobject Rotation");
+ fobj->Scale = MEM_callocN(length * (CHANNEL_VEC + 1) * sizeof(float), "fluidobject Scale");
+ fobj->Active = MEM_callocN(length * (CHANNEL_FLOAT + 1) * sizeof(float),
+ "fluidobject Active");
+ fobj->InitialVelocity = MEM_callocN(length * (CHANNEL_VEC + 1) * sizeof(float),
+ "fluidobject InitialVelocity");
+
+ if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) {
+ fobj->AttractforceStrength = MEM_callocN(length * (CHANNEL_FLOAT + 1) * sizeof(float),
+ "fluidobject AttractforceStrength");
+ fobj->AttractforceRadius = MEM_callocN(length * (CHANNEL_FLOAT + 1) * sizeof(float),
+ "fluidobject AttractforceRadius");
+ fobj->VelocityforceStrength = MEM_callocN(length * (CHANNEL_FLOAT + 1) * sizeof(float),
+ "fluidobject VelocityforceStrength");
+ fobj->VelocityforceRadius = MEM_callocN(length * (CHANNEL_FLOAT + 1) * sizeof(float),
+ "fluidobject VelocityforceRadius");
+ }
+
+ if (fluid_is_animated_mesh(fluidmd->fss)) {
+ float *verts = NULL;
+ int *tris = NULL, modifierIndex = BLI_findindex(&ob->modifiers, (ModifierData *)fluidmd);
+
+ initElbeemMesh(depsgraph,
+ scene,
+ ob,
+ &fobj->numVerts,
+ &verts,
+ &fobj->numTris,
+ &tris,
+ 0,
+ modifierIndex);
+ fobj->VertexCache = MEM_callocN(length * ((fobj->numVerts * CHANNEL_VEC) + 1) *
+ sizeof(float),
+ "fluidobject VertexCache");
+
+ MEM_freeN(verts);
+ MEM_freeN(tris);
+ }
+
+ BLI_addtail(fobjects, fobj);
+ }
+ }
+
+ /* now we loop over the frames and fill the allocated channels with data */
+ for (i = 0; i < channels->length; i++) {
+ FluidObject *fobj;
+ float viscosity, gravity[3];
+ float timeAtFrame, time;
+
+ eval_time = domainSettings->bakeStart + i;
+
+ /* Modifying the global scene isn't nice, but we can do it in
+ * this part of the process before a threaded job is created */
+ scene->r.cfra = (int)eval_time;
+ ED_update_for_newframe(CTX_data_main(C), depsgraph);
+
+ /* now scene data should be current according to animation system, so we fill the channels */
+
+ /* Domain time */
+ // TODO: have option for not running sim, time mangling, in which case second case comes in handy
+ if (channels->DomainTime) {
+ time = get_fluid_rate(domainSettings) * (float)channels->aniFrameTime;
+ timeAtFrame = channels->timeAtFrame[i] + time;
+
+ channels->timeAtFrame[i + 1] = timeAtFrame;
+ set_channel(channels->DomainTime, i, &time, i, CHANNEL_FLOAT);
+ }
+ else {
+ timeAtFrame = channels->timeAtFrame[i + 1];
+ }
+
+ /* Domain properties - gravity/viscosity */
+ get_fluid_gravity(gravity, scene, domainSettings);
+ set_channel(channels->DomainGravity, timeAtFrame, gravity, i, CHANNEL_VEC);
+ viscosity = get_fluid_viscosity(domainSettings);
+ set_channel(channels->DomainViscosity, timeAtFrame, &viscosity, i, CHANNEL_FLOAT);
+
+ /* object movement */
+ for (fobj = fobjects->first; fobj; fobj = fobj->next) {
+ Object *ob = fobj->object;
+ FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(
+ ob, eModifierType_Fluidsim);
+ float active = (float)((fluidmd->fss->flag & OB_FLUIDSIM_ACTIVE) ? 1 : 0);
+ float rot_d[3] = {0.f, 0.f, 0.f}, old_rot[3] = {0.f, 0.f, 0.f};
+
+ if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE))
+ continue;
+
+ /* init euler rotation values and convert to elbeem format */
+ /* get the rotation from ob->obmat rather than ob->rot to account for parent animations */
+ if (i) {
+ copy_v3_v3(old_rot, fobj->Rotation + 4 * (i - 1));
+ mul_v3_fl(old_rot, (float)-M_PI / 180.f);
+ }
+
+ mat4_to_compatible_eulO(rot_d, old_rot, 0, ob->obmat);
+ mul_v3_fl(rot_d, -180.0f / (float)M_PI);
+
+ set_channel(fobj->Translation, timeAtFrame, ob->loc, i, CHANNEL_VEC);
+ set_channel(fobj->Rotation, timeAtFrame, rot_d, i, CHANNEL_VEC);
+ set_channel(fobj->Scale, timeAtFrame, ob->scale, i, CHANNEL_VEC);
+ set_channel(fobj->Active, timeAtFrame, &active, i, CHANNEL_FLOAT);
+ set_channel(fobj->InitialVelocity, timeAtFrame, &fluidmd->fss->iniVelx, i, CHANNEL_VEC);
+
+ // printf("Active: %f, Frame: %f\n", active, timeAtFrame);
+
+ if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) {
+ set_channel(fobj->AttractforceStrength,
+ timeAtFrame,
+ &fluidmd->fss->attractforceStrength,
+ i,
+ CHANNEL_FLOAT);
+ set_channel(fobj->AttractforceRadius,
+ timeAtFrame,
+ &fluidmd->fss->attractforceRadius,
+ i,
+ CHANNEL_FLOAT);
+ set_channel(fobj->VelocityforceStrength,
+ timeAtFrame,
+ &fluidmd->fss->velocityforceStrength,
+ i,
+ CHANNEL_FLOAT);
+ set_channel(fobj->VelocityforceRadius,
+ timeAtFrame,
+ &fluidmd->fss->velocityforceRadius,
+ i,
+ CHANNEL_FLOAT);
+ }
+
+ if (fluid_is_animated_mesh(fluidmd->fss)) {
+ set_vertex_channel(depsgraph, fobj->VertexCache, timeAtFrame, scene, fobj, i);
+ }
+ }
+ }
}
static void export_fluid_objects(const bContext *C, ListBase *fobjects, Scene *scene, int length)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- FluidObject *fobj;
-
- for (fobj=fobjects->first; fobj; fobj=fobj->next) {
- Object *ob = fobj->object;
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
- int modifierIndex = BLI_findindex(&ob->modifiers, fluidmd);
-
- float *verts=NULL;
- int *tris=NULL;
- int numVerts=0, numTris=0;
- bool deform = fluid_is_animated_mesh(fluidmd->fss);
-
- elbeemMesh fsmesh;
-
- if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE))
- continue;
-
- elbeemResetMesh(&fsmesh);
-
- fsmesh.type = fluidmd->fss->type;
- fsmesh.name = ob->id.name;
-
- initElbeemMesh(depsgraph, scene, ob, &numVerts, &verts, &numTris, &tris, 0, modifierIndex);
-
- fsmesh.numVertices = numVerts;
- fsmesh.numTriangles = numTris;
- fsmesh.vertices = verts;
- fsmesh.triangles = tris;
-
- fsmesh.channelSizeTranslation =
- fsmesh.channelSizeRotation =
- fsmesh.channelSizeScale =
- fsmesh.channelSizeInitialVel =
- fsmesh.channelSizeActive = length;
-
- fsmesh.channelTranslation = fobj->Translation;
- fsmesh.channelRotation = fobj->Rotation;
- fsmesh.channelScale = fobj->Scale;
- fsmesh.channelActive = fobj->Active;
-
- if ( ELEM(fsmesh.type, OB_FLUIDSIM_FLUID, OB_FLUIDSIM_INFLOW)) {
- fsmesh.channelInitialVel = fobj->InitialVelocity;
- fsmesh.localInivelCoords = ((fluidmd->fss->typeFlags & OB_FSINFLOW_LOCALCOORD) ? 1 : 0);
- }
-
- if (fluidmd->fss->typeFlags & OB_FSBND_NOSLIP)
- fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
- else if (fluidmd->fss->typeFlags & OB_FSBND_PARTSLIP)
- fsmesh.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP;
- else if (fluidmd->fss->typeFlags & OB_FSBND_FREESLIP)
- fsmesh.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP;
-
- fsmesh.obstaclePartslip = fluidmd->fss->partSlipValue;
- fsmesh.volumeInitType = fluidmd->fss->volumeInitType;
- fsmesh.obstacleImpactFactor = fluidmd->fss->surfaceSmoothing; // misused value
-
- if (fsmesh.type == OB_FLUIDSIM_CONTROL) {
- fsmesh.cpsTimeStart = fluidmd->fss->cpsTimeStart;
- fsmesh.cpsTimeEnd = fluidmd->fss->cpsTimeEnd;
- fsmesh.cpsQuality = fluidmd->fss->cpsQuality;
- fsmesh.obstacleType = (fluidmd->fss->flag & OB_FLUIDSIM_REVERSE);
-
- fsmesh.channelSizeAttractforceRadius =
- fsmesh.channelSizeVelocityforceStrength =
- fsmesh.channelSizeVelocityforceRadius =
- fsmesh.channelSizeAttractforceStrength = length;
-
- fsmesh.channelAttractforceStrength = fobj->AttractforceStrength;
- fsmesh.channelAttractforceRadius = fobj->AttractforceRadius;
- fsmesh.channelVelocityforceStrength = fobj->VelocityforceStrength;
- fsmesh.channelVelocityforceRadius = fobj->VelocityforceRadius;
- }
- else {
- fsmesh.channelAttractforceStrength =
- fsmesh.channelAttractforceRadius =
- fsmesh.channelVelocityforceStrength =
- fsmesh.channelVelocityforceRadius = NULL;
- }
-
- /* animated meshes */
- if (deform) {
- fsmesh.channelSizeVertices = length;
- fsmesh.channelVertices = fobj->VertexCache;
-
- /* remove channels */
- fsmesh.channelTranslation =
- fsmesh.channelRotation =
- fsmesh.channelScale = NULL;
-
- /* Override user settings, only noslip is supported here! */
- if (fsmesh.type != OB_FLUIDSIM_CONTROL)
- fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
- }
-
- elbeemAddMesh(&fsmesh);
-
- if (verts) MEM_freeN(verts);
- if (tris) MEM_freeN(tris);
- }
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ FluidObject *fobj;
+
+ for (fobj = fobjects->first; fobj; fobj = fobj->next) {
+ Object *ob = fobj->object;
+ FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(
+ ob, eModifierType_Fluidsim);
+ int modifierIndex = BLI_findindex(&ob->modifiers, fluidmd);
+
+ float *verts = NULL;
+ int *tris = NULL;
+ int numVerts = 0, numTris = 0;
+ bool deform = fluid_is_animated_mesh(fluidmd->fss);
+
+ elbeemMesh fsmesh;
+
+ if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE))
+ continue;
+
+ elbeemResetMesh(&fsmesh);
+
+ fsmesh.type = fluidmd->fss->type;
+ fsmesh.name = ob->id.name;
+
+ initElbeemMesh(depsgraph, scene, ob, &numVerts, &verts, &numTris, &tris, 0, modifierIndex);
+
+ fsmesh.numVertices = numVerts;
+ fsmesh.numTriangles = numTris;
+ fsmesh.vertices = verts;
+ fsmesh.triangles = tris;
+
+ fsmesh.channelSizeTranslation = fsmesh.channelSizeRotation = fsmesh.channelSizeScale =
+ fsmesh.channelSizeInitialVel = fsmesh.channelSizeActive = length;
+
+ fsmesh.channelTranslation = fobj->Translation;
+ fsmesh.channelRotation = fobj->Rotation;
+ fsmesh.channelScale = fobj->Scale;
+ fsmesh.channelActive = fobj->Active;
+
+ if (ELEM(fsmesh.type, OB_FLUIDSIM_FLUID, OB_FLUIDSIM_INFLOW)) {
+ fsmesh.channelInitialVel = fobj->InitialVelocity;
+ fsmesh.localInivelCoords = ((fluidmd->fss->typeFlags & OB_FSINFLOW_LOCALCOORD) ? 1 : 0);
+ }
+
+ if (fluidmd->fss->typeFlags & OB_FSBND_NOSLIP)
+ fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
+ else if (fluidmd->fss->typeFlags & OB_FSBND_PARTSLIP)
+ fsmesh.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP;
+ else if (fluidmd->fss->typeFlags & OB_FSBND_FREESLIP)
+ fsmesh.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP;
+
+ fsmesh.obstaclePartslip = fluidmd->fss->partSlipValue;
+ fsmesh.volumeInitType = fluidmd->fss->volumeInitType;
+ fsmesh.obstacleImpactFactor = fluidmd->fss->surfaceSmoothing; // misused value
+
+ if (fsmesh.type == OB_FLUIDSIM_CONTROL) {
+ fsmesh.cpsTimeStart = fluidmd->fss->cpsTimeStart;
+ fsmesh.cpsTimeEnd = fluidmd->fss->cpsTimeEnd;
+ fsmesh.cpsQuality = fluidmd->fss->cpsQuality;
+ fsmesh.obstacleType = (fluidmd->fss->flag & OB_FLUIDSIM_REVERSE);
+
+ fsmesh.channelSizeAttractforceRadius = fsmesh.channelSizeVelocityforceStrength =
+ fsmesh.channelSizeVelocityforceRadius = fsmesh.channelSizeAttractforceStrength = length;
+
+ fsmesh.channelAttractforceStrength = fobj->AttractforceStrength;
+ fsmesh.channelAttractforceRadius = fobj->AttractforceRadius;
+ fsmesh.channelVelocityforceStrength = fobj->VelocityforceStrength;
+ fsmesh.channelVelocityforceRadius = fobj->VelocityforceRadius;
+ }
+ else {
+ fsmesh.channelAttractforceStrength = fsmesh.channelAttractforceRadius =
+ fsmesh.channelVelocityforceStrength = fsmesh.channelVelocityforceRadius = NULL;
+ }
+
+ /* animated meshes */
+ if (deform) {
+ fsmesh.channelSizeVertices = length;
+ fsmesh.channelVertices = fobj->VertexCache;
+
+ /* remove channels */
+ fsmesh.channelTranslation = fsmesh.channelRotation = fsmesh.channelScale = NULL;
+
+ /* Override user settings, only noslip is supported here! */
+ if (fsmesh.type != OB_FLUIDSIM_CONTROL)
+ fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
+ }
+
+ elbeemAddMesh(&fsmesh);
+
+ if (verts)
+ MEM_freeN(verts);
+ if (tris)
+ MEM_freeN(tris);
+ }
}
static int fluid_validate_scene(ReportList *reports, ViewLayer *view_layer, Object *fsDomain)
{
- Base *base;
- Object *newdomain = NULL;
- int channelObjCount = 0;
- int fluidInputCount = 0;
-
- for (base = FIRSTBASE(view_layer); base; base = base->next) {
- Object *ob = base->object;
- FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
-
- /* only find objects with fluid modifiers */
- if (!fluidmdtmp || ob->type != OB_MESH) continue;
-
- if (fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN) {
- /* if no initial domain object given, find another potential domain */
- if (!fsDomain) {
- newdomain = ob;
- }
- /* if there's more than one domain, cancel */
- else if (fsDomain && ob != fsDomain) {
- BKE_report(reports, RPT_ERROR, "There should be only one domain object");
- return 0;
- }
- }
-
- /* count number of objects needed for animation channels */
- if ( !ELEM(fluidmdtmp->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE) )
- channelObjCount++;
-
- /* count number of fluid input objects */
- if (ELEM(fluidmdtmp->fss->type, OB_FLUIDSIM_FLUID, OB_FLUIDSIM_INFLOW))
- fluidInputCount++;
- }
-
- if (newdomain)
- fsDomain = newdomain;
-
- if (!fsDomain) {
- BKE_report(reports, RPT_ERROR, "No domain object found");
- return 0;
- }
-
- if (channelObjCount >= 255) {
- BKE_report(reports, RPT_ERROR, "Cannot bake with more than 256 objects");
- return 0;
- }
-
- if (fluidInputCount == 0) {
- BKE_report(reports, RPT_ERROR, "No fluid input objects in the scene");
- return 0;
- }
-
- return 1;
+ Base *base;
+ Object *newdomain = NULL;
+ int channelObjCount = 0;
+ int fluidInputCount = 0;
+
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
+ Object *ob = base->object;
+ FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(
+ ob, eModifierType_Fluidsim);
+
+ /* only find objects with fluid modifiers */
+ if (!fluidmdtmp || ob->type != OB_MESH)
+ continue;
+
+ if (fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN) {
+ /* if no initial domain object given, find another potential domain */
+ if (!fsDomain) {
+ newdomain = ob;
+ }
+ /* if there's more than one domain, cancel */
+ else if (fsDomain && ob != fsDomain) {
+ BKE_report(reports, RPT_ERROR, "There should be only one domain object");
+ return 0;
+ }
+ }
+
+ /* count number of objects needed for animation channels */
+ if (!ELEM(fluidmdtmp->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE))
+ channelObjCount++;
+
+ /* count number of fluid input objects */
+ if (ELEM(fluidmdtmp->fss->type, OB_FLUIDSIM_FLUID, OB_FLUIDSIM_INFLOW))
+ fluidInputCount++;
+ }
+
+ if (newdomain)
+ fsDomain = newdomain;
+
+ if (!fsDomain) {
+ BKE_report(reports, RPT_ERROR, "No domain object found");
+ return 0;
+ }
+
+ if (channelObjCount >= 255) {
+ BKE_report(reports, RPT_ERROR, "Cannot bake with more than 256 objects");
+ return 0;
+ }
+
+ if (fluidInputCount == 0) {
+ BKE_report(reports, RPT_ERROR, "No fluid input objects in the scene");
+ return 0;
+ }
+
+ return 1;
}
+# define FLUID_SUFFIX_CONFIG "fluidsim.cfg"
+# define FLUID_SUFFIX_CONFIG_TMP (FLUID_SUFFIX_CONFIG ".tmp")
+# define FLUID_SUFFIX_SURFACE "fluidsurface"
-#define FLUID_SUFFIX_CONFIG "fluidsim.cfg"
-#define FLUID_SUFFIX_CONFIG_TMP (FLUID_SUFFIX_CONFIG ".tmp")
-#define FLUID_SUFFIX_SURFACE "fluidsurface"
-
-static bool fluid_init_filepaths(
- Main *bmain, ReportList *reports, FluidsimSettings *domainSettings, Object *fsDomain,
- char *targetDir, char *targetFile)
+static bool fluid_init_filepaths(Main *bmain,
+ ReportList *reports,
+ FluidsimSettings *domainSettings,
+ Object *fsDomain,
+ char *targetDir,
+ char *targetFile)
{
- const char *suffixConfigTmp = FLUID_SUFFIX_CONFIG_TMP;
-
- /* prepare names... */
- const char *relbase = modifier_path_relbase(bmain, fsDomain);
-
- /* We do not accept empty paths, they can end in random places silently, see T51176. */
- if (domainSettings->surfdataPath[0] == '\0') {
- modifier_path_init(domainSettings->surfdataPath, sizeof(domainSettings->surfdataPath),
- OB_FLUIDSIM_SURF_DIR_DEFAULT);
- BKE_reportf(reports, RPT_WARNING, "Fluidsim: empty cache path, reset to default '%s'",
- domainSettings->surfdataPath);
- }
-
- BLI_strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
- BLI_path_abs(targetDir, relbase);
-
- /* .tmp: don't overwrite/delete original file */
- BLI_join_dirfile(targetFile, FILE_MAX, targetDir, suffixConfigTmp);
-
- /* Ensure whole path exists and is wirtable. */
- const bool dir_exists = BLI_dir_create_recursive(targetDir);
- const bool is_writable = BLI_file_is_writable(targetFile);
-
- /* 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 || !is_writable) {
- modifier_path_init(domainSettings->surfdataPath, sizeof(domainSettings->surfdataPath),
- OB_FLUIDSIM_SURF_DIR_DEFAULT);
-
- if (!dir_exists) {
- BKE_reportf(reports, RPT_ERROR, "Fluidsim: could not create cache directory '%s', reset to default '%s'",
- targetDir, domainSettings->surfdataPath);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Fluidsim: cache directory '%s' is not writable, reset to default '%s'",
- targetDir, domainSettings->surfdataPath);
- }
-
- BLI_strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
- BLI_path_abs(targetDir, relbase);
-
- /* .tmp: don't overwrite/delete original file */
- BLI_join_dirfile(targetFile, FILE_MAX, targetDir, suffixConfigTmp);
-
- /* Ensure whole path exists and is wirtable. */
- if (!BLI_dir_create_recursive(targetDir) || !BLI_file_is_writable(targetFile)) {
- BKE_reportf(reports, RPT_ERROR, "Fluidsim: could not use default cache directory '%s', "
- "please define a valid cache path manually", targetDir);
- }
- return false;
- }
-
- return true;
+ const char *suffixConfigTmp = FLUID_SUFFIX_CONFIG_TMP;
+
+ /* prepare names... */
+ const char *relbase = modifier_path_relbase(bmain, fsDomain);
+
+ /* We do not accept empty paths, they can end in random places silently, see T51176. */
+ if (domainSettings->surfdataPath[0] == '\0') {
+ modifier_path_init(domainSettings->surfdataPath,
+ sizeof(domainSettings->surfdataPath),
+ OB_FLUIDSIM_SURF_DIR_DEFAULT);
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Fluidsim: empty cache path, reset to default '%s'",
+ domainSettings->surfdataPath);
+ }
+
+ BLI_strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
+ BLI_path_abs(targetDir, relbase);
+
+ /* .tmp: don't overwrite/delete original file */
+ BLI_join_dirfile(targetFile, FILE_MAX, targetDir, suffixConfigTmp);
+
+ /* Ensure whole path exists and is wirtable. */
+ const bool dir_exists = BLI_dir_create_recursive(targetDir);
+ const bool is_writable = BLI_file_is_writable(targetFile);
+
+ /* 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 || !is_writable) {
+ modifier_path_init(domainSettings->surfdataPath,
+ sizeof(domainSettings->surfdataPath),
+ OB_FLUIDSIM_SURF_DIR_DEFAULT);
+
+ if (!dir_exists) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Fluidsim: could not create cache directory '%s', reset to default '%s'",
+ targetDir,
+ domainSettings->surfdataPath);
+ }
+ else {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Fluidsim: cache directory '%s' is not writable, reset to default '%s'",
+ targetDir,
+ domainSettings->surfdataPath);
+ }
+
+ BLI_strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
+ BLI_path_abs(targetDir, relbase);
+
+ /* .tmp: don't overwrite/delete original file */
+ BLI_join_dirfile(targetFile, FILE_MAX, targetDir, suffixConfigTmp);
+
+ /* Ensure whole path exists and is wirtable. */
+ if (!BLI_dir_create_recursive(targetDir) || !BLI_file_is_writable(targetFile)) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Fluidsim: could not use default cache directory '%s', "
+ "please define a valid cache path manually",
+ targetDir);
+ }
+ return false;
+ }
+
+ return true;
}
/* ******************************************************************************** */
@@ -687,392 +746,431 @@ static bool fluid_init_filepaths(
/* ******************************************************************************** */
typedef struct FluidBakeJob {
- /* from wmJob */
- void *owner;
- short *stop, *do_update;
- float *progress;
- int current_frame;
- elbeemSimulationSettings *settings;
+ /* from wmJob */
+ void *owner;
+ short *stop, *do_update;
+ float *progress;
+ int current_frame;
+ elbeemSimulationSettings *settings;
} FluidBakeJob;
static void fluidbake_free(void *customdata)
{
- FluidBakeJob *fb= (FluidBakeJob *)customdata;
- MEM_freeN(fb);
+ FluidBakeJob *fb = (FluidBakeJob *)customdata;
+ MEM_freeN(fb);
}
/* called by fluidbake, only to check job 'stop' value */
static int fluidbake_breakjob(void *customdata)
{
- FluidBakeJob *fb= (FluidBakeJob *)customdata;
+ FluidBakeJob *fb = (FluidBakeJob *)customdata;
- if (fb->stop && *(fb->stop))
- return 1;
+ if (fb->stop && *(fb->stop))
+ return 1;
- /* this is not nice yet, need to make the jobs list template better
- * for identifying/acting upon various different jobs */
- /* but for now we'll reuse the render break... */
- return (G.is_break);
+ /* this is not nice yet, need to make the jobs list template better
+ * for identifying/acting upon various different jobs */
+ /* but for now we'll reuse the render break... */
+ return (G.is_break);
}
/* called by fluidbake, wmJob sends notifier */
static void fluidbake_updatejob(void *customdata, float progress)
{
- FluidBakeJob *fb= (FluidBakeJob *)customdata;
+ FluidBakeJob *fb = (FluidBakeJob *)customdata;
- *(fb->do_update) = true;
- *(fb->progress) = progress;
+ *(fb->do_update) = true;
+ *(fb->progress) = progress;
}
static void fluidbake_startjob(void *customdata, short *stop, short *do_update, float *progress)
{
- FluidBakeJob *fb= (FluidBakeJob *)customdata;
+ FluidBakeJob *fb = (FluidBakeJob *)customdata;
- fb->stop= stop;
- fb->do_update = do_update;
- fb->progress = progress;
+ fb->stop = stop;
+ fb->do_update = do_update;
+ fb->progress = progress;
- G.is_break = false; /* XXX shared with render - replace with job 'stop' switch */
+ G.is_break = false; /* XXX shared with render - replace with job 'stop' switch */
- elbeemSimulate();
- *do_update = true;
- *stop = 0;
+ elbeemSimulate();
+ *do_update = true;
+ *stop = 0;
}
static void fluidbake_endjob(void *customdata)
{
- FluidBakeJob *fb= (FluidBakeJob *)customdata;
+ FluidBakeJob *fb = (FluidBakeJob *)customdata;
- if (fb->settings) {
- MEM_freeN(fb->settings);
- fb->settings = NULL;
- }
+ if (fb->settings) {
+ MEM_freeN(fb->settings);
+ fb->settings = NULL;
+ }
}
static int runSimulationCallback(void *data, int status, int frame)
{
- FluidBakeJob *fb = (FluidBakeJob *)data;
- elbeemSimulationSettings *settings = fb->settings;
+ FluidBakeJob *fb = (FluidBakeJob *)data;
+ elbeemSimulationSettings *settings = fb->settings;
- if (status == FLUIDSIM_CBSTATUS_NEWFRAME) {
- fluidbake_updatejob(fb, frame / (float)settings->noOfFrames);
- //printf("elbeem blender cb s%d, f%d, domainid:%d noOfFrames: %d\n", status, frame, settings->domainId, settings->noOfFrames ); // DEBUG
- }
+ if (status == FLUIDSIM_CBSTATUS_NEWFRAME) {
+ fluidbake_updatejob(fb, frame / (float)settings->noOfFrames);
+ //printf("elbeem blender cb s%d, f%d, domainid:%d noOfFrames: %d\n", status, frame, settings->domainId, settings->noOfFrames ); // DEBUG
+ }
- if (fluidbake_breakjob(fb)) {
- return FLUIDSIM_CBRET_ABORT;
- }
+ if (fluidbake_breakjob(fb)) {
+ return FLUIDSIM_CBRET_ABORT;
+ }
- return FLUIDSIM_CBRET_CONTINUE;
+ return FLUIDSIM_CBRET_CONTINUE;
}
-static void fluidbake_free_data(FluidAnimChannels *channels, ListBase *fobjects, elbeemSimulationSettings *fsset, FluidBakeJob *fb)
+static void fluidbake_free_data(FluidAnimChannels *channels,
+ ListBase *fobjects,
+ elbeemSimulationSettings *fsset,
+ FluidBakeJob *fb)
{
- free_domain_channels(channels);
- MEM_freeN(channels);
- channels = NULL;
-
- free_all_fluidobject_channels(fobjects);
- BLI_freelistN(fobjects);
- MEM_freeN(fobjects);
- fobjects = NULL;
-
- if (fsset) {
- MEM_freeN(fsset);
- fsset = NULL;
- }
-
- if (fb) {
- MEM_freeN(fb);
- fb = NULL;
- }
+ free_domain_channels(channels);
+ MEM_freeN(channels);
+ channels = NULL;
+
+ free_all_fluidobject_channels(fobjects);
+ BLI_freelistN(fobjects);
+ MEM_freeN(fobjects);
+ fobjects = NULL;
+
+ if (fsset) {
+ MEM_freeN(fsset);
+ fsset = NULL;
+ }
+
+ if (fb) {
+ MEM_freeN(fb);
+ fb = NULL;
+ }
}
/* copied from rna_fluidsim.c: fluidsim_find_lastframe() */
static void fluidsim_delete_until_lastframe(FluidsimSettings *fss, const char *relbase)
{
- char targetDir[FILE_MAX], targetFile[FILE_MAX];
- char targetDirVel[FILE_MAX], targetFileVel[FILE_MAX];
- char previewDir[FILE_MAX], previewFile[FILE_MAX];
- int curFrame = 1, exists = 0;
-
- BLI_join_dirfile(targetDir, sizeof(targetDir), fss->surfdataPath, OB_FLUIDSIM_SURF_FINAL_OBJ_FNAME);
- BLI_join_dirfile(targetDirVel, sizeof(targetDirVel), fss->surfdataPath, OB_FLUIDSIM_SURF_FINAL_VEL_FNAME);
- BLI_join_dirfile(previewDir, sizeof(previewDir), fss->surfdataPath, OB_FLUIDSIM_SURF_PREVIEW_OBJ_FNAME);
-
- BLI_path_abs(targetDir, relbase);
- BLI_path_abs(targetDirVel, relbase);
- BLI_path_abs(previewDir, relbase);
-
- do {
- BLI_strncpy(targetFile, targetDir, sizeof(targetFile));
- BLI_strncpy(targetFileVel, targetDirVel, sizeof(targetFileVel));
- BLI_strncpy(previewFile, previewDir, sizeof(previewFile));
-
- BLI_path_frame(targetFile, curFrame, 0);
- BLI_path_frame(targetFileVel, curFrame, 0);
- BLI_path_frame(previewFile, curFrame, 0);
-
- curFrame++;
-
- if ((exists = BLI_exists(targetFile))) {
- BLI_delete(targetFile, false, false);
- BLI_delete(targetFileVel, false, false);
- BLI_delete(previewFile, false, false);
- }
- } while (exists);
-
- return;
+ char targetDir[FILE_MAX], targetFile[FILE_MAX];
+ char targetDirVel[FILE_MAX], targetFileVel[FILE_MAX];
+ char previewDir[FILE_MAX], previewFile[FILE_MAX];
+ int curFrame = 1, exists = 0;
+
+ BLI_join_dirfile(
+ targetDir, sizeof(targetDir), fss->surfdataPath, OB_FLUIDSIM_SURF_FINAL_OBJ_FNAME);
+ BLI_join_dirfile(
+ targetDirVel, sizeof(targetDirVel), fss->surfdataPath, OB_FLUIDSIM_SURF_FINAL_VEL_FNAME);
+ BLI_join_dirfile(
+ previewDir, sizeof(previewDir), fss->surfdataPath, OB_FLUIDSIM_SURF_PREVIEW_OBJ_FNAME);
+
+ BLI_path_abs(targetDir, relbase);
+ BLI_path_abs(targetDirVel, relbase);
+ BLI_path_abs(previewDir, relbase);
+
+ do {
+ BLI_strncpy(targetFile, targetDir, sizeof(targetFile));
+ BLI_strncpy(targetFileVel, targetDirVel, sizeof(targetFileVel));
+ BLI_strncpy(previewFile, previewDir, sizeof(previewFile));
+
+ BLI_path_frame(targetFile, curFrame, 0);
+ BLI_path_frame(targetFileVel, curFrame, 0);
+ BLI_path_frame(previewFile, curFrame, 0);
+
+ curFrame++;
+
+ if ((exists = BLI_exists(targetFile))) {
+ BLI_delete(targetFile, false, false);
+ BLI_delete(targetFileVel, false, false);
+ BLI_delete(previewFile, false, false);
+ }
+ } while (exists);
+
+ return;
}
static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, short do_job)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int i;
- FluidsimSettings *domainSettings;
-
- char debugStrBuffer[256];
-
- int gridlevels = 0;
- const char *relbase= modifier_path_relbase(bmain, fsDomain);
- const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp
- const char *suffixConfigTmp = FLUID_SUFFIX_CONFIG_TMP;
- const char *suffixSurface = FLUID_SUFFIX_SURFACE;
-
- char targetDir[FILE_MAX]; // store & modify output settings
- char targetFile[FILE_MAX]; // temp. store filename from targetDir for access
-
- float domainMat[4][4];
- float invDomMat[4][4];
-
- int noFrames;
- int origFrame = scene->r.cfra;
-
- FluidAnimChannels *channels = MEM_callocN(sizeof(FluidAnimChannels), "fluid domain animation channels");
- ListBase *fobjects = MEM_callocN(sizeof(ListBase), "fluid objects");
- FluidsimModifierData *fluidmd = NULL;
- Mesh *mesh = NULL;
-
- FluidBakeJob *fb;
- elbeemSimulationSettings *fsset= MEM_callocN(sizeof(elbeemSimulationSettings), "Fluid sim settings");
-
- fb= MEM_callocN(sizeof(FluidBakeJob), "fluid bake job");
-
- if (BLI_getenv(strEnvName)) {
- int dlevel = atoi(BLI_getenv(strEnvName));
- elbeemSetDebugLevel(dlevel);
- BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::msg: Debug messages activated due to envvar '%s'\n", strEnvName);
- elbeemDebugOut(debugStrBuffer);
- }
-
- /* make sure it corresponds to startFrame setting (old: noFrames = scene->r.efra - scene->r.sfra +1) */;
- noFrames = scene->r.efra - 0;
- if (noFrames<=0) {
- BKE_report(reports, RPT_ERROR, "No frames to export (check your animation range settings)");
- fluidbake_free_data(channels, fobjects, fsset, fb);
- return 0;
- }
-
- /* check scene for sane object/modifier settings */
- if (!fluid_validate_scene(reports, view_layer, fsDomain)) {
- fluidbake_free_data(channels, fobjects, fsset, fb);
- return 0;
- }
-
- /* these both have to be valid, otherwise we wouldn't be here */
- fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim);
- domainSettings = fluidmd->fss;
- mesh = fsDomain->data;
-
- domainSettings->bakeStart = 1;
- domainSettings->bakeEnd = scene->r.efra;
-
- // calculate bounding box
- fluid_get_bb(mesh->mvert, mesh->totvert, fsDomain->obmat, domainSettings->bbStart, domainSettings->bbSize);
-
- // reset last valid frame
- domainSettings->lastgoodframe = -1;
-
- /* delete old baked files */
- fluidsim_delete_until_lastframe(domainSettings, relbase);
-
- /* rough check of settings... */
- if (domainSettings->previewresxyz > domainSettings->resolutionxyz) {
- BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", domainSettings->previewresxyz, domainSettings->resolutionxyz);
- elbeemDebugOut(debugStrBuffer);
- domainSettings->previewresxyz = domainSettings->resolutionxyz;
- }
- // set adaptive coarsening according to resolutionxyz
- // this should do as an approximation, with in/outflow
- // doing this more accurate would be overkill
- // perhaps add manual setting?
- if (domainSettings->maxRefine <0) {
- if (domainSettings->resolutionxyz>128) {
- gridlevels = 2;
- }
- else if (domainSettings->resolutionxyz > 64) {
- gridlevels = 1;
- }
- else {
- gridlevels = 0;
- }
- }
- else {
- gridlevels = domainSettings->maxRefine;
- }
- BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::msg: Baking %s, refine: %d\n", fsDomain->id.name, gridlevels);
- elbeemDebugOut(debugStrBuffer);
-
-
-
- /* ******** prepare output file paths ******** */
- if (!fluid_init_filepaths(bmain, reports, domainSettings, fsDomain, targetDir, targetFile)) {
- fluidbake_free_data(channels, fobjects, fsset, fb);
- return false;
- }
-
- channels->length = scene->r.efra; // DG TODO: why using endframe and not "noFrames" here? .. because "noFrames" is buggy too? (not using sfra)
- channels->aniFrameTime = (double)((double)domainSettings->animEnd - (double)domainSettings->animStart) / (double)noFrames;
-
- /* ******** initialize and allocate animation channels ******** */
- fluid_init_all_channels(C, fsDomain, domainSettings, channels, fobjects);
-
- /* reset to original current frame */
- scene->r.cfra = origFrame;
- ED_update_for_newframe(CTX_data_main(C), depsgraph);
-
- /* ******** init domain object's matrix ******** */
- copy_m4_m4(domainMat, fsDomain->obmat);
- if (!invert_m4_m4(invDomMat, domainMat)) {
- BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::error - Invalid obj matrix?\n");
- elbeemDebugOut(debugStrBuffer);
- BKE_report(reports, RPT_ERROR, "Invalid object matrix");
-
- fluidbake_free_data(channels, fobjects, fsset, fb);
- return 0;
- }
-
- /* ******** start writing / exporting ******** */
- // use .tmp, don't overwrite/delete original file
- BLI_join_dirfile(targetFile, sizeof(targetFile), targetDir, suffixConfigTmp);
-
- /* ******** export domain to elbeem ******** */
- elbeemResetSettings(fsset);
- fsset->version = 1;
- fsset->threads = (domainSettings->threads == 0) ? BKE_scene_num_threads(scene) : domainSettings->threads;
- // setup global settings
- copy_v3_v3(fsset->geoStart, domainSettings->bbStart);
- copy_v3_v3(fsset->geoSize, domainSettings->bbSize);
-
- // simulate with 50^3
- fsset->resolutionxyz = (int)domainSettings->resolutionxyz;
- fsset->previewresxyz = (int)domainSettings->previewresxyz;
-
- fsset->realsize = get_fluid_size_m(scene, fsDomain, domainSettings);
- fsset->viscosity = get_fluid_viscosity(domainSettings);
- get_fluid_gravity(fsset->gravity, scene, domainSettings);
-
- // simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz
- fsset->animStart = domainSettings->animStart;
- fsset->aniFrameTime = channels->aniFrameTime;
- fsset->noOfFrames = noFrames; // is otherwise subtracted in parser
-
- BLI_join_dirfile(targetFile, sizeof(targetFile), targetDir, suffixSurface);
-
- // defaults for compressibility and adaptive grids
- fsset->gstar = domainSettings->gstar;
- fsset->maxRefine = domainSettings->maxRefine; // check <-> gridlevels
- fsset->generateParticles = domainSettings->generateParticles;
- fsset->numTracerParticles = domainSettings->generateTracers;
- fsset->surfaceSmoothing = domainSettings->surfaceSmoothing;
- fsset->surfaceSubdivs = domainSettings->surfaceSubdivs;
- fsset->farFieldSize = domainSettings->farFieldSize;
- BLI_strncpy(fsset->outputPath, targetFile, sizeof(fsset->outputPath));
-
- // domain channels
- fsset->channelSizeFrameTime =
- fsset->channelSizeViscosity =
- fsset->channelSizeGravity = channels->length;
- fsset->channelFrameTime = channels->DomainTime;
- fsset->channelViscosity = channels->DomainViscosity;
- fsset->channelGravity = channels->DomainGravity;
-
- fsset->runsimCallback = &runSimulationCallback;
- fsset->runsimUserData = fb;
-
- if (domainSettings->typeFlags & OB_FSBND_NOSLIP) fsset->domainobsType = FLUIDSIM_OBSTACLE_NOSLIP;
- else if (domainSettings->typeFlags&OB_FSBND_PARTSLIP) fsset->domainobsType = FLUIDSIM_OBSTACLE_PARTSLIP;
- else if (domainSettings->typeFlags&OB_FSBND_FREESLIP) fsset->domainobsType = FLUIDSIM_OBSTACLE_FREESLIP;
- fsset->domainobsPartslip = domainSettings->partSlipValue;
-
- /* use domainobsType also for surface generation flag (bit: >=64) */
- if (domainSettings->typeFlags & OB_FSSG_NOOBS)
- fsset->mFsSurfGenSetting = FLUIDSIM_FSSG_NOOBS;
- else
- fsset->mFsSurfGenSetting = 0; // "normal" mode
-
- fsset->generateVertexVectors = (domainSettings->domainNovecgen==0);
-
- // init blender domain transform matrix
- { int j;
- for (i=0; i<4; i++) {
- for (j=0; j<4; j++) {
- fsset->surfaceTrafo[i*4+j] = invDomMat[j][i];
- }
- } }
-
- /* ******** init solver with settings ******** */
- elbeemInit();
- elbeemAddDomain(fsset);
-
- /* ******** export all fluid objects to elbeem ******** */
- export_fluid_objects(C, fobjects, scene, channels->length);
-
- /* custom data for fluid bake job */
- fb->settings = fsset;
-
- if (do_job) {
- wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Fluid Simulation",
- WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_SIM_FLUID);
-
- /* setup job */
- WM_jobs_customdata_set(wm_job, fb, fluidbake_free);
- WM_jobs_timer(wm_job, 0.1, NC_SCENE|ND_FRAME, NC_SCENE|ND_FRAME);
- WM_jobs_callbacks(wm_job, fluidbake_startjob, NULL, NULL, fluidbake_endjob);
-
- WM_jobs_start(CTX_wm_manager(C), wm_job);
- }
- else {
- short dummy_stop = 0, dummy_do_update = 0;
- float dummy_progress = 0.0f;
-
- /* blocking, use with exec() */
- fluidbake_startjob((void *)fb, &dummy_stop, &dummy_do_update, &dummy_progress);
- fluidbake_endjob((void *)fb);
- fluidbake_free((void *)fb);
- }
-
- /* ******** free stored animation data ******** */
- fluidbake_free_data(channels, fobjects, NULL, NULL);
-
- // elbeemFree();
- return 1;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int i;
+ FluidsimSettings *domainSettings;
+
+ char debugStrBuffer[256];
+
+ int gridlevels = 0;
+ const char *relbase = modifier_path_relbase(bmain, fsDomain);
+ const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp
+ const char *suffixConfigTmp = FLUID_SUFFIX_CONFIG_TMP;
+ const char *suffixSurface = FLUID_SUFFIX_SURFACE;
+
+ char targetDir[FILE_MAX]; // store & modify output settings
+ char targetFile[FILE_MAX]; // temp. store filename from targetDir for access
+
+ float domainMat[4][4];
+ float invDomMat[4][4];
+
+ int noFrames;
+ int origFrame = scene->r.cfra;
+
+ FluidAnimChannels *channels = MEM_callocN(sizeof(FluidAnimChannels),
+ "fluid domain animation channels");
+ ListBase *fobjects = MEM_callocN(sizeof(ListBase), "fluid objects");
+ FluidsimModifierData *fluidmd = NULL;
+ Mesh *mesh = NULL;
+
+ FluidBakeJob *fb;
+ elbeemSimulationSettings *fsset = MEM_callocN(sizeof(elbeemSimulationSettings),
+ "Fluid sim settings");
+
+ fb = MEM_callocN(sizeof(FluidBakeJob), "fluid bake job");
+
+ if (BLI_getenv(strEnvName)) {
+ int dlevel = atoi(BLI_getenv(strEnvName));
+ elbeemSetDebugLevel(dlevel);
+ BLI_snprintf(debugStrBuffer,
+ sizeof(debugStrBuffer),
+ "fluidsimBake::msg: Debug messages activated due to envvar '%s'\n",
+ strEnvName);
+ elbeemDebugOut(debugStrBuffer);
+ }
+
+ /* make sure it corresponds to startFrame setting (old: noFrames = scene->r.efra - scene->r.sfra +1) */
+ ;
+ noFrames = scene->r.efra - 0;
+ if (noFrames <= 0) {
+ BKE_report(reports, RPT_ERROR, "No frames to export (check your animation range settings)");
+ fluidbake_free_data(channels, fobjects, fsset, fb);
+ return 0;
+ }
+
+ /* check scene for sane object/modifier settings */
+ if (!fluid_validate_scene(reports, view_layer, fsDomain)) {
+ fluidbake_free_data(channels, fobjects, fsset, fb);
+ return 0;
+ }
+
+ /* these both have to be valid, otherwise we wouldn't be here */
+ fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim);
+ domainSettings = fluidmd->fss;
+ mesh = fsDomain->data;
+
+ domainSettings->bakeStart = 1;
+ domainSettings->bakeEnd = scene->r.efra;
+
+ // calculate bounding box
+ fluid_get_bb(mesh->mvert,
+ mesh->totvert,
+ fsDomain->obmat,
+ domainSettings->bbStart,
+ domainSettings->bbSize);
+
+ // reset last valid frame
+ domainSettings->lastgoodframe = -1;
+
+ /* delete old baked files */
+ fluidsim_delete_until_lastframe(domainSettings, relbase);
+
+ /* rough check of settings... */
+ if (domainSettings->previewresxyz > domainSettings->resolutionxyz) {
+ BLI_snprintf(debugStrBuffer,
+ sizeof(debugStrBuffer),
+ "fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n",
+ domainSettings->previewresxyz,
+ domainSettings->resolutionxyz);
+ elbeemDebugOut(debugStrBuffer);
+ domainSettings->previewresxyz = domainSettings->resolutionxyz;
+ }
+ // set adaptive coarsening according to resolutionxyz
+ // this should do as an approximation, with in/outflow
+ // doing this more accurate would be overkill
+ // perhaps add manual setting?
+ if (domainSettings->maxRefine < 0) {
+ if (domainSettings->resolutionxyz > 128) {
+ gridlevels = 2;
+ }
+ else if (domainSettings->resolutionxyz > 64) {
+ gridlevels = 1;
+ }
+ else {
+ gridlevels = 0;
+ }
+ }
+ else {
+ gridlevels = domainSettings->maxRefine;
+ }
+ BLI_snprintf(debugStrBuffer,
+ sizeof(debugStrBuffer),
+ "fluidsimBake::msg: Baking %s, refine: %d\n",
+ fsDomain->id.name,
+ gridlevels);
+ elbeemDebugOut(debugStrBuffer);
+
+ /* ******** prepare output file paths ******** */
+ if (!fluid_init_filepaths(bmain, reports, domainSettings, fsDomain, targetDir, targetFile)) {
+ fluidbake_free_data(channels, fobjects, fsset, fb);
+ return false;
+ }
+
+ channels->length =
+ scene->r
+ .efra; // DG TODO: why using endframe and not "noFrames" here? .. because "noFrames" is buggy too? (not using sfra)
+ channels->aniFrameTime = (double)((double)domainSettings->animEnd -
+ (double)domainSettings->animStart) /
+ (double)noFrames;
+
+ /* ******** initialize and allocate animation channels ******** */
+ fluid_init_all_channels(C, fsDomain, domainSettings, channels, fobjects);
+
+ /* reset to original current frame */
+ scene->r.cfra = origFrame;
+ ED_update_for_newframe(CTX_data_main(C), depsgraph);
+
+ /* ******** init domain object's matrix ******** */
+ copy_m4_m4(domainMat, fsDomain->obmat);
+ if (!invert_m4_m4(invDomMat, domainMat)) {
+ BLI_snprintf(
+ debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::error - Invalid obj matrix?\n");
+ elbeemDebugOut(debugStrBuffer);
+ BKE_report(reports, RPT_ERROR, "Invalid object matrix");
+
+ fluidbake_free_data(channels, fobjects, fsset, fb);
+ return 0;
+ }
+
+ /* ******** start writing / exporting ******** */
+ // use .tmp, don't overwrite/delete original file
+ BLI_join_dirfile(targetFile, sizeof(targetFile), targetDir, suffixConfigTmp);
+
+ /* ******** export domain to elbeem ******** */
+ elbeemResetSettings(fsset);
+ fsset->version = 1;
+ fsset->threads = (domainSettings->threads == 0) ? BKE_scene_num_threads(scene) :
+ domainSettings->threads;
+ // setup global settings
+ copy_v3_v3(fsset->geoStart, domainSettings->bbStart);
+ copy_v3_v3(fsset->geoSize, domainSettings->bbSize);
+
+ // simulate with 50^3
+ fsset->resolutionxyz = (int)domainSettings->resolutionxyz;
+ fsset->previewresxyz = (int)domainSettings->previewresxyz;
+
+ fsset->realsize = get_fluid_size_m(scene, fsDomain, domainSettings);
+ fsset->viscosity = get_fluid_viscosity(domainSettings);
+ get_fluid_gravity(fsset->gravity, scene, domainSettings);
+
+ // simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz
+ fsset->animStart = domainSettings->animStart;
+ fsset->aniFrameTime = channels->aniFrameTime;
+ fsset->noOfFrames = noFrames; // is otherwise subtracted in parser
+
+ BLI_join_dirfile(targetFile, sizeof(targetFile), targetDir, suffixSurface);
+
+ // defaults for compressibility and adaptive grids
+ fsset->gstar = domainSettings->gstar;
+ fsset->maxRefine = domainSettings->maxRefine; // check <-> gridlevels
+ fsset->generateParticles = domainSettings->generateParticles;
+ fsset->numTracerParticles = domainSettings->generateTracers;
+ fsset->surfaceSmoothing = domainSettings->surfaceSmoothing;
+ fsset->surfaceSubdivs = domainSettings->surfaceSubdivs;
+ fsset->farFieldSize = domainSettings->farFieldSize;
+ BLI_strncpy(fsset->outputPath, targetFile, sizeof(fsset->outputPath));
+
+ // domain channels
+ fsset->channelSizeFrameTime = fsset->channelSizeViscosity = fsset->channelSizeGravity =
+ channels->length;
+ fsset->channelFrameTime = channels->DomainTime;
+ fsset->channelViscosity = channels->DomainViscosity;
+ fsset->channelGravity = channels->DomainGravity;
+
+ fsset->runsimCallback = &runSimulationCallback;
+ fsset->runsimUserData = fb;
+
+ if (domainSettings->typeFlags & OB_FSBND_NOSLIP)
+ fsset->domainobsType = FLUIDSIM_OBSTACLE_NOSLIP;
+ else if (domainSettings->typeFlags & OB_FSBND_PARTSLIP)
+ fsset->domainobsType = FLUIDSIM_OBSTACLE_PARTSLIP;
+ else if (domainSettings->typeFlags & OB_FSBND_FREESLIP)
+ fsset->domainobsType = FLUIDSIM_OBSTACLE_FREESLIP;
+ fsset->domainobsPartslip = domainSettings->partSlipValue;
+
+ /* use domainobsType also for surface generation flag (bit: >=64) */
+ if (domainSettings->typeFlags & OB_FSSG_NOOBS)
+ fsset->mFsSurfGenSetting = FLUIDSIM_FSSG_NOOBS;
+ else
+ fsset->mFsSurfGenSetting = 0; // "normal" mode
+
+ fsset->generateVertexVectors = (domainSettings->domainNovecgen == 0);
+
+ // init blender domain transform matrix
+ {
+ int j;
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 4; j++) {
+ fsset->surfaceTrafo[i * 4 + j] = invDomMat[j][i];
+ }
+ }
+ }
+
+ /* ******** init solver with settings ******** */
+ elbeemInit();
+ elbeemAddDomain(fsset);
+
+ /* ******** export all fluid objects to elbeem ******** */
+ export_fluid_objects(C, fobjects, scene, channels->length);
+
+ /* custom data for fluid bake job */
+ fb->settings = fsset;
+
+ if (do_job) {
+ wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ scene,
+ "Fluid Simulation",
+ WM_JOB_PROGRESS,
+ WM_JOB_TYPE_OBJECT_SIM_FLUID);
+
+ /* setup job */
+ WM_jobs_customdata_set(wm_job, fb, fluidbake_free);
+ WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_FRAME, NC_SCENE | ND_FRAME);
+ WM_jobs_callbacks(wm_job, fluidbake_startjob, NULL, NULL, fluidbake_endjob);
+
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+ }
+ else {
+ short dummy_stop = 0, dummy_do_update = 0;
+ float dummy_progress = 0.0f;
+
+ /* blocking, use with exec() */
+ fluidbake_startjob((void *)fb, &dummy_stop, &dummy_do_update, &dummy_progress);
+ fluidbake_endjob((void *)fb);
+ fluidbake_free((void *)fb);
+ }
+
+ /* ******** free stored animation data ******** */
+ fluidbake_free_data(channels, fobjects, NULL, NULL);
+
+ // elbeemFree();
+ return 1;
}
static void UNUSED_FUNCTION(fluidsimFreeBake)(Object *UNUSED(ob))
{
- /* not implemented yet */
+ /* not implemented yet */
}
#else /* WITH_MOD_FLUID */
/* only compile dummy functions */
-static int fluidsimBake(bContext *UNUSED(C), ReportList *UNUSED(reports), Object *UNUSED(ob), short UNUSED(do_job))
+static int fluidsimBake(bContext *UNUSED(C),
+ ReportList *UNUSED(reports),
+ Object *UNUSED(ob),
+ short UNUSED(do_job))
{
- return 0;
+ return 0;
}
#endif /* WITH_MOD_FLUID */
@@ -1081,33 +1179,33 @@ static int fluidsimBake(bContext *UNUSED(C), ReportList *UNUSED(reports), Object
static int fluid_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- /* only one bake job at a time */
- if (WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_SIM_FLUID))
- return OPERATOR_CANCELLED;
+ /* only one bake job at a time */
+ if (WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_SIM_FLUID))
+ return OPERATOR_CANCELLED;
- if (!fluidsimBake(C, op->reports, CTX_data_active_object(C), true))
- return OPERATOR_CANCELLED;
+ if (!fluidsimBake(C, op->reports, CTX_data_active_object(C), true))
+ return OPERATOR_CANCELLED;
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int fluid_bake_exec(bContext *C, wmOperator *op)
{
- if (!fluidsimBake(C, op->reports, CTX_data_active_object(C), false))
- return OPERATOR_CANCELLED;
+ if (!fluidsimBake(C, op->reports, CTX_data_active_object(C), false))
+ return OPERATOR_CANCELLED;
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void FLUID_OT_bake(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Fluid Simulation Bake";
- ot->description = "Bake fluid simulation";
- ot->idname = "FLUID_OT_bake";
-
- /* api callbacks */
- ot->invoke = fluid_bake_invoke;
- ot->exec = fluid_bake_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* identifiers */
+ ot->name = "Fluid Simulation Bake";
+ ot->description = "Bake fluid simulation";
+ ot->idname = "FLUID_OT_bake";
+
+ /* api callbacks */
+ ot->invoke = fluid_bake_invoke;
+ ot->exec = fluid_bake_exec;
+ ot->poll = ED_operator_object_active_editable;
}
diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h
index dbadb2356d1..bb7cfe9b1a3 100644
--- a/source/blender/editors/physics/physics_intern.h
+++ b/source/blender/editors/physics/physics_intern.h
@@ -21,7 +21,6 @@
* \ingroup edphys
*/
-
#ifndef __PHYSICS_INTERN_H__
#define __PHYSICS_INTERN_H__
@@ -62,11 +61,15 @@ void PARTICLE_OT_edited_clear(struct wmOperatorType *ot);
void PARTICLE_OT_unify_length(struct wmOperatorType *ot);
-void PE_create_particle_edit(
- struct Depsgraph *depsgraph, struct Scene *scene,
- struct Object *ob, struct PointCache *cache, struct ParticleSystem *psys);
+void PE_create_particle_edit(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob,
+ struct PointCache *cache,
+ struct ParticleSystem *psys);
void recalc_lengths(struct PTCacheEdit *edit);
-void recalc_emitter_field(struct Depsgraph *depsgraph, struct Object *ob, struct ParticleSystem *psys);
+void recalc_emitter_field(struct Depsgraph *depsgraph,
+ struct Object *ob,
+ struct ParticleSystem *psys);
void update_world_cos(struct Depsgraph *depsgraph, struct Object *ob, struct PTCacheEdit *edit);
/* particle_object.c */
diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c
index 40cbf51b840..b1b3927d05e 100644
--- a/source/blender/editors/physics/physics_ops.c
+++ b/source/blender/editors/physics/physics_ops.c
@@ -32,141 +32,139 @@
#include "ED_physics.h"
#include "ED_object.h"
-#include "physics_intern.h" // own include
-
+#include "physics_intern.h" // own include
/***************************** particles ***********************************/
static void operatortypes_particle(void)
{
- WM_operatortype_append(PARTICLE_OT_select_all);
- WM_operatortype_append(PARTICLE_OT_select_roots);
- 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_less);
- WM_operatortype_append(PARTICLE_OT_select_more);
-
- WM_operatortype_append(PARTICLE_OT_hide);
- WM_operatortype_append(PARTICLE_OT_reveal);
-
- WM_operatortype_append(PARTICLE_OT_rekey);
- WM_operatortype_append(PARTICLE_OT_subdivide);
- WM_operatortype_append(PARTICLE_OT_remove_doubles);
- WM_operatortype_append(PARTICLE_OT_weight_set);
- WM_operatortype_append(PARTICLE_OT_delete);
- WM_operatortype_append(PARTICLE_OT_mirror);
-
- WM_operatortype_append(PARTICLE_OT_brush_edit);
-
- WM_operatortype_append(PARTICLE_OT_shape_cut);
-
- WM_operatortype_append(PARTICLE_OT_particle_edit_toggle);
- WM_operatortype_append(PARTICLE_OT_edited_clear);
-
- WM_operatortype_append(PARTICLE_OT_unify_length);
-
-
- WM_operatortype_append(OBJECT_OT_particle_system_add);
- WM_operatortype_append(OBJECT_OT_particle_system_remove);
-
- WM_operatortype_append(PARTICLE_OT_new);
- WM_operatortype_append(PARTICLE_OT_new_target);
- WM_operatortype_append(PARTICLE_OT_target_remove);
- WM_operatortype_append(PARTICLE_OT_target_move_up);
- WM_operatortype_append(PARTICLE_OT_target_move_down);
- WM_operatortype_append(PARTICLE_OT_connect_hair);
- WM_operatortype_append(PARTICLE_OT_disconnect_hair);
- WM_operatortype_append(PARTICLE_OT_copy_particle_systems);
- WM_operatortype_append(PARTICLE_OT_duplicate_particle_system);
-
- WM_operatortype_append(PARTICLE_OT_dupliob_refresh);
- WM_operatortype_append(PARTICLE_OT_dupliob_copy);
- WM_operatortype_append(PARTICLE_OT_dupliob_remove);
- WM_operatortype_append(PARTICLE_OT_dupliob_move_up);
- WM_operatortype_append(PARTICLE_OT_dupliob_move_down);
-
- WM_operatortype_append(RIGIDBODY_OT_object_add);
- WM_operatortype_append(RIGIDBODY_OT_object_remove);
-
- WM_operatortype_append(RIGIDBODY_OT_objects_add);
- WM_operatortype_append(RIGIDBODY_OT_objects_remove);
-
- WM_operatortype_append(RIGIDBODY_OT_shape_change);
- WM_operatortype_append(RIGIDBODY_OT_mass_calculate);
-
- WM_operatortype_append(RIGIDBODY_OT_constraint_add);
- WM_operatortype_append(RIGIDBODY_OT_constraint_remove);
-
- WM_operatortype_append(RIGIDBODY_OT_world_add);
- WM_operatortype_append(RIGIDBODY_OT_world_remove);
-// WM_operatortype_append(RIGIDBODY_OT_world_export);
+ WM_operatortype_append(PARTICLE_OT_select_all);
+ WM_operatortype_append(PARTICLE_OT_select_roots);
+ 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_less);
+ WM_operatortype_append(PARTICLE_OT_select_more);
+
+ WM_operatortype_append(PARTICLE_OT_hide);
+ WM_operatortype_append(PARTICLE_OT_reveal);
+
+ WM_operatortype_append(PARTICLE_OT_rekey);
+ WM_operatortype_append(PARTICLE_OT_subdivide);
+ WM_operatortype_append(PARTICLE_OT_remove_doubles);
+ WM_operatortype_append(PARTICLE_OT_weight_set);
+ WM_operatortype_append(PARTICLE_OT_delete);
+ WM_operatortype_append(PARTICLE_OT_mirror);
+
+ WM_operatortype_append(PARTICLE_OT_brush_edit);
+
+ WM_operatortype_append(PARTICLE_OT_shape_cut);
+
+ WM_operatortype_append(PARTICLE_OT_particle_edit_toggle);
+ WM_operatortype_append(PARTICLE_OT_edited_clear);
+
+ WM_operatortype_append(PARTICLE_OT_unify_length);
+
+ WM_operatortype_append(OBJECT_OT_particle_system_add);
+ WM_operatortype_append(OBJECT_OT_particle_system_remove);
+
+ WM_operatortype_append(PARTICLE_OT_new);
+ WM_operatortype_append(PARTICLE_OT_new_target);
+ WM_operatortype_append(PARTICLE_OT_target_remove);
+ WM_operatortype_append(PARTICLE_OT_target_move_up);
+ WM_operatortype_append(PARTICLE_OT_target_move_down);
+ WM_operatortype_append(PARTICLE_OT_connect_hair);
+ WM_operatortype_append(PARTICLE_OT_disconnect_hair);
+ WM_operatortype_append(PARTICLE_OT_copy_particle_systems);
+ WM_operatortype_append(PARTICLE_OT_duplicate_particle_system);
+
+ WM_operatortype_append(PARTICLE_OT_dupliob_refresh);
+ WM_operatortype_append(PARTICLE_OT_dupliob_copy);
+ WM_operatortype_append(PARTICLE_OT_dupliob_remove);
+ WM_operatortype_append(PARTICLE_OT_dupliob_move_up);
+ WM_operatortype_append(PARTICLE_OT_dupliob_move_down);
+
+ WM_operatortype_append(RIGIDBODY_OT_object_add);
+ WM_operatortype_append(RIGIDBODY_OT_object_remove);
+
+ WM_operatortype_append(RIGIDBODY_OT_objects_add);
+ WM_operatortype_append(RIGIDBODY_OT_objects_remove);
+
+ WM_operatortype_append(RIGIDBODY_OT_shape_change);
+ WM_operatortype_append(RIGIDBODY_OT_mass_calculate);
+
+ WM_operatortype_append(RIGIDBODY_OT_constraint_add);
+ WM_operatortype_append(RIGIDBODY_OT_constraint_remove);
+
+ WM_operatortype_append(RIGIDBODY_OT_world_add);
+ WM_operatortype_append(RIGIDBODY_OT_world_remove);
+ // WM_operatortype_append(RIGIDBODY_OT_world_export);
}
static void keymap_particle(wmKeyConfig *keyconf)
{
- wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Particle", 0, 0);
- keymap->poll = PE_poll;
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Particle", 0, 0);
+ keymap->poll = PE_poll;
}
/******************************* boids *************************************/
static void operatortypes_boids(void)
{
- WM_operatortype_append(BOID_OT_rule_add);
- WM_operatortype_append(BOID_OT_rule_del);
- WM_operatortype_append(BOID_OT_rule_move_up);
- WM_operatortype_append(BOID_OT_rule_move_down);
-
- WM_operatortype_append(BOID_OT_state_add);
- WM_operatortype_append(BOID_OT_state_del);
- WM_operatortype_append(BOID_OT_state_move_up);
- WM_operatortype_append(BOID_OT_state_move_down);
+ WM_operatortype_append(BOID_OT_rule_add);
+ WM_operatortype_append(BOID_OT_rule_del);
+ WM_operatortype_append(BOID_OT_rule_move_up);
+ WM_operatortype_append(BOID_OT_rule_move_down);
+
+ WM_operatortype_append(BOID_OT_state_add);
+ WM_operatortype_append(BOID_OT_state_del);
+ WM_operatortype_append(BOID_OT_state_move_up);
+ WM_operatortype_append(BOID_OT_state_move_down);
}
/********************************* fluid ***********************************/
static void operatortypes_fluid(void)
{
- WM_operatortype_append(FLUID_OT_bake);
+ WM_operatortype_append(FLUID_OT_bake);
}
/**************************** point cache **********************************/
static void operatortypes_pointcache(void)
{
- WM_operatortype_append(PTCACHE_OT_bake_all);
- WM_operatortype_append(PTCACHE_OT_free_bake_all);
- WM_operatortype_append(PTCACHE_OT_bake);
- WM_operatortype_append(PTCACHE_OT_free_bake);
- WM_operatortype_append(PTCACHE_OT_bake_from_cache);
- WM_operatortype_append(PTCACHE_OT_add);
- WM_operatortype_append(PTCACHE_OT_remove);
+ WM_operatortype_append(PTCACHE_OT_bake_all);
+ WM_operatortype_append(PTCACHE_OT_free_bake_all);
+ WM_operatortype_append(PTCACHE_OT_bake);
+ WM_operatortype_append(PTCACHE_OT_free_bake);
+ WM_operatortype_append(PTCACHE_OT_bake_from_cache);
+ WM_operatortype_append(PTCACHE_OT_add);
+ WM_operatortype_append(PTCACHE_OT_remove);
}
/********************************* dynamic paint ***********************************/
static void operatortypes_dynamicpaint(void)
{
- WM_operatortype_append(DPAINT_OT_bake);
- WM_operatortype_append(DPAINT_OT_surface_slot_add);
- WM_operatortype_append(DPAINT_OT_surface_slot_remove);
- WM_operatortype_append(DPAINT_OT_type_toggle);
- WM_operatortype_append(DPAINT_OT_output_toggle);
+ WM_operatortype_append(DPAINT_OT_bake);
+ WM_operatortype_append(DPAINT_OT_surface_slot_add);
+ WM_operatortype_append(DPAINT_OT_surface_slot_remove);
+ WM_operatortype_append(DPAINT_OT_type_toggle);
+ WM_operatortype_append(DPAINT_OT_output_toggle);
}
/****************************** general ************************************/
void ED_operatortypes_physics(void)
{
- operatortypes_particle();
- operatortypes_boids();
- operatortypes_fluid();
- operatortypes_pointcache();
- operatortypes_dynamicpaint();
+ operatortypes_particle();
+ operatortypes_boids();
+ operatortypes_fluid();
+ operatortypes_pointcache();
+ operatortypes_dynamicpaint();
}
void ED_keymap_physics(wmKeyConfig *keyconf)
{
- keymap_particle(keyconf);
+ keymap_particle(keyconf);
}
diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c
index ab89922e89c..e9e89a31f94 100644
--- a/source/blender/editors/physics/physics_pointcache.c
+++ b/source/blender/editors/physics/physics_pointcache.c
@@ -51,384 +51,387 @@
static bool ptcache_bake_all_poll(bContext *C)
{
- return CTX_data_scene(C) != NULL;
+ return CTX_data_scene(C) != NULL;
}
static bool ptcache_poll(bContext *C)
{
- PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
- return (ptr.data && ptr.id.data);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
+ return (ptr.data && ptr.id.data);
}
typedef struct PointCacheJob {
- wmWindowManager *wm;
- void *owner;
- short *stop, *do_update;
- float *progress;
+ wmWindowManager *wm;
+ void *owner;
+ short *stop, *do_update;
+ float *progress;
- PTCacheBaker *baker;
+ PTCacheBaker *baker;
} PointCacheJob;
static void ptcache_job_free(void *customdata)
{
- PointCacheJob *job = customdata;
- MEM_freeN(job->baker);
- MEM_freeN(job);
+ PointCacheJob *job = customdata;
+ MEM_freeN(job->baker);
+ MEM_freeN(job);
}
static int ptcache_job_break(void *customdata)
{
- PointCacheJob *job = customdata;
+ PointCacheJob *job = customdata;
- if (G.is_break) {
- return 1;
- }
+ if (G.is_break) {
+ return 1;
+ }
- if (job->stop && *(job->stop)) {
- return 1;
- }
+ if (job->stop && *(job->stop)) {
+ return 1;
+ }
- return 0;
+ return 0;
}
static void ptcache_job_update(void *customdata, float progress, int *cancel)
{
- PointCacheJob *job = customdata;
+ PointCacheJob *job = customdata;
- if (ptcache_job_break(job)) {
- *cancel = 1;
- }
+ if (ptcache_job_break(job)) {
+ *cancel = 1;
+ }
- *(job->do_update) = true;
- *(job->progress) = progress;
+ *(job->do_update) = true;
+ *(job->progress) = progress;
}
static void ptcache_job_startjob(void *customdata, short *stop, short *do_update, float *progress)
{
- PointCacheJob *job = customdata;
+ PointCacheJob *job = customdata;
- job->stop = stop;
- job->do_update = do_update;
- job->progress = progress;
+ job->stop = stop;
+ job->do_update = do_update;
+ job->progress = progress;
- G.is_break = false;
+ G.is_break = false;
- /* XXX annoying hack: needed to prevent data corruption when changing
- * scene frame in separate threads
- */
- WM_set_locked_interface(job->wm, true);
+ /* XXX annoying hack: needed to prevent data corruption when changing
+ * scene frame in separate threads
+ */
+ WM_set_locked_interface(job->wm, true);
- BKE_ptcache_bake(job->baker);
+ BKE_ptcache_bake(job->baker);
- *do_update = true;
- *stop = 0;
+ *do_update = true;
+ *stop = 0;
}
static void ptcache_job_endjob(void *customdata)
{
- PointCacheJob *job = customdata;
- Scene *scene = job->baker->scene;
+ PointCacheJob *job = customdata;
+ Scene *scene = job->baker->scene;
- WM_set_locked_interface(job->wm, false);
+ WM_set_locked_interface(job->wm, false);
- WM_main_add_notifier(NC_SCENE | ND_FRAME, scene);
- WM_main_add_notifier(NC_OBJECT | ND_POINTCACHE, job->baker->pid.ob);
+ WM_main_add_notifier(NC_SCENE | ND_FRAME, scene);
+ WM_main_add_notifier(NC_OBJECT | ND_POINTCACHE, job->baker->pid.ob);
}
static void ptcache_free_bake(PointCache *cache)
{
- if (cache->edit) {
- if (!cache->edit->edited || 1) {// XXX okee("Lose changes done in particle mode?")) {
- PE_free_ptcache_edit(cache->edit);
- cache->edit = NULL;
- cache->flag &= ~PTCACHE_BAKED;
- }
- }
- else {
- cache->flag &= ~PTCACHE_BAKED;
- }
+ if (cache->edit) {
+ if (!cache->edit->edited || 1) { // XXX okee("Lose changes done in particle mode?")) {
+ PE_free_ptcache_edit(cache->edit);
+ cache->edit = NULL;
+ cache->flag &= ~PTCACHE_BAKED;
+ }
+ }
+ else {
+ cache->flag &= ~PTCACHE_BAKED;
+ }
}
static PTCacheBaker *ptcache_baker_create(bContext *C, wmOperator *op, bool all)
{
- PTCacheBaker *baker = MEM_callocN(sizeof(PTCacheBaker), "PTCacheBaker");
-
- baker->bmain = CTX_data_main(C);
- baker->scene = CTX_data_scene(C);
- baker->view_layer = CTX_data_view_layer(C);
- baker->depsgraph = CTX_data_depsgraph(C);
- baker->bake = RNA_boolean_get(op->ptr, "bake");
- baker->render = 0;
- baker->anim_init = 0;
- baker->quick_step = 1;
-
- if (!all) {
- PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
- Object *ob = ptr.id.data;
- PointCache *cache = ptr.data;
- baker->pid = BKE_ptcache_id_find(ob, baker->scene, cache);
- }
-
- return baker;
+ PTCacheBaker *baker = MEM_callocN(sizeof(PTCacheBaker), "PTCacheBaker");
+
+ baker->bmain = CTX_data_main(C);
+ baker->scene = CTX_data_scene(C);
+ baker->view_layer = CTX_data_view_layer(C);
+ baker->depsgraph = CTX_data_depsgraph(C);
+ baker->bake = RNA_boolean_get(op->ptr, "bake");
+ baker->render = 0;
+ baker->anim_init = 0;
+ baker->quick_step = 1;
+
+ if (!all) {
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
+ Object *ob = ptr.id.data;
+ PointCache *cache = ptr.data;
+ baker->pid = BKE_ptcache_id_find(ob, baker->scene, cache);
+ }
+
+ return baker;
}
static int ptcache_bake_exec(bContext *C, wmOperator *op)
{
- bool all = STREQ(op->type->idname, "PTCACHE_OT_bake_all");
+ bool all = STREQ(op->type->idname, "PTCACHE_OT_bake_all");
- PTCacheBaker *baker = ptcache_baker_create(C, op, all);
- BKE_ptcache_bake(baker);
- MEM_freeN(baker);
+ PTCacheBaker *baker = ptcache_baker_create(C, op, all);
+ BKE_ptcache_bake(baker);
+ MEM_freeN(baker);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int ptcache_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- bool all = STREQ(op->type->idname, "PTCACHE_OT_bake_all");
+ bool all = STREQ(op->type->idname, "PTCACHE_OT_bake_all");
- PointCacheJob *job = MEM_mallocN(sizeof(PointCacheJob), "PointCacheJob");
- job->wm = CTX_wm_manager(C);
- job->baker = ptcache_baker_create(C, op, all);
- job->baker->bake_job = job;
- job->baker->update_progress = ptcache_job_update;
+ PointCacheJob *job = MEM_mallocN(sizeof(PointCacheJob), "PointCacheJob");
+ job->wm = CTX_wm_manager(C);
+ job->baker = ptcache_baker_create(C, op, all);
+ job->baker->bake_job = job;
+ job->baker->update_progress = ptcache_job_update;
- wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), CTX_data_scene(C),
- "Point Cache", WM_JOB_PROGRESS, WM_JOB_TYPE_POINTCACHE);
+ wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ CTX_data_scene(C),
+ "Point Cache",
+ WM_JOB_PROGRESS,
+ WM_JOB_TYPE_POINTCACHE);
- WM_jobs_customdata_set(wm_job, job, ptcache_job_free);
- WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_POINTCACHE, NC_OBJECT | ND_POINTCACHE);
- WM_jobs_callbacks(wm_job, ptcache_job_startjob, NULL, NULL, ptcache_job_endjob);
+ WM_jobs_customdata_set(wm_job, job, ptcache_job_free);
+ WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_POINTCACHE, NC_OBJECT | ND_POINTCACHE);
+ WM_jobs_callbacks(wm_job, ptcache_job_startjob, NULL, NULL, ptcache_job_endjob);
- WM_set_locked_interface(CTX_wm_manager(C), true);
+ WM_set_locked_interface(CTX_wm_manager(C), true);
- WM_jobs_start(CTX_wm_manager(C), wm_job);
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
- /* we must run modal until the bake job is done, otherwise the undo push
- * happens before the job ends, which can lead to race conditions between
- * the baking and file writing code */
- return OPERATOR_RUNNING_MODAL;
+ /* we must run modal until the bake job is done, otherwise the undo push
+ * happens before the job ends, which can lead to race conditions between
+ * the baking and file writing code */
+ return OPERATOR_RUNNING_MODAL;
}
static int ptcache_bake_modal(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Scene *scene = (Scene *) op->customdata;
+ Scene *scene = (Scene *)op->customdata;
- /* no running blender, remove handler and pass through */
- if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_POINTCACHE)) {
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
- }
+ /* no running blender, remove handler and pass through */
+ if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_POINTCACHE)) {
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ }
- return OPERATOR_PASS_THROUGH;
+ return OPERATOR_PASS_THROUGH;
}
static void ptcache_bake_cancel(bContext *C, wmOperator *op)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- Scene *scene = (Scene *) op->customdata;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ Scene *scene = (Scene *)op->customdata;
- /* kill on cancel, because job is using op->reports */
- WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_POINTCACHE);
+ /* kill on cancel, because job is using op->reports */
+ WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_POINTCACHE);
}
static int ptcache_free_bake_all_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- PTCacheID *pid;
- ListBase pidlist;
+ Scene *scene = CTX_data_scene(C);
+ PTCacheID *pid;
+ ListBase pidlist;
- FOREACH_SCENE_OBJECT_BEGIN(scene, ob)
- {
- BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
+ FOREACH_SCENE_OBJECT_BEGIN (scene, ob) {
+ BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
- for (pid = pidlist.first; pid; pid = pid->next) {
- ptcache_free_bake(pid->cache);
- }
+ for (pid = pidlist.first; pid; pid = pid->next) {
+ ptcache_free_bake(pid->cache);
+ }
- BLI_freelistN(&pidlist);
+ BLI_freelistN(&pidlist);
- WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
- }
- FOREACH_SCENE_OBJECT_END;
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, ob);
+ }
+ FOREACH_SCENE_OBJECT_END;
- WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PTCACHE_OT_bake_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Bake All Physics";
- ot->description = "Bake all physics";
- ot->idname = "PTCACHE_OT_bake_all";
-
- /* api callbacks */
- ot->exec = ptcache_bake_exec;
- ot->invoke = ptcache_bake_invoke;
- ot->modal = ptcache_bake_modal;
- ot->cancel = ptcache_bake_cancel;
- ot->poll = ptcache_bake_all_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "bake", 1, "Bake", "");
+ /* identifiers */
+ ot->name = "Bake All Physics";
+ ot->description = "Bake all physics";
+ ot->idname = "PTCACHE_OT_bake_all";
+
+ /* api callbacks */
+ ot->exec = ptcache_bake_exec;
+ ot->invoke = ptcache_bake_invoke;
+ ot->modal = ptcache_bake_modal;
+ ot->cancel = ptcache_bake_cancel;
+ ot->poll = ptcache_bake_all_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "bake", 1, "Bake", "");
}
void PTCACHE_OT_free_bake_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete All Physics Bakes";
- ot->idname = "PTCACHE_OT_free_bake_all";
- ot->description = "Delete all baked caches of all objects in the current scene";
+ /* identifiers */
+ ot->name = "Delete All Physics Bakes";
+ ot->idname = "PTCACHE_OT_free_bake_all";
+ ot->description = "Delete all baked caches of all objects in the current scene";
- /* api callbacks */
- ot->exec = ptcache_free_bake_all_exec;
- ot->poll = ptcache_bake_all_poll;
+ /* api callbacks */
+ ot->exec = ptcache_free_bake_all_exec;
+ ot->poll = ptcache_bake_all_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int ptcache_free_bake_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
- PointCache *cache= ptr.data;
- Object *ob= ptr.id.data;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
+ PointCache *cache = ptr.data;
+ Object *ob = ptr.id.data;
- ptcache_free_bake(cache);
+ ptcache_free_bake(cache);
- WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int ptcache_bake_from_cache_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
- PointCache *cache= ptr.data;
- Object *ob= ptr.id.data;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
+ PointCache *cache = ptr.data;
+ Object *ob = ptr.id.data;
- cache->flag |= PTCACHE_BAKED;
+ cache->flag |= PTCACHE_BAKED;
- WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PTCACHE_OT_bake(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Bake Physics";
- ot->description = "Bake physics";
- ot->idname = "PTCACHE_OT_bake";
-
- /* api callbacks */
- ot->exec = ptcache_bake_exec;
- ot->invoke = ptcache_bake_invoke;
- ot->modal = ptcache_bake_modal;
- ot->cancel = ptcache_bake_cancel;
- ot->poll = ptcache_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
+ /* identifiers */
+ ot->name = "Bake Physics";
+ ot->description = "Bake physics";
+ ot->idname = "PTCACHE_OT_bake";
+
+ /* api callbacks */
+ ot->exec = ptcache_bake_exec;
+ ot->invoke = ptcache_bake_invoke;
+ ot->modal = ptcache_bake_modal;
+ ot->cancel = ptcache_bake_cancel;
+ ot->poll = ptcache_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
}
void PTCACHE_OT_free_bake(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Physics Bake";
- ot->description = "Delete physics bake";
- ot->idname = "PTCACHE_OT_free_bake";
+ /* identifiers */
+ ot->name = "Delete Physics Bake";
+ ot->description = "Delete physics bake";
+ ot->idname = "PTCACHE_OT_free_bake";
- /* api callbacks */
- ot->exec = ptcache_free_bake_exec;
- ot->poll = ptcache_poll;
+ /* api callbacks */
+ ot->exec = ptcache_free_bake_exec;
+ ot->poll = ptcache_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void PTCACHE_OT_bake_from_cache(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Bake From Cache";
- ot->description = "Bake from cache";
- ot->idname = "PTCACHE_OT_bake_from_cache";
+ /* identifiers */
+ ot->name = "Bake From Cache";
+ ot->description = "Bake from cache";
+ ot->idname = "PTCACHE_OT_bake_from_cache";
- /* api callbacks */
- ot->exec = ptcache_bake_from_cache_exec;
- ot->poll = ptcache_poll;
+ /* api callbacks */
+ ot->exec = ptcache_bake_from_cache_exec;
+ ot->poll = ptcache_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int ptcache_add_new_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
- Object *ob= ptr.id.data;
- PointCache *cache= ptr.data;
- PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
-
- if (pid.cache) {
- PointCache *cache_new = BKE_ptcache_add(pid.ptcaches);
- cache_new->step = pid.default_step;
- *(pid.cache_ptr) = cache_new;
-
- DEG_id_tag_update(&ob->id, ID_RECALC_POINT_CACHE);
- WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
- WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
- }
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
+ Object *ob = ptr.id.data;
+ PointCache *cache = ptr.data;
+ PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
+
+ if (pid.cache) {
+ PointCache *cache_new = BKE_ptcache_add(pid.ptcaches);
+ cache_new->step = pid.default_step;
+ *(pid.cache_ptr) = cache_new;
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_POINT_CACHE);
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, ob);
+ }
+
+ return OPERATOR_FINISHED;
}
static int ptcache_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
- Scene *scene= CTX_data_scene(C);
- Object *ob= ptr.id.data;
- PointCache *cache= ptr.data;
- PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
-
- /* don't delete last cache */
- if (pid.cache && pid.ptcaches->first != pid.ptcaches->last) {
- BLI_remlink(pid.ptcaches, pid.cache);
- BKE_ptcache_free(pid.cache);
- *(pid.cache_ptr) = pid.ptcaches->first;
-
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
- }
-
- return OPERATOR_FINISHED;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ptr.id.data;
+ PointCache *cache = ptr.data;
+ PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
+
+ /* don't delete last cache */
+ if (pid.cache && pid.ptcaches->first != pid.ptcaches->last) {
+ BLI_remlink(pid.ptcaches, pid.cache);
+ BKE_ptcache_free(pid.cache);
+ *(pid.cache_ptr) = pid.ptcaches->first;
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, ob);
+ }
+
+ return OPERATOR_FINISHED;
}
void PTCACHE_OT_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add New Cache";
- ot->description = "Add new cache";
- ot->idname = "PTCACHE_OT_add";
+ /* identifiers */
+ ot->name = "Add New Cache";
+ ot->description = "Add new cache";
+ ot->idname = "PTCACHE_OT_add";
- /* api callbacks */
- ot->exec = ptcache_add_new_exec;
- ot->poll = ptcache_poll;
+ /* api callbacks */
+ ot->exec = ptcache_add_new_exec;
+ ot->poll = ptcache_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void PTCACHE_OT_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Current Cache";
- ot->description = "Delete current cache";
- ot->idname = "PTCACHE_OT_remove";
+ /* identifiers */
+ ot->name = "Delete Current Cache";
+ ot->description = "Delete current cache";
+ ot->idname = "PTCACHE_OT_remove";
- /* api callbacks */
- ot->exec = ptcache_remove_exec;
- ot->poll = ptcache_poll;
+ /* api callbacks */
+ ot->exec = ptcache_remove_exec;
+ ot->poll = ptcache_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
index 499a1d0e2e5..2d2c90f9391 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -56,54 +56,55 @@
static bool ED_operator_rigidbody_con_active_poll(bContext *C)
{
- if (ED_operator_object_active_editable(C)) {
- Object *ob = CTX_data_active_object(C);
- return (ob && ob->rigidbody_constraint);
- }
- else
- return 0;
+ if (ED_operator_object_active_editable(C)) {
+ Object *ob = CTX_data_active_object(C);
+ return (ob && ob->rigidbody_constraint);
+ }
+ else
+ return 0;
}
-
-bool ED_rigidbody_constraint_add(Main *bmain, Scene *scene, Object *ob, int type, ReportList *reports)
+bool ED_rigidbody_constraint_add(
+ Main *bmain, Scene *scene, Object *ob, int type, ReportList *reports)
{
- RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
-
- /* check that object doesn't already have a constraint */
- if (ob->rigidbody_constraint) {
- BKE_reportf(reports, RPT_INFO, "Object '%s' already has a Rigid Body Constraint", ob->id.name + 2);
- return false;
- }
- /* create constraint group if it doesn't already exits */
- if (rbw->constraints == NULL) {
- rbw->constraints = BKE_collection_add(bmain, NULL, "RigidBodyConstraints");
- id_fake_user_set(&rbw->constraints->id);
- }
- /* make rigidbody constraint settings */
- ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, type);
-
- /* add constraint to rigid body constraint group */
- BKE_collection_object_add(bmain, rbw->constraints, ob);
-
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- DEG_id_tag_update(&rbw->constraints->id, ID_RECALC_COPY_ON_WRITE);
-
- return true;
+ RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
+
+ /* check that object doesn't already have a constraint */
+ if (ob->rigidbody_constraint) {
+ BKE_reportf(
+ reports, RPT_INFO, "Object '%s' already has a Rigid Body Constraint", ob->id.name + 2);
+ return false;
+ }
+ /* create constraint group if it doesn't already exits */
+ if (rbw->constraints == NULL) {
+ rbw->constraints = BKE_collection_add(bmain, NULL, "RigidBodyConstraints");
+ id_fake_user_set(&rbw->constraints->id);
+ }
+ /* make rigidbody constraint settings */
+ ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, type);
+
+ /* add constraint to rigid body constraint group */
+ BKE_collection_object_add(bmain, rbw->constraints, ob);
+
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ DEG_id_tag_update(&rbw->constraints->id, ID_RECALC_COPY_ON_WRITE);
+
+ return true;
}
void ED_rigidbody_constraint_remove(Main *bmain, Scene *scene, Object *ob)
{
- RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
+ RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
- BKE_rigidbody_remove_constraint(scene, ob);
- if (rbw) {
- BKE_collection_object_remove(bmain, rbw->constraints, ob, false);
- DEG_id_tag_update(&rbw->constraints->id, ID_RECALC_COPY_ON_WRITE);
- }
+ BKE_rigidbody_remove_constraint(scene, ob);
+ if (rbw) {
+ BKE_collection_object_remove(bmain, rbw->constraints, ob, false);
+ DEG_id_tag_update(&rbw->constraints->id, ID_RECALC_COPY_ON_WRITE);
+ }
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
}
/* ********************************************** */
@@ -113,88 +114,93 @@ void ED_rigidbody_constraint_remove(Main *bmain, Scene *scene, Object *ob)
static int rigidbody_con_add_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);
- RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
- Object *ob = OBACT(view_layer);
- int type = RNA_enum_get(op->ptr, "type");
- bool changed;
-
- /* sanity checks */
- if (ELEM(NULL, scene, rbw)) {
- BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to add Rigid Body Constraint to");
- return OPERATOR_CANCELLED;
- }
- /* apply to active object */
- changed = ED_rigidbody_constraint_add(bmain, scene, ob, type, op->reports);
-
- if (changed) {
- /* send updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
+ Object *ob = OBACT(view_layer);
+ int type = RNA_enum_get(op->ptr, "type");
+ bool changed;
+
+ /* sanity checks */
+ if (ELEM(NULL, scene, rbw)) {
+ BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to add Rigid Body Constraint to");
+ return OPERATOR_CANCELLED;
+ }
+ /* apply to active object */
+ changed = ED_rigidbody_constraint_add(bmain, scene, ob, type, op->reports);
+
+ if (changed) {
+ /* send updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void RIGIDBODY_OT_constraint_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->idname = "RIGIDBODY_OT_constraint_add";
- ot->name = "Add Rigid Body Constraint";
- ot->description = "Add Rigid Body Constraint to active object";
-
- /* callbacks */
- ot->exec = rigidbody_con_add_exec;
- ot->poll = ED_operator_object_active_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_rigidbody_constraint_type_items, RBC_TYPE_FIXED, "Rigid Body Constraint Type", "");
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_constraint_add";
+ ot->name = "Add Rigid Body Constraint";
+ ot->description = "Add Rigid Body Constraint to active object";
+
+ /* callbacks */
+ ot->exec = rigidbody_con_add_exec;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna,
+ "type",
+ rna_enum_rigidbody_constraint_type_items,
+ RBC_TYPE_FIXED,
+ "Rigid Body Constraint Type",
+ "");
}
/* ************ Remove Rigid Body Constraint ************** */
static int rigidbody_con_remove_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);
- Object *ob = OBACT(view_layer);
-
- /* apply to active object */
- if (ELEM(NULL, ob, ob->rigidbody_constraint)) {
- BKE_report(op->reports, RPT_ERROR, "Object has no Rigid Body Constraint to remove");
- return OPERATOR_CANCELLED;
- }
- else {
- ED_rigidbody_constraint_remove(bmain, scene, ob);
- }
-
- /* send updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+
+ /* apply to active object */
+ if (ELEM(NULL, ob, ob->rigidbody_constraint)) {
+ BKE_report(op->reports, RPT_ERROR, "Object has no Rigid Body Constraint to remove");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ ED_rigidbody_constraint_remove(bmain, scene, ob);
+ }
+
+ /* send updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void RIGIDBODY_OT_constraint_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->idname = "RIGIDBODY_OT_constraint_remove";
- ot->name = "Remove Rigid Body Constraint";
- ot->description = "Remove Rigid Body Constraint from Object";
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_constraint_remove";
+ ot->name = "Remove Rigid Body Constraint";
+ ot->description = "Remove Rigid Body Constraint from Object";
- /* callbacks */
- ot->exec = rigidbody_con_remove_exec;
- ot->poll = ED_operator_rigidbody_con_active_poll;
+ /* callbacks */
+ ot->exec = rigidbody_con_remove_exec;
+ ot->poll = ED_operator_rigidbody_con_active_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index fd76a1b18f4..2914127f8d8 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -25,7 +25,6 @@
#include <stdlib.h>
#include <string.h>
-
#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
@@ -63,73 +62,73 @@
static bool ED_operator_rigidbody_active_poll(bContext *C)
{
- if (ED_operator_object_active_editable(C)) {
- Object *ob = ED_object_active_context(C);
- return (ob && ob->rigidbody_object);
- }
- else
- return 0;
+ if (ED_operator_object_active_editable(C)) {
+ Object *ob = ED_object_active_context(C);
+ return (ob && ob->rigidbody_object);
+ }
+ else
+ return 0;
}
static bool ED_operator_rigidbody_add_poll(bContext *C)
{
- if (ED_operator_object_active_editable(C)) {
- Object *ob = ED_object_active_context(C);
- return (ob && ob->type == OB_MESH);
- }
- else
- return 0;
+ if (ED_operator_object_active_editable(C)) {
+ Object *ob = ED_object_active_context(C);
+ return (ob && ob->type == OB_MESH);
+ }
+ else
+ return 0;
}
/* ----------------- */
bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, ReportList *reports)
{
- RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
-
- if (ob->type != OB_MESH) {
- BKE_report(reports, RPT_ERROR, "Can't add Rigid Body to non mesh object");
- return false;
- }
-
- /* Add rigid body world and group if they don't exist for convenience */
- if (rbw == NULL) {
- rbw = BKE_rigidbody_create_world(scene);
- if (rbw == NULL) {
- BKE_report(reports, RPT_ERROR, "Can't create Rigid Body world");
- return false;
- }
- BKE_rigidbody_validate_sim_world(scene, rbw, false);
- scene->rigidbody_world = rbw;
- }
- if (rbw->group == NULL) {
- rbw->group = BKE_collection_add(bmain, NULL, "RigidBodyWorld");
- id_fake_user_set(&rbw->group->id);
- }
-
- /* make rigidbody object settings */
- if (ob->rigidbody_object == NULL) {
- ob->rigidbody_object = BKE_rigidbody_create_object(scene, ob, type);
- }
- ob->rigidbody_object->type = type;
- ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE;
-
- /* add object to rigid body group */
- BKE_collection_object_add(bmain, rbw->group, ob);
-
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- DEG_id_tag_update(&rbw->group->id, ID_RECALC_COPY_ON_WRITE);
-
- return true;
+ RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
+
+ if (ob->type != OB_MESH) {
+ BKE_report(reports, RPT_ERROR, "Can't add Rigid Body to non mesh object");
+ return false;
+ }
+
+ /* Add rigid body world and group if they don't exist for convenience */
+ if (rbw == NULL) {
+ rbw = BKE_rigidbody_create_world(scene);
+ if (rbw == NULL) {
+ BKE_report(reports, RPT_ERROR, "Can't create Rigid Body world");
+ return false;
+ }
+ BKE_rigidbody_validate_sim_world(scene, rbw, false);
+ scene->rigidbody_world = rbw;
+ }
+ if (rbw->group == NULL) {
+ rbw->group = BKE_collection_add(bmain, NULL, "RigidBodyWorld");
+ id_fake_user_set(&rbw->group->id);
+ }
+
+ /* make rigidbody object settings */
+ if (ob->rigidbody_object == NULL) {
+ ob->rigidbody_object = BKE_rigidbody_create_object(scene, ob, type);
+ }
+ ob->rigidbody_object->type = type;
+ ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE;
+
+ /* add object to rigid body group */
+ BKE_collection_object_add(bmain, rbw->group, ob);
+
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ DEG_id_tag_update(&rbw->group->id, ID_RECALC_COPY_ON_WRITE);
+
+ return true;
}
void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob)
{
- BKE_rigidbody_remove_object(bmain, scene, ob);
+ BKE_rigidbody_remove_object(bmain, scene, ob);
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
}
/* ********************************************** */
@@ -139,88 +138,93 @@ void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob)
static int rigidbody_object_add_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- int type = RNA_enum_get(op->ptr, "type");
- bool changed;
-
- /* apply to active object */
- changed = ED_rigidbody_object_add(bmain, scene, ob, type, op->reports);
-
- if (changed) {
- /* send updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ int type = RNA_enum_get(op->ptr, "type");
+ bool changed;
+
+ /* apply to active object */
+ changed = ED_rigidbody_object_add(bmain, scene, ob, type, op->reports);
+
+ if (changed) {
+ /* send updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void RIGIDBODY_OT_object_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->idname = "RIGIDBODY_OT_object_add";
- ot->name = "Add Rigid Body";
- ot->description = "Add active object as Rigid Body";
-
- /* callbacks */
- ot->exec = rigidbody_object_add_exec;
- ot->poll = ED_operator_rigidbody_add_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_rigidbody_object_type_items, RBO_TYPE_ACTIVE, "Rigid Body Type", "");
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_object_add";
+ ot->name = "Add Rigid Body";
+ ot->description = "Add active object as Rigid Body";
+
+ /* callbacks */
+ ot->exec = rigidbody_object_add_exec;
+ ot->poll = ED_operator_rigidbody_add_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna,
+ "type",
+ rna_enum_rigidbody_object_type_items,
+ RBO_TYPE_ACTIVE,
+ "Rigid Body Type",
+ "");
}
/* ************ Remove Rigid Body ************** */
static int rigidbody_object_remove_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- bool changed = false;
-
- /* apply to active object */
- if (!ELEM(NULL, ob, ob->rigidbody_object)) {
- ED_rigidbody_object_remove(bmain, scene, ob);
- changed = true;
- }
-
- if (changed) {
- /* send updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Object has no Rigid Body settings to remove");
- return OPERATOR_CANCELLED;
- }
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ bool changed = false;
+
+ /* apply to active object */
+ if (!ELEM(NULL, ob, ob->rigidbody_object)) {
+ ED_rigidbody_object_remove(bmain, scene, ob);
+ changed = true;
+ }
+
+ if (changed) {
+ /* send updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Object has no Rigid Body settings to remove");
+ return OPERATOR_CANCELLED;
+ }
}
void RIGIDBODY_OT_object_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->idname = "RIGIDBODY_OT_object_remove";
- ot->name = "Remove Rigid Body";
- ot->description = "Remove Rigid Body settings from Object";
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_object_remove";
+ ot->name = "Remove Rigid Body";
+ ot->description = "Remove Rigid Body settings from Object";
- /* callbacks */
- ot->exec = rigidbody_object_remove_exec;
- ot->poll = ED_operator_rigidbody_active_poll;
+ /* callbacks */
+ ot->exec = rigidbody_object_remove_exec;
+ ot->poll = ED_operator_rigidbody_active_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************************************** */
@@ -230,92 +234,96 @@ void RIGIDBODY_OT_object_remove(wmOperatorType *ot)
static int rigidbody_objects_add_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- int type = RNA_enum_get(op->ptr, "type");
- bool changed = false;
-
- /* create rigid body objects and add them to the world's group */
- CTX_DATA_BEGIN(C, Object *, ob, selected_objects) {
- changed |= ED_rigidbody_object_add(bmain, scene, ob, type, op->reports);
- }
- CTX_DATA_END;
-
- if (changed) {
- /* send updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ int type = RNA_enum_get(op->ptr, "type");
+ bool changed = false;
+
+ /* create rigid body objects and add them to the world's group */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ changed |= ED_rigidbody_object_add(bmain, scene, ob, type, op->reports);
+ }
+ CTX_DATA_END;
+
+ if (changed) {
+ /* send updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void RIGIDBODY_OT_objects_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->idname = "RIGIDBODY_OT_objects_add";
- ot->name = "Add Rigid Bodies";
- ot->description = "Add selected objects as Rigid Bodies";
-
- /* callbacks */
- ot->exec = rigidbody_objects_add_exec;
- ot->poll = ED_operator_rigidbody_add_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_rigidbody_object_type_items, RBO_TYPE_ACTIVE, "Rigid Body Type", "");
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_objects_add";
+ ot->name = "Add Rigid Bodies";
+ ot->description = "Add selected objects as Rigid Bodies";
+
+ /* callbacks */
+ ot->exec = rigidbody_objects_add_exec;
+ ot->poll = ED_operator_rigidbody_add_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna,
+ "type",
+ rna_enum_rigidbody_object_type_items,
+ RBO_TYPE_ACTIVE,
+ "Rigid Body Type",
+ "");
}
/* ************ Remove Rigid Bodies ************** */
static int rigidbody_objects_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- bool changed = false;
-
- /* apply this to all selected objects... */
- CTX_DATA_BEGIN(C, Object *, ob, selected_objects)
- {
- if (ob->rigidbody_object) {
- ED_rigidbody_object_remove(bmain, scene, ob);
- changed = true;
- }
- }
- CTX_DATA_END;
-
- if (changed) {
- /* send updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ bool changed = false;
+
+ /* apply this to all selected objects... */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ if (ob->rigidbody_object) {
+ ED_rigidbody_object_remove(bmain, scene, ob);
+ changed = true;
+ }
+ }
+ CTX_DATA_END;
+
+ if (changed) {
+ /* send updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void RIGIDBODY_OT_objects_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->idname = "RIGIDBODY_OT_objects_remove";
- ot->name = "Remove Rigid Bodies";
- ot->description = "Remove selected objects from Rigid Body simulation";
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_objects_remove";
+ ot->name = "Remove Rigid Bodies";
+ ot->description = "Remove selected objects from Rigid Body simulation";
- /* callbacks */
- ot->exec = rigidbody_objects_remove_exec;
- ot->poll = ED_operator_scene_editable;
+ /* callbacks */
+ ot->exec = rigidbody_objects_remove_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************************************** */
@@ -325,64 +333,68 @@ void RIGIDBODY_OT_objects_remove(wmOperatorType *ot)
static int rigidbody_objects_shape_change_exec(bContext *C, wmOperator *op)
{
- int shape = RNA_enum_get(op->ptr, "type");
- bool changed = false;
-
- /* apply this to all selected objects... */
- CTX_DATA_BEGIN(C, Object *, ob, selected_objects)
- {
- if (ob->rigidbody_object) {
- PointerRNA ptr;
-
- /* use RNA-system to change the property and perform all necessary changes */
- RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr);
- RNA_enum_set(&ptr, "collision_shape", shape);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
-
- changed = true;
- }
- }
- CTX_DATA_END;
-
- if (changed) {
- /* send updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ int shape = RNA_enum_get(op->ptr, "type");
+ bool changed = false;
+
+ /* apply this to all selected objects... */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ if (ob->rigidbody_object) {
+ PointerRNA ptr;
+
+ /* use RNA-system to change the property and perform all necessary changes */
+ RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr);
+ RNA_enum_set(&ptr, "collision_shape", shape);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+
+ changed = true;
+ }
+ }
+ CTX_DATA_END;
+
+ if (changed) {
+ /* send updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void RIGIDBODY_OT_shape_change(wmOperatorType *ot)
{
- /* identifiers */
- ot->idname = "RIGIDBODY_OT_shape_change";
- ot->name = "Change Collision Shape";
- ot->description = "Change collision shapes for selected Rigid Body Objects";
-
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = rigidbody_objects_shape_change_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_rigidbody_object_shape_items, RB_SHAPE_TRIMESH, "Rigid Body Shape", "");
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_shape_change";
+ ot->name = "Change Collision Shape";
+ ot->description = "Change collision shapes for selected Rigid Body Objects";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = rigidbody_objects_shape_change_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna,
+ "type",
+ rna_enum_rigidbody_object_shape_items,
+ RB_SHAPE_TRIMESH,
+ "Rigid Body Shape",
+ "");
}
/* ************ Calculate Mass ************** */
/* Entry in material density table */
typedef struct rbMaterialDensityItem {
- const char *name; /* Name of material */
- float density; /* Density (kg/m^3) */
+ const char *name; /* Name of material */
+ float density; /* Density (kg/m^3) */
} rbMaterialDensityItem;
/* Preset density values for materials (kg/m^3)
@@ -392,184 +404,194 @@ typedef struct rbMaterialDensityItem {
* 3) http://www.avlandesign.com/density_metal.htm
*/
static rbMaterialDensityItem RB_MATERIAL_DENSITY_TABLE[] = {
- {N_("Air"), 1.0f}, /* not quite; adapted from 1.43 for oxygen for use as default */
- {N_("Acrylic"), 1400.0f},
- {N_("Asphalt (Crushed)"), 721.0f},
- {N_("Bark"), 240.0f},
- {N_("Beans (Cocoa)"), 593.0f},
- {N_("Beans (Soy)"), 721.0f},
- {N_("Brick (Pressed)"), 2400.0f},
- {N_("Brick (Common)"), 2000.0f},
- {N_("Brick (Soft)"), 1600.0f},
- {N_("Brass"), 8216.0f},
- {N_("Bronze"), 8860.0f},
- {N_("Carbon (Solid)"), 2146.0f},
- {N_("Cardboard"), 689.0f},
- {N_("Cast Iron"), 7150.0f},
- /* {N_("Cement"), 1442.0f}, */
- {N_("Chalk (Solid)"), 2499.0f},
- /* {N_("Coffee (Fresh/Roast)"), ~500}, */
- {N_("Concrete"), 2320.0f},
- {N_("Charcoal"), 208.0f},
- {N_("Cork"), 240.0f},
- {N_("Copper"), 8933.0f},
- {N_("Garbage"), 481.0f},
- {N_("Glass (Broken)"), 1940.0f},
- {N_("Glass (Solid)"), 2190.0f},
- {N_("Gold"), 19282.0f},
- {N_("Granite (Broken)"), 1650.0f},
- {N_("Granite (Solid)"), 2691.0f},
- {N_("Gravel"), 2780.0f},
- {N_("Ice (Crushed)"), 593.0f},
- {N_("Ice (Solid)"), 919.0f},
- {N_("Iron"), 7874.0f},
- {N_("Lead"), 11342.0f},
- {N_("Limestone (Broken)"), 1554.0f},
- {N_("Limestone (Solid)"), 2611.0f},
- {N_("Marble (Broken)"), 1570.0f},
- {N_("Marble (Solid)"), 2563.0f},
- {N_("Paper"), 1201.0f},
- {N_("Peanuts (Shelled)"), 641.0f},
- {N_("Peanuts (Not Shelled)"), 272.0f},
- {N_("Plaster"), 849.0f},
- {N_("Plastic"), 1200.0f},
- {N_("Polystyrene"), 1050.0f},
- {N_("Rubber"), 1522.0f},
- {N_("Silver"), 10501.0f},
- {N_("Steel"), 7860.0f},
- {N_("Stone"), 2515.0f},
- {N_("Stone (Crushed)"), 1602.0f},
- {N_("Timber"), 610.0f},
+ {N_("Air"), 1.0f}, /* not quite; adapted from 1.43 for oxygen for use as default */
+ {N_("Acrylic"), 1400.0f},
+ {N_("Asphalt (Crushed)"), 721.0f},
+ {N_("Bark"), 240.0f},
+ {N_("Beans (Cocoa)"), 593.0f},
+ {N_("Beans (Soy)"), 721.0f},
+ {N_("Brick (Pressed)"), 2400.0f},
+ {N_("Brick (Common)"), 2000.0f},
+ {N_("Brick (Soft)"), 1600.0f},
+ {N_("Brass"), 8216.0f},
+ {N_("Bronze"), 8860.0f},
+ {N_("Carbon (Solid)"), 2146.0f},
+ {N_("Cardboard"), 689.0f},
+ {N_("Cast Iron"), 7150.0f},
+ /* {N_("Cement"), 1442.0f}, */
+ {N_("Chalk (Solid)"), 2499.0f},
+ /* {N_("Coffee (Fresh/Roast)"), ~500}, */
+ {N_("Concrete"), 2320.0f},
+ {N_("Charcoal"), 208.0f},
+ {N_("Cork"), 240.0f},
+ {N_("Copper"), 8933.0f},
+ {N_("Garbage"), 481.0f},
+ {N_("Glass (Broken)"), 1940.0f},
+ {N_("Glass (Solid)"), 2190.0f},
+ {N_("Gold"), 19282.0f},
+ {N_("Granite (Broken)"), 1650.0f},
+ {N_("Granite (Solid)"), 2691.0f},
+ {N_("Gravel"), 2780.0f},
+ {N_("Ice (Crushed)"), 593.0f},
+ {N_("Ice (Solid)"), 919.0f},
+ {N_("Iron"), 7874.0f},
+ {N_("Lead"), 11342.0f},
+ {N_("Limestone (Broken)"), 1554.0f},
+ {N_("Limestone (Solid)"), 2611.0f},
+ {N_("Marble (Broken)"), 1570.0f},
+ {N_("Marble (Solid)"), 2563.0f},
+ {N_("Paper"), 1201.0f},
+ {N_("Peanuts (Shelled)"), 641.0f},
+ {N_("Peanuts (Not Shelled)"), 272.0f},
+ {N_("Plaster"), 849.0f},
+ {N_("Plastic"), 1200.0f},
+ {N_("Polystyrene"), 1050.0f},
+ {N_("Rubber"), 1522.0f},
+ {N_("Silver"), 10501.0f},
+ {N_("Steel"), 7860.0f},
+ {N_("Stone"), 2515.0f},
+ {N_("Stone (Crushed)"), 1602.0f},
+ {N_("Timber"), 610.0f},
};
-static const int NUM_RB_MATERIAL_PRESETS = sizeof(RB_MATERIAL_DENSITY_TABLE) / sizeof(rbMaterialDensityItem);
-
+static const int NUM_RB_MATERIAL_PRESETS = sizeof(RB_MATERIAL_DENSITY_TABLE) /
+ sizeof(rbMaterialDensityItem);
/* dynamically generate list of items
* - Although there is a runtime cost, this has a lower maintenance cost
* in the long run than other two-list solutions...
*/
-static const EnumPropertyItem *rigidbody_materials_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *rigidbody_materials_itemf(bContext *UNUSED(C),
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- EnumPropertyItem item_tmp = {0};
- EnumPropertyItem *item = NULL;
- int totitem = 0;
- int i = 0;
-
- /* add each preset to the list */
- for (i = 0; i < NUM_RB_MATERIAL_PRESETS; i++) {
- rbMaterialDensityItem *preset = &RB_MATERIAL_DENSITY_TABLE[i];
-
- item_tmp.identifier = preset->name;
- item_tmp.name = IFACE_(preset->name);
- item_tmp.value = i;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- }
-
- /* add special "custom" entry to the end of the list */
- {
- item_tmp.identifier = "Custom";
- item_tmp.name = IFACE_("Custom");
- item_tmp.value = -1;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ EnumPropertyItem item_tmp = {0};
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+ int i = 0;
+
+ /* add each preset to the list */
+ for (i = 0; i < NUM_RB_MATERIAL_PRESETS; i++) {
+ rbMaterialDensityItem *preset = &RB_MATERIAL_DENSITY_TABLE[i];
+
+ item_tmp.identifier = preset->name;
+ item_tmp.name = IFACE_(preset->name);
+ item_tmp.value = i;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
+
+ /* add special "custom" entry to the end of the list */
+ {
+ item_tmp.identifier = "Custom";
+ item_tmp.name = IFACE_("Custom");
+ item_tmp.value = -1;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
/* ------------------------------------------ */
static int rigidbody_objects_calc_mass_exec(bContext *C, wmOperator *op)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int material = RNA_enum_get(op->ptr, "material");
- float density;
- bool changed = false;
-
- /* get density (kg/m^3) to apply */
- if (material >= 0) {
- /* get density from table, and store in props for later repeating */
- if (material >= NUM_RB_MATERIAL_PRESETS)
- material = 0;
-
- density = RB_MATERIAL_DENSITY_TABLE[material].density;
- RNA_float_set(op->ptr, "density", density);
- }
- else {
- /* custom - grab from whatever value is set */
- density = RNA_float_get(op->ptr, "density");
- }
-
- /* apply this to all selected objects (with rigidbodies)... */
- CTX_DATA_BEGIN(C, Object *, ob, selected_objects)
- {
- if (ob->rigidbody_object) {
- PointerRNA ptr;
-
- float volume; /* m^3 */
- float mass; /* kg */
-
- /* mass is calculated from the approximate volume of the object,
- * and the density of the material we're simulating
- */
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- BKE_rigidbody_calc_volume(ob_eval, &volume);
- mass = volume * density;
-
- /* use RNA-system to change the property and perform all necessary changes */
- RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr);
- RNA_float_set(&ptr, "mass", mass);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
-
- changed = true;
- }
- }
- CTX_DATA_END;
-
- if (changed) {
- /* send updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int material = RNA_enum_get(op->ptr, "material");
+ float density;
+ bool changed = false;
+
+ /* get density (kg/m^3) to apply */
+ if (material >= 0) {
+ /* get density from table, and store in props for later repeating */
+ if (material >= NUM_RB_MATERIAL_PRESETS)
+ material = 0;
+
+ density = RB_MATERIAL_DENSITY_TABLE[material].density;
+ RNA_float_set(op->ptr, "density", density);
+ }
+ else {
+ /* custom - grab from whatever value is set */
+ density = RNA_float_get(op->ptr, "density");
+ }
+
+ /* apply this to all selected objects (with rigidbodies)... */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ if (ob->rigidbody_object) {
+ PointerRNA ptr;
+
+ float volume; /* m^3 */
+ float mass; /* kg */
+
+ /* mass is calculated from the approximate volume of the object,
+ * and the density of the material we're simulating
+ */
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ BKE_rigidbody_calc_volume(ob_eval, &volume);
+ mass = volume * density;
+
+ /* use RNA-system to change the property and perform all necessary changes */
+ RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr);
+ RNA_float_set(&ptr, "mass", mass);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+
+ changed = true;
+ }
+ }
+ CTX_DATA_END;
+
+ if (changed) {
+ /* send updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void RIGIDBODY_OT_mass_calculate(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->idname = "RIGIDBODY_OT_mass_calculate";
- ot->name = "Calculate Mass";
- ot->description = "Automatically calculate mass values for Rigid Body Objects based on volume";
-
- /* callbacks */
- ot->invoke = WM_menu_invoke; // XXX
- ot->exec = rigidbody_objects_calc_mass_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
-
- /* properties */
- ot->prop = prop = RNA_def_enum(ot->srna, "material",
- DummyRNA_DEFAULT_items, 0,
- "Material Preset",
- "Type of material that objects are made of (determines material density)");
- RNA_def_enum_funcs(prop, rigidbody_materials_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
-
- RNA_def_float(ot->srna, "density", 1.0, FLT_MIN, FLT_MAX,
- "Density",
- "Custom density value (kg/m^3) to use instead of material preset",
- 1.0f, 2500.0f);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_mass_calculate";
+ ot->name = "Calculate Mass";
+ ot->description = "Automatically calculate mass values for Rigid Body Objects based on volume";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke; // XXX
+ ot->exec = rigidbody_objects_calc_mass_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+
+ /* properties */
+ ot->prop = prop = RNA_def_enum(
+ ot->srna,
+ "material",
+ DummyRNA_DEFAULT_items,
+ 0,
+ "Material Preset",
+ "Type of material that objects are made of (determines material density)");
+ RNA_def_enum_funcs(prop, rigidbody_materials_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+
+ RNA_def_float(ot->srna,
+ "density",
+ 1.0,
+ FLT_MIN,
+ FLT_MAX,
+ "Density",
+ "Custom density value (kg/m^3) to use instead of material preset",
+ 1.0f,
+ 2500.0f);
}
/* ********************************************** */
diff --git a/source/blender/editors/physics/rigidbody_world.c b/source/blender/editors/physics/rigidbody_world.c
index b9049f79d0c..179a5a513f4 100644
--- a/source/blender/editors/physics/rigidbody_world.c
+++ b/source/blender/editors/physics/rigidbody_world.c
@@ -56,13 +56,13 @@
/* check if there is an active rigid body world */
static bool ED_rigidbody_world_active_poll(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- return (scene && scene->rigidbody_world);
+ Scene *scene = CTX_data_scene(C);
+ return (scene && scene->rigidbody_world);
}
static bool ED_rigidbody_world_add_poll(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- return (scene && scene->rigidbody_world == NULL);
+ Scene *scene = CTX_data_scene(C);
+ return (scene && scene->rigidbody_world == NULL);
}
/* ********************************************** */
@@ -72,73 +72,73 @@ static bool ED_rigidbody_world_add_poll(bContext *C)
static int rigidbody_world_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- RigidBodyWorld *rbw;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ RigidBodyWorld *rbw;
- rbw = BKE_rigidbody_create_world(scene);
-// BKE_rigidbody_validate_sim_world(scene, rbw, false);
- scene->rigidbody_world = rbw;
+ rbw = BKE_rigidbody_create_world(scene);
+ // BKE_rigidbody_validate_sim_world(scene, rbw, false);
+ scene->rigidbody_world = rbw;
- /* Full rebuild of DEG! */
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update_ex(bmain, &scene->id, ID_RECALC_ANIMATION);
+ /* Full rebuild of DEG! */
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update_ex(bmain, &scene->id, ID_RECALC_ANIMATION);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void RIGIDBODY_OT_world_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->idname = "RIGIDBODY_OT_world_add";
- ot->name = "Add Rigid Body World";
- ot->description = "Add Rigid Body simulation world to the current scene";
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_world_add";
+ ot->name = "Add Rigid Body World";
+ ot->description = "Add Rigid Body simulation world to the current scene";
- /* callbacks */
- ot->exec = rigidbody_world_add_exec;
- ot->poll = ED_rigidbody_world_add_poll;
+ /* callbacks */
+ ot->exec = rigidbody_world_add_exec;
+ ot->poll = ED_rigidbody_world_add_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********** Remove RigidBody World ************* */
static int rigidbody_world_remove_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- RigidBodyWorld *rbw = scene->rigidbody_world;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ RigidBodyWorld *rbw = scene->rigidbody_world;
- /* sanity checks */
- if (ELEM(NULL, scene, rbw)) {
- BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to remove");
- return OPERATOR_CANCELLED;
- }
+ /* sanity checks */
+ if (ELEM(NULL, scene, rbw)) {
+ BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to remove");
+ return OPERATOR_CANCELLED;
+ }
- BKE_rigidbody_free_world(scene);
+ BKE_rigidbody_free_world(scene);
- /* Full rebuild of DEG! */
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update_ex(bmain, &scene->id, ID_RECALC_ANIMATION);
+ /* Full rebuild of DEG! */
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update_ex(bmain, &scene->id, ID_RECALC_ANIMATION);
- /* done */
- return OPERATOR_FINISHED;
+ /* done */
+ return OPERATOR_FINISHED;
}
void RIGIDBODY_OT_world_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->idname = "RIGIDBODY_OT_world_remove";
- ot->name = "Remove Rigid Body World";
- ot->description = "Remove Rigid Body simulation world from the current scene";
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_world_remove";
+ ot->name = "Remove Rigid Body World";
+ ot->description = "Remove Rigid Body simulation world from the current scene";
- /* callbacks */
- ot->exec = rigidbody_world_remove_exec;
- ot->poll = ED_rigidbody_world_active_poll;
+ /* callbacks */
+ ot->exec = rigidbody_world_remove_exec;
+ ot->poll = ED_rigidbody_world_active_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************************************** */
@@ -148,59 +148,65 @@ void RIGIDBODY_OT_world_remove(wmOperatorType *ot)
static int rigidbody_world_export_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- RigidBodyWorld *rbw = scene->rigidbody_world;
- char path[FILE_MAX];
-
- /* sanity checks */
- if (ELEM(NULL, scene, rbw)) {
- BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to export");
- return OPERATOR_CANCELLED;
- }
- if (rbw->shared->physics_world == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Rigid Body World has no associated physics data to export");
- return OPERATOR_CANCELLED;
- }
-
- RNA_string_get(op->ptr, "filepath", path);
+ Scene *scene = CTX_data_scene(C);
+ RigidBodyWorld *rbw = scene->rigidbody_world;
+ char path[FILE_MAX];
+
+ /* sanity checks */
+ if (ELEM(NULL, scene, rbw)) {
+ BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to export");
+ return OPERATOR_CANCELLED;
+ }
+ if (rbw->shared->physics_world == NULL) {
+ BKE_report(
+ op->reports, RPT_ERROR, "Rigid Body World has no associated physics data to export");
+ return OPERATOR_CANCELLED;
+ }
+
+ RNA_string_get(op->ptr, "filepath", path);
#ifdef WITH_BULLET
- RB_dworld_export(rbw->shared->physics_world, path);
+ RB_dworld_export(rbw->shared->physics_world, path);
#endif
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int rigidbody_world_export_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (!RNA_struct_property_is_set(op->ptr, "relative_path"))
- RNA_boolean_set(op->ptr, "relative_path", (U.flag & USER_RELPATHS) != 0);
+ if (!RNA_struct_property_is_set(op->ptr, "relative_path"))
+ RNA_boolean_set(op->ptr, "relative_path", (U.flag & USER_RELPATHS) != 0);
- if (RNA_struct_property_is_set(op->ptr, "filepath"))
- return rigidbody_world_export_exec(C, op);
+ if (RNA_struct_property_is_set(op->ptr, "filepath"))
+ return rigidbody_world_export_exec(C, op);
- // TODO: use the actual rigidbody world's name + .bullet instead of this temp crap
- RNA_string_set(op->ptr, "filepath", "rigidbodyworld_export.bullet");
- WM_event_add_fileselect(C, op);
+ // TODO: use the actual rigidbody world's name + .bullet instead of this temp crap
+ RNA_string_set(op->ptr, "filepath", "rigidbodyworld_export.bullet");
+ WM_event_add_fileselect(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void RIGIDBODY_OT_world_export(wmOperatorType *ot)
{
- /* identifiers */
- ot->idname = "RIGIDBODY_OT_world_export";
- ot->name = "Export Rigid Body World";
- ot->description = "Export Rigid Body world to simulator's own fileformat (i.e. '.bullet' for Bullet Physics)";
-
- /* callbacks */
- ot->invoke = rigidbody_world_export_invoke;
- ot->exec = rigidbody_world_export_exec;
- ot->poll = ED_rigidbody_world_active_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER, FILE_SPECIAL, FILE_SAVE,
- FILE_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_world_export";
+ ot->name = "Export Rigid Body World";
+ ot->description =
+ "Export Rigid Body world to simulator's own fileformat (i.e. '.bullet' for Bullet Physics)";
+
+ /* callbacks */
+ ot->invoke = rigidbody_world_export_invoke;
+ ot->exec = rigidbody_world_export_exec;
+ ot->poll = ED_rigidbody_world_active_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER,
+ FILE_SPECIAL,
+ FILE_SAVE,
+ FILE_RELPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
}
diff --git a/source/blender/editors/render/CMakeLists.txt b/source/blender/editors/render/CMakeLists.txt
index dee56d7f2fa..5d414c3af0f 100644
--- a/source/blender/editors/render/CMakeLists.txt
+++ b/source/blender/editors/render/CMakeLists.txt
@@ -16,58 +16,58 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blenloader
- ../../blentranslation
- ../../depsgraph
- ../../draw
- ../../gpu
- ../../imbuf
- ../../bmesh
- ../../makesdna
- ../../makesrna
- ../../render/extern/include
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blenloader
+ ../../blentranslation
+ ../../depsgraph
+ ../../draw
+ ../../gpu
+ ../../imbuf
+ ../../bmesh
+ ../../makesdna
+ ../../makesrna
+ ../../render/extern/include
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- render_internal.c
- render_opengl.c
- render_ops.c
- render_preview.c
- render_shading.c
- render_update.c
- render_view.c
+ render_internal.c
+ render_opengl.c
+ render_ops.c
+ render_preview.c
+ render_shading.c
+ render_update.c
+ render_view.c
- render_intern.h
+ render_intern.h
)
set(LIB
)
if(WITH_HEADLESS)
- add_definitions(-DWITH_HEADLESS)
+ add_definitions(-DWITH_HEADLESS)
endif()
add_definitions(${GL_DEFINITIONS})
if(WITH_FREESTYLE)
- list(APPEND INC
- ../../freestyle
- )
- add_definitions(-DWITH_FREESTYLE)
+ list(APPEND INC
+ ../../freestyle
+ )
+ add_definitions(-DWITH_FREESTYLE)
endif()
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
blender_add_lib(bf_editor_render "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h
index 88f6df50420..1e03d986e3e 100644
--- a/source/blender/editors/render/render_intern.h
+++ b/source/blender/editors/render/render_intern.h
@@ -21,7 +21,6 @@
* \ingroup edrend
*/
-
#ifndef __RENDER_INTERN_H__
#define __RENDER_INTERN_H__
@@ -75,7 +74,6 @@ void SCENE_OT_freestyle_modifier_copy(struct wmOperatorType *ot);
void SCENE_OT_freestyle_stroke_material_create(struct wmOperatorType *ot);
#endif
-
void TEXTURE_OT_slot_copy(struct wmOperatorType *ot);
void TEXTURE_OT_slot_paste(struct wmOperatorType *ot);
void TEXTURE_OT_slot_move(struct wmOperatorType *ot);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index b5546bd7b90..6df1ba5e0aa 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -21,7 +21,6 @@
* \ingroup edrend
*/
-
#include <math.h>
#include <string.h>
#include <stddef.h>
@@ -92,160 +91,175 @@
static int render_break(void *rjv);
typedef struct RenderJob {
- Main *main;
- Scene *scene;
- ViewLayer *single_layer;
- Scene *current_scene;
- /* TODO(sergey): Should not be needed once engine will have own
- * depsgraph and copy-on-write will be implemented.
- */
- Depsgraph *depsgraph;
- Render *re;
- struct Object *camera_override;
- bool v3d_override;
- bool anim, write_still;
- Image *image;
- ImageUser iuser;
- bool image_outdated;
- short *stop;
- short *do_update;
- float *progress;
- ReportList *reports;
- int orig_layer;
- int last_layer;
- ScrArea *sa;
- ColorManagedViewSettings view_settings;
- ColorManagedDisplaySettings display_settings;
- bool supports_glsl_draw;
- bool interface_locked;
+ Main *main;
+ Scene *scene;
+ ViewLayer *single_layer;
+ Scene *current_scene;
+ /* TODO(sergey): Should not be needed once engine will have own
+ * depsgraph and copy-on-write will be implemented.
+ */
+ Depsgraph *depsgraph;
+ Render *re;
+ struct Object *camera_override;
+ bool v3d_override;
+ bool anim, write_still;
+ Image *image;
+ ImageUser iuser;
+ bool image_outdated;
+ short *stop;
+ short *do_update;
+ float *progress;
+ ReportList *reports;
+ int orig_layer;
+ int last_layer;
+ ScrArea *sa;
+ ColorManagedViewSettings view_settings;
+ ColorManagedDisplaySettings display_settings;
+ bool supports_glsl_draw;
+ bool interface_locked;
} RenderJob;
/* called inside thread! */
-static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibuf, ImageUser *iuser, volatile rcti *renrect, const char *viewname)
+static void image_buffer_rect_update(RenderJob *rj,
+ RenderResult *rr,
+ ImBuf *ibuf,
+ ImageUser *iuser,
+ volatile rcti *renrect,
+ const char *viewname)
{
- Scene *scene = rj->scene;
- const float *rectf = NULL;
- int ymin, ymax, xmin, xmax;
- int rymin, rxmin;
- int linear_stride, linear_offset_x, linear_offset_y;
- ColorManagedViewSettings *view_settings;
- ColorManagedDisplaySettings *display_settings;
-
- /* Exception for exr tiles -- display buffer conversion happens here,
- * NOT in the color management pipeline.
- */
- if (ibuf->userflags & IB_DISPLAY_BUFFER_INVALID &&
- rr->do_exr_tile == false)
- {
- /* The whole image buffer it so be color managed again anyway. */
- return;
- }
-
- /* if renrect argument, we only refresh scanlines */
- if (renrect) {
- /* if (ymax == recty), rendering of layer is ready,
- * we should not draw, other things happen... */
- if (rr->renlay == NULL || renrect->ymax >= rr->recty)
- return;
-
- /* xmin here is first subrect x coord, xmax defines subrect width */
- xmin = renrect->xmin + rr->crop;
- xmax = renrect->xmax - xmin + rr->crop;
- if (xmax < 2)
- return;
-
- ymin = renrect->ymin + rr->crop;
- ymax = renrect->ymax - ymin + rr->crop;
- if (ymax < 2)
- return;
- renrect->ymin = renrect->ymax;
-
- }
- else {
- xmin = ymin = rr->crop;
- xmax = rr->rectx - 2 * rr->crop;
- ymax = rr->recty - 2 * rr->crop;
- }
-
- /* xmin ymin is in tile coords. transform to ibuf */
- rxmin = rr->tilerect.xmin + xmin;
- if (rxmin >= ibuf->x) return;
- rymin = rr->tilerect.ymin + ymin;
- if (rymin >= ibuf->y) return;
-
- if (rxmin + xmax > ibuf->x)
- xmax = ibuf->x - rxmin;
- if (rymin + ymax > ibuf->y)
- ymax = ibuf->y - rymin;
-
- if (xmax < 1 || ymax < 1) return;
-
- /* The thing here is, the logic below (which was default behavior
- * of how rectf is acquiring since forever) gives float buffer for
- * composite output only. This buffer can not be used for other
- * passes obviously.
- *
- * We might try finding corresponding for pass buffer in render result
- * (which is actually missing when rendering with Cycles, who only
- * writes all the passes when the tile is finished) or use float
- * buffer from image buffer as reference, which is easier to use and
- * contains all the data we need anyway.
- * - sergey -
- */
- /* TODO(sergey): Need to check has_combined here? */
- if (iuser->pass == 0) {
- RenderView *rv;
- const int view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
- rv = RE_RenderViewGetById(rr, view_id);
-
- /* find current float rect for display, first case is after composite... still weak */
- if (rv->rectf)
- rectf = rv->rectf;
- else {
- if (rv->rect32) {
- /* special case, currently only happens with sequencer rendering,
- * which updates the whole frame, so we can only mark display buffer
- * as invalid here (sergey)
- */
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
- return;
- }
- else {
- if (rr->renlay == NULL) return;
- rectf = RE_RenderLayerGetPass(rr->renlay, RE_PASSNAME_COMBINED, viewname);
- }
- }
- if (rectf == NULL) return;
-
- rectf += 4 * (rr->rectx * ymin + xmin);
- linear_stride = rr->rectx;
- linear_offset_x = rxmin;
- linear_offset_y = rymin;
- }
- else {
- rectf = ibuf->rect_float;
- linear_stride = ibuf->x;
- linear_offset_x = 0;
- linear_offset_y = 0;
- }
-
- if (rr->do_exr_tile) {
- /* We don't support changing color management settings during rendering
- * when using Save Buffers option.
- */
- view_settings = &rj->view_settings;
- display_settings = &rj->display_settings;
- }
- else {
- view_settings = &scene->view_settings;
- display_settings = &scene->display_settings;
- }
-
- IMB_partial_display_buffer_update(ibuf, rectf, NULL,
- linear_stride, linear_offset_x, linear_offset_y,
- view_settings, display_settings,
- rxmin, rymin, rxmin + xmax, rymin + ymax,
- rr->do_exr_tile);
+ Scene *scene = rj->scene;
+ const float *rectf = NULL;
+ int ymin, ymax, xmin, xmax;
+ int rymin, rxmin;
+ int linear_stride, linear_offset_x, linear_offset_y;
+ ColorManagedViewSettings *view_settings;
+ ColorManagedDisplaySettings *display_settings;
+
+ /* Exception for exr tiles -- display buffer conversion happens here,
+ * NOT in the color management pipeline.
+ */
+ if (ibuf->userflags & IB_DISPLAY_BUFFER_INVALID && rr->do_exr_tile == false) {
+ /* The whole image buffer it so be color managed again anyway. */
+ return;
+ }
+
+ /* if renrect argument, we only refresh scanlines */
+ if (renrect) {
+ /* if (ymax == recty), rendering of layer is ready,
+ * we should not draw, other things happen... */
+ if (rr->renlay == NULL || renrect->ymax >= rr->recty)
+ return;
+
+ /* xmin here is first subrect x coord, xmax defines subrect width */
+ xmin = renrect->xmin + rr->crop;
+ xmax = renrect->xmax - xmin + rr->crop;
+ if (xmax < 2)
+ return;
+
+ ymin = renrect->ymin + rr->crop;
+ ymax = renrect->ymax - ymin + rr->crop;
+ if (ymax < 2)
+ return;
+ renrect->ymin = renrect->ymax;
+ }
+ else {
+ xmin = ymin = rr->crop;
+ xmax = rr->rectx - 2 * rr->crop;
+ ymax = rr->recty - 2 * rr->crop;
+ }
+
+ /* xmin ymin is in tile coords. transform to ibuf */
+ rxmin = rr->tilerect.xmin + xmin;
+ if (rxmin >= ibuf->x)
+ return;
+ rymin = rr->tilerect.ymin + ymin;
+ if (rymin >= ibuf->y)
+ return;
+
+ if (rxmin + xmax > ibuf->x)
+ xmax = ibuf->x - rxmin;
+ if (rymin + ymax > ibuf->y)
+ ymax = ibuf->y - rymin;
+
+ if (xmax < 1 || ymax < 1)
+ return;
+
+ /* The thing here is, the logic below (which was default behavior
+ * of how rectf is acquiring since forever) gives float buffer for
+ * composite output only. This buffer can not be used for other
+ * passes obviously.
+ *
+ * We might try finding corresponding for pass buffer in render result
+ * (which is actually missing when rendering with Cycles, who only
+ * writes all the passes when the tile is finished) or use float
+ * buffer from image buffer as reference, which is easier to use and
+ * contains all the data we need anyway.
+ * - sergey -
+ */
+ /* TODO(sergey): Need to check has_combined here? */
+ if (iuser->pass == 0) {
+ RenderView *rv;
+ const int view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
+ rv = RE_RenderViewGetById(rr, view_id);
+
+ /* find current float rect for display, first case is after composite... still weak */
+ if (rv->rectf)
+ rectf = rv->rectf;
+ else {
+ if (rv->rect32) {
+ /* special case, currently only happens with sequencer rendering,
+ * which updates the whole frame, so we can only mark display buffer
+ * as invalid here (sergey)
+ */
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ return;
+ }
+ else {
+ if (rr->renlay == NULL)
+ return;
+ rectf = RE_RenderLayerGetPass(rr->renlay, RE_PASSNAME_COMBINED, viewname);
+ }
+ }
+ if (rectf == NULL)
+ return;
+
+ rectf += 4 * (rr->rectx * ymin + xmin);
+ linear_stride = rr->rectx;
+ linear_offset_x = rxmin;
+ linear_offset_y = rymin;
+ }
+ else {
+ rectf = ibuf->rect_float;
+ linear_stride = ibuf->x;
+ linear_offset_x = 0;
+ linear_offset_y = 0;
+ }
+
+ if (rr->do_exr_tile) {
+ /* We don't support changing color management settings during rendering
+ * when using Save Buffers option.
+ */
+ view_settings = &rj->view_settings;
+ display_settings = &rj->display_settings;
+ }
+ else {
+ view_settings = &scene->view_settings;
+ display_settings = &scene->display_settings;
+ }
+
+ IMB_partial_display_buffer_update(ibuf,
+ rectf,
+ NULL,
+ linear_stride,
+ linear_offset_x,
+ linear_offset_y,
+ view_settings,
+ display_settings,
+ rxmin,
+ rymin,
+ rxmin + xmax,
+ rymin + ymax,
+ rr->do_exr_tile);
}
/* ****************************** render invoking ***************** */
@@ -253,108 +267,118 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu
/* set callbacks, exported to sequence render too.
* Only call in foreground (UI) renders. */
-static void screen_render_single_layer_set(wmOperator *op, Main *mainp, ViewLayer *active_layer, Scene **scene, ViewLayer **single_layer)
+static void screen_render_single_layer_set(
+ wmOperator *op, Main *mainp, ViewLayer *active_layer, Scene **scene, ViewLayer **single_layer)
{
- /* single layer re-render */
- if (RNA_struct_property_is_set(op->ptr, "scene")) {
- Scene *scn;
- char scene_name[MAX_ID_NAME - 2];
-
- RNA_string_get(op->ptr, "scene", scene_name);
- scn = (Scene *)BLI_findstring(&mainp->scenes, scene_name, offsetof(ID, name) + 2);
-
- if (scn) {
- /* camera switch wont have updated */
- scn->r.cfra = (*scene)->r.cfra;
- BKE_scene_camera_switch_update(scn);
-
- *scene = scn;
- }
- }
-
- if (RNA_struct_property_is_set(op->ptr, "layer")) {
- ViewLayer *rl;
- char rl_name[RE_MAXNAME];
-
- RNA_string_get(op->ptr, "layer", rl_name);
- rl = (ViewLayer *)BLI_findstring(&(*scene)->view_layers, rl_name, offsetof(ViewLayer, name));
-
- if (rl)
- *single_layer = rl;
- }
- else if (((*scene)->r.scemode & R_SINGLE_LAYER) && active_layer) {
- *single_layer = active_layer;
- }
+ /* single layer re-render */
+ if (RNA_struct_property_is_set(op->ptr, "scene")) {
+ Scene *scn;
+ char scene_name[MAX_ID_NAME - 2];
+
+ RNA_string_get(op->ptr, "scene", scene_name);
+ scn = (Scene *)BLI_findstring(&mainp->scenes, scene_name, offsetof(ID, name) + 2);
+
+ if (scn) {
+ /* camera switch wont have updated */
+ scn->r.cfra = (*scene)->r.cfra;
+ BKE_scene_camera_switch_update(scn);
+
+ *scene = scn;
+ }
+ }
+
+ if (RNA_struct_property_is_set(op->ptr, "layer")) {
+ ViewLayer *rl;
+ char rl_name[RE_MAXNAME];
+
+ RNA_string_get(op->ptr, "layer", rl_name);
+ rl = (ViewLayer *)BLI_findstring(&(*scene)->view_layers, rl_name, offsetof(ViewLayer, name));
+
+ if (rl)
+ *single_layer = rl;
+ }
+ else if (((*scene)->r.scemode & R_SINGLE_LAYER) && active_layer) {
+ *single_layer = active_layer;
+ }
}
/* executes blocking render */
static int screen_render_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- RenderEngineType *re_type = RE_engines_find(scene->r.engine);
- ViewLayer *active_layer = CTX_data_view_layer(C);
- ViewLayer *single_layer = NULL;
- Render *re;
- Image *ima;
- View3D *v3d = CTX_wm_view3d(C);
- Main *mainp = CTX_data_main(C);
- const bool is_animation = RNA_boolean_get(op->ptr, "animation");
- const bool is_write_still = RNA_boolean_get(op->ptr, "write_still");
- struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
-
- /* Cannot do render if there is not this function. */
- if (re_type->render == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- /* custom scene and single layer re-render */
- screen_render_single_layer_set(op, mainp, active_layer, &scene, &single_layer);
-
- if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected");
- return OPERATOR_CANCELLED;
- }
-
- re = RE_NewSceneRender(scene);
-
- G.is_break = false;
- RE_test_break_cb(re, NULL, render_break);
-
- ima = BKE_image_verify_viewer(mainp, IMA_TYPE_R_RESULT, "Render Result");
- BKE_image_signal(mainp, ima, NULL, IMA_SIGNAL_FREE);
- BKE_image_backup_render(scene, ima, true);
-
- /* cleanup sequencer caches before starting user triggered render.
- * otherwise, invalidated cache entries can make their way into
- * the output rendering. We can't put that into RE_BlenderFrame,
- * since sequence rendering can call that recursively... (peter) */
- BKE_sequencer_cache_cleanup();
-
- RE_SetReports(re, op->reports);
-
- BLI_threaded_malloc_begin();
- if (is_animation)
- RE_BlenderAnim(re, mainp, scene, single_layer, camera_override, scene->r.sfra, scene->r.efra, scene->r.frame_step);
- else
- RE_BlenderFrame(re, mainp, scene, single_layer, camera_override, scene->r.cfra, is_write_still);
- BLI_threaded_malloc_end();
-
- RE_SetReports(re, NULL);
-
- // no redraw needed, we leave state as we entered it
- ED_update_for_newframe(mainp, CTX_data_depsgraph(C));
-
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ RenderEngineType *re_type = RE_engines_find(scene->r.engine);
+ ViewLayer *active_layer = CTX_data_view_layer(C);
+ ViewLayer *single_layer = NULL;
+ Render *re;
+ Image *ima;
+ View3D *v3d = CTX_wm_view3d(C);
+ Main *mainp = CTX_data_main(C);
+ const bool is_animation = RNA_boolean_get(op->ptr, "animation");
+ const bool is_write_still = RNA_boolean_get(op->ptr, "write_still");
+ struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
+
+ /* Cannot do render if there is not this function. */
+ if (re_type->render == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* custom scene and single layer re-render */
+ screen_render_single_layer_set(op, mainp, active_layer, &scene, &single_layer);
+
+ if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) {
+ BKE_report(
+ op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected");
+ return OPERATOR_CANCELLED;
+ }
+
+ re = RE_NewSceneRender(scene);
+
+ G.is_break = false;
+ RE_test_break_cb(re, NULL, render_break);
+
+ ima = BKE_image_verify_viewer(mainp, IMA_TYPE_R_RESULT, "Render Result");
+ BKE_image_signal(mainp, ima, NULL, IMA_SIGNAL_FREE);
+ BKE_image_backup_render(scene, ima, true);
+
+ /* cleanup sequencer caches before starting user triggered render.
+ * otherwise, invalidated cache entries can make their way into
+ * the output rendering. We can't put that into RE_BlenderFrame,
+ * since sequence rendering can call that recursively... (peter) */
+ BKE_sequencer_cache_cleanup();
+
+ RE_SetReports(re, op->reports);
+
+ BLI_threaded_malloc_begin();
+ if (is_animation)
+ RE_BlenderAnim(re,
+ mainp,
+ scene,
+ single_layer,
+ camera_override,
+ scene->r.sfra,
+ scene->r.efra,
+ scene->r.frame_step);
+ else
+ RE_BlenderFrame(
+ re, mainp, scene, single_layer, camera_override, scene->r.cfra, is_write_still);
+ BLI_threaded_malloc_end();
+
+ RE_SetReports(re, NULL);
+
+ // no redraw needed, we leave state as we entered it
+ ED_update_for_newframe(mainp, CTX_data_depsgraph(C));
+
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
+
+ return OPERATOR_FINISHED;
}
static void render_freejob(void *rjv)
{
- RenderJob *rj = rjv;
+ RenderJob *rj = rjv;
- BKE_color_managed_view_settings_free(&rj->view_settings);
- MEM_freeN(rj);
+ BKE_color_managed_view_settings_free(&rj->view_settings);
+ MEM_freeN(rj);
}
/* str is IMA_MAX_RENDER_TEXT in size */
@@ -364,124 +388,130 @@ static void make_renderinfo_string(const RenderStats *rs,
const char *error,
char *str)
{
- char info_time_str[32]; // used to be extern to header_info.c
- uintptr_t mem_in_use, mmap_in_use, peak_memory;
- float megs_used_memory, mmap_used_memory, megs_peak_memory;
- char *spos = str;
-
- mem_in_use = MEM_get_memory_in_use();
- mmap_in_use = MEM_get_mapped_memory_in_use();
- peak_memory = MEM_get_peak_memory();
-
- megs_used_memory = (mem_in_use - mmap_in_use) / (1024.0 * 1024.0);
- mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0);
- megs_peak_memory = (peak_memory) / (1024.0 * 1024.0);
-
- /* local view */
- if (rs->localview)
- spos += sprintf(spos, "%s | ", IFACE_("3D Local View"));
- else if (v3d_override)
- spos += sprintf(spos, "%s | ", IFACE_("3D View"));
-
- /* frame number */
- spos += sprintf(spos, IFACE_("Frame:%d "), (scene->r.cfra));
-
- /* previous and elapsed time */
- BLI_timecode_string_from_time_simple(info_time_str, sizeof(info_time_str), rs->lastframetime);
-
- if (rs->infostr && rs->infostr[0]) {
- if (rs->lastframetime != 0.0)
- spos += sprintf(spos, IFACE_("| Last:%s "), info_time_str);
- else
- spos += sprintf(spos, "| ");
-
- BLI_timecode_string_from_time_simple(info_time_str, sizeof(info_time_str), PIL_check_seconds_timer() - rs->starttime);
- }
- else
- spos += sprintf(spos, "| ");
-
- spos += sprintf(spos, IFACE_("Time:%s "), info_time_str);
-
- /* statistics */
- if (rs->statstr) {
- if (rs->statstr[0]) {
- spos += sprintf(spos, "| %s ", rs->statstr);
- }
- }
- else {
- if (rs->totvert || rs->totface || rs->tothalo || rs->totstrand || rs->totlamp)
- spos += sprintf(spos, "| ");
-
- if (rs->totvert) spos += sprintf(spos, IFACE_("Ve:%d "), rs->totvert);
- if (rs->totface) spos += sprintf(spos, IFACE_("Fa:%d "), rs->totface);
- if (rs->tothalo) spos += sprintf(spos, IFACE_("Ha:%d "), rs->tothalo);
- if (rs->totstrand) spos += sprintf(spos, IFACE_("St:%d "), rs->totstrand);
- if (rs->totlamp) spos += sprintf(spos, IFACE_("Li:%d "), rs->totlamp);
-
- if (rs->mem_peak == 0.0f)
- spos += sprintf(spos, IFACE_("| Mem:%.2fM (%.2fM, Peak %.2fM) "),
- megs_used_memory, mmap_used_memory, megs_peak_memory);
- else
- spos += sprintf(spos, IFACE_("| Mem:%.2fM, Peak: %.2fM "), rs->mem_used, rs->mem_peak);
-
- if (rs->curfield)
- spos += sprintf(spos, IFACE_("Field %d "), rs->curfield);
- if (rs->curblur)
- spos += sprintf(spos, IFACE_("Blur %d "), rs->curblur);
- }
-
- /* full sample */
- if (rs->curfsa)
- spos += sprintf(spos, IFACE_("| Full Sample %d "), rs->curfsa);
-
- /* extra info */
- if (rs->infostr && rs->infostr[0]) {
- spos += sprintf(spos, "| %s ", rs->infostr);
- }
- else if (error && error[0]) {
- spos += sprintf(spos, "| %s ", error);
- }
-
- /* very weak... but 512 characters is quite safe */
- if (spos >= str + IMA_MAX_RENDER_TEXT)
- if (G.debug & G_DEBUG)
- printf("WARNING! renderwin text beyond limit\n");
-
+ char info_time_str[32]; // used to be extern to header_info.c
+ uintptr_t mem_in_use, mmap_in_use, peak_memory;
+ float megs_used_memory, mmap_used_memory, megs_peak_memory;
+ char *spos = str;
+
+ mem_in_use = MEM_get_memory_in_use();
+ mmap_in_use = MEM_get_mapped_memory_in_use();
+ peak_memory = MEM_get_peak_memory();
+
+ megs_used_memory = (mem_in_use - mmap_in_use) / (1024.0 * 1024.0);
+ mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0);
+ megs_peak_memory = (peak_memory) / (1024.0 * 1024.0);
+
+ /* local view */
+ if (rs->localview)
+ spos += sprintf(spos, "%s | ", IFACE_("3D Local View"));
+ else if (v3d_override)
+ spos += sprintf(spos, "%s | ", IFACE_("3D View"));
+
+ /* frame number */
+ spos += sprintf(spos, IFACE_("Frame:%d "), (scene->r.cfra));
+
+ /* previous and elapsed time */
+ BLI_timecode_string_from_time_simple(info_time_str, sizeof(info_time_str), rs->lastframetime);
+
+ if (rs->infostr && rs->infostr[0]) {
+ if (rs->lastframetime != 0.0)
+ spos += sprintf(spos, IFACE_("| Last:%s "), info_time_str);
+ else
+ spos += sprintf(spos, "| ");
+
+ BLI_timecode_string_from_time_simple(
+ info_time_str, sizeof(info_time_str), PIL_check_seconds_timer() - rs->starttime);
+ }
+ else
+ spos += sprintf(spos, "| ");
+
+ spos += sprintf(spos, IFACE_("Time:%s "), info_time_str);
+
+ /* statistics */
+ if (rs->statstr) {
+ if (rs->statstr[0]) {
+ spos += sprintf(spos, "| %s ", rs->statstr);
+ }
+ }
+ else {
+ if (rs->totvert || rs->totface || rs->tothalo || rs->totstrand || rs->totlamp)
+ spos += sprintf(spos, "| ");
+
+ if (rs->totvert)
+ spos += sprintf(spos, IFACE_("Ve:%d "), rs->totvert);
+ if (rs->totface)
+ spos += sprintf(spos, IFACE_("Fa:%d "), rs->totface);
+ if (rs->tothalo)
+ spos += sprintf(spos, IFACE_("Ha:%d "), rs->tothalo);
+ if (rs->totstrand)
+ spos += sprintf(spos, IFACE_("St:%d "), rs->totstrand);
+ if (rs->totlamp)
+ spos += sprintf(spos, IFACE_("Li:%d "), rs->totlamp);
+
+ if (rs->mem_peak == 0.0f)
+ spos += sprintf(spos,
+ IFACE_("| Mem:%.2fM (%.2fM, Peak %.2fM) "),
+ megs_used_memory,
+ mmap_used_memory,
+ megs_peak_memory);
+ else
+ spos += sprintf(spos, IFACE_("| Mem:%.2fM, Peak: %.2fM "), rs->mem_used, rs->mem_peak);
+
+ if (rs->curfield)
+ spos += sprintf(spos, IFACE_("Field %d "), rs->curfield);
+ if (rs->curblur)
+ spos += sprintf(spos, IFACE_("Blur %d "), rs->curblur);
+ }
+
+ /* full sample */
+ if (rs->curfsa)
+ spos += sprintf(spos, IFACE_("| Full Sample %d "), rs->curfsa);
+
+ /* extra info */
+ if (rs->infostr && rs->infostr[0]) {
+ spos += sprintf(spos, "| %s ", rs->infostr);
+ }
+ else if (error && error[0]) {
+ spos += sprintf(spos, "| %s ", error);
+ }
+
+ /* very weak... but 512 characters is quite safe */
+ if (spos >= str + IMA_MAX_RENDER_TEXT)
+ if (G.debug & G_DEBUG)
+ printf("WARNING! renderwin text beyond limit\n");
}
static void image_renderinfo_cb(void *rjv, RenderStats *rs)
{
- RenderJob *rj = rjv;
- RenderResult *rr;
-
- rr = RE_AcquireResultRead(rj->re);
+ RenderJob *rj = rjv;
+ RenderResult *rr;
- if (rr) {
- /* malloc OK here, stats_draw is not in tile threads */
- if (rr->text == NULL)
- rr->text = MEM_callocN(IMA_MAX_RENDER_TEXT, "rendertext");
+ rr = RE_AcquireResultRead(rj->re);
- make_renderinfo_string(rs, rj->scene, rj->v3d_override,
- rr->error, rr->text);
- }
+ if (rr) {
+ /* malloc OK here, stats_draw is not in tile threads */
+ if (rr->text == NULL)
+ rr->text = MEM_callocN(IMA_MAX_RENDER_TEXT, "rendertext");
- RE_ReleaseResult(rj->re);
+ make_renderinfo_string(rs, rj->scene, rj->v3d_override, rr->error, rr->text);
+ }
- /* make jobs timer to send notifier */
- *(rj->do_update) = true;
+ RE_ReleaseResult(rj->re);
+ /* make jobs timer to send notifier */
+ *(rj->do_update) = true;
}
static void render_progress_update(void *rjv, float progress)
{
- RenderJob *rj = rjv;
+ RenderJob *rj = rjv;
- if (rj->progress && *rj->progress != progress) {
- *rj->progress = progress;
+ if (rj->progress && *rj->progress != progress) {
+ *rj->progress = progress;
- /* make jobs timer to send notifier */
- *(rj->do_update) = true;
- }
+ /* make jobs timer to send notifier */
+ *(rj->do_update) = true;
+ }
}
/* Not totally reliable, but works fine in most of cases and
@@ -491,615 +521,645 @@ 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;
-
- /* image window, compo node users */
- for (wm = rj->main->wm.first; wm && matched_sa == NULL; wm = wm->id.next) { /* only 1 wm */
- wmWindow *win;
- for (win = wm->windows.first; win && matched_sa == 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.
- if (sima != NULL && sima->image == rj->image) {
- if (first_sa == NULL) {
- first_sa = sa;
- }
- if (sa == rj->sa) {
- matched_sa = sa;
- break;
- }
- }
- }
- }
- }
- }
-
- if (matched_sa == NULL) {
- matched_sa = first_sa;
- }
-
- if (matched_sa) {
- SpaceImage *sima = matched_sa->spacedata.first;
- RenderResult *main_rr = RE_AcquireResultRead(rj->re);
-
- /* TODO(sergey): is there faster way to get the layer index? */
- if (rr->renlay) {
- int layer = BLI_findstringindex(&main_rr->layers,
- (char *)rr->renlay->name,
- offsetof(RenderLayer, name));
- sima->iuser.layer = layer;
- rj->last_layer = layer;
- }
-
- iuser->pass = sima->iuser.pass;
- iuser->layer = sima->iuser.layer;
-
- RE_ReleaseResult(rj->re);
- }
+ wmWindowManager *wm;
+ ScrArea *first_sa = NULL, *matched_sa = NULL;
+
+ /* image window, compo node users */
+ for (wm = rj->main->wm.first; wm && matched_sa == NULL; wm = wm->id.next) { /* only 1 wm */
+ wmWindow *win;
+ for (win = wm->windows.first; win && matched_sa == 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.
+ if (sima != NULL && sima->image == rj->image) {
+ if (first_sa == NULL) {
+ first_sa = sa;
+ }
+ if (sa == rj->sa) {
+ matched_sa = sa;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (matched_sa == NULL) {
+ matched_sa = first_sa;
+ }
+
+ if (matched_sa) {
+ SpaceImage *sima = matched_sa->spacedata.first;
+ RenderResult *main_rr = RE_AcquireResultRead(rj->re);
+
+ /* TODO(sergey): is there faster way to get the layer index? */
+ if (rr->renlay) {
+ int layer = BLI_findstringindex(
+ &main_rr->layers, (char *)rr->renlay->name, offsetof(RenderLayer, name));
+ sima->iuser.layer = layer;
+ rj->last_layer = layer;
+ }
+
+ iuser->pass = sima->iuser.pass;
+ iuser->layer = sima->iuser.layer;
+
+ RE_ReleaseResult(rj->re);
+ }
}
static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrect)
{
- RenderJob *rj = rjv;
- Image *ima = rj->image;
- ImBuf *ibuf;
- void *lock;
- const char *viewname = RE_GetActiveRenderView(rj->re);
-
- /* only update if we are displaying the slot being rendered */
- if (ima->render_slot != ima->last_render_slot) {
- rj->image_outdated = true;
- return;
- }
- else if (rj->image_outdated) {
- /* update entire render */
- rj->image_outdated = false;
- BKE_image_signal(rj->main, ima, NULL, IMA_SIGNAL_COLORMANAGE);
- *(rj->do_update) = true;
- return;
- }
-
- if (rr == NULL)
- return;
-
- /* update part of render */
- render_image_update_pass_and_layer(rj, rr, &rj->iuser);
- ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
- if (ibuf) {
- /* Don't waste time on CPU side color management if
- * image will be displayed using GLSL.
- *
- * Need to update rect if Save Buffers enabled because in
- * this case GLSL doesn't have original float buffer to
- * operate with.
- */
- if (rr->do_exr_tile ||
- !rj->supports_glsl_draw ||
- ibuf->channels == 1 ||
- U.image_draw_method != IMAGE_DRAW_METHOD_GLSL)
- {
- image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, renrect, viewname);
- }
-
- /* make jobs timer to send notifier */
- *(rj->do_update) = true;
- }
- BKE_image_release_ibuf(ima, ibuf, lock);
+ RenderJob *rj = rjv;
+ Image *ima = rj->image;
+ ImBuf *ibuf;
+ void *lock;
+ const char *viewname = RE_GetActiveRenderView(rj->re);
+
+ /* only update if we are displaying the slot being rendered */
+ if (ima->render_slot != ima->last_render_slot) {
+ rj->image_outdated = true;
+ return;
+ }
+ else if (rj->image_outdated) {
+ /* update entire render */
+ rj->image_outdated = false;
+ BKE_image_signal(rj->main, ima, NULL, IMA_SIGNAL_COLORMANAGE);
+ *(rj->do_update) = true;
+ return;
+ }
+
+ if (rr == NULL)
+ return;
+
+ /* update part of render */
+ render_image_update_pass_and_layer(rj, rr, &rj->iuser);
+ ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
+ if (ibuf) {
+ /* Don't waste time on CPU side color management if
+ * image will be displayed using GLSL.
+ *
+ * Need to update rect if Save Buffers enabled because in
+ * this case GLSL doesn't have original float buffer to
+ * operate with.
+ */
+ if (rr->do_exr_tile || !rj->supports_glsl_draw || ibuf->channels == 1 ||
+ U.image_draw_method != IMAGE_DRAW_METHOD_GLSL) {
+ image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, renrect, viewname);
+ }
+
+ /* make jobs timer to send notifier */
+ *(rj->do_update) = true;
+ }
+ BKE_image_release_ibuf(ima, ibuf, lock);
}
static void current_scene_update(void *rjv, Scene *scene)
{
- RenderJob *rj = rjv;
- rj->current_scene = scene;
- rj->iuser.scene = scene;
+ RenderJob *rj = rjv;
+ rj->current_scene = scene;
+ rj->iuser.scene = scene;
}
static void render_startjob(void *rjv, short *stop, short *do_update, float *progress)
{
- RenderJob *rj = rjv;
-
- rj->stop = stop;
- rj->do_update = do_update;
- rj->progress = progress;
-
- RE_SetReports(rj->re, rj->reports);
-
- if (rj->anim)
- RE_BlenderAnim(rj->re, rj->main, rj->scene, rj->single_layer, rj->camera_override, rj->scene->r.sfra, rj->scene->r.efra, rj->scene->r.frame_step);
- else
- RE_BlenderFrame(rj->re, rj->main, rj->scene, rj->single_layer, rj->camera_override, rj->scene->r.cfra, rj->write_still);
-
- RE_SetReports(rj->re, NULL);
+ RenderJob *rj = rjv;
+
+ rj->stop = stop;
+ rj->do_update = do_update;
+ rj->progress = progress;
+
+ RE_SetReports(rj->re, rj->reports);
+
+ if (rj->anim)
+ RE_BlenderAnim(rj->re,
+ rj->main,
+ rj->scene,
+ rj->single_layer,
+ rj->camera_override,
+ rj->scene->r.sfra,
+ rj->scene->r.efra,
+ rj->scene->r.frame_step);
+ else
+ RE_BlenderFrame(rj->re,
+ rj->main,
+ rj->scene,
+ rj->single_layer,
+ rj->camera_override,
+ rj->scene->r.cfra,
+ rj->write_still);
+
+ RE_SetReports(rj->re, NULL);
}
static void render_image_restore_layer(RenderJob *rj)
{
- wmWindowManager *wm;
-
- /* image window, compo node users */
- for (wm = rj->main->wm.first; wm; wm = wm->id.next) { /* only 1 wm */
- wmWindow *win;
- 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;
-
- if (RE_HasSingleLayer(rj->re)) {
- /* For single layer renders keep the active layer
- * visible, or show the compositing result. */
- RenderResult *rr = RE_AcquireResultRead(rj->re);
- if (RE_HasCombinedLayer(rr)) {
- sima->iuser.layer = 0;
- }
- RE_ReleaseResult(rj->re);
- }
- else {
- /* For multiple layer render, set back the layer
- * that was set at the start of rendering. */
- sima->iuser.layer = rj->orig_layer;
- }
- }
- return;
- }
- }
- }
- }
+ wmWindowManager *wm;
+
+ /* image window, compo node users */
+ for (wm = rj->main->wm.first; wm; wm = wm->id.next) { /* only 1 wm */
+ wmWindow *win;
+ 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;
+
+ if (RE_HasSingleLayer(rj->re)) {
+ /* For single layer renders keep the active layer
+ * visible, or show the compositing result. */
+ RenderResult *rr = RE_AcquireResultRead(rj->re);
+ if (RE_HasCombinedLayer(rr)) {
+ sima->iuser.layer = 0;
+ }
+ RE_ReleaseResult(rj->re);
+ }
+ else {
+ /* For multiple layer render, set back the layer
+ * that was set at the start of rendering. */
+ sima->iuser.layer = rj->orig_layer;
+ }
+ }
+ return;
+ }
+ }
+ }
+ }
}
static void render_endjob(void *rjv)
{
- RenderJob *rj = rjv;
-
- /* this render may be used again by the sequencer without the active
- * 'Render' where the callbacks would be re-assigned. assign dummy callbacks
- * to avoid referencing freed renderjobs bug T24508. */
- RE_InitRenderCB(rj->re);
-
- if (rj->main != G_MAIN)
- BKE_main_free(rj->main);
-
- /* else the frame will not update for the original value */
- if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) {
- /* possible this fails of loading new file while rendering */
- if (G_MAIN->wm.first) {
- ED_update_for_newframe(G_MAIN, rj->depsgraph);
- }
- }
-
- /* XXX above function sets all tags in nodes */
- ntreeCompositClearTags(rj->scene->nodetree);
-
- /* potentially set by caller */
- rj->scene->r.scemode &= ~R_NO_FRAME_UPDATE;
-
- if (rj->single_layer) {
- nodeUpdateID(rj->scene->nodetree, &rj->scene->id);
- WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene);
- }
-
- if (rj->sa) {
- render_image_restore_layer(rj);
- }
-
- /* XXX render stability hack */
- G.is_rendering = false;
- WM_main_add_notifier(NC_SCENE | ND_RENDER_RESULT, NULL);
-
- /* Partial render result will always update display buffer
- * for first render layer only. This is nice because you'll
- * see render progress during rendering, but it ends up in
- * wrong display buffer shown after rendering.
- *
- * The code below will mark display buffer as invalid after
- * rendering in case multiple layers were rendered, which
- * ensures display buffer matches render layer after
- * rendering.
- *
- * Perhaps proper way would be to toggle active render
- * layer in image editor and job, so we always display
- * layer being currently rendered. But this is not so much
- * trivial at this moment, especially because of external
- * engine API, so lets use simple and robust way for now
- * - sergey -
- */
- if (rj->scene->view_layers.first != rj->scene->view_layers.last ||
- rj->image_outdated)
- {
- void *lock;
- Image *ima = rj->image;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
-
- if (ibuf)
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
-
- BKE_image_release_ibuf(ima, ibuf, lock);
- }
-
- /* Finally unlock the user interface (if it was locked). */
- if (rj->interface_locked) {
- /* Interface was locked, so window manager couldn't have been changed
- * and using one from Global will unlock exactly the same manager as
- * was locked before running the job.
- */
- WM_set_locked_interface(G_MAIN->wm.first, false);
- DEG_on_visible_update(G_MAIN, false);
- }
+ RenderJob *rj = rjv;
+
+ /* this render may be used again by the sequencer without the active
+ * 'Render' where the callbacks would be re-assigned. assign dummy callbacks
+ * to avoid referencing freed renderjobs bug T24508. */
+ RE_InitRenderCB(rj->re);
+
+ if (rj->main != G_MAIN)
+ BKE_main_free(rj->main);
+
+ /* else the frame will not update for the original value */
+ if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) {
+ /* possible this fails of loading new file while rendering */
+ if (G_MAIN->wm.first) {
+ ED_update_for_newframe(G_MAIN, rj->depsgraph);
+ }
+ }
+
+ /* XXX above function sets all tags in nodes */
+ ntreeCompositClearTags(rj->scene->nodetree);
+
+ /* potentially set by caller */
+ rj->scene->r.scemode &= ~R_NO_FRAME_UPDATE;
+
+ if (rj->single_layer) {
+ nodeUpdateID(rj->scene->nodetree, &rj->scene->id);
+ WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene);
+ }
+
+ if (rj->sa) {
+ render_image_restore_layer(rj);
+ }
+
+ /* XXX render stability hack */
+ G.is_rendering = false;
+ WM_main_add_notifier(NC_SCENE | ND_RENDER_RESULT, NULL);
+
+ /* Partial render result will always update display buffer
+ * for first render layer only. This is nice because you'll
+ * see render progress during rendering, but it ends up in
+ * wrong display buffer shown after rendering.
+ *
+ * The code below will mark display buffer as invalid after
+ * rendering in case multiple layers were rendered, which
+ * ensures display buffer matches render layer after
+ * rendering.
+ *
+ * Perhaps proper way would be to toggle active render
+ * layer in image editor and job, so we always display
+ * layer being currently rendered. But this is not so much
+ * trivial at this moment, especially because of external
+ * engine API, so lets use simple and robust way for now
+ * - sergey -
+ */
+ if (rj->scene->view_layers.first != rj->scene->view_layers.last || rj->image_outdated) {
+ void *lock;
+ Image *ima = rj->image;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
+
+ if (ibuf)
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ }
+
+ /* Finally unlock the user interface (if it was locked). */
+ if (rj->interface_locked) {
+ /* Interface was locked, so window manager couldn't have been changed
+ * and using one from Global will unlock exactly the same manager as
+ * was locked before running the job.
+ */
+ WM_set_locked_interface(G_MAIN->wm.first, false);
+ DEG_on_visible_update(G_MAIN, false);
+ }
}
/* called by render, check job 'stop' value or the global */
static int render_breakjob(void *rjv)
{
- RenderJob *rj = rjv;
+ RenderJob *rj = rjv;
- if (G.is_break)
- return 1;
- if (rj->stop && *(rj->stop))
- return 1;
- return 0;
+ if (G.is_break)
+ return 1;
+ if (rj->stop && *(rj->stop))
+ return 1;
+ return 0;
}
/* for exec() when there is no render job
* note: this wont check for the escape key being pressed, but doing so isnt threadsafe */
static int render_break(void *UNUSED(rjv))
{
- if (G.is_break)
- return 1;
- return 0;
+ if (G.is_break)
+ return 1;
+ return 0;
}
/* runs in thread, no cursor setting here works. careful with notifiers too (malloc conflicts) */
/* maybe need a way to get job send notifier? */
static void render_drawlock(void *rjv, int lock)
{
- RenderJob *rj = rjv;
+ RenderJob *rj = rjv;
- /* If interface is locked, renderer callback shall do nothing. */
- if (!rj->interface_locked) {
- BKE_spacedata_draw_locks(lock);
- }
+ /* If interface is locked, renderer callback shall do nothing. */
+ if (!rj->interface_locked) {
+ BKE_spacedata_draw_locks(lock);
+ }
}
/* catch esc */
static int screen_render_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- Scene *scene = (Scene *) op->customdata;
-
- /* no running blender, remove handler and pass through */
- if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER)) {
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
- }
-
- /* running render */
- switch (event->type) {
- case ESCKEY:
- return OPERATOR_RUNNING_MODAL;
- }
- return OPERATOR_PASS_THROUGH;
+ Scene *scene = (Scene *)op->customdata;
+
+ /* no running blender, remove handler and pass through */
+ if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER)) {
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ }
+
+ /* running render */
+ switch (event->type) {
+ case ESCKEY:
+ return OPERATOR_RUNNING_MODAL;
+ }
+ return OPERATOR_PASS_THROUGH;
}
static void screen_render_cancel(bContext *C, wmOperator *op)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- Scene *scene = (Scene *) op->customdata;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ Scene *scene = (Scene *)op->customdata;
- /* kill on cancel, because job is using op->reports */
- WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER);
+ /* kill on cancel, because job is using op->reports */
+ WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER);
}
static void clean_viewport_memory_base(Base *base)
{
- if ((base->flag & BASE_VISIBLE) == 0) {
- return;
- }
+ if ((base->flag & BASE_VISIBLE) == 0) {
+ return;
+ }
- Object *object = base->object;
+ Object *object = base->object;
- if (object->id.tag & LIB_TAG_DOIT) {
- return;
- }
+ if (object->id.tag & LIB_TAG_DOIT) {
+ return;
+ }
- object->id.tag &= ~LIB_TAG_DOIT;
- if (RE_allow_render_generic_object(object)) {
- BKE_object_free_derived_caches(object);
- }
+ object->id.tag &= ~LIB_TAG_DOIT;
+ if (RE_allow_render_generic_object(object)) {
+ BKE_object_free_derived_caches(object);
+ }
}
static void clean_viewport_memory(Main *bmain, Scene *scene)
{
- Scene *sce_iter;
- Base *base;
-
- /* Tag all the available objects. */
- BKE_main_id_tag_listbase(&bmain->objects, LIB_TAG_DOIT, true);
-
- /* 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) {
- ViewLayer *view_layer = WM_window_get_active_view_layer(win);
-
- for (base = view_layer->object_bases.first; base; base = base->next) {
- clean_viewport_memory_base(base);
- }
- }
- }
-
- for (SETLOOPER_SET_ONLY(scene, sce_iter, base)) {
- clean_viewport_memory_base(base);
- }
+ Scene *sce_iter;
+ Base *base;
+
+ /* Tag all the available objects. */
+ BKE_main_id_tag_listbase(&bmain->objects, LIB_TAG_DOIT, true);
+
+ /* 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) {
+ ViewLayer *view_layer = WM_window_get_active_view_layer(win);
+
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ clean_viewport_memory_base(base);
+ }
+ }
+ }
+
+ for (SETLOOPER_SET_ONLY(scene, sce_iter, base)) {
+ clean_viewport_memory_base(base);
+ }
}
/* using context, starts job */
static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- /* new render clears all callbacks */
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *active_layer = CTX_data_view_layer(C);
- ViewLayer *single_layer = NULL;
- RenderEngineType *re_type = RE_engines_find(scene->r.engine);
- Render *re;
- wmJob *wm_job;
- RenderJob *rj;
- Image *ima;
- int jobflag;
- const bool is_animation = RNA_boolean_get(op->ptr, "animation");
- const bool is_write_still = RNA_boolean_get(op->ptr, "write_still");
- const bool use_viewport = RNA_boolean_get(op->ptr, "use_viewport");
- View3D *v3d = use_viewport ? CTX_wm_view3d(C) : NULL;
- struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
- const char *name;
- ScrArea *sa;
-
- /* Cannot do render if there is not this function. */
- if (re_type->render == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- /* custom scene and single layer re-render */
- screen_render_single_layer_set(op, bmain, active_layer, &scene, &single_layer);
-
- /* only one render job at a time */
- if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER))
- return OPERATOR_CANCELLED;
-
- if (!RE_is_rendering_allowed(scene, single_layer, camera_override, op->reports)) {
- return OPERATOR_CANCELLED;
- }
-
- if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected");
- 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));
-
- /* cancel animation playback */
- if (ED_screen_animation_playing(CTX_wm_manager(C)))
- ED_screen_animation_play(C, 0, 0);
-
- /* handle UI stuff */
- WM_cursor_wait(1);
-
- /* flush sculpt and editmode changes */
- ED_editors_flush_edits(bmain, true);
-
- /* cleanup sequencer caches before starting user triggered render.
- * otherwise, invalidated cache entries can make their way into
- * the output rendering. We can't put that into RE_BlenderFrame,
- * since sequence rendering can call that recursively... (peter) */
- BKE_sequencer_cache_cleanup();
-
- // store spare
- // get view3d layer, local layer, make this nice api call to render
- // store spare
-
- /* ensure at least 1 area shows result */
- sa = render_view_open(C, event->x, event->y, op->reports);
-
- jobflag = WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS;
-
- if (RNA_struct_property_is_set(op->ptr, "layer"))
- jobflag |= WM_JOB_SUSPEND;
-
- /* job custom data */
- rj = MEM_callocN(sizeof(RenderJob), "render job");
- rj->main = bmain;
- rj->scene = scene;
- rj->current_scene = rj->scene;
- rj->single_layer = single_layer;
- /* TODO(sergey): Render engine should be using own depsgraph. */
- rj->depsgraph = CTX_data_depsgraph(C);
- rj->camera_override = camera_override;
- rj->anim = is_animation;
- rj->write_still = is_write_still && !is_animation;
- rj->iuser.scene = scene;
- rj->iuser.ok = 1;
- rj->reports = op->reports;
- rj->orig_layer = 0;
- rj->last_layer = 0;
- rj->sa = sa;
- 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;
- rj->orig_layer = sima->iuser.layer;
- }
-
- if (v3d) {
- if (camera_override && camera_override != scene->camera)
- rj->v3d_override = true;
- }
-
- /* Lock the user interface depending on render settings. */
- if (scene->r.use_lock_interface) {
- WM_set_locked_interface(CTX_wm_manager(C), true);
-
- /* Set flag interface need to be unlocked.
- *
- * This is so because we don't have copy of render settings
- * accessible from render job and copy is needed in case
- * of non-locked rendering, so we wouldn't try to unlock
- * anything if option was initially unset but then was
- * enabled during rendering.
- */
- rj->interface_locked = true;
-
- /* Clean memory used by viewport? */
- clean_viewport_memory(rj->main, scene);
- }
-
- /* setup job */
- if (RE_seq_render_active(scene, &scene->r)) name = "Sequence Render";
- else name = "Render";
-
- wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, name, jobflag, WM_JOB_TYPE_RENDER);
- WM_jobs_customdata_set(wm_job, rj, render_freejob);
- WM_jobs_timer(wm_job, 0.2, NC_SCENE | ND_RENDER_RESULT, 0);
- WM_jobs_callbacks(wm_job, render_startjob, NULL, NULL, render_endjob);
-
- /* get a render result image, and make sure it is empty */
- ima = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result");
- BKE_image_signal(rj->main, ima, NULL, IMA_SIGNAL_FREE);
- BKE_image_backup_render(rj->scene, ima, true);
- rj->image = ima;
-
- /* setup new render */
- re = RE_NewSceneRender(scene);
- RE_test_break_cb(re, rj, render_breakjob);
- RE_draw_lock_cb(re, rj, render_drawlock);
- RE_display_update_cb(re, rj, image_rect_update);
- RE_current_scene_update_cb(re, rj, current_scene_update);
- RE_stats_draw_cb(re, rj, image_renderinfo_cb);
- RE_progress_cb(re, rj, render_progress_update);
- RE_gl_context_create(re);
-
- rj->re = re;
- G.is_break = false;
-
- /* store actual owner of job, so modal operator could check for it,
- * the reason of this is that active scene could change when rendering
- * several layers from compositor [#31800]
- */
- op->customdata = scene;
-
- WM_jobs_start(CTX_wm_manager(C), wm_job);
-
- WM_cursor_wait(0);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
-
- /* we set G.is_rendering here already instead of only in the job, this ensure
- * main loop or other scene updates are disabled in time, since they may
- * have started before the job thread */
- G.is_rendering = true;
-
- /* add modal handler for ESC */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
+ /* new render clears all callbacks */
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *active_layer = CTX_data_view_layer(C);
+ ViewLayer *single_layer = NULL;
+ RenderEngineType *re_type = RE_engines_find(scene->r.engine);
+ Render *re;
+ wmJob *wm_job;
+ RenderJob *rj;
+ Image *ima;
+ int jobflag;
+ const bool is_animation = RNA_boolean_get(op->ptr, "animation");
+ const bool is_write_still = RNA_boolean_get(op->ptr, "write_still");
+ const bool use_viewport = RNA_boolean_get(op->ptr, "use_viewport");
+ View3D *v3d = use_viewport ? CTX_wm_view3d(C) : NULL;
+ struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
+ const char *name;
+ ScrArea *sa;
+
+ /* Cannot do render if there is not this function. */
+ if (re_type->render == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* custom scene and single layer re-render */
+ screen_render_single_layer_set(op, bmain, active_layer, &scene, &single_layer);
+
+ /* only one render job at a time */
+ if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER))
+ return OPERATOR_CANCELLED;
+
+ if (!RE_is_rendering_allowed(scene, single_layer, camera_override, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) {
+ BKE_report(
+ op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected");
+ 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));
+
+ /* cancel animation playback */
+ if (ED_screen_animation_playing(CTX_wm_manager(C)))
+ ED_screen_animation_play(C, 0, 0);
+
+ /* handle UI stuff */
+ WM_cursor_wait(1);
+
+ /* flush sculpt and editmode changes */
+ ED_editors_flush_edits(bmain, true);
+
+ /* cleanup sequencer caches before starting user triggered render.
+ * otherwise, invalidated cache entries can make their way into
+ * the output rendering. We can't put that into RE_BlenderFrame,
+ * since sequence rendering can call that recursively... (peter) */
+ BKE_sequencer_cache_cleanup();
+
+ // store spare
+ // get view3d layer, local layer, make this nice api call to render
+ // store spare
+
+ /* ensure at least 1 area shows result */
+ sa = render_view_open(C, event->x, event->y, op->reports);
+
+ jobflag = WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS;
+
+ if (RNA_struct_property_is_set(op->ptr, "layer"))
+ jobflag |= WM_JOB_SUSPEND;
+
+ /* job custom data */
+ rj = MEM_callocN(sizeof(RenderJob), "render job");
+ rj->main = bmain;
+ rj->scene = scene;
+ rj->current_scene = rj->scene;
+ rj->single_layer = single_layer;
+ /* TODO(sergey): Render engine should be using own depsgraph. */
+ rj->depsgraph = CTX_data_depsgraph(C);
+ rj->camera_override = camera_override;
+ rj->anim = is_animation;
+ rj->write_still = is_write_still && !is_animation;
+ rj->iuser.scene = scene;
+ rj->iuser.ok = 1;
+ rj->reports = op->reports;
+ rj->orig_layer = 0;
+ rj->last_layer = 0;
+ rj->sa = sa;
+ 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;
+ rj->orig_layer = sima->iuser.layer;
+ }
+
+ if (v3d) {
+ if (camera_override && camera_override != scene->camera)
+ rj->v3d_override = true;
+ }
+
+ /* Lock the user interface depending on render settings. */
+ if (scene->r.use_lock_interface) {
+ WM_set_locked_interface(CTX_wm_manager(C), true);
+
+ /* Set flag interface need to be unlocked.
+ *
+ * This is so because we don't have copy of render settings
+ * accessible from render job and copy is needed in case
+ * of non-locked rendering, so we wouldn't try to unlock
+ * anything if option was initially unset but then was
+ * enabled during rendering.
+ */
+ rj->interface_locked = true;
+
+ /* Clean memory used by viewport? */
+ clean_viewport_memory(rj->main, scene);
+ }
+
+ /* setup job */
+ if (RE_seq_render_active(scene, &scene->r))
+ name = "Sequence Render";
+ else
+ name = "Render";
+
+ wm_job = WM_jobs_get(
+ CTX_wm_manager(C), CTX_wm_window(C), scene, name, jobflag, WM_JOB_TYPE_RENDER);
+ WM_jobs_customdata_set(wm_job, rj, render_freejob);
+ WM_jobs_timer(wm_job, 0.2, NC_SCENE | ND_RENDER_RESULT, 0);
+ WM_jobs_callbacks(wm_job, render_startjob, NULL, NULL, render_endjob);
+
+ /* get a render result image, and make sure it is empty */
+ ima = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result");
+ BKE_image_signal(rj->main, ima, NULL, IMA_SIGNAL_FREE);
+ BKE_image_backup_render(rj->scene, ima, true);
+ rj->image = ima;
+
+ /* setup new render */
+ re = RE_NewSceneRender(scene);
+ RE_test_break_cb(re, rj, render_breakjob);
+ RE_draw_lock_cb(re, rj, render_drawlock);
+ RE_display_update_cb(re, rj, image_rect_update);
+ RE_current_scene_update_cb(re, rj, current_scene_update);
+ RE_stats_draw_cb(re, rj, image_renderinfo_cb);
+ RE_progress_cb(re, rj, render_progress_update);
+ RE_gl_context_create(re);
+
+ rj->re = re;
+ G.is_break = false;
+
+ /* store actual owner of job, so modal operator could check for it,
+ * the reason of this is that active scene could change when rendering
+ * several layers from compositor [#31800]
+ */
+ op->customdata = scene;
+
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+
+ WM_cursor_wait(0);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
+
+ /* we set G.is_rendering here already instead of only in the job, this ensure
+ * main loop or other scene updates are disabled in time, since they may
+ * have started before the job thread */
+ G.is_rendering = true;
+
+ /* add modal handler for ESC */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
}
/* contextual render, using current scene, view3d? */
void RENDER_OT_render(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Render";
- ot->description = "Render active scene";
- ot->idname = "RENDER_OT_render";
-
- /* api callbacks */
- ot->invoke = screen_render_invoke;
- ot->modal = screen_render_modal;
- ot->cancel = screen_render_cancel;
- ot->exec = screen_render_exec;
-
- /*ot->poll = ED_operator_screenactive;*/ /* this isn't needed, causes failer in background mode */
-
- prop = RNA_def_boolean(ot->srna, "animation", 0, "Animation", "Render files from the animation range of this scene");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- RNA_def_boolean(ot->srna, "write_still", 0, "Write Image", "Save rendered the image to the output path (used only when animation is disabled)");
- prop = RNA_def_boolean(ot->srna, "use_viewport", 0, "Use 3D Viewport", "When inside a 3D viewport, use layers and camera of the viewport");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_string(ot->srna, "layer", NULL, RE_MAXNAME, "Render Layer", "Single render layer to re-render (used only when animation is disabled)");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_string(ot->srna, "scene", NULL, MAX_ID_NAME - 2, "Scene", "Scene to render, current scene if not specified");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Render";
+ ot->description = "Render active scene";
+ ot->idname = "RENDER_OT_render";
+
+ /* api callbacks */
+ ot->invoke = screen_render_invoke;
+ ot->modal = screen_render_modal;
+ ot->cancel = screen_render_cancel;
+ ot->exec = screen_render_exec;
+
+ /*ot->poll = ED_operator_screenactive;*/ /* this isn't needed, causes failer in background mode */
+
+ prop = RNA_def_boolean(ot->srna,
+ "animation",
+ 0,
+ "Animation",
+ "Render files from the animation range of this scene");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_boolean(
+ ot->srna,
+ "write_still",
+ 0,
+ "Write Image",
+ "Save rendered the image to the output path (used only when animation is disabled)");
+ prop = RNA_def_boolean(ot->srna,
+ "use_viewport",
+ 0,
+ "Use 3D Viewport",
+ "When inside a 3D viewport, use layers and camera of the viewport");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_string(ot->srna,
+ "layer",
+ NULL,
+ RE_MAXNAME,
+ "Render Layer",
+ "Single render layer to re-render (used only when animation is disabled)");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_string(ot->srna,
+ "scene",
+ NULL,
+ MAX_ID_NAME - 2,
+ "Scene",
+ "Scene to render, current scene if not specified");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-
Scene *ED_render_job_get_scene(const bContext *C)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- RenderJob *rj = (RenderJob *)WM_jobs_customdata_from_type(wm, WM_JOB_TYPE_RENDER);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ RenderJob *rj = (RenderJob *)WM_jobs_customdata_from_type(wm, WM_JOB_TYPE_RENDER);
- if (rj)
- return rj->scene;
+ if (rj)
+ return rj->scene;
- return NULL;
+ return NULL;
}
Scene *ED_render_job_get_current_scene(const bContext *C)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- RenderJob *rj = (RenderJob *)WM_jobs_customdata_from_type(wm, WM_JOB_TYPE_RENDER);
- if (rj) {
- return rj->current_scene;
- }
- return NULL;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ RenderJob *rj = (RenderJob *)WM_jobs_customdata_from_type(wm, WM_JOB_TYPE_RENDER);
+ if (rj) {
+ return rj->current_scene;
+ }
+ return NULL;
}
-
/* Motion blur curve preset */
static int render_shutter_curve_preset_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- CurveMapping *mblur_shutter_curve = &scene->r.mblur_shutter_curve;
- CurveMap *cm = mblur_shutter_curve->cm;
- int preset = RNA_enum_get(op->ptr, "shape");
-
- cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
- mblur_shutter_curve->preset = preset;
- curvemap_reset(cm,
- &mblur_shutter_curve->clipr,
- mblur_shutter_curve->preset,
- CURVEMAP_SLOPE_POS_NEG);
- curvemapping_changed(mblur_shutter_curve, false);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ CurveMapping *mblur_shutter_curve = &scene->r.mblur_shutter_curve;
+ CurveMap *cm = mblur_shutter_curve->cm;
+ int preset = RNA_enum_get(op->ptr, "shape");
+
+ cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
+ mblur_shutter_curve->preset = preset;
+ curvemap_reset(
+ cm, &mblur_shutter_curve->clipr, mblur_shutter_curve->preset, CURVEMAP_SLOPE_POS_NEG);
+ curvemapping_changed(mblur_shutter_curve, false);
+
+ return OPERATOR_FINISHED;
}
void RENDER_OT_shutter_curve_preset(wmOperatorType *ot)
{
- PropertyRNA *prop;
- static const EnumPropertyItem prop_shape_items[] = {
- {CURVE_PRESET_SHARP, "SHARP", 0, "Sharp", ""},
- {CURVE_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""},
- {CURVE_PRESET_MAX, "MAX", 0, "Max", ""},
- {CURVE_PRESET_LINE, "LINE", 0, "Line", ""},
- {CURVE_PRESET_ROUND, "ROUND", 0, "Round", ""},
- {CURVE_PRESET_ROOT, "ROOT", 0, "Root", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- ot->name = "Shutter Curve Preset";
- ot->description = "Set shutter curve";
- ot->idname = "RENDER_OT_shutter_curve_preset";
-
- ot->exec = render_shutter_curve_preset_exec;
-
- prop = RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", "");
- RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
+ PropertyRNA *prop;
+ static const EnumPropertyItem prop_shape_items[] = {
+ {CURVE_PRESET_SHARP, "SHARP", 0, "Sharp", ""},
+ {CURVE_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""},
+ {CURVE_PRESET_MAX, "MAX", 0, "Max", ""},
+ {CURVE_PRESET_LINE, "LINE", 0, "Line", ""},
+ {CURVE_PRESET_ROUND, "ROUND", 0, "Round", ""},
+ {CURVE_PRESET_ROOT, "ROOT", 0, "Root", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ ot->name = "Shutter Curve Preset";
+ ot->description = "Set shutter curve";
+ ot->idname = "RENDER_OT_shutter_curve_preset";
+
+ ot->exec = render_shutter_curve_preset_exec;
+
+ prop = RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", "");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
}
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 3fdc34bd9c9..6862881de59 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -21,7 +21,6 @@
* \ingroup edrend
*/
-
#include <math.h>
#include <string.h>
#include <stddef.h>
@@ -88,1039 +87,1079 @@
#define MAX_SCHEDULED_FRAMES 8
typedef struct OGLRender {
- Main *bmain;
- Render *re;
- Scene *scene;
- WorkSpace *workspace;
- ViewLayer *view_layer;
- Depsgraph *depsgraph;
-
- View3D *v3d;
- RegionView3D *rv3d;
- ARegion *ar;
-
- ScrArea *prevsa;
- ARegion *prevar;
-
- int views_len; /* multi-view views */
-
- bool is_sequencer;
- SpaceSeq *sseq;
- struct {
- ImBuf **ibufs_arr;
- } seq_data;
-
-
- Image *ima;
- ImageUser iuser;
-
- GPUOffScreen *ofs;
- int ofs_samples;
- bool ofs_full_samples;
- int sizex, sizey;
- int write_still;
-
- ReportList *reports;
- bMovieHandle *mh;
- int cfrao, nfra;
-
- int totvideos;
-
- /* quick lookup */
- int view_id;
-
- /* wm vars for timer and progress cursor */
- wmWindowManager *wm;
- wmWindow *win;
-
- 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;
- SpinLock reports_lock;
- unsigned int num_scheduled_frames;
- ThreadMutex task_mutex;
- ThreadCondition task_condition;
+ Main *bmain;
+ Render *re;
+ Scene *scene;
+ WorkSpace *workspace;
+ ViewLayer *view_layer;
+ Depsgraph *depsgraph;
+
+ View3D *v3d;
+ RegionView3D *rv3d;
+ ARegion *ar;
+
+ ScrArea *prevsa;
+ ARegion *prevar;
+
+ int views_len; /* multi-view views */
+
+ bool is_sequencer;
+ SpaceSeq *sseq;
+ struct {
+ ImBuf **ibufs_arr;
+ } seq_data;
+
+ Image *ima;
+ ImageUser iuser;
+
+ GPUOffScreen *ofs;
+ int ofs_samples;
+ bool ofs_full_samples;
+ int sizex, sizey;
+ int write_still;
+
+ ReportList *reports;
+ bMovieHandle *mh;
+ int cfrao, nfra;
+
+ int totvideos;
+
+ /* quick lookup */
+ int view_id;
+
+ /* wm vars for timer and progress cursor */
+ wmWindowManager *wm;
+ wmWindow *win;
+
+ 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;
+ SpinLock reports_lock;
+ unsigned int num_scheduled_frames;
+ ThreadMutex task_mutex;
+ ThreadCondition task_condition;
#ifdef DEBUG_TIME
- double time_start;
+ double time_start;
#endif
} OGLRender;
static bool screen_opengl_is_multiview(OGLRender *oglrender)
{
- View3D *v3d = oglrender->v3d;
- RegionView3D *rv3d = oglrender->rv3d;
- RenderData *rd = &oglrender->scene->r;
+ View3D *v3d = oglrender->v3d;
+ RegionView3D *rv3d = oglrender->rv3d;
+ RenderData *rd = &oglrender->scene->r;
- if ((rd == NULL) || ((v3d != NULL) && (rv3d == NULL)))
- return false;
+ if ((rd == NULL) || ((v3d != NULL) && (rv3d == NULL)))
+ return false;
- return (rd->scemode & R_MULTIVIEW) && ((v3d == NULL) || (rv3d->persp == RV3D_CAMOB && v3d->camera));
+ return (rd->scemode & R_MULTIVIEW) &&
+ ((v3d == NULL) || (rv3d->persp == RV3D_CAMOB && v3d->camera));
}
static void screen_opengl_views_setup(OGLRender *oglrender)
{
- RenderResult *rr;
- RenderView *rv;
- SceneRenderView *srv;
- bool is_multiview;
- Object *camera;
- View3D *v3d = oglrender->v3d;
-
- RenderData *rd = &oglrender->scene->r;
-
- rr = RE_AcquireResultWrite(oglrender->re);
-
- is_multiview = screen_opengl_is_multiview(oglrender);
-
- if (!is_multiview) {
- /* we only have one view when multiview is off */
- rv = rr->views.first;
-
- if (rv == NULL) {
- rv = MEM_callocN(sizeof(RenderView), "new opengl render view");
- BLI_addtail(&rr->views, rv);
- }
-
- while (rv->next) {
- RenderView *rv_del = rv->next;
- BLI_remlink(&rr->views, rv_del);
-
- if (rv_del->rectf)
- MEM_freeN(rv_del->rectf);
-
- if (rv_del->rectz)
- MEM_freeN(rv_del->rectz);
-
- if (rv_del->rect32)
- MEM_freeN(rv_del->rect32);
-
- MEM_freeN(rv_del);
- }
- }
- else {
- if (v3d) {
- RE_SetOverrideCamera(oglrender->re, V3D_CAMERA_SCENE(oglrender->scene, v3d));
- }
-
- /* remove all the views that are not needed */
- rv = rr->views.last;
- while (rv) {
- srv = BLI_findstring(&rd->views, rv->name, offsetof(SceneRenderView, name));
- if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
- rv = rv->prev;
- }
- else {
- RenderView *rv_del = rv;
- rv = rv_del->prev;
-
- BLI_remlink(&rr->views, rv_del);
-
- if (rv_del->rectf)
- MEM_freeN(rv_del->rectf);
-
- if (rv_del->rectz)
- MEM_freeN(rv_del->rectz);
-
- if (rv_del->rect32)
- MEM_freeN(rv_del->rect32);
-
- MEM_freeN(rv_del);
- }
- }
-
- /* create all the views that are needed */
- for (srv = rd->views.first; srv; srv = srv->next) {
- if (BKE_scene_multiview_is_render_view_active(rd, srv) == false)
- continue;
-
- rv = BLI_findstring(&rr->views, srv->name, offsetof(SceneRenderView, name));
-
- if (rv == NULL) {
- rv = MEM_callocN(sizeof(RenderView), "new opengl render view");
- BLI_strncpy(rv->name, srv->name, sizeof(rv->name));
- BLI_addtail(&rr->views, rv);
- }
- }
- }
-
- if (!(is_multiview && BKE_scene_multiview_is_stereo3d(rd)))
- oglrender->iuser.flag &= ~IMA_SHOW_STEREO;
-
- /* will only work for non multiview correctly */
- if (v3d) {
- camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, "new opengl render view");
- BKE_render_result_stamp_info(oglrender->scene, camera, rr, false);
- }
- else {
- BKE_render_result_stamp_info(oglrender->scene, oglrender->scene->camera, rr, false);
- }
-
- RE_ReleaseResult(oglrender->re);
+ RenderResult *rr;
+ RenderView *rv;
+ SceneRenderView *srv;
+ bool is_multiview;
+ Object *camera;
+ View3D *v3d = oglrender->v3d;
+
+ RenderData *rd = &oglrender->scene->r;
+
+ rr = RE_AcquireResultWrite(oglrender->re);
+
+ is_multiview = screen_opengl_is_multiview(oglrender);
+
+ if (!is_multiview) {
+ /* we only have one view when multiview is off */
+ rv = rr->views.first;
+
+ if (rv == NULL) {
+ rv = MEM_callocN(sizeof(RenderView), "new opengl render view");
+ BLI_addtail(&rr->views, rv);
+ }
+
+ while (rv->next) {
+ RenderView *rv_del = rv->next;
+ BLI_remlink(&rr->views, rv_del);
+
+ if (rv_del->rectf)
+ MEM_freeN(rv_del->rectf);
+
+ if (rv_del->rectz)
+ MEM_freeN(rv_del->rectz);
+
+ if (rv_del->rect32)
+ MEM_freeN(rv_del->rect32);
+
+ MEM_freeN(rv_del);
+ }
+ }
+ else {
+ if (v3d) {
+ RE_SetOverrideCamera(oglrender->re, V3D_CAMERA_SCENE(oglrender->scene, v3d));
+ }
+
+ /* remove all the views that are not needed */
+ rv = rr->views.last;
+ while (rv) {
+ srv = BLI_findstring(&rd->views, rv->name, offsetof(SceneRenderView, name));
+ if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
+ rv = rv->prev;
+ }
+ else {
+ RenderView *rv_del = rv;
+ rv = rv_del->prev;
+
+ BLI_remlink(&rr->views, rv_del);
+
+ if (rv_del->rectf)
+ MEM_freeN(rv_del->rectf);
+
+ if (rv_del->rectz)
+ MEM_freeN(rv_del->rectz);
+
+ if (rv_del->rect32)
+ MEM_freeN(rv_del->rect32);
+
+ MEM_freeN(rv_del);
+ }
+ }
+
+ /* create all the views that are needed */
+ for (srv = rd->views.first; srv; srv = srv->next) {
+ if (BKE_scene_multiview_is_render_view_active(rd, srv) == false)
+ continue;
+
+ rv = BLI_findstring(&rr->views, srv->name, offsetof(SceneRenderView, name));
+
+ if (rv == NULL) {
+ rv = MEM_callocN(sizeof(RenderView), "new opengl render view");
+ BLI_strncpy(rv->name, srv->name, sizeof(rv->name));
+ BLI_addtail(&rr->views, rv);
+ }
+ }
+ }
+
+ if (!(is_multiview && BKE_scene_multiview_is_stereo3d(rd)))
+ oglrender->iuser.flag &= ~IMA_SHOW_STEREO;
+
+ /* will only work for non multiview correctly */
+ if (v3d) {
+ camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, "new opengl render view");
+ BKE_render_result_stamp_info(oglrender->scene, camera, rr, false);
+ }
+ else {
+ BKE_render_result_stamp_info(oglrender->scene, oglrender->scene->camera, rr, false);
+ }
+
+ RE_ReleaseResult(oglrender->re);
}
static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, RenderResult *rr)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = oglrender->scene;
- ARegion *ar = oglrender->ar;
- View3D *v3d = oglrender->v3d;
- RegionView3D *rv3d = oglrender->rv3d;
- Object *camera = NULL;
- int sizex = oglrender->sizex;
- int sizey = oglrender->sizey;
- const short view_context = (v3d != NULL);
- bool draw_sky = (scene->r.alphamode == R_ADDSKY);
- float *rectf = NULL;
- const char *viewname = RE_GetActiveRenderView(oglrender->re);
- ImBuf *ibuf_result = NULL;
-
- if (oglrender->is_sequencer) {
- SpaceSeq *sseq = oglrender->sseq;
- struct bGPdata *gpd = (sseq && (sseq->flag & SEQ_SHOW_GPENCIL)) ? sseq->gpd : NULL;
-
- /* use pre-calculated ImBuf (avoids deadlock), see: */
- ImBuf *ibuf = oglrender->seq_data.ibufs_arr[oglrender->view_id];
-
- if (ibuf) {
- ImBuf *out = IMB_dupImBuf(ibuf);
- IMB_freeImBuf(ibuf);
- /* OpenGL render is considered to be preview and should be
- * as fast as possible. So currently we're making sure sequencer
- * result is always byte to simplify color management pipeline.
- *
- * TODO(sergey): In the case of output to float container (EXR)
- * it actually makes sense to keep float buffer instead.
- */
- if (out->rect_float != NULL) {
- IMB_rect_from_float(out);
- imb_freerectfloatImBuf(out);
- }
- BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y));
- RE_render_result_rect_from_ibuf(rr, &scene->r, out, oglrender->view_id);
- IMB_freeImBuf(out);
- }
- else if (gpd) {
- /* If there are no strips, Grease Pencil still needs a buffer to draw on */
- ImBuf *out = IMB_allocImBuf(oglrender->sizex, oglrender->sizey, 32, IB_rect);
- RE_render_result_rect_from_ibuf(rr, &scene->r, out, oglrender->view_id);
- IMB_freeImBuf(out);
- }
-
- if (gpd) {
- int i;
- unsigned char *gp_rect;
- unsigned char *render_rect = (unsigned char *)RE_RenderViewGetById(rr, oglrender->view_id)->rect32;
-
- DRW_opengl_context_enable();
- GPU_offscreen_bind(oglrender->ofs, true);
-
- GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f);
- GPU_clear(GPU_COLOR_BIT | GPU_DEPTH_BIT);
-
- wmOrtho2(0, sizex, 0, sizey);
- GPU_matrix_translate_2f(sizex / 2, sizey / 2);
-
- G.f |= G_FLAG_RENDER_VIEWPORT;
- 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");
- GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, gp_rect);
-
- for (i = 0; i < sizex * sizey * 4; i += 4) {
- blend_color_mix_byte(&render_rect[i], &render_rect[i], &gp_rect[i]);
- }
- GPU_offscreen_unbind(oglrender->ofs, true);
- DRW_opengl_context_disable();
-
- MEM_freeN(gp_rect);
- }
- }
- else {
- /* shouldnt suddenly give errors mid-render but possible */
- char err_out[256] = "unknown";
- ImBuf *ibuf_view;
- const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL;
-
- unsigned int draw_flags = V3D_OFSDRAW_NONE;
- draw_flags |= (oglrender->ofs_full_samples) ? V3D_OFSDRAW_USE_FULL_SAMPLE : 0;
-
- if (view_context) {
- ibuf_view = ED_view3d_draw_offscreen_imbuf(
- depsgraph, scene, v3d->shading.type,
- v3d, ar, sizex, sizey,
- IB_rectfloat, draw_flags, alpha_mode, oglrender->ofs_samples, viewname,
- oglrender->ofs, err_out);
-
- /* for stamp only */
- if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
- camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, viewname);
- }
- }
- else {
- draw_flags |= V3D_OFSDRAW_USE_GPENCIL;
- ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(
- depsgraph, scene, OB_SOLID,
- scene->camera, oglrender->sizex, oglrender->sizey,
- IB_rectfloat, draw_flags,
- alpha_mode, oglrender->ofs_samples, viewname,
- oglrender->ofs, err_out);
- camera = scene->camera;
- }
-
- if (ibuf_view) {
- ibuf_result = ibuf_view;
- rectf = (float *)ibuf_view->rect_float;
- }
- else {
- fprintf(stderr, "%s: failed to get buffer, %s\n", __func__, err_out);
- }
- }
-
- if (ibuf_result != NULL) {
- if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) {
- BKE_image_stamp_buf(scene, camera, NULL, NULL, rectf, rr->rectx, rr->recty, 4);
- }
- RE_render_result_rect_from_ibuf(rr, &scene->r, ibuf_result, oglrender->view_id);
- IMB_freeImBuf(ibuf_result);
- }
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = oglrender->scene;
+ ARegion *ar = oglrender->ar;
+ View3D *v3d = oglrender->v3d;
+ RegionView3D *rv3d = oglrender->rv3d;
+ Object *camera = NULL;
+ int sizex = oglrender->sizex;
+ int sizey = oglrender->sizey;
+ const short view_context = (v3d != NULL);
+ bool draw_sky = (scene->r.alphamode == R_ADDSKY);
+ float *rectf = NULL;
+ const char *viewname = RE_GetActiveRenderView(oglrender->re);
+ ImBuf *ibuf_result = NULL;
+
+ if (oglrender->is_sequencer) {
+ SpaceSeq *sseq = oglrender->sseq;
+ struct bGPdata *gpd = (sseq && (sseq->flag & SEQ_SHOW_GPENCIL)) ? sseq->gpd : NULL;
+
+ /* use pre-calculated ImBuf (avoids deadlock), see: */
+ ImBuf *ibuf = oglrender->seq_data.ibufs_arr[oglrender->view_id];
+
+ if (ibuf) {
+ ImBuf *out = IMB_dupImBuf(ibuf);
+ IMB_freeImBuf(ibuf);
+ /* OpenGL render is considered to be preview and should be
+ * as fast as possible. So currently we're making sure sequencer
+ * result is always byte to simplify color management pipeline.
+ *
+ * TODO(sergey): In the case of output to float container (EXR)
+ * it actually makes sense to keep float buffer instead.
+ */
+ if (out->rect_float != NULL) {
+ IMB_rect_from_float(out);
+ imb_freerectfloatImBuf(out);
+ }
+ BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y));
+ RE_render_result_rect_from_ibuf(rr, &scene->r, out, oglrender->view_id);
+ IMB_freeImBuf(out);
+ }
+ else if (gpd) {
+ /* If there are no strips, Grease Pencil still needs a buffer to draw on */
+ ImBuf *out = IMB_allocImBuf(oglrender->sizex, oglrender->sizey, 32, IB_rect);
+ RE_render_result_rect_from_ibuf(rr, &scene->r, out, oglrender->view_id);
+ IMB_freeImBuf(out);
+ }
+
+ if (gpd) {
+ int i;
+ unsigned char *gp_rect;
+ unsigned char *render_rect =
+ (unsigned char *)RE_RenderViewGetById(rr, oglrender->view_id)->rect32;
+
+ DRW_opengl_context_enable();
+ GPU_offscreen_bind(oglrender->ofs, true);
+
+ GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f);
+ GPU_clear(GPU_COLOR_BIT | GPU_DEPTH_BIT);
+
+ wmOrtho2(0, sizex, 0, sizey);
+ GPU_matrix_translate_2f(sizex / 2, sizey / 2);
+
+ G.f |= G_FLAG_RENDER_VIEWPORT;
+ 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");
+ GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, gp_rect);
+
+ for (i = 0; i < sizex * sizey * 4; i += 4) {
+ blend_color_mix_byte(&render_rect[i], &render_rect[i], &gp_rect[i]);
+ }
+ GPU_offscreen_unbind(oglrender->ofs, true);
+ DRW_opengl_context_disable();
+
+ MEM_freeN(gp_rect);
+ }
+ }
+ else {
+ /* shouldnt suddenly give errors mid-render but possible */
+ char err_out[256] = "unknown";
+ ImBuf *ibuf_view;
+ const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL;
+
+ unsigned int draw_flags = V3D_OFSDRAW_NONE;
+ draw_flags |= (oglrender->ofs_full_samples) ? V3D_OFSDRAW_USE_FULL_SAMPLE : 0;
+
+ if (view_context) {
+ ibuf_view = ED_view3d_draw_offscreen_imbuf(depsgraph,
+ scene,
+ v3d->shading.type,
+ v3d,
+ ar,
+ sizex,
+ sizey,
+ IB_rectfloat,
+ draw_flags,
+ alpha_mode,
+ oglrender->ofs_samples,
+ viewname,
+ oglrender->ofs,
+ err_out);
+
+ /* for stamp only */
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, viewname);
+ }
+ }
+ else {
+ draw_flags |= V3D_OFSDRAW_USE_GPENCIL;
+ ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(depsgraph,
+ scene,
+ OB_SOLID,
+ scene->camera,
+ oglrender->sizex,
+ oglrender->sizey,
+ IB_rectfloat,
+ draw_flags,
+ alpha_mode,
+ oglrender->ofs_samples,
+ viewname,
+ oglrender->ofs,
+ err_out);
+ camera = scene->camera;
+ }
+
+ if (ibuf_view) {
+ ibuf_result = ibuf_view;
+ rectf = (float *)ibuf_view->rect_float;
+ }
+ else {
+ fprintf(stderr, "%s: failed to get buffer, %s\n", __func__, err_out);
+ }
+ }
+
+ if (ibuf_result != NULL) {
+ if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) {
+ BKE_image_stamp_buf(scene, camera, NULL, NULL, rectf, rr->rectx, rr->recty, 4);
+ }
+ RE_render_result_rect_from_ibuf(rr, &scene->r, ibuf_result, oglrender->view_id);
+ IMB_freeImBuf(ibuf_result);
+ }
}
static void screen_opengl_render_write(OGLRender *oglrender)
{
- Scene *scene = oglrender->scene;
- RenderResult *rr;
- bool ok;
- char name[FILE_MAX];
-
- rr = RE_AcquireResultRead(oglrender->re);
-
- BKE_image_path_from_imformat(
- name, scene->r.pic, BKE_main_blendfile_path(oglrender->bmain), scene->r.cfra,
- &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false, NULL);
-
- /* write images as individual images or stereo */
- BKE_render_result_stamp_info(scene, scene->camera, rr, false);
- ok = RE_WriteRenderViewsImage(oglrender->reports, rr, scene, false, name);
-
- RE_ReleaseResultImage(oglrender->re);
-
- if (ok) printf("OpenGL Render written to '%s'\n", name);
- else printf("OpenGL Render failed to write '%s'\n", name);
+ Scene *scene = oglrender->scene;
+ RenderResult *rr;
+ bool ok;
+ char name[FILE_MAX];
+
+ rr = RE_AcquireResultRead(oglrender->re);
+
+ BKE_image_path_from_imformat(name,
+ scene->r.pic,
+ BKE_main_blendfile_path(oglrender->bmain),
+ scene->r.cfra,
+ &scene->r.im_format,
+ (scene->r.scemode & R_EXTENSION) != 0,
+ false,
+ NULL);
+
+ /* write images as individual images or stereo */
+ BKE_render_result_stamp_info(scene, scene->camera, rr, false);
+ ok = RE_WriteRenderViewsImage(oglrender->reports, rr, scene, false, name);
+
+ RE_ReleaseResultImage(oglrender->re);
+
+ if (ok)
+ printf("OpenGL Render written to '%s'\n", name);
+ else
+ printf("OpenGL Render failed to write '%s'\n", name);
}
static void UNUSED_FUNCTION(addAlphaOverFloat)(float dest[4], const float source[4])
{
- /* d = s + (1-alpha_s)d*/
- float mul;
-
- mul = 1.0f - source[3];
+ /* d = s + (1-alpha_s)d*/
+ float mul;
- dest[0] = (mul * dest[0]) + source[0];
- dest[1] = (mul * dest[1]) + source[1];
- dest[2] = (mul * dest[2]) + source[2];
- dest[3] = (mul * dest[3]) + source[3];
+ mul = 1.0f - source[3];
+ dest[0] = (mul * dest[0]) + source[0];
+ dest[1] = (mul * dest[1]) + source[1];
+ dest[2] = (mul * dest[2]) + source[2];
+ dest[3] = (mul * dest[3]) + source[3];
}
static void screen_opengl_render_apply(const bContext *C, OGLRender *oglrender)
{
- RenderResult *rr;
- RenderView *rv;
- int view_id;
- ImBuf *ibuf;
- void *lock;
-
- if (oglrender->is_sequencer) {
- Scene *scene = oglrender->scene;
-
- SeqRenderData context;
- SpaceSeq *sseq = oglrender->sseq;
- int chanshown = sseq ? sseq->chanshown : 0;
-
- BKE_sequencer_new_render_data(
- oglrender->bmain, oglrender->depsgraph, scene,
- oglrender->sizex, oglrender->sizey, 100.0f, false,
- &context);
-
- for (view_id = 0; view_id < oglrender->views_len; view_id++) {
- context.view_id = view_id;
- context.gpu_offscreen = oglrender->ofs;
- context.gpu_full_samples = oglrender->ofs_full_samples;
-
- oglrender->seq_data.ibufs_arr[view_id] = BKE_sequencer_give_ibuf(&context, CFRA, chanshown);
- }
- }
-
- rr = RE_AcquireResultRead(oglrender->re);
- for (rv = rr->views.first, view_id = 0; rv; rv = rv->next, view_id++) {
- BLI_assert(view_id < oglrender->views_len);
- RE_SetActiveRenderView(oglrender->re, rv->name);
- oglrender->view_id = view_id;
- /* render composite */
- screen_opengl_render_doit(C, oglrender, rr);
- }
-
- RE_ReleaseResult(oglrender->re);
-
- ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock);
- if (ibuf) {
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
- }
- BKE_image_release_ibuf(oglrender->ima, ibuf, lock);
-
- if (oglrender->write_still) {
- screen_opengl_render_write(oglrender);
- }
+ RenderResult *rr;
+ RenderView *rv;
+ int view_id;
+ ImBuf *ibuf;
+ void *lock;
+
+ if (oglrender->is_sequencer) {
+ Scene *scene = oglrender->scene;
+
+ SeqRenderData context;
+ SpaceSeq *sseq = oglrender->sseq;
+ int chanshown = sseq ? sseq->chanshown : 0;
+
+ BKE_sequencer_new_render_data(oglrender->bmain,
+ oglrender->depsgraph,
+ scene,
+ oglrender->sizex,
+ oglrender->sizey,
+ 100.0f,
+ false,
+ &context);
+
+ for (view_id = 0; view_id < oglrender->views_len; view_id++) {
+ context.view_id = view_id;
+ context.gpu_offscreen = oglrender->ofs;
+ context.gpu_full_samples = oglrender->ofs_full_samples;
+
+ oglrender->seq_data.ibufs_arr[view_id] = BKE_sequencer_give_ibuf(&context, CFRA, chanshown);
+ }
+ }
+
+ rr = RE_AcquireResultRead(oglrender->re);
+ for (rv = rr->views.first, view_id = 0; rv; rv = rv->next, view_id++) {
+ BLI_assert(view_id < oglrender->views_len);
+ RE_SetActiveRenderView(oglrender->re, rv->name);
+ oglrender->view_id = view_id;
+ /* render composite */
+ screen_opengl_render_doit(C, oglrender, rr);
+ }
+
+ RE_ReleaseResult(oglrender->re);
+
+ ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock);
+ if (ibuf) {
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ }
+ BKE_image_release_ibuf(oglrender->ima, ibuf, lock);
+
+ if (oglrender->write_still) {
+ screen_opengl_render_write(oglrender);
+ }
}
static bool screen_opengl_fullsample_enabled(Scene *scene)
{
- if (scene->r.scemode & R_FULL_SAMPLE) {
- return true;
- }
- else {
- /* XXX TODO:
- * Technically if the hardware supports MSAA we could keep using Blender 2.7x approach.
- * However anti-aliasing without full_sample is not playing well even in 2.7x.
- *
- * For example, if you enable depth of field, there is aliasing, even if the viewport is fine.
- * For 2.8x this is more complicated because so many things rely on shader.
- * So until we fix the gpu_framebuffer anti-aliasing suupport we need to force full sample.
- */
- return true;
- }
+ if (scene->r.scemode & R_FULL_SAMPLE) {
+ return true;
+ }
+ else {
+ /* XXX TODO:
+ * Technically if the hardware supports MSAA we could keep using Blender 2.7x approach.
+ * However anti-aliasing without full_sample is not playing well even in 2.7x.
+ *
+ * For example, if you enable depth of field, there is aliasing, even if the viewport is fine.
+ * For 2.8x this is more complicated because so many things rely on shader.
+ * So until we fix the gpu_framebuffer anti-aliasing suupport we need to force full sample.
+ */
+ return true;
+ }
}
static bool screen_opengl_render_init(bContext *C, wmOperator *op)
{
- /* new render clears all callbacks */
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
- WorkSpace *workspace = CTX_wm_workspace(C);
-
- Scene *scene = CTX_data_scene(C);
- ScrArea *prevsa = CTX_wm_area(C);
- ARegion *prevar = CTX_wm_region(C);
- GPUOffScreen *ofs;
- OGLRender *oglrender;
- int sizex, sizey;
- const int samples = (scene->r.mode & R_OSA) ? scene->r.osa : 0;
- const bool full_samples = (samples != 0) && screen_opengl_fullsample_enabled(scene);
- bool is_view_context = RNA_boolean_get(op->ptr, "view_context");
- const bool is_animation = RNA_boolean_get(op->ptr, "animation");
- const bool is_sequencer = RNA_boolean_get(op->ptr, "sequencer");
- const bool is_write_still = RNA_boolean_get(op->ptr, "write_still");
- char err_out[256] = "unknown";
-
- if (G.background) {
- BKE_report(op->reports, RPT_ERROR, "Cannot use OpenGL render in background mode (no opengl context)");
- return false;
- }
-
- /* only one render job at a time */
- if (WM_jobs_test(wm, scene, WM_JOB_TYPE_RENDER))
- return false;
-
- if (is_sequencer) {
- is_view_context = false;
- }
- else {
- /* ensure we have a 3d view */
- if (!ED_view3d_context_activate(C)) {
- RNA_boolean_set(op->ptr, "view_context", false);
- is_view_context = false;
- }
-
- if (!is_view_context && scene->camera == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Scene has no camera");
- return false;
- }
- }
-
- if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected");
- return false;
- }
-
- /* stop all running jobs, except screen one. currently previews frustrate Render */
- WM_jobs_kill_all_except(wm, CTX_wm_screen(C));
-
- /* create offscreen buffer */
- sizex = (scene->r.size * scene->r.xsch) / 100;
- sizey = (scene->r.size * scene->r.ysch) / 100;
-
- /* corrects render size with actual size, not every card supports non-power-of-two dimensions */
- DRW_opengl_context_enable(); /* Offscreen creation needs to be done in DRW context. */
- ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, true, true, err_out);
- DRW_opengl_context_disable();
-
- if (!ofs) {
- BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out);
- return false;
- }
-
- /* allocate opengl render */
- oglrender = MEM_callocN(sizeof(OGLRender), "OGLRender");
- op->customdata = oglrender;
-
- oglrender->ofs = ofs;
- oglrender->ofs_samples = samples;
- oglrender->ofs_full_samples = full_samples;
- oglrender->sizex = sizex;
- oglrender->sizey = sizey;
- oglrender->bmain = CTX_data_main(C);
- oglrender->scene = scene;
- oglrender->workspace = workspace;
- oglrender->view_layer = CTX_data_view_layer(C);
- oglrender->depsgraph = CTX_data_depsgraph(C);
- oglrender->cfrao = scene->r.cfra;
-
- oglrender->write_still = is_write_still && !is_animation;
- oglrender->is_animation = is_animation;
-
- oglrender->views_len = BKE_scene_multiview_num_views_get(&scene->r);
-
- oglrender->is_sequencer = is_sequencer;
- if (is_sequencer) {
- oglrender->sseq = CTX_wm_space_seq(C);
- ImBuf **ibufs_arr = MEM_callocN(sizeof(*ibufs_arr) * oglrender->views_len, __func__);
- oglrender->seq_data.ibufs_arr = ibufs_arr;
- }
-
- oglrender->prevsa = prevsa;
- oglrender->prevar = prevar;
-
- if (is_view_context) {
- /* so quad view renders camera */
- ED_view3d_context_user_region(C, &oglrender->v3d, &oglrender->ar);
-
- oglrender->rv3d = oglrender->ar->regiondata;
-
- /* MUST be cleared on exit */
- memset(&oglrender->scene->customdata_mask_modal, 0, sizeof(oglrender->scene->customdata_mask_modal));
- ED_view3d_datamask(C, oglrender->scene, oglrender->v3d, &oglrender->scene->customdata_mask_modal);
-
- /* apply immediately in case we're rendering from a script,
- * running notifiers again will overwrite */
- CustomData_MeshMasks_update(&oglrender->scene->customdata_mask, &oglrender->scene->customdata_mask_modal);
- }
-
- /* create render */
- oglrender->re = RE_NewSceneRender(scene);
-
- /* create image and image user */
- oglrender->ima = BKE_image_verify_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);
-
- oglrender->iuser.scene = scene;
- oglrender->iuser.ok = 1;
-
- /* create render result */
- RE_InitState(oglrender->re, NULL, &scene->r, &scene->view_layers, NULL, sizex, sizey, NULL);
-
- /* create render views */
- screen_opengl_views_setup(oglrender);
-
- /* wm vars */
- oglrender->wm = wm;
- oglrender->win = win;
-
- oglrender->totvideos = 0;
- oglrender->mh = NULL;
- oglrender->movie_ctx_arr = NULL;
-
- if (is_animation) {
- 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);
- }
- else {
- oglrender->task_scheduler = NULL;
- oglrender->task_pool = BLI_task_pool_create(task_scheduler,
- oglrender);
- }
- oglrender->pool_ok = true;
- BLI_spin_init(&oglrender->reports_lock);
- }
- else {
- oglrender->task_scheduler = NULL;
- oglrender->task_pool = NULL;
- }
- oglrender->num_scheduled_frames = 0;
- BLI_mutex_init(&oglrender->task_mutex);
- BLI_condition_init(&oglrender->task_condition);
+ /* new render clears all callbacks */
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+ WorkSpace *workspace = CTX_wm_workspace(C);
+
+ Scene *scene = CTX_data_scene(C);
+ ScrArea *prevsa = CTX_wm_area(C);
+ ARegion *prevar = CTX_wm_region(C);
+ GPUOffScreen *ofs;
+ OGLRender *oglrender;
+ int sizex, sizey;
+ const int samples = (scene->r.mode & R_OSA) ? scene->r.osa : 0;
+ const bool full_samples = (samples != 0) && screen_opengl_fullsample_enabled(scene);
+ bool is_view_context = RNA_boolean_get(op->ptr, "view_context");
+ const bool is_animation = RNA_boolean_get(op->ptr, "animation");
+ const bool is_sequencer = RNA_boolean_get(op->ptr, "sequencer");
+ const bool is_write_still = RNA_boolean_get(op->ptr, "write_still");
+ char err_out[256] = "unknown";
+
+ if (G.background) {
+ BKE_report(
+ op->reports, RPT_ERROR, "Cannot use OpenGL render in background mode (no opengl context)");
+ return false;
+ }
+
+ /* only one render job at a time */
+ if (WM_jobs_test(wm, scene, WM_JOB_TYPE_RENDER))
+ return false;
+
+ if (is_sequencer) {
+ is_view_context = false;
+ }
+ else {
+ /* ensure we have a 3d view */
+ if (!ED_view3d_context_activate(C)) {
+ RNA_boolean_set(op->ptr, "view_context", false);
+ is_view_context = false;
+ }
+
+ if (!is_view_context && scene->camera == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Scene has no camera");
+ return false;
+ }
+ }
+
+ if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) {
+ BKE_report(
+ op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected");
+ return false;
+ }
+
+ /* stop all running jobs, except screen one. currently previews frustrate Render */
+ WM_jobs_kill_all_except(wm, CTX_wm_screen(C));
+
+ /* create offscreen buffer */
+ sizex = (scene->r.size * scene->r.xsch) / 100;
+ sizey = (scene->r.size * scene->r.ysch) / 100;
+
+ /* corrects render size with actual size, not every card supports non-power-of-two dimensions */
+ DRW_opengl_context_enable(); /* Offscreen creation needs to be done in DRW context. */
+ ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, true, true, err_out);
+ DRW_opengl_context_disable();
+
+ if (!ofs) {
+ BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out);
+ return false;
+ }
+
+ /* allocate opengl render */
+ oglrender = MEM_callocN(sizeof(OGLRender), "OGLRender");
+ op->customdata = oglrender;
+
+ oglrender->ofs = ofs;
+ oglrender->ofs_samples = samples;
+ oglrender->ofs_full_samples = full_samples;
+ oglrender->sizex = sizex;
+ oglrender->sizey = sizey;
+ oglrender->bmain = CTX_data_main(C);
+ oglrender->scene = scene;
+ oglrender->workspace = workspace;
+ oglrender->view_layer = CTX_data_view_layer(C);
+ oglrender->depsgraph = CTX_data_depsgraph(C);
+ oglrender->cfrao = scene->r.cfra;
+
+ oglrender->write_still = is_write_still && !is_animation;
+ oglrender->is_animation = is_animation;
+
+ oglrender->views_len = BKE_scene_multiview_num_views_get(&scene->r);
+
+ oglrender->is_sequencer = is_sequencer;
+ if (is_sequencer) {
+ oglrender->sseq = CTX_wm_space_seq(C);
+ ImBuf **ibufs_arr = MEM_callocN(sizeof(*ibufs_arr) * oglrender->views_len, __func__);
+ oglrender->seq_data.ibufs_arr = ibufs_arr;
+ }
+
+ oglrender->prevsa = prevsa;
+ oglrender->prevar = prevar;
+
+ if (is_view_context) {
+ /* so quad view renders camera */
+ ED_view3d_context_user_region(C, &oglrender->v3d, &oglrender->ar);
+
+ oglrender->rv3d = oglrender->ar->regiondata;
+
+ /* MUST be cleared on exit */
+ memset(&oglrender->scene->customdata_mask_modal,
+ 0,
+ sizeof(oglrender->scene->customdata_mask_modal));
+ ED_view3d_datamask(
+ C, oglrender->scene, oglrender->v3d, &oglrender->scene->customdata_mask_modal);
+
+ /* apply immediately in case we're rendering from a script,
+ * running notifiers again will overwrite */
+ CustomData_MeshMasks_update(&oglrender->scene->customdata_mask,
+ &oglrender->scene->customdata_mask_modal);
+ }
+
+ /* create render */
+ oglrender->re = RE_NewSceneRender(scene);
+
+ /* create image and image user */
+ oglrender->ima = BKE_image_verify_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);
+
+ oglrender->iuser.scene = scene;
+ oglrender->iuser.ok = 1;
+
+ /* create render result */
+ RE_InitState(oglrender->re, NULL, &scene->r, &scene->view_layers, NULL, sizex, sizey, NULL);
+
+ /* create render views */
+ screen_opengl_views_setup(oglrender);
+
+ /* wm vars */
+ oglrender->wm = wm;
+ oglrender->win = win;
+
+ oglrender->totvideos = 0;
+ oglrender->mh = NULL;
+ oglrender->movie_ctx_arr = NULL;
+
+ if (is_animation) {
+ 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);
+ }
+ else {
+ oglrender->task_scheduler = NULL;
+ oglrender->task_pool = BLI_task_pool_create(task_scheduler, oglrender);
+ }
+ oglrender->pool_ok = true;
+ BLI_spin_init(&oglrender->reports_lock);
+ }
+ else {
+ oglrender->task_scheduler = NULL;
+ oglrender->task_pool = NULL;
+ }
+ oglrender->num_scheduled_frames = 0;
+ BLI_mutex_init(&oglrender->task_mutex);
+ BLI_condition_init(&oglrender->task_condition);
#ifdef DEBUG_TIME
- oglrender->time_start = PIL_check_seconds_timer();
+ oglrender->time_start = PIL_check_seconds_timer();
#endif
- return true;
+ return true;
}
static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = oglrender->scene;
- int i;
-
- if (oglrender->is_animation) {
- /* Trickery part for movie output:
- *
- * We MUST write frames in an exact order, so we only let background
- * thread to work on that, and main thread is simply waits for that
- * thread to do all the dirty work.
- *
- * After this loop is done work_and_wait() will have nothing to do,
- * so we don't run into wrong order of frames written to the stream.
- */
- if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
- BLI_mutex_lock(&oglrender->task_mutex);
- while (oglrender->num_scheduled_frames > 0) {
- BLI_condition_wait(&oglrender->task_condition,
- &oglrender->task_mutex);
- }
- BLI_mutex_unlock(&oglrender->task_mutex);
- }
- 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);
- BLI_condition_end(&oglrender->task_condition);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = oglrender->scene;
+ int i;
+
+ if (oglrender->is_animation) {
+ /* Trickery part for movie output:
+ *
+ * We MUST write frames in an exact order, so we only let background
+ * thread to work on that, and main thread is simply waits for that
+ * thread to do all the dirty work.
+ *
+ * After this loop is done work_and_wait() will have nothing to do,
+ * so we don't run into wrong order of frames written to the stream.
+ */
+ if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
+ BLI_mutex_lock(&oglrender->task_mutex);
+ while (oglrender->num_scheduled_frames > 0) {
+ BLI_condition_wait(&oglrender->task_condition, &oglrender->task_mutex);
+ }
+ BLI_mutex_unlock(&oglrender->task_mutex);
+ }
+ 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);
+ BLI_condition_end(&oglrender->task_condition);
#ifdef DEBUG_TIME
- printf("Total render time: %f\n", PIL_check_seconds_timer() - oglrender->time_start);
+ printf("Total render time: %f\n", PIL_check_seconds_timer() - oglrender->time_start);
#endif
- if (oglrender->mh) {
- if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
- for (i = 0; i < oglrender->totvideos; i++) {
- oglrender->mh->end_movie(oglrender->movie_ctx_arr[i]);
- oglrender->mh->context_free(oglrender->movie_ctx_arr[i]);
- }
- }
+ if (oglrender->mh) {
+ if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
+ for (i = 0; i < oglrender->totvideos; i++) {
+ oglrender->mh->end_movie(oglrender->movie_ctx_arr[i]);
+ oglrender->mh->context_free(oglrender->movie_ctx_arr[i]);
+ }
+ }
- if (oglrender->movie_ctx_arr) {
- MEM_freeN(oglrender->movie_ctx_arr);
- }
- }
+ if (oglrender->movie_ctx_arr) {
+ MEM_freeN(oglrender->movie_ctx_arr);
+ }
+ }
- if (oglrender->timer) { /* exec will not have a timer */
- Depsgraph *depsgraph = oglrender->depsgraph;
- scene->r.cfra = oglrender->cfrao;
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+ if (oglrender->timer) { /* exec will not have a timer */
+ Depsgraph *depsgraph = oglrender->depsgraph;
+ scene->r.cfra = oglrender->cfrao;
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
- WM_event_remove_timer(oglrender->wm, oglrender->win, oglrender->timer);
- }
+ WM_event_remove_timer(oglrender->wm, oglrender->win, oglrender->timer);
+ }
- WM_cursor_modal_restore(oglrender->win);
+ WM_cursor_modal_restore(oglrender->win);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, oglrender->scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, oglrender->scene);
- DRW_opengl_context_enable();
- GPU_offscreen_free(oglrender->ofs);
- DRW_opengl_context_disable();
+ DRW_opengl_context_enable();
+ GPU_offscreen_free(oglrender->ofs);
+ DRW_opengl_context_disable();
- if (oglrender->is_sequencer) {
- MEM_freeN(oglrender->seq_data.ibufs_arr);
- }
+ if (oglrender->is_sequencer) {
+ MEM_freeN(oglrender->seq_data.ibufs_arr);
+ }
- memset(&oglrender->scene->customdata_mask_modal, 0, sizeof(oglrender->scene->customdata_mask_modal));
+ memset(&oglrender->scene->customdata_mask_modal,
+ 0,
+ sizeof(oglrender->scene->customdata_mask_modal));
- CTX_wm_area_set(C, oglrender->prevsa);
- CTX_wm_region_set(C, oglrender->prevar);
+ CTX_wm_area_set(C, oglrender->prevsa);
+ CTX_wm_region_set(C, oglrender->prevar);
- MEM_freeN(oglrender);
+ MEM_freeN(oglrender);
}
static void screen_opengl_render_cancel(bContext *C, wmOperator *op)
{
- screen_opengl_render_end(C, op->customdata);
+ screen_opengl_render_end(C, op->customdata);
}
/* share between invoke and exec */
static bool screen_opengl_render_anim_initialize(bContext *C, wmOperator *op)
{
- /* initialize animation */
- OGLRender *oglrender;
- Scene *scene;
-
- oglrender = op->customdata;
- scene = oglrender->scene;
- oglrender->totvideos = BKE_scene_multiview_num_videos_get(&scene->r);
-
- oglrender->reports = op->reports;
-
- if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
- size_t width, height;
- int i;
-
- BKE_scene_multiview_videos_dimensions_get(&scene->r, oglrender->sizex, oglrender->sizey, &width, &height);
- oglrender->mh = BKE_movie_handle_get(scene->r.im_format.imtype);
-
- if (oglrender->mh == NULL) {
- BKE_report(oglrender->reports, RPT_ERROR, "Movie format unsupported");
- screen_opengl_render_end(C, oglrender);
- return false;
- }
-
- oglrender->movie_ctx_arr = MEM_mallocN(sizeof(void *) * oglrender->totvideos, "Movies");
-
- for (i = 0; i < oglrender->totvideos; i++) {
- const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, i);
-
- oglrender->movie_ctx_arr[i] = oglrender->mh->context_create();
- if (!oglrender->mh->start_movie(oglrender->movie_ctx_arr[i], scene, &scene->r, oglrender->sizex,
- oglrender->sizey, oglrender->reports, PRVRANGEON != 0, suffix))
- {
- screen_opengl_render_end(C, oglrender);
- return false;
- }
- }
- }
-
- oglrender->cfrao = scene->r.cfra;
- oglrender->nfra = PSFRA;
- scene->r.cfra = PSFRA;
-
- return true;
+ /* initialize animation */
+ OGLRender *oglrender;
+ Scene *scene;
+
+ oglrender = op->customdata;
+ scene = oglrender->scene;
+ oglrender->totvideos = BKE_scene_multiview_num_videos_get(&scene->r);
+
+ oglrender->reports = op->reports;
+
+ if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
+ size_t width, height;
+ int i;
+
+ BKE_scene_multiview_videos_dimensions_get(
+ &scene->r, oglrender->sizex, oglrender->sizey, &width, &height);
+ oglrender->mh = BKE_movie_handle_get(scene->r.im_format.imtype);
+
+ if (oglrender->mh == NULL) {
+ BKE_report(oglrender->reports, RPT_ERROR, "Movie format unsupported");
+ screen_opengl_render_end(C, oglrender);
+ return false;
+ }
+
+ oglrender->movie_ctx_arr = MEM_mallocN(sizeof(void *) * oglrender->totvideos, "Movies");
+
+ for (i = 0; i < oglrender->totvideos; i++) {
+ const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, i);
+
+ oglrender->movie_ctx_arr[i] = oglrender->mh->context_create();
+ if (!oglrender->mh->start_movie(oglrender->movie_ctx_arr[i],
+ scene,
+ &scene->r,
+ oglrender->sizex,
+ oglrender->sizey,
+ oglrender->reports,
+ PRVRANGEON != 0,
+ suffix)) {
+ screen_opengl_render_end(C, oglrender);
+ return false;
+ }
+ }
+ }
+
+ oglrender->cfrao = scene->r.cfra;
+ oglrender->nfra = PSFRA;
+ scene->r.cfra = PSFRA;
+
+ return true;
}
typedef struct WriteTaskData {
- RenderResult *rr;
- Scene tmp_scene;
+ RenderResult *rr;
+ 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, int UNUSED(thread_id))
{
- OGLRender *oglrender = (OGLRender *) BLI_task_pool_userdata(pool);
- WriteTaskData *task_data = (WriteTaskData *) task_data_v;
- Scene *scene = &task_data->tmp_scene;
- RenderResult *rr = task_data->rr;
- const bool is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype);
- const int cfra = scene->r.cfra;
- bool ok;
- /* Don't attempt to write if we've got an error. */
- if (!oglrender->pool_ok) {
- RE_FreeRenderResult(rr);
- BLI_mutex_lock(&oglrender->task_mutex);
- oglrender->num_scheduled_frames--;
- BLI_condition_notify_all(&oglrender->task_condition);
- BLI_mutex_unlock(&oglrender->task_mutex);
- return;
- }
- /* Construct local thread0safe copy of reports structure which we can
- * safely pass to the underlying functions.
- */
- ReportList reports;
- BKE_reports_init(&reports, oglrender->reports->flag & ~RPT_PRINT);
- /* Do actual save logic here, depending on the file format.
- *
- * NOTE: We have to construct temporary scene with proper scene->r.cfra.
- * This is because underlying calls do not use r.cfra but use scene
- * for that.
- */
- if (is_movie) {
- ok = RE_WriteRenderViewsMovie(&reports,
- rr,
- scene,
- &scene->r,
- oglrender->mh,
- oglrender->movie_ctx_arr,
- oglrender->totvideos,
- PRVRANGEON != 0);
- }
- else {
- /* TODO(sergey): We can in theory save some CPU ticks here because we
- * calculate file name again here.
- */
- char name[FILE_MAX];
- BKE_image_path_from_imformat(name,
- scene->r.pic,
- BKE_main_blendfile_path(oglrender->bmain),
- cfra,
- &scene->r.im_format,
- (scene->r.scemode & R_EXTENSION) != 0,
- true,
- NULL);
-
- BKE_render_result_stamp_info(scene, scene->camera, rr, false);
- ok = RE_WriteRenderViewsImage(NULL, rr, scene, true, name);
- if (!ok) {
- BKE_reportf(&reports,
- RPT_ERROR,
- "Write error: cannot save %s",
- name);
- }
- }
- if (reports.list.first != NULL) {
- BLI_spin_lock(&oglrender->reports_lock);
- for (Report *report = reports.list.first;
- report != NULL;
- report = report->next)
- {
- BKE_report(oglrender->reports,
- report->type,
- report->message);
- }
- BLI_spin_unlock(&oglrender->reports_lock);
- }
- if (!ok) {
- oglrender->pool_ok = false;
- }
- RE_FreeRenderResult(rr);
- BLI_mutex_lock(&oglrender->task_mutex);
- oglrender->num_scheduled_frames--;
- BLI_condition_notify_all(&oglrender->task_condition);
- BLI_mutex_unlock(&oglrender->task_mutex);
+ OGLRender *oglrender = (OGLRender *)BLI_task_pool_userdata(pool);
+ WriteTaskData *task_data = (WriteTaskData *)task_data_v;
+ Scene *scene = &task_data->tmp_scene;
+ RenderResult *rr = task_data->rr;
+ const bool is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype);
+ const int cfra = scene->r.cfra;
+ bool ok;
+ /* Don't attempt to write if we've got an error. */
+ if (!oglrender->pool_ok) {
+ RE_FreeRenderResult(rr);
+ BLI_mutex_lock(&oglrender->task_mutex);
+ oglrender->num_scheduled_frames--;
+ BLI_condition_notify_all(&oglrender->task_condition);
+ BLI_mutex_unlock(&oglrender->task_mutex);
+ return;
+ }
+ /* Construct local thread0safe copy of reports structure which we can
+ * safely pass to the underlying functions.
+ */
+ ReportList reports;
+ BKE_reports_init(&reports, oglrender->reports->flag & ~RPT_PRINT);
+ /* Do actual save logic here, depending on the file format.
+ *
+ * NOTE: We have to construct temporary scene with proper scene->r.cfra.
+ * This is because underlying calls do not use r.cfra but use scene
+ * for that.
+ */
+ if (is_movie) {
+ ok = RE_WriteRenderViewsMovie(&reports,
+ rr,
+ scene,
+ &scene->r,
+ oglrender->mh,
+ oglrender->movie_ctx_arr,
+ oglrender->totvideos,
+ PRVRANGEON != 0);
+ }
+ else {
+ /* TODO(sergey): We can in theory save some CPU ticks here because we
+ * calculate file name again here.
+ */
+ char name[FILE_MAX];
+ BKE_image_path_from_imformat(name,
+ scene->r.pic,
+ BKE_main_blendfile_path(oglrender->bmain),
+ cfra,
+ &scene->r.im_format,
+ (scene->r.scemode & R_EXTENSION) != 0,
+ true,
+ NULL);
+
+ BKE_render_result_stamp_info(scene, scene->camera, rr, false);
+ ok = RE_WriteRenderViewsImage(NULL, rr, scene, true, name);
+ if (!ok) {
+ BKE_reportf(&reports, RPT_ERROR, "Write error: cannot save %s", name);
+ }
+ }
+ if (reports.list.first != NULL) {
+ BLI_spin_lock(&oglrender->reports_lock);
+ for (Report *report = reports.list.first; report != NULL; report = report->next) {
+ BKE_report(oglrender->reports, report->type, report->message);
+ }
+ BLI_spin_unlock(&oglrender->reports_lock);
+ }
+ if (!ok) {
+ oglrender->pool_ok = false;
+ }
+ RE_FreeRenderResult(rr);
+ BLI_mutex_lock(&oglrender->task_mutex);
+ oglrender->num_scheduled_frames--;
+ BLI_condition_notify_all(&oglrender->task_condition);
+ BLI_mutex_unlock(&oglrender->task_mutex);
}
static bool schedule_write_result(OGLRender *oglrender, RenderResult *rr)
{
- if (!oglrender->pool_ok) {
- RE_FreeRenderResult(rr);
- return false;
- }
- Scene *scene = oglrender->scene;
- WriteTaskData *task_data = MEM_mallocN(sizeof(WriteTaskData), "write task data");
- task_data->rr = rr;
- task_data->tmp_scene = *scene;
- BLI_mutex_lock(&oglrender->task_mutex);
- oglrender->num_scheduled_frames++;
- if (oglrender->num_scheduled_frames > MAX_SCHEDULED_FRAMES) {
- 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);
- return true;
+ if (!oglrender->pool_ok) {
+ RE_FreeRenderResult(rr);
+ return false;
+ }
+ Scene *scene = oglrender->scene;
+ WriteTaskData *task_data = MEM_mallocN(sizeof(WriteTaskData), "write task data");
+ task_data->rr = rr;
+ task_data->tmp_scene = *scene;
+ BLI_mutex_lock(&oglrender->task_mutex);
+ oglrender->num_scheduled_frames++;
+ if (oglrender->num_scheduled_frames > MAX_SCHEDULED_FRAMES) {
+ 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);
+ return true;
}
static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- OGLRender *oglrender = op->customdata;
- Scene *scene = oglrender->scene;
- Depsgraph *depsgraph = oglrender->depsgraph;
- char name[FILE_MAX];
- bool ok = false;
- const bool view_context = (oglrender->v3d != NULL);
- bool is_movie;
- RenderResult *rr;
-
- /* go to next frame */
- if (CFRA < oglrender->nfra)
- CFRA++;
- while (CFRA < oglrender->nfra) {
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
- CFRA++;
- }
-
- is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype);
-
- if (!is_movie) {
- BKE_image_path_from_imformat(
- name, scene->r.pic, BKE_main_blendfile_path(oglrender->bmain), scene->r.cfra,
- &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true, NULL);
-
- if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) {
- BLI_spin_lock(&oglrender->reports_lock);
- BKE_reportf(op->reports, RPT_INFO, "Skipping existing frame \"%s\"", name);
- BLI_spin_unlock(&oglrender->reports_lock);
- ok = true;
- goto finally;
- }
- }
-
- WM_cursor_time(oglrender->win, scene->r.cfra);
-
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
-
- if (view_context) {
- if (oglrender->rv3d->persp == RV3D_CAMOB && oglrender->v3d->camera && oglrender->v3d->scenelock) {
- /* since BKE_scene_graph_update_for_newframe() is used rather
- * then ED_update_for_newframe() the camera needs to be set */
- if (BKE_scene_camera_switch_update(scene)) {
- oglrender->v3d->camera = scene->camera;
- }
- }
- }
- else {
- BKE_scene_camera_switch_update(scene);
- }
-
- /* render into offscreen buffer */
- screen_opengl_render_apply(C, oglrender);
-
- /* save to disk */
- rr = RE_AcquireResultRead(oglrender->re);
- RenderResult *new_rr = RE_DuplicateRenderResult(rr);
- RE_ReleaseResult(oglrender->re);
-
- ok = schedule_write_result(oglrender, new_rr);
-
-finally: /* Step the frame and bail early if needed */
-
- /* go to next frame */
- oglrender->nfra += scene->r.frame_step;
-
- /* stop at the end or on error */
- if (CFRA >= PEFRA || !ok) {
- screen_opengl_render_end(C, op->customdata);
- return 0;
- }
-
- return 1;
+ Main *bmain = CTX_data_main(C);
+ OGLRender *oglrender = op->customdata;
+ Scene *scene = oglrender->scene;
+ Depsgraph *depsgraph = oglrender->depsgraph;
+ char name[FILE_MAX];
+ bool ok = false;
+ const bool view_context = (oglrender->v3d != NULL);
+ bool is_movie;
+ RenderResult *rr;
+
+ /* go to next frame */
+ if (CFRA < oglrender->nfra)
+ CFRA++;
+ while (CFRA < oglrender->nfra) {
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+ CFRA++;
+ }
+
+ is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype);
+
+ if (!is_movie) {
+ BKE_image_path_from_imformat(name,
+ scene->r.pic,
+ BKE_main_blendfile_path(oglrender->bmain),
+ scene->r.cfra,
+ &scene->r.im_format,
+ (scene->r.scemode & R_EXTENSION) != 0,
+ true,
+ NULL);
+
+ if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) {
+ BLI_spin_lock(&oglrender->reports_lock);
+ BKE_reportf(op->reports, RPT_INFO, "Skipping existing frame \"%s\"", name);
+ BLI_spin_unlock(&oglrender->reports_lock);
+ ok = true;
+ goto finally;
+ }
+ }
+
+ WM_cursor_time(oglrender->win, scene->r.cfra);
+
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+
+ if (view_context) {
+ if (oglrender->rv3d->persp == RV3D_CAMOB && oglrender->v3d->camera &&
+ oglrender->v3d->scenelock) {
+ /* since BKE_scene_graph_update_for_newframe() is used rather
+ * then ED_update_for_newframe() the camera needs to be set */
+ if (BKE_scene_camera_switch_update(scene)) {
+ oglrender->v3d->camera = scene->camera;
+ }
+ }
+ }
+ else {
+ BKE_scene_camera_switch_update(scene);
+ }
+
+ /* render into offscreen buffer */
+ screen_opengl_render_apply(C, oglrender);
+
+ /* save to disk */
+ rr = RE_AcquireResultRead(oglrender->re);
+ RenderResult *new_rr = RE_DuplicateRenderResult(rr);
+ RE_ReleaseResult(oglrender->re);
+
+ ok = schedule_write_result(oglrender, new_rr);
+
+finally: /* Step the frame and bail early if needed */
+
+ /* go to next frame */
+ oglrender->nfra += scene->r.frame_step;
+
+ /* stop at the end or on error */
+ if (CFRA >= PEFRA || !ok) {
+ screen_opengl_render_end(C, op->customdata);
+ return 0;
+ }
+
+ return 1;
}
-
static int screen_opengl_render_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- OGLRender *oglrender = op->customdata;
- const bool anim = RNA_boolean_get(op->ptr, "animation");
- bool ret;
-
- switch (event->type) {
- case ESCKEY:
- /* cancel */
- oglrender->pool_ok = false; /* Flag pool for cancel. */
- screen_opengl_render_end(C, op->customdata);
- return OPERATOR_FINISHED;
- case TIMER:
- /* render frame? */
- if (oglrender->timer == event->customdata)
- break;
- ATTR_FALLTHROUGH;
- default:
- /* nothing to do */
- return OPERATOR_RUNNING_MODAL;
- }
-
- /* run first because screen_opengl_render_anim_step can free oglrender */
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, oglrender->scene);
-
- if (anim == 0) {
- screen_opengl_render_apply(C, op->customdata);
- screen_opengl_render_end(C, op->customdata);
- return OPERATOR_FINISHED;
- }
- else {
- ret = screen_opengl_render_anim_step(C, op);
- }
-
- /* stop at the end or on error */
- if (ret == false) {
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_RUNNING_MODAL;
+ OGLRender *oglrender = op->customdata;
+ const bool anim = RNA_boolean_get(op->ptr, "animation");
+ bool ret;
+
+ switch (event->type) {
+ case ESCKEY:
+ /* cancel */
+ oglrender->pool_ok = false; /* Flag pool for cancel. */
+ screen_opengl_render_end(C, op->customdata);
+ return OPERATOR_FINISHED;
+ case TIMER:
+ /* render frame? */
+ if (oglrender->timer == event->customdata)
+ break;
+ ATTR_FALLTHROUGH;
+ default:
+ /* nothing to do */
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ /* run first because screen_opengl_render_anim_step can free oglrender */
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, oglrender->scene);
+
+ if (anim == 0) {
+ screen_opengl_render_apply(C, op->customdata);
+ screen_opengl_render_end(C, op->customdata);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ ret = screen_opengl_render_anim_step(C, op);
+ }
+
+ /* stop at the end or on error */
+ if (ret == false) {
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
static int screen_opengl_render_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- OGLRender *oglrender;
- const bool anim = RNA_boolean_get(op->ptr, "animation");
+ OGLRender *oglrender;
+ const bool anim = RNA_boolean_get(op->ptr, "animation");
- if (!screen_opengl_render_init(C, op))
- return OPERATOR_CANCELLED;
+ if (!screen_opengl_render_init(C, op))
+ return OPERATOR_CANCELLED;
- if (anim) {
- if (!screen_opengl_render_anim_initialize(C, op))
- return OPERATOR_CANCELLED;
- }
+ if (anim) {
+ if (!screen_opengl_render_anim_initialize(C, op))
+ return OPERATOR_CANCELLED;
+ }
- oglrender = op->customdata;
- render_view_open(C, event->x, event->y, op->reports);
+ oglrender = op->customdata;
+ render_view_open(C, event->x, event->y, op->reports);
- /* view may be changed above (R_OUTPUT_WINDOW) */
- oglrender->win = CTX_wm_window(C);
+ /* view may be changed above (R_OUTPUT_WINDOW) */
+ oglrender->win = CTX_wm_window(C);
- WM_event_add_modal_handler(C, op);
- oglrender->timer = WM_event_add_timer(oglrender->wm, oglrender->win, TIMER, 0.01f);
+ WM_event_add_modal_handler(C, op);
+ oglrender->timer = WM_event_add_timer(oglrender->wm, oglrender->win, TIMER, 0.01f);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
/* executes blocking render */
static int screen_opengl_render_exec(bContext *C, wmOperator *op)
{
- const bool is_animation = RNA_boolean_get(op->ptr, "animation");
+ const bool is_animation = RNA_boolean_get(op->ptr, "animation");
- if (!screen_opengl_render_init(C, op))
- return OPERATOR_CANCELLED;
+ if (!screen_opengl_render_init(C, op))
+ return OPERATOR_CANCELLED;
- if (!is_animation) { /* same as invoke */
- /* render image */
- screen_opengl_render_apply(C, op->customdata);
- screen_opengl_render_end(C, op->customdata);
+ if (!is_animation) { /* same as invoke */
+ /* render image */
+ screen_opengl_render_apply(C, op->customdata);
+ screen_opengl_render_end(C, op->customdata);
- return OPERATOR_FINISHED;
- }
- else {
- bool ret = true;
+ return OPERATOR_FINISHED;
+ }
+ else {
+ bool ret = true;
- if (!screen_opengl_render_anim_initialize(C, op))
- return OPERATOR_CANCELLED;
+ if (!screen_opengl_render_anim_initialize(C, op))
+ return OPERATOR_CANCELLED;
- while (ret) {
- ret = screen_opengl_render_anim_step(C, op);
- }
- }
+ while (ret) {
+ ret = screen_opengl_render_anim_step(C, op);
+ }
+ }
- /* no redraw needed, we leave state as we entered it */
-// ED_update_for_newframe(C);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, CTX_data_scene(C));
+ /* no redraw needed, we leave state as we entered it */
+ // ED_update_for_newframe(C);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, CTX_data_scene(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void RENDER_OT_opengl(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Viewport Render";
- ot->description = "Take a snapshot of the active viewport";
- ot->idname = "RENDER_OT_opengl";
-
- /* api callbacks */
- ot->invoke = screen_opengl_render_invoke;
- ot->exec = screen_opengl_render_exec; /* blocking */
- ot->modal = screen_opengl_render_modal;
- ot->cancel = screen_opengl_render_cancel;
-
- ot->poll = ED_operator_screenactive;
-
- prop = RNA_def_boolean(ot->srna, "animation", 0, "Animation", "Render files from the animation range of this scene");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "sequencer", 0, "Sequencer", "Render using the sequencer's OpenGL display");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "write_still", 0, "Write Image", "Save rendered the image to the output path (used only when animation is disabled)");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "view_context", 1, "View Context", "Use the current 3D view for rendering, else use scene settings");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Viewport Render";
+ ot->description = "Take a snapshot of the active viewport";
+ ot->idname = "RENDER_OT_opengl";
+
+ /* api callbacks */
+ ot->invoke = screen_opengl_render_invoke;
+ ot->exec = screen_opengl_render_exec; /* blocking */
+ ot->modal = screen_opengl_render_modal;
+ ot->cancel = screen_opengl_render_cancel;
+
+ ot->poll = ED_operator_screenactive;
+
+ prop = RNA_def_boolean(ot->srna,
+ "animation",
+ 0,
+ "Animation",
+ "Render files from the animation range of this scene");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(
+ ot->srna, "sequencer", 0, "Sequencer", "Render using the sequencer's OpenGL display");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(
+ ot->srna,
+ "write_still",
+ 0,
+ "Write Image",
+ "Save rendered the image to the output path (used only when animation is disabled)");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna,
+ "view_context",
+ 1,
+ "View Context",
+ "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 */
diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c
index ad3a5a161ac..b77f5c2bbad 100644
--- a/source/blender/editors/render/render_ops.c
+++ b/source/blender/editors/render/render_ops.c
@@ -29,66 +29,66 @@
#include "WM_api.h"
-#include "render_intern.h" // own include
+#include "render_intern.h" // own include
/***************************** render ***********************************/
void ED_operatortypes_render(void)
{
- WM_operatortype_append(OBJECT_OT_material_slot_add);
- WM_operatortype_append(OBJECT_OT_material_slot_remove);
- WM_operatortype_append(OBJECT_OT_material_slot_assign);
- WM_operatortype_append(OBJECT_OT_material_slot_select);
- WM_operatortype_append(OBJECT_OT_material_slot_deselect);
- WM_operatortype_append(OBJECT_OT_material_slot_copy);
- WM_operatortype_append(OBJECT_OT_material_slot_move);
+ WM_operatortype_append(OBJECT_OT_material_slot_add);
+ WM_operatortype_append(OBJECT_OT_material_slot_remove);
+ WM_operatortype_append(OBJECT_OT_material_slot_assign);
+ WM_operatortype_append(OBJECT_OT_material_slot_select);
+ WM_operatortype_append(OBJECT_OT_material_slot_deselect);
+ WM_operatortype_append(OBJECT_OT_material_slot_copy);
+ WM_operatortype_append(OBJECT_OT_material_slot_move);
- WM_operatortype_append(MATERIAL_OT_new);
- WM_operatortype_append(TEXTURE_OT_new);
- WM_operatortype_append(WORLD_OT_new);
+ WM_operatortype_append(MATERIAL_OT_new);
+ WM_operatortype_append(TEXTURE_OT_new);
+ WM_operatortype_append(WORLD_OT_new);
- WM_operatortype_append(MATERIAL_OT_copy);
- WM_operatortype_append(MATERIAL_OT_paste);
+ WM_operatortype_append(MATERIAL_OT_copy);
+ WM_operatortype_append(MATERIAL_OT_paste);
- WM_operatortype_append(SCENE_OT_view_layer_add);
- WM_operatortype_append(SCENE_OT_view_layer_remove);
+ WM_operatortype_append(SCENE_OT_view_layer_add);
+ WM_operatortype_append(SCENE_OT_view_layer_remove);
- WM_operatortype_append(SCENE_OT_render_view_add);
- WM_operatortype_append(SCENE_OT_render_view_remove);
+ WM_operatortype_append(SCENE_OT_render_view_add);
+ WM_operatortype_append(SCENE_OT_render_view_remove);
- WM_operatortype_append(SCENE_OT_light_cache_bake);
- WM_operatortype_append(SCENE_OT_light_cache_free);
+ WM_operatortype_append(SCENE_OT_light_cache_bake);
+ WM_operatortype_append(SCENE_OT_light_cache_free);
#ifdef WITH_FREESTYLE
- WM_operatortype_append(SCENE_OT_freestyle_module_add);
- WM_operatortype_append(SCENE_OT_freestyle_module_remove);
- WM_operatortype_append(SCENE_OT_freestyle_module_move);
- WM_operatortype_append(SCENE_OT_freestyle_lineset_add);
- WM_operatortype_append(SCENE_OT_freestyle_lineset_copy);
- WM_operatortype_append(SCENE_OT_freestyle_lineset_paste);
- WM_operatortype_append(SCENE_OT_freestyle_lineset_remove);
- WM_operatortype_append(SCENE_OT_freestyle_lineset_move);
- WM_operatortype_append(SCENE_OT_freestyle_linestyle_new);
- WM_operatortype_append(SCENE_OT_freestyle_color_modifier_add);
- WM_operatortype_append(SCENE_OT_freestyle_alpha_modifier_add);
- WM_operatortype_append(SCENE_OT_freestyle_thickness_modifier_add);
- WM_operatortype_append(SCENE_OT_freestyle_geometry_modifier_add);
- WM_operatortype_append(SCENE_OT_freestyle_modifier_remove);
- WM_operatortype_append(SCENE_OT_freestyle_modifier_move);
- WM_operatortype_append(SCENE_OT_freestyle_modifier_copy);
- WM_operatortype_append(SCENE_OT_freestyle_stroke_material_create);
+ WM_operatortype_append(SCENE_OT_freestyle_module_add);
+ WM_operatortype_append(SCENE_OT_freestyle_module_remove);
+ WM_operatortype_append(SCENE_OT_freestyle_module_move);
+ WM_operatortype_append(SCENE_OT_freestyle_lineset_add);
+ WM_operatortype_append(SCENE_OT_freestyle_lineset_copy);
+ WM_operatortype_append(SCENE_OT_freestyle_lineset_paste);
+ WM_operatortype_append(SCENE_OT_freestyle_lineset_remove);
+ WM_operatortype_append(SCENE_OT_freestyle_lineset_move);
+ WM_operatortype_append(SCENE_OT_freestyle_linestyle_new);
+ WM_operatortype_append(SCENE_OT_freestyle_color_modifier_add);
+ WM_operatortype_append(SCENE_OT_freestyle_alpha_modifier_add);
+ WM_operatortype_append(SCENE_OT_freestyle_thickness_modifier_add);
+ WM_operatortype_append(SCENE_OT_freestyle_geometry_modifier_add);
+ WM_operatortype_append(SCENE_OT_freestyle_modifier_remove);
+ WM_operatortype_append(SCENE_OT_freestyle_modifier_move);
+ WM_operatortype_append(SCENE_OT_freestyle_modifier_copy);
+ WM_operatortype_append(SCENE_OT_freestyle_stroke_material_create);
#endif
- WM_operatortype_append(TEXTURE_OT_slot_copy);
- WM_operatortype_append(TEXTURE_OT_slot_paste);
- WM_operatortype_append(TEXTURE_OT_slot_move);
+ WM_operatortype_append(TEXTURE_OT_slot_copy);
+ WM_operatortype_append(TEXTURE_OT_slot_paste);
+ WM_operatortype_append(TEXTURE_OT_slot_move);
- /* render_internal.c */
- WM_operatortype_append(RENDER_OT_view_show);
- WM_operatortype_append(RENDER_OT_render);
- WM_operatortype_append(RENDER_OT_view_cancel);
- WM_operatortype_append(RENDER_OT_shutter_curve_preset);
+ /* render_internal.c */
+ WM_operatortype_append(RENDER_OT_view_show);
+ WM_operatortype_append(RENDER_OT_render);
+ WM_operatortype_append(RENDER_OT_view_cancel);
+ WM_operatortype_append(RENDER_OT_shutter_curve_preset);
- /* render_opengl.c */
- WM_operatortype_append(RENDER_OT_opengl);
+ /* render_opengl.c */
+ WM_operatortype_append(RENDER_OT_opengl);
}
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 77b24a1b4d9..c62d6530c6b 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -21,7 +21,6 @@
* \ingroup edrend
*/
-
/* global includes */
#include <stdlib.h>
@@ -29,9 +28,9 @@
#include <string.h>
#ifndef WIN32
-#include <unistd.h>
+# include <unistd.h>
#else
-#include <io.h>
+# include <io.h>
#endif
#include "MEM_guardedalloc.h"
@@ -102,89 +101,90 @@
ImBuf *get_brush_icon(Brush *brush)
{
- static const int flags = IB_rect | IB_multilayer | IB_metadata;
+ static const int flags = IB_rect | IB_multilayer | IB_metadata;
- char path[FILE_MAX];
- const char *folder;
+ char path[FILE_MAX];
+ const char *folder;
- if (!(brush->icon_imbuf)) {
- if (brush->flag & BRUSH_CUSTOM_ICON) {
+ if (!(brush->icon_imbuf)) {
+ if (brush->flag & BRUSH_CUSTOM_ICON) {
- if (brush->icon_filepath[0]) {
- // first use the path directly to try and load the file
+ if (brush->icon_filepath[0]) {
+ // first use the path directly to try and load the file
- BLI_strncpy(path, brush->icon_filepath, sizeof(brush->icon_filepath));
- BLI_path_abs(path, BKE_main_blendfile_path_from_global());
+ BLI_strncpy(path, brush->icon_filepath, sizeof(brush->icon_filepath));
+ BLI_path_abs(path, BKE_main_blendfile_path_from_global());
- /* use default colorspaces for brushes */
- brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
+ /* use default colorspaces for brushes */
+ brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
- // otherwise lets try to find it in other directories
- if (!(brush->icon_imbuf)) {
- folder = BKE_appdir_folder_id(BLENDER_DATAFILES, "brushicons");
+ // otherwise lets try to find it in other directories
+ if (!(brush->icon_imbuf)) {
+ folder = BKE_appdir_folder_id(BLENDER_DATAFILES, "brushicons");
- BLI_make_file_string(BKE_main_blendfile_path_from_global(), path, folder, brush->icon_filepath);
+ BLI_make_file_string(
+ BKE_main_blendfile_path_from_global(), path, folder, brush->icon_filepath);
- if (path[0]) {
- /* use fefault color spaces */
- brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
- }
- }
+ if (path[0]) {
+ /* use fefault color spaces */
+ brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
+ }
+ }
- if (brush->icon_imbuf)
- BKE_icon_changed(BKE_icon_id_ensure(&brush->id));
- }
- }
- }
+ if (brush->icon_imbuf)
+ BKE_icon_changed(BKE_icon_id_ensure(&brush->id));
+ }
+ }
+ }
- if (!(brush->icon_imbuf))
- brush->id.icon_id = 0;
+ if (!(brush->icon_imbuf))
+ brush->id.icon_id = 0;
- return brush->icon_imbuf;
+ return brush->icon_imbuf;
}
typedef struct ShaderPreview {
- /* from wmJob */
- void *owner;
- short *stop, *do_update;
-
- Scene *scene;
- Depsgraph *depsgraph;
- ID *id, *id_copy;
- ID *parent;
- MTex *slot;
-
- /* datablocks with nodes need full copy during preview render, glsl uses it too */
- Material *matcopy;
- Tex *texcopy;
- Light *lampcopy;
- World *worldcopy;
-
- /** Copy of the active objects #Object.color */
- float color[4];
-
- int sizex, sizey;
- unsigned int *pr_rect;
- int pr_method;
- bool own_id_copy;
-
- Main *bmain;
- Main *pr_main;
+ /* from wmJob */
+ void *owner;
+ short *stop, *do_update;
+
+ Scene *scene;
+ Depsgraph *depsgraph;
+ ID *id, *id_copy;
+ ID *parent;
+ MTex *slot;
+
+ /* datablocks with nodes need full copy during preview render, glsl uses it too */
+ Material *matcopy;
+ Tex *texcopy;
+ Light *lampcopy;
+ World *worldcopy;
+
+ /** Copy of the active objects #Object.color */
+ float color[4];
+
+ int sizex, sizey;
+ unsigned int *pr_rect;
+ int pr_method;
+ bool own_id_copy;
+
+ Main *bmain;
+ Main *pr_main;
} ShaderPreview;
typedef struct IconPreviewSize {
- struct IconPreviewSize *next, *prev;
- int sizex, sizey;
- unsigned int *rect;
+ struct IconPreviewSize *next, *prev;
+ int sizex, sizey;
+ unsigned int *rect;
} IconPreviewSize;
typedef struct IconPreview {
- Main *bmain;
- Scene *scene;
- Depsgraph *depsgraph;
- void *owner;
- ID *id, *id_copy;
- ListBase sizes;
+ Main *bmain;
+ Scene *scene;
+ Depsgraph *depsgraph;
+ void *owner;
+ ID *id, *id_copy;
+ ListBase sizes;
} IconPreview;
/* *************************** Preview for buttons *********************** */
@@ -195,1195 +195,1242 @@ static Main *G_pr_main_grease_pencil = NULL;
#ifndef WITH_HEADLESS
static Main *load_main_from_memory(const void *blend, int blend_size)
{
- const int fileflags = G.fileflags;
- Main *bmain = NULL;
- BlendFileData *bfd;
+ const int fileflags = G.fileflags;
+ Main *bmain = NULL;
+ BlendFileData *bfd;
- G.fileflags |= G_FILE_NO_UI;
- bfd = BLO_read_from_memory(blend, blend_size, BLO_READ_SKIP_NONE, NULL);
- if (bfd) {
- bmain = bfd->main;
+ G.fileflags |= G_FILE_NO_UI;
+ bfd = BLO_read_from_memory(blend, blend_size, BLO_READ_SKIP_NONE, NULL);
+ if (bfd) {
+ bmain = bfd->main;
- MEM_freeN(bfd);
- }
- G.fileflags = fileflags;
+ MEM_freeN(bfd);
+ }
+ G.fileflags = fileflags;
- return bmain;
+ return bmain;
}
#endif
void ED_preview_ensure_dbase(void)
{
#ifndef WITH_HEADLESS
- static bool base_initialized = false;
- BLI_assert(BLI_thread_is_main());
- if (!base_initialized) {
- G_pr_main = load_main_from_memory(datatoc_preview_blend, datatoc_preview_blend_size);
- G_pr_main_grease_pencil = load_main_from_memory(datatoc_preview_grease_pencil_blend, datatoc_preview_grease_pencil_blend_size);
- base_initialized = true;
- }
+ static bool base_initialized = false;
+ BLI_assert(BLI_thread_is_main());
+ if (!base_initialized) {
+ G_pr_main = load_main_from_memory(datatoc_preview_blend, datatoc_preview_blend_size);
+ G_pr_main_grease_pencil = load_main_from_memory(datatoc_preview_grease_pencil_blend,
+ datatoc_preview_grease_pencil_blend_size);
+ base_initialized = true;
+ }
#endif
}
static bool check_engine_supports_preview(Scene *scene)
{
- RenderEngineType *type = RE_engines_find(scene->r.engine);
- return (type->flag & RE_USE_PREVIEW) != 0;
+ RenderEngineType *type = RE_engines_find(scene->r.engine);
+ return (type->flag & RE_USE_PREVIEW) != 0;
}
void ED_preview_free_dbase(void)
{
- if (G_pr_main)
- BKE_main_free(G_pr_main);
+ if (G_pr_main)
+ BKE_main_free(G_pr_main);
- if (G_pr_main_grease_pencil)
- BKE_main_free(G_pr_main_grease_pencil);
+ if (G_pr_main_grease_pencil)
+ BKE_main_free(G_pr_main_grease_pencil);
}
static Scene *preview_get_scene(Main *pr_main)
{
- if (pr_main == NULL) return NULL;
+ if (pr_main == NULL)
+ return NULL;
- return pr_main->scenes.first;
+ return pr_main->scenes.first;
}
static const char *preview_collection_name(const char pr_type)
{
- switch (pr_type) {
- case MA_FLAT:
- return "Flat";
- case MA_SPHERE:
- return "Sphere";
- case MA_CUBE:
- return "Cube";
- case MA_SHADERBALL:
- return "Shader Ball";
- case MA_CLOTH:
- return "Cloth";
- case MA_FLUID:
- return "Fluid";
- case MA_SPHERE_A:
- return "World Shader Ball";
- case MA_LAMP:
- return "Lamp";
- case MA_SKY:
- return "Sky";
- case MA_HAIR:
- return "Hair";
- case MA_ATMOS:
- return "Atmosphere";
- default:
- BLI_assert(!"Unknown preview type");
- return "";
- }
+ switch (pr_type) {
+ case MA_FLAT:
+ return "Flat";
+ case MA_SPHERE:
+ return "Sphere";
+ case MA_CUBE:
+ return "Cube";
+ case MA_SHADERBALL:
+ return "Shader Ball";
+ case MA_CLOTH:
+ return "Cloth";
+ case MA_FLUID:
+ return "Fluid";
+ case MA_SPHERE_A:
+ return "World Shader Ball";
+ case MA_LAMP:
+ return "Lamp";
+ case MA_SKY:
+ return "Sky";
+ case MA_HAIR:
+ return "Hair";
+ case MA_ATMOS:
+ return "Atmosphere";
+ default:
+ BLI_assert(!"Unknown preview type");
+ return "";
+ }
}
-static void set_preview_visibility(Scene *scene, ViewLayer *view_layer, char pr_type, int pr_method)
+static void set_preview_visibility(Scene *scene,
+ ViewLayer *view_layer,
+ char pr_type,
+ int pr_method)
{
- /* Set appropriate layer as visibile. */
- LayerCollection *lc = view_layer->layer_collections.first;
- const char *collection_name = preview_collection_name(pr_type);
-
- for (lc = lc->layer_collections.first; lc; lc = lc->next) {
- if (STREQ(lc->collection->id.name + 2, collection_name)) {
- lc->collection->flag &= ~COLLECTION_RESTRICT_RENDER;
- }
- else {
- lc->collection->flag |= COLLECTION_RESTRICT_RENDER;
- }
- }
-
- /* Hide floor for icon renders. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (STREQ(base->object->id.name + 2, "Floor")) {
- if (pr_method == PR_ICON_RENDER) {
- base->object->restrictflag |= OB_RESTRICT_RENDER;
- }
- else {
- base->object->restrictflag &= ~OB_RESTRICT_RENDER;
- }
- }
- }
-
- BKE_layer_collection_sync(scene, view_layer);
+ /* Set appropriate layer as visibile. */
+ LayerCollection *lc = view_layer->layer_collections.first;
+ const char *collection_name = preview_collection_name(pr_type);
+
+ for (lc = lc->layer_collections.first; lc; lc = lc->next) {
+ if (STREQ(lc->collection->id.name + 2, collection_name)) {
+ lc->collection->flag &= ~COLLECTION_RESTRICT_RENDER;
+ }
+ else {
+ lc->collection->flag |= COLLECTION_RESTRICT_RENDER;
+ }
+ }
+
+ /* Hide floor for icon renders. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (STREQ(base->object->id.name + 2, "Floor")) {
+ if (pr_method == PR_ICON_RENDER) {
+ base->object->restrictflag |= OB_RESTRICT_RENDER;
+ }
+ else {
+ base->object->restrictflag &= ~OB_RESTRICT_RENDER;
+ }
+ }
+ }
+
+ BKE_layer_collection_sync(scene, view_layer);
}
static World *preview_get_localized_world(ShaderPreview *sp, World *world)
{
- if (world == NULL) {
- return NULL;
- }
- if (sp->worldcopy != NULL) {
- return sp->worldcopy;
- }
- sp->worldcopy = BKE_world_localize(world);
- BLI_addtail(&sp->pr_main->worlds, sp->worldcopy);
- return sp->worldcopy;
+ if (world == NULL) {
+ return NULL;
+ }
+ if (sp->worldcopy != NULL) {
+ return sp->worldcopy;
+ }
+ sp->worldcopy = BKE_world_localize(world);
+ BLI_addtail(&sp->pr_main->worlds, sp->worldcopy);
+ return sp->worldcopy;
}
static ID *duplicate_ids(ID *id, Depsgraph *depsgraph)
{
- if (id == NULL) {
- /* Non-ID preview render. */
- return NULL;
- }
-
- ID *id_eval = id;
-
- if (depsgraph) {
- id_eval = DEG_get_evaluated_id(depsgraph, id);
- }
-
- switch (GS(id->name)) {
- case ID_MA:
- return (ID *)BKE_material_localize((Material *)id_eval);
- case ID_TE:
- return (ID *)BKE_texture_localize((Tex *)id_eval);
- case ID_LA:
- return (ID *)BKE_light_localize((Light *)id_eval);
- case ID_WO:
- return (ID *)BKE_world_localize((World *)id_eval);
- case ID_IM:
- case ID_BR:
- case ID_SCR:
- return NULL;
- default:
- BLI_assert(!"ID type preview not supported.");
- return NULL;
- }
+ if (id == NULL) {
+ /* Non-ID preview render. */
+ return NULL;
+ }
+
+ ID *id_eval = id;
+
+ if (depsgraph) {
+ id_eval = DEG_get_evaluated_id(depsgraph, id);
+ }
+
+ switch (GS(id->name)) {
+ case ID_MA:
+ return (ID *)BKE_material_localize((Material *)id_eval);
+ case ID_TE:
+ return (ID *)BKE_texture_localize((Tex *)id_eval);
+ case ID_LA:
+ return (ID *)BKE_light_localize((Light *)id_eval);
+ case ID_WO:
+ return (ID *)BKE_world_localize((World *)id_eval);
+ case ID_IM:
+ case ID_BR:
+ case ID_SCR:
+ return NULL;
+ default:
+ BLI_assert(!"ID type preview not supported.");
+ return NULL;
+ }
}
/* call this with a pointer to initialize preview scene */
/* call this with NULL to restore assigned ID pointers in preview scene */
-static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp)
+static Scene *preview_prepare_scene(
+ Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp)
{
- Scene *sce;
- Main *pr_main = sp->pr_main;
-
- memcpy(pr_main->name, BKE_main_blendfile_path(bmain), sizeof(pr_main->name));
-
- sce = preview_get_scene(pr_main);
- if (sce) {
- ViewLayer *view_layer = sce->view_layers.first;
-
- /* this flag tells render to not execute depsgraph or ipos etc */
- sce->r.scemode |= R_BUTS_PREVIEW;
- /* set world always back, is used now */
- sce->world = pr_main->worlds.first;
- /* now: exposure copy */
- if (scene->world) {
- sce->world->exp = scene->world->exp;
- sce->world->range = scene->world->range;
- }
-
- sce->r.color_mgt_flag = scene->r.color_mgt_flag;
- BKE_color_managed_display_settings_copy(&sce->display_settings, &scene->display_settings);
-
- BKE_color_managed_view_settings_free(&sce->view_settings);
- BKE_color_managed_view_settings_copy(&sce->view_settings, &scene->view_settings);
-
- /* prevent overhead for small renders and icons (32) */
- if (id && sp->sizex < 40) {
- sce->r.tilex = sce->r.tiley = 64;
- }
- else {
- sce->r.tilex = sce->r.xsch / 4;
- sce->r.tiley = sce->r.ysch / 4;
- }
-
- if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO)
- sce->r.alphamode = R_ALPHAPREMUL;
- else
- sce->r.alphamode = R_ADDSKY;
-
- sce->r.cfra = scene->r.cfra;
-
- if (id_type == ID_TE) {
- /* Texture is not actually rendered with engine, just set dummy value. */
- BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(sce->r.engine));
- }
- else {
- BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine));
- }
-
- if (id_type == ID_MA) {
- Material *mat = NULL, *origmat = (Material *)id;
-
- if (origmat) {
- /* work on a copy */
- BLI_assert(sp->id_copy != NULL);
- mat = sp->matcopy = (Material *)sp->id_copy;
- sp->id_copy = NULL;
- BLI_addtail(&pr_main->materials, mat);
-
- /* Use current scene world for lighting. */
- if (mat->pr_flag == MA_PREVIEW_WORLD && sp->pr_method == PR_BUTS_RENDER) {
- /* Use current scene world to light sphere. */
- sce->world = preview_get_localized_world(sp, scene->world);
- }
- else if (sce->world) {
- /* Use a default world color. Using the current
- * scene world can be slow if it has big textures. */
- sce->world->use_nodes = false;
- sce->world->horr = 0.05f;
- sce->world->horg = 0.05f;
- sce->world->horb = 0.05f;
- }
-
- set_preview_visibility(sce, view_layer, mat->pr_type, sp->pr_method);
-
- if (sp->pr_method != PR_ICON_RENDER) {
- if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
- /* two previews, they get copied by wmJob */
- BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, true);
- /* WATCH: Accessing origmat is not safe! */
- BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, true);
- }
- }
- }
- else {
- sce->r.mode &= ~(R_OSA);
- }
-
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- 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);
- int actcol = max_ii(base->object->actcol - 1, 0);
-
- if (matar && actcol < base->object->totcol)
- (*matar)[actcol] = mat;
- }
- else if (base->object->type == OB_LAMP) {
- base->flag |= BASE_VISIBLE;
- }
- }
- }
- }
- else if (id_type == ID_TE) {
- Tex *tex = NULL, *origtex = (Tex *)id;
-
- if (origtex) {
- BLI_assert(sp->id_copy != NULL);
- tex = sp->texcopy = (Tex *)sp->id_copy;
- sp->id_copy = NULL;
- BLI_addtail(&pr_main->textures, tex);
- }
-
- if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
- /* two previews, they get copied by wmJob */
- BKE_node_preview_init_tree(tex->nodetree, sp->sizex, sp->sizey, true);
- /* WATCH: Accessing origtex is not safe! */
- BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, true);
- }
- }
- else if (id_type == ID_LA) {
- Light *la = NULL, *origla = (Light *)id;
-
- /* work on a copy */
- if (origla) {
- BLI_assert(sp->id_copy != NULL);
- la = sp->lampcopy = (Light *)sp->id_copy;
- sp->id_copy = NULL;
- BLI_addtail(&pr_main->lights, la);
- }
-
- set_preview_visibility(sce, view_layer, MA_LAMP, sp->pr_method);
-
- if (sce->world) {
- /* Only use lighting from the light. */
- sce->world->use_nodes = false;
- sce->world->horr = 0.0f;
- sce->world->horg = 0.0f;
- sce->world->horb = 0.0f;
- }
-
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (base->object->id.name[2] == 'p') {
- if (base->object->type == OB_LAMP)
- base->object->data = la;
- }
- }
-
- if (la && la->nodetree && sp->pr_method == PR_NODE_RENDER) {
- /* two previews, they get copied by wmJob */
- BKE_node_preview_init_tree(la->nodetree, sp->sizex, sp->sizey, true);
- /* WATCH: Accessing origla is not safe! */
- BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, true);
- }
- }
- else if (id_type == ID_WO) {
- World *wrld = NULL, *origwrld = (World *)id;
-
- if (origwrld) {
- BLI_assert(sp->id_copy != NULL);
- wrld = sp->worldcopy = (World *)sp->id_copy;
- sp->id_copy = NULL;
- BLI_addtail(&pr_main->worlds, wrld);
- }
-
- set_preview_visibility(sce, view_layer, MA_SKY, sp->pr_method);
- sce->world = wrld;
-
- if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
- /* two previews, they get copied by wmJob */
- BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, true);
- /* WATCH: Accessing origwrld is not safe! */
- BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, true);
- }
- }
-
- return sce;
- }
-
- return NULL;
+ Scene *sce;
+ Main *pr_main = sp->pr_main;
+
+ memcpy(pr_main->name, BKE_main_blendfile_path(bmain), sizeof(pr_main->name));
+
+ sce = preview_get_scene(pr_main);
+ if (sce) {
+ ViewLayer *view_layer = sce->view_layers.first;
+
+ /* this flag tells render to not execute depsgraph or ipos etc */
+ sce->r.scemode |= R_BUTS_PREVIEW;
+ /* set world always back, is used now */
+ sce->world = pr_main->worlds.first;
+ /* now: exposure copy */
+ if (scene->world) {
+ sce->world->exp = scene->world->exp;
+ sce->world->range = scene->world->range;
+ }
+
+ sce->r.color_mgt_flag = scene->r.color_mgt_flag;
+ BKE_color_managed_display_settings_copy(&sce->display_settings, &scene->display_settings);
+
+ BKE_color_managed_view_settings_free(&sce->view_settings);
+ BKE_color_managed_view_settings_copy(&sce->view_settings, &scene->view_settings);
+
+ /* prevent overhead for small renders and icons (32) */
+ if (id && sp->sizex < 40) {
+ sce->r.tilex = sce->r.tiley = 64;
+ }
+ else {
+ sce->r.tilex = sce->r.xsch / 4;
+ sce->r.tiley = sce->r.ysch / 4;
+ }
+
+ if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO)
+ sce->r.alphamode = R_ALPHAPREMUL;
+ else
+ sce->r.alphamode = R_ADDSKY;
+
+ sce->r.cfra = scene->r.cfra;
+
+ if (id_type == ID_TE) {
+ /* Texture is not actually rendered with engine, just set dummy value. */
+ BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(sce->r.engine));
+ }
+ else {
+ BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine));
+ }
+
+ if (id_type == ID_MA) {
+ Material *mat = NULL, *origmat = (Material *)id;
+
+ if (origmat) {
+ /* work on a copy */
+ BLI_assert(sp->id_copy != NULL);
+ mat = sp->matcopy = (Material *)sp->id_copy;
+ sp->id_copy = NULL;
+ BLI_addtail(&pr_main->materials, mat);
+
+ /* Use current scene world for lighting. */
+ if (mat->pr_flag == MA_PREVIEW_WORLD && sp->pr_method == PR_BUTS_RENDER) {
+ /* Use current scene world to light sphere. */
+ sce->world = preview_get_localized_world(sp, scene->world);
+ }
+ else if (sce->world) {
+ /* Use a default world color. Using the current
+ * scene world can be slow if it has big textures. */
+ sce->world->use_nodes = false;
+ sce->world->horr = 0.05f;
+ sce->world->horg = 0.05f;
+ sce->world->horb = 0.05f;
+ }
+
+ set_preview_visibility(sce, view_layer, mat->pr_type, sp->pr_method);
+
+ if (sp->pr_method != PR_ICON_RENDER) {
+ if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
+ /* two previews, they get copied by wmJob */
+ BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, true);
+ /* WATCH: Accessing origmat is not safe! */
+ BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, true);
+ }
+ }
+ }
+ else {
+ sce->r.mode &= ~(R_OSA);
+ }
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ 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);
+ int actcol = max_ii(base->object->actcol - 1, 0);
+
+ if (matar && actcol < base->object->totcol)
+ (*matar)[actcol] = mat;
+ }
+ else if (base->object->type == OB_LAMP) {
+ base->flag |= BASE_VISIBLE;
+ }
+ }
+ }
+ }
+ else if (id_type == ID_TE) {
+ Tex *tex = NULL, *origtex = (Tex *)id;
+
+ if (origtex) {
+ BLI_assert(sp->id_copy != NULL);
+ tex = sp->texcopy = (Tex *)sp->id_copy;
+ sp->id_copy = NULL;
+ BLI_addtail(&pr_main->textures, tex);
+ }
+
+ if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
+ /* two previews, they get copied by wmJob */
+ BKE_node_preview_init_tree(tex->nodetree, sp->sizex, sp->sizey, true);
+ /* WATCH: Accessing origtex is not safe! */
+ BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, true);
+ }
+ }
+ else if (id_type == ID_LA) {
+ Light *la = NULL, *origla = (Light *)id;
+
+ /* work on a copy */
+ if (origla) {
+ BLI_assert(sp->id_copy != NULL);
+ la = sp->lampcopy = (Light *)sp->id_copy;
+ sp->id_copy = NULL;
+ BLI_addtail(&pr_main->lights, la);
+ }
+
+ set_preview_visibility(sce, view_layer, MA_LAMP, sp->pr_method);
+
+ if (sce->world) {
+ /* Only use lighting from the light. */
+ sce->world->use_nodes = false;
+ sce->world->horr = 0.0f;
+ sce->world->horg = 0.0f;
+ sce->world->horb = 0.0f;
+ }
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->object->id.name[2] == 'p') {
+ if (base->object->type == OB_LAMP)
+ base->object->data = la;
+ }
+ }
+
+ if (la && la->nodetree && sp->pr_method == PR_NODE_RENDER) {
+ /* two previews, they get copied by wmJob */
+ BKE_node_preview_init_tree(la->nodetree, sp->sizex, sp->sizey, true);
+ /* WATCH: Accessing origla is not safe! */
+ BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, true);
+ }
+ }
+ else if (id_type == ID_WO) {
+ World *wrld = NULL, *origwrld = (World *)id;
+
+ if (origwrld) {
+ BLI_assert(sp->id_copy != NULL);
+ wrld = sp->worldcopy = (World *)sp->id_copy;
+ sp->id_copy = NULL;
+ BLI_addtail(&pr_main->worlds, wrld);
+ }
+
+ set_preview_visibility(sce, view_layer, MA_SKY, sp->pr_method);
+ sce->world = wrld;
+
+ if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
+ /* two previews, they get copied by wmJob */
+ BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, true);
+ /* WATCH: Accessing origwrld is not safe! */
+ BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, true);
+ }
+ }
+
+ return sce;
+ }
+
+ return NULL;
}
/* 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)
{
- Render *re;
- RenderView *rv;
- RenderResult rres;
- char name[32];
- int offx = 0;
- int newx = BLI_rcti_size_x(rect);
- int newy = BLI_rcti_size_y(rect);
- bool ok = false;
-
- if (!split || first) sprintf(name, "Preview %p", (void *)sa);
- else sprintf(name, "SecondPreview %p", (void *)sa);
-
- if (split) {
- if (first) {
- offx = 0;
- newx = newx / 2;
- }
- else {
- offx = newx / 2;
- newx = newx - newx / 2;
- }
- }
-
- /* test if something rendered ok */
- re = RE_GetRender(name);
-
- if (re == NULL)
- return false;
-
- RE_AcquireResultImageViews(re, &rres);
-
- if (!BLI_listbase_is_empty(&rres.views)) {
- /* material preview only needs monoscopy (view 0) */
- rv = RE_RenderViewGetById(&rres, 0);
- }
- else {
- /* possible the job clears the views but we're still drawing T45496 */
- rv = NULL;
- }
-
- if (rv && rv->rectf) {
-
- 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");
- 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);
-
- IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
- immDrawPixelsTex(&state, fx, fy, rres.rectx, rres.recty, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect_byte,
- 1.0f, 1.0f, NULL);
-
- MEM_freeN(rect_byte);
-
- ok = 1;
- }
- }
- }
-
- RE_ReleaseResultImageViews(re, &rres);
-
- return ok;
+ Render *re;
+ RenderView *rv;
+ RenderResult rres;
+ char name[32];
+ int offx = 0;
+ int newx = BLI_rcti_size_x(rect);
+ int newy = BLI_rcti_size_y(rect);
+ bool ok = false;
+
+ if (!split || first)
+ sprintf(name, "Preview %p", (void *)sa);
+ else
+ sprintf(name, "SecondPreview %p", (void *)sa);
+
+ if (split) {
+ if (first) {
+ offx = 0;
+ newx = newx / 2;
+ }
+ else {
+ offx = newx / 2;
+ newx = newx - newx / 2;
+ }
+ }
+
+ /* test if something rendered ok */
+ re = RE_GetRender(name);
+
+ if (re == NULL)
+ return false;
+
+ RE_AcquireResultImageViews(re, &rres);
+
+ if (!BLI_listbase_is_empty(&rres.views)) {
+ /* material preview only needs monoscopy (view 0) */
+ rv = RE_RenderViewGetById(&rres, 0);
+ }
+ else {
+ /* possible the job clears the views but we're still drawing T45496 */
+ rv = NULL;
+ }
+
+ if (rv && rv->rectf) {
+
+ 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");
+ 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);
+
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(&state,
+ fx,
+ fy,
+ rres.rectx,
+ rres.recty,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ GL_NEAREST,
+ rect_byte,
+ 1.0f,
+ 1.0f,
+ NULL);
+
+ MEM_freeN(rect_byte);
+
+ ok = 1;
+ }
+ }
+ }
+
+ RE_ReleaseResultImageViews(re, &rres);
+
+ return ok;
}
void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, rcti *rect)
{
- if (idp) {
- wmWindowManager *wm = CTX_wm_manager(C);
- ScrArea *sa = 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);
- rcti newrect;
- int ok;
- int newx = BLI_rcti_size_x(rect);
- int newy = BLI_rcti_size_y(rect);
-
- newrect.xmin = rect->xmin;
- newrect.xmax = rect->xmin;
- newrect.ymin = rect->ymin;
- 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);
- }
- else
- ok = ed_preview_draw_rect(sa, 0, 0, rect, &newrect);
-
- if (ok)
- *rect = newrect;
-
- /* start a new preview render job if signaled through sbuts->preview,
- * 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)))
- {
- if (sbuts != NULL) {
- sbuts->preview = 0;
- }
- ED_preview_shader_job(C, sa, id, parent, slot, newx, newy, PR_BUTS_RENDER);
- }
- }
+ if (idp) {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ ScrArea *sa = 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);
+ rcti newrect;
+ int ok;
+ int newx = BLI_rcti_size_x(rect);
+ int newy = BLI_rcti_size_y(rect);
+
+ newrect.xmin = rect->xmin;
+ newrect.xmax = rect->xmin;
+ newrect.ymin = rect->ymin;
+ 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);
+ }
+ else
+ ok = ed_preview_draw_rect(sa, 0, 0, rect, &newrect);
+
+ if (ok)
+ *rect = newrect;
+
+ /* start a new preview render job if signaled through sbuts->preview,
+ * 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))) {
+ if (sbuts != NULL) {
+ sbuts->preview = 0;
+ }
+ ED_preview_shader_job(C, sa, id, parent, slot, newx, newy, PR_BUTS_RENDER);
+ }
+ }
}
/* **************************** new shader preview system ****************** */
/* inside thread, called by renderer, sets job update value */
-static void shader_preview_update(void *spv, RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect))
+static void shader_preview_update(void *spv,
+ RenderResult *UNUSED(rr),
+ volatile struct rcti *UNUSED(rect))
{
- ShaderPreview *sp = spv;
+ ShaderPreview *sp = spv;
- *(sp->do_update) = true;
+ *(sp->do_update) = true;
}
/* called by renderer, checks job value */
static int shader_preview_break(void *spv)
{
- ShaderPreview *sp = spv;
+ ShaderPreview *sp = spv;
- return *(sp->stop);
+ return *(sp->stop);
}
/* outside thread, called before redraw notifiers, it moves finished preview over */
static void shader_preview_updatejob(void *spv)
{
- ShaderPreview *sp = spv;
-
- if (sp->id) {
- if (sp->pr_method == PR_NODE_RENDER) {
- if (GS(sp->id->name) == ID_MA) {
- Material *mat = (Material *)sp->id;
-
- if (sp->matcopy && mat->nodetree && sp->matcopy->nodetree)
- ntreeLocalSync(sp->matcopy->nodetree, mat->nodetree);
- }
- else if (GS(sp->id->name) == ID_TE) {
- Tex *tex = (Tex *)sp->id;
-
- if (sp->texcopy && tex->nodetree && sp->texcopy->nodetree)
- ntreeLocalSync(sp->texcopy->nodetree, tex->nodetree);
- }
- else if (GS(sp->id->name) == ID_WO) {
- World *wrld = (World *)sp->id;
-
- if (sp->worldcopy && wrld->nodetree && sp->worldcopy->nodetree)
- ntreeLocalSync(sp->worldcopy->nodetree, wrld->nodetree);
- }
- else if (GS(sp->id->name) == ID_LA) {
- Light *la = (Light *)sp->id;
-
- if (sp->lampcopy && la->nodetree && sp->lampcopy->nodetree)
- ntreeLocalSync(sp->lampcopy->nodetree, la->nodetree);
- }
- }
- }
+ ShaderPreview *sp = spv;
+
+ if (sp->id) {
+ if (sp->pr_method == PR_NODE_RENDER) {
+ if (GS(sp->id->name) == ID_MA) {
+ Material *mat = (Material *)sp->id;
+
+ if (sp->matcopy && mat->nodetree && sp->matcopy->nodetree)
+ ntreeLocalSync(sp->matcopy->nodetree, mat->nodetree);
+ }
+ else if (GS(sp->id->name) == ID_TE) {
+ Tex *tex = (Tex *)sp->id;
+
+ if (sp->texcopy && tex->nodetree && sp->texcopy->nodetree)
+ ntreeLocalSync(sp->texcopy->nodetree, tex->nodetree);
+ }
+ else if (GS(sp->id->name) == ID_WO) {
+ World *wrld = (World *)sp->id;
+
+ if (sp->worldcopy && wrld->nodetree && sp->worldcopy->nodetree)
+ ntreeLocalSync(sp->worldcopy->nodetree, wrld->nodetree);
+ }
+ else if (GS(sp->id->name) == ID_LA) {
+ Light *la = (Light *)sp->id;
+
+ if (sp->lampcopy && la->nodetree && sp->lampcopy->nodetree)
+ ntreeLocalSync(sp->lampcopy->nodetree, la->nodetree);
+ }
+ }
+ }
}
/* Renders texture directly to render buffer. */
static void shader_preview_texture(ShaderPreview *sp, Tex *tex, Scene *sce, Render *re)
{
- /* Setup output buffer. */
- int width = sp->sizex;
- int height = sp->sizey;
-
- /* This is needed otherwise no RenderResult is created. */
- sce->r.scemode &= ~R_BUTS_PREVIEW;
- RE_InitState(re, NULL, &sce->r, &sce->view_layers, NULL, width, height, NULL);
- RE_SetScene(re, sce);
-
- /* Create buffer in empty RenderView created in the init step. */
- RenderResult *rr = RE_AcquireResultWrite(re);
- RenderView *rv = (RenderView *)rr->views.first;
- rv->rectf = MEM_callocN(sizeof(float) * 4 * width * height, "texture render result");
- RE_ReleaseResult(re);
-
- /* Get texture image pool (if any) */
- struct ImagePool *img_pool = BKE_image_pool_new();
- BKE_texture_fetch_images_for_pool(tex, img_pool);
-
- /* Fill in image buffer. */
- float *rect_float = rv->rectf;
- float tex_coord[3] = {0.0f, 0.0f, 0.0f};
- bool color_manage = true;
-
- for (int y = 0; y < height; y++) {
- /* Tex coords between -1.0f and 1.0f. */
- tex_coord[1] = ((float)y / (float)height) * 2.0f - 1.0f;
-
- for (int x = 0; x < width; x++) {
- tex_coord[0] = ((float)x / (float)height) * 2.0f - 1.0f;
-
- /* Evaluate texture at tex_coord .*/
- TexResult texres = {0};
- BKE_texture_get_value_ex(sce, tex, tex_coord, &texres, img_pool, color_manage);
-
- rect_float[0] = texres.tr;
- rect_float[1] = texres.tg;
- rect_float[2] = texres.tb;
- rect_float[3] = 1.0f;
-
- rect_float += 4;
- }
-
- /* Check if we should cancel texture preview. */
- if (shader_preview_break(sp)) {
- break;
- }
- }
-
- BKE_image_pool_free(img_pool);
+ /* Setup output buffer. */
+ int width = sp->sizex;
+ int height = sp->sizey;
+
+ /* This is needed otherwise no RenderResult is created. */
+ sce->r.scemode &= ~R_BUTS_PREVIEW;
+ RE_InitState(re, NULL, &sce->r, &sce->view_layers, NULL, width, height, NULL);
+ RE_SetScene(re, sce);
+
+ /* Create buffer in empty RenderView created in the init step. */
+ RenderResult *rr = RE_AcquireResultWrite(re);
+ RenderView *rv = (RenderView *)rr->views.first;
+ rv->rectf = MEM_callocN(sizeof(float) * 4 * width * height, "texture render result");
+ RE_ReleaseResult(re);
+
+ /* Get texture image pool (if any) */
+ struct ImagePool *img_pool = BKE_image_pool_new();
+ BKE_texture_fetch_images_for_pool(tex, img_pool);
+
+ /* Fill in image buffer. */
+ float *rect_float = rv->rectf;
+ float tex_coord[3] = {0.0f, 0.0f, 0.0f};
+ bool color_manage = true;
+
+ for (int y = 0; y < height; y++) {
+ /* Tex coords between -1.0f and 1.0f. */
+ tex_coord[1] = ((float)y / (float)height) * 2.0f - 1.0f;
+
+ for (int x = 0; x < width; x++) {
+ tex_coord[0] = ((float)x / (float)height) * 2.0f - 1.0f;
+
+ /* Evaluate texture at tex_coord .*/
+ TexResult texres = {0};
+ BKE_texture_get_value_ex(sce, tex, tex_coord, &texres, img_pool, color_manage);
+
+ rect_float[0] = texres.tr;
+ rect_float[1] = texres.tg;
+ rect_float[2] = texres.tb;
+ rect_float[3] = 1.0f;
+
+ rect_float += 4;
+ }
+
+ /* Check if we should cancel texture preview. */
+ if (shader_preview_break(sp)) {
+ break;
+ }
+ }
+
+ BKE_image_pool_free(img_pool);
}
static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int first)
{
- Render *re;
- Scene *sce;
- float oldlens;
- short idtype = GS(id->name);
- char name[32];
- int sizex;
- Main *pr_main = sp->pr_main;
- ID *id_eval = id;
-
- if (sp->depsgraph) {
- id_eval = DEG_get_evaluated_id(sp->depsgraph, id);
- }
-
- /* in case of split preview, use border render */
- if (split) {
- if (first) sizex = sp->sizex / 2;
- else sizex = sp->sizex - sp->sizex / 2;
- }
- else {
- sizex = sp->sizex;
- }
-
- /* we have to set preview variables first */
- sce = preview_get_scene(pr_main);
- if (sce) {
- sce->r.xsch = sizex;
- sce->r.ysch = sp->sizey;
- sce->r.size = 100;
- }
-
-
- /* get the stuff from the builtin preview dbase */
- sce = preview_prepare_scene(sp->bmain, sp->scene, id_eval, idtype, sp);
- if (sce == NULL) return;
-
- if (!split || first) sprintf(name, "Preview %p", sp->owner);
- else sprintf(name, "SecondPreview %p", sp->owner);
- re = RE_GetRender(name);
-
- /* full refreshed render from first tile */
- if (re == NULL)
- re = RE_NewRender(name);
-
- /* sce->r gets copied in RE_InitState! */
- sce->r.scemode &= ~(R_MATNODE_PREVIEW | R_TEXNODE_PREVIEW);
- sce->r.scemode &= ~R_NO_IMAGE_LOAD;
-
- if (sp->pr_method == PR_ICON_RENDER) {
- sce->r.scemode |= R_NO_IMAGE_LOAD;
- sce->r.mode |= R_OSA;
- }
- else if (sp->pr_method == PR_NODE_RENDER) {
- if (idtype == ID_MA) sce->r.scemode |= R_MATNODE_PREVIEW;
- else if (idtype == ID_TE) sce->r.scemode |= R_TEXNODE_PREVIEW;
- sce->r.mode &= ~R_OSA;
- }
- else { /* PR_BUTS_RENDER */
- sce->r.mode |= R_OSA;
- }
-
-
- /* callbacs are cleared on GetRender() */
- if (ELEM(sp->pr_method, PR_BUTS_RENDER, PR_NODE_RENDER)) {
- RE_display_update_cb(re, sp, shader_preview_update);
- }
- /* set this for all previews, default is react to G.is_break still */
- RE_test_break_cb(re, sp, shader_preview_break);
-
- /* lens adjust */
- oldlens = ((Camera *)sce->camera->data)->lens;
- if (sizex > sp->sizey)
- ((Camera *)sce->camera->data)->lens *= (float)sp->sizey / (float)sizex;
-
- /* entire cycle for render engine */
- if (idtype == ID_TE) {
- shader_preview_texture(sp, (Tex *)id, sce, re);
- }
- else {
- /* Render preview scene */
- RE_PreviewRender(re, pr_main, sce);
- }
-
- ((Camera *)sce->camera->data)->lens = oldlens;
-
- /* handle results */
- if (sp->pr_method == PR_ICON_RENDER) {
- // char *rct= (char *)(sp->pr_rect + 32*16 + 16);
-
- if (sp->pr_rect)
- RE_ResultGet32(re, sp->pr_rect);
- }
-
- /* unassign the pointers, reset vars */
- preview_prepare_scene(sp->bmain, sp->scene, NULL, GS(id->name), sp);
-
- /* XXX bad exception, end-exec is not being called in render, because it uses local main */
-// if (idtype == ID_TE) {
-// Tex *tex= (Tex *)id;
-// if (tex->use_nodes && tex->nodetree)
-// ntreeEndExecTree(tex->nodetree);
-// }
-
+ Render *re;
+ Scene *sce;
+ float oldlens;
+ short idtype = GS(id->name);
+ char name[32];
+ int sizex;
+ Main *pr_main = sp->pr_main;
+ ID *id_eval = id;
+
+ if (sp->depsgraph) {
+ id_eval = DEG_get_evaluated_id(sp->depsgraph, id);
+ }
+
+ /* in case of split preview, use border render */
+ if (split) {
+ if (first)
+ sizex = sp->sizex / 2;
+ else
+ sizex = sp->sizex - sp->sizex / 2;
+ }
+ else {
+ sizex = sp->sizex;
+ }
+
+ /* we have to set preview variables first */
+ sce = preview_get_scene(pr_main);
+ if (sce) {
+ sce->r.xsch = sizex;
+ sce->r.ysch = sp->sizey;
+ sce->r.size = 100;
+ }
+
+ /* get the stuff from the builtin preview dbase */
+ sce = preview_prepare_scene(sp->bmain, sp->scene, id_eval, idtype, sp);
+ if (sce == NULL)
+ return;
+
+ if (!split || first)
+ sprintf(name, "Preview %p", sp->owner);
+ else
+ sprintf(name, "SecondPreview %p", sp->owner);
+ re = RE_GetRender(name);
+
+ /* full refreshed render from first tile */
+ if (re == NULL)
+ re = RE_NewRender(name);
+
+ /* sce->r gets copied in RE_InitState! */
+ sce->r.scemode &= ~(R_MATNODE_PREVIEW | R_TEXNODE_PREVIEW);
+ sce->r.scemode &= ~R_NO_IMAGE_LOAD;
+
+ if (sp->pr_method == PR_ICON_RENDER) {
+ sce->r.scemode |= R_NO_IMAGE_LOAD;
+ sce->r.mode |= R_OSA;
+ }
+ else if (sp->pr_method == PR_NODE_RENDER) {
+ if (idtype == ID_MA)
+ sce->r.scemode |= R_MATNODE_PREVIEW;
+ else if (idtype == ID_TE)
+ sce->r.scemode |= R_TEXNODE_PREVIEW;
+ sce->r.mode &= ~R_OSA;
+ }
+ else { /* PR_BUTS_RENDER */
+ sce->r.mode |= R_OSA;
+ }
+
+ /* callbacs are cleared on GetRender() */
+ if (ELEM(sp->pr_method, PR_BUTS_RENDER, PR_NODE_RENDER)) {
+ RE_display_update_cb(re, sp, shader_preview_update);
+ }
+ /* set this for all previews, default is react to G.is_break still */
+ RE_test_break_cb(re, sp, shader_preview_break);
+
+ /* lens adjust */
+ oldlens = ((Camera *)sce->camera->data)->lens;
+ if (sizex > sp->sizey)
+ ((Camera *)sce->camera->data)->lens *= (float)sp->sizey / (float)sizex;
+
+ /* entire cycle for render engine */
+ if (idtype == ID_TE) {
+ shader_preview_texture(sp, (Tex *)id, sce, re);
+ }
+ else {
+ /* Render preview scene */
+ RE_PreviewRender(re, pr_main, sce);
+ }
+
+ ((Camera *)sce->camera->data)->lens = oldlens;
+
+ /* handle results */
+ if (sp->pr_method == PR_ICON_RENDER) {
+ // char *rct= (char *)(sp->pr_rect + 32*16 + 16);
+
+ if (sp->pr_rect)
+ RE_ResultGet32(re, sp->pr_rect);
+ }
+
+ /* unassign the pointers, reset vars */
+ preview_prepare_scene(sp->bmain, sp->scene, NULL, GS(id->name), sp);
+
+ /* XXX bad exception, end-exec is not being called in render, because it uses local main */
+ // if (idtype == ID_TE) {
+ // Tex *tex= (Tex *)id;
+ // if (tex->use_nodes && tex->nodetree)
+ // ntreeEndExecTree(tex->nodetree);
+ // }
}
/* runs inside thread for material and icons */
static void shader_preview_startjob(void *customdata, short *stop, short *do_update)
{
- ShaderPreview *sp = customdata;
+ ShaderPreview *sp = customdata;
- sp->stop = stop;
- sp->do_update = do_update;
+ sp->stop = stop;
+ sp->do_update = do_update;
- if (sp->parent) {
- shader_preview_render(sp, sp->id, 1, 1);
- shader_preview_render(sp, sp->parent, 1, 0);
- }
- else
- shader_preview_render(sp, sp->id, 0, 0);
+ if (sp->parent) {
+ shader_preview_render(sp, sp->id, 1, 1);
+ shader_preview_render(sp, sp->parent, 1, 0);
+ }
+ else
+ shader_preview_render(sp, sp->id, 0, 0);
- *do_update = true;
+ *do_update = true;
}
static void shader_preview_free(void *customdata)
{
- ShaderPreview *sp = customdata;
- Main *pr_main = sp->pr_main;
-
- if (sp->matcopy) {
- sp->id_copy = (ID *)sp->matcopy;
- BLI_remlink(&pr_main->materials, sp->matcopy);
- }
- if (sp->texcopy) {
- sp->id_copy = (ID *)sp->texcopy;
- BLI_remlink(&pr_main->textures, sp->texcopy);
- }
- if (sp->worldcopy) {
- sp->id_copy = (ID *)sp->worldcopy;
- BLI_remlink(&pr_main->worlds, sp->worldcopy);
- }
- if (sp->lampcopy) {
- sp->id_copy = (ID *)sp->lampcopy;
- BLI_remlink(&pr_main->lights, sp->lampcopy);
- }
- if (sp->id_copy) {
- /* node previews */
- shader_preview_updatejob(sp);
- }
- if (sp->id_copy && sp->own_id_copy) {
- struct IDProperty *properties;
- /* get rid of copied ID */
- properties = IDP_GetProperties(sp->id_copy, false);
- if (properties) {
- IDP_FreeProperty_ex(properties, false);
- MEM_freeN(properties);
- }
- switch (GS(sp->id_copy->name)) {
- case ID_MA:
- BKE_material_free((Material *)sp->id_copy);
- break;
- case ID_TE:
- BKE_texture_free((Tex *)sp->id_copy);
- break;
- case ID_LA:
- BKE_light_free((Light *)sp->id_copy);
- break;
- case ID_WO:
- BKE_world_free((World *)sp->id_copy);
- break;
- default:
- BLI_assert(!"ID type preview not supported.");
- break;
- }
- MEM_freeN(sp->id_copy);
- }
-
- MEM_freeN(sp);
+ ShaderPreview *sp = customdata;
+ Main *pr_main = sp->pr_main;
+
+ if (sp->matcopy) {
+ sp->id_copy = (ID *)sp->matcopy;
+ BLI_remlink(&pr_main->materials, sp->matcopy);
+ }
+ if (sp->texcopy) {
+ sp->id_copy = (ID *)sp->texcopy;
+ BLI_remlink(&pr_main->textures, sp->texcopy);
+ }
+ if (sp->worldcopy) {
+ sp->id_copy = (ID *)sp->worldcopy;
+ BLI_remlink(&pr_main->worlds, sp->worldcopy);
+ }
+ if (sp->lampcopy) {
+ sp->id_copy = (ID *)sp->lampcopy;
+ BLI_remlink(&pr_main->lights, sp->lampcopy);
+ }
+ if (sp->id_copy) {
+ /* node previews */
+ shader_preview_updatejob(sp);
+ }
+ if (sp->id_copy && sp->own_id_copy) {
+ struct IDProperty *properties;
+ /* get rid of copied ID */
+ properties = IDP_GetProperties(sp->id_copy, false);
+ if (properties) {
+ IDP_FreeProperty_ex(properties, false);
+ MEM_freeN(properties);
+ }
+ switch (GS(sp->id_copy->name)) {
+ case ID_MA:
+ BKE_material_free((Material *)sp->id_copy);
+ break;
+ case ID_TE:
+ BKE_texture_free((Tex *)sp->id_copy);
+ break;
+ case ID_LA:
+ BKE_light_free((Light *)sp->id_copy);
+ break;
+ case ID_WO:
+ BKE_world_free((World *)sp->id_copy);
+ break;
+ default:
+ BLI_assert(!"ID type preview not supported.");
+ break;
+ }
+ MEM_freeN(sp->id_copy);
+ }
+
+ MEM_freeN(sp);
}
/* ************************* icon preview ********************** */
static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned int *rect)
{
- struct ImBuf *ima;
- unsigned int *drect, *srect;
- float scaledx, scaledy;
- short ex, ey, dx, dy;
+ struct ImBuf *ima;
+ unsigned int *drect, *srect;
+ float scaledx, scaledy;
+ short ex, ey, dx, dy;
- /* paranoia test */
- if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL))
- return;
+ /* paranoia test */
+ if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL))
+ return;
- /* waste of cpu cyles... but the imbuf API has no other way to scale fast (ton) */
- ima = IMB_dupImBuf(ibuf);
+ /* waste of cpu cyles... but the imbuf API has no other way to scale fast (ton) */
+ ima = IMB_dupImBuf(ibuf);
- if (!ima)
- return;
+ if (!ima)
+ return;
- if (ima->x > ima->y) {
- scaledx = (float)w;
- scaledy = ( (float)ima->y / (float)ima->x) * (float)w;
- }
- else {
- scaledx = ( (float)ima->x / (float)ima->y) * (float)h;
- scaledy = (float)h;
- }
+ if (ima->x > ima->y) {
+ scaledx = (float)w;
+ scaledy = ((float)ima->y / (float)ima->x) * (float)w;
+ }
+ else {
+ scaledx = ((float)ima->x / (float)ima->y) * (float)h;
+ scaledy = (float)h;
+ }
- ex = (short)scaledx;
- ey = (short)scaledy;
+ ex = (short)scaledx;
+ ey = (short)scaledy;
- dx = (w - ex) / 2;
- dy = (h - ey) / 2;
+ dx = (w - ex) / 2;
+ dy = (h - ey) / 2;
- IMB_scalefastImBuf(ima, ex, ey);
+ IMB_scalefastImBuf(ima, ex, ey);
- /* if needed, convert to 32 bits */
- if (ima->rect == NULL)
- IMB_rect_from_float(ima);
+ /* if needed, convert to 32 bits */
+ if (ima->rect == NULL)
+ IMB_rect_from_float(ima);
- srect = ima->rect;
- drect = rect;
+ srect = ima->rect;
+ drect = rect;
- drect += dy * w + dx;
- for (; ey > 0; ey--) {
- memcpy(drect, srect, ex * sizeof(int));
- drect += w;
- srect += ima->x;
- }
+ drect += dy * w + dx;
+ for (; ey > 0; ey--) {
+ memcpy(drect, srect, ex * sizeof(int));
+ drect += w;
+ srect += ima->x;
+ }
- IMB_freeImBuf(ima);
+ IMB_freeImBuf(ima);
}
static void set_alpha(char *cp, int sizex, int sizey, char alpha)
{
- int a, size = sizex * sizey;
+ int a, size = sizex * sizey;
- for (a = 0; a < size; a++, cp += 4)
- cp[3] = alpha;
+ for (a = 0; a < size; a++, cp += 4)
+ cp[3] = alpha;
}
static void icon_preview_startjob(void *customdata, short *stop, short *do_update)
{
- ShaderPreview *sp = customdata;
-
- if (sp->pr_method == PR_ICON_DEFERRED) {
- PreviewImage *prv = sp->owner;
- ImBuf *thumb;
- char *deferred_data = PRV_DEFERRED_DATA(prv);
- int source = deferred_data[0];
- char *path = &deferred_data[1];
-
-// printf("generating deferred %d×%d preview for %s\n", sp->sizex, sp->sizey, path);
-
- thumb = IMB_thumb_manage(path, THB_LARGE, source);
-
- if (thumb) {
- /* PreviewImage assumes premultiplied alhpa... */
- IMB_premultiply_alpha(thumb);
-
- icon_copy_rect(thumb, sp->sizex, sp->sizey, sp->pr_rect);
- IMB_freeImBuf(thumb);
- }
- }
- else {
- ID *id = sp->id;
- short idtype = GS(id->name);
-
- if (idtype == ID_IM) {
- Image *ima = (Image *)id;
- ImBuf *ibuf = NULL;
- ImageUser iuser = {NULL};
-
- /* ima->ok is zero when Image cannot load */
- if (ima == NULL || ima->ok == 0)
- return;
-
- /* setup dummy image user */
- iuser.ok = iuser.framenr = 1;
- iuser.scene = sp->scene;
-
- /* elubie: this needs to be changed: here image is always loaded if not
- * already there. Very expensive for large images. Need to find a way to
- * only get existing ibuf */
- ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
- if (ibuf == NULL || ibuf->rect == NULL) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- return;
- }
-
- icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect);
-
- *do_update = true;
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
- else if (idtype == ID_BR) {
- Brush *br = (Brush *)id;
-
- br->icon_imbuf = get_brush_icon(br);
-
- memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(unsigned int));
-
- if (!(br->icon_imbuf) || !(br->icon_imbuf->rect))
- return;
-
- icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect);
-
- *do_update = true;
- }
- else if (idtype == ID_SCR) {
- bScreen *screen = (bScreen *)id;
-
- ED_screen_preview_render(screen, sp->sizex, sp->sizey, sp->pr_rect);
- *do_update = true;
- }
- else {
- /* re-use shader job */
- shader_preview_startjob(customdata, stop, do_update);
-
- /* world is rendered with alpha=0, so it wasn't displayed
- * this could be render option for sky to, for later */
- if (idtype == ID_WO) {
- set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255);
- }
- }
- }
+ ShaderPreview *sp = customdata;
+
+ if (sp->pr_method == PR_ICON_DEFERRED) {
+ PreviewImage *prv = sp->owner;
+ ImBuf *thumb;
+ char *deferred_data = PRV_DEFERRED_DATA(prv);
+ int source = deferred_data[0];
+ char *path = &deferred_data[1];
+
+ // printf("generating deferred %d×%d preview for %s\n", sp->sizex, sp->sizey, path);
+
+ thumb = IMB_thumb_manage(path, THB_LARGE, source);
+
+ if (thumb) {
+ /* PreviewImage assumes premultiplied alhpa... */
+ IMB_premultiply_alpha(thumb);
+
+ icon_copy_rect(thumb, sp->sizex, sp->sizey, sp->pr_rect);
+ IMB_freeImBuf(thumb);
+ }
+ }
+ else {
+ ID *id = sp->id;
+ short idtype = GS(id->name);
+
+ if (idtype == ID_IM) {
+ Image *ima = (Image *)id;
+ ImBuf *ibuf = NULL;
+ ImageUser iuser = {NULL};
+
+ /* ima->ok is zero when Image cannot load */
+ if (ima == NULL || ima->ok == 0)
+ return;
+
+ /* setup dummy image user */
+ iuser.ok = iuser.framenr = 1;
+ iuser.scene = sp->scene;
+
+ /* elubie: this needs to be changed: here image is always loaded if not
+ * already there. Very expensive for large images. Need to find a way to
+ * only get existing ibuf */
+ ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
+ if (ibuf == NULL || ibuf->rect == NULL) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ return;
+ }
+
+ icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect);
+
+ *do_update = true;
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+ else if (idtype == ID_BR) {
+ Brush *br = (Brush *)id;
+
+ br->icon_imbuf = get_brush_icon(br);
+
+ memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(unsigned int));
+
+ if (!(br->icon_imbuf) || !(br->icon_imbuf->rect))
+ return;
+
+ icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect);
+
+ *do_update = true;
+ }
+ else if (idtype == ID_SCR) {
+ bScreen *screen = (bScreen *)id;
+
+ ED_screen_preview_render(screen, sp->sizex, sp->sizey, sp->pr_rect);
+ *do_update = true;
+ }
+ else {
+ /* re-use shader job */
+ shader_preview_startjob(customdata, stop, do_update);
+
+ /* world is rendered with alpha=0, so it wasn't displayed
+ * this could be render option for sky to, for later */
+ if (idtype == ID_WO) {
+ set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255);
+ }
+ }
+ }
}
/* use same function for icon & shader, so the job manager
* does not run two of them at the same time. */
-static void common_preview_startjob(void *customdata, short *stop, short *do_update, float *UNUSED(progress))
+static void common_preview_startjob(void *customdata,
+ short *stop,
+ short *do_update,
+ float *UNUSED(progress))
{
- ShaderPreview *sp = customdata;
+ ShaderPreview *sp = customdata;
- if (ELEM(sp->pr_method, PR_ICON_RENDER, PR_ICON_DEFERRED))
- icon_preview_startjob(customdata, stop, do_update);
- else
- shader_preview_startjob(customdata, stop, do_update);
+ if (ELEM(sp->pr_method, PR_ICON_RENDER, PR_ICON_DEFERRED))
+ icon_preview_startjob(customdata, stop, do_update);
+ else
+ shader_preview_startjob(customdata, stop, do_update);
}
/* exported functions */
static void icon_preview_add_size(IconPreview *ip, unsigned int *rect, int sizex, int sizey)
{
- IconPreviewSize *cur_size = ip->sizes.first, *new_size;
+ IconPreviewSize *cur_size = ip->sizes.first, *new_size;
- while (cur_size) {
- if (cur_size->sizex == sizex && cur_size->sizey == sizey) {
- /* requested size is already in list, no need to add it again */
- return;
- }
+ while (cur_size) {
+ if (cur_size->sizex == sizex && cur_size->sizey == sizey) {
+ /* requested size is already in list, no need to add it again */
+ return;
+ }
- cur_size = cur_size->next;
- }
+ cur_size = cur_size->next;
+ }
- new_size = MEM_callocN(sizeof(IconPreviewSize), "IconPreviewSize");
- new_size->sizex = sizex;
- new_size->sizey = sizey;
- new_size->rect = rect;
+ new_size = MEM_callocN(sizeof(IconPreviewSize), "IconPreviewSize");
+ new_size->sizex = sizex;
+ new_size->sizey = sizey;
+ new_size->rect = rect;
- BLI_addtail(&ip->sizes, new_size);
+ BLI_addtail(&ip->sizes, new_size);
}
-static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short *do_update, float *progress)
+static void icon_preview_startjob_all_sizes(void *customdata,
+ short *stop,
+ short *do_update,
+ float *progress)
{
- IconPreview *ip = (IconPreview *)customdata;
- IconPreviewSize *cur_size;
-
- for (cur_size = ip->sizes.first; cur_size; cur_size = cur_size->next) {
- PreviewImage *prv = ip->owner;
-
- if (prv->tag & PRV_TAG_DEFFERED_DELETE) {
- /* Non-thread-protected reading is not an issue here. */
- continue;
- }
-
- if (!check_engine_supports_preview(ip->scene)) {
- continue;
- }
-
- ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
- const bool is_render = !(prv->tag & PRV_TAG_DEFFERED);
-
- /* construct shader preview from image size and previewcustomdata */
- sp->scene = ip->scene;
- sp->depsgraph = ip->depsgraph;
- sp->owner = ip->owner;
- sp->sizex = cur_size->sizex;
- sp->sizey = cur_size->sizey;
- sp->pr_method = is_render ? PR_ICON_RENDER : PR_ICON_DEFERRED;
- sp->pr_rect = cur_size->rect;
- sp->id = ip->id;
- sp->id_copy = ip->id_copy;
- sp->bmain = ip->bmain;
- sp->own_id_copy = false;
- Material *ma = NULL;
-
- if (is_render) {
- BLI_assert(ip->id);
-
- /* grease pencil use its own preview file */
- if (GS(ip->id->name) == ID_MA) {
- ma = (Material *)ip->id;
- }
-
- if ((ma == NULL) || (ma->gp_style == NULL)) {
- sp->pr_main = G_pr_main;
- }
- else {
- sp->pr_main = G_pr_main_grease_pencil;
- }
- }
-
- common_preview_startjob(sp, stop, do_update, progress);
- shader_preview_free(sp);
- }
+ IconPreview *ip = (IconPreview *)customdata;
+ IconPreviewSize *cur_size;
+
+ for (cur_size = ip->sizes.first; cur_size; cur_size = cur_size->next) {
+ PreviewImage *prv = ip->owner;
+
+ if (prv->tag & PRV_TAG_DEFFERED_DELETE) {
+ /* Non-thread-protected reading is not an issue here. */
+ continue;
+ }
+
+ if (!check_engine_supports_preview(ip->scene)) {
+ continue;
+ }
+
+ ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
+ const bool is_render = !(prv->tag & PRV_TAG_DEFFERED);
+
+ /* construct shader preview from image size and previewcustomdata */
+ sp->scene = ip->scene;
+ sp->depsgraph = ip->depsgraph;
+ sp->owner = ip->owner;
+ sp->sizex = cur_size->sizex;
+ sp->sizey = cur_size->sizey;
+ sp->pr_method = is_render ? PR_ICON_RENDER : PR_ICON_DEFERRED;
+ sp->pr_rect = cur_size->rect;
+ sp->id = ip->id;
+ sp->id_copy = ip->id_copy;
+ sp->bmain = ip->bmain;
+ sp->own_id_copy = false;
+ Material *ma = NULL;
+
+ if (is_render) {
+ BLI_assert(ip->id);
+
+ /* grease pencil use its own preview file */
+ if (GS(ip->id->name) == ID_MA) {
+ ma = (Material *)ip->id;
+ }
+
+ if ((ma == NULL) || (ma->gp_style == NULL)) {
+ sp->pr_main = G_pr_main;
+ }
+ else {
+ sp->pr_main = G_pr_main_grease_pencil;
+ }
+ }
+
+ common_preview_startjob(sp, stop, do_update, progress);
+ shader_preview_free(sp);
+ }
}
static void icon_preview_endjob(void *customdata)
{
- IconPreview *ip = customdata;
+ IconPreview *ip = customdata;
- if (ip->id) {
+ if (ip->id) {
- if (GS(ip->id->name) == ID_BR)
- WM_main_add_notifier(NC_BRUSH | NA_EDITED, ip->id);
+ if (GS(ip->id->name) == ID_BR)
+ WM_main_add_notifier(NC_BRUSH | NA_EDITED, ip->id);
#if 0
- if (GS(ip->id->name) == ID_MA) {
- Material *ma = (Material *)ip->id;
- PreviewImage *prv_img = ma->preview;
- int i;
-
- /* signal to gpu texture */
- for (i = 0; i < NUM_ICON_SIZES; ++i) {
- if (prv_img->gputexture[i]) {
- GPU_texture_free(prv_img->gputexture[i]);
- prv_img->gputexture[i] = NULL;
- WM_main_add_notifier(NC_MATERIAL|ND_SHADING_DRAW, ip->id);
- }
- }
- }
+ if (GS(ip->id->name) == ID_MA) {
+ Material *ma = (Material *)ip->id;
+ PreviewImage *prv_img = ma->preview;
+ int i;
+
+ /* signal to gpu texture */
+ for (i = 0; i < NUM_ICON_SIZES; ++i) {
+ if (prv_img->gputexture[i]) {
+ GPU_texture_free(prv_img->gputexture[i]);
+ prv_img->gputexture[i] = NULL;
+ WM_main_add_notifier(NC_MATERIAL|ND_SHADING_DRAW, ip->id);
+ }
+ }
+ }
#endif
- }
-
- if (ip->owner) {
- PreviewImage *prv_img = ip->owner;
- prv_img->tag &= ~PRV_TAG_DEFFERED_RENDERING;
- if (prv_img->tag & PRV_TAG_DEFFERED_DELETE) {
- BLI_assert(prv_img->tag & PRV_TAG_DEFFERED);
- BKE_previewimg_cached_release_pointer(prv_img);
- }
- }
+ }
+
+ if (ip->owner) {
+ PreviewImage *prv_img = ip->owner;
+ prv_img->tag &= ~PRV_TAG_DEFFERED_RENDERING;
+ if (prv_img->tag & PRV_TAG_DEFFERED_DELETE) {
+ BLI_assert(prv_img->tag & PRV_TAG_DEFFERED);
+ BKE_previewimg_cached_release_pointer(prv_img);
+ }
+ }
}
static void icon_preview_free(void *customdata)
{
- IconPreview *ip = (IconPreview *)customdata;
-
- if (ip->id_copy) {
- /* Feels a bit hacky just to reuse shader_preview_free() */
- ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
- sp->id_copy = ip->id_copy;
- sp->own_id_copy = true;
- shader_preview_free(sp);
- ip->id_copy = NULL;
- }
-
- BLI_freelistN(&ip->sizes);
- MEM_freeN(ip);
+ IconPreview *ip = (IconPreview *)customdata;
+
+ if (ip->id_copy) {
+ /* Feels a bit hacky just to reuse shader_preview_free() */
+ ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
+ sp->id_copy = ip->id_copy;
+ sp->own_id_copy = true;
+ shader_preview_free(sp);
+ ip->id_copy = NULL;
+ }
+
+ BLI_freelistN(&ip->sizes);
+ 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, unsigned int *rect, int sizex, int sizey)
{
- IconPreview ip = {NULL};
- short stop = false, update = false;
- float progress = 0.0f;
+ IconPreview ip = {NULL};
+ short stop = false, update = false;
+ float progress = 0.0f;
- ED_preview_ensure_dbase();
+ ED_preview_ensure_dbase();
- ip.bmain = bmain;
- ip.scene = scene;
- ip.owner = BKE_previewimg_id_ensure(id);
- ip.id = id;
- ip.id_copy = duplicate_ids(id, NULL);
+ ip.bmain = bmain;
+ ip.scene = scene;
+ ip.owner = BKE_previewimg_id_ensure(id);
+ ip.id = id;
+ ip.id_copy = duplicate_ids(id, NULL);
- icon_preview_add_size(&ip, rect, sizex, sizey);
+ icon_preview_add_size(&ip, rect, sizex, sizey);
- icon_preview_startjob_all_sizes(&ip, &stop, &update, &progress);
+ icon_preview_startjob_all_sizes(&ip, &stop, &update, &progress);
- icon_preview_endjob(&ip);
+ icon_preview_endjob(&ip);
- BLI_freelistN(&ip.sizes);
+ BLI_freelistN(&ip.sizes);
}
-void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *rect, int sizex, int sizey)
+void ED_preview_icon_job(
+ const bContext *C, void *owner, ID *id, unsigned int *rect, int sizex, int sizey)
{
- wmJob *wm_job;
- IconPreview *ip, *old_ip;
-
- ED_preview_ensure_dbase();
-
- /* suspended start means it starts after 1 timer step, see WM_jobs_timer below */
- wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner, "Icon Preview",
- WM_JOB_EXCL_RENDER | WM_JOB_SUSPEND, WM_JOB_TYPE_RENDER_PREVIEW);
-
- ip = MEM_callocN(sizeof(IconPreview), "icon preview");
-
- /* render all resolutions from suspended job too */
- old_ip = WM_jobs_customdata_get(wm_job);
- if (old_ip)
- BLI_movelisttolist(&ip->sizes, &old_ip->sizes);
-
- /* customdata for preview thread */
- ip->bmain = CTX_data_main(C);
- ip->scene = CTX_data_scene(C);
- ip->depsgraph = CTX_data_depsgraph(C);
- ip->owner = owner;
- ip->id = id;
- ip->id_copy = duplicate_ids(id, ip->depsgraph);
-
- icon_preview_add_size(ip, rect, sizex, sizey);
-
- /* Special threading hack: warn main code that this preview is being rendered and cannot be freed... */
- {
- PreviewImage *prv_img = owner;
- if (prv_img->tag & PRV_TAG_DEFFERED) {
- prv_img->tag |= PRV_TAG_DEFFERED_RENDERING;
- }
- }
-
- /* setup job */
- WM_jobs_customdata_set(wm_job, ip, icon_preview_free);
- WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW);
- WM_jobs_callbacks(wm_job, icon_preview_startjob_all_sizes, NULL, NULL, icon_preview_endjob);
-
- WM_jobs_start(CTX_wm_manager(C), wm_job);
+ wmJob *wm_job;
+ IconPreview *ip, *old_ip;
+
+ ED_preview_ensure_dbase();
+
+ /* suspended start means it starts after 1 timer step, see WM_jobs_timer below */
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ owner,
+ "Icon Preview",
+ WM_JOB_EXCL_RENDER | WM_JOB_SUSPEND,
+ WM_JOB_TYPE_RENDER_PREVIEW);
+
+ ip = MEM_callocN(sizeof(IconPreview), "icon preview");
+
+ /* render all resolutions from suspended job too */
+ old_ip = WM_jobs_customdata_get(wm_job);
+ if (old_ip)
+ BLI_movelisttolist(&ip->sizes, &old_ip->sizes);
+
+ /* customdata for preview thread */
+ ip->bmain = CTX_data_main(C);
+ ip->scene = CTX_data_scene(C);
+ ip->depsgraph = CTX_data_depsgraph(C);
+ ip->owner = owner;
+ ip->id = id;
+ ip->id_copy = duplicate_ids(id, ip->depsgraph);
+
+ icon_preview_add_size(ip, rect, sizex, sizey);
+
+ /* Special threading hack: warn main code that this preview is being rendered and cannot be freed... */
+ {
+ PreviewImage *prv_img = owner;
+ if (prv_img->tag & PRV_TAG_DEFFERED) {
+ prv_img->tag |= PRV_TAG_DEFFERED_RENDERING;
+ }
+ }
+
+ /* setup job */
+ WM_jobs_customdata_set(wm_job, ip, icon_preview_free);
+ WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW);
+ WM_jobs_callbacks(wm_job, icon_preview_startjob_all_sizes, NULL, NULL, icon_preview_endjob);
+
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
}
-void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, MTex *slot, int sizex, int sizey, int method)
+void ED_preview_shader_job(const bContext *C,
+ void *owner,
+ ID *id,
+ ID *parent,
+ MTex *slot,
+ int sizex,
+ int sizey,
+ int method)
{
- Object *ob = CTX_data_active_object(C);
- wmJob *wm_job;
- ShaderPreview *sp;
- Scene *scene = CTX_data_scene(C);
- short id_type = GS(id->name);
-
- /* Use workspace render only for buttons Window, since the other previews are related to the datablock. */
-
- if (!check_engine_supports_preview(scene)) {
- return;
- }
-
- /* Only texture node preview is supported with Cycles. */
- if (method == PR_NODE_RENDER && id_type != ID_TE) {
- return;
- }
-
- ED_preview_ensure_dbase();
-
- wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner, "Shader Preview",
- WM_JOB_EXCL_RENDER, WM_JOB_TYPE_RENDER_PREVIEW);
- sp = MEM_callocN(sizeof(ShaderPreview), "shader preview");
-
- /* customdata for preview thread */
- sp->scene = scene;
- sp->depsgraph = CTX_data_depsgraph(C);
- sp->owner = owner;
- sp->sizex = sizex;
- sp->sizey = sizey;
- sp->pr_method = method;
- sp->id = id;
- sp->id_copy = duplicate_ids(id, sp->depsgraph);
- sp->own_id_copy = true;
- sp->parent = parent;
- sp->slot = slot;
- sp->bmain = CTX_data_main(C);
- Material *ma = NULL;
-
- /* hardcoded preview .blend for Eevee + Cycles, this should be solved
- * once with custom preview .blend path for external engines */
-
- /* grease pencil use its own preview file */
- if (GS(id->name) == ID_MA) {
- ma = (Material *)id;
- }
-
- if ((ma == NULL) || (ma->gp_style == NULL)) {
- sp->pr_main = G_pr_main;
- }
- else {
- sp->pr_main = G_pr_main_grease_pencil;
- }
-
- if (ob && ob->totcol) {
- copy_v4_v4(sp->color, ob->color);
- }
- else {
- ARRAY_SET_ITEMS(sp->color, 0.0f, 0.0f, 0.0f, 1.0f);
- }
-
- /* setup job */
- WM_jobs_customdata_set(wm_job, sp, shader_preview_free);
- WM_jobs_timer(wm_job, 0.1, NC_MATERIAL, NC_MATERIAL);
- WM_jobs_callbacks(wm_job, common_preview_startjob, NULL, shader_preview_updatejob, NULL);
-
- WM_jobs_start(CTX_wm_manager(C), wm_job);
+ Object *ob = CTX_data_active_object(C);
+ wmJob *wm_job;
+ ShaderPreview *sp;
+ Scene *scene = CTX_data_scene(C);
+ short id_type = GS(id->name);
+
+ /* Use workspace render only for buttons Window, since the other previews are related to the datablock. */
+
+ if (!check_engine_supports_preview(scene)) {
+ return;
+ }
+
+ /* Only texture node preview is supported with Cycles. */
+ if (method == PR_NODE_RENDER && id_type != ID_TE) {
+ return;
+ }
+
+ ED_preview_ensure_dbase();
+
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ owner,
+ "Shader Preview",
+ WM_JOB_EXCL_RENDER,
+ WM_JOB_TYPE_RENDER_PREVIEW);
+ sp = MEM_callocN(sizeof(ShaderPreview), "shader preview");
+
+ /* customdata for preview thread */
+ sp->scene = scene;
+ sp->depsgraph = CTX_data_depsgraph(C);
+ sp->owner = owner;
+ sp->sizex = sizex;
+ sp->sizey = sizey;
+ sp->pr_method = method;
+ sp->id = id;
+ sp->id_copy = duplicate_ids(id, sp->depsgraph);
+ sp->own_id_copy = true;
+ sp->parent = parent;
+ sp->slot = slot;
+ sp->bmain = CTX_data_main(C);
+ Material *ma = NULL;
+
+ /* hardcoded preview .blend for Eevee + Cycles, this should be solved
+ * once with custom preview .blend path for external engines */
+
+ /* grease pencil use its own preview file */
+ if (GS(id->name) == ID_MA) {
+ ma = (Material *)id;
+ }
+
+ if ((ma == NULL) || (ma->gp_style == NULL)) {
+ sp->pr_main = G_pr_main;
+ }
+ else {
+ sp->pr_main = G_pr_main_grease_pencil;
+ }
+
+ if (ob && ob->totcol) {
+ copy_v4_v4(sp->color, ob->color);
+ }
+ else {
+ ARRAY_SET_ITEMS(sp->color, 0.0f, 0.0f, 0.0f, 1.0f);
+ }
+
+ /* setup job */
+ WM_jobs_customdata_set(wm_job, sp, shader_preview_free);
+ WM_jobs_timer(wm_job, 0.1, NC_MATERIAL, NC_MATERIAL);
+ WM_jobs_callbacks(wm_job, common_preview_startjob, NULL, shader_preview_updatejob, NULL);
+
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
}
void ED_preview_kill_jobs(wmWindowManager *wm, Main *UNUSED(bmain))
{
- if (wm)
- WM_jobs_kill(wm, NULL, common_preview_startjob);
+ if (wm)
+ WM_jobs_kill(wm, NULL, common_preview_startjob);
}
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 9bf9b15cd07..70157abf2ef 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -100,1890 +100,1937 @@
*/
static Object **object_array_for_shading(bContext *C, uint *r_objects_len)
{
- ScrArea *sa = CTX_wm_area(C);
- SpaceProperties *sbuts = NULL;
- View3D *v3d = NULL;
- if (sa->spacetype == SPACE_PROPERTIES) {
- sbuts = sa->spacedata.first;
- }
- else if (sa->spacetype == SPACE_VIEW3D) {
- v3d = sa->spacedata.first;
- }
-
- Object **objects;
- if (sbuts && sbuts->pinid && GS(sbuts->pinid->name) == ID_OB) {
- objects = MEM_mallocN(sizeof(*objects), __func__);
- objects[0] = (Object *)sbuts->pinid;
- *r_objects_len = 1;
- }
- else {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, v3d, r_objects_len);
- }
- return objects;
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceProperties *sbuts = NULL;
+ View3D *v3d = NULL;
+ if (sa->spacetype == SPACE_PROPERTIES) {
+ sbuts = sa->spacedata.first;
+ }
+ else if (sa->spacetype == SPACE_VIEW3D) {
+ v3d = sa->spacedata.first;
+ }
+
+ Object **objects;
+ if (sbuts && sbuts->pinid && GS(sbuts->pinid->name) == ID_OB) {
+ objects = MEM_mallocN(sizeof(*objects), __func__);
+ objects[0] = (Object *)sbuts->pinid;
+ *r_objects_len = 1;
+ }
+ else {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, v3d, r_objects_len);
+ }
+ return objects;
}
/********************** material slot operators *********************/
static int material_slot_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_context(C);
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_context(C);
- if (!ob)
- return OPERATOR_CANCELLED;
+ if (!ob)
+ return OPERATOR_CANCELLED;
- BKE_object_material_slot_add(bmain, ob);
+ BKE_object_material_slot_add(bmain, ob);
- if (ob->mode & OB_MODE_TEXTURE_PAINT) {
- Scene *scene = CTX_data_scene(C);
- BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
- WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
- }
+ if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ Scene *scene = CTX_data_scene(C);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ }
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob);
- WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob);
+ WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_material_slot_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Material Slot";
- ot->idname = "OBJECT_OT_material_slot_add";
- ot->description = "Add a new material slot";
+ /* identifiers */
+ ot->name = "Add Material Slot";
+ ot->idname = "OBJECT_OT_material_slot_add";
+ ot->description = "Add a new material slot";
- /* api callbacks */
- ot->exec = material_slot_add_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->exec = material_slot_add_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
static int material_slot_remove_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- if (!ob)
- return OPERATOR_CANCELLED;
+ if (!ob)
+ return OPERATOR_CANCELLED;
- /* Removing material slots in edit mode screws things up, see bug #21822.*/
- if (ob == CTX_data_edit_object(C)) {
- BKE_report(op->reports, RPT_ERROR, "Unable to remove material slot in edit mode");
- return OPERATOR_CANCELLED;
- }
+ /* Removing material slots in edit mode screws things up, see bug #21822.*/
+ if (ob == CTX_data_edit_object(C)) {
+ BKE_report(op->reports, RPT_ERROR, "Unable to remove material slot in edit mode");
+ return OPERATOR_CANCELLED;
+ }
- BKE_object_material_slot_remove(CTX_data_main(C), ob);
+ BKE_object_material_slot_remove(CTX_data_main(C), ob);
- if (ob->mode & OB_MODE_TEXTURE_PAINT) {
- Scene *scene = CTX_data_scene(C);
- BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
- WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
- }
+ if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ Scene *scene = CTX_data_scene(C);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob);
- WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob);
+ WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_material_slot_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Material Slot";
- ot->idname = "OBJECT_OT_material_slot_remove";
- ot->description = "Remove the selected material slot";
+ /* identifiers */
+ ot->name = "Remove Material Slot";
+ ot->idname = "OBJECT_OT_material_slot_remove";
+ ot->description = "Remove the selected material slot";
- /* api callbacks */
- ot->exec = material_slot_remove_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->exec = material_slot_remove_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op))
{
- View3D *v3d = CTX_wm_view3d(C);
- bool changed_multi = false;
-
- 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) {
- continue;
- }
- bool changed = false;
- if (ob->type == OB_MESH) {
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMFace *efa;
- BMIter iter;
-
- if (em) {
- 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;
- }
- }
- }
- }
- else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
- Nurb *nu;
- ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data);
-
- if (nurbs) {
- for (nu = nurbs->first; nu; nu = nu->next) {
- if (ED_curve_nurb_select_check(v3d, nu)) {
- changed = true;
- nu->mat_nr = ob->actcol - 1;
- }
- }
- }
- }
- else if (ob->type == OB_FONT) {
- EditFont *ef = ((Curve *)ob->data)->editfont;
- int i, selstart, selend;
-
- if (ef && BKE_vfont_select_get(ob, &selstart, &selend)) {
- for (i = selstart; i <= selend; i++) {
- changed = true;
- ef->textbufinfo[i].mat_nr = ob->actcol;
- }
- }
- }
-
- if (changed) {
- changed_multi = true;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- }
- }
- MEM_freeN(objects);
-
- return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ View3D *v3d = CTX_wm_view3d(C);
+ bool changed_multi = false;
+
+ 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) {
+ continue;
+ }
+ bool changed = false;
+ if (ob->type == OB_MESH) {
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMFace *efa;
+ BMIter iter;
+
+ if (em) {
+ 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;
+ }
+ }
+ }
+ }
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ Nurb *nu;
+ ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data);
+
+ if (nurbs) {
+ for (nu = nurbs->first; nu; nu = nu->next) {
+ if (ED_curve_nurb_select_check(v3d, nu)) {
+ changed = true;
+ nu->mat_nr = ob->actcol - 1;
+ }
+ }
+ }
+ }
+ else if (ob->type == OB_FONT) {
+ EditFont *ef = ((Curve *)ob->data)->editfont;
+ int i, selstart, selend;
+
+ if (ef && BKE_vfont_select_get(ob, &selstart, &selend)) {
+ for (i = selstart; i <= selend; i++) {
+ changed = true;
+ ef->textbufinfo[i].mat_nr = ob->actcol;
+ }
+ }
+ }
+
+ if (changed) {
+ changed_multi = true;
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ }
+ }
+ MEM_freeN(objects);
+
+ return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void OBJECT_OT_material_slot_assign(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Assign Material Slot";
- ot->idname = "OBJECT_OT_material_slot_assign";
- ot->description = "Assign active material slot to selection";
+ /* identifiers */
+ ot->name = "Assign Material Slot";
+ ot->idname = "OBJECT_OT_material_slot_assign";
+ ot->description = "Assign active material slot to selection";
- /* api callbacks */
- ot->exec = material_slot_assign_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->exec = material_slot_assign_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
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;
-
- 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];
- short mat_nr_active = -1;
-
- if (ob->totcol == 0) {
- continue;
- }
- if (obact && (mat_active == give_current_material(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 thats not a common use case. */
- for (short i = 0; i < ob->totcol; i++) {
- const Material *mat = give_current_material(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);
-
- if (em) {
- changed = EDBM_deselect_by_material(em, mat_nr_active, select);
- }
- }
- else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
- ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data);
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- int a;
-
- if (nurbs) {
- for (nu = nurbs->first; nu; nu = nu->next) {
- if (nu->mat_nr == mat_nr_active) {
- if (nu->bezt) {
- a = nu->pntsu;
- bezt = nu->bezt;
- while (a--) {
- if (bezt->hide == 0) {
- changed = true;
- if (select) {
- bezt->f1 |= SELECT;
- bezt->f2 |= SELECT;
- bezt->f3 |= SELECT;
- }
- else {
- bezt->f1 &= ~SELECT;
- bezt->f2 &= ~SELECT;
- bezt->f3 &= ~SELECT;
- }
- }
- bezt++;
- }
- }
- else if (nu->bp) {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a--) {
- if (bp->hide == 0) {
- changed = true;
- if (select) bp->f1 |= SELECT;
- else bp->f1 &= ~SELECT;
- }
- bp++;
- }
- }
- }
- }
- }
- }
-
- if (changed) {
- changed_multi = true;
- DEG_id_tag_update(ob->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
- }
- }
-
- MEM_freeN(objects);
-
- return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ bool changed_multi = false;
+ Object *obact = CTX_data_active_object(C);
+ const Material *mat_active = obact ? give_current_material(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];
+ short mat_nr_active = -1;
+
+ if (ob->totcol == 0) {
+ continue;
+ }
+ if (obact && (mat_active == give_current_material(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 thats not a common use case. */
+ for (short i = 0; i < ob->totcol; i++) {
+ const Material *mat = give_current_material(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);
+
+ if (em) {
+ changed = EDBM_deselect_by_material(em, mat_nr_active, select);
+ }
+ }
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a;
+
+ if (nurbs) {
+ for (nu = nurbs->first; nu; nu = nu->next) {
+ if (nu->mat_nr == mat_nr_active) {
+ if (nu->bezt) {
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ while (a--) {
+ if (bezt->hide == 0) {
+ changed = true;
+ if (select) {
+ bezt->f1 |= SELECT;
+ bezt->f2 |= SELECT;
+ bezt->f3 |= SELECT;
+ }
+ else {
+ bezt->f1 &= ~SELECT;
+ bezt->f2 &= ~SELECT;
+ bezt->f3 &= ~SELECT;
+ }
+ }
+ bezt++;
+ }
+ }
+ else if (nu->bp) {
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a--) {
+ if (bp->hide == 0) {
+ changed = true;
+ if (select)
+ bp->f1 |= SELECT;
+ else
+ bp->f1 &= ~SELECT;
+ }
+ bp++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (changed) {
+ changed_multi = true;
+ DEG_id_tag_update(ob->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
+ }
+ }
+
+ MEM_freeN(objects);
+
+ return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static int material_slot_select_exec(bContext *C, wmOperator *UNUSED(op))
{
- return material_slot_de_select(C, true);
+ return material_slot_de_select(C, true);
}
void OBJECT_OT_material_slot_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Material Slot";
- ot->idname = "OBJECT_OT_material_slot_select";
- ot->description = "Select by active material slot";
+ /* identifiers */
+ ot->name = "Select Material Slot";
+ ot->idname = "OBJECT_OT_material_slot_select";
+ ot->description = "Select by active material slot";
- /* api callbacks */
- ot->exec = material_slot_select_exec;
+ /* api callbacks */
+ ot->exec = material_slot_select_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
static int material_slot_deselect_exec(bContext *C, wmOperator *UNUSED(op))
{
- return material_slot_de_select(C, false);
+ return material_slot_de_select(C, false);
}
void OBJECT_OT_material_slot_deselect(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Deselect Material Slot";
- ot->idname = "OBJECT_OT_material_slot_deselect";
- ot->description = "Deselect by active material slot";
+ /* identifiers */
+ ot->name = "Deselect Material Slot";
+ ot->idname = "OBJECT_OT_material_slot_deselect";
+ ot->description = "Deselect by active material slot";
- /* api callbacks */
- ot->exec = material_slot_deselect_exec;
+ /* api callbacks */
+ ot->exec = material_slot_deselect_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
-
static int material_slot_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_context(C);
- Material ***matar;
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_context(C);
+ Material ***matar;
- if (!ob || !(matar = give_matarar(ob)))
- return OPERATOR_CANCELLED;
+ if (!ob || !(matar = give_matarar(ob)))
+ return OPERATOR_CANCELLED;
- CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects)
- {
- if (ob != ob_iter && give_matarar(ob_iter)) {
- if (ob->data != ob_iter->data)
- assign_matarar(bmain, ob_iter, matar, ob->totcol);
+ CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
+ if (ob != ob_iter && give_matarar(ob_iter)) {
+ if (ob->data != ob_iter->data)
+ assign_matarar(bmain, ob_iter, matar, ob->totcol);
- if (ob_iter->totcol == ob->totcol) {
- ob_iter->actcol = ob->actcol;
- DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
- }
- }
- }
- CTX_DATA_END;
+ if (ob_iter->totcol == ob->totcol) {
+ ob_iter->actcol = ob->actcol;
+ DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
+ }
+ }
+ }
+ CTX_DATA_END;
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
void OBJECT_OT_material_slot_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Material to Selected";
- ot->idname = "OBJECT_OT_material_slot_copy";
- ot->description = "Copy material to selected objects";
+ /* identifiers */
+ ot->name = "Copy Material to Selected";
+ ot->idname = "OBJECT_OT_material_slot_copy";
+ ot->description = "Copy material to selected objects";
- /* api callbacks */
- ot->exec = material_slot_copy_exec;
+ /* api callbacks */
+ ot->exec = material_slot_copy_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
static int material_slot_move_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- unsigned int *slot_remap;
- int index_pair[2];
+ unsigned int *slot_remap;
+ int index_pair[2];
- int dir = RNA_enum_get(op->ptr, "direction");
+ int dir = RNA_enum_get(op->ptr, "direction");
- if (!ob || ob->totcol < 2) {
- return OPERATOR_CANCELLED;
- }
+ if (!ob || ob->totcol < 2) {
+ return OPERATOR_CANCELLED;
+ }
- /* up */
- if (dir == 1 && ob->actcol > 1) {
- index_pair[0] = ob->actcol - 2;
- index_pair[1] = ob->actcol - 1;
- ob->actcol--;
- }
- /* down */
- else if (dir == -1 && ob->actcol < ob->totcol) {
- index_pair[0] = ob->actcol - 1;
- index_pair[1] = ob->actcol - 0;
- ob->actcol++;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ /* up */
+ if (dir == 1 && ob->actcol > 1) {
+ index_pair[0] = ob->actcol - 2;
+ index_pair[1] = ob->actcol - 1;
+ ob->actcol--;
+ }
+ /* down */
+ else if (dir == -1 && ob->actcol < ob->totcol) {
+ index_pair[0] = ob->actcol - 1;
+ index_pair[1] = ob->actcol - 0;
+ ob->actcol++;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
- slot_remap = MEM_mallocN(sizeof(unsigned int) * ob->totcol, __func__);
+ slot_remap = MEM_mallocN(sizeof(unsigned int) * ob->totcol, __func__);
- range_vn_u(slot_remap, ob->totcol, 0);
+ range_vn_u(slot_remap, ob->totcol, 0);
- slot_remap[index_pair[0]] = index_pair[1];
- slot_remap[index_pair[1]] = index_pair[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_material_remap_object(ob, slot_remap);
- MEM_freeN(slot_remap);
+ MEM_freeN(slot_remap);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_material_slot_move(wmOperatorType *ot)
{
- static const EnumPropertyItem material_slot_move[] = {
- {1, "UP", 0, "Up", ""},
- {-1, "DOWN", 0, "Down", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem material_slot_move[] = {
+ {1, "UP", 0, "Up", ""},
+ {-1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Move Material";
- ot->idname = "OBJECT_OT_material_slot_move";
- ot->description = "Move the active material up/down in the list";
+ /* identifiers */
+ ot->name = "Move Material";
+ ot->idname = "OBJECT_OT_material_slot_move";
+ ot->description = "Move the active material up/down in the list";
- /* api callbacks */
- ot->exec = material_slot_move_exec;
+ /* api callbacks */
+ ot->exec = material_slot_move_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_enum(ot->srna, "direction", material_slot_move, 0, "Direction",
- "Direction to move the active material towards");
+ RNA_def_enum(ot->srna,
+ "direction",
+ material_slot_move,
+ 0,
+ "Direction",
+ "Direction to move the active material towards");
}
/********************** new material operator *********************/
static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
{
- Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
- Main *bmain = CTX_data_main(C);
- PointerRNA ptr, idptr;
- PropertyRNA *prop;
-
- /* hook into UI */
- UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
-
- Object *ob = (prop && RNA_struct_is_a(ptr.type, &RNA_Object)) ? ptr.data : NULL;
-
- /* add or copy material */
- if (ma) {
- Material *new_ma = NULL;
- BKE_id_copy_ex(bmain, &ma->id, (ID **)&new_ma, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS);
- ma = new_ma;
- }
- else {
- const char *name = DATA_("Material");
- if (!(ob != NULL && ob->type == OB_GPENCIL)) {
- ma = BKE_material_add(bmain, name);
- }
- else {
- ma = BKE_material_add_gpencil(bmain, name);
- }
- ED_node_shader_default(C, &ma->id);
- ma->use_nodes = true;
- }
-
-
- if (prop) {
- 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) {
- BKE_object_material_slot_add(bmain, ob);
- }
- }
-
- /* when creating new ID blocks, use is already 1, but RNA
- * pointer use also increases user, so this compensates it */
- id_us_min(&ma->id);
-
- RNA_id_pointer_create(&ma->id, &idptr);
- RNA_property_pointer_set(&ptr, prop, idptr);
- RNA_property_update(C, &ptr, prop);
- }
-
- WM_event_add_notifier(C, NC_MATERIAL | NA_ADDED, ma);
-
- return OPERATOR_FINISHED;
+ Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
+ Main *bmain = CTX_data_main(C);
+ PointerRNA ptr, idptr;
+ PropertyRNA *prop;
+
+ /* hook into UI */
+ UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
+
+ Object *ob = (prop && RNA_struct_is_a(ptr.type, &RNA_Object)) ? ptr.data : NULL;
+
+ /* add or copy material */
+ if (ma) {
+ Material *new_ma = NULL;
+ BKE_id_copy_ex(bmain, &ma->id, (ID **)&new_ma, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS);
+ ma = new_ma;
+ }
+ else {
+ const char *name = DATA_("Material");
+ if (!(ob != NULL && ob->type == OB_GPENCIL)) {
+ ma = BKE_material_add(bmain, name);
+ }
+ else {
+ ma = BKE_material_add_gpencil(bmain, name);
+ }
+ ED_node_shader_default(C, &ma->id);
+ ma->use_nodes = true;
+ }
+
+ if (prop) {
+ 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) {
+ BKE_object_material_slot_add(bmain, ob);
+ }
+ }
+
+ /* when creating new ID blocks, use is already 1, but RNA
+ * pointer use also increases user, so this compensates it */
+ id_us_min(&ma->id);
+
+ RNA_id_pointer_create(&ma->id, &idptr);
+ RNA_property_pointer_set(&ptr, prop, idptr);
+ RNA_property_update(C, &ptr, prop);
+ }
+
+ WM_event_add_notifier(C, NC_MATERIAL | NA_ADDED, ma);
+
+ return OPERATOR_FINISHED;
}
void MATERIAL_OT_new(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "New Material";
- ot->idname = "MATERIAL_OT_new";
- ot->description = "Add a new material";
+ /* identifiers */
+ ot->name = "New Material";
+ ot->idname = "MATERIAL_OT_new";
+ ot->description = "Add a new material";
- /* api callbacks */
- ot->exec = new_material_exec;
+ /* api callbacks */
+ ot->exec = new_material_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
/********************** new texture operator *********************/
static int new_texture_exec(bContext *C, wmOperator *UNUSED(op))
{
- Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
- Main *bmain = CTX_data_main(C);
- PointerRNA ptr, idptr;
- PropertyRNA *prop;
+ Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
+ Main *bmain = CTX_data_main(C);
+ PointerRNA ptr, idptr;
+ PropertyRNA *prop;
- /* add or copy texture */
- if (tex) {
- tex = BKE_texture_copy(bmain, tex);
- }
- else {
- tex = BKE_texture_add(bmain, DATA_("Texture"));
- }
+ /* add or copy texture */
+ if (tex) {
+ tex = BKE_texture_copy(bmain, tex);
+ }
+ else {
+ tex = BKE_texture_add(bmain, DATA_("Texture"));
+ }
- /* hook into UI */
- UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
+ /* hook into UI */
+ UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
- if (prop) {
- /* when creating new ID blocks, use is already 1, but RNA
- * pointer use also increases user, so this compensates it */
- id_us_min(&tex->id);
+ if (prop) {
+ /* when creating new ID blocks, use is already 1, but RNA
+ * pointer use also increases user, so this compensates it */
+ id_us_min(&tex->id);
- RNA_id_pointer_create(&tex->id, &idptr);
- RNA_property_pointer_set(&ptr, prop, idptr);
- RNA_property_update(C, &ptr, prop);
- }
+ RNA_id_pointer_create(&tex->id, &idptr);
+ RNA_property_pointer_set(&ptr, prop, idptr);
+ RNA_property_update(C, &ptr, prop);
+ }
- WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, tex);
+ WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, tex);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXTURE_OT_new(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "New Texture";
- ot->idname = "TEXTURE_OT_new";
- ot->description = "Add a new texture";
+ /* identifiers */
+ ot->name = "New Texture";
+ ot->idname = "TEXTURE_OT_new";
+ ot->description = "Add a new texture";
- /* api callbacks */
- ot->exec = new_texture_exec;
+ /* api callbacks */
+ ot->exec = new_texture_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
/********************** new world operator *********************/
static int new_world_exec(bContext *C, wmOperator *UNUSED(op))
{
- World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
- Main *bmain = CTX_data_main(C);
- PointerRNA ptr, idptr;
- PropertyRNA *prop;
+ World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
+ Main *bmain = CTX_data_main(C);
+ PointerRNA ptr, idptr;
+ PropertyRNA *prop;
- /* add or copy world */
- if (wo) {
- wo = BKE_world_copy(bmain, wo);
- }
- else {
- wo = BKE_world_add(bmain, DATA_("World"));
- ED_node_shader_default(C, &wo->id);
- wo->use_nodes = true;
- }
+ /* add or copy world */
+ if (wo) {
+ wo = BKE_world_copy(bmain, wo);
+ }
+ else {
+ wo = BKE_world_add(bmain, DATA_("World"));
+ ED_node_shader_default(C, &wo->id);
+ wo->use_nodes = true;
+ }
- /* hook into UI */
- UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
+ /* hook into UI */
+ UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
- if (prop) {
- /* when creating new ID blocks, use is already 1, but RNA
- * pointer use also increases user, so this compensates it */
- id_us_min(&wo->id);
+ if (prop) {
+ /* when creating new ID blocks, use is already 1, but RNA
+ * pointer use also increases user, so this compensates it */
+ id_us_min(&wo->id);
- RNA_id_pointer_create(&wo->id, &idptr);
- RNA_property_pointer_set(&ptr, prop, idptr);
- RNA_property_update(C, &ptr, prop);
- }
+ RNA_id_pointer_create(&wo->id, &idptr);
+ RNA_property_pointer_set(&ptr, prop, idptr);
+ RNA_property_update(C, &ptr, prop);
+ }
- WM_event_add_notifier(C, NC_WORLD | NA_ADDED, wo);
+ WM_event_add_notifier(C, NC_WORLD | NA_ADDED, wo);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void WORLD_OT_new(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "New World";
- ot->idname = "WORLD_OT_new";
- ot->description = "Create a new world Data-Block";
+ /* identifiers */
+ ot->name = "New World";
+ ot->idname = "WORLD_OT_new";
+ ot->description = "Create a new world Data-Block";
- /* api callbacks */
- ot->exec = new_world_exec;
+ /* api callbacks */
+ ot->exec = new_world_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
/********************** render layer operators *********************/
static int view_layer_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- wmWindow *win = CTX_wm_window(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = BKE_view_layer_add(scene, NULL);
+ wmWindow *win = CTX_wm_window(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = BKE_view_layer_add(scene, NULL);
- if (win) {
- WM_window_set_active_view_layer(win, view_layer);
- }
+ if (win) {
+ WM_window_set_active_view_layer(win, view_layer);
+ }
- DEG_id_tag_update(&scene->id, 0);
- DEG_relations_tag_update(CTX_data_main(C));
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ DEG_id_tag_update(&scene->id, 0);
+ DEG_relations_tag_update(CTX_data_main(C));
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_view_layer_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add View Layer";
- ot->idname = "SCENE_OT_view_layer_add";
- ot->description = "Add a view layer";
+ /* identifiers */
+ ot->name = "Add View Layer";
+ ot->idname = "SCENE_OT_view_layer_add";
+ ot->description = "Add a view layer";
- /* api callbacks */
- ot->exec = view_layer_add_exec;
+ /* api callbacks */
+ ot->exec = view_layer_add_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
static bool view_layer_remove_poll(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- return (scene->view_layers.first != scene->view_layers.last);
+ Scene *scene = CTX_data_scene(C);
+ return (scene->view_layers.first != scene->view_layers.last);
}
static int view_layer_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
- if (!ED_scene_view_layer_delete(bmain, scene, view_layer, NULL)) {
- return OPERATOR_CANCELLED;
- }
+ if (!ED_scene_view_layer_delete(bmain, scene, view_layer, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_view_layer_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove View Layer";
- ot->idname = "SCENE_OT_view_layer_remove";
- ot->description = "Remove the selected view layer";
+ /* identifiers */
+ ot->name = "Remove View Layer";
+ ot->idname = "SCENE_OT_view_layer_remove";
+ ot->description = "Remove the selected view layer";
- /* api callbacks */
- ot->exec = view_layer_remove_exec;
- ot->poll = view_layer_remove_poll;
+ /* api callbacks */
+ ot->exec = view_layer_remove_exec;
+ ot->poll = view_layer_remove_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
/********************** light cache operators *********************/
enum {
- LIGHTCACHE_SUBSET_ALL = 0,
- LIGHTCACHE_SUBSET_DIRTY,
- LIGHTCACHE_SUBSET_CUBE,
+ LIGHTCACHE_SUBSET_ALL = 0,
+ LIGHTCACHE_SUBSET_DIRTY,
+ LIGHTCACHE_SUBSET_CUBE,
};
static void light_cache_bake_tag_cache(Scene *scene, wmOperator *op)
{
- if (scene->eevee.light_cache != 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;
- break;
- case LIGHTCACHE_SUBSET_CUBE:
- scene->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_CUBE;
- break;
- case LIGHTCACHE_SUBSET_DIRTY:
- /* Leave tag untouched. */
- break;
- }
- }
+ if (scene->eevee.light_cache != 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;
+ break;
+ case LIGHTCACHE_SUBSET_CUBE:
+ scene->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_CUBE;
+ break;
+ case LIGHTCACHE_SUBSET_DIRTY:
+ /* Leave tag untouched. */
+ break;
+ }
+ }
}
/* catch esc */
static int light_cache_bake_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- Scene *scene = (Scene *) op->customdata;
+ Scene *scene = (Scene *)op->customdata;
- /* no running blender, remove handler and pass through */
- if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER)) {
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
- }
+ /* no running blender, remove handler and pass through */
+ if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER)) {
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ }
- /* running render */
- switch (event->type) {
- case ESCKEY:
- return OPERATOR_RUNNING_MODAL;
- }
- return OPERATOR_PASS_THROUGH;
+ /* running render */
+ switch (event->type) {
+ case ESCKEY:
+ return OPERATOR_RUNNING_MODAL;
+ }
+ return OPERATOR_PASS_THROUGH;
}
static void light_cache_bake_cancel(bContext *C, wmOperator *op)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- Scene *scene = (Scene *) op->customdata;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ Scene *scene = (Scene *)op->customdata;
- /* kill on cancel, because job is using op->reports */
- WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER);
+ /* kill on cancel, because job is using op->reports */
+ WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER);
}
/* executes blocking render */
static int light_cache_bake_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
- G.is_break = false;
+ G.is_break = false;
- /* TODO abort if selected engine is not eevee. */
- void *rj = EEVEE_lightbake_job_data_alloc(bmain, view_layer, scene, false, scene->r.cfra);
+ /* TODO abort if selected engine is not eevee. */
+ void *rj = EEVEE_lightbake_job_data_alloc(bmain, view_layer, scene, false, scene->r.cfra);
- light_cache_bake_tag_cache(scene, op);
+ light_cache_bake_tag_cache(scene, op);
- short stop = 0, do_update; float progress; /* Not actually used. */
- EEVEE_lightbake_job(rj, &stop, &do_update, &progress);
- EEVEE_lightbake_job_data_free(rj);
+ short stop = 0, do_update;
+ float progress; /* Not actually used. */
+ EEVEE_lightbake_job(rj, &stop, &do_update, &progress);
+ EEVEE_lightbake_job_data_free(rj);
- // no redraw needed, we leave state as we entered it
- ED_update_for_newframe(bmain, CTX_data_depsgraph(C));
+ // no redraw needed, we leave state as we entered it
+ ED_update_for_newframe(bmain, CTX_data_depsgraph(C));
- WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
+ WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int light_cache_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- int delay = RNA_int_get(op->ptr, "delay");
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ int delay = RNA_int_get(op->ptr, "delay");
- wmJob *wm_job = EEVEE_lightbake_job_create(wm, win, bmain, view_layer, scene, delay, scene->r.cfra);
+ wmJob *wm_job = EEVEE_lightbake_job_create(
+ wm, win, bmain, view_layer, scene, delay, scene->r.cfra);
- if (!wm_job) {
- return OPERATOR_CANCELLED;
- }
+ if (!wm_job) {
+ return OPERATOR_CANCELLED;
+ }
- /* add modal handler for ESC */
- WM_event_add_modal_handler(C, op);
+ /* add modal handler for ESC */
+ WM_event_add_modal_handler(C, op);
- light_cache_bake_tag_cache(scene, op);
+ light_cache_bake_tag_cache(scene, op);
- /* store actual owner of job, so modal operator could check for it,
- * the reason of this is that active scene could change when rendering
- * several layers from compositor [#31800]
- */
- op->customdata = scene;
+ /* store actual owner of job, so modal operator could check for it,
+ * the reason of this is that active scene could change when rendering
+ * several layers from compositor [#31800]
+ */
+ op->customdata = scene;
- WM_jobs_start(wm, wm_job);
+ WM_jobs_start(wm, wm_job);
- WM_cursor_wait(0);
+ WM_cursor_wait(0);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void SCENE_OT_light_cache_bake(wmOperatorType *ot)
{
- static const EnumPropertyItem light_cache_subset_items[] = {
- {LIGHTCACHE_SUBSET_ALL, "ALL", 0, "All LightProbes",
- "Bake both irradiance grids and reflection cubemaps"},
- {LIGHTCACHE_SUBSET_DIRTY, "DIRTY", 0, "Dirty Only",
- "Only bake lightprobes that are marked as dirty"},
- {LIGHTCACHE_SUBSET_CUBE, "CUBEMAPS", 0, "Cubemaps Only",
- "Try to only bake reflection cubemaps if irradiance grids are up to date"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Bake Light Cache";
- ot->idname = "SCENE_OT_light_cache_bake";
- ot->description = "Bake the active view layer lighting";
-
- /* api callbacks */
- ot->invoke = light_cache_bake_invoke;
- ot->modal = light_cache_bake_modal;
- ot->cancel = light_cache_bake_cancel;
- ot->exec = light_cache_bake_exec;
-
- ot->prop = RNA_def_int(ot->srna, "delay", 0, 0, 2000, "Delay", "Delay in millisecond before baking starts", 0, 2000);
- RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
-
- ot->prop = RNA_def_enum(ot->srna, "subset", light_cache_subset_items, 0, "Subset", "Subset of probes to update");
- RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+ static const EnumPropertyItem light_cache_subset_items[] = {
+ {LIGHTCACHE_SUBSET_ALL,
+ "ALL",
+ 0,
+ "All LightProbes",
+ "Bake both irradiance grids and reflection cubemaps"},
+ {LIGHTCACHE_SUBSET_DIRTY,
+ "DIRTY",
+ 0,
+ "Dirty Only",
+ "Only bake lightprobes that are marked as dirty"},
+ {LIGHTCACHE_SUBSET_CUBE,
+ "CUBEMAPS",
+ 0,
+ "Cubemaps Only",
+ "Try to only bake reflection cubemaps if irradiance grids are up to date"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Bake Light Cache";
+ ot->idname = "SCENE_OT_light_cache_bake";
+ ot->description = "Bake the active view layer lighting";
+
+ /* api callbacks */
+ ot->invoke = light_cache_bake_invoke;
+ ot->modal = light_cache_bake_modal;
+ ot->cancel = light_cache_bake_cancel;
+ ot->exec = light_cache_bake_exec;
+
+ ot->prop = RNA_def_int(ot->srna,
+ "delay",
+ 0,
+ 0,
+ 2000,
+ "Delay",
+ "Delay in millisecond before baking starts",
+ 0,
+ 2000);
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+
+ ot->prop = RNA_def_enum(
+ ot->srna, "subset", light_cache_subset_items, 0, "Subset", "Subset of probes to update");
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
}
static bool light_cache_free_poll(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- return scene->eevee.light_cache;
+ return scene->eevee.light_cache;
}
static int light_cache_free_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- /* kill potential bake job first (see T57011) */
- wmWindowManager *wm = CTX_wm_manager(C);
- WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_LIGHT_BAKE);
+ /* kill potential bake job first (see T57011) */
+ wmWindowManager *wm = CTX_wm_manager(C);
+ WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_LIGHT_BAKE);
- if (!scene->eevee.light_cache) {
- return OPERATOR_CANCELLED;
- }
+ if (!scene->eevee.light_cache) {
+ return OPERATOR_CANCELLED;
+ }
- EEVEE_lightcache_free(scene->eevee.light_cache);
- scene->eevee.light_cache = NULL;
+ EEVEE_lightcache_free(scene->eevee.light_cache);
+ scene->eevee.light_cache = NULL;
- EEVEE_lightcache_info_update(&scene->eevee);
+ EEVEE_lightcache_info_update(&scene->eevee);
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_light_cache_free(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Light Cache";
- ot->idname = "SCENE_OT_light_cache_free";
- ot->description = "Delete cached indirect lighting";
+ /* identifiers */
+ ot->name = "Delete Light Cache";
+ ot->idname = "SCENE_OT_light_cache_free";
+ ot->description = "Delete cached indirect lighting";
- /* api callbacks */
- ot->exec = light_cache_free_exec;
- ot->poll = light_cache_free_poll;
+ /* api callbacks */
+ ot->exec = light_cache_free_exec;
+ ot->poll = light_cache_free_poll;
}
/********************** render view operators *********************/
static bool render_view_remove_poll(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- /* don't allow user to remove "left" and "right" views */
- return scene->r.actview > 1;
+ /* don't allow user to remove "left" and "right" views */
+ return scene->r.actview > 1;
}
static int render_view_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- BKE_scene_add_render_view(scene, NULL);
- scene->r.actview = BLI_listbase_count(&scene->r.views) - 1;
+ BKE_scene_add_render_view(scene, NULL);
+ scene->r.actview = BLI_listbase_count(&scene->r.views) - 1;
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_render_view_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Render View";
- ot->idname = "SCENE_OT_render_view_add";
- ot->description = "Add a render view";
+ /* identifiers */
+ ot->name = "Add Render View";
+ ot->idname = "SCENE_OT_render_view_add";
+ ot->description = "Add a render view";
- /* api callbacks */
- ot->exec = render_view_add_exec;
+ /* api callbacks */
+ ot->exec = render_view_add_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int render_view_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- SceneRenderView *rv = BLI_findlink(&scene->r.views, scene->r.actview);
+ Scene *scene = CTX_data_scene(C);
+ SceneRenderView *rv = BLI_findlink(&scene->r.views, scene->r.actview);
- if (!BKE_scene_remove_render_view(scene, rv))
- return OPERATOR_CANCELLED;
+ if (!BKE_scene_remove_render_view(scene, rv))
+ return OPERATOR_CANCELLED;
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_render_view_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Render View";
- ot->idname = "SCENE_OT_render_view_remove";
- ot->description = "Remove the selected render view";
+ /* identifiers */
+ ot->name = "Remove Render View";
+ ot->idname = "SCENE_OT_render_view_remove";
+ ot->description = "Remove the selected render view";
- /* api callbacks */
- ot->exec = render_view_remove_exec;
- ot->poll = render_view_remove_poll;
+ /* api callbacks */
+ ot->exec = render_view_remove_exec;
+ ot->poll = render_view_remove_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
#ifdef WITH_FREESTYLE
static bool freestyle_linestyle_check_report(FreestyleLineSet *lineset, ReportList *reports)
{
- if (!lineset) {
- BKE_report(reports, RPT_ERROR, "No active lineset and associated line style to manipulate the modifier");
- return false;
- }
- if (!lineset->linestyle) {
- BKE_report(reports, RPT_ERROR, "The active lineset does not have a line style (indicating data corruption)");
- return false;
- }
+ if (!lineset) {
+ BKE_report(reports,
+ RPT_ERROR,
+ "No active lineset and associated line style to manipulate the modifier");
+ return false;
+ }
+ if (!lineset->linestyle) {
+ BKE_report(reports,
+ RPT_ERROR,
+ "The active lineset does not have a line style (indicating data corruption)");
+ return false;
+ }
- return true;
+ return true;
}
static bool freestyle_active_module_poll(bContext *C)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
- FreestyleModuleConfig *module = ptr.data;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
+ FreestyleModuleConfig *module = ptr.data;
- return module != NULL;
+ return module != NULL;
}
static int freestyle_module_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
- BKE_freestyle_module_add(&view_layer->freestyle_config);
+ BKE_freestyle_module_add(&view_layer->freestyle_config);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_freestyle_module_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Freestyle Module";
- ot->idname = "SCENE_OT_freestyle_module_add";
- ot->description = "Add a style module into the list of modules";
+ /* identifiers */
+ ot->name = "Add Freestyle Module";
+ ot->idname = "SCENE_OT_freestyle_module_add";
+ ot->description = "Add a style module into the list of modules";
- /* api callbacks */
- ot->exec = freestyle_module_add_exec;
+ /* api callbacks */
+ ot->exec = freestyle_module_add_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
static int freestyle_module_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
- FreestyleModuleConfig *module = ptr.data;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
+ FreestyleModuleConfig *module = ptr.data;
- BKE_freestyle_module_delete(&view_layer->freestyle_config, module);
+ BKE_freestyle_module_delete(&view_layer->freestyle_config, module);
- DEG_id_tag_update(&scene->id, 0);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+ DEG_id_tag_update(&scene->id, 0);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_freestyle_module_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Freestyle Module";
- ot->idname = "SCENE_OT_freestyle_module_remove";
- ot->description = "Remove the style module from the stack";
+ /* identifiers */
+ ot->name = "Remove Freestyle Module";
+ ot->idname = "SCENE_OT_freestyle_module_remove";
+ ot->description = "Remove the style module from the stack";
- /* api callbacks */
- ot->poll = freestyle_active_module_poll;
- ot->exec = freestyle_module_remove_exec;
+ /* api callbacks */
+ ot->poll = freestyle_active_module_poll;
+ ot->exec = freestyle_module_remove_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
static int freestyle_module_move_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
- FreestyleModuleConfig *module = ptr.data;
- int dir = RNA_enum_get(op->ptr, "direction");
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
+ FreestyleModuleConfig *module = ptr.data;
+ int dir = RNA_enum_get(op->ptr, "direction");
- if (BKE_freestyle_module_move(&view_layer->freestyle_config, module, dir)) {
- DEG_id_tag_update(&scene->id, 0);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
- }
+ if (BKE_freestyle_module_move(&view_layer->freestyle_config, module, dir)) {
+ DEG_id_tag_update(&scene->id, 0);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_freestyle_module_move(wmOperatorType *ot)
{
- static const EnumPropertyItem direction_items[] = {
- {-1, "UP", 0, "Up", ""},
- {1, "DOWN", 0, "Down", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem direction_items[] = {
+ {-1, "UP", 0, "Up", ""},
+ {1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Move Freestyle Module";
- ot->idname = "SCENE_OT_freestyle_module_move";
- ot->description = "Change the position of the style module within in the list of style modules";
+ /* identifiers */
+ ot->name = "Move Freestyle Module";
+ ot->idname = "SCENE_OT_freestyle_module_move";
+ ot->description = "Change the position of the style module within in the list of style modules";
- /* api callbacks */
- ot->poll = freestyle_active_module_poll;
- ot->exec = freestyle_module_move_exec;
+ /* api callbacks */
+ ot->poll = freestyle_active_module_poll;
+ ot->exec = freestyle_module_move_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- /* props */
- RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction",
- "Direction to move the chosen style module towards");
+ /* props */
+ RNA_def_enum(ot->srna,
+ "direction",
+ direction_items,
+ 0,
+ "Direction",
+ "Direction to move the chosen style module towards");
}
static int freestyle_lineset_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
- BKE_freestyle_lineset_add(bmain, &view_layer->freestyle_config, NULL);
+ BKE_freestyle_lineset_add(bmain, &view_layer->freestyle_config, NULL);
- DEG_id_tag_update(&scene->id, 0);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+ DEG_id_tag_update(&scene->id, 0);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_freestyle_lineset_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Line Set";
- ot->idname = "SCENE_OT_freestyle_lineset_add";
- ot->description = "Add a line set into the list of line sets";
+ /* identifiers */
+ ot->name = "Add Line Set";
+ ot->idname = "SCENE_OT_freestyle_lineset_add";
+ ot->description = "Add a line set into the list of line sets";
- /* api callbacks */
- ot->exec = freestyle_lineset_add_exec;
+ /* api callbacks */
+ ot->exec = freestyle_lineset_add_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
static bool freestyle_active_lineset_poll(bContext *C)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
- if (!view_layer) {
- return false;
- }
+ if (!view_layer) {
+ return false;
+ }
- return BKE_freestyle_lineset_get_active(&view_layer->freestyle_config) != NULL;
+ return BKE_freestyle_lineset_get_active(&view_layer->freestyle_config) != NULL;
}
static int freestyle_lineset_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
- FRS_copy_active_lineset(&view_layer->freestyle_config);
+ FRS_copy_active_lineset(&view_layer->freestyle_config);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_freestyle_lineset_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Line Set";
- ot->idname = "SCENE_OT_freestyle_lineset_copy";
- ot->description = "Copy the active line set to a buffer";
+ /* identifiers */
+ ot->name = "Copy Line Set";
+ ot->idname = "SCENE_OT_freestyle_lineset_copy";
+ ot->description = "Copy the active line set to a buffer";
- /* api callbacks */
- ot->exec = freestyle_lineset_copy_exec;
- ot->poll = freestyle_active_lineset_poll;
+ /* api callbacks */
+ ot->exec = freestyle_lineset_copy_exec;
+ ot->poll = freestyle_active_lineset_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
static int freestyle_lineset_paste_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
- FRS_paste_active_lineset(&view_layer->freestyle_config);
+ FRS_paste_active_lineset(&view_layer->freestyle_config);
- DEG_id_tag_update(&scene->id, 0);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+ DEG_id_tag_update(&scene->id, 0);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_freestyle_lineset_paste(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Paste Line Set";
- ot->idname = "SCENE_OT_freestyle_lineset_paste";
- ot->description = "Paste the buffer content to the active line set";
+ /* identifiers */
+ ot->name = "Paste Line Set";
+ ot->idname = "SCENE_OT_freestyle_lineset_paste";
+ ot->description = "Paste the buffer content to the active line set";
- /* api callbacks */
- ot->exec = freestyle_lineset_paste_exec;
- ot->poll = freestyle_active_lineset_poll;
+ /* api callbacks */
+ ot->exec = freestyle_lineset_paste_exec;
+ ot->poll = freestyle_active_lineset_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
static int freestyle_lineset_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
- FRS_delete_active_lineset(&view_layer->freestyle_config);
+ FRS_delete_active_lineset(&view_layer->freestyle_config);
- DEG_id_tag_update(&scene->id, 0);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+ DEG_id_tag_update(&scene->id, 0);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_freestyle_lineset_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Line Set";
- ot->idname = "SCENE_OT_freestyle_lineset_remove";
- ot->description = "Remove the active line set from the list of line sets";
+ /* identifiers */
+ ot->name = "Remove Line Set";
+ ot->idname = "SCENE_OT_freestyle_lineset_remove";
+ ot->description = "Remove the active line set from the list of line sets";
- /* api callbacks */
- ot->exec = freestyle_lineset_remove_exec;
- ot->poll = freestyle_active_lineset_poll;
+ /* api callbacks */
+ ot->exec = freestyle_lineset_remove_exec;
+ ot->poll = freestyle_active_lineset_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
static int freestyle_lineset_move_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- int dir = RNA_enum_get(op->ptr, "direction");
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ int dir = RNA_enum_get(op->ptr, "direction");
- if (FRS_move_active_lineset(&view_layer->freestyle_config, dir)) {
- DEG_id_tag_update(&scene->id, 0);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
- }
+ if (FRS_move_active_lineset(&view_layer->freestyle_config, dir)) {
+ DEG_id_tag_update(&scene->id, 0);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_freestyle_lineset_move(wmOperatorType *ot)
{
- static const EnumPropertyItem direction_items[] = {
- {-1, "UP", 0, "Up", ""},
- {1, "DOWN", 0, "Down", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem direction_items[] = {
+ {-1, "UP", 0, "Up", ""},
+ {1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Move Line Set";
- ot->idname = "SCENE_OT_freestyle_lineset_move";
- ot->description = "Change the position of the active line set within the list of line sets";
+ /* identifiers */
+ ot->name = "Move Line Set";
+ ot->idname = "SCENE_OT_freestyle_lineset_move";
+ ot->description = "Change the position of the active line set within the list of line sets";
- /* api callbacks */
- ot->exec = freestyle_lineset_move_exec;
- ot->poll = freestyle_active_lineset_poll;
+ /* api callbacks */
+ ot->exec = freestyle_lineset_move_exec;
+ ot->poll = freestyle_active_lineset_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- /* props */
- RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction",
- "Direction to move the active line set towards");
+ /* props */
+ RNA_def_enum(ot->srna,
+ "direction",
+ direction_items,
+ 0,
+ "Direction",
+ "Direction to move the active line set towards");
}
static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
+ Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
- if (!lineset) {
- BKE_report(op->reports, RPT_ERROR, "No active lineset to add a new line style to");
- return OPERATOR_CANCELLED;
- }
- if (lineset->linestyle) {
- id_us_min(&lineset->linestyle->id);
- lineset->linestyle = BKE_linestyle_copy(bmain, lineset->linestyle);
- }
- else {
- lineset->linestyle = BKE_linestyle_new(bmain, "LineStyle");
- }
- DEG_id_tag_update(&lineset->linestyle->id, 0);
- WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
+ if (!lineset) {
+ BKE_report(op->reports, RPT_ERROR, "No active lineset to add a new line style to");
+ return OPERATOR_CANCELLED;
+ }
+ if (lineset->linestyle) {
+ id_us_min(&lineset->linestyle->id);
+ lineset->linestyle = BKE_linestyle_copy(bmain, lineset->linestyle);
+ }
+ else {
+ lineset->linestyle = BKE_linestyle_new(bmain, "LineStyle");
+ }
+ DEG_id_tag_update(&lineset->linestyle->id, 0);
+ WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_freestyle_linestyle_new(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "New Line Style";
- ot->idname = "SCENE_OT_freestyle_linestyle_new";
- ot->description = "Create a new line style, reusable by multiple line sets";
+ /* identifiers */
+ ot->name = "New Line Style";
+ ot->idname = "SCENE_OT_freestyle_linestyle_new";
+ ot->description = "Create a new line style, reusable by multiple line sets";
- /* api callbacks */
- ot->exec = freestyle_linestyle_new_exec;
- ot->poll = freestyle_active_lineset_poll;
+ /* api callbacks */
+ ot->exec = freestyle_linestyle_new_exec;
+ ot->poll = freestyle_active_lineset_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
static int freestyle_color_modifier_add_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
- int type = RNA_enum_get(op->ptr, "type");
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
+ int type = RNA_enum_get(op->ptr, "type");
- if (!freestyle_linestyle_check_report(lineset, op->reports)) {
- return OPERATOR_CANCELLED;
- }
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
- if (BKE_linestyle_color_modifier_add(lineset->linestyle, NULL, type) == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Unknown line color modifier type");
- return OPERATOR_CANCELLED;
- }
- DEG_id_tag_update(&lineset->linestyle->id, 0);
- WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
+ if (BKE_linestyle_color_modifier_add(lineset->linestyle, NULL, type) == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unknown line color modifier type");
+ return OPERATOR_CANCELLED;
+ }
+ DEG_id_tag_update(&lineset->linestyle->id, 0);
+ WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_freestyle_color_modifier_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Line Color Modifier";
- ot->idname = "SCENE_OT_freestyle_color_modifier_add";
- ot->description = "Add a line color modifier to the line style associated with the active lineset";
+ /* identifiers */
+ ot->name = "Add Line Color Modifier";
+ ot->idname = "SCENE_OT_freestyle_color_modifier_add";
+ ot->description =
+ "Add a line color modifier to the line style associated with the active lineset";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = freestyle_color_modifier_add_exec;
- ot->poll = freestyle_active_lineset_poll;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = freestyle_color_modifier_add_exec;
+ ot->poll = freestyle_active_lineset_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_color_modifier_type_items, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", rna_enum_linestyle_color_modifier_type_items, 0, "Type", "");
}
static int freestyle_alpha_modifier_add_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
- int type = RNA_enum_get(op->ptr, "type");
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
+ int type = RNA_enum_get(op->ptr, "type");
- if (!freestyle_linestyle_check_report(lineset, op->reports)) {
- return OPERATOR_CANCELLED;
- }
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
- if (BKE_linestyle_alpha_modifier_add(lineset->linestyle, NULL, type) == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Unknown alpha transparency modifier type");
- return OPERATOR_CANCELLED;
- }
- DEG_id_tag_update(&lineset->linestyle->id, 0);
- WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
+ if (BKE_linestyle_alpha_modifier_add(lineset->linestyle, NULL, type) == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unknown alpha transparency modifier type");
+ return OPERATOR_CANCELLED;
+ }
+ DEG_id_tag_update(&lineset->linestyle->id, 0);
+ WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_freestyle_alpha_modifier_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Alpha Transparency Modifier";
- ot->idname = "SCENE_OT_freestyle_alpha_modifier_add";
- ot->description = "Add an alpha transparency modifier to the line style associated with the active lineset";
+ /* identifiers */
+ ot->name = "Add Alpha Transparency Modifier";
+ ot->idname = "SCENE_OT_freestyle_alpha_modifier_add";
+ ot->description =
+ "Add an alpha transparency modifier to the line style associated with the active lineset";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = freestyle_alpha_modifier_add_exec;
- ot->poll = freestyle_active_lineset_poll;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = freestyle_alpha_modifier_add_exec;
+ ot->poll = freestyle_active_lineset_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_alpha_modifier_type_items, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", rna_enum_linestyle_alpha_modifier_type_items, 0, "Type", "");
}
static int freestyle_thickness_modifier_add_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
- int type = RNA_enum_get(op->ptr, "type");
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
+ int type = RNA_enum_get(op->ptr, "type");
- if (!freestyle_linestyle_check_report(lineset, op->reports)) {
- return OPERATOR_CANCELLED;
- }
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
- if (BKE_linestyle_thickness_modifier_add(lineset->linestyle, NULL, type) == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Unknown line thickness modifier type");
- return OPERATOR_CANCELLED;
- }
- DEG_id_tag_update(&lineset->linestyle->id, 0);
- WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
+ if (BKE_linestyle_thickness_modifier_add(lineset->linestyle, NULL, type) == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unknown line thickness modifier type");
+ return OPERATOR_CANCELLED;
+ }
+ DEG_id_tag_update(&lineset->linestyle->id, 0);
+ WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_freestyle_thickness_modifier_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Line Thickness Modifier";
- ot->idname = "SCENE_OT_freestyle_thickness_modifier_add";
- ot->description = "Add a line thickness modifier to the line style associated with the active lineset";
+ /* identifiers */
+ ot->name = "Add Line Thickness Modifier";
+ ot->idname = "SCENE_OT_freestyle_thickness_modifier_add";
+ ot->description =
+ "Add a line thickness modifier to the line style associated with the active lineset";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = freestyle_thickness_modifier_add_exec;
- ot->poll = freestyle_active_lineset_poll;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = freestyle_thickness_modifier_add_exec;
+ ot->poll = freestyle_active_lineset_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_thickness_modifier_type_items, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", rna_enum_linestyle_thickness_modifier_type_items, 0, "Type", "");
}
static int freestyle_geometry_modifier_add_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
- int type = RNA_enum_get(op->ptr, "type");
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
+ int type = RNA_enum_get(op->ptr, "type");
- if (!freestyle_linestyle_check_report(lineset, op->reports)) {
- return OPERATOR_CANCELLED;
- }
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
- if (BKE_linestyle_geometry_modifier_add(lineset->linestyle, NULL, type) == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Unknown stroke geometry modifier type");
- return OPERATOR_CANCELLED;
- }
- DEG_id_tag_update(&lineset->linestyle->id, 0);
- WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
+ if (BKE_linestyle_geometry_modifier_add(lineset->linestyle, NULL, type) == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unknown stroke geometry modifier type");
+ return OPERATOR_CANCELLED;
+ }
+ DEG_id_tag_update(&lineset->linestyle->id, 0);
+ WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_freestyle_geometry_modifier_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Stroke Geometry Modifier";
- ot->idname = "SCENE_OT_freestyle_geometry_modifier_add";
- ot->description = "Add a stroke geometry modifier to the line style associated with the active lineset";
+ /* identifiers */
+ ot->name = "Add Stroke Geometry Modifier";
+ ot->idname = "SCENE_OT_freestyle_geometry_modifier_add";
+ ot->description =
+ "Add a stroke geometry modifier to the line style associated with the active lineset";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = freestyle_geometry_modifier_add_exec;
- ot->poll = freestyle_active_lineset_poll;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = freestyle_geometry_modifier_add_exec;
+ ot->poll = freestyle_active_lineset_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_geometry_modifier_type_items, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", rna_enum_linestyle_geometry_modifier_type_items, 0, "Type", "");
}
static int freestyle_get_modifier_type(PointerRNA *ptr)
{
- if (RNA_struct_is_a(ptr->type, &RNA_LineStyleColorModifier))
- return LS_MODIFIER_TYPE_COLOR;
- else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleAlphaModifier))
- return LS_MODIFIER_TYPE_ALPHA;
- else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleThicknessModifier))
- return LS_MODIFIER_TYPE_THICKNESS;
- else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleGeometryModifier))
- return LS_MODIFIER_TYPE_GEOMETRY;
- return -1;
+ if (RNA_struct_is_a(ptr->type, &RNA_LineStyleColorModifier))
+ return LS_MODIFIER_TYPE_COLOR;
+ else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleAlphaModifier))
+ return LS_MODIFIER_TYPE_ALPHA;
+ else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleThicknessModifier))
+ return LS_MODIFIER_TYPE_THICKNESS;
+ else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleGeometryModifier))
+ return LS_MODIFIER_TYPE_GEOMETRY;
+ return -1;
}
static int freestyle_modifier_remove_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
- PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
- LineStyleModifier *modifier = ptr.data;
-
- if (!freestyle_linestyle_check_report(lineset, op->reports)) {
- return OPERATOR_CANCELLED;
- }
-
- switch (freestyle_get_modifier_type(&ptr)) {
- case LS_MODIFIER_TYPE_COLOR:
- BKE_linestyle_color_modifier_remove(lineset->linestyle, modifier);
- break;
- case LS_MODIFIER_TYPE_ALPHA:
- BKE_linestyle_alpha_modifier_remove(lineset->linestyle, modifier);
- break;
- case LS_MODIFIER_TYPE_THICKNESS:
- BKE_linestyle_thickness_modifier_remove(lineset->linestyle, modifier);
- break;
- case LS_MODIFIER_TYPE_GEOMETRY:
- BKE_linestyle_geometry_modifier_remove(lineset->linestyle, modifier);
- break;
- default:
- BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
- return OPERATOR_CANCELLED;
- }
- DEG_id_tag_update(&lineset->linestyle->id, 0);
- WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
+ LineStyleModifier *modifier = ptr.data;
+
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (freestyle_get_modifier_type(&ptr)) {
+ case LS_MODIFIER_TYPE_COLOR:
+ BKE_linestyle_color_modifier_remove(lineset->linestyle, modifier);
+ break;
+ case LS_MODIFIER_TYPE_ALPHA:
+ BKE_linestyle_alpha_modifier_remove(lineset->linestyle, modifier);
+ break;
+ case LS_MODIFIER_TYPE_THICKNESS:
+ BKE_linestyle_thickness_modifier_remove(lineset->linestyle, modifier);
+ break;
+ case LS_MODIFIER_TYPE_GEOMETRY:
+ BKE_linestyle_geometry_modifier_remove(lineset->linestyle, modifier);
+ break;
+ default:
+ BKE_report(
+ op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
+ return OPERATOR_CANCELLED;
+ }
+ DEG_id_tag_update(&lineset->linestyle->id, 0);
+ WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
+
+ return OPERATOR_FINISHED;
}
void SCENE_OT_freestyle_modifier_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Modifier";
- ot->idname = "SCENE_OT_freestyle_modifier_remove";
- ot->description = "Remove the modifier from the list of modifiers";
+ /* identifiers */
+ ot->name = "Remove Modifier";
+ ot->idname = "SCENE_OT_freestyle_modifier_remove";
+ ot->description = "Remove the modifier from the list of modifiers";
- /* api callbacks */
- ot->exec = freestyle_modifier_remove_exec;
- ot->poll = freestyle_active_lineset_poll;
+ /* api callbacks */
+ ot->exec = freestyle_modifier_remove_exec;
+ ot->poll = freestyle_active_lineset_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
- PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
- LineStyleModifier *modifier = ptr.data;
-
- if (!freestyle_linestyle_check_report(lineset, op->reports)) {
- return OPERATOR_CANCELLED;
- }
-
- switch (freestyle_get_modifier_type(&ptr)) {
- case LS_MODIFIER_TYPE_COLOR:
- BKE_linestyle_color_modifier_copy(lineset->linestyle, modifier, 0);
- break;
- case LS_MODIFIER_TYPE_ALPHA:
- BKE_linestyle_alpha_modifier_copy(lineset->linestyle, modifier, 0);
- break;
- case LS_MODIFIER_TYPE_THICKNESS:
- BKE_linestyle_thickness_modifier_copy(lineset->linestyle, modifier, 0);
- break;
- case LS_MODIFIER_TYPE_GEOMETRY:
- BKE_linestyle_geometry_modifier_copy(lineset->linestyle, modifier, 0);
- break;
- default:
- BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
- return OPERATOR_CANCELLED;
- }
- DEG_id_tag_update(&lineset->linestyle->id, 0);
- WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
+ LineStyleModifier *modifier = ptr.data;
+
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (freestyle_get_modifier_type(&ptr)) {
+ case LS_MODIFIER_TYPE_COLOR:
+ BKE_linestyle_color_modifier_copy(lineset->linestyle, modifier, 0);
+ break;
+ case LS_MODIFIER_TYPE_ALPHA:
+ BKE_linestyle_alpha_modifier_copy(lineset->linestyle, modifier, 0);
+ break;
+ case LS_MODIFIER_TYPE_THICKNESS:
+ BKE_linestyle_thickness_modifier_copy(lineset->linestyle, modifier, 0);
+ break;
+ case LS_MODIFIER_TYPE_GEOMETRY:
+ BKE_linestyle_geometry_modifier_copy(lineset->linestyle, modifier, 0);
+ break;
+ default:
+ BKE_report(
+ op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
+ return OPERATOR_CANCELLED;
+ }
+ DEG_id_tag_update(&lineset->linestyle->id, 0);
+ WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
+
+ return OPERATOR_FINISHED;
}
void SCENE_OT_freestyle_modifier_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Modifier";
- ot->idname = "SCENE_OT_freestyle_modifier_copy";
- ot->description = "Duplicate the modifier within the list of modifiers";
+ /* identifiers */
+ ot->name = "Copy Modifier";
+ ot->idname = "SCENE_OT_freestyle_modifier_copy";
+ ot->description = "Duplicate the modifier within the list of modifiers";
- /* api callbacks */
- ot->exec = freestyle_modifier_copy_exec;
- ot->poll = freestyle_active_lineset_poll;
+ /* api callbacks */
+ ot->exec = freestyle_modifier_copy_exec;
+ ot->poll = freestyle_active_lineset_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
static int freestyle_modifier_move_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
- PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
- LineStyleModifier *modifier = ptr.data;
- int dir = RNA_enum_get(op->ptr, "direction");
- bool changed = false;
-
- if (!freestyle_linestyle_check_report(lineset, op->reports)) {
- return OPERATOR_CANCELLED;
- }
-
- switch (freestyle_get_modifier_type(&ptr)) {
- case LS_MODIFIER_TYPE_COLOR:
- changed = BKE_linestyle_color_modifier_move(lineset->linestyle, modifier, dir);
- break;
- case LS_MODIFIER_TYPE_ALPHA:
- changed = BKE_linestyle_alpha_modifier_move(lineset->linestyle, modifier, dir);
- break;
- case LS_MODIFIER_TYPE_THICKNESS:
- changed = BKE_linestyle_thickness_modifier_move(lineset->linestyle, modifier, dir);
- break;
- case LS_MODIFIER_TYPE_GEOMETRY:
- changed = BKE_linestyle_geometry_modifier_move(lineset->linestyle, modifier, dir);
- break;
- default:
- BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
- return OPERATOR_CANCELLED;
- }
-
- if (changed) {
- DEG_id_tag_update(&lineset->linestyle->id, 0);
- WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
- }
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
+ LineStyleModifier *modifier = ptr.data;
+ int dir = RNA_enum_get(op->ptr, "direction");
+ bool changed = false;
+
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (freestyle_get_modifier_type(&ptr)) {
+ case LS_MODIFIER_TYPE_COLOR:
+ changed = BKE_linestyle_color_modifier_move(lineset->linestyle, modifier, dir);
+ break;
+ case LS_MODIFIER_TYPE_ALPHA:
+ changed = BKE_linestyle_alpha_modifier_move(lineset->linestyle, modifier, dir);
+ break;
+ case LS_MODIFIER_TYPE_THICKNESS:
+ changed = BKE_linestyle_thickness_modifier_move(lineset->linestyle, modifier, dir);
+ break;
+ case LS_MODIFIER_TYPE_GEOMETRY:
+ changed = BKE_linestyle_geometry_modifier_move(lineset->linestyle, modifier, dir);
+ break;
+ default:
+ BKE_report(
+ op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (changed) {
+ DEG_id_tag_update(&lineset->linestyle->id, 0);
+ WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
+ }
+
+ return OPERATOR_FINISHED;
}
void SCENE_OT_freestyle_modifier_move(wmOperatorType *ot)
{
- static const EnumPropertyItem direction_items[] = {
- {-1, "UP", 0, "Up", ""},
- {1, "DOWN", 0, "Down", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem direction_items[] = {
+ {-1, "UP", 0, "Up", ""},
+ {1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Move Modifier";
- ot->idname = "SCENE_OT_freestyle_modifier_move";
- ot->description = "Move the modifier within the list of modifiers";
+ /* identifiers */
+ ot->name = "Move Modifier";
+ ot->idname = "SCENE_OT_freestyle_modifier_move";
+ ot->description = "Move the modifier within the list of modifiers";
- /* api callbacks */
- ot->exec = freestyle_modifier_move_exec;
- ot->poll = freestyle_active_lineset_poll;
+ /* api callbacks */
+ ot->exec = freestyle_modifier_move_exec;
+ ot->poll = freestyle_active_lineset_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- /* props */
- RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction",
- "Direction to move the chosen modifier towards");
+ /* props */
+ RNA_def_enum(ot->srna,
+ "direction",
+ direction_items,
+ 0,
+ "Direction",
+ "Direction to move the chosen modifier towards");
}
static int freestyle_stroke_material_create_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- FreestyleLineStyle *linestyle = BKE_linestyle_active_from_view_layer(view_layer);
+ Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ FreestyleLineStyle *linestyle = BKE_linestyle_active_from_view_layer(view_layer);
- if (!linestyle) {
- BKE_report(op->reports, RPT_ERROR, "No active line style in the current scene");
- return OPERATOR_CANCELLED;
- }
+ if (!linestyle) {
+ BKE_report(op->reports, RPT_ERROR, "No active line style in the current scene");
+ return OPERATOR_CANCELLED;
+ }
- FRS_create_stroke_material(bmain, linestyle);
+ FRS_create_stroke_material(bmain, linestyle);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SCENE_OT_freestyle_stroke_material_create(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Create Freestyle Stroke Material";
- ot->idname = "SCENE_OT_freestyle_stroke_material_create";
- ot->description = "Create Freestyle stroke material for testing";
+ /* identifiers */
+ ot->name = "Create Freestyle Stroke Material";
+ ot->idname = "SCENE_OT_freestyle_stroke_material_create";
+ ot->description = "Create Freestyle stroke material for testing";
- /* api callbacks */
- ot->exec = freestyle_stroke_material_create_exec;
+ /* api callbacks */
+ ot->exec = freestyle_stroke_material_create_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
#endif /* WITH_FREESTYLE */
static int texture_slot_move_exec(bContext *C, wmOperator *op)
{
- ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
+ ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
- if (id) {
- MTex **mtex_ar, *mtexswap;
- short act;
- int type = RNA_enum_get(op->ptr, "type");
- struct AnimData *adt = BKE_animdata_from_id(id);
+ if (id) {
+ MTex **mtex_ar, *mtexswap;
+ short act;
+ int type = RNA_enum_get(op->ptr, "type");
+ struct AnimData *adt = BKE_animdata_from_id(id);
- give_active_mtex(id, &mtex_ar, &act);
+ give_active_mtex(id, &mtex_ar, &act);
- if (type == -1) { /* Up */
- if (act > 0) {
- mtexswap = mtex_ar[act];
- mtex_ar[act] = mtex_ar[act - 1];
- mtex_ar[act - 1] = mtexswap;
+ if (type == -1) { /* Up */
+ if (act > 0) {
+ mtexswap = mtex_ar[act];
+ mtex_ar[act] = mtex_ar[act - 1];
+ mtex_ar[act - 1] = mtexswap;
- BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act - 1, -1, 0);
- BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act, act - 1, 0);
- BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, -1, act, 0);
+ BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act - 1, -1, 0);
+ BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act, act - 1, 0);
+ BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, -1, act, 0);
- set_active_mtex(id, act - 1);
- }
- }
- else { /* Down */
- if (act < MAX_MTEX - 1) {
- mtexswap = mtex_ar[act];
- mtex_ar[act] = mtex_ar[act + 1];
- mtex_ar[act + 1] = mtexswap;
+ set_active_mtex(id, act - 1);
+ }
+ }
+ else { /* Down */
+ if (act < MAX_MTEX - 1) {
+ mtexswap = mtex_ar[act];
+ mtex_ar[act] = mtex_ar[act + 1];
+ mtex_ar[act + 1] = mtexswap;
- BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act + 1, -1, 0);
- BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act, act + 1, 0);
- BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, -1, act, 0);
+ BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act + 1, -1, 0);
+ BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act, act + 1, 0);
+ BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, -1, act, 0);
- set_active_mtex(id, act + 1);
- }
- }
+ set_active_mtex(id, act + 1);
+ }
+ }
- DEG_id_tag_update(id, 0);
- WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C));
- }
+ DEG_id_tag_update(id, 0);
+ WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C));
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXTURE_OT_slot_move(wmOperatorType *ot)
{
- static const EnumPropertyItem slot_move[] = {
- {-1, "UP", 0, "Up", ""},
- {1, "DOWN", 0, "Down", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem slot_move[] = {
+ {-1, "UP", 0, "Up", ""},
+ {1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Move Texture Slot";
- ot->idname = "TEXTURE_OT_slot_move";
- ot->description = "Move texture slots up and down";
+ /* identifiers */
+ ot->name = "Move Texture Slot";
+ ot->idname = "TEXTURE_OT_slot_move";
+ ot->description = "Move texture slots up and down";
- /* api callbacks */
- ot->exec = texture_slot_move_exec;
+ /* api callbacks */
+ ot->exec = texture_slot_move_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
+ RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
}
-
-
/********************** material operators *********************/
/* material copy/paste */
static int copy_material_exec(bContext *C, wmOperator *UNUSED(op))
{
- Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
+ Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
- if (ma == NULL)
- return OPERATOR_CANCELLED;
+ if (ma == NULL)
+ return OPERATOR_CANCELLED;
- copy_matcopybuf(CTX_data_main(C), ma);
+ copy_matcopybuf(CTX_data_main(C), ma);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MATERIAL_OT_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Material";
- ot->idname = "MATERIAL_OT_copy";
- ot->description = "Copy the material settings and nodes";
+ /* identifiers */
+ ot->name = "Copy Material";
+ ot->idname = "MATERIAL_OT_copy";
+ ot->description = "Copy the material settings and nodes";
- /* api callbacks */
- ot->exec = copy_material_exec;
+ /* api callbacks */
+ ot->exec = copy_material_exec;
- /* flags */
- /* no undo needed since no changes are made to the material */
- ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL;
+ /* flags */
+ /* no undo needed since no changes are made to the material */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL;
}
static int paste_material_exec(bContext *C, wmOperator *UNUSED(op))
{
- Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
+ Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
- if (ma == NULL)
- return OPERATOR_CANCELLED;
+ if (ma == NULL)
+ return OPERATOR_CANCELLED;
- paste_matcopybuf(CTX_data_main(C), ma);
+ paste_matcopybuf(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);
+ DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MATERIAL_OT_paste(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Paste Material";
- ot->idname = "MATERIAL_OT_paste";
- ot->description = "Paste the material settings and nodes";
+ /* identifiers */
+ ot->name = "Paste Material";
+ ot->idname = "MATERIAL_OT_paste";
+ ot->description = "Paste the material settings and nodes";
- /* api callbacks */
- ot->exec = paste_material_exec;
+ /* api callbacks */
+ ot->exec = paste_material_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
-
static short mtexcopied = 0; /* must be reset on file load */
static MTex mtexcopybuf;
void ED_render_clear_mtex_copybuf(void)
-{ /* use for file reload */
- mtexcopied = 0;
+{ /* use for file reload */
+ mtexcopied = 0;
}
static void copy_mtex_copybuf(ID *id)
{
- MTex **mtex = NULL;
+ MTex **mtex = NULL;
- switch (GS(id->name)) {
- case ID_PA:
- mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
- break;
- case ID_LS:
- mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
- break;
- default:
- break;
- }
+ switch (GS(id->name)) {
+ case ID_PA:
+ mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
+ break;
+ case ID_LS:
+ mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
+ break;
+ default:
+ break;
+ }
- if (mtex && *mtex) {
- memcpy(&mtexcopybuf, *mtex, sizeof(MTex));
- mtexcopied = 1;
- }
- else {
- mtexcopied = 0;
- }
+ if (mtex && *mtex) {
+ memcpy(&mtexcopybuf, *mtex, sizeof(MTex));
+ mtexcopied = 1;
+ }
+ else {
+ mtexcopied = 0;
+ }
}
static void paste_mtex_copybuf(ID *id)
{
- MTex **mtex = NULL;
+ MTex **mtex = NULL;
- if (mtexcopied == 0 || mtexcopybuf.tex == NULL)
- return;
+ if (mtexcopied == 0 || mtexcopybuf.tex == NULL)
+ return;
- switch (GS(id->name)) {
- case ID_PA:
- mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
- break;
- case ID_LS:
- mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
- break;
- default:
- BLI_assert(!"invalid id type");
- return;
- }
+ switch (GS(id->name)) {
+ case ID_PA:
+ mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
+ break;
+ case ID_LS:
+ mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
+ break;
+ default:
+ BLI_assert(!"invalid id type");
+ return;
+ }
- if (mtex) {
- if (*mtex == NULL) {
- *mtex = MEM_mallocN(sizeof(MTex), "mtex copy");
- }
- else if ((*mtex)->tex) {
- id_us_min(&(*mtex)->tex->id);
- }
+ if (mtex) {
+ if (*mtex == NULL) {
+ *mtex = MEM_mallocN(sizeof(MTex), "mtex copy");
+ }
+ else if ((*mtex)->tex) {
+ id_us_min(&(*mtex)->tex->id);
+ }
- memcpy(*mtex, &mtexcopybuf, sizeof(MTex));
+ memcpy(*mtex, &mtexcopybuf, sizeof(MTex));
- id_us_plus((ID *)mtexcopybuf.tex);
- }
+ id_us_plus((ID *)mtexcopybuf.tex);
+ }
}
-
static int copy_mtex_exec(bContext *C, wmOperator *UNUSED(op))
{
- ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
+ ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
- if (id == NULL) {
- /* copying empty slot */
- ED_render_clear_mtex_copybuf();
- return OPERATOR_CANCELLED;
- }
+ if (id == NULL) {
+ /* copying empty slot */
+ ED_render_clear_mtex_copybuf();
+ return OPERATOR_CANCELLED;
+ }
- copy_mtex_copybuf(id);
+ copy_mtex_copybuf(id);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static bool copy_mtex_poll(bContext *C)
{
- ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
+ ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
- return (id != NULL);
+ return (id != NULL);
}
void TEXTURE_OT_slot_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Texture Slot Settings";
- ot->idname = "TEXTURE_OT_slot_copy";
- ot->description = "Copy the material texture settings and nodes";
+ /* identifiers */
+ ot->name = "Copy Texture Slot Settings";
+ ot->idname = "TEXTURE_OT_slot_copy";
+ ot->description = "Copy the material texture settings and nodes";
- /* api callbacks */
- ot->exec = copy_mtex_exec;
- ot->poll = copy_mtex_poll;
+ /* api callbacks */
+ ot->exec = copy_mtex_exec;
+ ot->poll = copy_mtex_poll;
- /* flags */
- /* no undo needed since no changes are made to the mtex */
- ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL;
+ /* flags */
+ /* no undo needed since no changes are made to the mtex */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL;
}
static int paste_mtex_exec(bContext *C, wmOperator *UNUSED(op))
{
- ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
+ ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
- if (id == NULL) {
- Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
- Light *la = CTX_data_pointer_get_type(C, "light", &RNA_Light).data;
- World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
- ParticleSystem *psys = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data;
- FreestyleLineStyle *linestyle = CTX_data_pointer_get_type(C, "line_style", &RNA_FreestyleLineStyle).data;
+ if (id == NULL) {
+ Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
+ Light *la = CTX_data_pointer_get_type(C, "light", &RNA_Light).data;
+ World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
+ ParticleSystem *psys =
+ CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data;
+ FreestyleLineStyle *linestyle =
+ CTX_data_pointer_get_type(C, "line_style", &RNA_FreestyleLineStyle).data;
- if (ma)
- id = &ma->id;
- else if (la)
- id = &la->id;
- else if (wo)
- id = &wo->id;
- else if (psys)
- id = &psys->part->id;
- else if (linestyle)
- id = &linestyle->id;
+ if (ma)
+ id = &ma->id;
+ else if (la)
+ id = &la->id;
+ else if (wo)
+ id = &wo->id;
+ else if (psys)
+ id = &psys->part->id;
+ else if (linestyle)
+ id = &linestyle->id;
- if (id == NULL)
- return OPERATOR_CANCELLED;
- }
+ if (id == NULL)
+ return OPERATOR_CANCELLED;
+ }
- paste_mtex_copybuf(id);
+ paste_mtex_copybuf(id);
- WM_event_add_notifier(C, NC_TEXTURE | ND_SHADING_LINKS, NULL);
+ WM_event_add_notifier(C, NC_TEXTURE | ND_SHADING_LINKS, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXTURE_OT_slot_paste(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Paste Texture Slot Settings";
- ot->idname = "TEXTURE_OT_slot_paste";
- ot->description = "Copy the texture settings and nodes";
+ /* identifiers */
+ ot->name = "Paste Texture Slot Settings";
+ ot->idname = "TEXTURE_OT_slot_paste";
+ ot->description = "Copy the texture settings and nodes";
- /* api callbacks */
- ot->exec = paste_mtex_exec;
+ /* api callbacks */
+ ot->exec = paste_mtex_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index bbd73b581f4..dfc7610946a 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -69,141 +69,138 @@
void ED_render_scene_update(const DEGEditorUpdateContext *update_ctx, int updated)
{
- /* viewport rendering update on data changes, happens after depsgraph
- * updates if there was any change. context is set to the 3d view */
- Main *bmain = update_ctx->bmain;
- Scene *scene = update_ctx->scene;
- ViewLayer *view_layer = update_ctx->view_layer;
- bContext *C;
- wmWindowManager *wm;
- wmWindow *win;
- static bool recursive_check = false;
-
- /* don't do this render engine update if we're updating the scene from
- * other threads doing e.g. rendering or baking jobs */
- if (!BLI_thread_is_main())
- return;
-
- /* don't call this recursively for frame updates */
- if (recursive_check)
- return;
-
- /* Do not call if no WM available, see T42688. */
- if (BLI_listbase_is_empty(&bmain->wm))
- return;
-
- recursive_check = true;
-
- C = CTX_create();
- CTX_data_main_set(C, bmain);
- CTX_data_scene_set(C, scene);
-
- CTX_wm_manager_set(C, bmain->wm.first);
- 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;
-
- CTX_wm_window_set(C, win);
-
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype != SPACE_VIEW3D) {
- continue;
- }
- View3D *v3d = sa->spacedata.first;
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype != RGN_TYPE_WINDOW) {
- continue;
- }
- RegionView3D *rv3d = ar->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);
-
- engine->flag &= ~RE_ENGINE_DO_UPDATE;
- engine->type->view_update(engine, C);
-
- }
- else {
- RenderEngineType *engine_type =
- ED_view3d_engine_type(scene, v3d->shading.type);
- if (updated) {
- DRW_notify_view_update(
- (&(DRWUpdateContext){
- .bmain = bmain,
- .depsgraph = update_ctx->depsgraph,
- .scene = scene,
- .view_layer = view_layer,
- .ar = ar,
- .v3d = (View3D *)sa->spacedata.first,
- .engine_type = engine_type,
- }));
- }
- }
- }
- }
- }
-
- CTX_free(C);
-
- recursive_check = false;
+ /* viewport rendering update on data changes, happens after depsgraph
+ * updates if there was any change. context is set to the 3d view */
+ Main *bmain = update_ctx->bmain;
+ Scene *scene = update_ctx->scene;
+ ViewLayer *view_layer = update_ctx->view_layer;
+ bContext *C;
+ wmWindowManager *wm;
+ wmWindow *win;
+ static bool recursive_check = false;
+
+ /* don't do this render engine update if we're updating the scene from
+ * other threads doing e.g. rendering or baking jobs */
+ if (!BLI_thread_is_main())
+ return;
+
+ /* don't call this recursively for frame updates */
+ if (recursive_check)
+ return;
+
+ /* Do not call if no WM available, see T42688. */
+ if (BLI_listbase_is_empty(&bmain->wm))
+ return;
+
+ recursive_check = true;
+
+ C = CTX_create();
+ CTX_data_main_set(C, bmain);
+ CTX_data_scene_set(C, scene);
+
+ CTX_wm_manager_set(C, bmain->wm.first);
+ 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;
+
+ CTX_wm_window_set(C, win);
+
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ if (sa->spacetype != SPACE_VIEW3D) {
+ continue;
+ }
+ View3D *v3d = sa->spacedata.first;
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype != RGN_TYPE_WINDOW) {
+ continue;
+ }
+ RegionView3D *rv3d = ar->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);
+
+ engine->flag &= ~RE_ENGINE_DO_UPDATE;
+ engine->type->view_update(engine, C);
+ }
+ else {
+ RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
+ if (updated) {
+ DRW_notify_view_update((&(DRWUpdateContext){
+ .bmain = bmain,
+ .depsgraph = update_ctx->depsgraph,
+ .scene = scene,
+ .view_layer = view_layer,
+ .ar = ar,
+ .v3d = (View3D *)sa->spacedata.first,
+ .engine_type = engine_type,
+ }));
+ }
+ }
+ }
+ }
+ }
+
+ CTX_free(C);
+
+ recursive_check = false;
}
void ED_render_engine_area_exit(Main *bmain, ScrArea *sa)
{
- /* clear all render engines in this area */
- ARegion *ar;
- wmWindowManager *wm = bmain->wm.first;
-
- if (sa->spacetype != SPACE_VIEW3D)
- return;
-
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype != RGN_TYPE_WINDOW || !(ar->regiondata))
- continue;
- ED_view3d_stop_render_preview(wm, ar);
- }
+ /* clear all render engines in this area */
+ ARegion *ar;
+ wmWindowManager *wm = bmain->wm.first;
+
+ if (sa->spacetype != SPACE_VIEW3D)
+ return;
+
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype != RGN_TYPE_WINDOW || !(ar->regiondata))
+ continue;
+ ED_view3d_stop_render_preview(wm, ar);
+ }
}
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);
- }
- }
- RE_FreePersistentData();
- /* Inform all render engines and draw managers. */
- DEGEditorUpdateContext update_ctx = {NULL};
- update_ctx.bmain = bmain;
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- update_ctx.scene = scene;
- LISTBASE_FOREACH(ViewLayer *, view_layer, &scene->view_layers) {
- /* TDODO(sergey): Iterate over depsgraphs instead? */
- update_ctx.depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
- update_ctx.view_layer = view_layer;
- ED_render_id_flush_update(&update_ctx, &scene->id);
- }
- if (scene->nodetree) {
- ntreeCompositUpdateRLayers(scene->nodetree);
- }
- }
+ /* 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);
+ }
+ }
+ RE_FreePersistentData();
+ /* Inform all render engines and draw managers. */
+ DEGEditorUpdateContext update_ctx = {NULL};
+ update_ctx.bmain = bmain;
+ for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ update_ctx.scene = scene;
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
+ /* TDODO(sergey): Iterate over depsgraphs instead? */
+ update_ctx.depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+ update_ctx.view_layer = view_layer;
+ ED_render_id_flush_update(&update_ctx, &scene->id);
+ }
+ if (scene->nodetree) {
+ ntreeCompositUpdateRLayers(scene->nodetree);
+ }
+ }
}
void ED_render_view_layer_changed(Main *bmain, bScreen *sc)
{
- for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
- ED_render_engine_area_exit(bmain, sa);
- }
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
+ ED_render_engine_area_exit(bmain, sa);
+ }
}
/***************************** Updates ***********************************
@@ -213,102 +210,102 @@ void ED_render_view_layer_changed(Main *bmain, bScreen *sc)
static void material_changed(Main *UNUSED(bmain), Material *ma)
{
- /* icons */
- BKE_icon_changed(BKE_icon_id_ensure(&ma->id));
+ /* icons */
+ BKE_icon_changed(BKE_icon_id_ensure(&ma->id));
}
static void lamp_changed(Main *UNUSED(bmain), Light *la)
{
- /* icons */
- BKE_icon_changed(BKE_icon_id_ensure(&la->id));
+ /* icons */
+ BKE_icon_changed(BKE_icon_id_ensure(&la->id));
}
static void texture_changed(Main *bmain, Tex *tex)
{
- Scene *scene;
- ViewLayer *view_layer;
- bNode *node;
-
- /* icons */
- BKE_icon_changed(BKE_icon_id_ensure(&tex->id));
-
- for (scene = bmain->scenes.first; scene; scene = scene->id.next) {
- /* paint overlays */
- for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
- BKE_paint_invalidate_overlay_tex(scene, view_layer, tex);
- }
- /* find compositing nodes */
- if (scene->use_nodes && scene->nodetree) {
- for (node = scene->nodetree->nodes.first; node; node = node->next) {
- if (node->id == &tex->id)
- ED_node_tag_update_id(&scene->id);
- }
- }
- }
+ Scene *scene;
+ ViewLayer *view_layer;
+ bNode *node;
+
+ /* icons */
+ BKE_icon_changed(BKE_icon_id_ensure(&tex->id));
+
+ for (scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ /* paint overlays */
+ for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ BKE_paint_invalidate_overlay_tex(scene, view_layer, tex);
+ }
+ /* find compositing nodes */
+ if (scene->use_nodes && scene->nodetree) {
+ for (node = scene->nodetree->nodes.first; node; node = node->next) {
+ if (node->id == &tex->id)
+ ED_node_tag_update_id(&scene->id);
+ }
+ }
+ }
}
static void world_changed(Main *UNUSED(bmain), World *wo)
{
- /* icons */
- BKE_icon_changed(BKE_icon_id_ensure(&wo->id));
+ /* icons */
+ BKE_icon_changed(BKE_icon_id_ensure(&wo->id));
}
static void image_changed(Main *bmain, Image *ima)
{
- Tex *tex;
+ Tex *tex;
- /* icons */
- BKE_icon_changed(BKE_icon_id_ensure(&ima->id));
+ /* icons */
+ BKE_icon_changed(BKE_icon_id_ensure(&ima->id));
- /* textures */
- for (tex = bmain->textures.first; tex; tex = tex->id.next)
- if (tex->ima == ima)
- texture_changed(bmain, tex);
+ /* textures */
+ for (tex = bmain->textures.first; tex; tex = tex->id.next)
+ if (tex->ima == ima)
+ texture_changed(bmain, tex);
}
static void scene_changed(Main *bmain, Scene *scene)
{
- Object *ob;
-
- /* glsl */
- for (ob = bmain->objects.first; ob; ob = ob->id.next) {
- if (ob->mode & OB_MODE_TEXTURE_PAINT) {
- BKE_texpaint_slots_refresh_object(scene, ob);
- BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
- }
- }
+ Object *ob;
+
+ /* glsl */
+ for (ob = bmain->objects.first; ob; ob = ob->id.next) {
+ if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ BKE_texpaint_slots_refresh_object(scene, ob);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ }
+ }
}
void ED_render_id_flush_update(const DEGEditorUpdateContext *update_ctx, ID *id)
{
- /* this can be called from render or baking thread when a python script makes
- * changes, in that case we don't want to do any editor updates, and making
- * GPU changes is not possible because OpenGL only works in the main thread */
- if (!BLI_thread_is_main()) {
- return;
- }
- Main *bmain = update_ctx->bmain;
- /* Internal ID update handlers. */
- switch (GS(id->name)) {
- case ID_MA:
- material_changed(bmain, (Material *)id);
- break;
- case ID_TE:
- texture_changed(bmain, (Tex *)id);
- break;
- case ID_WO:
- world_changed(bmain, (World *)id);
- break;
- case ID_LA:
- lamp_changed(bmain, (Light *)id);
- break;
- case ID_IM:
- image_changed(bmain, (Image *)id);
- break;
- case ID_SCE:
- scene_changed(bmain, (Scene *)id);
- break;
- default:
- break;
- }
+ /* this can be called from render or baking thread when a python script makes
+ * changes, in that case we don't want to do any editor updates, and making
+ * GPU changes is not possible because OpenGL only works in the main thread */
+ if (!BLI_thread_is_main()) {
+ return;
+ }
+ Main *bmain = update_ctx->bmain;
+ /* Internal ID update handlers. */
+ switch (GS(id->name)) {
+ case ID_MA:
+ material_changed(bmain, (Material *)id);
+ break;
+ case ID_TE:
+ texture_changed(bmain, (Tex *)id);
+ break;
+ case ID_WO:
+ world_changed(bmain, (World *)id);
+ break;
+ case ID_LA:
+ lamp_changed(bmain, (Light *)id);
+ break;
+ case ID_IM:
+ image_changed(bmain, (Image *)id);
+ break;
+ case ID_SCE:
+ scene_changed(bmain, (Scene *)id);
+ break;
+ default:
+ break;
+ }
}
diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c
index 1d7022c5263..258e98977c7 100644
--- a/source/blender/editors/render/render_view.c
+++ b/source/blender/editors/render/render_view.c
@@ -49,77 +49,77 @@
/*********************** utilities for finding areas *************************/
/* returns biggest area that is not uv/image editor. Note that it uses buttons */
-/* window as the last possible alternative. */
+/* window as the last possible alternative. */
/* 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;
- 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) {
- if (foundwin == 0 && size > bwmaxsize) {
- bwmaxsize = size;
- big = sa;
- }
- }
- else if (sa->spacetype != SPACE_IMAGE && size > maxsize) {
- maxsize = size;
- big = sa;
- foundwin = 1;
- }
- }
- }
-
- return big;
+ bScreen *sc = CTX_wm_screen(C);
+ ScrArea *sa, *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) {
+ if (foundwin == 0 && size > bwmaxsize) {
+ bwmaxsize = size;
+ big = sa;
+ }
+ }
+ else if (sa->spacetype != SPACE_IMAGE && size > maxsize) {
+ maxsize = size;
+ big = sa;
+ foundwin = 1;
+ }
+ }
+ }
+
+ return big;
}
static ScrArea *find_area_showing_r_result(bContext *C, Scene *scene, wmWindow **win)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- ScrArea *sa = NULL;
- SpaceImage *sima;
-
- /* find an imagewindow showing render result */
- for (*win = wm->windows.first; *win; *win = (*win)->next) {
- 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;
- if (sima->image && sima->image->type == IMA_TYPE_R_RESULT)
- break;
- }
- }
- if (sa)
- break;
- }
- }
-
- return sa;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ ScrArea *sa = NULL;
+ SpaceImage *sima;
+
+ /* find an imagewindow showing render result */
+ for (*win = wm->windows.first; *win; *win = (*win)->next) {
+ 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;
+ if (sima->image && sima->image->type == IMA_TYPE_R_RESULT)
+ break;
+ }
+ }
+ if (sa)
+ break;
+ }
+ }
+
+ return sa;
}
static ScrArea *find_area_image_empty(bContext *C)
{
- bScreen *sc = CTX_wm_screen(C);
- ScrArea *sa;
- 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;
- if (!sima->image)
- break;
- }
- }
-
- return sa;
+ bScreen *sc = CTX_wm_screen(C);
+ ScrArea *sa;
+ 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;
+ if (!sima->image)
+ break;
+ }
+ }
+
+ return sa;
}
/********************** open image editor for render *************************/
@@ -127,224 +127,225 @@ static ScrArea *find_area_image_empty(bContext *C)
/* new window uses x,y to set position */
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;
- SpaceImage *sima;
- bool area_was_image = false;
-
- if (scene->r.displaymode == R_OUTPUT_NONE)
- return NULL;
-
- if (scene->r.displaymode == R_OUTPUT_WINDOW) {
- int sizex = 30 * UI_DPI_FAC + (scene->r.xsch * scene->r.size) / 100;
- int sizey = 60 * UI_DPI_FAC + (scene->r.ysch * scene->r.size) / 100;
-
- /* arbitrary... miniature image window views don't make much sense */
- if (sizex < 320) sizex = 320;
- if (sizey < 256) sizey = 256;
-
- /* changes context! */
- if (WM_window_open_temp(C, mx, my, sizex, sizey, WM_WINDOW_RENDER) == NULL) {
- BKE_report(reports, RPT_ERROR, "Failed to open window!");
- return NULL;
- }
-
- sa = CTX_wm_area(C);
- }
- else if (scene->r.displaymode == R_OUTPUT_SCREEN) {
- sa = 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;
- }
- else {
- if (sa && sa->spacetype == SPACE_IMAGE)
- area_was_image = true;
-
- /* this function returns with changed context */
- sa = ED_screen_full_newspace(C, sa, SPACE_IMAGE);
- }
- }
-
- if (!sa) {
- sa = find_area_showing_r_result(C, scene, &win);
- if (sa == NULL)
- sa = find_area_image_empty(C);
-
- /* if area found in other window, we make that one show in front */
- if (win && win != CTX_wm_window(C))
- wm_window_raise(win);
-
- if (sa == 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;
-
- /* 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 | AREA_FLAG_TEMP_TYPE);
- }
- }
- 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;
-
- /* makes ESC go back to prev space */
- sima->flag |= SI_PREVSPACE;
- }
- }
- }
- }
- sima = sa->spacedata.first;
-
- /* get the correct image, and scale it */
- sima->image = BKE_image_verify_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 esc */
- if (sa->full) {
- sima->flag |= SI_FULLWINDOW;
-
- /* Tell the image editor to revert to previous space in space list on close
- * _only_ if it wasn't already an image editor when the render was invoked */
- if (area_was_image == 0)
- sima->flag |= SI_PREVSPACE;
- else {
- /* Leave it alone so the image editor will just go back from
- * full screen to the original tiled setup */
- }
- }
-
- return sa;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ wmWindow *win = NULL;
+ ScrArea *sa = NULL;
+ SpaceImage *sima;
+ bool area_was_image = false;
+
+ if (scene->r.displaymode == R_OUTPUT_NONE)
+ return NULL;
+
+ if (scene->r.displaymode == R_OUTPUT_WINDOW) {
+ int sizex = 30 * UI_DPI_FAC + (scene->r.xsch * scene->r.size) / 100;
+ int sizey = 60 * UI_DPI_FAC + (scene->r.ysch * scene->r.size) / 100;
+
+ /* arbitrary... miniature image window views don't make much sense */
+ if (sizex < 320)
+ sizex = 320;
+ if (sizey < 256)
+ sizey = 256;
+
+ /* changes context! */
+ if (WM_window_open_temp(C, mx, my, sizex, sizey, WM_WINDOW_RENDER) == NULL) {
+ BKE_report(reports, RPT_ERROR, "Failed to open window!");
+ return NULL;
+ }
+
+ sa = CTX_wm_area(C);
+ }
+ else if (scene->r.displaymode == R_OUTPUT_SCREEN) {
+ sa = 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;
+ }
+ else {
+ if (sa && sa->spacetype == SPACE_IMAGE)
+ area_was_image = true;
+
+ /* this function returns with changed context */
+ sa = ED_screen_full_newspace(C, sa, SPACE_IMAGE);
+ }
+ }
+
+ if (!sa) {
+ sa = find_area_showing_r_result(C, scene, &win);
+ if (sa == NULL)
+ sa = find_area_image_empty(C);
+
+ /* if area found in other window, we make that one show in front */
+ if (win && win != CTX_wm_window(C))
+ wm_window_raise(win);
+
+ if (sa == 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;
+
+ /* 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 | AREA_FLAG_TEMP_TYPE);
+ }
+ }
+ 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;
+
+ /* makes ESC go back to prev space */
+ sima->flag |= SI_PREVSPACE;
+ }
+ }
+ }
+ }
+ sima = sa->spacedata.first;
+
+ /* get the correct image, and scale it */
+ sima->image = BKE_image_verify_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 esc */
+ if (sa->full) {
+ sima->flag |= SI_FULLWINDOW;
+
+ /* Tell the image editor to revert to previous space in space list on close
+ * _only_ if it wasn't already an image editor when the render was invoked */
+ if (area_was_image == 0)
+ sima->flag |= SI_PREVSPACE;
+ else {
+ /* Leave it alone so the image editor will just go back from
+ * full screen to the original tiled setup */
+ }
+ }
+
+ return sa;
}
/*************************** cancel render viewer **********************/
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;
-
- /* ensure image editor fullscreen and area fullscreen states are in sync */
- if ((sima->flag & SI_FULLWINDOW) && !sa->full) {
- sima->flag &= ~SI_FULLWINDOW;
- }
-
- /* test if we have a temp screen in front */
- if (WM_window_is_temp_screen(win)) {
- wm_window_lower(win);
- return OPERATOR_FINISHED;
- }
- /* determine if render already shows */
- else if (sima->flag & SI_PREVSPACE) {
- sima->flag &= ~SI_PREVSPACE;
-
- if (sima->flag & SI_FULLWINDOW) {
- sima->flag &= ~SI_FULLWINDOW;
- ED_screen_full_prevspace(C, sa);
- }
- else {
- ED_area_prevspace(C, sa);
- }
-
- return OPERATOR_FINISHED;
- }
- else if (sima->flag & SI_FULLWINDOW) {
- sima->flag &= ~SI_FULLWINDOW;
- ED_screen_state_toggle(C, win, sa, SCREENMAXIMIZED);
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_PASS_THROUGH;
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceImage *sima = sa->spacedata.first;
+
+ /* ensure image editor fullscreen and area fullscreen states are in sync */
+ if ((sima->flag & SI_FULLWINDOW) && !sa->full) {
+ sima->flag &= ~SI_FULLWINDOW;
+ }
+
+ /* test if we have a temp screen in front */
+ if (WM_window_is_temp_screen(win)) {
+ wm_window_lower(win);
+ return OPERATOR_FINISHED;
+ }
+ /* determine if render already shows */
+ else if (sima->flag & SI_PREVSPACE) {
+ sima->flag &= ~SI_PREVSPACE;
+
+ if (sima->flag & SI_FULLWINDOW) {
+ sima->flag &= ~SI_FULLWINDOW;
+ ED_screen_full_prevspace(C, sa);
+ }
+ else {
+ ED_area_prevspace(C, sa);
+ }
+
+ return OPERATOR_FINISHED;
+ }
+ else if (sima->flag & SI_FULLWINDOW) {
+ sima->flag &= ~SI_FULLWINDOW;
+ ED_screen_state_toggle(C, win, sa, SCREENMAXIMIZED);
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_PASS_THROUGH;
}
void RENDER_OT_view_cancel(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Cancel Render View";
- ot->description = "Cancel show render view";
- ot->idname = "RENDER_OT_view_cancel";
-
- /* api callbacks */
- ot->exec = render_view_cancel_exec;
- ot->poll = ED_operator_image_active;
+ /* identifiers */
+ ot->name = "Cancel Render View";
+ ot->description = "Cancel show render view";
+ ot->idname = "RENDER_OT_view_cancel";
+
+ /* api callbacks */
+ ot->exec = render_view_cancel_exec;
+ ot->poll = ED_operator_image_active;
}
/************************* show render viewer *****************/
static int render_view_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- wmWindow *wincur = CTX_wm_window(C);
-
- /* test if we have currently a temp screen active */
- if (WM_window_is_temp_screen(wincur)) {
- wm_window_lower(wincur);
- }
- else {
- wmWindow *win, *winshow;
- ScrArea *sa = 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);
-
- if ((WM_window_is_temp_screen(win) && ((ScrArea *)sc->areabase.first)->spacetype == SPACE_IMAGE) ||
- (win == winshow && winshow != wincur))
- {
- wm_window_raise(win);
- return OPERATOR_FINISHED;
- }
- }
-
- /* determine if render already shows */
- if (sa) {
- /* but don't close it when rendering */
- if (G.is_rendering == false) {
- SpaceImage *sima = sa->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);
- }
- else {
- ED_area_prevspace(C, sa);
- }
- }
- }
- }
- else {
- render_view_open(C, event->x, event->y, op->reports);
- }
- }
-
- return OPERATOR_FINISHED;
+ wmWindow *wincur = CTX_wm_window(C);
+
+ /* test if we have currently a temp screen active */
+ if (WM_window_is_temp_screen(wincur)) {
+ wm_window_lower(wincur);
+ }
+ else {
+ wmWindow *win, *winshow;
+ ScrArea *sa = 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);
+
+ if ((WM_window_is_temp_screen(win) &&
+ ((ScrArea *)sc->areabase.first)->spacetype == SPACE_IMAGE) ||
+ (win == winshow && winshow != wincur)) {
+ wm_window_raise(win);
+ return OPERATOR_FINISHED;
+ }
+ }
+
+ /* determine if render already shows */
+ if (sa) {
+ /* but don't close it when rendering */
+ if (G.is_rendering == false) {
+ SpaceImage *sima = sa->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);
+ }
+ else {
+ ED_area_prevspace(C, sa);
+ }
+ }
+ }
+ }
+ else {
+ render_view_open(C, event->x, event->y, op->reports);
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void RENDER_OT_view_show(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Show/Hide Render View";
- ot->description = "Toggle show render view";
- ot->idname = "RENDER_OT_view_show";
-
- /* api callbacks */
- ot->invoke = render_view_show_invoke;
- ot->poll = ED_operator_screenactive;
+ /* identifiers */
+ ot->name = "Show/Hide Render View";
+ ot->description = "Toggle show render view";
+ ot->idname = "RENDER_OT_view_show";
+
+ /* api callbacks */
+ ot->invoke = render_view_show_invoke;
+ ot->poll = ED_operator_screenactive;
}
diff --git a/source/blender/editors/scene/CMakeLists.txt b/source/blender/editors/scene/CMakeLists.txt
index be1cd09f965..cd59f06c6e3 100644
--- a/source/blender/editors/scene/CMakeLists.txt
+++ b/source/blender/editors/scene/CMakeLists.txt
@@ -16,14 +16,14 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../depsgraph
- ../../makesdna
- ../../makesrna
- ../../windowmanager
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../depsgraph
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
)
set(INC_SYS
@@ -31,16 +31,16 @@ set(INC_SYS
)
set(SRC
- scene_edit.c
+ scene_edit.c
)
set(LIB
- bf_blenkernel
- bf_blenlib
+ bf_blenkernel
+ bf_blenlib
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
blender_add_lib(bf_editor_scene "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/scene/scene_edit.c b/source/blender/editors/scene/scene_edit.c
index ec0a851de97..381b595171a 100644
--- a/source/blender/editors/scene/scene_edit.c
+++ b/source/blender/editors/scene/scene_edit.c
@@ -56,31 +56,30 @@
#include "WM_api.h"
#include "WM_types.h"
-
Scene *ED_scene_add(Main *bmain, bContext *C, wmWindow *win, eSceneCopyMethod method)
{
- Scene *scene_new;
+ Scene *scene_new;
- if (method == SCE_COPY_NEW) {
- scene_new = BKE_scene_add(bmain, DATA_("Scene"));
- }
- else { /* different kinds of copying */
- Scene *scene_old = WM_window_get_active_scene(win);
+ if (method == SCE_COPY_NEW) {
+ scene_new = BKE_scene_add(bmain, DATA_("Scene"));
+ }
+ else { /* different kinds of copying */
+ Scene *scene_old = WM_window_get_active_scene(win);
- scene_new = BKE_scene_copy(bmain, scene_old, method);
+ scene_new = BKE_scene_copy(bmain, scene_old, method);
- /* these can't be handled in blenkernel currently, so do them here */
- if (method == SCE_COPY_FULL) {
- ED_editors_flush_edits(bmain, false);
- ED_object_single_users(bmain, scene_new, true, true);
- }
- }
+ /* these can't be handled in blenkernel currently, so do them here */
+ if (method == SCE_COPY_FULL) {
+ ED_editors_flush_edits(bmain, false);
+ ED_object_single_users(bmain, scene_new, true, true);
+ }
+ }
- WM_window_set_active_scene(bmain, C, win, scene_new);
+ WM_window_set_active_scene(bmain, C, win, scene_new);
- WM_event_add_notifier(C, NC_SCENE | ND_SCENEBROWSE, scene_new);
+ WM_event_add_notifier(C, NC_SCENE | ND_SCENEBROWSE, scene_new);
- return scene_new;
+ return scene_new;
}
/**
@@ -89,185 +88,188 @@ Scene *ED_scene_add(Main *bmain, bContext *C, wmWindow *win, eSceneCopyMethod me
*/
bool ED_scene_delete(bContext *C, Main *bmain, wmWindow *win, Scene *scene)
{
- Scene *scene_new;
+ Scene *scene_new;
- /* kill running jobs */
- wmWindowManager *wm = bmain->wm.first;
- WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_ANY);
+ /* kill running jobs */
+ wmWindowManager *wm = bmain->wm.first;
+ WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_ANY);
- if (scene->id.prev)
- scene_new = scene->id.prev;
- else if (scene->id.next)
- scene_new = scene->id.next;
- else
- return false;
+ if (scene->id.prev)
+ scene_new = scene->id.prev;
+ else if (scene->id.next)
+ scene_new = scene->id.next;
+ else
+ return false;
- WM_window_set_active_scene(bmain, C, win, scene_new);
+ WM_window_set_active_scene(bmain, C, win, scene_new);
- BKE_id_delete(bmain, scene);
+ BKE_id_delete(bmain, scene);
- return true;
+ return true;
}
/* Depsgraph updates after scene becomes active in a window. */
void ED_scene_change_update(Main *bmain, Scene *scene, ViewLayer *layer)
{
- Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, layer, true);
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, layer, true);
- BKE_scene_set_background(bmain, scene);
- DEG_graph_relations_update(depsgraph, bmain, scene, layer);
- DEG_on_visible_update(bmain, false);
+ BKE_scene_set_background(bmain, scene);
+ DEG_graph_relations_update(depsgraph, bmain, scene, layer);
+ DEG_on_visible_update(bmain, false);
- ED_render_engine_changed(bmain);
- ED_update_for_newframe(bmain, depsgraph);
+ ED_render_engine_changed(bmain);
+ ED_update_for_newframe(bmain, depsgraph);
}
-static bool view_layer_remove_poll(
- const Scene *scene, const ViewLayer *layer)
+static bool view_layer_remove_poll(const Scene *scene, const ViewLayer *layer)
{
- const int act = BLI_findindex(&scene->view_layers, layer);
-
- if (act == -1) {
- return false;
- }
- else if ((scene->view_layers.first == scene->view_layers.last) &&
- (scene->view_layers.first == layer))
- {
- /* ensure 1 layer is kept */
- return false;
- }
-
- return true;
+ const int act = BLI_findindex(&scene->view_layers, layer);
+
+ if (act == -1) {
+ return false;
+ }
+ else if ((scene->view_layers.first == scene->view_layers.last) &&
+ (scene->view_layers.first == layer)) {
+ /* ensure 1 layer is kept */
+ return false;
+ }
+
+ return true;
}
static void view_layer_remove_unset_nodetrees(const Main *bmain, Scene *scene, ViewLayer *layer)
{
- int act_layer_index = BLI_findindex(&scene->view_layers, layer);
+ int act_layer_index = BLI_findindex(&scene->view_layers, layer);
- for (Scene *sce = bmain->scenes.first; sce; sce = sce->id.next) {
- if (sce->nodetree) {
- BKE_nodetree_remove_layer_n(sce->nodetree, scene, act_layer_index);
- }
- }
+ for (Scene *sce = bmain->scenes.first; sce; sce = sce->id.next) {
+ if (sce->nodetree) {
+ BKE_nodetree_remove_layer_n(sce->nodetree, scene, act_layer_index);
+ }
+ }
}
-bool ED_scene_view_layer_delete(
- Main *bmain, Scene *scene, ViewLayer *layer,
- ReportList *reports)
+bool ED_scene_view_layer_delete(Main *bmain, Scene *scene, ViewLayer *layer, ReportList *reports)
{
- if (view_layer_remove_poll(scene, layer) == false) {
- if (reports) {
- BKE_reportf(reports, RPT_ERROR, "View layer '%s' could not be removed from scene '%s'",
- layer->name, scene->id.name + 2);
- }
-
- return false;
- }
-
- /* We need to unset nodetrees before removing the layer, otherwise its index will be -1. */
- view_layer_remove_unset_nodetrees(bmain, scene, layer);
-
- BLI_remlink(&scene->view_layers, layer);
- BLI_assert(BLI_listbase_is_empty(&scene->view_layers) == false);
-
- /* Remove from windows. */
- wmWindowManager *wm = bmain->wm.first;
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
- 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_view_layer_free(layer);
-
- DEG_id_tag_update(&scene->id, 0);
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER | NA_REMOVED, scene);
-
- return true;
+ if (view_layer_remove_poll(scene, layer) == false) {
+ if (reports) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "View layer '%s' could not be removed from scene '%s'",
+ layer->name,
+ scene->id.name + 2);
+ }
+
+ return false;
+ }
+
+ /* We need to unset nodetrees before removing the layer, otherwise its index will be -1. */
+ view_layer_remove_unset_nodetrees(bmain, scene, layer);
+
+ BLI_remlink(&scene->view_layers, layer);
+ BLI_assert(BLI_listbase_is_empty(&scene->view_layers) == false);
+
+ /* Remove from windows. */
+ wmWindowManager *wm = bmain->wm.first;
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ 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_view_layer_free(layer);
+
+ DEG_id_tag_update(&scene->id, 0);
+ DEG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER | NA_REMOVED, scene);
+
+ return true;
}
static int scene_new_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- wmWindow *win = CTX_wm_window(C);
- int type = RNA_enum_get(op->ptr, "type");
+ Main *bmain = CTX_data_main(C);
+ wmWindow *win = CTX_wm_window(C);
+ int type = RNA_enum_get(op->ptr, "type");
- ED_scene_add(bmain, C, win, type);
+ ED_scene_add(bmain, C, win, type);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SCENE_OT_new(wmOperatorType *ot)
{
- static EnumPropertyItem type_items[] = {
- {SCE_COPY_NEW, "NEW", 0, "New",
- "Add a new, empty scene with default settings"},
- {SCE_COPY_EMPTY, "EMPTY", 0, "Copy Settings",
- "Add a new, empty scene, and copy settings from the current scene"},
- {SCE_COPY_LINK_COLLECTION, "LINK_COPY", 0, "Linked Copy",
- "Link in the collections from the current scene (shallow copy)"},
- {SCE_COPY_FULL, "FULL_COPY", 0, "Full Copy",
- "Make a full copy of the current scene"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "New Scene";
- ot->description = "Add new scene by type";
- ot->idname = "SCENE_OT_new";
-
- /* api callbacks */
- ot->exec = scene_new_exec;
- ot->invoke = WM_menu_invoke;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
+ static EnumPropertyItem type_items[] = {
+ {SCE_COPY_NEW, "NEW", 0, "New", "Add a new, empty scene with default settings"},
+ {SCE_COPY_EMPTY,
+ "EMPTY",
+ 0,
+ "Copy Settings",
+ "Add a new, empty scene, and copy settings from the current scene"},
+ {SCE_COPY_LINK_COLLECTION,
+ "LINK_COPY",
+ 0,
+ "Linked Copy",
+ "Link in the collections from the current scene (shallow copy)"},
+ {SCE_COPY_FULL, "FULL_COPY", 0, "Full Copy", "Make a full copy of the current scene"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "New Scene";
+ ot->description = "Add new scene by type";
+ ot->idname = "SCENE_OT_new";
+
+ /* api callbacks */
+ ot->exec = scene_new_exec;
+ ot->invoke = WM_menu_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
}
static bool scene_delete_poll(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- return (scene->id.prev || scene->id.next);
+ Scene *scene = CTX_data_scene(C);
+ return (scene->id.prev || scene->id.next);
}
static int scene_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- if (ED_scene_delete(C, CTX_data_main(C), CTX_wm_window(C), scene) == false) {
- return OPERATOR_CANCELLED;
- }
+ if (ED_scene_delete(C, CTX_data_main(C), CTX_wm_window(C), scene) == false) {
+ return OPERATOR_CANCELLED;
+ }
- if (G.debug & G_DEBUG)
- printf("scene delete %p\n", scene);
+ if (G.debug & G_DEBUG)
+ printf("scene delete %p\n", scene);
- WM_event_add_notifier(C, NC_SCENE | NA_REMOVED, scene);
+ WM_event_add_notifier(C, NC_SCENE | NA_REMOVED, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SCENE_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Scene";
- ot->description = "Delete active scene";
- ot->idname = "SCENE_OT_delete";
+ /* identifiers */
+ ot->name = "Delete Scene";
+ ot->description = "Delete active scene";
+ ot->idname = "SCENE_OT_delete";
- /* api callbacks */
- ot->exec = scene_delete_exec;
- ot->poll = scene_delete_poll;
+ /* api callbacks */
+ ot->exec = scene_delete_exec;
+ ot->poll = scene_delete_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void ED_operatortypes_scene(void)
{
- WM_operatortype_append(SCENE_OT_new);
- WM_operatortype_append(SCENE_OT_delete);
+ WM_operatortype_append(SCENE_OT_new);
+ WM_operatortype_append(SCENE_OT_delete);
}
diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt
index 11516a73d1e..daa72ac194c 100644
--- a/source/blender/editors/screen/CMakeLists.txt
+++ b/source/blender/editors/screen/CMakeLists.txt
@@ -16,51 +16,51 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenfont
- ../../blenkernel
- ../../blenlib
- ../../blenloader
- ../../blentranslation
- ../../bmesh
- ../../depsgraph
- ../../gpu
- ../../imbuf
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenfont
+ ../../blenkernel
+ ../../blenlib
+ ../../blenloader
+ ../../blentranslation
+ ../../bmesh
+ ../../depsgraph
+ ../../gpu
+ ../../imbuf
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- area.c
- area_utils.c
- glutil.c
- screen_context.c
- screen_draw.c
- screen_edit.c
- screen_geometry.c
- screen_ops.c
- screen_user_menu.c
- screendump.c
- workspace_edit.c
- workspace_layout_edit.c
+ area.c
+ area_utils.c
+ glutil.c
+ screen_context.c
+ screen_draw.c
+ screen_edit.c
+ screen_geometry.c
+ screen_ops.c
+ screen_user_menu.c
+ screendump.c
+ workspace_edit.c
+ workspace_layout_edit.c
- screen_intern.h
+ screen_intern.h
)
set(LIB
- bf_editor_datafiles
- bf_editor_space_sequencer
+ bf_editor_datafiles
+ bf_editor_space_sequencer
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index e01f6e04086..4ca26d108a2 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -21,7 +21,6 @@
* \ingroup edscr
*/
-
#include <string.h>
#include <stdio.h>
@@ -73,111 +72,114 @@
#include "screen_intern.h"
enum RegionEmbossSide {
- REGION_EMBOSS_LEFT = (1 << 0),
- REGION_EMBOSS_TOP = (1 << 1),
- REGION_EMBOSS_BOTTOM = (1 << 2),
- REGION_EMBOSS_RIGHT = (1 << 3),
- REGION_EMBOSS_ALL = REGION_EMBOSS_LEFT | REGION_EMBOSS_TOP | REGION_EMBOSS_RIGHT | REGION_EMBOSS_BOTTOM,
+ REGION_EMBOSS_LEFT = (1 << 0),
+ REGION_EMBOSS_TOP = (1 << 1),
+ REGION_EMBOSS_BOTTOM = (1 << 2),
+ REGION_EMBOSS_RIGHT = (1 << 3),
+ REGION_EMBOSS_ALL = REGION_EMBOSS_LEFT | REGION_EMBOSS_TOP | REGION_EMBOSS_RIGHT |
+ REGION_EMBOSS_BOTTOM,
};
/* general area and region code */
static void region_draw_emboss(const ARegion *ar, const rcti *scirct, int sides)
{
- rcti rect;
+ 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;
+ /* 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;
- /* set transp line */
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ /* set transp line */
+ 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] = {0.0f, 0.0f, 0.0f, 0.25f};
- UI_GetThemeColor3fv(TH_EDITOR_OUTLINE, color);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.25f};
+ UI_GetThemeColor3fv(TH_EDITOR_OUTLINE, color);
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4fv(color);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
- immBeginAtMost(GPU_PRIM_LINES, 8);
+ immBeginAtMost(GPU_PRIM_LINES, 8);
- /* right */
- if (sides & REGION_EMBOSS_RIGHT) {
- immVertex2f(pos, rect.xmax, rect.ymax);
- immVertex2f(pos, rect.xmax, rect.ymin);
- }
+ /* right */
+ if (sides & REGION_EMBOSS_RIGHT) {
+ immVertex2f(pos, rect.xmax, rect.ymax);
+ immVertex2f(pos, rect.xmax, rect.ymin);
+ }
- /* bottom */
- if (sides & REGION_EMBOSS_BOTTOM) {
- immVertex2f(pos, rect.xmax, rect.ymin);
- immVertex2f(pos, rect.xmin, rect.ymin);
- }
+ /* bottom */
+ if (sides & REGION_EMBOSS_BOTTOM) {
+ immVertex2f(pos, rect.xmax, rect.ymin);
+ immVertex2f(pos, rect.xmin, rect.ymin);
+ }
- /* left */
- if (sides & REGION_EMBOSS_LEFT) {
- immVertex2f(pos, rect.xmin, rect.ymin);
- immVertex2f(pos, rect.xmin, rect.ymax);
- }
+ /* left */
+ if (sides & REGION_EMBOSS_LEFT) {
+ immVertex2f(pos, rect.xmin, rect.ymin);
+ immVertex2f(pos, rect.xmin, rect.ymax);
+ }
- /* top */
- if (sides & REGION_EMBOSS_TOP) {
- immVertex2f(pos, rect.xmin, rect.ymax);
- immVertex2f(pos, rect.xmax, rect.ymax);
- }
+ /* top */
+ if (sides & REGION_EMBOSS_TOP) {
+ immVertex2f(pos, rect.xmin, rect.ymax);
+ immVertex2f(pos, rect.xmax, rect.ymax);
+ }
- immEnd();
- immUnbindProgram();
+ immEnd();
+ immUnbindProgram();
- GPU_blend(false);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(false);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void ED_region_pixelspace(ARegion *ar)
{
- wmOrtho2_region_pixelspace(ar);
- GPU_matrix_identity_set();
+ wmOrtho2_region_pixelspace(ar);
+ GPU_matrix_identity_set();
}
/* only exported for WM */
-void ED_region_do_listen(wmWindow *win, ScrArea *sa, ARegion *ar, wmNotifier *note, const Scene *scene)
+void ED_region_do_listen(
+ wmWindow *win, ScrArea *sa, ARegion *ar, wmNotifier *note, const Scene *scene)
{
- /* generic notes first */
- switch (note->category) {
- case NC_WM:
- if (note->data == ND_FILEREAD)
- ED_region_tag_redraw(ar);
- break;
- case NC_WINDOW:
- ED_region_tag_redraw(ar);
- break;
- }
+ /* generic notes first */
+ switch (note->category) {
+ case NC_WM:
+ if (note->data == ND_FILEREAD)
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_WINDOW:
+ ED_region_tag_redraw(ar);
+ break;
+ }
- if (ar->type && ar->type->listener)
- ar->type->listener(win, sa, ar, note, scene);
+ if (ar->type && ar->type->listener)
+ ar->type->listener(win, sa, ar, note, scene);
}
/* only exported for WM */
void ED_area_do_listen(wmWindow *win, ScrArea *sa, wmNotifier *note, Scene *scene)
{
- /* no generic notes? */
- if (sa->type && sa->type->listener) {
- sa->type->listener(win, sa, note, scene);
- }
+ /* no generic notes? */
+ if (sa->type && sa->type->listener) {
+ sa->type->listener(win, sa, note, scene);
+ }
}
/* only exported for WM */
void ED_area_do_refresh(bContext *C, ScrArea *sa)
{
- /* no generic notes? */
- if (sa->type && sa->type->refresh) {
- sa->type->refresh(C, sa);
- }
- sa->do_refresh = false;
+ /* no generic notes? */
+ if (sa->type && sa->type->refresh) {
+ sa->type->refresh(C, sa);
+ }
+ sa->do_refresh = false;
}
/**
@@ -185,49 +187,49 @@ void ED_area_do_refresh(bContext *C, ScrArea *sa)
*/
static void area_draw_azone_fullscreen(short x1, short y1, short x2, short y2, float alpha)
{
- int x = x2 - ((float) x2 - x1) * 0.5f / UI_DPI_FAC;
- int y = y2 - ((float) y2 - y1) * 0.5f / UI_DPI_FAC;
+ int x = x2 - ((float)x2 - x1) * 0.5f / UI_DPI_FAC;
+ int y = y2 - ((float)y2 - y1) * 0.5f / UI_DPI_FAC;
- /* adjust the icon distance from the corner */
- x += 36.0f / UI_DPI_FAC;
- y += 36.0f / UI_DPI_FAC;
+ /* adjust the icon distance from the corner */
+ x += 36.0f / UI_DPI_FAC;
+ y += 36.0f / UI_DPI_FAC;
- /* draws from the left bottom corner of the icon */
- x -= UI_DPI_ICON_SIZE;
- y -= UI_DPI_ICON_SIZE;
+ /* draws from the left bottom corner of the icon */
+ x -= UI_DPI_ICON_SIZE;
+ y -= UI_DPI_ICON_SIZE;
- alpha = min_ff(alpha, 0.75f);
+ alpha = min_ff(alpha, 0.75f);
- UI_icon_draw_aspect(x, y, ICON_FULLSCREEN_EXIT, 0.7f / UI_DPI_FAC, alpha, NULL);
+ UI_icon_draw_aspect(x, y, ICON_FULLSCREEN_EXIT, 0.7f / UI_DPI_FAC, alpha, NULL);
- /* debug drawing :
- * The click_rect is the same as defined in fullscreen_click_rcti_init
- * Keep them both in sync */
+ /* debug drawing :
+ * The click_rect is the same as defined in fullscreen_click_rcti_init
+ * Keep them both in sync */
- if (G.debug_value == 101) {
- rcti click_rect;
- float icon_size = UI_DPI_ICON_SIZE + 7 * UI_DPI_FAC;
+ if (G.debug_value == 101) {
+ rcti click_rect;
+ float icon_size = UI_DPI_ICON_SIZE + 7 * UI_DPI_FAC;
- BLI_rcti_init(&click_rect, x, x + icon_size, y, y + icon_size);
+ BLI_rcti_init(&click_rect, x, x + icon_size, y, y + icon_size);
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4f(1.0f, 0.0f, 0.0f, alpha);
- imm_draw_box_wire_2d(pos, click_rect.xmin, click_rect.ymin, click_rect.xmax, click_rect.ymax);
+ immUniformColor4f(1.0f, 0.0f, 0.0f, alpha);
+ imm_draw_box_wire_2d(pos, click_rect.xmin, click_rect.ymin, click_rect.xmax, click_rect.ymax);
- immUniformColor4f(0.0f, 1.0f, 1.0f, alpha);
- immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, click_rect.xmin, click_rect.ymin);
- immVertex2f(pos, click_rect.xmax, click_rect.ymax);
- immVertex2f(pos, click_rect.xmin, click_rect.ymax);
- immVertex2f(pos, click_rect.xmax, click_rect.ymin);
- immEnd();
+ immUniformColor4f(0.0f, 1.0f, 1.0f, alpha);
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex2f(pos, click_rect.xmin, click_rect.ymin);
+ immVertex2f(pos, click_rect.xmax, click_rect.ymax);
+ immVertex2f(pos, click_rect.xmin, click_rect.ymax);
+ immVertex2f(pos, click_rect.xmax, click_rect.ymin);
+ immEnd();
- immUnbindProgram();
- }
+ immUnbindProgram();
+ }
}
/**
@@ -235,7 +237,7 @@ static void area_draw_azone_fullscreen(short x1, short y1, short x2, short y2, f
*/
static void area_draw_azone(short UNUSED(x1), short UNUSED(y1), short UNUSED(x2), short UNUSED(y2))
{
- /* No drawing needed since all corners are action zone, and visually distinguishable. */
+ /* No drawing needed since all corners are action zone, and visually distinguishable. */
}
/**
@@ -243,204 +245,210 @@ static void area_draw_azone(short UNUSED(x1), short UNUSED(y1), short UNUSED(x2)
*/
static void draw_azone_arrow(float x1, float y1, float x2, float y2, AZEdge edge)
{
- const float size = 0.2f * U.widget_unit;
- const float l = 1.0f; /* arrow length */
- const float s = 0.25f; /* arrow thickness */
- const float hl = l / 2.0f;
- const float points[6][2] = {{0, -hl}, {l, hl}, {l - s, hl + s}, {0, s + s - hl}, {s - l, hl + s}, {-l, hl}};
- const float center[2] = {(x1 + x2) / 2, (y1 + y2) / 2};
-
- int axis;
- int sign;
- switch (edge) {
- case AE_BOTTOM_TO_TOPLEFT:
- axis = 0;
- sign = 1;
- break;
- case AE_TOP_TO_BOTTOMRIGHT:
- axis = 0;
- sign = -1;
- break;
- case AE_LEFT_TO_TOPRIGHT:
- axis = 1;
- sign = 1;
- break;
- case AE_RIGHT_TO_TOPLEFT:
- axis = 1;
- sign = -1;
- break;
- default:
- BLI_assert(0);
- return;
- }
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- GPU_blend(true);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4f(0.8f, 0.8f, 0.8f, 0.4f);
-
- immBegin(GPU_PRIM_TRI_FAN, 6);
- for (int i = 0; i < 6; i++) {
- if (axis == 0) {
- immVertex2f(pos, center[0] + points[i][0] * size, center[1] + points[i][1] * sign * size);
- }
- else {
- immVertex2f(pos, center[0] + points[i][1] * sign * size, center[1] + points[i][0] * size);
- }
- }
- immEnd();
-
- immUnbindProgram();
- GPU_blend(false);
+ const float size = 0.2f * U.widget_unit;
+ const float l = 1.0f; /* arrow length */
+ const float s = 0.25f; /* arrow thickness */
+ const float hl = l / 2.0f;
+ const float points[6][2] = {
+ {0, -hl}, {l, hl}, {l - s, hl + s}, {0, s + s - hl}, {s - l, hl + s}, {-l, hl}};
+ const float center[2] = {(x1 + x2) / 2, (y1 + y2) / 2};
+
+ int axis;
+ int sign;
+ switch (edge) {
+ case AE_BOTTOM_TO_TOPLEFT:
+ axis = 0;
+ sign = 1;
+ break;
+ case AE_TOP_TO_BOTTOMRIGHT:
+ axis = 0;
+ sign = -1;
+ break;
+ case AE_LEFT_TO_TOPRIGHT:
+ axis = 1;
+ sign = 1;
+ break;
+ case AE_RIGHT_TO_TOPLEFT:
+ axis = 1;
+ sign = -1;
+ break;
+ default:
+ BLI_assert(0);
+ return;
+ }
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ GPU_blend(true);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4f(0.8f, 0.8f, 0.8f, 0.4f);
+
+ immBegin(GPU_PRIM_TRI_FAN, 6);
+ for (int i = 0; i < 6; i++) {
+ if (axis == 0) {
+ immVertex2f(pos, center[0] + points[i][0] * size, center[1] + points[i][1] * sign * size);
+ }
+ else {
+ immVertex2f(pos, center[0] + points[i][1] * sign * size, center[1] + points[i][0] * size);
+ }
+ }
+ immEnd();
+
+ immUnbindProgram();
+ GPU_blend(false);
}
static void region_draw_azone_tab_arrow(AZone *az)
{
- GPU_blend(true);
+ GPU_blend(true);
- /* add code to draw region hidden as 'too small' */
- switch (az->edge) {
- case AE_TOP_TO_BOTTOMRIGHT:
- UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
- break;
- case AE_BOTTOM_TO_TOPLEFT:
- UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
- break;
- case AE_LEFT_TO_TOPRIGHT:
- UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
- break;
- case AE_RIGHT_TO_TOPLEFT:
- UI_draw_roundbox_corner_set(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
- break;
- }
+ /* add code to draw region hidden as 'too small' */
+ switch (az->edge) {
+ case AE_TOP_TO_BOTTOMRIGHT:
+ UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
+ break;
+ case AE_BOTTOM_TO_TOPLEFT:
+ UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
+ break;
+ case AE_LEFT_TO_TOPRIGHT:
+ UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
+ break;
+ case AE_RIGHT_TO_TOPLEFT:
+ UI_draw_roundbox_corner_set(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
+ break;
+ }
- float color[4] = {0.05f, 0.05f, 0.05f, 0.4f};
- UI_draw_roundbox_aa(true, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, color);
+ float color[4] = {0.05f, 0.05f, 0.05f, 0.4f};
+ 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);
+ 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)
{
- sa->flag |= AREA_FLAG_ACTIONZONES_UPDATE;
+ sa->flag |= AREA_FLAG_ACTIONZONES_UPDATE;
}
static void region_draw_azones(ScrArea *sa, ARegion *ar)
{
- AZone *az;
-
- if (!sa)
- return;
-
- GPU_line_width(1.0f);
- 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_translate_2f(-ar->winrct.xmin, -ar->winrct.ymin);
-
- for (az = sa->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 (az->type == AZONE_AREA) {
- area_draw_azone(az->x1, az->y1, az->x2, az->y2);
- }
- else if (az->type == AZONE_REGION) {
- if (az->ar) {
- /* 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);
- }
- }
- }
- else if (az->type == AZONE_FULLSCREEN) {
- area_draw_azone_fullscreen(az->x1, az->y1, az->x2, az->y2, az->alpha);
- }
- }
- if (!IS_EQF(az->alpha, 0.0f) && ELEM(az->type, AZONE_FULLSCREEN, AZONE_REGION_SCROLL)) {
- area_azone_tag_update(sa);
- }
- }
-
- GPU_matrix_pop();
-
- GPU_blend(false);
+ AZone *az;
+
+ if (!sa)
+ return;
+
+ GPU_line_width(1.0f);
+ 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_translate_2f(-ar->winrct.xmin, -ar->winrct.ymin);
+
+ for (az = sa->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 (az->type == AZONE_AREA) {
+ area_draw_azone(az->x1, az->y1, az->x2, az->y2);
+ }
+ else if (az->type == AZONE_REGION) {
+ if (az->ar) {
+ /* 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);
+ }
+ }
+ }
+ else if (az->type == AZONE_FULLSCREEN) {
+ area_draw_azone_fullscreen(az->x1, az->y1, az->x2, az->y2, az->alpha);
+ }
+ }
+ if (!IS_EQF(az->alpha, 0.0f) && ELEM(az->type, AZONE_FULLSCREEN, AZONE_REGION_SCROLL)) {
+ area_azone_tag_update(sa);
+ }
+ }
+
+ GPU_matrix_pop();
+
+ GPU_blend(false);
}
static void region_draw_status_text(ScrArea *sa, ARegion *ar)
{
- bool overlap = ED_region_is_overlap(sa->spacetype, ar->regiontype);
+ bool overlap = ED_region_is_overlap(sa->spacetype, ar->regiontype);
- if (overlap) {
- GPU_clear_color(0.0, 0.0, 0.0, 0.0);
- glClear(GL_COLOR_BUFFER_BIT);
- }
- else {
- UI_ThemeClearColor(TH_HEADER);
- glClear(GL_COLOR_BUFFER_BIT);
- }
+ if (overlap) {
+ GPU_clear_color(0.0, 0.0, 0.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+ else {
+ UI_ThemeClearColor(TH_HEADER);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
- int fontid = BLF_set_default();
+ int fontid = BLF_set_default();
- const float width = BLF_width(fontid, ar->headerstr, BLF_DRAW_STR_DUMMY_MAX);
- const float x = UI_UNIT_X;
- const float y = 0.4f * UI_UNIT_Y;
+ const float width = BLF_width(fontid, ar->headerstr, BLF_DRAW_STR_DUMMY_MAX);
+ const float x = UI_UNIT_X;
+ const float y = 0.4f * UI_UNIT_Y;
- if (overlap) {
- const float pad = 2.0f * UI_DPI_FAC;
- 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;
+ if (overlap) {
+ const float pad = 2.0f * UI_DPI_FAC;
+ 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;
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- float color[4] = {0.0f, 0.0f, 0.0f, 0.5f};
- UI_GetThemeColor3fv(TH_BACK, color);
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_aa(true, x1, y1, x2, y2, 4.0f, color);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.5f};
+ UI_GetThemeColor3fv(TH_BACK, color);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_aa(true, x1, y1, x2, y2, 4.0f, color);
- UI_FontThemeColor(fontid, TH_TEXT);
- }
- else {
- UI_FontThemeColor(fontid, TH_TEXT);
- }
+ UI_FontThemeColor(fontid, TH_TEXT);
+ }
+ else {
+ UI_FontThemeColor(fontid, TH_TEXT);
+ }
- BLF_position(fontid, x, y, 0.0f);
- BLF_draw(fontid, ar->headerstr, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_position(fontid, x, y, 0.0f);
+ BLF_draw(fontid, ar->headerstr, BLF_DRAW_STR_DUMMY_MAX);
}
/* Follow wmMsgNotifyFn spec */
-void ED_region_do_msg_notify_tag_redraw(
- bContext *UNUSED(C), wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val)
-{
- ARegion *ar = msg_val->owner;
- ED_region_tag_redraw(ar);
-
- /* 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_UI)) {
- while (ar && ar->prev) {
- ar = ar->prev;
- }
- for (; ar; ar = ar->next) {
- if (ELEM(ar->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_CHANNELS)) {
- ED_region_tag_redraw(ar);
- }
- }
- }
+void ED_region_do_msg_notify_tag_redraw(bContext *UNUSED(C),
+ wmMsgSubscribeKey *UNUSED(msg_key),
+ wmMsgSubscribeValue *msg_val)
+{
+ ARegion *ar = msg_val->owner;
+ ED_region_tag_redraw(ar);
+
+ /* 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_UI)) {
+ while (ar && ar->prev) {
+ ar = ar->prev;
+ }
+ for (; ar; ar = ar->next) {
+ if (ELEM(ar->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_CHANNELS)) {
+ ED_region_tag_redraw(ar);
+ }
+ }
+ }
}
/* Follow wmMsgNotifyFn spec */
-void ED_area_do_msg_notify_tag_refresh(
- bContext *UNUSED(C), wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val)
+void ED_area_do_msg_notify_tag_refresh(bContext *UNUSED(C),
+ wmMsgSubscribeKey *UNUSED(msg_key),
+ wmMsgSubscribeValue *msg_val)
{
- ScrArea *sa = msg_val->user_data;
- ED_area_tag_refresh(sa);
+ ScrArea *sa = msg_val->user_data;
+ ED_area_tag_refresh(sa);
}
/**
@@ -451,140 +459,141 @@ void ED_area_do_msg_notify_tag_refresh(
*/
static bool area_is_pseudo_minimized(const ScrArea *area)
{
- return (area->winx < 3) || (area->winy < 3);
+ return (area->winx < 3) || (area->winy < 3);
}
/* only exported for WM */
void ED_region_do_layout(bContext *C, ARegion *ar)
{
- /* This is optional, only needed for dynamically sized regions. */
- ScrArea *sa = CTX_wm_area(C);
- ARegionType *at = ar->type;
+ /* This is optional, only needed for dynamically sized regions. */
+ ScrArea *sa = CTX_wm_area(C);
+ ARegionType *at = ar->type;
- if (!at->layout) {
- return;
- }
+ if (!at->layout) {
+ return;
+ }
- if (at->do_lock || (sa && area_is_pseudo_minimized(sa))) {
- return;
- }
+ if (at->do_lock || (sa && area_is_pseudo_minimized(sa))) {
+ return;
+ }
- ar->do_draw |= RGN_DRAWING;
+ ar->do_draw |= RGN_DRAWING;
- UI_SetTheme(sa ? sa->spacetype : 0, at->regionid);
- at->layout(C, ar);
+ UI_SetTheme(sa ? sa->spacetype : 0, at->regionid);
+ at->layout(C, ar);
}
/* only exported for WM */
void ED_region_do_draw(bContext *C, ARegion *ar)
{
- wmWindow *win = CTX_wm_window(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegionType *at = ar->type;
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegionType *at = ar->type;
- /* see BKE_spacedata_draw_locks() */
- if (at->do_lock)
- return;
+ /* see BKE_spacedata_draw_locks() */
+ if (at->do_lock)
+ return;
- ar->do_draw |= RGN_DRAWING;
+ ar->do_draw |= RGN_DRAWING;
- /* Set viewport, scissor, ortho and ar->drawrct. */
- wmPartialViewport(&ar->drawrct, &ar->winrct, &ar->drawrct);
+ /* Set viewport, scissor, ortho and ar->drawrct. */
+ wmPartialViewport(&ar->drawrct, &ar->winrct, &ar->drawrct);
- wmOrtho2_region_pixelspace(ar);
+ wmOrtho2_region_pixelspace(ar);
- UI_SetTheme(sa ? sa->spacetype : 0, at->regionid);
+ UI_SetTheme(sa ? sa->spacetype : 0, at->regionid);
- if (sa && area_is_pseudo_minimized(sa)) {
- 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 (at->draw) {
- at->draw(C, ar);
- }
+ if (sa && area_is_pseudo_minimized(sa)) {
+ 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 (at->draw) {
+ at->draw(C, ar);
+ }
- /* XXX test: add convention to end regions always in pixel space, for drawing of borders/gestures etc */
- ED_region_pixelspace(ar);
+ /* XXX test: add convention to end regions always in pixel space, for drawing of borders/gestures etc */
+ ED_region_pixelspace(ar);
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_PIXEL);
+ ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_PIXEL);
- region_draw_azones(sa, ar);
+ region_draw_azones(sa, ar);
- /* for debugging unneeded area redraws and partial redraw */
+ /* for debugging unneeded area redraws and partial redraw */
#if 0
- GPU_blend(true);
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4f(drand48(), drand48(), drand48(), 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);
- immUnbindProgram();
- GPU_blend(false);
+ GPU_blend(true);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4f(drand48(), drand48(), drand48(), 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);
+ immUnbindProgram();
+ GPU_blend(false);
#endif
- memset(&ar->drawrct, 0, sizeof(ar->drawrct));
-
- UI_blocklist_free_inactive(C, &ar->uiblocks);
-
- if (sa) {
- 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));
- }
- else if ((ar->regiontype == RGN_TYPE_WINDOW) && (ar->alignment == RGN_ALIGN_QSPLIT)) {
-
- /* draw separating lines between the quad views */
-
- float color[4] = { 0.0f, 0.0f, 0.0f, 0.8f };
- UI_GetThemeColor3fv(TH_EDITOR_OUTLINE, color);
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- 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);
- immUnbindProgram();
- }
- }
-
- /* We may want to detach message-subscriptions from drawing. */
- {
- WorkSpace *workspace = CTX_wm_workspace(C);
- wmWindowManager *wm = CTX_wm_manager(C);
- 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);
-
- /* 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;
-
- PointerRNA ptr;
- RNA_pointer_create(&screen->id, &RNA_Space, sl, &ptr);
-
- wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
- .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);
- }
+ memset(&ar->drawrct, 0, sizeof(ar->drawrct));
+
+ UI_blocklist_free_inactive(C, &ar->uiblocks);
+
+ if (sa) {
+ 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));
+ }
+ else if ((ar->regiontype == RGN_TYPE_WINDOW) && (ar->alignment == RGN_ALIGN_QSPLIT)) {
+
+ /* draw separating lines between the quad views */
+
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.8f};
+ UI_GetThemeColor3fv(TH_EDITOR_OUTLINE, color);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ 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);
+ immUnbindProgram();
+ }
+ }
+
+ /* We may want to detach message-subscriptions from drawing. */
+ {
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ 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);
+
+ /* 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;
+
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_Space, sl, &ptr);
+
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .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);
+ }
}
/* **********************************
@@ -594,93 +603,93 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
void ED_region_tag_redraw(ARegion *ar)
{
- /* 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)) {
- /* 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));
- }
+ /* 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)) {
+ /* 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));
+ }
}
void ED_region_tag_redraw_overlay(ARegion *ar)
{
- if (ar)
- ar->do_draw_overlay = RGN_DRAW;
+ if (ar)
+ ar->do_draw_overlay = RGN_DRAW;
}
void ED_region_tag_redraw_no_rebuild(ARegion *ar)
{
- 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 (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));
+ }
}
void ED_region_tag_refresh_ui(ARegion *ar)
{
- if (ar) {
- ar->do_draw |= RGN_DRAW_REFRESH_UI;
- }
+ if (ar) {
+ ar->do_draw |= RGN_DRAW_REFRESH_UI;
+ }
}
void ED_region_tag_redraw_partial(ARegion *ar, const rcti *rct)
{
- if (ar && !(ar->do_draw & RGN_DRAWING)) {
- if (!(ar->do_draw & (RGN_DRAW | RGN_DRAW_NO_REBUILD | RGN_DRAW_PARTIAL))) {
- /* no redraw set yet, set partial region */
- ar->do_draw |= RGN_DRAW_PARTIAL;
- ar->drawrct = *rct;
- }
- else if (ar->drawrct.xmin != ar->drawrct.xmax) {
- BLI_assert((ar->do_draw & RGN_DRAW_PARTIAL) != 0);
- /* partial redraw already set, expand region */
- BLI_rcti_union(&ar->drawrct, rct);
- }
- else {
- BLI_assert((ar->do_draw & (RGN_DRAW | RGN_DRAW_NO_REBUILD)) != 0);
- /* Else, full redraw is already requested, nothing to do here. */
- }
- }
+ if (ar && !(ar->do_draw & RGN_DRAWING)) {
+ if (!(ar->do_draw & (RGN_DRAW | RGN_DRAW_NO_REBUILD | RGN_DRAW_PARTIAL))) {
+ /* no redraw set yet, set partial region */
+ ar->do_draw |= RGN_DRAW_PARTIAL;
+ ar->drawrct = *rct;
+ }
+ else if (ar->drawrct.xmin != ar->drawrct.xmax) {
+ BLI_assert((ar->do_draw & RGN_DRAW_PARTIAL) != 0);
+ /* partial redraw already set, expand region */
+ BLI_rcti_union(&ar->drawrct, rct);
+ }
+ else {
+ BLI_assert((ar->do_draw & (RGN_DRAW | RGN_DRAW_NO_REBUILD)) != 0);
+ /* Else, full redraw is already requested, nothing to do here. */
+ }
+ }
}
void ED_area_tag_redraw(ScrArea *sa)
{
- ARegion *ar;
+ ARegion *ar;
- if (sa)
- for (ar = sa->regionbase.first; ar; ar = ar->next)
- ED_region_tag_redraw(ar);
+ if (sa)
+ for (ar = sa->regionbase.first; ar; ar = ar->next)
+ ED_region_tag_redraw(ar);
}
void ED_area_tag_redraw_no_rebuild(ScrArea *sa)
{
- ARegion *ar;
+ ARegion *ar;
- if (sa)
- for (ar = sa->regionbase.first; ar; ar = ar->next)
- ED_region_tag_redraw_no_rebuild(ar);
+ if (sa)
+ for (ar = sa->regionbase.first; ar; ar = ar->next)
+ ED_region_tag_redraw_no_rebuild(ar);
}
void ED_area_tag_redraw_regiontype(ScrArea *sa, int regiontype)
{
- ARegion *ar;
+ ARegion *ar;
- if (sa) {
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == regiontype) {
- ED_region_tag_redraw(ar);
- }
- }
- }
+ if (sa) {
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == regiontype) {
+ ED_region_tag_redraw(ar);
+ }
+ }
+ }
}
void ED_area_tag_refresh(ScrArea *sa)
{
- if (sa)
- sa->do_refresh = true;
+ if (sa)
+ sa->do_refresh = true;
}
/* *************************************************************** */
@@ -688,339 +697,341 @@ void ED_area_tag_refresh(ScrArea *sa)
/* use NULL to disable it */
void ED_area_status_text(ScrArea *sa, const char *str)
{
- ARegion *ar;
-
- /* happens when running transform operators in background mode */
- if (sa == NULL)
- return;
-
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_HEADER) {
- if (str) {
- if (ar->headerstr == NULL)
- ar->headerstr = MEM_mallocN(UI_MAX_DRAW_STR, "headerprint");
- BLI_strncpy(ar->headerstr, str, UI_MAX_DRAW_STR);
- BLI_str_rstrip(ar->headerstr);
- }
- else if (ar->headerstr) {
- MEM_freeN(ar->headerstr);
- ar->headerstr = NULL;
- }
- ED_region_tag_redraw(ar);
- }
- }
+ ARegion *ar;
+
+ /* happens when running transform operators in background mode */
+ if (sa == NULL)
+ return;
+
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_HEADER) {
+ if (str) {
+ if (ar->headerstr == NULL)
+ ar->headerstr = MEM_mallocN(UI_MAX_DRAW_STR, "headerprint");
+ BLI_strncpy(ar->headerstr, str, UI_MAX_DRAW_STR);
+ BLI_str_rstrip(ar->headerstr);
+ }
+ else if (ar->headerstr) {
+ MEM_freeN(ar->headerstr);
+ ar->headerstr = NULL;
+ }
+ ED_region_tag_redraw(ar);
+ }
+ }
}
void ED_workspace_status_text(bContext *C, const char *str)
{
- wmWindow *win = CTX_wm_window(C);
- WorkSpace *workspace = CTX_wm_workspace(C);
+ wmWindow *win = CTX_wm_window(C);
+ WorkSpace *workspace = CTX_wm_workspace(C);
- /* Can be NULL when running operators in background mode. */
- if (workspace == NULL)
- return;
+ /* Can be NULL when running operators in background mode. */
+ if (workspace == NULL)
+ return;
- if (str) {
- if (workspace->status_text == NULL)
- workspace->status_text = MEM_mallocN(UI_MAX_DRAW_STR, "headerprint");
- BLI_strncpy(workspace->status_text, str, UI_MAX_DRAW_STR);
- }
- else if (workspace->status_text) {
- MEM_freeN(workspace->status_text);
- workspace->status_text = NULL;
- }
+ if (str) {
+ if (workspace->status_text == NULL)
+ workspace->status_text = MEM_mallocN(UI_MAX_DRAW_STR, "headerprint");
+ BLI_strncpy(workspace->status_text, str, UI_MAX_DRAW_STR);
+ }
+ else if (workspace->status_text) {
+ MEM_freeN(workspace->status_text);
+ workspace->status_text = NULL;
+ }
- /* 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);
- break;
- }
- }
+ /* 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);
+ break;
+ }
+ }
}
/* ************************************************************ */
-
static void area_azone_initialize(wmWindow *win, const bScreen *screen, ScrArea *sa)
{
- AZone *az;
-
- /* reinitialize entirely, regions and fullscreen add azones too */
- BLI_freelistN(&sa->actionzones);
-
- if (screen->state != SCREENNORMAL) {
- return;
- }
-
- if (U.app_flag & USER_APP_LOCK_UI_LAYOUT) {
- return;
- }
-
- if (ED_area_is_global(sa)) {
- return;
- }
-
- if (screen->temp) {
- return;
- }
-
- float coords[4][4] = {
- /* Bottom-left. */
- {sa->totrct.xmin - U.pixelsize,
- sa->totrct.ymin - U.pixelsize,
- sa->totrct.xmin + AZONESPOTW,
- sa->totrct.ymin + AZONESPOTH},
- /* Bottom-right. */
- {sa->totrct.xmax - AZONESPOTW,
- sa->totrct.ymin - U.pixelsize,
- sa->totrct.xmax + U.pixelsize,
- sa->totrct.ymin + AZONESPOTH},
- /* Top-left. */
- {sa->totrct.xmin - U.pixelsize,
- sa->totrct.ymax - AZONESPOTH,
- sa->totrct.xmin + AZONESPOTW,
- sa->totrct.ymax + U.pixelsize},
- /* Top-right. */
- {sa->totrct.xmax - AZONESPOTW,
- sa->totrct.ymax - AZONESPOTH,
- sa->totrct.xmax + U.pixelsize,
- sa->totrct.ymax + U.pixelsize}};
-
- for (int i = 0; i < 4; i++) {
- /* can't click on bottom corners on OS X, already used for resizing */
+ AZone *az;
+
+ /* reinitialize entirely, regions and fullscreen add azones too */
+ BLI_freelistN(&sa->actionzones);
+
+ if (screen->state != SCREENNORMAL) {
+ return;
+ }
+
+ if (U.app_flag & USER_APP_LOCK_UI_LAYOUT) {
+ return;
+ }
+
+ if (ED_area_is_global(sa)) {
+ return;
+ }
+
+ if (screen->temp) {
+ return;
+ }
+
+ float coords[4][4] = {/* Bottom-left. */
+ {sa->totrct.xmin - U.pixelsize,
+ sa->totrct.ymin - U.pixelsize,
+ sa->totrct.xmin + AZONESPOTW,
+ sa->totrct.ymin + AZONESPOTH},
+ /* Bottom-right. */
+ {sa->totrct.xmax - AZONESPOTW,
+ sa->totrct.ymin - U.pixelsize,
+ sa->totrct.xmax + U.pixelsize,
+ sa->totrct.ymin + AZONESPOTH},
+ /* Top-left. */
+ {sa->totrct.xmin - U.pixelsize,
+ sa->totrct.ymax - AZONESPOTH,
+ sa->totrct.xmin + AZONESPOTW,
+ sa->totrct.ymax + U.pixelsize},
+ /* Top-right. */
+ {sa->totrct.xmax - AZONESPOTW,
+ sa->totrct.ymax - AZONESPOTH,
+ sa->totrct.xmax + U.pixelsize,
+ sa->totrct.ymax + U.pixelsize}};
+
+ for (int i = 0; i < 4; i++) {
+ /* can't click on bottom corners on OS X, already used for resizing */
#ifdef __APPLE__
- if (!WM_window_is_fullscreen(win) &&
- ((coords[i][0] == 0 && coords[i][1] == 0) ||
- (coords[i][0] == WM_window_pixels_x(win) && coords[i][1] == 0)))
- {
- continue;
- }
+ if (!WM_window_is_fullscreen(win) &&
+ ((coords[i][0] == 0 && coords[i][1] == 0) ||
+ (coords[i][0] == WM_window_pixels_x(win) && coords[i][1] == 0))) {
+ continue;
+ }
#else
- (void)win;
+ (void)win;
#endif
- /* set area action zones */
- az = (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
- BLI_addtail(&(sa->actionzones), az);
- az->type = AZONE_AREA;
- az->x1 = coords[i][0];
- az->y1 = coords[i][1];
- az->x2 = coords[i][2];
- az->y2 = coords[i][3];
- BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
- }
+ /* set area action zones */
+ az = (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
+ BLI_addtail(&(sa->actionzones), az);
+ az->type = AZONE_AREA;
+ az->x1 = coords[i][0];
+ az->y1 = coords[i][1];
+ az->x2 = coords[i][2];
+ az->y2 = coords[i][3];
+ BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
+ }
}
static void fullscreen_azone_initialize(ScrArea *sa, ARegion *ar)
{
- AZone *az;
+ AZone *az;
- if (ED_area_is_global(sa) || (ar->regiontype != RGN_TYPE_WINDOW))
- return;
+ if (ED_area_is_global(sa) || (ar->regiontype != RGN_TYPE_WINDOW))
+ return;
- az = (AZone *)MEM_callocN(sizeof(AZone), "fullscreen action zone");
- BLI_addtail(&(sa->actionzones), az);
- az->type = AZONE_FULLSCREEN;
- az->ar = ar;
- az->alpha = 0.0f;
+ az = (AZone *)MEM_callocN(sizeof(AZone), "fullscreen action zone");
+ BLI_addtail(&(sa->actionzones), az);
+ az->type = AZONE_FULLSCREEN;
+ az->ar = ar;
+ az->alpha = 0.0f;
- az->x1 = ar->winrct.xmax - (AZONEFADEOUT - 1);
- az->y1 = ar->winrct.ymax - (AZONEFADEOUT - 1);
- az->x2 = ar->winrct.xmax;
- az->y2 = ar->winrct.ymax;
- BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
+ az->x1 = ar->winrct.xmax - (AZONEFADEOUT - 1);
+ az->y1 = ar->winrct.ymax - (AZONEFADEOUT - 1);
+ az->x2 = ar->winrct.xmax;
+ az->y2 = ar->winrct.ymax;
+ BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
}
-#define AZONEPAD_EDGE (0.1f * U.widget_unit)
-#define AZONEPAD_ICON (0.45f * U.widget_unit)
+#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)
{
- 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;
- 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;
- 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;
- 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;
- break;
- }
-
- BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
+ 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;
+ 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;
+ 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;
+ 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;
+ 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)
{
- AZone *azt;
- int tot = 0, add;
- /* Edge offset multiplied by the */
-
- float edge_offset = 1.0f;
- 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) {
- if (azt->edge == az->edge) tot++;
- }
-
- 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;
- 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;
- 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);
- 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);
- break;
- }
- /* rect needed for mouse pointer test */
- BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
+ AZone *azt;
+ int tot = 0, add;
+ /* Edge offset multiplied by the */
+
+ float edge_offset = 1.0f;
+ 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) {
+ if (azt->edge == az->edge)
+ tot++;
+ }
+
+ 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;
+ 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;
+ 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);
+ 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);
+ 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)
{
- const bool is_hidden = (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL));
+ const bool is_hidden = (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL));
- if (is_hidden && is_fullscreen) {
- return false;
- }
- if (!is_hidden && ar->regiontype == RGN_TYPE_HEADER) {
- return false;
- }
+ if (is_hidden && is_fullscreen) {
+ return false;
+ }
+ if (!is_hidden && ar->regiontype == RGN_TYPE_HEADER) {
+ return false;
+ }
- return true;
+ return true;
}
-static void region_azone_edge_initialize(ScrArea *sa, ARegion *ar, AZEdge edge, const bool is_fullscreen)
+static void region_azone_edge_initialize(ScrArea *sa,
+ ARegion *ar,
+ AZEdge edge,
+ const bool is_fullscreen)
{
- AZone *az = NULL;
- const bool is_hidden = (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL));
+ AZone *az = NULL;
+ const bool is_hidden = (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL));
- if (!region_azone_edge_poll(ar, is_fullscreen)) {
- return;
- }
+ if (!region_azone_edge_poll(ar, is_fullscreen)) {
+ return;
+ }
- az = (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
- BLI_addtail(&(sa->actionzones), az);
- az->type = AZONE_REGION;
- az->ar = ar;
- az->edge = edge;
+ az = (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
+ BLI_addtail(&(sa->actionzones), az);
+ az->type = AZONE_REGION;
+ az->ar = ar;
+ az->edge = edge;
- if (is_hidden) {
- region_azone_tab_plus(sa, az, ar);
- }
- else {
- region_azone_edge(az, ar);
- }
+ if (is_hidden) {
+ region_azone_tab_plus(sa, az, ar);
+ }
+ else {
+ region_azone_edge(az, ar);
+ }
}
-static void region_azone_scrollbar_initialize(ScrArea *sa, ARegion *ar, AZScrollDirection direction)
+static void region_azone_scrollbar_initialize(ScrArea *sa,
+ ARegion *ar,
+ AZScrollDirection direction)
{
- rcti scroller_vert = (direction == AZ_SCROLL_VERT) ? ar->v2d.vert : ar->v2d.hor;
- AZone *az = MEM_callocN(sizeof(*az), __func__);
+ rcti scroller_vert = (direction == AZ_SCROLL_VERT) ? ar->v2d.vert : ar->v2d.hor;
+ AZone *az = MEM_callocN(sizeof(*az), __func__);
- BLI_addtail(&sa->actionzones, az);
- az->type = AZONE_REGION_SCROLL;
- az->ar = ar;
- az->direction = direction;
+ BLI_addtail(&sa->actionzones, az);
+ az->type = AZONE_REGION_SCROLL;
+ az->ar = ar;
+ az->direction = direction;
- if (direction == AZ_SCROLL_VERT) {
- az->ar->v2d.alpha_vert = 0;
- }
- else if (direction == AZ_SCROLL_HOR) {
- az->ar->v2d.alpha_hor = 0;
- }
+ if (direction == AZ_SCROLL_VERT) {
+ az->ar->v2d.alpha_vert = 0;
+ }
+ else if (direction == AZ_SCROLL_HOR) {
+ az->ar->v2d.alpha_hor = 0;
+ }
- BLI_rcti_translate(&scroller_vert, ar->winrct.xmin, ar->winrct.ymin);
- az->x1 = scroller_vert.xmin - AZONEFADEIN;
- az->y1 = scroller_vert.ymin - AZONEFADEIN;
- az->x2 = scroller_vert.xmax + AZONEFADEIN;
- az->y2 = scroller_vert.ymax + AZONEFADEIN;
+ BLI_rcti_translate(&scroller_vert, ar->winrct.xmin, ar->winrct.ymin);
+ az->x1 = scroller_vert.xmin - AZONEFADEIN;
+ az->y1 = scroller_vert.ymin - AZONEFADEIN;
+ az->x2 = scroller_vert.xmax + AZONEFADEIN;
+ az->y2 = scroller_vert.ymax + AZONEFADEIN;
- BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
+ BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
}
static void region_azones_scrollbars_initialize(ScrArea *sa, ARegion *ar)
{
- const View2D *v2d = &ar->v2d;
+ const View2D *v2d = &ar->v2d;
- if ((v2d->scroll & V2D_SCROLL_VERTICAL) && ((v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) == 0)) {
- region_azone_scrollbar_initialize(sa, ar, AZ_SCROLL_VERT);
- }
- if ((v2d->scroll & V2D_SCROLL_HORIZONTAL) && ((v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) == 0)) {
- region_azone_scrollbar_initialize(sa, ar, AZ_SCROLL_HOR);
- }
+ if ((v2d->scroll & V2D_SCROLL_VERTICAL) && ((v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) == 0)) {
+ region_azone_scrollbar_initialize(sa, ar, AZ_SCROLL_VERT);
+ }
+ if ((v2d->scroll & V2D_SCROLL_HORIZONTAL) &&
+ ((v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) == 0)) {
+ region_azone_scrollbar_initialize(sa, ar, AZ_SCROLL_HOR);
+ }
}
-
/* *************************************************************** */
static void region_azones_add(const bScreen *screen, ScrArea *sa, ARegion *ar, const int alignment)
{
- const bool is_fullscreen = screen->state == SCREENFULL;
+ const bool is_fullscreen = screen->state == SCREENFULL;
- /* 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);
- else if (alignment == RGN_ALIGN_BOTTOM)
- region_azone_edge_initialize(sa, ar, AE_TOP_TO_BOTTOMRIGHT, is_fullscreen);
- else if (alignment == RGN_ALIGN_RIGHT)
- region_azone_edge_initialize(sa, ar, AE_LEFT_TO_TOPRIGHT, is_fullscreen);
- else if (alignment == RGN_ALIGN_LEFT)
- region_azone_edge_initialize(sa, ar, AE_RIGHT_TO_TOPLEFT, 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);
+ else if (alignment == RGN_ALIGN_BOTTOM)
+ region_azone_edge_initialize(sa, ar, AE_TOP_TO_BOTTOMRIGHT, is_fullscreen);
+ else if (alignment == RGN_ALIGN_RIGHT)
+ region_azone_edge_initialize(sa, ar, AE_LEFT_TO_TOPRIGHT, is_fullscreen);
+ else if (alignment == RGN_ALIGN_LEFT)
+ region_azone_edge_initialize(sa, ar, AE_RIGHT_TO_TOPLEFT, is_fullscreen);
- if (is_fullscreen) {
- fullscreen_azone_initialize(sa, ar);
- }
+ if (is_fullscreen) {
+ fullscreen_azone_initialize(sa, ar);
+ }
- region_azones_scrollbars_initialize(sa, ar);
+ region_azones_scrollbars_initialize(sa, ar);
}
/* dir is direction to check, not the splitting edge direction! */
static int rct_fits(const rcti *rect, char dir, int size)
{
- if (dir == 'h') {
- return BLI_rcti_size_x(rect) + 1 - size;
- }
- else { /* 'v' */
- return BLI_rcti_size_y(rect) + 1 - size;
- }
+ if (dir == 'h') {
+ return BLI_rcti_size_x(rect) + 1 - size;
+ }
+ else { /* 'v' */
+ return BLI_rcti_size_y(rect) + 1 - size;
+ }
}
/* *************************************************************** */
@@ -1029,655 +1040,665 @@ static int rct_fits(const rcti *rect, char dir, int size)
/* function checks if some overlapping region was defined before - on same place */
static void region_overlap_fix(ScrArea *sa, ARegion *ar)
{
- ARegion *ar1;
- const int align = ar->alignment & ~RGN_SPLIT_PREV;
- int align1 = 0;
-
- /* find overlapping previous region on same place */
- for (ar1 = ar->prev; ar1; ar1 = ar1->prev) {
- if (ar1->flag & (RGN_FLAG_HIDDEN)) {
- continue;
- }
-
- if (ar1->overlap && ((ar1->alignment & RGN_SPLIT_PREV) == 0)) {
- if (ELEM(ar1->alignment, RGN_ALIGN_FLOAT)) {
- continue;
- }
- align1 = ar1->alignment;
- if (BLI_rcti_isect(&ar1->winrct, &ar->winrct, NULL)) {
- if (align1 != align) {
- /* Left overlapping right or vice-versa, forbid this! */
- ar->flag |= RGN_FLAG_TOO_SMALL;
- return;
- }
- /* Else, we have our previous region on same side. */
- break;
- }
- }
- }
-
- /* 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;
- return;
- }
- else {
- BLI_rcti_translate(&ar->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;
- return;
- }
- else {
- BLI_rcti_translate(&ar->winrct, -ar1->winx, 0);
- }
- }
- }
-
- /* At this point, 'ar' 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) {
- if (ar1->flag & (RGN_FLAG_HIDDEN)) {
- continue;
- }
- if (ELEM(ar1->alignment, RGN_ALIGN_FLOAT)) {
- continue;
- }
-
- if (ar1->overlap && (ar1->alignment & RGN_SPLIT_PREV) == 0) {
- if ((ar1->alignment != align) && BLI_rcti_isect(&ar1->winrct, &ar->winrct, NULL)) {
- /* Left overlapping right or vice-versa, forbid this! */
- ar->flag |= RGN_FLAG_TOO_SMALL;
- return;
- }
- }
- }
+ ARegion *ar1;
+ const int align = ar->alignment & ~RGN_SPLIT_PREV;
+ int align1 = 0;
+
+ /* find overlapping previous region on same place */
+ for (ar1 = ar->prev; ar1; ar1 = ar1->prev) {
+ if (ar1->flag & (RGN_FLAG_HIDDEN)) {
+ continue;
+ }
+
+ if (ar1->overlap && ((ar1->alignment & RGN_SPLIT_PREV) == 0)) {
+ if (ELEM(ar1->alignment, RGN_ALIGN_FLOAT)) {
+ continue;
+ }
+ align1 = ar1->alignment;
+ if (BLI_rcti_isect(&ar1->winrct, &ar->winrct, NULL)) {
+ if (align1 != align) {
+ /* Left overlapping right or vice-versa, forbid this! */
+ ar->flag |= RGN_FLAG_TOO_SMALL;
+ return;
+ }
+ /* Else, we have our previous region on same side. */
+ break;
+ }
+ }
+ }
+
+ /* 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;
+ return;
+ }
+ else {
+ BLI_rcti_translate(&ar->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;
+ return;
+ }
+ else {
+ BLI_rcti_translate(&ar->winrct, -ar1->winx, 0);
+ }
+ }
+ }
+
+ /* At this point, 'ar' 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) {
+ if (ar1->flag & (RGN_FLAG_HIDDEN)) {
+ continue;
+ }
+ if (ELEM(ar1->alignment, RGN_ALIGN_FLOAT)) {
+ continue;
+ }
+
+ if (ar1->overlap && (ar1->alignment & RGN_SPLIT_PREV) == 0) {
+ if ((ar1->alignment != align) && BLI_rcti_isect(&ar1->winrct, &ar->winrct, NULL)) {
+ /* Left overlapping right or vice-versa, forbid this! */
+ ar->flag |= RGN_FLAG_TOO_SMALL;
+ return;
+ }
+ }
+ }
}
/* overlapping regions only in the following restricted cases */
bool ED_region_is_overlap(int spacetype, int regiontype)
{
- if (regiontype == RGN_TYPE_HUD) {
- return true;
- }
- if (U.uiflag2 & USER_REGION_OVERLAP) {
- if (spacetype == SPACE_NODE) {
- if (regiontype == RGN_TYPE_TOOLS) {
- return true;
- }
- }
- else if (ELEM(spacetype, SPACE_VIEW3D, SPACE_IMAGE)) {
- if (ELEM(regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS, RGN_TYPE_HEADER, RGN_TYPE_FOOTER)) {
- return true;
- }
- }
- }
-
- return false;
-}
-
-static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, rcti *overlap_remainder, int quad)
-{
- rcti *remainder_prev = remainder;
-
- if (ar == NULL)
- return;
-
- int prev_winx = ar->winx;
- int prev_winy = ar->winy;
-
- /* no returns in function, winrct gets set in the end again */
- BLI_rcti_init(&ar->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;
-
- int alignment = ar->alignment & ~RGN_SPLIT_PREV;
-
- /* set here, assuming userpref switching forces to call this again */
- ar->overlap = ED_region_is_overlap(sa->spacetype, ar->regiontype);
-
- /* clear state flags first */
- ar->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)) {
- alignment = RGN_ALIGN_NONE;
- }
-
- /* prefsize, taking into account DPI */
- int prefsizex = UI_DPI_FAC * ((ar->sizex > 1) ? ar->sizex + 0.5f : ar->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;
- }
- else if (ar->regiontype == RGN_TYPE_HEADER) {
- prefsizey = ED_area_headersize();
- }
- else if (ar->regiontype == RGN_TYPE_FOOTER) {
- prefsizey = ED_area_footersize();
- }
- else if (ED_area_is_global(sa)) {
- prefsizey = ED_region_global_size_y();
- }
- else if (ar->regiontype == RGN_TYPE_UI && sa->spacetype == SPACE_FILE) {
- prefsizey = UI_UNIT_Y * 2 + (UI_UNIT_Y / 2);
- }
- else {
- prefsizey = UI_DPI_FAC * (ar->sizey > 1 ? ar->sizey + 0.5f : ar->type->prefsizey);
- }
-
-
- if (ar->flag & RGN_FLAG_HIDDEN) {
- /* hidden is user flag */
- }
- else if (alignment == RGN_ALIGN_FLOAT) {
- /**
- * \note Currently this window type is only used for #RGN_TYPE_HUD,
- * We expect the panel to resize it's self to be larger.
- *
- * This aligns to the lower left of the area.
- */
- const int size_min[2] = {UI_UNIT_X, UI_UNIT_Y};
- rcti overlap_remainder_margin = *overlap_remainder;
- 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->winrct.ymin = overlap_remainder_margin.ymin;
- ar->winrct.xmax = ar->winrct.xmin + prefsizex - 1;
- ar->winrct.ymax = ar->winrct.ymin + prefsizey - 1;
-
- BLI_rcti_isect(&ar->winrct, &overlap_remainder_margin, &ar->winrct);
-
- if (BLI_rcti_size_x(&ar->winrct) != prefsizex - 1) {
- ar->flag |= RGN_FLAG_SIZE_CLAMP_X;
- }
- if (BLI_rcti_size_y(&ar->winrct) != prefsizey - 1) {
- ar->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],
- };
- 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;
- }
- }
- 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;
- }
- else if (alignment == RGN_ALIGN_NONE) {
- /* typically last region */
- ar->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;
-
- if (rct_fits(winrct, 'v', prefsizey) < 0) {
- ar->flag |= RGN_FLAG_TOO_SMALL;
- }
- else {
- int fac = rct_fits(winrct, 'v', prefsizey);
-
- if (fac < 0)
- prefsizey += fac;
-
- ar->winrct = *winrct;
-
- if (alignment == RGN_ALIGN_TOP) {
- ar->winrct.ymin = ar->winrct.ymax - prefsizey + 1;
- winrct->ymax = ar->winrct.ymin - 1;
- }
- else {
- ar->winrct.ymax = ar->winrct.ymin + prefsizey - 1;
- winrct->ymin = ar->winrct.ymax + 1;
- }
- }
- }
- else if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
- rcti *winrct = (ar->overlap) ? overlap_remainder : remainder;
-
- if (rct_fits(winrct, 'h', prefsizex) < 0) {
- ar->flag |= RGN_FLAG_TOO_SMALL;
- }
- else {
- int fac = rct_fits(winrct, 'h', prefsizex);
-
- if (fac < 0)
- prefsizex += fac;
-
- ar->winrct = *winrct;
-
- if (alignment == RGN_ALIGN_RIGHT) {
- ar->winrct.xmin = ar->winrct.xmax - prefsizex + 1;
- winrct->xmax = ar->winrct.xmin - 1;
- }
- else {
- ar->winrct.xmax = ar->winrct.xmin + prefsizex - 1;
- winrct->xmin = ar->winrct.xmax + 1;
- }
- }
- }
- else if (alignment == RGN_ALIGN_VSPLIT || alignment == RGN_ALIGN_HSPLIT) {
- /* percentage subdiv*/
- ar->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;
- }
- else {
- BLI_rcti_init(remainder, 0, 0, 0, 0);
- }
- }
- else {
- if (rct_fits(remainder, 'v', prefsizey) > 4) {
- ar->winrct.ymax = BLI_rcti_cent_y(remainder);
- remainder->ymin = ar->winrct.ymax + 1;
- }
- else {
- BLI_rcti_init(remainder, 0, 0, 0, 0);
- }
- }
- }
- else if (alignment == RGN_ALIGN_QSPLIT) {
- ar->winrct = *remainder;
-
- /* test if there's still 4 regions left */
- if (quad == 0) {
- ARegion *artest = ar->next;
- int count = 1;
-
- while (artest) {
- artest->alignment = RGN_ALIGN_QSPLIT;
- artest = artest->next;
- count++;
- }
-
- if (count != 4) {
- /* let's stop adding regions */
- BLI_rcti_init(remainder, 0, 0, 0, 0);
- if (G.debug & G_DEBUG)
- printf("region quadsplit failed\n");
- }
- else {
- quad = 1;
- }
- }
- if (quad) {
- if (quad == 1) { /* left bottom */
- ar->winrct.xmax = BLI_rcti_cent_x(remainder);
- ar->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;
- }
- else if (quad == 3) { /* right bottom */
- ar->winrct.xmin = BLI_rcti_cent_x(remainder) + 1;
- ar->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;
- BLI_rcti_init(remainder, 0, 0, 0, 0);
- }
-
- quad++;
- }
- }
-
- /* for speedup */
- ar->winx = BLI_rcti_size_x(&ar->winrct) + 1;
- ar->winy = BLI_rcti_size_y(&ar->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 (ar->winy > 1) ar->sizey = (ar->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);
- }
-
- /* set winrect for azones */
- if (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) {
- ar->winrct = (ar->overlap) ? *overlap_remainder : *remainder;
-
- switch (alignment) {
- case RGN_ALIGN_TOP:
- ar->winrct.ymin = ar->winrct.ymax;
- break;
- case RGN_ALIGN_BOTTOM:
- ar->winrct.ymax = ar->winrct.ymin;
- break;
- case RGN_ALIGN_RIGHT:
- ar->winrct.xmin = ar->winrct.xmax;
- break;
- case RGN_ALIGN_LEFT:
- default:
- /* prevent winrct to be valid */
- ar->winrct.xmax = ar->winrct.xmin;
- break;
- }
- }
-
- /* restore prev-split exception */
- if (ar->alignment & RGN_SPLIT_PREV) {
- if (ar->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;
- }
- }
-
- /* After non-overlapping region, all following overlapping regions
- * fit within the remaining space again. */
- if (!ar->overlap) {
- *overlap_remainder = *remainder;
- }
-
- region_rect_recursive(sa, ar->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 (regiontype == RGN_TYPE_HUD) {
+ return true;
+ }
+ if (U.uiflag2 & USER_REGION_OVERLAP) {
+ if (spacetype == SPACE_NODE) {
+ if (regiontype == RGN_TYPE_TOOLS) {
+ return true;
+ }
+ }
+ else if (ELEM(spacetype, SPACE_VIEW3D, SPACE_IMAGE)) {
+ if (ELEM(regiontype,
+ RGN_TYPE_TOOLS,
+ RGN_TYPE_UI,
+ RGN_TYPE_TOOL_PROPS,
+ RGN_TYPE_HEADER,
+ RGN_TYPE_FOOTER)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static void region_rect_recursive(
+ ScrArea *sa, ARegion *ar, rcti *remainder, rcti *overlap_remainder, int quad)
+{
+ rcti *remainder_prev = remainder;
+
+ if (ar == NULL)
+ return;
+
+ int prev_winx = ar->winx;
+ int prev_winy = ar->winy;
+
+ /* no returns in function, winrct gets set in the end again */
+ BLI_rcti_init(&ar->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;
+
+ int alignment = ar->alignment & ~RGN_SPLIT_PREV;
+
+ /* set here, assuming userpref switching forces to call this again */
+ ar->overlap = ED_region_is_overlap(sa->spacetype, ar->regiontype);
+
+ /* clear state flags first */
+ ar->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)) {
+ alignment = RGN_ALIGN_NONE;
+ }
+
+ /* prefsize, taking into account DPI */
+ int prefsizex = UI_DPI_FAC * ((ar->sizex > 1) ? ar->sizex + 0.5f : ar->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;
+ }
+ else if (ar->regiontype == RGN_TYPE_HEADER) {
+ prefsizey = ED_area_headersize();
+ }
+ else if (ar->regiontype == RGN_TYPE_FOOTER) {
+ prefsizey = ED_area_footersize();
+ }
+ else if (ED_area_is_global(sa)) {
+ prefsizey = ED_region_global_size_y();
+ }
+ else if (ar->regiontype == RGN_TYPE_UI && sa->spacetype == SPACE_FILE) {
+ prefsizey = UI_UNIT_Y * 2 + (UI_UNIT_Y / 2);
+ }
+ else {
+ prefsizey = UI_DPI_FAC * (ar->sizey > 1 ? ar->sizey + 0.5f : ar->type->prefsizey);
+ }
+
+ if (ar->flag & RGN_FLAG_HIDDEN) {
+ /* hidden is user flag */
+ }
+ else if (alignment == RGN_ALIGN_FLOAT) {
+ /**
+ * \note Currently this window type is only used for #RGN_TYPE_HUD,
+ * We expect the panel to resize it's self to be larger.
+ *
+ * This aligns to the lower left of the area.
+ */
+ const int size_min[2] = {UI_UNIT_X, UI_UNIT_Y};
+ rcti overlap_remainder_margin = *overlap_remainder;
+ 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->winrct.ymin = overlap_remainder_margin.ymin;
+ ar->winrct.xmax = ar->winrct.xmin + prefsizex - 1;
+ ar->winrct.ymax = ar->winrct.ymin + prefsizey - 1;
+
+ BLI_rcti_isect(&ar->winrct, &overlap_remainder_margin, &ar->winrct);
+
+ if (BLI_rcti_size_x(&ar->winrct) != prefsizex - 1) {
+ ar->flag |= RGN_FLAG_SIZE_CLAMP_X;
+ }
+ if (BLI_rcti_size_y(&ar->winrct) != prefsizey - 1) {
+ ar->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],
+ };
+ 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;
+ }
+ }
+ 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;
+ }
+ else if (alignment == RGN_ALIGN_NONE) {
+ /* typically last region */
+ ar->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;
+
+ if (rct_fits(winrct, 'v', prefsizey) < 0) {
+ ar->flag |= RGN_FLAG_TOO_SMALL;
+ }
+ else {
+ int fac = rct_fits(winrct, 'v', prefsizey);
+
+ if (fac < 0)
+ prefsizey += fac;
+
+ ar->winrct = *winrct;
+
+ if (alignment == RGN_ALIGN_TOP) {
+ ar->winrct.ymin = ar->winrct.ymax - prefsizey + 1;
+ winrct->ymax = ar->winrct.ymin - 1;
+ }
+ else {
+ ar->winrct.ymax = ar->winrct.ymin + prefsizey - 1;
+ winrct->ymin = ar->winrct.ymax + 1;
+ }
+ }
+ }
+ else if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
+ rcti *winrct = (ar->overlap) ? overlap_remainder : remainder;
+
+ if (rct_fits(winrct, 'h', prefsizex) < 0) {
+ ar->flag |= RGN_FLAG_TOO_SMALL;
+ }
+ else {
+ int fac = rct_fits(winrct, 'h', prefsizex);
+
+ if (fac < 0)
+ prefsizex += fac;
+
+ ar->winrct = *winrct;
+
+ if (alignment == RGN_ALIGN_RIGHT) {
+ ar->winrct.xmin = ar->winrct.xmax - prefsizex + 1;
+ winrct->xmax = ar->winrct.xmin - 1;
+ }
+ else {
+ ar->winrct.xmax = ar->winrct.xmin + prefsizex - 1;
+ winrct->xmin = ar->winrct.xmax + 1;
+ }
+ }
+ }
+ else if (alignment == RGN_ALIGN_VSPLIT || alignment == RGN_ALIGN_HSPLIT) {
+ /* percentage subdiv*/
+ ar->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;
+ }
+ else {
+ BLI_rcti_init(remainder, 0, 0, 0, 0);
+ }
+ }
+ else {
+ if (rct_fits(remainder, 'v', prefsizey) > 4) {
+ ar->winrct.ymax = BLI_rcti_cent_y(remainder);
+ remainder->ymin = ar->winrct.ymax + 1;
+ }
+ else {
+ BLI_rcti_init(remainder, 0, 0, 0, 0);
+ }
+ }
+ }
+ else if (alignment == RGN_ALIGN_QSPLIT) {
+ ar->winrct = *remainder;
+
+ /* test if there's still 4 regions left */
+ if (quad == 0) {
+ ARegion *artest = ar->next;
+ int count = 1;
+
+ while (artest) {
+ artest->alignment = RGN_ALIGN_QSPLIT;
+ artest = artest->next;
+ count++;
+ }
+
+ if (count != 4) {
+ /* let's stop adding regions */
+ BLI_rcti_init(remainder, 0, 0, 0, 0);
+ if (G.debug & G_DEBUG)
+ printf("region quadsplit failed\n");
+ }
+ else {
+ quad = 1;
+ }
+ }
+ if (quad) {
+ if (quad == 1) { /* left bottom */
+ ar->winrct.xmax = BLI_rcti_cent_x(remainder);
+ ar->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;
+ }
+ else if (quad == 3) { /* right bottom */
+ ar->winrct.xmin = BLI_rcti_cent_x(remainder) + 1;
+ ar->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;
+ BLI_rcti_init(remainder, 0, 0, 0, 0);
+ }
+
+ quad++;
+ }
+ }
+
+ /* for speedup */
+ ar->winx = BLI_rcti_size_x(&ar->winrct) + 1;
+ ar->winy = BLI_rcti_size_y(&ar->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 (ar->winy > 1)
+ ar->sizey = (ar->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);
+ }
+
+ /* set winrect for azones */
+ if (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) {
+ ar->winrct = (ar->overlap) ? *overlap_remainder : *remainder;
+
+ switch (alignment) {
+ case RGN_ALIGN_TOP:
+ ar->winrct.ymin = ar->winrct.ymax;
+ break;
+ case RGN_ALIGN_BOTTOM:
+ ar->winrct.ymax = ar->winrct.ymin;
+ break;
+ case RGN_ALIGN_RIGHT:
+ ar->winrct.xmin = ar->winrct.xmax;
+ break;
+ case RGN_ALIGN_LEFT:
+ default:
+ /* prevent winrct to be valid */
+ ar->winrct.xmax = ar->winrct.xmin;
+ break;
+ }
+ }
+
+ /* restore prev-split exception */
+ if (ar->alignment & RGN_SPLIT_PREV) {
+ if (ar->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;
+ }
+ }
+
+ /* After non-overlapping region, all following overlapping regions
+ * fit within the remaining space again. */
+ if (!ar->overlap) {
+ *overlap_remainder = *remainder;
+ }
+
+ region_rect_recursive(sa, ar->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);
+ }
}
static void area_calc_totrct(ScrArea *sa, 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;
-
- /* 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 (sa->totrct.xmax < (window_rect->xmax - 1)) {
- sa->totrct.xmax -= px;
- }
- if (sa->totrct.ymin > window_rect->ymin) {
- sa->totrct.ymin += px;
- }
- if (sa->totrct.ymax < (window_rect->ymax - 1)) {
- sa->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. */
+ 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;
+
+ /* 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 (sa->totrct.xmax < (window_rect->xmax - 1)) {
+ sa->totrct.xmax -= px;
+ }
+ if (sa->totrct.ymin > window_rect->ymin) {
+ sa->totrct.ymin += px;
+ }
+ if (sa->totrct.ymax < (window_rect->ymax - 1)) {
+ sa->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(sa->totrct.xmin >= 0);
+ BLI_assert(sa->totrct.xmax >= 0);
+ BLI_assert(sa->totrct.ymin >= 0);
+ BLI_assert(sa->totrct.ymax >= 0);
#endif
- /* for speedup */
- sa->winx = BLI_rcti_size_x(&sa->totrct) + 1;
- sa->winy = BLI_rcti_size_y(&sa->totrct) + 1;
+ /* for speedup */
+ sa->winx = BLI_rcti_size_x(&sa->totrct) + 1;
+ sa->winy = BLI_rcti_size_y(&sa->totrct) + 1;
}
-
/* used for area initialize below */
static void region_subwindow(ARegion *ar)
{
- bool hidden = (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) != 0;
+ bool hidden = (ar->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 ((ar->alignment & RGN_SPLIT_PREV) && ar->prev)
+ hidden = hidden || (ar->prev->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL));
- ar->visible = !hidden;
+ ar->visible = !hidden;
}
/**
* \param ar: Region, may be NULL when adding handlers for \a sa.
*/
-static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ARegion *ar, ListBase *handlers, int flag)
-{
- BLI_assert(ar ? (&ar->handlers == handlers) : (&sa->handlers == handlers));
-
- /* note, add-handler checks if it already exists */
-
- /* XXX it would be good to have boundbox checks for some of these... */
- if (flag & ED_KEYMAP_UI) {
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "User Interface", 0, 0);
- WM_event_add_keymap_handler(handlers, keymap);
-
- /* user interface widgets */
- UI_region_handlers_add(handlers);
- }
- if (flag & ED_KEYMAP_GIZMO) {
- BLI_assert(ar && ar->type->regionid == RGN_TYPE_WINDOW);
- if (ar) {
- /* 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});
- }
- WM_gizmomap_add_handlers(ar, ar->gizmo_map);
- }
- }
- if (flag & ED_KEYMAP_TOOL) {
- WM_event_add_keymap_handler_dynamic(&ar->handlers, WM_event_get_keymap_from_toolsystem, sa);
- }
- if (flag & ED_KEYMAP_VIEW2D) {
- /* 2d-viewport handling+manipulation */
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "View2D", 0, 0);
- WM_event_add_keymap_handler(handlers, keymap);
- }
- if (flag & ED_KEYMAP_MARKERS) {
- /* time-markers */
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Markers", 0, 0);
-
- /* use a boundbox restricted map */
- /* same local check for all areas */
- static rcti rect = {0, 10000, 0, -1};
- rect.ymax = UI_MARKER_MARGIN_Y;
- BLI_assert(ar->type->regionid == RGN_TYPE_WINDOW);
- WM_event_add_keymap_handler_bb(handlers, keymap, &rect, &ar->winrct);
- }
- if (flag & ED_KEYMAP_ANIMATION) {
- /* frame changing and timeline operators (for time spaces) */
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Animation", 0, 0);
- WM_event_add_keymap_handler(handlers, keymap);
- }
- if (flag & ED_KEYMAP_FRAMES) {
- /* frame changing/jumping (for all spaces) */
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Frames", 0, 0);
- WM_event_add_keymap_handler(handlers, keymap);
- }
- if (flag & ED_KEYMAP_HEADER) {
- /* standard keymap for headers regions */
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Header", 0, 0);
- WM_event_add_keymap_handler(handlers, keymap);
- }
- if (flag & ED_KEYMAP_FOOTER) {
- /* standard keymap for footer regions */
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Footer", 0, 0);
- WM_event_add_keymap_handler(handlers, keymap);
- }
-
- /* Keep last because of LMB/RMB handling, see: T57527. */
- if (flag & ED_KEYMAP_GPENCIL) {
- /* grease pencil */
- /* NOTE: This is now 4 keymaps - One for basic functionality,
- * and others for special stroke modes (edit, paint and sculpt).
- *
- * For now, it's easier to just include all,
- * since you hardly want one without the others.
- */
- wmKeyMap *keymap_general = WM_keymap_ensure(wm->defaultconf, "Grease Pencil", 0, 0);
- WM_event_add_keymap_handler(handlers, keymap_general);
-
- wmKeyMap *keymap_edit = WM_keymap_ensure(wm->defaultconf, "Grease Pencil Stroke Edit Mode", 0, 0);
- WM_event_add_keymap_handler(handlers, keymap_edit);
-
- wmKeyMap *keymap_paint = WM_keymap_ensure(wm->defaultconf, "Grease Pencil Stroke Paint Mode", 0, 0);
- WM_event_add_keymap_handler(handlers, keymap_paint);
-
- wmKeyMap *keymap_paint_draw = WM_keymap_ensure(wm->defaultconf, "Grease Pencil Stroke Paint (Draw brush)", 0, 0);
- WM_event_add_keymap_handler(handlers, keymap_paint_draw);
-
- wmKeyMap *keymap_paint_erase = WM_keymap_ensure(wm->defaultconf, "Grease Pencil Stroke Paint (Erase)", 0, 0);
- WM_event_add_keymap_handler(handlers, keymap_paint_erase);
-
- wmKeyMap *keymap_paint_fill = WM_keymap_ensure(wm->defaultconf, "Grease Pencil Stroke Paint (Fill)", 0, 0);
- WM_event_add_keymap_handler(handlers, keymap_paint_fill);
-
- wmKeyMap *keymap_sculpt = WM_keymap_ensure(wm->defaultconf, "Grease Pencil Stroke Sculpt Mode", 0, 0);
- WM_event_add_keymap_handler(handlers, keymap_sculpt);
- }
+static void ed_default_handlers(
+ wmWindowManager *wm, ScrArea *sa, ARegion *ar, ListBase *handlers, int flag)
+{
+ BLI_assert(ar ? (&ar->handlers == handlers) : (&sa->handlers == handlers));
+
+ /* note, add-handler checks if it already exists */
+
+ /* XXX it would be good to have boundbox checks for some of these... */
+ if (flag & ED_KEYMAP_UI) {
+ wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "User Interface", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap);
+
+ /* user interface widgets */
+ UI_region_handlers_add(handlers);
+ }
+ if (flag & ED_KEYMAP_GIZMO) {
+ BLI_assert(ar && ar->type->regionid == RGN_TYPE_WINDOW);
+ if (ar) {
+ /* 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});
+ }
+ WM_gizmomap_add_handlers(ar, ar->gizmo_map);
+ }
+ }
+ if (flag & ED_KEYMAP_TOOL) {
+ WM_event_add_keymap_handler_dynamic(&ar->handlers, WM_event_get_keymap_from_toolsystem, sa);
+ }
+ if (flag & ED_KEYMAP_VIEW2D) {
+ /* 2d-viewport handling+manipulation */
+ wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "View2D", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap);
+ }
+ if (flag & ED_KEYMAP_MARKERS) {
+ /* time-markers */
+ wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Markers", 0, 0);
+
+ /* use a boundbox restricted map */
+ /* same local check for all areas */
+ static rcti rect = {0, 10000, 0, -1};
+ rect.ymax = UI_MARKER_MARGIN_Y;
+ BLI_assert(ar->type->regionid == RGN_TYPE_WINDOW);
+ WM_event_add_keymap_handler_bb(handlers, keymap, &rect, &ar->winrct);
+ }
+ if (flag & ED_KEYMAP_ANIMATION) {
+ /* frame changing and timeline operators (for time spaces) */
+ wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Animation", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap);
+ }
+ if (flag & ED_KEYMAP_FRAMES) {
+ /* frame changing/jumping (for all spaces) */
+ wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Frames", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap);
+ }
+ if (flag & ED_KEYMAP_HEADER) {
+ /* standard keymap for headers regions */
+ wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Header", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap);
+ }
+ if (flag & ED_KEYMAP_FOOTER) {
+ /* standard keymap for footer regions */
+ wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Footer", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap);
+ }
+
+ /* Keep last because of LMB/RMB handling, see: T57527. */
+ if (flag & ED_KEYMAP_GPENCIL) {
+ /* grease pencil */
+ /* NOTE: This is now 4 keymaps - One for basic functionality,
+ * and others for special stroke modes (edit, paint and sculpt).
+ *
+ * For now, it's easier to just include all,
+ * since you hardly want one without the others.
+ */
+ wmKeyMap *keymap_general = WM_keymap_ensure(wm->defaultconf, "Grease Pencil", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_general);
+
+ wmKeyMap *keymap_edit = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Edit Mode", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_edit);
+
+ wmKeyMap *keymap_paint = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Paint Mode", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_paint);
+
+ wmKeyMap *keymap_paint_draw = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Paint (Draw brush)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_paint_draw);
+
+ wmKeyMap *keymap_paint_erase = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Paint (Erase)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_paint_erase);
+
+ wmKeyMap *keymap_paint_fill = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Paint (Fill)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_paint_fill);
+
+ wmKeyMap *keymap_sculpt = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Sculpt Mode", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_sculpt);
+ }
}
void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *area)
{
- rcti rect, overlap_rect;
- rcti window_rect;
+ rcti rect, overlap_rect;
+ rcti window_rect;
- if (!(area->flag & AREA_FLAG_REGION_SIZE_UPDATE)) {
- return;
- }
- const bScreen *screen = WM_window_get_active_screen(win);
+ if (!(area->flag & AREA_FLAG_REGION_SIZE_UPDATE)) {
+ return;
+ }
+ const bScreen *screen = WM_window_get_active_screen(win);
- WM_window_rect_calc(win, &window_rect);
- area_calc_totrct(area, &window_rect);
+ WM_window_rect_calc(win, &window_rect);
+ area_calc_totrct(area, &window_rect);
- /* region rect sizes */
- rect = area->totrct;
- overlap_rect = rect;
- region_rect_recursive(area, area->regionbase.first, &rect, &overlap_rect, 0);
+ /* region rect sizes */
+ rect = area->totrct;
+ overlap_rect = rect;
+ region_rect_recursive(area, area->regionbase.first, &rect, &overlap_rect, 0);
- /* Dynamically sized regions may have changed region sizes, so we have to force azone update. */
- area_azone_initialize(win, screen, area);
+ /* 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);
+ for (ARegion *ar = area->regionbase.first; ar; ar = ar->next) {
+ region_subwindow(ar);
- /* region size may have changed, init does necessary adjustments */
- if (ar->type->init) {
- ar->type->init(wm, ar);
- }
+ /* region size may have changed, init does necessary adjustments */
+ if (ar->type->init) {
+ ar->type->init(wm, ar);
+ }
- /* Some AZones use View2D data which is only updated in region init, so call that first! */
- region_azones_add(screen, area, ar, ar->alignment & ~RGN_SPLIT_PREV);
- }
- ED_area_azones_update(area, &win->eventstate->x);
+ /* Some AZones use View2D data which is only updated in region init, so call that first! */
+ region_azones_add(screen, area, ar, ar->alignment & ~RGN_SPLIT_PREV);
+ }
+ ED_area_azones_update(area, &win->eventstate->x);
- area->flag &= ~AREA_FLAG_REGION_SIZE_UPDATE;
+ area->flag &= ~AREA_FLAG_REGION_SIZE_UPDATE;
}
/* called in screen_refresh, or screens_init, also area size changes */
void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
{
- 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;
- rcti rect, overlap_rect;
- rcti window_rect;
-
- if (ED_area_is_global(sa) && (sa->global->flag & GLOBAL_AREA_IS_HIDDEN)) {
- return;
- }
- WM_window_rect_calc(win, &window_rect);
-
- /* set typedefinitions */
- sa->type = BKE_spacetype_from_id(sa->spacetype);
-
- if (sa->type == NULL) {
- sa->spacetype = SPACE_VIEW3D;
- sa->type = BKE_spacetype_from_id(sa->spacetype);
- }
-
- for (ar = sa->regionbase.first; ar; ar = ar->next)
- ar->type = BKE_regiontype_from_id_or_first(sa->type, ar->regiontype);
-
- /* area sizes */
- area_calc_totrct(sa, &window_rect);
-
- /* region rect sizes */
- rect = sa->totrct;
- overlap_rect = rect;
- region_rect_recursive(sa, sa->regionbase.first, &rect, &overlap_rect, 0);
- sa->flag &= ~AREA_FLAG_REGION_SIZE_UPDATE;
-
- /* default area handlers */
- ed_default_handlers(wm, sa, NULL, &sa->handlers, sa->type->keymapflag);
- /* checks spacedata, adds own handlers */
- if (sa->type->init)
- sa->type->init(wm, sa);
-
- /* clear all azones, add the area triangle widgets */
- area_azone_initialize(win, screen, sa);
-
- /* region windows, default and own handlers */
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- region_subwindow(ar);
-
- if (ar->visible) {
- /* default region handlers */
- ed_default_handlers(wm, sa, ar, &ar->handlers, ar->type->keymapflag);
- /* own handlers */
- if (ar->type->init) {
- ar->type->init(wm, ar);
- }
- }
- else {
- /* prevent uiblocks to run */
- UI_blocklist_free(NULL, &ar->uiblocks);
- }
-
- /* Some AZones use View2D data which is only updated in region init, so call that first! */
- region_azones_add(screen, sa, ar, ar->alignment & ~RGN_SPLIT_PREV);
- }
-
-
- /* 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;
- }
- else {
- sa->runtime.tool = NULL;
- sa->runtime.is_tool_set = true;
- }
- }
+ 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;
+ rcti rect, overlap_rect;
+ rcti window_rect;
+
+ if (ED_area_is_global(sa) && (sa->global->flag & GLOBAL_AREA_IS_HIDDEN)) {
+ return;
+ }
+ WM_window_rect_calc(win, &window_rect);
+
+ /* set typedefinitions */
+ sa->type = BKE_spacetype_from_id(sa->spacetype);
+
+ if (sa->type == NULL) {
+ sa->spacetype = SPACE_VIEW3D;
+ sa->type = BKE_spacetype_from_id(sa->spacetype);
+ }
+
+ for (ar = sa->regionbase.first; ar; ar = ar->next)
+ ar->type = BKE_regiontype_from_id_or_first(sa->type, ar->regiontype);
+
+ /* area sizes */
+ area_calc_totrct(sa, &window_rect);
+
+ /* region rect sizes */
+ rect = sa->totrct;
+ overlap_rect = rect;
+ region_rect_recursive(sa, sa->regionbase.first, &rect, &overlap_rect, 0);
+ sa->flag &= ~AREA_FLAG_REGION_SIZE_UPDATE;
+
+ /* default area handlers */
+ ed_default_handlers(wm, sa, NULL, &sa->handlers, sa->type->keymapflag);
+ /* checks spacedata, adds own handlers */
+ if (sa->type->init)
+ sa->type->init(wm, sa);
+
+ /* clear all azones, add the area triangle widgets */
+ area_azone_initialize(win, screen, sa);
+
+ /* region windows, default and own handlers */
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ region_subwindow(ar);
+
+ if (ar->visible) {
+ /* default region handlers */
+ ed_default_handlers(wm, sa, ar, &ar->handlers, ar->type->keymapflag);
+ /* own handlers */
+ if (ar->type->init) {
+ ar->type->init(wm, ar);
+ }
+ }
+ else {
+ /* prevent uiblocks to run */
+ UI_blocklist_free(NULL, &ar->uiblocks);
+ }
+
+ /* Some AZones use View2D data which is only updated in region init, so call that first! */
+ region_azones_add(screen, sa, ar, ar->alignment & ~RGN_SPLIT_PREV);
+ }
+
+ /* 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;
+ }
+ else {
+ sa->runtime.tool = NULL;
+ sa->runtime.is_tool_set = true;
+ }
+ }
}
static void region_update_rect(ARegion *ar)
{
- ar->winx = BLI_rcti_size_x(&ar->winrct) + 1;
- ar->winy = BLI_rcti_size_y(&ar->winrct) + 1;
+ ar->winx = BLI_rcti_size_x(&ar->winrct) + 1;
+ ar->winy = BLI_rcti_size_y(&ar->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);
+ /* 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);
}
/**
@@ -1685,63 +1706,63 @@ static void region_update_rect(ARegion *ar)
*/
void ED_region_update_rect(ARegion *ar)
{
- region_update_rect(ar);
+ region_update_rect(ar);
}
/* externally called for floating regions like menus */
void ED_region_init(ARegion *ar)
{
- /* refresh can be called before window opened */
- region_subwindow(ar);
+ /* refresh can be called before window opened */
+ region_subwindow(ar);
- region_update_rect(ar);
+ region_update_rect(ar);
}
void ED_region_cursor_set(wmWindow *win, ScrArea *sa, ARegion *ar)
{
- if (ar && sa && ar->type && ar->type->cursor) {
- ar->type->cursor(win, sa, ar);
- }
- else {
- if (WM_cursor_set_from_tool(win, sa, ar)) {
- return;
- }
- WM_cursor_set(win, CURSOR_STD);
- }
+ if (ar && sa && ar->type && ar->type->cursor) {
+ ar->type->cursor(win, sa, ar);
+ }
+ else {
+ if (WM_cursor_set_from_tool(win, sa, ar)) {
+ return;
+ }
+ WM_cursor_set(win, CURSOR_STD);
+ }
}
/* for use after changing visibility of regions */
void ED_region_visibility_change_update(bContext *C, ARegion *ar)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *sa = CTX_wm_area(C);
- if (ar->flag & RGN_FLAG_HIDDEN)
- WM_event_remove_handlers(C, &ar->handlers);
+ if (ar->flag & RGN_FLAG_HIDDEN)
+ WM_event_remove_handlers(C, &ar->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), sa);
+ ED_area_tag_redraw(sa);
}
/* for quick toggle, can skip fades */
void region_toggle_hidden(bContext *C, ARegion *ar, const bool do_fade)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *sa = CTX_wm_area(C);
- ar->flag ^= RGN_FLAG_HIDDEN;
+ ar->flag ^= RGN_FLAG_HIDDEN;
- if (do_fade && ar->overlap) {
- /* starts a timer, and in end calls the stuff below itself (region_sblend_invoke()) */
- region_blend_start(C, sa, ar);
- }
- else {
- ED_region_visibility_change_update(C, ar);
- }
+ if (do_fade && ar->overlap) {
+ /* starts a timer, and in end calls the stuff below itself (region_sblend_invoke()) */
+ region_blend_start(C, sa, ar);
+ }
+ else {
+ ED_region_visibility_change_update(C, ar);
+ }
}
/* exported to all editors, uses fading default */
void ED_region_toggle_hidden(bContext *C, ARegion *ar)
{
- region_toggle_hidden(C, ar, true);
+ region_toggle_hidden(C, ar, true);
}
/**
@@ -1749,73 +1770,72 @@ void ED_region_toggle_hidden(bContext *C, ARegion *ar)
*/
void ED_area_data_copy(ScrArea *sa_dst, ScrArea *sa_src, const bool do_free)
{
- SpaceType *st;
- ARegion *ar;
- const char spacetype = sa_dst->spacetype;
- const short flag_copy = HEADER_NO_PULLDOWN;
+ SpaceType *st;
+ ARegion *ar;
+ const char spacetype = sa_dst->spacetype;
+ const short flag_copy = HEADER_NO_PULLDOWN;
- sa_dst->spacetype = sa_src->spacetype;
- sa_dst->type = sa_src->type;
+ sa_dst->spacetype = sa_src->spacetype;
+ sa_dst->type = sa_src->type;
- sa_dst->flag = (sa_dst->flag & ~flag_copy) | (sa_src->flag & flag_copy);
+ sa_dst->flag = (sa_dst->flag & ~flag_copy) | (sa_src->flag & flag_copy);
- /* area */
- if (do_free) {
- BKE_spacedata_freelist(&sa_dst->spacedata);
- }
- BKE_spacedata_copylist(&sa_dst->spacedata, &sa_src->spacedata);
+ /* area */
+ if (do_free) {
+ BKE_spacedata_freelist(&sa_dst->spacedata);
+ }
+ BKE_spacedata_copylist(&sa_dst->spacedata, &sa_src->spacedata);
- /* Note; SPACE_EMPTY is possible on new screens */
+ /* 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);
- BLI_freelistN(&sa_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);
- }
+ /* 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);
+ BLI_freelistN(&sa_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);
+ }
}
void ED_area_data_swap(ScrArea *sa_dst, ScrArea *sa_src)
{
- SWAP(char, sa_dst->spacetype, sa_src->spacetype);
- SWAP(SpaceType *, sa_dst->type, sa_src->type);
-
+ SWAP(char, sa_dst->spacetype, sa_src->spacetype);
+ SWAP(SpaceType *, sa_dst->type, sa_src->type);
- SWAP(ListBase, sa_dst->spacedata, sa_src->spacedata);
- SWAP(ListBase, sa_dst->regionbase, sa_src->regionbase);
+ SWAP(ListBase, sa_dst->spacedata, sa_src->spacedata);
+ SWAP(ListBase, sa_dst->regionbase, sa_src->regionbase);
}
/* *********** Space switching code *********** */
void ED_area_swapspace(bContext *C, ScrArea *sa1, ScrArea *sa2)
{
- ScrArea *tmp = MEM_callocN(sizeof(ScrArea), "addscrarea");
+ ScrArea *tmp = MEM_callocN(sizeof(ScrArea), "addscrarea");
- ED_area_exit(C, sa1);
- ED_area_exit(C, sa2);
+ ED_area_exit(C, sa1);
+ ED_area_exit(C, 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_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);
- BKE_screen_area_free(tmp);
- MEM_freeN(tmp);
+ BKE_screen_area_free(tmp);
+ MEM_freeN(tmp);
- /* tell WM to refresh, cursor types etc */
- WM_event_add_mousemove(C);
+ /* tell WM to refresh, cursor types etc */
+ WM_event_add_mousemove(C);
- ED_area_tag_redraw(sa1);
- ED_area_tag_refresh(sa1);
- ED_area_tag_redraw(sa2);
- ED_area_tag_refresh(sa2);
+ ED_area_tag_redraw(sa1);
+ ED_area_tag_refresh(sa1);
+ ED_area_tag_redraw(sa2);
+ ED_area_tag_refresh(sa2);
}
/**
@@ -1823,325 +1843,348 @@ void ED_area_swapspace(bContext *C, ScrArea *sa1, ScrArea *sa2)
*/
void ED_area_newspace(bContext *C, ScrArea *sa, int type, const bool skip_ar_exit)
{
- wmWindow *win = CTX_wm_window(C);
-
- if (sa->spacetype != type) {
- SpaceType *st;
- SpaceLink *slold;
- SpaceLink *sl;
- /* store sa->type->exit callback */
- void *sa_exit = sa->type ? sa->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).
- *
- * However, add-on install for example, forces the header to the top which shouldn't
- * be applied back to the previous space type when closing - see: T57724
- *
- * Newly created windows wont have any space data, use the alignment
- * 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);
- const bool sync_header_alignment = (
- (header_alignment != -1) &&
- (sa->flag & AREA_FLAG_TEMP_TYPE) == 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;
- }
-
- ED_area_exit(C, sa);
-
- /* restore old area exit callback */
- if (skip_ar_exit && sa->type) {
- sa->type->exit = sa_exit;
- }
-
- st = BKE_spacetype_from_id(type);
- slold = sa->spacedata.first;
-
- sa->spacetype = type;
- sa->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
- * (e.g. with properties editor) until space-data is properly created */
-
- /* check previously stored space */
- for (sl = sa->spacedata.first; sl; sl = sl->next)
- if (sl->spacetype == type)
- break;
-
- /* 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);
- if (slold == sl) {
- slold = NULL;
- }
- sl = NULL;
- }
-
- if (sl) {
- /* swap regions */
- slold->regionbase = sa->regionbase;
- sa->regionbase = sl->regionbase;
- BLI_listbase_clear(&sl->regionbase);
-
- /* put in front of list */
- BLI_remlink(&sa->spacedata, sl);
- BLI_addhead(&sa->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);
-
- /* swap regions */
- if (slold)
- slold->regionbase = sa->regionbase;
- sa->regionbase = sl->regionbase;
- BLI_listbase_clear(&sl->regionbase);
- }
- }
-
- /* Sync header alignment. */
- if (sync_header_alignment) {
- /* Spaces with footer. */
- if (st->spaceid == SPACE_TEXT) {
- for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_HEADER) {
- ar->alignment = header_alignment;
- }
- if (ar->regiontype == RGN_TYPE_FOOTER) {
- int footer_alignment = (header_alignment == RGN_ALIGN_BOTTOM) ? RGN_ALIGN_TOP : RGN_ALIGN_BOTTOM;
- ar->alignment = footer_alignment;
- break;
- }
- }
- }
- else {
- for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_HEADER) {
- ar->alignment = header_alignment;
- break;
- }
- }
- }
- }
-
- ED_area_initialize(CTX_wm_manager(C), win, sa);
-
- /* tell WM to refresh, cursor types etc */
- WM_event_add_mousemove(C);
-
- /* send space change notifier */
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CHANGED, sa);
-
- ED_area_tag_refresh(sa);
- }
-
- /* also redraw when re-used */
- ED_area_tag_redraw(sa);
+ wmWindow *win = CTX_wm_window(C);
+
+ if (sa->spacetype != type) {
+ SpaceType *st;
+ SpaceLink *slold;
+ SpaceLink *sl;
+ /* store sa->type->exit callback */
+ void *sa_exit = sa->type ? sa->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).
+ *
+ * However, add-on install for example, forces the header to the top which shouldn't
+ * be applied back to the previous space type when closing - see: T57724
+ *
+ * Newly created windows wont have any space data, use the alignment
+ * 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);
+ const bool sync_header_alignment = ((header_alignment != -1) &&
+ (sa->flag & AREA_FLAG_TEMP_TYPE) == 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;
+ }
+
+ ED_area_exit(C, sa);
+
+ /* restore old area exit callback */
+ if (skip_ar_exit && sa->type) {
+ sa->type->exit = sa_exit;
+ }
+
+ st = BKE_spacetype_from_id(type);
+ slold = sa->spacedata.first;
+
+ sa->spacetype = type;
+ sa->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
+ * (e.g. with properties editor) until space-data is properly created */
+
+ /* check previously stored space */
+ for (sl = sa->spacedata.first; sl; sl = sl->next)
+ if (sl->spacetype == type)
+ break;
+
+ /* 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);
+ if (slold == sl) {
+ slold = NULL;
+ }
+ sl = NULL;
+ }
+
+ if (sl) {
+ /* swap regions */
+ slold->regionbase = sa->regionbase;
+ sa->regionbase = sl->regionbase;
+ BLI_listbase_clear(&sl->regionbase);
+
+ /* put in front of list */
+ BLI_remlink(&sa->spacedata, sl);
+ BLI_addhead(&sa->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);
+
+ /* swap regions */
+ if (slold)
+ slold->regionbase = sa->regionbase;
+ sa->regionbase = sl->regionbase;
+ BLI_listbase_clear(&sl->regionbase);
+ }
+ }
+
+ /* Sync header alignment. */
+ if (sync_header_alignment) {
+ /* Spaces with footer. */
+ if (st->spaceid == SPACE_TEXT) {
+ for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_HEADER) {
+ ar->alignment = header_alignment;
+ }
+ if (ar->regiontype == RGN_TYPE_FOOTER) {
+ int footer_alignment = (header_alignment == RGN_ALIGN_BOTTOM) ? RGN_ALIGN_TOP :
+ RGN_ALIGN_BOTTOM;
+ ar->alignment = footer_alignment;
+ break;
+ }
+ }
+ }
+ else {
+ for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_HEADER) {
+ ar->alignment = header_alignment;
+ break;
+ }
+ }
+ }
+ }
+
+ ED_area_initialize(CTX_wm_manager(C), win, sa);
+
+ /* tell WM to refresh, cursor types etc */
+ WM_event_add_mousemove(C);
+
+ /* send space change notifier */
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CHANGED, sa);
+
+ ED_area_tag_refresh(sa);
+ }
+
+ /* also redraw when re-used */
+ ED_area_tag_redraw(sa);
}
void ED_area_prevspace(bContext *C, ScrArea *sa)
{
- SpaceLink *sl = sa->spacedata.first;
+ SpaceLink *sl = sa->spacedata.first;
- if (sl && sl->next) {
- ED_area_newspace(C, sa, sl->next->spacetype, false);
+ if (sl && sl->next) {
+ ED_area_newspace(C, sa, sl->next->spacetype, false);
- /* keep old spacedata but move it to end, so calling
- * ED_area_prevspace once more won't open it again */
- BLI_remlink(&sa->spacedata, sl);
- BLI_addtail(&sa->spacedata, sl);
- }
- else {
- /* no change */
- return;
- }
- sa->flag &= ~(AREA_FLAG_STACKED_FULLSCREEN | AREA_FLAG_TEMP_TYPE);
+ /* keep old spacedata but move it to end, so calling
+ * ED_area_prevspace once more won't open it again */
+ BLI_remlink(&sa->spacedata, sl);
+ BLI_addtail(&sa->spacedata, sl);
+ }
+ else {
+ /* no change */
+ return;
+ }
+ sa->flag &= ~(AREA_FLAG_STACKED_FULLSCREEN | AREA_FLAG_TEMP_TYPE);
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(sa);
- /* send space change notifier */
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CHANGED, sa);
+ /* send space change notifier */
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CHANGED, sa);
}
/* 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);
- PointerRNA areaptr;
- int xco = 0.4 * U.widget_unit;
-
- RNA_pointer_create(&(scr->id), &RNA_Area, sa, &areaptr);
-
- uiDefButR(block, UI_BTYPE_MENU, 0, "", xco, yco, 1.6 * U.widget_unit, U.widget_unit,
- &areaptr, "ui_type", 0, 0.0f, 0.0f, 0.0f, 0.0f, "");
-
- return xco + 1.7 * U.widget_unit;
+ ScrArea *sa = CTX_wm_area(C);
+ bScreen *scr = CTX_wm_screen(C);
+ PointerRNA areaptr;
+ int xco = 0.4 * U.widget_unit;
+
+ RNA_pointer_create(&(scr->id), &RNA_Area, sa, &areaptr);
+
+ uiDefButR(block,
+ UI_BTYPE_MENU,
+ 0,
+ "",
+ xco,
+ yco,
+ 1.6 * U.widget_unit,
+ U.widget_unit,
+ &areaptr,
+ "ui_type",
+ 0,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ "");
+
+ return xco + 1.7 * U.widget_unit;
}
/************************ standard UI regions ************************/
static ThemeColorID region_background_color_id(const bContext *C, const ARegion *region)
{
- ScrArea *area = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
- switch (region->regiontype) {
- case RGN_TYPE_HEADER:
- if (ED_screen_area_active(C) || ED_area_is_global(area)) {
- return TH_HEADER;
- }
- else {
- return TH_HEADERDESEL;
- }
- case RGN_TYPE_PREVIEW:
- return TH_PREVIEW_BACK;
- default:
- return TH_BACK;
- }
+ switch (region->regiontype) {
+ case RGN_TYPE_HEADER:
+ if (ED_screen_area_active(C) || ED_area_is_global(area)) {
+ return TH_HEADER;
+ }
+ else {
+ return TH_HEADERDESEL;
+ }
+ case RGN_TYPE_PREVIEW:
+ return TH_PREVIEW_BACK;
+ default:
+ return TH_BACK;
+ }
}
static void region_clear_color(const bContext *C, const ARegion *ar, ThemeColorID colorid)
{
- if (ar->alignment == RGN_ALIGN_FLOAT) {
- /* handle our own drawing. */
- }
- else if (ar->overlap) {
- /* view should be in pixelspace */
- UI_view2d_view_restore(C);
+ if (ar->alignment == RGN_ALIGN_FLOAT) {
+ /* handle our own drawing. */
+ }
+ else if (ar->overlap) {
+ /* view should be in pixelspace */
+ UI_view2d_view_restore(C);
- float back[4];
- UI_GetThemeColor4fv(colorid, back);
- GPU_clear_color(back[3] * back[0], back[3] * back[1], back[3] * back[2], back[3]);
- GPU_clear(GPU_COLOR_BIT);
- }
- else {
- UI_ThemeClearColor(colorid);
- GPU_clear(GPU_COLOR_BIT);
- }
+ float back[4];
+ UI_GetThemeColor4fv(colorid, back);
+ GPU_clear_color(back[3] * back[0], back[3] * back[1], back[3] * back[2], back[3]);
+ GPU_clear(GPU_COLOR_BIT);
+ }
+ else {
+ UI_ThemeClearColor(colorid);
+ GPU_clear(GPU_COLOR_BIT);
+ }
}
BLI_INLINE bool streq_array_any(const char *s, const char *arr[])
{
- for (uint i = 0; arr[i]; i++) {
- if (STREQ(arr[i], s)) {
- return true;
- }
- }
- return false;
-}
-
-static void ed_panel_draw(
- const bContext *C,
- ScrArea *sa,
- ARegion *ar,
- ListBase *lb,
- PanelType *pt,
- Panel *panel,
- int w,
- int em,
- bool vertical)
-{
- uiStyle *style = UI_style_get_dpi();
-
- /* draw panel */
- uiBlock *block = UI_block_begin(C, ar, pt->idname, UI_EMBOSS);
-
- bool open;
- panel = UI_panel_begin(sa, ar, lb, block, pt, panel, &open);
-
- /* bad fixed values */
- int xco, yco, h = 0;
-
- if (pt->draw_header_preset && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
- /* for preset menu */
- panel->layout = UI_block_layout(
- block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
- 0, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, 0, style);
-
- pt->draw_header_preset(C, panel);
-
- int headerend = w - UI_UNIT_X;
-
- UI_block_layout_resolve(block, &xco, &yco);
- UI_block_translate(block, headerend - xco, 0);
- panel->layout = NULL;
- }
-
- if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
- int labelx, labely;
- UI_panel_label_offset(block, &labelx, &labely);
-
- /* for enabled buttons */
- panel->layout = UI_block_layout(
- block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
- labelx, labely, UI_UNIT_Y, 1, 0, style);
-
- pt->draw_header(C, panel);
-
- UI_block_layout_resolve(block, &xco, &yco);
- panel->labelofs = xco - labelx;
- panel->layout = NULL;
- }
- else {
- panel->labelofs = 0;
- }
-
- if (open) {
- short panelContext;
-
- /* panel context can either be toolbar region or normal panels region */
- if (pt->flag & PNL_LAYOUT_VERT_BAR) {
- panelContext = UI_LAYOUT_VERT_BAR;
- }
- else if (ar->regiontype == RGN_TYPE_TOOLS) {
- panelContext = UI_LAYOUT_TOOLBAR;
- }
- else {
- panelContext = UI_LAYOUT_PANEL;
- }
-
- panel->layout = UI_block_layout(
- block, UI_LAYOUT_VERTICAL, panelContext,
- (pt->flag & PNL_LAYOUT_VERT_BAR) ? 0 : style->panelspace, 0,
- (pt->flag & PNL_LAYOUT_VERT_BAR) ? 0 : w - 2 * style->panelspace,
- em, 0, style);
-
- pt->draw(C, panel);
-
- UI_block_layout_resolve(block, &xco, &yco);
- panel->layout = NULL;
-
- if (yco != 0) {
- h = -yco + 2 * style->panelspace;
- }
- }
-
- UI_block_end(C, block);
-
- /* Draw child panels. */
- if (open) {
- for (LinkData *link = pt->children.first; link; link = link->next) {
- 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);
- }
- }
- }
-
- UI_panel_end(block, w, h);
+ for (uint i = 0; arr[i]; i++) {
+ if (STREQ(arr[i], s)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void ed_panel_draw(const bContext *C,
+ ScrArea *sa,
+ ARegion *ar,
+ ListBase *lb,
+ PanelType *pt,
+ Panel *panel,
+ int w,
+ int em,
+ bool vertical)
+{
+ uiStyle *style = UI_style_get_dpi();
+
+ /* draw panel */
+ uiBlock *block = UI_block_begin(C, ar, pt->idname, UI_EMBOSS);
+
+ bool open;
+ panel = UI_panel_begin(sa, ar, lb, block, pt, panel, &open);
+
+ /* bad fixed values */
+ int xco, yco, h = 0;
+
+ if (pt->draw_header_preset && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
+ /* for preset menu */
+ panel->layout = UI_block_layout(block,
+ UI_LAYOUT_HORIZONTAL,
+ UI_LAYOUT_HEADER,
+ 0,
+ (UI_UNIT_Y * 1.1f) + style->panelspace,
+ UI_UNIT_Y,
+ 1,
+ 0,
+ style);
+
+ pt->draw_header_preset(C, panel);
+
+ int headerend = w - UI_UNIT_X;
+
+ UI_block_layout_resolve(block, &xco, &yco);
+ UI_block_translate(block, headerend - xco, 0);
+ panel->layout = NULL;
+ }
+
+ if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
+ int labelx, labely;
+ UI_panel_label_offset(block, &labelx, &labely);
+
+ /* for enabled buttons */
+ panel->layout = UI_block_layout(
+ block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, labelx, labely, UI_UNIT_Y, 1, 0, style);
+
+ pt->draw_header(C, panel);
+
+ UI_block_layout_resolve(block, &xco, &yco);
+ panel->labelofs = xco - labelx;
+ panel->layout = NULL;
+ }
+ else {
+ panel->labelofs = 0;
+ }
+
+ if (open) {
+ short panelContext;
+
+ /* panel context can either be toolbar region or normal panels region */
+ if (pt->flag & PNL_LAYOUT_VERT_BAR) {
+ panelContext = UI_LAYOUT_VERT_BAR;
+ }
+ else if (ar->regiontype == RGN_TYPE_TOOLS) {
+ panelContext = UI_LAYOUT_TOOLBAR;
+ }
+ else {
+ panelContext = UI_LAYOUT_PANEL;
+ }
+
+ panel->layout = UI_block_layout(block,
+ UI_LAYOUT_VERTICAL,
+ panelContext,
+ (pt->flag & PNL_LAYOUT_VERT_BAR) ? 0 : style->panelspace,
+ 0,
+ (pt->flag & PNL_LAYOUT_VERT_BAR) ? 0 :
+ w - 2 * style->panelspace,
+ em,
+ 0,
+ style);
+
+ pt->draw(C, panel);
+
+ UI_block_layout_resolve(block, &xco, &yco);
+ panel->layout = NULL;
+
+ if (yco != 0) {
+ h = -yco + 2 * style->panelspace;
+ }
+ }
+
+ UI_block_end(C, block);
+
+ /* Draw child panels. */
+ if (open) {
+ for (LinkData *link = pt->children.first; link; link = link->next) {
+ 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);
+ }
+ }
+ }
+
+ UI_panel_end(block, w, h);
}
/**
@@ -2150,430 +2193,423 @@ static void ed_panel_draw(
* Can be NULL to skip context checks.
*/
void ED_region_panels_layout_ex(
- const bContext *C, ARegion *ar,
- const char *contexts[], int contextnr, const bool vertical)
-{
- ar->runtime.category = NULL;
-
- const WorkSpace *workspace = CTX_wm_workspace(C);
- ScrArea *sa = CTX_wm_area(C);
- PanelType *pt;
- View2D *v2d = &ar->v2d;
- int x, y, w, em;
- bool is_context_new = 0;
- int scroll;
-
- /* XXX, should use some better check? */
- /* For now also has hardcoded check for clip editor until it supports actual toolbar. */
- bool use_category_tabs = ((1 << ar->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) ||
- (ar->regiontype == RGN_TYPE_TOOLS && sa->spacetype == SPACE_CLIP);
- /* offset panels for small vertical tab area */
- const char *category = NULL;
- const int category_tabs_width = UI_PANEL_CATEGORY_MARGIN_WIDTH;
- int margin_x = 0;
- const bool region_layout_based = ar->flag & RGN_FLAG_DYNAMIC_SIZE;
-
- BLI_SMALLSTACK_DECLARE(pt_stack, PanelType *);
-
- if (contextnr != -1)
- is_context_new = UI_view2d_tab_set(v2d, contextnr);
-
- /* before setting the view */
- if (vertical) {
- /* only allow scrolling in vertical direction */
- v2d->keepofs |= V2D_LOCKOFS_X | V2D_KEEPOFS_Y;
- v2d->keepofs &= ~(V2D_LOCKOFS_Y | V2D_KEEPOFS_X);
- v2d->scroll &= ~(V2D_SCROLL_BOTTOM);
- v2d->scroll |= (V2D_SCROLL_RIGHT);
- }
- else {
- /* for now, allow scrolling in both directions (since layouts are optimized for vertical,
- * they often don't fit in horizontal layout)
- */
- v2d->keepofs &= ~(V2D_LOCKOFS_X | V2D_LOCKOFS_Y | V2D_KEEPOFS_X | V2D_KEEPOFS_Y);
- v2d->scroll |= (V2D_SCROLL_BOTTOM);
- v2d->scroll &= ~(V2D_SCROLL_RIGHT);
- }
-
- scroll = v2d->scroll;
-
-
- /* collect panels to draw */
- for (pt = ar->type->paneltypes.last; pt; pt = pt->prev) {
- /* Only draw top level panels. */
- if (pt->parent) {
- continue;
- }
-
- /* verify context */
- if (contexts && pt->context[0] && !streq_array_any(pt->context, contexts)) {
- continue;
- }
-
- /* If we're tagged, only use compatible. */
- if (pt->owner_id[0] && BKE_workspace_owner_id_check(workspace, pt->owner_id) == false) {
- continue;
- }
-
- /* draw panel */
- if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
- BLI_SMALLSTACK_PUSH(pt_stack, pt);
- }
- }
-
-
- /* collect categories */
- if (use_category_tabs) {
- UI_panel_category_clear_all(ar);
-
- /* gather unique categories */
- BLI_SMALLSTACK_ITER_BEGIN(pt_stack, pt)
- {
- if (pt->category[0]) {
- if (!UI_panel_category_find(ar, pt->category)) {
- UI_panel_category_add(ar, pt->category);
- }
- }
- }
- BLI_SMALLSTACK_ITER_END;
-
- if (!UI_panel_category_is_visible(ar)) {
- use_category_tabs = false;
- }
- else {
- category = UI_panel_category_active_get(ar, 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 */
- }
- else {
- w = UI_PANEL_WIDTH;
- em = (ar->type->prefsizex) ? 10 : 20;
- }
-
- w -= margin_x;
-
- /* create panels */
- UI_panels_begin(C, ar);
-
- /* set view2d view matrix - UI_block_begin() stores it */
- UI_view2d_view_ortho(v2d);
-
- BLI_SMALLSTACK_ITER_BEGIN(pt_stack, pt)
- {
- Panel *panel = UI_panel_find_by_type(&ar->panels, pt);
-
- if (use_category_tabs && pt->category[0] && !STREQ(category, pt->category)) {
- if ((panel == NULL) || ((panel->flag & PNL_PIN) == 0)) {
- continue;
- }
- }
-
- ed_panel_draw(C, sa, ar, &ar->panels, pt, panel, w, em, vertical);
- }
- BLI_SMALLSTACK_ITER_END;
-
- /* align panels and return size */
- UI_panels_end(C, ar, &x, &y);
-
- /* 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;
- if (panel != NULL) {
- 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;
- }
- y = ABS(ar->sizey * UI_DPI_FAC - 1);
- }
- }
- else if (vertical) {
- /* we always keep the scroll offset - so the total view gets increased with the scrolled away part */
- if (v2d->cur.ymax < -FLT_EPSILON) {
- /* Clamp to lower view boundary */
- if (v2d->tot.ymin < -v2d->winy) {
- y = min_ii(y, 0);
- }
- else {
- y = min_ii(y, v2d->cur.ymin);
- }
- }
-
- y = -y;
- }
- else {
- /* don't jump back when panels close or hide */
- if (!is_context_new) {
- if (v2d->tot.xmax > v2d->winx) {
- x = max_ii(x, 0);
- }
- else {
- x = max_ii(x, v2d->cur.xmax);
- }
- }
-
- 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 */
+ const bContext *C, ARegion *ar, const char *contexts[], int contextnr, const bool vertical)
+{
+ ar->runtime.category = NULL;
+
+ const WorkSpace *workspace = CTX_wm_workspace(C);
+ ScrArea *sa = CTX_wm_area(C);
+ PanelType *pt;
+ View2D *v2d = &ar->v2d;
+ int x, y, w, em;
+ bool is_context_new = 0;
+ int scroll;
+
+ /* XXX, should use some better check? */
+ /* For now also has hardcoded check for clip editor until it supports actual toolbar. */
+ bool use_category_tabs = ((1 << ar->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) ||
+ (ar->regiontype == RGN_TYPE_TOOLS && sa->spacetype == SPACE_CLIP);
+ /* offset panels for small vertical tab area */
+ const char *category = NULL;
+ const int category_tabs_width = UI_PANEL_CATEGORY_MARGIN_WIDTH;
+ int margin_x = 0;
+ const bool region_layout_based = ar->flag & RGN_FLAG_DYNAMIC_SIZE;
+
+ BLI_SMALLSTACK_DECLARE(pt_stack, PanelType *);
+
+ if (contextnr != -1)
+ is_context_new = UI_view2d_tab_set(v2d, contextnr);
+
+ /* before setting the view */
+ if (vertical) {
+ /* only allow scrolling in vertical direction */
+ v2d->keepofs |= V2D_LOCKOFS_X | V2D_KEEPOFS_Y;
+ v2d->keepofs &= ~(V2D_LOCKOFS_Y | V2D_KEEPOFS_X);
+ v2d->scroll &= ~(V2D_SCROLL_BOTTOM);
+ v2d->scroll |= (V2D_SCROLL_RIGHT);
+ }
+ else {
+ /* for now, allow scrolling in both directions (since layouts are optimized for vertical,
+ * they often don't fit in horizontal layout)
+ */
+ v2d->keepofs &= ~(V2D_LOCKOFS_X | V2D_LOCKOFS_Y | V2D_KEEPOFS_X | V2D_KEEPOFS_Y);
+ v2d->scroll |= (V2D_SCROLL_BOTTOM);
+ v2d->scroll &= ~(V2D_SCROLL_RIGHT);
+ }
+
+ scroll = v2d->scroll;
+
+ /* collect panels to draw */
+ for (pt = ar->type->paneltypes.last; pt; pt = pt->prev) {
+ /* Only draw top level panels. */
+ if (pt->parent) {
+ continue;
+ }
+
+ /* verify context */
+ if (contexts && pt->context[0] && !streq_array_any(pt->context, contexts)) {
+ continue;
+ }
+
+ /* If we're tagged, only use compatible. */
+ if (pt->owner_id[0] && BKE_workspace_owner_id_check(workspace, pt->owner_id) == false) {
+ continue;
+ }
+
+ /* draw panel */
+ if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
+ BLI_SMALLSTACK_PUSH(pt_stack, pt);
+ }
+ }
+
+ /* collect categories */
+ if (use_category_tabs) {
+ UI_panel_category_clear_all(ar);
+
+ /* gather unique categories */
+ BLI_SMALLSTACK_ITER_BEGIN (pt_stack, pt) {
+ if (pt->category[0]) {
+ if (!UI_panel_category_find(ar, pt->category)) {
+ UI_panel_category_add(ar, pt->category);
+ }
+ }
+ }
+ BLI_SMALLSTACK_ITER_END;
+
+ if (!UI_panel_category_is_visible(ar)) {
+ use_category_tabs = false;
+ }
+ else {
+ category = UI_panel_category_active_get(ar, 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 */
+ }
+ else {
+ w = UI_PANEL_WIDTH;
+ em = (ar->type->prefsizex) ? 10 : 20;
+ }
+
+ w -= margin_x;
+
+ /* create panels */
+ UI_panels_begin(C, ar);
+
+ /* set view2d view matrix - UI_block_begin() stores it */
+ UI_view2d_view_ortho(v2d);
+
+ BLI_SMALLSTACK_ITER_BEGIN (pt_stack, pt) {
+ Panel *panel = UI_panel_find_by_type(&ar->panels, pt);
+
+ if (use_category_tabs && pt->category[0] && !STREQ(category, pt->category)) {
+ if ((panel == NULL) || ((panel->flag & PNL_PIN) == 0)) {
+ continue;
+ }
+ }
+
+ ed_panel_draw(C, sa, ar, &ar->panels, pt, panel, w, em, vertical);
+ }
+ BLI_SMALLSTACK_ITER_END;
+
+ /* align panels and return size */
+ UI_panels_end(C, ar, &x, &y);
+
+ /* 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;
+ if (panel != NULL) {
+ 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;
+ }
+ y = ABS(ar->sizey * UI_DPI_FAC - 1);
+ }
+ }
+ else if (vertical) {
+ /* we always keep the scroll offset - so the total view gets increased with the scrolled away part */
+ if (v2d->cur.ymax < -FLT_EPSILON) {
+ /* Clamp to lower view boundary */
+ if (v2d->tot.ymin < -v2d->winy) {
+ y = min_ii(y, 0);
+ }
+ else {
+ y = min_ii(y, v2d->cur.ymin);
+ }
+ }
+
+ y = -y;
+ }
+ else {
+ /* don't jump back when panels close or hide */
+ if (!is_context_new) {
+ if (v2d->tot.xmax > v2d->winx) {
+ x = max_ii(x, 0);
+ }
+ else {
+ x = max_ii(x, v2d->cur.xmax);
+ }
+ }
+
+ 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;
+ UI_panels_scale(ar, BLI_rctf_size_x(&v2d->cur));
+ break;
#endif
- }
+ }
- if (use_category_tabs) {
- ar->runtime.category = category;
- }
+ if (use_category_tabs) {
+ ar->runtime.category = category;
+ }
}
void ED_region_panels_layout(const bContext *C, ARegion *ar)
{
- ED_region_panels_layout_ex(C, ar, NULL, -1, true);
+ ED_region_panels_layout_ex(C, ar, NULL, -1, true);
}
void ED_region_panels_draw(const bContext *C, ARegion *ar)
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &ar->v2d;
- if (ar->alignment != RGN_ALIGN_FLOAT) {
- region_clear_color(C, ar, (ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK);
- }
+ if (ar->alignment != RGN_ALIGN_FLOAT) {
+ region_clear_color(
+ C, ar, (ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK);
+ }
- /* reset line width for drawing tabs */
- GPU_line_width(1.0f);
+ /* reset line width for drawing tabs */
+ GPU_line_width(1.0f);
- /* set the view */
- UI_view2d_view_ortho(v2d);
+ /* set the view */
+ UI_view2d_view_ortho(v2d);
- /* View2D matrix might have changed due to dynamic sized regions. */
- UI_blocklist_update_window_matrix(C, &ar->uiblocks);
+ /* View2D matrix might have changed due to dynamic sized regions. */
+ UI_blocklist_update_window_matrix(C, &ar->uiblocks);
- /* draw panels */
- UI_panels_draw(C, ar);
+ /* draw panels */
+ UI_panels_draw(C, ar);
- /* restore view matrix */
- UI_view2d_view_restore(C);
+ /* restore view matrix */
+ UI_view2d_view_restore(C);
- /* Set in layout. */
- if (ar->runtime.category) {
- UI_panel_category_draw_all(ar, ar->runtime.category);
- }
+ /* Set in layout. */
+ if (ar->runtime.category) {
+ UI_panel_category_draw_all(ar, ar->runtime.category);
+ }
- /* scrollers */
- const rcti *mask = NULL;
- rcti mask_buf;
- if (ar->runtime.category && (ar->alignment == RGN_ALIGN_RIGHT)) {
- UI_view2d_mask_from_win(v2d, &mask_buf);
- mask_buf.xmax -= UI_PANEL_CATEGORY_MARGIN_WIDTH;
- mask = &mask_buf;
- }
- View2DScrollers *scrollers = UI_view2d_scrollers_calc(
- C, v2d, mask, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
+ /* scrollers */
+ const rcti *mask = NULL;
+ rcti mask_buf;
+ if (ar->runtime.category && (ar->alignment == RGN_ALIGN_RIGHT)) {
+ UI_view2d_mask_from_win(v2d, &mask_buf);
+ mask_buf.xmax -= UI_PANEL_CATEGORY_MARGIN_WIDTH;
+ mask = &mask_buf;
+ }
+ View2DScrollers *scrollers = UI_view2d_scrollers_calc(
+ C, v2d, mask, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
}
void ED_region_panels_ex(
- const bContext *C, ARegion *ar,
- const char *contexts[], int contextnr, const bool vertical)
+ const bContext *C, ARegion *ar, const char *contexts[], int contextnr, const bool vertical)
{
- /* TODO: remove? */
- ED_region_panels_layout_ex(C, ar, contexts, contextnr, vertical);
- ED_region_panels_draw(C, ar);
+ /* TODO: remove? */
+ ED_region_panels_layout_ex(C, ar, contexts, contextnr, vertical);
+ ED_region_panels_draw(C, ar);
}
void ED_region_panels(const bContext *C, ARegion *ar)
{
- /* TODO: remove? */
- ED_region_panels_layout(C, ar);
- ED_region_panels_draw(C, ar);
+ /* TODO: remove? */
+ ED_region_panels_layout(C, ar);
+ ED_region_panels_draw(C, ar);
}
void ED_region_panels_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy);
- keymap = WM_keymap_ensure(wm->defaultconf, "View2D Buttons List", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "View2D Buttons List", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
}
void ED_region_header_layout(const bContext *C, ARegion *ar)
{
- 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;
+ 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;
- /* Height of buttons and scaling needed to achieve it. */
- const int buttony = min_ii(UI_UNIT_Y, ar->winy - 2 * UI_DPI_FAC);
- const float buttony_scale = buttony / (float)UI_UNIT_Y;
+ /* Height of buttons and scaling needed to achieve it. */
+ const int buttony = min_ii(UI_UNIT_Y, ar->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 maxco = xco;
+ /* Vertically center buttons. */
+ int xco = UI_HEADER_OFFSET;
+ int yco = buttony + (ar->winy - buttony) / 2;
+ int maxco = xco;
- /* XXX workaround for 1 px alignment issue. Not sure what causes it... Would prefer a proper fix - Julian */
- if (!ELEM(CTX_wm_area(C)->spacetype, SPACE_TOPBAR, SPACE_STATUSBAR)) {
- yco -= 1;
- }
+ /* XXX workaround for 1 px alignment issue. Not sure what causes it... Would prefer a proper fix - Julian */
+ if (!ELEM(CTX_wm_area(C)->spacetype, SPACE_TOPBAR, SPACE_STATUSBAR)) {
+ yco -= 1;
+ }
- /* set view2d view matrix for scrolling (without scrollers) */
- UI_view2d_view_ortho(&ar->v2d);
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(&ar->v2d);
- /* draw all headers types */
- for (ht = ar->type->headertypes.first; ht; ht = ht->next) {
- if (ht->poll && !ht->poll(C, ht)) {
- continue;
- }
+ /* draw all headers types */
+ for (ht = ar->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);
- layout = UI_block_layout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, xco, yco, buttony, 1, 0, style);
+ block = UI_block_begin(C, ar, ht->idname, UI_EMBOSS);
+ layout = UI_block_layout(
+ block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, xco, yco, buttony, 1, 0, style);
- if (buttony_scale != 1.0f) {
- uiLayoutSetScaleY(layout, buttony_scale);
- }
+ if (buttony_scale != 1.0f) {
+ uiLayoutSetScaleY(layout, buttony_scale);
+ }
- if (ht->draw) {
- header.type = ht;
- header.layout = layout;
- ht->draw(C, &header);
- if (ht->next) {
- uiItemS(layout);
- }
+ if (ht->draw) {
+ header.type = ht;
+ header.layout = layout;
+ ht->draw(C, &header);
+ if (ht->next) {
+ uiItemS(layout);
+ }
- /* for view2d */
- xco = uiLayoutGetWidth(layout);
- if (xco > maxco)
- maxco = xco;
- }
+ /* for view2d */
+ xco = uiLayoutGetWidth(layout);
+ if (xco > maxco)
+ maxco = xco;
+ }
- UI_block_layout_resolve(block, &xco, &yco);
+ UI_block_layout_resolve(block, &xco, &yco);
- /* for view2d */
- if (xco > maxco)
- maxco = xco;
+ /* for view2d */
+ if (xco > maxco)
+ maxco = xco;
- int new_sizex = (maxco + UI_HEADER_OFFSET) / UI_DPI_FAC;
+ int new_sizex = (maxco + UI_HEADER_OFFSET) / UI_DPI_FAC;
- if (region_layout_based && (ar->sizex != new_sizex)) {
- /* region size is layout based and needs to be updated */
- ScrArea *sa = CTX_wm_area(C);
+ if (region_layout_based && (ar->sizex != new_sizex)) {
+ /* region size is layout based and needs to be updated */
+ ScrArea *sa = CTX_wm_area(C);
- ar->sizex = new_sizex;
- sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
- }
+ ar->sizex = new_sizex;
+ sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
+ }
- UI_block_end(C, block);
- }
+ UI_block_end(C, block);
+ }
- if (!region_layout_based) {
- maxco += UI_HEADER_OFFSET;
- }
+ if (!region_layout_based) {
+ maxco += UI_HEADER_OFFSET;
+ }
- /* always as last */
- UI_view2d_totRect_set(&ar->v2d, maxco, ar->winy);
+ /* always as last */
+ UI_view2d_totRect_set(&ar->v2d, maxco, ar->winy);
- /* restore view matrix */
- UI_view2d_view_restore(C);
+ /* restore view matrix */
+ UI_view2d_view_restore(C);
}
void ED_region_header_draw(const bContext *C, ARegion *ar)
{
- /* clear */
- region_clear_color(C, ar, region_background_color_id(C, ar));
+ /* clear */
+ region_clear_color(C, ar, region_background_color_id(C, ar));
- UI_view2d_view_ortho(&ar->v2d);
+ UI_view2d_view_ortho(&ar->v2d);
- /* View2D matrix might have changed due to dynamic sized regions. */
- UI_blocklist_update_window_matrix(C, &ar->uiblocks);
+ /* View2D matrix might have changed due to dynamic sized regions. */
+ UI_blocklist_update_window_matrix(C, &ar->uiblocks);
- /* draw blocks */
- UI_blocklist_draw(C, &ar->uiblocks);
+ /* draw blocks */
+ UI_blocklist_draw(C, &ar->uiblocks);
- /* restore view matrix */
- UI_view2d_view_restore(C);
+ /* restore view matrix */
+ UI_view2d_view_restore(C);
}
void ED_region_header(const bContext *C, ARegion *ar)
{
- /* TODO: remove? */
- ED_region_header_layout(C, ar);
- ED_region_header_draw(C, ar);
+ /* TODO: remove? */
+ ED_region_header_layout(C, ar);
+ ED_region_header_draw(C, ar);
}
void ED_region_header_init(ARegion *ar)
{
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
}
int ED_area_headersize(void)
{
- /* Accomodate widget and padding. */
- return U.widget_unit + (int)(UI_DPI_FAC * HEADER_PADDING_Y);
+ /* Accomodate widget and padding. */
+ return U.widget_unit + (int)(UI_DPI_FAC * HEADER_PADDING_Y);
}
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;
- }
- }
- return fallback;
+ for (ARegion *ar = area->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_HEADER) {
+ return ar->alignment;
+ }
+ }
+ return fallback;
}
int ED_area_header_alignment(const ScrArea *area)
{
- return ED_area_header_alignment_or_fallback(
- area, (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP);
+ return ED_area_header_alignment_or_fallback(
+ area, (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP);
}
int ED_area_footersize(void)
{
- return ED_area_headersize();
+ return ED_area_headersize();
}
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;
- }
- }
- return fallback;
+ for (ARegion *ar = area->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_FOOTER) {
+ return ar->alignment;
+ }
+ }
+ return fallback;
}
int ED_area_footer_alignment(const ScrArea *area)
{
- return ED_area_footer_alignment_or_fallback(
- area, (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_TOP : RGN_ALIGN_BOTTOM);
+ return ED_area_footer_alignment_or_fallback(
+ area, (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_TOP : RGN_ALIGN_BOTTOM);
}
/**
@@ -2581,51 +2617,51 @@ int ED_area_footer_alignment(const ScrArea *area)
*/
int ED_area_global_size_y(const ScrArea *area)
{
- BLI_assert(ED_area_is_global(area));
- return round_fl_to_int(area->global->cur_fixed_height * UI_DPI_FAC);
+ BLI_assert(ED_area_is_global(area));
+ return round_fl_to_int(area->global->cur_fixed_height * UI_DPI_FAC);
}
int ED_area_global_min_size_y(const ScrArea *area)
{
- BLI_assert(ED_area_is_global(area));
- return round_fl_to_int(area->global->size_min * UI_DPI_FAC);
+ BLI_assert(ED_area_is_global(area));
+ return round_fl_to_int(area->global->size_min * UI_DPI_FAC);
}
int ED_area_global_max_size_y(const ScrArea *area)
{
- BLI_assert(ED_area_is_global(area));
- return round_fl_to_int(area->global->size_max * UI_DPI_FAC);
+ BLI_assert(ED_area_is_global(area));
+ return round_fl_to_int(area->global->size_max * UI_DPI_FAC);
}
bool ED_area_is_global(const ScrArea *area)
{
- return area->global != NULL;
+ return area->global != NULL;
}
ScrArea *ED_screen_areas_iter_first(const wmWindow *win, const bScreen *screen)
{
- ScrArea *global_area = win->global_areas.areabase.first;
+ ScrArea *global_area = win->global_areas.areabase.first;
- if (!global_area) {
- return screen->areabase.first;
- }
- else if ((global_area->global->flag & GLOBAL_AREA_IS_HIDDEN) == 0) {
- return global_area;
- }
- /* Find next visible area. */
- return ED_screen_areas_iter_next(screen, global_area);
+ if (!global_area) {
+ return screen->areabase.first;
+ }
+ else if ((global_area->global->flag & GLOBAL_AREA_IS_HIDDEN) == 0) {
+ return global_area;
+ }
+ /* Find next visible area. */
+ return ED_screen_areas_iter_next(screen, global_area);
}
ScrArea *ED_screen_areas_iter_next(const bScreen *screen, const ScrArea *area)
{
- if (area->global) {
- for (ScrArea *area_iter = area->next; area_iter; area_iter = area_iter->next) {
- if ((area_iter->global->flag & GLOBAL_AREA_IS_HIDDEN) == 0) {
- return area_iter;
- }
- }
- /* No visible next global area found, start iterating over layout areas. */
- return screen->areabase.first;
- }
+ if (area->global) {
+ for (ScrArea *area_iter = area->next; area_iter; area_iter = area_iter->next) {
+ if ((area_iter->global->flag & GLOBAL_AREA_IS_HIDDEN) == 0) {
+ return area_iter;
+ }
+ }
+ /* No visible next global area found, start iterating over layout areas. */
+ return screen->areabase.first;
+ }
- return area->next;
+ return area->next;
}
/**
@@ -2636,646 +2672,654 @@ ScrArea *ED_screen_areas_iter_next(const bScreen *screen, const ScrArea *area)
*/
int ED_region_global_size_y(void)
{
- return ED_area_headersize(); /* same size as header */
-}
-
-void ED_region_info_draw_multiline(ARegion *ar, 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();
- int fontid = style->widget.uifont_id;
- int scissor[4];
- rcti rect;
- int num_lines = 0;
-
- /* background box */
- ED_region_visible_rect(ar, &rect);
-
- /* Box fill entire width or just around text. */
- if (!full_redraw) {
- const char **text = &text_array[0];
- while (*text) {
- rect.xmax = min_ii(rect.xmax, rect.xmin + BLF_width(fontid, *text, BLF_DRAW_STR_DUMMY_MAX) + 1.2f * U.widget_unit);
- text++;
- num_lines++;
- }
- }
- /* Just count the line number. */
- else {
- const char **text = &text_array[0];
- while (*text) {
- text++;
- num_lines++;
- }
- }
-
- rect.ymin = rect.ymax - header_height * num_lines;
-
- /* setup scissor */
- GPU_scissor_get_i(scissor);
- GPU_scissor(rect.xmin, rect.ymin,
- BLI_rcti_size_x(&rect) + 1, BLI_rcti_size_y(&rect) + 1);
-
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4fv(fill_color);
- immRecti(pos, rect.xmin, rect.ymin, rect.xmax + 1, rect.ymax + 1);
- immUnbindProgram();
- GPU_blend(false);
-
- /* text */
- UI_FontThemeColor(fontid, TH_TEXT_HI);
- BLF_clipping(fontid, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- BLF_enable(fontid, BLF_CLIPPING);
- int offset = num_lines - 1;
- {
- const char **text = &text_array[0];
- while (*text) {
- BLF_position(fontid, rect.xmin + 0.6f * U.widget_unit, rect.ymin + 0.3f * U.widget_unit + offset * header_height, 0.0f);
- BLF_draw(fontid, *text, BLF_DRAW_STR_DUMMY_MAX);
- text++;
- offset--;
- }
- }
-
- BLF_disable(fontid, BLF_CLIPPING);
-
- /* restore scissor as it was before */
- GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
-}
-
-void ED_region_info_draw(ARegion *ar, 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);
-}
-
-#define MAX_METADATA_STR 1024
-
-static const char *meta_data_list[] =
-{
- "File",
- "Strip",
- "Date",
- "RenderTime",
- "Note",
- "Marker",
- "Time",
- "Frame",
- "Camera",
- "Scene",
+ return ED_area_headersize(); /* same size as header */
+}
+
+void ED_region_info_draw_multiline(ARegion *ar,
+ 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();
+ int fontid = style->widget.uifont_id;
+ int scissor[4];
+ rcti rect;
+ int num_lines = 0;
+
+ /* background box */
+ ED_region_visible_rect(ar, &rect);
+
+ /* Box fill entire width or just around text. */
+ if (!full_redraw) {
+ const char **text = &text_array[0];
+ while (*text) {
+ rect.xmax = min_ii(rect.xmax,
+ rect.xmin + BLF_width(fontid, *text, BLF_DRAW_STR_DUMMY_MAX) +
+ 1.2f * U.widget_unit);
+ text++;
+ num_lines++;
+ }
+ }
+ /* Just count the line number. */
+ else {
+ const char **text = &text_array[0];
+ while (*text) {
+ text++;
+ num_lines++;
+ }
+ }
+
+ rect.ymin = rect.ymax - header_height * num_lines;
+
+ /* setup scissor */
+ GPU_scissor_get_i(scissor);
+ GPU_scissor(rect.xmin, rect.ymin, BLI_rcti_size_x(&rect) + 1, BLI_rcti_size_y(&rect) + 1);
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(fill_color);
+ immRecti(pos, rect.xmin, rect.ymin, rect.xmax + 1, rect.ymax + 1);
+ immUnbindProgram();
+ GPU_blend(false);
+
+ /* text */
+ UI_FontThemeColor(fontid, TH_TEXT_HI);
+ BLF_clipping(fontid, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ BLF_enable(fontid, BLF_CLIPPING);
+ int offset = num_lines - 1;
+ {
+ const char **text = &text_array[0];
+ while (*text) {
+ BLF_position(fontid,
+ rect.xmin + 0.6f * U.widget_unit,
+ rect.ymin + 0.3f * U.widget_unit + offset * header_height,
+ 0.0f);
+ BLF_draw(fontid, *text, BLF_DRAW_STR_DUMMY_MAX);
+ text++;
+ offset--;
+ }
+ }
+
+ BLF_disable(fontid, BLF_CLIPPING);
+
+ /* restore scissor as it was before */
+ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+}
+
+void ED_region_info_draw(ARegion *ar,
+ 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);
+}
+
+#define MAX_METADATA_STR 1024
+
+static const char *meta_data_list[] = {
+ "File",
+ "Strip",
+ "Date",
+ "RenderTime",
+ "Note",
+ "Marker",
+ "Time",
+ "Frame",
+ "Camera",
+ "Scene",
};
BLI_INLINE bool metadata_is_valid(ImBuf *ibuf, char *r_str, short index, int offset)
{
- return (IMB_metadata_get_field(ibuf->metadata, meta_data_list[index], r_str + offset, MAX_METADATA_STR - offset) && r_str[0]);
+ return (IMB_metadata_get_field(
+ ibuf->metadata, meta_data_list[index], r_str + offset, MAX_METADATA_STR - offset) &&
+ r_str[0]);
}
BLI_INLINE bool metadata_is_custom_drawable(const char *field)
{
- /* Metadata field stored by Blender for multilayer EXR images. Is rather
- * useless to be viewed all the time. Can still be seen in the Metadata
- * panel. */
- if (STREQ(field, "BlenderMultiChannel")) {
- return false;
- }
- /* Is almost always has value "scanlineimage", also useless to be seen
- * all the time. */
- if (STREQ(field, "type")) {
- return false;
- }
- return !BKE_stamp_is_known_field(field);
+ /* Metadata field stored by Blender for multilayer EXR images. Is rather
+ * useless to be viewed all the time. Can still be seen in the Metadata
+ * panel. */
+ if (STREQ(field, "BlenderMultiChannel")) {
+ return false;
+ }
+ /* Is almost always has value "scanlineimage", also useless to be seen
+ * all the time. */
+ if (STREQ(field, "type")) {
+ return false;
+ }
+ return !BKE_stamp_is_known_field(field);
}
typedef struct MetadataCustomDrawContext {
- int fontid;
- int xmin, ymin;
- int vertical_offset;
- int current_y;
+ int fontid;
+ int xmin, ymin;
+ int vertical_offset;
+ int current_y;
} MetadataCustomDrawContext;
-static void metadata_custom_draw_fields(
- const char *field,
- const char *value,
- void *ctx_v)
+static void metadata_custom_draw_fields(const char *field, const char *value, void *ctx_v)
{
- if (!metadata_is_custom_drawable(field)) {
- return;
- }
- MetadataCustomDrawContext *ctx = (MetadataCustomDrawContext *)ctx_v;
- char temp_str[MAX_METADATA_STR];
- BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: %s", field, value);
- BLF_position(ctx->fontid, ctx->xmin, ctx->ymin + ctx->current_y, 0.0f);
- BLF_draw(ctx->fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
- ctx->current_y += ctx->vertical_offset;
+ if (!metadata_is_custom_drawable(field)) {
+ return;
+ }
+ MetadataCustomDrawContext *ctx = (MetadataCustomDrawContext *)ctx_v;
+ char temp_str[MAX_METADATA_STR];
+ BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: %s", field, value);
+ BLF_position(ctx->fontid, ctx->xmin, ctx->ymin + ctx->current_y, 0.0f);
+ BLF_draw(ctx->fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ ctx->current_y += ctx->vertical_offset;
}
static void metadata_draw_imbuf(ImBuf *ibuf, const rctf *rect, int fontid, const bool is_top)
{
- char temp_str[MAX_METADATA_STR];
- int line_width;
- int ofs_y = 0;
- short i;
- int len;
- const float height = BLF_height_max(fontid);
- const float margin = height / 8;
- const float vertical_offset = (height + margin);
-
- /* values taking margins into account */
- const float descender = BLF_descender(fontid);
- const float xmin = (rect->xmin + margin);
- const float xmax = (rect->xmax - margin);
- const float ymin = (rect->ymin + margin) - descender;
- const float ymax = (rect->ymax - margin) - descender;
-
- if (is_top) {
- for (i = 0; i < 4; i++) {
- /* first line */
- if (i == 0) {
- bool do_newline = false;
- len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[0]);
- if (metadata_is_valid(ibuf, temp_str, 0, len)) {
- BLF_position(fontid, xmin, ymax - vertical_offset, 0.0f);
- BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
- do_newline = true;
- }
-
- len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[1]);
- if (metadata_is_valid(ibuf, temp_str, 1, len)) {
- line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
- BLF_position(fontid, xmax - line_width, ymax - vertical_offset, 0.0f);
- BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
- do_newline = true;
- }
-
- if (do_newline)
- ofs_y += vertical_offset;
- } /* Strip */
- else if (i == 1 || i == 2) {
- len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
- if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
- BLF_position(fontid, xmin, ymax - vertical_offset - ofs_y, 0.0f);
- BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
- ofs_y += vertical_offset;
- }
- } /* Note (wrapped) */
- else if (i == 3) {
- len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
- if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
- struct ResultBLF info;
- BLF_enable(fontid, BLF_WORD_WRAP);
- BLF_wordwrap(fontid, ibuf->x - (margin * 2));
- BLF_position(fontid, xmin, ymax - vertical_offset - ofs_y, 0.0f);
- BLF_draw_ex(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX, &info);
- BLF_wordwrap(fontid, 0);
- BLF_disable(fontid, BLF_WORD_WRAP);
- ofs_y += vertical_offset * info.lines;
- }
- }
- else {
- len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
- if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
- line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
- BLF_position(fontid, xmax - line_width, ymax - vertical_offset - ofs_y, 0.0f);
- BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
- ofs_y += vertical_offset;
- }
- }
- }
- }
- else {
- MetadataCustomDrawContext ctx;
- 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);
- int ofs_x = 0;
- ofs_y = ctx.current_y;
- for (i = 5; i < 10; i++) {
- len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i]);
- if (metadata_is_valid(ibuf, temp_str, i, len)) {
- BLF_position(fontid, xmin + ofs_x, ymin + ofs_y, 0.0f);
- BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
-
- ofs_x += BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX) + UI_UNIT_X;
- }
- }
- }
+ char temp_str[MAX_METADATA_STR];
+ int line_width;
+ int ofs_y = 0;
+ short i;
+ int len;
+ const float height = BLF_height_max(fontid);
+ const float margin = height / 8;
+ const float vertical_offset = (height + margin);
+
+ /* values taking margins into account */
+ const float descender = BLF_descender(fontid);
+ const float xmin = (rect->xmin + margin);
+ const float xmax = (rect->xmax - margin);
+ const float ymin = (rect->ymin + margin) - descender;
+ const float ymax = (rect->ymax - margin) - descender;
+
+ if (is_top) {
+ for (i = 0; i < 4; i++) {
+ /* first line */
+ if (i == 0) {
+ bool do_newline = false;
+ len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[0]);
+ if (metadata_is_valid(ibuf, temp_str, 0, len)) {
+ BLF_position(fontid, xmin, ymax - vertical_offset, 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ do_newline = true;
+ }
+
+ len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[1]);
+ if (metadata_is_valid(ibuf, temp_str, 1, len)) {
+ line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_position(fontid, xmax - line_width, ymax - vertical_offset, 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ do_newline = true;
+ }
+
+ if (do_newline)
+ ofs_y += vertical_offset;
+ } /* Strip */
+ else if (i == 1 || i == 2) {
+ len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
+ if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
+ BLF_position(fontid, xmin, ymax - vertical_offset - ofs_y, 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ ofs_y += vertical_offset;
+ }
+ } /* Note (wrapped) */
+ else if (i == 3) {
+ len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
+ if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
+ struct ResultBLF info;
+ BLF_enable(fontid, BLF_WORD_WRAP);
+ BLF_wordwrap(fontid, ibuf->x - (margin * 2));
+ BLF_position(fontid, xmin, ymax - vertical_offset - ofs_y, 0.0f);
+ BLF_draw_ex(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX, &info);
+ BLF_wordwrap(fontid, 0);
+ BLF_disable(fontid, BLF_WORD_WRAP);
+ ofs_y += vertical_offset * info.lines;
+ }
+ }
+ else {
+ len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
+ if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
+ line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_position(fontid, xmax - line_width, ymax - vertical_offset - ofs_y, 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ ofs_y += vertical_offset;
+ }
+ }
+ }
+ }
+ else {
+ MetadataCustomDrawContext ctx;
+ 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);
+ int ofs_x = 0;
+ ofs_y = ctx.current_y;
+ for (i = 5; i < 10; i++) {
+ len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i]);
+ if (metadata_is_valid(ibuf, temp_str, i, len)) {
+ BLF_position(fontid, xmin + ofs_x, ymin + ofs_y, 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+
+ ofs_x += BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX) + UI_UNIT_X;
+ }
+ }
+ }
}
typedef struct MetadataCustomCountContext {
- int count;
+ int count;
} MetadataCustomCountContext;
-static void metadata_custom_count_fields(
- const char *field,
- const char *UNUSED(value),
- void *ctx_v)
+static void metadata_custom_count_fields(const char *field, const char *UNUSED(value), void *ctx_v)
{
- if (!metadata_is_custom_drawable(field)) {
- return;
- }
- MetadataCustomCountContext *ctx = (MetadataCustomCountContext *)ctx_v;
- ctx->count++;
+ if (!metadata_is_custom_drawable(field)) {
+ return;
+ }
+ MetadataCustomCountContext *ctx = (MetadataCustomCountContext *)ctx_v;
+ ctx->count++;
}
-
static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top)
{
- const float height = BLF_height_max(fontid);
- const float margin = (height / 8);
- char str[MAX_METADATA_STR] = "";
- short i, count = 0;
-
- if (is_top) {
- if (metadata_is_valid(ibuf, str, 0, 0) || metadata_is_valid(ibuf, str, 1, 0)) {
- count++;
- }
- for (i = 2; i < 5; i++) {
- if (metadata_is_valid(ibuf, str, i, 0)) {
- if (i == 4) {
- struct {
- struct ResultBLF info;
- rctf rect;
- } wrap;
-
- BLF_enable(fontid, BLF_WORD_WRAP);
- BLF_wordwrap(fontid, ibuf->x - (margin * 2));
- BLF_boundbox_ex(fontid, str, sizeof(str), &wrap.rect, &wrap.info);
- BLF_wordwrap(fontid, 0);
- BLF_disable(fontid, BLF_WORD_WRAP);
-
- count += wrap.info.lines;
- }
- else {
- count++;
- }
- }
- }
- }
- else {
- for (i = 5; i < 10; i++) {
- if (metadata_is_valid(ibuf, str, i, 0)) {
- count = 1;
- break;
- }
- }
- MetadataCustomCountContext ctx;
- ctx.count = 0;
- IMB_metadata_foreach(ibuf, metadata_custom_count_fields, &ctx);
- count += ctx.count;
- }
-
- if (count) {
- return (height + margin) * count;
- }
-
- return 0;
+ const float height = BLF_height_max(fontid);
+ const float margin = (height / 8);
+ char str[MAX_METADATA_STR] = "";
+ short i, count = 0;
+
+ if (is_top) {
+ if (metadata_is_valid(ibuf, str, 0, 0) || metadata_is_valid(ibuf, str, 1, 0)) {
+ count++;
+ }
+ for (i = 2; i < 5; i++) {
+ if (metadata_is_valid(ibuf, str, i, 0)) {
+ if (i == 4) {
+ struct {
+ struct ResultBLF info;
+ rctf rect;
+ } wrap;
+
+ BLF_enable(fontid, BLF_WORD_WRAP);
+ BLF_wordwrap(fontid, ibuf->x - (margin * 2));
+ BLF_boundbox_ex(fontid, str, sizeof(str), &wrap.rect, &wrap.info);
+ BLF_wordwrap(fontid, 0);
+ BLF_disable(fontid, BLF_WORD_WRAP);
+
+ count += wrap.info.lines;
+ }
+ else {
+ count++;
+ }
+ }
+ }
+ }
+ else {
+ for (i = 5; i < 10; i++) {
+ if (metadata_is_valid(ibuf, str, i, 0)) {
+ count = 1;
+ break;
+ }
+ }
+ MetadataCustomCountContext ctx;
+ ctx.count = 0;
+ IMB_metadata_foreach(ibuf, metadata_custom_count_fields, &ctx);
+ count += ctx.count;
+ }
+
+ if (count) {
+ return (height + margin) * count;
+ }
+
+ return 0;
}
#undef MAX_METADATA_STR
-void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame, float zoomx, float zoomy)
+void ED_region_image_metadata_draw(
+ int x, int y, ImBuf *ibuf, const rctf *frame, float zoomx, float zoomy)
{
- float box_y;
- rctf rect;
- uiStyle *style = UI_style_get_dpi();
-
- if (!ibuf->metadata)
- return;
+ float box_y;
+ rctf rect;
+ uiStyle *style = UI_style_get_dpi();
- /* find window pixel coordinates of origin */
- GPU_matrix_push();
+ if (!ibuf->metadata)
+ return;
- /* offset and zoom using ogl */
- GPU_matrix_translate_2f(x, y);
- GPU_matrix_scale_2f(zoomx, zoomy);
+ /* find window pixel coordinates of origin */
+ GPU_matrix_push();
- BLF_size(blf_mono_font, style->widgetlabel.points * 1.5f * U.pixelsize, U.dpi);
+ /* offset and zoom using ogl */
+ GPU_matrix_translate_2f(x, y);
+ GPU_matrix_scale_2f(zoomx, zoomy);
- /* *** upper box*** */
+ BLF_size(blf_mono_font, style->widgetlabel.points * 1.5f * U.pixelsize, U.dpi);
- /* get needed box height */
- box_y = metadata_box_height_get(ibuf, blf_mono_font, true);
+ /* *** upper box*** */
- if (box_y) {
- /* set up rect */
- BLI_rctf_init(&rect, frame->xmin, frame->xmax, frame->ymax, frame->ymax + box_y);
- /* draw top box */
- 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_METADATA_BG);
- immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- immUnbindProgram();
+ /* get needed box height */
+ box_y = metadata_box_height_get(ibuf, blf_mono_font, true);
- BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- BLF_enable(blf_mono_font, BLF_CLIPPING);
+ if (box_y) {
+ /* set up rect */
+ BLI_rctf_init(&rect, frame->xmin, frame->xmax, frame->ymax, frame->ymax + box_y);
+ /* draw top box */
+ 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_METADATA_BG);
+ immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ immUnbindProgram();
- UI_FontThemeColor(blf_mono_font, TH_METADATA_TEXT);
- metadata_draw_imbuf(ibuf, &rect, blf_mono_font, true);
+ BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ BLF_enable(blf_mono_font, BLF_CLIPPING);
- BLF_disable(blf_mono_font, BLF_CLIPPING);
- }
+ UI_FontThemeColor(blf_mono_font, TH_METADATA_TEXT);
+ metadata_draw_imbuf(ibuf, &rect, blf_mono_font, true);
+ BLF_disable(blf_mono_font, BLF_CLIPPING);
+ }
- /* *** lower box*** */
+ /* *** lower box*** */
- box_y = metadata_box_height_get(ibuf, blf_mono_font, false);
+ box_y = metadata_box_height_get(ibuf, blf_mono_font, false);
- if (box_y) {
- /* set up box rect */
- BLI_rctf_init(&rect, frame->xmin, frame->xmax, frame->ymin - box_y, frame->ymin);
- /* draw top box */
- 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_METADATA_BG);
- immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- immUnbindProgram();
+ if (box_y) {
+ /* set up box rect */
+ BLI_rctf_init(&rect, frame->xmin, frame->xmax, frame->ymin - box_y, frame->ymin);
+ /* draw top box */
+ 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_METADATA_BG);
+ immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ immUnbindProgram();
- BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- BLF_enable(blf_mono_font, BLF_CLIPPING);
+ BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ BLF_enable(blf_mono_font, BLF_CLIPPING);
- UI_FontThemeColor(blf_mono_font, TH_METADATA_TEXT);
- metadata_draw_imbuf(ibuf, &rect, blf_mono_font, false);
+ UI_FontThemeColor(blf_mono_font, TH_METADATA_TEXT);
+ metadata_draw_imbuf(ibuf, &rect, blf_mono_font, false);
- BLF_disable(blf_mono_font, BLF_CLIPPING);
- }
+ BLF_disable(blf_mono_font, BLF_CLIPPING);
+ }
- GPU_matrix_pop();
+ GPU_matrix_pop();
}
typedef struct MetadataPanelDrawContext {
- uiLayout *layout;
+ uiLayout *layout;
} MetadataPanelDrawContext;
-static void metadata_panel_draw_field(
- const char *field,
- const char *value,
- void *ctx_v)
+static void metadata_panel_draw_field(const char *field, const char *value, void *ctx_v)
{
- MetadataPanelDrawContext *ctx = (MetadataPanelDrawContext *)ctx_v;
- uiLayout *row = uiLayoutRow(ctx->layout, false);
- uiItemL(row, field, ICON_NONE);
- uiItemL(row, value, ICON_NONE);
+ MetadataPanelDrawContext *ctx = (MetadataPanelDrawContext *)ctx_v;
+ uiLayout *row = uiLayoutRow(ctx->layout, false);
+ uiItemL(row, field, ICON_NONE);
+ uiItemL(row, value, ICON_NONE);
}
void ED_region_image_metadata_panel_draw(ImBuf *ibuf, uiLayout *layout)
{
- MetadataPanelDrawContext ctx;
- ctx.layout = layout;
- IMB_metadata_foreach(ibuf, metadata_panel_draw_field, &ctx);
+ MetadataPanelDrawContext ctx;
+ ctx.layout = layout;
+ IMB_metadata_foreach(ibuf, metadata_panel_draw_field, &ctx);
}
void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
{
- float gridsize, gridstep = 1.0f / 32.0f;
- float fac, blendfac;
- int x1, y1, x2, y2;
-
- /* the image is located inside (0, 0), (1, 1) as set by view2d */
- UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x1, &y1);
- UI_view2d_view_to_region(&ar->v2d, 1.0f, 1.0f, &x2, &y2);
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColorShade(TH_BACK, 20);
- immRectf(pos, x1, y1, x2, y2);
- immUnbindProgram();
-
- /* gridsize adapted to zoom level */
- gridsize = 0.5f * (zoomx + zoomy);
- if (gridsize <= 0.0f)
- return;
-
- if (gridsize < 1.0f) {
- while (gridsize < 1.0f) {
- gridsize *= 4.0f;
- gridstep *= 4.0f;
- }
- }
- else {
- while (gridsize >= 4.0f) {
- gridsize /= 4.0f;
- gridstep /= 4.0f;
- }
- }
-
- blendfac = 0.25f * gridsize - floorf(0.25f * gridsize);
- CLAMP(blendfac, 0.0f, 1.0f);
-
- int count_fine = 1.0f / gridstep;
- int count_large = 1.0f / (4.0f * gridstep);
-
- 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);
-
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- immBegin(GPU_PRIM_LINES, 4 * count_fine + 4 * count_large);
-
- float theme_color[3];
- UI_GetThemeColorShade3fv(TH_BACK, (int)(20.0f * (1.0f - blendfac)), theme_color);
- fac = 0.0f;
-
- /* the fine resolution level */
- for (int i = 0; i < count_fine; i++) {
- immAttr3fv(color, theme_color);
- immVertex2f(pos, x1, y1 * (1.0f - fac) + y2 * fac);
- immAttr3fv(color, theme_color);
- immVertex2f(pos, x2, y1 * (1.0f - fac) + y2 * fac);
- immAttr3fv(color, theme_color);
- immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y1);
- immAttr3fv(color, theme_color);
- immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y2);
- fac += gridstep;
- }
-
- if (count_large > 0) {
- UI_GetThemeColor3fv(TH_BACK, theme_color);
- fac = 0.0f;
-
- /* the large resolution level */
- for (int i = 0; i < count_large; i++) {
- immAttr3fv(color, theme_color);
- immVertex2f(pos, x1, y1 * (1.0f - fac) + y2 * fac);
- immAttr3fv(color, theme_color);
- immVertex2f(pos, x2, y1 * (1.0f - fac) + y2 * fac);
- immAttr3fv(color, theme_color);
- immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y1);
- immAttr3fv(color, theme_color);
- immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y2);
- fac += 4.0f * gridstep;
- }
- }
-
- immEnd();
- immUnbindProgram();
- }
+ float gridsize, gridstep = 1.0f / 32.0f;
+ float fac, blendfac;
+ int x1, y1, x2, y2;
+
+ /* the image is located inside (0, 0), (1, 1) as set by view2d */
+ UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x1, &y1);
+ UI_view2d_view_to_region(&ar->v2d, 1.0f, 1.0f, &x2, &y2);
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShade(TH_BACK, 20);
+ immRectf(pos, x1, y1, x2, y2);
+ immUnbindProgram();
+
+ /* gridsize adapted to zoom level */
+ gridsize = 0.5f * (zoomx + zoomy);
+ if (gridsize <= 0.0f)
+ return;
+
+ if (gridsize < 1.0f) {
+ while (gridsize < 1.0f) {
+ gridsize *= 4.0f;
+ gridstep *= 4.0f;
+ }
+ }
+ else {
+ while (gridsize >= 4.0f) {
+ gridsize /= 4.0f;
+ gridstep /= 4.0f;
+ }
+ }
+
+ blendfac = 0.25f * gridsize - floorf(0.25f * gridsize);
+ CLAMP(blendfac, 0.0f, 1.0f);
+
+ int count_fine = 1.0f / gridstep;
+ int count_large = 1.0f / (4.0f * gridstep);
+
+ 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);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GPU_PRIM_LINES, 4 * count_fine + 4 * count_large);
+
+ float theme_color[3];
+ UI_GetThemeColorShade3fv(TH_BACK, (int)(20.0f * (1.0f - blendfac)), theme_color);
+ fac = 0.0f;
+
+ /* the fine resolution level */
+ for (int i = 0; i < count_fine; i++) {
+ immAttr3fv(color, theme_color);
+ immVertex2f(pos, x1, y1 * (1.0f - fac) + y2 * fac);
+ immAttr3fv(color, theme_color);
+ immVertex2f(pos, x2, y1 * (1.0f - fac) + y2 * fac);
+ immAttr3fv(color, theme_color);
+ immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y1);
+ immAttr3fv(color, theme_color);
+ immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y2);
+ fac += gridstep;
+ }
+
+ if (count_large > 0) {
+ UI_GetThemeColor3fv(TH_BACK, theme_color);
+ fac = 0.0f;
+
+ /* the large resolution level */
+ for (int i = 0; i < count_large; i++) {
+ immAttr3fv(color, theme_color);
+ immVertex2f(pos, x1, y1 * (1.0f - fac) + y2 * fac);
+ immAttr3fv(color, theme_color);
+ immVertex2f(pos, x2, y1 * (1.0f - fac) + y2 * fac);
+ immAttr3fv(color, theme_color);
+ immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y1);
+ immAttr3fv(color, theme_color);
+ immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y2);
+ fac += 4.0f * gridstep;
+ }
+ }
+
+ immEnd();
+ immUnbindProgram();
+ }
}
/* If the area has overlapping regions, it returns visible rect for Region *ar */
/* rect gets returned in local region coordinates */
void ED_region_visible_rect(ARegion *ar, rcti *rect)
{
- ARegion *arn = ar;
-
- /* allow function to be called without area */
- while (arn->prev)
- arn = arn->prev;
-
- *rect = ar->winrct;
-
- /* check if a region overlaps with the current one */
- for (; arn; arn = arn->next) {
- if (ar != arn && arn->overlap) {
- if (BLI_rcti_isect(rect, &arn->winrct, NULL)) {
- if (ELEM(arn->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) {
- rect->xmin = arn->winrct.xmax;
- }
-
- /* Overlap right. */
- if (ABS(rect->xmax - arn->winrct.xmax) < 2) {
- rect->xmax = arn->winrct.xmin;
- }
- }
- else if (ELEM(arn->alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
- /* Same logic as above for vertical regions. */
- if (ABS(rect->ymin - arn->winrct.ymin) < 2) {
- rect->ymin = arn->winrct.ymax;
- }
- if (ABS(rect->ymax - arn->winrct.ymax) < 2) {
- rect->ymax = arn->winrct.ymin;
- }
- }
- else if (arn->alignment == RGN_ALIGN_FLOAT) {
- /* Skip floating. */
- }
- else {
- BLI_assert(!"Region overlap with unknown alignment");
- }
- }
- }
- }
- BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->winrct.ymin);
+ ARegion *arn = ar;
+
+ /* allow function to be called without area */
+ while (arn->prev)
+ arn = arn->prev;
+
+ *rect = ar->winrct;
+
+ /* check if a region overlaps with the current one */
+ for (; arn; arn = arn->next) {
+ if (ar != arn && arn->overlap) {
+ if (BLI_rcti_isect(rect, &arn->winrct, NULL)) {
+ if (ELEM(arn->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) {
+ rect->xmin = arn->winrct.xmax;
+ }
+
+ /* Overlap right. */
+ if (ABS(rect->xmax - arn->winrct.xmax) < 2) {
+ rect->xmax = arn->winrct.xmin;
+ }
+ }
+ else if (ELEM(arn->alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
+ /* Same logic as above for vertical regions. */
+ if (ABS(rect->ymin - arn->winrct.ymin) < 2) {
+ rect->ymin = arn->winrct.ymax;
+ }
+ if (ABS(rect->ymax - arn->winrct.ymax) < 2) {
+ rect->ymax = arn->winrct.ymin;
+ }
+ }
+ else if (arn->alignment == RGN_ALIGN_FLOAT) {
+ /* Skip floating. */
+ }
+ else {
+ BLI_assert(!"Region overlap with unknown alignment");
+ }
+ }
+ }
+ }
+ BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->winrct.ymin);
}
/* Cache display helpers */
void ED_region_cache_draw_background(const ARegion *ar)
{
- 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, 0, ar->winx, 8 * UI_DPI_FAC);
- immUnbindProgram();
+ 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, 0, ar->winx, 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();
- int fontid = style->widget.uifont_id;
- char numstr[32];
- float font_dims[2] = {0.0f, 0.0f};
+ uiStyle *style = UI_style_get();
+ int fontid = style->widget.uifont_id;
+ char numstr[32];
+ float font_dims[2] = {0.0f, 0.0f};
- /* frame number */
- BLF_size(fontid, 11.0f * U.pixelsize, U.dpi);
- BLI_snprintf(numstr, sizeof(numstr), "%d", framenr);
+ /* frame number */
+ BLF_size(fontid, 11.0f * U.pixelsize, U.dpi);
+ BLI_snprintf(numstr, sizeof(numstr), "%d", framenr);
- BLF_width_and_height(fontid, numstr, sizeof(numstr), &font_dims[0], &font_dims[1]);
+ BLF_width_and_height(fontid, numstr, sizeof(numstr), &font_dims[0], &font_dims[1]);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor(TH_CFRAME);
- immRecti(pos, x, y, x + font_dims[0] + 6.0f, y + font_dims[1] + 4.0f);
- immUnbindProgram();
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_CFRAME);
+ immRecti(pos, x, y, x + font_dims[0] + 6.0f, y + font_dims[1] + 4.0f);
+ immUnbindProgram();
- UI_FontThemeColor(fontid, TH_TEXT);
- BLF_position(fontid, x + 2.0f, y + 2.0f, 0.0f);
- BLF_draw(fontid, numstr, sizeof(numstr));
+ UI_FontThemeColor(fontid, TH_TEXT);
+ BLF_position(fontid, x + 2.0f, y + 2.0f, 0.0f);
+ BLF_draw(fontid, numstr, sizeof(numstr));
}
-void ED_region_cache_draw_cached_segments(const ARegion *ar, const int num_segments, const int *points, const int sfra, const int efra)
+void ED_region_cache_draw_cached_segments(
+ const ARegion *ar, const int num_segments, const int *points, const int sfra, const int efra)
{
- if (num_segments) {
- 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, 128);
+ if (num_segments) {
+ 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, 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;
+ 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;
- immRecti(pos, x1, 0, x2, 8 * UI_DPI_FAC);
- /* TODO(merwin): use primitive restart to draw multiple rects more efficiently */
- }
+ immRecti(pos, x1, 0, x2, 8 * UI_DPI_FAC);
+ /* TODO(merwin): use primitive restart to draw multiple rects more efficiently */
+ }
- immUnbindProgram();
- }
+ immUnbindProgram();
+ }
}
/**
* Generate subscriptions for this region.
*/
-void ED_region_message_subscribe(
- bContext *C,
- struct WorkSpace *workspace, struct Scene *scene,
- struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar,
- struct wmMsgBus *mbus)
+void ED_region_message_subscribe(bContext *C,
+ struct WorkSpace *workspace,
+ struct Scene *scene,
+ struct bScreen *screen,
+ struct ScrArea *sa,
+ struct ARegion *ar,
+ struct wmMsgBus *mbus)
{
- if (ar->gizmo_map != NULL) {
- WM_gizmomap_message_subscribe(C, ar->gizmo_map, ar, mbus);
- }
+ if (ar->gizmo_map != NULL) {
+ WM_gizmomap_message_subscribe(C, ar->gizmo_map, ar, mbus);
+ }
- if (!BLI_listbase_is_empty(&ar->uiblocks)) {
- UI_region_message_subscribe(ar, mbus);
- }
+ if (!BLI_listbase_is_empty(&ar->uiblocks)) {
+ UI_region_message_subscribe(ar, mbus);
+ }
- if (ar->type->message_subscribe != NULL) {
- ar->type->message_subscribe(C, workspace, scene, screen, sa, ar, mbus);
- }
+ if (ar->type->message_subscribe != NULL) {
+ ar->type->message_subscribe(C, workspace, scene, screen, sa, ar, mbus);
+ }
}
int ED_region_snap_size_test(const ARegion *ar)
{
- /* 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));
- }
- return 0;
+ /* 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));
+ }
+ return 0;
}
bool ED_region_snap_size_apply(ARegion *ar, int snap_flag)
{
- bool changed = false;
- if (ar->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;
- 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;
- changed = true;
- }
- }
- }
- return changed;
+ bool changed = false;
+ if (ar->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;
+ 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;
+ changed = true;
+ }
+ }
+ }
+ return changed;
}
diff --git a/source/blender/editors/screen/area_utils.c b/source/blender/editors/screen/area_utils.c
index 2137d98d226..1a99210b73d 100644
--- a/source/blender/editors/screen/area_utils.c
+++ b/source/blender/editors/screen/area_utils.c
@@ -42,18 +42,20 @@
/**
* Callback for #ARegionType.message_subscribe
*/
-void ED_region_generic_tools_region_message_subscribe(
- const struct bContext *UNUSED(C),
- struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene),
- struct bScreen *UNUSED(screen), struct ScrArea *UNUSED(sa), struct ARegion *ar,
- struct wmMsgBus *mbus)
+void ED_region_generic_tools_region_message_subscribe(const struct bContext *UNUSED(C),
+ struct WorkSpace *UNUSED(workspace),
+ struct Scene *UNUSED(scene),
+ struct bScreen *UNUSED(screen),
+ struct ScrArea *UNUSED(sa),
+ struct ARegion *ar,
+ struct wmMsgBus *mbus)
{
- wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
- .notify = ED_region_do_msg_notify_tag_redraw,
- };
- WM_msg_subscribe_rna_anon_prop(mbus, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+ WM_msg_subscribe_rna_anon_prop(mbus, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
}
/**
@@ -61,23 +63,23 @@ void ED_region_generic_tools_region_message_subscribe(
*/
int ED_region_generic_tools_region_snap_size(const ARegion *ar, int size, int axis)
{
- if (axis == 0) {
- /* Note, this depends on the icon size: see #ICON_DEFAULT_HEIGHT_TOOLBAR. */
- const float snap_units[] = {2 + 0.8f, 4 + 0.8f};
- const float aspect = BLI_rctf_size_x(&ar->v2d.cur) / (BLI_rcti_size_x(&ar->v2d.mask) + 1);
- int best_diff = INT_MAX;
- int best_size = size;
- for (uint i = 0; i < ARRAY_SIZE(snap_units); i += 1) {
- const int test_size = (snap_units[i] * U.widget_unit) / (UI_DPI_FAC * aspect);
- const int test_diff = ABS(test_size - size);
- if (test_diff < best_diff) {
- best_size = test_size;
- best_diff = test_diff;
- }
- }
- return best_size;
- }
- return size;
+ if (axis == 0) {
+ /* Note, this depends on the icon size: see #ICON_DEFAULT_HEIGHT_TOOLBAR. */
+ const float snap_units[] = {2 + 0.8f, 4 + 0.8f};
+ const float aspect = BLI_rctf_size_x(&ar->v2d.cur) / (BLI_rcti_size_x(&ar->v2d.mask) + 1);
+ int best_diff = INT_MAX;
+ int best_size = size;
+ for (uint i = 0; i < ARRAY_SIZE(snap_units); i += 1) {
+ const int test_size = (snap_units[i] * U.widget_unit) / (UI_DPI_FAC * aspect);
+ const int test_diff = ABS(test_size - size);
+ if (test_diff < best_diff) {
+ best_size = test_size;
+ best_diff = test_diff;
+ }
+ }
+ return best_size;
+ }
+ return size;
}
/** \} */
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 1606a159e38..7fec62157c1 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -21,7 +21,6 @@
* \ingroup edscr
*/
-
#include <stdio.h>
#include <string.h>
@@ -50,75 +49,76 @@
/* Invert line handling */
-#define GL_TOGGLE(mode, onoff) (((onoff) ? glEnable : glDisable)(mode))
+#define GL_TOGGLE(mode, onoff) (((onoff) ? glEnable : glDisable)(mode))
void set_inverted_drawing(int enable)
{
- glLogicOp(enable ? GL_INVERT : GL_COPY);
- GL_TOGGLE(GL_COLOR_LOGIC_OP, enable);
- GL_TOGGLE(GL_DITHER, !enable);
+ glLogicOp(enable ? GL_INVERT : GL_COPY);
+ GL_TOGGLE(GL_COLOR_LOGIC_OP, enable);
+ GL_TOGGLE(GL_DITHER, !enable);
}
float glaGetOneFloat(int param)
{
- GLfloat v;
- glGetFloatv(param, &v);
- return v;
+ GLfloat v;
+ glGetFloatv(param, &v);
+ return v;
}
int glaGetOneInt(int param)
{
- GLint v;
- glGetIntegerv(param, &v);
- return v;
+ GLint v;
+ glGetIntegerv(param, &v);
+ return v;
}
void glaRasterPosSafe2f(float x, float y, float known_good_x, float known_good_y)
{
- GLubyte dummy = 0;
-
- /* As long as known good coordinates are correct
- * this is guaranteed to generate an ok raster
- * position (ignoring potential (real) overflow
- * issues).
- */
- glRasterPos2f(known_good_x, known_good_y);
-
- /* Now shift the raster position to where we wanted
- * it in the first place using the glBitmap trick.
- */
- glBitmap(0, 0, 0, 0, x - known_good_x, y - known_good_y, &dummy);
+ GLubyte dummy = 0;
+
+ /* As long as known good coordinates are correct
+ * this is guaranteed to generate an ok raster
+ * position (ignoring potential (real) overflow
+ * issues).
+ */
+ glRasterPos2f(known_good_x, known_good_y);
+
+ /* Now shift the raster position to where we wanted
+ * it in the first place using the glBitmap trick.
+ */
+ glBitmap(0, 0, 0, 0, x - known_good_x, y - known_good_y, &dummy);
}
static int get_cached_work_texture(int *r_w, int *r_h)
{
- static GLint texid = -1;
- static int tex_w = 256;
- static int tex_h = 256;
+ static GLint texid = -1;
+ static int tex_w = 256;
+ static int tex_h = 256;
- if (texid == -1) {
- glGenTextures(1, (GLuint *)&texid);
+ if (texid == -1) {
+ glGenTextures(1, (GLuint *)&texid);
- glBindTexture(GL_TEXTURE_2D, texid);
+ glBindTexture(GL_TEXTURE_2D, texid);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- glBindTexture(GL_TEXTURE_2D, 0);
- }
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
- *r_w = tex_w;
- *r_h = tex_h;
- return texid;
+ *r_w = tex_w;
+ *r_h = tex_h;
+ return texid;
}
static void immDrawPixelsTexSetupAttributes(IMMDrawPixelsTexState *state)
{
- GPUVertFormat *vert_format = immVertexFormat();
- state->pos = GPU_vertformat_attr_add(vert_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- state->texco = GPU_vertformat_attr_add(vert_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPUVertFormat *vert_format = immVertexFormat();
+ state->pos = GPU_vertformat_attr_add(vert_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ state->texco = GPU_vertformat_attr_add(
+ vert_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
/* To be used before calling immDrawPixelsTex
@@ -128,17 +128,17 @@ static void immDrawPixelsTexSetupAttributes(IMMDrawPixelsTexState *state)
* */
IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin)
{
- IMMDrawPixelsTexState state;
- immDrawPixelsTexSetupAttributes(&state);
+ IMMDrawPixelsTexState state;
+ immDrawPixelsTexSetupAttributes(&state);
- state.shader = GPU_shader_get_builtin_shader(builtin);
+ state.shader = GPU_shader_get_builtin_shader(builtin);
- /* Shader will be unbind by immUnbindProgram in immDrawPixelsTexScaled_clipping */
- immBindBuiltinProgram(builtin);
- immUniform1i("image", 0);
- state.do_shader_unbind = true;
+ /* Shader will be unbind by immUnbindProgram in immDrawPixelsTexScaled_clipping */
+ immBindBuiltinProgram(builtin);
+ immUniform1i("image", 0);
+ state.do_shader_unbind = true;
- return state;
+ return state;
}
/* Use the currently bound shader.
@@ -155,210 +155,381 @@ IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin)
* it's finished.
* */
void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state,
- float x, float y, int img_w, int img_h,
- int format, int type, int zoomfilter, void *rect,
- float scaleX, float scaleY,
- float clip_min_x, float clip_min_y,
- float clip_max_x, float clip_max_y,
- float xzoom, float yzoom, float color[4])
+ float x,
+ float y,
+ int img_w,
+ int img_h,
+ int format,
+ int type,
+ int zoomfilter,
+ void *rect,
+ float scaleX,
+ float scaleY,
+ float clip_min_x,
+ float clip_min_y,
+ float clip_max_x,
+ float clip_max_y,
+ float xzoom,
+ float yzoom,
+ float color[4])
{
- unsigned char *uc_rect = (unsigned char *) 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;
- int texid = get_cached_work_texture(&tex_w, &tex_h);
- int components;
- const bool use_clipping = ((clip_min_x < clip_max_x) && (clip_min_y < clip_max_y));
- float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
-
- GLint unpack_row_length;
- glGetIntegerv(GL_UNPACK_ROW_LENGTH, &unpack_row_length);
-
- glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, texid);
-
- /* don't want nasty border artifacts */
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, zoomfilter);
-
- /* setup seamless 2=on, 0=off */
- seamless = ((tex_w < img_w || tex_h < img_h) && tex_w > 2 && tex_h > 2) ? 2 : 0;
-
- offset_x = tex_w - seamless;
- offset_y = tex_h - seamless;
-
- nsubparts_x = (img_w + (offset_x - 1)) / (offset_x);
- nsubparts_y = (img_h + (offset_y - 1)) / (offset_y);
-
- if (format == GL_RGBA)
- components = 4;
- else if (format == GL_RGB)
- components = 3;
- else if (format == GL_RED)
- components = 1;
- else {
- BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled");
- return;
- }
-
- if (type == GL_FLOAT) {
- /* need to set internal format to higher range float */
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, tex_w, tex_h, 0, format, GL_FLOAT, NULL);
- }
- else {
- /* switch to 8bit RGBA for byte buffer */
- 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;
-
- /* optional */
- /* NOTE: Shader could be null for GLSL OCIO drawing, it is fine, since
- * it does not need color.
- */
- if (state->shader != NULL && GPU_shader_get_uniform_ensure(state->shader, "color") != -1) {
- immUniformColor4fv((color) ? color : white);
- }
-
- for (subpart_y = 0; subpart_y < nsubparts_y; subpart_y++) {
- for (subpart_x = 0; subpart_x < nsubparts_x; subpart_x++) {
- int remainder_x = img_w - subpart_x * offset_x;
- int remainder_y = img_h - subpart_y * offset_y;
- int subpart_w = (remainder_x < tex_w) ? remainder_x : tex_w;
- int subpart_h = (remainder_y < tex_h) ? remainder_y : tex_h;
- int offset_left = (seamless && subpart_x != 0) ? 1 : 0;
- int offset_bot = (seamless && subpart_y != 0) ? 1 : 0;
- int offset_right = (seamless && remainder_x > tex_w) ? 1 : 0;
- int offset_top = (seamless && remainder_y > tex_h) ? 1 : 0;
- float rast_x = x + subpart_x * offset_x * xzoom;
- float rast_y = y + subpart_y * offset_y * yzoom;
- /* check if we already got these because we always get 2 more when doing seamless */
- if (subpart_w <= seamless || subpart_h <= seamless)
- continue;
-
- if (use_clipping) {
- if (rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX < clip_min_x ||
- rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY < clip_min_y)
- {
- continue;
- }
- if (rast_x + (float)offset_left * xzoom > clip_max_x ||
- rast_y + (float)offset_bot * yzoom > clip_max_y)
- {
- continue;
- }
- }
-
- if (type == GL_FLOAT) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[((size_t)subpart_y) * offset_y * img_w * components + subpart_x * offset_x * components]);
-
- /* add an extra border of pixels so linear looks ok at edges of full image */
- if (subpart_w < tex_w)
- glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[((size_t)subpart_y) * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
- if (subpart_h < tex_h)
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_FLOAT, &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]);
- if (subpart_w < tex_w && subpart_h < tex_h)
- glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_FLOAT, &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
- }
- else {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[((size_t)subpart_y) * offset_y * img_w * components + subpart_x * offset_x * components]);
-
- if (subpart_w < tex_w)
- glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[((size_t)subpart_y) * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
- if (subpart_h < tex_h)
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]);
- if (subpart_w < tex_w && subpart_h < tex_h)
- glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
- }
-
- immBegin(GPU_PRIM_TRI_FAN, 4);
- immAttr2f(texco, (float)(0 + offset_left) / tex_w, (float)(0 + offset_bot) / tex_h);
- immVertex2f(pos, rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * yzoom);
-
- immAttr2f(texco, (float)(subpart_w - offset_right) / tex_w, (float)(0 + offset_bot) / tex_h);
- immVertex2f(pos, rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)offset_bot * yzoom);
-
- immAttr2f(texco, (float)(subpart_w - offset_right) / tex_w, (float)(subpart_h - offset_top) / tex_h);
- immVertex2f(pos, rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
-
- immAttr2f(texco, (float)(0 + offset_left) / tex_w, (float)(subpart_h - offset_top) / tex_h);
- immVertex2f(pos, rast_x + (float)offset_left * xzoom, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
- immEnd();
-
- /* NOTE: Weirdly enough this is only required on macOS. Without this there is some sort of
- * bleeding of data is happening from tiles which are drawn later on.
- * This doesn't seem to be too slow, but still would be nice to have fast and nice solution. */
+ unsigned char *uc_rect = (unsigned char *)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;
+ int texid = get_cached_work_texture(&tex_w, &tex_h);
+ int components;
+ const bool use_clipping = ((clip_min_x < clip_max_x) && (clip_min_y < clip_max_y));
+ float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+
+ GLint unpack_row_length;
+ glGetIntegerv(GL_UNPACK_ROW_LENGTH, &unpack_row_length);
+
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, texid);
+
+ /* don't want nasty border artifacts */
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, zoomfilter);
+
+ /* setup seamless 2=on, 0=off */
+ seamless = ((tex_w < img_w || tex_h < img_h) && tex_w > 2 && tex_h > 2) ? 2 : 0;
+
+ offset_x = tex_w - seamless;
+ offset_y = tex_h - seamless;
+
+ nsubparts_x = (img_w + (offset_x - 1)) / (offset_x);
+ nsubparts_y = (img_h + (offset_y - 1)) / (offset_y);
+
+ if (format == GL_RGBA)
+ components = 4;
+ else if (format == GL_RGB)
+ components = 3;
+ else if (format == GL_RED)
+ components = 1;
+ else {
+ BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled");
+ return;
+ }
+
+ if (type == GL_FLOAT) {
+ /* need to set internal format to higher range float */
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, tex_w, tex_h, 0, format, GL_FLOAT, NULL);
+ }
+ else {
+ /* switch to 8bit RGBA for byte buffer */
+ 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;
+
+ /* optional */
+ /* NOTE: Shader could be null for GLSL OCIO drawing, it is fine, since
+ * it does not need color.
+ */
+ if (state->shader != NULL && GPU_shader_get_uniform_ensure(state->shader, "color") != -1) {
+ immUniformColor4fv((color) ? color : white);
+ }
+
+ for (subpart_y = 0; subpart_y < nsubparts_y; subpart_y++) {
+ for (subpart_x = 0; subpart_x < nsubparts_x; subpart_x++) {
+ int remainder_x = img_w - subpart_x * offset_x;
+ int remainder_y = img_h - subpart_y * offset_y;
+ int subpart_w = (remainder_x < tex_w) ? remainder_x : tex_w;
+ int subpart_h = (remainder_y < tex_h) ? remainder_y : tex_h;
+ int offset_left = (seamless && subpart_x != 0) ? 1 : 0;
+ int offset_bot = (seamless && subpart_y != 0) ? 1 : 0;
+ int offset_right = (seamless && remainder_x > tex_w) ? 1 : 0;
+ int offset_top = (seamless && remainder_y > tex_h) ? 1 : 0;
+ float rast_x = x + subpart_x * offset_x * xzoom;
+ float rast_y = y + subpart_y * offset_y * yzoom;
+ /* check if we already got these because we always get 2 more when doing seamless */
+ if (subpart_w <= seamless || subpart_h <= seamless)
+ continue;
+
+ if (use_clipping) {
+ if (rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX < clip_min_x ||
+ rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY < clip_min_y) {
+ continue;
+ }
+ if (rast_x + (float)offset_left * xzoom > clip_max_x ||
+ rast_y + (float)offset_bot * yzoom > clip_max_y) {
+ continue;
+ }
+ }
+
+ if (type == GL_FLOAT) {
+ glTexSubImage2D(GL_TEXTURE_2D,
+ 0,
+ 0,
+ 0,
+ subpart_w,
+ subpart_h,
+ format,
+ GL_FLOAT,
+ &f_rect[((size_t)subpart_y) * offset_y * img_w * components +
+ subpart_x * offset_x * components]);
+
+ /* add an extra border of pixels so linear looks ok at edges of full image */
+ if (subpart_w < tex_w)
+ glTexSubImage2D(GL_TEXTURE_2D,
+ 0,
+ subpart_w,
+ 0,
+ 1,
+ subpart_h,
+ format,
+ GL_FLOAT,
+ &f_rect[((size_t)subpart_y) * offset_y * img_w * components +
+ (subpart_x * offset_x + subpart_w - 1) * components]);
+ if (subpart_h < tex_h)
+ glTexSubImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ 0,
+ subpart_h,
+ subpart_w,
+ 1,
+ format,
+ GL_FLOAT,
+ &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components +
+ subpart_x * offset_x * components]);
+ if (subpart_w < tex_w && subpart_h < tex_h)
+ glTexSubImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ subpart_w,
+ subpart_h,
+ 1,
+ 1,
+ format,
+ GL_FLOAT,
+ &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components +
+ (subpart_x * offset_x + subpart_w - 1) * components]);
+ }
+ else {
+ glTexSubImage2D(GL_TEXTURE_2D,
+ 0,
+ 0,
+ 0,
+ subpart_w,
+ subpart_h,
+ format,
+ GL_UNSIGNED_BYTE,
+ &uc_rect[((size_t)subpart_y) * offset_y * img_w * components +
+ subpart_x * offset_x * components]);
+
+ if (subpart_w < tex_w)
+ glTexSubImage2D(GL_TEXTURE_2D,
+ 0,
+ subpart_w,
+ 0,
+ 1,
+ subpart_h,
+ format,
+ GL_UNSIGNED_BYTE,
+ &uc_rect[((size_t)subpart_y) * offset_y * img_w * components +
+ (subpart_x * offset_x + subpart_w - 1) * components]);
+ if (subpart_h < tex_h)
+ glTexSubImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ 0,
+ subpart_h,
+ subpart_w,
+ 1,
+ format,
+ GL_UNSIGNED_BYTE,
+ &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components +
+ subpart_x * offset_x * components]);
+ if (subpart_w < tex_w && subpart_h < tex_h)
+ glTexSubImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ subpart_w,
+ subpart_h,
+ 1,
+ 1,
+ format,
+ GL_UNSIGNED_BYTE,
+ &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components +
+ (subpart_x * offset_x + subpart_w - 1) * components]);
+ }
+
+ immBegin(GPU_PRIM_TRI_FAN, 4);
+ immAttr2f(texco, (float)(0 + offset_left) / tex_w, (float)(0 + offset_bot) / tex_h);
+ immVertex2f(pos, rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * yzoom);
+
+ immAttr2f(texco, (float)(subpart_w - offset_right) / tex_w, (float)(0 + offset_bot) / tex_h);
+ immVertex2f(pos,
+ rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX,
+ rast_y + (float)offset_bot * yzoom);
+
+ immAttr2f(texco,
+ (float)(subpart_w - offset_right) / tex_w,
+ (float)(subpart_h - offset_top) / tex_h);
+ immVertex2f(pos,
+ rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX,
+ rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
+
+ immAttr2f(texco, (float)(0 + offset_left) / tex_w, (float)(subpart_h - offset_top) / tex_h);
+ immVertex2f(pos,
+ rast_x + (float)offset_left * xzoom,
+ rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
+ immEnd();
+
+ /* NOTE: Weirdly enough this is only required on macOS. Without this there is some sort of
+ * bleeding of data is happening from tiles which are drawn later on.
+ * This doesn't seem to be too slow, but still would be nice to have fast and nice solution. */
#ifdef __APPLE__
- GPU_flush();
+ GPU_flush();
#endif
- }
- }
+ }
+ }
- if (state->do_shader_unbind) {
- immUnbindProgram();
- }
+ if (state->do_shader_unbind) {
+ immUnbindProgram();
+ }
- glBindTexture(GL_TEXTURE_2D, 0);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, unpack_row_length);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, unpack_row_length);
}
void immDrawPixelsTexScaled(IMMDrawPixelsTexState *state,
- float x, float y, int img_w, int img_h,
- int format, int type, int zoomfilter, void *rect,
- float scaleX, float scaleY, float xzoom, float yzoom, float color[4])
+ float x,
+ float y,
+ int img_w,
+ int img_h,
+ int format,
+ int type,
+ int zoomfilter,
+ void *rect,
+ float scaleX,
+ float scaleY,
+ float xzoom,
+ float yzoom,
+ float color[4])
{
- immDrawPixelsTexScaled_clipping(state, x, y, img_w, img_h, format, type, zoomfilter, rect,
- scaleX, scaleY, 0.0f, 0.0f, 0.0f, 0.0f, xzoom, yzoom, color);
+ immDrawPixelsTexScaled_clipping(state,
+ x,
+ y,
+ img_w,
+ img_h,
+ format,
+ type,
+ zoomfilter,
+ rect,
+ scaleX,
+ scaleY,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ xzoom,
+ yzoom,
+ color);
}
void immDrawPixelsTex(IMMDrawPixelsTexState *state,
- float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect,
- float xzoom, float yzoom, float color[4])
+ float x,
+ float y,
+ int img_w,
+ int img_h,
+ int format,
+ int type,
+ int zoomfilter,
+ void *rect,
+ float xzoom,
+ float yzoom,
+ float color[4])
{
- immDrawPixelsTexScaled_clipping(state, x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, xzoom, yzoom, color);
+ immDrawPixelsTexScaled_clipping(state,
+ x,
+ y,
+ img_w,
+ img_h,
+ format,
+ type,
+ zoomfilter,
+ rect,
+ 1.0f,
+ 1.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ xzoom,
+ yzoom,
+ color);
}
void immDrawPixelsTex_clipping(IMMDrawPixelsTexState *state,
- float x, float y, int img_w, int img_h,
- int format, int type, int zoomfilter, void *rect,
- float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y,
- float xzoom, float yzoom, float color[4])
+ float x,
+ float y,
+ int img_w,
+ int img_h,
+ int format,
+ int type,
+ int zoomfilter,
+ void *rect,
+ float clip_min_x,
+ float clip_min_y,
+ float clip_max_x,
+ float clip_max_y,
+ float xzoom,
+ float yzoom,
+ float color[4])
{
- immDrawPixelsTexScaled_clipping(state, x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f,
- clip_min_x, clip_min_y, clip_max_x, clip_max_y, xzoom, yzoom, color);
+ immDrawPixelsTexScaled_clipping(state,
+ x,
+ y,
+ img_w,
+ img_h,
+ format,
+ type,
+ zoomfilter,
+ rect,
+ 1.0f,
+ 1.0f,
+ clip_min_x,
+ clip_min_y,
+ clip_max_x,
+ clip_max_y,
+ xzoom,
+ yzoom,
+ color);
}
/* *************** glPolygonOffset hack ************* */
float bglPolygonOffsetCalc(const float winmat[16], float viewdist, float dist)
{
- if (winmat[15] > 0.5f) {
+ if (winmat[15] > 0.5f) {
#if 1
- return 0.00001f * dist * viewdist; // ortho tweaking
+ return 0.00001f * dist * viewdist; // ortho tweaking
#else
- static float depth_fac = 0.0f;
- if (depth_fac == 0.0f) {
- int depthbits;
- glGetIntegerv(GL_DEPTH_BITS, &depthbits);
- depth_fac = 1.0f / (float)((1 << depthbits) - 1);
- }
- offs = (-1.0 / winmat[10]) * dist * depth_fac;
-
- UNUSED_VARS(viewdist);
+ static float depth_fac = 0.0f;
+ if (depth_fac == 0.0f) {
+ int depthbits;
+ glGetIntegerv(GL_DEPTH_BITS, &depthbits);
+ depth_fac = 1.0f / (float)((1 << depthbits) - 1);
+ }
+ offs = (-1.0 / winmat[10]) * dist * depth_fac;
+
+ UNUSED_VARS(viewdist);
#endif
- }
- else {
- /* This adjustment effectively results in reducing the Z value by 0.25%.
- *
- * winmat[14] actually evaluates to `-2 * far * near / (far - near)`,
- * is very close to -0.2 with default clip range, and is used as the coefficient multiplied by `w / z`,
- * thus controlling the z dependent part of the depth value.
- */
- return winmat[14] * -0.0025f * dist;
- }
+ }
+ else {
+ /* This adjustment effectively results in reducing the Z value by 0.25%.
+ *
+ * winmat[14] actually evaluates to `-2 * far * near / (far - near)`,
+ * is very close to -0.2 with default clip range, and is used as the coefficient multiplied by `w / z`,
+ * thus controlling the z dependent part of the depth value.
+ */
+ return winmat[14] * -0.0025f * dist;
+ }
}
/**
@@ -366,201 +537,267 @@ float bglPolygonOffsetCalc(const float winmat[16], float viewdist, float dist)
*/
void bglPolygonOffset(float viewdist, float dist)
{
- static float winmat[16], offset = 0.0f;
+ static float winmat[16], offset = 0.0f;
- if (dist != 0.0f) {
- // glEnable(GL_POLYGON_OFFSET_FILL);
- // glPolygonOffset(-1.0, -1.0);
+ if (dist != 0.0f) {
+ // glEnable(GL_POLYGON_OFFSET_FILL);
+ // glPolygonOffset(-1.0, -1.0);
- /* hack below is to mimic polygon offset */
- GPU_matrix_projection_get(winmat);
+ /* hack below is to mimic polygon offset */
+ GPU_matrix_projection_get(winmat);
- /* dist is from camera to center point */
+ /* dist is from camera to center point */
- float offs = bglPolygonOffsetCalc(winmat, viewdist, dist);
+ float offs = bglPolygonOffsetCalc(winmat, viewdist, dist);
- winmat[14] -= offs;
- offset += offs;
- }
- else {
- winmat[14] += offset;
- offset = 0.0;
- }
+ winmat[14] -= offs;
+ offset += offs;
+ }
+ else {
+ winmat[14] += offset;
+ offset = 0.0;
+ }
- GPU_matrix_projection_set(winmat);
+ GPU_matrix_projection_set(winmat);
}
/* **** Color management helper functions for GLSL display/transform ***** */
/* Draw given image buffer on a screen using GLSL for display transform */
-void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter,
+void glaDrawImBuf_glsl_clipping(ImBuf *ibuf,
+ float x,
+ float y,
+ int zoomfilter,
ColorManagedViewSettings *view_settings,
ColorManagedDisplaySettings *display_settings,
- float clip_min_x, float clip_min_y,
- float clip_max_x, float clip_max_y,
- float zoom_x, float zoom_y)
+ float clip_min_x,
+ float clip_min_y,
+ float clip_max_x,
+ float clip_max_y,
+ float zoom_x,
+ float zoom_y)
{
- bool force_fallback = false;
- bool need_fallback = true;
-
- /* Early out */
- if (ibuf->rect == NULL && ibuf->rect_float == NULL)
- return;
-
- /* Single channel images could not be transformed using GLSL yet */
- force_fallback |= ibuf->channels == 1;
-
- /* If user decided not to use GLSL, fallback to glaDrawPixelsAuto */
- force_fallback |= (U.image_draw_method != IMAGE_DRAW_METHOD_GLSL);
-
- /* Try to draw buffer using GLSL display transform */
- if (force_fallback == false) {
- int ok;
-
- IMMDrawPixelsTexState state = {0};
- /* We want GLSL state to be fully handled by OCIO. */
- state.do_shader_unbind = false;
- immDrawPixelsTexSetupAttributes(&state);
-
- 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);
- }
- else {
- ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings,
- ibuf->dither, true);
- }
- }
- else {
- ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings,
- ibuf->rect_colorspace,
- ibuf->dither, false);
- }
-
- if (ok) {
- if (ibuf->rect_float) {
- int format = 0;
-
- if (ibuf->channels == 3)
- format = GL_RGB;
- else if (ibuf->channels == 4)
- format = GL_RGBA;
- else
- BLI_assert(!"Incompatible number of channels for GLSL display");
-
- if (format != 0) {
- immDrawPixelsTex_clipping(&state,
- x, y, ibuf->x, ibuf->y, format, GL_FLOAT,
- zoomfilter, ibuf->rect_float,
- clip_min_x, clip_min_y, clip_max_x, clip_max_y,
- zoom_x, zoom_y, NULL);
- }
- }
- else if (ibuf->rect) {
- /* ibuf->rect is always RGBA */
- immDrawPixelsTex_clipping(&state,
- x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
- zoomfilter, ibuf->rect,
- clip_min_x, clip_min_y, clip_max_x, clip_max_y,
- zoom_x, zoom_y, NULL);
- }
-
- IMB_colormanagement_finish_glsl_draw();
-
- need_fallback = false;
- }
- }
-
- /* In case GLSL failed or not usable, fallback to glaDrawPixelsAuto */
- if (need_fallback) {
- unsigned char *display_buffer;
- void *cache_handle;
-
- display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, display_settings, &cache_handle);
-
- if (display_buffer) {
- IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
- immDrawPixelsTex_clipping(&state,
- x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
- zoomfilter, display_buffer,
- clip_min_x, clip_min_y, clip_max_x, clip_max_y,
- zoom_x, zoom_y, NULL);
- }
-
- IMB_display_buffer_release(cache_handle);
- }
+ bool force_fallback = false;
+ bool need_fallback = true;
+
+ /* Early out */
+ if (ibuf->rect == NULL && ibuf->rect_float == NULL)
+ return;
+
+ /* Single channel images could not be transformed using GLSL yet */
+ force_fallback |= ibuf->channels == 1;
+
+ /* If user decided not to use GLSL, fallback to glaDrawPixelsAuto */
+ force_fallback |= (U.image_draw_method != IMAGE_DRAW_METHOD_GLSL);
+
+ /* Try to draw buffer using GLSL display transform */
+ if (force_fallback == false) {
+ int ok;
+
+ IMMDrawPixelsTexState state = {0};
+ /* We want GLSL state to be fully handled by OCIO. */
+ state.do_shader_unbind = false;
+ immDrawPixelsTexSetupAttributes(&state);
+
+ 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);
+ }
+ else {
+ ok = IMB_colormanagement_setup_glsl_draw(
+ view_settings, display_settings, ibuf->dither, true);
+ }
+ }
+ else {
+ ok = IMB_colormanagement_setup_glsl_draw_from_space(
+ view_settings, display_settings, ibuf->rect_colorspace, ibuf->dither, false);
+ }
+
+ if (ok) {
+ if (ibuf->rect_float) {
+ int format = 0;
+
+ if (ibuf->channels == 3)
+ format = GL_RGB;
+ else if (ibuf->channels == 4)
+ format = GL_RGBA;
+ else
+ BLI_assert(!"Incompatible number of channels for GLSL display");
+
+ if (format != 0) {
+ immDrawPixelsTex_clipping(&state,
+ x,
+ y,
+ ibuf->x,
+ ibuf->y,
+ format,
+ GL_FLOAT,
+ zoomfilter,
+ ibuf->rect_float,
+ clip_min_x,
+ clip_min_y,
+ clip_max_x,
+ clip_max_y,
+ zoom_x,
+ zoom_y,
+ NULL);
+ }
+ }
+ else if (ibuf->rect) {
+ /* ibuf->rect is always RGBA */
+ immDrawPixelsTex_clipping(&state,
+ x,
+ y,
+ ibuf->x,
+ ibuf->y,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ zoomfilter,
+ ibuf->rect,
+ clip_min_x,
+ clip_min_y,
+ clip_max_x,
+ clip_max_y,
+ zoom_x,
+ zoom_y,
+ NULL);
+ }
+
+ IMB_colormanagement_finish_glsl_draw();
+
+ need_fallback = false;
+ }
+ }
+
+ /* In case GLSL failed or not usable, fallback to glaDrawPixelsAuto */
+ if (need_fallback) {
+ unsigned char *display_buffer;
+ void *cache_handle;
+
+ display_buffer = IMB_display_buffer_acquire(
+ ibuf, view_settings, display_settings, &cache_handle);
+
+ if (display_buffer) {
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex_clipping(&state,
+ x,
+ y,
+ ibuf->x,
+ ibuf->y,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ zoomfilter,
+ display_buffer,
+ clip_min_x,
+ clip_min_y,
+ clip_max_x,
+ clip_max_y,
+ zoom_x,
+ zoom_y,
+ NULL);
+ }
+
+ IMB_display_buffer_release(cache_handle);
+ }
}
-void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter,
+void glaDrawImBuf_glsl(ImBuf *ibuf,
+ float x,
+ float y,
+ int zoomfilter,
ColorManagedViewSettings *view_settings,
ColorManagedDisplaySettings *display_settings,
- float zoom_x, float zoom_y)
+ float zoom_x,
+ float zoom_y)
{
- glaDrawImBuf_glsl_clipping(ibuf, x, y, zoomfilter, view_settings, display_settings,
- 0.0f, 0.0f, 0.0f, 0.0f, zoom_x, zoom_y);
+ glaDrawImBuf_glsl_clipping(ibuf,
+ x,
+ y,
+ zoomfilter,
+ view_settings,
+ display_settings,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ zoom_x,
+ zoom_y);
}
void glaDrawImBuf_glsl_ctx_clipping(const bContext *C,
ImBuf *ibuf,
- float x, float y,
+ float x,
+ float y,
int zoomfilter,
- float clip_min_x, float clip_min_y,
- float clip_max_x, float clip_max_y,
- float zoom_x, float zoom_y)
+ float clip_min_x,
+ float clip_min_y,
+ float clip_max_x,
+ float clip_max_y,
+ float zoom_x,
+ float zoom_y)
{
- ColorManagedViewSettings *view_settings;
- ColorManagedDisplaySettings *display_settings;
-
- IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings);
-
- glaDrawImBuf_glsl_clipping(ibuf, x, y, zoomfilter, view_settings, display_settings,
- clip_min_x, clip_min_y, clip_max_x, clip_max_y,
- zoom_x, zoom_y);
+ ColorManagedViewSettings *view_settings;
+ ColorManagedDisplaySettings *display_settings;
+
+ IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings);
+
+ glaDrawImBuf_glsl_clipping(ibuf,
+ x,
+ y,
+ zoomfilter,
+ view_settings,
+ display_settings,
+ clip_min_x,
+ clip_min_y,
+ clip_max_x,
+ clip_max_y,
+ zoom_x,
+ zoom_y);
}
-void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int zoomfilter,
- float zoom_x, float zoom_y)
+void glaDrawImBuf_glsl_ctx(
+ const bContext *C, ImBuf *ibuf, float x, float y, int zoomfilter, float zoom_x, float zoom_y)
{
- glaDrawImBuf_glsl_ctx_clipping(C, ibuf, x, y, zoomfilter, 0.0f, 0.0f, 0.0f, 0.0f, zoom_x, zoom_y);
+ glaDrawImBuf_glsl_ctx_clipping(
+ C, ibuf, x, y, zoomfilter, 0.0f, 0.0f, 0.0f, 0.0f, zoom_x, zoom_y);
}
/* 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)
{
- float delta_x = 4.0f * UI_DPI_FAC / zoomx;
- float delta_y = 4.0f * UI_DPI_FAC / zoomy;
-
- delta_x = min_ff(delta_x, border->xmax - border->xmin);
- delta_y = min_ff(delta_y, border->ymax - border->ymin);
-
- /* left bottom corner */
- immBegin(GPU_PRIM_LINE_STRIP, 3);
- immVertex2f(pos, border->xmin, border->ymin + delta_y);
- immVertex2f(pos, border->xmin, border->ymin);
- immVertex2f(pos, border->xmin + delta_x, border->ymin);
- immEnd();
-
- /* left top corner */
- immBegin(GPU_PRIM_LINE_STRIP, 3);
- immVertex2f(pos, border->xmin, border->ymax - delta_y);
- immVertex2f(pos, border->xmin, border->ymax);
- immVertex2f(pos, border->xmin + delta_x, border->ymax);
- immEnd();
-
- /* right bottom corner */
- immBegin(GPU_PRIM_LINE_STRIP, 3);
- immVertex2f(pos, border->xmax - delta_x, border->ymin);
- immVertex2f(pos, border->xmax, border->ymin);
- immVertex2f(pos, border->xmax, border->ymin + delta_y);
- immEnd();
-
- /* right top corner */
- immBegin(GPU_PRIM_LINE_STRIP, 3);
- immVertex2f(pos, border->xmax - delta_x, border->ymax);
- immVertex2f(pos, border->xmax, border->ymax);
- immVertex2f(pos, border->xmax, border->ymax - delta_y);
- immEnd();
+ float delta_x = 4.0f * UI_DPI_FAC / zoomx;
+ float delta_y = 4.0f * UI_DPI_FAC / zoomy;
+
+ delta_x = min_ff(delta_x, border->xmax - border->xmin);
+ delta_y = min_ff(delta_y, border->ymax - border->ymin);
+
+ /* left bottom corner */
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
+ immVertex2f(pos, border->xmin, border->ymin + delta_y);
+ immVertex2f(pos, border->xmin, border->ymin);
+ immVertex2f(pos, border->xmin + delta_x, border->ymin);
+ immEnd();
+
+ /* left top corner */
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
+ immVertex2f(pos, border->xmin, border->ymax - delta_y);
+ immVertex2f(pos, border->xmin, border->ymax);
+ immVertex2f(pos, border->xmin + delta_x, border->ymax);
+ immEnd();
+
+ /* right bottom corner */
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
+ immVertex2f(pos, border->xmax - delta_x, border->ymin);
+ immVertex2f(pos, border->xmax, border->ymin);
+ immVertex2f(pos, border->xmax, border->ymin + delta_y);
+ immEnd();
+
+ /* right top corner */
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
+ immVertex2f(pos, border->xmax - delta_x, border->ymax);
+ immVertex2f(pos, border->xmax, border->ymax);
+ immVertex2f(pos, border->xmax, border->ymax - delta_y);
+ immEnd();
}
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index b16d7f68976..719403531ff 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -65,636 +65,680 @@
#include "screen_intern.h"
-const char *screen_context_dir[] = {
- "scene", "view_layer", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases",
- "selected_objects", "selected_bases",
- "editable_objects", "editable_bases",
- "selected_editable_objects", "selected_editable_bases",
- "objects_in_mode", "objects_in_mode_unique_data",
- "visible_bones", "editable_bones", "selected_bones", "selected_editable_bones",
- "visible_pose_bones", "selected_pose_bones", "selected_pose_bones_from_active_object",
- "active_bone", "active_pose_bone",
- "active_base", "active_object", "object", "edit_object",
- "sculpt_object", "vertex_paint_object", "weight_paint_object",
- "image_paint_object", "particle_edit_object", "uv_sculpt_object", "pose_object",
- "sequences", "selected_sequences", "selected_editable_sequences", /* sequencer */
- "gpencil_data", "gpencil_data_owner", /* grease pencil data */
- "visible_gpencil_layers", "editable_gpencil_layers", "editable_gpencil_strokes",
- "active_gpencil_layer", "active_gpencil_frame",
- "active_operator", "selected_editable_fcurves",
- NULL};
+const char *screen_context_dir[] = {"scene",
+ "view_layer",
+ "visible_objects",
+ "visible_bases",
+ "selectable_objects",
+ "selectable_bases",
+ "selected_objects",
+ "selected_bases",
+ "editable_objects",
+ "editable_bases",
+ "selected_editable_objects",
+ "selected_editable_bases",
+ "objects_in_mode",
+ "objects_in_mode_unique_data",
+ "visible_bones",
+ "editable_bones",
+ "selected_bones",
+ "selected_editable_bones",
+ "visible_pose_bones",
+ "selected_pose_bones",
+ "selected_pose_bones_from_active_object",
+ "active_bone",
+ "active_pose_bone",
+ "active_base",
+ "active_object",
+ "object",
+ "edit_object",
+ "sculpt_object",
+ "vertex_paint_object",
+ "weight_paint_object",
+ "image_paint_object",
+ "particle_edit_object",
+ "uv_sculpt_object",
+ "pose_object",
+ "sequences",
+ "selected_sequences",
+ "selected_editable_sequences", /* sequencer */
+ "gpencil_data",
+ "gpencil_data_owner", /* grease pencil data */
+ "visible_gpencil_layers",
+ "editable_gpencil_layers",
+ "editable_gpencil_strokes",
+ "active_gpencil_layer",
+ "active_gpencil_frame",
+ "active_operator",
+ "selected_editable_fcurves",
+ NULL};
int ed_screen_context(const bContext *C, const char *member, bContextDataResult *result)
{
- 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);
- Scene *scene = WM_window_get_active_scene(win);
- ViewLayer *view_layer = WM_window_get_active_view_layer(win);
- Object *obact = (view_layer && view_layer->basact) ? view_layer->basact->object : NULL;
- Object *obedit = view_layer ? OBEDIT_FROM_VIEW_LAYER(view_layer) : NULL;
-
- if (CTX_data_dir(member)) {
- CTX_data_dir_set(result, screen_context_dir);
- return 1;
- }
- else if (CTX_data_equals(member, "scene")) {
- CTX_data_id_pointer_set(result, &scene->id);
- return 1;
- }
- else if (CTX_data_equals(member, "visible_objects")) {
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (BASE_VISIBLE(v3d, base)) {
- CTX_data_id_list_add(result, &base->object->id);
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "selectable_objects")) {
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (BASE_SELECTABLE(v3d, base)) {
- CTX_data_id_list_add(result, &base->object->id);
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "selected_objects")) {
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (BASE_SELECTED(v3d, base)) {
- CTX_data_id_list_add(result, &base->object->id);
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "selected_editable_objects")) {
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (BASE_SELECTED_EDITABLE(v3d, base)) {
- CTX_data_id_list_add(result, &base->object->id);
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- 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) {
- if (BASE_EDITABLE(v3d, base)) {
- CTX_data_id_list_add(result, &base->object->id);
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if ( CTX_data_equals(member, "visible_bases")) {
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (BASE_VISIBLE(v3d, base)) {
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "selectable_bases")) {
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (BASE_SELECTABLE(v3d, base)) {
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "selected_bases")) {
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (BASE_SELECTED(v3d, base)) {
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "selected_editable_bases")) {
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (BASE_SELECTED_EDITABLE(v3d, base)) {
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "editable_bases")) {
- /* Visible + Editable, but not necessarily selected */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (BASE_EDITABLE(v3d, base)) {
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "objects_in_mode")) {
- if (obact && (obact->mode != OB_MODE_OBJECT)) {
- FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) {
- CTX_data_id_list_add(result, &ob_iter->id);
- } FOREACH_OBJECT_IN_MODE_END;
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "objects_in_mode_unique_data")) {
- if (obact && (obact->mode != OB_MODE_OBJECT)) {
- FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) {
- ob_iter->id.tag |= LIB_TAG_DOIT;
- } FOREACH_OBJECT_IN_MODE_END;
- FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) {
- if (ob_iter->id.tag & LIB_TAG_DOIT) {
- ob_iter->id.tag &= ~LIB_TAG_DOIT;
- CTX_data_id_list_add(result, &ob_iter->id);
- }
- } FOREACH_OBJECT_IN_MODE_END;
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "visible_bones") || CTX_data_equals(member, "editable_bones")) {
- bArmature *arm = (obedit && obedit->type == OB_ARMATURE) ? obedit->data : NULL;
- EditBone *ebone, *flipbone = NULL;
- const bool editable_bones = CTX_data_equals(member, "editable_bones");
-
- if (arm && arm->edbo) {
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint i = 0; i < objects_len; i++) {
- Object *ob = objects[i];
- arm = ob->data;
-
- /* Attention: X-Axis Mirroring is also handled here... */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- /* first and foremost, bone must be visible and selected */
- if (EBONE_VISIBLE(arm, ebone)) {
- /* Get 'x-axis mirror equivalent' bone if the X-Axis Mirroring option is enabled
- * so that most users of this data don't need to explicitly check for it themselves.
- *
- * We need to make sure that these mirrored copies are not selected, otherwise some
- * bones will be operated on twice.
- */
- if (arm->flag & ARM_MIRROR_EDIT)
- flipbone = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
-
- /* if we're filtering for editable too, use the check for that instead,
- * as it has selection check too */
- if (editable_bones) {
- /* only selected + editable */
- if (EBONE_EDITABLE(ebone)) {
- CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
-
- if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
- CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
- }
- }
- else {
- /* only include bones if visible */
- CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
-
- if ((flipbone) && EBONE_VISIBLE(arm, flipbone) == 0)
- CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
- }
- }
- }
- }
- MEM_freeN(objects);
-
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "selected_bones") || CTX_data_equals(member, "selected_editable_bones")) {
- bArmature *arm = (obedit && obedit->type == OB_ARMATURE) ? obedit->data : NULL;
- EditBone *ebone, *flipbone = NULL;
- const bool selected_editable_bones = CTX_data_equals(member, "selected_editable_bones");
-
- if (arm && arm->edbo) {
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint i = 0; i < objects_len; i++) {
- Object *ob = objects[i];
- arm = ob->data;
-
- /* Attention: X-Axis Mirroring is also handled here... */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- /* first and foremost, bone must be visible and selected */
- if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_SELECTED)) {
- /* Get 'x-axis mirror equivalent' bone if the X-Axis Mirroring option is enabled
- * so that most users of this data don't need to explicitly check for it themselves.
- *
- * We need to make sure that these mirrored copies are not selected, otherwise some
- * bones will be operated on twice.
- */
- if (arm->flag & ARM_MIRROR_EDIT)
- flipbone = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
-
- /* if we're filtering for editable too, use the check for that instead,
- * as it has selection check too */
- if (selected_editable_bones) {
- /* only selected + editable */
- if (EBONE_EDITABLE(ebone)) {
- CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
-
- if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
- CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
- }
- }
- else {
- /* only include bones if selected */
- CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
-
- if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
- CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
- }
- }
- }
- }
- MEM_freeN(objects);
-
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "visible_pose_bones")) {
- Object *obpose = BKE_object_pose_armature_get(obact);
- if (obpose && obpose->pose && obpose->data) {
- if (obpose != obact) {
- FOREACH_PCHAN_VISIBLE_IN_OBJECT_BEGIN (obpose, pchan) {
- CTX_data_list_add(result, &obpose->id, &RNA_PoseBone, pchan);
- } FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
- }
- else if (obact->mode & OB_MODE_POSE) {
- FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) {
- FOREACH_PCHAN_VISIBLE_IN_OBJECT_BEGIN (ob_iter, pchan) {
- CTX_data_list_add(result, &ob_iter->id, &RNA_PoseBone, pchan);
- } FOREACH_PCHAN_VISIBLE_IN_OBJECT_END;
- } FOREACH_OBJECT_IN_MODE_END;
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "selected_pose_bones")) {
- Object *obpose = BKE_object_pose_armature_get(obact);
- if (obpose && obpose->pose && obpose->data) {
- if (obpose != obact) {
- FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (obpose, pchan) {
- CTX_data_list_add(result, &obpose->id, &RNA_PoseBone, pchan);
- } FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
- }
- else if (obact->mode & OB_MODE_POSE) {
- FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) {
- FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob_iter, pchan) {
- CTX_data_list_add(result, &ob_iter->id, &RNA_PoseBone, pchan);
- } FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
- } FOREACH_OBJECT_IN_MODE_END;
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "selected_pose_bones_from_active_object")) {
- Object *obpose = BKE_object_pose_armature_get(obact);
- if (obpose && obpose->pose && obpose->data) {
- if (obpose != obact) {
- FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (obpose, pchan) {
- CTX_data_list_add(result, &obpose->id, &RNA_PoseBone, pchan);
- } FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
- }
- else if (obact->mode & OB_MODE_POSE) {
- FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (obact, pchan) {
- CTX_data_list_add(result, &obact->id, &RNA_PoseBone, pchan);
- } FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "active_bone")) {
- if (obact && obact->type == OB_ARMATURE) {
- bArmature *arm = obact->data;
- if (arm->edbo) {
- if (arm->act_edbone) {
- CTX_data_pointer_set(result, &arm->id, &RNA_EditBone, arm->act_edbone);
- return 1;
- }
- }
- else {
- if (arm->act_bone) {
- CTX_data_pointer_set(result, &arm->id, &RNA_Bone, arm->act_bone);
- return 1;
- }
- }
- }
- }
- else if (CTX_data_equals(member, "active_pose_bone")) {
- bPoseChannel *pchan;
- Object *obpose = BKE_object_pose_armature_get(obact);
-
- pchan = BKE_pose_channel_active(obpose);
- if (pchan) {
- CTX_data_pointer_set(result, &obpose->id, &RNA_PoseBone, pchan);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "active_base")) {
- if (view_layer->basact)
- CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->basact);
-
- return 1;
- }
- else if (CTX_data_equals(member, "active_object")) {
- if (obact)
- CTX_data_id_pointer_set(result, &obact->id);
-
- return 1;
- }
- else if (CTX_data_equals(member, "object")) {
- if (obact)
- CTX_data_id_pointer_set(result, &obact->id);
-
- return 1;
- }
- else if (CTX_data_equals(member, "edit_object")) {
- /* convenience for now, 1 object per scene in editmode */
- if (obedit)
- CTX_data_id_pointer_set(result, &obedit->id);
-
- return 1;
- }
- else if (CTX_data_equals(member, "sculpt_object")) {
- if (obact && (obact->mode & OB_MODE_SCULPT))
- CTX_data_id_pointer_set(result, &obact->id);
-
- return 1;
- }
- else if (CTX_data_equals(member, "vertex_paint_object")) {
- if (obact && (obact->mode & OB_MODE_VERTEX_PAINT))
- CTX_data_id_pointer_set(result, &obact->id);
-
- return 1;
- }
- else if (CTX_data_equals(member, "weight_paint_object")) {
- if (obact && (obact->mode & OB_MODE_WEIGHT_PAINT))
- CTX_data_id_pointer_set(result, &obact->id);
-
- return 1;
- }
- else if (CTX_data_equals(member, "image_paint_object")) {
- if (obact && (obact->mode & OB_MODE_TEXTURE_PAINT))
- CTX_data_id_pointer_set(result, &obact->id);
-
- return 1;
- }
- else if (CTX_data_equals(member, "particle_edit_object")) {
- if (obact && (obact->mode & OB_MODE_PARTICLE_EDIT))
- CTX_data_id_pointer_set(result, &obact->id);
-
- return 1;
- }
- else if (CTX_data_equals(member, "uv_sculpt_object")) {
- /* TODO(campbell): most likely we change rules for uv_sculpt. */
- if (obact && (obact->mode & OB_MODE_EDIT)) {
- const ToolSettings *ts = scene->toolsettings;
- if (ts->use_uv_sculpt) {
- if (ED_uvedit_test(obedit)) {
- WorkSpace *workspace = CTX_wm_workspace(C);
- if ((workspace->tools_space_type == SPACE_IMAGE) &&
- (workspace->tools_mode == SI_MODE_UV))
- {
- CTX_data_id_pointer_set(result, &obact->id);
- }
- }
- }
- }
- return 1;
- }
- else if (CTX_data_equals(member, "pose_object")) {
- Object *obpose = BKE_object_pose_armature_get(obact);
- if (obpose) {
- CTX_data_id_pointer_set(result, &obpose->id);
- }
- return 1;
- }
- else if (CTX_data_equals(member, "sequences")) {
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- if (ed) {
- Sequence *seq;
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- CTX_data_list_add(result, &scene->id, &RNA_Sequence, seq);
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "selected_sequences")) {
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- if (ed) {
- Sequence *seq;
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if (seq->flag & SELECT) {
- CTX_data_list_add(result, &scene->id, &RNA_Sequence, seq);
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "selected_editable_sequences")) {
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- if (ed) {
- Sequence *seq;
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if (seq->flag & SELECT && !(seq->flag & SEQ_LOCK)) {
- CTX_data_list_add(result, &scene->id, &RNA_Sequence, seq);
- }
- }
- 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((ID *)sc, sa, scene, obact);
-
- if (gpd) {
- CTX_data_id_pointer_set(result, &gpd->id);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "gpencil_data_owner")) {
- /* pointer to which data/datablock owns the reference to the Grease Pencil data being used (as gpencil_data)
- * XXX: see comment for gpencil_data case...
- */
- bGPdata **gpd_ptr = NULL;
- PointerRNA ptr;
-
- /* get pointer to Grease Pencil Data */
- gpd_ptr = ED_gpencil_data_get_pointers_direct((ID *)sc, sa, scene, obact, &ptr);
-
- if (gpd_ptr) {
- CTX_data_pointer_set(result, ptr.id.data, ptr.type, ptr.data);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "active_gpencil_layer")) {
- /* XXX: see comment for gpencil_data case... */
- bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, sa, scene, obact);
-
- if (gpd) {
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
-
- if (gpl) {
- CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl);
- return 1;
- }
- }
- }
- else if (CTX_data_equals(member, "active_gpencil_frame")) {
- /* XXX: see comment for gpencil_data case... */
- bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, sa, scene, obact);
-
- if (gpd) {
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
-
- if (gpl) {
- CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl->actframe);
- return 1;
- }
- }
- }
- else if (CTX_data_equals(member, "visible_gpencil_layers")) {
- /* XXX: see comment for gpencil_data case... */
- bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, sa, scene, obact);
-
- if (gpd) {
- bGPDlayer *gpl;
-
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if ((gpl->flag & GP_LAYER_HIDE) == 0) {
- CTX_data_list_add(result, &gpd->id, &RNA_GPencilLayer, gpl);
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "editable_gpencil_layers")) {
- /* XXX: see comment for gpencil_data case... */
- bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, sa, scene, obact);
-
- if (gpd) {
- bGPDlayer *gpl;
-
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpencil_layer_is_editable(gpl)) {
- CTX_data_list_add(result, &gpd->id, &RNA_GPencilLayer, gpl);
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "editable_gpencil_strokes")) {
- /* XXX: see comment for gpencil_data case... */
- bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, sa, scene, 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)) {
- bGPDframe *gpf;
- bGPDstroke *gps;
- bGPDframe *init_gpf = gpl->actframe;
- if (is_multiedit) {
- init_gpf = gpl->frames.first;
- }
-
- 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)) {
- /* check if the color is editable */
- if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) {
- continue;
- }
-
- CTX_data_list_add(result, &gpd->id, &RNA_GPencilStroke, gps);
- }
- }
- }
- /* if not multiedit out of loop */
- if (!is_multiedit) {
- break;
- }
- }
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "active_operator")) {
- wmOperator *op = NULL;
-
- SpaceFile *sfile = CTX_wm_space_file(C);
- if (sfile) {
- op = sfile->op;
- }
- else if ((op = UI_context_active_operator_get(C))) {
- /* do nothing */
- }
- else {
- /* note, this checks poll, could be a problem, but this also
- * happens for the toolbar */
- op = WM_operator_last_redo(C);
- }
- /* TODO, get the operator from popup's */
-
- if (op && op->ptr) {
- CTX_data_pointer_set(result, NULL, &RNA_Operator, op);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "selected_editable_fcurves")) {
- bAnimContext ac;
-
- if (ANIM_animdata_get_context(C, &ac) && ELEM(ac.spacetype, SPACE_ACTION, SPACE_GRAPH)) {
- bAnimListElem *ale;
- ListBase anim_data = {NULL, NULL};
-
- int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS | ANIMFILTER_SEL) |
- (ac.spacetype == SPACE_GRAPH ? ANIMFILTER_CURVE_VISIBLE : ANIMFILTER_LIST_VISIBLE);
-
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- if (ale->type == ANIMTYPE_FCURVE)
- CTX_data_list_add(result, ale->id, &RNA_FCurve, ale->data);
- }
-
- ANIM_animdata_freelist(&anim_data);
-
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- }
- else {
- return 0; /* not found */
- }
-
- return -1; /* found but not available */
+ 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);
+ Scene *scene = WM_window_get_active_scene(win);
+ ViewLayer *view_layer = WM_window_get_active_view_layer(win);
+ Object *obact = (view_layer && view_layer->basact) ? view_layer->basact->object : NULL;
+ Object *obedit = view_layer ? OBEDIT_FROM_VIEW_LAYER(view_layer) : NULL;
+
+ if (CTX_data_dir(member)) {
+ CTX_data_dir_set(result, screen_context_dir);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "scene")) {
+ CTX_data_id_pointer_set(result, &scene->id);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "visible_objects")) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_VISIBLE(v3d, base)) {
+ CTX_data_id_list_add(result, &base->object->id);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "selectable_objects")) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTABLE(v3d, base)) {
+ CTX_data_id_list_add(result, &base->object->id);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "selected_objects")) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTED(v3d, base)) {
+ CTX_data_id_list_add(result, &base->object->id);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "selected_editable_objects")) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTED_EDITABLE(v3d, base)) {
+ CTX_data_id_list_add(result, &base->object->id);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ 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) {
+ if (BASE_EDITABLE(v3d, base)) {
+ CTX_data_id_list_add(result, &base->object->id);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "visible_bases")) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_VISIBLE(v3d, base)) {
+ CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "selectable_bases")) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTABLE(v3d, base)) {
+ CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "selected_bases")) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTED(v3d, base)) {
+ CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "selected_editable_bases")) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTED_EDITABLE(v3d, base)) {
+ CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "editable_bases")) {
+ /* Visible + Editable, but not necessarily selected */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_EDITABLE(v3d, base)) {
+ CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "objects_in_mode")) {
+ if (obact && (obact->mode != OB_MODE_OBJECT)) {
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) {
+ CTX_data_id_list_add(result, &ob_iter->id);
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "objects_in_mode_unique_data")) {
+ if (obact && (obact->mode != OB_MODE_OBJECT)) {
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) {
+ ob_iter->id.tag |= LIB_TAG_DOIT;
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) {
+ if (ob_iter->id.tag & LIB_TAG_DOIT) {
+ ob_iter->id.tag &= ~LIB_TAG_DOIT;
+ CTX_data_id_list_add(result, &ob_iter->id);
+ }
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "visible_bones") || CTX_data_equals(member, "editable_bones")) {
+ bArmature *arm = (obedit && obedit->type == OB_ARMATURE) ? obedit->data : NULL;
+ EditBone *ebone, *flipbone = NULL;
+ const bool editable_bones = CTX_data_equals(member, "editable_bones");
+
+ if (arm && arm->edbo) {
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint i = 0; i < objects_len; i++) {
+ Object *ob = objects[i];
+ arm = ob->data;
+
+ /* Attention: X-Axis Mirroring is also handled here... */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ /* first and foremost, bone must be visible and selected */
+ if (EBONE_VISIBLE(arm, ebone)) {
+ /* Get 'x-axis mirror equivalent' bone if the X-Axis Mirroring option is enabled
+ * so that most users of this data don't need to explicitly check for it themselves.
+ *
+ * We need to make sure that these mirrored copies are not selected, otherwise some
+ * bones will be operated on twice.
+ */
+ if (arm->flag & ARM_MIRROR_EDIT)
+ flipbone = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
+
+ /* if we're filtering for editable too, use the check for that instead,
+ * as it has selection check too */
+ if (editable_bones) {
+ /* only selected + editable */
+ if (EBONE_EDITABLE(ebone)) {
+ CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
+
+ if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
+ CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
+ }
+ }
+ else {
+ /* only include bones if visible */
+ CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
+
+ if ((flipbone) && EBONE_VISIBLE(arm, flipbone) == 0)
+ CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
+ }
+ }
+ }
+ }
+ MEM_freeN(objects);
+
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "selected_bones") ||
+ CTX_data_equals(member, "selected_editable_bones")) {
+ bArmature *arm = (obedit && obedit->type == OB_ARMATURE) ? obedit->data : NULL;
+ EditBone *ebone, *flipbone = NULL;
+ const bool selected_editable_bones = CTX_data_equals(member, "selected_editable_bones");
+
+ if (arm && arm->edbo) {
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint i = 0; i < objects_len; i++) {
+ Object *ob = objects[i];
+ arm = ob->data;
+
+ /* Attention: X-Axis Mirroring is also handled here... */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ /* first and foremost, bone must be visible and selected */
+ if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_SELECTED)) {
+ /* Get 'x-axis mirror equivalent' bone if the X-Axis Mirroring option is enabled
+ * so that most users of this data don't need to explicitly check for it themselves.
+ *
+ * We need to make sure that these mirrored copies are not selected, otherwise some
+ * bones will be operated on twice.
+ */
+ if (arm->flag & ARM_MIRROR_EDIT)
+ flipbone = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
+
+ /* if we're filtering for editable too, use the check for that instead,
+ * as it has selection check too */
+ if (selected_editable_bones) {
+ /* only selected + editable */
+ if (EBONE_EDITABLE(ebone)) {
+ CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
+
+ if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
+ CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
+ }
+ }
+ else {
+ /* only include bones if selected */
+ CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
+
+ if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
+ CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
+ }
+ }
+ }
+ }
+ MEM_freeN(objects);
+
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "visible_pose_bones")) {
+ Object *obpose = BKE_object_pose_armature_get(obact);
+ if (obpose && obpose->pose && obpose->data) {
+ if (obpose != obact) {
+ FOREACH_PCHAN_VISIBLE_IN_OBJECT_BEGIN (obpose, pchan) {
+ CTX_data_list_add(result, &obpose->id, &RNA_PoseBone, pchan);
+ }
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
+ }
+ else if (obact->mode & OB_MODE_POSE) {
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) {
+ FOREACH_PCHAN_VISIBLE_IN_OBJECT_BEGIN (ob_iter, pchan) {
+ CTX_data_list_add(result, &ob_iter->id, &RNA_PoseBone, pchan);
+ }
+ FOREACH_PCHAN_VISIBLE_IN_OBJECT_END;
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "selected_pose_bones")) {
+ Object *obpose = BKE_object_pose_armature_get(obact);
+ if (obpose && obpose->pose && obpose->data) {
+ if (obpose != obact) {
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (obpose, pchan) {
+ CTX_data_list_add(result, &obpose->id, &RNA_PoseBone, pchan);
+ }
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
+ }
+ else if (obact->mode & OB_MODE_POSE) {
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) {
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob_iter, pchan) {
+ CTX_data_list_add(result, &ob_iter->id, &RNA_PoseBone, pchan);
+ }
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "selected_pose_bones_from_active_object")) {
+ Object *obpose = BKE_object_pose_armature_get(obact);
+ if (obpose && obpose->pose && obpose->data) {
+ if (obpose != obact) {
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (obpose, pchan) {
+ CTX_data_list_add(result, &obpose->id, &RNA_PoseBone, pchan);
+ }
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
+ }
+ else if (obact->mode & OB_MODE_POSE) {
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (obact, pchan) {
+ CTX_data_list_add(result, &obact->id, &RNA_PoseBone, pchan);
+ }
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "active_bone")) {
+ if (obact && obact->type == OB_ARMATURE) {
+ bArmature *arm = obact->data;
+ if (arm->edbo) {
+ if (arm->act_edbone) {
+ CTX_data_pointer_set(result, &arm->id, &RNA_EditBone, arm->act_edbone);
+ return 1;
+ }
+ }
+ else {
+ if (arm->act_bone) {
+ CTX_data_pointer_set(result, &arm->id, &RNA_Bone, arm->act_bone);
+ return 1;
+ }
+ }
+ }
+ }
+ else if (CTX_data_equals(member, "active_pose_bone")) {
+ bPoseChannel *pchan;
+ Object *obpose = BKE_object_pose_armature_get(obact);
+
+ pchan = BKE_pose_channel_active(obpose);
+ if (pchan) {
+ CTX_data_pointer_set(result, &obpose->id, &RNA_PoseBone, pchan);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "active_base")) {
+ if (view_layer->basact)
+ CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->basact);
+
+ return 1;
+ }
+ else if (CTX_data_equals(member, "active_object")) {
+ if (obact)
+ CTX_data_id_pointer_set(result, &obact->id);
+
+ return 1;
+ }
+ else if (CTX_data_equals(member, "object")) {
+ if (obact)
+ CTX_data_id_pointer_set(result, &obact->id);
+
+ return 1;
+ }
+ else if (CTX_data_equals(member, "edit_object")) {
+ /* convenience for now, 1 object per scene in editmode */
+ if (obedit)
+ CTX_data_id_pointer_set(result, &obedit->id);
+
+ return 1;
+ }
+ else if (CTX_data_equals(member, "sculpt_object")) {
+ if (obact && (obact->mode & OB_MODE_SCULPT))
+ CTX_data_id_pointer_set(result, &obact->id);
+
+ return 1;
+ }
+ else if (CTX_data_equals(member, "vertex_paint_object")) {
+ if (obact && (obact->mode & OB_MODE_VERTEX_PAINT))
+ CTX_data_id_pointer_set(result, &obact->id);
+
+ return 1;
+ }
+ else if (CTX_data_equals(member, "weight_paint_object")) {
+ if (obact && (obact->mode & OB_MODE_WEIGHT_PAINT))
+ CTX_data_id_pointer_set(result, &obact->id);
+
+ return 1;
+ }
+ else if (CTX_data_equals(member, "image_paint_object")) {
+ if (obact && (obact->mode & OB_MODE_TEXTURE_PAINT))
+ CTX_data_id_pointer_set(result, &obact->id);
+
+ return 1;
+ }
+ else if (CTX_data_equals(member, "particle_edit_object")) {
+ if (obact && (obact->mode & OB_MODE_PARTICLE_EDIT))
+ CTX_data_id_pointer_set(result, &obact->id);
+
+ return 1;
+ }
+ else if (CTX_data_equals(member, "uv_sculpt_object")) {
+ /* TODO(campbell): most likely we change rules for uv_sculpt. */
+ if (obact && (obact->mode & OB_MODE_EDIT)) {
+ const ToolSettings *ts = scene->toolsettings;
+ if (ts->use_uv_sculpt) {
+ if (ED_uvedit_test(obedit)) {
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ if ((workspace->tools_space_type == SPACE_IMAGE) &&
+ (workspace->tools_mode == SI_MODE_UV)) {
+ CTX_data_id_pointer_set(result, &obact->id);
+ }
+ }
+ }
+ }
+ return 1;
+ }
+ else if (CTX_data_equals(member, "pose_object")) {
+ Object *obpose = BKE_object_pose_armature_get(obact);
+ if (obpose) {
+ CTX_data_id_pointer_set(result, &obpose->id);
+ }
+ return 1;
+ }
+ else if (CTX_data_equals(member, "sequences")) {
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ if (ed) {
+ Sequence *seq;
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ CTX_data_list_add(result, &scene->id, &RNA_Sequence, seq);
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "selected_sequences")) {
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ if (ed) {
+ Sequence *seq;
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (seq->flag & SELECT) {
+ CTX_data_list_add(result, &scene->id, &RNA_Sequence, seq);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "selected_editable_sequences")) {
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ if (ed) {
+ Sequence *seq;
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (seq->flag & SELECT && !(seq->flag & SEQ_LOCK)) {
+ CTX_data_list_add(result, &scene->id, &RNA_Sequence, seq);
+ }
+ }
+ 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((ID *)sc, sa, scene, obact);
+
+ if (gpd) {
+ CTX_data_id_pointer_set(result, &gpd->id);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "gpencil_data_owner")) {
+ /* pointer to which data/datablock owns the reference to the Grease Pencil data being used (as gpencil_data)
+ * XXX: see comment for gpencil_data case...
+ */
+ bGPdata **gpd_ptr = NULL;
+ PointerRNA ptr;
+
+ /* get pointer to Grease Pencil Data */
+ gpd_ptr = ED_gpencil_data_get_pointers_direct((ID *)sc, sa, scene, obact, &ptr);
+
+ if (gpd_ptr) {
+ CTX_data_pointer_set(result, ptr.id.data, ptr.type, ptr.data);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "active_gpencil_layer")) {
+ /* XXX: see comment for gpencil_data case... */
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, sa, scene, obact);
+
+ if (gpd) {
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+
+ if (gpl) {
+ CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl);
+ return 1;
+ }
+ }
+ }
+ else if (CTX_data_equals(member, "active_gpencil_frame")) {
+ /* XXX: see comment for gpencil_data case... */
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, sa, scene, obact);
+
+ if (gpd) {
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+
+ if (gpl) {
+ CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl->actframe);
+ return 1;
+ }
+ }
+ }
+ else if (CTX_data_equals(member, "visible_gpencil_layers")) {
+ /* XXX: see comment for gpencil_data case... */
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, sa, scene, obact);
+
+ if (gpd) {
+ bGPDlayer *gpl;
+
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if ((gpl->flag & GP_LAYER_HIDE) == 0) {
+ CTX_data_list_add(result, &gpd->id, &RNA_GPencilLayer, gpl);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "editable_gpencil_layers")) {
+ /* XXX: see comment for gpencil_data case... */
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, sa, scene, obact);
+
+ if (gpd) {
+ bGPDlayer *gpl;
+
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpencil_layer_is_editable(gpl)) {
+ CTX_data_list_add(result, &gpd->id, &RNA_GPencilLayer, gpl);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "editable_gpencil_strokes")) {
+ /* XXX: see comment for gpencil_data case... */
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, sa, scene, 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)) {
+ bGPDframe *gpf;
+ bGPDstroke *gps;
+ bGPDframe *init_gpf = gpl->actframe;
+ if (is_multiedit) {
+ init_gpf = gpl->frames.first;
+ }
+
+ 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)) {
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) {
+ continue;
+ }
+
+ CTX_data_list_add(result, &gpd->id, &RNA_GPencilStroke, gps);
+ }
+ }
+ }
+ /* if not multiedit out of loop */
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "active_operator")) {
+ wmOperator *op = NULL;
+
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ if (sfile) {
+ op = sfile->op;
+ }
+ else if ((op = UI_context_active_operator_get(C))) {
+ /* do nothing */
+ }
+ else {
+ /* note, this checks poll, could be a problem, but this also
+ * happens for the toolbar */
+ op = WM_operator_last_redo(C);
+ }
+ /* TODO, get the operator from popup's */
+
+ if (op && op->ptr) {
+ CTX_data_pointer_set(result, NULL, &RNA_Operator, op);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "selected_editable_fcurves")) {
+ bAnimContext ac;
+
+ if (ANIM_animdata_get_context(C, &ac) && ELEM(ac.spacetype, SPACE_ACTION, SPACE_GRAPH)) {
+ bAnimListElem *ale;
+ ListBase anim_data = {NULL, NULL};
+
+ int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS |
+ ANIMFILTER_SEL) |
+ (ac.spacetype == SPACE_GRAPH ? ANIMFILTER_CURVE_VISIBLE :
+ ANIMFILTER_LIST_VISIBLE);
+
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (ale->type == ANIMTYPE_FCURVE)
+ CTX_data_list_add(result, ale->id, &RNA_FCurve, ale->data);
+ }
+
+ ANIM_animdata_freelist(&anim_data);
+
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
+ else {
+ return 0; /* not found */
+ }
+
+ return -1; /* found but not available */
}
diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c
index 6a0332731b4..fb738bf40cd 100644
--- a/source/blender/editors/screen/screen_draw.c
+++ b/source/blender/editors/screen/screen_draw.c
@@ -44,80 +44,80 @@
*/
static void draw_horizontal_join_shape(ScrArea *sa, char dir, unsigned int pos)
{
- const float width = screen_geom_area_width(sa) - 1;
- const float height = screen_geom_area_height(sa) - 1;
- vec2f points[10];
- short i;
- float w, h;
+ const float width = screen_geom_area_width(sa) - 1;
+ const float height = screen_geom_area_height(sa) - 1;
+ vec2f points[10];
+ short i;
+ float w, h;
- if (height < width) {
- h = height / 8;
- w = height / 4;
- }
- else {
- h = width / 8;
- w = width / 4;
- }
+ if (height < width) {
+ h = height / 8;
+ w = height / 4;
+ }
+ else {
+ h = width / 8;
+ w = width / 4;
+ }
- points[0].x = sa->v1->vec.x;
- points[0].y = sa->v1->vec.y + height / 2;
+ points[0].x = sa->v1->vec.x;
+ points[0].y = sa->v1->vec.y + height / 2;
- points[1].x = sa->v1->vec.x;
- points[1].y = sa->v1->vec.y;
+ points[1].x = sa->v1->vec.x;
+ points[1].y = sa->v1->vec.y;
- points[2].x = sa->v4->vec.x - w;
- points[2].y = sa->v4->vec.y;
+ points[2].x = sa->v4->vec.x - w;
+ points[2].y = sa->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 = sa->v4->vec.x - w;
+ points[3].y = sa->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 = sa->v4->vec.x - 2 * w;
+ points[4].y = sa->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 = sa->v4->vec.x - w;
+ points[5].y = sa->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 = sa->v3->vec.x - w;
+ points[6].y = sa->v3->vec.y;
- points[7].x = sa->v2->vec.x;
- points[7].y = sa->v2->vec.y;
+ points[7].x = sa->v2->vec.x;
+ points[7].y = sa->v2->vec.y;
- points[8].x = sa->v4->vec.x;
- points[8].y = sa->v4->vec.y + height / 2 - h;
+ points[8].x = sa->v4->vec.x;
+ points[8].y = sa->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 = sa->v4->vec.x;
+ points[9].y = sa->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;
- for (i = 0; i < 10; i++) {
- points[i].x -= cx;
- points[i].x = -points[i].x;
- points[i].x += sa->v1->vec.x;
- }
- }
+ if (dir == 'l') {
+ /* when direction is left, then we flip direction of arrow */
+ float cx = sa->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;
+ }
+ }
- immBegin(GPU_PRIM_TRI_FAN, 5);
+ immBegin(GPU_PRIM_TRI_FAN, 5);
- for (i = 0; i < 5; i++) {
- immVertex2f(pos, points[i].x, points[i].y);
- }
+ for (i = 0; i < 5; i++) {
+ immVertex2f(pos, points[i].x, points[i].y);
+ }
- immEnd();
+ immEnd();
- immBegin(GPU_PRIM_TRI_FAN, 5);
+ immBegin(GPU_PRIM_TRI_FAN, 5);
- for (i = 4; i < 8; i++) {
- immVertex2f(pos, points[i].x, points[i].y);
- }
+ for (i = 4; i < 8; i++) {
+ immVertex2f(pos, points[i].x, points[i].y);
+ }
- immVertex2f(pos, points[0].x, points[0].y);
- immEnd();
+ immVertex2f(pos, points[0].x, points[0].y);
+ immEnd();
- immRectf(pos, points[2].x, points[2].y, points[8].x, points[8].y);
- immRectf(pos, points[6].x, points[6].y, points[9].x, points[9].y);
+ immRectf(pos, points[2].x, points[2].y, points[8].x, points[8].y);
+ immRectf(pos, points[6].x, points[6].y, points[9].x, points[9].y);
}
/**
@@ -125,80 +125,80 @@ static void draw_horizontal_join_shape(ScrArea *sa, char dir, unsigned int pos)
*/
static void draw_vertical_join_shape(ScrArea *sa, char dir, unsigned int pos)
{
- const float width = screen_geom_area_width(sa) - 1;
- const float height = screen_geom_area_height(sa) - 1;
- vec2f points[10];
- short i;
- float w, h;
+ const float width = screen_geom_area_width(sa) - 1;
+ const float height = screen_geom_area_height(sa) - 1;
+ vec2f points[10];
+ short i;
+ float w, h;
- if (height < width) {
- h = height / 4;
- w = height / 8;
- }
- else {
- h = width / 4;
- w = width / 8;
- }
+ if (height < width) {
+ h = height / 4;
+ w = height / 8;
+ }
+ else {
+ h = width / 4;
+ w = width / 8;
+ }
- points[0].x = sa->v1->vec.x + width / 2;
- points[0].y = sa->v3->vec.y;
+ points[0].x = sa->v1->vec.x + width / 2;
+ points[0].y = sa->v3->vec.y;
- points[1].x = sa->v2->vec.x;
- points[1].y = sa->v2->vec.y;
+ points[1].x = sa->v2->vec.x;
+ points[1].y = sa->v2->vec.y;
- points[2].x = sa->v1->vec.x;
- points[2].y = sa->v1->vec.y + h;
+ points[2].x = sa->v1->vec.x;
+ points[2].y = sa->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 = sa->v1->vec.x + width / 2 - 2 * w;
+ points[3].y = sa->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 = sa->v1->vec.x + width / 2;
+ points[4].y = sa->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 = sa->v1->vec.x + width / 2 + 2 * w;
+ points[5].y = sa->v1->vec.y + h;
- points[6].x = sa->v4->vec.x;
- points[6].y = sa->v4->vec.y + h;
+ points[6].x = sa->v4->vec.x;
+ points[6].y = sa->v4->vec.y + h;
- points[7].x = sa->v3->vec.x;
- points[7].y = sa->v3->vec.y;
+ points[7].x = sa->v3->vec.x;
+ points[7].y = sa->v3->vec.y;
- points[8].x = sa->v1->vec.x + width / 2 - w;
- points[8].y = sa->v1->vec.y;
+ points[8].x = sa->v1->vec.x + width / 2 - w;
+ points[8].y = sa->v1->vec.y;
- points[9].x = sa->v1->vec.x + width / 2 + w;
- points[9].y = sa->v1->vec.y;
+ points[9].x = sa->v1->vec.x + width / 2 + w;
+ points[9].y = sa->v1->vec.y;
- if (dir == 'u') {
- /* when direction is up, then we flip direction of arrow */
- float cy = sa->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;
- }
- }
+ if (dir == 'u') {
+ /* when direction is up, then we flip direction of arrow */
+ float cy = sa->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;
+ }
+ }
- immBegin(GPU_PRIM_TRI_FAN, 5);
+ immBegin(GPU_PRIM_TRI_FAN, 5);
- for (i = 0; i < 5; i++) {
- immVertex2f(pos, points[i].x, points[i].y);
- }
+ for (i = 0; i < 5; i++) {
+ immVertex2f(pos, points[i].x, points[i].y);
+ }
- immEnd();
+ immEnd();
- immBegin(GPU_PRIM_TRI_FAN, 5);
+ immBegin(GPU_PRIM_TRI_FAN, 5);
- for (i = 4; i < 8; i++) {
- immVertex2f(pos, points[i].x, points[i].y);
- }
+ for (i = 4; i < 8; i++) {
+ immVertex2f(pos, points[i].x, points[i].y);
+ }
- immVertex2f(pos, points[0].x, points[0].y);
- immEnd();
+ immVertex2f(pos, points[0].x, points[0].y);
+ immEnd();
- immRectf(pos, points[2].x, points[2].y, points[8].x, points[8].y);
- immRectf(pos, points[6].x, points[6].y, points[9].x, points[9].y);
+ immRectf(pos, points[2].x, points[2].y, points[8].x, points[8].y);
+ immRectf(pos, points[6].x, points[6].y, points[9].x, points[9].y);
}
/**
@@ -206,88 +206,88 @@ static void draw_vertical_join_shape(ScrArea *sa, char dir, unsigned int pos)
*/
static void draw_join_shape(ScrArea *sa, char dir, unsigned int pos)
{
- if (dir == 'u' || dir == 'd') {
- draw_vertical_join_shape(sa, dir, pos);
- }
- else {
- draw_horizontal_join_shape(sa, dir, pos);
- }
+ if (dir == 'u' || dir == 'd') {
+ draw_vertical_join_shape(sa, dir, pos);
+ }
+ else {
+ draw_horizontal_join_shape(sa, dir, pos);
+ }
}
#define CORNER_RESOLUTION 3
static void do_vert_pair(GPUVertBuf *vbo, uint pos, uint *vidx, int corner, int i)
{
- float inter[2], exter[2];
- inter[0] = cosf(corner * M_PI_2 + (i * M_PI_2 / (CORNER_RESOLUTION - 1.0f)));
- inter[1] = sinf(corner * M_PI_2 + (i * M_PI_2 / (CORNER_RESOLUTION - 1.0f)));
-
- /* Snap point to edge */
- float div = 1.0f / max_ff(fabsf(inter[0]), fabsf(inter[1]));
- mul_v2_v2fl(exter, inter, div);
- exter[0] = roundf(exter[0]);
- exter[1] = roundf(exter[1]);
-
- if (i == 0 || i == (CORNER_RESOLUTION - 1)) {
- copy_v2_v2(inter, exter);
- }
-
- /* Line width is 20% of the entire corner size. */
- const float line_width = 0.2f; /* Keep in sync with shader */
- mul_v2_fl(inter, 1.0f - line_width);
- mul_v2_fl(exter, 1.0f + line_width);
-
- switch (corner) {
- case 0:
- add_v2_v2(inter, (float[2]){-1.0f, -1.0f});
- add_v2_v2(exter, (float[2]){-1.0f, -1.0f});
- break;
- case 1:
- add_v2_v2(inter, (float[2]){1.0f, -1.0f});
- add_v2_v2(exter, (float[2]){1.0f, -1.0f});
- break;
- case 2:
- add_v2_v2(inter, (float[2]){1.0f, 1.0f});
- add_v2_v2(exter, (float[2]){1.0f, 1.0f});
- break;
- case 3:
- add_v2_v2(inter, (float[2]){-1.0f, 1.0f});
- add_v2_v2(exter, (float[2]){-1.0f, 1.0f});
- break;
- }
-
- GPU_vertbuf_attr_set(vbo, pos, (*vidx)++, inter);
- GPU_vertbuf_attr_set(vbo, pos, (*vidx)++, exter);
+ float inter[2], exter[2];
+ inter[0] = cosf(corner * M_PI_2 + (i * M_PI_2 / (CORNER_RESOLUTION - 1.0f)));
+ inter[1] = sinf(corner * M_PI_2 + (i * M_PI_2 / (CORNER_RESOLUTION - 1.0f)));
+
+ /* Snap point to edge */
+ float div = 1.0f / max_ff(fabsf(inter[0]), fabsf(inter[1]));
+ mul_v2_v2fl(exter, inter, div);
+ exter[0] = roundf(exter[0]);
+ exter[1] = roundf(exter[1]);
+
+ if (i == 0 || i == (CORNER_RESOLUTION - 1)) {
+ copy_v2_v2(inter, exter);
+ }
+
+ /* Line width is 20% of the entire corner size. */
+ const float line_width = 0.2f; /* Keep in sync with shader */
+ mul_v2_fl(inter, 1.0f - line_width);
+ mul_v2_fl(exter, 1.0f + line_width);
+
+ switch (corner) {
+ case 0:
+ add_v2_v2(inter, (float[2]){-1.0f, -1.0f});
+ add_v2_v2(exter, (float[2]){-1.0f, -1.0f});
+ break;
+ case 1:
+ add_v2_v2(inter, (float[2]){1.0f, -1.0f});
+ add_v2_v2(exter, (float[2]){1.0f, -1.0f});
+ break;
+ case 2:
+ add_v2_v2(inter, (float[2]){1.0f, 1.0f});
+ add_v2_v2(exter, (float[2]){1.0f, 1.0f});
+ break;
+ case 3:
+ add_v2_v2(inter, (float[2]){-1.0f, 1.0f});
+ add_v2_v2(exter, (float[2]){-1.0f, 1.0f});
+ break;
+ }
+
+ GPU_vertbuf_attr_set(vbo, pos, (*vidx)++, inter);
+ GPU_vertbuf_attr_set(vbo, pos, (*vidx)++, exter);
}
static GPUBatch *batch_screen_edges_get(int *corner_len)
{
- static GPUBatch *screen_edges_batch = NULL;
-
- if (screen_edges_batch == NULL) {
- GPUVertFormat format = {0};
- uint pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, CORNER_RESOLUTION * 2 * 4 + 2);
-
- uint vidx = 0;
- for (int corner = 0; corner < 4; ++corner) {
- for (int c = 0; c < CORNER_RESOLUTION; ++c) {
- do_vert_pair(vbo, pos, &vidx, corner, c);
- }
- }
- /* close the loop */
- do_vert_pair(vbo, pos, &vidx, 0, 0);
-
- screen_edges_batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
- gpu_batch_presets_register(screen_edges_batch);
- }
-
- if (corner_len) {
- *corner_len = CORNER_RESOLUTION * 2;
- }
- return screen_edges_batch;
+ static GPUBatch *screen_edges_batch = NULL;
+
+ if (screen_edges_batch == NULL) {
+ GPUVertFormat format = {0};
+ uint pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, CORNER_RESOLUTION * 2 * 4 + 2);
+
+ uint vidx = 0;
+ for (int corner = 0; corner < 4; ++corner) {
+ for (int c = 0; c < CORNER_RESOLUTION; ++c) {
+ do_vert_pair(vbo, pos, &vidx, corner, c);
+ }
+ }
+ /* close the loop */
+ do_vert_pair(vbo, pos, &vidx, 0, 0);
+
+ screen_edges_batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ gpu_batch_presets_register(screen_edges_batch);
+ }
+
+ if (corner_len) {
+ *corner_len = CORNER_RESOLUTION * 2;
+ }
+ return screen_edges_batch;
}
#undef CORNER_RESOLUTION
@@ -297,10 +297,11 @@ static GPUBatch *batch_screen_edges_get(int *corner_len)
*/
static void scrarea_draw_shape_dark(ScrArea *sa, char dir, unsigned int 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);
+ 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(sa, dir, pos);
}
/**
@@ -308,42 +309,43 @@ static void scrarea_draw_shape_dark(ScrArea *sa, char dir, unsigned int pos)
*/
static void scrarea_draw_shape_light(ScrArea *sa, char UNUSED(dir), unsigned int 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); */
+ 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); */
- immRectf(pos, sa->v1->vec.x, sa->v1->vec.y, sa->v3->vec.x, sa->v3->vec.y);
+ immRectf(pos, sa->v1->vec.x, sa->v1->vec.y, sa->v3->vec.x, sa->v3->vec.y);
}
-static void drawscredge_area_draw(int sizex, int sizey, short x1, short y1, short x2, short y2, float edge_thickness)
+static void drawscredge_area_draw(
+ int sizex, int sizey, short x1, short y1, short x2, short y2, float edge_thickness)
{
- rctf rect;
- BLI_rctf_init(&rect, (float)x1, (float)x2, (float)y1, (float)y2);
-
- /* right border area */
- if (x2 >= sizex - 1) {
- rect.xmax += edge_thickness * 0.5f;
- }
-
- /* left border area */
- if (x1 <= 0) { /* otherwise it draws the emboss of window over */
- rect.xmin -= edge_thickness * 0.5f;
- }
-
- /* top border area */
- if (y2 >= sizey - 1) {
- rect.ymax += edge_thickness * 0.5f;
- }
-
- /* bottom border area */
- if (y1 <= 0) {
- rect.ymin -= edge_thickness * 0.5f;
- }
-
- GPUBatch *batch = batch_screen_edges_get(NULL);
- GPU_batch_uniform_4fv(batch, "rect", (float *)&rect);
- GPU_batch_draw(batch);
+ rctf rect;
+ BLI_rctf_init(&rect, (float)x1, (float)x2, (float)y1, (float)y2);
+
+ /* right border area */
+ if (x2 >= sizex - 1) {
+ rect.xmax += edge_thickness * 0.5f;
+ }
+
+ /* left border area */
+ if (x1 <= 0) { /* otherwise it draws the emboss of window over */
+ rect.xmin -= edge_thickness * 0.5f;
+ }
+
+ /* top border area */
+ if (y2 >= sizey - 1) {
+ rect.ymax += edge_thickness * 0.5f;
+ }
+
+ /* bottom border area */
+ if (y1 <= 0) {
+ rect.ymin -= edge_thickness * 0.5f;
+ }
+
+ GPUBatch *batch = batch_screen_edges_get(NULL);
+ GPU_batch_uniform_4fv(batch, "rect", (float *)&rect);
+ GPU_batch_draw(batch);
}
/**
@@ -351,12 +353,12 @@ static void drawscredge_area_draw(int sizex, int sizey, short x1, short y1, shor
*/
static void drawscredge_area(ScrArea *sa, 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 = sa->v1->vec.x;
+ short y1 = sa->v1->vec.y;
+ short x2 = sa->v3->vec.x;
+ short y2 = sa->v3->vec.y;
- drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2, edge_thickness);
+ drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2, edge_thickness);
}
/**
@@ -364,71 +366,72 @@ static void drawscredge_area(ScrArea *sa, int sizex, int sizey, float edge_thick
*/
void ED_screen_draw_edges(wmWindow *win)
{
- bScreen *screen = WM_window_get_active_screen(win);
- screen->do_draw = false;
-
- if (screen->state == SCREENFULL) {
- return;
- }
-
- if (screen->temp && BLI_listbase_is_single(&screen->areabase)) {
- return;
- }
-
- const int winsize_x = WM_window_pixels_x(win);
- const int winsize_y = WM_window_pixels_y(win);
- float col[4], corner_scale, edge_thickness;
- int verts_per_corner = 0;
-
- ScrArea *sa;
-
- 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});
- }
-
- if (GPU_type_matches(GPU_DEVICE_INTEL_UHD, GPU_OS_UNIX, GPU_DRIVER_ANY)) {
- /* For some reason, on linux + Intel UHD Graphics 620 the driver
- * hangs if we don't flush before this. (See T57455) */
- GPU_flush();
- }
-
- GPU_scissor(scissor_rect.xmin,
- scissor_rect.ymin,
- BLI_rcti_size_x(&scissor_rect) + 1,
- BLI_rcti_size_y(&scissor_rect) + 1);
-
- /* It seems that all areas gets smaller when pixelsize is > 1.
- * So in order to avoid missing pixels we just disable de scissors. */
- if (U.pixelsize <= 1.0f) {
- glEnable(GL_SCISSOR_TEST);
- }
-
- UI_GetThemeColor4fv(TH_EDITOR_OUTLINE, col);
- col[3] = 1.0f;
- corner_scale = U.pixelsize * 8.0f;
- edge_thickness = corner_scale * 0.21f;
-
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- GPUBatch *batch = batch_screen_edges_get(&verts_per_corner);
- GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_AREA_EDGES);
- GPU_batch_uniform_1i(batch, "cornerLen", verts_per_corner);
- 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);
- }
-
- GPU_blend(false);
-
- if (U.pixelsize <= 1.0f) {
- glDisable(GL_SCISSOR_TEST);
- }
+ bScreen *screen = WM_window_get_active_screen(win);
+ screen->do_draw = false;
+
+ if (screen->state == SCREENFULL) {
+ return;
+ }
+
+ if (screen->temp && BLI_listbase_is_single(&screen->areabase)) {
+ return;
+ }
+
+ const int winsize_x = WM_window_pixels_x(win);
+ const int winsize_y = WM_window_pixels_y(win);
+ float col[4], corner_scale, edge_thickness;
+ int verts_per_corner = 0;
+
+ ScrArea *sa;
+
+ 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});
+ }
+
+ if (GPU_type_matches(GPU_DEVICE_INTEL_UHD, GPU_OS_UNIX, GPU_DRIVER_ANY)) {
+ /* For some reason, on linux + Intel UHD Graphics 620 the driver
+ * hangs if we don't flush before this. (See T57455) */
+ GPU_flush();
+ }
+
+ GPU_scissor(scissor_rect.xmin,
+ scissor_rect.ymin,
+ BLI_rcti_size_x(&scissor_rect) + 1,
+ BLI_rcti_size_y(&scissor_rect) + 1);
+
+ /* It seems that all areas gets smaller when pixelsize is > 1.
+ * So in order to avoid missing pixels we just disable de scissors. */
+ if (U.pixelsize <= 1.0f) {
+ glEnable(GL_SCISSOR_TEST);
+ }
+
+ UI_GetThemeColor4fv(TH_EDITOR_OUTLINE, col);
+ col[3] = 1.0f;
+ corner_scale = U.pixelsize * 8.0f;
+ edge_thickness = corner_scale * 0.21f;
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ GPUBatch *batch = batch_screen_edges_get(&verts_per_corner);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_AREA_EDGES);
+ GPU_batch_uniform_1i(batch, "cornerLen", verts_per_corner);
+ 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);
+ }
+
+ GPU_blend(false);
+
+ if (U.pixelsize <= 1.0f) {
+ glDisable(GL_SCISSOR_TEST);
+ }
}
/**
@@ -439,100 +442,100 @@ void ED_screen_draw_edges(wmWindow *win)
*/
void ED_screen_draw_join_shape(ScrArea *sa1, ScrArea *sa2)
{
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- GPU_line_width(1);
-
- /* blended join arrow */
- int dir = area_getorientation(sa1, sa2);
- int dira = -1;
- if (dir != -1) {
- switch (dir) {
- case 0: /* W */
- dir = 'r';
- dira = 'l';
- break;
- case 1: /* N */
- dir = 'd';
- dira = 'u';
- break;
- case 2: /* E */
- dir = 'l';
- dira = 'r';
- break;
- case 3: /* S */
- dir = 'u';
- dira = 'd';
- break;
- }
-
- GPU_blend(true);
-
- scrarea_draw_shape_dark(sa2, dir, pos);
- scrarea_draw_shape_light(sa1, dira, pos);
-
- GPU_blend(false);
- }
-
- immUnbindProgram();
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ GPU_line_width(1);
+
+ /* blended join arrow */
+ int dir = area_getorientation(sa1, sa2);
+ int dira = -1;
+ if (dir != -1) {
+ switch (dir) {
+ case 0: /* W */
+ dir = 'r';
+ dira = 'l';
+ break;
+ case 1: /* N */
+ dir = 'd';
+ dira = 'u';
+ break;
+ case 2: /* E */
+ dir = 'l';
+ dira = 'r';
+ break;
+ case 3: /* S */
+ dir = 'u';
+ dira = 'd';
+ break;
+ }
+
+ GPU_blend(true);
+
+ scrarea_draw_shape_dark(sa2, dir, pos);
+ scrarea_draw_shape_light(sa1, dira, pos);
+
+ GPU_blend(false);
+ }
+
+ immUnbindProgram();
}
void ED_screen_draw_split_preview(ScrArea *sa, 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);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- /* splitpoint */
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ /* splitpoint */
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- immUniformColor4ub(255, 255, 255, 100);
+ immUniformColor4ub(255, 255, 255, 100);
- immBegin(GPU_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
- if (dir == 'h') {
- const float y = (1 - fac) * sa->totrct.ymin + fac * sa->totrct.ymax;
+ if (dir == 'h') {
+ const float y = (1 - fac) * sa->totrct.ymin + fac * sa->totrct.ymax;
- immVertex2f(pos, sa->totrct.xmin, y);
- immVertex2f(pos, sa->totrct.xmax, y);
+ immVertex2f(pos, sa->totrct.xmin, y);
+ immVertex2f(pos, sa->totrct.xmax, y);
- immEnd();
+ immEnd();
- immUniformColor4ub(0, 0, 0, 100);
+ immUniformColor4ub(0, 0, 0, 100);
- immBegin(GPU_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, sa->totrct.xmin, y + 1);
- immVertex2f(pos, sa->totrct.xmax, y + 1);
+ immVertex2f(pos, sa->totrct.xmin, y + 1);
+ immVertex2f(pos, sa->totrct.xmax, y + 1);
- immEnd();
- }
- else {
- BLI_assert(dir == 'v');
- const float x = (1 - fac) * sa->totrct.xmin + fac * sa->totrct.xmax;
+ immEnd();
+ }
+ else {
+ BLI_assert(dir == 'v');
+ const float x = (1 - fac) * sa->totrct.xmin + fac * sa->totrct.xmax;
- immVertex2f(pos, x, sa->totrct.ymin);
- immVertex2f(pos, x, sa->totrct.ymax);
+ immVertex2f(pos, x, sa->totrct.ymin);
+ immVertex2f(pos, x, sa->totrct.ymax);
- immEnd();
+ immEnd();
- immUniformColor4ub(0, 0, 0, 100);
+ immUniformColor4ub(0, 0, 0, 100);
- immBegin(GPU_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, x + 1, sa->totrct.ymin);
- immVertex2f(pos, x + 1, sa->totrct.ymax);
+ immVertex2f(pos, x + 1, sa->totrct.ymin);
+ immVertex2f(pos, x + 1, sa->totrct.ymax);
- immEnd();
- }
+ immEnd();
+ }
- GPU_blend(false);
+ GPU_blend(false);
- immUnbindProgram();
+ immUnbindProgram();
}
-
/* -------------------------------------------------------------------- */
/* Screen Thumbnail Preview */
@@ -540,65 +543,65 @@ void ED_screen_draw_split_preview(ScrArea *sa, const int dir, const float fac)
* Calculates a scale factor to squash the preview for \a screen into a rectangle of given size and aspect.
*/
static void screen_preview_scale_get(
- const bScreen *screen, float size_x, float size_y,
- const float asp[2],
- float r_scale[2])
+ const bScreen *screen, float size_x, float size_y, const float asp[2], float r_scale[2])
{
- 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);
- }
- r_scale[0] = (size_x * asp[0]) / max_x;
- r_scale[1] = (size_y * asp[1]) / max_y;
+ 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);
+ }
+ r_scale[0] = (size_x * asp[0]) / max_x;
+ r_scale[1] = (size_y * asp[1]) / max_y;
}
-static void screen_preview_draw_areas(const bScreen *screen, const float scale[2], const float col[4],
+static void screen_preview_draw_areas(const bScreen *screen,
+ const float scale[2],
+ const float col[4],
const float ofs_between_areas)
{
- const float ofs_h = ofs_between_areas * 0.5f;
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4fv(col);
-
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- 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,
- };
-
- immBegin(GPU_PRIM_TRI_FAN, 4);
- immVertex2f(pos, rect.xmin, rect.ymin);
- immVertex2f(pos, rect.xmax, rect.ymin);
- immVertex2f(pos, rect.xmax, rect.ymax);
- immVertex2f(pos, rect.xmin, rect.ymax);
- immEnd();
- }
-
- immUnbindProgram();
+ const float ofs_h = ofs_between_areas * 0.5f;
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(col);
+
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ 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,
+ };
+
+ immBegin(GPU_PRIM_TRI_FAN, 4);
+ immVertex2f(pos, rect.xmin, rect.ymin);
+ immVertex2f(pos, rect.xmax, rect.ymin);
+ immVertex2f(pos, rect.xmax, rect.ymax);
+ immVertex2f(pos, rect.xmin, rect.ymax);
+ immEnd();
+ }
+
+ immUnbindProgram();
}
static void screen_preview_draw(const bScreen *screen, int size_x, int size_y)
{
- const float asp[2] = {1.0f, 0.8f}; /* square previews look a bit ugly */
- /* could use theme color (tui.wcol_menu_item.text), but then we'd need to regenerate all previews when changing */
- const float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
- float scale[2];
+ const float asp[2] = {1.0f, 0.8f}; /* square previews look a bit ugly */
+ /* could use theme color (tui.wcol_menu_item.text), but then we'd need to regenerate all previews when changing */
+ const float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ float scale[2];
- wmOrtho2(0.0f, size_x, 0.0f, size_y);
- /* center */
- GPU_matrix_push();
- GPU_matrix_identity_set();
- GPU_matrix_translate_2f(size_x * (1.0f - asp[0]) * 0.5f, size_y * (1.0f - asp[1]) * 0.5f);
+ wmOrtho2(0.0f, size_x, 0.0f, size_y);
+ /* center */
+ GPU_matrix_push();
+ GPU_matrix_identity_set();
+ GPU_matrix_translate_2f(size_x * (1.0f - asp[0]) * 0.5f, size_y * (1.0f - asp[1]) * 0.5f);
- screen_preview_scale_get(screen, size_x, size_y, asp, scale);
- screen_preview_draw_areas(screen, scale, col, 1.5f);
+ screen_preview_scale_get(screen, size_x, size_y, asp, scale);
+ screen_preview_draw_areas(screen, scale, col, 1.5f);
- GPU_matrix_pop();
+ GPU_matrix_pop();
}
/**
@@ -606,17 +609,17 @@ static void screen_preview_draw(const bScreen *screen, int size_x, int size_y)
*/
void ED_screen_preview_render(const bScreen *screen, int size_x, int size_y, unsigned int *r_rect)
{
- char err_out[256] = "unknown";
- GPUOffScreen *offscreen = GPU_offscreen_create(size_x, size_y, 0, true, false, err_out);
+ char err_out[256] = "unknown";
+ GPUOffScreen *offscreen = GPU_offscreen_create(size_x, size_y, 0, true, false, err_out);
- GPU_offscreen_bind(offscreen, true);
- GPU_clear_color(0.0, 0.0, 0.0, 0.0);
- GPU_clear(GPU_COLOR_BIT | GPU_DEPTH_BIT);
+ GPU_offscreen_bind(offscreen, true);
+ GPU_clear_color(0.0, 0.0, 0.0, 0.0);
+ GPU_clear(GPU_COLOR_BIT | GPU_DEPTH_BIT);
- screen_preview_draw(screen, size_x, size_y);
+ screen_preview_draw(screen, size_x, size_y);
- GPU_offscreen_read_pixels(offscreen, GL_UNSIGNED_BYTE, r_rect);
- GPU_offscreen_unbind(offscreen, true);
+ GPU_offscreen_read_pixels(offscreen, GL_UNSIGNED_BYTE, r_rect);
+ GPU_offscreen_unbind(offscreen, true);
- GPU_offscreen_free(offscreen);
+ GPU_offscreen_free(offscreen);
}
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 031eee3c9a4..8caa960bb9a 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -21,11 +21,9 @@
* \ingroup edscr
*/
-
#include <string.h>
#include <math.h>
-
#include "MEM_guardedalloc.h"
#include "DNA_object_types.h"
@@ -64,136 +62,140 @@
#include "DEG_depsgraph_query.h"
-#include "screen_intern.h" /* own module include */
-
+#include "screen_intern.h" /* own module include */
/* adds no space data */
-static ScrArea *screen_addarea_ex(
- ScrAreaMap *area_map,
- ScrVert *bottom_left, ScrVert *top_left, ScrVert *top_right, ScrVert *bottom_right,
- short spacetype)
+static ScrArea *screen_addarea_ex(ScrAreaMap *area_map,
+ ScrVert *bottom_left,
+ ScrVert *top_left,
+ ScrVert *top_right,
+ ScrVert *bottom_right,
+ short spacetype)
{
- ScrArea *sa = MEM_callocN(sizeof(ScrArea), "addscrarea");
+ ScrArea *sa = MEM_callocN(sizeof(ScrArea), "addscrarea");
- sa->v1 = bottom_left;
- sa->v2 = top_left;
- sa->v3 = top_right;
- sa->v4 = bottom_right;
- sa->spacetype = spacetype;
+ sa->v1 = bottom_left;
+ sa->v2 = top_left;
+ sa->v3 = top_right;
+ sa->v4 = bottom_right;
+ sa->spacetype = spacetype;
- BLI_addtail(&area_map->areabase, sa);
+ BLI_addtail(&area_map->areabase, sa);
- return sa;
+ return sa;
}
-static ScrArea *screen_addarea(
- bScreen *sc,
- ScrVert *left_bottom, ScrVert *left_top, ScrVert *right_top, ScrVert *right_bottom,
- short spacetype)
+static ScrArea *screen_addarea(bScreen *sc,
+ ScrVert *left_bottom,
+ ScrVert *left_top,
+ ScrVert *right_top,
+ ScrVert *right_bottom,
+ short spacetype)
{
- return screen_addarea_ex(AREAMAP_FROM_SCREEN(sc), left_bottom, left_top, right_top, right_bottom,
- spacetype);
+ return screen_addarea_ex(
+ AREAMAP_FROM_SCREEN(sc), left_bottom, left_top, right_top, right_bottom, spacetype);
}
static void screen_delarea(bContext *C, bScreen *sc, ScrArea *sa)
{
- ED_area_exit(C, sa);
+ ED_area_exit(C, sa);
- BKE_screen_area_free(sa);
+ BKE_screen_area_free(sa);
- BLI_remlink(&sc->areabase, sa);
- MEM_freeN(sa);
+ BLI_remlink(&sc->areabase, sa);
+ MEM_freeN(sa);
}
ScrArea *area_split(const wmWindow *win, bScreen *sc, ScrArea *sa, char dir, float fac, int merge)
{
- ScrArea *newa = NULL;
- ScrVert *sv1, *sv2;
- short split;
- rcti window_rect;
-
- if (sa == NULL) return NULL;
-
- WM_window_rect_calc(win, &window_rect);
-
- split = screen_geom_find_area_split_point(sa, &window_rect, dir, fac);
- if (split == 0) return NULL;
-
- /* note regarding (fac > 0.5f) checks below.
- * normally it shouldn't matter which is used since the copy should match the original
- * however with viewport rendering and python console this isn't the case. - campbell */
-
- 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);
-
- /* 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);
-
- if (fac > 0.5f) {
- /* new areas: top */
- newa = screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->spacetype);
-
- /* area below */
- sa->v2 = sv1;
- sa->v3 = sv2;
- }
- else {
- /* new areas: bottom */
- newa = screen_addarea(sc, sa->v1, sv1, sv2, sa->v4, sa->spacetype);
-
- /* area above */
- sa->v1 = sv1;
- sa->v4 = sv2;
- }
-
- ED_area_data_copy(newa, sa, 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);
-
- /* 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);
-
- if (fac > 0.5f) {
- /* new areas: right */
- newa = screen_addarea(sc, sv1, sv2, sa->v3, sa->v4, sa->spacetype);
-
- /* area left */
- sa->v3 = sv2;
- sa->v4 = sv1;
- }
- else {
- /* new areas: left */
- newa = screen_addarea(sc, sa->v1, sa->v2, sv2, sv1, sa->spacetype);
-
- /* area right */
- sa->v1 = sv1;
- sa->v2 = sv2;
- }
-
- ED_area_data_copy(newa, sa, true);
- }
-
- /* remove double vertices en edges */
- if (merge)
- BKE_screen_remove_double_scrverts(sc);
- BKE_screen_remove_double_scredges(sc);
- BKE_screen_remove_unused_scredges(sc);
-
- return newa;
+ ScrArea *newa = NULL;
+ ScrVert *sv1, *sv2;
+ short split;
+ rcti window_rect;
+
+ if (sa == NULL)
+ return NULL;
+
+ WM_window_rect_calc(win, &window_rect);
+
+ split = screen_geom_find_area_split_point(sa, &window_rect, dir, fac);
+ if (split == 0)
+ return NULL;
+
+ /* note regarding (fac > 0.5f) checks below.
+ * normally it shouldn't matter which is used since the copy should match the original
+ * however with viewport rendering and python console this isn't the case. - campbell */
+
+ 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);
+
+ /* 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);
+
+ if (fac > 0.5f) {
+ /* new areas: top */
+ newa = screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->spacetype);
+
+ /* area below */
+ sa->v2 = sv1;
+ sa->v3 = sv2;
+ }
+ else {
+ /* new areas: bottom */
+ newa = screen_addarea(sc, sa->v1, sv1, sv2, sa->v4, sa->spacetype);
+
+ /* area above */
+ sa->v1 = sv1;
+ sa->v4 = sv2;
+ }
+
+ ED_area_data_copy(newa, sa, 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);
+
+ /* 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);
+
+ if (fac > 0.5f) {
+ /* new areas: right */
+ newa = screen_addarea(sc, sv1, sv2, sa->v3, sa->v4, sa->spacetype);
+
+ /* area left */
+ sa->v3 = sv2;
+ sa->v4 = sv1;
+ }
+ else {
+ /* new areas: left */
+ newa = screen_addarea(sc, sa->v1, sa->v2, sv2, sv1, sa->spacetype);
+
+ /* area right */
+ sa->v1 = sv1;
+ sa->v2 = sv2;
+ }
+
+ ED_area_data_copy(newa, sa, true);
+ }
+
+ /* remove double vertices en edges */
+ if (merge)
+ BKE_screen_remove_double_scrverts(sc);
+ BKE_screen_remove_double_scredges(sc);
+ BKE_screen_remove_unused_scredges(sc);
+
+ return newa;
}
/**
@@ -201,74 +203,74 @@ 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;
- ScrVert *sv1, *sv2, *sv3, *sv4;
+ bScreen *sc;
+ 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;
+ sc = BKE_libblock_alloc(bmain, ID_SCR, name, 0);
+ sc->do_refresh = true;
+ sc->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(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);
- 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(sc, sv1, sv2);
+ screen_geom_edge_add(sc, sv2, sv3);
+ screen_geom_edge_add(sc, sv3, sv4);
+ screen_geom_edge_add(sc, sv4, sv1);
- /* dummy type, no spacedata */
- screen_addarea(sc, sv1, sv2, sv3, sv4, SPACE_EMPTY);
+ /* dummy type, no spacedata */
+ screen_addarea(sc, sv1, sv2, sv3, sv4, SPACE_EMPTY);
- return sc;
+ return sc;
}
void screen_data_copy(bScreen *to, bScreen *from)
{
- ScrVert *s1, *s2;
- ScrEdge *se;
- ScrArea *sa, *saf;
-
- /* free contents of 'to', is from blenkernel screen.c */
- BKE_screen_free(to);
-
- to->flag = from->flag;
-
- BLI_duplicatelist(&to->vertbase, &from->vertbase);
- BLI_duplicatelist(&to->edgebase, &from->edgebase);
- BLI_duplicatelist(&to->areabase, &from->areabase);
- BLI_listbase_clear(&to->regionbase);
-
- s2 = to->vertbase.first;
- for (s1 = from->vertbase.first; s1; s1 = s1->next, s2 = s2->next) {
- s1->newv = s2;
- }
-
- for (se = to->edgebase.first; se; se = se->next) {
- se->v1 = se->v1->newv;
- se->v2 = se->v2->newv;
- BKE_screen_sort_scrvert(&(se->v1), &(se->v2));
- }
-
- 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;
-
- BLI_listbase_clear(&sa->spacedata);
- BLI_listbase_clear(&sa->regionbase);
- BLI_listbase_clear(&sa->actionzones);
- BLI_listbase_clear(&sa->handlers);
-
- ED_area_data_copy(sa, saf, true);
- }
-
- /* put at zero (needed?) */
- for (s1 = from->vertbase.first; s1; s1 = s1->next)
- s1->newv = NULL;
+ ScrVert *s1, *s2;
+ ScrEdge *se;
+ ScrArea *sa, *saf;
+
+ /* free contents of 'to', is from blenkernel screen.c */
+ BKE_screen_free(to);
+
+ to->flag = from->flag;
+
+ BLI_duplicatelist(&to->vertbase, &from->vertbase);
+ BLI_duplicatelist(&to->edgebase, &from->edgebase);
+ BLI_duplicatelist(&to->areabase, &from->areabase);
+ BLI_listbase_clear(&to->regionbase);
+
+ s2 = to->vertbase.first;
+ for (s1 = from->vertbase.first; s1; s1 = s1->next, s2 = s2->next) {
+ s1->newv = s2;
+ }
+
+ for (se = to->edgebase.first; se; se = se->next) {
+ se->v1 = se->v1->newv;
+ se->v2 = se->v2->newv;
+ BKE_screen_sort_scrvert(&(se->v1), &(se->v2));
+ }
+
+ 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;
+
+ BLI_listbase_clear(&sa->spacedata);
+ BLI_listbase_clear(&sa->regionbase);
+ BLI_listbase_clear(&sa->actionzones);
+ BLI_listbase_clear(&sa->handlers);
+
+ ED_area_data_copy(sa, saf, true);
+ }
+
+ /* put at zero (needed?) */
+ for (s1 = from->vertbase.first; s1; s1 = s1->next)
+ s1->newv = NULL;
}
/**
@@ -276,45 +278,45 @@ void screen_data_copy(bScreen *to, bScreen *from)
*/
void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new)
{
- screen_new->winid = win->winid;
- screen_new->do_refresh = true;
- screen_new->do_draw = true;
+ screen_new->winid = win->winid;
+ screen_new->do_refresh = true;
+ screen_new->do_draw = true;
}
-
/* with sa 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)
{
- ScrVert *sav1, *sav2, *sav3, *sav4;
- ScrVert *sbv1, *sbv2, *sbv3, *sbv4;
-
- if (sa == NULL || sb == NULL) return -1;
-
- sav1 = sa->v1;
- sav2 = sa->v2;
- sav3 = sa->v3;
- sav4 = sa->v4;
- sbv1 = sb->v1;
- sbv2 = sb->v2;
- sbv3 = sb->v3;
- sbv4 = sb->v4;
-
- if (sav1 == sbv4 && sav2 == sbv3) { /* sa to right of sb = W */
- return 0;
- }
- else if (sav2 == sbv1 && sav3 == sbv4) { /* sa to bottom of sb = N */
- return 1;
- }
- else if (sav3 == sbv2 && sav4 == sbv1) { /* sa to left of sb = E */
- return 2;
- }
- else if (sav1 == sbv2 && sav4 == sbv3) { /* sa on top of sb = S*/
- return 3;
- }
-
- return -1;
+ ScrVert *sav1, *sav2, *sav3, *sav4;
+ ScrVert *sbv1, *sbv2, *sbv3, *sbv4;
+
+ if (sa == NULL || sb == NULL)
+ return -1;
+
+ sav1 = sa->v1;
+ sav2 = sa->v2;
+ sav3 = sa->v3;
+ sav4 = sa->v4;
+ sbv1 = sb->v1;
+ sbv2 = sb->v2;
+ sbv3 = sb->v3;
+ sbv4 = sb->v4;
+
+ if (sav1 == sbv4 && sav2 == sbv3) { /* sa to right of sb = W */
+ return 0;
+ }
+ else if (sav2 == sbv1 && sav3 == sbv4) { /* sa to bottom of sb = N */
+ return 1;
+ }
+ else if (sav3 == sbv2 && sav4 == sbv1) { /* sa to left of sb = E */
+ return 2;
+ }
+ else if (sav1 == sbv2 && sav4 == sbv3) { /* sa on top of sb = S*/
+ return 3;
+ }
+
+ return -1;
}
/* Helper function to join 2 areas, it has a return value, 0=failed 1=success
@@ -322,272 +324,273 @@ int area_getorientation(ScrArea *sa, ScrArea *sb)
*/
int screen_area_join(bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2)
{
- int dir;
-
- dir = area_getorientation(sa1, sa2);
- /*printf("dir is : %i\n", dir);*/
-
- if (dir == -1) {
- return 0;
- }
-
- if (dir == 0) {
- sa1->v1 = sa2->v1;
- sa1->v2 = sa2->v2;
- screen_geom_edge_add(scr, sa1->v2, sa1->v3);
- screen_geom_edge_add(scr, sa1->v1, sa1->v4);
- }
- else if (dir == 1) {
- sa1->v2 = sa2->v2;
- sa1->v3 = sa2->v3;
- screen_geom_edge_add(scr, sa1->v1, sa1->v2);
- screen_geom_edge_add(scr, sa1->v3, sa1->v4);
- }
- else if (dir == 2) {
- sa1->v3 = sa2->v3;
- sa1->v4 = sa2->v4;
- screen_geom_edge_add(scr, sa1->v2, sa1->v3);
- screen_geom_edge_add(scr, sa1->v1, sa1->v4);
- }
- else if (dir == 3) {
- sa1->v1 = sa2->v1;
- sa1->v4 = sa2->v4;
- screen_geom_edge_add(scr, sa1->v1, sa1->v2);
- screen_geom_edge_add(scr, sa1->v3, sa1->v4);
- }
-
- screen_delarea(C, scr, sa2);
- BKE_screen_remove_double_scrverts(scr);
- /* Update preview thumbnail */
- BKE_icon_changed(scr->id.icon_id);
-
- return 1;
+ int dir;
+
+ dir = area_getorientation(sa1, sa2);
+ /*printf("dir is : %i\n", dir);*/
+
+ if (dir == -1) {
+ return 0;
+ }
+
+ if (dir == 0) {
+ sa1->v1 = sa2->v1;
+ sa1->v2 = sa2->v2;
+ screen_geom_edge_add(scr, sa1->v2, sa1->v3);
+ screen_geom_edge_add(scr, sa1->v1, sa1->v4);
+ }
+ else if (dir == 1) {
+ sa1->v2 = sa2->v2;
+ sa1->v3 = sa2->v3;
+ screen_geom_edge_add(scr, sa1->v1, sa1->v2);
+ screen_geom_edge_add(scr, sa1->v3, sa1->v4);
+ }
+ else if (dir == 2) {
+ sa1->v3 = sa2->v3;
+ sa1->v4 = sa2->v4;
+ screen_geom_edge_add(scr, sa1->v2, sa1->v3);
+ screen_geom_edge_add(scr, sa1->v1, sa1->v4);
+ }
+ else if (dir == 3) {
+ sa1->v1 = sa2->v1;
+ sa1->v4 = sa2->v4;
+ screen_geom_edge_add(scr, sa1->v1, sa1->v2);
+ screen_geom_edge_add(scr, sa1->v3, sa1->v4);
+ }
+
+ screen_delarea(C, scr, sa2);
+ BKE_screen_remove_double_scrverts(scr);
+ /* Update preview thumbnail */
+ BKE_icon_changed(scr->id.icon_id);
+
+ return 1;
}
-
/* ****************** EXPORTED API TO OTHER MODULES *************************** */
/* screen sets cursor based on active 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);
- }
- return;
- }
- }
- }
+ 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);
+ }
+ return;
+ }
+ }
+ }
}
void ED_screen_do_listen(bContext *C, wmNotifier *note)
{
- wmWindow *win = CTX_wm_window(C);
- bScreen *screen = CTX_wm_screen(C);
-
- /* generic notes */
- switch (note->category) {
- case NC_WM:
- if (note->data == ND_FILEREAD)
- screen->do_draw = true;
- break;
- case NC_WINDOW:
- screen->do_draw = true;
- break;
- case NC_SCREEN:
- if (note->action == NA_EDITED)
- screen->do_draw = screen->do_refresh = true;
- break;
- case NC_SCENE:
- if (note->data == ND_MODE)
- region_cursor_set(win, true);
- break;
- }
+ wmWindow *win = CTX_wm_window(C);
+ bScreen *screen = CTX_wm_screen(C);
+
+ /* generic notes */
+ switch (note->category) {
+ case NC_WM:
+ if (note->data == ND_FILEREAD)
+ screen->do_draw = true;
+ break;
+ case NC_WINDOW:
+ screen->do_draw = true;
+ break;
+ case NC_SCREEN:
+ if (note->action == NA_EDITED)
+ screen->do_draw = screen->do_refresh = true;
+ break;
+ case NC_SCENE:
+ if (note->data == ND_MODE)
+ region_cursor_set(win, true);
+ break;
+ }
}
/* helper call for below, dpi changes headers */
static void screen_refresh_headersizes(void)
{
- const ListBase *lb = BKE_spacetypes_list();
- SpaceType *st;
-
- for (st = lb->first; st; st = st->next) {
- ARegionType *art;
- art = BKE_regiontype_from_id(st, RGN_TYPE_HEADER);
- if (art) art->prefsizey = ED_area_headersize();
-
- art = BKE_regiontype_from_id(st, RGN_TYPE_FOOTER);
- if (art) art->prefsizey = ED_area_headersize();
- }
+ const ListBase *lb = BKE_spacetypes_list();
+ SpaceType *st;
+
+ for (st = lb->first; st; st = st->next) {
+ ARegionType *art;
+ art = BKE_regiontype_from_id(st, RGN_TYPE_HEADER);
+ if (art)
+ art->prefsizey = ED_area_headersize();
+
+ art = BKE_regiontype_from_id(st, RGN_TYPE_FOOTER);
+ if (art)
+ art->prefsizey = ED_area_headersize();
+ }
}
/* make this screen usable */
/* for file read and first use, for scaling window, area moves */
void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
{
- bScreen *screen = WM_window_get_active_screen(win);
-
- /* exception for bg mode, we only need the screen context */
- if (!G.background) {
- /* header size depends on DPI, let's verify */
- WM_window_set_dpi(win);
-
- ED_screen_global_areas_refresh(win);
- screen_refresh_headersizes();
-
- screen_geom_vertices_scale(win, screen);
-
- 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);
- }
-
- /* wake up animtimer */
- if (screen->animtimer)
- WM_event_timer_sleep(wm, win, screen->animtimer, false);
- }
-
- if (G.debug & G_DEBUG_EVENTS) {
- printf("%s: set screen\n", __func__);
- }
- screen->do_refresh = false;
- /* prevent multiwin errors */
- screen->winid = win->winid;
-
- screen->context = ed_screen_context;
+ bScreen *screen = WM_window_get_active_screen(win);
+
+ /* exception for bg mode, we only need the screen context */
+ if (!G.background) {
+ /* header size depends on DPI, let's verify */
+ WM_window_set_dpi(win);
+
+ ED_screen_global_areas_refresh(win);
+ screen_refresh_headersizes();
+
+ screen_geom_vertices_scale(win, screen);
+
+ 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);
+ }
+
+ /* wake up animtimer */
+ if (screen->animtimer)
+ WM_event_timer_sleep(wm, win, screen->animtimer, false);
+ }
+
+ if (G.debug & G_DEBUG_EVENTS) {
+ printf("%s: set screen\n", __func__);
+ }
+ screen->do_refresh = false;
+ /* prevent multiwin errors */
+ screen->winid = win->winid;
+
+ screen->context = ed_screen_context;
}
/* file read, set all screens, ... */
void ED_screens_initialize(Main *bmain, wmWindowManager *wm)
{
- wmWindow *win;
-
- for (win = wm->windows.first; win; win = win->next) {
- if (BKE_workspace_active_get(win->workspace_hook) == NULL) {
- BKE_workspace_active_set(win->workspace_hook, bmain->workspaces.first);
- }
-
- ED_screen_refresh(wm, win);
- if (win->eventstate) {
- ED_screen_set_active_region(NULL, win, &win->eventstate->x);
- }
- }
-
- if (U.uiflag & USER_HEADER_FROM_PREF) {
- for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
- BKE_screen_header_alignment_reset(screen);
- }
- }
+ wmWindow *win;
+
+ for (win = wm->windows.first; win; win = win->next) {
+ if (BKE_workspace_active_get(win->workspace_hook) == NULL) {
+ BKE_workspace_active_set(win->workspace_hook, bmain->workspaces.first);
+ }
+
+ ED_screen_refresh(wm, win);
+ if (win->eventstate) {
+ ED_screen_set_active_region(NULL, win, &win->eventstate->x);
+ }
+ }
+
+ if (U.uiflag & USER_HEADER_FROM_PREF) {
+ for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
+ BKE_screen_header_alignment_reset(screen);
+ }
+ }
}
void ED_screen_ensure_updated(wmWindowManager *wm, wmWindow *win, bScreen *screen)
{
- if (screen->do_refresh) {
- ED_screen_refresh(wm, win);
- }
+ if (screen->do_refresh) {
+ ED_screen_refresh(wm, win);
+ }
}
-
/* *********** exit calls are for closing running stuff ******** */
void ED_region_exit(bContext *C, ARegion *ar)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
- ARegion *prevar = CTX_wm_region(C);
+ 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 (ar->type && ar->type->exit)
+ ar->type->exit(wm, ar);
- CTX_wm_region_set(C, ar);
+ CTX_wm_region_set(C, ar);
- 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, &ar->handlers);
+ WM_event_modal_handler_region_replace(win, ar, NULL);
+ WM_draw_region_free(ar);
- if (ar->headerstr) {
- MEM_freeN(ar->headerstr);
- ar->headerstr = NULL;
- }
+ if (ar->headerstr) {
+ MEM_freeN(ar->headerstr);
+ ar->headerstr = NULL;
+ }
- if (ar->regiontimer) {
- WM_event_remove_timer(wm, win, ar->regiontimer);
- ar->regiontimer = NULL;
- }
+ if (ar->regiontimer) {
+ WM_event_remove_timer(wm, win, ar->regiontimer);
+ ar->regiontimer = NULL;
+ }
- WM_msgbus_clear_by_owner(wm->message_bus, ar);
+ WM_msgbus_clear_by_owner(wm->message_bus, ar);
- CTX_wm_region_set(C, prevar);
+ CTX_wm_region_set(C, prevar);
}
void ED_area_exit(bContext *C, ScrArea *sa)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
- ScrArea *prevsa = CTX_wm_area(C);
- ARegion *ar;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *prevsa = CTX_wm_area(C);
+ ARegion *ar;
- if (sa->type && sa->type->exit)
- sa->type->exit(wm, sa);
+ if (sa->type && sa->type->exit)
+ sa->type->exit(wm, sa);
- CTX_wm_area_set(C, sa);
+ CTX_wm_area_set(C, sa);
- for (ar = sa->regionbase.first; ar; ar = ar->next)
- ED_region_exit(C, ar);
+ for (ar = sa->regionbase.first; ar; ar = ar->next)
+ ED_region_exit(C, ar);
- WM_event_remove_handlers(C, &sa->handlers);
- WM_event_modal_handler_area_replace(win, sa, NULL);
+ WM_event_remove_handlers(C, &sa->handlers);
+ WM_event_modal_handler_area_replace(win, sa, NULL);
- CTX_wm_area_set(C, prevsa);
+ CTX_wm_area_set(C, prevsa);
}
void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *prevwin = CTX_wm_window(C);
-
- CTX_wm_window_set(C, window);
-
- if (screen->animtimer)
- WM_event_remove_timer(wm, window, screen->animtimer);
- screen->animtimer = NULL;
- screen->scrubbing = false;
-
- screen->active_region = NULL;
-
- for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) {
- ED_region_exit(C, ar);
- }
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- ED_area_exit(C, sa);
- }
- /* 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);
- }
-
- /* mark it available for use for other windows */
- screen->winid = 0;
-
- if (!WM_window_is_temp_screen(prevwin)) {
- /* use previous window if possible */
- CTX_wm_window_set(C, prevwin);
- }
- else {
- /* none otherwise */
- CTX_wm_window_set(C, NULL);
- }
-
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *prevwin = CTX_wm_window(C);
+
+ CTX_wm_window_set(C, window);
+
+ if (screen->animtimer)
+ WM_event_remove_timer(wm, window, screen->animtimer);
+ screen->animtimer = NULL;
+ screen->scrubbing = false;
+
+ screen->active_region = NULL;
+
+ for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) {
+ ED_region_exit(C, ar);
+ }
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ ED_area_exit(C, sa);
+ }
+ /* 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);
+ }
+
+ /* mark it available for use for other windows */
+ screen->winid = 0;
+
+ if (!WM_window_is_temp_screen(prevwin)) {
+ /* use previous window if possible */
+ CTX_wm_window_set(C, prevwin);
+ }
+ else {
+ /* none otherwise */
+ CTX_wm_window_set(C, NULL);
+ }
}
/* *********************************** */
@@ -595,357 +598,364 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
/* case when on area-edge or in azones, or outside window */
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;
-
- for (sa = screen->areabase.first; sa; sa = sa->next)
- if ((az = ED_area_actionzone_find_xy(sa, xy)))
- break;
-
- if (sa) {
- if (az->type == AZONE_AREA)
- WM_cursor_set(win, CURSOR_EDIT);
- else if (az->type == AZONE_REGION) {
- if (az->edge == AE_LEFT_TO_TOPRIGHT || az->edge == AE_RIGHT_TO_TOPLEFT)
- WM_cursor_set(win, CURSOR_X_MOVE);
- else
- WM_cursor_set(win, CURSOR_Y_MOVE);
- }
- }
- else {
- ScrEdge *actedge = screen_geom_find_active_scredge(win, screen, xy[0], xy[1]);
-
- if (actedge) {
- if (screen_geom_edge_is_horizontal(actedge))
- WM_cursor_set(win, CURSOR_Y_MOVE);
- else
- WM_cursor_set(win, CURSOR_X_MOVE);
- }
- else
- WM_cursor_set(win, CURSOR_STD);
- }
+ const bScreen *screen = WM_window_get_active_screen(win);
+ AZone *az = NULL;
+ ScrArea *sa;
+
+ for (sa = screen->areabase.first; sa; sa = sa->next)
+ if ((az = ED_area_actionzone_find_xy(sa, xy)))
+ break;
+
+ if (sa) {
+ if (az->type == AZONE_AREA)
+ WM_cursor_set(win, CURSOR_EDIT);
+ else if (az->type == AZONE_REGION) {
+ if (az->edge == AE_LEFT_TO_TOPRIGHT || az->edge == AE_RIGHT_TO_TOPLEFT)
+ WM_cursor_set(win, CURSOR_X_MOVE);
+ else
+ WM_cursor_set(win, CURSOR_Y_MOVE);
+ }
+ }
+ else {
+ ScrEdge *actedge = screen_geom_find_active_scredge(win, screen, xy[0], xy[1]);
+
+ if (actedge) {
+ if (screen_geom_edge_is_horizontal(actedge))
+ WM_cursor_set(win, CURSOR_Y_MOVE);
+ else
+ WM_cursor_set(win, CURSOR_X_MOVE);
+ }
+ else
+ WM_cursor_set(win, CURSOR_STD);
+ }
}
-
/* 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 (BLI_rcti_isect_pt_v(&ar->winrct, xy)) {
- scr->active_region = ar;
- break;
- }
- }
- }
- else
- scr->active_region = NULL;
-
- /* check for redraw headers */
- if (old_ar != scr->active_region) {
-
- ED_screen_areas_iter(win, scr, area_iter) {
- bool do_draw = false;
-
- for (ar = area_iter->regionbase.first; ar; ar = ar->next) {
- if (ar == old_ar || ar == scr->active_region) {
- do_draw = true;
- }
- }
-
- if (do_draw) {
- for (ar = area_iter->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_HEADER) {
- ED_region_tag_redraw_no_rebuild(ar);
- }
- }
- }
- }
- }
-
- /* 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);
- }
- }
+ 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 (BLI_rcti_isect_pt_v(&ar->winrct, xy)) {
+ scr->active_region = ar;
+ break;
+ }
+ }
+ }
+ else
+ scr->active_region = NULL;
+
+ /* check for redraw headers */
+ if (old_ar != scr->active_region) {
+
+ ED_screen_areas_iter(win, scr, area_iter)
+ {
+ bool do_draw = false;
+
+ for (ar = area_iter->regionbase.first; ar; ar = ar->next) {
+ if (ar == old_ar || ar == scr->active_region) {
+ do_draw = true;
+ }
+ }
+
+ if (do_draw) {
+ for (ar = area_iter->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_HEADER) {
+ ED_region_tag_redraw_no_rebuild(ar);
+ }
+ }
+ }
+ }
+ }
+
+ /* 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);
+ }
+ }
}
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);
-
- if (win && sc && sa) {
- AZone *az = ED_area_actionzone_find_xy(sa, &win->eventstate->x);
- ARegion *ar;
-
- if (az && az->type == AZONE_REGION)
- return 1;
-
- for (ar = sa->regionbase.first; ar; ar = ar->next)
- if (ar == sc->active_region)
- return 1;
- }
- return 0;
+ wmWindow *win = CTX_wm_window(C);
+ bScreen *sc = CTX_wm_screen(C);
+ ScrArea *sa = CTX_wm_area(C);
+
+ if (win && sc && sa) {
+ AZone *az = ED_area_actionzone_find_xy(sa, &win->eventstate->x);
+ ARegion *ar;
+
+ if (az && az->type == AZONE_REGION)
+ return 1;
+
+ for (ar = sa->regionbase.first; ar; ar = ar->next)
+ if (ar == sc->active_region)
+ return 1;
+ }
+ return 0;
}
/**
* Add an area and geometry (screen-edges and -vertices) for it to \a area_map,
* with coordinates/dimensions matching \a rect.
*/
-static ScrArea *screen_area_create_with_geometry(
- ScrAreaMap *area_map, const rcti *rect,
- short spacetype)
+static ScrArea *screen_area_create_with_geometry(ScrAreaMap *area_map,
+ const rcti *rect,
+ short spacetype)
{
- ScrVert *bottom_left = screen_geom_vertex_add_ex(area_map, rect->xmin, rect->ymin);
- ScrVert *top_left = screen_geom_vertex_add_ex(area_map, rect->xmin, rect->ymax);
- ScrVert *top_right = screen_geom_vertex_add_ex(area_map, rect->xmax, rect->ymax);
- ScrVert *bottom_right = screen_geom_vertex_add_ex(area_map, rect->xmax, rect->ymin);
+ ScrVert *bottom_left = screen_geom_vertex_add_ex(area_map, rect->xmin, rect->ymin);
+ ScrVert *top_left = screen_geom_vertex_add_ex(area_map, rect->xmin, rect->ymax);
+ ScrVert *top_right = screen_geom_vertex_add_ex(area_map, rect->xmax, rect->ymax);
+ ScrVert *bottom_right = screen_geom_vertex_add_ex(area_map, rect->xmax, rect->ymin);
- screen_geom_edge_add_ex(area_map, bottom_left, top_left);
- screen_geom_edge_add_ex(area_map, top_left, top_right);
- screen_geom_edge_add_ex(area_map, top_right, bottom_right);
- screen_geom_edge_add_ex(area_map, bottom_right, bottom_left);
+ screen_geom_edge_add_ex(area_map, bottom_left, top_left);
+ screen_geom_edge_add_ex(area_map, top_left, top_right);
+ screen_geom_edge_add_ex(area_map, top_right, bottom_right);
+ screen_geom_edge_add_ex(area_map, bottom_right, bottom_left);
- return screen_addarea_ex(area_map, bottom_left, top_left, top_right, bottom_right, spacetype);
+ 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)
{
- 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;
+ 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;
}
-static void screen_global_area_refresh(
- wmWindow *win, bScreen *screen,
- eSpace_Type space_type, GlobalAreaAlign align, const rcti *rect,
- const short height_cur, const short height_min, const short height_max)
+static void screen_global_area_refresh(wmWindow *win,
+ bScreen *screen,
+ eSpace_Type space_type,
+ GlobalAreaAlign align,
+ const rcti *rect,
+ const short height_cur,
+ const short height_min,
+ const short height_max)
{
- ScrArea *area;
-
- for (area = win->global_areas.areabase.first; area; area = area->next) {
- if (area->spacetype == space_type) {
- break;
- }
- }
-
- if (area) {
- screen_area_set_geometry_rect(area, rect);
- }
- else {
- area = screen_area_create_with_geometry(&win->global_areas, rect, space_type);
- SpaceType *stype = BKE_spacetype_from_id(space_type);
- SpaceLink *slink = stype->new(area, WM_window_get_active_scene(win));
-
- area->regionbase = slink->regionbase;
-
- BLI_addhead(&area->spacedata, slink);
- BLI_listbase_clear(&slink->regionbase);
-
- /* Data specific to global areas. */
- area->global = MEM_callocN(sizeof(*area->global), __func__);
- area->global->size_max = height_max;
- area->global->size_min = height_min;
- area->global->align = align;
- }
-
- if (area->global->cur_fixed_height != height_cur) {
- /* Refresh layout if size changes. */
- area->global->cur_fixed_height = height_cur;
- screen->do_refresh = true;
- }
+ ScrArea *area;
+
+ for (area = win->global_areas.areabase.first; area; area = area->next) {
+ if (area->spacetype == space_type) {
+ break;
+ }
+ }
+
+ if (area) {
+ screen_area_set_geometry_rect(area, rect);
+ }
+ else {
+ area = screen_area_create_with_geometry(&win->global_areas, rect, space_type);
+ SpaceType *stype = BKE_spacetype_from_id(space_type);
+ SpaceLink *slink = stype->new (area, WM_window_get_active_scene(win));
+
+ area->regionbase = slink->regionbase;
+
+ BLI_addhead(&area->spacedata, slink);
+ BLI_listbase_clear(&slink->regionbase);
+
+ /* Data specific to global areas. */
+ area->global = MEM_callocN(sizeof(*area->global), __func__);
+ area->global->size_max = height_max;
+ area->global->size_min = height_min;
+ area->global->align = align;
+ }
+
+ if (area->global->cur_fixed_height != height_cur) {
+ /* Refresh layout if size changes. */
+ area->global->cur_fixed_height = height_cur;
+ screen->do_refresh = true;
+ }
}
static int screen_global_header_size(void)
{
- return (int)ceilf(ED_area_headersize() / UI_DPI_FAC);
+ return (int)ceilf(ED_area_headersize() / UI_DPI_FAC);
}
static void screen_global_topbar_area_refresh(wmWindow *win, bScreen *screen)
{
- const short size_min = screen_global_header_size();
- const short size_max = 2.25 * screen_global_header_size();
- const short size = (screen->flag & SCREEN_COLLAPSE_TOPBAR) ? size_min : size_max;
- rcti rect;
+ const short size_min = screen_global_header_size();
+ const short size_max = 2.25 * screen_global_header_size();
+ const short size = (screen->flag & SCREEN_COLLAPSE_TOPBAR) ? size_min : size_max;
+ rcti rect;
- BLI_rcti_init(&rect, 0, WM_window_pixels_x(win) - 1, 0, WM_window_pixels_y(win) - 1);
- rect.ymin = rect.ymax - size_max;
+ BLI_rcti_init(&rect, 0, WM_window_pixels_x(win) - 1, 0, WM_window_pixels_y(win) - 1);
+ rect.ymin = rect.ymax - size_max;
- screen_global_area_refresh(win, screen, SPACE_TOPBAR, GLOBAL_AREA_ALIGN_TOP, &rect, size, size_min, size_max);
+ screen_global_area_refresh(
+ win, screen, SPACE_TOPBAR, GLOBAL_AREA_ALIGN_TOP, &rect, size, size_min, size_max);
}
static void screen_global_statusbar_area_refresh(wmWindow *win, bScreen *screen)
{
- const short size_min = 1;
- const short size_max = 0.8f * screen_global_header_size();
- const short size = (screen->flag & SCREEN_COLLAPSE_STATUSBAR) ? size_min : size_max;
- rcti rect;
+ const short size_min = 1;
+ const short size_max = 0.8f * screen_global_header_size();
+ const short size = (screen->flag & SCREEN_COLLAPSE_STATUSBAR) ? size_min : size_max;
+ rcti rect;
- BLI_rcti_init(&rect, 0, WM_window_pixels_x(win) - 1, 0, WM_window_pixels_y(win) - 1);
- rect.ymax = rect.ymin + size_max;
+ BLI_rcti_init(&rect, 0, WM_window_pixels_x(win) - 1, 0, WM_window_pixels_y(win) - 1);
+ rect.ymax = rect.ymin + size_max;
- screen_global_area_refresh(win, screen, SPACE_STATUSBAR, GLOBAL_AREA_ALIGN_BOTTOM, &rect, size, size_min, size_max);
+ screen_global_area_refresh(
+ win, screen, SPACE_STATUSBAR, GLOBAL_AREA_ALIGN_BOTTOM, &rect, size, size_min, size_max);
}
void ED_screen_global_areas_sync(wmWindow *win)
{
- /* Update screen flags from height in window, this is weak and perhaps
- * global areas should just become part of the screen instead. */
- bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
-
- screen->flag &= ~(SCREEN_COLLAPSE_STATUSBAR | SCREEN_COLLAPSE_TOPBAR);
-
- for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) {
- if (area->global->cur_fixed_height == area->global->size_min) {
- if (area->spacetype == SPACE_TOPBAR) {
- screen->flag |= SCREEN_COLLAPSE_TOPBAR;
- }
- else if (area->spacetype == SPACE_STATUSBAR) {
- screen->flag |= SCREEN_COLLAPSE_STATUSBAR;
- }
- }
- }
+ /* Update screen flags from height in window, this is weak and perhaps
+ * global areas should just become part of the screen instead. */
+ bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
+
+ screen->flag &= ~(SCREEN_COLLAPSE_STATUSBAR | SCREEN_COLLAPSE_TOPBAR);
+
+ for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) {
+ if (area->global->cur_fixed_height == area->global->size_min) {
+ if (area->spacetype == SPACE_TOPBAR) {
+ screen->flag |= SCREEN_COLLAPSE_TOPBAR;
+ }
+ else if (area->spacetype == SPACE_STATUSBAR) {
+ screen->flag |= SCREEN_COLLAPSE_STATUSBAR;
+ }
+ }
+ }
}
void ED_screen_global_areas_refresh(wmWindow *win)
{
- /* Don't create global area for child and temporary windows. */
- bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
- if ((win->parent != NULL) || screen->temp) {
- if (win->global_areas.areabase.first) {
- screen->do_refresh = true;
- BKE_screen_area_map_free(&win->global_areas);
- }
- return;
- }
-
- screen_global_topbar_area_refresh(win, screen);
- screen_global_statusbar_area_refresh(win, screen);
+ /* Don't create global area for child and temporary windows. */
+ bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
+ if ((win->parent != NULL) || screen->temp) {
+ if (win->global_areas.areabase.first) {
+ screen->do_refresh = true;
+ BKE_screen_area_map_free(&win->global_areas);
+ }
+ return;
+ }
+
+ screen_global_topbar_area_refresh(win, screen);
+ screen_global_statusbar_area_refresh(win, screen);
}
-
/* -------------------------------------------------------------------- */
/* Screen changing */
static bScreen *screen_fullscreen_find_associated_normal_screen(const Main *bmain, bScreen *screen)
{
- for (bScreen *screen_iter = bmain->screens.first; screen_iter; screen_iter = screen_iter->id.next) {
- ScrArea *sa = screen_iter->areabase.first;
- if (sa && sa->full == screen) {
- return screen_iter;
- }
- }
-
- return screen;
+ for (bScreen *screen_iter = bmain->screens.first; screen_iter;
+ screen_iter = screen_iter->id.next) {
+ ScrArea *sa = screen_iter->areabase.first;
+ if (sa && sa->full == screen) {
+ return screen_iter;
+ }
+ }
+
+ return screen;
}
/**
* \return the screen to activate.
* \warning The returned screen may not always equal \a screen_new!
*/
-bScreen *screen_change_prepare(bScreen *screen_old, bScreen *screen_new, Main *bmain, bContext *C, wmWindow *win)
+bScreen *screen_change_prepare(
+ bScreen *screen_old, bScreen *screen_new, Main *bmain, bContext *C, wmWindow *win)
{
- /* validate screen, it's called with notifier reference */
- if (BLI_findindex(&bmain->screens, screen_new) == -1) {
- return NULL;
- }
-
- if (ELEM(screen_new->state, SCREENMAXIMIZED, SCREENFULL)) {
- screen_new = screen_fullscreen_find_associated_normal_screen(bmain, screen_new);
- }
-
- /* check for valid winid */
- if (!(screen_new->winid == 0 || screen_new->winid == win->winid)) {
- return NULL;
- }
-
- if (screen_old != screen_new) {
- 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);
- }
-
- /* we put timer to sleep, so screen_exit has to think there's no timer */
- screen_old->animtimer = NULL;
- if (wt) {
- WM_event_timer_sleep(CTX_wm_manager(C), win, wt, true);
- }
- ED_screen_exit(C, win, screen_old);
-
- /* Same scene, "transfer" playback to new screen. */
- if (wt) {
- screen_new->animtimer = wt;
- }
-
- return screen_new;
- }
-
- return NULL;
+ /* validate screen, it's called with notifier reference */
+ if (BLI_findindex(&bmain->screens, screen_new) == -1) {
+ return NULL;
+ }
+
+ if (ELEM(screen_new->state, SCREENMAXIMIZED, SCREENFULL)) {
+ screen_new = screen_fullscreen_find_associated_normal_screen(bmain, screen_new);
+ }
+
+ /* check for valid winid */
+ if (!(screen_new->winid == 0 || screen_new->winid == win->winid)) {
+ return NULL;
+ }
+
+ if (screen_old != screen_new) {
+ 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);
+ }
+
+ /* we put timer to sleep, so screen_exit has to think there's no timer */
+ screen_old->animtimer = NULL;
+ if (wt) {
+ WM_event_timer_sleep(CTX_wm_manager(C), win, wt, true);
+ }
+ ED_screen_exit(C, win, screen_old);
+
+ /* Same scene, "transfer" playback to new screen. */
+ if (wt) {
+ screen_new->animtimer = wt;
+ }
+
+ return screen_new;
+ }
+
+ return NULL;
}
void screen_change_update(bContext *C, wmWindow *win, bScreen *sc)
{
- 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);
+ 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);
- CTX_wm_window_set(C, win); /* stores C->wm.screen... hrmf */
+ CTX_wm_window_set(C, win); /* stores C->wm.screen... hrmf */
- ED_screen_refresh(CTX_wm_manager(C), win);
+ ED_screen_refresh(CTX_wm_manager(C), win);
- BKE_screen_view3d_scene_sync(sc, 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);
+ BKE_screen_view3d_scene_sync(sc, 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);
+ /* makes button hilites work */
+ WM_event_add_mousemove(C);
}
-
/**
* \brief Change the active screen.
*
@@ -956,117 +966,117 @@ void screen_change_update(bContext *C, wmWindow *win, bScreen *sc)
*/
bool ED_screen_change(bContext *C, bScreen *sc)
{
- 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);
+ 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);
- if (screen_new) {
- WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
- WM_window_set_active_screen(win, workspace, sc);
- screen_change_update(C, win, screen_new);
+ if (screen_new) {
+ WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
+ WM_window_set_active_screen(win, workspace, sc);
+ screen_change_update(C, win, screen_new);
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
static void screen_set_3dview_camera(Scene *scene, ViewLayer *view_layer, ScrArea *sa, 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();
- if (!v3d->camera) {
- ARegion *ar;
- ListBase *regionbase;
-
- /* regionbase is in different place depending if space is active */
- if (v3d == sa->spacedata.first)
- regionbase = &sa->regionbase;
- else
- regionbase = &v3d->regionbase;
-
- for (ar = regionbase->first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = ar->regiondata;
- if (rv3d->persp == RV3D_CAMOB) {
- rv3d->persp = RV3D_PERSP;
- }
- }
- }
- }
- }
+ /* 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();
+ if (!v3d->camera) {
+ ARegion *ar;
+ ListBase *regionbase;
+
+ /* regionbase is in different place depending if space is active */
+ if (v3d == sa->spacedata.first)
+ regionbase = &sa->regionbase;
+ else
+ regionbase = &v3d->regionbase;
+
+ for (ar = regionbase->first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = ar->regiondata;
+ if (rv3d->persp == RV3D_CAMOB) {
+ rv3d->persp = RV3D_PERSP;
+ }
+ }
+ }
+ }
+ }
}
void ED_screen_scene_change(bContext *C, wmWindow *win, Scene *scene)
{
#if 0
- ViewLayer *view_layer_old = WM_window_get_active_view_layer(win);
+ ViewLayer *view_layer_old = WM_window_get_active_view_layer(win);
#endif
- /* Switch scene. */
- win->scene = scene;
- if (CTX_wm_window(C) == win) {
- CTX_data_scene_set(C, scene);
- }
+ /* Switch scene. */
+ win->scene = scene;
+ if (CTX_wm_window(C) == win) {
+ CTX_data_scene_set(C, scene);
+ }
- /* Ensure the view layer name is updated. */
- WM_window_ensure_active_view_layer(win);
- ViewLayer *view_layer = WM_window_get_active_view_layer(win);
+ /* Ensure the view layer name is updated. */
+ WM_window_ensure_active_view_layer(win);
+ ViewLayer *view_layer = WM_window_get_active_view_layer(win);
#if 0
- /* Mode Syncing. */
- if (view_layer_old) {
- WorkSpace *workspace = CTX_wm_workspace(C);
- Object *obact_new = OBACT(view_layer);
- UNUSED_VARS(obact_new);
- eObjectMode object_mode_old = workspace->object_mode;
- Object *obact_old = OBACT(view_layer_old);
- UNUSED_VARS(obact_old, object_mode_old);
- }
+ /* Mode Syncing. */
+ if (view_layer_old) {
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ Object *obact_new = OBACT(view_layer);
+ UNUSED_VARS(obact_new);
+ eObjectMode object_mode_old = workspace->object_mode;
+ Object *obact_old = OBACT(view_layer_old);
+ UNUSED_VARS(obact_old, object_mode_old);
+ }
#endif
- /* 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- screen_set_3dview_camera(scene, view_layer, sa, v3d);
- }
- }
- }
+ /* 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ screen_set_3dview_camera(scene, view_layer, sa, v3d);
+ }
+ }
+ }
}
ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type)
{
- wmWindow *win = CTX_wm_window(C);
- ScrArea *newsa = NULL;
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *newsa = NULL;
- if (!sa || sa->full == NULL) {
- newsa = ED_screen_state_toggle(C, win, sa, SCREENMAXIMIZED);
- }
+ if (!sa || sa->full == NULL) {
+ newsa = ED_screen_state_toggle(C, win, sa, SCREENMAXIMIZED);
+ }
- if (!newsa) {
- newsa = sa;
- }
+ if (!newsa) {
+ newsa = sa;
+ }
- BLI_assert(newsa);
+ BLI_assert(newsa);
- if (sa && (sa->spacetype != type)) {
- newsa->flag |= AREA_FLAG_TEMP_TYPE;
- }
- else {
- newsa->flag &= ~AREA_FLAG_TEMP_TYPE;
- }
+ if (sa && (sa->spacetype != type)) {
+ newsa->flag |= AREA_FLAG_TEMP_TYPE;
+ }
+ else {
+ newsa->flag &= ~AREA_FLAG_TEMP_TYPE;
+ }
- ED_area_newspace(C, newsa, type, (newsa->flag & AREA_FLAG_TEMP_TYPE));
+ ED_area_newspace(C, newsa, type, (newsa->flag & AREA_FLAG_TEMP_TYPE));
- return newsa;
+ return newsa;
}
/**
@@ -1074,57 +1084,57 @@ ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type)
*/
void ED_screen_full_prevspace(bContext *C, ScrArea *sa)
{
- BLI_assert(sa->full);
-
- if (sa->flag & AREA_FLAG_STACKED_FULLSCREEN) {
- /* stacked fullscreen -> only go back to previous screen and don't toggle out of fullscreen */
- ED_area_prevspace(C, sa);
- }
- else {
- ED_screen_restore_temp_type(C, sa);
- }
+ BLI_assert(sa->full);
+
+ if (sa->flag & AREA_FLAG_STACKED_FULLSCREEN) {
+ /* stacked fullscreen -> only go back to previous screen and don't toggle out of fullscreen */
+ ED_area_prevspace(C, sa);
+ }
+ else {
+ ED_screen_restore_temp_type(C, sa);
+ }
}
void ED_screen_restore_temp_type(bContext *C, ScrArea *sa)
{
- /* incase nether functions below run */
- ED_area_tag_redraw(sa);
-
- if (sa->flag & AREA_FLAG_TEMP_TYPE) {
- ED_area_prevspace(C, sa);
- /* Flag should be cleared now. */
- BLI_assert((sa->flag & AREA_FLAG_TEMP_TYPE) == 0);
- }
-
- if (sa->full) {
- ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENMAXIMIZED);
- }
+ /* incase nether functions below run */
+ ED_area_tag_redraw(sa);
+
+ if (sa->flag & AREA_FLAG_TEMP_TYPE) {
+ ED_area_prevspace(C, sa);
+ /* Flag should be cleared now. */
+ BLI_assert((sa->flag & AREA_FLAG_TEMP_TYPE) == 0);
+ }
+
+ if (sa->full) {
+ ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENMAXIMIZED);
+ }
}
/* restore a screen / area back to default operation, after temp fullscreen modes */
void ED_screen_full_restore(bContext *C, ScrArea *sa)
{
- wmWindow *win = CTX_wm_window(C);
- SpaceLink *sl = sa->spacedata.first;
- bScreen *screen = CTX_wm_screen(C);
- short state = (screen ? screen->state : SCREENMAXIMIZED);
-
- /* if fullscreen area has a temporary space (such as a file browser or fullscreen render
- * overlaid on top of an existing setup) then return to the previous space */
-
- if (sl->next) {
- if (sa->flag & AREA_FLAG_TEMP_TYPE) {
- ED_screen_full_prevspace(C, sa);
- }
- else {
- ED_screen_state_toggle(C, win, sa, state);
- }
- /* warning: 'sa' may be freed */
- }
- /* otherwise just tile the area again */
- else {
- ED_screen_state_toggle(C, win, sa, state);
- }
+ wmWindow *win = CTX_wm_window(C);
+ SpaceLink *sl = sa->spacedata.first;
+ bScreen *screen = CTX_wm_screen(C);
+ short state = (screen ? screen->state : SCREENMAXIMIZED);
+
+ /* if fullscreen area has a temporary space (such as a file browser or fullscreen render
+ * overlaid on top of an existing setup) then return to the previous space */
+
+ if (sl->next) {
+ if (sa->flag & AREA_FLAG_TEMP_TYPE) {
+ ED_screen_full_prevspace(C, sa);
+ }
+ else {
+ ED_screen_state_toggle(C, win, sa, state);
+ }
+ /* warning: 'sa' may be freed */
+ }
+ /* otherwise just tile the area again */
+ else {
+ ED_screen_state_toggle(C, win, sa, state);
+ }
}
/**
@@ -1134,180 +1144,186 @@ void ED_screen_full_restore(bContext *C, ScrArea *sa)
*/
ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, 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;
-
- if (sa) {
- /* 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);
-
- if (ar->regiontimer) {
- WM_event_remove_timer(wm, NULL, ar->regiontimer);
- ar->regiontimer = NULL;
- }
- }
-
- /* prevent hanging status prints */
- ED_area_status_text(sa, NULL);
- ED_workspace_status_text(C, NULL);
- }
-
- if (sa && sa->full) {
- WorkSpaceLayout *layout_old = WM_window_get_active_layout(win);
- /* restoring back to SCREENNORMAL */
- sc = sa->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)->state != SCREENNORMAL);
-
- sc->state = SCREENNORMAL;
- sc->flag = oldscreen->flag;
-
- /* find old area to restore from */
- ScrArea *fullsa = NULL;
- for (ScrArea *old = sc->areabase.first; old; old = old->next) {
- /* area to restore from is always first */
- if (old->full && !fullsa) {
- fullsa = old;
- }
-
- /* clear full screen state */
- old->full = NULL;
- }
-
- sa->full = NULL;
-
- if (fullsa == NULL) {
- if (G.debug & G_DEBUG)
- printf("%s: something wrong in areafullscreen\n", __func__);
- return NULL;
- }
-
- if (state == SCREENFULL) {
- /* unhide global areas */
- for (ScrArea *glob_area = win->global_areas.areabase.first; glob_area; glob_area = glob_area->next) {
- 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;
- }
- }
-
- ED_area_data_swap(fullsa, sa);
-
- /* animtimer back */
- sc->animtimer = oldscreen->animtimer;
- oldscreen->animtimer = NULL;
-
- ED_screen_change(C, sc);
-
- BKE_workspace_layout_remove(CTX_data_main(C), workspace, layout_old);
-
- /* After we've restored back to SCREENNORMAL, we have to wait with
- * 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;
- }
- else {
- /* change from SCREENNORMAL to new state */
- WorkSpaceLayout *layout_new;
- ScrArea *newa;
- char newname[MAX_ID_NAME - 2];
-
- BLI_assert(ELEM(state, SCREENMAXIMIZED, SCREENFULL));
-
- oldscreen = WM_window_get_active_screen(win);
-
- oldscreen->state = state;
- BLI_snprintf(newname, sizeof(newname), "%s-%s", oldscreen->id.name + 2, "nonnormal");
-
- 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;
-
- /* timer */
- sc->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;
- }
-
- newa = (ScrArea *)sc->areabase.first;
-
- /* copy area */
- ED_area_data_swap(newa, sa);
- newa->flag = sa->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) {
- 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;
-
- if (ELEM(ar->regiontype,
- RGN_TYPE_UI, RGN_TYPE_HEADER, RGN_TYPE_FOOTER,
- RGN_TYPE_TOOLS, RGN_TYPE_NAV_BAR, RGN_TYPE_EXECUTE))
- {
- ar->flag |= RGN_FLAG_HIDDEN;
- }
- }
- }
-
- sa->full = oldscreen;
- newa->full = oldscreen;
-
- ED_screen_change(C, sc);
- }
-
- /* XXX bad code: setscreen() ends with first area active. fullscreen render assumes this too */
- CTX_wm_area_set(C, sc->areabase.first);
-
- return sc->areabase.first;
+ 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;
+
+ if (sa) {
+ /* 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);
+
+ if (ar->regiontimer) {
+ WM_event_remove_timer(wm, NULL, ar->regiontimer);
+ ar->regiontimer = NULL;
+ }
+ }
+
+ /* prevent hanging status prints */
+ ED_area_status_text(sa, NULL);
+ ED_workspace_status_text(C, NULL);
+ }
+
+ if (sa && sa->full) {
+ WorkSpaceLayout *layout_old = WM_window_get_active_layout(win);
+ /* restoring back to SCREENNORMAL */
+ sc = sa->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)->state != SCREENNORMAL);
+
+ sc->state = SCREENNORMAL;
+ sc->flag = oldscreen->flag;
+
+ /* find old area to restore from */
+ ScrArea *fullsa = NULL;
+ for (ScrArea *old = sc->areabase.first; old; old = old->next) {
+ /* area to restore from is always first */
+ if (old->full && !fullsa) {
+ fullsa = old;
+ }
+
+ /* clear full screen state */
+ old->full = NULL;
+ }
+
+ sa->full = NULL;
+
+ if (fullsa == NULL) {
+ if (G.debug & G_DEBUG)
+ printf("%s: something wrong in areafullscreen\n", __func__);
+ return NULL;
+ }
+
+ if (state == SCREENFULL) {
+ /* unhide global areas */
+ for (ScrArea *glob_area = win->global_areas.areabase.first; glob_area;
+ glob_area = glob_area->next) {
+ 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;
+ }
+ }
+
+ ED_area_data_swap(fullsa, sa);
+
+ /* animtimer back */
+ sc->animtimer = oldscreen->animtimer;
+ oldscreen->animtimer = NULL;
+
+ ED_screen_change(C, sc);
+
+ BKE_workspace_layout_remove(CTX_data_main(C), workspace, layout_old);
+
+ /* After we've restored back to SCREENNORMAL, we have to wait with
+ * 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;
+ }
+ else {
+ /* change from SCREENNORMAL to new state */
+ WorkSpaceLayout *layout_new;
+ ScrArea *newa;
+ char newname[MAX_ID_NAME - 2];
+
+ BLI_assert(ELEM(state, SCREENMAXIMIZED, SCREENFULL));
+
+ oldscreen = WM_window_get_active_screen(win);
+
+ oldscreen->state = state;
+ BLI_snprintf(newname, sizeof(newname), "%s-%s", oldscreen->id.name + 2, "nonnormal");
+
+ 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;
+
+ /* timer */
+ sc->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;
+ }
+
+ newa = (ScrArea *)sc->areabase.first;
+
+ /* copy area */
+ ED_area_data_swap(newa, sa);
+ newa->flag = sa->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) {
+ 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;
+
+ if (ELEM(ar->regiontype,
+ RGN_TYPE_UI,
+ RGN_TYPE_HEADER,
+ RGN_TYPE_FOOTER,
+ RGN_TYPE_TOOLS,
+ RGN_TYPE_NAV_BAR,
+ RGN_TYPE_EXECUTE)) {
+ ar->flag |= RGN_FLAG_HIDDEN;
+ }
+ }
+ }
+
+ sa->full = oldscreen;
+ newa->full = oldscreen;
+
+ ED_screen_change(C, sc);
+ }
+
+ /* XXX bad code: setscreen() ends with first area active. fullscreen render assumes this too */
+ CTX_wm_area_set(C, sc->areabase.first);
+
+ return sc->areabase.first;
}
/* update frame rate info for viewport drawing */
void ED_refresh_viewport_fps(bContext *C)
{
- wmTimer *animtimer = CTX_wm_screen(C)->animtimer;
- Scene *scene = CTX_data_scene(C);
-
- /* is anim playback running? */
- if (animtimer && (U.uiflag & USER_SHOW_FPS)) {
- ScreenFrameRateInfo *fpsi = scene->fps_info;
-
- /* if there isn't any info, init it first */
- if (fpsi == NULL)
- fpsi = scene->fps_info = MEM_callocN(sizeof(ScreenFrameRateInfo), "refresh_viewport_fps fps_info");
-
- /* update the values */
- fpsi->redrawtime = fpsi->lredrawtime;
- fpsi->lredrawtime = animtimer->ltime;
- }
- else {
- /* playback stopped or shouldn't be running */
- if (scene->fps_info)
- MEM_freeN(scene->fps_info);
- scene->fps_info = NULL;
- }
+ wmTimer *animtimer = CTX_wm_screen(C)->animtimer;
+ Scene *scene = CTX_data_scene(C);
+
+ /* is anim playback running? */
+ if (animtimer && (U.uiflag & USER_SHOW_FPS)) {
+ ScreenFrameRateInfo *fpsi = scene->fps_info;
+
+ /* if there isn't any info, init it first */
+ if (fpsi == NULL)
+ fpsi = scene->fps_info = MEM_callocN(sizeof(ScreenFrameRateInfo),
+ "refresh_viewport_fps fps_info");
+
+ /* update the values */
+ fpsi->redrawtime = fpsi->lredrawtime;
+ fpsi->lredrawtime = animtimer->ltime;
+ }
+ else {
+ /* playback stopped or shouldn't be running */
+ if (scene->fps_info)
+ MEM_freeN(scene->fps_info);
+ scene->fps_info = NULL;
+ }
}
/* redraws: uses defines from stime->redraws
@@ -1315,138 +1331,136 @@ void ED_refresh_viewport_fps(bContext *C)
*/
void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync, int enable)
{
- bScreen *screen = CTX_wm_screen(C);
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
- Scene *scene = CTX_data_scene(C);
- bScreen *stopscreen = ED_screen_animation_playing(wm);
-
- if (stopscreen) {
- WM_event_remove_timer(wm, win, stopscreen->animtimer);
- stopscreen->animtimer = NULL;
- }
-
- if (enable) {
- ScreenAnimData *sad = MEM_callocN(sizeof(ScreenAnimData), "ScreenAnimData");
-
- screen->animtimer = WM_event_add_timer(wm, win, TIMER0, (1.0 / FPS));
-
- sad->ar = 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) {
- if (scene->r.psfra > scene->r.cfra) {
- sad->sfra = scene->r.cfra;
- scene->r.cfra = scene->r.psfra;
- }
- else
- sad->sfra = scene->r.cfra;
- }
- else {
- if (scene->r.sfra > scene->r.cfra) {
- sad->sfra = scene->r.cfra;
- scene->r.cfra = scene->r.sfra;
- }
- else
- sad->sfra = scene->r.cfra;
- }
- 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);
-
- char spacetype = -1;
-
- if (sa)
- spacetype = sa->spacetype;
-
- sad->from_anim_edit = (ELEM(spacetype, SPACE_GRAPH, SPACE_ACTION, SPACE_NLA));
-
- screen->animtimer->customdata = sad;
-
- }
-
- /* notifier catched by top header, for button */
- WM_event_add_notifier(C, NC_SCREEN | ND_ANIMPLAY, NULL);
+ bScreen *screen = CTX_wm_screen(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+ Scene *scene = CTX_data_scene(C);
+ bScreen *stopscreen = ED_screen_animation_playing(wm);
+
+ if (stopscreen) {
+ WM_event_remove_timer(wm, win, stopscreen->animtimer);
+ stopscreen->animtimer = NULL;
+ }
+
+ if (enable) {
+ ScreenAnimData *sad = MEM_callocN(sizeof(ScreenAnimData), "ScreenAnimData");
+
+ screen->animtimer = WM_event_add_timer(wm, win, TIMER0, (1.0 / FPS));
+
+ sad->ar = 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) {
+ if (scene->r.psfra > scene->r.cfra) {
+ sad->sfra = scene->r.cfra;
+ scene->r.cfra = scene->r.psfra;
+ }
+ else
+ sad->sfra = scene->r.cfra;
+ }
+ else {
+ if (scene->r.sfra > scene->r.cfra) {
+ sad->sfra = scene->r.cfra;
+ scene->r.cfra = scene->r.sfra;
+ }
+ else
+ sad->sfra = scene->r.cfra;
+ }
+ 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);
+
+ char spacetype = -1;
+
+ if (sa)
+ spacetype = sa->spacetype;
+
+ sad->from_anim_edit = (ELEM(spacetype, SPACE_GRAPH, SPACE_ACTION, SPACE_NLA));
+
+ screen->animtimer->customdata = sad;
+ }
+
+ /* notifier catched by top header, for button */
+ WM_event_add_notifier(C, NC_SCREEN | ND_ANIMPLAY, NULL);
}
/* helper for screen_animation_play() - only to be used for TimeLine */
static ARegion *time_top_left_3dwindow(bScreen *screen)
{
- ARegion *aret = NULL;
- ScrArea *sa;
- 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;
- }
- }
- }
- }
- }
-
- return aret;
+ ARegion *aret = NULL;
+ ScrArea *sa;
+ 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;
+ }
+ }
+ }
+ }
+ }
+
+ return aret;
}
void ED_screen_animation_timer_update(bScreen *screen, int redraws, int refresh)
{
- if (screen && screen->animtimer) {
- wmTimer *wt = screen->animtimer;
- ScreenAnimData *sad = wt->customdata;
-
- sad->redraws = redraws;
- sad->refresh = refresh;
- sad->ar = NULL;
- if (redraws & TIME_REGION)
- sad->ar = time_top_left_3dwindow(screen);
- }
+ if (screen && screen->animtimer) {
+ wmTimer *wt = screen->animtimer;
+ ScreenAnimData *sad = wt->customdata;
+
+ sad->redraws = redraws;
+ sad->refresh = refresh;
+ sad->ar = NULL;
+ if (redraws & TIME_REGION)
+ sad->ar = time_top_left_3dwindow(screen);
+ }
}
/* results in fully updated anim system */
void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph)
{
- Scene *scene = DEG_get_input_scene(depsgraph);
+ Scene *scene = DEG_get_input_scene(depsgraph);
#ifdef DURIAN_CAMERA_SWITCH
- void *camera = BKE_scene_camera_switch_find(scene);
- if (camera && scene->camera != camera) {
- bScreen *sc;
- 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);
- }
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- }
+ void *camera = BKE_scene_camera_switch_find(scene);
+ if (camera && scene->camera != camera) {
+ bScreen *sc;
+ 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);
+ }
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ }
#endif
- ED_clip_update_frame(bmain, scene->r.cfra);
+ ED_clip_update_frame(bmain, scene->r.cfra);
- /* this function applies the changes too */
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+ /* this function applies the changes too */
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
- /* composite */
- if (scene->use_nodes && scene->nodetree)
- ntreeCompositTagAnimated(scene->nodetree);
-
- /* update animated texture nodes */
- {
- Tex *tex;
- for (tex = bmain->textures.first; tex; tex = tex->id.next) {
- if (tex->use_nodes && tex->nodetree) {
- ntreeTexTagAnimated(tex->nodetree);
- }
- }
- }
+ /* composite */
+ if (scene->use_nodes && scene->nodetree)
+ ntreeCompositTagAnimated(scene->nodetree);
+ /* update animated texture nodes */
+ {
+ Tex *tex;
+ for (tex = bmain->textures.first; tex; tex = tex->id.next) {
+ if (tex->use_nodes && tex->nodetree) {
+ ntreeTexTagAnimated(tex->nodetree);
+ }
+ }
+ }
}
/*
@@ -1454,81 +1468,76 @@ void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph)
*/
bool ED_screen_stereo3d_required(const bScreen *screen, const Scene *scene)
{
- ScrArea *sa;
- const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
-
- for (sa = screen->areabase.first; sa; sa = sa->next) {
- switch (sa->spacetype) {
- case SPACE_VIEW3D:
- {
- View3D *v3d;
-
- if (!is_multiview)
- continue;
-
- v3d = sa->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;
- if (rv3d->persp == RV3D_CAMOB) {
- return true;
- }
- }
- }
- }
- break;
- }
- case SPACE_IMAGE:
- {
- SpaceImage *sima;
-
- /* images should always show in stereo, even if
- * the file doesn't have views enabled */
- sima = sa->spacedata.first;
- if (sima->image && BKE_image_is_stereo(sima->image) &&
- (sima->iuser.flag & IMA_SHOW_STEREO))
- {
- return true;
- }
- break;
- }
- case SPACE_NODE:
- {
- SpaceNode *snode;
-
- if (!is_multiview)
- continue;
-
- snode = sa->spacedata.first;
- if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) {
- return true;
- }
- break;
- }
- case SPACE_SEQ:
- {
- SpaceSeq *sseq;
-
- if (!is_multiview)
- continue;
-
- sseq = sa->spacedata.first;
- if (ELEM(sseq->view, SEQ_VIEW_PREVIEW, SEQ_VIEW_SEQUENCE_PREVIEW)) {
- return true;
- }
-
- if (sseq->draw_flag & SEQ_DRAW_BACKDROP) {
- return true;
- }
-
- break;
- }
- }
- }
-
- return false;
+ ScrArea *sa;
+ const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
+
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
+ switch (sa->spacetype) {
+ case SPACE_VIEW3D: {
+ View3D *v3d;
+
+ if (!is_multiview)
+ continue;
+
+ v3d = sa->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;
+ if (rv3d->persp == RV3D_CAMOB) {
+ return true;
+ }
+ }
+ }
+ }
+ break;
+ }
+ case SPACE_IMAGE: {
+ SpaceImage *sima;
+
+ /* images should always show in stereo, even if
+ * the file doesn't have views enabled */
+ sima = sa->spacedata.first;
+ if (sima->image && BKE_image_is_stereo(sima->image) &&
+ (sima->iuser.flag & IMA_SHOW_STEREO)) {
+ return true;
+ }
+ break;
+ }
+ case SPACE_NODE: {
+ SpaceNode *snode;
+
+ if (!is_multiview)
+ continue;
+
+ snode = sa->spacedata.first;
+ if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) {
+ return true;
+ }
+ break;
+ }
+ case SPACE_SEQ: {
+ SpaceSeq *sseq;
+
+ if (!is_multiview)
+ continue;
+
+ sseq = sa->spacedata.first;
+ if (ELEM(sseq->view, SEQ_VIEW_PREVIEW, SEQ_VIEW_SEQUENCE_PREVIEW)) {
+ return true;
+ }
+
+ if (sseq->draw_flag & SEQ_DRAW_BACKDROP) {
+ return true;
+ }
+
+ break;
+ }
+ }
+ }
+
+ return false;
}
/**
@@ -1536,52 +1545,55 @@ bool ED_screen_stereo3d_required(const bScreen *screen, const Scene *scene)
* \note Assumes \a screen to be visible/active!
*/
-Scene *ED_screen_scene_find_with_window(const bScreen *screen, const wmWindowManager *wm, struct wmWindow **r_window)
+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) {
- if (WM_window_get_active_screen(win) == screen) {
- if (r_window) {
- *r_window = win;
- }
- return WM_window_get_active_scene(win);
- }
- }
-
- BLI_assert(0);
- return NULL;
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ if (WM_window_get_active_screen(win) == screen) {
+ if (r_window) {
+ *r_window = win;
+ }
+ return WM_window_get_active_scene(win);
+ }
+ }
+
+ BLI_assert(0);
+ return NULL;
}
-ScrArea *ED_screen_area_find_with_spacedata(const bScreen *screen, const SpaceLink *sl, const bool only_visible)
+ScrArea *ED_screen_area_find_with_spacedata(const bScreen *screen,
+ const SpaceLink *sl,
+ const bool only_visible)
{
- if (only_visible) {
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa->spacedata.first == sl) {
- return sa;
- }
- }
- }
- else {
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- if (BLI_findindex(&sa->spacedata, sl) != -1) {
- return sa;
- }
- }
- }
- return NULL;
+ if (only_visible) {
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ if (sa->spacedata.first == sl) {
+ return sa;
+ }
+ }
+ }
+ else {
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ if (BLI_findindex(&sa->spacedata, sl) != -1) {
+ return sa;
+ }
+ }
+ }
+ return NULL;
}
Scene *ED_screen_scene_find(const bScreen *screen, const wmWindowManager *wm)
{
- return ED_screen_scene_find_with_window(screen, wm, NULL);
+ return ED_screen_scene_find_with_window(screen, wm, NULL);
}
-
wmWindow *ED_screen_window_find(const bScreen *screen, const wmWindowManager *wm)
{
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
- if (WM_window_get_active_screen(win) == screen) {
- return win;
- }
- }
- return NULL;
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ if (WM_window_get_active_screen(win) == screen) {
+ return win;
+ }
+ }
+ return NULL;
}
diff --git a/source/blender/editors/screen/screen_geometry.c b/source/blender/editors/screen/screen_geometry.c
index 68fd28013f8..1ad0e930582 100644
--- a/source/blender/editors/screen/screen_geometry.c
+++ b/source/blender/editors/screen/screen_geometry.c
@@ -39,108 +39,108 @@
#include "screen_intern.h"
-
int screen_geom_area_height(const ScrArea *area)
{
- return area->v2->vec.y - area->v1->vec.y + 1;
+ return area->v2->vec.y - area->v1->vec.y + 1;
}
int screen_geom_area_width(const ScrArea *area)
{
- return area->v4->vec.x - area->v1->vec.x + 1;
+ return area->v4->vec.x - area->v1->vec.x + 1;
}
ScrVert *screen_geom_vertex_add_ex(ScrAreaMap *area_map, short x, short y)
{
- ScrVert *sv = MEM_callocN(sizeof(ScrVert), "addscrvert");
- sv->vec.x = x;
- sv->vec.y = y;
+ ScrVert *sv = MEM_callocN(sizeof(ScrVert), "addscrvert");
+ sv->vec.x = x;
+ sv->vec.y = y;
- BLI_addtail(&area_map->vertbase, sv);
- return sv;
+ BLI_addtail(&area_map->vertbase, sv);
+ return sv;
}
ScrVert *screen_geom_vertex_add(bScreen *sc, 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(sc), x, y);
}
ScrEdge *screen_geom_edge_add_ex(ScrAreaMap *area_map, ScrVert *v1, ScrVert *v2)
{
- ScrEdge *se = MEM_callocN(sizeof(ScrEdge), "addscredge");
+ ScrEdge *se = MEM_callocN(sizeof(ScrEdge), "addscredge");
- BKE_screen_sort_scrvert(&v1, &v2);
- se->v1 = v1;
- se->v2 = v2;
+ BKE_screen_sort_scrvert(&v1, &v2);
+ se->v1 = v1;
+ se->v2 = v2;
- BLI_addtail(&area_map->edgebase, se);
- return se;
+ BLI_addtail(&area_map->edgebase, se);
+ return se;
}
ScrEdge *screen_geom_edge_add(bScreen *sc, 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(sc), v1, v2);
}
bool screen_geom_edge_is_horizontal(ScrEdge *se)
{
- return (se->v1->vec.y == se->v2->vec.y);
+ return (se->v1->vec.y == se->v2->vec.y);
}
/**
* \param bounds_rect: Either window or screen bounds. Used to exclude edges along window/screen edges.
*/
-ScrEdge *screen_geom_area_map_find_active_scredge(
- const ScrAreaMap *area_map,
- const rcti *bounds_rect,
- const int mx, const int my)
+ScrEdge *screen_geom_area_map_find_active_scredge(const ScrAreaMap *area_map,
+ const rcti *bounds_rect,
+ const int mx,
+ const int my)
{
- int safety = U.widget_unit / 10;
-
- CLAMP_MIN(safety, 2);
-
- for (ScrEdge *se = area_map->edgebase.first; se; se = se->next) {
- 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;
- min = MIN2(se->v1->vec.x, se->v2->vec.x);
- max = MAX2(se->v1->vec.x, se->v2->vec.x);
-
- if (abs(my - se->v1->vec.y) <= safety && mx >= min && mx <= max)
- return se;
- }
- }
- else {
- if ((se->v1->vec.x > bounds_rect->xmin) && (se->v1->vec.x < (bounds_rect->xmax - 1))) {
- short min, max;
- min = MIN2(se->v1->vec.y, se->v2->vec.y);
- max = MAX2(se->v1->vec.y, se->v2->vec.y);
-
- if (abs(mx - se->v1->vec.x) <= safety && my >= min && my <= max)
- return se;
- }
- }
- }
-
- return NULL;
+ int safety = U.widget_unit / 10;
+
+ CLAMP_MIN(safety, 2);
+
+ for (ScrEdge *se = area_map->edgebase.first; se; se = se->next) {
+ 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;
+ min = MIN2(se->v1->vec.x, se->v2->vec.x);
+ max = MAX2(se->v1->vec.x, se->v2->vec.x);
+
+ if (abs(my - se->v1->vec.y) <= safety && mx >= min && mx <= max)
+ return se;
+ }
+ }
+ else {
+ if ((se->v1->vec.x > bounds_rect->xmin) && (se->v1->vec.x < (bounds_rect->xmax - 1))) {
+ short min, max;
+ min = MIN2(se->v1->vec.y, se->v2->vec.y);
+ max = MAX2(se->v1->vec.y, se->v2->vec.y);
+
+ if (abs(mx - se->v1->vec.x) <= safety && my >= min && my <= max)
+ return se;
+ }
+ }
+ }
+
+ return NULL;
}
/* need win size to make sure not to include edges along screen edge */
-ScrEdge *screen_geom_find_active_scredge(
- const wmWindow *win, const bScreen *screen,
- const int mx, const int my)
+ScrEdge *screen_geom_find_active_scredge(const wmWindow *win,
+ const bScreen *screen,
+ const int mx,
+ const int my)
{
- /* Use layout size (screen excluding global areas) for screen-layout area edges */
- rcti screen_rect;
- ScrEdge *se;
-
- WM_window_screen_rect_calc(win, &screen_rect);
- se = screen_geom_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(screen), &screen_rect, mx, my);
-
- if (!se) {
- /* Use entire window size (screen including global areas) for global area edges */
- rcti win_rect;
- WM_window_rect_calc(win, &win_rect);
- se = screen_geom_area_map_find_active_scredge(&win->global_areas, &win_rect, mx, my);
- }
- return se;
+ /* Use layout size (screen excluding global areas) for screen-layout area edges */
+ rcti screen_rect;
+ ScrEdge *se;
+
+ WM_window_screen_rect_calc(win, &screen_rect);
+ se = screen_geom_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(screen), &screen_rect, mx, my);
+
+ if (!se) {
+ /* Use entire window size (screen including global areas) for global area edges */
+ rcti win_rect;
+ WM_window_rect_calc(win, &win_rect);
+ se = screen_geom_area_map_find_active_scredge(&win->global_areas, &win_rect, mx, my);
+ }
+ return se;
}
/**
@@ -152,262 +152,261 @@ ScrEdge *screen_geom_find_active_scredge(
*/
void screen_geom_vertices_scale(const wmWindow *win, bScreen *sc)
{
- /* clamp Y size of header sized areas when expanding windows
- * avoids annoying empty space around file menu */
+ /* clamp Y size of header sized areas when expanding windows
+ * avoids annoying empty space around file menu */
#define USE_HEADER_SIZE_CLAMP
- rcti window_rect, screen_rect;
-
- WM_window_rect_calc(win, &window_rect);
- WM_window_screen_rect_calc(win, &screen_rect);
+ rcti window_rect, screen_rect;
- const int headery_init = ED_area_headersize();
- 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];
+ WM_window_rect_calc(win, &window_rect);
+ WM_window_screen_rect_calc(win, &screen_rect);
- /* calculate size */
- min[0] = min[1] = 20000.0f;
- max[0] = max[1] = 0.0f;
+ const int headery_init = ED_area_headersize();
+ 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];
- for (sv = sc->vertbase.first; sv; sv = sv->next) {
- const float fv[2] = {(float)sv->vec.x, (float)sv->vec.y};
- minmax_v2v2_v2(min, max, fv);
- }
+ /* calculate size */
+ min[0] = min[1] = 20000.0f;
+ max[0] = max[1] = 0.0f;
- screen_size_x_prev = (max[0] - min[0]) + 1;
- screen_size_y_prev = (max[1] - min[1]) + 1;
+ for (sv = sc->vertbase.first; sv; sv = sv->next) {
+ const float fv[2] = {(float)sv->vec.x, (float)sv->vec.y};
+ minmax_v2v2_v2(min, max, fv);
+ }
+ screen_size_x_prev = (max[0] - min[0]) + 1;
+ screen_size_y_prev = (max[1] - min[1]) + 1;
#ifdef USE_HEADER_SIZE_CLAMP
-#define TEMP_BOTTOM 1
-#define TEMP_TOP 2
-
- /* if the window's Y axis grows, clamp header sized areas */
- if (screen_size_y_prev < screen_size_y) { /* growing? */
- const int headery_margin_max = headery_init + 5;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
- sa->temp = 0;
-
- if (ar && !(ar->flag & RGN_FLAG_HIDDEN)) {
- if (sa->v2->vec.y == max[1]) {
- if (screen_geom_area_height(sa) < headery_margin_max) {
- sa->temp = TEMP_TOP;
- }
- }
- else if (sa->v1->vec.y == min[1]) {
- if (screen_geom_area_height(sa) < headery_margin_max) {
- sa->temp = TEMP_BOTTOM;
- }
- }
- }
- }
- }
+# define TEMP_BOTTOM 1
+# define TEMP_TOP 2
+
+ /* if the window's Y axis grows, clamp header sized areas */
+ if (screen_size_y_prev < screen_size_y) { /* growing? */
+ const int headery_margin_max = headery_init + 5;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+ sa->temp = 0;
+
+ if (ar && !(ar->flag & RGN_FLAG_HIDDEN)) {
+ if (sa->v2->vec.y == max[1]) {
+ if (screen_geom_area_height(sa) < headery_margin_max) {
+ sa->temp = TEMP_TOP;
+ }
+ }
+ else if (sa->v1->vec.y == min[1]) {
+ if (screen_geom_area_height(sa) < headery_margin_max) {
+ sa->temp = TEMP_BOTTOM;
+ }
+ }
+ }
+ }
+ }
#endif
+ if (screen_size_x_prev != screen_size_x || screen_size_y_prev != screen_size_y) {
+ const float facx = ((float)screen_size_x - 1) / ((float)screen_size_x_prev - 1);
+ const float facy = ((float)screen_size_y - 1) / ((float)screen_size_y_prev - 1);
- if (screen_size_x_prev != screen_size_x || screen_size_y_prev != screen_size_y) {
- const float facx = ((float)screen_size_x - 1) / ((float)screen_size_x_prev - 1);
- 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) {
- 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);
-
- sv->vec.y = screen_rect.ymin + round_fl_to_short((sv->vec.y - min[1]) * facy);
- CLAMP(sv->vec.y, screen_rect.ymin, screen_rect.ymax - 1);
- }
- }
+ /* make sure it fits! */
+ for (sv = sc->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);
+ sv->vec.y = screen_rect.ymin + round_fl_to_short((sv->vec.y - min[1]) * facy);
+ CLAMP(sv->vec.y, screen_rect.ymin, screen_rect.ymax - 1);
+ }
+ }
#ifdef USE_HEADER_SIZE_CLAMP
- if (screen_size_y_prev < screen_size_y) { /* growing? */
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- ScrEdge *se = NULL;
-
- if (sa->temp == 0)
- continue;
-
- if (sa->v1 == sa->v2)
- continue;
-
- /* adjust headery if verts are along the edge of window */
- if (sa->temp == TEMP_TOP) {
- /* lower edge */
- const int yval = sa->v2->vec.y - headery_init;
- se = BKE_screen_find_edge(sc, sa->v4, sa->v1);
- if (se != NULL) {
- screen_geom_select_connected_edge(win, se);
- }
- for (sv = sc->vertbase.first; sv; sv = sv->next) {
- if (sv != sa->v2 && sv != sa->v3) {
- if (sv->flag) {
- sv->vec.y = yval;
- }
- }
- }
- }
- else {
- /* upper edge */
- const int yval = sa->v1->vec.y + headery_init;
- se = BKE_screen_find_edge(sc, sa->v2, sa->v3);
- if (se != NULL) {
- screen_geom_select_connected_edge(win, se);
- }
- for (sv = sc->vertbase.first; sv; sv = sv->next) {
- if (sv != sa->v1 && sv != sa->v4) {
- if (sv->flag) {
- sv->vec.y = yval;
- }
- }
- }
- }
- }
- }
-
-#undef USE_HEADER_SIZE_CLAMP
-#undef TEMP_BOTTOM
-#undef TEMP_TOP
+ if (screen_size_y_prev < screen_size_y) { /* growing? */
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ ScrEdge *se = NULL;
+
+ if (sa->temp == 0)
+ continue;
+
+ if (sa->v1 == sa->v2)
+ continue;
+
+ /* adjust headery if verts are along the edge of window */
+ if (sa->temp == TEMP_TOP) {
+ /* lower edge */
+ const int yval = sa->v2->vec.y - headery_init;
+ se = BKE_screen_find_edge(sc, sa->v4, sa->v1);
+ if (se != NULL) {
+ screen_geom_select_connected_edge(win, se);
+ }
+ for (sv = sc->vertbase.first; sv; sv = sv->next) {
+ if (sv != sa->v2 && sv != sa->v3) {
+ if (sv->flag) {
+ sv->vec.y = yval;
+ }
+ }
+ }
+ }
+ else {
+ /* upper edge */
+ const int yval = sa->v1->vec.y + headery_init;
+ se = BKE_screen_find_edge(sc, sa->v2, sa->v3);
+ if (se != NULL) {
+ screen_geom_select_connected_edge(win, se);
+ }
+ for (sv = sc->vertbase.first; sv; sv = sv->next) {
+ if (sv != sa->v1 && sv != sa->v4) {
+ if (sv->flag) {
+ sv->vec.y = yval;
+ }
+ }
+ }
+ }
+ }
+ }
+
+# undef USE_HEADER_SIZE_CLAMP
+# undef TEMP_BOTTOM
+# undef TEMP_TOP
#endif
-
- /* test for collapsed areas. This could happen in some blender version... */
- /* ton: removed option now, it needs Context... */
-
- /* make each window at least ED_area_headersize() high */
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- int headery = headery_init;
-
- /* adjust headery if verts are along the edge of window */
- if (sa->v1->vec.y > window_rect.ymin)
- headery += U.pixelsize;
- if (sa->v2->vec.y < (window_rect.ymax - 1))
- headery += U.pixelsize;
-
- if (screen_geom_area_height(sa) < 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;
-
- screen_geom_select_connected_edge(win, se);
-
- /* all selected vertices get the right offset */
- for (sv = sc->vertbase.first; sv; sv = sv->next) {
- /* if is a collapsed area */
- if (sv != sa->v2 && sv != sa->v3) {
- if (sv->flag) {
- sv->vec.y = yval;
- }
- }
- }
- }
- }
- }
-
- /* 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) {
- if (area->global->flag & GLOBAL_AREA_IS_HIDDEN) {
- continue;
- }
-
- int height = ED_area_global_size_y(area) - 1;
-
- if (area->v1->vec.y > window_rect.ymin) {
- height += U.pixelsize;
- }
- if (area->v2->vec.y < (window_rect.ymax - 1)) {
- height += U.pixelsize;
- }
-
- /* width */
- area->v1->vec.x = area->v2->vec.x = window_rect.xmin;
- area->v3->vec.x = area->v4->vec.x = window_rect.xmax - 1;
- /* height */
- area->v1->vec.y = area->v4->vec.y = window_rect.ymin;
- area->v2->vec.y = area->v3->vec.y = window_rect.ymax - 1;
-
- switch (area->global->align) {
- case GLOBAL_AREA_ALIGN_TOP:
- area->v1->vec.y = area->v4->vec.y = area->v2->vec.y - height;
- break;
- case GLOBAL_AREA_ALIGN_BOTTOM:
- area->v2->vec.y = area->v3->vec.y = area->v1->vec.y + height;
- break;
- }
- }
+ /* test for collapsed areas. This could happen in some blender version... */
+ /* ton: removed option now, it needs Context... */
+
+ /* make each window at least ED_area_headersize() high */
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ int headery = headery_init;
+
+ /* adjust headery if verts are along the edge of window */
+ if (sa->v1->vec.y > window_rect.ymin)
+ headery += U.pixelsize;
+ if (sa->v2->vec.y < (window_rect.ymax - 1))
+ headery += U.pixelsize;
+
+ if (screen_geom_area_height(sa) < 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;
+
+ screen_geom_select_connected_edge(win, se);
+
+ /* all selected vertices get the right offset */
+ for (sv = sc->vertbase.first; sv; sv = sv->next) {
+ /* if is a collapsed area */
+ if (sv != sa->v2 && sv != sa->v3) {
+ if (sv->flag) {
+ sv->vec.y = yval;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* 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) {
+ if (area->global->flag & GLOBAL_AREA_IS_HIDDEN) {
+ continue;
+ }
+
+ int height = ED_area_global_size_y(area) - 1;
+
+ if (area->v1->vec.y > window_rect.ymin) {
+ height += U.pixelsize;
+ }
+ if (area->v2->vec.y < (window_rect.ymax - 1)) {
+ height += U.pixelsize;
+ }
+
+ /* width */
+ area->v1->vec.x = area->v2->vec.x = window_rect.xmin;
+ area->v3->vec.x = area->v4->vec.x = window_rect.xmax - 1;
+ /* height */
+ area->v1->vec.y = area->v4->vec.y = window_rect.ymin;
+ area->v2->vec.y = area->v3->vec.y = window_rect.ymax - 1;
+
+ switch (area->global->align) {
+ case GLOBAL_AREA_ALIGN_TOP:
+ area->v1->vec.y = area->v4->vec.y = area->v2->vec.y - height;
+ break;
+ case GLOBAL_AREA_ALIGN_BOTTOM:
+ area->v2->vec.y = area->v3->vec.y = area->v1->vec.y + height;
+ break;
+ }
+ }
}
/**
* \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, const rcti *window_rect, char dir, float fac)
+short screen_geom_find_area_split_point(const ScrArea *sa,
+ 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 short area_min_x = AREAMINX;
- const short area_min_y = ED_area_headersize();
- int area_min;
-
- // area big enough?
- if ((dir == 'v') && (cur_area_width <= 2 * area_min_x)) {
- return 0;
- }
- if ((dir == 'h') && (cur_area_height <= 2 * area_min_y)) {
- return 0;
- }
-
- // to be sure
- CLAMP(fac, 0.0f, 1.0f);
-
- if (dir == 'h') {
- y = sa->v1->vec.y + round_fl_to_short(fac * cur_area_height);
-
- area_min = area_min_y;
-
- if (sa->v1->vec.y > window_rect->ymin) {
- area_min += U.pixelsize;
- }
- if (sa->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;
- }
- else if (sa->v2->vec.y - y < area_min) {
- y = sa->v2->vec.y - area_min;
- }
-
- return y;
- }
- else {
- x = sa->v1->vec.x + round_fl_to_short(fac * cur_area_width);
-
- area_min = area_min_x;
-
- if (sa->v1->vec.x > window_rect->xmin) {
- area_min += U.pixelsize;
- }
- if (sa->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;
- }
- else if (sa->v4->vec.x - x < area_min) {
- x = sa->v4->vec.x - area_min;
- }
-
- return x;
- }
+ short x, y;
+ const int cur_area_width = screen_geom_area_width(sa);
+ const int cur_area_height = screen_geom_area_height(sa);
+ const short area_min_x = AREAMINX;
+ const short area_min_y = ED_area_headersize();
+ int area_min;
+
+ // area big enough?
+ if ((dir == 'v') && (cur_area_width <= 2 * area_min_x)) {
+ return 0;
+ }
+ if ((dir == 'h') && (cur_area_height <= 2 * area_min_y)) {
+ return 0;
+ }
+
+ // to be sure
+ CLAMP(fac, 0.0f, 1.0f);
+
+ if (dir == 'h') {
+ y = sa->v1->vec.y + round_fl_to_short(fac * cur_area_height);
+
+ area_min = area_min_y;
+
+ if (sa->v1->vec.y > window_rect->ymin) {
+ area_min += U.pixelsize;
+ }
+ if (sa->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;
+ }
+ else if (sa->v2->vec.y - y < area_min) {
+ y = sa->v2->vec.y - area_min;
+ }
+
+ return y;
+ }
+ else {
+ x = sa->v1->vec.x + round_fl_to_short(fac * cur_area_width);
+
+ area_min = area_min_x;
+
+ if (sa->v1->vec.x > window_rect->xmin) {
+ area_min += U.pixelsize;
+ }
+ if (sa->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;
+ }
+ else if (sa->v4->vec.x - x < area_min) {
+ x = sa->v4->vec.x - area_min;
+ }
+
+ return x;
+ }
}
/**
@@ -415,44 +414,45 @@ short screen_geom_find_area_split_point(const ScrArea *sa, const rcti *window_re
*/
void screen_geom_select_connected_edge(const wmWindow *win, ScrEdge *edge)
{
- bScreen *sc = WM_window_get_active_screen(win);
- bool oneselected = true;
- char dir;
-
- /* select connected, only in the right direction */
- /* 'dir' is the direction of EDGE */
-
- if (edge->v1->vec.x == edge->v2->vec.x) {
- dir = 'v';
- }
- else {
- dir = 'h';
- }
-
- ED_screen_verts_iter(win, sc, sv) {
- sv->flag = 0;
- }
-
- edge->v1->flag = 1;
- edge->v2->flag = 1;
-
- while (oneselected) {
- oneselected = false;
- for (ScrEdge *se = sc->edgebase.first; se; se = se->next) {
- if (se->v1->flag + se->v2->flag == 1) {
- if (dir == 'h') {
- if (se->v1->vec.y == se->v2->vec.y) {
- se->v1->flag = se->v2->flag = 1;
- oneselected = true;
- }
- }
- if (dir == 'v') {
- if (se->v1->vec.x == se->v2->vec.x) {
- se->v1->flag = se->v2->flag = 1;
- oneselected = true;
- }
- }
- }
- }
- }
+ bScreen *sc = WM_window_get_active_screen(win);
+ bool oneselected = true;
+ char dir;
+
+ /* select connected, only in the right direction */
+ /* 'dir' is the direction of EDGE */
+
+ if (edge->v1->vec.x == edge->v2->vec.x) {
+ dir = 'v';
+ }
+ else {
+ dir = 'h';
+ }
+
+ ED_screen_verts_iter(win, sc, sv)
+ {
+ sv->flag = 0;
+ }
+
+ edge->v1->flag = 1;
+ edge->v2->flag = 1;
+
+ while (oneselected) {
+ oneselected = false;
+ for (ScrEdge *se = sc->edgebase.first; se; se = se->next) {
+ if (se->v1->flag + se->v2->flag == 1) {
+ if (dir == 'h') {
+ if (se->v1->vec.y == se->v2->vec.y) {
+ se->v1->flag = se->v2->flag = 1;
+ oneselected = true;
+ }
+ }
+ if (dir == 'v') {
+ if (se->v1->vec.x == se->v2->vec.x) {
+ se->v1->flag = se->v2->flag = 1;
+ oneselected = true;
+ }
+ }
+ }
+ }
+ }
}
diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h
index cb400bb3734..d2c43d1df28 100644
--- a/source/blender/editors/screen/screen_intern.h
+++ b/source/blender/editors/screen/screen_intern.h
@@ -30,62 +30,69 @@ struct bContextDataResult;
/* internal exports only */
-#define AZONESPOTW UI_HEADER_OFFSET /* width of corner azone - max */
-#define AZONESPOTH (0.6f * U.widget_unit) /* height of corner azone */
-#define AZONEFADEIN (5.0f * U.widget_unit) /* when azone is totally visible */
-#define AZONEFADEOUT (6.5f * U.widget_unit) /* when we start seeing the azone */
+#define AZONESPOTW UI_HEADER_OFFSET /* width of corner azone - max */
+#define AZONESPOTH (0.6f * U.widget_unit) /* height of corner azone */
+#define AZONEFADEIN (5.0f * U.widget_unit) /* when azone is totally visible */
+#define AZONEFADEOUT (6.5f * U.widget_unit) /* when we start seeing the azone */
/* area.c */
-void ED_area_data_copy(ScrArea *sa_dst, ScrArea *sa_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 ED_area_data_copy(ScrArea *sa_dst, ScrArea *sa_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);
/* 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);
-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);
+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);
+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);
struct AZone *ED_area_actionzone_find_xy(ScrArea *sa, 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);
-ScrEdge *screen_geom_edge_add_ex(ScrAreaMap *area_map, ScrVert *v1, ScrVert *v2);
-ScrEdge *screen_geom_edge_add(bScreen *sc, 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,
- const int mx, const int my);
-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, const rcti *window_rect, char dir, float fac);
-void screen_geom_select_connected_edge(const wmWindow *win, ScrEdge *edge);
-
+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);
+ScrEdge *screen_geom_edge_add_ex(ScrAreaMap *area_map, ScrVert *v1, ScrVert *v2);
+ScrEdge *screen_geom_edge_add(bScreen *sc, 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,
+ const int mx,
+ const int my);
+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,
+ const rcti *window_rect,
+ char dir,
+ float fac);
+void screen_geom_select_connected_edge(const wmWindow *win, ScrEdge *edge);
/* screen_context.c */
-int ed_screen_context(
- const struct bContext *C, const char *member, struct bContextDataResult *result);
+int ed_screen_context(const struct bContext *C,
+ const char *member,
+ struct bContextDataResult *result);
extern const char *screen_context_dir[]; /* doc access */
/* screendump.c */
-void SCREEN_OT_screenshot(struct wmOperatorType *ot);
+void SCREEN_OT_screenshot(struct wmOperatorType *ot);
/* screen_ops.c */
-void region_blend_start(struct bContext *C, struct ScrArea *sa, struct ARegion *ar);
+void region_blend_start(struct bContext *C, struct ScrArea *sa, struct ARegion *ar);
/* workspace_layout_edit.c */
bool workspace_layout_set_poll(const struct WorkSpaceLayout *layout);
-
#endif /* __SCREEN_INTERN_H__ */
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 3e5bebc4d35..94b5f695de8 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -21,7 +21,6 @@
* \ingroup edscr
*/
-
#include <math.h>
#include <string.h>
@@ -90,12 +89,12 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "screen_intern.h" /* own module include */
+#include "screen_intern.h" /* own module include */
-#define KM_MODAL_CANCEL 1
-#define KM_MODAL_APPLY 2
-#define KM_MODAL_SNAP_ON 3
-#define KM_MODAL_SNAP_OFF 4
+#define KM_MODAL_CANCEL 1
+#define KM_MODAL_APPLY 2
+#define KM_MODAL_SNAP_ON 3
+#define KM_MODAL_SNAP_OFF 4
/* -------------------------------------------------------------------- */
/** \name Public Poll API
@@ -103,275 +102,286 @@
bool ED_operator_regionactive(bContext *C)
{
- if (CTX_wm_window(C) == NULL) return 0;
- if (CTX_wm_screen(C) == NULL) return 0;
- if (CTX_wm_region(C) == NULL) return 0;
- return 1;
+ if (CTX_wm_window(C) == NULL)
+ return 0;
+ if (CTX_wm_screen(C) == NULL)
+ return 0;
+ if (CTX_wm_region(C) == NULL)
+ return 0;
+ return 1;
}
bool ED_operator_areaactive(bContext *C)
{
- if (CTX_wm_window(C) == NULL) return 0;
- if (CTX_wm_screen(C) == NULL) return 0;
- if (CTX_wm_area(C) == NULL) return 0;
- return 1;
+ if (CTX_wm_window(C) == NULL)
+ return 0;
+ if (CTX_wm_screen(C) == NULL)
+ return 0;
+ if (CTX_wm_area(C) == NULL)
+ return 0;
+ return 1;
}
bool ED_operator_screenactive(bContext *C)
{
- if (CTX_wm_window(C) == NULL) return 0;
- if (CTX_wm_screen(C) == NULL) return 0;
- return 1;
+ if (CTX_wm_window(C) == NULL)
+ return 0;
+ if (CTX_wm_screen(C) == NULL)
+ return 0;
+ return 1;
}
/* XXX added this to prevent anim state to change during renders */
static bool ED_operator_screenactive_norender(bContext *C)
{
- if (G.is_rendering) return 0;
- if (CTX_wm_window(C) == NULL) return 0;
- if (CTX_wm_screen(C) == NULL) return 0;
- return 1;
+ if (G.is_rendering)
+ return 0;
+ if (CTX_wm_window(C) == NULL)
+ return 0;
+ if (CTX_wm_screen(C) == NULL)
+ return 0;
+ return 1;
}
/* when mouse is over area-edge */
bool ED_operator_screen_mainwinactive(bContext *C)
{
- bScreen *screen;
- if (CTX_wm_window(C) == NULL) return 0;
- screen = CTX_wm_screen(C);
- if (screen == NULL) return 0;
- if (screen->active_region != NULL) return 0;
- return 1;
+ bScreen *screen;
+ if (CTX_wm_window(C) == NULL)
+ return 0;
+ screen = CTX_wm_screen(C);
+ if (screen == NULL)
+ return 0;
+ if (screen->active_region != NULL)
+ return 0;
+ return 1;
}
bool ED_operator_scene(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- if (scene)
- return 1;
- return 0;
+ Scene *scene = CTX_data_scene(C);
+ if (scene)
+ return 1;
+ return 0;
}
bool ED_operator_scene_editable(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- if (scene && !ID_IS_LINKED(scene))
- return 1;
- return 0;
+ Scene *scene = CTX_data_scene(C);
+ if (scene && !ID_IS_LINKED(scene))
+ return 1;
+ return 0;
}
bool ED_operator_objectmode(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- Object *obact = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obact = CTX_data_active_object(C);
- if (scene == NULL || ID_IS_LINKED(scene))
- return 0;
- if (CTX_data_edit_object(C))
- return 0;
+ if (scene == NULL || ID_IS_LINKED(scene))
+ return 0;
+ if (CTX_data_edit_object(C))
+ return 0;
- /* add a check for ob->mode too? */
- if (obact && (obact->mode != OB_MODE_OBJECT))
- return 0;
+ /* add a check for ob->mode too? */
+ if (obact && (obact->mode != OB_MODE_OBJECT))
+ return 0;
- return 1;
+ return 1;
}
-
static bool ed_spacetype_test(bContext *C, int type)
{
- if (ED_operator_areaactive(C)) {
- SpaceLink *sl = (SpaceLink *)CTX_wm_space_data(C);
- return sl && (sl->spacetype == type);
- }
- return 0;
+ if (ED_operator_areaactive(C)) {
+ SpaceLink *sl = (SpaceLink *)CTX_wm_space_data(C);
+ return sl && (sl->spacetype == type);
+ }
+ return 0;
}
bool ED_operator_view3d_active(bContext *C)
{
- return ed_spacetype_test(C, SPACE_VIEW3D);
+ return ed_spacetype_test(C, SPACE_VIEW3D);
}
bool ED_operator_region_view3d_active(bContext *C)
{
- if (CTX_wm_region_view3d(C))
- return true;
+ if (CTX_wm_region_view3d(C))
+ return true;
- CTX_wm_operator_poll_msg_set(C, "expected a view3d region");
- return false;
+ CTX_wm_operator_poll_msg_set(C, "expected a view3d region");
+ return false;
}
/* generic for any view2d which uses anim_ops */
bool ED_operator_animview_active(bContext *C)
{
- if (ED_operator_areaactive(C)) {
- SpaceLink *sl = (SpaceLink *)CTX_wm_space_data(C);
- if (sl && (ELEM(sl->spacetype, SPACE_SEQ, SPACE_ACTION, SPACE_NLA, SPACE_GRAPH)))
- return true;
- }
+ if (ED_operator_areaactive(C)) {
+ SpaceLink *sl = (SpaceLink *)CTX_wm_space_data(C);
+ if (sl && (ELEM(sl->spacetype, SPACE_SEQ, SPACE_ACTION, SPACE_NLA, SPACE_GRAPH)))
+ return true;
+ }
- CTX_wm_operator_poll_msg_set(C, "expected a timeline/animation area to be active");
- return 0;
+ CTX_wm_operator_poll_msg_set(C, "expected a timeline/animation area to be active");
+ return 0;
}
bool ED_operator_outliner_active(bContext *C)
{
- return ed_spacetype_test(C, SPACE_OUTLINER);
+ return ed_spacetype_test(C, SPACE_OUTLINER);
}
bool ED_operator_outliner_active_no_editobject(bContext *C)
{
- if (ed_spacetype_test(C, SPACE_OUTLINER)) {
- Object *ob = ED_object_active_context(C);
- Object *obedit = CTX_data_edit_object(C);
- if (ob && ob == obedit)
- return 0;
- else
- return 1;
- }
- return 0;
+ if (ed_spacetype_test(C, SPACE_OUTLINER)) {
+ Object *ob = ED_object_active_context(C);
+ Object *obedit = CTX_data_edit_object(C);
+ if (ob && ob == obedit)
+ return 0;
+ else
+ return 1;
+ }
+ return 0;
}
bool ED_operator_file_active(bContext *C)
{
- return ed_spacetype_test(C, SPACE_FILE);
+ return ed_spacetype_test(C, SPACE_FILE);
}
bool ED_operator_action_active(bContext *C)
{
- return ed_spacetype_test(C, SPACE_ACTION);
+ return ed_spacetype_test(C, SPACE_ACTION);
}
bool ED_operator_buttons_active(bContext *C)
{
- return ed_spacetype_test(C, SPACE_PROPERTIES);
+ return ed_spacetype_test(C, SPACE_PROPERTIES);
}
bool ED_operator_node_active(bContext *C)
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
- if (snode && snode->edittree)
- return 1;
+ if (snode && snode->edittree)
+ return 1;
- return 0;
+ return 0;
}
bool ED_operator_node_editable(bContext *C)
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
- if (snode && snode->edittree && !ID_IS_LINKED(snode->edittree))
- return 1;
+ if (snode && snode->edittree && !ID_IS_LINKED(snode->edittree))
+ return 1;
- return 0;
+ return 0;
}
bool ED_operator_graphedit_active(bContext *C)
{
- return ed_spacetype_test(C, SPACE_GRAPH);
+ return ed_spacetype_test(C, SPACE_GRAPH);
}
bool ED_operator_sequencer_active(bContext *C)
{
- return ed_spacetype_test(C, SPACE_SEQ);
+ return ed_spacetype_test(C, SPACE_SEQ);
}
bool ED_operator_sequencer_active_editable(bContext *C)
{
- return ed_spacetype_test(C, SPACE_SEQ) && ED_operator_scene_editable(C);
+ return ed_spacetype_test(C, SPACE_SEQ) && ED_operator_scene_editable(C);
}
bool ED_operator_image_active(bContext *C)
{
- return ed_spacetype_test(C, SPACE_IMAGE);
+ return ed_spacetype_test(C, SPACE_IMAGE);
}
bool ED_operator_nla_active(bContext *C)
{
- return ed_spacetype_test(C, SPACE_NLA);
+ return ed_spacetype_test(C, SPACE_NLA);
}
bool ED_operator_info_active(bContext *C)
{
- return ed_spacetype_test(C, SPACE_INFO);
+ return ed_spacetype_test(C, SPACE_INFO);
}
-
bool ED_operator_console_active(bContext *C)
{
- return ed_spacetype_test(C, SPACE_CONSOLE);
+ return ed_spacetype_test(C, SPACE_CONSOLE);
}
static bool ed_object_hidden(Object *ob)
{
- /* if hidden but in edit mode, we still display, can happen with animation */
- return ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT));
+ /* if hidden but in edit mode, we still display, can happen with animation */
+ return ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT));
}
bool ED_operator_object_active(bContext *C)
{
- Object *ob = ED_object_active_context(C);
- return ((ob != NULL) && !ed_object_hidden(ob));
+ Object *ob = ED_object_active_context(C);
+ return ((ob != NULL) && !ed_object_hidden(ob));
}
bool ED_operator_object_active_editable(bContext *C)
{
- Object *ob = ED_object_active_context(C);
- return ((ob != NULL) && !ID_IS_LINKED(ob) && !ed_object_hidden(ob));
+ Object *ob = ED_object_active_context(C);
+ return ((ob != NULL) && !ID_IS_LINKED(ob) && !ed_object_hidden(ob));
}
bool ED_operator_object_active_editable_mesh(bContext *C)
{
- Object *ob = ED_object_active_context(C);
- return ((ob != NULL) && !ID_IS_LINKED(ob) && !ed_object_hidden(ob) &&
- (ob->type == OB_MESH) && !ID_IS_LINKED(ob->data));
+ Object *ob = ED_object_active_context(C);
+ return ((ob != NULL) && !ID_IS_LINKED(ob) && !ed_object_hidden(ob) && (ob->type == OB_MESH) &&
+ !ID_IS_LINKED(ob->data));
}
bool ED_operator_object_active_editable_font(bContext *C)
{
- Object *ob = ED_object_active_context(C);
- return ((ob != NULL) && !ID_IS_LINKED(ob) && !ed_object_hidden(ob) &&
- (ob->type == OB_FONT));
+ Object *ob = ED_object_active_context(C);
+ return ((ob != NULL) && !ID_IS_LINKED(ob) && !ed_object_hidden(ob) && (ob->type == OB_FONT));
}
bool ED_operator_editmesh(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_MESH)
- return NULL != BKE_editmesh_from_object(obedit);
- return 0;
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_MESH)
+ return NULL != BKE_editmesh_from_object(obedit);
+ return 0;
}
bool ED_operator_editmesh_view3d(bContext *C)
{
- return ED_operator_editmesh(C) && ED_operator_view3d_active(C);
+ return ED_operator_editmesh(C) && ED_operator_view3d_active(C);
}
bool ED_operator_editmesh_region_view3d(bContext *C)
{
- if (ED_operator_editmesh(C) && CTX_wm_region_view3d(C))
- return 1;
+ if (ED_operator_editmesh(C) && CTX_wm_region_view3d(C))
+ return 1;
- CTX_wm_operator_poll_msg_set(C, "expected a view3d region & editmesh");
- return 0;
+ CTX_wm_operator_poll_msg_set(C, "expected a view3d region & editmesh");
+ return 0;
}
bool ED_operator_editmesh_auto_smooth(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_MESH && (((Mesh *)(obedit->data))->flag & ME_AUTOSMOOTH)) {
- return NULL != BKE_editmesh_from_object(obedit);
- }
- return 0;
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_MESH && (((Mesh *)(obedit->data))->flag & ME_AUTOSMOOTH)) {
+ return NULL != BKE_editmesh_from_object(obedit);
+ }
+ return 0;
}
bool ED_operator_editarmature(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_ARMATURE)
- return NULL != ((bArmature *)obedit->data)->edbo;
- return 0;
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_ARMATURE)
+ return NULL != ((bArmature *)obedit->data)->edbo;
+ return 0;
}
/**
@@ -383,193 +393,189 @@ bool ED_operator_editarmature(bContext *C)
*/
bool ED_operator_posemode_exclusive(bContext *C)
{
- Object *obact = CTX_data_active_object(C);
+ Object *obact = CTX_data_active_object(C);
- if (obact && !(obact->mode & OB_MODE_EDIT)) {
- Object *obpose;
- if ((obpose = BKE_object_pose_armature_get(obact))) {
- if (obact == obpose) {
- return 1;
- }
- }
- }
+ if (obact && !(obact->mode & OB_MODE_EDIT)) {
+ Object *obpose;
+ if ((obpose = BKE_object_pose_armature_get(obact))) {
+ if (obact == obpose) {
+ return 1;
+ }
+ }
+ }
- return 0;
+ return 0;
}
/* allows for pinned pose objects to be used in the object buttons
* and the non-active pose object to be used in the 3D view */
bool ED_operator_posemode_context(bContext *C)
{
- Object *obpose = ED_pose_object_from_context(C);
+ Object *obpose = ED_pose_object_from_context(C);
- if (obpose && !(obpose->mode & OB_MODE_EDIT)) {
- if (BKE_object_pose_context_check(obpose)) {
- return 1;
- }
- }
+ if (obpose && !(obpose->mode & OB_MODE_EDIT)) {
+ if (BKE_object_pose_context_check(obpose)) {
+ return 1;
+ }
+ }
- return 0;
+ return 0;
}
bool ED_operator_posemode(bContext *C)
{
- Object *obact = CTX_data_active_object(C);
+ Object *obact = CTX_data_active_object(C);
- if (obact && !(obact->mode & OB_MODE_EDIT)) {
- Object *obpose;
- if ((obpose = BKE_object_pose_armature_get(obact))) {
- if ((obact == obpose) || (obact->mode & OB_MODE_WEIGHT_PAINT)) {
- return 1;
- }
- }
- }
+ if (obact && !(obact->mode & OB_MODE_EDIT)) {
+ Object *obpose;
+ if ((obpose = BKE_object_pose_armature_get(obact))) {
+ if ((obact == obpose) || (obact->mode & OB_MODE_WEIGHT_PAINT)) {
+ return 1;
+ }
+ }
+ }
- return 0;
+ return 0;
}
bool ED_operator_posemode_local(bContext *C)
{
- if (ED_operator_posemode(C)) {
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bArmature *arm = ob->data;
- return !(ID_IS_LINKED(&ob->id) ||
- ID_IS_LINKED(&arm->id));
- }
- return false;
+ if (ED_operator_posemode(C)) {
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ bArmature *arm = ob->data;
+ return !(ID_IS_LINKED(&ob->id) || ID_IS_LINKED(&arm->id));
+ }
+ return false;
}
/* wrapper for ED_space_image_show_uvedit */
bool ED_operator_uvedit(bContext *C)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- Object *obedit = CTX_data_edit_object(C);
- return ED_space_image_show_uvedit(sima, obedit);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Object *obedit = CTX_data_edit_object(C);
+ return ED_space_image_show_uvedit(sima, obedit);
}
bool ED_operator_uvedit_space_image(bContext *C)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- Object *obedit = CTX_data_edit_object(C);
- return sima && ED_space_image_show_uvedit(sima, obedit);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Object *obedit = CTX_data_edit_object(C);
+ return sima && ED_space_image_show_uvedit(sima, obedit);
}
bool ED_operator_uvmap(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = NULL;
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = NULL;
- if (obedit && obedit->type == OB_MESH) {
- em = BKE_editmesh_from_object(obedit);
- }
+ if (obedit && obedit->type == OB_MESH) {
+ em = BKE_editmesh_from_object(obedit);
+ }
- if (em && (em->bm->totface)) {
- return true;
- }
+ if (em && (em->bm->totface)) {
+ return true;
+ }
- return false;
+ return false;
}
bool ED_operator_editsurfcurve(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && ELEM(obedit->type, OB_CURVE, OB_SURF))
- return NULL != ((Curve *)obedit->data)->editnurb;
- return 0;
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && ELEM(obedit->type, OB_CURVE, OB_SURF))
+ return NULL != ((Curve *)obedit->data)->editnurb;
+ return 0;
}
bool ED_operator_editsurfcurve_region_view3d(bContext *C)
{
- if (ED_operator_editsurfcurve(C) && CTX_wm_region_view3d(C))
- return 1;
+ if (ED_operator_editsurfcurve(C) && CTX_wm_region_view3d(C))
+ return 1;
- CTX_wm_operator_poll_msg_set(C, "expected a view3d region & editcurve");
- return 0;
+ CTX_wm_operator_poll_msg_set(C, "expected a view3d region & editcurve");
+ return 0;
}
bool ED_operator_editcurve(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_CURVE)
- return NULL != ((Curve *)obedit->data)->editnurb;
- return 0;
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_CURVE)
+ return NULL != ((Curve *)obedit->data)->editnurb;
+ return 0;
}
bool ED_operator_editcurve_3d(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_CURVE) {
- Curve *cu = (Curve *)obedit->data;
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_CURVE) {
+ Curve *cu = (Curve *)obedit->data;
- return (cu->flag & CU_3D) && (NULL != cu->editnurb);
- }
- return 0;
+ return (cu->flag & CU_3D) && (NULL != cu->editnurb);
+ }
+ return 0;
}
bool ED_operator_editsurf(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_SURF)
- return NULL != ((Curve *)obedit->data)->editnurb;
- return 0;
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_SURF)
+ return NULL != ((Curve *)obedit->data)->editnurb;
+ return 0;
}
bool ED_operator_editfont(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_FONT)
- return NULL != ((Curve *)obedit->data)->editfont;
- return 0;
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_FONT)
+ return NULL != ((Curve *)obedit->data)->editfont;
+ return 0;
}
bool ED_operator_editlattice(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_LATTICE)
- return NULL != ((Lattice *)obedit->data)->editlatt;
- return 0;
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_LATTICE)
+ return NULL != ((Lattice *)obedit->data)->editlatt;
+ return 0;
}
bool ED_operator_editmball(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_MBALL)
- return NULL != ((MetaBall *)obedit->data)->editelems;
- return 0;
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_MBALL)
+ return NULL != ((MetaBall *)obedit->data)->editelems;
+ return 0;
}
bool ED_operator_mask(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- if (sa && sa->spacedata.first) {
- switch (sa->spacetype) {
- case SPACE_CLIP:
- {
- SpaceClip *sc = sa->spacedata.first;
- return ED_space_clip_check_show_maskedit(sc);
- }
- case SPACE_SEQ:
- {
- SpaceSeq *sseq = sa->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;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- return ED_space_image_check_show_maskedit(sima, view_layer);
- }
- }
- }
-
- return false;
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa && sa->spacedata.first) {
+ switch (sa->spacetype) {
+ case SPACE_CLIP: {
+ SpaceClip *sc = sa->spacedata.first;
+ return ED_space_clip_check_show_maskedit(sc);
+ }
+ case SPACE_SEQ: {
+ SpaceSeq *sseq = sa->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;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ return ED_space_image_check_show_maskedit(sima, view_layer);
+ }
+ }
+ }
+
+ return false;
}
bool ED_operator_camera(bContext *C)
{
- struct Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
- return (cam != NULL);
+ struct Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
+ return (cam != NULL);
}
/** \} */
@@ -580,31 +586,31 @@ bool ED_operator_camera(bContext *C)
static bool screen_active_editable(bContext *C)
{
- if (ED_operator_screenactive(C)) {
- /* no full window splitting allowed */
- if (CTX_wm_screen(C)->state != SCREENNORMAL)
- return 0;
- return 1;
- }
- return 0;
+ if (ED_operator_screenactive(C)) {
+ /* no full window splitting allowed */
+ if (CTX_wm_screen(C)->state != SCREENNORMAL)
+ return 0;
+ return 1;
+ }
+ return 0;
}
static ARegion *screen_find_region_type(bContext *C, int type)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *ar = CTX_wm_region(C);
- /* find the header region
- * - try context first, but upon failing, search all regions in area...
- */
- if ((ar == NULL) || (ar->regiontype != type)) {
- ScrArea *sa = CTX_wm_area(C);
- ar = BKE_area_find_region_type(sa, type);
- }
- else {
- ar = NULL;
- }
+ /* find the header region
+ * - try context first, but upon failing, search all regions in area...
+ */
+ if ((ar == NULL) || (ar->regiontype != type)) {
+ ScrArea *sa = CTX_wm_area(C);
+ ar = BKE_area_find_region_type(sa, type);
+ }
+ else {
+ ar = NULL;
+ }
- return ar;
+ return ar;
}
/** \} */
@@ -620,422 +626,422 @@ static ARegion *screen_find_region_type(bContext *C, int type)
*
* apply() set action-zone event
*
- * exit() free customdata
+ * exit() free customdata
*
* callbacks:
*
- * exec() never used
+ * exec() never used
*
* invoke() check if in zone
* add customdata, put mouseco and area in it
* add modal handler
*
- * modal() accept modal events while doing it
+ * modal() accept modal events while doing it
* call apply() with gesture info, active window, nonactive window
* call exit() and remove handler when LMB confirm
*/
typedef struct sActionzoneData {
- ScrArea *sa1, *sa2;
- AZone *az;
- int x, y, gesture_dir, modifier;
+ ScrArea *sa1, *sa2;
+ AZone *az;
+ int x, y, gesture_dir, modifier;
} sActionzoneData;
/* quick poll to save operators to be created and handled */
static bool actionzone_area_poll(bContext *C)
{
- wmWindow *win = CTX_wm_window(C);
- bScreen *screen = WM_window_get_active_screen(win);
+ wmWindow *win = CTX_wm_window(C);
+ bScreen *screen = WM_window_get_active_screen(win);
- if (screen && win && win->eventstate) {
- const int *xy = &win->eventstate->x;
- AZone *az;
+ if (screen && win && win->eventstate) {
+ 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)
- if (BLI_rcti_isect_pt_v(&az->rect, xy))
- return 1;
- }
- }
- return 0;
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ for (az = sa->actionzones.first; az; az = az->next)
+ if (BLI_rcti_isect_pt_v(&az->rect, xy))
+ return 1;
+ }
+ }
+ return 0;
}
/* the debug drawing of the click_rect is in area_draw_azone_fullscreen, keep both in sync */
-static void fullscreen_click_rcti_init(rcti *rect, const short x1, const short y1, const short x2, const short y2)
+static void fullscreen_click_rcti_init(
+ rcti *rect, const short x1, const short y1, const short x2, const short y2)
{
- int x = x2 - ((float) x2 - x1) * 0.5f / UI_DPI_FAC;
- int y = y2 - ((float) y2 - y1) * 0.5f / UI_DPI_FAC;
- float icon_size = UI_DPI_ICON_SIZE + 7 * UI_DPI_FAC;
+ int x = x2 - ((float)x2 - x1) * 0.5f / UI_DPI_FAC;
+ int y = y2 - ((float)y2 - y1) * 0.5f / UI_DPI_FAC;
+ float icon_size = UI_DPI_ICON_SIZE + 7 * UI_DPI_FAC;
- /* adjust the icon distance from the corner */
- x += 36.0f / UI_DPI_FAC;
- y += 36.0f / UI_DPI_FAC;
+ /* adjust the icon distance from the corner */
+ x += 36.0f / UI_DPI_FAC;
+ y += 36.0f / UI_DPI_FAC;
- /* draws from the left bottom corner of the icon */
- x -= UI_DPI_ICON_SIZE;
- y -= UI_DPI_ICON_SIZE;
+ /* draws from the left bottom corner of the icon */
+ x -= UI_DPI_ICON_SIZE;
+ y -= UI_DPI_ICON_SIZE;
- BLI_rcti_init(rect, x, x + icon_size, y, y + icon_size);
+ BLI_rcti_init(rect, x, x + icon_size, y, y + icon_size);
}
static AZone *area_actionzone_refresh_xy(ScrArea *sa, const int xy[2], const bool test_only)
{
- AZone *az = NULL;
-
- for (az = sa->actionzones.first; az; az = az->next) {
- if (BLI_rcti_isect_pt_v(&az->rect, xy)) {
- if (az->type == AZONE_AREA) {
- break;
- }
- else if (az->type == AZONE_REGION) {
- break;
- }
- else if (az->type == AZONE_FULLSCREEN) {
- rcti click_rect;
- fullscreen_click_rcti_init(&click_rect, az->x1, az->y1, az->x2, az->y2);
- const bool click_isect = BLI_rcti_isect_pt_v(&click_rect, xy);
-
- if (test_only) {
- if (click_isect) {
- break;
- }
- }
- else {
- if (click_isect) {
- 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);
-
- if (mouse_sq < spot_sq) {
- az->alpha = 1.0f;
- }
- else if (mouse_sq < fadein_sq) {
- az->alpha = 1.0f;
- }
- else if (mouse_sq < fadeout_sq) {
- az->alpha = 1.0f - ((float)(mouse_sq - fadein_sq)) / ((float)(fadeout_sq - fadein_sq));
- }
- else {
- az->alpha = 0.0f;
- }
-
- /* fade in/out but no click */
- az = NULL;
- }
-
- /* XXX force redraw to show/hide the action zone */
- ED_area_tag_redraw(sa);
- break;
- }
- }
- else if (az->type == AZONE_REGION_SCROLL) {
- ARegion *ar = az->ar;
- View2D *v2d = &ar->v2d;
- int scroll_flag = 0;
- const int isect_value = UI_view2d_mouse_in_scrollers_ex(ar, 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)) ||
- ((az->direction == AZ_SCROLL_VERT) && !(scroll_flag & V2D_SCROLL_VERTICAL)))
- {
- /* no scrollbars, do nothing. */
- }
- else if (test_only) {
- if (isect_value != 0) {
- break;
- }
- }
- else {
- bool redraw = false;
-
- if (isect_value == 'h') {
- if (az->direction == AZ_SCROLL_HOR) {
- az->alpha = 1.0f;
- v2d->alpha_hor = 255;
- redraw = true;
- }
- }
- else if (isect_value == 'v') {
- if (az->direction == AZ_SCROLL_VERT) {
- az->alpha = 1.0f;
- v2d->alpha_vert = 255;
- redraw = true;
- }
- }
- else {
- const int local_xy[2] = {xy[0] - ar->winrct.xmin, xy[1] - ar->winrct.ymin};
- float dist_fac = 0.0f, alpha = 0.0f;
-
- if (az->direction == AZ_SCROLL_HOR) {
- dist_fac = BLI_rcti_length_y(&v2d->hor, local_xy[1]) / AZONEFADEIN;
- CLAMP(dist_fac, 0.0f, 1.0f);
- alpha = 1.0f - dist_fac;
-
- v2d->alpha_hor = alpha * 255;
- }
- else if (az->direction == AZ_SCROLL_VERT) {
- dist_fac = BLI_rcti_length_x(&v2d->vert, local_xy[0]) / AZONEFADEIN;
- CLAMP(dist_fac, 0.0f, 1.0f);
- alpha = 1.0f - dist_fac;
-
- v2d->alpha_vert = alpha * 255;
- }
- az->alpha = alpha;
- redraw = true;
- }
-
- if (redraw) {
- ED_region_tag_redraw_no_rebuild(ar);
- }
- /* Don't return! */
- }
- }
- }
- 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);
- }
- 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);
- }
- 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);
- }
- else {
- BLI_assert(0);
- }
- }
- }
- }
-
- return az;
+ AZone *az = NULL;
+
+ for (az = sa->actionzones.first; az; az = az->next) {
+ if (BLI_rcti_isect_pt_v(&az->rect, xy)) {
+ if (az->type == AZONE_AREA) {
+ break;
+ }
+ else if (az->type == AZONE_REGION) {
+ break;
+ }
+ else if (az->type == AZONE_FULLSCREEN) {
+ rcti click_rect;
+ fullscreen_click_rcti_init(&click_rect, az->x1, az->y1, az->x2, az->y2);
+ const bool click_isect = BLI_rcti_isect_pt_v(&click_rect, xy);
+
+ if (test_only) {
+ if (click_isect) {
+ break;
+ }
+ }
+ else {
+ if (click_isect) {
+ 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);
+
+ if (mouse_sq < spot_sq) {
+ az->alpha = 1.0f;
+ }
+ else if (mouse_sq < fadein_sq) {
+ az->alpha = 1.0f;
+ }
+ else if (mouse_sq < fadeout_sq) {
+ az->alpha = 1.0f -
+ ((float)(mouse_sq - fadein_sq)) / ((float)(fadeout_sq - fadein_sq));
+ }
+ else {
+ az->alpha = 0.0f;
+ }
+
+ /* fade in/out but no click */
+ az = NULL;
+ }
+
+ /* XXX force redraw to show/hide the action zone */
+ ED_area_tag_redraw(sa);
+ break;
+ }
+ }
+ else if (az->type == AZONE_REGION_SCROLL) {
+ ARegion *ar = az->ar;
+ View2D *v2d = &ar->v2d;
+ int scroll_flag = 0;
+ const int isect_value = UI_view2d_mouse_in_scrollers_ex(
+ ar, 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)) ||
+ ((az->direction == AZ_SCROLL_VERT) && !(scroll_flag & V2D_SCROLL_VERTICAL))) {
+ /* no scrollbars, do nothing. */
+ }
+ else if (test_only) {
+ if (isect_value != 0) {
+ break;
+ }
+ }
+ else {
+ bool redraw = false;
+
+ if (isect_value == 'h') {
+ if (az->direction == AZ_SCROLL_HOR) {
+ az->alpha = 1.0f;
+ v2d->alpha_hor = 255;
+ redraw = true;
+ }
+ }
+ else if (isect_value == 'v') {
+ if (az->direction == AZ_SCROLL_VERT) {
+ az->alpha = 1.0f;
+ v2d->alpha_vert = 255;
+ redraw = true;
+ }
+ }
+ else {
+ const int local_xy[2] = {xy[0] - ar->winrct.xmin, xy[1] - ar->winrct.ymin};
+ float dist_fac = 0.0f, alpha = 0.0f;
+
+ if (az->direction == AZ_SCROLL_HOR) {
+ dist_fac = BLI_rcti_length_y(&v2d->hor, local_xy[1]) / AZONEFADEIN;
+ CLAMP(dist_fac, 0.0f, 1.0f);
+ alpha = 1.0f - dist_fac;
+
+ v2d->alpha_hor = alpha * 255;
+ }
+ else if (az->direction == AZ_SCROLL_VERT) {
+ dist_fac = BLI_rcti_length_x(&v2d->vert, local_xy[0]) / AZONEFADEIN;
+ CLAMP(dist_fac, 0.0f, 1.0f);
+ alpha = 1.0f - dist_fac;
+
+ v2d->alpha_vert = alpha * 255;
+ }
+ az->alpha = alpha;
+ redraw = true;
+ }
+
+ if (redraw) {
+ ED_region_tag_redraw_no_rebuild(ar);
+ }
+ /* Don't return! */
+ }
+ }
+ }
+ 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);
+ }
+ 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);
+ }
+ 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);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ }
+ }
+
+ return az;
}
/* 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])
{
- for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
- AZone *az = area_actionzone_refresh_xy(sa, xy, true);
- if (az != NULL) {
- return az;
- }
- }
- return NULL;
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
+ AZone *az = area_actionzone_refresh_xy(sa, xy, true);
+ if (az != NULL) {
+ return az;
+ }
+ }
+ return NULL;
}
/* Returns the area that the azone belongs to */
static ScrArea *screen_actionzone_area(bScreen *sc, const AZone *az)
{
- for (ScrArea *area = sc->areabase.first; area; area = area->next) {
- for (AZone *zone = area->actionzones.first; zone; zone = zone->next) {
- if (zone == az) {
- return area;
- }
- }
- }
- return NULL;
+ for (ScrArea *area = sc->areabase.first; area; area = area->next) {
+ for (AZone *zone = area->actionzones.first; zone; zone = zone->next) {
+ if (zone == az) {
+ return area;
+ }
+ }
+ }
+ return NULL;
}
AZone *ED_area_actionzone_find_xy(ScrArea *sa, const int xy[2])
{
- return area_actionzone_refresh_xy(sa, xy, true);
+ return area_actionzone_refresh_xy(sa, xy, true);
}
AZone *ED_area_azones_update(ScrArea *sa, const int xy[2])
{
- return area_actionzone_refresh_xy(sa, xy, false);
+ return area_actionzone_refresh_xy(sa, xy, false);
}
static void actionzone_exit(wmOperator *op)
{
- if (op->customdata)
- MEM_freeN(op->customdata);
- op->customdata = NULL;
+ if (op->customdata)
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
}
/* send EVT_ACTIONZONE event */
static void actionzone_apply(bContext *C, wmOperator *op, int type)
{
- wmEvent event;
- wmWindow *win = CTX_wm_window(C);
- sActionzoneData *sad = op->customdata;
+ wmEvent event;
+ wmWindow *win = CTX_wm_window(C);
+ sActionzoneData *sad = op->customdata;
- sad->modifier = RNA_int_get(op->ptr, "modifier");
+ sad->modifier = RNA_int_get(op->ptr, "modifier");
- wm_event_init_from_window(win, &event);
+ wm_event_init_from_window(win, &event);
- if (type == AZONE_AREA)
- event.type = EVT_ACTIONZONE_AREA;
- else if (type == AZONE_FULLSCREEN)
- event.type = EVT_ACTIONZONE_FULLSCREEN;
- else
- event.type = EVT_ACTIONZONE_REGION;
+ if (type == AZONE_AREA)
+ event.type = EVT_ACTIONZONE_AREA;
+ else if (type == AZONE_FULLSCREEN)
+ event.type = EVT_ACTIONZONE_FULLSCREEN;
+ else
+ event.type = EVT_ACTIONZONE_REGION;
- event.val = KM_NOTHING;
- event.customdata = op->customdata;
- event.customdatafree = true;
- op->customdata = NULL;
+ event.val = KM_NOTHING;
+ event.customdata = op->customdata;
+ event.customdatafree = true;
+ op->customdata = NULL;
- wm_event_add(win, &event);
+ wm_event_add(win, &event);
}
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);
- sActionzoneData *sad;
+ bScreen *sc = CTX_wm_screen(C);
+ AZone *az = screen_actionzone_find_xy(sc, &event->x);
+ sActionzoneData *sad;
- /* quick escape - Scroll azones only hide/unhide the scroll-bars, they have their own handling. */
- if (az == NULL || ELEM(az->type, AZONE_REGION_SCROLL))
- return OPERATOR_PASS_THROUGH;
+ /* quick escape - Scroll azones only hide/unhide the scroll-bars, they have their own handling. */
+ if (az == NULL || ELEM(az->type, AZONE_REGION_SCROLL))
+ return OPERATOR_PASS_THROUGH;
- /* ok we do the action-zone */
- sad = op->customdata = MEM_callocN(sizeof(sActionzoneData), "sActionzoneData");
- sad->sa1 = screen_actionzone_area(sc, az);
- sad->az = az;
- sad->x = event->x; sad->y = event->y;
+ /* ok we do the action-zone */
+ sad = op->customdata = MEM_callocN(sizeof(sActionzoneData), "sActionzoneData");
+ sad->sa1 = screen_actionzone_area(sc, az);
+ sad->az = az;
+ sad->x = event->x;
+ sad->y = event->y;
- /* region azone directly reacts on mouse clicks */
- if (ELEM(sad->az->type, AZONE_REGION, AZONE_FULLSCREEN)) {
- actionzone_apply(C, op, sad->az->type);
- actionzone_exit(op);
- return OPERATOR_FINISHED;
- }
- else {
- /* add modal handler */
- WM_event_add_modal_handler(C, op);
+ /* region azone directly reacts on mouse clicks */
+ if (ELEM(sad->az->type, AZONE_REGION, AZONE_FULLSCREEN)) {
+ actionzone_apply(C, op, sad->az->type);
+ actionzone_exit(op);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ /* add modal handler */
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
- }
+ return OPERATOR_RUNNING_MODAL;
+ }
}
-
static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- bScreen *sc = CTX_wm_screen(C);
- sActionzoneData *sad = op->customdata;
-
- switch (event->type) {
- case MOUSEMOVE:
- {
- bool is_gesture;
-
- const int delta_x = (event->x - sad->x);
- const int delta_y = (event->y - sad->y);
-
- /* Movement in dominant direction. */
- 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);
- const int split_threshold = (1.2 * U.widget_unit);
- const int area_threshold = (0.1 * U.widget_unit);
-
- /* Calculate gesture cardinal direction. */
- if (delta_y > ABS(delta_x))
- sad->gesture_dir = 'n';
- else if (delta_x >= ABS(delta_y))
- sad->gesture_dir = 'e';
- else if (delta_y < -ABS(delta_x))
- sad->gesture_dir = 's';
- else
- sad->gesture_dir = 'w';
-
- if (sad->az->type == AZONE_AREA) {
- wmWindow *win = CTX_wm_window(C);
- rcti screen_rect;
-
- WM_window_screen_rect_calc(win, &screen_rect);
-
- /* 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))
- {
- /* Are we still in same area? */
- if (BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, event->x, event->y) == sad->sa1) {
- /* Same area, so possible split. */
- WM_cursor_set(win, (ELEM(sad->gesture_dir, 'n', 's')) ? BC_V_SPLITCURSOR : BC_H_SPLITCURSOR);
- is_gesture = (delta_max > split_threshold);
- }
- else {
- /* Different area, so posible join. */
- if (sad->gesture_dir == 'n')
- WM_cursor_set(win, BC_N_ARROWCURSOR);
- else if (sad->gesture_dir == 's')
- WM_cursor_set(win, BC_S_ARROWCURSOR);
- else if (sad->gesture_dir == 'e')
- WM_cursor_set(win, BC_E_ARROWCURSOR);
- else
- WM_cursor_set(win, BC_W_ARROWCURSOR);
- is_gesture = (delta_max > join_threshold);
- }
- }
- else {
- WM_cursor_set(CTX_wm_window(C), BC_CROSSCURSOR);
- is_gesture = false;
- }
- }
- else {
- is_gesture = (delta_max > area_threshold);
- }
-
- /* 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);
- /* apply sends event */
- actionzone_apply(C, op, sad->az->type);
- actionzone_exit(op);
-
- return OPERATOR_FINISHED;
- }
- break;
- }
- case ESCKEY:
- actionzone_exit(op);
- return OPERATOR_CANCELLED;
- case LEFTMOUSE:
- actionzone_exit(op);
- return OPERATOR_CANCELLED;
-
- }
-
- return OPERATOR_RUNNING_MODAL;
+ bScreen *sc = CTX_wm_screen(C);
+ sActionzoneData *sad = op->customdata;
+
+ switch (event->type) {
+ case MOUSEMOVE: {
+ bool is_gesture;
+
+ const int delta_x = (event->x - sad->x);
+ const int delta_y = (event->y - sad->y);
+
+ /* Movement in dominant direction. */
+ 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);
+ const int split_threshold = (1.2 * U.widget_unit);
+ const int area_threshold = (0.1 * U.widget_unit);
+
+ /* Calculate gesture cardinal direction. */
+ if (delta_y > ABS(delta_x))
+ sad->gesture_dir = 'n';
+ else if (delta_x >= ABS(delta_y))
+ sad->gesture_dir = 'e';
+ else if (delta_y < -ABS(delta_x))
+ sad->gesture_dir = 's';
+ else
+ sad->gesture_dir = 'w';
+
+ if (sad->az->type == AZONE_AREA) {
+ wmWindow *win = CTX_wm_window(C);
+ rcti screen_rect;
+
+ WM_window_screen_rect_calc(win, &screen_rect);
+
+ /* 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)) {
+ /* Are we still in same area? */
+ if (BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, event->x, event->y) == sad->sa1) {
+ /* Same area, so possible split. */
+ WM_cursor_set(
+ win, (ELEM(sad->gesture_dir, 'n', 's')) ? BC_V_SPLITCURSOR : BC_H_SPLITCURSOR);
+ is_gesture = (delta_max > split_threshold);
+ }
+ else {
+ /* Different area, so posible join. */
+ if (sad->gesture_dir == 'n')
+ WM_cursor_set(win, BC_N_ARROWCURSOR);
+ else if (sad->gesture_dir == 's')
+ WM_cursor_set(win, BC_S_ARROWCURSOR);
+ else if (sad->gesture_dir == 'e')
+ WM_cursor_set(win, BC_E_ARROWCURSOR);
+ else
+ WM_cursor_set(win, BC_W_ARROWCURSOR);
+ is_gesture = (delta_max > join_threshold);
+ }
+ }
+ else {
+ WM_cursor_set(CTX_wm_window(C), BC_CROSSCURSOR);
+ is_gesture = false;
+ }
+ }
+ else {
+ is_gesture = (delta_max > area_threshold);
+ }
+
+ /* 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);
+ /* apply sends event */
+ actionzone_apply(C, op, sad->az->type);
+ actionzone_exit(op);
+
+ return OPERATOR_FINISHED;
+ }
+ break;
+ }
+ case ESCKEY:
+ actionzone_exit(op);
+ return OPERATOR_CANCELLED;
+ case LEFTMOUSE:
+ actionzone_exit(op);
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
static void actionzone_cancel(bContext *UNUSED(C), wmOperator *op)
{
- actionzone_exit(op);
+ actionzone_exit(op);
}
static void SCREEN_OT_actionzone(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Handle Area Action Zones";
- ot->description = "Handle area action zones for mouse actions/gestures";
- ot->idname = "SCREEN_OT_actionzone";
+ /* identifiers */
+ ot->name = "Handle Area Action Zones";
+ ot->description = "Handle area action zones for mouse actions/gestures";
+ ot->idname = "SCREEN_OT_actionzone";
- ot->invoke = actionzone_invoke;
- ot->modal = actionzone_modal;
- ot->poll = actionzone_area_poll;
- ot->cancel = actionzone_cancel;
+ ot->invoke = actionzone_invoke;
+ ot->modal = actionzone_modal;
+ ot->poll = actionzone_area_poll;
+ ot->cancel = actionzone_cancel;
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
- RNA_def_int(ot->srna, "modifier", 0, 0, 2, "Modifier", "Modifier state", 0, 2);
+ RNA_def_int(ot->srna, "modifier", 0, 0, 2, "Modifier", "Modifier state", 0, 2);
}
/** \} */
@@ -1065,101 +1071,99 @@ static void SCREEN_OT_actionzone(wmOperatorType *ot)
*/
typedef struct sAreaSwapData {
- ScrArea *sa1, *sa2;
+ ScrArea *sa1, *sa2;
} sAreaSwapData;
static int area_swap_init(wmOperator *op, const wmEvent *event)
{
- sAreaSwapData *sd = NULL;
- sActionzoneData *sad = event->customdata;
+ sAreaSwapData *sd = NULL;
+ sActionzoneData *sad = event->customdata;
- if (sad == NULL || sad->sa1 == NULL)
- return 0;
+ if (sad == NULL || sad->sa1 == NULL)
+ return 0;
- sd = MEM_callocN(sizeof(sAreaSwapData), "sAreaSwapData");
- sd->sa1 = sad->sa1;
- sd->sa2 = sad->sa2;
- op->customdata = sd;
+ sd = MEM_callocN(sizeof(sAreaSwapData), "sAreaSwapData");
+ sd->sa1 = sad->sa1;
+ sd->sa2 = sad->sa2;
+ op->customdata = sd;
- return 1;
+ return 1;
}
-
static void area_swap_exit(bContext *C, wmOperator *op)
{
- WM_cursor_modal_restore(CTX_wm_window(C));
- if (op->customdata)
- MEM_freeN(op->customdata);
- op->customdata = NULL;
+ WM_cursor_modal_restore(CTX_wm_window(C));
+ if (op->customdata)
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
}
static void area_swap_cancel(bContext *C, wmOperator *op)
{
- area_swap_exit(C, op);
+ area_swap_exit(C, op);
}
static int area_swap_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (!area_swap_init(op, event))
- return OPERATOR_PASS_THROUGH;
+ if (!area_swap_init(op, event))
+ return OPERATOR_PASS_THROUGH;
- /* add modal handler */
- WM_cursor_modal_set(CTX_wm_window(C), BC_SWAPAREA_CURSOR);
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
+ /* add modal handler */
+ WM_cursor_modal_set(CTX_wm_window(C), BC_SWAPAREA_CURSOR);
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
}
static int area_swap_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- sActionzoneData *sad = op->customdata;
+ sActionzoneData *sad = op->customdata;
- switch (event->type) {
- case MOUSEMOVE:
- /* second area, for join */
- sad->sa2 = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, event->x, event->y);
- break;
- case LEFTMOUSE: /* release LMB */
- if (event->val == KM_RELEASE) {
- if (!sad->sa2 || sad->sa1 == sad->sa2) {
- area_swap_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
+ switch (event->type) {
+ case MOUSEMOVE:
+ /* second area, for join */
+ sad->sa2 = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, event->x, event->y);
+ break;
+ case LEFTMOUSE: /* release LMB */
+ if (event->val == KM_RELEASE) {
+ if (!sad->sa2 || sad->sa1 == sad->sa2) {
+ area_swap_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
- ED_area_tag_redraw(sad->sa1);
- ED_area_tag_redraw(sad->sa2);
+ ED_area_tag_redraw(sad->sa1);
+ ED_area_tag_redraw(sad->sa2);
- ED_area_swapspace(C, sad->sa1, sad->sa2);
+ ED_area_swapspace(C, sad->sa1, sad->sa2);
- area_swap_exit(C, op);
+ area_swap_exit(C, op);
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
- }
- break;
+ return OPERATOR_FINISHED;
+ }
+ break;
- case ESCKEY:
- area_swap_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- return OPERATOR_RUNNING_MODAL;
+ case ESCKEY:
+ area_swap_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ return OPERATOR_RUNNING_MODAL;
}
static void SCREEN_OT_area_swap(wmOperatorType *ot)
{
- ot->name = "Swap Areas";
- ot->description = "Swap selected areas screen positions";
- ot->idname = "SCREEN_OT_area_swap";
+ ot->name = "Swap Areas";
+ ot->description = "Swap selected areas screen positions";
+ ot->idname = "SCREEN_OT_area_swap";
- ot->invoke = area_swap_invoke;
- ot->modal = area_swap_modal;
- ot->poll = ED_operator_areaactive;
- ot->cancel = area_swap_cancel;
+ ot->invoke = area_swap_invoke;
+ ot->modal = area_swap_modal;
+ ot->poll = ED_operator_areaactive;
+ ot->cancel = area_swap_cancel;
- ot->flag = OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_BLOCKING;
}
/** \} */
@@ -1173,81 +1177,81 @@ static void SCREEN_OT_area_swap(wmOperatorType *ot)
/* operator callback */
static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Main *bmain = CTX_data_main(C);
- wmWindow *newwin, *win = CTX_wm_window(C);
- Scene *scene;
- WorkSpace *workspace = WM_window_get_active_workspace(win);
- WorkSpaceLayout *layout_old = WM_window_get_active_layout(win);
- WorkSpaceLayout *layout_new;
- bScreen *newsc;
- ScrArea *sa;
- rcti rect;
-
- win = CTX_wm_window(C);
- scene = CTX_data_scene(C);
- sa = CTX_wm_area(C);
+ Main *bmain = CTX_data_main(C);
+ wmWindow *newwin, *win = CTX_wm_window(C);
+ Scene *scene;
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+ WorkSpaceLayout *layout_old = WM_window_get_active_layout(win);
+ WorkSpaceLayout *layout_new;
+ bScreen *newsc;
+ ScrArea *sa;
+ rcti rect;
- /* XXX hrmf! */
- if (event->type == EVT_ACTIONZONE_AREA) {
- sActionzoneData *sad = event->customdata;
+ win = CTX_wm_window(C);
+ scene = CTX_data_scene(C);
+ sa = CTX_wm_area(C);
- if (sad == NULL)
- return OPERATOR_PASS_THROUGH;
+ /* XXX hrmf! */
+ if (event->type == EVT_ACTIONZONE_AREA) {
+ sActionzoneData *sad = event->customdata;
- sa = sad->sa1;
- }
+ if (sad == NULL)
+ return OPERATOR_PASS_THROUGH;
- /* adds window to WM */
- rect = sa->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;
+ sa = sad->sa1;
+ }
- newwin = WM_window_open(C, &rect);
- if (newwin == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Failed to open window!");
- goto finally;
- }
+ /* adds window to WM */
+ rect = sa->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;
- *newwin->stereo3d_format = *win->stereo3d_format;
+ newwin = WM_window_open(C, &rect);
+ if (newwin == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Failed to open window!");
+ goto finally;
+ }
- newwin->scene = scene;
+ *newwin->stereo3d_format = *win->stereo3d_format;
- BKE_workspace_active_set(newwin->workspace_hook, workspace);
- /* allocs new screen and adds to newly created window, using window size */
- layout_new = ED_workspace_layout_add(bmain, workspace, newwin, BKE_workspace_layout_name_get(layout_old));
- newsc = BKE_workspace_layout_screen_get(layout_new);
- WM_window_set_active_layout(newwin, workspace, layout_new);
+ newwin->scene = scene;
- /* copy area to new screen */
- ED_area_data_copy((ScrArea *)newsc->areabase.first, sa, true);
+ BKE_workspace_active_set(newwin->workspace_hook, workspace);
+ /* allocs new screen and adds to newly created window, using window size */
+ layout_new = ED_workspace_layout_add(
+ bmain, workspace, newwin, BKE_workspace_layout_name_get(layout_old));
+ newsc = BKE_workspace_layout_screen_get(layout_new);
+ WM_window_set_active_layout(newwin, workspace, layout_new);
- ED_area_tag_redraw((ScrArea *)newsc->areabase.first);
+ /* copy area to new screen */
+ ED_area_data_copy((ScrArea *)newsc->areabase.first, sa, true);
- /* screen, areas init */
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ ED_area_tag_redraw((ScrArea *)newsc->areabase.first);
+ /* screen, areas init */
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
finally:
- if (event->type == EVT_ACTIONZONE_AREA)
- actionzone_exit(op);
+ if (event->type == EVT_ACTIONZONE_AREA)
+ actionzone_exit(op);
- if (newwin) {
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ if (newwin) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static void SCREEN_OT_area_dupli(wmOperatorType *ot)
{
- ot->name = "Duplicate Area into New Window";
- ot->description = "Duplicate selected area into new window";
- ot->idname = "SCREEN_OT_area_dupli";
+ ot->name = "Duplicate Area into New Window";
+ ot->description = "Duplicate selected area into new window";
+ ot->idname = "SCREEN_OT_area_dupli";
- ot->invoke = area_dupli_invoke;
- ot->poll = ED_operator_areaactive;
+ ot->invoke = area_dupli_invoke;
+ ot->poll = ED_operator_areaactive;
}
/** \} */
@@ -1265,9 +1269,9 @@ static void SCREEN_OT_area_dupli(wmOperatorType *ot)
* init() set default property values, find edge based on mouse coords, test
* if the edge can be moved, select edges, calculate min and max movement
*
- * apply() apply delta on selection
+ * apply() apply delta on selection
*
- * exit() cleanup, send notifier
+ * exit() cleanup, send notifier
*
* cancel() cancel moving
*
@@ -1285,443 +1289,454 @@ static void SCREEN_OT_area_dupli(wmOperatorType *ot)
*/
typedef struct sAreaMoveData {
- int bigger, smaller, origval, step;
- char dir;
- enum AreaMoveSnapType {
- /* Snapping disabled */
- SNAP_NONE = 0,
- /* Snap to an invisible grid with a unit defined in AREAGRID */
- SNAP_AREAGRID,
- /* Snap to fraction (half, third.. etc) and adjacent edges. */
- SNAP_FRACTION_AND_ADJACENT,
- /* Snap to either bigger or smaller, nothing in-between (used for
- * global areas). This has priority over other snap types, if it is
- * used, toggling SNAP_FRACTION_AND_ADJACENT doesn't work. */
- SNAP_BIGGER_SMALLER_ONLY,
- } snap_type;
+ int bigger, smaller, origval, step;
+ char dir;
+ enum AreaMoveSnapType {
+ /* Snapping disabled */
+ SNAP_NONE = 0,
+ /* Snap to an invisible grid with a unit defined in AREAGRID */
+ SNAP_AREAGRID,
+ /* Snap to fraction (half, third.. etc) and adjacent edges. */
+ SNAP_FRACTION_AND_ADJACENT,
+ /* Snap to either bigger or smaller, nothing in-between (used for
+ * global areas). This has priority over other snap types, if it is
+ * used, toggling SNAP_FRACTION_AND_ADJACENT doesn't work. */
+ SNAP_BIGGER_SMALLER_ONLY,
+ } snap_type;
} 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)
-{
- rcti window_rect;
- int areaminy = ED_area_headersize();
- int areamin;
-
- /* we check all areas and test for free space with MINSIZE */
- *bigger = *smaller = 100000;
-
- if (use_bigger_smaller_snap != NULL) {
- *use_bigger_smaller_snap = false;
- for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) {
- int size_min = ED_area_global_min_size_y(area) - 1;
- int size_max = ED_area_global_max_size_y(area) - 1;
-
- size_min = max_ii(size_min, 0);
- BLI_assert(size_min < size_max);
-
- /* logic here is only tested for lower edge :) */
- /* left edge */
- if ((area->v1->editflag && area->v2->editflag)) {
- *smaller = area->v4->vec.x - size_max;
- *bigger = area->v4->vec.x - size_min;
- *use_bigger_smaller_snap = true;
- return;
- }
- /* top edge */
- else if ((area->v2->editflag && area->v3->editflag)) {
- *smaller = area->v1->vec.y + size_min;
- *bigger = area->v1->vec.y + size_max;
- *use_bigger_smaller_snap = true;
- return;
- }
- /* right edge */
- else if ((area->v3->editflag && area->v4->editflag)) {
- *smaller = area->v1->vec.x + size_min;
- *bigger = area->v1->vec.x + size_max;
- *use_bigger_smaller_snap = true;
- return;
- }
- /* lower edge */
- else if ((area->v4->editflag && area->v1->editflag)) {
- *smaller = area->v2->vec.y - size_max;
- *bigger = area->v2->vec.y - size_min;
- *use_bigger_smaller_snap = true;
- return;
- }
- }
- }
-
- WM_window_rect_calc(win, &window_rect);
-
- for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
- if (dir == 'h') {
- int y1;
- areamin = areaminy;
-
- if (sa->v1->vec.y > window_rect.ymin)
- areamin += U.pixelsize;
- if (sa->v2->vec.y < (window_rect.ymax - 1))
- areamin += U.pixelsize;
-
- y1 = screen_geom_area_height(sa) - areamin;
-
- /* if top or down edge selected, test height */
- if (sa->v1->editflag && sa->v4->editflag)
- *bigger = min_ii(*bigger, y1);
- else if (sa->v2->editflag && sa->v3->editflag)
- *smaller = min_ii(*smaller, y1);
- }
- else {
- int x1;
- areamin = AREAMINX;
-
- if (sa->v1->vec.x > window_rect.xmin)
- areamin += U.pixelsize;
- if (sa->v4->vec.x < (window_rect.xmax - 1))
- areamin += U.pixelsize;
-
- x1 = screen_geom_area_width(sa) - areamin;
-
- /* if left or right edge selected, test width */
- if (sa->v1->editflag && sa->v2->editflag)
- *bigger = min_ii(*bigger, x1);
- else if (sa->v3->editflag && sa->v4->editflag)
- *smaller = min_ii(*smaller, x1);
- }
- }
+ wmWindow *win, bScreen *sc, int dir, int *bigger, int *smaller, bool *use_bigger_smaller_snap)
+{
+ rcti window_rect;
+ int areaminy = ED_area_headersize();
+ int areamin;
+
+ /* we check all areas and test for free space with MINSIZE */
+ *bigger = *smaller = 100000;
+
+ if (use_bigger_smaller_snap != NULL) {
+ *use_bigger_smaller_snap = false;
+ for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) {
+ int size_min = ED_area_global_min_size_y(area) - 1;
+ int size_max = ED_area_global_max_size_y(area) - 1;
+
+ size_min = max_ii(size_min, 0);
+ BLI_assert(size_min < size_max);
+
+ /* logic here is only tested for lower edge :) */
+ /* left edge */
+ if ((area->v1->editflag && area->v2->editflag)) {
+ *smaller = area->v4->vec.x - size_max;
+ *bigger = area->v4->vec.x - size_min;
+ *use_bigger_smaller_snap = true;
+ return;
+ }
+ /* top edge */
+ else if ((area->v2->editflag && area->v3->editflag)) {
+ *smaller = area->v1->vec.y + size_min;
+ *bigger = area->v1->vec.y + size_max;
+ *use_bigger_smaller_snap = true;
+ return;
+ }
+ /* right edge */
+ else if ((area->v3->editflag && area->v4->editflag)) {
+ *smaller = area->v1->vec.x + size_min;
+ *bigger = area->v1->vec.x + size_max;
+ *use_bigger_smaller_snap = true;
+ return;
+ }
+ /* lower edge */
+ else if ((area->v4->editflag && area->v1->editflag)) {
+ *smaller = area->v2->vec.y - size_max;
+ *bigger = area->v2->vec.y - size_min;
+ *use_bigger_smaller_snap = true;
+ return;
+ }
+ }
+ }
+
+ WM_window_rect_calc(win, &window_rect);
+
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
+ if (dir == 'h') {
+ int y1;
+ areamin = areaminy;
+
+ if (sa->v1->vec.y > window_rect.ymin)
+ areamin += U.pixelsize;
+ if (sa->v2->vec.y < (window_rect.ymax - 1))
+ areamin += U.pixelsize;
+
+ y1 = screen_geom_area_height(sa) - areamin;
+
+ /* if top or down edge selected, test height */
+ if (sa->v1->editflag && sa->v4->editflag)
+ *bigger = min_ii(*bigger, y1);
+ else if (sa->v2->editflag && sa->v3->editflag)
+ *smaller = min_ii(*smaller, y1);
+ }
+ else {
+ int x1;
+ areamin = AREAMINX;
+
+ if (sa->v1->vec.x > window_rect.xmin)
+ areamin += U.pixelsize;
+ if (sa->v4->vec.x < (window_rect.xmax - 1))
+ areamin += U.pixelsize;
+
+ x1 = screen_geom_area_width(sa) - areamin;
+
+ /* if left or right edge selected, test width */
+ if (sa->v1->editflag && sa->v2->editflag)
+ *bigger = min_ii(*bigger, x1);
+ else if (sa->v3->editflag && sa->v4->editflag)
+ *smaller = min_ii(*smaller, x1);
+ }
+ }
}
/* validate selection inside screen, set variables OK */
/* return 0: init failed */
static int area_move_init(bContext *C, wmOperator *op)
{
- bScreen *sc = CTX_wm_screen(C);
- wmWindow *win = CTX_wm_window(C);
- ScrEdge *actedge;
- sAreaMoveData *md;
- int x, y;
-
- /* required properties */
- x = RNA_int_get(op->ptr, "x");
- y = RNA_int_get(op->ptr, "y");
-
- /* setup */
- actedge = screen_geom_find_active_scredge(win, sc, x, y);
- if (actedge == NULL) return 0;
-
- md = MEM_callocN(sizeof(sAreaMoveData), "sAreaMoveData");
- op->customdata = md;
-
- md->dir = screen_geom_edge_is_horizontal(actedge) ? 'h' : 'v';
- if (md->dir == 'h') md->origval = actedge->v1->vec.y;
- else md->origval = actedge->v1->vec.x;
-
- 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) {
- 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);
-
- md->snap_type = use_bigger_smaller_snap ? SNAP_BIGGER_SMALLER_ONLY : SNAP_AREAGRID;
-
- return 1;
-}
-
-static int area_snap_calc_location(
- const bScreen *sc, const enum AreaMoveSnapType snap_type,
- const int delta, const int origval, const int dir,
- const int bigger, const int smaller)
-{
- BLI_assert(snap_type != SNAP_NONE);
- int m_cursor_final = -1;
- const int m_cursor = origval + delta;
- const int m_span = (float)(bigger + smaller);
- const int m_min = origval - smaller;
- // const int axis_max = axis_min + m_span;
-
- switch (snap_type) {
- case SNAP_AREAGRID:
- m_cursor_final = m_cursor;
- if (delta != bigger && delta != -smaller) {
- m_cursor_final -= (m_cursor % AREAGRID);
- CLAMP(m_cursor_final, origval - smaller, origval + bigger);
- }
- break;
-
- case SNAP_BIGGER_SMALLER_ONLY:
- m_cursor_final = (m_cursor >= bigger) ? bigger : smaller;
- break;
-
- case SNAP_FRACTION_AND_ADJACENT:
- {
- const int axis = (dir == 'v') ? 0 : 1;
- int snap_dist_best = INT_MAX;
- {
- const float div_array[] = {
- /* Middle. */
- 1.0f / 2.0f,
- /* Thirds. */
- 1.0f / 3.0f, 2.0f / 3.0f,
- /* Quaters. */
- 1.0f / 4.0f, 3.0f / 4.0f,
- /* Eighth. */
- 1.0f / 8.0f, 3.0f / 8.0f,
- 5.0f / 8.0f, 7.0f / 8.0f,
- };
- /* Test the snap to the best division. */
- for (int i = 0; i < ARRAY_SIZE(div_array); i++) {
- const int m_cursor_test = m_min + round_fl_to_int(m_span * div_array[i]);
- const int snap_dist_test = abs(m_cursor - m_cursor_test);
- if (snap_dist_best >= snap_dist_test) {
- snap_dist_best = snap_dist_test;
- m_cursor_final = m_cursor_test;
- }
- }
- }
-
- for (const ScrVert *v1 = sc->vertbase.first; v1; v1 = v1->next) {
- if (!v1->editflag) {
- continue;
- }
- const int v_loc = (&v1->vec.x)[!axis];
-
- for (const ScrVert *v2 = sc->vertbase.first; v2; v2 = v2->next) {
- if (v2->editflag) {
- continue;
- }
- if (v_loc == (&v2->vec.x)[!axis]) {
- const int v_loc2 = (&v2->vec.x)[axis];
- /* Do not snap to the vertices at the ends. */
- if ((origval - smaller) < v_loc2 && v_loc2 < (origval + bigger)) {
- const int snap_dist_test = abs(m_cursor - v_loc2);
- if (snap_dist_best >= snap_dist_test) {
- snap_dist_best = snap_dist_test;
- m_cursor_final = v_loc2;
- }
- }
- }
- }
- }
- break;
- }
- case SNAP_NONE:
- break;
- }
-
- BLI_assert(ELEM(snap_type, SNAP_BIGGER_SMALLER_ONLY) ||
- IN_RANGE_INCL(m_cursor_final, origval - smaller, origval + bigger));
-
- return m_cursor_final;
+ bScreen *sc = CTX_wm_screen(C);
+ wmWindow *win = CTX_wm_window(C);
+ ScrEdge *actedge;
+ sAreaMoveData *md;
+ int x, y;
+
+ /* required properties */
+ x = RNA_int_get(op->ptr, "x");
+ y = RNA_int_get(op->ptr, "y");
+
+ /* setup */
+ actedge = screen_geom_find_active_scredge(win, sc, x, y);
+ if (actedge == NULL)
+ return 0;
+
+ md = MEM_callocN(sizeof(sAreaMoveData), "sAreaMoveData");
+ op->customdata = md;
+
+ md->dir = screen_geom_edge_is_horizontal(actedge) ? 'h' : 'v';
+ if (md->dir == 'h')
+ md->origval = actedge->v1->vec.y;
+ else
+ md->origval = actedge->v1->vec.x;
+
+ 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)
+ {
+ 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);
+
+ md->snap_type = use_bigger_smaller_snap ? SNAP_BIGGER_SMALLER_ONLY : SNAP_AREAGRID;
+
+ return 1;
+}
+
+static int area_snap_calc_location(const bScreen *sc,
+ const enum AreaMoveSnapType snap_type,
+ const int delta,
+ const int origval,
+ const int dir,
+ const int bigger,
+ const int smaller)
+{
+ BLI_assert(snap_type != SNAP_NONE);
+ int m_cursor_final = -1;
+ const int m_cursor = origval + delta;
+ const int m_span = (float)(bigger + smaller);
+ const int m_min = origval - smaller;
+ // const int axis_max = axis_min + m_span;
+
+ switch (snap_type) {
+ case SNAP_AREAGRID:
+ m_cursor_final = m_cursor;
+ if (delta != bigger && delta != -smaller) {
+ m_cursor_final -= (m_cursor % AREAGRID);
+ CLAMP(m_cursor_final, origval - smaller, origval + bigger);
+ }
+ break;
+
+ case SNAP_BIGGER_SMALLER_ONLY:
+ m_cursor_final = (m_cursor >= bigger) ? bigger : smaller;
+ break;
+
+ case SNAP_FRACTION_AND_ADJACENT: {
+ const int axis = (dir == 'v') ? 0 : 1;
+ int snap_dist_best = INT_MAX;
+ {
+ const float div_array[] = {
+ /* Middle. */
+ 1.0f / 2.0f,
+ /* Thirds. */
+ 1.0f / 3.0f,
+ 2.0f / 3.0f,
+ /* Quaters. */
+ 1.0f / 4.0f,
+ 3.0f / 4.0f,
+ /* Eighth. */
+ 1.0f / 8.0f,
+ 3.0f / 8.0f,
+ 5.0f / 8.0f,
+ 7.0f / 8.0f,
+ };
+ /* Test the snap to the best division. */
+ for (int i = 0; i < ARRAY_SIZE(div_array); i++) {
+ const int m_cursor_test = m_min + round_fl_to_int(m_span * div_array[i]);
+ const int snap_dist_test = abs(m_cursor - m_cursor_test);
+ if (snap_dist_best >= snap_dist_test) {
+ snap_dist_best = snap_dist_test;
+ m_cursor_final = m_cursor_test;
+ }
+ }
+ }
+
+ for (const ScrVert *v1 = sc->vertbase.first; v1; v1 = v1->next) {
+ if (!v1->editflag) {
+ continue;
+ }
+ const int v_loc = (&v1->vec.x)[!axis];
+
+ for (const ScrVert *v2 = sc->vertbase.first; v2; v2 = v2->next) {
+ if (v2->editflag) {
+ continue;
+ }
+ if (v_loc == (&v2->vec.x)[!axis]) {
+ const int v_loc2 = (&v2->vec.x)[axis];
+ /* Do not snap to the vertices at the ends. */
+ if ((origval - smaller) < v_loc2 && v_loc2 < (origval + bigger)) {
+ const int snap_dist_test = abs(m_cursor - v_loc2);
+ if (snap_dist_best >= snap_dist_test) {
+ snap_dist_best = snap_dist_test;
+ m_cursor_final = v_loc2;
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ case SNAP_NONE:
+ break;
+ }
+
+ BLI_assert(ELEM(snap_type, SNAP_BIGGER_SMALLER_ONLY) ||
+ IN_RANGE_INCL(m_cursor_final, origval - smaller, origval + bigger));
+
+ return m_cursor_final;
}
/* moves selected screen edge amount of delta, used by split & move */
-static void area_move_apply_do(
- const bContext *C, int delta,
- const int origval, const int dir,
- const int bigger, const int smaller,
- const enum AreaMoveSnapType snap_type)
-{
- wmWindow *win = CTX_wm_window(C);
- bScreen *sc = CTX_wm_screen(C);
- short final_loc = -1;
- bool doredraw = false;
-
- if (snap_type != SNAP_BIGGER_SMALLER_ONLY) {
- CLAMP(delta, -smaller, bigger);
- }
-
- if (snap_type == SNAP_NONE) {
- final_loc = origval + delta;
- }
- else {
- final_loc = area_snap_calc_location(sc, 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) {
- if (v1->editflag) {
- short oldval = (&v1->vec.x)[axis];
- (&v1->vec.x)[axis] = final_loc;
-
- if (oldval == final_loc) {
- /* nothing will change to the other vertices either. */
- break;
- }
- doredraw = true;
- }
- }
-
- /* 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)) {
- /* 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;
- }
- else {
- sa->global->cur_fixed_height = sa->global->size_max;
- }
-
- sc->do_refresh = true;
- redraw_all = true;
- }
- ED_area_tag_redraw(sa);
- }
- }
- if (redraw_all) {
- ED_screen_areas_iter(win, sc, sa) {
- ED_area_tag_redraw(sa);
- }
- }
-
- ED_screen_global_areas_sync(win);
-
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); /* redraw everything */
- /* Update preview thumbnail */
- BKE_icon_changed(sc->id.icon_id);
- }
+static void area_move_apply_do(const bContext *C,
+ int delta,
+ const int origval,
+ const int dir,
+ const int bigger,
+ const int smaller,
+ const enum AreaMoveSnapType snap_type)
+{
+ wmWindow *win = CTX_wm_window(C);
+ bScreen *sc = CTX_wm_screen(C);
+ short final_loc = -1;
+ bool doredraw = false;
+
+ if (snap_type != SNAP_BIGGER_SMALLER_ONLY) {
+ CLAMP(delta, -smaller, bigger);
+ }
+
+ if (snap_type == SNAP_NONE) {
+ final_loc = origval + delta;
+ }
+ else {
+ final_loc = area_snap_calc_location(sc, 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)
+ {
+ if (v1->editflag) {
+ short oldval = (&v1->vec.x)[axis];
+ (&v1->vec.x)[axis] = final_loc;
+
+ if (oldval == final_loc) {
+ /* nothing will change to the other vertices either. */
+ break;
+ }
+ doredraw = true;
+ }
+ }
+
+ /* 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)) {
+ /* 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;
+ }
+ else {
+ sa->global->cur_fixed_height = sa->global->size_max;
+ }
+
+ sc->do_refresh = true;
+ redraw_all = true;
+ }
+ ED_area_tag_redraw(sa);
+ }
+ }
+ if (redraw_all) {
+ ED_screen_areas_iter(win, sc, sa)
+ {
+ ED_area_tag_redraw(sa);
+ }
+ }
+
+ ED_screen_global_areas_sync(win);
+
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); /* redraw everything */
+ /* Update preview thumbnail */
+ BKE_icon_changed(sc->id.icon_id);
+ }
}
static void area_move_apply(bContext *C, wmOperator *op)
{
- sAreaMoveData *md = op->customdata;
- int delta = RNA_int_get(op->ptr, "delta");
+ sAreaMoveData *md = op->customdata;
+ int delta = RNA_int_get(op->ptr, "delta");
- area_move_apply_do(C, delta, md->origval, md->dir, md->bigger, md->smaller, md->snap_type);
+ area_move_apply_do(C, delta, md->origval, md->dir, md->bigger, md->smaller, md->snap_type);
}
static void area_move_exit(bContext *C, wmOperator *op)
{
- if (op->customdata)
- MEM_freeN(op->customdata);
- op->customdata = NULL;
+ if (op->customdata)
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
- /* this makes sure aligned edges will result in aligned grabbing */
- BKE_screen_remove_double_scrverts(CTX_wm_screen(C));
- BKE_screen_remove_double_scredges(CTX_wm_screen(C));
+ /* this makes sure aligned edges will result in aligned grabbing */
+ BKE_screen_remove_double_scrverts(CTX_wm_screen(C));
+ BKE_screen_remove_double_scredges(CTX_wm_screen(C));
- G.moving &= ~G_TRANSFORM_WM;
+ G.moving &= ~G_TRANSFORM_WM;
}
static int area_move_exec(bContext *C, wmOperator *op)
{
- if (!area_move_init(C, op))
- return OPERATOR_CANCELLED;
+ if (!area_move_init(C, op))
+ return OPERATOR_CANCELLED;
- area_move_apply(C, op);
- area_move_exit(C, op);
+ area_move_apply(C, op);
+ area_move_exit(C, op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* interaction callback */
static int area_move_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- RNA_int_set(op->ptr, "x", event->x);
- RNA_int_set(op->ptr, "y", event->y);
+ RNA_int_set(op->ptr, "x", event->x);
+ RNA_int_set(op->ptr, "y", event->y);
- if (!area_move_init(C, op))
- return OPERATOR_PASS_THROUGH;
+ if (!area_move_init(C, op))
+ return OPERATOR_PASS_THROUGH;
- G.moving |= G_TRANSFORM_WM;
+ G.moving |= G_TRANSFORM_WM;
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static void area_move_cancel(bContext *C, wmOperator *op)
{
- RNA_int_set(op->ptr, "delta", 0);
- area_move_apply(C, op);
- area_move_exit(C, op);
+ RNA_int_set(op->ptr, "delta", 0);
+ area_move_apply(C, op);
+ area_move_exit(C, op);
}
/* modal callback for while moving edges */
static int area_move_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- sAreaMoveData *md = op->customdata;
- int delta, x, y;
-
- /* execute the events */
- switch (event->type) {
- case MOUSEMOVE:
- {
- x = RNA_int_get(op->ptr, "x");
- y = RNA_int_get(op->ptr, "y");
-
- delta = (md->dir == 'v') ? event->x - x : event->y - y;
- RNA_int_set(op->ptr, "delta", delta);
-
- area_move_apply(C, op);
- break;
- }
- case EVT_MODAL_MAP:
- {
- switch (event->val) {
- case KM_MODAL_APPLY:
- area_move_exit(C, op);
- return OPERATOR_FINISHED;
-
- case KM_MODAL_CANCEL:
- area_move_cancel(C, op);
- return OPERATOR_CANCELLED;
-
- case KM_MODAL_SNAP_ON:
- if (md->snap_type != SNAP_BIGGER_SMALLER_ONLY) {
- md->snap_type = SNAP_FRACTION_AND_ADJACENT;
- }
- break;
-
- case KM_MODAL_SNAP_OFF:
- if (md->snap_type != SNAP_BIGGER_SMALLER_ONLY) {
- md->snap_type = SNAP_AREAGRID;
- }
- break;
- }
- break;
- }
- }
-
- return OPERATOR_RUNNING_MODAL;
+ sAreaMoveData *md = op->customdata;
+ int delta, x, y;
+
+ /* execute the events */
+ switch (event->type) {
+ case MOUSEMOVE: {
+ x = RNA_int_get(op->ptr, "x");
+ y = RNA_int_get(op->ptr, "y");
+
+ delta = (md->dir == 'v') ? event->x - x : event->y - y;
+ RNA_int_set(op->ptr, "delta", delta);
+
+ area_move_apply(C, op);
+ break;
+ }
+ case EVT_MODAL_MAP: {
+ switch (event->val) {
+ case KM_MODAL_APPLY:
+ area_move_exit(C, op);
+ return OPERATOR_FINISHED;
+
+ case KM_MODAL_CANCEL:
+ area_move_cancel(C, op);
+ return OPERATOR_CANCELLED;
+
+ case KM_MODAL_SNAP_ON:
+ if (md->snap_type != SNAP_BIGGER_SMALLER_ONLY) {
+ md->snap_type = SNAP_FRACTION_AND_ADJACENT;
+ }
+ break;
+
+ case KM_MODAL_SNAP_OFF:
+ if (md->snap_type != SNAP_BIGGER_SMALLER_ONLY) {
+ md->snap_type = SNAP_AREAGRID;
+ }
+ break;
+ }
+ break;
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
static void SCREEN_OT_area_move(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move Area Edges";
- ot->description = "Move selected area edges";
- ot->idname = "SCREEN_OT_area_move";
+ /* identifiers */
+ ot->name = "Move Area Edges";
+ ot->description = "Move selected area edges";
+ ot->idname = "SCREEN_OT_area_move";
- ot->exec = area_move_exec;
- ot->invoke = area_move_invoke;
- ot->cancel = area_move_cancel;
- ot->modal = area_move_modal;
- ot->poll = ED_operator_screen_mainwinactive; /* when mouse is over area-edge */
+ ot->exec = area_move_exec;
+ ot->invoke = area_move_invoke;
+ ot->cancel = area_move_cancel;
+ ot->modal = area_move_modal;
+ ot->poll = ED_operator_screen_mainwinactive; /* when mouse is over area-edge */
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
- /* rna */
- RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
+ /* rna */
+ RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
}
/** \} */
@@ -1765,496 +1780,506 @@ static void SCREEN_OT_area_move(wmOperatorType *ot)
*/
typedef struct sAreaSplitData {
- int origval; /* for move areas */
- int bigger, smaller; /* constraints for moving new edge */
- int delta; /* delta move edge */
- int origmin, origsize; /* to calculate fac, for property storage */
- int previewmode; /* draw previewline, then split */
- void *draw_callback; /* call `ED_screen_draw_split_preview` */
- bool do_snap;
-
- ScrEdge *nedge; /* new edge */
- ScrArea *sarea; /* start area */
- ScrArea *narea; /* new area */
+ int origval; /* for move areas */
+ int bigger, smaller; /* constraints for moving new edge */
+ int delta; /* delta move edge */
+ int origmin, origsize; /* to calculate fac, for property storage */
+ int previewmode; /* draw previewline, then split */
+ void *draw_callback; /* call `ED_screen_draw_split_preview` */
+ bool do_snap;
+
+ ScrEdge *nedge; /* new edge */
+ ScrArea *sarea; /* start area */
+ ScrArea *narea; /* new area */
} sAreaSplitData;
static void area_split_draw_cb(const struct wmWindow *UNUSED(win), void *userdata)
{
- const wmOperator *op = userdata;
+ const wmOperator *op = userdata;
- sAreaSplitData *sd = op->customdata;
- if (sd->sarea) {
- int dir = RNA_enum_get(op->ptr, "direction");
- float fac = RNA_float_get(op->ptr, "factor");
+ sAreaSplitData *sd = op->customdata;
+ if (sd->sarea) {
+ int dir = RNA_enum_get(op->ptr, "direction");
+ float fac = RNA_float_get(op->ptr, "factor");
- ED_screen_draw_split_preview(sd->sarea, dir, fac);
- }
+ ED_screen_draw_split_preview(sd->sarea, dir, fac);
+ }
}
/* generic init, menu case, doesn't need active area */
static int area_split_menu_init(bContext *C, wmOperator *op)
{
- sAreaSplitData *sd;
+ sAreaSplitData *sd;
- /* custom data */
- sd = (sAreaSplitData *)MEM_callocN(sizeof(sAreaSplitData), "op_area_split");
- op->customdata = sd;
+ /* custom data */
+ sd = (sAreaSplitData *)MEM_callocN(sizeof(sAreaSplitData), "op_area_split");
+ op->customdata = sd;
- sd->sarea = CTX_wm_area(C);
+ sd->sarea = CTX_wm_area(C);
- return 1;
+ return 1;
}
/* generic init, no UI stuff here, assumes active area */
static int area_split_init(bContext *C, wmOperator *op)
{
- ScrArea *sa = CTX_wm_area(C);
- sAreaSplitData *sd;
- int areaminy = ED_area_headersize();
- int dir;
+ ScrArea *sa = CTX_wm_area(C);
+ sAreaSplitData *sd;
+ int areaminy = ED_area_headersize();
+ int dir;
- /* required context */
- if (sa == NULL) return 0;
+ /* required context */
+ if (sa == NULL)
+ return 0;
- /* required properties */
- dir = RNA_enum_get(op->ptr, "direction");
+ /* required properties */
+ dir = RNA_enum_get(op->ptr, "direction");
- /* minimal size */
- if (dir == 'v' && sa->winx < 2 * AREAMINX) return 0;
- if (dir == 'h' && sa->winy < 2 * areaminy) return 0;
+ /* minimal size */
+ if (dir == 'v' && sa->winx < 2 * AREAMINX)
+ return 0;
+ if (dir == 'h' && sa->winy < 2 * areaminy)
+ return 0;
- /* custom data */
- sd = (sAreaSplitData *)MEM_callocN(sizeof(sAreaSplitData), "op_area_split");
- op->customdata = sd;
+ /* custom data */
+ sd = (sAreaSplitData *)MEM_callocN(sizeof(sAreaSplitData), "op_area_split");
+ op->customdata = sd;
- sd->sarea = sa;
- if (dir == 'v') {
- sd->origmin = sa->v1->vec.x;
- sd->origsize = sa->v4->vec.x - sd->origmin;
- }
- else {
- sd->origmin = sa->v1->vec.y;
- sd->origsize = sa->v2->vec.y - sd->origmin;
- }
+ sd->sarea = sa;
+ if (dir == 'v') {
+ sd->origmin = sa->v1->vec.x;
+ sd->origsize = sa->v4->vec.x - sd->origmin;
+ }
+ else {
+ sd->origmin = sa->v1->vec.y;
+ sd->origsize = sa->v2->vec.y - sd->origmin;
+ }
- return 1;
+ return 1;
}
/* with sa 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)
{
- ScrVert *sav1 = sa->v1;
- ScrVert *sav2 = sa->v2;
- ScrVert *sav3 = sa->v3;
- ScrVert *sav4 = sa->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 */
- return BKE_screen_find_edge(screen, sav1, sav2);
- }
- else if (sav2 == sbv1 && sav3 == sbv4) { /* sa 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 */
- return BKE_screen_find_edge(screen, sav3, sav4);
- }
- else if (sav1 == sbv2 && sav4 == sbv3) { /* sa on top of sb = S*/
- return BKE_screen_find_edge(screen, sav1, sav4);
- }
-
- return NULL;
+ ScrVert *sav1 = sa->v1;
+ ScrVert *sav2 = sa->v2;
+ ScrVert *sav3 = sa->v3;
+ ScrVert *sav4 = sa->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 */
+ return BKE_screen_find_edge(screen, sav1, sav2);
+ }
+ else if (sav2 == sbv1 && sav3 == sbv4) { /* sa 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 */
+ return BKE_screen_find_edge(screen, sav3, sav4);
+ }
+ else if (sav1 == sbv2 && sav4 == sbv3) { /* sa on top of sb = S*/
+ return BKE_screen_find_edge(screen, sav1, sav4);
+ }
+
+ return NULL;
}
-
/* do the split, return success */
static int area_split_apply(bContext *C, wmOperator *op)
{
- const wmWindow *win = CTX_wm_window(C);
- bScreen *sc = CTX_wm_screen(C);
- sAreaSplitData *sd = (sAreaSplitData *)op->customdata;
- float fac;
- int dir;
+ const wmWindow *win = CTX_wm_window(C);
+ bScreen *sc = CTX_wm_screen(C);
+ sAreaSplitData *sd = (sAreaSplitData *)op->customdata;
+ float fac;
+ int dir;
- fac = RNA_float_get(op->ptr, "factor");
- dir = RNA_enum_get(op->ptr, "direction");
+ 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, sc, sd->sarea, dir, fac, 0); /* 0 = no merge */
- if (sd->narea) {
- sd->nedge = area_findsharededge(sc, sd->sarea, sd->narea);
+ if (sd->narea) {
+ sd->nedge = area_findsharededge(sc, sd->sarea, sd->narea);
- /* select newly created edge, prepare for moving edge */
- ED_screen_verts_iter(win, sc, sv) {
- sv->editflag = 0;
- }
+ /* select newly created edge, prepare for moving edge */
+ ED_screen_verts_iter(win, sc, sv)
+ {
+ sv->editflag = 0;
+ }
- sd->nedge->v1->editflag = 1;
- sd->nedge->v2->editflag = 1;
+ sd->nedge->v1->editflag = 1;
+ sd->nedge->v2->editflag = 1;
- if (dir == 'h') sd->origval = sd->nedge->v1->vec.y;
- else sd->origval = sd->nedge->v1->vec.x;
+ if (dir == 'h')
+ sd->origval = sd->nedge->v1->vec.y;
+ else
+ sd->origval = sd->nedge->v1->vec.x;
- ED_area_tag_redraw(sd->sarea);
- ED_area_tag_redraw(sd->narea);
+ ED_area_tag_redraw(sd->sarea);
+ ED_area_tag_redraw(sd->narea);
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
- /* Update preview thumbnail */
- BKE_icon_changed(sc->id.icon_id);
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ /* Update preview thumbnail */
+ BKE_icon_changed(sc->id.icon_id);
- return 1;
- }
+ return 1;
+ }
- return 0;
+ return 0;
}
static void area_split_exit(bContext *C, wmOperator *op)
{
- if (op->customdata) {
- sAreaSplitData *sd = (sAreaSplitData *)op->customdata;
- if (sd->sarea) ED_area_tag_redraw(sd->sarea);
- if (sd->narea) ED_area_tag_redraw(sd->narea);
+ if (op->customdata) {
+ sAreaSplitData *sd = (sAreaSplitData *)op->customdata;
+ if (sd->sarea)
+ ED_area_tag_redraw(sd->sarea);
+ if (sd->narea)
+ ED_area_tag_redraw(sd->narea);
- if (sd->draw_callback)
- WM_draw_cb_exit(CTX_wm_window(C), sd->draw_callback);
+ if (sd->draw_callback)
+ WM_draw_cb_exit(CTX_wm_window(C), sd->draw_callback);
- MEM_freeN(op->customdata);
- op->customdata = NULL;
- }
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+ }
- WM_cursor_modal_restore(CTX_wm_window(C));
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ WM_cursor_modal_restore(CTX_wm_window(C));
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
- /* this makes sure aligned edges will result in aligned grabbing */
- BKE_screen_remove_double_scrverts(CTX_wm_screen(C));
- BKE_screen_remove_double_scredges(CTX_wm_screen(C));
+ /* this makes sure aligned edges will result in aligned grabbing */
+ BKE_screen_remove_double_scrverts(CTX_wm_screen(C));
+ BKE_screen_remove_double_scredges(CTX_wm_screen(C));
}
static void area_split_preview_update_cursor(bContext *C, wmOperator *op)
{
- wmWindow *win = CTX_wm_window(C);
- int dir = RNA_enum_get(op->ptr, "direction");
- WM_cursor_set(win, (dir == 'n' || dir == 's') ? BC_V_SPLITCURSOR : BC_H_SPLITCURSOR);
+ wmWindow *win = CTX_wm_window(C);
+ int dir = RNA_enum_get(op->ptr, "direction");
+ WM_cursor_set(win, (dir == 'n' || dir == 's') ? BC_V_SPLITCURSOR : BC_H_SPLITCURSOR);
}
/* UI callback, adds new handler */
static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- wmWindow *win = CTX_wm_window(C);
- bScreen *sc = CTX_wm_screen(C);
- sAreaSplitData *sd;
- int dir;
-
- /* no full window splitting allowed */
- BLI_assert(sc->state == SCREENNORMAL);
-
- PropertyRNA *prop_dir = RNA_struct_find_property(op->ptr, "direction");
- PropertyRNA *prop_factor = RNA_struct_find_property(op->ptr, "factor");
- PropertyRNA *prop_cursor = RNA_struct_find_property(op->ptr, "cursor");
-
- if (event->type == EVT_ACTIONZONE_AREA) {
- sActionzoneData *sad = event->customdata;
-
- if (sad == NULL || sad->modifier > 0) {
- return OPERATOR_PASS_THROUGH;
- }
-
- /* verify *sad itself */
- if (sad->sa1 == NULL || sad->az == NULL)
- return OPERATOR_PASS_THROUGH;
-
- /* is this our *sad? if areas not equal it should be passed on */
- if (CTX_wm_area(C) != sad->sa1 || sad->sa1 != sad->sa2)
- return OPERATOR_PASS_THROUGH;
-
- /* The factor will be close to 1.0f when near the top-left and the bottom-right corners. */
- const float factor_v = ((float)(event->y - sad->sa1->v1->vec.y)) / (float)sad->sa1->winy;
- const float factor_h = ((float)(event->x - sad->sa1->v1->vec.x)) / (float)sad->sa1->winx;
- const bool is_left = factor_v < 0.5f;
- const bool is_bottom = factor_h < 0.5f;
- const bool is_right = !is_left;
- const bool is_top = !is_bottom;
- float factor;
-
- /* Prepare operator state vars. */
- if (ELEM(sad->gesture_dir, 'n', 's')) {
- dir = 'h';
- factor = factor_h;
- }
- else {
- dir = 'v';
- factor = factor_v;
- }
-
- if ((is_top && is_left) ||
- (is_bottom && is_right))
- {
- factor = 1.0f - factor;
- }
-
- RNA_property_float_set(op->ptr, prop_factor, factor);
-
- RNA_property_enum_set(op->ptr, prop_dir, dir);
-
- /* general init, also non-UI case, adds customdata, sets area and defaults */
- if (!area_split_init(C, op)) {
- return OPERATOR_PASS_THROUGH;
- }
- }
- else if (RNA_property_is_set(op->ptr, prop_dir)) {
- ScrArea *sa = CTX_wm_area(C);
- if (sa == 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);
- }
- else {
- RNA_property_float_set(
- op->ptr, prop_factor,
- ((float)(event->y - sa->v1->vec.y)) / (float)sa->winy);
- }
-
- if (!area_split_init(C, op)) {
- return OPERATOR_CANCELLED;
- }
- }
- else {
- ScrEdge *actedge;
- rcti window_rect;
- int event_co[2];
-
- /* retrieve initial mouse coord, so we can find the active edge */
- if (RNA_property_is_set(op->ptr, prop_cursor)) {
- RNA_property_int_get_array(op->ptr, prop_cursor, event_co);
- }
- else {
- copy_v2_v2_int(event_co, &event->x);
- }
-
- 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]);
- if (actedge == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- dir = screen_geom_edge_is_horizontal(actedge) ? 'v' : 'h';
-
- RNA_property_enum_set(op->ptr, prop_dir, dir);
-
- /* special case, adds customdata, sets defaults */
- if (!area_split_menu_init(C, op)) {
- return OPERATOR_CANCELLED;
- }
- }
-
- sd = (sAreaSplitData *)op->customdata;
-
- if (event->type == EVT_ACTIONZONE_AREA) {
-
- /* do the split */
- if (area_split_apply(C, op)) {
- area_move_set_limits(win, sc, dir, &sd->bigger, &sd->smaller, NULL);
-
- /* add temp handler for edge move or cancel */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
- }
- }
- else {
- sd->previewmode = 1;
- sd->draw_callback = WM_draw_cb_activate(win, area_split_draw_cb, op);
- /* add temp handler for edge move or cancel */
- WM_event_add_modal_handler(C, op);
- area_split_preview_update_cursor(C, op);
-
- return OPERATOR_RUNNING_MODAL;
-
- }
-
- return OPERATOR_PASS_THROUGH;
+ wmWindow *win = CTX_wm_window(C);
+ bScreen *sc = CTX_wm_screen(C);
+ sAreaSplitData *sd;
+ int dir;
+
+ /* no full window splitting allowed */
+ BLI_assert(sc->state == SCREENNORMAL);
+
+ PropertyRNA *prop_dir = RNA_struct_find_property(op->ptr, "direction");
+ PropertyRNA *prop_factor = RNA_struct_find_property(op->ptr, "factor");
+ PropertyRNA *prop_cursor = RNA_struct_find_property(op->ptr, "cursor");
+
+ if (event->type == EVT_ACTIONZONE_AREA) {
+ sActionzoneData *sad = event->customdata;
+
+ if (sad == NULL || sad->modifier > 0) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ /* verify *sad itself */
+ if (sad->sa1 == NULL || sad->az == NULL)
+ return OPERATOR_PASS_THROUGH;
+
+ /* is this our *sad? if areas not equal it should be passed on */
+ if (CTX_wm_area(C) != sad->sa1 || sad->sa1 != sad->sa2)
+ return OPERATOR_PASS_THROUGH;
+
+ /* The factor will be close to 1.0f when near the top-left and the bottom-right corners. */
+ const float factor_v = ((float)(event->y - sad->sa1->v1->vec.y)) / (float)sad->sa1->winy;
+ const float factor_h = ((float)(event->x - sad->sa1->v1->vec.x)) / (float)sad->sa1->winx;
+ const bool is_left = factor_v < 0.5f;
+ const bool is_bottom = factor_h < 0.5f;
+ const bool is_right = !is_left;
+ const bool is_top = !is_bottom;
+ float factor;
+
+ /* Prepare operator state vars. */
+ if (ELEM(sad->gesture_dir, 'n', 's')) {
+ dir = 'h';
+ factor = factor_h;
+ }
+ else {
+ dir = 'v';
+ factor = factor_v;
+ }
+
+ if ((is_top && is_left) || (is_bottom && is_right)) {
+ factor = 1.0f - factor;
+ }
+
+ RNA_property_float_set(op->ptr, prop_factor, factor);
+
+ RNA_property_enum_set(op->ptr, prop_dir, dir);
+
+ /* general init, also non-UI case, adds customdata, sets area and defaults */
+ if (!area_split_init(C, op)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+ }
+ else if (RNA_property_is_set(op->ptr, prop_dir)) {
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa == 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);
+ }
+ else {
+ RNA_property_float_set(
+ op->ptr, prop_factor, ((float)(event->y - sa->v1->vec.y)) / (float)sa->winy);
+ }
+
+ if (!area_split_init(C, op)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ ScrEdge *actedge;
+ rcti window_rect;
+ int event_co[2];
+
+ /* retrieve initial mouse coord, so we can find the active edge */
+ if (RNA_property_is_set(op->ptr, prop_cursor)) {
+ RNA_property_int_get_array(op->ptr, prop_cursor, event_co);
+ }
+ else {
+ copy_v2_v2_int(event_co, &event->x);
+ }
+
+ 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]);
+ if (actedge == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ dir = screen_geom_edge_is_horizontal(actedge) ? 'v' : 'h';
+
+ RNA_property_enum_set(op->ptr, prop_dir, dir);
+
+ /* special case, adds customdata, sets defaults */
+ if (!area_split_menu_init(C, op)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ sd = (sAreaSplitData *)op->customdata;
+
+ if (event->type == EVT_ACTIONZONE_AREA) {
+
+ /* do the split */
+ if (area_split_apply(C, op)) {
+ area_move_set_limits(win, sc, dir, &sd->bigger, &sd->smaller, NULL);
+
+ /* add temp handler for edge move or cancel */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+ else {
+ sd->previewmode = 1;
+ sd->draw_callback = WM_draw_cb_activate(win, area_split_draw_cb, op);
+ /* add temp handler for edge move or cancel */
+ WM_event_add_modal_handler(C, op);
+ area_split_preview_update_cursor(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ return OPERATOR_PASS_THROUGH;
}
/* function to be called outside UI context, or for redo */
static int area_split_exec(bContext *C, wmOperator *op)
{
- if (!area_split_init(C, op))
- return OPERATOR_CANCELLED;
+ if (!area_split_init(C, op))
+ return OPERATOR_CANCELLED;
- area_split_apply(C, op);
- area_split_exit(C, op);
+ area_split_apply(C, op);
+ area_split_exit(C, op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
static void area_split_cancel(bContext *C, wmOperator *op)
{
- sAreaSplitData *sd = (sAreaSplitData *)op->customdata;
+ sAreaSplitData *sd = (sAreaSplitData *)op->customdata;
- if (sd->previewmode) {
- /* pass */
- }
- else {
- if (screen_area_join(C, CTX_wm_screen(C), sd->sarea, sd->narea)) {
- if (CTX_wm_area(C) == sd->narea) {
- CTX_wm_area_set(C, NULL);
- CTX_wm_region_set(C, NULL);
- }
- sd->narea = NULL;
- }
- }
- area_split_exit(C, op);
+ if (sd->previewmode) {
+ /* pass */
+ }
+ else {
+ if (screen_area_join(C, CTX_wm_screen(C), sd->sarea, sd->narea)) {
+ if (CTX_wm_area(C) == sd->narea) {
+ CTX_wm_area_set(C, NULL);
+ CTX_wm_region_set(C, NULL);
+ }
+ sd->narea = NULL;
+ }
+ }
+ area_split_exit(C, op);
}
static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- sAreaSplitData *sd = (sAreaSplitData *)op->customdata;
- PropertyRNA *prop_dir = RNA_struct_find_property(op->ptr, "direction");
- bool update_factor = false;
-
- /* execute the events */
- switch (event->type) {
- case MOUSEMOVE:
- update_factor = true;
- break;
-
- case LEFTMOUSE:
- if (sd->previewmode) {
- area_split_apply(C, op);
- area_split_exit(C, op);
- return OPERATOR_FINISHED;
- }
- else {
- if (event->val == KM_RELEASE) { /* mouse up */
- area_split_exit(C, op);
- return OPERATOR_FINISHED;
- }
- }
- break;
-
- case MIDDLEMOUSE:
- case TABKEY:
- if (sd->previewmode == 0) {
- /* pass */
- }
- else {
- if (event->val == KM_PRESS) {
- if (sd->sarea) {
- int dir = RNA_property_enum_get(op->ptr, prop_dir);
- RNA_property_enum_set(op->ptr, prop_dir, (dir == 'v') ? 'h' : 'v');
- area_split_preview_update_cursor(C, op);
- update_factor = true;
- }
- }
- }
-
- break;
-
- case RIGHTMOUSE: /* cancel operation */
- case ESCKEY:
- area_split_cancel(C, op);
- return OPERATOR_CANCELLED;
-
- case LEFTCTRLKEY:
- sd->do_snap = event->val == KM_PRESS;
- update_factor = true;
- break;
- }
-
- if (update_factor) {
- const int dir = RNA_property_enum_get(op->ptr, prop_dir);
-
- sd->delta = (dir == 'v') ? event->x - sd->origval : event->y - sd->origval;
-
- if (sd->previewmode == 0) {
- if (sd->do_snap) {
- const int snap_loc = area_snap_calc_location(
- CTX_wm_screen(C), SNAP_FRACTION_AND_ADJACENT, sd->delta, sd->origval, dir,
- sd->bigger, sd->smaller);
- sd->delta = snap_loc - sd->origval;
- }
- area_move_apply_do(C, sd->delta, sd->origval, dir, sd->bigger, sd->smaller, SNAP_NONE);
- }
- else {
- if (sd->sarea) {
- ED_area_tag_redraw(sd->sarea);
- }
- /* area context not set */
- 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;
- if (dir == 'v') {
- sd->origmin = sa->v1->vec.x;
- sd->origsize = sa->v4->vec.x - sd->origmin;
- }
- else {
- sd->origmin = sa->v1->vec.y;
- sd->origsize = sa->v2->vec.y - sd->origmin;
- }
-
- if (sd->do_snap) {
- sa->v1->editflag = sa->v2->editflag = sa->v3->editflag = sa->v4->editflag = 1;
-
- const int snap_loc = area_snap_calc_location(
- CTX_wm_screen(C), SNAP_FRACTION_AND_ADJACENT, sd->delta, sd->origval, dir,
- sd->origmin + sd->origsize, -sd->origmin);
-
- sa->v1->editflag = sa->v2->editflag = sa->v3->editflag = sa->v4->editflag = 0;
- sd->delta = snap_loc - sd->origval;
- }
-
- ED_area_tag_redraw(sd->sarea);
- }
-
- CTX_wm_screen(C)->do_draw = true;
- }
-
- float fac = (float)(sd->delta + sd->origval - sd->origmin) / sd->origsize;
- RNA_float_set(op->ptr, "factor", fac);
- }
-
- return OPERATOR_RUNNING_MODAL;
+ sAreaSplitData *sd = (sAreaSplitData *)op->customdata;
+ PropertyRNA *prop_dir = RNA_struct_find_property(op->ptr, "direction");
+ bool update_factor = false;
+
+ /* execute the events */
+ switch (event->type) {
+ case MOUSEMOVE:
+ update_factor = true;
+ break;
+
+ case LEFTMOUSE:
+ if (sd->previewmode) {
+ area_split_apply(C, op);
+ area_split_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ if (event->val == KM_RELEASE) { /* mouse up */
+ area_split_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ }
+ break;
+
+ case MIDDLEMOUSE:
+ case TABKEY:
+ if (sd->previewmode == 0) {
+ /* pass */
+ }
+ else {
+ if (event->val == KM_PRESS) {
+ if (sd->sarea) {
+ int dir = RNA_property_enum_get(op->ptr, prop_dir);
+ RNA_property_enum_set(op->ptr, prop_dir, (dir == 'v') ? 'h' : 'v');
+ area_split_preview_update_cursor(C, op);
+ update_factor = true;
+ }
+ }
+ }
+
+ break;
+
+ case RIGHTMOUSE: /* cancel operation */
+ case ESCKEY:
+ area_split_cancel(C, op);
+ return OPERATOR_CANCELLED;
+
+ case LEFTCTRLKEY:
+ sd->do_snap = event->val == KM_PRESS;
+ update_factor = true;
+ break;
+ }
+
+ if (update_factor) {
+ const int dir = RNA_property_enum_get(op->ptr, prop_dir);
+
+ sd->delta = (dir == 'v') ? event->x - sd->origval : event->y - sd->origval;
+
+ if (sd->previewmode == 0) {
+ if (sd->do_snap) {
+ const int snap_loc = area_snap_calc_location(CTX_wm_screen(C),
+ SNAP_FRACTION_AND_ADJACENT,
+ sd->delta,
+ sd->origval,
+ dir,
+ sd->bigger,
+ sd->smaller);
+ sd->delta = snap_loc - sd->origval;
+ }
+ area_move_apply_do(C, sd->delta, sd->origval, dir, sd->bigger, sd->smaller, SNAP_NONE);
+ }
+ else {
+ if (sd->sarea) {
+ ED_area_tag_redraw(sd->sarea);
+ }
+ /* area context not set */
+ 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;
+ if (dir == 'v') {
+ sd->origmin = sa->v1->vec.x;
+ sd->origsize = sa->v4->vec.x - sd->origmin;
+ }
+ else {
+ sd->origmin = sa->v1->vec.y;
+ sd->origsize = sa->v2->vec.y - sd->origmin;
+ }
+
+ if (sd->do_snap) {
+ sa->v1->editflag = sa->v2->editflag = sa->v3->editflag = sa->v4->editflag = 1;
+
+ const int snap_loc = area_snap_calc_location(CTX_wm_screen(C),
+ SNAP_FRACTION_AND_ADJACENT,
+ sd->delta,
+ sd->origval,
+ dir,
+ sd->origmin + sd->origsize,
+ -sd->origmin);
+
+ sa->v1->editflag = sa->v2->editflag = sa->v3->editflag = sa->v4->editflag = 0;
+ sd->delta = snap_loc - sd->origval;
+ }
+
+ ED_area_tag_redraw(sd->sarea);
+ }
+
+ CTX_wm_screen(C)->do_draw = true;
+ }
+
+ float fac = (float)(sd->delta + sd->origval - sd->origmin) / sd->origsize;
+ RNA_float_set(op->ptr, "factor", fac);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
static const EnumPropertyItem prop_direction_items[] = {
- {'h', "HORIZONTAL", 0, "Horizontal", ""},
- {'v', "VERTICAL", 0, "Vertical", ""},
- {0, NULL, 0, NULL, NULL},
+ {'h', "HORIZONTAL", 0, "Horizontal", ""},
+ {'v', "VERTICAL", 0, "Vertical", ""},
+ {0, NULL, 0, NULL, NULL},
};
static void SCREEN_OT_area_split(wmOperatorType *ot)
{
- ot->name = "Split Area";
- ot->description = "Split selected area into new windows";
- ot->idname = "SCREEN_OT_area_split";
+ ot->name = "Split Area";
+ ot->description = "Split selected area into new windows";
+ ot->idname = "SCREEN_OT_area_split";
- ot->exec = area_split_exec;
- ot->invoke = area_split_invoke;
- ot->modal = area_split_modal;
- ot->cancel = area_split_cancel;
+ ot->exec = area_split_exec;
+ ot->invoke = area_split_invoke;
+ ot->modal = area_split_modal;
+ ot->cancel = area_split_cancel;
- ot->poll = screen_active_editable;
+ ot->poll = screen_active_editable;
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
- /* rna */
- RNA_def_enum(ot->srna, "direction", prop_direction_items, 'h', "Direction", "");
- RNA_def_float(ot->srna, "factor", 0.5f, 0.0, 1.0, "Factor", "", 0.0, 1.0);
- RNA_def_int_vector(ot->srna, "cursor", 2, NULL, INT_MIN, INT_MAX, "Cursor", "", INT_MIN, INT_MAX);
+ /* rna */
+ RNA_def_enum(ot->srna, "direction", prop_direction_items, 'h', "Direction", "");
+ RNA_def_float(ot->srna, "factor", 0.5f, 0.0, 1.0, "Factor", "", 0.0, 1.0);
+ RNA_def_int_vector(
+ ot->srna, "cursor", 2, NULL, INT_MIN, INT_MAX, "Cursor", "", INT_MIN, INT_MAX);
}
/** \} */
@@ -2264,275 +2289,276 @@ static void SCREEN_OT_area_split(wmOperatorType *ot)
* \{ */
typedef struct RegionMoveData {
- AZone *az;
- ARegion *ar;
- ScrArea *sa;
- int bigger, smaller, origval;
- int origx, origy;
- int maxsize;
- AZEdge edge;
+ AZone *az;
+ ARegion *ar;
+ ScrArea *sa;
+ int bigger, smaller, origval;
+ int origx, origy;
+ int maxsize;
+ AZEdge edge;
} RegionMoveData;
static int area_max_regionsize(ScrArea *sa, ARegion *scalear, AZEdge edge)
{
- int dist;
-
- /* regions in regions. */
- if (scalear->alignment & RGN_SPLIT_PREV) {
- const int align = scalear->alignment & RGN_ALIGN_ENUM_MASK;
-
- if (ELEM(align, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
- ARegion *ar = scalear->prev;
- dist = ar->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;
- }
- }
- else {
- if (edge == AE_RIGHT_TO_TOPLEFT || edge == AE_LEFT_TO_TOPRIGHT) {
- dist = BLI_rcti_size_x(&sa->totrct);
- }
- else { /* AE_BOTTOM_TO_TOPLEFT, AE_TOP_TO_BOTTOMRIGHT */
- dist = BLI_rcti_size_y(&sa->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)
- continue;
-
- if (scalear->alignment == RGN_ALIGN_LEFT && ar->alignment == RGN_ALIGN_RIGHT) {
- dist -= ar->winx;
- }
- else if (scalear->alignment == RGN_ALIGN_RIGHT && ar->alignment == RGN_ALIGN_LEFT) {
- dist -= ar->winx;
- }
- else if (scalear->alignment == RGN_ALIGN_TOP &&
- (ar->alignment == RGN_ALIGN_BOTTOM || ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_FOOTER)))
- {
- dist -= ar->winy;
- }
- else if (scalear->alignment == RGN_ALIGN_BOTTOM &&
- (ar->alignment == RGN_ALIGN_TOP || ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_FOOTER)))
- {
- dist -= ar->winy;
- }
- }
- }
-
- dist /= UI_DPI_FAC;
- return dist;
+ int dist;
+
+ /* regions in regions. */
+ if (scalear->alignment & RGN_SPLIT_PREV) {
+ const int align = scalear->alignment & RGN_ALIGN_ENUM_MASK;
+
+ if (ELEM(align, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
+ ARegion *ar = scalear->prev;
+ dist = ar->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;
+ }
+ }
+ else {
+ if (edge == AE_RIGHT_TO_TOPLEFT || edge == AE_LEFT_TO_TOPRIGHT) {
+ dist = BLI_rcti_size_x(&sa->totrct);
+ }
+ else { /* AE_BOTTOM_TO_TOPLEFT, AE_TOP_TO_BOTTOMRIGHT */
+ dist = BLI_rcti_size_y(&sa->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)
+ continue;
+
+ if (scalear->alignment == RGN_ALIGN_LEFT && ar->alignment == RGN_ALIGN_RIGHT) {
+ dist -= ar->winx;
+ }
+ else if (scalear->alignment == RGN_ALIGN_RIGHT && ar->alignment == RGN_ALIGN_LEFT) {
+ dist -= ar->winx;
+ }
+ else if (scalear->alignment == RGN_ALIGN_TOP &&
+ (ar->alignment == RGN_ALIGN_BOTTOM ||
+ ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_FOOTER))) {
+ dist -= ar->winy;
+ }
+ else if (scalear->alignment == RGN_ALIGN_BOTTOM &&
+ (ar->alignment == RGN_ALIGN_TOP ||
+ ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_FOOTER))) {
+ dist -= ar->winy;
+ }
+ }
+ }
+
+ dist /= UI_DPI_FAC;
+ return dist;
}
static int region_scale_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- sActionzoneData *sad = event->customdata;
- AZone *az;
+ sActionzoneData *sad = event->customdata;
+ AZone *az;
- if (event->type != EVT_ACTIONZONE_REGION) {
- BKE_report(op->reports, RPT_ERROR, "Can only scale region size from an action zone");
- return OPERATOR_CANCELLED;
- }
+ if (event->type != EVT_ACTIONZONE_REGION) {
+ BKE_report(op->reports, RPT_ERROR, "Can only scale region size from an action zone");
+ return OPERATOR_CANCELLED;
+ }
- az = sad->az;
+ az = sad->az;
- if (az->ar) {
- RegionMoveData *rmd = MEM_callocN(sizeof(RegionMoveData), "RegionMoveData");
+ if (az->ar) {
+ RegionMoveData *rmd = MEM_callocN(sizeof(RegionMoveData), "RegionMoveData");
- op->customdata = rmd;
+ op->customdata = rmd;
- rmd->az = az;
- rmd->ar = az->ar;
- rmd->sa = 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->az = az;
+ rmd->ar = az->ar;
+ rmd->sa = 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);
- /* if not set we do now, otherwise it uses type */
- if (rmd->ar->sizex == 0)
- rmd->ar->sizex = rmd->ar->winx;
- if (rmd->ar->sizey == 0)
- rmd->ar->sizey = rmd->ar->winy;
+ /* if not set we do now, otherwise it uses type */
+ if (rmd->ar->sizex == 0)
+ rmd->ar->sizex = rmd->ar->winx;
+ if (rmd->ar->sizey == 0)
+ rmd->ar->sizey = rmd->ar->winy;
- /* now copy to regionmovedata */
- if (rmd->edge == AE_LEFT_TO_TOPRIGHT || rmd->edge == AE_RIGHT_TO_TOPLEFT) {
- rmd->origval = rmd->ar->sizex;
- }
- else {
- rmd->origval = rmd->ar->sizey;
- }
+ /* now copy to regionmovedata */
+ if (rmd->edge == AE_LEFT_TO_TOPRIGHT || rmd->edge == AE_RIGHT_TO_TOPLEFT) {
+ rmd->origval = rmd->ar->sizex;
+ }
+ else {
+ rmd->origval = rmd->ar->sizey;
+ }
- CLAMP(rmd->maxsize, 0, 1000);
+ CLAMP(rmd->maxsize, 0, 1000);
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
- }
+ return OPERATOR_RUNNING_MODAL;
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void region_scale_validate_size(RegionMoveData *rmd)
{
- if ((rmd->ar->flag & RGN_FLAG_HIDDEN) == 0) {
- short *size, maxsize = -1;
-
+ if ((rmd->ar->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;
- else
- size = &rmd->ar->sizey;
+ if (rmd->edge == AE_LEFT_TO_TOPRIGHT || rmd->edge == AE_RIGHT_TO_TOPLEFT)
+ size = &rmd->ar->sizex;
+ else
+ size = &rmd->ar->sizey;
- maxsize = rmd->maxsize - (UI_UNIT_Y / UI_DPI_FAC);
+ maxsize = rmd->maxsize - (UI_UNIT_Y / UI_DPI_FAC);
- if (*size > maxsize && maxsize > 0)
- *size = maxsize;
- }
+ if (*size > maxsize && maxsize > 0)
+ *size = maxsize;
+ }
}
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);
- }
+ /* 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);
+ }
- region_toggle_hidden(C, rmd->ar, 0);
- region_scale_validate_size(rmd);
+ region_toggle_hidden(C, rmd->ar, 0);
+ region_scale_validate_size(rmd);
}
static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- RegionMoveData *rmd = op->customdata;
- int delta;
-
- /* 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 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;
- if (rmd->edge == AE_LEFT_TO_TOPRIGHT) delta = -delta;
-
- /* region sizes now get multiplied */
- delta /= UI_DPI_FAC;
-
- rmd->ar->sizex = rmd->origval + delta;
-
- 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;
- }
- }
- CLAMP(rmd->ar->sizex, 0, rmd->maxsize);
-
- if (rmd->ar->sizex < UI_UNIT_X) {
- rmd->ar->sizex = rmd->origval;
- if (!(rmd->ar->flag & RGN_FLAG_HIDDEN))
- region_scale_toggle_hidden(C, rmd);
- }
- else if (rmd->ar->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 {
- delta = event->y - rmd->origy;
- if (rmd->edge == AE_BOTTOM_TO_TOPLEFT) delta = -delta;
-
- /* region sizes now get multiplied */
- delta /= UI_DPI_FAC;
-
- rmd->ar->sizey = rmd->origval + delta;
-
- 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;
- }
- }
- CLAMP(rmd->ar->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 (rmd->ar->sizey < UI_UNIT_Y / 4) {
- rmd->ar->sizey = rmd->origval;
- if (!(rmd->ar->flag & RGN_FLAG_HIDDEN))
- region_scale_toggle_hidden(C, rmd);
- }
- else if (rmd->ar->flag & RGN_FLAG_HIDDEN) {
- region_scale_toggle_hidden(C, rmd);
- }
- else if (rmd->ar->flag & RGN_FLAG_DYNAMIC_SIZE) {
- rmd->ar->sizey = rmd->origval;
- }
- }
- ED_area_tag_redraw(rmd->sa);
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
-
- break;
- }
- 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) {
- region_scale_toggle_hidden(C, rmd);
- }
- else if (rmd->ar->flag & RGN_FLAG_TOO_SMALL) {
- region_scale_validate_size(rmd);
- }
-
- ED_area_tag_redraw(rmd->sa);
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
- }
- MEM_freeN(op->customdata);
- op->customdata = NULL;
-
- return OPERATOR_FINISHED;
- }
- break;
-
- case ESCKEY:
- break;
- }
-
- return OPERATOR_RUNNING_MODAL;
+ RegionMoveData *rmd = op->customdata;
+ int delta;
+
+ /* 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 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;
+ if (rmd->edge == AE_LEFT_TO_TOPRIGHT)
+ delta = -delta;
+
+ /* region sizes now get multiplied */
+ delta /= UI_DPI_FAC;
+
+ rmd->ar->sizex = rmd->origval + delta;
+
+ 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;
+ }
+ }
+ CLAMP(rmd->ar->sizex, 0, rmd->maxsize);
+
+ if (rmd->ar->sizex < UI_UNIT_X) {
+ rmd->ar->sizex = rmd->origval;
+ if (!(rmd->ar->flag & RGN_FLAG_HIDDEN))
+ region_scale_toggle_hidden(C, rmd);
+ }
+ else if (rmd->ar->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 {
+ delta = event->y - rmd->origy;
+ if (rmd->edge == AE_BOTTOM_TO_TOPLEFT)
+ delta = -delta;
+
+ /* region sizes now get multiplied */
+ delta /= UI_DPI_FAC;
+
+ rmd->ar->sizey = rmd->origval + delta;
+
+ 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;
+ }
+ }
+ CLAMP(rmd->ar->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 (rmd->ar->sizey < UI_UNIT_Y / 4) {
+ rmd->ar->sizey = rmd->origval;
+ if (!(rmd->ar->flag & RGN_FLAG_HIDDEN))
+ region_scale_toggle_hidden(C, rmd);
+ }
+ else if (rmd->ar->flag & RGN_FLAG_HIDDEN) {
+ region_scale_toggle_hidden(C, rmd);
+ }
+ else if (rmd->ar->flag & RGN_FLAG_DYNAMIC_SIZE) {
+ rmd->ar->sizey = rmd->origval;
+ }
+ }
+ ED_area_tag_redraw(rmd->sa);
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+
+ break;
+ }
+ 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) {
+ region_scale_toggle_hidden(C, rmd);
+ }
+ else if (rmd->ar->flag & RGN_FLAG_TOO_SMALL) {
+ region_scale_validate_size(rmd);
+ }
+
+ ED_area_tag_redraw(rmd->sa);
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ }
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+
+ return OPERATOR_FINISHED;
+ }
+ break;
+
+ case ESCKEY:
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
static void region_scale_cancel(bContext *UNUSED(C), wmOperator *op)
{
- MEM_freeN(op->customdata);
- op->customdata = NULL;
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
}
static void SCREEN_OT_region_scale(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Scale Region Size";
- ot->description = "Scale selected area";
- ot->idname = "SCREEN_OT_region_scale";
+ /* identifiers */
+ ot->name = "Scale Region Size";
+ ot->description = "Scale selected area";
+ ot->idname = "SCREEN_OT_region_scale";
- ot->invoke = region_scale_invoke;
- ot->modal = region_scale_modal;
- ot->cancel = region_scale_cancel;
+ ot->invoke = region_scale_invoke;
+ ot->modal = region_scale_modal;
+ ot->cancel = region_scale_cancel;
- ot->poll = ED_operator_areaactive;
+ ot->poll = ED_operator_areaactive;
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
}
/** \} */
@@ -2543,81 +2569,80 @@ static void SCREEN_OT_region_scale(wmOperatorType *ot)
static void areas_do_frame_follow(bContext *C, bool middle)
{
- bScreen *scr = 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) {
- 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) {
- /* 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 (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);
- }
- }
- 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;
- }
- 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;
- }
- }
- }
- }
- }
- }
- }
+ bScreen *scr = 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) {
+ 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) {
+ /* 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 (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);
+ }
+ }
+ 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;
+ }
+ 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;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
/* function to be called outside UI context, or for redo */
static int frame_offset_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- int delta;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ int delta;
- delta = RNA_int_get(op->ptr, "delta");
+ delta = RNA_int_get(op->ptr, "delta");
- CFRA += delta;
- FRAMENUMBER_MIN_CLAMP(CFRA);
- SUBFRA = 0.f;
+ CFRA += delta;
+ FRAMENUMBER_MIN_CLAMP(CFRA);
+ SUBFRA = 0.f;
- areas_do_frame_follow(C, false);
+ areas_do_frame_follow(C, false);
- BKE_sound_seek_scene(bmain, scene);
+ BKE_sound_seek_scene(bmain, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SCREEN_OT_frame_offset(wmOperatorType *ot)
{
- ot->name = "Frame Offset";
- ot->idname = "SCREEN_OT_frame_offset";
- ot->description = "Move current frame forward/backward by a given number";
+ ot->name = "Frame Offset";
+ ot->idname = "SCREEN_OT_frame_offset";
+ ot->description = "Move current frame forward/backward by a given number";
- ot->exec = frame_offset_exec;
+ ot->exec = frame_offset_exec;
- ot->poll = ED_operator_screenactive_norender;
- ot->flag = OPTYPE_UNDO_GROUPED;
- ot->undo_group = "Frame Change";
+ ot->poll = ED_operator_screenactive_norender;
+ ot->flag = OPTYPE_UNDO_GROUPED;
+ ot->undo_group = "Frame Change";
- /* rna */
- RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
+ /* rna */
+ RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
}
/** \} */
@@ -2629,54 +2654,54 @@ static void SCREEN_OT_frame_offset(wmOperatorType *ot)
/* function to be called outside UI context, or for redo */
static int frame_jump_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- wmTimer *animtimer = CTX_wm_screen(C)->animtimer;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ wmTimer *animtimer = CTX_wm_screen(C)->animtimer;
- /* Don't change CFRA directly if animtimer is running as this can cause
- * first/last frame not to be actually shown (bad since for example physics
- * simulations aren't reset properly).
- */
- if (animtimer) {
- ScreenAnimData *sad = animtimer->customdata;
+ /* Don't change CFRA directly if animtimer is running as this can cause
+ * first/last frame not to be actually shown (bad since for example physics
+ * simulations aren't reset properly).
+ */
+ if (animtimer) {
+ ScreenAnimData *sad = animtimer->customdata;
- sad->flag |= ANIMPLAY_FLAG_USE_NEXT_FRAME;
+ sad->flag |= ANIMPLAY_FLAG_USE_NEXT_FRAME;
- if (RNA_boolean_get(op->ptr, "end"))
- sad->nextfra = PEFRA;
- else
- sad->nextfra = PSFRA;
- }
- else {
- if (RNA_boolean_get(op->ptr, "end"))
- CFRA = PEFRA;
- else
- CFRA = PSFRA;
+ if (RNA_boolean_get(op->ptr, "end"))
+ sad->nextfra = PEFRA;
+ else
+ sad->nextfra = PSFRA;
+ }
+ else {
+ if (RNA_boolean_get(op->ptr, "end"))
+ CFRA = PEFRA;
+ else
+ CFRA = PSFRA;
- areas_do_frame_follow(C, true);
+ areas_do_frame_follow(C, true);
- BKE_sound_seek_scene(bmain, scene);
+ BKE_sound_seek_scene(bmain, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
- }
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SCREEN_OT_frame_jump(wmOperatorType *ot)
{
- ot->name = "Jump to Endpoint";
- ot->description = "Jump to first/last frame in frame range";
- ot->idname = "SCREEN_OT_frame_jump";
+ ot->name = "Jump to Endpoint";
+ ot->description = "Jump to first/last frame in frame range";
+ ot->idname = "SCREEN_OT_frame_jump";
- ot->exec = frame_jump_exec;
+ ot->exec = frame_jump_exec;
- ot->poll = ED_operator_screenactive_norender;
- ot->flag = OPTYPE_UNDO_GROUPED;
- ot->undo_group = "Frame Change";
+ ot->poll = ED_operator_screenactive_norender;
+ ot->flag = OPTYPE_UNDO_GROUPED;
+ ot->undo_group = "Frame Change";
- /* rna */
- RNA_def_boolean(ot->srna, "end", 0, "Last Frame", "Jump to the last frame of the frame range");
+ /* rna */
+ RNA_def_boolean(ot->srna, "end", 0, "Last Frame", "Jump to the last frame of the frame range");
}
/** \} */
@@ -2688,108 +2713,108 @@ static void SCREEN_OT_frame_jump(wmOperatorType *ot)
/* function to be called outside UI context, or for redo */
static int keyframe_jump_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- bDopeSheet ads = {NULL};
- DLRBT_Tree keys;
- ActKeyColumn *ak;
- float cfra;
- const bool next = RNA_boolean_get(op->ptr, "next");
- bool done = false;
-
- /* sanity checks */
- if (scene == NULL)
- return OPERATOR_CANCELLED;
-
- cfra = (float)(CFRA);
-
- /* init binarytree-list for getting keyframes */
- BLI_dlrbTree_init(&keys);
-
- /* seed up dummy dopesheet context with flags to perform necessary filtering */
- if ((scene->flag & SCE_KEYS_NO_SELONLY) == 0) {
- /* only selected channels are included */
- ads.filterflag |= ADS_FILTER_ONLYSEL;
- }
-
- /* populate tree with keyframe nodes */
- scene_to_keylist(&ads, scene, &keys, 0);
-
- if (ob) {
- ob_to_keylist(&ads, ob, &keys, 0);
-
- if (ob->type == OB_GPENCIL) {
- const bool active = !(scene->flag & SCE_KEYS_NO_SELONLY);
- gpencil_to_keylist(&ads, ob->data, &keys, active);
- }
- }
-
- {
- Mask *mask = CTX_data_edit_mask(C);
- if (mask) {
- MaskLayer *masklay = BKE_mask_layer_active(mask);
- mask_to_keylist(&ads, masklay, &keys);
- }
- }
-
- /* find matching keyframe in the right direction */
- if (next)
- ak = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfra);
- else
- ak = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfra);
-
- while ((ak != NULL) && (done == false)) {
- if (CFRA != (int)ak->cfra) {
- /* this changes the frame, so set the frame and we're done */
- CFRA = (int)ak->cfra;
- done = true;
- }
- else {
- /* take another step... */
- if (next) {
- ak = ak->next;
- }
- else {
- ak = ak->prev;
- }
- }
- }
-
- /* free temp stuff */
- BLI_dlrbTree_free(&keys);
-
- /* any success? */
- if (done == false) {
- BKE_report(op->reports, RPT_INFO, "No more keyframes to jump to in this direction");
-
- return OPERATOR_CANCELLED;
- }
- else {
- areas_do_frame_follow(C, true);
-
- BKE_sound_seek_scene(bmain, scene);
-
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
-
- return OPERATOR_FINISHED;
- }
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ bDopeSheet ads = {NULL};
+ DLRBT_Tree keys;
+ ActKeyColumn *ak;
+ float cfra;
+ const bool next = RNA_boolean_get(op->ptr, "next");
+ bool done = false;
+
+ /* sanity checks */
+ if (scene == NULL)
+ return OPERATOR_CANCELLED;
+
+ cfra = (float)(CFRA);
+
+ /* init binarytree-list for getting keyframes */
+ BLI_dlrbTree_init(&keys);
+
+ /* seed up dummy dopesheet context with flags to perform necessary filtering */
+ if ((scene->flag & SCE_KEYS_NO_SELONLY) == 0) {
+ /* only selected channels are included */
+ ads.filterflag |= ADS_FILTER_ONLYSEL;
+ }
+
+ /* populate tree with keyframe nodes */
+ scene_to_keylist(&ads, scene, &keys, 0);
+
+ if (ob) {
+ ob_to_keylist(&ads, ob, &keys, 0);
+
+ if (ob->type == OB_GPENCIL) {
+ const bool active = !(scene->flag & SCE_KEYS_NO_SELONLY);
+ gpencil_to_keylist(&ads, ob->data, &keys, active);
+ }
+ }
+
+ {
+ Mask *mask = CTX_data_edit_mask(C);
+ if (mask) {
+ MaskLayer *masklay = BKE_mask_layer_active(mask);
+ mask_to_keylist(&ads, masklay, &keys);
+ }
+ }
+
+ /* find matching keyframe in the right direction */
+ if (next)
+ ak = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfra);
+ else
+ ak = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfra);
+
+ while ((ak != NULL) && (done == false)) {
+ if (CFRA != (int)ak->cfra) {
+ /* this changes the frame, so set the frame and we're done */
+ CFRA = (int)ak->cfra;
+ done = true;
+ }
+ else {
+ /* take another step... */
+ if (next) {
+ ak = ak->next;
+ }
+ else {
+ ak = ak->prev;
+ }
+ }
+ }
+
+ /* free temp stuff */
+ BLI_dlrbTree_free(&keys);
+
+ /* any success? */
+ if (done == false) {
+ BKE_report(op->reports, RPT_INFO, "No more keyframes to jump to in this direction");
+
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ areas_do_frame_follow(C, true);
+
+ BKE_sound_seek_scene(bmain, scene);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+
+ return OPERATOR_FINISHED;
+ }
}
static void SCREEN_OT_keyframe_jump(wmOperatorType *ot)
{
- ot->name = "Jump to Keyframe";
- ot->description = "Jump to previous/next keyframe";
- ot->idname = "SCREEN_OT_keyframe_jump";
+ ot->name = "Jump to Keyframe";
+ ot->description = "Jump to previous/next keyframe";
+ ot->idname = "SCREEN_OT_keyframe_jump";
- ot->exec = keyframe_jump_exec;
+ ot->exec = keyframe_jump_exec;
- ot->poll = ED_operator_screenactive_norender;
- ot->flag = OPTYPE_UNDO_GROUPED;
- ot->undo_group = "Frame Change";
+ ot->poll = ED_operator_screenactive_norender;
+ ot->flag = OPTYPE_UNDO_GROUPED;
+ ot->undo_group = "Frame Change";
- /* properties */
- RNA_def_boolean(ot->srna, "next", true, "Next Keyframe", "");
+ /* properties */
+ RNA_def_boolean(ot->srna, "next", true, "Next Keyframe", "");
}
/** \} */
@@ -2801,62 +2826,62 @@ static void SCREEN_OT_keyframe_jump(wmOperatorType *ot)
/* function to be called outside UI context, or for redo */
static int marker_jump_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- TimeMarker *marker;
- int closest = CFRA;
- const bool next = RNA_boolean_get(op->ptr, "next");
- bool found = false;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ TimeMarker *marker;
+ int closest = CFRA;
+ const bool next = RNA_boolean_get(op->ptr, "next");
+ bool found = false;
- /* find matching marker in the right direction */
- for (marker = scene->markers.first; marker; marker = marker->next) {
- if (next) {
- if ((marker->frame > CFRA) && (!found || closest > marker->frame)) {
- closest = marker->frame;
- found = true;
- }
- }
- else {
- if ((marker->frame < CFRA) && (!found || closest < marker->frame)) {
- closest = marker->frame;
- found = true;
- }
- }
- }
+ /* find matching marker in the right direction */
+ for (marker = scene->markers.first; marker; marker = marker->next) {
+ if (next) {
+ if ((marker->frame > CFRA) && (!found || closest > marker->frame)) {
+ closest = marker->frame;
+ found = true;
+ }
+ }
+ else {
+ if ((marker->frame < CFRA) && (!found || closest < marker->frame)) {
+ closest = marker->frame;
+ found = true;
+ }
+ }
+ }
- /* any success? */
- if (!found) {
- BKE_report(op->reports, RPT_INFO, "No more markers to jump to in this direction");
+ /* any success? */
+ if (!found) {
+ BKE_report(op->reports, RPT_INFO, "No more markers to jump to in this direction");
- return OPERATOR_CANCELLED;
- }
- else {
- CFRA = closest;
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ CFRA = closest;
- areas_do_frame_follow(C, true);
+ areas_do_frame_follow(C, true);
- BKE_sound_seek_scene(bmain, scene);
+ BKE_sound_seek_scene(bmain, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
}
static void SCREEN_OT_marker_jump(wmOperatorType *ot)
{
- ot->name = "Jump to Marker";
- ot->description = "Jump to previous/next marker";
- ot->idname = "SCREEN_OT_marker_jump";
+ ot->name = "Jump to Marker";
+ ot->description = "Jump to previous/next marker";
+ ot->idname = "SCREEN_OT_marker_jump";
- ot->exec = marker_jump_exec;
+ ot->exec = marker_jump_exec;
- ot->poll = ED_operator_screenactive_norender;
- ot->flag = OPTYPE_UNDO_GROUPED;
- ot->undo_group = "Frame Change";
+ ot->poll = ED_operator_screenactive_norender;
+ ot->flag = OPTYPE_UNDO_GROUPED;
+ ot->undo_group = "Frame Change";
- /* properties */
- RNA_def_boolean(ot->srna, "next", true, "Next Marker", "");
+ /* properties */
+ RNA_def_boolean(ot->srna, "next", true, "Next Marker", "");
}
/** \} */
@@ -2868,27 +2893,27 @@ static void SCREEN_OT_marker_jump(wmOperatorType *ot)
/* function to be called outside UI context, or for redo */
static int screen_set_exec(bContext *C, wmOperator *op)
{
- WorkSpace *workspace = CTX_wm_workspace(C);
- int delta = RNA_int_get(op->ptr, "delta");
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ int delta = RNA_int_get(op->ptr, "delta");
- if (ED_workspace_layout_cycle(workspace, delta, C)) {
- return OPERATOR_FINISHED;
- }
+ if (ED_workspace_layout_cycle(workspace, delta, C)) {
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
static void SCREEN_OT_screen_set(wmOperatorType *ot)
{
- ot->name = "Set Screen";
- ot->description = "Cycle through available screens";
- ot->idname = "SCREEN_OT_screen_set";
+ ot->name = "Set Screen";
+ ot->description = "Cycle through available screens";
+ ot->idname = "SCREEN_OT_screen_set";
- ot->exec = screen_set_exec;
- ot->poll = ED_operator_screenactive;
+ ot->exec = screen_set_exec;
+ ot->poll = ED_operator_screenactive;
- /* rna */
- RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
+ /* rna */
+ RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
}
/** \} */
@@ -2900,59 +2925,60 @@ static void SCREEN_OT_screen_set(wmOperatorType *ot)
/* function to be called outside UI context, or for redo */
static int screen_maximize_area_exec(bContext *C, wmOperator *op)
{
- bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = 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) break;
- }
-
- if (sa == NULL) {
- sa = 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);
- }
- else {
- if (!ELEM(screen->state, SCREENNORMAL, SCREENMAXIMIZED)) {
- return OPERATOR_CANCELLED;
- }
- ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENMAXIMIZED);
- }
-
- return OPERATOR_FINISHED;
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = 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)
+ break;
+ }
+
+ if (sa == NULL) {
+ sa = 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);
+ }
+ else {
+ if (!ELEM(screen->state, SCREENNORMAL, SCREENMAXIMIZED)) {
+ return OPERATOR_CANCELLED;
+ }
+ ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENMAXIMIZED);
+ }
+
+ return OPERATOR_FINISHED;
}
static bool screen_maximize_area_poll(bContext *C)
{
- const bScreen *screen = CTX_wm_screen(C);
- const ScrArea *area = CTX_wm_area(C);
- return ED_operator_areaactive(C) &&
- /* Don't allow maximizing global areas but allow minimizing from them. */
- ((screen->state != SCREENNORMAL) || !ED_area_is_global(area));
+ const bScreen *screen = CTX_wm_screen(C);
+ const ScrArea *area = CTX_wm_area(C);
+ return ED_operator_areaactive(C) &&
+ /* Don't allow maximizing global areas but allow minimizing from them. */
+ ((screen->state != SCREENNORMAL) || !ED_area_is_global(area));
}
static void SCREEN_OT_screen_full_area(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- ot->name = "Toggle Maximize Area";
- ot->description = "Toggle display selected area as fullscreen/maximized";
- ot->idname = "SCREEN_OT_screen_full_area";
+ ot->name = "Toggle Maximize Area";
+ ot->description = "Toggle display selected area as fullscreen/maximized";
+ ot->idname = "SCREEN_OT_screen_full_area";
- ot->exec = screen_maximize_area_exec;
- ot->poll = screen_maximize_area_poll;
- ot->flag = 0;
+ ot->exec = screen_maximize_area_exec;
+ ot->poll = screen_maximize_area_poll;
+ ot->flag = 0;
- prop = RNA_def_boolean(ot->srna, "use_hide_panels", false, "Hide Panels", "Hide all the panels");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "use_hide_panels", false, "Hide Panels", "Hide all the panels");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/** \} */
@@ -2973,37 +2999,36 @@ static void SCREEN_OT_screen_full_area(wmOperatorType *ot)
*
* apply() do the actual join
*
- * exit() cleanup, send notifier
+ * exit() cleanup, send notifier
*
* callbacks:
*
- * exec() calls init, apply, exit
+ * exec() calls init, apply, exit
*
* invoke() sets mouse coords in x,y
* call init()
* add modal handler
*
- * modal() accept modal events while doing it
+ * modal() accept modal events while doing it
* call apply() with active window and nonactive window
* call exit() and remove handler when LMB confirm
*/
typedef struct sAreaJoinData {
- ScrArea *sa1; /* first area to be considered */
- ScrArea *sa2; /* second area to be considered */
- void *draw_callback; /* call `ED_screen_draw_join_shape` */
+ ScrArea *sa1; /* first area to be considered */
+ ScrArea *sa2; /* second area to be considered */
+ void *draw_callback; /* call `ED_screen_draw_join_shape` */
} sAreaJoinData;
-
static void area_join_draw_cb(const struct wmWindow *UNUSED(win), void *userdata)
{
- const wmOperator *op = userdata;
+ const wmOperator *op = userdata;
- sAreaJoinData *sd = op->customdata;
- if (sd->sa1 && sd->sa2) {
- ED_screen_draw_join_shape(sd->sa1, sd->sa2);
- }
+ sAreaJoinData *sd = op->customdata;
+ if (sd->sa1 && sd->sa2) {
+ ED_screen_draw_join_shape(sd->sa1, sd->sa2);
+ }
}
/* validate selection inside screen, set variables OK */
@@ -3011,252 +3036,252 @@ static void area_join_draw_cb(const struct wmWindow *UNUSED(win), void *userdata
/* XXX todo: find edge based on (x,y) and set other area? */
static int area_join_init(bContext *C, wmOperator *op)
{
- const wmWindow *win = CTX_wm_window(C);
- bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa1, *sa2;
- sAreaJoinData *jd = NULL;
- int x1, y1;
- int x2, y2;
+ const wmWindow *win = CTX_wm_window(C);
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa1, *sa2;
+ sAreaJoinData *jd = NULL;
+ int x1, y1;
+ int x2, y2;
- /* required properties, make negative to get return 0 if not set by caller */
- x1 = RNA_int_get(op->ptr, "min_x");
- y1 = RNA_int_get(op->ptr, "min_y");
- x2 = RNA_int_get(op->ptr, "max_x");
- y2 = RNA_int_get(op->ptr, "max_y");
+ /* required properties, make negative to get return 0 if not set by caller */
+ x1 = RNA_int_get(op->ptr, "min_x");
+ y1 = RNA_int_get(op->ptr, "min_y");
+ x2 = RNA_int_get(op->ptr, "max_x");
+ y2 = RNA_int_get(op->ptr, "max_y");
- sa1 = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, x1, y1);
- if (sa1 == NULL) {
- sa1 = BKE_screen_area_map_find_area_xy(&win->global_areas, SPACE_TYPE_ANY, x1, y1);
- }
- sa2 = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, x2, y2);
- if (sa2 == NULL) {
- sa2 = BKE_screen_area_map_find_area_xy(&win->global_areas, SPACE_TYPE_ANY, x2, y2);
- }
- if ((sa1 && ED_area_is_global(sa1)) || (sa2 && ED_area_is_global(sa2))) {
- BKE_report(op->reports, RPT_ERROR, "Global areas (Top Bar, Status Bar) do not support joining");
- return 0;
- }
- else if (sa1 == NULL || sa2 == NULL || sa1 == sa2) {
- return 0;
- }
+ sa1 = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, x1, y1);
+ if (sa1 == NULL) {
+ sa1 = BKE_screen_area_map_find_area_xy(&win->global_areas, SPACE_TYPE_ANY, x1, y1);
+ }
+ sa2 = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, x2, y2);
+ if (sa2 == NULL) {
+ sa2 = BKE_screen_area_map_find_area_xy(&win->global_areas, SPACE_TYPE_ANY, x2, y2);
+ }
+ if ((sa1 && ED_area_is_global(sa1)) || (sa2 && ED_area_is_global(sa2))) {
+ BKE_report(
+ op->reports, RPT_ERROR, "Global areas (Top Bar, Status Bar) do not support joining");
+ return 0;
+ }
+ else if (sa1 == NULL || sa2 == NULL || sa1 == sa2) {
+ return 0;
+ }
- jd = (sAreaJoinData *)MEM_callocN(sizeof(sAreaJoinData), "op_area_join");
+ jd = (sAreaJoinData *)MEM_callocN(sizeof(sAreaJoinData), "op_area_join");
- jd->sa1 = sa1;
- jd->sa2 = sa2;
+ jd->sa1 = sa1;
+ jd->sa2 = sa2;
- op->customdata = jd;
+ op->customdata = jd;
- jd->draw_callback = WM_draw_cb_activate(CTX_wm_window(C), area_join_draw_cb, op);
+ jd->draw_callback = WM_draw_cb_activate(CTX_wm_window(C), area_join_draw_cb, op);
- return 1;
+ return 1;
}
/* apply the join of the areas (space types) */
static int area_join_apply(bContext *C, wmOperator *op)
{
- sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
- if (!jd) return 0;
+ sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
+ if (!jd)
+ return 0;
- if (!screen_area_join(C, CTX_wm_screen(C), jd->sa1, jd->sa2)) {
- return 0;
- }
- if (CTX_wm_area(C) == jd->sa2) {
- CTX_wm_area_set(C, NULL);
- CTX_wm_region_set(C, NULL);
- }
+ if (!screen_area_join(C, CTX_wm_screen(C), jd->sa1, jd->sa2)) {
+ return 0;
+ }
+ if (CTX_wm_area(C) == jd->sa2) {
+ CTX_wm_area_set(C, NULL);
+ CTX_wm_region_set(C, NULL);
+ }
- return 1;
+ return 1;
}
/* finish operation */
static void area_join_exit(bContext *C, wmOperator *op)
{
- sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
+ sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
- if (jd) {
- if (jd->draw_callback)
- WM_draw_cb_exit(CTX_wm_window(C), jd->draw_callback);
+ if (jd) {
+ if (jd->draw_callback)
+ WM_draw_cb_exit(CTX_wm_window(C), jd->draw_callback);
- MEM_freeN(jd);
- op->customdata = NULL;
- }
+ MEM_freeN(jd);
+ op->customdata = NULL;
+ }
- /* this makes sure aligned edges will result in aligned grabbing */
- BKE_screen_remove_double_scredges(CTX_wm_screen(C));
- BKE_screen_remove_unused_scredges(CTX_wm_screen(C));
- BKE_screen_remove_unused_scrverts(CTX_wm_screen(C));
+ /* this makes sure aligned edges will result in aligned grabbing */
+ BKE_screen_remove_double_scredges(CTX_wm_screen(C));
+ BKE_screen_remove_unused_scredges(CTX_wm_screen(C));
+ BKE_screen_remove_unused_scrverts(CTX_wm_screen(C));
}
static int area_join_exec(bContext *C, wmOperator *op)
{
- if (!area_join_init(C, op))
- return OPERATOR_CANCELLED;
+ if (!area_join_init(C, op))
+ return OPERATOR_CANCELLED;
- area_join_apply(C, op);
- area_join_exit(C, op);
+ area_join_apply(C, op);
+ area_join_exit(C, op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* interaction callback */
static int area_join_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (event->type == EVT_ACTIONZONE_AREA) {
- sActionzoneData *sad = event->customdata;
+ if (event->type == EVT_ACTIONZONE_AREA) {
+ sActionzoneData *sad = event->customdata;
- if (sad == NULL || sad->modifier > 0) {
- return OPERATOR_PASS_THROUGH;
- }
+ if (sad == NULL || sad->modifier > 0) {
+ return OPERATOR_PASS_THROUGH;
+ }
- /* verify *sad itself */
- if (sad->sa1 == NULL || sad->sa2 == NULL)
- return OPERATOR_PASS_THROUGH;
+ /* verify *sad itself */
+ if (sad->sa1 == NULL || sad->sa2 == NULL)
+ return OPERATOR_PASS_THROUGH;
- /* is this our *sad? if areas equal it should be passed on */
- if (sad->sa1 == sad->sa2)
- return OPERATOR_PASS_THROUGH;
+ /* is this our *sad? if areas equal it should be passed on */
+ if (sad->sa1 == sad->sa2)
+ return OPERATOR_PASS_THROUGH;
- /* prepare operator state vars */
- RNA_int_set(op->ptr, "min_x", sad->sa1->totrct.xmin);
- RNA_int_set(op->ptr, "min_y", sad->sa1->totrct.ymin);
- RNA_int_set(op->ptr, "max_x", sad->sa2->totrct.xmin);
- RNA_int_set(op->ptr, "max_y", sad->sa2->totrct.ymin);
- }
+ /* prepare operator state vars */
+ RNA_int_set(op->ptr, "min_x", sad->sa1->totrct.xmin);
+ RNA_int_set(op->ptr, "min_y", sad->sa1->totrct.ymin);
+ RNA_int_set(op->ptr, "max_x", sad->sa2->totrct.xmin);
+ RNA_int_set(op->ptr, "max_y", sad->sa2->totrct.ymin);
+ }
+ if (!area_join_init(C, op))
+ return OPERATOR_CANCELLED;
- if (!area_join_init(C, op))
- return OPERATOR_CANCELLED;
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static void area_join_cancel(bContext *C, wmOperator *op)
{
- WM_event_add_notifier(C, NC_WINDOW, NULL);
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
- area_join_exit(C, op);
+ area_join_exit(C, 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);
- wmWindow *win = CTX_wm_window(C);
- sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
-
- /* execute the events */
- switch (event->type) {
-
- case MOUSEMOVE:
- {
- ScrArea *sa = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, event->x, event->y);
- int dir = -1;
-
- if (sa) {
- if (jd->sa1 != sa) {
- dir = area_getorientation(jd->sa1, sa);
- if (dir != -1) {
- jd->sa2 = sa;
- }
- 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);
- if (dir != -1) {
- jd->sa1 = jd->sa2;
- jd->sa2 = sa;
- }
- else {
- jd->sa2 = NULL;
- }
- }
- WM_event_add_notifier(C, NC_WINDOW, NULL);
- }
- else {
- /* we are back in the area previously selected for keeping
- * we swap the areas if possible to allow user to choose */
- if (jd->sa2 != NULL) {
- jd->sa1 = jd->sa2;
- jd->sa2 = sa;
- dir = area_getorientation(jd->sa1, jd->sa2);
- if (dir == -1) {
- printf("oops, didn't expect that!\n");
- }
- }
- else {
- dir = area_getorientation(jd->sa1, sa);
- if (dir != -1) {
- jd->sa2 = sa;
- }
- }
- WM_event_add_notifier(C, NC_WINDOW, NULL);
- }
- }
-
- if (dir == 1)
- WM_cursor_set(win, BC_N_ARROWCURSOR);
- else if (dir == 3)
- WM_cursor_set(win, BC_S_ARROWCURSOR);
- else if (dir == 2)
- WM_cursor_set(win, BC_E_ARROWCURSOR);
- else if (dir == 0)
- WM_cursor_set(win, BC_W_ARROWCURSOR);
- else
- WM_cursor_set(win, BC_STOPCURSOR);
-
- break;
- }
- case LEFTMOUSE:
- if (event->val == KM_RELEASE) {
- ED_area_tag_redraw(jd->sa1);
- ED_area_tag_redraw(jd->sa2);
-
- area_join_apply(C, op);
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
- area_join_exit(C, op);
- return OPERATOR_FINISHED;
- }
- break;
-
- case RIGHTMOUSE:
- case ESCKEY:
- area_join_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_RUNNING_MODAL;
+ bScreen *sc = CTX_wm_screen(C);
+ wmWindow *win = CTX_wm_window(C);
+ sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
+
+ /* execute the events */
+ switch (event->type) {
+
+ case MOUSEMOVE: {
+ ScrArea *sa = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, event->x, event->y);
+ int dir = -1;
+
+ if (sa) {
+ if (jd->sa1 != sa) {
+ dir = area_getorientation(jd->sa1, sa);
+ if (dir != -1) {
+ jd->sa2 = sa;
+ }
+ 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);
+ if (dir != -1) {
+ jd->sa1 = jd->sa2;
+ jd->sa2 = sa;
+ }
+ else {
+ jd->sa2 = NULL;
+ }
+ }
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ }
+ else {
+ /* we are back in the area previously selected for keeping
+ * we swap the areas if possible to allow user to choose */
+ if (jd->sa2 != NULL) {
+ jd->sa1 = jd->sa2;
+ jd->sa2 = sa;
+ dir = area_getorientation(jd->sa1, jd->sa2);
+ if (dir == -1) {
+ printf("oops, didn't expect that!\n");
+ }
+ }
+ else {
+ dir = area_getorientation(jd->sa1, sa);
+ if (dir != -1) {
+ jd->sa2 = sa;
+ }
+ }
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ }
+ }
+
+ if (dir == 1)
+ WM_cursor_set(win, BC_N_ARROWCURSOR);
+ else if (dir == 3)
+ WM_cursor_set(win, BC_S_ARROWCURSOR);
+ else if (dir == 2)
+ WM_cursor_set(win, BC_E_ARROWCURSOR);
+ else if (dir == 0)
+ WM_cursor_set(win, BC_W_ARROWCURSOR);
+ else
+ WM_cursor_set(win, BC_STOPCURSOR);
+
+ break;
+ }
+ case LEFTMOUSE:
+ if (event->val == KM_RELEASE) {
+ ED_area_tag_redraw(jd->sa1);
+ ED_area_tag_redraw(jd->sa2);
+
+ area_join_apply(C, op);
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ area_join_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ break;
+
+ case RIGHTMOUSE:
+ case ESCKEY:
+ area_join_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
/* Operator for joining two areas (space types) */
static void SCREEN_OT_area_join(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Join Area";
- ot->description = "Join selected areas into new window";
- ot->idname = "SCREEN_OT_area_join";
+ /* identifiers */
+ ot->name = "Join Area";
+ ot->description = "Join selected areas into new window";
+ ot->idname = "SCREEN_OT_area_join";
- /* api callbacks */
- ot->exec = area_join_exec;
- ot->invoke = area_join_invoke;
- ot->modal = area_join_modal;
- ot->poll = screen_active_editable;
- ot->cancel = area_join_cancel;
+ /* api callbacks */
+ ot->exec = area_join_exec;
+ ot->invoke = area_join_invoke;
+ ot->modal = area_join_modal;
+ ot->poll = screen_active_editable;
+ ot->cancel = area_join_cancel;
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
- /* rna */
- RNA_def_int(ot->srna, "min_x", -100, INT_MIN, INT_MAX, "X 1", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "min_y", -100, INT_MIN, INT_MAX, "Y 1", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "max_x", -100, INT_MIN, INT_MAX, "X 2", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "max_y", -100, INT_MIN, INT_MAX, "Y 2", "", INT_MIN, INT_MAX);
+ /* rna */
+ RNA_def_int(ot->srna, "min_x", -100, INT_MIN, INT_MAX, "X 1", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "min_y", -100, INT_MIN, INT_MAX, "Y 1", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "max_x", -100, INT_MIN, INT_MAX, "X 2", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "max_y", -100, INT_MIN, INT_MAX, "Y 2", "", INT_MIN, INT_MAX);
}
/** \} */
@@ -3267,52 +3292,55 @@ static void SCREEN_OT_area_join(wmOperatorType *ot)
static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- const wmWindow *win = CTX_wm_window(C);
- const bScreen *sc = CTX_wm_screen(C);
- uiPopupMenu *pup;
- uiLayout *layout;
- PointerRNA ptr;
- ScrEdge *actedge;
- rcti window_rect;
+ const wmWindow *win = CTX_wm_window(C);
+ const bScreen *sc = CTX_wm_screen(C);
+ uiPopupMenu *pup;
+ uiLayout *layout;
+ PointerRNA ptr;
+ 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, event->x, event->y);
+ WM_window_rect_calc(win, &window_rect);
+ actedge = screen_geom_area_map_find_active_scredge(
+ AREAMAP_FROM_SCREEN(sc), &window_rect, event->x, event->y);
- if (actedge == NULL) return OPERATOR_CANCELLED;
+ if (actedge == NULL)
+ return OPERATOR_CANCELLED;
- pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
+ pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
- uiItemFullO(layout, "SCREEN_OT_area_split", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr);
- /* store initial mouse cursor position */
- RNA_int_set_array(&ptr, "cursor", &event->x);
+ uiItemFullO(
+ layout, "SCREEN_OT_area_split", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr);
+ /* store initial mouse cursor position */
+ RNA_int_set_array(&ptr, "cursor", &event->x);
- uiItemFullO(layout, "SCREEN_OT_area_join", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr);
- /* mouse cursor on edge, '4' can fail on wide edges... */
- RNA_int_set(&ptr, "min_x", event->x + 4);
- RNA_int_set(&ptr, "min_y", event->y + 4);
- RNA_int_set(&ptr, "max_x", event->x - 4);
- RNA_int_set(&ptr, "max_y", event->y - 4);
+ uiItemFullO(layout, "SCREEN_OT_area_join", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr);
+ /* mouse cursor on edge, '4' can fail on wide edges... */
+ RNA_int_set(&ptr, "min_x", event->x + 4);
+ RNA_int_set(&ptr, "min_y", event->y + 4);
+ RNA_int_set(&ptr, "max_x", event->x - 4);
+ RNA_int_set(&ptr, "max_y", event->y - 4);
- UI_popup_menu_end(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
static void SCREEN_OT_area_options(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Area Options";
- ot->description = "Operations for splitting and merging";
- ot->idname = "SCREEN_OT_area_options";
+ /* identifiers */
+ ot->name = "Area Options";
+ ot->description = "Operations for splitting and merging";
+ ot->idname = "SCREEN_OT_area_options";
- /* api callbacks */
- ot->invoke = screen_area_options_invoke;
+ /* api callbacks */
+ ot->invoke = screen_area_options_invoke;
- ot->poll = ED_operator_screen_mainwinactive;
+ ot->poll = ED_operator_screen_mainwinactive;
- /* flags */
- ot->flag = OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_INTERNAL;
}
/** \} */
@@ -3323,39 +3351,38 @@ static void SCREEN_OT_area_options(wmOperatorType *ot)
static int spacedata_cleanup_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- bScreen *screen;
- ScrArea *sa;
- int tot = 0;
+ Main *bmain = CTX_data_main(C);
+ bScreen *screen;
+ ScrArea *sa;
+ 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;
+ 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);
- }
- }
- }
- BKE_reportf(op->reports, RPT_INFO, "Removed amount of editors: %d", tot);
+ BLI_remlink(&sa->spacedata, sl);
+ tot += BLI_listbase_count(&sa->spacedata);
+ BKE_spacedata_freelist(&sa->spacedata);
+ BLI_addtail(&sa->spacedata, sl);
+ }
+ }
+ }
+ BKE_reportf(op->reports, RPT_INFO, "Removed amount of editors: %d", tot);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SCREEN_OT_spacedata_cleanup(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clean-up Space-data";
- ot->description = "Remove unused settings for invisible editors";
- ot->idname = "SCREEN_OT_spacedata_cleanup";
-
- /* api callbacks */
- ot->exec = spacedata_cleanup_exec;
- ot->poll = WM_operator_winactive;
+ /* identifiers */
+ ot->name = "Clean-up Space-data";
+ ot->description = "Remove unused settings for invisible editors";
+ ot->idname = "SCREEN_OT_spacedata_cleanup";
+ /* api callbacks */
+ ot->exec = spacedata_cleanup_exec;
+ ot->poll = WM_operator_winactive;
}
/** \} */
@@ -3366,39 +3393,38 @@ static void SCREEN_OT_spacedata_cleanup(wmOperatorType *ot)
static int repeat_last_exec(bContext *C, wmOperator *UNUSED(op))
{
- wmWindowManager *wm = CTX_wm_manager(C);
- wmOperator *lastop = wm->operators.last;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmOperator *lastop = wm->operators.last;
- /* Seek last registered operator */
- while (lastop) {
- if (lastop->type->flag & OPTYPE_REGISTER) {
- break;
- }
- else {
- lastop = lastop->prev;
- }
- }
+ /* Seek last registered operator */
+ while (lastop) {
+ if (lastop->type->flag & OPTYPE_REGISTER) {
+ break;
+ }
+ else {
+ lastop = lastop->prev;
+ }
+ }
- if (lastop) {
- WM_operator_free_all_after(wm, lastop);
- WM_operator_repeat_interactive(C, lastop);
- }
+ if (lastop) {
+ WM_operator_free_all_after(wm, lastop);
+ WM_operator_repeat_interactive(C, lastop);
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
static void SCREEN_OT_repeat_last(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Repeat Last";
- ot->description = "Repeat last action";
- ot->idname = "SCREEN_OT_repeat_last";
-
- /* api callbacks */
- ot->exec = repeat_last_exec;
+ /* identifiers */
+ ot->name = "Repeat Last";
+ ot->description = "Repeat last action";
+ ot->idname = "SCREEN_OT_repeat_last";
- ot->poll = ED_operator_screenactive;
+ /* api callbacks */
+ ot->exec = repeat_last_exec;
+ ot->poll = ED_operator_screenactive;
}
/** \} */
@@ -3409,59 +3435,60 @@ static void SCREEN_OT_repeat_last(wmOperatorType *ot)
static int repeat_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- wmWindowManager *wm = CTX_wm_manager(C);
- wmOperator *lastop;
- uiPopupMenu *pup;
- uiLayout *layout;
- int items, i;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmOperator *lastop;
+ uiPopupMenu *pup;
+ uiLayout *layout;
+ int items, i;
- items = BLI_listbase_count(&wm->operators);
- if (items == 0)
- return OPERATOR_CANCELLED;
+ items = BLI_listbase_count(&wm->operators);
+ if (items == 0)
+ return OPERATOR_CANCELLED;
- pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
+ pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
- for (i = items - 1, lastop = wm->operators.last; lastop; lastop = lastop->prev, i--)
- if ((lastop->type->flag & OPTYPE_REGISTER) && WM_operator_repeat_check(C, lastop)) {
- uiItemIntO(layout, RNA_struct_ui_name(lastop->type->srna), ICON_NONE, op->type->idname, "index", i);
- }
+ for (i = items - 1, lastop = wm->operators.last; lastop; lastop = lastop->prev, i--)
+ if ((lastop->type->flag & OPTYPE_REGISTER) && WM_operator_repeat_check(C, lastop)) {
+ uiItemIntO(
+ layout, RNA_struct_ui_name(lastop->type->srna), ICON_NONE, op->type->idname, "index", i);
+ }
- UI_popup_menu_end(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
static int repeat_history_exec(bContext *C, wmOperator *op)
{
- wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
- op = BLI_findlink(&wm->operators, RNA_int_get(op->ptr, "index"));
- if (op) {
- /* let's put it as last operator in list */
- BLI_remlink(&wm->operators, op);
- BLI_addtail(&wm->operators, op);
+ op = BLI_findlink(&wm->operators, RNA_int_get(op->ptr, "index"));
+ if (op) {
+ /* let's put it as last operator in list */
+ BLI_remlink(&wm->operators, op);
+ BLI_addtail(&wm->operators, op);
- WM_operator_repeat(C, op);
- }
+ WM_operator_repeat(C, op);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SCREEN_OT_repeat_history(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Repeat History";
- ot->description = "Display menu for previous actions performed";
- ot->idname = "SCREEN_OT_repeat_history";
+ /* identifiers */
+ ot->name = "Repeat History";
+ ot->description = "Display menu for previous actions performed";
+ ot->idname = "SCREEN_OT_repeat_history";
- /* api callbacks */
- ot->invoke = repeat_history_invoke;
- ot->exec = repeat_history_exec;
+ /* api callbacks */
+ ot->invoke = repeat_history_invoke;
+ ot->exec = repeat_history_exec;
- ot->poll = ED_operator_screenactive;
+ ot->poll = ED_operator_screenactive;
- RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000);
+ RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000);
}
/** \} */
@@ -3472,25 +3499,25 @@ static void SCREEN_OT_repeat_history(wmOperatorType *ot)
static int redo_last_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
- wmOperator *lastop = WM_operator_last_redo(C);
+ wmOperator *lastop = WM_operator_last_redo(C);
- if (lastop)
- WM_operator_redo_popup(C, lastop);
+ if (lastop)
+ WM_operator_redo_popup(C, lastop);
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
static void SCREEN_OT_redo_last(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Redo Last";
- ot->description = "Display menu for last action performed";
- ot->idname = "SCREEN_OT_redo_last";
+ /* identifiers */
+ ot->name = "Redo Last";
+ ot->description = "Display menu for last action performed";
+ ot->idname = "SCREEN_OT_redo_last";
- /* api callbacks */
- ot->invoke = redo_last_invoke;
+ /* api callbacks */
+ ot->invoke = redo_last_invoke;
- ot->poll = ED_operator_screenactive;
+ ot->poll = ED_operator_screenactive;
}
/** \} */
@@ -3501,153 +3528,162 @@ static void SCREEN_OT_redo_last(wmOperatorType *ot)
static void view3d_localview_update_rv3d(struct RegionView3D *rv3d)
{
- if (rv3d->localvd) {
- rv3d->localvd->view = rv3d->view;
- rv3d->localvd->persp = rv3d->persp;
- copy_qt_qt(rv3d->localvd->viewquat, rv3d->viewquat);
- }
+ if (rv3d->localvd) {
+ rv3d->localvd->view = rv3d->view;
+ rv3d->localvd->persp = rv3d->persp;
+ copy_qt_qt(rv3d->localvd->viewquat, rv3d->viewquat);
+ }
}
-static void region_quadview_init_rv3d(ScrArea *sa, ARegion *ar,
- const char viewlock, const char view, const char persp)
+static void region_quadview_init_rv3d(
+ ScrArea *sa, ARegion *ar, const char viewlock, const char view, const char persp)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = ar->regiondata;
- if (persp == RV3D_CAMOB) {
- ED_view3d_lastview_store(rv3d);
- }
+ if (persp == RV3D_CAMOB) {
+ ED_view3d_lastview_store(rv3d);
+ }
- rv3d->viewlock = viewlock;
- rv3d->view = view;
- rv3d->persp = persp;
+ rv3d->viewlock = viewlock;
+ rv3d->view = view;
+ 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_lock(rv3d);
+ view3d_localview_update_rv3d(rv3d);
+ if ((viewlock & RV3D_BOXCLIP) && (persp == RV3D_ORTHO)) {
+ ED_view3d_quadview_update(sa, ar, true);
+ }
}
/* insert a region in the area region list */
static int region_quadview_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
-
- /* some rules... */
- if (ar->regiontype != RGN_TYPE_WINDOW) {
- BKE_report(op->reports, RPT_ERROR, "Only window region can be 4-splitted");
- }
- else if (ar->alignment == RGN_ALIGN_QSPLIT) {
- /* Exit quad-view */
- ScrArea *sa = CTX_wm_area(C);
- ARegion *arn;
-
- /* keep current region */
- ar->alignment = 0;
-
- if (sa->spacetype == SPACE_VIEW3D) {
- ARegion *ar_iter;
- RegionView3D *rv3d = ar->regiondata;
-
- /* if this is a locked view, use settings from 'User' view */
- if (rv3d->viewlock) {
- View3D *v3d_user;
- ARegion *ar_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;
- }
- }
- }
-
- rv3d->viewlock_quad = RV3D_VIEWLOCK_INIT;
- rv3d->viewlock = 0;
- rv3d->rflag &= ~RV3D_CLIPPING;
-
- /* accumulate locks, incase 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;
- 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_exit(C, ar);
- BKE_area_region_free(sa->type, ar);
- BLI_remlink(&sa->regionbase, ar);
- MEM_freeN(ar);
- }
- }
- ED_area_tag_redraw(sa);
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
- }
- else if (ar->next) {
- BKE_report(op->reports, RPT_ERROR, "Only last region can be 4-splitted");
- }
- else {
- /* Enter quad-view */
- ScrArea *sa = CTX_wm_area(C);
- ARegion *newar;
- int count;
-
- ar->alignment = RGN_ALIGN_QSPLIT;
-
- for (count = 0; count < 3; count++) {
- newar = BKE_area_region_copy(sa->type, ar);
- BLI_addtail(&sa->regionbase, newar);
- }
-
- /* lock views and set them */
- if (sa->spacetype == SPACE_VIEW3D) {
- View3D *v3d = sa->spacedata.first;
- int index_qsplit = 0;
-
- /* run ED_view3d_lock() so the correct 'rv3d->viewquat' is set,
- * otherwise when restoring rv3d->localvd the 'viewquat' won't
- * match the 'view', set on entering localview See: [#26315],
- *
- * We could avoid manipulating rv3d->localvd here if exiting
- * localview with a 4-split would assign these view locks */
- RegionView3D *rv3d = ar->regiondata;
- const char viewlock = (rv3d->viewlock_quad & RV3D_VIEWLOCK_INIT) ?
- (rv3d->viewlock_quad & ~RV3D_VIEWLOCK_INIT) : RV3D_LOCKED;
-
- 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), viewlock, ED_view3d_lock_view_from_index(index_qsplit++), RV3D_ORTHO);
- region_quadview_init_rv3d(sa, (ar = ar->next), viewlock, ED_view3d_lock_view_from_index(index_qsplit++), RV3D_ORTHO);
- /* forcing camera is distracting */
+ ARegion *ar = CTX_wm_region(C);
+
+ /* some rules... */
+ if (ar->regiontype != RGN_TYPE_WINDOW) {
+ BKE_report(op->reports, RPT_ERROR, "Only window region can be 4-splitted");
+ }
+ else if (ar->alignment == RGN_ALIGN_QSPLIT) {
+ /* Exit quad-view */
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *arn;
+
+ /* keep current region */
+ ar->alignment = 0;
+
+ if (sa->spacetype == SPACE_VIEW3D) {
+ ARegion *ar_iter;
+ RegionView3D *rv3d = ar->regiondata;
+
+ /* if this is a locked view, use settings from 'User' view */
+ if (rv3d->viewlock) {
+ View3D *v3d_user;
+ ARegion *ar_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;
+ }
+ }
+ }
+
+ rv3d->viewlock_quad = RV3D_VIEWLOCK_INIT;
+ rv3d->viewlock = 0;
+ rv3d->rflag &= ~RV3D_CLIPPING;
+
+ /* accumulate locks, incase 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;
+ 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_exit(C, ar);
+ BKE_area_region_free(sa->type, ar);
+ BLI_remlink(&sa->regionbase, ar);
+ MEM_freeN(ar);
+ }
+ }
+ ED_area_tag_redraw(sa);
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ }
+ else if (ar->next) {
+ BKE_report(op->reports, RPT_ERROR, "Only last region can be 4-splitted");
+ }
+ else {
+ /* Enter quad-view */
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *newar;
+ int count;
+
+ ar->alignment = RGN_ALIGN_QSPLIT;
+
+ for (count = 0; count < 3; count++) {
+ newar = BKE_area_region_copy(sa->type, ar);
+ BLI_addtail(&sa->regionbase, newar);
+ }
+
+ /* lock views and set them */
+ if (sa->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = sa->spacedata.first;
+ int index_qsplit = 0;
+
+ /* run ED_view3d_lock() so the correct 'rv3d->viewquat' is set,
+ * otherwise when restoring rv3d->localvd the 'viewquat' won't
+ * match the 'view', set on entering localview See: [#26315],
+ *
+ * We could avoid manipulating rv3d->localvd here if exiting
+ * localview with a 4-split would assign these view locks */
+ RegionView3D *rv3d = ar->regiondata;
+ const char viewlock = (rv3d->viewlock_quad & RV3D_VIEWLOCK_INIT) ?
+ (rv3d->viewlock_quad & ~RV3D_VIEWLOCK_INIT) :
+ RV3D_LOCKED;
+
+ 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),
+ viewlock,
+ ED_view3d_lock_view_from_index(index_qsplit++),
+ RV3D_ORTHO);
+ region_quadview_init_rv3d(sa,
+ (ar = ar->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);
- else region_quadview_init_rv3d(sa, (ar = ar->next), 0, RV3D_VIEW_USER, RV3D_PERSP);
+ if (v3d->camera) region_quadview_init_rv3d(sa, (ar = ar->next), 0, RV3D_VIEW_CAMERA, RV3D_CAMOB);
+ else region_quadview_init_rv3d(sa, (ar = ar->next), 0, RV3D_VIEW_USER, RV3D_PERSP);
#else
- (void)v3d;
+ (void)v3d;
#endif
- }
- ED_area_tag_redraw(sa);
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
- }
+ }
+ ED_area_tag_redraw(sa);
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ }
-
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SCREEN_OT_region_quadview(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Quad View";
- ot->description = "Split selected area into camera, front, right & top views";
- ot->idname = "SCREEN_OT_region_quadview";
+ /* identifiers */
+ ot->name = "Toggle Quad View";
+ ot->description = "Split selected area into camera, front, right & top views";
+ ot->idname = "SCREEN_OT_region_quadview";
- /* api callbacks */
- ot->exec = region_quadview_exec;
- ot->poll = ED_operator_region_view3d_active;
- ot->flag = 0;
+ /* api callbacks */
+ ot->exec = region_quadview_exec;
+ ot->poll = ED_operator_region_view3d_active;
+ ot->flag = 0;
}
/** \} */
@@ -3659,51 +3695,51 @@ static void SCREEN_OT_region_quadview(wmOperatorType *ot)
/* flip a region alignment */
static int region_flip_exec(bContext *C, wmOperator *UNUSED(op))
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *ar = CTX_wm_region(C);
- if (!ar)
- return OPERATOR_CANCELLED;
+ if (!ar)
+ return OPERATOR_CANCELLED;
- if (ar->alignment == RGN_ALIGN_TOP)
- ar->alignment = RGN_ALIGN_BOTTOM;
- else if (ar->alignment == RGN_ALIGN_BOTTOM)
- ar->alignment = RGN_ALIGN_TOP;
- else if (ar->alignment == RGN_ALIGN_LEFT)
- ar->alignment = RGN_ALIGN_RIGHT;
- else if (ar->alignment == RGN_ALIGN_RIGHT)
- ar->alignment = RGN_ALIGN_LEFT;
+ if (ar->alignment == RGN_ALIGN_TOP)
+ ar->alignment = RGN_ALIGN_BOTTOM;
+ else if (ar->alignment == RGN_ALIGN_BOTTOM)
+ ar->alignment = RGN_ALIGN_TOP;
+ else if (ar->alignment == RGN_ALIGN_LEFT)
+ ar->alignment = RGN_ALIGN_RIGHT;
+ else if (ar->alignment == RGN_ALIGN_RIGHT)
+ ar->alignment = RGN_ALIGN_LEFT;
- ED_area_tag_redraw(CTX_wm_area(C));
- WM_event_add_mousemove(C);
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ ED_area_tag_redraw(CTX_wm_area(C));
+ WM_event_add_mousemove(C);
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static bool region_flip_poll(bContext *C)
{
- ScrArea *area = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
- /* don't flip anything around in topbar */
- if (area && area->spacetype == SPACE_TOPBAR) {
- CTX_wm_operator_poll_msg_set(C, "Flipping regions in the Top-bar is not allowed");
- return 0;
- }
+ /* don't flip anything around in topbar */
+ if (area && area->spacetype == SPACE_TOPBAR) {
+ CTX_wm_operator_poll_msg_set(C, "Flipping regions in the Top-bar is not allowed");
+ return 0;
+ }
- return ED_operator_areaactive(C);
+ return ED_operator_areaactive(C);
}
static void SCREEN_OT_region_flip(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Flip Region";
- ot->idname = "SCREEN_OT_region_flip";
- ot->description = "Toggle the region's alignment (left/right or top/bottom)";
+ /* identifiers */
+ ot->name = "Flip Region";
+ ot->idname = "SCREEN_OT_region_flip";
+ ot->description = "Toggle the region's alignment (left/right or top/bottom)";
- /* api callbacks */
- ot->exec = region_flip_exec;
- ot->poll = region_flip_poll;
- ot->flag = 0;
+ /* api callbacks */
+ ot->exec = region_flip_exec;
+ ot->poll = region_flip_poll;
+ ot->flag = 0;
}
/** \} */
@@ -3714,30 +3750,30 @@ static void SCREEN_OT_region_flip(wmOperatorType *ot)
static int header_exec(bContext *C, wmOperator *UNUSED(op))
{
- ARegion *ar = screen_find_region_type(C, RGN_TYPE_HEADER);
+ ARegion *ar = screen_find_region_type(C, RGN_TYPE_HEADER);
- if (ar == NULL) {
- return OPERATOR_CANCELLED;
- }
+ if (ar == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- ar->flag ^= RGN_FLAG_HIDDEN;
+ ar->flag ^= RGN_FLAG_HIDDEN;
- ED_area_tag_redraw(CTX_wm_area(C));
+ ED_area_tag_redraw(CTX_wm_area(C));
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SCREEN_OT_header(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Header";
- ot->description = "Toggle header display";
- ot->idname = "SCREEN_OT_header";
+ /* identifiers */
+ ot->name = "Toggle Header";
+ ot->description = "Toggle header display";
+ ot->idname = "SCREEN_OT_header";
- /* api callbacks */
- ot->exec = header_exec;
+ /* api callbacks */
+ ot->exec = header_exec;
}
/** \} */
@@ -3749,28 +3785,27 @@ static void SCREEN_OT_header(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 *sa = CTX_wm_area(C);
- sa->flag = sa->flag ^ HEADER_NO_PULLDOWN;
+ sa->flag = sa->flag ^ HEADER_NO_PULLDOWN;
- ED_area_tag_redraw(sa);
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ ED_area_tag_redraw(sa);
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
static void SCREEN_OT_header_toggle_menus(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Expand/Collapse Header Menus";
- ot->idname = "SCREEN_OT_header_toggle_menus";
- ot->description = "Expand or collapse the header pulldown menus";
+ /* identifiers */
+ ot->name = "Expand/Collapse Header Menus";
+ ot->idname = "SCREEN_OT_header_toggle_menus";
+ ot->description = "Expand or collapse the header pulldown menus";
- /* api callbacks */
- ot->exec = header_toggle_menus_exec;
- ot->poll = ED_operator_areaactive;
- ot->flag = 0;
+ /* api callbacks */
+ ot->exec = header_toggle_menus_exec;
+ ot->poll = ED_operator_areaactive;
+ ot->flag = 0;
}
/** \} */
@@ -3781,66 +3816,70 @@ static void SCREEN_OT_header_toggle_menus(wmOperatorType *ot)
static bool header_context_menu_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- return (sa && sa->spacetype != SPACE_STATUSBAR);
+ ScrArea *sa = CTX_wm_area(C);
+ return (sa && sa->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 = (ar->alignment == RGN_ALIGN_TOP) ? IFACE_("Flip to Bottom") : IFACE_("Flip to Top");
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ const char *but_flip_str = (ar->alignment == RGN_ALIGN_TOP) ? IFACE_("Flip to Bottom") :
+ IFACE_("Flip to Top");
- if (!ELEM(sa->spacetype, SPACE_TOPBAR)) {
- uiItemO(layout, IFACE_("Toggle Header"), ICON_NONE, "SCREEN_OT_header");
- }
+ if (!ELEM(sa->spacetype, SPACE_TOPBAR)) {
+ uiItemO(layout, IFACE_("Toggle Header"), ICON_NONE, "SCREEN_OT_header");
+ }
- /* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */
- uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
+ /* 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)) {
- uiItemO(layout, but_flip_str, ICON_NONE, "SCREEN_OT_region_flip");
- }
+ if (!ELEM(sa->spacetype, SPACE_TOPBAR)) {
+ uiItemO(layout, but_flip_str, ICON_NONE, "SCREEN_OT_region_flip");
+ }
- uiItemO(layout, IFACE_("Collapse Menus"),
- (sa->flag & HEADER_NO_PULLDOWN) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT,
- "SCREEN_OT_header_toggle_menus");
+ uiItemO(layout,
+ IFACE_("Collapse Menus"),
+ (sa->flag & HEADER_NO_PULLDOWN) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT,
+ "SCREEN_OT_header_toggle_menus");
- /* 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)) {
- uiItemS(layout);
+ /* 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)) {
+ uiItemS(layout);
- const char *but_str = sa->full ? IFACE_("Tile Area") : IFACE_("Maximize Area");
- uiItemO(layout, but_str, ICON_NONE, "SCREEN_OT_screen_full_area");
- }
+ const char *but_str = sa->full ? IFACE_("Tile Area") : IFACE_("Maximize Area");
+ uiItemO(layout, but_str, ICON_NONE, "SCREEN_OT_screen_full_area");
+ }
}
-static int header_context_menu_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
+static int header_context_menu_invoke(bContext *C,
+ wmOperator *UNUSED(op),
+ const wmEvent *UNUSED(event))
{
- uiPopupMenu *pup;
- uiLayout *layout;
+ uiPopupMenu *pup;
+ uiLayout *layout;
- pup = UI_popup_menu_begin(C, IFACE_("Header"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
+ 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);
+ ED_screens_header_tools_menu_create(C, layout, NULL);
- UI_popup_menu_end(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
static void SCREEN_OT_header_context_menu(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Header Context Menu";
- ot->description = "Display header region context menu";
- ot->idname = "SCREEN_OT_header_context_menu";
+ /* identifiers */
+ ot->name = "Header Context Menu";
+ ot->description = "Display header region context menu";
+ ot->idname = "SCREEN_OT_header_context_menu";
- /* api callbacks */
- ot->poll = header_context_menu_poll;
- ot->invoke = header_context_menu_invoke;
+ /* api callbacks */
+ ot->poll = header_context_menu_poll;
+ ot->invoke = header_context_menu_invoke;
}
/** \} */
@@ -3851,30 +3890,30 @@ static void SCREEN_OT_header_context_menu(wmOperatorType *ot)
static int footer_exec(bContext *C, wmOperator *UNUSED(op))
{
- ARegion *ar = screen_find_region_type(C, RGN_TYPE_FOOTER);
+ ARegion *ar = screen_find_region_type(C, RGN_TYPE_FOOTER);
- if (ar == NULL) {
- return OPERATOR_CANCELLED;
- }
+ if (ar == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- ar->flag ^= RGN_FLAG_HIDDEN;
+ ar->flag ^= RGN_FLAG_HIDDEN;
- ED_area_tag_redraw(CTX_wm_area(C));
+ ED_area_tag_redraw(CTX_wm_area(C));
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SCREEN_OT_footer(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Footer";
- ot->description = "Toggle footer display";
- ot->idname = "SCREEN_OT_footer";
+ /* identifiers */
+ ot->name = "Toggle Footer";
+ ot->description = "Toggle footer display";
+ ot->idname = "SCREEN_OT_footer";
- /* api callbacks */
- ot->exec = footer_exec;
+ /* api callbacks */
+ ot->exec = footer_exec;
}
/** \} */
@@ -3885,59 +3924,61 @@ static void SCREEN_OT_footer(wmOperatorType *ot)
static bool footer_context_menu_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- return sa;
+ ScrArea *sa = CTX_wm_area(C);
+ return sa;
}
void ED_screens_footer_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- const char *but_flip_str = (ar->alignment == RGN_ALIGN_TOP) ? IFACE_("Flip to Bottom") : IFACE_("Flip to Top");
-
- uiItemO(layout, IFACE_("Toggle Footer"), ICON_NONE, "SCREEN_OT_footer");
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ const char *but_flip_str = (ar->alignment == RGN_ALIGN_TOP) ? IFACE_("Flip to Bottom") :
+ IFACE_("Flip to Top");
- /* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */
- uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
+ uiItemO(layout, IFACE_("Toggle Footer"), ICON_NONE, "SCREEN_OT_footer");
- uiItemO(layout, but_flip_str, ICON_NONE, "SCREEN_OT_region_flip");
+ /* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
+ uiItemO(layout, but_flip_str, ICON_NONE, "SCREEN_OT_region_flip");
- /* file browser should be fullscreen all the time, topbar should
- * never be. But other regions can be maximized/restored... */
- if (!ELEM(sa->spacetype, SPACE_FILE, SPACE_TOPBAR)) {
- uiItemS(layout);
+ /* file browser should be fullscreen all the time, topbar should
+ * never be. But other regions can be maximized/restored... */
+ if (!ELEM(sa->spacetype, SPACE_FILE, SPACE_TOPBAR)) {
+ uiItemS(layout);
- const char *but_str = sa->full ? IFACE_("Tile Area") : IFACE_("Maximize Area");
- uiItemO(layout, but_str, ICON_NONE, "SCREEN_OT_screen_full_area");
- }
+ const char *but_str = sa->full ? IFACE_("Tile Area") : IFACE_("Maximize Area");
+ uiItemO(layout, but_str, ICON_NONE, "SCREEN_OT_screen_full_area");
+ }
}
-static int footer_context_menu_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
+static int footer_context_menu_invoke(bContext *C,
+ wmOperator *UNUSED(op),
+ const wmEvent *UNUSED(event))
{
- uiPopupMenu *pup;
- uiLayout *layout;
+ uiPopupMenu *pup;
+ uiLayout *layout;
- pup = UI_popup_menu_begin(C, IFACE_("Footer"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
+ 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);
+ ED_screens_footer_tools_menu_create(C, layout, NULL);
- UI_popup_menu_end(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
static void SCREEN_OT_footer_context_menu(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Footer Context Menu";
- ot->description = "Display footer region context menu";
- ot->idname = "SCREEN_OT_footer_context_menu";
+ /* identifiers */
+ ot->name = "Footer Context Menu";
+ ot->description = "Display footer region context menu";
+ ot->idname = "SCREEN_OT_footer_context_menu";
- /* api callbacks */
- ot->poll = footer_context_menu_poll;
- ot->invoke = footer_context_menu_invoke;
+ /* api callbacks */
+ ot->poll = footer_context_menu_poll;
+ ot->invoke = footer_context_menu_invoke;
}
/** \} */
@@ -3948,13 +3989,14 @@ static void SCREEN_OT_footer_context_menu(wmOperatorType *ot)
void ED_screens_navigation_bar_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
{
- const ARegion *ar = CTX_wm_region(C);
- const char *but_flip_str = (ar->alignment == RGN_ALIGN_LEFT) ? IFACE_("Flip to Right") : IFACE_("Flip to Left");
+ const ARegion *ar = CTX_wm_region(C);
+ const char *but_flip_str = (ar->alignment == RGN_ALIGN_LEFT) ? IFACE_("Flip to Right") :
+ IFACE_("Flip to Left");
- /* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */
- uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
+ /* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
- uiItemO(layout, but_flip_str, ICON_NONE, "SCREEN_OT_region_flip");
+ uiItemO(layout, but_flip_str, ICON_NONE, "SCREEN_OT_region_flip");
}
/** \} */
@@ -3967,297 +4009,299 @@ void ED_screens_navigation_bar_tools_menu_create(bContext *C, uiLayout *layout,
static int match_area_with_refresh(int spacetype, int refresh)
{
- switch (spacetype) {
- case SPACE_TIME:
- if (refresh & SPACE_TIME)
- return 1;
- break;
- }
-
- return 0;
-}
-
-static int match_region_with_redraws(int spacetype, int regiontype, int redraws, bool from_anim_edit)
-{
- if (regiontype == RGN_TYPE_WINDOW) {
-
- switch (spacetype) {
- case SPACE_VIEW3D:
- if ((redraws & TIME_ALL_3D_WIN) || from_anim_edit)
- return 1;
- break;
- case SPACE_GRAPH:
- case SPACE_NLA:
- if ((redraws & TIME_ALL_ANIM_WIN) || from_anim_edit)
- return 1;
- break;
- case SPACE_ACTION:
- /* if only 1 window or 3d windows, we do timeline too
- * NOTE: Now we do do action editor in all these cases, since timeline is here
- */
- if ((redraws & (TIME_ALL_ANIM_WIN | TIME_REGION | TIME_ALL_3D_WIN)) || from_anim_edit)
- return 1;
- break;
- case SPACE_PROPERTIES:
- if (redraws & TIME_ALL_BUTS_WIN)
- return 1;
- break;
- case SPACE_SEQ:
- if ((redraws & (TIME_SEQ | TIME_ALL_ANIM_WIN)) || from_anim_edit)
- return 1;
- break;
- case SPACE_NODE:
- if (redraws & (TIME_NODES))
- return 1;
- break;
- case SPACE_IMAGE:
- if ((redraws & TIME_ALL_IMAGE_WIN) || from_anim_edit)
- return 1;
- break;
- case SPACE_CLIP:
- if ((redraws & TIME_CLIPS) || from_anim_edit)
- return 1;
- break;
-
- }
- }
- else if (regiontype == RGN_TYPE_CHANNELS) {
- switch (spacetype) {
- case SPACE_GRAPH:
- case SPACE_ACTION:
- case SPACE_NLA:
- if (redraws & TIME_ALL_ANIM_WIN)
- return 1;
- break;
- }
- }
- else if (regiontype == RGN_TYPE_UI) {
- if (spacetype == SPACE_CLIP) {
- /* Track Preview button is on Properties Editor in SpaceClip,
- * and it's very common case when users want it be refreshing
- * during playback, so asking people to enable special option
- * for this is a bit tricky, so add exception here for refreshing
- * Properties Editor for SpaceClip always */
- return 1;
- }
-
- if (redraws & TIME_ALL_BUTS_WIN)
- return 1;
- }
- else if (regiontype == RGN_TYPE_HEADER) {
- if (spacetype == SPACE_ACTION)
- return 1;
- }
- else if (regiontype == RGN_TYPE_PREVIEW) {
- switch (spacetype) {
- case SPACE_SEQ:
- if (redraws & (TIME_SEQ | TIME_ALL_ANIM_WIN))
- return 1;
- break;
- case SPACE_CLIP:
- return 1;
- }
- }
- return 0;
+ switch (spacetype) {
+ case SPACE_TIME:
+ if (refresh & SPACE_TIME)
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+static int match_region_with_redraws(int spacetype,
+ int regiontype,
+ int redraws,
+ bool from_anim_edit)
+{
+ if (regiontype == RGN_TYPE_WINDOW) {
+
+ switch (spacetype) {
+ case SPACE_VIEW3D:
+ if ((redraws & TIME_ALL_3D_WIN) || from_anim_edit)
+ return 1;
+ break;
+ case SPACE_GRAPH:
+ case SPACE_NLA:
+ if ((redraws & TIME_ALL_ANIM_WIN) || from_anim_edit)
+ return 1;
+ break;
+ case SPACE_ACTION:
+ /* if only 1 window or 3d windows, we do timeline too
+ * NOTE: Now we do do action editor in all these cases, since timeline is here
+ */
+ if ((redraws & (TIME_ALL_ANIM_WIN | TIME_REGION | TIME_ALL_3D_WIN)) || from_anim_edit)
+ return 1;
+ break;
+ case SPACE_PROPERTIES:
+ if (redraws & TIME_ALL_BUTS_WIN)
+ return 1;
+ break;
+ case SPACE_SEQ:
+ if ((redraws & (TIME_SEQ | TIME_ALL_ANIM_WIN)) || from_anim_edit)
+ return 1;
+ break;
+ case SPACE_NODE:
+ if (redraws & (TIME_NODES))
+ return 1;
+ break;
+ case SPACE_IMAGE:
+ if ((redraws & TIME_ALL_IMAGE_WIN) || from_anim_edit)
+ return 1;
+ break;
+ case SPACE_CLIP:
+ if ((redraws & TIME_CLIPS) || from_anim_edit)
+ return 1;
+ break;
+ }
+ }
+ else if (regiontype == RGN_TYPE_CHANNELS) {
+ switch (spacetype) {
+ case SPACE_GRAPH:
+ case SPACE_ACTION:
+ case SPACE_NLA:
+ if (redraws & TIME_ALL_ANIM_WIN)
+ return 1;
+ break;
+ }
+ }
+ else if (regiontype == RGN_TYPE_UI) {
+ if (spacetype == SPACE_CLIP) {
+ /* Track Preview button is on Properties Editor in SpaceClip,
+ * and it's very common case when users want it be refreshing
+ * during playback, so asking people to enable special option
+ * for this is a bit tricky, so add exception here for refreshing
+ * Properties Editor for SpaceClip always */
+ return 1;
+ }
+
+ if (redraws & TIME_ALL_BUTS_WIN)
+ return 1;
+ }
+ else if (regiontype == RGN_TYPE_HEADER) {
+ if (spacetype == SPACE_ACTION)
+ return 1;
+ }
+ else if (regiontype == RGN_TYPE_PREVIEW) {
+ switch (spacetype) {
+ case SPACE_SEQ:
+ if (redraws & (TIME_SEQ | TIME_ALL_ANIM_WIN))
+ return 1;
+ break;
+ case SPACE_CLIP:
+ return 1;
+ }
+ }
+ return 0;
}
//#define PROFILE_AUDIO_SYNCH
static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- bScreen *screen = CTX_wm_screen(C);
+ bScreen *screen = CTX_wm_screen(C);
#ifdef PROFILE_AUDIO_SYNCH
- static int old_frame = 0;
- int newfra_int;
+ static int old_frame = 0;
+ int newfra_int;
#endif
- if (screen->animtimer && screen->animtimer == event->customdata) {
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
- wmTimer *wt = screen->animtimer;
- ScreenAnimData *sad = wt->customdata;
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *window;
- ScrArea *sa;
- int sync;
- float time;
-
- /* sync, don't sync, or follow scene setting */
- if (sad->flag & ANIMPLAY_FLAG_SYNC) sync = 1;
- else if (sad->flag & ANIMPLAY_FLAG_NO_SYNC) sync = 0;
- else sync = (scene->flag & SCE_FRAME_DROP);
-
- if ((scene->audio.flag & AUDIO_SYNC) &&
- (sad->flag & ANIMPLAY_FLAG_REVERSE) == false &&
- isfinite(time = BKE_sound_sync_scene(scene)))
- {
- double newfra = (double)time * FPS;
-
- /* give some space here to avoid jumps */
- if (newfra + 0.5 > scene->r.cfra && newfra - 0.5 < scene->r.cfra)
- scene->r.cfra++;
- else
- scene->r.cfra = newfra + 0.5;
+ if (screen->animtimer && screen->animtimer == event->customdata) {
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ wmTimer *wt = screen->animtimer;
+ ScreenAnimData *sad = wt->customdata;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *window;
+ ScrArea *sa;
+ int sync;
+ float time;
+
+ /* sync, don't sync, or follow scene setting */
+ if (sad->flag & ANIMPLAY_FLAG_SYNC)
+ sync = 1;
+ else if (sad->flag & ANIMPLAY_FLAG_NO_SYNC)
+ sync = 0;
+ else
+ sync = (scene->flag & SCE_FRAME_DROP);
+
+ if ((scene->audio.flag & AUDIO_SYNC) && (sad->flag & ANIMPLAY_FLAG_REVERSE) == false &&
+ isfinite(time = BKE_sound_sync_scene(scene))) {
+ double newfra = (double)time * FPS;
+
+ /* give some space here to avoid jumps */
+ if (newfra + 0.5 > scene->r.cfra && newfra - 0.5 < scene->r.cfra)
+ scene->r.cfra++;
+ else
+ scene->r.cfra = newfra + 0.5;
#ifdef PROFILE_AUDIO_SYNCH
- newfra_int = scene->r.cfra;
- if (newfra_int < old_frame) {
- printf("back jump detected, frame %d!\n", newfra_int);
- }
- else if (newfra_int > old_frame + 1) {
- printf("forward jump detected, frame %d!\n", newfra_int);
- }
- fflush(stdout);
- old_frame = newfra_int;
+ newfra_int = scene->r.cfra;
+ if (newfra_int < old_frame) {
+ printf("back jump detected, frame %d!\n", newfra_int);
+ }
+ else if (newfra_int > old_frame + 1) {
+ printf("forward jump detected, frame %d!\n", newfra_int);
+ }
+ fflush(stdout);
+ old_frame = newfra_int;
#endif
- }
- 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));
-
- /* skip frames */
- if (sad->flag & ANIMPLAY_FLAG_REVERSE)
- scene->r.cfra -= step;
- else
- scene->r.cfra += step;
- }
- else {
- /* one frame +/- */
- if (sad->flag & ANIMPLAY_FLAG_REVERSE)
- scene->r.cfra--;
- else
- scene->r.cfra++;
- }
- }
-
- sad->last_duration = wt->duration;
-
- /* reset 'jumped' flag before checking if we need to jump... */
- sad->flag &= ~ANIMPLAY_FLAG_JUMPED;
-
- if (sad->flag & ANIMPLAY_FLAG_REVERSE) {
- /* jump back to end? */
- if (PRVRANGEON) {
- if (scene->r.cfra < scene->r.psfra) {
- scene->r.cfra = scene->r.pefra;
- sad->flag |= ANIMPLAY_FLAG_JUMPED;
- }
- }
- else {
- if (scene->r.cfra < scene->r.sfra) {
- scene->r.cfra = scene->r.efra;
- sad->flag |= ANIMPLAY_FLAG_JUMPED;
- }
- }
- }
- else {
- /* jump back to start? */
- if (PRVRANGEON) {
- if (scene->r.cfra > scene->r.pefra) {
- scene->r.cfra = scene->r.psfra;
- sad->flag |= ANIMPLAY_FLAG_JUMPED;
- }
- }
- else {
- if (scene->r.cfra > scene->r.efra) {
- scene->r.cfra = scene->r.sfra;
- sad->flag |= ANIMPLAY_FLAG_JUMPED;
- }
- }
- }
-
- /* next frame overridden by user action (pressed jump to first/last frame) */
- if (sad->flag & ANIMPLAY_FLAG_USE_NEXT_FRAME) {
- scene->r.cfra = sad->nextfra;
- sad->flag &= ~ANIMPLAY_FLAG_USE_NEXT_FRAME;
- sad->flag |= ANIMPLAY_FLAG_JUMPED;
- }
-
- if (sad->flag & ANIMPLAY_FLAG_JUMPED) {
- BKE_sound_seek_scene(bmain, scene);
+ }
+ 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));
+
+ /* skip frames */
+ if (sad->flag & ANIMPLAY_FLAG_REVERSE)
+ scene->r.cfra -= step;
+ else
+ scene->r.cfra += step;
+ }
+ else {
+ /* one frame +/- */
+ if (sad->flag & ANIMPLAY_FLAG_REVERSE)
+ scene->r.cfra--;
+ else
+ scene->r.cfra++;
+ }
+ }
+
+ sad->last_duration = wt->duration;
+
+ /* reset 'jumped' flag before checking if we need to jump... */
+ sad->flag &= ~ANIMPLAY_FLAG_JUMPED;
+
+ if (sad->flag & ANIMPLAY_FLAG_REVERSE) {
+ /* jump back to end? */
+ if (PRVRANGEON) {
+ if (scene->r.cfra < scene->r.psfra) {
+ scene->r.cfra = scene->r.pefra;
+ sad->flag |= ANIMPLAY_FLAG_JUMPED;
+ }
+ }
+ else {
+ if (scene->r.cfra < scene->r.sfra) {
+ scene->r.cfra = scene->r.efra;
+ sad->flag |= ANIMPLAY_FLAG_JUMPED;
+ }
+ }
+ }
+ else {
+ /* jump back to start? */
+ if (PRVRANGEON) {
+ if (scene->r.cfra > scene->r.pefra) {
+ scene->r.cfra = scene->r.psfra;
+ sad->flag |= ANIMPLAY_FLAG_JUMPED;
+ }
+ }
+ else {
+ if (scene->r.cfra > scene->r.efra) {
+ scene->r.cfra = scene->r.sfra;
+ sad->flag |= ANIMPLAY_FLAG_JUMPED;
+ }
+ }
+ }
+
+ /* next frame overridden by user action (pressed jump to first/last frame) */
+ if (sad->flag & ANIMPLAY_FLAG_USE_NEXT_FRAME) {
+ scene->r.cfra = sad->nextfra;
+ sad->flag &= ~ANIMPLAY_FLAG_USE_NEXT_FRAME;
+ sad->flag |= ANIMPLAY_FLAG_JUMPED;
+ }
+
+ if (sad->flag & ANIMPLAY_FLAG_JUMPED) {
+ BKE_sound_seek_scene(bmain, scene);
#ifdef PROFILE_AUDIO_SYNCH
- old_frame = CFRA;
+ old_frame = CFRA;
#endif
- }
-
- /* since we follow drawflags, we can't send notifier but tag regions ourselves */
- ED_update_for_newframe(bmain, depsgraph);
-
- for (window = wm->windows.first; window; window = window->next) {
- const bScreen *win_screen = WM_window_get_active_screen(window);
-
- for (sa = win_screen->areabase.first; sa; sa = sa->next) {
- ARegion *ar;
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- bool redraw = false;
- if (ar == sad->ar) {
- redraw = true;
- }
- else if (match_region_with_redraws(sa->spacetype, ar->regiontype, sad->redraws, sad->from_anim_edit)) {
- redraw = true;
- }
-
- if (redraw) {
- ED_region_tag_redraw(ar);
- /* 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;
- }
- 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;
- }
- }
- }
- }
- }
-
- if (match_area_with_refresh(sa->spacetype, sad->refresh))
- ED_area_tag_refresh(sa);
- }
- }
-
- /* update frame rate info too
- * NOTE: this may not be accurate enough, since we might need this after modifiers/etc.
- * have been calculated instead of just before updates have been done?
- */
- ED_refresh_viewport_fps(C);
-
- /* Recalculate the time-step for the timer now that we've finished calculating this,
- * since the frames-per-second value may have been changed.
- */
- /* TODO: this may make evaluation a bit slower if the value doesn't change... any way to avoid this? */
- wt->timestep = (1.0 / FPS);
-
- return OPERATOR_FINISHED;
- }
- return OPERATOR_PASS_THROUGH;
+ }
+
+ /* since we follow drawflags, we can't send notifier but tag regions ourselves */
+ ED_update_for_newframe(bmain, depsgraph);
+
+ for (window = wm->windows.first; window; window = window->next) {
+ const bScreen *win_screen = WM_window_get_active_screen(window);
+
+ for (sa = win_screen->areabase.first; sa; sa = sa->next) {
+ ARegion *ar;
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ bool redraw = false;
+ if (ar == sad->ar) {
+ redraw = true;
+ }
+ else if (match_region_with_redraws(
+ sa->spacetype, ar->regiontype, sad->redraws, sad->from_anim_edit)) {
+ redraw = true;
+ }
+
+ if (redraw) {
+ ED_region_tag_redraw(ar);
+ /* 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;
+ }
+ 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;
+ }
+ }
+ }
+ }
+ }
+
+ if (match_area_with_refresh(sa->spacetype, sad->refresh))
+ ED_area_tag_refresh(sa);
+ }
+ }
+
+ /* update frame rate info too
+ * NOTE: this may not be accurate enough, since we might need this after modifiers/etc.
+ * have been calculated instead of just before updates have been done?
+ */
+ ED_refresh_viewport_fps(C);
+
+ /* Recalculate the time-step for the timer now that we've finished calculating this,
+ * since the frames-per-second value may have been changed.
+ */
+ /* TODO: this may make evaluation a bit slower if the value doesn't change... any way to avoid this? */
+ wt->timestep = (1.0 / FPS);
+
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_PASS_THROUGH;
}
static void SCREEN_OT_animation_step(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Animation Step";
- ot->description = "Step through animation by position";
- ot->idname = "SCREEN_OT_animation_step";
+ /* identifiers */
+ ot->name = "Animation Step";
+ ot->description = "Step through animation by position";
+ ot->idname = "SCREEN_OT_animation_step";
- /* api callbacks */
- ot->invoke = screen_animation_step;
-
- ot->poll = ED_operator_screenactive_norender;
+ /* api callbacks */
+ ot->invoke = screen_animation_step;
+ ot->poll = ED_operator_screenactive_norender;
}
/** \} */
@@ -4271,93 +4315,93 @@ 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) {
- bScreen *screen = WM_window_get_active_screen(win);
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ bScreen *screen = WM_window_get_active_screen(win);
- if (screen->animtimer || screen->scrubbing) {
- return screen;
- }
- }
+ if (screen->animtimer || screen->scrubbing) {
+ return screen;
+ }
+ }
- return NULL;
+ return NULL;
}
bScreen *ED_screen_animation_no_scrub(const wmWindowManager *wm)
{
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
- bScreen *screen = WM_window_get_active_screen(win);
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ bScreen *screen = WM_window_get_active_screen(win);
- if (screen->animtimer) {
- return screen;
- }
- }
+ if (screen->animtimer) {
+ return screen;
+ }
+ }
- return NULL;
+ return NULL;
}
-
/* toggle operator */
int ED_screen_animation_play(bContext *C, int sync, int mode)
{
- bScreen *screen = CTX_wm_screen(C);
- Scene *scene = CTX_data_scene(C);
+ bScreen *screen = CTX_wm_screen(C);
+ Scene *scene = CTX_data_scene(C);
- if (ED_screen_animation_playing(CTX_wm_manager(C))) {
- /* stop playback now */
- ED_screen_animation_timer(C, 0, 0, 0, 0);
- BKE_sound_stop_scene(scene);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ /* stop playback now */
+ ED_screen_animation_timer(C, 0, 0, 0, 0);
+ BKE_sound_stop_scene(scene);
- 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;
+ 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);
+ if (mode == 1) /* XXX only play audio forwards!? */
+ BKE_sound_play_scene(scene);
- ED_screen_animation_timer(C, screen->redraws_flag, refresh, sync, mode);
+ ED_screen_animation_timer(C, screen->redraws_flag, refresh, sync, mode);
- if (screen->animtimer) {
- wmTimer *wt = screen->animtimer;
- ScreenAnimData *sad = wt->customdata;
+ if (screen->animtimer) {
+ wmTimer *wt = screen->animtimer;
+ ScreenAnimData *sad = wt->customdata;
- sad->ar = CTX_wm_region(C);
- }
- }
+ sad->ar = CTX_wm_region(C);
+ }
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int screen_animation_play_exec(bContext *C, wmOperator *op)
{
- int mode = (RNA_boolean_get(op->ptr, "reverse")) ? -1 : 1;
- int sync = -1;
+ int mode = (RNA_boolean_get(op->ptr, "reverse")) ? -1 : 1;
+ int sync = -1;
- if (RNA_struct_property_is_set(op->ptr, "sync"))
- sync = (RNA_boolean_get(op->ptr, "sync"));
+ if (RNA_struct_property_is_set(op->ptr, "sync"))
+ sync = (RNA_boolean_get(op->ptr, "sync"));
- return ED_screen_animation_play(C, sync, mode);
+ return ED_screen_animation_play(C, sync, mode);
}
static void SCREEN_OT_animation_play(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Play Animation";
- ot->description = "Play animation";
- ot->idname = "SCREEN_OT_animation_play";
+ /* identifiers */
+ ot->name = "Play Animation";
+ ot->description = "Play animation";
+ ot->idname = "SCREEN_OT_animation_play";
- /* api callbacks */
- ot->exec = screen_animation_play_exec;
+ /* api callbacks */
+ ot->exec = screen_animation_play_exec;
- ot->poll = ED_operator_screenactive_norender;
+ ot->poll = ED_operator_screenactive_norender;
- prop = RNA_def_boolean(ot->srna, "reverse", 0, "Play in Reverse", "Animation is played backwards");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "sync", 0, "Sync", "Drop frames to maintain framerate");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(
+ ot->srna, "reverse", 0, "Play in Reverse", "Animation is played backwards");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "sync", 0, "Sync", "Drop frames to maintain framerate");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/** \} */
@@ -4368,41 +4412,45 @@ static void SCREEN_OT_animation_play(wmOperatorType *ot)
static int screen_animation_cancel_exec(bContext *C, wmOperator *op)
{
- bScreen *screen = ED_screen_animation_playing(CTX_wm_manager(C));
+ bScreen *screen = ED_screen_animation_playing(CTX_wm_manager(C));
- if (screen) {
- if (RNA_boolean_get(op->ptr, "restore_frame") && screen->animtimer) {
- ScreenAnimData *sad = screen->animtimer->customdata;
- Scene *scene = CTX_data_scene(C);
+ if (screen) {
+ if (RNA_boolean_get(op->ptr, "restore_frame") && screen->animtimer) {
+ ScreenAnimData *sad = screen->animtimer->customdata;
+ Scene *scene = CTX_data_scene(C);
- /* reset current frame before stopping, and just send a notifier to deal with the rest
- * (since playback still needs to be stopped)
- */
- scene->r.cfra = sad->sfra;
+ /* reset current frame before stopping, and just send a notifier to deal with the rest
+ * (since playback still needs to be stopped)
+ */
+ scene->r.cfra = sad->sfra;
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
- }
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ }
- /* call the other "toggling" operator to clean up now */
- ED_screen_animation_play(C, 0, 0);
- }
+ /* call the other "toggling" operator to clean up now */
+ ED_screen_animation_play(C, 0, 0);
+ }
- return OPERATOR_PASS_THROUGH;
+ return OPERATOR_PASS_THROUGH;
}
static void SCREEN_OT_animation_cancel(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Cancel Animation";
- ot->description = "Cancel animation, returning to the original frame";
- ot->idname = "SCREEN_OT_animation_cancel";
+ /* identifiers */
+ ot->name = "Cancel Animation";
+ ot->description = "Cancel animation, returning to the original frame";
+ ot->idname = "SCREEN_OT_animation_cancel";
- /* api callbacks */
- ot->exec = screen_animation_cancel_exec;
+ /* api callbacks */
+ ot->exec = screen_animation_cancel_exec;
- ot->poll = ED_operator_screenactive;
+ ot->poll = ED_operator_screenactive;
- RNA_def_boolean(ot->srna, "restore_frame", true, "Restore Frame", "Restore the frame when animation was initialized");
+ RNA_def_boolean(ot->srna,
+ "restore_frame",
+ true,
+ "Restore Frame",
+ "Restore the frame when animation was initialized");
}
/** \} */
@@ -4419,48 +4467,48 @@ static void SCREEN_OT_animation_cancel(wmOperatorType *ot)
*
* callbacks:
*
- * exec() has to be filled in by user
+ * exec() has to be filled in by user
*
* invoke() default WM function
* adds modal handler
*
- * modal() default WM function
+ * modal() default WM function
* accept modal events while doing it, calls exec(), handles ESC and border drawing
*
- * poll() has to be filled in by user for context
+ * poll() has to be filled in by user for context
*/
#if 0
static int box_select_exec(bContext *C, wmOperator *op)
{
- int event_type = RNA_int_get(op->ptr, "event_type");
+ int event_type = RNA_int_get(op->ptr, "event_type");
- if (event_type == LEFTMOUSE)
- printf("box select do select\n");
- else if (event_type == RIGHTMOUSE)
- printf("box select deselect\n");
- else
- printf("box select do something\n");
+ if (event_type == LEFTMOUSE)
+ printf("box select do select\n");
+ else if (event_type == RIGHTMOUSE)
+ printf("box select deselect\n");
+ else
+ printf("box select do something\n");
- return 1;
+ return 1;
}
static void SCREEN_OT_box_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Box Select";
- ot->idname = "SCREEN_OT_box_select";
+ /* identifiers */
+ ot->name = "Box Select";
+ ot->idname = "SCREEN_OT_box_select";
- /* api callbacks */
- ot->exec = box_select_exec;
- ot->invoke = WM_gesture_box_invoke;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
+ /* api callbacks */
+ ot->exec = box_select_exec;
+ ot->invoke = WM_gesture_box_invoke;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
- ot->poll = ED_operator_areaactive;
+ ot->poll = ED_operator_areaactive;
- /* rna */
- RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
- WM_operator_properties_border(ot);
+ /* rna */
+ RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+ WM_operator_properties_border(ot);
}
#endif
@@ -4472,36 +4520,36 @@ static void SCREEN_OT_box_select(wmOperatorType *ot)
/* *********************** generic fullscreen 'back' button *************** */
-
static int fullscreen_back_exec(bContext *C, wmOperator *op)
{
- bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = NULL;
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = NULL;
- /* search current screen for 'fullscreen' areas */
- for (sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa->full) break;
- }
- if (!sa) {
- BKE_report(op->reports, RPT_ERROR, "No fullscreen areas were found");
- return OPERATOR_CANCELLED;
- }
+ /* search current screen for 'fullscreen' areas */
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
+ if (sa->full)
+ break;
+ }
+ if (!sa) {
+ 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, sa);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SCREEN_OT_back_to_previous(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Back to Previous Screen";
- ot->description = "Revert back to the original screen layout, before fullscreen area overlay";
- ot->idname = "SCREEN_OT_back_to_previous";
+ /* identifiers */
+ ot->name = "Back to Previous Screen";
+ ot->description = "Revert back to the original screen layout, before fullscreen area overlay";
+ ot->idname = "SCREEN_OT_back_to_previous";
- /* api callbacks */
- ot->exec = fullscreen_back_exec;
- ot->poll = ED_operator_screenactive;
+ /* api callbacks */
+ ot->exec = fullscreen_back_exec;
+ ot->poll = ED_operator_screenactive;
}
/** \} */
@@ -4512,35 +4560,34 @@ static void SCREEN_OT_back_to_previous(struct wmOperatorType *ot)
static int userpref_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- int sizex = (500 + UI_NAVIGATION_REGION_WIDTH) * UI_DPI_FAC;
- int sizey = 520 * UI_DPI_FAC;
+ int sizex = (500 + UI_NAVIGATION_REGION_WIDTH) * UI_DPI_FAC;
+ int sizey = 520 * UI_DPI_FAC;
- /* changes context! */
- if (WM_window_open_temp(C, event->x, event->y, sizex, sizey, WM_WINDOW_USERPREFS) != NULL) {
- /* The header only contains the editor switcher and looks empty.
- * So hiding in the temp window makes sense. */
- ScrArea *area = CTX_wm_area(C);
- ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_HEADER);
- region->flag |= RGN_FLAG_HIDDEN;
- return OPERATOR_FINISHED;
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Failed to open window!");
- return OPERATOR_CANCELLED;
- }
+ /* changes context! */
+ if (WM_window_open_temp(C, event->x, event->y, sizex, sizey, WM_WINDOW_USERPREFS) != NULL) {
+ /* The header only contains the editor switcher and looks empty.
+ * So hiding in the temp window makes sense. */
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_HEADER);
+ region->flag |= RGN_FLAG_HIDDEN;
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Failed to open window!");
+ return OPERATOR_CANCELLED;
+ }
}
-
static void SCREEN_OT_userpref_show(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Show Preferences";
- ot->description = "Edit user preferences and system settings";
- ot->idname = "SCREEN_OT_userpref_show";
+ /* identifiers */
+ ot->name = "Show Preferences";
+ ot->description = "Edit user preferences and system settings";
+ ot->idname = "SCREEN_OT_userpref_show";
- /* api callbacks */
- ot->invoke = userpref_show_invoke;
- ot->poll = ED_operator_screenactive;
+ /* api callbacks */
+ ot->invoke = userpref_show_invoke;
+ ot->poll = ED_operator_screenactive;
}
/** \} */
@@ -4551,64 +4598,61 @@ static void SCREEN_OT_userpref_show(struct wmOperatorType *ot)
static int drivers_editor_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- PointerRNA ptr = {{NULL}};
- PropertyRNA *prop = NULL;
- int index = -1;
- uiBut *but = NULL;
-
- int sizex = 900 * UI_DPI_FAC;
- int sizey = 580 * UI_DPI_FAC;
-
- /* Get active property to show driver for
- * - Need to grab it first, or else this info disappears
- * after we've created the window
- */
- but = UI_context_active_but_prop_get(C, &ptr, &prop, &index);
-
- /* changes context! */
- if (WM_window_open_temp(C, event->x, event->y, sizex, sizey, WM_WINDOW_DRIVERS) != NULL) {
- /* activate driver F-Curve for the property under the cursor */
- if (but) {
- FCurve *fcu;
- bool driven, special;
-
- fcu = rna_get_fcurve_context_ui(C,
- &ptr, prop, index,
- NULL, NULL, &driven, &special);
- if (fcu) {
- /* Isolate this F-Curve... */
- bAnimContext ac;
- if (ANIM_animdata_get_context(C, &ac)) {
- int filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS;
- ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, 0, ACHANNEL_SETFLAG_CLEAR);
- ANIM_set_active_channel(&ac, ac.data, ac.datatype, filter, fcu, ANIMTYPE_FCURVE);
- }
- else {
- /* Just blindly isolate... This isn't the best, and shouldn't happen, but may be enough... */
- fcu->flag |= (FCURVE_ACTIVE | FCURVE_SELECTED);
- }
- }
- }
-
- return OPERATOR_FINISHED;
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Failed to open window!");
- return OPERATOR_CANCELLED;
- }
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop = NULL;
+ int index = -1;
+ uiBut *but = NULL;
+
+ int sizex = 900 * UI_DPI_FAC;
+ int sizey = 580 * UI_DPI_FAC;
+
+ /* Get active property to show driver for
+ * - Need to grab it first, or else this info disappears
+ * after we've created the window
+ */
+ but = UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ /* changes context! */
+ if (WM_window_open_temp(C, event->x, event->y, sizex, sizey, WM_WINDOW_DRIVERS) != NULL) {
+ /* activate driver F-Curve for the property under the cursor */
+ if (but) {
+ FCurve *fcu;
+ bool driven, special;
+
+ fcu = rna_get_fcurve_context_ui(C, &ptr, prop, index, NULL, NULL, &driven, &special);
+ if (fcu) {
+ /* Isolate this F-Curve... */
+ bAnimContext ac;
+ if (ANIM_animdata_get_context(C, &ac)) {
+ int filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS;
+ ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ ANIM_set_active_channel(&ac, ac.data, ac.datatype, filter, fcu, ANIMTYPE_FCURVE);
+ }
+ else {
+ /* Just blindly isolate... This isn't the best, and shouldn't happen, but may be enough... */
+ fcu->flag |= (FCURVE_ACTIVE | FCURVE_SELECTED);
+ }
+ }
+ }
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Failed to open window!");
+ return OPERATOR_CANCELLED;
+ }
}
-
static void SCREEN_OT_drivers_editor_show(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Show Drivers Editor";
- ot->description = "Show drivers editor in a separate window";
- ot->idname = "SCREEN_OT_drivers_editor_show";
+ /* identifiers */
+ ot->name = "Show Drivers Editor";
+ ot->description = "Show drivers editor in a separate window";
+ ot->idname = "SCREEN_OT_drivers_editor_show";
- /* api callbacks */
- ot->invoke = drivers_editor_show_invoke;
- ot->poll = ED_operator_screenactive;
+ /* api callbacks */
+ ot->invoke = drivers_editor_show_invoke;
+ ot->poll = ED_operator_screenactive;
}
/** \} */
@@ -4619,28 +4663,28 @@ static void SCREEN_OT_drivers_editor_show(struct wmOperatorType *ot)
static int screen_new_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- wmWindow *win = CTX_wm_window(C);
- WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
- WorkSpaceLayout *layout_old = BKE_workspace_active_layout_get(win->workspace_hook);
- WorkSpaceLayout *layout_new;
+ Main *bmain = CTX_data_main(C);
+ wmWindow *win = CTX_wm_window(C);
+ WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
+ WorkSpaceLayout *layout_old = BKE_workspace_active_layout_get(win->workspace_hook);
+ WorkSpaceLayout *layout_new;
- layout_new = ED_workspace_layout_duplicate(bmain, workspace, layout_old, win);
- WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTBROWSE, layout_new);
+ layout_new = ED_workspace_layout_duplicate(bmain, workspace, layout_old, win);
+ WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTBROWSE, layout_new);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SCREEN_OT_new(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "New Screen";
- ot->description = "Add a new screen";
- ot->idname = "SCREEN_OT_new";
+ /* identifiers */
+ ot->name = "New Screen";
+ ot->description = "Add a new screen";
+ ot->idname = "SCREEN_OT_new";
- /* api callbacks */
- ot->exec = screen_new_exec;
- ot->poll = WM_operator_winactive;
+ /* api callbacks */
+ ot->exec = screen_new_exec;
+ ot->poll = WM_operator_winactive;
}
/** \} */
@@ -4651,24 +4695,24 @@ static void SCREEN_OT_new(wmOperatorType *ot)
static int screen_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- bScreen *sc = CTX_wm_screen(C);
- WorkSpace *workspace = CTX_wm_workspace(C);
- WorkSpaceLayout *layout = BKE_workspace_layout_find(workspace, sc);
+ bScreen *sc = CTX_wm_screen(C);
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ WorkSpaceLayout *layout = BKE_workspace_layout_find(workspace, sc);
- WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTDELETE, layout);
+ WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTDELETE, layout);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SCREEN_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Screen";
- ot->description = "Delete active screen";
- ot->idname = "SCREEN_OT_delete";
+ /* identifiers */
+ ot->name = "Delete Screen";
+ ot->description = "Delete active screen";
+ ot->idname = "SCREEN_OT_delete";
- /* api callbacks */
- ot->exec = screen_delete_exec;
+ /* api callbacks */
+ ot->exec = screen_delete_exec;
}
/** \} */
@@ -4682,288 +4726,289 @@ static void SCREEN_OT_delete(wmOperatorType *ot)
* This because flag RGN_HIDDEN is set in end - region doesn't draw at all then */
typedef struct RegionAlphaInfo {
- ScrArea *sa;
- ARegion *ar, *child_ar; /* other region */
- int hidden;
+ ScrArea *sa;
+ ARegion *ar, *child_ar; /* other region */
+ int hidden;
} RegionAlphaInfo;
-#define TIMEOUT 0.1f
-#define TIMESTEP (1.0f / 60.0f)
+#define TIMEOUT 0.1f
+#define TIMESTEP (1.0f / 60.0f)
float ED_region_blend_alpha(ARegion *ar)
{
- /* check parent too */
- if (ar->regiontimer == NULL && (ar->alignment & RGN_SPLIT_PREV) && ar->prev) {
- ar = ar->prev;
- }
+ /* check parent too */
+ if (ar->regiontimer == NULL && (ar->alignment & RGN_SPLIT_PREV) && ar->prev) {
+ ar = ar->prev;
+ }
- if (ar->regiontimer) {
- RegionAlphaInfo *rgi = ar->regiontimer->customdata;
- float alpha;
+ if (ar->regiontimer) {
+ RegionAlphaInfo *rgi = ar->regiontimer->customdata;
+ float alpha;
- alpha = (float)ar->regiontimer->duration / TIMEOUT;
- /* makes sure the blend out works 100% - without area redraws */
- if (rgi->hidden) alpha = 0.9f - TIMESTEP - alpha;
+ alpha = (float)ar->regiontimer->duration / TIMEOUT;
+ /* makes sure the blend out works 100% - without area redraws */
+ if (rgi->hidden)
+ alpha = 0.9f - TIMESTEP - alpha;
- CLAMP(alpha, 0.0f, 1.0f);
- return alpha;
- }
- return 1.0f;
+ CLAMP(alpha, 0.0f, 1.0f);
+ return alpha;
+ }
+ return 1.0f;
}
/* assumes region has running region-blend timer */
static void region_blend_end(bContext *C, ARegion *ar, const bool is_running)
{
- RegionAlphaInfo *rgi = ar->regiontimer->customdata;
-
- /* always send redraw */
- ED_region_tag_redraw(ar);
- if (rgi->child_ar)
- ED_region_tag_redraw(rgi->child_ar);
-
- /* if running timer was hiding, the flag toggle went wrong */
- if (is_running) {
- if (rgi->hidden)
- rgi->ar->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);
- }
- /* area decoration needs redraw in end */
- ED_area_tag_redraw(rgi->sa);
- }
- WM_event_remove_timer(CTX_wm_manager(C), NULL, ar->regiontimer); /* frees rgi */
- ar->regiontimer = NULL;
-
+ RegionAlphaInfo *rgi = ar->regiontimer->customdata;
+
+ /* always send redraw */
+ ED_region_tag_redraw(ar);
+ if (rgi->child_ar)
+ ED_region_tag_redraw(rgi->child_ar);
+
+ /* if running timer was hiding, the flag toggle went wrong */
+ if (is_running) {
+ if (rgi->hidden)
+ rgi->ar->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);
+ }
+ /* area decoration needs redraw in end */
+ ED_area_tag_redraw(rgi->sa);
+ }
+ WM_event_remove_timer(CTX_wm_manager(C), NULL, ar->regiontimer); /* frees rgi */
+ ar->regiontimer = NULL;
}
/* assumes that *ar itself is not a splitted version from previous region */
void region_blend_start(bContext *C, ScrArea *sa, ARegion *ar)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
- RegionAlphaInfo *rgi;
-
- /* end running timer */
- if (ar->regiontimer) {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+ RegionAlphaInfo *rgi;
- region_blend_end(C, ar, true);
- }
- rgi = MEM_callocN(sizeof(RegionAlphaInfo), "RegionAlphaInfo");
+ /* end running timer */
+ if (ar->regiontimer) {
- rgi->hidden = ar->flag & RGN_FLAG_HIDDEN;
- rgi->sa = sa;
- rgi->ar = ar;
- ar->flag &= ~RGN_FLAG_HIDDEN;
+ region_blend_end(C, ar, true);
+ }
+ rgi = MEM_callocN(sizeof(RegionAlphaInfo), "RegionAlphaInfo");
- /* blend in, reinitialize regions because it got unhidden */
- if (rgi->hidden == 0)
- ED_area_initialize(wm, win, sa);
- else
- WM_event_remove_handlers(C, &ar->handlers);
+ rgi->hidden = ar->flag & RGN_FLAG_HIDDEN;
+ rgi->sa = sa;
+ rgi->ar = ar;
+ ar->flag &= ~RGN_FLAG_HIDDEN;
- if (ar->next) {
- if (ar->next->alignment & RGN_SPLIT_PREV) {
- rgi->child_ar = ar->next;
- }
- }
+ /* blend in, reinitialize regions because it got unhidden */
+ if (rgi->hidden == 0)
+ ED_area_initialize(wm, win, sa);
+ else
+ WM_event_remove_handlers(C, &ar->handlers);
- /* new timer */
- ar->regiontimer = WM_event_add_timer(wm, win, TIMERREGION, TIMESTEP);
- ar->regiontimer->customdata = rgi;
+ if (ar->next) {
+ if (ar->next->alignment & RGN_SPLIT_PREV) {
+ rgi->child_ar = ar->next;
+ }
+ }
+ /* new timer */
+ ar->regiontimer = WM_event_add_timer(wm, win, TIMERREGION, TIMESTEP);
+ ar->regiontimer->customdata = rgi;
}
/* timer runs in win->handlers, so it cannot use context to find area/region */
static int region_blend_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- RegionAlphaInfo *rgi;
- wmTimer *timer = event->customdata;
+ RegionAlphaInfo *rgi;
+ wmTimer *timer = event->customdata;
- /* event type is TIMERREGION, but we better check */
- if (event->type != TIMERREGION || timer == NULL)
- return OPERATOR_PASS_THROUGH;
+ /* event type is TIMERREGION, but we better check */
+ if (event->type != TIMERREGION || timer == NULL)
+ return OPERATOR_PASS_THROUGH;
- rgi = timer->customdata;
+ rgi = timer->customdata;
- /* always send redraws */
- ED_region_tag_redraw(rgi->ar);
- if (rgi->child_ar)
- ED_region_tag_redraw(rgi->child_ar);
+ /* always send redraws */
+ ED_region_tag_redraw(rgi->ar);
+ if (rgi->child_ar)
+ ED_region_tag_redraw(rgi->child_ar);
- /* end timer? */
- if (rgi->ar->regiontimer->duration > (double)TIMEOUT) {
- region_blend_end(C, rgi->ar, false);
- return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
- }
+ /* end timer? */
+ if (rgi->ar->regiontimer->duration > (double)TIMEOUT) {
+ region_blend_end(C, rgi->ar, false);
+ return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
+ }
- return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
+ return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
}
static void SCREEN_OT_region_blend(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Region Alpha";
- ot->idname = "SCREEN_OT_region_blend";
- ot->description = "Blend in and out overlapping region";
+ /* identifiers */
+ ot->name = "Region Alpha";
+ ot->idname = "SCREEN_OT_region_blend";
+ ot->description = "Blend in and out overlapping region";
- /* api callbacks */
- ot->invoke = region_blend_invoke;
+ /* api callbacks */
+ ot->invoke = region_blend_invoke;
- /* flags */
- ot->flag = OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_INTERNAL;
- /* properties */
+ /* properties */
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Space Type Set or Cycle Operator
* \{ */
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 *sa = CTX_wm_area(C);
+ return (sa && !ELEM(sa->spacetype, SPACE_TOPBAR, SPACE_STATUSBAR));
}
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);
- 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) {
- /* Set the type. */
- RNA_property_enum_set(&ptr, prop_type, space_type);
- RNA_property_update(C, &ptr, prop_type);
- }
- else {
- /* Types match, cycle the subtype. */
- const int space_type_ui = RNA_property_enum_get(&ptr, prop_ui_type);
- const EnumPropertyItem *item;
- int item_len;
- bool free;
- RNA_property_enum_items(C, &ptr, prop_ui_type, &item, &item_len, &free);
- int index = RNA_enum_from_value(item, space_type_ui);
- for (int i = 1; i < item_len; i++) {
- const EnumPropertyItem *item_test = &item[(index + i) % item_len];
- if ((item_test->value >> 16) == space_type) {
- RNA_property_enum_set(&ptr, prop_ui_type, item_test->value);
- RNA_property_update(C, &ptr, prop_ui_type);
- break;
- }
- }
- if (free) {
- MEM_freeN((void *)item);
- }
- }
-
- return OPERATOR_FINISHED;
+ 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);
+ 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) {
+ /* Set the type. */
+ RNA_property_enum_set(&ptr, prop_type, space_type);
+ RNA_property_update(C, &ptr, prop_type);
+ }
+ else {
+ /* Types match, cycle the subtype. */
+ const int space_type_ui = RNA_property_enum_get(&ptr, prop_ui_type);
+ const EnumPropertyItem *item;
+ int item_len;
+ bool free;
+ RNA_property_enum_items(C, &ptr, prop_ui_type, &item, &item_len, &free);
+ int index = RNA_enum_from_value(item, space_type_ui);
+ for (int i = 1; i < item_len; i++) {
+ const EnumPropertyItem *item_test = &item[(index + i) % item_len];
+ if ((item_test->value >> 16) == space_type) {
+ RNA_property_enum_set(&ptr, prop_ui_type, item_test->value);
+ RNA_property_update(C, &ptr, prop_ui_type);
+ break;
+ }
+ }
+ if (free) {
+ MEM_freeN((void *)item);
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
static void SCREEN_OT_space_type_set_or_cycle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Cycle Space Type Set";
- ot->description = "Set the space type or cycle sub-type";
- ot->idname = "SCREEN_OT_space_type_set_or_cycle";
+ /* identifiers */
+ ot->name = "Cycle Space Type Set";
+ ot->description = "Set the space type or cycle sub-type";
+ ot->idname = "SCREEN_OT_space_type_set_or_cycle";
- /* api callbacks */
- ot->exec = space_type_set_or_cycle_exec;
- ot->poll = space_type_set_or_cycle_poll;
+ /* api callbacks */
+ ot->exec = space_type_set_or_cycle_exec;
+ ot->poll = space_type_set_or_cycle_poll;
- ot->flag = 0;
+ ot->flag = 0;
- RNA_def_enum(ot->srna, "space_type", rna_enum_space_type_items, SPACE_EMPTY, "Type", "");
+ RNA_def_enum(ot->srna, "space_type", rna_enum_space_type_items, SPACE_EMPTY, "Type", "");
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Space Context Cycle Operator
* \{ */
static const EnumPropertyItem space_context_cycle_direction[] = {
- {SPACE_CONTEXT_CYCLE_PREV, "PREV", 0, "Previous", ""},
- {SPACE_CONTEXT_CYCLE_NEXT, "NEXT", 0, "Next", ""},
- {0, NULL, 0, NULL, NULL},
+ {SPACE_CONTEXT_CYCLE_PREV, "PREV", 0, "Previous", ""},
+ {SPACE_CONTEXT_CYCLE_NEXT, "NEXT", 0, "Next", ""},
+ {0, NULL, 0, NULL, NULL},
};
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 *sa = CTX_wm_area(C);
+ /* sa might be NULL if called out of window bounds */
+ return (sa && ELEM(sa->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.
*/
-static void context_cycle_prop_get(
- bScreen *screen, const ScrArea *sa,
- PointerRNA *r_ptr, PropertyRNA **r_prop)
-{
- const char *propname;
-
- switch (sa->spacetype) {
- case SPACE_PROPERTIES:
- RNA_pointer_create(&screen->id, &RNA_SpaceProperties, sa->spacedata.first, r_ptr);
- propname = "context";
- break;
- case SPACE_USERPREF:
- RNA_pointer_create(NULL, &RNA_Preferences, &U, r_ptr);
- propname = "active_section";
- break;
- default:
- BLI_assert(0);
- propname = "";
- }
-
- *r_prop = RNA_struct_find_property(r_ptr, propname);
+static void context_cycle_prop_get(bScreen *screen,
+ const ScrArea *sa,
+ PointerRNA *r_ptr,
+ PropertyRNA **r_prop)
+{
+ const char *propname;
+
+ switch (sa->spacetype) {
+ case SPACE_PROPERTIES:
+ RNA_pointer_create(&screen->id, &RNA_SpaceProperties, sa->spacedata.first, r_ptr);
+ propname = "context";
+ break;
+ case SPACE_USERPREF:
+ RNA_pointer_create(NULL, &RNA_Preferences, &U, r_ptr);
+ propname = "active_section";
+ break;
+ default:
+ BLI_assert(0);
+ propname = "";
+ }
+
+ *r_prop = RNA_struct_find_property(r_ptr, propname);
}
static int space_context_cycle_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- const int direction = RNA_enum_get(op->ptr, "direction");
+ const int direction = RNA_enum_get(op->ptr, "direction");
- PointerRNA ptr;
- PropertyRNA *prop;
- context_cycle_prop_get(CTX_wm_screen(C), CTX_wm_area(C), &ptr, &prop);
- const int old_context = RNA_property_enum_get(&ptr, prop);
- const int new_context = RNA_property_enum_step(
- C, &ptr, prop, old_context,
- direction == SPACE_CONTEXT_CYCLE_PREV ? -1 : 1);
- RNA_property_enum_set(&ptr, prop, new_context);
- RNA_property_update(C, &ptr, prop);
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ context_cycle_prop_get(CTX_wm_screen(C), CTX_wm_area(C), &ptr, &prop);
+ const int old_context = RNA_property_enum_get(&ptr, prop);
+ const int new_context = RNA_property_enum_step(
+ C, &ptr, prop, old_context, direction == SPACE_CONTEXT_CYCLE_PREV ? -1 : 1);
+ RNA_property_enum_set(&ptr, prop, new_context);
+ RNA_property_update(C, &ptr, prop);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SCREEN_OT_space_context_cycle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Cycle Space Context";
- ot->description = "Cycle through the editor context by activating the next/previous one";
- ot->idname = "SCREEN_OT_space_context_cycle";
+ /* identifiers */
+ ot->name = "Cycle Space Context";
+ ot->description = "Cycle through the editor context by activating the next/previous one";
+ ot->idname = "SCREEN_OT_space_context_cycle";
- /* api callbacks */
- ot->invoke = space_context_cycle_invoke;
- ot->poll = space_context_cycle_poll;
+ /* api callbacks */
+ ot->invoke = space_context_cycle_invoke;
+ ot->poll = space_context_cycle_poll;
- ot->flag = 0;
+ ot->flag = 0;
- RNA_def_enum(ot->srna, "direction", space_context_cycle_direction, SPACE_CONTEXT_CYCLE_NEXT, "Direction",
- "Direction to cycle through");
+ RNA_def_enum(ot->srna,
+ "direction",
+ space_context_cycle_direction,
+ SPACE_CONTEXT_CYCLE_NEXT,
+ "Direction",
+ "Direction to cycle through");
}
/** \} */
@@ -4974,63 +5019,67 @@ static void SCREEN_OT_space_context_cycle(wmOperatorType *ot)
static int space_workspace_cycle_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- wmWindow *win = CTX_wm_window(C);
- if (WM_window_is_temp_screen(win)) {
- return OPERATOR_CANCELLED;
- }
+ wmWindow *win = CTX_wm_window(C);
+ if (WM_window_is_temp_screen(win)) {
+ return OPERATOR_CANCELLED;
+ }
- Main *bmain = CTX_data_main(C);
- const int direction = RNA_enum_get(op->ptr, "direction");
- WorkSpace *workspace_src = WM_window_get_active_workspace(win);
- WorkSpace *workspace_dst = NULL;
+ Main *bmain = CTX_data_main(C);
+ const int direction = RNA_enum_get(op->ptr, "direction");
+ WorkSpace *workspace_src = WM_window_get_active_workspace(win);
+ WorkSpace *workspace_dst = NULL;
- ListBase ordered;
- BKE_id_ordered_list(&ordered, &bmain->workspaces);
+ ListBase ordered;
+ BKE_id_ordered_list(&ordered, &bmain->workspaces);
- for (LinkData *link = ordered.first; link; link = link->next) {
- if (link->data == workspace_src) {
- if (direction == SPACE_CONTEXT_CYCLE_PREV) {
- workspace_dst = (link->prev) ? link->prev->data : NULL;
- }
- else {
- workspace_dst = (link->next) ? link->next->data : NULL;
- }
- }
- }
+ for (LinkData *link = ordered.first; link; link = link->next) {
+ if (link->data == workspace_src) {
+ if (direction == SPACE_CONTEXT_CYCLE_PREV) {
+ workspace_dst = (link->prev) ? link->prev->data : NULL;
+ }
+ else {
+ workspace_dst = (link->next) ? link->next->data : NULL;
+ }
+ }
+ }
- if (workspace_dst == NULL) {
- LinkData *link = (direction == SPACE_CONTEXT_CYCLE_PREV) ? ordered.last : ordered.first;
- workspace_dst = link->data;
- }
+ if (workspace_dst == NULL) {
+ LinkData *link = (direction == SPACE_CONTEXT_CYCLE_PREV) ? ordered.last : ordered.first;
+ workspace_dst = link->data;
+ }
- BLI_freelistN(&ordered);
+ BLI_freelistN(&ordered);
- if (workspace_src == workspace_dst) {
- return OPERATOR_CANCELLED;
- }
+ if (workspace_src == workspace_dst) {
+ return OPERATOR_CANCELLED;
+ }
- win->workspace_hook->temp_workspace_store = workspace_dst;
- WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, workspace_dst);
- win->workspace_hook->temp_workspace_store = NULL;
+ win->workspace_hook->temp_workspace_store = workspace_dst;
+ WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, workspace_dst);
+ win->workspace_hook->temp_workspace_store = NULL;
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SCREEN_OT_workspace_cycle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Cycle Workspace";
- ot->description = "Cycle through workspaces";
- ot->idname = "SCREEN_OT_workspace_cycle";
+ /* identifiers */
+ ot->name = "Cycle Workspace";
+ ot->description = "Cycle through workspaces";
+ ot->idname = "SCREEN_OT_workspace_cycle";
- /* api callbacks */
- ot->invoke = space_workspace_cycle_invoke;
- ot->poll = ED_operator_screenactive;
+ /* api callbacks */
+ ot->invoke = space_workspace_cycle_invoke;
+ ot->poll = ED_operator_screenactive;
- ot->flag = 0;
+ ot->flag = 0;
- RNA_def_enum(ot->srna, "direction", space_context_cycle_direction, SPACE_CONTEXT_CYCLE_NEXT, "Direction",
- "Direction to cycle through");
+ RNA_def_enum(ot->srna,
+ "direction",
+ space_context_cycle_direction,
+ SPACE_CONTEXT_CYCLE_NEXT,
+ "Direction",
+ "Direction to cycle through");
}
/** \} */
@@ -5042,62 +5091,61 @@ static void SCREEN_OT_workspace_cycle(wmOperatorType *ot)
/* called in spacetypes.c */
void ED_operatortypes_screen(void)
{
- /* generic UI stuff */
- WM_operatortype_append(SCREEN_OT_actionzone);
- WM_operatortype_append(SCREEN_OT_repeat_last);
- WM_operatortype_append(SCREEN_OT_repeat_history);
- WM_operatortype_append(SCREEN_OT_redo_last);
-
- /* screen tools */
- WM_operatortype_append(SCREEN_OT_area_move);
- WM_operatortype_append(SCREEN_OT_area_split);
- WM_operatortype_append(SCREEN_OT_area_join);
- WM_operatortype_append(SCREEN_OT_area_options);
- WM_operatortype_append(SCREEN_OT_area_dupli);
- WM_operatortype_append(SCREEN_OT_area_swap);
- WM_operatortype_append(SCREEN_OT_region_quadview);
- WM_operatortype_append(SCREEN_OT_region_scale);
- WM_operatortype_append(SCREEN_OT_region_flip);
- WM_operatortype_append(SCREEN_OT_header);
- WM_operatortype_append(SCREEN_OT_header_toggle_menus);
- WM_operatortype_append(SCREEN_OT_header_context_menu);
- WM_operatortype_append(SCREEN_OT_footer);
- WM_operatortype_append(SCREEN_OT_footer_context_menu);
- WM_operatortype_append(SCREEN_OT_screen_set);
- WM_operatortype_append(SCREEN_OT_screen_full_area);
- WM_operatortype_append(SCREEN_OT_back_to_previous);
- WM_operatortype_append(SCREEN_OT_spacedata_cleanup);
- WM_operatortype_append(SCREEN_OT_screenshot);
- WM_operatortype_append(SCREEN_OT_userpref_show);
- WM_operatortype_append(SCREEN_OT_drivers_editor_show);
- WM_operatortype_append(SCREEN_OT_region_blend);
- WM_operatortype_append(SCREEN_OT_space_type_set_or_cycle);
- WM_operatortype_append(SCREEN_OT_space_context_cycle);
- WM_operatortype_append(SCREEN_OT_workspace_cycle);
-
- /*frame changes*/
- WM_operatortype_append(SCREEN_OT_frame_offset);
- WM_operatortype_append(SCREEN_OT_frame_jump);
- WM_operatortype_append(SCREEN_OT_keyframe_jump);
- WM_operatortype_append(SCREEN_OT_marker_jump);
-
- WM_operatortype_append(SCREEN_OT_animation_step);
- WM_operatortype_append(SCREEN_OT_animation_play);
- WM_operatortype_append(SCREEN_OT_animation_cancel);
-
- /* new/delete */
- WM_operatortype_append(SCREEN_OT_new);
- WM_operatortype_append(SCREEN_OT_delete);
-
- /* tools shared by more space types */
- WM_operatortype_append(ED_OT_undo);
- WM_operatortype_append(ED_OT_undo_push);
- WM_operatortype_append(ED_OT_redo);
- WM_operatortype_append(ED_OT_undo_redo);
- WM_operatortype_append(ED_OT_undo_history);
-
- WM_operatortype_append(ED_OT_flush_edits);
-
+ /* generic UI stuff */
+ WM_operatortype_append(SCREEN_OT_actionzone);
+ WM_operatortype_append(SCREEN_OT_repeat_last);
+ WM_operatortype_append(SCREEN_OT_repeat_history);
+ WM_operatortype_append(SCREEN_OT_redo_last);
+
+ /* screen tools */
+ WM_operatortype_append(SCREEN_OT_area_move);
+ WM_operatortype_append(SCREEN_OT_area_split);
+ WM_operatortype_append(SCREEN_OT_area_join);
+ WM_operatortype_append(SCREEN_OT_area_options);
+ WM_operatortype_append(SCREEN_OT_area_dupli);
+ WM_operatortype_append(SCREEN_OT_area_swap);
+ WM_operatortype_append(SCREEN_OT_region_quadview);
+ WM_operatortype_append(SCREEN_OT_region_scale);
+ WM_operatortype_append(SCREEN_OT_region_flip);
+ WM_operatortype_append(SCREEN_OT_header);
+ WM_operatortype_append(SCREEN_OT_header_toggle_menus);
+ WM_operatortype_append(SCREEN_OT_header_context_menu);
+ WM_operatortype_append(SCREEN_OT_footer);
+ WM_operatortype_append(SCREEN_OT_footer_context_menu);
+ WM_operatortype_append(SCREEN_OT_screen_set);
+ WM_operatortype_append(SCREEN_OT_screen_full_area);
+ WM_operatortype_append(SCREEN_OT_back_to_previous);
+ WM_operatortype_append(SCREEN_OT_spacedata_cleanup);
+ WM_operatortype_append(SCREEN_OT_screenshot);
+ WM_operatortype_append(SCREEN_OT_userpref_show);
+ WM_operatortype_append(SCREEN_OT_drivers_editor_show);
+ WM_operatortype_append(SCREEN_OT_region_blend);
+ WM_operatortype_append(SCREEN_OT_space_type_set_or_cycle);
+ WM_operatortype_append(SCREEN_OT_space_context_cycle);
+ WM_operatortype_append(SCREEN_OT_workspace_cycle);
+
+ /*frame changes*/
+ WM_operatortype_append(SCREEN_OT_frame_offset);
+ WM_operatortype_append(SCREEN_OT_frame_jump);
+ WM_operatortype_append(SCREEN_OT_keyframe_jump);
+ WM_operatortype_append(SCREEN_OT_marker_jump);
+
+ WM_operatortype_append(SCREEN_OT_animation_step);
+ WM_operatortype_append(SCREEN_OT_animation_play);
+ WM_operatortype_append(SCREEN_OT_animation_cancel);
+
+ /* new/delete */
+ WM_operatortype_append(SCREEN_OT_new);
+ WM_operatortype_append(SCREEN_OT_delete);
+
+ /* tools shared by more space types */
+ WM_operatortype_append(ED_OT_undo);
+ WM_operatortype_append(ED_OT_undo_push);
+ WM_operatortype_append(ED_OT_redo);
+ WM_operatortype_append(ED_OT_undo_redo);
+ WM_operatortype_append(ED_OT_undo_history);
+
+ WM_operatortype_append(ED_OT_flush_edits);
}
/** \} */
@@ -5108,62 +5156,63 @@ void ED_operatortypes_screen(void)
static void keymap_modal_set(wmKeyConfig *keyconf)
{
- static const EnumPropertyItem modal_items[] = {
- {KM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
- {KM_MODAL_APPLY, "APPLY", 0, "Apply", ""},
- {KM_MODAL_SNAP_ON, "SNAP", 0, "Snap on", ""},
- {KM_MODAL_SNAP_OFF, "SNAP_OFF", 0, "Snap off", ""},
- {0, NULL, 0, NULL, NULL},
- };
- wmKeyMap *keymap;
+ static const EnumPropertyItem modal_items[] = {
+ {KM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
+ {KM_MODAL_APPLY, "APPLY", 0, "Apply", ""},
+ {KM_MODAL_SNAP_ON, "SNAP", 0, "Snap on", ""},
+ {KM_MODAL_SNAP_OFF, "SNAP_OFF", 0, "Snap off", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+ wmKeyMap *keymap;
- /* Standard Modal keymap ------------------------------------------------ */
- keymap = WM_modalkeymap_add(keyconf, "Standard Modal Map", modal_items);
-
- WM_modalkeymap_assign(keymap, "SCREEN_OT_area_move");
+ /* Standard Modal keymap ------------------------------------------------ */
+ keymap = WM_modalkeymap_add(keyconf, "Standard Modal Map", modal_items);
+ WM_modalkeymap_assign(keymap, "SCREEN_OT_area_move");
}
-static bool blend_file_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
+static bool blend_file_drop_poll(bContext *UNUSED(C),
+ wmDrag *drag,
+ const wmEvent *UNUSED(event),
+ const char **UNUSED(tooltip))
{
- if (drag->type == WM_DRAG_PATH) {
- if (drag->icon == ICON_FILE_BLEND)
- return 1;
- }
- return 0;
+ if (drag->type == WM_DRAG_PATH) {
+ if (drag->icon == ICON_FILE_BLEND)
+ return 1;
+ }
+ return 0;
}
static void blend_file_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- /* copy drag path to properties */
- RNA_string_set(drop->ptr, "filepath", drag->path);
+ /* copy drag path to properties */
+ RNA_string_set(drop->ptr, "filepath", drag->path);
}
-
/* called in spacetypes.c */
void ED_keymap_screen(wmKeyConfig *keyconf)
{
- ListBase *lb;
+ ListBase *lb;
- /* Screen Editing ------------------------------------------------ */
- WM_keymap_ensure(keyconf, "Screen Editing", 0, 0);
+ /* Screen Editing ------------------------------------------------ */
+ WM_keymap_ensure(keyconf, "Screen Editing", 0, 0);
- /* Header Editing ------------------------------------------------ */
- /* note: this is only used when the cursor is inside the header */
- WM_keymap_ensure(keyconf, "Header", 0, 0);
+ /* Header Editing ------------------------------------------------ */
+ /* note: this is only used when the cursor is inside the header */
+ WM_keymap_ensure(keyconf, "Header", 0, 0);
- /* Screen General ------------------------------------------------ */
- WM_keymap_ensure(keyconf, "Screen", 0, 0);
+ /* Screen General ------------------------------------------------ */
+ WM_keymap_ensure(keyconf, "Screen", 0, 0);
- /* Anim Playback ------------------------------------------------ */
- WM_keymap_ensure(keyconf, "Frames", 0, 0);
+ /* Anim Playback ------------------------------------------------ */
+ WM_keymap_ensure(keyconf, "Frames", 0, 0);
- /* dropbox for entire window */
- lb = WM_dropboxmap_find("Window", 0, 0);
- WM_dropbox_add(lb, "WM_OT_drop_blend_file", blend_file_drop_poll, blend_file_drop_copy);
- WM_dropbox_add(lb, "UI_OT_drop_color", UI_drop_color_poll, UI_drop_color_copy);
+ /* dropbox for entire window */
+ lb = WM_dropboxmap_find("Window", 0, 0);
+ WM_dropbox_add(lb, "WM_OT_drop_blend_file", blend_file_drop_poll, blend_file_drop_copy);
+ WM_dropbox_add(lb, "UI_OT_drop_color", UI_drop_color_poll, UI_drop_color_copy);
- keymap_modal_set(keyconf);
+ keymap_modal_set(keyconf);
}
/** \} */
diff --git a/source/blender/editors/screen/screen_user_menu.c b/source/blender/editors/screen/screen_user_menu.c
index 4b8f210f1d9..0ec989db12b 100644
--- a/source/blender/editors/screen/screen_user_menu.c
+++ b/source/blender/editors/screen/screen_user_menu.c
@@ -57,29 +57,33 @@
bUserMenu **ED_screen_user_menus_find(const bContext *C, uint *r_len)
{
- SpaceLink *sl = CTX_wm_space_data(C);
- const char *context = CTX_data_mode_string(C);
-
- if (sl == NULL) {
- *r_len = 0;
- return NULL;
- }
-
- uint array_len = 3;
- bUserMenu **um_array = MEM_calloc_arrayN(array_len, sizeof(*um_array), __func__);
- um_array[0] = BKE_blender_user_menu_find(&U.user_menus, sl->spacetype, context);
- um_array[1] = (sl->spacetype != SPACE_TOPBAR) ? BKE_blender_user_menu_find(&U.user_menus, SPACE_TOPBAR, context) : NULL;
- um_array[2] = (sl->spacetype == SPACE_VIEW3D) ? BKE_blender_user_menu_find(&U.user_menus, SPACE_PROPERTIES, context) : NULL;
-
- *r_len = array_len;
- return um_array;
+ SpaceLink *sl = CTX_wm_space_data(C);
+ const char *context = CTX_data_mode_string(C);
+
+ if (sl == NULL) {
+ *r_len = 0;
+ return NULL;
+ }
+
+ uint array_len = 3;
+ bUserMenu **um_array = MEM_calloc_arrayN(array_len, sizeof(*um_array), __func__);
+ um_array[0] = BKE_blender_user_menu_find(&U.user_menus, sl->spacetype, context);
+ um_array[1] = (sl->spacetype != SPACE_TOPBAR) ?
+ BKE_blender_user_menu_find(&U.user_menus, SPACE_TOPBAR, context) :
+ NULL;
+ um_array[2] = (sl->spacetype == SPACE_VIEW3D) ?
+ BKE_blender_user_menu_find(&U.user_menus, SPACE_PROPERTIES, context) :
+ NULL;
+
+ *r_len = array_len;
+ return um_array;
}
bUserMenu *ED_screen_user_menu_ensure(bContext *C)
{
- SpaceLink *sl = CTX_wm_space_data(C);
- const char *context = CTX_data_mode_string(C);
- return BKE_blender_user_menu_ensure(&U.user_menus, sl->spacetype, context);
+ SpaceLink *sl = CTX_wm_space_data(C);
+ const char *context = CTX_data_mode_string(C);
+ return BKE_blender_user_menu_ensure(&U.user_menus, sl->spacetype, context);
}
/** \} */
@@ -88,96 +92,98 @@ bUserMenu *ED_screen_user_menu_ensure(bContext *C)
/** \name Menu Item
* \{ */
-bUserMenuItem_Op *ED_screen_user_menu_item_find_operator(
- ListBase *lb,
- const wmOperatorType *ot, IDProperty *prop, short opcontext)
+bUserMenuItem_Op *ED_screen_user_menu_item_find_operator(ListBase *lb,
+ const wmOperatorType *ot,
+ IDProperty *prop,
+ short opcontext)
{
- for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) {
- 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) &&
- (IDP_EqualsProperties(prop, umi_op->prop)))
- {
- return umi_op;
- }
- }
- }
- return NULL;
+ for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) {
+ 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) &&
+ (IDP_EqualsProperties(prop, umi_op->prop))) {
+ return umi_op;
+ }
+ }
+ }
+ return NULL;
}
-struct bUserMenuItem_Menu *ED_screen_user_menu_item_find_menu(
- struct ListBase *lb,
- const struct MenuType *mt)
+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) {
- if (umi->type == USER_MENU_TYPE_MENU) {
- bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)umi;
- if (STREQ(mt->idname, umi_mt->mt_idname)) {
- return umi_mt;
- }
- }
- }
- return NULL;
+ for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) {
+ if (umi->type == USER_MENU_TYPE_MENU) {
+ bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)umi;
+ if (STREQ(mt->idname, umi_mt->mt_idname)) {
+ return umi_mt;
+ }
+ }
+ }
+ return NULL;
}
-struct bUserMenuItem_Prop *ED_screen_user_menu_item_find_prop(
- struct ListBase *lb,
- const char *context_data_path, const char *prop_id, int prop_index)
+struct bUserMenuItem_Prop *ED_screen_user_menu_item_find_prop(struct ListBase *lb,
+ const char *context_data_path,
+ const char *prop_id,
+ int prop_index)
{
- for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) {
- 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) &&
- (prop_index == umi_pr->prop_index))
- {
- return umi_pr;
- }
- }
- }
- return NULL;
+ for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) {
+ 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) &&
+ (prop_index == umi_pr->prop_index)) {
+ return umi_pr;
+ }
+ }
+ }
+ return NULL;
}
-void ED_screen_user_menu_item_add_operator(
- ListBase *lb, const char *ui_name,
- const wmOperatorType *ot, const IDProperty *prop, short opcontext)
+void ED_screen_user_menu_item_add_operator(ListBase *lb,
+ const char *ui_name,
+ const wmOperatorType *ot,
+ const IDProperty *prop,
+ short opcontext)
{
- bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)BKE_blender_user_menu_item_add(lb, USER_MENU_TYPE_OPERATOR);
- umi_op->opcontext = opcontext;
- if (!STREQ(ui_name, ot->name)) {
- STRNCPY(umi_op->item.ui_name, ui_name);
- }
- STRNCPY(umi_op->op_idname, ot->idname);
- umi_op->prop = prop ? IDP_CopyProperty(prop) : NULL;
+ bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)BKE_blender_user_menu_item_add(
+ lb, USER_MENU_TYPE_OPERATOR);
+ umi_op->opcontext = opcontext;
+ if (!STREQ(ui_name, ot->name)) {
+ STRNCPY(umi_op->item.ui_name, ui_name);
+ }
+ STRNCPY(umi_op->op_idname, ot->idname);
+ umi_op->prop = prop ? IDP_CopyProperty(prop) : NULL;
}
-void ED_screen_user_menu_item_add_menu(
- ListBase *lb, const char *ui_name,
- const MenuType *mt)
+void ED_screen_user_menu_item_add_menu(ListBase *lb, const char *ui_name, const MenuType *mt)
{
- bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)BKE_blender_user_menu_item_add(lb, USER_MENU_TYPE_MENU);
- if (!STREQ(ui_name, mt->label)) {
- STRNCPY(umi_mt->item.ui_name, ui_name);
- }
- STRNCPY(umi_mt->mt_idname, mt->idname);
+ bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)BKE_blender_user_menu_item_add(
+ lb, USER_MENU_TYPE_MENU);
+ if (!STREQ(ui_name, mt->label)) {
+ STRNCPY(umi_mt->item.ui_name, ui_name);
+ }
+ STRNCPY(umi_mt->mt_idname, mt->idname);
}
-void ED_screen_user_menu_item_add_prop(
- ListBase *lb, const char *ui_name,
- const char *context_data_path, const char *prop_id, int prop_index)
+void ED_screen_user_menu_item_add_prop(ListBase *lb,
+ const char *ui_name,
+ const char *context_data_path,
+ const char *prop_id,
+ int prop_index)
{
- bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)BKE_blender_user_menu_item_add(lb, USER_MENU_TYPE_PROP);
- STRNCPY(umi_pr->item.ui_name, ui_name);
- STRNCPY(umi_pr->context_data_path, context_data_path);
- STRNCPY(umi_pr->prop_id, prop_id);
- umi_pr->prop_index = prop_index;
+ bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)BKE_blender_user_menu_item_add(
+ lb, USER_MENU_TYPE_PROP);
+ STRNCPY(umi_pr->item.ui_name, ui_name);
+ STRNCPY(umi_pr->context_data_path, context_data_path);
+ STRNCPY(umi_pr->prop_id, prop_id);
+ umi_pr->prop_index = prop_index;
}
void ED_screen_user_menu_item_remove(ListBase *lb, bUserMenuItem *umi)
{
- BLI_remlink(lb, umi);
- BKE_blender_user_menu_item_free(umi);
+ BLI_remlink(lb, umi);
+ BKE_blender_user_menu_item_free(umi);
}
/** \} */
@@ -188,95 +194,92 @@ void ED_screen_user_menu_item_remove(ListBase *lb, bUserMenuItem *umi)
static void screen_user_menu_draw(const bContext *C, Menu *menu)
{
- uint um_array_len;
- bUserMenu **um_array = ED_screen_user_menus_find(C, &um_array_len);
- bool is_empty = true;
- for (int um_index = 0; um_index < um_array_len; um_index++) {
- bUserMenu *um = um_array[um_index];
- if (um == NULL) {
- continue;
- }
- for (bUserMenuItem *umi = um->items.first; umi; umi = umi->next) {
- const char *ui_name = umi->ui_name[0] ? umi->ui_name : NULL;
- if (umi->type == USER_MENU_TYPE_OPERATOR) {
- bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi;
- IDProperty *prop = umi_op->prop ? IDP_CopyProperty(umi_op->prop) : NULL;
- uiItemFullO(
- menu->layout, umi_op->op_idname, ui_name,
- ICON_NONE, prop, umi_op->opcontext, 0, NULL);
- is_empty = false;
- }
- else if (umi->type == USER_MENU_TYPE_MENU) {
- bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)umi;
- uiItemM(menu->layout, umi_mt->mt_idname, ui_name,
- ICON_NONE);
- is_empty = false;
- }
- else if (umi->type == USER_MENU_TYPE_PROP) {
- bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)umi;
-
- char *data_path = strchr(umi_pr->context_data_path, '.');
- if (data_path) {
- *data_path = '\0';
- }
- PointerRNA ptr = CTX_data_pointer_get(C, umi_pr->context_data_path);
- if (ptr.type == NULL) {
- PointerRNA ctx_ptr;
- RNA_pointer_create(NULL, &RNA_Context, (void *)C, &ctx_ptr);
- if (!RNA_path_resolve_full(&ctx_ptr, umi_pr->context_data_path, &ptr, NULL, NULL)) {
- ptr.type = NULL;
- }
- }
- if (data_path) {
- *data_path = '.';
- data_path += 1;
- }
-
- bool ok = false;
- if (ptr.type != NULL) {
- PropertyRNA *prop = NULL;
- PointerRNA prop_ptr = ptr;
- if ((data_path == NULL) || RNA_path_resolve_full(&ptr, data_path, &prop_ptr, NULL, NULL)) {
- prop = RNA_struct_find_property(&prop_ptr, umi_pr->prop_id);
- if (prop) {
- ok = true;
- uiItemFullR(
- menu->layout,
- &prop_ptr, prop, umi_pr->prop_index,
- 0, 0, ui_name, ICON_NONE);
- is_empty = false;
- }
- }
- }
- if (!ok) {
- char label[512];
- SNPRINTF(label, "Missing: %s.%s", umi_pr->context_data_path, umi_pr->prop_id);
- uiItemL(menu->layout, label, ICON_NONE);
- }
- }
- else if (umi->type == USER_MENU_TYPE_SEP) {
- uiItemS(menu->layout);
- }
- }
- }
- if (um_array) {
- MEM_freeN(um_array);
- }
-
- if (is_empty) {
- uiItemL(menu->layout, IFACE_("No menu items found"), ICON_NONE);
- uiItemL(menu->layout, IFACE_("Right click on buttons to add them to this menu"), ICON_NONE);
- }
+ uint um_array_len;
+ bUserMenu **um_array = ED_screen_user_menus_find(C, &um_array_len);
+ bool is_empty = true;
+ for (int um_index = 0; um_index < um_array_len; um_index++) {
+ bUserMenu *um = um_array[um_index];
+ if (um == NULL) {
+ continue;
+ }
+ for (bUserMenuItem *umi = um->items.first; umi; umi = umi->next) {
+ const char *ui_name = umi->ui_name[0] ? umi->ui_name : NULL;
+ if (umi->type == USER_MENU_TYPE_OPERATOR) {
+ bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi;
+ IDProperty *prop = umi_op->prop ? IDP_CopyProperty(umi_op->prop) : NULL;
+ uiItemFullO(
+ menu->layout, umi_op->op_idname, ui_name, ICON_NONE, prop, umi_op->opcontext, 0, NULL);
+ is_empty = false;
+ }
+ else if (umi->type == USER_MENU_TYPE_MENU) {
+ bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)umi;
+ uiItemM(menu->layout, umi_mt->mt_idname, ui_name, ICON_NONE);
+ is_empty = false;
+ }
+ else if (umi->type == USER_MENU_TYPE_PROP) {
+ bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)umi;
+
+ char *data_path = strchr(umi_pr->context_data_path, '.');
+ if (data_path) {
+ *data_path = '\0';
+ }
+ PointerRNA ptr = CTX_data_pointer_get(C, umi_pr->context_data_path);
+ if (ptr.type == NULL) {
+ PointerRNA ctx_ptr;
+ RNA_pointer_create(NULL, &RNA_Context, (void *)C, &ctx_ptr);
+ if (!RNA_path_resolve_full(&ctx_ptr, umi_pr->context_data_path, &ptr, NULL, NULL)) {
+ ptr.type = NULL;
+ }
+ }
+ if (data_path) {
+ *data_path = '.';
+ data_path += 1;
+ }
+
+ bool ok = false;
+ if (ptr.type != NULL) {
+ PropertyRNA *prop = NULL;
+ PointerRNA prop_ptr = ptr;
+ if ((data_path == NULL) ||
+ RNA_path_resolve_full(&ptr, data_path, &prop_ptr, NULL, NULL)) {
+ prop = RNA_struct_find_property(&prop_ptr, umi_pr->prop_id);
+ if (prop) {
+ ok = true;
+ uiItemFullR(
+ menu->layout, &prop_ptr, prop, umi_pr->prop_index, 0, 0, ui_name, ICON_NONE);
+ is_empty = false;
+ }
+ }
+ }
+ if (!ok) {
+ char label[512];
+ SNPRINTF(label, "Missing: %s.%s", umi_pr->context_data_path, umi_pr->prop_id);
+ uiItemL(menu->layout, label, ICON_NONE);
+ }
+ }
+ else if (umi->type == USER_MENU_TYPE_SEP) {
+ uiItemS(menu->layout);
+ }
+ }
+ }
+ if (um_array) {
+ MEM_freeN(um_array);
+ }
+
+ if (is_empty) {
+ uiItemL(menu->layout, IFACE_("No menu items found"), ICON_NONE);
+ uiItemL(menu->layout, IFACE_("Right click on buttons to add them to this menu"), ICON_NONE);
+ }
}
void ED_screen_user_menu_register(void)
{
- MenuType *mt = MEM_callocN(sizeof(MenuType), __func__);
- strcpy(mt->idname, "SCREEN_MT_user_menu");
- strcpy(mt->label, "Quick Favorites");
- strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- mt->draw = screen_user_menu_draw;
- WM_menutype_add(mt);
+ MenuType *mt = MEM_callocN(sizeof(MenuType), __func__);
+ strcpy(mt->idname, "SCREEN_MT_user_menu");
+ strcpy(mt->label, "Quick Favorites");
+ strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ mt->draw = screen_user_menu_draw;
+ WM_menutype_add(mt);
}
/** \} */
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index 2e634cccedb..37ffdef0b9b 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -22,7 +22,6 @@
* \ingroup edscr
*/
-
#include <string.h>
#include <errno.h>
@@ -57,239 +56,249 @@
#include "screen_intern.h"
typedef struct ScreenshotData {
- unsigned int *dumprect;
- int dumpsx, dumpsy;
- rcti crop;
+ unsigned int *dumprect;
+ int dumpsx, dumpsy;
+ rcti crop;
- ImageFormatData im_format;
+ ImageFormatData im_format;
} ScreenshotData;
static void screenshot_read_pixels(int x, int y, int w, int h, unsigned char *rect)
{
- int i;
+ int i;
- glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect);
- glFinish();
+ glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+ glFinish();
- /* clear alpha, it is not set to a meaningful value in opengl */
- for (i = 0, rect += 3; i < w * h; i++, rect += 4)
- *rect = 255;
+ /* clear alpha, it is not set to a meaningful value in opengl */
+ for (i = 0, rect += 3; i < w * h; i++, rect += 4)
+ *rect = 255;
}
/* get shot from frontbuffer */
static unsigned int *screenshot(bContext *C, int *dumpsx, int *dumpsy)
{
- wmWindow *win = CTX_wm_window(C);
- int x = 0, y = 0;
- unsigned int *dumprect = NULL;
+ wmWindow *win = CTX_wm_window(C);
+ int x = 0, y = 0;
+ unsigned int *dumprect = NULL;
- x = 0;
- y = 0;
- *dumpsx = WM_window_pixels_x(win);
- *dumpsy = WM_window_pixels_y(win);
+ x = 0;
+ y = 0;
+ *dumpsx = WM_window_pixels_x(win);
+ *dumpsy = WM_window_pixels_y(win);
- if (*dumpsx && *dumpsy) {
+ if (*dumpsx && *dumpsy) {
- dumprect = MEM_mallocN(sizeof(int) * (*dumpsx) * (*dumpsy), "dumprect");
- glReadBuffer(GL_FRONT);
- screenshot_read_pixels(x, y, *dumpsx, *dumpsy, (unsigned char *)dumprect);
- glReadBuffer(GL_BACK);
- }
+ dumprect = MEM_mallocN(sizeof(int) * (*dumpsx) * (*dumpsy), "dumprect");
+ glReadBuffer(GL_FRONT);
+ screenshot_read_pixels(x, y, *dumpsx, *dumpsy, (unsigned char *)dumprect);
+ glReadBuffer(GL_BACK);
+ }
- return dumprect;
+ return dumprect;
}
/* call from both exec and invoke */
static int screenshot_data_create(bContext *C, wmOperator *op)
{
- unsigned int *dumprect;
- int dumpsx, dumpsy;
+ unsigned int *dumprect;
+ int dumpsx, dumpsy;
- /* do redraw so we don't show popups/menus */
- WM_redraw_windows(C);
+ /* do redraw so we don't show popups/menus */
+ WM_redraw_windows(C);
- dumprect = screenshot(C, &dumpsx, &dumpsy);
+ dumprect = screenshot(C, &dumpsx, &dumpsy);
- if (dumprect) {
- ScreenshotData *scd = MEM_callocN(sizeof(ScreenshotData), "screenshot");
- ScrArea *sa = CTX_wm_area(C);
+ if (dumprect) {
+ ScreenshotData *scd = MEM_callocN(sizeof(ScreenshotData), "screenshot");
+ ScrArea *sa = CTX_wm_area(C);
- scd->dumpsx = dumpsx;
- scd->dumpsy = dumpsy;
- scd->dumprect = dumprect;
- if (sa) {
- scd->crop = sa->totrct;
- }
+ scd->dumpsx = dumpsx;
+ scd->dumpsy = dumpsy;
+ scd->dumprect = dumprect;
+ if (sa) {
+ scd->crop = sa->totrct;
+ }
- BKE_imformat_defaults(&scd->im_format);
+ BKE_imformat_defaults(&scd->im_format);
- op->customdata = scd;
+ op->customdata = scd;
- return true;
- }
- else {
- op->customdata = NULL;
- return false;
- }
+ return true;
+ }
+ else {
+ op->customdata = NULL;
+ return false;
+ }
}
static void screenshot_data_free(wmOperator *op)
{
- ScreenshotData *scd = op->customdata;
-
- if (scd) {
- if (scd->dumprect)
- MEM_freeN(scd->dumprect);
- MEM_freeN(scd);
- op->customdata = NULL;
- }
+ ScreenshotData *scd = op->customdata;
+
+ if (scd) {
+ if (scd->dumprect)
+ MEM_freeN(scd->dumprect);
+ MEM_freeN(scd);
+ op->customdata = NULL;
+ }
}
static void screenshot_crop(ImBuf *ibuf, rcti crop)
{
- unsigned int *to = ibuf->rect;
- unsigned int *from = ibuf->rect + crop.ymin * ibuf->x + crop.xmin;
- int crop_x = BLI_rcti_size_x(&crop);
- int crop_y = BLI_rcti_size_y(&crop);
- int y;
-
- if (crop_x > 0 && crop_y > 0) {
- for (y = 0; y < crop_y; y++, to += crop_x, from += ibuf->x)
- memmove(to, from, sizeof(unsigned int) * crop_x);
-
- ibuf->x = crop_x;
- ibuf->y = crop_y;
- }
+ unsigned int *to = ibuf->rect;
+ unsigned int *from = ibuf->rect + crop.ymin * ibuf->x + crop.xmin;
+ int crop_x = BLI_rcti_size_x(&crop);
+ int crop_y = BLI_rcti_size_y(&crop);
+ int y;
+
+ if (crop_x > 0 && crop_y > 0) {
+ for (y = 0; y < crop_y; y++, to += crop_x, from += ibuf->x)
+ memmove(to, from, sizeof(unsigned int) * crop_x);
+
+ ibuf->x = crop_x;
+ ibuf->y = crop_y;
+ }
}
static int screenshot_exec(bContext *C, wmOperator *op)
{
- ScreenshotData *scd = op->customdata;
- bool ok = false;
-
- if (scd == NULL) {
- /* when running exec directly */
- screenshot_data_create(C, op);
- scd = op->customdata;
- }
-
- if (scd) {
- if (scd->dumprect) {
- ImBuf *ibuf;
- char path[FILE_MAX];
-
- RNA_string_get(op->ptr, "filepath", path);
- BLI_path_abs(path, BKE_main_blendfile_path_from_global());
-
- /* operator ensures the extension */
- ibuf = IMB_allocImBuf(scd->dumpsx, scd->dumpsy, 24, 0);
- ibuf->rect = scd->dumprect;
-
- /* crop to show only single editor */
- if (!RNA_boolean_get(op->ptr, "full"))
- screenshot_crop(ibuf, scd->crop);
-
- if (scd->im_format.planes == R_IMF_PLANES_BW) {
- /* bw screenshot? - users will notice if it fails! */
- IMB_color_to_bw(ibuf);
- }
- if (BKE_imbuf_write(ibuf, path, &scd->im_format)) {
- ok = true;
- }
- else {
- BKE_reportf(op->reports, RPT_ERROR, "Could not write image: %s", strerror(errno));
- }
-
- IMB_freeImBuf(ibuf);
- }
- }
-
- screenshot_data_free(op);
-
- return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ ScreenshotData *scd = op->customdata;
+ bool ok = false;
+
+ if (scd == NULL) {
+ /* when running exec directly */
+ screenshot_data_create(C, op);
+ scd = op->customdata;
+ }
+
+ if (scd) {
+ if (scd->dumprect) {
+ ImBuf *ibuf;
+ char path[FILE_MAX];
+
+ RNA_string_get(op->ptr, "filepath", path);
+ BLI_path_abs(path, BKE_main_blendfile_path_from_global());
+
+ /* operator ensures the extension */
+ ibuf = IMB_allocImBuf(scd->dumpsx, scd->dumpsy, 24, 0);
+ ibuf->rect = scd->dumprect;
+
+ /* crop to show only single editor */
+ if (!RNA_boolean_get(op->ptr, "full"))
+ screenshot_crop(ibuf, scd->crop);
+
+ if (scd->im_format.planes == R_IMF_PLANES_BW) {
+ /* bw screenshot? - users will notice if it fails! */
+ IMB_color_to_bw(ibuf);
+ }
+ if (BKE_imbuf_write(ibuf, path, &scd->im_format)) {
+ ok = true;
+ }
+ else {
+ BKE_reportf(op->reports, RPT_ERROR, "Could not write image: %s", strerror(errno));
+ }
+
+ IMB_freeImBuf(ibuf);
+ }
+ }
+
+ screenshot_data_free(op);
+
+ return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static int screenshot_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (screenshot_data_create(C, op)) {
- if (RNA_struct_property_is_set(op->ptr, "filepath"))
- return screenshot_exec(C, op);
-
- /* extension is added by 'screenshot_check' after */
- char filepath[FILE_MAX] = "//screen";
- if (G.relbase_valid) {
- BLI_strncpy(filepath, BKE_main_blendfile_path_from_global(), sizeof(filepath));
- BLI_path_extension_replace(filepath, sizeof(filepath), ""); /* strip '.blend' */
- }
- RNA_string_set(op->ptr, "filepath", filepath);
-
- WM_event_add_fileselect(C, op);
-
- return OPERATOR_RUNNING_MODAL;
- }
- return OPERATOR_CANCELLED;
+ if (screenshot_data_create(C, op)) {
+ if (RNA_struct_property_is_set(op->ptr, "filepath"))
+ return screenshot_exec(C, op);
+
+ /* extension is added by 'screenshot_check' after */
+ char filepath[FILE_MAX] = "//screen";
+ if (G.relbase_valid) {
+ BLI_strncpy(filepath, BKE_main_blendfile_path_from_global(), sizeof(filepath));
+ BLI_path_extension_replace(filepath, sizeof(filepath), ""); /* strip '.blend' */
+ }
+ RNA_string_set(op->ptr, "filepath", filepath);
+
+ WM_event_add_fileselect(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ return OPERATOR_CANCELLED;
}
static bool screenshot_check(bContext *UNUSED(C), wmOperator *op)
{
- ScreenshotData *scd = op->customdata;
- return WM_operator_filesel_ensure_ext_imtype(op, &scd->im_format);
+ ScreenshotData *scd = op->customdata;
+ return WM_operator_filesel_ensure_ext_imtype(op, &scd->im_format);
}
static void screenshot_cancel(bContext *UNUSED(C), wmOperator *op)
{
- screenshot_data_free(op);
+ screenshot_data_free(op);
}
-static bool screenshot_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop, void *UNUSED(user_data))
+static bool screenshot_draw_check_prop(PointerRNA *UNUSED(ptr),
+ PropertyRNA *prop,
+ void *UNUSED(user_data))
{
- const char *prop_id = RNA_property_identifier(prop);
+ const char *prop_id = RNA_property_identifier(prop);
- return !(STREQ(prop_id, "filepath"));
+ return !(STREQ(prop_id, "filepath"));
}
static void screenshot_draw(bContext *UNUSED(C), wmOperator *op)
{
- uiLayout *layout = op->layout;
- ScreenshotData *scd = op->customdata;
- PointerRNA ptr;
-
- /* image template */
- RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &scd->im_format, &ptr);
- uiTemplateImageSettings(layout, &ptr, false);
-
- /* main draw call */
- RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
- uiDefAutoButsRNA(layout, &ptr, screenshot_draw_check_prop, NULL, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
+ uiLayout *layout = op->layout;
+ ScreenshotData *scd = op->customdata;
+ PointerRNA ptr;
+
+ /* image template */
+ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &scd->im_format, &ptr);
+ uiTemplateImageSettings(layout, &ptr, false);
+
+ /* main draw call */
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+ uiDefAutoButsRNA(
+ layout, &ptr, screenshot_draw_check_prop, NULL, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
}
static bool screenshot_poll(bContext *C)
{
- if (G.background)
- return false;
+ if (G.background)
+ return false;
- return WM_operator_winactive(C);
+ return WM_operator_winactive(C);
}
void SCREEN_OT_screenshot(wmOperatorType *ot)
{
- /* weak: opname starting with 'save' makes filewindow give save-over */
- ot->name = "Save Screenshot";
- ot->idname = "SCREEN_OT_screenshot";
- ot->description = "Capture a picture of the active area or whole Blender window";
-
- ot->invoke = screenshot_invoke;
- ot->check = screenshot_check;
- ot->exec = screenshot_exec;
- ot->cancel = screenshot_cancel;
- ot->ui = screenshot_draw;
- ot->poll = screenshot_poll;
-
- ot->flag = 0;
-
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE, FILE_SPECIAL, FILE_SAVE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
- RNA_def_boolean(ot->srna, "full", 1, "Full Screen",
- "Capture the whole window (otherwise only capture the active area)");
+ /* weak: opname starting with 'save' makes filewindow give save-over */
+ ot->name = "Save Screenshot";
+ ot->idname = "SCREEN_OT_screenshot";
+ ot->description = "Capture a picture of the active area or whole Blender window";
+
+ ot->invoke = screenshot_invoke;
+ ot->check = screenshot_check;
+ ot->exec = screenshot_exec;
+ ot->cancel = screenshot_cancel;
+ ot->ui = screenshot_draw;
+ ot->poll = screenshot_poll;
+
+ ot->flag = 0;
+
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_IMAGE,
+ FILE_SPECIAL,
+ FILE_SAVE,
+ WM_FILESEL_FILEPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
+ RNA_def_boolean(ot->srna,
+ "full",
+ 1,
+ "Full Screen",
+ "Capture the whole window (otherwise only capture the active area)");
}
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
index 63d25cb96c4..5750a1f36a7 100644
--- a/source/blender/editors/screen/workspace_edit.c
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -67,7 +67,6 @@
#include "screen_intern.h"
-
/** \name Workspace API
*
* \brief API for managing workspaces and their data.
@@ -75,69 +74,70 @@
WorkSpace *ED_workspace_add(Main *bmain, const char *name)
{
- return BKE_workspace_add(bmain, name);
+ return BKE_workspace_add(bmain, name);
}
/**
* Changes the object mode (if needed) to the one set in \a workspace_new.
* Object mode is still stored on object level. In future it should all be workspace level instead.
*/
-static void workspace_change_update(
- WorkSpace *workspace_new, const WorkSpace *workspace_old,
- bContext *C, wmWindowManager *wm)
+static void workspace_change_update(WorkSpace *workspace_new,
+ const WorkSpace *workspace_old,
+ bContext *C,
+ wmWindowManager *wm)
{
- /* needs to be done before changing mode! (to ensure right context) */
- UNUSED_VARS(workspace_old, workspace_new, C, wm);
+ /* needs to be done before changing mode! (to ensure right context) */
+ UNUSED_VARS(workspace_old, workspace_new, C, wm);
#if 0
- Object *ob_act = CTX_data_active_object(C)
- eObjectMode mode_old = workspace_old->object_mode;
- eObjectMode mode_new = workspace_new->object_mode;
-
- if (mode_old != mode_new) {
- ED_object_mode_compat_set(C, ob_act, mode_new, &wm->reports);
- ED_object_mode_toggle(C, mode_new);
- }
+ Object *ob_act = CTX_data_active_object(C)
+ eObjectMode mode_old = workspace_old->object_mode;
+ eObjectMode mode_new = workspace_new->object_mode;
+
+ if (mode_old != mode_new) {
+ ED_object_mode_compat_set(C, ob_act, mode_new, &wm->reports);
+ ED_object_mode_toggle(C, mode_new);
+ }
#endif
}
static bool workspace_change_find_new_layout_cb(const WorkSpaceLayout *layout, void *UNUSED(arg))
{
- /* return false to stop the iterator if we've found a layout that can be activated */
- return workspace_layout_set_poll(layout) ? false : true;
+ /* return false to stop the iterator if we've found a layout that can be activated */
+ return workspace_layout_set_poll(layout) ? false : true;
}
-static WorkSpaceLayout *workspace_change_get_new_layout(
- Main *bmain, WorkSpace *workspace_new, wmWindow *win)
+static WorkSpaceLayout *workspace_change_get_new_layout(Main *bmain,
+ WorkSpace *workspace_new,
+ wmWindow *win)
{
- /* ED_workspace_duplicate may have stored a layout to activate once the workspace gets activated. */
- WorkSpaceLayout *layout_old = WM_window_get_active_layout(win);
- WorkSpaceLayout *layout_new;
- bScreen *screen_new;
-
- if (win->workspace_hook->temp_workspace_store) {
- layout_new = win->workspace_hook->temp_layout_store;
- }
- else {
- layout_new = BKE_workspace_hook_layout_for_workspace_get(win->workspace_hook, workspace_new);
- if (!layout_new) {
- layout_new = BKE_workspace_layouts_get(workspace_new)->first;
- }
- }
- screen_new = BKE_workspace_layout_screen_get(layout_new);
-
- if (screen_new->winid) {
- /* screen is already used, try to find a free one */
- WorkSpaceLayout *layout_temp = BKE_workspace_layout_iter_circular(
- workspace_new, layout_new, workspace_change_find_new_layout_cb,
- NULL, false);
- if (!layout_temp) {
- /* fallback solution: duplicate layout from old workspace */
- layout_temp = ED_workspace_layout_duplicate(bmain, workspace_new, layout_old, win);
- }
- layout_new = layout_temp;
- }
-
- return layout_new;
+ /* ED_workspace_duplicate may have stored a layout to activate once the workspace gets activated. */
+ WorkSpaceLayout *layout_old = WM_window_get_active_layout(win);
+ WorkSpaceLayout *layout_new;
+ bScreen *screen_new;
+
+ if (win->workspace_hook->temp_workspace_store) {
+ layout_new = win->workspace_hook->temp_layout_store;
+ }
+ else {
+ layout_new = BKE_workspace_hook_layout_for_workspace_get(win->workspace_hook, workspace_new);
+ if (!layout_new) {
+ layout_new = BKE_workspace_layouts_get(workspace_new)->first;
+ }
+ }
+ screen_new = BKE_workspace_layout_screen_get(layout_new);
+
+ if (screen_new->winid) {
+ /* screen is already used, try to find a free one */
+ WorkSpaceLayout *layout_temp = BKE_workspace_layout_iter_circular(
+ workspace_new, layout_new, workspace_change_find_new_layout_cb, NULL, false);
+ if (!layout_temp) {
+ /* fallback solution: duplicate layout from old workspace */
+ layout_temp = ED_workspace_layout_duplicate(bmain, workspace_new, layout_old, win);
+ }
+ layout_new = layout_temp;
+ }
+
+ return layout_new;
}
/**
@@ -149,464 +149,472 @@ static WorkSpaceLayout *workspace_change_get_new_layout(
* \warning Do NOT call in area/region queues!
* \returns if workspace changing was successful.
*/
-bool ED_workspace_change(
- WorkSpace *workspace_new, bContext *C, wmWindowManager *wm, wmWindow *win)
+bool ED_workspace_change(WorkSpace *workspace_new, bContext *C, wmWindowManager *wm, wmWindow *win)
{
- Main *bmain = CTX_data_main(C);
- WorkSpace *workspace_old = WM_window_get_active_workspace(win);
- WorkSpaceLayout *layout_new = workspace_change_get_new_layout(bmain, workspace_new, win);
- bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new);
- bScreen *screen_old = BKE_workspace_active_screen_get(win->workspace_hook);
+ Main *bmain = CTX_data_main(C);
+ WorkSpace *workspace_old = WM_window_get_active_workspace(win);
+ WorkSpaceLayout *layout_new = workspace_change_get_new_layout(bmain, workspace_new, win);
+ bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new);
+ bScreen *screen_old = BKE_workspace_active_screen_get(win->workspace_hook);
- win->workspace_hook->temp_layout_store = NULL;
- if (workspace_old == workspace_new) {
- /* Could also return true, everything that needs to be done was done (nothing :P), but nothing changed */
- return false;
- }
+ win->workspace_hook->temp_layout_store = NULL;
+ if (workspace_old == workspace_new) {
+ /* Could also return true, everything that needs to be done was done (nothing :P), but nothing changed */
+ return false;
+ }
- screen_new = screen_change_prepare(screen_old, screen_new, bmain, C, win);
- BLI_assert(BKE_workspace_layout_screen_get(layout_new) == screen_new);
+ screen_new = screen_change_prepare(screen_old, screen_new, bmain, C, win);
+ BLI_assert(BKE_workspace_layout_screen_get(layout_new) == screen_new);
- if (screen_new == NULL) {
- return false;
- }
+ if (screen_new == NULL) {
+ return false;
+ }
- BKE_workspace_hook_layout_for_workspace_set(win->workspace_hook, workspace_new, layout_new);
- BKE_workspace_active_set(win->workspace_hook, workspace_new);
+ BKE_workspace_hook_layout_for_workspace_set(win->workspace_hook, workspace_new, layout_new);
+ BKE_workspace_active_set(win->workspace_hook, workspace_new);
- /* update screen *after* changing workspace - which also causes the
- * actual screen change and updates context (including CTX_wm_workspace) */
- screen_change_update(C, win, screen_new);
- workspace_change_update(workspace_new, workspace_old, C, wm);
+ /* update screen *after* changing workspace - which also causes the
+ * actual screen change and updates context (including CTX_wm_workspace) */
+ screen_change_update(C, win, screen_new);
+ workspace_change_update(workspace_new, workspace_old, C, wm);
- BLI_assert(CTX_wm_workspace(C) == workspace_new);
+ BLI_assert(CTX_wm_workspace(C) == workspace_new);
- WM_toolsystem_unlink_all(C, workspace_old);
- /* Area initialization will initialize based on the new workspace. */
+ WM_toolsystem_unlink_all(C, workspace_old);
+ /* Area initialization will initialize based on the new workspace. */
- /* Automatic mode switching. */
- if (workspace_new->object_mode != workspace_old->object_mode) {
- ED_object_mode_generic_enter(C, workspace_new->object_mode);
- }
+ /* Automatic mode switching. */
+ if (workspace_new->object_mode != workspace_old->object_mode) {
+ ED_object_mode_generic_enter(C, workspace_new->object_mode);
+ }
- return true;
+ return true;
}
/**
* Duplicate a workspace including its layouts. Does not activate the workspace, but
* it stores the screen-layout to be activated (BKE_workspace_temp_layout_store)
*/
-WorkSpace *ED_workspace_duplicate(
- WorkSpace *workspace_old, Main *bmain, wmWindow *win)
+WorkSpace *ED_workspace_duplicate(WorkSpace *workspace_old, Main *bmain, wmWindow *win)
{
- WorkSpaceLayout *layout_active_old = BKE_workspace_active_layout_get(win->workspace_hook);
- ListBase *layouts_old = BKE_workspace_layouts_get(workspace_old);
- WorkSpace *workspace_new = ED_workspace_add(bmain, workspace_old->id.name + 2);
+ WorkSpaceLayout *layout_active_old = BKE_workspace_active_layout_get(win->workspace_hook);
+ ListBase *layouts_old = BKE_workspace_layouts_get(workspace_old);
+ WorkSpace *workspace_new = ED_workspace_add(bmain, workspace_old->id.name + 2);
- workspace_new->flags = workspace_old->flags;
- BLI_duplicatelist(&workspace_new->owner_ids, &workspace_old->owner_ids);
+ workspace_new->flags = workspace_old->flags;
+ BLI_duplicatelist(&workspace_new->owner_ids, &workspace_old->owner_ids);
- /* TODO(campbell): tools */
+ /* TODO(campbell): tools */
- for (WorkSpaceLayout *layout_old = layouts_old->first; layout_old; layout_old = layout_old->next) {
- WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate(bmain, workspace_new, layout_old, win);
+ for (WorkSpaceLayout *layout_old = layouts_old->first; layout_old;
+ layout_old = layout_old->next) {
+ WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate(
+ bmain, workspace_new, layout_old, win);
- if (layout_active_old == layout_old) {
- win->workspace_hook->temp_layout_store = layout_new;
- }
- }
- return workspace_new;
+ if (layout_active_old == layout_old) {
+ win->workspace_hook->temp_layout_store = layout_new;
+ }
+ }
+ return workspace_new;
}
/**
* \return if succeeded.
*/
-bool ED_workspace_delete(
- WorkSpace *workspace, Main *bmain, bContext *C, wmWindowManager *wm)
+bool ED_workspace_delete(WorkSpace *workspace, Main *bmain, bContext *C, wmWindowManager *wm)
{
- if (BLI_listbase_is_single(&bmain->workspaces)) {
- return false;
- }
-
- ListBase ordered;
- BKE_id_ordered_list(&ordered, &bmain->workspaces);
- WorkSpace *prev = NULL, *next = NULL;
- for (LinkData *link = ordered.first; link; link = link->next) {
- if (link->data == workspace) {
- prev = link->prev ? link->prev->data : NULL;
- next = link->next ? link->next->data : NULL;
- break;
- }
- }
- BLI_freelistN(&ordered);
- BLI_assert((prev != NULL) || (next != NULL));
-
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
- WorkSpace *workspace_active = WM_window_get_active_workspace(win);
- if (workspace_active == workspace) {
- ED_workspace_change((prev != NULL) ? prev : next, C, wm, win);
- }
- }
-
- BKE_id_free(bmain, &workspace->id);
- return true;
+ if (BLI_listbase_is_single(&bmain->workspaces)) {
+ return false;
+ }
+
+ ListBase ordered;
+ BKE_id_ordered_list(&ordered, &bmain->workspaces);
+ WorkSpace *prev = NULL, *next = NULL;
+ for (LinkData *link = ordered.first; link; link = link->next) {
+ if (link->data == workspace) {
+ prev = link->prev ? link->prev->data : NULL;
+ next = link->next ? link->next->data : NULL;
+ break;
+ }
+ }
+ BLI_freelistN(&ordered);
+ BLI_assert((prev != NULL) || (next != NULL));
+
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ WorkSpace *workspace_active = WM_window_get_active_workspace(win);
+ if (workspace_active == workspace) {
+ ED_workspace_change((prev != NULL) ? prev : next, C, wm, win);
+ }
+ }
+
+ BKE_id_free(bmain, &workspace->id);
+ return true;
}
/**
* Some editor data may need to be synced with scene data (3D View camera and layers).
* This function ensures data is synced for editors in active layout of \a workspace.
*/
-void ED_workspace_scene_data_sync(
- WorkSpaceInstanceHook *hook, Scene *scene)
+void ED_workspace_scene_data_sync(WorkSpaceInstanceHook *hook, Scene *scene)
{
- bScreen *screen = BKE_workspace_active_screen_get(hook);
- BKE_screen_view3d_scene_sync(screen, scene);
+ bScreen *screen = BKE_workspace_active_screen_get(hook);
+ BKE_screen_view3d_scene_sync(screen, scene);
}
/** \} Workspace API */
-
/** \name Workspace Operators
*
* \{ */
static WorkSpace *workspace_context_get(bContext *C)
{
- ID *id = UI_context_active_but_get_tab_ID(C);
- if (id && GS(id->name) == ID_WS) {
- return (WorkSpace *)id;
- }
+ ID *id = UI_context_active_but_get_tab_ID(C);
+ if (id && GS(id->name) == ID_WS) {
+ return (WorkSpace *)id;
+ }
- wmWindow *win = CTX_wm_window(C);
- return WM_window_get_active_workspace(win);
+ wmWindow *win = CTX_wm_window(C);
+ return WM_window_get_active_workspace(win);
}
static bool workspace_context_poll(bContext *C)
{
- return workspace_context_get(C) != NULL;
+ return workspace_context_get(C) != NULL;
}
static int workspace_new_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- wmWindow *win = CTX_wm_window(C);
- WorkSpace *workspace = workspace_context_get(C);
+ Main *bmain = CTX_data_main(C);
+ wmWindow *win = CTX_wm_window(C);
+ WorkSpace *workspace = workspace_context_get(C);
- workspace = ED_workspace_duplicate(workspace, bmain, win);
+ workspace = ED_workspace_duplicate(workspace, bmain, win);
- WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, workspace);
+ WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, workspace);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void WORKSPACE_OT_duplicate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "New Workspace";
- ot->description = "Add a new workspace";
- ot->idname = "WORKSPACE_OT_duplicate";
-
- /* api callbacks */
- ot->poll = workspace_context_poll;
- ot->exec = workspace_new_exec;
+ /* identifiers */
+ ot->name = "New Workspace";
+ ot->description = "Add a new workspace";
+ ot->idname = "WORKSPACE_OT_duplicate";
+
+ /* api callbacks */
+ ot->poll = workspace_context_poll;
+ ot->exec = workspace_new_exec;
}
static int workspace_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- WorkSpace *workspace = workspace_context_get(C);
- WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_DELETE, workspace);
- WM_event_add_notifier(C, NC_WINDOW, NULL);
+ WorkSpace *workspace = workspace_context_get(C);
+ WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_DELETE, workspace);
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void WORKSPACE_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Workspace";
- ot->description = "Delete the active workspace";
- ot->idname = "WORKSPACE_OT_delete";
-
- /* api callbacks */
- ot->poll = workspace_context_poll;
- ot->exec = workspace_delete_exec;
+ /* identifiers */
+ ot->name = "Delete Workspace";
+ ot->description = "Delete the active workspace";
+ ot->idname = "WORKSPACE_OT_delete";
+
+ /* api callbacks */
+ ot->poll = workspace_context_poll;
+ ot->exec = workspace_delete_exec;
}
static bool workspace_append_activate_poll(bContext *C)
{
- wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false);
- return WM_operator_poll(C, ot);
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false);
+ return WM_operator_poll(C, ot);
}
static int workspace_append(bContext *C, const char *directory, const char *idname)
{
- wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false);
- PointerRNA opptr;
- int retval;
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false);
+ PointerRNA opptr;
+ int retval;
- WM_operator_properties_create_ptr(&opptr, ot);
- RNA_string_set(&opptr, "directory", directory);
- RNA_string_set(&opptr, "filename", idname);
- RNA_boolean_set(&opptr, "autoselect", false);
+ WM_operator_properties_create_ptr(&opptr, ot);
+ RNA_string_set(&opptr, "directory", directory);
+ RNA_string_set(&opptr, "filename", idname);
+ RNA_boolean_set(&opptr, "autoselect", false);
- retval = WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &opptr);
+ retval = WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &opptr);
- WM_operator_properties_free(&opptr);
+ WM_operator_properties_free(&opptr);
- return retval;
+ return retval;
}
static int workspace_append_activate_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- char idname[MAX_ID_NAME - 2], filepath[FILE_MAX];
+ Main *bmain = CTX_data_main(C);
+ char idname[MAX_ID_NAME - 2], filepath[FILE_MAX];
- if (!RNA_struct_property_is_set(op->ptr, "idname") ||
- !RNA_struct_property_is_set(op->ptr, "filepath"))
- {
- return OPERATOR_CANCELLED;
- }
- RNA_string_get(op->ptr, "idname", idname);
- RNA_string_get(op->ptr, "filepath", filepath);
+ if (!RNA_struct_property_is_set(op->ptr, "idname") ||
+ !RNA_struct_property_is_set(op->ptr, "filepath")) {
+ return OPERATOR_CANCELLED;
+ }
+ RNA_string_get(op->ptr, "idname", idname);
+ RNA_string_get(op->ptr, "filepath", filepath);
- if (workspace_append(C, filepath, idname) != OPERATOR_CANCELLED) {
- WorkSpace *appended_workspace = BLI_findstring(&bmain->workspaces, idname, offsetof(ID, name) + 2);
- BLI_assert(appended_workspace != NULL);
+ if (workspace_append(C, filepath, idname) != OPERATOR_CANCELLED) {
+ WorkSpace *appended_workspace = BLI_findstring(
+ &bmain->workspaces, idname, offsetof(ID, name) + 2);
+ BLI_assert(appended_workspace != NULL);
- /* Reorder to last position. */
- BKE_id_reorder(&bmain->workspaces, &appended_workspace->id, NULL, true);
+ /* Reorder to last position. */
+ BKE_id_reorder(&bmain->workspaces, &appended_workspace->id, NULL, true);
- /* Changing workspace changes context. Do delayed! */
- WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, appended_workspace);
+ /* Changing workspace changes context. Do delayed! */
+ WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, appended_workspace);
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
static void WORKSPACE_OT_append_activate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Append and Activate Workspace";
- ot->description = "Append a workspace and make it the active one in the current window";
- ot->idname = "WORKSPACE_OT_append_activate";
-
- /* api callbacks */
- ot->exec = workspace_append_activate_exec;
- ot->poll = workspace_append_activate_poll;
-
- RNA_def_string(ot->srna, "idname", NULL, MAX_ID_NAME - 2, "Identifier",
- "Name of the workspace to append and activate");
- RNA_def_string(ot->srna, "filepath", NULL, FILE_MAX, "Filepath",
- "Path to the library");
+ /* identifiers */
+ ot->name = "Append and Activate Workspace";
+ ot->description = "Append a workspace and make it the active one in the current window";
+ ot->idname = "WORKSPACE_OT_append_activate";
+
+ /* api callbacks */
+ ot->exec = workspace_append_activate_exec;
+ ot->poll = workspace_append_activate_poll;
+
+ RNA_def_string(ot->srna,
+ "idname",
+ NULL,
+ MAX_ID_NAME - 2,
+ "Identifier",
+ "Name of the workspace to append and activate");
+ RNA_def_string(ot->srna, "filepath", NULL, FILE_MAX, "Filepath", "Path to the library");
}
static WorkspaceConfigFileData *workspace_config_file_read(const char *app_template)
{
- const char *cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, app_template);
- char startup_file_path[FILE_MAX] = {0};
+ const char *cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, app_template);
+ char startup_file_path[FILE_MAX] = {0};
- if (cfgdir) {
- BLI_join_dirfile(startup_file_path, sizeof(startup_file_path), cfgdir, BLENDER_STARTUP_FILE);
- }
+ if (cfgdir) {
+ BLI_join_dirfile(startup_file_path, sizeof(startup_file_path), cfgdir, BLENDER_STARTUP_FILE);
+ }
- bool has_path = BLI_exists(startup_file_path);
- return (has_path) ? BKE_blendfile_workspace_config_read(startup_file_path, NULL, 0, NULL) : NULL;
+ bool has_path = BLI_exists(startup_file_path);
+ return (has_path) ? BKE_blendfile_workspace_config_read(startup_file_path, NULL, 0, NULL) : NULL;
}
static WorkspaceConfigFileData *workspace_system_file_read(const char *app_template)
{
- if (app_template == NULL) {
- return BKE_blendfile_workspace_config_read(NULL, datatoc_startup_blend, datatoc_startup_blend_size, NULL);
- }
-
- char template_dir[FILE_MAX];
- if (!BKE_appdir_app_template_id_search(app_template, template_dir, sizeof(template_dir))) {
- return NULL;
- }
-
- char startup_file_path[FILE_MAX];
- BLI_join_dirfile(startup_file_path, sizeof(startup_file_path), template_dir, BLENDER_STARTUP_FILE);
-
- bool has_path = BLI_exists(startup_file_path);
- return (has_path) ? BKE_blendfile_workspace_config_read(startup_file_path, NULL, 0, NULL) : NULL;
+ if (app_template == NULL) {
+ return BKE_blendfile_workspace_config_read(
+ NULL, datatoc_startup_blend, datatoc_startup_blend_size, NULL);
+ }
+
+ char template_dir[FILE_MAX];
+ if (!BKE_appdir_app_template_id_search(app_template, template_dir, sizeof(template_dir))) {
+ return NULL;
+ }
+
+ char startup_file_path[FILE_MAX];
+ BLI_join_dirfile(
+ startup_file_path, sizeof(startup_file_path), template_dir, BLENDER_STARTUP_FILE);
+
+ bool has_path = BLI_exists(startup_file_path);
+ return (has_path) ? BKE_blendfile_workspace_config_read(startup_file_path, NULL, 0, NULL) : NULL;
}
-static void workspace_append_button(
- uiLayout *layout, wmOperatorType *ot_append, const WorkSpace *workspace, const Main *from_main)
+static void workspace_append_button(uiLayout *layout,
+ wmOperatorType *ot_append,
+ const WorkSpace *workspace,
+ const Main *from_main)
{
- const ID *id = (ID *)workspace;
- PointerRNA opptr;
- char lib_path[FILE_MAX_LIBEXTRA];
- const char *filepath = from_main->name;
-
- if (strlen(filepath) == 0) {
- filepath = BLO_EMBEDDED_STARTUP_BLEND;
- }
-
- BLI_path_join(
- lib_path, sizeof(lib_path), filepath, BKE_idcode_to_name(GS(id->name)), NULL);
-
- BLI_assert(STREQ(ot_append->idname, "WORKSPACE_OT_append_activate"));
- uiItemFullO_ptr(
- layout, ot_append, workspace->id.name + 2, ICON_NONE, NULL,
- WM_OP_EXEC_DEFAULT, 0, &opptr);
- RNA_string_set(&opptr, "idname", id->name + 2);
- RNA_string_set(&opptr, "filepath", lib_path);
+ const ID *id = (ID *)workspace;
+ PointerRNA opptr;
+ char lib_path[FILE_MAX_LIBEXTRA];
+ const char *filepath = from_main->name;
+
+ if (strlen(filepath) == 0) {
+ filepath = BLO_EMBEDDED_STARTUP_BLEND;
+ }
+
+ BLI_path_join(lib_path, sizeof(lib_path), filepath, BKE_idcode_to_name(GS(id->name)), NULL);
+
+ BLI_assert(STREQ(ot_append->idname, "WORKSPACE_OT_append_activate"));
+ uiItemFullO_ptr(
+ layout, ot_append, workspace->id.name + 2, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
+ RNA_string_set(&opptr, "idname", id->name + 2);
+ RNA_string_set(&opptr, "filepath", lib_path);
}
static void workspace_add_menu(bContext *C, uiLayout *layout, void *template_v)
{
- Main *bmain = CTX_data_main(C);
- const char *app_template = template_v;
- bool has_startup_items = false;
-
- wmOperatorType *ot_append = WM_operatortype_find("WORKSPACE_OT_append_activate", true);
- WorkspaceConfigFileData *startup_config = workspace_config_file_read(app_template);
- WorkspaceConfigFileData *builtin_config = workspace_system_file_read(app_template);
-
- if (startup_config) {
- for (WorkSpace *workspace = startup_config->workspaces.first; workspace; workspace = workspace->id.next) {
- uiLayout *row = uiLayoutRow(layout, false);
- if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) {
- uiLayoutSetActive(row, false);
- }
-
- workspace_append_button(row, ot_append, workspace, startup_config->main);
- has_startup_items = true;
- }
- }
-
- if (builtin_config) {
- bool has_title = false;
-
- for (WorkSpace *workspace = builtin_config->workspaces.first; workspace; workspace = workspace->id.next) {
- if (startup_config && BLI_findstring(&startup_config->workspaces, workspace->id.name, offsetof(ID, name))) {
- continue;
- }
-
- if (!has_title) {
- if (has_startup_items) {
- uiItemS(layout);
- }
- has_title = true;
- }
-
- uiLayout *row = uiLayoutRow(layout, false);
- if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) {
- uiLayoutSetActive(row, false);
- }
-
- workspace_append_button(row, ot_append, workspace, builtin_config->main);
- }
- }
-
- if (startup_config) {
- BKE_blendfile_workspace_config_data_free(startup_config);
- }
- if (builtin_config) {
- BKE_blendfile_workspace_config_data_free(builtin_config);
- }
+ Main *bmain = CTX_data_main(C);
+ const char *app_template = template_v;
+ bool has_startup_items = false;
+
+ wmOperatorType *ot_append = WM_operatortype_find("WORKSPACE_OT_append_activate", true);
+ WorkspaceConfigFileData *startup_config = workspace_config_file_read(app_template);
+ WorkspaceConfigFileData *builtin_config = workspace_system_file_read(app_template);
+
+ if (startup_config) {
+ for (WorkSpace *workspace = startup_config->workspaces.first; workspace;
+ workspace = workspace->id.next) {
+ uiLayout *row = uiLayoutRow(layout, false);
+ if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) {
+ uiLayoutSetActive(row, false);
+ }
+
+ workspace_append_button(row, ot_append, workspace, startup_config->main);
+ has_startup_items = true;
+ }
+ }
+
+ if (builtin_config) {
+ bool has_title = false;
+
+ for (WorkSpace *workspace = builtin_config->workspaces.first; workspace;
+ workspace = workspace->id.next) {
+ if (startup_config &&
+ BLI_findstring(&startup_config->workspaces, workspace->id.name, offsetof(ID, name))) {
+ continue;
+ }
+
+ if (!has_title) {
+ if (has_startup_items) {
+ uiItemS(layout);
+ }
+ has_title = true;
+ }
+
+ uiLayout *row = uiLayoutRow(layout, false);
+ if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) {
+ uiLayoutSetActive(row, false);
+ }
+
+ workspace_append_button(row, ot_append, workspace, builtin_config->main);
+ }
+ }
+
+ if (startup_config) {
+ BKE_blendfile_workspace_config_data_free(startup_config);
+ }
+ if (builtin_config) {
+ BKE_blendfile_workspace_config_data_free(builtin_config);
+ }
}
static int workspace_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- uiPopupMenu *pup = UI_popup_menu_begin(C, op->type->name, ICON_ADD);
- uiLayout *layout = UI_popup_menu_layout(pup);
+ uiPopupMenu *pup = UI_popup_menu_begin(C, op->type->name, ICON_ADD);
+ uiLayout *layout = UI_popup_menu_layout(pup);
- uiItemMenuF(layout, IFACE_("General"), ICON_NONE, workspace_add_menu, NULL);
+ uiItemMenuF(layout, IFACE_("General"), ICON_NONE, workspace_add_menu, NULL);
- ListBase templates;
- BKE_appdir_app_templates(&templates);
+ ListBase templates;
+ BKE_appdir_app_templates(&templates);
- for (LinkData *link = templates.first; link; link = link->next) {
- char *template = link->data;
- char display_name[FILE_MAX];
+ for (LinkData *link = templates.first; link; link = link->next) {
+ char *template = link->data;
+ char display_name[FILE_MAX];
- BLI_path_to_display_name(display_name, sizeof(display_name), template);
+ BLI_path_to_display_name(display_name, sizeof(display_name), template);
- /* Steals ownership of link data string. */
- uiItemMenuFN(layout, display_name, ICON_NONE, workspace_add_menu, template);
- }
+ /* Steals ownership of link data string. */
+ uiItemMenuFN(layout, display_name, ICON_NONE, workspace_add_menu, template);
+ }
- BLI_freelistN(&templates);
+ BLI_freelistN(&templates);
- uiItemS(layout);
- uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Duplicate Current"), ICON_DUPLICATE,
- "WORKSPACE_OT_duplicate");
+ uiItemS(layout);
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Duplicate Current"),
+ ICON_DUPLICATE,
+ "WORKSPACE_OT_duplicate");
- UI_popup_menu_end(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
static void WORKSPACE_OT_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Workspace";
- ot->description = "Add a new workspace by duplicating the current one or appending one "
- "from the user configuration";
- ot->idname = "WORKSPACE_OT_add";
-
- /* api callbacks */
- ot->invoke = workspace_add_invoke;
+ /* identifiers */
+ ot->name = "Add Workspace";
+ ot->description =
+ "Add a new workspace by duplicating the current one or appending one "
+ "from the user configuration";
+ ot->idname = "WORKSPACE_OT_add";
+
+ /* api callbacks */
+ ot->invoke = workspace_add_invoke;
}
static int workspace_reorder_to_back_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- WorkSpace *workspace = workspace_context_get(C);
+ Main *bmain = CTX_data_main(C);
+ WorkSpace *workspace = workspace_context_get(C);
- BKE_id_reorder(&bmain->workspaces, &workspace->id, NULL, true);
- WM_event_add_notifier(C, NC_WINDOW, NULL);
+ BKE_id_reorder(&bmain->workspaces, &workspace->id, NULL, true);
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
static void WORKSPACE_OT_reorder_to_back(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Workspace Reorder to Back";
- ot->description = "Reorder workspace to be first in the list";
- ot->idname = "WORKSPACE_OT_reorder_to_back";
-
- /* api callbacks */
- ot->poll = workspace_context_poll;
- ot->exec = workspace_reorder_to_back_exec;
+ /* identifiers */
+ ot->name = "Workspace Reorder to Back";
+ ot->description = "Reorder workspace to be first in the list";
+ ot->idname = "WORKSPACE_OT_reorder_to_back";
+
+ /* api callbacks */
+ ot->poll = workspace_context_poll;
+ ot->exec = workspace_reorder_to_back_exec;
}
static int workspace_reorder_to_front_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- WorkSpace *workspace = workspace_context_get(C);
+ Main *bmain = CTX_data_main(C);
+ WorkSpace *workspace = workspace_context_get(C);
- BKE_id_reorder(&bmain->workspaces, &workspace->id, NULL, false);
- WM_event_add_notifier(C, NC_WINDOW, NULL);
+ BKE_id_reorder(&bmain->workspaces, &workspace->id, NULL, false);
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
static void WORKSPACE_OT_reorder_to_front(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Workspace Reorder to Front";
- ot->description = "Reorder workspace to be first in the list";
- ot->idname = "WORKSPACE_OT_reorder_to_front";
-
- /* api callbacks */
- ot->poll = workspace_context_poll;
- ot->exec = workspace_reorder_to_front_exec;
+ /* identifiers */
+ ot->name = "Workspace Reorder to Front";
+ ot->description = "Reorder workspace to be first in the list";
+ ot->idname = "WORKSPACE_OT_reorder_to_front";
+
+ /* api callbacks */
+ ot->poll = workspace_context_poll;
+ ot->exec = workspace_reorder_to_front_exec;
}
void ED_operatortypes_workspace(void)
{
- WM_operatortype_append(WORKSPACE_OT_duplicate);
- WM_operatortype_append(WORKSPACE_OT_delete);
- WM_operatortype_append(WORKSPACE_OT_add);
- WM_operatortype_append(WORKSPACE_OT_append_activate);
- WM_operatortype_append(WORKSPACE_OT_reorder_to_back);
- WM_operatortype_append(WORKSPACE_OT_reorder_to_front);
+ WM_operatortype_append(WORKSPACE_OT_duplicate);
+ WM_operatortype_append(WORKSPACE_OT_delete);
+ WM_operatortype_append(WORKSPACE_OT_add);
+ WM_operatortype_append(WORKSPACE_OT_append_activate);
+ WM_operatortype_append(WORKSPACE_OT_reorder_to_back);
+ WM_operatortype_append(WORKSPACE_OT_reorder_to_front);
}
/** \} Workspace Operators */
diff --git a/source/blender/editors/screen/workspace_layout_edit.c b/source/blender/editors/screen/workspace_layout_edit.c
index 401f0323af6..67ac5067134 100644
--- a/source/blender/editors/screen/workspace_layout_edit.c
+++ b/source/blender/editors/screen/workspace_layout_edit.c
@@ -40,164 +40,163 @@
/**
* Empty screen, with 1 dummy area without spacedata. Uses window size.
*/
-WorkSpaceLayout *ED_workspace_layout_add(
- Main *bmain,
- WorkSpace *workspace,
- wmWindow *win,
- const char *name)
+WorkSpaceLayout *ED_workspace_layout_add(Main *bmain,
+ WorkSpace *workspace,
+ wmWindow *win,
+ const char *name)
{
- bScreen *screen;
- rcti screen_rect;
+ bScreen *screen;
+ rcti screen_rect;
- WM_window_screen_rect_calc(win, &screen_rect);
- screen = screen_add(bmain, name, &screen_rect);
+ WM_window_screen_rect_calc(win, &screen_rect);
+ screen = screen_add(bmain, name, &screen_rect);
- return BKE_workspace_layout_add(bmain, workspace, screen, name);
+ return BKE_workspace_layout_add(bmain, workspace, screen, name);
}
-WorkSpaceLayout *ED_workspace_layout_duplicate(
- Main *bmain,
- WorkSpace *workspace, const WorkSpaceLayout *layout_old,
- wmWindow *win)
+WorkSpaceLayout *ED_workspace_layout_duplicate(Main *bmain,
+ WorkSpace *workspace,
+ const WorkSpaceLayout *layout_old,
+ wmWindow *win)
{
- bScreen *screen_old = BKE_workspace_layout_screen_get(layout_old);
- const char *name = BKE_workspace_layout_name_get(layout_old);
- bScreen *screen_new;
- WorkSpaceLayout *layout_new;
-
- layout_new = ED_workspace_layout_add(bmain, workspace, win, name);
- 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) {
- if (area_old->full) {
- ScrArea *area_new = (ScrArea *)screen_new->areabase.first;
- ED_area_data_copy(area_new, area_old, true);
- ED_area_tag_redraw(area_new);
- break;
- }
- }
- }
- else {
- screen_data_copy(screen_new, screen_old);
- }
-
- return layout_new;
+ bScreen *screen_old = BKE_workspace_layout_screen_get(layout_old);
+ const char *name = BKE_workspace_layout_name_get(layout_old);
+ bScreen *screen_new;
+ WorkSpaceLayout *layout_new;
+
+ layout_new = ED_workspace_layout_add(bmain, workspace, win, name);
+ 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) {
+ if (area_old->full) {
+ ScrArea *area_new = (ScrArea *)screen_new->areabase.first;
+ ED_area_data_copy(area_new, area_old, true);
+ ED_area_tag_redraw(area_new);
+ break;
+ }
+ }
+ }
+ else {
+ screen_data_copy(screen_new, screen_old);
+ }
+
+ return layout_new;
}
-static bool workspace_layout_delete_doit(
- WorkSpace *workspace, WorkSpaceLayout *layout_old, WorkSpaceLayout *layout_new,
- bContext *C)
+static bool workspace_layout_delete_doit(WorkSpace *workspace,
+ WorkSpaceLayout *layout_old,
+ WorkSpaceLayout *layout_new,
+ bContext *C)
{
- Main *bmain = CTX_data_main(C);
- wmWindow *win = CTX_wm_window(C);
- bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new);
+ Main *bmain = CTX_data_main(C);
+ wmWindow *win = CTX_wm_window(C);
+ bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new);
- ED_screen_change(C, screen_new);
+ ED_screen_change(C, screen_new);
- if (BKE_workspace_active_layout_get(win->workspace_hook) != layout_old) {
- BKE_workspace_layout_remove(bmain, workspace, layout_old);
- return true;
- }
+ if (BKE_workspace_active_layout_get(win->workspace_hook) != layout_old) {
+ BKE_workspace_layout_remove(bmain, workspace, layout_old);
+ return true;
+ }
- return false;
+ return false;
}
bool workspace_layout_set_poll(const WorkSpaceLayout *layout)
{
- const bScreen *screen = BKE_workspace_layout_screen_get(layout);
-
- return ((BKE_screen_is_used(screen) == false) &&
- /* in typical usage temp screens should have a nonzero winid
- * (all temp screens should be used, or closed & freed). */
- (screen->temp == false) &&
- (BKE_screen_is_fullscreen_area(screen) == false) &&
- (screen->id.name[2] != '.' || !(U.uiflag & USER_HIDE_DOT)));
+ const bScreen *screen = BKE_workspace_layout_screen_get(layout);
+
+ return ((BKE_screen_is_used(screen) == false) &&
+ /* in typical usage temp screens should have a nonzero winid
+ * (all temp screens should be used, or closed & freed). */
+ (screen->temp == false) && (BKE_screen_is_fullscreen_area(screen) == false) &&
+ (screen->id.name[2] != '.' || !(U.uiflag & USER_HIDE_DOT)));
}
static WorkSpaceLayout *workspace_layout_delete_find_new(const WorkSpaceLayout *layout_old)
{
- for (WorkSpaceLayout *layout_new = layout_old->prev; layout_new; layout_new = layout_new->next) {
- if (workspace_layout_set_poll(layout_new)) {
- return layout_new;
- }
- }
-
- for (WorkSpaceLayout *layout_new = layout_old->next; layout_new; layout_new = layout_new->next) {
- if (workspace_layout_set_poll(layout_new)) {
- return layout_new;
- }
- }
-
- return NULL;
+ for (WorkSpaceLayout *layout_new = layout_old->prev; layout_new; layout_new = layout_new->next) {
+ if (workspace_layout_set_poll(layout_new)) {
+ return layout_new;
+ }
+ }
+
+ for (WorkSpaceLayout *layout_new = layout_old->next; layout_new; layout_new = layout_new->next) {
+ if (workspace_layout_set_poll(layout_new)) {
+ return layout_new;
+ }
+ }
+
+ return NULL;
}
/**
* \warning Only call outside of area/region loops!
* \return true if succeeded.
*/
-bool ED_workspace_layout_delete(
- WorkSpace *workspace, WorkSpaceLayout *layout_old,
- bContext *C)
+bool ED_workspace_layout_delete(WorkSpace *workspace, WorkSpaceLayout *layout_old, bContext *C)
{
- const bScreen *screen_old = BKE_workspace_layout_screen_get(layout_old);
- WorkSpaceLayout *layout_new;
+ const bScreen *screen_old = BKE_workspace_layout_screen_get(layout_old);
+ WorkSpaceLayout *layout_new;
- BLI_assert(BLI_findindex(BKE_workspace_layouts_get(workspace), layout_old) != -1);
+ BLI_assert(BLI_findindex(BKE_workspace_layouts_get(workspace), layout_old) != -1);
- /* don't allow deleting temp fullscreens for now */
- if (BKE_screen_is_fullscreen_area(screen_old)) {
- return false;
- }
+ /* don't allow deleting temp fullscreens for now */
+ if (BKE_screen_is_fullscreen_area(screen_old)) {
+ return false;
+ }
- /* A layout/screen can only be in use by one window at a time, so as
- * long as we are able to find a layout/screen that is unused, we
- * can safely assume ours is not in use anywhere an delete it. */
+ /* A layout/screen can only be in use by one window at a time, so as
+ * long as we are able to find a layout/screen that is unused, we
+ * can safely assume ours is not in use anywhere an delete it. */
- layout_new = workspace_layout_delete_find_new(layout_old);
+ layout_new = workspace_layout_delete_find_new(layout_old);
- if (layout_new) {
- return workspace_layout_delete_doit(workspace, layout_old, layout_new, C);
- }
+ if (layout_new) {
+ return workspace_layout_delete_doit(workspace, layout_old, layout_new, C);
+ }
- return false;
+ return false;
}
static bool workspace_layout_cycle_iter_cb(const WorkSpaceLayout *layout, void *UNUSED(arg))
{
- /* return false to stop iterator when we have found a layout to activate */
- return !workspace_layout_set_poll(layout);
+ /* return false to stop iterator when we have found a layout to activate */
+ return !workspace_layout_set_poll(layout);
}
-bool ED_workspace_layout_cycle(
- WorkSpace *workspace, const short direction, bContext *C)
+bool ED_workspace_layout_cycle(WorkSpace *workspace, const short direction, bContext *C)
{
- wmWindow *win = CTX_wm_window(C);
- 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);
+ wmWindow *win = CTX_wm_window(C);
+ 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);
- if (old_screen->temp || (sa && sa->full && sa->full->temp)) {
- return false;
- }
+ if (old_screen->temp || (sa && sa->full && sa->full->temp)) {
+ return false;
+ }
- BLI_assert(ELEM(direction, 1, -1));
- new_layout = BKE_workspace_layout_iter_circular(workspace, old_layout, workspace_layout_cycle_iter_cb,
- NULL, (direction == -1) ? true : false);
+ BLI_assert(ELEM(direction, 1, -1));
+ new_layout = BKE_workspace_layout_iter_circular(workspace,
+ old_layout,
+ workspace_layout_cycle_iter_cb,
+ NULL,
+ (direction == -1) ? true : false);
- if (new_layout && (old_layout != new_layout)) {
- bScreen *new_screen = BKE_workspace_layout_screen_get(new_layout);
+ if (new_layout && (old_layout != new_layout)) {
+ bScreen *new_screen = BKE_workspace_layout_screen_get(new_layout);
- if (sa && sa->full) {
- /* return to previous state before switching screens */
- ED_screen_full_restore(C, sa); /* may free screen of old_layout */
- }
+ if (sa && sa->full) {
+ /* return to previous state before switching screens */
+ ED_screen_full_restore(C, sa); /* may free screen of old_layout */
+ }
- ED_screen_change(C, new_screen);
+ ED_screen_change(C, new_screen);
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index e7a8c704fda..cddaf69b965 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -16,61 +16,61 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../uvedit
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../bmesh
- ../../depsgraph
- ../../gpu
- ../../imbuf
- ../../makesdna
- ../../makesrna
- ../../render/extern/include
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../uvedit
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../bmesh
+ ../../depsgraph
+ ../../gpu
+ ../../imbuf
+ ../../makesdna
+ ../../makesrna
+ ../../render/extern/include
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- paint_cursor.c
- paint_curve.c
- paint_curve_undo.c
- paint_hide.c
- paint_image.c
- paint_image_2d.c
- paint_image_proj.c
- paint_image_undo.c
- paint_mask.c
- paint_ops.c
- paint_stroke.c
- paint_utils.c
- paint_vertex.c
- paint_vertex_color_ops.c
- paint_vertex_color_utils.c
- paint_vertex_proj.c
- paint_vertex_weight_ops.c
- paint_vertex_weight_utils.c
- sculpt.c
- sculpt_undo.c
- sculpt_uv.c
+ paint_cursor.c
+ paint_curve.c
+ paint_curve_undo.c
+ paint_hide.c
+ paint_image.c
+ paint_image_2d.c
+ paint_image_proj.c
+ paint_image_undo.c
+ paint_mask.c
+ paint_ops.c
+ paint_stroke.c
+ paint_utils.c
+ paint_vertex.c
+ paint_vertex_color_ops.c
+ paint_vertex_color_utils.c
+ paint_vertex_proj.c
+ paint_vertex_weight_ops.c
+ paint_vertex_weight_utils.c
+ sculpt.c
+ sculpt_undo.c
+ sculpt_uv.c
- paint_intern.h
- sculpt_intern.h
+ paint_intern.h
+ sculpt_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
+ bf_blenkernel
+ bf_blenlib
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 4b714e03d3b..da183d190fa 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -75,1103 +75,1101 @@
*/
typedef struct TexSnapshot {
- GLuint overlay_texture;
- int winx;
- int winy;
- int old_size;
- float old_zoom;
- bool old_col;
+ GLuint overlay_texture;
+ int winx;
+ int winy;
+ int old_size;
+ float old_zoom;
+ bool old_col;
} TexSnapshot;
typedef struct CursorSnapshot {
- GLuint overlay_texture;
- int size;
- int zoom;
+ GLuint overlay_texture;
+ int size;
+ int zoom;
} CursorSnapshot;
static TexSnapshot primary_snap = {0};
-static TexSnapshot secondary_snap = {0};
-static CursorSnapshot cursor_snap = {0};
+static TexSnapshot secondary_snap = {0};
+static CursorSnapshot cursor_snap = {0};
/* delete overlay cursor textures to preserve memory and invalidate all overlay flags */
void paint_cursor_delete_textures(void)
{
- if (primary_snap.overlay_texture)
- glDeleteTextures(1, &primary_snap.overlay_texture);
- if (secondary_snap.overlay_texture)
- glDeleteTextures(1, &secondary_snap.overlay_texture);
- if (cursor_snap.overlay_texture)
- glDeleteTextures(1, &cursor_snap.overlay_texture);
-
- memset(&primary_snap, 0, sizeof(TexSnapshot));
- memset(&secondary_snap, 0, sizeof(TexSnapshot));
- memset(&cursor_snap, 0, sizeof(CursorSnapshot));
-
- BKE_paint_invalidate_overlay_all();
+ if (primary_snap.overlay_texture)
+ glDeleteTextures(1, &primary_snap.overlay_texture);
+ if (secondary_snap.overlay_texture)
+ glDeleteTextures(1, &secondary_snap.overlay_texture);
+ if (cursor_snap.overlay_texture)
+ glDeleteTextures(1, &cursor_snap.overlay_texture);
+
+ memset(&primary_snap, 0, sizeof(TexSnapshot));
+ memset(&secondary_snap, 0, sizeof(TexSnapshot));
+ memset(&cursor_snap, 0, sizeof(CursorSnapshot));
+
+ BKE_paint_invalidate_overlay_all();
}
static int same_tex_snap(TexSnapshot *snap, MTex *mtex, ViewContext *vc, bool col, float zoom)
{
- return (/* make brush smaller shouldn't cause a resample */
- //(mtex->brush_map_mode != MTEX_MAP_MODE_VIEW ||
- //(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)) &&
- (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL ||
- snap->old_zoom == zoom) &&
- snap->old_col == col
- );
+ return (/* make brush smaller shouldn't cause a resample */
+ //(mtex->brush_map_mode != MTEX_MAP_MODE_VIEW ||
+ //(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)) &&
+ (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL || snap->old_zoom == zoom) &&
+ snap->old_col == col);
}
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->old_zoom = zoom;
+ snap->winx = vc->ar->winx;
+ snap->winy = vc->ar->winy;
}
typedef struct LoadTexData {
- Brush *br;
- ViewContext *vc;
+ Brush *br;
+ ViewContext *vc;
- MTex *mtex;
- GLubyte *buffer;
- bool col;
+ MTex *mtex;
+ GLubyte *buffer;
+ bool col;
- struct ImagePool *pool;
- int size;
- float rotation;
- float radius;
+ struct ImagePool *pool;
+ int size;
+ float rotation;
+ float radius;
} LoadTexData;
-static void load_tex_task_cb_ex(
- void *__restrict userdata,
- const int j,
- const ParallelRangeTLS *__restrict tls)
+static void load_tex_task_cb_ex(void *__restrict userdata,
+ const int j,
+ const ParallelRangeTLS *__restrict tls)
{
- LoadTexData *data = userdata;
- Brush *br = data->br;
- ViewContext *vc = data->vc;
-
- MTex *mtex = data->mtex;
- GLubyte *buffer = data->buffer;
- const bool col = data->col;
-
- struct ImagePool *pool = data->pool;
- const int size = data->size;
- const float rotation = data->rotation;
- const float radius = data->radius;
-
- bool convert_to_linear = false;
- struct ColorSpace *colorspace = NULL;
-
- 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 */
- if (tex_ibuf && tex_ibuf->rect_float == NULL) {
- convert_to_linear = true;
- colorspace = tex_ibuf->rect_colorspace;
- }
- BKE_image_pool_release_ibuf(mtex->tex->ima, tex_ibuf, pool);
- }
-
- for (int i = 0; i < size; i++) {
- // largely duplicated from tex_strength
-
- int index = j * size + i;
-
- float x = (float)i / size;
- float y = (float)j / size;
- float len;
-
- if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) {
- x *= vc->ar->winx / radius;
- y *= vc->ar->winy / radius;
- }
- else {
- x = (x - 0.5f) * 2.0f;
- y = (y - 0.5f) * 2.0f;
- }
-
- len = sqrtf(x * x + y * y);
-
- if (ELEM(mtex->brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_STENCIL) || len <= 1.0f) {
- /* it is probably worth optimizing for those cases where the texture is not rotated by skipping the calls to
- * atan2, sqrtf, sin, and cos. */
- if (mtex->tex && (rotation > 0.001f || rotation < -0.001f)) {
- const float angle = atan2f(y, x) + rotation;
-
- x = len * cosf(angle);
- y = len * sinf(angle);
- }
-
- if (col) {
- float rgba[4];
-
- paint_get_tex_pixel_col(mtex, x, y, rgba, pool, tls->thread_id, convert_to_linear, colorspace);
-
- buffer[index * 4] = rgba[0] * 255;
- buffer[index * 4 + 1] = rgba[1] * 255;
- buffer[index * 4 + 2] = rgba[2] * 255;
- buffer[index * 4 + 3] = rgba[3] * 255;
- }
- else {
- float avg = paint_get_tex_pixel(mtex, x, y, pool, tls->thread_id);
-
- avg += br->texture_sample_bias;
-
- /* clamp to avoid precision overflow */
- CLAMP(avg, 0.0f, 1.0f);
- buffer[index] = 255 - (GLubyte)(255 * avg);
- }
- }
- else {
- if (col) {
- buffer[index * 4] = 0;
- buffer[index * 4 + 1] = 0;
- buffer[index * 4 + 2] = 0;
- buffer[index * 4 + 3] = 0;
- }
- else {
- buffer[index] = 0;
- }
- }
- }
+ LoadTexData *data = userdata;
+ Brush *br = data->br;
+ ViewContext *vc = data->vc;
+
+ MTex *mtex = data->mtex;
+ GLubyte *buffer = data->buffer;
+ const bool col = data->col;
+
+ struct ImagePool *pool = data->pool;
+ const int size = data->size;
+ const float rotation = data->rotation;
+ const float radius = data->radius;
+
+ bool convert_to_linear = false;
+ struct ColorSpace *colorspace = NULL;
+
+ 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 */
+ if (tex_ibuf && tex_ibuf->rect_float == NULL) {
+ convert_to_linear = true;
+ colorspace = tex_ibuf->rect_colorspace;
+ }
+ BKE_image_pool_release_ibuf(mtex->tex->ima, tex_ibuf, pool);
+ }
+
+ for (int i = 0; i < size; i++) {
+ // largely duplicated from tex_strength
+
+ int index = j * size + i;
+
+ float x = (float)i / size;
+ float y = (float)j / size;
+ float len;
+
+ if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) {
+ x *= vc->ar->winx / radius;
+ y *= vc->ar->winy / radius;
+ }
+ else {
+ x = (x - 0.5f) * 2.0f;
+ y = (y - 0.5f) * 2.0f;
+ }
+
+ len = sqrtf(x * x + y * y);
+
+ if (ELEM(mtex->brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_STENCIL) || len <= 1.0f) {
+ /* it is probably worth optimizing for those cases where the texture is not rotated by skipping the calls to
+ * atan2, sqrtf, sin, and cos. */
+ if (mtex->tex && (rotation > 0.001f || rotation < -0.001f)) {
+ const float angle = atan2f(y, x) + rotation;
+
+ x = len * cosf(angle);
+ y = len * sinf(angle);
+ }
+
+ if (col) {
+ float rgba[4];
+
+ paint_get_tex_pixel_col(
+ mtex, x, y, rgba, pool, tls->thread_id, convert_to_linear, colorspace);
+
+ buffer[index * 4] = rgba[0] * 255;
+ buffer[index * 4 + 1] = rgba[1] * 255;
+ buffer[index * 4 + 2] = rgba[2] * 255;
+ buffer[index * 4 + 3] = rgba[3] * 255;
+ }
+ else {
+ float avg = paint_get_tex_pixel(mtex, x, y, pool, tls->thread_id);
+
+ avg += br->texture_sample_bias;
+
+ /* clamp to avoid precision overflow */
+ CLAMP(avg, 0.0f, 1.0f);
+ buffer[index] = 255 - (GLubyte)(255 * avg);
+ }
+ }
+ else {
+ if (col) {
+ buffer[index * 4] = 0;
+ buffer[index * 4 + 1] = 0;
+ buffer[index * 4 + 2] = 0;
+ buffer[index * 4 + 3] = 0;
+ }
+ else {
+ buffer[index] = 0;
+ }
+ }
+ }
}
static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool primary)
{
- bool init;
- TexSnapshot *target;
-
- MTex *mtex = (primary) ? &br->mtex : &br->mask_mtex;
- eOverlayControlFlags overlay_flags = BKE_paint_get_overlay_flags();
- GLubyte *buffer = NULL;
-
- int size;
- bool refresh;
- eOverlayControlFlags invalid = (
- (primary) ?
- (overlay_flags & PAINT_OVERLAY_INVALID_TEXTURE_PRIMARY) :
- (overlay_flags & PAINT_OVERLAY_INVALID_TEXTURE_SECONDARY));
- target = (primary) ? &primary_snap : &secondary_snap;
-
- refresh =
- !target->overlay_texture ||
- (invalid != 0) ||
- !same_tex_snap(target, mtex, vc, col, zoom);
-
- init = (target->overlay_texture != 0);
-
- if (refresh) {
- struct ImagePool *pool = NULL;
- /* 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;
-
- make_tex_snap(target, vc, zoom);
-
- if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
- int s = BKE_brush_size_get(vc->scene, br);
- int r = 1;
-
- for (s >>= 1; s > 0; s >>= 1)
- r++;
-
- size = (1 << r);
-
- if (size < 256)
- size = 256;
-
- if (size < target->old_size)
- size = target->old_size;
- }
- else {
- size = 512;
- }
-
- if (target->old_size != size) {
- if (target->overlay_texture) {
- glDeleteTextures(1, &target->overlay_texture);
- target->overlay_texture = 0;
- }
-
- init = false;
-
- target->old_size = size;
- }
- if (col)
- buffer = MEM_mallocN(sizeof(GLubyte) * size * size * 4, "load_tex");
- else
- buffer = MEM_mallocN(sizeof(GLubyte) * size * size, "load_tex");
-
- pool = BKE_image_pool_new();
-
- if (mtex->tex && mtex->tex->nodetree) {
- /* has internal flag to detect it only does it once */
- ntreeTexBeginExecTree(mtex->tex->nodetree);
- }
-
- LoadTexData data = {
- .br = br, .vc = vc, .mtex = mtex, .buffer = buffer, .col = col,
- .pool = pool, .size = size, .rotation = rotation, .radius = radius,
- };
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- BLI_task_parallel_range(0, size, &data, load_tex_task_cb_ex, &settings);
-
- if (mtex->tex && mtex->tex->nodetree)
- ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
-
- if (pool)
- BKE_image_pool_free(pool);
-
- if (!target->overlay_texture)
- glGenTextures(1, &target->overlay_texture);
- }
- else {
- size = target->old_size;
- }
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, target->overlay_texture);
-
- if (refresh) {
- GLenum format = col ? GL_RGBA : GL_RED;
- GLenum internalformat = col ? GL_RGBA8 : GL_R8;
-
- if (!init || (target->old_col != col)) {
- glTexImage2D(GL_TEXTURE_2D, 0, internalformat, size, size, 0, format, GL_UNSIGNED_BYTE, buffer);
- }
- else {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, format, GL_UNSIGNED_BYTE, buffer);
- }
-
- if (buffer)
- MEM_freeN(buffer);
-
- target->old_col = col;
- }
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
- if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
- }
-
- BKE_paint_reset_overlay_invalid(invalid);
-
- return 1;
+ bool init;
+ TexSnapshot *target;
+
+ MTex *mtex = (primary) ? &br->mtex : &br->mask_mtex;
+ eOverlayControlFlags overlay_flags = BKE_paint_get_overlay_flags();
+ GLubyte *buffer = NULL;
+
+ int size;
+ bool refresh;
+ eOverlayControlFlags invalid = ((primary) ?
+ (overlay_flags & PAINT_OVERLAY_INVALID_TEXTURE_PRIMARY) :
+ (overlay_flags & PAINT_OVERLAY_INVALID_TEXTURE_SECONDARY));
+ target = (primary) ? &primary_snap : &secondary_snap;
+
+ refresh = !target->overlay_texture || (invalid != 0) ||
+ !same_tex_snap(target, mtex, vc, col, zoom);
+
+ init = (target->overlay_texture != 0);
+
+ if (refresh) {
+ struct ImagePool *pool = NULL;
+ /* 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;
+
+ make_tex_snap(target, vc, zoom);
+
+ if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
+ int s = BKE_brush_size_get(vc->scene, br);
+ int r = 1;
+
+ for (s >>= 1; s > 0; s >>= 1)
+ r++;
+
+ size = (1 << r);
+
+ if (size < 256)
+ size = 256;
+
+ if (size < target->old_size)
+ size = target->old_size;
+ }
+ else {
+ size = 512;
+ }
+
+ if (target->old_size != size) {
+ if (target->overlay_texture) {
+ glDeleteTextures(1, &target->overlay_texture);
+ target->overlay_texture = 0;
+ }
+
+ init = false;
+
+ target->old_size = size;
+ }
+ if (col)
+ buffer = MEM_mallocN(sizeof(GLubyte) * size * size * 4, "load_tex");
+ else
+ buffer = MEM_mallocN(sizeof(GLubyte) * size * size, "load_tex");
+
+ pool = BKE_image_pool_new();
+
+ if (mtex->tex && mtex->tex->nodetree) {
+ /* has internal flag to detect it only does it once */
+ ntreeTexBeginExecTree(mtex->tex->nodetree);
+ }
+
+ LoadTexData data = {
+ .br = br,
+ .vc = vc,
+ .mtex = mtex,
+ .buffer = buffer,
+ .col = col,
+ .pool = pool,
+ .size = size,
+ .rotation = rotation,
+ .radius = radius,
+ };
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ BLI_task_parallel_range(0, size, &data, load_tex_task_cb_ex, &settings);
+
+ if (mtex->tex && mtex->tex->nodetree)
+ ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
+
+ if (pool)
+ BKE_image_pool_free(pool);
+
+ if (!target->overlay_texture)
+ glGenTextures(1, &target->overlay_texture);
+ }
+ else {
+ size = target->old_size;
+ }
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, target->overlay_texture);
+
+ if (refresh) {
+ GLenum format = col ? GL_RGBA : GL_RED;
+ GLenum internalformat = col ? GL_RGBA8 : GL_R8;
+
+ if (!init || (target->old_col != col)) {
+ glTexImage2D(
+ GL_TEXTURE_2D, 0, internalformat, size, size, 0, format, GL_UNSIGNED_BYTE, buffer);
+ }
+ else {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, format, GL_UNSIGNED_BYTE, buffer);
+ }
+
+ if (buffer)
+ MEM_freeN(buffer);
+
+ target->old_col = col;
+ }
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+ }
+
+ BKE_paint_reset_overlay_invalid(invalid);
+
+ return 1;
}
-static void load_tex_cursor_task_cb(
- void *__restrict userdata,
- const int j,
- const ParallelRangeTLS *__restrict UNUSED(tls))
+static void load_tex_cursor_task_cb(void *__restrict userdata,
+ const int j,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
{
- LoadTexData *data = userdata;
- Brush *br = data->br;
+ LoadTexData *data = userdata;
+ Brush *br = data->br;
- GLubyte *buffer = data->buffer;
+ GLubyte *buffer = data->buffer;
- const int size = data->size;
+ const int size = data->size;
- for (int i = 0; i < size; i++) {
- // largely duplicated from tex_strength
+ for (int i = 0; i < size; i++) {
+ // largely duplicated from tex_strength
- const int index = j * size + i;
- const float x = (((float)i / size) - 0.5f) * 2.0f;
- const float y = (((float)j / size) - 0.5f) * 2.0f;
- const float len = sqrtf(x * x + y * y);
+ const int index = j * size + i;
+ const float x = (((float)i / size) - 0.5f) * 2.0f;
+ const float y = (((float)j / size) - 0.5f) * 2.0f;
+ 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 */
+ if (len <= 1.0f) {
+ float avg = BKE_brush_curve_strength_clamped(br, len, 1.0f); /* Falloff curve */
- buffer[index] = 255 - (GLubyte)(255 * avg);
- }
- else {
- buffer[index] = 0;
- }
- }
+ buffer[index] = 255 - (GLubyte)(255 * avg);
+ }
+ else {
+ buffer[index] = 0;
+ }
+ }
}
static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
{
- bool init;
+ bool init;
- eOverlayControlFlags overlay_flags = BKE_paint_get_overlay_flags();
- GLubyte *buffer = NULL;
+ eOverlayControlFlags overlay_flags = BKE_paint_get_overlay_flags();
+ GLubyte *buffer = NULL;
- int size;
- const bool refresh =
- !cursor_snap.overlay_texture ||
- (overlay_flags & PAINT_OVERLAY_INVALID_CURVE) ||
- cursor_snap.zoom != zoom;
+ int size;
+ const bool refresh = !cursor_snap.overlay_texture ||
+ (overlay_flags & PAINT_OVERLAY_INVALID_CURVE) || cursor_snap.zoom != zoom;
- init = (cursor_snap.overlay_texture != 0);
+ init = (cursor_snap.overlay_texture != 0);
- if (refresh) {
- int s, r;
+ if (refresh) {
+ int s, r;
- cursor_snap.zoom = zoom;
+ cursor_snap.zoom = zoom;
- s = BKE_brush_size_get(vc->scene, br);
- r = 1;
+ s = BKE_brush_size_get(vc->scene, br);
+ r = 1;
- for (s >>= 1; s > 0; s >>= 1)
- r++;
+ for (s >>= 1; s > 0; s >>= 1)
+ r++;
- size = (1 << r);
+ size = (1 << r);
- if (size < 256)
- size = 256;
+ if (size < 256)
+ size = 256;
- if (size < cursor_snap.size)
- size = cursor_snap.size;
+ if (size < cursor_snap.size)
+ size = cursor_snap.size;
- if (cursor_snap.size != size) {
- if (cursor_snap.overlay_texture) {
- glDeleteTextures(1, &cursor_snap.overlay_texture);
- cursor_snap.overlay_texture = 0;
- }
+ if (cursor_snap.size != size) {
+ if (cursor_snap.overlay_texture) {
+ glDeleteTextures(1, &cursor_snap.overlay_texture);
+ cursor_snap.overlay_texture = 0;
+ }
- init = false;
+ init = false;
- cursor_snap.size = size;
- }
- buffer = MEM_mallocN(sizeof(GLubyte) * size * size, "load_tex");
+ cursor_snap.size = size;
+ }
+ buffer = MEM_mallocN(sizeof(GLubyte) * size * size, "load_tex");
- curvemapping_initialize(br->curve);
+ curvemapping_initialize(br->curve);
- LoadTexData data = {
- .br = br, .buffer = buffer, .size = size,
- };
+ LoadTexData data = {
+ .br = br,
+ .buffer = buffer,
+ .size = size,
+ };
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- BLI_task_parallel_range(0, size, &data, load_tex_cursor_task_cb, &settings);
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ BLI_task_parallel_range(0, size, &data, load_tex_cursor_task_cb, &settings);
- if (!cursor_snap.overlay_texture)
- glGenTextures(1, &cursor_snap.overlay_texture);
- }
- else {
- size = cursor_snap.size;
- }
+ if (!cursor_snap.overlay_texture)
+ glGenTextures(1, &cursor_snap.overlay_texture);
+ }
+ else {
+ size = cursor_snap.size;
+ }
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, cursor_snap.overlay_texture);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, cursor_snap.overlay_texture);
- if (refresh) {
- if (!init) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, size, size, 0, GL_RED, GL_UNSIGNED_BYTE, buffer);
- }
- else {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, GL_RED, GL_UNSIGNED_BYTE, buffer);
- }
+ if (refresh) {
+ if (!init) {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, size, size, 0, GL_RED, GL_UNSIGNED_BYTE, buffer);
+ }
+ else {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, GL_RED, GL_UNSIGNED_BYTE, buffer);
+ }
- if (buffer)
- MEM_freeN(buffer);
- }
+ if (buffer)
+ MEM_freeN(buffer);
+ }
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
- BKE_paint_reset_overlay_invalid(PAINT_OVERLAY_INVALID_CURVE);
+ BKE_paint_reset_overlay_invalid(PAINT_OVERLAY_INVALID_CURVE);
- return 1;
+ return 1;
}
-
-
-static int project_brush_radius(
- ViewContext *vc,
- float radius,
- const float location[3])
+static int project_brush_radius(ViewContext *vc, float radius, const float location[3])
{
- float view[3], nonortho[3], ortho[3], offset[3], p1[2], p2[2];
-
- ED_view3d_global_to_vector(vc->rv3d, location, view);
-
- /* create a vector that is not orthogonal to view */
-
- if (fabsf(view[0]) < 0.1f) {
- nonortho[0] = view[0] + 1.0f;
- nonortho[1] = view[1];
- nonortho[2] = view[2];
- }
- else if (fabsf(view[1]) < 0.1f) {
- nonortho[0] = view[0];
- nonortho[1] = view[1] + 1.0f;
- nonortho[2] = view[2];
- }
- else {
- nonortho[0] = view[0];
- nonortho[1] = view[1];
- nonortho[2] = view[2] + 1.0f;
- }
-
- /* 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 */
- 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) == 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 */
- return len_v2v2(p1, p2);
- }
- else {
- BLI_assert(0); /* assert because the code that sets up the vectors should disallow this */
- return 0;
- }
+ float view[3], nonortho[3], ortho[3], offset[3], p1[2], p2[2];
+
+ ED_view3d_global_to_vector(vc->rv3d, location, view);
+
+ /* create a vector that is not orthogonal to view */
+
+ if (fabsf(view[0]) < 0.1f) {
+ nonortho[0] = view[0] + 1.0f;
+ nonortho[1] = view[1];
+ nonortho[2] = view[2];
+ }
+ else if (fabsf(view[1]) < 0.1f) {
+ nonortho[0] = view[0];
+ nonortho[1] = view[1] + 1.0f;
+ nonortho[2] = view[2];
+ }
+ else {
+ nonortho[0] = view[0];
+ nonortho[1] = view[1];
+ nonortho[2] = view[2] + 1.0f;
+ }
+
+ /* 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 */
+ 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) ==
+ 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 */
+ return len_v2v2(p1, p2);
+ }
+ else {
+ BLI_assert(0); /* assert because the code that sets up the vectors should disallow this */
+ return 0;
+ }
}
-static bool sculpt_get_brush_geometry(
- bContext *C, ViewContext *vc,
- int x, int y, int *pixel_radius,
- float location[3], UnifiedPaintSettings *ups)
+static bool sculpt_get_brush_geometry(bContext *C,
+ ViewContext *vc,
+ int x,
+ int y,
+ int *pixel_radius,
+ float location[3],
+ UnifiedPaintSettings *ups)
{
- Scene *scene = CTX_data_scene(C);
- Paint *paint = BKE_paint_get_active_from_context(C);
- float mouse[2];
- bool hit = false;
-
- mouse[0] = x;
- mouse[1] = y;
-
- if (vc->obact->sculpt && vc->obact->sculpt->pbvh) {
- if (!ups->stroke_active) {
- hit = sculpt_stroke_get_location(C, location, mouse);
- }
- else {
- hit = ups->last_hit;
- copy_v3_v3(location, ups->last_location);
- }
- }
-
- if (hit) {
- Brush *brush = BKE_paint_brush(paint);
-
- *pixel_radius = project_brush_radius(
- vc, BKE_brush_unprojected_radius_get(scene, brush), location);
-
- if (*pixel_radius == 0)
- *pixel_radius = BKE_brush_size_get(scene, brush);
-
- mul_m4_v3(vc->obact->obmat, location);
- }
- else {
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
-
- *pixel_radius = BKE_brush_size_get(scene, brush);
- }
-
- return hit;
+ Scene *scene = CTX_data_scene(C);
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ float mouse[2];
+ bool hit = false;
+
+ mouse[0] = x;
+ mouse[1] = y;
+
+ if (vc->obact->sculpt && vc->obact->sculpt->pbvh) {
+ if (!ups->stroke_active) {
+ hit = sculpt_stroke_get_location(C, location, mouse);
+ }
+ else {
+ hit = ups->last_hit;
+ copy_v3_v3(location, ups->last_location);
+ }
+ }
+
+ if (hit) {
+ Brush *brush = BKE_paint_brush(paint);
+
+ *pixel_radius = project_brush_radius(
+ vc, BKE_brush_unprojected_radius_get(scene, brush), location);
+
+ if (*pixel_radius == 0)
+ *pixel_radius = BKE_brush_size_get(scene, brush);
+
+ mul_m4_v3(vc->obact->obmat, location);
+ }
+ else {
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ *pixel_radius = BKE_brush_size_get(scene, brush);
+ }
+
+ return hit;
}
/* Draw an overlay that shows what effect the brush's texture will
* have on brush strength */
-static void paint_draw_tex_overlay(
- UnifiedPaintSettings *ups, Brush *brush,
- ViewContext *vc, int x, int y, float zoom, bool col, bool primary)
+static void paint_draw_tex_overlay(UnifiedPaintSettings *ups,
+ Brush *brush,
+ ViewContext *vc,
+ int x,
+ int y,
+ float zoom,
+ bool col,
+ bool primary)
{
- rctf quad;
- /* check for overlay mode */
-
- MTex *mtex = (primary) ? &brush->mtex : &brush->mask_mtex;
- bool valid = (
- (primary) ?
- (brush->overlay_flags & BRUSH_OVERLAY_PRIMARY) != 0 :
- (brush->overlay_flags & BRUSH_OVERLAY_SECONDARY) != 0);
- int overlay_alpha = (primary) ? brush->texture_overlay_alpha : brush->mask_overlay_alpha;
-
- if (!(mtex->tex) || !((mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) ||
- (valid &&
- ELEM(mtex->brush_map_mode, MTEX_MAP_MODE_VIEW, MTEX_MAP_MODE_TILED))))
- {
- return;
- }
-
- if (load_tex(brush, vc, zoom, col, primary)) {
- GPU_blend(true);
-
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glDepthMask(GL_FALSE);
- glDepthFunc(GL_ALWAYS);
-
- if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
- GPU_matrix_push();
-
- /* 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 */
- if (primary && ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) {
- const float scale = ups->size_pressure_value;
- GPU_matrix_translate_2f(x, y);
- GPU_matrix_scale_2f(scale, scale);
- GPU_matrix_translate_2f(-x, -y);
- }
-
- if (ups->draw_anchored) {
- quad.xmin = ups->anchored_initial_mouse[0] - ups->anchored_size;
- quad.ymin = ups->anchored_initial_mouse[1] - ups->anchored_size;
- quad.xmax = ups->anchored_initial_mouse[0] + ups->anchored_size;
- quad.ymax = ups->anchored_initial_mouse[1] + ups->anchored_size;
- }
- else {
- const int radius = BKE_brush_size_get(vc->scene, brush) * zoom;
- quad.xmin = x - radius;
- quad.ymin = y - radius;
- quad.xmax = x + radius;
- quad.ymax = y + radius;
- }
- }
- 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);
- }
- /* Stencil code goes here */
- else {
- if (primary) {
- quad.xmin = -brush->stencil_dimension[0];
- quad.ymin = -brush->stencil_dimension[1];
- quad.xmax = brush->stencil_dimension[0];
- quad.ymax = brush->stencil_dimension[1];
- }
- else {
- quad.xmin = -brush->mask_stencil_dimension[0];
- quad.ymin = -brush->mask_stencil_dimension[1];
- quad.xmax = brush->mask_stencil_dimension[0];
- quad.ymax = brush->mask_stencil_dimension[1];
- }
- GPU_matrix_push();
- if (primary)
- GPU_matrix_translate_2fv(brush->stencil_pos);
- else
- GPU_matrix_translate_2fv(brush->mask_stencil_pos);
- GPU_matrix_rotate_2d(RAD2DEGF(mtex->rot));
- }
-
- /* 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);
-
- if (col) {
- immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
- immUniformColor4f(1.0f, 1.0f, 1.0f, overlay_alpha * 0.01f);
- }
- else {
- GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_ALPHA_COLOR);
- immUniformColor3fvAlpha(U.sculpt_paint_overlay_col, overlay_alpha * 0.01f);
- }
-
- /* draw textured quad */
- immUniform1i("image", 0);
-
- immBegin(GPU_PRIM_TRI_FAN, 4);
- immAttr2f(texCoord, 0.0f, 0.0f);
- immVertex2f(pos, quad.xmin, quad.ymin);
- immAttr2f(texCoord, 1.0f, 0.0f);
- immVertex2f(pos, quad.xmax, quad.ymin);
- immAttr2f(texCoord, 1.0f, 1.0f);
- immVertex2f(pos, quad.xmax, quad.ymax);
- immAttr2f(texCoord, 0.0f, 1.0f);
- immVertex2f(pos, quad.xmin, quad.ymax);
- immEnd();
-
- immUnbindProgram();
- GPU_blend_set_func(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA);
-
- if (ELEM(mtex->brush_map_mode, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_VIEW)) {
- GPU_matrix_pop();
- }
- }
+ rctf quad;
+ /* check for overlay mode */
+
+ MTex *mtex = (primary) ? &brush->mtex : &brush->mask_mtex;
+ bool valid = ((primary) ? (brush->overlay_flags & BRUSH_OVERLAY_PRIMARY) != 0 :
+ (brush->overlay_flags & BRUSH_OVERLAY_SECONDARY) != 0);
+ int overlay_alpha = (primary) ? brush->texture_overlay_alpha : brush->mask_overlay_alpha;
+
+ if (!(mtex->tex) ||
+ !((mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) ||
+ (valid && ELEM(mtex->brush_map_mode, MTEX_MAP_MODE_VIEW, MTEX_MAP_MODE_TILED)))) {
+ return;
+ }
+
+ if (load_tex(brush, vc, zoom, col, primary)) {
+ GPU_blend(true);
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glDepthMask(GL_FALSE);
+ glDepthFunc(GL_ALWAYS);
+
+ if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
+ GPU_matrix_push();
+
+ /* 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 */
+ if (primary && ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) {
+ const float scale = ups->size_pressure_value;
+ GPU_matrix_translate_2f(x, y);
+ GPU_matrix_scale_2f(scale, scale);
+ GPU_matrix_translate_2f(-x, -y);
+ }
+
+ if (ups->draw_anchored) {
+ quad.xmin = ups->anchored_initial_mouse[0] - ups->anchored_size;
+ quad.ymin = ups->anchored_initial_mouse[1] - ups->anchored_size;
+ quad.xmax = ups->anchored_initial_mouse[0] + ups->anchored_size;
+ quad.ymax = ups->anchored_initial_mouse[1] + ups->anchored_size;
+ }
+ else {
+ const int radius = BKE_brush_size_get(vc->scene, brush) * zoom;
+ quad.xmin = x - radius;
+ quad.ymin = y - radius;
+ quad.xmax = x + radius;
+ quad.ymax = y + radius;
+ }
+ }
+ 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);
+ }
+ /* Stencil code goes here */
+ else {
+ if (primary) {
+ quad.xmin = -brush->stencil_dimension[0];
+ quad.ymin = -brush->stencil_dimension[1];
+ quad.xmax = brush->stencil_dimension[0];
+ quad.ymax = brush->stencil_dimension[1];
+ }
+ else {
+ quad.xmin = -brush->mask_stencil_dimension[0];
+ quad.ymin = -brush->mask_stencil_dimension[1];
+ quad.xmax = brush->mask_stencil_dimension[0];
+ quad.ymax = brush->mask_stencil_dimension[1];
+ }
+ GPU_matrix_push();
+ if (primary)
+ GPU_matrix_translate_2fv(brush->stencil_pos);
+ else
+ GPU_matrix_translate_2fv(brush->mask_stencil_pos);
+ GPU_matrix_rotate_2d(RAD2DEGF(mtex->rot));
+ }
+
+ /* 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);
+
+ if (col) {
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
+ immUniformColor4f(1.0f, 1.0f, 1.0f, overlay_alpha * 0.01f);
+ }
+ else {
+ GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_ALPHA_COLOR);
+ immUniformColor3fvAlpha(U.sculpt_paint_overlay_col, overlay_alpha * 0.01f);
+ }
+
+ /* draw textured quad */
+ immUniform1i("image", 0);
+
+ immBegin(GPU_PRIM_TRI_FAN, 4);
+ immAttr2f(texCoord, 0.0f, 0.0f);
+ immVertex2f(pos, quad.xmin, quad.ymin);
+ immAttr2f(texCoord, 1.0f, 0.0f);
+ immVertex2f(pos, quad.xmax, quad.ymin);
+ immAttr2f(texCoord, 1.0f, 1.0f);
+ immVertex2f(pos, quad.xmax, quad.ymax);
+ immAttr2f(texCoord, 0.0f, 1.0f);
+ immVertex2f(pos, quad.xmin, quad.ymax);
+ immEnd();
+
+ immUnbindProgram();
+ GPU_blend_set_func(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA);
+
+ if (ELEM(mtex->brush_map_mode, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_VIEW)) {
+ GPU_matrix_pop();
+ }
+ }
}
/* Draw an overlay that shows what effect the brush's texture will
* have on brush strength */
static void paint_draw_cursor_overlay(
- UnifiedPaintSettings *ups, Brush *brush,
- ViewContext *vc, int x, int y, float zoom)
+ UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc, int x, int y, float zoom)
{
- rctf quad;
- /* check for overlay mode */
-
- if (!(brush->overlay_flags & BRUSH_OVERLAY_CURSOR)) {
- return;
- }
-
- if (load_tex_cursor(brush, vc, zoom)) {
- bool do_pop = false;
- float center[2];
- GPU_blend(true);
-
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glDepthMask(GL_FALSE);
- glDepthFunc(GL_ALWAYS);
-
- if (ups->draw_anchored) {
- copy_v2_v2(center, ups->anchored_initial_mouse);
- quad.xmin = ups->anchored_initial_mouse[0] - ups->anchored_size;
- quad.ymin = ups->anchored_initial_mouse[1] - ups->anchored_size;
- quad.xmax = ups->anchored_initial_mouse[0] + ups->anchored_size;
- quad.ymax = ups->anchored_initial_mouse[1] + ups->anchored_size;
- }
- else {
- const int radius = BKE_brush_size_get(vc->scene, brush) * zoom;
- center[0] = x;
- center[1] = y;
-
- quad.xmin = x - radius;
- quad.ymin = y - radius;
- quad.xmax = x + radius;
- quad.ymax = y + radius;
- }
-
- /* scale based on tablet pressure */
- if (ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) {
- do_pop = true;
- GPU_matrix_push();
- GPU_matrix_translate_2fv(center);
- GPU_matrix_scale_1f(ups->size_pressure_value);
- GPU_matrix_translate_2f(-center[0], -center[1]);
- }
-
- 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);
-
- GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_ALPHA_COLOR);
-
- immUniformColor3fvAlpha(U.sculpt_paint_overlay_col, brush->cursor_overlay_alpha * 0.01f);
-
- /* draw textured quad */
-
- /* draw textured quad */
- immUniform1i("image", 0);
-
- immBegin(GPU_PRIM_TRI_FAN, 4);
- immAttr2f(texCoord, 0.0f, 0.0f);
- immVertex2f(pos, quad.xmin, quad.ymin);
- immAttr2f(texCoord, 1.0f, 0.0f);
- immVertex2f(pos, quad.xmax, quad.ymin);
- immAttr2f(texCoord, 1.0f, 1.0f);
- immVertex2f(pos, quad.xmax, quad.ymax);
- immAttr2f(texCoord, 0.0f, 1.0f);
- immVertex2f(pos, quad.xmin, quad.ymax);
- immEnd();
-
- immUnbindProgram();
-
- GPU_blend_set_func(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA);
-
- if (do_pop)
- GPU_matrix_pop();
- }
+ rctf quad;
+ /* check for overlay mode */
+
+ if (!(brush->overlay_flags & BRUSH_OVERLAY_CURSOR)) {
+ return;
+ }
+
+ if (load_tex_cursor(brush, vc, zoom)) {
+ bool do_pop = false;
+ float center[2];
+ GPU_blend(true);
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glDepthMask(GL_FALSE);
+ glDepthFunc(GL_ALWAYS);
+
+ if (ups->draw_anchored) {
+ copy_v2_v2(center, ups->anchored_initial_mouse);
+ quad.xmin = ups->anchored_initial_mouse[0] - ups->anchored_size;
+ quad.ymin = ups->anchored_initial_mouse[1] - ups->anchored_size;
+ quad.xmax = ups->anchored_initial_mouse[0] + ups->anchored_size;
+ quad.ymax = ups->anchored_initial_mouse[1] + ups->anchored_size;
+ }
+ else {
+ const int radius = BKE_brush_size_get(vc->scene, brush) * zoom;
+ center[0] = x;
+ center[1] = y;
+
+ quad.xmin = x - radius;
+ quad.ymin = y - radius;
+ quad.xmax = x + radius;
+ quad.ymax = y + radius;
+ }
+
+ /* scale based on tablet pressure */
+ if (ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) {
+ do_pop = true;
+ GPU_matrix_push();
+ GPU_matrix_translate_2fv(center);
+ GPU_matrix_scale_1f(ups->size_pressure_value);
+ GPU_matrix_translate_2f(-center[0], -center[1]);
+ }
+
+ 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);
+
+ GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_ALPHA_COLOR);
+
+ immUniformColor3fvAlpha(U.sculpt_paint_overlay_col, brush->cursor_overlay_alpha * 0.01f);
+
+ /* draw textured quad */
+
+ /* draw textured quad */
+ immUniform1i("image", 0);
+
+ immBegin(GPU_PRIM_TRI_FAN, 4);
+ immAttr2f(texCoord, 0.0f, 0.0f);
+ immVertex2f(pos, quad.xmin, quad.ymin);
+ immAttr2f(texCoord, 1.0f, 0.0f);
+ immVertex2f(pos, quad.xmax, quad.ymin);
+ immAttr2f(texCoord, 1.0f, 1.0f);
+ immVertex2f(pos, quad.xmax, quad.ymax);
+ immAttr2f(texCoord, 0.0f, 1.0f);
+ immVertex2f(pos, quad.xmin, quad.ymax);
+ immEnd();
+
+ immUnbindProgram();
+
+ GPU_blend_set_func(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA);
+
+ if (do_pop)
+ GPU_matrix_pop();
+ }
}
-static void paint_draw_alpha_overlay(
- UnifiedPaintSettings *ups, Brush *brush,
- ViewContext *vc, int x, int y, float zoom, ePaintMode mode)
+static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups,
+ Brush *brush,
+ ViewContext *vc,
+ int x,
+ int y,
+ float zoom,
+ ePaintMode mode)
{
- /* Color means that primary brush texture is colored and
- * secondary is used for alpha/mask control. */
- bool col = ELEM(mode, PAINT_MODE_TEXTURE_3D, PAINT_MODE_TEXTURE_2D, PAINT_MODE_VERTEX);
- eOverlayControlFlags flags = BKE_paint_get_overlay_flags();
- gpuPushAttr(GPU_DEPTH_BUFFER_BIT | GPU_BLEND_BIT);
-
- /* 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;
-
- /* coloured overlay should be drawn separately */
- if (col) {
- if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY))
- paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, true, true);
- if (!(flags & PAINT_OVERLAY_OVERRIDE_SECONDARY))
- paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, false);
- if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR))
- paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
- }
- else {
- if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY) && (mode != PAINT_MODE_WEIGHT))
- paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, true);
- if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR))
- paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
- }
-
- GPU_matrix_pop();
- gpuPopAttr();
+ /* Color means that primary brush texture is colored and
+ * secondary is used for alpha/mask control. */
+ bool col = ELEM(mode, PAINT_MODE_TEXTURE_3D, PAINT_MODE_TEXTURE_2D, PAINT_MODE_VERTEX);
+ eOverlayControlFlags flags = BKE_paint_get_overlay_flags();
+ gpuPushAttr(GPU_DEPTH_BUFFER_BIT | GPU_BLEND_BIT);
+
+ /* 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;
+
+ /* coloured overlay should be drawn separately */
+ if (col) {
+ if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY))
+ paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, true, true);
+ if (!(flags & PAINT_OVERLAY_OVERRIDE_SECONDARY))
+ paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, false);
+ if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR))
+ paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
+ }
+ else {
+ if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY) && (mode != PAINT_MODE_WEIGHT))
+ paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, true);
+ if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR))
+ paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
+ }
+
+ GPU_matrix_pop();
+ gpuPopAttr();
}
-
BLI_INLINE void draw_tri_point(
- unsigned int pos, float sel_col[4], float pivot_col[4],
- float *co, float width, bool selected)
+ unsigned int pos, float sel_col[4], float pivot_col[4], float *co, float width, bool selected)
{
- immUniformColor4fv(selected ? sel_col : pivot_col);
-
- GPU_line_width(3.0f);
-
- float w = width / 2.0f;
- float tri[3][2] = {
- {co[0], co[1] + w},
- {co[0] - w, co[1] - w},
- {co[0] + w, co[1] - w},
- };
-
- immBegin(GPU_PRIM_LINE_LOOP, 3);
- immVertex2fv(pos, tri[0]);
- immVertex2fv(pos, tri[1]);
- immVertex2fv(pos, tri[2]);
- immEnd();
-
- immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
- GPU_line_width(1.0f);
-
- immBegin(GPU_PRIM_LINE_LOOP, 3);
- immVertex2fv(pos, tri[0]);
- immVertex2fv(pos, tri[1]);
- immVertex2fv(pos, tri[2]);
- immEnd();
+ immUniformColor4fv(selected ? sel_col : pivot_col);
+
+ GPU_line_width(3.0f);
+
+ float w = width / 2.0f;
+ float tri[3][2] = {
+ {co[0], co[1] + w},
+ {co[0] - w, co[1] - w},
+ {co[0] + w, co[1] - w},
+ };
+
+ immBegin(GPU_PRIM_LINE_LOOP, 3);
+ immVertex2fv(pos, tri[0]);
+ immVertex2fv(pos, tri[1]);
+ immVertex2fv(pos, tri[2]);
+ immEnd();
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
+ GPU_line_width(1.0f);
+
+ immBegin(GPU_PRIM_LINE_LOOP, 3);
+ immVertex2fv(pos, tri[0]);
+ immVertex2fv(pos, tri[1]);
+ immVertex2fv(pos, tri[2]);
+ immEnd();
}
BLI_INLINE void draw_rect_point(
- unsigned int pos, float sel_col[4], float handle_col[4],
- float *co, float width, bool selected)
+ unsigned int pos, float sel_col[4], float handle_col[4], float *co, float width, bool selected)
{
- immUniformColor4fv(selected ? sel_col : handle_col);
+ immUniformColor4fv(selected ? sel_col : handle_col);
- GPU_line_width(3.0f);
+ GPU_line_width(3.0f);
- float w = width / 2.0f;
- float minx = co[0] - w;
- float miny = co[1] - w;
- float maxx = co[0] + w;
- float maxy = co[1] + w;
+ float w = width / 2.0f;
+ float minx = co[0] - w;
+ float miny = co[1] - w;
+ float maxx = co[0] + w;
+ float maxy = co[1] + w;
- imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy);
+ imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy);
- immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
- GPU_line_width(1.0f);
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
+ GPU_line_width(1.0f);
- imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy);
+ 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)
{
- immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
- GPU_line_width(3.0f);
-
- immBegin(GPU_PRIM_LINE_STRIP, 3);
- immVertex2fv(pos, bez->vec[0]);
- immVertex2fv(pos, bez->vec[1]);
- immVertex2fv(pos, bez->vec[2]);
- immEnd();
-
- GPU_line_width(1.0f);
-
- if (bez->f1 || bez->f2) {
- immUniformColor4fv(sel_col);
- }
- else {
- immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
- }
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2fv(pos, bez->vec[0]);
- immVertex2fv(pos, bez->vec[1]);
- immEnd();
-
- if (bez->f3 || bez->f2) {
- immUniformColor4fv(sel_col);
- }
- else {
- immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
- }
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2fv(pos, bez->vec[1]);
- immVertex2fv(pos, bez->vec[2]);
- immEnd();
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
+ GPU_line_width(3.0f);
+
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
+ immVertex2fv(pos, bez->vec[0]);
+ immVertex2fv(pos, bez->vec[1]);
+ immVertex2fv(pos, bez->vec[2]);
+ immEnd();
+
+ GPU_line_width(1.0f);
+
+ if (bez->f1 || bez->f2) {
+ immUniformColor4fv(sel_col);
+ }
+ else {
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
+ }
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2fv(pos, bez->vec[0]);
+ immVertex2fv(pos, bez->vec[1]);
+ immEnd();
+
+ if (bez->f3 || bez->f2) {
+ immUniformColor4fv(sel_col);
+ }
+ else {
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
+ }
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2fv(pos, bez->vec[1]);
+ immVertex2fv(pos, bez->vec[2]);
+ immEnd();
}
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);
-
- if (brush->paint_curve && brush->paint_curve->points) {
- int i;
- PaintCurve *pc = brush->paint_curve;
- PaintCurvePoint *cp = pc->points;
-
- GPU_line_smooth(true);
- GPU_blend(true);
-
- /* 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);
-
- float selec_col[4], handle_col[4], pivot_col[4];
- UI_GetThemeColor4fv(TH_VERTEX_SELECT, selec_col);
- UI_GetThemeColor4fv(TH_PAINT_CURVE_HANDLE, handle_col);
- UI_GetThemeColor4fv(TH_PAINT_CURVE_PIVOT, pivot_col);
-
- for (i = 0; i < pc->tot_points - 1; i++, cp++) {
- int j;
- PaintCurvePoint *cp_next = cp + 1;
- float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
- /* 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(pos, selec_col, handle_col, &cp->bez.vec[0][0], 8.0f, cp->bez.f1 || cp->bez.f2);
- draw_rect_point(pos, selec_col, handle_col, &cp->bez.vec[2][0], 8.0f, cp->bez.f3 || cp->bez.f2);
-
- for (j = 0; j < 2; j++)
- BKE_curve_forward_diff_bezier(
- cp->bez.vec[1][j],
- cp->bez.vec[2][j],
- cp_next->bez.vec[0][j],
- cp_next->bez.vec[1][j],
- data + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2]));
-
- float (*v)[2] = (float(*)[2])data;
-
- immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
- GPU_line_width(3.0f);
- immBegin(GPU_PRIM_LINE_STRIP, PAINT_CURVE_NUM_SEGMENTS + 1);
- for (j = 0; j <= PAINT_CURVE_NUM_SEGMENTS; j++) {
- immVertex2fv(pos, v[j]);
- }
- immEnd();
-
- immUniformColor4f(0.9f, 0.9f, 1.0f, 0.5f);
- GPU_line_width(1.0f);
- immBegin(GPU_PRIM_LINE_STRIP, PAINT_CURVE_NUM_SEGMENTS + 1);
- for (j = 0; j <= PAINT_CURVE_NUM_SEGMENTS; j++) {
- immVertex2fv(pos, v[j]);
- }
- immEnd();
- }
-
- /* 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(pos, selec_col, handle_col, &cp->bez.vec[0][0], 8.0f, cp->bez.f1 || cp->bez.f2);
- draw_rect_point(pos, selec_col, handle_col, &cp->bez.vec[2][0], 8.0f, cp->bez.f3 || cp->bez.f2);
-
- GPU_blend(false);
- GPU_line_smooth(false);
-
- immUnbindProgram();
- }
- GPU_matrix_pop();
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(vc->ar->winrct.xmin, vc->ar->winrct.ymin);
+
+ if (brush->paint_curve && brush->paint_curve->points) {
+ int i;
+ PaintCurve *pc = brush->paint_curve;
+ PaintCurvePoint *cp = pc->points;
+
+ GPU_line_smooth(true);
+ GPU_blend(true);
+
+ /* 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);
+
+ float selec_col[4], handle_col[4], pivot_col[4];
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, selec_col);
+ UI_GetThemeColor4fv(TH_PAINT_CURVE_HANDLE, handle_col);
+ UI_GetThemeColor4fv(TH_PAINT_CURVE_PIVOT, pivot_col);
+
+ for (i = 0; i < pc->tot_points - 1; i++, cp++) {
+ int j;
+ PaintCurvePoint *cp_next = cp + 1;
+ float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
+ /* 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(
+ pos, selec_col, handle_col, &cp->bez.vec[0][0], 8.0f, cp->bez.f1 || cp->bez.f2);
+ draw_rect_point(
+ pos, selec_col, handle_col, &cp->bez.vec[2][0], 8.0f, cp->bez.f3 || cp->bez.f2);
+
+ for (j = 0; j < 2; j++)
+ BKE_curve_forward_diff_bezier(cp->bez.vec[1][j],
+ cp->bez.vec[2][j],
+ cp_next->bez.vec[0][j],
+ cp_next->bez.vec[1][j],
+ data + j,
+ PAINT_CURVE_NUM_SEGMENTS,
+ sizeof(float[2]));
+
+ float(*v)[2] = (float(*)[2])data;
+
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
+ GPU_line_width(3.0f);
+ immBegin(GPU_PRIM_LINE_STRIP, PAINT_CURVE_NUM_SEGMENTS + 1);
+ for (j = 0; j <= PAINT_CURVE_NUM_SEGMENTS; j++) {
+ immVertex2fv(pos, v[j]);
+ }
+ immEnd();
+
+ immUniformColor4f(0.9f, 0.9f, 1.0f, 0.5f);
+ GPU_line_width(1.0f);
+ immBegin(GPU_PRIM_LINE_STRIP, PAINT_CURVE_NUM_SEGMENTS + 1);
+ for (j = 0; j <= PAINT_CURVE_NUM_SEGMENTS; j++) {
+ immVertex2fv(pos, v[j]);
+ }
+ immEnd();
+ }
+
+ /* 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(
+ pos, selec_col, handle_col, &cp->bez.vec[0][0], 8.0f, cp->bez.f1 || cp->bez.f2);
+ draw_rect_point(
+ pos, selec_col, handle_col, &cp->bez.vec[2][0], 8.0f, cp->bez.f3 || cp->bez.f2);
+
+ GPU_blend(false);
+ GPU_line_smooth(false);
+
+ immUnbindProgram();
+ }
+ GPU_matrix_pop();
}
/* Special actions taken when paint cursor goes over mesh */
/* TODO: sculpt only for now */
-static void paint_cursor_on_hit(
- UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc,
- const float location[3])
+static void paint_cursor_on_hit(UnifiedPaintSettings *ups,
+ Brush *brush,
+ ViewContext *vc,
+ const float location[3])
{
- float unprojected_radius, projected_radius;
-
- /* update the brush's cached 3D radius */
- if (!BKE_brush_use_locked_size(vc->scene, brush)) {
- /* get 2D brush radius */
- if (ups->draw_anchored)
- projected_radius = ups->anchored_size;
- else {
- if (brush->flag & BRUSH_ANCHORED)
- projected_radius = 8;
- else
- projected_radius = BKE_brush_size_get(vc->scene, brush);
- }
-
- /* convert brush radius from 2D to 3D */
- unprojected_radius = paint_calc_object_space_radius(
- vc, location, projected_radius);
-
- /* scale 3D brush radius by pressure */
- if (ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush))
- unprojected_radius *= ups->size_pressure_value;
-
- /* set cached value in either Brush or UnifiedPaintSettings */
- BKE_brush_unprojected_radius_set(vc->scene, brush, unprojected_radius);
- }
+ float unprojected_radius, projected_radius;
+
+ /* update the brush's cached 3D radius */
+ if (!BKE_brush_use_locked_size(vc->scene, brush)) {
+ /* get 2D brush radius */
+ if (ups->draw_anchored)
+ projected_radius = ups->anchored_size;
+ else {
+ if (brush->flag & BRUSH_ANCHORED)
+ projected_radius = 8;
+ else
+ projected_radius = BKE_brush_size_get(vc->scene, brush);
+ }
+
+ /* convert brush radius from 2D to 3D */
+ unprojected_radius = paint_calc_object_space_radius(vc, location, projected_radius);
+
+ /* scale 3D brush radius by pressure */
+ if (ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush))
+ unprojected_radius *= ups->size_pressure_value;
+
+ /* set cached value in either Brush or UnifiedPaintSettings */
+ BKE_brush_unprojected_radius_set(vc->scene, brush, unprojected_radius);
+ }
}
static bool ommit_cursor_drawing(Paint *paint, ePaintMode mode, Brush *brush)
{
- if (paint->flags & PAINT_SHOW_BRUSH) {
- if (ELEM(mode, PAINT_MODE_TEXTURE_2D, PAINT_MODE_TEXTURE_3D) && brush->imagepaint_tool == PAINT_TOOL_FILL) {
- return true;
- }
- return false;
- }
- return true;
+ if (paint->flags & PAINT_SHOW_BRUSH) {
+ if (ELEM(mode, PAINT_MODE_TEXTURE_2D, PAINT_MODE_TEXTURE_3D) &&
+ brush->imagepaint_tool == PAINT_TOOL_FILL) {
+ return true;
+ }
+ return false;
+ }
+ return true;
}
static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
{
- Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
- UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
- Paint *paint = BKE_paint_get_active_from_context(C);
- Brush *brush = BKE_paint_brush(paint);
- ePaintMode mode = BKE_paintmode_get_active_from_context(C);
-
- /* check that brush drawing is enabled */
- if (ommit_cursor_drawing(paint, mode, brush))
- return;
-
- /* 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);
-
- if (vc.rv3d && (vc.rv3d->rflag & RV3D_NAVIGATING)) {
- return;
- }
-
- /* skip everything and draw brush here */
- if (brush->flag & BRUSH_CURVE) {
- paint_draw_curve_cursor(brush, &vc);
- return;
- }
-
- float zoomx, zoomy;
- get_imapaint_zoom(C, &zoomx, &zoomy);
- zoomx = max_ff(zoomx, zoomy);
-
- /* set various defaults */
- const float *outline_col = brush->add_col;
- const float outline_alpha = 0.5f;
- 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
- * and we may get interference with the stroke itself.
- * For line strokes, such interference is visible */
- if (!ups->stroke_active) {
- paint_calculate_rake_rotation(ups, brush, translation);
- }
-
- /* draw overlay */
- paint_draw_alpha_overlay(ups, brush, &vc, x, y, zoomx, mode);
-
- /* TODO: as sculpt and other paint modes are unified, this
- * special mode of drawing will go away */
- if ((mode == PAINT_MODE_SCULPT) && vc.obact->sculpt) {
- float location[3];
- int pixel_radius;
-
- /* 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 */
- /* TODO: no way currently to know state of pen flip or
- * 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 */
- if (hit)
- paint_cursor_on_hit(ups, brush, &vc, location);
- }
-
- 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);
- }
-
- /* make lines pretty */
- GPU_line_width(1.0f);
- GPU_blend(true); /* TODO: also set blend mode? */
- GPU_line_smooth(true);
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* set brush color */
- immUniformColor3fvAlpha(outline_col, outline_alpha);
-
- /* draw brush outline */
- if (ups->stroke_active && BKE_brush_use_size_pressure(scene, brush)) {
- /* inner at full alpha */
- imm_draw_circle_wire_2d(pos, translation[0], translation[1], final_radius * ups->size_pressure_value, 40);
- /* outer at half alpha */
- immUniformColor3fvAlpha(outline_col, outline_alpha * 0.5f);
- }
- imm_draw_circle_wire_2d(pos, translation[0], translation[1], final_radius, 40);
-
- immUnbindProgram();
-
- /* restore GL state */
- GPU_blend(false);
- GPU_line_smooth(false);
+ Scene *scene = CTX_data_scene(C);
+ ARegion *ar = CTX_wm_region(C);
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Brush *brush = BKE_paint_brush(paint);
+ ePaintMode mode = BKE_paintmode_get_active_from_context(C);
+
+ /* check that brush drawing is enabled */
+ if (ommit_cursor_drawing(paint, mode, brush))
+ return;
+
+ /* 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);
+
+ if (vc.rv3d && (vc.rv3d->rflag & RV3D_NAVIGATING)) {
+ return;
+ }
+
+ /* skip everything and draw brush here */
+ if (brush->flag & BRUSH_CURVE) {
+ paint_draw_curve_cursor(brush, &vc);
+ return;
+ }
+
+ float zoomx, zoomy;
+ get_imapaint_zoom(C, &zoomx, &zoomy);
+ zoomx = max_ff(zoomx, zoomy);
+
+ /* set various defaults */
+ const float *outline_col = brush->add_col;
+ const float outline_alpha = 0.5f;
+ 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
+ * and we may get interference with the stroke itself.
+ * For line strokes, such interference is visible */
+ if (!ups->stroke_active) {
+ paint_calculate_rake_rotation(ups, brush, translation);
+ }
+
+ /* draw overlay */
+ paint_draw_alpha_overlay(ups, brush, &vc, x, y, zoomx, mode);
+
+ /* TODO: as sculpt and other paint modes are unified, this
+ * special mode of drawing will go away */
+ if ((mode == PAINT_MODE_SCULPT) && vc.obact->sculpt) {
+ float location[3];
+ int pixel_radius;
+
+ /* 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 */
+ /* TODO: no way currently to know state of pen flip or
+ * 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 */
+ if (hit)
+ paint_cursor_on_hit(ups, brush, &vc, location);
+ }
+
+ 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);
+ }
+
+ /* make lines pretty */
+ GPU_line_width(1.0f);
+ GPU_blend(true); /* TODO: also set blend mode? */
+ GPU_line_smooth(true);
+
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* set brush color */
+ immUniformColor3fvAlpha(outline_col, outline_alpha);
+
+ /* draw brush outline */
+ if (ups->stroke_active && BKE_brush_use_size_pressure(scene, brush)) {
+ /* inner at full alpha */
+ imm_draw_circle_wire_2d(
+ pos, translation[0], translation[1], final_radius * ups->size_pressure_value, 40);
+ /* outer at half alpha */
+ immUniformColor3fvAlpha(outline_col, outline_alpha * 0.5f);
+ }
+ imm_draw_circle_wire_2d(pos, translation[0], translation[1], final_radius, 40);
+
+ immUnbindProgram();
+
+ /* restore GL state */
+ GPU_blend(false);
+ GPU_line_smooth(false);
}
/* Public API */
void paint_cursor_start(bContext *C, bool (*poll)(bContext *C))
{
- Paint *p = BKE_paint_get_active_from_context(C);
-
- if (p && !p->paint_cursor) {
- p->paint_cursor = WM_paint_cursor_activate(
- CTX_wm_manager(C),
- SPACE_TYPE_ANY, RGN_TYPE_ANY,
- poll,
- paint_draw_cursor,
- NULL);
- }
-
- /* invalidate the paint cursors */
- BKE_paint_invalidate_overlay_all();
+ Paint *p = BKE_paint_get_active_from_context(C);
+
+ if (p && !p->paint_cursor) {
+ p->paint_cursor = WM_paint_cursor_activate(
+ CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, poll, paint_draw_cursor, NULL);
+ }
+
+ /* invalidate the paint cursors */
+ BKE_paint_invalidate_overlay_all();
}
void paint_cursor_start_explicit(Paint *p, wmWindowManager *wm, bool (*poll)(bContext *C))
{
- if (p && !p->paint_cursor) {
- p->paint_cursor = WM_paint_cursor_activate(
- wm,
- SPACE_TYPE_ANY, RGN_TYPE_ANY,
- poll,
- paint_draw_cursor,
- NULL);
- }
+ if (p && !p->paint_cursor) {
+ p->paint_cursor = WM_paint_cursor_activate(
+ wm, SPACE_TYPE_ANY, RGN_TYPE_ANY, poll, paint_draw_cursor, NULL);
+ }
}
diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c
index 6e43c0ab492..bc6e019142a 100644
--- a/source/blender/editors/sculpt_paint/paint_curve.c
+++ b/source/blender/editors/sculpt_paint/paint_curve.c
@@ -55,26 +55,26 @@
bool paint_curve_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
- Paint *p;
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- SpaceImage *sima;
+ Object *ob = CTX_data_active_object(C);
+ Paint *p;
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ SpaceImage *sima;
- if (rv3d && !(ob && ((ob->mode & OB_MODE_ALL_PAINT) != 0)))
- return false;
+ if (rv3d && !(ob && ((ob->mode & OB_MODE_ALL_PAINT) != 0)))
+ return false;
- sima = CTX_wm_space_image(C);
+ sima = CTX_wm_space_image(C);
- if (sima && sima->mode != SI_MODE_PAINT)
- return false;
+ if (sima && sima->mode != SI_MODE_PAINT)
+ return false;
- p = BKE_paint_get_active_from_context(C);
+ p = BKE_paint_get_active_from_context(C);
- if (p && p->brush && (p->brush->flag & BRUSH_CURVE)) {
- return true;
- }
+ if (p && p->brush && (p->brush->flag & BRUSH_CURVE)) {
+ return true;
+ }
- return false;
+ return false;
}
#define SEL_F1 (1 << 0)
@@ -82,655 +82,670 @@ bool paint_curve_poll(bContext *C)
#define SEL_F3 (1 << 2)
/* returns 0, 1, or 2 in point according to handle 1, pivot or handle 2 */
-static PaintCurvePoint *paintcurve_point_get_closest(PaintCurve *pc, const float pos[2], bool ignore_pivot, const float threshold, char *point)
+static PaintCurvePoint *paintcurve_point_get_closest(
+ PaintCurve *pc, const float pos[2], bool ignore_pivot, const float threshold, char *point)
{
- PaintCurvePoint *pcp, *closest = NULL;
- int i;
- float dist, closest_dist = FLT_MAX;
-
- 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;
- }
- }
- 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;
- }
- }
- }
- 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;
- }
- }
- }
-
- return closest;
+ PaintCurvePoint *pcp, *closest = NULL;
+ int i;
+ float dist, closest_dist = FLT_MAX;
+
+ 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;
+ }
+ }
+ 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;
+ }
+ }
+ }
+ 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;
+ }
+ }
+ }
+
+ return closest;
}
static int paintcurve_point_co_index(char sel)
{
- char i = 0;
- while (sel != 1) {
- sel >>= 1;
- i++;
- }
- return i;
+ char i = 0;
+ while (sel != 1) {
+ sel >>= 1;
+ i++;
+ }
+ return i;
}
-static char paintcurve_point_side_index(const BezTriple *bezt, const bool is_first, const char fallback)
+static char paintcurve_point_side_index(const BezTriple *bezt,
+ const bool is_first,
+ const char fallback)
{
- /* when matching, guess based on endpoint side */
- if (BEZT_ISSEL_ANY(bezt)) {
- if ((bezt->f1 & SELECT) == (bezt->f3 & SELECT)) {
- return is_first ? SEL_F1 : SEL_F3;
- }
- else if (bezt->f1 & SELECT) {
- return SEL_F1;
- }
- else if (bezt->f3 & SELECT) {
- return SEL_F3;
- }
- else {
- return fallback;
- }
- }
- else {
- return 0;
- }
+ /* when matching, guess based on endpoint side */
+ if (BEZT_ISSEL_ANY(bezt)) {
+ if ((bezt->f1 & SELECT) == (bezt->f3 & SELECT)) {
+ return is_first ? SEL_F1 : SEL_F3;
+ }
+ else if (bezt->f1 & SELECT) {
+ return SEL_F1;
+ }
+ else if (bezt->f3 & SELECT) {
+ return SEL_F3;
+ }
+ else {
+ return fallback;
+ }
+ }
+ else {
+ return 0;
+ }
}
/******************* Operators *********************************/
static int paintcurve_new_exec(bContext *C, wmOperator *UNUSED(op))
{
- Paint *p = BKE_paint_get_active_from_context(C);
- Main *bmain = CTX_data_main(C);
+ Paint *p = BKE_paint_get_active_from_context(C);
+ Main *bmain = CTX_data_main(C);
- if (p && p->brush) {
- p->brush->paint_curve = BKE_paint_curve_add(bmain, "PaintCurve");
- }
+ if (p && p->brush) {
+ p->brush->paint_curve = BKE_paint_curve_add(bmain, "PaintCurve");
+ }
- WM_event_add_notifier(C, NC_PAINTCURVE | NA_ADDED, NULL);
+ WM_event_add_notifier(C, NC_PAINTCURVE | NA_ADDED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PAINTCURVE_OT_new(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add New Paint Curve";
- ot->description = "Add new paint curve";
- ot->idname = "PAINTCURVE_OT_new";
+ /* identifiers */
+ ot->name = "Add New Paint Curve";
+ ot->description = "Add new paint curve";
+ ot->idname = "PAINTCURVE_OT_new";
- /* api callbacks */
- ot->exec = paintcurve_new_exec;
- ot->poll = paint_curve_poll;
+ /* api callbacks */
+ ot->exec = paintcurve_new_exec;
+ ot->poll = paint_curve_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static void paintcurve_point_add(bContext *C, wmOperator *op, const int loc[2])
+static void paintcurve_point_add(bContext *C, wmOperator *op, const int loc[2])
{
- Paint *p = BKE_paint_get_active_from_context(C);
- Brush *br = p->brush;
- Main *bmain = CTX_data_main(C);
- PaintCurve *pc;
- PaintCurvePoint *pcp;
- wmWindow *window = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
- float vec[3] = {loc[0], loc[1], 0.0};
- int add_index;
- int i;
-
- pc = br->paint_curve;
- if (!pc) {
- br->paint_curve = pc = BKE_paint_curve_add(bmain, "PaintCurve");
- }
-
- ED_paintcurve_undo_push_begin(op->type->name);
-
- pcp = MEM_mallocN((pc->tot_points + 1) * sizeof(PaintCurvePoint), "PaintCurvePoint");
- add_index = pc->add_index;
-
- if (pc->points) {
- if (add_index > 0)
- memcpy(pcp, pc->points, add_index * sizeof(PaintCurvePoint));
- if (add_index < pc->tot_points)
- memcpy(pcp + add_index + 1, pc->points + add_index, (pc->tot_points - add_index) * sizeof(PaintCurvePoint));
-
- MEM_freeN(pc->points);
- }
- pc->points = pcp;
- pc->tot_points++;
-
- /* initialize new point */
- memset(&pcp[add_index], 0, sizeof(PaintCurvePoint));
- copy_v3_v3(pcp[add_index].bez.vec[0], vec);
- copy_v3_v3(pcp[add_index].bez.vec[1], vec);
- copy_v3_v3(pcp[add_index].bez.vec[2], vec);
-
- /* last step, clear selection from all bezier handles expect the next */
- for (i = 0; i < pc->tot_points; i++) {
- pcp[i].bez.f1 = pcp[i].bez.f2 = pcp[i].bez.f3 = 0;
- }
-
- BKE_paint_curve_clamp_endpoint_add_index(pc, add_index);
-
- if (pc->add_index != 0) {
- pcp[add_index].bez.f3 = SELECT;
- pcp[add_index].bez.h2 = HD_ALIGN;
- }
- else {
- pcp[add_index].bez.f1 = SELECT;
- pcp[add_index].bez.h1 = HD_ALIGN;
- }
-
- ED_paintcurve_undo_push_end();
-
- WM_paint_cursor_tag_redraw(window, ar);
+ Paint *p = BKE_paint_get_active_from_context(C);
+ Brush *br = p->brush;
+ Main *bmain = CTX_data_main(C);
+ PaintCurve *pc;
+ PaintCurvePoint *pcp;
+ wmWindow *window = CTX_wm_window(C);
+ ARegion *ar = CTX_wm_region(C);
+ float vec[3] = {loc[0], loc[1], 0.0};
+ int add_index;
+ int i;
+
+ pc = br->paint_curve;
+ if (!pc) {
+ br->paint_curve = pc = BKE_paint_curve_add(bmain, "PaintCurve");
+ }
+
+ ED_paintcurve_undo_push_begin(op->type->name);
+
+ pcp = MEM_mallocN((pc->tot_points + 1) * sizeof(PaintCurvePoint), "PaintCurvePoint");
+ add_index = pc->add_index;
+
+ if (pc->points) {
+ if (add_index > 0)
+ memcpy(pcp, pc->points, add_index * sizeof(PaintCurvePoint));
+ if (add_index < pc->tot_points)
+ memcpy(pcp + add_index + 1,
+ pc->points + add_index,
+ (pc->tot_points - add_index) * sizeof(PaintCurvePoint));
+
+ MEM_freeN(pc->points);
+ }
+ pc->points = pcp;
+ pc->tot_points++;
+
+ /* initialize new point */
+ memset(&pcp[add_index], 0, sizeof(PaintCurvePoint));
+ copy_v3_v3(pcp[add_index].bez.vec[0], vec);
+ copy_v3_v3(pcp[add_index].bez.vec[1], vec);
+ copy_v3_v3(pcp[add_index].bez.vec[2], vec);
+
+ /* last step, clear selection from all bezier handles expect the next */
+ for (i = 0; i < pc->tot_points; i++) {
+ pcp[i].bez.f1 = pcp[i].bez.f2 = pcp[i].bez.f3 = 0;
+ }
+
+ BKE_paint_curve_clamp_endpoint_add_index(pc, add_index);
+
+ if (pc->add_index != 0) {
+ pcp[add_index].bez.f3 = SELECT;
+ pcp[add_index].bez.h2 = HD_ALIGN;
+ }
+ else {
+ pcp[add_index].bez.f1 = SELECT;
+ pcp[add_index].bez.h1 = HD_ALIGN;
+ }
+
+ ED_paintcurve_undo_push_end();
+
+ WM_paint_cursor_tag_redraw(window, ar);
}
-
static int paintcurve_add_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- int loc[2] = {event->mval[0], event->mval[1]};
- paintcurve_point_add(C, op, loc);
- RNA_int_set_array(op->ptr, "location", loc);
- return OPERATOR_FINISHED;
+ int loc[2] = {event->mval[0], event->mval[1]};
+ paintcurve_point_add(C, op, loc);
+ RNA_int_set_array(op->ptr, "location", loc);
+ return OPERATOR_FINISHED;
}
static int paintcurve_add_point_exec(bContext *C, wmOperator *op)
{
- int loc[2];
+ int loc[2];
- if (RNA_struct_property_is_set(op->ptr, "location")) {
- RNA_int_get_array(op->ptr, "location", loc);
- paintcurve_point_add(C, op, loc);
- return OPERATOR_FINISHED;
- }
+ if (RNA_struct_property_is_set(op->ptr, "location")) {
+ RNA_int_get_array(op->ptr, "location", loc);
+ paintcurve_point_add(C, op, loc);
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
void PAINTCURVE_OT_add_point(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add New Paint Curve Point";
- ot->description = ot->name;
- ot->idname = "PAINTCURVE_OT_add_point";
-
- /* api callbacks */
- ot->invoke = paintcurve_add_point_invoke;
- ot->exec = paintcurve_add_point_exec;
- ot->poll = paint_curve_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
-
- /* properties */
- RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, SHRT_MAX,
- "Location", "Location of vertex in area space", 0, SHRT_MAX);
+ /* identifiers */
+ ot->name = "Add New Paint Curve Point";
+ ot->description = ot->name;
+ ot->idname = "PAINTCURVE_OT_add_point";
+
+ /* api callbacks */
+ ot->invoke = paintcurve_add_point_invoke;
+ ot->exec = paintcurve_add_point_exec;
+ ot->poll = paint_curve_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_int_vector(ot->srna,
+ "location",
+ 2,
+ NULL,
+ 0,
+ SHRT_MAX,
+ "Location",
+ "Location of vertex in area space",
+ 0,
+ SHRT_MAX);
}
static int paintcurve_delete_point_exec(bContext *C, wmOperator *op)
{
- Paint *p = BKE_paint_get_active_from_context(C);
- Brush *br = p->brush;
- PaintCurve *pc;
- PaintCurvePoint *pcp;
- wmWindow *window = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
- int i;
- int tot_del = 0;
- pc = br->paint_curve;
-
- if (!pc || pc->tot_points == 0) {
- return OPERATOR_CANCELLED;
- }
-
- ED_paintcurve_undo_push_begin(op->type->name);
+ Paint *p = BKE_paint_get_active_from_context(C);
+ Brush *br = p->brush;
+ PaintCurve *pc;
+ PaintCurvePoint *pcp;
+ wmWindow *window = CTX_wm_window(C);
+ ARegion *ar = CTX_wm_region(C);
+ int i;
+ int tot_del = 0;
+ pc = br->paint_curve;
+
+ if (!pc || pc->tot_points == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_paintcurve_undo_push_begin(op->type->name);
#define DELETE_TAG 2
- for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
- if (BEZT_ISSEL_ANY(&pcp->bez)) {
- pcp->bez.f2 |= DELETE_TAG;
- tot_del++;
- }
- }
-
- if (tot_del > 0) {
- int j = 0;
- int new_tot = pc->tot_points - tot_del;
- PaintCurvePoint *points_new = NULL;
- if (new_tot > 0)
- points_new = MEM_mallocN(new_tot * sizeof(PaintCurvePoint), "PaintCurvePoint");
-
- for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
- if (!(pcp->bez.f2 & DELETE_TAG)) {
- points_new[j] = pc->points[i];
-
- if ((i + 1) == pc->add_index) {
- BKE_paint_curve_clamp_endpoint_add_index(pc, j);
- }
- j++;
- }
- else if ((i + 1) == pc->add_index) {
- /* prefer previous point */
- pc->add_index = j;
- }
- }
- MEM_freeN(pc->points);
-
- pc->points = points_new;
- pc->tot_points = new_tot;
- }
+ for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
+ if (BEZT_ISSEL_ANY(&pcp->bez)) {
+ pcp->bez.f2 |= DELETE_TAG;
+ tot_del++;
+ }
+ }
+
+ if (tot_del > 0) {
+ int j = 0;
+ int new_tot = pc->tot_points - tot_del;
+ PaintCurvePoint *points_new = NULL;
+ if (new_tot > 0)
+ points_new = MEM_mallocN(new_tot * sizeof(PaintCurvePoint), "PaintCurvePoint");
+
+ for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
+ if (!(pcp->bez.f2 & DELETE_TAG)) {
+ points_new[j] = pc->points[i];
+
+ if ((i + 1) == pc->add_index) {
+ BKE_paint_curve_clamp_endpoint_add_index(pc, j);
+ }
+ j++;
+ }
+ else if ((i + 1) == pc->add_index) {
+ /* prefer previous point */
+ pc->add_index = j;
+ }
+ }
+ MEM_freeN(pc->points);
+
+ pc->points = points_new;
+ pc->tot_points = new_tot;
+ }
#undef DELETE_TAG
- ED_paintcurve_undo_push_end();
+ ED_paintcurve_undo_push_end();
- WM_paint_cursor_tag_redraw(window, ar);
+ WM_paint_cursor_tag_redraw(window, ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
void PAINTCURVE_OT_delete_point(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Paint Curve Point";
- ot->description = ot->name;
- ot->idname = "PAINTCURVE_OT_delete_point";
+ /* identifiers */
+ ot->name = "Remove Paint Curve Point";
+ ot->description = ot->name;
+ ot->idname = "PAINTCURVE_OT_delete_point";
- /* api callbacks */
- ot->exec = paintcurve_delete_point_exec;
- ot->poll = paint_curve_poll;
+ /* api callbacks */
+ ot->exec = paintcurve_delete_point_exec;
+ ot->poll = paint_curve_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
-
-static bool paintcurve_point_select(bContext *C, wmOperator *op, const int loc[2], bool toggle, bool extend)
+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);
- Paint *p = BKE_paint_get_active_from_context(C);
- Brush *br = p->brush;
- PaintCurve *pc;
- int i;
- const float loc_fl[2] = {UNPACK2(loc)};
-
- pc = br->paint_curve;
-
- if (!pc)
- return false;
-
- ED_paintcurve_undo_push_begin(op->type->name);
-
- if (toggle) {
- PaintCurvePoint *pcp;
- char select = 0;
- bool selected = false;
-
- pcp = pc->points;
-
- for (i = 0; i < pc->tot_points; i++) {
- if (pcp[i].bez.f1 || pcp[i].bez.f2 || pcp[i].bez.f3) {
- selected = true;
- break;
- }
- }
-
- if (!selected) {
- select = SELECT;
- }
-
- for (i = 0; i < pc->tot_points; i++) {
- pc->points[i].bez.f1 = pc->points[i].bez.f2 = pc->points[i].bez.f3 = select;
- }
- }
- else {
- PaintCurvePoint *pcp;
- char selflag;
-
- pcp = paintcurve_point_get_closest(pc, loc_fl, false, PAINT_CURVE_SELECT_THRESHOLD, &selflag);
-
- if (pcp) {
- BKE_paint_curve_clamp_endpoint_add_index(pc, pcp - pc->points);
-
- if (selflag == SEL_F2) {
- if (extend)
- pcp->bez.f2 ^= SELECT;
- else
- pcp->bez.f2 |= SELECT;
- }
- else if (selflag == SEL_F1) {
- if (extend)
- pcp->bez.f1 ^= SELECT;
- else
- pcp->bez.f1 |= SELECT;
- }
- else if (selflag == SEL_F3) {
- if (extend)
- pcp->bez.f3 ^= SELECT;
- else
- pcp->bez.f3 |= SELECT;
- }
- }
-
- /* clear selection for unselected points if not extending and if a point has been selected */
- if (!extend && pcp) {
- for (i = 0; i < pc->tot_points; i++) {
- pc->points[i].bez.f1 = pc->points[i].bez.f2 = pc->points[i].bez.f3 = 0;
-
- if ((pc->points + i) == pcp) {
- char index = paintcurve_point_co_index(selflag);
- PAINT_CURVE_POINT_SELECT(pcp, index);
- }
- }
- }
-
- if (!pcp) {
- ED_paintcurve_undo_push_end();
- return false;
- }
- }
-
- ED_paintcurve_undo_push_end();
-
- WM_paint_cursor_tag_redraw(window, ar);
-
- return true;
+ wmWindow *window = CTX_wm_window(C);
+ ARegion *ar = CTX_wm_region(C);
+ Paint *p = BKE_paint_get_active_from_context(C);
+ Brush *br = p->brush;
+ PaintCurve *pc;
+ int i;
+ const float loc_fl[2] = {UNPACK2(loc)};
+
+ pc = br->paint_curve;
+
+ if (!pc)
+ return false;
+
+ ED_paintcurve_undo_push_begin(op->type->name);
+
+ if (toggle) {
+ PaintCurvePoint *pcp;
+ char select = 0;
+ bool selected = false;
+
+ pcp = pc->points;
+
+ for (i = 0; i < pc->tot_points; i++) {
+ if (pcp[i].bez.f1 || pcp[i].bez.f2 || pcp[i].bez.f3) {
+ selected = true;
+ break;
+ }
+ }
+
+ if (!selected) {
+ select = SELECT;
+ }
+
+ for (i = 0; i < pc->tot_points; i++) {
+ pc->points[i].bez.f1 = pc->points[i].bez.f2 = pc->points[i].bez.f3 = select;
+ }
+ }
+ else {
+ PaintCurvePoint *pcp;
+ char selflag;
+
+ pcp = paintcurve_point_get_closest(pc, loc_fl, false, PAINT_CURVE_SELECT_THRESHOLD, &selflag);
+
+ if (pcp) {
+ BKE_paint_curve_clamp_endpoint_add_index(pc, pcp - pc->points);
+
+ if (selflag == SEL_F2) {
+ if (extend)
+ pcp->bez.f2 ^= SELECT;
+ else
+ pcp->bez.f2 |= SELECT;
+ }
+ else if (selflag == SEL_F1) {
+ if (extend)
+ pcp->bez.f1 ^= SELECT;
+ else
+ pcp->bez.f1 |= SELECT;
+ }
+ else if (selflag == SEL_F3) {
+ if (extend)
+ pcp->bez.f3 ^= SELECT;
+ else
+ pcp->bez.f3 |= SELECT;
+ }
+ }
+
+ /* clear selection for unselected points if not extending and if a point has been selected */
+ if (!extend && pcp) {
+ for (i = 0; i < pc->tot_points; i++) {
+ pc->points[i].bez.f1 = pc->points[i].bez.f2 = pc->points[i].bez.f3 = 0;
+
+ if ((pc->points + i) == pcp) {
+ char index = paintcurve_point_co_index(selflag);
+ PAINT_CURVE_POINT_SELECT(pcp, index);
+ }
+ }
+ }
+
+ if (!pcp) {
+ ED_paintcurve_undo_push_end();
+ return false;
+ }
+ }
+
+ ED_paintcurve_undo_push_end();
+
+ WM_paint_cursor_tag_redraw(window, ar);
+
+ return true;
}
-
static int paintcurve_select_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- int loc[2] = {UNPACK2(event->mval)};
- bool toggle = RNA_boolean_get(op->ptr, "toggle");
- bool extend = RNA_boolean_get(op->ptr, "extend");
- if (paintcurve_point_select(C, op, loc, toggle, extend)) {
- RNA_int_set_array(op->ptr, "location", loc);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ int loc[2] = {UNPACK2(event->mval)};
+ bool toggle = RNA_boolean_get(op->ptr, "toggle");
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+ if (paintcurve_point_select(C, op, loc, toggle, extend)) {
+ RNA_int_set_array(op->ptr, "location", loc);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static int paintcurve_select_point_exec(bContext *C, wmOperator *op)
{
- int loc[2];
+ int loc[2];
- if (RNA_struct_property_is_set(op->ptr, "location")) {
- bool toggle = RNA_boolean_get(op->ptr, "toggle");
- bool extend = RNA_boolean_get(op->ptr, "extend");
- RNA_int_get_array(op->ptr, "location", loc);
- if (paintcurve_point_select(C, op, loc, toggle, extend))
- return OPERATOR_FINISHED;
- }
+ if (RNA_struct_property_is_set(op->ptr, "location")) {
+ bool toggle = RNA_boolean_get(op->ptr, "toggle");
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+ RNA_int_get_array(op->ptr, "location", loc);
+ if (paintcurve_point_select(C, op, loc, toggle, extend))
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
void PAINTCURVE_OT_select(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Select Paint Curve Point";
- ot->description = "Select a paint curve point";
- ot->idname = "PAINTCURVE_OT_select";
-
- /* api callbacks */
- ot->invoke = paintcurve_select_point_invoke;
- ot->exec = paintcurve_select_point_exec;
- ot->poll = paint_curve_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
-
- /* properties */
- RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, SHRT_MAX,
- "Location", "Location of vertex in area space", 0, SHRT_MAX);
- prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle", "(De)select all");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Paint Curve Point";
+ ot->description = "Select a paint curve point";
+ ot->idname = "PAINTCURVE_OT_select";
+
+ /* api callbacks */
+ ot->invoke = paintcurve_select_point_invoke;
+ ot->exec = paintcurve_select_point_exec;
+ ot->poll = paint_curve_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_int_vector(ot->srna,
+ "location",
+ 2,
+ NULL,
+ 0,
+ SHRT_MAX,
+ "Location",
+ "Location of vertex in area space",
+ 0,
+ SHRT_MAX);
+ prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle", "(De)select all");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
typedef struct PointSlideData {
- PaintCurvePoint *pcp;
- char select;
- int initial_loc[2];
- float point_initial_loc[3][2];
- int event;
- bool align;
+ PaintCurvePoint *pcp;
+ char select;
+ int initial_loc[2];
+ float point_initial_loc[3][2];
+ int event;
+ bool align;
} PointSlideData;
static int paintcurve_slide_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Paint *p = BKE_paint_get_active_from_context(C);
- const float loc_fl[2] = {UNPACK2(event->mval)};
- char select;
- int i;
- bool do_select = RNA_boolean_get(op->ptr, "select");
- bool align = RNA_boolean_get(op->ptr, "align");
- Brush *br = p->brush;
- PaintCurve *pc = br->paint_curve;
- PaintCurvePoint *pcp;
-
- if (!pc)
- return OPERATOR_PASS_THROUGH;
-
- if (do_select) {
- pcp = paintcurve_point_get_closest(pc, loc_fl, align, PAINT_CURVE_SELECT_THRESHOLD, &select);
- }
- else {
- pcp = NULL;
- /* just find first selected point */
- for (i = 0; i < pc->tot_points; i++) {
- if ((select = paintcurve_point_side_index(&pc->points[i].bez, i == 0, SEL_F3))) {
- pcp = &pc->points[i];
- break;
- }
- }
- }
-
-
- if (pcp) {
- ARegion *ar = 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);
- psd->event = event->type;
- psd->pcp = pcp;
- psd->select = paintcurve_point_co_index(select);
- for (i = 0; i < 3; i++) {
- copy_v2_v2(psd->point_initial_loc[i], pcp->bez.vec[i]);
- }
- psd->align = align;
- op->customdata = psd;
-
- /* first, clear all selection from points */
- for (i = 0; i < pc->tot_points; i++)
- pc->points[i].bez.f1 = pc->points[i].bez.f3 = pc->points[i].bez.f2 = 0;
-
- /* only select the active point */
- PAINT_CURVE_POINT_SELECT(pcp, psd->select);
- 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);
- return OPERATOR_RUNNING_MODAL;
- }
-
- return OPERATOR_PASS_THROUGH;
+ Paint *p = BKE_paint_get_active_from_context(C);
+ const float loc_fl[2] = {UNPACK2(event->mval)};
+ char select;
+ int i;
+ bool do_select = RNA_boolean_get(op->ptr, "select");
+ bool align = RNA_boolean_get(op->ptr, "align");
+ Brush *br = p->brush;
+ PaintCurve *pc = br->paint_curve;
+ PaintCurvePoint *pcp;
+
+ if (!pc)
+ return OPERATOR_PASS_THROUGH;
+
+ if (do_select) {
+ pcp = paintcurve_point_get_closest(pc, loc_fl, align, PAINT_CURVE_SELECT_THRESHOLD, &select);
+ }
+ else {
+ pcp = NULL;
+ /* just find first selected point */
+ for (i = 0; i < pc->tot_points; i++) {
+ if ((select = paintcurve_point_side_index(&pc->points[i].bez, i == 0, SEL_F3))) {
+ pcp = &pc->points[i];
+ break;
+ }
+ }
+ }
+
+ if (pcp) {
+ ARegion *ar = 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);
+ psd->event = event->type;
+ psd->pcp = pcp;
+ psd->select = paintcurve_point_co_index(select);
+ for (i = 0; i < 3; i++) {
+ copy_v2_v2(psd->point_initial_loc[i], pcp->bez.vec[i]);
+ }
+ psd->align = align;
+ op->customdata = psd;
+
+ /* first, clear all selection from points */
+ for (i = 0; i < pc->tot_points; i++)
+ pc->points[i].bez.f1 = pc->points[i].bez.f3 = pc->points[i].bez.f2 = 0;
+
+ /* only select the active point */
+ PAINT_CURVE_POINT_SELECT(pcp, psd->select);
+ 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);
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ return OPERATOR_PASS_THROUGH;
}
static int paintcurve_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- PointSlideData *psd = op->customdata;
-
- if (event->type == psd->event && event->val == KM_RELEASE) {
- MEM_freeN(psd);
- ED_paintcurve_undo_push_begin(op->type->name);
- ED_paintcurve_undo_push_end();
- return OPERATOR_FINISHED;
- }
-
- switch (event->type) {
- case MOUSEMOVE:
- {
- ARegion *ar = 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) {
- int i;
- for (i = 0; i < 3; i++)
- add_v2_v2v2(psd->pcp->bez.vec[i], diff, psd->point_initial_loc[i]);
- }
- else {
- add_v2_v2(diff, psd->point_initial_loc[psd->select]);
- copy_v2_v2(psd->pcp->bez.vec[psd->select], diff);
-
- if (psd->align) {
- char opposite = (psd->select == 0) ? 2 : 0;
- sub_v2_v2v2(diff, psd->pcp->bez.vec[1], psd->pcp->bez.vec[psd->select]);
- add_v2_v2v2(psd->pcp->bez.vec[opposite], psd->pcp->bez.vec[1], diff);
- }
- }
- WM_paint_cursor_tag_redraw(window, ar);
- break;
- }
- default:
- break;
- }
-
- return OPERATOR_RUNNING_MODAL;
+ PointSlideData *psd = op->customdata;
+
+ if (event->type == psd->event && event->val == KM_RELEASE) {
+ MEM_freeN(psd);
+ ED_paintcurve_undo_push_begin(op->type->name);
+ ED_paintcurve_undo_push_end();
+ return OPERATOR_FINISHED;
+ }
+
+ switch (event->type) {
+ case MOUSEMOVE: {
+ ARegion *ar = 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) {
+ int i;
+ for (i = 0; i < 3; i++)
+ add_v2_v2v2(psd->pcp->bez.vec[i], diff, psd->point_initial_loc[i]);
+ }
+ else {
+ add_v2_v2(diff, psd->point_initial_loc[psd->select]);
+ copy_v2_v2(psd->pcp->bez.vec[psd->select], diff);
+
+ if (psd->align) {
+ char opposite = (psd->select == 0) ? 2 : 0;
+ sub_v2_v2v2(diff, psd->pcp->bez.vec[1], psd->pcp->bez.vec[psd->select]);
+ add_v2_v2v2(psd->pcp->bez.vec[opposite], psd->pcp->bez.vec[1], diff);
+ }
+ }
+ WM_paint_cursor_tag_redraw(window, ar);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
-
void PAINTCURVE_OT_slide(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Slide Paint Curve Point";
- ot->description = "Select and slide paint curve point";
- ot->idname = "PAINTCURVE_OT_slide";
-
- /* api callbacks */
- ot->invoke = paintcurve_slide_invoke;
- ot->modal = paintcurve_slide_modal;
- ot->poll = paint_curve_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "align", false, "Align Handles", "Aligns opposite point handle during transform");
- RNA_def_boolean(ot->srna, "select", true, "Select", "Attempt to select a point handle before transform");
+ /* identifiers */
+ ot->name = "Slide Paint Curve Point";
+ ot->description = "Select and slide paint curve point";
+ ot->idname = "PAINTCURVE_OT_slide";
+
+ /* api callbacks */
+ ot->invoke = paintcurve_slide_invoke;
+ ot->modal = paintcurve_slide_modal;
+ ot->poll = paint_curve_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(
+ ot->srna, "align", false, "Align Handles", "Aligns opposite point handle during transform");
+ RNA_def_boolean(
+ ot->srna, "select", true, "Select", "Attempt to select a point handle before transform");
}
static int paintcurve_draw_exec(bContext *C, wmOperator *UNUSED(op))
{
- ePaintMode mode = BKE_paintmode_get_active_from_context(C);
- const char *name;
-
- switch (mode) {
- case PAINT_MODE_TEXTURE_2D:
- case PAINT_MODE_TEXTURE_3D:
- name = "PAINT_OT_image_paint";
- break;
- case PAINT_MODE_WEIGHT:
- name = "PAINT_OT_weight_paint";
- break;
- case PAINT_MODE_VERTEX:
- name = "PAINT_OT_vertex_paint";
- break;
- case PAINT_MODE_SCULPT:
- name = "SCULPT_OT_brush_stroke";
- break;
- default:
- return OPERATOR_PASS_THROUGH;
- }
-
- return WM_operator_name_call(C, name, WM_OP_INVOKE_DEFAULT, NULL);
+ ePaintMode mode = BKE_paintmode_get_active_from_context(C);
+ const char *name;
+
+ switch (mode) {
+ case PAINT_MODE_TEXTURE_2D:
+ case PAINT_MODE_TEXTURE_3D:
+ name = "PAINT_OT_image_paint";
+ break;
+ case PAINT_MODE_WEIGHT:
+ name = "PAINT_OT_weight_paint";
+ break;
+ case PAINT_MODE_VERTEX:
+ name = "PAINT_OT_vertex_paint";
+ break;
+ case PAINT_MODE_SCULPT:
+ name = "SCULPT_OT_brush_stroke";
+ break;
+ default:
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ return WM_operator_name_call(C, name, WM_OP_INVOKE_DEFAULT, NULL);
}
void PAINTCURVE_OT_draw(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Draw Curve";
- ot->description = "Draw curve";
- ot->idname = "PAINTCURVE_OT_draw";
+ /* identifiers */
+ ot->name = "Draw Curve";
+ ot->description = "Draw curve";
+ ot->idname = "PAINTCURVE_OT_draw";
- /* api callbacks */
- ot->exec = paintcurve_draw_exec;
- ot->poll = paint_curve_poll;
+ /* api callbacks */
+ ot->exec = paintcurve_draw_exec;
+ ot->poll = paint_curve_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
static int paintcurve_cursor_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- ePaintMode mode = BKE_paintmode_get_active_from_context(C);
-
- switch (mode) {
- case PAINT_MODE_TEXTURE_2D:
- {
- ARegion *ar = CTX_wm_region(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- float location[2];
-
- if (!sima)
- return OPERATOR_CANCELLED;
-
- UI_view2d_region_to_view(&ar->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;
- }
- default:
- ED_view3d_cursor3d_update(C, event->mval, true, V3D_CURSOR_ORIENT_VIEW);
- break;
- }
-
- return OPERATOR_FINISHED;
+ ePaintMode mode = BKE_paintmode_get_active_from_context(C);
+
+ switch (mode) {
+ case PAINT_MODE_TEXTURE_2D: {
+ ARegion *ar = CTX_wm_region(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ float location[2];
+
+ if (!sima)
+ return OPERATOR_CANCELLED;
+
+ UI_view2d_region_to_view(
+ &ar->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;
+ }
+ default:
+ ED_view3d_cursor3d_update(C, event->mval, true, V3D_CURSOR_ORIENT_VIEW);
+ break;
+ }
+
+ return OPERATOR_FINISHED;
}
void PAINTCURVE_OT_cursor(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Place Cursor";
- ot->description = "Place cursor";
- ot->idname = "PAINTCURVE_OT_cursor";
+ /* identifiers */
+ ot->name = "Place Cursor";
+ ot->description = "Place cursor";
+ ot->idname = "PAINTCURVE_OT_cursor";
- /* api callbacks */
- ot->invoke = paintcurve_cursor_invoke;
- ot->poll = paint_curve_poll;
+ /* api callbacks */
+ ot->invoke = paintcurve_cursor_invoke;
+ ot->poll = paint_curve_poll;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
diff --git a/source/blender/editors/sculpt_paint/paint_curve_undo.c b/source/blender/editors/sculpt_paint/paint_curve_undo.c
index 1eaed8eabb8..c03cb69df88 100644
--- a/source/blender/editors/sculpt_paint/paint_curve_undo.c
+++ b/source/blender/editors/sculpt_paint/paint_curve_undo.c
@@ -44,30 +44,30 @@
* \{ */
typedef struct UndoCurve {
- PaintCurvePoint *points; /* points of curve */
- int tot_points;
- int add_index;
+ PaintCurvePoint *points; /* points of curve */
+ int tot_points;
+ int add_index;
} UndoCurve;
static void undocurve_from_paintcurve(UndoCurve *uc, const PaintCurve *pc)
{
- BLI_assert(BLI_array_is_zeroed(uc, 1));
- uc->points = MEM_dupallocN(pc->points);
- uc->tot_points = pc->tot_points;
- uc->add_index = pc->add_index;
+ BLI_assert(BLI_array_is_zeroed(uc, 1));
+ uc->points = MEM_dupallocN(pc->points);
+ uc->tot_points = pc->tot_points;
+ uc->add_index = pc->add_index;
}
static void undocurve_to_paintcurve(const UndoCurve *uc, PaintCurve *pc)
{
- MEM_SAFE_FREE(pc->points);
- pc->points = MEM_dupallocN(uc->points);
- pc->tot_points = uc->tot_points;
- pc->add_index = uc->add_index;
+ MEM_SAFE_FREE(pc->points);
+ pc->points = MEM_dupallocN(uc->points);
+ pc->tot_points = uc->tot_points;
+ pc->add_index = uc->add_index;
}
static void undocurve_free_data(UndoCurve *uc)
{
- MEM_SAFE_FREE(uc->points);
+ MEM_SAFE_FREE(uc->points);
}
/** \} */
@@ -77,92 +77,96 @@ static void undocurve_free_data(UndoCurve *uc)
* \{ */
typedef struct PaintCurveUndoStep {
- UndoStep step;
- PaintCurve *pc;
- UndoCurve data;
+ UndoStep step;
+ PaintCurve *pc;
+ UndoCurve data;
} PaintCurveUndoStep;
static bool paintcurve_undosys_poll(bContext *C)
{
- if (C == NULL || !paint_curve_poll(C)) {
- return false;
- }
- Paint *p = BKE_paint_get_active_from_context(C);
- return (p->brush && p->brush->paint_curve);
+ if (C == NULL || !paint_curve_poll(C)) {
+ return false;
+ }
+ Paint *p = BKE_paint_get_active_from_context(C);
+ return (p->brush && p->brush->paint_curve);
}
static void paintcurve_undosys_step_encode_init(struct bContext *C, UndoStep *us_p)
{
- /* XXX, use to set the undo type only. */
- UNUSED_VARS(C, us_p);
+ /* XXX, use to set the undo type only. */
+ UNUSED_VARS(C, us_p);
}
-static bool paintcurve_undosys_step_encode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p)
+static bool paintcurve_undosys_step_encode(struct bContext *C,
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p)
{
- if (C == NULL || !paint_curve_poll(C)) {
- return false;
- }
- Paint *p = BKE_paint_get_active_from_context(C);
- PaintCurve *pc = p ? (p->brush ? p->brush->paint_curve : NULL) : NULL;
- if (pc == NULL) {
- return false;
- }
-
- PaintCurveUndoStep *us = (PaintCurveUndoStep *)us_p;
- BLI_assert(us->step.data_size == 0);
-
- us->pc = pc;
- undocurve_from_paintcurve(&us->data, pc);
-
- return true;
+ if (C == NULL || !paint_curve_poll(C)) {
+ return false;
+ }
+ Paint *p = BKE_paint_get_active_from_context(C);
+ PaintCurve *pc = p ? (p->brush ? p->brush->paint_curve : NULL) : NULL;
+ if (pc == NULL) {
+ return false;
+ }
+
+ PaintCurveUndoStep *us = (PaintCurveUndoStep *)us_p;
+ BLI_assert(us->step.data_size == 0);
+
+ us->pc = pc;
+ undocurve_from_paintcurve(&us->data, pc);
+
+ return true;
}
-static void paintcurve_undosys_step_decode(struct bContext *UNUSED(C), struct Main *UNUSED(bmain), UndoStep *us_p, int UNUSED(dir))
+static void paintcurve_undosys_step_decode(struct bContext *UNUSED(C),
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p,
+ int UNUSED(dir))
{
- PaintCurveUndoStep *us = (PaintCurveUndoStep *)us_p;
- undocurve_to_paintcurve(&us->data, us->pc);
+ PaintCurveUndoStep *us = (PaintCurveUndoStep *)us_p;
+ undocurve_to_paintcurve(&us->data, us->pc);
}
static void paintcurve_undosys_step_free(UndoStep *us_p)
{
- PaintCurveUndoStep *us = (PaintCurveUndoStep *)us_p;
- undocurve_free_data(&us->data);
+ PaintCurveUndoStep *us = (PaintCurveUndoStep *)us_p;
+ undocurve_free_data(&us->data);
}
/* Export for ED_undo_sys. */
void ED_paintcurve_undosys_type(UndoType *ut)
{
- ut->name = "Paint Curve";
- /* don't poll for now */
- ut->poll = paintcurve_undosys_poll;
- ut->step_encode_init = paintcurve_undosys_step_encode_init;
- ut->step_encode = paintcurve_undosys_step_encode;
- ut->step_decode = paintcurve_undosys_step_decode;
- ut->step_free = paintcurve_undosys_step_free;
+ ut->name = "Paint Curve";
+ /* don't poll for now */
+ ut->poll = paintcurve_undosys_poll;
+ ut->step_encode_init = paintcurve_undosys_step_encode_init;
+ ut->step_encode = paintcurve_undosys_step_encode;
+ ut->step_decode = paintcurve_undosys_step_decode;
+ ut->step_free = paintcurve_undosys_step_free;
- ut->use_context = false;
+ ut->use_context = false;
- ut->step_size = sizeof(PaintCurveUndoStep);
+ ut->step_size = sizeof(PaintCurveUndoStep);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Utilities
* \{ */
void ED_paintcurve_undo_push_begin(const char *name)
{
- UndoStack *ustack = ED_undo_stack_get();
- bContext *C = NULL; /* special case, we never read from this. */
- BKE_undosys_step_push_init_with_type(ustack, C, name, BKE_UNDOSYS_TYPE_PAINTCURVE);
+ UndoStack *ustack = ED_undo_stack_get();
+ bContext *C = NULL; /* special case, we never read from this. */
+ BKE_undosys_step_push_init_with_type(ustack, C, name, BKE_UNDOSYS_TYPE_PAINTCURVE);
}
void ED_paintcurve_undo_push_end(void)
{
- UndoStack *ustack = ED_undo_stack_get();
- BKE_undosys_step_push(ustack, NULL, NULL);
+ UndoStack *ustack = ED_undo_stack_get();
+ BKE_undosys_step_push(ustack, NULL, NULL);
}
/** \} */
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index b64c23ad0b6..c1f87f676e2 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -61,273 +61,241 @@
#include <assert.h>
/* 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)
+static bool is_effected(PartialVisArea area,
+ float planes[4][4],
+ const float co[3],
+ const float mask)
{
- if (area == PARTIALVIS_ALL)
- return 1;
- else if (area == PARTIALVIS_MASKED) {
- return mask > 0.5f;
- }
- else {
- bool inside = isect_point_planes_v3(planes, 4, co);
- return ((inside && area == PARTIALVIS_INSIDE) ||
- (!inside && area == PARTIALVIS_OUTSIDE));
- }
+ if (area == PARTIALVIS_ALL)
+ return 1;
+ else if (area == PARTIALVIS_MASKED) {
+ return mask > 0.5f;
+ }
+ else {
+ bool inside = isect_point_planes_v3(planes, 4, co);
+ return ((inside && area == PARTIALVIS_INSIDE) || (!inside && area == PARTIALVIS_OUTSIDE));
+ }
}
-static void partialvis_update_mesh(
- Object *ob,
- PBVH *pbvh,
- PBVHNode *node,
- PartialVisAction action,
- PartialVisArea area,
- float planes[4][4])
+static void partialvis_update_mesh(Object *ob,
+ PBVH *pbvh,
+ PBVHNode *node,
+ PartialVisAction action,
+ PartialVisArea area,
+ float planes[4][4])
{
- Mesh *me = ob->data;
- MVert *mvert;
- const float *paint_mask;
- const int *vert_indices;
- int totvert, i;
- bool any_changed = false, any_visible = false;
-
- BKE_pbvh_node_num_verts(pbvh, node, NULL, &totvert);
- 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);
-
- 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 */
- if (is_effected(area, planes, v->co, vmask)) {
- if (action == PARTIALVIS_HIDE)
- v->flag |= ME_HIDE;
- else
- v->flag &= ~ME_HIDE;
- any_changed = true;
- }
-
- if (!(v->flag & ME_HIDE))
- any_visible = true;
- }
-
- if (any_changed) {
- BKE_pbvh_node_mark_rebuild_draw(node);
- BKE_pbvh_node_fully_hidden_set(node, !any_visible);
- }
+ Mesh *me = ob->data;
+ MVert *mvert;
+ const float *paint_mask;
+ const int *vert_indices;
+ int totvert, i;
+ bool any_changed = false, any_visible = false;
+
+ BKE_pbvh_node_num_verts(pbvh, node, NULL, &totvert);
+ 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);
+
+ 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 */
+ if (is_effected(area, planes, v->co, vmask)) {
+ if (action == PARTIALVIS_HIDE)
+ v->flag |= ME_HIDE;
+ else
+ v->flag &= ~ME_HIDE;
+ any_changed = true;
+ }
+
+ if (!(v->flag & ME_HIDE))
+ any_visible = true;
+ }
+
+ if (any_changed) {
+ BKE_pbvh_node_mark_rebuild_draw(node);
+ BKE_pbvh_node_fully_hidden_set(node, !any_visible);
+ }
}
/* Hide or show elements in multires grids with a special GridFlags
* customdata layer. */
-static void partialvis_update_grids(
- Object *ob,
- PBVH *pbvh,
- PBVHNode *node,
- PartialVisAction action,
- PartialVisArea area,
- float planes[4][4])
+static void partialvis_update_grids(Object *ob,
+ PBVH *pbvh,
+ PBVHNode *node,
+ PartialVisAction action,
+ PartialVisArea area,
+ float planes[4][4])
{
- CCGElem **grids;
- CCGKey key;
- BLI_bitmap **grid_hidden;
- int *grid_indices, totgrid, i;
- bool any_changed = false, any_visible = false;
-
-
- /* get PBVH data */
- BKE_pbvh_node_get_grids(
- pbvh, node,
- &grid_indices, &totgrid, NULL, NULL,
- &grids);
- grid_hidden = BKE_pbvh_grid_hidden(pbvh);
- BKE_pbvh_get_grid_key(pbvh, &key);
-
- sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
-
- for (i = 0; i < totgrid; i++) {
- int any_hidden = 0;
- int g = grid_indices[i], x, y;
- BLI_bitmap *gh = grid_hidden[g];
-
- if (!gh) {
- switch (action) {
- case PARTIALVIS_HIDE:
- /* 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 */
- continue;
- }
- }
- else if (action == PARTIALVIS_SHOW && area == PARTIALVIS_ALL) {
- /* special case if we're showing all, just free the
- * grid */
- MEM_freeN(gh);
- grid_hidden[g] = NULL;
- any_changed = true;
- any_visible = true;
- continue;
- }
-
- for (y = 0; y < key.grid_size; y++) {
- for (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 */
- if (is_effected(area, planes, co, mask)) {
- /* 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 */
- if (BLI_BITMAP_TEST(gh, y * key.grid_size + x))
- any_hidden = true;
- else
- any_visible = true;
- }
- }
-
- /* 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 */
- if (any_changed) {
- BKE_pbvh_node_mark_rebuild_draw(node);
- BKE_pbvh_node_fully_hidden_set(node, !any_visible);
- multires_mark_as_modified(ob, MULTIRES_HIDDEN_MODIFIED);
- }
+ CCGElem **grids;
+ CCGKey key;
+ BLI_bitmap **grid_hidden;
+ int *grid_indices, totgrid, i;
+ bool any_changed = false, any_visible = false;
+
+ /* get PBVH data */
+ BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, NULL, NULL, &grids);
+ grid_hidden = BKE_pbvh_grid_hidden(pbvh);
+ BKE_pbvh_get_grid_key(pbvh, &key);
+
+ sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
+
+ for (i = 0; i < totgrid; i++) {
+ int any_hidden = 0;
+ int g = grid_indices[i], x, y;
+ BLI_bitmap *gh = grid_hidden[g];
+
+ if (!gh) {
+ switch (action) {
+ case PARTIALVIS_HIDE:
+ /* 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 */
+ continue;
+ }
+ }
+ else if (action == PARTIALVIS_SHOW && area == PARTIALVIS_ALL) {
+ /* special case if we're showing all, just free the
+ * grid */
+ MEM_freeN(gh);
+ grid_hidden[g] = NULL;
+ any_changed = true;
+ any_visible = true;
+ continue;
+ }
+
+ for (y = 0; y < key.grid_size; y++) {
+ for (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 */
+ if (is_effected(area, planes, co, mask)) {
+ /* 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 */
+ if (BLI_BITMAP_TEST(gh, y * key.grid_size + x))
+ any_hidden = true;
+ else
+ any_visible = true;
+ }
+ }
+
+ /* 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 */
+ if (any_changed) {
+ BKE_pbvh_node_mark_rebuild_draw(node);
+ BKE_pbvh_node_fully_hidden_set(node, !any_visible);
+ multires_mark_as_modified(ob, MULTIRES_HIDDEN_MODIFIED);
+ }
}
-static void partialvis_update_bmesh_verts(
- BMesh *bm,
- GSet *verts,
- PartialVisAction action,
- PartialVisArea area,
- float planes[4][4],
- bool *any_changed,
- bool *any_visible)
+static void partialvis_update_bmesh_verts(BMesh *bm,
+ GSet *verts,
+ PartialVisAction action,
+ PartialVisArea area,
+ float planes[4][4],
+ bool *any_changed,
+ bool *any_visible)
{
- GSetIterator gs_iter;
-
- GSET_ITER (gs_iter, verts) {
- 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 */
- if (is_effected(area, planes, v->co, *vmask)) {
- if (action == PARTIALVIS_HIDE)
- BM_elem_flag_enable(v, BM_ELEM_HIDDEN);
- else
- BM_elem_flag_disable(v, BM_ELEM_HIDDEN);
- (*any_changed) = true;
- }
-
- if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN))
- (*any_visible) = true;
- }
+ GSetIterator gs_iter;
+
+ GSET_ITER (gs_iter, verts) {
+ 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 */
+ if (is_effected(area, planes, v->co, *vmask)) {
+ if (action == PARTIALVIS_HIDE)
+ BM_elem_flag_enable(v, BM_ELEM_HIDDEN);
+ else
+ BM_elem_flag_disable(v, BM_ELEM_HIDDEN);
+ (*any_changed) = true;
+ }
+
+ if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN))
+ (*any_visible) = true;
+ }
}
static void partialvis_update_bmesh_faces(GSet *faces)
{
- GSetIterator gs_iter;
+ GSetIterator gs_iter;
- GSET_ITER (gs_iter, faces) {
- BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
+ GSET_ITER (gs_iter, faces) {
+ BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
- if (paint_is_bmesh_face_hidden(f))
- BM_elem_flag_enable(f, BM_ELEM_HIDDEN);
- else
- BM_elem_flag_disable(f, BM_ELEM_HIDDEN);
- }
+ if (paint_is_bmesh_face_hidden(f))
+ BM_elem_flag_enable(f, BM_ELEM_HIDDEN);
+ else
+ BM_elem_flag_disable(f, BM_ELEM_HIDDEN);
+ }
}
-static void partialvis_update_bmesh(
- Object *ob,
- PBVH *pbvh,
- PBVHNode *node,
- PartialVisAction action,
- PartialVisArea area,
- float planes[4][4])
+static void partialvis_update_bmesh(Object *ob,
+ PBVH *pbvh,
+ PBVHNode *node,
+ PartialVisAction action,
+ PartialVisArea area,
+ float planes[4][4])
{
- BMesh *bm;
- GSet *unique, *other, *faces;
- bool any_changed = false, any_visible = false;
-
- bm = BKE_pbvh_get_bmesh(pbvh);
- unique = BKE_pbvh_bmesh_node_unique_verts(node);
- other = BKE_pbvh_bmesh_node_other_verts(node);
- faces = BKE_pbvh_bmesh_node_faces(node);
-
- 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 */
- partialvis_update_bmesh_faces(faces);
-
- if (any_changed) {
- BKE_pbvh_node_mark_rebuild_draw(node);
- BKE_pbvh_node_fully_hidden_set(node, !any_visible);
- }
+ BMesh *bm;
+ GSet *unique, *other, *faces;
+ bool any_changed = false, any_visible = false;
+
+ bm = BKE_pbvh_get_bmesh(pbvh);
+ unique = BKE_pbvh_bmesh_node_unique_verts(node);
+ other = BKE_pbvh_bmesh_node_other_verts(node);
+ faces = BKE_pbvh_bmesh_node_faces(node);
+
+ 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 */
+ partialvis_update_bmesh_faces(faces);
+
+ if (any_changed) {
+ BKE_pbvh_node_mark_rebuild_draw(node);
+ BKE_pbvh_node_fully_hidden_set(node, !any_visible);
+ }
}
static void rect_from_props(rcti *rect, PointerRNA *ptr)
{
- rect->xmin = RNA_int_get(ptr, "xmin");
- rect->ymin = RNA_int_get(ptr, "ymin");
- rect->xmax = RNA_int_get(ptr, "xmax");
- rect->ymax = RNA_int_get(ptr, "ymax");
+ rect->xmin = RNA_int_get(ptr, "xmin");
+ rect->ymin = RNA_int_get(ptr, "ymin");
+ rect->xmax = RNA_int_get(ptr, "xmax");
+ rect->ymax = RNA_int_get(ptr, "ymax");
}
-static void clip_planes_from_rect(
- bContext *C,
- float clip_planes[4][4],
- const rcti *rect)
+static void clip_planes_from_rect(bContext *C, float clip_planes[4][4], const rcti *rect)
{
- ViewContext vc;
- BoundBox bb;
+ ViewContext vc;
+ BoundBox bb;
- view3d_operator_needs_opengl(C);
- ED_view3d_viewcontext_init(C, &vc);
- ED_view3d_clipping_calc(&bb, clip_planes, vc.ar, vc.obact, rect);
- negate_m4(clip_planes);
+ view3d_operator_needs_opengl(C);
+ ED_view3d_viewcontext_init(C, &vc);
+ ED_view3d_clipping_calc(&bb, clip_planes, vc.ar, vc.obact, rect);
+ negate_m4(clip_planes);
}
/* If mode is inside, get all PBVH nodes that lie at least partially
@@ -335,144 +303,148 @@ static void clip_planes_from_rect(
* that lie at least partially outside the volume. If showing all, get
* all nodes. */
static void get_pbvh_nodes(
- PBVH *pbvh,
- PBVHNode ***nodes,
- int *totnode,
- float clip_planes[4][4],
- PartialVisArea mode)
+ PBVH *pbvh, PBVHNode ***nodes, int *totnode, float clip_planes[4][4], PartialVisArea mode)
{
- BKE_pbvh_SearchCallback cb = NULL;
-
- /* select search callback */
- switch (mode) {
- case PARTIALVIS_INSIDE:
- cb = BKE_pbvh_node_planes_contain_AABB;
- break;
- case PARTIALVIS_OUTSIDE:
- cb = BKE_pbvh_node_planes_exclude_AABB;
- break;
- case PARTIALVIS_ALL:
- case PARTIALVIS_MASKED:
- break;
- }
-
- BKE_pbvh_search_gather(pbvh, cb, clip_planes, nodes, totnode);
+ BKE_pbvh_SearchCallback cb = NULL;
+
+ /* select search callback */
+ switch (mode) {
+ case PARTIALVIS_INSIDE:
+ cb = BKE_pbvh_node_planes_contain_AABB;
+ break;
+ case PARTIALVIS_OUTSIDE:
+ cb = BKE_pbvh_node_planes_exclude_AABB;
+ break;
+ case PARTIALVIS_ALL:
+ case PARTIALVIS_MASKED:
+ break;
+ }
+
+ BKE_pbvh_search_gather(pbvh, cb, clip_planes, nodes, totnode);
}
static int hide_show_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
- Object *ob = CTX_data_active_object(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Mesh *me = ob->data;
- PartialVisAction action;
- PartialVisArea area;
- PBVH *pbvh;
- PBVHNode **nodes;
- PBVHType pbvh_type;
- float clip_planes[4][4];
- rcti rect;
- int totnode, i;
-
- /* read operator properties */
- action = RNA_enum_get(op->ptr, "action");
- area = RNA_enum_get(op->ptr, "area");
- rect_from_props(&rect, op->ptr);
-
- clip_planes_from_rect(C, clip_planes, &rect);
-
- pbvh = BKE_sculpt_object_pbvh_ensure(depsgraph, ob);
- BLI_assert(ob->sculpt->pbvh == pbvh);
-
- get_pbvh_nodes(pbvh, &nodes, &totnode, clip_planes, area);
- pbvh_type = BKE_pbvh_type(pbvh);
-
- /* start undo */
- switch (action) {
- case PARTIALVIS_HIDE:
- sculpt_undo_push_begin("Hide area");
- break;
- case PARTIALVIS_SHOW:
- sculpt_undo_push_begin("Show area");
- break;
- }
-
- for (i = 0; i < totnode; i++) {
- switch (pbvh_type) {
- case PBVH_FACES:
- partialvis_update_mesh(ob, pbvh, nodes[i], action, area, clip_planes);
- break;
- case PBVH_GRIDS:
- partialvis_update_grids(ob, pbvh, nodes[i], action, area, clip_planes);
- break;
- case PBVH_BMESH:
- partialvis_update_bmesh(ob, pbvh, nodes[i], action, area, clip_planes);
- break;
- }
- }
-
- if (nodes)
- MEM_freeN(nodes);
-
- /* 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) */
- if (pbvh_type == PBVH_FACES) {
- BKE_mesh_flush_hidden_from_verts(me);
- }
-
- ED_region_tag_redraw(ar);
-
- return OPERATOR_FINISHED;
+ ARegion *ar = CTX_wm_region(C);
+ Object *ob = CTX_data_active_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Mesh *me = ob->data;
+ PartialVisAction action;
+ PartialVisArea area;
+ PBVH *pbvh;
+ PBVHNode **nodes;
+ PBVHType pbvh_type;
+ float clip_planes[4][4];
+ rcti rect;
+ int totnode, i;
+
+ /* read operator properties */
+ action = RNA_enum_get(op->ptr, "action");
+ area = RNA_enum_get(op->ptr, "area");
+ rect_from_props(&rect, op->ptr);
+
+ clip_planes_from_rect(C, clip_planes, &rect);
+
+ pbvh = BKE_sculpt_object_pbvh_ensure(depsgraph, ob);
+ BLI_assert(ob->sculpt->pbvh == pbvh);
+
+ get_pbvh_nodes(pbvh, &nodes, &totnode, clip_planes, area);
+ pbvh_type = BKE_pbvh_type(pbvh);
+
+ /* start undo */
+ switch (action) {
+ case PARTIALVIS_HIDE:
+ sculpt_undo_push_begin("Hide area");
+ break;
+ case PARTIALVIS_SHOW:
+ sculpt_undo_push_begin("Show area");
+ break;
+ }
+
+ for (i = 0; i < totnode; i++) {
+ switch (pbvh_type) {
+ case PBVH_FACES:
+ partialvis_update_mesh(ob, pbvh, nodes[i], action, area, clip_planes);
+ break;
+ case PBVH_GRIDS:
+ partialvis_update_grids(ob, pbvh, nodes[i], action, area, clip_planes);
+ break;
+ case PBVH_BMESH:
+ partialvis_update_bmesh(ob, pbvh, nodes[i], action, area, clip_planes);
+ break;
+ }
+ }
+
+ if (nodes)
+ MEM_freeN(nodes);
+
+ /* 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) */
+ if (pbvh_type == PBVH_FACES) {
+ BKE_mesh_flush_hidden_from_verts(me);
+ }
+
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_FINISHED;
}
static int hide_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- PartialVisArea area = RNA_enum_get(op->ptr, "area");
+ PartialVisArea area = RNA_enum_get(op->ptr, "area");
- if (!ELEM(area, PARTIALVIS_ALL, PARTIALVIS_MASKED))
- return WM_gesture_box_invoke(C, op, event);
- else
- return op->type->exec(C, op);
+ if (!ELEM(area, PARTIALVIS_ALL, PARTIALVIS_MASKED))
+ return WM_gesture_box_invoke(C, op, event);
+ else
+ return op->type->exec(C, op);
}
void PAINT_OT_hide_show(struct wmOperatorType *ot)
{
- static const EnumPropertyItem action_items[] = {
- {PARTIALVIS_HIDE, "HIDE", 0, "Hide", "Hide vertices"},
- {PARTIALVIS_SHOW, "SHOW", 0, "Show", "Show vertices"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem area_items[] = {
- {PARTIALVIS_OUTSIDE, "OUTSIDE", 0, "Outside", "Hide or show vertices outside the selection"},
- {PARTIALVIS_INSIDE, "INSIDE", 0, "Inside", "Hide or show vertices inside the selection"},
- {PARTIALVIS_ALL, "ALL", 0, "All", "Hide or show all vertices"},
- {PARTIALVIS_MASKED, "MASKED", 0, "Masked", "Hide or show vertices that are masked (minimum mask value of 0.5)"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Hide/Show";
- ot->idname = "PAINT_OT_hide_show";
- ot->description = "Hide/show some vertices";
-
- /* 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;
-
- ot->flag = OPTYPE_REGISTER;
-
- /* rna */
- RNA_def_enum(ot->srna, "action", action_items, PARTIALVIS_HIDE,
- "Action", "Whether to hide or show vertices");
- RNA_def_enum(ot->srna, "area", area_items, PARTIALVIS_INSIDE,
- "Area", "Which vertices to hide or show");
-
- WM_operator_properties_border(ot);
+ static const EnumPropertyItem action_items[] = {
+ {PARTIALVIS_HIDE, "HIDE", 0, "Hide", "Hide vertices"},
+ {PARTIALVIS_SHOW, "SHOW", 0, "Show", "Show vertices"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem area_items[] = {
+ {PARTIALVIS_OUTSIDE, "OUTSIDE", 0, "Outside", "Hide or show vertices outside the selection"},
+ {PARTIALVIS_INSIDE, "INSIDE", 0, "Inside", "Hide or show vertices inside the selection"},
+ {PARTIALVIS_ALL, "ALL", 0, "All", "Hide or show all vertices"},
+ {PARTIALVIS_MASKED,
+ "MASKED",
+ 0,
+ "Masked",
+ "Hide or show vertices that are masked (minimum mask value of 0.5)"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Hide/Show";
+ ot->idname = "PAINT_OT_hide_show";
+ ot->description = "Hide/show some vertices";
+
+ /* 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;
+
+ ot->flag = OPTYPE_REGISTER;
+
+ /* rna */
+ RNA_def_enum(ot->srna,
+ "action",
+ action_items,
+ PARTIALVIS_HIDE,
+ "Action",
+ "Whether to hide or show vertices");
+ RNA_def_enum(
+ ot->srna, "area", area_items, PARTIALVIS_INSIDE, "Area", "Which vertices to hide or show");
+
+ WM_operator_properties_border(ot);
}
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 237e60cd5e0..3a3f4335fd5 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -54,7 +54,6 @@
#include "BKE_paint.h"
#include "BKE_undo_system.h"
-
#include "DEG_depsgraph.h"
#include "UI_interface.h"
@@ -78,7 +77,6 @@
#include "GPU_immediate.h"
#include "GPU_state.h"
-
#include "IMB_colormanagement.h"
#include "paint_intern.h"
@@ -90,662 +88,679 @@ static ImagePaintPartialRedraw imapaintpartial = {0, 0, 0, 0, 0};
ImagePaintPartialRedraw *get_imapaintpartial(void)
{
- return &imapaintpartial;
+ return &imapaintpartial;
}
void set_imapaintpartial(struct ImagePaintPartialRedraw *ippr)
{
- imapaintpartial = *ippr;
+ imapaintpartial = *ippr;
}
/* Imagepaint Partial Redraw & Dirty Region */
void ED_imapaint_clear_partial_redraw(void)
{
- memset(&imapaintpartial, 0, sizeof(imapaintpartial));
+ memset(&imapaintpartial, 0, sizeof(imapaintpartial));
}
-void imapaint_region_tiles(ImBuf *ibuf, int x, int y, int w, int h, int *tx, int *ty, int *tw, int *th)
+void imapaint_region_tiles(
+ ImBuf *ibuf, int x, int y, int w, int h, int *tx, int *ty, int *tw, int *th)
{
- int srcx = 0, srcy = 0;
+ int srcx = 0, srcy = 0;
- IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h);
+ IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h);
- *tw = ((x + w - 1) >> IMAPAINT_TILE_BITS);
- *th = ((y + h - 1) >> IMAPAINT_TILE_BITS);
- *tx = (x >> IMAPAINT_TILE_BITS);
- *ty = (y >> IMAPAINT_TILE_BITS);
+ *tw = ((x + w - 1) >> IMAPAINT_TILE_BITS);
+ *th = ((y + h - 1) >> IMAPAINT_TILE_BITS);
+ *tx = (x >> IMAPAINT_TILE_BITS);
+ *ty = (y >> IMAPAINT_TILE_BITS);
}
void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h, bool find_old)
{
- ImBuf *tmpibuf = NULL;
- int tilex, tiley, tilew, tileh, tx, ty;
- int srcx = 0, srcy = 0;
+ ImBuf *tmpibuf = NULL;
+ int tilex, tiley, tilew, tileh, tx, ty;
+ int srcx = 0, srcy = 0;
- IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h);
+ IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h);
- if (w == 0 || h == 0)
- return;
+ if (w == 0 || h == 0)
+ return;
- if (!imapaintpartial.enabled) {
- imapaintpartial.x1 = x;
- imapaintpartial.y1 = y;
- imapaintpartial.x2 = x + w;
- imapaintpartial.y2 = y + h;
- imapaintpartial.enabled = 1;
- }
- else {
- imapaintpartial.x1 = min_ii(imapaintpartial.x1, x);
- imapaintpartial.y1 = min_ii(imapaintpartial.y1, y);
- imapaintpartial.x2 = max_ii(imapaintpartial.x2, x + w);
- imapaintpartial.y2 = max_ii(imapaintpartial.y2, y + h);
- }
+ if (!imapaintpartial.enabled) {
+ imapaintpartial.x1 = x;
+ imapaintpartial.y1 = y;
+ imapaintpartial.x2 = x + w;
+ imapaintpartial.y2 = y + h;
+ imapaintpartial.enabled = 1;
+ }
+ else {
+ imapaintpartial.x1 = min_ii(imapaintpartial.x1, x);
+ imapaintpartial.y1 = min_ii(imapaintpartial.y1, y);
+ imapaintpartial.x2 = max_ii(imapaintpartial.x2, x + w);
+ imapaintpartial.y2 = max_ii(imapaintpartial.y2, y + h);
+ }
- imapaint_region_tiles(ibuf, x, y, w, h, &tilex, &tiley, &tilew, &tileh);
+ imapaint_region_tiles(ibuf, x, y, w, h, &tilex, &tiley, &tilew, &tileh);
- ListBase *undo_tiles = ED_image_undo_get_tiles();
+ ListBase *undo_tiles = ED_image_undo_get_tiles();
- for (ty = tiley; ty <= tileh; ty++)
- for (tx = tilex; tx <= tilew; tx++)
- image_undo_push_tile(undo_tiles, ima, ibuf, &tmpibuf, tx, ty, NULL, NULL, false, find_old);
+ for (ty = tiley; ty <= tileh; ty++)
+ for (tx = tilex; tx <= tilew; tx++)
+ image_undo_push_tile(undo_tiles, ima, ibuf, &tmpibuf, tx, ty, NULL, NULL, false, find_old);
- ibuf->userflags |= IB_BITMAPDIRTY;
+ ibuf->userflags |= IB_BITMAPDIRTY;
- if (tmpibuf)
- IMB_freeImBuf(tmpibuf);
+ if (tmpibuf)
+ IMB_freeImBuf(tmpibuf);
}
void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint)
{
- if (imapaintpartial.x1 != imapaintpartial.x2 &&
- imapaintpartial.y1 != imapaintpartial.y2)
- {
- IMB_partial_display_buffer_update_delayed(
- ibuf, imapaintpartial.x1, imapaintpartial.y1,
- imapaintpartial.x2, imapaintpartial.y2);
- }
-
- if (ibuf->mipmap[0])
- ibuf->userflags |= IB_MIPMAP_INVALID;
-
- /* todo: should set_tpage create ->rect? */
- if (texpaint || (sima && sima->lock)) {
- int w = imapaintpartial.x2 - imapaintpartial.x1;
- int h = imapaintpartial.y2 - imapaintpartial.y1;
- if (w && h) {
- /* Testing with partial update in uv editor too */
- GPU_paint_update_image(image, (sima ? &sima->iuser : NULL), imapaintpartial.x1, imapaintpartial.y1, w, h);
- }
- }
+ if (imapaintpartial.x1 != imapaintpartial.x2 && imapaintpartial.y1 != imapaintpartial.y2) {
+ IMB_partial_display_buffer_update_delayed(
+ ibuf, imapaintpartial.x1, imapaintpartial.y1, imapaintpartial.x2, imapaintpartial.y2);
+ }
+
+ if (ibuf->mipmap[0])
+ ibuf->userflags |= IB_MIPMAP_INVALID;
+
+ /* todo: should set_tpage create ->rect? */
+ if (texpaint || (sima && sima->lock)) {
+ int w = imapaintpartial.x2 - imapaintpartial.x1;
+ int h = imapaintpartial.y2 - imapaintpartial.y1;
+ if (w && h) {
+ /* Testing with partial update in uv editor too */
+ GPU_paint_update_image(
+ image, (sima ? &sima->iuser : NULL), imapaintpartial.x1, imapaintpartial.y1, w, h);
+ }
+ }
}
/* paint blur kernels. Projective painting enforces use of a 2x2 kernel due to lagging */
BlurKernel *paint_new_blur_kernel(Brush *br, bool proj)
{
- int i, j;
- BlurKernel *kernel = MEM_mallocN(sizeof(BlurKernel), "blur kernel");
- float radius;
- int side;
- eBlurKernelType type = br->blur_mode;
-
- if (proj) {
- radius = 0.5f;
-
- side = kernel->side = 2;
- kernel->side_squared = kernel->side * kernel->side;
- kernel->wdata = MEM_mallocN(sizeof(float) * kernel->side_squared, "blur kernel data");
- kernel->pixel_len = radius;
- }
- else {
- if (br->blur_kernel_radius <= 0)
- br->blur_kernel_radius = 1;
-
- radius = br->blur_kernel_radius;
-
- side = kernel->side = radius * 2 + 1;
- kernel->side_squared = kernel->side * kernel->side;
- kernel->wdata = MEM_mallocN(sizeof(float) * kernel->side_squared, "blur kernel data");
- kernel->pixel_len = br->blur_kernel_radius;
- }
-
- switch (type) {
- case KERNEL_BOX:
- for (i = 0; i < kernel->side_squared; i++)
- kernel->wdata[i] = 1.0;
- break;
-
- case KERNEL_GAUSSIAN:
- {
- /* at 3.0 standard deviations distance, kernel is about zero */
- float standard_dev = radius / 3.0f;
-
- /* make the necessary adjustment to the value for use in the normal distribution formula */
- standard_dev = -standard_dev * standard_dev * 2;
-
- for (i = 0; i < side; i++) {
- for (j = 0; j < side; j++) {
- float idist = radius - i;
- float jdist = radius - j;
- float value = exp((idist * idist + jdist * jdist) / standard_dev);
-
- kernel->wdata[i + j * side] = value;
- }
- }
-
- break;
- }
-
- default:
- printf("unidentified kernel type, aborting\n");
- MEM_freeN(kernel->wdata);
- MEM_freeN(kernel);
- return NULL;
- }
-
- return kernel;
+ int i, j;
+ BlurKernel *kernel = MEM_mallocN(sizeof(BlurKernel), "blur kernel");
+ float radius;
+ int side;
+ eBlurKernelType type = br->blur_mode;
+
+ if (proj) {
+ radius = 0.5f;
+
+ side = kernel->side = 2;
+ kernel->side_squared = kernel->side * kernel->side;
+ kernel->wdata = MEM_mallocN(sizeof(float) * kernel->side_squared, "blur kernel data");
+ kernel->pixel_len = radius;
+ }
+ else {
+ if (br->blur_kernel_radius <= 0)
+ br->blur_kernel_radius = 1;
+
+ radius = br->blur_kernel_radius;
+
+ side = kernel->side = radius * 2 + 1;
+ kernel->side_squared = kernel->side * kernel->side;
+ kernel->wdata = MEM_mallocN(sizeof(float) * kernel->side_squared, "blur kernel data");
+ kernel->pixel_len = br->blur_kernel_radius;
+ }
+
+ switch (type) {
+ case KERNEL_BOX:
+ for (i = 0; i < kernel->side_squared; i++)
+ kernel->wdata[i] = 1.0;
+ break;
+
+ case KERNEL_GAUSSIAN: {
+ /* at 3.0 standard deviations distance, kernel is about zero */
+ float standard_dev = radius / 3.0f;
+
+ /* make the necessary adjustment to the value for use in the normal distribution formula */
+ standard_dev = -standard_dev * standard_dev * 2;
+
+ for (i = 0; i < side; i++) {
+ for (j = 0; j < side; j++) {
+ float idist = radius - i;
+ float jdist = radius - j;
+ float value = exp((idist * idist + jdist * jdist) / standard_dev);
+
+ kernel->wdata[i + j * side] = value;
+ }
+ }
+
+ break;
+ }
+
+ default:
+ printf("unidentified kernel type, aborting\n");
+ MEM_freeN(kernel->wdata);
+ MEM_freeN(kernel);
+ return NULL;
+ }
+
+ return kernel;
}
void paint_delete_blur_kernel(BlurKernel *kernel)
{
- if (kernel->wdata)
- MEM_freeN(kernel->wdata);
+ if (kernel->wdata)
+ MEM_freeN(kernel->wdata);
}
/************************ image paint poll ************************/
static Brush *image_paint_brush(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- ToolSettings *settings = scene->toolsettings;
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *settings = scene->toolsettings;
- return BKE_paint_brush(&settings->imapaint.paint);
+ return BKE_paint_brush(&settings->imapaint.paint);
}
static bool image_paint_poll_ex(bContext *C, bool check_tool)
{
- Object *obact;
-
- if (!image_paint_brush(C))
- return 0;
-
- obact = CTX_data_active_object(C);
- if ((obact && obact->mode & OB_MODE_TEXTURE_PAINT) && CTX_wm_region_view3d(C)) {
- if (!check_tool || WM_toolsystem_active_tool_is_brush(C)) {
- return 1;
- }
- }
- else {
- SpaceImage *sima = CTX_wm_space_image(C);
-
- if (sima) {
- ARegion *ar = CTX_wm_region(C);
-
- if ((sima->mode == SI_MODE_PAINT) && ar->regiontype == RGN_TYPE_WINDOW) {
- return 1;
- }
- }
- }
-
- return 0;
+ Object *obact;
+
+ if (!image_paint_brush(C))
+ return 0;
+
+ obact = CTX_data_active_object(C);
+ if ((obact && obact->mode & OB_MODE_TEXTURE_PAINT) && CTX_wm_region_view3d(C)) {
+ if (!check_tool || WM_toolsystem_active_tool_is_brush(C)) {
+ return 1;
+ }
+ }
+ else {
+ SpaceImage *sima = CTX_wm_space_image(C);
+
+ if (sima) {
+ ARegion *ar = CTX_wm_region(C);
+
+ if ((sima->mode == SI_MODE_PAINT) && ar->regiontype == RGN_TYPE_WINDOW) {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
}
static bool image_paint_poll(bContext *C)
{
- return image_paint_poll_ex(C, true);
+ return image_paint_poll_ex(C, true);
}
static bool image_paint_poll_ignore_tool(bContext *C)
{
- return image_paint_poll_ex(C, false);
+ return image_paint_poll_ex(C, false);
}
static bool image_paint_2d_clone_poll(bContext *C)
{
- Brush *brush = image_paint_brush(C);
+ Brush *brush = image_paint_brush(C);
- if (!CTX_wm_region_view3d(C) && image_paint_poll(C))
- if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE))
- if (brush->clone.image)
- return 1;
+ if (!CTX_wm_region_view3d(C) && image_paint_poll(C))
+ if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE))
+ if (brush->clone.image)
+ return 1;
- return 0;
+ return 0;
}
/************************ paint operator ************************/
typedef enum eTexPaintMode {
- PAINT_MODE_2D,
- PAINT_MODE_3D_PROJECT,
+ PAINT_MODE_2D,
+ PAINT_MODE_3D_PROJECT,
} eTexPaintMode;
typedef struct PaintOperation {
- eTexPaintMode mode;
+ eTexPaintMode mode;
- void *custom_paint;
+ void *custom_paint;
- float prevmouse[2];
- float startmouse[2];
- double starttime;
+ float prevmouse[2];
+ float startmouse[2];
+ double starttime;
- void *cursor;
- ViewContext vc;
+ void *cursor;
+ ViewContext vc;
} PaintOperation;
bool paint_use_opacity_masking(Brush *brush)
{
- return ((brush->flag & BRUSH_AIRBRUSH) ||
- (brush->flag & BRUSH_DRAG_DOT) ||
- (brush->flag & BRUSH_ANCHORED) ||
- (brush->imagepaint_tool == PAINT_TOOL_SMEAR) ||
- (brush->imagepaint_tool == PAINT_TOOL_SOFTEN) ||
- (brush->imagepaint_tool == PAINT_TOOL_FILL) ||
- (brush->flag & BRUSH_USE_GRADIENT) ||
- (brush->mtex.tex &&
- !ELEM(brush->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_3D)) ?
- false : true);
+ return ((brush->flag & BRUSH_AIRBRUSH) || (brush->flag & BRUSH_DRAG_DOT) ||
+ (brush->flag & BRUSH_ANCHORED) || (brush->imagepaint_tool == PAINT_TOOL_SMEAR) ||
+ (brush->imagepaint_tool == PAINT_TOOL_SOFTEN) ||
+ (brush->imagepaint_tool == PAINT_TOOL_FILL) ||
+ (brush->flag & BRUSH_USE_GRADIENT) ||
+ (brush->mtex.tex && !ELEM(brush->mtex.brush_map_mode,
+ MTEX_MAP_MODE_TILED,
+ MTEX_MAP_MODE_STENCIL,
+ MTEX_MAP_MODE_3D)) ?
+ false :
+ true);
}
-void paint_brush_color_get(
- struct Scene *scene, struct Brush *br, bool color_correction, bool invert, float distance,
- float pressure, float color[3], struct ColorManagedDisplay *display)
+void paint_brush_color_get(struct Scene *scene,
+ struct Brush *br,
+ bool color_correction,
+ bool invert,
+ float distance,
+ float pressure,
+ float color[3],
+ struct ColorManagedDisplay *display)
{
- if (invert)
- copy_v3_v3(color, BKE_brush_secondary_color_get(scene, br));
- else {
- if (br->flag & BRUSH_USE_GRADIENT) {
- float color_gr[4];
- switch (br->gradient_stroke_mode) {
- case BRUSH_GRADIENT_PRESSURE:
- BKE_colorband_evaluate(br->gradient, pressure, color_gr);
- break;
- case BRUSH_GRADIENT_SPACING_REPEAT:
- {
- float coord = fmod(distance / br->gradient_spacing, 1.0);
- BKE_colorband_evaluate(br->gradient, coord, color_gr);
- break;
- }
- case BRUSH_GRADIENT_SPACING_CLAMP:
- {
- BKE_colorband_evaluate(br->gradient, distance / br->gradient_spacing, color_gr);
- break;
- }
- }
- copy_v3_v3(color, color_gr);
- }
- else
- copy_v3_v3(color, BKE_brush_color_get(scene, br));
- }
- if (color_correction)
- IMB_colormanagement_display_to_scene_linear_v3(color, display);
+ if (invert)
+ copy_v3_v3(color, BKE_brush_secondary_color_get(scene, br));
+ else {
+ if (br->flag & BRUSH_USE_GRADIENT) {
+ float color_gr[4];
+ switch (br->gradient_stroke_mode) {
+ case BRUSH_GRADIENT_PRESSURE:
+ BKE_colorband_evaluate(br->gradient, pressure, color_gr);
+ break;
+ case BRUSH_GRADIENT_SPACING_REPEAT: {
+ float coord = fmod(distance / br->gradient_spacing, 1.0);
+ BKE_colorband_evaluate(br->gradient, coord, color_gr);
+ break;
+ }
+ case BRUSH_GRADIENT_SPACING_CLAMP: {
+ BKE_colorband_evaluate(br->gradient, distance / br->gradient_spacing, color_gr);
+ break;
+ }
+ }
+ copy_v3_v3(color, color_gr);
+ }
+ else
+ copy_v3_v3(color, BKE_brush_color_get(scene, br));
+ }
+ if (color_correction)
+ IMB_colormanagement_display_to_scene_linear_v3(color, display);
}
void paint_brush_init_tex(Brush *brush)
{
- /* init mtex nodes */
- if (brush) {
- MTex *mtex = &brush->mtex;
- if (mtex->tex && mtex->tex->nodetree) {
- /* has internal flag to detect it only does it once */
- ntreeTexBeginExecTree(mtex->tex->nodetree);
- }
- mtex = &brush->mask_mtex;
- if (mtex->tex && mtex->tex->nodetree) {
- ntreeTexBeginExecTree(mtex->tex->nodetree);
- }
- }
+ /* init mtex nodes */
+ if (brush) {
+ MTex *mtex = &brush->mtex;
+ if (mtex->tex && mtex->tex->nodetree) {
+ /* has internal flag to detect it only does it once */
+ ntreeTexBeginExecTree(mtex->tex->nodetree);
+ }
+ mtex = &brush->mask_mtex;
+ if (mtex->tex && mtex->tex->nodetree) {
+ ntreeTexBeginExecTree(mtex->tex->nodetree);
+ }
+ }
}
void paint_brush_exit_tex(Brush *brush)
{
- if (brush) {
- MTex *mtex = &brush->mtex;
- if (mtex->tex && mtex->tex->nodetree)
- ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
- mtex = &brush->mask_mtex;
- if (mtex->tex && mtex->tex->nodetree)
- ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
- }
+ if (brush) {
+ MTex *mtex = &brush->mtex;
+ if (mtex->tex && mtex->tex->nodetree)
+ ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
+ mtex = &brush->mask_mtex;
+ if (mtex->tex && mtex->tex->nodetree)
+ ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
+ }
}
static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customdata)
{
- PaintOperation *pop = (PaintOperation *)customdata;
+ PaintOperation *pop = (PaintOperation *)customdata;
- if (pop) {
- GPU_line_smooth(true);
- GPU_blend(true);
+ if (pop) {
+ GPU_line_smooth(true);
+ GPU_blend(true);
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ 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 *ar = pop->vc.ar;
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- GPU_line_width(4.0);
- immUniformColor4ub(0, 0, 0, 255);
+ GPU_line_width(4.0);
+ immUniformColor4ub(0, 0, 0, 255);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2i(pos, x, y);
- immVertex2i(pos, pop->startmouse[0] + ar->winrct.xmin, pop->startmouse[1] + ar->winrct.ymin);
- immEnd();
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2i(pos, x, y);
+ immVertex2i(pos, pop->startmouse[0] + ar->winrct.xmin, pop->startmouse[1] + ar->winrct.ymin);
+ immEnd();
- GPU_line_width(2.0);
- immUniformColor4ub(255, 255, 255, 255);
+ GPU_line_width(2.0);
+ immUniformColor4ub(255, 255, 255, 255);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2i(pos, x, y);
- immVertex2i(pos, pop->startmouse[0] + ar->winrct.xmin, pop->startmouse[1] + ar->winrct.ymin);
- immEnd();
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2i(pos, x, y);
+ immVertex2i(pos, pop->startmouse[0] + ar->winrct.xmin, pop->startmouse[1] + ar->winrct.ymin);
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
- GPU_blend(false);
- GPU_line_smooth(false);
- }
+ GPU_blend(false);
+ GPU_line_smooth(false);
+ }
}
-
static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const float mouse[2])
{
- Scene *scene = CTX_data_scene(C);
- ToolSettings *settings = scene->toolsettings;
- PaintOperation *pop = MEM_callocN(sizeof(PaintOperation), "PaintOperation"); /* caller frees */
- Brush *brush = BKE_paint_brush(&settings->imapaint.paint);
- int mode = RNA_enum_get(op->ptr, "mode");
- ED_view3d_viewcontext_init(C, &pop->vc);
-
- copy_v2_v2(pop->prevmouse, mouse);
- copy_v2_v2(pop->startmouse, mouse);
-
- /* initialize from context */
- if (CTX_wm_region_view3d(C)) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- bool uvs, mat, tex, stencil;
- if (!BKE_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, &stencil)) {
- BKE_paint_data_warning(op->reports, uvs, mat, tex, stencil);
- MEM_freeN(pop);
- WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
- return NULL;
- }
- pop->mode = PAINT_MODE_3D_PROJECT;
- pop->custom_paint = paint_proj_new_stroke(C, ob, mouse, mode);
- }
- else {
- pop->mode = PAINT_MODE_2D;
- pop->custom_paint = paint_2d_new_stroke(C, op, mode);
- }
-
- if (!pop->custom_paint) {
- MEM_freeN(pop);
- return NULL;
- }
-
- if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) {
- pop->cursor = WM_paint_cursor_activate(
- CTX_wm_manager(C),
- SPACE_TYPE_ANY, RGN_TYPE_ANY,
- image_paint_poll, gradient_draw_line,
- pop);
- }
-
- settings->imapaint.flag |= IMAGEPAINT_DRAWING;
- ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_2D);
-
- return pop;
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *settings = scene->toolsettings;
+ PaintOperation *pop = MEM_callocN(sizeof(PaintOperation), "PaintOperation"); /* caller frees */
+ Brush *brush = BKE_paint_brush(&settings->imapaint.paint);
+ int mode = RNA_enum_get(op->ptr, "mode");
+ ED_view3d_viewcontext_init(C, &pop->vc);
+
+ copy_v2_v2(pop->prevmouse, mouse);
+ copy_v2_v2(pop->startmouse, mouse);
+
+ /* initialize from context */
+ if (CTX_wm_region_view3d(C)) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ bool uvs, mat, tex, stencil;
+ if (!BKE_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, &stencil)) {
+ BKE_paint_data_warning(op->reports, uvs, mat, tex, stencil);
+ MEM_freeN(pop);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ return NULL;
+ }
+ pop->mode = PAINT_MODE_3D_PROJECT;
+ pop->custom_paint = paint_proj_new_stroke(C, ob, mouse, mode);
+ }
+ else {
+ pop->mode = PAINT_MODE_2D;
+ pop->custom_paint = paint_2d_new_stroke(C, op, mode);
+ }
+
+ if (!pop->custom_paint) {
+ MEM_freeN(pop);
+ return NULL;
+ }
+
+ if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) {
+ pop->cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
+ SPACE_TYPE_ANY,
+ RGN_TYPE_ANY,
+ image_paint_poll,
+ gradient_draw_line,
+ pop);
+ }
+
+ settings->imapaint.flag |= IMAGEPAINT_DRAWING;
+ ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_2D);
+
+ return pop;
}
static void paint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
{
- PaintOperation *pop = paint_stroke_mode_data(stroke);
- Scene *scene = CTX_data_scene(C);
- ToolSettings *toolsettings = CTX_data_tool_settings(C);
- UnifiedPaintSettings *ups = &toolsettings->unified_paint_settings;
- Brush *brush = BKE_paint_brush(&toolsettings->imapaint.paint);
-
- float alphafac = (brush->flag & BRUSH_ACCUMULATE) ? ups->overlap_factor : 1.0f;
-
- /* initial brush values. Maybe it should be considered moving these to stroke system */
- float startalpha = BKE_brush_alpha_get(scene, brush);
-
- float mouse[2];
- float pressure;
- float size;
- float distance = paint_stroke_distance_get(stroke);
- int eraser;
-
- RNA_float_get_array(itemptr, "mouse", mouse);
- pressure = RNA_float_get(itemptr, "pressure");
- eraser = RNA_boolean_get(itemptr, "pen_flip");
- size = max_ff(1.0f, RNA_float_get(itemptr, "size"));
-
- /* stroking with fill tool only acts on stroke end */
- if (brush->imagepaint_tool == PAINT_TOOL_FILL) {
- copy_v2_v2(pop->prevmouse, mouse);
- return;
- }
-
- if (BKE_brush_use_alpha_pressure(scene, brush))
- BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * pressure * alphafac));
- else
- BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * alphafac));
-
- if ((brush->flag & BRUSH_DRAG_DOT) || (brush->flag & BRUSH_ANCHORED)) {
- UndoStack *ustack = CTX_wm_manager(C)->undo_stack;
- ED_image_undo_restore(ustack->step_init);
- }
-
- if (pop->mode == PAINT_MODE_3D_PROJECT) {
- paint_proj_stroke(C, pop->custom_paint, pop->prevmouse, mouse, eraser, pressure, distance, size);
- }
- else {
- paint_2d_stroke(pop->custom_paint, pop->prevmouse, mouse, eraser, pressure, distance, size);
- }
-
- copy_v2_v2(pop->prevmouse, mouse);
-
- /* restore brush values */
- BKE_brush_alpha_set(scene, brush, startalpha);
+ PaintOperation *pop = paint_stroke_mode_data(stroke);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *toolsettings = CTX_data_tool_settings(C);
+ UnifiedPaintSettings *ups = &toolsettings->unified_paint_settings;
+ Brush *brush = BKE_paint_brush(&toolsettings->imapaint.paint);
+
+ float alphafac = (brush->flag & BRUSH_ACCUMULATE) ? ups->overlap_factor : 1.0f;
+
+ /* initial brush values. Maybe it should be considered moving these to stroke system */
+ float startalpha = BKE_brush_alpha_get(scene, brush);
+
+ float mouse[2];
+ float pressure;
+ float size;
+ float distance = paint_stroke_distance_get(stroke);
+ int eraser;
+
+ RNA_float_get_array(itemptr, "mouse", mouse);
+ pressure = RNA_float_get(itemptr, "pressure");
+ eraser = RNA_boolean_get(itemptr, "pen_flip");
+ size = max_ff(1.0f, RNA_float_get(itemptr, "size"));
+
+ /* stroking with fill tool only acts on stroke end */
+ if (brush->imagepaint_tool == PAINT_TOOL_FILL) {
+ copy_v2_v2(pop->prevmouse, mouse);
+ return;
+ }
+
+ if (BKE_brush_use_alpha_pressure(scene, brush))
+ BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * pressure * alphafac));
+ else
+ BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * alphafac));
+
+ if ((brush->flag & BRUSH_DRAG_DOT) || (brush->flag & BRUSH_ANCHORED)) {
+ UndoStack *ustack = CTX_wm_manager(C)->undo_stack;
+ ED_image_undo_restore(ustack->step_init);
+ }
+
+ if (pop->mode == PAINT_MODE_3D_PROJECT) {
+ paint_proj_stroke(
+ C, pop->custom_paint, pop->prevmouse, mouse, eraser, pressure, distance, size);
+ }
+ else {
+ paint_2d_stroke(pop->custom_paint, pop->prevmouse, mouse, eraser, pressure, distance, size);
+ }
+
+ copy_v2_v2(pop->prevmouse, mouse);
+
+ /* restore brush values */
+ BKE_brush_alpha_set(scene, brush, startalpha);
}
static void paint_stroke_redraw(const bContext *C, struct PaintStroke *stroke, bool final)
{
- PaintOperation *pop = paint_stroke_mode_data(stroke);
-
- if (pop->mode == PAINT_MODE_3D_PROJECT) {
- paint_proj_redraw(C, pop->custom_paint, final);
- }
- else {
- paint_2d_redraw(C, pop->custom_paint, final);
- }
+ PaintOperation *pop = paint_stroke_mode_data(stroke);
+
+ if (pop->mode == PAINT_MODE_3D_PROJECT) {
+ paint_proj_redraw(C, pop->custom_paint, final);
+ }
+ else {
+ paint_2d_redraw(C, pop->custom_paint, final);
+ }
}
static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
{
- Scene *scene = CTX_data_scene(C);
- ToolSettings *toolsettings = scene->toolsettings;
- PaintOperation *pop = paint_stroke_mode_data(stroke);
- Brush *brush = BKE_paint_brush(&toolsettings->imapaint.paint);
-
- toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
-
- if (brush->imagepaint_tool == PAINT_TOOL_FILL) {
- if (brush->flag & BRUSH_USE_GRADIENT) {
- if (pop->mode == PAINT_MODE_2D) {
- paint_2d_gradient_fill(C, brush, pop->startmouse, pop->prevmouse, pop->custom_paint);
- }
- else {
- paint_proj_stroke(
- C, pop->custom_paint, pop->startmouse, pop->prevmouse, paint_stroke_flipped(stroke),
- 1.0, 0.0, BKE_brush_size_get(scene, brush));
- /* two redraws, one for GPU update, one for notification */
- paint_proj_redraw(C, pop->custom_paint, false);
- paint_proj_redraw(C, pop->custom_paint, true);
- }
- }
- else {
- if (pop->mode == PAINT_MODE_2D) {
- float color[3];
- if (paint_stroke_inverted(stroke)) {
- srgb_to_linearrgb_v3_v3(color, BKE_brush_secondary_color_get(scene, brush));
- }
- else {
- srgb_to_linearrgb_v3_v3(color, BKE_brush_color_get(scene, brush));
- }
- paint_2d_bucket_fill(C, color, brush, pop->prevmouse, pop->custom_paint);
- }
- else {
- paint_proj_stroke(
- C, pop->custom_paint, pop->startmouse, pop->prevmouse, paint_stroke_flipped(stroke),
- 1.0, 0.0, BKE_brush_size_get(scene, brush));
- /* two redraws, one for GPU update, one for notification */
- paint_proj_redraw(C, pop->custom_paint, false);
- paint_proj_redraw(C, pop->custom_paint, true);
- }
- }
- }
- if (pop->mode == PAINT_MODE_3D_PROJECT) {
- paint_proj_stroke_done(pop->custom_paint);
- }
- else {
- paint_2d_stroke_done(pop->custom_paint);
- }
-
- if (pop->cursor) {
- WM_paint_cursor_end(CTX_wm_manager(C), pop->cursor);
- }
-
- ED_image_undo_push_end();
-
- /* duplicate warning, see texpaint_init */
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *toolsettings = scene->toolsettings;
+ PaintOperation *pop = paint_stroke_mode_data(stroke);
+ Brush *brush = BKE_paint_brush(&toolsettings->imapaint.paint);
+
+ toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
+
+ if (brush->imagepaint_tool == PAINT_TOOL_FILL) {
+ if (brush->flag & BRUSH_USE_GRADIENT) {
+ if (pop->mode == PAINT_MODE_2D) {
+ paint_2d_gradient_fill(C, brush, pop->startmouse, pop->prevmouse, pop->custom_paint);
+ }
+ else {
+ paint_proj_stroke(C,
+ pop->custom_paint,
+ pop->startmouse,
+ pop->prevmouse,
+ paint_stroke_flipped(stroke),
+ 1.0,
+ 0.0,
+ BKE_brush_size_get(scene, brush));
+ /* two redraws, one for GPU update, one for notification */
+ paint_proj_redraw(C, pop->custom_paint, false);
+ paint_proj_redraw(C, pop->custom_paint, true);
+ }
+ }
+ else {
+ if (pop->mode == PAINT_MODE_2D) {
+ float color[3];
+ if (paint_stroke_inverted(stroke)) {
+ srgb_to_linearrgb_v3_v3(color, BKE_brush_secondary_color_get(scene, brush));
+ }
+ else {
+ srgb_to_linearrgb_v3_v3(color, BKE_brush_color_get(scene, brush));
+ }
+ paint_2d_bucket_fill(C, color, brush, pop->prevmouse, pop->custom_paint);
+ }
+ else {
+ paint_proj_stroke(C,
+ pop->custom_paint,
+ pop->startmouse,
+ pop->prevmouse,
+ paint_stroke_flipped(stroke),
+ 1.0,
+ 0.0,
+ BKE_brush_size_get(scene, brush));
+ /* two redraws, one for GPU update, one for notification */
+ paint_proj_redraw(C, pop->custom_paint, false);
+ paint_proj_redraw(C, pop->custom_paint, true);
+ }
+ }
+ }
+ if (pop->mode == PAINT_MODE_3D_PROJECT) {
+ paint_proj_stroke_done(pop->custom_paint);
+ }
+ else {
+ paint_2d_stroke_done(pop->custom_paint);
+ }
+
+ if (pop->cursor) {
+ WM_paint_cursor_end(CTX_wm_manager(C), pop->cursor);
+ }
+
+ ED_image_undo_push_end();
+
+ /* duplicate warning, see texpaint_init */
#if 0
- if (pop->s.warnmultifile)
- BKE_reportf(op->reports, RPT_WARNING, "Image requires 4 color channels to paint: %s", pop->s.warnmultifile);
- if (pop->s.warnpackedfile)
- BKE_reportf(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted: %s", pop->s.warnpackedfile);
+ if (pop->s.warnmultifile)
+ BKE_reportf(op->reports, RPT_WARNING, "Image requires 4 color channels to paint: %s", pop->s.warnmultifile);
+ if (pop->s.warnpackedfile)
+ BKE_reportf(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted: %s", pop->s.warnpackedfile);
#endif
- MEM_freeN(pop);
+ MEM_freeN(pop);
}
static bool paint_stroke_test_start(bContext *C, wmOperator *op, const float mouse[2])
{
- PaintOperation *pop;
+ PaintOperation *pop;
- /* TODO Should avoid putting this here. Instead, last position should be requested
- * from stroke system. */
+ /* TODO Should avoid putting this here. Instead, last position should be requested
+ * from stroke system. */
- if (!(pop = texture_paint_init(C, op, mouse))) {
- return false;
- }
+ if (!(pop = texture_paint_init(C, op, mouse))) {
+ return false;
+ }
- paint_stroke_set_mode_data(op->customdata, pop);
+ paint_stroke_set_mode_data(op->customdata, pop);
- return true;
+ return true;
}
-
static int paint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- int retval;
-
- op->customdata = paint_stroke_new(
- C, op, NULL, paint_stroke_test_start,
- paint_stroke_update_step,
- paint_stroke_redraw,
- paint_stroke_done, event->type);
-
- if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
- paint_stroke_data_free(op);
- return OPERATOR_FINISHED;
- }
- /* add modal handler */
- WM_event_add_modal_handler(C, op);
-
- OPERATOR_RETVAL_CHECK(retval);
- BLI_assert(retval == OPERATOR_RUNNING_MODAL);
-
- return OPERATOR_RUNNING_MODAL;
+ int retval;
+
+ op->customdata = paint_stroke_new(C,
+ op,
+ NULL,
+ paint_stroke_test_start,
+ paint_stroke_update_step,
+ paint_stroke_redraw,
+ paint_stroke_done,
+ event->type);
+
+ if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
+ paint_stroke_data_free(op);
+ return OPERATOR_FINISHED;
+ }
+ /* add modal handler */
+ WM_event_add_modal_handler(C, op);
+
+ OPERATOR_RETVAL_CHECK(retval);
+ BLI_assert(retval == OPERATOR_RUNNING_MODAL);
+
+ return OPERATOR_RUNNING_MODAL;
}
static int paint_exec(bContext *C, wmOperator *op)
{
- PropertyRNA *strokeprop;
- PointerRNA firstpoint;
- float mouse[2];
-
- strokeprop = RNA_struct_find_property(op->ptr, "stroke");
-
- if (!RNA_property_collection_lookup_int(op->ptr, strokeprop, 0, &firstpoint))
- return OPERATOR_CANCELLED;
-
- RNA_float_get_array(&firstpoint, "mouse", mouse);
-
- op->customdata = paint_stroke_new(
- C, op, NULL, paint_stroke_test_start,
- paint_stroke_update_step,
- paint_stroke_redraw,
- paint_stroke_done, 0);
- /* frees op->customdata */
- return paint_stroke_exec(C, op);
+ PropertyRNA *strokeprop;
+ PointerRNA firstpoint;
+ float mouse[2];
+
+ strokeprop = RNA_struct_find_property(op->ptr, "stroke");
+
+ if (!RNA_property_collection_lookup_int(op->ptr, strokeprop, 0, &firstpoint))
+ return OPERATOR_CANCELLED;
+
+ RNA_float_get_array(&firstpoint, "mouse", mouse);
+
+ op->customdata = paint_stroke_new(C,
+ op,
+ NULL,
+ paint_stroke_test_start,
+ paint_stroke_update_step,
+ paint_stroke_redraw,
+ paint_stroke_done,
+ 0);
+ /* frees op->customdata */
+ return paint_stroke_exec(C, op);
}
void PAINT_OT_image_paint(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Image Paint";
- ot->idname = "PAINT_OT_image_paint";
- ot->description = "Paint a stroke into the image";
-
- /* api callbacks */
- ot->invoke = paint_invoke;
- ot->modal = paint_stroke_modal;
- ot->exec = paint_exec;
- ot->poll = image_paint_poll;
- ot->cancel = paint_stroke_cancel;
-
- /* flags */
- ot->flag = OPTYPE_BLOCKING;
-
- paint_stroke_operator_properties(ot);
+ /* identifiers */
+ ot->name = "Image Paint";
+ ot->idname = "PAINT_OT_image_paint";
+ ot->description = "Paint a stroke into the image";
+
+ /* api callbacks */
+ ot->invoke = paint_invoke;
+ ot->modal = paint_stroke_modal;
+ ot->exec = paint_exec;
+ ot->poll = image_paint_poll;
+ ot->cancel = paint_stroke_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
+
+ paint_stroke_operator_properties(ot);
}
-
int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
- if (!rv3d) {
- SpaceImage *sima = CTX_wm_space_image(C);
+ if (!rv3d) {
+ SpaceImage *sima = CTX_wm_space_image(C);
- if (sima->mode == SI_MODE_PAINT) {
- ARegion *ar = CTX_wm_region(C);
- ED_space_image_get_zoom(sima, ar, zoomx, zoomy);
+ if (sima->mode == SI_MODE_PAINT) {
+ ARegion *ar = CTX_wm_region(C);
+ ED_space_image_get_zoom(sima, ar, zoomx, zoomy);
- return 1;
- }
- }
+ return 1;
+ }
+ }
- *zoomx = *zoomy = 1;
+ *zoomx = *zoomy = 1;
- return 0;
+ return 0;
}
/************************ cursor drawing *******************************/
static void toggle_paint_cursor(bContext *C, int enable)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- Scene *scene = CTX_data_scene(C);
- ToolSettings *settings = scene->toolsettings;
-
- if (settings->imapaint.paintcursor && !enable) {
- WM_paint_cursor_end(wm, settings->imapaint.paintcursor);
- settings->imapaint.paintcursor = NULL;
- paint_cursor_delete_textures();
- }
- else if (enable)
- paint_cursor_start(C, image_paint_poll);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *settings = scene->toolsettings;
+
+ if (settings->imapaint.paintcursor && !enable) {
+ WM_paint_cursor_end(wm, settings->imapaint.paintcursor);
+ settings->imapaint.paintcursor = NULL;
+ paint_cursor_delete_textures();
+ }
+ else if (enable)
+ paint_cursor_start(C, image_paint_poll);
}
/* enable the paint cursor if it isn't already.
@@ -755,526 +770,534 @@ static void toggle_paint_cursor(bContext *C, int enable)
* ensure that the cursor is hidden when not in paint mode */
void ED_space_image_paint_update(Main *bmain, wmWindowManager *wm, Scene *scene)
{
- ToolSettings *settings = scene->toolsettings;
- ImagePaintSettings *imapaint = &settings->imapaint;
- bool enabled = false;
-
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
- 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) {
- enabled = true;
- }
- }
- }
- }
-
- if (enabled) {
- BKE_paint_init(bmain, scene, PAINT_MODE_TEXTURE_2D, PAINT_CURSOR_TEXTURE_PAINT);
-
- paint_cursor_start_explicit(&imapaint->paint, wm, image_paint_poll);
- }
- else {
- paint_cursor_delete_textures();
- }
+ ToolSettings *settings = scene->toolsettings;
+ ImagePaintSettings *imapaint = &settings->imapaint;
+ bool enabled = false;
+
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ 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) {
+ enabled = true;
+ }
+ }
+ }
+ }
+
+ if (enabled) {
+ BKE_paint_init(bmain, scene, PAINT_MODE_TEXTURE_2D, PAINT_CURSOR_TEXTURE_PAINT);
+
+ paint_cursor_start_explicit(&imapaint->paint, wm, image_paint_poll);
+ }
+ else {
+ paint_cursor_delete_textures();
+ }
}
/************************ grab clone operator ************************/
typedef struct GrabClone {
- float startoffset[2];
- int startx, starty;
+ float startoffset[2];
+ int startx, starty;
} GrabClone;
static void grab_clone_apply(bContext *C, wmOperator *op)
{
- Brush *brush = image_paint_brush(C);
- float delta[2];
+ Brush *brush = image_paint_brush(C);
+ float delta[2];
- RNA_float_get_array(op->ptr, "delta", delta);
- add_v2_v2(brush->clone.offset, delta);
- ED_region_tag_redraw(CTX_wm_region(C));
+ RNA_float_get_array(op->ptr, "delta", delta);
+ add_v2_v2(brush->clone.offset, delta);
+ ED_region_tag_redraw(CTX_wm_region(C));
}
static int grab_clone_exec(bContext *C, wmOperator *op)
{
- grab_clone_apply(C, op);
+ grab_clone_apply(C, op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int grab_clone_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Brush *brush = image_paint_brush(C);
- GrabClone *cmv;
+ Brush *brush = image_paint_brush(C);
+ GrabClone *cmv;
- cmv = MEM_callocN(sizeof(GrabClone), "GrabClone");
- copy_v2_v2(cmv->startoffset, brush->clone.offset);
- cmv->startx = event->x;
- cmv->starty = event->y;
- op->customdata = cmv;
+ cmv = MEM_callocN(sizeof(GrabClone), "GrabClone");
+ copy_v2_v2(cmv->startoffset, brush->clone.offset);
+ cmv->startx = event->x;
+ cmv->starty = event->y;
+ op->customdata = cmv;
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static int grab_clone_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- Brush *brush = image_paint_brush(C);
- ARegion *ar = CTX_wm_region(C);
- GrabClone *cmv = op->customdata;
- float startfx, startfy, fx, fy, delta[2];
- int xmin = ar->winrct.xmin, ymin = ar->winrct.ymin;
-
- switch (event->type) {
- case LEFTMOUSE:
- case MIDDLEMOUSE:
- case RIGHTMOUSE: // XXX hardcoded
- MEM_freeN(op->customdata);
- return OPERATOR_FINISHED;
- 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);
-
- delta[0] = fx - startfx;
- delta[1] = fy - startfy;
- RNA_float_set_array(op->ptr, "delta", delta);
-
- copy_v2_v2(brush->clone.offset, cmv->startoffset);
-
- grab_clone_apply(C, op);
- break;
- }
-
- return OPERATOR_RUNNING_MODAL;
+ Brush *brush = image_paint_brush(C);
+ ARegion *ar = CTX_wm_region(C);
+ GrabClone *cmv = op->customdata;
+ float startfx, startfy, fx, fy, delta[2];
+ int xmin = ar->winrct.xmin, ymin = ar->winrct.ymin;
+
+ switch (event->type) {
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ case RIGHTMOUSE: // XXX hardcoded
+ MEM_freeN(op->customdata);
+ return OPERATOR_FINISHED;
+ 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);
+
+ delta[0] = fx - startfx;
+ delta[1] = fy - startfy;
+ RNA_float_set_array(op->ptr, "delta", delta);
+
+ copy_v2_v2(brush->clone.offset, cmv->startoffset);
+
+ grab_clone_apply(C, op);
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
static void grab_clone_cancel(bContext *UNUSED(C), wmOperator *op)
{
- MEM_freeN(op->customdata);
+ MEM_freeN(op->customdata);
}
void PAINT_OT_grab_clone(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Grab Clone";
- ot->idname = "PAINT_OT_grab_clone";
- ot->description = "Move the clone source image";
-
- /* api callbacks */
- ot->exec = grab_clone_exec;
- ot->invoke = grab_clone_invoke;
- ot->modal = grab_clone_modal;
- ot->cancel = grab_clone_cancel;
- ot->poll = image_paint_2d_clone_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* properties */
- RNA_def_float_vector(ot->srna, "delta", 2, NULL, -FLT_MAX, FLT_MAX, "Delta", "Delta offset of clone image in 0.0..1.0 coordinates", -1.0f, 1.0f);
+ /* identifiers */
+ ot->name = "Grab Clone";
+ ot->idname = "PAINT_OT_grab_clone";
+ ot->description = "Move the clone source image";
+
+ /* api callbacks */
+ ot->exec = grab_clone_exec;
+ ot->invoke = grab_clone_invoke;
+ ot->modal = grab_clone_modal;
+ ot->cancel = grab_clone_cancel;
+ ot->poll = image_paint_2d_clone_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* properties */
+ RNA_def_float_vector(ot->srna,
+ "delta",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Delta",
+ "Delta offset of clone image in 0.0..1.0 coordinates",
+ -1.0f,
+ 1.0f);
}
/******************** sample color operator ********************/
typedef struct {
- bool show_cursor;
- short event_type;
- float initcolor[3];
- bool sample_palette;
-} SampleColorData;
-
+ bool show_cursor;
+ short event_type;
+ float initcolor[3];
+ bool sample_palette;
+} SampleColorData;
static void sample_color_update_header(SampleColorData *data, bContext *C)
{
- char msg[UI_MAX_DRAW_STR];
- ScrArea *sa = CTX_wm_area(C);
-
- if (sa) {
- BLI_snprintf(
- msg, sizeof(msg),
- IFACE_("Sample color for %s"),
- !data->sample_palette ?
- IFACE_("Brush. Use Left Click to sample for palette instead") :
- IFACE_("Palette. Use Left Click to sample more colors"));
- ED_workspace_status_text(C, msg);
- }
+ char msg[UI_MAX_DRAW_STR];
+ ScrArea *sa = CTX_wm_area(C);
+
+ if (sa) {
+ BLI_snprintf(msg,
+ sizeof(msg),
+ IFACE_("Sample color for %s"),
+ !data->sample_palette ?
+ IFACE_("Brush. Use Left Click to sample for palette instead") :
+ IFACE_("Palette. Use Left Click to sample more colors"));
+ ED_workspace_status_text(C, msg);
+ }
}
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);
- wmWindow *win = CTX_wm_window(C);
- const bool show_cursor = ((paint->flags & PAINT_SHOW_BRUSH) != 0);
- int location[2];
- paint->flags &= ~PAINT_SHOW_BRUSH;
+ 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);
+ 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_redraw_windows(C);
+ /* force redraw without cursor */
+ WM_paint_cursor_tag_redraw(win, ar);
+ WM_redraw_windows(C);
- RNA_int_get_array(op->ptr, "location", location);
- const bool use_palette = RNA_boolean_get(op->ptr, "palette");
- const bool use_sample_texture = (mode == PAINT_MODE_TEXTURE_3D) && !RNA_boolean_get(op->ptr, "merged");
+ RNA_int_get_array(op->ptr, "location", location);
+ const bool use_palette = RNA_boolean_get(op->ptr, "palette");
+ 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, ar, location[0], location[1], use_sample_texture, use_palette);
- if (show_cursor) {
- paint->flags |= PAINT_SHOW_BRUSH;
- }
+ if (show_cursor) {
+ paint->flags |= PAINT_SHOW_BRUSH;
+ }
- WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
+ WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Scene *scene = CTX_data_scene(C);
- 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);
- wmWindow *win = CTX_wm_window(C);
+ Scene *scene = CTX_data_scene(C);
+ 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);
+ wmWindow *win = CTX_wm_window(C);
- data->event_type = event->type;
- data->show_cursor = ((paint->flags & PAINT_SHOW_BRUSH) != 0);
- copy_v3_v3(data->initcolor, BKE_brush_color_get(scene, brush));
- data->sample_palette = false;
- op->customdata = data;
- paint->flags &= ~PAINT_SHOW_BRUSH;
+ data->event_type = event->type;
+ data->show_cursor = ((paint->flags & PAINT_SHOW_BRUSH) != 0);
+ copy_v3_v3(data->initcolor, BKE_brush_color_get(scene, brush));
+ data->sample_palette = false;
+ op->customdata = data;
+ paint->flags &= ~PAINT_SHOW_BRUSH;
- sample_color_update_header(data, C);
+ sample_color_update_header(data, C);
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
- /* force redraw without cursor */
- WM_paint_cursor_tag_redraw(win, ar);
- WM_redraw_windows(C);
+ /* force redraw without cursor */
+ WM_paint_cursor_tag_redraw(win, ar);
+ WM_redraw_windows(C);
- RNA_int_set_array(op->ptr, "location", event->mval);
+ RNA_int_set_array(op->ptr, "location", event->mval);
- ePaintMode mode = BKE_paintmode_get_active_from_context(C);
- const bool use_sample_texture = (mode == PAINT_MODE_TEXTURE_3D) && !RNA_boolean_get(op->ptr, "merged");
+ ePaintMode mode = BKE_paintmode_get_active_from_context(C);
+ 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);
- WM_cursor_modal_set(win, BC_EYEDROPPER_CURSOR);
+ paint_sample_color(C, ar, event->mval[0], event->mval[1], use_sample_texture, false);
+ WM_cursor_modal_set(win, BC_EYEDROPPER_CURSOR);
- WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
+ WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- Scene *scene = CTX_data_scene(C);
- SampleColorData *data = op->customdata;
- Paint *paint = BKE_paint_get_active_from_context(C);
- Brush *brush = BKE_paint_brush(paint);
-
- if ((event->type == data->event_type) && (event->val == KM_RELEASE)) {
- if (data->show_cursor) {
- paint->flags |= PAINT_SHOW_BRUSH;
- }
-
- if (data->sample_palette) {
- BKE_brush_color_set(scene, brush, data->initcolor);
- RNA_boolean_set(op->ptr, "palette", true);
- }
- WM_cursor_modal_restore(CTX_wm_window(C));
- MEM_freeN(data);
- ED_workspace_status_text(C, NULL);
-
- return OPERATOR_FINISHED;
- }
-
- ePaintMode mode = BKE_paintmode_get_active_from_context(C);
- const bool use_sample_texture = (mode == PAINT_MODE_TEXTURE_3D) && !RNA_boolean_get(op->ptr, "merged");
-
- switch (event->type) {
- case MOUSEMOVE:
- {
- ARegion *ar = 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);
- WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
- break;
- }
-
- case LEFTMOUSE:
- if (event->val == KM_PRESS) {
- ARegion *ar = 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);
- if (!data->sample_palette) {
- data->sample_palette = true;
- sample_color_update_header(data, C);
- }
- WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
- }
- break;
- }
-
- return OPERATOR_RUNNING_MODAL;
+ Scene *scene = CTX_data_scene(C);
+ SampleColorData *data = op->customdata;
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Brush *brush = BKE_paint_brush(paint);
+
+ if ((event->type == data->event_type) && (event->val == KM_RELEASE)) {
+ if (data->show_cursor) {
+ paint->flags |= PAINT_SHOW_BRUSH;
+ }
+
+ if (data->sample_palette) {
+ BKE_brush_color_set(scene, brush, data->initcolor);
+ RNA_boolean_set(op->ptr, "palette", true);
+ }
+ WM_cursor_modal_restore(CTX_wm_window(C));
+ MEM_freeN(data);
+ ED_workspace_status_text(C, NULL);
+
+ return OPERATOR_FINISHED;
+ }
+
+ ePaintMode mode = BKE_paintmode_get_active_from_context(C);
+ const bool use_sample_texture = (mode == PAINT_MODE_TEXTURE_3D) &&
+ !RNA_boolean_get(op->ptr, "merged");
+
+ switch (event->type) {
+ case MOUSEMOVE: {
+ ARegion *ar = 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);
+ WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
+ break;
+ }
+
+ case LEFTMOUSE:
+ if (event->val == KM_PRESS) {
+ ARegion *ar = 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);
+ if (!data->sample_palette) {
+ data->sample_palette = true;
+ sample_color_update_header(data, C);
+ }
+ WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
static bool sample_color_poll(bContext *C)
{
- return (image_paint_poll_ignore_tool(C) || vertex_paint_poll_ignore_tool(C));
+ return (image_paint_poll_ignore_tool(C) || vertex_paint_poll_ignore_tool(C));
}
void PAINT_OT_sample_color(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Sample Color";
- ot->idname = "PAINT_OT_sample_color";
- ot->description = "Use the mouse to sample a color in the image";
+ /* identifiers */
+ ot->name = "Sample Color";
+ ot->idname = "PAINT_OT_sample_color";
+ ot->description = "Use the mouse to sample a color in the image";
- /* api callbacks */
- ot->exec = sample_color_exec;
- ot->invoke = sample_color_invoke;
- ot->modal = sample_color_modal;
- ot->poll = sample_color_poll;
+ /* api callbacks */
+ ot->exec = sample_color_exec;
+ ot->invoke = sample_color_invoke;
+ ot->modal = sample_color_modal;
+ ot->poll = sample_color_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- PropertyRNA *prop;
+ /* properties */
+ PropertyRNA *prop;
- prop = RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "", 0, 16384);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ prop = RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "", 0, 16384);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
- RNA_def_boolean(ot->srna, "merged", 0, "Sample Merged", "Sample the output display color");
- RNA_def_boolean(ot->srna, "palette", 0, "Add to Palette", "");
+ RNA_def_boolean(ot->srna, "merged", 0, "Sample Merged", "Sample the output display color");
+ RNA_def_boolean(ot->srna, "palette", 0, "Add to Palette", "");
}
/******************** texture paint toggle operator ********************/
static bool texture_paint_toggle_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
- if (ob == NULL || ob->type != OB_MESH)
- return 0;
- if (!ob->data || ID_IS_LINKED(ob->data))
- return 0;
- if (CTX_data_edit_object(C))
- return 0;
-
- return 1;
+ Object *ob = CTX_data_active_object(C);
+ if (ob == NULL || ob->type != OB_MESH)
+ return 0;
+ if (!ob->data || ID_IS_LINKED(ob->data))
+ return 0;
+ if (CTX_data_edit_object(C))
+ return 0;
+
+ return 1;
}
static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
{
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- const int mode_flag = OB_MODE_TEXTURE_PAINT;
- const bool is_mode_set = (ob->mode & mode_flag) != 0;
-
- if (!is_mode_set) {
- if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
- return OPERATOR_CANCELLED;
- }
- }
-
- if (ob->mode & mode_flag) {
- ob->mode &= ~mode_flag;
-
- if (U.glreslimit != 0)
- GPU_free_images(bmain);
- GPU_paint_set_mipmap(bmain, 1);
-
- toggle_paint_cursor(C, 0);
- }
- else {
- bScreen *sc;
- Image *ima = NULL;
- ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
-
- /* This has to stay here to regenerate the texture paint
- * cache in case we are loading a file */
- BKE_texpaint_slots_refresh_object(scene, ob);
-
- BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
-
- /* entering paint mode also sets image to editors */
- if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
- /* set the current material active paint slot on image editor */
- Material *ma = give_current_material(ob, ob->actcol);
-
- if (ma && ma->texpaintslot)
- ima = ma->texpaintslot[ma->paint_active_slot].ima;
- }
- else if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
- ima = imapaint->canvas;
- }
-
- if (ima) {
- for (sc = bmain->screens.first; sc; sc = sc->id.next) {
- ScrArea *sa;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)sl;
-
- if (!sima->pin) {
- Object *obedit = CTX_data_edit_object(C);
- ED_space_image_set(bmain, sima, obedit, ima, true);
- }
- }
- }
- }
- }
- }
-
- ob->mode |= mode_flag;
-
- BKE_paint_init(bmain, scene, PAINT_MODE_TEXTURE_3D, PAINT_CURSOR_TEXTURE_PAINT);
-
- BKE_paint_toolslots_brush_validate(bmain, &imapaint->paint);
-
- if (U.glreslimit != 0)
- GPU_free_images(bmain);
- GPU_paint_set_mipmap(bmain, 0);
-
- toggle_paint_cursor(C, 1);
- }
-
- Mesh *me = BKE_mesh_from_object(ob);
- BLI_assert(me != NULL);
- DEG_id_tag_update(&me->id, ID_RECALC_COPY_ON_WRITE);
-
- WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
-
- WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
-
- WM_toolsystem_update_from_context_view3d(C);
-
- return OPERATOR_FINISHED;
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ const int mode_flag = OB_MODE_TEXTURE_PAINT;
+ const bool is_mode_set = (ob->mode & mode_flag) != 0;
+
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ if (ob->mode & mode_flag) {
+ ob->mode &= ~mode_flag;
+
+ if (U.glreslimit != 0)
+ GPU_free_images(bmain);
+ GPU_paint_set_mipmap(bmain, 1);
+
+ toggle_paint_cursor(C, 0);
+ }
+ else {
+ bScreen *sc;
+ Image *ima = NULL;
+ ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
+
+ /* This has to stay here to regenerate the texture paint
+ * cache in case we are loading a file */
+ BKE_texpaint_slots_refresh_object(scene, ob);
+
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+
+ /* entering paint mode also sets image to editors */
+ if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
+ /* set the current material active paint slot on image editor */
+ Material *ma = give_current_material(ob, ob->actcol);
+
+ if (ma && ma->texpaintslot)
+ ima = ma->texpaintslot[ma->paint_active_slot].ima;
+ }
+ else if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
+ ima = imapaint->canvas;
+ }
+
+ if (ima) {
+ for (sc = bmain->screens.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)sl;
+
+ if (!sima->pin) {
+ Object *obedit = CTX_data_edit_object(C);
+ ED_space_image_set(bmain, sima, obedit, ima, true);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ ob->mode |= mode_flag;
+
+ BKE_paint_init(bmain, scene, PAINT_MODE_TEXTURE_3D, PAINT_CURSOR_TEXTURE_PAINT);
+
+ BKE_paint_toolslots_brush_validate(bmain, &imapaint->paint);
+
+ if (U.glreslimit != 0)
+ GPU_free_images(bmain);
+ GPU_paint_set_mipmap(bmain, 0);
+
+ toggle_paint_cursor(C, 1);
+ }
+
+ Mesh *me = BKE_mesh_from_object(ob);
+ BLI_assert(me != NULL);
+ DEG_id_tag_update(&me->id, ID_RECALC_COPY_ON_WRITE);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
+
+ WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
+
+ WM_toolsystem_update_from_context_view3d(C);
+
+ return OPERATOR_FINISHED;
}
void PAINT_OT_texture_paint_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Texture Paint Toggle";
- ot->idname = "PAINT_OT_texture_paint_toggle";
- ot->description = "Toggle texture paint mode in 3D view";
+ /* identifiers */
+ ot->name = "Texture Paint Toggle";
+ ot->idname = "PAINT_OT_texture_paint_toggle";
+ ot->description = "Toggle texture paint mode in 3D view";
- /* api callbacks */
- ot->exec = texture_paint_toggle_exec;
- ot->poll = texture_paint_toggle_poll;
+ /* api callbacks */
+ ot->exec = texture_paint_toggle_exec;
+ ot->poll = texture_paint_toggle_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
}
-
static int brush_colors_flip_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Paint *paint = BKE_paint_get_active(scene, view_layer);
- Brush *br = BKE_paint_brush(paint);
-
- if (ups->flag & UNIFIED_PAINT_COLOR) {
- swap_v3_v3(ups->rgb, ups->secondary_rgb);
- }
- else if (br) {
- swap_v3_v3(br->rgb, br->secondary_rgb);
- }
- WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, br);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Paint *paint = BKE_paint_get_active(scene, view_layer);
+ Brush *br = BKE_paint_brush(paint);
+
+ if (ups->flag & UNIFIED_PAINT_COLOR) {
+ swap_v3_v3(ups->rgb, ups->secondary_rgb);
+ }
+ else if (br) {
+ swap_v3_v3(br->rgb, br->secondary_rgb);
+ }
+ WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, br);
+
+ return OPERATOR_FINISHED;
}
static bool brush_colors_flip_poll(bContext *C)
{
- if (image_paint_poll(C)) {
- Brush *br = image_paint_brush(C);
- if (ELEM(br->imagepaint_tool, PAINT_TOOL_DRAW, PAINT_TOOL_FILL))
- return true;
- }
- else {
- Object *ob = CTX_data_active_object(C);
- if (ob != NULL) {
- if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT)) {
- return true;
- }
- }
- }
- return false;
+ if (image_paint_poll(C)) {
+ Brush *br = image_paint_brush(C);
+ if (ELEM(br->imagepaint_tool, PAINT_TOOL_DRAW, PAINT_TOOL_FILL))
+ return true;
+ }
+ else {
+ Object *ob = CTX_data_active_object(C);
+ if (ob != NULL) {
+ if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT)) {
+ return true;
+ }
+ }
+ }
+ return false;
}
void PAINT_OT_brush_colors_flip(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Brush Colors Flip";
- ot->idname = "PAINT_OT_brush_colors_flip";
- ot->description = "Toggle foreground and background brush colors";
+ /* identifiers */
+ ot->name = "Brush Colors Flip";
+ ot->idname = "PAINT_OT_brush_colors_flip";
+ ot->description = "Toggle foreground and background brush colors";
- /* api callbacks */
- ot->exec = brush_colors_flip_exec;
- ot->poll = brush_colors_flip_poll;
+ /* api callbacks */
+ ot->exec = brush_colors_flip_exec;
+ ot->poll = brush_colors_flip_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
void ED_imapaint_bucket_fill(struct bContext *C, float color[3], wmOperator *op)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = sima->image;
+ 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);
+ BKE_undosys_step_push_init_with_type(wm->undo_stack, C, op->type->name, BKE_UNDOSYS_TYPE_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);
- paint_2d_bucket_fill(C, color, NULL, NULL, NULL);
+ paint_2d_bucket_fill(C, color, NULL, NULL, NULL);
- BKE_undosys_step_push(wm->undo_stack, C, op->type->name);
+ BKE_undosys_step_push(wm->undo_stack, C, op->type->name);
- DEG_id_tag_update(&ima->id, 0);
+ DEG_id_tag_update(&ima->id, 0);
}
-
static bool texture_paint_poll(bContext *C)
{
- if (texture_paint_toggle_poll(C))
- if (CTX_data_active_object(C)->mode & OB_MODE_TEXTURE_PAINT)
- return 1;
+ if (texture_paint_toggle_poll(C))
+ if (CTX_data_active_object(C)->mode & OB_MODE_TEXTURE_PAINT)
+ return 1;
- return 0;
+ return 0;
}
bool image_texture_paint_poll(bContext *C)
{
- return (texture_paint_poll(C) || image_paint_poll(C));
+ return (texture_paint_poll(C) || image_paint_poll(C));
}
bool facemask_paint_poll(bContext *C)
{
- return BKE_paint_select_face_test(CTX_data_active_object(C));
+ return BKE_paint_select_face_test(CTX_data_active_object(C));
}
bool vert_paint_poll(bContext *C)
{
- return BKE_paint_select_vert_test(CTX_data_active_object(C));
+ return BKE_paint_select_vert_test(CTX_data_active_object(C));
}
bool mask_paint_poll(bContext *C)
{
- return BKE_paint_select_elem_test(CTX_data_active_object(C));
+ return BKE_paint_select_elem_test(CTX_data_active_object(C));
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index cad75efbf56..5390f18304a 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -30,7 +30,6 @@
#include "DNA_space_types.h"
#include "DNA_object_types.h"
-
#include "BLI_math_color_blend.h"
#include "BLI_stack.h"
#include "BLI_bitmap.h"
@@ -57,7 +56,6 @@
#include "UI_view2d.h"
-
#include "GPU_draw.h"
#include "paint_intern.h"
@@ -67,1677 +65,1854 @@
/* Defines and Structs */
typedef struct BrushPainterCache {
- bool use_float; /* need float imbuf? */
- bool use_color_correction; /* use color correction for float */
- bool invert;
-
- bool is_texbrush;
- bool is_maskbrush;
-
- int lastdiameter;
- float last_tex_rotation;
- float last_mask_rotation;
- float last_pressure;
-
- 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;
+ bool use_float; /* need float imbuf? */
+ bool use_color_correction; /* use color correction for float */
+ bool invert;
+
+ bool is_texbrush;
+ bool is_maskbrush;
+
+ int lastdiameter;
+ float last_tex_rotation;
+ float last_mask_rotation;
+ float last_pressure;
+
+ 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;
} BrushPainterCache;
typedef struct BrushPainter {
- Scene *scene;
- Brush *brush;
+ Scene *scene;
+ Brush *brush;
- float lastpaintpos[2]; /* position of last paint op */
- float startpaintpos[2]; /* position of first paint */
+ float lastpaintpos[2]; /* position of last paint op */
+ float startpaintpos[2]; /* position of first paint */
- short firsttouch; /* first paint op */
+ short firsttouch; /* first paint op */
- struct ImagePool *pool; /* image pool */
- rctf tex_mapping; /* texture coordinate mapping */
- rctf mask_mapping; /* mask texture coordinate mapping */
+ struct ImagePool *pool; /* image pool */
+ rctf tex_mapping; /* texture coordinate mapping */
+ rctf mask_mapping; /* mask texture coordinate mapping */
- BrushPainterCache cache;
+ BrushPainterCache cache;
} BrushPainter;
typedef struct ImagePaintRegion {
- int destx, desty;
- int srcx, srcy;
- int width, height;
+ int destx, desty;
+ int srcx, srcy;
+ int width, height;
} ImagePaintRegion;
typedef struct ImagePaintState {
- BrushPainter *painter;
- SpaceImage *sima;
- View2D *v2d;
- Scene *scene;
- bScreen *screen;
- struct ImagePool *image_pool;
-
- Brush *brush;
- short tool, blend;
- Image *image;
- ImBuf *canvas;
- ImBuf *clonecanvas;
- const char *warnpackedfile;
- const char *warnmultifile;
-
- bool do_masking;
-
- /* viewport texture paint only, but _not_ project paint */
- Object *ob;
- int faceindex;
- float uv[2];
- int do_facesel;
- int symmetry;
-
- bool need_redraw;
-
- BlurKernel *blurkernel;
+ BrushPainter *painter;
+ SpaceImage *sima;
+ View2D *v2d;
+ Scene *scene;
+ bScreen *screen;
+ struct ImagePool *image_pool;
+
+ Brush *brush;
+ short tool, blend;
+ Image *image;
+ ImBuf *canvas;
+ ImBuf *clonecanvas;
+ const char *warnpackedfile;
+ const char *warnmultifile;
+
+ bool do_masking;
+
+ /* viewport texture paint only, but _not_ project paint */
+ Object *ob;
+ int faceindex;
+ float uv[2];
+ int do_facesel;
+ int symmetry;
+
+ bool need_redraw;
+
+ BlurKernel *blurkernel;
} ImagePaintState;
-
static BrushPainter *brush_painter_2d_new(Scene *scene, Brush *brush, bool invert)
{
- BrushPainter *painter = MEM_callocN(sizeof(BrushPainter), "BrushPainter");
+ BrushPainter *painter = MEM_callocN(sizeof(BrushPainter), "BrushPainter");
- painter->brush = brush;
- painter->scene = scene;
- painter->firsttouch = 1;
- painter->cache.lastdiameter = -1; /* force ibuf create in refresh */
- painter->cache.invert = invert;
+ painter->brush = brush;
+ painter->scene = scene;
+ painter->firsttouch = 1;
+ painter->cache.lastdiameter = -1; /* force ibuf create in refresh */
+ painter->cache.invert = invert;
- return painter;
+ return painter;
}
-
-static void brush_painter_2d_require_imbuf(BrushPainter *painter, bool use_float, bool use_color_correction)
+static void brush_painter_2d_require_imbuf(BrushPainter *painter,
+ bool use_float,
+ bool use_color_correction)
{
- Brush *brush = painter->brush;
-
- if ((painter->cache.use_float != use_float)) {
- if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
- if (painter->cache.curve_mask) MEM_freeN(painter->cache.curve_mask);
- if (painter->cache.tex_mask) MEM_freeN(painter->cache.tex_mask);
- if (painter->cache.tex_mask_old) MEM_freeN(painter->cache.tex_mask_old);
- painter->cache.ibuf = NULL;
- painter->cache.curve_mask = NULL;
- painter->cache.tex_mask = NULL;
- painter->cache.lastdiameter = -1; /* force ibuf create in refresh */
- }
-
- painter->cache.use_float = use_float;
- painter->cache.use_color_correction = use_float && use_color_correction;
- painter->cache.is_texbrush = (brush->mtex.tex && brush->imagepaint_tool == PAINT_TOOL_DRAW) ? true : false;
- painter->cache.is_maskbrush = (brush->mask_mtex.tex) ? true : false;
+ Brush *brush = painter->brush;
+
+ if ((painter->cache.use_float != use_float)) {
+ if (painter->cache.ibuf)
+ IMB_freeImBuf(painter->cache.ibuf);
+ if (painter->cache.curve_mask)
+ MEM_freeN(painter->cache.curve_mask);
+ if (painter->cache.tex_mask)
+ MEM_freeN(painter->cache.tex_mask);
+ if (painter->cache.tex_mask_old)
+ MEM_freeN(painter->cache.tex_mask_old);
+ painter->cache.ibuf = NULL;
+ painter->cache.curve_mask = NULL;
+ painter->cache.tex_mask = NULL;
+ painter->cache.lastdiameter = -1; /* force ibuf create in refresh */
+ }
+
+ painter->cache.use_float = use_float;
+ painter->cache.use_color_correction = use_float && use_color_correction;
+ painter->cache.is_texbrush = (brush->mtex.tex && brush->imagepaint_tool == PAINT_TOOL_DRAW) ?
+ true :
+ false;
+ painter->cache.is_maskbrush = (brush->mask_mtex.tex) ? true : false;
}
static void brush_painter_2d_free(BrushPainter *painter)
{
- if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
- if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
- if (painter->cache.curve_mask) MEM_freeN(painter->cache.curve_mask);
- if (painter->cache.tex_mask) MEM_freeN(painter->cache.tex_mask);
- if (painter->cache.tex_mask_old) MEM_freeN(painter->cache.tex_mask_old);
- MEM_freeN(painter);
+ if (painter->cache.ibuf)
+ IMB_freeImBuf(painter->cache.ibuf);
+ if (painter->cache.texibuf)
+ IMB_freeImBuf(painter->cache.texibuf);
+ if (painter->cache.curve_mask)
+ MEM_freeN(painter->cache.curve_mask);
+ if (painter->cache.tex_mask)
+ MEM_freeN(painter->cache.tex_mask);
+ if (painter->cache.tex_mask_old)
+ MEM_freeN(painter->cache.tex_mask_old);
+ MEM_freeN(painter);
}
static void brush_imbuf_tex_co(rctf *mapping, int x, int y, float texco[3])
{
- texco[0] = mapping->xmin + x * mapping->xmax;
- texco[1] = mapping->ymin + y * mapping->ymax;
- texco[2] = 0.0f;
+ texco[0] = mapping->xmin + x * mapping->xmax;
+ texco[1] = mapping->ymin + y * mapping->ymax;
+ texco[2] = 0.0f;
}
/* create a mask with the mask texture */
static unsigned short *brush_painter_mask_ibuf_new(BrushPainter *painter, int size)
{
- Scene *scene = painter->scene;
- Brush *brush = painter->brush;
- rctf mask_mapping = painter->mask_mapping;
- struct ImagePool *pool = painter->pool;
-
- float texco[3];
- unsigned short *mask, *m;
- int x, y, thread = 0;
-
- mask = MEM_mallocN(sizeof(unsigned short) * size * size, "brush_painter_mask");
- m = mask;
-
- for (y = 0; y < size; y++) {
- for (x = 0; x < size; x++, m++) {
- 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);
- }
- }
-
- return mask;
+ Scene *scene = painter->scene;
+ Brush *brush = painter->brush;
+ rctf mask_mapping = painter->mask_mapping;
+ struct ImagePool *pool = painter->pool;
+
+ float texco[3];
+ unsigned short *mask, *m;
+ int x, y, thread = 0;
+
+ mask = MEM_mallocN(sizeof(unsigned short) * size * size, "brush_painter_mask");
+ m = mask;
+
+ for (y = 0; y < size; y++) {
+ for (x = 0; x < size; x++, m++) {
+ 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);
+ }
+ }
+
+ return mask;
}
/* update rectangular section of the brush image */
-static void brush_painter_mask_imbuf_update(
- BrushPainter *painter, unsigned short *tex_mask_old,
- int origx, int origy, int w, int h, int xt, int yt, int diameter)
+static void brush_painter_mask_imbuf_update(BrushPainter *painter,
+ unsigned short *tex_mask_old,
+ int origx,
+ int origy,
+ int w,
+ int h,
+ int xt,
+ int yt,
+ int diameter)
{
- Scene *scene = painter->scene;
- Brush *brush = painter->brush;
- rctf tex_mapping = painter->mask_mapping;
- struct ImagePool *pool = painter->pool;
- unsigned short res;
-
- bool use_texture_old = (tex_mask_old != NULL);
-
- int x, y, thread = 0;
-
- unsigned short *tex_mask = painter->cache.tex_mask;
- unsigned short *tex_mask_cur = painter->cache.tex_mask_old;
-
- /* fill pixels */
- for (y = origy; y < h; y++) {
- for (x = origx; x < w; x++) {
- /* sample texture */
- float texco[3];
-
- /* handle byte pixel */
- unsigned short *b = tex_mask + (y * diameter + x);
- unsigned short *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));
- }
-
- /* read from old texture buffer */
- if (use_texture_old) {
- res = *(tex_mask_old + ((y - origy + yt) * painter->cache.tex_mask_old_w + (x - origx + xt)));
- }
-
- /* write to new texture mask */
- *t = res;
- /* write to mask image buffer */
- *b = res;
- }
- }
+ Scene *scene = painter->scene;
+ Brush *brush = painter->brush;
+ rctf tex_mapping = painter->mask_mapping;
+ struct ImagePool *pool = painter->pool;
+ unsigned short res;
+
+ bool use_texture_old = (tex_mask_old != NULL);
+
+ int x, y, thread = 0;
+
+ unsigned short *tex_mask = painter->cache.tex_mask;
+ unsigned short *tex_mask_cur = painter->cache.tex_mask_old;
+
+ /* fill pixels */
+ for (y = origy; y < h; y++) {
+ for (x = origx; x < w; x++) {
+ /* sample texture */
+ float texco[3];
+
+ /* handle byte pixel */
+ unsigned short *b = tex_mask + (y * diameter + x);
+ unsigned short *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));
+ }
+
+ /* read from old texture buffer */
+ if (use_texture_old) {
+ res = *(tex_mask_old +
+ ((y - origy + yt) * painter->cache.tex_mask_old_w + (x - origx + xt)));
+ }
+
+ /* write to new texture mask */
+ *t = res;
+ /* write to mask image buffer */
+ *b = res;
+ }
+ }
}
-
/**
* Update the brush mask image by trying to reuse the cached texture result.
* This can be considerably faster for brushes that change size due to pressure or
* textures that stick to the surface where only part of the pixels are new
*/
-static void brush_painter_mask_imbuf_partial_update(BrushPainter *painter, const float pos[2], int diameter)
+static void brush_painter_mask_imbuf_partial_update(BrushPainter *painter,
+ const float pos[2],
+ int diameter)
{
- BrushPainterCache *cache = &painter->cache;
- unsigned short *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");
-
- /* 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");
-
- if (tex_mask_old) {
- ImBuf maskibuf;
- ImBuf maskibuf_old;
- maskibuf.x = maskibuf.y = diameter;
- maskibuf_old.x = cache->tex_mask_old_w;
- maskibuf_old.y = cache->tex_mask_old_h;
-
- srcx = srcy = 0;
- w = cache->tex_mask_old_w;
- h = cache->tex_mask_old_h;
- destx = (int)floorf(painter->lastpaintpos[0]) - (int)floorf(pos[0]) + (diameter / 2 - w / 2);
- desty = (int)floorf(painter->lastpaintpos[1]) - (int)floorf(pos[1]) + (diameter / 2 - h / 2);
-
- /* hack, use temporary rects so that clipping works */
- IMB_rectclip(&maskibuf, &maskibuf_old, &destx, &desty, &srcx, &srcy, &w, &h);
- }
- else {
- srcx = srcy = 0;
- destx = desty = 0;
- w = h = 0;
- }
-
- x1 = min_ii(destx, diameter);
- y1 = min_ii(desty, diameter);
- x2 = min_ii(destx + w, diameter);
- y2 = min_ii(desty + h, diameter);
-
- /* blend existing texture in new position */
- if ((x1 < x2) && (y1 < y2))
- brush_painter_mask_imbuf_update(painter, tex_mask_old, x1, y1, x2, y2, srcx, srcy, diameter);
-
- if (tex_mask_old)
- MEM_freeN(tex_mask_old);
-
- /* sample texture in new areas */
- if ((0 < x1) && (0 < diameter))
- brush_painter_mask_imbuf_update(painter, NULL, 0, 0, x1, diameter, 0, 0, diameter);
- if ((x2 < diameter) && (0 < diameter))
- brush_painter_mask_imbuf_update(painter, NULL, x2, 0, diameter, diameter, 0, 0, diameter);
- if ((x1 < x2) && (0 < y1))
- brush_painter_mask_imbuf_update(painter, NULL, x1, 0, x2, y1, 0, 0, diameter);
- if ((x1 < x2) && (y2 < diameter))
- brush_painter_mask_imbuf_update(painter, NULL, x1, y2, x2, diameter, 0, 0, diameter);
-
- /* through with sampling, now update sizes */
- cache->tex_mask_old_w = diameter;
- cache->tex_mask_old_h = diameter;
+ BrushPainterCache *cache = &painter->cache;
+ unsigned short *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");
+
+ /* 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");
+
+ if (tex_mask_old) {
+ ImBuf maskibuf;
+ ImBuf maskibuf_old;
+ maskibuf.x = maskibuf.y = diameter;
+ maskibuf_old.x = cache->tex_mask_old_w;
+ maskibuf_old.y = cache->tex_mask_old_h;
+
+ srcx = srcy = 0;
+ w = cache->tex_mask_old_w;
+ h = cache->tex_mask_old_h;
+ destx = (int)floorf(painter->lastpaintpos[0]) - (int)floorf(pos[0]) + (diameter / 2 - w / 2);
+ desty = (int)floorf(painter->lastpaintpos[1]) - (int)floorf(pos[1]) + (diameter / 2 - h / 2);
+
+ /* hack, use temporary rects so that clipping works */
+ IMB_rectclip(&maskibuf, &maskibuf_old, &destx, &desty, &srcx, &srcy, &w, &h);
+ }
+ else {
+ srcx = srcy = 0;
+ destx = desty = 0;
+ w = h = 0;
+ }
+
+ x1 = min_ii(destx, diameter);
+ y1 = min_ii(desty, diameter);
+ x2 = min_ii(destx + w, diameter);
+ y2 = min_ii(desty + h, diameter);
+
+ /* blend existing texture in new position */
+ if ((x1 < x2) && (y1 < y2))
+ brush_painter_mask_imbuf_update(painter, tex_mask_old, x1, y1, x2, y2, srcx, srcy, diameter);
+
+ if (tex_mask_old)
+ MEM_freeN(tex_mask_old);
+
+ /* sample texture in new areas */
+ if ((0 < x1) && (0 < diameter))
+ brush_painter_mask_imbuf_update(painter, NULL, 0, 0, x1, diameter, 0, 0, diameter);
+ if ((x2 < diameter) && (0 < diameter))
+ brush_painter_mask_imbuf_update(painter, NULL, x2, 0, diameter, diameter, 0, 0, diameter);
+ if ((x1 < x2) && (0 < y1))
+ brush_painter_mask_imbuf_update(painter, NULL, x1, 0, x2, y1, 0, 0, diameter);
+ if ((x1 < x2) && (y2 < diameter))
+ brush_painter_mask_imbuf_update(painter, NULL, x1, y2, x2, diameter, 0, 0, diameter);
+
+ /* through with sampling, now update sizes */
+ cache->tex_mask_old_w = diameter;
+ cache->tex_mask_old_h = diameter;
}
/* create a mask with the falloff strength */
-static unsigned short *brush_painter_curve_mask_new(BrushPainter *painter, int diameter, float radius)
+static unsigned short *brush_painter_curve_mask_new(BrushPainter *painter,
+ int diameter,
+ float radius)
{
- Brush *brush = painter->brush;
+ Brush *brush = painter->brush;
- int xoff = -radius;
- int yoff = -radius;
+ int xoff = -radius;
+ int yoff = -radius;
- unsigned short *mask, *m;
- int x, y;
+ unsigned short *mask, *m;
+ int x, y;
- mask = MEM_mallocN(sizeof(unsigned short) * diameter * diameter, "brush_painter_mask");
- m = mask;
+ mask = MEM_mallocN(sizeof(unsigned short) * diameter * diameter, "brush_painter_mask");
+ m = mask;
- for (y = 0; y < diameter; y++) {
- for (x = 0; x < diameter; x++, m++) {
- float xy[2] = {x + xoff, y + yoff};
- float len = len_v2(xy);
+ for (y = 0; y < diameter; y++) {
+ for (x = 0; x < diameter; x++, m++) {
+ float xy[2] = {x + xoff, y + yoff};
+ float len = len_v2(xy);
- *m = (unsigned short)(65535.0f * BKE_brush_curve_strength_clamped(brush, len, radius));
- }
- }
+ *m = (unsigned short)(65535.0f * BKE_brush_curve_strength_clamped(brush, len, radius));
+ }
+ }
- return mask;
+ return mask;
}
-
/* create imbuf with brush color */
-static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size, float pressure, float distance)
+static ImBuf *brush_painter_imbuf_new(BrushPainter *painter,
+ int size,
+ float pressure,
+ float distance)
{
- Scene *scene = painter->scene;
- Brush *brush = painter->brush;
-
- const char *display_device = scene->display_settings.display_device;
- struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
-
- rctf tex_mapping = painter->tex_mapping;
- struct ImagePool *pool = painter->pool;
-
- bool use_color_correction = painter->cache.use_color_correction;
- bool use_float = painter->cache.use_float;
- bool is_texbrush = painter->cache.is_texbrush;
-
- int x, y, thread = 0;
- float brush_rgb[3];
-
- /* allocate image buffer */
- ImBuf *ibuf = IMB_allocImBuf(size, size, 32, (use_float) ? IB_rectfloat : IB_rect);
-
- /* get brush color */
- if (brush->imagepaint_tool == PAINT_TOOL_DRAW) {
- paint_brush_color_get(scene, brush, use_color_correction, painter->cache.invert, distance, pressure, brush_rgb, display);
- }
- else {
- brush_rgb[0] = 1.0f;
- brush_rgb[1] = 1.0f;
- brush_rgb[2] = 1.0f;
- }
-
- /* fill image buffer */
- for (y = 0; y < size; y++) {
- for (x = 0; x < size; x++) {
- /* sample texture and multiply with brush color */
- float texco[3], rgba[4];
-
- if (is_texbrush) {
- brush_imbuf_tex_co(&tex_mapping, x, y, texco);
- BKE_brush_sample_tex_3d(scene, brush, texco, rgba, thread, pool);
- /* TODO(sergey): Support texture paint color space. */
- if (!use_float) {
- IMB_colormanagement_scene_linear_to_display_v3(rgba, display);
- }
- mul_v3_v3(rgba, brush_rgb);
- }
- else {
- copy_v3_v3(rgba, brush_rgb);
- rgba[3] = 1.0f;
- }
-
- if (use_float) {
- /* write to float pixel */
- float *dstf = ibuf->rect_float + (y * size + x) * 4;
- mul_v3_v3fl(dstf, rgba, rgba[3]); /* premultiply */
- dstf[3] = rgba[3];
- }
- else {
- /* write to byte pixel */
- unsigned char *dst = (unsigned char *)ibuf->rect + (y * size + x) * 4;
-
- rgb_float_to_uchar(dst, rgba);
- dst[3] = unit_float_to_uchar_clamp(rgba[3]);
- }
- }
- }
-
- return ibuf;
+ Scene *scene = painter->scene;
+ Brush *brush = painter->brush;
+
+ const char *display_device = scene->display_settings.display_device;
+ struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
+
+ rctf tex_mapping = painter->tex_mapping;
+ struct ImagePool *pool = painter->pool;
+
+ bool use_color_correction = painter->cache.use_color_correction;
+ bool use_float = painter->cache.use_float;
+ bool is_texbrush = painter->cache.is_texbrush;
+
+ int x, y, thread = 0;
+ float brush_rgb[3];
+
+ /* allocate image buffer */
+ ImBuf *ibuf = IMB_allocImBuf(size, size, 32, (use_float) ? IB_rectfloat : IB_rect);
+
+ /* get brush color */
+ if (brush->imagepaint_tool == PAINT_TOOL_DRAW) {
+ paint_brush_color_get(scene,
+ brush,
+ use_color_correction,
+ painter->cache.invert,
+ distance,
+ pressure,
+ brush_rgb,
+ display);
+ }
+ else {
+ brush_rgb[0] = 1.0f;
+ brush_rgb[1] = 1.0f;
+ brush_rgb[2] = 1.0f;
+ }
+
+ /* fill image buffer */
+ for (y = 0; y < size; y++) {
+ for (x = 0; x < size; x++) {
+ /* sample texture and multiply with brush color */
+ float texco[3], rgba[4];
+
+ if (is_texbrush) {
+ brush_imbuf_tex_co(&tex_mapping, x, y, texco);
+ BKE_brush_sample_tex_3d(scene, brush, texco, rgba, thread, pool);
+ /* TODO(sergey): Support texture paint color space. */
+ if (!use_float) {
+ IMB_colormanagement_scene_linear_to_display_v3(rgba, display);
+ }
+ mul_v3_v3(rgba, brush_rgb);
+ }
+ else {
+ copy_v3_v3(rgba, brush_rgb);
+ rgba[3] = 1.0f;
+ }
+
+ if (use_float) {
+ /* write to float pixel */
+ float *dstf = ibuf->rect_float + (y * size + x) * 4;
+ mul_v3_v3fl(dstf, rgba, rgba[3]); /* premultiply */
+ dstf[3] = rgba[3];
+ }
+ else {
+ /* write to byte pixel */
+ unsigned char *dst = (unsigned char *)ibuf->rect + (y * size + x) * 4;
+
+ rgb_float_to_uchar(dst, rgba);
+ dst[3] = unit_float_to_uchar_clamp(rgba[3]);
+ }
+ }
+ }
+
+ return ibuf;
}
/* update rectangular section of the brush image */
static void brush_painter_imbuf_update(
- BrushPainter *painter, ImBuf *oldtexibuf,
- int origx, int origy, int w, int h, int xt, int yt)
+ BrushPainter *painter, ImBuf *oldtexibuf, int origx, int origy, int w, int h, int xt, int yt)
{
- Scene *scene = painter->scene;
- Brush *brush = painter->brush;
-
- const char *display_device = scene->display_settings.display_device;
- struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
-
- rctf tex_mapping = painter->tex_mapping;
- struct ImagePool *pool = painter->pool;
-
- bool use_color_correction = painter->cache.use_color_correction;
- bool use_float = painter->cache.use_float;
- bool is_texbrush = painter->cache.is_texbrush;
- bool use_texture_old = (oldtexibuf != NULL);
-
- int x, y, thread = 0;
- float brush_rgb[3];
-
- ImBuf *ibuf = painter->cache.ibuf;
- ImBuf *texibuf = painter->cache.texibuf;
-
- /* get brush color */
- if (brush->imagepaint_tool == PAINT_TOOL_DRAW) {
- paint_brush_color_get(scene, brush, use_color_correction, painter->cache.invert, 0.0, 1.0, brush_rgb, display);
- }
- else {
- brush_rgb[0] = 1.0f;
- brush_rgb[1] = 1.0f;
- brush_rgb[2] = 1.0f;
- }
-
- /* fill pixels */
- for (y = origy; y < h; y++) {
- for (x = origx; x < w; x++) {
- /* sample texture and multiply with brush color */
- float texco[3], rgba[4];
-
- if (!use_texture_old) {
- if (is_texbrush) {
- brush_imbuf_tex_co(&tex_mapping, x, y, texco);
- BKE_brush_sample_tex_3d(scene, brush, texco, rgba, thread, pool);
- /* TODO(sergey): Support texture paint color space. */
- if (!use_float) {
- IMB_colormanagement_scene_linear_to_display_v3(rgba, display);
- }
- mul_v3_v3(rgba, brush_rgb);
- }
- else {
- copy_v3_v3(rgba, brush_rgb);
- rgba[3] = 1.0f;
- }
- }
-
- if (use_float) {
- /* handle float pixel */
- float *bf = ibuf->rect_float + (y * ibuf->x + x) * 4;
- float *tf = texibuf->rect_float + (y * texibuf->x + x) * 4;
-
- /* read from old texture buffer */
- if (use_texture_old) {
- const float *otf = oldtexibuf->rect_float + ((y - origy + yt) * oldtexibuf->x + (x - origx + xt)) * 4;
- copy_v4_v4(rgba, otf);
- }
-
- /* write to new texture buffer */
- copy_v4_v4(tf, rgba);
-
- /* output premultiplied float image, mf was already premultiplied */
- mul_v3_v3fl(bf, rgba, rgba[3]);
- bf[3] = rgba[3];
- }
- else {
- unsigned char 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;
-
- /* 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;
- crgba[0] = ot[0];
- crgba[1] = ot[1];
- crgba[2] = ot[2];
- crgba[3] = ot[3];
- }
- else
- rgba_float_to_uchar(crgba, rgba);
-
- /* write to new texture buffer */
- t[0] = crgba[0];
- t[1] = crgba[1];
- t[2] = crgba[2];
- t[3] = crgba[3];
-
- /* write to brush image buffer */
- b[0] = crgba[0];
- b[1] = crgba[1];
- b[2] = crgba[2];
- b[3] = crgba[3];
- }
- }
- }
+ Scene *scene = painter->scene;
+ Brush *brush = painter->brush;
+
+ const char *display_device = scene->display_settings.display_device;
+ struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
+
+ rctf tex_mapping = painter->tex_mapping;
+ struct ImagePool *pool = painter->pool;
+
+ bool use_color_correction = painter->cache.use_color_correction;
+ bool use_float = painter->cache.use_float;
+ bool is_texbrush = painter->cache.is_texbrush;
+ bool use_texture_old = (oldtexibuf != NULL);
+
+ int x, y, thread = 0;
+ float brush_rgb[3];
+
+ ImBuf *ibuf = painter->cache.ibuf;
+ ImBuf *texibuf = painter->cache.texibuf;
+
+ /* get brush color */
+ if (brush->imagepaint_tool == PAINT_TOOL_DRAW) {
+ paint_brush_color_get(
+ scene, brush, use_color_correction, painter->cache.invert, 0.0, 1.0, brush_rgb, display);
+ }
+ else {
+ brush_rgb[0] = 1.0f;
+ brush_rgb[1] = 1.0f;
+ brush_rgb[2] = 1.0f;
+ }
+
+ /* fill pixels */
+ for (y = origy; y < h; y++) {
+ for (x = origx; x < w; x++) {
+ /* sample texture and multiply with brush color */
+ float texco[3], rgba[4];
+
+ if (!use_texture_old) {
+ if (is_texbrush) {
+ brush_imbuf_tex_co(&tex_mapping, x, y, texco);
+ BKE_brush_sample_tex_3d(scene, brush, texco, rgba, thread, pool);
+ /* TODO(sergey): Support texture paint color space. */
+ if (!use_float) {
+ IMB_colormanagement_scene_linear_to_display_v3(rgba, display);
+ }
+ mul_v3_v3(rgba, brush_rgb);
+ }
+ else {
+ copy_v3_v3(rgba, brush_rgb);
+ rgba[3] = 1.0f;
+ }
+ }
+
+ if (use_float) {
+ /* handle float pixel */
+ float *bf = ibuf->rect_float + (y * ibuf->x + x) * 4;
+ float *tf = texibuf->rect_float + (y * texibuf->x + x) * 4;
+
+ /* read from old texture buffer */
+ if (use_texture_old) {
+ const float *otf = oldtexibuf->rect_float +
+ ((y - origy + yt) * oldtexibuf->x + (x - origx + xt)) * 4;
+ copy_v4_v4(rgba, otf);
+ }
+
+ /* write to new texture buffer */
+ copy_v4_v4(tf, rgba);
+
+ /* output premultiplied float image, mf was already premultiplied */
+ mul_v3_v3fl(bf, rgba, rgba[3]);
+ bf[3] = rgba[3];
+ }
+ else {
+ unsigned char 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;
+
+ /* 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;
+ crgba[0] = ot[0];
+ crgba[1] = ot[1];
+ crgba[2] = ot[2];
+ crgba[3] = ot[3];
+ }
+ else
+ rgba_float_to_uchar(crgba, rgba);
+
+ /* write to new texture buffer */
+ t[0] = crgba[0];
+ t[1] = crgba[1];
+ t[2] = crgba[2];
+ t[3] = crgba[3];
+
+ /* write to brush image buffer */
+ b[0] = crgba[0];
+ b[1] = crgba[1];
+ b[2] = crgba[2];
+ b[3] = crgba[3];
+ }
+ }
+ }
}
/* update the brush image by trying to reuse the cached texture result. this
* can be considerably faster for brushes that change size due to pressure or
* textures that stick to the surface where only part of the pixels are new */
-static void brush_painter_imbuf_partial_update(BrushPainter *painter, const float pos[2], int diameter)
+static void brush_painter_imbuf_partial_update(BrushPainter *painter,
+ const float pos[2],
+ int diameter)
{
- BrushPainterCache *cache = &painter->cache;
- ImBuf *oldtexibuf, *ibuf;
- int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
-
- /* create brush image buffer if it didn't exist yet */
- imbflag = (cache->use_float) ? IB_rectfloat : IB_rect;
- if (!cache->ibuf)
- cache->ibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
- ibuf = cache->ibuf;
-
- /* create new texture image buffer with coordinates relative to old */
- oldtexibuf = cache->texibuf;
- cache->texibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
-
- if (oldtexibuf) {
- srcx = srcy = 0;
- w = oldtexibuf->x;
- h = oldtexibuf->y;
- destx = (int)floorf(painter->lastpaintpos[0]) - (int)floorf(pos[0]) + (diameter / 2 - w / 2);
- desty = (int)floorf(painter->lastpaintpos[1]) - (int)floorf(pos[1]) + (diameter / 2 - h / 2);
-
- IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h);
- }
- else {
- srcx = srcy = 0;
- destx = desty = 0;
- w = h = 0;
- }
-
- x1 = min_ii(destx, ibuf->x);
- y1 = min_ii(desty, ibuf->y);
- x2 = min_ii(destx + w, ibuf->x);
- y2 = min_ii(desty + h, ibuf->y);
-
- /* blend existing texture in new position */
- if ((x1 < x2) && (y1 < y2))
- brush_painter_imbuf_update(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy);
-
- if (oldtexibuf)
- IMB_freeImBuf(oldtexibuf);
-
- /* sample texture in new areas */
- if ((0 < x1) && (0 < ibuf->y))
- brush_painter_imbuf_update(painter, NULL, 0, 0, x1, ibuf->y, 0, 0);
- if ((x2 < ibuf->x) && (0 < ibuf->y))
- brush_painter_imbuf_update(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0);
- if ((x1 < x2) && (0 < y1))
- brush_painter_imbuf_update(painter, NULL, x1, 0, x2, y1, 0, 0);
- if ((x1 < x2) && (y2 < ibuf->y))
- brush_painter_imbuf_update(painter, NULL, x1, y2, x2, ibuf->y, 0, 0);
+ BrushPainterCache *cache = &painter->cache;
+ ImBuf *oldtexibuf, *ibuf;
+ int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
+
+ /* create brush image buffer if it didn't exist yet */
+ imbflag = (cache->use_float) ? IB_rectfloat : IB_rect;
+ if (!cache->ibuf)
+ cache->ibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
+ ibuf = cache->ibuf;
+
+ /* create new texture image buffer with coordinates relative to old */
+ oldtexibuf = cache->texibuf;
+ cache->texibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
+
+ if (oldtexibuf) {
+ srcx = srcy = 0;
+ w = oldtexibuf->x;
+ h = oldtexibuf->y;
+ destx = (int)floorf(painter->lastpaintpos[0]) - (int)floorf(pos[0]) + (diameter / 2 - w / 2);
+ desty = (int)floorf(painter->lastpaintpos[1]) - (int)floorf(pos[1]) + (diameter / 2 - h / 2);
+
+ IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h);
+ }
+ else {
+ srcx = srcy = 0;
+ destx = desty = 0;
+ w = h = 0;
+ }
+
+ x1 = min_ii(destx, ibuf->x);
+ y1 = min_ii(desty, ibuf->y);
+ x2 = min_ii(destx + w, ibuf->x);
+ y2 = min_ii(desty + h, ibuf->y);
+
+ /* blend existing texture in new position */
+ if ((x1 < x2) && (y1 < y2))
+ brush_painter_imbuf_update(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy);
+
+ if (oldtexibuf)
+ IMB_freeImBuf(oldtexibuf);
+
+ /* sample texture in new areas */
+ if ((0 < x1) && (0 < ibuf->y))
+ brush_painter_imbuf_update(painter, NULL, 0, 0, x1, ibuf->y, 0, 0);
+ if ((x2 < ibuf->x) && (0 < ibuf->y))
+ brush_painter_imbuf_update(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0);
+ if ((x1 < x2) && (0 < y1))
+ brush_painter_imbuf_update(painter, NULL, x1, 0, x2, y1, 0, 0);
+ if ((x1 < x2) && (y2 < ibuf->y))
+ brush_painter_imbuf_update(painter, NULL, x1, y2, x2, ibuf->y, 0, 0);
}
-static void brush_painter_2d_tex_mapping(ImagePaintState *s, int diameter, const float startpos[2], const float pos[2], const float mouse[2], int mapmode, rctf *mapping)
+static void brush_painter_2d_tex_mapping(ImagePaintState *s,
+ int diameter,
+ const float startpos[2],
+ const float pos[2],
+ const float mouse[2],
+ int mapmode,
+ rctf *mapping)
{
- float invw = 1.0f / (float)s->canvas->x;
- float invh = 1.0f / (float)s->canvas->y;
- int xmin, ymin, xmax, ymax;
- int ipos[2];
-
- /* find start coordinate of brush in canvas */
- ipos[0] = (int)floorf((pos[0] - diameter / 2) + 1.0f);
- ipos[1] = (int)floorf((pos[1] - diameter / 2) + 1.0f);
-
- if (mapmode == MTEX_MAP_MODE_STENCIL) {
- /* map from view coordinates of brush to region coordinates */
- UI_view2d_view_to_region(s->v2d, ipos[0] * invw, ipos[1] * invh, &xmin, &ymin);
- UI_view2d_view_to_region(s->v2d, (ipos[0] + diameter) * invw, (ipos[1] + diameter) * invh, &xmax, &ymax);
-
- /* output mapping from brush ibuf x/y to region coordinates */
- mapping->xmin = xmin;
- mapping->ymin = ymin;
- mapping->xmax = (xmax - xmin) / (float)diameter;
- mapping->ymax = (ymax - ymin) / (float)diameter;
- }
- else if (mapmode == MTEX_MAP_MODE_3D) {
- /* 3D mapping, just mapping to canvas 0..1 */
- mapping->xmin = 2.0f * (ipos[0] * invw - 0.5f);
- mapping->ymin = 2.0f * (ipos[1] * invh - 0.5f);
- mapping->xmax = 2.0f * invw;
- mapping->ymax = 2.0f * invh;
- }
- else if (ELEM(mapmode, MTEX_MAP_MODE_VIEW, MTEX_MAP_MODE_RANDOM)) {
- /* view mapping */
- mapping->xmin = mouse[0] - diameter * 0.5f + 0.5f;
- mapping->ymin = mouse[1] - diameter * 0.5f + 0.5f;
- mapping->xmax = 1.0f;
- mapping->ymax = 1.0f;
- }
- else /* if (mapmode == MTEX_MAP_MODE_TILED) */ {
- mapping->xmin = (int)(-diameter * 0.5) + (int)floorf(pos[0]) - (int)floorf(startpos[0]);
- mapping->ymin = (int)(-diameter * 0.5) + (int)floorf(pos[1]) - (int)floorf(startpos[1]);
- mapping->xmax = 1.0f;
- mapping->ymax = 1.0f;
- }
+ float invw = 1.0f / (float)s->canvas->x;
+ float invh = 1.0f / (float)s->canvas->y;
+ int xmin, ymin, xmax, ymax;
+ int ipos[2];
+
+ /* find start coordinate of brush in canvas */
+ ipos[0] = (int)floorf((pos[0] - diameter / 2) + 1.0f);
+ ipos[1] = (int)floorf((pos[1] - diameter / 2) + 1.0f);
+
+ if (mapmode == MTEX_MAP_MODE_STENCIL) {
+ /* map from view coordinates of brush to region coordinates */
+ UI_view2d_view_to_region(s->v2d, ipos[0] * invw, ipos[1] * invh, &xmin, &ymin);
+ UI_view2d_view_to_region(
+ s->v2d, (ipos[0] + diameter) * invw, (ipos[1] + diameter) * invh, &xmax, &ymax);
+
+ /* output mapping from brush ibuf x/y to region coordinates */
+ mapping->xmin = xmin;
+ mapping->ymin = ymin;
+ mapping->xmax = (xmax - xmin) / (float)diameter;
+ mapping->ymax = (ymax - ymin) / (float)diameter;
+ }
+ else if (mapmode == MTEX_MAP_MODE_3D) {
+ /* 3D mapping, just mapping to canvas 0..1 */
+ mapping->xmin = 2.0f * (ipos[0] * invw - 0.5f);
+ mapping->ymin = 2.0f * (ipos[1] * invh - 0.5f);
+ mapping->xmax = 2.0f * invw;
+ mapping->ymax = 2.0f * invh;
+ }
+ else if (ELEM(mapmode, MTEX_MAP_MODE_VIEW, MTEX_MAP_MODE_RANDOM)) {
+ /* view mapping */
+ mapping->xmin = mouse[0] - diameter * 0.5f + 0.5f;
+ mapping->ymin = mouse[1] - diameter * 0.5f + 0.5f;
+ mapping->xmax = 1.0f;
+ mapping->ymax = 1.0f;
+ }
+ else /* if (mapmode == MTEX_MAP_MODE_TILED) */ {
+ mapping->xmin = (int)(-diameter * 0.5) + (int)floorf(pos[0]) - (int)floorf(startpos[0]);
+ mapping->ymin = (int)(-diameter * 0.5) + (int)floorf(pos[1]) - (int)floorf(startpos[1]);
+ mapping->xmax = 1.0f;
+ mapping->ymax = 1.0f;
+ }
}
-static void brush_painter_2d_refresh_cache(ImagePaintState *s, BrushPainter *painter, const float pos[2], const float mouse[2], float pressure, float distance, float size)
+static void brush_painter_2d_refresh_cache(ImagePaintState *s,
+ BrushPainter *painter,
+ const float pos[2],
+ const float mouse[2],
+ float pressure,
+ float distance,
+ float size)
{
- const Scene *scene = painter->scene;
- UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
- Brush *brush = painter->brush;
- BrushPainterCache *cache = &painter->cache;
- const int diameter = 2 * size;
-
- bool do_random = false;
- bool do_partial_update = false;
- bool update_color = (
- (brush->flag & BRUSH_USE_GRADIENT) &&
- ((ELEM(brush->gradient_stroke_mode,
- BRUSH_GRADIENT_SPACING_REPEAT,
- BRUSH_GRADIENT_SPACING_CLAMP)) ||
- (cache->last_pressure != pressure)));
- float tex_rotation = -brush->mtex.rot;
- float mask_rotation = -brush->mask_mtex.rot;
-
- painter->pool = BKE_image_pool_new();
-
- /* determine how can update based on textures used */
- if (painter->cache.is_texbrush) {
- if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) {
- tex_rotation += ups->brush_rotation;
- }
- else if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
- do_random = true;
- else if (!((brush->flag & BRUSH_ANCHORED) || update_color))
- do_partial_update = true;
-
- brush_painter_2d_tex_mapping(
- s, diameter, painter->startpaintpos, pos, mouse,
- brush->mtex.brush_map_mode, &painter->tex_mapping);
- }
-
- if (painter->cache.is_maskbrush) {
- bool renew_maxmask = false;
- bool do_partial_update_mask = false;
- /* invalidate case for all mapping modes */
- if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) {
- mask_rotation += ups->brush_rotation_sec;
- }
- else if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM) {
- renew_maxmask = true;
- }
- else if (!(brush->flag & BRUSH_ANCHORED)) {
- do_partial_update_mask = true;
- renew_maxmask = true;
- }
- /* explicitly disable partial update even if it has been enabled above */
- if (brush->mask_pressure) {
- do_partial_update_mask = false;
- renew_maxmask = true;
- }
-
- if ((diameter != cache->lastdiameter) ||
- (mask_rotation != cache->last_mask_rotation) ||
- renew_maxmask)
- {
- if (cache->tex_mask) {
- MEM_freeN(cache->tex_mask);
- cache->tex_mask = NULL;
- }
-
- brush_painter_2d_tex_mapping(
- s, diameter, painter->startpaintpos, pos, mouse,
- brush->mask_mtex.brush_map_mode, &painter->mask_mapping);
-
- if (do_partial_update_mask)
- brush_painter_mask_imbuf_partial_update(painter, pos, diameter);
- else
- cache->tex_mask = brush_painter_mask_ibuf_new(painter, diameter);
- cache->last_mask_rotation = mask_rotation;
- }
- }
-
- /* curve mask can only change if the size changes */
- if (diameter != cache->lastdiameter) {
- if (cache->curve_mask) {
- MEM_freeN(cache->curve_mask);
- cache->curve_mask = NULL;
- }
-
- cache->curve_mask = brush_painter_curve_mask_new(painter, diameter, size);
- }
-
- /* detect if we need to recreate image brush buffer */
- if ((diameter != cache->lastdiameter) ||
- (tex_rotation != cache->last_tex_rotation) ||
- do_random ||
- update_color)
- {
- if (cache->ibuf) {
- IMB_freeImBuf(cache->ibuf);
- cache->ibuf = NULL;
- }
-
- if (do_partial_update) {
- /* do partial update of texture */
- brush_painter_imbuf_partial_update(painter, pos, diameter);
- }
- else {
- /* create brush from scratch */
- cache->ibuf = brush_painter_imbuf_new(painter, diameter, pressure, distance);
- }
-
- cache->lastdiameter = diameter;
- cache->last_tex_rotation = tex_rotation;
- cache->last_pressure = pressure;
- }
- else if (do_partial_update) {
- /* do only partial update of texture */
- int dx = (int)floorf(painter->lastpaintpos[0]) - (int)floorf(pos[0]);
- int dy = (int)floorf(painter->lastpaintpos[1]) - (int)floorf(pos[1]);
-
- if ((dx != 0) || (dy != 0)) {
- brush_painter_imbuf_partial_update(painter, pos, diameter);
- }
- }
-
- BKE_image_pool_free(painter->pool);
- painter->pool = NULL;
+ const Scene *scene = painter->scene;
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+ Brush *brush = painter->brush;
+ BrushPainterCache *cache = &painter->cache;
+ const int diameter = 2 * size;
+
+ bool do_random = false;
+ bool do_partial_update = false;
+ bool update_color = ((brush->flag & BRUSH_USE_GRADIENT) &&
+ ((ELEM(brush->gradient_stroke_mode,
+ BRUSH_GRADIENT_SPACING_REPEAT,
+ BRUSH_GRADIENT_SPACING_CLAMP)) ||
+ (cache->last_pressure != pressure)));
+ float tex_rotation = -brush->mtex.rot;
+ float mask_rotation = -brush->mask_mtex.rot;
+
+ painter->pool = BKE_image_pool_new();
+
+ /* determine how can update based on textures used */
+ if (painter->cache.is_texbrush) {
+ if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) {
+ tex_rotation += ups->brush_rotation;
+ }
+ else if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
+ do_random = true;
+ else if (!((brush->flag & BRUSH_ANCHORED) || update_color))
+ do_partial_update = true;
+
+ brush_painter_2d_tex_mapping(s,
+ diameter,
+ painter->startpaintpos,
+ pos,
+ mouse,
+ brush->mtex.brush_map_mode,
+ &painter->tex_mapping);
+ }
+
+ if (painter->cache.is_maskbrush) {
+ bool renew_maxmask = false;
+ bool do_partial_update_mask = false;
+ /* invalidate case for all mapping modes */
+ if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) {
+ mask_rotation += ups->brush_rotation_sec;
+ }
+ else if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM) {
+ renew_maxmask = true;
+ }
+ else if (!(brush->flag & BRUSH_ANCHORED)) {
+ do_partial_update_mask = true;
+ renew_maxmask = true;
+ }
+ /* explicitly disable partial update even if it has been enabled above */
+ if (brush->mask_pressure) {
+ do_partial_update_mask = false;
+ renew_maxmask = true;
+ }
+
+ if ((diameter != cache->lastdiameter) || (mask_rotation != cache->last_mask_rotation) ||
+ renew_maxmask) {
+ if (cache->tex_mask) {
+ MEM_freeN(cache->tex_mask);
+ cache->tex_mask = NULL;
+ }
+
+ brush_painter_2d_tex_mapping(s,
+ diameter,
+ painter->startpaintpos,
+ pos,
+ mouse,
+ brush->mask_mtex.brush_map_mode,
+ &painter->mask_mapping);
+
+ if (do_partial_update_mask)
+ brush_painter_mask_imbuf_partial_update(painter, pos, diameter);
+ else
+ cache->tex_mask = brush_painter_mask_ibuf_new(painter, diameter);
+ cache->last_mask_rotation = mask_rotation;
+ }
+ }
+
+ /* curve mask can only change if the size changes */
+ if (diameter != cache->lastdiameter) {
+ if (cache->curve_mask) {
+ MEM_freeN(cache->curve_mask);
+ cache->curve_mask = NULL;
+ }
+
+ cache->curve_mask = brush_painter_curve_mask_new(painter, diameter, size);
+ }
+
+ /* detect if we need to recreate image brush buffer */
+ if ((diameter != cache->lastdiameter) || (tex_rotation != cache->last_tex_rotation) ||
+ do_random || update_color) {
+ if (cache->ibuf) {
+ IMB_freeImBuf(cache->ibuf);
+ cache->ibuf = NULL;
+ }
+
+ if (do_partial_update) {
+ /* do partial update of texture */
+ brush_painter_imbuf_partial_update(painter, pos, diameter);
+ }
+ else {
+ /* create brush from scratch */
+ cache->ibuf = brush_painter_imbuf_new(painter, diameter, pressure, distance);
+ }
+
+ cache->lastdiameter = diameter;
+ cache->last_tex_rotation = tex_rotation;
+ cache->last_pressure = pressure;
+ }
+ else if (do_partial_update) {
+ /* do only partial update of texture */
+ int dx = (int)floorf(painter->lastpaintpos[0]) - (int)floorf(pos[0]);
+ int dy = (int)floorf(painter->lastpaintpos[1]) - (int)floorf(pos[1]);
+
+ if ((dx != 0) || (dy != 0)) {
+ brush_painter_imbuf_partial_update(painter, pos, diameter);
+ }
+ }
+
+ BKE_image_pool_free(painter->pool);
+ painter->pool = NULL;
}
/* keep these functions in sync */
static void paint_2d_ibuf_rgb_get(ImBuf *ibuf, int x, int y, float r_rgb[4])
{
- if (ibuf->rect_float) {
- const float *rrgbf = ibuf->rect_float + (ibuf->x * y + x) * 4;
- copy_v4_v4(r_rgb, rrgbf);
- }
- else {
- unsigned char *rrgb = (unsigned char *)ibuf->rect + (ibuf->x * y + x) * 4;
- straight_uchar_to_premul_float(r_rgb, rrgb);
- }
+ if (ibuf->rect_float) {
+ const float *rrgbf = ibuf->rect_float + (ibuf->x * y + x) * 4;
+ copy_v4_v4(r_rgb, rrgbf);
+ }
+ else {
+ unsigned char *rrgb = (unsigned char *)ibuf->rect + (ibuf->x * y + x) * 4;
+ straight_uchar_to_premul_float(r_rgb, rrgb);
+ }
}
-static void paint_2d_ibuf_rgb_set(ImBuf *ibuf, int x, int y, const bool is_torus, const float rgb[4])
+static void paint_2d_ibuf_rgb_set(
+ ImBuf *ibuf, int x, int y, const bool is_torus, const float rgb[4])
{
- if (is_torus) {
- x %= ibuf->x;
- if (x < 0) x += ibuf->x;
- y %= ibuf->y;
- if (y < 0) y += ibuf->y;
- }
-
- if (ibuf->rect_float) {
- float *rrgbf = ibuf->rect_float + (ibuf->x * y + x) * 4;
- float map_alpha = (rgb[3] == 0.0f) ? rrgbf[3] : rrgbf[3] / rgb[3];
-
- mul_v3_v3fl(rrgbf, rgb, map_alpha);
- rrgbf[3] = rgb[3];
- }
- else {
- unsigned char straight[4];
- unsigned char *rrgb = (unsigned char *)ibuf->rect + (ibuf->x * y + x) * 4;
-
- premul_float_to_straight_uchar(straight, rgb);
- rrgb[0] = straight[0];
- rrgb[1] = straight[1];
- rrgb[2] = straight[2];
- rrgb[3] = straight[3];
- }
+ if (is_torus) {
+ x %= ibuf->x;
+ if (x < 0)
+ x += ibuf->x;
+ y %= ibuf->y;
+ if (y < 0)
+ y += ibuf->y;
+ }
+
+ if (ibuf->rect_float) {
+ float *rrgbf = ibuf->rect_float + (ibuf->x * y + x) * 4;
+ float map_alpha = (rgb[3] == 0.0f) ? rrgbf[3] : rrgbf[3] / rgb[3];
+
+ mul_v3_v3fl(rrgbf, rgb, map_alpha);
+ rrgbf[3] = rgb[3];
+ }
+ else {
+ unsigned char straight[4];
+ unsigned char *rrgb = (unsigned char *)ibuf->rect + (ibuf->x * y + x) * 4;
+
+ premul_float_to_straight_uchar(straight, rgb);
+ rrgb[0] = straight[0];
+ rrgb[1] = straight[1];
+ rrgb[2] = straight[2];
+ rrgb[3] = straight[3];
+ }
}
static void paint_2d_ibuf_tile_convert(ImBuf *ibuf, int *x, int *y, short tile)
{
- if (tile & PAINT_TILE_X) {
- *x %= ibuf->x;
- if (*x < 0) *x += ibuf->x;
- }
- if (tile & PAINT_TILE_Y) {
- *y %= ibuf->y;
- if (*y < 0) *y += ibuf->y;
- }
+ if (tile & PAINT_TILE_X) {
+ *x %= ibuf->x;
+ if (*x < 0)
+ *x += ibuf->x;
+ }
+ if (tile & PAINT_TILE_Y) {
+ *y %= ibuf->y;
+ if (*y < 0)
+ *y += ibuf->y;
+ }
}
-
static float paint_2d_ibuf_add_if(ImBuf *ibuf, int x, int y, float *outrgb, short tile, float w)
{
- float inrgb[4];
-
- if (tile) paint_2d_ibuf_tile_convert(ibuf, &x, &y, tile);
- /* need to also do clipping here always since tiled coordinates
- * are not always within bounds */
- if (x < ibuf->x && x >= 0 && y < ibuf->y && y >= 0) {
- paint_2d_ibuf_rgb_get(ibuf, x, y, inrgb);
- }
- else return 0;
-
- mul_v4_fl(inrgb, w);
- add_v4_v4(outrgb, inrgb);
-
- return w;
+ float inrgb[4];
+
+ if (tile)
+ paint_2d_ibuf_tile_convert(ibuf, &x, &y, tile);
+ /* need to also do clipping here always since tiled coordinates
+ * are not always within bounds */
+ if (x < ibuf->x && x >= 0 && y < ibuf->y && y >= 0) {
+ paint_2d_ibuf_rgb_get(ibuf, x, y, inrgb);
+ }
+ else
+ return 0;
+
+ mul_v4_fl(inrgb, w);
+ add_v4_v4(outrgb, inrgb);
+
+ return w;
}
-static void paint_2d_lift_soften(ImagePaintState *s, ImBuf *ibuf, ImBuf *ibufb, int *pos, const short tile)
+static void paint_2d_lift_soften(
+ ImagePaintState *s, ImBuf *ibuf, ImBuf *ibufb, int *pos, const short tile)
{
- bool sharpen = (s->painter->cache.invert ^ ((s->brush->flag & BRUSH_DIR_IN) != 0));
- float threshold = s->brush->sharp_threshold;
- int x, y, xi, yi, xo, yo, xk, yk;
- float count;
- int out_off[2], in_off[2], dim[2];
- int diff_pos[2];
- float outrgb[4];
- float rgba[4];
- BlurKernel *kernel = s->blurkernel;
-
- dim[0] = ibufb->x;
- dim[1] = ibufb->y;
- in_off[0] = pos[0];
- in_off[1] = pos[1];
- out_off[0] = out_off[1] = 0;
-
- if (!tile) {
- IMB_rectclip(
- ibuf, ibufb, &in_off[0], &in_off[1], &out_off[0],
- &out_off[1], &dim[0], &dim[1]);
-
- if ((dim[0] == 0) || (dim[1] == 0))
- return;
- }
-
- /* find offset inside mask buffers to sample them */
- sub_v2_v2v2_int(diff_pos, out_off, in_off);
-
- for (y = 0; y < dim[1]; y++) {
- for (x = 0; x < dim[0]; x++) {
- /* get input pixel */
- xi = in_off[0] + x;
- yi = in_off[1] + y;
-
- count = 0.0;
- if (tile) {
- paint_2d_ibuf_tile_convert(ibuf, &xi, &yi, tile);
- if (xi < ibuf->x && xi >= 0 && yi < ibuf->y && yi >= 0)
- paint_2d_ibuf_rgb_get(ibuf, xi, yi, rgba);
- else
- zero_v4(rgba);
- }
- else {
- /* coordinates have been clipped properly here, it should be safe to do this */
- paint_2d_ibuf_rgb_get(ibuf, xi, yi, rgba);
- }
- zero_v4(outrgb);
-
- for (yk = 0; yk < kernel->side; yk++) {
- for (xk = 0; xk < kernel->side; xk++) {
- count += paint_2d_ibuf_add_if(
- ibuf, xi + xk - kernel->pixel_len,
- yi + yk - kernel->pixel_len, outrgb, tile,
- kernel->wdata[xk + yk * kernel->side]);
- }
- }
-
- if (count > 0.0f) {
- mul_v4_fl(outrgb, 1.0f / (float)count);
-
- if (sharpen) {
- /* subtract blurred image from normal image gives high pass filter */
- sub_v3_v3v3(outrgb, rgba, outrgb);
-
- /* now rgba_ub contains the edge result, but this should be converted to luminance to avoid
- * colored speckles appearing in final image, and also to check for threshold */
- outrgb[0] = outrgb[1] = outrgb[2] = IMB_colormanagement_get_luminance(outrgb);
- if (fabsf(outrgb[0]) > threshold) {
- float mask = BKE_brush_alpha_get(s->scene, s->brush);
- float alpha = rgba[3];
- rgba[3] = outrgb[3] = mask;
-
- /* add to enhance edges */
- blend_color_add_float(outrgb, rgba, outrgb);
- outrgb[3] = alpha;
- }
- else
- copy_v4_v4(outrgb, rgba);
- }
- }
- else
- copy_v4_v4(outrgb, rgba);
- /* write into brush buffer */
- xo = out_off[0] + x;
- yo = out_off[1] + y;
- paint_2d_ibuf_rgb_set(ibufb, xo, yo, 0, outrgb);
- }
- }
+ bool sharpen = (s->painter->cache.invert ^ ((s->brush->flag & BRUSH_DIR_IN) != 0));
+ float threshold = s->brush->sharp_threshold;
+ int x, y, xi, yi, xo, yo, xk, yk;
+ float count;
+ int out_off[2], in_off[2], dim[2];
+ int diff_pos[2];
+ float outrgb[4];
+ float rgba[4];
+ BlurKernel *kernel = s->blurkernel;
+
+ dim[0] = ibufb->x;
+ dim[1] = ibufb->y;
+ in_off[0] = pos[0];
+ in_off[1] = pos[1];
+ out_off[0] = out_off[1] = 0;
+
+ if (!tile) {
+ IMB_rectclip(ibuf, ibufb, &in_off[0], &in_off[1], &out_off[0], &out_off[1], &dim[0], &dim[1]);
+
+ if ((dim[0] == 0) || (dim[1] == 0))
+ return;
+ }
+
+ /* find offset inside mask buffers to sample them */
+ sub_v2_v2v2_int(diff_pos, out_off, in_off);
+
+ for (y = 0; y < dim[1]; y++) {
+ for (x = 0; x < dim[0]; x++) {
+ /* get input pixel */
+ xi = in_off[0] + x;
+ yi = in_off[1] + y;
+
+ count = 0.0;
+ if (tile) {
+ paint_2d_ibuf_tile_convert(ibuf, &xi, &yi, tile);
+ if (xi < ibuf->x && xi >= 0 && yi < ibuf->y && yi >= 0)
+ paint_2d_ibuf_rgb_get(ibuf, xi, yi, rgba);
+ else
+ zero_v4(rgba);
+ }
+ else {
+ /* coordinates have been clipped properly here, it should be safe to do this */
+ paint_2d_ibuf_rgb_get(ibuf, xi, yi, rgba);
+ }
+ zero_v4(outrgb);
+
+ for (yk = 0; yk < kernel->side; yk++) {
+ for (xk = 0; xk < kernel->side; xk++) {
+ count += paint_2d_ibuf_add_if(ibuf,
+ xi + xk - kernel->pixel_len,
+ yi + yk - kernel->pixel_len,
+ outrgb,
+ tile,
+ kernel->wdata[xk + yk * kernel->side]);
+ }
+ }
+
+ if (count > 0.0f) {
+ mul_v4_fl(outrgb, 1.0f / (float)count);
+
+ if (sharpen) {
+ /* subtract blurred image from normal image gives high pass filter */
+ sub_v3_v3v3(outrgb, rgba, outrgb);
+
+ /* now rgba_ub contains the edge result, but this should be converted to luminance to avoid
+ * colored speckles appearing in final image, and also to check for threshold */
+ outrgb[0] = outrgb[1] = outrgb[2] = IMB_colormanagement_get_luminance(outrgb);
+ if (fabsf(outrgb[0]) > threshold) {
+ float mask = BKE_brush_alpha_get(s->scene, s->brush);
+ float alpha = rgba[3];
+ rgba[3] = outrgb[3] = mask;
+
+ /* add to enhance edges */
+ blend_color_add_float(outrgb, rgba, outrgb);
+ outrgb[3] = alpha;
+ }
+ else
+ copy_v4_v4(outrgb, rgba);
+ }
+ }
+ else
+ copy_v4_v4(outrgb, rgba);
+ /* write into brush buffer */
+ xo = out_off[0] + x;
+ yo = out_off[1] + y;
+ paint_2d_ibuf_rgb_set(ibufb, xo, yo, 0, outrgb);
+ }
+ }
}
-static void paint_2d_set_region(ImagePaintRegion *region, int destx, int desty, int srcx, int srcy, int width, int height)
+static void paint_2d_set_region(
+ ImagePaintRegion *region, int destx, int desty, int srcx, int srcy, int width, int height)
{
- region->destx = destx;
- region->desty = desty;
- region->srcx = srcx;
- region->srcy = srcy;
- region->width = width;
- region->height = height;
+ region->destx = destx;
+ region->desty = desty;
+ region->srcx = srcx;
+ region->srcy = srcy;
+ region->width = width;
+ region->height = height;
}
-static int paint_2d_torus_split_region(ImagePaintRegion region[4], ImBuf *dbuf, ImBuf *sbuf, short tile)
+static int paint_2d_torus_split_region(ImagePaintRegion region[4],
+ ImBuf *dbuf,
+ ImBuf *sbuf,
+ short tile)
{
- int destx = region->destx;
- int desty = region->desty;
- int srcx = region->srcx;
- int srcy = region->srcy;
- int width = region->width;
- int height = region->height;
- int origw, origh, w, h, tot = 0;
-
- /* convert destination and source coordinates to be within image */
- if (tile & PAINT_TILE_X) {
- destx = destx % dbuf->x;
- if (destx < 0) destx += dbuf->x;
- srcx = srcx % sbuf->x;
- if (srcx < 0) srcx += sbuf->x;
- }
- if (tile & PAINT_TILE_Y) {
- desty = desty % dbuf->y;
- if (desty < 0) desty += dbuf->y;
- srcy = srcy % sbuf->y;
- if (srcy < 0) srcy += sbuf->y;
- }
- /* clip width of blending area to destination imbuf, to avoid writing the
- * same pixel twice */
- origw = w = (width > dbuf->x) ? dbuf->x : width;
- origh = h = (height > dbuf->y) ? dbuf->y : height;
-
- /* clip within image */
- IMB_rectclip(dbuf, sbuf, &destx, &desty, &srcx, &srcy, &w, &h);
- paint_2d_set_region(&region[tot++], destx, desty, srcx, srcy, w, h);
-
- /* do 3 other rects if needed */
- if ((tile & PAINT_TILE_X) && w < origw)
- paint_2d_set_region(&region[tot++], (destx + w) % dbuf->x, desty, (srcx + w) % sbuf->x, srcy, origw - w, h);
- if ((tile & PAINT_TILE_Y) && h < origh)
- paint_2d_set_region(&region[tot++], destx, (desty + h) % dbuf->y, srcx, (srcy + h) % sbuf->y, w, origh - h);
- if ((tile & PAINT_TILE_X) && (tile & PAINT_TILE_Y) && (w < origw) && (h < origh))
- paint_2d_set_region(&region[tot++], (destx + w) % dbuf->x, (desty + h) % dbuf->y, (srcx + w) % sbuf->x, (srcy + h) % sbuf->y, origw - w, origh - h);
-
- return tot;
+ int destx = region->destx;
+ int desty = region->desty;
+ int srcx = region->srcx;
+ int srcy = region->srcy;
+ int width = region->width;
+ int height = region->height;
+ int origw, origh, w, h, tot = 0;
+
+ /* convert destination and source coordinates to be within image */
+ if (tile & PAINT_TILE_X) {
+ destx = destx % dbuf->x;
+ if (destx < 0)
+ destx += dbuf->x;
+ srcx = srcx % sbuf->x;
+ if (srcx < 0)
+ srcx += sbuf->x;
+ }
+ if (tile & PAINT_TILE_Y) {
+ desty = desty % dbuf->y;
+ if (desty < 0)
+ desty += dbuf->y;
+ srcy = srcy % sbuf->y;
+ if (srcy < 0)
+ srcy += sbuf->y;
+ }
+ /* clip width of blending area to destination imbuf, to avoid writing the
+ * same pixel twice */
+ origw = w = (width > dbuf->x) ? dbuf->x : width;
+ origh = h = (height > dbuf->y) ? dbuf->y : height;
+
+ /* clip within image */
+ IMB_rectclip(dbuf, sbuf, &destx, &desty, &srcx, &srcy, &w, &h);
+ paint_2d_set_region(&region[tot++], destx, desty, srcx, srcy, w, h);
+
+ /* do 3 other rects if needed */
+ if ((tile & PAINT_TILE_X) && w < origw)
+ paint_2d_set_region(
+ &region[tot++], (destx + w) % dbuf->x, desty, (srcx + w) % sbuf->x, srcy, origw - w, h);
+ if ((tile & PAINT_TILE_Y) && h < origh)
+ paint_2d_set_region(
+ &region[tot++], destx, (desty + h) % dbuf->y, srcx, (srcy + h) % sbuf->y, w, origh - h);
+ if ((tile & PAINT_TILE_X) && (tile & PAINT_TILE_Y) && (w < origw) && (h < origh))
+ paint_2d_set_region(&region[tot++],
+ (destx + w) % dbuf->x,
+ (desty + h) % dbuf->y,
+ (srcx + w) % sbuf->x,
+ (srcy + h) % sbuf->y,
+ origw - w,
+ origh - h);
+
+ return tot;
}
static void paint_2d_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos, short tile)
{
- ImagePaintRegion region[4];
- int a, tot;
-
- paint_2d_set_region(region, 0, 0, pos[0], pos[1], ibufb->x, ibufb->y);
- tot = paint_2d_torus_split_region(region, ibufb, ibuf, tile);
-
- for (a = 0; a < tot; a++)
- IMB_rectblend(
- ibufb, ibufb, ibuf, NULL, NULL, NULL, 0, region[a].destx, region[a].desty,
- region[a].destx, region[a].desty,
- region[a].srcx, region[a].srcy,
- region[a].width, region[a].height, IMB_BLEND_COPY, false);
+ ImagePaintRegion region[4];
+ int a, tot;
+
+ paint_2d_set_region(region, 0, 0, pos[0], pos[1], ibufb->x, ibufb->y);
+ tot = paint_2d_torus_split_region(region, ibufb, ibuf, tile);
+
+ for (a = 0; a < tot; a++)
+ IMB_rectblend(ibufb,
+ ibufb,
+ ibuf,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ region[a].destx,
+ region[a].desty,
+ region[a].destx,
+ region[a].desty,
+ region[a].srcx,
+ region[a].srcy,
+ region[a].width,
+ region[a].height,
+ IMB_BLEND_COPY,
+ false);
}
static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos)
{
- /* note: allocImbuf returns zero'd memory, so regions outside image will
- * have zero alpha, and hence not be blended onto the image */
- int w = ibufb->x, h = ibufb->y, destx = 0, desty = 0, srcx = pos[0], srcy = pos[1];
- ImBuf *clonebuf = IMB_allocImBuf(w, h, ibufb->planes, ibufb->flags);
-
- IMB_rectclip(clonebuf, ibuf, &destx, &desty, &srcx, &srcy, &w, &h);
- IMB_rectblend(
- clonebuf, clonebuf, ibufb, NULL, NULL, NULL, 0, destx, desty, destx, desty, destx, desty, w, h,
- IMB_BLEND_COPY_ALPHA, false);
- IMB_rectblend(
- clonebuf, clonebuf, ibuf, NULL, NULL, NULL, 0, destx, desty, destx, desty, srcx, srcy, w, h,
- IMB_BLEND_COPY_RGB, false);
-
- return clonebuf;
+ /* note: allocImbuf returns zero'd memory, so regions outside image will
+ * have zero alpha, and hence not be blended onto the image */
+ int w = ibufb->x, h = ibufb->y, destx = 0, desty = 0, srcx = pos[0], srcy = pos[1];
+ ImBuf *clonebuf = IMB_allocImBuf(w, h, ibufb->planes, ibufb->flags);
+
+ IMB_rectclip(clonebuf, ibuf, &destx, &desty, &srcx, &srcy, &w, &h);
+ IMB_rectblend(clonebuf,
+ clonebuf,
+ ibufb,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ destx,
+ desty,
+ destx,
+ desty,
+ destx,
+ desty,
+ w,
+ h,
+ IMB_BLEND_COPY_ALPHA,
+ false);
+ IMB_rectblend(clonebuf,
+ clonebuf,
+ ibuf,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ destx,
+ desty,
+ destx,
+ desty,
+ srcx,
+ srcy,
+ w,
+ h,
+ IMB_BLEND_COPY_RGB,
+ false);
+
+ return clonebuf;
}
static void paint_2d_convert_brushco(ImBuf *ibufb, const float pos[2], int ipos[2])
{
- ipos[0] = (int)floorf((pos[0] - ibufb->x / 2));
- ipos[1] = (int)floorf((pos[1] - ibufb->y / 2));
+ ipos[0] = (int)floorf((pos[0] - ibufb->x / 2));
+ ipos[1] = (int)floorf((pos[1] - ibufb->y / 2));
}
-static void paint_2d_do_making_brush(
- ImagePaintState *s,
- ImagePaintRegion *region,
- unsigned short *curveb,
- unsigned short *texmaskb,
- ImBuf *frombuf,
- float mask_max,
- short blend,
- int tilex, int tiley,
- int tilew, int tileh)
+static void paint_2d_do_making_brush(ImagePaintState *s,
+ ImagePaintRegion *region,
+ unsigned short *curveb,
+ unsigned short *texmaskb,
+ ImBuf *frombuf,
+ float mask_max,
+ short blend,
+ int tilex,
+ int tiley,
+ int tilew,
+ int tileh)
{
- ImBuf tmpbuf;
- IMB_initImBuf(&tmpbuf, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, 0);
-
- ListBase *undo_tiles = ED_image_undo_get_tiles();
-
- for (int ty = tiley; ty <= tileh; ty++) {
- for (int tx = tilex; tx <= tilew; tx++) {
- /* retrieve original pixels + mask from undo buffer */
- unsigned short *mask;
- int origx = region->destx - tx * IMAPAINT_TILE_SIZE;
- int origy = region->desty - ty * IMAPAINT_TILE_SIZE;
-
- if (s->canvas->rect_float)
- tmpbuf.rect_float = image_undo_find_tile(undo_tiles, s->image, s->canvas, tx, ty, &mask, false);
- else
- tmpbuf.rect = image_undo_find_tile(undo_tiles, s->image, s->canvas, tx, ty, &mask, false);
-
- IMB_rectblend(
- s->canvas, &tmpbuf, frombuf, mask,
- curveb, texmaskb, mask_max,
- region->destx, region->desty,
- origx, origy,
- region->srcx, region->srcy,
- region->width, region->height,
- blend, ((s->brush->flag & BRUSH_ACCUMULATE) != 0));
- }
- }
+ ImBuf tmpbuf;
+ IMB_initImBuf(&tmpbuf, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, 0);
+
+ ListBase *undo_tiles = ED_image_undo_get_tiles();
+
+ for (int ty = tiley; ty <= tileh; ty++) {
+ for (int tx = tilex; tx <= tilew; tx++) {
+ /* retrieve original pixels + mask from undo buffer */
+ unsigned short *mask;
+ int origx = region->destx - tx * IMAPAINT_TILE_SIZE;
+ int origy = region->desty - ty * IMAPAINT_TILE_SIZE;
+
+ if (s->canvas->rect_float)
+ tmpbuf.rect_float = image_undo_find_tile(
+ undo_tiles, s->image, s->canvas, tx, ty, &mask, false);
+ else
+ tmpbuf.rect = image_undo_find_tile(undo_tiles, s->image, s->canvas, tx, ty, &mask, false);
+
+ IMB_rectblend(s->canvas,
+ &tmpbuf,
+ frombuf,
+ mask,
+ curveb,
+ texmaskb,
+ mask_max,
+ region->destx,
+ region->desty,
+ origx,
+ origy,
+ region->srcx,
+ region->srcy,
+ region->width,
+ region->height,
+ blend,
+ ((s->brush->flag & BRUSH_ACCUMULATE) != 0));
+ }
+ }
}
typedef struct Paint2DForeachData {
- ImagePaintState *s;
- ImagePaintRegion *region;
- unsigned short *curveb;
- unsigned short *texmaskb;
- ImBuf *frombuf;
- float mask_max;
- short blend;
- int tilex;
- int tilew;
+ ImagePaintState *s;
+ ImagePaintRegion *region;
+ unsigned short *curveb;
+ unsigned short *texmaskb;
+ ImBuf *frombuf;
+ float mask_max;
+ short blend;
+ int tilex;
+ int tilew;
} Paint2DForeachData;
-static void paint_2d_op_foreach_do(
- void *__restrict data_v,
- const int iter,
- const ParallelRangeTLS *__restrict UNUSED(tls))
+static void paint_2d_op_foreach_do(void *__restrict data_v,
+ const int iter,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
{
- Paint2DForeachData *data = (Paint2DForeachData *)data_v;
- paint_2d_do_making_brush(
- data->s, data->region, data->curveb,
- data->texmaskb, data->frombuf, data->mask_max,
- data->blend,
- data->tilex, iter,
- data->tilew, iter);
+ Paint2DForeachData *data = (Paint2DForeachData *)data_v;
+ paint_2d_do_making_brush(data->s,
+ data->region,
+ data->curveb,
+ data->texmaskb,
+ data->frombuf,
+ data->mask_max,
+ data->blend,
+ data->tilex,
+ iter,
+ data->tilew,
+ iter);
}
-static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsigned short *texmaskb, const float lastpos[2], const float pos[2])
+static int paint_2d_op(void *state,
+ ImBuf *ibufb,
+ unsigned short *curveb,
+ unsigned short *texmaskb,
+ const float lastpos[2],
+ const float pos[2])
{
- ImagePaintState *s = ((ImagePaintState *)state);
- ImBuf *clonebuf = NULL, *frombuf;
- ImagePaintRegion region[4];
- short tile = s->symmetry & (PAINT_TILE_X | PAINT_TILE_Y);
- short blend = s->blend;
- const float *offset = s->brush->clone.offset;
- float liftpos[2];
- float mask_max = BKE_brush_alpha_get(s->scene, s->brush);
- int bpos[2], blastpos[2], bliftpos[2];
- int a, tot;
-
- paint_2d_convert_brushco(ibufb, pos, bpos);
-
- /* lift from canvas */
- if (s->tool == PAINT_TOOL_SOFTEN) {
- paint_2d_lift_soften(s, s->canvas, ibufb, bpos, tile);
- blend = IMB_BLEND_INTERPOLATE;
- }
- else if (s->tool == PAINT_TOOL_SMEAR) {
- if (lastpos[0] == pos[0] && lastpos[1] == pos[1])
- return 0;
-
- paint_2d_convert_brushco(ibufb, lastpos, blastpos);
- paint_2d_lift_smear(s->canvas, ibufb, blastpos, tile);
- blend = IMB_BLEND_INTERPOLATE;
- }
- else if (s->tool == PAINT_TOOL_CLONE && s->clonecanvas) {
- liftpos[0] = pos[0] - offset[0] * s->canvas->x;
- liftpos[1] = pos[1] - offset[1] * s->canvas->y;
-
- paint_2d_convert_brushco(ibufb, liftpos, bliftpos);
- clonebuf = paint_2d_lift_clone(s->clonecanvas, ibufb, bliftpos);
- }
-
- frombuf = (clonebuf) ? clonebuf : ibufb;
-
- if (tile) {
- paint_2d_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
- tot = paint_2d_torus_split_region(region, s->canvas, frombuf, tile);
- }
- else {
- paint_2d_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
- tot = 1;
- }
-
- /* blend into canvas */
- for (a = 0; a < tot; a++) {
- ED_imapaint_dirty_region(
- s->image, s->canvas,
- region[a].destx, region[a].desty,
- region[a].width, region[a].height, true);
-
- if (s->do_masking) {
- /* masking, find original pixels tiles from undo buffer to composite over */
- int tilex, tiley, tilew, tileh;
-
- imapaint_region_tiles(
- s->canvas, region[a].destx, region[a].desty,
- region[a].width, region[a].height,
- &tilex, &tiley, &tilew, &tileh);
-
- if (tiley == tileh) {
- paint_2d_do_making_brush(
- s, &region[a], curveb, texmaskb, frombuf,
- mask_max, blend, tilex, tiley, tilew, tileh);
- }
- else {
- Paint2DForeachData data;
- data.s = s;
- data.region = &region[a];
- data.curveb = curveb;
- data.texmaskb = texmaskb;
- data.frombuf = frombuf;
- data.mask_max = mask_max;
- data.blend = blend;
- data.tilex = tilex;
- data.tilew = tilew;
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- BLI_task_parallel_range(
- tiley, tileh + 1, &data,
- paint_2d_op_foreach_do,
- &settings);
-
- }
- }
- else {
- /* no masking, composite brush directly onto canvas */
- IMB_rectblend_threaded(
- s->canvas, s->canvas, frombuf, NULL, curveb, texmaskb, mask_max,
- region[a].destx, region[a].desty,
- region[a].destx, region[a].desty,
- region[a].srcx, region[a].srcy,
- region[a].width, region[a].height, blend, false);
- }
- }
-
- if (clonebuf) IMB_freeImBuf(clonebuf);
-
- return 1;
+ ImagePaintState *s = ((ImagePaintState *)state);
+ ImBuf *clonebuf = NULL, *frombuf;
+ ImagePaintRegion region[4];
+ short tile = s->symmetry & (PAINT_TILE_X | PAINT_TILE_Y);
+ short blend = s->blend;
+ const float *offset = s->brush->clone.offset;
+ float liftpos[2];
+ float mask_max = BKE_brush_alpha_get(s->scene, s->brush);
+ int bpos[2], blastpos[2], bliftpos[2];
+ int a, tot;
+
+ paint_2d_convert_brushco(ibufb, pos, bpos);
+
+ /* lift from canvas */
+ if (s->tool == PAINT_TOOL_SOFTEN) {
+ paint_2d_lift_soften(s, s->canvas, ibufb, bpos, tile);
+ blend = IMB_BLEND_INTERPOLATE;
+ }
+ else if (s->tool == PAINT_TOOL_SMEAR) {
+ if (lastpos[0] == pos[0] && lastpos[1] == pos[1])
+ return 0;
+
+ paint_2d_convert_brushco(ibufb, lastpos, blastpos);
+ paint_2d_lift_smear(s->canvas, ibufb, blastpos, tile);
+ blend = IMB_BLEND_INTERPOLATE;
+ }
+ else if (s->tool == PAINT_TOOL_CLONE && s->clonecanvas) {
+ liftpos[0] = pos[0] - offset[0] * s->canvas->x;
+ liftpos[1] = pos[1] - offset[1] * s->canvas->y;
+
+ paint_2d_convert_brushco(ibufb, liftpos, bliftpos);
+ clonebuf = paint_2d_lift_clone(s->clonecanvas, ibufb, bliftpos);
+ }
+
+ frombuf = (clonebuf) ? clonebuf : ibufb;
+
+ if (tile) {
+ paint_2d_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
+ tot = paint_2d_torus_split_region(region, s->canvas, frombuf, tile);
+ }
+ else {
+ paint_2d_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
+ tot = 1;
+ }
+
+ /* blend into canvas */
+ for (a = 0; a < tot; a++) {
+ ED_imapaint_dirty_region(s->image,
+ s->canvas,
+ region[a].destx,
+ region[a].desty,
+ region[a].width,
+ region[a].height,
+ true);
+
+ if (s->do_masking) {
+ /* masking, find original pixels tiles from undo buffer to composite over */
+ int tilex, tiley, tilew, tileh;
+
+ imapaint_region_tiles(s->canvas,
+ region[a].destx,
+ region[a].desty,
+ region[a].width,
+ region[a].height,
+ &tilex,
+ &tiley,
+ &tilew,
+ &tileh);
+
+ if (tiley == tileh) {
+ paint_2d_do_making_brush(
+ s, &region[a], curveb, texmaskb, frombuf, mask_max, blend, tilex, tiley, tilew, tileh);
+ }
+ else {
+ Paint2DForeachData data;
+ data.s = s;
+ data.region = &region[a];
+ data.curveb = curveb;
+ data.texmaskb = texmaskb;
+ data.frombuf = frombuf;
+ data.mask_max = mask_max;
+ data.blend = blend;
+ data.tilex = tilex;
+ data.tilew = tilew;
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ BLI_task_parallel_range(tiley, tileh + 1, &data, paint_2d_op_foreach_do, &settings);
+ }
+ }
+ else {
+ /* no masking, composite brush directly onto canvas */
+ IMB_rectblend_threaded(s->canvas,
+ s->canvas,
+ frombuf,
+ NULL,
+ curveb,
+ texmaskb,
+ mask_max,
+ region[a].destx,
+ region[a].desty,
+ region[a].destx,
+ region[a].desty,
+ region[a].srcx,
+ region[a].srcy,
+ region[a].width,
+ region[a].height,
+ blend,
+ false);
+ }
+ }
+
+ if (clonebuf)
+ IMB_freeImBuf(clonebuf);
+
+ return 1;
}
-
static int paint_2d_canvas_set(ImagePaintState *s, Image *ima)
{
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL);
-
- /* verify that we can paint and set canvas */
- if (ima == NULL) {
- return 0;
- }
- else if (BKE_image_has_packedfile(ima) && ima->rr) {
- s->warnpackedfile = ima->id.name + 2;
- return 0;
- }
- else if (ibuf && ibuf->channels != 4) {
- s->warnmultifile = ima->id.name + 2;
- return 0;
- }
- else if (!ibuf || !(ibuf->rect || ibuf->rect_float))
- return 0;
-
- s->image = ima;
- s->canvas = ibuf;
-
- /* set clone canvas */
- if (s->tool == PAINT_TOOL_CLONE) {
- ima = s->brush->clone.image;
- ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL);
-
- if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- BKE_image_release_ibuf(s->image, s->canvas, NULL);
- return 0;
- }
-
- s->clonecanvas = ibuf;
-
- /* temporarily add float rect for cloning */
- if (s->canvas->rect_float && !s->clonecanvas->rect_float) {
- IMB_float_from_rect(s->clonecanvas);
- }
- else if (!s->canvas->rect_float && !s->clonecanvas->rect)
- IMB_rect_from_float(s->clonecanvas);
- }
-
- /* set masking */
- s->do_masking = paint_use_opacity_masking(s->brush);
-
- return 1;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL);
+
+ /* verify that we can paint and set canvas */
+ if (ima == NULL) {
+ return 0;
+ }
+ else if (BKE_image_has_packedfile(ima) && ima->rr) {
+ s->warnpackedfile = ima->id.name + 2;
+ return 0;
+ }
+ else if (ibuf && ibuf->channels != 4) {
+ s->warnmultifile = ima->id.name + 2;
+ return 0;
+ }
+ else if (!ibuf || !(ibuf->rect || ibuf->rect_float))
+ return 0;
+
+ s->image = ima;
+ s->canvas = ibuf;
+
+ /* set clone canvas */
+ if (s->tool == PAINT_TOOL_CLONE) {
+ ima = s->brush->clone.image;
+ ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL);
+
+ if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_release_ibuf(s->image, s->canvas, NULL);
+ return 0;
+ }
+
+ s->clonecanvas = ibuf;
+
+ /* temporarily add float rect for cloning */
+ if (s->canvas->rect_float && !s->clonecanvas->rect_float) {
+ IMB_float_from_rect(s->clonecanvas);
+ }
+ else if (!s->canvas->rect_float && !s->clonecanvas->rect)
+ IMB_rect_from_float(s->clonecanvas);
+ }
+
+ /* set masking */
+ s->do_masking = paint_use_opacity_masking(s->brush);
+
+ return 1;
}
static void paint_2d_canvas_free(ImagePaintState *s)
{
- BKE_image_release_ibuf(s->image, s->canvas, NULL);
- BKE_image_release_ibuf(s->brush->clone.image, s->clonecanvas, NULL);
+ BKE_image_release_ibuf(s->image, s->canvas, NULL);
+ BKE_image_release_ibuf(s->brush->clone.image, s->clonecanvas, NULL);
- if (s->blurkernel) {
- paint_delete_blur_kernel(s->blurkernel);
- MEM_freeN(s->blurkernel);
- }
+ if (s->blurkernel) {
+ paint_delete_blur_kernel(s->blurkernel);
+ MEM_freeN(s->blurkernel);
+ }
- image_undo_remove_masks();
+ image_undo_remove_masks();
}
-void paint_2d_stroke(void *ps, const float prev_mval[2], const float mval[2], const bool eraser, float pressure, float distance, float size)
+void paint_2d_stroke(void *ps,
+ const float prev_mval[2],
+ const float mval[2],
+ const bool eraser,
+ float pressure,
+ float distance,
+ float size)
{
- float newuv[2], olduv[2];
- ImagePaintState *s = ps;
- BrushPainter *painter = s->painter;
- ImBuf *ibuf = BKE_image_acquire_ibuf(s->image, s->sima ? &s->sima->iuser : NULL, NULL);
- const bool is_data = (ibuf && ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA);
+ float newuv[2], olduv[2];
+ ImagePaintState *s = ps;
+ BrushPainter *painter = s->painter;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(s->image, s->sima ? &s->sima->iuser : NULL, NULL);
+ const bool is_data = (ibuf && ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA);
- if (!ibuf)
- return;
+ if (!ibuf)
+ return;
- s->blend = s->brush->blend;
- if (eraser)
- s->blend = IMB_BLEND_ERASE_ALPHA;
+ s->blend = s->brush->blend;
+ if (eraser)
+ s->blend = IMB_BLEND_ERASE_ALPHA;
- UI_view2d_region_to_view(s->v2d, mval[0], mval[1], &newuv[0], &newuv[1]);
- UI_view2d_region_to_view(s->v2d, prev_mval[0], prev_mval[1], &olduv[0], &olduv[1]);
+ UI_view2d_region_to_view(s->v2d, mval[0], mval[1], &newuv[0], &newuv[1]);
+ UI_view2d_region_to_view(s->v2d, prev_mval[0], prev_mval[1], &olduv[0], &olduv[1]);
- newuv[0] *= ibuf->x;
- newuv[1] *= ibuf->y;
+ newuv[0] *= ibuf->x;
+ newuv[1] *= ibuf->y;
- olduv[0] *= ibuf->x;
- olduv[1] *= ibuf->y;
+ olduv[0] *= ibuf->x;
+ olduv[1] *= ibuf->y;
- if (painter->firsttouch) {
- float startuv[2];
+ if (painter->firsttouch) {
+ float startuv[2];
- UI_view2d_region_to_view(s->v2d, 0, 0, &startuv[0], &startuv[1]);
+ UI_view2d_region_to_view(s->v2d, 0, 0, &startuv[0], &startuv[1]);
- /* paint exactly once on first touch */
- painter->startpaintpos[0] = startuv[0] * ibuf->x;
- painter->startpaintpos[1] = startuv[1] * ibuf->y;
+ /* paint exactly once on first touch */
+ painter->startpaintpos[0] = startuv[0] * ibuf->x;
+ painter->startpaintpos[1] = startuv[1] * ibuf->y;
- painter->firsttouch = 0;
- copy_v2_v2(painter->lastpaintpos, newuv);
- }
- else {
- copy_v2_v2(painter->lastpaintpos, olduv);
- }
+ painter->firsttouch = 0;
+ copy_v2_v2(painter->lastpaintpos, newuv);
+ }
+ else {
+ copy_v2_v2(painter->lastpaintpos, olduv);
+ }
- /* 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
- */
- brush_painter_2d_require_imbuf(painter, (ibuf->rect_float != NULL), !is_data);
+ /* 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
+ */
+ brush_painter_2d_require_imbuf(painter, (ibuf->rect_float != NULL), !is_data);
- brush_painter_2d_refresh_cache(s, painter, newuv, mval, pressure, distance, size);
+ brush_painter_2d_refresh_cache(s, painter, newuv, mval, pressure, distance, size);
- if (paint_2d_op(s, painter->cache.ibuf, painter->cache.curve_mask, painter->cache.tex_mask, olduv, newuv))
- s->need_redraw = true;
+ if (paint_2d_op(s,
+ painter->cache.ibuf,
+ painter->cache.curve_mask,
+ painter->cache.tex_mask,
+ olduv,
+ newuv))
+ s->need_redraw = true;
- BKE_image_release_ibuf(s->image, ibuf, NULL);
+ BKE_image_release_ibuf(s->image, ibuf, NULL);
}
void *paint_2d_new_stroke(bContext *C, wmOperator *op, int mode)
{
- Scene *scene = CTX_data_scene(C);
- ToolSettings *settings = scene->toolsettings;
- Brush *brush = BKE_paint_brush(&settings->imapaint.paint);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *settings = scene->toolsettings;
+ Brush *brush = BKE_paint_brush(&settings->imapaint.paint);
- ImagePaintState *s = MEM_callocN(sizeof(ImagePaintState), "ImagePaintState");
+ ImagePaintState *s = MEM_callocN(sizeof(ImagePaintState), "ImagePaintState");
- s->sima = CTX_wm_space_image(C);
- s->v2d = &CTX_wm_region(C)->v2d;
- s->scene = scene;
- s->screen = CTX_wm_screen(C);
+ s->sima = CTX_wm_space_image(C);
+ s->v2d = &CTX_wm_region(C)->v2d;
+ s->scene = scene;
+ s->screen = CTX_wm_screen(C);
- s->brush = brush;
- s->tool = brush->imagepaint_tool;
- s->blend = brush->blend;
+ s->brush = brush;
+ s->tool = brush->imagepaint_tool;
+ s->blend = brush->blend;
- s->image = s->sima->image;
- s->symmetry = settings->imapaint.paint.symmetry_flags;
+ s->image = s->sima->image;
+ s->symmetry = settings->imapaint.paint.symmetry_flags;
- if (!paint_2d_canvas_set(s, s->image)) {
- if (s->warnmultifile)
- BKE_report(op->reports, RPT_WARNING, "Image requires 4 color channels to paint");
- if (s->warnpackedfile)
- BKE_report(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted");
+ if (!paint_2d_canvas_set(s, s->image)) {
+ if (s->warnmultifile)
+ BKE_report(op->reports, RPT_WARNING, "Image requires 4 color channels to paint");
+ if (s->warnpackedfile)
+ BKE_report(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted");
- MEM_freeN(s);
- return NULL;
- }
+ MEM_freeN(s);
+ return NULL;
+ }
- if (brush->imagepaint_tool == PAINT_TOOL_SOFTEN) {
- s->blurkernel = paint_new_blur_kernel(brush, false);
- }
+ if (brush->imagepaint_tool == PAINT_TOOL_SOFTEN) {
+ s->blurkernel = paint_new_blur_kernel(brush, false);
+ }
- paint_brush_init_tex(s->brush);
+ paint_brush_init_tex(s->brush);
- /* create painter */
- s->painter = brush_painter_2d_new(scene, s->brush, mode == BRUSH_STROKE_INVERT);
+ /* create painter */
+ s->painter = brush_painter_2d_new(scene, s->brush, mode == BRUSH_STROKE_INVERT);
- return s;
+ return s;
}
void paint_2d_redraw(const bContext *C, void *ps, bool final)
{
- ImagePaintState *s = ps;
-
- if (s->need_redraw) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(s->image, s->sima ? &s->sima->iuser : NULL, NULL);
-
- imapaint_image_update(s->sima, s->image, ibuf, false);
- ED_imapaint_clear_partial_redraw();
-
- BKE_image_release_ibuf(s->image, ibuf, NULL);
-
- s->need_redraw = false;
- }
- else if (!final) {
- return;
- }
-
- if (final) {
- if (s->image && !(s->sima && s->sima->lock))
- GPU_free_image(s->image);
-
- /* compositor listener deals with updating */
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, s->image);
- DEG_id_tag_update(&s->image->id, 0);
- }
- else {
- if (!s->sima || !s->sima->lock)
- ED_region_tag_redraw(CTX_wm_region(C));
- else
- WM_event_add_notifier(C, NC_IMAGE | NA_PAINTING, s->image);
- }
+ ImagePaintState *s = ps;
+
+ if (s->need_redraw) {
+ ImBuf *ibuf = BKE_image_acquire_ibuf(s->image, s->sima ? &s->sima->iuser : NULL, NULL);
+
+ imapaint_image_update(s->sima, s->image, ibuf, false);
+ ED_imapaint_clear_partial_redraw();
+
+ BKE_image_release_ibuf(s->image, ibuf, NULL);
+
+ s->need_redraw = false;
+ }
+ else if (!final) {
+ return;
+ }
+
+ if (final) {
+ if (s->image && !(s->sima && s->sima->lock))
+ GPU_free_image(s->image);
+
+ /* compositor listener deals with updating */
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, s->image);
+ DEG_id_tag_update(&s->image->id, 0);
+ }
+ else {
+ if (!s->sima || !s->sima->lock)
+ ED_region_tag_redraw(CTX_wm_region(C));
+ else
+ WM_event_add_notifier(C, NC_IMAGE | NA_PAINTING, s->image);
+ }
}
void paint_2d_stroke_done(void *ps)
{
- ImagePaintState *s = ps;
+ ImagePaintState *s = ps;
- paint_2d_canvas_free(s);
- brush_painter_2d_free(s->painter);
- paint_brush_exit_tex(s->brush);
+ paint_2d_canvas_free(s);
+ brush_painter_2d_free(s->painter);
+ paint_brush_exit_tex(s->brush);
- MEM_freeN(s);
+ MEM_freeN(s);
}
-static void paint_2d_fill_add_pixel_byte(
- const int x_px, const int y_px, ImBuf *ibuf, BLI_Stack *stack, BLI_bitmap *touched,
- const float color[4], float threshold_sq)
+static void paint_2d_fill_add_pixel_byte(const int x_px,
+ const int y_px,
+ ImBuf *ibuf,
+ BLI_Stack *stack,
+ BLI_bitmap *touched,
+ const float color[4],
+ float threshold_sq)
{
- size_t coordinate;
+ size_t coordinate;
- if (x_px >= ibuf->x || x_px < 0 || y_px >= ibuf->y || y_px < 0)
- return;
+ if (x_px >= ibuf->x || x_px < 0 || y_px >= ibuf->y || y_px < 0)
+ return;
- coordinate = ((size_t)y_px) * ibuf->x + x_px;
+ coordinate = ((size_t)y_px) * ibuf->x + x_px;
- if (!BLI_BITMAP_TEST(touched, coordinate)) {
- float color_f[4];
- unsigned char *color_b = (unsigned char *)(ibuf->rect + coordinate);
- rgba_uchar_to_float(color_f, color_b);
- straight_to_premul_v4(color_f);
+ if (!BLI_BITMAP_TEST(touched, coordinate)) {
+ float color_f[4];
+ unsigned char *color_b = (unsigned char *)(ibuf->rect + coordinate);
+ rgba_uchar_to_float(color_f, color_b);
+ straight_to_premul_v4(color_f);
- if (len_squared_v4v4(color_f, color) <= threshold_sq) {
- BLI_stack_push(stack, &coordinate);
- }
- BLI_BITMAP_SET(touched, coordinate, true);
- }
+ if (len_squared_v4v4(color_f, color) <= threshold_sq) {
+ BLI_stack_push(stack, &coordinate);
+ }
+ BLI_BITMAP_SET(touched, coordinate, true);
+ }
}
-static void paint_2d_fill_add_pixel_float(
- const int x_px, const int y_px, ImBuf *ibuf, BLI_Stack *stack, BLI_bitmap *touched,
- const float color[4], float threshold_sq)
+static void paint_2d_fill_add_pixel_float(const int x_px,
+ const int y_px,
+ ImBuf *ibuf,
+ BLI_Stack *stack,
+ BLI_bitmap *touched,
+ const float color[4],
+ float threshold_sq)
{
- size_t coordinate;
+ size_t coordinate;
- if (x_px >= ibuf->x || x_px < 0 || y_px >= ibuf->y || y_px < 0)
- return;
+ if (x_px >= ibuf->x || x_px < 0 || y_px >= ibuf->y || y_px < 0)
+ return;
- coordinate = ((size_t)y_px) * ibuf->x + x_px;
+ coordinate = ((size_t)y_px) * ibuf->x + x_px;
- if (!BLI_BITMAP_TEST(touched, coordinate)) {
- if (len_squared_v4v4(ibuf->rect_float + 4 * coordinate, color) <= threshold_sq) {
- BLI_stack_push(stack, &coordinate);
- }
- BLI_BITMAP_SET(touched, coordinate, true);
- }
+ if (!BLI_BITMAP_TEST(touched, coordinate)) {
+ if (len_squared_v4v4(ibuf->rect_float + 4 * coordinate, color) <= threshold_sq) {
+ BLI_stack_push(stack, &coordinate);
+ }
+ BLI_BITMAP_SET(touched, coordinate, true);
+ }
}
/* this function expects linear space color values */
void paint_2d_bucket_fill(
- const bContext *C, const float color[3], Brush *br,
- const float mouse_init[2],
- void *ps)
+ const bContext *C, const float color[3], Brush *br, const float mouse_init[2], void *ps)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = sima->image;
-
- ImagePaintState *s = ps;
-
- ImBuf *ibuf;
- int x_px, y_px;
- unsigned int color_b;
- float color_f[4];
- float strength = br ? br->alpha : 1.0f;
-
- bool do_float;
-
- if (!ima)
- return;
-
- ibuf = BKE_image_acquire_ibuf(ima, &sima->iuser, NULL);
-
- if (!ibuf)
- return;
-
- do_float = (ibuf->rect_float != NULL);
- /* first check if our image is float. If it is not we should correct the color to
- * 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);
- *(((char *)&color_b) + 3) = strength * 255;
- }
- else {
- copy_v3_v3(color_f, color);
- color_f[3] = strength;
- }
-
- if (!mouse_init || !br) {
- /* first case, no image UV, fill the whole image */
- ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false);
-
- if (do_float) {
- for (x_px = 0; x_px < ibuf->x; x_px++) {
- for (y_px = 0; y_px < ibuf->y; y_px++) {
- blend_color_mix_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);
- }
- }
- }
- 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);
- }
- }
- }
- }
- else {
- /* second case, start sweeping the neighboring pixels, looking for pixels whose
- * value is within the brush fill threshold from the fill color */
- BLI_Stack *stack;
- BLI_bitmap *touched;
- size_t coordinate;
- int width = ibuf->x;
- float image_init[2];
- int minx = ibuf->x, miny = ibuf->y, maxx = 0, maxy = 0;
- float pixel_color[4];
- /* We are comparing to sum of three squared values
- * (assumed in range [0,1]), so need to multiply... */
- float threshold_sq = br->fill_threshold * br->fill_threshold * 3;
-
- UI_view2d_region_to_view(s->v2d, mouse_init[0], mouse_init[1], &image_init[0], &image_init[1]);
-
- x_px = image_init[0] * ibuf->x;
- y_px = image_init[1] * ibuf->y;
-
- if (x_px >= ibuf->x || x_px < 0 || y_px > ibuf->y || y_px < 0) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- return;
- }
-
- /* change image invalidation method later */
- ED_imapaint_dirty_region(ima, ibuf, 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");
-
- coordinate = (((size_t)y_px) * ibuf->x + x_px);
-
- if (do_float) {
- copy_v4_v4(pixel_color, ibuf->rect_float + 4 * coordinate);
- }
- else {
- int pixel_color_b = *(ibuf->rect + coordinate);
- rgba_uchar_to_float(pixel_color, (unsigned char *)&pixel_color_b);
- straight_to_premul_v4(pixel_color);
- }
-
- BLI_stack_push(stack, &coordinate);
- BLI_BITMAP_SET(touched, coordinate, true);
-
- if (do_float) {
- while (!BLI_stack_is_empty(stack)) {
- BLI_stack_pop(stack, &coordinate);
-
- IMB_blend_color_float(
- ibuf->rect_float + 4 * (coordinate),
- ibuf->rect_float + 4 * (coordinate),
- color_f, br->blend);
-
- /* reconstruct the coordinates here */
- x_px = coordinate % width;
- y_px = coordinate / width;
-
- paint_2d_fill_add_pixel_float(x_px - 1, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
- paint_2d_fill_add_pixel_float(x_px - 1, y_px, ibuf, stack, touched, pixel_color, threshold_sq);
- paint_2d_fill_add_pixel_float(x_px - 1, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
- paint_2d_fill_add_pixel_float(x_px, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
- paint_2d_fill_add_pixel_float(x_px, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
- paint_2d_fill_add_pixel_float(x_px + 1, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
- paint_2d_fill_add_pixel_float(x_px + 1, y_px, ibuf, stack, touched, pixel_color, threshold_sq);
- paint_2d_fill_add_pixel_float(x_px + 1, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
-
- if (x_px > maxx)
- maxx = x_px;
- if (x_px < minx)
- minx = x_px;
- if (y_px > maxy)
- maxy = y_px;
- if (x_px > miny)
- miny = y_px;
- }
- }
- else {
- 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, br->blend);
-
- /* reconstruct the coordinates here */
- x_px = coordinate % width;
- y_px = coordinate / width;
-
- paint_2d_fill_add_pixel_byte(x_px - 1, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
- paint_2d_fill_add_pixel_byte(x_px - 1, y_px, ibuf, stack, touched, pixel_color, threshold_sq);
- paint_2d_fill_add_pixel_byte(x_px - 1, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
- paint_2d_fill_add_pixel_byte(x_px, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
- paint_2d_fill_add_pixel_byte(x_px, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
- paint_2d_fill_add_pixel_byte(x_px + 1, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
- paint_2d_fill_add_pixel_byte(x_px + 1, y_px, ibuf, stack, touched, pixel_color, threshold_sq);
- paint_2d_fill_add_pixel_byte(x_px + 1, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
-
- if (x_px > maxx)
- maxx = x_px;
- if (x_px < minx)
- minx = x_px;
- if (y_px > maxy)
- maxy = y_px;
- if (x_px > miny)
- miny = y_px;
- }
- }
-
- MEM_freeN(touched);
- BLI_stack_free(stack);
- }
-
- imapaint_image_update(sima, ima, ibuf, false);
- ED_imapaint_clear_partial_redraw();
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
-
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = sima->image;
+
+ ImagePaintState *s = ps;
+
+ ImBuf *ibuf;
+ int x_px, y_px;
+ unsigned int color_b;
+ float color_f[4];
+ float strength = br ? br->alpha : 1.0f;
+
+ bool do_float;
+
+ if (!ima)
+ return;
+
+ ibuf = BKE_image_acquire_ibuf(ima, &sima->iuser, NULL);
+
+ if (!ibuf)
+ return;
+
+ do_float = (ibuf->rect_float != NULL);
+ /* first check if our image is float. If it is not we should correct the color to
+ * 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);
+ *(((char *)&color_b) + 3) = strength * 255;
+ }
+ else {
+ copy_v3_v3(color_f, color);
+ color_f[3] = strength;
+ }
+
+ if (!mouse_init || !br) {
+ /* first case, no image UV, fill the whole image */
+ ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false);
+
+ if (do_float) {
+ for (x_px = 0; x_px < ibuf->x; x_px++) {
+ for (y_px = 0; y_px < ibuf->y; y_px++) {
+ blend_color_mix_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);
+ }
+ }
+ }
+ 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);
+ }
+ }
+ }
+ }
+ else {
+ /* second case, start sweeping the neighboring pixels, looking for pixels whose
+ * value is within the brush fill threshold from the fill color */
+ BLI_Stack *stack;
+ BLI_bitmap *touched;
+ size_t coordinate;
+ int width = ibuf->x;
+ float image_init[2];
+ int minx = ibuf->x, miny = ibuf->y, maxx = 0, maxy = 0;
+ float pixel_color[4];
+ /* We are comparing to sum of three squared values
+ * (assumed in range [0,1]), so need to multiply... */
+ float threshold_sq = br->fill_threshold * br->fill_threshold * 3;
+
+ UI_view2d_region_to_view(s->v2d, mouse_init[0], mouse_init[1], &image_init[0], &image_init[1]);
+
+ x_px = image_init[0] * ibuf->x;
+ y_px = image_init[1] * ibuf->y;
+
+ if (x_px >= ibuf->x || x_px < 0 || y_px > ibuf->y || y_px < 0) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ return;
+ }
+
+ /* change image invalidation method later */
+ ED_imapaint_dirty_region(ima, ibuf, 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");
+
+ coordinate = (((size_t)y_px) * ibuf->x + x_px);
+
+ if (do_float) {
+ copy_v4_v4(pixel_color, ibuf->rect_float + 4 * coordinate);
+ }
+ else {
+ int pixel_color_b = *(ibuf->rect + coordinate);
+ rgba_uchar_to_float(pixel_color, (unsigned char *)&pixel_color_b);
+ straight_to_premul_v4(pixel_color);
+ }
+
+ BLI_stack_push(stack, &coordinate);
+ BLI_BITMAP_SET(touched, coordinate, true);
+
+ if (do_float) {
+ while (!BLI_stack_is_empty(stack)) {
+ BLI_stack_pop(stack, &coordinate);
+
+ IMB_blend_color_float(ibuf->rect_float + 4 * (coordinate),
+ ibuf->rect_float + 4 * (coordinate),
+ color_f,
+ br->blend);
+
+ /* reconstruct the coordinates here */
+ x_px = coordinate % width;
+ y_px = coordinate / width;
+
+ paint_2d_fill_add_pixel_float(
+ x_px - 1, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(
+ x_px - 1, y_px, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(
+ x_px - 1, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(
+ x_px, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(
+ x_px, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(
+ x_px + 1, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(
+ x_px + 1, y_px, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(
+ x_px + 1, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
+
+ if (x_px > maxx)
+ maxx = x_px;
+ if (x_px < minx)
+ minx = x_px;
+ if (y_px > maxy)
+ maxy = y_px;
+ if (x_px > miny)
+ miny = y_px;
+ }
+ }
+ else {
+ 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,
+ br->blend);
+
+ /* reconstruct the coordinates here */
+ x_px = coordinate % width;
+ y_px = coordinate / width;
+
+ paint_2d_fill_add_pixel_byte(
+ x_px - 1, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(
+ x_px - 1, y_px, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(
+ x_px - 1, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(
+ x_px, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(
+ x_px, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(
+ x_px + 1, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(
+ x_px + 1, y_px, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(
+ x_px + 1, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
+
+ if (x_px > maxx)
+ maxx = x_px;
+ if (x_px < minx)
+ minx = x_px;
+ if (y_px > maxy)
+ maxy = y_px;
+ if (x_px > miny)
+ miny = y_px;
+ }
+ }
+
+ MEM_freeN(touched);
+ BLI_stack_free(stack);
+ }
+
+ imapaint_image_update(sima, ima, ibuf, false);
+ ED_imapaint_clear_partial_redraw();
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
}
void paint_2d_gradient_fill(
- const bContext *C, Brush *br,
- const float mouse_init[2], const float mouse_final[2],
- void *ps)
+ const bContext *C, Brush *br, const float mouse_init[2], const float mouse_final[2], void *ps)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = sima->image;
- ImagePaintState *s = ps;
-
- ImBuf *ibuf;
- int x_px, y_px;
- unsigned int color_b;
- float color_f[4];
- float image_init[2], image_final[2];
- float tangent[2];
- float line_len_sq_inv, line_len;
-
- bool do_float;
-
- if (!ima)
- return;
-
- ibuf = BKE_image_acquire_ibuf(ima, &sima->iuser, NULL);
-
- if (!ibuf)
- return;
-
- UI_view2d_region_to_view(s->v2d, mouse_final[0], mouse_final[1], &image_final[0], &image_final[1]);
- UI_view2d_region_to_view(s->v2d, mouse_init[0], mouse_init[1], &image_init[0], &image_init[1]);
-
- image_final[0] *= ibuf->x;
- image_final[1] *= ibuf->y;
-
- image_init[0] *= ibuf->x;
- image_init[1] *= ibuf->y;
-
- /* some math to get needed gradient variables */
- sub_v2_v2v2(tangent, image_final, image_init);
- line_len = len_squared_v2(tangent);
- line_len_sq_inv = 1.0f / line_len;
- line_len = sqrtf(line_len);
-
- do_float = (ibuf->rect_float != NULL);
-
- /* this will be substituted by something else when selection is available */
- ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false);
-
- if (do_float) {
- for (x_px = 0; x_px < ibuf->x; x_px++) {
- for (y_px = 0; y_px < ibuf->y; y_px++) {
- float f;
- float p[2] = {x_px - image_init[0], y_px - image_init[1]};
-
- switch (br->gradient_fill_mode) {
- case BRUSH_GRADIENT_LINEAR:
- {
- f = dot_v2v2(p, tangent) * line_len_sq_inv;
- break;
- }
- case BRUSH_GRADIENT_RADIAL:
- default:
- {
- f = len_v2(p) / line_len;
- break;
- }
- }
- BKE_colorband_evaluate(br->gradient, f, color_f);
- /* convert to premultiplied */
- mul_v3_fl(color_f, color_f[3]);
- color_f[3] *= br->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, br->blend);
- }
- }
- }
- else {
- for (x_px = 0; x_px < ibuf->x; x_px++) {
- for (y_px = 0; y_px < ibuf->y; y_px++) {
- float f;
- float p[2] = {x_px - image_init[0], y_px - image_init[1]};
-
- switch (br->gradient_fill_mode) {
- case BRUSH_GRADIENT_LINEAR:
- {
- f = dot_v2v2(p, tangent) * line_len_sq_inv;
- break;
- }
- case BRUSH_GRADIENT_RADIAL:
- default:
- {
- f = len_v2(p) / line_len;
- break;
- }
- }
-
- 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, br->blend);
- }
- }
- }
-
- imapaint_image_update(sima, ima, ibuf, false);
- ED_imapaint_clear_partial_redraw();
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
-
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = sima->image;
+ ImagePaintState *s = ps;
+
+ ImBuf *ibuf;
+ int x_px, y_px;
+ unsigned int color_b;
+ float color_f[4];
+ float image_init[2], image_final[2];
+ float tangent[2];
+ float line_len_sq_inv, line_len;
+
+ bool do_float;
+
+ if (!ima)
+ return;
+
+ ibuf = BKE_image_acquire_ibuf(ima, &sima->iuser, NULL);
+
+ if (!ibuf)
+ return;
+
+ UI_view2d_region_to_view(
+ s->v2d, mouse_final[0], mouse_final[1], &image_final[0], &image_final[1]);
+ UI_view2d_region_to_view(s->v2d, mouse_init[0], mouse_init[1], &image_init[0], &image_init[1]);
+
+ image_final[0] *= ibuf->x;
+ image_final[1] *= ibuf->y;
+
+ image_init[0] *= ibuf->x;
+ image_init[1] *= ibuf->y;
+
+ /* some math to get needed gradient variables */
+ sub_v2_v2v2(tangent, image_final, image_init);
+ line_len = len_squared_v2(tangent);
+ line_len_sq_inv = 1.0f / line_len;
+ line_len = sqrtf(line_len);
+
+ do_float = (ibuf->rect_float != NULL);
+
+ /* this will be substituted by something else when selection is available */
+ ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false);
+
+ if (do_float) {
+ for (x_px = 0; x_px < ibuf->x; x_px++) {
+ for (y_px = 0; y_px < ibuf->y; y_px++) {
+ float f;
+ float p[2] = {x_px - image_init[0], y_px - image_init[1]};
+
+ switch (br->gradient_fill_mode) {
+ case BRUSH_GRADIENT_LINEAR: {
+ f = dot_v2v2(p, tangent) * line_len_sq_inv;
+ break;
+ }
+ case BRUSH_GRADIENT_RADIAL:
+ default: {
+ f = len_v2(p) / line_len;
+ break;
+ }
+ }
+ BKE_colorband_evaluate(br->gradient, f, color_f);
+ /* convert to premultiplied */
+ mul_v3_fl(color_f, color_f[3]);
+ color_f[3] *= br->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,
+ br->blend);
+ }
+ }
+ }
+ else {
+ for (x_px = 0; x_px < ibuf->x; x_px++) {
+ for (y_px = 0; y_px < ibuf->y; y_px++) {
+ float f;
+ float p[2] = {x_px - image_init[0], y_px - image_init[1]};
+
+ switch (br->gradient_fill_mode) {
+ case BRUSH_GRADIENT_LINEAR: {
+ f = dot_v2v2(p, tangent) * line_len_sq_inv;
+ break;
+ }
+ case BRUSH_GRADIENT_RADIAL:
+ default: {
+ f = len_v2(p) / line_len;
+ break;
+ }
+ }
+
+ 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,
+ br->blend);
+ }
+ }
+ }
+
+ imapaint_image_update(sima, ima, ibuf, false);
+ ED_imapaint_clear_partial_redraw();
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 45ae3e9dc11..7a99f819913 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -45,7 +45,6 @@
#include "BLT_translation.h"
-
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -114,7 +113,7 @@ static void partial_redraw_array_init(ImagePaintPartialRedraw *pr);
/* unit_float_to_uchar_clamp as inline function */
BLI_INLINE unsigned char f_to_char(const float val)
{
- return unit_float_to_uchar_clamp(val);
+ return unit_float_to_uchar_clamp(val);
}
/* ProjectionPaint defines */
@@ -131,58 +130,56 @@ BLI_INLINE unsigned char f_to_char(const float val)
#define PROJ_BUCKET_RECT_MAX 256
#define PROJ_BOUNDBOX_DIV 8
-#define PROJ_BOUNDBOX_SQUARED (PROJ_BOUNDBOX_DIV * PROJ_BOUNDBOX_DIV)
+#define PROJ_BOUNDBOX_SQUARED (PROJ_BOUNDBOX_DIV * PROJ_BOUNDBOX_DIV)
//#define PROJ_DEBUG_PAINT 1
//#define PROJ_DEBUG_NOSEAMBLEED 1
//#define PROJ_DEBUG_PRINT_CLIP 1
#define PROJ_DEBUG_WINCLIP 1
-
#ifndef PROJ_DEBUG_NOSEAMBLEED
/* projectFaceSeamFlags options */
-//#define PROJ_FACE_IGNORE (1<<0) /* When the face is hidden, backfacing or occluded */
-//#define PROJ_FACE_INIT (1<<1) /* When we have initialized the faces data */
+//#define PROJ_FACE_IGNORE (1<<0) /* When the face is hidden, backfacing or occluded */
+//#define PROJ_FACE_INIT (1<<1) /* When we have initialized the faces data */
/* If this face has a seam on any of its edges. */
-#define PROJ_FACE_SEAM0 (1 << 0)
-#define PROJ_FACE_SEAM1 (1 << 1)
-#define PROJ_FACE_SEAM2 (1 << 2)
+# define PROJ_FACE_SEAM0 (1 << 0)
+# define PROJ_FACE_SEAM1 (1 << 1)
+# define PROJ_FACE_SEAM2 (1 << 2)
-#define PROJ_FACE_NOSEAM0 (1 << 4)
-#define PROJ_FACE_NOSEAM1 (1 << 5)
-#define PROJ_FACE_NOSEAM2 (1 << 6)
+# define PROJ_FACE_NOSEAM0 (1 << 4)
+# define PROJ_FACE_NOSEAM1 (1 << 5)
+# define PROJ_FACE_NOSEAM2 (1 << 6)
/* If the seam is completely initialized, including adjecent seams. */
-#define PROJ_FACE_SEAM_INIT0 (1 << 8)
-#define PROJ_FACE_SEAM_INIT1 (1 << 9)
-#define PROJ_FACE_SEAM_INIT2 (1 << 10)
+# define PROJ_FACE_SEAM_INIT0 (1 << 8)
+# define PROJ_FACE_SEAM_INIT1 (1 << 9)
+# define PROJ_FACE_SEAM_INIT2 (1 << 10)
-#define PROJ_FACE_DEGENERATE (1 << 12)
+# define PROJ_FACE_DEGENERATE (1 << 12)
/* face winding */
-#define PROJ_FACE_WINDING_INIT 1
-#define PROJ_FACE_WINDING_CW 2
+# define PROJ_FACE_WINDING_INIT 1
+# define PROJ_FACE_WINDING_CW 2
/* a slightly scaled down face is used to get fake 3D location for edge pixels in the seams
* as this number approaches 1.0f the likelihood increases of float precision errors where
* it is occluded by an adjacent face */
-#define PROJ_FACE_SCALE_SEAM 0.99f
-#endif /* PROJ_DEBUG_NOSEAMBLEED */
-
+# define PROJ_FACE_SCALE_SEAM 0.99f
+#endif /* PROJ_DEBUG_NOSEAMBLEED */
-#define PROJ_SRC_VIEW 1
-#define PROJ_SRC_IMAGE_CAM 2
+#define PROJ_SRC_VIEW 1
+#define PROJ_SRC_IMAGE_CAM 2
#define PROJ_SRC_IMAGE_VIEW 3
-#define PROJ_SRC_VIEW_FILL 4
+#define PROJ_SRC_VIEW_FILL 4
#define PROJ_VIEW_DATA_ID "view_data"
/* viewmat + winmat + clip_start + clip_end + is_ortho */
#define PROJ_VIEW_DATA_SIZE (4 * 4 + 4 * 4 + 3)
-#define PROJ_BUCKET_NULL 0
-#define PROJ_BUCKET_INIT (1 << 0)
-// #define PROJ_BUCKET_CLONE_INIT (1<<1)
+#define PROJ_BUCKET_NULL 0
+#define PROJ_BUCKET_INIT (1 << 0)
+// #define PROJ_BUCKET_CLONE_INIT (1<<1)
/* used for testing doubles, if a point is on a line etc */
#define PROJ_GEOM_TOLERANCE 0.00075f
@@ -198,605 +195,595 @@ BLI_INLINE unsigned char f_to_char(const float val)
* their imbufs, etc, in 1 array, When using threads this array is copied for each thread
* because 'partRedrawRect' and 'touch' values would not be thread safe */
typedef struct ProjPaintImage {
- Image *ima;
- ImBuf *ibuf;
- ImagePaintPartialRedraw *partRedrawRect;
- /** Only used to build undo tiles during painting. */
- volatile void **undoRect;
- /** The mask accumulation must happen on canvas, not on space screen bucket.
- * Here we store the mask rectangle. */
- unsigned short **maskRect;
- /** Store flag to enforce validation of undo rectangle. */
- bool **valid;
- bool touch;
+ Image *ima;
+ ImBuf *ibuf;
+ ImagePaintPartialRedraw *partRedrawRect;
+ /** Only used to build undo tiles during painting. */
+ volatile void **undoRect;
+ /** The mask accumulation must happen on canvas, not on space screen bucket.
+ * Here we store the mask rectangle. */
+ unsigned short **maskRect;
+ /** Store flag to enforce validation of undo rectangle. */
+ bool **valid;
+ bool touch;
} ProjPaintImage;
/**
* Handle for stroke (operator customdata)
*/
typedef struct ProjStrokeHandle {
- /* Support for painting from multiple views at once,
- * currently used to implement symmetry painting,
- * we can assume at least the first is set while painting. */
- struct ProjPaintState *ps_views[8];
- int ps_views_tot;
- int symmetry_flags;
+ /* Support for painting from multiple views at once,
+ * currently used to implement symmetry painting,
+ * we can assume at least the first is set while painting. */
+ struct ProjPaintState *ps_views[8];
+ int ps_views_tot;
+ int symmetry_flags;
- int orig_brush_size;
+ int orig_brush_size;
- bool need_redraw;
+ bool need_redraw;
- /* trick to bypass regular paint and allow clone picking */
- bool is_clone_cursor_pick;
+ /* trick to bypass regular paint and allow clone picking */
+ bool is_clone_cursor_pick;
- /* In ProjPaintState, only here for convenience */
- Scene *scene;
- Brush *brush;
+ /* In ProjPaintState, only here for convenience */
+ Scene *scene;
+ Brush *brush;
} ProjStrokeHandle;
typedef struct LoopSeamData {
- float seam_uvs[2][2];
- float seam_puvs[2][2];
- float corner_dist_sq[2];
+ float seam_uvs[2][2];
+ float seam_puvs[2][2];
+ float corner_dist_sq[2];
} LoopSeamData;
/* Main projection painting struct passed to all projection painting functions */
typedef struct ProjPaintState {
- View3D *v3d;
- RegionView3D *rv3d;
- ARegion *ar;
- Depsgraph *depsgraph;
- Scene *scene;
- /* PROJ_SRC_**** */
- int source;
-
- /* the paint color. It can change depending of inverted mode or not */
- float paint_color[3];
- float paint_color_linear[3];
- float dither;
-
- Brush *brush;
- short tool, blend, mode;
-
- float brush_size;
- Object *ob;
- /* for symmetry, we need to store modified object matrix */
- float obmat[4][4];
- float obmat_imat[4][4];
- /* end similarities with ImagePaintState */
-
- Image *stencil_ima;
- Image *canvas_ima;
- Image *clone_ima;
- float stencil_value;
-
- /* projection painting only */
- /** for multithreading, the first item is sometimes used for non threaded cases too. */
- MemArena *arena_mt[BLENDER_MAX_THREADS];
- /** screen sized 2D array, each pixel has a linked list of ProjPixel's */
- LinkNode **bucketRect;
- /** bucketRect aligned array linkList of faces overlapping each bucket. */
- LinkNode **bucketFaces;
- /** store if the bucks have been initialized. */
- unsigned char *bucketFlags;
-
- /** store options per vert, now only store if the vert is pointing away from the view. */
- char *vertFlags;
- /** The size of the bucket grid, the grid span's screenMin/screenMax
- * so you can paint outsize the screen or with 2 brushes at once. */
- int buckets_x;
- int buckets_y;
-
- /** result of project_paint_pixel_sizeof(), constant per stroke. */
- int pixel_sizeof;
-
- /** size of projectImages array. */
- int image_tot;
-
- /** verts projected into floating point screen space. */
- float (*screenCoords)[4];
- /** 2D bounds for mesh verts on the screen's plane (screenspace). */
- float screenMin[2];
- float screenMax[2];
- /** Calculated from screenMin & screenMax. */
- float screen_width;
- float screen_height;
- /** from the carea or from the projection render. */
- int winx, winy;
-
- /* options for projection painting */
- bool do_layer_clone;
- bool do_layer_stencil;
- bool do_layer_stencil_inv;
- bool do_stencil_brush;
- bool do_material_slots;
-
- /** Use raytraced occlusion? - ortherwise will paint right through to the back. */
- bool do_occlude;
- /** ignore faces with normals pointing away,
- * skips a lot of raycasts if your normals are correctly flipped. */
- bool do_backfacecull;
- /** mask out pixels based on their normals. */
- bool do_mask_normal;
- /** mask out pixels based on cavity. */
- bool do_mask_cavity;
- /** what angle to mask at. */
- float normal_angle;
- /** cos(normal_angle), faster to compare. */
- float normal_angle__cos;
- float normal_angle_inner;
- float normal_angle_inner__cos;
- /** difference between normal_angle and normal_angle_inner, for easy access. */
- float normal_angle_range;
-
- /** quick access to (me->editflag & ME_EDIT_PAINT_FACE_SEL) */
- bool do_face_sel;
- bool is_ortho;
- /** the object is negative scaled. */
- bool is_flip_object;
- /** use masking during painting. Some operations such as airbrush may disable. */
- bool do_masking;
- /** only to avoid running. */
- bool is_texbrush;
- /** mask brush is applied before masking. */
- bool is_maskbrush;
+ View3D *v3d;
+ RegionView3D *rv3d;
+ ARegion *ar;
+ Depsgraph *depsgraph;
+ Scene *scene;
+ /* PROJ_SRC_**** */
+ int source;
+
+ /* the paint color. It can change depending of inverted mode or not */
+ float paint_color[3];
+ float paint_color_linear[3];
+ float dither;
+
+ Brush *brush;
+ short tool, blend, mode;
+
+ float brush_size;
+ Object *ob;
+ /* for symmetry, we need to store modified object matrix */
+ float obmat[4][4];
+ float obmat_imat[4][4];
+ /* end similarities with ImagePaintState */
+
+ Image *stencil_ima;
+ Image *canvas_ima;
+ Image *clone_ima;
+ float stencil_value;
+
+ /* projection painting only */
+ /** for multithreading, the first item is sometimes used for non threaded cases too. */
+ MemArena *arena_mt[BLENDER_MAX_THREADS];
+ /** screen sized 2D array, each pixel has a linked list of ProjPixel's */
+ LinkNode **bucketRect;
+ /** bucketRect aligned array linkList of faces overlapping each bucket. */
+ LinkNode **bucketFaces;
+ /** store if the bucks have been initialized. */
+ unsigned char *bucketFlags;
+
+ /** store options per vert, now only store if the vert is pointing away from the view. */
+ char *vertFlags;
+ /** The size of the bucket grid, the grid span's screenMin/screenMax
+ * so you can paint outsize the screen or with 2 brushes at once. */
+ int buckets_x;
+ int buckets_y;
+
+ /** result of project_paint_pixel_sizeof(), constant per stroke. */
+ int pixel_sizeof;
+
+ /** size of projectImages array. */
+ int image_tot;
+
+ /** verts projected into floating point screen space. */
+ float (*screenCoords)[4];
+ /** 2D bounds for mesh verts on the screen's plane (screenspace). */
+ float screenMin[2];
+ float screenMax[2];
+ /** Calculated from screenMin & screenMax. */
+ float screen_width;
+ float screen_height;
+ /** from the carea or from the projection render. */
+ int winx, winy;
+
+ /* options for projection painting */
+ bool do_layer_clone;
+ bool do_layer_stencil;
+ bool do_layer_stencil_inv;
+ bool do_stencil_brush;
+ bool do_material_slots;
+
+ /** Use raytraced occlusion? - ortherwise will paint right through to the back. */
+ bool do_occlude;
+ /** ignore faces with normals pointing away,
+ * skips a lot of raycasts if your normals are correctly flipped. */
+ bool do_backfacecull;
+ /** mask out pixels based on their normals. */
+ bool do_mask_normal;
+ /** mask out pixels based on cavity. */
+ bool do_mask_cavity;
+ /** what angle to mask at. */
+ float normal_angle;
+ /** cos(normal_angle), faster to compare. */
+ float normal_angle__cos;
+ float normal_angle_inner;
+ float normal_angle_inner__cos;
+ /** difference between normal_angle and normal_angle_inner, for easy access. */
+ float normal_angle_range;
+
+ /** quick access to (me->editflag & ME_EDIT_PAINT_FACE_SEL) */
+ bool do_face_sel;
+ bool is_ortho;
+ /** the object is negative scaled. */
+ bool is_flip_object;
+ /** use masking during painting. Some operations such as airbrush may disable. */
+ bool do_masking;
+ /** only to avoid running. */
+ bool is_texbrush;
+ /** mask brush is applied before masking. */
+ bool is_maskbrush;
#ifndef PROJ_DEBUG_NOSEAMBLEED
- float seam_bleed_px;
- float seam_bleed_px_sq;
+ float seam_bleed_px;
+ float seam_bleed_px_sq;
#endif
- /* clone vars */
- float cloneOffset[2];
-
- /** Projection matrix, use for getting screen coords. */
- float projectMat[4][4];
- /** inverse of projectMat. */
- float projectMatInv[4][4];
- /** View vector, use for do_backfacecull and for ray casting with an ortho viewport. */
- float viewDir[3];
- /** View location in object relative 3D space, so can compare to verts. */
- float viewPos[3];
- float clip_start, clip_end;
-
- /* reproject vars */
- Image *reproject_image;
- ImBuf *reproject_ibuf;
- bool reproject_ibuf_free_float;
- bool reproject_ibuf_free_uchar;
-
- /* threads */
- int thread_tot;
- int bucketMin[2];
- int bucketMax[2];
- /** must lock threads while accessing these. */
- int context_bucket_x, context_bucket_y;
-
- struct CurveMapping *cavity_curve;
- BlurKernel *blurkernel;
-
-
-
- /* -------------------------------------------------------------------- */
- /* Vars shared between multiple views (keep last) */
- /**
- * This data is owned by ``ProjStrokeHandle.ps_views[0]``,
- * all other views re-use the data.
- */
+ /* clone vars */
+ float cloneOffset[2];
+
+ /** Projection matrix, use for getting screen coords. */
+ float projectMat[4][4];
+ /** inverse of projectMat. */
+ float projectMatInv[4][4];
+ /** View vector, use for do_backfacecull and for ray casting with an ortho viewport. */
+ float viewDir[3];
+ /** View location in object relative 3D space, so can compare to verts. */
+ float viewPos[3];
+ float clip_start, clip_end;
+
+ /* reproject vars */
+ Image *reproject_image;
+ ImBuf *reproject_ibuf;
+ bool reproject_ibuf_free_float;
+ bool reproject_ibuf_free_uchar;
+
+ /* threads */
+ int thread_tot;
+ int bucketMin[2];
+ int bucketMax[2];
+ /** must lock threads while accessing these. */
+ int context_bucket_x, context_bucket_y;
+
+ struct CurveMapping *cavity_curve;
+ BlurKernel *blurkernel;
+
+ /* -------------------------------------------------------------------- */
+ /* Vars shared between multiple views (keep last) */
+ /**
+ * This data is owned by ``ProjStrokeHandle.ps_views[0]``,
+ * all other views re-use the data.
+ */
#define PROJ_PAINT_STATE_SHARED_MEMCPY(ps_dst, ps_src) \
- MEMCPY_STRUCT_AFTER(ps_dst, ps_src, is_shared_user)
+ MEMCPY_STRUCT_AFTER(ps_dst, ps_src, is_shared_user)
-#define PROJ_PAINT_STATE_SHARED_CLEAR(ps) \
- MEMSET_STRUCT_AFTER(ps, 0, is_shared_user)
+#define PROJ_PAINT_STATE_SHARED_CLEAR(ps) MEMSET_STRUCT_AFTER(ps, 0, is_shared_user)
- bool is_shared_user;
+ bool is_shared_user;
- ProjPaintImage *projImages;
- /** cavity amount for vertices. */
- float *cavities;
+ ProjPaintImage *projImages;
+ /** cavity amount for vertices. */
+ float *cavities;
#ifndef PROJ_DEBUG_NOSEAMBLEED
- /** store info about faces, if they are initialized etc*/
- ushort *faceSeamFlags;
- /** save the winding of the face in uv space,
- * helps as an extra validation step for seam detection. */
- char *faceWindingFlags;
- /** expanded UVs for faces to use as seams. */
- LoopSeamData (*loopSeamData);
- /** Only needed for when seam_bleed_px is enabled, use to find UV seams. */
- LinkNode **vertFaces;
- /** Seams per vert, to find adjacent seams. */
- ListBase *vertSeams;
+ /** store info about faces, if they are initialized etc*/
+ ushort *faceSeamFlags;
+ /** save the winding of the face in uv space,
+ * helps as an extra validation step for seam detection. */
+ char *faceWindingFlags;
+ /** expanded UVs for faces to use as seams. */
+ LoopSeamData(*loopSeamData);
+ /** Only needed for when seam_bleed_px is enabled, use to find UV seams. */
+ LinkNode **vertFaces;
+ /** Seams per vert, to find adjacent seams. */
+ ListBase *vertSeams;
#endif
- SpinLock *tile_lock;
-
- Mesh *me_eval;
- bool me_eval_free;
- int totlooptri_eval;
- int totloop_eval;
- int totpoly_eval;
- int totedge_eval;
- int totvert_eval;
-
- const MVert *mvert_eval;
- const MEdge *medge_eval;
- const MPoly *mpoly_eval;
- const MLoop *mloop_eval;
- const MLoopTri *mlooptri_eval;
-
- const MLoopUV *mloopuv_stencil_eval;
-
- /**
- * \note These UV layers are aligned to \a mpoly_eval
- * but each pointer references the start of the layer,
- * so a loop indirection is needed as well.
- */
- const MLoopUV **poly_to_loop_uv;
- /** other UV map, use for cloning between layers. */
- const MLoopUV **poly_to_loop_uv_clone;
-
- /* Actual material for each index, either from object or Mesh datablock... */
- Material **mat_array;
-
- bool use_colormanagement;
+ SpinLock *tile_lock;
+
+ Mesh *me_eval;
+ bool me_eval_free;
+ int totlooptri_eval;
+ int totloop_eval;
+ int totpoly_eval;
+ int totedge_eval;
+ int totvert_eval;
+
+ const MVert *mvert_eval;
+ const MEdge *medge_eval;
+ const MPoly *mpoly_eval;
+ const MLoop *mloop_eval;
+ const MLoopTri *mlooptri_eval;
+
+ const MLoopUV *mloopuv_stencil_eval;
+
+ /**
+ * \note These UV layers are aligned to \a mpoly_eval
+ * but each pointer references the start of the layer,
+ * so a loop indirection is needed as well.
+ */
+ const MLoopUV **poly_to_loop_uv;
+ /** other UV map, use for cloning between layers. */
+ const MLoopUV **poly_to_loop_uv_clone;
+
+ /* Actual material for each index, either from object or Mesh datablock... */
+ Material **mat_array;
+
+ bool use_colormanagement;
} ProjPaintState;
typedef union pixelPointer {
- /** float buffer. */
- float *f_pt;
- /** 2 ways to access a char buffer. */
- unsigned int *uint_pt;
- unsigned char *ch_pt;
+ /** float buffer. */
+ float *f_pt;
+ /** 2 ways to access a char buffer. */
+ unsigned int *uint_pt;
+ unsigned char *ch_pt;
} PixelPointer;
typedef union pixelStore {
- unsigned char ch[4];
- unsigned int uint;
- float f[4];
+ unsigned char ch[4];
+ unsigned int uint;
+ float f[4];
} PixelStore;
typedef struct ProjPixel {
- /** the floating point screen projection of this pixel. */
- float projCoSS[2];
- float worldCoSS[3];
+ /** the floating point screen projection of this pixel. */
+ float projCoSS[2];
+ float worldCoSS[3];
- short x_px, y_px;
+ 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;
+ /** if anyone wants to paint onto more than 65535 images they can bite me. */
+ unsigned short image_index;
+ unsigned char bb_cell_index;
- /* for various reasons we may want to mask out painting onto this pixel */
- unsigned short mask;
+ /* for various reasons we may want to mask out painting onto this pixel */
+ unsigned short 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;
+ /* 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;
- /* horrible hack, store tile valid flag pointer here to re-validate tiles
- * used for anchored and drag-dot strokes */
- bool *valid;
+ /* horrible hack, store tile valid flag pointer here to re-validate tiles
+ * used for anchored and drag-dot strokes */
+ bool *valid;
- PixelPointer origColor;
- PixelStore newColor;
- PixelPointer pixel;
+ PixelPointer origColor;
+ PixelStore newColor;
+ PixelPointer pixel;
} ProjPixel;
typedef struct ProjPixelClone {
- struct ProjPixel __pp;
- PixelStore clonepx;
+ struct ProjPixel __pp;
+ PixelStore clonepx;
} ProjPixelClone;
/* undo tile pushing */
typedef struct {
- SpinLock *lock;
- bool masked;
- unsigned short tile_width;
- ImBuf **tmpibuf;
- ProjPaintImage *pjima;
+ SpinLock *lock;
+ bool masked;
+ unsigned short tile_width;
+ ImBuf **tmpibuf;
+ ProjPaintImage *pjima;
} TileInfo;
typedef struct VertSeam {
- struct VertSeam *next, *prev;
- int tri;
- uint loop;
- float angle;
- bool normal_cw;
- float uv[2];
+ struct VertSeam *next, *prev;
+ int tri;
+ uint loop;
+ float angle;
+ bool normal_cw;
+ float uv[2];
} VertSeam;
-
/* -------------------------------------------------------------------- */
/** \name MLoopTri accessor functions.
* \{ */
BLI_INLINE const MPoly *ps_tri_index_to_mpoly(const ProjPaintState *ps, int tri_index)
{
- return &ps->mpoly_eval[ps->mlooptri_eval[tri_index].poly];
+ return &ps->mpoly_eval[ps->mlooptri_eval[tri_index].poly];
}
#define PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) \
- ps->mloop_eval[lt->tri[0]].v, \
- ps->mloop_eval[lt->tri[1]].v, \
- ps->mloop_eval[lt->tri[2]].v,
+ ps->mloop_eval[lt->tri[0]].v, ps->mloop_eval[lt->tri[1]].v, ps->mloop_eval[lt->tri[2]].v,
#define PS_LOOPTRI_AS_UV_3(uvlayer, lt) \
- uvlayer[lt->poly][lt->tri[0]].uv, \
- uvlayer[lt->poly][lt->tri[1]].uv, \
- uvlayer[lt->poly][lt->tri[2]].uv,
+ uvlayer[lt->poly][lt->tri[0]].uv, uvlayer[lt->poly][lt->tri[1]].uv, \
+ uvlayer[lt->poly][lt->tri[2]].uv,
-#define PS_LOOPTRI_ASSIGN_UV_3(uv_tri, uvlayer, lt) { \
- (uv_tri)[0] = uvlayer[lt->poly][lt->tri[0]].uv; \
- (uv_tri)[1] = uvlayer[lt->poly][lt->tri[1]].uv; \
- (uv_tri)[2] = uvlayer[lt->poly][lt->tri[2]].uv; \
-} ((void)0)
+#define PS_LOOPTRI_ASSIGN_UV_3(uv_tri, uvlayer, lt) \
+ { \
+ (uv_tri)[0] = uvlayer[lt->poly][lt->tri[0]].uv; \
+ (uv_tri)[1] = uvlayer[lt->poly][lt->tri[1]].uv; \
+ (uv_tri)[2] = uvlayer[lt->poly][lt->tri[2]].uv; \
+ } \
+ ((void)0)
/** \} */
-
-
/* Finish projection painting structs */
static TexPaintSlot *project_paint_face_paint_slot(const ProjPaintState *ps, int tri_index)
{
- const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
- Material *ma = ps->mat_array[mp->mat_nr];
- return ma ? ma->texpaintslot + ma->paint_active_slot : NULL;
+ const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
+ Material *ma = ps->mat_array[mp->mat_nr];
+ return ma ? ma->texpaintslot + ma->paint_active_slot : NULL;
}
static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_index)
{
- if (ps->do_stencil_brush) {
- return ps->stencil_ima;
- }
- else {
- const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
- Material *ma = ps->mat_array[mp->mat_nr];
- TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_active_slot : NULL;
- return slot ? slot->ima : ps->canvas_ima;
- }
+ if (ps->do_stencil_brush) {
+ return ps->stencil_ima;
+ }
+ else {
+ const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
+ Material *ma = ps->mat_array[mp->mat_nr];
+ TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_active_slot : NULL;
+ return slot ? slot->ima : ps->canvas_ima;
+ }
}
static TexPaintSlot *project_paint_face_clone_slot(const ProjPaintState *ps, int tri_index)
{
- const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
- Material *ma = ps->mat_array[mp->mat_nr];
- return ma ? ma->texpaintslot + ma->paint_clone_slot : NULL;
+ const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
+ Material *ma = ps->mat_array[mp->mat_nr];
+ return ma ? ma->texpaintslot + ma->paint_clone_slot : NULL;
}
static Image *project_paint_face_clone_image(const ProjPaintState *ps, int tri_index)
{
- const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
- Material *ma = ps->mat_array[mp->mat_nr];
- TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_clone_slot : NULL;
- return slot ? slot->ima : ps->clone_ima;
+ const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
+ Material *ma = ps->mat_array[mp->mat_nr];
+ TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_clone_slot : NULL;
+ return slot ? slot->ima : ps->clone_ima;
}
/* fast projection bucket array lookup, use the safe version for bound checking */
static int project_bucket_offset(const ProjPaintState *ps, const float projCoSS[2])
{
- /* If we were not dealing with screenspace 2D coords we could simple do...
- * ps->bucketRect[x + (y*ps->buckets_y)] */
-
- /* please explain?
- * projCoSS[0] - ps->screenMin[0] : zero origin
- * ... / ps->screen_width : range from 0.0 to 1.0
- * ... * ps->buckets_x : use as a bucket index
- *
- * Second multiplication does similar but for vertical offset
- */
- return ( (int)(((projCoSS[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x)) +
- (((int)(((projCoSS[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y)) * ps->buckets_x);
+ /* If we were not dealing with screenspace 2D coords we could simple do...
+ * ps->bucketRect[x + (y*ps->buckets_y)] */
+
+ /* please explain?
+ * projCoSS[0] - ps->screenMin[0] : zero origin
+ * ... / ps->screen_width : range from 0.0 to 1.0
+ * ... * ps->buckets_x : use as a bucket index
+ *
+ * Second multiplication does similar but for vertical offset
+ */
+ return ((int)(((projCoSS[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x)) +
+ (((int)(((projCoSS[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y)) *
+ ps->buckets_x);
}
static int project_bucket_offset_safe(const ProjPaintState *ps, const float projCoSS[2])
{
- int bucket_index = project_bucket_offset(ps, projCoSS);
-
- if (bucket_index < 0 || bucket_index >= ps->buckets_x * ps->buckets_y) {
- return -1;
- }
- else {
- return bucket_index;
- }
+ int bucket_index = project_bucket_offset(ps, projCoSS);
+
+ if (bucket_index < 0 || bucket_index >= ps->buckets_x * ps->buckets_y) {
+ return -1;
+ }
+ else {
+ return bucket_index;
+ }
}
static float VecZDepthOrtho(
- const float pt[2],
- const float v1[3], const float v2[3], const float v3[3],
- float w[3])
+ const float pt[2], const float v1[3], const float v2[3], const float v3[3], float w[3])
{
- barycentric_weights_v2(v1, v2, v3, pt, w);
- return (v1[2] * w[0]) + (v2[2] * w[1]) + (v3[2] * w[2]);
+ barycentric_weights_v2(v1, v2, v3, pt, w);
+ return (v1[2] * w[0]) + (v2[2] * w[1]) + (v3[2] * w[2]);
}
static float VecZDepthPersp(
- const float pt[2],
- const float v1[4], const float v2[4], const float v3[4],
- float w[3])
+ const float pt[2], const float v1[4], const float v2[4], const float v3[4], float w[3])
{
- float wtot_inv, wtot;
- float w_tmp[3];
-
- barycentric_weights_v2_persp(v1, v2, v3, pt, w);
- /* for the depth we need the weights to match what
- * barycentric_weights_v2 would return, in this case its easiest just to
- * undo the 4th axis division and make it unit-sum
- *
- * don't call barycentric_weights_v2() because our callers expect 'w'
- * to be weighted from the perspective */
- w_tmp[0] = w[0] * v1[3];
- w_tmp[1] = w[1] * v2[3];
- w_tmp[2] = w[2] * v3[3];
-
- wtot = w_tmp[0] + w_tmp[1] + w_tmp[2];
-
- if (wtot != 0.0f) {
- wtot_inv = 1.0f / wtot;
-
- w_tmp[0] = w_tmp[0] * wtot_inv;
- w_tmp[1] = w_tmp[1] * wtot_inv;
- w_tmp[2] = w_tmp[2] * wtot_inv;
- }
- else /* dummy values for zero area face */
- w_tmp[0] = w_tmp[1] = w_tmp[2] = 1.0f / 3.0f;
- /* done mimicking barycentric_weights_v2() */
-
- return (v1[2] * w_tmp[0]) + (v2[2] * w_tmp[1]) + (v3[2] * w_tmp[2]);
+ float wtot_inv, wtot;
+ float w_tmp[3];
+
+ barycentric_weights_v2_persp(v1, v2, v3, pt, w);
+ /* for the depth we need the weights to match what
+ * barycentric_weights_v2 would return, in this case its easiest just to
+ * undo the 4th axis division and make it unit-sum
+ *
+ * don't call barycentric_weights_v2() because our callers expect 'w'
+ * to be weighted from the perspective */
+ w_tmp[0] = w[0] * v1[3];
+ w_tmp[1] = w[1] * v2[3];
+ w_tmp[2] = w[2] * v3[3];
+
+ wtot = w_tmp[0] + w_tmp[1] + w_tmp[2];
+
+ if (wtot != 0.0f) {
+ wtot_inv = 1.0f / wtot;
+
+ w_tmp[0] = w_tmp[0] * wtot_inv;
+ w_tmp[1] = w_tmp[1] * wtot_inv;
+ w_tmp[2] = w_tmp[2] * wtot_inv;
+ }
+ else /* dummy values for zero area face */
+ w_tmp[0] = w_tmp[1] = w_tmp[2] = 1.0f / 3.0f;
+ /* done mimicking barycentric_weights_v2() */
+
+ return (v1[2] * w_tmp[0]) + (v2[2] * w_tmp[1]) + (v3[2] * w_tmp[2]);
}
-
/* Return the top-most face index that the screen space coord 'pt' touches (or -1) */
-static int project_paint_PickFace(
- const ProjPaintState *ps, const float pt[2],
- float w[3])
+static int project_paint_PickFace(const ProjPaintState *ps, const float pt[2], float w[3])
{
- LinkNode *node;
- float w_tmp[3];
- int bucket_index;
- int best_tri_index = -1;
- float z_depth_best = FLT_MAX, z_depth;
-
- bucket_index = project_bucket_offset_safe(ps, pt);
- if (bucket_index == -1)
- return -1;
-
-
-
- /* we could return 0 for 1 face buckets, as long as this function assumes
- * that the point its testing is only every originated from an existing face */
-
- for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
- const int tri_index = POINTER_AS_INT(node->link);
- const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
- const float *vtri_ss[3] = {
- ps->screenCoords[ps->mloop_eval[lt->tri[0]].v],
- ps->screenCoords[ps->mloop_eval[lt->tri[1]].v],
- ps->screenCoords[ps->mloop_eval[lt->tri[2]].v],
- };
-
-
- if (isect_point_tri_v2(pt, UNPACK3(vtri_ss))) {
- if (ps->is_ortho) {
- z_depth = VecZDepthOrtho(pt, UNPACK3(vtri_ss), w_tmp);
- }
- else {
- z_depth = VecZDepthPersp(pt, UNPACK3(vtri_ss), w_tmp);
- }
-
- if (z_depth < z_depth_best) {
- best_tri_index = tri_index;
- z_depth_best = z_depth;
- copy_v3_v3(w, w_tmp);
- }
- }
- }
-
- /** will be -1 or a valid face. */
- return best_tri_index;
+ LinkNode *node;
+ float w_tmp[3];
+ int bucket_index;
+ int best_tri_index = -1;
+ float z_depth_best = FLT_MAX, z_depth;
+
+ bucket_index = project_bucket_offset_safe(ps, pt);
+ if (bucket_index == -1)
+ return -1;
+
+ /* we could return 0 for 1 face buckets, as long as this function assumes
+ * that the point its testing is only every originated from an existing face */
+
+ for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
+ const int tri_index = POINTER_AS_INT(node->link);
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
+ const float *vtri_ss[3] = {
+ ps->screenCoords[ps->mloop_eval[lt->tri[0]].v],
+ ps->screenCoords[ps->mloop_eval[lt->tri[1]].v],
+ ps->screenCoords[ps->mloop_eval[lt->tri[2]].v],
+ };
+
+ if (isect_point_tri_v2(pt, UNPACK3(vtri_ss))) {
+ if (ps->is_ortho) {
+ z_depth = VecZDepthOrtho(pt, UNPACK3(vtri_ss), w_tmp);
+ }
+ else {
+ z_depth = VecZDepthPersp(pt, UNPACK3(vtri_ss), w_tmp);
+ }
+
+ if (z_depth < z_depth_best) {
+ best_tri_index = tri_index;
+ z_depth_best = z_depth;
+ copy_v3_v3(w, w_tmp);
+ }
+ }
+ }
+
+ /** will be -1 or a valid face. */
+ return best_tri_index;
}
/* Converts a uv coord into a pixel location wrapping if the uv is outside 0-1 range */
static void uvco_to_wrapped_pxco(const float uv[2], int ibuf_x, int ibuf_y, float *x, float *y)
{
- /* use */
- *x = fmodf(uv[0], 1.0f);
- *y = fmodf(uv[1], 1.0f);
+ /* use */
+ *x = fmodf(uv[0], 1.0f);
+ *y = fmodf(uv[1], 1.0f);
- if (*x < 0.0f) *x += 1.0f;
- if (*y < 0.0f) *y += 1.0f;
+ if (*x < 0.0f)
+ *x += 1.0f;
+ if (*y < 0.0f)
+ *y += 1.0f;
- *x = *x * ibuf_x - 0.5f;
- *y = *y * ibuf_y - 0.5f;
+ *x = *x * ibuf_x - 0.5f;
+ *y = *y * ibuf_y - 0.5f;
}
/* 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,
+ unsigned char *rgba,
+ const bool interp)
{
- const MLoopTri *lt;
- const float *lt_tri_uv[3];
- float w[3], uv[2];
- int tri_index;
- Image *ima;
- ImBuf *ibuf;
- int xi, yi;
-
- tri_index = project_paint_PickFace(ps, pt, w);
-
- if (tri_index == -1)
- return 0;
-
- lt = &ps->mlooptri_eval[tri_index];
- PS_LOOPTRI_ASSIGN_UV_3(lt_tri_uv, ps->poly_to_loop_uv, lt);
-
- interp_v2_v2v2v2(uv, UNPACK3(lt_tri_uv), w);
-
- ima = project_paint_face_paint_image(ps, tri_index);
- /** we must have got the imbuf before getting here. */
- ibuf = BKE_image_get_first_ibuf(ima);
- if (!ibuf) return 0;
-
- if (interp) {
- float x, y;
- uvco_to_wrapped_pxco(uv, ibuf->x, ibuf->y, &x, &y);
-
- if (ibuf->rect_float) {
- if (rgba_fp) {
- bilinear_interpolation_color_wrap(ibuf, NULL, rgba_fp, x, y);
- }
- else {
- float rgba_tmp_f[4];
- bilinear_interpolation_color_wrap(ibuf, NULL, rgba_tmp_f, x, y);
- premul_float_to_straight_uchar(rgba, rgba_tmp_f);
- }
- }
- else {
- if (rgba) {
- bilinear_interpolation_color_wrap(ibuf, rgba, NULL, x, y);
- }
- else {
- unsigned char rgba_tmp[4];
- bilinear_interpolation_color_wrap(ibuf, rgba_tmp, NULL, x, y);
- straight_uchar_to_premul_float(rgba_fp, rgba_tmp);
- }
- }
- }
- else {
- //xi = (int)((uv[0]*ibuf->x) + 0.5f);
- //yi = (int)((uv[1]*ibuf->y) + 0.5f);
- //if (xi < 0 || xi >= ibuf->x || yi < 0 || yi >= ibuf->y) return 0;
-
- /* wrap */
- xi = mod_i((int)(uv[0] * ibuf->x), ibuf->x);
- yi = mod_i((int)(uv[1] * ibuf->y), ibuf->y);
-
- if (rgba) {
- if (ibuf->rect_float) {
- const float *rgba_tmp_fp = ibuf->rect_float + (xi + yi * ibuf->x * 4);
- premul_float_to_straight_uchar(rgba, rgba_tmp_fp);
- }
- else {
- *((unsigned int *)rgba) = *(unsigned int *)(((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4));
- }
- }
-
- if (rgba_fp) {
- if (ibuf->rect_float) {
- 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);
- straight_uchar_to_premul_float(rgba_fp, tmp_ch);
- }
- }
- }
- BKE_image_release_ibuf(ima, ibuf, NULL);
- return 1;
+ const MLoopTri *lt;
+ const float *lt_tri_uv[3];
+ float w[3], uv[2];
+ int tri_index;
+ Image *ima;
+ ImBuf *ibuf;
+ int xi, yi;
+
+ tri_index = project_paint_PickFace(ps, pt, w);
+
+ if (tri_index == -1)
+ return 0;
+
+ lt = &ps->mlooptri_eval[tri_index];
+ PS_LOOPTRI_ASSIGN_UV_3(lt_tri_uv, ps->poly_to_loop_uv, lt);
+
+ interp_v2_v2v2v2(uv, UNPACK3(lt_tri_uv), w);
+
+ ima = project_paint_face_paint_image(ps, tri_index);
+ /** we must have got the imbuf before getting here. */
+ ibuf = BKE_image_get_first_ibuf(ima);
+ if (!ibuf)
+ return 0;
+
+ if (interp) {
+ float x, y;
+ uvco_to_wrapped_pxco(uv, ibuf->x, ibuf->y, &x, &y);
+
+ if (ibuf->rect_float) {
+ if (rgba_fp) {
+ bilinear_interpolation_color_wrap(ibuf, NULL, rgba_fp, x, y);
+ }
+ else {
+ float rgba_tmp_f[4];
+ bilinear_interpolation_color_wrap(ibuf, NULL, rgba_tmp_f, x, y);
+ premul_float_to_straight_uchar(rgba, rgba_tmp_f);
+ }
+ }
+ else {
+ if (rgba) {
+ bilinear_interpolation_color_wrap(ibuf, rgba, NULL, x, y);
+ }
+ else {
+ unsigned char rgba_tmp[4];
+ bilinear_interpolation_color_wrap(ibuf, rgba_tmp, NULL, x, y);
+ straight_uchar_to_premul_float(rgba_fp, rgba_tmp);
+ }
+ }
+ }
+ else {
+ //xi = (int)((uv[0]*ibuf->x) + 0.5f);
+ //yi = (int)((uv[1]*ibuf->y) + 0.5f);
+ //if (xi < 0 || xi >= ibuf->x || yi < 0 || yi >= ibuf->y) return 0;
+
+ /* wrap */
+ xi = mod_i((int)(uv[0] * ibuf->x), ibuf->x);
+ yi = mod_i((int)(uv[1] * ibuf->y), ibuf->y);
+
+ if (rgba) {
+ if (ibuf->rect_float) {
+ const float *rgba_tmp_fp = ibuf->rect_float + (xi + yi * ibuf->x * 4);
+ premul_float_to_straight_uchar(rgba, rgba_tmp_fp);
+ }
+ else {
+ *((unsigned int *)rgba) = *(unsigned int *)(((char *)ibuf->rect) +
+ ((xi + yi * ibuf->x) * 4));
+ }
+ }
+
+ if (rgba_fp) {
+ if (ibuf->rect_float) {
+ 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);
+ straight_uchar_to_premul_float(rgba_fp, tmp_ch);
+ }
+ }
+ }
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ return 1;
}
/**
@@ -807,121 +794,125 @@ static bool project_paint_PickColor(
* - `1`: occluded
* - `2`: occluded with `w[3]` weights set (need to know in some cases)
*/
-static int project_paint_occlude_ptv(
- const float pt[3],
- const float v1[4], const float v2[4], const float v3[4],
- float w[3], const bool is_ortho)
+static int project_paint_occlude_ptv(const float pt[3],
+ const float v1[4],
+ const float v2[4],
+ const float v3[4],
+ float w[3],
+ const bool is_ortho)
{
- /* if all are behind us, return false */
- if (v1[2] > pt[2] && v2[2] > pt[2] && v3[2] > pt[2])
- return 0;
-
- /* do a 2D point in try intersection */
- if (!isect_point_tri_v2(pt, v1, v2, v3))
- return 0;
-
-
- /* From here on we know there IS an intersection */
- /* if ALL of the verts are infront of us then we know it intersects ? */
- if (v1[2] < pt[2] && v2[2] < pt[2] && v3[2] < pt[2]) {
- return 1;
- }
- else {
- /* we intersect? - find the exact depth at the point of intersection */
- /* Is this point is occluded by another face? */
- if (is_ortho) {
- if (VecZDepthOrtho(pt, v1, v2, v3, w) < pt[2]) return 2;
- }
- else {
- if (VecZDepthPersp(pt, v1, v2, v3, w) < pt[2]) return 2;
- }
- }
- return -1;
+ /* if all are behind us, return false */
+ if (v1[2] > pt[2] && v2[2] > pt[2] && v3[2] > pt[2])
+ return 0;
+
+ /* do a 2D point in try intersection */
+ if (!isect_point_tri_v2(pt, v1, v2, v3))
+ return 0;
+
+ /* From here on we know there IS an intersection */
+ /* if ALL of the verts are infront of us then we know it intersects ? */
+ if (v1[2] < pt[2] && v2[2] < pt[2] && v3[2] < pt[2]) {
+ return 1;
+ }
+ else {
+ /* we intersect? - find the exact depth at the point of intersection */
+ /* Is this point is occluded by another face? */
+ if (is_ortho) {
+ if (VecZDepthOrtho(pt, v1, v2, v3, w) < pt[2])
+ return 2;
+ }
+ else {
+ if (VecZDepthPersp(pt, v1, v2, v3, w) < pt[2])
+ return 2;
+ }
+ }
+ return -1;
}
-
-static int project_paint_occlude_ptv_clip(
- const float pt[3],
- const float v1[4], const float v2[4], const float v3[4],
- const float v1_3d[3], const float v2_3d[3], const float v3_3d[3],
- float w[3], const bool is_ortho, RegionView3D *rv3d)
+static int project_paint_occlude_ptv_clip(const float pt[3],
+ const float v1[4],
+ const float v2[4],
+ const float v3[4],
+ const float v1_3d[3],
+ const float v2_3d[3],
+ const float v3_3d[3],
+ float w[3],
+ const bool is_ortho,
+ RegionView3D *rv3d)
{
- float wco[3];
- int ret = project_paint_occlude_ptv(pt, v1, v2, v3, w, is_ortho);
+ float wco[3];
+ int ret = project_paint_occlude_ptv(pt, v1, v2, v3, w, is_ortho);
- if (ret <= 0)
- return ret;
+ if (ret <= 0)
+ return ret;
- if (ret == 1) { /* weights not calculated */
- if (is_ortho) {
- barycentric_weights_v2(v1, v2, v3, pt, w);
- }
- else {
- barycentric_weights_v2_persp(v1, v2, v3, pt, w);
- }
- }
+ if (ret == 1) { /* weights not calculated */
+ if (is_ortho) {
+ barycentric_weights_v2(v1, v2, v3, pt, w);
+ }
+ else {
+ barycentric_weights_v2_persp(v1, v2, v3, pt, w);
+ }
+ }
- /* Test if we're in the clipped area, */
- interp_v3_v3v3v3(wco, v1_3d, v2_3d, v3_3d, w);
+ /* Test if we're in the clipped area, */
+ interp_v3_v3v3v3(wco, v1_3d, v2_3d, v3_3d, w);
- if (!ED_view3d_clipping_test(rv3d, wco, true)) {
- return 1;
- }
+ if (!ED_view3d_clipping_test(rv3d, wco, true)) {
+ return 1;
+ }
- return -1;
+ return -1;
}
-
/* Check if a screenspace location is occluded by any other faces
* check, pixelScreenCo must be in screenspace, its Z-Depth only needs to be used for comparison
* and doesn't need to be correct in relation to X and Y coords
* (this is the case in perspective view) */
-static bool project_bucket_point_occluded(
- const ProjPaintState *ps, LinkNode *bucketFace,
- const int orig_face, const float pixelScreenCo[4])
+static bool project_bucket_point_occluded(const ProjPaintState *ps,
+ LinkNode *bucketFace,
+ const int orig_face,
+ const float pixelScreenCo[4])
{
- int isect_ret;
- const bool do_clip = ps->rv3d ? (ps->rv3d->rflag & RV3D_CLIPPING) != 0 : 0;
-
- /* we could return 0 for 1 face buckets, as long as this function assumes
- * that the point its testing is only every originated from an existing face */
-
- for (; bucketFace; bucketFace = bucketFace->next) {
- const int tri_index = POINTER_AS_INT(bucketFace->link);
-
- if (orig_face != tri_index) {
- const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
- const float *vtri_ss[3] = {
- ps->screenCoords[ps->mloop_eval[lt->tri[0]].v],
- ps->screenCoords[ps->mloop_eval[lt->tri[1]].v],
- ps->screenCoords[ps->mloop_eval[lt->tri[2]].v],
- };
- float w[3];
-
- if (do_clip) {
- const float *vtri_co[3] = {
- ps->mvert_eval[ps->mloop_eval[lt->tri[0]].v].co,
- ps->mvert_eval[ps->mloop_eval[lt->tri[1]].v].co,
- ps->mvert_eval[ps->mloop_eval[lt->tri[2]].v].co,
- };
- isect_ret = project_paint_occlude_ptv_clip(
- pixelScreenCo, UNPACK3(vtri_ss), UNPACK3(vtri_co),
- w, ps->is_ortho, ps->rv3d);
- }
- else {
- isect_ret = project_paint_occlude_ptv(
- pixelScreenCo, UNPACK3(vtri_ss),
- w, ps->is_ortho);
- }
-
- if (isect_ret >= 1) {
- /* TODO - we may want to cache the first hit,
- * it is not possible to swap the face order in the list anymore */
- return true;
- }
- }
- }
- return false;
+ int isect_ret;
+ const bool do_clip = ps->rv3d ? (ps->rv3d->rflag & RV3D_CLIPPING) != 0 : 0;
+
+ /* we could return 0 for 1 face buckets, as long as this function assumes
+ * that the point its testing is only every originated from an existing face */
+
+ for (; bucketFace; bucketFace = bucketFace->next) {
+ const int tri_index = POINTER_AS_INT(bucketFace->link);
+
+ if (orig_face != tri_index) {
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
+ const float *vtri_ss[3] = {
+ ps->screenCoords[ps->mloop_eval[lt->tri[0]].v],
+ ps->screenCoords[ps->mloop_eval[lt->tri[1]].v],
+ ps->screenCoords[ps->mloop_eval[lt->tri[2]].v],
+ };
+ float w[3];
+
+ if (do_clip) {
+ const float *vtri_co[3] = {
+ ps->mvert_eval[ps->mloop_eval[lt->tri[0]].v].co,
+ ps->mvert_eval[ps->mloop_eval[lt->tri[1]].v].co,
+ ps->mvert_eval[ps->mloop_eval[lt->tri[2]].v].co,
+ };
+ isect_ret = project_paint_occlude_ptv_clip(
+ pixelScreenCo, UNPACK3(vtri_ss), UNPACK3(vtri_co), w, ps->is_ortho, ps->rv3d);
+ }
+ else {
+ isect_ret = project_paint_occlude_ptv(pixelScreenCo, UNPACK3(vtri_ss), w, ps->is_ortho);
+ }
+
+ if (isect_ret >= 1) {
+ /* TODO - we may want to cache the first hit,
+ * it is not possible to swap the face order in the list anymore */
+ return true;
+ }
+ }
+ }
+ return false;
}
/* Basic line intersection, could move to math_geom.c, 2 points with a horizontal line
@@ -931,77 +922,77 @@ static bool project_bucket_point_occluded(
#define ISECT_TRUE_P2 3
static int line_isect_y(const float p1[2], const float p2[2], const float y_level, float *x_isect)
{
- float y_diff;
-
- /* are we touching the first point? - no interpolation needed */
- if (y_level == p1[1]) {
- *x_isect = p1[0];
- return ISECT_TRUE_P1;
- }
- /* are we touching the second point? - no interpolation needed */
- if (y_level == p2[1]) {
- *x_isect = p2[0];
- return ISECT_TRUE_P2;
- }
-
- /** yuck, horizontal line, we cant do much here. */
- y_diff = fabsf(p1[1] - p2[1]);
-
- if (y_diff < 0.000001f) {
- *x_isect = (p1[0] + p2[0]) * 0.5f;
- return ISECT_TRUE;
- }
-
- if (p1[1] > y_level && p2[1] < y_level) {
- /* (p1[1] - p2[1]); */
- *x_isect = (p2[0] * (p1[1] - y_level) + p1[0] * (y_level - p2[1])) / y_diff;
- return ISECT_TRUE;
- }
- else if (p1[1] < y_level && p2[1] > y_level) {
- /* (p2[1] - p1[1]); */
- *x_isect = (p2[0] * (y_level - p1[1]) + p1[0] * (p2[1] - y_level)) / y_diff;
- return ISECT_TRUE;
- }
- else {
- return 0;
- }
+ float y_diff;
+
+ /* are we touching the first point? - no interpolation needed */
+ if (y_level == p1[1]) {
+ *x_isect = p1[0];
+ return ISECT_TRUE_P1;
+ }
+ /* are we touching the second point? - no interpolation needed */
+ if (y_level == p2[1]) {
+ *x_isect = p2[0];
+ return ISECT_TRUE_P2;
+ }
+
+ /** yuck, horizontal line, we cant do much here. */
+ y_diff = fabsf(p1[1] - p2[1]);
+
+ if (y_diff < 0.000001f) {
+ *x_isect = (p1[0] + p2[0]) * 0.5f;
+ return ISECT_TRUE;
+ }
+
+ if (p1[1] > y_level && p2[1] < y_level) {
+ /* (p1[1] - p2[1]); */
+ *x_isect = (p2[0] * (p1[1] - y_level) + p1[0] * (y_level - p2[1])) / y_diff;
+ return ISECT_TRUE;
+ }
+ else if (p1[1] < y_level && p2[1] > y_level) {
+ /* (p2[1] - p1[1]); */
+ *x_isect = (p2[0] * (y_level - p1[1]) + p1[0] * (p2[1] - y_level)) / y_diff;
+ return ISECT_TRUE;
+ }
+ else {
+ return 0;
+ }
}
static int line_isect_x(const float p1[2], const float p2[2], const float x_level, float *y_isect)
{
- float x_diff;
-
- if (x_level == p1[0]) { /* are we touching the first point? - no interpolation needed */
- *y_isect = p1[1];
- return ISECT_TRUE_P1;
- }
- if (x_level == p2[0]) { /* are we touching the second point? - no interpolation needed */
- *y_isect = p2[1];
- return ISECT_TRUE_P2;
- }
-
- /* yuck, horizontal line, we cant do much here */
- x_diff = fabsf(p1[0] - p2[0]);
-
- /* yuck, vertical line, we cant do much here */
- if (x_diff < 0.000001f) {
- *y_isect = (p1[0] + p2[0]) * 0.5f;
- return ISECT_TRUE;
- }
-
- if (p1[0] > x_level && p2[0] < x_level) {
- /* (p1[0] - p2[0]); */
- *y_isect = (p2[1] * (p1[0] - x_level) + p1[1] * (x_level - p2[0])) / x_diff;
- return ISECT_TRUE;
- }
- else if (p1[0] < x_level && p2[0] > x_level) {
- /* (p2[0] - p1[0]); */
- *y_isect = (p2[1] * (x_level - p1[0]) + p1[1] * (p2[0] - x_level)) / x_diff;
- return ISECT_TRUE;
- }
- else {
- return 0;
- }
+ float x_diff;
+
+ if (x_level == p1[0]) { /* are we touching the first point? - no interpolation needed */
+ *y_isect = p1[1];
+ return ISECT_TRUE_P1;
+ }
+ if (x_level == p2[0]) { /* are we touching the second point? - no interpolation needed */
+ *y_isect = p2[1];
+ return ISECT_TRUE_P2;
+ }
+
+ /* yuck, horizontal line, we cant do much here */
+ x_diff = fabsf(p1[0] - p2[0]);
+
+ /* yuck, vertical line, we cant do much here */
+ if (x_diff < 0.000001f) {
+ *y_isect = (p1[0] + p2[0]) * 0.5f;
+ return ISECT_TRUE;
+ }
+
+ if (p1[0] > x_level && p2[0] < x_level) {
+ /* (p1[0] - p2[0]); */
+ *y_isect = (p2[1] * (p1[0] - x_level) + p1[1] * (x_level - p2[0])) / x_diff;
+ return ISECT_TRUE;
+ }
+ else if (p1[0] < x_level && p2[0] > x_level) {
+ /* (p2[0] - p1[0]); */
+ *y_isect = (p2[1] * (x_level - p1[0]) + p1[1] * (p2[0] - x_level)) / x_diff;
+ return ISECT_TRUE;
+ }
+ else {
+ return 0;
+ }
}
/* simple func use for comparing UV locations to check if there are seams.
@@ -1011,389 +1002,394 @@ static int line_isect_x(const float p1[2], const float p2[2], const float x_leve
#ifndef PROJ_DEBUG_NOSEAMBLEED
static bool cmp_uv(const float vec2a[2], const float vec2b[2])
{
- /* if the UV's are not between 0.0 and 1.0 */
- float xa = fmodf(vec2a[0], 1.0f);
- float ya = fmodf(vec2a[1], 1.0f);
+ /* if the UV's are not between 0.0 and 1.0 */
+ float xa = fmodf(vec2a[0], 1.0f);
+ float ya = fmodf(vec2a[1], 1.0f);
- float xb = fmodf(vec2b[0], 1.0f);
- float yb = fmodf(vec2b[1], 1.0f);
+ float xb = fmodf(vec2b[0], 1.0f);
+ float yb = fmodf(vec2b[1], 1.0f);
- if (xa < 0.0f) xa += 1.0f;
- if (ya < 0.0f) ya += 1.0f;
+ if (xa < 0.0f)
+ xa += 1.0f;
+ if (ya < 0.0f)
+ ya += 1.0f;
- if (xb < 0.0f) xb += 1.0f;
- if (yb < 0.0f) yb += 1.0f;
+ if (xb < 0.0f)
+ xb += 1.0f;
+ if (yb < 0.0f)
+ 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)) ? 1 :
+ 0;
}
#endif
/* set min_px and max_px to the image space bounds of the UV coords
* return zero if there is no area in the returned rectangle */
#ifndef PROJ_DEBUG_NOSEAMBLEED
-static bool pixel_bounds_uv(
- const float uv_quad[4][2],
- rcti *bounds_px,
- const int ibuf_x, const int ibuf_y
- )
+static bool pixel_bounds_uv(const float uv_quad[4][2],
+ rcti *bounds_px,
+ const int ibuf_x,
+ const int ibuf_y)
{
- /* UV bounds */
- float min_uv[2], max_uv[2];
+ /* UV bounds */
+ float min_uv[2], max_uv[2];
- INIT_MINMAX2(min_uv, max_uv);
+ INIT_MINMAX2(min_uv, max_uv);
- minmax_v2v2_v2(min_uv, max_uv, uv_quad[0]);
- minmax_v2v2_v2(min_uv, max_uv, uv_quad[1]);
- minmax_v2v2_v2(min_uv, max_uv, uv_quad[2]);
- minmax_v2v2_v2(min_uv, max_uv, uv_quad[3]);
+ minmax_v2v2_v2(min_uv, max_uv, uv_quad[0]);
+ minmax_v2v2_v2(min_uv, max_uv, uv_quad[1]);
+ minmax_v2v2_v2(min_uv, max_uv, uv_quad[2]);
+ minmax_v2v2_v2(min_uv, max_uv, uv_quad[3]);
- bounds_px->xmin = (int)(ibuf_x * min_uv[0]);
- bounds_px->ymin = (int)(ibuf_y * min_uv[1]);
+ bounds_px->xmin = (int)(ibuf_x * min_uv[0]);
+ bounds_px->ymin = (int)(ibuf_y * min_uv[1]);
- bounds_px->xmax = (int)(ibuf_x * max_uv[0]) + 1;
- bounds_px->ymax = (int)(ibuf_y * max_uv[1]) + 1;
+ bounds_px->xmax = (int)(ibuf_x * max_uv[0]) + 1;
+ bounds_px->ymax = (int)(ibuf_y * max_uv[1]) + 1;
- /*printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]);*/
+ /*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;
+ /* face uses no UV area when quantized to pixels? */
+ return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1;
}
#endif
-static bool pixel_bounds_array(float (*uv)[2], rcti *bounds_px, const int ibuf_x, const int ibuf_y, int tot)
+static bool pixel_bounds_array(
+ float (*uv)[2], rcti *bounds_px, const int ibuf_x, const int ibuf_y, int tot)
{
- /* UV bounds */
- float min_uv[2], max_uv[2];
+ /* UV bounds */
+ float min_uv[2], max_uv[2];
- if (tot == 0) {
- return 0;
- }
+ if (tot == 0) {
+ return 0;
+ }
- INIT_MINMAX2(min_uv, max_uv);
+ INIT_MINMAX2(min_uv, max_uv);
- while (tot--) {
- minmax_v2v2_v2(min_uv, max_uv, (*uv));
- uv++;
- }
+ while (tot--) {
+ minmax_v2v2_v2(min_uv, max_uv, (*uv));
+ uv++;
+ }
- bounds_px->xmin = (int)(ibuf_x * min_uv[0]);
- bounds_px->ymin = (int)(ibuf_y * min_uv[1]);
+ bounds_px->xmin = (int)(ibuf_x * min_uv[0]);
+ bounds_px->ymin = (int)(ibuf_y * min_uv[1]);
- bounds_px->xmax = (int)(ibuf_x * max_uv[0]) + 1;
- bounds_px->ymax = (int)(ibuf_y * max_uv[1]) + 1;
+ bounds_px->xmax = (int)(ibuf_x * max_uv[0]) + 1;
+ bounds_px->ymax = (int)(ibuf_y * max_uv[1]) + 1;
- /*printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]);*/
+ /*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;
+ /* face uses no UV area when quantized to pixels? */
+ return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1;
}
#ifndef PROJ_DEBUG_NOSEAMBLEED
static void project_face_winding_init(const ProjPaintState *ps, const int tri_index)
{
- /* detect the winding of faces in uv space */
- const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
- const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt) };
- float winding = cross_tri_v2(lt_tri_uv[0], lt_tri_uv[1], lt_tri_uv[2]);
+ /* detect the winding of faces in uv space */
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
+ const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
+ float winding = cross_tri_v2(lt_tri_uv[0], lt_tri_uv[1], lt_tri_uv[2]);
- if (winding > 0)
- ps->faceWindingFlags[tri_index] |= PROJ_FACE_WINDING_CW;
+ if (winding > 0)
+ ps->faceWindingFlags[tri_index] |= PROJ_FACE_WINDING_CW;
- ps->faceWindingFlags[tri_index] |= PROJ_FACE_WINDING_INIT;
+ ps->faceWindingFlags[tri_index] |= PROJ_FACE_WINDING_INIT;
}
/* This function returns 1 if this face has a seam along the 2 face-vert indices
* 'orig_i1_fidx' and 'orig_i2_fidx' */
-static bool check_seam(
- const ProjPaintState *ps,
- const int orig_face, const int orig_i1_fidx, const int orig_i2_fidx,
- int *other_face, int *orig_fidx)
+static bool check_seam(const ProjPaintState *ps,
+ const int orig_face,
+ const int orig_i1_fidx,
+ const int orig_i2_fidx,
+ int *other_face,
+ int *orig_fidx)
{
- 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;
- LinkNode *node;
- /* index in face */
- int i1_fidx = -1, i2_fidx = -1;
-
- for (node = ps->vertFaces[i1]; node; node = node->next) {
- const int tri_index = POINTER_AS_INT(node->link);
-
- if (tri_index != orig_face) {
- const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
- const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
- /* could check if the 2 faces images match here,
- * but then there wouldn't be a way to return the opposite face's info */
-
-
- /* We need to know the order of the verts in the adjacent face
- * set the i1_fidx and i2_fidx to (0,1,2,3) */
- i1_fidx = BKE_MESH_TESSTRI_VINDEX_ORDER(lt_vtri, i1);
- i2_fidx = BKE_MESH_TESSTRI_VINDEX_ORDER(lt_vtri, i2);
-
- /* Only need to check if 'i2_fidx' is valid because we know i1_fidx is the same vert on both faces */
- if (i2_fidx != -1) {
- const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt) };
- Image *tpage = project_paint_face_paint_image(ps, tri_index);
- Image *orig_tpage = project_paint_face_paint_image(ps, orig_face);
-
- BLI_assert(i1_fidx != -1);
-
- /* This IS an adjacent face!, now lets check if the UVs are ok */
-
- /* set up the other face */
- *other_face = tri_index;
-
- /* we check if difference is 1 here, else we might have a case of edge 2-0 for a tri */
- *orig_fidx = (i1_fidx < i2_fidx && (i2_fidx - i1_fidx == 1)) ? i1_fidx : i2_fidx;
-
- /* initialize face winding if needed */
- if ((ps->faceWindingFlags[tri_index] & PROJ_FACE_WINDING_INIT) == 0)
- project_face_winding_init(ps, tri_index);
-
- /* first test if they have the same image */
- if ((orig_tpage == tpage) &&
- cmp_uv(orig_lt_tri_uv[orig_i1_fidx], lt_tri_uv[i1_fidx]) &&
- cmp_uv(orig_lt_tri_uv[orig_i2_fidx], lt_tri_uv[i2_fidx]))
- {
- /* if faces don't have the same winding in uv space,
- * 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;
- }
-
- // printf("SEAM (NONE)\n");
- return 0;
-
- }
- else {
- // printf("SEAM (UV GAP)\n");
- return 1;
- }
- }
- }
- }
- // printf("SEAM (NO FACE)\n");
- *other_face = -1;
- return 1;
+ 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;
+ LinkNode *node;
+ /* index in face */
+ int i1_fidx = -1, i2_fidx = -1;
+
+ for (node = ps->vertFaces[i1]; node; node = node->next) {
+ const int tri_index = POINTER_AS_INT(node->link);
+
+ if (tri_index != orig_face) {
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
+ const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
+ /* could check if the 2 faces images match here,
+ * but then there wouldn't be a way to return the opposite face's info */
+
+ /* We need to know the order of the verts in the adjacent face
+ * set the i1_fidx and i2_fidx to (0,1,2,3) */
+ i1_fidx = BKE_MESH_TESSTRI_VINDEX_ORDER(lt_vtri, i1);
+ i2_fidx = BKE_MESH_TESSTRI_VINDEX_ORDER(lt_vtri, i2);
+
+ /* Only need to check if 'i2_fidx' is valid because we know i1_fidx is the same vert on both faces */
+ if (i2_fidx != -1) {
+ const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
+ Image *tpage = project_paint_face_paint_image(ps, tri_index);
+ Image *orig_tpage = project_paint_face_paint_image(ps, orig_face);
+
+ BLI_assert(i1_fidx != -1);
+
+ /* This IS an adjacent face!, now lets check if the UVs are ok */
+
+ /* set up the other face */
+ *other_face = tri_index;
+
+ /* we check if difference is 1 here, else we might have a case of edge 2-0 for a tri */
+ *orig_fidx = (i1_fidx < i2_fidx && (i2_fidx - i1_fidx == 1)) ? i1_fidx : i2_fidx;
+
+ /* initialize face winding if needed */
+ if ((ps->faceWindingFlags[tri_index] & PROJ_FACE_WINDING_INIT) == 0)
+ project_face_winding_init(ps, tri_index);
+
+ /* first test if they have the same image */
+ if ((orig_tpage == tpage) && cmp_uv(orig_lt_tri_uv[orig_i1_fidx], lt_tri_uv[i1_fidx]) &&
+ cmp_uv(orig_lt_tri_uv[orig_i2_fidx], lt_tri_uv[i2_fidx])) {
+ /* if faces don't have the same winding in uv space,
+ * 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;
+ }
+
+ // printf("SEAM (NONE)\n");
+ return 0;
+ }
+ else {
+ // printf("SEAM (UV GAP)\n");
+ return 1;
+ }
+ }
+ }
+ }
+ // printf("SEAM (NO FACE)\n");
+ *other_face = -1;
+ return 1;
}
-static VertSeam *find_adjacent_seam(const ProjPaintState *ps, uint loop_index, uint vert_index, VertSeam **r_seam)
+static VertSeam *find_adjacent_seam(const ProjPaintState *ps,
+ uint loop_index,
+ uint vert_index,
+ VertSeam **r_seam)
{
- ListBase *vert_seams = &ps->vertSeams[vert_index];
- VertSeam *seam = vert_seams->first;
- VertSeam *adjacent = NULL;
-
- while (seam->loop != loop_index) {
- seam = seam->next;
- }
-
- if (r_seam) {
- *r_seam = seam;
- }
-
- /* Circulate through the (sorted) vert seam array, in the direction of the seam normal,
- * until we find the first opposing seam, matching in UV space. */
- if (seam->normal_cw) {
- LISTBASE_CIRCULAR_BACKWARD_BEGIN(vert_seams, adjacent, seam)
- {
- if ((adjacent->normal_cw != seam->normal_cw) &&
- cmp_uv(adjacent->uv, seam->uv))
- {
- break;
- }
- }
- LISTBASE_CIRCULAR_BACKWARD_END(vert_seams, adjacent, seam);
- }
- else {
- LISTBASE_CIRCULAR_FORWARD_BEGIN(vert_seams, adjacent, seam)
- {
- if ((adjacent->normal_cw != seam->normal_cw) &&
- cmp_uv(adjacent->uv, seam->uv))
- {
- break;
- }
- }
- LISTBASE_CIRCULAR_FORWARD_END(vert_seams, adjacent, seam);
- }
-
- BLI_assert(adjacent);
-
- return adjacent;
+ ListBase *vert_seams = &ps->vertSeams[vert_index];
+ VertSeam *seam = vert_seams->first;
+ VertSeam *adjacent = NULL;
+
+ while (seam->loop != loop_index) {
+ seam = seam->next;
+ }
+
+ if (r_seam) {
+ *r_seam = seam;
+ }
+
+ /* Circulate through the (sorted) vert seam array, in the direction of the seam normal,
+ * until we find the first opposing seam, matching in UV space. */
+ if (seam->normal_cw) {
+ LISTBASE_CIRCULAR_BACKWARD_BEGIN (vert_seams, adjacent, seam) {
+ if ((adjacent->normal_cw != seam->normal_cw) && cmp_uv(adjacent->uv, seam->uv)) {
+ break;
+ }
+ }
+ LISTBASE_CIRCULAR_BACKWARD_END(vert_seams, adjacent, seam);
+ }
+ else {
+ LISTBASE_CIRCULAR_FORWARD_BEGIN (vert_seams, adjacent, seam) {
+ if ((adjacent->normal_cw != seam->normal_cw) && cmp_uv(adjacent->uv, seam->uv)) {
+ break;
+ }
+ }
+ LISTBASE_CIRCULAR_FORWARD_END(vert_seams, adjacent, seam);
+ }
+
+ BLI_assert(adjacent);
+
+ return adjacent;
}
/* Computes the normal of two seams at their intersection,
* and returns the angle between the seam and its normal. */
static float compute_seam_normal(VertSeam *seam, VertSeam *adj, float r_no[2])
{
- const float PI_2 = M_PI * 2.0f;
- float angle[2];
- float angle_rel, angle_no;
+ const float PI_2 = M_PI * 2.0f;
+ float angle[2];
+ float angle_rel, angle_no;
- if (seam->normal_cw) {
- angle[0] = adj->angle;
- angle[1] = seam->angle;
- }
- else {
- angle[0] = seam->angle;
- angle[1] = adj->angle;
- }
+ if (seam->normal_cw) {
+ angle[0] = adj->angle;
+ angle[1] = seam->angle;
+ }
+ else {
+ angle[0] = seam->angle;
+ angle[1] = adj->angle;
+ }
- angle_rel = angle[1] - angle[0];
+ angle_rel = angle[1] - angle[0];
- if (angle_rel < 0.0f) {
- angle_rel += PI_2;
- }
+ if (angle_rel < 0.0f) {
+ angle_rel += PI_2;
+ }
- angle_rel *= 0.5f;
+ angle_rel *= 0.5f;
- angle_no = angle_rel + angle[0];
+ angle_no = angle_rel + angle[0];
- if (angle_no > M_PI) {
- angle_no -= PI_2;
- }
+ if (angle_no > M_PI) {
+ angle_no -= PI_2;
+ }
- r_no[0] = cosf(angle_no);
- r_no[1] = sinf(angle_no);
+ r_no[0] = cosf(angle_no);
+ r_no[1] = sinf(angle_no);
- return angle_rel;
+ return angle_rel;
}
/* Calculate outset UV's, this is not the same as simply scaling the UVs,
* since the outset coords are a margin that keep an even distance from the original UV's,
* note that the image aspect is taken into account */
-static void uv_image_outset(
- const ProjPaintState *ps, float (*orig_uv)[2], float (*puv)[2],
- uint tri_index, const int ibuf_x, const int ibuf_y)
+static void uv_image_outset(const ProjPaintState *ps,
+ float (*orig_uv)[2],
+ float (*puv)[2],
+ uint tri_index,
+ const int ibuf_x,
+ const int ibuf_y)
{
- int fidx[2];
- uint loop_index;
- uint vert[2];
- const MLoopTri *ltri = &ps->mlooptri_eval[tri_index];
+ int fidx[2];
+ uint loop_index;
+ uint vert[2];
+ const MLoopTri *ltri = &ps->mlooptri_eval[tri_index];
- float ibuf_inv[2];
+ float ibuf_inv[2];
- ibuf_inv[0] = 1.0f / (float)ibuf_x;
- ibuf_inv[1] = 1.0f / (float)ibuf_y;
+ ibuf_inv[0] = 1.0f / (float)ibuf_x;
+ ibuf_inv[1] = 1.0f / (float)ibuf_y;
- for (fidx[0] = 0; fidx[0] < 3; fidx[0]++) {
- LoopSeamData *seam_data;
- float (*seam_uvs)[2];
- float ang[2];
+ for (fidx[0] = 0; fidx[0] < 3; fidx[0]++) {
+ LoopSeamData *seam_data;
+ float(*seam_uvs)[2];
+ float ang[2];
- if ((ps->faceSeamFlags[tri_index] & (PROJ_FACE_SEAM0 << fidx[0])) == 0) {
- continue;
- }
+ if ((ps->faceSeamFlags[tri_index] & (PROJ_FACE_SEAM0 << fidx[0])) == 0) {
+ continue;
+ }
- loop_index = ltri->tri[fidx[0]];
+ loop_index = ltri->tri[fidx[0]];
- seam_data = &ps->loopSeamData[loop_index];
- seam_uvs = seam_data->seam_uvs;
+ seam_data = &ps->loopSeamData[loop_index];
+ seam_uvs = seam_data->seam_uvs;
- if (seam_uvs[0][0] != FLT_MAX) {
- continue;
- }
+ if (seam_uvs[0][0] != FLT_MAX) {
+ continue;
+ }
- fidx[1] = (fidx[0] == 2) ? 0 : fidx[0] + 1;
+ fidx[1] = (fidx[0] == 2) ? 0 : fidx[0] + 1;
- vert[0] = ps->mloop_eval[loop_index].v;
- vert[1] = ps->mloop_eval[ltri->tri[fidx[1]]].v;
+ vert[0] = ps->mloop_eval[loop_index].v;
+ vert[1] = ps->mloop_eval[ltri->tri[fidx[1]]].v;
- for (uint i = 0; i < 2; i++) {
- VertSeam *seam;
- VertSeam *adj = find_adjacent_seam(ps, loop_index, vert[i], &seam);
- float no[2];
- float len_fact;
- float tri_ang;
+ for (uint i = 0; i < 2; i++) {
+ VertSeam *seam;
+ VertSeam *adj = find_adjacent_seam(ps, loop_index, vert[i], &seam);
+ float no[2];
+ float len_fact;
+ float tri_ang;
- ang[i] = compute_seam_normal(seam, adj, no);
- tri_ang = ang[i] - M_PI_2;
+ ang[i] = compute_seam_normal(seam, adj, no);
+ tri_ang = ang[i] - M_PI_2;
- if (tri_ang > 0.0f) {
- const float dist = ps->seam_bleed_px * tanf(tri_ang);
- seam_data->corner_dist_sq[i] = SQUARE(dist);
- }
- else {
- seam_data->corner_dist_sq[i] = 0.0f;
- }
+ if (tri_ang > 0.0f) {
+ const float dist = ps->seam_bleed_px * tanf(tri_ang);
+ seam_data->corner_dist_sq[i] = SQUARE(dist);
+ }
+ else {
+ seam_data->corner_dist_sq[i] = 0.0f;
+ }
- len_fact = cosf(tri_ang);
- len_fact = UNLIKELY(len_fact < FLT_EPSILON) ? FLT_MAX : (1.0f / len_fact);
+ len_fact = cosf(tri_ang);
+ len_fact = UNLIKELY(len_fact < FLT_EPSILON) ? FLT_MAX : (1.0f / len_fact);
- /* Clamp the length factor, see: T62236. */
- len_fact = MIN2(len_fact, 10.0f);
+ /* Clamp the length factor, see: T62236. */
+ len_fact = MIN2(len_fact, 10.0f);
- mul_v2_fl(no, ps->seam_bleed_px * len_fact);
+ mul_v2_fl(no, ps->seam_bleed_px * len_fact);
- add_v2_v2v2(seam_data->seam_puvs[i], puv[fidx[i]], no);
+ add_v2_v2v2(seam_data->seam_puvs[i], puv[fidx[i]], no);
- mul_v2_v2v2(seam_uvs[i], seam_data->seam_puvs[i], ibuf_inv);
- }
+ mul_v2_v2v2(seam_uvs[i], seam_data->seam_puvs[i], ibuf_inv);
+ }
- /* Handle convergent normals (can self-intersect). */
- if ((ang[0] + ang[1]) < M_PI) {
- if (isect_seg_seg_v2_simple(orig_uv[fidx[0]], seam_uvs[0], orig_uv[fidx[1]], seam_uvs[1])) {
- float isect_co[2];
+ /* Handle convergent normals (can self-intersect). */
+ if ((ang[0] + ang[1]) < M_PI) {
+ if (isect_seg_seg_v2_simple(orig_uv[fidx[0]], seam_uvs[0], orig_uv[fidx[1]], seam_uvs[1])) {
+ float isect_co[2];
- isect_seg_seg_v2_point(orig_uv[fidx[0]], seam_uvs[0], orig_uv[fidx[1]], seam_uvs[1], isect_co);
+ isect_seg_seg_v2_point(
+ orig_uv[fidx[0]], seam_uvs[0], orig_uv[fidx[1]], seam_uvs[1], isect_co);
- copy_v2_v2(seam_uvs[0], isect_co);
- copy_v2_v2(seam_uvs[1], isect_co);
- }
- }
-
- }
+ copy_v2_v2(seam_uvs[0], isect_co);
+ copy_v2_v2(seam_uvs[1], isect_co);
+ }
+ }
+ }
}
-static void insert_seam_vert_array(
- const ProjPaintState *ps, MemArena *arena, const int tri_index,
- const int fidx1, const int ibuf_x, const int ibuf_y)
+static void insert_seam_vert_array(const ProjPaintState *ps,
+ MemArena *arena,
+ const int tri_index,
+ const int fidx1,
+ const int ibuf_x,
+ const int ibuf_y)
{
- const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
- const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
- const int fidx[2] = {fidx1, ((fidx1 + 1) % 3)};
- float vec[2];
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
+ const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
+ const int fidx[2] = {fidx1, ((fidx1 + 1) % 3)};
+ float vec[2];
- VertSeam *vseam = BLI_memarena_alloc(arena, sizeof(VertSeam) * 2);
+ VertSeam *vseam = BLI_memarena_alloc(arena, sizeof(VertSeam) * 2);
- vseam->prev = NULL;
- vseam->next = NULL;
+ vseam->prev = NULL;
+ vseam->next = NULL;
- vseam->tri = tri_index;
- vseam->loop = lt->tri[fidx[0]];
+ vseam->tri = tri_index;
+ vseam->loop = lt->tri[fidx[0]];
- sub_v2_v2v2(vec, lt_tri_uv[fidx[1]], lt_tri_uv[fidx[0]]);
- vec[0] *= ibuf_x;
- vec[1] *= ibuf_y;
- vseam->angle = atan2f(vec[1], vec[0]);
+ sub_v2_v2v2(vec, lt_tri_uv[fidx[1]], lt_tri_uv[fidx[0]]);
+ vec[0] *= ibuf_x;
+ vec[1] *= ibuf_y;
+ vseam->angle = atan2f(vec[1], vec[0]);
- /* If face windings are not initialized, something must be wrong. */
- BLI_assert((ps->faceWindingFlags[tri_index] & PROJ_FACE_WINDING_INIT) != 0);
- vseam->normal_cw = (ps->faceWindingFlags[tri_index] & PROJ_FACE_WINDING_CW);
+ /* If face windings are not initialized, something must be wrong. */
+ BLI_assert((ps->faceWindingFlags[tri_index] & PROJ_FACE_WINDING_INIT) != 0);
+ vseam->normal_cw = (ps->faceWindingFlags[tri_index] & PROJ_FACE_WINDING_CW);
- copy_v2_v2(vseam->uv, lt_tri_uv[fidx[0]]);
+ copy_v2_v2(vseam->uv, lt_tri_uv[fidx[0]]);
- vseam[1] = vseam[0];
- vseam[1].angle += vseam[1].angle > 0.0f ? -M_PI : M_PI;
- vseam[1].normal_cw = !vseam[1].normal_cw;
- copy_v2_v2(vseam[1].uv, lt_tri_uv[fidx[1]]);
+ vseam[1] = vseam[0];
+ vseam[1].angle += vseam[1].angle > 0.0f ? -M_PI : M_PI;
+ vseam[1].normal_cw = !vseam[1].normal_cw;
+ copy_v2_v2(vseam[1].uv, lt_tri_uv[fidx[1]]);
- for (uint i = 0; i < 2; i++) {
- uint vert = ps->mloop_eval[lt->tri[fidx[i]]].v;
- ListBase *list = &ps->vertSeams[vert];
- VertSeam *item = list->first;
+ for (uint i = 0; i < 2; i++) {
+ uint vert = ps->mloop_eval[lt->tri[fidx[i]]].v;
+ ListBase *list = &ps->vertSeams[vert];
+ VertSeam *item = list->first;
- while (item && item->angle < vseam[i].angle) {
- item = item->next;
- }
+ while (item && item->angle < vseam[i].angle) {
+ item = item->next;
+ }
- BLI_insertlinkbefore(list, item, &vseam[i]);
- }
+ BLI_insertlinkbefore(list, item, &vseam[i]);
+ }
}
/*
@@ -1402,144 +1398,151 @@ static void insert_seam_vert_array(
*
* If we're multithreadng, make sure threads are locked when this is called
*/
-static void project_face_seams_init(
- const ProjPaintState *ps, MemArena *arena, const int tri_index, const uint vert_index,
- bool init_all, const int ibuf_x, const int ibuf_y)
+static void project_face_seams_init(const ProjPaintState *ps,
+ MemArena *arena,
+ const int tri_index,
+ const uint vert_index,
+ bool init_all,
+ const int ibuf_x,
+ const int ibuf_y)
{
- /* vars for the other face, we also set its flag */
- int other_face, other_fidx;
- /* next fidx in the face (0,1,2,3) -> (1,2,3,0) or (0,1,2) -> (1,2,0) for a tri */
- int fidx[2] = {2, 0};
- const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
- LinkNode *node;
-
- /* initialize face winding if needed */
- if ((ps->faceWindingFlags[tri_index] & PROJ_FACE_WINDING_INIT) == 0)
- project_face_winding_init(ps, tri_index);
-
- do {
- if (init_all ||
- (ps->mloop_eval[lt->tri[fidx[0]]].v == vert_index) ||
- (ps->mloop_eval[lt->tri[fidx[1]]].v == vert_index))
- {
- if ((ps->faceSeamFlags[tri_index] & (PROJ_FACE_SEAM0 << fidx[0] | PROJ_FACE_NOSEAM0 << fidx[0])) == 0) {
- if (check_seam(ps, tri_index, fidx[0], fidx[1], &other_face, &other_fidx)) {
- ps->faceSeamFlags[tri_index] |= PROJ_FACE_SEAM0 << fidx[0];
- insert_seam_vert_array(ps, arena, tri_index, fidx[0], ibuf_x, ibuf_y);
-
- if (other_face != -1) {
- /* Check if the other seam is already set. We don't want to insert it in the list twice. */
- if ((ps->faceSeamFlags[other_face] & (PROJ_FACE_SEAM0 << other_fidx)) == 0) {
- ps->faceSeamFlags[other_face] |= PROJ_FACE_SEAM0 << other_fidx;
- insert_seam_vert_array(ps, arena, other_face, other_fidx, ibuf_x, ibuf_y);
- }
- }
- }
- else {
- ps->faceSeamFlags[tri_index] |= PROJ_FACE_NOSEAM0 << fidx[0];
- ps->faceSeamFlags[tri_index] |= PROJ_FACE_SEAM_INIT0 << fidx[0];
-
- if (other_face != -1) {
- /* second 4 bits for disabled */
- ps->faceSeamFlags[other_face] |= PROJ_FACE_NOSEAM0 << other_fidx;
- ps->faceSeamFlags[other_face] |= PROJ_FACE_SEAM_INIT0 << other_fidx;
- }
- }
- }
- }
-
- fidx[1] = fidx[0];
- } while (fidx[0]--);
-
- if (init_all) {
- char checked_verts = 0;
-
- fidx[0] = 2;
- fidx[1] = 0;
-
- do {
- if ((ps->faceSeamFlags[tri_index] & (PROJ_FACE_SEAM_INIT0 << fidx[0])) == 0) {
- for (uint i = 0; i < 2; i++) {
- uint vert;
-
- if ((checked_verts & (1 << fidx[i])) != 0) {
- continue;
- }
-
- vert = ps->mloop_eval[lt->tri[fidx[i]]].v;
-
- for (node = ps->vertFaces[vert]; node; node = node->next) {
- const int tri = POINTER_AS_INT(node->link);
-
- project_face_seams_init(ps, arena, tri, vert, false, ibuf_x, ibuf_y);
- }
-
- checked_verts |= 1 << fidx[i];
- }
-
- ps->faceSeamFlags[tri_index] |= PROJ_FACE_SEAM_INIT0 << fidx[0];
- }
-
- fidx[1] = fidx[0];
- } while (fidx[0]--);
- }
+ /* vars for the other face, we also set its flag */
+ int other_face, other_fidx;
+ /* next fidx in the face (0,1,2,3) -> (1,2,3,0) or (0,1,2) -> (1,2,0) for a tri */
+ int fidx[2] = {2, 0};
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
+ LinkNode *node;
+
+ /* initialize face winding if needed */
+ if ((ps->faceWindingFlags[tri_index] & PROJ_FACE_WINDING_INIT) == 0)
+ project_face_winding_init(ps, tri_index);
+
+ do {
+ if (init_all || (ps->mloop_eval[lt->tri[fidx[0]]].v == vert_index) ||
+ (ps->mloop_eval[lt->tri[fidx[1]]].v == vert_index)) {
+ if ((ps->faceSeamFlags[tri_index] &
+ (PROJ_FACE_SEAM0 << fidx[0] | PROJ_FACE_NOSEAM0 << fidx[0])) == 0) {
+ if (check_seam(ps, tri_index, fidx[0], fidx[1], &other_face, &other_fidx)) {
+ ps->faceSeamFlags[tri_index] |= PROJ_FACE_SEAM0 << fidx[0];
+ insert_seam_vert_array(ps, arena, tri_index, fidx[0], ibuf_x, ibuf_y);
+
+ if (other_face != -1) {
+ /* Check if the other seam is already set. We don't want to insert it in the list twice. */
+ if ((ps->faceSeamFlags[other_face] & (PROJ_FACE_SEAM0 << other_fidx)) == 0) {
+ ps->faceSeamFlags[other_face] |= PROJ_FACE_SEAM0 << other_fidx;
+ insert_seam_vert_array(ps, arena, other_face, other_fidx, ibuf_x, ibuf_y);
+ }
+ }
+ }
+ else {
+ ps->faceSeamFlags[tri_index] |= PROJ_FACE_NOSEAM0 << fidx[0];
+ ps->faceSeamFlags[tri_index] |= PROJ_FACE_SEAM_INIT0 << fidx[0];
+
+ if (other_face != -1) {
+ /* second 4 bits for disabled */
+ ps->faceSeamFlags[other_face] |= PROJ_FACE_NOSEAM0 << other_fidx;
+ ps->faceSeamFlags[other_face] |= PROJ_FACE_SEAM_INIT0 << other_fidx;
+ }
+ }
+ }
+ }
+
+ fidx[1] = fidx[0];
+ } while (fidx[0]--);
+
+ if (init_all) {
+ char checked_verts = 0;
+
+ fidx[0] = 2;
+ fidx[1] = 0;
+
+ do {
+ if ((ps->faceSeamFlags[tri_index] & (PROJ_FACE_SEAM_INIT0 << fidx[0])) == 0) {
+ for (uint i = 0; i < 2; i++) {
+ uint vert;
+
+ if ((checked_verts & (1 << fidx[i])) != 0) {
+ continue;
+ }
+
+ vert = ps->mloop_eval[lt->tri[fidx[i]]].v;
+
+ for (node = ps->vertFaces[vert]; node; node = node->next) {
+ const int tri = POINTER_AS_INT(node->link);
+
+ project_face_seams_init(ps, arena, tri, vert, false, ibuf_x, ibuf_y);
+ }
+
+ checked_verts |= 1 << fidx[i];
+ }
+
+ ps->faceSeamFlags[tri_index] |= PROJ_FACE_SEAM_INIT0 << fidx[0];
+ }
+
+ fidx[1] = fidx[0];
+ } while (fidx[0]--);
+ }
}
-#endif // PROJ_DEBUG_NOSEAMBLEED
-
+#endif // PROJ_DEBUG_NOSEAMBLEED
/* Converts a UV location to a 3D screenspace location
* Takes a 'uv' and 3 UV coords, and sets the values of pixelScreenCo
*
* This is used for finding a pixels location in screenspace for painting */
-static void screen_px_from_ortho(
- const float uv[2],
- const float v1co[3], const float v2co[3], const float v3co[3], /* Screenspace coords */
- const float uv1co[2], const float uv2co[2], const float uv3co[2],
- float pixelScreenCo[4],
- float w[3])
+static void screen_px_from_ortho(const float uv[2],
+ const float v1co[3],
+ const float v2co[3],
+ const float v3co[3], /* Screenspace coords */
+ const float uv1co[2],
+ const float uv2co[2],
+ const float uv3co[2],
+ float pixelScreenCo[4],
+ float w[3])
{
- barycentric_weights_v2(uv1co, uv2co, uv3co, uv, w);
- interp_v3_v3v3v3(pixelScreenCo, v1co, v2co, v3co, w);
+ barycentric_weights_v2(uv1co, uv2co, uv3co, uv, w);
+ interp_v3_v3v3v3(pixelScreenCo, v1co, v2co, v3co, w);
}
/* same as screen_px_from_ortho except we
* do perspective correction on the pixel coordinate */
-static void screen_px_from_persp(
- const float uv[2],
- const float v1co[4], const float v2co[4], const float v3co[4], /* screenspace coords */
- const float uv1co[2], const float uv2co[2], const float uv3co[2],
- float pixelScreenCo[4],
- float w[3])
+static void screen_px_from_persp(const float uv[2],
+ const float v1co[4],
+ const float v2co[4],
+ const float v3co[4], /* screenspace coords */
+ const float uv1co[2],
+ const float uv2co[2],
+ const float uv3co[2],
+ float pixelScreenCo[4],
+ float w[3])
{
- float w_int[3];
- float wtot_inv, wtot;
- barycentric_weights_v2(uv1co, uv2co, uv3co, uv, w);
-
- /* re-weight from the 4th coord of each screen vert */
- w_int[0] = w[0] * v1co[3];
- w_int[1] = w[1] * v2co[3];
- w_int[2] = w[2] * v3co[3];
-
- wtot = w_int[0] + w_int[1] + w_int[2];
-
- if (wtot > 0.0f) {
- wtot_inv = 1.0f / wtot;
- w_int[0] *= wtot_inv;
- w_int[1] *= wtot_inv;
- w_int[2] *= wtot_inv;
- }
- else {
- w[0] = w[1] = w[2] =
- /* dummy values for zero area face */
- w_int[0] = w_int[1] = w_int[2] = 1.0f / 3.0f;
- }
- /* done re-weighting */
-
- /* do interpolation based on projected weight */
- interp_v3_v3v3v3(pixelScreenCo, v1co, v2co, v3co, w_int);
+ float w_int[3];
+ float wtot_inv, wtot;
+ barycentric_weights_v2(uv1co, uv2co, uv3co, uv, w);
+
+ /* re-weight from the 4th coord of each screen vert */
+ w_int[0] = w[0] * v1co[3];
+ w_int[1] = w[1] * v2co[3];
+ w_int[2] = w[2] * v3co[3];
+
+ wtot = w_int[0] + w_int[1] + w_int[2];
+
+ if (wtot > 0.0f) {
+ wtot_inv = 1.0f / wtot;
+ w_int[0] *= wtot_inv;
+ w_int[1] *= wtot_inv;
+ w_int[2] *= wtot_inv;
+ }
+ else {
+ w[0] = w[1] = w[2] =
+ /* dummy values for zero area face */
+ w_int[0] = w_int[1] = w_int[2] = 1.0f / 3.0f;
+ }
+ /* done re-weighting */
+
+ /* do interpolation based on projected weight */
+ interp_v3_v3v3v3(pixelScreenCo, v1co, v2co, v3co, w_int);
}
-
/**
* Set a direction vector based on a screen location.
* (use for perspective view, else we can simply use `ps->viewDir`)
@@ -1548,16 +1551,18 @@ static void screen_px_from_persp(
*
* \param r_dir: Resulting direction (length is undefined).
*/
-static void screen_px_to_vector_persp(
- int winx, int winy, const float projmat_inv[4][4], const float view_pos[3],
- const float co_px[2],
- float r_dir[3])
+static void screen_px_to_vector_persp(int winx,
+ int winy,
+ const float projmat_inv[4][4],
+ const float view_pos[3],
+ const float co_px[2],
+ float r_dir[3])
{
- r_dir[0] = 2.0f * (co_px[0] / winx) - 1.0f;
- r_dir[1] = 2.0f * (co_px[1] / winy) - 1.0f;
- r_dir[2] = -0.5f;
- mul_project_m4_v3((float(*)[4])projmat_inv, r_dir);
- sub_v3_v3(r_dir, view_pos);
+ r_dir[0] = 2.0f * (co_px[0] / winx) - 1.0f;
+ r_dir[1] = 2.0f * (co_px[1] / winy) - 1.0f;
+ r_dir[2] = -0.5f;
+ mul_project_m4_v3((float(*)[4])projmat_inv, r_dir);
+ sub_v3_v3(r_dir, view_pos);
}
/**
@@ -1568,578 +1573,601 @@ static void screen_px_to_vector_persp(
* \param p: 2D screen-space location.
* \param v1, v2: 3D object-space locations.
*/
-static float screen_px_line_point_factor_v2_persp(
- const ProjPaintState *ps,
- const float p[2],
- const float v1[3], const float v2[3])
+static float screen_px_line_point_factor_v2_persp(const ProjPaintState *ps,
+ const float p[2],
+ const float v1[3],
+ const float v2[3])
{
- const float zero[3] = {0};
- float v1_proj[3], v2_proj[3];
- float dir[3];
+ const float zero[3] = {0};
+ float v1_proj[3], v2_proj[3];
+ float dir[3];
- screen_px_to_vector_persp(ps->winx, ps->winy, ps->projectMatInv, ps->viewPos, p, dir);
+ screen_px_to_vector_persp(ps->winx, ps->winy, ps->projectMatInv, ps->viewPos, p, dir);
- sub_v3_v3v3(v1_proj, v1, ps->viewPos);
- sub_v3_v3v3(v2_proj, v2, ps->viewPos);
+ sub_v3_v3v3(v1_proj, v1, ps->viewPos);
+ sub_v3_v3v3(v2_proj, v2, ps->viewPos);
- project_plane_v3_v3v3(v1_proj, v1_proj, dir);
- project_plane_v3_v3v3(v2_proj, v2_proj, dir);
+ project_plane_v3_v3v3(v1_proj, v1_proj, dir);
+ project_plane_v3_v3v3(v2_proj, v2_proj, dir);
- return line_point_factor_v2(zero, v1_proj, v2_proj);
+ return line_point_factor_v2(zero, v1_proj, v2_proj);
}
-
-static void project_face_pixel(
- const float *lt_tri_uv[3], ImBuf *ibuf_other, const float w[3],
- unsigned char rgba_ub[4], float rgba_f[4])
+static void project_face_pixel(const float *lt_tri_uv[3],
+ ImBuf *ibuf_other,
+ const float w[3],
+ unsigned char rgba_ub[4],
+ float rgba_f[4])
{
- float uv_other[2], x, y;
-
- interp_v2_v2v2v2(uv_other, UNPACK3(lt_tri_uv), w);
+ float uv_other[2], x, y;
- /* use */
- uvco_to_wrapped_pxco(uv_other, ibuf_other->x, ibuf_other->y, &x, &y);
+ interp_v2_v2v2v2(uv_other, UNPACK3(lt_tri_uv), w);
- if (ibuf_other->rect_float) { /* from float to float */
- bilinear_interpolation_color_wrap(ibuf_other, NULL, rgba_f, x, y);
- }
- else { /* from char to float */
- bilinear_interpolation_color_wrap(ibuf_other, rgba_ub, NULL, x, y);
- }
+ /* use */
+ uvco_to_wrapped_pxco(uv_other, ibuf_other->x, ibuf_other->y, &x, &y);
+ if (ibuf_other->rect_float) { /* from float to float */
+ bilinear_interpolation_color_wrap(ibuf_other, NULL, rgba_f, x, y);
+ }
+ else { /* from char to float */
+ bilinear_interpolation_color_wrap(ibuf_other, rgba_ub, NULL, x, y);
+ }
}
/* run this outside project_paint_uvpixel_init since pixels with mask 0 don't need init */
-static float project_paint_uvpixel_mask(
- const ProjPaintState *ps,
- const int tri_index,
- const float w[3])
+static float project_paint_uvpixel_mask(const ProjPaintState *ps,
+ const int tri_index,
+ const float w[3])
{
- float mask;
-
- /* Image Mask */
- if (ps->do_layer_stencil) {
- /* another UV maps image is masking this one's */
- ImBuf *ibuf_other;
- Image *other_tpage = ps->stencil_ima;
-
- if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
- const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index];
- 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];
- float rgba_f[4];
-
- project_face_pixel(lt_other_tri_uv, ibuf_other, w, rgba_ub, rgba_f);
-
- if (ibuf_other->rect_float) { /* from float to float */
- mask = ((rgba_f[0] + rgba_f[1] + rgba_f[2]) * (1.0f / 3.0f)) * rgba_f[3];
- }
- else { /* from char to float */
- mask = ((rgba_ub[0] + rgba_ub[1] + rgba_ub[2]) * (1.0f / (255.0f * 3.0f))) * (rgba_ub[3] * (1.0f / 255.0f));
- }
-
- BKE_image_release_ibuf(other_tpage, ibuf_other, NULL);
-
- if (!ps->do_layer_stencil_inv) {
- /* matching the gimps layer mask black/white rules, white==full opacity */
- mask = (1.0f - mask);
- }
-
- if (mask == 0.0f) {
- return 0.0f;
- }
- }
- else {
- return 0.0f;
- }
- }
- else {
- mask = 1.0f;
- }
-
- if (ps->do_mask_cavity) {
- const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
- const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
- float ca1, ca2, ca3, ca_mask;
- ca1 = ps->cavities[lt_vtri[0]];
- ca2 = ps->cavities[lt_vtri[1]];
- ca3 = ps->cavities[lt_vtri[2]];
-
- ca_mask = w[0] * ca1 + w[1] * ca2 + w[2] * ca3;
- ca_mask = curvemapping_evaluateF(ps->cavity_curve, 0, ca_mask);
- CLAMP(ca_mask, 0.0f, 1.0f);
- mask *= ca_mask;
- }
-
- /* calculate mask */
- if (ps->do_mask_normal) {
- const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
- const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
- const MPoly *mp = &ps->mpoly_eval[lt->poly];
- float no[3], angle_cos;
-
- if (mp->flag & ME_SMOOTH) {
- const short *no1, *no2, *no3;
- no1 = ps->mvert_eval[lt_vtri[0]].no;
- no2 = ps->mvert_eval[lt_vtri[1]].no;
- no3 = ps->mvert_eval[lt_vtri[2]].no;
-
- no[0] = w[0] * no1[0] + w[1] * no2[0] + w[2] * no3[0];
- no[1] = w[0] * no1[1] + w[1] * no2[1] + w[2] * no3[1];
- no[2] = w[0] * no1[2] + w[1] * no2[2] + w[2] * no3[2];
- normalize_v3(no);
- }
- else {
- /* incase the */
+ float mask;
+
+ /* Image Mask */
+ if (ps->do_layer_stencil) {
+ /* another UV maps image is masking this one's */
+ ImBuf *ibuf_other;
+ Image *other_tpage = ps->stencil_ima;
+
+ if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
+ const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index];
+ 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];
+ float rgba_f[4];
+
+ project_face_pixel(lt_other_tri_uv, ibuf_other, w, rgba_ub, rgba_f);
+
+ if (ibuf_other->rect_float) { /* from float to float */
+ mask = ((rgba_f[0] + rgba_f[1] + rgba_f[2]) * (1.0f / 3.0f)) * rgba_f[3];
+ }
+ else { /* from char to float */
+ mask = ((rgba_ub[0] + rgba_ub[1] + rgba_ub[2]) * (1.0f / (255.0f * 3.0f))) *
+ (rgba_ub[3] * (1.0f / 255.0f));
+ }
+
+ BKE_image_release_ibuf(other_tpage, ibuf_other, NULL);
+
+ if (!ps->do_layer_stencil_inv) {
+ /* matching the gimps layer mask black/white rules, white==full opacity */
+ mask = (1.0f - mask);
+ }
+
+ if (mask == 0.0f) {
+ return 0.0f;
+ }
+ }
+ else {
+ return 0.0f;
+ }
+ }
+ else {
+ mask = 1.0f;
+ }
+
+ if (ps->do_mask_cavity) {
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
+ const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
+ float ca1, ca2, ca3, ca_mask;
+ ca1 = ps->cavities[lt_vtri[0]];
+ ca2 = ps->cavities[lt_vtri[1]];
+ ca3 = ps->cavities[lt_vtri[2]];
+
+ ca_mask = w[0] * ca1 + w[1] * ca2 + w[2] * ca3;
+ ca_mask = curvemapping_evaluateF(ps->cavity_curve, 0, ca_mask);
+ CLAMP(ca_mask, 0.0f, 1.0f);
+ mask *= ca_mask;
+ }
+
+ /* calculate mask */
+ if (ps->do_mask_normal) {
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
+ const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
+ const MPoly *mp = &ps->mpoly_eval[lt->poly];
+ float no[3], angle_cos;
+
+ if (mp->flag & ME_SMOOTH) {
+ const short *no1, *no2, *no3;
+ no1 = ps->mvert_eval[lt_vtri[0]].no;
+ no2 = ps->mvert_eval[lt_vtri[1]].no;
+ no3 = ps->mvert_eval[lt_vtri[2]].no;
+
+ no[0] = w[0] * no1[0] + w[1] * no2[0] + w[2] * no3[0];
+ no[1] = w[0] * no1[1] + w[1] * no2[1] + w[2] * no3[1];
+ no[2] = w[0] * no1[2] + w[1] * no2[2] + w[2] * no3[2];
+ normalize_v3(no);
+ }
+ else {
+ /* incase the */
#if 1
- /* normalizing per pixel isn't optimal, we could cache or check ps->*/
- normal_tri_v3(no,
- ps->mvert_eval[lt_vtri[0]].co,
- ps->mvert_eval[lt_vtri[1]].co,
- ps->mvert_eval[lt_vtri[2]].co);
+ /* normalizing per pixel isn't optimal, we could cache or check ps->*/
+ normal_tri_v3(no,
+ ps->mvert_eval[lt_vtri[0]].co,
+ ps->mvert_eval[lt_vtri[1]].co,
+ ps->mvert_eval[lt_vtri[2]].co);
#else
- /* don't use because some modifiers dont have normal data (subsurf for eg) */
- copy_v3_v3(no, (float *)ps->dm->getTessFaceData(ps->dm, tri_index, CD_NORMAL));
+ /* don't use because some modifiers dont have normal data (subsurf for eg) */
+ copy_v3_v3(no, (float *)ps->dm->getTessFaceData(ps->dm, tri_index, CD_NORMAL));
#endif
- }
-
- if (UNLIKELY(ps->is_flip_object)) {
- negate_v3(no);
- }
-
- /* now we can use the normal as a mask */
- if (ps->is_ortho) {
- angle_cos = dot_v3v3(ps->viewDir, no);
- }
- else {
- /* Annoying but for the perspective view we need to get the pixels location in 3D space :/ */
- float viewDirPersp[3];
- const float *co1, *co2, *co3;
- co1 = ps->mvert_eval[lt_vtri[0]].co;
- co2 = ps->mvert_eval[lt_vtri[1]].co;
- co3 = ps->mvert_eval[lt_vtri[2]].co;
-
- /* Get the direction from the viewPoint to the pixel and normalize */
- viewDirPersp[0] = (ps->viewPos[0] - (w[0] * co1[0] + w[1] * co2[0] + w[2] * co3[0]));
- viewDirPersp[1] = (ps->viewPos[1] - (w[0] * co1[1] + w[1] * co2[1] + w[2] * co3[1]));
- viewDirPersp[2] = (ps->viewPos[2] - (w[0] * co1[2] + w[1] * co2[2] + w[2] * co3[2]));
- normalize_v3(viewDirPersp);
- if (UNLIKELY(ps->is_flip_object)) {
- negate_v3(viewDirPersp);
- }
-
- angle_cos = dot_v3v3(viewDirPersp, no);
- }
-
- /* If backface culling is disabled, allow painting on back faces. */
- if (!ps->do_backfacecull) {
- angle_cos = fabsf(angle_cos);
- }
-
- if (angle_cos <= ps->normal_angle__cos) {
- /* outsize the normal limit*/
- return 0.0f;
- }
- else if (angle_cos < ps->normal_angle_inner__cos) {
- mask *= (ps->normal_angle - acosf(angle_cos)) / ps->normal_angle_range;
- } /* otherwise no mask normal is needed, were within the limit */
- }
-
- /* This only works when the opacity doesn't change while painting, stylus pressure messes with this
- * so don't use it. */
- // if (ps->is_airbrush == 0) mask *= BKE_brush_alpha_get(ps->brush);
-
- return mask;
+ }
+
+ if (UNLIKELY(ps->is_flip_object)) {
+ negate_v3(no);
+ }
+
+ /* now we can use the normal as a mask */
+ if (ps->is_ortho) {
+ angle_cos = dot_v3v3(ps->viewDir, no);
+ }
+ else {
+ /* Annoying but for the perspective view we need to get the pixels location in 3D space :/ */
+ float viewDirPersp[3];
+ const float *co1, *co2, *co3;
+ co1 = ps->mvert_eval[lt_vtri[0]].co;
+ co2 = ps->mvert_eval[lt_vtri[1]].co;
+ co3 = ps->mvert_eval[lt_vtri[2]].co;
+
+ /* Get the direction from the viewPoint to the pixel and normalize */
+ viewDirPersp[0] = (ps->viewPos[0] - (w[0] * co1[0] + w[1] * co2[0] + w[2] * co3[0]));
+ viewDirPersp[1] = (ps->viewPos[1] - (w[0] * co1[1] + w[1] * co2[1] + w[2] * co3[1]));
+ viewDirPersp[2] = (ps->viewPos[2] - (w[0] * co1[2] + w[1] * co2[2] + w[2] * co3[2]));
+ normalize_v3(viewDirPersp);
+ if (UNLIKELY(ps->is_flip_object)) {
+ negate_v3(viewDirPersp);
+ }
+
+ angle_cos = dot_v3v3(viewDirPersp, no);
+ }
+
+ /* If backface culling is disabled, allow painting on back faces. */
+ if (!ps->do_backfacecull) {
+ angle_cos = fabsf(angle_cos);
+ }
+
+ if (angle_cos <= ps->normal_angle__cos) {
+ /* outsize the normal limit*/
+ return 0.0f;
+ }
+ else if (angle_cos < ps->normal_angle_inner__cos) {
+ mask *= (ps->normal_angle - acosf(angle_cos)) / ps->normal_angle_range;
+ } /* otherwise no mask normal is needed, were within the limit */
+ }
+
+ /* This only works when the opacity doesn't change while painting, stylus pressure messes with this
+ * so don't use it. */
+ // if (ps->is_airbrush == 0) mask *= BKE_brush_alpha_get(ps->brush);
+
+ return mask;
}
static int project_paint_pixel_sizeof(const short tool)
{
- if ((tool == PAINT_TOOL_CLONE) || (tool == PAINT_TOOL_SMEAR)) {
- return sizeof(ProjPixelClone);
- }
- else {
- return sizeof(ProjPixel);
- }
+ if ((tool == PAINT_TOOL_CLONE) || (tool == PAINT_TOOL_SMEAR)) {
+ return sizeof(ProjPixelClone);
+ }
+ else {
+ return sizeof(ProjPixel);
+ }
}
static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty)
{
- ProjPaintImage *pjIma = tinf->pjima;
- int tile_index = tx + ty * tinf->tile_width;
- bool generate_tile = false;
-
- /* double check lock to avoid locking */
- if (UNLIKELY(!pjIma->undoRect[tile_index])) {
- if (tinf->lock)
- BLI_spin_lock(tinf->lock);
- if (LIKELY(!pjIma->undoRect[tile_index])) {
- pjIma->undoRect[tile_index] = TILE_PENDING;
- generate_tile = true;
- }
- if (tinf->lock)
- BLI_spin_unlock(tinf->lock);
- }
-
-
- if (generate_tile) {
- ListBase *undo_tiles = ED_image_undo_get_tiles();
- volatile void *undorect;
- if (tinf->masked) {
- undorect = image_undo_push_tile(
- undo_tiles, pjIma->ima, pjIma->ibuf, tinf->tmpibuf,
- tx, ty, &pjIma->maskRect[tile_index], &pjIma->valid[tile_index], true, false);
- }
- else {
- undorect = image_undo_push_tile(
- undo_tiles, pjIma->ima, pjIma->ibuf, tinf->tmpibuf,
- tx, ty, NULL, &pjIma->valid[tile_index], true, false);
- }
-
- pjIma->ibuf->userflags |= IB_BITMAPDIRTY;
- /* tile ready, publish */
- if (tinf->lock)
- BLI_spin_lock(tinf->lock);
- pjIma->undoRect[tile_index] = undorect;
- if (tinf->lock)
- BLI_spin_unlock(tinf->lock);
-
- }
-
- return tile_index;
+ ProjPaintImage *pjIma = tinf->pjima;
+ int tile_index = tx + ty * tinf->tile_width;
+ bool generate_tile = false;
+
+ /* double check lock to avoid locking */
+ if (UNLIKELY(!pjIma->undoRect[tile_index])) {
+ if (tinf->lock)
+ BLI_spin_lock(tinf->lock);
+ if (LIKELY(!pjIma->undoRect[tile_index])) {
+ pjIma->undoRect[tile_index] = TILE_PENDING;
+ generate_tile = true;
+ }
+ if (tinf->lock)
+ BLI_spin_unlock(tinf->lock);
+ }
+
+ if (generate_tile) {
+ ListBase *undo_tiles = ED_image_undo_get_tiles();
+ volatile void *undorect;
+ if (tinf->masked) {
+ undorect = image_undo_push_tile(undo_tiles,
+ pjIma->ima,
+ pjIma->ibuf,
+ tinf->tmpibuf,
+ tx,
+ ty,
+ &pjIma->maskRect[tile_index],
+ &pjIma->valid[tile_index],
+ true,
+ false);
+ }
+ else {
+ undorect = image_undo_push_tile(undo_tiles,
+ pjIma->ima,
+ pjIma->ibuf,
+ tinf->tmpibuf,
+ tx,
+ ty,
+ NULL,
+ &pjIma->valid[tile_index],
+ true,
+ false);
+ }
+
+ pjIma->ibuf->userflags |= IB_BITMAPDIRTY;
+ /* tile ready, publish */
+ if (tinf->lock)
+ BLI_spin_lock(tinf->lock);
+ pjIma->undoRect[tile_index] = undorect;
+ if (tinf->lock)
+ BLI_spin_unlock(tinf->lock);
+ }
+
+ return tile_index;
}
/* run this function when we know a bucket's, face's pixel can be initialized,
* return the ProjPixel which is added to 'ps->bucketRect[bucket_index]' */
-static ProjPixel *project_paint_uvpixel_init(
- const ProjPaintState *ps,
- MemArena *arena,
- const TileInfo *tinf,
- int x_px, int y_px,
- const float mask,
- const int tri_index,
- const float pixelScreenCo[4],
- const float world_spaceCo[3],
- const float w[3])
+static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps,
+ MemArena *arena,
+ const TileInfo *tinf,
+ int x_px,
+ int y_px,
+ const float mask,
+ const int tri_index,
+ const float pixelScreenCo[4],
+ const float world_spaceCo[3],
+ const float w[3])
{
- ProjPixel *projPixel;
- int x_tile, y_tile;
- int x_round, y_round;
- int tile_offset;
- /* volatile is important here to ensure pending check is not optimized away by compiler*/
- volatile int tile_index;
-
- ProjPaintImage *projima = tinf->pjima;
- ImBuf *ibuf = projima->ibuf;
- /* wrap pixel location */
-
- x_px = mod_i(x_px, ibuf->x);
- y_px = mod_i(y_px, ibuf->y);
-
- BLI_assert(ps->pixel_sizeof == project_paint_pixel_sizeof(ps->tool));
- projPixel = BLI_memarena_alloc(arena, ps->pixel_sizeof);
-
- /* calculate the undo tile offset of the pixel, used to store the original
- * pixel color and accumulated mask if any */
- x_tile = x_px >> IMAPAINT_TILE_BITS;
- y_tile = y_px >> IMAPAINT_TILE_BITS;
-
- x_round = x_tile * IMAPAINT_TILE_SIZE;
- y_round = y_tile * IMAPAINT_TILE_SIZE;
- //memset(projPixel, 0, size);
-
- tile_offset = (x_px - x_round) + (y_px - y_round) * IMAPAINT_TILE_SIZE;
- tile_index = project_paint_undo_subtiles(tinf, x_tile, y_tile);
-
- /* other thread may be initializing the tile so wait here */
- while (projima->undoRect[tile_index] == TILE_PENDING)
- ;
-
- BLI_assert(tile_index < (IMAPAINT_TILE_NUMBER(ibuf->x) * IMAPAINT_TILE_NUMBER(ibuf->y)));
- BLI_assert(tile_offset < (IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE));
-
- projPixel->valid = projima->valid[tile_index];
-
- if (ibuf->rect_float) {
- projPixel->pixel.f_pt = ibuf->rect_float + ((x_px + y_px * ibuf->x) * 4);
- projPixel->origColor.f_pt = (float *)projima->undoRect[tile_index] + 4 * tile_offset;
- 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->newColor.uint = 0;
- }
-
- /* screenspace unclamped, we could keep its z and w values but don't need them at the moment */
- if (ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) {
- copy_v3_v3(projPixel->worldCoSS, world_spaceCo);
- }
-
- copy_v2_v2(projPixel->projCoSS, pixelScreenCo);
-
- projPixel->x_px = x_px;
- projPixel->y_px = y_px;
-
- projPixel->mask = (unsigned short)(mask * 65535);
- if (ps->do_masking)
- projPixel->mask_accum = projima->maskRect[tile_index] + tile_offset;
- else
- projPixel->mask_accum = NULL;
-
- /* which bounding box cell are we in?, needed for undo */
- projPixel->bb_cell_index = ((int)(((float)x_px / (float)ibuf->x) * PROJ_BOUNDBOX_DIV)) +
- ((int)(((float)y_px / (float)ibuf->y) * PROJ_BOUNDBOX_DIV)) * PROJ_BOUNDBOX_DIV;
-
- /* done with view3d_project_float inline */
- if (ps->tool == PAINT_TOOL_CLONE) {
- if (ps->poly_to_loop_uv_clone) {
- ImBuf *ibuf_other;
- Image *other_tpage = project_paint_face_clone_image(ps, tri_index);
-
- if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
- const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index];
- const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv_clone, lt_other) };
-
- /* BKE_image_acquire_ibuf - TODO - this may be slow */
-
- if (ibuf->rect_float) {
- if (ibuf_other->rect_float) { /* from float to float */
- project_face_pixel(lt_other_tri_uv, ibuf_other, w, NULL, ((ProjPixelClone *)projPixel)->clonepx.f);
- }
- else { /* from char to float */
- unsigned char rgba_ub[4];
- float rgba[4];
- project_face_pixel(lt_other_tri_uv, ibuf_other, w, rgba_ub, NULL);
- if (ps->use_colormanagement) {
- srgb_to_linearrgb_uchar4(rgba, rgba_ub);
- }
- else {
- rgba_uchar_to_float(rgba, rgba_ub);
- }
- straight_to_premul_v4_v4(((ProjPixelClone *)projPixel)->clonepx.f, rgba);
- }
- }
- else {
- if (ibuf_other->rect_float) { /* float to char */
- float rgba[4];
- project_face_pixel(lt_other_tri_uv, ibuf_other, w, NULL, rgba);
- premul_to_straight_v4(rgba);
- if (ps->use_colormanagement) {
- linearrgb_to_srgb_uchar3(((ProjPixelClone *)projPixel)->clonepx.ch, rgba);
- }
- else {
- rgb_float_to_uchar(((ProjPixelClone *)projPixel)->clonepx.ch, rgba);
- }
- ((ProjPixelClone *)projPixel)->clonepx.ch[3] = rgba[3] * 255;
- }
- else { /* char to char */
- project_face_pixel(lt_other_tri_uv, ibuf_other, w, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL);
- }
- }
-
- BKE_image_release_ibuf(other_tpage, ibuf_other, NULL);
- }
- else {
- if (ibuf->rect_float) {
- ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0;
- }
- else {
- ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0;
- }
- }
-
- }
- else {
- float co[2];
- sub_v2_v2v2(co, projPixel->projCoSS, ps->cloneOffset);
-
- /* no need to initialize the bucket, we're only checking buckets faces and for this
- * the faces are already initialized in project_paint_delayed_face_init(...) */
- if (ibuf->rect_float) {
- if (!project_paint_PickColor(ps, co, ((ProjPixelClone *)projPixel)->clonepx.f, NULL, 1)) {
- /* zero alpha - ignore */
- ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0;
- }
- }
- else {
- if (!project_paint_PickColor(ps, co, NULL, ((ProjPixelClone *)projPixel)->clonepx.ch, 1)) {
- /* zero alpha - ignore */
- ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0;
- }
- }
- }
- }
+ ProjPixel *projPixel;
+ int x_tile, y_tile;
+ int x_round, y_round;
+ int tile_offset;
+ /* volatile is important here to ensure pending check is not optimized away by compiler*/
+ volatile int tile_index;
+
+ ProjPaintImage *projima = tinf->pjima;
+ ImBuf *ibuf = projima->ibuf;
+ /* wrap pixel location */
+
+ x_px = mod_i(x_px, ibuf->x);
+ y_px = mod_i(y_px, ibuf->y);
+
+ BLI_assert(ps->pixel_sizeof == project_paint_pixel_sizeof(ps->tool));
+ projPixel = BLI_memarena_alloc(arena, ps->pixel_sizeof);
+
+ /* calculate the undo tile offset of the pixel, used to store the original
+ * pixel color and accumulated mask if any */
+ x_tile = x_px >> IMAPAINT_TILE_BITS;
+ y_tile = y_px >> IMAPAINT_TILE_BITS;
+
+ x_round = x_tile * IMAPAINT_TILE_SIZE;
+ y_round = y_tile * IMAPAINT_TILE_SIZE;
+ //memset(projPixel, 0, size);
+
+ tile_offset = (x_px - x_round) + (y_px - y_round) * IMAPAINT_TILE_SIZE;
+ tile_index = project_paint_undo_subtiles(tinf, x_tile, y_tile);
+
+ /* other thread may be initializing the tile so wait here */
+ while (projima->undoRect[tile_index] == TILE_PENDING)
+ ;
+
+ BLI_assert(tile_index < (IMAPAINT_TILE_NUMBER(ibuf->x) * IMAPAINT_TILE_NUMBER(ibuf->y)));
+ BLI_assert(tile_offset < (IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE));
+
+ projPixel->valid = projima->valid[tile_index];
+
+ if (ibuf->rect_float) {
+ projPixel->pixel.f_pt = ibuf->rect_float + ((x_px + y_px * ibuf->x) * 4);
+ projPixel->origColor.f_pt = (float *)projima->undoRect[tile_index] + 4 * tile_offset;
+ 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->newColor.uint = 0;
+ }
+
+ /* screenspace unclamped, we could keep its z and w values but don't need them at the moment */
+ if (ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) {
+ copy_v3_v3(projPixel->worldCoSS, world_spaceCo);
+ }
+
+ copy_v2_v2(projPixel->projCoSS, pixelScreenCo);
+
+ projPixel->x_px = x_px;
+ projPixel->y_px = y_px;
+
+ projPixel->mask = (unsigned short)(mask * 65535);
+ if (ps->do_masking)
+ projPixel->mask_accum = projima->maskRect[tile_index] + tile_offset;
+ else
+ projPixel->mask_accum = NULL;
+
+ /* which bounding box cell are we in?, needed for undo */
+ projPixel->bb_cell_index = ((int)(((float)x_px / (float)ibuf->x) * PROJ_BOUNDBOX_DIV)) +
+ ((int)(((float)y_px / (float)ibuf->y) * PROJ_BOUNDBOX_DIV)) *
+ PROJ_BOUNDBOX_DIV;
+
+ /* done with view3d_project_float inline */
+ if (ps->tool == PAINT_TOOL_CLONE) {
+ if (ps->poly_to_loop_uv_clone) {
+ ImBuf *ibuf_other;
+ Image *other_tpage = project_paint_face_clone_image(ps, tri_index);
+
+ if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
+ const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index];
+ const float *lt_other_tri_uv[3] = {
+ PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv_clone, lt_other)};
+
+ /* BKE_image_acquire_ibuf - TODO - this may be slow */
+
+ if (ibuf->rect_float) {
+ if (ibuf_other->rect_float) { /* from float to float */
+ project_face_pixel(
+ lt_other_tri_uv, ibuf_other, w, NULL, ((ProjPixelClone *)projPixel)->clonepx.f);
+ }
+ else { /* from char to float */
+ unsigned char rgba_ub[4];
+ float rgba[4];
+ project_face_pixel(lt_other_tri_uv, ibuf_other, w, rgba_ub, NULL);
+ if (ps->use_colormanagement) {
+ srgb_to_linearrgb_uchar4(rgba, rgba_ub);
+ }
+ else {
+ rgba_uchar_to_float(rgba, rgba_ub);
+ }
+ straight_to_premul_v4_v4(((ProjPixelClone *)projPixel)->clonepx.f, rgba);
+ }
+ }
+ else {
+ if (ibuf_other->rect_float) { /* float to char */
+ float rgba[4];
+ project_face_pixel(lt_other_tri_uv, ibuf_other, w, NULL, rgba);
+ premul_to_straight_v4(rgba);
+ if (ps->use_colormanagement) {
+ linearrgb_to_srgb_uchar3(((ProjPixelClone *)projPixel)->clonepx.ch, rgba);
+ }
+ else {
+ rgb_float_to_uchar(((ProjPixelClone *)projPixel)->clonepx.ch, rgba);
+ }
+ ((ProjPixelClone *)projPixel)->clonepx.ch[3] = rgba[3] * 255;
+ }
+ else { /* char to char */
+ project_face_pixel(
+ lt_other_tri_uv, ibuf_other, w, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL);
+ }
+ }
+
+ BKE_image_release_ibuf(other_tpage, ibuf_other, NULL);
+ }
+ else {
+ if (ibuf->rect_float) {
+ ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0;
+ }
+ else {
+ ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0;
+ }
+ }
+ }
+ else {
+ float co[2];
+ sub_v2_v2v2(co, projPixel->projCoSS, ps->cloneOffset);
+
+ /* no need to initialize the bucket, we're only checking buckets faces and for this
+ * the faces are already initialized in project_paint_delayed_face_init(...) */
+ if (ibuf->rect_float) {
+ if (!project_paint_PickColor(ps, co, ((ProjPixelClone *)projPixel)->clonepx.f, NULL, 1)) {
+ /* zero alpha - ignore */
+ ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0;
+ }
+ }
+ else {
+ if (!project_paint_PickColor(ps, co, NULL, ((ProjPixelClone *)projPixel)->clonepx.ch, 1)) {
+ /* zero alpha - ignore */
+ ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0;
+ }
+ }
+ }
+ }
#ifdef PROJ_DEBUG_PAINT
- if (ibuf->rect_float) projPixel->pixel.f_pt[0] = 0;
- else projPixel->pixel.ch_pt[0] = 0;
+ if (ibuf->rect_float)
+ projPixel->pixel.f_pt[0] = 0;
+ else
+ projPixel->pixel.ch_pt[0] = 0;
#endif
- /* pointer arithmetic */
- projPixel->image_index = projima - ps->projImages;
+ /* pointer arithmetic */
+ projPixel->image_index = projima - ps->projImages;
- return projPixel;
+ return projPixel;
}
-static bool line_clip_rect2f(
- const rctf *cliprect,
- const rctf *rect,
- const float l1[2], const float l2[2],
- float l1_clip[2], float l2_clip[2])
+static bool line_clip_rect2f(const rctf *cliprect,
+ const rctf *rect,
+ const float l1[2],
+ const float l2[2],
+ float l1_clip[2],
+ float l2_clip[2])
{
- /* first account for horizontal, then vertical lines */
- /* horiz */
- 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;
- }
- /* 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;
- }
-
-
- /* this is a single point (or close to)*/
- if (fabsf(l1[0] - l2[0]) < PROJ_PIXEL_TOLERANCE) {
- if (BLI_rctf_isect_pt_v(rect, l1)) {
- copy_v2_v2(l1_clip, l1);
- copy_v2_v2(l2_clip, l2);
- return 1;
- }
- else {
- return 0;
- }
- }
-
- copy_v2_v2(l1_clip, l1);
- copy_v2_v2(l2_clip, l2);
- CLAMP(l1_clip[0], rect->xmin, rect->xmax);
- CLAMP(l2_clip[0], rect->xmin, rect->xmax);
- return 1;
- }
- else if (fabsf(l1[0] - l2[0]) < PROJ_PIXEL_TOLERANCE) {
- /* is the line out of range on its X axis? */
- if (l1[0] < rect->xmin || l1[0] > rect->xmax) {
- return 0;
- }
-
- /* line is out of range on its Y axis */
- if ((l1[1] < rect->ymin && l2[1] < rect->ymin) || (l1[1] > rect->ymax && l2[1] > rect->ymax)) {
- return 0;
- }
-
- /* this is a single point (or close to)*/
- if (fabsf(l1[1] - l2[1]) < PROJ_PIXEL_TOLERANCE) {
- if (BLI_rctf_isect_pt_v(rect, l1)) {
- copy_v2_v2(l1_clip, l1);
- copy_v2_v2(l2_clip, l2);
- return 1;
- }
- else {
- return 0;
- }
- }
-
- copy_v2_v2(l1_clip, l1);
- copy_v2_v2(l2_clip, l2);
- CLAMP(l1_clip[1], rect->ymin, rect->ymax);
- CLAMP(l2_clip[1], rect->ymin, rect->ymax);
- return 1;
- }
- else {
- float isect;
- short ok1 = 0;
- short ok2 = 0;
-
- /* Done with vertical lines */
-
- /* are either of the points inside the rectangle ? */
- if (BLI_rctf_isect_pt_v(rect, l1)) {
- copy_v2_v2(l1_clip, l1);
- ok1 = 1;
- }
-
- if (BLI_rctf_isect_pt_v(rect, l2)) {
- copy_v2_v2(l2_clip, l2);
- ok2 = 1;
- }
-
- /* line inside rect */
- if (ok1 && ok2) return 1;
-
- /* top/bottom */
- if (line_isect_y(l1, l2, rect->ymin, &isect) && (isect >= cliprect->xmin) && (isect <= cliprect->xmax)) {
- if (l1[1] < l2[1]) { /* line 1 is outside */
- l1_clip[0] = isect;
- l1_clip[1] = rect->ymin;
- ok1 = 1;
- }
- else {
- l2_clip[0] = isect;
- l2_clip[1] = rect->ymin;
- ok2 = 2;
- }
- }
-
- if (ok1 && ok2) return 1;
-
- if (line_isect_y(l1, l2, rect->ymax, &isect) && (isect >= cliprect->xmin) && (isect <= cliprect->xmax)) {
- if (l1[1] > l2[1]) { /* line 1 is outside */
- l1_clip[0] = isect;
- l1_clip[1] = rect->ymax;
- ok1 = 1;
- }
- else {
- l2_clip[0] = isect;
- l2_clip[1] = rect->ymax;
- ok2 = 2;
- }
- }
-
- if (ok1 && ok2) return 1;
-
- /* left/right */
- if (line_isect_x(l1, l2, rect->xmin, &isect) && (isect >= cliprect->ymin) && (isect <= cliprect->ymax)) {
- if (l1[0] < l2[0]) { /* line 1 is outside */
- l1_clip[0] = rect->xmin;
- l1_clip[1] = isect;
- ok1 = 1;
- }
- else {
- l2_clip[0] = rect->xmin;
- l2_clip[1] = isect;
- ok2 = 2;
- }
- }
-
- if (ok1 && ok2) return 1;
-
- if (line_isect_x(l1, l2, rect->xmax, &isect) && (isect >= cliprect->ymin) && (isect <= cliprect->ymax)) {
- if (l1[0] > l2[0]) { /* line 1 is outside */
- l1_clip[0] = rect->xmax;
- l1_clip[1] = isect;
- ok1 = 1;
- }
- else {
- l2_clip[0] = rect->xmax;
- l2_clip[1] = isect;
- ok2 = 2;
- }
- }
-
- if (ok1 && ok2) {
- return 1;
- }
- else {
- return 0;
- }
- }
+ /* first account for horizontal, then vertical lines */
+ /* horiz */
+ 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;
+ }
+ /* 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;
+ }
+
+ /* this is a single point (or close to)*/
+ if (fabsf(l1[0] - l2[0]) < PROJ_PIXEL_TOLERANCE) {
+ if (BLI_rctf_isect_pt_v(rect, l1)) {
+ copy_v2_v2(l1_clip, l1);
+ copy_v2_v2(l2_clip, l2);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+ }
+
+ copy_v2_v2(l1_clip, l1);
+ copy_v2_v2(l2_clip, l2);
+ CLAMP(l1_clip[0], rect->xmin, rect->xmax);
+ CLAMP(l2_clip[0], rect->xmin, rect->xmax);
+ return 1;
+ }
+ else if (fabsf(l1[0] - l2[0]) < PROJ_PIXEL_TOLERANCE) {
+ /* is the line out of range on its X axis? */
+ if (l1[0] < rect->xmin || l1[0] > rect->xmax) {
+ return 0;
+ }
+
+ /* line is out of range on its Y axis */
+ if ((l1[1] < rect->ymin && l2[1] < rect->ymin) || (l1[1] > rect->ymax && l2[1] > rect->ymax)) {
+ return 0;
+ }
+
+ /* this is a single point (or close to)*/
+ if (fabsf(l1[1] - l2[1]) < PROJ_PIXEL_TOLERANCE) {
+ if (BLI_rctf_isect_pt_v(rect, l1)) {
+ copy_v2_v2(l1_clip, l1);
+ copy_v2_v2(l2_clip, l2);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+ }
+
+ copy_v2_v2(l1_clip, l1);
+ copy_v2_v2(l2_clip, l2);
+ CLAMP(l1_clip[1], rect->ymin, rect->ymax);
+ CLAMP(l2_clip[1], rect->ymin, rect->ymax);
+ return 1;
+ }
+ else {
+ float isect;
+ short ok1 = 0;
+ short ok2 = 0;
+
+ /* Done with vertical lines */
+
+ /* are either of the points inside the rectangle ? */
+ if (BLI_rctf_isect_pt_v(rect, l1)) {
+ copy_v2_v2(l1_clip, l1);
+ ok1 = 1;
+ }
+
+ if (BLI_rctf_isect_pt_v(rect, l2)) {
+ copy_v2_v2(l2_clip, l2);
+ ok2 = 1;
+ }
+
+ /* line inside rect */
+ if (ok1 && ok2)
+ return 1;
+
+ /* top/bottom */
+ if (line_isect_y(l1, l2, rect->ymin, &isect) && (isect >= cliprect->xmin) &&
+ (isect <= cliprect->xmax)) {
+ if (l1[1] < l2[1]) { /* line 1 is outside */
+ l1_clip[0] = isect;
+ l1_clip[1] = rect->ymin;
+ ok1 = 1;
+ }
+ else {
+ l2_clip[0] = isect;
+ l2_clip[1] = rect->ymin;
+ ok2 = 2;
+ }
+ }
+
+ if (ok1 && ok2)
+ return 1;
+
+ if (line_isect_y(l1, l2, rect->ymax, &isect) && (isect >= cliprect->xmin) &&
+ (isect <= cliprect->xmax)) {
+ if (l1[1] > l2[1]) { /* line 1 is outside */
+ l1_clip[0] = isect;
+ l1_clip[1] = rect->ymax;
+ ok1 = 1;
+ }
+ else {
+ l2_clip[0] = isect;
+ l2_clip[1] = rect->ymax;
+ ok2 = 2;
+ }
+ }
+
+ if (ok1 && ok2)
+ return 1;
+
+ /* left/right */
+ if (line_isect_x(l1, l2, rect->xmin, &isect) && (isect >= cliprect->ymin) &&
+ (isect <= cliprect->ymax)) {
+ if (l1[0] < l2[0]) { /* line 1 is outside */
+ l1_clip[0] = rect->xmin;
+ l1_clip[1] = isect;
+ ok1 = 1;
+ }
+ else {
+ l2_clip[0] = rect->xmin;
+ l2_clip[1] = isect;
+ ok2 = 2;
+ }
+ }
+
+ if (ok1 && ok2)
+ return 1;
+
+ if (line_isect_x(l1, l2, rect->xmax, &isect) && (isect >= cliprect->ymin) &&
+ (isect <= cliprect->ymax)) {
+ if (l1[0] > l2[0]) { /* line 1 is outside */
+ l1_clip[0] = rect->xmax;
+ l1_clip[1] = isect;
+ ok1 = 1;
+ }
+ else {
+ l2_clip[0] = rect->xmax;
+ l2_clip[1] = isect;
+ ok2 = 2;
+ }
+ }
+
+ if (ok1 && ok2) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+ }
}
-
-
/**
* Scale the tri about its center
* scaling by #PROJ_FACE_SCALE_SEAM (0.99x) is used for getting fake UV pixel coords that are on the
@@ -2149,82 +2177,93 @@ static bool line_clip_rect2f(
static void scale_tri(float insetCos[3][3], const float *origCos[4], const float inset)
{
- float cent[3];
- cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0]) * (1.0f / 3.0f);
- cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1]) * (1.0f / 3.0f);
- cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2]) * (1.0f / 3.0f);
-
- sub_v3_v3v3(insetCos[0], origCos[0], cent);
- sub_v3_v3v3(insetCos[1], origCos[1], cent);
- sub_v3_v3v3(insetCos[2], origCos[2], cent);
-
- mul_v3_fl(insetCos[0], inset);
- mul_v3_fl(insetCos[1], inset);
- mul_v3_fl(insetCos[2], inset);
-
- add_v3_v3(insetCos[0], cent);
- add_v3_v3(insetCos[1], cent);
- add_v3_v3(insetCos[2], cent);
+ float cent[3];
+ cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0]) * (1.0f / 3.0f);
+ cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1]) * (1.0f / 3.0f);
+ cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2]) * (1.0f / 3.0f);
+
+ sub_v3_v3v3(insetCos[0], origCos[0], cent);
+ sub_v3_v3v3(insetCos[1], origCos[1], cent);
+ sub_v3_v3v3(insetCos[2], origCos[2], cent);
+
+ mul_v3_fl(insetCos[0], inset);
+ mul_v3_fl(insetCos[1], inset);
+ mul_v3_fl(insetCos[2], inset);
+
+ add_v3_v3(insetCos[0], cent);
+ add_v3_v3(insetCos[1], cent);
+ add_v3_v3(insetCos[2], cent);
}
-#endif //PROJ_DEBUG_NOSEAMBLEED
+#endif //PROJ_DEBUG_NOSEAMBLEED
static float len_squared_v2v2_alt(const float v1[2], const float v2_1, const float v2_2)
{
- float x, y;
+ float x, y;
- x = v1[0] - v2_1;
- y = v1[1] - v2_2;
- return x * x + y * y;
+ x = v1[0] - v2_1;
+ y = v1[1] - v2_2;
+ return x * x + y * y;
}
/* note, use a squared value so we can use len_squared_v2v2
* be sure that you have done a bounds check first or this may fail */
/* only give bucket_bounds as an arg because we need it elsewhere */
-static bool project_bucket_isect_circle(const float cent[2], const float radius_squared, const rctf *bucket_bounds)
+static bool project_bucket_isect_circle(const float cent[2],
+ const float radius_squared,
+ const rctf *bucket_bounds)
{
- /* Would normally to a simple intersection test, however we know the bounds of these 2 already intersect
- * so we only need to test if the center is inside the vertical or horizontal bounds on either axis,
- * this is even less work then an intersection test
- */
+ /* Would normally to a simple intersection test, however we know the bounds of these 2 already intersect
+ * so we only need to test if the center is inside the vertical or horizontal bounds on either axis,
+ * this is even less work then an intersection test
+ */
#if 0
- if (BLI_rctf_isect_pt_v(bucket_bounds, cent))
- return 1;
+ if (BLI_rctf_isect_pt_v(bucket_bounds, cent))
+ return 1;
#endif
- if ((bucket_bounds->xmin <= cent[0] && bucket_bounds->xmax >= cent[0]) ||
- (bucket_bounds->ymin <= cent[1] && bucket_bounds->ymax >= cent[1]))
- {
- return 1;
- }
-
- /* out of bounds left */
- if (cent[0] < bucket_bounds->xmin) {
- /* lower left out of radius test */
- if (cent[1] < bucket_bounds->ymin) {
- return (len_squared_v2v2_alt(cent, bucket_bounds->xmin, bucket_bounds->ymin) < radius_squared) ? 1 : 0;
- }
- /* 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;
- }
- }
- else if (cent[0] > bucket_bounds->xmax) {
- /* lower right out of radius test */
- if (cent[1] < bucket_bounds->ymin) {
- return (len_squared_v2v2_alt(cent, bucket_bounds->xmax, bucket_bounds->ymin) < radius_squared) ? 1 : 0;
- }
- /* 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;
- }
- }
-
- return 0;
+ if ((bucket_bounds->xmin <= cent[0] && bucket_bounds->xmax >= cent[0]) ||
+ (bucket_bounds->ymin <= cent[1] && bucket_bounds->ymax >= cent[1])) {
+ return 1;
+ }
+
+ /* out of bounds left */
+ if (cent[0] < bucket_bounds->xmin) {
+ /* lower left out of radius test */
+ if (cent[1] < bucket_bounds->ymin) {
+ return (len_squared_v2v2_alt(cent, bucket_bounds->xmin, bucket_bounds->ymin) <
+ radius_squared) ?
+ 1 :
+ 0;
+ }
+ /* 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;
+ }
+ }
+ else if (cent[0] > bucket_bounds->xmax) {
+ /* lower right out of radius test */
+ if (cent[1] < bucket_bounds->ymin) {
+ return (len_squared_v2v2_alt(cent, bucket_bounds->xmax, bucket_bounds->ymin) <
+ radius_squared) ?
+ 1 :
+ 0;
+ }
+ /* 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;
+ }
+ }
+
+ return 0;
}
-
-
/* Note for rect_to_uvspace_ortho() and rect_to_uvspace_persp()
* in ortho view this function gives good results when bucket_bounds are outside the triangle
* however in some cases, perspective view will mess up with faces that have minimal screenspace area
@@ -2234,70 +2273,75 @@ static bool project_bucket_isect_circle(const float cent[2], const float radius_
* funcs that only account for points inside the triangle.
* however switching back to this for ortho is always an option */
-static void rect_to_uvspace_ortho(
- const rctf *bucket_bounds,
- const float *v1coSS, const float *v2coSS, const float *v3coSS,
- const float *uv1co, const float *uv2co, const float *uv3co,
- float bucket_bounds_uv[4][2],
- const int flip)
+static void rect_to_uvspace_ortho(const rctf *bucket_bounds,
+ const float *v1coSS,
+ const float *v2coSS,
+ const float *v3coSS,
+ const float *uv1co,
+ const float *uv2co,
+ const float *uv3co,
+ float bucket_bounds_uv[4][2],
+ const int flip)
{
- float uv[2];
- float w[3];
-
- /* get the UV space bounding box */
- uv[0] = bucket_bounds->xmax;
- uv[1] = bucket_bounds->ymin;
- barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
- interp_v2_v2v2v2(bucket_bounds_uv[flip ? 3 : 0], uv1co, uv2co, uv3co, w);
-
- //uv[0] = bucket_bounds->xmax; // set above
- uv[1] = bucket_bounds->ymax;
- barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
- interp_v2_v2v2v2(bucket_bounds_uv[flip ? 2 : 1], uv1co, uv2co, uv3co, w);
-
- uv[0] = bucket_bounds->xmin;
- //uv[1] = bucket_bounds->ymax; // set above
- barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
- interp_v2_v2v2v2(bucket_bounds_uv[flip ? 1 : 2], uv1co, uv2co, uv3co, w);
-
- //uv[0] = bucket_bounds->xmin; // set above
- uv[1] = bucket_bounds->ymin;
- barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
- interp_v2_v2v2v2(bucket_bounds_uv[flip ? 0 : 3], uv1co, uv2co, uv3co, w);
+ float uv[2];
+ float w[3];
+
+ /* get the UV space bounding box */
+ uv[0] = bucket_bounds->xmax;
+ uv[1] = bucket_bounds->ymin;
+ barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
+ interp_v2_v2v2v2(bucket_bounds_uv[flip ? 3 : 0], uv1co, uv2co, uv3co, w);
+
+ //uv[0] = bucket_bounds->xmax; // set above
+ uv[1] = bucket_bounds->ymax;
+ barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
+ interp_v2_v2v2v2(bucket_bounds_uv[flip ? 2 : 1], uv1co, uv2co, uv3co, w);
+
+ uv[0] = bucket_bounds->xmin;
+ //uv[1] = bucket_bounds->ymax; // set above
+ barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
+ interp_v2_v2v2v2(bucket_bounds_uv[flip ? 1 : 2], uv1co, uv2co, uv3co, w);
+
+ //uv[0] = bucket_bounds->xmin; // set above
+ uv[1] = bucket_bounds->ymin;
+ barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
+ interp_v2_v2v2v2(bucket_bounds_uv[flip ? 0 : 3], uv1co, uv2co, uv3co, w);
}
/* same as above but use barycentric_weights_v2_persp */
-static void rect_to_uvspace_persp(
- const rctf *bucket_bounds,
- const float *v1coSS, const float *v2coSS, const float *v3coSS,
- const float *uv1co, const float *uv2co, const float *uv3co,
- float bucket_bounds_uv[4][2],
- const int flip
- )
+static void rect_to_uvspace_persp(const rctf *bucket_bounds,
+ const float *v1coSS,
+ const float *v2coSS,
+ const float *v3coSS,
+ const float *uv1co,
+ const float *uv2co,
+ const float *uv3co,
+ float bucket_bounds_uv[4][2],
+ const int flip)
{
- float uv[2];
- float w[3];
-
- /* get the UV space bounding box */
- uv[0] = bucket_bounds->xmax;
- uv[1] = bucket_bounds->ymin;
- barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
- interp_v2_v2v2v2(bucket_bounds_uv[flip ? 3 : 0], uv1co, uv2co, uv3co, w);
-
- //uv[0] = bucket_bounds->xmax; // set above
- uv[1] = bucket_bounds->ymax;
- barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
- interp_v2_v2v2v2(bucket_bounds_uv[flip ? 2 : 1], uv1co, uv2co, uv3co, w);
-
- uv[0] = bucket_bounds->xmin;
- //uv[1] = bucket_bounds->ymax; // set above
- barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
- interp_v2_v2v2v2(bucket_bounds_uv[flip ? 1 : 2], uv1co, uv2co, uv3co, w);
-
- //uv[0] = bucket_bounds->xmin; // set above
- uv[1] = bucket_bounds->ymin;
- barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
- interp_v2_v2v2v2(bucket_bounds_uv[flip ? 0 : 3], uv1co, uv2co, uv3co, w);
+ float uv[2];
+ float w[3];
+
+ /* get the UV space bounding box */
+ uv[0] = bucket_bounds->xmax;
+ uv[1] = bucket_bounds->ymin;
+ barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
+ interp_v2_v2v2v2(bucket_bounds_uv[flip ? 3 : 0], uv1co, uv2co, uv3co, w);
+
+ //uv[0] = bucket_bounds->xmax; // set above
+ uv[1] = bucket_bounds->ymax;
+ barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
+ interp_v2_v2v2v2(bucket_bounds_uv[flip ? 2 : 1], uv1co, uv2co, uv3co, w);
+
+ uv[0] = bucket_bounds->xmin;
+ //uv[1] = bucket_bounds->ymax; // set above
+ barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
+ interp_v2_v2v2v2(bucket_bounds_uv[flip ? 1 : 2], uv1co, uv2co, uv3co, w);
+
+ //uv[0] = bucket_bounds->xmin; // set above
+ uv[1] = bucket_bounds->ymin;
+ barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
+ interp_v2_v2v2v2(bucket_bounds_uv[flip ? 0 : 3], uv1co, uv2co, uv3co, w);
}
/* This works as we need it to but we can save a few steps and not use it */
@@ -2305,12 +2349,12 @@ static void rect_to_uvspace_persp(
#if 0
static float angle_2d_clockwise(const float p1[2], const float p2[2], const float p3[2])
{
- float v1[2], v2[2];
+ float v1[2], v2[2];
- v1[0] = p1[0] - p2[0]; v1[1] = p1[1] - p2[1];
- v2[0] = p3[0] - p2[0]; v2[1] = p3[1] - p2[1];
+ v1[0] = p1[0] - p2[0]; v1[1] = p1[1] - p2[1];
+ v2[0] = p3[0] - p2[0]; v2[1] = p3[1] - p2[1];
- return -atan2f(v1[0] * v2[1] - v1[1] * v2[0], v1[0] * v2[0] + v1[1] * v2[1]);
+ return -atan2f(v1[0] * v2[1] - v1[1] * v2[0], v1[0] * v2[0] + v1[1] * v2[1]);
}
#endif
@@ -2323,13 +2367,10 @@ static float angle_2d_clockwise(const float p1[2], const float p2[2], const floa
/* limit must be a fraction over 1.0f */
static bool IsectPT2Df_limit(
- const float pt[2],
- const float v1[2], const float v2[2], const float v3[2],
- const float limit)
+ const float pt[2], const float v1[2], const float v2[2], const float v3[2], const float limit)
{
- return ((area_tri_v2(pt, v1, v2) +
- area_tri_v2(pt, v2, v3) +
- area_tri_v2(pt, v3, v1)) / (area_tri_v2(v1, v2, v3))) < limit;
+ return ((area_tri_v2(pt, v1, v2) + area_tri_v2(pt, v2, v3) + area_tri_v2(pt, v3, v1)) /
+ (area_tri_v2(v1, v2, v3))) < limit;
}
/* Clip the face by a bucket and set the uv-space bucket_bounds_uv
@@ -2337,360 +2378,445 @@ static bool IsectPT2Df_limit(
* */
static int float_z_sort_flip(const void *p1, const void *p2)
{
- return (((float *)p1)[2] < ((float *)p2)[2] ? 1 : -1);
+ return (((float *)p1)[2] < ((float *)p2)[2] ? 1 : -1);
}
static int float_z_sort(const void *p1, const void *p2)
{
- return (((float *)p1)[2] < ((float *)p2)[2] ? -1 : 1);
+ return (((float *)p1)[2] < ((float *)p2)[2] ? -1 : 1);
}
/* assumes one point is within the rectangle */
-static bool line_rect_clip(
- const rctf *rect,
- const float l1[4], const float l2[4],
- const float uv1[2], const float uv2[2],
- float uv[2], bool is_ortho)
+static bool line_rect_clip(const rctf *rect,
+ const float l1[4],
+ const float l2[4],
+ const float uv1[2],
+ const float uv2[2],
+ float uv[2],
+ bool is_ortho)
{
- float min = FLT_MAX, tmp;
- float xlen = l2[0] - l1[0];
- float ylen = l2[1] - l1[1];
-
- /* 0.1 might seem too much, but remember, this is pixels! */
- if (xlen > 0.1f) {
- if ((l1[0] - rect->xmin) * (l2[0] - rect->xmin) <= 0) {
- tmp = rect->xmin;
- min = min_ff((tmp - l1[0]) / xlen, min);
- }
- else if ((l1[0] - rect->xmax) * (l2[0] - rect->xmax) < 0) {
- tmp = rect->xmax;
- min = min_ff((tmp - l1[0]) / xlen, min);
- }
- }
-
- if (ylen > 0.1f) {
- if ((l1[1] - rect->ymin) * (l2[1] - rect->ymin) <= 0) {
- tmp = rect->ymin;
- min = min_ff((tmp - l1[1]) / ylen, min);
- }
- else if ((l1[1] - rect->ymax) * (l2[1] - rect->ymax) < 0) {
- tmp = rect->ymax;
- min = min_ff((tmp - l1[1]) / ylen, min);
- }
- }
-
- if (min == FLT_MAX)
- return false;
-
- tmp = (is_ortho) ? 1.0f : (l1[3] + min * (l2[3] - l1[3]));
-
- uv[0] = (uv1[0] + min / tmp * (uv2[0] - uv1[0]));
- uv[1] = (uv1[1] + min / tmp * (uv2[1] - uv1[1]));
-
- return true;
+ float min = FLT_MAX, tmp;
+ float xlen = l2[0] - l1[0];
+ float ylen = l2[1] - l1[1];
+
+ /* 0.1 might seem too much, but remember, this is pixels! */
+ if (xlen > 0.1f) {
+ if ((l1[0] - rect->xmin) * (l2[0] - rect->xmin) <= 0) {
+ tmp = rect->xmin;
+ min = min_ff((tmp - l1[0]) / xlen, min);
+ }
+ else if ((l1[0] - rect->xmax) * (l2[0] - rect->xmax) < 0) {
+ tmp = rect->xmax;
+ min = min_ff((tmp - l1[0]) / xlen, min);
+ }
+ }
+
+ if (ylen > 0.1f) {
+ if ((l1[1] - rect->ymin) * (l2[1] - rect->ymin) <= 0) {
+ tmp = rect->ymin;
+ min = min_ff((tmp - l1[1]) / ylen, min);
+ }
+ else if ((l1[1] - rect->ymax) * (l2[1] - rect->ymax) < 0) {
+ tmp = rect->ymax;
+ min = min_ff((tmp - l1[1]) / ylen, min);
+ }
+ }
+
+ if (min == FLT_MAX)
+ return false;
+
+ tmp = (is_ortho) ? 1.0f : (l1[3] + min * (l2[3] - l1[3]));
+
+ uv[0] = (uv1[0] + min / tmp * (uv2[0] - uv1[0]));
+ uv[1] = (uv1[1] + min / tmp * (uv2[1] - uv1[1]));
+
+ return true;
}
-
-static void project_bucket_clip_face(
- const bool is_ortho, const bool is_flip_object,
- const rctf *cliprect,
- const rctf *bucket_bounds,
- const float *v1coSS, const float *v2coSS, const float *v3coSS,
- const float *uv1co, const float *uv2co, const float *uv3co,
- float bucket_bounds_uv[8][2],
- int *tot, bool cull)
+static void project_bucket_clip_face(const bool is_ortho,
+ const bool is_flip_object,
+ const rctf *cliprect,
+ const rctf *bucket_bounds,
+ const float *v1coSS,
+ const float *v2coSS,
+ const float *v3coSS,
+ const float *uv1co,
+ const float *uv2co,
+ const float *uv3co,
+ float bucket_bounds_uv[8][2],
+ int *tot,
+ bool cull)
{
- int inside_bucket_flag = 0;
- int inside_face_flag = 0;
- int flip;
- bool collinear = false;
-
- float bucket_bounds_ss[4][2];
-
- /* detect pathological case where face the three vertices are almost collinear in screen space.
- * mostly those will be culled but when flood filling or with
- * smooth shading it's a possibility */
- if (min_fff(dist_squared_to_line_v2(v1coSS, v2coSS, v3coSS),
- dist_squared_to_line_v2(v2coSS, v3coSS, v1coSS),
- dist_squared_to_line_v2(v3coSS, v1coSS, v2coSS)) < PROJ_PIXEL_TOLERANCE)
- {
- collinear = true;
- }
-
- /* get the UV space bounding box */
- inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v1coSS);
- inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v2coSS) << 1;
- inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v3coSS) << 2;
-
- if (inside_bucket_flag == ISECT_ALL3) {
- /* is_flip_object is used here because we use the face winding */
- flip = (((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) != is_flip_object) !=
- (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f));
-
- /* all screenspace points are inside the bucket bounding box,
- * this means we don't need to clip and can simply return the UVs */
- if (flip) { /* facing the back? */
- copy_v2_v2(bucket_bounds_uv[0], uv3co);
- copy_v2_v2(bucket_bounds_uv[1], uv2co);
- copy_v2_v2(bucket_bounds_uv[2], uv1co);
- }
- else {
- copy_v2_v2(bucket_bounds_uv[0], uv1co);
- copy_v2_v2(bucket_bounds_uv[1], uv2co);
- copy_v2_v2(bucket_bounds_uv[2], uv3co);
- }
-
- *tot = 3;
- return;
- }
- /* Handle pathological case here,
- * no need for further intersections below since triangle area is almost zero. */
- if (collinear) {
- int flag;
-
- (*tot) = 0;
-
- if (cull)
- return;
-
- if (inside_bucket_flag & ISECT_1) { copy_v2_v2(bucket_bounds_uv[*tot], uv1co); (*tot)++; }
-
- flag = inside_bucket_flag & (ISECT_1 | ISECT_2);
- if (flag && flag != (ISECT_1 | ISECT_2)) {
- if (line_rect_clip(bucket_bounds, v1coSS, v2coSS, uv1co, uv2co, bucket_bounds_uv[*tot], is_ortho))
- (*tot)++;
- }
-
- if (inside_bucket_flag & ISECT_2) { copy_v2_v2(bucket_bounds_uv[*tot], uv2co); (*tot)++; }
-
- flag = inside_bucket_flag & (ISECT_2 | ISECT_3);
- if (flag && flag != (ISECT_2 | ISECT_3)) {
- if (line_rect_clip(bucket_bounds, v2coSS, v3coSS, uv2co, uv3co, bucket_bounds_uv[*tot], is_ortho))
- (*tot)++;
- }
-
- if (inside_bucket_flag & ISECT_3) { copy_v2_v2(bucket_bounds_uv[*tot], uv3co); (*tot)++; }
-
- flag = inside_bucket_flag & (ISECT_3 | ISECT_1);
- if (flag && flag != (ISECT_3 | ISECT_1)) {
- if (line_rect_clip(bucket_bounds, v3coSS, v1coSS, uv3co, uv1co, bucket_bounds_uv[*tot], is_ortho))
- (*tot)++;
- }
-
- if ((*tot) < 3) {
- /* no intersections to speak of, but more probable is that all face is just outside the
- * rectangle and culled due to float precision issues. Since above tests have failed,
- * just dump triangle as is for painting */
- *tot = 0;
- copy_v2_v2(bucket_bounds_uv[*tot], uv1co); (*tot)++;
- copy_v2_v2(bucket_bounds_uv[*tot], uv2co); (*tot)++;
- copy_v2_v2(bucket_bounds_uv[*tot], uv3co); (*tot)++;
- return;
- }
-
- return;
- }
-
- /* get the UV space bounding box */
- /* use IsectPT2Df_limit here so we catch points are are touching the tri edge
- * (or a small fraction over) */
- bucket_bounds_ss[0][0] = bucket_bounds->xmax;
- bucket_bounds_ss[0][1] = bucket_bounds->ymin;
- inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[0], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_1 : 0);
-
- bucket_bounds_ss[1][0] = bucket_bounds->xmax;
- bucket_bounds_ss[1][1] = bucket_bounds->ymax;
- inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[1], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_2 : 0);
-
- bucket_bounds_ss[2][0] = bucket_bounds->xmin;
- bucket_bounds_ss[2][1] = bucket_bounds->ymax;
- inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[2], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_3 : 0);
-
- bucket_bounds_ss[3][0] = bucket_bounds->xmin;
- bucket_bounds_ss[3][1] = bucket_bounds->ymin;
- inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[3], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_4 : 0);
-
- flip = ((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) !=
- (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f));
-
- if (inside_face_flag == ISECT_ALL4) {
- /* bucket is totally inside the screenspace face, we can safely use weights */
-
- if (is_ortho) {
- rect_to_uvspace_ortho(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip);
- }
- else {
- rect_to_uvspace_persp(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip);
- }
-
- *tot = 4;
- return;
- }
- else {
- /* The Complicated Case!
- *
- * The 2 cases above are where the face is inside the bucket
- * or the bucket is inside the face.
- *
- * we need to make a convex polyline from the intersection between the screenspace face
- * and the bucket bounds.
- *
- * There are a number of ways this could be done, currently it just collects all
- * intersecting verts, and line intersections, then sorts them clockwise, this is
- * a lot easier then evaluating the geometry to do a correct clipping on both shapes.
- */
-
-
- /* Add a bunch of points, we know must make up the convex hull
- * which is the clipped rect and triangle */
-
- /* Maximum possible 6 intersections when using a rectangle and triangle */
-
- /* The 3rd float is used to store angle for qsort(), NOT as a Z location */
- float isectVCosSS[8][3];
- float v1_clipSS[2], v2_clipSS[2];
- float w[3];
-
- /* calc center */
- float cent[2] = {0.0f, 0.0f};
- /*float up[2] = {0.0f, 1.0f};*/
- int i;
- bool doubles;
-
- (*tot) = 0;
-
- if (inside_face_flag & ISECT_1) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[0]); (*tot)++; }
- if (inside_face_flag & ISECT_2) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[1]); (*tot)++; }
- if (inside_face_flag & ISECT_3) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[2]); (*tot)++; }
- if (inside_face_flag & ISECT_4) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[3]); (*tot)++; }
-
- if (inside_bucket_flag & ISECT_1) { copy_v2_v2(isectVCosSS[*tot], v1coSS); (*tot)++; }
- if (inside_bucket_flag & ISECT_2) { copy_v2_v2(isectVCosSS[*tot], v2coSS); (*tot)++; }
- if (inside_bucket_flag & ISECT_3) { copy_v2_v2(isectVCosSS[*tot], v3coSS); (*tot)++; }
-
- if ((inside_bucket_flag & (ISECT_1 | ISECT_2)) != (ISECT_1 | ISECT_2)) {
- if (line_clip_rect2f(cliprect, bucket_bounds, v1coSS, v2coSS, v1_clipSS, v2_clipSS)) {
- if ((inside_bucket_flag & ISECT_1) == 0) { copy_v2_v2(isectVCosSS[*tot], v1_clipSS); (*tot)++; }
- if ((inside_bucket_flag & ISECT_2) == 0) { copy_v2_v2(isectVCosSS[*tot], v2_clipSS); (*tot)++; }
- }
- }
-
- if ((inside_bucket_flag & (ISECT_2 | ISECT_3)) != (ISECT_2 | ISECT_3)) {
- if (line_clip_rect2f(cliprect, bucket_bounds, v2coSS, v3coSS, v1_clipSS, v2_clipSS)) {
- if ((inside_bucket_flag & ISECT_2) == 0) { copy_v2_v2(isectVCosSS[*tot], v1_clipSS); (*tot)++; }
- if ((inside_bucket_flag & ISECT_3) == 0) { copy_v2_v2(isectVCosSS[*tot], v2_clipSS); (*tot)++; }
- }
- }
-
- if ((inside_bucket_flag & (ISECT_3 | ISECT_1)) != (ISECT_3 | ISECT_1)) {
- if (line_clip_rect2f(cliprect, bucket_bounds, v3coSS, v1coSS, v1_clipSS, v2_clipSS)) {
- if ((inside_bucket_flag & ISECT_3) == 0) { copy_v2_v2(isectVCosSS[*tot], v1_clipSS); (*tot)++; }
- if ((inside_bucket_flag & ISECT_1) == 0) { copy_v2_v2(isectVCosSS[*tot], v2_clipSS); (*tot)++; }
- }
- }
-
-
- if ((*tot) < 3) { /* no intersections to speak of */
- *tot = 0;
- return;
- }
-
- /* now we have all points we need, collect their angles and sort them clockwise */
-
- for (i = 0; i < (*tot); i++) {
- cent[0] += isectVCosSS[i][0];
- cent[1] += isectVCosSS[i][1];
- }
- cent[0] = cent[0] / (float)(*tot);
- cent[1] = cent[1] / (float)(*tot);
-
-
-
- /* Collect angles for every point around the center point */
-
-
-#if 0 /* uses a few more cycles then the above loop */
- for (i = 0; i < (*tot); i++) {
- isectVCosSS[i][2] = angle_2d_clockwise(up, cent, isectVCosSS[i]);
- }
+ int inside_bucket_flag = 0;
+ int inside_face_flag = 0;
+ int flip;
+ bool collinear = false;
+
+ float bucket_bounds_ss[4][2];
+
+ /* detect pathological case where face the three vertices are almost collinear in screen space.
+ * mostly those will be culled but when flood filling or with
+ * smooth shading it's a possibility */
+ if (min_fff(dist_squared_to_line_v2(v1coSS, v2coSS, v3coSS),
+ dist_squared_to_line_v2(v2coSS, v3coSS, v1coSS),
+ dist_squared_to_line_v2(v3coSS, v1coSS, v2coSS)) < PROJ_PIXEL_TOLERANCE) {
+ collinear = true;
+ }
+
+ /* get the UV space bounding box */
+ inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v1coSS);
+ inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v2coSS) << 1;
+ inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v3coSS) << 2;
+
+ if (inside_bucket_flag == ISECT_ALL3) {
+ /* is_flip_object is used here because we use the face winding */
+ flip = (((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) != is_flip_object) !=
+ (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f));
+
+ /* all screenspace points are inside the bucket bounding box,
+ * this means we don't need to clip and can simply return the UVs */
+ if (flip) { /* facing the back? */
+ copy_v2_v2(bucket_bounds_uv[0], uv3co);
+ copy_v2_v2(bucket_bounds_uv[1], uv2co);
+ copy_v2_v2(bucket_bounds_uv[2], uv1co);
+ }
+ else {
+ copy_v2_v2(bucket_bounds_uv[0], uv1co);
+ copy_v2_v2(bucket_bounds_uv[1], uv2co);
+ copy_v2_v2(bucket_bounds_uv[2], uv3co);
+ }
+
+ *tot = 3;
+ return;
+ }
+ /* Handle pathological case here,
+ * no need for further intersections below since triangle area is almost zero. */
+ if (collinear) {
+ int flag;
+
+ (*tot) = 0;
+
+ if (cull)
+ return;
+
+ if (inside_bucket_flag & ISECT_1) {
+ copy_v2_v2(bucket_bounds_uv[*tot], uv1co);
+ (*tot)++;
+ }
+
+ flag = inside_bucket_flag & (ISECT_1 | ISECT_2);
+ if (flag && flag != (ISECT_1 | ISECT_2)) {
+ if (line_rect_clip(
+ bucket_bounds, v1coSS, v2coSS, uv1co, uv2co, bucket_bounds_uv[*tot], is_ortho))
+ (*tot)++;
+ }
+
+ if (inside_bucket_flag & ISECT_2) {
+ copy_v2_v2(bucket_bounds_uv[*tot], uv2co);
+ (*tot)++;
+ }
+
+ flag = inside_bucket_flag & (ISECT_2 | ISECT_3);
+ if (flag && flag != (ISECT_2 | ISECT_3)) {
+ if (line_rect_clip(
+ bucket_bounds, v2coSS, v3coSS, uv2co, uv3co, bucket_bounds_uv[*tot], is_ortho))
+ (*tot)++;
+ }
+
+ if (inside_bucket_flag & ISECT_3) {
+ copy_v2_v2(bucket_bounds_uv[*tot], uv3co);
+ (*tot)++;
+ }
+
+ flag = inside_bucket_flag & (ISECT_3 | ISECT_1);
+ if (flag && flag != (ISECT_3 | ISECT_1)) {
+ if (line_rect_clip(
+ bucket_bounds, v3coSS, v1coSS, uv3co, uv1co, bucket_bounds_uv[*tot], is_ortho))
+ (*tot)++;
+ }
+
+ if ((*tot) < 3) {
+ /* no intersections to speak of, but more probable is that all face is just outside the
+ * rectangle and culled due to float precision issues. Since above tests have failed,
+ * just dump triangle as is for painting */
+ *tot = 0;
+ copy_v2_v2(bucket_bounds_uv[*tot], uv1co);
+ (*tot)++;
+ copy_v2_v2(bucket_bounds_uv[*tot], uv2co);
+ (*tot)++;
+ copy_v2_v2(bucket_bounds_uv[*tot], uv3co);
+ (*tot)++;
+ return;
+ }
+
+ return;
+ }
+
+ /* get the UV space bounding box */
+ /* use IsectPT2Df_limit here so we catch points are are touching the tri edge
+ * (or a small fraction over) */
+ bucket_bounds_ss[0][0] = bucket_bounds->xmax;
+ bucket_bounds_ss[0][1] = bucket_bounds->ymin;
+ inside_face_flag |= (IsectPT2Df_limit(
+ bucket_bounds_ss[0], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ?
+ ISECT_1 :
+ 0);
+
+ bucket_bounds_ss[1][0] = bucket_bounds->xmax;
+ bucket_bounds_ss[1][1] = bucket_bounds->ymax;
+ inside_face_flag |= (IsectPT2Df_limit(
+ bucket_bounds_ss[1], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ?
+ ISECT_2 :
+ 0);
+
+ bucket_bounds_ss[2][0] = bucket_bounds->xmin;
+ bucket_bounds_ss[2][1] = bucket_bounds->ymax;
+ inside_face_flag |= (IsectPT2Df_limit(
+ bucket_bounds_ss[2], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ?
+ ISECT_3 :
+ 0);
+
+ bucket_bounds_ss[3][0] = bucket_bounds->xmin;
+ bucket_bounds_ss[3][1] = bucket_bounds->ymin;
+ inside_face_flag |= (IsectPT2Df_limit(
+ bucket_bounds_ss[3], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ?
+ ISECT_4 :
+ 0);
+
+ flip = ((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) !=
+ (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f));
+
+ if (inside_face_flag == ISECT_ALL4) {
+ /* bucket is totally inside the screenspace face, we can safely use weights */
+
+ if (is_ortho) {
+ rect_to_uvspace_ortho(
+ bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip);
+ }
+ else {
+ rect_to_uvspace_persp(
+ bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip);
+ }
+
+ *tot = 4;
+ return;
+ }
+ else {
+ /* The Complicated Case!
+ *
+ * The 2 cases above are where the face is inside the bucket
+ * or the bucket is inside the face.
+ *
+ * we need to make a convex polyline from the intersection between the screenspace face
+ * and the bucket bounds.
+ *
+ * There are a number of ways this could be done, currently it just collects all
+ * intersecting verts, and line intersections, then sorts them clockwise, this is
+ * a lot easier then evaluating the geometry to do a correct clipping on both shapes.
+ */
+
+ /* Add a bunch of points, we know must make up the convex hull
+ * which is the clipped rect and triangle */
+
+ /* Maximum possible 6 intersections when using a rectangle and triangle */
+
+ /* The 3rd float is used to store angle for qsort(), NOT as a Z location */
+ float isectVCosSS[8][3];
+ float v1_clipSS[2], v2_clipSS[2];
+ float w[3];
+
+ /* calc center */
+ float cent[2] = {0.0f, 0.0f};
+ /*float up[2] = {0.0f, 1.0f};*/
+ int i;
+ bool doubles;
+
+ (*tot) = 0;
+
+ if (inside_face_flag & ISECT_1) {
+ copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[0]);
+ (*tot)++;
+ }
+ if (inside_face_flag & ISECT_2) {
+ copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[1]);
+ (*tot)++;
+ }
+ if (inside_face_flag & ISECT_3) {
+ copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[2]);
+ (*tot)++;
+ }
+ if (inside_face_flag & ISECT_4) {
+ copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[3]);
+ (*tot)++;
+ }
+
+ if (inside_bucket_flag & ISECT_1) {
+ copy_v2_v2(isectVCosSS[*tot], v1coSS);
+ (*tot)++;
+ }
+ if (inside_bucket_flag & ISECT_2) {
+ copy_v2_v2(isectVCosSS[*tot], v2coSS);
+ (*tot)++;
+ }
+ if (inside_bucket_flag & ISECT_3) {
+ copy_v2_v2(isectVCosSS[*tot], v3coSS);
+ (*tot)++;
+ }
+
+ if ((inside_bucket_flag & (ISECT_1 | ISECT_2)) != (ISECT_1 | ISECT_2)) {
+ if (line_clip_rect2f(cliprect, bucket_bounds, v1coSS, v2coSS, v1_clipSS, v2_clipSS)) {
+ if ((inside_bucket_flag & ISECT_1) == 0) {
+ copy_v2_v2(isectVCosSS[*tot], v1_clipSS);
+ (*tot)++;
+ }
+ if ((inside_bucket_flag & ISECT_2) == 0) {
+ copy_v2_v2(isectVCosSS[*tot], v2_clipSS);
+ (*tot)++;
+ }
+ }
+ }
+
+ if ((inside_bucket_flag & (ISECT_2 | ISECT_3)) != (ISECT_2 | ISECT_3)) {
+ if (line_clip_rect2f(cliprect, bucket_bounds, v2coSS, v3coSS, v1_clipSS, v2_clipSS)) {
+ if ((inside_bucket_flag & ISECT_2) == 0) {
+ copy_v2_v2(isectVCosSS[*tot], v1_clipSS);
+ (*tot)++;
+ }
+ if ((inside_bucket_flag & ISECT_3) == 0) {
+ copy_v2_v2(isectVCosSS[*tot], v2_clipSS);
+ (*tot)++;
+ }
+ }
+ }
+
+ if ((inside_bucket_flag & (ISECT_3 | ISECT_1)) != (ISECT_3 | ISECT_1)) {
+ if (line_clip_rect2f(cliprect, bucket_bounds, v3coSS, v1coSS, v1_clipSS, v2_clipSS)) {
+ if ((inside_bucket_flag & ISECT_3) == 0) {
+ copy_v2_v2(isectVCosSS[*tot], v1_clipSS);
+ (*tot)++;
+ }
+ if ((inside_bucket_flag & ISECT_1) == 0) {
+ copy_v2_v2(isectVCosSS[*tot], v2_clipSS);
+ (*tot)++;
+ }
+ }
+ }
+
+ if ((*tot) < 3) { /* no intersections to speak of */
+ *tot = 0;
+ return;
+ }
+
+ /* now we have all points we need, collect their angles and sort them clockwise */
+
+ for (i = 0; i < (*tot); i++) {
+ cent[0] += isectVCosSS[i][0];
+ cent[1] += isectVCosSS[i][1];
+ }
+ cent[0] = cent[0] / (float)(*tot);
+ cent[1] = cent[1] / (float)(*tot);
+
+ /* Collect angles for every point around the center point */
+
+#if 0 /* uses a few more cycles then the above loop */
+ for (i = 0; i < (*tot); i++) {
+ isectVCosSS[i][2] = angle_2d_clockwise(up, cent, isectVCosSS[i]);
+ }
#endif
- /* Abuse this var for the loop below */
- v1_clipSS[0] = cent[0];
- v1_clipSS[1] = cent[1] + 1.0f;
-
- for (i = 0; i < (*tot); i++) {
- v2_clipSS[0] = isectVCosSS[i][0] - cent[0];
- v2_clipSS[1] = isectVCosSS[i][1] - cent[1];
- isectVCosSS[i][2] = atan2f(v1_clipSS[0] * v2_clipSS[1] - v1_clipSS[1] * v2_clipSS[0],
- v1_clipSS[0] * v2_clipSS[0] + v1_clipSS[1] * v2_clipSS[1]);
- }
-
- if (flip) qsort(isectVCosSS, *tot, sizeof(float) * 3, float_z_sort_flip);
- else qsort(isectVCosSS, *tot, sizeof(float) * 3, float_z_sort);
-
- doubles = true;
- while (doubles == true) {
- doubles = false;
-
- for (i = 0; i < (*tot); i++) {
- if (fabsf(isectVCosSS[(i + 1) % *tot][0] - isectVCosSS[i][0]) < PROJ_PIXEL_TOLERANCE &&
- fabsf(isectVCosSS[(i + 1) % *tot][1] - isectVCosSS[i][1]) < PROJ_PIXEL_TOLERANCE)
- {
- int j;
- for (j = i; j < (*tot) - 1; j++) {
- isectVCosSS[j][0] = isectVCosSS[j + 1][0];
- isectVCosSS[j][1] = isectVCosSS[j + 1][1];
- }
- /* keep looking for more doubles */
- doubles = true;
- (*tot)--;
- }
- }
-
- /* its possible there is only a few left after remove doubles */
- if ((*tot) < 3) {
- // printf("removed too many doubles B\n");
- *tot = 0;
- return;
- }
- }
-
- if (is_ortho) {
- for (i = 0; i < (*tot); i++) {
- barycentric_weights_v2(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w);
- interp_v2_v2v2v2(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w);
- }
- }
- else {
- for (i = 0; i < (*tot); i++) {
- barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w);
- interp_v2_v2v2v2(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w);
- }
- }
- }
+ /* Abuse this var for the loop below */
+ v1_clipSS[0] = cent[0];
+ v1_clipSS[1] = cent[1] + 1.0f;
+
+ for (i = 0; i < (*tot); i++) {
+ v2_clipSS[0] = isectVCosSS[i][0] - cent[0];
+ v2_clipSS[1] = isectVCosSS[i][1] - cent[1];
+ isectVCosSS[i][2] = atan2f(v1_clipSS[0] * v2_clipSS[1] - v1_clipSS[1] * v2_clipSS[0],
+ v1_clipSS[0] * v2_clipSS[0] + v1_clipSS[1] * v2_clipSS[1]);
+ }
+
+ if (flip)
+ qsort(isectVCosSS, *tot, sizeof(float) * 3, float_z_sort_flip);
+ else
+ qsort(isectVCosSS, *tot, sizeof(float) * 3, float_z_sort);
+
+ doubles = true;
+ while (doubles == true) {
+ doubles = false;
+
+ for (i = 0; i < (*tot); i++) {
+ if (fabsf(isectVCosSS[(i + 1) % *tot][0] - isectVCosSS[i][0]) < PROJ_PIXEL_TOLERANCE &&
+ fabsf(isectVCosSS[(i + 1) % *tot][1] - isectVCosSS[i][1]) < PROJ_PIXEL_TOLERANCE) {
+ int j;
+ for (j = i; j < (*tot) - 1; j++) {
+ isectVCosSS[j][0] = isectVCosSS[j + 1][0];
+ isectVCosSS[j][1] = isectVCosSS[j + 1][1];
+ }
+ /* keep looking for more doubles */
+ doubles = true;
+ (*tot)--;
+ }
+ }
+
+ /* its possible there is only a few left after remove doubles */
+ if ((*tot) < 3) {
+ // printf("removed too many doubles B\n");
+ *tot = 0;
+ return;
+ }
+ }
+
+ if (is_ortho) {
+ for (i = 0; i < (*tot); i++) {
+ barycentric_weights_v2(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w);
+ interp_v2_v2v2v2(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w);
+ }
+ }
+ else {
+ for (i = 0; i < (*tot); i++) {
+ barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w);
+ interp_v2_v2v2v2(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w);
+ }
+ }
+ }
#ifdef PROJ_DEBUG_PRINT_CLIP
- /* include this at the bottom of the above function to debug the output */
-
- {
- /* If there are ever any problems, */
- float test_uv[4][2];
- int i;
- if (is_ortho) rect_to_uvspace_ortho(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip);
- else rect_to_uvspace_persp(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip);
- printf("( [(%f,%f), (%f,%f), (%f,%f), (%f,%f)], ",
- test_uv[0][0], test_uv[0][1], test_uv[1][0], test_uv[1][1],
- test_uv[2][0], test_uv[2][1], test_uv[3][0], test_uv[3][1]);
-
- printf(" [(%f,%f), (%f,%f), (%f,%f)], ", uv1co[0], uv1co[1], uv2co[0], uv2co[1], uv3co[0], uv3co[1]);
-
- printf("[");
- for (i = 0; i < (*tot); i++) {
- printf("(%f, %f),", bucket_bounds_uv[i][0], bucket_bounds_uv[i][1]);
- }
- printf("]),\\\n");
- }
+ /* include this at the bottom of the above function to debug the output */
+
+ {
+ /* If there are ever any problems, */
+ float test_uv[4][2];
+ int i;
+ if (is_ortho)
+ rect_to_uvspace_ortho(
+ bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip);
+ else
+ rect_to_uvspace_persp(
+ bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip);
+ printf("( [(%f,%f), (%f,%f), (%f,%f), (%f,%f)], ",
+ test_uv[0][0],
+ test_uv[0][1],
+ test_uv[1][0],
+ test_uv[1][1],
+ test_uv[2][0],
+ test_uv[2][1],
+ test_uv[3][0],
+ test_uv[3][1]);
+
+ printf(" [(%f,%f), (%f,%f), (%f,%f)], ",
+ uv1co[0],
+ uv1co[1],
+ uv2co[0],
+ uv2co[1],
+ uv3co[0],
+ uv3co[1]);
+
+ printf("[");
+ for (i = 0; i < (*tot); i++) {
+ printf("(%f, %f),", bucket_bounds_uv[i][0], bucket_bounds_uv[i][1]);
+ }
+ printf("]),\\\n");
+ }
#endif
}
@@ -2740,7 +2866,6 @@ static void project_bucket_clip_face(
* main()
*/
-
#undef ISECT_1
#undef ISECT_2
#undef ISECT_3
@@ -2748,35 +2873,32 @@ static void project_bucket_clip_face(
#undef ISECT_ALL3
#undef ISECT_ALL4
-
/* checks if pt is inside a convex 2D polyline, the polyline must be ordered rotating clockwise
* otherwise it would have to test for mixed (line_point_side_v2 > 0.0f) cases */
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;
+ int i;
+ if (line_point_side_v2(uv[tot - 1], uv[0], pt) < 0.0f)
+ return 0;
- for (i = 1; i < tot; i++) {
- if (line_point_side_v2(uv[i - 1], uv[i], pt) < 0.0f)
- return 0;
+ for (i = 1; i < tot; i++) {
+ if (line_point_side_v2(uv[i - 1], uv[i], pt) < 0.0f)
+ return 0;
+ }
- }
-
- return 1;
+ return 1;
}
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);
-
- for (i = 1; i < tot; i++) {
- if ((line_point_side_v2(uv[i - 1], uv[i], pt) > 0.0f) != side)
- return 0;
+ int i;
+ bool side = (line_point_side_v2(uv[tot - 1], uv[0], pt) > 0.0f);
- }
+ for (i = 1; i < tot; i++) {
+ if ((line_point_side_v2(uv[i - 1], uv[i], pt) > 0.0f) != side)
+ return 0;
+ }
- return 1;
+ return 1;
}
/* One of the most important function for projection painting,
@@ -2784,1824 +2906,1853 @@ static bool IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot
*
* initialize pixels from this face where it intersects with the bucket_index,
* optionally initialize pixels for removing seams */
-static void project_paint_face_init(
- const ProjPaintState *ps,
- const int thread_index, const int bucket_index, const int tri_index, const int image_index,
- const rctf *clip_rect, const rctf *bucket_bounds, ImBuf *ibuf, ImBuf **tmpibuf)
+static void project_paint_face_init(const ProjPaintState *ps,
+ const int thread_index,
+ const int bucket_index,
+ const int tri_index,
+ const int image_index,
+ const rctf *clip_rect,
+ const rctf *bucket_bounds,
+ ImBuf *ibuf,
+ ImBuf **tmpibuf)
{
- /* Projection vars, to get the 3D locations into screen space */
- MemArena *arena = ps->arena_mt[thread_index];
- LinkNode **bucketPixelNodes = ps->bucketRect + bucket_index;
- LinkNode *bucketFaceNodes = ps->bucketFaces[bucket_index];
- bool threaded = (ps->thread_tot > 1);
-
- TileInfo tinf = {
- ps->tile_lock,
- ps->do_masking,
- IMAPAINT_TILE_NUMBER(ibuf->x),
- tmpibuf,
- ps->projImages + image_index,
- };
-
- const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
- const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
- const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt) };
-
- /* UV/pixel seeking data */
- /* Image X/Y-Pixel */
- int x, y;
- float mask;
- /* Image floating point UV - same as x, y but from 0.0-1.0 */
- float uv[2];
-
- /* vert co screen-space, these will be assigned to lt_vtri[0-2] */
- const float *v1coSS, *v2coSS, *v3coSS;
-
- /* vertex screenspace coords */
- const float *vCo[3];
-
- float w[3], wco[3];
-
- /* for convenience only, these will be assigned to lt_tri_uv[0],1,2 or lt_tri_uv[0],2,3 */
- float *uv1co, *uv2co, *uv3co;
- float pixelScreenCo[4];
- bool do_3d_mapping = ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D;
-
- /* ispace bounds */
- rcti bounds_px;
- /* vars for getting uvspace bounds */
-
- /* bucket bounds in UV space so we can init pixels only for this face, */
- float lt_uv_pxoffset[3][2];
- float xhalfpx, yhalfpx;
- const float ibuf_xf = (float)ibuf->x, ibuf_yf = (float)ibuf->y;
-
- /* for early loop exit */
- int has_x_isect = 0, has_isect = 0;
-
- float uv_clip[8][2];
- int uv_clip_tot;
- const bool is_ortho = ps->is_ortho;
- const bool is_flip_object = ps->is_flip_object;
- const bool do_backfacecull = ps->do_backfacecull;
- const bool do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0;
-
- vCo[0] = ps->mvert_eval[lt_vtri[0]].co;
- vCo[1] = ps->mvert_eval[lt_vtri[1]].co;
- vCo[2] = ps->mvert_eval[lt_vtri[2]].co;
-
-
- /* Use lt_uv_pxoffset instead of lt_tri_uv so we can offset the UV half a pixel
- * this is done so we can avoid offsetting all the pixels by 0.5 which causes
- * problems when wrapping negative coords */
- xhalfpx = (0.5f + (PROJ_PIXEL_TOLERANCE * (1.0f / 3.0f))) / ibuf_xf;
- yhalfpx = (0.5f + (PROJ_PIXEL_TOLERANCE * (1.0f / 4.0f))) / ibuf_yf;
-
- /* Note about (PROJ_GEOM_TOLERANCE/x) above...
- * Needed to add this offset since UV coords are often quads aligned to pixels.
- * In this case pixels can be exactly between 2 triangles causing nasty
- * artifacts.
- *
- * This workaround can be removed and painting will still work on most cases
- * but since the first thing most people try is painting onto a quad- better make it work.
- */
-
- lt_uv_pxoffset[0][0] = lt_tri_uv[0][0] - xhalfpx;
- lt_uv_pxoffset[0][1] = lt_tri_uv[0][1] - yhalfpx;
-
- lt_uv_pxoffset[1][0] = lt_tri_uv[1][0] - xhalfpx;
- lt_uv_pxoffset[1][1] = lt_tri_uv[1][1] - yhalfpx;
-
- lt_uv_pxoffset[2][0] = lt_tri_uv[2][0] - xhalfpx;
- lt_uv_pxoffset[2][1] = lt_tri_uv[2][1] - yhalfpx;
-
- {
- uv1co = lt_uv_pxoffset[0]; // was lt_tri_uv[i1];
- uv2co = lt_uv_pxoffset[1]; // was lt_tri_uv[i2];
- uv3co = lt_uv_pxoffset[2]; // was lt_tri_uv[i3];
-
- v1coSS = ps->screenCoords[lt_vtri[0]];
- v2coSS = ps->screenCoords[lt_vtri[1]];
- v3coSS = ps->screenCoords[lt_vtri[2]];
-
- /* This function gives is a concave polyline in UV space from the clipped tri*/
- project_bucket_clip_face(
- is_ortho, is_flip_object,
- clip_rect, bucket_bounds,
- v1coSS, v2coSS, v3coSS,
- uv1co, uv2co, uv3co,
- uv_clip, &uv_clip_tot,
- do_backfacecull || ps->do_occlude);
-
- /* sometimes this happens, better just allow for 8 intersectiosn even though there should be max 6 */
+ /* Projection vars, to get the 3D locations into screen space */
+ MemArena *arena = ps->arena_mt[thread_index];
+ LinkNode **bucketPixelNodes = ps->bucketRect + bucket_index;
+ LinkNode *bucketFaceNodes = ps->bucketFaces[bucket_index];
+ bool threaded = (ps->thread_tot > 1);
+
+ TileInfo tinf = {
+ ps->tile_lock,
+ ps->do_masking,
+ IMAPAINT_TILE_NUMBER(ibuf->x),
+ tmpibuf,
+ ps->projImages + image_index,
+ };
+
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
+ const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
+ const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
+
+ /* UV/pixel seeking data */
+ /* Image X/Y-Pixel */
+ int x, y;
+ float mask;
+ /* Image floating point UV - same as x, y but from 0.0-1.0 */
+ float uv[2];
+
+ /* vert co screen-space, these will be assigned to lt_vtri[0-2] */
+ const float *v1coSS, *v2coSS, *v3coSS;
+
+ /* vertex screenspace coords */
+ const float *vCo[3];
+
+ float w[3], wco[3];
+
+ /* for convenience only, these will be assigned to lt_tri_uv[0],1,2 or lt_tri_uv[0],2,3 */
+ float *uv1co, *uv2co, *uv3co;
+ float pixelScreenCo[4];
+ bool do_3d_mapping = ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D;
+
+ /* ispace bounds */
+ rcti bounds_px;
+ /* vars for getting uvspace bounds */
+
+ /* bucket bounds in UV space so we can init pixels only for this face, */
+ float lt_uv_pxoffset[3][2];
+ float xhalfpx, yhalfpx;
+ const float ibuf_xf = (float)ibuf->x, ibuf_yf = (float)ibuf->y;
+
+ /* for early loop exit */
+ int has_x_isect = 0, has_isect = 0;
+
+ float uv_clip[8][2];
+ int uv_clip_tot;
+ const bool is_ortho = ps->is_ortho;
+ const bool is_flip_object = ps->is_flip_object;
+ const bool do_backfacecull = ps->do_backfacecull;
+ const bool do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0;
+
+ vCo[0] = ps->mvert_eval[lt_vtri[0]].co;
+ vCo[1] = ps->mvert_eval[lt_vtri[1]].co;
+ vCo[2] = ps->mvert_eval[lt_vtri[2]].co;
+
+ /* Use lt_uv_pxoffset instead of lt_tri_uv so we can offset the UV half a pixel
+ * this is done so we can avoid offsetting all the pixels by 0.5 which causes
+ * problems when wrapping negative coords */
+ xhalfpx = (0.5f + (PROJ_PIXEL_TOLERANCE * (1.0f / 3.0f))) / ibuf_xf;
+ yhalfpx = (0.5f + (PROJ_PIXEL_TOLERANCE * (1.0f / 4.0f))) / ibuf_yf;
+
+ /* Note about (PROJ_GEOM_TOLERANCE/x) above...
+ * Needed to add this offset since UV coords are often quads aligned to pixels.
+ * In this case pixels can be exactly between 2 triangles causing nasty
+ * artifacts.
+ *
+ * This workaround can be removed and painting will still work on most cases
+ * but since the first thing most people try is painting onto a quad- better make it work.
+ */
+
+ lt_uv_pxoffset[0][0] = lt_tri_uv[0][0] - xhalfpx;
+ lt_uv_pxoffset[0][1] = lt_tri_uv[0][1] - yhalfpx;
+
+ lt_uv_pxoffset[1][0] = lt_tri_uv[1][0] - xhalfpx;
+ lt_uv_pxoffset[1][1] = lt_tri_uv[1][1] - yhalfpx;
+
+ lt_uv_pxoffset[2][0] = lt_tri_uv[2][0] - xhalfpx;
+ lt_uv_pxoffset[2][1] = lt_tri_uv[2][1] - yhalfpx;
+
+ {
+ uv1co = lt_uv_pxoffset[0]; // was lt_tri_uv[i1];
+ uv2co = lt_uv_pxoffset[1]; // was lt_tri_uv[i2];
+ uv3co = lt_uv_pxoffset[2]; // was lt_tri_uv[i3];
+
+ v1coSS = ps->screenCoords[lt_vtri[0]];
+ v2coSS = ps->screenCoords[lt_vtri[1]];
+ v3coSS = ps->screenCoords[lt_vtri[2]];
+
+ /* This function gives is a concave polyline in UV space from the clipped tri*/
+ project_bucket_clip_face(is_ortho,
+ is_flip_object,
+ clip_rect,
+ bucket_bounds,
+ v1coSS,
+ v2coSS,
+ v3coSS,
+ uv1co,
+ uv2co,
+ uv3co,
+ uv_clip,
+ &uv_clip_tot,
+ do_backfacecull || ps->do_occlude);
+
+ /* sometimes this happens, better just allow for 8 intersectiosn even though there should be max 6 */
#if 0
- if (uv_clip_tot > 6) {
- printf("this should never happen! %d\n", uv_clip_tot);
- }
+ if (uv_clip_tot > 6) {
+ printf("this should never happen! %d\n", uv_clip_tot);
+ }
#endif
- if (pixel_bounds_array(uv_clip, &bounds_px, ibuf->x, ibuf->y, uv_clip_tot)) {
+ if (pixel_bounds_array(uv_clip, &bounds_px, ibuf->x, ibuf->y, uv_clip_tot)) {
#if 0
- project_paint_undo_tiles_init(
- &bounds_px, ps->projImages + image_index, tmpibuf,
- tile_width, threaded, ps->do_masking);
+ project_paint_undo_tiles_init(
+ &bounds_px, ps->projImages + image_index, tmpibuf,
+ tile_width, threaded, ps->do_masking);
#endif
- /* clip face and */
-
- has_isect = 0;
- for (y = bounds_px.ymin; y < bounds_px.ymax; y++) {
- //uv[1] = (((float)y) + 0.5f) / (float)ibuf->y;
- /* use pixel offset UV coords instead */
- uv[1] = (float)y / ibuf_yf;
-
- has_x_isect = 0;
- for (x = bounds_px.xmin; x < bounds_px.xmax; x++) {
- //uv[0] = (((float)x) + 0.5f) / ibuf->x;
- /* use pixel offset UV coords instead */
- uv[0] = (float)x / ibuf_xf;
-
- /* Note about IsectPoly2Df_twoside, checking the face or uv flipping doesn't work,
- * could check the poly direction but better to do this */
- if ((do_backfacecull == true && IsectPoly2Df(uv, uv_clip, uv_clip_tot)) ||
- (do_backfacecull == false && IsectPoly2Df_twoside(uv, uv_clip, uv_clip_tot)))
- {
-
- has_x_isect = has_isect = 1;
-
- if (is_ortho) screen_px_from_ortho(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
- else screen_px_from_persp(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
-
- /* a pity we need to get the worldspace pixel location here */
- if (do_clip || do_3d_mapping) {
- interp_v3_v3v3v3(
- wco,
- ps->mvert_eval[lt_vtri[0]].co,
- ps->mvert_eval[lt_vtri[1]].co,
- ps->mvert_eval[lt_vtri[2]].co,
- w);
- if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, true)) {
- /* Watch out that no code below this needs to run */
- continue;
- }
- }
-
- /* Is this UV visible from the view? - raytrace */
- /* project_paint_PickFace is less complex, use for testing */
- //if (project_paint_PickFace(ps, pixelScreenCo, w, &side) == tri_index) {
- if ((ps->do_occlude == false) ||
- !project_bucket_point_occluded(ps, bucketFaceNodes, tri_index, pixelScreenCo))
- {
- mask = project_paint_uvpixel_mask(ps, tri_index, w);
-
- if (mask > 0.0f) {
- BLI_linklist_prepend_arena(
- bucketPixelNodes,
- project_paint_uvpixel_init(
- ps, arena, &tinf, x, y, mask, tri_index,
- pixelScreenCo, wco, w),
- arena);
- }
- }
-
- }
-//#if 0
- else if (has_x_isect) {
- /* assuming the face is not a bow-tie - we know we cant intersect again on the X */
- break;
- }
-//#endif
- }
-
-
-#if 0 /* TODO - investigate why this dosnt work sometimes! it should! */
- /* no intersection for this entire row,
- * after some intersection above means we can quit now */
- if (has_x_isect == 0 && has_isect) {
- break;
- }
+ /* clip face and */
+
+ has_isect = 0;
+ for (y = bounds_px.ymin; y < bounds_px.ymax; y++) {
+ //uv[1] = (((float)y) + 0.5f) / (float)ibuf->y;
+ /* use pixel offset UV coords instead */
+ uv[1] = (float)y / ibuf_yf;
+
+ has_x_isect = 0;
+ for (x = bounds_px.xmin; x < bounds_px.xmax; x++) {
+ //uv[0] = (((float)x) + 0.5f) / ibuf->x;
+ /* use pixel offset UV coords instead */
+ uv[0] = (float)x / ibuf_xf;
+
+ /* Note about IsectPoly2Df_twoside, checking the face or uv flipping doesn't work,
+ * could check the poly direction but better to do this */
+ if ((do_backfacecull == true && IsectPoly2Df(uv, uv_clip, uv_clip_tot)) ||
+ (do_backfacecull == false && IsectPoly2Df_twoside(uv, uv_clip, uv_clip_tot))) {
+
+ has_x_isect = has_isect = 1;
+
+ if (is_ortho)
+ screen_px_from_ortho(
+ uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
+ else
+ screen_px_from_persp(
+ uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
+
+ /* a pity we need to get the worldspace pixel location here */
+ if (do_clip || do_3d_mapping) {
+ interp_v3_v3v3v3(wco,
+ ps->mvert_eval[lt_vtri[0]].co,
+ ps->mvert_eval[lt_vtri[1]].co,
+ ps->mvert_eval[lt_vtri[2]].co,
+ w);
+ if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, true)) {
+ /* Watch out that no code below this needs to run */
+ continue;
+ }
+ }
+
+ /* Is this UV visible from the view? - raytrace */
+ /* project_paint_PickFace is less complex, use for testing */
+ //if (project_paint_PickFace(ps, pixelScreenCo, w, &side) == tri_index) {
+ if ((ps->do_occlude == false) ||
+ !project_bucket_point_occluded(ps, bucketFaceNodes, tri_index, pixelScreenCo)) {
+ mask = project_paint_uvpixel_mask(ps, tri_index, w);
+
+ if (mask > 0.0f) {
+ BLI_linklist_prepend_arena(
+ bucketPixelNodes,
+ project_paint_uvpixel_init(
+ ps, arena, &tinf, x, y, mask, tri_index, pixelScreenCo, wco, w),
+ arena);
+ }
+ }
+ }
+ //#if 0
+ else if (has_x_isect) {
+ /* assuming the face is not a bow-tie - we know we cant intersect again on the X */
+ break;
+ }
+ //#endif
+ }
+
+#if 0 /* TODO - investigate why this dosnt work sometimes! it should! */
+ /* no intersection for this entire row,
+ * after some intersection above means we can quit now */
+ if (has_x_isect == 0 && has_isect) {
+ break;
+ }
#endif
- }
- }
- }
-
+ }
+ }
+ }
#ifndef PROJ_DEBUG_NOSEAMBLEED
- if (ps->seam_bleed_px > 0.0f && !(ps->faceSeamFlags[tri_index] & PROJ_FACE_DEGENERATE)) {
- int face_seam_flag;
-
- if (threaded) {
- /* Other threads could be modifying these vars. */
- BLI_thread_lock(LOCK_CUSTOM1);
- }
-
- face_seam_flag = ps->faceSeamFlags[tri_index];
-
- /* are any of our edges un-initialized? */
- if ((face_seam_flag & PROJ_FACE_SEAM_INIT0) == 0 ||
- (face_seam_flag & PROJ_FACE_SEAM_INIT1) == 0 ||
- (face_seam_flag & PROJ_FACE_SEAM_INIT2) == 0)
- {
- project_face_seams_init(ps, arena, tri_index, 0, true, ibuf->x, ibuf->y);
- face_seam_flag = ps->faceSeamFlags[tri_index];
- //printf("seams - %d %d %d %d\n", flag&PROJ_FACE_SEAM0, flag&PROJ_FACE_SEAM1, flag&PROJ_FACE_SEAM2);
- }
-
- if ((face_seam_flag & (PROJ_FACE_SEAM0 | PROJ_FACE_SEAM1 | PROJ_FACE_SEAM2)) == 0) {
-
- if (threaded) {
- /* Other threads could be modifying these vars. */
- BLI_thread_unlock(LOCK_CUSTOM1);
- }
-
- }
- else {
- /* we have a seam - deal with it! */
-
- /* inset face coords. NOTE!!! ScreenSace for ortho, Worldspace in perspective view */
- float insetCos[3][3];
-
- /* vertex screenspace coords */
- const float *vCoSS[3];
-
- /* Store the screenspace coords of the face,
- * clipped by the bucket's screen aligned rectangle. */
- float bucket_clip_edges[2][2];
- float edge_verts_inset_clip[2][3];
- /* face edge pairs - loop throuh these:
- * ((0,1), (1,2), (2,3), (3,0)) or ((0,1), (1,2), (2,0)) for a tri */
- int fidx1, fidx2;
-
- float seam_subsection[4][2];
- float fac1, fac2;
-
- /* Pixelspace UVs. */
- float lt_puv[3][2];
-
- lt_puv[0][0] = lt_uv_pxoffset[0][0] * ibuf->x;
- lt_puv[0][1] = lt_uv_pxoffset[0][1] * ibuf->y;
-
- lt_puv[1][0] = lt_uv_pxoffset[1][0] * ibuf->x;
- lt_puv[1][1] = lt_uv_pxoffset[1][1] * ibuf->y;
-
- lt_puv[2][0] = lt_uv_pxoffset[2][0] * ibuf->x;
- lt_puv[2][1] = lt_uv_pxoffset[2][1] * ibuf->y;
-
- if ((ps->faceSeamFlags[tri_index] & PROJ_FACE_SEAM0) ||
- (ps->faceSeamFlags[tri_index] & PROJ_FACE_SEAM1) ||
- (ps->faceSeamFlags[tri_index] & PROJ_FACE_SEAM2))
- {
- uv_image_outset(ps, lt_uv_pxoffset, lt_puv, tri_index, ibuf->x, ibuf->y);
- }
-
- /* ps->loopSeamUVs cant be modified when threading, now this is done we can unlock. */
- if (threaded) {
- /* Other threads could be modifying these vars */
- BLI_thread_unlock(LOCK_CUSTOM1);
- }
-
- vCoSS[0] = ps->screenCoords[lt_vtri[0]];
- vCoSS[1] = ps->screenCoords[lt_vtri[1]];
- vCoSS[2] = ps->screenCoords[lt_vtri[2]];
-
- /* PROJ_FACE_SCALE_SEAM must be slightly less then 1.0f */
- if (is_ortho) {
- scale_tri(insetCos, vCoSS, PROJ_FACE_SCALE_SEAM);
- }
- else {
- scale_tri(insetCos, vCo, PROJ_FACE_SCALE_SEAM);
- }
-
- for (fidx1 = 0; fidx1 < 3; fidx1++) {
- /* next fidx in the face (0,1,2) -> (1,2,0) */
- fidx2 = (fidx1 == 2) ? 0 : fidx1 + 1;
-
- if ((face_seam_flag & (1 << fidx1)) && /* 1<<fidx1 -> PROJ_FACE_SEAM# */
- line_clip_rect2f(clip_rect, bucket_bounds, vCoSS[fidx1], vCoSS[fidx2], bucket_clip_edges[0], bucket_clip_edges[1]))
- {
- /* Avoid div by zero. */
- if (len_squared_v2v2(vCoSS[fidx1], vCoSS[fidx2]) > FLT_EPSILON) {
- uint loop_idx = ps->mlooptri_eval[tri_index].tri[fidx1];
- LoopSeamData *seam_data = &ps->loopSeamData[loop_idx];
- float (*seam_uvs)[2] = seam_data->seam_uvs;
-
- if (is_ortho) {
- fac1 = line_point_factor_v2(bucket_clip_edges[0], vCoSS[fidx1], vCoSS[fidx2]);
- fac2 = line_point_factor_v2(bucket_clip_edges[1], vCoSS[fidx1], vCoSS[fidx2]);
- }
- else {
- fac1 = screen_px_line_point_factor_v2_persp(ps, bucket_clip_edges[0], vCo[fidx1], vCo[fidx2]);
- fac2 = screen_px_line_point_factor_v2_persp(ps, bucket_clip_edges[1], vCo[fidx1], vCo[fidx2]);
- }
-
- interp_v2_v2v2(seam_subsection[0], lt_uv_pxoffset[fidx1], lt_uv_pxoffset[fidx2], fac1);
- interp_v2_v2v2(seam_subsection[1], lt_uv_pxoffset[fidx1], lt_uv_pxoffset[fidx2], fac2);
-
- interp_v2_v2v2(seam_subsection[2], seam_uvs[0], seam_uvs[1], fac2);
- interp_v2_v2v2(seam_subsection[3], seam_uvs[0], seam_uvs[1], fac1);
-
- /* if the bucket_clip_edges values Z values was kept we could avoid this
- * Inset needs to be added so occlusion tests wont hit adjacent faces */
- interp_v3_v3v3(edge_verts_inset_clip[0], insetCos[fidx1], insetCos[fidx2], fac1);
- interp_v3_v3v3(edge_verts_inset_clip[1], insetCos[fidx1], insetCos[fidx2], fac2);
-
-
- if (pixel_bounds_uv(seam_subsection, &bounds_px, ibuf->x, ibuf->y)) {
- /* bounds between the seam rect and the uvspace bucket pixels */
-
- has_isect = 0;
- for (y = bounds_px.ymin; y < bounds_px.ymax; y++) {
- // uv[1] = (((float)y) + 0.5f) / (float)ibuf->y;
- /* use offset uvs instead */
- uv[1] = (float)y / ibuf_yf;
-
- has_x_isect = 0;
- for (x = bounds_px.xmin; x < bounds_px.xmax; x++) {
- float puv[2] = {(float)x, (float)y};
- bool in_bounds;
- //uv[0] = (((float)x) + 0.5f) / (float)ibuf->x;
- /* use offset uvs instead */
- uv[0] = (float)x / ibuf_xf;
-
- /* test we're inside uvspace bucket and triangle bounds */
- if (equals_v2v2(seam_uvs[0], seam_uvs[1])) {
- in_bounds = isect_point_tri_v2(uv, UNPACK3(seam_subsection));
- }
- else {
- in_bounds = isect_point_quad_v2(uv, UNPACK4(seam_subsection));
- }
-
- if (in_bounds) {
- if ((seam_data->corner_dist_sq[0] > 0.0f) &&
- (len_squared_v2v2(puv, seam_data->seam_puvs[0]) < seam_data->corner_dist_sq[0]) &&
- (len_squared_v2v2(puv, lt_puv[fidx1]) > ps->seam_bleed_px_sq))
- {
- in_bounds = false;
- }
- else if ((seam_data->corner_dist_sq[1] > 0.0f) &&
- (len_squared_v2v2(puv, seam_data->seam_puvs[1]) < seam_data->corner_dist_sq[1]) &&
- (len_squared_v2v2(puv, lt_puv[fidx2]) > ps->seam_bleed_px_sq))
- {
- in_bounds = false;
- }
- }
-
- if (in_bounds) {
- float pixel_on_edge[4];
- float fac;
-
- if (is_ortho) {
- screen_px_from_ortho(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
- }
- else {
- screen_px_from_persp(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
- }
-
- /* We need the coord of the pixel on the edge, for the occlusion query. */
- fac = resolve_quad_u_v2(uv, UNPACK4(seam_subsection));
- interp_v3_v3v3(pixel_on_edge, edge_verts_inset_clip[0], edge_verts_inset_clip[1], fac);
-
- if (!is_ortho) {
- pixel_on_edge[3] = 1.0f;
- /* cast because of const */
- mul_m4_v4((float(*)[4])ps->projectMat, pixel_on_edge);
- pixel_on_edge[0] = (float)(ps->winx * 0.5f) + (ps->winx * 0.5f) * pixel_on_edge[0] / pixel_on_edge[3];
- pixel_on_edge[1] = (float)(ps->winy * 0.5f) + (ps->winy * 0.5f) * pixel_on_edge[1] / pixel_on_edge[3];
- /* Use the depth for bucket point occlusion */
- pixel_on_edge[2] = pixel_on_edge[2] / pixel_on_edge[3];
- }
-
- if ((ps->do_occlude == false) ||
- !project_bucket_point_occluded(ps, bucketFaceNodes, tri_index, pixel_on_edge))
- {
- /* a pity we need to get the worldspace
- * pixel location here */
- if (do_clip || do_3d_mapping) {
- interp_v3_v3v3v3(wco, vCo[0], vCo[1], vCo[2], w);
-
- if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, true)) {
- /* Watch out that no code below
- * this needs to run */
- continue;
- }
- }
-
- mask = project_paint_uvpixel_mask(ps, tri_index, w);
-
- if (mask > 0.0f) {
- BLI_linklist_prepend_arena(
- bucketPixelNodes,
- project_paint_uvpixel_init(ps, arena, &tinf, x, y, mask, tri_index,
- pixelScreenCo, wco, w),
- arena
- );
- }
-
- }
- }
- else if (has_x_isect) {
- /* assuming the face is not a bow-tie - we know
- * we cant intersect again on the X */
- break;
- }
- }
-
-#if 0 /* TODO - investigate why this dosnt work sometimes! it should! */
- /* no intersection for this entire row,
- * after some intersection above means we can quit now */
- if (has_x_isect == 0 && has_isect) {
- break;
- }
-#endif
- }
- }
- }
- }
- }
- }
- }
+ if (ps->seam_bleed_px > 0.0f && !(ps->faceSeamFlags[tri_index] & PROJ_FACE_DEGENERATE)) {
+ int face_seam_flag;
+
+ if (threaded) {
+ /* Other threads could be modifying these vars. */
+ BLI_thread_lock(LOCK_CUSTOM1);
+ }
+
+ face_seam_flag = ps->faceSeamFlags[tri_index];
+
+ /* are any of our edges un-initialized? */
+ if ((face_seam_flag & PROJ_FACE_SEAM_INIT0) == 0 ||
+ (face_seam_flag & PROJ_FACE_SEAM_INIT1) == 0 ||
+ (face_seam_flag & PROJ_FACE_SEAM_INIT2) == 0) {
+ project_face_seams_init(ps, arena, tri_index, 0, true, ibuf->x, ibuf->y);
+ face_seam_flag = ps->faceSeamFlags[tri_index];
+ //printf("seams - %d %d %d %d\n", flag&PROJ_FACE_SEAM0, flag&PROJ_FACE_SEAM1, flag&PROJ_FACE_SEAM2);
+ }
+
+ if ((face_seam_flag & (PROJ_FACE_SEAM0 | PROJ_FACE_SEAM1 | PROJ_FACE_SEAM2)) == 0) {
+
+ if (threaded) {
+ /* Other threads could be modifying these vars. */
+ BLI_thread_unlock(LOCK_CUSTOM1);
+ }
+ }
+ else {
+ /* we have a seam - deal with it! */
+
+ /* inset face coords. NOTE!!! ScreenSace for ortho, Worldspace in perspective view */
+ float insetCos[3][3];
+
+ /* vertex screenspace coords */
+ const float *vCoSS[3];
+
+ /* Store the screenspace coords of the face,
+ * clipped by the bucket's screen aligned rectangle. */
+ float bucket_clip_edges[2][2];
+ float edge_verts_inset_clip[2][3];
+ /* face edge pairs - loop throuh these:
+ * ((0,1), (1,2), (2,3), (3,0)) or ((0,1), (1,2), (2,0)) for a tri */
+ int fidx1, fidx2;
+
+ float seam_subsection[4][2];
+ float fac1, fac2;
+
+ /* Pixelspace UVs. */
+ float lt_puv[3][2];
+
+ lt_puv[0][0] = lt_uv_pxoffset[0][0] * ibuf->x;
+ lt_puv[0][1] = lt_uv_pxoffset[0][1] * ibuf->y;
+
+ lt_puv[1][0] = lt_uv_pxoffset[1][0] * ibuf->x;
+ lt_puv[1][1] = lt_uv_pxoffset[1][1] * ibuf->y;
+
+ lt_puv[2][0] = lt_uv_pxoffset[2][0] * ibuf->x;
+ lt_puv[2][1] = lt_uv_pxoffset[2][1] * ibuf->y;
+
+ if ((ps->faceSeamFlags[tri_index] & PROJ_FACE_SEAM0) ||
+ (ps->faceSeamFlags[tri_index] & PROJ_FACE_SEAM1) ||
+ (ps->faceSeamFlags[tri_index] & PROJ_FACE_SEAM2)) {
+ uv_image_outset(ps, lt_uv_pxoffset, lt_puv, tri_index, ibuf->x, ibuf->y);
+ }
+
+ /* ps->loopSeamUVs cant be modified when threading, now this is done we can unlock. */
+ if (threaded) {
+ /* Other threads could be modifying these vars */
+ BLI_thread_unlock(LOCK_CUSTOM1);
+ }
+
+ vCoSS[0] = ps->screenCoords[lt_vtri[0]];
+ vCoSS[1] = ps->screenCoords[lt_vtri[1]];
+ vCoSS[2] = ps->screenCoords[lt_vtri[2]];
+
+ /* PROJ_FACE_SCALE_SEAM must be slightly less then 1.0f */
+ if (is_ortho) {
+ scale_tri(insetCos, vCoSS, PROJ_FACE_SCALE_SEAM);
+ }
+ else {
+ scale_tri(insetCos, vCo, PROJ_FACE_SCALE_SEAM);
+ }
+
+ for (fidx1 = 0; fidx1 < 3; fidx1++) {
+ /* next fidx in the face (0,1,2) -> (1,2,0) */
+ fidx2 = (fidx1 == 2) ? 0 : fidx1 + 1;
+
+ if ((face_seam_flag & (1 << fidx1)) && /* 1<<fidx1 -> PROJ_FACE_SEAM# */
+ line_clip_rect2f(clip_rect,
+ bucket_bounds,
+ vCoSS[fidx1],
+ vCoSS[fidx2],
+ bucket_clip_edges[0],
+ bucket_clip_edges[1])) {
+ /* Avoid div by zero. */
+ if (len_squared_v2v2(vCoSS[fidx1], vCoSS[fidx2]) > FLT_EPSILON) {
+ uint loop_idx = ps->mlooptri_eval[tri_index].tri[fidx1];
+ LoopSeamData *seam_data = &ps->loopSeamData[loop_idx];
+ float(*seam_uvs)[2] = seam_data->seam_uvs;
+
+ if (is_ortho) {
+ fac1 = line_point_factor_v2(bucket_clip_edges[0], vCoSS[fidx1], vCoSS[fidx2]);
+ fac2 = line_point_factor_v2(bucket_clip_edges[1], vCoSS[fidx1], vCoSS[fidx2]);
+ }
+ else {
+ fac1 = screen_px_line_point_factor_v2_persp(
+ ps, bucket_clip_edges[0], vCo[fidx1], vCo[fidx2]);
+ fac2 = screen_px_line_point_factor_v2_persp(
+ ps, bucket_clip_edges[1], vCo[fidx1], vCo[fidx2]);
+ }
+
+ interp_v2_v2v2(seam_subsection[0], lt_uv_pxoffset[fidx1], lt_uv_pxoffset[fidx2], fac1);
+ interp_v2_v2v2(seam_subsection[1], lt_uv_pxoffset[fidx1], lt_uv_pxoffset[fidx2], fac2);
+
+ interp_v2_v2v2(seam_subsection[2], seam_uvs[0], seam_uvs[1], fac2);
+ interp_v2_v2v2(seam_subsection[3], seam_uvs[0], seam_uvs[1], fac1);
+
+ /* if the bucket_clip_edges values Z values was kept we could avoid this
+ * Inset needs to be added so occlusion tests wont hit adjacent faces */
+ interp_v3_v3v3(edge_verts_inset_clip[0], insetCos[fidx1], insetCos[fidx2], fac1);
+ interp_v3_v3v3(edge_verts_inset_clip[1], insetCos[fidx1], insetCos[fidx2], fac2);
+
+ if (pixel_bounds_uv(seam_subsection, &bounds_px, ibuf->x, ibuf->y)) {
+ /* bounds between the seam rect and the uvspace bucket pixels */
+
+ has_isect = 0;
+ for (y = bounds_px.ymin; y < bounds_px.ymax; y++) {
+ // uv[1] = (((float)y) + 0.5f) / (float)ibuf->y;
+ /* use offset uvs instead */
+ uv[1] = (float)y / ibuf_yf;
+
+ has_x_isect = 0;
+ for (x = bounds_px.xmin; x < bounds_px.xmax; x++) {
+ float puv[2] = {(float)x, (float)y};
+ bool in_bounds;
+ //uv[0] = (((float)x) + 0.5f) / (float)ibuf->x;
+ /* use offset uvs instead */
+ uv[0] = (float)x / ibuf_xf;
+
+ /* test we're inside uvspace bucket and triangle bounds */
+ if (equals_v2v2(seam_uvs[0], seam_uvs[1])) {
+ in_bounds = isect_point_tri_v2(uv, UNPACK3(seam_subsection));
+ }
+ else {
+ in_bounds = isect_point_quad_v2(uv, UNPACK4(seam_subsection));
+ }
+
+ if (in_bounds) {
+ if ((seam_data->corner_dist_sq[0] > 0.0f) &&
+ (len_squared_v2v2(puv, seam_data->seam_puvs[0]) <
+ seam_data->corner_dist_sq[0]) &&
+ (len_squared_v2v2(puv, lt_puv[fidx1]) > ps->seam_bleed_px_sq)) {
+ in_bounds = false;
+ }
+ else if ((seam_data->corner_dist_sq[1] > 0.0f) &&
+ (len_squared_v2v2(puv, seam_data->seam_puvs[1]) <
+ seam_data->corner_dist_sq[1]) &&
+ (len_squared_v2v2(puv, lt_puv[fidx2]) > ps->seam_bleed_px_sq)) {
+ in_bounds = false;
+ }
+ }
+
+ if (in_bounds) {
+ float pixel_on_edge[4];
+ float fac;
+
+ if (is_ortho) {
+ screen_px_from_ortho(
+ uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
+ }
+ else {
+ screen_px_from_persp(
+ uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
+ }
+
+ /* We need the coord of the pixel on the edge, for the occlusion query. */
+ fac = resolve_quad_u_v2(uv, UNPACK4(seam_subsection));
+ interp_v3_v3v3(
+ pixel_on_edge, edge_verts_inset_clip[0], edge_verts_inset_clip[1], fac);
+
+ if (!is_ortho) {
+ pixel_on_edge[3] = 1.0f;
+ /* cast because of const */
+ mul_m4_v4((float(*)[4])ps->projectMat, pixel_on_edge);
+ pixel_on_edge[0] = (float)(ps->winx * 0.5f) +
+ (ps->winx * 0.5f) * pixel_on_edge[0] / pixel_on_edge[3];
+ pixel_on_edge[1] = (float)(ps->winy * 0.5f) +
+ (ps->winy * 0.5f) * pixel_on_edge[1] / pixel_on_edge[3];
+ /* Use the depth for bucket point occlusion */
+ pixel_on_edge[2] = pixel_on_edge[2] / pixel_on_edge[3];
+ }
+
+ if ((ps->do_occlude == false) ||
+ !project_bucket_point_occluded(
+ ps, bucketFaceNodes, tri_index, pixel_on_edge)) {
+ /* a pity we need to get the worldspace
+ * pixel location here */
+ if (do_clip || do_3d_mapping) {
+ interp_v3_v3v3v3(wco, vCo[0], vCo[1], vCo[2], w);
+
+ if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, true)) {
+ /* Watch out that no code below
+ * this needs to run */
+ continue;
+ }
+ }
+
+ mask = project_paint_uvpixel_mask(ps, tri_index, w);
+
+ if (mask > 0.0f) {
+ BLI_linklist_prepend_arena(
+ bucketPixelNodes,
+ project_paint_uvpixel_init(
+ ps, arena, &tinf, x, y, mask, tri_index, pixelScreenCo, wco, w),
+ arena);
+ }
+ }
+ }
+ else if (has_x_isect) {
+ /* assuming the face is not a bow-tie - we know
+ * we cant intersect again on the X */
+ break;
+ }
+ }
+
+# if 0 /* TODO - investigate why this dosnt work sometimes! it should! */
+ /* no intersection for this entire row,
+ * after some intersection above means we can quit now */
+ if (has_x_isect == 0 && has_isect) {
+ break;
+ }
+# endif
+ }
+ }
+ }
+ }
+ }
+ }
+ }
#else
- UNUSED_VARS(vCo, threaded);
-#endif // PROJ_DEBUG_NOSEAMBLEED
+ UNUSED_VARS(vCo, threaded);
+#endif // PROJ_DEBUG_NOSEAMBLEED
}
-
/**
* Takes floating point screenspace min/max and
* returns int min/max to be used as indices for ps->bucketRect, ps->bucketFlags
*/
-static void project_paint_bucket_bounds(
- const ProjPaintState *ps,
- const float min[2], const float max[2],
- int bucketMin[2], int bucketMax[2])
+static void project_paint_bucket_bounds(const ProjPaintState *ps,
+ const float min[2],
+ const float max[2],
+ int bucketMin[2],
+ int bucketMax[2])
{
- /* divide by bucketWidth & bucketHeight so the bounds are offset in bucket grid units */
-
- /* XXX: the offset of 0.5 is always truncated to zero and the offset of 1.5f
- * is always truncated to 1, is this really correct?? - jwilkins */
-
- /* these offsets of 0.5 and 1.5 seem odd but they are correct */
- bucketMin[0] = (int)((int)(((float)(min[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 0.5f);
- bucketMin[1] = (int)((int)(((float)(min[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 0.5f);
-
- bucketMax[0] = (int)((int)(((float)(max[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 1.5f);
- bucketMax[1] = (int)((int)(((float)(max[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 1.5f);
-
- /* in case the rect is outside the mesh 2d bounds */
- CLAMP(bucketMin[0], 0, ps->buckets_x);
- CLAMP(bucketMin[1], 0, ps->buckets_y);
-
- CLAMP(bucketMax[0], 0, ps->buckets_x);
- CLAMP(bucketMax[1], 0, ps->buckets_y);
+ /* divide by bucketWidth & bucketHeight so the bounds are offset in bucket grid units */
+
+ /* XXX: the offset of 0.5 is always truncated to zero and the offset of 1.5f
+ * is always truncated to 1, is this really correct?? - jwilkins */
+
+ /* these offsets of 0.5 and 1.5 seem odd but they are correct */
+ bucketMin[0] =
+ (int)((int)(((float)(min[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 0.5f);
+ bucketMin[1] = (int)((int)(((float)(min[1] - ps->screenMin[1]) / ps->screen_height) *
+ ps->buckets_y) +
+ 0.5f);
+
+ bucketMax[0] =
+ (int)((int)(((float)(max[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 1.5f);
+ bucketMax[1] = (int)((int)(((float)(max[1] - ps->screenMin[1]) / ps->screen_height) *
+ ps->buckets_y) +
+ 1.5f);
+
+ /* in case the rect is outside the mesh 2d bounds */
+ CLAMP(bucketMin[0], 0, ps->buckets_x);
+ CLAMP(bucketMin[1], 0, ps->buckets_y);
+
+ CLAMP(bucketMax[0], 0, ps->buckets_x);
+ CLAMP(bucketMax[1], 0, ps->buckets_y);
}
/* set bucket_bounds to a screen space-aligned floating point bound-box */
-static void project_bucket_bounds(
- const ProjPaintState *ps, const int bucket_x, const int bucket_y, rctf *bucket_bounds)
+static void project_bucket_bounds(const ProjPaintState *ps,
+ const int bucket_x,
+ const int bucket_y,
+ rctf *bucket_bounds)
{
- /* left */
- bucket_bounds->xmin = (
- ps->screenMin[0] + ((bucket_x) * (ps->screen_width / ps->buckets_x)));
- /* right */
- bucket_bounds->xmax = (
- ps->screenMin[0] + ((bucket_x + 1) * (ps->screen_width / ps->buckets_x)));
-
- /* bottom */
- bucket_bounds->ymin = (
- ps->screenMin[1] + ((bucket_y) * (ps->screen_height / ps->buckets_y)));
- /* top */
- bucket_bounds->ymax = (
- ps->screenMin[1] + ((bucket_y + 1) * (ps->screen_height / ps->buckets_y)));
+ /* left */
+ bucket_bounds->xmin = (ps->screenMin[0] + ((bucket_x) * (ps->screen_width / ps->buckets_x)));
+ /* right */
+ bucket_bounds->xmax = (ps->screenMin[0] + ((bucket_x + 1) * (ps->screen_width / ps->buckets_x)));
+
+ /* bottom */
+ bucket_bounds->ymin = (ps->screenMin[1] + ((bucket_y) * (ps->screen_height / ps->buckets_y)));
+ /* top */
+ bucket_bounds->ymax = (ps->screenMin[1] +
+ ((bucket_y + 1) * (ps->screen_height / ps->buckets_y)));
}
/* Fill this bucket with pixels from the faces that intersect it.
*
* have bucket_bounds as an argument so we don't need to give bucket_x/y the rect function needs */
-static void project_bucket_init(
- const ProjPaintState *ps, const int thread_index, const int bucket_index,
- const rctf *clip_rect, const rctf *bucket_bounds)
+static void project_bucket_init(const ProjPaintState *ps,
+ const int thread_index,
+ const int bucket_index,
+ const rctf *clip_rect,
+ const rctf *bucket_bounds)
{
- LinkNode *node;
- int tri_index, image_index = 0;
- ImBuf *ibuf = NULL;
- Image *tpage_last = NULL, *tpage;
- ImBuf *tmpibuf = NULL;
-
- if (ps->image_tot == 1) {
- /* Simple loop, no context switching */
- ibuf = ps->projImages[0].ibuf;
-
- for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
- project_paint_face_init(
- ps, thread_index, bucket_index, POINTER_AS_INT(node->link), 0,
- clip_rect, bucket_bounds, ibuf, &tmpibuf);
- }
- }
- else {
-
- /* More complicated loop, switch between images */
- for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
- tri_index = POINTER_AS_INT(node->link);
-
- /* Image context switching */
- tpage = project_paint_face_paint_image(ps, tri_index);
- if (tpage_last != tpage) {
- tpage_last = tpage;
-
- for (image_index = 0; image_index < ps->image_tot; image_index++) {
- if (ps->projImages[image_index].ima == tpage_last) {
- ibuf = ps->projImages[image_index].ibuf;
- break;
- }
- }
- }
- /* context switching done */
-
- project_paint_face_init(
- ps, thread_index, bucket_index, tri_index, image_index,
- clip_rect, bucket_bounds, ibuf, &tmpibuf);
- }
- }
-
- if (tmpibuf)
- IMB_freeImBuf(tmpibuf);
-
- ps->bucketFlags[bucket_index] |= PROJ_BUCKET_INIT;
+ LinkNode *node;
+ int tri_index, image_index = 0;
+ ImBuf *ibuf = NULL;
+ Image *tpage_last = NULL, *tpage;
+ ImBuf *tmpibuf = NULL;
+
+ if (ps->image_tot == 1) {
+ /* Simple loop, no context switching */
+ ibuf = ps->projImages[0].ibuf;
+
+ for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
+ project_paint_face_init(ps,
+ thread_index,
+ bucket_index,
+ POINTER_AS_INT(node->link),
+ 0,
+ clip_rect,
+ bucket_bounds,
+ ibuf,
+ &tmpibuf);
+ }
+ }
+ else {
+
+ /* More complicated loop, switch between images */
+ for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
+ tri_index = POINTER_AS_INT(node->link);
+
+ /* Image context switching */
+ tpage = project_paint_face_paint_image(ps, tri_index);
+ if (tpage_last != tpage) {
+ tpage_last = tpage;
+
+ for (image_index = 0; image_index < ps->image_tot; image_index++) {
+ if (ps->projImages[image_index].ima == tpage_last) {
+ ibuf = ps->projImages[image_index].ibuf;
+ break;
+ }
+ }
+ }
+ /* context switching done */
+
+ project_paint_face_init(ps,
+ thread_index,
+ bucket_index,
+ tri_index,
+ image_index,
+ clip_rect,
+ bucket_bounds,
+ ibuf,
+ &tmpibuf);
+ }
+ }
+
+ if (tmpibuf)
+ IMB_freeImBuf(tmpibuf);
+
+ ps->bucketFlags[bucket_index] |= PROJ_BUCKET_INIT;
}
-
/* We want to know if a bucket and a face overlap in screen-space
*
* Note, if this ever returns false positives its not that bad, since a face in the bounding area
* will have its pixels calculated when it might not be needed later, (at the moment at least)
* obviously it shouldn't have bugs though */
-static bool project_bucket_face_isect(ProjPaintState *ps, int bucket_x, int bucket_y, const MLoopTri *lt)
+static bool project_bucket_face_isect(ProjPaintState *ps,
+ int bucket_x,
+ int bucket_y,
+ const MLoopTri *lt)
{
- /* TODO - replace this with a tricker method that uses sideofline for all
- * screenCoords's edges against the closest bucket corner */
- const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
- rctf bucket_bounds;
- float p1[2], p2[2], p3[2], p4[2];
- const float *v, *v1, *v2, *v3;
- int fidx;
-
- project_bucket_bounds(ps, bucket_x, bucket_y, &bucket_bounds);
-
- /* Is one of the faces verts in the bucket bounds? */
-
- fidx = 2;
- do {
- v = ps->screenCoords[lt_vtri[fidx]];
- if (BLI_rctf_isect_pt_v(&bucket_bounds, v)) {
- return 1;
- }
- } while (fidx--);
-
- v1 = ps->screenCoords[lt_vtri[0]];
- v2 = ps->screenCoords[lt_vtri[1]];
- v3 = ps->screenCoords[lt_vtri[2]];
-
- p1[0] = bucket_bounds.xmin; p1[1] = bucket_bounds.ymin;
- p2[0] = bucket_bounds.xmin; p2[1] = bucket_bounds.ymax;
- p3[0] = bucket_bounds.xmax; p3[1] = bucket_bounds.ymax;
- p4[0] = bucket_bounds.xmax; p4[1] = bucket_bounds.ymin;
-
- if (isect_point_tri_v2(p1, v1, v2, v3) ||
- isect_point_tri_v2(p2, v1, v2, v3) ||
- isect_point_tri_v2(p3, v1, v2, v3) ||
- isect_point_tri_v2(p4, v1, v2, v3) ||
- /* we can avoid testing v3,v1 because another intersection MUST exist if this intersects */
- (isect_seg_seg_v2(p1, p2, v1, v2) || isect_seg_seg_v2(p1, p2, v2, v3)) ||
- (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 0;
+ /* TODO - replace this with a tricker method that uses sideofline for all
+ * screenCoords's edges against the closest bucket corner */
+ const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
+ rctf bucket_bounds;
+ float p1[2], p2[2], p3[2], p4[2];
+ const float *v, *v1, *v2, *v3;
+ int fidx;
+
+ project_bucket_bounds(ps, bucket_x, bucket_y, &bucket_bounds);
+
+ /* Is one of the faces verts in the bucket bounds? */
+
+ fidx = 2;
+ do {
+ v = ps->screenCoords[lt_vtri[fidx]];
+ if (BLI_rctf_isect_pt_v(&bucket_bounds, v)) {
+ return 1;
+ }
+ } while (fidx--);
+
+ v1 = ps->screenCoords[lt_vtri[0]];
+ v2 = ps->screenCoords[lt_vtri[1]];
+ v3 = ps->screenCoords[lt_vtri[2]];
+
+ p1[0] = bucket_bounds.xmin;
+ p1[1] = bucket_bounds.ymin;
+ p2[0] = bucket_bounds.xmin;
+ p2[1] = bucket_bounds.ymax;
+ p3[0] = bucket_bounds.xmax;
+ p3[1] = bucket_bounds.ymax;
+ p4[0] = bucket_bounds.xmax;
+ p4[1] = bucket_bounds.ymin;
+
+ if (isect_point_tri_v2(p1, v1, v2, v3) || isect_point_tri_v2(p2, v1, v2, v3) ||
+ isect_point_tri_v2(p3, v1, v2, v3) || isect_point_tri_v2(p4, v1, v2, v3) ||
+ /* we can avoid testing v3,v1 because another intersection MUST exist if this intersects */
+ (isect_seg_seg_v2(p1, p2, v1, v2) || isect_seg_seg_v2(p1, p2, v2, v3)) ||
+ (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 0;
}
/* Add faces to the bucket but don't initialize its pixels
* TODO - when painting occluded, sort the faces on their min-Z
* and only add faces that faces that are not occluded */
-static void project_paint_delayed_face_init(ProjPaintState *ps, const MLoopTri *lt, const int tri_index)
+static void project_paint_delayed_face_init(ProjPaintState *ps,
+ const MLoopTri *lt,
+ const int tri_index)
{
- const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
- float min[2], max[2], *vCoSS;
- /* for ps->bucketRect indexing */
- int bucketMin[2], bucketMax[2];
- int fidx, bucket_x, bucket_y;
- /* for early loop exit */
- int has_x_isect = -1, has_isect = 0;
- /* just use the first thread arena since threading has not started yet */
- MemArena *arena = ps->arena_mt[0];
-
- INIT_MINMAX2(min, max);
-
- fidx = 2;
- do {
- vCoSS = ps->screenCoords[lt_vtri[fidx]];
- minmax_v2v2_v2(min, max, vCoSS);
- } while (fidx--);
-
- project_paint_bucket_bounds(ps, min, max, bucketMin, bucketMax);
-
- for (bucket_y = bucketMin[1]; bucket_y < bucketMax[1]; bucket_y++) {
- has_x_isect = 0;
- for (bucket_x = bucketMin[0]; bucket_x < bucketMax[0]; bucket_x++) {
- if (project_bucket_face_isect(ps, bucket_x, bucket_y, lt)) {
- int bucket_index = bucket_x + (bucket_y * ps->buckets_x);
- BLI_linklist_prepend_arena(
- &ps->bucketFaces[bucket_index],
- /* cast to a pointer to shut up the compiler */
- POINTER_FROM_INT(tri_index),
- arena
- );
-
- has_x_isect = has_isect = 1;
- }
- else if (has_x_isect) {
- /* assuming the face is not a bow-tie - we know we cant intersect again on the X */
- break;
- }
- }
-
- /* no intersection for this entire row,
- * after some intersection above means we can quit now */
- if (has_x_isect == 0 && has_isect) {
- break;
- }
- }
+ const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
+ float min[2], max[2], *vCoSS;
+ /* for ps->bucketRect indexing */
+ int bucketMin[2], bucketMax[2];
+ int fidx, bucket_x, bucket_y;
+ /* for early loop exit */
+ int has_x_isect = -1, has_isect = 0;
+ /* just use the first thread arena since threading has not started yet */
+ MemArena *arena = ps->arena_mt[0];
+
+ INIT_MINMAX2(min, max);
+
+ fidx = 2;
+ do {
+ vCoSS = ps->screenCoords[lt_vtri[fidx]];
+ minmax_v2v2_v2(min, max, vCoSS);
+ } while (fidx--);
+
+ project_paint_bucket_bounds(ps, min, max, bucketMin, bucketMax);
+
+ for (bucket_y = bucketMin[1]; bucket_y < bucketMax[1]; bucket_y++) {
+ has_x_isect = 0;
+ for (bucket_x = bucketMin[0]; bucket_x < bucketMax[0]; bucket_x++) {
+ if (project_bucket_face_isect(ps, bucket_x, bucket_y, lt)) {
+ int bucket_index = bucket_x + (bucket_y * ps->buckets_x);
+ BLI_linklist_prepend_arena(&ps->bucketFaces[bucket_index],
+ /* cast to a pointer to shut up the compiler */
+ POINTER_FROM_INT(tri_index),
+ arena);
+
+ has_x_isect = has_isect = 1;
+ }
+ else if (has_x_isect) {
+ /* assuming the face is not a bow-tie - we know we cant intersect again on the X */
+ break;
+ }
+ }
+
+ /* no intersection for this entire row,
+ * after some intersection above means we can quit now */
+ if (has_x_isect == 0 && has_isect) {
+ break;
+ }
+ }
#ifndef PROJ_DEBUG_NOSEAMBLEED
- if (ps->seam_bleed_px > 0.0f) {
- /* set as uninitialized */
- ps->loopSeamData[lt->tri[0]].seam_uvs[0][0] = FLT_MAX;
- ps->loopSeamData[lt->tri[1]].seam_uvs[0][0] = FLT_MAX;
- ps->loopSeamData[lt->tri[2]].seam_uvs[0][0] = FLT_MAX;
- }
+ if (ps->seam_bleed_px > 0.0f) {
+ /* set as uninitialized */
+ ps->loopSeamData[lt->tri[0]].seam_uvs[0][0] = FLT_MAX;
+ ps->loopSeamData[lt->tri[1]].seam_uvs[0][0] = FLT_MAX;
+ ps->loopSeamData[lt->tri[2]].seam_uvs[0][0] = FLT_MAX;
+ }
#endif
}
static void proj_paint_state_viewport_init(ProjPaintState *ps, const char symmetry_flag)
{
- float mat[3][3];
- float viewmat[4][4];
- float viewinv[4][4];
-
- ps->viewDir[0] = 0.0f;
- ps->viewDir[1] = 0.0f;
- ps->viewDir[2] = 1.0f;
-
- copy_m4_m4(ps->obmat, ps->ob->obmat);
-
- if (symmetry_flag) {
- int i;
- for (i = 0; i < 3; i++) {
- if ((symmetry_flag >> i) & 1) {
- negate_v3(ps->obmat[i]);
- ps->is_flip_object = !ps->is_flip_object;
- }
- }
- }
-
- invert_m4_m4(ps->obmat_imat, ps->obmat);
-
- if (ELEM(ps->source, PROJ_SRC_VIEW, PROJ_SRC_VIEW_FILL)) {
- /* normal drawing */
- ps->winx = ps->ar->winx;
- ps->winy = ps->ar->winy;
-
- copy_m4_m4(viewmat, ps->rv3d->viewmat);
- copy_m4_m4(viewinv, ps->rv3d->viewinv);
-
- ED_view3d_ob_project_mat_get_from_obmat(ps->rv3d, ps->obmat, ps->projectMat);
-
- ps->is_ortho = ED_view3d_clip_range_get(ps->depsgraph, ps->v3d, ps->rv3d, &ps->clip_start, &ps->clip_end, true);
- }
- else {
- /* re-projection */
- float winmat[4][4];
- float vmat[4][4];
-
- ps->winx = ps->reproject_ibuf->x;
- ps->winy = ps->reproject_ibuf->y;
-
- if (ps->source == PROJ_SRC_IMAGE_VIEW) {
- /* image stores camera data, tricky */
- IDProperty *idgroup = IDP_GetProperties(&ps->reproject_image->id, 0);
- IDProperty *view_data = IDP_GetPropertyFromGroup(idgroup, PROJ_VIEW_DATA_ID);
-
- const float *array = (float *)IDP_Array(view_data);
-
- /* use image array, written when creating image */
- memcpy(winmat, array, sizeof(winmat)); array += sizeof(winmat) / sizeof(float);
- memcpy(viewmat, array, sizeof(viewmat)); array += sizeof(viewmat) / sizeof(float);
- ps->clip_start = array[0];
- ps->clip_end = array[1];
- ps->is_ortho = array[2] ? 1 : 0;
-
- invert_m4_m4(viewinv, viewmat);
- }
- else if (ps->source == PROJ_SRC_IMAGE_CAM) {
- Object *cam_ob_eval = DEG_get_evaluated_object(ps->depsgraph, ps->scene->camera);
- CameraParams params;
-
- /* viewmat & viewinv */
- copy_m4_m4(viewinv, cam_ob_eval->obmat);
- normalize_m4(viewinv);
- invert_m4_m4(viewmat, viewinv);
-
- /* window matrix, clipping and ortho */
- BKE_camera_params_init(&params);
- BKE_camera_params_from_object(&params, cam_ob_eval);
- BKE_camera_params_compute_viewplane(&params, ps->winx, ps->winy, 1.0f, 1.0f);
- BKE_camera_params_compute_matrix(&params);
-
- copy_m4_m4(winmat, params.winmat);
- ps->clip_start = params.clip_start;
- ps->clip_end = params.clip_end;
- ps->is_ortho = params.is_ortho;
- }
- else {
- BLI_assert(0);
- }
-
- /* same as #ED_view3d_ob_project_mat_get */
- mul_m4_m4m4(vmat, viewmat, ps->obmat);
- mul_m4_m4m4(ps->projectMat, winmat, vmat);
- }
-
- invert_m4_m4(ps->projectMatInv, ps->projectMat);
-
- /* viewDir - object relative */
- copy_m3_m4(mat, viewinv);
- mul_m3_v3(mat, ps->viewDir);
- copy_m3_m4(mat, ps->obmat_imat);
- mul_m3_v3(mat, ps->viewDir);
- normalize_v3(ps->viewDir);
-
- if (UNLIKELY(ps->is_flip_object)) {
- negate_v3(ps->viewDir);
- }
-
- /* viewPos - object relative */
- copy_v3_v3(ps->viewPos, viewinv[3]);
- copy_m3_m4(mat, ps->obmat_imat);
- mul_m3_v3(mat, ps->viewPos);
- add_v3_v3(ps->viewPos, ps->obmat_imat[3]);
+ float mat[3][3];
+ float viewmat[4][4];
+ float viewinv[4][4];
+
+ ps->viewDir[0] = 0.0f;
+ ps->viewDir[1] = 0.0f;
+ ps->viewDir[2] = 1.0f;
+
+ copy_m4_m4(ps->obmat, ps->ob->obmat);
+
+ if (symmetry_flag) {
+ int i;
+ for (i = 0; i < 3; i++) {
+ if ((symmetry_flag >> i) & 1) {
+ negate_v3(ps->obmat[i]);
+ ps->is_flip_object = !ps->is_flip_object;
+ }
+ }
+ }
+
+ invert_m4_m4(ps->obmat_imat, ps->obmat);
+
+ if (ELEM(ps->source, PROJ_SRC_VIEW, PROJ_SRC_VIEW_FILL)) {
+ /* normal drawing */
+ ps->winx = ps->ar->winx;
+ ps->winy = ps->ar->winy;
+
+ copy_m4_m4(viewmat, ps->rv3d->viewmat);
+ copy_m4_m4(viewinv, ps->rv3d->viewinv);
+
+ ED_view3d_ob_project_mat_get_from_obmat(ps->rv3d, ps->obmat, ps->projectMat);
+
+ ps->is_ortho = ED_view3d_clip_range_get(
+ ps->depsgraph, ps->v3d, ps->rv3d, &ps->clip_start, &ps->clip_end, true);
+ }
+ else {
+ /* re-projection */
+ float winmat[4][4];
+ float vmat[4][4];
+
+ ps->winx = ps->reproject_ibuf->x;
+ ps->winy = ps->reproject_ibuf->y;
+
+ if (ps->source == PROJ_SRC_IMAGE_VIEW) {
+ /* image stores camera data, tricky */
+ IDProperty *idgroup = IDP_GetProperties(&ps->reproject_image->id, 0);
+ IDProperty *view_data = IDP_GetPropertyFromGroup(idgroup, PROJ_VIEW_DATA_ID);
+
+ const float *array = (float *)IDP_Array(view_data);
+
+ /* use image array, written when creating image */
+ memcpy(winmat, array, sizeof(winmat));
+ array += sizeof(winmat) / sizeof(float);
+ memcpy(viewmat, array, sizeof(viewmat));
+ array += sizeof(viewmat) / sizeof(float);
+ ps->clip_start = array[0];
+ ps->clip_end = array[1];
+ ps->is_ortho = array[2] ? 1 : 0;
+
+ invert_m4_m4(viewinv, viewmat);
+ }
+ else if (ps->source == PROJ_SRC_IMAGE_CAM) {
+ Object *cam_ob_eval = DEG_get_evaluated_object(ps->depsgraph, ps->scene->camera);
+ CameraParams params;
+
+ /* viewmat & viewinv */
+ copy_m4_m4(viewinv, cam_ob_eval->obmat);
+ normalize_m4(viewinv);
+ invert_m4_m4(viewmat, viewinv);
+
+ /* window matrix, clipping and ortho */
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_object(&params, cam_ob_eval);
+ BKE_camera_params_compute_viewplane(&params, ps->winx, ps->winy, 1.0f, 1.0f);
+ BKE_camera_params_compute_matrix(&params);
+
+ copy_m4_m4(winmat, params.winmat);
+ ps->clip_start = params.clip_start;
+ ps->clip_end = params.clip_end;
+ ps->is_ortho = params.is_ortho;
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ /* same as #ED_view3d_ob_project_mat_get */
+ mul_m4_m4m4(vmat, viewmat, ps->obmat);
+ mul_m4_m4m4(ps->projectMat, winmat, vmat);
+ }
+
+ invert_m4_m4(ps->projectMatInv, ps->projectMat);
+
+ /* viewDir - object relative */
+ copy_m3_m4(mat, viewinv);
+ mul_m3_v3(mat, ps->viewDir);
+ copy_m3_m4(mat, ps->obmat_imat);
+ mul_m3_v3(mat, ps->viewDir);
+ normalize_v3(ps->viewDir);
+
+ if (UNLIKELY(ps->is_flip_object)) {
+ negate_v3(ps->viewDir);
+ }
+
+ /* viewPos - object relative */
+ copy_v3_v3(ps->viewPos, viewinv[3]);
+ copy_m3_m4(mat, ps->obmat_imat);
+ mul_m3_v3(mat, ps->viewPos);
+ add_v3_v3(ps->viewPos, ps->obmat_imat[3]);
}
static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int diameter)
{
- const MVert *mv;
- float *projScreenCo;
- float projMargin;
- int a;
-
- INIT_MINMAX2(ps->screenMin, ps->screenMax);
-
- ps->screenCoords = MEM_mallocN(sizeof(float) * ps->totvert_eval * 4, "ProjectPaint ScreenVerts");
- projScreenCo = *ps->screenCoords;
-
- if (ps->is_ortho) {
- for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++, projScreenCo += 4) {
- mul_v3_m4v3(projScreenCo, ps->projectMat, mv->co);
-
- /* screen space, not clamped */
- projScreenCo[0] = (float)(ps->winx * 0.5f) + (ps->winx * 0.5f) * projScreenCo[0];
- projScreenCo[1] = (float)(ps->winy * 0.5f) + (ps->winy * 0.5f) * projScreenCo[1];
- minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo);
- }
- }
- else {
- for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++, projScreenCo += 4) {
- copy_v3_v3(projScreenCo, mv->co);
- projScreenCo[3] = 1.0f;
-
- mul_m4_v4(ps->projectMat, projScreenCo);
-
- if (projScreenCo[3] > ps->clip_start) {
- /* screen space, not clamped */
- projScreenCo[0] = (float)(ps->winx * 0.5f) + (ps->winx * 0.5f) * projScreenCo[0] / projScreenCo[3];
- projScreenCo[1] = (float)(ps->winy * 0.5f) + (ps->winy * 0.5f) * projScreenCo[1] / projScreenCo[3];
- /* Use the depth for bucket point occlusion */
- projScreenCo[2] = projScreenCo[2] / projScreenCo[3];
- minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo);
- }
- else {
- /* TODO - deal with cases where 1 side of a face goes behind the view ?
- *
- * After some research this is actually very tricky, only option is to
- * clip the derived mesh before painting, which is a Pain */
- projScreenCo[0] = FLT_MAX;
- }
- }
- }
-
- /* If this border is not added we get artifacts for faces that
- * have a parallel edge and at the bounds of the 2D projected verts eg
- * - a single screen aligned quad */
- projMargin = (ps->screenMax[0] - ps->screenMin[0]) * 0.000001f;
- ps->screenMax[0] += projMargin;
- ps->screenMin[0] -= projMargin;
- projMargin = (ps->screenMax[1] - ps->screenMin[1]) * 0.000001f;
- ps->screenMax[1] += projMargin;
- ps->screenMin[1] -= projMargin;
-
- if (ps->source == PROJ_SRC_VIEW) {
+ const MVert *mv;
+ float *projScreenCo;
+ float projMargin;
+ int a;
+
+ INIT_MINMAX2(ps->screenMin, ps->screenMax);
+
+ ps->screenCoords = MEM_mallocN(sizeof(float) * ps->totvert_eval * 4, "ProjectPaint ScreenVerts");
+ projScreenCo = *ps->screenCoords;
+
+ if (ps->is_ortho) {
+ for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++, projScreenCo += 4) {
+ mul_v3_m4v3(projScreenCo, ps->projectMat, mv->co);
+
+ /* screen space, not clamped */
+ projScreenCo[0] = (float)(ps->winx * 0.5f) + (ps->winx * 0.5f) * projScreenCo[0];
+ projScreenCo[1] = (float)(ps->winy * 0.5f) + (ps->winy * 0.5f) * projScreenCo[1];
+ minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo);
+ }
+ }
+ else {
+ for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++, projScreenCo += 4) {
+ copy_v3_v3(projScreenCo, mv->co);
+ projScreenCo[3] = 1.0f;
+
+ mul_m4_v4(ps->projectMat, projScreenCo);
+
+ if (projScreenCo[3] > ps->clip_start) {
+ /* screen space, not clamped */
+ projScreenCo[0] = (float)(ps->winx * 0.5f) +
+ (ps->winx * 0.5f) * projScreenCo[0] / projScreenCo[3];
+ projScreenCo[1] = (float)(ps->winy * 0.5f) +
+ (ps->winy * 0.5f) * projScreenCo[1] / projScreenCo[3];
+ /* Use the depth for bucket point occlusion */
+ projScreenCo[2] = projScreenCo[2] / projScreenCo[3];
+ minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo);
+ }
+ else {
+ /* TODO - deal with cases where 1 side of a face goes behind the view ?
+ *
+ * After some research this is actually very tricky, only option is to
+ * clip the derived mesh before painting, which is a Pain */
+ projScreenCo[0] = FLT_MAX;
+ }
+ }
+ }
+
+ /* If this border is not added we get artifacts for faces that
+ * have a parallel edge and at the bounds of the 2D projected verts eg
+ * - a single screen aligned quad */
+ projMargin = (ps->screenMax[0] - ps->screenMin[0]) * 0.000001f;
+ ps->screenMax[0] += projMargin;
+ ps->screenMin[0] -= projMargin;
+ projMargin = (ps->screenMax[1] - ps->screenMin[1]) * 0.000001f;
+ ps->screenMax[1] += projMargin;
+ ps->screenMin[1] -= projMargin;
+
+ if (ps->source == PROJ_SRC_VIEW) {
#ifdef PROJ_DEBUG_WINCLIP
- CLAMP(ps->screenMin[0], (float)(-diameter), (float)(ps->winx + diameter));
- CLAMP(ps->screenMax[0], (float)(-diameter), (float)(ps->winx + diameter));
+ CLAMP(ps->screenMin[0], (float)(-diameter), (float)(ps->winx + diameter));
+ CLAMP(ps->screenMax[0], (float)(-diameter), (float)(ps->winx + diameter));
- CLAMP(ps->screenMin[1], (float)(-diameter), (float)(ps->winy + diameter));
- CLAMP(ps->screenMax[1], (float)(-diameter), (float)(ps->winy + diameter));
+ CLAMP(ps->screenMin[1], (float)(-diameter), (float)(ps->winy + diameter));
+ CLAMP(ps->screenMax[1], (float)(-diameter), (float)(ps->winy + diameter));
#else
- UNUSED_VARS(diameter);
+ UNUSED_VARS(diameter);
#endif
- }
- else if (ps->source != PROJ_SRC_VIEW_FILL) { /* re-projection, use bounds */
- ps->screenMin[0] = 0;
- ps->screenMax[0] = (float)(ps->winx);
-
- ps->screenMin[1] = 0;
- ps->screenMax[1] = (float)(ps->winy);
- }
+ }
+ else if (ps->source != PROJ_SRC_VIEW_FILL) { /* re-projection, use bounds */
+ ps->screenMin[0] = 0;
+ ps->screenMax[0] = (float)(ps->winx);
+
+ ps->screenMin[1] = 0;
+ ps->screenMax[1] = (float)(ps->winy);
+ }
}
static void proj_paint_state_cavity_init(ProjPaintState *ps)
{
- const MVert *mv;
- const MEdge *me;
- float *cavities;
- int a;
-
- if (ps->do_mask_cavity) {
- int *counter = MEM_callocN(sizeof(int) * ps->totvert_eval, "counter");
- float (*edges)[3] = MEM_callocN(sizeof(float) * 3 * ps->totvert_eval, "edges");
- ps->cavities = MEM_mallocN(sizeof(float) * ps->totvert_eval, "ProjectPaint Cavities");
- cavities = ps->cavities;
-
- for (a = 0, me = ps->medge_eval; a < ps->totedge_eval; a++, me++) {
- float e[3];
- sub_v3_v3v3(e, ps->mvert_eval[me->v1].co, ps->mvert_eval[me->v2].co);
- normalize_v3(e);
- add_v3_v3(edges[me->v2], e);
- counter[me->v2]++;
- sub_v3_v3(edges[me->v1], e);
- counter[me->v1]++;
- }
- for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++) {
- if (counter[a] > 0) {
- float no[3];
- mul_v3_fl(edges[a], 1.0f / counter[a]);
- normal_short_to_float_v3(no, mv->no);
- /* augment the diffe*/
- cavities[a] = saacos(10.0f * dot_v3v3(no, edges[a])) * (float)M_1_PI;
- }
- else
- cavities[a] = 0.0;
- }
-
- MEM_freeN(counter);
- MEM_freeN(edges);
- }
+ const MVert *mv;
+ const MEdge *me;
+ float *cavities;
+ int a;
+
+ if (ps->do_mask_cavity) {
+ int *counter = MEM_callocN(sizeof(int) * ps->totvert_eval, "counter");
+ float(*edges)[3] = MEM_callocN(sizeof(float) * 3 * ps->totvert_eval, "edges");
+ ps->cavities = MEM_mallocN(sizeof(float) * ps->totvert_eval, "ProjectPaint Cavities");
+ cavities = ps->cavities;
+
+ for (a = 0, me = ps->medge_eval; a < ps->totedge_eval; a++, me++) {
+ float e[3];
+ sub_v3_v3v3(e, ps->mvert_eval[me->v1].co, ps->mvert_eval[me->v2].co);
+ normalize_v3(e);
+ add_v3_v3(edges[me->v2], e);
+ counter[me->v2]++;
+ sub_v3_v3(edges[me->v1], e);
+ counter[me->v1]++;
+ }
+ for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++) {
+ if (counter[a] > 0) {
+ float no[3];
+ mul_v3_fl(edges[a], 1.0f / counter[a]);
+ normal_short_to_float_v3(no, mv->no);
+ /* augment the diffe*/
+ cavities[a] = saacos(10.0f * dot_v3v3(no, edges[a])) * (float)M_1_PI;
+ }
+ else
+ cavities[a] = 0.0;
+ }
+
+ MEM_freeN(counter);
+ MEM_freeN(edges);
+ }
}
#ifndef PROJ_DEBUG_NOSEAMBLEED
static void proj_paint_state_seam_bleed_init(ProjPaintState *ps)
{
- if (ps->seam_bleed_px > 0.0f) {
- ps->vertFaces = MEM_callocN(sizeof(LinkNode *) * ps->totvert_eval, "paint-vertFaces");
- ps->faceSeamFlags = MEM_callocN(sizeof(ushort) * ps->totlooptri_eval, "paint-faceSeamFlags");
- ps->faceWindingFlags = MEM_callocN(sizeof(char) * ps->totlooptri_eval, "paint-faceWindindFlags");
- ps->loopSeamData = MEM_mallocN(sizeof(LoopSeamData) * ps->totloop_eval, "paint-loopSeamUVs");
- ps->vertSeams = MEM_callocN(sizeof(ListBase) * ps->totvert_eval, "paint-vertSeams");
- }
+ if (ps->seam_bleed_px > 0.0f) {
+ ps->vertFaces = MEM_callocN(sizeof(LinkNode *) * ps->totvert_eval, "paint-vertFaces");
+ ps->faceSeamFlags = MEM_callocN(sizeof(ushort) * ps->totlooptri_eval, "paint-faceSeamFlags");
+ ps->faceWindingFlags = MEM_callocN(sizeof(char) * ps->totlooptri_eval,
+ "paint-faceWindindFlags");
+ ps->loopSeamData = MEM_mallocN(sizeof(LoopSeamData) * ps->totloop_eval, "paint-loopSeamUVs");
+ ps->vertSeams = MEM_callocN(sizeof(ListBase) * ps->totvert_eval, "paint-vertSeams");
+ }
}
#endif
static void proj_paint_state_thread_init(ProjPaintState *ps, const bool reset_threads)
{
- int a;
+ int a;
- /* Thread stuff
- *
- * very small brushes run a lot slower multithreaded since the advantage with
- * threads is being able to fill in multiple buckets at once.
- * Only use threads for bigger brushes. */
+ /* Thread stuff
+ *
+ * very small brushes run a lot slower multithreaded since the advantage with
+ * threads is being able to fill in multiple buckets at once.
+ * Only use threads for bigger brushes. */
- ps->thread_tot = BKE_scene_num_threads(ps->scene);
+ ps->thread_tot = BKE_scene_num_threads(ps->scene);
- /* workaround for #35057, disable threading if diameter is less than is possible for
- * optimum bucket number generation */
- if (reset_threads)
- ps->thread_tot = 1;
+ /* workaround for #35057, disable threading if diameter is less than is possible for
+ * optimum bucket number generation */
+ if (reset_threads)
+ ps->thread_tot = 1;
- if (ps->is_shared_user == false) {
- if (ps->thread_tot > 1) {
- ps->tile_lock = MEM_mallocN(sizeof(SpinLock), "projpaint_tile_lock");
- BLI_spin_init(ps->tile_lock);
- }
+ if (ps->is_shared_user == false) {
+ if (ps->thread_tot > 1) {
+ ps->tile_lock = MEM_mallocN(sizeof(SpinLock), "projpaint_tile_lock");
+ BLI_spin_init(ps->tile_lock);
+ }
- image_undo_init_locks();
- }
+ image_undo_init_locks();
+ }
- for (a = 0; a < ps->thread_tot; a++) {
- ps->arena_mt[a] = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "project paint arena");
- }
+ for (a = 0; a < ps->thread_tot; a++) {
+ ps->arena_mt[a] = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "project paint arena");
+ }
}
static void proj_paint_state_vert_flags_init(ProjPaintState *ps)
{
- if (ps->do_backfacecull && ps->do_mask_normal) {
- float viewDirPersp[3];
- const MVert *mv;
- float no[3];
- int a;
-
- ps->vertFlags = MEM_callocN(sizeof(char) * ps->totvert_eval, "paint-vertFlags");
-
- for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++) {
- normal_short_to_float_v3(no, mv->no);
- if (UNLIKELY(ps->is_flip_object)) {
- negate_v3(no);
- }
-
- if (ps->is_ortho) {
- if (dot_v3v3(ps->viewDir, no) <= ps->normal_angle__cos) {
- /* 1 vert of this face is towards us */
- ps->vertFlags[a] |= PROJ_VERT_CULL;
- }
- }
- else {
- sub_v3_v3v3(viewDirPersp, ps->viewPos, mv->co);
- normalize_v3(viewDirPersp);
- if (UNLIKELY(ps->is_flip_object)) {
- negate_v3(viewDirPersp);
- }
- if (dot_v3v3(viewDirPersp, no) <= ps->normal_angle__cos) {
- /* 1 vert of this face is towards us */
- ps->vertFlags[a] |= PROJ_VERT_CULL;
- }
- }
- }
- }
- else {
- ps->vertFlags = NULL;
- }
+ if (ps->do_backfacecull && ps->do_mask_normal) {
+ float viewDirPersp[3];
+ const MVert *mv;
+ float no[3];
+ int a;
+
+ ps->vertFlags = MEM_callocN(sizeof(char) * ps->totvert_eval, "paint-vertFlags");
+
+ for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++) {
+ normal_short_to_float_v3(no, mv->no);
+ if (UNLIKELY(ps->is_flip_object)) {
+ negate_v3(no);
+ }
+
+ if (ps->is_ortho) {
+ if (dot_v3v3(ps->viewDir, no) <= ps->normal_angle__cos) {
+ /* 1 vert of this face is towards us */
+ ps->vertFlags[a] |= PROJ_VERT_CULL;
+ }
+ }
+ else {
+ sub_v3_v3v3(viewDirPersp, ps->viewPos, mv->co);
+ normalize_v3(viewDirPersp);
+ if (UNLIKELY(ps->is_flip_object)) {
+ negate_v3(viewDirPersp);
+ }
+ if (dot_v3v3(viewDirPersp, no) <= ps->normal_angle__cos) {
+ /* 1 vert of this face is towards us */
+ ps->vertFlags[a] |= PROJ_VERT_CULL;
+ }
+ }
+ }
+ }
+ else {
+ ps->vertFlags = NULL;
+ }
}
#ifndef PROJ_DEBUG_NOSEAMBLEED
-static void project_paint_bleed_add_face_user(
- const ProjPaintState *ps, MemArena *arena,
- const MLoopTri *lt, const int tri_index)
+static void project_paint_bleed_add_face_user(const ProjPaintState *ps,
+ MemArena *arena,
+ const MLoopTri *lt,
+ const int tri_index)
{
- /* add face user if we have bleed enabled, set the UV seam flags later */
- /* annoying but we need to add all faces even ones we never use elsewhere */
- if (ps->seam_bleed_px > 0.0f) {
- const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt) };
-
- /* Check for degenerate triangles. Degenerate faces cause trouble with bleed computations.
- * 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) {
- const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
- void *tri_index_p = POINTER_FROM_INT(tri_index);
-
- BLI_linklist_prepend_arena(&ps->vertFaces[lt_vtri[0]], tri_index_p, arena);
- BLI_linklist_prepend_arena(&ps->vertFaces[lt_vtri[1]], tri_index_p, arena);
- BLI_linklist_prepend_arena(&ps->vertFaces[lt_vtri[2]], tri_index_p, arena);
- }
- else {
- ps->faceSeamFlags[tri_index] |= PROJ_FACE_DEGENERATE;
- }
- }
+ /* add face user if we have bleed enabled, set the UV seam flags later */
+ /* annoying but we need to add all faces even ones we never use elsewhere */
+ if (ps->seam_bleed_px > 0.0f) {
+ const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
+
+ /* Check for degenerate triangles. Degenerate faces cause trouble with bleed computations.
+ * 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) {
+ const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
+ void *tri_index_p = POINTER_FROM_INT(tri_index);
+
+ BLI_linklist_prepend_arena(&ps->vertFaces[lt_vtri[0]], tri_index_p, arena);
+ BLI_linklist_prepend_arena(&ps->vertFaces[lt_vtri[1]], tri_index_p, arena);
+ BLI_linklist_prepend_arena(&ps->vertFaces[lt_vtri[2]], tri_index_p, arena);
+ }
+ else {
+ ps->faceSeamFlags[tri_index] |= PROJ_FACE_DEGENERATE;
+ }
+ }
}
#endif
/* Return true if evaluated mesh can be painted on, false otherwise */
static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *ps)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *ob = ps->ob;
-
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
-
- if (scene_eval == NULL || ob_eval == NULL) {
- return false;
- }
-
- CustomData_MeshMasks cddata_masks = scene_eval->customdata_mask;
- cddata_masks.fmask |= CD_MASK_MTFACE;
- cddata_masks.lmask |= CD_MASK_MLOOPUV;
-
- /* Workaround for subsurf selection, try the display mesh first */
- if (ps->source == PROJ_SRC_IMAGE_CAM) {
- /* using render mesh, assume only camera was rendered from */
- ps->me_eval = mesh_create_eval_final_render(
- depsgraph, scene_eval, ob_eval, &cddata_masks);
- ps->me_eval_free = true;
- }
- else {
- if (ps->do_face_sel) {
- cddata_masks.vmask |= CD_MASK_ORIGINDEX;
- cddata_masks.emask |= CD_MASK_ORIGINDEX;
- cddata_masks.pmask |= CD_MASK_ORIGINDEX;
- }
- ps->me_eval = mesh_get_eval_final(
- depsgraph, scene_eval, ob_eval,
- &cddata_masks);
- ps->me_eval_free = false;
- }
-
- if (!CustomData_has_layer(&ps->me_eval->ldata, CD_MLOOPUV)) {
- if (ps->me_eval_free) {
- BKE_id_free(NULL, ps->me_eval);
- }
- ps->me_eval = NULL;
- return false;
- }
-
- /* Build final material array, we use this a lot here. */
- /* materials start from 1, default material is 0 */
- const int totmat = ob->totcol + 1;
- ps->mat_array = MEM_malloc_arrayN(totmat, sizeof(*ps->mat_array), __func__);
- /* We leave last material as empty - rationale here is being able to index
- * 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[totmat - 1] = NULL;
-
- ps->mvert_eval = ps->me_eval->mvert;
- if (ps->do_mask_cavity) {
- ps->medge_eval = ps->me_eval->medge;
- }
- ps->mloop_eval = ps->me_eval->mloop;
- ps->mpoly_eval = ps->me_eval->mpoly;
-
- ps->totvert_eval = ps->me_eval->totvert;
- ps->totedge_eval = ps->me_eval->totedge;
- ps->totpoly_eval = ps->me_eval->totpoly;
- ps->totloop_eval = ps->me_eval->totloop;
-
- ps->mlooptri_eval = BKE_mesh_runtime_looptri_ensure(ps->me_eval);
- ps->totlooptri_eval = ps->me_eval->runtime.looptris.len;
-
- ps->poly_to_loop_uv = MEM_mallocN(ps->totpoly_eval * sizeof(MLoopUV *), "proj_paint_mtfaces");
-
- return true;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob = ps->ob;
+
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+
+ if (scene_eval == NULL || ob_eval == NULL) {
+ return false;
+ }
+
+ CustomData_MeshMasks cddata_masks = scene_eval->customdata_mask;
+ cddata_masks.fmask |= CD_MASK_MTFACE;
+ cddata_masks.lmask |= CD_MASK_MLOOPUV;
+
+ /* Workaround for subsurf selection, try the display mesh first */
+ if (ps->source == PROJ_SRC_IMAGE_CAM) {
+ /* using render mesh, assume only camera was rendered from */
+ ps->me_eval = mesh_create_eval_final_render(depsgraph, scene_eval, ob_eval, &cddata_masks);
+ ps->me_eval_free = true;
+ }
+ else {
+ if (ps->do_face_sel) {
+ cddata_masks.vmask |= CD_MASK_ORIGINDEX;
+ cddata_masks.emask |= CD_MASK_ORIGINDEX;
+ cddata_masks.pmask |= CD_MASK_ORIGINDEX;
+ }
+ ps->me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &cddata_masks);
+ ps->me_eval_free = false;
+ }
+
+ if (!CustomData_has_layer(&ps->me_eval->ldata, CD_MLOOPUV)) {
+ if (ps->me_eval_free) {
+ BKE_id_free(NULL, ps->me_eval);
+ }
+ ps->me_eval = NULL;
+ return false;
+ }
+
+ /* Build final material array, we use this a lot here. */
+ /* materials start from 1, default material is 0 */
+ const int totmat = ob->totcol + 1;
+ ps->mat_array = MEM_malloc_arrayN(totmat, sizeof(*ps->mat_array), __func__);
+ /* We leave last material as empty - rationale here is being able to index
+ * 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[totmat - 1] = NULL;
+
+ ps->mvert_eval = ps->me_eval->mvert;
+ if (ps->do_mask_cavity) {
+ ps->medge_eval = ps->me_eval->medge;
+ }
+ ps->mloop_eval = ps->me_eval->mloop;
+ ps->mpoly_eval = ps->me_eval->mpoly;
+
+ ps->totvert_eval = ps->me_eval->totvert;
+ ps->totedge_eval = ps->me_eval->totedge;
+ ps->totpoly_eval = ps->me_eval->totpoly;
+ ps->totloop_eval = ps->me_eval->totloop;
+
+ ps->mlooptri_eval = BKE_mesh_runtime_looptri_ensure(ps->me_eval);
+ ps->totlooptri_eval = ps->me_eval->runtime.looptris.len;
+
+ ps->poly_to_loop_uv = MEM_mallocN(ps->totpoly_eval * sizeof(MLoopUV *), "proj_paint_mtfaces");
+
+ return true;
}
typedef struct {
- const MLoopUV *mloopuv_clone_base;
- const TexPaintSlot *slot_last_clone;
- const TexPaintSlot *slot_clone;
+ const MLoopUV *mloopuv_clone_base;
+ const TexPaintSlot *slot_last_clone;
+ const TexPaintSlot *slot_clone;
} ProjPaintLayerClone;
-static void proj_paint_layer_clone_init(
- ProjPaintState *ps,
- ProjPaintLayerClone *layer_clone)
+static void proj_paint_layer_clone_init(ProjPaintState *ps, ProjPaintLayerClone *layer_clone)
{
- MLoopUV *mloopuv_clone_base = NULL;
+ MLoopUV *mloopuv_clone_base = NULL;
- /* use clone mtface? */
- if (ps->do_layer_clone) {
- const int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV);
+ /* use clone mtface? */
+ if (ps->do_layer_clone) {
+ const int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV);
- ps->poly_to_loop_uv_clone = MEM_mallocN(ps->totpoly_eval * sizeof(MLoopUV *), "proj_paint_mtfaces");
+ ps->poly_to_loop_uv_clone = MEM_mallocN(ps->totpoly_eval * sizeof(MLoopUV *),
+ "proj_paint_mtfaces");
- if (layer_num != -1)
- mloopuv_clone_base = CustomData_get_layer_n(&ps->me_eval->ldata, CD_MLOOPUV, layer_num);
+ if (layer_num != -1)
+ mloopuv_clone_base = CustomData_get_layer_n(&ps->me_eval->ldata, CD_MLOOPUV, layer_num);
- if (mloopuv_clone_base == NULL) {
- /* get active instead */
- mloopuv_clone_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
- }
+ if (mloopuv_clone_base == NULL) {
+ /* get active instead */
+ mloopuv_clone_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
+ }
+ }
- }
-
- memset(layer_clone, 0, sizeof(*layer_clone));
- layer_clone->mloopuv_clone_base = mloopuv_clone_base;
+ memset(layer_clone, 0, sizeof(*layer_clone));
+ layer_clone->mloopuv_clone_base = mloopuv_clone_base;
}
/* Return true if face should be skipped, false otherwise */
-static bool project_paint_clone_face_skip(
- ProjPaintState *ps,
- ProjPaintLayerClone *lc,
- const TexPaintSlot *slot,
- const int tri_index)
+static bool project_paint_clone_face_skip(ProjPaintState *ps,
+ ProjPaintLayerClone *lc,
+ const TexPaintSlot *slot,
+ const int tri_index)
{
- if (ps->do_layer_clone) {
- if (ps->do_material_slots) {
- lc->slot_clone = project_paint_face_clone_slot(ps, tri_index);
- /* all faces should have a valid slot, reassert here */
- if (ELEM(lc->slot_clone, NULL, slot))
- return true;
- }
- else if (ps->clone_ima == ps->canvas_ima)
- return true;
-
- if (ps->do_material_slots) {
- if (lc->slot_clone != lc->slot_last_clone) {
- if (!slot->uvname ||
- !(lc->mloopuv_clone_base = CustomData_get_layer_named(
- &ps->me_eval->ldata, CD_MLOOPUV,
- lc->slot_clone->uvname)))
- {
- lc->mloopuv_clone_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
- }
- lc->slot_last_clone = lc->slot_clone;
- }
- }
-
- /* will set multiple times for 4+ sided poly */
- ps->poly_to_loop_uv_clone[ps->mlooptri_eval[tri_index].poly] = lc->mloopuv_clone_base;
- }
- return false;
+ if (ps->do_layer_clone) {
+ if (ps->do_material_slots) {
+ lc->slot_clone = project_paint_face_clone_slot(ps, tri_index);
+ /* all faces should have a valid slot, reassert here */
+ if (ELEM(lc->slot_clone, NULL, slot))
+ return true;
+ }
+ else if (ps->clone_ima == ps->canvas_ima)
+ return true;
+
+ if (ps->do_material_slots) {
+ if (lc->slot_clone != lc->slot_last_clone) {
+ if (!slot->uvname || !(lc->mloopuv_clone_base = CustomData_get_layer_named(
+ &ps->me_eval->ldata, CD_MLOOPUV, lc->slot_clone->uvname))) {
+ lc->mloopuv_clone_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
+ }
+ lc->slot_last_clone = lc->slot_clone;
+ }
+ }
+
+ /* will set multiple times for 4+ sided poly */
+ ps->poly_to_loop_uv_clone[ps->mlooptri_eval[tri_index].poly] = lc->mloopuv_clone_base;
+ }
+ return false;
}
typedef struct {
- const MPoly *mpoly_orig;
+ const MPoly *mpoly_orig;
- const int *index_mp_to_orig;
+ const int *index_mp_to_orig;
} ProjPaintFaceLookup;
-static void proj_paint_face_lookup_init(
- const ProjPaintState *ps,
- ProjPaintFaceLookup *face_lookup)
+static void proj_paint_face_lookup_init(const ProjPaintState *ps, ProjPaintFaceLookup *face_lookup)
{
- memset(face_lookup, 0, sizeof(*face_lookup));
- if (ps->do_face_sel) {
- face_lookup->index_mp_to_orig = CustomData_get_layer(&ps->me_eval->pdata, CD_ORIGINDEX);
- face_lookup->mpoly_orig = ((Mesh *)ps->ob->data)->mpoly;
- }
+ memset(face_lookup, 0, sizeof(*face_lookup));
+ if (ps->do_face_sel) {
+ face_lookup->index_mp_to_orig = CustomData_get_layer(&ps->me_eval->pdata, CD_ORIGINDEX);
+ face_lookup->mpoly_orig = ((Mesh *)ps->ob->data)->mpoly;
+ }
}
/* Return true if face should be considered selected, false otherwise */
-static bool project_paint_check_face_sel(
- const ProjPaintState *ps,
- const ProjPaintFaceLookup *face_lookup,
- const MLoopTri *lt)
+static bool project_paint_check_face_sel(const ProjPaintState *ps,
+ const ProjPaintFaceLookup *face_lookup,
+ const MLoopTri *lt)
{
- if (ps->do_face_sel) {
- int orig_index;
- const MPoly *mp;
-
- if ((face_lookup->index_mp_to_orig != NULL) &&
- (((orig_index = (face_lookup->index_mp_to_orig[lt->poly]))) != ORIGINDEX_NONE))
- {
- mp = &face_lookup->mpoly_orig[orig_index];
- }
- else {
- mp = &ps->mpoly_eval[lt->poly];
- }
-
- return ((mp->flag & ME_FACE_SEL) != 0);
- }
- else {
- return true;
- }
+ if (ps->do_face_sel) {
+ int orig_index;
+ const MPoly *mp;
+
+ if ((face_lookup->index_mp_to_orig != NULL) &&
+ (((orig_index = (face_lookup->index_mp_to_orig[lt->poly]))) != ORIGINDEX_NONE)) {
+ mp = &face_lookup->mpoly_orig[orig_index];
+ }
+ else {
+ mp = &ps->mpoly_eval[lt->poly];
+ }
+
+ return ((mp->flag & ME_FACE_SEL) != 0);
+ }
+ else {
+ return true;
+ }
}
typedef struct {
- const float *v1;
- const float *v2;
- const float *v3;
+ const float *v1;
+ const float *v2;
+ const float *v3;
} ProjPaintFaceCoSS;
-static void proj_paint_face_coSS_init(
- const ProjPaintState *ps, const MLoopTri *lt,
- ProjPaintFaceCoSS *coSS)
+static void proj_paint_face_coSS_init(const ProjPaintState *ps,
+ const MLoopTri *lt,
+ ProjPaintFaceCoSS *coSS)
{
- const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
- coSS->v1 = ps->screenCoords[lt_vtri[0]];
- coSS->v2 = ps->screenCoords[lt_vtri[1]];
- coSS->v3 = ps->screenCoords[lt_vtri[2]];
+ const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
+ coSS->v1 = ps->screenCoords[lt_vtri[0]];
+ coSS->v2 = ps->screenCoords[lt_vtri[1]];
+ coSS->v3 = ps->screenCoords[lt_vtri[2]];
}
/* Return true if face should be culled, false otherwise */
-static bool project_paint_flt_max_cull(
- const ProjPaintState *ps,
- const ProjPaintFaceCoSS *coSS)
+static bool project_paint_flt_max_cull(const ProjPaintState *ps, const ProjPaintFaceCoSS *coSS)
{
- if (!ps->is_ortho) {
- if (coSS->v1[0] == FLT_MAX ||
- coSS->v2[0] == FLT_MAX ||
- coSS->v3[0] == FLT_MAX)
- {
- return true;
- }
- }
- return false;
+ if (!ps->is_ortho) {
+ if (coSS->v1[0] == FLT_MAX || coSS->v2[0] == FLT_MAX || coSS->v3[0] == FLT_MAX) {
+ return true;
+ }
+ }
+ return false;
}
#ifdef PROJ_DEBUG_WINCLIP
/* Return true if face should be culled, false otherwise */
-static bool project_paint_winclip(
- const ProjPaintState *ps,
- const ProjPaintFaceCoSS *coSS)
+static bool project_paint_winclip(const ProjPaintState *ps, const ProjPaintFaceCoSS *coSS)
{
- /* ignore faces outside the view */
- return ((ps->source != PROJ_SRC_VIEW_FILL) &&
- ((coSS->v1[0] < ps->screenMin[0] &&
- coSS->v2[0] < ps->screenMin[0] &&
- coSS->v3[0] < ps->screenMin[0]) ||
-
- (coSS->v1[0] > ps->screenMax[0] &&
- coSS->v2[0] > ps->screenMax[0] &&
- coSS->v3[0] > ps->screenMax[0]) ||
-
- (coSS->v1[1] < ps->screenMin[1] &&
- coSS->v2[1] < ps->screenMin[1] &&
- coSS->v3[1] < ps->screenMin[1]) ||
-
- (coSS->v1[1] > ps->screenMax[1] &&
- coSS->v2[1] > ps->screenMax[1] &&
- coSS->v3[1] > ps->screenMax[1])));
-}
-#endif //PROJ_DEBUG_WINCLIP
+ /* ignore faces outside the view */
+ return ((ps->source != PROJ_SRC_VIEW_FILL) &&
+ ((coSS->v1[0] < ps->screenMin[0] && coSS->v2[0] < ps->screenMin[0] &&
+ coSS->v3[0] < ps->screenMin[0]) ||
+ (coSS->v1[0] > ps->screenMax[0] && coSS->v2[0] > ps->screenMax[0] &&
+ coSS->v3[0] > ps->screenMax[0]) ||
-static void project_paint_build_proj_ima(
- ProjPaintState *ps, MemArena *arena,
- LinkNode *image_LinkList)
+ (coSS->v1[1] < ps->screenMin[1] && coSS->v2[1] < ps->screenMin[1] &&
+ coSS->v3[1] < ps->screenMin[1]) ||
+
+ (coSS->v1[1] > ps->screenMax[1] && coSS->v2[1] > ps->screenMax[1] &&
+ coSS->v3[1] > ps->screenMax[1])));
+}
+#endif //PROJ_DEBUG_WINCLIP
+
+static void project_paint_build_proj_ima(ProjPaintState *ps,
+ MemArena *arena,
+ LinkNode *image_LinkList)
{
- ProjPaintImage *projIma;
- LinkNode *node;
- int i;
-
- /* build an array of images we use */
- projIma = ps->projImages = BLI_memarena_alloc(arena, sizeof(ProjPaintImage) * ps->image_tot);
-
- for (node = image_LinkList, i = 0; node; node = node->next, i++, projIma++) {
- int size;
- projIma->ima = node->link;
- projIma->touch = 0;
- projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL);
- size = sizeof(void **) * IMAPAINT_TILE_NUMBER(projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(projIma->ibuf->y);
- projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
- partial_redraw_array_init(projIma->partRedrawRect);
- projIma->undoRect = (volatile void **) BLI_memarena_alloc(arena, size);
- memset((void *)projIma->undoRect, 0, size);
- projIma->maskRect = BLI_memarena_alloc(arena, size);
- memset(projIma->maskRect, 0, size);
- projIma->valid = BLI_memarena_alloc(arena, size);
- memset(projIma->valid, 0, size);
- }
+ ProjPaintImage *projIma;
+ LinkNode *node;
+ int i;
+
+ /* build an array of images we use */
+ projIma = ps->projImages = BLI_memarena_alloc(arena, sizeof(ProjPaintImage) * ps->image_tot);
+
+ for (node = image_LinkList, i = 0; node; node = node->next, i++, projIma++) {
+ int size;
+ projIma->ima = node->link;
+ projIma->touch = 0;
+ projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL);
+ size = sizeof(void **) * IMAPAINT_TILE_NUMBER(projIma->ibuf->x) *
+ IMAPAINT_TILE_NUMBER(projIma->ibuf->y);
+ projIma->partRedrawRect = BLI_memarena_alloc(
+ arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ partial_redraw_array_init(projIma->partRedrawRect);
+ projIma->undoRect = (volatile void **)BLI_memarena_alloc(arena, size);
+ memset((void *)projIma->undoRect, 0, size);
+ projIma->maskRect = BLI_memarena_alloc(arena, size);
+ memset(projIma->maskRect, 0, size);
+ projIma->valid = BLI_memarena_alloc(arena, size);
+ memset(projIma->valid, 0, size);
+ }
}
-static void project_paint_prepare_all_faces(
- ProjPaintState *ps, MemArena *arena,
- const ProjPaintFaceLookup *face_lookup,
- ProjPaintLayerClone *layer_clone,
- const MLoopUV *mloopuv_base,
- const bool is_multi_view)
+static void project_paint_prepare_all_faces(ProjPaintState *ps,
+ MemArena *arena,
+ const ProjPaintFaceLookup *face_lookup,
+ ProjPaintLayerClone *layer_clone,
+ const MLoopUV *mloopuv_base,
+ const bool is_multi_view)
{
- /* Image Vars - keep track of images we have used */
- LinkNodePair image_LinkList = {NULL, NULL};
-
- Image *tpage_last = NULL, *tpage;
- TexPaintSlot *slot_last = NULL;
- TexPaintSlot *slot = NULL;
- const MLoopTri *lt;
- int image_index = -1, tri_index;
- int prev_poly = -1;
-
- for (tri_index = 0, lt = ps->mlooptri_eval; tri_index < ps->totlooptri_eval; tri_index++, lt++) {
- bool is_face_sel;
- bool skip_tri = false;
-
- is_face_sel = project_paint_check_face_sel(ps, face_lookup, lt);
-
- if (!ps->do_stencil_brush) {
- slot = project_paint_face_paint_slot(ps, tri_index);
- /* all faces should have a valid slot, reassert here */
- if (slot == NULL) {
- mloopuv_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
- tpage = ps->canvas_ima;
- }
- else {
- if (slot != slot_last) {
- if (!slot->uvname || !(mloopuv_base = CustomData_get_layer_named(&ps->me_eval->ldata, CD_MLOOPUV, slot->uvname)))
- mloopuv_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
- slot_last = slot;
- }
-
- /* don't allow using the same inage for painting and stencilling */
- if (slot->ima == ps->stencil_ima) {
- /* Delay continuing the loop until after loop_uvs and bleed faces are initialized.
- * While this shouldn't be used, face-winding reads all polys.
- * It's less trouble to set all faces to valid UV's,
- * avoiding NULL checks all over. */
- skip_tri = true;
- }
- else {
- tpage = slot->ima;
- }
- }
- }
- else {
- tpage = ps->stencil_ima;
- }
-
- ps->poly_to_loop_uv[lt->poly] = mloopuv_base;
+ /* Image Vars - keep track of images we have used */
+ LinkNodePair image_LinkList = {NULL, NULL};
+
+ Image *tpage_last = NULL, *tpage;
+ TexPaintSlot *slot_last = NULL;
+ TexPaintSlot *slot = NULL;
+ const MLoopTri *lt;
+ int image_index = -1, tri_index;
+ int prev_poly = -1;
+
+ for (tri_index = 0, lt = ps->mlooptri_eval; tri_index < ps->totlooptri_eval; tri_index++, lt++) {
+ bool is_face_sel;
+ bool skip_tri = false;
+
+ is_face_sel = project_paint_check_face_sel(ps, face_lookup, lt);
+
+ if (!ps->do_stencil_brush) {
+ slot = project_paint_face_paint_slot(ps, tri_index);
+ /* all faces should have a valid slot, reassert here */
+ if (slot == NULL) {
+ mloopuv_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
+ tpage = ps->canvas_ima;
+ }
+ else {
+ if (slot != slot_last) {
+ if (!slot->uvname || !(mloopuv_base = CustomData_get_layer_named(
+ &ps->me_eval->ldata, CD_MLOOPUV, slot->uvname)))
+ mloopuv_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
+ slot_last = slot;
+ }
+
+ /* don't allow using the same inage for painting and stencilling */
+ if (slot->ima == ps->stencil_ima) {
+ /* Delay continuing the loop until after loop_uvs and bleed faces are initialized.
+ * While this shouldn't be used, face-winding reads all polys.
+ * It's less trouble to set all faces to valid UV's,
+ * avoiding NULL checks all over. */
+ skip_tri = true;
+ }
+ else {
+ tpage = slot->ima;
+ }
+ }
+ }
+ else {
+ tpage = ps->stencil_ima;
+ }
+
+ ps->poly_to_loop_uv[lt->poly] = mloopuv_base;
#ifndef PROJ_DEBUG_NOSEAMBLEED
- project_paint_bleed_add_face_user(ps, arena, lt, tri_index);
+ project_paint_bleed_add_face_user(ps, arena, lt, tri_index);
#endif
- if (skip_tri || project_paint_clone_face_skip(ps, layer_clone, slot, tri_index)) {
- continue;
- }
+ if (skip_tri || project_paint_clone_face_skip(ps, layer_clone, slot, tri_index)) {
+ continue;
+ }
- /* tfbase here should be non-null! */
- BLI_assert(mloopuv_base != NULL);
+ /* tfbase here should be non-null! */
+ BLI_assert(mloopuv_base != NULL);
- if (is_face_sel && tpage) {
- ProjPaintFaceCoSS coSS;
- proj_paint_face_coSS_init(ps, lt, &coSS);
+ if (is_face_sel && tpage) {
+ ProjPaintFaceCoSS coSS;
+ proj_paint_face_coSS_init(ps, lt, &coSS);
- if (is_multi_view == false) {
- if (project_paint_flt_max_cull(ps, &coSS)) {
- continue;
- }
+ if (is_multi_view == false) {
+ if (project_paint_flt_max_cull(ps, &coSS)) {
+ continue;
+ }
#ifdef PROJ_DEBUG_WINCLIP
- if (project_paint_winclip(ps, &coSS)) {
- continue;
- }
-
-#endif //PROJ_DEBUG_WINCLIP
-
- /* backface culls individual triangles but mask normal will use polygon */
- if (ps->do_backfacecull) {
- if (ps->do_mask_normal) {
- if (prev_poly != lt->poly) {
- int iloop;
- bool culled = true;
- const MPoly *poly = ps->mpoly_eval + lt->poly;
- int poly_loops = poly->totloop;
- prev_poly = lt->poly;
- for (iloop = 0; iloop < poly_loops; iloop++) {
- if (!(ps->vertFlags[ps->mloop_eval[poly->loopstart + iloop].v] & PROJ_VERT_CULL)) {
- culled = false;
- break;
- }
- }
-
- if (culled) {
- /* poly loops - 2 is number of triangles for poly,
- * but counter gets incremented when continuing, so decrease by 3 */
- int poly_tri = poly_loops - 3;
- tri_index += poly_tri;
- lt += poly_tri;
- continue;
- }
- }
- }
- else {
- if ((line_point_side_v2(coSS.v1, coSS.v2, coSS.v3) < 0.0f) != ps->is_flip_object) {
- continue;
- }
- }
- }
- }
-
- if (tpage_last != tpage) {
-
- image_index = BLI_linklist_index(image_LinkList.list, tpage);
-
- if (image_index == -1 && BKE_image_has_ibuf(tpage, NULL)) {
- /* MemArena dosnt have an append func */
- BLI_linklist_append(&image_LinkList, tpage);
- image_index = ps->image_tot;
- ps->image_tot++;
- }
-
- tpage_last = tpage;
- }
-
- if (image_index != -1) {
- /* Initialize the faces screen pixels */
- /* Add this to a list to initialize later */
- project_paint_delayed_face_init(ps, lt, tri_index);
- }
- }
- }
-
- /* build an array of images we use*/
- if (ps->is_shared_user == false) {
- project_paint_build_proj_ima(ps, arena, image_LinkList.list);
- }
-
- /* we have built the array, discard the linked list */
- BLI_linklist_free(image_LinkList.list, NULL);
+ if (project_paint_winclip(ps, &coSS)) {
+ continue;
+ }
+
+#endif //PROJ_DEBUG_WINCLIP
+
+ /* backface culls individual triangles but mask normal will use polygon */
+ if (ps->do_backfacecull) {
+ if (ps->do_mask_normal) {
+ if (prev_poly != lt->poly) {
+ int iloop;
+ bool culled = true;
+ const MPoly *poly = ps->mpoly_eval + lt->poly;
+ int poly_loops = poly->totloop;
+ prev_poly = lt->poly;
+ for (iloop = 0; iloop < poly_loops; iloop++) {
+ if (!(ps->vertFlags[ps->mloop_eval[poly->loopstart + iloop].v] & PROJ_VERT_CULL)) {
+ culled = false;
+ break;
+ }
+ }
+
+ if (culled) {
+ /* poly loops - 2 is number of triangles for poly,
+ * but counter gets incremented when continuing, so decrease by 3 */
+ int poly_tri = poly_loops - 3;
+ tri_index += poly_tri;
+ lt += poly_tri;
+ continue;
+ }
+ }
+ }
+ else {
+ if ((line_point_side_v2(coSS.v1, coSS.v2, coSS.v3) < 0.0f) != ps->is_flip_object) {
+ continue;
+ }
+ }
+ }
+ }
+
+ if (tpage_last != tpage) {
+
+ image_index = BLI_linklist_index(image_LinkList.list, tpage);
+
+ if (image_index == -1 && BKE_image_has_ibuf(tpage, NULL)) {
+ /* MemArena dosnt have an append func */
+ BLI_linklist_append(&image_LinkList, tpage);
+ image_index = ps->image_tot;
+ ps->image_tot++;
+ }
+
+ tpage_last = tpage;
+ }
+
+ if (image_index != -1) {
+ /* Initialize the faces screen pixels */
+ /* Add this to a list to initialize later */
+ project_paint_delayed_face_init(ps, lt, tri_index);
+ }
+ }
+ }
+
+ /* build an array of images we use*/
+ if (ps->is_shared_user == false) {
+ project_paint_build_proj_ima(ps, arena, image_LinkList.list);
+ }
+
+ /* we have built the array, discard the linked list */
+ BLI_linklist_free(image_LinkList.list, NULL);
}
/* run once per stroke before projection painting */
-static void project_paint_begin(
- const bContext *C, ProjPaintState *ps,
- const bool is_multi_view, const char symmetry_flag)
+static void project_paint_begin(const bContext *C,
+ ProjPaintState *ps,
+ const bool is_multi_view,
+ const char symmetry_flag)
{
- ProjPaintLayerClone layer_clone;
- ProjPaintFaceLookup face_lookup;
- const MLoopUV *mloopuv_base = NULL;
+ ProjPaintLayerClone layer_clone;
+ ProjPaintFaceLookup face_lookup;
+ const MLoopUV *mloopuv_base = NULL;
- /* at the moment this is just ps->arena_mt[0], but use this to show were not multithreading */
- MemArena *arena;
+ /* at the moment this is just ps->arena_mt[0], but use this to show were not multithreading */
+ MemArena *arena;
- const int diameter = 2 * BKE_brush_size_get(ps->scene, ps->brush);
+ const int diameter = 2 * BKE_brush_size_get(ps->scene, ps->brush);
- bool reset_threads = false;
+ bool reset_threads = false;
- /* ---- end defines ---- */
+ /* ---- end defines ---- */
- if (ps->source == PROJ_SRC_VIEW) {
- /* faster clipping lookups */
- ED_view3d_clipping_local(ps->rv3d, ps->ob->obmat);
- }
+ if (ps->source == PROJ_SRC_VIEW) {
+ /* faster clipping lookups */
+ ED_view3d_clipping_local(ps->rv3d, ps->ob->obmat);
+ }
- ps->do_face_sel = ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) != 0);
- ps->is_flip_object = (ps->ob->transflag & OB_NEG_SCALE) != 0;
+ ps->do_face_sel = ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) != 0);
+ ps->is_flip_object = (ps->ob->transflag & OB_NEG_SCALE) != 0;
- /* paint onto the derived mesh */
- if (ps->is_shared_user == false) {
- if (!proj_paint_state_mesh_eval_init(C, ps)) {
- return;
- }
- }
+ /* paint onto the derived mesh */
+ if (ps->is_shared_user == false) {
+ if (!proj_paint_state_mesh_eval_init(C, ps)) {
+ return;
+ }
+ }
- proj_paint_face_lookup_init(ps, &face_lookup);
- proj_paint_layer_clone_init(ps, &layer_clone);
+ proj_paint_face_lookup_init(ps, &face_lookup);
+ proj_paint_layer_clone_init(ps, &layer_clone);
- if (ps->do_layer_stencil || ps->do_stencil_brush) {
- //int layer_num = CustomData_get_stencil_layer(&ps->me_eval->ldata, CD_MLOOPUV);
- int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV);
- if (layer_num != -1)
- ps->mloopuv_stencil_eval = CustomData_get_layer_n(&ps->me_eval->ldata, CD_MLOOPUV, layer_num);
+ if (ps->do_layer_stencil || ps->do_stencil_brush) {
+ //int layer_num = CustomData_get_stencil_layer(&ps->me_eval->ldata, CD_MLOOPUV);
+ int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV);
+ if (layer_num != -1)
+ ps->mloopuv_stencil_eval = CustomData_get_layer_n(
+ &ps->me_eval->ldata, CD_MLOOPUV, layer_num);
- if (ps->mloopuv_stencil_eval == NULL) {
- /* get active instead */
- ps->mloopuv_stencil_eval = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
- }
+ if (ps->mloopuv_stencil_eval == NULL) {
+ /* get active instead */
+ ps->mloopuv_stencil_eval = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
+ }
- if (ps->do_stencil_brush)
- mloopuv_base = ps->mloopuv_stencil_eval;
- }
+ if (ps->do_stencil_brush)
+ mloopuv_base = ps->mloopuv_stencil_eval;
+ }
- /* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
- if (ps->is_shared_user == false) {
- proj_paint_state_cavity_init(ps);
- }
+ /* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
+ if (ps->is_shared_user == false) {
+ proj_paint_state_cavity_init(ps);
+ }
- proj_paint_state_viewport_init(ps, symmetry_flag);
+ proj_paint_state_viewport_init(ps, symmetry_flag);
- /* calculate vert screen coords
- * run this early so we can calculate the x/y resolution of our bucket rect */
- proj_paint_state_screen_coords_init(ps, diameter);
+ /* calculate vert screen coords
+ * run this early so we can calculate the x/y resolution of our bucket rect */
+ proj_paint_state_screen_coords_init(ps, diameter);
- /* only for convenience */
- ps->screen_width = ps->screenMax[0] - ps->screenMin[0];
- ps->screen_height = ps->screenMax[1] - ps->screenMin[1];
+ /* only for convenience */
+ ps->screen_width = ps->screenMax[0] - ps->screenMin[0];
+ ps->screen_height = ps->screenMax[1] - ps->screenMin[1];
- ps->buckets_x = (int)(ps->screen_width / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
- ps->buckets_y = (int)(ps->screen_height / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
+ ps->buckets_x = (int)(ps->screen_width / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
+ ps->buckets_y = (int)(ps->screen_height / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
- /* printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y); */
+ /* printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y); */
- if (ps->buckets_x > PROJ_BUCKET_RECT_MAX || ps->buckets_y > PROJ_BUCKET_RECT_MAX) {
- reset_threads = true;
- }
+ if (ps->buckets_x > PROJ_BUCKET_RECT_MAX || ps->buckets_y > PROJ_BUCKET_RECT_MAX) {
+ reset_threads = true;
+ }
- /* really high values could cause problems since it has to allocate a few
- * (ps->buckets_x*ps->buckets_y) sized arrays */
- CLAMP(ps->buckets_x, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
- CLAMP(ps->buckets_y, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
+ /* really high values could cause problems since it has to allocate a few
+ * (ps->buckets_x*ps->buckets_y) sized arrays */
+ CLAMP(ps->buckets_x, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
+ CLAMP(ps->buckets_y, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
- ps->bucketRect = MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketRect");
- ps->bucketFaces = MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces");
+ ps->bucketRect = MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y,
+ "paint-bucketRect");
+ ps->bucketFaces = MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y,
+ "paint-bucketFaces");
- ps->bucketFlags = MEM_callocN(sizeof(char) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces");
+ ps->bucketFlags = MEM_callocN(sizeof(char) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces");
#ifndef PROJ_DEBUG_NOSEAMBLEED
- if (ps->is_shared_user == false) {
- proj_paint_state_seam_bleed_init(ps);
- }
+ if (ps->is_shared_user == false) {
+ proj_paint_state_seam_bleed_init(ps);
+ }
#endif
- proj_paint_state_thread_init(ps, reset_threads);
- arena = ps->arena_mt[0];
+ proj_paint_state_thread_init(ps, reset_threads);
+ arena = ps->arena_mt[0];
- proj_paint_state_vert_flags_init(ps);
+ proj_paint_state_vert_flags_init(ps);
- project_paint_prepare_all_faces(ps, arena, &face_lookup, &layer_clone, mloopuv_base, is_multi_view);
+ project_paint_prepare_all_faces(
+ ps, arena, &face_lookup, &layer_clone, mloopuv_base, is_multi_view);
}
static void paint_proj_begin_clone(ProjPaintState *ps, const float mouse[2])
{
- /* setup clone offset */
- if (ps->tool == PAINT_TOOL_CLONE) {
- float projCo[4];
- copy_v3_v3(projCo, ps->scene->cursor.location);
- mul_m4_v3(ps->obmat_imat, projCo);
-
- projCo[3] = 1.0f;
- mul_m4_v4(ps->projectMat, projCo);
- ps->cloneOffset[0] = mouse[0] - ((float)(ps->winx * 0.5f) + (ps->winx * 0.5f) * projCo[0] / projCo[3]);
- ps->cloneOffset[1] = mouse[1] - ((float)(ps->winy * 0.5f) + (ps->winy * 0.5f) * projCo[1] / projCo[3]);
- }
+ /* setup clone offset */
+ if (ps->tool == PAINT_TOOL_CLONE) {
+ float projCo[4];
+ copy_v3_v3(projCo, ps->scene->cursor.location);
+ mul_m4_v3(ps->obmat_imat, projCo);
+
+ projCo[3] = 1.0f;
+ mul_m4_v4(ps->projectMat, projCo);
+ ps->cloneOffset[0] = mouse[0] -
+ ((float)(ps->winx * 0.5f) + (ps->winx * 0.5f) * projCo[0] / projCo[3]);
+ ps->cloneOffset[1] = mouse[1] -
+ ((float)(ps->winy * 0.5f) + (ps->winy * 0.5f) * projCo[1] / projCo[3]);
+ }
}
static void project_paint_end(ProjPaintState *ps)
{
- int a;
-
- image_undo_remove_masks();
-
- /* dereference used image buffers */
- if (ps->is_shared_user == false) {
- ProjPaintImage *projIma;
- for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) {
- BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL);
- DEG_id_tag_update(&projIma->ima->id, 0);
- }
- }
-
- if (ps->reproject_ibuf_free_float) {
- imb_freerectfloatImBuf(ps->reproject_ibuf);
- }
- if (ps->reproject_ibuf_free_uchar) {
- imb_freerectImBuf(ps->reproject_ibuf);
- }
- BKE_image_release_ibuf(ps->reproject_image, ps->reproject_ibuf, NULL);
-
- MEM_freeN(ps->screenCoords);
- MEM_freeN(ps->bucketRect);
- MEM_freeN(ps->bucketFaces);
- MEM_freeN(ps->bucketFlags);
-
- if (ps->is_shared_user == false) {
- if (ps->mat_array != NULL) {
- MEM_freeN(ps->mat_array);
- }
-
- /* must be set for non-shared */
- BLI_assert(ps->poly_to_loop_uv || ps->is_shared_user);
- if (ps->poly_to_loop_uv)
- MEM_freeN((void *)ps->poly_to_loop_uv);
-
- if (ps->do_layer_clone)
- MEM_freeN((void *)ps->poly_to_loop_uv_clone);
- if (ps->thread_tot > 1) {
- BLI_spin_end(ps->tile_lock);
- MEM_freeN((void *)ps->tile_lock);
- }
-
- image_undo_end_locks();
+ int a;
+
+ image_undo_remove_masks();
+
+ /* dereference used image buffers */
+ if (ps->is_shared_user == false) {
+ ProjPaintImage *projIma;
+ for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) {
+ BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL);
+ DEG_id_tag_update(&projIma->ima->id, 0);
+ }
+ }
+
+ if (ps->reproject_ibuf_free_float) {
+ imb_freerectfloatImBuf(ps->reproject_ibuf);
+ }
+ if (ps->reproject_ibuf_free_uchar) {
+ imb_freerectImBuf(ps->reproject_ibuf);
+ }
+ BKE_image_release_ibuf(ps->reproject_image, ps->reproject_ibuf, NULL);
+
+ MEM_freeN(ps->screenCoords);
+ MEM_freeN(ps->bucketRect);
+ MEM_freeN(ps->bucketFaces);
+ MEM_freeN(ps->bucketFlags);
+
+ if (ps->is_shared_user == false) {
+ if (ps->mat_array != NULL) {
+ MEM_freeN(ps->mat_array);
+ }
+
+ /* must be set for non-shared */
+ BLI_assert(ps->poly_to_loop_uv || ps->is_shared_user);
+ if (ps->poly_to_loop_uv)
+ MEM_freeN((void *)ps->poly_to_loop_uv);
+
+ if (ps->do_layer_clone)
+ MEM_freeN((void *)ps->poly_to_loop_uv_clone);
+ if (ps->thread_tot > 1) {
+ BLI_spin_end(ps->tile_lock);
+ MEM_freeN((void *)ps->tile_lock);
+ }
+
+ image_undo_end_locks();
#ifndef PROJ_DEBUG_NOSEAMBLEED
- if (ps->seam_bleed_px > 0.0f) {
- MEM_freeN(ps->vertFaces);
- MEM_freeN(ps->faceSeamFlags);
- MEM_freeN(ps->faceWindingFlags);
- MEM_freeN(ps->loopSeamData);
- MEM_freeN(ps->vertSeams);
- }
+ if (ps->seam_bleed_px > 0.0f) {
+ MEM_freeN(ps->vertFaces);
+ MEM_freeN(ps->faceSeamFlags);
+ MEM_freeN(ps->faceWindingFlags);
+ MEM_freeN(ps->loopSeamData);
+ MEM_freeN(ps->vertSeams);
+ }
#endif
- if (ps->do_mask_cavity) {
- MEM_freeN(ps->cavities);
- }
+ if (ps->do_mask_cavity) {
+ MEM_freeN(ps->cavities);
+ }
- if (ps->me_eval_free) {
- BKE_id_free(NULL, ps->me_eval);
- }
- ps->me_eval = NULL;
- }
+ if (ps->me_eval_free) {
+ BKE_id_free(NULL, ps->me_eval);
+ }
+ ps->me_eval = NULL;
+ }
- if (ps->blurkernel) {
- paint_delete_blur_kernel(ps->blurkernel);
- MEM_freeN(ps->blurkernel);
- }
+ if (ps->blurkernel) {
+ paint_delete_blur_kernel(ps->blurkernel);
+ MEM_freeN(ps->blurkernel);
+ }
- if (ps->vertFlags) MEM_freeN(ps->vertFlags);
+ if (ps->vertFlags)
+ MEM_freeN(ps->vertFlags);
- for (a = 0; a < ps->thread_tot; a++) {
- BLI_memarena_free(ps->arena_mt[a]);
- }
+ for (a = 0; a < ps->thread_tot; a++) {
+ BLI_memarena_free(ps->arena_mt[a]);
+ }
}
/* 1 = an undo, -1 is a redo. */
static void partial_redraw_single_init(ImagePaintPartialRedraw *pr)
{
- pr->x1 = INT_MAX;
- pr->y1 = INT_MAX;
+ pr->x1 = INT_MAX;
+ pr->y1 = INT_MAX;
- pr->x2 = -1;
- pr->y2 = -1;
+ pr->x2 = -1;
+ pr->y2 = -1;
- pr->enabled = 1;
+ pr->enabled = 1;
}
static void partial_redraw_array_init(ImagePaintPartialRedraw *pr)
{
- int tot = PROJ_BOUNDBOX_SQUARED;
- while (tot--) {
- partial_redraw_single_init(pr);
- pr++;
- }
+ int tot = PROJ_BOUNDBOX_SQUARED;
+ while (tot--) {
+ partial_redraw_single_init(pr);
+ pr++;
+ }
}
-
-static bool partial_redraw_array_merge(ImagePaintPartialRedraw *pr, ImagePaintPartialRedraw *pr_other, int tot)
+static bool partial_redraw_array_merge(ImagePaintPartialRedraw *pr,
+ ImagePaintPartialRedraw *pr_other,
+ int tot)
{
- bool touch = 0;
- while (tot--) {
- pr->x1 = min_ii(pr->x1, pr_other->x1);
- pr->y1 = min_ii(pr->y1, pr_other->y1);
+ bool touch = 0;
+ while (tot--) {
+ pr->x1 = min_ii(pr->x1, pr_other->x1);
+ pr->y1 = min_ii(pr->y1, pr_other->y1);
- pr->x2 = max_ii(pr->x2, pr_other->x2);
- pr->y2 = max_ii(pr->y2, pr_other->y2);
+ pr->x2 = max_ii(pr->x2, pr_other->x2);
+ pr->y2 = max_ii(pr->y2, pr_other->y2);
- if (pr->x2 != -1)
- touch = 1;
+ if (pr->x2 != -1)
+ touch = 1;
- pr++; pr_other++;
- }
+ pr++;
+ pr_other++;
+ }
- return touch;
+ return touch;
}
/* Loop over all images on this mesh and update any we have touched */
static bool project_image_refresh_tagged(ProjPaintState *ps)
{
- ImagePaintPartialRedraw *pr;
- ProjPaintImage *projIma;
- int a, i;
- bool redraw = false;
-
-
- for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) {
- if (projIma->touch) {
- /* look over each bound cell */
- for (i = 0; i < PROJ_BOUNDBOX_SQUARED; i++) {
- pr = &(projIma->partRedrawRect[i]);
- if (pr->x2 != -1) { /* TODO - use 'enabled' ? */
- set_imapaintpartial(pr);
- imapaint_image_update(NULL, projIma->ima, projIma->ibuf, true);
- redraw = 1;
- }
-
- partial_redraw_single_init(pr);
- }
-
- /* clear for reuse */
- projIma->touch = 0;
- }
- }
-
- return redraw;
+ ImagePaintPartialRedraw *pr;
+ ProjPaintImage *projIma;
+ int a, i;
+ bool redraw = false;
+
+ for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) {
+ if (projIma->touch) {
+ /* look over each bound cell */
+ for (i = 0; i < PROJ_BOUNDBOX_SQUARED; i++) {
+ pr = &(projIma->partRedrawRect[i]);
+ if (pr->x2 != -1) { /* TODO - use 'enabled' ? */
+ set_imapaintpartial(pr);
+ imapaint_image_update(NULL, projIma->ima, projIma->ibuf, true);
+ redraw = 1;
+ }
+
+ partial_redraw_single_init(pr);
+ }
+
+ /* clear for reuse */
+ projIma->touch = 0;
+ }
+ }
+
+ return redraw;
}
/* run this per painting onto each mouse location */
static bool project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2])
{
- if (ps->source == PROJ_SRC_VIEW) {
- float min_brush[2], max_brush[2];
- const float radius = ps->brush_size;
+ if (ps->source == PROJ_SRC_VIEW) {
+ float min_brush[2], max_brush[2];
+ const float radius = ps->brush_size;
- /* so we don't have a bucket bounds that is way too small to paint into */
- // if (radius < 1.0f) radius = 1.0f; // this doesn't work yet :/
+ /* so we don't have a bucket bounds that is way too small to paint into */
+ // if (radius < 1.0f) radius = 1.0f; // this doesn't work yet :/
- min_brush[0] = mval_f[0] - radius;
- min_brush[1] = mval_f[1] - radius;
+ min_brush[0] = mval_f[0] - radius;
+ min_brush[1] = mval_f[1] - radius;
- max_brush[0] = mval_f[0] + radius;
- max_brush[1] = mval_f[1] + radius;
+ max_brush[0] = mval_f[0] + radius;
+ max_brush[1] = mval_f[1] + radius;
- /* offset to make this a valid bucket index */
- project_paint_bucket_bounds(ps, min_brush, max_brush, ps->bucketMin, ps->bucketMax);
+ /* offset to make this a valid bucket index */
+ project_paint_bucket_bounds(ps, min_brush, max_brush, ps->bucketMin, ps->bucketMax);
- /* mouse outside the model areas? */
- if (ps->bucketMin[0] == ps->bucketMax[0] || ps->bucketMin[1] == ps->bucketMax[1]) {
- return 0;
- }
+ /* mouse outside the model areas? */
+ if (ps->bucketMin[0] == ps->bucketMax[0] || ps->bucketMin[1] == ps->bucketMax[1]) {
+ return 0;
+ }
- ps->context_bucket_x = ps->bucketMin[0];
- ps->context_bucket_y = ps->bucketMin[1];
- }
- else { /* reproject: PROJ_SRC_* */
- ps->bucketMin[0] = 0;
- ps->bucketMin[1] = 0;
+ ps->context_bucket_x = ps->bucketMin[0];
+ ps->context_bucket_y = ps->bucketMin[1];
+ }
+ else { /* reproject: PROJ_SRC_* */
+ ps->bucketMin[0] = 0;
+ ps->bucketMin[1] = 0;
- ps->bucketMax[0] = ps->buckets_x;
- ps->bucketMax[1] = ps->buckets_y;
+ ps->bucketMax[0] = ps->buckets_x;
+ ps->bucketMax[1] = ps->buckets_y;
- ps->context_bucket_x = 0;
- ps->context_bucket_y = 0;
- }
- return 1;
+ ps->context_bucket_x = 0;
+ ps->context_bucket_y = 0;
+ }
+ return 1;
}
-
-static bool project_bucket_iter_next(
- ProjPaintState *ps, int *bucket_index,
- rctf *bucket_bounds, const float mval[2])
+static bool project_bucket_iter_next(ProjPaintState *ps,
+ int *bucket_index,
+ rctf *bucket_bounds,
+ const float mval[2])
{
- const int diameter = 2 * ps->brush_size;
+ const int diameter = 2 * ps->brush_size;
- if (ps->thread_tot > 1)
- BLI_thread_lock(LOCK_CUSTOM1);
+ if (ps->thread_tot > 1)
+ BLI_thread_lock(LOCK_CUSTOM1);
- //printf("%d %d\n", ps->context_bucket_x, ps->context_bucket_y);
+ //printf("%d %d\n", ps->context_bucket_x, ps->context_bucket_y);
- for (; ps->context_bucket_y < ps->bucketMax[1]; ps->context_bucket_y++) {
- for (; ps->context_bucket_x < ps->bucketMax[0]; ps->context_bucket_x++) {
+ for (; ps->context_bucket_y < ps->bucketMax[1]; ps->context_bucket_y++) {
+ for (; ps->context_bucket_x < ps->bucketMax[0]; ps->context_bucket_x++) {
- /* use bucket_bounds for project_bucket_isect_circle and project_bucket_init*/
- project_bucket_bounds(ps, ps->context_bucket_x, ps->context_bucket_y, bucket_bounds);
+ /* use bucket_bounds for project_bucket_isect_circle and project_bucket_init*/
+ project_bucket_bounds(ps, ps->context_bucket_x, ps->context_bucket_y, bucket_bounds);
- if ((ps->source != PROJ_SRC_VIEW) ||
- project_bucket_isect_circle(mval, (float)(diameter * diameter), bucket_bounds))
- {
- *bucket_index = ps->context_bucket_x + (ps->context_bucket_y * ps->buckets_x);
- ps->context_bucket_x++;
+ if ((ps->source != PROJ_SRC_VIEW) ||
+ project_bucket_isect_circle(mval, (float)(diameter * diameter), bucket_bounds)) {
+ *bucket_index = ps->context_bucket_x + (ps->context_bucket_y * ps->buckets_x);
+ ps->context_bucket_x++;
- if (ps->thread_tot > 1)
- BLI_thread_unlock(LOCK_CUSTOM1);
+ if (ps->thread_tot > 1)
+ BLI_thread_unlock(LOCK_CUSTOM1);
- return 1;
- }
- }
- ps->context_bucket_x = ps->bucketMin[0];
- }
+ return 1;
+ }
+ }
+ ps->context_bucket_x = ps->bucketMin[0];
+ }
- if (ps->thread_tot > 1)
- BLI_thread_unlock(LOCK_CUSTOM1);
- return 0;
+ if (ps->thread_tot > 1)
+ BLI_thread_unlock(LOCK_CUSTOM1);
+ return 0;
}
/* Each thread gets one of these, also used as an argument to pass to project_paint_op */
typedef struct ProjectHandle {
- /* args */
- ProjPaintState *ps;
- float prevmval[2];
- float mval[2];
+ /* args */
+ ProjPaintState *ps;
+ float prevmval[2];
+ float mval[2];
- /* Annoying but we need to have image bounds per thread,
- * then merge into ps->projectPartialRedraws. */
+ /* Annoying but we need to have image bounds per thread,
+ * then merge into ps->projectPartialRedraws. */
- /* array of partial redraws */
- ProjPaintImage *projImages;
+ /* array of partial redraws */
+ ProjPaintImage *projImages;
- /* thread settings */
- int thread_index;
+ /* thread settings */
+ int thread_index;
- struct ImagePool *pool;
+ struct ImagePool *pool;
} ProjectHandle;
static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, float mask)
{
- const unsigned char *clone_pt = ((ProjPixelClone *)projPixel)->clonepx.ch;
-
- if (clone_pt[3]) {
- unsigned char 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);
-
- if (ps->do_masking) {
- IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt, clone_rgba, ps->blend);
- }
- else {
- IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->pixel.ch_pt, clone_rgba, ps->blend);
- }
- }
+ const unsigned char *clone_pt = ((ProjPixelClone *)projPixel)->clonepx.ch;
+
+ if (clone_pt[3]) {
+ unsigned char 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);
+
+ if (ps->do_masking) {
+ IMB_blend_color_byte(
+ projPixel->pixel.ch_pt, projPixel->origColor.ch_pt, clone_rgba, ps->blend);
+ }
+ else {
+ IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->pixel.ch_pt, clone_rgba, ps->blend);
+ }
+ }
}
static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, float mask)
{
- const float *clone_pt = ((ProjPixelClone *)projPixel)->clonepx.f;
+ const float *clone_pt = ((ProjPixelClone *)projPixel)->clonepx.f;
- if (clone_pt[3]) {
- float clone_rgba[4];
+ if (clone_pt[3]) {
+ float clone_rgba[4];
- mul_v4_v4fl(clone_rgba, clone_pt, mask);
+ mul_v4_v4fl(clone_rgba, clone_pt, mask);
- if (ps->do_masking) {
- IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt, clone_rgba, ps->blend);
- }
- else {
- IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, clone_rgba, ps->blend);
- }
- }
+ if (ps->do_masking) {
+ IMB_blend_color_float(
+ projPixel->pixel.f_pt, projPixel->origColor.f_pt, clone_rgba, ps->blend);
+ }
+ else {
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, clone_rgba, ps->blend);
+ }
+ }
}
/**
@@ -4609,1342 +4760,1396 @@ static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, fl
* accumulation of color greater than 'projPixel->mask' however in the case of smear its not
* really that important to be correct as it is with clone and painting
*/
-static void do_projectpaint_smear(
- ProjPaintState *ps, ProjPixel *projPixel, float mask,
- MemArena *smearArena, LinkNode **smearPixels, const float co[2])
+static void do_projectpaint_smear(ProjPaintState *ps,
+ ProjPixel *projPixel,
+ float mask,
+ MemArena *smearArena,
+ LinkNode **smearPixels,
+ const float co[2])
{
- unsigned char rgba_ub[4];
+ unsigned char rgba_ub[4];
- if (project_paint_PickColor(ps, co, NULL, rgba_ub, 1) == 0)
- return;
+ if (project_paint_PickColor(ps, co, NULL, rgba_ub, 1) == 0)
+ return;
- blend_color_interpolate_byte(((ProjPixelClone *)projPixel)->clonepx.ch, projPixel->pixel.ch_pt, rgba_ub, mask);
- BLI_linklist_prepend_arena(smearPixels, (void *)projPixel, smearArena);
+ blend_color_interpolate_byte(
+ ((ProjPixelClone *)projPixel)->clonepx.ch, projPixel->pixel.ch_pt, rgba_ub, mask);
+ BLI_linklist_prepend_arena(smearPixels, (void *)projPixel, smearArena);
}
-static void do_projectpaint_smear_f(
- ProjPaintState *ps, ProjPixel *projPixel, float mask,
- MemArena *smearArena, LinkNode **smearPixels_f, const float co[2])
+static void do_projectpaint_smear_f(ProjPaintState *ps,
+ ProjPixel *projPixel,
+ float mask,
+ MemArena *smearArena,
+ LinkNode **smearPixels_f,
+ const float co[2])
{
- float rgba[4];
+ float rgba[4];
- if (project_paint_PickColor(ps, co, rgba, NULL, 1) == 0)
- return;
+ if (project_paint_PickColor(ps, co, rgba, NULL, 1) == 0)
+ return;
- blend_color_interpolate_float(((ProjPixelClone *)projPixel)->clonepx.f, projPixel->pixel.f_pt, rgba, mask);
- BLI_linklist_prepend_arena(smearPixels_f, (void *)projPixel, smearArena);
+ blend_color_interpolate_float(
+ ((ProjPixelClone *)projPixel)->clonepx.f, projPixel->pixel.f_pt, rgba, mask);
+ BLI_linklist_prepend_arena(smearPixels_f, (void *)projPixel, smearArena);
}
-static void do_projectpaint_soften_f(
- ProjPaintState *ps, ProjPixel *projPixel, float mask,
- MemArena *softenArena, LinkNode **softenPixels)
+static void do_projectpaint_soften_f(ProjPaintState *ps,
+ ProjPixel *projPixel,
+ float mask,
+ MemArena *softenArena,
+ LinkNode **softenPixels)
{
- float accum_tot = 0.0f;
- int xk, yk;
- BlurKernel *kernel = ps->blurkernel;
- float *rgba = projPixel->newColor.f;
-
- /* rather then painting, accumulate surrounding colors */
- zero_v4(rgba);
-
- for (yk = 0; yk < kernel->side; yk++) {
- for (xk = 0; xk < kernel->side; xk++) {
- float rgba_tmp[4];
- float co_ofs[2] = {2.0f * xk - 1.0f, 2.0f * yk - 1.0f};
-
- add_v2_v2(co_ofs, projPixel->projCoSS);
-
- if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, true)) {
- float weight = kernel->wdata[xk + yk * kernel->side];
- mul_v4_fl(rgba_tmp, weight);
- add_v4_v4(rgba, rgba_tmp);
- accum_tot += weight;
- }
- }
- }
-
- if (LIKELY(accum_tot != 0)) {
- mul_v4_fl(rgba, 1.0f / (float)accum_tot);
-
- if (ps->mode == BRUSH_STROKE_INVERT) {
- /* subtract blurred image from normal image gives high pass filter */
- sub_v3_v3v3(rgba, projPixel->pixel.f_pt, rgba);
-
- /* now rgba_ub contains the edge result, but this should be converted to luminance to avoid
- * colored speckles appearing in final image, and also to check for threshold */
- rgba[0] = rgba[1] = rgba[2] = IMB_colormanagement_get_luminance(rgba);
- if (fabsf(rgba[0]) > ps->brush->sharp_threshold) {
- float alpha = projPixel->pixel.f_pt[3];
- projPixel->pixel.f_pt[3] = rgba[3] = mask;
-
- /* add to enhance edges */
- blend_color_add_float(rgba, projPixel->pixel.f_pt, rgba);
- rgba[3] = alpha;
- }
- else
- return;
- }
- else {
- blend_color_interpolate_float(rgba, projPixel->pixel.f_pt, rgba, mask);
- }
-
- BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena);
- }
+ float accum_tot = 0.0f;
+ int xk, yk;
+ BlurKernel *kernel = ps->blurkernel;
+ float *rgba = projPixel->newColor.f;
+
+ /* rather then painting, accumulate surrounding colors */
+ zero_v4(rgba);
+
+ for (yk = 0; yk < kernel->side; yk++) {
+ for (xk = 0; xk < kernel->side; xk++) {
+ float rgba_tmp[4];
+ float co_ofs[2] = {2.0f * xk - 1.0f, 2.0f * yk - 1.0f};
+
+ add_v2_v2(co_ofs, projPixel->projCoSS);
+
+ if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, true)) {
+ float weight = kernel->wdata[xk + yk * kernel->side];
+ mul_v4_fl(rgba_tmp, weight);
+ add_v4_v4(rgba, rgba_tmp);
+ accum_tot += weight;
+ }
+ }
+ }
+
+ if (LIKELY(accum_tot != 0)) {
+ mul_v4_fl(rgba, 1.0f / (float)accum_tot);
+
+ if (ps->mode == BRUSH_STROKE_INVERT) {
+ /* subtract blurred image from normal image gives high pass filter */
+ sub_v3_v3v3(rgba, projPixel->pixel.f_pt, rgba);
+
+ /* now rgba_ub contains the edge result, but this should be converted to luminance to avoid
+ * colored speckles appearing in final image, and also to check for threshold */
+ rgba[0] = rgba[1] = rgba[2] = IMB_colormanagement_get_luminance(rgba);
+ if (fabsf(rgba[0]) > ps->brush->sharp_threshold) {
+ float alpha = projPixel->pixel.f_pt[3];
+ projPixel->pixel.f_pt[3] = rgba[3] = mask;
+
+ /* add to enhance edges */
+ blend_color_add_float(rgba, projPixel->pixel.f_pt, rgba);
+ rgba[3] = alpha;
+ }
+ else
+ return;
+ }
+ else {
+ blend_color_interpolate_float(rgba, projPixel->pixel.f_pt, rgba, mask);
+ }
+
+ BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena);
+ }
}
-static void do_projectpaint_soften(
- ProjPaintState *ps, ProjPixel *projPixel, float mask,
- MemArena *softenArena, LinkNode **softenPixels)
+static void do_projectpaint_soften(ProjPaintState *ps,
+ ProjPixel *projPixel,
+ float mask,
+ MemArena *softenArena,
+ LinkNode **softenPixels)
{
- float accum_tot = 0;
- int xk, yk;
- BlurKernel *kernel = ps->blurkernel;
- /* convert to byte after */
- float rgba[4];
-
- /* rather then painting, accumulate surrounding colors */
- zero_v4(rgba);
-
- for (yk = 0; yk < kernel->side; yk++) {
- for (xk = 0; xk < kernel->side; xk++) {
- float rgba_tmp[4];
- float co_ofs[2] = {2.0f * xk - 1.0f, 2.0f * yk - 1.0f};
-
- add_v2_v2(co_ofs, projPixel->projCoSS);
-
- if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, true)) {
- float weight = kernel->wdata[xk + yk * kernel->side];
- mul_v4_fl(rgba_tmp, weight);
- add_v4_v4(rgba, rgba_tmp);
- accum_tot += weight;
- }
- }
- }
-
- if (LIKELY(accum_tot != 0)) {
- unsigned char *rgba_ub = projPixel->newColor.ch;
-
- mul_v4_fl(rgba, 1.0f / (float)accum_tot);
-
- if (ps->mode == BRUSH_STROKE_INVERT) {
- float rgba_pixel[4];
-
- straight_uchar_to_premul_float(rgba_pixel, projPixel->pixel.ch_pt);
-
- /* subtract blurred image from normal image gives high pass filter */
- sub_v3_v3v3(rgba, rgba_pixel, rgba);
- /* now rgba_ub contains the edge result, but this should be converted to luminance to avoid
- * colored speckles appearing in final image, and also to check for threshold */
- rgba[0] = rgba[1] = rgba[2] = IMB_colormanagement_get_luminance(rgba);
- if (fabsf(rgba[0]) > ps->brush->sharp_threshold) {
- float alpha = rgba_pixel[3];
- rgba[3] = rgba_pixel[3] = mask;
-
- /* add to enhance edges */
- blend_color_add_float(rgba, rgba_pixel, rgba);
-
- rgba[3] = alpha;
- premul_float_to_straight_uchar(rgba_ub, rgba);
- }
- else
- return;
- }
- else {
- premul_float_to_straight_uchar(rgba_ub, rgba);
- blend_color_interpolate_byte(rgba_ub, projPixel->pixel.ch_pt, rgba_ub, mask);
- }
- BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena);
- }
+ float accum_tot = 0;
+ int xk, yk;
+ BlurKernel *kernel = ps->blurkernel;
+ /* convert to byte after */
+ float rgba[4];
+
+ /* rather then painting, accumulate surrounding colors */
+ zero_v4(rgba);
+
+ for (yk = 0; yk < kernel->side; yk++) {
+ for (xk = 0; xk < kernel->side; xk++) {
+ float rgba_tmp[4];
+ float co_ofs[2] = {2.0f * xk - 1.0f, 2.0f * yk - 1.0f};
+
+ add_v2_v2(co_ofs, projPixel->projCoSS);
+
+ if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, true)) {
+ float weight = kernel->wdata[xk + yk * kernel->side];
+ mul_v4_fl(rgba_tmp, weight);
+ add_v4_v4(rgba, rgba_tmp);
+ accum_tot += weight;
+ }
+ }
+ }
+
+ if (LIKELY(accum_tot != 0)) {
+ unsigned char *rgba_ub = projPixel->newColor.ch;
+
+ mul_v4_fl(rgba, 1.0f / (float)accum_tot);
+
+ if (ps->mode == BRUSH_STROKE_INVERT) {
+ float rgba_pixel[4];
+
+ straight_uchar_to_premul_float(rgba_pixel, projPixel->pixel.ch_pt);
+
+ /* subtract blurred image from normal image gives high pass filter */
+ sub_v3_v3v3(rgba, rgba_pixel, rgba);
+ /* now rgba_ub contains the edge result, but this should be converted to luminance to avoid
+ * colored speckles appearing in final image, and also to check for threshold */
+ rgba[0] = rgba[1] = rgba[2] = IMB_colormanagement_get_luminance(rgba);
+ if (fabsf(rgba[0]) > ps->brush->sharp_threshold) {
+ float alpha = rgba_pixel[3];
+ rgba[3] = rgba_pixel[3] = mask;
+
+ /* add to enhance edges */
+ blend_color_add_float(rgba, rgba_pixel, rgba);
+
+ rgba[3] = alpha;
+ premul_float_to_straight_uchar(rgba_ub, rgba);
+ }
+ else
+ return;
+ }
+ else {
+ premul_float_to_straight_uchar(rgba_ub, rgba);
+ blend_color_interpolate_byte(rgba_ub, projPixel->pixel.ch_pt, rgba_ub, mask);
+ }
+ BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena);
+ }
}
-static void do_projectpaint_draw(
- ProjPaintState *ps, ProjPixel *projPixel, const float texrgb[3], float mask,
- float dither, float u, float v)
+static void do_projectpaint_draw(ProjPaintState *ps,
+ ProjPixel *projPixel,
+ const float texrgb[3],
+ float mask,
+ float dither,
+ float u,
+ float v)
{
- float rgb[3];
- unsigned char rgba_ub[4];
-
- if (ps->is_texbrush) {
- mul_v3_v3v3(rgb, texrgb, ps->paint_color_linear);
- /* TODO(sergey): Support texture paint color space. */
- if (ps->use_colormanagement) {
- linearrgb_to_srgb_v3_v3(rgb, rgb);
- }
- else {
- copy_v3_v3(rgb, rgb);
- }
- }
- else {
- copy_v3_v3(rgb, ps->paint_color);
- }
-
- if (dither > 0.0f) {
- float_to_byte_dither_v3(rgba_ub, rgb, dither, u, v);
- }
- else {
- unit_float_to_uchar_clamp_v3(rgba_ub, rgb);
- }
- rgba_ub[3] = f_to_char(mask);
-
- if (ps->do_masking) {
- IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt, rgba_ub, ps->blend);
- }
- else {
- IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->pixel.ch_pt, rgba_ub, ps->blend);
- }
+ float rgb[3];
+ unsigned char rgba_ub[4];
+
+ if (ps->is_texbrush) {
+ mul_v3_v3v3(rgb, texrgb, ps->paint_color_linear);
+ /* TODO(sergey): Support texture paint color space. */
+ if (ps->use_colormanagement) {
+ linearrgb_to_srgb_v3_v3(rgb, rgb);
+ }
+ else {
+ copy_v3_v3(rgb, rgb);
+ }
+ }
+ else {
+ copy_v3_v3(rgb, ps->paint_color);
+ }
+
+ if (dither > 0.0f) {
+ float_to_byte_dither_v3(rgba_ub, rgb, dither, u, v);
+ }
+ else {
+ unit_float_to_uchar_clamp_v3(rgba_ub, rgb);
+ }
+ rgba_ub[3] = f_to_char(mask);
+
+ if (ps->do_masking) {
+ IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt, rgba_ub, ps->blend);
+ }
+ else {
+ IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->pixel.ch_pt, rgba_ub, ps->blend);
+ }
}
-static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, const float texrgb[3], float mask)
+static void do_projectpaint_draw_f(ProjPaintState *ps,
+ ProjPixel *projPixel,
+ const float texrgb[3],
+ float mask)
{
- float rgba[4];
+ float rgba[4];
- copy_v3_v3(rgba, ps->paint_color_linear);
+ copy_v3_v3(rgba, ps->paint_color_linear);
- if (ps->is_texbrush)
- mul_v3_v3(rgba, texrgb);
+ if (ps->is_texbrush)
+ mul_v3_v3(rgba, texrgb);
- mul_v3_fl(rgba, mask);
- rgba[3] = mask;
+ mul_v3_fl(rgba, mask);
+ rgba[3] = mask;
- if (ps->do_masking) {
- IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt, rgba, ps->blend);
- }
- else {
- IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, rgba, ps->blend);
- }
+ if (ps->do_masking) {
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt, rgba, ps->blend);
+ }
+ else {
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, rgba, ps->blend);
+ }
}
static void do_projectpaint_mask(ProjPaintState *ps, ProjPixel *projPixel, float mask)
{
- unsigned char rgba_ub[4];
- rgba_ub[0] = rgba_ub[1] = rgba_ub[2] = ps->stencil_value * 255.0f;
- rgba_ub[3] = f_to_char(mask);
-
- if (ps->do_masking) {
- IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt, rgba_ub, ps->blend);
- }
- else {
- IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->pixel.ch_pt, rgba_ub, ps->blend);
- }
+ unsigned char rgba_ub[4];
+ rgba_ub[0] = rgba_ub[1] = rgba_ub[2] = ps->stencil_value * 255.0f;
+ rgba_ub[3] = f_to_char(mask);
+
+ if (ps->do_masking) {
+ IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt, rgba_ub, ps->blend);
+ }
+ else {
+ IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->pixel.ch_pt, rgba_ub, ps->blend);
+ }
}
static void do_projectpaint_mask_f(ProjPaintState *ps, ProjPixel *projPixel, float mask)
{
- float rgba[4];
- rgba[0] = rgba[1] = rgba[2] = ps->stencil_value;
- rgba[3] = mask;
-
- if (ps->do_masking) {
- IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt, rgba, ps->blend);
- }
- else {
- IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, rgba, ps->blend);
- }
+ float rgba[4];
+ rgba[0] = rgba[1] = rgba[2] = ps->stencil_value;
+ rgba[3] = mask;
+
+ if (ps->do_masking) {
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt, rgba, ps->blend);
+ }
+ else {
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, rgba, ps->blend);
+ }
}
-static void image_paint_partial_redraw_expand(
- ImagePaintPartialRedraw *cell,
- const ProjPixel *projPixel)
+static void image_paint_partial_redraw_expand(ImagePaintPartialRedraw *cell,
+ const ProjPixel *projPixel)
{
- cell->x1 = min_ii(cell->x1, (int)projPixel->x_px);
- cell->y1 = min_ii(cell->y1, (int)projPixel->y_px);
+ cell->x1 = min_ii(cell->x1, (int)projPixel->x_px);
+ cell->y1 = min_ii(cell->y1, (int)projPixel->y_px);
- cell->x2 = max_ii(cell->x2, (int)projPixel->x_px + 1);
- cell->y2 = max_ii(cell->y2, (int)projPixel->y_px + 1);
+ cell->x2 = max_ii(cell->x2, (int)projPixel->x_px + 1);
+ cell->y2 = max_ii(cell->y2, (int)projPixel->y_px + 1);
}
/* run this for single and multithreaded painting */
static void *do_projectpaint_thread(void *ph_v)
{
- /* First unpack args from the struct */
- ProjPaintState *ps = ((ProjectHandle *)ph_v)->ps;
- ProjPaintImage *projImages = ((ProjectHandle *)ph_v)->projImages;
- const float *lastpos = ((ProjectHandle *)ph_v)->prevmval;
- const float *pos = ((ProjectHandle *)ph_v)->mval;
- const int thread_index = ((ProjectHandle *)ph_v)->thread_index;
- struct ImagePool *pool = ((ProjectHandle *)ph_v)->pool;
- /* Done with args from ProjectHandle */
-
- LinkNode *node;
- ProjPixel *projPixel;
- Brush *brush = ps->brush;
-
- int last_index = -1;
- ProjPaintImage *last_projIma = NULL;
- ImagePaintPartialRedraw *last_partial_redraw_cell;
-
- float dist_sq, dist;
-
- float falloff;
- int bucket_index;
- bool is_floatbuf = false;
- const short tool = ps->tool;
- rctf bucket_bounds;
-
- /* for smear only */
- float pos_ofs[2] = {0};
- float co[2];
- unsigned short 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 */
- const float brush_radius_sq = brush_radius * brush_radius;
-
- const bool lock_alpha = ELEM(brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ?
- 0 : (brush->flag & BRUSH_LOCK_ALPHA) != 0;
-
- LinkNode *smearPixels = NULL;
- LinkNode *smearPixels_f = NULL;
- /* mem arena for this brush projection only */
- MemArena *smearArena = NULL;
-
- LinkNode *softenPixels = NULL;
- LinkNode *softenPixels_f = NULL;
- /* mem arena for this brush projection only */
- MemArena *softenArena = NULL;
-
- if (tool == PAINT_TOOL_SMEAR) {
- pos_ofs[0] = pos[0] - lastpos[0];
- pos_ofs[1] = pos[1] - lastpos[1];
-
- smearArena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "paint smear arena");
- }
- else if (tool == PAINT_TOOL_SOFTEN) {
- softenArena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "paint soften arena");
- }
-
- /* printf("brush bounds %d %d %d %d\n",
- * bucketMin[0], bucketMin[1], bucketMax[0], bucketMax[1]); */
-
- while (project_bucket_iter_next(ps, &bucket_index, &bucket_bounds, pos)) {
-
- /* Check this bucket and its faces are initialized */
- if (ps->bucketFlags[bucket_index] == PROJ_BUCKET_NULL) {
- rctf clip_rect = bucket_bounds;
- clip_rect.xmin -= PROJ_PIXEL_TOLERANCE;
- clip_rect.xmax += PROJ_PIXEL_TOLERANCE;
- clip_rect.ymin -= PROJ_PIXEL_TOLERANCE;
- clip_rect.ymax += PROJ_PIXEL_TOLERANCE;
- /* No pixels initialized */
- project_bucket_init(ps, thread_index, bucket_index, &clip_rect, &bucket_bounds);
- }
-
- if (ps->source != PROJ_SRC_VIEW) {
-
- /* Re-Projection, simple, no brushes! */
-
- for (node = ps->bucketRect[bucket_index]; node; node = node->next) {
- projPixel = (ProjPixel *)node->link;
-
- /* copy of code below */
- if (last_index != projPixel->image_index) {
- last_index = projPixel->image_index;
- last_projIma = projImages + last_index;
-
- last_projIma->touch = 1;
- is_floatbuf = (last_projIma->ibuf->rect_float != NULL);
- }
- /* end copy */
-
- /* fill tools */
- if (ps->source == PROJ_SRC_VIEW_FILL) {
- if (brush->flag & BRUSH_USE_GRADIENT) {
- /* these could probably be cached instead of being done per pixel */
- float tangent[2];
- float line_len_sq_inv, line_len;
- float f;
- float color_f[4];
- float p[2] = {projPixel->projCoSS[0] - lastpos[0], projPixel->projCoSS[1] - lastpos[1]};
-
- sub_v2_v2v2(tangent, pos, lastpos);
- line_len = len_squared_v2(tangent);
- line_len_sq_inv = 1.0f / line_len;
- line_len = sqrtf(line_len);
-
- switch (brush->gradient_fill_mode) {
- case BRUSH_GRADIENT_LINEAR:
- {
- f = dot_v2v2(p, tangent) * line_len_sq_inv;
- break;
- }
- case BRUSH_GRADIENT_RADIAL:
- default:
- {
- f = len_v2(p) / line_len;
- break;
- }
- }
- BKE_colorband_evaluate(brush->gradient, f, color_f);
- color_f[3] *= ((float)projPixel->mask) * (1.0f / 65535.0f) * brush->alpha;
-
- if (is_floatbuf) {
- /* convert to premultipied */
- mul_v3_fl(color_f, color_f[3]);
- IMB_blend_color_float(
- projPixel->pixel.f_pt, projPixel->origColor.f_pt,
- color_f, ps->blend);
- }
- else {
- linearrgb_to_srgb_v3_v3(color_f, color_f);
-
- if (ps->dither > 0.0f) {
- float_to_byte_dither_v3(projPixel->newColor.ch, color_f, ps->dither, projPixel->x_px, projPixel->y_px);
- }
- else {
- unit_float_to_uchar_clamp_v3(projPixel->newColor.ch, color_f);
- }
- projPixel->newColor.ch[3] = unit_float_to_uchar_clamp(color_f[3]);
- IMB_blend_color_byte(
- projPixel->pixel.ch_pt, projPixel->origColor.ch_pt,
- projPixel->newColor.ch, ps->blend);
- }
- }
- else {
- if (is_floatbuf) {
- float newColor_f[4];
- 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(
- projPixel->pixel.f_pt, projPixel->origColor.f_pt,
- newColor_f, ps->blend);
- }
- else {
- float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
- 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, projPixel->origColor.ch_pt,
- projPixel->newColor.ch, ps->blend);
- }
- }
-
- if (lock_alpha) {
- if (is_floatbuf) {
- /* slightly more involved case since floats are in premultiplied space we need
- * to make sure alpha is consistent, see T44627 */
- float rgb_straight[4];
- premul_to_straight_v4_v4(rgb_straight, projPixel->pixel.f_pt);
- rgb_straight[3] = projPixel->origColor.f_pt[3];
- straight_to_premul_v4_v4(projPixel->pixel.f_pt, rgb_straight);
- }
- else {
- projPixel->pixel.ch_pt[3] = projPixel->origColor.ch_pt[3];
- }
- }
-
- last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index;
- image_paint_partial_redraw_expand(last_partial_redraw_cell, projPixel);
- }
- else {
- if (is_floatbuf) {
- if (UNLIKELY(ps->reproject_ibuf->rect_float == NULL)) {
- IMB_float_from_rect(ps->reproject_ibuf);
- ps->reproject_ibuf_free_float = true;
- }
-
- bicubic_interpolation_color(
- ps->reproject_ibuf, NULL, projPixel->newColor.f,
- projPixel->projCoSS[0], projPixel->projCoSS[1]);
- if (projPixel->newColor.f[3]) {
- float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
-
- mul_v4_v4fl(projPixel->newColor.f, projPixel->newColor.f, mask);
-
- blend_color_mix_float(
- projPixel->pixel.f_pt, projPixel->origColor.f_pt,
- projPixel->newColor.f);
- }
- }
- else {
- if (UNLIKELY(ps->reproject_ibuf->rect == NULL)) {
- IMB_rect_from_float(ps->reproject_ibuf);
- ps->reproject_ibuf_free_uchar = true;
- }
-
- bicubic_interpolation_color(
- ps->reproject_ibuf, projPixel->newColor.ch, NULL,
- projPixel->projCoSS[0], projPixel->projCoSS[1]);
- if (projPixel->newColor.ch[3]) {
- float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
- projPixel->newColor.ch[3] *= mask;
-
- blend_color_mix_byte(
- projPixel->pixel.ch_pt, projPixel->origColor.ch_pt,
- projPixel->newColor.ch);
- }
- }
- }
- }
- }
- else {
- /* Normal brush painting */
-
- for (node = ps->bucketRect[bucket_index]; node; node = node->next) {
-
- projPixel = (ProjPixel *)node->link;
-
- dist_sq = len_squared_v2v2(projPixel->projCoSS, pos);
-
- /*if (dist < radius) {*/ /* correct but uses a sqrtf */
- if (dist_sq <= brush_radius_sq) {
- dist = sqrtf(dist_sq);
-
- falloff = BKE_brush_curve_strength_clamped(ps->brush, dist, brush_radius);
-
- if (falloff > 0.0f) {
- float texrgb[3];
- float mask;
-
- /* Extra mask for normal, layer stencil, .. */
- float custom_mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
-
- /* Mask texture. */
- if (ps->is_maskbrush) {
- float texmask = BKE_brush_sample_masktex(ps->scene, ps->brush, projPixel->projCoSS, thread_index, pool);
- CLAMP(texmask, 0.0f, 1.0f);
- custom_mask *= texmask;
- }
-
- /* Color texture (alpha used as mask). */
- if (ps->is_texbrush) {
- MTex *mtex = &brush->mtex;
- float samplecos[3];
- float texrgba[4];
-
- /* taking 3d copy to account for 3D mapping too.
- * It gets concatenated during sampling */
- if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
- copy_v3_v3(samplecos, projPixel->worldCoSS);
- }
- else {
- copy_v2_v2(samplecos, projPixel->projCoSS);
- samplecos[2] = 0.0f;
- }
-
- /* note, for clone and smear,
- * we only use the alpha, could be a special function */
- BKE_brush_sample_tex_3d(ps->scene, brush, samplecos, texrgba, thread_index, pool);
-
- copy_v3_v3(texrgb, texrgba);
- custom_mask *= texrgba[3];
- }
- else {
- zero_v3(texrgb);
- }
-
- if (ps->do_masking) {
- /* masking to keep brush contribution to a pixel limited. note we do not do
- * a simple max(mask, mask_accum), as this is very sensitive to spacing and
- * gives poor results for strokes crossing themselves.
- *
- * Instead we use a formula that adds up but approaches brush_alpha slowly
- * and never exceeds it, which gives nice smooth results. */
- float mask_accum = *projPixel->mask_accum;
- float max_mask = brush_alpha * custom_mask * falloff * 65535.0f;
-
- if (brush->flag & BRUSH_ACCUMULATE)
- mask = mask_accum + max_mask;
- else
- mask = mask_accum + (max_mask - mask_accum * falloff);
-
- mask = min_ff(mask, 65535.0f);
- mask_short = (unsigned short)mask;
-
- if (mask_short > *projPixel->mask_accum) {
- *projPixel->mask_accum = mask_short;
- mask = mask_short * (1.0f / 65535.0f);
- }
- else {
- /* Go onto the next pixel */
- continue;
- }
- }
- else {
- mask = brush_alpha * custom_mask * falloff;
- }
-
- if (mask > 0.0f) {
-
- /* copy of code above */
- if (last_index != projPixel->image_index) {
- last_index = projPixel->image_index;
- last_projIma = projImages + last_index;
-
- last_projIma->touch = 1;
- is_floatbuf = (last_projIma->ibuf->rect_float != NULL);
- }
- /* end copy */
-
- /* validate undo tile, since we will modify t*/
- *projPixel->valid = true;
-
- last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index;
- image_paint_partial_redraw_expand(last_partial_redraw_cell, projPixel);
-
- /* texrgb is not used for clone, smear or soften */
- switch (tool) {
- case PAINT_TOOL_CLONE:
- if (is_floatbuf) do_projectpaint_clone_f(ps, projPixel, mask);
- else do_projectpaint_clone(ps, projPixel, mask);
- break;
- case PAINT_TOOL_SMEAR:
- sub_v2_v2v2(co, projPixel->projCoSS, pos_ofs);
-
- if (is_floatbuf) do_projectpaint_smear_f(ps, projPixel, mask, smearArena, &smearPixels_f, co);
- else do_projectpaint_smear(ps, projPixel, mask, smearArena, &smearPixels, co);
- break;
- case PAINT_TOOL_SOFTEN:
- if (is_floatbuf) do_projectpaint_soften_f(ps, projPixel, mask, softenArena, &softenPixels_f);
- else do_projectpaint_soften(ps, projPixel, mask, softenArena, &softenPixels);
- break;
- case PAINT_TOOL_MASK:
- if (is_floatbuf) do_projectpaint_mask_f(ps, projPixel, mask);
- else do_projectpaint_mask(ps, projPixel, mask);
- break;
- default:
- if (is_floatbuf) do_projectpaint_draw_f(ps, projPixel, texrgb, mask);
- else do_projectpaint_draw(ps, projPixel, texrgb, mask, ps->dither, projPixel->x_px, projPixel->y_px);
- break;
- }
-
- if (lock_alpha) {
- if (is_floatbuf) {
- /* slightly more involved case since floats are in premultiplied space we need
- * to make sure alpha is consistent, see T44627 */
- float rgb_straight[4];
- premul_to_straight_v4_v4(rgb_straight, projPixel->pixel.f_pt);
- rgb_straight[3] = projPixel->origColor.f_pt[3];
- straight_to_premul_v4_v4(projPixel->pixel.f_pt, rgb_straight);
- }
- else {
- projPixel->pixel.ch_pt[3] = projPixel->origColor.ch_pt[3];
- }
- }
- }
-
- /* done painting */
- }
- }
- }
- }
- }
-
-
- if (tool == PAINT_TOOL_SMEAR) {
-
- for (node = smearPixels; node; node = node->next) { /* this wont run for a float image */
- projPixel = node->link;
- *projPixel->pixel.uint_pt = ((ProjPixelClone *)projPixel)->clonepx.uint;
- }
-
- for (node = smearPixels_f; node; node = node->next) {
- projPixel = node->link;
- copy_v4_v4(projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.f);
- }
-
- BLI_memarena_free(smearArena);
- }
- else if (tool == PAINT_TOOL_SOFTEN) {
-
- for (node = softenPixels; node; node = node->next) { /* this wont run for a float image */
- projPixel = node->link;
- *projPixel->pixel.uint_pt = projPixel->newColor.uint;
- }
-
- for (node = softenPixels_f; node; node = node->next) {
- projPixel = node->link;
- copy_v4_v4(projPixel->pixel.f_pt, projPixel->newColor.f);
- }
-
- BLI_memarena_free(softenArena);
- }
-
- return NULL;
+ /* First unpack args from the struct */
+ ProjPaintState *ps = ((ProjectHandle *)ph_v)->ps;
+ ProjPaintImage *projImages = ((ProjectHandle *)ph_v)->projImages;
+ const float *lastpos = ((ProjectHandle *)ph_v)->prevmval;
+ const float *pos = ((ProjectHandle *)ph_v)->mval;
+ const int thread_index = ((ProjectHandle *)ph_v)->thread_index;
+ struct ImagePool *pool = ((ProjectHandle *)ph_v)->pool;
+ /* Done with args from ProjectHandle */
+
+ LinkNode *node;
+ ProjPixel *projPixel;
+ Brush *brush = ps->brush;
+
+ int last_index = -1;
+ ProjPaintImage *last_projIma = NULL;
+ ImagePaintPartialRedraw *last_partial_redraw_cell;
+
+ float dist_sq, dist;
+
+ float falloff;
+ int bucket_index;
+ bool is_floatbuf = false;
+ const short tool = ps->tool;
+ rctf bucket_bounds;
+
+ /* for smear only */
+ float pos_ofs[2] = {0};
+ float co[2];
+ unsigned short 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 */
+ const float brush_radius_sq = brush_radius * brush_radius;
+
+ const bool lock_alpha = ELEM(brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ?
+ 0 :
+ (brush->flag & BRUSH_LOCK_ALPHA) != 0;
+
+ LinkNode *smearPixels = NULL;
+ LinkNode *smearPixels_f = NULL;
+ /* mem arena for this brush projection only */
+ MemArena *smearArena = NULL;
+
+ LinkNode *softenPixels = NULL;
+ LinkNode *softenPixels_f = NULL;
+ /* mem arena for this brush projection only */
+ MemArena *softenArena = NULL;
+
+ if (tool == PAINT_TOOL_SMEAR) {
+ pos_ofs[0] = pos[0] - lastpos[0];
+ pos_ofs[1] = pos[1] - lastpos[1];
+
+ smearArena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "paint smear arena");
+ }
+ else if (tool == PAINT_TOOL_SOFTEN) {
+ softenArena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "paint soften arena");
+ }
+
+ /* printf("brush bounds %d %d %d %d\n",
+ * bucketMin[0], bucketMin[1], bucketMax[0], bucketMax[1]); */
+
+ while (project_bucket_iter_next(ps, &bucket_index, &bucket_bounds, pos)) {
+
+ /* Check this bucket and its faces are initialized */
+ if (ps->bucketFlags[bucket_index] == PROJ_BUCKET_NULL) {
+ rctf clip_rect = bucket_bounds;
+ clip_rect.xmin -= PROJ_PIXEL_TOLERANCE;
+ clip_rect.xmax += PROJ_PIXEL_TOLERANCE;
+ clip_rect.ymin -= PROJ_PIXEL_TOLERANCE;
+ clip_rect.ymax += PROJ_PIXEL_TOLERANCE;
+ /* No pixels initialized */
+ project_bucket_init(ps, thread_index, bucket_index, &clip_rect, &bucket_bounds);
+ }
+
+ if (ps->source != PROJ_SRC_VIEW) {
+
+ /* Re-Projection, simple, no brushes! */
+
+ for (node = ps->bucketRect[bucket_index]; node; node = node->next) {
+ projPixel = (ProjPixel *)node->link;
+
+ /* copy of code below */
+ if (last_index != projPixel->image_index) {
+ last_index = projPixel->image_index;
+ last_projIma = projImages + last_index;
+
+ last_projIma->touch = 1;
+ is_floatbuf = (last_projIma->ibuf->rect_float != NULL);
+ }
+ /* end copy */
+
+ /* fill tools */
+ if (ps->source == PROJ_SRC_VIEW_FILL) {
+ if (brush->flag & BRUSH_USE_GRADIENT) {
+ /* these could probably be cached instead of being done per pixel */
+ float tangent[2];
+ float line_len_sq_inv, line_len;
+ float f;
+ float color_f[4];
+ float p[2] = {projPixel->projCoSS[0] - lastpos[0],
+ projPixel->projCoSS[1] - lastpos[1]};
+
+ sub_v2_v2v2(tangent, pos, lastpos);
+ line_len = len_squared_v2(tangent);
+ line_len_sq_inv = 1.0f / line_len;
+ line_len = sqrtf(line_len);
+
+ switch (brush->gradient_fill_mode) {
+ case BRUSH_GRADIENT_LINEAR: {
+ f = dot_v2v2(p, tangent) * line_len_sq_inv;
+ break;
+ }
+ case BRUSH_GRADIENT_RADIAL:
+ default: {
+ f = len_v2(p) / line_len;
+ break;
+ }
+ }
+ BKE_colorband_evaluate(brush->gradient, f, color_f);
+ color_f[3] *= ((float)projPixel->mask) * (1.0f / 65535.0f) * brush->alpha;
+
+ if (is_floatbuf) {
+ /* convert to premultipied */
+ mul_v3_fl(color_f, color_f[3]);
+ IMB_blend_color_float(
+ projPixel->pixel.f_pt, projPixel->origColor.f_pt, color_f, ps->blend);
+ }
+ else {
+ linearrgb_to_srgb_v3_v3(color_f, color_f);
+
+ if (ps->dither > 0.0f) {
+ float_to_byte_dither_v3(
+ projPixel->newColor.ch, color_f, ps->dither, projPixel->x_px, projPixel->y_px);
+ }
+ else {
+ unit_float_to_uchar_clamp_v3(projPixel->newColor.ch, color_f);
+ }
+ projPixel->newColor.ch[3] = unit_float_to_uchar_clamp(color_f[3]);
+ IMB_blend_color_byte(projPixel->pixel.ch_pt,
+ projPixel->origColor.ch_pt,
+ projPixel->newColor.ch,
+ ps->blend);
+ }
+ }
+ else {
+ if (is_floatbuf) {
+ float newColor_f[4];
+ 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(
+ projPixel->pixel.f_pt, projPixel->origColor.f_pt, newColor_f, ps->blend);
+ }
+ else {
+ float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
+ 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,
+ projPixel->origColor.ch_pt,
+ projPixel->newColor.ch,
+ ps->blend);
+ }
+ }
+
+ if (lock_alpha) {
+ if (is_floatbuf) {
+ /* slightly more involved case since floats are in premultiplied space we need
+ * to make sure alpha is consistent, see T44627 */
+ float rgb_straight[4];
+ premul_to_straight_v4_v4(rgb_straight, projPixel->pixel.f_pt);
+ rgb_straight[3] = projPixel->origColor.f_pt[3];
+ straight_to_premul_v4_v4(projPixel->pixel.f_pt, rgb_straight);
+ }
+ else {
+ projPixel->pixel.ch_pt[3] = projPixel->origColor.ch_pt[3];
+ }
+ }
+
+ last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index;
+ image_paint_partial_redraw_expand(last_partial_redraw_cell, projPixel);
+ }
+ else {
+ if (is_floatbuf) {
+ if (UNLIKELY(ps->reproject_ibuf->rect_float == NULL)) {
+ IMB_float_from_rect(ps->reproject_ibuf);
+ ps->reproject_ibuf_free_float = true;
+ }
+
+ bicubic_interpolation_color(ps->reproject_ibuf,
+ NULL,
+ projPixel->newColor.f,
+ projPixel->projCoSS[0],
+ projPixel->projCoSS[1]);
+ if (projPixel->newColor.f[3]) {
+ float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
+
+ mul_v4_v4fl(projPixel->newColor.f, projPixel->newColor.f, mask);
+
+ blend_color_mix_float(
+ projPixel->pixel.f_pt, projPixel->origColor.f_pt, projPixel->newColor.f);
+ }
+ }
+ else {
+ if (UNLIKELY(ps->reproject_ibuf->rect == NULL)) {
+ IMB_rect_from_float(ps->reproject_ibuf);
+ ps->reproject_ibuf_free_uchar = true;
+ }
+
+ bicubic_interpolation_color(ps->reproject_ibuf,
+ projPixel->newColor.ch,
+ NULL,
+ projPixel->projCoSS[0],
+ projPixel->projCoSS[1]);
+ if (projPixel->newColor.ch[3]) {
+ float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
+ projPixel->newColor.ch[3] *= mask;
+
+ blend_color_mix_byte(
+ projPixel->pixel.ch_pt, projPixel->origColor.ch_pt, projPixel->newColor.ch);
+ }
+ }
+ }
+ }
+ }
+ else {
+ /* Normal brush painting */
+
+ for (node = ps->bucketRect[bucket_index]; node; node = node->next) {
+
+ projPixel = (ProjPixel *)node->link;
+
+ dist_sq = len_squared_v2v2(projPixel->projCoSS, pos);
+
+ /*if (dist < radius) {*/ /* correct but uses a sqrtf */
+ if (dist_sq <= brush_radius_sq) {
+ dist = sqrtf(dist_sq);
+
+ falloff = BKE_brush_curve_strength_clamped(ps->brush, dist, brush_radius);
+
+ if (falloff > 0.0f) {
+ float texrgb[3];
+ float mask;
+
+ /* Extra mask for normal, layer stencil, .. */
+ float custom_mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
+
+ /* Mask texture. */
+ if (ps->is_maskbrush) {
+ float texmask = BKE_brush_sample_masktex(
+ ps->scene, ps->brush, projPixel->projCoSS, thread_index, pool);
+ CLAMP(texmask, 0.0f, 1.0f);
+ custom_mask *= texmask;
+ }
+
+ /* Color texture (alpha used as mask). */
+ if (ps->is_texbrush) {
+ MTex *mtex = &brush->mtex;
+ float samplecos[3];
+ float texrgba[4];
+
+ /* taking 3d copy to account for 3D mapping too.
+ * It gets concatenated during sampling */
+ if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
+ copy_v3_v3(samplecos, projPixel->worldCoSS);
+ }
+ else {
+ copy_v2_v2(samplecos, projPixel->projCoSS);
+ samplecos[2] = 0.0f;
+ }
+
+ /* note, for clone and smear,
+ * we only use the alpha, could be a special function */
+ BKE_brush_sample_tex_3d(ps->scene, brush, samplecos, texrgba, thread_index, pool);
+
+ copy_v3_v3(texrgb, texrgba);
+ custom_mask *= texrgba[3];
+ }
+ else {
+ zero_v3(texrgb);
+ }
+
+ if (ps->do_masking) {
+ /* masking to keep brush contribution to a pixel limited. note we do not do
+ * a simple max(mask, mask_accum), as this is very sensitive to spacing and
+ * gives poor results for strokes crossing themselves.
+ *
+ * Instead we use a formula that adds up but approaches brush_alpha slowly
+ * and never exceeds it, which gives nice smooth results. */
+ float mask_accum = *projPixel->mask_accum;
+ float max_mask = brush_alpha * custom_mask * falloff * 65535.0f;
+
+ if (brush->flag & BRUSH_ACCUMULATE)
+ mask = mask_accum + max_mask;
+ else
+ mask = mask_accum + (max_mask - mask_accum * falloff);
+
+ mask = min_ff(mask, 65535.0f);
+ mask_short = (unsigned short)mask;
+
+ if (mask_short > *projPixel->mask_accum) {
+ *projPixel->mask_accum = mask_short;
+ mask = mask_short * (1.0f / 65535.0f);
+ }
+ else {
+ /* Go onto the next pixel */
+ continue;
+ }
+ }
+ else {
+ mask = brush_alpha * custom_mask * falloff;
+ }
+
+ if (mask > 0.0f) {
+
+ /* copy of code above */
+ if (last_index != projPixel->image_index) {
+ last_index = projPixel->image_index;
+ last_projIma = projImages + last_index;
+
+ last_projIma->touch = 1;
+ is_floatbuf = (last_projIma->ibuf->rect_float != NULL);
+ }
+ /* end copy */
+
+ /* validate undo tile, since we will modify t*/
+ *projPixel->valid = true;
+
+ last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index;
+ image_paint_partial_redraw_expand(last_partial_redraw_cell, projPixel);
+
+ /* texrgb is not used for clone, smear or soften */
+ switch (tool) {
+ case PAINT_TOOL_CLONE:
+ if (is_floatbuf)
+ do_projectpaint_clone_f(ps, projPixel, mask);
+ else
+ do_projectpaint_clone(ps, projPixel, mask);
+ break;
+ case PAINT_TOOL_SMEAR:
+ sub_v2_v2v2(co, projPixel->projCoSS, pos_ofs);
+
+ if (is_floatbuf)
+ do_projectpaint_smear_f(ps, projPixel, mask, smearArena, &smearPixels_f, co);
+ else
+ do_projectpaint_smear(ps, projPixel, mask, smearArena, &smearPixels, co);
+ break;
+ case PAINT_TOOL_SOFTEN:
+ if (is_floatbuf)
+ do_projectpaint_soften_f(ps, projPixel, mask, softenArena, &softenPixels_f);
+ else
+ do_projectpaint_soften(ps, projPixel, mask, softenArena, &softenPixels);
+ break;
+ case PAINT_TOOL_MASK:
+ if (is_floatbuf)
+ do_projectpaint_mask_f(ps, projPixel, mask);
+ else
+ do_projectpaint_mask(ps, projPixel, mask);
+ break;
+ default:
+ if (is_floatbuf)
+ do_projectpaint_draw_f(ps, projPixel, texrgb, mask);
+ else
+ do_projectpaint_draw(
+ ps, projPixel, texrgb, mask, ps->dither, projPixel->x_px, projPixel->y_px);
+ break;
+ }
+
+ if (lock_alpha) {
+ if (is_floatbuf) {
+ /* slightly more involved case since floats are in premultiplied space we need
+ * to make sure alpha is consistent, see T44627 */
+ float rgb_straight[4];
+ premul_to_straight_v4_v4(rgb_straight, projPixel->pixel.f_pt);
+ rgb_straight[3] = projPixel->origColor.f_pt[3];
+ straight_to_premul_v4_v4(projPixel->pixel.f_pt, rgb_straight);
+ }
+ else {
+ projPixel->pixel.ch_pt[3] = projPixel->origColor.ch_pt[3];
+ }
+ }
+ }
+
+ /* done painting */
+ }
+ }
+ }
+ }
+ }
+
+ if (tool == PAINT_TOOL_SMEAR) {
+
+ for (node = smearPixels; node; node = node->next) { /* this wont run for a float image */
+ projPixel = node->link;
+ *projPixel->pixel.uint_pt = ((ProjPixelClone *)projPixel)->clonepx.uint;
+ }
+
+ for (node = smearPixels_f; node; node = node->next) {
+ projPixel = node->link;
+ copy_v4_v4(projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.f);
+ }
+
+ BLI_memarena_free(smearArena);
+ }
+ else if (tool == PAINT_TOOL_SOFTEN) {
+
+ for (node = softenPixels; node; node = node->next) { /* this wont run for a float image */
+ projPixel = node->link;
+ *projPixel->pixel.uint_pt = projPixel->newColor.uint;
+ }
+
+ for (node = softenPixels_f; node; node = node->next) {
+ projPixel = node->link;
+ copy_v4_v4(projPixel->pixel.f_pt, projPixel->newColor.f);
+ }
+
+ BLI_memarena_free(softenArena);
+ }
+
+ return NULL;
}
static bool project_paint_op(void *state, const float lastpos[2], const float pos[2])
{
- /* First unpack args from the struct */
- ProjPaintState *ps = (ProjPaintState *)state;
- bool touch_any = false;
-
- ProjectHandle handles[BLENDER_MAX_THREADS];
- ListBase threads;
- int a, i;
-
- struct ImagePool *pool;
-
- if (!project_bucket_iter_init(ps, pos)) {
- return touch_any;
- }
-
- if (ps->thread_tot > 1)
- BLI_threadpool_init(&threads, do_projectpaint_thread, ps->thread_tot);
-
- pool = BKE_image_pool_new();
-
- /* get the threads running */
- for (a = 0; a < ps->thread_tot; a++) {
-
- /* set defaults in handles */
- //memset(&handles[a], 0, sizeof(BakeShade));
-
- handles[a].ps = ps;
- copy_v2_v2(handles[a].mval, pos);
- copy_v2_v2(handles[a].prevmval, lastpos);
-
- /* thread specific */
- handles[a].thread_index = a;
-
- handles[a].projImages = BLI_memarena_alloc(ps->arena_mt[a], ps->image_tot * sizeof(ProjPaintImage));
-
- memcpy(handles[a].projImages, ps->projImages, ps->image_tot * sizeof(ProjPaintImage));
-
- /* image bounds */
- for (i = 0; i < ps->image_tot; i++) {
- handles[a].projImages[i].partRedrawRect = BLI_memarena_alloc(ps->arena_mt[a], sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
- memcpy(handles[a].projImages[i].partRedrawRect, ps->projImages[i].partRedrawRect, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
- }
-
- handles[a].pool = pool;
-
- if (ps->thread_tot > 1)
- BLI_threadpool_insert(&threads, &handles[a]);
- }
-
- if (ps->thread_tot > 1) /* wait for everything to be done */
- BLI_threadpool_end(&threads);
- else
- do_projectpaint_thread(&handles[0]);
-
-
- BKE_image_pool_free(pool);
-
- /* move threaded bounds back into ps->projectPartialRedraws */
- for (i = 0; i < ps->image_tot; i++) {
- int touch = 0;
- for (a = 0; a < ps->thread_tot; a++) {
- touch |= partial_redraw_array_merge(ps->projImages[i].partRedrawRect, handles[a].projImages[i].partRedrawRect, PROJ_BOUNDBOX_SQUARED);
- }
-
- if (touch) {
- ps->projImages[i].touch = 1;
- touch_any = 1;
- }
- }
-
- /* calculate pivot for rotation around seletion if needed */
- if (U.uiflag & USER_ORBIT_SELECTION) {
- float w[3];
- int tri_index;
-
- tri_index = project_paint_PickFace(ps, pos, w);
-
- if (tri_index != -1) {
- const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
- const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
- float world[3];
- UnifiedPaintSettings *ups = &ps->scene->toolsettings->unified_paint_settings;
-
- interp_v3_v3v3v3(
- world,
- ps->mvert_eval[lt_vtri[0]].co,
- ps->mvert_eval[lt_vtri[1]].co,
- ps->mvert_eval[lt_vtri[2]].co,
- w);
-
- ups->average_stroke_counter++;
- mul_m4_v3(ps->obmat, world);
- add_v3_v3(ups->average_stroke_accum, world);
- ups->last_stroke_valid = true;
- }
- }
-
- return touch_any;
+ /* First unpack args from the struct */
+ ProjPaintState *ps = (ProjPaintState *)state;
+ bool touch_any = false;
+
+ ProjectHandle handles[BLENDER_MAX_THREADS];
+ ListBase threads;
+ int a, i;
+
+ struct ImagePool *pool;
+
+ if (!project_bucket_iter_init(ps, pos)) {
+ return touch_any;
+ }
+
+ if (ps->thread_tot > 1)
+ BLI_threadpool_init(&threads, do_projectpaint_thread, ps->thread_tot);
+
+ pool = BKE_image_pool_new();
+
+ /* get the threads running */
+ for (a = 0; a < ps->thread_tot; a++) {
+
+ /* set defaults in handles */
+ //memset(&handles[a], 0, sizeof(BakeShade));
+
+ handles[a].ps = ps;
+ copy_v2_v2(handles[a].mval, pos);
+ copy_v2_v2(handles[a].prevmval, lastpos);
+
+ /* thread specific */
+ handles[a].thread_index = a;
+
+ handles[a].projImages = BLI_memarena_alloc(ps->arena_mt[a],
+ ps->image_tot * sizeof(ProjPaintImage));
+
+ memcpy(handles[a].projImages, ps->projImages, ps->image_tot * sizeof(ProjPaintImage));
+
+ /* image bounds */
+ for (i = 0; i < ps->image_tot; i++) {
+ handles[a].projImages[i].partRedrawRect = BLI_memarena_alloc(
+ ps->arena_mt[a], sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ memcpy(handles[a].projImages[i].partRedrawRect,
+ ps->projImages[i].partRedrawRect,
+ sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ }
+
+ handles[a].pool = pool;
+
+ if (ps->thread_tot > 1)
+ BLI_threadpool_insert(&threads, &handles[a]);
+ }
+
+ if (ps->thread_tot > 1) /* wait for everything to be done */
+ BLI_threadpool_end(&threads);
+ else
+ do_projectpaint_thread(&handles[0]);
+
+ BKE_image_pool_free(pool);
+
+ /* move threaded bounds back into ps->projectPartialRedraws */
+ for (i = 0; i < ps->image_tot; i++) {
+ int touch = 0;
+ for (a = 0; a < ps->thread_tot; a++) {
+ touch |= partial_redraw_array_merge(ps->projImages[i].partRedrawRect,
+ handles[a].projImages[i].partRedrawRect,
+ PROJ_BOUNDBOX_SQUARED);
+ }
+
+ if (touch) {
+ ps->projImages[i].touch = 1;
+ touch_any = 1;
+ }
+ }
+
+ /* calculate pivot for rotation around seletion if needed */
+ if (U.uiflag & USER_ORBIT_SELECTION) {
+ float w[3];
+ int tri_index;
+
+ tri_index = project_paint_PickFace(ps, pos, w);
+
+ if (tri_index != -1) {
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
+ const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
+ float world[3];
+ UnifiedPaintSettings *ups = &ps->scene->toolsettings->unified_paint_settings;
+
+ interp_v3_v3v3v3(world,
+ ps->mvert_eval[lt_vtri[0]].co,
+ ps->mvert_eval[lt_vtri[1]].co,
+ ps->mvert_eval[lt_vtri[2]].co,
+ w);
+
+ ups->average_stroke_counter++;
+ mul_m4_v3(ps->obmat, world);
+ add_v3_v3(ups->average_stroke_accum, world);
+ ups->last_stroke_valid = true;
+ }
+ }
+
+ return touch_any;
}
-
-static void paint_proj_stroke_ps(
- const bContext *UNUSED(C), void *ps_handle_p, const float prev_pos[2], const float pos[2],
- const bool eraser, float pressure, float distance, float size,
- /* extra view */
- ProjPaintState *ps
- )
+static void paint_proj_stroke_ps(const bContext *UNUSED(C),
+ void *ps_handle_p,
+ const float prev_pos[2],
+ const float pos[2],
+ const bool eraser,
+ float pressure,
+ float distance,
+ float size,
+ /* extra view */
+ ProjPaintState *ps)
{
- ProjStrokeHandle *ps_handle = ps_handle_p;
- Brush *brush = ps->brush;
- Scene *scene = ps->scene;
-
- ps->brush_size = size;
- ps->blend = brush->blend;
- if (eraser)
- ps->blend = IMB_BLEND_ERASE_ALPHA;
-
- /* handle gradient and inverted stroke color here */
- if (ELEM(ps->tool, PAINT_TOOL_DRAW, PAINT_TOOL_FILL)) {
- paint_brush_color_get(scene, brush, false, ps->mode == BRUSH_STROKE_INVERT, distance, pressure, ps->paint_color, NULL);
- if (ps->use_colormanagement) {
- srgb_to_linearrgb_v3_v3(ps->paint_color_linear, ps->paint_color);
- }
- else {
- copy_v3_v3(ps->paint_color_linear, ps->paint_color);
- }
- }
- else if (ps->tool == PAINT_TOOL_MASK) {
- ps->stencil_value = brush->weight;
-
- if ((ps->mode == BRUSH_STROKE_INVERT) ^
- ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) != 0))
- {
- ps->stencil_value = 1.0f - ps->stencil_value;
- }
- }
-
- if (project_paint_op(ps, prev_pos, pos)) {
- ps_handle->need_redraw = true;
- project_image_refresh_tagged(ps);
- }
+ ProjStrokeHandle *ps_handle = ps_handle_p;
+ Brush *brush = ps->brush;
+ Scene *scene = ps->scene;
+
+ ps->brush_size = size;
+ ps->blend = brush->blend;
+ if (eraser)
+ ps->blend = IMB_BLEND_ERASE_ALPHA;
+
+ /* handle gradient and inverted stroke color here */
+ if (ELEM(ps->tool, PAINT_TOOL_DRAW, PAINT_TOOL_FILL)) {
+ paint_brush_color_get(scene,
+ brush,
+ false,
+ ps->mode == BRUSH_STROKE_INVERT,
+ distance,
+ pressure,
+ ps->paint_color,
+ NULL);
+ if (ps->use_colormanagement) {
+ srgb_to_linearrgb_v3_v3(ps->paint_color_linear, ps->paint_color);
+ }
+ else {
+ copy_v3_v3(ps->paint_color_linear, ps->paint_color);
+ }
+ }
+ else if (ps->tool == PAINT_TOOL_MASK) {
+ ps->stencil_value = brush->weight;
+
+ if ((ps->mode == BRUSH_STROKE_INVERT) ^
+ ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) != 0)) {
+ ps->stencil_value = 1.0f - ps->stencil_value;
+ }
+ }
+
+ if (project_paint_op(ps, prev_pos, pos)) {
+ ps_handle->need_redraw = true;
+ project_image_refresh_tagged(ps);
+ }
}
-
-void paint_proj_stroke(
- const bContext *C, void *ps_handle_p, const float prev_pos[2], const float pos[2],
- const bool eraser, float pressure, float distance, float size)
+void paint_proj_stroke(const bContext *C,
+ void *ps_handle_p,
+ const float prev_pos[2],
+ const float pos[2],
+ const bool eraser,
+ float pressure,
+ float distance,
+ float size)
{
- int i;
- ProjStrokeHandle *ps_handle = ps_handle_p;
+ int i;
+ ProjStrokeHandle *ps_handle = ps_handle_p;
- /* clone gets special treatment here to avoid going through image initialization */
- if (ps_handle->is_clone_cursor_pick) {
- Scene *scene = ps_handle->scene;
- struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
- View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
- float *cursor = scene->cursor.location;
- int mval_i[2] = {(int)pos[0], (int)pos[1]};
+ /* clone gets special treatment here to avoid going through image initialization */
+ if (ps_handle->is_clone_cursor_pick) {
+ Scene *scene = ps_handle->scene;
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+ float *cursor = scene->cursor.location;
+ int mval_i[2] = {(int)pos[0], (int)pos[1]};
- view3d_operator_needs_opengl(C);
+ view3d_operator_needs_opengl(C);
- if (!ED_view3d_autodist(depsgraph, ar, v3d, mval_i, cursor, false, NULL)) {
- return;
- }
+ if (!ED_view3d_autodist(depsgraph, ar, v3d, mval_i, cursor, false, NULL)) {
+ return;
+ }
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- return;
- }
+ return;
+ }
- for (i = 0; i < ps_handle->ps_views_tot; i++) {
- ProjPaintState *ps = ps_handle->ps_views[i];
- paint_proj_stroke_ps(C, ps_handle_p, prev_pos, pos, eraser, pressure, distance, size, ps);
- }
+ for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ ProjPaintState *ps = ps_handle->ps_views[i];
+ paint_proj_stroke_ps(C, ps_handle_p, prev_pos, pos, eraser, pressure, distance, size, ps);
+ }
}
-
/* initialize project paint settings from context */
static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int mode)
{
- Scene *scene = CTX_data_scene(C);
- ToolSettings *settings = scene->toolsettings;
-
- /* brush */
- ps->mode = mode;
- ps->brush = BKE_paint_brush(&settings->imapaint.paint);
- if (ps->brush) {
- Brush *brush = ps->brush;
- ps->tool = brush->imagepaint_tool;
- ps->blend = brush->blend;
- /* only check for inversion for the soften tool, elsewhere,
- * a resident brush inversion flag can cause issues */
- if (brush->imagepaint_tool == PAINT_TOOL_SOFTEN) {
- ps->mode = (((ps->mode == BRUSH_STROKE_INVERT) ^ ((brush->flag & BRUSH_DIR_IN) != 0)) ?
- BRUSH_STROKE_INVERT : BRUSH_STROKE_NORMAL);
-
- ps->blurkernel = paint_new_blur_kernel(brush, true);
- }
-
- /* disable for 3d mapping also because painting on mirrored mesh can create "stripes" */
- ps->do_masking = paint_use_opacity_masking(brush);
- ps->is_texbrush = (brush->mtex.tex && brush->imagepaint_tool == PAINT_TOOL_DRAW) ? true : false;
- ps->is_maskbrush = (brush->mask_mtex.tex) ? true : false;
- }
- else {
- /* brush may be NULL*/
- ps->do_masking = false;
- ps->is_texbrush = false;
- ps->is_maskbrush = false;
- }
-
- /* sizeof(ProjPixel), since we alloc this a _lot_ */
- ps->pixel_sizeof = project_paint_pixel_sizeof(ps->tool);
- BLI_assert(ps->pixel_sizeof >= sizeof(ProjPixel));
-
- /* these can be NULL */
- ps->v3d = CTX_wm_view3d(C);
- ps->rv3d = CTX_wm_region_view3d(C);
- ps->ar = CTX_wm_region(C);
-
- ps->depsgraph = CTX_data_depsgraph(C);
- ps->scene = scene;
- /* allow override of active object */
- ps->ob = ob;
-
- ps->do_material_slots = (settings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL);
- ps->stencil_ima = settings->imapaint.stencil;
- ps->canvas_ima = (!ps->do_material_slots) ?
- settings->imapaint.canvas : NULL;
- ps->clone_ima = (!ps->do_material_slots) ?
- settings->imapaint.clone : NULL;
-
- ps->do_mask_cavity = (settings->imapaint.paint.flags & PAINT_USE_CAVITY_MASK) ? true : false;
- ps->cavity_curve = settings->imapaint.paint.cavity_curve;
-
- /* setup projection painting data */
- if (ps->tool != PAINT_TOOL_FILL) {
- ps->do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? false : true;
- ps->do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? false : true;
- ps->do_mask_normal = (settings->imapaint.flag & IMAGEPAINT_PROJECT_FLAT) ? false : true;
- }
- else {
- ps->do_backfacecull = ps->do_occlude = ps->do_mask_normal = 0;
- }
-
- if (ps->tool == PAINT_TOOL_CLONE)
- ps->do_layer_clone = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) ? 1 : 0;
-
-
- ps->do_stencil_brush = (ps->brush && ps->brush->imagepaint_tool == PAINT_TOOL_MASK);
- /* deactivate stenciling for the stencil brush :) */
- ps->do_layer_stencil = ((settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) &&
- !(ps->do_stencil_brush) && ps->stencil_ima);
- ps->do_layer_stencil_inv = ((settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) != 0);
-
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *settings = scene->toolsettings;
+
+ /* brush */
+ ps->mode = mode;
+ ps->brush = BKE_paint_brush(&settings->imapaint.paint);
+ if (ps->brush) {
+ Brush *brush = ps->brush;
+ ps->tool = brush->imagepaint_tool;
+ ps->blend = brush->blend;
+ /* only check for inversion for the soften tool, elsewhere,
+ * a resident brush inversion flag can cause issues */
+ if (brush->imagepaint_tool == PAINT_TOOL_SOFTEN) {
+ ps->mode = (((ps->mode == BRUSH_STROKE_INVERT) ^ ((brush->flag & BRUSH_DIR_IN) != 0)) ?
+ BRUSH_STROKE_INVERT :
+ BRUSH_STROKE_NORMAL);
+
+ ps->blurkernel = paint_new_blur_kernel(brush, true);
+ }
+
+ /* disable for 3d mapping also because painting on mirrored mesh can create "stripes" */
+ ps->do_masking = paint_use_opacity_masking(brush);
+ ps->is_texbrush = (brush->mtex.tex && brush->imagepaint_tool == PAINT_TOOL_DRAW) ? true :
+ false;
+ ps->is_maskbrush = (brush->mask_mtex.tex) ? true : false;
+ }
+ else {
+ /* brush may be NULL*/
+ ps->do_masking = false;
+ ps->is_texbrush = false;
+ ps->is_maskbrush = false;
+ }
+
+ /* sizeof(ProjPixel), since we alloc this a _lot_ */
+ ps->pixel_sizeof = project_paint_pixel_sizeof(ps->tool);
+ BLI_assert(ps->pixel_sizeof >= sizeof(ProjPixel));
+
+ /* these can be NULL */
+ ps->v3d = CTX_wm_view3d(C);
+ ps->rv3d = CTX_wm_region_view3d(C);
+ ps->ar = CTX_wm_region(C);
+
+ ps->depsgraph = CTX_data_depsgraph(C);
+ ps->scene = scene;
+ /* allow override of active object */
+ ps->ob = ob;
+
+ ps->do_material_slots = (settings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL);
+ ps->stencil_ima = settings->imapaint.stencil;
+ ps->canvas_ima = (!ps->do_material_slots) ? settings->imapaint.canvas : NULL;
+ ps->clone_ima = (!ps->do_material_slots) ? settings->imapaint.clone : NULL;
+
+ ps->do_mask_cavity = (settings->imapaint.paint.flags & PAINT_USE_CAVITY_MASK) ? true : false;
+ ps->cavity_curve = settings->imapaint.paint.cavity_curve;
+
+ /* setup projection painting data */
+ if (ps->tool != PAINT_TOOL_FILL) {
+ ps->do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? false : true;
+ ps->do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? false : true;
+ ps->do_mask_normal = (settings->imapaint.flag & IMAGEPAINT_PROJECT_FLAT) ? false : true;
+ }
+ else {
+ ps->do_backfacecull = ps->do_occlude = ps->do_mask_normal = 0;
+ }
+
+ if (ps->tool == PAINT_TOOL_CLONE)
+ ps->do_layer_clone = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) ? 1 : 0;
+
+ ps->do_stencil_brush = (ps->brush && ps->brush->imagepaint_tool == PAINT_TOOL_MASK);
+ /* deactivate stenciling for the stencil brush :) */
+ ps->do_layer_stencil = ((settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) &&
+ !(ps->do_stencil_brush) && ps->stencil_ima);
+ ps->do_layer_stencil_inv = ((settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) !=
+ 0);
#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);
+ /* pixel num to bleed */
+ ps->seam_bleed_px = settings->imapaint.seam_bleed;
+ ps->seam_bleed_px_sq = SQUARE(settings->imapaint.seam_bleed);
#endif
- if (ps->do_mask_normal) {
- ps->normal_angle_inner = settings->imapaint.normal_angle;
- ps->normal_angle = (ps->normal_angle_inner + 90.0f) * 0.5f;
- }
- else {
- ps->normal_angle_inner = ps->normal_angle = settings->imapaint.normal_angle;
- }
+ if (ps->do_mask_normal) {
+ ps->normal_angle_inner = settings->imapaint.normal_angle;
+ ps->normal_angle = (ps->normal_angle_inner + 90.0f) * 0.5f;
+ }
+ else {
+ ps->normal_angle_inner = ps->normal_angle = settings->imapaint.normal_angle;
+ }
- ps->normal_angle_inner *= (float)(M_PI_2 / 90);
- ps->normal_angle *= (float)(M_PI_2 / 90);
- ps->normal_angle_range = ps->normal_angle - ps->normal_angle_inner;
+ ps->normal_angle_inner *= (float)(M_PI_2 / 90);
+ ps->normal_angle *= (float)(M_PI_2 / 90);
+ ps->normal_angle_range = ps->normal_angle - ps->normal_angle_inner;
- if (ps->normal_angle_range <= 0.0f) {
- /* no need to do blending */
- ps->do_mask_normal = false;
- }
+ if (ps->normal_angle_range <= 0.0f) {
+ /* no need to do blending */
+ ps->do_mask_normal = false;
+ }
- ps->normal_angle__cos = cosf(ps->normal_angle);
- ps->normal_angle_inner__cos = cosf(ps->normal_angle_inner);
+ ps->normal_angle__cos = cosf(ps->normal_angle);
+ ps->normal_angle_inner__cos = cosf(ps->normal_angle_inner);
- ps->dither = settings->imapaint.dither;
+ ps->dither = settings->imapaint.dither;
- ps->use_colormanagement = BKE_scene_check_color_management_enabled(CTX_data_scene(C));
+ ps->use_colormanagement = BKE_scene_check_color_management_enabled(CTX_data_scene(C));
- return;
+ return;
}
void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int mode)
{
- ProjStrokeHandle *ps_handle;
- Scene *scene = CTX_data_scene(C);
- ToolSettings *settings = scene->toolsettings;
- int i;
- bool is_multi_view;
- char symmetry_flag_views[ARRAY_SIZE(ps_handle->ps_views)] = {0};
-
- ps_handle = MEM_callocN(sizeof(ProjStrokeHandle), "ProjStrokeHandle");
- ps_handle->scene = scene;
- ps_handle->brush = BKE_paint_brush(&settings->imapaint.paint);
-
- /* bypass regular stroke logic */
- if ((ps_handle->brush->imagepaint_tool == PAINT_TOOL_CLONE) &&
- (mode == BRUSH_STROKE_INVERT))
- {
- view3d_operator_needs_opengl(C);
- ps_handle->is_clone_cursor_pick = true;
- return ps_handle;
- }
-
- ps_handle->orig_brush_size = BKE_brush_size_get(scene, ps_handle->brush);
-
- ps_handle->symmetry_flags = settings->imapaint.paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
- ps_handle->ps_views_tot = 1 + (pow_i(2, count_bits_i(ps_handle->symmetry_flags)) - 1);
- is_multi_view = (ps_handle->ps_views_tot != 1);
-
- for (i = 0; i < ps_handle->ps_views_tot; i++) {
- ProjPaintState *ps = MEM_callocN(sizeof(ProjPaintState), "ProjectionPaintState");
- ps_handle->ps_views[i] = ps;
- }
-
- if (ps_handle->symmetry_flags) {
- int index = 0;
-
- int x = 0;
- do {
- int y = 0;
- do {
- int z = 0;
- do {
- symmetry_flag_views[index++] = (
- (x ? PAINT_SYMM_X : 0) |
- (y ? PAINT_SYMM_Y : 0) |
- (z ? PAINT_SYMM_Z : 0));
- BLI_assert(index <= ps_handle->ps_views_tot);
- } while ((z++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_Z));
- } while ((y++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_Y));
- } while ((x++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_X));
- BLI_assert(index == ps_handle->ps_views_tot);
- }
-
- for (i = 0; i < ps_handle->ps_views_tot; i++) {
- ProjPaintState *ps = ps_handle->ps_views[i];
-
- project_state_init(C, ob, ps, mode);
-
- if (ps->ob == NULL) {
- ps_handle->ps_views_tot = i + 1;
- goto fail;
- }
- }
-
- /* Don't allow brush size below 2 */
- if (BKE_brush_size_get(scene, ps_handle->brush) < 2)
- BKE_brush_size_set(scene, ps_handle->brush, 2 * U.pixelsize);
-
- /* allocate and initialize spatial data structures */
-
- for (i = 0; i < ps_handle->ps_views_tot; i++) {
- ProjPaintState *ps = ps_handle->ps_views[i];
-
- ps->source = (ps->tool == PAINT_TOOL_FILL) ? PROJ_SRC_VIEW_FILL : PROJ_SRC_VIEW;
- project_image_refresh_tagged(ps);
-
- /* re-use! */
- if (i != 0) {
- ps->is_shared_user = true;
- PROJ_PAINT_STATE_SHARED_MEMCPY(ps, ps_handle->ps_views[0]);
- }
-
- project_paint_begin(C, ps, is_multi_view, symmetry_flag_views[i]);
- if (ps->me_eval == NULL) {
- goto fail;
- }
-
- paint_proj_begin_clone(ps, mouse);
- }
-
- paint_brush_init_tex(ps_handle->brush);
-
- return ps_handle;
-
+ ProjStrokeHandle *ps_handle;
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *settings = scene->toolsettings;
+ int i;
+ bool is_multi_view;
+ char symmetry_flag_views[ARRAY_SIZE(ps_handle->ps_views)] = {0};
+
+ ps_handle = MEM_callocN(sizeof(ProjStrokeHandle), "ProjStrokeHandle");
+ ps_handle->scene = scene;
+ ps_handle->brush = BKE_paint_brush(&settings->imapaint.paint);
+
+ /* bypass regular stroke logic */
+ if ((ps_handle->brush->imagepaint_tool == PAINT_TOOL_CLONE) && (mode == BRUSH_STROKE_INVERT)) {
+ view3d_operator_needs_opengl(C);
+ ps_handle->is_clone_cursor_pick = true;
+ return ps_handle;
+ }
+
+ ps_handle->orig_brush_size = BKE_brush_size_get(scene, ps_handle->brush);
+
+ ps_handle->symmetry_flags = settings->imapaint.paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+ ps_handle->ps_views_tot = 1 + (pow_i(2, count_bits_i(ps_handle->symmetry_flags)) - 1);
+ is_multi_view = (ps_handle->ps_views_tot != 1);
+
+ for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ ProjPaintState *ps = MEM_callocN(sizeof(ProjPaintState), "ProjectionPaintState");
+ ps_handle->ps_views[i] = ps;
+ }
+
+ if (ps_handle->symmetry_flags) {
+ int index = 0;
+
+ int x = 0;
+ do {
+ int y = 0;
+ do {
+ int z = 0;
+ do {
+ symmetry_flag_views[index++] = ((x ? PAINT_SYMM_X : 0) | (y ? PAINT_SYMM_Y : 0) |
+ (z ? PAINT_SYMM_Z : 0));
+ BLI_assert(index <= ps_handle->ps_views_tot);
+ } while ((z++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_Z));
+ } while ((y++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_Y));
+ } while ((x++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_X));
+ BLI_assert(index == ps_handle->ps_views_tot);
+ }
+
+ for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ ProjPaintState *ps = ps_handle->ps_views[i];
+
+ project_state_init(C, ob, ps, mode);
+
+ if (ps->ob == NULL) {
+ ps_handle->ps_views_tot = i + 1;
+ goto fail;
+ }
+ }
+
+ /* Don't allow brush size below 2 */
+ if (BKE_brush_size_get(scene, ps_handle->brush) < 2)
+ BKE_brush_size_set(scene, ps_handle->brush, 2 * U.pixelsize);
+
+ /* allocate and initialize spatial data structures */
+
+ for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ ProjPaintState *ps = ps_handle->ps_views[i];
+
+ ps->source = (ps->tool == PAINT_TOOL_FILL) ? PROJ_SRC_VIEW_FILL : PROJ_SRC_VIEW;
+ project_image_refresh_tagged(ps);
+
+ /* re-use! */
+ if (i != 0) {
+ ps->is_shared_user = true;
+ PROJ_PAINT_STATE_SHARED_MEMCPY(ps, ps_handle->ps_views[0]);
+ }
+
+ project_paint_begin(C, ps, is_multi_view, symmetry_flag_views[i]);
+ if (ps->me_eval == NULL) {
+ goto fail;
+ }
+
+ paint_proj_begin_clone(ps, mouse);
+ }
+
+ paint_brush_init_tex(ps_handle->brush);
+
+ return ps_handle;
fail:
- for (i = 0; i < ps_handle->ps_views_tot; i++) {
- ProjPaintState *ps = ps_handle->ps_views[i];
- MEM_freeN(ps);
- }
- MEM_freeN(ps_handle);
- return NULL;
+ for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ ProjPaintState *ps = ps_handle->ps_views[i];
+ MEM_freeN(ps);
+ }
+ MEM_freeN(ps_handle);
+ return NULL;
}
void paint_proj_redraw(const bContext *C, void *ps_handle_p, bool final)
{
- ProjStrokeHandle *ps_handle = ps_handle_p;
-
- if (ps_handle->need_redraw) {
- ps_handle->need_redraw = false;
- }
- else if (!final) {
- return;
- }
-
- if (final) {
- /* compositor listener deals with updating */
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, NULL);
- }
- else {
- ED_region_tag_redraw(CTX_wm_region(C));
- }
+ ProjStrokeHandle *ps_handle = ps_handle_p;
+
+ if (ps_handle->need_redraw) {
+ ps_handle->need_redraw = false;
+ }
+ else if (!final) {
+ return;
+ }
+
+ if (final) {
+ /* compositor listener deals with updating */
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, NULL);
+ }
+ else {
+ ED_region_tag_redraw(CTX_wm_region(C));
+ }
}
void paint_proj_stroke_done(void *ps_handle_p)
{
- ProjStrokeHandle *ps_handle = ps_handle_p;
- Scene *scene = ps_handle->scene;
- int i;
+ 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;
- }
+ if (ps_handle->is_clone_cursor_pick) {
+ MEM_freeN(ps_handle);
+ return;
+ }
- for (i = 1; i < ps_handle->ps_views_tot; i++) {
- PROJ_PAINT_STATE_SHARED_CLEAR(ps_handle->ps_views[i]);
- }
+ for (i = 1; i < ps_handle->ps_views_tot; i++) {
+ PROJ_PAINT_STATE_SHARED_CLEAR(ps_handle->ps_views[i]);
+ }
- BKE_brush_size_set(scene, ps_handle->brush, ps_handle->orig_brush_size);
+ BKE_brush_size_set(scene, ps_handle->brush, ps_handle->orig_brush_size);
- paint_brush_exit_tex(ps_handle->brush);
+ paint_brush_exit_tex(ps_handle->brush);
- for (i = 0; i < ps_handle->ps_views_tot; i++) {
- ProjPaintState *ps;
- ps = ps_handle->ps_views[i];
- project_paint_end(ps);
- MEM_freeN(ps);
+ for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ ProjPaintState *ps;
+ ps = ps_handle->ps_views[i];
+ project_paint_end(ps);
+ MEM_freeN(ps);
+ }
- }
-
- MEM_freeN(ps_handle);
+ MEM_freeN(ps_handle);
}
/* 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"));
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- ProjPaintState ps = {NULL};
- int orig_brush_size;
- IDProperty *idgroup;
- IDProperty *view_data = NULL;
- Object *ob = OBACT(view_layer);
- bool uvs, mat, tex;
-
- if (ob == NULL || ob->type != OB_MESH) {
- BKE_report(op->reports, RPT_ERROR, "No active mesh object");
- return OPERATOR_CANCELLED;
- }
-
- if (!BKE_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, NULL)) {
- BKE_paint_data_warning(op->reports, uvs, mat, tex, true);
- WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
- return OPERATOR_CANCELLED;
- }
-
- project_state_init(C, ob, &ps, BRUSH_STROKE_NORMAL);
-
- if (image == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Image could not be found");
- return OPERATOR_CANCELLED;
- }
-
- ps.reproject_image = image;
- ps.reproject_ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
-
- if ((ps.reproject_ibuf == NULL) ||
- ((ps.reproject_ibuf->rect || ps.reproject_ibuf->rect_float) == false))
- {
- BKE_report(op->reports, RPT_ERROR, "Image data could not be found");
- return OPERATOR_CANCELLED;
- }
-
- idgroup = IDP_GetProperties(&image->id, 0);
-
- if (idgroup) {
- view_data = IDP_GetPropertyTypeFromGroup(idgroup, PROJ_VIEW_DATA_ID, IDP_ARRAY);
-
- /* type check to make sure its ok */
- if (view_data->len != PROJ_VIEW_DATA_SIZE || view_data->subtype != IDP_FLOAT) {
- BKE_report(op->reports, RPT_ERROR, "Image project data invalid");
- return OPERATOR_CANCELLED;
- }
- }
-
- if (view_data) {
- /* image has stored view projection info */
- ps.source = PROJ_SRC_IMAGE_VIEW;
- }
- else {
- ps.source = PROJ_SRC_IMAGE_CAM;
-
- if (scene->camera == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active camera set");
- return OPERATOR_CANCELLED;
- }
- }
-
- /* override */
- ps.is_texbrush = false;
- ps.is_maskbrush = false;
- ps.do_masking = false;
- orig_brush_size = BKE_brush_size_get(scene, ps.brush);
- /* cover the whole image */
- BKE_brush_size_set(scene, ps.brush, 32 * U.pixelsize);
-
- /* so pixels are initialized with minimal info */
- ps.tool = PAINT_TOOL_DRAW;
-
- scene->toolsettings->imapaint.flag |= IMAGEPAINT_DRAWING;
-
- ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_3D);
-
- /* allocate and initialize spatial data structures */
- project_paint_begin(C, &ps, false, 0);
-
- if (ps.me_eval == NULL) {
- BKE_brush_size_set(scene, ps.brush, orig_brush_size);
- BKE_report(op->reports, RPT_ERROR, "Could not get valid evaluated mesh");
- return OPERATOR_CANCELLED;
- }
- else {
- float pos[2] = {0.0, 0.0};
- float lastpos[2] = {0.0, 0.0};
- int a;
-
- project_paint_op(&ps, lastpos, pos);
-
- project_image_refresh_tagged(&ps);
-
- for (a = 0; a < ps.image_tot; a++) {
- GPU_free_image(ps.projImages[a].ima);
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ps.projImages[a].ima);
- }
- }
-
- project_paint_end(&ps);
-
- scene->toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
- BKE_brush_size_set(scene, ps.brush, orig_brush_size);
-
- return OPERATOR_FINISHED;
+ Image *image = BLI_findlink(&CTX_data_main(C)->images, RNA_enum_get(op->ptr, "image"));
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ ProjPaintState ps = {NULL};
+ int orig_brush_size;
+ IDProperty *idgroup;
+ IDProperty *view_data = NULL;
+ Object *ob = OBACT(view_layer);
+ bool uvs, mat, tex;
+
+ if (ob == NULL || ob->type != OB_MESH) {
+ BKE_report(op->reports, RPT_ERROR, "No active mesh object");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!BKE_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, NULL)) {
+ BKE_paint_data_warning(op->reports, uvs, mat, tex, true);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ return OPERATOR_CANCELLED;
+ }
+
+ project_state_init(C, ob, &ps, BRUSH_STROKE_NORMAL);
+
+ if (image == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Image could not be found");
+ return OPERATOR_CANCELLED;
+ }
+
+ ps.reproject_image = image;
+ ps.reproject_ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
+
+ if ((ps.reproject_ibuf == NULL) ||
+ ((ps.reproject_ibuf->rect || ps.reproject_ibuf->rect_float) == false)) {
+ BKE_report(op->reports, RPT_ERROR, "Image data could not be found");
+ return OPERATOR_CANCELLED;
+ }
+
+ idgroup = IDP_GetProperties(&image->id, 0);
+
+ if (idgroup) {
+ view_data = IDP_GetPropertyTypeFromGroup(idgroup, PROJ_VIEW_DATA_ID, IDP_ARRAY);
+
+ /* type check to make sure its ok */
+ if (view_data->len != PROJ_VIEW_DATA_SIZE || view_data->subtype != IDP_FLOAT) {
+ BKE_report(op->reports, RPT_ERROR, "Image project data invalid");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ if (view_data) {
+ /* image has stored view projection info */
+ ps.source = PROJ_SRC_IMAGE_VIEW;
+ }
+ else {
+ ps.source = PROJ_SRC_IMAGE_CAM;
+
+ if (scene->camera == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active camera set");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ /* override */
+ ps.is_texbrush = false;
+ ps.is_maskbrush = false;
+ ps.do_masking = false;
+ orig_brush_size = BKE_brush_size_get(scene, ps.brush);
+ /* cover the whole image */
+ BKE_brush_size_set(scene, ps.brush, 32 * U.pixelsize);
+
+ /* so pixels are initialized with minimal info */
+ ps.tool = PAINT_TOOL_DRAW;
+
+ scene->toolsettings->imapaint.flag |= IMAGEPAINT_DRAWING;
+
+ ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_3D);
+
+ /* allocate and initialize spatial data structures */
+ project_paint_begin(C, &ps, false, 0);
+
+ if (ps.me_eval == NULL) {
+ BKE_brush_size_set(scene, ps.brush, orig_brush_size);
+ BKE_report(op->reports, RPT_ERROR, "Could not get valid evaluated mesh");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ float pos[2] = {0.0, 0.0};
+ float lastpos[2] = {0.0, 0.0};
+ int a;
+
+ project_paint_op(&ps, lastpos, pos);
+
+ project_image_refresh_tagged(&ps);
+
+ for (a = 0; a < ps.image_tot; a++) {
+ GPU_free_image(ps.projImages[a].ima);
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ps.projImages[a].ima);
+ }
+ }
+
+ project_paint_end(&ps);
+
+ scene->toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
+ BKE_brush_size_set(scene, ps.brush, orig_brush_size);
+
+ return OPERATOR_FINISHED;
}
void PAINT_OT_project_image(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Project Image";
- ot->idname = "PAINT_OT_project_image";
- ot->description = "Project an edited render from the active camera back onto the object";
+ /* identifiers */
+ ot->name = "Project Image";
+ ot->idname = "PAINT_OT_project_image";
+ ot->description = "Project an edited render from the active camera back onto the object";
- /* api callbacks */
- ot->invoke = WM_enum_search_invoke;
- ot->exec = texture_paint_camera_project_exec;
+ /* api callbacks */
+ ot->invoke = WM_enum_search_invoke;
+ ot->exec = texture_paint_camera_project_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_enum(ot->srna, "image", DummyRNA_NULL_items, 0, "Image", "");
- RNA_def_enum_funcs(prop, RNA_image_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ prop = RNA_def_enum(ot->srna, "image", DummyRNA_NULL_items, 0, "Image", "");
+ RNA_def_enum_funcs(prop, RNA_image_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
static bool texture_paint_image_from_view_poll(bContext *C)
{
- if (BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_VIEW3D, 0) == NULL) {
- CTX_wm_operator_poll_msg_set(C, "No 3D viewport found to create image from");
- return false;
- }
- return true;
+ if (BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_VIEW3D, 0) == NULL) {
+ CTX_wm_operator_poll_msg_set(C, "No 3D viewport found to create image from");
+ return false;
+ }
+ return true;
}
static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
{
- Image *image;
- ImBuf *ibuf;
- char filename[FILE_MAX];
-
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- ToolSettings *settings = scene->toolsettings;
- int w = settings->imapaint.screen_grab_size[0];
- int h = settings->imapaint.screen_grab_size[1];
- int maxsize;
- char err_out[256] = "unknown";
-
- ScrArea *sa = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_VIEW3D, 0);
- if (!sa) {
- BKE_report(op->reports, RPT_ERROR, "No 3D viewport found to create image from");
- return OPERATOR_CANCELLED;
- }
- View3D *v3d = sa->spacedata.first;
- ARegion *ar = BKE_area_find_region_active_win(sa);
- if (!ar) {
- BKE_report(op->reports, RPT_ERROR, "No 3D viewport found to create image from");
- return OPERATOR_CANCELLED;
- }
- RegionView3D *rv3d = ar->regiondata;
-
- RNA_string_get(op->ptr, "filepath", filename);
-
- maxsize = GPU_max_texture_size();
-
- if (w > maxsize) w = maxsize;
- if (h > maxsize) h = maxsize;
-
- ibuf = ED_view3d_draw_offscreen_imbuf(
- depsgraph, scene, v3d->shading.type,
- v3d, ar,
- w, h, IB_rect, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL,
- NULL, err_out);
- if (!ibuf) {
- /* Mostly happens when OpenGL offscreen buffer was failed to create, */
- /* but could be other reasons. Should be handled in the future. nazgul */
- BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer: %s", err_out);
- return OPERATOR_CANCELLED;
- }
-
- image = BKE_image_add_from_imbuf(bmain, ibuf, "image_view");
-
- /* Drop reference to ibuf so that the image owns it */
- IMB_freeImBuf(ibuf);
-
- if (image) {
- /* now for the trickiness. store the view projection here!
- * re-projection will reuse this */
- IDPropertyTemplate val;
- IDProperty *idgroup = IDP_GetProperties(&image->id, 1);
- IDProperty *view_data;
- bool is_ortho;
- float *array;
-
- val.array.len = PROJ_VIEW_DATA_SIZE;
- val.array.type = IDP_FLOAT;
- view_data = IDP_New(IDP_ARRAY, &val, PROJ_VIEW_DATA_ID);
-
- array = (float *)IDP_Array(view_data);
- memcpy(array, rv3d->winmat, sizeof(rv3d->winmat)); array += sizeof(rv3d->winmat) / sizeof(float);
- memcpy(array, rv3d->viewmat, sizeof(rv3d->viewmat)); array += sizeof(rv3d->viewmat) / sizeof(float);
- is_ortho = ED_view3d_clip_range_get(CTX_data_depsgraph(C), v3d, rv3d, &array[0], &array[1], true);
- /* using float for a bool is dodgy but since its an extra member in the array...
- * easier then adding a single bool prop */
- array[2] = is_ortho ? 1.0f : 0.0f;
-
- IDP_AddToGroup(idgroup, view_data);
- }
-
- return OPERATOR_FINISHED;
+ Image *image;
+ ImBuf *ibuf;
+ char filename[FILE_MAX];
+
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *settings = scene->toolsettings;
+ int w = settings->imapaint.screen_grab_size[0];
+ int h = settings->imapaint.screen_grab_size[1];
+ int maxsize;
+ char err_out[256] = "unknown";
+
+ ScrArea *sa = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_VIEW3D, 0);
+ if (!sa) {
+ BKE_report(op->reports, RPT_ERROR, "No 3D viewport found to create image from");
+ return OPERATOR_CANCELLED;
+ }
+ View3D *v3d = sa->spacedata.first;
+ ARegion *ar = BKE_area_find_region_active_win(sa);
+ if (!ar) {
+ BKE_report(op->reports, RPT_ERROR, "No 3D viewport found to create image from");
+ return OPERATOR_CANCELLED;
+ }
+ RegionView3D *rv3d = ar->regiondata;
+
+ RNA_string_get(op->ptr, "filepath", filename);
+
+ maxsize = GPU_max_texture_size();
+
+ if (w > maxsize)
+ w = maxsize;
+ if (h > maxsize)
+ h = maxsize;
+
+ ibuf = ED_view3d_draw_offscreen_imbuf(depsgraph,
+ scene,
+ v3d->shading.type,
+ v3d,
+ ar,
+ w,
+ h,
+ IB_rect,
+ V3D_OFSDRAW_NONE,
+ R_ALPHAPREMUL,
+ 0,
+ NULL,
+ NULL,
+ err_out);
+ if (!ibuf) {
+ /* Mostly happens when OpenGL offscreen buffer was failed to create, */
+ /* but could be other reasons. Should be handled in the future. nazgul */
+ BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer: %s", err_out);
+ return OPERATOR_CANCELLED;
+ }
+
+ image = BKE_image_add_from_imbuf(bmain, ibuf, "image_view");
+
+ /* Drop reference to ibuf so that the image owns it */
+ IMB_freeImBuf(ibuf);
+
+ if (image) {
+ /* now for the trickiness. store the view projection here!
+ * re-projection will reuse this */
+ IDPropertyTemplate val;
+ IDProperty *idgroup = IDP_GetProperties(&image->id, 1);
+ IDProperty *view_data;
+ bool is_ortho;
+ float *array;
+
+ val.array.len = PROJ_VIEW_DATA_SIZE;
+ val.array.type = IDP_FLOAT;
+ view_data = IDP_New(IDP_ARRAY, &val, PROJ_VIEW_DATA_ID);
+
+ array = (float *)IDP_Array(view_data);
+ memcpy(array, rv3d->winmat, sizeof(rv3d->winmat));
+ array += sizeof(rv3d->winmat) / sizeof(float);
+ memcpy(array, rv3d->viewmat, sizeof(rv3d->viewmat));
+ array += sizeof(rv3d->viewmat) / sizeof(float);
+ is_ortho = ED_view3d_clip_range_get(
+ CTX_data_depsgraph(C), v3d, rv3d, &array[0], &array[1], true);
+ /* using float for a bool is dodgy but since its an extra member in the array...
+ * easier then adding a single bool prop */
+ array[2] = is_ortho ? 1.0f : 0.0f;
+
+ IDP_AddToGroup(idgroup, view_data);
+ }
+
+ return OPERATOR_FINISHED;
}
void PAINT_OT_image_from_view(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Image from View";
- ot->idname = "PAINT_OT_image_from_view";
- ot->description = "Make an image from biggest 3D view for re-projection";
+ /* identifiers */
+ ot->name = "Image from View";
+ ot->idname = "PAINT_OT_image_from_view";
+ ot->description = "Make an image from biggest 3D view for re-projection";
- /* api callbacks */
- ot->exec = texture_paint_image_from_view_exec;
- ot->poll = texture_paint_image_from_view_poll;
+ /* api callbacks */
+ ot->exec = texture_paint_image_from_view_exec;
+ ot->poll = texture_paint_image_from_view_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
- RNA_def_string_file_name(ot->srna, "filepath", NULL, FILE_MAX, "File Path", "Name of the file");
+ RNA_def_string_file_name(ot->srna, "filepath", NULL, FILE_MAX, "File Path", "Name of the file");
}
/*********************************************
@@ -5953,462 +6158,476 @@ void PAINT_OT_image_from_view(wmOperatorType *ot)
void BKE_paint_data_warning(struct ReportList *reports, bool uvs, bool mat, bool tex, bool stencil)
{
- BKE_reportf(
- reports, RPT_WARNING, "Missing%s%s%s%s detected!",
- !uvs ? " UVs," : "",
- !mat ? " Materials," : "",
- !tex ? " Textures," : "",
- !stencil ? " Stencil," : ""
- );
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Missing%s%s%s%s detected!",
+ !uvs ? " UVs," : "",
+ !mat ? " Materials," : "",
+ !tex ? " Textures," : "",
+ !stencil ? " Stencil," : "");
}
/* Make sure that active object has a material,
* and assign UVs and image layers if they do not exist */
-bool BKE_paint_proj_mesh_data_check(Scene *scene, Object *ob, bool *uvs, bool *mat, bool *tex, bool *stencil)
+bool BKE_paint_proj_mesh_data_check(
+ Scene *scene, Object *ob, bool *uvs, bool *mat, bool *tex, bool *stencil)
{
- Mesh *me;
- int layernum;
- ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
- Brush *br = BKE_paint_brush(&imapaint->paint);
- bool hasmat = true;
- bool hastex = true;
- bool hasstencil = true;
- bool hasuvs = true;
-
- imapaint->missing_data = 0;
-
- BLI_assert(ob->type == OB_MESH);
-
- if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
- /* no material, add one */
- if (ob->totcol == 0) {
- hasmat = false;
- hastex = false;
- }
- 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);
-
- if (ma) {
- hasmat = true;
- if (!ma->texpaintslot) {
- /* refresh here just in case */
- BKE_texpaint_slot_refresh_cache(scene, ma);
-
- /* if still no slots, we have to add */
- if (ma->texpaintslot) {
- hastex = true;
- break;
- }
- }
- else {
- hastex = true;
- break;
- }
- }
- }
- }
- }
- else if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
- if (imapaint->canvas == NULL) {
- hastex = false;
- }
- }
-
- me = BKE_mesh_from_object(ob);
- layernum = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
-
- if (layernum == 0) {
- hasuvs = false;
- }
-
- /* Make sure we have a stencil to paint on! */
- if (br && br->imagepaint_tool == PAINT_TOOL_MASK) {
- imapaint->flag |= IMAGEPAINT_PROJECT_LAYER_STENCIL;
-
- if (imapaint->stencil == NULL) {
- hasstencil = false;
- }
- }
-
- if (!hasuvs) imapaint->missing_data |= IMAGEPAINT_MISSING_UVS;
- if (!hasmat) imapaint->missing_data |= IMAGEPAINT_MISSING_MATERIAL;
- if (!hastex) imapaint->missing_data |= IMAGEPAINT_MISSING_TEX;
- if (!hasstencil) imapaint->missing_data |= IMAGEPAINT_MISSING_STENCIL;
-
- if (uvs) {
- *uvs = hasuvs;
- }
- if (mat) {
- *mat = hasmat;
- }
- if (tex) {
- *tex = hastex;
- }
- if (stencil) {
- *stencil = hasstencil;
- }
-
- return hasuvs && hasmat && hastex && hasstencil;
+ Mesh *me;
+ int layernum;
+ ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
+ Brush *br = BKE_paint_brush(&imapaint->paint);
+ bool hasmat = true;
+ bool hastex = true;
+ bool hasstencil = true;
+ bool hasuvs = true;
+
+ imapaint->missing_data = 0;
+
+ BLI_assert(ob->type == OB_MESH);
+
+ if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
+ /* no material, add one */
+ if (ob->totcol == 0) {
+ hasmat = false;
+ hastex = false;
+ }
+ 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);
+
+ if (ma) {
+ hasmat = true;
+ if (!ma->texpaintslot) {
+ /* refresh here just in case */
+ BKE_texpaint_slot_refresh_cache(scene, ma);
+
+ /* if still no slots, we have to add */
+ if (ma->texpaintslot) {
+ hastex = true;
+ break;
+ }
+ }
+ else {
+ hastex = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
+ if (imapaint->canvas == NULL) {
+ hastex = false;
+ }
+ }
+
+ me = BKE_mesh_from_object(ob);
+ layernum = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
+
+ if (layernum == 0) {
+ hasuvs = false;
+ }
+
+ /* Make sure we have a stencil to paint on! */
+ if (br && br->imagepaint_tool == PAINT_TOOL_MASK) {
+ imapaint->flag |= IMAGEPAINT_PROJECT_LAYER_STENCIL;
+
+ if (imapaint->stencil == NULL) {
+ hasstencil = false;
+ }
+ }
+
+ if (!hasuvs)
+ imapaint->missing_data |= IMAGEPAINT_MISSING_UVS;
+ if (!hasmat)
+ imapaint->missing_data |= IMAGEPAINT_MISSING_MATERIAL;
+ if (!hastex)
+ imapaint->missing_data |= IMAGEPAINT_MISSING_TEX;
+ if (!hasstencil)
+ imapaint->missing_data |= IMAGEPAINT_MISSING_STENCIL;
+
+ if (uvs) {
+ *uvs = hasuvs;
+ }
+ if (mat) {
+ *mat = hasmat;
+ }
+ if (tex) {
+ *tex = hastex;
+ }
+ if (stencil) {
+ *stencil = hasstencil;
+ }
+
+ return hasuvs && hasmat && hastex && hasstencil;
}
/* Add layer operator */
enum {
- LAYER_BASE_COLOR,
- LAYER_SPECULAR,
- LAYER_ROUGHNESS,
- LAYER_METALLIC,
- LAYER_NORMAL,
- LAYER_BUMP,
- LAYER_DISPLACEMENT,
+ LAYER_BASE_COLOR,
+ LAYER_SPECULAR,
+ LAYER_ROUGHNESS,
+ LAYER_METALLIC,
+ LAYER_NORMAL,
+ LAYER_BUMP,
+ LAYER_DISPLACEMENT,
};
static const EnumPropertyItem layer_type_items[] = {
- {LAYER_BASE_COLOR, "BASE_COLOR", 0, "Base Color", ""},
- {LAYER_SPECULAR, "SPECULAR", 0, "Specular", ""},
- {LAYER_ROUGHNESS, "ROUGHNESS", 0, "Roughness", ""},
- {LAYER_METALLIC, "METALLIC", 0, "Metallic", ""},
- {LAYER_NORMAL, "NORMAL", 0, "Normal", ""},
- {LAYER_BUMP, "BUMP", 0, "Bump", ""},
- {LAYER_DISPLACEMENT, "DISPLACEMENT", 0, "Displacement", ""},
- {0, NULL, 0, NULL, NULL},
+ {LAYER_BASE_COLOR, "BASE_COLOR", 0, "Base Color", ""},
+ {LAYER_SPECULAR, "SPECULAR", 0, "Specular", ""},
+ {LAYER_ROUGHNESS, "ROUGHNESS", 0, "Roughness", ""},
+ {LAYER_METALLIC, "METALLIC", 0, "Metallic", ""},
+ {LAYER_NORMAL, "NORMAL", 0, "Normal", ""},
+ {LAYER_BUMP, "BUMP", 0, "Bump", ""},
+ {LAYER_DISPLACEMENT, "DISPLACEMENT", 0, "Displacement", ""},
+ {0, NULL, 0, NULL, NULL},
};
static Image *proj_paint_image_create(wmOperator *op, Main *bmain)
{
- Image *ima;
- float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
- char imagename[MAX_ID_NAME - 2] = "Material Diffuse Color";
- int width = 1024;
- int height = 1024;
- bool use_float = false;
- short gen_type = IMA_GENTYPE_BLANK;
- bool alpha = false;
-
- if (op) {
- width = RNA_int_get(op->ptr, "width");
- height = RNA_int_get(op->ptr, "height");
- use_float = RNA_boolean_get(op->ptr, "float");
- gen_type = RNA_enum_get(op->ptr, "generated_type");
- RNA_float_get_array(op->ptr, "color", color);
- alpha = RNA_boolean_get(op->ptr, "alpha");
- RNA_string_get(op->ptr, "name", imagename);
- }
- ima = BKE_image_add_generated(
- bmain, width, height, imagename, alpha ? 32 : 24, use_float,
- gen_type, color, false);
-
- return ima;
+ Image *ima;
+ float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ char imagename[MAX_ID_NAME - 2] = "Material Diffuse Color";
+ int width = 1024;
+ int height = 1024;
+ bool use_float = false;
+ short gen_type = IMA_GENTYPE_BLANK;
+ bool alpha = false;
+
+ if (op) {
+ width = RNA_int_get(op->ptr, "width");
+ height = RNA_int_get(op->ptr, "height");
+ use_float = RNA_boolean_get(op->ptr, "float");
+ gen_type = RNA_enum_get(op->ptr, "generated_type");
+ RNA_float_get_array(op->ptr, "color", color);
+ alpha = RNA_boolean_get(op->ptr, "alpha");
+ RNA_string_get(op->ptr, "name", imagename);
+ }
+ ima = BKE_image_add_generated(
+ bmain, width, height, imagename, alpha ? 32 : 24, use_float, gen_type, color, false);
+
+ return ima;
}
static void proj_paint_default_color(wmOperator *op, int type, Material *ma)
{
- if (RNA_struct_property_is_set(op->ptr, "color")) {
- return;
- }
-
- bNode *in_node = ntreeFindType(ma->nodetree, SH_NODE_BSDF_PRINCIPLED);
- if (in_node == NULL) {
- return;
- }
-
- float color[4];
-
- if (type >= LAYER_BASE_COLOR && type < LAYER_NORMAL) {
- /* Copy color from node, so result is unchanged after assigning textures. */
- bNodeSocket *in_sock = nodeFindSocket(in_node, SOCK_IN, layer_type_items[type].name);
-
- switch (in_sock->type) {
- case SOCK_FLOAT: {
- bNodeSocketValueFloat *socket_data = in_sock->default_value;
- copy_v3_fl(color, socket_data->value);
- color[3] = 1.0f;
- break;
- }
- case SOCK_VECTOR:
- case SOCK_RGBA: {
- bNodeSocketValueRGBA *socket_data = in_sock->default_value;
- copy_v3_v3(color, socket_data->value);
- color[3] = 1.0f;
- break;
- }
- default: {
- return;
- }
- }
- }
- else if (type == LAYER_NORMAL) {
- /* Neutral tangent space normal map. */
- rgba_float_args_set(color, 0.5f, 0.5f, 1.0f, 1.0f);
- }
- else if (ELEM(type, LAYER_BUMP, LAYER_DISPLACEMENT)) {
- /* Neutral displacement and bump map. */
- rgba_float_args_set(color, 0.5f, 0.5f, 0.5f, 1.0f);
- }
- else {
- return;
- }
-
- RNA_float_set_array(op->ptr, "color", color);
+ if (RNA_struct_property_is_set(op->ptr, "color")) {
+ return;
+ }
+
+ bNode *in_node = ntreeFindType(ma->nodetree, SH_NODE_BSDF_PRINCIPLED);
+ if (in_node == NULL) {
+ return;
+ }
+
+ float color[4];
+
+ if (type >= LAYER_BASE_COLOR && type < LAYER_NORMAL) {
+ /* Copy color from node, so result is unchanged after assigning textures. */
+ bNodeSocket *in_sock = nodeFindSocket(in_node, SOCK_IN, layer_type_items[type].name);
+
+ switch (in_sock->type) {
+ case SOCK_FLOAT: {
+ bNodeSocketValueFloat *socket_data = in_sock->default_value;
+ copy_v3_fl(color, socket_data->value);
+ color[3] = 1.0f;
+ break;
+ }
+ case SOCK_VECTOR:
+ case SOCK_RGBA: {
+ bNodeSocketValueRGBA *socket_data = in_sock->default_value;
+ copy_v3_v3(color, socket_data->value);
+ color[3] = 1.0f;
+ break;
+ }
+ default: {
+ return;
+ }
+ }
+ }
+ else if (type == LAYER_NORMAL) {
+ /* Neutral tangent space normal map. */
+ rgba_float_args_set(color, 0.5f, 0.5f, 1.0f, 1.0f);
+ }
+ else if (ELEM(type, LAYER_BUMP, LAYER_DISPLACEMENT)) {
+ /* Neutral displacement and bump map. */
+ rgba_float_args_set(color, 0.5f, 0.5f, 0.5f, 1.0f);
+ }
+ else {
+ return;
+ }
+
+ RNA_float_set_array(op->ptr, "color", color);
}
static bool proj_paint_add_slot(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- Scene *scene = CTX_data_scene(C);
- Material *ma;
- Image *ima = NULL;
-
- if (!ob)
- return false;
-
- ma = give_current_material(ob, ob->actcol);
+ Object *ob = ED_object_active_context(C);
+ Scene *scene = CTX_data_scene(C);
+ Material *ma;
+ Image *ima = NULL;
+
+ if (!ob)
+ return false;
+
+ ma = give_current_material(ob, ob->actcol);
- if (ma) {
- Main *bmain = CTX_data_main(C);
- int type = RNA_enum_get(op->ptr, "type");
+ if (ma) {
+ Main *bmain = CTX_data_main(C);
+ int type = RNA_enum_get(op->ptr, "type");
- bNode *imanode;
- bNodeTree *ntree = ma->nodetree;
+ bNode *imanode;
+ bNodeTree *ntree = ma->nodetree;
- if (!ntree) {
- ED_node_shader_default(C, &ma->id);
- ntree = ma->nodetree;
- }
+ if (!ntree) {
+ ED_node_shader_default(C, &ma->id);
+ ntree = ma->nodetree;
+ }
- ma->use_nodes = true;
+ ma->use_nodes = true;
- /* try to add an image node */
- imanode = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE);
+ /* try to add an image node */
+ imanode = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE);
- ima = proj_paint_image_create(op, bmain);
- imanode->id = &ima->id;
+ ima = proj_paint_image_create(op, bmain);
+ imanode->id = &ima->id;
- nodeSetActive(ntree, imanode);
+ nodeSetActive(ntree, imanode);
- /* Connect to first available principled bsdf node. */
- bNode *in_node = ntreeFindType(ntree, SH_NODE_BSDF_PRINCIPLED);
- bNode *out_node = imanode;
+ /* Connect to first available principled bsdf node. */
+ bNode *in_node = ntreeFindType(ntree, SH_NODE_BSDF_PRINCIPLED);
+ bNode *out_node = imanode;
- if (in_node != NULL) {
- bNodeSocket *out_sock = nodeFindSocket(out_node, SOCK_OUT, "Color");
- bNodeSocket *in_sock = NULL;
+ if (in_node != NULL) {
+ bNodeSocket *out_sock = nodeFindSocket(out_node, SOCK_OUT, "Color");
+ bNodeSocket *in_sock = NULL;
- if (type >= LAYER_BASE_COLOR && type < LAYER_NORMAL) {
- in_sock = nodeFindSocket(in_node, SOCK_IN, layer_type_items[type].name);
- }
- else if (type == LAYER_NORMAL) {
- bNode *nor_node;
- nor_node = nodeAddStaticNode(C, ntree, SH_NODE_NORMAL_MAP);
+ if (type >= LAYER_BASE_COLOR && type < LAYER_NORMAL) {
+ in_sock = nodeFindSocket(in_node, SOCK_IN, layer_type_items[type].name);
+ }
+ else if (type == LAYER_NORMAL) {
+ bNode *nor_node;
+ nor_node = nodeAddStaticNode(C, ntree, SH_NODE_NORMAL_MAP);
- in_sock = nodeFindSocket(nor_node, SOCK_IN, "Color");
- nodeAddLink(ntree, out_node, out_sock, nor_node, in_sock);
+ in_sock = nodeFindSocket(nor_node, SOCK_IN, "Color");
+ nodeAddLink(ntree, out_node, out_sock, nor_node, in_sock);
- in_sock = nodeFindSocket(in_node, SOCK_IN, "Normal");
- out_sock = nodeFindSocket(nor_node, SOCK_OUT, "Normal");
+ in_sock = nodeFindSocket(in_node, SOCK_IN, "Normal");
+ out_sock = nodeFindSocket(nor_node, SOCK_OUT, "Normal");
- out_node = nor_node;
- }
- else if (type == LAYER_BUMP) {
- bNode *bump_node;
- bump_node = nodeAddStaticNode(C, ntree, SH_NODE_BUMP);
+ out_node = nor_node;
+ }
+ else if (type == LAYER_BUMP) {
+ bNode *bump_node;
+ bump_node = nodeAddStaticNode(C, ntree, SH_NODE_BUMP);
- in_sock = nodeFindSocket(bump_node, SOCK_IN, "Height");
- nodeAddLink(ntree, out_node, out_sock, bump_node, in_sock);
+ in_sock = nodeFindSocket(bump_node, SOCK_IN, "Height");
+ nodeAddLink(ntree, out_node, out_sock, bump_node, in_sock);
- in_sock = nodeFindSocket(in_node, SOCK_IN, "Normal");
- out_sock = nodeFindSocket(bump_node, SOCK_OUT, "Normal");
+ in_sock = nodeFindSocket(in_node, SOCK_IN, "Normal");
+ out_sock = nodeFindSocket(bump_node, SOCK_OUT, "Normal");
- out_node = bump_node;
- }
- else if (type == LAYER_DISPLACEMENT) {
- /* Connect to the displacement output socket */
- in_node = ntreeFindType(ntree, SH_NODE_OUTPUT_MATERIAL);
+ out_node = bump_node;
+ }
+ else if (type == LAYER_DISPLACEMENT) {
+ /* Connect to the displacement output socket */
+ in_node = ntreeFindType(ntree, SH_NODE_OUTPUT_MATERIAL);
- if (in_node != NULL) {
- in_sock = nodeFindSocket(in_node, SOCK_IN, layer_type_items[type].name);
- }
- else {
- in_sock = NULL;
- }
- }
+ if (in_node != NULL) {
+ in_sock = nodeFindSocket(in_node, SOCK_IN, layer_type_items[type].name);
+ }
+ else {
+ in_sock = NULL;
+ }
+ }
- if (type > LAYER_BASE_COLOR) {
- /* This is a "non color data" image */
- NodeTexImage *tex = imanode->storage;
- tex->color_space = SHD_COLORSPACE_NONE;
- }
+ if (type > LAYER_BASE_COLOR) {
+ /* This is a "non color data" image */
+ NodeTexImage *tex = imanode->storage;
+ tex->color_space = SHD_COLORSPACE_NONE;
+ }
- /* Check if the socket in already connected to something */
- bNodeLink *link = in_sock ? in_sock->link : NULL;
- if (in_sock != NULL && link == NULL) {
- nodeAddLink(ntree, out_node, out_sock, in_node, in_sock);
+ /* Check if the socket in already connected to something */
+ bNodeLink *link = in_sock ? in_sock->link : NULL;
+ if (in_sock != NULL && link == NULL) {
+ nodeAddLink(ntree, out_node, out_sock, in_node, in_sock);
- nodePositionRelative(out_node, in_node, out_sock, in_sock);
- }
- }
+ nodePositionRelative(out_node, in_node, out_sock, in_sock);
+ }
+ }
- ntreeUpdateTree(CTX_data_main(C), ntree);
- /* In case we added more than one node, position them too. */
- nodePositionPropagate(out_node);
+ ntreeUpdateTree(CTX_data_main(C), ntree);
+ /* In case we added more than one node, position them too. */
+ nodePositionPropagate(out_node);
- if (ima) {
- BKE_texpaint_slot_refresh_cache(scene, ma);
- BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE);
- WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
- }
+ if (ima) {
+ BKE_texpaint_slot_refresh_cache(scene, ma);
+ BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE);
+ WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
+ }
- DEG_id_tag_update(&ntree->id, 0);
- DEG_id_tag_update(&ma->id, ID_RECALC_SHADING);
- ED_area_tag_redraw(CTX_wm_area(C));
+ DEG_id_tag_update(&ntree->id, 0);
+ DEG_id_tag_update(&ma->id, ID_RECALC_SHADING);
+ ED_area_tag_redraw(CTX_wm_area(C));
- BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
static int get_texture_layer_type(wmOperator *op, const char *prop_name)
{
- int type_value = RNA_enum_get(op->ptr, prop_name);
- int type = RNA_enum_from_value(layer_type_items, type_value);
- BLI_assert(type != -1);
- return type;
+ int type_value = RNA_enum_get(op->ptr, prop_name);
+ int type = RNA_enum_from_value(layer_type_items, type_value);
+ BLI_assert(type != -1);
+ return type;
}
static Material *get_or_create_current_material(bContext *C, Object *ob)
{
- Material *ma = give_current_material(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);
- }
- return ma;
+ Material *ma = give_current_material(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);
+ }
+ return ma;
}
static int texture_paint_add_texture_paint_slot_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- Material *ma = get_or_create_current_material(C, ob);
-
- int type = get_texture_layer_type(op, "type");
- proj_paint_default_color(op, type, ma);
-
- if (proj_paint_add_slot(C, op)) {
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Object *ob = ED_object_active_context(C);
+ Material *ma = get_or_create_current_material(C, ob);
+
+ int type = get_texture_layer_type(op, "type");
+ proj_paint_default_color(op, type, ma);
+
+ if (proj_paint_add_slot(C, op)) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
-static void get_default_texture_layer_name_for_object(Object *ob, int texture_type, char *dst, int dst_length)
+static void get_default_texture_layer_name_for_object(Object *ob,
+ int texture_type,
+ char *dst,
+ int dst_length)
{
- Material *ma = give_current_material(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);
+ Material *ma = give_current_material(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);
}
-static int texture_paint_add_texture_paint_slot_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int texture_paint_add_texture_paint_slot_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
{
- /* Get material and default color to display in the popup. */
- Object *ob = ED_object_active_context(C);
- Material *ma = get_or_create_current_material(C, ob);
+ /* Get material and default color to display in the popup. */
+ Object *ob = ED_object_active_context(C);
+ Material *ma = get_or_create_current_material(C, ob);
- int type = get_texture_layer_type(op, "type");
- proj_paint_default_color(op, type, ma);
+ int type = get_texture_layer_type(op, "type");
+ proj_paint_default_color(op, type, ma);
- char imagename[MAX_ID_NAME - 2];
- get_default_texture_layer_name_for_object(ob, type, (char *)&imagename, sizeof(imagename));
- RNA_string_set(op->ptr, "name", imagename);
+ char imagename[MAX_ID_NAME - 2];
+ 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, 100);
}
#define IMA_DEF_NAME N_("Untitled")
-
void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot)
{
- PropertyRNA *prop;
- static float default_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
-
- /* identifiers */
- ot->name = "Add Texture Paint Slot";
- ot->description = "Add a texture paint slot";
- ot->idname = "PAINT_OT_add_texture_paint_slot";
-
- /* 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;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "type", layer_type_items, 0, "Type", "Merge method to use");
- RNA_def_property_flag(prop, PROP_HIDDEN);
- RNA_def_string(ot->srna, "name", IMA_DEF_NAME, MAX_ID_NAME - 2, "Name", "Image data-block name");
- prop = RNA_def_int(ot->srna, "width", 1024, 1, INT_MAX, "Width", "Image width", 1, 16384);
- RNA_def_property_subtype(prop, PROP_PIXEL);
- prop = RNA_def_int(ot->srna, "height", 1024, 1, INT_MAX, "Height", "Image height", 1, 16384);
- RNA_def_property_subtype(prop, PROP_PIXEL);
- prop = RNA_def_float_color(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_enum(ot->srna, "generated_type", rna_enum_image_generated_type_items, IMA_GENTYPE_BLANK,
- "Generated Type", "Fill the image with a grid for UV map testing");
- RNA_def_boolean(ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth");
+ PropertyRNA *prop;
+ static float default_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+
+ /* identifiers */
+ ot->name = "Add Texture Paint Slot";
+ ot->description = "Add a texture paint slot";
+ ot->idname = "PAINT_OT_add_texture_paint_slot";
+
+ /* 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;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna, "type", layer_type_items, 0, "Type", "Merge method to use");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "name", IMA_DEF_NAME, MAX_ID_NAME - 2, "Name", "Image data-block name");
+ prop = RNA_def_int(ot->srna, "width", 1024, 1, INT_MAX, "Width", "Image width", 1, 16384);
+ RNA_def_property_subtype(prop, PROP_PIXEL);
+ prop = RNA_def_int(ot->srna, "height", 1024, 1, INT_MAX, "Height", "Image height", 1, 16384);
+ RNA_def_property_subtype(prop, PROP_PIXEL);
+ prop = RNA_def_float_color(
+ 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_enum(ot->srna,
+ "generated_type",
+ rna_enum_image_generated_type_items,
+ IMA_GENTYPE_BLANK,
+ "Generated Type",
+ "Fill the image with a grid for UV map testing");
+ RNA_def_boolean(
+ ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth");
}
static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op))
{
- /* no checks here, poll function does them for us */
- Main *bmain = CTX_data_main(C);
- Object *ob = CTX_data_active_object(C);
- Scene *scene = CTX_data_scene(C);
+ /* no checks here, poll function does them for us */
+ Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
- ED_uvedit_add_simple_uvs(bmain, scene, ob);
+ ED_uvedit_add_simple_uvs(bmain, scene, ob);
- BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
- DEG_id_tag_update(ob->data, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, scene);
- return OPERATOR_FINISHED;
+ DEG_id_tag_update(ob->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, scene);
+ return OPERATOR_FINISHED;
}
static bool add_simple_uvs_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if (!ob || ob->type != OB_MESH || ob->mode != OB_MODE_TEXTURE_PAINT) {
- return false;
- }
- return true;
+ if (!ob || ob->type != OB_MESH || ob->mode != OB_MODE_TEXTURE_PAINT) {
+ return false;
+ }
+ return true;
}
void PAINT_OT_add_simple_uvs(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add simple UVs";
- ot->description = "Add cube map uvs on mesh";
- ot->idname = "PAINT_OT_add_simple_uvs";
+ /* identifiers */
+ ot->name = "Add simple UVs";
+ ot->description = "Add cube map uvs on mesh";
+ ot->idname = "PAINT_OT_add_simple_uvs";
- /* api callbacks */
- ot->exec = add_simple_uvs_exec;
- ot->poll = add_simple_uvs_poll;
+ /* api callbacks */
+ ot->exec = add_simple_uvs_exec;
+ ot->poll = add_simple_uvs_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_undo.c b/source/blender/editors/sculpt_paint/paint_image_undo.c
index 8c4bfe00654..68abdfbf95b 100644
--- a/source/blender/editors/sculpt_paint/paint_image_undo.c
+++ b/source/blender/editors/sculpt_paint/paint_image_undo.c
@@ -55,26 +55,26 @@
* \{ */
typedef struct UndoImageTile {
- struct UndoImageTile *next, *prev;
+ struct UndoImageTile *next, *prev;
- char ibufname[IMB_FILENAME_SIZE];
+ char ibufname[IMB_FILENAME_SIZE];
- union {
- float *fp;
- unsigned int *uint;
- void *pt;
- } rect;
+ union {
+ float *fp;
+ unsigned int *uint;
+ void *pt;
+ } rect;
- unsigned short *mask;
+ unsigned short *mask;
- int x, y;
+ int x, y;
- Image *ima;
- short source, use_float;
- char gen_type;
- bool valid;
+ Image *ima;
+ short source, use_float;
+ char gen_type;
+ bool valid;
- size_t undo_size;
+ size_t undo_size;
} UndoImageTile;
/* this is a static resource for non-globality,
@@ -84,281 +84,305 @@ static SpinLock undolock;
void image_undo_init_locks(void)
{
- BLI_spin_init(&undolock);
+ BLI_spin_init(&undolock);
}
void image_undo_end_locks(void)
{
- BLI_spin_end(&undolock);
+ BLI_spin_end(&undolock);
}
/* UNDO */
typedef enum {
- COPY = 0,
- RESTORE = 1,
- RESTORE_COPY = 2,
+ COPY = 0,
+ RESTORE = 1,
+ RESTORE_COPY = 2,
} CopyMode;
static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, CopyMode mode)
{
- if (mode == COPY) {
- /* copy or swap contents of tile->rect and region in ibuf->rect */
- IMB_rectcpy(
- tmpibuf, ibuf, 0, 0, tile->x * IMAPAINT_TILE_SIZE,
- tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
-
- if (ibuf->rect_float) {
- SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
- }
- else {
- SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
- }
- }
- else {
- if (mode == RESTORE_COPY) {
- IMB_rectcpy(
- tmpibuf, ibuf, 0, 0, tile->x * IMAPAINT_TILE_SIZE,
- tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
- }
- /* swap to the tmpbuf for easy copying */
- if (ibuf->rect_float) {
- SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
- }
- else {
- SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
- }
-
- IMB_rectcpy(
- ibuf, tmpibuf, tile->x * IMAPAINT_TILE_SIZE,
- tile->y * IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
-
- if (mode == RESTORE) {
- if (ibuf->rect_float) {
- SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
- }
- else {
- SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
- }
- }
- }
+ if (mode == COPY) {
+ /* copy or swap contents of tile->rect and region in ibuf->rect */
+ IMB_rectcpy(tmpibuf,
+ ibuf,
+ 0,
+ 0,
+ tile->x * IMAPAINT_TILE_SIZE,
+ tile->y * IMAPAINT_TILE_SIZE,
+ IMAPAINT_TILE_SIZE,
+ IMAPAINT_TILE_SIZE);
+
+ if (ibuf->rect_float) {
+ SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
+ }
+ else {
+ SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
+ }
+ }
+ else {
+ if (mode == RESTORE_COPY) {
+ IMB_rectcpy(tmpibuf,
+ ibuf,
+ 0,
+ 0,
+ tile->x * IMAPAINT_TILE_SIZE,
+ tile->y * IMAPAINT_TILE_SIZE,
+ IMAPAINT_TILE_SIZE,
+ IMAPAINT_TILE_SIZE);
+ }
+ /* swap to the tmpbuf for easy copying */
+ if (ibuf->rect_float) {
+ SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
+ }
+ else {
+ SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
+ }
+
+ IMB_rectcpy(ibuf,
+ tmpibuf,
+ tile->x * IMAPAINT_TILE_SIZE,
+ tile->y * IMAPAINT_TILE_SIZE,
+ 0,
+ 0,
+ IMAPAINT_TILE_SIZE,
+ IMAPAINT_TILE_SIZE);
+
+ if (mode == RESTORE) {
+ if (ibuf->rect_float) {
+ SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
+ }
+ else {
+ SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
+ }
+ }
+ }
}
-void *image_undo_find_tile(
- ListBase *undo_tiles,
- Image *ima, ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask, bool validate)
+void *image_undo_find_tile(ListBase *undo_tiles,
+ Image *ima,
+ ImBuf *ibuf,
+ int x_tile,
+ int y_tile,
+ unsigned short **mask,
+ bool validate)
{
- UndoImageTile *tile;
- short use_float = ibuf->rect_float ? 1 : 0;
-
- for (tile = undo_tiles->first; tile; tile = tile->next) {
- if (tile->x == x_tile && tile->y == y_tile && ima->gen_type == tile->gen_type && ima->source == tile->source) {
- if (tile->use_float == use_float) {
- if (STREQ(tile->ibufname, ibuf->name)) {
- if (mask) {
- /* allocate mask if requested */
- if (!tile->mask) {
- tile->mask = MEM_callocN(
- sizeof(unsigned short) * IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE,
- "UndoImageTile.mask");
- }
-
- *mask = tile->mask;
- }
- if (validate) {
- tile->valid = true;
- }
- return tile->rect.pt;
- }
- }
- }
- }
-
- return NULL;
+ UndoImageTile *tile;
+ short use_float = ibuf->rect_float ? 1 : 0;
+
+ for (tile = undo_tiles->first; tile; tile = tile->next) {
+ if (tile->x == x_tile && tile->y == y_tile && ima->gen_type == tile->gen_type &&
+ ima->source == tile->source) {
+ if (tile->use_float == use_float) {
+ if (STREQ(tile->ibufname, ibuf->name)) {
+ if (mask) {
+ /* allocate mask if requested */
+ if (!tile->mask) {
+ tile->mask = MEM_callocN(sizeof(unsigned short) * IMAPAINT_TILE_SIZE *
+ IMAPAINT_TILE_SIZE,
+ "UndoImageTile.mask");
+ }
+
+ *mask = tile->mask;
+ }
+ if (validate) {
+ tile->valid = true;
+ }
+ return tile->rect.pt;
+ }
+ }
+ }
+ }
+
+ return NULL;
}
-void *image_undo_push_tile(
- ListBase *undo_tiles,
- Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile,
- unsigned short **mask, bool **valid, bool proj, bool find_prev)
+void *image_undo_push_tile(ListBase *undo_tiles,
+ Image *ima,
+ ImBuf *ibuf,
+ ImBuf **tmpibuf,
+ int x_tile,
+ int y_tile,
+ unsigned short **mask,
+ bool **valid,
+ bool proj,
+ bool find_prev)
{
- UndoImageTile *tile;
- int allocsize;
- short use_float = ibuf->rect_float ? 1 : 0;
- void *data;
-
- /* check if tile is already pushed */
-
- /* in projective painting we keep accounting of tiles, so if we need one pushed, just push! */
- if (find_prev) {
- data = image_undo_find_tile(undo_tiles, ima, ibuf, x_tile, y_tile, mask, true);
- if (data) {
- return data;
- }
- }
-
- if (*tmpibuf == NULL) {
- *tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat | IB_rect);
- }
-
- tile = MEM_callocN(sizeof(UndoImageTile), "UndoImageTile");
- tile->x = x_tile;
- tile->y = y_tile;
-
- /* add mask explicitly here */
- if (mask) {
- *mask = tile->mask = MEM_callocN(
- sizeof(unsigned short) * IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE,
- "UndoImageTile.mask");
- }
- allocsize = IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE * 4;
- allocsize *= (ibuf->rect_float) ? sizeof(float) : sizeof(char);
- tile->rect.pt = MEM_mapallocN(allocsize, "UndeImageTile.rect");
-
- BLI_strncpy(tile->ibufname, ibuf->name, sizeof(tile->ibufname));
-
- tile->gen_type = ima->gen_type;
- tile->source = ima->source;
- tile->use_float = use_float;
- tile->valid = true;
- tile->ima = ima;
-
- if (valid) {
- *valid = &tile->valid;
- }
- undo_copy_tile(tile, *tmpibuf, ibuf, COPY);
-
- if (proj) {
- BLI_spin_lock(&undolock);
- }
- BLI_addtail(undo_tiles, tile);
-
- if (proj) {
- BLI_spin_unlock(&undolock);
- }
- return tile->rect.pt;
+ UndoImageTile *tile;
+ int allocsize;
+ short use_float = ibuf->rect_float ? 1 : 0;
+ void *data;
+
+ /* check if tile is already pushed */
+
+ /* in projective painting we keep accounting of tiles, so if we need one pushed, just push! */
+ if (find_prev) {
+ data = image_undo_find_tile(undo_tiles, ima, ibuf, x_tile, y_tile, mask, true);
+ if (data) {
+ return data;
+ }
+ }
+
+ if (*tmpibuf == NULL) {
+ *tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat | IB_rect);
+ }
+
+ tile = MEM_callocN(sizeof(UndoImageTile), "UndoImageTile");
+ tile->x = x_tile;
+ tile->y = y_tile;
+
+ /* add mask explicitly here */
+ if (mask) {
+ *mask = tile->mask = MEM_callocN(
+ sizeof(unsigned short) * IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE, "UndoImageTile.mask");
+ }
+ allocsize = IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE * 4;
+ allocsize *= (ibuf->rect_float) ? sizeof(float) : sizeof(char);
+ tile->rect.pt = MEM_mapallocN(allocsize, "UndeImageTile.rect");
+
+ BLI_strncpy(tile->ibufname, ibuf->name, sizeof(tile->ibufname));
+
+ tile->gen_type = ima->gen_type;
+ tile->source = ima->source;
+ tile->use_float = use_float;
+ tile->valid = true;
+ tile->ima = ima;
+
+ if (valid) {
+ *valid = &tile->valid;
+ }
+ undo_copy_tile(tile, *tmpibuf, ibuf, COPY);
+
+ if (proj) {
+ BLI_spin_lock(&undolock);
+ }
+ BLI_addtail(undo_tiles, tile);
+
+ if (proj) {
+ BLI_spin_unlock(&undolock);
+ }
+ return tile->rect.pt;
}
void image_undo_remove_masks(void)
{
- ListBase *undo_tiles = ED_image_undo_get_tiles();
- UndoImageTile *tile;
-
- for (tile = undo_tiles->first; tile; tile = tile->next) {
- if (tile->mask) {
- MEM_freeN(tile->mask);
- tile->mask = NULL;
- }
- }
+ ListBase *undo_tiles = ED_image_undo_get_tiles();
+ UndoImageTile *tile;
+
+ for (tile = undo_tiles->first; tile; tile = tile->next) {
+ if (tile->mask) {
+ MEM_freeN(tile->mask);
+ tile->mask = NULL;
+ }
+ }
}
static void image_undo_restore_runtime(ListBase *lb)
{
- ImBuf *ibuf, *tmpibuf;
- UndoImageTile *tile;
+ ImBuf *ibuf, *tmpibuf;
+ UndoImageTile *tile;
- tmpibuf = IMB_allocImBuf(
- IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32,
- IB_rectfloat | IB_rect);
+ tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat | IB_rect);
- for (tile = lb->first; tile; tile = tile->next) {
- Image *ima = tile->ima;
- ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ for (tile = lb->first; tile; tile = tile->next) {
+ Image *ima = tile->ima;
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
- undo_copy_tile(tile, tmpibuf, ibuf, RESTORE);
+ undo_copy_tile(tile, tmpibuf, ibuf, RESTORE);
- GPU_free_image(ima); /* force OpenGL reload (maybe partial update will operate better?) */
- if (ibuf->rect_float) {
- ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
- }
- if (ibuf->mipmap[0]) {
- ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */
- }
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ GPU_free_image(ima); /* force OpenGL reload (maybe partial update will operate better?) */
+ if (ibuf->rect_float) {
+ ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
+ }
+ if (ibuf->mipmap[0]) {
+ ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */
+ }
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
- IMB_freeImBuf(tmpibuf);
+ IMB_freeImBuf(tmpibuf);
}
static void image_undo_restore_list(ListBase *lb, struct UndoIDPtrMap *id_map)
{
- ImBuf *tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat | IB_rect);
+ ImBuf *tmpibuf = IMB_allocImBuf(
+ IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat | IB_rect);
- /* Store last found image. */
- ID *image_prev[2] = {NULL};
+ /* Store last found image. */
+ ID *image_prev[2] = {NULL};
- for (UndoImageTile *tile = lb->first; tile; tile = tile->next) {
- short use_float;
+ for (UndoImageTile *tile = lb->first; tile; tile = tile->next) {
+ short use_float;
- Image *ima = (Image *)BKE_undosys_ID_map_lookup_with_prev(id_map, &tile->ima->id, image_prev);
+ Image *ima = (Image *)BKE_undosys_ID_map_lookup_with_prev(id_map, &tile->ima->id, image_prev);
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
- if (ima && ibuf && !STREQ(tile->ibufname, ibuf->name)) {
- /* current ImBuf filename was changed, probably current frame
- * was changed when painting on image sequence, rather than storing
- * full image user (which isn't so obvious, btw) try to find ImBuf with
- * matched file name in list of already loaded images */
+ if (ima && ibuf && !STREQ(tile->ibufname, ibuf->name)) {
+ /* current ImBuf filename was changed, probably current frame
+ * was changed when painting on image sequence, rather than storing
+ * full image user (which isn't so obvious, btw) try to find ImBuf with
+ * matched file name in list of already loaded images */
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_release_ibuf(ima, ibuf, NULL);
- ibuf = BKE_image_get_ibuf_with_name(ima, tile->ibufname);
- }
+ ibuf = BKE_image_get_ibuf_with_name(ima, tile->ibufname);
+ }
- if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- continue;
- }
+ if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ continue;
+ }
- if (ima->gen_type != tile->gen_type || ima->source != tile->source) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- continue;
- }
+ if (ima->gen_type != tile->gen_type || ima->source != tile->source) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ continue;
+ }
- use_float = ibuf->rect_float ? 1 : 0;
+ use_float = ibuf->rect_float ? 1 : 0;
- if (use_float != tile->use_float) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- continue;
- }
+ if (use_float != tile->use_float) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ continue;
+ }
- undo_copy_tile(tile, tmpibuf, ibuf, RESTORE_COPY);
+ undo_copy_tile(tile, tmpibuf, ibuf, RESTORE_COPY);
- GPU_free_image(ima); /* force OpenGL reload */
- if (ibuf->rect_float) {
- ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
- }
- if (ibuf->mipmap[0]) {
- ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */
- }
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ GPU_free_image(ima); /* force OpenGL reload */
+ if (ibuf->rect_float) {
+ ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
+ }
+ if (ibuf->mipmap[0]) {
+ ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */
+ }
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
- DEG_id_tag_update(&ima->id, 0);
+ DEG_id_tag_update(&ima->id, 0);
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
- IMB_freeImBuf(tmpibuf);
+ IMB_freeImBuf(tmpibuf);
}
static void image_undo_free_list(ListBase *lb)
{
- for (UndoImageTile *tile = lb->first, *tile_next; tile; tile = tile_next) {
- tile_next = tile->next;
- MEM_freeN(tile->rect.pt);
- MEM_freeN(tile);
- }
+ for (UndoImageTile *tile = lb->first, *tile_next; tile; tile = tile_next) {
+ tile_next = tile->next;
+ MEM_freeN(tile->rect.pt);
+ MEM_freeN(tile);
+ }
}
static void image_undo_invalidate(void)
{
- UndoImageTile *tile;
- ListBase *lb = ED_image_undo_get_tiles();
+ UndoImageTile *tile;
+ ListBase *lb = ED_image_undo_get_tiles();
- for (tile = lb->first; tile; tile = tile->next) {
- tile->valid = false;
- }
+ for (tile = lb->first; tile; tile = tile->next) {
+ tile->valid = false;
+ }
}
/** \} */
@@ -368,258 +392,260 @@ static void image_undo_invalidate(void)
* \{ */
typedef struct ImageUndoStep {
- UndoStep step;
- ListBase tiles;
- bool is_encode_init;
- ePaintMode paint_mode;
+ UndoStep step;
+ ListBase tiles;
+ bool is_encode_init;
+ ePaintMode paint_mode;
- /* Use for all ID lookups (can be NULL). */
- struct UndoIDPtrMap *id_map;
+ /* Use for all ID lookups (can be NULL). */
+ struct UndoIDPtrMap *id_map;
} ImageUndoStep;
static void image_undosys_step_encode_store_ids(ImageUndoStep *us)
{
- us->id_map = BKE_undosys_ID_map_create();
+ us->id_map = BKE_undosys_ID_map_create();
- ID *image_prev = NULL;
- for (UndoImageTile *tile = us->tiles.first; tile; tile = tile->next) {
- BKE_undosys_ID_map_add_with_prev(us->id_map, &tile->ima->id, &image_prev);
- }
+ ID *image_prev = NULL;
+ for (UndoImageTile *tile = us->tiles.first; tile; tile = tile->next) {
+ BKE_undosys_ID_map_add_with_prev(us->id_map, &tile->ima->id, &image_prev);
+ }
}
/* Restore at runtime. */
#if 0
static void paint_undosys_step_decode_restore_ids(ImageUndoStep *us)
{
- ID *image_prev[2] = {NULL};
- for (UndoImageTile *tile = us->tiles.first; tile; tile = tile->next) {
- tile->ima = (Image *)BKE_undosys_ID_map_lookup_with_prev(us->id_map, &tile->ima->id, image_prev);
- }
+ ID *image_prev[2] = {NULL};
+ for (UndoImageTile *tile = us->tiles.first; tile; tile = tile->next) {
+ tile->ima = (Image *)BKE_undosys_ID_map_lookup_with_prev(us->id_map, &tile->ima->id, image_prev);
+ }
}
#endif
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;
- if ((obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) ||
- (sima->mode == SI_MODE_PAINT))
- {
- return true;
- }
- }
- else {
- if (obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) {
- return true;
- }
- }
- return false;
+ 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;
+ if ((obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) || (sima->mode == SI_MODE_PAINT)) {
+ return true;
+ }
+ }
+ else {
+ if (obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) {
+ return true;
+ }
+ }
+ return false;
}
static void image_undosys_step_encode_init(struct bContext *UNUSED(C), UndoStep *us_p)
{
- ImageUndoStep *us = (ImageUndoStep *)us_p;
- /* dummy, memory is cleared anyway. */
- us->is_encode_init = true;
- BLI_listbase_clear(&us->tiles);
+ ImageUndoStep *us = (ImageUndoStep *)us_p;
+ /* dummy, memory is cleared anyway. */
+ us->is_encode_init = true;
+ BLI_listbase_clear(&us->tiles);
}
-static bool image_undosys_step_encode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p)
+static bool image_undosys_step_encode(struct bContext *C,
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p)
{
- /* dummy, encoding is done along the way by adding tiles
- * to the current 'ImageUndoStep' added by encode_init. */
- ImageUndoStep *us = (ImageUndoStep *)us_p;
-
- BLI_assert(us->step.data_size == 0);
-
- int allocsize = IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE * 4;
-
- if (us->is_encode_init) {
- /* first dispose of invalid tiles (may happen due to drag dot for instance) */
- for (UndoImageTile *tile = us->tiles.first; tile;) {
- if (!tile->valid) {
- UndoImageTile *tmp_tile = tile->next;
- MEM_freeN(tile->rect.pt);
- BLI_freelinkN(&us->tiles, tile);
- tile = tmp_tile;
- }
- else {
- us->step.data_size += allocsize * ((tile->use_float) ? sizeof(float) : sizeof(char));
- tile = tile->next;
- }
- }
- }
- else {
- /* Happens when switching modes. */
- ePaintMode paint_mode = BKE_paintmode_get_active_from_context(C);
- BLI_assert(ELEM(paint_mode, PAINT_MODE_TEXTURE_2D, PAINT_MODE_TEXTURE_3D));
- us->paint_mode = paint_mode;
- }
-
- image_undosys_step_encode_store_ids(us);
-
- us_p->is_applied = true;
-
- return true;
+ /* dummy, encoding is done along the way by adding tiles
+ * to the current 'ImageUndoStep' added by encode_init. */
+ ImageUndoStep *us = (ImageUndoStep *)us_p;
+
+ BLI_assert(us->step.data_size == 0);
+
+ int allocsize = IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE * 4;
+
+ if (us->is_encode_init) {
+ /* first dispose of invalid tiles (may happen due to drag dot for instance) */
+ for (UndoImageTile *tile = us->tiles.first; tile;) {
+ if (!tile->valid) {
+ UndoImageTile *tmp_tile = tile->next;
+ MEM_freeN(tile->rect.pt);
+ BLI_freelinkN(&us->tiles, tile);
+ tile = tmp_tile;
+ }
+ else {
+ us->step.data_size += allocsize * ((tile->use_float) ? sizeof(float) : sizeof(char));
+ tile = tile->next;
+ }
+ }
+ }
+ else {
+ /* Happens when switching modes. */
+ ePaintMode paint_mode = BKE_paintmode_get_active_from_context(C);
+ BLI_assert(ELEM(paint_mode, PAINT_MODE_TEXTURE_2D, PAINT_MODE_TEXTURE_3D));
+ us->paint_mode = paint_mode;
+ }
+
+ image_undosys_step_encode_store_ids(us);
+
+ us_p->is_applied = true;
+
+ return true;
}
-
static void image_undosys_step_decode_undo_impl(ImageUndoStep *us)
{
- BLI_assert(us->step.is_applied == true);
- image_undo_restore_list(&us->tiles, us->id_map);
- us->step.is_applied = false;
+ BLI_assert(us->step.is_applied == true);
+ image_undo_restore_list(&us->tiles, us->id_map);
+ us->step.is_applied = false;
}
static void image_undosys_step_decode_redo_impl(ImageUndoStep *us)
{
- BLI_assert(us->step.is_applied == false);
- image_undo_restore_list(&us->tiles, us->id_map);
- us->step.is_applied = true;
+ BLI_assert(us->step.is_applied == false);
+ image_undo_restore_list(&us->tiles, us->id_map);
+ us->step.is_applied = true;
}
static void image_undosys_step_decode_undo(ImageUndoStep *us)
{
- ImageUndoStep *us_iter = us;
- while (us_iter->step.next && (us_iter->step.next->type == us_iter->step.type)) {
- if (us_iter->step.next->is_applied == false) {
- break;
- }
- us_iter = (ImageUndoStep *)us_iter->step.next;
- }
- while (us_iter != us) {
- image_undosys_step_decode_undo_impl(us_iter);
- us_iter = (ImageUndoStep *)us_iter->step.prev;
- }
+ ImageUndoStep *us_iter = us;
+ while (us_iter->step.next && (us_iter->step.next->type == us_iter->step.type)) {
+ if (us_iter->step.next->is_applied == false) {
+ break;
+ }
+ us_iter = (ImageUndoStep *)us_iter->step.next;
+ }
+ while (us_iter != us) {
+ image_undosys_step_decode_undo_impl(us_iter);
+ us_iter = (ImageUndoStep *)us_iter->step.prev;
+ }
}
static void image_undosys_step_decode_redo(ImageUndoStep *us)
{
- ImageUndoStep *us_iter = us;
- while (us_iter->step.prev && (us_iter->step.prev->type == us_iter->step.type)) {
- if (us_iter->step.prev->is_applied == true) {
- break;
- }
- us_iter = (ImageUndoStep *)us_iter->step.prev;
- }
- while (us_iter && (us_iter->step.is_applied == false)) {
- image_undosys_step_decode_redo_impl(us_iter);
- if (us_iter == us) {
- break;
- }
- us_iter = (ImageUndoStep *)us_iter->step.next;
- }
+ ImageUndoStep *us_iter = us;
+ while (us_iter->step.prev && (us_iter->step.prev->type == us_iter->step.type)) {
+ if (us_iter->step.prev->is_applied == true) {
+ break;
+ }
+ us_iter = (ImageUndoStep *)us_iter->step.prev;
+ }
+ while (us_iter && (us_iter->step.is_applied == false)) {
+ image_undosys_step_decode_redo_impl(us_iter);
+ if (us_iter == us) {
+ break;
+ }
+ us_iter = (ImageUndoStep *)us_iter->step.next;
+ }
}
-static void image_undosys_step_decode(struct bContext *C, struct Main *bmain, UndoStep *us_p, int dir)
+static void image_undosys_step_decode(struct bContext *C,
+ struct Main *bmain,
+ UndoStep *us_p,
+ int dir)
{
- ImageUndoStep *us = (ImageUndoStep *)us_p;
+ ImageUndoStep *us = (ImageUndoStep *)us_p;
#if 0
- paint_undosys_step_decode_restore_ids(us);
+ paint_undosys_step_decode_restore_ids(us);
#endif
- if (dir < 0) {
- image_undosys_step_decode_undo(us);
- }
- else {
- image_undosys_step_decode_redo(us);
- }
+ if (dir < 0) {
+ image_undosys_step_decode_undo(us);
+ }
+ else {
+ image_undosys_step_decode_redo(us);
+ }
- if (us->paint_mode == PAINT_MODE_TEXTURE_3D) {
- ED_object_mode_set(C, OB_MODE_TEXTURE_PAINT);
- }
+ if (us->paint_mode == PAINT_MODE_TEXTURE_3D) {
+ ED_object_mode_set(C, OB_MODE_TEXTURE_PAINT);
+ }
- /* Refresh texture slots. */
- ED_editors_init_for_undo(bmain);
+ /* Refresh texture slots. */
+ ED_editors_init_for_undo(bmain);
}
static void image_undosys_step_free(UndoStep *us_p)
{
- ImageUndoStep *us = (ImageUndoStep *)us_p;
- image_undo_free_list(&us->tiles);
- BKE_undosys_ID_map_destroy(us->id_map);
+ ImageUndoStep *us = (ImageUndoStep *)us_p;
+ image_undo_free_list(&us->tiles);
+ BKE_undosys_ID_map_destroy(us->id_map);
}
-static void image_undosys_foreach_ID_ref(
- UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+static void image_undosys_foreach_ID_ref(UndoStep *us_p,
+ UndoTypeForEachIDRefFn foreach_ID_ref_fn,
+ void *user_data)
{
- ImageUndoStep *us = (ImageUndoStep *)us_p;
- if (us->id_map != NULL) {
- BKE_undosys_ID_map_foreach_ID_ref(us->id_map, foreach_ID_ref_fn, user_data);
- }
+ ImageUndoStep *us = (ImageUndoStep *)us_p;
+ if (us->id_map != NULL) {
+ BKE_undosys_ID_map_foreach_ID_ref(us->id_map, foreach_ID_ref_fn, user_data);
+ }
}
/* Export for ED_undo_sys. */
void ED_image_undosys_type(UndoType *ut)
{
- ut->name = "Image";
- ut->poll = image_undosys_poll;
- ut->step_encode_init = image_undosys_step_encode_init;
- ut->step_encode = image_undosys_step_encode;
- ut->step_decode = image_undosys_step_decode;
- ut->step_free = image_undosys_step_free;
+ ut->name = "Image";
+ ut->poll = image_undosys_poll;
+ ut->step_encode_init = image_undosys_step_encode_init;
+ ut->step_encode = image_undosys_step_encode;
+ ut->step_decode = image_undosys_step_decode;
+ ut->step_free = image_undosys_step_free;
- ut->step_foreach_ID_ref = image_undosys_foreach_ID_ref;
+ ut->step_foreach_ID_ref = image_undosys_foreach_ID_ref;
- ut->use_context = true;
+ ut->use_context = true;
- ut->step_size = sizeof(ImageUndoStep);
+ ut->step_size = sizeof(ImageUndoStep);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Utilities
* \{ */
ListBase *ED_image_undosys_step_get_tiles(UndoStep *us_p)
{
- ImageUndoStep *us = (ImageUndoStep *)us_p;
- return &us->tiles;
+ ImageUndoStep *us = (ImageUndoStep *)us_p;
+ return &us->tiles;
}
ListBase *ED_image_undo_get_tiles(void)
{
- UndoStack *ustack = ED_undo_stack_get();
- UndoStep *us_prev = ustack->step_init;
- UndoStep *us_p = BKE_undosys_stack_init_or_active_with_type(ustack, BKE_UNDOSYS_TYPE_IMAGE);
- ImageUndoStep *us = (ImageUndoStep *)us_p;
- /* We should always have an undo push started when accessing tiles,
- * not doing this means we won't have paint_mode correctly set. */
- BLI_assert(us_p == us_prev);
- if (us_p != us_prev) {
- /* Fallback value until we can be sure this never happens. */
- us->paint_mode = PAINT_MODE_TEXTURE_2D;
- }
- return ED_image_undosys_step_get_tiles(us_p);
+ UndoStack *ustack = ED_undo_stack_get();
+ UndoStep *us_prev = ustack->step_init;
+ UndoStep *us_p = BKE_undosys_stack_init_or_active_with_type(ustack, BKE_UNDOSYS_TYPE_IMAGE);
+ ImageUndoStep *us = (ImageUndoStep *)us_p;
+ /* We should always have an undo push started when accessing tiles,
+ * not doing this means we won't have paint_mode correctly set. */
+ BLI_assert(us_p == us_prev);
+ if (us_p != us_prev) {
+ /* Fallback value until we can be sure this never happens. */
+ us->paint_mode = PAINT_MODE_TEXTURE_2D;
+ }
+ return ED_image_undosys_step_get_tiles(us_p);
}
/* restore painting image to previous state. Used for anchored and drag-dot style brushes*/
void ED_image_undo_restore(UndoStep *us)
{
- ListBase *lb = ED_image_undosys_step_get_tiles(us);
- image_undo_restore_runtime(lb);
- image_undo_invalidate();
+ ListBase *lb = ED_image_undosys_step_get_tiles(us);
+ image_undo_restore_runtime(lb);
+ image_undo_invalidate();
}
void ED_image_undo_push_begin(const char *name, int paint_mode)
{
- UndoStack *ustack = ED_undo_stack_get();
- bContext *C = NULL; /* special case, we never read from this. */
- UndoStep *us_p = BKE_undosys_step_push_init_with_type(ustack, C, name, BKE_UNDOSYS_TYPE_IMAGE);
- ImageUndoStep *us = (ImageUndoStep *)us_p;
- BLI_assert(ELEM(paint_mode, PAINT_MODE_TEXTURE_2D, PAINT_MODE_TEXTURE_3D));
- us->paint_mode = paint_mode;
+ UndoStack *ustack = ED_undo_stack_get();
+ bContext *C = NULL; /* special case, we never read from this. */
+ UndoStep *us_p = BKE_undosys_step_push_init_with_type(ustack, C, name, BKE_UNDOSYS_TYPE_IMAGE);
+ ImageUndoStep *us = (ImageUndoStep *)us_p;
+ BLI_assert(ELEM(paint_mode, PAINT_MODE_TEXTURE_2D, PAINT_MODE_TEXTURE_3D));
+ us->paint_mode = paint_mode;
}
void ED_image_undo_push_end(void)
{
- UndoStack *ustack = ED_undo_stack_get();
- BKE_undosys_step_push(ustack, NULL, NULL);
+ UndoStack *ustack = ED_undo_stack_get();
+ BKE_undosys_step_push(ustack, NULL, NULL);
}
/** \} */
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 0e8262bd82f..1a8d2f79290 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -21,7 +21,6 @@
* \ingroup edsculpt
*/
-
#ifndef __PAINT_INTERN_H__
#define __PAINT_INTERN_H__
@@ -51,22 +50,27 @@ struct wmWindowManager;
enum ePaintMode;
typedef struct CoNo {
- float co[3];
- float no[3];
+ float co[3];
+ float no[3];
} CoNo;
/* paint_stroke.c */
typedef bool (*StrokeGetLocation)(struct bContext *C, float location[3], const float mouse[2]);
typedef bool (*StrokeTestStart)(struct bContext *C, struct wmOperator *op, const float mouse[2]);
-typedef void (*StrokeUpdateStep)(struct bContext *C, struct PaintStroke *stroke, struct PointerRNA *itemptr);
+typedef void (*StrokeUpdateStep)(struct bContext *C,
+ struct PaintStroke *stroke,
+ struct PointerRNA *itemptr);
typedef void (*StrokeRedraw)(const struct bContext *C, struct PaintStroke *stroke, bool final);
typedef void (*StrokeDone)(const struct bContext *C, struct PaintStroke *stroke);
-struct PaintStroke *paint_stroke_new(
- struct bContext *C, struct wmOperator *op,
- StrokeGetLocation get_location, StrokeTestStart test_start,
- StrokeUpdateStep update_step, StrokeRedraw redraw,
- StrokeDone done, int event_type);
+struct PaintStroke *paint_stroke_new(struct bContext *C,
+ struct wmOperator *op,
+ StrokeGetLocation get_location,
+ StrokeTestStart test_start,
+ StrokeUpdateStep update_step,
+ StrokeRedraw redraw,
+ StrokeDone done,
+ int event_type);
void paint_stroke_data_free(struct wmOperator *op);
bool paint_space_stroke_enabled(struct Brush *br, enum ePaintMode mode);
@@ -88,7 +92,9 @@ float paint_stroke_distance_get(struct PaintStroke *stroke);
void paint_stroke_set_mode_data(struct PaintStroke *stroke, void *mode_data);
bool paint_poll(struct bContext *C);
void paint_cursor_start(struct bContext *C, bool (*poll)(struct bContext *C));
-void paint_cursor_start_explicit(struct Paint *p, struct wmWindowManager *wm, bool (*poll)(struct bContext *C));
+void paint_cursor_start_explicit(struct Paint *p,
+ struct wmWindowManager *wm,
+ bool (*poll)(struct bContext *C));
void paint_cursor_delete_textures(void);
/* paint_vertex.c */
@@ -99,15 +105,17 @@ bool vertex_paint_poll(struct bContext *C);
bool vertex_paint_poll_ignore_tool(struct bContext *C);
bool vertex_paint_mode_poll(struct bContext *C);
-typedef void (*VPaintTransform_Callback)(const float col[3], const void *user_data, float r_col[3]);
+typedef void (*VPaintTransform_Callback)(const float col[3],
+ const void *user_data,
+ float r_col[3]);
void PAINT_OT_weight_paint_toggle(struct wmOperatorType *ot);
void PAINT_OT_weight_paint(struct wmOperatorType *ot);
void PAINT_OT_weight_set(struct wmOperatorType *ot);
enum {
- WPAINT_GRADIENT_TYPE_LINEAR,
- WPAINT_GRADIENT_TYPE_RADIAL,
+ WPAINT_GRADIENT_TYPE_LINEAR,
+ WPAINT_GRADIENT_TYPE_RADIAL,
};
void PAINT_OT_weight_gradient(struct wmOperatorType *ot);
@@ -117,28 +125,31 @@ void PAINT_OT_vertex_paint(struct wmOperatorType *ot);
unsigned int vpaint_get_current_col(struct Scene *scene, struct VPaint *vp, bool secondary);
/* paint_vertex_color_utils.c */
-unsigned int ED_vpaint_blend_tool(
- const int tool, const uint col,
- const uint paintcol, const int alpha_i);
-bool ED_vpaint_color_transform(
- struct Object *ob, VPaintTransform_Callback vpaint_tx_fn, const void *user_data);
+unsigned int ED_vpaint_blend_tool(const int tool,
+ const uint col,
+ const uint paintcol,
+ const int alpha_i);
+bool ED_vpaint_color_transform(struct Object *ob,
+ VPaintTransform_Callback vpaint_tx_fn,
+ const void *user_data);
/* paint_vertex_weight_utils.c */
-float ED_wpaint_blend_tool(
- const int tool,
- const float weight,
- const float paintval, const float alpha);
+float ED_wpaint_blend_tool(const int tool,
+ const float weight,
+ const float paintval,
+ const float alpha);
/* Utility for tools to ensure vertex groups exist before they begin. */
enum eWPaintFlag {
- WPAINT_ENSURE_MIRROR = (1 << 0),
+ WPAINT_ENSURE_MIRROR = (1 << 0),
};
struct WPaintVGroupIndex {
- int active;
- int mirror;
+ int active;
+ int mirror;
};
-bool ED_wpaint_ensure_data(
- struct bContext *C, struct ReportList *reports,
- enum eWPaintFlag flag, struct WPaintVGroupIndex *vgroup_index);
+bool ED_wpaint_ensure_data(struct bContext *C,
+ struct ReportList *reports,
+ enum eWPaintFlag flag,
+ struct WPaintVGroupIndex *vgroup_index);
int ED_wpaint_mirror_vgroup_ensure(struct Object *ob, const int vgroup_active);
/* paint_vertex_color_ops.c */
@@ -157,55 +168,77 @@ void PAINT_OT_weight_sample_group(struct wmOperatorType *ot);
/* paint_vertex_proj.c */
struct VertProjHandle;
-struct VertProjHandle *ED_vpaint_proj_handle_create(
- struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob,
- struct CoNo **r_vcosnos);
-void ED_vpaint_proj_handle_update(
- struct Depsgraph *depsgraph, struct VertProjHandle *vp_handle,
- /* runtime vars */
- struct ARegion *ar, const float mval_fl[2]);
-void ED_vpaint_proj_handle_free(
- struct VertProjHandle *vp_handle);
-
+struct VertProjHandle *ED_vpaint_proj_handle_create(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob,
+ struct CoNo **r_vcosnos);
+void ED_vpaint_proj_handle_update(struct Depsgraph *depsgraph,
+ struct VertProjHandle *vp_handle,
+ /* runtime vars */
+ struct ARegion *ar,
+ const float mval_fl[2]);
+void ED_vpaint_proj_handle_free(struct VertProjHandle *vp_handle);
/* paint_image.c */
typedef struct ImagePaintPartialRedraw {
- int x1, y1, x2, y2; /* XXX, could use 'rcti' */
- int enabled;
+ int x1, y1, x2, y2; /* XXX, could use 'rcti' */
+ int enabled;
} ImagePaintPartialRedraw;
-#define IMAPAINT_TILE_BITS 6
-#define IMAPAINT_TILE_SIZE (1 << IMAPAINT_TILE_BITS)
-#define IMAPAINT_TILE_NUMBER(size) (((size) + IMAPAINT_TILE_SIZE - 1) >> IMAPAINT_TILE_BITS)
+#define IMAPAINT_TILE_BITS 6
+#define IMAPAINT_TILE_SIZE (1 << IMAPAINT_TILE_BITS)
+#define IMAPAINT_TILE_NUMBER(size) (((size) + IMAPAINT_TILE_SIZE - 1) >> IMAPAINT_TILE_BITS)
bool image_texture_paint_poll(struct bContext *C);
-void imapaint_image_update(struct SpaceImage *sima, struct Image *image, struct ImBuf *ibuf, short texpaint);
+void imapaint_image_update(struct SpaceImage *sima,
+ struct Image *image,
+ struct ImBuf *ibuf,
+ short texpaint);
struct ImagePaintPartialRedraw *get_imapaintpartial(void);
void set_imapaintpartial(struct ImagePaintPartialRedraw *ippr);
-void imapaint_region_tiles(struct ImBuf *ibuf, int x, int y, int w, int h, int *tx, int *ty, int *tw, int *th);
+void imapaint_region_tiles(
+ struct ImBuf *ibuf, int x, int y, int w, int h, int *tx, int *ty, int *tw, int *th);
int get_imapaint_zoom(struct bContext *C, float *zoomx, float *zoomy);
void *paint_2d_new_stroke(struct bContext *, struct wmOperator *, int mode);
void paint_2d_redraw(const struct bContext *C, void *ps, bool final);
void paint_2d_stroke_done(void *ps);
-void paint_2d_stroke(
- void *ps, const float prev_mval[2], const float mval[2],
- const bool eraser, float pressure, float distance, float size);
-void paint_2d_bucket_fill(
- const struct bContext *C, const float color[3], struct Brush *br, const float mouse_init[2], void *ps);
-void paint_2d_gradient_fill(
- const struct bContext *C, struct Brush *br, const float mouse_init[2], const float mouse_final[2], void *ps);
-void *paint_proj_new_stroke(
- struct bContext *C, struct Object *ob, const float mouse[2], int mode);
-void paint_proj_stroke(
- const struct bContext *C, void *ps, const float prevmval_i[2], const float mval_i[2],
- const bool eraser, float pressure, float distance, float size);
+void paint_2d_stroke(void *ps,
+ const float prev_mval[2],
+ const float mval[2],
+ const bool eraser,
+ float pressure,
+ float distance,
+ float size);
+void paint_2d_bucket_fill(const struct bContext *C,
+ const float color[3],
+ struct Brush *br,
+ const float mouse_init[2],
+ void *ps);
+void paint_2d_gradient_fill(const struct bContext *C,
+ struct Brush *br,
+ const float mouse_init[2],
+ const float mouse_final[2],
+ void *ps);
+void *paint_proj_new_stroke(struct bContext *C, struct Object *ob, const float mouse[2], int mode);
+void paint_proj_stroke(const struct bContext *C,
+ void *ps,
+ const float prevmval_i[2],
+ const float mval_i[2],
+ const bool eraser,
+ float pressure,
+ float distance,
+ float size);
void paint_proj_redraw(const struct bContext *C, void *pps, bool final);
void paint_proj_stroke_done(void *ps);
-void paint_brush_color_get(
- struct Scene *scene, struct Brush *br,
- bool color_correction, bool invert, float distance, float pressure, float color[3],
- struct ColorManagedDisplay *display);
+void paint_brush_color_get(struct Scene *scene,
+ struct Brush *br,
+ bool color_correction,
+ bool invert,
+ float distance,
+ float pressure,
+ float color[3],
+ struct ColorManagedDisplay *display);
bool paint_use_opacity_masking(struct Brush *brush);
void paint_brush_init_tex(struct Brush *brush);
void paint_brush_exit_tex(struct Brush *brush);
@@ -221,14 +254,23 @@ void PAINT_OT_image_paint(struct wmOperatorType *ot);
void PAINT_OT_add_simple_uvs(struct wmOperatorType *ot);
/* paint_image_undo.c */
-void *image_undo_find_tile(
- ListBase *undo_tiles,
- struct Image *ima, struct ImBuf *ibuf, int x_tile, int y_tile,
- unsigned short **mask, bool validate);
-void *image_undo_push_tile(
- ListBase *undo_tiles,
- struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile,
- unsigned short **, bool **valid, bool proj, bool find_prev);
+void *image_undo_find_tile(ListBase *undo_tiles,
+ struct Image *ima,
+ struct ImBuf *ibuf,
+ int x_tile,
+ int y_tile,
+ unsigned short **mask,
+ bool validate);
+void *image_undo_push_tile(ListBase *undo_tiles,
+ struct Image *ima,
+ struct ImBuf *ibuf,
+ struct ImBuf **tmpibuf,
+ int x_tile,
+ int y_tile,
+ unsigned short **,
+ bool **valid,
+ bool proj,
+ bool find_prev);
void image_undo_remove_masks(void);
void image_undo_init_locks(void);
void image_undo_end_locks(void);
@@ -247,30 +289,37 @@ void SCULPT_OT_uv_sculpt_stroke(struct wmOperatorType *ot);
/* Convert the object-space axis-aligned bounding box (expressed as
* its minimum and maximum corners) into a screen-space rectangle,
* returns zero if the result is empty */
-bool paint_convert_bb_to_rect(
- struct rcti *rect,
- const float bb_min[3],
- const float bb_max[3],
- const struct ARegion *ar,
- struct RegionView3D *rv3d,
- struct Object *ob);
+bool paint_convert_bb_to_rect(struct rcti *rect,
+ const float bb_min[3],
+ const float bb_max[3],
+ const struct ARegion *ar,
+ struct RegionView3D *rv3d,
+ struct Object *ob);
/* Get four planes in object-space that describe the projection of
* 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,
- struct Object *ob,
- const struct rcti *screen_rect);
-
-float paint_calc_object_space_radius(struct ViewContext *vc, const float center[3], float pixel_radius);
-float paint_get_tex_pixel(const struct MTex *mtex, float u, float v, struct ImagePool *pool, int thread);
-void paint_get_tex_pixel_col(
- const struct MTex *mtex, float u, float v, float rgba[4],
- struct ImagePool *pool, int thread, bool convert, struct ColorSpace *colorspace);
-
-void paint_sample_color(struct bContext *C, struct ARegion *ar, int x, int y, bool texpaint_proj, bool palette);
+void paint_calc_redraw_planes(float planes[4][4],
+ const struct ARegion *ar,
+ struct Object *ob,
+ const struct rcti *screen_rect);
+
+float paint_calc_object_space_radius(struct ViewContext *vc,
+ const float center[3],
+ float pixel_radius);
+float paint_get_tex_pixel(
+ const struct MTex *mtex, float u, float v, struct ImagePool *pool, int thread);
+void paint_get_tex_pixel_col(const struct MTex *mtex,
+ float u,
+ float v,
+ float rgba[4],
+ struct ImagePool *pool,
+ int thread,
+ bool convert,
+ struct ColorSpace *colorspace);
+
+void paint_sample_color(
+ struct bContext *C, struct ARegion *ar, int x, int y, bool texpaint_proj, bool palette);
void paint_stroke_operator_properties(struct wmOperatorType *ot);
@@ -295,23 +344,23 @@ void flip_qt_qt(float out[3], const float in[3], const char symm);
/* stroke operator */
typedef enum BrushStrokeMode {
- BRUSH_STROKE_NORMAL,
- BRUSH_STROKE_INVERT,
- BRUSH_STROKE_SMOOTH,
+ BRUSH_STROKE_NORMAL,
+ BRUSH_STROKE_INVERT,
+ BRUSH_STROKE_SMOOTH,
} BrushStrokeMode;
/* paint_hide.c */
typedef enum {
- PARTIALVIS_HIDE,
- PARTIALVIS_SHOW,
+ PARTIALVIS_HIDE,
+ PARTIALVIS_SHOW,
} PartialVisAction;
typedef enum {
- PARTIALVIS_INSIDE,
- PARTIALVIS_OUTSIDE,
- PARTIALVIS_ALL,
- PARTIALVIS_MASKED,
+ PARTIALVIS_INSIDE,
+ PARTIALVIS_OUTSIDE,
+ PARTIALVIS_ALL,
+ PARTIALVIS_MASKED,
} PartialVisArea;
void PAINT_OT_hide_show(struct wmOperatorType *ot);
@@ -319,9 +368,9 @@ void PAINT_OT_hide_show(struct wmOperatorType *ot);
/* paint_mask.c */
typedef enum {
- PAINT_MASK_FLOOD_VALUE,
- PAINT_MASK_FLOOD_VALUE_INVERSE,
- PAINT_MASK_INVERT,
+ PAINT_MASK_FLOOD_VALUE,
+ PAINT_MASK_FLOOD_VALUE_INVERSE,
+ PAINT_MASK_INVERT,
} PaintMaskFloodMode;
void PAINT_OT_mask_flood_fill(struct wmOperatorType *ot);
@@ -338,10 +387,10 @@ void PAINTCURVE_OT_cursor(struct wmOperatorType *ot);
/* image painting blur kernel */
typedef struct {
- float *wdata; /* actual kernel */
- int side; /* kernel side */
- int side_squared; /* data side */
- int pixel_len; /* pixels around center that kernel is wide */
+ float *wdata; /* actual kernel */
+ int side; /* kernel side */
+ int side_squared; /* data side */
+ int pixel_len; /* pixels around center that kernel is wide */
} BlurKernel;
enum eBlurKernelType;
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index b88ae861229..ca48030daed 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -60,478 +60,503 @@
#include <stdlib.h>
static const EnumPropertyItem mode_items[] = {
- {PAINT_MASK_FLOOD_VALUE, "VALUE", 0, "Value", "Set mask to the level specified by the 'value' property"},
- {PAINT_MASK_FLOOD_VALUE_INVERSE, "VALUE_INVERSE", 0, "Value Inverted", "Set mask to the level specified by the inverted 'value' property"},
- {PAINT_MASK_INVERT, "INVERT", 0, "Invert", "Invert the mask"},
- {0}};
-
-
-static void mask_flood_fill_set_elem(
- float *elem,
- PaintMaskFloodMode mode,
- float value)
+ {PAINT_MASK_FLOOD_VALUE,
+ "VALUE",
+ 0,
+ "Value",
+ "Set mask to the level specified by the 'value' property"},
+ {PAINT_MASK_FLOOD_VALUE_INVERSE,
+ "VALUE_INVERSE",
+ 0,
+ "Value Inverted",
+ "Set mask to the level specified by the inverted 'value' property"},
+ {PAINT_MASK_INVERT, "INVERT", 0, "Invert", "Invert the mask"},
+ {0}};
+
+static void mask_flood_fill_set_elem(float *elem, PaintMaskFloodMode mode, float value)
{
- switch (mode) {
- case PAINT_MASK_FLOOD_VALUE:
- (*elem) = value;
- break;
- case PAINT_MASK_FLOOD_VALUE_INVERSE:
- (*elem) = 1.0f - value;
- break;
- case PAINT_MASK_INVERT:
- (*elem) = 1.0f - (*elem);
- break;
- }
+ switch (mode) {
+ case PAINT_MASK_FLOOD_VALUE:
+ (*elem) = value;
+ break;
+ case PAINT_MASK_FLOOD_VALUE_INVERSE:
+ (*elem) = 1.0f - value;
+ break;
+ case PAINT_MASK_INVERT:
+ (*elem) = 1.0f - (*elem);
+ break;
+ }
}
typedef struct MaskTaskData {
- Object *ob;
- PBVH *pbvh;
- PBVHNode **nodes;
- bool multires;
-
- PaintMaskFloodMode mode;
- float value;
- float (*clip_planes_final)[4];
+ Object *ob;
+ PBVH *pbvh;
+ PBVHNode **nodes;
+ bool multires;
+
+ PaintMaskFloodMode mode;
+ float value;
+ float (*clip_planes_final)[4];
} MaskTaskData;
-static void mask_flood_fill_task_cb(
- void *__restrict userdata,
- const int i,
- const ParallelRangeTLS *__restrict UNUSED(tls))
+static void mask_flood_fill_task_cb(void *__restrict userdata,
+ const int i,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
{
- MaskTaskData *data = userdata;
+ MaskTaskData *data = userdata;
- PBVHNode *node = data->nodes[i];
+ PBVHNode *node = data->nodes[i];
- const PaintMaskFloodMode mode = data->mode;
- const float value = data->value;
+ const PaintMaskFloodMode mode = data->mode;
+ const float value = data->value;
- PBVHVertexIter vi;
+ 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) {
- mask_flood_fill_set_elem(vi.mask, mode, value);
- } BKE_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_begin(data->pbvh, node, vi, PBVH_ITER_UNIQUE)
+ {
+ mask_flood_fill_set_elem(vi.mask, mode, value);
+ }
+ BKE_pbvh_vertex_iter_end;
- BKE_pbvh_node_mark_redraw(node);
- if (data->multires)
- BKE_pbvh_node_mark_normals_update(node);
+ BKE_pbvh_node_mark_redraw(node);
+ if (data->multires)
+ BKE_pbvh_node_mark_normals_update(node);
}
static int mask_flood_fill_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
- struct Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- PaintMaskFloodMode mode;
- float value;
- PBVH *pbvh;
- PBVHNode **nodes;
- int totnode;
- bool multires;
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ ARegion *ar = CTX_wm_region(C);
+ struct Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ PaintMaskFloodMode mode;
+ float value;
+ PBVH *pbvh;
+ PBVHNode **nodes;
+ int totnode;
+ bool multires;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- mode = RNA_enum_get(op->ptr, "mode");
- value = RNA_float_get(op->ptr, "value");
+ mode = RNA_enum_get(op->ptr, "mode");
+ value = RNA_float_get(op->ptr, "value");
- BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, true);
- pbvh = ob->sculpt->pbvh;
- multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
+ BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, true);
+ pbvh = ob->sculpt->pbvh;
+ multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
- BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+ 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, .pbvh = pbvh, .nodes = nodes, .multires = multires,
- .mode = mode, .value = value,
- };
+ MaskTaskData data = {
+ .ob = ob,
+ .pbvh = pbvh,
+ .nodes = nodes,
+ .multires = multires,
+ .mode = mode,
+ .value = value,
+ };
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ BLI_task_parallel_range(
- 0, totnode, &data, mask_flood_fill_task_cb,
- &settings);
+ 0, totnode, &data, mask_flood_fill_task_cb, &settings);
- if (multires)
- multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
+ if (multires)
+ multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
- sculpt_undo_push_end();
+ sculpt_undo_push_end();
- if (nodes)
- MEM_freeN(nodes);
+ if (nodes)
+ MEM_freeN(nodes);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PAINT_OT_mask_flood_fill(struct wmOperatorType *ot)
{
- /* 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 */
- ot->exec = mask_flood_fill_exec;
- ot->poll = sculpt_mode_poll;
-
- ot->flag = OPTYPE_REGISTER;
-
- /* rna */
- RNA_def_enum(ot->srna, "mode", mode_items, PAINT_MASK_FLOOD_VALUE, "Mode", NULL);
- RNA_def_float(ot->srna, "value", 0, 0, 1, "Value",
- "Mask level to use when mode is 'Value'; zero means no masking and one is fully masked", 0, 1);
+ /* 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 */
+ ot->exec = mask_flood_fill_exec;
+ ot->poll = sculpt_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER;
+
+ /* rna */
+ RNA_def_enum(ot->srna, "mode", mode_items, PAINT_MASK_FLOOD_VALUE, "Mode", NULL);
+ RNA_def_float(
+ ot->srna,
+ "value",
+ 0,
+ 0,
+ 1,
+ "Value",
+ "Mask level to use when mode is 'Value'; zero means no masking and one is fully masked",
+ 0,
+ 1);
}
/* 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])
{
- return isect_point_planes_v3(planes, 4, co);
+ return isect_point_planes_v3(planes, 4, co);
}
static void flip_plane(float out[4], const float in[4], const char symm)
{
- if (symm & PAINT_SYMM_X)
- out[0] = -in[0];
- else
- out[0] = in[0];
- if (symm & PAINT_SYMM_Y)
- out[1] = -in[1];
- else
- out[1] = in[1];
- if (symm & PAINT_SYMM_Z)
- out[2] = -in[2];
- else
- out[2] = in[2];
-
- out[3] = in[3];
+ if (symm & PAINT_SYMM_X)
+ out[0] = -in[0];
+ else
+ out[0] = in[0];
+ if (symm & PAINT_SYMM_Y)
+ out[1] = -in[1];
+ else
+ out[1] = in[1];
+ if (symm & PAINT_SYMM_Z)
+ out[2] = -in[2];
+ else
+ out[2] = in[2];
+
+ out[3] = in[3];
}
-static void mask_box_select_task_cb(
- void *__restrict userdata,
- const int i,
- const ParallelRangeTLS *__restrict UNUSED(tls))
+static void mask_box_select_task_cb(void *__restrict userdata,
+ const int i,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
{
- MaskTaskData *data = userdata;
+ MaskTaskData *data = userdata;
- PBVHNode *node = data->nodes[i];
+ PBVHNode *node = data->nodes[i];
- const PaintMaskFloodMode mode = data->mode;
- const float value = data->value;
- float (*clip_planes_final)[4] = data->clip_planes_final;
+ const PaintMaskFloodMode mode = data->mode;
+ const float value = data->value;
+ float(*clip_planes_final)[4] = data->clip_planes_final;
- PBVHVertexIter vi;
- bool any_masked = false;
+ PBVHVertexIter vi;
+ bool any_masked = false;
- BKE_pbvh_vertex_iter_begin(data->pbvh, node, vi, PBVH_ITER_UNIQUE) {
- if (is_effected(clip_planes_final, vi.co)) {
- if (!any_masked) {
- any_masked = true;
+ BKE_pbvh_vertex_iter_begin(data->pbvh, node, vi, PBVH_ITER_UNIQUE)
+ {
+ if (is_effected(clip_planes_final, vi.co)) {
+ 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)
- BKE_pbvh_node_mark_normals_update(node);
- }
- mask_flood_fill_set_elem(vi.mask, mode, value);
- }
- } BKE_pbvh_vertex_iter_end;
+ BKE_pbvh_node_mark_redraw(node);
+ if (data->multires)
+ BKE_pbvh_node_mark_normals_update(node);
+ }
+ mask_flood_fill_set_elem(vi.mask, mode, value);
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
bool ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *rect, bool select)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Sculpt *sd = vc->scene->toolsettings->sculpt;
- BoundBox bb;
- float clip_planes[4][4];
- float clip_planes_final[4][4];
- ARegion *ar = vc->ar;
- struct Scene *scene = vc->scene;
- Object *ob = vc->obact;
- PaintMaskFloodMode mode;
- float value;
- bool multires;
- PBVH *pbvh;
- PBVHNode **nodes;
- int totnode, symmpass;
- int symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
-
- mode = PAINT_MASK_FLOOD_VALUE;
- value = select ? 1.0 : 0.0;
-
- /* transform the clip planes in object space */
- ED_view3d_clipping_calc(&bb, clip_planes, vc->ar, vc->obact, rect);
- negate_m4(clip_planes);
-
- BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, true);
- pbvh = ob->sculpt->pbvh;
- multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
-
- sculpt_undo_push_begin("Mask box fill");
-
- for (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_plane(clip_planes_final[j], clip_planes[j], symmpass);
- }
-
- BKE_pbvh_search_gather(pbvh, BKE_pbvh_node_planes_contain_AABB, clip_planes_final, &nodes, &totnode);
-
- MaskTaskData data = {
- .ob = ob, .pbvh = pbvh, .nodes = nodes, .multires = multires,
- .mode = mode, .value = value, .clip_planes_final = clip_planes_final,
- };
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode, &data, mask_box_select_task_cb,
- &settings);
-
- if (nodes)
- MEM_freeN(nodes);
- }
- }
-
- if (multires)
- multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
-
- sculpt_undo_push_end();
-
- ED_region_tag_redraw(ar);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- return true;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Sculpt *sd = vc->scene->toolsettings->sculpt;
+ BoundBox bb;
+ float clip_planes[4][4];
+ float clip_planes_final[4][4];
+ ARegion *ar = vc->ar;
+ struct Scene *scene = vc->scene;
+ Object *ob = vc->obact;
+ PaintMaskFloodMode mode;
+ float value;
+ bool multires;
+ PBVH *pbvh;
+ PBVHNode **nodes;
+ int totnode, symmpass;
+ int symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+
+ mode = PAINT_MASK_FLOOD_VALUE;
+ value = select ? 1.0 : 0.0;
+
+ /* transform the clip planes in object space */
+ ED_view3d_clipping_calc(&bb, clip_planes, vc->ar, vc->obact, rect);
+ negate_m4(clip_planes);
+
+ BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, true);
+ pbvh = ob->sculpt->pbvh;
+ multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
+
+ sculpt_undo_push_begin("Mask box fill");
+
+ for (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_plane(clip_planes_final[j], clip_planes[j], symmpass);
+ }
+
+ BKE_pbvh_search_gather(
+ pbvh, BKE_pbvh_node_planes_contain_AABB, clip_planes_final, &nodes, &totnode);
+
+ MaskTaskData data = {
+ .ob = ob,
+ .pbvh = pbvh,
+ .nodes = nodes,
+ .multires = multires,
+ .mode = mode,
+ .value = value,
+ .clip_planes_final = clip_planes_final,
+ };
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) &&
+ totnode > SCULPT_THREADED_LIMIT);
+ BLI_task_parallel_range(0, totnode, &data, mask_box_select_task_cb, &settings);
+
+ if (nodes)
+ MEM_freeN(nodes);
+ }
+ }
+
+ if (multires)
+ multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
+
+ sculpt_undo_push_end();
+
+ ED_region_tag_redraw(ar);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return true;
}
typedef struct LassoMaskData {
- struct ViewContext *vc;
- float projviewobjmat[4][4];
- BLI_bitmap *px;
- int width;
- rcti rect; /* bounding box for scanfilling */
- int symmpass;
-
- MaskTaskData task_data;
+ struct ViewContext *vc;
+ float projviewobjmat[4][4];
+ BLI_bitmap *px;
+ int width;
+ rcti rect; /* bounding box for scanfilling */
+ int symmpass;
+
+ MaskTaskData task_data;
} LassoMaskData;
-
/* Lasso select. This could be defined as part of VIEW3D_OT_select_lasso, still the shortcuts conflict,
* so we will use a separate operator */
static bool is_effected_lasso(LassoMaskData *data, float co[3])
{
- float scr_co_f[2];
- int scr_co_s[2];
- 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);
-
- 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 */
- 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;
- }
-
- scr_co_s[0] -= data->rect.xmin;
- scr_co_s[1] -= data->rect.ymin;
-
- return BLI_BITMAP_TEST_BOOL(data->px, scr_co_s[1] * data->width + scr_co_s[0]);
+ float scr_co_f[2];
+ int scr_co_s[2];
+ 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);
+
+ 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 */
+ 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;
+ }
+
+ scr_co_s[0] -= data->rect.xmin;
+ scr_co_s[1] -= data->rect.ymin;
+
+ return BLI_BITMAP_TEST_BOOL(data->px, scr_co_s[1] * data->width + scr_co_s[0]);
}
static void mask_lasso_px_cb(int x, int x_end, int y, void *user_data)
{
- LassoMaskData *data = user_data;
- int index = (y * data->width) + x;
- int index_end = (y * data->width) + x_end;
- do {
- BLI_BITMAP_ENABLE(data->px, index);
- } while (++index != index_end);
+ LassoMaskData *data = user_data;
+ int index = (y * data->width) + x;
+ int index_end = (y * data->width) + x_end;
+ do {
+ BLI_BITMAP_ENABLE(data->px, index);
+ } while (++index != index_end);
}
-static void mask_gesture_lasso_task_cb(
- void *__restrict userdata,
- const int i,
- const ParallelRangeTLS *__restrict UNUSED(tls))
+static void mask_gesture_lasso_task_cb(void *__restrict userdata,
+ const int i,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
{
- LassoMaskData *lasso_data = userdata;
- MaskTaskData *data = &lasso_data->task_data;
+ LassoMaskData *lasso_data = userdata;
+ MaskTaskData *data = &lasso_data->task_data;
- PBVHNode *node = data->nodes[i];
+ PBVHNode *node = data->nodes[i];
- const PaintMaskFloodMode mode = data->mode;
- const float value = data->value;
+ const PaintMaskFloodMode mode = data->mode;
+ const float value = data->value;
- PBVHVertexIter vi;
- bool any_masked = false;
+ PBVHVertexIter vi;
+ bool any_masked = false;
- BKE_pbvh_vertex_iter_begin(data->pbvh, node, vi, PBVH_ITER_UNIQUE) {
- if (is_effected_lasso(lasso_data, vi.co)) {
- if (!any_masked) {
- any_masked = true;
+ BKE_pbvh_vertex_iter_begin(data->pbvh, node, vi, PBVH_ITER_UNIQUE)
+ {
+ if (is_effected_lasso(lasso_data, vi.co)) {
+ 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)
- BKE_pbvh_node_mark_normals_update(node);
- }
+ BKE_pbvh_node_mark_redraw(node);
+ if (data->multires)
+ BKE_pbvh_node_mark_normals_update(node);
+ }
- mask_flood_fill_set_elem(vi.mask, mode, value);
- }
- } BKE_pbvh_vertex_iter_end;
+ mask_flood_fill_set_elem(vi.mask, mode, value);
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
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);
-
- if (mcords) {
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- float clip_planes[4][4], clip_planes_final[4][4];
- BoundBox bb;
- Object *ob;
- ViewContext vc;
- LassoMaskData data;
- struct Scene *scene = CTX_data_scene(C);
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- int symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
- PBVH *pbvh;
- PBVHNode **nodes;
- int totnode, symmpass;
- 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 */
- ED_view3d_viewcontext_init(C, &vc);
-
- /* 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);
- data.width = data.rect.xmax - data.rect.xmin;
- data.px = BLI_BITMAP_NEW(data.width * (data.rect.ymax - data.rect.ymin), __func__);
-
- BLI_bitmap_draw_2d_poly_v2i_n(
- data.rect.xmin, data.rect.ymin, data.rect.xmax, data.rect.ymax,
- mcords, mcords_tot,
- mask_lasso_px_cb, &data);
-
- ED_view3d_clipping_calc(&bb, clip_planes, vc.ar, vc.obact, &data.rect);
- negate_m4(clip_planes);
-
- BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, true);
- pbvh = ob->sculpt->pbvh;
- multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
-
- sculpt_undo_push_begin("Mask lasso fill");
-
- for (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_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) */
- BKE_pbvh_search_gather(pbvh, BKE_pbvh_node_planes_contain_AABB, clip_planes_final, &nodes, &totnode);
-
- data.task_data.ob = ob;
- data.task_data.pbvh = pbvh;
- data.task_data.nodes = nodes;
- data.task_data.multires = multires;
- data.task_data.mode = mode;
- data.task_data.value = value;
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && (totnode > SCULPT_THREADED_LIMIT));
- BLI_task_parallel_range(
- 0, totnode, &data, mask_gesture_lasso_task_cb,
- &settings);
-
- if (nodes)
- MEM_freeN(nodes);
- }
- }
-
- if (multires)
- multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
-
- sculpt_undo_push_end();
-
- ED_region_tag_redraw(vc.ar);
- MEM_freeN((void *)mcords);
- MEM_freeN(data.px);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- return OPERATOR_FINISHED;
- }
- return OPERATOR_PASS_THROUGH;
+ int mcords_tot;
+ const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
+
+ if (mcords) {
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ float clip_planes[4][4], clip_planes_final[4][4];
+ BoundBox bb;
+ Object *ob;
+ ViewContext vc;
+ LassoMaskData data;
+ struct Scene *scene = CTX_data_scene(C);
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ int symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+ PBVH *pbvh;
+ PBVHNode **nodes;
+ int totnode, symmpass;
+ 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 */
+ ED_view3d_viewcontext_init(C, &vc);
+
+ /* 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);
+ data.width = data.rect.xmax - data.rect.xmin;
+ data.px = BLI_BITMAP_NEW(data.width * (data.rect.ymax - data.rect.ymin), __func__);
+
+ BLI_bitmap_draw_2d_poly_v2i_n(data.rect.xmin,
+ data.rect.ymin,
+ data.rect.xmax,
+ data.rect.ymax,
+ mcords,
+ mcords_tot,
+ mask_lasso_px_cb,
+ &data);
+
+ ED_view3d_clipping_calc(&bb, clip_planes, vc.ar, vc.obact, &data.rect);
+ negate_m4(clip_planes);
+
+ BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, true);
+ pbvh = ob->sculpt->pbvh;
+ multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
+
+ sculpt_undo_push_begin("Mask lasso fill");
+
+ for (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_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) */
+ BKE_pbvh_search_gather(
+ pbvh, BKE_pbvh_node_planes_contain_AABB, clip_planes_final, &nodes, &totnode);
+
+ data.task_data.ob = ob;
+ data.task_data.pbvh = pbvh;
+ data.task_data.nodes = nodes;
+ data.task_data.multires = multires;
+ data.task_data.mode = mode;
+ data.task_data.value = value;
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) &&
+ (totnode > SCULPT_THREADED_LIMIT));
+ BLI_task_parallel_range(0, totnode, &data, mask_gesture_lasso_task_cb, &settings);
+
+ if (nodes)
+ MEM_freeN(nodes);
+ }
+ }
+
+ if (multires)
+ multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
+
+ sculpt_undo_push_end();
+
+ ED_region_tag_redraw(vc.ar);
+ MEM_freeN((void *)mcords);
+ MEM_freeN(data.px);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_PASS_THROUGH;
}
void PAINT_OT_mask_lasso_gesture(wmOperatorType *ot)
{
- ot->name = "Mask Lasso Gesture";
- ot->idname = "PAINT_OT_mask_lasso_gesture";
- ot->description = "Add mask within the lasso as you move the brush";
-
- ot->invoke = WM_gesture_lasso_invoke;
- ot->modal = WM_gesture_lasso_modal;
- ot->exec = paint_mask_gesture_lasso_exec;
-
- ot->poll = sculpt_mode_poll;
-
- ot->flag = OPTYPE_REGISTER;
-
- /* 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, "Value",
- "Mask level to use when mode is 'Value'; zero means no masking and one is fully masked", 0, 1);
+ ot->name = "Mask Lasso Gesture";
+ ot->idname = "PAINT_OT_mask_lasso_gesture";
+ ot->description = "Add mask within the lasso as you move the brush";
+
+ ot->invoke = WM_gesture_lasso_invoke;
+ ot->modal = WM_gesture_lasso_modal;
+ ot->exec = paint_mask_gesture_lasso_exec;
+
+ ot->poll = sculpt_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER;
+
+ /* 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,
+ "Value",
+ "Mask level to use when mode is 'Value'; zero means no masking and one is fully masked",
+ 0,
+ 1);
}
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index 218d3ce4273..6686e255b08 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -66,1030 +66,1027 @@
/* Brush operators */
static int brush_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- /*int type = RNA_enum_get(op->ptr, "type");*/
- Paint *paint = BKE_paint_get_active_from_context(C);
- Brush *br = BKE_paint_brush(paint);
- Main *bmain = CTX_data_main(C);
- ePaintMode mode = BKE_paintmode_get_active_from_context(C);
-
- if (br) {
- br = BKE_brush_copy(bmain, br);
- }
- else {
- br = BKE_brush_add(bmain, "Brush", BKE_paint_object_mode_from_paintmode(mode));
- id_us_min(&br->id); /* fake user only */
- }
-
- BKE_paint_brush_set(paint, br);
-
- return OPERATOR_FINISHED;
+ /*int type = RNA_enum_get(op->ptr, "type");*/
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Brush *br = BKE_paint_brush(paint);
+ Main *bmain = CTX_data_main(C);
+ ePaintMode mode = BKE_paintmode_get_active_from_context(C);
+
+ if (br) {
+ br = BKE_brush_copy(bmain, br);
+ }
+ else {
+ br = BKE_brush_add(bmain, "Brush", BKE_paint_object_mode_from_paintmode(mode));
+ id_us_min(&br->id); /* fake user only */
+ }
+
+ BKE_paint_brush_set(paint, br);
+
+ return OPERATOR_FINISHED;
}
static void BRUSH_OT_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Brush";
- ot->description = "Add brush by mode type";
- ot->idname = "BRUSH_OT_add";
+ /* identifiers */
+ ot->name = "Add Brush";
+ ot->description = "Add brush by mode type";
+ ot->idname = "BRUSH_OT_add";
- /* api callbacks */
- ot->exec = brush_add_exec;
+ /* api callbacks */
+ ot->exec = brush_add_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int brush_add_gpencil_exec(bContext *C, wmOperator *UNUSED(op))
{
- /*int type = RNA_enum_get(op->ptr, "type");*/
- ToolSettings *ts = CTX_data_tool_settings(C);
- Paint *paint = &ts->gp_paint->paint;
- Brush *br = BKE_paint_brush(paint);
- Main *bmain = CTX_data_main(C);
- // ePaintMode mode = PAINT_MODE_GPENCIL;
-
- if (br) {
- br = BKE_brush_copy(bmain, br);
- }
- else {
- br = BKE_brush_add(bmain, "Brush", OB_MODE_PAINT_GPENCIL);
- id_us_min(&br->id); /* fake user only */
- }
-
- BKE_paint_brush_set(paint, br);
-
- /* init grease pencil specific data */
- BKE_brush_init_gpencil_settings(br);
-
- return OPERATOR_FINISHED;
+ /*int type = RNA_enum_get(op->ptr, "type");*/
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Paint *paint = &ts->gp_paint->paint;
+ Brush *br = BKE_paint_brush(paint);
+ Main *bmain = CTX_data_main(C);
+ // ePaintMode mode = PAINT_MODE_GPENCIL;
+
+ if (br) {
+ br = BKE_brush_copy(bmain, br);
+ }
+ else {
+ br = BKE_brush_add(bmain, "Brush", OB_MODE_PAINT_GPENCIL);
+ id_us_min(&br->id); /* fake user only */
+ }
+
+ BKE_paint_brush_set(paint, br);
+
+ /* init grease pencil specific data */
+ BKE_brush_init_gpencil_settings(br);
+
+ return OPERATOR_FINISHED;
}
static void BRUSH_OT_add_gpencil(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Drawing Brush";
- ot->description = "Add brush for Grease Pencil";
- ot->idname = "BRUSH_OT_add_gpencil";
+ /* identifiers */
+ ot->name = "Add Drawing Brush";
+ ot->description = "Add brush for Grease Pencil";
+ ot->idname = "BRUSH_OT_add_gpencil";
- /* api callbacks */
- ot->exec = brush_add_gpencil_exec;
+ /* api callbacks */
+ ot->exec = brush_add_gpencil_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int brush_scale_size_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Paint *paint = BKE_paint_get_active_from_context(C);
- Brush *brush = BKE_paint_brush(paint);
- // Object *ob = CTX_data_active_object(C);
- float scalar = RNA_float_get(op->ptr, "scalar");
-
- if (brush) {
- // pixel radius
- {
- const int old_size = BKE_brush_size_get(scene, brush);
- int size = (int)(scalar * old_size);
-
- if (abs(old_size - size) < U.pixelsize) {
- if (scalar > 1) {
- size += U.pixelsize;
- }
- else if (scalar < 1) {
- size -= U.pixelsize;
- }
- }
-
- BKE_brush_size_set(scene, brush, size);
- }
-
- // unprojected radius
- {
- float unprojected_radius = scalar * BKE_brush_unprojected_radius_get(scene, brush);
-
- if (unprojected_radius < 0.001f) // XXX magic number
- unprojected_radius = 0.001f;
-
- BKE_brush_unprojected_radius_set(scene, brush, unprojected_radius);
- }
-
- WM_main_add_notifier(NC_BRUSH | NA_EDITED, brush);
- }
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Brush *brush = BKE_paint_brush(paint);
+ // Object *ob = CTX_data_active_object(C);
+ float scalar = RNA_float_get(op->ptr, "scalar");
+
+ if (brush) {
+ // pixel radius
+ {
+ const int old_size = BKE_brush_size_get(scene, brush);
+ int size = (int)(scalar * old_size);
+
+ if (abs(old_size - size) < U.pixelsize) {
+ if (scalar > 1) {
+ size += U.pixelsize;
+ }
+ else if (scalar < 1) {
+ size -= U.pixelsize;
+ }
+ }
+
+ BKE_brush_size_set(scene, brush, size);
+ }
+
+ // unprojected radius
+ {
+ float unprojected_radius = scalar * BKE_brush_unprojected_radius_get(scene, brush);
+
+ if (unprojected_radius < 0.001f) // XXX magic number
+ unprojected_radius = 0.001f;
+
+ BKE_brush_unprojected_radius_set(scene, brush, unprojected_radius);
+ }
+
+ WM_main_add_notifier(NC_BRUSH | NA_EDITED, brush);
+ }
+
+ return OPERATOR_FINISHED;
}
static void BRUSH_OT_scale_size(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Scale Sculpt/Paint Brush Size";
- ot->description = "Change brush size by a scalar";
- ot->idname = "BRUSH_OT_scale_size";
+ /* identifiers */
+ ot->name = "Scale Sculpt/Paint Brush Size";
+ ot->description = "Change brush size by a scalar";
+ ot->idname = "BRUSH_OT_scale_size";
- /* api callbacks */
- ot->exec = brush_scale_size_exec;
+ /* api callbacks */
+ ot->exec = brush_scale_size_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_float(ot->srna, "scalar", 1, 0, 2, "Scalar", "Factor to scale brush size by", 0, 2);
+ RNA_def_float(ot->srna, "scalar", 1, 0, 2, "Scalar", "Factor to scale brush size by", 0, 2);
}
/* Palette operators */
static int palette_new_exec(bContext *C, wmOperator *UNUSED(op))
{
- Paint *paint = BKE_paint_get_active_from_context(C);
- Main *bmain = CTX_data_main(C);
- Palette *palette;
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Main *bmain = CTX_data_main(C);
+ Palette *palette;
- palette = BKE_palette_add(bmain, "Palette");
+ palette = BKE_palette_add(bmain, "Palette");
- BKE_paint_palette_set(paint, palette);
+ BKE_paint_palette_set(paint, palette);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void PALETTE_OT_new(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add New Palette";
- ot->description = "Add new palette";
- ot->idname = "PALETTE_OT_new";
+ /* identifiers */
+ ot->name = "Add New Palette";
+ ot->description = "Add new palette";
+ ot->idname = "PALETTE_OT_new";
- /* api callbacks */
- ot->exec = palette_new_exec;
+ /* api callbacks */
+ ot->exec = palette_new_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static bool palette_poll(bContext *C)
{
- Paint *paint = BKE_paint_get_active_from_context(C);
+ Paint *paint = BKE_paint_get_active_from_context(C);
- if (paint && paint->palette != NULL)
- return true;
+ if (paint && paint->palette != NULL)
+ return true;
- return false;
+ return false;
}
static int palette_color_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Paint *paint = BKE_paint_get_active_from_context(C);
- Brush *brush = paint->brush;
- ePaintMode mode = BKE_paintmode_get_active_from_context(C);
- Palette *palette = paint->palette;
- PaletteColor *color;
-
- color = BKE_palette_color_add(palette);
- palette->active_color = BLI_listbase_count(&palette->colors) - 1;
-
- if (ELEM(mode, PAINT_MODE_TEXTURE_3D, PAINT_MODE_TEXTURE_2D, PAINT_MODE_VERTEX)) {
- copy_v3_v3(color->rgb, BKE_brush_color_get(scene, brush));
- color->value = 0.0;
- }
- else if (mode == PAINT_MODE_WEIGHT) {
- zero_v3(color->rgb);
- color->value = brush->weight;
- }
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Brush *brush = paint->brush;
+ ePaintMode mode = BKE_paintmode_get_active_from_context(C);
+ Palette *palette = paint->palette;
+ PaletteColor *color;
+
+ color = BKE_palette_color_add(palette);
+ palette->active_color = BLI_listbase_count(&palette->colors) - 1;
+
+ if (ELEM(mode, PAINT_MODE_TEXTURE_3D, PAINT_MODE_TEXTURE_2D, PAINT_MODE_VERTEX)) {
+ copy_v3_v3(color->rgb, BKE_brush_color_get(scene, brush));
+ color->value = 0.0;
+ }
+ else if (mode == PAINT_MODE_WEIGHT) {
+ zero_v3(color->rgb);
+ color->value = brush->weight;
+ }
+
+ return OPERATOR_FINISHED;
}
static void PALETTE_OT_color_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "New Palette Color";
- ot->description = "Add new color to active palette";
- ot->idname = "PALETTE_OT_color_add";
-
- /* api callbacks */
- ot->exec = palette_color_add_exec;
- ot->poll = palette_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "New Palette Color";
+ ot->description = "Add new color to active palette";
+ ot->idname = "PALETTE_OT_color_add";
+
+ /* api callbacks */
+ ot->exec = palette_color_add_exec;
+ ot->poll = palette_poll;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int palette_color_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- Paint *paint = BKE_paint_get_active_from_context(C);
- Palette *palette = paint->palette;
- PaletteColor *color = BLI_findlink(&palette->colors, palette->active_color);
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Palette *palette = paint->palette;
+ PaletteColor *color = BLI_findlink(&palette->colors, palette->active_color);
- if (color) {
- BKE_palette_color_remove(palette, color);
- }
+ if (color) {
+ BKE_palette_color_remove(palette, color);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void PALETTE_OT_color_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Palette Color";
- ot->description = "Remove active color from palette";
- ot->idname = "PALETTE_OT_color_delete";
-
- /* api callbacks */
- ot->exec = palette_color_delete_exec;
- ot->poll = palette_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Delete Palette Color";
+ ot->description = "Remove active color from palette";
+ ot->idname = "PALETTE_OT_color_delete";
+
+ /* api callbacks */
+ ot->exec = palette_color_delete_exec;
+ ot->poll = palette_poll;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int brush_reset_exec(bContext *C, wmOperator *UNUSED(op))
{
- Paint *paint = BKE_paint_get_active_from_context(C);
- Brush *brush = BKE_paint_brush(paint);
- Object *ob = CTX_data_active_object(C);
-
- if (!ob || !brush) return OPERATOR_CANCELLED;
-
- /* TODO: other modes */
- if (ob->mode & OB_MODE_SCULPT) {
- BKE_brush_sculpt_reset(brush);
- }
- else {
- return OPERATOR_CANCELLED;
- }
- WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
-
- return OPERATOR_FINISHED;
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Brush *brush = BKE_paint_brush(paint);
+ Object *ob = CTX_data_active_object(C);
+
+ if (!ob || !brush)
+ return OPERATOR_CANCELLED;
+
+ /* TODO: other modes */
+ if (ob->mode & OB_MODE_SCULPT) {
+ BKE_brush_sculpt_reset(brush);
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+ WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
+
+ return OPERATOR_FINISHED;
}
static void BRUSH_OT_reset(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reset Brush";
- ot->description = "Return brush to defaults based on current tool";
- ot->idname = "BRUSH_OT_reset";
+ /* identifiers */
+ ot->name = "Reset Brush";
+ ot->description = "Return brush to defaults based on current tool";
+ ot->idname = "BRUSH_OT_reset";
- /* api callbacks */
- ot->exec = brush_reset_exec;
+ /* api callbacks */
+ ot->exec = brush_reset_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int brush_tool(const Brush *brush, size_t tool_offset)
{
- return *(((char *)brush) + tool_offset);
+ return *(((char *)brush) + tool_offset);
}
static void brush_tool_set(const Brush *brush, size_t tool_offset, int tool)
{
- *(((char *)brush) + tool_offset) = tool;
+ *(((char *)brush) + tool_offset) = tool;
}
static Brush *brush_tool_cycle(Main *bmain, Paint *paint, Brush *brush_orig, const int tool)
{
- Brush *brush, *first_brush;
-
- if (!brush_orig && !(brush_orig = bmain->brushes.first)) {
- return NULL;
- }
-
- if (brush_tool(brush_orig, paint->runtime.tool_offset) != tool) {
- /* If current brush's tool is different from what we need,
- * start cycling from the beginning of the list.
- * Such logic will activate the same exact brush not relating from
- * which tool user requests other tool.
- */
-
- /* Try to tool-slot first. */
- first_brush = BKE_paint_toolslots_brush_get(paint, tool);
- if (first_brush == NULL) {
- first_brush = bmain->brushes.first;
- }
- }
- else {
- /* If user wants to switch to brush with the same tool as
- * currently active brush do a cycling via all possible
- * brushes with requested tool.
- */
- first_brush = brush_orig->id.next ? brush_orig->id.next : bmain->brushes.first;
- }
-
- /* get the next brush with the active tool */
- brush = first_brush;
- do {
- if ((brush->ob_mode & paint->runtime.ob_mode) &&
- (brush_tool(brush, paint->runtime.tool_offset) == tool))
- {
- return brush;
- }
-
- brush = brush->id.next ? brush->id.next : bmain->brushes.first;
- } while (brush != first_brush);
-
- return NULL;
+ Brush *brush, *first_brush;
+
+ if (!brush_orig && !(brush_orig = bmain->brushes.first)) {
+ return NULL;
+ }
+
+ if (brush_tool(brush_orig, paint->runtime.tool_offset) != tool) {
+ /* If current brush's tool is different from what we need,
+ * start cycling from the beginning of the list.
+ * Such logic will activate the same exact brush not relating from
+ * which tool user requests other tool.
+ */
+
+ /* Try to tool-slot first. */
+ first_brush = BKE_paint_toolslots_brush_get(paint, tool);
+ if (first_brush == NULL) {
+ first_brush = bmain->brushes.first;
+ }
+ }
+ else {
+ /* If user wants to switch to brush with the same tool as
+ * currently active brush do a cycling via all possible
+ * brushes with requested tool.
+ */
+ first_brush = brush_orig->id.next ? brush_orig->id.next : bmain->brushes.first;
+ }
+
+ /* get the next brush with the active tool */
+ brush = first_brush;
+ do {
+ if ((brush->ob_mode & paint->runtime.ob_mode) &&
+ (brush_tool(brush, paint->runtime.tool_offset) == tool)) {
+ return brush;
+ }
+
+ brush = brush->id.next ? brush->id.next : bmain->brushes.first;
+ } while (brush != first_brush);
+
+ return NULL;
}
static Brush *brush_tool_toggle(Main *bmain, Paint *paint, Brush *brush_orig, const int tool)
{
- if (!brush_orig || brush_tool(brush_orig, paint->runtime.tool_offset) != tool) {
- Brush *br;
- /* if the current brush is not using the desired tool, look
- * for one that is */
- br = brush_tool_cycle(bmain, paint, brush_orig, tool);
- /* store the previously-selected brush */
- if (br)
- br->toggle_brush = brush_orig;
-
- return br;
- }
- else if (brush_orig->toggle_brush) {
- /* if current brush is using the desired tool, try to toggle
- * back to the previously selected brush. */
- return brush_orig->toggle_brush;
- }
- else
- return NULL;
+ if (!brush_orig || brush_tool(brush_orig, paint->runtime.tool_offset) != tool) {
+ Brush *br;
+ /* if the current brush is not using the desired tool, look
+ * for one that is */
+ br = brush_tool_cycle(bmain, paint, brush_orig, tool);
+ /* store the previously-selected brush */
+ if (br)
+ br->toggle_brush = brush_orig;
+
+ return br;
+ }
+ else if (brush_orig->toggle_brush) {
+ /* if current brush is using the desired tool, try to toggle
+ * back to the previously selected brush. */
+ return brush_orig->toggle_brush;
+ }
+ else
+ return NULL;
}
-static int brush_generic_tool_set(
- Main *bmain, Paint *paint, const int tool,
- const char *tool_name, const bool create_missing,
- const bool toggle)
+static int brush_generic_tool_set(Main *bmain,
+ Paint *paint,
+ const int tool,
+ const char *tool_name,
+ const bool create_missing,
+ const bool toggle)
{
- Brush *brush, *brush_orig = BKE_paint_brush(paint);
-
- if (toggle) {
- brush = brush_tool_toggle(bmain, paint, brush_orig, tool);
- }
- else {
- brush = brush_tool_cycle(bmain, paint, brush_orig, tool);
- }
-
- if (!brush && brush_tool(brush_orig, paint->runtime.tool_offset) != tool && create_missing) {
- 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);
- brush->toggle_brush = brush_orig;
- }
-
- if (brush) {
- BKE_paint_brush_set(paint, brush);
- BKE_paint_invalidate_overlay_all();
-
- WM_main_add_notifier(NC_BRUSH | NA_EDITED, brush);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Brush *brush, *brush_orig = BKE_paint_brush(paint);
+
+ if (toggle) {
+ brush = brush_tool_toggle(bmain, paint, brush_orig, tool);
+ }
+ else {
+ brush = brush_tool_cycle(bmain, paint, brush_orig, tool);
+ }
+
+ if (!brush && brush_tool(brush_orig, paint->runtime.tool_offset) != tool && create_missing) {
+ 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);
+ brush->toggle_brush = brush_orig;
+ }
+
+ if (brush) {
+ BKE_paint_brush_set(paint, brush);
+ BKE_paint_invalidate_overlay_all();
+
+ WM_main_add_notifier(NC_BRUSH | NA_EDITED, brush);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static const ePaintMode brush_select_paint_modes[] = {
- PAINT_MODE_SCULPT,
- PAINT_MODE_VERTEX,
- PAINT_MODE_WEIGHT,
- PAINT_MODE_TEXTURE_3D,
- PAINT_MODE_GPENCIL,
+ PAINT_MODE_SCULPT,
+ PAINT_MODE_VERTEX,
+ PAINT_MODE_WEIGHT,
+ PAINT_MODE_TEXTURE_3D,
+ PAINT_MODE_GPENCIL,
};
static int brush_select_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- const bool create_missing = RNA_boolean_get(op->ptr, "create_missing");
- const bool toggle = RNA_boolean_get(op->ptr, "toggle");
- const char *tool_name = "Brush";
- int tool = 0;
-
- ePaintMode paint_mode = PAINT_MODE_INVALID;
- for (int i = 0; i < ARRAY_SIZE(brush_select_paint_modes); i++) {
- paint_mode = brush_select_paint_modes[i];
- const char *op_prop_id = BKE_paint_get_tool_prop_id_from_paintmode(paint_mode);
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, op_prop_id);
- if (RNA_property_is_set(op->ptr, prop)) {
- tool = RNA_property_enum_get(op->ptr, prop);
- break;
- }
- }
-
- if (paint_mode == PAINT_MODE_INVALID) {
- return OPERATOR_CANCELLED;
- }
-
- Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
- const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode);
- RNA_enum_name_from_value(items, tool, &tool_name);
- return brush_generic_tool_set(
- bmain, paint, tool,
- tool_name, create_missing,
- toggle);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ const bool create_missing = RNA_boolean_get(op->ptr, "create_missing");
+ const bool toggle = RNA_boolean_get(op->ptr, "toggle");
+ const char *tool_name = "Brush";
+ int tool = 0;
+
+ ePaintMode paint_mode = PAINT_MODE_INVALID;
+ for (int i = 0; i < ARRAY_SIZE(brush_select_paint_modes); i++) {
+ paint_mode = brush_select_paint_modes[i];
+ const char *op_prop_id = BKE_paint_get_tool_prop_id_from_paintmode(paint_mode);
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, op_prop_id);
+ if (RNA_property_is_set(op->ptr, prop)) {
+ tool = RNA_property_enum_get(op->ptr, prop);
+ break;
+ }
+ }
+
+ if (paint_mode == PAINT_MODE_INVALID) {
+ return OPERATOR_CANCELLED;
+ }
+
+ Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
+ const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode);
+ RNA_enum_name_from_value(items, tool, &tool_name);
+ return brush_generic_tool_set(bmain, paint, tool, tool_name, create_missing, toggle);
}
static void PAINT_OT_brush_select(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Brush Select";
- ot->description = "Select a paint mode's brush by tool type";
- ot->idname = "PAINT_OT_brush_select";
-
- /* api callbacks */
- ot->exec = brush_select_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- /* All properties are hidden, so as not to show the redo panel. */
- for (int i = 0; i < ARRAY_SIZE(brush_select_paint_modes); i++) {
- const ePaintMode paint_mode = brush_select_paint_modes[i];
- const char *prop_id = BKE_paint_get_tool_prop_id_from_paintmode(paint_mode);
- prop = RNA_def_enum(ot->srna, prop_id, BKE_paint_get_tool_enum_from_paintmode(paint_mode), 0, prop_id, "");
- RNA_def_property_flag(prop, PROP_HIDDEN);
- }
-
- prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle between two brushes rather than cycling");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "create_missing", 0, "Create Missing", "If the requested brush type does not exist, create a new brush");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Brush Select";
+ ot->description = "Select a paint mode's brush by tool type";
+ ot->idname = "PAINT_OT_brush_select";
+
+ /* api callbacks */
+ ot->exec = brush_select_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ /* All properties are hidden, so as not to show the redo panel. */
+ for (int i = 0; i < ARRAY_SIZE(brush_select_paint_modes); i++) {
+ const ePaintMode paint_mode = brush_select_paint_modes[i];
+ const char *prop_id = BKE_paint_get_tool_prop_id_from_paintmode(paint_mode);
+ prop = RNA_def_enum(
+ ot->srna, prop_id, BKE_paint_get_tool_enum_from_paintmode(paint_mode), 0, prop_id, "");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ }
+
+ prop = RNA_def_boolean(
+ ot->srna, "toggle", 0, "Toggle", "Toggle between two brushes rather than cycling");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna,
+ "create_missing",
+ 0,
+ "Create Missing",
+ "If the requested brush type does not exist, create a new brush");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
static int brush_uv_sculpt_tool_set_exec(bContext *C, wmOperator *op)
{
- Brush *brush;
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = scene->toolsettings;
- ts->uv_sculpt_tool = RNA_enum_get(op->ptr, "tool");
- brush = ts->uvsculpt->paint.brush;
- /* To update toolshelf */
- WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
-
- return OPERATOR_FINISHED;
+ Brush *brush;
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
+ ts->uv_sculpt_tool = RNA_enum_get(op->ptr, "tool");
+ brush = ts->uvsculpt->paint.brush;
+ /* To update toolshelf */
+ WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
+
+ return OPERATOR_FINISHED;
}
static void BRUSH_OT_uv_sculpt_tool_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "UV Sculpt Tool Set";
- ot->description = "Set the UV sculpt tool";
- ot->idname = "BRUSH_OT_uv_sculpt_tool_set";
+ /* identifiers */
+ ot->name = "UV Sculpt Tool Set";
+ ot->description = "Set the UV sculpt tool";
+ ot->idname = "BRUSH_OT_uv_sculpt_tool_set";
- /* api callbacks */
- ot->exec = brush_uv_sculpt_tool_set_exec;
- ot->poll = uv_sculpt_poll;
+ /* api callbacks */
+ ot->exec = brush_uv_sculpt_tool_set_exec;
+ ot->poll = uv_sculpt_poll;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
- /* props */
- ot->prop = RNA_def_enum(ot->srna, "tool", rna_enum_uv_sculpt_tool_items, 0, "Tool", "");
+ /* props */
+ ot->prop = RNA_def_enum(ot->srna, "tool", rna_enum_uv_sculpt_tool_items, 0, "Tool", "");
}
/***** Stencil Control *****/
typedef enum {
- STENCIL_TRANSLATE,
- STENCIL_SCALE,
- STENCIL_ROTATE,
+ STENCIL_TRANSLATE,
+ STENCIL_SCALE,
+ STENCIL_ROTATE,
} StencilControlMode;
typedef enum {
- STENCIL_PRIMARY = 0,
- STENCIL_SECONDARY = 1,
+ STENCIL_PRIMARY = 0,
+ STENCIL_SECONDARY = 1,
} StencilTextureMode;
-
typedef enum {
- STENCIL_CONSTRAINT_X = 1,
- STENCIL_CONSTRAINT_Y = 2,
+ STENCIL_CONSTRAINT_X = 1,
+ STENCIL_CONSTRAINT_Y = 2,
} StencilConstraint;
typedef struct {
- float init_mouse[2];
- float init_spos[2];
- float init_sdim[2];
- float init_rot;
- float init_angle;
- float lenorig;
- float area_size[2];
- StencilControlMode mode;
- StencilConstraint constrain_mode;
- int mask; /* we are twaking mask or colour stencil */
- Brush *br;
- float *dim_target;
- float *rot_target;
- float *pos_target;
- short event_type;
+ float init_mouse[2];
+ float init_spos[2];
+ float init_sdim[2];
+ float init_rot;
+ float init_angle;
+ float lenorig;
+ float area_size[2];
+ StencilControlMode mode;
+ StencilConstraint constrain_mode;
+ int mask; /* we are twaking mask or colour stencil */
+ Brush *br;
+ float *dim_target;
+ float *rot_target;
+ float *pos_target;
+ short event_type;
} StencilControlData;
static void stencil_set_target(StencilControlData *scd)
{
- Brush *br = scd->br;
- float mdiff[2];
- if (scd->mask) {
- copy_v2_v2(scd->init_sdim, br->mask_stencil_dimension);
- copy_v2_v2(scd->init_spos, br->mask_stencil_pos);
- scd->init_rot = br->mask_mtex.rot;
-
- scd->dim_target = br->mask_stencil_dimension;
- scd->rot_target = &br->mask_mtex.rot;
- scd->pos_target = br->mask_stencil_pos;
-
- sub_v2_v2v2(mdiff, scd->init_mouse, br->mask_stencil_pos);
- }
- else {
- copy_v2_v2(scd->init_sdim, br->stencil_dimension);
- copy_v2_v2(scd->init_spos, br->stencil_pos);
- scd->init_rot = br->mtex.rot;
-
- scd->dim_target = br->stencil_dimension;
- scd->rot_target = &br->mtex.rot;
- scd->pos_target = br->stencil_pos;
-
- sub_v2_v2v2(mdiff, scd->init_mouse, br->stencil_pos);
- }
-
- scd->lenorig = len_v2(mdiff);
-
- scd->init_angle = atan2f(mdiff[1], mdiff[0]);
+ Brush *br = scd->br;
+ float mdiff[2];
+ if (scd->mask) {
+ copy_v2_v2(scd->init_sdim, br->mask_stencil_dimension);
+ copy_v2_v2(scd->init_spos, br->mask_stencil_pos);
+ scd->init_rot = br->mask_mtex.rot;
+
+ scd->dim_target = br->mask_stencil_dimension;
+ scd->rot_target = &br->mask_mtex.rot;
+ scd->pos_target = br->mask_stencil_pos;
+
+ sub_v2_v2v2(mdiff, scd->init_mouse, br->mask_stencil_pos);
+ }
+ else {
+ copy_v2_v2(scd->init_sdim, br->stencil_dimension);
+ copy_v2_v2(scd->init_spos, br->stencil_pos);
+ scd->init_rot = br->mtex.rot;
+
+ scd->dim_target = br->stencil_dimension;
+ scd->rot_target = &br->mtex.rot;
+ scd->pos_target = br->stencil_pos;
+
+ sub_v2_v2v2(mdiff, scd->init_mouse, br->stencil_pos);
+ }
+
+ scd->lenorig = len_v2(mdiff);
+
+ scd->init_angle = atan2f(mdiff[1], mdiff[0]);
}
static int stencil_control_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- 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);
- StencilControlData *scd;
- int mask = RNA_enum_get(op->ptr, "texmode");
-
- if (mask) {
- if (br->mask_mtex.brush_map_mode != MTEX_MAP_MODE_STENCIL)
- return OPERATOR_CANCELLED;
- }
- else {
- if (br->mtex.brush_map_mode != MTEX_MAP_MODE_STENCIL)
- return OPERATOR_CANCELLED;
- }
-
- scd = MEM_mallocN(sizeof(StencilControlData), "stencil_control");
- scd->mask = mask;
- scd->br = br;
-
- copy_v2_v2(scd->init_mouse, mvalf);
-
- stencil_set_target(scd);
-
- scd->mode = RNA_enum_get(op->ptr, "mode");
- scd->event_type = event->type;
- scd->area_size[0] = ar->winx;
- scd->area_size[1] = ar->winy;
-
-
- op->customdata = scd;
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
+ 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);
+ StencilControlData *scd;
+ int mask = RNA_enum_get(op->ptr, "texmode");
+
+ if (mask) {
+ if (br->mask_mtex.brush_map_mode != MTEX_MAP_MODE_STENCIL)
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ if (br->mtex.brush_map_mode != MTEX_MAP_MODE_STENCIL)
+ return OPERATOR_CANCELLED;
+ }
+
+ scd = MEM_mallocN(sizeof(StencilControlData), "stencil_control");
+ scd->mask = mask;
+ scd->br = br;
+
+ copy_v2_v2(scd->init_mouse, mvalf);
+
+ stencil_set_target(scd);
+
+ scd->mode = RNA_enum_get(op->ptr, "mode");
+ scd->event_type = event->type;
+ scd->area_size[0] = ar->winx;
+ scd->area_size[1] = ar->winy;
+
+ op->customdata = scd;
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
}
static void stencil_restore(StencilControlData *scd)
{
- copy_v2_v2(scd->dim_target, scd->init_sdim);
- copy_v2_v2(scd->pos_target, scd->init_spos);
- *scd->rot_target = scd->init_rot;
+ copy_v2_v2(scd->dim_target, scd->init_sdim);
+ copy_v2_v2(scd->pos_target, scd->init_spos);
+ *scd->rot_target = scd->init_rot;
}
static void stencil_control_cancel(bContext *UNUSED(C), wmOperator *op)
{
- StencilControlData *scd = op->customdata;
+ StencilControlData *scd = op->customdata;
- stencil_restore(scd);
- MEM_freeN(op->customdata);
+ stencil_restore(scd);
+ MEM_freeN(op->customdata);
}
static void stencil_control_calculate(StencilControlData *scd, const int mval[2])
{
#define PIXEL_MARGIN 5
- float mdiff[2];
- float mvalf[2] = {mval[0], mval[1]};
- switch (scd->mode) {
- case STENCIL_TRANSLATE:
- sub_v2_v2v2(mdiff, mvalf, scd->init_mouse);
- add_v2_v2v2(scd->pos_target, scd->init_spos, mdiff);
- CLAMP(scd->pos_target[0],
- -scd->dim_target[0] + PIXEL_MARGIN,
- scd->area_size[0] + scd->dim_target[0] - PIXEL_MARGIN);
-
- CLAMP(scd->pos_target[1],
- -scd->dim_target[1] + PIXEL_MARGIN,
- scd->area_size[1] + scd->dim_target[1] - PIXEL_MARGIN);
-
- break;
- case STENCIL_SCALE:
- {
- float len, factor;
- sub_v2_v2v2(mdiff, mvalf, scd->pos_target);
- len = len_v2(mdiff);
- factor = len / scd->lenorig;
- copy_v2_v2(mdiff, scd->init_sdim);
- if (scd->constrain_mode != STENCIL_CONSTRAINT_Y)
- mdiff[0] = factor * scd->init_sdim[0];
- 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);
- copy_v2_v2(scd->dim_target, mdiff);
- break;
- }
- case STENCIL_ROTATE:
- {
- float angle;
- sub_v2_v2v2(mdiff, mvalf, scd->pos_target);
- angle = atan2f(mdiff[1], mdiff[0]);
- angle = scd->init_rot + angle - scd->init_angle;
- if (angle < 0.0f)
- angle += (float)(2 * M_PI);
- if (angle > (float)(2 * M_PI))
- angle -= (float)(2 * M_PI);
- *scd->rot_target = angle;
- break;
- }
- }
+ float mdiff[2];
+ float mvalf[2] = {mval[0], mval[1]};
+ switch (scd->mode) {
+ case STENCIL_TRANSLATE:
+ sub_v2_v2v2(mdiff, mvalf, scd->init_mouse);
+ add_v2_v2v2(scd->pos_target, scd->init_spos, mdiff);
+ CLAMP(scd->pos_target[0],
+ -scd->dim_target[0] + PIXEL_MARGIN,
+ scd->area_size[0] + scd->dim_target[0] - PIXEL_MARGIN);
+
+ CLAMP(scd->pos_target[1],
+ -scd->dim_target[1] + PIXEL_MARGIN,
+ scd->area_size[1] + scd->dim_target[1] - PIXEL_MARGIN);
+
+ break;
+ case STENCIL_SCALE: {
+ float len, factor;
+ sub_v2_v2v2(mdiff, mvalf, scd->pos_target);
+ len = len_v2(mdiff);
+ factor = len / scd->lenorig;
+ copy_v2_v2(mdiff, scd->init_sdim);
+ if (scd->constrain_mode != STENCIL_CONSTRAINT_Y)
+ mdiff[0] = factor * scd->init_sdim[0];
+ 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);
+ copy_v2_v2(scd->dim_target, mdiff);
+ break;
+ }
+ case STENCIL_ROTATE: {
+ float angle;
+ sub_v2_v2v2(mdiff, mvalf, scd->pos_target);
+ angle = atan2f(mdiff[1], mdiff[0]);
+ angle = scd->init_rot + angle - scd->init_angle;
+ if (angle < 0.0f)
+ angle += (float)(2 * M_PI);
+ if (angle > (float)(2 * M_PI))
+ angle -= (float)(2 * M_PI);
+ *scd->rot_target = angle;
+ break;
+ }
+ }
#undef PIXEL_MARGIN
}
static int stencil_control_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- StencilControlData *scd = op->customdata;
-
- if (event->type == scd->event_type && event->val == KM_RELEASE) {
- MEM_freeN(op->customdata);
- WM_event_add_notifier(C, NC_WINDOW, NULL);
- return OPERATOR_FINISHED;
- }
-
- switch (event->type) {
- case MOUSEMOVE:
- stencil_control_calculate(scd, event->mval);
- break;
- case 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:
- if (event->val == KM_PRESS) {
-
- if (scd->constrain_mode == STENCIL_CONSTRAINT_X)
- scd->constrain_mode = 0;
- else
- scd->constrain_mode = STENCIL_CONSTRAINT_X;
-
- stencil_control_calculate(scd, event->mval);
- }
- break;
- case YKEY:
- if (event->val == KM_PRESS) {
- if (scd->constrain_mode == STENCIL_CONSTRAINT_Y)
- scd->constrain_mode = 0;
- else
- scd->constrain_mode = STENCIL_CONSTRAINT_Y;
-
- stencil_control_calculate(scd, event->mval);
- }
- break;
- default:
- break;
- }
-
- ED_region_tag_redraw(CTX_wm_region(C));
-
- return OPERATOR_RUNNING_MODAL;
+ StencilControlData *scd = op->customdata;
+
+ if (event->type == scd->event_type && event->val == KM_RELEASE) {
+ MEM_freeN(op->customdata);
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ return OPERATOR_FINISHED;
+ }
+
+ switch (event->type) {
+ case MOUSEMOVE:
+ stencil_control_calculate(scd, event->mval);
+ break;
+ case 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:
+ if (event->val == KM_PRESS) {
+
+ if (scd->constrain_mode == STENCIL_CONSTRAINT_X)
+ scd->constrain_mode = 0;
+ else
+ scd->constrain_mode = STENCIL_CONSTRAINT_X;
+
+ stencil_control_calculate(scd, event->mval);
+ }
+ break;
+ case YKEY:
+ if (event->val == KM_PRESS) {
+ if (scd->constrain_mode == STENCIL_CONSTRAINT_Y)
+ scd->constrain_mode = 0;
+ else
+ scd->constrain_mode = STENCIL_CONSTRAINT_Y;
+
+ stencil_control_calculate(scd, event->mval);
+ }
+ break;
+ default:
+ break;
+ }
+
+ ED_region_tag_redraw(CTX_wm_region(C));
+
+ return OPERATOR_RUNNING_MODAL;
}
static bool stencil_control_poll(bContext *C)
{
- ePaintMode mode = BKE_paintmode_get_active_from_context(C);
+ ePaintMode mode = BKE_paintmode_get_active_from_context(C);
- Paint *paint;
- Brush *br;
+ Paint *paint;
+ Brush *br;
- if (!paint_supports_texture(mode))
- return false;
+ if (!paint_supports_texture(mode))
+ return false;
- paint = BKE_paint_get_active_from_context(C);
- br = BKE_paint_brush(paint);
- return (br &&
- (br->mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL ||
- br->mask_mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL));
+ paint = BKE_paint_get_active_from_context(C);
+ br = BKE_paint_brush(paint);
+ return (br && (br->mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL ||
+ br->mask_mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL));
}
static void BRUSH_OT_stencil_control(wmOperatorType *ot)
{
- static const EnumPropertyItem stencil_control_items[] = {
- {STENCIL_TRANSLATE, "TRANSLATION", 0, "Translation", ""},
- {STENCIL_SCALE, "SCALE", 0, "Scale", ""},
- {STENCIL_ROTATE, "ROTATION", 0, "Rotation", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem stencil_texture_items[] = {
- {STENCIL_PRIMARY, "PRIMARY", 0, "Primary", ""},
- {STENCIL_SECONDARY, "SECONDARY", 0, "Secondary", ""},
- {0, NULL, 0, NULL, NULL},
- };
- /* identifiers */
- ot->name = "Stencil Brush Control";
- ot->description = "Control the stencil brush";
- ot->idname = "BRUSH_OT_stencil_control";
-
- /* api callbacks */
- ot->invoke = stencil_control_invoke;
- ot->modal = stencil_control_modal;
- ot->cancel = stencil_control_cancel;
- ot->poll = stencil_control_poll;
-
- /* flags */
- ot->flag = 0;
-
- PropertyRNA *prop;
- prop = RNA_def_enum(ot->srna, "mode", stencil_control_items, STENCIL_TRANSLATE, "Tool", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_enum(ot->srna, "texmode", stencil_texture_items, STENCIL_PRIMARY, "Tool", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ static const EnumPropertyItem stencil_control_items[] = {
+ {STENCIL_TRANSLATE, "TRANSLATION", 0, "Translation", ""},
+ {STENCIL_SCALE, "SCALE", 0, "Scale", ""},
+ {STENCIL_ROTATE, "ROTATION", 0, "Rotation", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem stencil_texture_items[] = {
+ {STENCIL_PRIMARY, "PRIMARY", 0, "Primary", ""},
+ {STENCIL_SECONDARY, "SECONDARY", 0, "Secondary", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+ /* identifiers */
+ ot->name = "Stencil Brush Control";
+ ot->description = "Control the stencil brush";
+ ot->idname = "BRUSH_OT_stencil_control";
+
+ /* api callbacks */
+ ot->invoke = stencil_control_invoke;
+ ot->modal = stencil_control_modal;
+ ot->cancel = stencil_control_cancel;
+ ot->poll = stencil_control_poll;
+
+ /* flags */
+ ot->flag = 0;
+
+ PropertyRNA *prop;
+ prop = RNA_def_enum(ot->srna, "mode", stencil_control_items, STENCIL_TRANSLATE, "Tool", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_enum(ot->srna, "texmode", stencil_texture_items, STENCIL_PRIMARY, "Tool", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
-
static int stencil_fit_image_aspect_exec(bContext *C, wmOperator *op)
{
- Paint *paint = BKE_paint_get_active_from_context(C);
- Brush *br = BKE_paint_brush(paint);
- bool use_scale = RNA_boolean_get(op->ptr, "use_scale");
- bool use_repeat = RNA_boolean_get(op->ptr, "use_repeat");
- bool do_mask = RNA_boolean_get(op->ptr, "mask");
- Tex *tex = NULL;
- MTex *mtex = NULL;
- if (br) {
- mtex = do_mask ? &br->mask_mtex : &br->mtex;
- tex = mtex->tex;
- }
-
- if (tex && tex->type == TEX_IMAGE && tex->ima) {
- float aspx, aspy;
- Image *ima = tex->ima;
- float orig_area, stencil_area, factor;
- ED_image_get_uv_aspect(ima, NULL, &aspx, &aspy);
-
- if (use_scale) {
- aspx *= mtex->size[0];
- aspy *= mtex->size[1];
- }
-
- if (use_repeat && tex->extend == TEX_REPEAT) {
- aspx *= tex->xrepeat;
- aspy *= tex->yrepeat;
- }
-
- orig_area = aspx * aspy;
-
- if (do_mask) {
- stencil_area = br->mask_stencil_dimension[0] * br->mask_stencil_dimension[1];
- }
- else {
- stencil_area = br->stencil_dimension[0] * br->stencil_dimension[1];
- }
-
- factor = sqrtf(stencil_area / orig_area);
-
- if (do_mask) {
- br->mask_stencil_dimension[0] = factor * aspx;
- br->mask_stencil_dimension[1] = factor * aspy;
-
- }
- else {
- br->stencil_dimension[0] = factor * aspx;
- br->stencil_dimension[1] = factor * aspy;
- }
- }
-
- WM_event_add_notifier(C, NC_WINDOW, NULL);
-
- return OPERATOR_FINISHED;
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Brush *br = BKE_paint_brush(paint);
+ bool use_scale = RNA_boolean_get(op->ptr, "use_scale");
+ bool use_repeat = RNA_boolean_get(op->ptr, "use_repeat");
+ bool do_mask = RNA_boolean_get(op->ptr, "mask");
+ Tex *tex = NULL;
+ MTex *mtex = NULL;
+ if (br) {
+ mtex = do_mask ? &br->mask_mtex : &br->mtex;
+ tex = mtex->tex;
+ }
+
+ if (tex && tex->type == TEX_IMAGE && tex->ima) {
+ float aspx, aspy;
+ Image *ima = tex->ima;
+ float orig_area, stencil_area, factor;
+ ED_image_get_uv_aspect(ima, NULL, &aspx, &aspy);
+
+ if (use_scale) {
+ aspx *= mtex->size[0];
+ aspy *= mtex->size[1];
+ }
+
+ if (use_repeat && tex->extend == TEX_REPEAT) {
+ aspx *= tex->xrepeat;
+ aspy *= tex->yrepeat;
+ }
+
+ orig_area = aspx * aspy;
+
+ if (do_mask) {
+ stencil_area = br->mask_stencil_dimension[0] * br->mask_stencil_dimension[1];
+ }
+ else {
+ stencil_area = br->stencil_dimension[0] * br->stencil_dimension[1];
+ }
+
+ factor = sqrtf(stencil_area / orig_area);
+
+ if (do_mask) {
+ br->mask_stencil_dimension[0] = factor * aspx;
+ br->mask_stencil_dimension[1] = factor * aspy;
+ }
+ else {
+ br->stencil_dimension[0] = factor * aspx;
+ br->stencil_dimension[1] = factor * aspy;
+ }
+ }
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+ return OPERATOR_FINISHED;
}
-
static void BRUSH_OT_stencil_fit_image_aspect(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Image Aspect";
- ot->description = "When using an image texture, adjust the stencil size to fit the image aspect ratio";
- ot->idname = "BRUSH_OT_stencil_fit_image_aspect";
-
- /* api callbacks */
- ot->exec = stencil_fit_image_aspect_exec;
- ot->poll = stencil_control_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "use_repeat", 1, "Use Repeat", "Use repeat mapping values");
- RNA_def_boolean(ot->srna, "use_scale", 1, "Use Scale", "Use texture scale values");
- RNA_def_boolean(ot->srna, "mask", 0, "Modify Mask Stencil", "Modify either the primary or mask stencil");
+ /* identifiers */
+ ot->name = "Image Aspect";
+ ot->description =
+ "When using an image texture, adjust the stencil size to fit the image aspect ratio";
+ ot->idname = "BRUSH_OT_stencil_fit_image_aspect";
+
+ /* api callbacks */
+ ot->exec = stencil_fit_image_aspect_exec;
+ ot->poll = stencil_control_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "use_repeat", 1, "Use Repeat", "Use repeat mapping values");
+ RNA_def_boolean(ot->srna, "use_scale", 1, "Use Scale", "Use texture scale values");
+ RNA_def_boolean(
+ ot->srna, "mask", 0, "Modify Mask Stencil", "Modify either the primary or mask stencil");
}
-
static int stencil_reset_transform_exec(bContext *C, wmOperator *op)
{
- Paint *paint = BKE_paint_get_active_from_context(C);
- Brush *br = BKE_paint_brush(paint);
- bool do_mask = RNA_boolean_get(op->ptr, "mask");
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Brush *br = BKE_paint_brush(paint);
+ bool do_mask = RNA_boolean_get(op->ptr, "mask");
- if (!br)
- return OPERATOR_CANCELLED;
+ if (!br)
+ return OPERATOR_CANCELLED;
- if (do_mask) {
- br->mask_stencil_pos[0] = 256;
- br->mask_stencil_pos[1] = 256;
+ if (do_mask) {
+ br->mask_stencil_pos[0] = 256;
+ br->mask_stencil_pos[1] = 256;
- br->mask_stencil_dimension[0] = 256;
- br->mask_stencil_dimension[1] = 256;
+ br->mask_stencil_dimension[0] = 256;
+ br->mask_stencil_dimension[1] = 256;
- br->mask_mtex.rot = 0;
- }
- else {
- br->stencil_pos[0] = 256;
- br->stencil_pos[1] = 256;
+ br->mask_mtex.rot = 0;
+ }
+ else {
+ br->stencil_pos[0] = 256;
+ br->stencil_pos[1] = 256;
- br->stencil_dimension[0] = 256;
- br->stencil_dimension[1] = 256;
+ br->stencil_dimension[0] = 256;
+ br->stencil_dimension[1] = 256;
- br->mtex.rot = 0;
- }
+ br->mtex.rot = 0;
+ }
- WM_event_add_notifier(C, NC_WINDOW, NULL);
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
static void BRUSH_OT_stencil_reset_transform(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reset Transform";
- ot->description = "Reset the stencil transformation to the default";
- ot->idname = "BRUSH_OT_stencil_reset_transform";
+ /* identifiers */
+ ot->name = "Reset Transform";
+ ot->description = "Reset the stencil transformation to the default";
+ ot->idname = "BRUSH_OT_stencil_reset_transform";
- /* api callbacks */
- ot->exec = stencil_reset_transform_exec;
- ot->poll = stencil_control_poll;
+ /* api callbacks */
+ ot->exec = stencil_reset_transform_exec;
+ ot->poll = stencil_control_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "mask", 0, "Modify Mask Stencil", "Modify either the primary or mask stencil");
+ RNA_def_boolean(
+ ot->srna, "mask", 0, "Modify Mask Stencil", "Modify either the primary or mask stencil");
}
-
/**************************** registration **********************************/
void ED_operatormacros_paint(void)
{
- wmOperatorType *ot;
- wmOperatorTypeMacro *otmacro;
-
- ot = WM_operatortype_append_macro(
- "PAINTCURVE_OT_add_point_slide", "Add Curve Point and Slide",
- "Add new curve point and slide it", OPTYPE_UNDO);
- ot->description = "Add new curve point and slide it";
- WM_operatortype_macro_define(ot, "PAINTCURVE_OT_add_point");
- otmacro = WM_operatortype_macro_define(ot, "PAINTCURVE_OT_slide");
- RNA_boolean_set(otmacro->ptr, "align", true);
- RNA_boolean_set(otmacro->ptr, "select", false);
+ wmOperatorType *ot;
+ wmOperatorTypeMacro *otmacro;
+
+ ot = WM_operatortype_append_macro("PAINTCURVE_OT_add_point_slide",
+ "Add Curve Point and Slide",
+ "Add new curve point and slide it",
+ OPTYPE_UNDO);
+ ot->description = "Add new curve point and slide it";
+ WM_operatortype_macro_define(ot, "PAINTCURVE_OT_add_point");
+ otmacro = WM_operatortype_macro_define(ot, "PAINTCURVE_OT_slide");
+ RNA_boolean_set(otmacro->ptr, "align", true);
+ RNA_boolean_set(otmacro->ptr, "select", false);
}
-
void ED_operatortypes_paint(void)
{
- /* palette */
- WM_operatortype_append(PALETTE_OT_new);
- WM_operatortype_append(PALETTE_OT_color_add);
- WM_operatortype_append(PALETTE_OT_color_delete);
-
- /* paint curve */
- WM_operatortype_append(PAINTCURVE_OT_new);
- WM_operatortype_append(PAINTCURVE_OT_add_point);
- WM_operatortype_append(PAINTCURVE_OT_delete_point);
- WM_operatortype_append(PAINTCURVE_OT_select);
- WM_operatortype_append(PAINTCURVE_OT_slide);
- WM_operatortype_append(PAINTCURVE_OT_draw);
- WM_operatortype_append(PAINTCURVE_OT_cursor);
-
- /* brush */
- WM_operatortype_append(BRUSH_OT_add);
- WM_operatortype_append(BRUSH_OT_add_gpencil);
- WM_operatortype_append(BRUSH_OT_scale_size);
- WM_operatortype_append(BRUSH_OT_curve_preset);
- WM_operatortype_append(BRUSH_OT_reset);
- WM_operatortype_append(BRUSH_OT_stencil_control);
- WM_operatortype_append(BRUSH_OT_stencil_fit_image_aspect);
- WM_operatortype_append(BRUSH_OT_stencil_reset_transform);
-
- /* note, particle uses a different system, can be added with existing operators in wm.py */
- WM_operatortype_append(PAINT_OT_brush_select);
- WM_operatortype_append(BRUSH_OT_uv_sculpt_tool_set);
-
- /* image */
- WM_operatortype_append(PAINT_OT_texture_paint_toggle);
- WM_operatortype_append(PAINT_OT_image_paint);
- WM_operatortype_append(PAINT_OT_sample_color);
- WM_operatortype_append(PAINT_OT_grab_clone);
- WM_operatortype_append(PAINT_OT_project_image);
- WM_operatortype_append(PAINT_OT_image_from_view);
- WM_operatortype_append(PAINT_OT_brush_colors_flip);
- WM_operatortype_append(PAINT_OT_add_texture_paint_slot);
- WM_operatortype_append(PAINT_OT_add_simple_uvs);
-
- /* weight */
- WM_operatortype_append(PAINT_OT_weight_paint_toggle);
- WM_operatortype_append(PAINT_OT_weight_paint);
- WM_operatortype_append(PAINT_OT_weight_set);
- WM_operatortype_append(PAINT_OT_weight_from_bones);
- WM_operatortype_append(PAINT_OT_weight_gradient);
- WM_operatortype_append(PAINT_OT_weight_sample);
- WM_operatortype_append(PAINT_OT_weight_sample_group);
-
- /* uv */
- WM_operatortype_append(SCULPT_OT_uv_sculpt_stroke);
-
- /* vertex selection */
- WM_operatortype_append(PAINT_OT_vert_select_all);
- WM_operatortype_append(PAINT_OT_vert_select_ungrouped);
-
- /* vertex */
- WM_operatortype_append(PAINT_OT_vertex_paint_toggle);
- WM_operatortype_append(PAINT_OT_vertex_paint);
- WM_operatortype_append(PAINT_OT_vertex_color_set);
- WM_operatortype_append(PAINT_OT_vertex_color_smooth);
-
- WM_operatortype_append(PAINT_OT_vertex_color_brightness_contrast);
- WM_operatortype_append(PAINT_OT_vertex_color_hsv);
- WM_operatortype_append(PAINT_OT_vertex_color_invert);
- WM_operatortype_append(PAINT_OT_vertex_color_levels);
- WM_operatortype_append(PAINT_OT_vertex_color_from_weight);
-
- /* face-select */
- WM_operatortype_append(PAINT_OT_face_select_linked);
- WM_operatortype_append(PAINT_OT_face_select_linked_pick);
- WM_operatortype_append(PAINT_OT_face_select_all);
- WM_operatortype_append(PAINT_OT_face_select_hide);
- WM_operatortype_append(PAINT_OT_face_select_reveal);
-
- /* partial visibility */
- WM_operatortype_append(PAINT_OT_hide_show);
-
- /* paint masking */
- WM_operatortype_append(PAINT_OT_mask_flood_fill);
- WM_operatortype_append(PAINT_OT_mask_lasso_gesture);
+ /* palette */
+ WM_operatortype_append(PALETTE_OT_new);
+ WM_operatortype_append(PALETTE_OT_color_add);
+ WM_operatortype_append(PALETTE_OT_color_delete);
+
+ /* paint curve */
+ WM_operatortype_append(PAINTCURVE_OT_new);
+ WM_operatortype_append(PAINTCURVE_OT_add_point);
+ WM_operatortype_append(PAINTCURVE_OT_delete_point);
+ WM_operatortype_append(PAINTCURVE_OT_select);
+ WM_operatortype_append(PAINTCURVE_OT_slide);
+ WM_operatortype_append(PAINTCURVE_OT_draw);
+ WM_operatortype_append(PAINTCURVE_OT_cursor);
+
+ /* brush */
+ WM_operatortype_append(BRUSH_OT_add);
+ WM_operatortype_append(BRUSH_OT_add_gpencil);
+ WM_operatortype_append(BRUSH_OT_scale_size);
+ WM_operatortype_append(BRUSH_OT_curve_preset);
+ WM_operatortype_append(BRUSH_OT_reset);
+ WM_operatortype_append(BRUSH_OT_stencil_control);
+ WM_operatortype_append(BRUSH_OT_stencil_fit_image_aspect);
+ WM_operatortype_append(BRUSH_OT_stencil_reset_transform);
+
+ /* note, particle uses a different system, can be added with existing operators in wm.py */
+ WM_operatortype_append(PAINT_OT_brush_select);
+ WM_operatortype_append(BRUSH_OT_uv_sculpt_tool_set);
+
+ /* image */
+ WM_operatortype_append(PAINT_OT_texture_paint_toggle);
+ WM_operatortype_append(PAINT_OT_image_paint);
+ WM_operatortype_append(PAINT_OT_sample_color);
+ WM_operatortype_append(PAINT_OT_grab_clone);
+ WM_operatortype_append(PAINT_OT_project_image);
+ WM_operatortype_append(PAINT_OT_image_from_view);
+ WM_operatortype_append(PAINT_OT_brush_colors_flip);
+ WM_operatortype_append(PAINT_OT_add_texture_paint_slot);
+ WM_operatortype_append(PAINT_OT_add_simple_uvs);
+
+ /* weight */
+ WM_operatortype_append(PAINT_OT_weight_paint_toggle);
+ WM_operatortype_append(PAINT_OT_weight_paint);
+ WM_operatortype_append(PAINT_OT_weight_set);
+ WM_operatortype_append(PAINT_OT_weight_from_bones);
+ WM_operatortype_append(PAINT_OT_weight_gradient);
+ WM_operatortype_append(PAINT_OT_weight_sample);
+ WM_operatortype_append(PAINT_OT_weight_sample_group);
+
+ /* uv */
+ WM_operatortype_append(SCULPT_OT_uv_sculpt_stroke);
+
+ /* vertex selection */
+ WM_operatortype_append(PAINT_OT_vert_select_all);
+ WM_operatortype_append(PAINT_OT_vert_select_ungrouped);
+
+ /* vertex */
+ WM_operatortype_append(PAINT_OT_vertex_paint_toggle);
+ WM_operatortype_append(PAINT_OT_vertex_paint);
+ WM_operatortype_append(PAINT_OT_vertex_color_set);
+ WM_operatortype_append(PAINT_OT_vertex_color_smooth);
+
+ WM_operatortype_append(PAINT_OT_vertex_color_brightness_contrast);
+ WM_operatortype_append(PAINT_OT_vertex_color_hsv);
+ WM_operatortype_append(PAINT_OT_vertex_color_invert);
+ WM_operatortype_append(PAINT_OT_vertex_color_levels);
+ WM_operatortype_append(PAINT_OT_vertex_color_from_weight);
+
+ /* face-select */
+ WM_operatortype_append(PAINT_OT_face_select_linked);
+ WM_operatortype_append(PAINT_OT_face_select_linked_pick);
+ WM_operatortype_append(PAINT_OT_face_select_all);
+ WM_operatortype_append(PAINT_OT_face_select_hide);
+ WM_operatortype_append(PAINT_OT_face_select_reveal);
+
+ /* partial visibility */
+ WM_operatortype_append(PAINT_OT_hide_show);
+
+ /* paint masking */
+ WM_operatortype_append(PAINT_OT_mask_flood_fill);
+ WM_operatortype_append(PAINT_OT_mask_lasso_gesture);
}
void ED_keymap_paint(wmKeyConfig *keyconf)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- keymap = WM_keymap_ensure(keyconf, "Paint Curve", 0, 0);
- keymap->poll = paint_curve_poll;
+ keymap = WM_keymap_ensure(keyconf, "Paint Curve", 0, 0);
+ keymap->poll = paint_curve_poll;
- /* Sculpt mode */
- keymap = WM_keymap_ensure(keyconf, "Sculpt", 0, 0);
- keymap->poll = sculpt_mode_poll;
+ /* Sculpt mode */
+ keymap = WM_keymap_ensure(keyconf, "Sculpt", 0, 0);
+ keymap->poll = sculpt_mode_poll;
- /* Vertex Paint mode */
- keymap = WM_keymap_ensure(keyconf, "Vertex Paint", 0, 0);
- keymap->poll = vertex_paint_mode_poll;
+ /* Vertex Paint mode */
+ keymap = WM_keymap_ensure(keyconf, "Vertex Paint", 0, 0);
+ keymap->poll = vertex_paint_mode_poll;
- /* Weight Paint mode */
- keymap = WM_keymap_ensure(keyconf, "Weight Paint", 0, 0);
- keymap->poll = weight_paint_mode_poll;
+ /* Weight Paint mode */
+ keymap = WM_keymap_ensure(keyconf, "Weight Paint", 0, 0);
+ keymap->poll = weight_paint_mode_poll;
- /*Weight paint's Vertex Selection Mode */
- keymap = WM_keymap_ensure(keyconf, "Weight Paint Vertex Selection", 0, 0);
- keymap->poll = vert_paint_poll;
+ /*Weight paint's Vertex Selection Mode */
+ keymap = WM_keymap_ensure(keyconf, "Weight Paint Vertex Selection", 0, 0);
+ keymap->poll = vert_paint_poll;
- /* Image/Texture Paint mode */
- keymap = WM_keymap_ensure(keyconf, "Image Paint", 0, 0);
- keymap->poll = image_texture_paint_poll;
+ /* Image/Texture Paint mode */
+ keymap = WM_keymap_ensure(keyconf, "Image Paint", 0, 0);
+ keymap->poll = image_texture_paint_poll;
- /* face-mask mode */
- keymap = WM_keymap_ensure(keyconf, "Face Mask", 0, 0);
- keymap->poll = facemask_paint_poll;
+ /* face-mask mode */
+ keymap = WM_keymap_ensure(keyconf, "Face Mask", 0, 0);
+ keymap->poll = facemask_paint_poll;
- keymap = WM_keymap_ensure(keyconf, "UV Sculpt", 0, 0);
- keymap->poll = uv_sculpt_keymap_poll;
+ keymap = WM_keymap_ensure(keyconf, "UV Sculpt", 0, 0);
+ keymap->poll = uv_sculpt_keymap_poll;
- /* paint stroke */
- keymap = paint_stroke_modal_keymap(keyconf);
- WM_modalkeymap_assign(keymap, "SCULPT_OT_brush_stroke");
+ /* paint stroke */
+ keymap = paint_stroke_modal_keymap(keyconf);
+ WM_modalkeymap_assign(keymap, "SCULPT_OT_brush_stroke");
}
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index d66224034eb..4a586f4f7df 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -21,7 +21,6 @@
* \ingroup edsculpt
*/
-
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
@@ -49,7 +48,6 @@
#include "WM_api.h"
#include "WM_types.h"
-
#include "GPU_immediate.h"
#include "GPU_state.h"
@@ -70,844 +68,847 @@
#endif
typedef struct PaintSample {
- float mouse[2];
- float pressure;
+ float mouse[2];
+ float pressure;
} PaintSample;
typedef struct PaintStroke {
- void *mode_data;
- void *stroke_cursor;
- wmTimer *timer;
- struct RNG *rng;
-
- /* Cached values */
- ViewContext vc;
- Brush *brush;
- UnifiedPaintSettings *ups;
-
- /* used for lines and curves */
- ListBase line;
-
- /* Paint stroke can use up to PAINT_MAX_INPUT_SAMPLES prior inputs
- * to smooth the stroke */
- PaintSample samples[PAINT_MAX_INPUT_SAMPLES];
- int num_samples;
- int cur_sample;
-
- float last_mouse_position[2];
- /* space distance covered so far */
- float stroke_distance;
-
- /* Set whether any stroke step has yet occurred
- * e.g. in sculpt mode, stroke doesn't start until cursor
- * passes over the mesh */
- bool stroke_started;
- /* Set when enough motion was found for rake rotation */
- bool rake_started;
- /* event that started stroke, for modal() return */
- int event_type;
- /* check if stroke variables have been initialized */
- bool stroke_init;
- /* check if various brush mapping variables have been initialized */
- bool brush_init;
- float initial_mouse[2];
- /* cached_pressure stores initial pressure for size pressure influence mainly */
- float cached_size_pressure;
- /* last pressure will store last pressure value for use in interpolation for space strokes */
- float last_pressure;
- int stroke_mode;
-
- float zoom_2d;
- int pen_flip;
-
- /* line constraint */
- bool constrain_line;
- float constrained_pos[2];
-
- StrokeGetLocation get_location;
- StrokeTestStart test_start;
- StrokeUpdateStep update_step;
- StrokeRedraw redraw;
- StrokeDone done;
+ void *mode_data;
+ void *stroke_cursor;
+ wmTimer *timer;
+ struct RNG *rng;
+
+ /* Cached values */
+ ViewContext vc;
+ Brush *brush;
+ UnifiedPaintSettings *ups;
+
+ /* used for lines and curves */
+ ListBase line;
+
+ /* Paint stroke can use up to PAINT_MAX_INPUT_SAMPLES prior inputs
+ * to smooth the stroke */
+ PaintSample samples[PAINT_MAX_INPUT_SAMPLES];
+ int num_samples;
+ int cur_sample;
+
+ float last_mouse_position[2];
+ /* space distance covered so far */
+ float stroke_distance;
+
+ /* Set whether any stroke step has yet occurred
+ * e.g. in sculpt mode, stroke doesn't start until cursor
+ * passes over the mesh */
+ bool stroke_started;
+ /* Set when enough motion was found for rake rotation */
+ bool rake_started;
+ /* event that started stroke, for modal() return */
+ int event_type;
+ /* check if stroke variables have been initialized */
+ bool stroke_init;
+ /* check if various brush mapping variables have been initialized */
+ bool brush_init;
+ float initial_mouse[2];
+ /* cached_pressure stores initial pressure for size pressure influence mainly */
+ float cached_size_pressure;
+ /* last pressure will store last pressure value for use in interpolation for space strokes */
+ float last_pressure;
+ int stroke_mode;
+
+ float zoom_2d;
+ int pen_flip;
+
+ /* line constraint */
+ bool constrain_line;
+ float constrained_pos[2];
+
+ StrokeGetLocation get_location;
+ StrokeTestStart test_start;
+ StrokeUpdateStep update_step;
+ StrokeRedraw redraw;
+ StrokeDone done;
} PaintStroke;
/*** Cursors ***/
static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata)
{
- Paint *paint = BKE_paint_get_active_from_context(C);
- Brush *brush = BKE_paint_brush(paint);
- PaintStroke *stroke = customdata;
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Brush *brush = BKE_paint_brush(paint);
+ PaintStroke *stroke = customdata;
- if (stroke && brush) {
- GPU_line_smooth(true);
- GPU_blend(true);
+ if (stroke && brush) {
+ GPU_line_smooth(true);
+ GPU_blend(true);
- ARegion *ar = stroke->vc.ar;
+ ARegion *ar = stroke->vc.ar;
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4ubv(paint->paint_cursor_col);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv(paint->paint_cursor_col);
- 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);
+ 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);
- immEnd();
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
- GPU_blend(false);
- GPU_line_smooth(false);
- }
+ GPU_blend(false);
+ GPU_line_smooth(false);
+ }
}
static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
{
- Paint *paint = BKE_paint_get_active_from_context(C);
- PaintStroke *stroke = customdata;
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ PaintStroke *stroke = customdata;
- GPU_line_smooth(true);
+ GPU_line_smooth(true);
- uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
- immUniform1i("colors_len", 2); /* "advanced" mode */
- const float alpha = (float)paint->paint_cursor_col[3] / 255.0f;
- immUniformArray4fv("colors", (float *)(float[][4]){{0.0f, 0.0f, 0.0f, alpha}, {1.0f, 1.0f, 1.0f, alpha}}, 2);
- immUniform1f("dash_width", 6.0f);
+ immUniform1i("colors_len", 2); /* "advanced" mode */
+ const float alpha = (float)paint->paint_cursor_col[3] / 255.0f;
+ immUniformArray4fv(
+ "colors", (float *)(float[][4]){{0.0f, 0.0f, 0.0f, alpha}, {1.0f, 1.0f, 1.0f, alpha}}, 2);
+ immUniform1f("dash_width", 6.0f);
- immBegin(GPU_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
- ARegion *ar = stroke->vc.ar;
+ ARegion *ar = stroke->vc.ar;
- if (stroke->constrain_line) {
- immVertex2f(shdr_pos,
- stroke->last_mouse_position[0] + ar->winrct.xmin,
- stroke->last_mouse_position[1] + ar->winrct.ymin);
+ if (stroke->constrain_line) {
+ immVertex2f(shdr_pos,
+ stroke->last_mouse_position[0] + ar->winrct.xmin,
+ stroke->last_mouse_position[1] + ar->winrct.ymin);
- immVertex2f(shdr_pos,
- stroke->constrained_pos[0] + ar->winrct.xmin,
- stroke->constrained_pos[1] + ar->winrct.ymin);
- }
- else {
- immVertex2f(shdr_pos,
- stroke->last_mouse_position[0] + ar->winrct.xmin,
- stroke->last_mouse_position[1] + ar->winrct.ymin);
+ immVertex2f(shdr_pos,
+ stroke->constrained_pos[0] + ar->winrct.xmin,
+ stroke->constrained_pos[1] + ar->winrct.ymin);
+ }
+ else {
+ immVertex2f(shdr_pos,
+ stroke->last_mouse_position[0] + ar->winrct.xmin,
+ stroke->last_mouse_position[1] + ar->winrct.ymin);
- immVertex2f(shdr_pos, x, y);
- }
+ immVertex2f(shdr_pos, x, y);
+ }
- immEnd();
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
- GPU_line_smooth(false);
+ GPU_line_smooth(false);
}
static bool paint_tool_require_location(Brush *brush, ePaintMode mode)
{
- switch (mode) {
- case PAINT_MODE_SCULPT:
- if (ELEM(brush->sculpt_tool,
- SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB))
- {
- return false;
- }
- else {
- return true;
- }
- default:
- break;
- }
-
- return true;
+ switch (mode) {
+ case PAINT_MODE_SCULPT:
+ if (ELEM(brush->sculpt_tool,
+ SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_SNAKE_HOOK,
+ SCULPT_TOOL_THUMB)) {
+ return false;
+ }
+ else {
+ return true;
+ }
+ default:
+ break;
+ }
+
+ return true;
}
/* Initialize the stroke cache variants from operator properties */
-static bool paint_brush_update(
- bContext *C,
- Brush *brush,
- ePaintMode mode,
- struct PaintStroke *stroke,
- const float mouse_init[2],
- float mouse[2], float pressure,
- float r_location[3], bool *r_location_is_set)
+static bool paint_brush_update(bContext *C,
+ Brush *brush,
+ ePaintMode mode,
+ struct PaintStroke *stroke,
+ const float mouse_init[2],
+ float mouse[2],
+ float pressure,
+ float r_location[3],
+ bool *r_location_is_set)
{
- Scene *scene = CTX_data_scene(C);
- UnifiedPaintSettings *ups = stroke->ups;
- bool location_sampled = false;
- bool location_success = false;
- /* Use to perform all operations except applying the stroke,
- * needed for operations that require cursor motion (rake). */
- bool is_dry_run = false;
- bool do_random = false;
- bool do_random_mask = false;
- *r_location_is_set = false;
- /* 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 (!stroke->brush_init) {
- copy_v2_v2(stroke->initial_mouse, mouse);
- copy_v2_v2(ups->last_rake, mouse);
- copy_v2_v2(ups->tex_mouse, mouse);
- copy_v2_v2(ups->mask_tex_mouse, mouse);
- stroke->cached_size_pressure = pressure;
-
- ups->do_linear_conversion = false;
- ups->colorspace = NULL;
-
- /* check here if color sampling the main brush should do color conversion. This is done here
- * to avoid locking up to get the image buffer during sampling */
- if (brush->mtex.tex && brush->mtex.tex->type == TEX_IMAGE && brush->mtex.tex->ima) {
- ImBuf *tex_ibuf = BKE_image_pool_acquire_ibuf(brush->mtex.tex->ima, &brush->mtex.tex->iuser, NULL);
- if (tex_ibuf && tex_ibuf->rect_float == NULL) {
- ups->do_linear_conversion = true;
- ups->colorspace = tex_ibuf->rect_colorspace;
- }
- BKE_image_pool_release_ibuf(brush->mtex.tex->ima, tex_ibuf, NULL);
- }
-
- stroke->brush_init = true;
- }
-
- if (paint_supports_dynamic_size(brush, mode)) {
- copy_v2_v2(ups->tex_mouse, mouse);
- copy_v2_v2(ups->mask_tex_mouse, mouse);
- stroke->cached_size_pressure = pressure;
- }
-
- /* Truly temporary data that isn't stored in properties */
-
- ups->stroke_active = true;
- ups->size_pressure_value = stroke->cached_size_pressure;
-
- ups->pixel_radius = BKE_brush_size_get(scene, brush);
-
- if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, mode)) {
- ups->pixel_radius *= stroke->cached_size_pressure;
- }
-
- if (paint_supports_dynamic_tex_coords(brush, mode)) {
-
- if (ELEM(brush->mtex.brush_map_mode,
- MTEX_MAP_MODE_VIEW,
- MTEX_MAP_MODE_AREA,
- MTEX_MAP_MODE_RANDOM))
- {
- do_random = true;
- }
-
- if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
- BKE_brush_randomize_texture_coords(ups, false);
- else {
- copy_v2_v2(ups->tex_mouse, mouse);
- }
-
- /* take care of mask texture, if any */
- if (brush->mask_mtex.tex) {
-
- if (ELEM(brush->mask_mtex.brush_map_mode,
- MTEX_MAP_MODE_VIEW,
- MTEX_MAP_MODE_AREA,
- MTEX_MAP_MODE_RANDOM))
- {
- do_random_mask = true;
- }
-
- if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
- BKE_brush_randomize_texture_coords(ups, true);
- else {
- copy_v2_v2(ups->mask_tex_mouse, mouse);
- }
- }
- }
-
-
- if (brush->flag & BRUSH_ANCHORED) {
- bool hit = false;
- float halfway[2];
-
- const float dx = mouse[0] - stroke->initial_mouse[0];
- const float dy = mouse[1] - stroke->initial_mouse[1];
-
- ups->anchored_size = ups->pixel_radius = sqrtf(dx * dx + dy * dy);
-
- ups->brush_rotation = ups->brush_rotation_sec = atan2f(dx, dy) + (float)M_PI;
-
- if (brush->flag & BRUSH_EDGE_TO_EDGE) {
- halfway[0] = dx * 0.5f + stroke->initial_mouse[0];
- halfway[1] = dy * 0.5f + stroke->initial_mouse[1];
-
- if (stroke->get_location) {
- if (stroke->get_location(C, r_location, halfway)) {
- hit = true;
- location_sampled = true;
- location_success = true;
- *r_location_is_set = true;
- }
- else if (!paint_tool_require_location(brush, mode)) {
- hit = true;
- }
- }
- else {
- hit = true;
- }
- }
- if (hit) {
- copy_v2_v2(ups->anchored_initial_mouse, halfway);
- copy_v2_v2(ups->tex_mouse, halfway);
- copy_v2_v2(ups->mask_tex_mouse, halfway);
- copy_v2_v2(mouse, halfway);
- ups->anchored_size /= 2.0f;
- ups->pixel_radius /= 2.0f;
- stroke->stroke_distance = ups->pixel_radius;
- }
- else {
- copy_v2_v2(ups->anchored_initial_mouse, stroke->initial_mouse);
- copy_v2_v2(mouse, stroke->initial_mouse);
- stroke->stroke_distance = ups->pixel_radius;
- }
- ups->pixel_radius /= stroke->zoom_2d;
- ups->draw_anchored = true;
- }
- else {
- /* here we are using the initial mouse coordinate because we do not want the rake
- * result to depend on jittering */
- if (!stroke->brush_init) {
- copy_v2_v2(ups->last_rake, mouse_init);
- }
- /* curve strokes do their own rake calculation */
- else if (!(brush->flag & BRUSH_CURVE)) {
- if (!paint_calculate_rake_rotation(ups, brush, mouse_init)) {
- /* Not enough motion to define an angle. */
- if (!stroke->rake_started) {
- is_dry_run = true;
- }
- }
- else {
- stroke->rake_started = true;
- }
- }
- }
-
- if ((do_random || do_random_mask) && stroke->rng == NULL) {
- /* Lazy initialization. */
- uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
- rng_seed ^= (uint)POINTER_AS_INT(brush);
- stroke->rng = BLI_rng_new(rng_seed);
- }
-
- if (do_random) {
- if (brush->mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) {
- ups->brush_rotation += -brush->mtex.random_angle / 2.0f +
- brush->mtex.random_angle * BLI_rng_get_float(stroke->rng);
- }
- }
-
- if (do_random_mask) {
- if (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) {
- ups->brush_rotation_sec += -brush->mask_mtex.random_angle / 2.0f +
- brush->mask_mtex.random_angle * BLI_rng_get_float(stroke->rng);
- }
- }
-
- if (!location_sampled) {
- if (stroke->get_location) {
- if (stroke->get_location(C, r_location, mouse)) {
- location_success = true;
- *r_location_is_set = true;
- }
- else if (!paint_tool_require_location(brush, mode))
- location_success = true;
- }
- else {
- zero_v3(r_location);
- location_success = true;
- /* don't set 'r_location_is_set', since we don't want to use the value. */
- }
- }
-
- return location_success && (is_dry_run == false);
+ Scene *scene = CTX_data_scene(C);
+ UnifiedPaintSettings *ups = stroke->ups;
+ bool location_sampled = false;
+ bool location_success = false;
+ /* Use to perform all operations except applying the stroke,
+ * needed for operations that require cursor motion (rake). */
+ bool is_dry_run = false;
+ bool do_random = false;
+ bool do_random_mask = false;
+ *r_location_is_set = false;
+ /* 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 (!stroke->brush_init) {
+ copy_v2_v2(stroke->initial_mouse, mouse);
+ copy_v2_v2(ups->last_rake, mouse);
+ copy_v2_v2(ups->tex_mouse, mouse);
+ copy_v2_v2(ups->mask_tex_mouse, mouse);
+ stroke->cached_size_pressure = pressure;
+
+ ups->do_linear_conversion = false;
+ ups->colorspace = NULL;
+
+ /* check here if color sampling the main brush should do color conversion. This is done here
+ * to avoid locking up to get the image buffer during sampling */
+ if (brush->mtex.tex && brush->mtex.tex->type == TEX_IMAGE && brush->mtex.tex->ima) {
+ ImBuf *tex_ibuf = BKE_image_pool_acquire_ibuf(
+ brush->mtex.tex->ima, &brush->mtex.tex->iuser, NULL);
+ if (tex_ibuf && tex_ibuf->rect_float == NULL) {
+ ups->do_linear_conversion = true;
+ ups->colorspace = tex_ibuf->rect_colorspace;
+ }
+ BKE_image_pool_release_ibuf(brush->mtex.tex->ima, tex_ibuf, NULL);
+ }
+
+ stroke->brush_init = true;
+ }
+
+ if (paint_supports_dynamic_size(brush, mode)) {
+ copy_v2_v2(ups->tex_mouse, mouse);
+ copy_v2_v2(ups->mask_tex_mouse, mouse);
+ stroke->cached_size_pressure = pressure;
+ }
+
+ /* Truly temporary data that isn't stored in properties */
+
+ ups->stroke_active = true;
+ ups->size_pressure_value = stroke->cached_size_pressure;
+
+ ups->pixel_radius = BKE_brush_size_get(scene, brush);
+
+ if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, mode)) {
+ ups->pixel_radius *= stroke->cached_size_pressure;
+ }
+
+ if (paint_supports_dynamic_tex_coords(brush, mode)) {
+
+ if (ELEM(brush->mtex.brush_map_mode,
+ MTEX_MAP_MODE_VIEW,
+ MTEX_MAP_MODE_AREA,
+ MTEX_MAP_MODE_RANDOM)) {
+ do_random = true;
+ }
+
+ if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
+ BKE_brush_randomize_texture_coords(ups, false);
+ else {
+ copy_v2_v2(ups->tex_mouse, mouse);
+ }
+
+ /* take care of mask texture, if any */
+ if (brush->mask_mtex.tex) {
+
+ if (ELEM(brush->mask_mtex.brush_map_mode,
+ MTEX_MAP_MODE_VIEW,
+ MTEX_MAP_MODE_AREA,
+ MTEX_MAP_MODE_RANDOM)) {
+ do_random_mask = true;
+ }
+
+ if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
+ BKE_brush_randomize_texture_coords(ups, true);
+ else {
+ copy_v2_v2(ups->mask_tex_mouse, mouse);
+ }
+ }
+ }
+
+ if (brush->flag & BRUSH_ANCHORED) {
+ bool hit = false;
+ float halfway[2];
+
+ const float dx = mouse[0] - stroke->initial_mouse[0];
+ const float dy = mouse[1] - stroke->initial_mouse[1];
+
+ ups->anchored_size = ups->pixel_radius = sqrtf(dx * dx + dy * dy);
+
+ ups->brush_rotation = ups->brush_rotation_sec = atan2f(dx, dy) + (float)M_PI;
+
+ if (brush->flag & BRUSH_EDGE_TO_EDGE) {
+ halfway[0] = dx * 0.5f + stroke->initial_mouse[0];
+ halfway[1] = dy * 0.5f + stroke->initial_mouse[1];
+
+ if (stroke->get_location) {
+ if (stroke->get_location(C, r_location, halfway)) {
+ hit = true;
+ location_sampled = true;
+ location_success = true;
+ *r_location_is_set = true;
+ }
+ else if (!paint_tool_require_location(brush, mode)) {
+ hit = true;
+ }
+ }
+ else {
+ hit = true;
+ }
+ }
+ if (hit) {
+ copy_v2_v2(ups->anchored_initial_mouse, halfway);
+ copy_v2_v2(ups->tex_mouse, halfway);
+ copy_v2_v2(ups->mask_tex_mouse, halfway);
+ copy_v2_v2(mouse, halfway);
+ ups->anchored_size /= 2.0f;
+ ups->pixel_radius /= 2.0f;
+ stroke->stroke_distance = ups->pixel_radius;
+ }
+ else {
+ copy_v2_v2(ups->anchored_initial_mouse, stroke->initial_mouse);
+ copy_v2_v2(mouse, stroke->initial_mouse);
+ stroke->stroke_distance = ups->pixel_radius;
+ }
+ ups->pixel_radius /= stroke->zoom_2d;
+ ups->draw_anchored = true;
+ }
+ else {
+ /* here we are using the initial mouse coordinate because we do not want the rake
+ * result to depend on jittering */
+ if (!stroke->brush_init) {
+ copy_v2_v2(ups->last_rake, mouse_init);
+ }
+ /* curve strokes do their own rake calculation */
+ else if (!(brush->flag & BRUSH_CURVE)) {
+ if (!paint_calculate_rake_rotation(ups, brush, mouse_init)) {
+ /* Not enough motion to define an angle. */
+ if (!stroke->rake_started) {
+ is_dry_run = true;
+ }
+ }
+ else {
+ stroke->rake_started = true;
+ }
+ }
+ }
+
+ if ((do_random || do_random_mask) && stroke->rng == NULL) {
+ /* Lazy initialization. */
+ uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
+ rng_seed ^= (uint)POINTER_AS_INT(brush);
+ stroke->rng = BLI_rng_new(rng_seed);
+ }
+
+ if (do_random) {
+ if (brush->mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) {
+ ups->brush_rotation += -brush->mtex.random_angle / 2.0f +
+ brush->mtex.random_angle * BLI_rng_get_float(stroke->rng);
+ }
+ }
+
+ if (do_random_mask) {
+ if (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) {
+ ups->brush_rotation_sec += -brush->mask_mtex.random_angle / 2.0f +
+ brush->mask_mtex.random_angle * BLI_rng_get_float(stroke->rng);
+ }
+ }
+
+ if (!location_sampled) {
+ if (stroke->get_location) {
+ if (stroke->get_location(C, r_location, mouse)) {
+ location_success = true;
+ *r_location_is_set = true;
+ }
+ else if (!paint_tool_require_location(brush, mode))
+ location_success = true;
+ }
+ else {
+ zero_v3(r_location);
+ location_success = true;
+ /* don't set 'r_location_is_set', since we don't want to use the value. */
+ }
+ }
+
+ return location_success && (is_dry_run == false);
}
static bool paint_stroke_use_jitter(ePaintMode mode, Brush *brush, bool invert)
{
- bool use_jitter = (brush->flag & BRUSH_ABSOLUTE_JITTER) ?
- (brush->jitter_absolute != 0) : (brush->jitter != 0);
-
- /* jitter-ed brush gives weird and unpredictable result for this
- * kinds of stroke, so manually disable jitter usage (sergey) */
- use_jitter &= (brush->flag & (BRUSH_DRAG_DOT | BRUSH_ANCHORED)) == 0;
- use_jitter &= (!ELEM(mode, PAINT_MODE_TEXTURE_2D, PAINT_MODE_TEXTURE_3D) ||
- !(invert && brush->imagepaint_tool == PAINT_TOOL_CLONE));
+ bool use_jitter = (brush->flag & BRUSH_ABSOLUTE_JITTER) ? (brush->jitter_absolute != 0) :
+ (brush->jitter != 0);
+ /* jitter-ed brush gives weird and unpredictable result for this
+ * kinds of stroke, so manually disable jitter usage (sergey) */
+ use_jitter &= (brush->flag & (BRUSH_DRAG_DOT | BRUSH_ANCHORED)) == 0;
+ use_jitter &= (!ELEM(mode, PAINT_MODE_TEXTURE_2D, PAINT_MODE_TEXTURE_3D) ||
+ !(invert && brush->imagepaint_tool == PAINT_TOOL_CLONE));
- return use_jitter;
+ return use_jitter;
}
/* Put the location of the next stroke dot into the stroke RNA and apply it to the mesh */
-static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float mouse_in[2], float pressure)
+static void paint_brush_stroke_add_step(bContext *C,
+ wmOperator *op,
+ const float mouse_in[2],
+ float pressure)
{
- Scene *scene = CTX_data_scene(C);
- Paint *paint = BKE_paint_get_active_from_context(C);
- ePaintMode mode = BKE_paintmode_get_active_from_context(C);
- Brush *brush = BKE_paint_brush(paint);
- PaintStroke *stroke = op->customdata;
- UnifiedPaintSettings *ups = stroke->ups;
- float mouse_out[2];
- PointerRNA itemptr;
- float location[3];
+ Scene *scene = CTX_data_scene(C);
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ ePaintMode mode = BKE_paintmode_get_active_from_context(C);
+ Brush *brush = BKE_paint_brush(paint);
+ PaintStroke *stroke = op->customdata;
+ UnifiedPaintSettings *ups = stroke->ups;
+ float mouse_out[2];
+ PointerRNA itemptr;
+ float location[3];
/* the following code is adapted from texture paint. It may not be needed but leaving here
* just in case for reference (code in texpaint removed as part of refactoring).
* It's strange that only texpaint had these guards. */
#if 0
- /* special exception here for too high pressure values on first touch in
- * windows for some tablets, then we just skip first touch .. */
- if (tablet && (pressure >= 0.99f) &&
- ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) ||
- BKE_brush_use_alpha_pressure(scene, pop->s.brush) ||
- BKE_brush_use_size_pressure(scene, pop->s.brush)))
- {
- return;
- }
-
- /* This can be removed once fixed properly in
- * BKE_brush_painter_paint(
- * BrushPainter *painter, BrushFunc func,
- * float *pos, double time, float pressure, void *user);
- * at zero pressure we should do nothing 1/2^12 is 0.0002
- * which is the sensitivity of the most sensitive pen tablet available */
- if (tablet && (pressure < 0.0002f) &&
- ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) ||
- BKE_brush_use_alpha_pressure(scene, pop->s.brush) ||
- BKE_brush_use_size_pressure(scene, pop->s.brush)))
- {
- return;
- }
+ /* special exception here for too high pressure values on first touch in
+ * windows for some tablets, then we just skip first touch .. */
+ if (tablet && (pressure >= 0.99f) &&
+ ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) ||
+ BKE_brush_use_alpha_pressure(scene, pop->s.brush) ||
+ BKE_brush_use_size_pressure(scene, pop->s.brush)))
+ {
+ return;
+ }
+
+ /* This can be removed once fixed properly in
+ * BKE_brush_painter_paint(
+ * BrushPainter *painter, BrushFunc func,
+ * float *pos, double time, float pressure, void *user);
+ * at zero pressure we should do nothing 1/2^12 is 0.0002
+ * which is the sensitivity of the most sensitive pen tablet available */
+ if (tablet && (pressure < 0.0002f) &&
+ ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) ||
+ BKE_brush_use_alpha_pressure(scene, pop->s.brush) ||
+ BKE_brush_use_size_pressure(scene, pop->s.brush)))
+ {
+ return;
+ }
#endif
- /* copy last position -before- jittering, or space fill code
- * will create too many dabs */
- copy_v2_v2(stroke->last_mouse_position, mouse_in);
- stroke->last_pressure = pressure;
-
- if (paint_stroke_use_jitter(mode, brush, stroke->stroke_mode == BRUSH_STROKE_INVERT)) {
- float delta[2];
- float factor = stroke->zoom_2d;
-
- if (brush->flag & BRUSH_JITTER_PRESSURE)
- factor *= pressure;
-
- BKE_brush_jitter_pos(scene, brush, mouse_in, mouse_out);
-
- /* XXX: meh, this is round about because
- * BKE_brush_jitter_pos isn't written in the best way to
- * be reused here */
- if (factor != 1.0f) {
- sub_v2_v2v2(delta, mouse_out, mouse_in);
- mul_v2_fl(delta, factor);
- add_v2_v2v2(mouse_out, mouse_in, delta);
- }
- }
- else {
- copy_v2_v2(mouse_out, mouse_in);
- }
-
-
- bool is_location_is_set;
- ups->last_hit = paint_brush_update(
- C, brush, mode, stroke, mouse_in, mouse_out, pressure,
- location, &is_location_is_set);
- if (is_location_is_set) {
- copy_v3_v3(ups->last_location, location);
- }
- if (!ups->last_hit) {
- return;
- }
-
- /* Add to stroke */
- RNA_collection_add(op->ptr, "stroke", &itemptr);
- RNA_float_set(&itemptr, "size", ups->pixel_radius);
- RNA_float_set_array(&itemptr, "location", location);
- RNA_float_set_array(&itemptr, "mouse", mouse_out);
- RNA_boolean_set(&itemptr, "pen_flip", stroke->pen_flip);
- RNA_float_set(&itemptr, "pressure", pressure);
-
- stroke->update_step(C, stroke, &itemptr);
-
- /* don't record this for now, it takes up a lot of memory when doing long
- * strokes with small brush size, and operators have register disabled */
- RNA_collection_clear(op->ptr, "stroke");
+ /* copy last position -before- jittering, or space fill code
+ * will create too many dabs */
+ copy_v2_v2(stroke->last_mouse_position, mouse_in);
+ stroke->last_pressure = pressure;
+
+ if (paint_stroke_use_jitter(mode, brush, stroke->stroke_mode == BRUSH_STROKE_INVERT)) {
+ float delta[2];
+ float factor = stroke->zoom_2d;
+
+ if (brush->flag & BRUSH_JITTER_PRESSURE)
+ factor *= pressure;
+
+ BKE_brush_jitter_pos(scene, brush, mouse_in, mouse_out);
+
+ /* XXX: meh, this is round about because
+ * BKE_brush_jitter_pos isn't written in the best way to
+ * be reused here */
+ if (factor != 1.0f) {
+ sub_v2_v2v2(delta, mouse_out, mouse_in);
+ mul_v2_fl(delta, factor);
+ add_v2_v2v2(mouse_out, mouse_in, delta);
+ }
+ }
+ else {
+ copy_v2_v2(mouse_out, mouse_in);
+ }
+
+ bool is_location_is_set;
+ ups->last_hit = paint_brush_update(
+ C, brush, mode, stroke, mouse_in, mouse_out, pressure, location, &is_location_is_set);
+ if (is_location_is_set) {
+ copy_v3_v3(ups->last_location, location);
+ }
+ if (!ups->last_hit) {
+ return;
+ }
+
+ /* Add to stroke */
+ RNA_collection_add(op->ptr, "stroke", &itemptr);
+ RNA_float_set(&itemptr, "size", ups->pixel_radius);
+ RNA_float_set_array(&itemptr, "location", location);
+ RNA_float_set_array(&itemptr, "mouse", mouse_out);
+ RNA_boolean_set(&itemptr, "pen_flip", stroke->pen_flip);
+ RNA_float_set(&itemptr, "pressure", pressure);
+
+ stroke->update_step(C, stroke, &itemptr);
+
+ /* don't record this for now, it takes up a lot of memory when doing long
+ * strokes with small brush size, and operators have register disabled */
+ RNA_collection_clear(op->ptr, "stroke");
}
/* Returns zero if no sculpt changes should be made, non-zero otherwise */
-static bool paint_smooth_stroke(
- PaintStroke *stroke, const PaintSample *sample, ePaintMode mode,
- float r_mouse[2], float *r_pressure)
+static bool paint_smooth_stroke(PaintStroke *stroke,
+ const PaintSample *sample,
+ ePaintMode mode,
+ float r_mouse[2],
+ float *r_pressure)
{
- if (paint_supports_smooth_stroke(stroke->brush, mode)) {
- float radius = stroke->brush->smooth_stroke_radius * stroke->zoom_2d;
- float u = stroke->brush->smooth_stroke_factor;
-
- /* 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)) {
- return false;
- }
-
- interp_v2_v2v2(r_mouse, sample->mouse, stroke->last_mouse_position, u);
- *r_pressure = interpf(sample->pressure, stroke->last_pressure, u);
- }
- else {
- r_mouse[0] = sample->mouse[0];
- r_mouse[1] = sample->mouse[1];
- *r_pressure = sample->pressure;
- }
-
- return true;
+ if (paint_supports_smooth_stroke(stroke->brush, mode)) {
+ float radius = stroke->brush->smooth_stroke_radius * stroke->zoom_2d;
+ float u = stroke->brush->smooth_stroke_factor;
+
+ /* 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)) {
+ return false;
+ }
+
+ interp_v2_v2v2(r_mouse, sample->mouse, stroke->last_mouse_position, u);
+ *r_pressure = interpf(sample->pressure, stroke->last_pressure, u);
+ }
+ else {
+ r_mouse[0] = sample->mouse[0];
+ r_mouse[1] = sample->mouse[1];
+ *r_pressure = sample->pressure;
+ }
+
+ return true;
}
-static float paint_space_stroke_spacing(
- const Scene *scene, PaintStroke *stroke, float size_pressure, float spacing_pressure)
+static float paint_space_stroke_spacing(const Scene *scene,
+ PaintStroke *stroke,
+ float size_pressure,
+ float spacing_pressure)
{
- /* brushes can have a minimum size of 1.0 but with pressure it can be smaller then a pixel
- * causing very high step sizes, hanging blender [#32381] */
- const float size_clamp = max_ff(1.0f, BKE_brush_size_get(scene, stroke->brush) * size_pressure);
- float spacing = stroke->brush->spacing;
+ /* brushes can have a minimum size of 1.0 but with pressure it can be smaller then a pixel
+ * causing very high step sizes, hanging blender [#32381] */
+ const float size_clamp = max_ff(1.0f, BKE_brush_size_get(scene, stroke->brush) * size_pressure);
+ float spacing = stroke->brush->spacing;
- /* apply spacing pressure */
- if (stroke->brush->flag & BRUSH_SPACING_PRESSURE)
- spacing = spacing * (1.5f - spacing_pressure);
+ /* apply spacing pressure */
+ if (stroke->brush->flag & BRUSH_SPACING_PRESSURE)
+ spacing = spacing * (1.5f - spacing_pressure);
- /* stroke system is used for 2d paint too, so we need to account for
- * the fact that brush can be scaled there. */
- spacing *= stroke->zoom_2d;
+ /* stroke system is used for 2d paint too, so we need to account for
+ * the fact that brush can be scaled there. */
+ spacing *= stroke->zoom_2d;
- return max_ff(1.0, size_clamp * spacing / 50.0f);
+ return max_ff(1.0, size_clamp * spacing / 50.0f);
}
-
-
static float paint_stroke_overlapped_curve(Brush *br, float x, float spacing)
{
- int i;
- const int n = 100 / spacing;
- const float h = spacing / 50.0f;
- const float x0 = x - 1;
+ int i;
+ const int n = 100 / spacing;
+ const float h = spacing / 50.0f;
+ const float x0 = x - 1;
- float sum;
+ float sum;
- sum = 0;
- for (i = 0; i < n; i++) {
- float xx;
+ sum = 0;
+ for (i = 0; i < n; i++) {
+ float xx;
- xx = fabsf(x0 + i * h);
+ xx = fabsf(x0 + i * h);
- if (xx < 1.0f)
- sum += BKE_brush_curve_strength(br, xx, 1);
- }
+ if (xx < 1.0f)
+ sum += BKE_brush_curve_strength(br, xx, 1);
+ }
- return sum;
+ return sum;
}
static float paint_stroke_integrate_overlap(Brush *br, float factor)
{
- int i;
- int m;
- float g;
- float max;
-
- float spacing = br->spacing * factor;
-
- if (!(br->flag & BRUSH_SPACE_ATTEN && (br->spacing < 100)))
- return 1.0;
-
- m = 10;
- g = 1.0f / m;
- max = 0;
- for (i = 0; i < m; i++) {
- float overlap = fabs(paint_stroke_overlapped_curve(br, i * g, spacing));
-
- if (overlap > max)
- max = overlap;
- }
-
- if (max == 0.0f)
- return 1.0f;
- else
- return 1.0f / max;
+ int i;
+ int m;
+ float g;
+ float max;
+
+ float spacing = br->spacing * factor;
+
+ if (!(br->flag & BRUSH_SPACE_ATTEN && (br->spacing < 100)))
+ return 1.0;
+
+ m = 10;
+ g = 1.0f / m;
+ max = 0;
+ for (i = 0; i < m; i++) {
+ float overlap = fabs(paint_stroke_overlapped_curve(br, i * g, spacing));
+
+ if (overlap > max)
+ max = overlap;
+ }
+
+ if (max == 0.0f)
+ return 1.0f;
+ else
+ return 1.0f / max;
}
static float paint_space_stroke_spacing_variable(
- const Scene *scene, PaintStroke *stroke, float pressure, float dpressure, float length)
+ const Scene *scene, PaintStroke *stroke, float pressure, float dpressure, float length)
{
- if (BKE_brush_use_size_pressure(scene, stroke->brush)) {
- /* use pressure to modify size. set spacing so that at 100%, the circles
- * are aligned nicely with no overlap. for this the spacing needs to be
- * the average of the previous and next size. */
- float s = paint_space_stroke_spacing(scene, stroke, 1.0f, pressure);
- float q = s * dpressure / (2.0f * length);
- float pressure_fac = (1.0f + q) / (1.0f - q);
-
- float last_size_pressure = stroke->last_pressure;
- float new_size_pressure = stroke->last_pressure * pressure_fac;
-
- /* average spacing */
- float last_spacing = paint_space_stroke_spacing(scene, stroke, last_size_pressure, pressure);
- float new_spacing = paint_space_stroke_spacing(scene, stroke, new_size_pressure, pressure);
-
- return 0.5f * (last_spacing + new_spacing);
- }
- else {
- /* no size pressure */
- return paint_space_stroke_spacing(scene, stroke, 1.0f, pressure);
- }
+ if (BKE_brush_use_size_pressure(scene, stroke->brush)) {
+ /* use pressure to modify size. set spacing so that at 100%, the circles
+ * are aligned nicely with no overlap. for this the spacing needs to be
+ * the average of the previous and next size. */
+ float s = paint_space_stroke_spacing(scene, stroke, 1.0f, pressure);
+ float q = s * dpressure / (2.0f * length);
+ float pressure_fac = (1.0f + q) / (1.0f - q);
+
+ float last_size_pressure = stroke->last_pressure;
+ float new_size_pressure = stroke->last_pressure * pressure_fac;
+
+ /* average spacing */
+ float last_spacing = paint_space_stroke_spacing(scene, stroke, last_size_pressure, pressure);
+ float new_spacing = paint_space_stroke_spacing(scene, stroke, new_size_pressure, pressure);
+
+ return 0.5f * (last_spacing + new_spacing);
+ }
+ else {
+ /* no size pressure */
+ return paint_space_stroke_spacing(scene, stroke, 1.0f, pressure);
+ }
}
/* For brushes with stroke spacing enabled, moves mouse in steps
* towards the final mouse location. */
-static int paint_space_stroke(bContext *C, wmOperator *op, const float final_mouse[2], float final_pressure)
+static int paint_space_stroke(bContext *C,
+ wmOperator *op,
+ const float final_mouse[2],
+ float final_pressure)
{
- const Scene *scene = CTX_data_scene(C);
- PaintStroke *stroke = op->customdata;
- UnifiedPaintSettings *ups = stroke->ups;
- int cnt = 0;
+ const Scene *scene = CTX_data_scene(C);
+ PaintStroke *stroke = op->customdata;
+ UnifiedPaintSettings *ups = stroke->ups;
+ int cnt = 0;
- float pressure, dpressure;
- float mouse[2], dmouse[2];
- float length;
- float no_pressure_spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
+ float pressure, dpressure;
+ float mouse[2], dmouse[2];
+ float length;
+ float no_pressure_spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
- sub_v2_v2v2(dmouse, final_mouse, stroke->last_mouse_position);
+ sub_v2_v2v2(dmouse, final_mouse, stroke->last_mouse_position);
- pressure = stroke->last_pressure;
- dpressure = final_pressure - stroke->last_pressure;
+ pressure = stroke->last_pressure;
+ dpressure = final_pressure - stroke->last_pressure;
- length = normalize_v2(dmouse);
+ length = normalize_v2(dmouse);
- while (length > 0.0f) {
- float spacing = paint_space_stroke_spacing_variable(scene, stroke, pressure, dpressure, length);
+ while (length > 0.0f) {
+ float spacing = paint_space_stroke_spacing_variable(
+ scene, stroke, pressure, dpressure, length);
- if (length >= spacing) {
- mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing;
- mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing;
- pressure = stroke->last_pressure + (spacing / length) * dpressure;
+ if (length >= spacing) {
+ mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing;
+ mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing;
+ pressure = stroke->last_pressure + (spacing / length) * dpressure;
- ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, spacing / no_pressure_spacing);
+ ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush,
+ spacing / no_pressure_spacing);
- stroke->stroke_distance += spacing / stroke->zoom_2d;
- paint_brush_stroke_add_step(C, op, mouse, pressure);
+ stroke->stroke_distance += spacing / stroke->zoom_2d;
+ paint_brush_stroke_add_step(C, op, mouse, pressure);
- length -= spacing;
- pressure = stroke->last_pressure;
- dpressure = final_pressure - stroke->last_pressure;
+ length -= spacing;
+ pressure = stroke->last_pressure;
+ dpressure = final_pressure - stroke->last_pressure;
- cnt++;
- }
- else {
- break;
- }
- }
+ cnt++;
+ }
+ else {
+ break;
+ }
+ }
- return cnt;
+ return cnt;
}
/**** Public API ****/
-PaintStroke *paint_stroke_new(
- bContext *C,
- wmOperator *op,
- StrokeGetLocation get_location,
- StrokeTestStart test_start,
- StrokeUpdateStep update_step,
- StrokeRedraw redraw,
- StrokeDone done, int event_type)
+PaintStroke *paint_stroke_new(bContext *C,
+ wmOperator *op,
+ StrokeGetLocation get_location,
+ StrokeTestStart test_start,
+ StrokeUpdateStep update_step,
+ StrokeRedraw redraw,
+ StrokeDone done,
+ int event_type)
{
- PaintStroke *stroke = MEM_callocN(sizeof(PaintStroke), "PaintStroke");
- ToolSettings *toolsettings = CTX_data_tool_settings(C);
- UnifiedPaintSettings *ups = &toolsettings->unified_paint_settings;
- Paint *p = BKE_paint_get_active_from_context(C);
- Brush *br = stroke->brush = BKE_paint_brush(p);
- float zoomx, zoomy;
-
- ED_view3d_viewcontext_init(C, &stroke->vc);
-
- stroke->get_location = get_location;
- stroke->test_start = test_start;
- stroke->update_step = update_step;
- stroke->redraw = redraw;
- stroke->done = done;
- stroke->event_type = event_type; /* for modal, return event */
- stroke->ups = ups;
- stroke->stroke_mode = RNA_enum_get(op->ptr, "mode");
-
- get_imapaint_zoom(C, &zoomx, &zoomy);
- stroke->zoom_2d = max_ff(zoomx, zoomy);
-
- if (stroke->stroke_mode == BRUSH_STROKE_INVERT) {
- if (br->flag & (BRUSH_CURVE)) {
- RNA_enum_set(op->ptr, "mode", BRUSH_STROKE_NORMAL);
- }
- }
- /* initialize here */
- ups->overlap_factor = 1.0;
- ups->stroke_active = true;
-
- zero_v3(ups->average_stroke_accum);
- ups->average_stroke_counter = 0;
-
- /* initialize here to avoid initialization conflict with threaded strokes */
- curvemapping_initialize(br->curve);
- if (p->flags & PAINT_USE_CAVITY_MASK)
- curvemapping_initialize(p->cavity_curve);
-
- BKE_paint_set_overlay_override(br->overlay_flags);
-
- return stroke;
+ PaintStroke *stroke = MEM_callocN(sizeof(PaintStroke), "PaintStroke");
+ ToolSettings *toolsettings = CTX_data_tool_settings(C);
+ UnifiedPaintSettings *ups = &toolsettings->unified_paint_settings;
+ Paint *p = BKE_paint_get_active_from_context(C);
+ Brush *br = stroke->brush = BKE_paint_brush(p);
+ float zoomx, zoomy;
+
+ ED_view3d_viewcontext_init(C, &stroke->vc);
+
+ stroke->get_location = get_location;
+ stroke->test_start = test_start;
+ stroke->update_step = update_step;
+ stroke->redraw = redraw;
+ stroke->done = done;
+ stroke->event_type = event_type; /* for modal, return event */
+ stroke->ups = ups;
+ stroke->stroke_mode = RNA_enum_get(op->ptr, "mode");
+
+ get_imapaint_zoom(C, &zoomx, &zoomy);
+ stroke->zoom_2d = max_ff(zoomx, zoomy);
+
+ if (stroke->stroke_mode == BRUSH_STROKE_INVERT) {
+ if (br->flag & (BRUSH_CURVE)) {
+ RNA_enum_set(op->ptr, "mode", BRUSH_STROKE_NORMAL);
+ }
+ }
+ /* initialize here */
+ ups->overlap_factor = 1.0;
+ ups->stroke_active = true;
+
+ zero_v3(ups->average_stroke_accum);
+ ups->average_stroke_counter = 0;
+
+ /* initialize here to avoid initialization conflict with threaded strokes */
+ curvemapping_initialize(br->curve);
+ if (p->flags & PAINT_USE_CAVITY_MASK)
+ curvemapping_initialize(p->cavity_curve);
+
+ BKE_paint_set_overlay_override(br->overlay_flags);
+
+ return stroke;
}
void paint_stroke_data_free(struct wmOperator *op)
{
- BKE_paint_set_overlay_override(0);
- MEM_SAFE_FREE(op->customdata);
+ BKE_paint_set_overlay_override(0);
+ MEM_SAFE_FREE(op->customdata);
}
static void stroke_done(struct bContext *C, struct wmOperator *op)
{
- struct PaintStroke *stroke = op->customdata;
- UnifiedPaintSettings *ups = stroke->ups;
+ struct PaintStroke *stroke = op->customdata;
+ UnifiedPaintSettings *ups = stroke->ups;
- ups->draw_anchored = false;
- ups->stroke_active = false;
+ ups->draw_anchored = false;
+ ups->stroke_active = false;
- /* reset rotation here to avoid doing so in cursor display */
- if (!(stroke->brush->mtex.brush_angle_mode & MTEX_ANGLE_RAKE))
- ups->brush_rotation = 0.0f;
+ /* reset rotation here to avoid doing so in cursor display */
+ if (!(stroke->brush->mtex.brush_angle_mode & MTEX_ANGLE_RAKE))
+ ups->brush_rotation = 0.0f;
- if (!(stroke->brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE))
- ups->brush_rotation_sec = 0.0f;
+ if (!(stroke->brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE))
+ ups->brush_rotation_sec = 0.0f;
- if (stroke->stroke_started) {
- if (stroke->redraw)
- stroke->redraw(C, stroke, true);
+ if (stroke->stroke_started) {
+ if (stroke->redraw)
+ stroke->redraw(C, stroke, true);
- if (stroke->done)
- stroke->done(C, stroke);
- }
+ if (stroke->done)
+ stroke->done(C, stroke);
+ }
- if (stroke->timer) {
- WM_event_remove_timer(
- CTX_wm_manager(C),
- CTX_wm_window(C),
- stroke->timer);
- }
+ if (stroke->timer) {
+ WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), stroke->timer);
+ }
- if (stroke->rng) {
- BLI_rng_free(stroke->rng);
- }
+ if (stroke->rng) {
+ BLI_rng_free(stroke->rng);
+ }
- if (stroke->stroke_cursor)
- WM_paint_cursor_end(CTX_wm_manager(C), stroke->stroke_cursor);
+ if (stroke->stroke_cursor)
+ WM_paint_cursor_end(CTX_wm_manager(C), stroke->stroke_cursor);
- BLI_freelistN(&stroke->line);
+ BLI_freelistN(&stroke->line);
- paint_stroke_data_free(op);
+ paint_stroke_data_free(op);
}
/* Returns zero if the stroke dots should not be spaced, non-zero otherwise */
bool paint_space_stroke_enabled(Brush *br, ePaintMode mode)
{
- return (br->flag & BRUSH_SPACE) && paint_supports_dynamic_size(br, mode);
+ return (br->flag & BRUSH_SPACE) && paint_supports_dynamic_size(br, mode);
}
static bool sculpt_is_grab_tool(Brush *br)
{
- return ELEM(
- br->sculpt_tool,
- SCULPT_TOOL_GRAB,
- SCULPT_TOOL_THUMB,
- SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_SNAKE_HOOK);
+ return ELEM(br->sculpt_tool,
+ SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_THUMB,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_SNAKE_HOOK);
}
/* return true if the brush size can change during paint (normally used for pressure) */
bool paint_supports_dynamic_size(Brush *br, ePaintMode mode)
{
- if (br->flag & BRUSH_ANCHORED)
- return false;
-
- switch (mode) {
- case PAINT_MODE_SCULPT:
- if (sculpt_is_grab_tool(br))
- return false;
- break;
-
- case PAINT_MODE_TEXTURE_2D: /* fall through */
- case PAINT_MODE_TEXTURE_3D:
- if ((br->imagepaint_tool == PAINT_TOOL_FILL) &&
- (br->flag & BRUSH_USE_GRADIENT))
- {
- return false;
- }
- break;
-
- default:
- break;
- }
- return true;
+ if (br->flag & BRUSH_ANCHORED)
+ return false;
+
+ switch (mode) {
+ case PAINT_MODE_SCULPT:
+ if (sculpt_is_grab_tool(br))
+ return false;
+ break;
+
+ case PAINT_MODE_TEXTURE_2D: /* fall through */
+ case PAINT_MODE_TEXTURE_3D:
+ if ((br->imagepaint_tool == PAINT_TOOL_FILL) && (br->flag & BRUSH_USE_GRADIENT)) {
+ return false;
+ }
+ break;
+
+ default:
+ break;
+ }
+ return true;
}
bool paint_supports_smooth_stroke(Brush *br, ePaintMode mode)
{
- if (!(br->flag & BRUSH_SMOOTH_STROKE) ||
- (br->flag & (BRUSH_ANCHORED | BRUSH_DRAG_DOT | BRUSH_LINE)))
- {
- return false;
- }
-
- switch (mode) {
- case PAINT_MODE_SCULPT:
- if (sculpt_is_grab_tool(br))
- return false;
- break;
- default:
- break;
- }
- return true;
+ if (!(br->flag & BRUSH_SMOOTH_STROKE) ||
+ (br->flag & (BRUSH_ANCHORED | BRUSH_DRAG_DOT | BRUSH_LINE))) {
+ return false;
+ }
+
+ switch (mode) {
+ case PAINT_MODE_SCULPT:
+ if (sculpt_is_grab_tool(br))
+ return false;
+ break;
+ default:
+ break;
+ }
+ return true;
}
bool paint_supports_texture(ePaintMode mode)
{
- /* omit: PAINT_WEIGHT, PAINT_SCULPT_UV, PAINT_INVALID */
- return ELEM(mode, PAINT_MODE_SCULPT, PAINT_MODE_VERTEX, PAINT_MODE_TEXTURE_3D, PAINT_MODE_TEXTURE_2D);
+ /* omit: PAINT_WEIGHT, PAINT_SCULPT_UV, PAINT_INVALID */
+ return ELEM(
+ mode, PAINT_MODE_SCULPT, PAINT_MODE_VERTEX, PAINT_MODE_TEXTURE_3D, PAINT_MODE_TEXTURE_2D);
}
/* return true if the brush size can change during paint (normally used for pressure) */
bool paint_supports_dynamic_tex_coords(Brush *br, ePaintMode mode)
{
- if (br->flag & BRUSH_ANCHORED)
- return false;
-
- switch (mode) {
- case PAINT_MODE_SCULPT:
- if (sculpt_is_grab_tool(br))
- return false;
- break;
- default:
- break;
- }
- return true;
+ if (br->flag & BRUSH_ANCHORED)
+ return false;
+
+ switch (mode) {
+ case PAINT_MODE_SCULPT:
+ if (sculpt_is_grab_tool(br))
+ return false;
+ break;
+ default:
+ break;
+ }
+ return true;
}
#define PAINT_STROKE_MODAL_CANCEL 1
@@ -915,487 +916,486 @@ bool paint_supports_dynamic_tex_coords(Brush *br, ePaintMode mode)
/* called in paint_ops.c, on each regeneration of keymaps */
struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf)
{
- static struct EnumPropertyItem modal_items[] = {
- {PAINT_STROKE_MODAL_CANCEL, "CANCEL", 0,
- "Cancel",
- "Cancel and undo a stroke in progress"},
+ static struct EnumPropertyItem modal_items[] = {
+ {PAINT_STROKE_MODAL_CANCEL, "CANCEL", 0, "Cancel", "Cancel and undo a stroke in progress"},
- { 0 }
- };
+ {0}};
- static const char *name = "Paint Stroke Modal";
+ static const char *name = "Paint Stroke Modal";
- struct wmKeyMap *keymap = WM_modalkeymap_get(keyconf, name);
+ struct wmKeyMap *keymap = WM_modalkeymap_get(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);
- }
+ /* this function is called for each spacetype, only needs to add map once */
+ if (!keymap) {
+ keymap = WM_modalkeymap_add(keyconf, name, modal_items);
+ }
- return keymap;
+ return keymap;
}
static void paint_stroke_add_sample(
- const Paint *paint,
- PaintStroke *stroke,
- float x, float y, float pressure)
+ const Paint *paint, PaintStroke *stroke, float x, float y, float pressure)
{
- PaintSample *sample = &stroke->samples[stroke->cur_sample];
- int max_samples = CLAMPIS(paint->num_input_samples, 1, PAINT_MAX_INPUT_SAMPLES);
-
- sample->mouse[0] = x;
- sample->mouse[1] = y;
- sample->pressure = pressure;
-
- stroke->cur_sample++;
- if (stroke->cur_sample >= max_samples)
- stroke->cur_sample = 0;
- if (stroke->num_samples < max_samples)
- stroke->num_samples++;
+ PaintSample *sample = &stroke->samples[stroke->cur_sample];
+ int max_samples = CLAMPIS(paint->num_input_samples, 1, PAINT_MAX_INPUT_SAMPLES);
+
+ sample->mouse[0] = x;
+ sample->mouse[1] = y;
+ sample->pressure = pressure;
+
+ stroke->cur_sample++;
+ if (stroke->cur_sample >= max_samples)
+ stroke->cur_sample = 0;
+ if (stroke->num_samples < max_samples)
+ stroke->num_samples++;
}
-static void paint_stroke_sample_average(
- const PaintStroke *stroke,
- PaintSample *average)
+static void paint_stroke_sample_average(const PaintStroke *stroke, PaintSample *average)
{
- int i;
+ int i;
- memset(average, 0, sizeof(*average));
+ memset(average, 0, sizeof(*average));
- BLI_assert(stroke->num_samples > 0);
+ BLI_assert(stroke->num_samples > 0);
- for (i = 0; i < stroke->num_samples; i++) {
- add_v2_v2(average->mouse, stroke->samples[i].mouse);
- average->pressure += stroke->samples[i].pressure;
- }
+ for (i = 0; i < stroke->num_samples; i++) {
+ add_v2_v2(average->mouse, stroke->samples[i].mouse);
+ average->pressure += stroke->samples[i].pressure;
+ }
- mul_v2_fl(average->mouse, 1.0f / stroke->num_samples);
- average->pressure /= stroke->num_samples;
+ mul_v2_fl(average->mouse, 1.0f / stroke->num_samples);
+ average->pressure /= stroke->num_samples;
- // printf("avg=(%f, %f), num=%d\n", average->mouse[0], average->mouse[1], stroke->num_samples);
+ // printf("avg=(%f, %f), num=%d\n", average->mouse[0], average->mouse[1], stroke->num_samples);
}
/**
* Slightly different version of spacing for line/curve strokes,
* makes sure the dabs stay on the line path.
*/
-static void paint_line_strokes_spacing(
- bContext *C, wmOperator *op, PaintStroke *stroke, float spacing, float *length_residue,
- const float old_pos[2], const float new_pos[2])
+static void paint_line_strokes_spacing(bContext *C,
+ wmOperator *op,
+ PaintStroke *stroke,
+ float spacing,
+ float *length_residue,
+ const float old_pos[2],
+ const float new_pos[2])
{
- UnifiedPaintSettings *ups = stroke->ups;
+ UnifiedPaintSettings *ups = stroke->ups;
- float mouse[2], dmouse[2];
- float length;
+ float mouse[2], dmouse[2];
+ float length;
- sub_v2_v2v2(dmouse, new_pos, old_pos);
- copy_v2_v2(stroke->last_mouse_position, old_pos);
+ sub_v2_v2v2(dmouse, new_pos, old_pos);
+ copy_v2_v2(stroke->last_mouse_position, old_pos);
- length = normalize_v2(dmouse);
+ length = normalize_v2(dmouse);
- BLI_assert(length >= 0.0f);
+ BLI_assert(length >= 0.0f);
- if (length == 0.0f)
- return;
+ if (length == 0.0f)
+ return;
- while (length > 0.0f) {
- float spacing_final = spacing - *length_residue;
- length += *length_residue;
- *length_residue = 0.0;
+ while (length > 0.0f) {
+ float spacing_final = spacing - *length_residue;
+ length += *length_residue;
+ *length_residue = 0.0;
- if (length >= spacing) {
- mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing_final;
- mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing_final;
+ if (length >= spacing) {
+ mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing_final;
+ mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing_final;
- ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, 1.0);
+ ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, 1.0);
- stroke->stroke_distance += spacing / stroke->zoom_2d;
- paint_brush_stroke_add_step(C, op, mouse, 1.0);
+ stroke->stroke_distance += spacing / stroke->zoom_2d;
+ paint_brush_stroke_add_step(C, op, mouse, 1.0);
- length -= spacing;
- spacing_final = spacing;
- }
- else {
- break;
- }
- }
+ length -= spacing;
+ spacing_final = spacing;
+ }
+ else {
+ break;
+ }
+ }
- *length_residue = length;
+ *length_residue = length;
}
-
static void paint_stroke_line_end(bContext *C, wmOperator *op, PaintStroke *stroke, float mouse[2])
{
- Brush *br = stroke->brush;
- if (stroke->stroke_started && (br->flag & BRUSH_LINE)) {
- stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
+ Brush *br = stroke->brush;
+ if (stroke->stroke_started && (br->flag & BRUSH_LINE)) {
+ stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
- paint_brush_stroke_add_step(C, op, stroke->last_mouse_position, 1.0);
- paint_space_stroke(C, op, mouse, 1.0);
- }
+ paint_brush_stroke_add_step(C, op, stroke->last_mouse_position, 1.0);
+ paint_space_stroke(C, op, mouse, 1.0);
+ }
}
static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *stroke)
{
- Brush *br = stroke->brush;
+ Brush *br = stroke->brush;
- if (br->flag & BRUSH_CURVE) {
- UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
- const Scene *scene = CTX_data_scene(C);
- const float spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
- PaintCurve *pc = br->paint_curve;
- PaintCurvePoint *pcp;
- float length_residue = 0.0f;
- int i;
+ if (br->flag & BRUSH_CURVE) {
+ UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
+ const Scene *scene = CTX_data_scene(C);
+ const float spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
+ PaintCurve *pc = br->paint_curve;
+ PaintCurvePoint *pcp;
+ float length_residue = 0.0f;
+ int i;
- if (!pc)
- return true;
+ if (!pc)
+ return true;
#ifdef DEBUG_TIME
- TIMEIT_START_AVERAGED(whole_stroke);
+ TIMEIT_START_AVERAGED(whole_stroke);
#endif
- pcp = pc->points;
- stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
-
- for (i = 0; i < pc->tot_points - 1; i++, pcp++) {
- int j;
- float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
- float tangents[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
- PaintCurvePoint *pcp_next = pcp + 1;
- bool do_rake = false;
-
- for (j = 0; j < 2; j++) {
- BKE_curve_forward_diff_bezier(
- pcp->bez.vec[1][j],
- pcp->bez.vec[2][j],
- pcp_next->bez.vec[0][j],
- pcp_next->bez.vec[1][j],
- data + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2]));
- }
-
- if ((br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) ||
- (br->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE))
- {
- do_rake = true;
- for (j = 0; j < 2; j++) {
- BKE_curve_forward_diff_tangent_bezier(
- pcp->bez.vec[1][j],
- pcp->bez.vec[2][j],
- pcp_next->bez.vec[0][j],
- pcp_next->bez.vec[1][j],
- tangents + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2]));
- }
- }
-
- for (j = 0; j < PAINT_CURVE_NUM_SEGMENTS; j++) {
- if (do_rake) {
- float rotation = atan2f(tangents[2 * j], tangents[2 * j + 1]);
- paint_update_brush_rake_rotation(ups, br, rotation);
- }
-
- if (!stroke->stroke_started) {
- stroke->last_pressure = 1.0;
- copy_v2_v2(stroke->last_mouse_position, data + 2 * j);
- stroke->stroke_started = stroke->test_start(C, op, stroke->last_mouse_position);
-
- if (stroke->stroke_started) {
- paint_brush_stroke_add_step(C, op, data + 2 * j, 1.0);
- paint_line_strokes_spacing(
- C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
- }
- }
- else {
- paint_line_strokes_spacing(
- C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
- }
- }
- }
-
- stroke_done(C, op);
+ pcp = pc->points;
+ stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
+
+ for (i = 0; i < pc->tot_points - 1; i++, pcp++) {
+ int j;
+ float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
+ float tangents[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
+ PaintCurvePoint *pcp_next = pcp + 1;
+ bool do_rake = false;
+
+ for (j = 0; j < 2; j++) {
+ BKE_curve_forward_diff_bezier(pcp->bez.vec[1][j],
+ pcp->bez.vec[2][j],
+ pcp_next->bez.vec[0][j],
+ pcp_next->bez.vec[1][j],
+ data + j,
+ PAINT_CURVE_NUM_SEGMENTS,
+ sizeof(float[2]));
+ }
+
+ if ((br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) ||
+ (br->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) {
+ do_rake = true;
+ for (j = 0; j < 2; j++) {
+ BKE_curve_forward_diff_tangent_bezier(pcp->bez.vec[1][j],
+ pcp->bez.vec[2][j],
+ pcp_next->bez.vec[0][j],
+ pcp_next->bez.vec[1][j],
+ tangents + j,
+ PAINT_CURVE_NUM_SEGMENTS,
+ sizeof(float[2]));
+ }
+ }
+
+ for (j = 0; j < PAINT_CURVE_NUM_SEGMENTS; j++) {
+ if (do_rake) {
+ float rotation = atan2f(tangents[2 * j], tangents[2 * j + 1]);
+ paint_update_brush_rake_rotation(ups, br, rotation);
+ }
+
+ if (!stroke->stroke_started) {
+ stroke->last_pressure = 1.0;
+ copy_v2_v2(stroke->last_mouse_position, data + 2 * j);
+ stroke->stroke_started = stroke->test_start(C, op, stroke->last_mouse_position);
+
+ if (stroke->stroke_started) {
+ paint_brush_stroke_add_step(C, op, data + 2 * j, 1.0);
+ paint_line_strokes_spacing(
+ C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
+ }
+ }
+ else {
+ paint_line_strokes_spacing(
+ C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
+ }
+ }
+ }
+
+ stroke_done(C, op);
#ifdef DEBUG_TIME
- TIMEIT_END_AVERAGED(whole_stroke);
+ TIMEIT_END_AVERAGED(whole_stroke);
#endif
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
static void paint_stroke_line_constrain(PaintStroke *stroke, float mouse[2])
{
- if (stroke->constrain_line) {
- float line[2];
- float angle, len, res;
-
- sub_v2_v2v2(line, mouse, stroke->last_mouse_position);
- angle = atan2f(line[1], line[0]);
- len = len_v2(line);
-
- /* divide angle by PI/4 */
- angle = 4.0f * angle / (float)M_PI;
-
- /* now take residue */
- res = angle - floorf(angle);
-
- /* residue decides how close we are at a certain angle */
- if (res <= 0.5f) {
- angle = floorf(angle) * (float)M_PI_4;
- }
- else {
- angle = (floorf(angle) + 1.0f) * (float)M_PI_4;
- }
-
- mouse[0] = stroke->constrained_pos[0] = len * cosf(angle) + stroke->last_mouse_position[0];
- mouse[1] = stroke->constrained_pos[1] = len * sinf(angle) + stroke->last_mouse_position[1];
- }
+ if (stroke->constrain_line) {
+ float line[2];
+ float angle, len, res;
+
+ sub_v2_v2v2(line, mouse, stroke->last_mouse_position);
+ angle = atan2f(line[1], line[0]);
+ len = len_v2(line);
+
+ /* divide angle by PI/4 */
+ angle = 4.0f * angle / (float)M_PI;
+
+ /* now take residue */
+ res = angle - floorf(angle);
+
+ /* residue decides how close we are at a certain angle */
+ if (res <= 0.5f) {
+ angle = floorf(angle) * (float)M_PI_4;
+ }
+ else {
+ angle = (floorf(angle) + 1.0f) * (float)M_PI_4;
+ }
+
+ mouse[0] = stroke->constrained_pos[0] = len * cosf(angle) + stroke->last_mouse_position[0];
+ mouse[1] = stroke->constrained_pos[1] = len * sinf(angle) + stroke->last_mouse_position[1];
+ }
}
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;
- PaintSample sample_average;
- float mouse[2];
- bool first_dab = false;
- bool first_modal = false;
- bool redraw = false;
- float pressure;
-
- /* see if tablet affects event. Line, anchored and drag dot strokes do not support pressure */
- pressure = (
- (br->flag & (BRUSH_LINE | BRUSH_ANCHORED | BRUSH_DRAG_DOT)) ?
- 1.0f : WM_event_tablet_data(event, &stroke->pen_flip, NULL));
-
- paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1], pressure);
- paint_stroke_sample_average(stroke, &sample_average);
+ 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;
+ PaintSample sample_average;
+ float mouse[2];
+ bool first_dab = false;
+ bool first_modal = false;
+ bool redraw = false;
+ float pressure;
+
+ /* see if tablet affects event. Line, anchored and drag dot strokes do not support pressure */
+ pressure = ((br->flag & (BRUSH_LINE | BRUSH_ANCHORED | BRUSH_DRAG_DOT)) ?
+ 1.0f :
+ WM_event_tablet_data(event, &stroke->pen_flip, NULL));
+
+ paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1], pressure);
+ paint_stroke_sample_average(stroke, &sample_average);
#ifdef WITH_INPUT_NDOF
- /* let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously!
- * this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it
- * since the 2D deltas are zero -- code in this file needs to be updated to use the
- * post-NDOF_MOTION MOUSEMOVE */
- if (event->type == NDOF_MOTION)
- return OPERATOR_PASS_THROUGH;
+ /* let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously!
+ * this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it
+ * since the 2D deltas are zero -- code in this file needs to be updated to use the
+ * post-NDOF_MOTION MOUSEMOVE */
+ if (event->type == NDOF_MOTION)
+ return OPERATOR_PASS_THROUGH;
#endif
- /* one time initialization */
- if (!stroke->stroke_init) {
- if (paint_stroke_curve_end(C, op, stroke))
- return OPERATOR_FINISHED;
-
- if (paint_supports_smooth_stroke(br, mode))
- stroke->stroke_cursor = WM_paint_cursor_activate(
- CTX_wm_manager(C),
- SPACE_TYPE_ANY, RGN_TYPE_ANY,
- paint_poll, paint_draw_smooth_cursor, stroke);
-
- stroke->stroke_init = true;
- first_modal = true;
- }
-
- /* one time stroke initialization */
- if (!stroke->stroke_started) {
- stroke->last_pressure = sample_average.pressure;
- copy_v2_v2(stroke->last_mouse_position, sample_average.mouse);
- stroke->stroke_started = stroke->test_start(C, op, sample_average.mouse);
- BLI_assert((stroke->stroke_started & ~1) == 0); /* 0/1 */
-
- if (stroke->stroke_started) {
- if (br->flag & BRUSH_AIRBRUSH)
- stroke->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, stroke->brush->rate);
-
- if (br->flag & BRUSH_LINE) {
- stroke->stroke_cursor = WM_paint_cursor_activate(
- CTX_wm_manager(C),
- SPACE_TYPE_ANY, RGN_TYPE_ANY,
- paint_poll, paint_draw_line_cursor, stroke);
- }
-
- first_dab = true;
- }
- }
-
- /* Cancel */
- if (event->type == EVT_MODAL_MAP && event->val == PAINT_STROKE_MODAL_CANCEL) {
- if (op->type->cancel) {
- op->type->cancel(C, op);
- }
- else {
- paint_stroke_cancel(C, op);
- }
- return OPERATOR_CANCELLED;
- }
-
- if (event->type == stroke->event_type && !first_modal) {
- if (event->val == KM_RELEASE) {
- copy_v2_fl2(mouse, event->mval[0], event->mval[1]);
- paint_stroke_line_constrain(stroke, mouse);
- paint_stroke_line_end(C, op, stroke, mouse);
- stroke_done(C, op);
- return OPERATOR_FINISHED;
- }
- }
- else if (ELEM(event->type, RETKEY, SPACEKEY)) {
- paint_stroke_line_end(C, op, stroke, sample_average.mouse);
- stroke_done(C, op);
- return OPERATOR_FINISHED;
- }
- else if (br->flag & BRUSH_LINE) {
- if (event->alt)
- stroke->constrain_line = true;
- else
- stroke->constrain_line = false;
-
- copy_v2_fl2(mouse, event->mval[0], event->mval[1]);
- paint_stroke_line_constrain(stroke, mouse);
-
- if (stroke->stroke_started && (first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)))) {
- if ((br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) || (br->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) {
- copy_v2_v2(stroke->ups->last_rake, stroke->last_mouse_position);
- }
- paint_calculate_rake_rotation(stroke->ups, br, mouse);
- }
- }
- else if (first_modal ||
- /* regular dabs */
- (!(br->flag & (BRUSH_AIRBRUSH)) && (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE))) ||
- /* airbrush */
- ((br->flag & BRUSH_AIRBRUSH) && event->type == TIMER && event->customdata == stroke->timer))
- {
- if (paint_smooth_stroke(stroke, &sample_average, mode, mouse, &pressure)) {
- if (stroke->stroke_started) {
- if (paint_space_stroke_enabled(br, mode)) {
- if (paint_space_stroke(C, op, mouse, pressure))
- redraw = true;
- }
- else {
- float dmouse[2];
- sub_v2_v2v2(dmouse, mouse, stroke->last_mouse_position);
- stroke->stroke_distance += len_v2(dmouse);
- paint_brush_stroke_add_step(C, op, mouse, pressure);
- redraw = true;
- }
- }
- }
- }
-
- /* we want the stroke to have the first daub at the start location
- * instead of waiting till we have moved the space distance */
- if (first_dab &&
- paint_space_stroke_enabled(br, mode) &&
- !(br->flag & BRUSH_SMOOTH_STROKE))
- {
- stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
- paint_brush_stroke_add_step(C, op, sample_average.mouse, sample_average.pressure);
- redraw = true;
- }
-
- /* do updates for redraw. if event is inbetween mousemove there are more
- * 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);
-
- /* At the very least, invalidate the cursor */
- if (ar && (p->flags & PAINT_SHOW_BRUSH))
- WM_paint_cursor_tag_redraw(window, ar);
-
- if (redraw && stroke->redraw)
- stroke->redraw(C, stroke, false);
- }
-
- return OPERATOR_RUNNING_MODAL;
+ /* one time initialization */
+ if (!stroke->stroke_init) {
+ if (paint_stroke_curve_end(C, op, stroke))
+ return OPERATOR_FINISHED;
+
+ if (paint_supports_smooth_stroke(br, mode))
+ stroke->stroke_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
+ SPACE_TYPE_ANY,
+ RGN_TYPE_ANY,
+ paint_poll,
+ paint_draw_smooth_cursor,
+ stroke);
+
+ stroke->stroke_init = true;
+ first_modal = true;
+ }
+
+ /* one time stroke initialization */
+ if (!stroke->stroke_started) {
+ stroke->last_pressure = sample_average.pressure;
+ copy_v2_v2(stroke->last_mouse_position, sample_average.mouse);
+ stroke->stroke_started = stroke->test_start(C, op, sample_average.mouse);
+ BLI_assert((stroke->stroke_started & ~1) == 0); /* 0/1 */
+
+ if (stroke->stroke_started) {
+ if (br->flag & BRUSH_AIRBRUSH)
+ stroke->timer = WM_event_add_timer(
+ CTX_wm_manager(C), CTX_wm_window(C), TIMER, stroke->brush->rate);
+
+ if (br->flag & BRUSH_LINE) {
+ stroke->stroke_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
+ SPACE_TYPE_ANY,
+ RGN_TYPE_ANY,
+ paint_poll,
+ paint_draw_line_cursor,
+ stroke);
+ }
+
+ first_dab = true;
+ }
+ }
+
+ /* Cancel */
+ if (event->type == EVT_MODAL_MAP && event->val == PAINT_STROKE_MODAL_CANCEL) {
+ if (op->type->cancel) {
+ op->type->cancel(C, op);
+ }
+ else {
+ paint_stroke_cancel(C, op);
+ }
+ return OPERATOR_CANCELLED;
+ }
+
+ if (event->type == stroke->event_type && !first_modal) {
+ if (event->val == KM_RELEASE) {
+ copy_v2_fl2(mouse, event->mval[0], event->mval[1]);
+ paint_stroke_line_constrain(stroke, mouse);
+ paint_stroke_line_end(C, op, stroke, mouse);
+ stroke_done(C, op);
+ return OPERATOR_FINISHED;
+ }
+ }
+ else if (ELEM(event->type, RETKEY, SPACEKEY)) {
+ paint_stroke_line_end(C, op, stroke, sample_average.mouse);
+ stroke_done(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else if (br->flag & BRUSH_LINE) {
+ if (event->alt)
+ stroke->constrain_line = true;
+ else
+ stroke->constrain_line = false;
+
+ copy_v2_fl2(mouse, event->mval[0], event->mval[1]);
+ paint_stroke_line_constrain(stroke, mouse);
+
+ if (stroke->stroke_started &&
+ (first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)))) {
+ if ((br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) ||
+ (br->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) {
+ copy_v2_v2(stroke->ups->last_rake, stroke->last_mouse_position);
+ }
+ paint_calculate_rake_rotation(stroke->ups, br, mouse);
+ }
+ }
+ else if (first_modal ||
+ /* regular dabs */
+ (!(br->flag & (BRUSH_AIRBRUSH)) &&
+ (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE))) ||
+ /* airbrush */
+ ((br->flag & BRUSH_AIRBRUSH) && event->type == TIMER &&
+ event->customdata == stroke->timer)) {
+ if (paint_smooth_stroke(stroke, &sample_average, mode, mouse, &pressure)) {
+ if (stroke->stroke_started) {
+ if (paint_space_stroke_enabled(br, mode)) {
+ if (paint_space_stroke(C, op, mouse, pressure))
+ redraw = true;
+ }
+ else {
+ float dmouse[2];
+ sub_v2_v2v2(dmouse, mouse, stroke->last_mouse_position);
+ stroke->stroke_distance += len_v2(dmouse);
+ paint_brush_stroke_add_step(C, op, mouse, pressure);
+ redraw = true;
+ }
+ }
+ }
+ }
+
+ /* we want the stroke to have the first daub at the start location
+ * instead of waiting till we have moved the space distance */
+ if (first_dab && paint_space_stroke_enabled(br, mode) && !(br->flag & BRUSH_SMOOTH_STROKE)) {
+ stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
+ paint_brush_stroke_add_step(C, op, sample_average.mouse, sample_average.pressure);
+ redraw = true;
+ }
+
+ /* do updates for redraw. if event is inbetween mousemove there are more
+ * 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);
+
+ /* At the very least, invalidate the cursor */
+ if (ar && (p->flags & PAINT_SHOW_BRUSH))
+ WM_paint_cursor_tag_redraw(window, ar);
+
+ if (redraw && stroke->redraw)
+ stroke->redraw(C, stroke, false);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
int paint_stroke_exec(bContext *C, wmOperator *op)
{
- PaintStroke *stroke = op->customdata;
+ PaintStroke *stroke = op->customdata;
- /* only when executed for the first time */
- if (stroke->stroke_started == 0) {
- PropertyRNA *strokeprop;
- PointerRNA firstpoint;
- float mouse[2];
+ /* only when executed for the first time */
+ if (stroke->stroke_started == 0) {
+ PropertyRNA *strokeprop;
+ PointerRNA firstpoint;
+ float mouse[2];
- strokeprop = RNA_struct_find_property(op->ptr, "stroke");
+ strokeprop = RNA_struct_find_property(op->ptr, "stroke");
- if (RNA_property_collection_lookup_int(op->ptr, strokeprop, 0, &firstpoint)) {
- RNA_float_get_array(&firstpoint, "mouse", mouse);
- stroke->stroke_started = stroke->test_start(C, op, mouse);
- }
- }
+ if (RNA_property_collection_lookup_int(op->ptr, strokeprop, 0, &firstpoint)) {
+ RNA_float_get_array(&firstpoint, "mouse", mouse);
+ stroke->stroke_started = stroke->test_start(C, op, mouse);
+ }
+ }
- if (stroke->stroke_started) {
- RNA_BEGIN (op->ptr, itemptr, "stroke")
- {
- stroke->update_step(C, stroke, &itemptr);
- }
- RNA_END;
- }
+ if (stroke->stroke_started) {
+ RNA_BEGIN (op->ptr, itemptr, "stroke") {
+ stroke->update_step(C, stroke, &itemptr);
+ }
+ RNA_END;
+ }
- bool ok = (stroke->stroke_started != 0);
+ bool ok = (stroke->stroke_started != 0);
- stroke_done(C, op);
+ stroke_done(C, op);
- return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void paint_stroke_cancel(bContext *C, wmOperator *op)
{
- stroke_done(C, op);
+ stroke_done(C, op);
}
ViewContext *paint_stroke_view_context(PaintStroke *stroke)
{
- return &stroke->vc;
+ return &stroke->vc;
}
void *paint_stroke_mode_data(struct PaintStroke *stroke)
{
- return stroke->mode_data;
+ return stroke->mode_data;
}
bool paint_stroke_flipped(struct PaintStroke *stroke)
{
- return stroke->pen_flip;
+ return stroke->pen_flip;
}
bool paint_stroke_inverted(struct PaintStroke *stroke)
{
- return stroke->stroke_mode == BRUSH_STROKE_INVERT;
+ return stroke->stroke_mode == BRUSH_STROKE_INVERT;
}
float paint_stroke_distance_get(struct PaintStroke *stroke)
{
- return stroke->stroke_distance;
+ return stroke->stroke_distance;
}
void paint_stroke_set_mode_data(PaintStroke *stroke, void *mode_data)
{
- stroke->mode_data = mode_data;
+ stroke->mode_data = mode_data;
}
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);
-
- if (p && ob && BKE_paint_brush(p) &&
- (sa && ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) &&
- (ar && ar->regiontype == RGN_TYPE_WINDOW))
- {
- /* Check the current tool is a brush. */
- bToolRef *tref = sa->runtime.tool;
- if (tref && tref->runtime && tref->runtime->data_block[0]) {
- return true;
- }
- }
- return false;
+ 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);
+
+ if (p && ob && BKE_paint_brush(p) && (sa && ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) &&
+ (ar && ar->regiontype == RGN_TYPE_WINDOW)) {
+ /* Check the current tool is a brush. */
+ bToolRef *tref = sa->runtime.tool;
+ if (tref && tref->runtime && tref->runtime->data_block[0]) {
+ return true;
+ }
+ }
+ return false;
}
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 35401c470cc..098e38dbdb5 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -80,699 +80,720 @@
/* Convert the object-space axis-aligned bounding box (expressed as
* its minimum and maximum corners) into a screen-space rectangle,
* returns zero if the result is empty */
-bool paint_convert_bb_to_rect(
- rcti *rect,
- const float bb_min[3],
- const float bb_max[3],
- const ARegion *ar,
- RegionView3D *rv3d,
- Object *ob)
+bool paint_convert_bb_to_rect(rcti *rect,
+ const float bb_min[3],
+ const float bb_max[3],
+ const ARegion *ar,
+ RegionView3D *rv3d,
+ Object *ob)
{
- float projection_mat[4][4];
- int i, j, k;
-
- BLI_rcti_init_minmax(rect);
-
- /* return zero if the bounding box has non-positive volume */
- if (bb_min[0] > bb_max[0] || bb_min[1] > bb_max[1] || bb_min[2] > bb_max[2])
- return 0;
-
- ED_view3d_ob_project_mat_get(rv3d, ob, projection_mat);
-
- for (i = 0; i < 2; ++i) {
- for (j = 0; j < 2; ++j) {
- for (k = 0; k < 2; ++k) {
- float vec[3], proj[2];
- int proj_i[2];
- vec[0] = i ? bb_min[0] : bb_max[0];
- 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);
- /* expand 2D rectangle */
-
- /* we could project directly to int? */
- proj_i[0] = proj[0];
- proj_i[1] = proj[1];
-
- BLI_rcti_do_minmax_v(rect, proj_i);
- }
- }
- }
-
- /* return false if the rectangle has non-positive area */
- return rect->xmin < rect->xmax && rect->ymin < rect->ymax;
+ float projection_mat[4][4];
+ int i, j, k;
+
+ BLI_rcti_init_minmax(rect);
+
+ /* return zero if the bounding box has non-positive volume */
+ if (bb_min[0] > bb_max[0] || bb_min[1] > bb_max[1] || bb_min[2] > bb_max[2])
+ return 0;
+
+ ED_view3d_ob_project_mat_get(rv3d, ob, projection_mat);
+
+ for (i = 0; i < 2; ++i) {
+ for (j = 0; j < 2; ++j) {
+ for (k = 0; k < 2; ++k) {
+ float vec[3], proj[2];
+ int proj_i[2];
+ vec[0] = i ? bb_min[0] : bb_max[0];
+ 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);
+ /* expand 2D rectangle */
+
+ /* we could project directly to int? */
+ proj_i[0] = proj[0];
+ proj_i[1] = proj[1];
+
+ BLI_rcti_do_minmax_v(rect, proj_i);
+ }
+ }
+ }
+
+ /* return false if the rectangle has non-positive area */
+ return rect->xmin < rect->xmax && rect->ymin < rect->ymax;
}
/* Get four planes in object-space that describe the projection of
* 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,
- Object *ob,
- const rcti *screen_rect)
+void paint_calc_redraw_planes(float planes[4][4],
+ const ARegion *ar,
+ Object *ob,
+ const rcti *screen_rect)
{
- BoundBox bb;
- rcti rect;
-
- /* use some extra space just in case */
- rect = *screen_rect;
- rect.xmin -= 2;
- rect.xmax += 2;
- rect.ymin -= 2;
- rect.ymax += 2;
-
- ED_view3d_clipping_calc(&bb, planes, ar, ob, &rect);
- negate_m4(planes);
+ BoundBox bb;
+ rcti rect;
+
+ /* use some extra space just in case */
+ rect = *screen_rect;
+ rect.xmin -= 2;
+ rect.xmax += 2;
+ rect.ymin -= 2;
+ rect.ymax += 2;
+
+ ED_view3d_clipping_calc(&bb, planes, ar, ob, &rect);
+ negate_m4(planes);
}
-float paint_calc_object_space_radius(
- ViewContext *vc, const float center[3],
- float pixel_radius)
+float paint_calc_object_space_radius(ViewContext *vc, const float center[3], float pixel_radius)
{
- Object *ob = vc->obact;
- float delta[3], scale, loc[3];
- const float mval_f[2] = {pixel_radius, 0.0f};
- float zfac;
+ Object *ob = vc->obact;
+ float delta[3], scale, loc[3];
+ const float mval_f[2] = {pixel_radius, 0.0f};
+ float zfac;
- mul_v3_m4v3(loc, ob->obmat, center);
+ 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);
+ zfac = ED_view3d_calc_zfac(vc->rv3d, loc, NULL);
+ ED_view3d_win_to_delta(vc->ar, mval_f, delta, zfac);
- scale = fabsf(mat4_to_scale(ob->obmat));
- scale = (scale == 0.0f) ? 1.0f : scale;
+ scale = fabsf(mat4_to_scale(ob->obmat));
+ scale = (scale == 0.0f) ? 1.0f : scale;
- return len_v3(delta) / scale;
+ return len_v3(delta) / scale;
}
float paint_get_tex_pixel(const MTex *mtex, float u, float v, struct ImagePool *pool, int thread)
{
- float intensity, rgba[4];
- float co[3] = {u, v, 0.0f};
+ float intensity, rgba[4];
+ float co[3] = {u, v, 0.0f};
- externtex(mtex, co, &intensity,
- rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false);
+ externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false);
- return intensity;
+ return intensity;
}
-void paint_get_tex_pixel_col(
- const MTex *mtex, float u, float v, float rgba[4], struct ImagePool *pool,
- int thread, bool convert_to_linear, struct ColorSpace *colorspace)
+void paint_get_tex_pixel_col(const MTex *mtex,
+ float u,
+ float v,
+ float rgba[4],
+ struct ImagePool *pool,
+ int thread,
+ bool convert_to_linear,
+ 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);
- if (!hasrgb) {
- rgba[0] = intensity;
- rgba[1] = intensity;
- rgba[2] = intensity;
- rgba[3] = 1.0f;
- }
-
- if (convert_to_linear)
- IMB_colormanagement_colorspace_to_scene_linear_v3(rgba, colorspace);
-
- 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);
+ 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);
+ if (!hasrgb) {
+ rgba[0] = intensity;
+ rgba[1] = intensity;
+ rgba[2] = intensity;
+ rgba[3] = 1.0f;
+ }
+
+ if (convert_to_linear)
+ IMB_colormanagement_colorspace_to_scene_linear_v3(rgba, colorspace);
+
+ 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);
}
void paint_stroke_operator_properties(wmOperatorType *ot)
{
- static const EnumPropertyItem stroke_mode_items[] = {
- {BRUSH_STROKE_NORMAL, "NORMAL", 0, "Regular", "Apply brush normally"},
- {BRUSH_STROKE_INVERT, "INVERT", 0, "Invert", "Invert action of brush for duration of stroke"},
- {BRUSH_STROKE_SMOOTH, "SMOOTH", 0, "Smooth", "Switch brush to smooth mode for duration of stroke"},
- {0},
- };
-
- PropertyRNA *prop;
-
- prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
-
- RNA_def_enum(ot->srna, "mode", stroke_mode_items, BRUSH_STROKE_NORMAL,
- "Stroke Mode",
- "Action taken when a paint stroke is made");
-
+ static const EnumPropertyItem stroke_mode_items[] = {
+ {BRUSH_STROKE_NORMAL, "NORMAL", 0, "Regular", "Apply brush normally"},
+ {BRUSH_STROKE_INVERT,
+ "INVERT",
+ 0,
+ "Invert",
+ "Invert action of brush for duration of stroke"},
+ {BRUSH_STROKE_SMOOTH,
+ "SMOOTH",
+ 0,
+ "Smooth",
+ "Switch brush to smooth mode for duration of stroke"},
+ {0},
+ };
+
+ PropertyRNA *prop;
+
+ prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ RNA_def_enum(ot->srna,
+ "mode",
+ stroke_mode_items,
+ BRUSH_STROKE_NORMAL,
+ "Stroke Mode",
+ "Action taken when a paint stroke is made");
}
/* 3D Paint */
static void imapaint_project(float matrix[4][4], const float co[3], float pco[4])
{
- copy_v3_v3(pco, co);
- pco[3] = 1.0f;
+ copy_v3_v3(pco, co);
+ pco[3] = 1.0f;
- mul_m4_v4(matrix, pco);
+ mul_m4_v4(matrix, pco);
}
-static void imapaint_tri_weights(
- float matrix[4][4], GLint view[4],
- const float v1[3], const float v2[3], const float v3[3],
- const float co[2], float w[3])
+static void imapaint_tri_weights(float matrix[4][4],
+ GLint view[4],
+ const float v1[3],
+ const float v2[3],
+ const float v3[3],
+ const float co[2],
+ float w[3])
{
- float pv1[4], pv2[4], pv3[4], h[3], divw;
- float wmat[3][3], invwmat[3][3];
-
- /* compute barycentric coordinates */
-
- /* project the verts */
- imapaint_project(matrix, v1, pv1);
- imapaint_project(matrix, v2, pv2);
- imapaint_project(matrix, v3, pv3);
-
- /* do inverse view mapping, see gluProject man page */
- h[0] = (co[0] - view[0]) * 2.0f / view[2] - 1.0f;
- h[1] = (co[1] - view[1]) * 2.0f / view[3] - 1.0f;
- h[2] = 1.0f;
-
- /* solve for (w1,w2,w3)/perspdiv in:
- * h * perspdiv = Project * Model * (w1 * v1 + w2 * v2 + w3 * v3) */
-
- wmat[0][0] = pv1[0]; wmat[1][0] = pv2[0]; wmat[2][0] = pv3[0];
- wmat[0][1] = pv1[1]; wmat[1][1] = pv2[1]; wmat[2][1] = pv3[1];
- wmat[0][2] = pv1[3]; wmat[1][2] = pv2[3]; wmat[2][2] = pv3[3];
-
- invert_m3_m3(invwmat, wmat);
- mul_m3_v3(invwmat, h);
-
- copy_v3_v3(w, h);
-
- /* w is still divided by perspdiv, make it sum to one */
- divw = w[0] + w[1] + w[2];
- if (divw != 0.0f) {
- mul_v3_fl(w, 1.0f / divw);
- }
+ float pv1[4], pv2[4], pv3[4], h[3], divw;
+ float wmat[3][3], invwmat[3][3];
+
+ /* compute barycentric coordinates */
+
+ /* project the verts */
+ imapaint_project(matrix, v1, pv1);
+ imapaint_project(matrix, v2, pv2);
+ imapaint_project(matrix, v3, pv3);
+
+ /* do inverse view mapping, see gluProject man page */
+ h[0] = (co[0] - view[0]) * 2.0f / view[2] - 1.0f;
+ h[1] = (co[1] - view[1]) * 2.0f / view[3] - 1.0f;
+ h[2] = 1.0f;
+
+ /* solve for (w1,w2,w3)/perspdiv in:
+ * h * perspdiv = Project * Model * (w1 * v1 + w2 * v2 + w3 * v3) */
+
+ wmat[0][0] = pv1[0];
+ wmat[1][0] = pv2[0];
+ wmat[2][0] = pv3[0];
+ wmat[0][1] = pv1[1];
+ wmat[1][1] = pv2[1];
+ wmat[2][1] = pv3[1];
+ wmat[0][2] = pv1[3];
+ wmat[1][2] = pv2[3];
+ wmat[2][2] = pv3[3];
+
+ invert_m3_m3(invwmat, wmat);
+ mul_m3_v3(invwmat, h);
+
+ copy_v3_v3(w, h);
+
+ /* w is still divided by perspdiv, make it sum to one */
+ divw = w[0] + w[1] + w[2];
+ if (divw != 0.0f) {
+ mul_v3_fl(w, 1.0f / divw);
+ }
}
/* 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,
+ unsigned int faceindex,
+ const int xy[2],
+ float uv[2])
{
- int i, findex;
- float p[2], w[3], absw, minabsw;
- float matrix[4][4], proj[4][4];
- GLint view[4];
- const eImagePaintMode mode = scene->toolsettings->imapaint.mode;
-
- const MLoopTri *lt = BKE_mesh_runtime_looptri_ensure(me_eval);
- const int tottri = me_eval->runtime.looptris.len;
-
- const MVert *mvert = me_eval->mvert;
- const MPoly *mpoly = me_eval->mpoly;
- const MLoop *mloop = me_eval->mloop;
- const int *index_mp_to_orig = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX);
-
- /* get the needed opengl matrices */
- GPU_viewport_size_get_i(view);
- GPU_matrix_model_view_get(matrix);
- GPU_matrix_projection_get(proj);
- view[0] = view[1] = 0;
- mul_m4_m4m4(matrix, matrix, ob_eval->obmat);
- mul_m4_m4m4(matrix, proj, matrix);
-
- minabsw = 1e10;
- uv[0] = uv[1] = 0.0;
-
- /* test all faces in the derivedmesh with the original index of the picked face */
- /* face means poly here, not triangle, indeed */
- for (i = 0; i < tottri; i++, lt++) {
- findex = index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly;
-
- if (findex == faceindex) {
- const MLoopUV *mloopuv;
- const MPoly *mp = &mpoly[lt->poly];
- const MLoopUV *tri_uv[3];
- float tri_co[3][3];
-
- for (int j = 3; j--; ) {
- copy_v3_v3(tri_co[j], mvert[mloop[lt->tri[j]].v].co);
- }
-
- if (mode == IMAGEPAINT_MODE_MATERIAL) {
- const Material *ma;
- const TexPaintSlot *slot;
-
- ma = give_current_material(ob_eval, mp->mat_nr + 1);
- slot = &ma->texpaintslot[ma->paint_active_slot];
-
- if (!(slot && slot->uvname &&
- (mloopuv = CustomData_get_layer_named(&me_eval->ldata, CD_MLOOPUV, slot->uvname))))
- {
- mloopuv = CustomData_get_layer(&me_eval->ldata, CD_MLOOPUV);
- }
- }
- else {
- mloopuv = CustomData_get_layer(&me_eval->ldata, CD_MLOOPUV);
- }
-
- tri_uv[0] = &mloopuv[lt->tri[0]];
- tri_uv[1] = &mloopuv[lt->tri[1]];
- tri_uv[2] = &mloopuv[lt->tri[2]];
-
- p[0] = xy[0];
- p[1] = xy[1];
-
- imapaint_tri_weights(matrix, view, UNPACK3(tri_co), p, w);
- absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
- if (absw < minabsw) {
- uv[0] = tri_uv[0]->uv[0] * w[0] + tri_uv[1]->uv[0] * w[1] + tri_uv[2]->uv[0] * w[2];
- uv[1] = tri_uv[0]->uv[1] * w[0] + tri_uv[1]->uv[1] * w[1] + tri_uv[2]->uv[1] * w[2];
- minabsw = absw;
- }
- }
- }
+ int i, findex;
+ float p[2], w[3], absw, minabsw;
+ float matrix[4][4], proj[4][4];
+ GLint view[4];
+ const eImagePaintMode mode = scene->toolsettings->imapaint.mode;
+
+ const MLoopTri *lt = BKE_mesh_runtime_looptri_ensure(me_eval);
+ const int tottri = me_eval->runtime.looptris.len;
+
+ const MVert *mvert = me_eval->mvert;
+ const MPoly *mpoly = me_eval->mpoly;
+ const MLoop *mloop = me_eval->mloop;
+ const int *index_mp_to_orig = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX);
+
+ /* get the needed opengl matrices */
+ GPU_viewport_size_get_i(view);
+ GPU_matrix_model_view_get(matrix);
+ GPU_matrix_projection_get(proj);
+ view[0] = view[1] = 0;
+ mul_m4_m4m4(matrix, matrix, ob_eval->obmat);
+ mul_m4_m4m4(matrix, proj, matrix);
+
+ minabsw = 1e10;
+ uv[0] = uv[1] = 0.0;
+
+ /* test all faces in the derivedmesh with the original index of the picked face */
+ /* face means poly here, not triangle, indeed */
+ for (i = 0; i < tottri; i++, lt++) {
+ findex = index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly;
+
+ if (findex == faceindex) {
+ const MLoopUV *mloopuv;
+ const MPoly *mp = &mpoly[lt->poly];
+ const MLoopUV *tri_uv[3];
+ float tri_co[3][3];
+
+ for (int j = 3; j--;) {
+ copy_v3_v3(tri_co[j], mvert[mloop[lt->tri[j]].v].co);
+ }
+
+ if (mode == IMAGEPAINT_MODE_MATERIAL) {
+ const Material *ma;
+ const TexPaintSlot *slot;
+
+ ma = give_current_material(ob_eval, mp->mat_nr + 1);
+ slot = &ma->texpaintslot[ma->paint_active_slot];
+
+ if (!(slot && slot->uvname &&
+ (mloopuv = CustomData_get_layer_named(&me_eval->ldata, CD_MLOOPUV, slot->uvname)))) {
+ mloopuv = CustomData_get_layer(&me_eval->ldata, CD_MLOOPUV);
+ }
+ }
+ else {
+ mloopuv = CustomData_get_layer(&me_eval->ldata, CD_MLOOPUV);
+ }
+
+ tri_uv[0] = &mloopuv[lt->tri[0]];
+ tri_uv[1] = &mloopuv[lt->tri[1]];
+ tri_uv[2] = &mloopuv[lt->tri[2]];
+
+ p[0] = xy[0];
+ p[1] = xy[1];
+
+ imapaint_tri_weights(matrix, view, UNPACK3(tri_co), p, w);
+ absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
+ if (absw < minabsw) {
+ uv[0] = tri_uv[0]->uv[0] * w[0] + tri_uv[1]->uv[0] * w[1] + tri_uv[2]->uv[0] * w[2];
+ uv[1] = tri_uv[0]->uv[1] * w[0] + tri_uv[1]->uv[1] * w[1] + tri_uv[2]->uv[1] * w[2];
+ minabsw = absw;
+ }
+ }
+ }
}
/* 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],
+ unsigned int *r_index,
+ unsigned int totpoly)
{
- if (totpoly == 0)
- return 0;
+ if (totpoly == 0)
+ return 0;
- /* sample only on the exact position */
- *r_index = ED_view3d_select_id_sample(vc, mval[0], mval[1]);
+ /* sample only on the exact position */
+ *r_index = ED_view3d_select_id_sample(vc, mval[0], mval[1]);
- if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) {
- return 0;
- }
+ if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) {
+ return 0;
+ }
- (*r_index)--;
+ (*r_index)--;
- return 1;
+ return 1;
}
-
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);
- ima = ma && ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
+ Image *ima;
+ MPoly *mp = me->mpoly + face_index;
+ Material *ma = give_current_material(ob, mp->mat_nr + 1);
+ ima = ma && ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
- return ima;
+ return ima;
}
/* Uses symm to selectively flip any axis of a coordinate. */
void flip_v3_v3(float out[3], const float in[3], const char symm)
{
- if (symm & PAINT_SYMM_X)
- out[0] = -in[0];
- else
- out[0] = in[0];
- if (symm & PAINT_SYMM_Y)
- out[1] = -in[1];
- else
- out[1] = in[1];
- if (symm & PAINT_SYMM_Z)
- out[2] = -in[2];
- else
- out[2] = in[2];
+ if (symm & PAINT_SYMM_X)
+ out[0] = -in[0];
+ else
+ out[0] = in[0];
+ if (symm & PAINT_SYMM_Y)
+ out[1] = -in[1];
+ else
+ out[1] = in[1];
+ if (symm & PAINT_SYMM_Z)
+ out[2] = -in[2];
+ else
+ out[2] = in[2];
}
void flip_qt_qt(float out[4], const float in[4], const char symm)
{
- float axis[3], angle;
-
- quat_to_axis_angle(axis, &angle, in);
- normalize_v3(axis);
-
- if (symm & PAINT_SYMM_X) {
- axis[0] *= -1.0f;
- angle *= -1.0f;
- }
- if (symm & PAINT_SYMM_Y) {
- axis[1] *= -1.0f;
- angle *= -1.0f;
- }
- if (symm & PAINT_SYMM_Z) {
- axis[2] *= -1.0f;
- angle *= -1.0f;
- }
-
- axis_angle_normalized_to_quat(out, axis, angle);
+ float axis[3], angle;
+
+ quat_to_axis_angle(axis, &angle, in);
+ normalize_v3(axis);
+
+ if (symm & PAINT_SYMM_X) {
+ axis[0] *= -1.0f;
+ angle *= -1.0f;
+ }
+ if (symm & PAINT_SYMM_Y) {
+ axis[1] *= -1.0f;
+ angle *= -1.0f;
+ }
+ if (symm & PAINT_SYMM_Z) {
+ axis[2] *= -1.0f;
+ angle *= -1.0f;
+ }
+
+ axis_angle_normalized_to_quat(out, axis, angle);
}
/* 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)
+void paint_sample_color(
+ bContext *C, ARegion *ar, int x, int y, bool texpaint_proj, bool use_palette)
{
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Paint *paint = BKE_paint_get_active_from_context(C);
- 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;
-
- CLAMP(x, 0, ar->winx);
- CLAMP(y, 0, ar->winy);
-
- if (use_palette) {
- if (!palette) {
- palette = BKE_palette_add(CTX_data_main(C), "Palette");
- BKE_paint_palette_set(paint, palette);
- }
-
- color = BKE_palette_color_add(palette);
- palette->active_color = BLI_listbase_count(&palette->colors) - 1;
- }
-
-
- if (CTX_wm_view3d(C) && texpaint_proj) {
- /* first try getting a colour directly from the mesh faces if possible */
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- bool sample_success = false;
- ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
- bool use_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL);
-
- if (ob) {
- CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH;
- cddata_masks.pmask |= CD_MASK_ORIGINDEX;
- Mesh *me = (Mesh *)ob->data;
- Mesh *me_eval = mesh_get_eval_final(depsgraph, scene, ob_eval, &cddata_masks);
-
- ViewContext vc;
- const int mval[2] = {x, y};
- unsigned int faceindex;
- unsigned int totpoly = me->totpoly;
-
- if (CustomData_has_layer(&me_eval->ldata, CD_MLOOPUV)) {
- ED_view3d_viewcontext_init(C, &vc);
-
- view3d_operator_needs_opengl(C);
-
- if (imapaint_pick_face(&vc, mval, &faceindex, totpoly)) {
- Image *image;
-
- if (use_material)
- image = imapaint_face_image(ob_eval, me_eval, faceindex);
- else
- image = imapaint->canvas;
-
- if (image) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
- if (ibuf && ibuf->rect) {
- float uv[2];
- float u, v;
- imapaint_pick_uv(me_eval, scene, ob_eval, faceindex, mval, uv);
- sample_success = true;
-
- u = fmodf(uv[0], 1.0f);
- v = fmodf(uv[1], 1.0f);
-
- if (u < 0.0f) u += 1.0f;
- if (v < 0.0f) v += 1.0f;
-
- u = u * ibuf->x;
- v = v * ibuf->y;
-
- if (ibuf->rect_float) {
- float rgba_f[4];
- bilinear_interpolation_color_wrap(ibuf, NULL, rgba_f, u, v);
- straight_to_premul_v4(rgba_f);
- if (use_palette) {
- linearrgb_to_srgb_v3_v3(color->rgb, rgba_f);
- }
- else {
- linearrgb_to_srgb_v3_v3(rgba_f, rgba_f);
- BKE_brush_color_set(scene, br, rgba_f);
- }
- }
- else {
- unsigned char rgba[4];
- bilinear_interpolation_color_wrap(ibuf, rgba, NULL, u, v);
- if (use_palette) {
- rgb_uchar_to_float(color->rgb, rgba);
- }
- else {
- float rgba_f[3];
- rgb_uchar_to_float(rgba_f, rgba);
- BKE_brush_color_set(scene, br, rgba_f);
- }
- }
- }
-
- BKE_image_release_ibuf(image, ibuf, NULL);
- }
- }
- }
- }
-
- if (!sample_success) {
- glReadBuffer(GL_FRONT);
- glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
- glReadBuffer(GL_BACK);
- }
- else
- return;
- }
- else {
- glReadBuffer(GL_FRONT);
- glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
- glReadBuffer(GL_BACK);
- }
- cp = (unsigned char *)&col;
-
- if (use_palette) {
- rgb_uchar_to_float(color->rgb, cp);
- }
- else {
- float rgba_f[3];
- rgb_uchar_to_float(rgba_f, cp);
- BKE_brush_color_set(scene, br, rgba_f);
- }
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ 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;
+
+ CLAMP(x, 0, ar->winx);
+ CLAMP(y, 0, ar->winy);
+
+ if (use_palette) {
+ if (!palette) {
+ palette = BKE_palette_add(CTX_data_main(C), "Palette");
+ BKE_paint_palette_set(paint, palette);
+ }
+
+ color = BKE_palette_color_add(palette);
+ palette->active_color = BLI_listbase_count(&palette->colors) - 1;
+ }
+
+ if (CTX_wm_view3d(C) && texpaint_proj) {
+ /* first try getting a colour directly from the mesh faces if possible */
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ bool sample_success = false;
+ ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
+ bool use_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL);
+
+ if (ob) {
+ CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH;
+ cddata_masks.pmask |= CD_MASK_ORIGINDEX;
+ Mesh *me = (Mesh *)ob->data;
+ Mesh *me_eval = mesh_get_eval_final(depsgraph, scene, ob_eval, &cddata_masks);
+
+ ViewContext vc;
+ const int mval[2] = {x, y};
+ unsigned int faceindex;
+ unsigned int totpoly = me->totpoly;
+
+ if (CustomData_has_layer(&me_eval->ldata, CD_MLOOPUV)) {
+ ED_view3d_viewcontext_init(C, &vc);
+
+ view3d_operator_needs_opengl(C);
+
+ if (imapaint_pick_face(&vc, mval, &faceindex, totpoly)) {
+ Image *image;
+
+ if (use_material)
+ image = imapaint_face_image(ob_eval, me_eval, faceindex);
+ else
+ image = imapaint->canvas;
+
+ if (image) {
+ ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
+ if (ibuf && ibuf->rect) {
+ float uv[2];
+ float u, v;
+ imapaint_pick_uv(me_eval, scene, ob_eval, faceindex, mval, uv);
+ sample_success = true;
+
+ u = fmodf(uv[0], 1.0f);
+ v = fmodf(uv[1], 1.0f);
+
+ if (u < 0.0f)
+ u += 1.0f;
+ if (v < 0.0f)
+ v += 1.0f;
+
+ u = u * ibuf->x;
+ v = v * ibuf->y;
+
+ if (ibuf->rect_float) {
+ float rgba_f[4];
+ bilinear_interpolation_color_wrap(ibuf, NULL, rgba_f, u, v);
+ straight_to_premul_v4(rgba_f);
+ if (use_palette) {
+ linearrgb_to_srgb_v3_v3(color->rgb, rgba_f);
+ }
+ else {
+ linearrgb_to_srgb_v3_v3(rgba_f, rgba_f);
+ BKE_brush_color_set(scene, br, rgba_f);
+ }
+ }
+ else {
+ unsigned char rgba[4];
+ bilinear_interpolation_color_wrap(ibuf, rgba, NULL, u, v);
+ if (use_palette) {
+ rgb_uchar_to_float(color->rgb, rgba);
+ }
+ else {
+ float rgba_f[3];
+ rgb_uchar_to_float(rgba_f, rgba);
+ BKE_brush_color_set(scene, br, rgba_f);
+ }
+ }
+ }
+
+ BKE_image_release_ibuf(image, ibuf, NULL);
+ }
+ }
+ }
+ }
+
+ if (!sample_success) {
+ glReadBuffer(GL_FRONT);
+ glReadPixels(
+ x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
+ glReadBuffer(GL_BACK);
+ }
+ else
+ return;
+ }
+ else {
+ glReadBuffer(GL_FRONT);
+ glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
+ glReadBuffer(GL_BACK);
+ }
+ cp = (unsigned char *)&col;
+
+ if (use_palette) {
+ rgb_uchar_to_float(color->rgb, cp);
+ }
+ else {
+ float rgba_f[3];
+ rgb_uchar_to_float(rgba_f, cp);
+ BKE_brush_color_set(scene, br, rgba_f);
+ }
}
static int brush_curve_preset_exec(bContext *C, wmOperator *op)
{
- Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));
+ Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));
- if (br) {
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- BKE_brush_curve_preset(br, RNA_enum_get(op->ptr, "shape"));
- BKE_paint_invalidate_cursor_overlay(scene, view_layer, br->curve);
- }
+ if (br) {
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_brush_curve_preset(br, RNA_enum_get(op->ptr, "shape"));
+ BKE_paint_invalidate_cursor_overlay(scene, view_layer, br->curve);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static bool brush_curve_preset_poll(bContext *C)
{
- Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));
+ Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));
- return br && br->curve;
+ return br && br->curve;
}
void BRUSH_OT_curve_preset(wmOperatorType *ot)
{
- PropertyRNA *prop;
- static const EnumPropertyItem prop_shape_items[] = {
- {CURVE_PRESET_SHARP, "SHARP", 0, "Sharp", ""},
- {CURVE_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""},
- {CURVE_PRESET_MAX, "MAX", 0, "Max", ""},
- {CURVE_PRESET_LINE, "LINE", 0, "Line", ""},
- {CURVE_PRESET_ROUND, "ROUND", 0, "Round", ""},
- {CURVE_PRESET_ROOT, "ROOT", 0, "Root", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- ot->name = "Preset";
- ot->description = "Set brush shape";
- ot->idname = "BRUSH_OT_curve_preset";
-
- ot->exec = brush_curve_preset_exec;
- ot->poll = brush_curve_preset_poll;
-
- prop = RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", "");
- RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
+ PropertyRNA *prop;
+ static const EnumPropertyItem prop_shape_items[] = {
+ {CURVE_PRESET_SHARP, "SHARP", 0, "Sharp", ""},
+ {CURVE_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""},
+ {CURVE_PRESET_MAX, "MAX", 0, "Max", ""},
+ {CURVE_PRESET_LINE, "LINE", 0, "Line", ""},
+ {CURVE_PRESET_ROUND, "ROUND", 0, "Round", ""},
+ {CURVE_PRESET_ROOT, "ROOT", 0, "Root", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ ot->name = "Preset";
+ ot->description = "Set brush shape";
+ ot->idname = "BRUSH_OT_curve_preset";
+
+ ot->exec = brush_curve_preset_exec;
+ ot->poll = brush_curve_preset_poll;
+
+ prop = RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", "");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
}
-
/* face-select ops */
static int paint_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
{
- paintface_select_linked(C, CTX_data_active_object(C), NULL, true);
- ED_region_tag_redraw(CTX_wm_region(C));
- return OPERATOR_FINISHED;
+ paintface_select_linked(C, CTX_data_active_object(C), NULL, true);
+ ED_region_tag_redraw(CTX_wm_region(C));
+ return OPERATOR_FINISHED;
}
void PAINT_OT_face_select_linked(wmOperatorType *ot)
{
- ot->name = "Select Linked";
- ot->description = "Select linked faces";
- ot->idname = "PAINT_OT_face_select_linked";
+ ot->name = "Select Linked";
+ ot->description = "Select linked faces";
+ ot->idname = "PAINT_OT_face_select_linked";
- ot->exec = paint_select_linked_exec;
- ot->poll = facemask_paint_poll;
+ ot->exec = paint_select_linked_exec;
+ ot->poll = facemask_paint_poll;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int paint_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- const bool select = !RNA_boolean_get(op->ptr, "deselect");
- view3d_operator_needs_opengl(C);
- paintface_select_linked(C, CTX_data_active_object(C), event->mval, select);
- ED_region_tag_redraw(CTX_wm_region(C));
- return OPERATOR_FINISHED;
+ const bool select = !RNA_boolean_get(op->ptr, "deselect");
+ view3d_operator_needs_opengl(C);
+ paintface_select_linked(C, CTX_data_active_object(C), event->mval, select);
+ ED_region_tag_redraw(CTX_wm_region(C));
+ return OPERATOR_FINISHED;
}
void PAINT_OT_face_select_linked_pick(wmOperatorType *ot)
{
- ot->name = "Select Linked Pick";
- ot->description = "Select linked faces under the cursor";
- ot->idname = "PAINT_OT_face_select_linked_pick";
+ ot->name = "Select Linked Pick";
+ ot->description = "Select linked faces under the cursor";
+ ot->idname = "PAINT_OT_face_select_linked_pick";
- ot->invoke = paint_select_linked_pick_invoke;
- ot->poll = facemask_paint_poll;
+ ot->invoke = paint_select_linked_pick_invoke;
+ ot->poll = facemask_paint_poll;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect rather than select items");
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect rather than select items");
}
-
static int face_select_all_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
- if (paintface_deselect_all_visible(C, ob, RNA_enum_get(op->ptr, "action"), true)) {
- ED_region_tag_redraw(CTX_wm_region(C));
- return OPERATOR_FINISHED;
- }
- return OPERATOR_CANCELLED;
+ Object *ob = CTX_data_active_object(C);
+ if (paintface_deselect_all_visible(C, ob, RNA_enum_get(op->ptr, "action"), true)) {
+ ED_region_tag_redraw(CTX_wm_region(C));
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_CANCELLED;
}
-
void PAINT_OT_face_select_all(wmOperatorType *ot)
{
- ot->name = "(De)select All";
- ot->description = "Change selection for all faces";
- ot->idname = "PAINT_OT_face_select_all";
+ ot->name = "(De)select All";
+ ot->description = "Change selection for all faces";
+ ot->idname = "PAINT_OT_face_select_all";
- ot->exec = face_select_all_exec;
- ot->poll = facemask_paint_poll;
+ ot->exec = face_select_all_exec;
+ ot->poll = facemask_paint_poll;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_select_all(ot);
+ WM_operator_properties_select_all(ot);
}
-
static int vert_select_all_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
- paintvert_deselect_all_visible(ob, RNA_enum_get(op->ptr, "action"), true);
- paintvert_tag_select_update(C, ob);
- ED_region_tag_redraw(CTX_wm_region(C));
- return OPERATOR_FINISHED;
+ Object *ob = CTX_data_active_object(C);
+ paintvert_deselect_all_visible(ob, RNA_enum_get(op->ptr, "action"), true);
+ paintvert_tag_select_update(C, ob);
+ ED_region_tag_redraw(CTX_wm_region(C));
+ return OPERATOR_FINISHED;
}
-
void PAINT_OT_vert_select_all(wmOperatorType *ot)
{
- ot->name = "(De)select All";
- ot->description = "Change selection for all vertices";
- ot->idname = "PAINT_OT_vert_select_all";
+ ot->name = "(De)select All";
+ ot->description = "Change selection for all vertices";
+ ot->idname = "PAINT_OT_vert_select_all";
- ot->exec = vert_select_all_exec;
- ot->poll = vert_paint_poll;
+ ot->exec = vert_select_all_exec;
+ ot->poll = vert_paint_poll;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_select_all(ot);
+ WM_operator_properties_select_all(ot);
}
-
static int vert_select_ungrouped_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
- Mesh *me = ob->data;
-
- if (BLI_listbase_is_empty(&ob->defbase) || (me->dvert == NULL)) {
- BKE_report(op->reports, RPT_ERROR, "No weights/vertex groups on object");
- return OPERATOR_CANCELLED;
- }
-
- paintvert_select_ungrouped(ob, RNA_boolean_get(op->ptr, "extend"), true);
- paintvert_tag_select_update(C, ob);
- ED_region_tag_redraw(CTX_wm_region(C));
- return OPERATOR_FINISHED;
+ Object *ob = CTX_data_active_object(C);
+ Mesh *me = ob->data;
+
+ if (BLI_listbase_is_empty(&ob->defbase) || (me->dvert == NULL)) {
+ BKE_report(op->reports, RPT_ERROR, "No weights/vertex groups on object");
+ return OPERATOR_CANCELLED;
+ }
+
+ paintvert_select_ungrouped(ob, RNA_boolean_get(op->ptr, "extend"), true);
+ paintvert_tag_select_update(C, ob);
+ ED_region_tag_redraw(CTX_wm_region(C));
+ return OPERATOR_FINISHED;
}
void PAINT_OT_vert_select_ungrouped(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Ungrouped";
- ot->idname = "PAINT_OT_vert_select_ungrouped";
- ot->description = "Select vertices without a group";
+ /* identifiers */
+ ot->name = "Select Ungrouped";
+ ot->idname = "PAINT_OT_vert_select_ungrouped";
+ ot->description = "Select vertices without a group";
- /* api callbacks */
- ot->exec = vert_select_ungrouped_exec;
- ot->poll = vert_paint_poll;
+ /* api callbacks */
+ ot->exec = vert_select_ungrouped_exec;
+ ot->poll = vert_paint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
static int face_select_hide_exec(bContext *C, wmOperator *op)
{
- const bool unselected = RNA_boolean_get(op->ptr, "unselected");
- Object *ob = CTX_data_active_object(C);
- paintface_hide(C, ob, unselected);
- ED_region_tag_redraw(CTX_wm_region(C));
- return OPERATOR_FINISHED;
+ const bool unselected = RNA_boolean_get(op->ptr, "unselected");
+ Object *ob = CTX_data_active_object(C);
+ paintface_hide(C, ob, unselected);
+ ED_region_tag_redraw(CTX_wm_region(C));
+ return OPERATOR_FINISHED;
}
void PAINT_OT_face_select_hide(wmOperatorType *ot)
{
- ot->name = "Face Select Hide";
- ot->description = "Hide selected faces";
- ot->idname = "PAINT_OT_face_select_hide";
+ ot->name = "Face Select Hide";
+ ot->description = "Hide selected faces";
+ ot->idname = "PAINT_OT_face_select_hide";
- ot->exec = face_select_hide_exec;
- ot->poll = facemask_paint_poll;
+ ot->exec = face_select_hide_exec;
+ ot->poll = facemask_paint_poll;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
+ RNA_def_boolean(
+ ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
}
static int face_select_reveal_exec(bContext *C, wmOperator *op)
{
- const bool select = RNA_boolean_get(op->ptr, "select");
- Object *ob = CTX_data_active_object(C);
- paintface_reveal(C, ob, select);
- ED_region_tag_redraw(CTX_wm_region(C));
- return OPERATOR_FINISHED;
+ const bool select = RNA_boolean_get(op->ptr, "select");
+ Object *ob = CTX_data_active_object(C);
+ paintface_reveal(C, ob, select);
+ ED_region_tag_redraw(CTX_wm_region(C));
+ return OPERATOR_FINISHED;
}
void PAINT_OT_face_select_reveal(wmOperatorType *ot)
{
- ot->name = "Face Select Reveal";
- ot->description = "Reveal hidden faces";
- ot->idname = "PAINT_OT_face_select_reveal";
+ ot->name = "Face Select Reveal";
+ ot->description = "Reveal hidden faces";
+ ot->idname = "PAINT_OT_face_select_reveal";
- ot->exec = face_select_reveal_exec;
- ot->poll = facemask_paint_poll;
+ ot->exec = face_select_reveal_exec;
+ ot->poll = facemask_paint_poll;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "select", true, "Select", "");
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 85bdba683cd..70783ff004e 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -77,130 +77,130 @@
#include "BKE_ccg.h"
#include "sculpt_intern.h"
-#include "paint_intern.h" /* own include */
+#include "paint_intern.h" /* own include */
/* Use for 'blur' brush, align with PBVH nodes, created and freed on each update. */
struct VPaintAverageAccum {
- uint len;
- uint value[3];
+ uint len;
+ uint value[3];
};
struct WPaintAverageAccum {
- uint len;
- double value;
+ uint len;
+ double value;
};
struct NormalAnglePrecalc {
- bool do_mask_normal;
- /* what angle to mask at */
- float angle;
- /* cos(angle), faster to compare */
- float angle__cos;
- float angle_inner;
- float angle_inner__cos;
- /* difference between angle and angle_inner, for easy access */
- float angle_range;
+ bool do_mask_normal;
+ /* what angle to mask at */
+ float angle;
+ /* cos(angle), faster to compare */
+ float angle__cos;
+ float angle_inner;
+ float angle_inner__cos;
+ /* difference between angle and angle_inner, for easy access */
+ float angle_range;
};
-
-static void view_angle_limits_init(
- struct NormalAnglePrecalc *a, float angle, bool do_mask_normal)
+static void view_angle_limits_init(struct NormalAnglePrecalc *a, float angle, bool do_mask_normal)
{
- angle = RAD2DEGF(angle);
- a->do_mask_normal = do_mask_normal;
- if (do_mask_normal) {
- a->angle_inner = angle;
- a->angle = (a->angle_inner + 90.0f) * 0.5f;
- }
- else {
- a->angle_inner = a->angle = angle;
- }
+ angle = RAD2DEGF(angle);
+ a->do_mask_normal = do_mask_normal;
+ if (do_mask_normal) {
+ a->angle_inner = angle;
+ a->angle = (a->angle_inner + 90.0f) * 0.5f;
+ }
+ else {
+ a->angle_inner = a->angle = angle;
+ }
- a->angle_inner *= (float)(M_PI_2 / 90);
- a->angle *= (float)(M_PI_2 / 90);
- a->angle_range = a->angle - a->angle_inner;
+ a->angle_inner *= (float)(M_PI_2 / 90);
+ a->angle *= (float)(M_PI_2 / 90);
+ a->angle_range = a->angle - a->angle_inner;
- if (a->angle_range <= 0.0f) {
- a->do_mask_normal = false; /* no need to do blending */
- }
+ if (a->angle_range <= 0.0f) {
+ a->do_mask_normal = false; /* no need to do blending */
+ }
- a->angle__cos = cosf(a->angle);
- a->angle_inner__cos = cosf(a->angle_inner);
+ a->angle__cos = cosf(a->angle);
+ a->angle_inner__cos = cosf(a->angle_inner);
}
-static float view_angle_limits_apply_falloff(
- const struct NormalAnglePrecalc *a, float angle_cos, float *mask_p)
+static float view_angle_limits_apply_falloff(const struct NormalAnglePrecalc *a,
+ float angle_cos,
+ float *mask_p)
{
- if (angle_cos <= a->angle__cos) {
- /* outsize the normal limit */
- return false;
- }
- else if (angle_cos < a->angle_inner__cos) {
- *mask_p *= (a->angle - acosf(angle_cos)) / a->angle_range;
- return true;
- }
- else {
- return true;
- }
+ if (angle_cos <= a->angle__cos) {
+ /* outsize the normal limit */
+ return false;
+ }
+ else if (angle_cos < a->angle_inner__cos) {
+ *mask_p *= (a->angle - acosf(angle_cos)) / a->angle_range;
+ return true;
+ }
+ else {
+ return true;
+ }
}
static bool vwpaint_use_normal(const VPaint *vp)
{
- return ((vp->paint.brush->flag & BRUSH_FRONTFACE) != 0) ||
- ((vp->paint.brush->flag & BRUSH_FRONTFACE_FALLOFF) != 0);
+ return ((vp->paint.brush->flag & BRUSH_FRONTFACE) != 0) ||
+ ((vp->paint.brush->flag & BRUSH_FRONTFACE_FALLOFF) != 0);
}
static bool brush_use_accumulate_ex(const Brush *brush, const int ob_mode)
{
- return ((brush->flag & BRUSH_ACCUMULATE) != 0 ||
- (ob_mode == OB_MODE_VERTEX_PAINT ?
- (brush->vertexpaint_tool == VPAINT_TOOL_SMEAR) :
- (brush->weightpaint_tool == WPAINT_TOOL_SMEAR)));
+ return ((brush->flag & BRUSH_ACCUMULATE) != 0 ||
+ (ob_mode == OB_MODE_VERTEX_PAINT ? (brush->vertexpaint_tool == VPAINT_TOOL_SMEAR) :
+ (brush->weightpaint_tool == WPAINT_TOOL_SMEAR)));
}
static bool brush_use_accumulate(const VPaint *vp)
{
- return brush_use_accumulate_ex(vp->paint.brush, vp->paint.runtime.ob_mode);
+ return brush_use_accumulate_ex(vp->paint.brush, vp->paint.runtime.ob_mode);
}
-static MDeformVert *defweight_prev_init(MDeformVert *dvert_prev, MDeformVert *dvert_curr, int index)
+static MDeformVert *defweight_prev_init(MDeformVert *dvert_prev,
+ MDeformVert *dvert_curr,
+ int index)
{
- MDeformVert *dv_curr = &dvert_curr[index];
- MDeformVert *dv_prev = &dvert_prev[index];
- if (dv_prev->flag == 1) {
- dv_prev->flag = 0;
- defvert_copy(dv_prev, dv_curr);
- }
- return dv_prev;
+ MDeformVert *dv_curr = &dvert_curr[index];
+ MDeformVert *dv_prev = &dvert_prev[index];
+ if (dv_prev->flag == 1) {
+ dv_prev->flag = 0;
+ defvert_copy(dv_prev, dv_curr);
+ }
+ return dv_prev;
}
/* check if we can do partial updates and have them draw realtime
* (without evaluating modifiers) */
static bool vertex_paint_use_fast_update_check(Object *ob)
{
- Mesh *me_eval = ob->runtime.mesh_eval;
+ Mesh *me_eval = ob->runtime.mesh_eval;
- if (me_eval != NULL) {
- Mesh *me = BKE_mesh_from_object(ob);
- if (me && me->mloopcol) {
- return (me->mloopcol == CustomData_get_layer(&me_eval->ldata, CD_MLOOPCOL));
- }
- }
+ if (me_eval != NULL) {
+ Mesh *me = BKE_mesh_from_object(ob);
+ if (me && me->mloopcol) {
+ return (me->mloopcol == CustomData_get_layer(&me_eval->ldata, CD_MLOOPCOL));
+ }
+ }
- return false;
+ return false;
}
static void paint_last_stroke_update(Scene *scene, ARegion *ar, const float mval[2])
{
- const int mval_i[2] = {mval[0], mval[1]};
- float world[3];
+ const int mval_i[2] = {mval[0], mval[1]};
+ float world[3];
- if (ED_view3d_autodist_simple(ar, mval_i, world, 0, NULL)) {
- UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
- ups->average_stroke_counter++;
- add_v3_v3(ups->average_stroke_accum, world);
- ups->last_stroke_valid = true;
- }
+ if (ED_view3d_autodist_simple(ar, mval_i, world, 0, NULL)) {
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+ ups->average_stroke_counter++;
+ add_v3_v3(ups->average_stroke_accum, world);
+ ups->last_stroke_valid = true;
+ }
}
/* polling - retrieve whether cursor should be set or operator should be done */
@@ -208,349 +208,360 @@ static void paint_last_stroke_update(Scene *scene, ARegion *ar, const float mval
/* Returns true if vertex paint mode is active */
bool vertex_paint_mode_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- return ob && ob->mode == OB_MODE_VERTEX_PAINT && ((Mesh *)ob->data)->totpoly;
+ return ob && ob->mode == OB_MODE_VERTEX_PAINT && ((Mesh *)ob->data)->totpoly;
}
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) {
- if (!check_tool || WM_toolsystem_active_tool_is_brush(C)) {
- return 1;
- }
- }
- }
- }
- return 0;
+ 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) {
+ if (!check_tool || WM_toolsystem_active_tool_is_brush(C)) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
}
bool vertex_paint_poll(bContext *C)
{
- return vertex_paint_poll_ex(C, true);
+ return vertex_paint_poll_ex(C, true);
}
bool vertex_paint_poll_ignore_tool(bContext *C)
{
- return vertex_paint_poll_ex(C, false);
+ return vertex_paint_poll_ex(C, false);
}
bool weight_paint_mode_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- return ob && ob->mode == OB_MODE_WEIGHT_PAINT && ((Mesh *)ob->data)->totpoly;
+ return ob && ob->mode == OB_MODE_WEIGHT_PAINT && ((Mesh *)ob->data)->totpoly;
}
static bool weight_paint_poll_ex(bContext *C, bool check_tool)
{
- Object *ob = CTX_data_active_object(C);
- ScrArea *sa;
-
- 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 (ar->regiontype == RGN_TYPE_WINDOW) {
- if (!check_tool || WM_toolsystem_active_tool_is_brush(C)) {
- return 1;
- }
- }
- }
- return 0;
+ Object *ob = CTX_data_active_object(C);
+ ScrArea *sa;
+
+ 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 (ar->regiontype == RGN_TYPE_WINDOW) {
+ if (!check_tool || WM_toolsystem_active_tool_is_brush(C)) {
+ return 1;
+ }
+ }
+ }
+ return 0;
}
bool weight_paint_poll(bContext *C)
{
- return weight_paint_poll_ex(C, true);
+ return weight_paint_poll_ex(C, true);
}
bool weight_paint_poll_ignore_tool(bContext *C)
{
- return weight_paint_poll_ex(C, false);
+ return weight_paint_poll_ex(C, false);
}
uint vpaint_get_current_col(Scene *scene, VPaint *vp, bool secondary)
{
- Brush *brush = BKE_paint_brush(&vp->paint);
- uchar col[4];
- rgb_float_to_uchar(col, secondary ? BKE_brush_secondary_color_get(scene, brush) : BKE_brush_color_get(scene, brush));
- col[3] = 255; /* alpha isn't used, could even be removed to speedup paint a little */
- return *(uint *)col;
+ Brush *brush = BKE_paint_brush(&vp->paint);
+ uchar col[4];
+ rgb_float_to_uchar(col,
+ secondary ? BKE_brush_secondary_color_get(scene, brush) :
+ BKE_brush_color_get(scene, brush));
+ col[3] = 255; /* alpha isn't used, could even be removed to speedup paint a little */
+ return *(uint *)col;
}
/* wpaint has 'wpaint_blend' */
-static uint vpaint_blend(
- const VPaint *vp, uint color_curr, uint color_orig,
- uint color_paint, const int alpha_i,
- /* pre scaled from [0-1] --> [0-255] */
- const int brush_alpha_value_i)
-{
- const Brush *brush = vp->paint.brush;
- const IMB_BlendMode blend = brush->blend;
-
- uint color_blend = ED_vpaint_blend_tool(blend, color_curr, color_paint, alpha_i);
-
- /* if no accumulate, clip color adding with colorig & orig alpha */
- if (!brush_use_accumulate(vp)) {
- uint color_test, a;
- char *cp, *ct, *co;
-
- color_test = ED_vpaint_blend_tool(blend, color_orig, color_paint, brush_alpha_value_i);
-
- cp = (char *)&color_blend;
- ct = (char *)&color_test;
- co = (char *)&color_orig;
-
- for (a = 0; a < 4; a++) {
- if (ct[a] < co[a]) {
- if (cp[a] < ct[a]) cp[a] = ct[a];
- else if (cp[a] > co[a]) cp[a] = co[a];
- }
- else {
- if (cp[a] < co[a]) cp[a] = co[a];
- else if (cp[a] > ct[a]) cp[a] = ct[a];
- }
- }
- }
-
- if ((brush->flag & BRUSH_LOCK_ALPHA) &&
- !ELEM(blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA))
- {
- char *cp, *cc;
- cp = (char *)&color_blend;
- cc = (char *)&color_curr;
- cp[3] = cc[3];
- }
-
- return color_blend;
-}
-
-static void tex_color_alpha(
- VPaint *vp, const ViewContext *vc, const float co[3],
- float r_rgba[4])
-{
- const Brush *brush = BKE_paint_brush(&vp->paint);
- BLI_assert(brush->mtex.tex != NULL);
- if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) {
- BKE_brush_sample_tex_3d(vc->scene, brush, co, r_rgba, 0, NULL);
- }
- 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) == 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);
- }
- else {
- zero_v4(r_rgba);
- }
- }
+static uint vpaint_blend(const VPaint *vp,
+ uint color_curr,
+ uint color_orig,
+ uint color_paint,
+ const int alpha_i,
+ /* pre scaled from [0-1] --> [0-255] */
+ const int brush_alpha_value_i)
+{
+ const Brush *brush = vp->paint.brush;
+ const IMB_BlendMode blend = brush->blend;
+
+ uint color_blend = ED_vpaint_blend_tool(blend, color_curr, color_paint, alpha_i);
+
+ /* if no accumulate, clip color adding with colorig & orig alpha */
+ if (!brush_use_accumulate(vp)) {
+ uint color_test, a;
+ char *cp, *ct, *co;
+
+ color_test = ED_vpaint_blend_tool(blend, color_orig, color_paint, brush_alpha_value_i);
+
+ cp = (char *)&color_blend;
+ ct = (char *)&color_test;
+ co = (char *)&color_orig;
+
+ for (a = 0; a < 4; a++) {
+ if (ct[a] < co[a]) {
+ if (cp[a] < ct[a])
+ cp[a] = ct[a];
+ else if (cp[a] > co[a])
+ cp[a] = co[a];
+ }
+ else {
+ if (cp[a] < co[a])
+ cp[a] = co[a];
+ else if (cp[a] > ct[a])
+ cp[a] = ct[a];
+ }
+ }
+ }
+
+ if ((brush->flag & BRUSH_LOCK_ALPHA) &&
+ !ELEM(blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA)) {
+ char *cp, *cc;
+ cp = (char *)&color_blend;
+ cc = (char *)&color_curr;
+ cp[3] = cc[3];
+ }
+
+ return color_blend;
+}
+
+static void tex_color_alpha(VPaint *vp, const ViewContext *vc, const float co[3], float r_rgba[4])
+{
+ const Brush *brush = BKE_paint_brush(&vp->paint);
+ BLI_assert(brush->mtex.tex != NULL);
+ if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) {
+ BKE_brush_sample_tex_3d(vc->scene, brush, co, r_rgba, 0, NULL);
+ }
+ 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) ==
+ 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);
+ }
+ else {
+ zero_v4(r_rgba);
+ }
+ }
}
/* vpaint has 'vpaint_blend' */
-static float wpaint_blend(
- const VPaint *wp, float weight,
- const float alpha, float paintval,
- const float UNUSED(brush_alpha_value),
- const short do_flip)
-{
- const Brush *brush = wp->paint.brush;
- IMB_BlendMode blend = brush->blend;
-
- if (do_flip) {
- switch (blend) {
- case IMB_BLEND_MIX:
- paintval = 1.f - paintval; break;
- case IMB_BLEND_ADD:
- blend = IMB_BLEND_SUB; break;
- case IMB_BLEND_SUB:
- blend = IMB_BLEND_ADD; break;
- case IMB_BLEND_LIGHTEN:
- blend = IMB_BLEND_DARKEN; break;
- case IMB_BLEND_DARKEN:
- blend = IMB_BLEND_LIGHTEN; break;
- default: break;
- }
- }
-
- weight = ED_wpaint_blend_tool(blend, weight, paintval, alpha);
-
- CLAMP(weight, 0.0f, 1.0f);
-
- return weight;
+static float wpaint_blend(const VPaint *wp,
+ float weight,
+ const float alpha,
+ float paintval,
+ const float UNUSED(brush_alpha_value),
+ const short do_flip)
+{
+ const Brush *brush = wp->paint.brush;
+ IMB_BlendMode blend = brush->blend;
+
+ if (do_flip) {
+ switch (blend) {
+ case IMB_BLEND_MIX:
+ paintval = 1.f - paintval;
+ break;
+ case IMB_BLEND_ADD:
+ blend = IMB_BLEND_SUB;
+ break;
+ case IMB_BLEND_SUB:
+ blend = IMB_BLEND_ADD;
+ break;
+ case IMB_BLEND_LIGHTEN:
+ blend = IMB_BLEND_DARKEN;
+ break;
+ case IMB_BLEND_DARKEN:
+ blend = IMB_BLEND_LIGHTEN;
+ break;
+ default:
+ break;
+ }
+ }
+
+ weight = ED_wpaint_blend_tool(blend, weight, paintval, alpha);
+
+ CLAMP(weight, 0.0f, 1.0f);
+
+ return weight;
}
static float wpaint_clamp_monotonic(float oldval, float curval, float newval)
{
- if (newval < oldval)
- return MIN2(newval, curval);
- else if (newval > oldval)
- return MAX2(newval, curval);
- else
- return newval;
+ if (newval < oldval)
+ return MIN2(newval, curval);
+ else if (newval > oldval)
+ return MAX2(newval, curval);
+ else
+ return newval;
}
/* ----------------------------------------------------- */
-static void do_weight_paint_normalize_all(MDeformVert *dvert, const int defbase_tot, const bool *vgroup_validmap)
-{
- float sum = 0.0f, fac;
- uint i, tot = 0;
- MDeformWeight *dw;
-
- for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
- if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
- tot++;
- sum += dw->weight;
- }
- }
-
- if ((tot == 0) || (sum == 1.0f)) {
- return;
- }
-
- if (sum != 0.0f) {
- fac = 1.0f / sum;
-
- for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
- if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
- dw->weight *= fac;
- }
- }
- }
- else {
- /* hrmf, not a factor in this case */
- fac = 1.0f / tot;
-
- for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
- if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
- dw->weight = fac;
- }
- }
- }
+static void do_weight_paint_normalize_all(MDeformVert *dvert,
+ const int defbase_tot,
+ const bool *vgroup_validmap)
+{
+ float sum = 0.0f, fac;
+ uint i, tot = 0;
+ MDeformWeight *dw;
+
+ for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
+ if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
+ tot++;
+ sum += dw->weight;
+ }
+ }
+
+ if ((tot == 0) || (sum == 1.0f)) {
+ return;
+ }
+
+ if (sum != 0.0f) {
+ fac = 1.0f / sum;
+
+ for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
+ if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
+ dw->weight *= fac;
+ }
+ }
+ }
+ else {
+ /* hrmf, not a factor in this case */
+ fac = 1.0f / tot;
+
+ for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
+ if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
+ dw->weight = fac;
+ }
+ }
+ }
}
/**
* A version of #do_weight_paint_normalize_all that includes locked weights
* but only changes unlocked weights.
*/
-static bool do_weight_paint_normalize_all_locked(
- MDeformVert *dvert, const int defbase_tot, const bool *vgroup_validmap,
- const bool *lock_flags)
-{
- float sum = 0.0f, fac;
- float sum_unlock = 0.0f;
- float lock_weight = 0.0f;
- uint i, tot = 0;
- MDeformWeight *dw;
-
- if (lock_flags == NULL) {
- do_weight_paint_normalize_all(dvert, defbase_tot, vgroup_validmap);
- return true;
- }
-
- for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
- if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
- sum += dw->weight;
-
- if (lock_flags[dw->def_nr]) {
- lock_weight += dw->weight;
- }
- else {
- tot++;
- sum_unlock += dw->weight;
- }
- }
- }
-
- if (sum == 1.0f) {
- return true;
- }
-
- if (tot == 0) {
- return false;
- }
-
- if (lock_weight >= 1.0f) {
- /* locked groups make it impossible to fully normalize,
- * zero out what we can and return false */
- for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
- if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
- if (lock_flags[dw->def_nr] == false) {
- dw->weight = 0.0f;
- }
- }
- }
-
- return (lock_weight == 1.0f);
- }
- else if (sum_unlock != 0.0f) {
- fac = (1.0f - lock_weight) / sum_unlock;
-
- for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
- if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
- if (lock_flags[dw->def_nr] == false) {
- dw->weight *= fac;
- /* paranoid but possibly with float error */
- CLAMP(dw->weight, 0.0f, 1.0f);
- }
- }
- }
- }
- else {
- /* hrmf, not a factor in this case */
- fac = (1.0f - lock_weight) / tot;
- /* paranoid but possibly with float error */
- CLAMP(fac, 0.0f, 1.0f);
-
- for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
- if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
- if (lock_flags[dw->def_nr] == false) {
- dw->weight = fac;
- }
- }
- }
- }
-
- return true;
+static bool do_weight_paint_normalize_all_locked(MDeformVert *dvert,
+ const int defbase_tot,
+ const bool *vgroup_validmap,
+ const bool *lock_flags)
+{
+ float sum = 0.0f, fac;
+ float sum_unlock = 0.0f;
+ float lock_weight = 0.0f;
+ uint i, tot = 0;
+ MDeformWeight *dw;
+
+ if (lock_flags == NULL) {
+ do_weight_paint_normalize_all(dvert, defbase_tot, vgroup_validmap);
+ return true;
+ }
+
+ for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
+ if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
+ sum += dw->weight;
+
+ if (lock_flags[dw->def_nr]) {
+ lock_weight += dw->weight;
+ }
+ else {
+ tot++;
+ sum_unlock += dw->weight;
+ }
+ }
+ }
+
+ if (sum == 1.0f) {
+ return true;
+ }
+
+ if (tot == 0) {
+ return false;
+ }
+
+ if (lock_weight >= 1.0f) {
+ /* locked groups make it impossible to fully normalize,
+ * zero out what we can and return false */
+ for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
+ if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
+ if (lock_flags[dw->def_nr] == false) {
+ dw->weight = 0.0f;
+ }
+ }
+ }
+
+ return (lock_weight == 1.0f);
+ }
+ else if (sum_unlock != 0.0f) {
+ fac = (1.0f - lock_weight) / sum_unlock;
+
+ for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
+ if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
+ if (lock_flags[dw->def_nr] == false) {
+ dw->weight *= fac;
+ /* paranoid but possibly with float error */
+ CLAMP(dw->weight, 0.0f, 1.0f);
+ }
+ }
+ }
+ }
+ else {
+ /* hrmf, not a factor in this case */
+ fac = (1.0f - lock_weight) / tot;
+ /* paranoid but possibly with float error */
+ CLAMP(fac, 0.0f, 1.0f);
+
+ for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
+ if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
+ if (lock_flags[dw->def_nr] == false) {
+ dw->weight = fac;
+ }
+ }
+ }
+ }
+
+ return true;
}
/**
* \note same as function above except it does a second pass without active group
* if normalize fails with it.
*/
-static void do_weight_paint_normalize_all_locked_try_active(
- MDeformVert *dvert, const int defbase_tot, const bool *vgroup_validmap,
- const bool *lock_flags, const bool *lock_with_active)
-{
- /* first pass with both active and explicitly locked groups restricted from change */
-
- bool success = do_weight_paint_normalize_all_locked(dvert, defbase_tot, vgroup_validmap, lock_with_active);
-
- if (!success) {
- /**
- * Locks prevented the first pass from full completion, so remove restriction on active group; e.g:
- *
- * - With 1.0 weight painted into active:
- * nonzero locked weight; first pass zeroed out unlocked weight; scale 1 down to fit.
- * - With 0.0 weight painted into active:
- * no unlocked groups; first pass did nothing; increase 0 to fit.
- */
- do_weight_paint_normalize_all_locked(dvert, defbase_tot, vgroup_validmap, lock_flags);
- }
+static void do_weight_paint_normalize_all_locked_try_active(MDeformVert *dvert,
+ const int defbase_tot,
+ const bool *vgroup_validmap,
+ const bool *lock_flags,
+ const bool *lock_with_active)
+{
+ /* first pass with both active and explicitly locked groups restricted from change */
+
+ bool success = do_weight_paint_normalize_all_locked(
+ dvert, defbase_tot, vgroup_validmap, lock_with_active);
+
+ if (!success) {
+ /**
+ * Locks prevented the first pass from full completion, so remove restriction on active group; e.g:
+ *
+ * - With 1.0 weight painted into active:
+ * nonzero locked weight; first pass zeroed out unlocked weight; scale 1 down to fit.
+ * - With 0.0 weight painted into active:
+ * no unlocked groups; first pass did nothing; increase 0 to fit.
+ */
+ do_weight_paint_normalize_all_locked(dvert, defbase_tot, vgroup_validmap, lock_flags);
+ }
}
#if 0 /* UNUSED */
@@ -558,101 +569,108 @@ static bool has_unselected_unlocked_bone_group(
int defbase_tot, bool *defbase_sel, int selected,
const bool *lock_flags, const bool *vgroup_validmap)
{
- int i;
- if (defbase_tot == selected) {
- return false;
- }
- for (i = 0; i < defbase_tot; i++) {
- if (vgroup_validmap[i] && !defbase_sel[i] && !lock_flags[i]) {
- return true;
- }
- }
- return false;
+ int i;
+ if (defbase_tot == selected) {
+ return false;
+ }
+ for (i = 0; i < defbase_tot; i++) {
+ if (vgroup_validmap[i] && !defbase_sel[i] && !lock_flags[i]) {
+ return true;
+ }
+ }
+ return false;
}
#endif
-static void multipaint_clamp_change(
- MDeformVert *dvert, const int defbase_tot, const bool *defbase_sel,
- float *change_p)
-{
- int i;
- MDeformWeight *dw;
- float val;
- float change = *change_p;
-
- /* verify that the change does not cause values exceeding 1 and clamp it */
- for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
- if (dw->def_nr < defbase_tot && defbase_sel[dw->def_nr]) {
- if (dw->weight) {
- val = dw->weight * change;
- if (val > 1) {
- change = 1.0f / dw->weight;
- }
- }
- }
- }
-
- *change_p = change;
-}
-
-static bool multipaint_verify_change(MDeformVert *dvert, const int defbase_tot, float change, const bool *defbase_sel)
-{
- int i;
- MDeformWeight *dw;
- float val;
-
- /* in case the change is reduced, you need to recheck
- * the earlier values to make sure they are not 0
- * (precision error) */
- for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
- if (dw->def_nr < defbase_tot && defbase_sel[dw->def_nr]) {
- if (dw->weight) {
- val = dw->weight * change;
- /* the value should never reach zero while multi-painting if it
- * was nonzero beforehand */
- if (val <= 0) {
- return false;
- }
- }
- }
- }
-
- return true;
-}
-
-static void multipaint_apply_change(MDeformVert *dvert, const int defbase_tot, float change, const bool *defbase_sel)
-{
- int i;
- MDeformWeight *dw;
-
- /* apply the valid change */
- for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
- if (dw->def_nr < defbase_tot && defbase_sel[dw->def_nr]) {
- if (dw->weight) {
- dw->weight = dw->weight * change;
- CLAMP(dw->weight, 0.0f, 1.0f);
- }
- }
- }
+static void multipaint_clamp_change(MDeformVert *dvert,
+ const int defbase_tot,
+ const bool *defbase_sel,
+ float *change_p)
+{
+ int i;
+ MDeformWeight *dw;
+ float val;
+ float change = *change_p;
+
+ /* verify that the change does not cause values exceeding 1 and clamp it */
+ for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
+ if (dw->def_nr < defbase_tot && defbase_sel[dw->def_nr]) {
+ if (dw->weight) {
+ val = dw->weight * change;
+ if (val > 1) {
+ change = 1.0f / dw->weight;
+ }
+ }
+ }
+ }
+
+ *change_p = change;
+}
+
+static bool multipaint_verify_change(MDeformVert *dvert,
+ const int defbase_tot,
+ float change,
+ const bool *defbase_sel)
+{
+ int i;
+ MDeformWeight *dw;
+ float val;
+
+ /* in case the change is reduced, you need to recheck
+ * the earlier values to make sure they are not 0
+ * (precision error) */
+ for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
+ if (dw->def_nr < defbase_tot && defbase_sel[dw->def_nr]) {
+ if (dw->weight) {
+ val = dw->weight * change;
+ /* the value should never reach zero while multi-painting if it
+ * was nonzero beforehand */
+ if (val <= 0) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+static void multipaint_apply_change(MDeformVert *dvert,
+ const int defbase_tot,
+ float change,
+ const bool *defbase_sel)
+{
+ int i;
+ MDeformWeight *dw;
+
+ /* apply the valid change */
+ for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
+ if (dw->def_nr < defbase_tot && defbase_sel[dw->def_nr]) {
+ if (dw->weight) {
+ dw->weight = dw->weight * change;
+ CLAMP(dw->weight, 0.0f, 1.0f);
+ }
+ }
+ }
}
/**
* Variables stored both for 'active' and 'mirror' sides.
*/
struct WeightPaintGroupData {
- /** index of active group or its mirror
- *
- * - 'active' is always `ob->actdef`.
- * - 'mirror' is -1 when 'ME_EDIT_MIRROR_X' flag id disabled,
- * otherwise this will be set to the mirror or the active group (if the group isn't mirrored).
- */
- int index;
- /** lock that includes the 'index' as locked too
- *
- * - 'active' is set of locked or active/selected groups
- * - 'mirror' is set of locked or mirror groups
- */
- const bool *lock;
+ /** index of active group or its mirror
+ *
+ * - 'active' is always `ob->actdef`.
+ * - 'mirror' is -1 when 'ME_EDIT_MIRROR_X' flag id disabled,
+ * otherwise this will be set to the mirror or the active group (if the group isn't mirrored).
+ */
+ int index;
+ /** lock that includes the 'index' as locked too
+ *
+ * - 'active' is set of locked or active/selected groups
+ * - 'mirror' is set of locked or mirror groups
+ */
+ const bool *lock;
};
/* struct to avoid passing many args each call to do_weight_paint_vertex()
@@ -661,490 +679,504 @@ struct WeightPaintGroupData {
* paint stroke update - campbell */
typedef struct WeightPaintInfo {
- int defbase_tot;
+ int defbase_tot;
- /* both must add up to 'defbase_tot' */
- int defbase_tot_sel;
- int defbase_tot_unsel;
+ /* both must add up to 'defbase_tot' */
+ int defbase_tot_sel;
+ int defbase_tot_unsel;
- struct WeightPaintGroupData active, mirror;
+ struct WeightPaintGroupData active, mirror;
- /* boolean array for locked bones,
- * length of defbase_tot */
- const bool *lock_flags;
- /* boolean array for selected bones,
- * length of defbase_tot, cant be const because of how its passed */
- const bool *defbase_sel;
- /* same as WeightPaintData.vgroup_validmap,
- * only added here for convenience */
- const bool *vgroup_validmap;
+ /* boolean array for locked bones,
+ * length of defbase_tot */
+ const bool *lock_flags;
+ /* boolean array for selected bones,
+ * length of defbase_tot, cant be const because of how its passed */
+ const bool *defbase_sel;
+ /* same as WeightPaintData.vgroup_validmap,
+ * only added here for convenience */
+ const bool *vgroup_validmap;
- bool do_flip;
- bool do_multipaint;
- bool do_auto_normalize;
+ bool do_flip;
+ bool do_multipaint;
+ bool do_auto_normalize;
- float brush_alpha_value; /* result of BKE_brush_alpha_get() */
+ float brush_alpha_value; /* result of BKE_brush_alpha_get() */
} WeightPaintInfo;
static void do_weight_paint_vertex_single(
- /* vars which remain the same for every vert */
- const VPaint *wp, Object *ob, const WeightPaintInfo *wpi,
- /* vars which change on each stroke */
- const uint index, float alpha, float paintweight)
-{
- Mesh *me = ob->data;
- MDeformVert *dv = &me->dvert[index];
- bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
-
- MDeformWeight *dw;
- float weight_prev;
-
- /* mirror vars */
- int index_mirr;
- int vgroup_mirr;
-
- MDeformVert *dv_mirr;
- MDeformWeight *dw_mirr;
-
- /* 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) {
- index_mirr = mesh_get_x_mirror_vert(ob, NULL, index, topology);
- vgroup_mirr = wpi->mirror.index;
-
- /* another possible error - mirror group _and_ active group are the same (which is fine),
- * but we also are painting onto a center vertex - this would paint the same weight twice */
- if (index_mirr == index && vgroup_mirr == wpi->active.index) {
- index_mirr = vgroup_mirr = -1;
- }
- }
- else {
- index_mirr = vgroup_mirr = -1;
- }
-
- if (wp->flag & VP_FLAG_VGROUP_RESTRICT) {
- dw = defvert_find_index(dv, wpi->active.index);
- }
- else {
- dw = defvert_verify_index(dv, wpi->active.index);
- }
-
- if (dw == NULL) {
- return;
- }
-
- /* get the mirror def vars */
- 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);
-
- if (dw_mirr == NULL) {
- index_mirr = vgroup_mirr = -1;
- dv_mirr = NULL;
- }
- }
- else {
- if (index != index_mirr) {
- dw_mirr = defvert_verify_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);
-
- /* if we added another, get our old one back */
- if (totweight_prev != dv_mirr->totweight) {
- dw = &dv_mirr->dw[dw_offset];
- }
- }
- }
- }
- else {
- dv_mirr = NULL;
- dw_mirr = NULL;
- }
-
- 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);
- if (index_mirr != -1) {
- defweight_prev_init(dvert_prev, me->dvert, index_mirr);
- }
-
- weight_prev = defvert_find_weight(dv_prev, wpi->active.index);
- }
- else {
- weight_prev = dw->weight;
- }
-
- /* If there are no normalize-locks or multipaint,
- * then there is no need to run the more complicated checks */
-
- {
- 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);
-
- /* WATCH IT: take care of the ordering of applying mirror -> normalize,
- * can give wrong results [#26193], least confusing if normalize is done last */
-
- /* apply mirror */
- if (index_mirr != -1) {
- /* copy, not paint again */
- dw_mirr->weight = dw->weight;
- }
-
- /* apply normalize */
- if (wpi->do_auto_normalize) {
- /* note on normalize - this used to be applied after painting and normalize all weights,
- * in some ways this is good because there is feedback where the more weights involved would
- * 'resist' so you couldn't instantly zero out other weights by painting 1.0 on the active.
- *
- * However this gave a problem since applying mirror, then normalize both verts
- * the resulting weight wont match on both sides.
- *
- * If this 'resisting', slower normalize is nicer, we could call
- * do_weight_paint_normalize_all() and only use...
- * do_weight_paint_normalize_all_active() when normalizing the mirror vertex.
- * - campbell
- */
- do_weight_paint_normalize_all_locked_try_active(
- dv, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags, wpi->active.lock);
-
- if (index_mirr != -1) {
- /* only normalize if this is not a center vertex,
- * else we get a conflict, normalizing twice */
- if (index != index_mirr) {
- do_weight_paint_normalize_all_locked_try_active(
- dv_mirr, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags, wpi->mirror.lock);
- }
- else {
- /* this case accounts for...
- * - painting onto a center vertex of a mesh
- * - x mirror is enabled
- * - auto normalize is enabled
- * - the group you are painting onto has a L / R version
- *
- * We want L/R vgroups to have the same weight but this cant be if both are over 0.5,
- * We _could_ have special check for that, but this would need its own normalize function which
- * holds 2 groups from changing at once.
- *
- * So! just balance out the 2 weights, it keeps them equal and everything normalized.
- *
- * While it wont hit the desired weight immediately as the user waggles their mouse,
- * constant painting and re-normalizing will get there. this is also just simpler logic.
- * - campbell */
- dw_mirr->weight = dw->weight = (dw_mirr->weight + dw->weight) * 0.5f;
- }
- }
- }
- }
+ /* vars which remain the same for every vert */
+ const VPaint *wp,
+ Object *ob,
+ const WeightPaintInfo *wpi,
+ /* vars which change on each stroke */
+ const uint index,
+ float alpha,
+ float paintweight)
+{
+ Mesh *me = ob->data;
+ MDeformVert *dv = &me->dvert[index];
+ bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+
+ MDeformWeight *dw;
+ float weight_prev;
+
+ /* mirror vars */
+ int index_mirr;
+ int vgroup_mirr;
+
+ MDeformVert *dv_mirr;
+ MDeformWeight *dw_mirr;
+
+ /* 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) {
+ index_mirr = mesh_get_x_mirror_vert(ob, NULL, index, topology);
+ vgroup_mirr = wpi->mirror.index;
+
+ /* another possible error - mirror group _and_ active group are the same (which is fine),
+ * but we also are painting onto a center vertex - this would paint the same weight twice */
+ if (index_mirr == index && vgroup_mirr == wpi->active.index) {
+ index_mirr = vgroup_mirr = -1;
+ }
+ }
+ else {
+ index_mirr = vgroup_mirr = -1;
+ }
+
+ if (wp->flag & VP_FLAG_VGROUP_RESTRICT) {
+ dw = defvert_find_index(dv, wpi->active.index);
+ }
+ else {
+ dw = defvert_verify_index(dv, wpi->active.index);
+ }
+
+ if (dw == NULL) {
+ return;
+ }
+
+ /* get the mirror def vars */
+ 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);
+
+ if (dw_mirr == NULL) {
+ index_mirr = vgroup_mirr = -1;
+ dv_mirr = NULL;
+ }
+ }
+ else {
+ if (index != index_mirr) {
+ dw_mirr = defvert_verify_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);
+
+ /* if we added another, get our old one back */
+ if (totweight_prev != dv_mirr->totweight) {
+ dw = &dv_mirr->dw[dw_offset];
+ }
+ }
+ }
+ }
+ else {
+ dv_mirr = NULL;
+ dw_mirr = NULL;
+ }
+
+ 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);
+ if (index_mirr != -1) {
+ defweight_prev_init(dvert_prev, me->dvert, index_mirr);
+ }
+
+ weight_prev = defvert_find_weight(dv_prev, wpi->active.index);
+ }
+ else {
+ weight_prev = dw->weight;
+ }
+
+ /* If there are no normalize-locks or multipaint,
+ * then there is no need to run the more complicated checks */
+
+ {
+ 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);
+
+ /* WATCH IT: take care of the ordering of applying mirror -> normalize,
+ * can give wrong results [#26193], least confusing if normalize is done last */
+
+ /* apply mirror */
+ if (index_mirr != -1) {
+ /* copy, not paint again */
+ dw_mirr->weight = dw->weight;
+ }
+
+ /* apply normalize */
+ if (wpi->do_auto_normalize) {
+ /* note on normalize - this used to be applied after painting and normalize all weights,
+ * in some ways this is good because there is feedback where the more weights involved would
+ * 'resist' so you couldn't instantly zero out other weights by painting 1.0 on the active.
+ *
+ * However this gave a problem since applying mirror, then normalize both verts
+ * the resulting weight wont match on both sides.
+ *
+ * If this 'resisting', slower normalize is nicer, we could call
+ * do_weight_paint_normalize_all() and only use...
+ * do_weight_paint_normalize_all_active() when normalizing the mirror vertex.
+ * - campbell
+ */
+ do_weight_paint_normalize_all_locked_try_active(
+ dv, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags, wpi->active.lock);
+
+ if (index_mirr != -1) {
+ /* only normalize if this is not a center vertex,
+ * else we get a conflict, normalizing twice */
+ if (index != index_mirr) {
+ do_weight_paint_normalize_all_locked_try_active(
+ dv_mirr, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags, wpi->mirror.lock);
+ }
+ else {
+ /* this case accounts for...
+ * - painting onto a center vertex of a mesh
+ * - x mirror is enabled
+ * - auto normalize is enabled
+ * - the group you are painting onto has a L / R version
+ *
+ * We want L/R vgroups to have the same weight but this cant be if both are over 0.5,
+ * We _could_ have special check for that, but this would need its own normalize function which
+ * holds 2 groups from changing at once.
+ *
+ * So! just balance out the 2 weights, it keeps them equal and everything normalized.
+ *
+ * While it wont hit the desired weight immediately as the user waggles their mouse,
+ * constant painting and re-normalizing will get there. this is also just simpler logic.
+ * - campbell */
+ dw_mirr->weight = dw->weight = (dw_mirr->weight + dw->weight) * 0.5f;
+ }
+ }
+ }
+ }
}
static void do_weight_paint_vertex_multi(
- /* vars which remain the same for every vert */
- const VPaint *wp, Object *ob, const WeightPaintInfo *wpi,
- /* vars which change on each stroke */
- const uint index, float alpha, float paintweight)
-{
- Mesh *me = ob->data;
- MDeformVert *dv = &me->dvert[index];
- bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
-
- /* mirror vars */
- int index_mirr = -1;
- MDeformVert *dv_mirr = NULL;
-
- /* weights */
- float curw, oldw, neww, change, curw_mirr, change_mirr;
-
- /* 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) {
- index_mirr = mesh_get_x_mirror_vert(ob, NULL, index, topology);
-
- if (index_mirr != -1 && index_mirr != index) {
- dv_mirr = &me->dvert[index_mirr];
- }
- else {
- index_mirr = -1;
- }
- }
-
- /* 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);
-
- if (curw == 0.0f) {
- /* note: no weight to assign to this vertex, could add all groups? */
- return;
- }
-
- 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);
- if (index_mirr != -1) {
- defweight_prev_init(dvert_prev, me->dvert, index_mirr);
- }
-
- oldw = BKE_defvert_multipaint_collective_weight(
- dv_prev, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->do_auto_normalize);
- }
- else {
- oldw = curw;
- }
-
- neww = wpaint_blend(wp, oldw, alpha, paintweight, wpi->brush_alpha_value, wpi->do_flip);
- neww = wpaint_clamp_monotonic(oldw, curw, neww);
-
- change = neww / curw;
-
- /* 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);
-
- if (curw_mirr == 0.0f) {
- /* can't mirror into a zero weight vertex */
- dv_mirr = NULL;
- }
- else {
- /* mirror is changed to achieve the same collective weight value */
- float orig = change_mirr = curw * change / curw_mirr;
-
- multipaint_clamp_change(dv_mirr, wpi->defbase_tot, wpi->defbase_sel, &change_mirr);
-
- if (!multipaint_verify_change(dv_mirr, wpi->defbase_tot, change_mirr, wpi->defbase_sel)) {
- return;
- }
-
- change *= change_mirr / orig;
- }
- }
-
- if (!multipaint_verify_change(dv, wpi->defbase_tot, change, wpi->defbase_sel)) {
- return;
- }
-
- /* apply validated change to vertex and mirror */
- multipaint_apply_change(dv, wpi->defbase_tot, change, wpi->defbase_sel);
-
- if (dv_mirr != NULL) {
- multipaint_apply_change(dv_mirr, wpi->defbase_tot, change_mirr, wpi->defbase_sel);
- }
-
- /* normalize */
- if (wpi->do_auto_normalize) {
- do_weight_paint_normalize_all_locked_try_active(
- dv, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags, wpi->active.lock);
-
- if (dv_mirr != NULL) {
- do_weight_paint_normalize_all_locked_try_active(
- dv_mirr, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags, wpi->active.lock);
- }
- }
+ /* vars which remain the same for every vert */
+ const VPaint *wp,
+ Object *ob,
+ const WeightPaintInfo *wpi,
+ /* vars which change on each stroke */
+ const uint index,
+ float alpha,
+ float paintweight)
+{
+ Mesh *me = ob->data;
+ MDeformVert *dv = &me->dvert[index];
+ bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+
+ /* mirror vars */
+ int index_mirr = -1;
+ MDeformVert *dv_mirr = NULL;
+
+ /* weights */
+ float curw, oldw, neww, change, curw_mirr, change_mirr;
+
+ /* 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) {
+ index_mirr = mesh_get_x_mirror_vert(ob, NULL, index, topology);
+
+ if (index_mirr != -1 && index_mirr != index) {
+ dv_mirr = &me->dvert[index_mirr];
+ }
+ else {
+ index_mirr = -1;
+ }
+ }
+
+ /* 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);
+
+ if (curw == 0.0f) {
+ /* note: no weight to assign to this vertex, could add all groups? */
+ return;
+ }
+
+ 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);
+ if (index_mirr != -1) {
+ defweight_prev_init(dvert_prev, me->dvert, index_mirr);
+ }
+
+ oldw = BKE_defvert_multipaint_collective_weight(
+ dv_prev, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->do_auto_normalize);
+ }
+ else {
+ oldw = curw;
+ }
+
+ neww = wpaint_blend(wp, oldw, alpha, paintweight, wpi->brush_alpha_value, wpi->do_flip);
+ neww = wpaint_clamp_monotonic(oldw, curw, neww);
+
+ change = neww / curw;
+
+ /* 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);
+
+ if (curw_mirr == 0.0f) {
+ /* can't mirror into a zero weight vertex */
+ dv_mirr = NULL;
+ }
+ else {
+ /* mirror is changed to achieve the same collective weight value */
+ float orig = change_mirr = curw * change / curw_mirr;
+
+ multipaint_clamp_change(dv_mirr, wpi->defbase_tot, wpi->defbase_sel, &change_mirr);
+
+ if (!multipaint_verify_change(dv_mirr, wpi->defbase_tot, change_mirr, wpi->defbase_sel)) {
+ return;
+ }
+
+ change *= change_mirr / orig;
+ }
+ }
+
+ if (!multipaint_verify_change(dv, wpi->defbase_tot, change, wpi->defbase_sel)) {
+ return;
+ }
+
+ /* apply validated change to vertex and mirror */
+ multipaint_apply_change(dv, wpi->defbase_tot, change, wpi->defbase_sel);
+
+ if (dv_mirr != NULL) {
+ multipaint_apply_change(dv_mirr, wpi->defbase_tot, change_mirr, wpi->defbase_sel);
+ }
+
+ /* normalize */
+ if (wpi->do_auto_normalize) {
+ do_weight_paint_normalize_all_locked_try_active(
+ dv, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags, wpi->active.lock);
+
+ if (dv_mirr != NULL) {
+ do_weight_paint_normalize_all_locked_try_active(
+ dv_mirr, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags, wpi->active.lock);
+ }
+ }
}
static void do_weight_paint_vertex(
- /* vars which remain the same for every vert */
- const VPaint *wp, Object *ob, const WeightPaintInfo *wpi,
- /* vars which change on each stroke */
- const uint index, float alpha, float paintweight)
-{
- if (wpi->do_multipaint) {
- do_weight_paint_vertex_multi(wp, ob, wpi, index, alpha, paintweight);
- }
- else {
- do_weight_paint_vertex_single(wp, ob, wpi, index, alpha, paintweight);
- }
+ /* vars which remain the same for every vert */
+ const VPaint *wp,
+ Object *ob,
+ const WeightPaintInfo *wpi,
+ /* vars which change on each stroke */
+ const uint index,
+ float alpha,
+ float paintweight)
+{
+ if (wpi->do_multipaint) {
+ do_weight_paint_vertex_multi(wp, ob, wpi, index, alpha, paintweight);
+ }
+ else {
+ do_weight_paint_vertex_single(wp, ob, wpi, index, alpha, paintweight);
+ }
}
-
/* Toggle operator for turning vertex paint mode on or off (copied from sculpt.c) */
-static void vertex_paint_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob, eObjectMode object_mode)
+static void vertex_paint_init_session(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ eObjectMode object_mode)
{
- /* Create persistent sculpt mode data */
- BKE_sculpt_toolsettings_data_ensure(scene);
+ /* Create persistent sculpt mode data */
+ BKE_sculpt_toolsettings_data_ensure(scene);
- BLI_assert(ob->sculpt == NULL);
- ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
- ob->sculpt->mode_type = object_mode;
- BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false);
+ BLI_assert(ob->sculpt == NULL);
+ ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
+ ob->sculpt->mode_type = object_mode;
+ BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false);
}
static void vertex_paint_init_stroke(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false);
+ BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false);
}
static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob)
{
- /* Create maps */
- struct SculptVertexPaintGeomMap *gmap = NULL;
- if (ob->mode == OB_MODE_VERTEX_PAINT) {
- gmap = &ob->sculpt->mode.vpaint.gmap;
- BLI_assert(ob->sculpt->mode_type == OB_MODE_VERTEX_PAINT);
- }
- else if (ob->mode == OB_MODE_WEIGHT_PAINT) {
- gmap = &ob->sculpt->mode.wpaint.gmap;
- BLI_assert(ob->sculpt->mode_type == OB_MODE_WEIGHT_PAINT);
- }
- else {
- ob->sculpt->mode_type = 0;
- BLI_assert(0);
- return;
- }
-
- Mesh *me = ob->data;
-
- if (gmap->vert_to_loop == NULL) {
- gmap->vert_map_mem = NULL;
- gmap->vert_to_loop = NULL;
- gmap->poly_map_mem = NULL;
- gmap->vert_to_poly = NULL;
- BKE_mesh_vert_loop_map_create(
- &gmap->vert_to_loop,
- &gmap->vert_map_mem,
- me->mpoly, me->mloop, me->totvert, me->totpoly, me->totloop);
- BKE_mesh_vert_poly_map_create(
- &gmap->vert_to_poly,
- &gmap->poly_map_mem,
- me->mpoly, me->mloop, me->totvert, me->totpoly, me->totloop);
- }
-
- /* Create average brush arrays */
- if (ob->mode == OB_MODE_VERTEX_PAINT) {
- if (!brush_use_accumulate(ts->vpaint)) {
- if (ob->sculpt->mode.vpaint.previous_color == NULL) {
- ob->sculpt->mode.vpaint.previous_color =
- MEM_callocN(me->totloop * sizeof(uint), __func__);
- }
- }
- else {
- MEM_SAFE_FREE(ob->sculpt->mode.vpaint.previous_color);
- }
- }
- else if (ob->mode == OB_MODE_WEIGHT_PAINT) {
- if (!brush_use_accumulate(ts->wpaint)) {
- if (ob->sculpt->mode.wpaint.alpha_weight == NULL) {
- ob->sculpt->mode.wpaint.alpha_weight =
- MEM_callocN(me->totvert * sizeof(float), __func__);
- }
- if (ob->sculpt->mode.wpaint.dvert_prev == NULL) {
- ob->sculpt->mode.wpaint.dvert_prev =
- MEM_callocN(me->totvert * sizeof(MDeformVert), __func__);
- MDeformVert *dv = ob->sculpt->mode.wpaint.dvert_prev;
- for (int i = 0; i < me->totvert; i++, dv++) {
- /* Use to show this isn't initialized, never apply to the mesh data. */
- dv->flag = 1;
- }
- }
- }
- else {
- MEM_SAFE_FREE(ob->sculpt->mode.wpaint.alpha_weight);
- if (ob->sculpt->mode.wpaint.dvert_prev != NULL) {
- BKE_defvert_array_free_elems(ob->sculpt->mode.wpaint.dvert_prev, me->totvert);
- MEM_freeN(ob->sculpt->mode.wpaint.dvert_prev);
- ob->sculpt->mode.wpaint.dvert_prev = NULL;
- }
- }
- }
-
+ /* Create maps */
+ struct SculptVertexPaintGeomMap *gmap = NULL;
+ if (ob->mode == OB_MODE_VERTEX_PAINT) {
+ gmap = &ob->sculpt->mode.vpaint.gmap;
+ BLI_assert(ob->sculpt->mode_type == OB_MODE_VERTEX_PAINT);
+ }
+ else if (ob->mode == OB_MODE_WEIGHT_PAINT) {
+ gmap = &ob->sculpt->mode.wpaint.gmap;
+ BLI_assert(ob->sculpt->mode_type == OB_MODE_WEIGHT_PAINT);
+ }
+ else {
+ ob->sculpt->mode_type = 0;
+ BLI_assert(0);
+ return;
+ }
+
+ Mesh *me = ob->data;
+
+ if (gmap->vert_to_loop == NULL) {
+ gmap->vert_map_mem = NULL;
+ gmap->vert_to_loop = NULL;
+ gmap->poly_map_mem = NULL;
+ gmap->vert_to_poly = NULL;
+ BKE_mesh_vert_loop_map_create(&gmap->vert_to_loop,
+ &gmap->vert_map_mem,
+ me->mpoly,
+ me->mloop,
+ me->totvert,
+ me->totpoly,
+ me->totloop);
+ BKE_mesh_vert_poly_map_create(&gmap->vert_to_poly,
+ &gmap->poly_map_mem,
+ me->mpoly,
+ me->mloop,
+ me->totvert,
+ me->totpoly,
+ me->totloop);
+ }
+
+ /* Create average brush arrays */
+ if (ob->mode == OB_MODE_VERTEX_PAINT) {
+ if (!brush_use_accumulate(ts->vpaint)) {
+ if (ob->sculpt->mode.vpaint.previous_color == NULL) {
+ ob->sculpt->mode.vpaint.previous_color = MEM_callocN(me->totloop * sizeof(uint), __func__);
+ }
+ }
+ else {
+ MEM_SAFE_FREE(ob->sculpt->mode.vpaint.previous_color);
+ }
+ }
+ else if (ob->mode == OB_MODE_WEIGHT_PAINT) {
+ if (!brush_use_accumulate(ts->wpaint)) {
+ if (ob->sculpt->mode.wpaint.alpha_weight == NULL) {
+ ob->sculpt->mode.wpaint.alpha_weight = MEM_callocN(me->totvert * sizeof(float), __func__);
+ }
+ if (ob->sculpt->mode.wpaint.dvert_prev == NULL) {
+ ob->sculpt->mode.wpaint.dvert_prev = MEM_callocN(me->totvert * sizeof(MDeformVert),
+ __func__);
+ MDeformVert *dv = ob->sculpt->mode.wpaint.dvert_prev;
+ for (int i = 0; i < me->totvert; i++, dv++) {
+ /* Use to show this isn't initialized, never apply to the mesh data. */
+ dv->flag = 1;
+ }
+ }
+ }
+ else {
+ MEM_SAFE_FREE(ob->sculpt->mode.wpaint.alpha_weight);
+ if (ob->sculpt->mode.wpaint.dvert_prev != NULL) {
+ BKE_defvert_array_free_elems(ob->sculpt->mode.wpaint.dvert_prev, me->totvert);
+ MEM_freeN(ob->sculpt->mode.wpaint.dvert_prev);
+ ob->sculpt->mode.wpaint.dvert_prev = NULL;
+ }
+ }
+ }
}
/* -------------------------------------------------------------------- */
/** \name Enter Vertex/Weight Paint Mode
* \{ */
-static void ed_vwpaintmode_enter_generic(
- Main *bmain, Depsgraph *depsgraph,
- wmWindowManager *wm, Scene *scene,
- Object *ob, const eObjectMode mode_flag)
-{
- ob->mode |= mode_flag;
- Mesh *me = BKE_mesh_from_object(ob);
-
- /* Same as sculpt mode, make sure we don't have cached derived mesh which
- * points to freed arrays.
- */
- BKE_object_free_derived_caches(ob);
-
- if (mode_flag == OB_MODE_VERTEX_PAINT) {
- const ePaintMode paint_mode = PAINT_MODE_VERTEX;
- ED_mesh_color_ensure(me, NULL);
-
- BKE_paint_ensure(scene->toolsettings, (Paint **)&scene->toolsettings->vpaint);
- Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
- paint_cursor_start_explicit(paint, wm, vertex_paint_poll);
- BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_VERTEX_PAINT);
- }
- else if (mode_flag == OB_MODE_WEIGHT_PAINT) {
- const ePaintMode paint_mode = PAINT_MODE_WEIGHT;
-
- BKE_paint_ensure(scene->toolsettings, (Paint **)&scene->toolsettings->wpaint);
- Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
- paint_cursor_start_explicit(paint, wm, weight_paint_poll);
- 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_vgroup_sync_from_pose(ob);
- }
- else {
- BLI_assert(0);
- }
-
- /* Create vertex/weight paint mode session data */
- if (ob->sculpt) {
- if (ob->sculpt->cache) {
- sculpt_cache_free(ob->sculpt->cache);
- ob->sculpt->cache = NULL;
- }
- BKE_sculptsession_free(ob);
- }
-
- vertex_paint_init_session(depsgraph, scene, ob, mode_flag);
-
- /* Flush object mode. */
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+static void ed_vwpaintmode_enter_generic(Main *bmain,
+ Depsgraph *depsgraph,
+ wmWindowManager *wm,
+ Scene *scene,
+ Object *ob,
+ const eObjectMode mode_flag)
+{
+ ob->mode |= mode_flag;
+ Mesh *me = BKE_mesh_from_object(ob);
+
+ /* Same as sculpt mode, make sure we don't have cached derived mesh which
+ * points to freed arrays.
+ */
+ BKE_object_free_derived_caches(ob);
+
+ if (mode_flag == OB_MODE_VERTEX_PAINT) {
+ const ePaintMode paint_mode = PAINT_MODE_VERTEX;
+ ED_mesh_color_ensure(me, NULL);
+
+ BKE_paint_ensure(scene->toolsettings, (Paint **)&scene->toolsettings->vpaint);
+ Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
+ paint_cursor_start_explicit(paint, wm, vertex_paint_poll);
+ BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_VERTEX_PAINT);
+ }
+ else if (mode_flag == OB_MODE_WEIGHT_PAINT) {
+ const ePaintMode paint_mode = PAINT_MODE_WEIGHT;
+
+ BKE_paint_ensure(scene->toolsettings, (Paint **)&scene->toolsettings->wpaint);
+ Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
+ paint_cursor_start_explicit(paint, wm, weight_paint_poll);
+ 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_vgroup_sync_from_pose(ob);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ /* Create vertex/weight paint mode session data */
+ if (ob->sculpt) {
+ if (ob->sculpt->cache) {
+ sculpt_cache_free(ob->sculpt->cache);
+ ob->sculpt->cache = NULL;
+ }
+ BKE_sculptsession_free(ob);
+ }
+
+ vertex_paint_init_session(depsgraph, scene, ob, mode_flag);
+
+ /* Flush object mode. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
}
void ED_object_vpaintmode_enter_ex(
- Main *bmain, Depsgraph *depsgraph, wmWindowManager *wm,
- Scene *scene, Object *ob)
+ Main *bmain, Depsgraph *depsgraph, wmWindowManager *wm, Scene *scene, Object *ob)
{
- ed_vwpaintmode_enter_generic(
- bmain, depsgraph, wm, scene, ob, OB_MODE_VERTEX_PAINT);
+ ed_vwpaintmode_enter_generic(bmain, depsgraph, wm, scene, ob, OB_MODE_VERTEX_PAINT);
}
void ED_object_vpaintmode_enter(struct bContext *C)
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- wmWindowManager *wm = CTX_wm_manager(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
}
void ED_object_wpaintmode_enter_ex(
- Main *bmain, Depsgraph *depsgraph, wmWindowManager *wm,
- Scene *scene, Object *ob)
+ Main *bmain, Depsgraph *depsgraph, wmWindowManager *wm, Scene *scene, Object *ob)
{
- ed_vwpaintmode_enter_generic(
- bmain, depsgraph, wm, scene, ob, OB_MODE_WEIGHT_PAINT);
+ ed_vwpaintmode_enter_generic(bmain, depsgraph, wm, scene, ob, OB_MODE_WEIGHT_PAINT);
}
void ED_object_wpaintmode_enter(struct bContext *C)
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- wmWindowManager *wm = CTX_wm_manager(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
}
/** \} */
@@ -1153,72 +1185,71 @@ void ED_object_wpaintmode_enter(struct bContext *C)
/** \name Exit Vertex/Weight Paint Mode
* \{ */
-static void ed_vwpaintmode_exit_generic(
- Object *ob, const eObjectMode mode_flag)
-{
- Mesh *me = BKE_mesh_from_object(ob);
- ob->mode &= ~mode_flag;
-
- if (mode_flag == OB_MODE_VERTEX_PAINT) {
- if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
- BKE_mesh_flush_select_from_polys(me);
- }
- else if (me->editflag & ME_EDIT_PAINT_VERT_SEL) {
- BKE_mesh_flush_select_from_verts(me);
- }
- }
- else if (mode_flag == OB_MODE_WEIGHT_PAINT) {
- if (me->editflag & ME_EDIT_PAINT_VERT_SEL) {
- BKE_mesh_flush_select_from_verts(me);
- }
- else if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
- BKE_mesh_flush_select_from_polys(me);
- }
- }
- else {
- BLI_assert(0);
- }
-
- /* 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);
- ob->sculpt->cache = NULL;
- }
-
- BKE_sculptsession_free(ob);
-
- 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');
- }
-
- /* Never leave derived meshes behind. */
- BKE_object_free_derived_caches(ob);
-
- /* Flush object mode. */
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+static void ed_vwpaintmode_exit_generic(Object *ob, const eObjectMode mode_flag)
+{
+ Mesh *me = BKE_mesh_from_object(ob);
+ ob->mode &= ~mode_flag;
+
+ if (mode_flag == OB_MODE_VERTEX_PAINT) {
+ if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
+ BKE_mesh_flush_select_from_polys(me);
+ }
+ else if (me->editflag & ME_EDIT_PAINT_VERT_SEL) {
+ BKE_mesh_flush_select_from_verts(me);
+ }
+ }
+ else if (mode_flag == OB_MODE_WEIGHT_PAINT) {
+ if (me->editflag & ME_EDIT_PAINT_VERT_SEL) {
+ BKE_mesh_flush_select_from_verts(me);
+ }
+ else if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
+ BKE_mesh_flush_select_from_polys(me);
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ /* 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);
+ ob->sculpt->cache = NULL;
+ }
+
+ BKE_sculptsession_free(ob);
+
+ 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');
+ }
+
+ /* Never leave derived meshes behind. */
+ BKE_object_free_derived_caches(ob);
+
+ /* Flush object mode. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
}
void ED_object_vpaintmode_exit_ex(Object *ob)
{
- ed_vwpaintmode_exit_generic(ob, OB_MODE_VERTEX_PAINT);
+ ed_vwpaintmode_exit_generic(ob, OB_MODE_VERTEX_PAINT);
}
void ED_object_vpaintmode_exit(struct bContext *C)
{
- Object *ob = CTX_data_active_object(C);
- ED_object_vpaintmode_exit_ex(ob);
+ Object *ob = CTX_data_active_object(C);
+ ED_object_vpaintmode_exit_ex(ob);
}
void ED_object_wpaintmode_exit_ex(Object *ob)
{
- ed_vwpaintmode_exit_generic(ob, OB_MODE_WEIGHT_PAINT);
+ ed_vwpaintmode_exit_generic(ob, OB_MODE_WEIGHT_PAINT);
}
void ED_object_wpaintmode_exit(struct bContext *C)
{
- Object *ob = CTX_data_active_object(C);
- ED_object_wpaintmode_exit_ex(ob);
+ Object *ob = CTX_data_active_object(C);
+ ED_object_wpaintmode_exit_ex(ob);
}
/** \} */
@@ -1230,1159 +1261,1182 @@ void ED_object_wpaintmode_exit(struct bContext *C)
*/
static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- Object *ob = CTX_data_active_object(C);
- const int mode_flag = OB_MODE_WEIGHT_PAINT;
- const bool is_mode_set = (ob->mode & mode_flag) != 0;
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = scene->toolsettings;
-
- if (!is_mode_set) {
- if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
- return OPERATOR_CANCELLED;
- }
- }
-
- Mesh *me = BKE_mesh_from_object(ob);
-
- if (is_mode_set) {
- ED_object_wpaintmode_exit_ex(ob);
- }
- else {
- Depsgraph *depsgraph = CTX_data_depsgraph_on_load(C);
- wmWindowManager *wm = CTX_wm_manager(C);
- ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
- BKE_paint_toolslots_brush_validate(bmain, &ts->wpaint->paint);
- }
-
- /* When locked, it's almost impossible to select the pose then the object to enter weight paint mode.
- * In this case move our pose object in/out of pose mode.
- * This is in fits with the convention of selecting multiple objects and entering a mode. */
- if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
- Object *ob_arm = modifiers_isDeformedByArmature(ob);
- if (ob_arm && (ob_arm->base_flag & BASE_SELECTED)) {
- if (ob_arm->mode & OB_MODE_POSE) {
- ED_object_posemode_exit_ex(bmain, ob_arm);
- }
- else {
- ED_object_posemode_enter_ex(bmain, ob_arm);
- }
- }
- }
-
- /* Weightpaint works by overriding colors in mesh,
- * so need to make sure we recalc on enter and
- * exit (exit needs doing regardless because we
- * should redeform).
- */
- DEG_id_tag_update(&me->id, 0);
-
- WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
-
- WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
-
- WM_toolsystem_update_from_context_view3d(C);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ Object *ob = CTX_data_active_object(C);
+ const int mode_flag = OB_MODE_WEIGHT_PAINT;
+ const bool is_mode_set = (ob->mode & mode_flag) != 0;
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
+
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ Mesh *me = BKE_mesh_from_object(ob);
+
+ if (is_mode_set) {
+ ED_object_wpaintmode_exit_ex(ob);
+ }
+ else {
+ Depsgraph *depsgraph = CTX_data_depsgraph_on_load(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
+ BKE_paint_toolslots_brush_validate(bmain, &ts->wpaint->paint);
+ }
+
+ /* When locked, it's almost impossible to select the pose then the object to enter weight paint mode.
+ * In this case move our pose object in/out of pose mode.
+ * This is in fits with the convention of selecting multiple objects and entering a mode. */
+ if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ Object *ob_arm = modifiers_isDeformedByArmature(ob);
+ if (ob_arm && (ob_arm->base_flag & BASE_SELECTED)) {
+ if (ob_arm->mode & OB_MODE_POSE) {
+ ED_object_posemode_exit_ex(bmain, ob_arm);
+ }
+ else {
+ ED_object_posemode_enter_ex(bmain, ob_arm);
+ }
+ }
+ }
+
+ /* Weightpaint works by overriding colors in mesh,
+ * so need to make sure we recalc on enter and
+ * exit (exit needs doing regardless because we
+ * should redeform).
+ */
+ DEG_id_tag_update(&me->id, 0);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
+
+ WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
+
+ WM_toolsystem_update_from_context_view3d(C);
+
+ return OPERATOR_FINISHED;
}
/* for switching to/from mode */
static bool paint_poll_test(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
- if (ob == NULL || ob->type != OB_MESH)
- return 0;
- if (!ob->data || ID_IS_LINKED(ob->data))
- return 0;
- if (CTX_data_edit_object(C))
- return 0;
- return 1;
+ Object *ob = CTX_data_active_object(C);
+ if (ob == NULL || ob->type != OB_MESH)
+ return 0;
+ if (!ob->data || ID_IS_LINKED(ob->data))
+ return 0;
+ if (CTX_data_edit_object(C))
+ return 0;
+ return 1;
}
void PAINT_OT_weight_paint_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Weight Paint Mode";
- ot->idname = "PAINT_OT_weight_paint_toggle";
- ot->description = "Toggle weight paint mode in 3D view";
+ /* identifiers */
+ ot->name = "Weight Paint Mode";
+ ot->idname = "PAINT_OT_weight_paint_toggle";
+ ot->description = "Toggle weight paint mode in 3D view";
- /* api callbacks */
- ot->exec = wpaint_mode_toggle_exec;
- ot->poll = paint_poll_test;
+ /* api callbacks */
+ ot->exec = wpaint_mode_toggle_exec;
+ ot->poll = paint_poll_test;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
}
/* ************ weight paint operator ********** */
struct WPaintData {
- ViewContext vc;
- struct NormalAnglePrecalc normal_angle_precalc;
+ ViewContext vc;
+ struct NormalAnglePrecalc normal_angle_precalc;
- struct WeightPaintGroupData active, mirror;
+ struct WeightPaintGroupData active, mirror;
- /* variables for auto normalize */
- const bool *vgroup_validmap; /* stores if vgroups tie to deforming bones or not */
- const bool *lock_flags;
+ /* variables for auto normalize */
+ const bool *vgroup_validmap; /* stores if vgroups tie to deforming bones or not */
+ const bool *lock_flags;
- /* 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 */
+ /* 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 */
- int defbase_tot;
+ int defbase_tot;
- /* original weight values for use in blur/smear */
- float *precomputed_weight;
- bool precomputed_weight_ready;
+ /* original weight values for use in blur/smear */
+ float *precomputed_weight;
+ bool precomputed_weight_ready;
};
/* Initialize the stroke cache invariants from operator properties */
static void vwpaint_update_cache_invariants(
- bContext *C, const VPaint *vp, SculptSession *ss, wmOperator *op, const float mouse[2])
-{
- StrokeCache *cache;
- Scene *scene = CTX_data_scene(C);
- UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
- const Brush *brush = vp->paint.brush;
- ViewContext *vc = paint_stroke_view_context(op->customdata);
- Object *ob = CTX_data_active_object(C);
- float mat[3][3];
- float view_dir[3] = {0.0f, 0.0f, 1.0f};
- int mode;
-
- /* VW paint needs to allocate stroke cache before update is called. */
- if (!ss->cache) {
- cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
- ss->cache = cache;
- }
- else {
- cache = ss->cache;
- }
-
- /* Initial mouse location */
- if (mouse)
- copy_v2_v2(cache->initial_mouse, mouse);
- else
- zero_v2(cache->initial_mouse);
-
- mode = RNA_enum_get(op->ptr, "mode");
- cache->invert = mode == BRUSH_STROKE_INVERT;
- cache->alt_smooth = mode == BRUSH_STROKE_SMOOTH;
- /* 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;
- else ups->draw_inverted = false;
-
- copy_v2_v2(cache->mouse, cache->initial_mouse);
- /* Truly temporary data that isn't stored in properties */
- cache->vc = vc;
- cache->brush = brush;
- cache->first_time = 1;
-
- /* cache projection matrix */
- ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat);
-
- invert_m4_m4(ob->imat, ob->obmat);
- copy_m3_m4(mat, cache->vc->rv3d->viewinv);
- mul_m3_v3(mat, view_dir);
- copy_m3_m4(mat, ob->imat);
- mul_m3_v3(mat, view_dir);
- normalize_v3_v3(cache->true_view_normal, view_dir);
-
- copy_v3_v3(cache->view_normal, cache->true_view_normal);
- cache->bstrength = BKE_brush_alpha_get(scene, brush);
- cache->is_last_valid = false;
+ bContext *C, const VPaint *vp, SculptSession *ss, wmOperator *op, const float mouse[2])
+{
+ StrokeCache *cache;
+ Scene *scene = CTX_data_scene(C);
+ UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
+ const Brush *brush = vp->paint.brush;
+ ViewContext *vc = paint_stroke_view_context(op->customdata);
+ Object *ob = CTX_data_active_object(C);
+ float mat[3][3];
+ float view_dir[3] = {0.0f, 0.0f, 1.0f};
+ int mode;
+
+ /* VW paint needs to allocate stroke cache before update is called. */
+ if (!ss->cache) {
+ cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
+ ss->cache = cache;
+ }
+ else {
+ cache = ss->cache;
+ }
+
+ /* Initial mouse location */
+ if (mouse)
+ copy_v2_v2(cache->initial_mouse, mouse);
+ else
+ zero_v2(cache->initial_mouse);
+
+ mode = RNA_enum_get(op->ptr, "mode");
+ cache->invert = mode == BRUSH_STROKE_INVERT;
+ cache->alt_smooth = mode == BRUSH_STROKE_SMOOTH;
+ /* 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;
+ else
+ ups->draw_inverted = false;
+
+ copy_v2_v2(cache->mouse, cache->initial_mouse);
+ /* Truly temporary data that isn't stored in properties */
+ cache->vc = vc;
+ cache->brush = brush;
+ cache->first_time = 1;
+
+ /* cache projection matrix */
+ ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat);
+
+ invert_m4_m4(ob->imat, ob->obmat);
+ copy_m3_m4(mat, cache->vc->rv3d->viewinv);
+ mul_m3_v3(mat, view_dir);
+ copy_m3_m4(mat, ob->imat);
+ mul_m3_v3(mat, view_dir);
+ normalize_v3_v3(cache->true_view_normal, view_dir);
+
+ copy_v3_v3(cache->view_normal, cache->true_view_normal);
+ cache->bstrength = BKE_brush_alpha_get(scene, brush);
+ cache->is_last_valid = false;
}
/* Initialize the stroke cache variants from operator properties */
static void vwpaint_update_cache_variants(bContext *C, VPaint *vp, Object *ob, PointerRNA *ptr)
{
- Scene *scene = CTX_data_scene(C);
- SculptSession *ss = ob->sculpt;
- StrokeCache *cache = ss->cache;
- Brush *brush = BKE_paint_brush(&vp->paint);
-
- /* This effects the actual brush radius, so things farther away
- * are compared with a larger radius and vice versa. */
- if (cache->first_time) {
- RNA_float_get_array(ptr, "location", cache->true_location);
- }
-
- 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 */
- 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 */
- if (cache->first_time) {
- if (!BKE_brush_use_locked_size(scene, brush)) {
- cache->initial_radius = paint_calc_object_space_radius(
- cache->vc, cache->true_location, BKE_brush_size_get(scene, brush));
- BKE_brush_unprojected_radius_set(scene, brush, cache->initial_radius);
- }
- else {
- cache->initial_radius = BKE_brush_unprojected_radius_get(scene, brush);
- }
- }
-
- if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, PAINT_MODE_SCULPT)) {
- cache->radius = cache->initial_radius * cache->pressure;
- }
- else {
- cache->radius = cache->initial_radius;
- }
-
- cache->radius_squared = cache->radius * cache->radius;
-
- if (ss->pbvh) {
- BKE_pbvh_update(ss->pbvh, PBVH_UpdateRedraw, NULL);
- BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB, NULL);
- }
+ Scene *scene = CTX_data_scene(C);
+ SculptSession *ss = ob->sculpt;
+ StrokeCache *cache = ss->cache;
+ Brush *brush = BKE_paint_brush(&vp->paint);
+
+ /* This effects the actual brush radius, so things farther away
+ * are compared with a larger radius and vice versa. */
+ if (cache->first_time) {
+ RNA_float_get_array(ptr, "location", cache->true_location);
+ }
+
+ 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 */
+ 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 */
+ if (cache->first_time) {
+ if (!BKE_brush_use_locked_size(scene, brush)) {
+ cache->initial_radius = paint_calc_object_space_radius(
+ cache->vc, cache->true_location, BKE_brush_size_get(scene, brush));
+ BKE_brush_unprojected_radius_set(scene, brush, cache->initial_radius);
+ }
+ else {
+ cache->initial_radius = BKE_brush_unprojected_radius_get(scene, brush);
+ }
+ }
+
+ if (BKE_brush_use_size_pressure(scene, brush) &&
+ paint_supports_dynamic_size(brush, PAINT_MODE_SCULPT)) {
+ cache->radius = cache->initial_radius * cache->pressure;
+ }
+ else {
+ cache->radius = cache->initial_radius;
+ }
+
+ cache->radius_squared = cache->radius * cache->radius;
+
+ if (ss->pbvh) {
+ BKE_pbvh_update(ss->pbvh, PBVH_UpdateRedraw, NULL);
+ BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB, NULL);
+ }
}
static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mouse[2])
{
- Scene *scene = CTX_data_scene(C);
- struct PaintStroke *stroke = op->customdata;
- ToolSettings *ts = scene->toolsettings;
- Object *ob = CTX_data_active_object(C);
- Mesh *me = BKE_mesh_from_object(ob);
- struct WPaintData *wpd;
- struct WPaintVGroupIndex vgroup_index;
- int defbase_tot, defbase_tot_sel;
- bool *defbase_sel;
- SculptSession *ss = ob->sculpt;
- VPaint *vp = CTX_data_tool_settings(C)->wpaint;
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
-
- if (ED_wpaint_ensure_data(C, op->reports, WPAINT_ENSURE_MIRROR, &vgroup_index) == false) {
- return false;
- }
-
- {
- /* check if we are attempting to paint onto a locked vertex group,
- * and other options disallow it from doing anything useful */
- bDeformGroup *dg;
- dg = BLI_findlink(&ob->defbase, vgroup_index.active);
- if (dg->flag & DG_LOCK_WEIGHT) {
- BKE_report(op->reports, RPT_WARNING, "Active group is locked, aborting");
- return false;
- }
- if (vgroup_index.mirror != -1) {
- dg = BLI_findlink(&ob->defbase, vgroup_index.mirror);
- if (dg->flag & DG_LOCK_WEIGHT) {
- BKE_report(op->reports, RPT_WARNING, "Mirror group is locked, aborting");
- return false;
- }
- }
- }
-
- /* check that multipaint groups are unlocked */
- defbase_tot = BLI_listbase_count(&ob->defbase);
- defbase_sel = BKE_object_defgroup_selected_get(ob, defbase_tot, &defbase_tot_sel);
-
- if (ts->multipaint && defbase_tot_sel > 1) {
- int i;
- bDeformGroup *dg;
-
- if (me->editflag & ME_EDIT_MIRROR_X) {
- BKE_object_defgroup_mirror_selection(ob, defbase_tot, defbase_sel, defbase_sel, &defbase_tot_sel);
- }
-
- for (i = 0; i < defbase_tot; i++) {
- if (defbase_sel[i]) {
- dg = BLI_findlink(&ob->defbase, i);
- if (dg->flag & DG_LOCK_WEIGHT) {
- BKE_report(op->reports, RPT_WARNING, "Multipaint group is locked, aborting");
- MEM_freeN(defbase_sel);
- return false;
- }
- }
- }
- }
-
- /* ALLOCATIONS! no return after this line */
- /* make mode data storage */
- wpd = MEM_callocN(sizeof(struct WPaintData), "WPaintData");
- paint_stroke_set_mode_data(stroke, wpd);
- ED_view3d_viewcontext_init(C, &wpd->vc);
- view_angle_limits_init(
- &wpd->normal_angle_precalc, vp->paint.brush->falloff_angle,
- (vp->paint.brush->flag & BRUSH_FRONTFACE_FALLOFF) != 0);
-
- wpd->active.index = vgroup_index.active;
- wpd->mirror.index = vgroup_index.mirror;
-
- /* multipaint */
- wpd->defbase_tot = defbase_tot;
- wpd->defbase_sel = defbase_sel;
- wpd->defbase_tot_sel = defbase_tot_sel > 1 ? defbase_tot_sel : 1;
- wpd->do_multipaint = (ts->multipaint && defbase_tot_sel > 1);
-
- /* 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) {
- wpd->vgroup_validmap = BKE_object_defgroup_validmap_get(ob, wpd->defbase_tot);
- }
-
- if (wpd->do_multipaint && ts->auto_normalize) {
- bool *tmpflags;
- tmpflags = MEM_mallocN(sizeof(bool) * defbase_tot, __func__);
- if (wpd->lock_flags) {
- BLI_array_binary_or(tmpflags, wpd->defbase_sel, wpd->lock_flags, wpd->defbase_tot);
- }
- else {
- memcpy(tmpflags, wpd->defbase_sel, sizeof(*tmpflags) * wpd->defbase_tot);
- }
- wpd->active.lock = tmpflags;
- }
- else if (ts->auto_normalize) {
- bool *tmpflags;
-
- tmpflags = wpd->lock_flags ?
- MEM_dupallocN(wpd->lock_flags) :
- MEM_callocN(sizeof(bool) * defbase_tot, __func__);
- tmpflags[wpd->active.index] = true;
- wpd->active.lock = tmpflags;
-
- tmpflags = wpd->lock_flags ?
- MEM_dupallocN(wpd->lock_flags) :
- MEM_callocN(sizeof(bool) * defbase_tot, __func__);
- tmpflags[(wpd->mirror.index != -1) ? wpd->mirror.index : wpd->active.index] = true;
- wpd->mirror.lock = tmpflags;
- }
-
- if (ELEM(vp->paint.brush->weightpaint_tool, WPAINT_TOOL_SMEAR, WPAINT_TOOL_BLUR)) {
- wpd->precomputed_weight = MEM_mallocN(sizeof(float) * me->totvert, __func__);
- }
-
- /* If not previously created, create vertex/weight paint mode session data */
- vertex_paint_init_stroke(depsgraph, scene, ob);
- vwpaint_update_cache_invariants(C, vp, ss, op, mouse);
- vertex_paint_init_session_data(ts, ob);
-
- if (ob->sculpt->mode.wpaint.dvert_prev != NULL) {
- MDeformVert *dv = ob->sculpt->mode.wpaint.dvert_prev;
- for (int i = 0; i < me->totvert; i++, dv++) {
- /* Use to show this isn't initialized, never apply to the mesh data. */
- dv->flag = 1;
- }
- }
-
- return true;
+ Scene *scene = CTX_data_scene(C);
+ struct PaintStroke *stroke = op->customdata;
+ ToolSettings *ts = scene->toolsettings;
+ Object *ob = CTX_data_active_object(C);
+ Mesh *me = BKE_mesh_from_object(ob);
+ struct WPaintData *wpd;
+ struct WPaintVGroupIndex vgroup_index;
+ int defbase_tot, defbase_tot_sel;
+ bool *defbase_sel;
+ SculptSession *ss = ob->sculpt;
+ VPaint *vp = CTX_data_tool_settings(C)->wpaint;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
+ if (ED_wpaint_ensure_data(C, op->reports, WPAINT_ENSURE_MIRROR, &vgroup_index) == false) {
+ return false;
+ }
+
+ {
+ /* check if we are attempting to paint onto a locked vertex group,
+ * and other options disallow it from doing anything useful */
+ bDeformGroup *dg;
+ dg = BLI_findlink(&ob->defbase, vgroup_index.active);
+ if (dg->flag & DG_LOCK_WEIGHT) {
+ BKE_report(op->reports, RPT_WARNING, "Active group is locked, aborting");
+ return false;
+ }
+ if (vgroup_index.mirror != -1) {
+ dg = BLI_findlink(&ob->defbase, vgroup_index.mirror);
+ if (dg->flag & DG_LOCK_WEIGHT) {
+ BKE_report(op->reports, RPT_WARNING, "Mirror group is locked, aborting");
+ return false;
+ }
+ }
+ }
+
+ /* check that multipaint groups are unlocked */
+ defbase_tot = BLI_listbase_count(&ob->defbase);
+ defbase_sel = BKE_object_defgroup_selected_get(ob, defbase_tot, &defbase_tot_sel);
+
+ if (ts->multipaint && defbase_tot_sel > 1) {
+ int i;
+ bDeformGroup *dg;
+
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ BKE_object_defgroup_mirror_selection(
+ ob, defbase_tot, defbase_sel, defbase_sel, &defbase_tot_sel);
+ }
+
+ for (i = 0; i < defbase_tot; i++) {
+ if (defbase_sel[i]) {
+ dg = BLI_findlink(&ob->defbase, i);
+ if (dg->flag & DG_LOCK_WEIGHT) {
+ BKE_report(op->reports, RPT_WARNING, "Multipaint group is locked, aborting");
+ MEM_freeN(defbase_sel);
+ return false;
+ }
+ }
+ }
+ }
+
+ /* ALLOCATIONS! no return after this line */
+ /* make mode data storage */
+ wpd = MEM_callocN(sizeof(struct WPaintData), "WPaintData");
+ paint_stroke_set_mode_data(stroke, wpd);
+ ED_view3d_viewcontext_init(C, &wpd->vc);
+ view_angle_limits_init(&wpd->normal_angle_precalc,
+ vp->paint.brush->falloff_angle,
+ (vp->paint.brush->flag & BRUSH_FRONTFACE_FALLOFF) != 0);
+
+ wpd->active.index = vgroup_index.active;
+ wpd->mirror.index = vgroup_index.mirror;
+
+ /* multipaint */
+ wpd->defbase_tot = defbase_tot;
+ wpd->defbase_sel = defbase_sel;
+ wpd->defbase_tot_sel = defbase_tot_sel > 1 ? defbase_tot_sel : 1;
+ wpd->do_multipaint = (ts->multipaint && defbase_tot_sel > 1);
+
+ /* 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) {
+ wpd->vgroup_validmap = BKE_object_defgroup_validmap_get(ob, wpd->defbase_tot);
+ }
+
+ if (wpd->do_multipaint && ts->auto_normalize) {
+ bool *tmpflags;
+ tmpflags = MEM_mallocN(sizeof(bool) * defbase_tot, __func__);
+ if (wpd->lock_flags) {
+ BLI_array_binary_or(tmpflags, wpd->defbase_sel, wpd->lock_flags, wpd->defbase_tot);
+ }
+ else {
+ memcpy(tmpflags, wpd->defbase_sel, sizeof(*tmpflags) * wpd->defbase_tot);
+ }
+ wpd->active.lock = tmpflags;
+ }
+ else if (ts->auto_normalize) {
+ bool *tmpflags;
+
+ tmpflags = wpd->lock_flags ? MEM_dupallocN(wpd->lock_flags) :
+ MEM_callocN(sizeof(bool) * defbase_tot, __func__);
+ tmpflags[wpd->active.index] = true;
+ wpd->active.lock = tmpflags;
+
+ tmpflags = wpd->lock_flags ? MEM_dupallocN(wpd->lock_flags) :
+ MEM_callocN(sizeof(bool) * defbase_tot, __func__);
+ tmpflags[(wpd->mirror.index != -1) ? wpd->mirror.index : wpd->active.index] = true;
+ wpd->mirror.lock = tmpflags;
+ }
+
+ if (ELEM(vp->paint.brush->weightpaint_tool, WPAINT_TOOL_SMEAR, WPAINT_TOOL_BLUR)) {
+ wpd->precomputed_weight = MEM_mallocN(sizeof(float) * me->totvert, __func__);
+ }
+
+ /* If not previously created, create vertex/weight paint mode session data */
+ vertex_paint_init_stroke(depsgraph, scene, ob);
+ vwpaint_update_cache_invariants(C, vp, ss, op, mouse);
+ vertex_paint_init_session_data(ts, ob);
+
+ if (ob->sculpt->mode.wpaint.dvert_prev != NULL) {
+ MDeformVert *dv = ob->sculpt->mode.wpaint.dvert_prev;
+ for (int i = 0; i < me->totvert; i++, dv++) {
+ /* Use to show this isn't initialized, never apply to the mesh data. */
+ dv->flag = 1;
+ }
+ }
+
+ return true;
}
static float dot_vf3vs3(const float brushNormal[3], const short vertexNormal[3])
{
- float normal[3];
- normal_short_to_float_v3(normal, vertexNormal);
- return dot_v3v3(brushNormal, normal);
+ float normal[3];
+ normal_short_to_float_v3(normal, vertexNormal);
+ return dot_v3v3(brushNormal, normal);
}
-static void get_brush_alpha_data(
- const Scene *scene, const SculptSession *ss, const Brush *brush,
- float *r_brush_size_pressure, float *r_brush_alpha_value, float *r_brush_alpha_pressure)
+static void get_brush_alpha_data(const Scene *scene,
+ const SculptSession *ss,
+ const Brush *brush,
+ float *r_brush_size_pressure,
+ float *r_brush_alpha_value,
+ float *r_brush_alpha_pressure)
{
- *r_brush_size_pressure =
- BKE_brush_size_get(scene, brush) *
- (BKE_brush_use_size_pressure(scene, brush) ? ss->cache->pressure : 1.0f);
- *r_brush_alpha_value =
- BKE_brush_alpha_get(scene, brush);
- *r_brush_alpha_pressure =
- (BKE_brush_use_alpha_pressure(scene, brush) ? ss->cache->pressure : 1.0f);
+ *r_brush_size_pressure = BKE_brush_size_get(scene, brush) *
+ (BKE_brush_use_size_pressure(scene, brush) ? ss->cache->pressure :
+ 1.0f);
+ *r_brush_alpha_value = BKE_brush_alpha_get(scene, brush);
+ *r_brush_alpha_pressure = (BKE_brush_use_alpha_pressure(scene, brush) ? ss->cache->pressure :
+ 1.0f);
}
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);
+ 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);
- CLAMP(weight, 0.0f, 1.0f);
- return weight;
- }
- else {
- return defvert_find_weight(dv, wpi->active.index);
- }
+ CLAMP(weight, 0.0f, 1.0f);
+ return weight;
+ }
+ else {
+ return defvert_find_weight(dv, wpi->active.index);
+ }
}
-static void do_wpaint_precompute_weight_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict UNUSED(tls))
+static void do_wpaint_precompute_weight_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
{
- SculptThreadedTaskData *data = userdata;
- const MDeformVert *dv = &data->me->dvert[n];
+ SculptThreadedTaskData *data = userdata;
+ const MDeformVert *dv = &data->me->dvert[n];
- data->wpd->precomputed_weight[n] = wpaint_get_active_weight(dv, data->wpi);
+ data->wpd->precomputed_weight[n] = wpaint_get_active_weight(dv, data->wpi);
}
static void precompute_weight_values(
- bContext *C, Object *ob, Brush *brush, struct WPaintData *wpd, WeightPaintInfo *wpi, Mesh *me)
-{
- if (wpd->precomputed_weight_ready && !brush_use_accumulate_ex(brush, ob->mode))
- return;
-
- /* threaded loop over vertices */
- SculptThreadedTaskData data = {
- .C = C, .ob = ob, .wpd = wpd, .wpi = wpi, .me = me,
- };
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- BLI_task_parallel_range(
- 0, me->totvert,
- &data,
- do_wpaint_precompute_weight_cb_ex,
- &settings);
-
- wpd->precomputed_weight_ready = true;
-}
-
-static void do_wpaint_brush_blur_task_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict UNUSED(tls))
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
- const bool has_grids = (pbvh_type == PBVH_GRIDS);
- const struct SculptVertexPaintGeomMap *gmap = &ss->mode.wpaint.gmap;
-
- const Brush *brush = data->brush;
- const StrokeCache *cache = ss->cache;
- Scene *scene = CTX_data_scene(data->C);
-
- float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
- get_brush_alpha_data(scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
- const bool use_normal = vwpaint_use_normal(data->vp);
- const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
- 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(ss, &test, data->brush->falloff_shape);
- const float *sculpt_normal_frontface =
- sculpt_brush_frontface_normal_from_falloff_shape(ss, data->brush->falloff_shape);
-
- /* For each vertex */
- PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- /* Test to see if the vertex coordinates are within the spherical brush region. */
- if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- /* For grid based pbvh, take the vert whose loop corresponds to the current grid.
- * Otherwise, take the current vert. */
- const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
- const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
- const char v_flag = data->me->mvert[v_index].flag;
- /* If the vertex is selected */
- if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) {
- /* Get the average poly weight */
- int total_hit_loops = 0;
- float weight_final = 0.0f;
- for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
- const int p_index = gmap->vert_to_poly[v_index].indices[j];
- const MPoly *mp = &data->me->mpoly[p_index];
-
- total_hit_loops += mp->totloop;
- for (int k = 0; k < mp->totloop; k++) {
- const int l_index = mp->loopstart + k;
- const MLoop *ml = &data->me->mloop[l_index];
- weight_final += data->wpd->precomputed_weight[ml->v];
- }
- }
-
- /* Apply the weight to the vertex. */
- if (total_hit_loops != 0) {
- float brush_strength = cache->bstrength;
- const float angle_cos = (use_normal && vd.no) ?
- dot_vf3vs3(sculpt_normal_frontface, vd.no) : 1.0f;
- if (((brush->flag & BRUSH_FRONTFACE) == 0 ||
- (angle_cos > 0.0f)) &&
- ((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
- view_angle_limits_apply_falloff(&data->wpd->normal_angle_precalc, angle_cos, &brush_strength)))
- {
- const float brush_fade = BKE_brush_curve_strength(brush, sqrtf(test.dist), cache->radius);
- const float final_alpha =
- brush_fade * brush_strength *
- grid_alpha * brush_alpha_pressure;
-
- if ((brush->flag & BRUSH_ACCUMULATE) == 0) {
- if (ss->mode.wpaint.alpha_weight[v_index] < final_alpha) {
- ss->mode.wpaint.alpha_weight[v_index] = final_alpha;
- }
- else {
- continue;
- }
- }
-
- weight_final /= total_hit_loops;
- /* Only paint visible verts */
- do_weight_paint_vertex(
- data->vp, data->ob, data->wpi,
- v_index, final_alpha, weight_final);
- }
- }
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
-}
-
-static void do_wpaint_brush_smear_task_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict UNUSED(tls))
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
- const bool has_grids = (pbvh_type == PBVH_GRIDS);
- const struct SculptVertexPaintGeomMap *gmap = &ss->mode.wpaint.gmap;
-
- const Brush *brush = data->brush;
- const Scene *scene = CTX_data_scene(data->C);
- const StrokeCache *cache = ss->cache;
- float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
- get_brush_alpha_data(scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
- const bool use_normal = vwpaint_use_normal(data->vp);
- const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
- const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
- float brush_dir[3];
-
- sub_v3_v3v3(brush_dir, cache->location, cache->last_location);
- project_plane_v3_v3v3(brush_dir, brush_dir, cache->view_normal);
-
- 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(ss, &test, data->brush->falloff_shape);
- const float *sculpt_normal_frontface =
- sculpt_brush_frontface_normal_from_falloff_shape(ss, data->brush->falloff_shape);
-
- /* For each vertex */
- PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- /* Test to see if the vertex coordinates are within the spherical brush region. */
- if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- /* For grid based pbvh, take the vert whose loop corresponds to the current grid.
- * Otherwise, take the current vert. */
- const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
- const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
- const MVert *mv_curr = &data->me->mvert[v_index];
-
- /* If the vertex is selected */
- if (!(use_face_sel || use_vert_sel) || mv_curr->flag & SELECT) {
- float brush_strength = cache->bstrength;
- const float angle_cos = (use_normal && vd.no) ?
- dot_vf3vs3(sculpt_normal_frontface, vd.no) : 1.0f;
- if (((brush->flag & BRUSH_FRONTFACE) == 0 ||
- (angle_cos > 0.0f)) &&
- ((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
- view_angle_limits_apply_falloff(&data->wpd->normal_angle_precalc, angle_cos, &brush_strength)))
- {
- bool do_color = false;
- /* Minimum dot product between brush direction and current
- * to neighbor direction is 0.0, meaning orthogonal. */
- float stroke_dot_max = 0.0f;
-
- /* Get the color of the loop in the opposite direction of the brush movement
- * (this callback is specifically for smear.) */
- float weight_final = 0.0;
- for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
- const int p_index = gmap->vert_to_poly[v_index].indices[j];
- const MPoly *mp = &data->me->mpoly[p_index];
- const MLoop *ml_other = &data->me->mloop[mp->loopstart];
- for (int k = 0; k < mp->totloop; k++, ml_other++) {
- const uint v_other_index = ml_other->v;
- if (v_other_index != v_index) {
- const MVert *mv_other = &data->me->mvert[v_other_index];
-
- /* Get the direction from the selected vert to the neighbor. */
- float other_dir[3];
- sub_v3_v3v3(other_dir, mv_curr->co, mv_other->co);
- project_plane_v3_v3v3(other_dir, other_dir, cache->view_normal);
-
- normalize_v3(other_dir);
-
- const float stroke_dot = dot_v3v3(other_dir, brush_dir);
-
- if (stroke_dot > stroke_dot_max) {
- stroke_dot_max = stroke_dot;
- weight_final = data->wpd->precomputed_weight[v_other_index];
- do_color = true;
- }
- }
- }
- }
- /* Apply weight to vertex */
- if (do_color) {
- const float brush_fade = BKE_brush_curve_strength(brush, sqrtf(test.dist), cache->radius);
- const float final_alpha =
- brush_fade * brush_strength *
- grid_alpha * brush_alpha_pressure;
-
- if (final_alpha <= 0.0f)
- continue;
-
- do_weight_paint_vertex(
- data->vp, data->ob, data->wpi,
- v_index, final_alpha, (float)weight_final);
- }
- }
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
- }
-}
-
-static void do_wpaint_brush_draw_task_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict UNUSED(tls))
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
- const bool has_grids = (pbvh_type == PBVH_GRIDS);
- const Scene *scene = CTX_data_scene(data->C);
-
- const Brush *brush = data->brush;
- const StrokeCache *cache = ss->cache;
- /* note: normally `BKE_brush_weight_get(scene, brush)` is used,
- * however in this case we calculate a new weight each time. */
- const float paintweight = data->strength;
- float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
- get_brush_alpha_data(scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
- const bool use_normal = vwpaint_use_normal(data->vp);
- const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
- 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(ss, &test, data->brush->falloff_shape);
- const float *sculpt_normal_frontface =
- sculpt_brush_frontface_normal_from_falloff_shape(ss, data->brush->falloff_shape);
-
- /* For each vertex */
- PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- /* Test to see if the vertex coordinates are within the spherical brush region. */
- if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- /* Note: grids are 1:1 with corners (aka loops).
- * For multires, take the vert whose loop corresponds to the current grid.
- * Otherwise, take the current vert. */
- const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
- const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
-
- const char v_flag = data->me->mvert[v_index].flag;
- /* If the vertex is selected */
- if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) {
- float brush_strength = cache->bstrength;
- const float angle_cos = (use_normal && vd.no) ?
- dot_vf3vs3(sculpt_normal_frontface, vd.no) : 1.0f;
- if (((brush->flag & BRUSH_FRONTFACE) == 0 ||
- (angle_cos > 0.0f)) &&
- ((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
- view_angle_limits_apply_falloff(&data->wpd->normal_angle_precalc, angle_cos, &brush_strength)))
- {
- const float brush_fade = BKE_brush_curve_strength(brush, sqrtf(test.dist), cache->radius);
- const float final_alpha = brush_fade * brush_strength * grid_alpha * brush_alpha_pressure;
-
- if ((brush->flag & BRUSH_ACCUMULATE) == 0) {
- if (ss->mode.wpaint.alpha_weight[v_index] < final_alpha) {
- ss->mode.wpaint.alpha_weight[v_index] = final_alpha;
- }
- else {
- continue;
- }
- }
-
- do_weight_paint_vertex(
- data->vp, data->ob, data->wpi,
- v_index, final_alpha, paintweight);
- }
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
+ bContext *C, Object *ob, Brush *brush, struct WPaintData *wpd, WeightPaintInfo *wpi, Mesh *me)
+{
+ if (wpd->precomputed_weight_ready && !brush_use_accumulate_ex(brush, ob->mode))
+ return;
+
+ /* threaded loop over vertices */
+ SculptThreadedTaskData data = {
+ .C = C,
+ .ob = ob,
+ .wpd = wpd,
+ .wpi = wpi,
+ .me = me,
+ };
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ BLI_task_parallel_range(0, me->totvert, &data, do_wpaint_precompute_weight_cb_ex, &settings);
+
+ wpd->precomputed_weight_ready = true;
+}
+
+static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
+ const bool has_grids = (pbvh_type == PBVH_GRIDS);
+ const struct SculptVertexPaintGeomMap *gmap = &ss->mode.wpaint.gmap;
+
+ const Brush *brush = data->brush;
+ const StrokeCache *cache = ss->cache;
+ Scene *scene = CTX_data_scene(data->C);
+
+ float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
+ get_brush_alpha_data(
+ scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
+ const bool use_normal = vwpaint_use_normal(data->vp);
+ const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ 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(
+ ss, &test, data->brush->falloff_shape);
+ const float *sculpt_normal_frontface = sculpt_brush_frontface_normal_from_falloff_shape(
+ ss, data->brush->falloff_shape);
+
+ /* For each vertex */
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ /* Test to see if the vertex coordinates are within the spherical brush region. */
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ /* For grid based pbvh, take the vert whose loop corresponds to the current grid.
+ * Otherwise, take the current vert. */
+ const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v :
+ vd.vert_indices[vd.i];
+ const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
+ const char v_flag = data->me->mvert[v_index].flag;
+ /* If the vertex is selected */
+ if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) {
+ /* Get the average poly weight */
+ int total_hit_loops = 0;
+ float weight_final = 0.0f;
+ for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
+ const int p_index = gmap->vert_to_poly[v_index].indices[j];
+ const MPoly *mp = &data->me->mpoly[p_index];
+
+ total_hit_loops += mp->totloop;
+ for (int k = 0; k < mp->totloop; k++) {
+ const int l_index = mp->loopstart + k;
+ const MLoop *ml = &data->me->mloop[l_index];
+ weight_final += data->wpd->precomputed_weight[ml->v];
+ }
+ }
+
+ /* Apply the weight to the vertex. */
+ if (total_hit_loops != 0) {
+ float brush_strength = cache->bstrength;
+ const float angle_cos = (use_normal && vd.no) ?
+ dot_vf3vs3(sculpt_normal_frontface, vd.no) :
+ 1.0f;
+ if (((brush->flag & BRUSH_FRONTFACE) == 0 || (angle_cos > 0.0f)) &&
+ ((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
+ view_angle_limits_apply_falloff(
+ &data->wpd->normal_angle_precalc, angle_cos, &brush_strength))) {
+ const float brush_fade = BKE_brush_curve_strength(
+ brush, sqrtf(test.dist), cache->radius);
+ const float final_alpha = brush_fade * brush_strength * grid_alpha *
+ brush_alpha_pressure;
+
+ if ((brush->flag & BRUSH_ACCUMULATE) == 0) {
+ if (ss->mode.wpaint.alpha_weight[v_index] < final_alpha) {
+ ss->mode.wpaint.alpha_weight[v_index] = final_alpha;
+ }
+ else {
+ continue;
+ }
+ }
+
+ weight_final /= total_hit_loops;
+ /* Only paint visible verts */
+ do_weight_paint_vertex(
+ data->vp, data->ob, data->wpi, v_index, final_alpha, weight_final);
+ }
+ }
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
+ const bool has_grids = (pbvh_type == PBVH_GRIDS);
+ const struct SculptVertexPaintGeomMap *gmap = &ss->mode.wpaint.gmap;
+
+ const Brush *brush = data->brush;
+ const Scene *scene = CTX_data_scene(data->C);
+ const StrokeCache *cache = ss->cache;
+ float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
+ get_brush_alpha_data(
+ scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
+ const bool use_normal = vwpaint_use_normal(data->vp);
+ const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+ float brush_dir[3];
+
+ sub_v3_v3v3(brush_dir, cache->location, cache->last_location);
+ project_plane_v3_v3v3(brush_dir, brush_dir, cache->view_normal);
+
+ 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(
+ ss, &test, data->brush->falloff_shape);
+ const float *sculpt_normal_frontface = sculpt_brush_frontface_normal_from_falloff_shape(
+ ss, data->brush->falloff_shape);
+
+ /* For each vertex */
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ /* Test to see if the vertex coordinates are within the spherical brush region. */
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ /* For grid based pbvh, take the vert whose loop corresponds to the current grid.
+ * Otherwise, take the current vert. */
+ const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v :
+ vd.vert_indices[vd.i];
+ const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
+ const MVert *mv_curr = &data->me->mvert[v_index];
+
+ /* If the vertex is selected */
+ if (!(use_face_sel || use_vert_sel) || mv_curr->flag & SELECT) {
+ float brush_strength = cache->bstrength;
+ const float angle_cos = (use_normal && vd.no) ?
+ dot_vf3vs3(sculpt_normal_frontface, vd.no) :
+ 1.0f;
+ if (((brush->flag & BRUSH_FRONTFACE) == 0 || (angle_cos > 0.0f)) &&
+ ((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
+ view_angle_limits_apply_falloff(
+ &data->wpd->normal_angle_precalc, angle_cos, &brush_strength))) {
+ bool do_color = false;
+ /* Minimum dot product between brush direction and current
+ * to neighbor direction is 0.0, meaning orthogonal. */
+ float stroke_dot_max = 0.0f;
+
+ /* Get the color of the loop in the opposite direction of the brush movement
+ * (this callback is specifically for smear.) */
+ float weight_final = 0.0;
+ for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
+ const int p_index = gmap->vert_to_poly[v_index].indices[j];
+ const MPoly *mp = &data->me->mpoly[p_index];
+ const MLoop *ml_other = &data->me->mloop[mp->loopstart];
+ for (int k = 0; k < mp->totloop; k++, ml_other++) {
+ const uint v_other_index = ml_other->v;
+ if (v_other_index != v_index) {
+ const MVert *mv_other = &data->me->mvert[v_other_index];
+
+ /* Get the direction from the selected vert to the neighbor. */
+ float other_dir[3];
+ sub_v3_v3v3(other_dir, mv_curr->co, mv_other->co);
+ project_plane_v3_v3v3(other_dir, other_dir, cache->view_normal);
+
+ normalize_v3(other_dir);
+
+ const float stroke_dot = dot_v3v3(other_dir, brush_dir);
+
+ if (stroke_dot > stroke_dot_max) {
+ stroke_dot_max = stroke_dot;
+ weight_final = data->wpd->precomputed_weight[v_other_index];
+ do_color = true;
+ }
+ }
+ }
+ }
+ /* Apply weight to vertex */
+ if (do_color) {
+ const float brush_fade = BKE_brush_curve_strength(
+ brush, sqrtf(test.dist), cache->radius);
+ const float final_alpha = brush_fade * brush_strength * grid_alpha *
+ brush_alpha_pressure;
+
+ if (final_alpha <= 0.0f)
+ continue;
+
+ do_weight_paint_vertex(
+ data->vp, data->ob, data->wpi, v_index, final_alpha, (float)weight_final);
+ }
+ }
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+ }
+}
+
+static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
+ const bool has_grids = (pbvh_type == PBVH_GRIDS);
+ const Scene *scene = CTX_data_scene(data->C);
+
+ const Brush *brush = data->brush;
+ const StrokeCache *cache = ss->cache;
+ /* note: normally `BKE_brush_weight_get(scene, brush)` is used,
+ * however in this case we calculate a new weight each time. */
+ const float paintweight = data->strength;
+ float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
+ get_brush_alpha_data(
+ scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
+ const bool use_normal = vwpaint_use_normal(data->vp);
+ const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ 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(
+ ss, &test, data->brush->falloff_shape);
+ const float *sculpt_normal_frontface = sculpt_brush_frontface_normal_from_falloff_shape(
+ ss, data->brush->falloff_shape);
+
+ /* For each vertex */
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ /* Test to see if the vertex coordinates are within the spherical brush region. */
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ /* Note: grids are 1:1 with corners (aka loops).
+ * For multires, take the vert whose loop corresponds to the current grid.
+ * Otherwise, take the current vert. */
+ const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v :
+ vd.vert_indices[vd.i];
+ const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
+
+ const char v_flag = data->me->mvert[v_index].flag;
+ /* If the vertex is selected */
+ if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) {
+ float brush_strength = cache->bstrength;
+ const float angle_cos = (use_normal && vd.no) ?
+ dot_vf3vs3(sculpt_normal_frontface, vd.no) :
+ 1.0f;
+ if (((brush->flag & BRUSH_FRONTFACE) == 0 || (angle_cos > 0.0f)) &&
+ ((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
+ view_angle_limits_apply_falloff(
+ &data->wpd->normal_angle_precalc, angle_cos, &brush_strength))) {
+ const float brush_fade = BKE_brush_curve_strength(
+ brush, sqrtf(test.dist), cache->radius);
+ const float final_alpha = brush_fade * brush_strength * grid_alpha *
+ brush_alpha_pressure;
+
+ if ((brush->flag & BRUSH_ACCUMULATE) == 0) {
+ if (ss->mode.wpaint.alpha_weight[v_index] < final_alpha) {
+ ss->mode.wpaint.alpha_weight[v_index] = final_alpha;
+ }
+ else {
+ continue;
+ }
+ }
+
+ do_weight_paint_vertex(data->vp, data->ob, data->wpi, v_index, final_alpha, paintweight);
+ }
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
static void do_wpaint_brush_calc_average_weight_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict UNUSED(tls))
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- StrokeCache *cache = ss->cache;
- const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
- const bool has_grids = (pbvh_type == PBVH_GRIDS);
-
- const bool use_normal = vwpaint_use_normal(data->vp);
- const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
- const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
-
- struct WPaintAverageAccum *accum = (struct WPaintAverageAccum *)data->custom_data + n;
- accum->len = 0;
- accum->value = 0.0;
-
- SculptBrushTest test;
- 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(ss, data->brush->falloff_shape);
-
- /* For each vertex */
- PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- /* Test to see if the vertex coordinates are within the spherical brush region. */
- if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- const float angle_cos = (use_normal && vd.no) ?
- dot_vf3vs3(sculpt_normal_frontface, vd.no) : 1.0f;
- if (angle_cos > 0.0 && BKE_brush_curve_strength(data->brush, sqrtf(test.dist), cache->radius) > 0.0) {
- const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
- // const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
- const char v_flag = data->me->mvert[v_index].flag;
-
- /* If the vertex is selected. */
- if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) {
- const MDeformVert *dv = &data->me->dvert[v_index];
- accum->len += 1;
- accum->value += wpaint_get_active_weight(dv, data->wpi);
- }
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
-}
-
-static void calculate_average_weight(SculptThreadedTaskData *data, PBVHNode **UNUSED(nodes), int totnode)
-{
- struct WPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__);
- data->custom_data = accum;
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((data->sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- 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;
- for (int i = 0; i < totnode; i++) {
- accum_len += accum[i].len;
- accum_weight += accum[i].value;
- }
- if (accum_len != 0) {
- accum_weight /= accum_len;
- data->strength = (float)accum_weight;
- }
-
- MEM_SAFE_FREE(data->custom_data); /* 'accum' */
-}
-
-
-static void wpaint_paint_leaves(
- bContext *C, Object *ob, Sculpt *sd, VPaint *vp, struct WPaintData *wpd, WeightPaintInfo *wpi,
- Mesh *me, PBVHNode **nodes, int totnode)
-{
- Scene *scene = CTX_data_scene(C);
- const Brush *brush = ob->sculpt->cache->brush;
-
- /* threaded loop over nodes */
- SculptThreadedTaskData data = {
- .C = C, .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- .vp = vp, .wpd = wpd, .wpi = wpi, .me = me,
- };
-
- /* Use this so average can modify its weight without touching the brush. */
- data.strength = BKE_brush_weight_get(scene, brush);
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- /* NOTE: current mirroring code cannot be run in parallel */
- settings.use_threading = !(me->editflag & ME_EDIT_MIRROR_X);
-
- switch ((eBrushWeightPaintTool)brush->weightpaint_tool) {
- case WPAINT_TOOL_AVERAGE:
- calculate_average_weight(&data, nodes, totnode);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_wpaint_brush_draw_task_cb_ex,
- &settings);
- break;
- case WPAINT_TOOL_SMEAR:
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_wpaint_brush_smear_task_cb_ex,
- &settings);
- break;
- case WPAINT_TOOL_BLUR:
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_wpaint_brush_blur_task_cb_ex,
- &settings);
- break;
- case WPAINT_TOOL_DRAW:
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_wpaint_brush_draw_task_cb_ex,
- &settings);
- break;
- }
+ void *__restrict userdata, const int n, const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ StrokeCache *cache = ss->cache;
+ const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
+ const bool has_grids = (pbvh_type == PBVH_GRIDS);
+
+ const bool use_normal = vwpaint_use_normal(data->vp);
+ const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+
+ struct WPaintAverageAccum *accum = (struct WPaintAverageAccum *)data->custom_data + n;
+ accum->len = 0;
+ accum->value = 0.0;
+
+ SculptBrushTest test;
+ 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(
+ ss, data->brush->falloff_shape);
+
+ /* For each vertex */
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ /* Test to see if the vertex coordinates are within the spherical brush region. */
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ const float angle_cos = (use_normal && vd.no) ? dot_vf3vs3(sculpt_normal_frontface, vd.no) :
+ 1.0f;
+ if (angle_cos > 0.0 &&
+ BKE_brush_curve_strength(data->brush, sqrtf(test.dist), cache->radius) > 0.0) {
+ const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v :
+ vd.vert_indices[vd.i];
+ // const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
+ const char v_flag = data->me->mvert[v_index].flag;
+
+ /* If the vertex is selected. */
+ if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) {
+ const MDeformVert *dv = &data->me->dvert[v_index];
+ accum->len += 1;
+ accum->value += wpaint_get_active_weight(dv, data->wpi);
+ }
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static void calculate_average_weight(SculptThreadedTaskData *data,
+ PBVHNode **UNUSED(nodes),
+ int totnode)
+{
+ struct WPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__);
+ data->custom_data = accum;
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((data->sd->flags & SCULPT_USE_OPENMP) &&
+ totnode > SCULPT_THREADED_LIMIT);
+ 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;
+ for (int i = 0; i < totnode; i++) {
+ accum_len += accum[i].len;
+ accum_weight += accum[i].value;
+ }
+ if (accum_len != 0) {
+ accum_weight /= accum_len;
+ data->strength = (float)accum_weight;
+ }
+
+ MEM_SAFE_FREE(data->custom_data); /* 'accum' */
+}
+
+static void wpaint_paint_leaves(bContext *C,
+ Object *ob,
+ Sculpt *sd,
+ VPaint *vp,
+ struct WPaintData *wpd,
+ WeightPaintInfo *wpi,
+ Mesh *me,
+ PBVHNode **nodes,
+ int totnode)
+{
+ Scene *scene = CTX_data_scene(C);
+ const Brush *brush = ob->sculpt->cache->brush;
+
+ /* threaded loop over nodes */
+ SculptThreadedTaskData data = {
+ .C = C,
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .vp = vp,
+ .wpd = wpd,
+ .wpi = wpi,
+ .me = me,
+ };
+
+ /* Use this so average can modify its weight without touching the brush. */
+ data.strength = BKE_brush_weight_get(scene, brush);
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ /* NOTE: current mirroring code cannot be run in parallel */
+ settings.use_threading = !(me->editflag & ME_EDIT_MIRROR_X);
+
+ switch ((eBrushWeightPaintTool)brush->weightpaint_tool) {
+ case WPAINT_TOOL_AVERAGE:
+ calculate_average_weight(&data, nodes, totnode);
+ BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings);
+ break;
+ case WPAINT_TOOL_SMEAR:
+ BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_smear_task_cb_ex, &settings);
+ break;
+ case WPAINT_TOOL_BLUR:
+ BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_blur_task_cb_ex, &settings);
+ break;
+ case WPAINT_TOOL_DRAW:
+ BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings);
+ break;
+ }
}
static PBVHNode **vwpaint_pbvh_gather_generic(
- Object *ob, VPaint *wp, Sculpt *sd, Brush *brush, int *r_totnode)
-{
- SculptSession *ss = ob->sculpt;
- const bool use_normal = vwpaint_use_normal(wp);
- PBVHNode **nodes = NULL;
-
- /* Build a list of all nodes that are potentially within the brush's area of influence */
- if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
- SculptSearchSphereData data = {
- .ss = ss,
- .sd = sd,
- .radius_squared = ss->cache->radius_squared,
- .original = true,
- };
- BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, r_totnode);
- if (use_normal) {
- sculpt_pbvh_calc_area_normal(brush, ob, nodes, *r_totnode, true, ss->cache->sculpt_normal_symm);
- }
- else {
- zero_v3(ss->cache->sculpt_normal_symm);
- }
- }
- else {
- struct DistRayAABB_Precalc dist_ray_to_aabb_precalc;
- dist_squared_ray_to_aabb_v3_precalc(&dist_ray_to_aabb_precalc, ss->cache->location, ss->cache->view_normal);
- SculptSearchCircleData data = {
- .ss = ss,
- .sd = sd,
- .radius_squared = ss->cache->radius_squared,
- .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);
- if (use_normal) {
- copy_v3_v3(ss->cache->sculpt_normal_symm, ss->cache->view_normal);
- }
- else {
- zero_v3(ss->cache->sculpt_normal_symm);
- }
- }
- return nodes;
-}
-
-static void wpaint_do_paint(
- bContext *C, Object *ob, VPaint *wp, Sculpt *sd, struct WPaintData *wpd, WeightPaintInfo *wpi,
- Mesh *me, Brush *brush, const char symm, const int axis, const int i, const float angle)
-{
- SculptSession *ss = ob->sculpt;
- ss->cache->radial_symmetry_pass = i;
- sculpt_cache_calc_brushdata_symm(ss->cache, symm, axis, angle);
-
- int totnode;
- PBVHNode **nodes = vwpaint_pbvh_gather_generic(ob, wp, sd, brush, &totnode);
-
- wpaint_paint_leaves(C, ob, sd, wp, wpd, wpi, me, nodes, totnode);
-
- if (nodes)
- MEM_freeN(nodes);
-}
-
-static void wpaint_do_radial_symmetry(
- bContext *C, Object *ob, VPaint *wp, Sculpt *sd, struct WPaintData *wpd, WeightPaintInfo *wpi,
- Mesh *me, Brush *brush, const char symm, const int axis)
-{
- for (int i = 1; i < wp->radial_symm[axis - 'X']; i++) {
- const float angle = (2.0 * M_PI) * i / wp->radial_symm[axis - 'X'];
- wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, symm, axis, i, angle);
- }
+ Object *ob, VPaint *wp, Sculpt *sd, Brush *brush, int *r_totnode)
+{
+ SculptSession *ss = ob->sculpt;
+ const bool use_normal = vwpaint_use_normal(wp);
+ PBVHNode **nodes = NULL;
+
+ /* Build a list of all nodes that are potentially within the brush's area of influence */
+ if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
+ SculptSearchSphereData data = {
+ .ss = ss,
+ .sd = sd,
+ .radius_squared = ss->cache->radius_squared,
+ .original = true,
+ };
+ BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, r_totnode);
+ if (use_normal) {
+ sculpt_pbvh_calc_area_normal(
+ brush, ob, nodes, *r_totnode, true, ss->cache->sculpt_normal_symm);
+ }
+ else {
+ zero_v3(ss->cache->sculpt_normal_symm);
+ }
+ }
+ else {
+ struct DistRayAABB_Precalc dist_ray_to_aabb_precalc;
+ dist_squared_ray_to_aabb_v3_precalc(
+ &dist_ray_to_aabb_precalc, ss->cache->location, ss->cache->view_normal);
+ SculptSearchCircleData data = {
+ .ss = ss,
+ .sd = sd,
+ .radius_squared = ss->cache->radius_squared,
+ .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);
+ if (use_normal) {
+ copy_v3_v3(ss->cache->sculpt_normal_symm, ss->cache->view_normal);
+ }
+ else {
+ zero_v3(ss->cache->sculpt_normal_symm);
+ }
+ }
+ return nodes;
+}
+
+static void wpaint_do_paint(bContext *C,
+ Object *ob,
+ VPaint *wp,
+ Sculpt *sd,
+ struct WPaintData *wpd,
+ WeightPaintInfo *wpi,
+ Mesh *me,
+ Brush *brush,
+ const char symm,
+ const int axis,
+ const int i,
+ const float angle)
+{
+ SculptSession *ss = ob->sculpt;
+ ss->cache->radial_symmetry_pass = i;
+ sculpt_cache_calc_brushdata_symm(ss->cache, symm, axis, angle);
+
+ int totnode;
+ PBVHNode **nodes = vwpaint_pbvh_gather_generic(ob, wp, sd, brush, &totnode);
+
+ wpaint_paint_leaves(C, ob, sd, wp, wpd, wpi, me, nodes, totnode);
+
+ if (nodes)
+ MEM_freeN(nodes);
+}
+
+static void wpaint_do_radial_symmetry(bContext *C,
+ Object *ob,
+ VPaint *wp,
+ Sculpt *sd,
+ struct WPaintData *wpd,
+ WeightPaintInfo *wpi,
+ Mesh *me,
+ Brush *brush,
+ const char symm,
+ const int axis)
+{
+ for (int i = 1; i < wp->radial_symm[axis - 'X']; i++) {
+ const float angle = (2.0 * M_PI) * i / wp->radial_symm[axis - 'X'];
+ wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, symm, axis, i, angle);
+ }
}
/* near duplicate of: sculpt.c's,
* 'do_symmetrical_brush_actions' and 'vpaint_do_symmetrical_brush_actions'. */
static void wpaint_do_symmetrical_brush_actions(
- bContext *C, Object *ob, VPaint *wp, Sculpt *sd, struct WPaintData *wpd, WeightPaintInfo *wpi)
-{
- Brush *brush = BKE_paint_brush(&wp->paint);
- Mesh *me = ob->data;
- SculptSession *ss = ob->sculpt;
- StrokeCache *cache = ss->cache;
- const char symm = wp->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
- int i = 0;
-
- /* initial stroke */
- wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'X', 0, 0);
- wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'X');
- wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'Y');
- wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'Z');
-
- cache->symmetry = symm;
-
- /* 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 = 1; i <= symm; i++) {
- 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);
-
- if (i & (1 << 0)) {
- wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, i, 'X', 0, 0);
- wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, i, 'X');
- }
- if (i & (1 << 1)) {
- wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Y', 0, 0);
- wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Y');
- }
- if (i & (1 << 2)) {
- wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Z', 0, 0);
- wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Z');
- }
- }
- }
- copy_v3_v3(cache->true_last_location, cache->true_location);
- cache->is_last_valid = true;
+ bContext *C, Object *ob, VPaint *wp, Sculpt *sd, struct WPaintData *wpd, WeightPaintInfo *wpi)
+{
+ Brush *brush = BKE_paint_brush(&wp->paint);
+ Mesh *me = ob->data;
+ SculptSession *ss = ob->sculpt;
+ StrokeCache *cache = ss->cache;
+ const char symm = wp->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+ int i = 0;
+
+ /* initial stroke */
+ wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'X', 0, 0);
+ wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'X');
+ wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'Y');
+ wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'Z');
+
+ cache->symmetry = symm;
+
+ /* 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 = 1; i <= symm; i++) {
+ 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);
+
+ if (i & (1 << 0)) {
+ wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, i, 'X', 0, 0);
+ wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, i, 'X');
+ }
+ if (i & (1 << 1)) {
+ wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Y', 0, 0);
+ wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Y');
+ }
+ if (i & (1 << 2)) {
+ wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Z', 0, 0);
+ wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Z');
+ }
+ }
+ }
+ copy_v3_v3(cache->true_last_location, cache->true_location);
+ cache->is_last_valid = true;
}
static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
{
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- VPaint *wp = ts->wpaint;
- Brush *brush = BKE_paint_brush(&wp->paint);
- struct WPaintData *wpd = paint_stroke_mode_data(stroke);
- ViewContext *vc;
- Object *ob = CTX_data_active_object(C);
-
- SculptSession *ss = ob->sculpt;
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ VPaint *wp = ts->wpaint;
+ Brush *brush = BKE_paint_brush(&wp->paint);
+ struct WPaintData *wpd = paint_stroke_mode_data(stroke);
+ ViewContext *vc;
+ Object *ob = CTX_data_active_object(C);
- vwpaint_update_cache_variants(C, wp, ob, itemptr);
+ SculptSession *ss = ob->sculpt;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- float mat[4][4];
- float mval[2];
+ vwpaint_update_cache_variants(C, wp, ob, itemptr);
- const float brush_alpha_value = BKE_brush_alpha_get(scene, brush);
+ float mat[4][4];
+ float mval[2];
- /* intentionally don't initialize as NULL, make sure we initialize all members below */
- WeightPaintInfo wpi;
+ const float brush_alpha_value = BKE_brush_alpha_get(scene, brush);
- /* cannot paint if there is no stroke data */
- if (wpd == NULL) {
- /* XXX: force a redraw here, since even though we can't paint,
- * at least view won't freeze until stroke ends */
- ED_region_tag_redraw(CTX_wm_region(C));
- return;
- }
+ /* intentionally don't initialize as NULL, make sure we initialize all members below */
+ WeightPaintInfo wpi;
- vc = &wpd->vc;
- ob = vc->obact;
+ /* cannot paint if there is no stroke data */
+ if (wpd == NULL) {
+ /* XXX: force a redraw here, since even though we can't paint,
+ * at least view won't freeze until stroke ends */
+ ED_region_tag_redraw(CTX_wm_region(C));
+ return;
+ }
- view3d_operator_needs_opengl(C);
- ED_view3d_init_mats_rv3d(ob, vc->rv3d);
+ vc = &wpd->vc;
+ ob = vc->obact;
- /* load projection matrix */
- mul_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat);
+ view3d_operator_needs_opengl(C);
+ ED_view3d_init_mats_rv3d(ob, vc->rv3d);
+ /* load projection matrix */
+ mul_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat);
- /* *** setup WeightPaintInfo - pass onto do_weight_paint_vertex *** */
- wpi.defbase_tot = wpd->defbase_tot;
- wpi.defbase_sel = wpd->defbase_sel;
- wpi.defbase_tot_sel = wpd->defbase_tot_sel;
+ /* *** setup WeightPaintInfo - pass onto do_weight_paint_vertex *** */
+ wpi.defbase_tot = wpd->defbase_tot;
+ wpi.defbase_sel = wpd->defbase_sel;
+ wpi.defbase_tot_sel = wpd->defbase_tot_sel;
- wpi.defbase_tot_unsel = wpi.defbase_tot - wpi.defbase_tot_sel;
- wpi.active = wpd->active;
- wpi.mirror = wpd->mirror;
- wpi.lock_flags = wpd->lock_flags;
- wpi.vgroup_validmap = wpd->vgroup_validmap;
- 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.brush_alpha_value = brush_alpha_value;
- /* *** done setting up WeightPaintInfo *** */
+ wpi.defbase_tot_unsel = wpi.defbase_tot - wpi.defbase_tot_sel;
+ wpi.active = wpd->active;
+ wpi.mirror = wpd->mirror;
+ wpi.lock_flags = wpd->lock_flags;
+ wpi.vgroup_validmap = wpd->vgroup_validmap;
+ 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.brush_alpha_value = brush_alpha_value;
+ /* *** done setting up WeightPaintInfo *** */
- if (wpd->precomputed_weight) {
- precompute_weight_values(C, ob, brush, wpd, &wpi, ob->data);
- }
+ if (wpd->precomputed_weight) {
+ precompute_weight_values(C, ob, brush, wpd, &wpi, ob->data);
+ }
- wpaint_do_symmetrical_brush_actions(C, ob, wp, sd, wpd, &wpi);
+ wpaint_do_symmetrical_brush_actions(C, ob, wp, sd, wpd, &wpi);
- swap_m4m4(vc->rv3d->persmat, mat);
+ swap_m4m4(vc->rv3d->persmat, mat);
- /* calculate pivot for rotation around seletion if needed */
- /* also needed for "View Selected" on last stroke */
- paint_last_stroke_update(scene, vc->ar, mval);
+ /* calculate pivot for rotation around seletion if needed */
+ /* also needed for "View Selected" on last stroke */
+ paint_last_stroke_update(scene, vc->ar, mval);
- BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+ BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
- DEG_id_tag_update(ob->data, 0);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- swap_m4m4(wpd->vc.rv3d->persmat, mat);
+ DEG_id_tag_update(ob->data, 0);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ swap_m4m4(wpd->vc.rv3d->persmat, mat);
- rcti r;
- if (sculpt_get_redraw_rect(vc->ar, CTX_wm_region_view3d(C), ob, &r)) {
- if (ss->cache) {
- ss->cache->current_r = r;
- }
+ rcti r;
+ if (sculpt_get_redraw_rect(vc->ar, 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 */
- if (ss->cache) {
- if (!BLI_rcti_is_empty(&ss->cache->previous_r))
- BLI_rcti_union(&r, &ss->cache->previous_r);
- }
+ /* previous is not set in the current cache else
+ * the partial rect will always grow */
+ if (ss->cache) {
+ if (!BLI_rcti_is_empty(&ss->cache->previous_r))
+ BLI_rcti_union(&r, &ss->cache->previous_r);
+ }
- 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->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;
- ss->partial_redraw = 1;
- }
- ED_region_tag_redraw_partial(vc->ar, &r);
+ ss->partial_redraw = 1;
+ }
+ ED_region_tag_redraw_partial(vc->ar, &r);
}
static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
{
- Object *ob = CTX_data_active_object(C);
- struct WPaintData *wpd = paint_stroke_mode_data(stroke);
-
- if (wpd) {
- if (wpd->defbase_sel)
- MEM_freeN((void *)wpd->defbase_sel);
- if (wpd->vgroup_validmap)
- MEM_freeN((void *)wpd->vgroup_validmap);
- if (wpd->lock_flags)
- MEM_freeN((void *)wpd->lock_flags);
- if (wpd->active.lock)
- MEM_freeN((void *)wpd->active.lock);
- if (wpd->mirror.lock)
- MEM_freeN((void *)wpd->mirror.lock);
- if (wpd->precomputed_weight)
- MEM_freeN(wpd->precomputed_weight);
-
- MEM_freeN(wpd);
- }
-
- /* and particles too */
- if (ob->particlesystem.first) {
- ParticleSystem *psys;
- int i;
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- for (i = 0; i < PSYS_TOT_VG; i++) {
- if (psys->vgroup[i] == ob->actdef) {
- psys->recalc |= ID_RECALC_PSYS_RESET;
- break;
- }
- }
- }
- }
-
- DEG_id_tag_update(ob->data, 0);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- sculpt_cache_free(ob->sculpt->cache);
- ob->sculpt->cache = NULL;
+ Object *ob = CTX_data_active_object(C);
+ struct WPaintData *wpd = paint_stroke_mode_data(stroke);
+
+ if (wpd) {
+ if (wpd->defbase_sel)
+ MEM_freeN((void *)wpd->defbase_sel);
+ if (wpd->vgroup_validmap)
+ MEM_freeN((void *)wpd->vgroup_validmap);
+ if (wpd->lock_flags)
+ MEM_freeN((void *)wpd->lock_flags);
+ if (wpd->active.lock)
+ MEM_freeN((void *)wpd->active.lock);
+ if (wpd->mirror.lock)
+ MEM_freeN((void *)wpd->mirror.lock);
+ if (wpd->precomputed_weight)
+ MEM_freeN(wpd->precomputed_weight);
+
+ MEM_freeN(wpd);
+ }
+
+ /* and particles too */
+ if (ob->particlesystem.first) {
+ ParticleSystem *psys;
+ int i;
+
+ for (psys = ob->particlesystem.first; psys; psys = psys->next) {
+ for (i = 0; i < PSYS_TOT_VG; i++) {
+ if (psys->vgroup[i] == ob->actdef) {
+ psys->recalc |= ID_RECALC_PSYS_RESET;
+ break;
+ }
+ }
+ }
+ }
+
+ DEG_id_tag_update(ob->data, 0);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ sculpt_cache_free(ob->sculpt->cache);
+ ob->sculpt->cache = NULL;
}
-
static int wpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- int retval;
+ int retval;
- op->customdata = paint_stroke_new(
- C, op, sculpt_stroke_get_location, wpaint_stroke_test_start,
- wpaint_stroke_update_step, NULL,
- wpaint_stroke_done, event->type);
+ op->customdata = paint_stroke_new(C,
+ op,
+ sculpt_stroke_get_location,
+ wpaint_stroke_test_start,
+ wpaint_stroke_update_step,
+ NULL,
+ wpaint_stroke_done,
+ event->type);
- if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
- paint_stroke_data_free(op);
- return OPERATOR_FINISHED;
- }
- /* add modal handler */
- WM_event_add_modal_handler(C, op);
+ if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
+ paint_stroke_data_free(op);
+ return OPERATOR_FINISHED;
+ }
+ /* add modal handler */
+ WM_event_add_modal_handler(C, op);
- OPERATOR_RETVAL_CHECK(retval);
- BLI_assert(retval == OPERATOR_RUNNING_MODAL);
+ OPERATOR_RETVAL_CHECK(retval);
+ BLI_assert(retval == OPERATOR_RUNNING_MODAL);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static int wpaint_exec(bContext *C, wmOperator *op)
{
- op->customdata = paint_stroke_new(
- C, op, sculpt_stroke_get_location, wpaint_stroke_test_start,
- wpaint_stroke_update_step, NULL,
- wpaint_stroke_done, 0);
+ op->customdata = paint_stroke_new(C,
+ op,
+ sculpt_stroke_get_location,
+ wpaint_stroke_test_start,
+ wpaint_stroke_update_step,
+ NULL,
+ wpaint_stroke_done,
+ 0);
- /* frees op->customdata */
- paint_stroke_exec(C, op);
+ /* frees op->customdata */
+ paint_stroke_exec(C, op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
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);
- ob->sculpt->cache = NULL;
- }
+ Object *ob = CTX_data_active_object(C);
+ if (ob->sculpt->cache) {
+ sculpt_cache_free(ob->sculpt->cache);
+ ob->sculpt->cache = NULL;
+ }
- paint_stroke_cancel(C, op);
+ paint_stroke_cancel(C, op);
}
void PAINT_OT_weight_paint(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Weight Paint";
- ot->idname = "PAINT_OT_weight_paint";
- ot->description = "Paint a stroke in the current vertex group's weights";
+ /* identifiers */
+ ot->name = "Weight Paint";
+ ot->idname = "PAINT_OT_weight_paint";
+ ot->description = "Paint a stroke in the current vertex group's weights";
- /* api callbacks */
- ot->invoke = wpaint_invoke;
- ot->modal = paint_stroke_modal;
- ot->exec = wpaint_exec;
- ot->poll = weight_paint_poll;
- ot->cancel = wpaint_cancel;
+ /* api callbacks */
+ ot->invoke = wpaint_invoke;
+ ot->modal = paint_stroke_modal;
+ ot->exec = wpaint_exec;
+ ot->poll = weight_paint_poll;
+ ot->cancel = wpaint_cancel;
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
- paint_stroke_operator_properties(ot);
+ paint_stroke_operator_properties(ot);
}
/* ************ set / clear vertex paint mode ********** */
@@ -2392,64 +2446,62 @@ void PAINT_OT_weight_paint(wmOperatorType *ot)
*/
static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- Object *ob = CTX_data_active_object(C);
- const int mode_flag = OB_MODE_VERTEX_PAINT;
- const bool is_mode_set = (ob->mode & mode_flag) != 0;
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = scene->toolsettings;
+ Main *bmain = CTX_data_main(C);
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ Object *ob = CTX_data_active_object(C);
+ const int mode_flag = OB_MODE_VERTEX_PAINT;
+ const bool is_mode_set = (ob->mode & mode_flag) != 0;
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
- if (!is_mode_set) {
- if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
- return OPERATOR_CANCELLED;
- }
- }
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
- Mesh *me = BKE_mesh_from_object(ob);
+ Mesh *me = BKE_mesh_from_object(ob);
- /* toggle: end vpaint */
- if (is_mode_set) {
- ED_object_vpaintmode_exit_ex(ob);
- }
- else {
- Depsgraph *depsgraph = CTX_data_depsgraph_on_load(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);
- }
+ /* toggle: end vpaint */
+ if (is_mode_set) {
+ ED_object_vpaintmode_exit_ex(ob);
+ }
+ else {
+ Depsgraph *depsgraph = CTX_data_depsgraph_on_load(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);
+ }
- BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+ BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
- /* update modifier stack for mapping requirements */
- DEG_id_tag_update(&me->id, 0);
+ /* update modifier stack for mapping requirements */
+ DEG_id_tag_update(&me->id, 0);
- WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
- WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
+ WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
- WM_toolsystem_update_from_context_view3d(C);
+ WM_toolsystem_update_from_context_view3d(C);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PAINT_OT_vertex_paint_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Vertex Paint Mode";
- ot->idname = "PAINT_OT_vertex_paint_toggle";
- ot->description = "Toggle the vertex paint mode in 3D view";
+ /* identifiers */
+ ot->name = "Vertex Paint Mode";
+ ot->idname = "PAINT_OT_vertex_paint_toggle";
+ ot->description = "Toggle the vertex paint mode in 3D view";
- /* api callbacks */
- ot->exec = vpaint_mode_toggle_exec;
- ot->poll = paint_poll_test;
+ /* api callbacks */
+ ot->exec = vpaint_mode_toggle_exec;
+ ot->poll = paint_poll_test;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
}
-
-
/* ********************** vertex paint operator ******************* */
/* Implementation notes:
@@ -2471,815 +2523,847 @@ void PAINT_OT_vertex_paint_toggle(wmOperatorType *ot)
*/
typedef struct PolyFaceMap {
- struct PolyFaceMap *next, *prev;
- int facenr;
+ struct PolyFaceMap *next, *prev;
+ int facenr;
} PolyFaceMap;
struct VPaintData {
- ViewContext vc;
- struct NormalAnglePrecalc normal_angle_precalc;
+ ViewContext vc;
+ struct NormalAnglePrecalc normal_angle_precalc;
- uint paintcol;
+ uint paintcol;
- struct VertProjHandle *vp_handle;
- struct CoNo *vertexcosnos;
+ struct VertProjHandle *vp_handle;
+ struct CoNo *vertexcosnos;
- /* modify 'me->mcol' directly, since the derived mesh is drawing from this
- * array, otherwise we need to refresh the modifier stack */
- bool use_fast_update;
+ /* modify 'me->mcol' directly, since the derived mesh is drawing from this
+ * array, otherwise we need to refresh the modifier stack */
+ bool use_fast_update;
- /* loops tagged as having been painted, to apply shared vertex color
- * blending only to modified loops */
- bool *mlooptag;
+ /* loops tagged as having been painted, to apply shared vertex color
+ * blending only to modified loops */
+ bool *mlooptag;
- bool is_texbrush;
+ bool is_texbrush;
- /* Special storage for smear brush, avoid feedback loop - update each step. */
- struct {
- uint *color_prev;
- uint *color_curr;
- } smear;
+ /* Special storage for smear brush, avoid feedback loop - update each step. */
+ struct {
+ uint *color_prev;
+ uint *color_curr;
+ } smear;
};
static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const float mouse[2])
{
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = scene->toolsettings;
- struct PaintStroke *stroke = op->customdata;
- VPaint *vp = ts->vpaint;
- Brush *brush = BKE_paint_brush(&vp->paint);
- struct VPaintData *vpd;
- Object *ob = CTX_data_active_object(C);
- Mesh *me;
- SculptSession *ss = ob->sculpt;
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
-
- /* context checks could be a poll() */
- me = BKE_mesh_from_object(ob);
- if (me == NULL || me->totpoly == 0)
- return false;
-
- ED_mesh_color_ensure(me, NULL);
- if (me->mloopcol == NULL)
- return false;
-
- /* make mode data storage */
- vpd = MEM_callocN(sizeof(*vpd), "VPaintData");
- paint_stroke_set_mode_data(stroke, vpd);
- ED_view3d_viewcontext_init(C, &vpd->vc);
- view_angle_limits_init(
- &vpd->normal_angle_precalc, vp->paint.brush->falloff_angle,
- (vp->paint.brush->flag & BRUSH_FRONTFACE_FALLOFF) != 0);
-
- vpd->paintcol = vpaint_get_current_col(scene, vp, (RNA_enum_get(op->ptr, "mode") == BRUSH_STROKE_INVERT));
-
- vpd->is_texbrush = !(brush->vertexpaint_tool == VPAINT_TOOL_BLUR) && brush->mtex.tex;
-
- /* are we painting onto a modified mesh?,
- * if not we can skip face map trickiness */
- if (vertex_paint_use_fast_update_check(ob)) {
- vpd->use_fast_update = true;
-/* printf("Fast update!\n");*/
- }
- else {
- vpd->use_fast_update = false;
-/* printf("No fast update!\n");*/
- }
-
- /* to keep tracked of modified loops for shared vertex color blending */
- if (brush->vertexpaint_tool == VPAINT_TOOL_BLUR) {
- vpd->mlooptag = MEM_mallocN(sizeof(bool) * me->totloop, "VPaintData mlooptag");
- }
-
- if (brush->vertexpaint_tool == VPAINT_TOOL_SMEAR) {
- vpd->smear.color_prev = MEM_mallocN(sizeof(uint) * me->totloop, __func__);
- memcpy(vpd->smear.color_prev, me->mloopcol, sizeof(uint) * me->totloop);
- vpd->smear.color_curr = MEM_dupallocN(vpd->smear.color_prev);
- }
-
- /* Create projection handle */
- if (vpd->is_texbrush) {
- ob->sculpt->building_vp_handle = true;
- vpd->vp_handle = ED_vpaint_proj_handle_create(depsgraph, scene, ob, &vpd->vertexcosnos);
- ob->sculpt->building_vp_handle = false;
- }
-
- /* If not previously created, create vertex/weight paint mode session data */
- vertex_paint_init_stroke(depsgraph, scene, ob);
- vwpaint_update_cache_invariants(C, vp, ss, op, mouse);
- vertex_paint_init_session_data(ts, ob);
-
- if (ob->sculpt->mode.vpaint.previous_color != NULL) {
- memset(ob->sculpt->mode.vpaint.previous_color, 0, sizeof(uint) * me->totloop);
- }
-
- return 1;
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
+ struct PaintStroke *stroke = op->customdata;
+ VPaint *vp = ts->vpaint;
+ Brush *brush = BKE_paint_brush(&vp->paint);
+ struct VPaintData *vpd;
+ Object *ob = CTX_data_active_object(C);
+ Mesh *me;
+ SculptSession *ss = ob->sculpt;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
+ /* context checks could be a poll() */
+ me = BKE_mesh_from_object(ob);
+ if (me == NULL || me->totpoly == 0)
+ return false;
+
+ ED_mesh_color_ensure(me, NULL);
+ if (me->mloopcol == NULL)
+ return false;
+
+ /* make mode data storage */
+ vpd = MEM_callocN(sizeof(*vpd), "VPaintData");
+ paint_stroke_set_mode_data(stroke, vpd);
+ ED_view3d_viewcontext_init(C, &vpd->vc);
+ view_angle_limits_init(&vpd->normal_angle_precalc,
+ vp->paint.brush->falloff_angle,
+ (vp->paint.brush->flag & BRUSH_FRONTFACE_FALLOFF) != 0);
+
+ vpd->paintcol = vpaint_get_current_col(
+ scene, vp, (RNA_enum_get(op->ptr, "mode") == BRUSH_STROKE_INVERT));
+
+ vpd->is_texbrush = !(brush->vertexpaint_tool == VPAINT_TOOL_BLUR) && brush->mtex.tex;
+
+ /* are we painting onto a modified mesh?,
+ * if not we can skip face map trickiness */
+ if (vertex_paint_use_fast_update_check(ob)) {
+ vpd->use_fast_update = true;
+ /* printf("Fast update!\n");*/
+ }
+ else {
+ vpd->use_fast_update = false;
+ /* printf("No fast update!\n");*/
+ }
+
+ /* to keep tracked of modified loops for shared vertex color blending */
+ if (brush->vertexpaint_tool == VPAINT_TOOL_BLUR) {
+ vpd->mlooptag = MEM_mallocN(sizeof(bool) * me->totloop, "VPaintData mlooptag");
+ }
+
+ if (brush->vertexpaint_tool == VPAINT_TOOL_SMEAR) {
+ vpd->smear.color_prev = MEM_mallocN(sizeof(uint) * me->totloop, __func__);
+ memcpy(vpd->smear.color_prev, me->mloopcol, sizeof(uint) * me->totloop);
+ vpd->smear.color_curr = MEM_dupallocN(vpd->smear.color_prev);
+ }
+
+ /* Create projection handle */
+ if (vpd->is_texbrush) {
+ ob->sculpt->building_vp_handle = true;
+ vpd->vp_handle = ED_vpaint_proj_handle_create(depsgraph, scene, ob, &vpd->vertexcosnos);
+ ob->sculpt->building_vp_handle = false;
+ }
+
+ /* If not previously created, create vertex/weight paint mode session data */
+ vertex_paint_init_stroke(depsgraph, scene, ob);
+ vwpaint_update_cache_invariants(C, vp, ss, op, mouse);
+ vertex_paint_init_session_data(ts, ob);
+
+ if (ob->sculpt->mode.vpaint.previous_color != NULL) {
+ memset(ob->sculpt->mode.vpaint.previous_color, 0, sizeof(uint) * me->totloop);
+ }
+
+ return 1;
}
static void do_vpaint_brush_calc_average_color_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict UNUSED(tls))
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
- const bool has_grids = (pbvh_type == PBVH_GRIDS);
- const struct SculptVertexPaintGeomMap *gmap = &ss->mode.vpaint.gmap;
-
- StrokeCache *cache = ss->cache;
- uint *lcol = data->lcol;
- char *col;
- const bool use_vert_sel = (data->me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
-
- struct VPaintAverageAccum *accum = (struct VPaintAverageAccum *)data->custom_data + n;
- accum->len = 0;
- memset(accum->value, 0, sizeof(accum->value));
-
- SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn =
- sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
-
- /* For each vertex */
- PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- /* Test to see if the vertex coordinates are within the spherical brush region. */
- if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
- if (BKE_brush_curve_strength(data->brush, 0.0, cache->radius) > 0.0) {
- /* If the vertex is selected for painting. */
- const MVert *mv = &data->me->mvert[v_index];
- if (!use_vert_sel || mv->flag & SELECT) {
- accum->len += gmap->vert_to_loop[v_index].count;
- /* if a vertex is within the brush region, then add it's color to the blend. */
- for (int j = 0; j < gmap->vert_to_loop[v_index].count; j++) {
- const int l_index = gmap->vert_to_loop[v_index].indices[j];
- col = (char *)(&lcol[l_index]);
- /* Color is squared to compensate the sqrt color encoding. */
- accum->value[0] += col[0] * col[0];
- accum->value[1] += col[1] * col[1];
- accum->value[2] += col[2] * col[2];
- }
- }
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
-}
-
-static float tex_color_alpha_ubyte(
- SculptThreadedTaskData *data, const float v_co[3],
- uint *r_color)
-{
- float rgba[4];
- float rgba_br[3];
- tex_color_alpha(data->vp, &data->vpd->vc, v_co, rgba);
- rgb_uchar_to_float(rgba_br, (const uchar *)&data->vpd->paintcol);
- mul_v3_v3(rgba_br, rgba);
- rgb_float_to_uchar((uchar *)r_color, rgba_br);
- return rgba[3];
-}
-
-static void do_vpaint_brush_draw_task_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict UNUSED(tls))
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
- const bool has_grids = (pbvh_type == PBVH_GRIDS);
- const struct SculptVertexPaintGeomMap *gmap = &ss->mode.vpaint.gmap;
-
- const Brush *brush = data->brush;
- const StrokeCache *cache = ss->cache;
- uint *lcol = data->lcol;
- const Scene *scene = CTX_data_scene(data->C);
- float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
- get_brush_alpha_data(scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
- const bool use_normal = vwpaint_use_normal(data->vp);
- const bool use_vert_sel = (data->me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
- 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(ss, &test, data->brush->falloff_shape);
- const float *sculpt_normal_frontface =
- sculpt_brush_frontface_normal_from_falloff_shape(ss, data->brush->falloff_shape);
-
- /* For each vertex */
- PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- /* Test to see if the vertex coordinates are within the spherical brush region. */
- if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- /* Note: Grids are 1:1 with corners (aka loops).
- * For grid based pbvh, take the vert whose loop corresponds to the current grid.
- * Otherwise, take the current vert. */
- const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
- const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
- const MVert *mv = &data->me->mvert[v_index];
-
- /* If the vertex is selected for painting. */
- if (!use_vert_sel || mv->flag & SELECT) {
- /* Calc the dot prod. between ray norm on surf and current vert
- * (ie splash prevention factor), and only paint front facing verts. */
- float brush_strength = cache->bstrength;
- const float angle_cos = (use_normal && vd.no) ?
- dot_vf3vs3(sculpt_normal_frontface, vd.no) : 1.0f;
- if (((brush->flag & BRUSH_FRONTFACE) == 0 ||
- (angle_cos > 0.0f)) &&
- ((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
- view_angle_limits_apply_falloff(&data->vpd->normal_angle_precalc, angle_cos, &brush_strength)))
- {
- const float brush_fade = BKE_brush_curve_strength(brush, sqrtf(test.dist), cache->radius);
- uint color_final = data->vpd->paintcol;
-
- /* If we're painting with a texture, sample the texture color and alpha. */
- float tex_alpha = 1.0;
- if (data->vpd->is_texbrush) {
- /* Note: we may want to paint alpha as vertex color alpha. */
- tex_alpha = tex_color_alpha_ubyte(
- data, data->vpd->vertexcosnos[v_index].co,
- &color_final);
- }
- /* For each poly owning this vert, paint each loop belonging to this vert. */
- for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
- const int p_index = gmap->vert_to_poly[v_index].indices[j];
- const int l_index = gmap->vert_to_loop[v_index].indices[j];
- BLI_assert(data->me->mloop[l_index].v == v_index);
- const MPoly *mp = &data->me->mpoly[p_index];
- if (!use_face_sel || mp->flag & ME_FACE_SEL) {
- uint color_orig = 0; /* unused when array is NULL */
- if (ss->mode.vpaint.previous_color != NULL) {
- /* Get the previous loop color */
- if (ss->mode.vpaint.previous_color[l_index] == 0) {
- ss->mode.vpaint.previous_color[l_index] = lcol[l_index];
- }
- color_orig = ss->mode.vpaint.previous_color[l_index];
- }
- const float final_alpha =
- 255 * brush_fade * brush_strength *
- tex_alpha * brush_alpha_pressure * grid_alpha;
-
- /* Mix the new color with the original based on final_alpha. */
- lcol[l_index] = vpaint_blend(
- data->vp, lcol[l_index], color_orig, color_final,
- final_alpha, 255 * brush_strength);
- }
- }
- }
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
-}
-
-static void do_vpaint_brush_blur_task_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict UNUSED(tls))
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
- const bool has_grids = (pbvh_type == PBVH_GRIDS);
-
- Scene *scene = CTX_data_scene(data->C);
- const struct SculptVertexPaintGeomMap *gmap = &ss->mode.vpaint.gmap;
- const Brush *brush = data->brush;
- const StrokeCache *cache = ss->cache;
- uint *lcol = data->lcol;
- float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
- get_brush_alpha_data(scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
- const bool use_normal = vwpaint_use_normal(data->vp);
- const bool use_vert_sel = (data->me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
- 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(ss, &test, data->brush->falloff_shape);
- const float *sculpt_normal_frontface =
- sculpt_brush_frontface_normal_from_falloff_shape(ss, data->brush->falloff_shape);
-
- /* For each vertex */
- PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- /* Test to see if the vertex coordinates are within the spherical brush region. */
- if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- /* For grid based pbvh, take the vert whose loop corresponds to the current grid.
- * Otherwise, take the current vert. */
- const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
- const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
- const MVert *mv = &data->me->mvert[v_index];
-
- /* If the vertex is selected for painting. */
- if (!use_vert_sel || mv->flag & SELECT) {
- float brush_strength = cache->bstrength;
- const float angle_cos = (use_normal && vd.no) ?
- dot_vf3vs3(sculpt_normal_frontface, vd.no) : 1.0f;
- if (((brush->flag & BRUSH_FRONTFACE) == 0 ||
- (angle_cos > 0.0f)) &&
- ((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
- view_angle_limits_apply_falloff(&data->vpd->normal_angle_precalc, angle_cos, &brush_strength)))
- {
- const float brush_fade = BKE_brush_curve_strength(brush, sqrtf(test.dist), cache->radius);
-
- /* Get the average poly color */
- uint color_final = 0;
- int total_hit_loops = 0;
- uint blend[4] = {0};
- for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
- int p_index = gmap->vert_to_poly[v_index].indices[j];
- const MPoly *mp = &data->me->mpoly[p_index];
- if (!use_face_sel || mp->flag & ME_FACE_SEL) {
- total_hit_loops += mp->totloop;
- for (int k = 0; k < mp->totloop; k++) {
- const uint l_index = mp->loopstart + k;
- const char *col = (const char *)(&lcol[l_index]);
- /* Color is squared to compensate the sqrt color encoding. */
- blend[0] += (uint)col[0] * (uint)col[0];
- blend[1] += (uint)col[1] * (uint)col[1];
- blend[2] += (uint)col[2] * (uint)col[2];
- blend[3] += (uint)col[3] * (uint)col[3];
- }
- }
- }
- if (total_hit_loops != 0) {
- /* Use rgb^2 color averaging. */
- char *col = (char *)(&color_final);
- col[0] = round_fl_to_uchar(sqrtf(divide_round_i(blend[0], total_hit_loops)));
- col[1] = round_fl_to_uchar(sqrtf(divide_round_i(blend[1], total_hit_loops)));
- col[2] = round_fl_to_uchar(sqrtf(divide_round_i(blend[2], total_hit_loops)));
- col[3] = round_fl_to_uchar(sqrtf(divide_round_i(blend[3], total_hit_loops)));
-
- /* For each poly owning this vert,
- * paint each loop belonging to this vert. */
- for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
- const int p_index = gmap->vert_to_poly[v_index].indices[j];
- const int l_index = gmap->vert_to_loop[v_index].indices[j];
- BLI_assert(data->me->mloop[l_index].v == v_index);
- const MPoly *mp = &data->me->mpoly[p_index];
- if (!use_face_sel || mp->flag & ME_FACE_SEL) {
- uint color_orig = 0; /* unused when array is NULL */
- if (ss->mode.vpaint.previous_color != NULL) {
- /* Get the previous loop color */
- if (ss->mode.vpaint.previous_color[l_index] == 0) {
- ss->mode.vpaint.previous_color[l_index] = lcol[l_index];
- }
- color_orig = ss->mode.vpaint.previous_color[l_index];
- }
- const float final_alpha =
- 255 * brush_fade * brush_strength *
- brush_alpha_pressure * grid_alpha;
- /* Mix the new color with the original
- * based on the brush strength and the curve. */
- lcol[l_index] = vpaint_blend(
- data->vp, lcol[l_index], color_orig, *((uint *)col),
- final_alpha, 255 * brush_strength);
- }
- }
- }
- }
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
-}
-
-static void do_vpaint_brush_smear_task_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict UNUSED(tls))
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
- const bool has_grids = (pbvh_type == PBVH_GRIDS);
-
- Scene *scene = CTX_data_scene(data->C);
- const struct SculptVertexPaintGeomMap *gmap = &ss->mode.vpaint.gmap;
- const Brush *brush = data->brush;
- const StrokeCache *cache = ss->cache;
- uint *lcol = data->lcol;
- float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
- get_brush_alpha_data(scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
- float brush_dir[3];
- const bool use_normal = vwpaint_use_normal(data->vp);
- const bool use_vert_sel = (data->me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
- const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
-
- sub_v3_v3v3(brush_dir, cache->location, cache->last_location);
- project_plane_v3_v3v3(brush_dir, brush_dir, cache->view_normal);
-
- 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(ss, &test, data->brush->falloff_shape);
- const float *sculpt_normal_frontface =
- sculpt_brush_frontface_normal_from_falloff_shape(ss, data->brush->falloff_shape);
-
- /* For each vertex */
- PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- /* Test to see if the vertex coordinates are within the spherical brush region. */
- if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- /* For grid based pbvh, take the vert whose loop corresponds to the current grid.
- * Otherwise, take the current vert. */
- const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
- const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
- const MVert *mv_curr = &data->me->mvert[v_index];
-
- /* if the vertex is selected for painting. */
- if (!use_vert_sel || mv_curr->flag & SELECT) {
- /* Calc the dot prod. between ray norm on surf and current vert
- * (ie splash prevention factor), and only paint front facing verts. */
- float brush_strength = cache->bstrength;
- const float angle_cos = (use_normal && vd.no) ?
- dot_vf3vs3(sculpt_normal_frontface, vd.no) : 1.0f;
- if (((brush->flag & BRUSH_FRONTFACE) == 0 ||
- (angle_cos > 0.0f)) &&
- ((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
- view_angle_limits_apply_falloff(&data->vpd->normal_angle_precalc, angle_cos, &brush_strength)))
- {
- const float brush_fade = BKE_brush_curve_strength(brush, sqrtf(test.dist), cache->radius);
-
- bool do_color = false;
- /* Minimum dot product between brush direction and current
- * to neighbor direction is 0.0, meaning orthogonal. */
- float stroke_dot_max = 0.0f;
-
- /* Get the color of the loop in the opposite
- * direction of the brush movement */
- uint color_final = 0;
- for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
- const int p_index = gmap->vert_to_poly[v_index].indices[j];
- const int l_index = gmap->vert_to_loop[v_index].indices[j];
- BLI_assert(data->me->mloop[l_index].v == v_index);
- UNUSED_VARS_NDEBUG(l_index);
- const MPoly *mp = &data->me->mpoly[p_index];
- if (!use_face_sel || mp->flag & ME_FACE_SEL) {
- const MLoop *ml_other = &data->me->mloop[mp->loopstart];
- for (int k = 0; k < mp->totloop; k++, ml_other++) {
- const uint v_other_index = ml_other->v;
- if (v_other_index != v_index) {
- const MVert *mv_other = &data->me->mvert[v_other_index];
-
- /* Get the direction from the
- * selected vert to the neighbor. */
- float other_dir[3];
- sub_v3_v3v3(other_dir, mv_curr->co, mv_other->co);
- project_plane_v3_v3v3(other_dir, other_dir, cache->view_normal);
-
- normalize_v3(other_dir);
-
- const float stroke_dot = dot_v3v3(other_dir, brush_dir);
-
- if (stroke_dot > stroke_dot_max) {
- stroke_dot_max = stroke_dot;
- color_final = data->vpd->smear.color_prev[mp->loopstart + k];
- do_color = true;
- }
- }
- }
- }
- }
-
- if (do_color) {
- const float final_alpha =
- 255 * brush_fade * brush_strength *
- brush_alpha_pressure * grid_alpha;
-
- /* For each poly owning this vert,
- * paint each loop belonging to this vert. */
- for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
- const int p_index = gmap->vert_to_poly[v_index].indices[j];
- const int l_index = gmap->vert_to_loop[v_index].indices[j];
- BLI_assert(data->me->mloop[l_index].v == v_index);
- const MPoly *mp = &data->me->mpoly[p_index];
- if (!use_face_sel || mp->flag & ME_FACE_SEL) {
- /* Get the previous loop color */
- uint color_orig = 0; /* unused when array is NULL */
- if (ss->mode.vpaint.previous_color != NULL) {
- /* Get the previous loop color */
- if (ss->mode.vpaint.previous_color[l_index] == 0) {
- ss->mode.vpaint.previous_color[l_index] = lcol[l_index];
- }
- color_orig = ss->mode.vpaint.previous_color[l_index];
- }
- /* Mix the new color with the original
- * based on the brush strength and the curve. */
- lcol[l_index] = vpaint_blend(
- data->vp, lcol[l_index], color_orig, color_final,
- final_alpha, 255 * brush_strength);
-
- data->vpd->smear.color_curr[l_index] = lcol[l_index];
- }
- }
- }
- }
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
- }
-}
-
-static void calculate_average_color(SculptThreadedTaskData *data, PBVHNode **UNUSED(nodes), int totnode)
-{
- struct VPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__);
- data->custom_data = accum;
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&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};
- uchar blend[4] = {0};
- for (int i = 0; i < totnode; i++) {
- accum_len += accum[i].len;
- accum_value[0] += accum[i].value[0];
- accum_value[1] += accum[i].value[1];
- accum_value[2] += accum[i].value[2];
- }
- if (accum_len != 0) {
- blend[0] = round_fl_to_uchar(sqrtf(divide_round_i(accum_value[0], accum_len)));
- blend[1] = round_fl_to_uchar(sqrtf(divide_round_i(accum_value[1], accum_len)));
- blend[2] = round_fl_to_uchar(sqrtf(divide_round_i(accum_value[2], accum_len)));
- blend[3] = 255;
- data->vpd->paintcol = *((uint *)blend);
- }
-
- MEM_SAFE_FREE(data->custom_data); /* 'accum' */
-}
-
-static void vpaint_paint_leaves(
- bContext *C, Sculpt *sd, VPaint *vp, struct VPaintData *vpd,
- Object *ob, Mesh *me, PBVHNode **nodes, int totnode)
-{
- const Brush *brush = ob->sculpt->cache->brush;
-
- SculptThreadedTaskData data = {
- .C = C, .sd = sd, .ob = ob, .brush = brush, .nodes = nodes, .vp = vp, .vpd = vpd,
- .lcol = (uint *)me->mloopcol, .me = me,
- };
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- switch ((eBrushVertexPaintTool)brush->vertexpaint_tool) {
- case VPAINT_TOOL_AVERAGE:
- calculate_average_color(&data, nodes, totnode);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_vpaint_brush_draw_task_cb_ex,
- &settings);
- break;
- case VPAINT_TOOL_BLUR:
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_vpaint_brush_blur_task_cb_ex,
- &settings);
- break;
- case VPAINT_TOOL_SMEAR:
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_vpaint_brush_smear_task_cb_ex,
- &settings);
- break;
- case VPAINT_TOOL_DRAW:
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_vpaint_brush_draw_task_cb_ex,
- &settings);
- break;
- }
-}
-
-static void vpaint_do_paint(
- bContext *C, Sculpt *sd, VPaint *vp, struct VPaintData *vpd,
- Object *ob, Mesh *me, Brush *brush, const char symm, const int axis, const int i, const float angle)
-{
- SculptSession *ss = ob->sculpt;
- ss->cache->radial_symmetry_pass = i;
- sculpt_cache_calc_brushdata_symm(ss->cache, symm, axis, angle);
-
- int totnode;
- PBVHNode **nodes = vwpaint_pbvh_gather_generic(ob, vp, sd, brush, &totnode);
-
- /* Paint those leaves. */
- vpaint_paint_leaves(C, sd, vp, vpd, ob, me, nodes, totnode);
-
- if (nodes) {
- MEM_freeN(nodes);
- }
-}
-
-static void vpaint_do_radial_symmetry(
- bContext *C, Sculpt *sd, VPaint *vp, struct VPaintData *vpd, Object *ob, Mesh *me,
- Brush *brush, const char symm, const int axis)
-{
- for (int i = 1; i < vp->radial_symm[axis - 'X']; i++) {
- const float angle = (2.0 * M_PI) * i / vp->radial_symm[axis - 'X'];
- vpaint_do_paint(C, sd, vp, vpd, ob, me, brush, symm, axis, i, angle);
- }
+ void *__restrict userdata, const int n, const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
+ const bool has_grids = (pbvh_type == PBVH_GRIDS);
+ const struct SculptVertexPaintGeomMap *gmap = &ss->mode.vpaint.gmap;
+
+ StrokeCache *cache = ss->cache;
+ uint *lcol = data->lcol;
+ char *col;
+ const bool use_vert_sel = (data->me->editflag &
+ (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
+
+ struct VPaintAverageAccum *accum = (struct VPaintAverageAccum *)data->custom_data + n;
+ accum->len = 0;
+ memset(accum->value, 0, sizeof(accum->value));
+
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ ss, &test, data->brush->falloff_shape);
+
+ /* For each vertex */
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ /* Test to see if the vertex coordinates are within the spherical brush region. */
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v :
+ vd.vert_indices[vd.i];
+ if (BKE_brush_curve_strength(data->brush, 0.0, cache->radius) > 0.0) {
+ /* If the vertex is selected for painting. */
+ const MVert *mv = &data->me->mvert[v_index];
+ if (!use_vert_sel || mv->flag & SELECT) {
+ accum->len += gmap->vert_to_loop[v_index].count;
+ /* if a vertex is within the brush region, then add it's color to the blend. */
+ for (int j = 0; j < gmap->vert_to_loop[v_index].count; j++) {
+ const int l_index = gmap->vert_to_loop[v_index].indices[j];
+ col = (char *)(&lcol[l_index]);
+ /* Color is squared to compensate the sqrt color encoding. */
+ accum->value[0] += col[0] * col[0];
+ accum->value[1] += col[1] * col[1];
+ accum->value[2] += col[2] * col[2];
+ }
+ }
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static float tex_color_alpha_ubyte(SculptThreadedTaskData *data,
+ const float v_co[3],
+ uint *r_color)
+{
+ float rgba[4];
+ float rgba_br[3];
+ tex_color_alpha(data->vp, &data->vpd->vc, v_co, rgba);
+ rgb_uchar_to_float(rgba_br, (const uchar *)&data->vpd->paintcol);
+ mul_v3_v3(rgba_br, rgba);
+ rgb_float_to_uchar((uchar *)r_color, rgba_br);
+ return rgba[3];
+}
+
+static void do_vpaint_brush_draw_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
+ const bool has_grids = (pbvh_type == PBVH_GRIDS);
+ const struct SculptVertexPaintGeomMap *gmap = &ss->mode.vpaint.gmap;
+
+ const Brush *brush = data->brush;
+ const StrokeCache *cache = ss->cache;
+ uint *lcol = data->lcol;
+ const Scene *scene = CTX_data_scene(data->C);
+ float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
+ get_brush_alpha_data(
+ scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
+ const bool use_normal = vwpaint_use_normal(data->vp);
+ const bool use_vert_sel = (data->me->editflag &
+ (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
+ 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(
+ ss, &test, data->brush->falloff_shape);
+ const float *sculpt_normal_frontface = sculpt_brush_frontface_normal_from_falloff_shape(
+ ss, data->brush->falloff_shape);
+
+ /* For each vertex */
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ /* Test to see if the vertex coordinates are within the spherical brush region. */
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ /* Note: Grids are 1:1 with corners (aka loops).
+ * For grid based pbvh, take the vert whose loop corresponds to the current grid.
+ * Otherwise, take the current vert. */
+ const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v :
+ vd.vert_indices[vd.i];
+ const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
+ const MVert *mv = &data->me->mvert[v_index];
+
+ /* If the vertex is selected for painting. */
+ if (!use_vert_sel || mv->flag & SELECT) {
+ /* Calc the dot prod. between ray norm on surf and current vert
+ * (ie splash prevention factor), and only paint front facing verts. */
+ float brush_strength = cache->bstrength;
+ const float angle_cos = (use_normal && vd.no) ?
+ dot_vf3vs3(sculpt_normal_frontface, vd.no) :
+ 1.0f;
+ if (((brush->flag & BRUSH_FRONTFACE) == 0 || (angle_cos > 0.0f)) &&
+ ((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
+ view_angle_limits_apply_falloff(
+ &data->vpd->normal_angle_precalc, angle_cos, &brush_strength))) {
+ const float brush_fade = BKE_brush_curve_strength(
+ brush, sqrtf(test.dist), cache->radius);
+ uint color_final = data->vpd->paintcol;
+
+ /* If we're painting with a texture, sample the texture color and alpha. */
+ float tex_alpha = 1.0;
+ if (data->vpd->is_texbrush) {
+ /* Note: we may want to paint alpha as vertex color alpha. */
+ tex_alpha = tex_color_alpha_ubyte(
+ data, data->vpd->vertexcosnos[v_index].co, &color_final);
+ }
+ /* For each poly owning this vert, paint each loop belonging to this vert. */
+ for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
+ const int p_index = gmap->vert_to_poly[v_index].indices[j];
+ const int l_index = gmap->vert_to_loop[v_index].indices[j];
+ BLI_assert(data->me->mloop[l_index].v == v_index);
+ const MPoly *mp = &data->me->mpoly[p_index];
+ if (!use_face_sel || mp->flag & ME_FACE_SEL) {
+ uint color_orig = 0; /* unused when array is NULL */
+ if (ss->mode.vpaint.previous_color != NULL) {
+ /* Get the previous loop color */
+ if (ss->mode.vpaint.previous_color[l_index] == 0) {
+ ss->mode.vpaint.previous_color[l_index] = lcol[l_index];
+ }
+ color_orig = ss->mode.vpaint.previous_color[l_index];
+ }
+ const float final_alpha = 255 * brush_fade * brush_strength * tex_alpha *
+ brush_alpha_pressure * grid_alpha;
+
+ /* Mix the new color with the original based on final_alpha. */
+ lcol[l_index] = vpaint_blend(data->vp,
+ lcol[l_index],
+ color_orig,
+ color_final,
+ final_alpha,
+ 255 * brush_strength);
+ }
+ }
+ }
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static void do_vpaint_brush_blur_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
+ const bool has_grids = (pbvh_type == PBVH_GRIDS);
+
+ Scene *scene = CTX_data_scene(data->C);
+ const struct SculptVertexPaintGeomMap *gmap = &ss->mode.vpaint.gmap;
+ const Brush *brush = data->brush;
+ const StrokeCache *cache = ss->cache;
+ uint *lcol = data->lcol;
+ float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
+ get_brush_alpha_data(
+ scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
+ const bool use_normal = vwpaint_use_normal(data->vp);
+ const bool use_vert_sel = (data->me->editflag &
+ (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
+ 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(
+ ss, &test, data->brush->falloff_shape);
+ const float *sculpt_normal_frontface = sculpt_brush_frontface_normal_from_falloff_shape(
+ ss, data->brush->falloff_shape);
+
+ /* For each vertex */
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ /* Test to see if the vertex coordinates are within the spherical brush region. */
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ /* For grid based pbvh, take the vert whose loop corresponds to the current grid.
+ * Otherwise, take the current vert. */
+ const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v :
+ vd.vert_indices[vd.i];
+ const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
+ const MVert *mv = &data->me->mvert[v_index];
+
+ /* If the vertex is selected for painting. */
+ if (!use_vert_sel || mv->flag & SELECT) {
+ float brush_strength = cache->bstrength;
+ const float angle_cos = (use_normal && vd.no) ?
+ dot_vf3vs3(sculpt_normal_frontface, vd.no) :
+ 1.0f;
+ if (((brush->flag & BRUSH_FRONTFACE) == 0 || (angle_cos > 0.0f)) &&
+ ((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
+ view_angle_limits_apply_falloff(
+ &data->vpd->normal_angle_precalc, angle_cos, &brush_strength))) {
+ const float brush_fade = BKE_brush_curve_strength(
+ brush, sqrtf(test.dist), cache->radius);
+
+ /* Get the average poly color */
+ uint color_final = 0;
+ int total_hit_loops = 0;
+ uint blend[4] = {0};
+ for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
+ int p_index = gmap->vert_to_poly[v_index].indices[j];
+ const MPoly *mp = &data->me->mpoly[p_index];
+ if (!use_face_sel || mp->flag & ME_FACE_SEL) {
+ total_hit_loops += mp->totloop;
+ for (int k = 0; k < mp->totloop; k++) {
+ const uint l_index = mp->loopstart + k;
+ const char *col = (const char *)(&lcol[l_index]);
+ /* Color is squared to compensate the sqrt color encoding. */
+ blend[0] += (uint)col[0] * (uint)col[0];
+ blend[1] += (uint)col[1] * (uint)col[1];
+ blend[2] += (uint)col[2] * (uint)col[2];
+ blend[3] += (uint)col[3] * (uint)col[3];
+ }
+ }
+ }
+ if (total_hit_loops != 0) {
+ /* Use rgb^2 color averaging. */
+ char *col = (char *)(&color_final);
+ col[0] = round_fl_to_uchar(sqrtf(divide_round_i(blend[0], total_hit_loops)));
+ col[1] = round_fl_to_uchar(sqrtf(divide_round_i(blend[1], total_hit_loops)));
+ col[2] = round_fl_to_uchar(sqrtf(divide_round_i(blend[2], total_hit_loops)));
+ col[3] = round_fl_to_uchar(sqrtf(divide_round_i(blend[3], total_hit_loops)));
+
+ /* For each poly owning this vert,
+ * paint each loop belonging to this vert. */
+ for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
+ const int p_index = gmap->vert_to_poly[v_index].indices[j];
+ const int l_index = gmap->vert_to_loop[v_index].indices[j];
+ BLI_assert(data->me->mloop[l_index].v == v_index);
+ const MPoly *mp = &data->me->mpoly[p_index];
+ if (!use_face_sel || mp->flag & ME_FACE_SEL) {
+ uint color_orig = 0; /* unused when array is NULL */
+ if (ss->mode.vpaint.previous_color != NULL) {
+ /* Get the previous loop color */
+ if (ss->mode.vpaint.previous_color[l_index] == 0) {
+ ss->mode.vpaint.previous_color[l_index] = lcol[l_index];
+ }
+ color_orig = ss->mode.vpaint.previous_color[l_index];
+ }
+ const float final_alpha = 255 * brush_fade * brush_strength *
+ brush_alpha_pressure * grid_alpha;
+ /* Mix the new color with the original
+ * based on the brush strength and the curve. */
+ lcol[l_index] = vpaint_blend(data->vp,
+ lcol[l_index],
+ color_orig,
+ *((uint *)col),
+ final_alpha,
+ 255 * brush_strength);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static void do_vpaint_brush_smear_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
+ const bool has_grids = (pbvh_type == PBVH_GRIDS);
+
+ Scene *scene = CTX_data_scene(data->C);
+ const struct SculptVertexPaintGeomMap *gmap = &ss->mode.vpaint.gmap;
+ const Brush *brush = data->brush;
+ const StrokeCache *cache = ss->cache;
+ uint *lcol = data->lcol;
+ float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
+ get_brush_alpha_data(
+ scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
+ float brush_dir[3];
+ const bool use_normal = vwpaint_use_normal(data->vp);
+ const bool use_vert_sel = (data->me->editflag &
+ (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
+ const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+
+ sub_v3_v3v3(brush_dir, cache->location, cache->last_location);
+ project_plane_v3_v3v3(brush_dir, brush_dir, cache->view_normal);
+
+ 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(
+ ss, &test, data->brush->falloff_shape);
+ const float *sculpt_normal_frontface = sculpt_brush_frontface_normal_from_falloff_shape(
+ ss, data->brush->falloff_shape);
+
+ /* For each vertex */
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ /* Test to see if the vertex coordinates are within the spherical brush region. */
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ /* For grid based pbvh, take the vert whose loop corresponds to the current grid.
+ * Otherwise, take the current vert. */
+ const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v :
+ vd.vert_indices[vd.i];
+ const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
+ const MVert *mv_curr = &data->me->mvert[v_index];
+
+ /* if the vertex is selected for painting. */
+ if (!use_vert_sel || mv_curr->flag & SELECT) {
+ /* Calc the dot prod. between ray norm on surf and current vert
+ * (ie splash prevention factor), and only paint front facing verts. */
+ float brush_strength = cache->bstrength;
+ const float angle_cos = (use_normal && vd.no) ?
+ dot_vf3vs3(sculpt_normal_frontface, vd.no) :
+ 1.0f;
+ if (((brush->flag & BRUSH_FRONTFACE) == 0 || (angle_cos > 0.0f)) &&
+ ((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
+ view_angle_limits_apply_falloff(
+ &data->vpd->normal_angle_precalc, angle_cos, &brush_strength))) {
+ const float brush_fade = BKE_brush_curve_strength(
+ brush, sqrtf(test.dist), cache->radius);
+
+ bool do_color = false;
+ /* Minimum dot product between brush direction and current
+ * to neighbor direction is 0.0, meaning orthogonal. */
+ float stroke_dot_max = 0.0f;
+
+ /* Get the color of the loop in the opposite
+ * direction of the brush movement */
+ uint color_final = 0;
+ for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
+ const int p_index = gmap->vert_to_poly[v_index].indices[j];
+ const int l_index = gmap->vert_to_loop[v_index].indices[j];
+ BLI_assert(data->me->mloop[l_index].v == v_index);
+ UNUSED_VARS_NDEBUG(l_index);
+ const MPoly *mp = &data->me->mpoly[p_index];
+ if (!use_face_sel || mp->flag & ME_FACE_SEL) {
+ const MLoop *ml_other = &data->me->mloop[mp->loopstart];
+ for (int k = 0; k < mp->totloop; k++, ml_other++) {
+ const uint v_other_index = ml_other->v;
+ if (v_other_index != v_index) {
+ const MVert *mv_other = &data->me->mvert[v_other_index];
+
+ /* Get the direction from the
+ * selected vert to the neighbor. */
+ float other_dir[3];
+ sub_v3_v3v3(other_dir, mv_curr->co, mv_other->co);
+ project_plane_v3_v3v3(other_dir, other_dir, cache->view_normal);
+
+ normalize_v3(other_dir);
+
+ const float stroke_dot = dot_v3v3(other_dir, brush_dir);
+
+ if (stroke_dot > stroke_dot_max) {
+ stroke_dot_max = stroke_dot;
+ color_final = data->vpd->smear.color_prev[mp->loopstart + k];
+ do_color = true;
+ }
+ }
+ }
+ }
+ }
+
+ if (do_color) {
+ const float final_alpha = 255 * brush_fade * brush_strength * brush_alpha_pressure *
+ grid_alpha;
+
+ /* For each poly owning this vert,
+ * paint each loop belonging to this vert. */
+ for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
+ const int p_index = gmap->vert_to_poly[v_index].indices[j];
+ const int l_index = gmap->vert_to_loop[v_index].indices[j];
+ BLI_assert(data->me->mloop[l_index].v == v_index);
+ const MPoly *mp = &data->me->mpoly[p_index];
+ if (!use_face_sel || mp->flag & ME_FACE_SEL) {
+ /* Get the previous loop color */
+ uint color_orig = 0; /* unused when array is NULL */
+ if (ss->mode.vpaint.previous_color != NULL) {
+ /* Get the previous loop color */
+ if (ss->mode.vpaint.previous_color[l_index] == 0) {
+ ss->mode.vpaint.previous_color[l_index] = lcol[l_index];
+ }
+ color_orig = ss->mode.vpaint.previous_color[l_index];
+ }
+ /* Mix the new color with the original
+ * based on the brush strength and the curve. */
+ lcol[l_index] = vpaint_blend(data->vp,
+ lcol[l_index],
+ color_orig,
+ color_final,
+ final_alpha,
+ 255 * brush_strength);
+
+ data->vpd->smear.color_curr[l_index] = lcol[l_index];
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+ }
+}
+
+static void calculate_average_color(SculptThreadedTaskData *data,
+ PBVHNode **UNUSED(nodes),
+ int totnode)
+{
+ struct VPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__);
+ data->custom_data = accum;
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&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};
+ uchar blend[4] = {0};
+ for (int i = 0; i < totnode; i++) {
+ accum_len += accum[i].len;
+ accum_value[0] += accum[i].value[0];
+ accum_value[1] += accum[i].value[1];
+ accum_value[2] += accum[i].value[2];
+ }
+ if (accum_len != 0) {
+ blend[0] = round_fl_to_uchar(sqrtf(divide_round_i(accum_value[0], accum_len)));
+ blend[1] = round_fl_to_uchar(sqrtf(divide_round_i(accum_value[1], accum_len)));
+ blend[2] = round_fl_to_uchar(sqrtf(divide_round_i(accum_value[2], accum_len)));
+ blend[3] = 255;
+ data->vpd->paintcol = *((uint *)blend);
+ }
+
+ MEM_SAFE_FREE(data->custom_data); /* 'accum' */
+}
+
+static void vpaint_paint_leaves(bContext *C,
+ Sculpt *sd,
+ VPaint *vp,
+ struct VPaintData *vpd,
+ Object *ob,
+ Mesh *me,
+ PBVHNode **nodes,
+ int totnode)
+{
+ const Brush *brush = ob->sculpt->cache->brush;
+
+ SculptThreadedTaskData data = {
+ .C = C,
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .vp = vp,
+ .vpd = vpd,
+ .lcol = (uint *)me->mloopcol,
+ .me = me,
+ };
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ switch ((eBrushVertexPaintTool)brush->vertexpaint_tool) {
+ case VPAINT_TOOL_AVERAGE:
+ calculate_average_color(&data, nodes, totnode);
+ BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings);
+ break;
+ case VPAINT_TOOL_BLUR:
+ BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_blur_task_cb_ex, &settings);
+ break;
+ case VPAINT_TOOL_SMEAR:
+ BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_smear_task_cb_ex, &settings);
+ break;
+ case VPAINT_TOOL_DRAW:
+ BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings);
+ break;
+ }
+}
+
+static void vpaint_do_paint(bContext *C,
+ Sculpt *sd,
+ VPaint *vp,
+ struct VPaintData *vpd,
+ Object *ob,
+ Mesh *me,
+ Brush *brush,
+ const char symm,
+ const int axis,
+ const int i,
+ const float angle)
+{
+ SculptSession *ss = ob->sculpt;
+ ss->cache->radial_symmetry_pass = i;
+ sculpt_cache_calc_brushdata_symm(ss->cache, symm, axis, angle);
+
+ int totnode;
+ PBVHNode **nodes = vwpaint_pbvh_gather_generic(ob, vp, sd, brush, &totnode);
+
+ /* Paint those leaves. */
+ vpaint_paint_leaves(C, sd, vp, vpd, ob, me, nodes, totnode);
+
+ if (nodes) {
+ MEM_freeN(nodes);
+ }
+}
+
+static void vpaint_do_radial_symmetry(bContext *C,
+ Sculpt *sd,
+ VPaint *vp,
+ struct VPaintData *vpd,
+ Object *ob,
+ Mesh *me,
+ Brush *brush,
+ const char symm,
+ const int axis)
+{
+ for (int i = 1; i < vp->radial_symm[axis - 'X']; i++) {
+ const float angle = (2.0 * M_PI) * i / vp->radial_symm[axis - 'X'];
+ vpaint_do_paint(C, sd, vp, vpd, ob, me, brush, symm, axis, i, angle);
+ }
}
/* near duplicate of: sculpt.c's,
* 'do_symmetrical_brush_actions' and 'wpaint_do_symmetrical_brush_actions'. */
static void vpaint_do_symmetrical_brush_actions(
- bContext *C, Sculpt *sd, VPaint *vp, struct VPaintData *vpd, Object *ob)
-{
- Brush *brush = BKE_paint_brush(&vp->paint);
- Mesh *me = ob->data;
- SculptSession *ss = ob->sculpt;
- StrokeCache *cache = ss->cache;
- const char symm = vp->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
- int i = 0;
-
- /* initial stroke */
- vpaint_do_paint(C, sd, vp, vpd, ob, me, brush, i, 'X', 0, 0);
- vpaint_do_radial_symmetry(C, sd, vp, vpd, ob, me, brush, i, 'X');
- vpaint_do_radial_symmetry(C, sd, vp, vpd, ob, me, brush, i, 'Y');
- vpaint_do_radial_symmetry(C, sd, vp, vpd, ob, me, brush, i, 'Z');
-
- cache->symmetry = symm;
-
- /* 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 = 1; i <= symm; i++) {
- 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);
-
- if (i & (1 << 0)) {
- vpaint_do_paint(C, sd, vp, vpd, ob, me, brush, i, 'X', 0, 0);
- vpaint_do_radial_symmetry(C, sd, vp, vpd, ob, me, brush, i, 'X');
- }
- if (i & (1 << 1)) {
- vpaint_do_paint(C, sd, vp, vpd, ob, me, brush, i, 'Y', 0, 0);
- vpaint_do_radial_symmetry(C, sd, vp, vpd, ob, me, brush, i, 'Y');
- }
- if (i & (1 << 2)) {
- vpaint_do_paint(C, sd, vp, vpd, ob, me, brush, i, 'Z', 0, 0);
- vpaint_do_radial_symmetry(C, sd, vp, vpd, ob, me, brush, i, 'Z');
- }
- }
- }
-
- copy_v3_v3(cache->true_last_location, cache->true_location);
- cache->is_last_valid = true;
+ bContext *C, Sculpt *sd, VPaint *vp, struct VPaintData *vpd, Object *ob)
+{
+ Brush *brush = BKE_paint_brush(&vp->paint);
+ Mesh *me = ob->data;
+ SculptSession *ss = ob->sculpt;
+ StrokeCache *cache = ss->cache;
+ const char symm = vp->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+ int i = 0;
+
+ /* initial stroke */
+ vpaint_do_paint(C, sd, vp, vpd, ob, me, brush, i, 'X', 0, 0);
+ vpaint_do_radial_symmetry(C, sd, vp, vpd, ob, me, brush, i, 'X');
+ vpaint_do_radial_symmetry(C, sd, vp, vpd, ob, me, brush, i, 'Y');
+ vpaint_do_radial_symmetry(C, sd, vp, vpd, ob, me, brush, i, 'Z');
+
+ cache->symmetry = symm;
+
+ /* 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 = 1; i <= symm; i++) {
+ 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);
+
+ if (i & (1 << 0)) {
+ vpaint_do_paint(C, sd, vp, vpd, ob, me, brush, i, 'X', 0, 0);
+ vpaint_do_radial_symmetry(C, sd, vp, vpd, ob, me, brush, i, 'X');
+ }
+ if (i & (1 << 1)) {
+ vpaint_do_paint(C, sd, vp, vpd, ob, me, brush, i, 'Y', 0, 0);
+ vpaint_do_radial_symmetry(C, sd, vp, vpd, ob, me, brush, i, 'Y');
+ }
+ if (i & (1 << 2)) {
+ vpaint_do_paint(C, sd, vp, vpd, ob, me, brush, i, 'Z', 0, 0);
+ vpaint_do_radial_symmetry(C, sd, vp, vpd, ob, me, brush, i, 'Z');
+ }
+ }
+ }
+
+ copy_v3_v3(cache->true_last_location, cache->true_location);
+ cache->is_last_valid = true;
}
static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
{
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- struct VPaintData *vpd = paint_stroke_mode_data(stroke);
- VPaint *vp = ts->vpaint;
- ViewContext *vc = &vpd->vc;
- Object *ob = vc->obact;
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ struct VPaintData *vpd = paint_stroke_mode_data(stroke);
+ VPaint *vp = ts->vpaint;
+ ViewContext *vc = &vpd->vc;
+ Object *ob = vc->obact;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- vwpaint_update_cache_variants(C, vp, ob, itemptr);
+ vwpaint_update_cache_variants(C, vp, ob, itemptr);
- float mat[4][4];
- float mval[2];
+ float mat[4][4];
+ float mval[2];
- ED_view3d_init_mats_rv3d(ob, vc->rv3d);
+ ED_view3d_init_mats_rv3d(ob, vc->rv3d);
- /* load projection matrix */
- mul_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat);
+ /* load projection matrix */
+ mul_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat);
- swap_m4m4(vc->rv3d->persmat, mat);
+ swap_m4m4(vc->rv3d->persmat, mat);
- vpaint_do_symmetrical_brush_actions(C, sd, vp, vpd, ob);
+ vpaint_do_symmetrical_brush_actions(C, sd, vp, vpd, ob);
- swap_m4m4(vc->rv3d->persmat, mat);
+ swap_m4m4(vc->rv3d->persmat, mat);
- BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+ BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
- if (vp->paint.brush->vertexpaint_tool == VPAINT_TOOL_SMEAR) {
- memcpy(vpd->smear.color_prev, vpd->smear.color_curr, sizeof(uint) * ((Mesh *)ob->data)->totloop);
- }
+ if (vp->paint.brush->vertexpaint_tool == VPAINT_TOOL_SMEAR) {
+ memcpy(
+ 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 */
- paint_last_stroke_update(scene, vc->ar, mval);
+ /* calculate pivot for rotation around seletion if needed */
+ /* also needed for "View Selected" on last stroke */
+ paint_last_stroke_update(scene, vc->ar, mval);
- ED_region_tag_redraw(vc->ar);
+ ED_region_tag_redraw(vc->ar);
- if (vpd->use_fast_update == false) {
- /* recalculate modifier stack to get new colors, slow,
- * avoid this if we can! */
- DEG_id_tag_update(ob->data, 0);
- }
- else {
- /* Flush changes through DEG. */
- DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE);
- }
+ if (vpd->use_fast_update == false) {
+ /* recalculate modifier stack to get new colors, slow,
+ * avoid this if we can! */
+ DEG_id_tag_update(ob->data, 0);
+ }
+ else {
+ /* Flush changes through DEG. */
+ DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE);
+ }
}
static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
{
- struct VPaintData *vpd = paint_stroke_mode_data(stroke);
- ViewContext *vc = &vpd->vc;
- Object *ob = vc->obact;
+ struct VPaintData *vpd = paint_stroke_mode_data(stroke);
+ ViewContext *vc = &vpd->vc;
+ Object *ob = vc->obact;
- if (vpd->is_texbrush) {
- ED_vpaint_proj_handle_free(vpd->vp_handle);
- }
+ if (vpd->is_texbrush) {
+ ED_vpaint_proj_handle_free(vpd->vp_handle);
+ }
- if (vpd->mlooptag)
- MEM_freeN(vpd->mlooptag);
- if (vpd->smear.color_prev)
- MEM_freeN(vpd->smear.color_prev);
- if (vpd->smear.color_curr)
- MEM_freeN(vpd->smear.color_curr);
+ if (vpd->mlooptag)
+ MEM_freeN(vpd->mlooptag);
+ if (vpd->smear.color_prev)
+ MEM_freeN(vpd->smear.color_prev);
+ if (vpd->smear.color_curr)
+ MEM_freeN(vpd->smear.color_curr);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- MEM_freeN(vpd);
+ MEM_freeN(vpd);
- sculpt_cache_free(ob->sculpt->cache);
- ob->sculpt->cache = NULL;
+ sculpt_cache_free(ob->sculpt->cache);
+ ob->sculpt->cache = NULL;
}
static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- int retval;
+ int retval;
- op->customdata = paint_stroke_new(
- C, op, sculpt_stroke_get_location, vpaint_stroke_test_start,
- vpaint_stroke_update_step, NULL,
- vpaint_stroke_done, event->type);
+ op->customdata = paint_stroke_new(C,
+ op,
+ sculpt_stroke_get_location,
+ vpaint_stroke_test_start,
+ vpaint_stroke_update_step,
+ NULL,
+ vpaint_stroke_done,
+ event->type);
- if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
- paint_stroke_data_free(op);
- return OPERATOR_FINISHED;
- }
+ if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
+ paint_stroke_data_free(op);
+ return OPERATOR_FINISHED;
+ }
- /* add modal handler */
- WM_event_add_modal_handler(C, op);
+ /* add modal handler */
+ WM_event_add_modal_handler(C, op);
- OPERATOR_RETVAL_CHECK(retval);
- BLI_assert(retval == OPERATOR_RUNNING_MODAL);
+ OPERATOR_RETVAL_CHECK(retval);
+ BLI_assert(retval == OPERATOR_RUNNING_MODAL);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static int vpaint_exec(bContext *C, wmOperator *op)
{
- op->customdata = paint_stroke_new(
- C, op, sculpt_stroke_get_location, vpaint_stroke_test_start,
- vpaint_stroke_update_step, NULL,
- vpaint_stroke_done, 0);
+ op->customdata = paint_stroke_new(C,
+ op,
+ sculpt_stroke_get_location,
+ vpaint_stroke_test_start,
+ vpaint_stroke_update_step,
+ NULL,
+ vpaint_stroke_done,
+ 0);
- /* frees op->customdata */
- paint_stroke_exec(C, op);
+ /* frees op->customdata */
+ paint_stroke_exec(C, op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
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);
- ob->sculpt->cache = NULL;
- }
+ Object *ob = CTX_data_active_object(C);
+ if (ob->sculpt->cache) {
+ sculpt_cache_free(ob->sculpt->cache);
+ ob->sculpt->cache = NULL;
+ }
- paint_stroke_cancel(C, op);
+ paint_stroke_cancel(C, op);
}
void PAINT_OT_vertex_paint(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Vertex Paint";
- ot->idname = "PAINT_OT_vertex_paint";
- ot->description = "Paint a stroke in the active vertex color layer";
+ /* identifiers */
+ ot->name = "Vertex Paint";
+ ot->idname = "PAINT_OT_vertex_paint";
+ ot->description = "Paint a stroke in the active vertex color layer";
- /* api callbacks */
- ot->invoke = vpaint_invoke;
- ot->modal = paint_stroke_modal;
- ot->exec = vpaint_exec;
- ot->poll = vertex_paint_poll;
- ot->cancel = vpaint_cancel;
+ /* api callbacks */
+ ot->invoke = vpaint_invoke;
+ ot->modal = paint_stroke_modal;
+ ot->exec = vpaint_exec;
+ ot->poll = vertex_paint_poll;
+ ot->cancel = vpaint_cancel;
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
- paint_stroke_operator_properties(ot);
+ paint_stroke_operator_properties(ot);
}
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 ae1736581fe..ad7cfebb8d5 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
@@ -42,24 +42,23 @@
#include "ED_mesh.h"
-#include "paint_intern.h" /* own include */
-
+#include "paint_intern.h" /* own include */
static bool vertex_weight_paint_mode_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
- Mesh *me = BKE_mesh_from_object(ob);
- return (ob && (ob->mode == OB_MODE_VERTEX_PAINT || ob->mode == OB_MODE_WEIGHT_PAINT)) &&
- (me && me->totpoly && me->dvert);
+ Object *ob = CTX_data_active_object(C);
+ Mesh *me = BKE_mesh_from_object(ob);
+ return (ob && (ob->mode == OB_MODE_VERTEX_PAINT || ob->mode == OB_MODE_WEIGHT_PAINT)) &&
+ (me && me->totpoly && me->dvert);
}
static void tag_object_after_update(Object *object)
{
- BLI_assert(object->type == OB_MESH);
- Mesh *mesh = object->data;
- DEG_id_tag_update(&mesh->id, ID_RECALC_COPY_ON_WRITE);
- /* NOTE: Original mesh is used for display, so tag it directly here. */
- BKE_mesh_batch_cache_dirty_tag(mesh, BKE_MESH_BATCH_DIRTY_ALL);
+ BLI_assert(object->type == OB_MESH);
+ Mesh *mesh = object->data;
+ DEG_id_tag_update(&mesh->id, ID_RECALC_COPY_ON_WRITE);
+ /* NOTE: Original mesh is used for display, so tag it directly here. */
+ BKE_mesh_batch_cache_dirty_tag(mesh, BKE_MESH_BATCH_DIRTY_ALL);
}
/* -------------------------------------------------------------------- */
@@ -68,74 +67,71 @@ static void tag_object_after_update(Object *object)
static bool vertex_color_set(Object *ob, uint paintcol)
{
- Mesh *me;
- const MPoly *mp;
- int i, j;
-
- if (((me = BKE_mesh_from_object(ob)) == NULL) ||
- (ED_mesh_color_ensure(me, NULL) == false))
- {
- return false;
- }
+ Mesh *me;
+ const MPoly *mp;
+ int i, j;
- const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
- const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+ if (((me = BKE_mesh_from_object(ob)) == NULL) || (ED_mesh_color_ensure(me, NULL) == false)) {
+ return false;
+ }
- mp = me->mpoly;
- for (i = 0; i < me->totpoly; i++, mp++) {
- MLoopCol *lcol = me->mloopcol + mp->loopstart;
+ const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
- if (use_face_sel && !(mp->flag & ME_FACE_SEL))
- continue;
+ mp = me->mpoly;
+ for (i = 0; i < me->totpoly; i++, mp++) {
+ MLoopCol *lcol = me->mloopcol + mp->loopstart;
- j = 0;
- do {
- uint vidx = me->mloop[mp->loopstart + j].v;
- if (!(use_vert_sel && !(me->mvert[vidx].flag & SELECT))) {
- *(int *)lcol = paintcol;
- }
- lcol++;
- j++;
- } while (j < mp->totloop);
+ if (use_face_sel && !(mp->flag & ME_FACE_SEL))
+ continue;
- }
+ j = 0;
+ do {
+ uint vidx = me->mloop[mp->loopstart + j].v;
+ if (!(use_vert_sel && !(me->mvert[vidx].flag & SELECT))) {
+ *(int *)lcol = paintcol;
+ }
+ lcol++;
+ j++;
+ } while (j < mp->totloop);
+ }
- /* remove stale me->mcol, will be added later */
- BKE_mesh_tessface_clear(me);
+ /* remove stale me->mcol, will be added later */
+ BKE_mesh_tessface_clear(me);
- tag_object_after_update(ob);
+ tag_object_after_update(ob);
- return true;
+ return true;
}
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);
-
- if (vertex_color_set(obact, paintcol)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ 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);
+
+ if (vertex_color_set(obact, paintcol)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void PAINT_OT_vertex_color_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Vertex Colors";
- ot->idname = "PAINT_OT_vertex_color_set";
- ot->description = "Fill the active vertex color layer with the current paint color";
+ /* identifiers */
+ ot->name = "Set Vertex Colors";
+ ot->idname = "PAINT_OT_vertex_color_set";
+ ot->description = "Fill the active vertex color layer with the current paint color";
- /* api callbacks */
- ot->exec = vertex_color_set_exec;
- ot->poll = vertex_paint_mode_poll;
+ /* api callbacks */
+ ot->exec = vertex_color_set_exec;
+ ot->poll = vertex_paint_mode_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -146,67 +142,65 @@ void PAINT_OT_vertex_color_set(wmOperatorType *ot)
static bool vertex_paint_from_weight(Object *ob)
{
- Mesh *me;
- const MPoly *mp;
- int vgroup_active;
-
- if (((me = BKE_mesh_from_object(ob)) == NULL ||
- (ED_mesh_color_ensure(me, NULL)) == false))
- {
- return false;
- }
-
- /* TODO: respect selection. */
- /* TODO: Do we want to take weights from evaluated mesh instead? 2.7x was not doing it anyway... */
- mp = me->mpoly;
- vgroup_active = ob->actdef - 1;
- for (int i = 0; i < me->totpoly; i++, mp++) {
- MLoopCol *lcol = &me->mloopcol[mp->loopstart];
- uint j = 0;
- do {
- uint vidx = me->mloop[mp->loopstart + j].v;
- const float weight = defvert_find_weight(&me->dvert[vidx], vgroup_active);
- const uchar grayscale = weight * 255;
- lcol->r = grayscale;
- lcol->b = grayscale;
- lcol->g = grayscale;
- lcol++;
- j++;
- } while (j < mp->totloop);
- }
-
- tag_object_after_update(ob);
-
- return true;
+ Mesh *me;
+ const MPoly *mp;
+ int vgroup_active;
+
+ if (((me = BKE_mesh_from_object(ob)) == NULL || (ED_mesh_color_ensure(me, NULL)) == false)) {
+ return false;
+ }
+
+ /* TODO: respect selection. */
+ /* TODO: Do we want to take weights from evaluated mesh instead? 2.7x was not doing it anyway... */
+ mp = me->mpoly;
+ vgroup_active = ob->actdef - 1;
+ for (int i = 0; i < me->totpoly; i++, mp++) {
+ MLoopCol *lcol = &me->mloopcol[mp->loopstart];
+ uint j = 0;
+ do {
+ uint vidx = me->mloop[mp->loopstart + j].v;
+ const float weight = defvert_find_weight(&me->dvert[vidx], vgroup_active);
+ const uchar grayscale = weight * 255;
+ lcol->r = grayscale;
+ lcol->b = grayscale;
+ lcol->g = grayscale;
+ lcol++;
+ j++;
+ } while (j < mp->totloop);
+ }
+
+ tag_object_after_update(ob);
+
+ return true;
}
static int vertex_paint_from_weight_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obact = CTX_data_active_object(C);
- if (vertex_paint_from_weight(obact)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Object *obact = CTX_data_active_object(C);
+ if (vertex_paint_from_weight(obact)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void PAINT_OT_vertex_color_from_weight(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Vertex Color from Weight";
- ot->idname = "PAINT_OT_vertex_color_from_weight";
- ot->description = "Convert active weight into gray scale vertex colors";
+ /* identifiers */
+ ot->name = "Vertex Color from Weight";
+ ot->idname = "PAINT_OT_vertex_color_from_weight";
+ ot->description = "Convert active weight into gray scale vertex colors";
- /* api callback */
- ot->exec = vertex_paint_from_weight_exec;
- ot->poll = vertex_weight_paint_mode_poll;
+ /* api callback */
+ ot->exec = vertex_paint_from_weight_exec;
+ ot->poll = vertex_weight_paint_mode_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* TODO: invert, alpha */
+ /* TODO: invert, alpha */
}
/** \} */
@@ -217,131 +211,129 @@ void PAINT_OT_vertex_color_from_weight(wmOperatorType *ot)
static void vertex_color_smooth_looptag(Mesh *me, bool *mlooptag)
{
- const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
- const MPoly *mp;
- int (*scol)[4];
- int i, j;
- bool has_shared = false;
-
- /* if no mloopcol: do not do */
- /* if mtexpoly: only the involved faces, otherwise all */
-
- if (me->mloopcol == NULL || me->totvert == 0 || me->totpoly == 0) return;
-
- scol = MEM_callocN(sizeof(int) * me->totvert * 5, "scol");
-
- for (i = 0, mp = me->mpoly; i < me->totpoly; i++, mp++) {
- if ((use_face_sel == false) || (mp->flag & ME_FACE_SEL)) {
- const MLoop *ml = me->mloop + mp->loopstart;
- MLoopCol *lcol = me->mloopcol + mp->loopstart;
- for (j = 0; j < mp->totloop; j++, ml++, lcol++) {
- scol[ml->v][0] += lcol->r;
- scol[ml->v][1] += lcol->g;
- scol[ml->v][2] += lcol->b;
- scol[ml->v][3] += 1;
- has_shared = 1;
- }
- }
- }
-
- if (has_shared) {
- for (i = 0; i < me->totvert; i++) {
- if (scol[i][3] != 0) {
- scol[i][0] = divide_round_i(scol[i][0], scol[i][3]);
- scol[i][1] = divide_round_i(scol[i][1], scol[i][3]);
- scol[i][2] = divide_round_i(scol[i][2], scol[i][3]);
- }
- }
-
- for (i = 0, mp = me->mpoly; i < me->totpoly; i++, mp++) {
- if ((use_face_sel == false) || (mp->flag & ME_FACE_SEL)) {
- const MLoop *ml = me->mloop + mp->loopstart;
- MLoopCol *lcol = me->mloopcol + mp->loopstart;
- for (j = 0; j < mp->totloop; j++, ml++, lcol++) {
- if (mlooptag[mp->loopstart + j]) {
- lcol->r = scol[ml->v][0];
- lcol->g = scol[ml->v][1];
- lcol->b = scol[ml->v][2];
- }
- }
- }
- }
- }
-
- MEM_freeN(scol);
+ const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ const MPoly *mp;
+ int(*scol)[4];
+ int i, j;
+ bool has_shared = false;
+
+ /* if no mloopcol: do not do */
+ /* if mtexpoly: only the involved faces, otherwise all */
+
+ if (me->mloopcol == NULL || me->totvert == 0 || me->totpoly == 0)
+ return;
+
+ scol = MEM_callocN(sizeof(int) * me->totvert * 5, "scol");
+
+ for (i = 0, mp = me->mpoly; i < me->totpoly; i++, mp++) {
+ if ((use_face_sel == false) || (mp->flag & ME_FACE_SEL)) {
+ const MLoop *ml = me->mloop + mp->loopstart;
+ MLoopCol *lcol = me->mloopcol + mp->loopstart;
+ for (j = 0; j < mp->totloop; j++, ml++, lcol++) {
+ scol[ml->v][0] += lcol->r;
+ scol[ml->v][1] += lcol->g;
+ scol[ml->v][2] += lcol->b;
+ scol[ml->v][3] += 1;
+ has_shared = 1;
+ }
+ }
+ }
+
+ if (has_shared) {
+ for (i = 0; i < me->totvert; i++) {
+ if (scol[i][3] != 0) {
+ scol[i][0] = divide_round_i(scol[i][0], scol[i][3]);
+ scol[i][1] = divide_round_i(scol[i][1], scol[i][3]);
+ scol[i][2] = divide_round_i(scol[i][2], scol[i][3]);
+ }
+ }
+
+ for (i = 0, mp = me->mpoly; i < me->totpoly; i++, mp++) {
+ if ((use_face_sel == false) || (mp->flag & ME_FACE_SEL)) {
+ const MLoop *ml = me->mloop + mp->loopstart;
+ MLoopCol *lcol = me->mloopcol + mp->loopstart;
+ for (j = 0; j < mp->totloop; j++, ml++, lcol++) {
+ if (mlooptag[mp->loopstart + j]) {
+ lcol->r = scol[ml->v][0];
+ lcol->g = scol[ml->v][1];
+ lcol->b = scol[ml->v][2];
+ }
+ }
+ }
+ }
+ }
+
+ MEM_freeN(scol);
}
static bool vertex_color_smooth(Object *ob)
{
- Mesh *me;
- const MPoly *mp;
+ Mesh *me;
+ const MPoly *mp;
- int i, j;
+ int i, j;
- bool *mlooptag;
+ bool *mlooptag;
- if (((me = BKE_mesh_from_object(ob)) == NULL) ||
- (ED_mesh_color_ensure(me, NULL) == false))
- {
- return false;
- }
+ if (((me = BKE_mesh_from_object(ob)) == NULL) || (ED_mesh_color_ensure(me, NULL) == false)) {
+ return false;
+ }
- const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
- mlooptag = MEM_callocN(sizeof(bool) * me->totloop, "VPaintData mlooptag");
+ mlooptag = MEM_callocN(sizeof(bool) * me->totloop, "VPaintData mlooptag");
- /* simply tag loops of selected faces */
- mp = me->mpoly;
- for (i = 0; i < me->totpoly; i++, mp++) {
- const MLoop *ml = me->mloop + mp->loopstart;
- int ml_index = mp->loopstart;
+ /* simply tag loops of selected faces */
+ mp = me->mpoly;
+ for (i = 0; i < me->totpoly; i++, mp++) {
+ const MLoop *ml = me->mloop + mp->loopstart;
+ int ml_index = mp->loopstart;
- if (use_face_sel && !(mp->flag & ME_FACE_SEL))
- continue;
+ if (use_face_sel && !(mp->flag & ME_FACE_SEL))
+ continue;
- for (j = 0; j < mp->totloop; j++, ml_index++, ml++) {
- mlooptag[ml_index] = true;
- }
- }
+ for (j = 0; j < mp->totloop; j++, ml_index++, ml++) {
+ mlooptag[ml_index] = true;
+ }
+ }
- /* remove stale me->mcol, will be added later */
- BKE_mesh_tessface_clear(me);
+ /* remove stale me->mcol, will be added later */
+ BKE_mesh_tessface_clear(me);
- vertex_color_smooth_looptag(me, mlooptag);
+ vertex_color_smooth_looptag(me, mlooptag);
- MEM_freeN(mlooptag);
+ MEM_freeN(mlooptag);
- tag_object_after_update(ob);
+ tag_object_after_update(ob);
- return true;
+ return true;
}
-
static int vertex_color_smooth_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obact = CTX_data_active_object(C);
- if (vertex_color_smooth(obact)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Object *obact = CTX_data_active_object(C);
+ if (vertex_color_smooth(obact)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void PAINT_OT_vertex_color_smooth(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Smooth Vertex Colors";
- ot->idname = "PAINT_OT_vertex_color_smooth";
- ot->description = "Smooth colors across vertices";
+ /* identifiers */
+ ot->name = "Smooth Vertex Colors";
+ ot->idname = "PAINT_OT_vertex_color_smooth";
+ ot->description = "Smooth colors across vertices";
- /* api callbacks */
- ot->exec = vertex_color_smooth_exec;
- ot->poll = vertex_paint_mode_poll;
+ /* api callbacks */
+ ot->exec = vertex_color_smooth_exec;
+ ot->poll = vertex_paint_mode_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -351,231 +343,234 @@ void PAINT_OT_vertex_color_smooth(wmOperatorType *ot)
* \{ */
struct VPaintTx_BrightContrastData {
- /* pre-calculated */
- float gain;
- float offset;
+ /* pre-calculated */
+ float gain;
+ float offset;
};
-static void vpaint_tx_brightness_contrast(const float col[3], const void *user_data, float r_col[3])
+static void vpaint_tx_brightness_contrast(const float col[3],
+ const void *user_data,
+ float r_col[3])
{
- const struct VPaintTx_BrightContrastData *data = user_data;
+ const struct VPaintTx_BrightContrastData *data = user_data;
- for (int i = 0; i < 3; i++) {
- r_col[i] = data->gain * col[i] + data->offset;
- }
+ for (int i = 0; i < 3; i++) {
+ r_col[i] = data->gain * col[i] + data->offset;
+ }
}
static int vertex_color_brightness_contrast_exec(bContext *C, wmOperator *op)
{
- Object *obact = CTX_data_active_object(C);
-
- 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;
- gain = 1.0f - delta * 2.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 / ((gain != 0.0f) ? gain : FLT_EPSILON);
- offset = gain * (brightness - delta);
- }
- else {
- delta *= -1;
- offset = gain * (brightness + delta);
- }
- }
-
- const struct VPaintTx_BrightContrastData user_data = {
- .gain = gain,
- .offset = offset,
- };
-
- if (ED_vpaint_color_transform(obact, vpaint_tx_brightness_contrast, &user_data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Object *obact = CTX_data_active_object(C);
+
+ 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;
+ gain = 1.0f - delta * 2.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 / ((gain != 0.0f) ? gain : FLT_EPSILON);
+ offset = gain * (brightness - delta);
+ }
+ else {
+ delta *= -1;
+ offset = gain * (brightness + delta);
+ }
+ }
+
+ const struct VPaintTx_BrightContrastData user_data = {
+ .gain = gain,
+ .offset = offset,
+ };
+
+ if (ED_vpaint_color_transform(obact, vpaint_tx_brightness_contrast, &user_data)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void PAINT_OT_vertex_color_brightness_contrast(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Vertex Paint Bright/Contrast";
- ot->idname = "PAINT_OT_vertex_color_brightness_contrast";
- ot->description = "Adjust vertex color brightness/contrast";
+ /* identifiers */
+ ot->name = "Vertex Paint Bright/Contrast";
+ ot->idname = "PAINT_OT_vertex_color_brightness_contrast";
+ ot->description = "Adjust vertex color brightness/contrast";
- /* api callbacks */
- ot->exec = vertex_color_brightness_contrast_exec;
- ot->poll = vertex_paint_mode_poll;
+ /* api callbacks */
+ ot->exec = vertex_color_brightness_contrast_exec;
+ ot->poll = vertex_paint_mode_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* params */
- 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);
+ /* params */
+ 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);
}
struct VPaintTx_HueSatData {
- float hue;
- float sat;
- float val;
+ float hue;
+ float sat;
+ float val;
};
static void vpaint_tx_hsv(const float col[3], const void *user_data, float r_col[3])
{
- const struct VPaintTx_HueSatData *data = user_data;
- float hsv[3];
- rgb_to_hsv_v(col, hsv);
-
- hsv[0] += (data->hue - 0.5f);
- if (hsv[0] > 1.0f) {
- hsv[0] -= 1.0f;
- }
- else if (hsv[0] < 0.0f) {
- hsv[0] += 1.0f;
- }
- hsv[1] *= data->sat;
- hsv[2] *= data->val;
-
- hsv_to_rgb_v(hsv, r_col);
+ const struct VPaintTx_HueSatData *data = user_data;
+ float hsv[3];
+ rgb_to_hsv_v(col, hsv);
+
+ hsv[0] += (data->hue - 0.5f);
+ if (hsv[0] > 1.0f) {
+ hsv[0] -= 1.0f;
+ }
+ else if (hsv[0] < 0.0f) {
+ hsv[0] += 1.0f;
+ }
+ hsv[1] *= data->sat;
+ hsv[2] *= data->val;
+
+ hsv_to_rgb_v(hsv, r_col);
}
static int vertex_color_hsv_exec(bContext *C, wmOperator *op)
{
- Object *obact = CTX_data_active_object(C);
-
- const struct VPaintTx_HueSatData user_data = {
- .hue = RNA_float_get(op->ptr, "h"),
- .sat = RNA_float_get(op->ptr, "s"),
- .val = RNA_float_get(op->ptr, "v"),
- };
-
- if (ED_vpaint_color_transform(obact, vpaint_tx_hsv, &user_data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Object *obact = CTX_data_active_object(C);
+
+ const struct VPaintTx_HueSatData user_data = {
+ .hue = RNA_float_get(op->ptr, "h"),
+ .sat = RNA_float_get(op->ptr, "s"),
+ .val = RNA_float_get(op->ptr, "v"),
+ };
+
+ if (ED_vpaint_color_transform(obact, vpaint_tx_hsv, &user_data)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void PAINT_OT_vertex_color_hsv(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Vertex Paint Hue Saturation Value";
- ot->idname = "PAINT_OT_vertex_color_hsv";
- ot->description = "Adjust vertex color HSV values";
-
- /* api callbacks */
- ot->exec = vertex_color_hsv_exec;
- ot->poll = vertex_paint_mode_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* params */
- 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);
+ /* identifiers */
+ ot->name = "Vertex Paint Hue Saturation Value";
+ ot->idname = "PAINT_OT_vertex_color_hsv";
+ ot->description = "Adjust vertex color HSV values";
+
+ /* api callbacks */
+ ot->exec = vertex_color_hsv_exec;
+ ot->poll = vertex_paint_mode_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* params */
+ 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 void vpaint_tx_invert(const float col[3], const void *UNUSED(user_data), float r_col[3])
{
- for (int i = 0; i < 3; i++) {
- r_col[i] = 1.0f - col[i];
- }
+ for (int i = 0; i < 3; i++) {
+ r_col[i] = 1.0f - col[i];
+ }
}
static int vertex_color_invert_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obact = CTX_data_active_object(C);
-
- if (ED_vpaint_color_transform(obact, vpaint_tx_invert, NULL)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Object *obact = CTX_data_active_object(C);
+
+ if (ED_vpaint_color_transform(obact, vpaint_tx_invert, NULL)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void PAINT_OT_vertex_color_invert(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Vertex Paint Invert";
- ot->idname = "PAINT_OT_vertex_color_invert";
- ot->description = "Invert RGB values";
+ /* identifiers */
+ ot->name = "Vertex Paint Invert";
+ ot->idname = "PAINT_OT_vertex_color_invert";
+ ot->description = "Invert RGB values";
- /* api callbacks */
- ot->exec = vertex_color_invert_exec;
- ot->poll = vertex_paint_mode_poll;
+ /* api callbacks */
+ ot->exec = vertex_color_invert_exec;
+ ot->poll = vertex_paint_mode_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
struct VPaintTx_LevelsData {
- float gain;
- float offset;
+ float gain;
+ float offset;
};
static void vpaint_tx_levels(const float col[3], const void *user_data, float r_col[3])
{
- const struct VPaintTx_LevelsData *data = user_data;
- for (int i = 0; i < 3; i++) {
- r_col[i] = data->gain * (col[i] + data->offset);
- }
+ const struct VPaintTx_LevelsData *data = user_data;
+ for (int i = 0; i < 3; i++) {
+ r_col[i] = data->gain * (col[i] + data->offset);
+ }
}
static int vertex_color_levels_exec(bContext *C, wmOperator *op)
{
- Object *obact = CTX_data_active_object(C);
-
- const struct VPaintTx_LevelsData user_data = {
- .gain = RNA_float_get(op->ptr, "gain"),
- .offset = RNA_float_get(op->ptr, "offset"),
- };
-
- if (ED_vpaint_color_transform(obact, vpaint_tx_levels, &user_data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Object *obact = CTX_data_active_object(C);
+
+ const struct VPaintTx_LevelsData user_data = {
+ .gain = RNA_float_get(op->ptr, "gain"),
+ .offset = RNA_float_get(op->ptr, "offset"),
+ };
+
+ if (ED_vpaint_color_transform(obact, vpaint_tx_levels, &user_data)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void PAINT_OT_vertex_color_levels(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Vertex Paint Levels";
- ot->idname = "PAINT_OT_vertex_color_levels";
- ot->description = "Adjust levels of vertex colors";
-
- /* api callbacks */
- ot->exec = vertex_color_levels_exec;
- ot->poll = vertex_paint_mode_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* params */
- 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);
+ /* identifiers */
+ ot->name = "Vertex Paint Levels";
+ ot->idname = "PAINT_OT_vertex_color_levels";
+ ot->description = "Adjust levels of vertex colors";
+
+ /* api callbacks */
+ ot->exec = vertex_color_levels_exec;
+ ot->poll = vertex_paint_mode_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* params */
+ 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);
}
/** \} */
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 4a5c72e5199..6511c90f5e1 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_color_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_color_utils.c
@@ -41,53 +41,50 @@
#include "ED_mesh.h"
-#include "paint_intern.h" /* own include */
+#include "paint_intern.h" /* own include */
#define EPS_SATURATION 0.0005f
/**
* Apply callback to each vertex of the active vertex color layer.
*/
-bool ED_vpaint_color_transform(
- struct Object *ob,
- VPaintTransform_Callback vpaint_tx_fn,
- const void *user_data)
+bool ED_vpaint_color_transform(struct Object *ob,
+ VPaintTransform_Callback vpaint_tx_fn,
+ const void *user_data)
{
- Mesh *me;
- const MPoly *mp;
+ Mesh *me;
+ const MPoly *mp;
- if (((me = BKE_mesh_from_object(ob)) == NULL) ||
- (ED_mesh_color_ensure(me, NULL) == false))
- {
- return false;
- }
+ if (((me = BKE_mesh_from_object(ob)) == NULL) || (ED_mesh_color_ensure(me, NULL) == false)) {
+ return false;
+ }
- const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
- mp = me->mpoly;
+ const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ mp = me->mpoly;
- for (int i = 0; i < me->totpoly; i++, mp++) {
- MLoopCol *lcol = &me->mloopcol[mp->loopstart];
+ for (int i = 0; i < me->totpoly; i++, mp++) {
+ MLoopCol *lcol = &me->mloopcol[mp->loopstart];
- if (use_face_sel && !(mp->flag & ME_FACE_SEL)) {
- continue;
- }
+ if (use_face_sel && !(mp->flag & ME_FACE_SEL)) {
+ continue;
+ }
- for (int j = 0; j < mp->totloop; j++, lcol++) {
- float col_mix[3];
- rgb_uchar_to_float(col_mix, &lcol->r);
+ for (int j = 0; j < mp->totloop; j++, lcol++) {
+ float col_mix[3];
+ rgb_uchar_to_float(col_mix, &lcol->r);
- vpaint_tx_fn(col_mix, user_data, col_mix);
+ vpaint_tx_fn(col_mix, user_data, col_mix);
- rgb_float_to_uchar(&lcol->r, col_mix);
- }
- }
+ rgb_float_to_uchar(&lcol->r, col_mix);
+ }
+ }
- /* remove stale me->mcol, will be added later */
- BKE_mesh_tessface_clear(me);
+ /* remove stale me->mcol, will be added later */
+ BKE_mesh_tessface_clear(me);
- DEG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
- return true;
+ return true;
}
/* -------------------------------------------------------------------- */
@@ -96,548 +93,566 @@ bool ED_vpaint_color_transform(
BLI_INLINE uint mcol_blend(uint col_src, uint col_dst, int fac)
{
- uchar *cp_src, *cp_dst, *cp_mix;
- int mfac;
- uint col_mix = 0;
+ uchar *cp_src, *cp_dst, *cp_mix;
+ int mfac;
+ uint col_mix = 0;
- if (fac == 0) {
- return col_src;
- }
+ if (fac == 0) {
+ return col_src;
+ }
- if (fac >= 255) {
- return col_dst;
- }
+ if (fac >= 255) {
+ return col_dst;
+ }
- mfac = 255 - fac;
+ mfac = 255 - fac;
- cp_src = (uchar *)&col_src;
- cp_dst = (uchar *)&col_dst;
- cp_mix = (uchar *)&col_mix;
+ cp_src = (uchar *)&col_src;
+ cp_dst = (uchar *)&col_dst;
+ cp_mix = (uchar *)&col_mix;
- /* Updated to use the rgb squared color model which blends nicer. */
- int r1 = cp_src[0] * cp_src[0];
- int g1 = cp_src[1] * cp_src[1];
- int b1 = cp_src[2] * cp_src[2];
- int a1 = cp_src[3] * cp_src[3];
+ /* Updated to use the rgb squared color model which blends nicer. */
+ int r1 = cp_src[0] * cp_src[0];
+ int g1 = cp_src[1] * cp_src[1];
+ int b1 = cp_src[2] * cp_src[2];
+ int a1 = cp_src[3] * cp_src[3];
- int r2 = cp_dst[0] * cp_dst[0];
- int g2 = cp_dst[1] * cp_dst[1];
- int b2 = cp_dst[2] * cp_dst[2];
- int a2 = cp_dst[3] * cp_dst[3];
+ int r2 = cp_dst[0] * cp_dst[0];
+ int g2 = cp_dst[1] * cp_dst[1];
+ int b2 = cp_dst[2] * cp_dst[2];
+ int a2 = cp_dst[3] * cp_dst[3];
- cp_mix[0] = round_fl_to_uchar(sqrtf(divide_round_i((mfac * r1 + fac * r2), 255)));
- cp_mix[1] = round_fl_to_uchar(sqrtf(divide_round_i((mfac * g1 + fac * g2), 255)));
- cp_mix[2] = round_fl_to_uchar(sqrtf(divide_round_i((mfac * b1 + fac * b2), 255)));
- cp_mix[3] = round_fl_to_uchar(sqrtf(divide_round_i((mfac * a1 + fac * a2), 255)));
+ cp_mix[0] = round_fl_to_uchar(sqrtf(divide_round_i((mfac * r1 + fac * r2), 255)));
+ cp_mix[1] = round_fl_to_uchar(sqrtf(divide_round_i((mfac * g1 + fac * g2), 255)));
+ cp_mix[2] = round_fl_to_uchar(sqrtf(divide_round_i((mfac * b1 + fac * b2), 255)));
+ cp_mix[3] = round_fl_to_uchar(sqrtf(divide_round_i((mfac * a1 + fac * a2), 255)));
- return col_mix;
+ return col_mix;
}
BLI_INLINE uint mcol_add(uint col_src, uint col_dst, int fac)
{
- uchar *cp_src, *cp_dst, *cp_mix;
- int temp;
- uint col_mix = 0;
-
- if (fac == 0) {
- return col_src;
- }
-
- cp_src = (uchar *)&col_src;
- cp_dst = (uchar *)&col_dst;
- cp_mix = (uchar *)&col_mix;
-
- temp = cp_src[0] + divide_round_i((fac * cp_dst[0]), 255);
- cp_mix[0] = (temp > 254) ? 255 : temp;
- temp = cp_src[1] + divide_round_i((fac * cp_dst[1]), 255);
- cp_mix[1] = (temp > 254) ? 255 : temp;
- temp = cp_src[2] + divide_round_i((fac * cp_dst[2]), 255);
- cp_mix[2] = (temp > 254) ? 255 : temp;
- temp = cp_src[3] + divide_round_i((fac * cp_dst[3]), 255);
- cp_mix[3] = (temp > 254) ? 255 : temp;
-
- return col_mix;
+ uchar *cp_src, *cp_dst, *cp_mix;
+ int temp;
+ uint col_mix = 0;
+
+ if (fac == 0) {
+ return col_src;
+ }
+
+ cp_src = (uchar *)&col_src;
+ cp_dst = (uchar *)&col_dst;
+ cp_mix = (uchar *)&col_mix;
+
+ temp = cp_src[0] + divide_round_i((fac * cp_dst[0]), 255);
+ cp_mix[0] = (temp > 254) ? 255 : temp;
+ temp = cp_src[1] + divide_round_i((fac * cp_dst[1]), 255);
+ cp_mix[1] = (temp > 254) ? 255 : temp;
+ temp = cp_src[2] + divide_round_i((fac * cp_dst[2]), 255);
+ cp_mix[2] = (temp > 254) ? 255 : temp;
+ temp = cp_src[3] + divide_round_i((fac * cp_dst[3]), 255);
+ cp_mix[3] = (temp > 254) ? 255 : temp;
+
+ return col_mix;
}
BLI_INLINE uint mcol_sub(uint col_src, uint col_dst, int fac)
{
- uchar *cp_src, *cp_dst, *cp_mix;
- int temp;
- uint col_mix = 0;
-
- if (fac == 0) {
- return col_src;
- }
-
- cp_src = (uchar *)&col_src;
- cp_dst = (uchar *)&col_dst;
- cp_mix = (uchar *)&col_mix;
-
- temp = cp_src[0] - divide_round_i((fac * cp_dst[0]), 255);
- cp_mix[0] = (temp < 0) ? 0 : temp;
- temp = cp_src[1] - divide_round_i((fac * cp_dst[1]), 255);
- cp_mix[1] = (temp < 0) ? 0 : temp;
- temp = cp_src[2] - divide_round_i((fac * cp_dst[2]), 255);
- cp_mix[2] = (temp < 0) ? 0 : temp;
- temp = cp_src[3] - divide_round_i((fac * cp_dst[3]), 255);
- cp_mix[3] = (temp < 0) ? 0 : temp;
-
- return col_mix;
+ uchar *cp_src, *cp_dst, *cp_mix;
+ int temp;
+ uint col_mix = 0;
+
+ if (fac == 0) {
+ return col_src;
+ }
+
+ cp_src = (uchar *)&col_src;
+ cp_dst = (uchar *)&col_dst;
+ cp_mix = (uchar *)&col_mix;
+
+ temp = cp_src[0] - divide_round_i((fac * cp_dst[0]), 255);
+ cp_mix[0] = (temp < 0) ? 0 : temp;
+ temp = cp_src[1] - divide_round_i((fac * cp_dst[1]), 255);
+ cp_mix[1] = (temp < 0) ? 0 : temp;
+ temp = cp_src[2] - divide_round_i((fac * cp_dst[2]), 255);
+ cp_mix[2] = (temp < 0) ? 0 : temp;
+ temp = cp_src[3] - divide_round_i((fac * cp_dst[3]), 255);
+ cp_mix[3] = (temp < 0) ? 0 : temp;
+
+ return col_mix;
}
BLI_INLINE uint mcol_mul(uint col_src, uint col_dst, int fac)
{
- uchar *cp_src, *cp_dst, *cp_mix;
- int mfac;
- uint col_mix = 0;
+ uchar *cp_src, *cp_dst, *cp_mix;
+ int mfac;
+ uint col_mix = 0;
- if (fac == 0) {
- return col_src;
- }
+ if (fac == 0) {
+ return col_src;
+ }
- mfac = 255 - fac;
+ mfac = 255 - fac;
- cp_src = (uchar *)&col_src;
- cp_dst = (uchar *)&col_dst;
- cp_mix = (uchar *)&col_mix;
+ cp_src = (uchar *)&col_src;
+ cp_dst = (uchar *)&col_dst;
+ cp_mix = (uchar *)&col_mix;
- /* first mul, then blend the fac */
- cp_mix[0] = divide_round_i(mfac * cp_src[0] * 255 + fac * cp_dst[0] * cp_src[0], 255 * 255);
- cp_mix[1] = divide_round_i(mfac * cp_src[1] * 255 + fac * cp_dst[1] * cp_src[1], 255 * 255);
- cp_mix[2] = divide_round_i(mfac * cp_src[2] * 255 + fac * cp_dst[2] * cp_src[2], 255 * 255);
- cp_mix[3] = divide_round_i(mfac * cp_src[3] * 255 + fac * cp_dst[3] * cp_src[3], 255 * 255);
+ /* first mul, then blend the fac */
+ cp_mix[0] = divide_round_i(mfac * cp_src[0] * 255 + fac * cp_dst[0] * cp_src[0], 255 * 255);
+ cp_mix[1] = divide_round_i(mfac * cp_src[1] * 255 + fac * cp_dst[1] * cp_src[1], 255 * 255);
+ cp_mix[2] = divide_round_i(mfac * cp_src[2] * 255 + fac * cp_dst[2] * cp_src[2], 255 * 255);
+ cp_mix[3] = divide_round_i(mfac * cp_src[3] * 255 + fac * cp_dst[3] * cp_src[3], 255 * 255);
- return col_mix;
+ return col_mix;
}
BLI_INLINE uint mcol_lighten(uint col_src, uint col_dst, int fac)
{
- uchar *cp_src, *cp_dst, *cp_mix;
- int mfac;
- uint col_mix = 0;
-
- if (fac == 0) {
- return col_src;
- }
- else if (fac >= 255) {
- return col_dst;
- }
-
- mfac = 255 - fac;
-
- cp_src = (uchar *)&col_src;
- cp_dst = (uchar *)&col_dst;
- cp_mix = (uchar *)&col_mix;
-
- /* See if are 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)) {
- return col_src;
- }
-
- cp_mix[0] = divide_round_i(mfac * cp_src[0] + fac * cp_dst[0], 255);
- cp_mix[1] = divide_round_i(mfac * cp_src[1] + fac * cp_dst[1], 255);
- cp_mix[2] = divide_round_i(mfac * cp_src[2] + fac * cp_dst[2], 255);
- cp_mix[3] = divide_round_i(mfac * cp_src[3] + fac * cp_dst[3], 255);
-
- return col_mix;
+ uchar *cp_src, *cp_dst, *cp_mix;
+ int mfac;
+ uint col_mix = 0;
+
+ if (fac == 0) {
+ return col_src;
+ }
+ else if (fac >= 255) {
+ return col_dst;
+ }
+
+ mfac = 255 - fac;
+
+ cp_src = (uchar *)&col_src;
+ cp_dst = (uchar *)&col_dst;
+ cp_mix = (uchar *)&col_mix;
+
+ /* See if are 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)) {
+ return col_src;
+ }
+
+ cp_mix[0] = divide_round_i(mfac * cp_src[0] + fac * cp_dst[0], 255);
+ cp_mix[1] = divide_round_i(mfac * cp_src[1] + fac * cp_dst[1], 255);
+ cp_mix[2] = divide_round_i(mfac * cp_src[2] + fac * cp_dst[2], 255);
+ cp_mix[3] = divide_round_i(mfac * cp_src[3] + fac * cp_dst[3], 255);
+
+ return col_mix;
}
BLI_INLINE uint mcol_darken(uint col_src, uint col_dst, int fac)
{
- uchar *cp_src, *cp_dst, *cp_mix;
- int mfac;
- uint col_mix = 0;
-
- if (fac == 0) {
- return col_src;
- }
- else if (fac >= 255) {
- return col_dst;
- }
-
- mfac = 255 - fac;
-
- cp_src = (uchar *)&col_src;
- cp_dst = (uchar *)&col_dst;
- cp_mix = (uchar *)&col_mix;
-
- /* See if were 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)) {
- return col_src;
- }
-
- cp_mix[0] = divide_round_i((mfac * cp_src[0] + fac * cp_dst[0]), 255);
- cp_mix[1] = divide_round_i((mfac * cp_src[1] + fac * cp_dst[1]), 255);
- cp_mix[2] = divide_round_i((mfac * cp_src[2] + fac * cp_dst[2]), 255);
- cp_mix[3] = divide_round_i((mfac * cp_src[3] + fac * cp_dst[3]), 255);
- return col_mix;
+ uchar *cp_src, *cp_dst, *cp_mix;
+ int mfac;
+ uint col_mix = 0;
+
+ if (fac == 0) {
+ return col_src;
+ }
+ else if (fac >= 255) {
+ return col_dst;
+ }
+
+ mfac = 255 - fac;
+
+ cp_src = (uchar *)&col_src;
+ cp_dst = (uchar *)&col_dst;
+ cp_mix = (uchar *)&col_mix;
+
+ /* See if were 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)) {
+ return col_src;
+ }
+
+ cp_mix[0] = divide_round_i((mfac * cp_src[0] + fac * cp_dst[0]), 255);
+ cp_mix[1] = divide_round_i((mfac * cp_src[1] + fac * cp_dst[1]), 255);
+ cp_mix[2] = divide_round_i((mfac * cp_src[2] + fac * cp_dst[2]), 255);
+ cp_mix[3] = divide_round_i((mfac * cp_src[3] + fac * cp_dst[3]), 255);
+ return col_mix;
}
BLI_INLINE uint mcol_colordodge(uint col_src, uint col_dst, int fac)
{
- uchar *cp_src, *cp_dst, *cp_mix;
- int mfac, temp;
- uint col_mix = 0;
-
- if (fac == 0) {
- return col_src;
- }
-
- mfac = 255 - fac;
-
- cp_src = (uchar *)&col_src;
- cp_dst = (uchar *)&col_dst;
- cp_mix = (uchar *)&col_mix;
-
- temp = (cp_dst[0] == 255) ? 255 : min_ii((cp_src[0] * 225) / (255 - cp_dst[0]), 255);
- cp_mix[0] = (mfac * cp_src[0] + temp * fac) / 255;
- temp = (cp_dst[1] == 255) ? 255 : min_ii((cp_src[1] * 225) / (255 - cp_dst[1]), 255);
- cp_mix[1] = (mfac * cp_src[1] + temp * fac) / 255;
- temp = (cp_dst[2] == 255) ? 255 : min_ii((cp_src[2] * 225) / (255 - cp_dst[2]), 255);
- cp_mix[2] = (mfac * cp_src[2] + temp * fac) / 255;
- temp = (cp_dst[3] == 255) ? 255 : min_ii((cp_src[3] * 225) / (255 - cp_dst[3]), 255);
- cp_mix[3] = (mfac * cp_src[3] + temp * fac) / 255;
- return col_mix;
+ uchar *cp_src, *cp_dst, *cp_mix;
+ int mfac, temp;
+ uint col_mix = 0;
+
+ if (fac == 0) {
+ return col_src;
+ }
+
+ mfac = 255 - fac;
+
+ cp_src = (uchar *)&col_src;
+ cp_dst = (uchar *)&col_dst;
+ cp_mix = (uchar *)&col_mix;
+
+ temp = (cp_dst[0] == 255) ? 255 : min_ii((cp_src[0] * 225) / (255 - cp_dst[0]), 255);
+ cp_mix[0] = (mfac * cp_src[0] + temp * fac) / 255;
+ temp = (cp_dst[1] == 255) ? 255 : min_ii((cp_src[1] * 225) / (255 - cp_dst[1]), 255);
+ cp_mix[1] = (mfac * cp_src[1] + temp * fac) / 255;
+ temp = (cp_dst[2] == 255) ? 255 : min_ii((cp_src[2] * 225) / (255 - cp_dst[2]), 255);
+ cp_mix[2] = (mfac * cp_src[2] + temp * fac) / 255;
+ temp = (cp_dst[3] == 255) ? 255 : min_ii((cp_src[3] * 225) / (255 - cp_dst[3]), 255);
+ cp_mix[3] = (mfac * cp_src[3] + temp * fac) / 255;
+ return col_mix;
}
BLI_INLINE uint mcol_difference(uint col_src, uint col_dst, int fac)
{
- uchar *cp_src, *cp_dst, *cp_mix;
- int mfac, temp;
- uint col_mix = 0;
-
- if (fac == 0) {
- return col_src;
- }
-
- mfac = 255 - fac;
-
- cp_src = (uchar *)&col_src;
- cp_dst = (uchar *)&col_dst;
- cp_mix = (uchar *)&col_mix;
-
- temp = abs(cp_src[0] - cp_dst[0]);
- cp_mix[0] = (mfac * cp_src[0] + temp * fac) / 255;
- temp = abs(cp_src[1] - cp_dst[1]);
- cp_mix[1] = (mfac * cp_src[1] + temp * fac) / 255;
- temp = abs(cp_src[2] - cp_dst[2]);
- cp_mix[2] = (mfac * cp_src[2] + temp * fac) / 255;
- temp = abs(cp_src[3] - cp_dst[3]);
- cp_mix[3] = (mfac * cp_src[3] + temp * fac) / 255;
- return col_mix;
+ uchar *cp_src, *cp_dst, *cp_mix;
+ int mfac, temp;
+ uint col_mix = 0;
+
+ if (fac == 0) {
+ return col_src;
+ }
+
+ mfac = 255 - fac;
+
+ cp_src = (uchar *)&col_src;
+ cp_dst = (uchar *)&col_dst;
+ cp_mix = (uchar *)&col_mix;
+
+ temp = abs(cp_src[0] - cp_dst[0]);
+ cp_mix[0] = (mfac * cp_src[0] + temp * fac) / 255;
+ temp = abs(cp_src[1] - cp_dst[1]);
+ cp_mix[1] = (mfac * cp_src[1] + temp * fac) / 255;
+ temp = abs(cp_src[2] - cp_dst[2]);
+ cp_mix[2] = (mfac * cp_src[2] + temp * fac) / 255;
+ temp = abs(cp_src[3] - cp_dst[3]);
+ cp_mix[3] = (mfac * cp_src[3] + temp * fac) / 255;
+ return col_mix;
}
BLI_INLINE uint mcol_screen(uint col_src, uint col_dst, int fac)
{
- uchar *cp_src, *cp_dst, *cp_mix;
- int mfac, temp;
- uint col_mix = 0;
-
- if (fac == 0) {
- return col_src;
- }
-
- mfac = 255 - fac;
-
- cp_src = (uchar *)&col_src;
- cp_dst = (uchar *)&col_dst;
- cp_mix = (uchar *)&col_mix;
-
- temp = max_ii(255 - (((255 - cp_src[0]) * (255 - cp_dst[0])) / 255), 0);
- cp_mix[0] = (mfac * cp_src[0] + temp * fac) / 255;
- temp = max_ii(255 - (((255 - cp_src[1]) * (255 - cp_dst[1])) / 255), 0);
- cp_mix[1] = (mfac * cp_src[1] + temp * fac) / 255;
- temp = max_ii(255 - (((255 - cp_src[2]) * (255 - cp_dst[2])) / 255), 0);
- cp_mix[2] = (mfac * cp_src[2] + temp * fac) / 255;
- temp = max_ii(255 - (((255 - cp_src[3]) * (255 - cp_dst[3])) / 255), 0);
- cp_mix[3] = (mfac * cp_src[3] + temp * fac) / 255;
- return col_mix;
+ uchar *cp_src, *cp_dst, *cp_mix;
+ int mfac, temp;
+ uint col_mix = 0;
+
+ if (fac == 0) {
+ return col_src;
+ }
+
+ mfac = 255 - fac;
+
+ cp_src = (uchar *)&col_src;
+ cp_dst = (uchar *)&col_dst;
+ cp_mix = (uchar *)&col_mix;
+
+ temp = max_ii(255 - (((255 - cp_src[0]) * (255 - cp_dst[0])) / 255), 0);
+ cp_mix[0] = (mfac * cp_src[0] + temp * fac) / 255;
+ temp = max_ii(255 - (((255 - cp_src[1]) * (255 - cp_dst[1])) / 255), 0);
+ cp_mix[1] = (mfac * cp_src[1] + temp * fac) / 255;
+ temp = max_ii(255 - (((255 - cp_src[2]) * (255 - cp_dst[2])) / 255), 0);
+ cp_mix[2] = (mfac * cp_src[2] + temp * fac) / 255;
+ temp = max_ii(255 - (((255 - cp_src[3]) * (255 - cp_dst[3])) / 255), 0);
+ cp_mix[3] = (mfac * cp_src[3] + temp * fac) / 255;
+ return col_mix;
}
BLI_INLINE uint mcol_hardlight(uint col_src, uint col_dst, int fac)
{
- uchar *cp_src, *cp_dst, *cp_mix;
- int mfac, temp;
- uint col_mix = 0;
-
- if (fac == 0) {
- return col_src;
- }
-
- mfac = 255 - fac;
-
- cp_src = (uchar *)&col_src;
- cp_dst = (uchar *)&col_dst;
- cp_mix = (uchar *)&col_mix;
-
- int i = 0;
-
- for (i = 0; i < 4; i++) {
- if (cp_dst[i] > 127) {
- temp = 255 - ((255 - 2 * (cp_dst[i] - 127)) * (255 - cp_src[i]) / 255);
- }
- else {
- temp = (2 * cp_dst[i] * cp_src[i]) >> 8;
- }
- cp_mix[i] = min_ii((mfac * cp_src[i] + temp * fac) / 255, 255);
- }
- return col_mix;
+ uchar *cp_src, *cp_dst, *cp_mix;
+ int mfac, temp;
+ uint col_mix = 0;
+
+ if (fac == 0) {
+ return col_src;
+ }
+
+ mfac = 255 - fac;
+
+ cp_src = (uchar *)&col_src;
+ cp_dst = (uchar *)&col_dst;
+ cp_mix = (uchar *)&col_mix;
+
+ int i = 0;
+
+ for (i = 0; i < 4; i++) {
+ if (cp_dst[i] > 127) {
+ temp = 255 - ((255 - 2 * (cp_dst[i] - 127)) * (255 - cp_src[i]) / 255);
+ }
+ else {
+ temp = (2 * cp_dst[i] * cp_src[i]) >> 8;
+ }
+ cp_mix[i] = min_ii((mfac * cp_src[i] + temp * fac) / 255, 255);
+ }
+ return col_mix;
}
BLI_INLINE uint mcol_overlay(uint col_src, uint col_dst, int fac)
{
- uchar *cp_src, *cp_dst, *cp_mix;
- int mfac, temp;
- uint col_mix = 0;
-
- if (fac == 0) {
- return col_src;
- }
-
- mfac = 255 - fac;
-
- cp_src = (uchar *)&col_src;
- cp_dst = (uchar *)&col_dst;
- cp_mix = (uchar *)&col_mix;
-
- int i = 0;
-
- for (i = 0; i < 4; i++) {
- if (cp_src[i] > 127) {
- temp = 255 - ((255 - 2 * (cp_src[i] - 127)) * (255 - cp_dst[i]) / 255);
- }
- else {
- temp = (2 * cp_dst[i] * cp_src[i]) >> 8;
- }
- cp_mix[i] = min_ii((mfac * cp_src[i] + temp * fac) / 255, 255);
- }
- return col_mix;
+ uchar *cp_src, *cp_dst, *cp_mix;
+ int mfac, temp;
+ uint col_mix = 0;
+
+ if (fac == 0) {
+ return col_src;
+ }
+
+ mfac = 255 - fac;
+
+ cp_src = (uchar *)&col_src;
+ cp_dst = (uchar *)&col_dst;
+ cp_mix = (uchar *)&col_mix;
+
+ int i = 0;
+
+ for (i = 0; i < 4; i++) {
+ if (cp_src[i] > 127) {
+ temp = 255 - ((255 - 2 * (cp_src[i] - 127)) * (255 - cp_dst[i]) / 255);
+ }
+ else {
+ temp = (2 * cp_dst[i] * cp_src[i]) >> 8;
+ }
+ cp_mix[i] = min_ii((mfac * cp_src[i] + temp * fac) / 255, 255);
+ }
+ return col_mix;
}
BLI_INLINE uint mcol_softlight(uint col_src, uint col_dst, int fac)
{
- uchar *cp_src, *cp_dst, *cp_mix;
- int mfac, temp;
- uint col_mix = 0;
-
- if (fac == 0) {
- return col_src;
- }
-
- mfac = 255 - fac;
-
- cp_src = (uchar *)&col_src;
- cp_dst = (uchar *)&col_dst;
- cp_mix = (uchar *)&col_mix;
-
- int i = 0;
-
- for (i = 0; i < 4; i++) {
- if (cp_src[i] < 127) {
- temp = ((2 * ((cp_dst[i] / 2) + 64)) * cp_src[i]) / 255;
- }
- else {
- temp = 255 - (2 * (255 - ((cp_dst[i] / 2) + 64)) * (255 - cp_src[i]) / 255);
- }
- cp_mix[i] = (temp * fac + cp_src[i] * mfac) / 255;
- }
- return col_mix;
+ uchar *cp_src, *cp_dst, *cp_mix;
+ int mfac, temp;
+ uint col_mix = 0;
+
+ if (fac == 0) {
+ return col_src;
+ }
+
+ mfac = 255 - fac;
+
+ cp_src = (uchar *)&col_src;
+ cp_dst = (uchar *)&col_dst;
+ cp_mix = (uchar *)&col_mix;
+
+ int i = 0;
+
+ for (i = 0; i < 4; i++) {
+ if (cp_src[i] < 127) {
+ temp = ((2 * ((cp_dst[i] / 2) + 64)) * cp_src[i]) / 255;
+ }
+ else {
+ temp = 255 - (2 * (255 - ((cp_dst[i] / 2) + 64)) * (255 - cp_src[i]) / 255);
+ }
+ cp_mix[i] = (temp * fac + cp_src[i] * mfac) / 255;
+ }
+ return col_mix;
}
BLI_INLINE uint mcol_exclusion(uint col_src, uint col_dst, int fac)
{
- uchar *cp_src, *cp_dst, *cp_mix;
- int mfac, temp;
- uint col_mix = 0;
+ uchar *cp_src, *cp_dst, *cp_mix;
+ int mfac, temp;
+ uint col_mix = 0;
- if (fac == 0) {
- return col_src;
- }
+ if (fac == 0) {
+ return col_src;
+ }
- mfac = 255 - fac;
+ mfac = 255 - fac;
- cp_src = (uchar *)&col_src;
- cp_dst = (uchar *)&col_dst;
- cp_mix = (uchar *)&col_mix;
+ cp_src = (uchar *)&col_src;
+ cp_dst = (uchar *)&col_dst;
+ cp_mix = (uchar *)&col_mix;
- int i = 0;
+ int i = 0;
- for (i = 0; i < 4; i++) {
- temp = 127 - ((2 * (cp_src[i] - 127) * (cp_dst[i] - 127)) / 255);
- cp_mix[i] = (temp * fac + cp_src[i] * mfac) / 255;
- }
- return col_mix;
+ for (i = 0; i < 4; i++) {
+ temp = 127 - ((2 * (cp_src[i] - 127) * (cp_dst[i] - 127)) / 255);
+ cp_mix[i] = (temp * fac + cp_src[i] * mfac) / 255;
+ }
+ return col_mix;
}
BLI_INLINE uint mcol_luminosity(uint col_src, uint col_dst, int fac)
{
- uchar *cp_src, *cp_dst, *cp_mix;
- int mfac;
- uint col_mix = 0;
+ uchar *cp_src, *cp_dst, *cp_mix;
+ int mfac;
+ uint col_mix = 0;
- if (fac == 0) {
- return col_src;
- }
+ if (fac == 0) {
+ return col_src;
+ }
- mfac = 255 - fac;
+ mfac = 255 - fac;
- cp_src = (uchar *)&col_src;
- cp_dst = (uchar *)&col_dst;
- cp_mix = (uchar *)&col_mix;
+ cp_src = (uchar *)&col_src;
+ cp_dst = (uchar *)&col_dst;
+ cp_mix = (uchar *)&col_mix;
- float h1, s1, v1;
- float h2, s2, v2;
- float r, g, b;
- rgb_to_hsv(cp_src[0] / 255.0f, cp_src[1] / 255.0f, cp_src[2] / 255.0f, &h1, &s1, &v1);
- rgb_to_hsv(cp_dst[0] / 255.0f, cp_dst[1] / 255.0f, cp_dst[2] / 255.0f, &h2, &s2, &v2);
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+ rgb_to_hsv(cp_src[0] / 255.0f, cp_src[1] / 255.0f, cp_src[2] / 255.0f, &h1, &s1, &v1);
+ rgb_to_hsv(cp_dst[0] / 255.0f, cp_dst[1] / 255.0f, cp_dst[2] / 255.0f, &h2, &s2, &v2);
- v1 = v2;
+ v1 = v2;
- hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
- cp_mix[0] = ((int)(r * 255.0f) * fac + mfac * cp_src[0]) / 255;
- cp_mix[1] = ((int)(g * 255.0f) * fac + mfac * cp_src[1]) / 255;
- cp_mix[2] = ((int)(b * 255.0f) * fac + mfac * cp_src[2]) / 255;
- cp_mix[3] = ((int)(cp_dst[3]) * fac + mfac * cp_src[3]) / 255;
- return col_mix;
+ cp_mix[0] = ((int)(r * 255.0f) * fac + mfac * cp_src[0]) / 255;
+ cp_mix[1] = ((int)(g * 255.0f) * fac + mfac * cp_src[1]) / 255;
+ cp_mix[2] = ((int)(b * 255.0f) * fac + mfac * cp_src[2]) / 255;
+ cp_mix[3] = ((int)(cp_dst[3]) * fac + mfac * cp_src[3]) / 255;
+ return col_mix;
}
BLI_INLINE uint mcol_saturation(uint col_src, uint col_dst, int fac)
{
- uchar *cp_src, *cp_dst, *cp_mix;
- int mfac;
- uint col_mix = 0;
+ uchar *cp_src, *cp_dst, *cp_mix;
+ int mfac;
+ uint col_mix = 0;
- if (fac == 0) {
- return col_src;
- }
+ if (fac == 0) {
+ return col_src;
+ }
- mfac = 255 - fac;
+ mfac = 255 - fac;
- cp_src = (uchar *)&col_src;
- cp_dst = (uchar *)&col_dst;
- cp_mix = (uchar *)&col_mix;
+ cp_src = (uchar *)&col_src;
+ cp_dst = (uchar *)&col_dst;
+ cp_mix = (uchar *)&col_mix;
- float h1, s1, v1;
- float h2, s2, v2;
- float r, g, b;
- rgb_to_hsv(cp_src[0] / 255.0f, cp_src[1] / 255.0f, cp_src[2] / 255.0f, &h1, &s1, &v1);
- rgb_to_hsv(cp_dst[0] / 255.0f, cp_dst[1] / 255.0f, cp_dst[2] / 255.0f, &h2, &s2, &v2);
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+ rgb_to_hsv(cp_src[0] / 255.0f, cp_src[1] / 255.0f, cp_src[2] / 255.0f, &h1, &s1, &v1);
+ rgb_to_hsv(cp_dst[0] / 255.0f, cp_dst[1] / 255.0f, cp_dst[2] / 255.0f, &h2, &s2, &v2);
- if (s1 > EPS_SATURATION) {
- s1 = s2;
- }
+ if (s1 > EPS_SATURATION) {
+ s1 = s2;
+ }
- hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
- cp_mix[0] = ((int)(r * 255.0f) * fac + mfac * cp_src[0]) / 255;
- cp_mix[1] = ((int)(g * 255.0f) * fac + mfac * cp_src[1]) / 255;
- cp_mix[2] = ((int)(b * 255.0f) * fac + mfac * cp_src[2]) / 255;
- return col_mix;
+ cp_mix[0] = ((int)(r * 255.0f) * fac + mfac * cp_src[0]) / 255;
+ cp_mix[1] = ((int)(g * 255.0f) * fac + mfac * cp_src[1]) / 255;
+ cp_mix[2] = ((int)(b * 255.0f) * fac + mfac * cp_src[2]) / 255;
+ return col_mix;
}
BLI_INLINE uint mcol_hue(uint col_src, uint col_dst, int fac)
{
- uchar *cp_src, *cp_dst, *cp_mix;
- int mfac;
- uint col_mix = 0;
+ uchar *cp_src, *cp_dst, *cp_mix;
+ int mfac;
+ uint col_mix = 0;
- if (fac == 0) {
- return col_src;
- }
+ if (fac == 0) {
+ return col_src;
+ }
- mfac = 255 - fac;
+ mfac = 255 - fac;
- cp_src = (uchar *)&col_src;
- cp_dst = (uchar *)&col_dst;
- cp_mix = (uchar *)&col_mix;
+ cp_src = (uchar *)&col_src;
+ cp_dst = (uchar *)&col_dst;
+ cp_mix = (uchar *)&col_mix;
- float h1, s1, v1;
- float h2, s2, v2;
- float r, g, b;
- rgb_to_hsv(cp_src[0] / 255.0f, cp_src[1] / 255.0f, cp_src[2] / 255.0f, &h1, &s1, &v1);
- rgb_to_hsv(cp_dst[0] / 255.0f, cp_dst[1] / 255.0f, cp_dst[2] / 255.0f, &h2, &s2, &v2);
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+ rgb_to_hsv(cp_src[0] / 255.0f, cp_src[1] / 255.0f, cp_src[2] / 255.0f, &h1, &s1, &v1);
+ rgb_to_hsv(cp_dst[0] / 255.0f, cp_dst[1] / 255.0f, cp_dst[2] / 255.0f, &h2, &s2, &v2);
- h1 = h2;
+ h1 = h2;
- hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
- cp_mix[0] = ((int)(r * 255.0f) * fac + mfac * cp_src[0]) / 255;
- cp_mix[1] = ((int)(g * 255.0f) * fac + mfac * cp_src[1]) / 255;
- cp_mix[2] = ((int)(b * 255.0f) * fac + mfac * cp_src[2]) / 255;
- cp_mix[3] = ((int)(cp_dst[3]) * fac + mfac * cp_src[3]) / 255;
- return col_mix;
+ cp_mix[0] = ((int)(r * 255.0f) * fac + mfac * cp_src[0]) / 255;
+ cp_mix[1] = ((int)(g * 255.0f) * fac + mfac * cp_src[1]) / 255;
+ cp_mix[2] = ((int)(b * 255.0f) * fac + mfac * cp_src[2]) / 255;
+ cp_mix[3] = ((int)(cp_dst[3]) * fac + mfac * cp_src[3]) / 255;
+ return col_mix;
}
BLI_INLINE uint mcol_alpha_add(uint col_src, int fac)
{
- uchar *cp_src, *cp_mix;
- int temp;
- uint col_mix = col_src;
+ uchar *cp_src, *cp_mix;
+ int temp;
+ uint col_mix = col_src;
- if (fac == 0) {
- return col_src;
- }
+ if (fac == 0) {
+ return col_src;
+ }
- cp_src = (uchar *)&col_src;
- cp_mix = (uchar *)&col_mix;
+ cp_src = (uchar *)&col_src;
+ cp_mix = (uchar *)&col_mix;
- temp = cp_src[3] + fac;
- cp_mix[3] = (temp > 254) ? 255 : temp;
+ temp = cp_src[3] + fac;
+ cp_mix[3] = (temp > 254) ? 255 : temp;
- return col_mix;
+ return col_mix;
}
BLI_INLINE uint mcol_alpha_sub(uint col_src, int fac)
{
- uchar *cp_src, *cp_mix;
- int temp;
- uint col_mix = col_src;
+ uchar *cp_src, *cp_mix;
+ int temp;
+ uint col_mix = col_src;
- if (fac == 0) {
- return col_src;
- }
+ if (fac == 0) {
+ return col_src;
+ }
- cp_src = (uchar *)&col_src;
- cp_mix = (uchar *)&col_mix;
+ cp_src = (uchar *)&col_src;
+ cp_mix = (uchar *)&col_mix;
- temp = cp_src[3] - fac;
- cp_mix[3] = temp < 0 ? 0 : temp;
+ temp = cp_src[3] - fac;
+ cp_mix[3] = temp < 0 ? 0 : temp;
- return col_mix;
+ return col_mix;
}
/* wpaint has 'ED_wpaint_blend_tool' */
-uint ED_vpaint_blend_tool(
- const int tool, const uint col,
- const uint paintcol, const int alpha_i)
+uint ED_vpaint_blend_tool(const int tool, const uint col, const uint paintcol, const int alpha_i)
{
- switch ((IMB_BlendMode)tool) {
- case IMB_BLEND_MIX: return mcol_blend(col, paintcol, alpha_i);
- case IMB_BLEND_ADD: return mcol_add(col, paintcol, alpha_i);
- case IMB_BLEND_SUB: return mcol_sub(col, paintcol, alpha_i);
- case IMB_BLEND_MUL: return mcol_mul(col, paintcol, alpha_i);
- case IMB_BLEND_LIGHTEN: return mcol_lighten(col, paintcol, alpha_i);
- case IMB_BLEND_DARKEN: return mcol_darken(col, paintcol, alpha_i);
- case IMB_BLEND_COLORDODGE: return mcol_colordodge(col, paintcol, alpha_i);
- case IMB_BLEND_DIFFERENCE: return mcol_difference(col, paintcol, alpha_i);
- case IMB_BLEND_SCREEN: return mcol_screen(col, paintcol, alpha_i);
- case IMB_BLEND_HARDLIGHT: return mcol_hardlight(col, paintcol, alpha_i);
- case IMB_BLEND_OVERLAY: return mcol_overlay(col, paintcol, alpha_i);
- case IMB_BLEND_SOFTLIGHT: return mcol_softlight(col, paintcol, alpha_i);
- case IMB_BLEND_EXCLUSION: return mcol_exclusion(col, paintcol, alpha_i);
- case IMB_BLEND_LUMINOSITY: return mcol_luminosity(col, paintcol, alpha_i);
- case IMB_BLEND_SATURATION: return mcol_saturation(col, paintcol, alpha_i);
- case IMB_BLEND_HUE: return mcol_hue(col, paintcol, alpha_i);
- /* non-color */
- case IMB_BLEND_ERASE_ALPHA: return mcol_alpha_sub(col, alpha_i);
- case IMB_BLEND_ADD_ALPHA: return mcol_alpha_add(col, alpha_i);
- default:
- BLI_assert(0);
- return 0;
- }
+ switch ((IMB_BlendMode)tool) {
+ case IMB_BLEND_MIX:
+ return mcol_blend(col, paintcol, alpha_i);
+ case IMB_BLEND_ADD:
+ return mcol_add(col, paintcol, alpha_i);
+ case IMB_BLEND_SUB:
+ return mcol_sub(col, paintcol, alpha_i);
+ case IMB_BLEND_MUL:
+ return mcol_mul(col, paintcol, alpha_i);
+ case IMB_BLEND_LIGHTEN:
+ return mcol_lighten(col, paintcol, alpha_i);
+ case IMB_BLEND_DARKEN:
+ return mcol_darken(col, paintcol, alpha_i);
+ case IMB_BLEND_COLORDODGE:
+ return mcol_colordodge(col, paintcol, alpha_i);
+ case IMB_BLEND_DIFFERENCE:
+ return mcol_difference(col, paintcol, alpha_i);
+ case IMB_BLEND_SCREEN:
+ return mcol_screen(col, paintcol, alpha_i);
+ case IMB_BLEND_HARDLIGHT:
+ return mcol_hardlight(col, paintcol, alpha_i);
+ case IMB_BLEND_OVERLAY:
+ return mcol_overlay(col, paintcol, alpha_i);
+ case IMB_BLEND_SOFTLIGHT:
+ return mcol_softlight(col, paintcol, alpha_i);
+ case IMB_BLEND_EXCLUSION:
+ return mcol_exclusion(col, paintcol, alpha_i);
+ case IMB_BLEND_LUMINOSITY:
+ return mcol_luminosity(col, paintcol, alpha_i);
+ case IMB_BLEND_SATURATION:
+ return mcol_saturation(col, paintcol, alpha_i);
+ case IMB_BLEND_HUE:
+ return mcol_hue(col, paintcol, alpha_i);
+ /* non-color */
+ case IMB_BLEND_ERASE_ALPHA:
+ return mcol_alpha_sub(col, alpha_i);
+ case IMB_BLEND_ADD_ALPHA:
+ return mcol_alpha_add(col, alpha_i);
+ default:
+ BLI_assert(0);
+ return 0;
+ }
}
/** \} */
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_proj.c b/source/blender/editors/sculpt_paint/paint_vertex_proj.c
index 9246c852b3a..7bca7745ca0 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_proj.c
@@ -43,195 +43,193 @@
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "paint_intern.h" /* own include */
-
+#include "paint_intern.h" /* own include */
/* Opaque Structs for internal use */
/* stored while painting */
struct VertProjHandle {
- CoNo *vcosnos;
+ CoNo *vcosnos;
- bool use_update;
+ bool use_update;
- /* use for update */
- float *dists_sq;
+ /* use for update */
+ float *dists_sq;
- Object *ob;
- Scene *scene;
+ Object *ob;
+ Scene *scene;
};
/* only for passing to the callbacks */
struct VertProjUpdate {
- struct VertProjHandle *vp_handle;
+ struct VertProjHandle *vp_handle;
- /* runtime */
- ARegion *ar;
- const float *mval_fl;
+ /* runtime */
+ ARegion *ar;
+ const float *mval_fl;
};
-
/* -------------------------------------------------------------------- */
/* Internal Init */
static void vpaint_proj_dm_map_cosnos_init__map_cb(
- void *userData, int index, const float co[3],
- const float no_f[3], const short no_s[3])
+ void *userData, int index, const float co[3], const float no_f[3], const short no_s[3])
{
- struct VertProjHandle *vp_handle = userData;
- CoNo *co_no = &vp_handle->vcosnos[index];
-
- /* check if we've been here before (normal should not be 0) */
- if (!is_zero_v3(co_no->no)) {
- /* remember that multiple dm verts share the same source vert */
- vp_handle->use_update = true;
- return;
- }
-
- copy_v3_v3(co_no->co, co);
- if (no_f) {
- copy_v3_v3(co_no->no, no_f);
- }
- else {
- normal_short_to_float_v3(co_no->no, no_s);
- }
+ struct VertProjHandle *vp_handle = userData;
+ CoNo *co_no = &vp_handle->vcosnos[index];
+
+ /* check if we've been here before (normal should not be 0) */
+ if (!is_zero_v3(co_no->no)) {
+ /* remember that multiple dm verts share the same source vert */
+ vp_handle->use_update = true;
+ return;
+ }
+
+ copy_v3_v3(co_no->co, co);
+ if (no_f) {
+ copy_v3_v3(co_no->no, no_f);
+ }
+ else {
+ normal_short_to_float_v3(co_no->no, no_s);
+ }
}
-static void vpaint_proj_dm_map_cosnos_init(
- struct Depsgraph *depsgraph, Scene *UNUSED(scene), Object *ob,
- struct VertProjHandle *vp_handle)
+static void vpaint_proj_dm_map_cosnos_init(struct Depsgraph *depsgraph,
+ Scene *UNUSED(scene),
+ Object *ob,
+ struct VertProjHandle *vp_handle)
{
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- Mesh *me = ob->data;
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ Mesh *me = ob->data;
- CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH_ORIGINDEX;
- Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &cddata_masks);
+ CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH_ORIGINDEX;
+ Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &cddata_masks);
- memset(vp_handle->vcosnos, 0, sizeof(*vp_handle->vcosnos) * me->totvert);
- BKE_mesh_foreach_mapped_vert(me_eval, vpaint_proj_dm_map_cosnos_init__map_cb, vp_handle, MESH_FOREACH_USE_NORMAL);
+ memset(vp_handle->vcosnos, 0, sizeof(*vp_handle->vcosnos) * me->totvert);
+ BKE_mesh_foreach_mapped_vert(
+ me_eval, vpaint_proj_dm_map_cosnos_init__map_cb, vp_handle, MESH_FOREACH_USE_NORMAL);
}
-
/* -------------------------------------------------------------------- */
/* Internal Update */
/* Same as init but take mouse location into account */
static void vpaint_proj_dm_map_cosnos_update__map_cb(
- void *userData, int index, const float co[3],
- const float no_f[3], const short no_s[3])
+ void *userData, int index, const float co[3], const float no_f[3], const short no_s[3])
{
- struct VertProjUpdate *vp_update = userData;
- struct VertProjHandle *vp_handle = vp_update->vp_handle;
-
- CoNo *co_no = &vp_handle->vcosnos[index];
-
- /* find closest vertex */
- {
- /* first find distance to this vertex */
- 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) == 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]) {
- /* bail out! */
- return;
- }
-
- vp_handle->dists_sq[index] = dist_sq;
- }
- else if (vp_handle->dists_sq[index] != FLT_MAX) {
- /* already initialized & couldn't project this 'co' */
- return;
- }
- }
- /* continue with regular functionality */
-
- copy_v3_v3(co_no->co, co);
- if (no_f) {
- copy_v3_v3(co_no->no, no_f);
- }
- else {
- normal_short_to_float_v3(co_no->no, no_s);
- }
+ struct VertProjUpdate *vp_update = userData;
+ struct VertProjHandle *vp_handle = vp_update->vp_handle;
+
+ CoNo *co_no = &vp_handle->vcosnos[index];
+
+ /* find closest vertex */
+ {
+ /* first find distance to this vertex */
+ 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) ==
+ 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]) {
+ /* bail out! */
+ return;
+ }
+
+ vp_handle->dists_sq[index] = dist_sq;
+ }
+ else if (vp_handle->dists_sq[index] != FLT_MAX) {
+ /* already initialized & couldn't project this 'co' */
+ return;
+ }
+ }
+ /* continue with regular functionality */
+
+ copy_v3_v3(co_no->co, co);
+ if (no_f) {
+ copy_v3_v3(co_no->no, no_f);
+ }
+ else {
+ normal_short_to_float_v3(co_no->no, no_s);
+ }
}
-static void vpaint_proj_dm_map_cosnos_update(
- struct Depsgraph *depsgraph, struct VertProjHandle *vp_handle,
- ARegion *ar, const float mval_fl[2])
+static void vpaint_proj_dm_map_cosnos_update(struct Depsgraph *depsgraph,
+ struct VertProjHandle *vp_handle,
+ ARegion *ar,
+ const float mval_fl[2])
{
- struct VertProjUpdate vp_update = {vp_handle, ar, mval_fl};
+ struct VertProjUpdate vp_update = {vp_handle, ar, mval_fl};
- Object *ob = vp_handle->ob;
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- Mesh *me = ob->data;
+ Object *ob = vp_handle->ob;
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ Mesh *me = ob->data;
- CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH_ORIGINDEX;
- Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &cddata_masks);
+ CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH_ORIGINDEX;
+ Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &cddata_masks);
- /* quick sanity check - we shouldn't have to run this if there are no modifiers */
- BLI_assert(BLI_listbase_is_empty(&ob->modifiers) == false);
+ /* quick sanity check - we shouldn't have to run this if there are no modifiers */
+ BLI_assert(BLI_listbase_is_empty(&ob->modifiers) == false);
- copy_vn_fl(vp_handle->dists_sq, me->totvert, FLT_MAX);
- BKE_mesh_foreach_mapped_vert(me_eval, vpaint_proj_dm_map_cosnos_update__map_cb, &vp_update, MESH_FOREACH_USE_NORMAL);
+ copy_vn_fl(vp_handle->dists_sq, me->totvert, FLT_MAX);
+ BKE_mesh_foreach_mapped_vert(
+ me_eval, vpaint_proj_dm_map_cosnos_update__map_cb, &vp_update, MESH_FOREACH_USE_NORMAL);
}
-
/* -------------------------------------------------------------------- */
/* Public Functions */
-struct VertProjHandle *ED_vpaint_proj_handle_create(
- struct Depsgraph *depsgraph, Scene *scene, Object *ob,
- CoNo **r_vcosnos)
+struct VertProjHandle *ED_vpaint_proj_handle_create(struct Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ CoNo **r_vcosnos)
{
- struct VertProjHandle *vp_handle = MEM_mallocN(sizeof(struct VertProjHandle), __func__);
- Mesh *me = ob->data;
+ struct VertProjHandle *vp_handle = MEM_mallocN(sizeof(struct VertProjHandle), __func__);
+ Mesh *me = ob->data;
- /* setup the handle */
- vp_handle->vcosnos = MEM_mallocN(sizeof(CoNo) * me->totvert, "vertexcosnos map");
- vp_handle->use_update = false;
+ /* setup the handle */
+ vp_handle->vcosnos = MEM_mallocN(sizeof(CoNo) * me->totvert, "vertexcosnos map");
+ vp_handle->use_update = false;
- /* sets 'use_update' if needed */
- vpaint_proj_dm_map_cosnos_init(depsgraph, scene, ob, vp_handle);
+ /* sets 'use_update' if needed */
+ vpaint_proj_dm_map_cosnos_init(depsgraph, scene, ob, vp_handle);
- if (vp_handle->use_update) {
- vp_handle->dists_sq = MEM_mallocN(sizeof(float) * me->totvert, __func__);
+ if (vp_handle->use_update) {
+ vp_handle->dists_sq = MEM_mallocN(sizeof(float) * me->totvert, __func__);
- vp_handle->ob = ob;
- vp_handle->scene = scene;
- }
- else {
- vp_handle->dists_sq = NULL;
+ vp_handle->ob = ob;
+ vp_handle->scene = scene;
+ }
+ else {
+ vp_handle->dists_sq = NULL;
- vp_handle->ob = NULL;
- vp_handle->scene = NULL;
- }
+ vp_handle->ob = NULL;
+ vp_handle->scene = NULL;
+ }
- *r_vcosnos = vp_handle->vcosnos;
- return vp_handle;
+ *r_vcosnos = vp_handle->vcosnos;
+ return vp_handle;
}
-void ED_vpaint_proj_handle_update(
- struct Depsgraph *depsgraph, struct VertProjHandle *vp_handle,
- ARegion *ar, const float mval_fl[2])
+void ED_vpaint_proj_handle_update(struct Depsgraph *depsgraph,
+ struct VertProjHandle *vp_handle,
+ ARegion *ar,
+ const float mval_fl[2])
{
- if (vp_handle->use_update) {
- vpaint_proj_dm_map_cosnos_update(depsgraph, vp_handle, ar, mval_fl);
- }
+ if (vp_handle->use_update) {
+ vpaint_proj_dm_map_cosnos_update(depsgraph, vp_handle, ar, mval_fl);
+ }
}
-void ED_vpaint_proj_handle_free(struct VertProjHandle *vp_handle)
+void ED_vpaint_proj_handle_free(struct VertProjHandle *vp_handle)
{
- if (vp_handle->use_update) {
- MEM_freeN(vp_handle->dists_sq);
- }
+ if (vp_handle->use_update) {
+ MEM_freeN(vp_handle->dists_sq);
+ }
- MEM_freeN(vp_handle->vcosnos);
- MEM_freeN(vp_handle);
+ MEM_freeN(vp_handle->vcosnos);
+ MEM_freeN(vp_handle);
}
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 cd366ecff3b..29d150c44fe 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
@@ -63,7 +63,7 @@
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "paint_intern.h" /* own include */
+#include "paint_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Store Previous Weights
@@ -72,37 +72,36 @@
* \{ */
struct WPaintPrev {
- /* previous vertex weights */
- struct MDeformVert *wpaint_prev;
- /* allocation size of prev buffers */
- int tot;
+ /* previous vertex weights */
+ struct MDeformVert *wpaint_prev;
+ /* allocation size of prev buffers */
+ int tot;
};
-
static void wpaint_prev_init(struct WPaintPrev *wpp)
{
- wpp->wpaint_prev = NULL;
- wpp->tot = 0;
+ wpp->wpaint_prev = NULL;
+ wpp->tot = 0;
}
static void wpaint_prev_create(struct WPaintPrev *wpp, MDeformVert *dverts, int dcount)
{
- wpaint_prev_init(wpp);
+ wpaint_prev_init(wpp);
- if (dverts && dcount) {
- wpp->wpaint_prev = MEM_mallocN(sizeof(MDeformVert) * dcount, "wpaint prev");
- wpp->tot = dcount;
- BKE_defvert_array_copy(wpp->wpaint_prev, dverts, dcount);
- }
+ if (dverts && dcount) {
+ wpp->wpaint_prev = MEM_mallocN(sizeof(MDeformVert) * dcount, "wpaint prev");
+ wpp->tot = dcount;
+ BKE_defvert_array_copy(wpp->wpaint_prev, dverts, dcount);
+ }
}
static void wpaint_prev_destroy(struct WPaintPrev *wpp)
{
- if (wpp->wpaint_prev) {
- BKE_defvert_array_free(wpp->wpaint_prev, wpp->tot);
- }
- wpp->wpaint_prev = NULL;
- wpp->tot = 0;
+ if (wpp->wpaint_prev) {
+ BKE_defvert_array_free(wpp->wpaint_prev, wpp->tot);
+ }
+ wpp->wpaint_prev = NULL;
+ wpp->tot = 0;
}
/** \} */
@@ -113,53 +112,59 @@ static void wpaint_prev_destroy(struct WPaintPrev *wpp)
static bool weight_from_bones_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(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) && modifiers_isDeformedByArmature(ob));
}
static int weight_from_bones_exec(bContext *C, wmOperator *op)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- Object *armob = modifiers_isDeformedByArmature(ob);
- Mesh *me = ob->data;
- int type = RNA_enum_get(op->ptr, "type");
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ Object *armob = modifiers_isDeformedByArmature(ob);
+ Mesh *me = ob->data;
+ int type = RNA_enum_get(op->ptr, "type");
- ED_object_vgroup_calc_from_armature(op->reports, depsgraph, scene, ob, armob, type, (me->editflag & ME_EDIT_MIRROR_X));
+ ED_object_vgroup_calc_from_armature(
+ op->reports, depsgraph, scene, ob, armob, type, (me->editflag & ME_EDIT_MIRROR_X));
- DEG_id_tag_update(&me->id, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+ DEG_id_tag_update(&me->id, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void PAINT_OT_weight_from_bones(wmOperatorType *ot)
{
- static const EnumPropertyItem type_items[] = {
- {ARM_GROUPS_AUTO, "AUTOMATIC", 0, "Automatic", "Automatic weights from bones"},
- {ARM_GROUPS_ENVELOPE, "ENVELOPES", 0, "From Envelopes", "Weights from envelopes with user defined radius"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Weight from Bones";
- ot->idname = "PAINT_OT_weight_from_bones";
- ot->description = (
- "Set the weights of the groups matching the attached armature's selected bones, "
- "using the distance between the vertices and the bones");
-
- /* api callbacks */
- ot->exec = weight_from_bones_exec;
- ot->invoke = WM_menu_invoke;
- ot->poll = weight_from_bones_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "Method to use for assigning weights");
+ static const EnumPropertyItem type_items[] = {
+ {ARM_GROUPS_AUTO, "AUTOMATIC", 0, "Automatic", "Automatic weights from bones"},
+ {ARM_GROUPS_ENVELOPE,
+ "ENVELOPES",
+ 0,
+ "From Envelopes",
+ "Weights from envelopes with user defined radius"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Weight from Bones";
+ ot->idname = "PAINT_OT_weight_from_bones";
+ ot->description =
+ ("Set the weights of the groups matching the attached armature's selected bones, "
+ "using the distance between the vertices and the bones");
+
+ /* api callbacks */
+ ot->exec = weight_from_bones_exec;
+ ot->invoke = WM_menu_invoke;
+ ot->poll = weight_from_bones_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", type_items, 0, "Type", "Method to use for assigning weights");
}
/** \} */
@@ -172,95 +177,103 @@ void PAINT_OT_weight_from_bones(wmOperatorType *ot)
/* note: we cant sample frontbuf, weight colors are interpolated too unpredictable */
static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewContext vc;
- Mesh *me;
- bool changed = false;
-
- ED_view3d_viewcontext_init(C, &vc);
- me = BKE_mesh_from_object(vc.obact);
-
- if (me && me->dvert && vc.v3d && vc.rv3d && (vc.obact->actdef != 0)) {
- const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
- int v_idx_best = -1;
- uint index;
-
- view3d_operator_needs_opengl(C);
- ED_view3d_init_mats_rv3d(vc.obact, vc.rv3d);
-
- if (use_vert_sel) {
- if (ED_mesh_pick_vert(C, vc.obact, event->mval, ED_MESH_PICK_DEFAULT_VERT_DIST, true, &index)) {
- v_idx_best = index;
- }
- }
- else {
- if (ED_mesh_pick_face_vert(C, vc.obact, event->mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
- v_idx_best = index;
- }
- else if (ED_mesh_pick_face(C, vc.obact, event->mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
- /* this relies on knowning the internal worksings of ED_mesh_pick_face_vert() */
- BKE_report(op->reports, RPT_WARNING, "The modifier used does not support deformed locations");
- }
- }
-
- if (v_idx_best != -1) { /* should always be valid */
- 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);
-
- /* 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);
-
- if (defbase_tot_sel > 1) {
- if (me->editflag & ME_EDIT_MIRROR_X) {
- BKE_object_defgroup_mirror_selection(
- 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);
-
- /* If auto-normalize is enabled, but weights are not normalized,
- * the value can exceed 1. */
- CLAMP(vgroup_weight, 0.0f, 1.0f);
- }
-
- MEM_freeN(defbase_sel);
- }
-
- BKE_brush_weight_set(vc.scene, brush, vgroup_weight);
- changed = true;
- }
- }
-
- if (changed) {
- /* not really correct since the brush didn't change, but redraws the toolbar */
- WM_main_add_notifier(NC_BRUSH | NA_EDITED, NULL); /* ts->wpaint->paint.brush */
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ ViewContext vc;
+ Mesh *me;
+ bool changed = false;
+
+ ED_view3d_viewcontext_init(C, &vc);
+ me = BKE_mesh_from_object(vc.obact);
+
+ if (me && me->dvert && vc.v3d && vc.rv3d && (vc.obact->actdef != 0)) {
+ const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+ int v_idx_best = -1;
+ uint index;
+
+ view3d_operator_needs_opengl(C);
+ ED_view3d_init_mats_rv3d(vc.obact, vc.rv3d);
+
+ if (use_vert_sel) {
+ if (ED_mesh_pick_vert(
+ C, vc.obact, event->mval, ED_MESH_PICK_DEFAULT_VERT_DIST, true, &index)) {
+ v_idx_best = index;
+ }
+ }
+ else {
+ if (ED_mesh_pick_face_vert(
+ C, vc.obact, event->mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
+ v_idx_best = index;
+ }
+ else if (ED_mesh_pick_face(
+ C, vc.obact, event->mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
+ /* this relies on knowning the internal worksings of ED_mesh_pick_face_vert() */
+ BKE_report(
+ op->reports, RPT_WARNING, "The modifier used does not support deformed locations");
+ }
+ }
+
+ if (v_idx_best != -1) { /* should always be valid */
+ 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);
+
+ /* 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);
+
+ if (defbase_tot_sel > 1) {
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ BKE_object_defgroup_mirror_selection(
+ 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);
+
+ /* If auto-normalize is enabled, but weights are not normalized,
+ * the value can exceed 1. */
+ CLAMP(vgroup_weight, 0.0f, 1.0f);
+ }
+
+ MEM_freeN(defbase_sel);
+ }
+
+ BKE_brush_weight_set(vc.scene, brush, vgroup_weight);
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ /* not really correct since the brush didn't change, but redraws the toolbar */
+ WM_main_add_notifier(NC_BRUSH | NA_EDITED, NULL); /* ts->wpaint->paint.brush */
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void PAINT_OT_weight_sample(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Weight Paint Sample Weight";
- ot->idname = "PAINT_OT_weight_sample";
- ot->description = "Use the mouse to sample a weight in the 3D view";
+ /* identifiers */
+ ot->name = "Weight Paint Sample Weight";
+ ot->idname = "PAINT_OT_weight_sample";
+ ot->description = "Use the mouse to sample a weight in the 3D view";
- /* api callbacks */
- ot->invoke = weight_sample_invoke;
- ot->poll = weight_paint_mode_poll;
+ /* api callbacks */
+ ot->invoke = weight_sample_invoke;
+ ot->poll = weight_paint_mode_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/** \} */
@@ -270,132 +283,137 @@ void PAINT_OT_weight_sample(wmOperatorType *ot)
* \{ */
/* samples cursor location, and gives menu with vertex groups to activate */
-static bool weight_paint_sample_enum_itemf__helper(const MDeformVert *dvert, const int defbase_tot, int *groups)
+static bool weight_paint_sample_enum_itemf__helper(const MDeformVert *dvert,
+ const int defbase_tot,
+ int *groups)
{
- /* this func fills in used vgroup's */
- bool found = false;
- int i = dvert->totweight;
- MDeformWeight *dw;
- for (dw = dvert->dw; i > 0; dw++, i--) {
- if (dw->def_nr < defbase_tot) {
- groups[dw->def_nr] = true;
- found = true;
- }
- }
- return found;
+ /* this func fills in used vgroup's */
+ bool found = false;
+ int i = dvert->totweight;
+ MDeformWeight *dw;
+ for (dw = dvert->dw; i > 0; dw++, i--) {
+ if (dw->def_nr < defbase_tot) {
+ groups[dw->def_nr] = true;
+ found = true;
+ }
+ }
+ return found;
}
-static const EnumPropertyItem *weight_paint_sample_enum_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- if (C) {
- wmWindow *win = CTX_wm_window(C);
- if (win && win->eventstate) {
- ViewContext vc;
- Mesh *me;
-
- ED_view3d_viewcontext_init(C, &vc);
- me = BKE_mesh_from_object(vc.obact);
-
- if (me && me->dvert && vc.v3d && vc.rv3d && vc.obact->defbase.first) {
- const int defbase_tot = BLI_listbase_count(&vc.obact->defbase);
- const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
- int *groups = MEM_callocN(defbase_tot * sizeof(int), "groups");
- bool found = false;
- uint index;
-
- const int mval[2] = {
- win->eventstate->x - vc.ar->winrct.xmin,
- win->eventstate->y - vc.ar->winrct.ymin,
- };
-
- view3d_operator_needs_opengl(C);
- ED_view3d_init_mats_rv3d(vc.obact, vc.rv3d);
-
- if (use_vert_sel) {
- if (ED_mesh_pick_vert(C, vc.obact, mval, ED_MESH_PICK_DEFAULT_VERT_DIST, true, &index)) {
- MDeformVert *dvert = &me->dvert[index];
- found |= weight_paint_sample_enum_itemf__helper(dvert, defbase_tot, groups);
- }
- }
- else {
- if (ED_mesh_pick_face(C, vc.obact, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
- const MPoly *mp = &me->mpoly[index];
- uint fidx = mp->totloop - 1;
-
- do {
- MDeformVert *dvert = &me->dvert[me->mloop[mp->loopstart + fidx].v];
- found |= weight_paint_sample_enum_itemf__helper(dvert, defbase_tot, groups);
- } while (fidx--);
- }
- }
-
- if (found == false) {
- MEM_freeN(groups);
- }
- else {
- EnumPropertyItem *item = NULL, item_tmp = {0};
- int totitem = 0;
- int i = 0;
- bDeformGroup *dg;
- for (dg = vc.obact->defbase.first; dg && i < defbase_tot; i++, dg = dg->next) {
- if (groups[i]) {
- item_tmp.identifier = item_tmp.name = dg->name;
- item_tmp.value = i;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- }
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- MEM_freeN(groups);
- return item;
- }
- }
- }
- }
-
- return DummyRNA_NULL_items;
+ if (C) {
+ wmWindow *win = CTX_wm_window(C);
+ if (win && win->eventstate) {
+ ViewContext vc;
+ Mesh *me;
+
+ ED_view3d_viewcontext_init(C, &vc);
+ me = BKE_mesh_from_object(vc.obact);
+
+ if (me && me->dvert && vc.v3d && vc.rv3d && vc.obact->defbase.first) {
+ const int defbase_tot = BLI_listbase_count(&vc.obact->defbase);
+ const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+ int *groups = MEM_callocN(defbase_tot * sizeof(int), "groups");
+ bool found = false;
+ uint index;
+
+ const int mval[2] = {
+ win->eventstate->x - vc.ar->winrct.xmin,
+ win->eventstate->y - vc.ar->winrct.ymin,
+ };
+
+ view3d_operator_needs_opengl(C);
+ ED_view3d_init_mats_rv3d(vc.obact, vc.rv3d);
+
+ if (use_vert_sel) {
+ if (ED_mesh_pick_vert(C, vc.obact, mval, ED_MESH_PICK_DEFAULT_VERT_DIST, true, &index)) {
+ MDeformVert *dvert = &me->dvert[index];
+ found |= weight_paint_sample_enum_itemf__helper(dvert, defbase_tot, groups);
+ }
+ }
+ else {
+ if (ED_mesh_pick_face(C, vc.obact, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
+ const MPoly *mp = &me->mpoly[index];
+ uint fidx = mp->totloop - 1;
+
+ do {
+ MDeformVert *dvert = &me->dvert[me->mloop[mp->loopstart + fidx].v];
+ found |= weight_paint_sample_enum_itemf__helper(dvert, defbase_tot, groups);
+ } while (fidx--);
+ }
+ }
+
+ if (found == false) {
+ MEM_freeN(groups);
+ }
+ else {
+ EnumPropertyItem *item = NULL, item_tmp = {0};
+ int totitem = 0;
+ int i = 0;
+ bDeformGroup *dg;
+ for (dg = vc.obact->defbase.first; dg && i < defbase_tot; i++, dg = dg->next) {
+ if (groups[i]) {
+ item_tmp.identifier = item_tmp.name = dg->name;
+ item_tmp.value = i;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ MEM_freeN(groups);
+ return item;
+ }
+ }
+ }
+ }
+
+ return DummyRNA_NULL_items;
}
static int weight_sample_group_exec(bContext *C, wmOperator *op)
{
- int type = RNA_enum_get(op->ptr, "group");
- ViewContext vc;
- ED_view3d_viewcontext_init(C, &vc);
+ int type = RNA_enum_get(op->ptr, "group");
+ ViewContext vc;
+ ED_view3d_viewcontext_init(C, &vc);
- BLI_assert(type + 1 >= 0);
- vc.obact->actdef = type + 1;
+ BLI_assert(type + 1 >= 0);
+ vc.obact->actdef = type + 1;
- DEG_id_tag_update(&vc.obact->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, vc.obact);
- return OPERATOR_FINISHED;
+ DEG_id_tag_update(&vc.obact->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, vc.obact);
+ return OPERATOR_FINISHED;
}
/* TODO, we could make this a menu into OBJECT_OT_vertex_group_set_active
* rather than its own operator */
void PAINT_OT_weight_sample_group(wmOperatorType *ot)
{
- PropertyRNA *prop = NULL;
-
- /* identifiers */
- ot->name = "Weight Paint Sample Group";
- ot->idname = "PAINT_OT_weight_sample_group";
- ot->description = "Select one of the vertex groups available under current mouse position";
-
- /* api callbacks */
- ot->exec = weight_sample_group_exec;
- ot->invoke = WM_menu_invoke;
- ot->poll = weight_paint_mode_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* keyingset to use (dynamic enum) */
- prop = RNA_def_enum(ot->srna, "group", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
- RNA_def_enum_funcs(prop, weight_paint_sample_enum_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop = NULL;
+
+ /* identifiers */
+ ot->name = "Weight Paint Sample Group";
+ ot->idname = "PAINT_OT_weight_sample_group";
+ ot->description = "Select one of the vertex groups available under current mouse position";
+
+ /* api callbacks */
+ ot->exec = weight_sample_group_exec;
+ ot->invoke = WM_menu_invoke;
+ ot->poll = weight_paint_mode_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* keyingset to use (dynamic enum) */
+ prop = RNA_def_enum(
+ ot->srna, "group", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
+ RNA_def_enum_funcs(prop, weight_paint_sample_enum_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
/** \} */
@@ -407,123 +425,122 @@ void PAINT_OT_weight_sample_group(wmOperatorType *ot)
/* fills in the selected faces with the current weight and vertex group */
static bool weight_paint_set(Object *ob, float paintweight)
{
- Mesh *me = ob->data;
- const MPoly *mp;
- MDeformWeight *dw, *dw_prev;
- int vgroup_active, vgroup_mirror = -1;
- uint index;
- const bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
-
- /* mutually exclusive, could be made into a */
- const short paint_selmode = ME_EDIT_PAINT_SEL_MODE(me);
-
- if (me->totpoly == 0 || me->dvert == NULL || !me->mpoly) {
- return false;
- }
-
- vgroup_active = ob->actdef - 1;
-
- /* if mirror painting, find the other group */
- if (me->editflag & ME_EDIT_MIRROR_X) {
- vgroup_mirror = ED_wpaint_mirror_vgroup_ensure(ob, vgroup_active);
- }
-
- struct WPaintPrev wpp;
- wpaint_prev_create(&wpp, me->dvert, me->totvert);
-
- for (index = 0, mp = me->mpoly; index < me->totpoly; index++, mp++) {
- uint fidx = mp->totloop - 1;
-
- if ((paint_selmode == SCE_SELECT_FACE) && !(mp->flag & ME_FACE_SEL)) {
- continue;
- }
-
- do {
- uint vidx = me->mloop[mp->loopstart + fidx].v;
-
- if (!me->dvert[vidx].flag) {
- if ((paint_selmode == SCE_SELECT_VERTEX) && !(me->mvert[vidx].flag & SELECT)) {
- continue;
- }
-
- dw = defvert_verify_index(&me->dvert[vidx], vgroup_active);
- if (dw) {
- dw_prev = defvert_verify_index(wpp.wpaint_prev + vidx, vgroup_active);
- dw_prev->weight = dw->weight; /* set the undo weight */
- dw->weight = paintweight;
-
- if (me->editflag & ME_EDIT_MIRROR_X) { /* x mirror painting */
- int j = mesh_get_x_mirror_vert(ob, NULL, vidx, topology);
- 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);
- }
- else {
- dw = defvert_verify_index(me->dvert + j, vgroup_active);
- dw_prev = defvert_verify_index(wpp.wpaint_prev + j, vgroup_active);
- }
- dw_prev->weight = dw->weight; /* set the undo weight */
- dw->weight = paintweight;
- }
- }
- }
- me->dvert[vidx].flag = 1;
- }
-
- } while (fidx--);
- }
-
- {
- MDeformVert *dv = me->dvert;
- for (index = me->totvert; index != 0; index--, dv++) {
- dv->flag = 0;
- }
- }
-
- wpaint_prev_destroy(&wpp);
-
- DEG_id_tag_update(&me->id, 0);
-
- return true;
+ Mesh *me = ob->data;
+ const MPoly *mp;
+ MDeformWeight *dw, *dw_prev;
+ int vgroup_active, vgroup_mirror = -1;
+ uint index;
+ const bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+
+ /* mutually exclusive, could be made into a */
+ const short paint_selmode = ME_EDIT_PAINT_SEL_MODE(me);
+
+ if (me->totpoly == 0 || me->dvert == NULL || !me->mpoly) {
+ return false;
+ }
+
+ vgroup_active = ob->actdef - 1;
+
+ /* if mirror painting, find the other group */
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ vgroup_mirror = ED_wpaint_mirror_vgroup_ensure(ob, vgroup_active);
+ }
+
+ struct WPaintPrev wpp;
+ wpaint_prev_create(&wpp, me->dvert, me->totvert);
+
+ for (index = 0, mp = me->mpoly; index < me->totpoly; index++, mp++) {
+ uint fidx = mp->totloop - 1;
+
+ if ((paint_selmode == SCE_SELECT_FACE) && !(mp->flag & ME_FACE_SEL)) {
+ continue;
+ }
+
+ do {
+ uint vidx = me->mloop[mp->loopstart + fidx].v;
+
+ if (!me->dvert[vidx].flag) {
+ if ((paint_selmode == SCE_SELECT_VERTEX) && !(me->mvert[vidx].flag & SELECT)) {
+ continue;
+ }
+
+ dw = defvert_verify_index(&me->dvert[vidx], vgroup_active);
+ if (dw) {
+ dw_prev = defvert_verify_index(wpp.wpaint_prev + vidx, vgroup_active);
+ dw_prev->weight = dw->weight; /* set the undo weight */
+ dw->weight = paintweight;
+
+ if (me->editflag & ME_EDIT_MIRROR_X) { /* x mirror painting */
+ int j = mesh_get_x_mirror_vert(ob, NULL, vidx, topology);
+ 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);
+ }
+ else {
+ dw = defvert_verify_index(me->dvert + j, vgroup_active);
+ dw_prev = defvert_verify_index(wpp.wpaint_prev + j, vgroup_active);
+ }
+ dw_prev->weight = dw->weight; /* set the undo weight */
+ dw->weight = paintweight;
+ }
+ }
+ }
+ me->dvert[vidx].flag = 1;
+ }
+
+ } while (fidx--);
+ }
+
+ {
+ MDeformVert *dv = me->dvert;
+ for (index = me->totvert; index != 0; index--, dv++) {
+ dv->flag = 0;
+ }
+ }
+
+ wpaint_prev_destroy(&wpp);
+
+ DEG_id_tag_update(&me->id, 0);
+
+ return true;
}
-
static int weight_paint_set_exec(bContext *C, wmOperator *op)
{
- struct Scene *scene = CTX_data_scene(C);
- Object *obact = CTX_data_active_object(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- Brush *brush = BKE_paint_brush(&ts->wpaint->paint);
- float vgroup_weight = BKE_brush_weight_get(scene, brush);
-
- if (ED_wpaint_ensure_data(C, op->reports, WPAINT_ENSURE_MIRROR, NULL) == false) {
- return OPERATOR_CANCELLED;
- }
-
- if (weight_paint_set(obact, vgroup_weight)) {
- ED_region_tag_redraw(CTX_wm_region(C)); /* XXX - should redraw all 3D views */
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ struct Scene *scene = CTX_data_scene(C);
+ Object *obact = CTX_data_active_object(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Brush *brush = BKE_paint_brush(&ts->wpaint->paint);
+ float vgroup_weight = BKE_brush_weight_get(scene, brush);
+
+ if (ED_wpaint_ensure_data(C, op->reports, WPAINT_ENSURE_MIRROR, NULL) == false) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (weight_paint_set(obact, vgroup_weight)) {
+ ED_region_tag_redraw(CTX_wm_region(C)); /* XXX - should redraw all 3D views */
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void PAINT_OT_weight_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Weight";
- ot->idname = "PAINT_OT_weight_set";
- ot->description = "Fill the active vertex group with the current paint weight";
+ /* identifiers */
+ ot->name = "Set Weight";
+ ot->idname = "PAINT_OT_weight_set";
+ ot->description = "Fill the active vertex group with the current paint weight";
- /* api callbacks */
- ot->exec = weight_paint_set_exec;
- ot->poll = mask_paint_poll;
+ /* api callbacks */
+ ot->exec = weight_paint_set_exec;
+ ot->poll = mask_paint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -534,339 +551,340 @@ void PAINT_OT_weight_set(wmOperatorType *ot)
/* *** VGroups Gradient *** */
typedef struct WPGradient_vertStore {
- float sco[2];
- float weight_orig;
- enum {
- VGRAD_STORE_NOP = 0,
- VGRAD_STORE_DW_EXIST = (1 << 0),
- } flag;
+ float sco[2];
+ float weight_orig;
+ enum {
+ VGRAD_STORE_NOP = 0,
+ VGRAD_STORE_DW_EXIST = (1 << 0),
+ } flag;
} WPGradient_vertStore;
typedef struct WPGradient_vertStoreBase {
- struct WPaintPrev wpp;
- WPGradient_vertStore elem[0];
+ struct WPaintPrev wpp;
+ WPGradient_vertStore elem[0];
} WPGradient_vertStoreBase;
typedef struct WPGradient_userData {
- struct ARegion *ar;
- Scene *scene;
- Mesh *me;
- Brush *brush;
- const float *sco_start; /* [2] */
- const float *sco_end; /* [2] */
- float sco_line_div; /* store (1.0f / len_v2v2(sco_start, sco_end)) */
- int def_nr;
- bool is_init;
- WPGradient_vertStoreBase *vert_cache;
- /* only for init */
- BLI_bitmap *vert_visit;
-
- /* options */
- short use_select;
- short type;
- float weightpaint;
+ struct ARegion *ar;
+ Scene *scene;
+ Mesh *me;
+ Brush *brush;
+ const float *sco_start; /* [2] */
+ const float *sco_end; /* [2] */
+ float sco_line_div; /* store (1.0f / len_v2v2(sco_start, sco_end)) */
+ int def_nr;
+ bool is_init;
+ WPGradient_vertStoreBase *vert_cache;
+ /* only for init */
+ BLI_bitmap *vert_visit;
+
+ /* options */
+ short use_select;
+ short type;
+ float weightpaint;
} WPGradient_userData;
static void gradientVert_update(WPGradient_userData *grad_data, int index)
{
- Mesh *me = grad_data->me;
- WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
- float alpha;
-
- if (grad_data->type == WPAINT_GRADIENT_TYPE_LINEAR) {
- alpha = line_point_factor_v2(vs->sco, grad_data->sco_start, grad_data->sco_end);
- }
- else {
- BLI_assert(grad_data->type == WPAINT_GRADIENT_TYPE_RADIAL);
- alpha = len_v2v2(grad_data->sco_start, vs->sco) * grad_data->sco_line_div;
- }
- /* no need to clamp 'alpha' yet */
-
- /* adjust weight */
- alpha = BKE_brush_curve_strength_clamped(grad_data->brush, alpha, 1.0f);
-
- if (alpha != 0.0f) {
- MDeformVert *dv = &me->dvert[index];
- MDeformWeight *dw = defvert_verify_index(dv, grad_data->def_nr);
- // dw->weight = alpha; // testing
- int tool = grad_data->brush->blend;
- float testw;
-
- /* init if we just added */
- testw = ED_wpaint_blend_tool(tool, vs->weight_orig, grad_data->weightpaint, alpha * grad_data->brush->alpha);
- CLAMP(testw, 0.0f, 1.0f);
- dw->weight = testw;
- }
- else {
- 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);
- dw->weight = vs->weight_orig;
- }
- else {
- /* wasn't originally existing, remove */
- MDeformWeight *dw = defvert_find_index(dv, grad_data->def_nr);
- if (dw) {
- defvert_remove_group(dv, dw);
- }
- }
- }
+ Mesh *me = grad_data->me;
+ WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
+ float alpha;
+
+ if (grad_data->type == WPAINT_GRADIENT_TYPE_LINEAR) {
+ alpha = line_point_factor_v2(vs->sco, grad_data->sco_start, grad_data->sco_end);
+ }
+ else {
+ BLI_assert(grad_data->type == WPAINT_GRADIENT_TYPE_RADIAL);
+ alpha = len_v2v2(grad_data->sco_start, vs->sco) * grad_data->sco_line_div;
+ }
+ /* no need to clamp 'alpha' yet */
+
+ /* adjust weight */
+ alpha = BKE_brush_curve_strength_clamped(grad_data->brush, alpha, 1.0f);
+
+ if (alpha != 0.0f) {
+ MDeformVert *dv = &me->dvert[index];
+ MDeformWeight *dw = defvert_verify_index(dv, grad_data->def_nr);
+ // dw->weight = alpha; // testing
+ int tool = grad_data->brush->blend;
+ float testw;
+
+ /* init if we just added */
+ testw = ED_wpaint_blend_tool(
+ tool, vs->weight_orig, grad_data->weightpaint, alpha * grad_data->brush->alpha);
+ CLAMP(testw, 0.0f, 1.0f);
+ dw->weight = testw;
+ }
+ else {
+ 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);
+ dw->weight = vs->weight_orig;
+ }
+ else {
+ /* wasn't originally existing, remove */
+ MDeformWeight *dw = defvert_find_index(dv, grad_data->def_nr);
+ if (dw) {
+ defvert_remove_group(dv, dw);
+ }
+ }
+ }
}
-static void gradientVertUpdate__mapFunc(
- void *userData, int index, const float UNUSED(co[3]),
- const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+static void gradientVertUpdate__mapFunc(void *userData,
+ int index,
+ const float UNUSED(co[3]),
+ const float UNUSED(no_f[3]),
+ const short UNUSED(no_s[3]))
{
- WPGradient_userData *grad_data = userData;
- WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
+ WPGradient_userData *grad_data = userData;
+ WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
- if (vs->sco[0] == FLT_MAX) {
- return;
- }
+ if (vs->sco[0] == FLT_MAX) {
+ return;
+ }
- gradientVert_update(grad_data, index);
+ gradientVert_update(grad_data, index);
}
-static void gradientVertInit__mapFunc(
- void *userData, int index, const float co[3],
- const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+static void gradientVertInit__mapFunc(void *userData,
+ int index,
+ const float co[3],
+ const float UNUSED(no_f[3]),
+ const short UNUSED(no_s[3]))
{
- WPGradient_userData *grad_data = userData;
- Mesh *me = grad_data->me;
- WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
-
- if (grad_data->use_select && !(me->mvert[index].flag & SELECT)) {
- copy_v2_fl(vs->sco, FLT_MAX);
- return;
- }
-
- /* run first pass only,
- * the screen coords of the verts need to be cached because
- * updating the mesh may move them about (entering feedback loop) */
- if (BLI_BITMAP_TEST(grad_data->vert_visit, index)) {
- copy_v2_fl(vs->sco, FLT_MAX);
- return;
- }
-
- if (ED_view3d_project_float_object(
- grad_data->ar,
- co, vs->sco,
- V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) != V3D_PROJ_RET_OK)
- {
- return;
- }
-
- MDeformVert *dv = &me->dvert[index];
- const MDeformWeight *dw = defvert_find_index(dv, grad_data->def_nr);
- if (dw) {
- vs->weight_orig = dw->weight;
- vs->flag = VGRAD_STORE_DW_EXIST;
- }
- else {
- vs->weight_orig = 0.0f;
- vs->flag = VGRAD_STORE_NOP;
- }
- BLI_BITMAP_ENABLE(grad_data->vert_visit, index);
- gradientVert_update(grad_data, index);
+ WPGradient_userData *grad_data = userData;
+ Mesh *me = grad_data->me;
+ WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
+
+ if (grad_data->use_select && !(me->mvert[index].flag & SELECT)) {
+ copy_v2_fl(vs->sco, FLT_MAX);
+ return;
+ }
+
+ /* run first pass only,
+ * the screen coords of the verts need to be cached because
+ * updating the mesh may move them about (entering feedback loop) */
+ if (BLI_BITMAP_TEST(grad_data->vert_visit, index)) {
+ copy_v2_fl(vs->sco, FLT_MAX);
+ return;
+ }
+
+ if (ED_view3d_project_float_object(
+ grad_data->ar, co, vs->sco, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) !=
+ V3D_PROJ_RET_OK) {
+ return;
+ }
+
+ MDeformVert *dv = &me->dvert[index];
+ const MDeformWeight *dw = defvert_find_index(dv, grad_data->def_nr);
+ if (dw) {
+ vs->weight_orig = dw->weight;
+ vs->flag = VGRAD_STORE_DW_EXIST;
+ }
+ else {
+ vs->weight_orig = 0.0f;
+ vs->flag = VGRAD_STORE_NOP;
+ }
+ BLI_BITMAP_ENABLE(grad_data->vert_visit, index);
+ gradientVert_update(grad_data, index);
}
static int paint_weight_gradient_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- wmGesture *gesture = op->customdata;
- WPGradient_vertStoreBase *vert_cache = gesture->userdata;
- int ret = WM_gesture_straightline_modal(C, op, event);
-
- if (ret & OPERATOR_RUNNING_MODAL) {
- if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { /* XXX, hardcoded */
- /* generally crap! redo! */
- WM_gesture_straightline_cancel(C, op);
- ret &= ~OPERATOR_RUNNING_MODAL;
- ret |= OPERATOR_FINISHED;
- }
- }
-
- if (ret & OPERATOR_CANCELLED) {
- Object *ob = CTX_data_active_object(C);
- if (vert_cache != NULL) {
- Mesh *me = ob->data;
- if (vert_cache->wpp.wpaint_prev) {
- BKE_defvert_array_free_elems(me->dvert, me->totvert);
- BKE_defvert_array_copy(me->dvert, vert_cache->wpp.wpaint_prev, me->totvert);
- wpaint_prev_destroy(&vert_cache->wpp);
- }
- MEM_freeN(vert_cache);
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- }
- else if (ret & OPERATOR_FINISHED) {
- wpaint_prev_destroy(&vert_cache->wpp);
- MEM_freeN(vert_cache);
- }
-
- return ret;
+ wmGesture *gesture = op->customdata;
+ WPGradient_vertStoreBase *vert_cache = gesture->userdata;
+ int ret = WM_gesture_straightline_modal(C, op, event);
+
+ if (ret & OPERATOR_RUNNING_MODAL) {
+ if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { /* XXX, hardcoded */
+ /* generally crap! redo! */
+ WM_gesture_straightline_cancel(C, op);
+ ret &= ~OPERATOR_RUNNING_MODAL;
+ ret |= OPERATOR_FINISHED;
+ }
+ }
+
+ if (ret & OPERATOR_CANCELLED) {
+ Object *ob = CTX_data_active_object(C);
+ if (vert_cache != NULL) {
+ Mesh *me = ob->data;
+ if (vert_cache->wpp.wpaint_prev) {
+ BKE_defvert_array_free_elems(me->dvert, me->totvert);
+ BKE_defvert_array_copy(me->dvert, vert_cache->wpp.wpaint_prev, me->totvert);
+ wpaint_prev_destroy(&vert_cache->wpp);
+ }
+ MEM_freeN(vert_cache);
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ else if (ret & OPERATOR_FINISHED) {
+ wpaint_prev_destroy(&vert_cache->wpp);
+ MEM_freeN(vert_cache);
+ }
+
+ return ret;
}
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);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- Mesh *me = ob->data;
- int x_start = RNA_int_get(op->ptr, "xstart");
- int y_start = RNA_int_get(op->ptr, "ystart");
- int x_end = RNA_int_get(op->ptr, "xend");
- int y_end = RNA_int_get(op->ptr, "yend");
- float sco_start[2] = {x_start, y_start};
- float sco_end[2] = {x_end, y_end};
- const bool is_interactive = (gesture != NULL);
-
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
-
- WPGradient_userData data = {NULL};
-
- if (is_interactive) {
- if (gesture->userdata == NULL) {
- gesture->userdata = MEM_mallocN(
- sizeof(WPGradient_vertStoreBase) +
- (sizeof(WPGradient_vertStore) * me->totvert),
- __func__);
- gesture->userdata_free = false;
- data.is_init = true;
-
- wpaint_prev_create(&((WPGradient_vertStoreBase *)gesture->userdata)->wpp, me->dvert, me->totvert);
-
- /* on init only, convert face -> vert sel */
- if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
- BKE_mesh_flush_select_from_polys(me);
- }
- }
-
- vert_cache = gesture->userdata;
- }
- else {
- if (ED_wpaint_ensure_data(C, op->reports, 0, NULL) == false) {
- return OPERATOR_CANCELLED;
- }
-
- data.is_init = true;
- vert_cache = MEM_mallocN(
- sizeof(WPGradient_vertStoreBase) +
- (sizeof(WPGradient_vertStore) * me->totvert),
- __func__);
- }
-
- data.ar = ar;
- data.scene = scene;
- data.me = ob->data;
- data.sco_start = sco_start;
- data.sco_end = sco_end;
- data.sco_line_div = 1.0f / len_v2v2(sco_start, sco_end);
- data.def_nr = ob->actdef - 1;
- data.use_select = (me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL));
- data.vert_cache = vert_cache;
- data.vert_visit = NULL;
- data.type = RNA_enum_get(op->ptr, "type");
-
- {
- ToolSettings *ts = CTX_data_tool_settings(C);
- VPaint *wp = ts->wpaint;
- struct Brush *brush = BKE_paint_brush(&wp->paint);
-
- curvemapping_initialize(brush->curve);
-
- data.brush = brush;
- data.weightpaint = BKE_brush_weight_get(scene, brush);
- }
-
- ED_view3d_init_mats_rv3d(ob, ar->regiondata);
-
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
-
- CustomData_MeshMasks cddata_masks = scene->customdata_mask;
- cddata_masks.vmask |= CD_MASK_ORIGINDEX;
- cddata_masks.emask |= CD_MASK_ORIGINDEX;
- cddata_masks.pmask |= CD_MASK_ORIGINDEX;
- Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &cddata_masks);
- if (data.is_init) {
- data.vert_visit = BLI_BITMAP_NEW(me->totvert, __func__);
-
- BKE_mesh_foreach_mapped_vert(me_eval, gradientVertInit__mapFunc, &data, MESH_FOREACH_NOP);
-
- MEM_freeN(data.vert_visit);
- data.vert_visit = NULL;
- }
- else {
- BKE_mesh_foreach_mapped_vert(me_eval, gradientVertUpdate__mapFunc, &data, MESH_FOREACH_NOP);
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- if (is_interactive == false) {
- MEM_freeN(vert_cache);
- }
-
- return OPERATOR_FINISHED;
+ wmGesture *gesture = op->customdata;
+ WPGradient_vertStoreBase *vert_cache;
+ struct ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ Mesh *me = ob->data;
+ int x_start = RNA_int_get(op->ptr, "xstart");
+ int y_start = RNA_int_get(op->ptr, "ystart");
+ int x_end = RNA_int_get(op->ptr, "xend");
+ int y_end = RNA_int_get(op->ptr, "yend");
+ float sco_start[2] = {x_start, y_start};
+ float sco_end[2] = {x_end, y_end};
+ const bool is_interactive = (gesture != NULL);
+
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
+ WPGradient_userData data = {NULL};
+
+ if (is_interactive) {
+ if (gesture->userdata == NULL) {
+ gesture->userdata = MEM_mallocN(sizeof(WPGradient_vertStoreBase) +
+ (sizeof(WPGradient_vertStore) * me->totvert),
+ __func__);
+ gesture->userdata_free = false;
+ data.is_init = true;
+
+ wpaint_prev_create(
+ &((WPGradient_vertStoreBase *)gesture->userdata)->wpp, me->dvert, me->totvert);
+
+ /* on init only, convert face -> vert sel */
+ if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
+ BKE_mesh_flush_select_from_polys(me);
+ }
+ }
+
+ vert_cache = gesture->userdata;
+ }
+ else {
+ if (ED_wpaint_ensure_data(C, op->reports, 0, NULL) == false) {
+ return OPERATOR_CANCELLED;
+ }
+
+ data.is_init = true;
+ vert_cache = MEM_mallocN(
+ sizeof(WPGradient_vertStoreBase) + (sizeof(WPGradient_vertStore) * me->totvert), __func__);
+ }
+
+ data.ar = ar;
+ data.scene = scene;
+ data.me = ob->data;
+ data.sco_start = sco_start;
+ data.sco_end = sco_end;
+ data.sco_line_div = 1.0f / len_v2v2(sco_start, sco_end);
+ data.def_nr = ob->actdef - 1;
+ data.use_select = (me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL));
+ data.vert_cache = vert_cache;
+ data.vert_visit = NULL;
+ data.type = RNA_enum_get(op->ptr, "type");
+
+ {
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ VPaint *wp = ts->wpaint;
+ struct Brush *brush = BKE_paint_brush(&wp->paint);
+
+ curvemapping_initialize(brush->curve);
+
+ data.brush = brush;
+ data.weightpaint = BKE_brush_weight_get(scene, brush);
+ }
+
+ ED_view3d_init_mats_rv3d(ob, ar->regiondata);
+
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+
+ CustomData_MeshMasks cddata_masks = scene->customdata_mask;
+ cddata_masks.vmask |= CD_MASK_ORIGINDEX;
+ cddata_masks.emask |= CD_MASK_ORIGINDEX;
+ cddata_masks.pmask |= CD_MASK_ORIGINDEX;
+ Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &cddata_masks);
+ if (data.is_init) {
+ data.vert_visit = BLI_BITMAP_NEW(me->totvert, __func__);
+
+ BKE_mesh_foreach_mapped_vert(me_eval, gradientVertInit__mapFunc, &data, MESH_FOREACH_NOP);
+
+ MEM_freeN(data.vert_visit);
+ data.vert_visit = NULL;
+ }
+ else {
+ BKE_mesh_foreach_mapped_vert(me_eval, gradientVertUpdate__mapFunc, &data, MESH_FOREACH_NOP);
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ if (is_interactive == false) {
+ MEM_freeN(vert_cache);
+ }
+
+ return OPERATOR_FINISHED;
}
static int paint_weight_gradient_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- int ret;
-
- if (ED_wpaint_ensure_data(C, op->reports, 0, NULL) == false) {
- return OPERATOR_CANCELLED;
- }
-
- 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) {
- /* TODO, hardcoded, extend WM_gesture_straightline_ */
- if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
- wmGesture *gesture = op->customdata;
- gesture->is_active = true;
- }
- }
- }
- return ret;
+ int ret;
+
+ if (ED_wpaint_ensure_data(C, op->reports, 0, NULL) == false) {
+ return OPERATOR_CANCELLED;
+ }
+
+ 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) {
+ /* TODO, hardcoded, extend WM_gesture_straightline_ */
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
+ wmGesture *gesture = op->customdata;
+ gesture->is_active = true;
+ }
+ }
+ }
+ return ret;
}
void PAINT_OT_weight_gradient(wmOperatorType *ot)
{
- /* defined in DNA_space_types.h */
- static const EnumPropertyItem gradient_types[] = {
- {WPAINT_GRADIENT_TYPE_LINEAR, "LINEAR", 0, "Linear", ""},
- {WPAINT_GRADIENT_TYPE_RADIAL, "RADIAL", 0, "Radial", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Weight Gradient";
- ot->idname = "PAINT_OT_weight_gradient";
- ot->description = "Draw a line to apply a weight gradient to selected vertices";
-
- /* api callbacks */
- ot->invoke = paint_weight_gradient_invoke;
- ot->modal = paint_weight_gradient_modal;
- ot->exec = paint_weight_gradient_exec;
- ot->poll = weight_paint_poll_ignore_tool;
- ot->cancel = WM_gesture_straightline_cancel;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- prop = RNA_def_enum(ot->srna, "type", gradient_types, 0, "Type", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT);
+ /* defined in DNA_space_types.h */
+ static const EnumPropertyItem gradient_types[] = {
+ {WPAINT_GRADIENT_TYPE_LINEAR, "LINEAR", 0, "Linear", ""},
+ {WPAINT_GRADIENT_TYPE_RADIAL, "RADIAL", 0, "Radial", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Weight Gradient";
+ ot->idname = "PAINT_OT_weight_gradient";
+ ot->description = "Draw a line to apply a weight gradient to selected vertices";
+
+ /* api callbacks */
+ ot->invoke = paint_weight_gradient_invoke;
+ ot->modal = paint_weight_gradient_modal;
+ ot->exec = paint_weight_gradient_exec;
+ ot->poll = weight_paint_poll_ignore_tool;
+ ot->cancel = WM_gesture_straightline_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_enum(ot->srna, "type", gradient_types, 0, "Type", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT);
}
/** \} */
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 38f9f1dfa9f..88aed201b48 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c
@@ -47,111 +47,112 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "paint_intern.h" /* own include */
+#include "paint_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Weight Paint Sanity Checks
* \{ */
/* ensure we have data on wpaint start, add if needed */
-bool ED_wpaint_ensure_data(
- bContext *C, struct ReportList *reports,
- enum eWPaintFlag flag, struct WPaintVGroupIndex *vgroup_index)
+bool ED_wpaint_ensure_data(bContext *C,
+ struct ReportList *reports,
+ enum eWPaintFlag flag,
+ struct WPaintVGroupIndex *vgroup_index)
{
- Object *ob = CTX_data_active_object(C);
- Mesh *me = BKE_mesh_from_object(ob);
+ Object *ob = CTX_data_active_object(C);
+ Mesh *me = BKE_mesh_from_object(ob);
- if (vgroup_index) {
- vgroup_index->active = -1;
- vgroup_index->mirror = -1;
- }
+ if (vgroup_index) {
+ vgroup_index->active = -1;
+ vgroup_index->mirror = -1;
+ }
- if (BKE_object_is_in_editmode(ob)) {
- return false;
- }
+ if (BKE_object_is_in_editmode(ob)) {
+ return false;
+ }
- if (me == NULL || me->totpoly == 0) {
- return false;
- }
+ if (me == NULL || me->totpoly == 0) {
+ return false;
+ }
- /* if nothing was added yet, we make dverts and a vertex deform group */
- if (!me->dvert) {
- BKE_object_defgroup_data_create(&me->id);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
- }
+ /* if nothing was added yet, we make dverts and a vertex deform group */
+ if (!me->dvert) {
+ BKE_object_defgroup_data_create(&me->id);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+ }
- /* this happens on a Bone select, when no vgroup existed yet */
- if (ob->actdef <= 0) {
- Object *modob;
- if ((modob = modifiers_isDeformedByArmature(ob))) {
- Bone *actbone = ((bArmature *)modob->data)->act_bone;
- if (actbone) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(modob->pose, actbone->name);
+ /* this happens on a Bone select, when no vgroup existed yet */
+ if (ob->actdef <= 0) {
+ Object *modob;
+ if ((modob = modifiers_isDeformedByArmature(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);
- if (dg == NULL) {
- dg = BKE_object_defgroup_add_name(ob, pchan->name); /* sets actdef */
- }
- else {
- int actdef = 1 + BLI_findindex(&ob->defbase, dg);
- BLI_assert(actdef >= 0);
- ob->actdef = actdef;
- }
- }
- }
- }
- }
- if (BLI_listbase_is_empty(&ob->defbase)) {
- BKE_object_defgroup_add(ob);
- }
+ if (pchan) {
+ bDeformGroup *dg = defgroup_find_name(ob, pchan->name);
+ if (dg == NULL) {
+ dg = BKE_object_defgroup_add_name(ob, pchan->name); /* sets actdef */
+ }
+ else {
+ int actdef = 1 + BLI_findindex(&ob->defbase, dg);
+ BLI_assert(actdef >= 0);
+ ob->actdef = actdef;
+ }
+ }
+ }
+ }
+ }
+ if (BLI_listbase_is_empty(&ob->defbase)) {
+ BKE_object_defgroup_add(ob);
+ }
- /* ensure we don't try paint onto an invalid group */
- if (ob->actdef <= 0) {
- BKE_report(reports, RPT_WARNING, "No active vertex group for painting, aborting");
- return false;
- }
+ /* ensure we don't try paint onto an invalid group */
+ if (ob->actdef <= 0) {
+ BKE_report(reports, RPT_WARNING, "No active vertex group for painting, aborting");
+ return false;
+ }
- if (vgroup_index) {
- vgroup_index->active = ob->actdef - 1;
- }
+ if (vgroup_index) {
+ vgroup_index->active = ob->actdef - 1;
+ }
- if (flag & WPAINT_ENSURE_MIRROR) {
- if (me->editflag & ME_EDIT_MIRROR_X) {
- int mirror = ED_wpaint_mirror_vgroup_ensure(ob, ob->actdef - 1);
- if (vgroup_index) {
- vgroup_index->mirror = mirror;
- }
- }
- }
+ if (flag & WPAINT_ENSURE_MIRROR) {
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ int mirror = ED_wpaint_mirror_vgroup_ensure(ob, ob->actdef - 1);
+ if (vgroup_index) {
+ vgroup_index->mirror = mirror;
+ }
+ }
+ }
- return true;
+ return true;
}
/** \} */
/* mirror_vgroup is set to -1 when invalid */
int ED_wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active)
{
- bDeformGroup *defgroup = BLI_findlink(&ob->defbase, vgroup_active);
+ bDeformGroup *defgroup = BLI_findlink(&ob->defbase, vgroup_active);
- if (defgroup) {
- int mirrdef;
- char name_flip[MAXBONENAME];
+ if (defgroup) {
+ int mirrdef;
+ char name_flip[MAXBONENAME];
- BLI_string_flip_side_name(name_flip, defgroup->name, false, sizeof(name_flip));
- mirrdef = defgroup_name_index(ob, name_flip);
- if (mirrdef == -1) {
- if (BKE_defgroup_new(ob, name_flip)) {
- mirrdef = BLI_listbase_count(&ob->defbase) - 1;
- }
- }
+ BLI_string_flip_side_name(name_flip, defgroup->name, false, sizeof(name_flip));
+ mirrdef = defgroup_name_index(ob, name_flip);
+ if (mirrdef == -1) {
+ if (BKE_defgroup_new(ob, name_flip)) {
+ mirrdef = BLI_listbase_count(&ob->defbase) - 1;
+ }
+ }
- /* curdef should never be NULL unless this is
- * a light and BKE_object_defgroup_add_name fails */
- return mirrdef;
- }
+ /* curdef should never be NULL unless this is
+ * a light and BKE_object_defgroup_add_name fails */
+ return mirrdef;
+ }
- return -1;
+ return -1;
}
/* -------------------------------------------------------------------- */
@@ -160,144 +161,158 @@ int ED_wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active)
BLI_INLINE float wval_blend(const float weight, const float paintval, const float alpha)
{
- const float talpha = min_ff(alpha, 1.0f); /* blending with values over 1 doesn't make sense */
- return (paintval * talpha) + (weight * (1.0f - talpha));
+ const float talpha = min_ff(alpha, 1.0f); /* blending with values over 1 doesn't make sense */
+ return (paintval * talpha) + (weight * (1.0f - talpha));
}
BLI_INLINE float wval_add(const float weight, const float paintval, const float alpha)
{
- return weight + (paintval * alpha);
+ return weight + (paintval * alpha);
}
BLI_INLINE float wval_sub(const float weight, const float paintval, const float alpha)
{
- return weight - (paintval * alpha);
+ return weight - (paintval * alpha);
}
BLI_INLINE float wval_mul(const float weight, const float paintval, const float alpha)
-{ /* first mul, then blend the fac */
- return ((1.0f - alpha) + (alpha * paintval)) * weight;
+{ /* first mul, then blend the fac */
+ return ((1.0f - alpha) + (alpha * paintval)) * weight;
}
BLI_INLINE float wval_lighten(const float weight, const float paintval, const float alpha)
{
- return (weight < paintval) ? wval_blend(weight, paintval, alpha) : weight;
+ return (weight < paintval) ? wval_blend(weight, paintval, alpha) : weight;
}
BLI_INLINE float wval_darken(const float weight, const float paintval, const float alpha)
{
- return (weight > paintval) ? wval_blend(weight, paintval, alpha) : weight;
+ return (weight > paintval) ? wval_blend(weight, paintval, alpha) : weight;
}
/* mainly for color */
BLI_INLINE float wval_colordodge(float weight, float paintval, float fac)
{
- float mfac, temp;
- if (fac == 0.0f) {
- return weight;
- }
- mfac = 1.0f - fac;
- temp = (paintval == 1.0f) ? 1.0f : min_ff((weight * (225.0f / 255.0f)) / (1.0f - paintval), 1.0f);
- return mfac * weight + temp * fac;
+ float mfac, temp;
+ if (fac == 0.0f) {
+ return weight;
+ }
+ mfac = 1.0f - fac;
+ temp = (paintval == 1.0f) ? 1.0f :
+ min_ff((weight * (225.0f / 255.0f)) / (1.0f - paintval), 1.0f);
+ return mfac * weight + temp * fac;
}
BLI_INLINE float wval_difference(float weight, float paintval, float fac)
{
- float mfac, temp;
- if (fac == 0.0f) {
- return weight;
- }
- mfac = 1.0f - fac;
- temp = fabsf(weight - paintval);
- return mfac * weight + temp * fac;
+ float mfac, temp;
+ if (fac == 0.0f) {
+ return weight;
+ }
+ mfac = 1.0f - fac;
+ temp = fabsf(weight - paintval);
+ return mfac * weight + temp * fac;
}
BLI_INLINE float wval_screen(float weight, float paintval, float fac)
{
- float mfac, temp;
- if (fac == 0.0f) {
- return weight;
- }
- mfac = 1.0f - fac;
- temp = max_ff(1.0f - (((1.0f - weight) * (1.0f - paintval))), 0);
- return mfac * weight + temp * fac;
+ float mfac, temp;
+ if (fac == 0.0f) {
+ return weight;
+ }
+ mfac = 1.0f - fac;
+ temp = max_ff(1.0f - (((1.0f - weight) * (1.0f - paintval))), 0);
+ return mfac * weight + temp * fac;
}
BLI_INLINE float wval_hardlight(float weight, float paintval, float fac)
{
- float mfac, temp;
- if (fac == 0.0f) {
- return weight;
- }
- mfac = 1.0f - fac;
- if (paintval > 0.5f) {
- temp = 1.0f - ((1.0f - 2.0f * (paintval - 0.5f)) * (1.0f - weight));
- }
- else {
- temp = (2.0f * paintval * weight);
- }
- return mfac * weight + temp * fac;
+ float mfac, temp;
+ if (fac == 0.0f) {
+ return weight;
+ }
+ mfac = 1.0f - fac;
+ if (paintval > 0.5f) {
+ temp = 1.0f - ((1.0f - 2.0f * (paintval - 0.5f)) * (1.0f - weight));
+ }
+ else {
+ temp = (2.0f * paintval * weight);
+ }
+ return mfac * weight + temp * fac;
}
BLI_INLINE float wval_overlay(float weight, float paintval, float fac)
{
- float mfac, temp;
- if (fac == 0.0f) {
- return weight;
- }
- mfac = 1.0f - fac;
- if (weight > 0.5f) {
- temp = 1.0f - ((1.0f - 2.0f * (weight - 0.5f)) * (1.0f - paintval));
- }
- else {
- temp = (2.0f * paintval * weight);
- }
- return mfac * weight + temp * fac;
+ float mfac, temp;
+ if (fac == 0.0f) {
+ return weight;
+ }
+ mfac = 1.0f - fac;
+ if (weight > 0.5f) {
+ temp = 1.0f - ((1.0f - 2.0f * (weight - 0.5f)) * (1.0f - paintval));
+ }
+ else {
+ temp = (2.0f * paintval * weight);
+ }
+ return mfac * weight + temp * fac;
}
BLI_INLINE float wval_softlight(float weight, float paintval, float fac)
{
- float mfac, temp;
- if (fac == 0.0f) {
- return weight;
- }
- mfac = 1.0f - fac;
- if (weight < 0.5f) {
- temp = ((2.0f * ((paintval / 2.0f) + 0.25f)) * weight);
- }
- else {
- temp = 1.0f - (2.0f * (1.0f - ((paintval / 2.0f) + 0.25f)) * (1.0f - weight));
- }
- return temp * fac + weight * mfac;
+ float mfac, temp;
+ if (fac == 0.0f) {
+ return weight;
+ }
+ mfac = 1.0f - fac;
+ if (weight < 0.5f) {
+ temp = ((2.0f * ((paintval / 2.0f) + 0.25f)) * weight);
+ }
+ else {
+ temp = 1.0f - (2.0f * (1.0f - ((paintval / 2.0f) + 0.25f)) * (1.0f - weight));
+ }
+ return temp * fac + weight * mfac;
}
BLI_INLINE float wval_exclusion(float weight, float paintval, float fac)
{
- float mfac, temp;
- if (fac == 0.0f) {
- return weight;
- }
- mfac = 1.0f - fac;
- temp = 0.5f - ((2.0f * (weight - 0.5f) * (paintval - 0.5f)));
- return temp * fac + weight * mfac;
+ float mfac, temp;
+ if (fac == 0.0f) {
+ return weight;
+ }
+ mfac = 1.0f - fac;
+ temp = 0.5f - ((2.0f * (weight - 0.5f) * (paintval - 0.5f)));
+ return temp * fac + weight * mfac;
}
/* vpaint has 'vpaint_blend_tool' */
/* result is not clamped from [0-1] */
-float ED_wpaint_blend_tool(
- const int tool,
- /* dw->weight */
- const float weight,
- const float paintval, const float alpha)
+float ED_wpaint_blend_tool(const int tool,
+ /* dw->weight */
+ const float weight,
+ const float paintval,
+ const float alpha)
{
- switch ((IMB_BlendMode)tool) {
- case IMB_BLEND_MIX: return wval_blend(weight, paintval, alpha);
- case IMB_BLEND_ADD: return wval_add(weight, paintval, alpha);
- case IMB_BLEND_SUB: return wval_sub(weight, paintval, alpha);
- case IMB_BLEND_MUL: return wval_mul(weight, paintval, alpha);
- case IMB_BLEND_LIGHTEN: return wval_lighten(weight, paintval, alpha);
- case IMB_BLEND_DARKEN: return wval_darken(weight, paintval, alpha);
- /* Mostly make sense for color: support anyway. */
- case IMB_BLEND_COLORDODGE: return wval_colordodge(weight, paintval, alpha);
- case IMB_BLEND_DIFFERENCE: return wval_difference(weight, paintval, alpha);
- case IMB_BLEND_SCREEN: return wval_screen(weight, paintval, alpha);
- case IMB_BLEND_HARDLIGHT: return wval_hardlight(weight, paintval, alpha);
- case IMB_BLEND_OVERLAY: return wval_overlay(weight, paintval, alpha);
- case IMB_BLEND_SOFTLIGHT: return wval_softlight(weight, paintval, alpha);
- case IMB_BLEND_EXCLUSION: return wval_exclusion(weight, paintval, alpha);
- /* Only for color: just use blend. */
- default:
- return wval_blend(weight, paintval, alpha);
- }
+ switch ((IMB_BlendMode)tool) {
+ case IMB_BLEND_MIX:
+ return wval_blend(weight, paintval, alpha);
+ case IMB_BLEND_ADD:
+ return wval_add(weight, paintval, alpha);
+ case IMB_BLEND_SUB:
+ return wval_sub(weight, paintval, alpha);
+ case IMB_BLEND_MUL:
+ return wval_mul(weight, paintval, alpha);
+ case IMB_BLEND_LIGHTEN:
+ return wval_lighten(weight, paintval, alpha);
+ case IMB_BLEND_DARKEN:
+ return wval_darken(weight, paintval, alpha);
+ /* Mostly make sense for color: support anyway. */
+ case IMB_BLEND_COLORDODGE:
+ return wval_colordodge(weight, paintval, alpha);
+ case IMB_BLEND_DIFFERENCE:
+ return wval_difference(weight, paintval, alpha);
+ case IMB_BLEND_SCREEN:
+ return wval_screen(weight, paintval, alpha);
+ case IMB_BLEND_HARDLIGHT:
+ return wval_hardlight(weight, paintval, alpha);
+ case IMB_BLEND_OVERLAY:
+ return wval_overlay(weight, paintval, alpha);
+ case IMB_BLEND_SOFTLIGHT:
+ return wval_softlight(weight, paintval, alpha);
+ case IMB_BLEND_EXCLUSION:
+ return wval_exclusion(weight, paintval, alpha);
+ /* Only for color: just use blend. */
+ default:
+ return wval_blend(weight, paintval, alpha);
+ }
}
/** \} */
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index ad2cfb5f9fc..9309def4a77 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -22,7 +22,6 @@
* \ingroup edsculpt
*/
-
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
@@ -103,188 +102,175 @@
* (used for flushing updates at enter/exit sculpt mode) */
static bool sculpt_has_active_modifiers(Scene *scene, Object *ob)
{
- ModifierData *md;
- VirtualModifierData virtualModifierData;
+ ModifierData *md;
+ VirtualModifierData virtualModifierData;
- md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
+ md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
- /* exception for shape keys because we can edit those */
- for (; md; md = md->next) {
- if (modifier_isEnabled(scene, md, eModifierMode_Realtime))
- return 1;
- }
+ /* exception for shape keys because we can edit those */
+ for (; md; md = md->next) {
+ if (modifier_isEnabled(scene, md, eModifierMode_Realtime))
+ return 1;
+ }
- return 0;
+ return 0;
}
static bool sculpt_tool_needs_original(const char sculpt_tool)
{
- return ELEM(sculpt_tool,
- SCULPT_TOOL_GRAB,
- SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_THUMB,
- SCULPT_TOOL_LAYER);
+ return ELEM(
+ sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_THUMB, SCULPT_TOOL_LAYER);
}
static bool sculpt_tool_is_proxy_used(const char sculpt_tool)
{
- return ELEM(sculpt_tool,
- SCULPT_TOOL_SMOOTH,
- SCULPT_TOOL_LAYER);
+ return ELEM(sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_LAYER);
}
-static bool sculpt_brush_use_topology_rake(
- const SculptSession *ss, const Brush *brush)
+static bool sculpt_brush_use_topology_rake(const SculptSession *ss, const Brush *brush)
{
- return SCULPT_TOOL_HAS_TOPOLOGY_RAKE(brush->sculpt_tool) &&
- (brush->topology_rake_factor > 0.0f) &&
- (ss->bm != NULL);
+ return SCULPT_TOOL_HAS_TOPOLOGY_RAKE(brush->sculpt_tool) &&
+ (brush->topology_rake_factor > 0.0f) && (ss->bm != NULL);
}
/**
* Test whether the #StrokeCache.sculpt_normal needs update in #do_brush_action
*/
-static int sculpt_brush_needs_normal(
- const SculptSession *ss, const Brush *brush)
+static int sculpt_brush_needs_normal(const SculptSession *ss, const Brush *brush)
{
- return ((SCULPT_TOOL_HAS_NORMAL_WEIGHT(brush->sculpt_tool) &&
- (ss->cache->normal_weight > 0.0f)) ||
+ return ((SCULPT_TOOL_HAS_NORMAL_WEIGHT(brush->sculpt_tool) &&
+ (ss->cache->normal_weight > 0.0f)) ||
- ELEM(brush->sculpt_tool,
- SCULPT_TOOL_BLOB,
- SCULPT_TOOL_CREASE,
- SCULPT_TOOL_DRAW,
- SCULPT_TOOL_LAYER,
- SCULPT_TOOL_NUDGE,
- SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_THUMB) ||
+ ELEM(brush->sculpt_tool,
+ SCULPT_TOOL_BLOB,
+ SCULPT_TOOL_CREASE,
+ SCULPT_TOOL_DRAW,
+ SCULPT_TOOL_LAYER,
+ SCULPT_TOOL_NUDGE,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_THUMB) ||
- (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA)) ||
- sculpt_brush_use_topology_rake(ss, brush);
+ (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA)) ||
+ sculpt_brush_use_topology_rake(ss, brush);
}
/** \} */
static bool sculpt_brush_needs_rake_rotation(const Brush *brush)
{
- return SCULPT_TOOL_HAS_RAKE(brush->sculpt_tool) && (brush->rake_factor != 0.0f);
+ return SCULPT_TOOL_HAS_RAKE(brush->sculpt_tool) && (brush->rake_factor != 0.0f);
}
typedef enum StrokeFlags {
- CLIP_X = 1,
- CLIP_Y = 2,
- CLIP_Z = 4,
+ CLIP_X = 1,
+ CLIP_Y = 2,
+ CLIP_Z = 4,
} StrokeFlags;
/************** Access to original unmodified vertex data *************/
typedef struct {
- BMLog *bm_log;
+ BMLog *bm_log;
- SculptUndoNode *unode;
- float (*coords)[3];
- short (*normals)[3];
- const float *vmasks;
+ SculptUndoNode *unode;
+ float (*coords)[3];
+ short (*normals)[3];
+ const float *vmasks;
- /* Original coordinate, normal, and mask */
- const float *co;
- const short *no;
- float mask;
+ /* 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 */
static void sculpt_orig_vert_data_unode_init(SculptOrigVertData *data,
Object *ob,
SculptUndoNode *unode)
{
- SculptSession *ss = ob->sculpt;
- BMesh *bm = ss->bm;
+ SculptSession *ss = ob->sculpt;
+ BMesh *bm = ss->bm;
- memset(data, 0, sizeof(*data));
- data->unode = unode;
+ memset(data, 0, sizeof(*data));
+ data->unode = unode;
- if (bm) {
- data->bm_log = ss->bm_log;
- }
- else {
- data->coords = data->unode->co;
- data->normals = data->unode->no;
- data->vmasks = data->unode->mask;
- }
+ if (bm) {
+ data->bm_log = ss->bm_log;
+ }
+ else {
+ data->coords = data->unode->co;
+ data->normals = data->unode->no;
+ data->vmasks = data->unode->mask;
+ }
}
/* 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)
+static void sculpt_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *node)
{
- SculptUndoNode *unode;
- unode = sculpt_undo_push_node(ob, node, SCULPT_UNDO_COORDS);
- sculpt_orig_vert_data_unode_init(data, ob, unode);
+ SculptUndoNode *unode;
+ 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)
-{
- if (orig_data->unode->type == SCULPT_UNDO_COORDS) {
- if (orig_data->bm_log) {
- BM_log_original_vert_data(
- orig_data->bm_log, iter->bm_vert,
- &orig_data->co, &orig_data->no);
- }
- else {
- orig_data->co = orig_data->coords[iter->i];
- orig_data->no = orig_data->normals[iter->i];
- }
- }
- else if (orig_data->unode->type == SCULPT_UNDO_MASK) {
- if (orig_data->bm_log) {
- orig_data->mask = BM_log_original_mask(orig_data->bm_log, iter->bm_vert);
- }
- else {
- orig_data->mask = orig_data->vmasks[iter->i];
- }
- }
+static void sculpt_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter)
+{
+ if (orig_data->unode->type == SCULPT_UNDO_COORDS) {
+ if (orig_data->bm_log) {
+ BM_log_original_vert_data(orig_data->bm_log, iter->bm_vert, &orig_data->co, &orig_data->no);
+ }
+ else {
+ orig_data->co = orig_data->coords[iter->i];
+ orig_data->no = orig_data->normals[iter->i];
+ }
+ }
+ else if (orig_data->unode->type == SCULPT_UNDO_MASK) {
+ if (orig_data->bm_log) {
+ orig_data->mask = BM_log_original_mask(orig_data->bm_log, iter->bm_vert);
+ }
+ else {
+ orig_data->mask = orig_data->vmasks[iter->i];
+ }
+ }
}
static void sculpt_rake_data_update(struct SculptRakeData *srd, const float co[3])
{
- float rake_dist = len_v3v3(srd->follow_co, co);
- if (rake_dist > srd->follow_dist) {
- interp_v3_v3v3(srd->follow_co, srd->follow_co, co, rake_dist - srd->follow_dist);
- }
+ float rake_dist = len_v3v3(srd->follow_co, co);
+ if (rake_dist > srd->follow_dist) {
+ interp_v3_v3v3(srd->follow_co, srd->follow_co, co, rake_dist - srd->follow_dist);
+ }
}
-
-static void sculpt_rake_rotate(
- const SculptSession *ss, const float sculpt_co[3], const float v_co[3], float factor, float r_delta[3])
+static void sculpt_rake_rotate(const SculptSession *ss,
+ const float sculpt_co[3],
+ const float v_co[3],
+ float factor,
+ float r_delta[3])
{
- float vec_rot[3];
+ float vec_rot[3];
#if 0
- /* lerp */
- sub_v3_v3v3(vec_rot, v_co, sculpt_co);
- mul_qt_v3(ss->cache->rake_rotation_symmetry, vec_rot);
- add_v3_v3(vec_rot, sculpt_co);
- sub_v3_v3v3(r_delta, vec_rot, v_co);
- mul_v3_fl(r_delta, factor);
+ /* lerp */
+ sub_v3_v3v3(vec_rot, v_co, sculpt_co);
+ mul_qt_v3(ss->cache->rake_rotation_symmetry, vec_rot);
+ add_v3_v3(vec_rot, sculpt_co);
+ sub_v3_v3v3(r_delta, vec_rot, v_co);
+ mul_v3_fl(r_delta, factor);
#else
- /* slerp */
- float q_interp[4];
- sub_v3_v3v3(vec_rot, v_co, sculpt_co);
+ /* slerp */
+ float q_interp[4];
+ sub_v3_v3v3(vec_rot, v_co, sculpt_co);
- copy_qt_qt(q_interp, ss->cache->rake_rotation_symmetry);
- pow_qt_fl_normalized(q_interp, factor);
- mul_qt_v3(q_interp, vec_rot);
+ copy_qt_qt(q_interp, ss->cache->rake_rotation_symmetry);
+ pow_qt_fl_normalized(q_interp, factor);
+ mul_qt_v3(q_interp, vec_rot);
- add_v3_v3(vec_rot, sculpt_co);
- sub_v3_v3v3(r_delta, vec_rot, v_co);
+ add_v3_v3(vec_rot, sculpt_co);
+ sub_v3_v3v3(r_delta, vec_rot, v_co);
#endif
-
}
/**
@@ -292,26 +278,29 @@ static void sculpt_rake_rotate(
*
* \param grab_delta: Typically from `ss->cache->grab_delta_symmetry`.
*/
-static void sculpt_project_v3_normal_align(SculptSession *ss, const float normal_weight, float grab_delta[3])
+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. */
- const float len_signed = dot_v3v3(ss->cache->sculpt_normal_symm, grab_delta);
+ /* 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,
- * as the normal points towards the view, the scale increases. */
- float len_view_scale;
- {
- float view_aligned_normal[3];
- project_plane_v3_v3v3(view_aligned_normal, ss->cache->sculpt_normal_symm, ss->cache->view_normal);
- len_view_scale = fabsf(dot_v3v3(view_aligned_normal, ss->cache->sculpt_normal_symm));
- len_view_scale = (len_view_scale > FLT_EPSILON) ? 1.0f / len_view_scale : 1.0f;
- }
+ /* 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;
+ {
+ float view_aligned_normal[3];
+ project_plane_v3_v3v3(
+ view_aligned_normal, ss->cache->sculpt_normal_symm, ss->cache->view_normal);
+ len_view_scale = fabsf(dot_v3v3(view_aligned_normal, ss->cache->sculpt_normal_symm));
+ len_view_scale = (len_view_scale > FLT_EPSILON) ? 1.0f / len_view_scale : 1.0f;
+ }
- mul_v3_fl(grab_delta, 1.0f - normal_weight);
- madd_v3_v3fl(grab_delta, ss->cache->sculpt_normal_symm, (len_signed * normal_weight) * len_view_scale);
+ mul_v3_fl(grab_delta, 1.0f - normal_weight);
+ madd_v3_v3fl(
+ grab_delta, ss->cache->sculpt_normal_symm, (len_signed * normal_weight) * len_view_scale);
}
-
/** \name SculptProjectVector
*
* Fast-path for #project_plane_v3_v3v3
@@ -319,43 +308,39 @@ static void sculpt_project_v3_normal_align(SculptSession *ss, const float normal
* \{ */
typedef struct SculptProjectVector {
- float plane[3];
- float len_sq;
- float len_sq_inv_neg;
- bool is_valid;
+ float plane[3];
+ float len_sq;
+ float len_sq_inv_neg;
+ bool is_valid;
} SculptProjectVector;
/**
* \param plane: Direction, can be any length.
*/
-static void sculpt_project_v3_cache_init(
- SculptProjectVector *spvc, const float plane[3])
+static void sculpt_project_v3_cache_init(SculptProjectVector *spvc, const float plane[3])
{
- copy_v3_v3(spvc->plane, plane);
- spvc->len_sq = len_squared_v3(spvc->plane);
- spvc->is_valid = (spvc->len_sq > FLT_EPSILON);
- spvc->len_sq_inv_neg = (spvc->is_valid) ? -1.0f / spvc->len_sq : 0.0f;
+ copy_v3_v3(spvc->plane, plane);
+ spvc->len_sq = len_squared_v3(spvc->plane);
+ spvc->is_valid = (spvc->len_sq > FLT_EPSILON);
+ spvc->len_sq_inv_neg = (spvc->is_valid) ? -1.0f / spvc->len_sq : 0.0f;
}
/**
* Calculate the projection.
*/
-static void sculpt_project_v3(
- const SculptProjectVector *spvc, const float vec[3],
- float r_vec[3])
+static void sculpt_project_v3(const SculptProjectVector *spvc, const float vec[3], float r_vec[3])
{
#if 0
- project_plane_v3_v3v3(r_vec, vec, spvc->plane);
+ project_plane_v3_v3v3(r_vec, vec, spvc->plane);
#else
- /* inline the projection, cache `-1.0 / dot_v3_v3(v_proj, v_proj)` */
- madd_v3_v3fl(r_vec, spvc->plane, dot_v3v3(vec, spvc->plane) * spvc->len_sq_inv_neg);
+ /* inline the projection, cache `-1.0 / dot_v3_v3(v_proj, v_proj)` */
+ madd_v3_v3fl(r_vec, spvc->plane, dot_v3v3(vec, spvc->plane) * spvc->len_sq_inv_neg);
#endif
}
/** \} */
-
/**********************************************************************/
/* Returns true if the stroke will use dynamic topology, false
@@ -364,360 +349,351 @@ static void sculpt_project_v3(
* 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)
+static bool sculpt_stroke_is_dynamic_topology(const SculptSession *ss, const Brush *brush)
{
- return ((BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) &&
+ return ((BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) &&
- (!ss->cache || (!ss->cache->alt_smooth)) &&
+ (!ss->cache || (!ss->cache->alt_smooth)) &&
- /* Requires mesh restore, which doesn't work with
- * dynamic-topology */
- !(brush->flag & BRUSH_ANCHORED) &&
- !(brush->flag & BRUSH_DRAG_DOT) &&
+ /* Requires mesh restore, which doesn't work with
+ * dynamic-topology */
+ !(brush->flag & BRUSH_ANCHORED) && !(brush->flag & BRUSH_DRAG_DOT) &&
- SCULPT_TOOL_HAS_DYNTOPO(brush->sculpt_tool));
+ SCULPT_TOOL_HAS_DYNTOPO(brush->sculpt_tool));
}
/*** paint mesh ***/
-static void paint_mesh_restore_co_task_cb(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict UNUSED(tls))
+static void paint_mesh_restore_co_task_cb(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
- SculptUndoNode *unode;
- SculptUndoType type = (data->brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS);
+ SculptUndoNode *unode;
+ SculptUndoType type = (data->brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK :
+ SCULPT_UNDO_COORDS);
- if (ss->bm) {
- unode = sculpt_undo_push_node(data->ob, data->nodes[n], type);
- }
- else {
- unode = sculpt_undo_get_node(data->nodes[n]);
- }
+ if (ss->bm) {
+ unode = sculpt_undo_push_node(data->ob, data->nodes[n], type);
+ }
+ else {
+ unode = sculpt_undo_get_node(data->nodes[n]);
+ }
- if (unode) {
- PBVHVertexIter vd;
- SculptOrigVertData orig_data;
+ if (unode) {
+ PBVHVertexIter vd;
+ SculptOrigVertData orig_data;
- sculpt_orig_vert_data_unode_init(&orig_data, data->ob, unode);
+ sculpt_orig_vert_data_unode_init(&orig_data, data->ob, unode);
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- sculpt_orig_vert_data_update(&orig_data, &vd);
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ sculpt_orig_vert_data_update(&orig_data, &vd);
- if (orig_data.unode->type == SCULPT_UNDO_COORDS) {
- copy_v3_v3(vd.co, orig_data.co);
- if (vd.no)
- copy_v3_v3_short(vd.no, orig_data.no);
- else
- normal_short_to_float_v3(vd.fno, orig_data.no);
- }
- else if (orig_data.unode->type == SCULPT_UNDO_MASK) {
- *vd.mask = orig_data.mask;
- }
+ if (orig_data.unode->type == SCULPT_UNDO_COORDS) {
+ copy_v3_v3(vd.co, orig_data.co);
+ if (vd.no)
+ copy_v3_v3_short(vd.no, orig_data.no);
+ else
+ normal_short_to_float_v3(vd.fno, orig_data.no);
+ }
+ else if (orig_data.unode->type == SCULPT_UNDO_MASK) {
+ *vd.mask = orig_data.mask;
+ }
- if (vd.mvert)
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- BKE_pbvh_vertex_iter_end;
+ if (vd.mvert)
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ BKE_pbvh_vertex_iter_end;
- BKE_pbvh_node_mark_update(data->nodes[n]);
- }
+ BKE_pbvh_node_mark_update(data->nodes[n]);
+ }
}
static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
{
- SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
- PBVHNode **nodes;
- int totnode;
+ PBVHNode **nodes;
+ int totnode;
- BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
- /* Disable OpenMP when dynamic-topology is enabled. Otherwise, new entries might be inserted by
- * sculpt_undo_push_node() into the GHash used internally by BM_log_original_vert_co() by a different thread.
- * See T33787. */
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- };
+ /* Disable OpenMP when dynamic-topology is enabled. Otherwise, new entries might be inserted by
+ * sculpt_undo_push_node() into the GHash used internally by BM_log_original_vert_co() by a different thread.
+ * See T33787. */
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ };
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && !ss->bm && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- paint_mesh_restore_co_task_cb,
- &settings);
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && !ss->bm &&
+ totnode > SCULPT_THREADED_LIMIT);
+ BLI_task_parallel_range(0, totnode, &data, paint_mesh_restore_co_task_cb, &settings);
- if (nodes)
- MEM_freeN(nodes);
+ if (nodes)
+ MEM_freeN(nodes);
}
/*** BVH Tree ***/
static void sculpt_extend_redraw_rect_previous(Object *ob, rcti *rect)
{
- /* 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) */
- SculptSession *ss = ob->sculpt;
+ /* 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) */
+ SculptSession *ss = ob->sculpt;
- if (ss->cache) {
- if (!BLI_rcti_is_empty(&ss->cache->previous_r))
- BLI_rcti_union(rect, &ss->cache->previous_r);
- }
+ if (ss->cache) {
+ if (!BLI_rcti_is_empty(&ss->cache->previous_r))
+ BLI_rcti_union(rect, &ss->cache->previous_r);
+ }
}
/* Get a screen-space rectangle of the modified area */
-bool sculpt_get_redraw_rect(ARegion *ar, RegionView3D *rv3d,
- Object *ob, rcti *rect)
+bool sculpt_get_redraw_rect(ARegion *ar, RegionView3D *rv3d, Object *ob, rcti *rect)
{
- PBVH *pbvh = ob->sculpt->pbvh;
- float bb_min[3], bb_max[3];
+ PBVH *pbvh = ob->sculpt->pbvh;
+ float bb_min[3], bb_max[3];
- if (!pbvh)
- return 0;
+ if (!pbvh)
+ return 0;
- BKE_pbvh_redraw_BB(pbvh, bb_min, bb_max);
+ 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, ar, rv3d, ob)) {
+ return 0;
+ }
-
- return 1;
+ return 1;
}
void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar, Object *ob)
{
- PBVH *pbvh = ob->sculpt->pbvh;
- /* copy here, original will be used below */
- rcti rect = ob->sculpt->cache->current_r;
+ PBVH *pbvh = ob->sculpt->pbvh;
+ /* copy here, original will be used below */
+ rcti rect = ob->sculpt->cache->current_r;
- sculpt_extend_redraw_rect_previous(ob, &rect);
+ sculpt_extend_redraw_rect_previous(ob, &rect);
- paint_calc_redraw_planes(planes, ar, ob, &rect);
+ paint_calc_redraw_planes(planes, ar, ob, &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 */
- ob->sculpt->cache->previous_r = ob->sculpt->cache->current_r;
+ /* 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 */
+ ob->sculpt->cache->previous_r = ob->sculpt->cache->current_r;
- /* clear redraw flag from nodes */
- if (pbvh)
- BKE_pbvh_update(pbvh, PBVH_UpdateRedraw, NULL);
+ /* clear redraw flag from nodes */
+ if (pbvh)
+ BKE_pbvh_update(pbvh, PBVH_UpdateRedraw, NULL);
}
/************************ Brush Testing *******************/
void sculpt_brush_test_init(SculptSession *ss, SculptBrushTest *test)
{
- RegionView3D *rv3d = ss->cache->vc->rv3d;
+ RegionView3D *rv3d = ss->cache->vc->rv3d;
- test->radius_squared = ss->cache->radius_squared;
- copy_v3_v3(test->location, ss->cache->location);
- test->dist = 0.0f; /* just for initialize */
+ test->radius_squared = ss->cache->radius_squared;
+ copy_v3_v3(test->location, ss->cache->location);
+ test->dist = 0.0f; /* just for initialize */
- /* Only for 2D projection. */
- zero_v4(test->plane_view);
- zero_v4(test->plane_tool);
+ /* Only for 2D projection. */
+ zero_v4(test->plane_view);
+ zero_v4(test->plane_tool);
- test->mirror_symmetry_pass = ss->cache->mirror_symmetry_pass;
+ test->mirror_symmetry_pass = ss->cache->mirror_symmetry_pass;
- if (rv3d->rflag & RV3D_CLIPPING) {
- test->clip_rv3d = rv3d;
- }
- else {
- test->clip_rv3d = NULL;
- }
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ test->clip_rv3d = rv3d;
+ }
+ else {
+ test->clip_rv3d = NULL;
+ }
}
BLI_INLINE bool sculpt_brush_test_clipping(const SculptBrushTest *test, const float co[3])
{
- RegionView3D *rv3d = test->clip_rv3d;
- if (!rv3d) {
- return false;
- }
- float symm_co[3];
- flip_v3_v3(symm_co, co, test->mirror_symmetry_pass);
- return ED_view3d_clipping_test(rv3d, symm_co, true);
+ RegionView3D *rv3d = test->clip_rv3d;
+ if (!rv3d) {
+ return false;
+ }
+ float symm_co[3];
+ flip_v3_v3(symm_co, co, test->mirror_symmetry_pass);
+ return ED_view3d_clipping_test(rv3d, symm_co, true);
}
bool sculpt_brush_test_sphere(SculptBrushTest *test, const float co[3])
{
- float distsq = len_squared_v3v3(co, test->location);
+ float distsq = len_squared_v3v3(co, test->location);
- if (distsq <= test->radius_squared) {
- if (sculpt_brush_test_clipping(test, co)) {
- return 0;
- }
- test->dist = sqrtf(distsq);
- return 1;
- }
- else {
- return 0;
- }
+ if (distsq <= test->radius_squared) {
+ if (sculpt_brush_test_clipping(test, co)) {
+ return 0;
+ }
+ test->dist = sqrtf(distsq);
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
bool sculpt_brush_test_sphere_sq(SculptBrushTest *test, const float co[3])
{
- float distsq = len_squared_v3v3(co, test->location);
+ float distsq = len_squared_v3v3(co, test->location);
- if (distsq <= test->radius_squared) {
- if (sculpt_brush_test_clipping(test, co)) {
- return 0;
- }
- test->dist = distsq;
- return 1;
- }
- else {
- return 0;
- }
+ if (distsq <= test->radius_squared) {
+ if (sculpt_brush_test_clipping(test, co)) {
+ return 0;
+ }
+ test->dist = distsq;
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
bool sculpt_brush_test_sphere_fast(const SculptBrushTest *test, const float co[3])
{
- if (sculpt_brush_test_clipping(test, co)) {
- return 0;
- }
- return len_squared_v3v3(co, test->location) <= test->radius_squared;
+ if (sculpt_brush_test_clipping(test, co)) {
+ return 0;
+ }
+ return len_squared_v3v3(co, test->location) <= test->radius_squared;
}
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);
- float distsq = len_squared_v3v3(co_proj, test->location);
+ float co_proj[3];
+ closest_to_plane_normalized_v3(co_proj, test->plane_view, co);
+ float distsq = len_squared_v3v3(co_proj, test->location);
- if (distsq <= test->radius_squared) {
- if (sculpt_brush_test_clipping(test, co)) {
- return 0;
- }
- test->dist = distsq;
- return 1;
- }
- else {
- return 0;
- }
+ if (distsq <= test->radius_squared) {
+ if (sculpt_brush_test_clipping(test, co)) {
+ return 0;
+ }
+ test->dist = distsq;
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
bool sculpt_brush_test_cube(SculptBrushTest *test, const float co[3], float local[4][4])
{
- float side = M_SQRT1_2;
- float local_co[3];
+ float side = M_SQRT1_2;
+ float local_co[3];
- if (sculpt_brush_test_clipping(test, co)) {
- return 0;
- }
+ if (sculpt_brush_test_clipping(test, co)) {
+ return 0;
+ }
- mul_v3_m4v3(local_co, local, co);
+ mul_v3_m4v3(local_co, local, co);
- local_co[0] = fabsf(local_co[0]);
- local_co[1] = fabsf(local_co[1]);
- local_co[2] = fabsf(local_co[2]);
+ local_co[0] = fabsf(local_co[0]);
+ local_co[1] = fabsf(local_co[1]);
+ local_co[2] = fabsf(local_co[2]);
- if (local_co[0] <= side && local_co[1] <= side && local_co[2] <= side) {
- float p = 4.0f;
+ if (local_co[0] <= side && local_co[1] <= side && local_co[2] <= side) {
+ float p = 4.0f;
- test->dist = ((powf(local_co[0], p) +
- powf(local_co[1], p) +
- powf(local_co[2], p)) / powf(side, p));
+ test->dist = ((powf(local_co[0], p) + powf(local_co[1], p) + powf(local_co[2], p)) /
+ powf(side, p));
- return 1;
- }
- else {
- return 0;
- }
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
-SculptBrushTestFn sculpt_brush_test_init_with_falloff_shape(
- SculptSession *ss, SculptBrushTest *test, char falloff_shape)
+SculptBrushTestFn sculpt_brush_test_init_with_falloff_shape(SculptSession *ss,
+ SculptBrushTest *test,
+ char falloff_shape)
{
- 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;
- }
- 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;
- }
- return sculpt_brush_test_sq_fn;
+ 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;
+ }
+ 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;
+ }
+ return sculpt_brush_test_sq_fn;
}
-const float *sculpt_brush_frontface_normal_from_falloff_shape(
- SculptSession *ss, char falloff_shape)
+const float *sculpt_brush_frontface_normal_from_falloff_shape(SculptSession *ss,
+ char falloff_shape)
{
- if (falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
- return ss->cache->sculpt_normal_symm;
- }
- else {
- /* PAINT_FALLOFF_SHAPE_TUBE */
- return ss->cache->view_normal;
- }
+ if (falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
+ return ss->cache->sculpt_normal_symm;
+ }
+ else {
+ /* PAINT_FALLOFF_SHAPE_TUBE */
+ return ss->cache->view_normal;
+ }
}
-
-static float frontface(const Brush *br, const float sculpt_normal[3],
- const short no[3], const float fno[3])
+static float frontface(const Brush *br,
+ const float sculpt_normal[3],
+ const short no[3],
+ const float fno[3])
{
- if (br->flag & BRUSH_FRONTFACE) {
- float dot;
+ if (br->flag & BRUSH_FRONTFACE) {
+ float dot;
- if (no) {
- float tmp[3];
+ if (no) {
+ float tmp[3];
- normal_short_to_float_v3(tmp, no);
- dot = dot_v3v3(tmp, sculpt_normal);
- }
- else {
- dot = dot_v3v3(fno, sculpt_normal);
- }
- return dot > 0 ? dot : 0;
- }
- else {
- return 1;
- }
+ normal_short_to_float_v3(tmp, no);
+ dot = dot_v3v3(tmp, sculpt_normal);
+ }
+ else {
+ dot = dot_v3v3(fno, sculpt_normal);
+ }
+ return dot > 0 ? dot : 0;
+ }
+ else {
+ return 1;
+ }
}
#if 0
static bool sculpt_brush_test_cyl(SculptBrushTest *test, float co[3], float location[3], const float area_no[3])
{
- if (sculpt_brush_test_sphere_fast(test, co)) {
- float t1[3], t2[3], t3[3], dist;
+ if (sculpt_brush_test_sphere_fast(test, co)) {
+ float t1[3], t2[3], t3[3], dist;
- sub_v3_v3v3(t1, location, co);
- sub_v3_v3v3(t2, x2, location);
+ sub_v3_v3v3(t1, location, co);
+ sub_v3_v3v3(t2, x2, location);
- cross_v3_v3v3(t3, area_no, t1);
+ cross_v3_v3v3(t3, area_no, t1);
- dist = len_v3(t3) / len_v3(t2);
+ dist = len_v3(t3) / len_v3(t2);
- test->dist = dist;
+ test->dist = dist;
- return 1;
- }
+ return 1;
+ }
- return 0;
+ return 0;
}
#endif
@@ -726,70 +702,73 @@ static bool sculpt_brush_test_cyl(SculptBrushTest *test, float co[3], float loca
*/
static void flip_v3(float v[3], const char symm)
{
- flip_v3_v3(v, v, symm);
+ flip_v3_v3(v, v, symm);
}
static float calc_overlap(StrokeCache *cache, const char symm, const char axis, const float angle)
{
- float mirror[3];
- float distsq;
+ float mirror[3];
+ float distsq;
- /* flip_v3_v3(mirror, cache->traced_location, symm); */
- flip_v3_v3(mirror, cache->true_location, symm);
+ /* flip_v3_v3(mirror, cache->traced_location, symm); */
+ flip_v3_v3(mirror, cache->true_location, symm);
- if (axis != 0) {
- float mat[3][3];
- axis_angle_to_mat3_single(mat, axis, angle);
- mul_m3_v3(mat, mirror);
- }
+ if (axis != 0) {
+ float mat[3][3];
+ axis_angle_to_mat3_single(mat, axis, angle);
+ mul_m3_v3(mat, mirror);
+ }
- /* distsq = len_squared_v3v3(mirror, cache->traced_location); */
- distsq = len_squared_v3v3(mirror, cache->true_location);
+ /* 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;
+ if (distsq <= 4.0f * (cache->radius_squared))
+ return (2.0f * (cache->radius) - sqrtf(distsq)) / (2.0f * (cache->radius));
+ else
+ return 0;
}
-static float calc_radial_symmetry_feather(Sculpt *sd, StrokeCache *cache, const char symm, const char axis)
+static float calc_radial_symmetry_feather(Sculpt *sd,
+ StrokeCache *cache,
+ const char symm,
+ const char axis)
{
- int i;
- float overlap;
+ int i;
+ float overlap;
- overlap = 0;
- for (i = 1; i < sd->radial_symm[axis - 'X']; ++i) {
- const float angle = 2 * M_PI * i / sd->radial_symm[axis - 'X'];
- overlap += calc_overlap(cache, symm, axis, angle);
- }
+ overlap = 0;
+ for (i = 1; i < sd->radial_symm[axis - 'X']; ++i) {
+ const float angle = 2 * M_PI * i / sd->radial_symm[axis - 'X'];
+ overlap += calc_overlap(cache, symm, axis, angle);
+ }
- return overlap;
+ return overlap;
}
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;
+ if (sd->paint.symmetry_flags & PAINT_SYMMETRY_FEATHER) {
+ float overlap;
+ int symm = cache->symmetry;
+ int i;
- overlap = 0;
- for (i = 0; i <= symm; i++) {
- if (i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)))) {
+ overlap = 0;
+ for (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);
+ overlap += calc_overlap(cache, i, 0, 0);
- overlap += calc_radial_symmetry_feather(sd, cache, i, 'X');
- overlap += calc_radial_symmetry_feather(sd, cache, i, 'Y');
- overlap += calc_radial_symmetry_feather(sd, cache, i, 'Z');
- }
- }
+ overlap += calc_radial_symmetry_feather(sd, cache, i, 'X');
+ overlap += calc_radial_symmetry_feather(sd, cache, i, 'Y');
+ overlap += calc_radial_symmetry_feather(sd, cache, i, 'Z');
+ }
+ }
- return 1 / overlap;
- }
- else {
- return 1;
- }
+ return 1 / overlap;
+ }
+ else {
+ return 1;
+ }
}
/** \name Calculate Normal and Center
@@ -805,393 +784,395 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache)
* \note These are all _very_ similar, when changing one, check others.
* \{ */
-static void calc_area_normal_and_center_task_cb(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict UNUSED(tls))
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- float (*area_nos)[3] = data->area_nos;
- float (*area_cos)[3] = data->area_cos;
-
- PBVHVertexIter vd;
- SculptUndoNode *unode = NULL;
-
- float private_co[2][3] = {{0.0f}};
- float private_no[2][3] = {{0.0f}};
- int private_count[2] = {0};
- bool use_original = false;
-
- if (ss->cache->original) {
- 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);
-
-
- /* 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++) {
- const float *co_tri[3] = {
- orco_coords[orco_tris[i][0]],
- orco_coords[orco_tris[i][1]],
- orco_coords[orco_tris[i][2]],
- };
- float co[3];
-
- closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri));
-
- if (sculpt_brush_test_sq_fn(&test, co)) {
- 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 (area_cos)
- add_v3_v3(private_co[flip_index], co);
- if (area_nos)
- add_v3_v3(private_no[flip_index], no);
- private_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 */
-
- if (use_original) {
- if (unode->bm_entry) {
- BM_log_original_vert_data(ss->bm_log, vd.bm_vert, &co, &no_s);
- }
- else {
- co = unode->co[vd.i];
- no_s = unode->no[vd.i];
- }
- }
- else {
- co = vd.co;
- }
-
- if (sculpt_brush_test_sq_fn(&test, co)) {
- float no_buf[3];
- const float *no;
- int flip_index;
-
- if (use_original) {
- normal_short_to_float_v3(no_buf, no_s);
- no = no_buf;
- }
- else {
- if (vd.no) {
- normal_short_to_float_v3(no_buf, vd.no);
- no = no_buf;
- }
- else {
- no = vd.fno;
- }
- }
-
- flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f);
- if (area_cos)
- add_v3_v3(private_co[flip_index], co);
- if (area_nos)
- add_v3_v3(private_no[flip_index], no);
- private_count[flip_index] += 1;
- }
- }
- BKE_pbvh_vertex_iter_end;
- }
-
- BLI_mutex_lock(&data->mutex);
-
- /* for flatten center */
- if (area_cos) {
- add_v3_v3(area_cos[0], private_co[0]);
- add_v3_v3(area_cos[1], private_co[1]);
- }
-
- /* for area normal */
- if (area_nos) {
- add_v3_v3(area_nos[0], private_no[0]);
- add_v3_v3(area_nos[1], private_no[1]);
- }
-
- /* weights */
- data->count[0] += private_count[0];
- data->count[1] += private_count[1];
-
- BLI_mutex_unlock(&data->mutex);
+static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ float(*area_nos)[3] = data->area_nos;
+ float(*area_cos)[3] = data->area_cos;
+
+ PBVHVertexIter vd;
+ SculptUndoNode *unode = NULL;
+
+ float private_co[2][3] = {{0.0f}};
+ float private_no[2][3] = {{0.0f}};
+ int private_count[2] = {0};
+ bool use_original = false;
+
+ if (ss->cache->original) {
+ 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);
+
+ /* 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++) {
+ const float *co_tri[3] = {
+ orco_coords[orco_tris[i][0]],
+ orco_coords[orco_tris[i][1]],
+ orco_coords[orco_tris[i][2]],
+ };
+ float co[3];
+
+ closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri));
+
+ if (sculpt_brush_test_sq_fn(&test, co)) {
+ 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 (area_cos)
+ add_v3_v3(private_co[flip_index], co);
+ if (area_nos)
+ add_v3_v3(private_no[flip_index], no);
+ private_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 */
+
+ if (use_original) {
+ if (unode->bm_entry) {
+ BM_log_original_vert_data(ss->bm_log, vd.bm_vert, &co, &no_s);
+ }
+ else {
+ co = unode->co[vd.i];
+ no_s = unode->no[vd.i];
+ }
+ }
+ else {
+ co = vd.co;
+ }
+
+ if (sculpt_brush_test_sq_fn(&test, co)) {
+ float no_buf[3];
+ const float *no;
+ int flip_index;
+
+ if (use_original) {
+ normal_short_to_float_v3(no_buf, no_s);
+ no = no_buf;
+ }
+ else {
+ if (vd.no) {
+ normal_short_to_float_v3(no_buf, vd.no);
+ no = no_buf;
+ }
+ else {
+ no = vd.fno;
+ }
+ }
+
+ flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f);
+ if (area_cos)
+ add_v3_v3(private_co[flip_index], co);
+ if (area_nos)
+ add_v3_v3(private_no[flip_index], no);
+ private_count[flip_index] += 1;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+ }
+
+ BLI_mutex_lock(&data->mutex);
+
+ /* for flatten center */
+ if (area_cos) {
+ add_v3_v3(area_cos[0], private_co[0]);
+ add_v3_v3(area_cos[1], private_co[1]);
+ }
+
+ /* for area normal */
+ if (area_nos) {
+ add_v3_v3(area_nos[0], private_no[0]);
+ add_v3_v3(area_nos[1], private_no[1]);
+ }
+
+ /* weights */
+ data->count[0] += private_count[0];
+ data->count[1] += private_count[1];
+
+ BLI_mutex_unlock(&data->mutex);
}
static void calc_area_center(
- Sculpt *sd, Object *ob,
- PBVHNode **nodes, int totnode,
- 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);
- int n;
-
- /* 0=towards view, 1=flipped */
- float area_cos[2][3] = {{0.0f}};
-
- int count[2] = {0};
-
- /* Intentionally set 'sd' to NULL since we share logic with vertex paint. */
- SculptThreadedTaskData data = {
- .sd = NULL, .ob = ob, .brush = brush, .nodes = nodes, .totnode = totnode,
- .has_bm_orco = has_bm_orco, .area_cos = area_cos, .area_nos = NULL, .count = count,
- };
- BLI_mutex_init(&data.mutex);
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- calc_area_normal_and_center_task_cb,
- &settings);
-
- BLI_mutex_end(&data.mutex);
-
- /* for flatten center */
- for (n = 0; n < ARRAY_SIZE(area_cos); n++) {
- if (count[n] != 0) {
- mul_v3_v3fl(r_area_co, area_cos[n], 1.0f / count[n]);
- break;
- }
- }
- if (n == 2) {
- zero_v3(r_area_co);
- }
+ Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, 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);
+ int n;
+
+ /* 0=towards view, 1=flipped */
+ float area_cos[2][3] = {{0.0f}};
+
+ int count[2] = {0};
+
+ /* Intentionally set 'sd' to NULL since we share logic with vertex paint. */
+ SculptThreadedTaskData data = {
+ .sd = NULL,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .totnode = totnode,
+ .has_bm_orco = has_bm_orco,
+ .area_cos = area_cos,
+ .area_nos = NULL,
+ .count = count,
+ };
+ BLI_mutex_init(&data.mutex);
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
+
+ BLI_mutex_end(&data.mutex);
+
+ /* for flatten center */
+ for (n = 0; n < ARRAY_SIZE(area_cos); n++) {
+ if (count[n] != 0) {
+ mul_v3_v3fl(r_area_co, area_cos[n], 1.0f / count[n]);
+ break;
+ }
+ }
+ if (n == 2) {
+ zero_v3(r_area_co);
+ }
}
static void calc_area_normal(
- Sculpt *sd, Object *ob,
- PBVHNode **nodes, int totnode,
- float r_area_no[3])
+ 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) && totnode > SCULPT_THREADED_LIMIT;
- sculpt_pbvh_calc_area_normal(brush, ob, nodes, totnode, use_threading, r_area_no);
+ const Brush *brush = BKE_paint_brush(&sd->paint);
+ bool use_threading = (sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT;
+ sculpt_pbvh_calc_area_normal(brush, ob, nodes, totnode, use_threading, r_area_no);
}
/* expose 'calc_area_normal' externally. */
-void sculpt_pbvh_calc_area_normal(
- const Brush *brush, Object *ob,
- PBVHNode **nodes, int totnode,
- bool use_threading,
- float r_area_no[3])
-{
- SculptSession *ss = ob->sculpt;
- const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush);
-
- /* 0=towards view, 1=flipped */
- float area_nos[2][3] = {{0.0f}};
-
- int count[2] = {0};
-
- /* Intentionally set 'sd' to NULL since this is used for vertex paint too. */
- SculptThreadedTaskData data = {
- .sd = NULL, .ob = ob, .brush = brush, .nodes = nodes, .totnode = totnode,
- .has_bm_orco = has_bm_orco, .area_cos = NULL, .area_nos = area_nos, .count = count,
- };
- BLI_mutex_init(&data.mutex);
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = use_threading;
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- calc_area_normal_and_center_task_cb,
- &settings);
-
- BLI_mutex_end(&data.mutex);
-
- /* for area normal */
- for (int i = 0; i < ARRAY_SIZE(area_nos); i++) {
- if (normalize_v3_v3(r_area_no, area_nos[i]) != 0.0f) {
- break;
- }
- }
+void sculpt_pbvh_calc_area_normal(const Brush *brush,
+ Object *ob,
+ PBVHNode **nodes,
+ int totnode,
+ bool use_threading,
+ float r_area_no[3])
+{
+ SculptSession *ss = ob->sculpt;
+ const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush);
+
+ /* 0=towards view, 1=flipped */
+ float area_nos[2][3] = {{0.0f}};
+
+ int count[2] = {0};
+
+ /* Intentionally set 'sd' to NULL since this is used for vertex paint too. */
+ SculptThreadedTaskData data = {
+ .sd = NULL,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .totnode = totnode,
+ .has_bm_orco = has_bm_orco,
+ .area_cos = NULL,
+ .area_nos = area_nos,
+ .count = count,
+ };
+ BLI_mutex_init(&data.mutex);
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = use_threading;
+ BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
+
+ BLI_mutex_end(&data.mutex);
+
+ /* for area normal */
+ for (int i = 0; i < ARRAY_SIZE(area_nos); i++) {
+ if (normalize_v3_v3(r_area_no, area_nos[i]) != 0.0f) {
+ break;
+ }
+ }
}
-
/* 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);
- int n;
-
- /* 0=towards view, 1=flipped */
- float area_cos[2][3] = {{0.0f}};
- float area_nos[2][3] = {{0.0f}};
-
- int count[2] = {0};
-
- /* Intentionally set 'sd' to NULL since this is used for vertex paint too. */
- SculptThreadedTaskData data = {
- .sd = NULL, .ob = ob, .brush = brush, .nodes = nodes, .totnode = totnode,
- .has_bm_orco = has_bm_orco, .area_cos = area_cos, .area_nos = area_nos, .count = count,
- };
- BLI_mutex_init(&data.mutex);
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- calc_area_normal_and_center_task_cb,
- &settings);
-
- BLI_mutex_end(&data.mutex);
-
- /* for flatten center */
- for (n = 0; n < ARRAY_SIZE(area_cos); n++) {
- if (count[n] != 0) {
- mul_v3_v3fl(r_area_co, area_cos[n], 1.0f / count[n]);
- break;
- }
- }
- if (n == 2) {
- zero_v3(r_area_co);
- }
-
- /* for area normal */
- for (n = 0; n < ARRAY_SIZE(area_nos); n++) {
- if (normalize_v3_v3(r_area_no, area_nos[n]) != 0.0f) {
- break;
- }
- }
+ 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);
+ int n;
+
+ /* 0=towards view, 1=flipped */
+ float area_cos[2][3] = {{0.0f}};
+ float area_nos[2][3] = {{0.0f}};
+
+ int count[2] = {0};
+
+ /* Intentionally set 'sd' to NULL since this is used for vertex paint too. */
+ SculptThreadedTaskData data = {
+ .sd = NULL,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .totnode = totnode,
+ .has_bm_orco = has_bm_orco,
+ .area_cos = area_cos,
+ .area_nos = area_nos,
+ .count = count,
+ };
+ BLI_mutex_init(&data.mutex);
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
+
+ BLI_mutex_end(&data.mutex);
+
+ /* for flatten center */
+ for (n = 0; n < ARRAY_SIZE(area_cos); n++) {
+ if (count[n] != 0) {
+ mul_v3_v3fl(r_area_co, area_cos[n], 1.0f / count[n]);
+ break;
+ }
+ }
+ if (n == 2) {
+ zero_v3(r_area_co);
+ }
+
+ /* for area normal */
+ for (n = 0; n < ARRAY_SIZE(area_nos); n++) {
+ if (normalize_v3_v3(r_area_no, area_nos[n]) != 0.0f) {
+ break;
+ }
+ }
}
/** \} */
-
/* Return modified brush strength. Includes the direction of the brush, positive
* values pull vertices, negative values push. Uses tablet pressure and a
* special multiplier found experimentally to scale the strength factor. */
-static float brush_strength(
- const Sculpt *sd, const StrokeCache *cache,
- const float feather, const UnifiedPaintSettings *ups)
-{
- 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 */
- 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(scene, brush) ? cache->pressure : 1;
- float pen_flip = cache->pen_flip ? -1 : 1;
- float invert = cache->invert ? -1 : 1;
- float overlap = ups->overlap_factor;
- /* spacing is integer percentage of radius, divide by 50 to get
- * normalized diameter */
-
- float flip = dir * invert * pen_flip;
-
- switch (brush->sculpt_tool) {
- case SCULPT_TOOL_CLAY:
- case SCULPT_TOOL_CLAY_STRIPS:
- case SCULPT_TOOL_DRAW:
- case SCULPT_TOOL_LAYER:
- return alpha * flip * pressure * overlap * feather;
-
- case SCULPT_TOOL_MASK:
- overlap = (1 + overlap) / 2;
- switch ((BrushMaskTool)brush->mask_tool) {
- case BRUSH_MASK_DRAW:
- return alpha * flip * pressure * overlap * feather;
- case BRUSH_MASK_SMOOTH:
- return alpha * pressure * feather;
- }
- BLI_assert(!"Not supposed to happen");
- return 0.0f;
-
- case SCULPT_TOOL_CREASE:
- case SCULPT_TOOL_BLOB:
- return alpha * flip * pressure * overlap * feather;
-
- case SCULPT_TOOL_INFLATE:
- if (flip > 0) {
- return 0.250f * alpha * flip * pressure * overlap * feather;
- }
- else {
- return 0.125f * alpha * flip * pressure * overlap * feather;
- }
-
- case SCULPT_TOOL_FILL:
- case SCULPT_TOOL_SCRAPE:
- case SCULPT_TOOL_FLATTEN:
- if (flip > 0) {
- overlap = (1 + overlap) / 2;
- return alpha * flip * pressure * overlap * feather;
- }
- else {
- /* reduce strength for DEEPEN, PEAKS, and CONTRAST */
- return 0.5f * alpha * flip * pressure * overlap * feather;
- }
-
- case SCULPT_TOOL_SMOOTH:
- return alpha * pressure * feather;
-
- case SCULPT_TOOL_PINCH:
- if (flip > 0) {
- return alpha * flip * pressure * overlap * feather;
- }
- else {
- return 0.25f * alpha * flip * pressure * overlap * feather;
- }
-
- case SCULPT_TOOL_NUDGE:
- overlap = (1 + overlap) / 2;
- return alpha * pressure * overlap * feather;
-
- case SCULPT_TOOL_THUMB:
- return alpha * pressure * feather;
-
- case SCULPT_TOOL_SNAKE_HOOK:
- return root_alpha * feather;
-
- case SCULPT_TOOL_GRAB:
- return root_alpha * feather;
-
- case SCULPT_TOOL_ROTATE:
- return alpha * pressure * feather;
-
- default:
- return 0;
- }
+static float brush_strength(const Sculpt *sd,
+ const StrokeCache *cache,
+ const float feather,
+ const UnifiedPaintSettings *ups)
+{
+ 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 */
+ 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(scene, brush) ? cache->pressure : 1;
+ float pen_flip = cache->pen_flip ? -1 : 1;
+ float invert = cache->invert ? -1 : 1;
+ float overlap = ups->overlap_factor;
+ /* spacing is integer percentage of radius, divide by 50 to get
+ * normalized diameter */
+
+ float flip = dir * invert * pen_flip;
+
+ switch (brush->sculpt_tool) {
+ case SCULPT_TOOL_CLAY:
+ case SCULPT_TOOL_CLAY_STRIPS:
+ case SCULPT_TOOL_DRAW:
+ case SCULPT_TOOL_LAYER:
+ return alpha * flip * pressure * overlap * feather;
+
+ case SCULPT_TOOL_MASK:
+ overlap = (1 + overlap) / 2;
+ switch ((BrushMaskTool)brush->mask_tool) {
+ case BRUSH_MASK_DRAW:
+ return alpha * flip * pressure * overlap * feather;
+ case BRUSH_MASK_SMOOTH:
+ return alpha * pressure * feather;
+ }
+ BLI_assert(!"Not supposed to happen");
+ return 0.0f;
+
+ case SCULPT_TOOL_CREASE:
+ case SCULPT_TOOL_BLOB:
+ return alpha * flip * pressure * overlap * feather;
+
+ case SCULPT_TOOL_INFLATE:
+ if (flip > 0) {
+ return 0.250f * alpha * flip * pressure * overlap * feather;
+ }
+ else {
+ return 0.125f * alpha * flip * pressure * overlap * feather;
+ }
+
+ case SCULPT_TOOL_FILL:
+ case SCULPT_TOOL_SCRAPE:
+ case SCULPT_TOOL_FLATTEN:
+ if (flip > 0) {
+ overlap = (1 + overlap) / 2;
+ return alpha * flip * pressure * overlap * feather;
+ }
+ else {
+ /* reduce strength for DEEPEN, PEAKS, and CONTRAST */
+ return 0.5f * alpha * flip * pressure * overlap * feather;
+ }
+
+ case SCULPT_TOOL_SMOOTH:
+ return alpha * pressure * feather;
+
+ case SCULPT_TOOL_PINCH:
+ if (flip > 0) {
+ return alpha * flip * pressure * overlap * feather;
+ }
+ else {
+ return 0.25f * alpha * flip * pressure * overlap * feather;
+ }
+
+ case SCULPT_TOOL_NUDGE:
+ overlap = (1 + overlap) / 2;
+ return alpha * pressure * overlap * feather;
+
+ case SCULPT_TOOL_THUMB:
+ return alpha * pressure * feather;
+
+ case SCULPT_TOOL_SNAKE_HOOK:
+ return root_alpha * feather;
+
+ case SCULPT_TOOL_GRAB:
+ return root_alpha * feather;
+
+ case SCULPT_TOOL_ROTATE:
+ return alpha * pressure * feather;
+
+ default:
+ return 0;
+ }
}
/* Return a multiplier for brush strength on a particular vertex. */
-float tex_strength(SculptSession *ss, const Brush *br,
+float tex_strength(SculptSession *ss,
+ const Brush *br,
const float brush_point[3],
const float len,
const short vno[3],
@@ -1199,299 +1180,295 @@ float tex_strength(SculptSession *ss, const Brush *br,
const float mask,
const int thread_id)
{
- StrokeCache *cache = ss->cache;
- const Scene *scene = cache->vc->scene;
- const MTex *mtex = &br->mtex;
- float avg = 1;
- float rgba[4];
- float point[3];
+ StrokeCache *cache = ss->cache;
+ const Scene *scene = cache->vc->scene;
+ const MTex *mtex = &br->mtex;
+ float avg = 1;
+ float rgba[4];
+ float point[3];
- sub_v3_v3v3(point, brush_point, cache->plane_offset);
+ sub_v3_v3v3(point, brush_point, cache->plane_offset);
- if (!mtex->tex) {
- avg = 1;
- }
- else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
- /* 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 */
+ if (!mtex->tex) {
+ avg = 1;
+ }
+ else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
+ /* 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 */
- /* 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. */
+ /* 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. */
- flip_v3_v3(symm_point, point, cache->mirror_symmetry_pass);
+ flip_v3_v3(symm_point, point, cache->mirror_symmetry_pass);
- if (cache->radial_symmetry_pass)
- mul_m4_v3(cache->symm_rot_mat_inv, symm_point);
+ if (cache->radial_symmetry_pass)
+ 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->ar, symm_point, point_2d, cache->projection_mat);
- /* 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 */
+ /* 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 */
- mul_m4_v3(cache->brush_local_mat, symm_point);
+ mul_m4_v3(cache->brush_local_mat, symm_point);
- x = symm_point[0];
- y = symm_point[1];
+ x = symm_point[0];
+ y = symm_point[1];
- x *= br->mtex.size[0];
- y *= br->mtex.size[1];
+ x *= br->mtex.size[0];
+ y *= br->mtex.size[1];
- x += br->mtex.ofs[0];
- y += br->mtex.ofs[1];
+ x += br->mtex.ofs[0];
+ y += br->mtex.ofs[1];
- avg = paint_get_tex_pixel(&br->mtex, x, y, ss->tex_pool, thread_id);
+ avg = paint_get_tex_pixel(&br->mtex, x, y, ss->tex_pool, thread_id);
- avg += br->texture_sample_bias;
- }
- else {
- const float point_3d[3] = {point_2d[0], point_2d[1], 0.0f};
- avg = BKE_brush_sample_tex_3d(scene, br, point_3d, rgba, 0, ss->tex_pool);
- }
- }
+ avg += br->texture_sample_bias;
+ }
+ else {
+ const float point_3d[3] = {point_2d[0], point_2d[1], 0.0f};
+ avg = BKE_brush_sample_tex_3d(scene, br, point_3d, rgba, 0, ss->tex_pool);
+ }
+ }
- /* Falloff curve */
- avg *= BKE_brush_curve_strength(br, len, cache->radius);
+ /* Falloff curve */
+ avg *= BKE_brush_curve_strength(br, len, cache->radius);
- avg *= frontface(br, cache->view_normal, vno, fno);
+ avg *= frontface(br, cache->view_normal, vno, fno);
- /* Paint mask */
- avg *= 1.0f - mask;
+ /* Paint mask */
+ avg *= 1.0f - mask;
- return avg;
+ return avg;
}
/* Test AABB against sphere */
bool sculpt_search_sphere_cb(PBVHNode *node, void *data_v)
{
- SculptSearchSphereData *data = data_v;
- float *center = data->ss->cache->location, nearest[3];
- float t[3], bb_min[3], bb_max[3];
- int i;
+ SculptSearchSphereData *data = data_v;
+ float *center = data->ss->cache->location, nearest[3];
+ float t[3], bb_min[3], bb_max[3];
+ int i;
- if (data->original)
- BKE_pbvh_node_get_original_BB(node, bb_min, bb_max);
- else
- BKE_pbvh_node_get_BB(node, bb_min, bb_max);
+ if (data->original)
+ BKE_pbvh_node_get_original_BB(node, bb_min, bb_max);
+ else
+ BKE_pbvh_node_get_BB(node, bb_min, bb_max);
- for (i = 0; i < 3; ++i) {
- if (bb_min[i] > center[i])
- nearest[i] = bb_min[i];
- else if (bb_max[i] < center[i])
- nearest[i] = bb_max[i];
- else
- nearest[i] = center[i];
- }
+ for (i = 0; i < 3; ++i) {
+ if (bb_min[i] > center[i])
+ nearest[i] = bb_min[i];
+ else if (bb_max[i] < center[i])
+ nearest[i] = bb_max[i];
+ else
+ nearest[i] = center[i];
+ }
- sub_v3_v3v3(t, center, nearest);
+ sub_v3_v3v3(t, center, nearest);
- return len_squared_v3(t) < data->radius_squared;
+ return len_squared_v3(t) < data->radius_squared;
}
/* 2D projection (distance to line). */
bool sculpt_search_circle_cb(PBVHNode *node, void *data_v)
{
- SculptSearchCircleData *data = data_v;
- float bb_min[3], bb_max[3];
+ SculptSearchCircleData *data = data_v;
+ float bb_min[3], bb_max[3];
- if (data->original)
- BKE_pbvh_node_get_original_BB(node, bb_min, bb_max);
- else
- BKE_pbvh_node_get_BB(node, bb_min, bb_min);
+ if (data->original)
+ BKE_pbvh_node_get_original_BB(node, bb_min, bb_max);
+ else
+ BKE_pbvh_node_get_BB(node, bb_min, bb_min);
- float dummy_co[3], dummy_depth;
- const float dist_sq = dist_squared_ray_to_aabb_v3(
- data->dist_ray_to_aabb_precalc, bb_min, bb_max, dummy_co, &dummy_depth);
+ float dummy_co[3], dummy_depth;
+ 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;
+ return dist_sq < data->radius_squared || 1;
}
/* 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])
{
- int i;
-
- for (i = 0; i < 3; ++i) {
- if (sd->flags & (SCULPT_LOCK_X << i))
- continue;
-
- if ((ss->cache->flag & (CLIP_X << i)) && (fabsf(co[i]) <= ss->cache->clip_tolerance[i]))
- co[i] = 0.0f;
- else
- co[i] = val[i];
- }
-}
-
-static PBVHNode **sculpt_pbvh_gather_generic(
- Object *ob, Sculpt *sd, const Brush *brush, bool use_original, float radius_scale, int *r_totnode)
-{
- SculptSession *ss = ob->sculpt;
- PBVHNode **nodes = NULL;
-
- /* Build a list of all nodes that are potentially within the 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),
- .original = use_original,
- };
- BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, r_totnode);
- }
- else {
- struct DistRayAABB_Precalc dist_ray_to_aabb_precalc;
- dist_squared_ray_to_aabb_v3_precalc(&dist_ray_to_aabb_precalc, ss->cache->location, ss->cache->view_normal);
- SculptSearchCircleData data = {
- .ss = ss,
- .sd = sd,
- .radius_squared = SQUARE(ss->cache->radius * radius_scale),
- .original = use_original,
- .dist_ray_to_aabb_precalc = &dist_ray_to_aabb_precalc,
- };
- BKE_pbvh_search_gather(ss->pbvh, sculpt_search_circle_cb, &data, &nodes, r_totnode);
- }
- return nodes;
+ int i;
+
+ for (i = 0; i < 3; ++i) {
+ if (sd->flags & (SCULPT_LOCK_X << i))
+ continue;
+
+ if ((ss->cache->flag & (CLIP_X << i)) && (fabsf(co[i]) <= ss->cache->clip_tolerance[i]))
+ co[i] = 0.0f;
+ else
+ co[i] = val[i];
+ }
+}
+
+static PBVHNode **sculpt_pbvh_gather_generic(Object *ob,
+ Sculpt *sd,
+ const Brush *brush,
+ bool use_original,
+ float radius_scale,
+ int *r_totnode)
+{
+ SculptSession *ss = ob->sculpt;
+ PBVHNode **nodes = NULL;
+
+ /* Build a list of all nodes that are potentially within the 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),
+ .original = use_original,
+ };
+ BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, r_totnode);
+ }
+ else {
+ struct DistRayAABB_Precalc dist_ray_to_aabb_precalc;
+ dist_squared_ray_to_aabb_v3_precalc(
+ &dist_ray_to_aabb_precalc, ss->cache->location, ss->cache->view_normal);
+ SculptSearchCircleData data = {
+ .ss = ss,
+ .sd = sd,
+ .radius_squared = SQUARE(ss->cache->radius * radius_scale),
+ .original = use_original,
+ .dist_ray_to_aabb_precalc = &dist_ray_to_aabb_precalc,
+ };
+ BKE_pbvh_search_gather(ss->pbvh, sculpt_search_circle_cb, &data, &nodes, r_totnode);
+ }
+ return nodes;
}
/* 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])
-{
- const Brush *brush = BKE_paint_brush(&sd->paint);
- const SculptSession *ss = ob->sculpt;
-
- 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(sd, ob, nodes, totnode, r_area_no);
- break;
-
- default:
- break;
- }
-}
-
-static void update_sculpt_normal(Sculpt *sd, Object *ob,
- PBVHNode **nodes, int totnode)
-{
- const Brush *brush = BKE_paint_brush(&sd->paint);
- StrokeCache *cache = ob->sculpt->cache;
-
- if (cache->mirror_symmetry_pass == 0 &&
- cache->radial_symmetry_pass == 0 &&
- (cache->first_time || !(brush->flag & BRUSH_ORIGINAL_NORMAL)))
- {
- calc_sculpt_normal(sd, ob, nodes, totnode, cache->sculpt_normal);
- if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
- project_plane_v3_v3v3(cache->sculpt_normal, cache->sculpt_normal, cache->view_normal);
- normalize_v3(cache->sculpt_normal);
- }
- copy_v3_v3(cache->sculpt_normal_symm, cache->sculpt_normal);
- }
- else {
- copy_v3_v3(cache->sculpt_normal_symm, cache->sculpt_normal);
- flip_v3(cache->sculpt_normal_symm, cache->mirror_symmetry_pass);
- mul_m4_v3(cache->symm_rot_mat, cache->sculpt_normal_symm);
- }
+ Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3])
+{
+ const Brush *brush = BKE_paint_brush(&sd->paint);
+ const SculptSession *ss = ob->sculpt;
+
+ 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(sd, ob, nodes, totnode, r_area_no);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void update_sculpt_normal(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+{
+ const Brush *brush = BKE_paint_brush(&sd->paint);
+ StrokeCache *cache = ob->sculpt->cache;
+
+ if (cache->mirror_symmetry_pass == 0 && cache->radial_symmetry_pass == 0 &&
+ (cache->first_time || !(brush->flag & BRUSH_ORIGINAL_NORMAL))) {
+ calc_sculpt_normal(sd, ob, nodes, totnode, cache->sculpt_normal);
+ if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
+ project_plane_v3_v3v3(cache->sculpt_normal, cache->sculpt_normal, cache->view_normal);
+ normalize_v3(cache->sculpt_normal);
+ }
+ copy_v3_v3(cache->sculpt_normal_symm, cache->sculpt_normal);
+ }
+ else {
+ copy_v3_v3(cache->sculpt_normal_symm, cache->sculpt_normal);
+ flip_v3(cache->sculpt_normal_symm, cache->mirror_symmetry_pass);
+ mul_m4_v3(cache->symm_rot_mat, cache->sculpt_normal_symm);
+ }
}
static void calc_local_y(ViewContext *vc, const float center[3], float y[3])
{
- Object *ob = vc->obact;
- float loc[3], mval_f[2] = {0.0f, 1.0f};
- float zfac;
+ Object *ob = vc->obact;
+ float loc[3], mval_f[2] = {0.0f, 1.0f};
+ float zfac;
- mul_v3_m4v3(loc, ob->imat, center);
- zfac = ED_view3d_calc_zfac(vc->rv3d, loc, NULL);
+ 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);
- normalize_v3(y);
+ ED_view3d_win_to_delta(vc->ar, mval_f, y, zfac);
+ normalize_v3(y);
- add_v3_v3(y, ob->loc);
- mul_m4_v3(ob->imat, y);
+ add_v3_v3(y, ob->loc);
+ mul_m4_v3(ob->imat, y);
}
-static void calc_brush_local_mat(const Brush *brush, Object *ob,
- float local_mat[4][4])
+static void calc_brush_local_mat(const Brush *brush, Object *ob, float local_mat[4][4])
{
- const StrokeCache *cache = ob->sculpt->cache;
- float tmat[4][4];
- float mat[4][4];
- float scale[4][4];
- float angle, v[3];
- float up[3];
+ const StrokeCache *cache = ob->sculpt->cache;
+ float tmat[4][4];
+ float mat[4][4];
+ float scale[4][4];
+ float angle, v[3];
+ float up[3];
- /* Ensure ob->imat is up to date */
- invert_m4_m4(ob->imat, ob->obmat);
+ /* 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;
+ mat[1][3] = 0;
+ mat[2][3] = 0;
+ mat[3][3] = 1;
- /* Get view's up vector in object-space */
- calc_local_y(cache->vc, cache->location, up);
+ /* Get view's up vector in object-space */
+ calc_local_y(cache->vc, cache->location, up);
- /* 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 */
- angle = brush->mtex.rot - cache->special_rotation;
- rotate_v3_v3v3fl(mat[0], v, cache->sculpt_normal, angle);
+ /* 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 */
+ angle = brush->mtex.rot - cache->special_rotation;
+ rotate_v3_v3v3fl(mat[0], v, cache->sculpt_normal, angle);
- /* Get other axes */
- cross_v3_v3v3(mat[1], cache->sculpt_normal, mat[0]);
- copy_v3_v3(mat[2], cache->sculpt_normal);
+ /* Get other axes */
+ cross_v3_v3v3(mat[1], cache->sculpt_normal, mat[0]);
+ copy_v3_v3(mat[2], cache->sculpt_normal);
- /* Set location */
- copy_v3_v3(mat[3], cache->location);
+ /* Set location */
+ copy_v3_v3(mat[3], cache->location);
- /* Scale by brush radius */
- normalize_m4(mat);
- scale_m4_fl(scale, cache->radius);
- mul_m4_m4m4(tmat, mat, scale);
+ /* 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) */
- invert_m4_m4(local_mat, tmat);
+ /* Return inverse (for converting from modelspace coords to local
+ * area coords) */
+ invert_m4_m4(local_mat, tmat);
}
static void update_brush_local_mat(Sculpt *sd, Object *ob)
{
- StrokeCache *cache = ob->sculpt->cache;
+ StrokeCache *cache = ob->sculpt->cache;
- if (cache->mirror_symmetry_pass == 0 &&
- cache->radial_symmetry_pass == 0)
- {
- calc_brush_local_mat(BKE_paint_brush(&sd->paint), ob,
- cache->brush_local_mat);
- }
+ if (cache->mirror_symmetry_pass == 0 && cache->radial_symmetry_pass == 0) {
+ calc_brush_local_mat(BKE_paint_brush(&sd->paint), ob, cache->brush_local_mat);
+ }
}
/* For the smooth brush, uses the neighboring vertices around vert to calculate
@@ -1499,40 +1476,39 @@ static void update_brush_local_mat(Sculpt *sd, Object *ob)
* 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;
+ 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;
+ /* Don't modify corner vertices */
+ if (vert_map->count > 1) {
+ int i, total = 0;
- zero_v3(avg);
+ 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];
+ 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);
+ 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++;
- }
- }
- }
- }
+ total++;
+ }
+ }
+ }
+ }
- if (total > 0) {
- mul_v3_fl(avg, 1.0f / total);
- return;
- }
- }
+ if (total > 0) {
+ mul_v3_fl(avg, 1.0f / total);
+ return;
+ }
+ }
- copy_v3_v3(avg, deform_co ? deform_co[vert] : mvert[vert].co);
+ copy_v3_v3(avg, deform_co ? deform_co[vert] : mvert[vert].co);
}
/* Similar to neighbor_average(), but returns an averaged mask value
@@ -1540,2664 +1516,2727 @@ static void neighbor_average(SculptSession *ss, float avg[3], unsigned vert)
* corner vertices. */
static float neighbor_average_mask(SculptSession *ss, unsigned vert)
{
- const float *vmask = ss->vmask;
- float avg = 0;
- int i, total = 0;
+ 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];
+ 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 (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];
+ 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);
+ /* 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;
+ /* Don't modify corner vertices */
+ if (vfcount > 1) {
+ BMIter liter;
+ BMLoop *l;
+ int i, total = 0;
- zero_v3(avg);
+ zero_v3(avg);
- BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- const BMVert *adj_v[2] = {l->prev->v, l->next->v};
+ 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++;
- }
- }
- }
+ 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;
- }
- }
+ if (total > 0) {
+ mul_v3_fl(avg, 1.0f / total);
+ return;
+ }
+ }
- copy_v3_v3(avg, v->co);
+ copy_v3_v3(avg, v->co);
}
/* For bmesh: average only the four most aligned (parallel and perpendicular) edges
* relative to a direction. Naturally converges to a quad-like tessellation. */
static void bmesh_four_neighbor_average(float avg[3], float direction[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 < 2) {
- copy_v3_v3(avg, v->co);
- return;
- }
-
- /* Project the direction to the vertex normal and create an additional
- * parallel vector. */
- float dir_a[3], dir_b[3];
- cross_v3_v3v3(dir_a, direction, v->no);
- cross_v3_v3v3(dir_b, dir_a, v->no);
-
- /* The four vectors which will be used for smoothing.
- * Occasionally less than 4 verts match the requirements in that case
- * use 'v' as fallback. */
- BMVert *pos_a = v;
- BMVert *neg_a = v;
- BMVert *pos_b = v;
- BMVert *neg_b = v;
-
- float pos_score_a = 0.0f;
- float neg_score_a = 0.0f;
- float pos_score_b = 0.0f;
- float neg_score_b = 0.0f;
-
- BMIter liter;
- BMLoop *l;
-
- BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) {
- BMVert *adj_v[2] = { l->prev->v, l->next->v };
-
- for (int i = 0; i < ARRAY_SIZE(adj_v); i++) {
- BMVert *v_other = adj_v[i];
-
- if (vfcount != 2 || BM_vert_face_count_at_most(v_other, 2) <= 2) {
- float vec[3];
- sub_v3_v3v3(vec, v_other->co, v->co);
- normalize_v3(vec);
-
- /* The score is a measure of how orthogonal the edge is. */
- float score = dot_v3v3(vec, dir_a);
-
- if (score >= pos_score_a) {
- pos_a = v_other;
- pos_score_a = score;
- }
- else if (score < neg_score_a) {
- neg_a = v_other;
- neg_score_a = score;
- }
- /* The same scoring but for the perpendicular direction. */
- score = dot_v3v3(vec, dir_b);
-
- if (score >= pos_score_b) {
- pos_b = v_other;
- pos_score_b = score;
- }
- else if (score < neg_score_b) {
- neg_b = v_other;
- neg_score_b = score;
- }
- }
- }
- }
-
- /* Average everything together. */
- zero_v3(avg);
- add_v3_v3(avg, pos_a->co);
- add_v3_v3(avg, neg_a->co);
- add_v3_v3(avg, pos_b->co);
- add_v3_v3(avg, neg_b->co);
- mul_v3_fl(avg, 0.25f);
-
- /* 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);
+ /* 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 < 2) {
+ copy_v3_v3(avg, v->co);
+ return;
+ }
+
+ /* Project the direction to the vertex normal and create an additional
+ * parallel vector. */
+ float dir_a[3], dir_b[3];
+ cross_v3_v3v3(dir_a, direction, v->no);
+ cross_v3_v3v3(dir_b, dir_a, v->no);
+
+ /* The four vectors which will be used for smoothing.
+ * Occasionally less than 4 verts match the requirements in that case
+ * use 'v' as fallback. */
+ BMVert *pos_a = v;
+ BMVert *neg_a = v;
+ BMVert *pos_b = v;
+ BMVert *neg_b = v;
+
+ float pos_score_a = 0.0f;
+ float neg_score_a = 0.0f;
+ float pos_score_b = 0.0f;
+ float neg_score_b = 0.0f;
+
+ BMIter liter;
+ BMLoop *l;
+
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ BMVert *adj_v[2] = {l->prev->v, l->next->v};
+
+ for (int i = 0; i < ARRAY_SIZE(adj_v); i++) {
+ BMVert *v_other = adj_v[i];
+
+ if (vfcount != 2 || BM_vert_face_count_at_most(v_other, 2) <= 2) {
+ float vec[3];
+ sub_v3_v3v3(vec, v_other->co, v->co);
+ normalize_v3(vec);
+
+ /* The score is a measure of how orthogonal the edge is. */
+ float score = dot_v3v3(vec, dir_a);
+
+ if (score >= pos_score_a) {
+ pos_a = v_other;
+ pos_score_a = score;
+ }
+ else if (score < neg_score_a) {
+ neg_a = v_other;
+ neg_score_a = score;
+ }
+ /* The same scoring but for the perpendicular direction. */
+ score = dot_v3v3(vec, dir_b);
+
+ if (score >= pos_score_b) {
+ pos_b = v_other;
+ pos_score_b = score;
+ }
+ else if (score < neg_score_b) {
+ neg_b = v_other;
+ neg_score_b = score;
+ }
+ }
+ }
+ }
+
+ /* Average everything together. */
+ zero_v3(avg);
+ add_v3_v3(avg, pos_a->co);
+ add_v3_v3(avg, neg_a->co);
+ add_v3_v3(avg, pos_b->co);
+ add_v3_v3(avg, neg_b->co);
+ mul_v3_fl(avg, 0.25f);
+
+ /* 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);
}
/* 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;
+ 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};
+ 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++;
- }
- }
+ 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);
- }
+ if (total > 0) {
+ return avg / (float)total;
+ }
+ else {
+ const float *vmask = BM_ELEM_CD_GET_VOID_P(v, cd_vert_mask_offset);
+ return (*vmask);
+ }
}
/* Note: uses after-struct allocated mem to store actual cache... */
typedef struct SculptDoBrushSmoothGridDataChunk {
- size_t tmpgrid_size;
+ size_t tmpgrid_size;
} SculptDoBrushSmoothGridDataChunk;
typedef struct {
- SculptSession *ss;
- const float *ray_start, *ray_normal;
- bool hit;
- float depth;
- bool original;
+ SculptSession *ss;
+ const float *ray_start, *ray_normal;
+ bool hit;
+ float depth;
+ bool original;
} SculptRaycastData;
typedef struct {
- const float *ray_start, *ray_normal;
- bool hit;
- float depth;
- float edge_length;
+ const float *ray_start, *ray_normal;
+ bool hit;
+ float depth;
+ float edge_length;
} SculptDetailRaycastData;
typedef struct {
- SculptSession *ss;
- const float *ray_start, *ray_normal;
- bool hit;
- float depth;
- float dist_sq_to_ray;
- bool original;
+ SculptSession *ss;
+ const float *ray_start, *ray_normal;
+ bool hit;
+ float depth;
+ float dist_sq_to_ray;
+ bool original;
} SculptFindNearestToRayData;
-static void do_smooth_brush_mesh_task_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__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), 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 ParallelRangeTLS *__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, 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 ParallelRangeTLS *__restrict tls)
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- Sculpt *sd = data->sd;
- const Brush *brush = data->brush;
-
- float direction[3];
- copy_v3_v3(direction, ss->cache->grab_delta_symmetry);
-
- float tmp[3];
- mul_v3_v3fl(
- tmp, ss->cache->sculpt_normal_symm,
- dot_v3v3(ss->cache->sculpt_normal_symm, direction));
- sub_v3_v3(direction, tmp);
-
- /* Cancel if there's no grab data. */
- if (is_zero_v3(direction)) {
- return;
- }
-
- float bstrength = data->strength;
- 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);
-
- 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, tls->thread_id) * ss->cache->pressure;
-
- float avg[3], val[3];
-
- 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);
-
- 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 ParallelRangeTLS *__restrict tls)
-{
- SculptThreadedTaskData *data = userdata;
- SculptDoBrushSmoothGridDataChunk *data_chunk = tls->userdata_chunk;
- 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;
-
- CCGElem **griddata, *gddata;
- CCGKey key;
-
- float (*tmpgrid_co)[3] = NULL;
- float tmprow_co[2][3];
- float *tmpgrid_mask = NULL;
- float tmprow_mask[2];
-
- BLI_bitmap * const *grid_hidden;
- int *grid_indices, totgrid, gridsize;
- int i, x, y;
-
- SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn =
- sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
-
- CLAMP(bstrength, 0.0f, 1.0f);
-
- BKE_pbvh_node_get_grids(ss->pbvh, data->nodes[n], &grid_indices, &totgrid, NULL, &gridsize, &griddata);
- BKE_pbvh_get_grid_key(ss->pbvh, &key);
-
- grid_hidden = BKE_pbvh_grid_hidden(ss->pbvh);
-
- if (smooth_mask)
- tmpgrid_mask = (void *)(data_chunk + 1);
- else
- tmpgrid_co = (void *)(data_chunk + 1);
-
- for (i = 0; i < totgrid; i++) {
- int gi = grid_indices[i];
- const BLI_bitmap *gh = grid_hidden[gi];
- gddata = griddata[gi];
-
- if (smooth_mask)
- memset(tmpgrid_mask, 0, data_chunk->tmpgrid_size);
- else
- memset(tmpgrid_co, 0, data_chunk->tmpgrid_size);
-
- for (y = 0; y < gridsize - 1; y++) {
- const int v = y * gridsize;
- if (smooth_mask) {
- tmprow_mask[0] = (*CCG_elem_offset_mask(&key, gddata, v) +
- *CCG_elem_offset_mask(&key, gddata, v + gridsize));
- }
- else {
- add_v3_v3v3(tmprow_co[0],
- CCG_elem_offset_co(&key, gddata, v),
- CCG_elem_offset_co(&key, gddata, v + gridsize));
- }
-
- for (x = 0; x < gridsize - 1; x++) {
- const int v1 = x + y * gridsize;
- const int v2 = v1 + 1;
- const int v3 = v1 + gridsize;
- const int v4 = v3 + 1;
-
- if (smooth_mask) {
- float tmp;
-
- tmprow_mask[(x + 1) % 2] = (*CCG_elem_offset_mask(&key, gddata, v2) +
- *CCG_elem_offset_mask(&key, gddata, v4));
- tmp = tmprow_mask[(x + 1) % 2] + tmprow_mask[x % 2];
-
- tmpgrid_mask[v1] += tmp;
- tmpgrid_mask[v2] += tmp;
- tmpgrid_mask[v3] += tmp;
- tmpgrid_mask[v4] += tmp;
- }
- else {
- float tmp[3];
-
- add_v3_v3v3(tmprow_co[(x + 1) % 2],
- CCG_elem_offset_co(&key, gddata, v2),
- CCG_elem_offset_co(&key, gddata, v4));
- add_v3_v3v3(tmp, tmprow_co[(x + 1) % 2], tmprow_co[x % 2]);
-
- add_v3_v3(tmpgrid_co[v1], tmp);
- add_v3_v3(tmpgrid_co[v2], tmp);
- add_v3_v3(tmpgrid_co[v3], tmp);
- add_v3_v3(tmpgrid_co[v4], tmp);
- }
- }
- }
-
- /* blend with existing coordinates */
- for (y = 0; y < gridsize; y++) {
- for (x = 0; x < gridsize; x++) {
- float *co;
- const float *fno;
- float *mask;
- const int index = y * gridsize + x;
-
- if (gh) {
- if (BLI_BITMAP_TEST(gh, index))
- continue;
- }
-
- co = CCG_elem_offset_co(&key, gddata, index);
- fno = CCG_elem_offset_no(&key, gddata, index);
- mask = CCG_elem_offset_mask(&key, gddata, index);
-
- if (sculpt_brush_test_sq_fn(&test, co)) {
- const float strength_mask = (smooth_mask ? 0.0f : *mask);
- const float fade = bstrength * tex_strength(
- ss, brush, co, sqrtf(test.dist),
- NULL, fno, strength_mask, tls->thread_id);
- float f = 1.0f / 16.0f;
-
- if (x == 0 || x == gridsize - 1)
- f *= 2.0f;
-
- if (y == 0 || y == gridsize - 1)
- f *= 2.0f;
-
- if (smooth_mask) {
- *mask += ((tmpgrid_mask[index] * f) - *mask) * fade;
- }
- else {
- float *avg = tmpgrid_co[index];
- float val[3];
-
- mul_v3_fl(avg, f);
- sub_v3_v3v3(val, avg, co);
- madd_v3_v3v3fl(val, co, val, fade);
-
- sculpt_clip(sd, ss, co, val);
- }
- }
- }
- }
- }
-}
-
-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,
- };
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
-
- switch (type) {
- case PBVH_GRIDS:
- {
- int gridsize;
- size_t size;
- SculptDoBrushSmoothGridDataChunk *data_chunk;
-
- BKE_pbvh_node_get_grids(ss->pbvh, NULL, NULL, NULL, NULL, &gridsize, NULL);
- size = (size_t)gridsize;
- size = sizeof(float) * size * size * (smooth_mask ? 1 : 3);
- data_chunk = MEM_mallocN(sizeof(*data_chunk) + size, __func__);
- data_chunk->tmpgrid_size = size;
- size += sizeof(*data_chunk);
-
- settings.userdata_chunk = data_chunk;
- settings.userdata_chunk_size = size;
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_smooth_brush_multires_task_cb_ex,
- &settings);
-
- MEM_freeN(data_chunk);
- 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;
- }
-
- if (ss->multires)
- multires_stitch_grids(ob);
- }
+static void do_smooth_brush_mesh_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__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),
+ 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 ParallelRangeTLS *__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,
+ 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 ParallelRangeTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ Sculpt *sd = data->sd;
+ const Brush *brush = data->brush;
+
+ float direction[3];
+ copy_v3_v3(direction, ss->cache->grab_delta_symmetry);
+
+ float tmp[3];
+ mul_v3_v3fl(
+ tmp, ss->cache->sculpt_normal_symm, dot_v3v3(ss->cache->sculpt_normal_symm, direction));
+ sub_v3_v3(direction, tmp);
+
+ /* Cancel if there's no grab data. */
+ if (is_zero_v3(direction)) {
+ return;
+ }
+
+ float bstrength = data->strength;
+ 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);
+
+ 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, tls->thread_id) *
+ ss->cache->pressure;
+
+ float avg[3], val[3];
+
+ 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);
+
+ 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 ParallelRangeTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptDoBrushSmoothGridDataChunk *data_chunk = tls->userdata_chunk;
+ 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;
+
+ CCGElem **griddata, *gddata;
+ CCGKey key;
+
+ float(*tmpgrid_co)[3] = NULL;
+ float tmprow_co[2][3];
+ float *tmpgrid_mask = NULL;
+ float tmprow_mask[2];
+
+ BLI_bitmap *const *grid_hidden;
+ int *grid_indices, totgrid, gridsize;
+ int i, x, y;
+
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ ss, &test, data->brush->falloff_shape);
+
+ CLAMP(bstrength, 0.0f, 1.0f);
+
+ BKE_pbvh_node_get_grids(
+ ss->pbvh, data->nodes[n], &grid_indices, &totgrid, NULL, &gridsize, &griddata);
+ BKE_pbvh_get_grid_key(ss->pbvh, &key);
+
+ grid_hidden = BKE_pbvh_grid_hidden(ss->pbvh);
+
+ if (smooth_mask)
+ tmpgrid_mask = (void *)(data_chunk + 1);
+ else
+ tmpgrid_co = (void *)(data_chunk + 1);
+
+ for (i = 0; i < totgrid; i++) {
+ int gi = grid_indices[i];
+ const BLI_bitmap *gh = grid_hidden[gi];
+ gddata = griddata[gi];
+
+ if (smooth_mask)
+ memset(tmpgrid_mask, 0, data_chunk->tmpgrid_size);
+ else
+ memset(tmpgrid_co, 0, data_chunk->tmpgrid_size);
+
+ for (y = 0; y < gridsize - 1; y++) {
+ const int v = y * gridsize;
+ if (smooth_mask) {
+ tmprow_mask[0] = (*CCG_elem_offset_mask(&key, gddata, v) +
+ *CCG_elem_offset_mask(&key, gddata, v + gridsize));
+ }
+ else {
+ add_v3_v3v3(tmprow_co[0],
+ CCG_elem_offset_co(&key, gddata, v),
+ CCG_elem_offset_co(&key, gddata, v + gridsize));
+ }
+
+ for (x = 0; x < gridsize - 1; x++) {
+ const int v1 = x + y * gridsize;
+ const int v2 = v1 + 1;
+ const int v3 = v1 + gridsize;
+ const int v4 = v3 + 1;
+
+ if (smooth_mask) {
+ float tmp;
+
+ tmprow_mask[(x + 1) % 2] = (*CCG_elem_offset_mask(&key, gddata, v2) +
+ *CCG_elem_offset_mask(&key, gddata, v4));
+ tmp = tmprow_mask[(x + 1) % 2] + tmprow_mask[x % 2];
+
+ tmpgrid_mask[v1] += tmp;
+ tmpgrid_mask[v2] += tmp;
+ tmpgrid_mask[v3] += tmp;
+ tmpgrid_mask[v4] += tmp;
+ }
+ else {
+ float tmp[3];
+
+ add_v3_v3v3(tmprow_co[(x + 1) % 2],
+ CCG_elem_offset_co(&key, gddata, v2),
+ CCG_elem_offset_co(&key, gddata, v4));
+ add_v3_v3v3(tmp, tmprow_co[(x + 1) % 2], tmprow_co[x % 2]);
+
+ add_v3_v3(tmpgrid_co[v1], tmp);
+ add_v3_v3(tmpgrid_co[v2], tmp);
+ add_v3_v3(tmpgrid_co[v3], tmp);
+ add_v3_v3(tmpgrid_co[v4], tmp);
+ }
+ }
+ }
+
+ /* blend with existing coordinates */
+ for (y = 0; y < gridsize; y++) {
+ for (x = 0; x < gridsize; x++) {
+ float *co;
+ const float *fno;
+ float *mask;
+ const int index = y * gridsize + x;
+
+ if (gh) {
+ if (BLI_BITMAP_TEST(gh, index))
+ continue;
+ }
+
+ co = CCG_elem_offset_co(&key, gddata, index);
+ fno = CCG_elem_offset_no(&key, gddata, index);
+ mask = CCG_elem_offset_mask(&key, gddata, index);
+
+ if (sculpt_brush_test_sq_fn(&test, co)) {
+ const float strength_mask = (smooth_mask ? 0.0f : *mask);
+ const float fade =
+ bstrength *
+ tex_strength(
+ ss, brush, co, sqrtf(test.dist), NULL, fno, strength_mask, tls->thread_id);
+ float f = 1.0f / 16.0f;
+
+ if (x == 0 || x == gridsize - 1)
+ f *= 2.0f;
+
+ if (y == 0 || y == gridsize - 1)
+ f *= 2.0f;
+
+ if (smooth_mask) {
+ *mask += ((tmpgrid_mask[index] * f) - *mask) * fade;
+ }
+ else {
+ float *avg = tmpgrid_co[index];
+ float val[3];
+
+ mul_v3_fl(avg, f);
+ sub_v3_v3v3(val, avg, co);
+ madd_v3_v3v3fl(val, co, val, fade);
+
+ sculpt_clip(sd, ss, co, val);
+ }
+ }
+ }
+ }
+ }
+}
+
+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,
+ };
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+
+ switch (type) {
+ case PBVH_GRIDS: {
+ int gridsize;
+ size_t size;
+ SculptDoBrushSmoothGridDataChunk *data_chunk;
+
+ BKE_pbvh_node_get_grids(ss->pbvh, NULL, NULL, NULL, NULL, &gridsize, NULL);
+ size = (size_t)gridsize;
+ size = sizeof(float) * size * size * (smooth_mask ? 1 : 3);
+ data_chunk = MEM_mallocN(sizeof(*data_chunk) + size, __func__);
+ data_chunk->tmpgrid_size = size;
+ size += sizeof(*data_chunk);
+
+ settings.userdata_chunk = data_chunk;
+ settings.userdata_chunk_size = size;
+ BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_multires_task_cb_ex, &settings);
+
+ MEM_freeN(data_chunk);
+ 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;
+ }
+
+ if (ss->multires)
+ multires_stitch_grids(ob);
+ }
}
static void bmesh_topology_rake(
- Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, float bstrength)
+ Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, float bstrength)
{
- Brush *brush = BKE_paint_brush(&sd->paint);
- CLAMP(bstrength, 0.0f, 1.0f);
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ CLAMP(bstrength, 0.0f, 1.0f);
- /* Interactions increase both strength and quality. */
- const int iterations = 3;
+ /* Interactions increase both strength and quality. */
+ const int iterations = 3;
- int iteration;
- const int count = iterations * bstrength + 1;
- const float factor = iterations * bstrength / count;
+ int iteration;
+ const int count = iterations * bstrength + 1;
+ const float factor = iterations * bstrength / count;
- for (iteration = 0; iteration <= count; ++iteration) {
+ for (iteration = 0; iteration <= count; ++iteration) {
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- .strength = factor,
- };
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .strength = factor,
+ };
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_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);
+ 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 ParallelRangeTLS *__restrict tls)
+static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict tls)
{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const Brush *brush = data->brush;
- const float bstrength = ss->cache->bstrength;
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ const float bstrength = ss->cache->bstrength;
- PBVHVertexIter vd;
+ PBVHVertexIter vd;
- SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn =
- sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
+ 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 = tex_strength(
- ss, brush, vd.co, sqrtf(test.dist),
- vd.no, vd.fno, 0.0f, tls->thread_id);
+ 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, tls->thread_id);
- (*vd.mask) += fade * bstrength;
- CLAMP(*vd.mask, 0, 1);
+ (*vd.mask) += fade * bstrength;
+ CLAMP(*vd.mask, 0, 1);
- if (vd.mvert)
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- BKE_pbvh_vertex_iter_end;
- }
+ if (vd.mvert)
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ BKE_pbvh_vertex_iter_end;
+ }
}
static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
- Brush *brush = BKE_paint_brush(&sd->paint);
+ Brush *brush = BKE_paint_brush(&sd->paint);
- /* threaded loop over nodes */
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- };
+ /* threaded loop over nodes */
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ };
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_mask_brush_draw_task_cb_ex,
- &settings);
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ 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)
{
- SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
- switch ((BrushMaskTool)brush->mask_tool) {
- case BRUSH_MASK_DRAW:
- do_mask_brush_draw(sd, ob, nodes, totnode);
- break;
- case BRUSH_MASK_SMOOTH:
- smooth(sd, ob, nodes, totnode, ss->cache->bstrength, true);
- break;
- }
+ switch ((BrushMaskTool)brush->mask_tool) {
+ case BRUSH_MASK_DRAW:
+ do_mask_brush_draw(sd, ob, nodes, totnode);
+ break;
+ case BRUSH_MASK_SMOOTH:
+ smooth(sd, ob, nodes, totnode, ss->cache->bstrength, true);
+ break;
+ }
}
-static void do_draw_brush_task_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict tls)
+static void do_draw_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict tls)
{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const Brush *brush = data->brush;
- const float *offset = data->offset;
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ const float *offset = data->offset;
- PBVHVertexIter vd;
- float (*proxy)[3];
+ PBVHVertexIter vd;
+ float(*proxy)[3];
- proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
+ 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);
+ 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)) {
- /* offset vertex */
- const float fade = tex_strength(
- ss, brush, vd.co, sqrtf(test.dist),
- vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, tls->thread_id);
+ 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,
+ tls->thread_id);
- mul_v3_v3fl(proxy[vd.i], offset, fade);
+ mul_v3_v3fl(proxy[vd.i], offset, fade);
- if (vd.mvert)
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- BKE_pbvh_vertex_iter_end;
+ if (vd.mvert)
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
- SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
- float offset[3];
- const float bstrength = ss->cache->bstrength;
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ float offset[3];
+ const float bstrength = ss->cache->bstrength;
- /* 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);
+ /* 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 */
- curvemapping_initialize(brush->curve);
+ /* XXX - this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise
+ * initialize before threads so they can do curve mapping */
+ curvemapping_initialize(brush->curve);
- /* threaded loop over nodes */
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- .offset = offset,
- };
+ /* threaded loop over nodes */
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .offset = offset,
+ };
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_draw_brush_task_cb_ex,
- &settings);
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ BLI_task_parallel_range(0, totnode, &data, do_draw_brush_task_cb_ex, &settings);
}
/**
* Used for 'SCULPT_TOOL_CREASE' and 'SCULPT_TOOL_BLOB'
*/
-static void do_crease_brush_task_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict tls)
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const Brush *brush = data->brush;
- SculptProjectVector *spvc = data->spvc;
- const float flippedbstrength = data->flippedbstrength;
- const float *offset = data->offset;
-
- PBVHVertexIter vd;
- float (*proxy)[3];
-
- 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);
-
- 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, tls->thread_id);
- float val1[3];
- float val2[3];
-
- /* 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);
- }
-
- mul_v3_fl(val1, fade * flippedbstrength);
-
- sculpt_project_v3(spvc, val1, val1);
-
- /* then we draw */
- mul_v3_v3fl(val2, offset, fade);
-
- add_v3_v3v3(proxy[vd.i], val1, val2);
-
- if (vd.mvert)
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- BKE_pbvh_vertex_iter_end;
+static void do_crease_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ SculptProjectVector *spvc = data->spvc;
+ const float flippedbstrength = data->flippedbstrength;
+ const float *offset = data->offset;
+
+ PBVHVertexIter vd;
+ float(*proxy)[3];
+
+ 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);
+
+ 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,
+ tls->thread_id);
+ float val1[3];
+ float val2[3];
+
+ /* 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);
+ }
+
+ mul_v3_fl(val1, fade * flippedbstrength);
+
+ sculpt_project_v3(spvc, val1, val1);
+
+ /* then we draw */
+ mul_v3_v3fl(val2, offset, fade);
+
+ add_v3_v3v3(proxy[vd.i], val1, val2);
+
+ if (vd.mvert)
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
- SculptSession *ss = ob->sculpt;
- const Scene *scene = ss->cache->vc->scene;
- Brush *brush = BKE_paint_brush(&sd->paint);
- float offset[3];
- float bstrength = ss->cache->bstrength;
- float flippedbstrength, crease_correction;
- float brush_alpha;
-
- SculptProjectVector spvc;
-
- /* 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);
-
- /* we divide out the squared alpha and multiply by the squared crease to give us the pinch strength */
- crease_correction = brush->crease_pinch_factor * brush->crease_pinch_factor;
- brush_alpha = BKE_brush_alpha_get(scene, brush);
- if (brush_alpha > 0.0f)
- 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;
-
- 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 */
- sculpt_project_v3_cache_init(&spvc, ss->cache->sculpt_normal_symm);
-
- /* threaded loop over nodes */
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- .spvc = &spvc, .offset = offset, .flippedbstrength = flippedbstrength,
- };
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- 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,
- const int n,
- const ParallelRangeTLS *__restrict tls)
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const Brush *brush = data->brush;
-
- PBVHVertexIter vd;
- float (*proxy)[3];
- const float 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);
-
- 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, tls->thread_id);
- float val[3];
-
- 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);
- }
- mul_v3_v3fl(proxy[vd.i], val, fade);
-
- if (vd.mvert)
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- BKE_pbvh_vertex_iter_end;
+ SculptSession *ss = ob->sculpt;
+ const Scene *scene = ss->cache->vc->scene;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ float offset[3];
+ float bstrength = ss->cache->bstrength;
+ float flippedbstrength, crease_correction;
+ float brush_alpha;
+
+ SculptProjectVector spvc;
+
+ /* 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);
+
+ /* we divide out the squared alpha and multiply by the squared crease to give us the pinch strength */
+ crease_correction = brush->crease_pinch_factor * brush->crease_pinch_factor;
+ brush_alpha = BKE_brush_alpha_get(scene, brush);
+ if (brush_alpha > 0.0f)
+ 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;
+
+ 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 */
+ sculpt_project_v3_cache_init(&spvc, ss->cache->sculpt_normal_symm);
+
+ /* threaded loop over nodes */
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .spvc = &spvc,
+ .offset = offset,
+ .flippedbstrength = flippedbstrength,
+ };
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ 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,
+ const int n,
+ const ParallelRangeTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+
+ PBVHVertexIter vd;
+ float(*proxy)[3];
+ const float 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);
+
+ 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,
+ tls->thread_id);
+ float val[3];
+
+ 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);
+ }
+ mul_v3_v3fl(proxy[vd.i], val, fade);
+
+ if (vd.mvert)
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
- Brush *brush = BKE_paint_brush(&sd->paint);
+ Brush *brush = BKE_paint_brush(&sd->paint);
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- };
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ };
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_pinch_brush_task_cb_ex,
- &settings);
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ 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,
- const int n,
- const ParallelRangeTLS *__restrict tls)
+static void do_grab_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict tls)
{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const Brush *brush = data->brush;
- const float *grab_delta = data->grab_delta;
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ const float *grab_delta = data->grab_delta;
- PBVHVertexIter vd;
- SculptOrigVertData orig_data;
- float (*proxy)[3];
- const float bstrength = ss->cache->bstrength;
+ PBVHVertexIter vd;
+ SculptOrigVertData orig_data;
+ 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;
+ 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);
+ 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)
- {
- sculpt_orig_vert_data_update(&orig_data, &vd);
+ 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, 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, tls->thread_id);
+ 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,
+ tls->thread_id);
- mul_v3_v3fl(proxy[vd.i], grab_delta, fade);
+ mul_v3_v3fl(proxy[vd.i], grab_delta, fade);
- if (vd.mvert)
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- BKE_pbvh_vertex_iter_end;
+ if (vd.mvert)
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
- SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
- float grab_delta[3];
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ float grab_delta[3];
- copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry);
+ copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry);
- if (ss->cache->normal_weight > 0.0f) {
- sculpt_project_v3_normal_align(ss, ss->cache->normal_weight, grab_delta);
- }
+ if (ss->cache->normal_weight > 0.0f) {
+ sculpt_project_v3_normal_align(ss, ss->cache->normal_weight, grab_delta);
+ }
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- .grab_delta = grab_delta,
- };
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .grab_delta = grab_delta,
+ };
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_grab_brush_task_cb_ex,
- &settings);
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ BLI_task_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings);
}
-static void do_nudge_brush_task_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict tls)
+static void do_nudge_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict tls)
{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const Brush *brush = data->brush;
- const float *cono = data->cono;
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ const float *cono = data->cono;
- PBVHVertexIter vd;
- float (*proxy)[3];
- const float bstrength = ss->cache->bstrength;
+ PBVHVertexIter vd;
+ float(*proxy)[3];
+ const float bstrength = ss->cache->bstrength;
- proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
+ 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);
+ 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, vd.mask ? *vd.mask : 0.0f, tls->thread_id);
+ 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,
+ tls->thread_id);
- mul_v3_v3fl(proxy[vd.i], cono, fade);
+ mul_v3_v3fl(proxy[vd.i], cono, fade);
- if (vd.mvert)
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- BKE_pbvh_vertex_iter_end;
+ if (vd.mvert)
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
static void do_nudge_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 tmp[3], cono[3];
-
- copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry);
-
- cross_v3_v3v3(tmp, ss->cache->sculpt_normal_symm, grab_delta);
- cross_v3_v3v3(cono, tmp, ss->cache->sculpt_normal_symm);
-
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- .cono = cono,
- };
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- 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,
- const int n,
- const ParallelRangeTLS *__restrict tls)
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const Brush *brush = data->brush;
- SculptProjectVector *spvc = data->spvc;
- const float *grab_delta = data->grab_delta;
-
- PBVHVertexIter vd;
- float (*proxy)[3];
- const float bstrength = ss->cache->bstrength;
- const bool do_rake_rotation = ss->cache->is_rake_rotation_valid;
- const bool do_pinch = (brush->crease_pinch_factor != 0.5f);
- const float pinch = do_pinch ?
- (2.0f * (0.5f - brush->crease_pinch_factor) * (len_v3(grab_delta) / ss->cache->radius)) : 0.0f;
-
- 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);
-
- 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, tls->thread_id);
-
- mul_v3_v3fl(proxy[vd.i], grab_delta, fade);
-
- /* negative pinch will inflate, helps maintain volume */
- if (do_pinch) {
- float delta_pinch_init[3], delta_pinch[3];
-
- sub_v3_v3v3(delta_pinch, vd.co, test.location);
- if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
- project_plane_v3_v3v3(delta_pinch, delta_pinch, ss->cache->true_view_normal);
- }
-
- /* important to calculate based on the grabbed location
- * (intentionally ignore fade here). */
- add_v3_v3(delta_pinch, grab_delta);
-
- sculpt_project_v3(spvc, delta_pinch, delta_pinch);
-
- 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 */
- if (pinch > 0.0f) {
- /* 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);
- sub_v3_v3v3(delta_pinch, delta_pinch_init, delta_pinch);
- add_v3_v3(proxy[vd.i], delta_pinch);
- }
-
- if (do_rake_rotation) {
- float delta_rotate[3];
- sculpt_rake_rotate(ss, test.location, vd.co, fade, delta_rotate);
- add_v3_v3(proxy[vd.i], delta_rotate);
- }
-
- if (vd.mvert)
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- BKE_pbvh_vertex_iter_end;
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ float grab_delta[3];
+ float tmp[3], cono[3];
+
+ copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry);
+
+ cross_v3_v3v3(tmp, ss->cache->sculpt_normal_symm, grab_delta);
+ cross_v3_v3v3(cono, tmp, ss->cache->sculpt_normal_symm);
+
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .cono = cono,
+ };
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ 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,
+ const int n,
+ const ParallelRangeTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ SculptProjectVector *spvc = data->spvc;
+ const float *grab_delta = data->grab_delta;
+
+ PBVHVertexIter vd;
+ float(*proxy)[3];
+ const float bstrength = ss->cache->bstrength;
+ const bool do_rake_rotation = ss->cache->is_rake_rotation_valid;
+ const bool do_pinch = (brush->crease_pinch_factor != 0.5f);
+ const float pinch = do_pinch ? (2.0f * (0.5f - brush->crease_pinch_factor) *
+ (len_v3(grab_delta) / ss->cache->radius)) :
+ 0.0f;
+
+ 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);
+
+ 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,
+ tls->thread_id);
+
+ mul_v3_v3fl(proxy[vd.i], grab_delta, fade);
+
+ /* negative pinch will inflate, helps maintain volume */
+ if (do_pinch) {
+ float delta_pinch_init[3], delta_pinch[3];
+
+ sub_v3_v3v3(delta_pinch, vd.co, test.location);
+ if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
+ project_plane_v3_v3v3(delta_pinch, delta_pinch, ss->cache->true_view_normal);
+ }
+
+ /* important to calculate based on the grabbed location
+ * (intentionally ignore fade here). */
+ add_v3_v3(delta_pinch, grab_delta);
+
+ sculpt_project_v3(spvc, delta_pinch, delta_pinch);
+
+ 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 */
+ if (pinch > 0.0f) {
+ /* 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);
+ sub_v3_v3v3(delta_pinch, delta_pinch_init, delta_pinch);
+ add_v3_v3(proxy[vd.i], delta_pinch);
+ }
+
+ if (do_rake_rotation) {
+ float delta_rotate[3];
+ sculpt_rake_rotate(ss, test.location, vd.co, fade, delta_rotate);
+ add_v3_v3(proxy[vd.i], delta_rotate);
+ }
+
+ if (vd.mvert)
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
- SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
- const float bstrength = ss->cache->bstrength;
- float grab_delta[3];
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ const float bstrength = ss->cache->bstrength;
+ float grab_delta[3];
- SculptProjectVector spvc;
+ SculptProjectVector spvc;
- copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry);
+ copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry);
- if (bstrength < 0)
- negate_v3(grab_delta);
+ if (bstrength < 0)
+ negate_v3(grab_delta);
- if (ss->cache->normal_weight > 0.0f) {
- sculpt_project_v3_normal_align(ss, ss->cache->normal_weight, grab_delta);
- }
+ if (ss->cache->normal_weight > 0.0f) {
+ sculpt_project_v3_normal_align(ss, ss->cache->normal_weight, grab_delta);
+ }
- /* optionally pinch while painting */
- if (brush->crease_pinch_factor != 0.5f) {
- sculpt_project_v3_cache_init(&spvc, grab_delta);
- }
+ /* optionally pinch while painting */
+ if (brush->crease_pinch_factor != 0.5f) {
+ sculpt_project_v3_cache_init(&spvc, grab_delta);
+ }
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- .spvc = &spvc, .grab_delta = grab_delta,
- };
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .spvc = &spvc,
+ .grab_delta = grab_delta,
+ };
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_snake_hook_brush_task_cb_ex,
- &settings);
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ 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,
- const int n,
- const ParallelRangeTLS *__restrict tls)
+static void do_thumb_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict tls)
{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const Brush *brush = data->brush;
- const float *cono = data->cono;
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ const float *cono = data->cono;
- PBVHVertexIter vd;
- SculptOrigVertData orig_data;
- float (*proxy)[3];
- const float bstrength = ss->cache->bstrength;
+ PBVHVertexIter vd;
+ SculptOrigVertData orig_data;
+ 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;
+ 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);
+ 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)
- {
- sculpt_orig_vert_data_update(&orig_data, &vd);
+ 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, 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, tls->thread_id);
+ 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,
+ tls->thread_id);
- mul_v3_v3fl(proxy[vd.i], cono, fade);
+ mul_v3_v3fl(proxy[vd.i], cono, fade);
- if (vd.mvert)
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- BKE_pbvh_vertex_iter_end;
+ if (vd.mvert)
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
static void do_thumb_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 tmp[3], cono[3];
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ float grab_delta[3];
+ float tmp[3], cono[3];
- copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry);
+ copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry);
- cross_v3_v3v3(tmp, ss->cache->sculpt_normal_symm, grab_delta);
- cross_v3_v3v3(cono, tmp, ss->cache->sculpt_normal_symm);
+ cross_v3_v3v3(tmp, ss->cache->sculpt_normal_symm, grab_delta);
+ cross_v3_v3v3(cono, tmp, ss->cache->sculpt_normal_symm);
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- .cono = cono,
- };
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .cono = cono,
+ };
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_thumb_brush_task_cb_ex,
- &settings);
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ 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,
- const int n,
- const ParallelRangeTLS *__restrict tls)
+static void do_rotate_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict tls)
{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const Brush *brush = data->brush;
- const float angle = data->angle;
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ const float angle = data->angle;
- PBVHVertexIter vd;
- SculptOrigVertData orig_data;
- float (*proxy)[3];
- const float bstrength = ss->cache->bstrength;
+ PBVHVertexIter vd;
+ SculptOrigVertData orig_data;
+ 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;
+ 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);
+ 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)
- {
- sculpt_orig_vert_data_update(&orig_data, &vd);
+ 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, 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, tls->thread_id);
+ 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,
+ tls->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);
- mul_v3_m3v3(proxy[vd.i], rot, vec);
- add_v3_v3(proxy[vd.i], ss->cache->location);
- sub_v3_v3(proxy[vd.i], orig_data.co);
+ sub_v3_v3v3(vec, orig_data.co, ss->cache->location);
+ axis_angle_normalized_to_mat3(rot, ss->cache->sculpt_normal_symm, angle * fade);
+ mul_v3_m3v3(proxy[vd.i], rot, vec);
+ add_v3_v3(proxy[vd.i], ss->cache->location);
+ sub_v3_v3(proxy[vd.i], orig_data.co);
- if (vd.mvert)
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- BKE_pbvh_vertex_iter_end;
+ if (vd.mvert)
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
- SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
-
- static const int flip[8] = { 1, -1, -1, 1, -1, 1, 1, -1 };
- const float angle = ss->cache->vertex_rotation * flip[ss->cache->mirror_symmetry_pass];
-
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- .angle = angle,
- };
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_rotate_brush_task_cb_ex,
- &settings);
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ static const int flip[8] = {1, -1, -1, 1, -1, 1, 1, -1};
+ const float angle = ss->cache->vertex_rotation * flip[ss->cache->mirror_symmetry_pass];
+
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .angle = angle,
+ };
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ 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,
+ const int n,
+ const ParallelRangeTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ Sculpt *sd = data->sd;
+ const Brush *brush = data->brush;
+ const float *offset = data->offset;
+
+ 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);
+
+ 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)
+ {
+ 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,
+ tls->thread_id);
+ float *disp = &layer_disp[vd.i];
+ float val[3];
+
+ *disp += fade;
+
+ /* Don't let the displacement go past the limit */
+ if ((lim < 0.0f && *disp < lim) || (lim >= 0.0f && *disp > lim))
+ *disp = lim;
+
+ mul_v3_v3fl(val, offset, *disp);
+
+ if (!ss->multires && !ss->bm && ss->layer_co && (brush->flag & BRUSH_PERSISTENT)) {
+ int index = vd.vert_indices[vd.i];
+
+ /* persistent base */
+ add_v3_v3(val, ss->layer_co[index]);
+ }
+ else {
+ add_v3_v3(val, orig_data.co);
+ }
+
+ 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_layer_brush_task_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict tls)
+static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- Sculpt *sd = data->sd;
- const Brush *brush = data->brush;
- const float *offset = data->offset;
-
- 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; */
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ float offset[3];
- sculpt_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ mul_v3_v3v3(offset, ss->cache->scale, ss->cache->sculpt_normal_symm);
- /* 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);
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .offset = offset,
+ };
+ BLI_mutex_init(&data.mutex);
- SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn =
- sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ BLI_task_parallel_range(0, totnode, &data, do_layer_brush_task_cb_ex, &settings);
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- sculpt_orig_vert_data_update(&orig_data, &vd);
+ BLI_mutex_end(&data.mutex);
+}
- 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, tls->thread_id);
- float *disp = &layer_disp[vd.i];
- float val[3];
+static void do_inflate_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
- *disp += fade;
+ PBVHVertexIter vd;
+ float(*proxy)[3];
+ const float bstrength = ss->cache->bstrength;
- /* Don't let the displacement go past the limit */
- if ((lim < 0.0f && *disp < lim) || (lim >= 0.0f && *disp > lim))
- *disp = lim;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
- mul_v3_v3fl(val, offset, *disp);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ ss, &test, data->brush->falloff_shape);
- if (!ss->multires && !ss->bm && ss->layer_co && (brush->flag & BRUSH_PERSISTENT)) {
- int index = vd.vert_indices[vd.i];
+ 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,
+ tls->thread_id);
+ float val[3];
- /* persistent base */
- add_v3_v3(val, ss->layer_co[index]);
- }
- else {
- add_v3_v3(val, orig_data.co);
- }
+ if (vd.fno)
+ copy_v3_v3(val, vd.fno);
+ else
+ normal_short_to_float_v3(val, vd.no);
- sculpt_clip(sd, ss, vd.co, val);
+ mul_v3_fl(val, fade * ss->cache->radius);
+ mul_v3_v3v3(proxy[vd.i], val, ss->cache->scale);
- if (vd.mvert)
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- BKE_pbvh_vertex_iter_end;
+ if (vd.mvert)
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
-static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+static void do_inflate_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);
-
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- .offset = offset,
- };
- BLI_mutex_init(&data.mutex);
+ Brush *brush = BKE_paint_brush(&sd->paint);
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_layer_brush_task_cb_ex,
- &settings);
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ };
- BLI_mutex_end(&data.mutex);
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ BLI_task_parallel_range(0, totnode, &data, do_inflate_brush_task_cb_ex, &settings);
}
-static void do_inflate_brush_task_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict tls)
+static void calc_sculpt_plane(
+ Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3], float r_area_co[3])
{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const Brush *brush = data->brush;
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
- PBVHVertexIter vd;
- float (*proxy)[3];
- const float bstrength = ss->cache->bstrength;
+ 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_NORMAL))) {
+ switch (brush->sculpt_plane) {
+ case SCULPT_DISP_DIR_VIEW:
+ copy_v3_v3(r_area_no, ss->cache->true_view_normal);
+ break;
- proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
+ case SCULPT_DISP_DIR_X:
+ ARRAY_SET_ITEMS(r_area_no, 1, 0, 0);
+ break;
- SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn =
- sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
+ case SCULPT_DISP_DIR_Y:
+ ARRAY_SET_ITEMS(r_area_no, 0, 1, 0);
+ break;
- 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, tls->thread_id);
- float val[3];
+ case SCULPT_DISP_DIR_Z:
+ ARRAY_SET_ITEMS(r_area_no, 0, 0, 1);
+ break;
- if (vd.fno)
- copy_v3_v3(val, vd.fno);
- else
- normal_short_to_float_v3(val, vd.no);
+ 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;
- mul_v3_fl(val, fade * ss->cache->radius);
- mul_v3_v3v3(proxy[vd.i], val, ss->cache->scale);
+ default:
+ break;
+ }
- if (vd.mvert)
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- BKE_pbvh_vertex_iter_end;
-}
+ /* 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);
-static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
-{
- Brush *brush = BKE_paint_brush(&sd->paint);
+ /* for area normal */
+ copy_v3_v3(ss->cache->sculpt_normal, r_area_no);
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- };
+ /* for flatten center */
+ copy_v3_v3(ss->cache->last_center, r_area_co);
+ }
+ else {
+ /* for area normal */
+ copy_v3_v3(r_area_no, ss->cache->sculpt_normal);
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_inflate_brush_task_cb_ex,
- &settings);
-}
+ /* for flatten center */
+ copy_v3_v3(r_area_co, ss->cache->last_center);
-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_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 */
- copy_v3_v3(ss->cache->sculpt_normal, r_area_no);
-
- /* for flatten center */
- 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);
- }
+ /* 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);
+ }
}
static int 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)));
+ return (!(brush->flag & BRUSH_PLANE_TRIM) ||
+ ((dot_v3v3(val, val) <= cache->radius_squared * cache->plane_trim_squared)));
}
-static bool plane_point_side_flip(
- const float co[3], const float plane[4],
- const bool flip)
+static bool plane_point_side_flip(const float co[3], const float plane[4], const bool flip)
{
- float d = plane_point_side_v3(plane, co);
- if (flip) d = -d;
- return d <= 0.0f;
+ float d = plane_point_side_v3(plane, co);
+ if (flip)
+ d = -d;
+ return d <= 0.0f;
}
static int plane_point_side(const float co[3], const float plane[4])
{
- float d = plane_point_side_v3(plane, co);
- return d <= 0.0f;
+ float d = plane_point_side_v3(plane, co);
+ return d <= 0.0f;
}
static float get_offset(Sculpt *sd, SculptSession *ss)
{
- Brush *brush = BKE_paint_brush(&sd->paint);
+ Brush *brush = BKE_paint_brush(&sd->paint);
- float rv = brush->plane_offset;
+ float rv = brush->plane_offset;
- if (brush->flag & BRUSH_OFFSET_PRESSURE) {
- rv *= ss->cache->pressure;
- }
+ if (brush->flag & BRUSH_OFFSET_PRESSURE) {
+ rv *= ss->cache->pressure;
+ }
- return rv;
+ return rv;
}
-static void do_flatten_brush_task_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict tls)
+static void do_flatten_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict tls)
{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const Brush *brush = data->brush;
- const float *area_no = data->area_no;
- const float *area_co = data->area_co;
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ const float *area_no = data->area_no;
+ const float *area_co = data->area_co;
- PBVHVertexIter vd;
- float (*proxy)[3];
- const float bstrength = ss->cache->bstrength;
+ PBVHVertexIter vd;
+ float(*proxy)[3];
+ const float bstrength = ss->cache->bstrength;
- proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
+ 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);
+ SculptBrushTest test;
+ 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);
+ 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)) {
- float intr[3];
- float val[3];
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ float intr[3];
+ float val[3];
- closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co);
+ closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co);
- sub_v3_v3v3(val, intr, vd.co);
+ 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, tls->thread_id);
+ 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,
+ tls->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;
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
+ if (vd.mvert)
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
- SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
- const float radius = ss->cache->radius;
+ const float radius = ss->cache->radius;
- float area_no[3];
- float area_co[3];
+ float area_no[3];
+ float area_co[3];
- float offset = get_offset(sd, ss);
- float displace;
- float temp[3];
+ float offset = get_offset(sd, ss);
+ float displace;
+ float temp[3];
- calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co);
+ calc_sculpt_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);
- add_v3_v3(area_co, temp);
+ mul_v3_v3v3(temp, area_no, ss->cache->scale);
+ mul_v3_fl(temp, displace);
+ add_v3_v3(area_co, temp);
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- .area_no = area_no, .area_co = area_co,
- };
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .area_no = area_no,
+ .area_co = area_co,
+ };
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_flatten_brush_task_cb_ex,
- &settings);
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ BLI_task_parallel_range(0, totnode, &data, do_flatten_brush_task_cb_ex, &settings);
}
-static void do_clay_brush_task_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict tls)
+static void do_clay_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict tls)
{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const Brush *brush = data->brush;
- const float *area_no = data->area_no;
- const float *area_co = data->area_co;
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ const float *area_no = data->area_no;
+ const float *area_co = data->area_co;
- PBVHVertexIter vd;
- float (*proxy)[3];
- const bool flip = (ss->cache->bstrength < 0);
- const float bstrength = flip ? -ss->cache->bstrength : ss->cache->bstrength;
+ PBVHVertexIter vd;
+ float(*proxy)[3];
+ const bool flip = (ss->cache->bstrength < 0);
+ const float bstrength = flip ? -ss->cache->bstrength : ss->cache->bstrength;
- proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
+ 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);
+ SculptBrushTest test;
+ 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);
+ 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_flip(vd.co, test.plane_tool, flip)) {
- float intr[3];
- float val[3];
+ 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_flip(vd.co, test.plane_tool, flip)) {
+ float intr[3];
+ float val[3];
- closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co);
+ closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co);
- sub_v3_v3v3(val, intr, vd.co);
+ 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, sqrtf(test.dist),
- vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, tls->thread_id);
+ 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,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ tls->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;
- }
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
+ if (vd.mvert)
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
- SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
+ 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 bool flip = (ss->cache->bstrength < 0);
+ const float radius = flip ? -ss->cache->radius : ss->cache->radius;
- float offset = get_offset(sd, ss);
- float displace;
+ float offset = get_offset(sd, ss);
+ float displace;
- float area_no[3];
- float area_co[3];
- float temp[3];
+ float area_no[3];
+ float area_co[3];
+ float temp[3];
- calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co);
+ calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co);
- displace = radius * (0.25f + offset);
+ displace = radius * (0.25f + offset);
- mul_v3_v3v3(temp, area_no, ss->cache->scale);
- mul_v3_fl(temp, displace);
- add_v3_v3(area_co, temp);
+ mul_v3_v3v3(temp, area_no, ss->cache->scale);
+ mul_v3_fl(temp, displace);
+ add_v3_v3(area_co, temp);
- /* add_v3_v3v3(p, ss->cache->location, area_no); */
+ /* add_v3_v3v3(p, ss->cache->location, area_no); */
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- .area_no = area_no, .area_co = area_co,
- };
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .area_no = area_no,
+ .area_co = area_co,
+ };
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_clay_brush_task_cb_ex,
- &settings);
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ BLI_task_parallel_range(0, totnode, &data, do_clay_brush_task_cb_ex, &settings);
}
-static void do_clay_strips_brush_task_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict tls)
+static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__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_co = data->area_co;
+ 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_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;
+ PBVHVertexIter vd;
+ SculptBrushTest test;
+ float(*proxy)[3];
+ const bool flip = (ss->cache->bstrength < 0);
+ const float bstrength = flip ? -ss->cache->bstrength : ss->cache->bstrength;
- proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
+ 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);
+ sculpt_brush_test_init(ss, &test);
+ plane_from_point_normal_v3(test.plane_tool, area_co, area_no_sp);
- 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)) {
- float intr[3];
- float val[3];
+ 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)) {
+ float intr[3];
+ float val[3];
- closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co);
+ closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co);
- sub_v3_v3v3(val, intr, vd.co);
+ 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, tls->thread_id);
+ 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,
+ tls->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;
- }
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
+ if (vd.mvert)
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
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);
- const float radius = flip ? -ss->cache->radius : ss->cache->radius;
- const float offset = get_offset(sd, ss);
- const float displace = radius * (0.25f + offset);
-
- float area_no_sp[3]; /* the sculpt-plane normal (whatever its set to) */
- float area_no[3]; /* geometry normal */
- 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);
-
- 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);
-
- /* delay the first daub because grab delta is not setup */
- if (ss->cache->first_time)
- return;
-
- mul_v3_v3v3(temp, area_no_sp, 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_co = area_co, .mat = mat,
- };
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_clay_strips_brush_task_cb_ex,
- &settings);
-}
-
-static void do_fill_brush_task_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict tls)
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const Brush *brush = data->brush;
- const float *area_no = data->area_no;
- const float *area_co = data->area_co;
-
- PBVHVertexIter vd;
- float (*proxy)[3];
- const float 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);
-
- 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)) {
- float intr[3];
- float val[3];
-
- 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)) {
- const float fade = bstrength * tex_strength(
- ss, brush, vd.co, sqrtf(test.dist),
- vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, tls->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;
+ 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);
+
+ float area_no_sp[3]; /* the sculpt-plane normal (whatever its set to) */
+ float area_no[3]; /* geometry normal */
+ 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);
+
+ 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);
+
+ /* delay the first daub because grab delta is not setup */
+ if (ss->cache->first_time)
+ return;
+
+ mul_v3_v3v3(temp, area_no_sp, 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_co = area_co,
+ .mat = mat,
+ };
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ BLI_task_parallel_range(0, totnode, &data, do_clay_strips_brush_task_cb_ex, &settings);
+}
+
+static void do_fill_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ const float *area_no = data->area_no;
+ const float *area_co = data->area_co;
+
+ PBVHVertexIter vd;
+ float(*proxy)[3];
+ const float 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);
+
+ 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)) {
+ float intr[3];
+ float val[3];
+
+ 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)) {
+ const float fade = bstrength * tex_strength(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ tls->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;
}
static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
- SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
- const float radius = ss->cache->radius;
+ const float radius = ss->cache->radius;
- float area_no[3];
- float area_co[3];
- float offset = get_offset(sd, ss);
+ float area_no[3];
+ float area_co[3];
+ float offset = get_offset(sd, ss);
- float displace;
+ float displace;
- float temp[3];
+ float temp[3];
- calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co);
+ calc_sculpt_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);
- add_v3_v3(area_co, temp);
+ mul_v3_v3v3(temp, area_no, ss->cache->scale);
+ mul_v3_fl(temp, displace);
+ add_v3_v3(area_co, temp);
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- .area_no = area_no, .area_co = area_co,
- };
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .area_no = area_no,
+ .area_co = area_co,
+ };
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_fill_brush_task_cb_ex,
- &settings);
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ BLI_task_parallel_range(0, totnode, &data, do_fill_brush_task_cb_ex, &settings);
}
-static void do_scrape_brush_task_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict tls)
+static void do_scrape_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict tls)
{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const Brush *brush = data->brush;
- const float *area_no = data->area_no;
- const float *area_co = data->area_co;
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ const float *area_no = data->area_no;
+ const float *area_co = data->area_co;
- PBVHVertexIter vd;
- float (*proxy)[3];
- const float bstrength = ss->cache->bstrength;
+ PBVHVertexIter vd;
+ float(*proxy)[3];
+ const float bstrength = ss->cache->bstrength;
- proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
+ 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);
- plane_from_point_normal_v3(test.plane_tool, area_co, area_no);
+ SculptBrushTest test;
+ 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);
- 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];
+ 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);
+ closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co);
- sub_v3_v3v3(val, intr, vd.co);
+ 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, tls->thread_id);
+ 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,
+ tls->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;
- }
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
+ 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)
{
- SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
- const float radius = ss->cache->radius;
+ const float radius = ss->cache->radius;
- float area_no[3];
- float area_co[3];
- float offset = get_offset(sd, ss);
+ float area_no[3];
+ float area_co[3];
+ float offset = get_offset(sd, ss);
- float displace;
+ float displace;
- float temp[3];
+ float temp[3];
- calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co);
+ calc_sculpt_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);
- add_v3_v3(area_co, temp);
+ mul_v3_v3v3(temp, area_no, ss->cache->scale);
+ mul_v3_fl(temp, displace);
+ add_v3_v3(area_co, temp);
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- .area_no = area_no, .area_co = area_co,
- };
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .area_no = area_no,
+ .area_co = area_co,
+ };
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_scrape_brush_task_cb_ex,
- &settings);
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ BLI_task_parallel_range(0, totnode, &data, do_scrape_brush_task_cb_ex, &settings);
}
-static void do_gravity_task_cb_ex(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict tls)
+static void do_gravity_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict tls)
{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const Brush *brush = data->brush;
- float *offset = data->offset;
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ float *offset = data->offset;
- PBVHVertexIter vd;
- float (*proxy)[3];
+ PBVHVertexIter vd;
+ float(*proxy)[3];
- proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
+ 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);
+ 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 = tex_strength(
- ss, brush, vd.co, sqrtf(test.dist),
- vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, tls->thread_id);
+ 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,
+ tls->thread_id);
- mul_v3_v3fl(proxy[vd.i], offset, fade);
+ mul_v3_v3fl(proxy[vd.i], offset, fade);
- if (vd.mvert)
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- BKE_pbvh_vertex_iter_end;
+ if (vd.mvert)
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float bstrength)
{
- SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
- float offset[3]/*, area_no[3]*/;
- float gravity_vector[3];
+ float offset[3] /*, area_no[3]*/;
+ float gravity_vector[3];
- mul_v3_v3fl(gravity_vector, ss->cache->gravity_direction, -ss->cache->radius_squared);
+ mul_v3_v3fl(gravity_vector, ss->cache->gravity_direction, -ss->cache->radius_squared);
- /* offset with as much as possible factored in already */
- mul_v3_v3v3(offset, gravity_vector, ss->cache->scale);
- mul_v3_fl(offset, bstrength);
+ /* 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 */
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- .offset = offset,
- };
+ /* threaded loop over nodes */
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .offset = offset,
+ };
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- do_gravity_task_cb_ex,
- &settings);
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ BLI_task_parallel_range(0, totnode, &data, do_gravity_task_cb_ex, &settings);
}
-
void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
{
- Mesh *me = (Mesh *)ob->data;
- float (*ofs)[3] = NULL;
- int a;
- const int kb_act_idx = ob->shapenr - 1;
- KeyBlock *currkey;
+ Mesh *me = (Mesh *)ob->data;
+ float(*ofs)[3] = NULL;
+ int a;
+ const int kb_act_idx = ob->shapenr - 1;
+ KeyBlock *currkey;
- /* 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);
+ /* 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) */
- for (a = 0; a < me->totvert; a++) {
- sub_v3_v3v3(ofs[a], vertCos[a], ofs[a]);
- }
+ /* 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 */
- 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);
- }
- }
+ /* 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);
+ }
+ }
- MEM_freeN(ofs);
- }
+ MEM_freeN(ofs);
+ }
- /* modifying of basis key should update mesh */
- if (kb == me->key->refkey) {
- MVert *mvert = me->mvert;
+ /* modifying of basis key should update mesh */
+ if (kb == me->key->refkey) {
+ MVert *mvert = me->mvert;
- for (a = 0; a < me->totvert; a++, mvert++)
- copy_v3_v3(mvert->co, vertCos[a]);
+ for (a = 0; a < me->totvert; a++, mvert++)
+ copy_v3_v3(mvert->co, vertCos[a]);
- BKE_mesh_calc_normals(me);
- }
+ BKE_mesh_calc_normals(me);
+ }
- /* apply new coords on active key block, no need to re-allocate kb->data here! */
- BKE_keyblock_update_from_vertcos(ob, kb, vertCos);
+ /* apply new coords on active key block, no need to re-allocate kb->data here! */
+ BKE_keyblock_update_from_vertcos(ob, kb, vertCos);
}
/* Note: we do the topology update before any brush actions to avoid
* issues with the proxies. The size of the proxy can't change, so
* topology must be updated first. */
-static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings *UNUSED(ups))
-{
- SculptSession *ss = ob->sculpt;
-
- int n, totnode;
- /* 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 */
- if (totnode) {
- PBVHTopologyUpdateMode mode = 0;
- float location[3];
-
- if (!(sd->flags & SCULPT_DYNTOPO_DETAIL_MANUAL)) {
- if (sd->flags & SCULPT_DYNTOPO_SUBDIVIDE) {
- mode |= PBVH_Subdivide;
- }
-
- if ((sd->flags & SCULPT_DYNTOPO_COLLAPSE) ||
- (brush->sculpt_tool == SCULPT_TOOL_SIMPLIFY))
- {
- mode |= PBVH_Collapse;
- }
- }
-
- for (n = 0; n < totnode; n++) {
- sculpt_undo_push_node(ob, nodes[n],
- brush->sculpt_tool == SCULPT_TOOL_MASK ?
- SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS);
- BKE_pbvh_node_mark_update(nodes[n]);
-
- if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
- BKE_pbvh_node_mark_topology_update(nodes[n]);
- BKE_pbvh_bmesh_node_save_orig(nodes[n]);
- }
- }
-
- if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
- BKE_pbvh_bmesh_update_topology(
- ss->pbvh, mode,
- ss->cache->location,
- ss->cache->view_normal,
- ss->cache->radius,
- (brush->flag & BRUSH_FRONTFACE) != 0,
- (brush->falloff_shape != PAINT_FALLOFF_SHAPE_SPHERE));
- }
-
- MEM_freeN(nodes);
-
- /* update average stroke position */
- copy_v3_v3(location, ss->cache->true_location);
- mul_m4_v3(ob->obmat, location);
- }
-}
-
-static void do_brush_action_task_cb(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict UNUSED(tls))
-{
- SculptThreadedTaskData *data = userdata;
-
- sculpt_undo_push_node(data->ob, data->nodes[n],
- data->brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS);
- BKE_pbvh_node_mark_update(data->nodes[n]);
+static void sculpt_topology_update(Sculpt *sd,
+ Object *ob,
+ Brush *brush,
+ UnifiedPaintSettings *UNUSED(ups))
+{
+ SculptSession *ss = ob->sculpt;
+
+ int n, totnode;
+ /* 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 */
+ if (totnode) {
+ PBVHTopologyUpdateMode mode = 0;
+ float location[3];
+
+ if (!(sd->flags & SCULPT_DYNTOPO_DETAIL_MANUAL)) {
+ if (sd->flags & SCULPT_DYNTOPO_SUBDIVIDE) {
+ mode |= PBVH_Subdivide;
+ }
+
+ if ((sd->flags & SCULPT_DYNTOPO_COLLAPSE) || (brush->sculpt_tool == SCULPT_TOOL_SIMPLIFY)) {
+ mode |= PBVH_Collapse;
+ }
+ }
+
+ for (n = 0; n < totnode; n++) {
+ sculpt_undo_push_node(ob,
+ nodes[n],
+ brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK :
+ SCULPT_UNDO_COORDS);
+ BKE_pbvh_node_mark_update(nodes[n]);
+
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ BKE_pbvh_node_mark_topology_update(nodes[n]);
+ BKE_pbvh_bmesh_node_save_orig(nodes[n]);
+ }
+ }
+
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ BKE_pbvh_bmesh_update_topology(ss->pbvh,
+ mode,
+ ss->cache->location,
+ ss->cache->view_normal,
+ ss->cache->radius,
+ (brush->flag & BRUSH_FRONTFACE) != 0,
+ (brush->falloff_shape != PAINT_FALLOFF_SHAPE_SPHERE));
+ }
+
+ MEM_freeN(nodes);
+
+ /* update average stroke position */
+ copy_v3_v3(location, ss->cache->true_location);
+ mul_m4_v3(ob->obmat, location);
+ }
+}
+
+static void do_brush_action_task_cb(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+
+ sculpt_undo_push_node(data->ob,
+ data->nodes[n],
+ data->brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK :
+ SCULPT_UNDO_COORDS);
+ BKE_pbvh_node_mark_update(data->nodes[n]);
}
static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings *ups)
{
- SculptSession *ss = ob->sculpt;
- int totnode;
-
- /* 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.0f;
- PBVHNode **nodes = sculpt_pbvh_gather_generic(ob, sd, brush, use_original, radius_scale, &totnode);
-
- /* Only act if some verts are inside the brush area */
- if (totnode) {
- float location[3];
-
- SculptThreadedTaskData task_data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- };
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- 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);
-
- if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA)
- update_brush_local_mat(sd, ob);
-
- /* 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);
- break;
- case SCULPT_TOOL_CREASE:
- do_crease_brush(sd, ob, nodes, totnode);
- break;
- case SCULPT_TOOL_BLOB:
- do_crease_brush(sd, ob, nodes, totnode);
- break;
- case SCULPT_TOOL_PINCH:
- do_pinch_brush(sd, ob, nodes, totnode);
- break;
- case SCULPT_TOOL_INFLATE:
- do_inflate_brush(sd, ob, nodes, totnode);
- break;
- case SCULPT_TOOL_GRAB:
- do_grab_brush(sd, ob, nodes, totnode);
- break;
- case SCULPT_TOOL_ROTATE:
- do_rotate_brush(sd, ob, nodes, totnode);
- break;
- case SCULPT_TOOL_SNAKE_HOOK:
- do_snake_hook_brush(sd, ob, nodes, totnode);
- break;
- case SCULPT_TOOL_NUDGE:
- do_nudge_brush(sd, ob, nodes, totnode);
- break;
- case SCULPT_TOOL_THUMB:
- do_thumb_brush(sd, ob, nodes, totnode);
- break;
- case SCULPT_TOOL_LAYER:
- do_layer_brush(sd, ob, nodes, totnode);
- break;
- case SCULPT_TOOL_FLATTEN:
- do_flatten_brush(sd, ob, nodes, totnode);
- break;
- case SCULPT_TOOL_CLAY:
- do_clay_brush(sd, ob, nodes, totnode);
- break;
- case SCULPT_TOOL_CLAY_STRIPS:
- do_clay_strips_brush(sd, ob, nodes, totnode);
- break;
- case SCULPT_TOOL_FILL:
- do_fill_brush(sd, ob, nodes, totnode);
- break;
- case SCULPT_TOOL_SCRAPE:
- do_scrape_brush(sd, ob, nodes, totnode);
- break;
- case SCULPT_TOOL_MASK:
- do_mask_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);
- }
- else {
- smooth(sd, ob, nodes, totnode, brush->autosmooth_factor, false);
- }
- }
-
- if (sculpt_brush_use_topology_rake(ss, brush)) {
- bmesh_topology_rake(sd, ob, nodes, totnode, brush->topology_rake_factor);
- }
-
- if (ss->cache->supports_gravity)
- do_gravity(sd, ob, nodes, totnode, sd->gravity_factor);
-
- MEM_freeN(nodes);
-
- /* 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 */
- ups->last_stroke_valid = true;
- }
+ SculptSession *ss = ob->sculpt;
+ int totnode;
+
+ /* 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.0f;
+ PBVHNode **nodes = sculpt_pbvh_gather_generic(
+ ob, sd, brush, use_original, radius_scale, &totnode);
+
+ /* Only act if some verts are inside the brush area */
+ if (totnode) {
+ float location[3];
+
+ SculptThreadedTaskData task_data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ };
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ 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);
+
+ if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA)
+ update_brush_local_mat(sd, ob);
+
+ /* 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);
+ break;
+ case SCULPT_TOOL_CREASE:
+ do_crease_brush(sd, ob, nodes, totnode);
+ break;
+ case SCULPT_TOOL_BLOB:
+ do_crease_brush(sd, ob, nodes, totnode);
+ break;
+ case SCULPT_TOOL_PINCH:
+ do_pinch_brush(sd, ob, nodes, totnode);
+ break;
+ case SCULPT_TOOL_INFLATE:
+ do_inflate_brush(sd, ob, nodes, totnode);
+ break;
+ case SCULPT_TOOL_GRAB:
+ do_grab_brush(sd, ob, nodes, totnode);
+ break;
+ case SCULPT_TOOL_ROTATE:
+ do_rotate_brush(sd, ob, nodes, totnode);
+ break;
+ case SCULPT_TOOL_SNAKE_HOOK:
+ do_snake_hook_brush(sd, ob, nodes, totnode);
+ break;
+ case SCULPT_TOOL_NUDGE:
+ do_nudge_brush(sd, ob, nodes, totnode);
+ break;
+ case SCULPT_TOOL_THUMB:
+ do_thumb_brush(sd, ob, nodes, totnode);
+ break;
+ case SCULPT_TOOL_LAYER:
+ do_layer_brush(sd, ob, nodes, totnode);
+ break;
+ case SCULPT_TOOL_FLATTEN:
+ do_flatten_brush(sd, ob, nodes, totnode);
+ break;
+ case SCULPT_TOOL_CLAY:
+ do_clay_brush(sd, ob, nodes, totnode);
+ break;
+ case SCULPT_TOOL_CLAY_STRIPS:
+ do_clay_strips_brush(sd, ob, nodes, totnode);
+ break;
+ case SCULPT_TOOL_FILL:
+ do_fill_brush(sd, ob, nodes, totnode);
+ break;
+ case SCULPT_TOOL_SCRAPE:
+ do_scrape_brush(sd, ob, nodes, totnode);
+ break;
+ case SCULPT_TOOL_MASK:
+ do_mask_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);
+ }
+ else {
+ smooth(sd, ob, nodes, totnode, brush->autosmooth_factor, false);
+ }
+ }
+
+ if (sculpt_brush_use_topology_rake(ss, brush)) {
+ bmesh_topology_rake(sd, ob, nodes, totnode, brush->topology_rake_factor);
+ }
+
+ if (ss->cache->supports_gravity)
+ do_gravity(sd, ob, nodes, totnode, sd->gravity_factor);
+
+ MEM_freeN(nodes);
+
+ /* 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 */
+ ups->last_stroke_valid = true;
+ }
}
/* flush displacement from deformed PBVH vertex to original mesh */
static void sculpt_flush_pbvhvert_deform(Object *ob, PBVHVertexIter *vd)
{
- SculptSession *ss = ob->sculpt;
- Mesh *me = ob->data;
- float disp[3], newco[3];
- int index = vd->vert_indices[vd->i];
+ SculptSession *ss = ob->sculpt;
+ Mesh *me = ob->data;
+ float disp[3], newco[3];
+ int index = vd->vert_indices[vd->i];
- sub_v3_v3v3(disp, vd->co, ss->deform_cos[index]);
- mul_m3_v3(ss->deform_imats[index], disp);
- add_v3_v3v3(newco, disp, ss->orig_cos[index]);
+ sub_v3_v3v3(disp, vd->co, ss->deform_cos[index]);
+ mul_m3_v3(ss->deform_imats[index], disp);
+ add_v3_v3v3(newco, disp, ss->orig_cos[index]);
- copy_v3_v3(ss->deform_cos[index], vd->co);
- copy_v3_v3(ss->orig_cos[index], newco);
+ copy_v3_v3(ss->deform_cos[index], vd->co);
+ copy_v3_v3(ss->orig_cos[index], newco);
- if (!ss->kb)
- copy_v3_v3(me->mvert[index].co, newco);
+ if (!ss->kb)
+ copy_v3_v3(me->mvert[index].co, newco);
}
-static void sculpt_combine_proxies_task_cb(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict UNUSED(tls))
+static void sculpt_combine_proxies_task_cb(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- Sculpt *sd = data->sd;
- Object *ob = data->ob;
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ Sculpt *sd = data->sd;
+ Object *ob = data->ob;
- /* these brushes start from original coordinates */
- const bool use_orco = ELEM(data->brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_THUMB);
+ /* these brushes start from original coordinates */
+ const bool use_orco = ELEM(
+ data->brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_THUMB);
- PBVHVertexIter vd;
- PBVHProxyNode *proxies;
- int proxy_count;
- float (*orco)[3] = NULL;
+ PBVHVertexIter vd;
+ PBVHProxyNode *proxies;
+ int proxy_count;
+ float(*orco)[3] = NULL;
- if (use_orco && !ss->bm)
- orco = sculpt_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS)->co;
+ if (use_orco && !ss->bm)
+ 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);
+ BKE_pbvh_node_get_proxies(data->nodes[n], &proxies, &proxy_count);
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- float val[3];
- int p;
+ 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) {
- copy_v3_v3(val, BM_log_original_vert_co(ss->bm_log, vd.bm_vert));
- }
- else {
- copy_v3_v3(val, orco[vd.i]);
- }
- }
- else {
- copy_v3_v3(val, vd.co);
- }
+ if (use_orco) {
+ if (ss->bm) {
+ copy_v3_v3(val, BM_log_original_vert_co(ss->bm_log, vd.bm_vert));
+ }
+ else {
+ copy_v3_v3(val, orco[vd.i]);
+ }
+ }
+ else {
+ copy_v3_v3(val, vd.co);
+ }
- for (p = 0; p < proxy_count; p++)
- add_v3_v3(val, proxies[p].co[vd.i]);
+ for (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->modifiers_active)
- sculpt_flush_pbvhvert_deform(ob, &vd);
- }
- BKE_pbvh_vertex_iter_end;
+ if (ss->modifiers_active)
+ sculpt_flush_pbvhvert_deform(ob, &vd);
+ }
+ BKE_pbvh_vertex_iter_end;
- BKE_pbvh_node_free_proxies(data->nodes[n]);
+ BKE_pbvh_node_free_proxies(data->nodes[n]);
}
static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
{
- SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
- PBVHNode **nodes;
- int totnode;
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ PBVHNode **nodes;
+ int totnode;
- BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode);
+ BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode);
- /* 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, .ob = ob, .brush = brush, .nodes = nodes,
- };
+ /* 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,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ };
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- sculpt_combine_proxies_task_cb,
- &settings);
- }
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ BLI_task_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings);
+ }
- if (nodes)
- MEM_freeN(nodes);
+ if (nodes)
+ MEM_freeN(nodes);
}
/* copy the modified vertices from bvh to the active key */
static void sculpt_update_keyblock(Object *ob)
{
- SculptSession *ss = ob->sculpt;
- float (*vertCos)[3];
+ 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 */
- if (ss->orig_cos) vertCos = ss->orig_cos;
- else vertCos = BKE_pbvh_get_vertCos(ss->pbvh);
+ /* Keyblock update happens after handling deformation caused by modifiers,
+ * so ss->orig_cos would be updated with new stroke */
+ if (ss->orig_cos)
+ vertCos = ss->orig_cos;
+ else
+ vertCos = BKE_pbvh_get_vertCos(ss->pbvh);
- if (vertCos) {
- sculpt_vertcos_to_key(ob, ss->kb, vertCos);
+ if (vertCos) {
+ sculpt_vertcos_to_key(ob, ss->kb, vertCos);
- if (vertCos != ss->orig_cos)
- MEM_freeN(vertCos);
- }
+ if (vertCos != ss->orig_cos)
+ MEM_freeN(vertCos);
+ }
}
-static void sculpt_flush_stroke_deform_task_cb(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict UNUSED(tls))
+static void sculpt_flush_stroke_deform_task_cb(void *__restrict userdata,
+ const int n,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- Object *ob = data->ob;
- float (*vertCos)[3] = data->vertCos;
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ Object *ob = data->ob;
+ float(*vertCos)[3] = data->vertCos;
- PBVHVertexIter vd;
+ PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- sculpt_flush_pbvhvert_deform(ob, &vd);
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ sculpt_flush_pbvhvert_deform(ob, &vd);
- if (vertCos) {
- int index = vd.vert_indices[vd.i];
- copy_v3_v3(vertCos[index], ss->orig_cos[index]);
- }
- }
- BKE_pbvh_vertex_iter_end;
+ if (vertCos) {
+ int index = vd.vert_indices[vd.i];
+ copy_v3_v3(vertCos[index], ss->orig_cos[index]);
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
/* flush displacement from deformed PBVH to original layer */
static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob)
{
- SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
-
- if (sculpt_tool_is_proxy_used(brush->sculpt_tool)) {
- /* 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;
- PBVHNode **nodes;
- float (*vertCos)[3] = NULL;
-
- if (ss->kb) {
- 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
- */
- memcpy(vertCos, ss->orig_cos, sizeof(*vertCos) * me->totvert);
- }
-
- BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
-
- SculptThreadedTaskData data = {
- .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
- .vertCos = vertCos,
- };
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- &data,
- sculpt_flush_stroke_deform_task_cb,
- &settings);
-
- if (vertCos) {
- sculpt_vertcos_to_key(ob, ss->kb, vertCos);
- MEM_freeN(vertCos);
- }
-
- MEM_freeN(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 */
- BKE_mesh_calc_normals(me);
- }
- else if (ss->kb) {
- sculpt_update_keyblock(ob);
- }
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ if (sculpt_tool_is_proxy_used(brush->sculpt_tool)) {
+ /* 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;
+ PBVHNode **nodes;
+ float(*vertCos)[3] = NULL;
+
+ if (ss->kb) {
+ 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
+ */
+ memcpy(vertCos, ss->orig_cos, sizeof(*vertCos) * me->totvert);
+ }
+
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .vertCos = vertCos,
+ };
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ BLI_task_parallel_range(0, totnode, &data, sculpt_flush_stroke_deform_task_cb, &settings);
+
+ if (vertCos) {
+ sculpt_vertcos_to_key(ob, ss->kb, vertCos);
+ MEM_freeN(vertCos);
+ }
+
+ MEM_freeN(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 */
+ BKE_mesh_calc_normals(me);
+ }
+ else if (ss->kb) {
+ sculpt_update_keyblock(ob);
+ }
}
/* 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, const char symm,
- const char axis, const float angle)
-{
- flip_v3_v3(cache->location, cache->true_location, symm);
- flip_v3_v3(cache->last_location, cache->true_last_location, symm);
- flip_v3_v3(cache->grab_delta_symmetry, cache->grab_delta, symm);
- flip_v3_v3(cache->view_normal, cache->true_view_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 */
+void sculpt_cache_calc_brushdata_symm(StrokeCache *cache,
+ const char symm,
+ const char axis,
+ const float angle)
+{
+ flip_v3_v3(cache->location, cache->true_location, symm);
+ flip_v3_v3(cache->last_location, cache->true_last_location, symm);
+ flip_v3_v3(cache->grab_delta_symmetry, cache->grab_delta, symm);
+ flip_v3_v3(cache->view_normal, cache->true_view_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 */
#if 0
- if (sd->paint.symmetry_flags & PAINT_SYMMETRY_FEATHER) {
- float frac = 1.0f / max_overlap_count(sd);
- float reduce = (feather - frac) / (1 - frac);
+ if (sd->paint.symmetry_flags & PAINT_SYMMETRY_FEATHER) {
+ float frac = 1.0f / max_overlap_count(sd);
+ float reduce = (feather - frac) / (1 - frac);
- printf("feather: %f frac: %f reduce: %f\n", feather, frac, reduce);
+ printf("feather: %f frac: %f reduce: %f\n", feather, frac, reduce);
- if (frac < 1)
- mul_v3_fl(cache->grab_delta_symmetry, reduce);
- }
+ if (frac < 1)
+ mul_v3_fl(cache->grab_delta_symmetry, reduce);
+ }
#endif
- unit_m4(cache->symm_rot_mat);
- unit_m4(cache->symm_rot_mat_inv);
- zero_v3(cache->plane_offset);
+ unit_m4(cache->symm_rot_mat);
+ unit_m4(cache->symm_rot_mat_inv);
+ zero_v3(cache->plane_offset);
- if (axis) { /* expects XYZ */
- rotate_m4(cache->symm_rot_mat, axis, angle);
- rotate_m4(cache->symm_rot_mat_inv, axis, -angle);
- }
+ if (axis) { /* expects XYZ */
+ rotate_m4(cache->symm_rot_mat, axis, angle);
+ rotate_m4(cache->symm_rot_mat_inv, axis, -angle);
+ }
- mul_m4_v3(cache->symm_rot_mat, cache->location);
- mul_m4_v3(cache->symm_rot_mat, cache->grab_delta_symmetry);
+ mul_m4_v3(cache->symm_rot_mat, cache->location);
+ mul_m4_v3(cache->symm_rot_mat, cache->grab_delta_symmetry);
- if (cache->supports_gravity) {
- flip_v3_v3(cache->gravity_direction, cache->true_gravity_direction, symm);
- mul_m4_v3(cache->symm_rot_mat, cache->gravity_direction);
- }
+ if (cache->supports_gravity) {
+ flip_v3_v3(cache->gravity_direction, cache->true_gravity_direction, symm);
+ mul_m4_v3(cache->symm_rot_mat, cache->gravity_direction);
+ }
- if (cache->is_rake_rotation_valid) {
- flip_qt_qt(cache->rake_rotation_symmetry, cache->rake_rotation, symm);
- }
+ if (cache->is_rake_rotation_valid) {
+ flip_qt_qt(cache->rake_rotation_symmetry, cache->rake_rotation, symm);
+ }
}
typedef void (*BrushActionFunc)(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings *ups);
-static void do_tiled(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings *ups, BrushActionFunc action)
-{
- SculptSession *ss = ob->sculpt;
- StrokeCache *cache = ss->cache;
- const float radius = cache->radius;
- BoundBox *bb = BKE_object_boundbox_get(ob);
- 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. */
- int start[3];
- int end[3];
- int cur[3];
-
- float orgLoc[3]; /* position of the "prototype" stroke for tiling */
- copy_v3_v3(orgLoc, cache->location);
-
- for (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];
- }
- else
- start[dim] = end[dim] = 0;
- }
-
- /* 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 */
- 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 */
-
- ++cache->tile_pass;
-
- for (dim = 0; dim < 3; ++dim) {
- cache->location[dim] = cur[dim] * step[dim] + orgLoc[dim];
- cache->plane_offset[dim] = cur[dim] * step[dim];
- }
- action(sd, ob, brush, ups);
- }
- }
- }
-}
-
-
-static void do_radial_symmetry(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings *ups,
+static void do_tiled(
+ Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings *ups, BrushActionFunc action)
+{
+ SculptSession *ss = ob->sculpt;
+ StrokeCache *cache = ss->cache;
+ const float radius = cache->radius;
+ BoundBox *bb = BKE_object_boundbox_get(ob);
+ 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. */
+ int start[3];
+ int end[3];
+ int cur[3];
+
+ float orgLoc[3]; /* position of the "prototype" stroke for tiling */
+ copy_v3_v3(orgLoc, cache->location);
+
+ for (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];
+ }
+ else
+ start[dim] = end[dim] = 0;
+ }
+
+ /* 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 */
+ 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 */
+
+ ++cache->tile_pass;
+
+ for (dim = 0; dim < 3; ++dim) {
+ cache->location[dim] = cur[dim] * step[dim] + orgLoc[dim];
+ cache->plane_offset[dim] = cur[dim] * step[dim];
+ }
+ action(sd, ob, brush, ups);
+ }
+ }
+ }
+}
+
+static void do_radial_symmetry(Sculpt *sd,
+ Object *ob,
+ Brush *brush,
+ UnifiedPaintSettings *ups,
BrushActionFunc action,
- const char symm, const int axis,
+ const char symm,
+ const int axis,
const float UNUSED(feather))
{
- SculptSession *ss = ob->sculpt;
- int i;
+ 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'];
- ss->cache->radial_symmetry_pass = i;
- sculpt_cache_calc_brushdata_symm(ss->cache, symm, axis, angle);
- do_tiled(sd, ob, brush, ups, action);
- }
+ for (i = 1; i < sd->radial_symm[axis - 'X']; ++i) {
+ const float angle = 2 * M_PI * i / sd->radial_symm[axis - 'X'];
+ ss->cache->radial_symmetry_pass = i;
+ 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
@@ -4205,140 +4244,137 @@ static void do_radial_symmetry(Sculpt *sd, Object *ob, Brush *brush, UnifiedPain
* 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;
+ 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)
- multires_stitch_grids(ob);
+ if (ss->multires && mtex->tex && mtex->tex->type == TEX_NOISE)
+ multires_stitch_grids(ob);
}
-static void do_symmetrical_brush_actions(
- Sculpt *sd, Object *ob,
- BrushActionFunc action, UnifiedPaintSettings *ups)
+static void do_symmetrical_brush_actions(Sculpt *sd,
+ Object *ob,
+ BrushActionFunc action,
+ UnifiedPaintSettings *ups)
{
- Brush *brush = BKE_paint_brush(&sd->paint);
- SculptSession *ss = ob->sculpt;
- StrokeCache *cache = ss->cache;
- const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
- int i;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ 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);
+ float feather = calc_symmetry_feather(sd, ss->cache);
- cache->bstrength = brush_strength(sd, cache, feather, ups);
- cache->symmetry = symm;
+ cache->bstrength = brush_strength(sd, cache, feather, ups);
+ cache->symmetry = symm;
- /* 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) {
- 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;
+ /* 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) {
+ 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);
- do_tiled(sd, ob, brush, ups, action);
+ 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);
- do_radial_symmetry(sd, ob, brush, ups, action, i, 'Y', feather);
- do_radial_symmetry(sd, ob, brush, ups, action, i, 'Z', feather);
- }
- }
+ do_radial_symmetry(sd, ob, brush, ups, action, i, 'X', feather);
+ do_radial_symmetry(sd, ob, brush, ups, action, i, 'Y', feather);
+ do_radial_symmetry(sd, ob, brush, ups, action, i, 'Z', feather);
+ }
+ }
}
static void sculpt_update_tex(const Scene *scene, Sculpt *sd, SculptSession *ss)
{
- Brush *brush = BKE_paint_brush(&sd->paint);
- const int radius = BKE_brush_size_get(scene, brush);
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ const int radius = BKE_brush_size_get(scene, brush);
- if (ss->texcache) {
- MEM_freeN(ss->texcache);
- ss->texcache = NULL;
- }
+ if (ss->texcache) {
+ MEM_freeN(ss->texcache);
+ ss->texcache = NULL;
+ }
- if (ss->tex_pool) {
- BKE_image_pool_free(ss->tex_pool);
- ss->tex_pool = NULL;
- }
+ if (ss->tex_pool) {
+ BKE_image_pool_free(ss->tex_pool);
+ ss->tex_pool = NULL;
+ }
- /* 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);
- ss->texcache_actual = ss->texcache_side;
- ss->tex_pool = BKE_image_pool_new();
- }
+ /* 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);
+ ss->texcache_actual = ss->texcache_side;
+ ss->tex_pool = BKE_image_pool_new();
+ }
}
-
-
bool sculpt_mode_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
- return ob && ob->mode & OB_MODE_SCULPT;
+ Object *ob = CTX_data_active_object(C);
+ return ob && ob->mode & OB_MODE_SCULPT;
}
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)
{
- return (sculpt_poll(C) &&
- CTX_wm_region_view3d(C));
+ return (sculpt_poll(C) && CTX_wm_region_view3d(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)
{
- Brush *brush = BKE_paint_brush(&sd->paint);
-
- switch ((eBrushSculptTool)brush->sculpt_tool) {
- case SCULPT_TOOL_DRAW:
- return "Draw Brush";
- case SCULPT_TOOL_SMOOTH:
- return "Smooth Brush";
- case SCULPT_TOOL_CREASE:
- return "Crease Brush";
- case SCULPT_TOOL_BLOB:
- return "Blob Brush";
- case SCULPT_TOOL_PINCH:
- return "Pinch Brush";
- case SCULPT_TOOL_INFLATE:
- return "Inflate Brush";
- case SCULPT_TOOL_GRAB:
- return "Grab Brush";
- case SCULPT_TOOL_NUDGE:
- return "Nudge Brush";
- case SCULPT_TOOL_THUMB:
- return "Thumb Brush";
- case SCULPT_TOOL_LAYER:
- return "Layer Brush";
- case SCULPT_TOOL_FLATTEN:
- return "Flatten Brush";
- case SCULPT_TOOL_CLAY:
- return "Clay Brush";
- case SCULPT_TOOL_CLAY_STRIPS:
- return "Clay Strips Brush";
- case SCULPT_TOOL_FILL:
- return "Fill Brush";
- case SCULPT_TOOL_SCRAPE:
- return "Scrape Brush";
- case SCULPT_TOOL_SNAKE_HOOK:
- return "Snake Hook Brush";
- case SCULPT_TOOL_ROTATE:
- return "Rotate Brush";
- case SCULPT_TOOL_MASK:
- return "Mask Brush";
- case SCULPT_TOOL_SIMPLIFY:
- return "Simplify Brush";
- }
-
- return "Sculpting";
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ switch ((eBrushSculptTool)brush->sculpt_tool) {
+ case SCULPT_TOOL_DRAW:
+ return "Draw Brush";
+ case SCULPT_TOOL_SMOOTH:
+ return "Smooth Brush";
+ case SCULPT_TOOL_CREASE:
+ return "Crease Brush";
+ case SCULPT_TOOL_BLOB:
+ return "Blob Brush";
+ case SCULPT_TOOL_PINCH:
+ return "Pinch Brush";
+ case SCULPT_TOOL_INFLATE:
+ return "Inflate Brush";
+ case SCULPT_TOOL_GRAB:
+ return "Grab Brush";
+ case SCULPT_TOOL_NUDGE:
+ return "Nudge Brush";
+ case SCULPT_TOOL_THUMB:
+ return "Thumb Brush";
+ case SCULPT_TOOL_LAYER:
+ return "Layer Brush";
+ case SCULPT_TOOL_FLATTEN:
+ return "Flatten Brush";
+ case SCULPT_TOOL_CLAY:
+ return "Clay Brush";
+ case SCULPT_TOOL_CLAY_STRIPS:
+ return "Clay Strips Brush";
+ case SCULPT_TOOL_FILL:
+ return "Fill Brush";
+ case SCULPT_TOOL_SCRAPE:
+ return "Scrape Brush";
+ case SCULPT_TOOL_SNAKE_HOOK:
+ return "Snake Hook Brush";
+ case SCULPT_TOOL_ROTATE:
+ return "Rotate Brush";
+ case SCULPT_TOOL_MASK:
+ return "Mask Brush";
+ case SCULPT_TOOL_SIMPLIFY:
+ return "Simplify Brush";
+ }
+
+ return "Sculpting";
}
/**
@@ -4347,567 +4383,557 @@ static const char *sculpt_tool_name(Sculpt *sd)
void sculpt_cache_free(StrokeCache *cache)
{
- if (cache->dial)
- MEM_freeN(cache->dial);
- MEM_freeN(cache);
+ if (cache->dial)
+ MEM_freeN(cache->dial);
+ MEM_freeN(cache);
}
/* 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) {
- if (mmd->flag & (MOD_MIR_AXIS_X << i)) {
- /* enable sculpt clipping */
- ss->cache->flag |= CLIP_X << i;
-
- /* update the clip tolerance */
- if (mmd->tolerance >
- ss->cache->clip_tolerance[i])
- {
- ss->cache->clip_tolerance[i] =
- mmd->tolerance;
- }
- }
- }
- }
- }
- }
+ 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) {
+ if (mmd->flag & (MOD_MIR_AXIS_X << i)) {
+ /* enable sculpt clipping */
+ ss->cache->flag |= CLIP_X << i;
+
+ /* update the clip tolerance */
+ if (mmd->tolerance > ss->cache->clip_tolerance[i]) {
+ ss->cache->clip_tolerance[i] = mmd->tolerance;
+ }
+ }
+ }
+ }
+ }
+ }
}
/* 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])
-{
- StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
- Brush *brush = BKE_paint_brush(&sd->paint);
- ViewContext *vc = paint_stroke_view_context(op->customdata);
- Object *ob = CTX_data_active_object(C);
- 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]));
- }
- }
- cache->scale[0] = max_scale / ob->scale[0];
- cache->scale[1] = max_scale / ob->scale[1];
- cache->scale[2] = max_scale / ob->scale[2];
-
- cache->plane_trim_squared = brush->plane_trim * brush->plane_trim;
-
- cache->flag = 0;
-
- sculpt_init_mirror_clipping(ob, ss);
-
- /* Initial mouse location */
- if (mouse)
- copy_v2_v2(cache->initial_mouse, mouse);
- else
- zero_v2(cache->initial_mouse);
-
- 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 */
- if (SCULPT_TOOL_HAS_NORMAL_WEIGHT(brush->sculpt_tool)) {
- if (cache->invert) {
- cache->invert = false;
- cache->normal_weight = (cache->normal_weight == 0.0f);
- }
- }
-
- /* 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;
- else ups->draw_inverted = false;
-
- /* 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 {
- Paint *p = &sd->paint;
- Brush *br;
- int size = BKE_brush_size_get(scene, brush);
-
- BLI_strncpy(cache->saved_active_brush_name, brush->id.name + 2,
- sizeof(cache->saved_active_brush_name));
-
- br = (Brush *)BKE_libblock_find_name(bmain, ID_BR, "Smooth");
- if (br) {
- BKE_paint_brush_set(p, br);
- brush = br;
- cache->saved_smooth_size = BKE_brush_size_get(scene, brush);
- BKE_brush_size_set(scene, brush, size);
- curvemapping_initialize(brush->curve);
- }
- }
- }
-
- 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 */
-
- cache->vc = vc;
-
- cache->brush = brush;
-
- /* cache projection matrix */
- ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat);
-
- invert_m4_m4(ob->imat, ob->obmat);
- copy_m3_m4(mat, cache->vc->rv3d->viewinv);
- mul_m3_v3(mat, viewDir);
- copy_m3_m4(mat, ob->imat);
- mul_m3_v3(mat, viewDir);
- normalize_v3_v3(cache->true_view_normal, viewDir);
-
- 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 */
- if (cache->supports_gravity) {
- if (sd->gravity_object) {
- Object *gravity_object = sd->gravity_object;
-
- 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;
- }
-
- /* 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 */
- if (brush->flag & BRUSH_ANCHORED) {
- cache->original = 1;
- }
-
- if (SCULPT_TOOL_HAS_ACCUMULATE(brush->sculpt_tool)) {
- if (!(brush->flag & BRUSH_ACCUMULATE)) {
- cache->original = 1;
- }
- }
-
- cache->first_time = 1;
+ bContext *C, Sculpt *sd, SculptSession *ss, wmOperator *op, const float mouse[2])
+{
+ StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ ViewContext *vc = paint_stroke_view_context(op->customdata);
+ Object *ob = CTX_data_active_object(C);
+ 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]));
+ }
+ }
+ cache->scale[0] = max_scale / ob->scale[0];
+ cache->scale[1] = max_scale / ob->scale[1];
+ cache->scale[2] = max_scale / ob->scale[2];
+
+ cache->plane_trim_squared = brush->plane_trim * brush->plane_trim;
+
+ cache->flag = 0;
+
+ sculpt_init_mirror_clipping(ob, ss);
+
+ /* Initial mouse location */
+ if (mouse)
+ copy_v2_v2(cache->initial_mouse, mouse);
+ else
+ zero_v2(cache->initial_mouse);
+
+ 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 */
+ if (SCULPT_TOOL_HAS_NORMAL_WEIGHT(brush->sculpt_tool)) {
+ if (cache->invert) {
+ cache->invert = false;
+ cache->normal_weight = (cache->normal_weight == 0.0f);
+ }
+ }
+
+ /* 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;
+ else
+ ups->draw_inverted = false;
+
+ /* 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 {
+ Paint *p = &sd->paint;
+ Brush *br;
+ int size = BKE_brush_size_get(scene, brush);
+
+ BLI_strncpy(cache->saved_active_brush_name,
+ brush->id.name + 2,
+ sizeof(cache->saved_active_brush_name));
+
+ br = (Brush *)BKE_libblock_find_name(bmain, ID_BR, "Smooth");
+ if (br) {
+ BKE_paint_brush_set(p, br);
+ brush = br;
+ cache->saved_smooth_size = BKE_brush_size_get(scene, brush);
+ BKE_brush_size_set(scene, brush, size);
+ curvemapping_initialize(brush->curve);
+ }
+ }
+ }
+
+ 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 */
+
+ cache->vc = vc;
+
+ cache->brush = brush;
+
+ /* cache projection matrix */
+ ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat);
+
+ invert_m4_m4(ob->imat, ob->obmat);
+ copy_m3_m4(mat, cache->vc->rv3d->viewinv);
+ mul_m3_v3(mat, viewDir);
+ copy_m3_m4(mat, ob->imat);
+ mul_m3_v3(mat, viewDir);
+ normalize_v3_v3(cache->true_view_normal, viewDir);
+
+ 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 */
+ if (cache->supports_gravity) {
+ if (sd->gravity_object) {
+ Object *gravity_object = sd->gravity_object;
+
+ 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;
+ }
+
+ /* 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 */
+ if (brush->flag & BRUSH_ANCHORED) {
+ cache->original = 1;
+ }
+
+ if (SCULPT_TOOL_HAS_ACCUMULATE(brush->sculpt_tool)) {
+ if (!(brush->flag & BRUSH_ACCUMULATE)) {
+ cache->original = 1;
+ }
+ }
+
+ cache->first_time = 1;
#define PIXEL_INPUT_THRESHHOLD 5
- if (brush->sculpt_tool == SCULPT_TOOL_ROTATE)
- cache->dial = BLI_dial_initialize(cache->initial_mouse, PIXEL_INPUT_THRESHHOLD);
+ if (brush->sculpt_tool == SCULPT_TOOL_ROTATE)
+ cache->dial = BLI_dial_initialize(cache->initial_mouse, PIXEL_INPUT_THRESHHOLD);
#undef PIXEL_INPUT_THRESHHOLD
}
static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Brush *brush)
{
- SculptSession *ss = ob->sculpt;
- StrokeCache *cache = ss->cache;
- const float mouse[2] = {
- cache->mouse[0],
- cache->mouse[1],
- };
- int tool = brush->sculpt_tool;
-
- if (ELEM(tool,
- SCULPT_TOOL_GRAB, SCULPT_TOOL_NUDGE,
- SCULPT_TOOL_CLAY_STRIPS, SCULPT_TOOL_SNAKE_HOOK,
- SCULPT_TOOL_THUMB) ||
- sculpt_brush_use_topology_rake(ss, brush))
- {
- float grab_location[3], imat[4][4], delta[3], loc[3];
-
- if (cache->first_time) {
- copy_v3_v3(cache->orig_grab_location,
- cache->true_location);
- }
- else if (tool == SCULPT_TOOL_SNAKE_HOOK)
- add_v3_v3(cache->true_location, cache->grab_delta);
-
- /* 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);
-
- /* compute delta to move verts by */
- if (!cache->first_time) {
- switch (tool) {
- case SCULPT_TOOL_GRAB:
- case SCULPT_TOOL_THUMB:
- sub_v3_v3v3(delta, grab_location, cache->old_grab_location);
- invert_m4_m4(imat, ob->obmat);
- mul_mat3_m4_v3(imat, delta);
- add_v3_v3(cache->grab_delta, delta);
- break;
- case SCULPT_TOOL_CLAY_STRIPS:
- case SCULPT_TOOL_NUDGE:
- case SCULPT_TOOL_SNAKE_HOOK:
- if (brush->flag & BRUSH_ANCHORED) {
- float orig[3];
- mul_v3_m4v3(orig, ob->obmat, cache->orig_grab_location);
- sub_v3_v3v3(cache->grab_delta, grab_location, orig);
- }
- else {
- sub_v3_v3v3(cache->grab_delta, grab_location,
- cache->old_grab_location);
- }
- invert_m4_m4(imat, ob->obmat);
- mul_mat3_m4_v3(imat, cache->grab_delta);
- break;
- default:
- /* Use for 'Brush.topology_rake_factor'. */
- sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location);
- break;
-
- }
- }
- else {
- zero_v3(cache->grab_delta);
- }
-
- if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
- project_plane_v3_v3v3(cache->grab_delta, cache->grab_delta, ss->cache->true_view_normal);
- }
-
- copy_v3_v3(cache->old_grab_location, grab_location);
-
- if (tool == SCULPT_TOOL_GRAB)
- copy_v3_v3(cache->anchored_location, cache->true_location);
- else if (tool == SCULPT_TOOL_THUMB)
- copy_v3_v3(cache->anchored_location, cache->orig_grab_location);
-
- if (ELEM(tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB)) {
- /* location stays the same for finding vertices in brush radius */
- copy_v3_v3(cache->true_location, cache->orig_grab_location);
-
- ups->draw_anchored = true;
- copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse);
- ups->anchored_size = ups->pixel_radius;
- }
-
-
- /* handle 'rake' */
- cache->is_rake_rotation_valid = false;
-
- if (cache->first_time) {
- copy_v3_v3(cache->rake_data.follow_co, grab_location);
- }
-
- if (sculpt_brush_needs_rake_rotation(brush)) {
- cache->rake_data.follow_dist = cache->radius * SCULPT_RAKE_BRUSH_FACTOR;
-
- if (!is_zero_v3(cache->grab_delta)) {
- const float eps = 0.00001f;
-
- float v1[3], v2[3];
-
- copy_v3_v3(v1, cache->rake_data.follow_co);
- copy_v3_v3(v2, cache->rake_data.follow_co);
- sub_v3_v3(v2, cache->grab_delta);
-
- sub_v3_v3(v1, grab_location);
- sub_v3_v3(v2, grab_location);
-
- 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)) ?
- 1.0f : sqrtf(rake_dist_sq) / cache->rake_data.follow_dist;
-
- float axis[3], angle;
- float tquat[4];
-
- rotation_between_vecs_to_quat(tquat, v1, v2);
-
- /* use axis-angle to scale rotation since the factor may be above 1 */
- quat_to_axis_angle(axis, &angle, tquat);
- normalize_v3(axis);
-
- angle *= brush->rake_factor * rake_fade;
- axis_angle_normalized_to_quat(cache->rake_rotation, axis, angle);
- cache->is_rake_rotation_valid = true;
- }
- }
- sculpt_rake_data_update(&cache->rake_data, grab_location);
- }
- }
+ SculptSession *ss = ob->sculpt;
+ StrokeCache *cache = ss->cache;
+ const float mouse[2] = {
+ cache->mouse[0],
+ cache->mouse[1],
+ };
+ int tool = brush->sculpt_tool;
+
+ if (ELEM(tool,
+ SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_NUDGE,
+ SCULPT_TOOL_CLAY_STRIPS,
+ SCULPT_TOOL_SNAKE_HOOK,
+ SCULPT_TOOL_THUMB) ||
+ sculpt_brush_use_topology_rake(ss, brush)) {
+ float grab_location[3], imat[4][4], delta[3], loc[3];
+
+ if (cache->first_time) {
+ copy_v3_v3(cache->orig_grab_location, cache->true_location);
+ }
+ else if (tool == SCULPT_TOOL_SNAKE_HOOK)
+ add_v3_v3(cache->true_location, cache->grab_delta);
+
+ /* 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);
+
+ /* compute delta to move verts by */
+ if (!cache->first_time) {
+ switch (tool) {
+ case SCULPT_TOOL_GRAB:
+ case SCULPT_TOOL_THUMB:
+ sub_v3_v3v3(delta, grab_location, cache->old_grab_location);
+ invert_m4_m4(imat, ob->obmat);
+ mul_mat3_m4_v3(imat, delta);
+ add_v3_v3(cache->grab_delta, delta);
+ break;
+ case SCULPT_TOOL_CLAY_STRIPS:
+ case SCULPT_TOOL_NUDGE:
+ case SCULPT_TOOL_SNAKE_HOOK:
+ if (brush->flag & BRUSH_ANCHORED) {
+ float orig[3];
+ mul_v3_m4v3(orig, ob->obmat, cache->orig_grab_location);
+ sub_v3_v3v3(cache->grab_delta, grab_location, orig);
+ }
+ else {
+ sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location);
+ }
+ invert_m4_m4(imat, ob->obmat);
+ mul_mat3_m4_v3(imat, cache->grab_delta);
+ break;
+ default:
+ /* Use for 'Brush.topology_rake_factor'. */
+ sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location);
+ break;
+ }
+ }
+ else {
+ zero_v3(cache->grab_delta);
+ }
+
+ if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
+ project_plane_v3_v3v3(cache->grab_delta, cache->grab_delta, ss->cache->true_view_normal);
+ }
+
+ copy_v3_v3(cache->old_grab_location, grab_location);
+
+ if (tool == SCULPT_TOOL_GRAB)
+ copy_v3_v3(cache->anchored_location, cache->true_location);
+ else if (tool == SCULPT_TOOL_THUMB)
+ copy_v3_v3(cache->anchored_location, cache->orig_grab_location);
+
+ if (ELEM(tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB)) {
+ /* location stays the same for finding vertices in brush radius */
+ copy_v3_v3(cache->true_location, cache->orig_grab_location);
+
+ ups->draw_anchored = true;
+ copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse);
+ ups->anchored_size = ups->pixel_radius;
+ }
+
+ /* handle 'rake' */
+ cache->is_rake_rotation_valid = false;
+
+ if (cache->first_time) {
+ copy_v3_v3(cache->rake_data.follow_co, grab_location);
+ }
+
+ if (sculpt_brush_needs_rake_rotation(brush)) {
+ cache->rake_data.follow_dist = cache->radius * SCULPT_RAKE_BRUSH_FACTOR;
+
+ if (!is_zero_v3(cache->grab_delta)) {
+ const float eps = 0.00001f;
+
+ float v1[3], v2[3];
+
+ copy_v3_v3(v1, cache->rake_data.follow_co);
+ copy_v3_v3(v2, cache->rake_data.follow_co);
+ sub_v3_v3(v2, cache->grab_delta);
+
+ sub_v3_v3(v1, grab_location);
+ sub_v3_v3(v2, grab_location);
+
+ 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)) ?
+ 1.0f :
+ sqrtf(rake_dist_sq) / cache->rake_data.follow_dist;
+
+ float axis[3], angle;
+ float tquat[4];
+
+ rotation_between_vecs_to_quat(tquat, v1, v2);
+
+ /* use axis-angle to scale rotation since the factor may be above 1 */
+ quat_to_axis_angle(axis, &angle, tquat);
+ normalize_v3(axis);
+
+ angle *= brush->rake_factor * rake_fade;
+ axis_angle_normalized_to_quat(cache->rake_rotation, axis, angle);
+ cache->is_rake_rotation_valid = true;
+ }
+ }
+ sculpt_rake_data_update(&cache->rake_data, grab_location);
+ }
+ }
}
/* 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);
- UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
- SculptSession *ss = ob->sculpt;
- 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))
- )
- {
- 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 */
- 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 */
- if (cache->first_time) {
- if (!BKE_brush_use_locked_size(scene, brush)) {
- cache->initial_radius = paint_calc_object_space_radius(cache->vc,
- cache->true_location,
- BKE_brush_size_get(scene, brush));
- BKE_brush_unprojected_radius_set(scene, brush, cache->initial_radius);
- }
- else {
- cache->initial_radius = BKE_brush_unprojected_radius_get(scene, brush);
- }
- }
-
- if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, PAINT_MODE_SCULPT)) {
- cache->radius = cache->initial_radius * cache->pressure;
- }
- else {
- cache->radius = cache->initial_radius;
- }
-
- 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 */
- if (brush->flag & BRUSH_EDGE_TO_EDGE) {
- RNA_float_get_array(ptr, "location", cache->true_location);
- }
-
- cache->radius = paint_calc_object_space_radius(cache->vc,
- cache->true_location,
- ups->pixel_radius);
- cache->radius_squared = cache->radius * cache->radius;
-
- copy_v3_v3(cache->anchored_location, cache->true_location);
- }
-
- sculpt_update_brush_delta(ups, ob, brush);
-
- if (brush->sculpt_tool == SCULPT_TOOL_ROTATE) {
- cache->vertex_rotation = -BLI_dial_angle(cache->dial, cache->mouse) * cache->bstrength;
-
- ups->draw_anchored = true;
- copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse);
- copy_v3_v3(cache->anchored_location, cache->true_location);
- ups->anchored_size = ups->pixel_radius;
- }
-
- cache->special_rotation = ups->brush_rotation;
+static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, PointerRNA *ptr)
+{
+ Scene *scene = CTX_data_scene(C);
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+ SculptSession *ss = ob->sculpt;
+ 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))) {
+ 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 */
+ 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 */
+ if (cache->first_time) {
+ if (!BKE_brush_use_locked_size(scene, brush)) {
+ cache->initial_radius = paint_calc_object_space_radius(
+ cache->vc, cache->true_location, BKE_brush_size_get(scene, brush));
+ BKE_brush_unprojected_radius_set(scene, brush, cache->initial_radius);
+ }
+ else {
+ cache->initial_radius = BKE_brush_unprojected_radius_get(scene, brush);
+ }
+ }
+
+ if (BKE_brush_use_size_pressure(scene, brush) &&
+ paint_supports_dynamic_size(brush, PAINT_MODE_SCULPT)) {
+ cache->radius = cache->initial_radius * cache->pressure;
+ }
+ else {
+ cache->radius = cache->initial_radius;
+ }
+
+ 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 */
+ if (brush->flag & BRUSH_EDGE_TO_EDGE) {
+ RNA_float_get_array(ptr, "location", cache->true_location);
+ }
+
+ cache->radius = paint_calc_object_space_radius(
+ cache->vc, cache->true_location, ups->pixel_radius);
+ cache->radius_squared = cache->radius * cache->radius;
+
+ copy_v3_v3(cache->anchored_location, cache->true_location);
+ }
+
+ sculpt_update_brush_delta(ups, ob, brush);
+
+ if (brush->sculpt_tool == SCULPT_TOOL_ROTATE) {
+ cache->vertex_rotation = -BLI_dial_angle(cache->dial, cache->mouse) * cache->bstrength;
+
+ ups->draw_anchored = true;
+ copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse);
+ copy_v3_v3(cache->anchored_location, cache->true_location);
+ ups->anchored_size = ups->pixel_radius;
+ }
+
+ cache->special_rotation = ups->brush_rotation;
}
/* 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_any_smooth_mode(const Brush *brush,
- StrokeCache *cache,
- int stroke_mode)
+static bool sculpt_any_smooth_mode(const Brush *brush, StrokeCache *cache, int stroke_mode)
{
- return ((stroke_mode == BRUSH_STROKE_SMOOTH) ||
- (cache && 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)));
+ return ((stroke_mode == BRUSH_STROKE_SMOOTH) || (cache && 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)));
}
static void sculpt_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *brush)
{
- SculptSession *ss = ob->sculpt;
+ SculptSession *ss = ob->sculpt;
- if (ss->kb || ss->modifiers_active) {
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Sculpt *sd = scene->toolsettings->sculpt;
- bool need_pmap = sculpt_any_smooth_mode(brush, ss->cache, 0);
- BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, need_pmap, false);
- }
+ if (ss->kb || ss->modifiers_active) {
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Sculpt *sd = scene->toolsettings->sculpt;
+ bool need_pmap = sculpt_any_smooth_mode(brush, ss->cache, 0);
+ BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, need_pmap, false);
+ }
}
static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
{
- if (BKE_pbvh_node_get_tmin(node) < *tmin) {
- SculptRaycastData *srd = data_v;
- float (*origco)[3] = NULL;
- bool use_origco = false;
-
- if (srd->original && srd->ss->cache) {
- if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) {
- use_origco = true;
- }
- else {
- /* 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;
- }
- }
-
- if (BKE_pbvh_node_raycast(srd->ss->pbvh, node, origco, use_origco,
- srd->ray_start, srd->ray_normal, &srd->depth))
- {
- srd->hit = 1;
- *tmin = srd->depth;
- }
- }
+ if (BKE_pbvh_node_get_tmin(node) < *tmin) {
+ SculptRaycastData *srd = data_v;
+ float(*origco)[3] = NULL;
+ bool use_origco = false;
+
+ if (srd->original && srd->ss->cache) {
+ if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) {
+ use_origco = true;
+ }
+ else {
+ /* 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;
+ }
+ }
+
+ if (BKE_pbvh_node_raycast(srd->ss->pbvh,
+ node,
+ origco,
+ use_origco,
+ srd->ray_start,
+ srd->ray_normal,
+ &srd->depth)) {
+ srd->hit = 1;
+ *tmin = srd->depth;
+ }
+ }
}
static void sculpt_find_nearest_to_ray_cb(PBVHNode *node, void *data_v, float *tmin)
{
- if (BKE_pbvh_node_get_tmin(node) < *tmin) {
- SculptFindNearestToRayData *srd = data_v;
- float (*origco)[3] = NULL;
- bool use_origco = false;
-
- if (srd->original && srd->ss->cache) {
- if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) {
- use_origco = true;
- }
- else {
- /* 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;
- }
- }
-
- if (BKE_pbvh_node_find_nearest_to_ray(
- srd->ss->pbvh, node, origco, use_origco,
- srd->ray_start, srd->ray_normal,
- &srd->depth, &srd->dist_sq_to_ray))
- {
- srd->hit = 1;
- *tmin = srd->dist_sq_to_ray;
- }
- }
+ if (BKE_pbvh_node_get_tmin(node) < *tmin) {
+ SculptFindNearestToRayData *srd = data_v;
+ float(*origco)[3] = NULL;
+ bool use_origco = false;
+
+ if (srd->original && srd->ss->cache) {
+ if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) {
+ use_origco = true;
+ }
+ else {
+ /* 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;
+ }
+ }
+
+ if (BKE_pbvh_node_find_nearest_to_ray(srd->ss->pbvh,
+ node,
+ origco,
+ use_origco,
+ srd->ray_start,
+ srd->ray_normal,
+ &srd->depth,
+ &srd->dist_sq_to_ray)) {
+ srd->hit = 1;
+ *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->ray_normal,
- &srd->depth, &srd->edge_length))
- {
- srd->hit = 1;
- *tmin = srd->depth;
- }
- }
+ if (BKE_pbvh_node_get_tmin(node) < *tmin) {
+ SculptDetailRaycastData *srd = data_v;
+ if (BKE_pbvh_bmesh_node_raycast_detail(
+ node, srd->ray_start, srd->ray_normal, &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)
+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 obimat[4][4];
- float dist;
- Object *ob = vc->obact;
- RegionView3D *rv3d = vc->ar->regiondata;
+ float obimat[4][4];
+ float dist;
+ Object *ob = vc->obact;
+ RegionView3D *rv3d = vc->ar->regiondata;
- /* 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);
+ /* 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);
- invert_m4_m4(obimat, ob->obmat);
- mul_m4_v3(obimat, ray_start);
- mul_m4_v3(obimat, ray_end);
+ invert_m4_m4(obimat, ob->obmat);
+ mul_m4_v3(obimat, ray_start);
+ mul_m4_v3(obimat, ray_end);
- sub_v3_v3v3(ray_normal, ray_end, ray_start);
- dist = normalize_v3(ray_normal);
+ sub_v3_v3v3(ray_normal, ray_end, ray_start);
+ dist = normalize_v3(ray_normal);
- if ((rv3d->is_persp == false) &&
- /* if the ray is clipped, don't adjust its start/end */
- ((rv3d->rflag & RV3D_CLIPPING) == 0))
- {
- BKE_pbvh_raycast_project_ray_root(ob->sculpt->pbvh, original, ray_start, ray_end, ray_normal);
+ if ((rv3d->is_persp == false) &&
+ /* if the ray is clipped, don't adjust its start/end */
+ ((rv3d->rflag & RV3D_CLIPPING) == 0)) {
+ BKE_pbvh_raycast_project_ray_root(ob->sculpt->pbvh, original, ray_start, ray_end, ray_normal);
- /* recalculate the normal */
- sub_v3_v3v3(ray_normal, ray_end, ray_start);
- dist = normalize_v3(ray_normal);
- }
+ /* recalculate the normal */
+ sub_v3_v3v3(ray_normal, ray_end, ray_start);
+ dist = normalize_v3(ray_normal);
+ }
- return dist;
+ return dist;
}
/* Do a raycast in the tree to find the 3d brush location
@@ -4916,859 +4942,887 @@ static float sculpt_raycast_init(
*/
bool sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
{
- Object *ob;
- SculptSession *ss;
- StrokeCache *cache;
- float ray_start[3], ray_end[3], ray_normal[3], depth;
- bool original;
- ViewContext vc;
-
- ED_view3d_viewcontext_init(C, &vc);
-
- ob = vc.obact;
-
- ss = ob->sculpt;
- cache = ss->cache;
- original = (cache) ? cache->original : 0;
-
- const Brush *brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
-
- sculpt_stroke_modifiers_check(C, ob, brush);
-
- depth = sculpt_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, original);
-
- bool hit = false;
- {
- SculptRaycastData srd = {
- .original = original,
- .ss = ob->sculpt,
- .hit = 0,
- .ray_start = ray_start,
- .ray_normal = ray_normal,
- .depth = depth,
- };
- BKE_pbvh_raycast(
- ss->pbvh, sculpt_raycast_cb, &srd,
- ray_start, ray_normal, srd.original);
- if (srd.hit) {
- hit = true;
- copy_v3_v3(out, ray_normal);
- mul_v3_fl(out, srd.depth);
- add_v3_v3(out, ray_start);
- }
- }
-
- if (hit == false) {
- if (ELEM(brush->falloff_shape, PAINT_FALLOFF_SHAPE_TUBE)) {
- SculptFindNearestToRayData srd = {
- .original = original,
- .ss = ob->sculpt,
- .hit = 0,
- .ray_start = ray_start,
- .ray_normal = ray_normal,
- .depth = FLT_MAX,
- .dist_sq_to_ray = FLT_MAX,
- };
- BKE_pbvh_find_nearest_to_ray(
- ss->pbvh, sculpt_find_nearest_to_ray_cb, &srd,
- ray_start, ray_normal, srd.original);
- if (srd.hit) {
- hit = true;
- copy_v3_v3(out, ray_normal);
- mul_v3_fl(out, srd.depth);
- add_v3_v3(out, ray_start);
- }
- }
- }
-
- if (cache && hit) {
- copy_v3_v3(cache->true_location, out);
- }
-
- return hit;
+ Object *ob;
+ SculptSession *ss;
+ StrokeCache *cache;
+ float ray_start[3], ray_end[3], ray_normal[3], depth;
+ bool original;
+ ViewContext vc;
+
+ ED_view3d_viewcontext_init(C, &vc);
+
+ ob = vc.obact;
+
+ ss = ob->sculpt;
+ cache = ss->cache;
+ original = (cache) ? cache->original : 0;
+
+ const Brush *brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
+
+ sculpt_stroke_modifiers_check(C, ob, brush);
+
+ depth = sculpt_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, original);
+
+ bool hit = false;
+ {
+ SculptRaycastData srd = {
+ .original = original,
+ .ss = ob->sculpt,
+ .hit = 0,
+ .ray_start = ray_start,
+ .ray_normal = ray_normal,
+ .depth = depth,
+ };
+ BKE_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd, ray_start, ray_normal, srd.original);
+ if (srd.hit) {
+ hit = true;
+ copy_v3_v3(out, ray_normal);
+ mul_v3_fl(out, srd.depth);
+ add_v3_v3(out, ray_start);
+ }
+ }
+
+ if (hit == false) {
+ if (ELEM(brush->falloff_shape, PAINT_FALLOFF_SHAPE_TUBE)) {
+ SculptFindNearestToRayData srd = {
+ .original = original,
+ .ss = ob->sculpt,
+ .hit = 0,
+ .ray_start = ray_start,
+ .ray_normal = ray_normal,
+ .depth = FLT_MAX,
+ .dist_sq_to_ray = FLT_MAX,
+ };
+ BKE_pbvh_find_nearest_to_ray(
+ ss->pbvh, sculpt_find_nearest_to_ray_cb, &srd, ray_start, ray_normal, srd.original);
+ if (srd.hit) {
+ hit = true;
+ copy_v3_v3(out, ray_normal);
+ mul_v3_fl(out, srd.depth);
+ add_v3_v3(out, ray_start);
+ }
+ }
+ }
+
+ if (cache && hit) {
+ copy_v3_v3(cache->true_location, out);
+ }
+
+ return hit;
}
static void sculpt_brush_init_tex(const Scene *scene, Sculpt *sd, SculptSession *ss)
{
- Brush *brush = BKE_paint_brush(&sd->paint);
- MTex *mtex = &brush->mtex;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ MTex *mtex = &brush->mtex;
- /* init mtex nodes */
- if (mtex->tex && mtex->tex->nodetree) {
- /* has internal flag to detect it only does it once */
- ntreeTexBeginExecTree(mtex->tex->nodetree);
- }
+ /* init mtex nodes */
+ if (mtex->tex && mtex->tex->nodetree) {
+ /* 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. */
- sculpt_update_tex(scene, sd, ss);
+ /* 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);
}
static void sculpt_brush_stroke_init(bContext *C, wmOperator *op)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- SculptSession *ss = CTX_data_active_object(C)->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
- int mode = RNA_enum_get(op->ptr, "mode");
- bool is_smooth;
- bool need_mask = false;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ SculptSession *ss = CTX_data_active_object(C)->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ int mode = RNA_enum_get(op->ptr, "mode");
+ bool is_smooth;
+ bool need_mask = false;
- if (brush->sculpt_tool == SCULPT_TOOL_MASK) {
- need_mask = true;
- }
+ if (brush->sculpt_tool == SCULPT_TOOL_MASK) {
+ need_mask = true;
+ }
- view3d_operator_needs_opengl(C);
- sculpt_brush_init_tex(scene, sd, ss);
+ view3d_operator_needs_opengl(C);
+ sculpt_brush_init_tex(scene, sd, ss);
- is_smooth = sculpt_any_smooth_mode(brush, NULL, mode);
- BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, is_smooth, need_mask);
+ is_smooth = sculpt_any_smooth_mode(brush, NULL, mode);
+ BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, 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);
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
- /* Restore the mesh before continuing with anchored stroke */
- if ((brush->flag & BRUSH_ANCHORED) ||
- (brush->sculpt_tool == SCULPT_TOOL_GRAB &&
- BKE_brush_use_size_pressure(ss->cache->vc->scene, brush)) ||
- (brush->flag & BRUSH_DRAG_DOT))
- {
- paint_mesh_restore_co(sd, ob);
- }
+ /* Restore the mesh before continuing with anchored stroke */
+ if ((brush->flag & BRUSH_ANCHORED) ||
+ (brush->sculpt_tool == SCULPT_TOOL_GRAB &&
+ BKE_brush_use_size_pressure(ss->cache->vc->scene, brush)) ||
+ (brush->flag & BRUSH_DRAG_DOT)) {
+ paint_mesh_restore_co(sd, 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];
+ if (ob->runtime.bb) {
+ float bb_min[3], bb_max[3];
- BKE_pbvh_bounding_box(ob->sculpt->pbvh, bb_min, bb_max);
- BKE_boundbox_init_from_minmax(ob->runtime.bb, bb_min, bb_max);
- }
+ BKE_pbvh_bounding_box(ob->sculpt->pbvh, bb_min, bb_max);
+ BKE_boundbox_init_from_minmax(ob->runtime.bb, bb_min, bb_max);
+ }
}
static void sculpt_flush_update(bContext *C)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *ob = CTX_data_active_object(C);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- SculptSession *ss = ob->sculpt;
- ARegion *ar = CTX_wm_region(C);
- bScreen *screen = CTX_wm_screen(C);
- MultiresModifierData *mmd = ss->multires;
-
- if (mmd != NULL) {
- /* NOTE: SubdivCCG is living in the evaluated object. */
- multires_mark_as_modified(ob_eval, MULTIRES_COORDS_MODIFIED);
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
-
- bool use_shaded_mode = false;
- if (mmd || (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH)) {
- /* Multres or dyntopo are drawn directly by EEVEE,
- * no need for hacks in this case. */
- }
- else {
- /* We search if an area of the current window is in lookdev/rendered
- * display mode. In this case, for changes to show up, we need to
- * tag for ID_RECALC_GEOMETRY. */
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- if (v3d->shading.type > OB_SOLID) {
- use_shaded_mode = true;
- }
- }
- }
- }
- }
-
- if (ss->kb || ss->modifiers_active || use_shaded_mode) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- ED_region_tag_redraw(ar);
- }
- else {
- rcti r;
-
- BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB, NULL);
- /* 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);
-
- if (sculpt_get_redraw_rect(ar, 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 += ar->winrct.xmin - 2;
- r.xmax += ar->winrct.xmin + 2;
- r.ymin += ar->winrct.ymin - 2;
- r.ymax += ar->winrct.ymin + 2;
-
- ss->partial_redraw = 1;
- ED_region_tag_redraw_partial(ar, &r);
- }
- }
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob = CTX_data_active_object(C);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ SculptSession *ss = ob->sculpt;
+ ARegion *ar = CTX_wm_region(C);
+ bScreen *screen = CTX_wm_screen(C);
+ MultiresModifierData *mmd = ss->multires;
+
+ if (mmd != NULL) {
+ /* NOTE: SubdivCCG is living in the evaluated object. */
+ multires_mark_as_modified(ob_eval, MULTIRES_COORDS_MODIFIED);
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
+
+ bool use_shaded_mode = false;
+ if (mmd || (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH)) {
+ /* Multres or dyntopo are drawn directly by EEVEE,
+ * no need for hacks in this case. */
+ }
+ else {
+ /* We search if an area of the current window is in lookdev/rendered
+ * display mode. In this case, for changes to show up, we need to
+ * tag for ID_RECALC_GEOMETRY. */
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ if (v3d->shading.type > OB_SOLID) {
+ use_shaded_mode = true;
+ }
+ }
+ }
+ }
+ }
+
+ if (ss->kb || ss->modifiers_active || use_shaded_mode) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ ED_region_tag_redraw(ar);
+ }
+ else {
+ rcti r;
+
+ BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB, NULL);
+ /* 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);
+
+ if (sculpt_get_redraw_rect(ar, 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 += ar->winrct.xmin - 2;
+ r.xmax += ar->winrct.xmin + 2;
+ r.ymin += ar->winrct.ymin - 2;
+ r.ymax += ar->winrct.ymin + 2;
+
+ ss->partial_redraw = 1;
+ ED_region_tag_redraw_partial(ar, &r);
+ }
+ }
}
/* Returns whether the mouse/stylus is over the mesh (1)
* or over the background (0) */
static bool over_mesh(bContext *C, struct wmOperator *UNUSED(op), float x, float y)
{
- float mouse[2], co[3];
+ float mouse[2], co[3];
- mouse[0] = x;
- mouse[1] = y;
+ 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])
+static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const float mouse[2])
{
- /* Don't start the stroke until mouse goes over the mesh.
- * note: mouse will only be null when re-executing the saved stroke.
- * We have exception for 'exec' strokes since they may not set 'mouse',
- * only 'location', see: T52195. */
- if (((op->flag & OP_IS_INVOKE) == 0) ||
- (mouse == NULL) || over_mesh(C, op, mouse[0], mouse[1]))
- {
- Object *ob = CTX_data_active_object(C);
- SculptSession *ss = ob->sculpt;
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ /* Don't start the stroke until mouse goes over the mesh.
+ * note: mouse will only be null when re-executing the saved stroke.
+ * We have exception for 'exec' strokes since they may not set 'mouse',
+ * only 'location', see: T52195. */
+ if (((op->flag & OP_IS_INVOKE) == 0) || (mouse == NULL) ||
+ over_mesh(C, op, mouse[0], mouse[1])) {
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- ED_view3d_init_mats_rv3d(ob, CTX_wm_region_view3d(C));
+ ED_view3d_init_mats_rv3d(ob, CTX_wm_region_view3d(C));
- sculpt_update_cache_invariants(C, sd, ss, op, mouse);
+ 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;
- }
- else
- return 0;
+ return 1;
+ }
+ else
+ return 0;
}
-static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *UNUSED(stroke), PointerRNA *itemptr)
+static void sculpt_stroke_update_step(bContext *C,
+ struct PaintStroke *UNUSED(stroke),
+ PointerRNA *itemptr)
{
- UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- Object *ob = CTX_data_active_object(C);
- SculptSession *ss = ob->sculpt;
- const Brush *brush = BKE_paint_brush(&sd->paint);
+ UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ const Brush *brush = BKE_paint_brush(&sd->paint);
- sculpt_stroke_modifiers_check(C, ob, brush);
- sculpt_update_cache_variants(C, sd, ob, itemptr);
- sculpt_restore_mesh(sd, ob);
+ sculpt_stroke_modifiers_check(C, ob, brush);
+ sculpt_update_cache_variants(C, sd, ob, itemptr);
+ sculpt_restore_mesh(sd, ob);
- if (sd->flags & (SCULPT_DYNTOPO_DETAIL_CONSTANT | SCULPT_DYNTOPO_DETAIL_MANUAL)) {
- 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);
- }
- else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) {
- BKE_pbvh_bmesh_detail_size_set(ss->pbvh, ss->cache->radius * sd->detail_percent / 100.0f);
- }
- else {
- BKE_pbvh_bmesh_detail_size_set(
- ss->pbvh,
- (ss->cache->radius /
- (float)ups->pixel_radius) *
- (float)(sd->detail_size * U.pixelsize) / 0.4f);
- }
+ if (sd->flags & (SCULPT_DYNTOPO_DETAIL_CONSTANT | SCULPT_DYNTOPO_DETAIL_MANUAL)) {
+ 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);
+ }
+ else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) {
+ BKE_pbvh_bmesh_detail_size_set(ss->pbvh, ss->cache->radius * sd->detail_percent / 100.0f);
+ }
+ else {
+ BKE_pbvh_bmesh_detail_size_set(ss->pbvh,
+ (ss->cache->radius / (float)ups->pixel_radius) *
+ (float)(sd->detail_size * U.pixelsize) / 0.4f);
+ }
- if (sculpt_stroke_is_dynamic_topology(ss, brush)) {
- do_symmetrical_brush_actions(sd, ob, sculpt_topology_update, ups);
- }
+ 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);
+ do_symmetrical_brush_actions(sd, ob, do_brush_action, ups);
- sculpt_combine_proxies(sd, ob);
+ sculpt_combine_proxies(sd, ob);
- /* hack to fix noise texture tearing mesh */
- sculpt_fix_noise_tear(sd, ob);
+ /* hack to fix noise texture tearing mesh */
+ sculpt_fix_noise_tear(sd, ob);
- /* TODO(sergey): This is not really needed for the solid shading,
- * which does use pBVH drawing anyway, but texture and wireframe
- * requires this.
- *
- * Could be optimized later, but currently don't think it's so
- * much common scenario.
- *
- * Same applies to the DEG_id_tag_update() invoked from
- * sculpt_flush_update().
- */
- if (ss->modifiers_active) {
- sculpt_flush_stroke_deform(sd, ob);
- }
- else if (ss->kb) {
- sculpt_update_keyblock(ob);
- }
+ /* TODO(sergey): This is not really needed for the solid shading,
+ * which does use pBVH drawing anyway, but texture and wireframe
+ * requires this.
+ *
+ * Could be optimized later, but currently don't think it's so
+ * much common scenario.
+ *
+ * Same applies to the DEG_id_tag_update() invoked from
+ * sculpt_flush_update().
+ */
+ if (ss->modifiers_active) {
+ sculpt_flush_stroke_deform(sd, ob);
+ }
+ else if (ss->kb) {
+ sculpt_update_keyblock(ob);
+ }
- ss->cache->first_time = false;
+ ss->cache->first_time = false;
- /* Cleanup */
- sculpt_flush_update(C);
+ /* Cleanup */
+ sculpt_flush_update(C);
}
static void sculpt_brush_exit_tex(Sculpt *sd)
{
- Brush *brush = BKE_paint_brush(&sd->paint);
- MTex *mtex = &brush->mtex;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ MTex *mtex = &brush->mtex;
- if (mtex->tex && mtex->tex->nodetree)
- ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
+ if (mtex->tex && mtex->tex->nodetree)
+ ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
}
static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(stroke))
{
- Main *bmain = CTX_data_main(C);
- Object *ob = CTX_data_active_object(C);
- Scene *scene = CTX_data_scene(C);
- SculptSession *ss = ob->sculpt;
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+ SculptSession *ss = ob->sculpt;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- /* 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;
+ /* 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 */
- if (ss->cache->alt_smooth) {
- if (brush->sculpt_tool == SCULPT_TOOL_MASK) {
- brush->mask_tool = ss->cache->saved_mask_brush_tool;
- }
- else {
- BKE_brush_size_set(scene, brush, ss->cache->saved_smooth_size);
- brush = (Brush *)BKE_libblock_find_name(bmain, ID_BR, ss->cache->saved_active_brush_name);
- if (brush) {
- BKE_paint_brush_set(&sd->paint, brush);
- }
- }
- }
+ /* Alt-Smooth */
+ if (ss->cache->alt_smooth) {
+ if (brush->sculpt_tool == SCULPT_TOOL_MASK) {
+ brush->mask_tool = ss->cache->saved_mask_brush_tool;
+ }
+ else {
+ BKE_brush_size_set(scene, brush, ss->cache->saved_smooth_size);
+ brush = (Brush *)BKE_libblock_find_name(bmain, ID_BR, ss->cache->saved_active_brush_name);
+ if (brush) {
+ BKE_paint_brush_set(&sd->paint, brush);
+ }
+ }
+ }
- sculpt_cache_free(ss->cache);
- ss->cache = NULL;
+ sculpt_cache_free(ss->cache);
+ ss->cache = NULL;
- sculpt_undo_push_end();
+ sculpt_undo_push_end();
- BKE_pbvh_update(ss->pbvh, PBVH_UpdateOriginalBB, NULL);
+ BKE_pbvh_update(ss->pbvh, PBVH_UpdateOriginalBB, NULL);
- if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH)
- BKE_pbvh_bmesh_after_stroke(ss->pbvh);
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH)
+ BKE_pbvh_bmesh_after_stroke(ss->pbvh);
- /* 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 */
- if (ss->kb && !ss->modifiers_active) sculpt_update_keyblock(ob);
+ /* 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 */
+ if (ss->kb && !ss->modifiers_active)
+ sculpt_update_keyblock(ob);
- ss->partial_redraw = 0;
+ ss->partial_redraw = 0;
- /* try to avoid calling this, only for e.g. linked duplicates now */
- if (((Mesh *)ob->data)->id.us > 1)
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ /* try to avoid calling this, only for e.g. linked duplicates now */
+ if (((Mesh *)ob->data)->id.us > 1)
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- }
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
- sculpt_brush_exit_tex(sd);
+ sculpt_brush_exit_tex(sd);
}
static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- struct PaintStroke *stroke;
- int ignore_background_click;
- int retval;
+ struct PaintStroke *stroke;
+ int ignore_background_click;
+ int retval;
- sculpt_brush_stroke_init(C, op);
+ sculpt_brush_stroke_init(C, op);
- stroke = paint_stroke_new(C, op, sculpt_stroke_get_location,
- sculpt_stroke_test_start,
- sculpt_stroke_update_step, NULL,
- sculpt_stroke_done, event->type);
+ stroke = paint_stroke_new(C,
+ op,
+ sculpt_stroke_get_location,
+ sculpt_stroke_test_start,
+ sculpt_stroke_update_step,
+ NULL,
+ sculpt_stroke_done,
+ event->type);
- op->customdata = stroke;
+ op->customdata = stroke;
- /* For tablet rotation */
- ignore_background_click = RNA_boolean_get(op->ptr, "ignore_background_click");
+ /* 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)) {
- paint_stroke_data_free(op);
- return OPERATOR_PASS_THROUGH;
- }
+ if (ignore_background_click && !over_mesh(C, op, event->x, event->y)) {
+ paint_stroke_data_free(op);
+ return OPERATOR_PASS_THROUGH;
+ }
- if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
- paint_stroke_data_free(op);
- return OPERATOR_FINISHED;
- }
- /* add modal handler */
- WM_event_add_modal_handler(C, op);
+ if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
+ paint_stroke_data_free(op);
+ return OPERATOR_FINISHED;
+ }
+ /* add modal handler */
+ WM_event_add_modal_handler(C, op);
- OPERATOR_RETVAL_CHECK(retval);
- BLI_assert(retval == OPERATOR_RUNNING_MODAL);
+ OPERATOR_RETVAL_CHECK(retval);
+ BLI_assert(retval == OPERATOR_RUNNING_MODAL);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static int sculpt_brush_stroke_exec(bContext *C, wmOperator *op)
{
- sculpt_brush_stroke_init(C, op);
+ sculpt_brush_stroke_init(C, op);
- op->customdata = paint_stroke_new(C, op, sculpt_stroke_get_location, sculpt_stroke_test_start,
- sculpt_stroke_update_step, NULL, sculpt_stroke_done, 0);
+ op->customdata = paint_stroke_new(C,
+ op,
+ sculpt_stroke_get_location,
+ sculpt_stroke_test_start,
+ sculpt_stroke_update_step,
+ NULL,
+ sculpt_stroke_done,
+ 0);
- /* frees op->customdata */
- paint_stroke_exec(C, op);
+ /* frees op->customdata */
+ paint_stroke_exec(C, op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void sculpt_brush_stroke_cancel(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
- SculptSession *ss = ob->sculpt;
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- const Brush *brush = BKE_paint_brush(&sd->paint);
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ const Brush *brush = BKE_paint_brush(&sd->paint);
- /* 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)) {
- paint_mesh_restore_co(sd, ob);
- }
+ /* 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)) {
+ paint_mesh_restore_co(sd, ob);
+ }
- paint_stroke_cancel(C, op);
+ paint_stroke_cancel(C, op);
- if (ss->cache) {
- sculpt_cache_free(ss->cache);
- ss->cache = NULL;
- }
+ if (ss->cache) {
+ sculpt_cache_free(ss->cache);
+ ss->cache = NULL;
+ }
- sculpt_brush_exit_tex(sd);
+ sculpt_brush_exit_tex(sd);
}
static void SCULPT_OT_brush_stroke(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Sculpt";
- ot->idname = "SCULPT_OT_brush_stroke";
- ot->description = "Sculpt a stroke into the geometry";
+ /* identifiers */
+ ot->name = "Sculpt";
+ ot->idname = "SCULPT_OT_brush_stroke";
+ ot->description = "Sculpt a stroke into the geometry";
- /* api callbacks */
- ot->invoke = sculpt_brush_stroke_invoke;
- ot->modal = paint_stroke_modal;
- ot->exec = sculpt_brush_stroke_exec;
- ot->poll = sculpt_poll;
- ot->cancel = sculpt_brush_stroke_cancel;
+ /* api callbacks */
+ ot->invoke = sculpt_brush_stroke_invoke;
+ ot->modal = paint_stroke_modal;
+ ot->exec = sculpt_brush_stroke_exec;
+ ot->poll = sculpt_poll;
+ ot->cancel = sculpt_brush_stroke_cancel;
- /* flags (sculpt does own undo? (ton) */
- ot->flag = OPTYPE_BLOCKING;
+ /* flags (sculpt does own undo? (ton) */
+ ot->flag = OPTYPE_BLOCKING;
- /* properties */
+ /* properties */
- paint_stroke_operator_properties(ot);
+ paint_stroke_operator_properties(ot);
- RNA_def_boolean(ot->srna, "ignore_background_click", 0,
- "Ignore Background Click",
- "Clicks on the background do not start the stroke");
+ RNA_def_boolean(ot->srna,
+ "ignore_background_click",
+ 0,
+ "Ignore Background Click",
+ "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) */
static int sculpt_set_persistent_base_exec(bContext *C, wmOperator *UNUSED(op))
{
- SculptSession *ss = CTX_data_active_object(C)->sculpt;
+ SculptSession *ss = CTX_data_active_object(C)->sculpt;
- if (ss) {
- if (ss->layer_co)
- MEM_freeN(ss->layer_co);
- ss->layer_co = NULL;
- }
+ if (ss) {
+ if (ss->layer_co)
+ MEM_freeN(ss->layer_co);
+ ss->layer_co = NULL;
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SCULPT_OT_set_persistent_base(wmOperatorType *ot)
{
- /* 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";
+ /* 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 */
- ot->exec = sculpt_set_persistent_base_exec;
- ot->poll = sculpt_mode_poll;
+ /* api callbacks */
+ ot->exec = sculpt_set_persistent_base_exec;
+ ot->poll = sculpt_mode_poll;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ 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);
- }
+ 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;
+ SculptSession *ss = ob->sculpt;
- /* Clear out any existing DM and PBVH */
- if (ss->pbvh) {
- BKE_pbvh_free(ss->pbvh);
- }
- ss->pbvh = NULL;
- BKE_object_free_derived_caches(ob);
+ /* Clear out any existing DM and PBVH */
+ if (ss->pbvh) {
+ BKE_pbvh_free(ss->pbvh);
+ }
+ ss->pbvh = NULL;
+ BKE_object_free_derived_caches(ob);
}
void sculpt_dyntopo_node_layers_add(SculptSession *ss)
{
- int cd_node_layer_index;
+ int cd_node_layer_index;
- char layer_id[] = "_dyntopo_node_id";
+ 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);
- }
+ 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->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;
+ 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);
- }
+ 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->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;
+ ss->bm->pdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY;
}
-
-void sculpt_update_after_dynamic_topology_toggle(
- Depsgraph *depsgraph,
- Scene *scene, Object *ob)
+void sculpt_update_after_dynamic_topology_toggle(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- Sculpt *sd = scene->toolsettings->sculpt;
+ Sculpt *sd = scene->toolsettings->sculpt;
- /* Create the PBVH */
- BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, false);
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
+ /* Create the PBVH */
+ BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, false);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
}
-void sculpt_dynamic_topology_enable_ex(
- Depsgraph *depsgraph,
- Scene *scene, Object *ob)
+void sculpt_dynamic_topology_enable_ex(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- SculptSession *ss = ob->sculpt;
- Mesh *me = ob->data;
- const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me);
+ SculptSession *ss = ob->sculpt;
+ Mesh *me = ob->data;
+ const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me);
- sculpt_pbvh_clear(ob);
+ sculpt_pbvh_clear(ob);
- ss->bm_smooth_shading = (scene->toolsettings->sculpt->flags & SCULPT_DYNTOPO_SMOOTH_SHADING) != 0;
+ 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);
+ /* 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,}));
+ /* 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);
- }
+ 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 dynamic topology */
+ me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
- /* Enable logging for undo/redo */
- ss->bm_log = BM_log_create(ss->bm);
+ /* Enable logging for undo/redo */
+ ss->bm_log = BM_log_create(ss->bm);
- /* Refresh */
- sculpt_update_after_dynamic_topology_toggle(depsgraph, scene, ob);
+ /* Refresh */
+ sculpt_update_after_dynamic_topology_toggle(depsgraph, scene, ob);
}
/* 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 */
-void sculpt_dynamic_topology_disable_ex(
- 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->bm_enter_totvert;
- me->totloop = unode->bm_enter_totloop;
- me->totpoly = unode->bm_enter_totpoly;
- me->totedge = unode->bm_enter_totedge;
- me->totface = 0;
- CustomData_copy(&unode->bm_enter_vdata, &me->vdata, CD_MASK_MESH.vmask,
- CD_DUPLICATE, unode->bm_enter_totvert);
- CustomData_copy(&unode->bm_enter_edata, &me->edata, CD_MASK_MESH.emask,
- CD_DUPLICATE, unode->bm_enter_totedge);
- CustomData_copy(&unode->bm_enter_ldata, &me->ldata, CD_MASK_MESH.lmask,
- CD_DUPLICATE, unode->bm_enter_totloop);
- CustomData_copy(&unode->bm_enter_pdata, &me->pdata, CD_MASK_MESH.pmask,
- CD_DUPLICATE, unode->bm_enter_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);
-
- /* Refresh */
- sculpt_update_after_dynamic_topology_toggle(depsgraph, scene, ob);
+void sculpt_dynamic_topology_disable_ex(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->bm_enter_totvert;
+ me->totloop = unode->bm_enter_totloop;
+ me->totpoly = unode->bm_enter_totpoly;
+ me->totedge = unode->bm_enter_totedge;
+ me->totface = 0;
+ CustomData_copy(&unode->bm_enter_vdata,
+ &me->vdata,
+ CD_MASK_MESH.vmask,
+ CD_DUPLICATE,
+ unode->bm_enter_totvert);
+ CustomData_copy(&unode->bm_enter_edata,
+ &me->edata,
+ CD_MASK_MESH.emask,
+ CD_DUPLICATE,
+ unode->bm_enter_totedge);
+ CustomData_copy(&unode->bm_enter_ldata,
+ &me->ldata,
+ CD_MASK_MESH.lmask,
+ CD_DUPLICATE,
+ unode->bm_enter_totloop);
+ CustomData_copy(&unode->bm_enter_pdata,
+ &me->pdata,
+ CD_MASK_MESH.pmask,
+ CD_DUPLICATE,
+ unode->bm_enter_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);
+
+ /* Refresh */
+ sculpt_update_after_dynamic_topology_toggle(depsgraph, scene, ob);
}
void sculpt_dynamic_topology_disable(bContext *C, SculptUndoNode *unode)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- sculpt_dynamic_topology_disable_ex(depsgraph, scene, ob, unode);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ sculpt_dynamic_topology_disable_ex(depsgraph, scene, ob, unode);
}
-static void sculpt_dynamic_topology_disable_with_undo(
- Depsgraph *depsgraph, Scene *scene, Object *ob)
+static void sculpt_dynamic_topology_disable_with_undo(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(depsgraph, scene, ob, NULL);
- sculpt_undo_push_end();
- }
+ 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(depsgraph, scene, ob, NULL);
+ sculpt_undo_push_end();
+ }
}
-static void sculpt_dynamic_topology_enable_with_undo(
- Depsgraph *depsgraph,
- Scene *scene, Object *ob)
+static void sculpt_dynamic_topology_enable_with_undo(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(depsgraph, scene, ob);
- sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
- sculpt_undo_push_end();
- }
+ SculptSession *ss = ob->sculpt;
+ if (ss->bm == NULL) {
+ sculpt_undo_push_begin("Dynamic topology enable");
+ sculpt_dynamic_topology_enable_ex(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))
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- SculptSession *ss = ob->sculpt;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
- WM_cursor_wait(1);
+ WM_cursor_wait(1);
- if (ss->bm) {
- sculpt_dynamic_topology_disable_with_undo(depsgraph, scene, ob);
- }
- else {
- sculpt_dynamic_topology_enable_with_undo(depsgraph, scene, ob);
- }
+ if (ss->bm) {
+ sculpt_dynamic_topology_disable_with_undo(depsgraph, scene, ob);
+ }
+ else {
+ sculpt_dynamic_topology_enable_with_undo(depsgraph, scene, ob);
+ }
- WM_cursor_wait(0);
+ WM_cursor_wait(0);
- return OPERATOR_FINISHED;
+ 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),
+ 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);
+ 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_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");
+ 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);
- }
+ 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);
+ uiItemFullO_ptr(layout, ot, IFACE_("OK"), ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, NULL);
- UI_popup_menu_end(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
static enum eDynTopoWarnFlag sculpt_dynamic_topology_check(Scene *scene, Object *ob)
{
- Mesh *me = ob->data;
- SculptSession *ss = ob->sculpt;
+ Mesh *me = ob->data;
+ SculptSession *ss = ob->sculpt;
- enum eDynTopoWarnFlag flag = 0;
+ enum eDynTopoWarnFlag flag = 0;
- BLI_assert(ss->bm == NULL);
- UNUSED_VARS_NDEBUG(ss);
+ 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;
- }
- }
- }
+ 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);
+ {
+ 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;
+ /* 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;
- }
- }
- }
+ if (mti->type == eModifierTypeType_Constructive) {
+ flag |= DYNTOPO_WARN_MODIFIER;
+ break;
+ }
+ }
+ }
- return flag;
+ return flag;
}
-static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+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;
+ 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 (!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);
- }
- }
+ 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);
+ 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";
+ /* 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;
+ /* 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;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************* SCULPT_OT_optimize *************************/
static int sculpt_optimize_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- sculpt_pbvh_clear(ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ sculpt_pbvh_clear(ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static bool sculpt_and_dynamic_topology_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- return sculpt_mode_poll(C) && ob->sculpt->bm;
+ return sculpt_mode_poll(C) && ob->sculpt->bm;
}
/* The BVH gets less optimal more quickly with dynamic topology than
@@ -5777,572 +5831,578 @@ static bool sculpt_and_dynamic_topology_poll(bContext *C)
* to recalculate it than toggling modes. */
static void SCULPT_OT_optimize(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Optimize";
- ot->idname = "SCULPT_OT_optimize";
- ot->description = "Recalculate the sculpt BVH to improve performance";
+ /* identifiers */
+ ot->name = "Optimize";
+ ot->idname = "SCULPT_OT_optimize";
+ ot->description = "Recalculate the sculpt BVH to improve performance";
- /* api callbacks */
- ot->exec = sculpt_optimize_exec;
- ot->poll = sculpt_and_dynamic_topology_poll;
+ /* api callbacks */
+ ot->exec = sculpt_optimize_exec;
+ ot->poll = sculpt_and_dynamic_topology_poll;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************* Dynamic topology symmetrize ********************/
static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = CTX_data_active_object(C);
- const Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- SculptSession *ss = ob->sculpt;
+ Object *ob = CTX_data_active_object(C);
+ const Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ SculptSession *ss = ob->sculpt;
- /* 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);
- BM_log_before_all_removed(ss->bm, ss->bm_log);
+ /* 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);
+ BM_log_before_all_removed(ss->bm, ss->bm_log);
- BM_mesh_toolflags_set(ss->bm, true);
+ BM_mesh_toolflags_set(ss->bm, true);
- /* 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);
+ /* 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);
- /* bisect operator flags edges (keep tags clean for edge queue) */
- BM_mesh_elem_hflag_disable_all(ss->bm, BM_EDGE, BM_ELEM_TAG, false);
+ /* 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);
+ BM_mesh_toolflags_set(ss->bm, false);
- /* Finish undo */
- BM_log_all_added(ss->bm, ss->bm_log);
- sculpt_undo_push_end();
+ /* Finish undo */
+ BM_log_all_added(ss->bm, ss->bm_log);
+ sculpt_undo_push_end();
- /* Redraw */
- sculpt_pbvh_clear(ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ /* Redraw */
+ sculpt_pbvh_clear(ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SCULPT_OT_symmetrize(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Symmetrize";
- ot->idname = "SCULPT_OT_symmetrize";
- ot->description = "Symmetrize the topology modifications";
+ /* identifiers */
+ ot->name = "Symmetrize";
+ ot->idname = "SCULPT_OT_symmetrize";
+ ot->description = "Symmetrize the topology modifications";
- /* api callbacks */
- ot->exec = sculpt_symmetrize_exec;
- ot->poll = sculpt_and_dynamic_topology_poll;
+ /* api callbacks */
+ ot->exec = sculpt_symmetrize_exec;
+ ot->poll = sculpt_and_dynamic_topology_poll;
}
/**** Toggle operator for turning sculpt mode on or off ****/
static void sculpt_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- /* 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_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false);
-}
-
-static int ed_object_sculptmode_flush_recalc_flag(Scene *scene, Object *ob, MultiresModifierData *mmd)
-{
- int flush_recalc = 0;
- /* 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;
-}
-
-void ED_object_sculptmode_enter_ex(
- Main *bmain, Depsgraph *depsgraph,
- Scene *scene, Object *ob, const bool force_dyntopo,
- ReportList *reports)
-{
- const int mode_flag = OB_MODE_SCULPT;
- Mesh *me = BKE_mesh_from_object(ob);
-
- /* Enter sculptmode */
- ob->mode |= mode_flag;
-
- MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
-
- const int flush_recalc = ed_object_sculptmode_flush_recalc_flag(scene, ob, mmd);
-
- if (flush_recalc)
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
-
- /* 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.
- */
- BKE_object_free_derived_caches(ob);
-
- sculpt_init_session(depsgraph, scene, ob);
-
- /* 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) */
- BKE_sculpt_mask_layers_ensure(ob, mmd);
- }
-
- if (!(fabsf(ob->scale[0] - ob->scale[1]) < 1e-4f && fabsf(ob->scale[1] - ob->scale[2]) < 1e-4f)) {
- BKE_report(reports, RPT_WARNING,
- "Object has non-uniform scale, sculpting may be unpredictable");
- }
- else if (is_negative_m4(ob->obmat)) {
- BKE_report(reports, RPT_WARNING,
- "Object has negative scale, sculpting may be unpredictable");
- }
-
- 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);
-
- /* Check dynamic-topology flag; re-enter dynamic-topology mode when changing modes,
- * As long as no data was added that is not supported. */
- if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
- const char *message_unsupported = NULL;
- if (me->totloop != me->totpoly * 3) {
- message_unsupported = TIP_("non-triangle face");
- }
- else if (mmd != NULL) {
- message_unsupported = TIP_("multi-res modifier");
- }
- else {
- enum eDynTopoWarnFlag flag = sculpt_dynamic_topology_check(scene, ob);
- if (flag == 0) {
- /* pass */
- }
- else if (flag & DYNTOPO_WARN_VDATA) {
- message_unsupported = TIP_("vertex data");
- }
- else if (flag & DYNTOPO_WARN_EDATA) {
- message_unsupported = TIP_("edge data");
- }
- else if (flag & DYNTOPO_WARN_LDATA) {
- message_unsupported = TIP_("face data");
- }
- else if (flag & DYNTOPO_WARN_MODIFIER) {
- message_unsupported = TIP_("constructive modifier");
- }
- else {
- BLI_assert(0);
- }
- }
-
- if ((message_unsupported == NULL) || force_dyntopo) {
- /* 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 */
- if (has_undo) {
- sculpt_undo_push_begin("Dynamic topology enable");
- }
- sculpt_dynamic_topology_enable_ex(depsgraph, scene, ob);
- if (has_undo) {
- sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
- sculpt_undo_push_end();
- }
- }
- else {
- BKE_reportf(reports, RPT_WARNING,
- "Dynamic Topology found: %s, disabled",
- message_unsupported);
- me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY;
- }
- }
-
- /* Flush object mode. */
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ /* 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_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false);
+}
+
+static int ed_object_sculptmode_flush_recalc_flag(Scene *scene,
+ Object *ob,
+ MultiresModifierData *mmd)
+{
+ int flush_recalc = 0;
+ /* 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;
+}
+
+void ED_object_sculptmode_enter_ex(Main *bmain,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ const bool force_dyntopo,
+ ReportList *reports)
+{
+ const int mode_flag = OB_MODE_SCULPT;
+ Mesh *me = BKE_mesh_from_object(ob);
+
+ /* Enter sculptmode */
+ ob->mode |= mode_flag;
+
+ MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
+
+ const int flush_recalc = ed_object_sculptmode_flush_recalc_flag(scene, ob, mmd);
+
+ if (flush_recalc)
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+
+ /* 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.
+ */
+ BKE_object_free_derived_caches(ob);
+
+ sculpt_init_session(depsgraph, scene, ob);
+
+ /* 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) */
+ BKE_sculpt_mask_layers_ensure(ob, mmd);
+ }
+
+ if (!(fabsf(ob->scale[0] - ob->scale[1]) < 1e-4f &&
+ fabsf(ob->scale[1] - ob->scale[2]) < 1e-4f)) {
+ BKE_report(
+ reports, RPT_WARNING, "Object has non-uniform scale, sculpting may be unpredictable");
+ }
+ else if (is_negative_m4(ob->obmat)) {
+ BKE_report(reports, RPT_WARNING, "Object has negative scale, sculpting may be unpredictable");
+ }
+
+ 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);
+
+ /* Check dynamic-topology flag; re-enter dynamic-topology mode when changing modes,
+ * As long as no data was added that is not supported. */
+ if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
+ const char *message_unsupported = NULL;
+ if (me->totloop != me->totpoly * 3) {
+ message_unsupported = TIP_("non-triangle face");
+ }
+ else if (mmd != NULL) {
+ message_unsupported = TIP_("multi-res modifier");
+ }
+ else {
+ enum eDynTopoWarnFlag flag = sculpt_dynamic_topology_check(scene, ob);
+ if (flag == 0) {
+ /* pass */
+ }
+ else if (flag & DYNTOPO_WARN_VDATA) {
+ message_unsupported = TIP_("vertex data");
+ }
+ else if (flag & DYNTOPO_WARN_EDATA) {
+ message_unsupported = TIP_("edge data");
+ }
+ else if (flag & DYNTOPO_WARN_LDATA) {
+ message_unsupported = TIP_("face data");
+ }
+ else if (flag & DYNTOPO_WARN_MODIFIER) {
+ message_unsupported = TIP_("constructive modifier");
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+
+ if ((message_unsupported == NULL) || force_dyntopo) {
+ /* 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 */
+ if (has_undo) {
+ sculpt_undo_push_begin("Dynamic topology enable");
+ }
+ sculpt_dynamic_topology_enable_ex(depsgraph, scene, ob);
+ if (has_undo) {
+ sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
+ sculpt_undo_push_end();
+ }
+ }
+ else {
+ BKE_reportf(
+ reports, RPT_WARNING, "Dynamic Topology found: %s, disabled", message_unsupported);
+ me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY;
+ }
+ }
+
+ /* Flush object mode. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
}
void ED_object_sculptmode_enter(struct bContext *C, ReportList *reports)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, false, reports);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, false, reports);
}
-void ED_object_sculptmode_exit_ex(
- Depsgraph *depsgraph,
- Scene *scene, Object *ob)
+void ED_object_sculptmode_exit_ex(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- const int mode_flag = OB_MODE_SCULPT;
- Mesh *me = BKE_mesh_from_object(ob);
+ const int mode_flag = OB_MODE_SCULPT;
+ Mesh *me = BKE_mesh_from_object(ob);
- MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
- if (mmd) {
- multires_force_update(ob);
- }
+ MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
+ if (mmd) {
+ multires_force_update(ob);
+ }
- /* Not needed for now. */
+ /* Not needed for now. */
#if 0
- const int flush_recalc = ed_object_sculptmode_flush_recalc_flag(scene, ob, mmd);
+ const int flush_recalc = ed_object_sculptmode_flush_recalc_flag(scene, ob, mmd);
#endif
- /* Always for now, so leaving sculpt mode always ensures scene is in
- * a consistent state.
- */
- if (true || /* flush_recalc || */ (ob->sculpt && ob->sculpt->bm)) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
+ /* Always for now, so leaving sculpt mode always ensures scene is in
+ * a consistent state.
+ */
+ if (true || /* flush_recalc || */ (ob->sculpt && ob->sculpt->bm)) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
- 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 */
- sculpt_dynamic_topology_disable_with_undo(depsgraph, scene, ob);
+ 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 */
+ sculpt_dynamic_topology_disable_with_undo(depsgraph, scene, ob);
- /* store so we know to re-enable when entering sculpt mode */
- me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
- }
+ /* store so we know to re-enable when entering sculpt mode */
+ me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
+ }
- /* Leave sculptmode */
- ob->mode &= ~mode_flag;
+ /* Leave sculptmode */
+ ob->mode &= ~mode_flag;
- BKE_sculptsession_free(ob);
+ BKE_sculptsession_free(ob);
- paint_cursor_delete_textures();
+ paint_cursor_delete_textures();
- /* Never leave derived meshes behind. */
- BKE_object_free_derived_caches(ob);
+ /* Never leave derived meshes behind. */
+ BKE_object_free_derived_caches(ob);
- /* Flush object mode. */
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ /* Flush object mode. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
}
void ED_object_sculptmode_exit(bContext *C)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- ED_object_sculptmode_exit_ex(depsgraph, scene, ob);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ ED_object_sculptmode_exit_ex(depsgraph, scene, ob);
}
static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
{
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph_on_load(C);
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = scene->toolsettings;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- const int mode_flag = OB_MODE_SCULPT;
- const bool is_mode_set = (ob->mode & mode_flag) != 0;
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph_on_load(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ const int mode_flag = OB_MODE_SCULPT;
+ const bool is_mode_set = (ob->mode & mode_flag) != 0;
- if (!is_mode_set) {
- if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
- return OPERATOR_CANCELLED;
- }
- }
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
- if (is_mode_set) {
- ED_object_sculptmode_exit_ex(depsgraph, scene, ob);
- }
- else {
- ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, false, op->reports);
- BKE_paint_toolslots_brush_validate(bmain, &ts->sculpt->paint);
- }
+ if (is_mode_set) {
+ ED_object_sculptmode_exit_ex(depsgraph, scene, ob);
+ }
+ else {
+ ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, false, op->reports);
+ BKE_paint_toolslots_brush_validate(bmain, &ts->sculpt->paint);
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
- WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
+ WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
- WM_toolsystem_update_from_context_view3d(C);
+ WM_toolsystem_update_from_context_view3d(C);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SCULPT_OT_sculptmode_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Sculpt Mode";
- ot->idname = "SCULPT_OT_sculptmode_toggle";
- ot->description = "Toggle sculpt mode in 3D view";
+ /* identifiers */
+ ot->name = "Sculpt Mode";
+ ot->idname = "SCULPT_OT_sculptmode_toggle";
+ ot->description = "Toggle sculpt mode in 3D view";
- /* api callbacks */
- ot->exec = sculpt_mode_toggle_exec;
- ot->poll = ED_operator_object_active_editable_mesh;
+ /* api callbacks */
+ ot->exec = sculpt_mode_toggle_exec;
+ ot->poll = ED_operator_object_active_editable_mesh;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
}
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;
+ 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));
+ 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;
+ 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);
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnodes);
- if (!totnodes)
- return OPERATOR_CANCELLED;
+ 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]);
+ 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);
+ /* 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);
+ 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]);
- }
+ 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_freeN(nodes);
- sculpt_undo_push_end();
+ MEM_freeN(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);
+ /* 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;
+ 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";
+ /* 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;
+ /* api callbacks */
+ ot->exec = sculpt_detail_flood_fill_exec;
+ ot->poll = sculpt_and_constant_or_manual_detail_poll;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static void sample_detail(bContext *C, int mx, int my)
{
- /* 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;
- }
+ /* 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;
+ }
- /* 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);
+ /* 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);
- ViewContext vc;
- ED_view3d_viewcontext_init(C, &vc);
+ ViewContext vc;
+ ED_view3d_viewcontext_init(C, &vc);
- /* Pick sample detail. */
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- Object *ob = vc.obact;
- Brush *brush = BKE_paint_brush(&sd->paint);
+ /* Pick sample detail. */
+ 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);
+ 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);
+ 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.ray_normal = ray_normal;
- srd.depth = depth;
- srd.edge_length = 0.0f;
+ SculptDetailRaycastData srd;
+ srd.hit = 0;
+ srd.ray_start = ray_start;
+ srd.ray_normal = ray_normal;
+ srd.depth = depth;
+ srd.edge_length = 0.0f;
- BKE_pbvh_raycast(ob->sculpt->pbvh, sculpt_raycast_detail_cb, &srd,
- ray_start, ray_normal, false);
+ 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));
- }
+ 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));
+ }
- /* Restore context. */
- CTX_wm_area_set(C, prev_sa);
- CTX_wm_region_set(C, prev_ar);
+ /* Restore context. */
+ CTX_wm_area_set(C, prev_sa);
+ CTX_wm_region_set(C, prev_ar);
}
static int sculpt_sample_detail_size_exec(bContext *C, wmOperator *op)
{
- int ss_co[2];
- RNA_int_get_array(op->ptr, "location", ss_co);
- sample_detail(C, ss_co[0], ss_co[1]);
- return OPERATOR_FINISHED;
+ int ss_co[2];
+ RNA_int_get_array(op->ptr, "location", ss_co);
+ sample_detail(C, ss_co[0], ss_co[1]);
+ return OPERATOR_FINISHED;
}
-
static int sculpt_sample_detail_size_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e))
{
- ED_workspace_status_text(C, "Click on the mesh to set the detail");
- WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
- WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ ED_workspace_status_text(C, "Click on the mesh to set the detail");
+ WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
+ 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};
+ switch (event->type) {
+ case LEFTMOUSE:
+ if (event->val == KM_PRESS) {
+ int ss_co[2] = {event->x, event->y};
- sample_detail(C, ss_co[0], ss_co[1]);
+ sample_detail(C, ss_co[0], ss_co[1]);
- 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);
+ 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;
+ return OPERATOR_FINISHED;
+ }
+ break;
- case RIGHTMOUSE:
- {
- WM_cursor_modal_restore(CTX_wm_window(C));
- ED_workspace_status_text(C, NULL);
+ case RIGHTMOUSE: {
+ WM_cursor_modal_restore(CTX_wm_window(C));
+ ED_workspace_status_text(C, NULL);
- return OPERATOR_CANCELLED;
- }
- }
+ return OPERATOR_CANCELLED;
+ }
+ }
- return OPERATOR_RUNNING_MODAL;
+ 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";
+ /* 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_and_constant_or_manual_detail_poll;
+ /* 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_and_constant_or_manual_detail_poll;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ 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_int_array(ot->srna,
+ "location",
+ 2,
+ NULL,
+ 0,
+ SHRT_MAX,
+ "Location",
+ "Screen Coordinates of sampling",
+ 0,
+ SHRT_MAX);
}
-
/* 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);
+ 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;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- PointerRNA props_ptr;
- wmOperatorType *ot = WM_operatortype_find("WM_OT_radial_control", true);
+ PointerRNA props_ptr;
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_radial_control", true);
- WM_operator_properties_create_ptr(&props_ptr, ot);
+ 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");
- }
+ 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_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
- WM_operator_properties_free(&props_ptr);
+ WM_operator_properties_free(&props_ptr);
- return OPERATOR_FINISHED;
+ 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)";
+ /* 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;
+ /* api callbacks */
+ ot->exec = sculpt_set_detail_size_exec;
+ ot->poll = sculpt_and_dynamic_topology_poll;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void ED_operatortypes_sculpt(void)
{
- WM_operatortype_append(SCULPT_OT_brush_stroke);
- WM_operatortype_append(SCULPT_OT_sculptmode_toggle);
- WM_operatortype_append(SCULPT_OT_set_persistent_base);
- WM_operatortype_append(SCULPT_OT_dynamic_topology_toggle);
- WM_operatortype_append(SCULPT_OT_optimize);
- WM_operatortype_append(SCULPT_OT_symmetrize);
- WM_operatortype_append(SCULPT_OT_detail_flood_fill);
- WM_operatortype_append(SCULPT_OT_sample_detail_size);
- WM_operatortype_append(SCULPT_OT_set_detail_size);
+ WM_operatortype_append(SCULPT_OT_brush_stroke);
+ WM_operatortype_append(SCULPT_OT_sculptmode_toggle);
+ WM_operatortype_append(SCULPT_OT_set_persistent_base);
+ WM_operatortype_append(SCULPT_OT_dynamic_topology_toggle);
+ WM_operatortype_append(SCULPT_OT_optimize);
+ WM_operatortype_append(SCULPT_OT_symmetrize);
+ WM_operatortype_append(SCULPT_OT_detail_flood_fill);
+ WM_operatortype_append(SCULPT_OT_sample_detail_size);
+ WM_operatortype_append(SCULPT_OT_set_detail_size);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 44ed680a916..97f2ca1a143 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -21,7 +21,6 @@
* \ingroup edsculpt
*/
-
#ifndef __SCULPT_INTERN_H__
#define __SCULPT_INTERN_H__
@@ -52,72 +51,72 @@ bool sculpt_stroke_get_location(struct bContext *C, float out[3], const float mo
/* Dynamic topology */
void sculpt_pbvh_clear(Object *ob);
void sculpt_dyntopo_node_layers_add(struct SculptSession *ss);
-void sculpt_update_after_dynamic_topology_toggle(
- struct Depsgraph *depsgraph,
- struct Scene *scene, struct Object *ob);
-void sculpt_dynamic_topology_enable_ex(
- struct Depsgraph *depsgraph,
- struct Scene *scene, struct Object *ob);
-
-void sculpt_dynamic_topology_disable_ex(
- struct Depsgraph *depsgraph,
- struct Scene *scene, struct Object *ob,
- struct SculptUndoNode *unode);
+void sculpt_update_after_dynamic_topology_toggle(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob);
+void sculpt_dynamic_topology_enable_ex(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob);
+
+void sculpt_dynamic_topology_disable_ex(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob,
+ struct SculptUndoNode *unode);
void sculpt_dynamic_topology_disable(bContext *C, struct SculptUndoNode *unode);
/* Undo */
typedef enum {
- SCULPT_UNDO_COORDS,
- SCULPT_UNDO_HIDDEN,
- SCULPT_UNDO_MASK,
- SCULPT_UNDO_DYNTOPO_BEGIN,
- SCULPT_UNDO_DYNTOPO_END,
- SCULPT_UNDO_DYNTOPO_SYMMETRIZE,
+ SCULPT_UNDO_COORDS,
+ SCULPT_UNDO_HIDDEN,
+ SCULPT_UNDO_MASK,
+ SCULPT_UNDO_DYNTOPO_BEGIN,
+ SCULPT_UNDO_DYNTOPO_END,
+ SCULPT_UNDO_DYNTOPO_SYMMETRIZE,
} SculptUndoType;
typedef struct SculptUndoNode {
- struct SculptUndoNode *next, *prev;
-
- SculptUndoType type;
-
- char idname[MAX_ID_NAME]; /* name instead of pointer*/
- void *node; /* only during push, not valid afterwards! */
-
- float (*co)[3];
- float (*orig_co)[3];
- short (*no)[3];
- float *mask;
- int totvert;
-
- /* non-multires */
- int maxvert; /* to verify if totvert it still the same */
- int *index; /* to restore into right location */
- BLI_bitmap *vert_hidden;
-
- /* multires */
- int maxgrid; /* same for grid */
- int gridsize; /* same for grid */
- int totgrid; /* to restore into right location */
- int *grids; /* to restore into right location */
- BLI_bitmap **grid_hidden;
-
- /* bmesh */
- struct BMLogEntry *bm_entry;
- bool applied;
- CustomData bm_enter_vdata;
- CustomData bm_enter_edata;
- CustomData bm_enter_ldata;
- CustomData bm_enter_pdata;
- int bm_enter_totvert;
- int bm_enter_totedge;
- int bm_enter_totloop;
- int bm_enter_totpoly;
-
- /* shape keys */
- char shapeName[sizeof(((KeyBlock *)0))->name];
-
- size_t undo_size;
+ struct SculptUndoNode *next, *prev;
+
+ SculptUndoType type;
+
+ char idname[MAX_ID_NAME]; /* name instead of pointer*/
+ void *node; /* only during push, not valid afterwards! */
+
+ float (*co)[3];
+ float (*orig_co)[3];
+ short (*no)[3];
+ float *mask;
+ int totvert;
+
+ /* non-multires */
+ int maxvert; /* to verify if totvert it still the same */
+ int *index; /* to restore into right location */
+ BLI_bitmap *vert_hidden;
+
+ /* multires */
+ int maxgrid; /* same for grid */
+ int gridsize; /* same for grid */
+ int totgrid; /* to restore into right location */
+ int *grids; /* to restore into right location */
+ BLI_bitmap **grid_hidden;
+
+ /* bmesh */
+ struct BMLogEntry *bm_entry;
+ bool applied;
+ CustomData bm_enter_vdata;
+ CustomData bm_enter_edata;
+ CustomData bm_enter_ldata;
+ CustomData bm_enter_pdata;
+ int bm_enter_totvert;
+ int bm_enter_totedge;
+ int bm_enter_totloop;
+ int bm_enter_totpoly;
+
+ /* shape keys */
+ char shapeName[sizeof(((KeyBlock *)0))->name];
+
+ size_t undo_size;
} SculptUndoNode;
/* Factor of brush to have rake point following behind
@@ -125,89 +124,88 @@ typedef struct SculptUndoNode {
#define SCULPT_RAKE_BRUSH_FACTOR 0.25f
struct SculptRakeData {
- float follow_dist;
- float follow_co[3];
+ float follow_dist;
+ float follow_co[3];
};
/* Single struct used by all BLI_task threaded callbacks, let's avoid adding 10's of those... */
typedef struct SculptThreadedTaskData {
- struct bContext *C;
- struct Sculpt *sd;
- struct Object *ob;
- const struct Brush *brush;
- struct PBVHNode **nodes;
- int totnode;
-
- struct VPaint *vp;
- struct VPaintData *vpd;
- struct WPaintData *wpd;
- struct WeightPaintInfo *wpi;
- unsigned int *lcol;
- struct Mesh *me;
- /* For passing generic params. */
- void *custom_data;
-
-
- /* Data specific to some callbacks. */
- /* Note: even if only one or two of those are used at a time, keeping them separated, names help figuring out
- * what it is, and memory overhead is ridiculous anyway... */
- float flippedbstrength;
- float angle;
- float strength;
- bool smooth_mask;
- bool has_bm_orco;
-
- struct SculptProjectVector *spvc;
- float *offset;
- float *grab_delta;
- float *cono;
- float *area_no;
- float *area_no_sp;
- float *area_co;
- float(*mat)[4];
- float(*vertCos)[3];
-
- /* 0=towards view, 1=flipped */
- float(*area_cos)[3];
- float(*area_nos)[3];
- int *count;
-
- ThreadMutex mutex;
+ struct bContext *C;
+ struct Sculpt *sd;
+ struct Object *ob;
+ const struct Brush *brush;
+ struct PBVHNode **nodes;
+ int totnode;
+
+ struct VPaint *vp;
+ struct VPaintData *vpd;
+ struct WPaintData *wpd;
+ struct WeightPaintInfo *wpi;
+ unsigned int *lcol;
+ struct Mesh *me;
+ /* For passing generic params. */
+ void *custom_data;
+
+ /* Data specific to some callbacks. */
+ /* Note: even if only one or two of those are used at a time, keeping them separated, names help figuring out
+ * what it is, and memory overhead is ridiculous anyway... */
+ float flippedbstrength;
+ float angle;
+ float strength;
+ bool smooth_mask;
+ bool has_bm_orco;
+
+ struct SculptProjectVector *spvc;
+ float *offset;
+ float *grab_delta;
+ float *cono;
+ float *area_no;
+ float *area_no_sp;
+ float *area_co;
+ float (*mat)[4];
+ float (*vertCos)[3];
+
+ /* 0=towards view, 1=flipped */
+ float (*area_cos)[3];
+ float (*area_nos)[3];
+ int *count;
+
+ ThreadMutex mutex;
} SculptThreadedTaskData;
/*************** Brush testing declarations ****************/
typedef struct SculptBrushTest {
- float radius_squared;
- float location[3];
- float dist;
- int mirror_symmetry_pass;
+ float radius_squared;
+ float location[3];
+ float dist;
+ int mirror_symmetry_pass;
- /* For circle (not sphere) projection. */
- float plane_view[4];
+ /* For circle (not sphere) projection. */
+ float plane_view[4];
- /* Some tool code uses a plane for it's calculateions. */
- float plane_tool[4];
+ /* Some tool code uses a plane for it's calculateions. */
+ float plane_tool[4];
- /* View3d clipping - only set rv3d for clipping */
- struct RegionView3D *clip_rv3d;
+ /* View3d clipping - only set rv3d for clipping */
+ struct RegionView3D *clip_rv3d;
} SculptBrushTest;
typedef bool (*SculptBrushTestFn)(SculptBrushTest *test, const float co[3]);
typedef struct {
- struct Sculpt *sd;
- struct SculptSession *ss;
- float radius_squared;
- bool original;
+ struct Sculpt *sd;
+ struct SculptSession *ss;
+ float radius_squared;
+ bool original;
} SculptSearchSphereData;
typedef struct {
- struct Sculpt *sd;
- struct SculptSession *ss;
- float radius_squared;
- bool original;
- struct DistRayAABB_Precalc *dist_ray_to_aabb_precalc;
+ struct Sculpt *sd;
+ struct SculptSession *ss;
+ float radius_squared;
+ bool original;
+ struct DistRayAABB_Precalc *dist_ray_to_aabb_precalc;
} SculptSearchCircleData;
void sculpt_brush_test_init(struct SculptSession *ss, SculptBrushTest *test);
@@ -219,26 +217,28 @@ 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, 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 thread_id);
+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,
+ 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 thread_id);
/* just for vertex paint. */
-void sculpt_pbvh_calc_area_normal(
- const struct Brush *brush, Object *ob,
- PBVHNode **nodes, int totnode,
- bool use_threading,
- float r_area_no[3]);
+void sculpt_pbvh_calc_area_normal(const struct Brush *brush,
+ Object *ob,
+ PBVHNode **nodes,
+ int totnode,
+ bool use_threading,
+ float r_area_no[3]);
/* Cache stroke properties. Used because
* RNA property lookup isn't particularly fast.
@@ -247,98 +247,99 @@ void sculpt_pbvh_calc_area_normal(
*/
typedef struct StrokeCache {
- /* Invariants */
- float initial_radius;
- float scale[3];
- int flag;
- float clip_tolerance[3];
- float initial_mouse[2];
-
- /* Variants */
- float radius;
- float radius_squared;
- float true_location[3];
- float true_last_location[3];
- float location[3];
- float last_location[3];
- bool is_last_valid;
-
- bool pen_flip;
- bool invert;
- float pressure;
- float mouse[2];
- float bstrength;
- float normal_weight; /* from brush (with optional override) */
-
- /* The rest is temporary storage that isn't saved as a property */
-
- bool first_time; /* Beginning of stroke may do some things special */
-
- /* from ED_view3d_ob_project_mat_get() */
- float projection_mat[4][4];
-
- /* Clean this up! */
- struct ViewContext *vc;
- const struct Brush *brush;
-
- float special_rotation;
- float grab_delta[3], grab_delta_symmetry[3];
- float old_grab_location[3], orig_grab_location[3];
-
- /* screen-space rotation defined by mouse motion */
- float rake_rotation[4], rake_rotation_symmetry[4];
- bool is_rake_rotation_valid;
- struct SculptRakeData rake_data;
-
- /* 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;
- int mirror_symmetry_pass; /* the symmetry pass we are currently on between 0 and 7*/
- float true_view_normal[3];
- float view_normal[3];
-
- /* sculpt_normal gets calculated by calc_sculpt_normal(), then the
- * sculpt_normal_symm gets updated quickly with the usual symmetry
- * transforms */
- float sculpt_normal[3];
- float sculpt_normal_symm[3];
-
- /* Used for area texture mode, local_mat gets calculated by
- * calc_brush_local_mat() and used in tex_strength(). */
- float brush_local_mat[4][4];
-
- float plane_offset[3]; /* used to shift the plane around when doing tiled strokes */
- int tile_pass;
-
- float last_center[3];
- int radial_symmetry_pass;
- float symm_rot_mat[4][4];
- float symm_rot_mat_inv[4][4];
- bool original;
- float anchored_location[3];
-
- float vertex_rotation; /* amount to rotate the vertices when using rotate brush */
- struct Dial *dial;
-
- char saved_active_brush_name[MAX_ID_NAME];
- char saved_mask_brush_tool;
- int saved_smooth_size; /* smooth tool copies the size of the current tool */
- bool alt_smooth;
-
- float plane_trim_squared;
-
- bool supports_gravity;
- float true_gravity_direction[3];
- float gravity_direction[3];
-
- rcti previous_r; /* previous redraw rectangle */
- rcti current_r; /* current redraw rectangle */
+ /* Invariants */
+ float initial_radius;
+ float scale[3];
+ int flag;
+ float clip_tolerance[3];
+ float initial_mouse[2];
+
+ /* Variants */
+ float radius;
+ float radius_squared;
+ float true_location[3];
+ float true_last_location[3];
+ float location[3];
+ float last_location[3];
+ bool is_last_valid;
+
+ bool pen_flip;
+ bool invert;
+ float pressure;
+ float mouse[2];
+ float bstrength;
+ float normal_weight; /* from brush (with optional override) */
+
+ /* The rest is temporary storage that isn't saved as a property */
+
+ bool first_time; /* Beginning of stroke may do some things special */
+
+ /* from ED_view3d_ob_project_mat_get() */
+ float projection_mat[4][4];
+
+ /* Clean this up! */
+ struct ViewContext *vc;
+ const struct Brush *brush;
+
+ float special_rotation;
+ float grab_delta[3], grab_delta_symmetry[3];
+ float old_grab_location[3], orig_grab_location[3];
+
+ /* screen-space rotation defined by mouse motion */
+ float rake_rotation[4], rake_rotation_symmetry[4];
+ bool is_rake_rotation_valid;
+ struct SculptRakeData rake_data;
+
+ /* 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;
+ int mirror_symmetry_pass; /* the symmetry pass we are currently on between 0 and 7*/
+ float true_view_normal[3];
+ float view_normal[3];
+
+ /* sculpt_normal gets calculated by calc_sculpt_normal(), then the
+ * sculpt_normal_symm gets updated quickly with the usual symmetry
+ * transforms */
+ float sculpt_normal[3];
+ float sculpt_normal_symm[3];
+
+ /* Used for area texture mode, local_mat gets calculated by
+ * calc_brush_local_mat() and used in tex_strength(). */
+ float brush_local_mat[4][4];
+
+ float plane_offset[3]; /* used to shift the plane around when doing tiled strokes */
+ int tile_pass;
+
+ float last_center[3];
+ int radial_symmetry_pass;
+ float symm_rot_mat[4][4];
+ float symm_rot_mat_inv[4][4];
+ bool original;
+ float anchored_location[3];
+
+ float vertex_rotation; /* amount to rotate the vertices when using rotate brush */
+ struct Dial *dial;
+
+ char saved_active_brush_name[MAX_ID_NAME];
+ char saved_mask_brush_tool;
+ int saved_smooth_size; /* smooth tool copies the size of the current tool */
+ bool alt_smooth;
+
+ float plane_trim_squared;
+
+ bool supports_gravity;
+ float true_gravity_direction[3];
+ float gravity_direction[3];
+
+ rcti previous_r; /* previous redraw rectangle */
+ rcti current_r; /* current redraw rectangle */
} StrokeCache;
-void sculpt_cache_calc_brushdata_symm(
- StrokeCache *cache, const char symm,
- const char axis, const float angle);
+void sculpt_cache_calc_brushdata_symm(StrokeCache *cache,
+ const char symm,
+ const char axis,
+ const float angle);
void sculpt_cache_free(StrokeCache *cache);
SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type);
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 9c76292aaa7..0b995860feb 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -70,26 +70,25 @@
#include "paint_intern.h"
#include "sculpt_intern.h"
-
typedef struct UndoSculpt {
- ListBase nodes;
+ ListBase nodes;
- size_t undo_size;
+ size_t undo_size;
} UndoSculpt;
static UndoSculpt *sculpt_undo_get_nodes(void);
static void update_cb(PBVHNode *node, void *rebuild)
{
- BKE_pbvh_node_mark_update(node);
- if (*((bool *)rebuild))
- BKE_pbvh_node_mark_rebuild_draw(node);
- BKE_pbvh_node_fully_hidden_set(node, 0);
+ BKE_pbvh_node_mark_update(node);
+ if (*((bool *)rebuild))
+ BKE_pbvh_node_mark_rebuild_draw(node);
+ BKE_pbvh_node_fully_hidden_set(node, 0);
}
struct PartialUpdateData {
- PBVH *pbvh;
- bool rebuild;
+ PBVH *pbvh;
+ bool rebuild;
};
/**
@@ -97,248 +96,238 @@ struct PartialUpdateData {
*/
static void update_cb_partial(PBVHNode *node, void *userdata)
{
- struct PartialUpdateData *data = userdata;
- if (BKE_pbvh_node_vert_update_check_any(data->pbvh, node)) {
- update_cb(node, &(data->rebuild));
- }
+ struct PartialUpdateData *data = userdata;
+ if (BKE_pbvh_node_vert_update_check_any(data->pbvh, node)) {
+ update_cb(node, &(data->rebuild));
+ }
}
static bool test_swap_v3_v3(float a[3], float b[3])
{
- /* 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;
- }
- else {
- return false;
- }
+ /* 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;
+ }
+ else {
+ return false;
+ }
}
static bool sculpt_undo_restore_deformed(
- const SculptSession *ss,
- SculptUndoNode *unode,
- int uindex, int oindex,
- float coord[3])
+ const SculptSession *ss, SculptUndoNode *unode, int uindex, int oindex, float coord[3])
{
- if (test_swap_v3_v3(coord, unode->orig_co[uindex])) {
- copy_v3_v3(unode->co[uindex], ss->deform_cos[oindex]);
- return true;
- }
- else {
- return false;
- }
+ if (test_swap_v3_v3(coord, unode->orig_co[uindex])) {
+ copy_v3_v3(unode->co[uindex], ss->deform_cos[oindex]);
+ return true;
+ }
+ else {
+ return false;
+ }
}
static bool sculpt_undo_restore_coords(bContext *C, SculptUndoNode *unode)
{
- Scene *scene = CTX_data_scene(C);
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- SculptSession *ss = ob->sculpt;
- SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
- MVert *mvert;
- int *index;
-
- if (unode->maxvert) {
- /* regular mesh restore */
-
- if (ss->kb && !STREQ(ss->kb->name, unode->shapeName)) {
- /* 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;
-
- if (kb) {
- ob->shapenr = BLI_findindex(&key->block, kb) + 1;
-
- BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, false);
- WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob);
- }
- else {
- /* key has been removed -- skip this undo node */
- return 0;
- }
- }
-
- /* no need for float comparison here (memory is exactly equal or not) */
- index = unode->index;
- mvert = ss->mvert;
-
- if (ss->kb) {
- float (*vertCos)[3];
- vertCos = BKE_keyblock_convert_to_vertcos(ob, ss->kb);
-
- if (unode->orig_co) {
- if (ss->modifiers_active) {
- for (int i = 0; i < unode->totvert; i++) {
- sculpt_undo_restore_deformed(ss, unode, i, index[i], vertCos[index[i]]);
- }
- }
- else {
- for (int i = 0; i < unode->totvert; i++) {
- swap_v3_v3(vertCos[index[i]], unode->orig_co[i]);
- }
- }
- }
- else {
- for (int i = 0; i < unode->totvert; i++) {
- swap_v3_v3(vertCos[index[i]], unode->co[i]);
- }
- }
-
- /* propagate new coords to keyblock */
- sculpt_vertcos_to_key(ob, ss->kb, vertCos);
-
- /* pbvh uses it's own mvert array, so coords should be */
- /* propagated to pbvh here */
- BKE_pbvh_apply_vertCos(ss->pbvh, vertCos, ss->kb->totelem);
-
- MEM_freeN(vertCos);
- }
- else {
- if (unode->orig_co) {
- if (ss->modifiers_active) {
- for (int i = 0; i < unode->totvert; i++) {
- if (sculpt_undo_restore_deformed(ss, unode, i, index[i], mvert[index[i]].co)) {
- mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- }
- else {
- for (int i = 0; i < unode->totvert; i++) {
- if (test_swap_v3_v3(mvert[index[i]].co, unode->orig_co[i])) {
- mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- }
- }
- else {
- for (int i = 0; i < unode->totvert; i++) {
- if (test_swap_v3_v3(mvert[index[i]].co, unode->co[i])) {
- mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- }
- }
- }
- else if (unode->maxgrid && subdiv_ccg != NULL) {
- /* multires restore */
- CCGElem **grids, *grid;
- CCGKey key;
- float (*co)[3];
- int gridsize;
-
- grids = subdiv_ccg->grids;
- gridsize = subdiv_ccg->grid_size;
- BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
-
- co = unode->co;
- for (int j = 0; j < unode->totgrid; j++) {
- grid = grids[unode->grids[j]];
-
- for (int i = 0; i < gridsize * gridsize; i++, co++) {
- swap_v3_v3(CCG_elem_offset_co(&key, grid, i), co[0]);
- }
- }
- }
-
- return 1;
+ Scene *scene = CTX_data_scene(C);
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ SculptSession *ss = ob->sculpt;
+ SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
+ MVert *mvert;
+ int *index;
+
+ if (unode->maxvert) {
+ /* regular mesh restore */
+
+ if (ss->kb && !STREQ(ss->kb->name, unode->shapeName)) {
+ /* 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;
+
+ if (kb) {
+ ob->shapenr = BLI_findindex(&key->block, kb) + 1;
+
+ BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, false);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob);
+ }
+ else {
+ /* key has been removed -- skip this undo node */
+ return 0;
+ }
+ }
+
+ /* no need for float comparison here (memory is exactly equal or not) */
+ index = unode->index;
+ mvert = ss->mvert;
+
+ if (ss->kb) {
+ float(*vertCos)[3];
+ vertCos = BKE_keyblock_convert_to_vertcos(ob, ss->kb);
+
+ if (unode->orig_co) {
+ if (ss->modifiers_active) {
+ for (int i = 0; i < unode->totvert; i++) {
+ sculpt_undo_restore_deformed(ss, unode, i, index[i], vertCos[index[i]]);
+ }
+ }
+ else {
+ for (int i = 0; i < unode->totvert; i++) {
+ swap_v3_v3(vertCos[index[i]], unode->orig_co[i]);
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < unode->totvert; i++) {
+ swap_v3_v3(vertCos[index[i]], unode->co[i]);
+ }
+ }
+
+ /* propagate new coords to keyblock */
+ sculpt_vertcos_to_key(ob, ss->kb, vertCos);
+
+ /* pbvh uses it's own mvert array, so coords should be */
+ /* propagated to pbvh here */
+ BKE_pbvh_apply_vertCos(ss->pbvh, vertCos, ss->kb->totelem);
+
+ MEM_freeN(vertCos);
+ }
+ else {
+ if (unode->orig_co) {
+ if (ss->modifiers_active) {
+ for (int i = 0; i < unode->totvert; i++) {
+ if (sculpt_undo_restore_deformed(ss, unode, i, index[i], mvert[index[i]].co)) {
+ mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < unode->totvert; i++) {
+ if (test_swap_v3_v3(mvert[index[i]].co, unode->orig_co[i])) {
+ mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < unode->totvert; i++) {
+ if (test_swap_v3_v3(mvert[index[i]].co, unode->co[i])) {
+ mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ }
+ }
+ }
+ else if (unode->maxgrid && subdiv_ccg != NULL) {
+ /* multires restore */
+ CCGElem **grids, *grid;
+ CCGKey key;
+ float(*co)[3];
+ int gridsize;
+
+ grids = subdiv_ccg->grids;
+ gridsize = subdiv_ccg->grid_size;
+ BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
+
+ co = unode->co;
+ for (int j = 0; j < unode->totgrid; j++) {
+ grid = grids[unode->grids[j]];
+
+ for (int i = 0; i < gridsize * gridsize; i++, co++) {
+ swap_v3_v3(CCG_elem_offset_co(&key, grid, i), co[0]);
+ }
+ }
+ }
+
+ return 1;
}
-static bool sculpt_undo_restore_hidden(
- bContext *C,
- SculptUndoNode *unode)
+static bool sculpt_undo_restore_hidden(bContext *C, SculptUndoNode *unode)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- 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++) {
- 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);
- v->flag ^= ME_HIDE;
- v->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- }
- else if (unode->maxgrid && subdiv_ccg != NULL) {
- BLI_bitmap **grid_hidden = subdiv_ccg->grid_hidden;
-
- for (i = 0; i < unode->totgrid; i++) {
- SWAP(BLI_bitmap *,
- unode->grid_hidden[i],
- grid_hidden[unode->grids[i]]);
-
- }
- }
-
- return 1;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ 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++) {
+ 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);
+ v->flag ^= ME_HIDE;
+ v->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ }
+ else if (unode->maxgrid && subdiv_ccg != NULL) {
+ BLI_bitmap **grid_hidden = subdiv_ccg->grid_hidden;
+
+ for (i = 0; i < unode->totgrid; i++) {
+ SWAP(BLI_bitmap *, unode->grid_hidden[i], grid_hidden[unode->grids[i]]);
+ }
+ }
+
+ return 1;
}
static bool sculpt_undo_restore_mask(bContext *C, SculptUndoNode *unode)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- SculptSession *ss = ob->sculpt;
- SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
- MVert *mvert;
- float *vmask;
- int *index, i, j;
-
- if (unode->maxvert) {
- /* regular mesh restore */
-
- index = unode->index;
- mvert = ss->mvert;
- vmask = ss->vmask;
-
- for (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;
- }
- }
- }
- else if (unode->maxgrid && subdiv_ccg != NULL) {
- /* multires restore */
- CCGElem **grids, *grid;
- CCGKey key;
- float *mask;
- int gridsize;
-
- grids = subdiv_ccg->grids;
- gridsize = subdiv_ccg->grid_size;
- BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
-
- mask = unode->mask;
- for (j = 0; j < unode->totgrid; j++) {
- grid = grids[unode->grids[j]];
-
- for (i = 0; i < gridsize * gridsize; i++, mask++)
- SWAP(float, *CCG_elem_offset_mask(&key, grid, i), *mask);
- }
- }
-
- return 1;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ SculptSession *ss = ob->sculpt;
+ SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
+ MVert *mvert;
+ float *vmask;
+ int *index, i, j;
+
+ if (unode->maxvert) {
+ /* regular mesh restore */
+
+ index = unode->index;
+ mvert = ss->mvert;
+ vmask = ss->vmask;
+
+ for (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;
+ }
+ }
+ }
+ else if (unode->maxgrid && subdiv_ccg != NULL) {
+ /* multires restore */
+ CCGElem **grids, *grid;
+ CCGKey key;
+ float *mask;
+ int gridsize;
+
+ grids = subdiv_ccg->grids;
+ gridsize = subdiv_ccg->grid_size;
+ BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
+
+ mask = unode->mask;
+ for (j = 0; j < unode->totgrid; j++) {
+ grid = grids[unode->grids[j]];
+
+ for (i = 0; i < gridsize * gridsize; i++, mask++)
+ SWAP(float, *CCG_elem_offset_mask(&key, grid, i), *mask);
+ }
+ }
+
+ return 1;
}
static void sculpt_undo_bmesh_restore_generic_task_cb(
- void *__restrict userdata,
- const int n,
- const ParallelRangeTLS *__restrict UNUSED(tls))
+ void *__restrict userdata, const int n, const ParallelRangeTLS *__restrict UNUSED(tls))
{
- PBVHNode **nodes = userdata;
+ PBVHNode **nodes = userdata;
- BKE_pbvh_node_mark_redraw(nodes[n]);
+ BKE_pbvh_node_mark_redraw(nodes[n]);
}
static void sculpt_undo_bmesh_restore_generic(bContext *C,
@@ -346,59 +335,55 @@ static void sculpt_undo_bmesh_restore_generic(bContext *C,
Object *ob,
SculptSession *ss)
{
- if (unode->applied) {
- BM_log_undo(ss->bm, ss->bm_log);
- unode->applied = false;
- }
- else {
- BM_log_redo(ss->bm, ss->bm_log);
- unode->applied = true;
- }
-
- if (unode->type == SCULPT_UNDO_MASK) {
- int totnode;
- PBVHNode **nodes;
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
-
- BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
- BLI_task_parallel_range(
- 0, totnode,
- nodes,
- sculpt_undo_bmesh_restore_generic_task_cb,
- &settings);
-
- if (nodes)
- MEM_freeN(nodes);
- }
- else {
- sculpt_pbvh_clear(ob);
- }
+ if (unode->applied) {
+ BM_log_undo(ss->bm, ss->bm_log);
+ unode->applied = false;
+ }
+ else {
+ BM_log_redo(ss->bm, ss->bm_log);
+ unode->applied = true;
+ }
+
+ if (unode->type == SCULPT_UNDO_MASK) {
+ int totnode;
+ PBVHNode **nodes;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
+ BLI_task_parallel_range(
+ 0, totnode, nodes, sculpt_undo_bmesh_restore_generic_task_cb, &settings);
+
+ if (nodes)
+ MEM_freeN(nodes);
+ }
+ else {
+ sculpt_pbvh_clear(ob);
+ }
}
/* Create empty sculpt BMesh and enable logging */
-static void sculpt_undo_bmesh_enable(
- Object *ob, SculptUndoNode *unode)
+static void sculpt_undo_bmesh_enable(Object *ob, SculptUndoNode *unode)
{
- SculptSession *ss = ob->sculpt;
- Mesh *me = ob->data;
-
- sculpt_pbvh_clear(ob);
-
- /* 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);
- me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
-
- /* Restore the BMLog using saved entries */
- ss->bm_log = BM_log_from_existing_entries_create(ss->bm,
- unode->bm_entry);
+ SculptSession *ss = ob->sculpt;
+ Mesh *me = ob->data;
+
+ sculpt_pbvh_clear(ob);
+
+ /* 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);
+ me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
+
+ /* Restore the BMLog using saved entries */
+ ss->bm_log = BM_log_from_existing_entries_create(ss->bm, unode->bm_entry);
}
static void sculpt_undo_bmesh_restore_begin(bContext *C,
@@ -406,18 +391,18 @@ static void sculpt_undo_bmesh_restore_begin(bContext *C,
Object *ob,
SculptSession *ss)
{
- if (unode->applied) {
- sculpt_dynamic_topology_disable(C, unode);
- unode->applied = false;
- }
- else {
- sculpt_undo_bmesh_enable(ob, unode);
-
- /* Restore the mesh from the first log entry */
- BM_log_redo(ss->bm, ss->bm_log);
-
- unode->applied = true;
- }
+ if (unode->applied) {
+ sculpt_dynamic_topology_disable(C, unode);
+ unode->applied = false;
+ }
+ else {
+ sculpt_undo_bmesh_enable(ob, unode);
+
+ /* Restore the mesh from the first log entry */
+ BM_log_redo(ss->bm, ss->bm_log);
+
+ unode->applied = true;
+ }
}
static void sculpt_undo_bmesh_restore_end(bContext *C,
@@ -425,19 +410,19 @@ static void sculpt_undo_bmesh_restore_end(bContext *C,
Object *ob,
SculptSession *ss)
{
- if (unode->applied) {
- sculpt_undo_bmesh_enable(ob, unode);
-
- /* 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);
- unode->applied = true;
- }
+ if (unode->applied) {
+ sculpt_undo_bmesh_enable(ob, unode);
+
+ /* 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);
+ unode->applied = true;
+ }
}
/* Handle all dynamic-topology updates
@@ -449,565 +434,555 @@ static int sculpt_undo_bmesh_restore(bContext *C,
Object *ob,
SculptSession *ss)
{
- switch (unode->type) {
- case SCULPT_UNDO_DYNTOPO_BEGIN:
- sculpt_undo_bmesh_restore_begin(C, unode, ob, ss);
- return true;
-
- case SCULPT_UNDO_DYNTOPO_END:
- sculpt_undo_bmesh_restore_end(C, unode, ob, ss);
- return true;
-
- default:
- if (ss->bm_log) {
- sculpt_undo_bmesh_restore_generic(C, unode, ob, ss);
- return true;
- }
- break;
- }
-
- return false;
+ switch (unode->type) {
+ case SCULPT_UNDO_DYNTOPO_BEGIN:
+ sculpt_undo_bmesh_restore_begin(C, unode, ob, ss);
+ return true;
+
+ case SCULPT_UNDO_DYNTOPO_END:
+ sculpt_undo_bmesh_restore_end(C, unode, ob, ss);
+ return true;
+
+ default:
+ if (ss->bm_log) {
+ sculpt_undo_bmesh_restore_generic(C, unode, ob, ss);
+ return true;
+ }
+ break;
+ }
+
+ return false;
}
static void sculpt_undo_restore_list(bContext *C, ListBase *lb)
{
- Scene *scene = CTX_data_scene(C);
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- SculptSession *ss = ob->sculpt;
- SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
- SculptUndoNode *unode;
- bool update = false, rebuild = false;
- bool need_mask = false;
- bool partial_update = true;
-
- for (unode = lb->first; unode; unode = unode->next) {
- 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 */
- need_mask = true;
- break;
- }
- }
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
-
- BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, need_mask);
-
- if (lb->first && sculpt_undo_bmesh_restore(C, lb->first, ob, ss))
- return;
-
- for (unode = lb->first; unode; unode = unode->next) {
- if (!STREQ(unode->idname, ob->id.name))
- continue;
-
- /* check if undo data matches current data well enough to
- * continue */
- if (unode->maxvert) {
- if (ss->totvert != unode->maxvert)
- continue;
- }
- else if (unode->maxgrid && subdiv_ccg != NULL) {
- if ((subdiv_ccg->num_grids != unode->maxgrid) ||
- (subdiv_ccg->grid_size != unode->gridsize))
- {
- continue;
- }
-
- /* multi-res can't do partial updates since it doesn't flag edited vertices */
- partial_update = false;
- }
-
- switch (unode->type) {
- case SCULPT_UNDO_COORDS:
- if (sculpt_undo_restore_coords(C, unode))
- update = true;
- break;
- case SCULPT_UNDO_HIDDEN:
- if (sculpt_undo_restore_hidden(C, unode))
- rebuild = true;
- break;
- case SCULPT_UNDO_MASK:
- if (sculpt_undo_restore_mask(C, unode))
- update = true;
- 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;
- }
- }
-
- if (update || rebuild) {
- bool tag_update = false;
- /* 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 */
- if (partial_update) {
- struct PartialUpdateData data = {
- .rebuild = rebuild,
- .pbvh = ss->pbvh,
- };
- BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb_partial, &data);
- }
- else {
- BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, &rebuild);
- }
- BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw | PBVH_UpdateNormals, NULL);
-
- if (BKE_sculpt_multires_active(scene, ob)) {
- if (rebuild)
- multires_mark_as_modified(ob, MULTIRES_HIDDEN_MODIFIED);
- else
- multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
- }
-
- tag_update |= ((Mesh *)ob->data)->id.us > 1;
-
- if (ss->kb || ss->modifiers_active) {
- Mesh *mesh = ob->data;
- BKE_mesh_calc_normals(mesh);
-
- BKE_sculptsession_free_deformMats(ss);
- tag_update |= true;
- }
-
- if (tag_update) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- else {
- sculpt_update_object_bounding_box(ob);
- }
- }
+ Scene *scene = CTX_data_scene(C);
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ SculptSession *ss = ob->sculpt;
+ SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
+ SculptUndoNode *unode;
+ bool update = false, rebuild = false;
+ bool need_mask = false;
+ bool partial_update = true;
+
+ for (unode = lb->first; unode; unode = unode->next) {
+ 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 */
+ need_mask = true;
+ break;
+ }
+ }
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
+
+ BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, need_mask);
+
+ if (lb->first && sculpt_undo_bmesh_restore(C, lb->first, ob, ss))
+ return;
+
+ for (unode = lb->first; unode; unode = unode->next) {
+ if (!STREQ(unode->idname, ob->id.name))
+ continue;
+
+ /* check if undo data matches current data well enough to
+ * continue */
+ if (unode->maxvert) {
+ if (ss->totvert != unode->maxvert)
+ continue;
+ }
+ else if (unode->maxgrid && subdiv_ccg != NULL) {
+ if ((subdiv_ccg->num_grids != unode->maxgrid) ||
+ (subdiv_ccg->grid_size != unode->gridsize)) {
+ continue;
+ }
+
+ /* multi-res can't do partial updates since it doesn't flag edited vertices */
+ partial_update = false;
+ }
+
+ switch (unode->type) {
+ case SCULPT_UNDO_COORDS:
+ if (sculpt_undo_restore_coords(C, unode))
+ update = true;
+ break;
+ case SCULPT_UNDO_HIDDEN:
+ if (sculpt_undo_restore_hidden(C, unode))
+ rebuild = true;
+ break;
+ case SCULPT_UNDO_MASK:
+ if (sculpt_undo_restore_mask(C, unode))
+ update = true;
+ 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;
+ }
+ }
+
+ if (update || rebuild) {
+ bool tag_update = false;
+ /* 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 */
+ if (partial_update) {
+ struct PartialUpdateData data = {
+ .rebuild = rebuild,
+ .pbvh = ss->pbvh,
+ };
+ BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb_partial, &data);
+ }
+ else {
+ BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, &rebuild);
+ }
+ BKE_pbvh_update(ss->pbvh,
+ PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw | PBVH_UpdateNormals,
+ NULL);
+
+ if (BKE_sculpt_multires_active(scene, ob)) {
+ if (rebuild)
+ multires_mark_as_modified(ob, MULTIRES_HIDDEN_MODIFIED);
+ else
+ multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
+ }
+
+ tag_update |= ((Mesh *)ob->data)->id.us > 1;
+
+ if (ss->kb || ss->modifiers_active) {
+ Mesh *mesh = ob->data;
+ BKE_mesh_calc_normals(mesh);
+
+ BKE_sculptsession_free_deformMats(ss);
+ tag_update |= true;
+ }
+
+ if (tag_update) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ else {
+ sculpt_update_object_bounding_box(ob);
+ }
+ }
}
static void sculpt_undo_free_list(ListBase *lb)
{
- SculptUndoNode *unode = lb->first;
- while (unode != NULL) {
- SculptUndoNode *unode_next = unode->next;
- if (unode->co)
- MEM_freeN(unode->co);
- if (unode->no)
- MEM_freeN(unode->no);
- if (unode->index)
- MEM_freeN(unode->index);
- if (unode->grids)
- MEM_freeN(unode->grids);
- if (unode->orig_co)
- MEM_freeN(unode->orig_co);
- if (unode->vert_hidden)
- MEM_freeN(unode->vert_hidden);
- if (unode->grid_hidden) {
- for (int i = 0; i < unode->totgrid; i++) {
- if (unode->grid_hidden[i])
- MEM_freeN(unode->grid_hidden[i]);
- }
- MEM_freeN(unode->grid_hidden);
- }
- if (unode->mask)
- MEM_freeN(unode->mask);
-
- if (unode->bm_entry) {
- BM_log_entry_drop(unode->bm_entry);
- }
-
- if (unode->bm_enter_totvert)
- CustomData_free(&unode->bm_enter_vdata, unode->bm_enter_totvert);
- if (unode->bm_enter_totedge)
- CustomData_free(&unode->bm_enter_edata, unode->bm_enter_totedge);
- if (unode->bm_enter_totloop)
- CustomData_free(&unode->bm_enter_ldata, unode->bm_enter_totloop);
- if (unode->bm_enter_totpoly)
- CustomData_free(&unode->bm_enter_pdata, unode->bm_enter_totpoly);
-
- MEM_freeN(unode);
-
- unode = unode_next;
- }
+ SculptUndoNode *unode = lb->first;
+ while (unode != NULL) {
+ SculptUndoNode *unode_next = unode->next;
+ if (unode->co)
+ MEM_freeN(unode->co);
+ if (unode->no)
+ MEM_freeN(unode->no);
+ if (unode->index)
+ MEM_freeN(unode->index);
+ if (unode->grids)
+ MEM_freeN(unode->grids);
+ if (unode->orig_co)
+ MEM_freeN(unode->orig_co);
+ if (unode->vert_hidden)
+ MEM_freeN(unode->vert_hidden);
+ if (unode->grid_hidden) {
+ for (int i = 0; i < unode->totgrid; i++) {
+ if (unode->grid_hidden[i])
+ MEM_freeN(unode->grid_hidden[i]);
+ }
+ MEM_freeN(unode->grid_hidden);
+ }
+ if (unode->mask)
+ MEM_freeN(unode->mask);
+
+ if (unode->bm_entry) {
+ BM_log_entry_drop(unode->bm_entry);
+ }
+
+ if (unode->bm_enter_totvert)
+ CustomData_free(&unode->bm_enter_vdata, unode->bm_enter_totvert);
+ if (unode->bm_enter_totedge)
+ CustomData_free(&unode->bm_enter_edata, unode->bm_enter_totedge);
+ if (unode->bm_enter_totloop)
+ CustomData_free(&unode->bm_enter_ldata, unode->bm_enter_totloop);
+ if (unode->bm_enter_totpoly)
+ CustomData_free(&unode->bm_enter_pdata, unode->bm_enter_totpoly);
+
+ MEM_freeN(unode);
+
+ unode = unode_next;
+ }
}
/* Most likely we don't need this. */
#if 0
static bool sculpt_undo_cleanup(bContext *C, ListBase *lb)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- SculptUndoNode *unode;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ SculptUndoNode *unode;
- unode = lb->first;
+ unode = lb->first;
- if (unode && !STREQ(unode->idname, ob->id.name)) {
- if (unode->bm_entry)
- BM_log_cleanup_entry(unode->bm_entry);
+ if (unode && !STREQ(unode->idname, ob->id.name)) {
+ if (unode->bm_entry)
+ BM_log_cleanup_entry(unode->bm_entry);
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
#endif
SculptUndoNode *sculpt_undo_get_node(PBVHNode *node)
{
- UndoSculpt *usculpt = sculpt_undo_get_nodes();
+ UndoSculpt *usculpt = sculpt_undo_get_nodes();
- if (usculpt == NULL) {
- return NULL;
- }
+ if (usculpt == NULL) {
+ return NULL;
+ }
- return BLI_findptr(&usculpt->nodes, node, offsetof(SculptUndoNode, node));
+ return BLI_findptr(&usculpt->nodes, node, offsetof(SculptUndoNode, node));
}
-static void sculpt_undo_alloc_and_store_hidden(PBVH *pbvh,
- SculptUndoNode *unode)
+static void sculpt_undo_alloc_and_store_hidden(PBVH *pbvh, SculptUndoNode *unode)
{
- PBVHNode *node = unode->node;
- BLI_bitmap **grid_hidden;
- int i, *grid_indices, totgrid;
+ PBVHNode *node = unode->node;
+ BLI_bitmap **grid_hidden;
+ int i, *grid_indices, totgrid;
- grid_hidden = BKE_pbvh_grid_hidden(pbvh);
+ grid_hidden = BKE_pbvh_grid_hidden(pbvh);
- BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid,
- NULL, NULL, NULL);
+ BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, NULL, NULL, NULL);
- unode->grid_hidden = MEM_mapallocN(sizeof(*unode->grid_hidden) * totgrid,
- "unode->grid_hidden");
+ unode->grid_hidden = MEM_mapallocN(sizeof(*unode->grid_hidden) * totgrid, "unode->grid_hidden");
- for (i = 0; i < totgrid; i++) {
- if (grid_hidden[grid_indices[i]])
- unode->grid_hidden[i] = MEM_dupallocN(grid_hidden[grid_indices[i]]);
- else
- unode->grid_hidden[i] = NULL;
- }
+ for (i = 0; i < totgrid; i++) {
+ if (grid_hidden[grid_indices[i]])
+ unode->grid_hidden[i] = MEM_dupallocN(grid_hidden[grid_indices[i]]);
+ else
+ unode->grid_hidden[i] = NULL;
+ }
}
-static SculptUndoNode *sculpt_undo_alloc_node(
- Object *ob, PBVHNode *node,
- SculptUndoType 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;
- unode->node = node;
-
- if (node) {
- BKE_pbvh_node_num_verts(ss->pbvh, node, &totvert, &allvert);
- BKE_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
- &maxgrid, &gridsize, NULL);
-
- unode->totvert = totvert;
- }
- else
- maxgrid = 0;
-
- /* we will use this while sculpting, is mapalloc slow to access then? */
-
- /* general TODO, fix count_alloc */
- switch (type) {
- case SCULPT_UNDO_COORDS:
- unode->co = MEM_mapallocN(sizeof(float[3]) * allvert, "SculptUndoNode.co");
- unode->no = MEM_mapallocN(sizeof(short[3]) * allvert, "SculptUndoNode.no");
-
- usculpt->undo_size = (sizeof(float[3]) + sizeof(short[3]) + sizeof(int)) * allvert;
- break;
- case SCULPT_UNDO_HIDDEN:
- if (maxgrid)
- sculpt_undo_alloc_and_store_hidden(ss->pbvh, unode);
- else
- unode->vert_hidden = BLI_BITMAP_NEW(allvert, "SculptUndoNode.vert_hidden");
-
- break;
- case SCULPT_UNDO_MASK:
- unode->mask = MEM_mapallocN(sizeof(float) * allvert, "SculptUndoNode.mask");
-
- usculpt->undo_size += (sizeof(float) * sizeof(int)) * allvert;
-
- 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;
- }
-
- BLI_addtail(&usculpt->nodes, unode);
-
- if (maxgrid) {
- /* multires */
- unode->maxgrid = maxgrid;
- unode->totgrid = totgrid;
- unode->gridsize = gridsize;
- unode->grids = MEM_mapallocN(sizeof(int) * totgrid, "SculptUndoNode.grids");
- }
- else {
- /* regular mesh */
- unode->maxvert = ss->totvert;
- unode->index = MEM_mapallocN(sizeof(int) * allvert, "SculptUndoNode.index");
- }
-
- if (ss->modifiers_active)
- unode->orig_co = MEM_callocN(allvert * sizeof(*unode->orig_co), "undoSculpt orig_cos");
-
- return unode;
+ 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;
+ unode->node = node;
+
+ if (node) {
+ BKE_pbvh_node_num_verts(ss->pbvh, node, &totvert, &allvert);
+ BKE_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid, &maxgrid, &gridsize, NULL);
+
+ unode->totvert = totvert;
+ }
+ else
+ maxgrid = 0;
+
+ /* we will use this while sculpting, is mapalloc slow to access then? */
+
+ /* general TODO, fix count_alloc */
+ switch (type) {
+ case SCULPT_UNDO_COORDS:
+ unode->co = MEM_mapallocN(sizeof(float[3]) * allvert, "SculptUndoNode.co");
+ unode->no = MEM_mapallocN(sizeof(short[3]) * allvert, "SculptUndoNode.no");
+
+ usculpt->undo_size = (sizeof(float[3]) + sizeof(short[3]) + sizeof(int)) * allvert;
+ break;
+ case SCULPT_UNDO_HIDDEN:
+ if (maxgrid)
+ sculpt_undo_alloc_and_store_hidden(ss->pbvh, unode);
+ else
+ unode->vert_hidden = BLI_BITMAP_NEW(allvert, "SculptUndoNode.vert_hidden");
+
+ break;
+ case SCULPT_UNDO_MASK:
+ unode->mask = MEM_mapallocN(sizeof(float) * allvert, "SculptUndoNode.mask");
+
+ usculpt->undo_size += (sizeof(float) * sizeof(int)) * allvert;
+
+ 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;
+ }
+
+ BLI_addtail(&usculpt->nodes, unode);
+
+ if (maxgrid) {
+ /* multires */
+ unode->maxgrid = maxgrid;
+ unode->totgrid = totgrid;
+ unode->gridsize = gridsize;
+ unode->grids = MEM_mapallocN(sizeof(int) * totgrid, "SculptUndoNode.grids");
+ }
+ else {
+ /* regular mesh */
+ unode->maxvert = ss->totvert;
+ unode->index = MEM_mapallocN(sizeof(int) * allvert, "SculptUndoNode.index");
+ }
+
+ if (ss->modifiers_active)
+ unode->orig_co = MEM_callocN(allvert * sizeof(*unode->orig_co), "undoSculpt orig_cos");
+
+ return unode;
}
static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
{
- SculptSession *ss = ob->sculpt;
- PBVHVertexIter vd;
-
- BKE_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
- {
- copy_v3_v3(unode->co[vd.i], vd.co);
- if (vd.no) copy_v3_v3_short(unode->no[vd.i], vd.no);
- else normal_float_to_short_v3(unode->no[vd.i], vd.fno);
-
- if (ss->modifiers_active)
- copy_v3_v3(unode->orig_co[vd.i], ss->orig_cos[unode->index[vd.i]]);
- }
- BKE_pbvh_vertex_iter_end;
+ SculptSession *ss = ob->sculpt;
+ PBVHVertexIter vd;
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
+ {
+ copy_v3_v3(unode->co[vd.i], vd.co);
+ if (vd.no)
+ copy_v3_v3_short(unode->no[vd.i], vd.no);
+ else
+ normal_float_to_short_v3(unode->no[vd.i], vd.fno);
+
+ if (ss->modifiers_active)
+ copy_v3_v3(unode->orig_co[vd.i], ss->orig_cos[unode->index[vd.i]]);
+ }
+ BKE_pbvh_vertex_iter_end;
}
static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode)
{
- PBVH *pbvh = ob->sculpt->pbvh;
- PBVHNode *node = unode->node;
-
- if (unode->grids) {
- /* already stored during allocation */
- }
- else {
- MVert *mvert;
- const int *vert_indices;
- int allvert;
- int i;
-
- BKE_pbvh_node_num_verts(pbvh, node, NULL, &allvert);
- BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
- for (i = 0; i < allvert; i++) {
- BLI_BITMAP_SET(unode->vert_hidden, i,
- mvert[vert_indices[i]].flag & ME_HIDE);
- }
- }
+ PBVH *pbvh = ob->sculpt->pbvh;
+ PBVHNode *node = unode->node;
+
+ if (unode->grids) {
+ /* already stored during allocation */
+ }
+ else {
+ MVert *mvert;
+ const int *vert_indices;
+ int allvert;
+ int i;
+
+ BKE_pbvh_node_num_verts(pbvh, node, NULL, &allvert);
+ BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
+ for (i = 0; i < allvert; i++) {
+ BLI_BITMAP_SET(unode->vert_hidden, i, mvert[vert_indices[i]].flag & ME_HIDE);
+ }
+ }
}
static void sculpt_undo_store_mask(Object *ob, SculptUndoNode *unode)
{
- SculptSession *ss = ob->sculpt;
- PBVHVertexIter vd;
-
- BKE_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
- {
- unode->mask[vd.i] = *vd.mask;
- }
- BKE_pbvh_vertex_iter_end;
+ SculptSession *ss = ob->sculpt;
+ PBVHVertexIter vd;
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
+ {
+ unode->mask[vd.i] = *vd.mask;
+ }
+ BKE_pbvh_vertex_iter_end;
}
-static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
- PBVHNode *node,
- SculptUndoType type)
+static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, SculptUndoType type)
{
- UndoSculpt *usculpt = sculpt_undo_get_nodes();
- SculptSession *ss = ob->sculpt;
- PBVHVertexIter vd;
-
- SculptUndoNode *unode = usculpt->nodes.first;
-
- if (unode == NULL) {
- unode = MEM_callocN(sizeof(*unode), __func__);
-
- BLI_strncpy(unode->idname, ob->id.name, sizeof(unode->idname));
- unode->type = type;
- unode->applied = true;
-
- if (type == SCULPT_UNDO_DYNTOPO_END) {
- unode->bm_entry = BM_log_entry_add(ss->bm_log);
- 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->bm_enter_vdata, CD_MASK_MESH.vmask,
- CD_DUPLICATE, me->totvert);
- CustomData_copy(&me->edata, &unode->bm_enter_edata, CD_MASK_MESH.emask,
- CD_DUPLICATE, me->totedge);
- CustomData_copy(&me->ldata, &unode->bm_enter_ldata, CD_MASK_MESH.lmask,
- CD_DUPLICATE, me->totloop);
- CustomData_copy(&me->pdata, &unode->bm_enter_pdata, CD_MASK_MESH.pmask,
- CD_DUPLICATE, me->totpoly);
- unode->bm_enter_totvert = me->totvert;
- unode->bm_enter_totedge = me->totedge;
- unode->bm_enter_totloop = me->totloop;
- unode->bm_enter_totpoly = me->totpoly;
-
- unode->bm_entry = BM_log_entry_add(ss->bm_log);
- BM_log_all_added(ss->bm, ss->bm_log);
- }
- else {
- unode->bm_entry = BM_log_entry_add(ss->bm_log);
- }
-
- BLI_addtail(&usculpt->nodes, unode);
- }
-
- if (node) {
- switch (type) {
- case SCULPT_UNDO_COORDS:
- case SCULPT_UNDO_MASK:
- /* Before any vertex values get modified, ensure their
- * 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);
- }
- BKE_pbvh_vertex_iter_end;
- break;
-
- case SCULPT_UNDO_HIDDEN:
- {
- GSetIterator gs_iter;
- GSet *faces = BKE_pbvh_bmesh_node_faces(node);
- 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);
- }
- BKE_pbvh_vertex_iter_end;
-
- GSET_ITER (gs_iter, faces) {
- BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
- BM_log_face_modified(ss->bm_log, f);
- }
- break;
- }
-
- case SCULPT_UNDO_DYNTOPO_BEGIN:
- case SCULPT_UNDO_DYNTOPO_END:
- case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
- break;
- }
- }
-
- return unode;
+ UndoSculpt *usculpt = sculpt_undo_get_nodes();
+ SculptSession *ss = ob->sculpt;
+ PBVHVertexIter vd;
+
+ SculptUndoNode *unode = usculpt->nodes.first;
+
+ if (unode == NULL) {
+ unode = MEM_callocN(sizeof(*unode), __func__);
+
+ BLI_strncpy(unode->idname, ob->id.name, sizeof(unode->idname));
+ unode->type = type;
+ unode->applied = true;
+
+ if (type == SCULPT_UNDO_DYNTOPO_END) {
+ unode->bm_entry = BM_log_entry_add(ss->bm_log);
+ 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->bm_enter_vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, me->totvert);
+ CustomData_copy(
+ &me->edata, &unode->bm_enter_edata, CD_MASK_MESH.emask, CD_DUPLICATE, me->totedge);
+ CustomData_copy(
+ &me->ldata, &unode->bm_enter_ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, me->totloop);
+ CustomData_copy(
+ &me->pdata, &unode->bm_enter_pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, me->totpoly);
+ unode->bm_enter_totvert = me->totvert;
+ unode->bm_enter_totedge = me->totedge;
+ unode->bm_enter_totloop = me->totloop;
+ unode->bm_enter_totpoly = me->totpoly;
+
+ unode->bm_entry = BM_log_entry_add(ss->bm_log);
+ BM_log_all_added(ss->bm, ss->bm_log);
+ }
+ else {
+ unode->bm_entry = BM_log_entry_add(ss->bm_log);
+ }
+
+ BLI_addtail(&usculpt->nodes, unode);
+ }
+
+ if (node) {
+ switch (type) {
+ case SCULPT_UNDO_COORDS:
+ case SCULPT_UNDO_MASK:
+ /* Before any vertex values get modified, ensure their
+ * 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);
+ }
+ BKE_pbvh_vertex_iter_end;
+ break;
+
+ case SCULPT_UNDO_HIDDEN: {
+ GSetIterator gs_iter;
+ GSet *faces = BKE_pbvh_bmesh_node_faces(node);
+ 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);
+ }
+ BKE_pbvh_vertex_iter_end;
+
+ GSET_ITER (gs_iter, faces) {
+ BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
+ BM_log_face_modified(ss->bm_log, f);
+ }
+ break;
+ }
+
+ case SCULPT_UNDO_DYNTOPO_BEGIN:
+ case SCULPT_UNDO_DYNTOPO_END:
+ case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
+ break;
+ }
+ }
+
+ 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 */
- BLI_thread_lock(LOCK_CUSTOM1);
-
- 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 */
- unode = sculpt_undo_bmesh_push(ob, node, type);
- BLI_thread_unlock(LOCK_CUSTOM1);
- return unode;
- }
- else if ((unode = sculpt_undo_get_node(node))) {
- BLI_thread_unlock(LOCK_CUSTOM1);
- return unode;
- }
-
- unode = sculpt_undo_alloc_node(ob, node, type);
-
- /* NOTE: If this ever becomes a bottleneck, make a lock inside of the node.
- * so we release global lock sooner, but keep data locked for until it is
- * fully initialized.
- */
-
- if (unode->grids) {
- int totgrid, *grids;
- BKE_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
- NULL, NULL, NULL);
- memcpy(unode->grids, grids, sizeof(int) * totgrid);
- }
- else {
- const int *vert_indices;
- int allvert;
- BKE_pbvh_node_num_verts(ss->pbvh, node, NULL, &allvert);
- BKE_pbvh_node_get_verts(ss->pbvh, node, &vert_indices, NULL);
- memcpy(unode->index, vert_indices, sizeof(int) * unode->totvert);
- }
-
- switch (type) {
- case SCULPT_UNDO_COORDS:
- sculpt_undo_store_coords(ob, unode);
- break;
- case SCULPT_UNDO_HIDDEN:
- sculpt_undo_store_hidden(ob, unode);
- break;
- case SCULPT_UNDO_MASK:
- sculpt_undo_store_mask(ob, unode);
- 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;
- }
-
- /* store active shape key */
- if (ss->kb) BLI_strncpy(unode->shapeName, ss->kb->name, sizeof(ss->kb->name));
- else unode->shapeName[0] = '\0';
-
- BLI_thread_unlock(LOCK_CUSTOM1);
-
- return unode;
+ SculptSession *ss = ob->sculpt;
+ SculptUndoNode *unode;
+
+ /* list is manipulated by multiple threads, so we lock */
+ BLI_thread_lock(LOCK_CUSTOM1);
+
+ 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 */
+ unode = sculpt_undo_bmesh_push(ob, node, type);
+ BLI_thread_unlock(LOCK_CUSTOM1);
+ return unode;
+ }
+ else if ((unode = sculpt_undo_get_node(node))) {
+ BLI_thread_unlock(LOCK_CUSTOM1);
+ return unode;
+ }
+
+ unode = sculpt_undo_alloc_node(ob, node, type);
+
+ /* NOTE: If this ever becomes a bottleneck, make a lock inside of the node.
+ * so we release global lock sooner, but keep data locked for until it is
+ * fully initialized.
+ */
+
+ if (unode->grids) {
+ int totgrid, *grids;
+ BKE_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid, NULL, NULL, NULL);
+ memcpy(unode->grids, grids, sizeof(int) * totgrid);
+ }
+ else {
+ const int *vert_indices;
+ int allvert;
+ BKE_pbvh_node_num_verts(ss->pbvh, node, NULL, &allvert);
+ BKE_pbvh_node_get_verts(ss->pbvh, node, &vert_indices, NULL);
+ memcpy(unode->index, vert_indices, sizeof(int) * unode->totvert);
+ }
+
+ switch (type) {
+ case SCULPT_UNDO_COORDS:
+ sculpt_undo_store_coords(ob, unode);
+ break;
+ case SCULPT_UNDO_HIDDEN:
+ sculpt_undo_store_hidden(ob, unode);
+ break;
+ case SCULPT_UNDO_MASK:
+ sculpt_undo_store_mask(ob, unode);
+ 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;
+ }
+
+ /* store active shape key */
+ if (ss->kb)
+ BLI_strncpy(unode->shapeName, ss->kb->name, sizeof(ss->kb->name));
+ else
+ unode->shapeName[0] = '\0';
+
+ BLI_thread_unlock(LOCK_CUSTOM1);
+
+ return unode;
}
void sculpt_undo_push_begin(const char *name)
{
- UndoStack *ustack = ED_undo_stack_get();
- bContext *C = NULL; /* special case, we never read from this. */
- BKE_undosys_step_push_init_with_type(ustack, C, name, BKE_UNDOSYS_TYPE_SCULPT);
+ UndoStack *ustack = ED_undo_stack_get();
+ bContext *C = NULL; /* special case, we never read from this. */
+ BKE_undosys_step_push_init_with_type(ustack, C, name, BKE_UNDOSYS_TYPE_SCULPT);
}
void sculpt_undo_push_end(void)
{
- UndoSculpt *usculpt = sculpt_undo_get_nodes();
- SculptUndoNode *unode;
-
- /* 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) {
- UndoStack *ustack = ED_undo_stack_get();
- BKE_undosys_step_push(ustack, NULL, NULL);
- }
+ UndoSculpt *usculpt = sculpt_undo_get_nodes();
+ SculptUndoNode *unode;
+
+ /* 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) {
+ UndoStack *ustack = ED_undo_stack_get();
+ BKE_undosys_step_push(ustack, NULL, NULL);
+ }
}
/* -------------------------------------------------------------------- */
@@ -1015,149 +990,154 @@ void sculpt_undo_push_end(void)
* \{ */
typedef struct SculptUndoStep {
- UndoStep step;
- /* note: will split out into list for multi-object-sculpt-mode. */
- UndoSculpt data;
+ UndoStep step;
+ /* note: will split out into list for multi-object-sculpt-mode. */
+ UndoSculpt data;
} SculptUndoStep;
static bool sculpt_undosys_poll(bContext *C)
{
- Object *obact = CTX_data_active_object(C);
- if (obact && obact->type == OB_MESH) {
- if (obact && (obact->mode & OB_MODE_SCULPT)) {
- return true;
- }
- }
- return false;
+ Object *obact = CTX_data_active_object(C);
+ if (obact && obact->type == OB_MESH) {
+ if (obact && (obact->mode & OB_MODE_SCULPT)) {
+ return true;
+ }
+ }
+ return false;
}
static void sculpt_undosys_step_encode_init(struct bContext *UNUSED(C), UndoStep *us_p)
{
- SculptUndoStep *us = (SculptUndoStep *)us_p;
- /* dummy, memory is cleared anyway. */
- BLI_listbase_clear(&us->data.nodes);
+ SculptUndoStep *us = (SculptUndoStep *)us_p;
+ /* dummy, memory is cleared anyway. */
+ BLI_listbase_clear(&us->data.nodes);
}
-static bool sculpt_undosys_step_encode(struct bContext *UNUSED(C), struct Main *UNUSED(bmain), UndoStep *us_p)
+static bool sculpt_undosys_step_encode(struct bContext *UNUSED(C),
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p)
{
- /* 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;
-
- SculptUndoNode *unode = us->data.nodes.last;
- if (unode && unode->type == SCULPT_UNDO_DYNTOPO_END) {
- us->step.use_memfile_step = true;
- }
- us->step.is_applied = true;
- return true;
+ /* 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;
+
+ SculptUndoNode *unode = us->data.nodes.last;
+ if (unode && unode->type == SCULPT_UNDO_DYNTOPO_END) {
+ us->step.use_memfile_step = true;
+ }
+ us->step.is_applied = true;
+ return true;
}
static void sculpt_undosys_step_decode_undo_impl(struct bContext *C, SculptUndoStep *us)
{
- BLI_assert(us->step.is_applied == true);
- sculpt_undo_restore_list(C, &us->data.nodes);
- us->step.is_applied = false;
+ BLI_assert(us->step.is_applied == true);
+ sculpt_undo_restore_list(C, &us->data.nodes);
+ us->step.is_applied = false;
}
static void sculpt_undosys_step_decode_redo_impl(struct bContext *C, SculptUndoStep *us)
{
- BLI_assert(us->step.is_applied == false);
- sculpt_undo_restore_list(C, &us->data.nodes);
- us->step.is_applied = true;
+ BLI_assert(us->step.is_applied == false);
+ sculpt_undo_restore_list(C, &us->data.nodes);
+ us->step.is_applied = true;
}
static void sculpt_undosys_step_decode_undo(struct bContext *C, SculptUndoStep *us)
{
- SculptUndoStep *us_iter = us;
- while (us_iter->step.next && (us_iter->step.next->type == us_iter->step.type)) {
- if (us_iter->step.next->is_applied == false) {
- break;
- }
- us_iter = (SculptUndoStep *)us_iter->step.next;
- }
- while (us_iter != us) {
- sculpt_undosys_step_decode_undo_impl(C, us_iter);
- us_iter = (SculptUndoStep *)us_iter->step.prev;
- }
+ SculptUndoStep *us_iter = us;
+ while (us_iter->step.next && (us_iter->step.next->type == us_iter->step.type)) {
+ if (us_iter->step.next->is_applied == false) {
+ break;
+ }
+ us_iter = (SculptUndoStep *)us_iter->step.next;
+ }
+ while (us_iter != us) {
+ sculpt_undosys_step_decode_undo_impl(C, us_iter);
+ us_iter = (SculptUndoStep *)us_iter->step.prev;
+ }
}
static void sculpt_undosys_step_decode_redo(struct bContext *C, SculptUndoStep *us)
{
- SculptUndoStep *us_iter = us;
- while (us_iter->step.prev && (us_iter->step.prev->type == us_iter->step.type)) {
- if (us_iter->step.prev->is_applied == true) {
- break;
- }
- us_iter = (SculptUndoStep *)us_iter->step.prev;
- }
- while (us_iter && (us_iter->step.is_applied == false)) {
- sculpt_undosys_step_decode_redo_impl(C, us_iter);
- if (us_iter == us) {
- break;
- }
- us_iter = (SculptUndoStep *)us_iter->step.next;
- }
+ SculptUndoStep *us_iter = us;
+ while (us_iter->step.prev && (us_iter->step.prev->type == us_iter->step.type)) {
+ if (us_iter->step.prev->is_applied == true) {
+ break;
+ }
+ us_iter = (SculptUndoStep *)us_iter->step.prev;
+ }
+ while (us_iter && (us_iter->step.is_applied == false)) {
+ sculpt_undosys_step_decode_redo_impl(C, us_iter);
+ if (us_iter == us) {
+ break;
+ }
+ us_iter = (SculptUndoStep *)us_iter->step.next;
+ }
}
-static void sculpt_undosys_step_decode(struct bContext *C, struct Main *bmain, UndoStep *us_p, int dir)
+static void sculpt_undosys_step_decode(struct bContext *C,
+ struct Main *bmain,
+ UndoStep *us_p,
+ int dir)
{
- /* Ensure sculpt mode. */
- {
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- /* Sculpt needs evaluated state. */
- BKE_scene_view_layer_graph_evaluated_ensure(bmain, scene, view_layer);
- Object *ob = OBACT(view_layer);
- if (ob && (ob->type == OB_MESH)) {
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- if (ob->mode & OB_MODE_SCULPT) {
- /* pass */
- }
- else {
- ED_object_mode_generic_exit(bmain, depsgraph, scene, ob);
- Mesh *me = ob->data;
- /* Don't add sculpt topology undo steps when reading back undo state.
- * The undo steps must enter/exit for us. */
- me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY;
- ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, true, NULL);
- }
- BLI_assert(sculpt_undosys_poll(C));
- }
- else {
- BLI_assert(0);
- return;
- }
- }
-
- SculptUndoStep *us = (SculptUndoStep *)us_p;
- if (dir < 0) {
- sculpt_undosys_step_decode_undo(C, us);
- }
- else {
- sculpt_undosys_step_decode_redo(C, us);
- }
+ /* Ensure sculpt mode. */
+ {
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ /* Sculpt needs evaluated state. */
+ BKE_scene_view_layer_graph_evaluated_ensure(bmain, scene, view_layer);
+ Object *ob = OBACT(view_layer);
+ if (ob && (ob->type == OB_MESH)) {
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ if (ob->mode & OB_MODE_SCULPT) {
+ /* pass */
+ }
+ else {
+ ED_object_mode_generic_exit(bmain, depsgraph, scene, ob);
+ Mesh *me = ob->data;
+ /* Don't add sculpt topology undo steps when reading back undo state.
+ * The undo steps must enter/exit for us. */
+ me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY;
+ ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, true, NULL);
+ }
+ BLI_assert(sculpt_undosys_poll(C));
+ }
+ else {
+ BLI_assert(0);
+ return;
+ }
+ }
+
+ SculptUndoStep *us = (SculptUndoStep *)us_p;
+ if (dir < 0) {
+ sculpt_undosys_step_decode_undo(C, us);
+ }
+ else {
+ sculpt_undosys_step_decode_redo(C, us);
+ }
}
static void sculpt_undosys_step_free(UndoStep *us_p)
{
- SculptUndoStep *us = (SculptUndoStep *)us_p;
- sculpt_undo_free_list(&us->data.nodes);
+ SculptUndoStep *us = (SculptUndoStep *)us_p;
+ sculpt_undo_free_list(&us->data.nodes);
}
/* Export for ED_undo_sys. */
void ED_sculpt_undosys_type(UndoType *ut)
{
- ut->name = "Sculpt";
- ut->poll = sculpt_undosys_poll;
- ut->step_encode_init = sculpt_undosys_step_encode_init;
- ut->step_encode = sculpt_undosys_step_encode;
- ut->step_decode = sculpt_undosys_step_decode;
- ut->step_free = sculpt_undosys_step_free;
+ ut->name = "Sculpt";
+ ut->poll = sculpt_undosys_poll;
+ ut->step_encode_init = sculpt_undosys_step_encode_init;
+ ut->step_encode = sculpt_undosys_step_encode;
+ ut->step_decode = sculpt_undosys_step_decode;
+ ut->step_free = sculpt_undosys_step_free;
- ut->use_context = true;
+ ut->use_context = true;
- ut->step_size = sizeof(SculptUndoStep);
+ ut->step_size = sizeof(SculptUndoStep);
}
/** \} */
@@ -1168,15 +1148,15 @@ void ED_sculpt_undosys_type(UndoType *ut)
static UndoSculpt *sculpt_undosys_step_get_nodes(UndoStep *us_p)
{
- SculptUndoStep *us = (SculptUndoStep *)us_p;
- return &us->data;
+ SculptUndoStep *us = (SculptUndoStep *)us_p;
+ return &us->data;
}
static UndoSculpt *sculpt_undo_get_nodes(void)
{
- UndoStack *ustack = ED_undo_stack_get();
- UndoStep *us = BKE_undosys_stack_init_or_active_with_type(ustack, BKE_UNDOSYS_TYPE_SCULPT);
- return sculpt_undosys_step_get_nodes(us);
+ UndoStack *ustack = ED_undo_stack_get();
+ UndoStep *us = BKE_undosys_stack_init_or_active_with_type(ustack, BKE_UNDOSYS_TYPE_SCULPT);
+ return sculpt_undosys_step_get_nodes(us);
}
/** \} */
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index dde09bb0f45..39ada703b9b 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -22,7 +22,6 @@
* \ingroup edsculpt
*/
-
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
@@ -64,126 +63,123 @@
#include "UI_view2d.h"
-#define MARK_BOUNDARY 1
+#define MARK_BOUNDARY 1
typedef struct UvAdjacencyElement {
- /* pointer to original uvelement */
- UvElement *element;
- /* uv pointer for convenience. Caution, this points to the original UVs! */
- float *uv;
- /* general use flag (Used to check if Element is boundary here) */
- char flag;
+ /* pointer to original uvelement */
+ UvElement *element;
+ /* uv pointer for convenience. Caution, this points to the original UVs! */
+ float *uv;
+ /* general use flag (Used to check if Element is boundary here) */
+ char flag;
} UvAdjacencyElement;
typedef struct UvEdge {
- unsigned int uv1;
- unsigned int uv2;
- /* general use flag
- * (Used to check if edge is boundary here, and propagates to adjacency elements) */
- char flag;
+ unsigned int uv1;
+ unsigned int uv2;
+ /* general use flag
+ * (Used to check if edge is boundary here, and propagates to adjacency elements) */
+ char flag;
} UvEdge;
typedef struct UVInitialStrokeElement {
- /* index to unique uv */
- int uv;
+ /* index to unique uv */
+ int uv;
- /* strength of brush on initial position */
- float strength;
+ /* strength of brush on initial position */
+ float strength;
- /* initial uv position */
- float initial_uv[2];
+ /* initial uv position */
+ float initial_uv[2];
} UVInitialStrokeElement;
typedef struct UVInitialStroke {
- /* Initial Selection,for grab brushes for instance */
- UVInitialStrokeElement *initialSelection;
+ /* Initial Selection,for grab brushes for instance */
+ UVInitialStrokeElement *initialSelection;
- /* total initially selected UVs*/
- int totalInitialSelected;
+ /* total initially selected UVs*/
+ int totalInitialSelected;
- /* initial mouse coordinates */
- float init_coord[2];
+ /* initial mouse coordinates */
+ float init_coord[2];
} UVInitialStroke;
-
/* custom data for uv smoothing brush */
typedef struct UvSculptData {
- /* Contains the first of each set of coincident uvs.
- * These will be used to perform smoothing on and propagate the changes
- * to their coincident uvs */
- UvAdjacencyElement *uv;
+ /* Contains the first of each set of coincident uvs.
+ * These will be used to perform smoothing on and propagate the changes
+ * to their coincident uvs */
+ UvAdjacencyElement *uv;
- /* ...Is what it says */
- int totalUniqueUvs;
+ /* ...Is what it says */
+ int totalUniqueUvs;
- /* Edges used for adjacency info, used with laplacian smoothing */
- UvEdge *uvedges;
+ /* Edges used for adjacency info, used with laplacian smoothing */
+ UvEdge *uvedges;
- /* need I say more? */
- int totalUvEdges;
+ /* need I say more? */
+ int totalUvEdges;
- /* data for initial stroke, used by tools like grab */
- UVInitialStroke *initial_stroke;
+ /* data for initial stroke, used by tools like grab */
+ UVInitialStroke *initial_stroke;
- /* timer to be used for airbrush-type brush */
- wmTimer *timer;
+ /* timer to be used for airbrush-type brush */
+ wmTimer *timer;
- /* to determine quickly adjacent uvs */
- UvElementMap *elementMap;
+ /* to determine quickly adjacent uvs */
+ UvElementMap *elementMap;
- /* uvsmooth Paint for fast reference */
- Paint *uvsculpt;
+ /* uvsmooth Paint for fast reference */
+ Paint *uvsculpt;
- /* tool to use. duplicating here to change if modifier keys are pressed */
- char tool;
+ /* tool to use. duplicating here to change if modifier keys are pressed */
+ char tool;
- /* store invert flag here */
- char invert;
+ /* store invert flag here */
+ char invert;
} UvSculptData;
-
static Brush *uv_sculpt_brush(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- ToolSettings *settings = scene->toolsettings;
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *settings = scene->toolsettings;
- if (!settings->uvsculpt)
- return NULL;
- return BKE_paint_brush(&settings->uvsculpt->paint);
+ if (!settings->uvsculpt)
+ return NULL;
+ return BKE_paint_brush(&settings->uvsculpt->paint);
}
-
static bool uv_sculpt_brush_poll_do(bContext *C, const bool check_region)
{
- BMEditMesh *em;
- int ret;
- Object *obedit = CTX_data_edit_object(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- Scene *scene = CTX_data_scene(C);
- ToolSettings *toolsettings = scene->toolsettings;
-
- if (!uv_sculpt_brush(C) || !obedit || obedit->type != OB_MESH ||
- !sima || ED_space_image_show_render(sima) || (sima->mode == SI_MODE_PAINT))
- {
- return 0;
- }
-
- em = BKE_editmesh_from_object(obedit);
- ret = EDBM_uv_check(em);
-
- if (ret) {
- ARegion *ar = CTX_wm_region(C);
- if ((!toolsettings->use_uv_sculpt) || (check_region && ar && (ar->regiontype != RGN_TYPE_WINDOW))) {
- ret = 0;
- }
- }
-
- return ret;
+ BMEditMesh *em;
+ int ret;
+ Object *obedit = CTX_data_edit_object(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *toolsettings = scene->toolsettings;
+
+ if (!uv_sculpt_brush(C) || !obedit || obedit->type != OB_MESH || !sima ||
+ ED_space_image_show_render(sima) || (sima->mode == SI_MODE_PAINT)) {
+ return 0;
+ }
+
+ em = BKE_editmesh_from_object(obedit);
+ ret = EDBM_uv_check(em);
+
+ if (ret) {
+ ARegion *ar = CTX_wm_region(C);
+ if ((!toolsettings->use_uv_sculpt) ||
+ (check_region && ar && (ar->regiontype != RGN_TYPE_WINDOW))) {
+ ret = 0;
+ }
+ }
+
+ return ret;
}
static bool uv_sculpt_brush_poll(bContext *C)
{
- return uv_sculpt_brush_poll_do(C, true);
+ return uv_sculpt_brush_poll_do(C, true);
}
static void brush_drawcursor_uvsculpt(bContext *C, int x, int y, void *UNUSED(customdata))
@@ -191,74 +187,70 @@ static void brush_drawcursor_uvsculpt(bContext *C, int x, int y, void *UNUSED(cu
#define PX_SIZE_FADE_MAX 12.0f
#define PX_SIZE_FADE_MIN 4.0f
- Scene *scene = CTX_data_scene(C);
- //Brush *brush = image_paint_brush(C);
- Paint *paint = BKE_paint_get_active_from_context(C);
- Brush *brush = BKE_paint_brush(paint);
-
- if (paint && brush && paint->flags & PAINT_SHOW_BRUSH) {
- const float size = (float)BKE_brush_size_get(scene, brush);
- float alpha = 0.5f;
-
- /* fade out the brush (cheap trick to work around brush interfering with sampling [#])*/
- if (size < PX_SIZE_FADE_MIN) {
- return;
- }
- else if (size < PX_SIZE_FADE_MAX) {
- alpha *= (size - PX_SIZE_FADE_MIN) / (PX_SIZE_FADE_MAX - PX_SIZE_FADE_MIN);
- }
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3fvAlpha(brush->add_col, alpha);
-
- GPU_line_smooth(true);
- GPU_blend(true);
- imm_draw_circle_wire_2d(pos, (float)x, (float)y, size, 40);
- GPU_blend(false);
- GPU_line_smooth(false);
-
- immUnbindProgram();
- }
+ Scene *scene = CTX_data_scene(C);
+ //Brush *brush = image_paint_brush(C);
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Brush *brush = BKE_paint_brush(paint);
+
+ if (paint && brush && paint->flags & PAINT_SHOW_BRUSH) {
+ const float size = (float)BKE_brush_size_get(scene, brush);
+ float alpha = 0.5f;
+
+ /* fade out the brush (cheap trick to work around brush interfering with sampling [#])*/
+ if (size < PX_SIZE_FADE_MIN) {
+ return;
+ }
+ else if (size < PX_SIZE_FADE_MAX) {
+ alpha *= (size - PX_SIZE_FADE_MIN) / (PX_SIZE_FADE_MAX - PX_SIZE_FADE_MIN);
+ }
+
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fvAlpha(brush->add_col, alpha);
+
+ GPU_line_smooth(true);
+ GPU_blend(true);
+ imm_draw_circle_wire_2d(pos, (float)x, (float)y, size, 40);
+ GPU_blend(false);
+ GPU_line_smooth(false);
+
+ immUnbindProgram();
+ }
#undef PX_SIZE_FADE_MAX
#undef PX_SIZE_FADE_MIN
}
-
void ED_space_image_uv_sculpt_update(Main *bmain, wmWindowManager *wm, Scene *scene)
{
- ToolSettings *settings = scene->toolsettings;
- if (settings->use_uv_sculpt) {
- if (settings->uvsculpt == NULL) {
- settings->uv_sculpt_tool = UV_SCULPT_TOOL_GRAB;
- settings->uv_sculpt_settings = UV_SCULPT_LOCK_BORDERS | UV_SCULPT_ALL_ISLANDS;
- settings->uv_relax_method = UV_SCULPT_TOOL_RELAX_LAPLACIAN;
- }
- BKE_paint_ensure(settings, (Paint **)&settings->uvsculpt);
- BKE_paint_init(bmain, scene, PAINT_MODE_SCULPT_UV, PAINT_CURSOR_SCULPT);
-
- settings->uvsculpt->paint.paint_cursor = WM_paint_cursor_activate(
- wm,
- SPACE_IMAGE, RGN_TYPE_WINDOW,
- uv_sculpt_brush_poll,
- brush_drawcursor_uvsculpt, NULL);
- }
- else {
- if (settings->uvsculpt) {
- WM_paint_cursor_end(wm, settings->uvsculpt->paint.paint_cursor);
- settings->uvsculpt->paint.paint_cursor = NULL;
- }
- }
+ ToolSettings *settings = scene->toolsettings;
+ if (settings->use_uv_sculpt) {
+ if (settings->uvsculpt == NULL) {
+ settings->uv_sculpt_tool = UV_SCULPT_TOOL_GRAB;
+ settings->uv_sculpt_settings = UV_SCULPT_LOCK_BORDERS | UV_SCULPT_ALL_ISLANDS;
+ settings->uv_relax_method = UV_SCULPT_TOOL_RELAX_LAPLACIAN;
+ }
+ BKE_paint_ensure(settings, (Paint **)&settings->uvsculpt);
+ BKE_paint_init(bmain, scene, PAINT_MODE_SCULPT_UV, PAINT_CURSOR_SCULPT);
+
+ settings->uvsculpt->paint.paint_cursor = WM_paint_cursor_activate(
+ wm, SPACE_IMAGE, RGN_TYPE_WINDOW, uv_sculpt_brush_poll, brush_drawcursor_uvsculpt, NULL);
+ }
+ else {
+ if (settings->uvsculpt) {
+ WM_paint_cursor_end(wm, settings->uvsculpt->paint.paint_cursor);
+ settings->uvsculpt->paint.paint_cursor = NULL;
+ }
+ }
}
bool uv_sculpt_poll(bContext *C)
{
- return uv_sculpt_brush_poll_do(C, true);
+ return uv_sculpt_brush_poll_do(C, true);
}
bool uv_sculpt_keymap_poll(bContext *C)
{
- return uv_sculpt_brush_poll_do(C, false);
+ return uv_sculpt_brush_poll_do(C, false);
}
/*********** Improved Laplacian Relaxation Operator ************************/
@@ -267,660 +259,692 @@ bool uv_sculpt_keymap_poll(bContext *C)
***************************************************************************/
typedef struct Temp_UvData {
- float sum_co[2], p[2], b[2], sum_b[2];
- int ncounter;
+ float sum_co[2], p[2], b[2], sum_b[2];
+ int ncounter;
} Temp_UVData;
-
-
-static void HC_relaxation_iteration_uv(BMEditMesh *em, UvSculptData *sculptdata, float mouse_coord[2],
- float alpha, float radius, float aspectRatio)
+static void HC_relaxation_iteration_uv(BMEditMesh *em,
+ UvSculptData *sculptdata,
+ float mouse_coord[2],
+ float alpha,
+ float radius,
+ float aspectRatio)
{
- Temp_UVData *tmp_uvdata;
- float diff[2];
- int i;
- float radius_root = sqrtf(radius);
- Brush *brush = BKE_paint_brush(sculptdata->uvsculpt);
-
- tmp_uvdata = (Temp_UVData *)MEM_callocN(sculptdata->totalUniqueUvs * sizeof(Temp_UVData), "Temporal data");
-
- /* counting neighbors */
- for (i = 0; i < sculptdata->totalUvEdges; i++) {
- UvEdge *tmpedge = sculptdata->uvedges + i;
- tmp_uvdata[tmpedge->uv1].ncounter++;
- tmp_uvdata[tmpedge->uv2].ncounter++;
-
- add_v2_v2(tmp_uvdata[tmpedge->uv2].sum_co, sculptdata->uv[tmpedge->uv1].uv);
- add_v2_v2(tmp_uvdata[tmpedge->uv1].sum_co, sculptdata->uv[tmpedge->uv2].uv);
- }
-
- for (i = 0; i < sculptdata->totalUniqueUvs; i++) {
- copy_v2_v2(diff, tmp_uvdata[i].sum_co);
- mul_v2_fl(diff, 1.f / tmp_uvdata[i].ncounter);
- copy_v2_v2(tmp_uvdata[i].p, diff);
-
- tmp_uvdata[i].b[0] = diff[0] - sculptdata->uv[i].uv[0];
- tmp_uvdata[i].b[1] = diff[1] - sculptdata->uv[i].uv[1];
- }
-
- for (i = 0; i < sculptdata->totalUvEdges; i++) {
- UvEdge *tmpedge = sculptdata->uvedges + i;
- add_v2_v2(tmp_uvdata[tmpedge->uv1].sum_b, tmp_uvdata[tmpedge->uv2].b);
- add_v2_v2(tmp_uvdata[tmpedge->uv2].sum_b, tmp_uvdata[tmpedge->uv1].b);
- }
-
- for (i = 0; i < sculptdata->totalUniqueUvs; i++) {
- float dist;
- /* This is supposed to happen only if "Pin Edges" is on, since we have initialization on stroke start
- * If ever uv brushes get their own mode we should check for toolsettings option too */
- if ((sculptdata->uv[i].flag & MARK_BOUNDARY)) {
- continue;
- }
-
- sub_v2_v2v2(diff, sculptdata->uv[i].uv, mouse_coord);
- diff[1] /= aspectRatio;
- if ((dist = dot_v2v2(diff, diff)) <= radius) {
- UvElement *element;
- float strength;
- strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root);
-
- sculptdata->uv[i].uv[0] = (1.0f - strength) * sculptdata->uv[i].uv[0] + strength * (tmp_uvdata[i].p[0] - 0.5f * (tmp_uvdata[i].b[0] + tmp_uvdata[i].sum_b[0] / tmp_uvdata[i].ncounter));
- sculptdata->uv[i].uv[1] = (1.0f - strength) * sculptdata->uv[i].uv[1] + strength * (tmp_uvdata[i].p[1] - 0.5f * (tmp_uvdata[i].b[1] + tmp_uvdata[i].sum_b[1] / tmp_uvdata[i].ncounter));
-
- for (element = sculptdata->uv[i].element; element; element = element->next) {
- MLoopUV *luv;
- BMLoop *l;
-
- if (element->separate && element != sculptdata->uv[i].element)
- break;
-
- l = element->l;
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- copy_v2_v2(luv->uv, sculptdata->uv[i].uv);
- }
- }
- }
-
- MEM_freeN(tmp_uvdata);
-
- return;
+ Temp_UVData *tmp_uvdata;
+ float diff[2];
+ int i;
+ float radius_root = sqrtf(radius);
+ Brush *brush = BKE_paint_brush(sculptdata->uvsculpt);
+
+ tmp_uvdata = (Temp_UVData *)MEM_callocN(sculptdata->totalUniqueUvs * sizeof(Temp_UVData),
+ "Temporal data");
+
+ /* counting neighbors */
+ for (i = 0; i < sculptdata->totalUvEdges; i++) {
+ UvEdge *tmpedge = sculptdata->uvedges + i;
+ tmp_uvdata[tmpedge->uv1].ncounter++;
+ tmp_uvdata[tmpedge->uv2].ncounter++;
+
+ add_v2_v2(tmp_uvdata[tmpedge->uv2].sum_co, sculptdata->uv[tmpedge->uv1].uv);
+ add_v2_v2(tmp_uvdata[tmpedge->uv1].sum_co, sculptdata->uv[tmpedge->uv2].uv);
+ }
+
+ for (i = 0; i < sculptdata->totalUniqueUvs; i++) {
+ copy_v2_v2(diff, tmp_uvdata[i].sum_co);
+ mul_v2_fl(diff, 1.f / tmp_uvdata[i].ncounter);
+ copy_v2_v2(tmp_uvdata[i].p, diff);
+
+ tmp_uvdata[i].b[0] = diff[0] - sculptdata->uv[i].uv[0];
+ tmp_uvdata[i].b[1] = diff[1] - sculptdata->uv[i].uv[1];
+ }
+
+ for (i = 0; i < sculptdata->totalUvEdges; i++) {
+ UvEdge *tmpedge = sculptdata->uvedges + i;
+ add_v2_v2(tmp_uvdata[tmpedge->uv1].sum_b, tmp_uvdata[tmpedge->uv2].b);
+ add_v2_v2(tmp_uvdata[tmpedge->uv2].sum_b, tmp_uvdata[tmpedge->uv1].b);
+ }
+
+ for (i = 0; i < sculptdata->totalUniqueUvs; i++) {
+ float dist;
+ /* This is supposed to happen only if "Pin Edges" is on, since we have initialization on stroke start
+ * If ever uv brushes get their own mode we should check for toolsettings option too */
+ if ((sculptdata->uv[i].flag & MARK_BOUNDARY)) {
+ continue;
+ }
+
+ sub_v2_v2v2(diff, sculptdata->uv[i].uv, mouse_coord);
+ diff[1] /= aspectRatio;
+ if ((dist = dot_v2v2(diff, diff)) <= radius) {
+ UvElement *element;
+ float strength;
+ strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root);
+
+ sculptdata->uv[i].uv[0] = (1.0f - strength) * sculptdata->uv[i].uv[0] +
+ strength *
+ (tmp_uvdata[i].p[0] -
+ 0.5f * (tmp_uvdata[i].b[0] +
+ tmp_uvdata[i].sum_b[0] / tmp_uvdata[i].ncounter));
+ sculptdata->uv[i].uv[1] = (1.0f - strength) * sculptdata->uv[i].uv[1] +
+ strength *
+ (tmp_uvdata[i].p[1] -
+ 0.5f * (tmp_uvdata[i].b[1] +
+ tmp_uvdata[i].sum_b[1] / tmp_uvdata[i].ncounter));
+
+ for (element = sculptdata->uv[i].element; element; element = element->next) {
+ MLoopUV *luv;
+ BMLoop *l;
+
+ if (element->separate && element != sculptdata->uv[i].element)
+ break;
+
+ l = element->l;
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ copy_v2_v2(luv->uv, sculptdata->uv[i].uv);
+ }
+ }
+ }
+
+ MEM_freeN(tmp_uvdata);
+
+ return;
}
-static void laplacian_relaxation_iteration_uv(BMEditMesh *em, UvSculptData *sculptdata, float mouse_coord[2], float alpha, float radius, float aspectRatio)
+static void laplacian_relaxation_iteration_uv(BMEditMesh *em,
+ UvSculptData *sculptdata,
+ float mouse_coord[2],
+ float alpha,
+ float radius,
+ float aspectRatio)
{
- Temp_UVData *tmp_uvdata;
- float diff[2];
- int i;
- float radius_root = sqrtf(radius);
- Brush *brush = BKE_paint_brush(sculptdata->uvsculpt);
-
- tmp_uvdata = (Temp_UVData *)MEM_callocN(sculptdata->totalUniqueUvs * sizeof(Temp_UVData), "Temporal data");
-
- /* counting neighbors */
- for (i = 0; i < sculptdata->totalUvEdges; i++) {
- UvEdge *tmpedge = sculptdata->uvedges + i;
- tmp_uvdata[tmpedge->uv1].ncounter++;
- tmp_uvdata[tmpedge->uv2].ncounter++;
-
- add_v2_v2(tmp_uvdata[tmpedge->uv2].sum_co, sculptdata->uv[tmpedge->uv1].uv);
- add_v2_v2(tmp_uvdata[tmpedge->uv1].sum_co, sculptdata->uv[tmpedge->uv2].uv);
- }
-
- /* Original Lacplacian algorithm included removal of normal component of translation. here it is not
- * needed since we translate along the UV plane always.*/
- for (i = 0; i < sculptdata->totalUniqueUvs; i++) {
- copy_v2_v2(tmp_uvdata[i].p, tmp_uvdata[i].sum_co);
- mul_v2_fl(tmp_uvdata[i].p, 1.f / tmp_uvdata[i].ncounter);
- }
-
- for (i = 0; i < sculptdata->totalUniqueUvs; i++) {
- float dist;
- /* This is supposed to happen only if "Pin Edges" is on, since we have initialization on stroke start
- * If ever uv brushes get their own mode we should check for toolsettings option too */
- if ((sculptdata->uv[i].flag & MARK_BOUNDARY)) {
- continue;
- }
-
- sub_v2_v2v2(diff, sculptdata->uv[i].uv, mouse_coord);
- diff[1] /= aspectRatio;
- if ((dist = dot_v2v2(diff, diff)) <= radius) {
- UvElement *element;
- float strength;
- strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root);
-
- sculptdata->uv[i].uv[0] = (1.0f - strength) * sculptdata->uv[i].uv[0] + strength * tmp_uvdata[i].p[0];
- sculptdata->uv[i].uv[1] = (1.0f - strength) * sculptdata->uv[i].uv[1] + strength * tmp_uvdata[i].p[1];
-
- for (element = sculptdata->uv[i].element; element; element = element->next) {
- MLoopUV *luv;
- BMLoop *l;
-
- if (element->separate && element != sculptdata->uv[i].element)
- break;
-
- l = element->l;
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- copy_v2_v2(luv->uv, sculptdata->uv[i].uv);
- }
- }
- }
-
- MEM_freeN(tmp_uvdata);
-
- return;
+ Temp_UVData *tmp_uvdata;
+ float diff[2];
+ int i;
+ float radius_root = sqrtf(radius);
+ Brush *brush = BKE_paint_brush(sculptdata->uvsculpt);
+
+ tmp_uvdata = (Temp_UVData *)MEM_callocN(sculptdata->totalUniqueUvs * sizeof(Temp_UVData),
+ "Temporal data");
+
+ /* counting neighbors */
+ for (i = 0; i < sculptdata->totalUvEdges; i++) {
+ UvEdge *tmpedge = sculptdata->uvedges + i;
+ tmp_uvdata[tmpedge->uv1].ncounter++;
+ tmp_uvdata[tmpedge->uv2].ncounter++;
+
+ add_v2_v2(tmp_uvdata[tmpedge->uv2].sum_co, sculptdata->uv[tmpedge->uv1].uv);
+ add_v2_v2(tmp_uvdata[tmpedge->uv1].sum_co, sculptdata->uv[tmpedge->uv2].uv);
+ }
+
+ /* Original Lacplacian algorithm included removal of normal component of translation. here it is not
+ * needed since we translate along the UV plane always.*/
+ for (i = 0; i < sculptdata->totalUniqueUvs; i++) {
+ copy_v2_v2(tmp_uvdata[i].p, tmp_uvdata[i].sum_co);
+ mul_v2_fl(tmp_uvdata[i].p, 1.f / tmp_uvdata[i].ncounter);
+ }
+
+ for (i = 0; i < sculptdata->totalUniqueUvs; i++) {
+ float dist;
+ /* This is supposed to happen only if "Pin Edges" is on, since we have initialization on stroke start
+ * If ever uv brushes get their own mode we should check for toolsettings option too */
+ if ((sculptdata->uv[i].flag & MARK_BOUNDARY)) {
+ continue;
+ }
+
+ sub_v2_v2v2(diff, sculptdata->uv[i].uv, mouse_coord);
+ diff[1] /= aspectRatio;
+ if ((dist = dot_v2v2(diff, diff)) <= radius) {
+ UvElement *element;
+ float strength;
+ strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root);
+
+ sculptdata->uv[i].uv[0] = (1.0f - strength) * sculptdata->uv[i].uv[0] +
+ strength * tmp_uvdata[i].p[0];
+ sculptdata->uv[i].uv[1] = (1.0f - strength) * sculptdata->uv[i].uv[1] +
+ strength * tmp_uvdata[i].p[1];
+
+ for (element = sculptdata->uv[i].element; element; element = element->next) {
+ MLoopUV *luv;
+ BMLoop *l;
+
+ if (element->separate && element != sculptdata->uv[i].element)
+ break;
+
+ l = element->l;
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ copy_v2_v2(luv->uv, sculptdata->uv[i].uv);
+ }
+ }
+ }
+
+ MEM_freeN(tmp_uvdata);
+
+ return;
}
-
-static void uv_sculpt_stroke_apply(bContext *C, wmOperator *op, const wmEvent *event, Object *obedit)
+static void uv_sculpt_stroke_apply(bContext *C,
+ wmOperator *op,
+ const wmEvent *event,
+ Object *obedit)
{
- float co[2], radius, radius_root;
- Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- unsigned int tool;
- UvSculptData *sculptdata = (UvSculptData *)op->customdata;
- SpaceImage *sima;
- int invert;
- int width, height;
- float aspectRatio;
- float alpha, zoomx, zoomy;
- Brush *brush = BKE_paint_brush(sculptdata->uvsculpt);
- ToolSettings *toolsettings = CTX_data_tool_settings(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]);
-
- sima = CTX_wm_space_image(C);
- ED_space_image_get_size(sima, &width, &height);
- ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
-
- radius = BKE_brush_size_get(scene, brush) / (width * zoomx);
- aspectRatio = width / (float)height;
-
- /* We will compare squares to save some computation */
- radius = radius * radius;
- radius_root = sqrtf(radius);
-
- /*
- * Pinch Tool
- */
- if (tool == UV_SCULPT_TOOL_PINCH) {
- int i;
- alpha *= invert;
- for (i = 0; i < sculptdata->totalUniqueUvs; i++) {
- float dist, diff[2];
- /* This is supposed to happen only if "Lock Borders" is on, since we have initialization on stroke start
- * If ever uv brushes get their own mode we should check for toolsettings option too */
- if (sculptdata->uv[i].flag & MARK_BOUNDARY) {
- continue;
- }
-
- sub_v2_v2v2(diff, sculptdata->uv[i].uv, co);
- diff[1] /= aspectRatio;
- if ((dist = dot_v2v2(diff, diff)) <= radius) {
- UvElement *element;
- float strength;
- strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root);
- normalize_v2(diff);
-
- sculptdata->uv[i].uv[0] -= strength * diff[0] * 0.001f;
- sculptdata->uv[i].uv[1] -= strength * diff[1] * 0.001f;
-
- for (element = sculptdata->uv[i].element; element; element = element->next) {
- MLoopUV *luv;
- BMLoop *l;
-
- if (element->separate && element != sculptdata->uv[i].element)
- break;
-
- l = element->l;
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- copy_v2_v2(luv->uv, sculptdata->uv[i].uv);
- }
- }
- }
- }
-
- /*
- * Smooth Tool
- */
- else if (tool == UV_SCULPT_TOOL_RELAX) {
- unsigned int method = toolsettings->uv_relax_method;
- if (method == UV_SCULPT_TOOL_RELAX_HC) {
- HC_relaxation_iteration_uv(em, sculptdata, co, alpha, radius, aspectRatio);
- }
- else {
- laplacian_relaxation_iteration_uv(em, sculptdata, co, alpha, radius, aspectRatio);
- }
- }
-
- /*
- * Grab Tool
- */
- else if (tool == UV_SCULPT_TOOL_GRAB) {
- int i;
- float diff[2];
- sub_v2_v2v2(diff, co, sculptdata->initial_stroke->init_coord);
-
- for (i = 0; i < sculptdata->initial_stroke->totalInitialSelected; i++) {
- UvElement *element;
- int uvindex = sculptdata->initial_stroke->initialSelection[i].uv;
- float strength = sculptdata->initial_stroke->initialSelection[i].strength;
- sculptdata->uv[uvindex].uv[0] = sculptdata->initial_stroke->initialSelection[i].initial_uv[0] + strength * diff[0];
- sculptdata->uv[uvindex].uv[1] = sculptdata->initial_stroke->initialSelection[i].initial_uv[1] + strength * diff[1];
-
- for (element = sculptdata->uv[uvindex].element; element; element = element->next) {
- MLoopUV *luv;
- BMLoop *l;
-
- if (element->separate && element != sculptdata->uv[uvindex].element)
- break;
-
- l = element->l;
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- copy_v2_v2(luv->uv, sculptdata->uv[uvindex].uv);
- }
- }
- }
+ float co[2], radius, radius_root;
+ Scene *scene = CTX_data_scene(C);
+ ARegion *ar = CTX_wm_region(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ unsigned int tool;
+ UvSculptData *sculptdata = (UvSculptData *)op->customdata;
+ SpaceImage *sima;
+ int invert;
+ int width, height;
+ float aspectRatio;
+ float alpha, zoomx, zoomy;
+ Brush *brush = BKE_paint_brush(sculptdata->uvsculpt);
+ ToolSettings *toolsettings = CTX_data_tool_settings(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]);
+
+ sima = CTX_wm_space_image(C);
+ ED_space_image_get_size(sima, &width, &height);
+ ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
+
+ radius = BKE_brush_size_get(scene, brush) / (width * zoomx);
+ aspectRatio = width / (float)height;
+
+ /* We will compare squares to save some computation */
+ radius = radius * radius;
+ radius_root = sqrtf(radius);
+
+ /*
+ * Pinch Tool
+ */
+ if (tool == UV_SCULPT_TOOL_PINCH) {
+ int i;
+ alpha *= invert;
+ for (i = 0; i < sculptdata->totalUniqueUvs; i++) {
+ float dist, diff[2];
+ /* This is supposed to happen only if "Lock Borders" is on, since we have initialization on stroke start
+ * If ever uv brushes get their own mode we should check for toolsettings option too */
+ if (sculptdata->uv[i].flag & MARK_BOUNDARY) {
+ continue;
+ }
+
+ sub_v2_v2v2(diff, sculptdata->uv[i].uv, co);
+ diff[1] /= aspectRatio;
+ if ((dist = dot_v2v2(diff, diff)) <= radius) {
+ UvElement *element;
+ float strength;
+ strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root);
+ normalize_v2(diff);
+
+ sculptdata->uv[i].uv[0] -= strength * diff[0] * 0.001f;
+ sculptdata->uv[i].uv[1] -= strength * diff[1] * 0.001f;
+
+ for (element = sculptdata->uv[i].element; element; element = element->next) {
+ MLoopUV *luv;
+ BMLoop *l;
+
+ if (element->separate && element != sculptdata->uv[i].element)
+ break;
+
+ l = element->l;
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ copy_v2_v2(luv->uv, sculptdata->uv[i].uv);
+ }
+ }
+ }
+ }
+
+ /*
+ * Smooth Tool
+ */
+ else if (tool == UV_SCULPT_TOOL_RELAX) {
+ unsigned int method = toolsettings->uv_relax_method;
+ if (method == UV_SCULPT_TOOL_RELAX_HC) {
+ HC_relaxation_iteration_uv(em, sculptdata, co, alpha, radius, aspectRatio);
+ }
+ else {
+ laplacian_relaxation_iteration_uv(em, sculptdata, co, alpha, radius, aspectRatio);
+ }
+ }
+
+ /*
+ * Grab Tool
+ */
+ else if (tool == UV_SCULPT_TOOL_GRAB) {
+ int i;
+ float diff[2];
+ sub_v2_v2v2(diff, co, sculptdata->initial_stroke->init_coord);
+
+ for (i = 0; i < sculptdata->initial_stroke->totalInitialSelected; i++) {
+ UvElement *element;
+ int uvindex = sculptdata->initial_stroke->initialSelection[i].uv;
+ float strength = sculptdata->initial_stroke->initialSelection[i].strength;
+ sculptdata->uv[uvindex].uv[0] =
+ sculptdata->initial_stroke->initialSelection[i].initial_uv[0] + strength * diff[0];
+ sculptdata->uv[uvindex].uv[1] =
+ sculptdata->initial_stroke->initialSelection[i].initial_uv[1] + strength * diff[1];
+
+ for (element = sculptdata->uv[uvindex].element; element; element = element->next) {
+ MLoopUV *luv;
+ BMLoop *l;
+
+ if (element->separate && element != sculptdata->uv[uvindex].element)
+ break;
+
+ l = element->l;
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ copy_v2_v2(luv->uv, sculptdata->uv[uvindex].uv);
+ }
+ }
+ }
}
-
static void uv_sculpt_stroke_exit(bContext *C, wmOperator *op)
{
- UvSculptData *data = op->customdata;
- if (data->timer) {
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), data->timer);
- }
- if (data->elementMap) {
- BM_uv_element_map_free(data->elementMap);
- }
- if (data->uv) {
- MEM_freeN(data->uv);
- }
- if (data->uvedges) {
- MEM_freeN(data->uvedges);
- }
- if (data->initial_stroke) {
- if (data->initial_stroke->initialSelection) {
- MEM_freeN(data->initial_stroke->initialSelection);
- }
- MEM_freeN(data->initial_stroke);
- }
-
- MEM_freeN(data);
- op->customdata = NULL;
+ UvSculptData *data = op->customdata;
+ if (data->timer) {
+ WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), data->timer);
+ }
+ if (data->elementMap) {
+ BM_uv_element_map_free(data->elementMap);
+ }
+ if (data->uv) {
+ MEM_freeN(data->uv);
+ }
+ if (data->uvedges) {
+ MEM_freeN(data->uvedges);
+ }
+ if (data->initial_stroke) {
+ if (data->initial_stroke->initialSelection) {
+ MEM_freeN(data->initial_stroke->initialSelection);
+ }
+ MEM_freeN(data->initial_stroke);
+ }
+
+ MEM_freeN(data);
+ op->customdata = NULL;
}
-static int uv_element_offset_from_face_get(UvElementMap *map, BMFace *efa, BMLoop *l, int island_index, const bool doIslands)
+static int uv_element_offset_from_face_get(
+ UvElementMap *map, BMFace *efa, BMLoop *l, int island_index, const bool doIslands)
{
- UvElement *element = BM_uv_element_get(map, efa, l);
- if (!element || (doIslands && element->island != island_index)) {
- return -1;
- }
- return element - map->buf;
+ UvElement *element = BM_uv_element_get(map, efa, l);
+ if (!element || (doIslands && element->island != island_index)) {
+ return -1;
+ }
+ return element - map->buf;
}
-
static unsigned int uv_edge_hash(const void *key)
{
- const UvEdge *edge = key;
- return (BLI_ghashutil_uinthash(edge->uv2) +
- BLI_ghashutil_uinthash(edge->uv1));
+ const UvEdge *edge = key;
+ return (BLI_ghashutil_uinthash(edge->uv2) + BLI_ghashutil_uinthash(edge->uv1));
}
static bool uv_edge_compare(const void *a, const void *b)
{
- const UvEdge *edge1 = a;
- const UvEdge *edge2 = b;
+ const UvEdge *edge1 = a;
+ const UvEdge *edge2 = b;
- if ((edge1->uv1 == edge2->uv1) && (edge1->uv2 == edge2->uv2)) {
- return 0;
- }
- return 1;
+ if ((edge1->uv1 == edge2->uv1) && (edge1->uv2 == edge2->uv2)) {
+ return 0;
+ }
+ return 1;
}
-
static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wmEvent *event)
{
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- ToolSettings *ts = scene->toolsettings;
- UvSculptData *data = MEM_callocN(sizeof(*data), "UV Smooth Brush Data");
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- op->customdata = data;
-
- curvemapping_initialize(ts->uvsculpt->paint.brush->curve);
-
- if (data) {
- int counter = 0, i;
- ARegion *ar = CTX_wm_region(C);
- float co[2];
- BMFace *efa;
- MLoopUV *luv;
- BMLoop *l;
- BMIter iter, liter;
-
- UvEdge *edges;
- GHash *edgeHash;
- GHashIterator gh_iter;
-
- bool do_island_optimization = !(ts->uv_sculpt_settings & UV_SCULPT_ALL_ISLANDS);
- int island_index = 0;
- /* Holds, for each UvElement in elementMap, a pointer to its unique uv.*/
- int *uniqueUv;
- data->tool = (RNA_enum_get(op->ptr, "mode") == BRUSH_STROKE_SMOOTH) ? UV_SCULPT_TOOL_RELAX : ts->uv_sculpt_tool;
- data->invert = (RNA_enum_get(op->ptr, "mode") == BRUSH_STROKE_INVERT) ? 1 : 0;
-
- data->uvsculpt = &ts->uvsculpt->paint;
-
- if (do_island_optimization) {
- /* We will need island information */
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- data->elementMap = BM_uv_element_map_create(bm, false, true, true);
- }
- else {
- data->elementMap = BM_uv_element_map_create(bm, true, true, true);
- }
- }
- else {
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- data->elementMap = BM_uv_element_map_create(bm, false, true, false);
- }
- else {
- data->elementMap = BM_uv_element_map_create(bm, true, true, false);
- }
- }
-
- if (!data->elementMap) {
- uv_sculpt_stroke_exit(C, op);
- return NULL;
- }
-
- /* 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]);
-
- /* we need to find the active island here */
- if (do_island_optimization) {
- UvElement *element;
- UvNearestHit hit = UV_NEAREST_HIT_INIT;
- Image *ima = CTX_data_edit_image(C);
- uv_find_nearest_vert(scene, ima, obedit, co, 0.0f, &hit);
-
- element = BM_uv_element_get(data->elementMap, hit.efa, hit.l);
- island_index = element->island;
- }
-
-
- /* Count 'unique' uvs */
- for (i = 0; i < data->elementMap->totalUVs; i++) {
- if (data->elementMap->buf[i].separate &&
- (!do_island_optimization || data->elementMap->buf[i].island == island_index))
- {
- counter++;
- }
- }
-
- /* Allocate the unique uv buffers */
- data->uv = MEM_mallocN(sizeof(*data->uv) * counter, "uv_brush_unique_uvs");
- uniqueUv = MEM_mallocN(sizeof(*uniqueUv) * data->elementMap->totalUVs, "uv_brush_unique_uv_map");
- edgeHash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "uv_brush_edge_hash");
- /* we have at most totalUVs edges */
- edges = MEM_mallocN(sizeof(*edges) * data->elementMap->totalUVs, "uv_brush_all_edges");
- if (!data->uv || !uniqueUv || !edgeHash || !edges) {
- if (edges) {
- MEM_freeN(edges);
- }
- if (uniqueUv) {
- MEM_freeN(uniqueUv);
- }
- if (edgeHash) {
- BLI_ghash_free(edgeHash, NULL, NULL);
- }
- uv_sculpt_stroke_exit(C, op);
- return NULL;
- }
-
- data->totalUniqueUvs = counter;
- /* So that we can use this as index for the UvElements */
- counter = -1;
- /* initialize the unique UVs */
- for (i = 0; i < bm->totvert; i++) {
- UvElement *element = data->elementMap->vert[i];
- for (; element; element = element->next) {
- if (element->separate) {
- if (do_island_optimization && (element->island != island_index)) {
- /* skip this uv if not on the active island */
- for (; element->next && !(element->next->separate); element = element->next)
- ;
- continue;
- }
-
- l = element->l;
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
-
- counter++;
- data->uv[counter].element = element;
- data->uv[counter].flag = 0;
- data->uv[counter].uv = luv->uv;
- }
- /* pointer arithmetic to the rescue, as always :)*/
- uniqueUv[element - data->elementMap->buf] = counter;
- }
- }
-
-
- /* Now, on to generate our uv connectivity data */
- counter = 0;
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- int offset1, itmp1 = uv_element_offset_from_face_get(data->elementMap, efa, l, island_index, do_island_optimization);
- int offset2, itmp2 = uv_element_offset_from_face_get(data->elementMap, efa, l->next, island_index, do_island_optimization);
- char *flag;
-
- /* Skip edge if not found(unlikely) or not on valid island */
- if (itmp1 == -1 || itmp2 == -1)
- continue;
-
- offset1 = uniqueUv[itmp1];
- offset2 = uniqueUv[itmp2];
-
- edges[counter].flag = 0;
- /* using an order policy, sort uvs according to address space. This avoids
- * Having two different UvEdges with the same uvs on different positions */
- if (offset1 < offset2) {
- edges[counter].uv1 = offset1;
- edges[counter].uv2 = offset2;
- }
- else {
- edges[counter].uv1 = offset2;
- edges[counter].uv2 = offset1;
- }
- /* Hack! Set the value of the key to its flag.
- * Now we can set the flag when an edge exists twice :) */
- flag = BLI_ghash_lookup(edgeHash, &edges[counter]);
- if (flag) {
- *flag = 1;
- }
- else {
- /* Hack mentioned */
- BLI_ghash_insert(edgeHash, &edges[counter], &edges[counter].flag);
- }
- counter++;
- }
- }
-
- MEM_freeN(uniqueUv);
-
- /* Allocate connectivity data, we allocate edges once */
- data->uvedges = MEM_mallocN(sizeof(*data->uvedges) * BLI_ghash_len(edgeHash), "uv_brush_edge_connectivity_data");
- if (!data->uvedges) {
- BLI_ghash_free(edgeHash, NULL, NULL);
- MEM_freeN(edges);
- uv_sculpt_stroke_exit(C, op);
- return NULL;
- }
-
- /* fill the edges with data */
- i = 0;
- GHASH_ITER (gh_iter, edgeHash) {
- data->uvedges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(&gh_iter));
- }
- data->totalUvEdges = BLI_ghash_len(edgeHash);
-
- /* cleanup temporary stuff */
- BLI_ghash_free(edgeHash, NULL, NULL);
- MEM_freeN(edges);
-
- /* transfer boundary edge property to uvs */
- if (ts->uv_sculpt_settings & UV_SCULPT_LOCK_BORDERS) {
- for (i = 0; i < data->totalUvEdges; i++) {
- if (!data->uvedges[i].flag) {
- data->uv[data->uvedges[i].uv1].flag |= MARK_BOUNDARY;
- data->uv[data->uvedges[i].uv2].flag |= MARK_BOUNDARY;
- }
- }
- }
-
- /* Allocate initial selection for grab tool */
- if (data->tool == UV_SCULPT_TOOL_GRAB) {
- float radius, radius_root;
- UvSculptData *sculptdata = (UvSculptData *)op->customdata;
- SpaceImage *sima;
- int width, height;
- float aspectRatio;
- float alpha, zoomx, zoomy;
- Brush *brush = BKE_paint_brush(sculptdata->uvsculpt);
-
- alpha = BKE_brush_alpha_get(scene, brush);
-
- 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);
-
- aspectRatio = width / (float)height;
- radius /= (width * zoomx);
- radius = radius * radius;
- radius_root = sqrtf(radius);
-
- /* Allocate selection stack */
- data->initial_stroke = MEM_mallocN(sizeof(*data->initial_stroke), "uv_sculpt_initial_stroke");
- if (!data->initial_stroke) {
- uv_sculpt_stroke_exit(C, op);
- }
- data->initial_stroke->initialSelection = MEM_mallocN(sizeof(*data->initial_stroke->initialSelection) * data->totalUniqueUvs, "uv_sculpt_initial_selection");
- if (!data->initial_stroke->initialSelection) {
- uv_sculpt_stroke_exit(C, op);
- }
-
- copy_v2_v2(data->initial_stroke->init_coord, co);
-
- counter = 0;
-
- for (i = 0; i < data->totalUniqueUvs; i++) {
- float dist, diff[2];
- if (data->uv[i].flag & MARK_BOUNDARY) {
- continue;
- }
-
- sub_v2_v2v2(diff, data->uv[i].uv, co);
- diff[1] /= aspectRatio;
- if ((dist = dot_v2v2(diff, diff)) <= radius) {
- float strength;
- strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root);
-
- data->initial_stroke->initialSelection[counter].uv = i;
- data->initial_stroke->initialSelection[counter].strength = strength;
- copy_v2_v2(data->initial_stroke->initialSelection[counter].initial_uv, data->uv[i].uv);
- counter++;
- }
- }
-
- data->initial_stroke->totalInitialSelected = counter;
- }
- }
-
- return op->customdata;
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ ToolSettings *ts = scene->toolsettings;
+ UvSculptData *data = MEM_callocN(sizeof(*data), "UV Smooth Brush Data");
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ op->customdata = data;
+
+ curvemapping_initialize(ts->uvsculpt->paint.brush->curve);
+
+ if (data) {
+ int counter = 0, i;
+ ARegion *ar = CTX_wm_region(C);
+ float co[2];
+ BMFace *efa;
+ MLoopUV *luv;
+ BMLoop *l;
+ BMIter iter, liter;
+
+ UvEdge *edges;
+ GHash *edgeHash;
+ GHashIterator gh_iter;
+
+ bool do_island_optimization = !(ts->uv_sculpt_settings & UV_SCULPT_ALL_ISLANDS);
+ int island_index = 0;
+ /* Holds, for each UvElement in elementMap, a pointer to its unique uv.*/
+ int *uniqueUv;
+ data->tool = (RNA_enum_get(op->ptr, "mode") == BRUSH_STROKE_SMOOTH) ? UV_SCULPT_TOOL_RELAX :
+ ts->uv_sculpt_tool;
+ data->invert = (RNA_enum_get(op->ptr, "mode") == BRUSH_STROKE_INVERT) ? 1 : 0;
+
+ data->uvsculpt = &ts->uvsculpt->paint;
+
+ if (do_island_optimization) {
+ /* We will need island information */
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ data->elementMap = BM_uv_element_map_create(bm, false, true, true);
+ }
+ else {
+ data->elementMap = BM_uv_element_map_create(bm, true, true, true);
+ }
+ }
+ else {
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ data->elementMap = BM_uv_element_map_create(bm, false, true, false);
+ }
+ else {
+ data->elementMap = BM_uv_element_map_create(bm, true, true, false);
+ }
+ }
+
+ if (!data->elementMap) {
+ uv_sculpt_stroke_exit(C, op);
+ return NULL;
+ }
+
+ /* 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]);
+
+ /* we need to find the active island here */
+ if (do_island_optimization) {
+ UvElement *element;
+ UvNearestHit hit = UV_NEAREST_HIT_INIT;
+ Image *ima = CTX_data_edit_image(C);
+ uv_find_nearest_vert(scene, ima, obedit, co, 0.0f, &hit);
+
+ element = BM_uv_element_get(data->elementMap, hit.efa, hit.l);
+ island_index = element->island;
+ }
+
+ /* Count 'unique' uvs */
+ for (i = 0; i < data->elementMap->totalUVs; i++) {
+ if (data->elementMap->buf[i].separate &&
+ (!do_island_optimization || data->elementMap->buf[i].island == island_index)) {
+ counter++;
+ }
+ }
+
+ /* Allocate the unique uv buffers */
+ data->uv = MEM_mallocN(sizeof(*data->uv) * counter, "uv_brush_unique_uvs");
+ uniqueUv = MEM_mallocN(sizeof(*uniqueUv) * data->elementMap->totalUVs,
+ "uv_brush_unique_uv_map");
+ edgeHash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "uv_brush_edge_hash");
+ /* we have at most totalUVs edges */
+ edges = MEM_mallocN(sizeof(*edges) * data->elementMap->totalUVs, "uv_brush_all_edges");
+ if (!data->uv || !uniqueUv || !edgeHash || !edges) {
+ if (edges) {
+ MEM_freeN(edges);
+ }
+ if (uniqueUv) {
+ MEM_freeN(uniqueUv);
+ }
+ if (edgeHash) {
+ BLI_ghash_free(edgeHash, NULL, NULL);
+ }
+ uv_sculpt_stroke_exit(C, op);
+ return NULL;
+ }
+
+ data->totalUniqueUvs = counter;
+ /* So that we can use this as index for the UvElements */
+ counter = -1;
+ /* initialize the unique UVs */
+ for (i = 0; i < bm->totvert; i++) {
+ UvElement *element = data->elementMap->vert[i];
+ for (; element; element = element->next) {
+ if (element->separate) {
+ if (do_island_optimization && (element->island != island_index)) {
+ /* skip this uv if not on the active island */
+ for (; element->next && !(element->next->separate); element = element->next)
+ ;
+ continue;
+ }
+
+ l = element->l;
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ counter++;
+ data->uv[counter].element = element;
+ data->uv[counter].flag = 0;
+ data->uv[counter].uv = luv->uv;
+ }
+ /* pointer arithmetic to the rescue, as always :)*/
+ uniqueUv[element - data->elementMap->buf] = counter;
+ }
+ }
+
+ /* Now, on to generate our uv connectivity data */
+ counter = 0;
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ int offset1, itmp1 = uv_element_offset_from_face_get(
+ data->elementMap, efa, l, island_index, do_island_optimization);
+ int offset2, itmp2 = uv_element_offset_from_face_get(
+ data->elementMap, efa, l->next, island_index, do_island_optimization);
+ char *flag;
+
+ /* Skip edge if not found(unlikely) or not on valid island */
+ if (itmp1 == -1 || itmp2 == -1)
+ continue;
+
+ offset1 = uniqueUv[itmp1];
+ offset2 = uniqueUv[itmp2];
+
+ edges[counter].flag = 0;
+ /* using an order policy, sort uvs according to address space. This avoids
+ * Having two different UvEdges with the same uvs on different positions */
+ if (offset1 < offset2) {
+ edges[counter].uv1 = offset1;
+ edges[counter].uv2 = offset2;
+ }
+ else {
+ edges[counter].uv1 = offset2;
+ edges[counter].uv2 = offset1;
+ }
+ /* Hack! Set the value of the key to its flag.
+ * Now we can set the flag when an edge exists twice :) */
+ flag = BLI_ghash_lookup(edgeHash, &edges[counter]);
+ if (flag) {
+ *flag = 1;
+ }
+ else {
+ /* Hack mentioned */
+ BLI_ghash_insert(edgeHash, &edges[counter], &edges[counter].flag);
+ }
+ counter++;
+ }
+ }
+
+ MEM_freeN(uniqueUv);
+
+ /* Allocate connectivity data, we allocate edges once */
+ data->uvedges = MEM_mallocN(sizeof(*data->uvedges) * BLI_ghash_len(edgeHash),
+ "uv_brush_edge_connectivity_data");
+ if (!data->uvedges) {
+ BLI_ghash_free(edgeHash, NULL, NULL);
+ MEM_freeN(edges);
+ uv_sculpt_stroke_exit(C, op);
+ return NULL;
+ }
+
+ /* fill the edges with data */
+ i = 0;
+ GHASH_ITER (gh_iter, edgeHash) {
+ data->uvedges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(&gh_iter));
+ }
+ data->totalUvEdges = BLI_ghash_len(edgeHash);
+
+ /* cleanup temporary stuff */
+ BLI_ghash_free(edgeHash, NULL, NULL);
+ MEM_freeN(edges);
+
+ /* transfer boundary edge property to uvs */
+ if (ts->uv_sculpt_settings & UV_SCULPT_LOCK_BORDERS) {
+ for (i = 0; i < data->totalUvEdges; i++) {
+ if (!data->uvedges[i].flag) {
+ data->uv[data->uvedges[i].uv1].flag |= MARK_BOUNDARY;
+ data->uv[data->uvedges[i].uv2].flag |= MARK_BOUNDARY;
+ }
+ }
+ }
+
+ /* Allocate initial selection for grab tool */
+ if (data->tool == UV_SCULPT_TOOL_GRAB) {
+ float radius, radius_root;
+ UvSculptData *sculptdata = (UvSculptData *)op->customdata;
+ SpaceImage *sima;
+ int width, height;
+ float aspectRatio;
+ float alpha, zoomx, zoomy;
+ Brush *brush = BKE_paint_brush(sculptdata->uvsculpt);
+
+ alpha = BKE_brush_alpha_get(scene, brush);
+
+ 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);
+
+ aspectRatio = width / (float)height;
+ radius /= (width * zoomx);
+ radius = radius * radius;
+ radius_root = sqrtf(radius);
+
+ /* Allocate selection stack */
+ data->initial_stroke = MEM_mallocN(sizeof(*data->initial_stroke),
+ "uv_sculpt_initial_stroke");
+ if (!data->initial_stroke) {
+ uv_sculpt_stroke_exit(C, op);
+ }
+ data->initial_stroke->initialSelection = MEM_mallocN(
+ sizeof(*data->initial_stroke->initialSelection) * data->totalUniqueUvs,
+ "uv_sculpt_initial_selection");
+ if (!data->initial_stroke->initialSelection) {
+ uv_sculpt_stroke_exit(C, op);
+ }
+
+ copy_v2_v2(data->initial_stroke->init_coord, co);
+
+ counter = 0;
+
+ for (i = 0; i < data->totalUniqueUvs; i++) {
+ float dist, diff[2];
+ if (data->uv[i].flag & MARK_BOUNDARY) {
+ continue;
+ }
+
+ sub_v2_v2v2(diff, data->uv[i].uv, co);
+ diff[1] /= aspectRatio;
+ if ((dist = dot_v2v2(diff, diff)) <= radius) {
+ float strength;
+ strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root);
+
+ data->initial_stroke->initialSelection[counter].uv = i;
+ data->initial_stroke->initialSelection[counter].strength = strength;
+ copy_v2_v2(data->initial_stroke->initialSelection[counter].initial_uv, data->uv[i].uv);
+ counter++;
+ }
+ }
+
+ data->initial_stroke->totalInitialSelected = counter;
+ }
+ }
+
+ return op->customdata;
}
static int uv_sculpt_stroke_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- UvSculptData *data;
- Object *obedit = CTX_data_edit_object(C);
+ UvSculptData *data;
+ Object *obedit = CTX_data_edit_object(C);
- if (!(data = uv_sculpt_stroke_init(C, op, event))) {
- return OPERATOR_CANCELLED;
- }
+ if (!(data = uv_sculpt_stroke_init(C, op, event))) {
+ return OPERATOR_CANCELLED;
+ }
- uv_sculpt_stroke_apply(C, op, event, obedit);
+ uv_sculpt_stroke_apply(C, op, event, obedit);
- data->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.001f);
+ data->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.001f);
- if (!data->timer) {
- uv_sculpt_stroke_exit(C, op);
- return OPERATOR_CANCELLED;
- }
- WM_event_add_modal_handler(C, op);
+ if (!data->timer) {
+ uv_sculpt_stroke_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
-
static int uv_sculpt_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- UvSculptData *data = (UvSculptData *)op->customdata;
- Object *obedit = CTX_data_edit_object(C);
-
- switch (event->type) {
- case LEFTMOUSE:
- case MIDDLEMOUSE:
- case RIGHTMOUSE:
- uv_sculpt_stroke_exit(C, op);
- return OPERATOR_FINISHED;
-
- case MOUSEMOVE:
- case INBETWEEN_MOUSEMOVE:
- uv_sculpt_stroke_apply(C, op, event, obedit);
- break;
- case TIMER:
- if (event->customdata == data->timer)
- uv_sculpt_stroke_apply(C, op, event, obedit);
- break;
- default:
- return OPERATOR_RUNNING_MODAL;
- }
-
- ED_region_tag_redraw(CTX_wm_region(C));
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
- return OPERATOR_RUNNING_MODAL;
+ UvSculptData *data = (UvSculptData *)op->customdata;
+ Object *obedit = CTX_data_edit_object(C);
+
+ switch (event->type) {
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ case RIGHTMOUSE:
+ uv_sculpt_stroke_exit(C, op);
+ return OPERATOR_FINISHED;
+
+ case MOUSEMOVE:
+ case INBETWEEN_MOUSEMOVE:
+ uv_sculpt_stroke_apply(C, op, event, obedit);
+ break;
+ case TIMER:
+ if (event->customdata == data->timer)
+ uv_sculpt_stroke_apply(C, op, event, obedit);
+ break;
+ default:
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ ED_region_tag_redraw(CTX_wm_region(C));
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+ return OPERATOR_RUNNING_MODAL;
}
void SCULPT_OT_uv_sculpt_stroke(wmOperatorType *ot)
{
- static const EnumPropertyItem stroke_mode_items[] = {
- {BRUSH_STROKE_NORMAL, "NORMAL", 0, "Regular", "Apply brush normally"},
- {BRUSH_STROKE_INVERT, "INVERT", 0, "Invert", "Invert action of brush for duration of stroke"},
- {BRUSH_STROKE_SMOOTH, "RELAX", 0, "Relax", "Switch brush to relax mode for duration of stroke"},
- {0},
- };
-
- /* identifiers */
- ot->name = "Sculpt UVs";
- ot->description = "Sculpt UVs using a brush";
- ot->idname = "SCULPT_OT_uv_sculpt_stroke";
-
- /* api callbacks */
- ot->invoke = uv_sculpt_stroke_invoke;
- ot->modal = uv_sculpt_stroke_modal;
- ot->poll = uv_sculpt_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- RNA_def_enum(ot->srna, "mode", stroke_mode_items, BRUSH_STROKE_NORMAL, "Mode", "Stroke Mode");
+ static const EnumPropertyItem stroke_mode_items[] = {
+ {BRUSH_STROKE_NORMAL, "NORMAL", 0, "Regular", "Apply brush normally"},
+ {BRUSH_STROKE_INVERT,
+ "INVERT",
+ 0,
+ "Invert",
+ "Invert action of brush for duration of stroke"},
+ {BRUSH_STROKE_SMOOTH,
+ "RELAX",
+ 0,
+ "Relax",
+ "Switch brush to relax mode for duration of stroke"},
+ {0},
+ };
+
+ /* identifiers */
+ ot->name = "Sculpt UVs";
+ ot->description = "Sculpt UVs using a brush";
+ ot->idname = "SCULPT_OT_uv_sculpt_stroke";
+
+ /* api callbacks */
+ ot->invoke = uv_sculpt_stroke_invoke;
+ ot->modal = uv_sculpt_stroke_modal;
+ ot->poll = uv_sculpt_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "mode", stroke_mode_items, BRUSH_STROKE_NORMAL, "Mode", "Stroke Mode");
}
diff --git a/source/blender/editors/sound/CMakeLists.txt b/source/blender/editors/sound/CMakeLists.txt
index 8b1caa0f306..c2a88041a85 100644
--- a/source/blender/editors/sound/CMakeLists.txt
+++ b/source/blender/editors/sound/CMakeLists.txt
@@ -16,13 +16,13 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
)
set(INC_SYS
@@ -30,32 +30,32 @@ set(INC_SYS
)
set(SRC
- sound_ops.c
+ sound_ops.c
- sound_intern.h
+ sound_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
+ bf_blenkernel
+ bf_blenlib
)
if(WITH_AUDASPACE)
- list(APPEND INC_SYS
- ${AUDASPACE_C_INCLUDE_DIRS}
- )
- list(APPEND LIB
- bf_intern_audaspace
- )
- add_definitions(-DWITH_AUDASPACE)
+ list(APPEND INC_SYS
+ ${AUDASPACE_C_INCLUDE_DIRS}
+ )
+ list(APPEND LIB
+ bf_intern_audaspace
+ )
+ add_definitions(-DWITH_AUDASPACE)
endif()
if(WITH_CODEC_FFMPEG)
- add_definitions(-DWITH_FFMPEG)
+ add_definitions(-DWITH_FFMPEG)
endif()
if(WITH_CODEC_SNDFILE)
- add_definitions(-DWITH_SNDFILE)
+ add_definitions(-DWITH_SNDFILE)
endif()
blender_add_lib(bf_editor_sound "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/sound/sound_intern.h b/source/blender/editors/sound/sound_intern.h
index f648c639eca..40cdb9ccf02 100644
--- a/source/blender/editors/sound/sound_intern.h
+++ b/source/blender/editors/sound/sound_intern.h
@@ -21,9 +21,7 @@
* \ingroup edsnd
*/
-
#ifndef __SOUND_INTERN_H__
#define __SOUND_INTERN_H__
-
#endif /* __SOUND_INTERN_H__ */
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index 2a64d87fcba..31dfe0bd30a 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -21,7 +21,6 @@
* \ingroup edsnd
*/
-
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
@@ -66,146 +65,155 @@
#include "ED_sound.h"
#include "ED_util.h"
-
/******************** open sound operator ********************/
static void sound_open_cancel(bContext *UNUSED(C), wmOperator *op)
{
- MEM_freeN(op->customdata);
- op->customdata = NULL;
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
}
static void sound_open_init(bContext *C, wmOperator *op)
{
- PropertyPointerRNA *pprop;
+ PropertyPointerRNA *pprop;
- op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
- UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
+ op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
+ UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
}
#ifdef WITH_AUDASPACE
static int sound_open_exec(bContext *C, wmOperator *op)
{
- char path[FILE_MAX];
- bSound *sound;
- PropertyPointerRNA *pprop;
- PointerRNA idptr;
- AUD_SoundInfo info;
- Main *bmain = CTX_data_main(C);
-
- RNA_string_get(op->ptr, "filepath", path);
- sound = BKE_sound_new_file(bmain, path);
-
- if (!op->customdata)
- sound_open_init(C, op);
-
- if (sound->playback_handle == NULL) {
- if (op->customdata) MEM_freeN(op->customdata);
- BKE_id_free(bmain, sound);
- BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
- return OPERATOR_CANCELLED;
- }
-
- info = AUD_getInfo(sound->playback_handle);
-
- if (info.specs.channels == AUD_CHANNELS_INVALID) {
- BKE_id_free(bmain, sound);
- if (op->customdata) MEM_freeN(op->customdata);
- BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
- return OPERATOR_CANCELLED;
- }
-
- if (RNA_boolean_get(op->ptr, "mono")) {
- sound->flags |= SOUND_FLAGS_MONO;
- BKE_sound_load(bmain, sound);
- }
-
- if (RNA_boolean_get(op->ptr, "cache")) {
- BKE_sound_cache(sound);
- }
-
- /* hook into UI */
- pprop = op->customdata;
-
- if (pprop->prop) {
- /* when creating new ID blocks, use is already 1, but RNA
- * pointer use also increases user, so this compensates it */
- id_us_min(&sound->id);
-
- RNA_id_pointer_create(&sound->id, &idptr);
- RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
- RNA_property_update(C, &pprop->ptr, pprop->prop);
- }
-
- MEM_freeN(op->customdata);
- return OPERATOR_FINISHED;
+ char path[FILE_MAX];
+ bSound *sound;
+ PropertyPointerRNA *pprop;
+ PointerRNA idptr;
+ AUD_SoundInfo info;
+ Main *bmain = CTX_data_main(C);
+
+ RNA_string_get(op->ptr, "filepath", path);
+ sound = BKE_sound_new_file(bmain, path);
+
+ if (!op->customdata)
+ sound_open_init(C, op);
+
+ if (sound->playback_handle == NULL) {
+ if (op->customdata)
+ MEM_freeN(op->customdata);
+ BKE_id_free(bmain, sound);
+ BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
+ return OPERATOR_CANCELLED;
+ }
+
+ info = AUD_getInfo(sound->playback_handle);
+
+ if (info.specs.channels == AUD_CHANNELS_INVALID) {
+ BKE_id_free(bmain, sound);
+ if (op->customdata)
+ MEM_freeN(op->customdata);
+ BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (RNA_boolean_get(op->ptr, "mono")) {
+ sound->flags |= SOUND_FLAGS_MONO;
+ BKE_sound_load(bmain, sound);
+ }
+
+ if (RNA_boolean_get(op->ptr, "cache")) {
+ BKE_sound_cache(sound);
+ }
+
+ /* hook into UI */
+ pprop = op->customdata;
+
+ if (pprop->prop) {
+ /* when creating new ID blocks, use is already 1, but RNA
+ * pointer use also increases user, so this compensates it */
+ id_us_min(&sound->id);
+
+ RNA_id_pointer_create(&sound->id, &idptr);
+ RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
+ RNA_property_update(C, &pprop->ptr, pprop->prop);
+ }
+
+ MEM_freeN(op->customdata);
+ return OPERATOR_FINISHED;
}
-#else //WITH_AUDASPACE
+#else //WITH_AUDASPACE
static int sound_open_exec(bContext *UNUSED(C), wmOperator *op)
{
- BKE_report(op->reports, RPT_ERROR, "Compiled without sound support");
+ BKE_report(op->reports, RPT_ERROR, "Compiled without sound support");
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
#endif
static int sound_open_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (RNA_struct_property_is_set(op->ptr, "filepath"))
- return sound_open_exec(C, op);
+ if (RNA_struct_property_is_set(op->ptr, "filepath"))
+ return sound_open_exec(C, op);
- sound_open_init(C, op);
+ sound_open_init(C, op);
- return WM_operator_filesel(C, op, event);
+ return WM_operator_filesel(C, op, event);
}
static void SOUND_OT_open(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Open Sound";
- ot->description = "Load a sound file";
- ot->idname = "SOUND_OT_open";
-
- /* api callbacks */
- ot->exec = sound_open_exec;
- ot->invoke = sound_open_invoke;
- ot->cancel = sound_open_cancel;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
- RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
- RNA_def_boolean(ot->srna, "mono", false, "Mono", "Merge all the sound's channels into one");
+ /* identifiers */
+ ot->name = "Open Sound";
+ ot->description = "Load a sound file";
+ ot->idname = "SOUND_OT_open";
+
+ /* api callbacks */
+ ot->exec = sound_open_exec;
+ ot->invoke = sound_open_invoke;
+ ot->cancel = sound_open_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
+ RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
+ RNA_def_boolean(ot->srna, "mono", false, "Mono", "Merge all the sound's channels into one");
}
static void SOUND_OT_open_mono(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Open Sound Mono";
- ot->description = "Load a sound file as mono";
- ot->idname = "SOUND_OT_open_mono";
-
- /* api callbacks */
- ot->exec = sound_open_exec;
- ot->invoke = sound_open_invoke;
- ot->cancel = sound_open_cancel;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
- RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
- RNA_def_boolean(ot->srna, "mono", true, "Mono", "Mixdown the sound to mono");
+ /* identifiers */
+ ot->name = "Open Sound Mono";
+ ot->description = "Load a sound file as mono";
+ ot->idname = "SOUND_OT_open_mono";
+
+ /* api callbacks */
+ ot->exec = sound_open_exec;
+ ot->invoke = sound_open_invoke;
+ ot->cancel = sound_open_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
+ RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
+ RNA_def_boolean(ot->srna, "mono", true, "Mono", "Mixdown the sound to mono");
}
/* ******************************************************* */
@@ -214,613 +222,650 @@ static void sound_update_animation_flags(Scene *scene);
static int sound_update_animation_flags_cb(Sequence *seq, void *user_data)
{
- struct FCurve *fcu;
- Scene *scene = (Scene *)user_data;
- bool driven;
-
- fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "volume", 0, &driven);
- if (fcu || driven)
- seq->flag |= SEQ_AUDIO_VOLUME_ANIMATED;
- else
- seq->flag &= ~SEQ_AUDIO_VOLUME_ANIMATED;
-
- fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "pitch", 0, &driven);
- if (fcu || driven)
- seq->flag |= SEQ_AUDIO_PITCH_ANIMATED;
- else
- seq->flag &= ~SEQ_AUDIO_PITCH_ANIMATED;
-
- fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "pan", 0, &driven);
- if (fcu || driven)
- seq->flag |= SEQ_AUDIO_PAN_ANIMATED;
- else
- seq->flag &= ~SEQ_AUDIO_PAN_ANIMATED;
-
- if (seq->type == SEQ_TYPE_SCENE) {
- /* TODO(sergey): For now we do manual recursion into the scene strips,
- * but perhaps it should be covered by recursive_apply?
- */
- sound_update_animation_flags(seq->scene);
- }
-
- return 0;
+ struct FCurve *fcu;
+ Scene *scene = (Scene *)user_data;
+ bool driven;
+
+ fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "volume", 0, &driven);
+ if (fcu || driven)
+ seq->flag |= SEQ_AUDIO_VOLUME_ANIMATED;
+ else
+ seq->flag &= ~SEQ_AUDIO_VOLUME_ANIMATED;
+
+ fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "pitch", 0, &driven);
+ if (fcu || driven)
+ seq->flag |= SEQ_AUDIO_PITCH_ANIMATED;
+ else
+ seq->flag &= ~SEQ_AUDIO_PITCH_ANIMATED;
+
+ fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "pan", 0, &driven);
+ if (fcu || driven)
+ seq->flag |= SEQ_AUDIO_PAN_ANIMATED;
+ else
+ seq->flag &= ~SEQ_AUDIO_PAN_ANIMATED;
+
+ if (seq->type == SEQ_TYPE_SCENE) {
+ /* TODO(sergey): For now we do manual recursion into the scene strips,
+ * but perhaps it should be covered by recursive_apply?
+ */
+ sound_update_animation_flags(seq->scene);
+ }
+
+ return 0;
}
static void sound_update_animation_flags(Scene *scene)
{
- struct FCurve *fcu;
- bool driven;
- Sequence *seq;
-
- if (scene->id.tag & LIB_TAG_DOIT) {
- return;
- }
- scene->id.tag |= LIB_TAG_DOIT;
-
- SEQ_BEGIN(scene->ed, seq)
- {
- BKE_sequencer_recursive_apply(seq, sound_update_animation_flags_cb, scene);
- } SEQ_END;
-
- fcu = id_data_find_fcurve(&scene->id, scene, &RNA_Scene, "audio_volume", 0, &driven);
- if (fcu || driven)
- scene->audio.flag |= AUDIO_VOLUME_ANIMATED;
- else
- scene->audio.flag &= ~AUDIO_VOLUME_ANIMATED;
+ struct FCurve *fcu;
+ bool driven;
+ Sequence *seq;
+
+ if (scene->id.tag & LIB_TAG_DOIT) {
+ return;
+ }
+ scene->id.tag |= LIB_TAG_DOIT;
+
+ SEQ_BEGIN (scene->ed, seq) {
+ BKE_sequencer_recursive_apply(seq, sound_update_animation_flags_cb, scene);
+ }
+ SEQ_END;
+
+ fcu = id_data_find_fcurve(&scene->id, scene, &RNA_Scene, "audio_volume", 0, &driven);
+ if (fcu || driven)
+ scene->audio.flag |= AUDIO_VOLUME_ANIMATED;
+ else
+ scene->audio.flag &= ~AUDIO_VOLUME_ANIMATED;
}
static int sound_update_animation_flags_exec(bContext *C, wmOperator *UNUSED(op))
{
- BKE_main_id_tag_idcode(CTX_data_main(C), ID_SCE, LIB_TAG_DOIT, false);
- sound_update_animation_flags(CTX_data_scene(C));
- return OPERATOR_FINISHED;
+ BKE_main_id_tag_idcode(CTX_data_main(C), ID_SCE, LIB_TAG_DOIT, false);
+ sound_update_animation_flags(CTX_data_scene(C));
+ return OPERATOR_FINISHED;
}
static void SOUND_OT_update_animation_flags(wmOperatorType *ot)
{
- /*
- * This operator is needed to set a correct state of the sound animation
- * System. Unfortunately there's no really correct place to call the exec
- * function, that's why I made it an operator that's only visible in the
- * search menu. Apart from that the bake animation operator calls it too.
- */
-
- /* identifiers */
- ot->name = "Update Animation";
- ot->description = "Update animation flags";
- ot->idname = "SOUND_OT_update_animation_flags";
-
- /* api callbacks */
- ot->exec = sound_update_animation_flags_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /*
+ * This operator is needed to set a correct state of the sound animation
+ * System. Unfortunately there's no really correct place to call the exec
+ * function, that's why I made it an operator that's only visible in the
+ * search menu. Apart from that the bake animation operator calls it too.
+ */
+
+ /* identifiers */
+ ot->name = "Update Animation";
+ ot->description = "Update animation flags";
+ ot->idname = "SOUND_OT_update_animation_flags";
+
+ /* api callbacks */
+ ot->exec = sound_update_animation_flags_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
}
/* ******************************************************* */
static int sound_bake_animation_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int oldfra = scene->r.cfra;
- int cfra;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int oldfra = scene->r.cfra;
+ int cfra;
- sound_update_animation_flags_exec(C, NULL);
+ sound_update_animation_flags_exec(C, NULL);
- for (cfra = (scene->r.sfra > 0) ? (scene->r.sfra - 1) : 0; cfra <= scene->r.efra + 1; cfra++) {
- scene->r.cfra = cfra;
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
- }
+ for (cfra = (scene->r.sfra > 0) ? (scene->r.sfra - 1) : 0; cfra <= scene->r.efra + 1; cfra++) {
+ scene->r.cfra = cfra;
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+ }
- scene->r.cfra = oldfra;
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+ scene->r.cfra = oldfra;
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SOUND_OT_bake_animation(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Update Animation Cache";
- ot->description = "Update the audio animation cache";
- ot->idname = "SOUND_OT_bake_animation";
+ /* identifiers */
+ ot->name = "Update Animation Cache";
+ ot->description = "Update the audio animation cache";
+ ot->idname = "SOUND_OT_bake_animation";
- /* api callbacks */
- ot->exec = sound_bake_animation_exec;
+ /* api callbacks */
+ ot->exec = sound_bake_animation_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
}
-
/******************** mixdown operator ********************/
static int sound_mixdown_exec(bContext *C, wmOperator *op)
{
#ifdef WITH_AUDASPACE
- char path[FILE_MAX];
- char filename[FILE_MAX];
- Scene *scene;
- Main *bmain;
- int split;
-
- int bitrate, accuracy;
- AUD_DeviceSpecs specs;
- AUD_Container container;
- AUD_Codec codec;
- const char *result;
-
- sound_bake_animation_exec(C, op);
-
- RNA_string_get(op->ptr, "filepath", path);
- bitrate = RNA_int_get(op->ptr, "bitrate") * 1000;
- accuracy = RNA_int_get(op->ptr, "accuracy");
- specs.format = RNA_enum_get(op->ptr, "format");
- container = RNA_enum_get(op->ptr, "container");
- codec = RNA_enum_get(op->ptr, "codec");
- split = RNA_boolean_get(op->ptr, "split_channels");
- scene = CTX_data_scene(C);
- bmain = CTX_data_main(C);
- specs.channels = scene->r.ffcodecdata.audio_channels;
- specs.rate = scene->r.ffcodecdata.audio_mixrate;
-
- BLI_strncpy(filename, path, sizeof(filename));
- BLI_path_abs(filename, BKE_main_blendfile_path(bmain));
-
- if (split)
- result = AUD_mixdown_per_channel(scene->sound_scene, SFRA * specs.rate / FPS, (EFRA - SFRA + 1) * specs.rate / FPS,
- accuracy, filename, specs, container, codec, bitrate);
- else
- result = AUD_mixdown(scene->sound_scene, SFRA * specs.rate / FPS, (EFRA - SFRA + 1) * specs.rate / FPS,
- accuracy, filename, specs, container, codec, bitrate);
-
- BKE_sound_reset_scene_specs(scene);
-
- if (result) {
- BKE_report(op->reports, RPT_ERROR, result);
- return OPERATOR_CANCELLED;
- }
-#else // WITH_AUDASPACE
- (void)C;
- (void)op;
-#endif // WITH_AUDASPACE
- return OPERATOR_FINISHED;
+ char path[FILE_MAX];
+ char filename[FILE_MAX];
+ Scene *scene;
+ Main *bmain;
+ int split;
+
+ int bitrate, accuracy;
+ AUD_DeviceSpecs specs;
+ AUD_Container container;
+ AUD_Codec codec;
+ const char *result;
+
+ sound_bake_animation_exec(C, op);
+
+ RNA_string_get(op->ptr, "filepath", path);
+ bitrate = RNA_int_get(op->ptr, "bitrate") * 1000;
+ accuracy = RNA_int_get(op->ptr, "accuracy");
+ specs.format = RNA_enum_get(op->ptr, "format");
+ container = RNA_enum_get(op->ptr, "container");
+ codec = RNA_enum_get(op->ptr, "codec");
+ split = RNA_boolean_get(op->ptr, "split_channels");
+ scene = CTX_data_scene(C);
+ bmain = CTX_data_main(C);
+ specs.channels = scene->r.ffcodecdata.audio_channels;
+ specs.rate = scene->r.ffcodecdata.audio_mixrate;
+
+ BLI_strncpy(filename, path, sizeof(filename));
+ BLI_path_abs(filename, BKE_main_blendfile_path(bmain));
+
+ if (split)
+ result = AUD_mixdown_per_channel(scene->sound_scene,
+ SFRA * specs.rate / FPS,
+ (EFRA - SFRA + 1) * specs.rate / FPS,
+ accuracy,
+ filename,
+ specs,
+ container,
+ codec,
+ bitrate);
+ else
+ result = AUD_mixdown(scene->sound_scene,
+ SFRA * specs.rate / FPS,
+ (EFRA - SFRA + 1) * specs.rate / FPS,
+ accuracy,
+ filename,
+ specs,
+ container,
+ codec,
+ bitrate);
+
+ BKE_sound_reset_scene_specs(scene);
+
+ if (result) {
+ BKE_report(op->reports, RPT_ERROR, result);
+ return OPERATOR_CANCELLED;
+ }
+#else // WITH_AUDASPACE
+ (void)C;
+ (void)op;
+#endif // WITH_AUDASPACE
+ return OPERATOR_FINISHED;
}
#ifdef WITH_AUDASPACE
static const EnumPropertyItem container_items[] = {
-#ifdef WITH_FFMPEG
- {AUD_CONTAINER_AC3, "AC3", 0, "ac3", "Dolby Digital ATRAC 3"},
-#endif
- {AUD_CONTAINER_FLAC, "FLAC", 0, "flac", "Free Lossless Audio Codec"},
-#ifdef WITH_FFMPEG
- {AUD_CONTAINER_MATROSKA, "MATROSKA", 0, "mkv", "Matroska"},
- {AUD_CONTAINER_MP2, "MP2", 0, "mp2", "MPEG-1 Audio Layer II"},
- {AUD_CONTAINER_MP3, "MP3", 0, "mp3", "MPEG-2 Audio Layer III"},
-#endif
- {AUD_CONTAINER_OGG, "OGG", 0, "ogg", "Xiph.Org Ogg Container"},
- {AUD_CONTAINER_WAV, "WAV", 0, "wav", "Waveform Audio File Format"},
- {0, NULL, 0, NULL, NULL},
+# ifdef WITH_FFMPEG
+ {AUD_CONTAINER_AC3, "AC3", 0, "ac3", "Dolby Digital ATRAC 3"},
+# endif
+ {AUD_CONTAINER_FLAC, "FLAC", 0, "flac", "Free Lossless Audio Codec"},
+# ifdef WITH_FFMPEG
+ {AUD_CONTAINER_MATROSKA, "MATROSKA", 0, "mkv", "Matroska"},
+ {AUD_CONTAINER_MP2, "MP2", 0, "mp2", "MPEG-1 Audio Layer II"},
+ {AUD_CONTAINER_MP3, "MP3", 0, "mp3", "MPEG-2 Audio Layer III"},
+# endif
+ {AUD_CONTAINER_OGG, "OGG", 0, "ogg", "Xiph.Org Ogg Container"},
+ {AUD_CONTAINER_WAV, "WAV", 0, "wav", "Waveform Audio File Format"},
+ {0, NULL, 0, NULL, NULL},
};
static const char *snd_ext_sound[] = {
- ".ac3",
- ".flac",
- ".mkv",
- ".mp2",
- ".mp3",
- ".ogg",
- ".wav",
- NULL,
+ ".ac3",
+ ".flac",
+ ".mkv",
+ ".mp2",
+ ".mp3",
+ ".ogg",
+ ".wav",
+ NULL,
};
static bool sound_mixdown_check(bContext *UNUSED(C), wmOperator *op)
{
- AUD_Container container = RNA_enum_get(op->ptr, "container");
+ AUD_Container container = RNA_enum_get(op->ptr, "container");
- const char *extension = NULL;
+ const char *extension = NULL;
- const EnumPropertyItem *item = container_items;
- while (item->identifier != NULL) {
- if (item->value == container) {
- const char **ext = snd_ext_sound;
- while (*ext != NULL) {
- if (STREQ(*ext + 1, item->name)) {
- extension = *ext;
- break;
- }
+ const EnumPropertyItem *item = container_items;
+ while (item->identifier != NULL) {
+ if (item->value == container) {
+ const char **ext = snd_ext_sound;
+ while (*ext != NULL) {
+ if (STREQ(*ext + 1, item->name)) {
+ extension = *ext;
+ break;
+ }
- ext++;
- }
- }
- item++;
- }
+ ext++;
+ }
+ }
+ item++;
+ }
- if (extension) {
- PropertyRNA *prop;
- char filepath[FILE_MAX];
+ if (extension) {
+ PropertyRNA *prop;
+ char filepath[FILE_MAX];
- int check;
+ int check;
- prop = RNA_struct_find_property(op->ptr, "filepath");
- RNA_property_string_get(op->ptr, prop, filepath);
+ prop = RNA_struct_find_property(op->ptr, "filepath");
+ RNA_property_string_get(op->ptr, prop, filepath);
- if (BLI_path_extension_check_array(filepath, snd_ext_sound))
- check = BLI_path_extension_replace(filepath, FILE_MAX, extension);
- else
- check = BLI_path_extension_ensure(filepath, FILE_MAX, extension);
+ if (BLI_path_extension_check_array(filepath, snd_ext_sound))
+ check = BLI_path_extension_replace(filepath, FILE_MAX, extension);
+ else
+ check = BLI_path_extension_ensure(filepath, FILE_MAX, extension);
- if (!check)
- return check;
+ if (!check)
+ return check;
- RNA_property_string_set(op->ptr, prop, filepath);
- return true;
- }
+ RNA_property_string_set(op->ptr, prop, filepath);
+ return true;
+ }
- return false;
+ return false;
}
-#endif // WITH_AUDASPACE
+#endif // WITH_AUDASPACE
static int sound_mixdown_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (RNA_struct_property_is_set(op->ptr, "filepath"))
- return sound_mixdown_exec(C, op);
+ if (RNA_struct_property_is_set(op->ptr, "filepath"))
+ return sound_mixdown_exec(C, op);
- return WM_operator_filesel(C, op, event);
+ return WM_operator_filesel(C, op, event);
}
#ifdef WITH_AUDASPACE
-static bool sound_mixdown_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop, void *UNUSED(user_data))
+static bool sound_mixdown_draw_check_prop(PointerRNA *UNUSED(ptr),
+ PropertyRNA *prop,
+ void *UNUSED(user_data))
{
- const char *prop_id = RNA_property_identifier(prop);
- return !(STREQ(prop_id, "filepath") ||
- STREQ(prop_id, "directory") ||
- STREQ(prop_id, "filename"));
+ const char *prop_id = RNA_property_identifier(prop);
+ return !(STREQ(prop_id, "filepath") || STREQ(prop_id, "directory") ||
+ STREQ(prop_id, "filename"));
}
static void sound_mixdown_draw(bContext *C, wmOperator *op)
{
- static const EnumPropertyItem pcm_format_items[] = {
- {AUD_FORMAT_U8, "U8", 0, "U8", "8 bit unsigned"},
- {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
-#ifdef WITH_SNDFILE
- {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"},
-#endif
- {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"},
- {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32 bit floating point"},
- {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64 bit floating point"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem mp3_format_items[] = {
- {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
- {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"},
- {0, NULL, 0, NULL, NULL},
- };
-
-#ifdef WITH_SNDFILE
- static const EnumPropertyItem flac_format_items[] = {
- {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
- {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"},
- {0, NULL, 0, NULL, NULL},
- };
-#endif
-
- static const EnumPropertyItem all_codec_items[] = {
- {AUD_CODEC_AAC, "AAC", 0, "AAC", "Advanced Audio Coding"},
- {AUD_CODEC_AC3, "AC3", 0, "AC3", "Dolby Digital ATRAC 3"},
- {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
- {AUD_CODEC_MP2, "MP2", 0, "MP2", "MPEG-1 Audio Layer II"},
- {AUD_CODEC_MP3, "MP3", 0, "MP3", "MPEG-2 Audio Layer III"},
- {AUD_CODEC_PCM, "PCM", 0, "PCM", "Pulse Code Modulation (RAW)"},
- {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem ogg_codec_items[] = {
- {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
- {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
- {0, NULL, 0, NULL, NULL},
- };
-
- uiLayout *layout = op->layout;
- wmWindowManager *wm = CTX_wm_manager(C);
- PointerRNA ptr;
- PropertyRNA *prop_format;
- PropertyRNA *prop_codec;
- PropertyRNA *prop_bitrate;
-
- AUD_Container container = RNA_enum_get(op->ptr, "container");
- AUD_Codec codec = RNA_enum_get(op->ptr, "codec");
-
- prop_format = RNA_struct_find_property(op->ptr, "format");
- prop_codec = RNA_struct_find_property(op->ptr, "codec");
- prop_bitrate = RNA_struct_find_property(op->ptr, "bitrate");
-
- RNA_def_property_clear_flag(prop_bitrate, PROP_HIDDEN);
- RNA_def_property_flag(prop_codec, PROP_HIDDEN);
- RNA_def_property_flag(prop_format, PROP_HIDDEN);
-
- switch (container) {
- case AUD_CONTAINER_AC3:
- RNA_def_property_enum_items(prop_codec, all_codec_items);
- RNA_enum_set(op->ptr, "codec", AUD_CODEC_AC3);
- RNA_enum_set(op->ptr, "format", AUD_FORMAT_FLOAT32);
- break;
- case AUD_CONTAINER_FLAC:
- RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
- RNA_def_property_enum_items(prop_codec, all_codec_items);
- RNA_enum_set(op->ptr, "codec", AUD_CODEC_FLAC);
-#ifdef WITH_SNDFILE
- RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
- RNA_def_property_enum_items(prop_format, flac_format_items);
-#else
- RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
-#endif
- break;
- case AUD_CONTAINER_MATROSKA:
- RNA_def_property_clear_flag(prop_codec, PROP_HIDDEN);
- RNA_def_property_enum_items(prop_codec, all_codec_items);
-
- switch (codec) {
- case AUD_CODEC_AAC:
- RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
- break;
- case AUD_CODEC_AC3:
- RNA_enum_set(op->ptr, "format", AUD_FORMAT_FLOAT32);
- break;
- case AUD_CODEC_FLAC:
- RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
- RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
- break;
- case AUD_CODEC_MP2:
- RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
- break;
- case AUD_CODEC_MP3:
- RNA_def_property_enum_items(prop_format, mp3_format_items);
- RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
- break;
- case AUD_CODEC_PCM:
- RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
- RNA_def_property_enum_items(prop_format, pcm_format_items);
- RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
- break;
- case AUD_CODEC_VORBIS:
- RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
- break;
- default:
- break;
- }
-
- break;
- case AUD_CONTAINER_MP2:
- RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
- RNA_enum_set(op->ptr, "codec", AUD_CODEC_MP2);
- RNA_def_property_enum_items(prop_codec, all_codec_items);
- break;
- case AUD_CONTAINER_MP3:
- RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
- RNA_def_property_enum_items(prop_format, mp3_format_items);
- RNA_def_property_enum_items(prop_codec, all_codec_items);
- RNA_enum_set(op->ptr, "codec", AUD_CODEC_MP3);
- break;
- case AUD_CONTAINER_OGG:
- RNA_def_property_clear_flag(prop_codec, PROP_HIDDEN);
- RNA_def_property_enum_items(prop_codec, ogg_codec_items);
- RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
- break;
- case AUD_CONTAINER_WAV:
- RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
- RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
- RNA_def_property_enum_items(prop_format, pcm_format_items);
- RNA_def_property_enum_items(prop_codec, all_codec_items);
- RNA_enum_set(op->ptr, "codec", AUD_CODEC_PCM);
- break;
- default:
- break;
- }
-
- RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
-
- /* main draw call */
- uiDefAutoButsRNA(layout, &ptr, sound_mixdown_draw_check_prop, NULL, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
+ static const EnumPropertyItem pcm_format_items[] = {
+ {AUD_FORMAT_U8, "U8", 0, "U8", "8 bit unsigned"},
+ {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
+# ifdef WITH_SNDFILE
+ {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"},
+# endif
+ {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"},
+ {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32 bit floating point"},
+ {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64 bit floating point"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem mp3_format_items[] = {
+ {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
+ {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+# ifdef WITH_SNDFILE
+ static const EnumPropertyItem flac_format_items[] = {
+ {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
+ {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"},
+ {0, NULL, 0, NULL, NULL},
+ };
+# endif
+
+ static const EnumPropertyItem all_codec_items[] = {
+ {AUD_CODEC_AAC, "AAC", 0, "AAC", "Advanced Audio Coding"},
+ {AUD_CODEC_AC3, "AC3", 0, "AC3", "Dolby Digital ATRAC 3"},
+ {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
+ {AUD_CODEC_MP2, "MP2", 0, "MP2", "MPEG-1 Audio Layer II"},
+ {AUD_CODEC_MP3, "MP3", 0, "MP3", "MPEG-2 Audio Layer III"},
+ {AUD_CODEC_PCM, "PCM", 0, "PCM", "Pulse Code Modulation (RAW)"},
+ {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem ogg_codec_items[] = {
+ {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
+ {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ uiLayout *layout = op->layout;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ PointerRNA ptr;
+ PropertyRNA *prop_format;
+ PropertyRNA *prop_codec;
+ PropertyRNA *prop_bitrate;
+
+ AUD_Container container = RNA_enum_get(op->ptr, "container");
+ AUD_Codec codec = RNA_enum_get(op->ptr, "codec");
+
+ prop_format = RNA_struct_find_property(op->ptr, "format");
+ prop_codec = RNA_struct_find_property(op->ptr, "codec");
+ prop_bitrate = RNA_struct_find_property(op->ptr, "bitrate");
+
+ RNA_def_property_clear_flag(prop_bitrate, PROP_HIDDEN);
+ RNA_def_property_flag(prop_codec, PROP_HIDDEN);
+ RNA_def_property_flag(prop_format, PROP_HIDDEN);
+
+ switch (container) {
+ case AUD_CONTAINER_AC3:
+ RNA_def_property_enum_items(prop_codec, all_codec_items);
+ RNA_enum_set(op->ptr, "codec", AUD_CODEC_AC3);
+ RNA_enum_set(op->ptr, "format", AUD_FORMAT_FLOAT32);
+ break;
+ case AUD_CONTAINER_FLAC:
+ RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
+ RNA_def_property_enum_items(prop_codec, all_codec_items);
+ RNA_enum_set(op->ptr, "codec", AUD_CODEC_FLAC);
+# ifdef WITH_SNDFILE
+ RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
+ RNA_def_property_enum_items(prop_format, flac_format_items);
+# else
+ RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
+# endif
+ break;
+ case AUD_CONTAINER_MATROSKA:
+ RNA_def_property_clear_flag(prop_codec, PROP_HIDDEN);
+ RNA_def_property_enum_items(prop_codec, all_codec_items);
+
+ switch (codec) {
+ case AUD_CODEC_AAC:
+ RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
+ break;
+ case AUD_CODEC_AC3:
+ RNA_enum_set(op->ptr, "format", AUD_FORMAT_FLOAT32);
+ break;
+ case AUD_CODEC_FLAC:
+ RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
+ RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
+ break;
+ case AUD_CODEC_MP2:
+ RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
+ break;
+ case AUD_CODEC_MP3:
+ RNA_def_property_enum_items(prop_format, mp3_format_items);
+ RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
+ break;
+ case AUD_CODEC_PCM:
+ RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
+ RNA_def_property_enum_items(prop_format, pcm_format_items);
+ RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
+ break;
+ case AUD_CODEC_VORBIS:
+ RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
+ break;
+ default:
+ break;
+ }
+
+ break;
+ case AUD_CONTAINER_MP2:
+ RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
+ RNA_enum_set(op->ptr, "codec", AUD_CODEC_MP2);
+ RNA_def_property_enum_items(prop_codec, all_codec_items);
+ break;
+ case AUD_CONTAINER_MP3:
+ RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
+ RNA_def_property_enum_items(prop_format, mp3_format_items);
+ RNA_def_property_enum_items(prop_codec, all_codec_items);
+ RNA_enum_set(op->ptr, "codec", AUD_CODEC_MP3);
+ break;
+ case AUD_CONTAINER_OGG:
+ RNA_def_property_clear_flag(prop_codec, PROP_HIDDEN);
+ RNA_def_property_enum_items(prop_codec, ogg_codec_items);
+ RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
+ break;
+ case AUD_CONTAINER_WAV:
+ RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
+ RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
+ RNA_def_property_enum_items(prop_format, pcm_format_items);
+ RNA_def_property_enum_items(prop_codec, all_codec_items);
+ RNA_enum_set(op->ptr, "codec", AUD_CODEC_PCM);
+ break;
+ default:
+ break;
+ }
+
+ RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+
+ /* main draw call */
+ uiDefAutoButsRNA(
+ layout, &ptr, sound_mixdown_draw_check_prop, NULL, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
}
-#endif // WITH_AUDASPACE
+#endif // WITH_AUDASPACE
static void SOUND_OT_mixdown(wmOperatorType *ot)
{
#ifdef WITH_AUDASPACE
- static const EnumPropertyItem format_items[] = {
- {AUD_FORMAT_U8, "U8", 0, "U8", "8 bit unsigned"},
- {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
- {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"},
- {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"},
- {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32 bit floating point"},
- {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64 bit floating point"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem codec_items[] = {
-#ifdef WITH_FFMPEG
- {AUD_CODEC_AAC, "AAC", 0, "AAC", "Advanced Audio Coding"},
- {AUD_CODEC_AC3, "AC3", 0, "AC3", "Dolby Digital ATRAC 3"},
-#endif
- {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
-#ifdef WITH_FFMPEG
- {AUD_CODEC_MP2, "MP2", 0, "MP2", "MPEG-1 Audio Layer II"},
- {AUD_CODEC_MP3, "MP3", 0, "MP3", "MPEG-2 Audio Layer III"},
-#endif
- {AUD_CODEC_PCM, "PCM", 0, "PCM", "Pulse Code Modulation (RAW)"},
- {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
- {0, NULL, 0, NULL, NULL},
- };
-
-#endif // WITH_AUDASPACE
-
- /* identifiers */
- ot->name = "Mixdown";
- ot->description = "Mix the scene's audio to a sound file";
- ot->idname = "SOUND_OT_mixdown";
-
- /* api callbacks */
- ot->exec = sound_mixdown_exec;
- ot->invoke = sound_mixdown_invoke;
+ static const EnumPropertyItem format_items[] = {
+ {AUD_FORMAT_U8, "U8", 0, "U8", "8 bit unsigned"},
+ {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
+ {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"},
+ {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"},
+ {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32 bit floating point"},
+ {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64 bit floating point"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem codec_items[] = {
+# ifdef WITH_FFMPEG
+ {AUD_CODEC_AAC, "AAC", 0, "AAC", "Advanced Audio Coding"},
+ {AUD_CODEC_AC3, "AC3", 0, "AC3", "Dolby Digital ATRAC 3"},
+# endif
+ {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
+# ifdef WITH_FFMPEG
+ {AUD_CODEC_MP2, "MP2", 0, "MP2", "MPEG-1 Audio Layer II"},
+ {AUD_CODEC_MP3, "MP3", 0, "MP3", "MPEG-2 Audio Layer III"},
+# endif
+ {AUD_CODEC_PCM, "PCM", 0, "PCM", "Pulse Code Modulation (RAW)"},
+ {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+#endif // WITH_AUDASPACE
+
+ /* identifiers */
+ ot->name = "Mixdown";
+ ot->description = "Mix the scene's audio to a sound file";
+ ot->idname = "SOUND_OT_mixdown";
+
+ /* api callbacks */
+ ot->exec = sound_mixdown_exec;
+ ot->invoke = sound_mixdown_invoke;
#ifdef WITH_AUDASPACE
- ot->check = sound_mixdown_check;
- ot->ui = sound_mixdown_draw;
+ ot->check = sound_mixdown_check;
+ ot->ui = sound_mixdown_draw;
#endif
- /* flags */
- ot->flag = OPTYPE_REGISTER;
-
- /* properties */
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_SOUND, FILE_SPECIAL, FILE_SAVE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
+
+ /* properties */
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_SOUND,
+ FILE_SPECIAL,
+ FILE_SAVE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
#ifdef WITH_AUDASPACE
- RNA_def_int(ot->srna, "accuracy", 1024, 1, 16777216, "Accuracy",
- "Sample accuracy, important for animation data (the lower the value, the more accurate)",
- 1, 16777216);
- RNA_def_enum(ot->srna, "container", container_items, AUD_CONTAINER_FLAC, "Container", "File format");
- RNA_def_enum(ot->srna, "codec", codec_items, AUD_CODEC_FLAC, "Codec", "Audio Codec");
- RNA_def_enum(ot->srna, "format", format_items, AUD_FORMAT_S16, "Format", "Sample format");
- RNA_def_int(ot->srna, "bitrate", 192, 32, 512, "Bitrate", "Bitrate in kbit/s", 32, 512);
- RNA_def_boolean(ot->srna, "split_channels", 0, "Split channels", "Each channel will be rendered into a mono file");
-#endif // WITH_AUDASPACE
+ RNA_def_int(
+ ot->srna,
+ "accuracy",
+ 1024,
+ 1,
+ 16777216,
+ "Accuracy",
+ "Sample accuracy, important for animation data (the lower the value, the more accurate)",
+ 1,
+ 16777216);
+ RNA_def_enum(
+ ot->srna, "container", container_items, AUD_CONTAINER_FLAC, "Container", "File format");
+ RNA_def_enum(ot->srna, "codec", codec_items, AUD_CODEC_FLAC, "Codec", "Audio Codec");
+ RNA_def_enum(ot->srna, "format", format_items, AUD_FORMAT_S16, "Format", "Sample format");
+ RNA_def_int(ot->srna, "bitrate", 192, 32, 512, "Bitrate", "Bitrate in kbit/s", 32, 512);
+ RNA_def_boolean(ot->srna,
+ "split_channels",
+ 0,
+ "Split channels",
+ "Each channel will be rendered into a mono file");
+#endif // WITH_AUDASPACE
}
/* ******************************************************* */
static bool sound_poll(bContext *C)
{
- Editing *ed = CTX_data_scene(C)->ed;
+ Editing *ed = CTX_data_scene(C)->ed;
- if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM)
- return 0;
+ if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM)
+ return 0;
- return 1;
+ return 1;
}
/********************* pack operator *********************/
static int sound_pack_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Editing *ed = CTX_data_scene(C)->ed;
- bSound *sound;
+ Main *bmain = CTX_data_main(C);
+ Editing *ed = CTX_data_scene(C)->ed;
+ bSound *sound;
- if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM)
- return OPERATOR_CANCELLED;
+ if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM)
+ return OPERATOR_CANCELLED;
- sound = ed->act_seq->sound;
+ sound = ed->act_seq->sound;
- if (!sound || sound->packedfile)
- return OPERATOR_CANCELLED;
+ if (!sound || sound->packedfile)
+ return OPERATOR_CANCELLED;
- sound->packedfile = newPackedFile(op->reports, sound->name, ID_BLEND_PATH(bmain, &sound->id));
- BKE_sound_load(bmain, sound);
+ sound->packedfile = newPackedFile(op->reports, sound->name, ID_BLEND_PATH(bmain, &sound->id));
+ BKE_sound_load(bmain, sound);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SOUND_OT_pack(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Pack Sound";
- ot->description = "Pack the sound into the current blend file";
- ot->idname = "SOUND_OT_pack";
+ /* identifiers */
+ ot->name = "Pack Sound";
+ ot->description = "Pack the sound into the current blend file";
+ ot->idname = "SOUND_OT_pack";
- /* api callbacks */
- ot->exec = sound_pack_exec;
- ot->poll = sound_poll;
+ /* api callbacks */
+ ot->exec = sound_pack_exec;
+ ot->poll = sound_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************* unpack operator *********************/
static int sound_unpack_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- int method = RNA_enum_get(op->ptr, "method");
- bSound *sound = NULL;
+ Main *bmain = CTX_data_main(C);
+ int method = RNA_enum_get(op->ptr, "method");
+ bSound *sound = NULL;
- /* find the suppplied 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);
- sound = BLI_findstring(&bmain->sounds, sndname, offsetof(ID, name) + 2);
- }
+ /* find the suppplied 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);
+ sound = BLI_findstring(&bmain->sounds, sndname, offsetof(ID, name) + 2);
+ }
- if (!sound || !sound->packedfile)
- return OPERATOR_CANCELLED;
+ if (!sound || !sound->packedfile)
+ return OPERATOR_CANCELLED;
- if (G.fileflags & G_FILE_AUTOPACK)
- BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so image will be packed again on file save");
+ if (G.fileflags & G_FILE_AUTOPACK)
+ BKE_report(op->reports,
+ RPT_WARNING,
+ "AutoPack is enabled, so image will be packed again on file save");
- unpackSound(bmain, op->reports, sound, method);
+ unpackSound(bmain, op->reports, sound, method);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int sound_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Editing *ed = CTX_data_scene(C)->ed;
- bSound *sound;
+ Editing *ed = CTX_data_scene(C)->ed;
+ bSound *sound;
- if (RNA_struct_property_is_set(op->ptr, "id"))
- return sound_unpack_exec(C, op);
+ if (RNA_struct_property_is_set(op->ptr, "id"))
+ return sound_unpack_exec(C, op);
- if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM)
- return OPERATOR_CANCELLED;
+ if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM)
+ return OPERATOR_CANCELLED;
- sound = ed->act_seq->sound;
+ sound = ed->act_seq->sound;
- if (!sound || !sound->packedfile)
- return OPERATOR_CANCELLED;
+ if (!sound || !sound->packedfile)
+ return OPERATOR_CANCELLED;
- if (G.fileflags & G_FILE_AUTOPACK)
- BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so image will be packed again on file save");
+ if (G.fileflags & G_FILE_AUTOPACK)
+ BKE_report(op->reports,
+ RPT_WARNING,
+ "AutoPack is enabled, so image will be packed again on file save");
- unpack_menu(C, "SOUND_OT_unpack", sound->id.name + 2, sound->name, "sounds", sound->packedfile);
+ unpack_menu(C, "SOUND_OT_unpack", sound->id.name + 2, sound->name, "sounds", sound->packedfile);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void SOUND_OT_unpack(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unpack Sound";
- ot->description = "Unpack the sound to the samples filename";
- ot->idname = "SOUND_OT_unpack";
-
- /* api callbacks */
- ot->exec = sound_unpack_exec;
- ot->invoke = sound_unpack_invoke;
- ot->poll = sound_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "method", rna_enum_unpack_method_items, PF_USE_LOCAL, "Method", "How to unpack");
- /* XXX, weark!, will fail with library, name collisions */
- RNA_def_string(ot->srna, "id", NULL, MAX_ID_NAME - 2, "Sound Name", "Sound data-block name to unpack");
+ /* identifiers */
+ ot->name = "Unpack Sound";
+ ot->description = "Unpack the sound to the samples filename";
+ ot->idname = "SOUND_OT_unpack";
+
+ /* api callbacks */
+ ot->exec = sound_unpack_exec;
+ ot->invoke = sound_unpack_invoke;
+ ot->poll = sound_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(
+ ot->srna, "method", rna_enum_unpack_method_items, PF_USE_LOCAL, "Method", "How to unpack");
+ /* XXX, weark!, will fail with library, name collisions */
+ RNA_def_string(
+ ot->srna, "id", NULL, MAX_ID_NAME - 2, "Sound Name", "Sound data-block name to unpack");
}
/* ******************************************************* */
void ED_operatortypes_sound(void)
{
- WM_operatortype_append(SOUND_OT_open);
- WM_operatortype_append(SOUND_OT_open_mono);
- WM_operatortype_append(SOUND_OT_mixdown);
- WM_operatortype_append(SOUND_OT_pack);
- WM_operatortype_append(SOUND_OT_unpack);
- WM_operatortype_append(SOUND_OT_update_animation_flags);
- WM_operatortype_append(SOUND_OT_bake_animation);
+ WM_operatortype_append(SOUND_OT_open);
+ WM_operatortype_append(SOUND_OT_open_mono);
+ WM_operatortype_append(SOUND_OT_mixdown);
+ WM_operatortype_append(SOUND_OT_pack);
+ WM_operatortype_append(SOUND_OT_unpack);
+ WM_operatortype_append(SOUND_OT_update_animation_flags);
+ WM_operatortype_append(SOUND_OT_bake_animation);
}
diff --git a/source/blender/editors/space_action/CMakeLists.txt b/source/blender/editors/space_action/CMakeLists.txt
index 853577180bb..5251ebb1267 100644
--- a/source/blender/editors/space_action/CMakeLists.txt
+++ b/source/blender/editors/space_action/CMakeLists.txt
@@ -16,37 +16,37 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- action_buttons.c
- action_data.c
- action_draw.c
- action_edit.c
- action_ops.c
- action_select.c
- space_action.c
+ action_buttons.c
+ action_data.c
+ action_draw.c
+ action_edit.c
+ action_ops.c
+ action_select.c
+ space_action.c
- action_intern.h
+ action_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
+ bf_blenkernel
+ bf_blenlib
)
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/space_action/action_buttons.c b/source/blender/editors/space_action/action_buttons.c
index eaeeca6dfd1..a30d5f34ed0 100644
--- a/source/blender/editors/space_action/action_buttons.c
+++ b/source/blender/editors/space_action/action_buttons.c
@@ -21,7 +21,6 @@
* \ingroup spaction
*/
-
#include <string.h>
#include <stdio.h>
#include <math.h>
@@ -43,7 +42,6 @@
#include "BKE_screen.h"
#include "BKE_unit.h"
-
#include "WM_api.h"
#include "WM_types.h"
@@ -56,7 +54,7 @@
#include "UI_interface.h"
#include "UI_resources.h"
-#include "action_intern.h" // own include
+#include "action_intern.h" // own include
/* ******************* action editor space & buttons ************** */
@@ -65,56 +63,56 @@
void action_buttons_register(ARegionType *UNUSED(art))
{
#if 0
- PanelType *pt;
-
- // TODO: AnimData / Actions List
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype action panel properties");
- strcpy(pt->idname, "ACTION_PT_properties");
- strcpy(pt->label, N_("Active F-Curve"));
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = action_anim_panel_properties;
- pt->poll = action_anim_panel_poll;
- BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype action panel properties");
- strcpy(pt->idname, "ACTION_PT_key_properties");
- strcpy(pt->label, N_("Active Keyframe"));
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = action_anim_panel_key_properties;
- pt->poll = action_anim_panel_poll;
- BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype action panel modifiers");
- strcpy(pt->idname, "ACTION_PT_modifiers");
- strcpy(pt->label, N_("Modifiers"));
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = action_anim_panel_modifiers;
- pt->poll = action_anim_panel_poll;
- BLI_addtail(&art->paneltypes, pt);
+ PanelType *pt;
+
+ // TODO: AnimData / Actions List
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype action panel properties");
+ strcpy(pt->idname, "ACTION_PT_properties");
+ strcpy(pt->label, N_("Active F-Curve"));
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = action_anim_panel_properties;
+ pt->poll = action_anim_panel_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype action panel properties");
+ strcpy(pt->idname, "ACTION_PT_key_properties");
+ strcpy(pt->label, N_("Active Keyframe"));
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = action_anim_panel_key_properties;
+ pt->poll = action_anim_panel_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype action panel modifiers");
+ strcpy(pt->idname, "ACTION_PT_modifiers");
+ strcpy(pt->label, N_("Modifiers"));
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = action_anim_panel_modifiers;
+ pt->poll = action_anim_panel_poll;
+ BLI_addtail(&art->paneltypes, pt);
#endif
}
static int action_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = action_has_buttons_region(sa);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = action_has_buttons_region(sa);
- if (ar)
- ED_region_toggle_hidden(C, ar);
+ if (ar)
+ ED_region_toggle_hidden(C, ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_properties(wmOperatorType *ot)
{
- ot->name = "Toggle Sidebar";
- ot->idname = "ACTION_OT_properties";
- ot->description = "Toggle the properties region visibility";
+ ot->name = "Toggle Sidebar";
+ ot->idname = "ACTION_OT_properties";
+ ot->description = "Toggle the properties region visibility";
- ot->exec = action_properties_toggle_exec;
- ot->poll = ED_operator_action_active;
+ ot->exec = action_properties_toggle_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c
index 8ecf32a2c6c..e9670a0048d 100644
--- a/source/blender/editors/space_action/action_data.c
+++ b/source/blender/editors/space_action/action_data.c
@@ -21,13 +21,11 @@
* \ingroup spaction
*/
-
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <float.h>
-
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -76,25 +74,25 @@
/* Helper function to find the active AnimData block from the Action Editor context */
AnimData *ED_actedit_animdata_from_context(bContext *C)
{
- SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
- Object *ob = CTX_data_active_object(C);
- AnimData *adt = NULL;
-
- /* Get AnimData block to use */
- if (saction->mode == SACTCONT_ACTION) {
- /* Currently, "Action Editor" means object-level only... */
- if (ob) {
- adt = ob->adt;
- }
- }
- else if (saction->mode == SACTCONT_SHAPEKEY) {
- Key *key = BKE_key_from_object(ob);
- if (key) {
- adt = key->adt;
- }
- }
-
- return adt;
+ SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
+ Object *ob = CTX_data_active_object(C);
+ AnimData *adt = NULL;
+
+ /* Get AnimData block to use */
+ if (saction->mode == SACTCONT_ACTION) {
+ /* Currently, "Action Editor" means object-level only... */
+ if (ob) {
+ adt = ob->adt;
+ }
+ }
+ else if (saction->mode == SACTCONT_SHAPEKEY) {
+ Key *key = BKE_key_from_object(ob);
+ if (key) {
+ adt = key->adt;
+ }
+ }
+
+ return adt;
}
/* -------------------------------------------------------------------- */
@@ -102,61 +100,61 @@ 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);
- bAction *action;
-
- /* create action - the way to do this depends on whether we've got an
- * existing one there already, in which case we make a copy of it
- * (which is useful for "versioning" actions within the same file)
- */
- if (oldact && GS(oldact->id.name) == ID_AC) {
- /* make a copy of the existing action */
- action = BKE_action_copy(CTX_data_main(C), oldact);
- }
- else {
- /* just make a new (empty) action */
- action = BKE_action_add(CTX_data_main(C), "Action");
- }
-
- /* when creating new ID blocks, there is already 1 user (as for all new datablocks),
- * but the RNA pointer code will assign all the proper users instead, so we compensate
- * for that here
- */
- BLI_assert(action->id.us == 1);
- id_us_min(&action->id);
-
- /* set ID-Root type */
- if (sa->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
-
- if (saction->mode == SACTCONT_SHAPEKEY)
- action->idroot = ID_KE;
- else
- action->idroot = ID_OB;
- }
-
- return action;
+ ScrArea *sa = CTX_wm_area(C);
+ bAction *action;
+
+ /* create action - the way to do this depends on whether we've got an
+ * existing one there already, in which case we make a copy of it
+ * (which is useful for "versioning" actions within the same file)
+ */
+ if (oldact && GS(oldact->id.name) == ID_AC) {
+ /* make a copy of the existing action */
+ action = BKE_action_copy(CTX_data_main(C), oldact);
+ }
+ else {
+ /* just make a new (empty) action */
+ action = BKE_action_add(CTX_data_main(C), "Action");
+ }
+
+ /* when creating new ID blocks, there is already 1 user (as for all new datablocks),
+ * but the RNA pointer code will assign all the proper users instead, so we compensate
+ * for that here
+ */
+ BLI_assert(action->id.us == 1);
+ id_us_min(&action->id);
+
+ /* set ID-Root type */
+ if (sa->spacetype == SPACE_ACTION) {
+ SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
+
+ if (saction->mode == SACTCONT_SHAPEKEY)
+ action->idroot = ID_KE;
+ else
+ action->idroot = ID_OB;
+ }
+
+ return action;
}
/* Change the active action used by the action editor */
static void actedit_change_action(bContext *C, bAction *act)
{
- bScreen *screen = CTX_wm_screen(C);
- SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
+ bScreen *screen = CTX_wm_screen(C);
+ SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
- PointerRNA ptr, idptr;
- PropertyRNA *prop;
+ PointerRNA ptr, idptr;
+ PropertyRNA *prop;
- /* create RNA pointers and get the property */
- RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, saction, &ptr);
- prop = RNA_struct_find_property(&ptr, "action");
+ /* create RNA pointers and get the property */
+ RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, saction, &ptr);
+ prop = RNA_struct_find_property(&ptr, "action");
- /* NOTE: act may be NULL here, so better to just use a cast here */
- RNA_id_pointer_create((ID *)act, &idptr);
+ /* NOTE: act may be NULL here, so better to just use a cast here */
+ RNA_id_pointer_create((ID *)act, &idptr);
- /* set the new pointer, and force a refresh */
- RNA_property_pointer_set(&ptr, prop, idptr);
- RNA_property_update(C, &ptr, prop);
+ /* set the new pointer, and force a refresh */
+ RNA_property_pointer_set(&ptr, prop, idptr);
+ RNA_property_update(C, &ptr, prop);
}
/* ******************** New Action Operator *********************** */
@@ -169,115 +167,115 @@ static void actedit_change_action(bContext *C, bAction *act)
*/
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) */
- /* NOTE: unlike for pushdown, this operator needs to be run when creating an action from nothing... */
- if (ED_operator_action_active(C)) {
- SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
- Object *ob = CTX_data_active_object(C);
-
- /* For now, actions are only for the active object, and on object and shapekey levels... */
- if (saction->mode == SACTCONT_ACTION) {
- /* XXX: This assumes that actions are assigned to the active object in this mode */
- if (ob) {
- if ((ob->adt == NULL) || (ob->adt->flag & ADT_NLA_EDIT_ON) == 0)
- return true;
- }
- }
- else if (saction->mode == SACTCONT_SHAPEKEY) {
- Key *key = BKE_key_from_object(ob);
- if (key) {
- if ((key->adt == NULL) || (key->adt->flag & ADT_NLA_EDIT_ON) == 0)
- return true;
- }
- }
- }
- else if (ED_operator_nla_active(C)) {
- if (!(scene->flag & SCE_NLA_EDIT_ON)) {
- return true;
- }
- }
-
- /* something failed... */
- return false;
+ Scene *scene = CTX_data_scene(C);
+
+ /* Check tweakmode 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)) {
+ SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
+ Object *ob = CTX_data_active_object(C);
+
+ /* For now, actions are only for the active object, and on object and shapekey levels... */
+ if (saction->mode == SACTCONT_ACTION) {
+ /* XXX: This assumes that actions are assigned to the active object in this mode */
+ if (ob) {
+ if ((ob->adt == NULL) || (ob->adt->flag & ADT_NLA_EDIT_ON) == 0)
+ return true;
+ }
+ }
+ else if (saction->mode == SACTCONT_SHAPEKEY) {
+ Key *key = BKE_key_from_object(ob);
+ if (key) {
+ if ((key->adt == NULL) || (key->adt->flag & ADT_NLA_EDIT_ON) == 0)
+ return true;
+ }
+ }
+ }
+ else if (ED_operator_nla_active(C)) {
+ if (!(scene->flag & SCE_NLA_EDIT_ON)) {
+ return true;
+ }
+ }
+
+ /* something failed... */
+ return false;
}
static int action_new_exec(bContext *C, wmOperator *UNUSED(op))
{
- PointerRNA ptr, idptr;
- PropertyRNA *prop;
-
- /* hook into UI */
- UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
-
- if (prop) {
- bAction *action = NULL, *oldact = NULL;
- AnimData *adt = NULL;
- PointerRNA oldptr;
-
- oldptr = RNA_property_pointer_get(&ptr, prop);
- oldact = (bAction *)oldptr.id.data;
-
- /* stash the old action to prevent it from being lost */
- if (ptr.type == &RNA_AnimData) {
- adt = ptr.data;
- }
- else if (ptr.type == &RNA_SpaceDopeSheetEditor) {
- adt = ED_actedit_animdata_from_context(C);
- }
-
- /* Perform stashing operation - But only if there is an action */
- if (adt && oldact) {
- /* stash the action */
- if (BKE_nla_action_stash(adt)) {
- /* The stash operation will remove the user already
- * (and unlink the action from the AnimData action slot).
- * Hence, we must unset the ref to the action in the
- * action editor too (if this is where we're being called from)
- * first before setting the new action once it is created,
- * or else the user gets decremented twice!
- */
- if (ptr.type == &RNA_SpaceDopeSheetEditor) {
- SpaceAction *saction = (SpaceAction *)ptr.data;
- saction->action = NULL;
- }
- }
- else {
- //printf("WARNING: Failed to stash %s. It may already exist in the NLA stack though\n", oldact->id.name);
- }
- }
-
- /* create action */
- action = action_create_new(C, oldact);
-
- /* set this new action
- * NOTE: we can't use actedit_change_action, as this function is also called from the NLA
- */
- RNA_id_pointer_create(&action->id, &idptr);
- RNA_property_pointer_set(&ptr, prop, idptr);
- RNA_property_update(C, &ptr, prop);
- }
-
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
-
- return OPERATOR_FINISHED;
+ PointerRNA ptr, idptr;
+ PropertyRNA *prop;
+
+ /* hook into UI */
+ UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
+
+ if (prop) {
+ bAction *action = NULL, *oldact = NULL;
+ AnimData *adt = NULL;
+ PointerRNA oldptr;
+
+ oldptr = RNA_property_pointer_get(&ptr, prop);
+ oldact = (bAction *)oldptr.id.data;
+
+ /* stash the old action to prevent it from being lost */
+ if (ptr.type == &RNA_AnimData) {
+ adt = ptr.data;
+ }
+ else if (ptr.type == &RNA_SpaceDopeSheetEditor) {
+ adt = ED_actedit_animdata_from_context(C);
+ }
+
+ /* Perform stashing operation - But only if there is an action */
+ if (adt && oldact) {
+ /* stash the action */
+ if (BKE_nla_action_stash(adt)) {
+ /* The stash operation will remove the user already
+ * (and unlink the action from the AnimData action slot).
+ * Hence, we must unset the ref to the action in the
+ * action editor too (if this is where we're being called from)
+ * first before setting the new action once it is created,
+ * or else the user gets decremented twice!
+ */
+ if (ptr.type == &RNA_SpaceDopeSheetEditor) {
+ SpaceAction *saction = (SpaceAction *)ptr.data;
+ saction->action = NULL;
+ }
+ }
+ else {
+ //printf("WARNING: Failed to stash %s. It may already exist in the NLA stack though\n", oldact->id.name);
+ }
+ }
+
+ /* create action */
+ action = action_create_new(C, oldact);
+
+ /* set this new action
+ * NOTE: we can't use actedit_change_action, as this function is also called from the NLA
+ */
+ RNA_id_pointer_create(&action->id, &idptr);
+ RNA_property_pointer_set(&ptr, prop, idptr);
+ RNA_property_update(C, &ptr, prop);
+ }
+
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
+
+ return OPERATOR_FINISHED;
}
void ACTION_OT_new(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "New Action";
- ot->idname = "ACTION_OT_new";
- ot->description = "Create new action";
+ /* identifiers */
+ ot->name = "New Action";
+ ot->idname = "ACTION_OT_new";
+ ot->description = "Create new action";
- /* api callbacks */
- ot->exec = action_new_exec;
- ot->poll = action_new_poll;
+ /* api callbacks */
+ ot->exec = action_new_exec;
+ ot->poll = action_new_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************* Action Push-Down Operator ******************** */
@@ -289,127 +287,130 @@ void ACTION_OT_new(wmOperatorType *ot)
*/
static bool action_pushdown_poll(bContext *C)
{
- if (ED_operator_action_active(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 */
- 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.
- */
- if (!(adt->flag & ADT_NLA_EDIT_ON))
- return true;
- }
- }
-
- /* something failed... */
- return false;
+ if (ED_operator_action_active(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 */
+ 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.
+ */
+ if (!(adt->flag & ADT_NLA_EDIT_ON))
+ return true;
+ }
+ }
+
+ /* something failed... */
+ return false;
}
static int action_pushdown_exec(bContext *C, wmOperator *op)
{
- SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
- AnimData *adt = ED_actedit_animdata_from_context(C);
-
- /* Do the deed... */
- if (adt) {
- /* Perform the pushdown operation
- * - This will deal with all the AnimData-side usercounts
- */
- 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");
- return OPERATOR_CANCELLED;
- }
- else {
- /* action can be safely added */
- BKE_nla_action_pushdown(adt);
- }
-
- /* Stop displaying this action in this editor
- * NOTE: The editor itself doesn't set a user...
- */
- saction->action = NULL;
- }
-
- /* Send notifiers that stuff has changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
- return OPERATOR_FINISHED;
+ SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
+ AnimData *adt = ED_actedit_animdata_from_context(C);
+
+ /* Do the deed... */
+ if (adt) {
+ /* Perform the pushdown operation
+ * - This will deal with all the AnimData-side usercounts
+ */
+ 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");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* action can be safely added */
+ BKE_nla_action_pushdown(adt);
+ }
+
+ /* Stop displaying this action in this editor
+ * NOTE: The editor itself doesn't set a user...
+ */
+ saction->action = NULL;
+ }
+
+ /* Send notifiers that stuff has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
+ return OPERATOR_FINISHED;
}
void ACTION_OT_push_down(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Push Down Action";
- ot->idname = "ACTION_OT_push_down";
- ot->description = "Push action down on to the NLA stack as a new strip";
+ /* identifiers */
+ ot->name = "Push Down Action";
+ ot->idname = "ACTION_OT_push_down";
+ ot->description = "Push action down on to the NLA stack as a new strip";
- /* callbacks */
- ot->exec = action_pushdown_exec;
- ot->poll = action_pushdown_poll;
+ /* callbacks */
+ ot->exec = action_pushdown_exec;
+ ot->poll = action_pushdown_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************* Action Stash Operator ******************** */
static int action_stash_exec(bContext *C, wmOperator *op)
{
- SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
- AnimData *adt = ED_actedit_animdata_from_context(C);
-
- /* Perform stashing operation */
- if (adt) {
- /* don't do anything if this action is empty... */
- 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");
- return OPERATOR_CANCELLED;
- }
- else {
- /* stash the action */
- 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
- * first before setting the new action.
- */
- saction->action = NULL;
- }
- else {
- /* action has already been added - simply warn about this, and clear */
- BKE_report(op->reports, RPT_ERROR, "Action has already been stashed");
- }
-
- /* clear action refs from editor, and then also the backing data (not necessary) */
- actedit_change_action(C, NULL);
- }
- }
-
- /* Send notifiers that stuff has changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
- return OPERATOR_FINISHED;
+ SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
+ AnimData *adt = ED_actedit_animdata_from_context(C);
+
+ /* Perform stashing operation */
+ if (adt) {
+ /* don't do anything if this action is empty... */
+ 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");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* stash the action */
+ 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
+ * first before setting the new action.
+ */
+ saction->action = NULL;
+ }
+ else {
+ /* action has already been added - simply warn about this, and clear */
+ BKE_report(op->reports, RPT_ERROR, "Action has already been stashed");
+ }
+
+ /* clear action refs from editor, and then also the backing data (not necessary) */
+ actedit_change_action(C, NULL);
+ }
+ }
+
+ /* Send notifiers that stuff has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
+ return OPERATOR_FINISHED;
}
void ACTION_OT_stash(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Stash Action";
- ot->idname = "ACTION_OT_stash";
- ot->description = "Store this action in the NLA stack as a non-contributing strip for later use";
-
- /* callbacks */
- ot->exec = action_stash_exec;
- ot->poll = action_pushdown_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_boolean(ot->srna, "create_new", true, "Create New Action",
- "Create a new action once the existing one has been safely stored");
+ /* identifiers */
+ ot->name = "Stash Action";
+ ot->idname = "ACTION_OT_stash";
+ ot->description = "Store this action in the NLA stack as a non-contributing strip for later use";
+
+ /* callbacks */
+ ot->exec = action_stash_exec;
+ ot->poll = action_pushdown_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_boolean(ot->srna,
+ "create_new",
+ true,
+ "Create New Action",
+ "Create a new action once the existing one has been safely stored");
}
/* ----------------- */
@@ -420,94 +421,96 @@ void ACTION_OT_stash(wmOperatorType *ot)
*/
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) */
- /* NOTE: unlike for pushdown, this operator needs to be run when creating an action from nothing... */
- if (adt) {
- if (!(adt->flag & ADT_NLA_EDIT_ON))
- return true;
- }
- else {
- /* There may not be any action/animdata yet, so, just fallback to the global setting
- * (which may not be totally valid yet if the action editor was used and things are
- * now in an inconsistent state)
- */
- SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
- Scene *scene = CTX_data_scene(C);
-
- if (!(scene->flag & SCE_NLA_EDIT_ON)) {
- /* For now, actions are only for the active object, and on object and shapekey levels... */
- return ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY);
- }
- }
- }
-
- /* something failed... */
- return false;
+ 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) */
+ /* NOTE: unlike for pushdown, this operator needs to be run when creating an action from nothing... */
+ if (adt) {
+ if (!(adt->flag & ADT_NLA_EDIT_ON))
+ return true;
+ }
+ else {
+ /* There may not be any action/animdata yet, so, just fallback to the global setting
+ * (which may not be totally valid yet if the action editor was used and things are
+ * now in an inconsistent state)
+ */
+ SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
+ Scene *scene = CTX_data_scene(C);
+
+ if (!(scene->flag & SCE_NLA_EDIT_ON)) {
+ /* For now, actions are only for the active object, and on object and shapekey levels... */
+ return ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY);
+ }
+ }
+ }
+
+ /* something failed... */
+ return false;
}
static int action_stash_create_exec(bContext *C, wmOperator *op)
{
- SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
- AnimData *adt = ED_actedit_animdata_from_context(C);
-
- /* Check for no action... */
- if (saction->action == NULL) {
- /* just create a new action */
- bAction *action = action_create_new(C, NULL);
- actedit_change_action(C, action);
- }
- else if (adt) {
- /* Perform stashing operation */
- if (action_has_motion(adt->action) == 0) {
- /* don't do anything if this action is empty... */
- BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
- return OPERATOR_CANCELLED;
- }
- else {
- /* stash the action */
- if (BKE_nla_action_stash(adt)) {
- bAction *new_action = NULL;
-
- /* create new action not based on the old one (since the "new" operator already does that) */
- new_action = action_create_new(C, NULL);
-
- /* 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
- * first before setting the new action.
- */
- saction->action = NULL;
- actedit_change_action(C, new_action);
- }
- else {
- /* action has already been added - simply warn about this, and clear */
- BKE_report(op->reports, RPT_ERROR, "Action has already been stashed");
- actedit_change_action(C, NULL);
- }
- }
- }
-
- /* Send notifiers that stuff has changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
- return OPERATOR_FINISHED;
+ SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
+ AnimData *adt = ED_actedit_animdata_from_context(C);
+
+ /* Check for no action... */
+ if (saction->action == NULL) {
+ /* just create a new action */
+ bAction *action = action_create_new(C, NULL);
+ actedit_change_action(C, action);
+ }
+ else if (adt) {
+ /* Perform stashing operation */
+ if (action_has_motion(adt->action) == 0) {
+ /* don't do anything if this action is empty... */
+ BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* stash the action */
+ if (BKE_nla_action_stash(adt)) {
+ bAction *new_action = NULL;
+
+ /* create new action not based on the old one (since the "new" operator already does that) */
+ new_action = action_create_new(C, NULL);
+
+ /* 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
+ * first before setting the new action.
+ */
+ saction->action = NULL;
+ actedit_change_action(C, new_action);
+ }
+ else {
+ /* action has already been added - simply warn about this, and clear */
+ BKE_report(op->reports, RPT_ERROR, "Action has already been stashed");
+ actedit_change_action(C, NULL);
+ }
+ }
+ }
+
+ /* Send notifiers that stuff has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
+ return OPERATOR_FINISHED;
}
void ACTION_OT_stash_and_create(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Stash Action";
- ot->idname = "ACTION_OT_stash_and_create";
- ot->description = "Store this action in the NLA stack as a non-contributing strip for later use, and create a new action";
-
- /* callbacks */
- ot->exec = action_stash_create_exec;
- ot->poll = action_stash_create_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Stash Action";
+ ot->idname = "ACTION_OT_stash_and_create";
+ ot->description =
+ "Store this action in the NLA stack as a non-contributing strip for later use, and create a "
+ "new action";
+
+ /* callbacks */
+ ot->exec = action_stash_create_exec;
+ ot->poll = action_stash_create_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ************************************************************************** */
@@ -522,146 +525,152 @@ void ACTION_OT_stash_and_create(wmOperatorType *ot)
* 3) We need a convenient way to exit Tweak Mode from the Action Editor
*/
-void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act, ReportList *reports, bool force_delete)
+void ED_animedit_unlink_action(
+ bContext *C, ID *id, AnimData *adt, bAction *act, ReportList *reports, bool force_delete)
{
- ScrArea *sa = CTX_wm_area(C);
-
- /* If the old action only has a single user (that it's about to lose),
- * warn user about it
- *
- * TODO: Maybe we should just save it for them? But then, there's the problem of
- * trying to get rid of stuff that's actually unwanted!
- */
- if (act->id.us == 1) {
- BKE_reportf(reports, RPT_WARNING,
- "Action '%s' will not be saved, create Fake User or Stash in NLA Stack to retain",
- act->id.name + 2);
- }
-
- /* Clear Fake User and remove action stashing strip (if present) */
- if (force_delete) {
- /* Remove stashed strip binding this action to this datablock */
- /* XXX: we cannot unlink it from *OTHER* datablocks that may also be stashing it,
- * but GE users only seem to use/care about single-object binding for now so this
- * should be fine
- */
- if (adt) {
- NlaTrack *nlt, *nlt_next;
- NlaStrip *strip, *nstrip;
-
- for (nlt = adt->nla_tracks.first; nlt; nlt = nlt_next) {
- nlt_next = nlt->next;
-
- if (strstr(nlt->name, DATA_("[Action Stash]"))) {
- for (strip = nlt->strips.first; strip; strip = nstrip) {
- nstrip = strip->next;
-
- if (strip->act == act) {
- /* Remove this strip, and the track too if it doesn't have anything else */
- BKE_nlastrip_free(&nlt->strips, strip, true);
-
- if (nlt->strips.first == NULL) {
- BLI_assert(nstrip == NULL);
- BKE_nlatrack_free(&adt->nla_tracks, nlt, true);
- }
- }
- }
- }
- }
- }
-
- /* Clear Fake User */
- id_fake_user_clear(&act->id);
- }
-
- /* If in Tweak Mode, don't unlink. Instead, this
- * becomes a shortcut to exit Tweak Mode instead
- */
- if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
- /* Exit Tweak Mode */
- BKE_nla_tweakmode_exit(adt);
-
- /* Flush this to the Action Editor (if that's where this change was initiated) */
- if (sa->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) {
- /* clear action editor -> action */
- actedit_change_action(C, NULL);
- }
- else {
- /* clear AnimData -> action */
- PointerRNA ptr;
- PropertyRNA *prop;
-
- /* create AnimData RNA pointers */
- RNA_pointer_create(id, &RNA_AnimData, adt, &ptr);
- prop = RNA_struct_find_property(&ptr, "action");
-
- /* clear... */
- RNA_property_pointer_set(&ptr, prop, PointerRNA_NULL);
- RNA_property_update(C, &ptr, prop);
- }
- }
+ ScrArea *sa = CTX_wm_area(C);
+
+ /* If the old action only has a single user (that it's about to lose),
+ * warn user about it
+ *
+ * TODO: Maybe we should just save it for them? But then, there's the problem of
+ * trying to get rid of stuff that's actually unwanted!
+ */
+ if (act->id.us == 1) {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Action '%s' will not be saved, create Fake User or Stash in NLA Stack to retain",
+ act->id.name + 2);
+ }
+
+ /* Clear Fake User and remove action stashing strip (if present) */
+ if (force_delete) {
+ /* Remove stashed strip binding this action to this datablock */
+ /* XXX: we cannot unlink it from *OTHER* datablocks that may also be stashing it,
+ * but GE users only seem to use/care about single-object binding for now so this
+ * should be fine
+ */
+ if (adt) {
+ NlaTrack *nlt, *nlt_next;
+ NlaStrip *strip, *nstrip;
+
+ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt_next) {
+ nlt_next = nlt->next;
+
+ if (strstr(nlt->name, DATA_("[Action Stash]"))) {
+ for (strip = nlt->strips.first; strip; strip = nstrip) {
+ nstrip = strip->next;
+
+ if (strip->act == act) {
+ /* Remove this strip, and the track too if it doesn't have anything else */
+ BKE_nlastrip_free(&nlt->strips, strip, true);
+
+ if (nlt->strips.first == NULL) {
+ BLI_assert(nstrip == NULL);
+ BKE_nlatrack_free(&adt->nla_tracks, nlt, true);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Clear Fake User */
+ id_fake_user_clear(&act->id);
+ }
+
+ /* If in Tweak Mode, don't unlink. Instead, this
+ * becomes a shortcut to exit Tweak Mode instead
+ */
+ if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
+ /* Exit Tweak Mode */
+ BKE_nla_tweakmode_exit(adt);
+
+ /* Flush this to the Action Editor (if that's where this change was initiated) */
+ if (sa->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) {
+ /* clear action editor -> action */
+ actedit_change_action(C, NULL);
+ }
+ else {
+ /* clear AnimData -> action */
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ /* create AnimData RNA pointers */
+ RNA_pointer_create(id, &RNA_AnimData, adt, &ptr);
+ prop = RNA_struct_find_property(&ptr, "action");
+
+ /* clear... */
+ RNA_property_pointer_set(&ptr, prop, PointerRNA_NULL);
+ RNA_property_update(C, &ptr, prop);
+ }
+ }
}
/* -------------------------- */
static bool action_unlink_poll(bContext *C)
{
- if (ED_operator_action_active(C)) {
- SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
- AnimData *adt = ED_actedit_animdata_from_context(C);
+ if (ED_operator_action_active(C)) {
+ SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
+ AnimData *adt = ED_actedit_animdata_from_context(C);
- /* Only when there's an active action, in the right modes... */
- if (saction->action && adt)
- return true;
- }
+ /* Only when there's an active action, in the right modes... */
+ if (saction->action && adt)
+ return true;
+ }
- /* something failed... */
- return false;
+ /* something failed... */
+ return false;
}
static int action_unlink_exec(bContext *C, wmOperator *op)
{
- AnimData *adt = ED_actedit_animdata_from_context(C);
- bool force_delete = RNA_boolean_get(op->ptr, "force_delete");
+ AnimData *adt = ED_actedit_animdata_from_context(C);
+ bool force_delete = RNA_boolean_get(op->ptr, "force_delete");
- if (adt && adt->action) {
- ED_animedit_unlink_action(C, NULL, adt, adt->action, op->reports, force_delete);
- }
+ if (adt && adt->action) {
+ ED_animedit_unlink_action(C, NULL, adt, adt->action, op->reports, force_delete);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
{
- /* NOTE: this is hardcoded to match the behavior for the unlink button (in interface_templates.c) */
- RNA_boolean_set(op->ptr, "force_delete", evt->shift != 0);
- return action_unlink_exec(C, op);
+ /* NOTE: this is hardcoded to match the behavior for the unlink button (in interface_templates.c) */
+ RNA_boolean_set(op->ptr, "force_delete", evt->shift != 0);
+ return action_unlink_exec(C, op);
}
void ACTION_OT_unlink(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Unlink Action";
- ot->idname = "ACTION_OT_unlink";
- ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)";
-
- /* callbacks */
- ot->invoke = action_unlink_invoke;
- ot->exec = action_unlink_exec;
- ot->poll = action_unlink_poll;
-
- /* properties */
- prop = RNA_def_boolean(ot->srna, "force_delete", false, "Force Delete", "Clear Fake User and remove "
- "copy stashed in this data-block's NLA stack");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Unlink Action";
+ ot->idname = "ACTION_OT_unlink";
+ ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)";
+
+ /* callbacks */
+ ot->invoke = action_unlink_invoke;
+ ot->exec = action_unlink_exec;
+ ot->poll = action_unlink_poll;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna,
+ "force_delete",
+ false,
+ "Force Delete",
+ "Clear Fake User and remove "
+ "copy stashed in this data-block's NLA stack");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ************************************************************************** */
@@ -670,282 +679,284 @@ void ACTION_OT_unlink(wmOperatorType *ot)
/* Try to find NLA Strip to use for action layer up/down tool */
static NlaStrip *action_layer_get_nlastrip(ListBase *strips, float ctime)
{
- NlaStrip *strip;
-
- for (strip = strips->first; strip; strip = strip->next) {
- /* Can we use this? */
- if (IN_RANGE_INCL(ctime, strip->start, strip->end)) {
- /* in range - use this one */
- return strip;
- }
- else if ((ctime < strip->start) && (strip->prev == NULL)) {
- /* before first - use this one */
- return strip;
- }
- else if ((ctime > strip->end) && (strip->next == NULL)) {
- /* after last - use this one */
- return strip;
- }
- }
-
- /* nothing suitable found... */
- return NULL;
+ NlaStrip *strip;
+
+ for (strip = strips->first; strip; strip = strip->next) {
+ /* Can we use this? */
+ if (IN_RANGE_INCL(ctime, strip->start, strip->end)) {
+ /* in range - use this one */
+ return strip;
+ }
+ else if ((ctime < strip->start) && (strip->prev == NULL)) {
+ /* before first - use this one */
+ return strip;
+ }
+ else if ((ctime > strip->end) && (strip->next == NULL)) {
+ /* after last - use this one */
+ return strip;
+ }
+ }
+
+ /* nothing suitable found... */
+ return NULL;
}
/* Switch NLA Strips/Actions */
-static void action_layer_switch_strip(AnimData *adt,
- NlaTrack *old_track, NlaStrip *old_strip,
- NlaTrack *nlt, NlaStrip *strip)
+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
- */
- BKE_nla_tweakmode_exit(adt);
-
- if (old_strip) {
- old_strip->flag &= ~(NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT);
- }
- if (old_track) {
- old_track->flag &= ~(NLATRACK_ACTIVE | NLATRACK_SELECTED);
- }
-
- /* Make this one the active one instead */
- strip->flag |= (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT);
- nlt->flag |= NLATRACK_ACTIVE;
-
- /* Copy over "solo" flag - This is useful for stashed actions... */
- if (old_track) {
- if (old_track->flag & NLATRACK_SOLO) {
- old_track->flag &= ~NLATRACK_SOLO;
- nlt->flag |= NLATRACK_SOLO;
- }
- }
- else {
- /* NLA muting <==> Solo Tracks */
- if (adt->flag & ADT_NLA_EVAL_OFF) {
- /* disable NLA muting */
- adt->flag &= ~ADT_NLA_EVAL_OFF;
-
- /* mark this track as being solo */
- adt->flag |= ADT_NLA_SOLO_TRACK;
- nlt->flag |= NLATRACK_SOLO;
-
- // TODO: Needs restpose flushing (when we get reference track)
- }
- }
-
- /* Enter tweakmode again - hopefully we're now "it" */
- BKE_nla_tweakmode_enter(adt);
- BLI_assert(adt->actstrip == strip);
+ /* Exit tweakmode on old strip
+ * NOTE: We need to manually clear this stuff ourselves, as tweakmode exit doesn't do it
+ */
+ BKE_nla_tweakmode_exit(adt);
+
+ if (old_strip) {
+ old_strip->flag &= ~(NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT);
+ }
+ if (old_track) {
+ old_track->flag &= ~(NLATRACK_ACTIVE | NLATRACK_SELECTED);
+ }
+
+ /* Make this one the active one instead */
+ strip->flag |= (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT);
+ nlt->flag |= NLATRACK_ACTIVE;
+
+ /* Copy over "solo" flag - This is useful for stashed actions... */
+ if (old_track) {
+ if (old_track->flag & NLATRACK_SOLO) {
+ old_track->flag &= ~NLATRACK_SOLO;
+ nlt->flag |= NLATRACK_SOLO;
+ }
+ }
+ else {
+ /* NLA muting <==> Solo Tracks */
+ if (adt->flag & ADT_NLA_EVAL_OFF) {
+ /* disable NLA muting */
+ adt->flag &= ~ADT_NLA_EVAL_OFF;
+
+ /* mark this track as being solo */
+ adt->flag |= ADT_NLA_SOLO_TRACK;
+ nlt->flag |= NLATRACK_SOLO;
+
+ // TODO: Needs restpose flushing (when we get reference track)
+ }
+ }
+
+ /* Enter tweakmode again - hopefully we're now "it" */
+ BKE_nla_tweakmode_enter(adt);
+ BLI_assert(adt->actstrip == strip);
}
/* ********************** One Layer Up Operator ************************** */
static bool action_layer_next_poll(bContext *C)
{
- /* Action Editor's action editing modes only */
- 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... */
- 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
- */
- if (adt->nla_tracks.last) {
- NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.last;
-
- if (nlt->flag & NLATRACK_DISABLED) {
- /* A disabled track will either be the track itself,
- * or one of the ones above it.
- *
- * If this is the top-most one, there is the possibility
- * that there is no active action. For now, we let this
- * case return true too, so that there is a natural way
- * to "move to an empty layer", even though this means
- * that we won't actually have an action.
- */
- // return (adt->tmpact != NULL);
- return true;
- }
- }
- }
- }
- }
-
- /* something failed... */
- return false;
+ /* Action Editor's action editing modes only */
+ 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... */
+ 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
+ */
+ if (adt->nla_tracks.last) {
+ NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.last;
+
+ if (nlt->flag & NLATRACK_DISABLED) {
+ /* A disabled track will either be the track itself,
+ * or one of the ones above it.
+ *
+ * If this is the top-most one, there is the possibility
+ * that there is no active action. For now, we let this
+ * case return true too, so that there is a natural way
+ * to "move to an empty layer", even though this means
+ * that we won't actually have an action.
+ */
+ // return (adt->tmpact != NULL);
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ /* something failed... */
+ return false;
}
static int action_layer_next_exec(bContext *C, wmOperator *op)
{
- AnimData *adt = ED_actedit_animdata_from_context(C);
- NlaTrack *act_track;
-
- Scene *scene = CTX_data_scene(C);
- float ctime = BKE_scene_frame_get(scene);
-
- /* Get active track */
- act_track = BKE_nlatrack_find_tweaked(adt);
-
- if (act_track == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Could not find current NLA Track");
- return OPERATOR_CANCELLED;
- }
-
- /* Find next action, and hook it up */
- if (act_track->next) {
- NlaTrack *nlt;
-
- /* Find next action to use */
- for (nlt = act_track->next; nlt; nlt = nlt->next) {
- NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime);
-
- if (strip) {
- action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip);
- break;
- }
- }
- }
- else {
- /* No more actions (strips) - Go back to editing the original active action
- * NOTE: This will mean exiting tweakmode...
- */
- BKE_nla_tweakmode_exit(adt);
-
- /* Deal with solo flags...
- * Assume: Solo Track == NLA Muting
- */
- if (adt->flag & ADT_NLA_SOLO_TRACK) {
- /* turn off solo flags on tracks */
- act_track->flag &= ~NLATRACK_SOLO;
- adt->flag &= ~ADT_NLA_SOLO_TRACK;
-
- /* turn on NLA muting (to keep same effect) */
- adt->flag |= ADT_NLA_EVAL_OFF;
-
- // TODO: Needs restpose 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
- */
- actedit_change_action(C, adt->action);
- return OPERATOR_FINISHED;
+ AnimData *adt = ED_actedit_animdata_from_context(C);
+ NlaTrack *act_track;
+
+ Scene *scene = CTX_data_scene(C);
+ float ctime = BKE_scene_frame_get(scene);
+
+ /* Get active track */
+ act_track = BKE_nlatrack_find_tweaked(adt);
+
+ if (act_track == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Could not find current NLA Track");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Find next action, and hook it up */
+ if (act_track->next) {
+ NlaTrack *nlt;
+
+ /* Find next action to use */
+ for (nlt = act_track->next; nlt; nlt = nlt->next) {
+ NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime);
+
+ if (strip) {
+ action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip);
+ break;
+ }
+ }
+ }
+ else {
+ /* No more actions (strips) - Go back to editing the original active action
+ * NOTE: This will mean exiting tweakmode...
+ */
+ BKE_nla_tweakmode_exit(adt);
+
+ /* Deal with solo flags...
+ * Assume: Solo Track == NLA Muting
+ */
+ if (adt->flag & ADT_NLA_SOLO_TRACK) {
+ /* turn off solo flags on tracks */
+ act_track->flag &= ~NLATRACK_SOLO;
+ adt->flag &= ~ADT_NLA_SOLO_TRACK;
+
+ /* turn on NLA muting (to keep same effect) */
+ adt->flag |= ADT_NLA_EVAL_OFF;
+
+ // TODO: Needs restpose 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
+ */
+ actedit_change_action(C, adt->action);
+ return OPERATOR_FINISHED;
}
void ACTION_OT_layer_next(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Next Layer";
- ot->idname = "ACTION_OT_layer_next";
- ot->description = "Switch to editing action in animation layer above the current action in the NLA Stack";
-
- /* callbacks */
- ot->exec = action_layer_next_exec;
- ot->poll = action_layer_next_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Next Layer";
+ ot->idname = "ACTION_OT_layer_next";
+ ot->description =
+ "Switch to editing action in animation layer above the current action in the NLA Stack";
+
+ /* callbacks */
+ ot->exec = action_layer_next_exec;
+ ot->poll = action_layer_next_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************* One Layer Down Operator ************************* */
static bool action_layer_prev_poll(bContext *C)
{
- /* Action Editor's action editing modes only */
- if (ED_operator_action_active(C)) {
- AnimData *adt = ED_actedit_animdata_from_context(C);
- if (adt) {
- if (adt->flag & ADT_NLA_EDIT_ON) {
- /* Tweak Mode: We need to check if there are any tracks below the active one
- * that we can move to */
- if (adt->nla_tracks.first) {
- NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.first;
-
- /* Since the first disabled track is the track being tweaked/edited,
- * we can simplify things by only checking the first track:
- * - If it is disabled, this is the track being tweaked,
- * so there can't be anything below it
- * - Otherwise, there is at least 1 track below the tweaking
- * track that we can descend to
- */
- if ((nlt->flag & NLATRACK_DISABLED) == 0) {
- /* not disabled = there are actions below the one being tweaked */
- return true;
- }
- }
- }
- else {
- /* Normal Mode: If there are any tracks, we can try moving to those */
- return (adt->nla_tracks.first != NULL);
- }
- }
- }
-
- /* something failed... */
- return false;
+ /* Action Editor's action editing modes only */
+ if (ED_operator_action_active(C)) {
+ AnimData *adt = ED_actedit_animdata_from_context(C);
+ if (adt) {
+ if (adt->flag & ADT_NLA_EDIT_ON) {
+ /* Tweak Mode: We need to check if there are any tracks below the active one
+ * that we can move to */
+ if (adt->nla_tracks.first) {
+ NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.first;
+
+ /* Since the first disabled track is the track being tweaked/edited,
+ * we can simplify things by only checking the first track:
+ * - If it is disabled, this is the track being tweaked,
+ * so there can't be anything below it
+ * - Otherwise, there is at least 1 track below the tweaking
+ * track that we can descend to
+ */
+ if ((nlt->flag & NLATRACK_DISABLED) == 0) {
+ /* not disabled = there are actions below the one being tweaked */
+ return true;
+ }
+ }
+ }
+ else {
+ /* Normal Mode: If there are any tracks, we can try moving to those */
+ return (adt->nla_tracks.first != NULL);
+ }
+ }
+ }
+
+ /* something failed... */
+ return false;
}
static int action_layer_prev_exec(bContext *C, wmOperator *op)
{
- AnimData *adt = ED_actedit_animdata_from_context(C);
- NlaTrack *act_track;
- NlaTrack *nlt;
-
- Scene *scene = CTX_data_scene(C);
- float ctime = BKE_scene_frame_get(scene);
-
- /* Sanity Check */
- if (adt == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Internal Error: Could not find Animation Data/NLA Stack to use");
- return OPERATOR_CANCELLED;
- }
-
- /* Get active track */
- act_track = BKE_nlatrack_find_tweaked(adt);
-
- /* If there is no active track, that means we are using the active action... */
- if (act_track) {
- /* Active Track - Start from the one below it */
- nlt = act_track->prev;
- }
- else {
- /* Active Action - Use the top-most track */
- nlt = adt->nla_tracks.last;
- }
-
- /* Find previous action and hook it up */
- for (; nlt; nlt = nlt->prev) {
- NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime);
-
- if (strip) {
- action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip);
- break;
- }
- }
-
- /* Update the action that this editor now uses
- * NOTE: The calls above have already handled the usercount/animdata side of things
- */
- actedit_change_action(C, adt->action);
- return OPERATOR_FINISHED;
+ AnimData *adt = ED_actedit_animdata_from_context(C);
+ NlaTrack *act_track;
+ NlaTrack *nlt;
+
+ Scene *scene = CTX_data_scene(C);
+ float ctime = BKE_scene_frame_get(scene);
+
+ /* Sanity Check */
+ if (adt == NULL) {
+ BKE_report(
+ op->reports, RPT_ERROR, "Internal Error: Could not find Animation Data/NLA Stack to use");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Get active track */
+ act_track = BKE_nlatrack_find_tweaked(adt);
+
+ /* If there is no active track, that means we are using the active action... */
+ if (act_track) {
+ /* Active Track - Start from the one below it */
+ nlt = act_track->prev;
+ }
+ else {
+ /* Active Action - Use the top-most track */
+ nlt = adt->nla_tracks.last;
+ }
+
+ /* Find previous action and hook it up */
+ for (; nlt; nlt = nlt->prev) {
+ NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime);
+
+ if (strip) {
+ action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip);
+ break;
+ }
+ }
+
+ /* Update the action that this editor now uses
+ * NOTE: The calls above have already handled the usercount/animdata side of things
+ */
+ actedit_change_action(C, adt->action);
+ return OPERATOR_FINISHED;
}
void ACTION_OT_layer_prev(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Previous Layer";
- ot->idname = "ACTION_OT_layer_prev";
- ot->description = "Switch to editing action in animation layer below the current action in the NLA Stack";
-
- /* callbacks */
- ot->exec = action_layer_prev_exec;
- ot->poll = action_layer_prev_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Previous Layer";
+ ot->idname = "ACTION_OT_layer_prev";
+ ot->description =
+ "Switch to editing action in animation layer below the current action in the NLA Stack";
+
+ /* callbacks */
+ ot->exec = action_layer_prev_exec;
+ ot->poll = action_layer_prev_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ************************************************************************** */
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 0db1fd6eec3..b2baace1592 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -21,7 +21,6 @@
* \ingroup spaction
*/
-
/* System includes ----------------------------------------------------- */
#include <math.h>
@@ -46,10 +45,8 @@
#include "BKE_context.h"
#include "BKE_pointcache.h"
-
/* Everything from source (BIF, BDR, BSE) ------------------------------ */
-
#include "GPU_immediate.h"
#include "GPU_matrix.h"
#include "GPU_state.h"
@@ -69,325 +66,335 @@
/* left hand part */
void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- View2D *v2d = &ar->v2d;
- float y = 0.0f;
- size_t items;
- int height;
-
- /* build list of channels to draw */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac)));
- if (height > BLI_rcti_size_y(&v2d->mask)) {
- /* don't use totrect set, as the width stays the same
- * (NOTE: this is ok here, the configuration is pretty straightforward)
- */
- v2d->tot.ymin = (float)(-height);
- }
- /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */
- UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY);
-
- /* loop through channels, and set up drawing depending on their type */
- { /* first pass: just the standard GL-drawing for backdrop + text */
- size_t channel_index = 0;
-
- y = (float)ACHANNEL_FIRST(ac);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
- float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
-
- /* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
- {
- /* draw all channels using standard channel-drawing API */
- ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index);
- }
-
- /* adjust y-position for next one */
- y -= ACHANNEL_STEP(ac);
- channel_index++;
- }
- }
- { /* second pass: widgets */
- uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
- size_t channel_index = 0;
-
- y = (float)ACHANNEL_FIRST(ac);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
- float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
-
- /* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
- {
- /* draw all channels using standard channel-drawing API */
- rctf channel_rect;
- BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax, yminc, ymaxc);
- ANIM_channel_draw_widgets(C, ac, ale, block, &channel_rect, channel_index);
- }
-
- /* adjust y-position for next one */
- y -= ACHANNEL_STEP(ac);
- channel_index++;
- }
-
- UI_block_end(C, block);
- UI_block_draw(C, block);
- }
-
- /* free tempolary channels */
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ View2D *v2d = &ar->v2d;
+ float y = 0.0f;
+ size_t items;
+ int height;
+
+ /* build list of channels to draw */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac)));
+ if (height > BLI_rcti_size_y(&v2d->mask)) {
+ /* don't use totrect set, as the width stays the same
+ * (NOTE: this is ok here, the configuration is pretty straightforward)
+ */
+ v2d->tot.ymin = (float)(-height);
+ }
+ /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */
+ UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY);
+
+ /* loop through channels, and set up drawing depending on their type */
+ { /* first pass: just the standard GL-drawing for backdrop + text */
+ size_t channel_index = 0;
+
+ y = (float)ACHANNEL_FIRST(ac);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
+ float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
+
+ /* check if visible */
+ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ /* draw all channels using standard channel-drawing API */
+ ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index);
+ }
+
+ /* adjust y-position for next one */
+ y -= ACHANNEL_STEP(ac);
+ channel_index++;
+ }
+ }
+ { /* second pass: widgets */
+ uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ size_t channel_index = 0;
+
+ y = (float)ACHANNEL_FIRST(ac);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
+ float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
+
+ /* check if visible */
+ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ /* draw all channels using standard channel-drawing API */
+ rctf channel_rect;
+ BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax, yminc, ymaxc);
+ ANIM_channel_draw_widgets(C, ac, ale, block, &channel_rect, channel_index);
+ }
+
+ /* adjust y-position for next one */
+ y -= ACHANNEL_STEP(ac);
+ channel_index++;
+ }
+
+ UI_block_end(C, block);
+ UI_block_draw(C, block);
+ }
+
+ /* free tempolary channels */
+ ANIM_animdata_freelist(&anim_data);
}
/* ************************************************************************* */
/* Keyframes */
/* extra padding for lengths (to go under scrollers) */
-#define EXTRA_SCROLL_PAD 100.0f
+#define EXTRA_SCROLL_PAD 100.0f
/* draw keyframes in each channel */
void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
-
- View2D *v2d = &ar->v2d;
- bDopeSheet *ads = &saction->ads;
- AnimData *adt = NULL;
-
- float y;
-
- unsigned char col1[4], col2[4];
- unsigned char col1a[4], col2a[4];
- unsigned char col1b[4], col2b[4];
-
- const bool show_group_colors = !(saction->flag & SACTION_NODRAWGCOLORS);
-
-
- /* get theme colors */
- UI_GetThemeColor4ubv(TH_SHADE2, col2);
- UI_GetThemeColor4ubv(TH_HILITE, col1);
-
- UI_GetThemeColor4ubv(TH_GROUP, col2a);
- UI_GetThemeColor4ubv(TH_GROUP_ACTIVE, col1a);
-
- UI_GetThemeColor4ubv(TH_DOPESHEET_CHANNELOB, col1b);
- UI_GetThemeColor4ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
-
- /* build list of channels to draw */
- int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- int height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac)));
- /* don't use totrect set, as the width stays the same
- * (NOTE: this is ok here, the configuration is pretty straightforward)
- */
- v2d->tot.ymin = (float)(-height);
-
- /* first backdrop strips */
- y = (float)(-ACHANNEL_HEIGHT(ac));
-
- 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_blend(true);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
- const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
-
- /* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
- {
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- int sel = 0;
-
- /* determine if any need to draw channel */
- if (ale->datatype != ALE_NONE) {
- /* determine if channel is selected */
- if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT))
- sel = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
-
- if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY)) {
- switch (ale->type) {
- case ANIMTYPE_SUMMARY:
- {
- /* reddish color from NLA */
- immUniformThemeColor(TH_ANIM_ACTIVE);
- break;
- }
- case ANIMTYPE_SCENE:
- case ANIMTYPE_OBJECT:
- {
- immUniformColor3ubvAlpha(col1b, sel ? col1[3] : col1b[3]);
- break;
- }
- case ANIMTYPE_FILLACTD:
- case ANIMTYPE_DSSKEY:
- case ANIMTYPE_DSWOR:
- {
- immUniformColor3ubvAlpha(col2b, sel ? col1[3] : col2b[3]);
- break;
- }
- case ANIMTYPE_GROUP:
- {
- bActionGroup *agrp = ale->data;
- if (show_group_colors && agrp->customCol) {
- if (sel) {
- immUniformColor3ubvAlpha((unsigned char *)agrp->cs.select, col1a[3]);
- }
- else {
- immUniformColor3ubvAlpha((unsigned char *)agrp->cs.solid, col2a[3]);
- }
- }
- else {
- immUniformColor4ubv(sel ? col1a : col2a);
- }
- break;
- }
- 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]);
- }
- else {
- immUniformColor4ubv(sel ? col1 : col2);
- }
- break;
- }
- default:
- {
- immUniformColor4ubv(sel ? col1 : col2);
- }
- }
-
- /* draw region twice: firstly backdrop, then the current range */
- immRectf(pos, v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac));
- }
- else if (ac->datatype == ANIMCONT_GPENCIL) {
- unsigned char *color;
- if ((show_group_colors) && (ale->type == ANIMTYPE_GPLAYER)) {
- bGPDlayer *gpl = (bGPDlayer *)ale->data;
- unsigned char gpl_col[4];
- rgb_float_to_uchar(gpl_col, gpl->color);
- gpl_col[3] = col1[3];
-
- color = sel ? col1 : gpl_col;
- }
- else {
- color = sel ? col1 : col2;
- }
- /* frames less than one get less saturated background */
- immUniformColor4ubv(color);
- immRectf(pos, 0.0f, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF(ac));
-
- /* frames one and higher get a saturated background */
- immUniformColor3ubvAlpha(color, MIN2(255, color[3] * 2));
- immRectf(pos, v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac));
- }
- else if (ac->datatype == ANIMCONT_MASK) {
- /* TODO --- this is a copy of gpencil */
- /* frames less than one get less saturated background */
- unsigned char *color = sel ? col1 : col2;
- immUniformColor4ubv(color);
- immRectf(pos, 0.0f, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF(ac));
-
- /* frames one and higher get a saturated background */
- immUniformColor3ubvAlpha(color, MIN2(255, color[3] * 2));
- immRectf(pos, v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac));
- }
- }
- }
-
- /* Increment the step */
- y -= ACHANNEL_STEP(ac);
- }
- GPU_blend(false);
-
- /* black line marking 'current frame' for Time-Slide transform mode */
- if (saction->flag & SACTION_MOVING) {
- immUniformColor3f(0.0f, 0.0f, 0.0f);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, saction->timeslide, v2d->cur.ymin - EXTRA_SCROLL_PAD);
- immVertex2f(pos, saction->timeslide, v2d->cur.ymax);
- immEnd();
- }
- immUnbindProgram();
-
- /* Draw keyframes
- * 1) Only channels that are visible in the Action Editor get drawn/evaluated.
- * This is to try to optimize this for heavier data sets
- * 2) Keyframes which are out of view horizontally are disregarded
- */
- y = (float)(-ACHANNEL_HEIGHT(ac));
-
- int action_flag = saction->flag;
-
- if (saction->mode == SACTCONT_TIMELINE) {
- action_flag &= ~(SACTION_SHOW_INTERPOLATION | SACTION_SHOW_EXTREMES);
- }
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
- const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
-
- /* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
- {
- /* check if anything to show for this channel */
- if (ale->datatype != ALE_NONE) {
- adt = ANIM_nla_mapping_get(ac, ale);
-
- /* draw 'keyframes' for each specific datatype */
- switch (ale->datatype) {
- case ALE_ALL:
- draw_summary_channel(v2d, ale->data, y, ac->yscale_fac, action_flag);
- break;
- case ALE_SCE:
- draw_scene_channel(v2d, ads, ale->key_data, y, ac->yscale_fac, action_flag);
- break;
- case ALE_OB:
- draw_object_channel(v2d, ads, ale->key_data, y, ac->yscale_fac, action_flag);
- break;
- case ALE_ACT:
- draw_action_channel(v2d, adt, ale->key_data, y, ac->yscale_fac, action_flag);
- break;
- case ALE_GROUP:
- draw_agroup_channel(v2d, adt, ale->data, y, ac->yscale_fac, action_flag);
- break;
- case ALE_FCURVE:
- draw_fcurve_channel(v2d, adt, ale->key_data, y, ac->yscale_fac, action_flag);
- break;
- case ALE_GPFRAME:
- draw_gpl_channel(v2d, ads, ale->data, y, ac->yscale_fac, action_flag);
- break;
- case ALE_MASKLAY:
- draw_masklay_channel(v2d, ads, ale->data, y, ac->yscale_fac, action_flag);
- break;
- }
- }
- }
-
- y -= ACHANNEL_STEP(ac);
- }
-
- /* free temporary channels used for drawing */
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+
+ View2D *v2d = &ar->v2d;
+ bDopeSheet *ads = &saction->ads;
+ AnimData *adt = NULL;
+
+ float y;
+
+ unsigned char col1[4], col2[4];
+ unsigned char col1a[4], col2a[4];
+ unsigned char col1b[4], col2b[4];
+
+ const bool show_group_colors = !(saction->flag & SACTION_NODRAWGCOLORS);
+
+ /* get theme colors */
+ UI_GetThemeColor4ubv(TH_SHADE2, col2);
+ UI_GetThemeColor4ubv(TH_HILITE, col1);
+
+ UI_GetThemeColor4ubv(TH_GROUP, col2a);
+ UI_GetThemeColor4ubv(TH_GROUP_ACTIVE, col1a);
+
+ UI_GetThemeColor4ubv(TH_DOPESHEET_CHANNELOB, col1b);
+ UI_GetThemeColor4ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
+
+ /* build list of channels to draw */
+ int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ int height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac)));
+ /* don't use totrect set, as the width stays the same
+ * (NOTE: this is ok here, the configuration is pretty straightforward)
+ */
+ v2d->tot.ymin = (float)(-height);
+
+ /* first backdrop strips */
+ y = (float)(-ACHANNEL_HEIGHT(ac));
+
+ 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_blend(true);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
+ const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
+
+ /* check if visible */
+ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ int sel = 0;
+
+ /* determine if any need to draw channel */
+ if (ale->datatype != ALE_NONE) {
+ /* determine if channel is selected */
+ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT))
+ sel = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
+
+ if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY)) {
+ switch (ale->type) {
+ case ANIMTYPE_SUMMARY: {
+ /* reddish color from NLA */
+ immUniformThemeColor(TH_ANIM_ACTIVE);
+ break;
+ }
+ case ANIMTYPE_SCENE:
+ case ANIMTYPE_OBJECT: {
+ immUniformColor3ubvAlpha(col1b, sel ? col1[3] : col1b[3]);
+ break;
+ }
+ case ANIMTYPE_FILLACTD:
+ case ANIMTYPE_DSSKEY:
+ case ANIMTYPE_DSWOR: {
+ immUniformColor3ubvAlpha(col2b, sel ? col1[3] : col2b[3]);
+ break;
+ }
+ case ANIMTYPE_GROUP: {
+ bActionGroup *agrp = ale->data;
+ if (show_group_colors && agrp->customCol) {
+ if (sel) {
+ immUniformColor3ubvAlpha((unsigned char *)agrp->cs.select, col1a[3]);
+ }
+ else {
+ immUniformColor3ubvAlpha((unsigned char *)agrp->cs.solid, col2a[3]);
+ }
+ }
+ else {
+ immUniformColor4ubv(sel ? col1a : col2a);
+ }
+ break;
+ }
+ 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]);
+ }
+ else {
+ immUniformColor4ubv(sel ? col1 : col2);
+ }
+ break;
+ }
+ default: {
+ immUniformColor4ubv(sel ? col1 : col2);
+ }
+ }
+
+ /* draw region twice: firstly backdrop, then the current range */
+ immRectf(pos,
+ v2d->cur.xmin,
+ (float)y - ACHANNEL_HEIGHT_HALF(ac),
+ v2d->cur.xmax + EXTRA_SCROLL_PAD,
+ (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ }
+ else if (ac->datatype == ANIMCONT_GPENCIL) {
+ unsigned char *color;
+ if ((show_group_colors) && (ale->type == ANIMTYPE_GPLAYER)) {
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+ unsigned char gpl_col[4];
+ rgb_float_to_uchar(gpl_col, gpl->color);
+ gpl_col[3] = col1[3];
+
+ color = sel ? col1 : gpl_col;
+ }
+ else {
+ color = sel ? col1 : col2;
+ }
+ /* frames less than one get less saturated background */
+ immUniformColor4ubv(color);
+ immRectf(pos,
+ 0.0f,
+ (float)y - ACHANNEL_HEIGHT_HALF(ac),
+ v2d->cur.xmin,
+ (float)y + ACHANNEL_HEIGHT_HALF(ac));
+
+ /* frames one and higher get a saturated background */
+ immUniformColor3ubvAlpha(color, MIN2(255, color[3] * 2));
+ immRectf(pos,
+ v2d->cur.xmin,
+ (float)y - ACHANNEL_HEIGHT_HALF(ac),
+ v2d->cur.xmax + EXTRA_SCROLL_PAD,
+ (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ }
+ else if (ac->datatype == ANIMCONT_MASK) {
+ /* TODO --- this is a copy of gpencil */
+ /* frames less than one get less saturated background */
+ unsigned char *color = sel ? col1 : col2;
+ immUniformColor4ubv(color);
+ immRectf(pos,
+ 0.0f,
+ (float)y - ACHANNEL_HEIGHT_HALF(ac),
+ v2d->cur.xmin,
+ (float)y + ACHANNEL_HEIGHT_HALF(ac));
+
+ /* frames one and higher get a saturated background */
+ immUniformColor3ubvAlpha(color, MIN2(255, color[3] * 2));
+ immRectf(pos,
+ v2d->cur.xmin,
+ (float)y - ACHANNEL_HEIGHT_HALF(ac),
+ v2d->cur.xmax + EXTRA_SCROLL_PAD,
+ (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ }
+ }
+ }
+
+ /* Increment the step */
+ y -= ACHANNEL_STEP(ac);
+ }
+ GPU_blend(false);
+
+ /* black line marking 'current frame' for Time-Slide transform mode */
+ if (saction->flag & SACTION_MOVING) {
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, saction->timeslide, v2d->cur.ymin - EXTRA_SCROLL_PAD);
+ immVertex2f(pos, saction->timeslide, v2d->cur.ymax);
+ immEnd();
+ }
+ immUnbindProgram();
+
+ /* Draw keyframes
+ * 1) Only channels that are visible in the Action Editor get drawn/evaluated.
+ * This is to try to optimize this for heavier data sets
+ * 2) Keyframes which are out of view horizontally are disregarded
+ */
+ y = (float)(-ACHANNEL_HEIGHT(ac));
+
+ int action_flag = saction->flag;
+
+ if (saction->mode == SACTCONT_TIMELINE) {
+ action_flag &= ~(SACTION_SHOW_INTERPOLATION | SACTION_SHOW_EXTREMES);
+ }
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
+ const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
+
+ /* check if visible */
+ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ /* check if anything to show for this channel */
+ if (ale->datatype != ALE_NONE) {
+ adt = ANIM_nla_mapping_get(ac, ale);
+
+ /* draw 'keyframes' for each specific datatype */
+ switch (ale->datatype) {
+ case ALE_ALL:
+ draw_summary_channel(v2d, ale->data, y, ac->yscale_fac, action_flag);
+ break;
+ case ALE_SCE:
+ draw_scene_channel(v2d, ads, ale->key_data, y, ac->yscale_fac, action_flag);
+ break;
+ case ALE_OB:
+ draw_object_channel(v2d, ads, ale->key_data, y, ac->yscale_fac, action_flag);
+ break;
+ case ALE_ACT:
+ draw_action_channel(v2d, adt, ale->key_data, y, ac->yscale_fac, action_flag);
+ break;
+ case ALE_GROUP:
+ draw_agroup_channel(v2d, adt, ale->data, y, ac->yscale_fac, action_flag);
+ break;
+ case ALE_FCURVE:
+ draw_fcurve_channel(v2d, adt, ale->key_data, y, ac->yscale_fac, action_flag);
+ break;
+ case ALE_GPFRAME:
+ draw_gpl_channel(v2d, ads, ale->data, y, ac->yscale_fac, action_flag);
+ break;
+ case ALE_MASKLAY:
+ draw_masklay_channel(v2d, ads, ale->data, y, ac->yscale_fac, action_flag);
+ break;
+ }
+ }
+ }
+
+ y -= ACHANNEL_STEP(ac);
+ }
+
+ /* free temporary channels used for drawing */
+ ANIM_animdata_freelist(&anim_data);
}
/* ************************************************************************* */
@@ -395,148 +402,172 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
{
- PTCacheID *pid;
- ListBase pidlist;
- const float cache_draw_height = (4.0f * UI_DPI_FAC * U.pixelsize);
- float yoffs = 0.f;
-
- if (!(saction->cache_display & TIME_CACHE_DISPLAY) || (!ob))
- return;
-
- BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0);
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* iterate over pointcaches on the active object, and draw each one's range */
- for (pid = pidlist.first; pid; pid = pid->next) {
- float col[4];
-
- switch (pid->type) {
- case PTCACHE_TYPE_SOFTBODY:
- if (!(saction->cache_display & TIME_CACHE_SOFTBODY)) continue;
- break;
- case PTCACHE_TYPE_PARTICLES:
- if (!(saction->cache_display & TIME_CACHE_PARTICLES)) continue;
- break;
- case PTCACHE_TYPE_CLOTH:
- if (!(saction->cache_display & TIME_CACHE_CLOTH)) continue;
- break;
- case PTCACHE_TYPE_SMOKE_DOMAIN:
- case PTCACHE_TYPE_SMOKE_HIGHRES:
- if (!(saction->cache_display & TIME_CACHE_SMOKE)) continue;
- break;
- case PTCACHE_TYPE_DYNAMICPAINT:
- if (!(saction->cache_display & TIME_CACHE_DYNAMICPAINT)) continue;
- break;
- case PTCACHE_TYPE_RIGIDBODY:
- if (!(saction->cache_display & TIME_CACHE_RIGIDBODY)) continue;
- break;
- }
-
- if (pid->cache->cached_frames == NULL)
- continue;
-
- GPU_matrix_push();
- GPU_matrix_translate_2f(0.0, (float)V2D_SCROLL_HEIGHT_TEXT + yoffs);
- GPU_matrix_scale_2f(1.0, cache_draw_height);
-
- switch (pid->type) {
- case PTCACHE_TYPE_SOFTBODY:
- col[0] = 1.0; col[1] = 0.4; col[2] = 0.02;
- col[3] = 0.1;
- break;
- case PTCACHE_TYPE_PARTICLES:
- col[0] = 1.0; col[1] = 0.1; col[2] = 0.02;
- col[3] = 0.1;
- break;
- case PTCACHE_TYPE_CLOTH:
- col[0] = 0.1; col[1] = 0.1; col[2] = 0.75;
- col[3] = 0.1;
- break;
- case PTCACHE_TYPE_SMOKE_DOMAIN:
- case PTCACHE_TYPE_SMOKE_HIGHRES:
- col[0] = 0.2; col[1] = 0.2; col[2] = 0.2;
- col[3] = 0.1;
- break;
- case PTCACHE_TYPE_DYNAMICPAINT:
- col[0] = 1.0; col[1] = 0.1; col[2] = 0.75;
- col[3] = 0.1;
- break;
- case PTCACHE_TYPE_RIGIDBODY:
- col[0] = 1.0; col[1] = 0.6; col[2] = 0.0;
- col[3] = 0.1;
- break;
- default:
- col[0] = 1.0; col[1] = 0.0; col[2] = 1.0;
- col[3] = 0.1;
- BLI_assert(0);
- break;
- }
-
- const int sta = pid->cache->startframe, end = pid->cache->endframe;
-
- GPU_blend(true);
-
- immUniformColor4fv(col);
- immRectf(pos, (float)sta, 0.0, (float)end, 1.0);
-
- col[3] = 0.4f;
- if (pid->cache->flag & PTCACHE_BAKED) {
- col[0] -= 0.4f; col[1] -= 0.4f; col[2] -= 0.4f;
- }
- else if (pid->cache->flag & PTCACHE_OUTDATED) {
- col[0] += 0.4f; col[1] += 0.4f; col[2] += 0.4f;
- }
-
- immUniformColor4fv(col);
-
- {
- /* draw a quad for each chunk of consecutive cached frames */
- const int chunk_tot = 32;
- int chunk_len = 0;
- int ista = 0, iend = -1;
-
- for (int i = sta; i <= end; i++) {
- if (pid->cache->cached_frames[i - sta]) {
- if (chunk_len == 0) {
- immBeginAtMost(GPU_PRIM_TRIS, chunk_tot * 6);
- }
- if (ista > iend) {
- chunk_len++;
- ista = i;
- }
- iend = i;
- }
- else {
- if (ista <= iend) {
- immRectf_fast(pos, (float)ista - 0.5f, 0.0f, (float)iend + 0.5f, 1.0f);
- iend = ista - 1;
- }
- if (chunk_len >= chunk_tot) {
- immEnd();
- chunk_len = 0;
- }
- }
- }
- if (ista <= iend) {
- immRectf_fast(pos, (float)ista - 0.5f, 0.0f, (float)iend + 0.5f, 1.0f);
- }
- if (chunk_len != 0) {
- immEnd();
- }
- }
-
- GPU_blend(false);
-
- GPU_matrix_pop();
-
- yoffs += cache_draw_height;
- }
-
- immUnbindProgram();
-
- BLI_freelistN(&pidlist);
+ PTCacheID *pid;
+ ListBase pidlist;
+ const float cache_draw_height = (4.0f * UI_DPI_FAC * U.pixelsize);
+ float yoffs = 0.f;
+
+ if (!(saction->cache_display & TIME_CACHE_DISPLAY) || (!ob))
+ return;
+
+ BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0);
+
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* iterate over pointcaches on the active object, and draw each one's range */
+ for (pid = pidlist.first; pid; pid = pid->next) {
+ float col[4];
+
+ switch (pid->type) {
+ case PTCACHE_TYPE_SOFTBODY:
+ if (!(saction->cache_display & TIME_CACHE_SOFTBODY))
+ continue;
+ break;
+ case PTCACHE_TYPE_PARTICLES:
+ if (!(saction->cache_display & TIME_CACHE_PARTICLES))
+ continue;
+ break;
+ case PTCACHE_TYPE_CLOTH:
+ if (!(saction->cache_display & TIME_CACHE_CLOTH))
+ continue;
+ break;
+ case PTCACHE_TYPE_SMOKE_DOMAIN:
+ case PTCACHE_TYPE_SMOKE_HIGHRES:
+ if (!(saction->cache_display & TIME_CACHE_SMOKE))
+ continue;
+ break;
+ case PTCACHE_TYPE_DYNAMICPAINT:
+ if (!(saction->cache_display & TIME_CACHE_DYNAMICPAINT))
+ continue;
+ break;
+ case PTCACHE_TYPE_RIGIDBODY:
+ if (!(saction->cache_display & TIME_CACHE_RIGIDBODY))
+ continue;
+ break;
+ }
+
+ if (pid->cache->cached_frames == NULL)
+ continue;
+
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(0.0, (float)V2D_SCROLL_HEIGHT_TEXT + yoffs);
+ GPU_matrix_scale_2f(1.0, cache_draw_height);
+
+ switch (pid->type) {
+ case PTCACHE_TYPE_SOFTBODY:
+ col[0] = 1.0;
+ col[1] = 0.4;
+ col[2] = 0.02;
+ col[3] = 0.1;
+ break;
+ case PTCACHE_TYPE_PARTICLES:
+ col[0] = 1.0;
+ col[1] = 0.1;
+ col[2] = 0.02;
+ col[3] = 0.1;
+ break;
+ case PTCACHE_TYPE_CLOTH:
+ col[0] = 0.1;
+ col[1] = 0.1;
+ col[2] = 0.75;
+ col[3] = 0.1;
+ break;
+ case PTCACHE_TYPE_SMOKE_DOMAIN:
+ case PTCACHE_TYPE_SMOKE_HIGHRES:
+ col[0] = 0.2;
+ col[1] = 0.2;
+ col[2] = 0.2;
+ col[3] = 0.1;
+ break;
+ case PTCACHE_TYPE_DYNAMICPAINT:
+ col[0] = 1.0;
+ col[1] = 0.1;
+ col[2] = 0.75;
+ col[3] = 0.1;
+ break;
+ case PTCACHE_TYPE_RIGIDBODY:
+ col[0] = 1.0;
+ col[1] = 0.6;
+ col[2] = 0.0;
+ col[3] = 0.1;
+ break;
+ default:
+ col[0] = 1.0;
+ col[1] = 0.0;
+ col[2] = 1.0;
+ col[3] = 0.1;
+ BLI_assert(0);
+ break;
+ }
+
+ const int sta = pid->cache->startframe, end = pid->cache->endframe;
+
+ GPU_blend(true);
+
+ immUniformColor4fv(col);
+ immRectf(pos, (float)sta, 0.0, (float)end, 1.0);
+
+ col[3] = 0.4f;
+ if (pid->cache->flag & PTCACHE_BAKED) {
+ col[0] -= 0.4f;
+ col[1] -= 0.4f;
+ col[2] -= 0.4f;
+ }
+ else if (pid->cache->flag & PTCACHE_OUTDATED) {
+ col[0] += 0.4f;
+ col[1] += 0.4f;
+ col[2] += 0.4f;
+ }
+
+ immUniformColor4fv(col);
+
+ {
+ /* draw a quad for each chunk of consecutive cached frames */
+ const int chunk_tot = 32;
+ int chunk_len = 0;
+ int ista = 0, iend = -1;
+
+ for (int i = sta; i <= end; i++) {
+ if (pid->cache->cached_frames[i - sta]) {
+ if (chunk_len == 0) {
+ immBeginAtMost(GPU_PRIM_TRIS, chunk_tot * 6);
+ }
+ if (ista > iend) {
+ chunk_len++;
+ ista = i;
+ }
+ iend = i;
+ }
+ else {
+ if (ista <= iend) {
+ immRectf_fast(pos, (float)ista - 0.5f, 0.0f, (float)iend + 0.5f, 1.0f);
+ iend = ista - 1;
+ }
+ if (chunk_len >= chunk_tot) {
+ immEnd();
+ chunk_len = 0;
+ }
+ }
+ }
+ if (ista <= iend) {
+ immRectf_fast(pos, (float)ista - 0.5f, 0.0f, (float)iend + 0.5f, 1.0f);
+ }
+ if (chunk_len != 0) {
+ immEnd();
+ }
+ }
+
+ GPU_blend(false);
+
+ GPU_matrix_pop();
+
+ yoffs += cache_draw_height;
+ }
+
+ immUnbindProgram();
+
+ BLI_freelistN(&pidlist);
}
/* ************************************************************************* */
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index b0cc1b72b27..9ce709e1134 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -21,13 +21,11 @@
* \ingroup spaction
*/
-
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <float.h>
-
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -72,7 +70,6 @@
#include "action_intern.h"
-
/* ************************************************************************** */
/* POSE MARKERS STUFF */
@@ -86,73 +83,73 @@
*/
static bool act_markers_make_local_poll(bContext *C)
{
- SpaceAction *sact = CTX_wm_space_action(C);
+ SpaceAction *sact = CTX_wm_space_action(C);
- /* 1) */
- if (sact == NULL)
- return 0;
+ /* 1) */
+ if (sact == NULL)
+ return 0;
- /* 2) */
- if (ELEM(sact->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY) == 0)
- return 0;
- if (sact->action == NULL)
- return 0;
+ /* 2) */
+ if (ELEM(sact->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY) == 0)
+ return 0;
+ if (sact->action == NULL)
+ return 0;
- /* 3) */
- if (sact->flag & SACTION_POSEMARKERS_SHOW)
- return 0;
+ /* 3) */
+ if (sact->flag & SACTION_POSEMARKERS_SHOW)
+ return 0;
- /* 4) */
- return ED_markers_get_first_selected(ED_context_get_markers(C)) != NULL;
+ /* 4) */
+ return ED_markers_get_first_selected(ED_context_get_markers(C)) != NULL;
}
static int act_markers_make_local_exec(bContext *C, wmOperator *UNUSED(op))
{
- ListBase *markers = ED_context_get_markers(C);
+ ListBase *markers = ED_context_get_markers(C);
- SpaceAction *sact = CTX_wm_space_action(C);
- bAction *act = (sact) ? sact->action : NULL;
+ SpaceAction *sact = CTX_wm_space_action(C);
+ bAction *act = (sact) ? sact->action : NULL;
- TimeMarker *marker, *markern = NULL;
+ TimeMarker *marker, *markern = NULL;
- /* sanity checks */
- if (ELEM(NULL, markers, act))
- return OPERATOR_CANCELLED;
+ /* sanity checks */
+ if (ELEM(NULL, markers, act))
+ return OPERATOR_CANCELLED;
- /* migrate markers */
- for (marker = markers->first; marker; marker = markern) {
- markern = marker->next;
+ /* migrate markers */
+ for (marker = markers->first; marker; marker = markern) {
+ markern = marker->next;
- /* move if marker is selected */
- if (marker->flag & SELECT) {
- BLI_remlink(markers, marker);
- BLI_addtail(&act->markers, marker);
- }
- }
+ /* move if marker is selected */
+ if (marker->flag & SELECT) {
+ BLI_remlink(markers, marker);
+ BLI_addtail(&act->markers, marker);
+ }
+ }
- /* now enable the "show posemarkers only" setting, so that we can see that something did happen */
- sact->flag |= SACTION_POSEMARKERS_SHOW;
+ /* now enable the "show posemarkers only" setting, so that we can see that something did happen */
+ sact->flag |= SACTION_POSEMARKERS_SHOW;
- /* notifiers - both sets, as this change affects both */
- WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
+ /* notifiers - both sets, as this change affects both */
+ WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_markers_make_local(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Markers Local";
- ot->idname = "ACTION_OT_markers_make_local";
- ot->description = "Move selected scene markers to the active Action as local 'pose' markers";
+ /* identifiers */
+ ot->name = "Make Markers Local";
+ ot->idname = "ACTION_OT_markers_make_local";
+ ot->description = "Move selected scene markers to the active Action as local 'pose' markers";
- /* callbacks */
- ot->exec = act_markers_make_local_exec;
- ot->poll = act_markers_make_local_poll;
+ /* callbacks */
+ ot->exec = act_markers_make_local_exec;
+ ot->poll = act_markers_make_local_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ************************************************************************** */
@@ -163,142 +160,142 @@ void ACTION_OT_markers_make_local(wmOperatorType *ot)
/* Get the min/max keyframes*/
static bool get_keyframe_extents(bAnimContext *ac, float *min, float *max, const short onlySel)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- bool found = false;
-
- /* get data to filter, from Action or Dopesheet */
- /* XXX: what is sel doing here?!
- * Commented it, was breaking things (eg. the "auto preview range" tool). */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_SEL *//*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* set large values to try to override */
- *min = 999999999.0f;
- *max = -999999999.0f;
-
- /* check if any channels to set range with */
- if (anim_data.first) {
- /* go through channels, finding max extents */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
- if (ale->datatype == ALE_GPFRAME) {
- bGPDlayer *gpl = ale->data;
- bGPDframe *gpf;
-
- /* find gp-frame which is less than or equal to cframe */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- const float framenum = (float)gpf->framenum;
- *min = min_ff(*min, framenum);
- *max = max_ff(*max, framenum);
- found = true;
- }
- }
- else if (ale->datatype == ALE_MASKLAY) {
- MaskLayer *masklay = ale->data;
- MaskLayerShape *masklay_shape;
-
- /* find mask layer which is less than or equal to cframe */
- for (masklay_shape = masklay->splines_shapes.first;
- masklay_shape;
- masklay_shape = masklay_shape->next)
- {
- const float framenum = (float)masklay_shape->frame;
- *min = min_ff(*min, framenum);
- *max = max_ff(*max, framenum);
- found = true;
- }
- }
- else {
- FCurve *fcu = (FCurve *)ale->key_data;
- float tmin, tmax;
-
- /* get range and apply necessary scaling before processing */
- if (calc_fcurve_range(fcu, &tmin, &tmax, onlySel, false)) {
-
- if (adt) {
- tmin = BKE_nla_tweakedit_remap(adt, tmin, NLATIME_CONVERT_MAP);
- tmax = BKE_nla_tweakedit_remap(adt, tmax, NLATIME_CONVERT_MAP);
- }
-
- /* try to set cur using these values, if they're more extreme than previously set values */
- *min = min_ff(*min, tmin);
- *max = max_ff(*max, tmax);
- found = true;
- }
- }
- }
-
- if (fabsf(*max - *min) < 0.001f) {
- *min -= 0.0005f;
- *max += 0.0005f;
- }
-
- /* free memory */
- ANIM_animdata_freelist(&anim_data);
- }
- else {
- /* set default range */
- if (ac->scene) {
- *min = (float)ac->scene->r.sfra;
- *max = (float)ac->scene->r.efra;
- }
- else {
- *min = -5;
- *max = 100;
- }
- }
-
- return found;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ bool found = false;
+
+ /* get data to filter, from Action or Dopesheet */
+ /* XXX: what is sel doing here?!
+ * Commented it, was breaking things (eg. the "auto preview range" tool). */
+ filter = (ANIMFILTER_DATA_VISIBLE |
+ ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_SEL */ /*| ANIMFILTER_CURVESONLY*/ |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* set large values to try to override */
+ *min = 999999999.0f;
+ *max = -999999999.0f;
+
+ /* check if any channels to set range with */
+ if (anim_data.first) {
+ /* go through channels, finding max extents */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+ if (ale->datatype == ALE_GPFRAME) {
+ bGPDlayer *gpl = ale->data;
+ bGPDframe *gpf;
+
+ /* find gp-frame which is less than or equal to cframe */
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ const float framenum = (float)gpf->framenum;
+ *min = min_ff(*min, framenum);
+ *max = max_ff(*max, framenum);
+ found = true;
+ }
+ }
+ else if (ale->datatype == ALE_MASKLAY) {
+ MaskLayer *masklay = ale->data;
+ MaskLayerShape *masklay_shape;
+
+ /* find mask layer which is less than or equal to cframe */
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape->next) {
+ const float framenum = (float)masklay_shape->frame;
+ *min = min_ff(*min, framenum);
+ *max = max_ff(*max, framenum);
+ found = true;
+ }
+ }
+ else {
+ FCurve *fcu = (FCurve *)ale->key_data;
+ float tmin, tmax;
+
+ /* get range and apply necessary scaling before processing */
+ if (calc_fcurve_range(fcu, &tmin, &tmax, onlySel, false)) {
+
+ if (adt) {
+ tmin = BKE_nla_tweakedit_remap(adt, tmin, NLATIME_CONVERT_MAP);
+ tmax = BKE_nla_tweakedit_remap(adt, tmax, NLATIME_CONVERT_MAP);
+ }
+
+ /* try to set cur using these values, if they're more extreme than previously set values */
+ *min = min_ff(*min, tmin);
+ *max = max_ff(*max, tmax);
+ found = true;
+ }
+ }
+ }
+
+ if (fabsf(*max - *min) < 0.001f) {
+ *min -= 0.0005f;
+ *max += 0.0005f;
+ }
+
+ /* free memory */
+ ANIM_animdata_freelist(&anim_data);
+ }
+ else {
+ /* set default range */
+ if (ac->scene) {
+ *min = (float)ac->scene->r.sfra;
+ *max = (float)ac->scene->r.efra;
+ }
+ else {
+ *min = -5;
+ *max = 100;
+ }
+ }
+
+ return found;
}
/* ****************** Automatic Preview-Range Operator ****************** */
static int actkeys_previewrange_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
- Scene *scene;
- float min, max;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
- if (ac.scene == NULL)
- return OPERATOR_CANCELLED;
- else
- scene = ac.scene;
-
- /* set the range directly */
- get_keyframe_extents(&ac, &min, &max, false);
- scene->r.flag |= SCER_PRV_RANGE;
- scene->r.psfra = floorf(min);
- scene->r.pefra = ceilf(max);
-
- if (scene->r.psfra == scene->r.pefra) {
- scene->r.pefra = scene->r.psfra + 1;
- }
-
- /* set notifier that things have changed */
- // XXX err... there's nothing for frame ranges yet, but this should do fine too
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ Scene *scene;
+ float min, max;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ if (ac.scene == NULL)
+ return OPERATOR_CANCELLED;
+ else
+ scene = ac.scene;
+
+ /* set the range directly */
+ get_keyframe_extents(&ac, &min, &max, false);
+ scene->r.flag |= SCER_PRV_RANGE;
+ scene->r.psfra = floorf(min);
+ scene->r.pefra = ceilf(max);
+
+ if (scene->r.psfra == scene->r.pefra) {
+ scene->r.pefra = scene->r.psfra + 1;
+ }
+
+ /* set notifier that things have changed */
+ // XXX err... there's nothing for frame ranges yet, but this should do fine too
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene);
+
+ return OPERATOR_FINISHED;
}
void ACTION_OT_previewrange_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Auto-Set Preview Range";
- ot->idname = "ACTION_OT_previewrange_set";
- ot->description = "Set Preview Range based on extents of selected Keyframes";
+ /* identifiers */
+ ot->name = "Auto-Set Preview Range";
+ ot->idname = "ACTION_OT_previewrange_set";
+ ot->description = "Set Preview Range based on extents of selected Keyframes";
- /* api callbacks */
- ot->exec = actkeys_previewrange_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->exec = actkeys_previewrange_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** View-All Operator ****************** */
@@ -312,187 +309,186 @@ void ACTION_OT_previewrange_set(wmOperatorType *ot)
*/
static bool actkeys_channels_get_selected_extents(bAnimContext *ac, float *min, float *max)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* NOTE: not bool, since we want prioritise individual channels over expanders */
- short found = 0;
- float y;
-
- /* get all items - we need to do it this way */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* loop through all channels, finding the first one that's selected */
- y = (float)ACHANNEL_FIRST(ac);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
-
- /* must be selected... */
- if (acf && acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT) &&
- ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT))
- {
- /* update best estimate */
- *min = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
- *max = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
-
- /* is this high enough priority yet? */
- found = acf->channel_role;
-
- /* only stop our search when we've found an actual channel
- * - datablock expanders get less priority so that we don't abort prematurely
- */
- if (found == ACHANNEL_ROLE_CHANNEL) {
- break;
- }
- }
-
- /* adjust y-position for next one */
- y -= ACHANNEL_STEP(ac);
- }
-
- /* free all temp data */
- ANIM_animdata_freelist(&anim_data);
-
- return (found != 0);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* NOTE: not bool, since we want prioritise individual channels over expanders */
+ short found = 0;
+ float y;
+
+ /* get all items - we need to do it this way */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through all channels, finding the first one that's selected */
+ y = (float)ACHANNEL_FIRST(ac);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+
+ /* must be selected... */
+ if (acf && acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT) &&
+ ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT)) {
+ /* update best estimate */
+ *min = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
+ *max = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
+
+ /* is this high enough priority yet? */
+ found = acf->channel_role;
+
+ /* only stop our search when we've found an actual channel
+ * - datablock expanders get less priority so that we don't abort prematurely
+ */
+ if (found == ACHANNEL_ROLE_CHANNEL) {
+ break;
+ }
+ }
+
+ /* adjust y-position for next one */
+ y -= ACHANNEL_STEP(ac);
+ }
+
+ /* free all temp data */
+ ANIM_animdata_freelist(&anim_data);
+
+ return (found != 0);
}
static int actkeys_viewall(bContext *C, const bool only_sel)
{
- bAnimContext ac;
- View2D *v2d;
- float extra, min, max;
- bool found;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
- v2d = &ac.ar->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);
-
- if (only_sel && (found == false))
- return OPERATOR_CANCELLED;
-
- if (fabsf(max - min) < 1.0f) {
- /* Exception - center the single keyfrme */
- float xwidth = BLI_rctf_size_x(&v2d->cur);
-
- v2d->cur.xmin = min - xwidth / 2.0f;
- v2d->cur.xmax = max + xwidth / 2.0f;
- }
- else {
- /* Normal case - stretch the two keyframes out to fill the space, with extra spacing */
- v2d->cur.xmin = min;
- v2d->cur.xmax = max;
-
- extra = 0.125f * BLI_rctf_size_x(&v2d->cur);
- v2d->cur.xmin -= extra;
- v2d->cur.xmax += extra;
- }
-
- /* set vertical range */
- if (only_sel == false) {
- /* view all -> the summary channel is usually the shows everything, and resides right at the top... */
- v2d->cur.ymax = 0.0f;
- v2d->cur.ymin = (float)-BLI_rcti_size_y(&v2d->mask);
- }
- else {
- /* locate first selected channel (or the active one), and frame those */
- float ymin = v2d->cur.ymin;
- float ymax = v2d->cur.ymax;
-
- if (actkeys_channels_get_selected_extents(&ac, &ymin, &ymax)) {
- /* recenter the view so that this range is in the middle */
- float ymid = (ymax - ymin) / 2.0f + ymin;
- float x_center;
-
- UI_view2d_center_get(v2d, &x_center, NULL);
- UI_view2d_center_set(v2d, x_center, ymid);
- }
- }
-
- /* do View2D syncing */
- UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
-
- /* just redraw this view */
- ED_area_tag_redraw(CTX_wm_area(C));
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ View2D *v2d;
+ float extra, min, max;
+ bool found;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ v2d = &ac.ar->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);
+
+ if (only_sel && (found == false))
+ return OPERATOR_CANCELLED;
+
+ if (fabsf(max - min) < 1.0f) {
+ /* Exception - center the single keyfrme */
+ float xwidth = BLI_rctf_size_x(&v2d->cur);
+
+ v2d->cur.xmin = min - xwidth / 2.0f;
+ v2d->cur.xmax = max + xwidth / 2.0f;
+ }
+ else {
+ /* Normal case - stretch the two keyframes out to fill the space, with extra spacing */
+ v2d->cur.xmin = min;
+ v2d->cur.xmax = max;
+
+ extra = 0.125f * BLI_rctf_size_x(&v2d->cur);
+ v2d->cur.xmin -= extra;
+ v2d->cur.xmax += extra;
+ }
+
+ /* set vertical range */
+ if (only_sel == false) {
+ /* view all -> the summary channel is usually the shows everything, and resides right at the top... */
+ v2d->cur.ymax = 0.0f;
+ v2d->cur.ymin = (float)-BLI_rcti_size_y(&v2d->mask);
+ }
+ else {
+ /* locate first selected channel (or the active one), and frame those */
+ float ymin = v2d->cur.ymin;
+ float ymax = v2d->cur.ymax;
+
+ if (actkeys_channels_get_selected_extents(&ac, &ymin, &ymax)) {
+ /* recenter the view so that this range is in the middle */
+ float ymid = (ymax - ymin) / 2.0f + ymin;
+ float x_center;
+
+ UI_view2d_center_get(v2d, &x_center, NULL);
+ UI_view2d_center_set(v2d, x_center, ymid);
+ }
+ }
+
+ /* do View2D syncing */
+ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
+
+ /* just redraw this view */
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
}
/* ......... */
static int actkeys_viewall_exec(bContext *C, wmOperator *UNUSED(op))
{
- /* whole range */
- return actkeys_viewall(C, false);
+ /* whole range */
+ return actkeys_viewall(C, false);
}
static int actkeys_viewsel_exec(bContext *C, wmOperator *UNUSED(op))
{
- /* only selected */
- return actkeys_viewall(C, true);
+ /* only selected */
+ return actkeys_viewall(C, true);
}
/* ......... */
void ACTION_OT_view_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View All";
- ot->idname = "ACTION_OT_view_all";
- ot->description = "Reset viewable area to show full keyframe range";
+ /* identifiers */
+ ot->name = "View All";
+ ot->idname = "ACTION_OT_view_all";
+ ot->description = "Reset viewable area to show full keyframe range";
- /* api callbacks */
- ot->exec = actkeys_viewall_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->exec = actkeys_viewall_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void ACTION_OT_view_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Selected";
- ot->idname = "ACTION_OT_view_selected";
- ot->description = "Reset viewable area to show selected keyframes range";
+ /* identifiers */
+ ot->name = "View Selected";
+ ot->idname = "ACTION_OT_view_selected";
+ ot->description = "Reset viewable area to show selected keyframes range";
- /* api callbacks */
- ot->exec = actkeys_viewsel_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->exec = actkeys_viewsel_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** View-All Operator ****************** */
static int actkeys_view_frame_exec(bContext *C, wmOperator *op)
{
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- ANIM_center_frame(C, smooth_viewtx);
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ ANIM_center_frame(C, smooth_viewtx);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_view_frame(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Frame";
- ot->idname = "ACTION_OT_view_frame";
- ot->description = "Reset viewable area to show range around current frame";
+ /* identifiers */
+ ot->name = "View Frame";
+ ot->idname = "ACTION_OT_view_frame";
+ ot->description = "Reset viewable area to show range around current frame";
- /* api callbacks */
- ot->exec = actkeys_view_frame_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->exec = actkeys_view_frame_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ************************************************************************** */
@@ -503,553 +499,589 @@ void ACTION_OT_view_frame(wmOperatorType *ot)
static short copy_action_keys(bAnimContext *ac)
{
- ListBase anim_data = {NULL, NULL};
- int filter, ok = 0;
+ ListBase anim_data = {NULL, NULL};
+ int filter, ok = 0;
- /* clear buffer first */
- ANIM_fcurves_copybuf_free();
+ /* clear buffer first */
+ ANIM_fcurves_copybuf_free();
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* copy keyframes */
- ok = copy_animedit_keys(ac, &anim_data);
+ /* copy keyframes */
+ ok = copy_animedit_keys(ac, &anim_data);
- /* clean up */
- ANIM_animdata_freelist(&anim_data);
+ /* clean up */
+ ANIM_animdata_freelist(&anim_data);
- return ok;
+ return ok;
}
-
static short paste_action_keys(bAnimContext *ac,
- const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip)
+ const eKeyPasteOffset offset_mode,
+ const eKeyMergeMode merge_mode,
+ bool flip)
{
- ListBase anim_data = {NULL, NULL};
- int filter, ok = 0;
+ ListBase anim_data = {NULL, NULL};
+ int filter, ok = 0;
- /* filter data
- * - First time we try to filter more strictly, allowing only selected channels
- * to allow copying animation between channels
- * - Second time, we loosen things up if nothing was found the first time, allowing
- * users to just paste keyframes back into the original curve again [#31670]
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+ /* filter data
+ * - First time we try to filter more strictly, allowing only selected channels
+ * to allow copying animation between channels
+ * - Second time, we loosen things up if nothing was found the first time, allowing
+ * users to just paste keyframes back into the original curve again [#31670]
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
+ ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
- if (ANIM_animdata_filter(ac, &anim_data, filter | ANIMFILTER_SEL, ac->data, ac->datatype) == 0) {
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- }
+ if (ANIM_animdata_filter(ac, &anim_data, filter | ANIMFILTER_SEL, ac->data, ac->datatype) == 0) {
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ }
- /* paste keyframes */
- ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode, flip);
+ /* paste keyframes */
+ ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode, flip);
- /* clean up */
- ANIM_animdata_freelist(&anim_data);
+ /* clean up */
+ ANIM_animdata_freelist(&anim_data);
- return ok;
+ return ok;
}
/* ------------------- */
static int actkeys_copy_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* copy keyframes */
- if (ac.datatype == ANIMCONT_GPENCIL) {
- if (ED_gpencil_anim_copybuf_copy(&ac) == false) {
- /* Nothing got copied - An error about this should be been logged already */
- return OPERATOR_CANCELLED;
- }
- }
- else if (ac.datatype == ANIMCONT_MASK) {
- /* FIXME... */
- BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for mask mode");
- return OPERATOR_CANCELLED;
- }
- else {
- if (copy_action_keys(&ac)) {
- BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
- return OPERATOR_CANCELLED;
- }
- }
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* copy keyframes */
+ if (ac.datatype == ANIMCONT_GPENCIL) {
+ if (ED_gpencil_anim_copybuf_copy(&ac) == false) {
+ /* Nothing got copied - An error about this should be been logged already */
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else if (ac.datatype == ANIMCONT_MASK) {
+ /* FIXME... */
+ BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for mask mode");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ if (copy_action_keys(&ac)) {
+ BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void ACTION_OT_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Keyframes";
- ot->idname = "ACTION_OT_copy";
- ot->description = "Copy selected keyframes to the copy/paste buffer";
+ /* identifiers */
+ ot->name = "Copy Keyframes";
+ ot->idname = "ACTION_OT_copy";
+ ot->description = "Copy selected keyframes to the copy/paste buffer";
- /* api callbacks */
- ot->exec = actkeys_copy_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->exec = actkeys_copy_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int actkeys_paste_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
-
- const eKeyPasteOffset offset_mode = RNA_enum_get(op->ptr, "offset");
- const eKeyMergeMode merge_mode = RNA_enum_get(op->ptr, "merge");
- const bool flipped = RNA_boolean_get(op->ptr, "flipped");
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* ac.reports by default will be the global reports list, which won't show warnings */
- ac.reports = op->reports;
-
- /* paste keyframes */
- if (ac.datatype == ANIMCONT_GPENCIL) {
- if (ED_gpencil_anim_copybuf_paste(&ac, offset_mode) == false) {
- /* An error occurred - Reports should have been fired already */
- return OPERATOR_CANCELLED;
- }
- }
- else if (ac.datatype == ANIMCONT_MASK) {
- /* FIXME... */
- BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for grease pencil or mask mode");
- return OPERATOR_CANCELLED;
- }
- else {
- /* non-zero return means an error occurred while trying to paste */
- if (paste_action_keys(&ac, offset_mode, merge_mode, flipped)) {
- return OPERATOR_CANCELLED;
- }
- }
-
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+
+ const eKeyPasteOffset offset_mode = RNA_enum_get(op->ptr, "offset");
+ const eKeyMergeMode merge_mode = RNA_enum_get(op->ptr, "merge");
+ const bool flipped = RNA_boolean_get(op->ptr, "flipped");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* ac.reports by default will be the global reports list, which won't show warnings */
+ ac.reports = op->reports;
+
+ /* paste keyframes */
+ if (ac.datatype == ANIMCONT_GPENCIL) {
+ if (ED_gpencil_anim_copybuf_paste(&ac, offset_mode) == false) {
+ /* An error occurred - Reports should have been fired already */
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else if (ac.datatype == ANIMCONT_MASK) {
+ /* FIXME... */
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Keyframe pasting is not available for grease pencil or mask mode");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* non-zero return means an error occurred while trying to paste */
+ if (paste_action_keys(&ac, offset_mode, merge_mode, flipped)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
}
void ACTION_OT_paste(wmOperatorType *ot)
{
- PropertyRNA *prop;
- /* identifiers */
- ot->name = "Paste Keyframes";
- ot->idname = "ACTION_OT_paste";
- ot->description = "Paste keyframes from copy/paste buffer for the selected channels, starting on the current frame";
-
- /* api callbacks */
-// ot->invoke = WM_operator_props_popup; // better wait for action redo panel
- ot->exec = actkeys_paste_exec;
- ot->poll = ED_operator_action_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- RNA_def_enum(ot->srna, "offset", rna_enum_keyframe_paste_offset_items, KEYFRAME_PASTE_OFFSET_CFRA_START, "Offset", "Paste time offset of keys");
- RNA_def_enum(ot->srna, "merge", rna_enum_keyframe_paste_merge_items, KEYFRAME_PASTE_MERGE_MIX, "Type", "Method of merging pasted keys and existing");
- prop = RNA_def_boolean(ot->srna, "flipped", false, "Flipped", "Paste keyframes from mirrored bones if they exist");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+ /* identifiers */
+ ot->name = "Paste Keyframes";
+ ot->idname = "ACTION_OT_paste";
+ ot->description =
+ "Paste keyframes from copy/paste buffer for the selected channels, starting on the current "
+ "frame";
+
+ /* api callbacks */
+ // ot->invoke = WM_operator_props_popup; // better wait for action redo panel
+ ot->exec = actkeys_paste_exec;
+ ot->poll = ED_operator_action_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna,
+ "offset",
+ rna_enum_keyframe_paste_offset_items,
+ KEYFRAME_PASTE_OFFSET_CFRA_START,
+ "Offset",
+ "Paste time offset of keys");
+ RNA_def_enum(ot->srna,
+ "merge",
+ rna_enum_keyframe_paste_merge_items,
+ KEYFRAME_PASTE_MERGE_MIX,
+ "Type",
+ "Method of merging pasted keys and existing");
+ prop = RNA_def_boolean(
+ ot->srna, "flipped", false, "Flipped", "Paste keyframes from mirrored bones if they exist");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ******************** Insert Keyframes Operator ************************* */
/* defines for insert keyframes tool */
static const EnumPropertyItem prop_actkeys_insertkey_types[] = {
- {1, "ALL", 0, "All Channels", ""},
- {2, "SEL", 0, "Only Selected Channels", ""},
- {3, "GROUP", 0, "In Active Group", ""}, /* XXX not in all cases */
- {0, NULL, 0, NULL, NULL},
+ {1, "ALL", 0, "All Channels", ""},
+ {2, "SEL", 0, "Only Selected Channels", ""},
+ {3, "GROUP", 0, "In Active Group", ""}, /* XXX not in all cases */
+ {0, NULL, 0, NULL, NULL},
};
/* this function is responsible for inserting new keyframes */
static void insert_action_keys(bAnimContext *ac, short mode)
{
- ListBase anim_data = {NULL, NULL};
- ListBase nla_cache = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- struct Depsgraph *depsgraph = ac->depsgraph;
- ReportList *reports = ac->reports;
- Scene *scene = ac->scene;
- ToolSettings *ts = scene->toolsettings;
- short flag = 0;
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
- if (mode == 2) {
- filter |= ANIMFILTER_SEL;
- }
- else if (mode == 3) {
- filter |= ANIMFILTER_ACTGROUPED;
- }
-
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* init keyframing flag */
- flag = ANIM_get_keyframing_flags(scene, 1);
-
- /* insert keyframes */
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
- float cfra = (float)CFRA;
-
- /* read value from property the F-Curve represents, or from the curve only?
- * - ale->id != NULL: Typically, this means that we have enough info to try resolving the path
- * - ale->owner != NULL: If this is set, then the path may not be resolvable from the ID alone,
- * so it's easier for now to just read the F-Curve directly.
- * (TODO: add the full-blown PointerRNA relative parsing case here...)
- */
- if (ale->id && !ale->owner) {
- insert_keyframe(ac->bmain, depsgraph, reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)),
- fcu->rna_path, fcu->array_index, cfra, ts->keyframe_type, &nla_cache, flag);
- }
- else {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-
- /* adjust current frame for NLA-scaling */
- if (adt)
- cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
-
- const float curval = evaluate_fcurve(fcu, cfra);
- insert_vert_fcurve(fcu, cfra, curval, ts->keyframe_type, 0);
- }
-
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
-
- BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ ListBase nla_cache = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ struct Depsgraph *depsgraph = ac->depsgraph;
+ ReportList *reports = ac->reports;
+ Scene *scene = ac->scene;
+ ToolSettings *ts = scene->toolsettings;
+ short flag = 0;
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
+ ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+ if (mode == 2) {
+ filter |= ANIMFILTER_SEL;
+ }
+ else if (mode == 3) {
+ filter |= ANIMFILTER_ACTGROUPED;
+ }
+
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* init keyframing flag */
+ flag = ANIM_get_keyframing_flags(scene, 1);
+
+ /* insert keyframes */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
+ float cfra = (float)CFRA;
+
+ /* read value from property the F-Curve represents, or from the curve only?
+ * - ale->id != NULL: Typically, this means that we have enough info to try resolving the path
+ * - ale->owner != NULL: If this is set, then the path may not be resolvable from the ID alone,
+ * so it's easier for now to just read the F-Curve directly.
+ * (TODO: add the full-blown PointerRNA relative parsing case here...)
+ */
+ if (ale->id && !ale->owner) {
+ insert_keyframe(ac->bmain,
+ depsgraph,
+ reports,
+ ale->id,
+ NULL,
+ ((fcu->grp) ? (fcu->grp->name) : (NULL)),
+ fcu->rna_path,
+ fcu->array_index,
+ cfra,
+ ts->keyframe_type,
+ &nla_cache,
+ flag);
+ }
+ else {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ /* adjust current frame for NLA-scaling */
+ if (adt)
+ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+
+ const float curval = evaluate_fcurve(fcu, cfra);
+ insert_vert_fcurve(fcu, cfra, curval, ts->keyframe_type, 0);
+ }
+
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
+
+ BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* this function is for inserting new grease pencil frames */
static void insert_gpencil_keys(bAnimContext *ac, short mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- Scene *scene = ac->scene;
- ToolSettings *ts = scene->toolsettings;
- eGP_GetFrame_Mode add_frame_mode;
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- if (mode == 2) filter |= ANIMFILTER_SEL;
-
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
-
- /* add a copy or a blank frame? */
- if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST)
- add_frame_mode = GP_GETFRAME_ADD_COPY; /* XXX: actframe may not be what we want? */
- else
- add_frame_mode = GP_GETFRAME_ADD_NEW;
-
-
- /* 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);
- }
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ Scene *scene = ac->scene;
+ ToolSettings *ts = scene->toolsettings;
+ eGP_GetFrame_Mode add_frame_mode;
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_NODUPLIS);
+ if (mode == 2)
+ filter |= ANIMFILTER_SEL;
+
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* add a copy or a blank frame? */
+ if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST)
+ add_frame_mode = GP_GETFRAME_ADD_COPY; /* XXX: actframe may not be what we want? */
+ else
+ add_frame_mode = GP_GETFRAME_ADD_NEW;
+
+ /* 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);
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int actkeys_insertkey_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- short mode;
+ bAnimContext ac;
+ short mode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- if (ac.datatype == ANIMCONT_MASK) {
- BKE_report(op->reports, RPT_ERROR, "Insert Keyframes is not yet implemented for this mode");
- return OPERATOR_CANCELLED;
- }
+ if (ac.datatype == ANIMCONT_MASK) {
+ BKE_report(op->reports, RPT_ERROR, "Insert Keyframes is not yet implemented for this mode");
+ return OPERATOR_CANCELLED;
+ }
- /* what channels to affect? */
- mode = RNA_enum_get(op->ptr, "type");
+ /* what channels to affect? */
+ mode = RNA_enum_get(op->ptr, "type");
- /* insert keyframes */
- if (ac.datatype == ANIMCONT_GPENCIL) {
- insert_gpencil_keys(&ac, mode);
- }
- else {
- insert_action_keys(&ac, mode);
- }
+ /* insert keyframes */
+ if (ac.datatype == ANIMCONT_GPENCIL) {
+ insert_gpencil_keys(&ac, mode);
+ }
+ else {
+ insert_action_keys(&ac, mode);
+ }
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_keyframe_insert(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Insert Keyframes";
- ot->idname = "ACTION_OT_keyframe_insert";
- ot->description = "Insert keyframes for the specified channels";
+ /* identifiers */
+ ot->name = "Insert Keyframes";
+ ot->idname = "ACTION_OT_keyframe_insert";
+ ot->description = "Insert keyframes for the specified channels";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = actkeys_insertkey_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = actkeys_insertkey_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* id-props */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_insertkey_types, 0, "Type", "");
+ /* id-props */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_insertkey_types, 0, "Type", "");
}
/* ******************** Duplicate Keyframes Operator ************************* */
static void duplicate_action_keys(bAnimContext *ac)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* filter data */
- if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- }
- else {
- 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 filtered data and delete selected keys */
- for (ale = anim_data.first; ale; ale = ale->next) {
- if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE))
- duplicate_fcurve_keys((FCurve *)ale->key_data);
- else if (ale->type == ANIMTYPE_GPLAYER)
- ED_gplayer_frames_duplicate((bGPDlayer *)ale->data);
- else if (ale->type == ANIMTYPE_MASKLAYER)
- ED_masklayer_frames_duplicate((MaskLayer *)ale->data);
- else
- BLI_assert(0);
-
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_NODUPLIS);
+ }
+ else {
+ 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 filtered data and delete selected keys */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE))
+ duplicate_fcurve_keys((FCurve *)ale->key_data);
+ else if (ale->type == ANIMTYPE_GPLAYER)
+ ED_gplayer_frames_duplicate((bGPDlayer *)ale->data);
+ else if (ale->type == ANIMTYPE_MASKLAYER)
+ ED_masklayer_frames_duplicate((MaskLayer *)ale->data);
+ else
+ BLI_assert(0);
+
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int actkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
+ bAnimContext ac;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* duplicate keyframes */
- duplicate_action_keys(&ac);
+ /* duplicate keyframes */
+ duplicate_action_keys(&ac);
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_duplicate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Duplicate Keyframes";
- ot->idname = "ACTION_OT_duplicate";
- ot->description = "Make a copy of all selected keyframes";
+ /* identifiers */
+ ot->name = "Duplicate Keyframes";
+ ot->idname = "ACTION_OT_duplicate";
+ ot->description = "Make a copy of all selected keyframes";
- /* api callbacks */
- ot->exec = actkeys_duplicate_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->exec = actkeys_duplicate_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Delete Keyframes Operator ************************* */
static bool delete_action_keys(bAnimContext *ac)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- bool changed_final = false;
-
- /* filter data */
- if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- }
- else {
- 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 filtered data and delete selected keys */
- for (ale = anim_data.first; ale; ale = ale->next) {
- bool changed = false;
-
- if (ale->type == ANIMTYPE_GPLAYER) {
- changed = ED_gplayer_frames_delete((bGPDlayer *)ale->data);
- }
- else if (ale->type == ANIMTYPE_MASKLAYER) {
- changed = ED_masklayer_frames_delete((MaskLayer *)ale->data);
- }
- else {
- FCurve *fcu = (FCurve *)ale->key_data;
- AnimData *adt = ale->adt;
-
- /* delete selected keyframes only */
- changed = delete_fcurve_keys(fcu);
-
- /* Only delete curve too if it won't be doing anything anymore */
- if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0)) {
- ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
- ale->key_data = NULL;
- }
- }
-
- if (changed) {
- ale->update |= ANIM_UPDATE_DEFAULT;
- changed_final = true;
- }
- }
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
-
- return changed_final;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ bool changed_final = false;
+
+ /* filter data */
+ if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_NODUPLIS);
+ }
+ else {
+ 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 filtered data and delete selected keys */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ bool changed = false;
+
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ changed = ED_gplayer_frames_delete((bGPDlayer *)ale->data);
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ changed = ED_masklayer_frames_delete((MaskLayer *)ale->data);
+ }
+ else {
+ FCurve *fcu = (FCurve *)ale->key_data;
+ AnimData *adt = ale->adt;
+
+ /* delete selected keyframes only */
+ changed = delete_fcurve_keys(fcu);
+
+ /* Only delete curve too if it won't be doing anything anymore */
+ if ((fcu->totvert == 0) &&
+ (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0)) {
+ ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
+ ale->key_data = NULL;
+ }
+ }
+
+ if (changed) {
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ changed_final = true;
+ }
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+
+ return changed_final;
}
/* ------------------- */
static int actkeys_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
+ bAnimContext ac;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* delete keyframes */
- if (!delete_action_keys(&ac))
- return OPERATOR_CANCELLED;
+ /* delete keyframes */
+ if (!delete_action_keys(&ac))
+ return OPERATOR_CANCELLED;
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Keyframes";
- ot->idname = "ACTION_OT_delete";
- ot->description = "Remove all selected keyframes";
-
- /* api callbacks */
- ot->invoke = WM_operator_confirm;
- ot->exec = actkeys_delete_exec;
- ot->poll = ED_operator_action_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Delete Keyframes";
+ ot->idname = "ACTION_OT_delete";
+ ot->description = "Remove all selected keyframes";
+
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = actkeys_delete_exec;
+ ot->poll = ED_operator_action_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Clean Keyframes Operator ************************* */
static void clean_action_keys(bAnimContext *ac, float thresh, bool clean_chan)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_SEL /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* loop through filtered data and clean curves */
- for (ale = anim_data.first; ale; ale = ale->next) {
- clean_fcurve(ac, ale, thresh, clean_chan);
+ /* loop through filtered data and clean curves */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ clean_fcurve(ac, ale, thresh, clean_chan);
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int actkeys_clean_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- float thresh;
- bool clean_chan;
+ bAnimContext ac;
+ float thresh;
+ bool clean_chan;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
- BKE_report(op->reports, RPT_ERROR, "Not implemented");
- return OPERATOR_PASS_THROUGH;
- }
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented");
+ return OPERATOR_PASS_THROUGH;
+ }
- /* get cleaning threshold */
- thresh = RNA_float_get(op->ptr, "threshold");
- clean_chan = RNA_boolean_get(op->ptr, "channels");
+ /* get cleaning threshold */
+ thresh = RNA_float_get(op->ptr, "threshold");
+ clean_chan = RNA_boolean_get(op->ptr, "channels");
- /* clean keyframes */
- clean_action_keys(&ac, thresh, clean_chan);
+ /* clean keyframes */
+ clean_action_keys(&ac, thresh, clean_chan);
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_clean(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clean Keyframes";
- ot->idname = "ACTION_OT_clean";
- ot->description = "Simplify F-Curves by removing closely spaced keyframes";
-
- /* api callbacks */
- //ot->invoke = // XXX we need that number popup for this!
- ot->exec = actkeys_clean_exec;
- ot->poll = ED_operator_action_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_float(ot->srna, "threshold", 0.001f, 0.0f, FLT_MAX, "Threshold", "", 0.0f, 1000.0f);
- RNA_def_boolean(ot->srna, "channels", false, "Channels", "");
+ /* identifiers */
+ ot->name = "Clean Keyframes";
+ ot->idname = "ACTION_OT_clean";
+ ot->description = "Simplify F-Curves by removing closely spaced keyframes";
+
+ /* api callbacks */
+ //ot->invoke = // XXX we need that number popup for this!
+ ot->exec = actkeys_clean_exec;
+ ot->poll = ED_operator_action_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_float(
+ ot->srna, "threshold", 0.001f, 0.0f, FLT_MAX, "Threshold", "", 0.0f, 1000.0f);
+ RNA_def_boolean(ot->srna, "channels", false, "Channels", "");
}
/* ******************** Sample Keyframes Operator *********************** */
@@ -1057,62 +1089,63 @@ void ACTION_OT_clean(wmOperatorType *ot)
/* Evaluates the curves between each selected keyframe on each frame, and keys the value */
static void sample_action_keys(bAnimContext *ac)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- /* 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);
+ /* 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 filtered data and add keys between selected keyframes on every frame */
- for (ale = anim_data.first; ale; ale = ale->next) {
- sample_fcurve((FCurve *)ale->key_data);
+ /* loop through filtered data and add keys between selected keyframes on every frame */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ sample_fcurve((FCurve *)ale->key_data);
- ale->update |= ANIM_UPDATE_DEPS;
- }
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int actkeys_sample_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
+ bAnimContext ac;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
- BKE_report(op->reports, RPT_ERROR, "Not implemented");
- return OPERATOR_PASS_THROUGH;
- }
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented");
+ return OPERATOR_PASS_THROUGH;
+ }
- /* sample keyframes */
- sample_action_keys(&ac);
+ /* sample keyframes */
+ sample_action_keys(&ac);
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_sample(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Sample Keyframes";
- ot->idname = "ACTION_OT_sample";
- ot->description = "Add keyframes on every frame between the selected keyframes";
+ /* identifiers */
+ ot->name = "Sample Keyframes";
+ ot->idname = "ACTION_OT_sample";
+ ot->description = "Add keyframes on every frame between the selected keyframes";
- /* api callbacks */
- ot->exec = actkeys_sample_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->exec = actkeys_sample_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ************************************************************************** */
@@ -1121,114 +1154,131 @@ void ACTION_OT_sample(wmOperatorType *ot)
/* ******************** Set Extrapolation-Type Operator *********************** */
/* defines for make/clear cyclic extrapolation tools */
-#define MAKE_CYCLIC_EXPO -1
-#define CLEAR_CYCLIC_EXPO -2
+#define MAKE_CYCLIC_EXPO -1
+#define CLEAR_CYCLIC_EXPO -2
/* defines for set extrapolation-type for selected keyframes tool */
static const EnumPropertyItem prop_actkeys_expo_types[] = {
- {FCURVE_EXTRAPOLATE_CONSTANT, "CONSTANT", 0, "Constant Extrapolation", "Values on endpoint keyframes are held"},
- {FCURVE_EXTRAPOLATE_LINEAR, "LINEAR", 0, "Linear Extrapolation", "Straight-line slope of end segments are extended past the endpoint keyframes"},
-
- {MAKE_CYCLIC_EXPO, "MAKE_CYCLIC", 0, "Make Cyclic (F-Modifier)", "Add Cycles F-Modifier if one doesn't exist already"},
- {CLEAR_CYCLIC_EXPO, "CLEAR_CYCLIC", 0, "Clear Cyclic (F-Modifier)", "Remove Cycles F-Modifier if not needed anymore"},
- {0, NULL, 0, NULL, NULL},
+ {FCURVE_EXTRAPOLATE_CONSTANT,
+ "CONSTANT",
+ 0,
+ "Constant Extrapolation",
+ "Values on endpoint keyframes are held"},
+ {FCURVE_EXTRAPOLATE_LINEAR,
+ "LINEAR",
+ 0,
+ "Linear Extrapolation",
+ "Straight-line slope of end segments are extended past the endpoint keyframes"},
+
+ {MAKE_CYCLIC_EXPO,
+ "MAKE_CYCLIC",
+ 0,
+ "Make Cyclic (F-Modifier)",
+ "Add Cycles F-Modifier if one doesn't exist already"},
+ {CLEAR_CYCLIC_EXPO,
+ "CLEAR_CYCLIC",
+ 0,
+ "Clear Cyclic (F-Modifier)",
+ "Remove Cycles F-Modifier if not needed anymore"},
+ {0, NULL, 0, NULL, NULL},
};
/* this function is responsible for setting extrapolation mode for keyframes */
static void setexpo_action_keys(bAnimContext *ac, short mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* loop through setting mode per F-Curve */
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->data;
-
- if (mode >= 0) {
- /* just set mode setting */
- fcu->extend = mode;
- }
- else {
- /* shortcuts for managing Cycles F-Modifiers to make it easier to toggle cyclic animation
- * without having to go through FModifier UI in Graph Editor to do so
- */
- if (mode == MAKE_CYCLIC_EXPO) {
- /* only add if one doesn't exist */
- if (list_has_suitable_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, -1) == 0) {
- /* TODO: add some more preset versions which set different extrapolation options? */
- add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, fcu);
- }
- }
- else if (mode == CLEAR_CYCLIC_EXPO) {
- /* remove all the modifiers fitting this description */
- FModifier *fcm, *fcn = NULL;
-
- for (fcm = fcu->modifiers.first; fcm; fcm = fcn) {
- fcn = fcm->next;
-
- if (fcm->type == FMODIFIER_TYPE_CYCLES)
- remove_fmodifier(&fcu->modifiers, fcm);
- }
- }
- }
-
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_SEL /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through setting mode per F-Curve */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->data;
+
+ if (mode >= 0) {
+ /* just set mode setting */
+ fcu->extend = mode;
+ }
+ else {
+ /* shortcuts for managing Cycles F-Modifiers to make it easier to toggle cyclic animation
+ * without having to go through FModifier UI in Graph Editor to do so
+ */
+ if (mode == MAKE_CYCLIC_EXPO) {
+ /* only add if one doesn't exist */
+ if (list_has_suitable_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, -1) == 0) {
+ /* TODO: add some more preset versions which set different extrapolation options? */
+ add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, fcu);
+ }
+ }
+ else if (mode == CLEAR_CYCLIC_EXPO) {
+ /* remove all the modifiers fitting this description */
+ FModifier *fcm, *fcn = NULL;
+
+ for (fcm = fcu->modifiers.first; fcm; fcm = fcn) {
+ fcn = fcm->next;
+
+ if (fcm->type == FMODIFIER_TYPE_CYCLES)
+ remove_fmodifier(&fcu->modifiers, fcm);
+ }
+ }
+ }
+
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int actkeys_expo_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- short mode;
+ bAnimContext ac;
+ short mode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
- BKE_report(op->reports, RPT_ERROR, "Not implemented");
- return OPERATOR_PASS_THROUGH;
- }
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented");
+ return OPERATOR_PASS_THROUGH;
+ }
- /* get handle setting mode */
- mode = RNA_enum_get(op->ptr, "type");
+ /* get handle setting mode */
+ mode = RNA_enum_get(op->ptr, "type");
- /* set handle type */
- setexpo_action_keys(&ac, mode);
+ /* set handle type */
+ setexpo_action_keys(&ac, mode);
- /* set notifier that keyframe properties have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
+ /* set notifier that keyframe properties have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_extrapolation_type(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Keyframe Extrapolation";
- ot->idname = "ACTION_OT_extrapolation_type";
- ot->description = "Set extrapolation mode for selected F-Curves";
+ /* identifiers */
+ ot->name = "Set Keyframe Extrapolation";
+ ot->idname = "ACTION_OT_extrapolation_type";
+ ot->description = "Set extrapolation mode for selected F-Curves";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = actkeys_expo_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = actkeys_expo_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* id-props */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_expo_types, 0, "Type", "");
+ /* id-props */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_expo_types, 0, "Type", "");
}
/* ******************** Set Interpolation-Type Operator *********************** */
@@ -1236,73 +1286,76 @@ void ACTION_OT_extrapolation_type(wmOperatorType *ot)
/* 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);
+ 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;
- short mode;
+ bAnimContext ac;
+ short mode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
- BKE_report(op->reports, RPT_ERROR, "Not implemented");
- return OPERATOR_PASS_THROUGH;
- }
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented");
+ return OPERATOR_PASS_THROUGH;
+ }
- /* get handle setting mode */
- mode = RNA_enum_get(op->ptr, "type");
+ /* get handle setting mode */
+ mode = RNA_enum_get(op->ptr, "type");
- /* set handle type */
- setipo_action_keys(&ac, mode);
+ /* set handle type */
+ setipo_action_keys(&ac, mode);
- /* set notifier that keyframe properties have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
+ /* set notifier that keyframe properties have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_interpolation_type(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Keyframe Interpolation";
- ot->idname = "ACTION_OT_interpolation_type";
- ot->description = "Set interpolation mode for the F-Curve segments starting from the selected keyframes";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = actkeys_ipo_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_mode_items, 0, "Type", "");
+ /* identifiers */
+ ot->name = "Set Keyframe Interpolation";
+ ot->idname = "ACTION_OT_interpolation_type";
+ ot->description =
+ "Set interpolation mode for the F-Curve segments starting from the selected keyframes";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = actkeys_ipo_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_mode_items, 0, "Type", "");
}
/* ******************** Set Handle-Type Operator *********************** */
@@ -1310,81 +1363,82 @@ void ACTION_OT_interpolation_type(wmOperatorType *ot)
/* this function is responsible for setting handle-type of selected keyframes */
static void sethandles_action_keys(bAnimContext *ac, short mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- KeyframeEditFunc edit_cb = ANIM_editkeyframes_handles(mode);
- KeyframeEditFunc sel_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
-
- /* 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 flags for handles
- * 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) {
- FCurve *fcu = (FCurve *)ale->key_data;
-
- /* any selected keyframes for editing? */
- if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL)) {
- /* change type of selected handles */
- ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, edit_cb, calchandles_fcurve);
-
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
- }
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ KeyframeEditFunc edit_cb = ANIM_editkeyframes_handles(mode);
+ KeyframeEditFunc sel_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
+
+ /* 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 flags for handles
+ * 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) {
+ FCurve *fcu = (FCurve *)ale->key_data;
+
+ /* any selected keyframes for editing? */
+ if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL)) {
+ /* change type of selected handles */
+ ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, edit_cb, calchandles_fcurve);
+
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int actkeys_handletype_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- short mode;
+ bAnimContext ac;
+ short mode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
- BKE_report(op->reports, RPT_ERROR, "Not implemented");
- return OPERATOR_PASS_THROUGH;
- }
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented");
+ return OPERATOR_PASS_THROUGH;
+ }
- /* get handle setting mode */
- mode = RNA_enum_get(op->ptr, "type");
+ /* get handle setting mode */
+ mode = RNA_enum_get(op->ptr, "type");
- /* set handle type */
- sethandles_action_keys(&ac, mode);
+ /* set handle type */
+ sethandles_action_keys(&ac, mode);
- /* set notifier that keyframe properties have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
+ /* set notifier that keyframe properties have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_handle_type(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Keyframe Handle Type";
- ot->idname = "ACTION_OT_handle_type";
- ot->description = "Set type of handle for selected keyframes";
+ /* identifiers */
+ ot->name = "Set Keyframe Handle Type";
+ ot->idname = "ACTION_OT_handle_type";
+ ot->description = "Set type of handle for selected keyframes";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = actkeys_handletype_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = actkeys_handletype_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* id-props */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_keyframe_handle_type_items, 0, "Type", "");
+ /* id-props */
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_keyframe_handle_type_items, 0, "Type", "");
}
/* ******************** Set Keyframe-Type Operator *********************** */
@@ -1392,101 +1446,103 @@ void ACTION_OT_handle_type(wmOperatorType *ot)
/* this function is responsible for setting keyframe type for keyframes */
static void setkeytype_action_keys(bAnimContext *ac, short mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- KeyframeEditFunc set_cb = ANIM_editkeyframes_keytype(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, NULL);
-
- ale->update |= ANIM_UPDATE_DEPS | ANIM_UPDATE_HANDLES;
- }
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ KeyframeEditFunc set_cb = ANIM_editkeyframes_keytype(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, NULL);
+
+ ale->update |= ANIM_UPDATE_DEPS | ANIM_UPDATE_HANDLES;
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* this function is responsible for setting the keyframe type for Grease Pencil frames */
static void setkeytype_gpencil_keys(bAnimContext *ac, short mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* loop through each layer */
- for (ale = anim_data.first; ale; ale = ale->next) {
- if (ale->type == ANIMTYPE_GPLAYER) {
- ED_gplayer_frames_keytype_set(ale->data, mode);
- ale->update |= ANIM_UPDATE_DEPS;
- }
- }
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through each layer */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ ED_gplayer_frames_keytype_set(ale->data, mode);
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int actkeys_keytype_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- short mode;
+ bAnimContext ac;
+ short mode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- if (ac.datatype == ANIMCONT_MASK) {
- BKE_report(op->reports, RPT_ERROR, "Not implemented for Masks");
- return OPERATOR_PASS_THROUGH;
- }
+ if (ac.datatype == ANIMCONT_MASK) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented for Masks");
+ return OPERATOR_PASS_THROUGH;
+ }
- /* get handle setting mode */
- mode = RNA_enum_get(op->ptr, "type");
+ /* get handle setting mode */
+ mode = RNA_enum_get(op->ptr, "type");
- /* set handle type */
- if (ac.datatype == ANIMCONT_GPENCIL) {
- setkeytype_gpencil_keys(&ac, mode);
- }
- else {
- setkeytype_action_keys(&ac, mode);
- }
+ /* set handle type */
+ if (ac.datatype == ANIMCONT_GPENCIL) {
+ setkeytype_gpencil_keys(&ac, mode);
+ }
+ else {
+ setkeytype_action_keys(&ac, mode);
+ }
- /* set notifier that keyframe properties have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
+ /* set notifier that keyframe properties have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_keyframe_type(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Keyframe Type";
- ot->idname = "ACTION_OT_keyframe_type";
- ot->description = "Set type of keyframe for the selected keyframes";
+ /* identifiers */
+ ot->name = "Set Keyframe Type";
+ ot->idname = "ACTION_OT_keyframe_type";
+ ot->description = "Set type of keyframe for the selected keyframes";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = actkeys_keytype_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = actkeys_keytype_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* id-props */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_beztriple_keyframe_type_items, 0, "Type", "");
+ /* id-props */
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_beztriple_keyframe_type_items, 0, "Type", "");
}
/* ************************************************************************** */
@@ -1496,297 +1552,323 @@ void ACTION_OT_keyframe_type(wmOperatorType *ot)
static bool actkeys_framejump_poll(bContext *C)
{
- /* prevent changes during render */
- if (G.is_rendering)
- return 0;
+ /* prevent changes during render */
+ if (G.is_rendering)
+ return 0;
- return ED_operator_action_active(C);
+ return ED_operator_action_active(C);
}
/* snap current-frame indicator to 'average time' of selected keyframe */
static int actkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- KeyframeEditData ked = {{NULL}};
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* init edit data */
- /* loop over action data, averaging values */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
- if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_calc_average, NULL);
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
- }
- else
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_calc_average, NULL);
- }
-
- ANIM_animdata_freelist(&anim_data);
-
- /* set the new current frame value, based on the average time */
- if (ked.i1) {
- Scene *scene = ac.scene;
- CFRA = round_fl_to_int(ked.f1 / ked.i1);
- SUBFRA = 0.f;
- }
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ KeyframeEditData ked = {{NULL}};
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* init edit data */
+ /* loop over action data, averaging values */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_calc_average, NULL);
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
+ }
+ else
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_calc_average, NULL);
+ }
+
+ ANIM_animdata_freelist(&anim_data);
+
+ /* set the new current frame value, based on the average time */
+ if (ked.i1) {
+ Scene *scene = ac.scene;
+ CFRA = round_fl_to_int(ked.f1 / ked.i1);
+ SUBFRA = 0.f;
+ }
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene);
+
+ return OPERATOR_FINISHED;
}
void ACTION_OT_frame_jump(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Jump to Keyframes";
- ot->idname = "ACTION_OT_frame_jump";
- ot->description = "Set the current frame to the average frame value of selected keyframes";
+ /* identifiers */
+ ot->name = "Jump to Keyframes";
+ ot->idname = "ACTION_OT_frame_jump";
+ ot->description = "Set the current frame to the average frame value of selected keyframes";
- /* api callbacks */
- ot->exec = actkeys_framejump_exec;
- ot->poll = actkeys_framejump_poll;
+ /* api callbacks */
+ ot->exec = actkeys_framejump_exec;
+ ot->poll = actkeys_framejump_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Snap Keyframes Operator *********************** */
/* defines for snap keyframes tool */
static const EnumPropertyItem prop_actkeys_snap_types[] = {
- {ACTKEYS_SNAP_CFRA, "CFRA", 0, "Current frame",
- "Snap selected keyframes to the current frame"},
- {ACTKEYS_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame",
- "Snap selected keyframes to the nearest (whole) frame (use to fix accidental sub-frame offsets)"},
- {ACTKEYS_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Nearest Second",
- "Snap selected keyframes to the nearest second"},
- {ACTKEYS_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker",
- "Snap selected keyframes to the nearest marker"},
- {0, NULL, 0, NULL, NULL},
+ {ACTKEYS_SNAP_CFRA,
+ "CFRA",
+ 0,
+ "Current frame",
+ "Snap selected keyframes to the current frame"},
+ {ACTKEYS_SNAP_NEAREST_FRAME,
+ "NEAREST_FRAME",
+ 0,
+ "Nearest Frame",
+ "Snap selected keyframes to the nearest (whole) frame (use to fix accidental sub-frame "
+ "offsets)"},
+ {ACTKEYS_SNAP_NEAREST_SECOND,
+ "NEAREST_SECOND",
+ 0,
+ "Nearest Second",
+ "Snap selected keyframes to the nearest second"},
+ {ACTKEYS_SNAP_NEAREST_MARKER,
+ "NEAREST_MARKER",
+ 0,
+ "Nearest Marker",
+ "Snap selected keyframes to the nearest marker"},
+ {0, NULL, 0, NULL, NULL},
};
/* this function is responsible for snapping keyframes to frame-times */
static void snap_action_keys(bAnimContext *ac, short mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- KeyframeEditData ked = {{NULL}};
- KeyframeEditFunc edit_cb;
-
- /* filter data */
- if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- }
- else {
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
- }
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* get beztriple editing callbacks */
- edit_cb = ANIM_editkeyframes_snap(mode);
-
- ked.scene = ac->scene;
- if (mode == ACTKEYS_SNAP_NEAREST_MARKER) {
- ked.list.first = (ac->markers) ? ac->markers->first : NULL;
- ked.list.last = (ac->markers) ? ac->markers->last : NULL;
- }
-
- /* snap keyframes */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-
- if (ale->type == ANIMTYPE_GPLAYER) {
- ED_gplayer_snap_frames(ale->data, ac->scene, mode);
- }
- else if (ale->type == ANIMTYPE_MASKLAYER) {
- ED_masklayer_snap_frames(ale->data, ac->scene, mode);
- }
- else if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
- }
- else {
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
- }
-
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ KeyframeEditData ked = {{NULL}};
+ KeyframeEditFunc edit_cb;
+
+ /* filter data */
+ if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ }
+ else {
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
+ ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+ }
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* get beztriple editing callbacks */
+ edit_cb = ANIM_editkeyframes_snap(mode);
+
+ ked.scene = ac->scene;
+ if (mode == ACTKEYS_SNAP_NEAREST_MARKER) {
+ ked.list.first = (ac->markers) ? ac->markers->first : NULL;
+ ked.list.last = (ac->markers) ? ac->markers->last : NULL;
+ }
+
+ /* snap keyframes */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ ED_gplayer_snap_frames(ale->data, ac->scene, mode);
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ ED_masklayer_snap_frames(ale->data, ac->scene, mode);
+ }
+ else if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
+ }
+ else {
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+ }
+
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int actkeys_snap_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- short mode;
+ bAnimContext ac;
+ short mode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* get snapping mode */
- mode = RNA_enum_get(op->ptr, "type");
+ /* get snapping mode */
+ mode = RNA_enum_get(op->ptr, "type");
- /* snap keyframes */
- snap_action_keys(&ac, mode);
+ /* snap keyframes */
+ snap_action_keys(&ac, mode);
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_snap(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Snap Keys";
- ot->idname = "ACTION_OT_snap";
- ot->description = "Snap selected keyframes to the times specified";
+ /* identifiers */
+ ot->name = "Snap Keys";
+ ot->idname = "ACTION_OT_snap";
+ ot->description = "Snap selected keyframes to the times specified";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = actkeys_snap_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = actkeys_snap_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* id-props */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_snap_types, 0, "Type", "");
+ /* id-props */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_snap_types, 0, "Type", "");
}
/* ******************** Mirror Keyframes Operator *********************** */
/* defines for mirror keyframes tool */
static const EnumPropertyItem prop_actkeys_mirror_types[] = {
- {ACTKEYS_MIRROR_CFRA, "CFRA", 0, "By Times over Current frame",
- "Flip times of selected keyframes using the current frame as the mirror line"},
- {ACTKEYS_MIRROR_XAXIS, "XAXIS", 0, "By Values over Value=0",
- "Flip values of selected keyframes (i.e. negative values become positive, and vice versa)"},
- {ACTKEYS_MIRROR_MARKER, "MARKER", 0, "By Times over First Selected Marker",
- "Flip times of selected keyframes using the first selected marker as the reference point"},
- {0, NULL, 0, NULL, NULL},
+ {ACTKEYS_MIRROR_CFRA,
+ "CFRA",
+ 0,
+ "By Times over Current frame",
+ "Flip times of selected keyframes using the current frame as the mirror line"},
+ {ACTKEYS_MIRROR_XAXIS,
+ "XAXIS",
+ 0,
+ "By Values over Value=0",
+ "Flip values of selected keyframes (i.e. negative values become positive, and vice versa)"},
+ {ACTKEYS_MIRROR_MARKER,
+ "MARKER",
+ 0,
+ "By Times over First Selected Marker",
+ "Flip times of selected keyframes using the first selected marker as the reference point"},
+ {0, NULL, 0, NULL, NULL},
};
/* this function is responsible for mirroring keyframes */
static void mirror_action_keys(bAnimContext *ac, short mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- KeyframeEditData ked = {{NULL}};
- KeyframeEditFunc edit_cb;
-
- /* get beztriple editing callbacks */
- edit_cb = ANIM_editkeyframes_mirror(mode);
-
- ked.scene = ac->scene;
-
- /* for 'first selected marker' mode, need to find first selected marker first! */
- /* XXX should this be made into a helper func in the API? */
- if (mode == ACTKEYS_MIRROR_MARKER) {
- TimeMarker *marker = ED_markers_get_first_selected(ac->markers);
-
- if (marker)
- ked.f1 = (float)marker->frame;
- else
- return;
- }
-
- /* filter data */
- if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- }
- else {
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
- }
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* mirror keyframes */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-
- if (ale->type == ANIMTYPE_GPLAYER) {
- ED_gplayer_mirror_frames(ale->data, ac->scene, mode);
- }
- else if (ale->type == ANIMTYPE_MASKLAYER) {
- /* TODO */
- }
- else if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
- }
- else {
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
- }
-
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ KeyframeEditData ked = {{NULL}};
+ KeyframeEditFunc edit_cb;
+
+ /* get beztriple editing callbacks */
+ edit_cb = ANIM_editkeyframes_mirror(mode);
+
+ ked.scene = ac->scene;
+
+ /* for 'first selected marker' mode, need to find first selected marker first! */
+ /* XXX should this be made into a helper func in the API? */
+ if (mode == ACTKEYS_MIRROR_MARKER) {
+ TimeMarker *marker = ED_markers_get_first_selected(ac->markers);
+
+ if (marker)
+ ked.f1 = (float)marker->frame;
+ else
+ return;
+ }
+
+ /* filter data */
+ if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_NODUPLIS);
+ }
+ else {
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
+ ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+ }
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* mirror keyframes */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ ED_gplayer_mirror_frames(ale->data, ac->scene, mode);
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ /* TODO */
+ }
+ else if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
+ }
+ else {
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+ }
+
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int actkeys_mirror_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- short mode;
+ bAnimContext ac;
+ short mode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* get mirroring mode */
- mode = RNA_enum_get(op->ptr, "type");
+ /* get mirroring mode */
+ mode = RNA_enum_get(op->ptr, "type");
- /* mirror keyframes */
- mirror_action_keys(&ac, mode);
+ /* mirror keyframes */
+ mirror_action_keys(&ac, mode);
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_mirror(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Mirror Keys";
- ot->idname = "ACTION_OT_mirror";
- ot->description = "Flip selected keyframes over the selected mirror line";
+ /* identifiers */
+ ot->name = "Mirror Keys";
+ ot->idname = "ACTION_OT_mirror";
+ ot->description = "Flip selected keyframes over the selected mirror line";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = actkeys_mirror_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = actkeys_mirror_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* id-props */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_mirror_types, 0, "Type", "");
+ /* id-props */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_mirror_types, 0, "Type", "");
}
/* ************************************************************************** */
diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h
index 74da8aafcc8..5d86cf6faec 100644
--- a/source/blender/editors/space_action/action_intern.h
+++ b/source/blender/editors/space_action/action_intern.h
@@ -68,17 +68,17 @@ void ACTION_OT_clickselect(struct wmOperatorType *ot);
/* defines for left-right select tool */
enum eActKeys_LeftRightSelect_Mode {
- ACTKEYS_LRSEL_TEST = 0,
- ACTKEYS_LRSEL_LEFT,
- ACTKEYS_LRSEL_RIGHT,
+ ACTKEYS_LRSEL_TEST = 0,
+ ACTKEYS_LRSEL_LEFT,
+ ACTKEYS_LRSEL_RIGHT,
};
/* defines for column-select mode */
enum eActKeys_ColumnSelect_Mode {
- ACTKEYS_COLUMNSEL_KEYS = 0,
- ACTKEYS_COLUMNSEL_CFRA,
- ACTKEYS_COLUMNSEL_MARKERS_COLUMN,
- ACTKEYS_COLUMNSEL_MARKERS_BETWEEN,
+ ACTKEYS_COLUMNSEL_KEYS = 0,
+ ACTKEYS_COLUMNSEL_CFRA,
+ ACTKEYS_COLUMNSEL_MARKERS_COLUMN,
+ ACTKEYS_COLUMNSEL_MARKERS_BETWEEN,
};
/* ***************************************** */
@@ -124,20 +124,20 @@ void ACTION_OT_markers_make_local(struct wmOperatorType *ot);
* NOTE: keep in sync with eEditKeyframes_Snap (in ED_keyframes_edit.h)
*/
enum eActKeys_Snap_Mode {
- ACTKEYS_SNAP_CFRA = 1,
- ACTKEYS_SNAP_NEAREST_FRAME,
- ACTKEYS_SNAP_NEAREST_SECOND,
- ACTKEYS_SNAP_NEAREST_MARKER,
+ ACTKEYS_SNAP_CFRA = 1,
+ ACTKEYS_SNAP_NEAREST_FRAME,
+ ACTKEYS_SNAP_NEAREST_SECOND,
+ ACTKEYS_SNAP_NEAREST_MARKER,
};
/* defines for mirror keyframes
* NOTE: keep in sync with eEditKeyframes_Mirror (in ED_keyframes_edit.h)
*/
enum eActKeys_Mirror_Mode {
- ACTKEYS_MIRROR_CFRA = 1,
- ACTKEYS_MIRROR_YAXIS,
- ACTKEYS_MIRROR_XAXIS,
- ACTKEYS_MIRROR_MARKER,
+ ACTKEYS_MIRROR_CFRA = 1,
+ ACTKEYS_MIRROR_YAXIS,
+ ACTKEYS_MIRROR_XAXIS,
+ ACTKEYS_MIRROR_MARKER,
};
/* ***************************************** */
diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c
index 87b9ee4e1ef..d5ddf974284 100644
--- a/source/blender/editors/space_action/action_ops.c
+++ b/source/blender/editors/space_action/action_ops.c
@@ -21,14 +21,11 @@
* \ingroup spaction
*/
-
#include <stdlib.h>
#include <math.h>
-
#include "DNA_space_types.h"
-
#include "ED_anim_api.h"
#include "ED_markers.h"
#include "ED_transform.h"
@@ -46,68 +43,69 @@
void action_operatortypes(void)
{
- /* view */
- WM_operatortype_append(ACTION_OT_properties);
-
- /* keyframes */
- /* selection */
- WM_operatortype_append(ACTION_OT_clickselect);
- WM_operatortype_append(ACTION_OT_select_all);
- WM_operatortype_append(ACTION_OT_select_box);
- WM_operatortype_append(ACTION_OT_select_lasso);
- WM_operatortype_append(ACTION_OT_select_circle);
- WM_operatortype_append(ACTION_OT_select_column);
- WM_operatortype_append(ACTION_OT_select_linked);
- WM_operatortype_append(ACTION_OT_select_more);
- WM_operatortype_append(ACTION_OT_select_less);
- WM_operatortype_append(ACTION_OT_select_leftright);
-
- /* editing */
- WM_operatortype_append(ACTION_OT_snap);
- WM_operatortype_append(ACTION_OT_mirror);
- WM_operatortype_append(ACTION_OT_frame_jump);
- 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_keyframe_type);
- WM_operatortype_append(ACTION_OT_sample);
- WM_operatortype_append(ACTION_OT_clean);
- WM_operatortype_append(ACTION_OT_delete);
- WM_operatortype_append(ACTION_OT_duplicate);
- WM_operatortype_append(ACTION_OT_keyframe_insert);
- WM_operatortype_append(ACTION_OT_copy);
- WM_operatortype_append(ACTION_OT_paste);
-
- WM_operatortype_append(ACTION_OT_new);
- WM_operatortype_append(ACTION_OT_unlink);
-
- WM_operatortype_append(ACTION_OT_push_down);
- WM_operatortype_append(ACTION_OT_stash);
- WM_operatortype_append(ACTION_OT_stash_and_create);
-
- WM_operatortype_append(ACTION_OT_layer_next);
- WM_operatortype_append(ACTION_OT_layer_prev);
-
- WM_operatortype_append(ACTION_OT_previewrange_set);
- WM_operatortype_append(ACTION_OT_view_all);
- WM_operatortype_append(ACTION_OT_view_selected);
- WM_operatortype_append(ACTION_OT_view_frame);
-
- WM_operatortype_append(ACTION_OT_markers_make_local);
+ /* view */
+ WM_operatortype_append(ACTION_OT_properties);
+
+ /* keyframes */
+ /* selection */
+ WM_operatortype_append(ACTION_OT_clickselect);
+ WM_operatortype_append(ACTION_OT_select_all);
+ WM_operatortype_append(ACTION_OT_select_box);
+ WM_operatortype_append(ACTION_OT_select_lasso);
+ WM_operatortype_append(ACTION_OT_select_circle);
+ WM_operatortype_append(ACTION_OT_select_column);
+ WM_operatortype_append(ACTION_OT_select_linked);
+ WM_operatortype_append(ACTION_OT_select_more);
+ WM_operatortype_append(ACTION_OT_select_less);
+ WM_operatortype_append(ACTION_OT_select_leftright);
+
+ /* editing */
+ WM_operatortype_append(ACTION_OT_snap);
+ WM_operatortype_append(ACTION_OT_mirror);
+ WM_operatortype_append(ACTION_OT_frame_jump);
+ 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_keyframe_type);
+ WM_operatortype_append(ACTION_OT_sample);
+ WM_operatortype_append(ACTION_OT_clean);
+ WM_operatortype_append(ACTION_OT_delete);
+ WM_operatortype_append(ACTION_OT_duplicate);
+ WM_operatortype_append(ACTION_OT_keyframe_insert);
+ WM_operatortype_append(ACTION_OT_copy);
+ WM_operatortype_append(ACTION_OT_paste);
+
+ WM_operatortype_append(ACTION_OT_new);
+ WM_operatortype_append(ACTION_OT_unlink);
+
+ WM_operatortype_append(ACTION_OT_push_down);
+ WM_operatortype_append(ACTION_OT_stash);
+ WM_operatortype_append(ACTION_OT_stash_and_create);
+
+ WM_operatortype_append(ACTION_OT_layer_next);
+ WM_operatortype_append(ACTION_OT_layer_prev);
+
+ WM_operatortype_append(ACTION_OT_previewrange_set);
+ WM_operatortype_append(ACTION_OT_view_all);
+ WM_operatortype_append(ACTION_OT_view_selected);
+ WM_operatortype_append(ACTION_OT_view_frame);
+
+ WM_operatortype_append(ACTION_OT_markers_make_local);
}
void ED_operatormacros_action(void)
{
- wmOperatorType *ot;
- wmOperatorTypeMacro *otmacro;
-
- ot = WM_operatortype_append_macro("ACTION_OT_duplicate_move", "Duplicate",
- "Make a copy of all selected keyframes and move them",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "ACTION_OT_duplicate");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_transform");
- RNA_enum_set(otmacro->ptr, "mode", TFM_TIME_DUPLICATE);
- RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
+ wmOperatorType *ot;
+ wmOperatorTypeMacro *otmacro;
+
+ ot = WM_operatortype_append_macro("ACTION_OT_duplicate_move",
+ "Duplicate",
+ "Make a copy of all selected keyframes and move them",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "ACTION_OT_duplicate");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_transform");
+ RNA_enum_set(otmacro->ptr, "mode", TFM_TIME_DUPLICATE);
+ RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
}
/* ************************** registration - keymaps **********************************/
@@ -116,15 +114,15 @@ void ED_operatormacros_action(void)
void action_keymap(wmKeyConfig *keyconf)
{
- /* keymap for all regions */
- WM_keymap_ensure(keyconf, "Dopesheet Generic", SPACE_ACTION, 0);
+ /* keymap for all regions */
+ WM_keymap_ensure(keyconf, "Dopesheet Generic", SPACE_ACTION, 0);
- /* channels */
- /* Channels are not directly handled by the Action Editor module, but are inherited from the Animation module.
- * All the relevant operations, keymaps, drawing, etc. can therefore all be found in that module instead, as these
- * are all used for the Graph-Editor too.
- */
+ /* channels */
+ /* Channels are not directly handled by the Action Editor module, but are inherited from the Animation module.
+ * All the relevant operations, keymaps, drawing, etc. can therefore all be found in that module instead, as these
+ * are all used for the Graph-Editor too.
+ */
- /* keyframes */
- WM_keymap_ensure(keyconf, "Dopesheet", SPACE_ACTION, 0);
+ /* keyframes */
+ WM_keymap_ensure(keyconf, "Dopesheet", SPACE_ACTION, 0);
}
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 872f889e8b4..7499458181e 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -20,7 +20,6 @@
* \ingroup spaction
*/
-
#include <math.h>
#include <stdlib.h>
#include <string.h>
@@ -63,7 +62,6 @@
#include "action_intern.h"
-
/* ************************************************************************** */
/* KEYFRAMES STUFF */
@@ -82,125 +80,126 @@
*/
static void deselect_action_keys(bAnimContext *ac, short test, short sel)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- KeyframeEditData ked = {{NULL}};
- KeyframeEditFunc test_cb, sel_cb;
-
- /* determine type-based settings */
- if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
- }
- else {
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
- }
-
- /* filter data */
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* init BezTriple looping data */
- test_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
-
- /* See if we should be selecting or deselecting */
- if (test) {
- for (ale = anim_data.first; ale; ale = ale->next) {
- if (ale->type == ANIMTYPE_GPLAYER) {
- if (ED_gplayer_frame_select_check(ale->data)) {
- sel = SELECT_SUBTRACT;
- break;
- }
- }
- else if (ale->type == ANIMTYPE_MASKLAYER) {
- if (ED_masklayer_frame_select_check(ale->data)) {
- sel = SELECT_SUBTRACT;
- break;
- }
- }
- else {
- if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) {
- sel = SELECT_SUBTRACT;
- break;
- }
- }
- }
- }
-
- /* convert sel to selectmode, and use that to get editor */
- sel_cb = ANIM_editkeyframes_select(sel);
-
- /* Now set the flags */
- for (ale = anim_data.first; ale; ale = ale->next) {
- if (ale->type == ANIMTYPE_GPLAYER) {
- ED_gplayer_frame_select_set(ale->data, sel);
- ale->update |= ANIM_UPDATE_DEPS;
- }
- else if (ale->type == ANIMTYPE_MASKLAYER) {
- ED_masklayer_frame_select_set(ale->data, sel);
- }
- else {
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL);
- }
- }
-
- /* Cleanup */
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ KeyframeEditData ked = {{NULL}};
+ KeyframeEditFunc test_cb, sel_cb;
+
+ /* determine type-based settings */
+ if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
+ }
+ else {
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ |
+ ANIMFILTER_NODUPLIS);
+ }
+
+ /* filter data */
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* init BezTriple looping data */
+ test_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
+
+ /* See if we should be selecting or deselecting */
+ if (test) {
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ if (ED_gplayer_frame_select_check(ale->data)) {
+ sel = SELECT_SUBTRACT;
+ break;
+ }
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ if (ED_masklayer_frame_select_check(ale->data)) {
+ sel = SELECT_SUBTRACT;
+ break;
+ }
+ }
+ else {
+ if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) {
+ sel = SELECT_SUBTRACT;
+ break;
+ }
+ }
+ }
+ }
+
+ /* convert sel to selectmode, and use that to get editor */
+ sel_cb = ANIM_editkeyframes_select(sel);
+
+ /* Now set the flags */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ ED_gplayer_frame_select_set(ale->data, sel);
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ ED_masklayer_frame_select_set(ale->data, sel);
+ }
+ else {
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL);
+ }
+ }
+
+ /* Cleanup */
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int actkeys_deselectall_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* 'standard' behavior - check if selected, then apply relevant selection */
- const int action = RNA_enum_get(op->ptr, "action");
- switch (action) {
- case SEL_TOGGLE:
- deselect_action_keys(&ac, 1, SELECT_ADD);
- break;
- case SEL_SELECT:
- deselect_action_keys(&ac, 0, SELECT_ADD);
- break;
- case SEL_DESELECT:
- deselect_action_keys(&ac, 0, SELECT_SUBTRACT);
- break;
- case SEL_INVERT:
- deselect_action_keys(&ac, 0, SELECT_INVERT);
- break;
- default:
- BLI_assert(0);
- break;
- }
-
- /* set notifier that keyframe selection have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* 'standard' behavior - check if selected, then apply relevant selection */
+ const int action = RNA_enum_get(op->ptr, "action");
+ switch (action) {
+ case SEL_TOGGLE:
+ deselect_action_keys(&ac, 1, SELECT_ADD);
+ break;
+ case SEL_SELECT:
+ deselect_action_keys(&ac, 0, SELECT_ADD);
+ break;
+ case SEL_DESELECT:
+ deselect_action_keys(&ac, 0, SELECT_SUBTRACT);
+ break;
+ case SEL_INVERT:
+ deselect_action_keys(&ac, 0, SELECT_INVERT);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ /* set notifier that keyframe selection have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+
+ return OPERATOR_FINISHED;
}
void ACTION_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select All";
- ot->idname = "ACTION_OT_select_all";
- ot->description = "Toggle selection of all keyframes";
+ /* identifiers */
+ ot->name = "Select All";
+ ot->idname = "ACTION_OT_select_all";
+ ot->description = "Toggle selection of all keyframes";
- /* api callbacks */
- ot->exec = actkeys_deselectall_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->exec = actkeys_deselectall_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_select_all(ot);
+ /* properties */
+ WM_operator_properties_select_all(ot);
}
/* ******************** Box Select Operator **************************** */
@@ -213,190 +212,183 @@ void ACTION_OT_select_all(wmOperatorType *ot)
/* defines for box_select mode */
enum {
- ACTKEYS_BORDERSEL_ALLKEYS = 0,
- ACTKEYS_BORDERSEL_FRAMERANGE,
- ACTKEYS_BORDERSEL_CHANNELS,
+ ACTKEYS_BORDERSEL_ALLKEYS = 0,
+ ACTKEYS_BORDERSEL_FRAMERANGE,
+ ACTKEYS_BORDERSEL_CHANNELS,
} /*eActKeys_BoxSelect_Mode*/;
-
static void box_select_action(bAnimContext *ac, const rcti rect, short mode, short selectmode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- KeyframeEditData ked;
- KeyframeEditFunc ok_cb, select_cb;
- View2D *v2d = &ac->ar->v2d;
- rctf rectf;
- float ymin = 0, ymax = (float)(-ACHANNEL_HEIGHT_HALF(ac));
-
- /* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
- UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin + 2, &rectf.xmin, &rectf.ymin);
- UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax - 2, &rectf.xmax, &rectf.ymax);
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* get beztriple editing/validation funcs */
- select_cb = ANIM_editkeyframes_select(selectmode);
-
- if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS))
- ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
- else
- ok_cb = NULL;
-
- /* init editing data */
- memset(&ked, 0, sizeof(KeyframeEditData));
-
- /* loop over data, doing box select */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-
- /* get new vertical minimum extent of channel */
- ymin = ymax - ACHANNEL_STEP(ac);
-
- /* set horizontal range (if applicable) */
- if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) {
- /* if channel is mapped in NLA, apply correction */
- if (adt) {
- ked.iterflags &= ~(KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP);
- ked.f1 = BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
- ked.f2 = BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
- }
- else {
- ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */
- ked.f1 = rectf.xmin;
- ked.f2 = rectf.xmax;
- }
- }
-
- /* perform vertical suitability check (if applicable) */
- if ((mode == ACTKEYS_BORDERSEL_FRAMERANGE) ||
- !((ymax < rectf.ymin) || (ymin > rectf.ymax)))
- {
- /* loop over data selecting */
- switch (ale->type) {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ KeyframeEditData ked;
+ KeyframeEditFunc ok_cb, select_cb;
+ View2D *v2d = &ac->ar->v2d;
+ rctf rectf;
+ float ymin = 0, ymax = (float)(-ACHANNEL_HEIGHT_HALF(ac));
+
+ /* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
+ UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin + 2, &rectf.xmin, &rectf.ymin);
+ UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax - 2, &rectf.xmax, &rectf.ymax);
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* get beztriple editing/validation funcs */
+ select_cb = ANIM_editkeyframes_select(selectmode);
+
+ if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS))
+ ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
+ else
+ ok_cb = NULL;
+
+ /* init editing data */
+ memset(&ked, 0, sizeof(KeyframeEditData));
+
+ /* loop over data, doing box select */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ /* get new vertical minimum extent of channel */
+ ymin = ymax - ACHANNEL_STEP(ac);
+
+ /* set horizontal range (if applicable) */
+ if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) {
+ /* if channel is mapped in NLA, apply correction */
+ if (adt) {
+ ked.iterflags &= ~(KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP);
+ ked.f1 = BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
+ ked.f2 = BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
+ }
+ else {
+ ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */
+ ked.f1 = rectf.xmin;
+ ked.f2 = rectf.xmax;
+ }
+ }
+
+ /* perform vertical suitability check (if applicable) */
+ if ((mode == ACTKEYS_BORDERSEL_FRAMERANGE) || !((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
+ /* loop over data selecting */
+ switch (ale->type) {
#if 0 /* XXX: Keyframes are not currently shown here */
- case ANIMTYPE_GPDATABLOCK:
- {
- bGPdata *gpd = ale->data;
- bGPDlayer *gpl;
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- ED_gplayer_frames_select_box(gpl, rectf.xmin, rectf.xmax, selectmode);
- }
- ale->update |= ANIM_UPDATE_DEPS;
- break;
- }
+ case ANIMTYPE_GPDATABLOCK:
+ {
+ bGPdata *gpd = ale->data;
+ bGPDlayer *gpl;
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ ED_gplayer_frames_select_box(gpl, rectf.xmin, rectf.xmax, selectmode);
+ }
+ ale->update |= ANIM_UPDATE_DEPS;
+ break;
+ }
#endif
- case ANIMTYPE_GPLAYER:
- {
- ED_gplayer_frames_select_box(ale->data, rectf.xmin, rectf.xmax, selectmode);
- ale->update |= ANIM_UPDATE_DEPS;
- break;
- }
- case ANIMTYPE_MASKDATABLOCK:
- {
- Mask *mask = ale->data;
- MaskLayer *masklay;
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- ED_masklayer_frames_select_box(masklay, rectf.xmin, rectf.xmax, selectmode);
- }
- break;
- }
- case ANIMTYPE_MASKLAYER:
- {
- ED_masklayer_frames_select_box(ale->data, rectf.xmin, rectf.xmax, selectmode);
- break;
- }
- default:
- {
- ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
- break;
- }
- }
- }
-
- /* set minimum extent to be the maximum of the next channel */
- ymax = ymin;
- }
-
- /* cleanup */
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ case ANIMTYPE_GPLAYER: {
+ ED_gplayer_frames_select_box(ale->data, rectf.xmin, rectf.xmax, selectmode);
+ ale->update |= ANIM_UPDATE_DEPS;
+ break;
+ }
+ case ANIMTYPE_MASKDATABLOCK: {
+ Mask *mask = ale->data;
+ MaskLayer *masklay;
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ ED_masklayer_frames_select_box(masklay, rectf.xmin, rectf.xmax, selectmode);
+ }
+ break;
+ }
+ case ANIMTYPE_MASKLAYER: {
+ ED_masklayer_frames_select_box(ale->data, rectf.xmin, rectf.xmax, selectmode);
+ break;
+ }
+ default: {
+ ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
+ break;
+ }
+ }
+ }
+
+ /* set minimum extent to be the maximum of the next channel */
+ ymax = ymin;
+ }
+
+ /* cleanup */
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int actkeys_box_select_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- rcti rect;
- short mode = 0;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0) {
- return OPERATOR_CANCELLED;
- }
-
- const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
- const int selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- deselect_action_keys(&ac, 1, SELECT_SUBTRACT);
- }
-
- /* get settings from operator */
- WM_operator_properties_border_to_rcti(op, &rect);
-
- /* selection 'mode' depends on whether box_select region only matters on one axis */
- if (RNA_boolean_get(op->ptr, "axis_range")) {
- /* mode depends on which axis of the range is larger to determine which axis to use
- * - checking this in region-space is fine, as it's fundamentally still going to be a different rect size
- * - the frame-range select option is favored over the channel one (x over y), as frame-range one is often
- * used for tweaking timing when "blocking", while channels is not that useful...
- */
- if (BLI_rcti_size_x(&rect) >= BLI_rcti_size_y(&rect))
- mode = ACTKEYS_BORDERSEL_FRAMERANGE;
- else
- mode = ACTKEYS_BORDERSEL_CHANNELS;
- }
- else
- mode = ACTKEYS_BORDERSEL_ALLKEYS;
-
- /* apply box_select action */
- box_select_action(&ac, rect, mode, selectmode);
-
- /* set notifier that keyframe selection have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ rcti rect;
+ short mode = 0;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
+ const int selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ deselect_action_keys(&ac, 1, SELECT_SUBTRACT);
+ }
+
+ /* get settings from operator */
+ WM_operator_properties_border_to_rcti(op, &rect);
+
+ /* selection 'mode' depends on whether box_select region only matters on one axis */
+ if (RNA_boolean_get(op->ptr, "axis_range")) {
+ /* mode depends on which axis of the range is larger to determine which axis to use
+ * - checking this in region-space is fine, as it's fundamentally still going to be a different rect size
+ * - the frame-range select option is favored over the channel one (x over y), as frame-range one is often
+ * used for tweaking timing when "blocking", while channels is not that useful...
+ */
+ if (BLI_rcti_size_x(&rect) >= BLI_rcti_size_y(&rect))
+ mode = ACTKEYS_BORDERSEL_FRAMERANGE;
+ else
+ mode = ACTKEYS_BORDERSEL_CHANNELS;
+ }
+ else
+ mode = ACTKEYS_BORDERSEL_ALLKEYS;
+
+ /* apply box_select action */
+ box_select_action(&ac, rect, mode, selectmode);
+
+ /* set notifier that keyframe selection have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+
+ return OPERATOR_FINISHED;
}
void ACTION_OT_select_box(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Box Select";
- ot->idname = "ACTION_OT_select_box";
- ot->description = "Select all keyframes within the specified region";
+ /* identifiers */
+ ot->name = "Box Select";
+ ot->idname = "ACTION_OT_select_box";
+ ot->description = "Select all keyframes within the specified region";
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = actkeys_box_select_exec;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = actkeys_box_select_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
- ot->poll = ED_operator_action_active;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* rna */
- ot->prop = RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
+ /* rna */
+ ot->prop = RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
- /* properties */
- WM_operator_properties_gesture_box(ot);
- WM_operator_properties_select_operation_simple(ot);
+ /* properties */
+ WM_operator_properties_gesture_box(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
/* ******************** Region Select Operators ***************************** */
@@ -405,256 +397,252 @@ void ACTION_OT_select_box(wmOperatorType *ot)
* original Graph Editor implementation of these to do it this way.
*/
-static void region_select_action_keys(bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, void *data)
+static void region_select_action_keys(
+ bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, void *data)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- KeyframeEditData ked;
- KeyframeEditFunc ok_cb, select_cb;
- View2D *v2d = &ac->ar->v2d;
- rctf rectf, scaled_rectf;
- float ymin = 0, ymax = (float)(-ACHANNEL_HEIGHT_HALF(ac));
-
- /* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
- UI_view2d_region_to_view_rctf(v2d, rectf_view, &rectf);
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* get beztriple editing/validation funcs */
- select_cb = ANIM_editkeyframes_select(selectmode);
- ok_cb = ANIM_editkeyframes_ok(mode);
-
- /* init editing data */
- memset(&ked, 0, sizeof(KeyframeEditData));
- if (mode == BEZT_OK_CHANNEL_LASSO) {
- KeyframeEdit_LassoData *data_lasso = data;
- data_lasso->rectf_scaled = &scaled_rectf;
- ked.data = data_lasso;
- }
- else if (mode == BEZT_OK_CHANNEL_CIRCLE) {
- KeyframeEdit_CircleData *data_circle = data;
- data_circle->rectf_scaled = &scaled_rectf;
- ked.data = data;
- }
- else {
- ked.data = &scaled_rectf;
- }
-
- /* loop over data, doing region select */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-
- /* get new vertical minimum extent of channel */
- ymin = ymax - ACHANNEL_STEP(ac);
-
- /* compute midpoint of channel (used for testing if the key is in the region or not) */
- ked.channel_y = ymin + ACHANNEL_HEIGHT_HALF(ac);
-
- /* if channel is mapped in NLA, apply correction
- * - Apply to the bounds being checked, not all the keyframe points,
- * to avoid having scaling everything
- * - Save result to the scaled_rect, which is all that these operators
- * will read from
- */
- if (adt) {
- ked.iterflags &= ~(KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP);
- ked.f1 = BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
- ked.f2 = BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
- }
- else {
- ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */
- ked.f1 = rectf.xmin;
- ked.f2 = rectf.xmax;
- }
-
- /* Update values for scaled_rectf - which is used to compute the mapping in the callbacks
- * NOTE: Since summary tracks need late-binding remapping, the callbacks may overwrite these
- * with the properly remapped ked.f1/f2 values, when needed
- */
- scaled_rectf.xmin = ked.f1;
- scaled_rectf.xmax = ked.f2;
- scaled_rectf.ymin = ymin;
- scaled_rectf.ymax = ymax;
-
- /* perform vertical suitability check (if applicable) */
- if ((mode == ACTKEYS_BORDERSEL_FRAMERANGE) ||
- !((ymax < rectf.ymin) || (ymin > rectf.ymax)))
- {
- /* loop over data selecting */
- switch (ale->type) {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ KeyframeEditData ked;
+ KeyframeEditFunc ok_cb, select_cb;
+ View2D *v2d = &ac->ar->v2d;
+ rctf rectf, scaled_rectf;
+ float ymin = 0, ymax = (float)(-ACHANNEL_HEIGHT_HALF(ac));
+
+ /* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
+ UI_view2d_region_to_view_rctf(v2d, rectf_view, &rectf);
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* get beztriple editing/validation funcs */
+ select_cb = ANIM_editkeyframes_select(selectmode);
+ ok_cb = ANIM_editkeyframes_ok(mode);
+
+ /* init editing data */
+ memset(&ked, 0, sizeof(KeyframeEditData));
+ if (mode == BEZT_OK_CHANNEL_LASSO) {
+ KeyframeEdit_LassoData *data_lasso = data;
+ data_lasso->rectf_scaled = &scaled_rectf;
+ ked.data = data_lasso;
+ }
+ else if (mode == BEZT_OK_CHANNEL_CIRCLE) {
+ KeyframeEdit_CircleData *data_circle = data;
+ data_circle->rectf_scaled = &scaled_rectf;
+ ked.data = data;
+ }
+ else {
+ ked.data = &scaled_rectf;
+ }
+
+ /* loop over data, doing region select */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ /* get new vertical minimum extent of channel */
+ ymin = ymax - ACHANNEL_STEP(ac);
+
+ /* compute midpoint of channel (used for testing if the key is in the region or not) */
+ ked.channel_y = ymin + ACHANNEL_HEIGHT_HALF(ac);
+
+ /* if channel is mapped in NLA, apply correction
+ * - Apply to the bounds being checked, not all the keyframe points,
+ * to avoid having scaling everything
+ * - Save result to the scaled_rect, which is all that these operators
+ * will read from
+ */
+ if (adt) {
+ ked.iterflags &= ~(KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP);
+ ked.f1 = BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
+ ked.f2 = BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
+ }
+ else {
+ ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */
+ ked.f1 = rectf.xmin;
+ ked.f2 = rectf.xmax;
+ }
+
+ /* Update values for scaled_rectf - which is used to compute the mapping in the callbacks
+ * NOTE: Since summary tracks need late-binding remapping, the callbacks may overwrite these
+ * with the properly remapped ked.f1/f2 values, when needed
+ */
+ scaled_rectf.xmin = ked.f1;
+ scaled_rectf.xmax = ked.f2;
+ scaled_rectf.ymin = ymin;
+ scaled_rectf.ymax = ymax;
+
+ /* perform vertical suitability check (if applicable) */
+ if ((mode == ACTKEYS_BORDERSEL_FRAMERANGE) || !((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
+ /* loop over data selecting */
+ switch (ale->type) {
#if 0 /* XXX: Keyframes are not currently shown here */
- case ANIMTYPE_GPDATABLOCK:
- {
- bGPdata *gpd = ale->data;
- bGPDlayer *gpl;
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- ED_gplayer_frames_select_region(&ked, ale->data, mode, selectmode);
- }
- break;
- }
+ case ANIMTYPE_GPDATABLOCK:
+ {
+ bGPdata *gpd = ale->data;
+ bGPDlayer *gpl;
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ ED_gplayer_frames_select_region(&ked, ale->data, mode, selectmode);
+ }
+ break;
+ }
#endif
- case ANIMTYPE_GPLAYER:
- {
- ED_gplayer_frames_select_region(&ked, ale->data, mode, selectmode);
- ale->update |= ANIM_UPDATE_DEPS;
- break;
- }
- case ANIMTYPE_MASKDATABLOCK:
- {
- Mask *mask = ale->data;
- MaskLayer *masklay;
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- ED_masklayer_frames_select_region(&ked, masklay, mode, selectmode);
- }
- break;
- }
- case ANIMTYPE_MASKLAYER:
- {
- ED_masklayer_frames_select_region(&ked, ale->data, mode, selectmode);
- break;
- }
- default:
- ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
- break;
- }
- }
-
- /* set minimum extent to be the maximum of the next channel */
- ymax = ymin;
- }
-
- /* cleanup */
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ case ANIMTYPE_GPLAYER: {
+ ED_gplayer_frames_select_region(&ked, ale->data, mode, selectmode);
+ ale->update |= ANIM_UPDATE_DEPS;
+ break;
+ }
+ case ANIMTYPE_MASKDATABLOCK: {
+ Mask *mask = ale->data;
+ MaskLayer *masklay;
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ ED_masklayer_frames_select_region(&ked, masklay, mode, selectmode);
+ }
+ break;
+ }
+ case ANIMTYPE_MASKLAYER: {
+ ED_masklayer_frames_select_region(&ked, ale->data, mode, selectmode);
+ break;
+ }
+ default:
+ ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
+ break;
+ }
+ }
+
+ /* set minimum extent to be the maximum of the next channel */
+ ymax = ymin;
+ }
+
+ /* cleanup */
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ----------------------------------- */
static int actkeys_lassoselect_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
+ bAnimContext ac;
- KeyframeEdit_LassoData data_lasso;
- rcti rect;
- rctf rect_fl;
+ KeyframeEdit_LassoData data_lasso;
+ rcti rect;
+ rctf rect_fl;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- 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)
- return OPERATOR_CANCELLED;
+ 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)
+ return OPERATOR_CANCELLED;
- const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
- const int selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- deselect_action_keys(&ac, 1, SELECT_SUBTRACT);
- }
+ const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
+ const int selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ deselect_action_keys(&ac, 1, SELECT_SUBTRACT);
+ }
- /* get settings from operator */
- BLI_lasso_boundbox(&rect, data_lasso.mcords, data_lasso.mcords_tot);
- BLI_rctf_rcti_copy(&rect_fl, &rect);
+ /* get settings from operator */
+ BLI_lasso_boundbox(&rect, data_lasso.mcords, data_lasso.mcords_tot);
+ 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);
+ /* 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.mcords);
- /* send notifier that keyframe selection has changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ /* send notifier that keyframe selection has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_select_lasso(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Lasso Select";
- ot->description = "Select keyframe points using lasso selection";
- ot->idname = "ACTION_OT_select_lasso";
-
- /* api callbacks */
- ot->invoke = WM_gesture_lasso_invoke;
- ot->modal = WM_gesture_lasso_modal;
- ot->exec = actkeys_lassoselect_exec;
- ot->poll = ED_operator_action_active;
- 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);
+ /* identifiers */
+ ot->name = "Lasso Select";
+ ot->description = "Select keyframe points using lasso selection";
+ ot->idname = "ACTION_OT_select_lasso";
+
+ /* api callbacks */
+ ot->invoke = WM_gesture_lasso_invoke;
+ ot->modal = WM_gesture_lasso_modal;
+ ot->exec = actkeys_lassoselect_exec;
+ ot->poll = ED_operator_action_active;
+ 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);
}
/* ------------------- */
static int action_circle_select_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
+ bAnimContext ac;
- KeyframeEdit_CircleData data = {0};
- rctf rect_fl;
+ KeyframeEdit_CircleData data = {0};
+ rctf rect_fl;
- float x = RNA_int_get(op->ptr, "x");
- float y = RNA_int_get(op->ptr, "y");
- float radius = RNA_int_get(op->ptr, "radius");
+ float x = RNA_int_get(op->ptr, "x");
+ float y = RNA_int_get(op->ptr, "y");
+ float radius = RNA_int_get(op->ptr, "radius");
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- const eSelectOp sel_op = ED_select_op_modal(
- RNA_enum_get(op->ptr, "mode"), WM_gesture_is_modal_first(op->customdata));
- const short selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- deselect_action_keys(&ac, 0, SELECT_SUBTRACT);
- }
+ const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"),
+ WM_gesture_is_modal_first(op->customdata));
+ const short selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ deselect_action_keys(&ac, 0, SELECT_SUBTRACT);
+ }
- data.mval[0] = x;
- data.mval[1] = y;
- data.radius_squared = radius * radius;
- data.rectf_view = &rect_fl;
+ data.mval[0] = x;
+ data.mval[1] = y;
+ data.radius_squared = radius * radius;
+ data.rectf_view = &rect_fl;
- rect_fl.xmin = x - radius;
- rect_fl.xmax = x + radius;
- rect_fl.ymin = y - radius;
- rect_fl.ymax = y + radius;
+ rect_fl.xmin = x - radius;
+ rect_fl.xmax = x + radius;
+ rect_fl.ymin = y - radius;
+ rect_fl.ymax = y + radius;
- /* apply region select action */
- region_select_action_keys(&ac, &rect_fl, BEZT_OK_CHANNEL_CIRCLE, selectmode, &data);
+ /* apply region select action */
+ region_select_action_keys(&ac, &rect_fl, BEZT_OK_CHANNEL_CIRCLE, selectmode, &data);
- /* send notifier that keyframe selection has changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ /* send notifier that keyframe selection has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_select_circle(wmOperatorType *ot)
{
- ot->name = "Circle Select";
- ot->description = "Select keyframe points using circle selection";
- ot->idname = "ACTION_OT_select_circle";
-
- ot->invoke = WM_gesture_circle_invoke;
- ot->modal = WM_gesture_circle_modal;
- ot->exec = action_circle_select_exec;
- ot->poll = ED_operator_action_active;
- 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);
+ ot->name = "Circle Select";
+ ot->description = "Select keyframe points using circle selection";
+ ot->idname = "ACTION_OT_select_circle";
+
+ ot->invoke = WM_gesture_circle_invoke;
+ ot->modal = WM_gesture_circle_modal;
+ ot->exec = action_circle_select_exec;
+ ot->poll = ED_operator_action_active;
+ 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);
}
/* ******************** Column Select Operator **************************** */
@@ -667,11 +655,15 @@ void ACTION_OT_select_circle(wmOperatorType *ot)
/* defines for column-select mode */
static const EnumPropertyItem prop_column_select_types[] = {
- {ACTKEYS_COLUMNSEL_KEYS, "KEYS", 0, "On Selected Keyframes", ""},
- {ACTKEYS_COLUMNSEL_CFRA, "CFRA", 0, "On Current Frame", ""},
- {ACTKEYS_COLUMNSEL_MARKERS_COLUMN, "MARKERS_COLUMN", 0, "On Selected Markers", ""},
- {ACTKEYS_COLUMNSEL_MARKERS_BETWEEN, "MARKERS_BETWEEN", 0, "Between Min/Max Selected Markers", ""},
- {0, NULL, 0, NULL, NULL},
+ {ACTKEYS_COLUMNSEL_KEYS, "KEYS", 0, "On Selected Keyframes", ""},
+ {ACTKEYS_COLUMNSEL_CFRA, "CFRA", 0, "On Current Frame", ""},
+ {ACTKEYS_COLUMNSEL_MARKERS_COLUMN, "MARKERS_COLUMN", 0, "On Selected Markers", ""},
+ {ACTKEYS_COLUMNSEL_MARKERS_BETWEEN,
+ "MARKERS_BETWEEN",
+ 0,
+ "Between Min/Max Selected Markers",
+ ""},
+ {0, NULL, 0, NULL, NULL},
};
/* ------------------- */
@@ -681,248 +673,249 @@ static const EnumPropertyItem prop_column_select_types[] = {
* should de-duplicate - campbell */
static void markers_selectkeys_between(bAnimContext *ac)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- KeyframeEditFunc ok_cb, select_cb;
- KeyframeEditData ked = {{NULL}};
- float min, max;
-
- /* get extreme markers */
- ED_markers_get_minmax(ac->markers, 1, &min, &max);
- min -= 0.5f;
- max += 0.5f;
-
- /* get editing funcs + data */
- ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
- select_cb = ANIM_editkeyframes_select(SELECT_ADD);
-
- ked.f1 = min;
- ked.f2 = max;
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* select keys in-between */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-
- if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
- }
- else if (ale->type == ANIMTYPE_GPLAYER) {
- ED_gplayer_frames_select_box(ale->data, min, max, SELECT_ADD);
- ale->update |= ANIM_UPDATE_DEPS;
- }
- else if (ale->type == ANIMTYPE_MASKLAYER) {
- ED_masklayer_frames_select_box(ale->data, min, max, SELECT_ADD);
- }
- else {
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
- }
- }
-
- /* Cleanup */
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ KeyframeEditFunc ok_cb, select_cb;
+ KeyframeEditData ked = {{NULL}};
+ float min, max;
+
+ /* get extreme markers */
+ ED_markers_get_minmax(ac->markers, 1, &min, &max);
+ min -= 0.5f;
+ max += 0.5f;
+
+ /* get editing funcs + data */
+ ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
+ select_cb = ANIM_editkeyframes_select(SELECT_ADD);
+
+ ked.f1 = min;
+ ked.f2 = max;
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* select keys in-between */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
+ }
+ else if (ale->type == ANIMTYPE_GPLAYER) {
+ ED_gplayer_frames_select_box(ale->data, min, max, SELECT_ADD);
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ ED_masklayer_frames_select_box(ale->data, min, max, SELECT_ADD);
+ }
+ else {
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
+ }
+ }
+
+ /* Cleanup */
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
-
/* Selects all visible keyframes in the same frames as the specified elements */
static void columnselect_action_keys(bAnimContext *ac, short mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- Scene *scene = ac->scene;
- CfraElem *ce;
- KeyframeEditFunc select_cb, ok_cb;
- KeyframeEditData ked = {{NULL}};
-
- /* build list of columns */
- switch (mode) {
- case ACTKEYS_COLUMNSEL_KEYS: /* list of selected keys */
- if (ac->datatype == ANIMCONT_GPENCIL) {
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next)
- ED_gplayer_make_cfra_list(ale->data, &ked.list, 1);
- }
- else {
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next)
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_to_cfraelem, NULL);
- }
- ANIM_animdata_freelist(&anim_data);
- break;
-
- case ACTKEYS_COLUMNSEL_CFRA: /* current frame */
- /* make a single CfraElem for storing this */
- ce = MEM_callocN(sizeof(CfraElem), "cfraElem");
- BLI_addtail(&ked.list, ce);
-
- ce->cfra = (float)CFRA;
- break;
-
- case ACTKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
- ED_markers_make_cfra_list(ac->markers, &ked.list, SELECT);
- break;
-
- default: /* invalid option */
- return;
- }
-
- /* set up BezTriple edit callbacks */
- select_cb = ANIM_editkeyframes_select(SELECT_ADD);
- ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME);
-
- /* loop through all of the keys and select additional keyframes
- * based on the keys found to be selected above
- */
- if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE);
- else
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-
- /* loop over cfraelems (stored in the KeyframeEditData->list)
- * - we need to do this here, as we can apply fewer NLA-mapping conversions
- */
- for (ce = ked.list.first; ce; ce = ce->next) {
- /* set frame for validation callback to refer to */
- if (adt)
- ked.f1 = BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP);
- else
- ked.f1 = ce->cfra;
-
- /* select elements with frame number matching cfraelem */
- if (ale->type == ANIMTYPE_GPLAYER) {
- ED_gpencil_select_frame(ale->data, ce->cfra, SELECT_ADD);
- ale->update |= ANIM_UPDATE_DEPS;
- }
- else if (ale->type == ANIMTYPE_MASKLAYER) {
- ED_mask_select_frame(ale->data, ce->cfra, SELECT_ADD);
- }
- else {
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
- }
- }
- }
-
- /* free elements */
- BLI_freelistN(&ked.list);
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ Scene *scene = ac->scene;
+ CfraElem *ce;
+ KeyframeEditFunc select_cb, ok_cb;
+ KeyframeEditData ked = {{NULL}};
+
+ /* build list of columns */
+ switch (mode) {
+ case ACTKEYS_COLUMNSEL_KEYS: /* list of selected keys */
+ if (ac->datatype == ANIMCONT_GPENCIL) {
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next)
+ ED_gplayer_make_cfra_list(ale->data, &ked.list, 1);
+ }
+ else {
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next)
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_to_cfraelem, NULL);
+ }
+ ANIM_animdata_freelist(&anim_data);
+ break;
+
+ case ACTKEYS_COLUMNSEL_CFRA: /* current frame */
+ /* make a single CfraElem for storing this */
+ ce = MEM_callocN(sizeof(CfraElem), "cfraElem");
+ BLI_addtail(&ked.list, ce);
+
+ ce->cfra = (float)CFRA;
+ break;
+
+ case ACTKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
+ ED_markers_make_cfra_list(ac->markers, &ked.list, SELECT);
+ break;
+
+ default: /* invalid option */
+ return;
+ }
+
+ /* set up BezTriple edit callbacks */
+ select_cb = ANIM_editkeyframes_select(SELECT_ADD);
+ ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME);
+
+ /* loop through all of the keys and select additional keyframes
+ * based on the keys found to be selected above
+ */
+ if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE);
+ else
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ /* loop over cfraelems (stored in the KeyframeEditData->list)
+ * - we need to do this here, as we can apply fewer NLA-mapping conversions
+ */
+ for (ce = ked.list.first; ce; ce = ce->next) {
+ /* set frame for validation callback to refer to */
+ if (adt)
+ ked.f1 = BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP);
+ else
+ ked.f1 = ce->cfra;
+
+ /* select elements with frame number matching cfraelem */
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ ED_gpencil_select_frame(ale->data, ce->cfra, SELECT_ADD);
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ ED_mask_select_frame(ale->data, ce->cfra, SELECT_ADD);
+ }
+ else {
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
+ }
+ }
+ }
+
+ /* free elements */
+ BLI_freelistN(&ked.list);
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int actkeys_columnselect_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- short mode;
+ bAnimContext ac;
+ short mode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* action to take depends on the mode */
- mode = RNA_enum_get(op->ptr, "mode");
+ /* action to take depends on the mode */
+ mode = RNA_enum_get(op->ptr, "mode");
- if (mode == ACTKEYS_COLUMNSEL_MARKERS_BETWEEN)
- markers_selectkeys_between(&ac);
- else
- columnselect_action_keys(&ac, mode);
+ if (mode == ACTKEYS_COLUMNSEL_MARKERS_BETWEEN)
+ markers_selectkeys_between(&ac);
+ else
+ columnselect_action_keys(&ac, mode);
- /* set notifier that keyframe selection have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ /* set notifier that keyframe selection have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_select_column(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select All";
- ot->idname = "ACTION_OT_select_column";
- ot->description = "Select all keyframes on the specified frame(s)";
+ /* identifiers */
+ ot->name = "Select All";
+ ot->idname = "ACTION_OT_select_column";
+ ot->description = "Select all keyframes on the specified frame(s)";
- /* api callbacks */
- ot->exec = actkeys_columnselect_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->exec = actkeys_columnselect_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- ot->prop = RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
+ /* props */
+ ot->prop = RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
}
/* ******************** Select Linked Operator *********************** */
static int actkeys_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
+ bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- KeyframeEditFunc ok_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
- KeyframeEditFunc sel_cb = ANIM_editkeyframes_select(SELECT_ADD);
+ KeyframeEditFunc ok_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
+ KeyframeEditFunc sel_cb = ANIM_editkeyframes_select(SELECT_ADD);
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* loop through all of the keys and select additional keyframes based on these */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* loop through all of the keys and select additional keyframes based on these */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
- /* check if anything selected? */
- if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ok_cb, NULL)) {
- /* select every keyframe in this curve then */
- ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL);
- }
- }
+ /* check if anything selected? */
+ if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ok_cb, NULL)) {
+ /* select every keyframe in this curve then */
+ ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL);
+ }
+ }
- /* Cleanup */
- ANIM_animdata_freelist(&anim_data);
+ /* Cleanup */
+ ANIM_animdata_freelist(&anim_data);
- /* set notifier that keyframe selection has changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ /* set notifier that keyframe selection has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_select_linked(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Linked";
- ot->idname = "ACTION_OT_select_linked";
- ot->description = "Select keyframes occurring in the same F-Curves as selected ones";
+ /* identifiers */
+ ot->name = "Select Linked";
+ ot->idname = "ACTION_OT_select_linked";
+ ot->description = "Select keyframes occurring in the same F-Curves as selected ones";
- /* api callbacks */
- ot->exec = actkeys_select_linked_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->exec = actkeys_select_linked_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Select More/Less Operators *********************** */
@@ -930,110 +923,110 @@ void ACTION_OT_select_linked(wmOperatorType *ot)
/* Common code to perform selection */
static void select_moreless_action_keys(bAnimContext *ac, short mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- KeyframeEditData ked = {{NULL}};
- KeyframeEditFunc build_cb;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ KeyframeEditData ked = {{NULL}};
+ KeyframeEditFunc build_cb;
- /* init selmap building data */
- build_cb = ANIM_editkeyframes_buildselmap(mode);
+ /* init selmap building data */
+ build_cb = ANIM_editkeyframes_buildselmap(mode);
- /* loop through all of the keys and select additional keyframes based on these */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ /* loop through all of the keys and select additional keyframes based on these */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
- /* only continue if F-Curve has keyframes */
- if (fcu->bezt == NULL)
- continue;
+ /* only continue if F-Curve has keyframes */
+ if (fcu->bezt == NULL)
+ continue;
- /* build up map of whether F-Curve's keyframes should be selected or not */
- ked.data = MEM_callocN(fcu->totvert, "selmap actEdit more");
- ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, build_cb, NULL);
+ /* build up map of whether F-Curve's keyframes should be selected or not */
+ ked.data = MEM_callocN(fcu->totvert, "selmap actEdit more");
+ ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, build_cb, NULL);
- /* based on this map, adjust the selection status of the keyframes */
- ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, bezt_selmap_flush, NULL);
+ /* based on this map, adjust the selection status of the keyframes */
+ ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, bezt_selmap_flush, NULL);
- /* free the selmap used here */
- MEM_freeN(ked.data);
- ked.data = NULL;
- }
+ /* free the selmap used here */
+ MEM_freeN(ked.data);
+ ked.data = NULL;
+ }
- /* Cleanup */
- ANIM_animdata_freelist(&anim_data);
+ /* Cleanup */
+ ANIM_animdata_freelist(&anim_data);
}
/* ----------------- */
static int actkeys_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
+ bAnimContext ac;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* perform select changes */
- select_moreless_action_keys(&ac, SELMAP_MORE);
+ /* perform select changes */
+ select_moreless_action_keys(&ac, SELMAP_MORE);
- /* set notifier that keyframe selection has changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ /* set notifier that keyframe selection has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_select_more(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select More";
- ot->idname = "ACTION_OT_select_more";
- ot->description = "Select keyframes beside already selected ones";
+ /* identifiers */
+ ot->name = "Select More";
+ ot->idname = "ACTION_OT_select_more";
+ ot->description = "Select keyframes beside already selected ones";
- /* api callbacks */
- ot->exec = actkeys_select_more_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->exec = actkeys_select_more_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ----------------- */
static int actkeys_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
+ bAnimContext ac;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* perform select changes */
- select_moreless_action_keys(&ac, SELMAP_LESS);
+ /* perform select changes */
+ select_moreless_action_keys(&ac, SELMAP_LESS);
- /* set notifier that keyframe selection has changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ /* set notifier that keyframe selection has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ACTION_OT_select_less(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Less";
- ot->idname = "ACTION_OT_select_less";
- ot->description = "Deselect keyframes on ends of selection islands";
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->idname = "ACTION_OT_select_less";
+ ot->description = "Deselect keyframes on ends of selection islands";
- /* api callbacks */
- ot->exec = actkeys_select_less_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->exec = actkeys_select_less_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Select Left/Right Operator ************************* */
@@ -1041,186 +1034,187 @@ void ACTION_OT_select_less(wmOperatorType *ot)
/* defines for left-right select tool */
static const EnumPropertyItem prop_actkeys_leftright_select_types[] = {
- {ACTKEYS_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""},
- {ACTKEYS_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""},
- {ACTKEYS_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""},
- {0, NULL, 0, NULL, NULL},
+ {ACTKEYS_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""},
+ {ACTKEYS_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""},
+ {ACTKEYS_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""},
+ {0, NULL, 0, NULL, NULL},
};
/* --------------------------------- */
static void actkeys_select_leftright(bAnimContext *ac, short leftright, short select_mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- KeyframeEditFunc ok_cb, select_cb;
- KeyframeEditData ked = {{NULL}};
- Scene *scene = ac->scene;
-
- /* if select mode is replace, deselect all keyframes (and channels) first */
- if (select_mode == SELECT_REPLACE) {
- select_mode = SELECT_ADD;
-
- /* - deselect all other keyframes, so that just the newly selected remain
- * - channels aren't deselected, since we don't re-select any as a consequence
- */
- deselect_action_keys(ac, 0, SELECT_SUBTRACT);
- }
-
- /* set callbacks and editing data */
- ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
- select_cb = ANIM_editkeyframes_select(select_mode);
-
- if (leftright == ACTKEYS_LRSEL_LEFT) {
- ked.f1 = MINAFRAMEF;
- ked.f2 = (float)(CFRA + 0.1f);
- }
- else {
- ked.f1 = (float)(CFRA - 0.1f);
- ked.f2 = MAXFRAMEF;
- }
-
- /* filter data */
- if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
- }
- else {
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
- }
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* select keys */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-
- if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
- }
- else if (ale->type == ANIMTYPE_GPLAYER) {
- ED_gplayer_frames_select_box(ale->data, ked.f1, ked.f2, select_mode);
- ale->update |= ANIM_UPDATE_DEPS;
- }
- else if (ale->type == ANIMTYPE_MASKLAYER) {
- ED_masklayer_frames_select_box(ale->data, ked.f1, ked.f2, select_mode);
- }
- else {
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
- }
- }
-
- /* Sync marker support */
- if (select_mode == SELECT_ADD) {
- SpaceAction *saction = (SpaceAction *)ac->sl;
-
- if ((saction) && (saction->flag & SACTION_MARKERS_MOVE)) {
- ListBase *markers = ED_animcontext_get_markers(ac);
- TimeMarker *marker;
-
- for (marker = markers->first; marker; marker = marker->next) {
- if (((leftright == ACTKEYS_LRSEL_LEFT) && (marker->frame < CFRA)) ||
- ((leftright == ACTKEYS_LRSEL_RIGHT) && (marker->frame >= CFRA)))
- {
- marker->flag |= SELECT;
- }
- else {
- marker->flag &= ~SELECT;
- }
- }
- }
- }
-
- /* Cleanup */
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ KeyframeEditFunc ok_cb, select_cb;
+ KeyframeEditData ked = {{NULL}};
+ Scene *scene = ac->scene;
+
+ /* if select mode is replace, deselect all keyframes (and channels) first */
+ if (select_mode == SELECT_REPLACE) {
+ select_mode = SELECT_ADD;
+
+ /* - deselect all other keyframes, so that just the newly selected remain
+ * - channels aren't deselected, since we don't re-select any as a consequence
+ */
+ deselect_action_keys(ac, 0, SELECT_SUBTRACT);
+ }
+
+ /* set callbacks and editing data */
+ ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
+ select_cb = ANIM_editkeyframes_select(select_mode);
+
+ if (leftright == ACTKEYS_LRSEL_LEFT) {
+ ked.f1 = MINAFRAMEF;
+ ked.f2 = (float)(CFRA + 0.1f);
+ }
+ else {
+ ked.f1 = (float)(CFRA - 0.1f);
+ ked.f2 = MAXFRAMEF;
+ }
+
+ /* filter data */
+ if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
+ }
+ else {
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ |
+ ANIMFILTER_NODUPLIS);
+ }
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* select keys */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
+ }
+ else if (ale->type == ANIMTYPE_GPLAYER) {
+ ED_gplayer_frames_select_box(ale->data, ked.f1, ked.f2, select_mode);
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ ED_masklayer_frames_select_box(ale->data, ked.f1, ked.f2, select_mode);
+ }
+ else {
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
+ }
+ }
+
+ /* Sync marker support */
+ if (select_mode == SELECT_ADD) {
+ SpaceAction *saction = (SpaceAction *)ac->sl;
+
+ if ((saction) && (saction->flag & SACTION_MARKERS_MOVE)) {
+ ListBase *markers = ED_animcontext_get_markers(ac);
+ TimeMarker *marker;
+
+ for (marker = markers->first; marker; marker = marker->next) {
+ if (((leftright == ACTKEYS_LRSEL_LEFT) && (marker->frame < CFRA)) ||
+ ((leftright == ACTKEYS_LRSEL_RIGHT) && (marker->frame >= CFRA))) {
+ marker->flag |= SELECT;
+ }
+ else {
+ marker->flag &= ~SELECT;
+ }
+ }
+ }
+ }
+
+ /* Cleanup */
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ----------------- */
static int actkeys_select_leftright_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- short leftright = RNA_enum_get(op->ptr, "mode");
- short selectmode;
+ bAnimContext ac;
+ short leftright = RNA_enum_get(op->ptr, "mode");
+ short selectmode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* select mode is either replace (deselect all, then add) or add/extend */
- if (RNA_boolean_get(op->ptr, "extend"))
- selectmode = SELECT_INVERT;
- else
- selectmode = SELECT_REPLACE;
+ /* select mode is either replace (deselect all, then add) or add/extend */
+ if (RNA_boolean_get(op->ptr, "extend"))
+ selectmode = SELECT_INVERT;
+ else
+ selectmode = SELECT_REPLACE;
- /* if "test" mode is set, we don't have any info to set this with */
- if (leftright == ACTKEYS_LRSEL_TEST)
- return OPERATOR_CANCELLED;
+ /* if "test" mode is set, we don't have any info to set this with */
+ if (leftright == ACTKEYS_LRSEL_TEST)
+ return OPERATOR_CANCELLED;
- /* do the selecting now */
- actkeys_select_leftright(&ac, leftright, selectmode);
+ /* do the selecting now */
+ actkeys_select_leftright(&ac, leftright, selectmode);
- /* set notifier that keyframe selection (and channels too) have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
+ /* set notifier that keyframe selection (and channels too) have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int actkeys_select_leftright_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bAnimContext ac;
- short leftright = RNA_enum_get(op->ptr, "mode");
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* handle mode-based testing */
- if (leftright == ACTKEYS_LRSEL_TEST) {
- Scene *scene = ac.scene;
- ARegion *ar = ac.ar;
- View2D *v2d = &ar->v2d;
- float x;
-
- /* determine which side of the current frame mouse is on */
- x = UI_view2d_region_to_view_x(v2d, event->mval[0]);
- if (x < CFRA)
- RNA_enum_set(op->ptr, "mode", ACTKEYS_LRSEL_LEFT);
- else
- RNA_enum_set(op->ptr, "mode", ACTKEYS_LRSEL_RIGHT);
- }
-
- /* perform selection */
- return actkeys_select_leftright_exec(C, op);
+ bAnimContext ac;
+ short leftright = RNA_enum_get(op->ptr, "mode");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* handle mode-based testing */
+ if (leftright == ACTKEYS_LRSEL_TEST) {
+ Scene *scene = ac.scene;
+ ARegion *ar = ac.ar;
+ View2D *v2d = &ar->v2d;
+ float x;
+
+ /* determine which side of the current frame mouse is on */
+ x = UI_view2d_region_to_view_x(v2d, event->mval[0]);
+ if (x < CFRA)
+ RNA_enum_set(op->ptr, "mode", ACTKEYS_LRSEL_LEFT);
+ else
+ RNA_enum_set(op->ptr, "mode", ACTKEYS_LRSEL_RIGHT);
+ }
+
+ /* perform selection */
+ return actkeys_select_leftright_exec(C, op);
}
void ACTION_OT_select_leftright(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Select Left/Right";
- ot->idname = "ACTION_OT_select_leftright";
- ot->description = "Select keyframes to the left or the right of the current frame";
+ /* identifiers */
+ ot->name = "Select Left/Right";
+ ot->idname = "ACTION_OT_select_leftright";
+ ot->description = "Select keyframes to the left or the right of the current frame";
- /* api callbacks */
- ot->invoke = actkeys_select_leftright_invoke;
- ot->exec = actkeys_select_leftright_exec;
- ot->poll = ED_operator_action_active;
+ /* api callbacks */
+ ot->invoke = actkeys_select_leftright_invoke;
+ ot->exec = actkeys_select_leftright_exec;
+ ot->poll = ED_operator_action_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "mode", prop_actkeys_leftright_select_types, ACTKEYS_LRSEL_TEST, "Mode", "");
- RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+ /* properties */
+ ot->prop = RNA_def_enum(
+ ot->srna, "mode", prop_actkeys_leftright_select_types, ACTKEYS_LRSEL_TEST, "Mode", "");
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ******************** Mouse-Click Select Operator *********************** */
@@ -1237,52 +1231,55 @@ void ACTION_OT_select_leftright(wmOperatorType *ot)
/* ------------------- */
/* option 1) select keyframe directly under mouse */
-static void actkeys_mselect_single(bAnimContext *ac, bAnimListElem *ale, short select_mode, float selx)
+static void actkeys_mselect_single(bAnimContext *ac,
+ bAnimListElem *ale,
+ short select_mode,
+ float selx)
{
- KeyframeEditData ked = {{NULL}};
- KeyframeEditFunc select_cb, ok_cb;
-
- /* get functions for selecting keyframes */
- select_cb = ANIM_editkeyframes_select(select_mode);
- ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME);
- ked.f1 = selx;
- ked.iterflags |= KED_F1_NLA_UNMAP;
-
- /* select the nominated keyframe on the given frame */
- if (ale->type == ANIMTYPE_GPLAYER) {
- ED_gpencil_select_frame(ale->data, selx, select_mode);
- ale->update |= ANIM_UPDATE_DEPS;
- }
- else if (ale->type == ANIMTYPE_MASKLAYER) {
- ED_mask_select_frame(ale->data, selx, select_mode);
- }
- else {
- if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK) &&
- (ale->type == ANIMTYPE_SUMMARY) && (ale->datatype == ALE_ALL))
- {
- ListBase anim_data = {NULL, NULL};
- int filter;
-
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- if (ale->type == ANIMTYPE_GPLAYER) {
- ED_gpencil_select_frame(ale->data, selx, select_mode);
- ale->update |= ANIM_UPDATE_DEPS;
- }
- else if (ale->type == ANIMTYPE_MASKLAYER) {
- ED_mask_select_frame(ale->data, selx, select_mode);
- }
- }
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
- }
- else {
- ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
- }
- }
+ KeyframeEditData ked = {{NULL}};
+ KeyframeEditFunc select_cb, ok_cb;
+
+ /* get functions for selecting keyframes */
+ select_cb = ANIM_editkeyframes_select(select_mode);
+ ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME);
+ ked.f1 = selx;
+ ked.iterflags |= KED_F1_NLA_UNMAP;
+
+ /* select the nominated keyframe on the given frame */
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ ED_gpencil_select_frame(ale->data, selx, select_mode);
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ ED_mask_select_frame(ale->data, selx, select_mode);
+ }
+ else {
+ if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK) && (ale->type == ANIMTYPE_SUMMARY) &&
+ (ale->datatype == ALE_ALL)) {
+ ListBase anim_data = {NULL, NULL};
+ int filter;
+
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ ED_gpencil_select_frame(ale->data, selx, select_mode);
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ ED_mask_select_frame(ale->data, selx, select_mode);
+ }
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+ }
+ else {
+ ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
+ }
+ }
}
/* Option 2) Selects all the keyframes on either side of the current frame
@@ -1292,390 +1289,402 @@ static void actkeys_mselect_single(bAnimContext *ac, bAnimListElem *ale, short s
/* Option 3) Selects all visible keyframes in the same frame as the mouse click */
static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float selx)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- KeyframeEditFunc select_cb, ok_cb;
- KeyframeEditData ked = {{NULL}};
-
- /* set up BezTriple edit callbacks */
- select_cb = ANIM_editkeyframes_select(select_mode);
- ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME);
-
- /* loop through all of the keys and select additional keyframes
- * based on the keys found to be selected above
- */
- if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS);
- }
- else {
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
- }
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-
- /* set frame for validation callback to refer to */
- if (adt)
- ked.f1 = BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP);
- else
- ked.f1 = selx;
-
- /* select elements with frame number matching cfra */
- if (ale->type == ANIMTYPE_GPLAYER) {
- ED_gpencil_select_frame(ale->key_data, selx, select_mode);
- ale->update |= ANIM_UPDATE_DEPS;
- }
- else if (ale->type == ANIMTYPE_MASKLAYER) {
- ED_mask_select_frame(ale->key_data, selx, select_mode);
- }
- else {
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
- }
- }
-
- /* free elements */
- BLI_freelistN(&ked.list);
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ KeyframeEditFunc select_cb, ok_cb;
+ KeyframeEditData ked = {{NULL}};
+
+ /* set up BezTriple edit callbacks */
+ select_cb = ANIM_editkeyframes_select(select_mode);
+ ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME);
+
+ /* loop through all of the keys and select additional keyframes
+ * based on the keys found to be selected above
+ */
+ if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ |
+ ANIMFILTER_NODUPLIS);
+ }
+ else {
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
+ }
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ /* set frame for validation callback to refer to */
+ if (adt)
+ ked.f1 = BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP);
+ else
+ ked.f1 = selx;
+
+ /* select elements with frame number matching cfra */
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ ED_gpencil_select_frame(ale->key_data, selx, select_mode);
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ ED_mask_select_frame(ale->key_data, selx, select_mode);
+ }
+ else {
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
+ }
+ }
+
+ /* free elements */
+ BLI_freelistN(&ked.list);
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* option 4) select all keyframes in same channel */
static void actkeys_mselect_channel_only(bAnimContext *ac, bAnimListElem *ale, short select_mode)
{
- KeyframeEditFunc select_cb;
-
- /* get functions for selecting keyframes */
- select_cb = ANIM_editkeyframes_select(select_mode);
-
- /* select all keyframes in this channel */
- if (ale->type == ANIMTYPE_GPLAYER) {
- ED_gpencil_select_frames(ale->data, select_mode);
- ale->update = ANIM_UPDATE_DEPS;
- }
- else if (ale->type == ANIMTYPE_MASKLAYER) {
- ED_mask_select_frames(ale->data, select_mode);
- }
- else {
- if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK) &&
- (ale->type == ANIMTYPE_SUMMARY) && (ale->datatype == ALE_ALL))
- {
- ListBase anim_data = {NULL, NULL};
- int filter;
-
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- if (ale->type == ANIMTYPE_GPLAYER) {
- ED_gpencil_select_frames(ale->data, select_mode);
- ale->update |= ANIM_UPDATE_DEPS;
- }
- else if (ale->type == ANIMTYPE_MASKLAYER) {
- ED_mask_select_frames(ale->data, select_mode);
- }
- }
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
- }
- else {
- ANIM_animchannel_keyframes_loop(NULL, ac->ads, ale, NULL, select_cb, NULL);
- }
- }
+ KeyframeEditFunc select_cb;
+
+ /* get functions for selecting keyframes */
+ select_cb = ANIM_editkeyframes_select(select_mode);
+
+ /* select all keyframes in this channel */
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ ED_gpencil_select_frames(ale->data, select_mode);
+ ale->update = ANIM_UPDATE_DEPS;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ ED_mask_select_frames(ale->data, select_mode);
+ }
+ else {
+ if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK) && (ale->type == ANIMTYPE_SUMMARY) &&
+ (ale->datatype == ALE_ALL)) {
+ ListBase anim_data = {NULL, NULL};
+ int filter;
+
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ ED_gpencil_select_frames(ale->data, select_mode);
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ ED_mask_select_frames(ale->data, select_mode);
+ }
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+ }
+ else {
+ ANIM_animchannel_keyframes_loop(NULL, ac->ads, ale, NULL, select_cb, NULL);
+ }
+ }
}
/* ------------------- */
-static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_mode, bool column, bool same_channel)
+static void mouse_action_keys(
+ bAnimContext *ac, const int mval[2], short select_mode, bool column, bool same_channel)
{
- ListBase anim_data = {NULL, NULL};
- DLRBT_Tree anim_keys;
- bAnimListElem *ale;
- int filter;
-
- View2D *v2d = &ac->ar->v2d;
- bDopeSheet *ads = NULL;
- int channel_index;
- bool found = false;
- float frame = 0.0f; /* frame of keyframe under mouse - NLA corrections not applied/included */
- float selx = 0.0f; /* frame of keyframe under mouse */
- float key_hsize;
- float x, y;
- rctf rectf;
-
- /* get dopesheet info */
- if (ELEM(ac->datatype, ANIMCONT_DOPESHEET, ANIMCONT_TIMELINE))
- ads = ac->data;
-
- /* use View2D to determine the index of the channel (i.e a row in the list) where keyframe was */
- UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
- UI_view2d_listview_view_to_cell(v2d, 0, ACHANNEL_STEP(ac), 0, (float)ACHANNEL_HEIGHT_HALF(ac), x, y, NULL, &channel_index);
-
- /* x-range to check is +/- 7px for standard keyframe under standard dpi/y-scale (in screen/region-space),
- * on either side of mouse click (size of keyframe icon)
- */
-
- /* standard channel height (to allow for some slop) */
- key_hsize = ACHANNEL_HEIGHT(ac) * 0.8f;
- /* half-size (for either side), but rounded up to nearest int (for easier targeting) */
- key_hsize = roundf(key_hsize / 2.0f);
-
- UI_view2d_region_to_view(v2d, mval[0] - (int)key_hsize, mval[1], &rectf.xmin, &rectf.ymin);
- UI_view2d_region_to_view(v2d, mval[0] + (int)key_hsize, mval[1], &rectf.xmax, &rectf.ymax);
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* try to get channel */
- ale = BLI_findlink(&anim_data, channel_index);
- if (ale == NULL) {
- /* channel not found */
- printf("Error: animation channel (index = %d) not found in mouse_action_keys()\n", channel_index);
- ANIM_animdata_freelist(&anim_data);
- return;
- }
- else {
- /* found match - must return here... */
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
- ActKeyColumn *ak, *akn = NULL;
-
- /* make list of keyframes */
- BLI_dlrbTree_init(&anim_keys);
-
- if (ale->key_data) {
- switch (ale->datatype) {
- case ALE_SCE:
- {
- Scene *scene = (Scene *)ale->key_data;
- scene_to_keylist(ads, scene, &anim_keys, 0);
- break;
- }
- case ALE_OB:
- {
- Object *ob = (Object *)ale->key_data;
- ob_to_keylist(ads, ob, &anim_keys, 0);
- break;
- }
- case ALE_ACT:
- {
- bAction *act = (bAction *)ale->key_data;
- action_to_keylist(adt, act, &anim_keys, 0);
- break;
- }
- case ALE_FCURVE:
- {
- FCurve *fcu = (FCurve *)ale->key_data;
- fcurve_to_keylist(adt, fcu, &anim_keys, 0);
- break;
- }
- }
- }
- else if (ale->type == ANIMTYPE_SUMMARY) {
- /* dopesheet summary covers everything */
- summary_to_keylist(ac, &anim_keys, 0);
- }
- else if (ale->type == ANIMTYPE_GROUP) {
- // TODO: why don't we just give groups key_data too?
- bActionGroup *agrp = (bActionGroup *)ale->data;
- agroup_to_keylist(adt, agrp, &anim_keys, 0);
- }
- else if (ale->type == ANIMTYPE_GPLAYER) {
- // TODO: why don't we just give gplayers key_data too?
- bGPDlayer *gpl = (bGPDlayer *)ale->data;
- gpl_to_keylist(ads, gpl, &anim_keys);
- }
- else if (ale->type == ANIMTYPE_MASKLAYER) {
- // TODO: why don't we just give masklayers key_data too?
- MaskLayer *masklay = (MaskLayer *)ale->data;
- mask_to_keylist(ads, masklay, &anim_keys);
- }
-
- /* start from keyframe at root of BST,
- * traversing until we find one within the range that was clicked on */
- for (ak = anim_keys.root; ak; ak = akn) {
- if (IN_RANGE(ak->cfra, rectf.xmin, rectf.xmax)) {
- /* set the frame to use, and apply inverse-correction for NLA-mapping
- * so that the frame will get selected by the selection functions without
- * requiring to map each frame once again...
- */
- selx = BKE_nla_tweakedit_remap(adt, ak->cfra, NLATIME_CONVERT_UNMAP);
- frame = ak->cfra;
- found = true;
- break;
- }
- else if (ak->cfra < rectf.xmin)
- akn = ak->right;
- else
- akn = ak->left;
- }
-
- /* remove active channel from list of channels for separate treatment (since it's needed later on) */
- BLI_remlink(&anim_data, ale);
- ale->next = ale->prev = NULL;
-
- /* cleanup temporary lists */
- BLI_dlrbTree_free(&anim_keys);
-
- /* free list of channels, since it's not used anymore */
- ANIM_animdata_freelist(&anim_data);
- }
-
- /* for replacing selection, firstly need to clear existing selection */
- if (select_mode == SELECT_REPLACE) {
- /* reset selection mode for next steps */
- select_mode = SELECT_ADD;
-
- /* deselect all keyframes */
- deselect_action_keys(ac, 0, SELECT_SUBTRACT);
-
- /* highlight channel clicked on */
- if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_TIMELINE)) {
- /* deselect all other channels first */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
-
- /* Highlight Action-Group or F-Curve? */
- if (ale && ale->data) {
- if (ale->type == ANIMTYPE_GROUP) {
- bActionGroup *agrp = ale->data;
-
- agrp->flag |= AGRP_SELECTED;
- ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
- }
- else if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
- FCurve *fcu = ale->data;
-
- fcu->flag |= FCURVE_SELECTED;
- ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type);
- }
- }
- }
- else if (ac->datatype == ANIMCONT_GPENCIL) {
- /* deselect all other channels first */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
-
- /* Highlight GPencil Layer */
- if ((ale && ale->data) && (ale->type == ANIMTYPE_GPLAYER)) {
- bGPDlayer *gpl = ale->data;
-
- gpl->flag |= GP_LAYER_SELECT;
- //gpencil_layer_setactive(gpd, gpl);
- }
- }
- else if (ac->datatype == ANIMCONT_MASK) {
- /* deselect all other channels first */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
-
- /* Highlight GPencil Layer */
- if ((ale && ale->data) && (ale->type == ANIMTYPE_MASKLAYER)) {
- MaskLayer *masklay = ale->data;
-
- masklay->flag |= MASK_LAYERFLAG_SELECT;
- //gpencil_layer_setactive(gpd, gpl);
- }
- }
- }
-
- /* only select keyframes if we clicked on a valid channel and hit something */
- if (ale) {
- if (found) {
- /* apply selection to keyframes */
- if (column) {
- /* select all keyframes in the same frame as the one we hit on the active channel
- * [T41077]: "frame" not "selx" here (i.e. no NLA corrections yet) as the code here
- * does that itself again as it needs to work on multiple datablocks
- */
- actkeys_mselect_column(ac, select_mode, frame);
- }
- else if (same_channel) {
- /* select all keyframes in the active channel */
- actkeys_mselect_channel_only(ac, ale, select_mode);
- }
- else {
- /* select the nominated keyframe on the given frame */
- actkeys_mselect_single(ac, ale, select_mode, selx);
- }
- }
-
- /* flush tagged updates
- * NOTE: We temporarily add this channel back to the list so that this can happen
- */
- anim_data.first = anim_data.last = ale;
- ANIM_animdata_update(ac, &anim_data);
-
- /* free this channel */
- MEM_freeN(ale);
- }
+ ListBase anim_data = {NULL, NULL};
+ DLRBT_Tree anim_keys;
+ bAnimListElem *ale;
+ int filter;
+
+ View2D *v2d = &ac->ar->v2d;
+ bDopeSheet *ads = NULL;
+ int channel_index;
+ bool found = false;
+ float frame = 0.0f; /* frame of keyframe under mouse - NLA corrections not applied/included */
+ float selx = 0.0f; /* frame of keyframe under mouse */
+ float key_hsize;
+ float x, y;
+ rctf rectf;
+
+ /* get dopesheet info */
+ if (ELEM(ac->datatype, ANIMCONT_DOPESHEET, ANIMCONT_TIMELINE))
+ ads = ac->data;
+
+ /* use View2D to determine the index of the channel (i.e a row in the list) where keyframe was */
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
+ UI_view2d_listview_view_to_cell(
+ v2d, 0, ACHANNEL_STEP(ac), 0, (float)ACHANNEL_HEIGHT_HALF(ac), x, y, NULL, &channel_index);
+
+ /* x-range to check is +/- 7px for standard keyframe under standard dpi/y-scale (in screen/region-space),
+ * on either side of mouse click (size of keyframe icon)
+ */
+
+ /* standard channel height (to allow for some slop) */
+ key_hsize = ACHANNEL_HEIGHT(ac) * 0.8f;
+ /* half-size (for either side), but rounded up to nearest int (for easier targeting) */
+ key_hsize = roundf(key_hsize / 2.0f);
+
+ UI_view2d_region_to_view(v2d, mval[0] - (int)key_hsize, mval[1], &rectf.xmin, &rectf.ymin);
+ UI_view2d_region_to_view(v2d, mval[0] + (int)key_hsize, mval[1], &rectf.xmax, &rectf.ymax);
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* try to get channel */
+ ale = BLI_findlink(&anim_data, channel_index);
+ if (ale == NULL) {
+ /* channel not found */
+ printf("Error: animation channel (index = %d) not found in mouse_action_keys()\n",
+ channel_index);
+ ANIM_animdata_freelist(&anim_data);
+ return;
+ }
+ else {
+ /* found match - must return here... */
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+ ActKeyColumn *ak, *akn = NULL;
+
+ /* make list of keyframes */
+ BLI_dlrbTree_init(&anim_keys);
+
+ if (ale->key_data) {
+ switch (ale->datatype) {
+ case ALE_SCE: {
+ Scene *scene = (Scene *)ale->key_data;
+ scene_to_keylist(ads, scene, &anim_keys, 0);
+ break;
+ }
+ case ALE_OB: {
+ Object *ob = (Object *)ale->key_data;
+ ob_to_keylist(ads, ob, &anim_keys, 0);
+ break;
+ }
+ case ALE_ACT: {
+ bAction *act = (bAction *)ale->key_data;
+ action_to_keylist(adt, act, &anim_keys, 0);
+ break;
+ }
+ case ALE_FCURVE: {
+ FCurve *fcu = (FCurve *)ale->key_data;
+ fcurve_to_keylist(adt, fcu, &anim_keys, 0);
+ break;
+ }
+ }
+ }
+ else if (ale->type == ANIMTYPE_SUMMARY) {
+ /* dopesheet summary covers everything */
+ summary_to_keylist(ac, &anim_keys, 0);
+ }
+ else if (ale->type == ANIMTYPE_GROUP) {
+ // TODO: why don't we just give groups key_data too?
+ bActionGroup *agrp = (bActionGroup *)ale->data;
+ agroup_to_keylist(adt, agrp, &anim_keys, 0);
+ }
+ else if (ale->type == ANIMTYPE_GPLAYER) {
+ // TODO: why don't we just give gplayers key_data too?
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+ gpl_to_keylist(ads, gpl, &anim_keys);
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ // TODO: why don't we just give masklayers key_data too?
+ MaskLayer *masklay = (MaskLayer *)ale->data;
+ mask_to_keylist(ads, masklay, &anim_keys);
+ }
+
+ /* start from keyframe at root of BST,
+ * traversing until we find one within the range that was clicked on */
+ for (ak = anim_keys.root; ak; ak = akn) {
+ if (IN_RANGE(ak->cfra, rectf.xmin, rectf.xmax)) {
+ /* set the frame to use, and apply inverse-correction for NLA-mapping
+ * so that the frame will get selected by the selection functions without
+ * requiring to map each frame once again...
+ */
+ selx = BKE_nla_tweakedit_remap(adt, ak->cfra, NLATIME_CONVERT_UNMAP);
+ frame = ak->cfra;
+ found = true;
+ break;
+ }
+ else if (ak->cfra < rectf.xmin)
+ akn = ak->right;
+ else
+ akn = ak->left;
+ }
+
+ /* remove active channel from list of channels for separate treatment (since it's needed later on) */
+ BLI_remlink(&anim_data, ale);
+ ale->next = ale->prev = NULL;
+
+ /* cleanup temporary lists */
+ BLI_dlrbTree_free(&anim_keys);
+
+ /* free list of channels, since it's not used anymore */
+ ANIM_animdata_freelist(&anim_data);
+ }
+
+ /* for replacing selection, firstly need to clear existing selection */
+ if (select_mode == SELECT_REPLACE) {
+ /* reset selection mode for next steps */
+ select_mode = SELECT_ADD;
+
+ /* deselect all keyframes */
+ deselect_action_keys(ac, 0, SELECT_SUBTRACT);
+
+ /* highlight channel clicked on */
+ if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_TIMELINE)) {
+ /* deselect all other channels first */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+
+ /* Highlight Action-Group or F-Curve? */
+ if (ale && ale->data) {
+ if (ale->type == ANIMTYPE_GROUP) {
+ bActionGroup *agrp = ale->data;
+
+ agrp->flag |= AGRP_SELECTED;
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
+ }
+ else if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
+ FCurve *fcu = ale->data;
+
+ fcu->flag |= FCURVE_SELECTED;
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type);
+ }
+ }
+ }
+ else if (ac->datatype == ANIMCONT_GPENCIL) {
+ /* deselect all other channels first */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+
+ /* Highlight GPencil Layer */
+ if ((ale && ale->data) && (ale->type == ANIMTYPE_GPLAYER)) {
+ bGPDlayer *gpl = ale->data;
+
+ gpl->flag |= GP_LAYER_SELECT;
+ //gpencil_layer_setactive(gpd, gpl);
+ }
+ }
+ else if (ac->datatype == ANIMCONT_MASK) {
+ /* deselect all other channels first */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+
+ /* Highlight GPencil Layer */
+ if ((ale && ale->data) && (ale->type == ANIMTYPE_MASKLAYER)) {
+ MaskLayer *masklay = ale->data;
+
+ masklay->flag |= MASK_LAYERFLAG_SELECT;
+ //gpencil_layer_setactive(gpd, gpl);
+ }
+ }
+ }
+
+ /* only select keyframes if we clicked on a valid channel and hit something */
+ if (ale) {
+ if (found) {
+ /* apply selection to keyframes */
+ if (column) {
+ /* select all keyframes in the same frame as the one we hit on the active channel
+ * [T41077]: "frame" not "selx" here (i.e. no NLA corrections yet) as the code here
+ * does that itself again as it needs to work on multiple datablocks
+ */
+ actkeys_mselect_column(ac, select_mode, frame);
+ }
+ else if (same_channel) {
+ /* select all keyframes in the active channel */
+ actkeys_mselect_channel_only(ac, ale, select_mode);
+ }
+ else {
+ /* select the nominated keyframe on the given frame */
+ actkeys_mselect_single(ac, ale, select_mode, selx);
+ }
+ }
+
+ /* flush tagged updates
+ * NOTE: We temporarily add this channel back to the list so that this can happen
+ */
+ anim_data.first = anim_data.last = ale;
+ ANIM_animdata_update(ac, &anim_data);
+
+ /* free this channel */
+ MEM_freeN(ale);
+ }
}
/* handle clicking */
static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bAnimContext ac;
- /* ARegion *ar; */ /* UNUSED */
- short selectmode;
- bool column, channel;
+ bAnimContext ac;
+ /* ARegion *ar; */ /* UNUSED */
+ short selectmode;
+ bool column, channel;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* get useful pointers from animation context data */
- /* ar = ac.ar; */ /* UNUSED */
+ /* get useful pointers from animation context data */
+ /* ar = ac.ar; */ /* UNUSED */
- /* select mode is either replace (deselect all, then add) or add/extend */
- if (RNA_boolean_get(op->ptr, "extend"))
- selectmode = SELECT_INVERT;
- else
- selectmode = SELECT_REPLACE;
+ /* select mode is either replace (deselect all, then add) or add/extend */
+ if (RNA_boolean_get(op->ptr, "extend"))
+ selectmode = SELECT_INVERT;
+ else
+ selectmode = SELECT_REPLACE;
- /* column selection */
- column = RNA_boolean_get(op->ptr, "column");
- channel = RNA_boolean_get(op->ptr, "channel");
+ /* column selection */
+ column = RNA_boolean_get(op->ptr, "column");
+ channel = RNA_boolean_get(op->ptr, "channel");
- /* select keyframe(s) based upon mouse position*/
- mouse_action_keys(&ac, event->mval, selectmode, column, channel);
+ /* select keyframe(s) based upon mouse position*/
+ mouse_action_keys(&ac, event->mval, selectmode, column, channel);
- /* set notifier that keyframe selection (and channels too) have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
+ /* set notifier that keyframe selection (and channels too) have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
- /* for tweak grab to work */
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ /* for tweak grab to work */
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
}
void ACTION_OT_clickselect(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Select Keyframes";
- ot->idname = "ACTION_OT_clickselect";
- ot->description = "Select keyframes by clicking on them";
-
- /* callbacks */
- ot->invoke = actkeys_clickselect_invoke;
- ot->poll = ED_operator_action_active;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select",
- "Toggle keyframe selection instead of leaving newly selected keyframes only"); // SHIFTKEY
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- prop = RNA_def_boolean(ot->srna, "column", 0, "Column Select",
- "Select all keyframes that occur on the same frame as the one under the mouse"); // ALTKEY
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- prop = RNA_def_boolean(ot->srna, "channel", 0, "Only Channel",
- "Select all the keyframes in the channel under the mouse"); // CTRLKEY + ALTKEY
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Keyframes";
+ ot->idname = "ACTION_OT_clickselect";
+ ot->description = "Select keyframes by clicking on them";
+
+ /* callbacks */
+ ot->invoke = actkeys_clickselect_invoke;
+ ot->poll = ED_operator_action_active;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_boolean(
+ ot->srna,
+ "extend",
+ 0,
+ "Extend Select",
+ "Toggle keyframe selection instead of leaving newly selected keyframes only"); // SHIFTKEY
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(
+ ot->srna,
+ "column",
+ 0,
+ "Column Select",
+ "Select all keyframes that occur on the same frame as the one under the mouse"); // ALTKEY
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(
+ ot->srna,
+ "channel",
+ 0,
+ "Only Channel",
+ "Select all the keyframes in the channel under the mouse"); // CTRLKEY + ALTKEY
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ************************************************************************** */
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index f2550550bc1..bfbca07d530 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -53,770 +53,784 @@
#include "ED_anim_api.h"
#include "ED_markers.h"
-#include "action_intern.h" /* own include */
+#include "action_intern.h" /* own include */
#include "GPU_framebuffer.h"
/* ******************** manage regions ********************* */
ARegion *action_has_buttons_region(ScrArea *sa)
{
- ARegion *ar, *arnew;
+ ARegion *ar, *arnew;
- ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
- if (ar) return ar;
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
+ if (ar)
+ return ar;
- /* add subdiv level; after main */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ /* add subdiv level; after main */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- /* is error! */
- if (ar == NULL) return NULL;
+ /* is error! */
+ if (ar == NULL)
+ return NULL;
- arnew = MEM_callocN(sizeof(ARegion), "buttons for action");
+ arnew = MEM_callocN(sizeof(ARegion), "buttons for action");
- BLI_insertlinkafter(&sa->regionbase, ar, arnew);
- arnew->regiontype = RGN_TYPE_UI;
- arnew->alignment = RGN_ALIGN_RIGHT;
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype = RGN_TYPE_UI;
+ arnew->alignment = RGN_ALIGN_RIGHT;
- arnew->flag = RGN_FLAG_HIDDEN;
+ arnew->flag = RGN_FLAG_HIDDEN;
- return arnew;
+ return arnew;
}
/* ******************** default callbacks for action space ***************** */
static SpaceLink *action_new(const ScrArea *sa, const Scene *scene)
{
- SpaceAction *saction;
- ARegion *ar;
+ SpaceAction *saction;
+ ARegion *ar;
- saction = MEM_callocN(sizeof(SpaceAction), "initaction");
- saction->spacetype = SPACE_ACTION;
+ saction = MEM_callocN(sizeof(SpaceAction), "initaction");
+ saction->spacetype = SPACE_ACTION;
- saction->autosnap = SACTSNAP_FRAME;
- saction->mode = SACTCONT_DOPESHEET;
- saction->mode_prev = SACTCONT_DOPESHEET;
- saction->flag = SACTION_SHOW_INTERPOLATION;
+ saction->autosnap = SACTSNAP_FRAME;
+ saction->mode = SACTCONT_DOPESHEET;
+ saction->mode_prev = SACTCONT_DOPESHEET;
+ saction->flag = SACTION_SHOW_INTERPOLATION;
- saction->ads.filterflag |= ADS_FILTER_SUMMARY;
+ saction->ads.filterflag |= ADS_FILTER_SUMMARY;
- /* enable all cache display */
- saction->cache_display |= TIME_CACHE_DISPLAY;
- saction->cache_display |= (TIME_CACHE_SOFTBODY | TIME_CACHE_PARTICLES);
- saction->cache_display |= (TIME_CACHE_CLOTH | TIME_CACHE_SMOKE | TIME_CACHE_DYNAMICPAINT);
- saction->cache_display |= TIME_CACHE_RIGIDBODY;
+ /* enable all cache display */
+ saction->cache_display |= TIME_CACHE_DISPLAY;
+ saction->cache_display |= (TIME_CACHE_SOFTBODY | TIME_CACHE_PARTICLES);
+ saction->cache_display |= (TIME_CACHE_CLOTH | TIME_CACHE_SMOKE | TIME_CACHE_DYNAMICPAINT);
+ saction->cache_display |= TIME_CACHE_RIGIDBODY;
- /* header */
- ar = MEM_callocN(sizeof(ARegion), "header for action");
+ /* header */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_HEADER;
+ ar->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;
+ /* 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;
- /* 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;
+ /* 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;
- /* ui buttons */
- ar = MEM_callocN(sizeof(ARegion), "buttons region for action");
+ /* ui buttons */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_UI;
+ ar->alignment = RGN_ALIGN_RIGHT;
+ ar->flag = RGN_FLAG_HIDDEN;
- /* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for action");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for action");
- BLI_addtail(&saction->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&saction->regionbase, ar);
+ ar->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;
+ 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;
- ar->v2d.cur = ar->v2d.tot;
+ ar->v2d.cur = ar->v2d.tot;
- ar->v2d.min[0] = 0.0f;
- ar->v2d.min[1] = 0.0f;
+ 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.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_SCALE_HORIZONTAL);
- 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;
+ ar->v2d.minzoom = 0.01f;
+ ar->v2d.maxzoom = 50;
+ ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
+ 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;
- return (SpaceLink *)saction;
+ return (SpaceLink *)saction;
}
/* not spacelink itself */
static void action_free(SpaceLink *UNUSED(sl))
{
-// SpaceAction *saction = (SpaceAction *) sl;
+ // SpaceAction *saction = (SpaceAction *) sl;
}
-
/* spacetype; init callback */
static void action_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
{
- SpaceAction *saction = sa->spacedata.first;
- saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
+ SpaceAction *saction = sa->spacedata.first;
+ saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
}
static SpaceLink *action_duplicate(SpaceLink *sl)
{
- SpaceAction *sactionn = MEM_dupallocN(sl);
+ SpaceAction *sactionn = MEM_dupallocN(sl);
- /* clear or remove stuff from old */
+ /* clear or remove stuff from old */
- return (SpaceLink *)sactionn;
+ return (SpaceLink *)sactionn;
}
-
-
/* add handlers, stuff you only do once or on area/region changes */
static void action_main_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
- /* own keymap */
- keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet", SPACE_ACTION, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet Generic", SPACE_ACTION, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ /* own keymap */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet", SPACE_ACTION, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet Generic", SPACE_ACTION, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
}
static void action_main_region_draw(const bContext *C, ARegion *ar)
{
- /* 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;
- View2DGrid *grid;
- View2DScrollers *scrollers;
- short marker_flag = 0;
- short cfra_flag = 0;
- short unit = 0;
-
- /* clear and setup matrix */
- UI_ThemeClearColor(TH_BACK);
- GPU_clear(GPU_COLOR_BIT);
-
- UI_view2d_view_ortho(v2d);
-
- /* time grid */
- unit = (saction->flag & SACTION_DRAWTIME) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES;
- grid = UI_view2d_grid_calc(CTX_data_scene(C), v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY, ar->winx, ar->winy);
- UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL);
- UI_view2d_grid_free(grid);
-
- ED_region_draw_cb_draw(C, ar, 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);
- }
-
- /* current frame */
- if (saction->flag & SACTION_DRAWTIME) cfra_flag |= DRAWCFRA_UNIT_SECONDS;
- ANIM_draw_cfra(C, v2d, cfra_flag);
-
- /* markers */
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
-
- marker_flag = ((ac.markers && (ac.markers != &ac.scene->markers)) ? DRAW_MARKERS_LOCAL : 0) | DRAW_MARKERS_MARGIN;
- if (saction->flag & SACTION_SHOW_MARKER_LINES) marker_flag |= DRAW_MARKERS_LINES;
- ED_markers_draw(C, marker_flag);
-
- /* caches */
- if (saction->mode == SACTCONT_TIMELINE) {
- timeline_draw_cache(saction, obact, scene);
- }
-
- /* preview range */
- UI_view2d_view_ortho(v2d);
- ANIM_draw_previewrange(C, v2d, 0);
-
- /* callback */
- UI_view2d_view_ortho(v2d);
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
-
- /* reset view matrix */
- UI_view2d_view_restore(C);
-
- /* scrollers */
- scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
-
- /* draw current frame number-indicator on top of scrollers */
- if ((saction->flag & SACTION_NODRAWCFRANUM) == 0) {
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- ANIM_draw_cfra_number(C, v2d, cfra_flag);
- }
+ /* 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;
+ View2DGrid *grid;
+ View2DScrollers *scrollers;
+ short marker_flag = 0;
+ short cfra_flag = 0;
+ short unit = 0;
+
+ /* clear and setup matrix */
+ UI_ThemeClearColor(TH_BACK);
+ GPU_clear(GPU_COLOR_BIT);
+
+ UI_view2d_view_ortho(v2d);
+
+ /* time grid */
+ unit = (saction->flag & SACTION_DRAWTIME) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES;
+ grid = UI_view2d_grid_calc(CTX_data_scene(C),
+ v2d,
+ unit,
+ V2D_GRID_CLAMP,
+ V2D_ARG_DUMMY,
+ V2D_ARG_DUMMY,
+ ar->winx,
+ ar->winy);
+ UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL);
+ UI_view2d_grid_free(grid);
+
+ ED_region_draw_cb_draw(C, ar, 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);
+ }
+
+ /* current frame */
+ if (saction->flag & SACTION_DRAWTIME)
+ cfra_flag |= DRAWCFRA_UNIT_SECONDS;
+ ANIM_draw_cfra(C, v2d, cfra_flag);
+
+ /* markers */
+ UI_view2d_view_orthoSpecial(ar, v2d, 1);
+
+ marker_flag = ((ac.markers && (ac.markers != &ac.scene->markers)) ? DRAW_MARKERS_LOCAL : 0) |
+ DRAW_MARKERS_MARGIN;
+ if (saction->flag & SACTION_SHOW_MARKER_LINES)
+ marker_flag |= DRAW_MARKERS_LINES;
+ ED_markers_draw(C, marker_flag);
+
+ /* caches */
+ if (saction->mode == SACTCONT_TIMELINE) {
+ timeline_draw_cache(saction, obact, scene);
+ }
+
+ /* preview range */
+ UI_view2d_view_ortho(v2d);
+ ANIM_draw_previewrange(C, v2d, 0);
+
+ /* callback */
+ UI_view2d_view_ortho(v2d);
+ ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ scrollers = UI_view2d_scrollers_calc(
+ C, v2d, NULL, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+
+ /* draw current frame number-indicator on top of scrollers */
+ if ((saction->flag & SACTION_NODRAWCFRANUM) == 0) {
+ UI_view2d_view_orthoSpecial(ar, v2d, 1);
+ ANIM_draw_cfra_number(C, v2d, cfra_flag);
+ }
}
/* add handlers, stuff you only do once or on area/region changes */
static void action_channel_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- /* ensure the 2d view sync works - main region has bottom scroller */
- ar->v2d.scroll = V2D_SCROLL_BOTTOM;
+ /* ensure the 2d view sync works - main region has bottom scroller */
+ ar->v2d.scroll = V2D_SCROLL_BOTTOM;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
- /* own keymap */
- keymap = WM_keymap_ensure(wm->defaultconf, "Animation Channels", 0, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ /* own keymap */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Animation Channels", 0, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet Generic", SPACE_ACTION, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet Generic", SPACE_ACTION, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
}
static void action_channel_region_draw(const bContext *C, ARegion *ar)
{
- /* draw entirely, view changes should be handled here */
- bAnimContext ac;
- View2D *v2d = &ar->v2d;
+ /* draw entirely, view changes should be handled here */
+ bAnimContext ac;
+ View2D *v2d = &ar->v2d;
- /* clear and setup matrix */
- UI_ThemeClearColor(TH_BACK);
- GPU_clear(GPU_COLOR_BIT);
+ /* clear and setup matrix */
+ UI_ThemeClearColor(TH_BACK);
+ GPU_clear(GPU_COLOR_BIT);
- UI_view2d_view_ortho(v2d);
+ UI_view2d_view_ortho(v2d);
- /* data */
- if (ANIM_animdata_get_context(C, &ac)) {
- draw_channel_names((bContext *)C, &ac, ar);
- }
+ /* data */
+ if (ANIM_animdata_get_context(C, &ac)) {
+ draw_channel_names((bContext *)C, &ac, ar);
+ }
- /* reset view matrix */
- UI_view2d_view_restore(C);
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
- /* no scrollers here */
+ /* no scrollers here */
}
-
/* add handlers, stuff you only do once or on area/region changes */
static void action_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
- ED_region_header_init(ar);
+ ED_region_header_init(ar);
}
static void action_header_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_header(C, ar);
+ ED_region_header(C, ar);
}
-static void action_channel_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void action_channel_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_ANIMATION:
- ED_region_tag_redraw(ar);
- break;
- case NC_SCENE:
- switch (wmn->data) {
- case ND_OB_ACTIVE:
- case ND_FRAME:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_OBJECT:
- switch (wmn->data) {
- case ND_BONE_ACTIVE:
- case ND_BONE_SELECT:
- case ND_KEYS:
- ED_region_tag_redraw(ar);
- break;
- case ND_MODIFIER:
- if (wmn->action == NA_RENAME)
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_GPENCIL:
- if (ELEM(wmn->action, NA_RENAME, NA_SELECTED))
- ED_region_tag_redraw(ar);
- break;
- case NC_ID:
- if (wmn->action == NA_RENAME)
- ED_region_tag_redraw(ar);
- break;
- default:
- if (wmn->data == ND_KEYS)
- ED_region_tag_redraw(ar);
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_ANIMATION:
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_OB_ACTIVE:
+ case ND_FRAME:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch (wmn->data) {
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_KEYS:
+ ED_region_tag_redraw(ar);
+ break;
+ case ND_MODIFIER:
+ if (wmn->action == NA_RENAME)
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_GPENCIL:
+ if (ELEM(wmn->action, NA_RENAME, NA_SELECTED))
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_ID:
+ if (wmn->action == NA_RENAME)
+ ED_region_tag_redraw(ar);
+ break;
+ default:
+ if (wmn->data == ND_KEYS)
+ ED_region_tag_redraw(ar);
+ break;
+ }
}
-static void saction_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 wmMsgBus *mbus)
+static void saction_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 wmMsgBus *mbus)
{
- PointerRNA ptr;
- RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, sa->spacedata.first, &ptr);
-
- wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
- .notify = ED_region_do_msg_notify_tag_redraw,
- };
-
- /* All dopesheet filter settings, etc. affect the drawing of this editor,
- * also same applies for all animation-related datatypes that may appear here,
- * so just whitelist the entire structs for updates
- */
- {
- wmMsgParams_RNA msg_key_params = {{{0}}};
- StructRNA *type_array[] = {
- &RNA_DopeSheet, /* dopesheet filters */
-
- &RNA_ActionGroup, /* channel groups */
-
- &RNA_FCurve, /* F-Curve */
- &RNA_Keyframe,
- &RNA_FCurveSample,
-
- &RNA_GreasePencil, /* Grease Pencil */
- &RNA_GPencilLayer,
- &RNA_GPencilFrame,
- };
-
- for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
- msg_key_params.ptr.type = type_array[i];
- WM_msg_subscribe_rna_params(
- mbus,
- &msg_key_params,
- &msg_sub_value_region_tag_redraw,
- __func__);
- }
- }
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, sa->spacedata.first, &ptr);
+
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ /* All dopesheet filter settings, etc. affect the drawing of this editor,
+ * also same applies for all animation-related datatypes that may appear here,
+ * so just whitelist the entire structs for updates
+ */
+ {
+ wmMsgParams_RNA msg_key_params = {{{0}}};
+ StructRNA *type_array[] = {
+ &RNA_DopeSheet, /* dopesheet filters */
+
+ &RNA_ActionGroup, /* channel groups */
+
+ &RNA_FCurve, /* F-Curve */
+ &RNA_Keyframe,
+ &RNA_FCurveSample,
+
+ &RNA_GreasePencil, /* Grease Pencil */
+ &RNA_GPencilLayer,
+ &RNA_GPencilFrame,
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
+ msg_key_params.ptr.type = type_array[i];
+ WM_msg_subscribe_rna_params(
+ mbus, &msg_key_params, &msg_sub_value_region_tag_redraw, __func__);
+ }
+ }
}
-static void action_main_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void action_main_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_ANIMATION:
- ED_region_tag_redraw(ar);
- break;
- case NC_SCENE:
- switch (wmn->data) {
- case ND_RENDER_OPTIONS:
- case ND_OB_ACTIVE:
- case ND_FRAME:
- case ND_FRAME_RANGE:
- case ND_MARKERS:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_OBJECT:
- switch (wmn->data) {
- case ND_TRANSFORM:
- /* moving object shouldn't need to redraw action */
- break;
- case ND_BONE_ACTIVE:
- case ND_BONE_SELECT:
- case ND_KEYS:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_NODE:
- switch (wmn->action) {
- case NA_EDITED:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_ID:
- if (wmn->action == NA_RENAME)
- ED_region_tag_redraw(ar);
- break;
- case NC_SCREEN:
- if (ELEM(wmn->data, ND_LAYER)) {
- ED_region_tag_redraw(ar);
- }
- break;
- default:
- if (wmn->data == ND_KEYS)
- ED_region_tag_redraw(ar);
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_ANIMATION:
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_RENDER_OPTIONS:
+ case ND_OB_ACTIVE:
+ case ND_FRAME:
+ case ND_FRAME_RANGE:
+ case ND_MARKERS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch (wmn->data) {
+ case ND_TRANSFORM:
+ /* moving object shouldn't need to redraw action */
+ break;
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_KEYS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_NODE:
+ switch (wmn->action) {
+ case NA_EDITED:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_ID:
+ if (wmn->action == NA_RENAME)
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_SCREEN:
+ if (ELEM(wmn->data, ND_LAYER)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ default:
+ if (wmn->data == ND_KEYS)
+ ED_region_tag_redraw(ar);
+ break;
+ }
}
-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 wmMsgBus *mbus)
+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 wmMsgBus *mbus)
{
- PointerRNA ptr;
- RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, sa->spacedata.first, &ptr);
-
- wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
- .notify = ED_region_do_msg_notify_tag_redraw,
- };
-
- /* Timeline depends on scene properties. */
- {
- bool use_preview = (scene->r.flag & SCER_PRV_RANGE);
- extern PropertyRNA rna_Scene_frame_start;
- extern PropertyRNA rna_Scene_frame_end;
- extern PropertyRNA rna_Scene_frame_preview_start;
- extern PropertyRNA rna_Scene_frame_preview_end;
- extern PropertyRNA rna_Scene_use_preview_range;
- extern PropertyRNA rna_Scene_frame_current;
- const PropertyRNA *props[] = {
- use_preview ? &rna_Scene_frame_preview_start : &rna_Scene_frame_start,
- use_preview ? &rna_Scene_frame_preview_end : &rna_Scene_frame_end,
- &rna_Scene_use_preview_range,
- &rna_Scene_frame_current,
- };
-
- PointerRNA idptr;
- RNA_id_pointer_create(&scene->id, &idptr);
-
- for (int i = 0; i < ARRAY_SIZE(props); i++) {
- WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__);
- }
- }
-
- /* 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);
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, sa->spacedata.first, &ptr);
+
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ /* Timeline depends on scene properties. */
+ {
+ bool use_preview = (scene->r.flag & SCER_PRV_RANGE);
+ extern PropertyRNA rna_Scene_frame_start;
+ extern PropertyRNA rna_Scene_frame_end;
+ extern PropertyRNA rna_Scene_frame_preview_start;
+ extern PropertyRNA rna_Scene_frame_preview_end;
+ extern PropertyRNA rna_Scene_use_preview_range;
+ extern PropertyRNA rna_Scene_frame_current;
+ const PropertyRNA *props[] = {
+ use_preview ? &rna_Scene_frame_preview_start : &rna_Scene_frame_start,
+ use_preview ? &rna_Scene_frame_preview_end : &rna_Scene_frame_end,
+ &rna_Scene_use_preview_range,
+ &rna_Scene_frame_current,
+ };
+
+ PointerRNA idptr;
+ RNA_id_pointer_create(&scene->id, &idptr);
+
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__);
+ }
+ }
+
+ /* 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);
}
/* editor level listener */
-static void action_listener(
- wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene))
+static void action_listener(wmWindow *UNUSED(win),
+ ScrArea *sa,
+ wmNotifier *wmn,
+ Scene *UNUSED(scene))
{
- SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
-
- /* context changes */
- switch (wmn->category) {
- case NC_GPENCIL:
- /* 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);
- }
- else if (wmn->action == NA_SELECTED) {
- saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
- ED_area_tag_refresh(sa);
- }
- }
- break;
- case NC_ANIMATION:
- /* 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);
- }
- /* autocolor only really needs to change when channels are added/removed,
- * or previously hidden stuff appears
- * (assume for now that if just adding these works, that will be fine)
- */
- 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);
- }
- /* 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);
- }
- break;
- case NC_SCENE:
- switch (wmn->data) {
- 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);
- break;
- case ND_RENDER_RESULT:
- ED_area_tag_redraw(sa);
- break;
- case ND_FRAME_RANGE:
- for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- Scene *scene = wmn->reference;
- ar->v2d.tot.xmin = (float)(SFRA - 4);
- ar->v2d.tot.xmax = (float)(EFRA + 4);
- break;
- }
- }
- break;
- default:
- if (saction->mode != SACTCONT_TIMELINE) {
- /* Just redrawing the view will do. */
- ED_area_tag_redraw(sa);
- }
- break;
- }
- break;
- case NC_OBJECT:
- switch (wmn->data) {
- case ND_BONE_SELECT: /* selection changed, so force refresh to flush
- * (needs flag set to do syncing) */
- case ND_BONE_ACTIVE:
- saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
- ED_area_tag_refresh(sa);
- break;
- case ND_TRANSFORM:
- /* moving object shouldn't need to redraw action */
- break;
- case ND_POINTCACHE:
- case ND_MODIFIER:
- case ND_PARTICLE:
- /* only needed in timeline mode */
- if (saction->mode == SACTCONT_TIMELINE) {
- ED_area_tag_refresh(sa);
- ED_area_tag_redraw(sa);
- }
- break;
- default: /* just redrawing the view will do */
- ED_area_tag_redraw(sa);
- break;
- }
- break;
- case NC_MASK:
- if (saction->mode == SACTCONT_MASK) {
- switch (wmn->data) {
- case ND_DATA:
- ED_area_tag_refresh(sa);
- ED_area_tag_redraw(sa);
- break;
- default: /* just redrawing the view will do */
- ED_area_tag_redraw(sa);
- break;
- }
- }
- break;
- case NC_NODE:
- 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);
- }
- break;
- case NC_SPACE:
- switch (wmn->data) {
- case ND_SPACE_DOPESHEET:
- ED_area_tag_redraw(sa);
- break;
- case ND_SPACE_TIME:
- ED_area_tag_redraw(sa);
- break;
- case ND_SPACE_CHANGED:
- saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
- ED_area_tag_refresh(sa);
- 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);
- }
- break;
- case NC_WM:
- switch (wmn->data) {
- case ND_FILEREAD:
- ED_area_tag_refresh(sa);
- break;
- }
- break;
- }
+ SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
+
+ /* context changes */
+ switch (wmn->category) {
+ case NC_GPENCIL:
+ /* 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);
+ }
+ else if (wmn->action == NA_SELECTED) {
+ saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
+ ED_area_tag_refresh(sa);
+ }
+ }
+ break;
+ case NC_ANIMATION:
+ /* 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);
+ }
+ /* autocolor only really needs to change when channels are added/removed,
+ * or previously hidden stuff appears
+ * (assume for now that if just adding these works, that will be fine)
+ */
+ 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);
+ }
+ /* 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);
+ }
+ break;
+ case NC_SCENE:
+ switch (wmn->data) {
+ 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);
+ break;
+ case ND_RENDER_RESULT:
+ ED_area_tag_redraw(sa);
+ break;
+ case ND_FRAME_RANGE:
+ for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_WINDOW) {
+ Scene *scene = wmn->reference;
+ ar->v2d.tot.xmin = (float)(SFRA - 4);
+ ar->v2d.tot.xmax = (float)(EFRA + 4);
+ break;
+ }
+ }
+ break;
+ default:
+ if (saction->mode != SACTCONT_TIMELINE) {
+ /* Just redrawing the view will do. */
+ ED_area_tag_redraw(sa);
+ }
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch (wmn->data) {
+ case ND_BONE_SELECT: /* selection changed, so force refresh to flush
+ * (needs flag set to do syncing) */
+ case ND_BONE_ACTIVE:
+ saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
+ ED_area_tag_refresh(sa);
+ break;
+ case ND_TRANSFORM:
+ /* moving object shouldn't need to redraw action */
+ break;
+ case ND_POINTCACHE:
+ case ND_MODIFIER:
+ case ND_PARTICLE:
+ /* only needed in timeline mode */
+ if (saction->mode == SACTCONT_TIMELINE) {
+ ED_area_tag_refresh(sa);
+ ED_area_tag_redraw(sa);
+ }
+ break;
+ default: /* just redrawing the view will do */
+ ED_area_tag_redraw(sa);
+ break;
+ }
+ break;
+ case NC_MASK:
+ if (saction->mode == SACTCONT_MASK) {
+ switch (wmn->data) {
+ case ND_DATA:
+ ED_area_tag_refresh(sa);
+ ED_area_tag_redraw(sa);
+ break;
+ default: /* just redrawing the view will do */
+ ED_area_tag_redraw(sa);
+ break;
+ }
+ }
+ break;
+ case NC_NODE:
+ 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);
+ }
+ break;
+ case NC_SPACE:
+ switch (wmn->data) {
+ case ND_SPACE_DOPESHEET:
+ ED_area_tag_redraw(sa);
+ break;
+ case ND_SPACE_TIME:
+ ED_area_tag_redraw(sa);
+ break;
+ case ND_SPACE_CHANGED:
+ saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
+ ED_area_tag_refresh(sa);
+ 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);
+ }
+ break;
+ case NC_WM:
+ switch (wmn->data) {
+ case ND_FILEREAD:
+ ED_area_tag_refresh(sa);
+ break;
+ }
+ break;
+ }
}
static void action_header_region_listener(
- wmWindow *UNUSED(win), ScrArea *sa, ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+ wmWindow *UNUSED(win), ScrArea *sa, ARegion *ar, wmNotifier *wmn, const Scene *UNUSED(scene))
{
- SpaceAction *saction = (SpaceAction *)sa->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);
- }
- break;
- case NC_SCENE:
- if (saction->mode == SACTCONT_TIMELINE) {
- switch (wmn->data) {
- case ND_RENDER_RESULT:
- case ND_OB_SELECT:
- case ND_FRAME:
- case ND_FRAME_RANGE:
- case ND_KEYINGSET:
- case ND_RENDER_OPTIONS:
- ED_region_tag_redraw(ar);
- break;
- }
- }
- else {
- switch (wmn->data) {
- case ND_OB_ACTIVE:
- ED_region_tag_redraw(ar);
- break;
- }
- }
- break;
- case NC_ID:
- if (wmn->action == NA_RENAME)
- ED_region_tag_redraw(ar);
- break;
- case NC_ANIMATION:
- switch (wmn->data) {
- case ND_ANIMCHAN: /* set of visible animchannels changed */
- /* 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);
- break;
-
- case ND_KEYFRAME: /* new keyframed added -> active action may have changed */
- //saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- }
-
+ SpaceAction *saction = (SpaceAction *)sa->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);
+ }
+ break;
+ case NC_SCENE:
+ if (saction->mode == SACTCONT_TIMELINE) {
+ switch (wmn->data) {
+ case ND_RENDER_RESULT:
+ case ND_OB_SELECT:
+ case ND_FRAME:
+ case ND_FRAME_RANGE:
+ case ND_KEYINGSET:
+ case ND_RENDER_OPTIONS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ }
+ else {
+ switch (wmn->data) {
+ case ND_OB_ACTIVE:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ }
+ break;
+ case NC_ID:
+ if (wmn->action == NA_RENAME)
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_ANIMATION:
+ switch (wmn->data) {
+ case ND_ANIMCHAN: /* set of visible animchannels changed */
+ /* 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);
+ break;
+
+ case ND_KEYFRAME: /* new keyframed added -> active action may have changed */
+ //saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ }
}
/* add handlers, stuff you only do once or on area/region changes */
static void action_buttons_area_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, ar);
- keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet Generic", SPACE_ACTION, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet Generic", SPACE_ACTION, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
}
static void action_buttons_area_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, ar);
}
-static void action_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void action_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_ANIMATION:
- ED_region_tag_redraw(ar);
- break;
- case NC_SCENE:
- switch (wmn->data) {
- case ND_OB_ACTIVE:
- case ND_FRAME:
- case ND_MARKERS:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_OBJECT:
- switch (wmn->data) {
- case ND_BONE_ACTIVE:
- case ND_BONE_SELECT:
- case ND_KEYS:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- default:
- if (wmn->data == ND_KEYS)
- ED_region_tag_redraw(ar);
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_ANIMATION:
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_OB_ACTIVE:
+ case ND_FRAME:
+ case ND_MARKERS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch (wmn->data) {
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_KEYS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ default:
+ if (wmn->data == ND_KEYS)
+ ED_region_tag_redraw(ar);
+ break;
+ }
}
static void action_refresh(const bContext *C, ScrArea *sa)
{
- SpaceAction *saction = (SpaceAction *)sa->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;
-
- /* Perform syncing of channel state incl. selection
- * Active action setting also occurs here (as part of anim channel filtering in anim_filter.c)
- */
- ANIM_sync_animchannels_to_data(C);
- saction->runtime.flag &= ~SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
-
- /* Tag everything for redraw
- * - 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);
- }
-
- /* region updates? */
- // XXX re-sizing y-extents of tot should go here?
+ SpaceAction *saction = (SpaceAction *)sa->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;
+
+ /* Perform syncing of channel state incl. selection
+ * Active action setting also occurs here (as part of anim channel filtering in anim_filter.c)
+ */
+ ANIM_sync_animchannels_to_data(C);
+ saction->runtime.flag &= ~SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
+
+ /* Tag everything for redraw
+ * - 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);
+ }
+
+ /* region updates? */
+ // 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)
{
- SpaceAction *sact = (SpaceAction *)slink;
-
- if ((ID *)sact->action == old_id) {
- sact->action = (bAction *)new_id;
- }
-
- if ((ID *)sact->ads.filter_grp == old_id) {
- sact->ads.filter_grp = (Collection *)new_id;
- }
- if ((ID *)sact->ads.source == old_id) {
- sact->ads.source = new_id;
- }
-
+ SpaceAction *sact = (SpaceAction *)slink;
+
+ if ((ID *)sact->action == old_id) {
+ sact->action = (bAction *)new_id;
+ }
+
+ if ((ID *)sact->ads.filter_grp == old_id) {
+ sact->ads.filter_grp = (Collection *)new_id;
+ }
+ if ((ID *)sact->ads.source == old_id) {
+ sact->ads.source = new_id;
+ }
}
/**
@@ -826,100 +840,101 @@ static void action_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, I
*/
static int action_space_subtype_get(ScrArea *sa)
{
- SpaceAction *sact = sa->spacedata.first;
- return sact->mode == SACTCONT_TIMELINE ? SACTCONT_TIMELINE : SACTCONT_DOPESHEET;
+ SpaceAction *sact = sa->spacedata.first;
+ return sact->mode == SACTCONT_TIMELINE ? SACTCONT_TIMELINE : SACTCONT_DOPESHEET;
}
static void action_space_subtype_set(ScrArea *sa, int value)
{
- SpaceAction *sact = sa->spacedata.first;
- if (value == SACTCONT_TIMELINE) {
- if (sact->mode != SACTCONT_TIMELINE) {
- sact->mode_prev = sact->mode;
- }
- sact->mode = value;
- }
- else {
- sact->mode = sact->mode_prev;
- }
+ SpaceAction *sact = sa->spacedata.first;
+ if (value == SACTCONT_TIMELINE) {
+ if (sact->mode != SACTCONT_TIMELINE) {
+ sact->mode_prev = sact->mode;
+ }
+ sact->mode = value;
+ }
+ else {
+ sact->mode = sact->mode_prev;
+ }
}
-static void action_space_subtype_item_extend(
- bContext *UNUSED(C), EnumPropertyItem **item, int *totitem)
+static void action_space_subtype_item_extend(bContext *UNUSED(C),
+ EnumPropertyItem **item,
+ int *totitem)
{
- RNA_enum_items_add(item, totitem, rna_enum_space_action_mode_items);
+ RNA_enum_items_add(item, totitem, rna_enum_space_action_mode_items);
}
/* only called once, from space/spacetypes.c */
void ED_spacetype_action(void)
{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype action");
- ARegionType *art;
-
- st->spaceid = SPACE_ACTION;
- strncpy(st->name, "Action", BKE_ST_MAXNAME);
-
- st->new = action_new;
- st->free = action_free;
- st->init = action_init;
- st->duplicate = action_duplicate;
- st->operatortypes = action_operatortypes;
- st->keymap = action_keymap;
- st->listener = action_listener;
- st->refresh = action_refresh;
- st->id_remap = action_id_remap;
- st->space_subtype_item_extend = action_space_subtype_item_extend;
- st->space_subtype_get = action_space_subtype_get;
- st->space_subtype_set = action_space_subtype_set;
-
- /* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype action region");
- art->regionid = RGN_TYPE_WINDOW;
- art->init = action_main_region_init;
- art->draw = action_main_region_draw;
- art->listener = action_main_region_listener;
- art->message_subscribe = saction_main_region_message_subscribe;
- art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype action region");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
-
- art->init = action_header_region_init;
- art->draw = action_header_region_draw;
- art->listener = action_header_region_listener;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: channels */
- art = MEM_callocN(sizeof(ARegionType), "spacetype action region");
- art->regionid = RGN_TYPE_CHANNELS;
- art->prefsizex = 200;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES;
-
- art->init = action_channel_region_init;
- art->draw = action_channel_region_draw;
- art->listener = action_channel_region_listener;
- art->message_subscribe = saction_channel_region_message_subscribe;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: UI buttons */
- art = MEM_callocN(sizeof(ARegionType), "spacetype action region");
- art->regionid = RGN_TYPE_UI;
- art->prefsizex = 200;
- art->keymapflag = ED_KEYMAP_UI;
- art->listener = action_region_listener;
- art->init = action_buttons_area_init;
- art->draw = action_buttons_area_draw;
-
- BLI_addhead(&st->regiontypes, art);
-
- action_buttons_register(art);
-
- BKE_spacetype_register(st);
+ SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype action");
+ ARegionType *art;
+
+ st->spaceid = SPACE_ACTION;
+ strncpy(st->name, "Action", BKE_ST_MAXNAME);
+
+ st->new = action_new;
+ st->free = action_free;
+ st->init = action_init;
+ st->duplicate = action_duplicate;
+ st->operatortypes = action_operatortypes;
+ st->keymap = action_keymap;
+ st->listener = action_listener;
+ st->refresh = action_refresh;
+ st->id_remap = action_id_remap;
+ st->space_subtype_item_extend = action_space_subtype_item_extend;
+ st->space_subtype_get = action_space_subtype_get;
+ st->space_subtype_set = action_space_subtype_set;
+
+ /* regions: main window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype action region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init = action_main_region_init;
+ art->draw = action_main_region_draw;
+ art->listener = action_main_region_listener;
+ art->message_subscribe = saction_main_region_message_subscribe;
+ art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype action region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = HEADERY;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
+
+ art->init = action_header_region_init;
+ art->draw = action_header_region_draw;
+ art->listener = action_header_region_listener;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: channels */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype action region");
+ art->regionid = RGN_TYPE_CHANNELS;
+ art->prefsizex = 200;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES;
+
+ art->init = action_channel_region_init;
+ art->draw = action_channel_region_draw;
+ art->listener = action_channel_region_listener;
+ art->message_subscribe = saction_channel_region_message_subscribe;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: UI buttons */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype action region");
+ art->regionid = RGN_TYPE_UI;
+ art->prefsizex = 200;
+ art->keymapflag = ED_KEYMAP_UI;
+ art->listener = action_region_listener;
+ art->init = action_buttons_area_init;
+ art->draw = action_buttons_area_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ action_buttons_register(art);
+
+ BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_api/CMakeLists.txt b/source/blender/editors/space_api/CMakeLists.txt
index 6a440f38eb8..74d9b703c68 100644
--- a/source/blender/editors/space_api/CMakeLists.txt
+++ b/source/blender/editors/space_api/CMakeLists.txt
@@ -16,14 +16,14 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../io
- ../../blenkernel
- ../../blenlib
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
+ ../include
+ ../io
+ ../../blenkernel
+ ../../blenlib
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
)
set(INC_SYS
@@ -31,30 +31,30 @@ set(INC_SYS
)
set(SRC
- spacetypes.c
+ spacetypes.c
)
set(LIB
- bf_editor_io
- bf_editor_sound
- bf_editor_space_action
- bf_editor_space_buttons
- bf_editor_space_clip
- bf_editor_space_console
- bf_editor_space_file
- bf_editor_space_graph
- bf_editor_space_image
- bf_editor_space_info
- bf_editor_space_nla
- bf_editor_space_node
- bf_editor_space_outliner
- bf_editor_space_script
- bf_editor_space_sequencer
- bf_editor_space_statusbar
- bf_editor_space_text
- bf_editor_space_topbar
- bf_editor_space_userpref
- bf_editor_space_view3d
+ bf_editor_io
+ bf_editor_sound
+ bf_editor_space_action
+ bf_editor_space_buttons
+ bf_editor_space_clip
+ bf_editor_space_console
+ bf_editor_space_file
+ bf_editor_space_graph
+ bf_editor_space_image
+ bf_editor_space_info
+ bf_editor_space_nla
+ bf_editor_space_node
+ bf_editor_space_outliner
+ bf_editor_space_script
+ bf_editor_space_sequencer
+ bf_editor_space_statusbar
+ bf_editor_space_text
+ bf_editor_space_topbar
+ bf_editor_space_userpref
+ bf_editor_space_view3d
)
blender_add_lib(bf_editor_space_api "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index 0288d7888d8..89758bd35da 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -20,7 +20,6 @@
* \ingroup spapi
*/
-
#include <stdlib.h>
#include "MEM_guardedalloc.h"
@@ -31,14 +30,12 @@
#include "DNA_scene_types.h"
#include "DNA_windowmanager_types.h"
-
#include "BKE_context.h"
#include "BKE_screen.h"
#include "UI_interface.h"
#include "UI_view2d.h"
-
#include "ED_anim_api.h"
#include "ED_armature.h"
#include "ED_curve.h"
@@ -72,119 +69,119 @@
/* only call once on startup, storage is global in BKE kernel listbase */
void ED_spacetypes_init(void)
{
- const ListBase *spacetypes;
- SpaceType *type;
-
- /* UI_UNIT_X is now a variable, is used in some spacetype inits? */
- U.widget_unit = 20;
-
- /* create space types */
- ED_spacetype_outliner();
- ED_spacetype_view3d();
- ED_spacetype_ipo();
- ED_spacetype_image();
- ED_spacetype_node();
- ED_spacetype_buttons();
- ED_spacetype_info();
- ED_spacetype_file();
- ED_spacetype_action();
- ED_spacetype_nla();
- ED_spacetype_script();
- ED_spacetype_text();
- ED_spacetype_sequencer();
- ED_spacetype_console();
- ED_spacetype_userpref();
- ED_spacetype_clip();
- ED_spacetype_statusbar();
- ED_spacetype_topbar();
-// ...
-
- /* register operator types for screen and all spaces */
- ED_operatortypes_userpref();
- ED_operatortypes_workspace();
- ED_operatortypes_scene();
- ED_operatortypes_screen();
- ED_operatortypes_anim();
- ED_operatortypes_animchannels();
- ED_operatortypes_gpencil();
- ED_operatortypes_object();
- ED_operatortypes_lattice();
- ED_operatortypes_mesh();
- ED_operatortypes_sculpt();
- ED_operatortypes_uvedit();
- ED_operatortypes_paint();
- ED_operatortypes_physics();
- ED_operatortypes_curve();
- ED_operatortypes_armature();
- ED_operatortypes_marker();
- ED_operatortypes_metaball();
- ED_operatortypes_sound();
- ED_operatortypes_render();
- ED_operatortypes_mask();
- ED_operatortypes_io();
-
- ED_operatortypes_view2d();
- ED_operatortypes_ui();
-
- ED_screen_user_menu_register();
-
- /* gizmo types */
- ED_gizmotypes_button_2d();
- ED_gizmotypes_dial_3d();
- ED_gizmotypes_move_3d();
- ED_gizmotypes_arrow_2d();
- ED_gizmotypes_arrow_3d();
- ED_gizmotypes_preselect_3d();
- ED_gizmotypes_primitive_3d();
- ED_gizmotypes_blank_3d();
- ED_gizmotypes_cage_2d();
- ED_gizmotypes_cage_3d();
- ED_gizmotypes_value_2d();
-
- /* gizmo group types */
- ED_gizmogrouptypes_value_2d();
-
- /* register types for operators and gizmos */
- spacetypes = BKE_spacetypes_list();
- for (type = spacetypes->first; type; type = type->next) {
- /* init gizmo types first, operator-types need them */
- if (type->gizmos) {
- type->gizmos();
- }
- if (type->operatortypes) {
- type->operatortypes();
- }
- }
+ const ListBase *spacetypes;
+ SpaceType *type;
+
+ /* UI_UNIT_X is now a variable, is used in some spacetype inits? */
+ U.widget_unit = 20;
+
+ /* create space types */
+ ED_spacetype_outliner();
+ ED_spacetype_view3d();
+ ED_spacetype_ipo();
+ ED_spacetype_image();
+ ED_spacetype_node();
+ ED_spacetype_buttons();
+ ED_spacetype_info();
+ ED_spacetype_file();
+ ED_spacetype_action();
+ ED_spacetype_nla();
+ ED_spacetype_script();
+ ED_spacetype_text();
+ ED_spacetype_sequencer();
+ ED_spacetype_console();
+ ED_spacetype_userpref();
+ ED_spacetype_clip();
+ ED_spacetype_statusbar();
+ ED_spacetype_topbar();
+ // ...
+
+ /* register operator types for screen and all spaces */
+ ED_operatortypes_userpref();
+ ED_operatortypes_workspace();
+ ED_operatortypes_scene();
+ ED_operatortypes_screen();
+ ED_operatortypes_anim();
+ ED_operatortypes_animchannels();
+ ED_operatortypes_gpencil();
+ ED_operatortypes_object();
+ ED_operatortypes_lattice();
+ ED_operatortypes_mesh();
+ ED_operatortypes_sculpt();
+ ED_operatortypes_uvedit();
+ ED_operatortypes_paint();
+ ED_operatortypes_physics();
+ ED_operatortypes_curve();
+ ED_operatortypes_armature();
+ ED_operatortypes_marker();
+ ED_operatortypes_metaball();
+ ED_operatortypes_sound();
+ ED_operatortypes_render();
+ ED_operatortypes_mask();
+ ED_operatortypes_io();
+
+ ED_operatortypes_view2d();
+ ED_operatortypes_ui();
+
+ ED_screen_user_menu_register();
+
+ /* gizmo types */
+ ED_gizmotypes_button_2d();
+ ED_gizmotypes_dial_3d();
+ ED_gizmotypes_move_3d();
+ ED_gizmotypes_arrow_2d();
+ ED_gizmotypes_arrow_3d();
+ ED_gizmotypes_preselect_3d();
+ ED_gizmotypes_primitive_3d();
+ ED_gizmotypes_blank_3d();
+ ED_gizmotypes_cage_2d();
+ ED_gizmotypes_cage_3d();
+ ED_gizmotypes_value_2d();
+
+ /* gizmo group types */
+ ED_gizmogrouptypes_value_2d();
+
+ /* register types for operators and gizmos */
+ spacetypes = BKE_spacetypes_list();
+ for (type = spacetypes->first; type; type = type->next) {
+ /* init gizmo types first, operator-types need them */
+ if (type->gizmos) {
+ type->gizmos();
+ }
+ if (type->operatortypes) {
+ type->operatortypes();
+ }
+ }
}
void ED_spacemacros_init(void)
{
- const ListBase *spacetypes;
- SpaceType *type;
-
- /* Macros's must go last since they reference other operators.
- * We need to have them go after python operators too */
- ED_operatormacros_armature();
- ED_operatormacros_mesh();
- ED_operatormacros_metaball();
- ED_operatormacros_node();
- ED_operatormacros_object();
- ED_operatormacros_file();
- ED_operatormacros_graph();
- ED_operatormacros_action();
- ED_operatormacros_clip();
- ED_operatormacros_curve();
- ED_operatormacros_mask();
- ED_operatormacros_sequencer();
- ED_operatormacros_paint();
- ED_operatormacros_gpencil();
-
- /* register dropboxes (can use macros) */
- spacetypes = BKE_spacetypes_list();
- for (type = spacetypes->first; type; type = type->next) {
- if (type->dropboxes)
- type->dropboxes();
- }
+ const ListBase *spacetypes;
+ SpaceType *type;
+
+ /* Macros's must go last since they reference other operators.
+ * We need to have them go after python operators too */
+ ED_operatormacros_armature();
+ ED_operatormacros_mesh();
+ ED_operatormacros_metaball();
+ ED_operatormacros_node();
+ ED_operatormacros_object();
+ ED_operatormacros_file();
+ ED_operatormacros_graph();
+ ED_operatormacros_action();
+ ED_operatormacros_clip();
+ ED_operatormacros_curve();
+ ED_operatormacros_mask();
+ ED_operatormacros_sequencer();
+ ED_operatormacros_paint();
+ ED_operatormacros_gpencil();
+
+ /* register dropboxes (can use macros) */
+ spacetypes = BKE_spacetypes_list();
+ for (type = spacetypes->first; type; type = type->next) {
+ if (type->dropboxes)
+ type->dropboxes();
+ }
}
/* called in wm.c */
@@ -192,94 +189,93 @@ void ED_spacemacros_init(void)
* using the keymap the actual areas/regions add the handlers */
void ED_spacetypes_keymap(wmKeyConfig *keyconf)
{
- const ListBase *spacetypes;
- SpaceType *stype;
- ARegionType *atype;
-
- ED_keymap_screen(keyconf);
- ED_keymap_anim(keyconf);
- ED_keymap_animchannels(keyconf);
- ED_keymap_gpencil(keyconf);
- ED_keymap_object(keyconf);
- ED_keymap_lattice(keyconf);
- ED_keymap_mesh(keyconf);
- ED_keymap_uvedit(keyconf);
- ED_keymap_curve(keyconf);
- ED_keymap_armature(keyconf);
- ED_keymap_physics(keyconf);
- ED_keymap_metaball(keyconf);
- ED_keymap_paint(keyconf);
- ED_keymap_mask(keyconf);
- ED_keymap_marker(keyconf);
-
- ED_keymap_view2d(keyconf);
- ED_keymap_ui(keyconf);
-
- ED_keymap_transform(keyconf);
-
- spacetypes = BKE_spacetypes_list();
- for (stype = spacetypes->first; stype; stype = stype->next) {
- if (stype->keymap)
- stype->keymap(keyconf);
- for (atype = stype->regiontypes.first; atype; atype = atype->next) {
- if (atype->keymap)
- atype->keymap(keyconf);
- }
- }
+ const ListBase *spacetypes;
+ SpaceType *stype;
+ ARegionType *atype;
+
+ ED_keymap_screen(keyconf);
+ ED_keymap_anim(keyconf);
+ ED_keymap_animchannels(keyconf);
+ ED_keymap_gpencil(keyconf);
+ ED_keymap_object(keyconf);
+ ED_keymap_lattice(keyconf);
+ ED_keymap_mesh(keyconf);
+ ED_keymap_uvedit(keyconf);
+ ED_keymap_curve(keyconf);
+ ED_keymap_armature(keyconf);
+ ED_keymap_physics(keyconf);
+ ED_keymap_metaball(keyconf);
+ ED_keymap_paint(keyconf);
+ ED_keymap_mask(keyconf);
+ ED_keymap_marker(keyconf);
+
+ ED_keymap_view2d(keyconf);
+ ED_keymap_ui(keyconf);
+
+ ED_keymap_transform(keyconf);
+
+ spacetypes = BKE_spacetypes_list();
+ for (stype = spacetypes->first; stype; stype = stype->next) {
+ if (stype->keymap)
+ stype->keymap(keyconf);
+ for (atype = stype->regiontypes.first; atype; atype = atype->next) {
+ if (atype->keymap)
+ atype->keymap(keyconf);
+ }
+ }
}
/* ********************** custom drawcall api ***************** */
typedef struct RegionDrawCB {
- struct RegionDrawCB *next, *prev;
+ struct RegionDrawCB *next, *prev;
- void (*draw)(const struct bContext *, struct ARegion *, void *);
- void *customdata;
+ void (*draw)(const struct bContext *, struct ARegion *, void *);
+ void *customdata;
- int type;
+ int type;
} RegionDrawCB;
void *ED_region_draw_cb_activate(ARegionType *art,
void (*draw)(const struct bContext *, struct ARegion *, void *),
- void *customdata, int type)
+ void *customdata,
+ int type)
{
- RegionDrawCB *rdc = MEM_callocN(sizeof(RegionDrawCB), "RegionDrawCB");
+ RegionDrawCB *rdc = MEM_callocN(sizeof(RegionDrawCB), "RegionDrawCB");
- BLI_addtail(&art->drawcalls, rdc);
- rdc->draw = draw;
- rdc->customdata = customdata;
- rdc->type = type;
+ BLI_addtail(&art->drawcalls, rdc);
+ rdc->draw = draw;
+ rdc->customdata = customdata;
+ rdc->type = type;
- return rdc;
+ return rdc;
}
void ED_region_draw_cb_exit(ARegionType *art, void *handle)
{
- RegionDrawCB *rdc;
-
- for (rdc = art->drawcalls.first; rdc; rdc = rdc->next) {
- if (rdc == (RegionDrawCB *)handle) {
- BLI_remlink(&art->drawcalls, rdc);
- MEM_freeN(rdc);
- return;
- }
- }
+ RegionDrawCB *rdc;
+
+ for (rdc = art->drawcalls.first; rdc; rdc = rdc->next) {
+ if (rdc == (RegionDrawCB *)handle) {
+ BLI_remlink(&art->drawcalls, rdc);
+ MEM_freeN(rdc);
+ return;
+ }
+ }
}
void ED_region_draw_cb_draw(const bContext *C, ARegion *ar, int type)
{
- RegionDrawCB *rdc;
+ RegionDrawCB *rdc;
- for (rdc = ar->type->drawcalls.first; rdc; rdc = rdc->next) {
- if (rdc->type == type) {
- rdc->draw(C, ar, rdc->customdata);
- }
- }
+ for (rdc = ar->type->drawcalls.first; rdc; rdc = rdc->next) {
+ if (rdc->type == type) {
+ rdc->draw(C, ar, rdc->customdata);
+ }
+ }
}
-
-
/* ********************* space template *********************** */
/* forward declare */
void ED_spacetype_xxx(void);
@@ -287,57 +283,56 @@ void ED_spacetype_xxx(void);
/* allocate and init some vars */
static SpaceLink *xxx_new(const ScrArea *UNUSED(sa), const Scene *UNUSED(scene))
{
- return NULL;
+ return NULL;
}
/* not spacelink itself */
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))
{
- /* link area to SpaceXXX struct */
+ /* link area to SpaceXXX struct */
- /* define how many regions, the order and types */
+ /* define how many regions, the order and types */
- /* add types to regions */
+ /* add types to regions */
}
static SpaceLink *xxx_duplicate(SpaceLink *UNUSED(sl))
{
- return NULL;
+ return NULL;
}
static void xxx_operatortypes(void)
{
- /* register operator types for this space */
+ /* register operator types for this space */
}
static void xxx_keymap(wmKeyConfig *UNUSED(keyconf))
{
- /* add default items to keymap */
+ /* add default items to keymap */
}
/* only called once, from screen/spacetypes.c */
void ED_spacetype_xxx(void)
{
- static SpaceType st;
+ static SpaceType st;
- st.spaceid = SPACE_VIEW3D;
+ st.spaceid = SPACE_VIEW3D;
- st.new = xxx_new;
- st.free = xxx_free;
- st.init = xxx_init;
- st.duplicate = xxx_duplicate;
- st.operatortypes = xxx_operatortypes;
- st.keymap = xxx_keymap;
+ st.new = xxx_new;
+ st.free = xxx_free;
+ st.init = xxx_init;
+ st.duplicate = xxx_duplicate;
+ st.operatortypes = xxx_operatortypes;
+ st.keymap = xxx_keymap;
- BKE_spacetype_register(&st);
+ BKE_spacetype_register(&st);
}
/* ****************************** end template *********************** */
diff --git a/source/blender/editors/space_buttons/CMakeLists.txt b/source/blender/editors/space_buttons/CMakeLists.txt
index 5ec2041c1dc..ce08b62e8ef 100644
--- a/source/blender/editors/space_buttons/CMakeLists.txt
+++ b/source/blender/editors/space_buttons/CMakeLists.txt
@@ -16,42 +16,42 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- buttons_context.c
- buttons_ops.c
- buttons_texture.c
- space_buttons.c
+ buttons_context.c
+ buttons_ops.c
+ buttons_texture.c
+ space_buttons.c
- buttons_intern.h
+ buttons_intern.h
)
set(LIB
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
add_definitions(${GL_DEFINITIONS})
if(WITH_FREESTYLE)
- add_definitions(-DWITH_FREESTYLE)
+ add_definitions(-DWITH_FREESTYLE)
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 0579e20bb5a..607c3ddbb10 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -21,7 +21,6 @@
* \ingroup spbuttons
*/
-
#include <stdlib.h>
#include <string.h>
@@ -66,1058 +65,1120 @@
#include "WM_api.h"
-#include "buttons_intern.h" // own include
+#include "buttons_intern.h" // own include
static int set_pointer_type(ButsContextPath *path, bContextDataResult *result, StructRNA *type)
{
- PointerRNA *ptr;
- int a;
+ PointerRNA *ptr;
+ int a;
- for (a = 0; a < path->len; a++) {
- ptr = &path->ptr[a];
+ for (a = 0; a < path->len; a++) {
+ ptr = &path->ptr[a];
- if (RNA_struct_is_a(ptr->type, type)) {
- CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data);
- return 1;
- }
- }
+ if (RNA_struct_is_a(ptr->type, type)) {
+ CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data);
+ return 1;
+ }
+ }
- return 0;
+ return 0;
}
static PointerRNA *get_pointer_type(ButsContextPath *path, StructRNA *type)
{
- PointerRNA *ptr;
- int a;
+ PointerRNA *ptr;
+ int a;
- for (a = 0; a < path->len; a++) {
- ptr = &path->ptr[a];
+ for (a = 0; a < path->len; a++) {
+ ptr = &path->ptr[a];
- if (RNA_struct_is_a(ptr->type, type)) {
- return ptr;
- }
- }
+ if (RNA_struct_is_a(ptr->type, type)) {
+ return ptr;
+ }
+ }
- return NULL;
+ return NULL;
}
/************************* Creating the Path ************************/
static int buttons_context_path_scene(ButsContextPath *path)
{
- PointerRNA *ptr = &path->ptr[path->len - 1];
+ PointerRNA *ptr = &path->ptr[path->len - 1];
- /* this one just verifies */
- return RNA_struct_is_a(ptr->type, &RNA_Scene);
+ /* this one just verifies */
+ return RNA_struct_is_a(ptr->type, &RNA_Scene);
}
static int buttons_context_path_view_layer(ButsContextPath *path, wmWindow *win)
{
- PointerRNA *ptr = &path->ptr[path->len - 1];
-
- /* View Layer may have already been resolved in a previous call
- * (e.g. in buttons_context_path_linestyle). */
- if (RNA_struct_is_a(ptr->type, &RNA_ViewLayer)) {
- return 1;
- }
-
- if (buttons_context_path_scene(path)) {
- Scene *scene = path->ptr[path->len - 1].data;
- ViewLayer *view_layer = (win->scene == scene) ?
- WM_window_get_active_view_layer(win) :
- BKE_view_layer_default_view(scene);
-
- RNA_pointer_create(&scene->id, &RNA_ViewLayer, view_layer, &path->ptr[path->len]);
- path->len++;
- return 1;
- }
-
- return 0;
+ PointerRNA *ptr = &path->ptr[path->len - 1];
+
+ /* View Layer may have already been resolved in a previous call
+ * (e.g. in buttons_context_path_linestyle). */
+ if (RNA_struct_is_a(ptr->type, &RNA_ViewLayer)) {
+ return 1;
+ }
+
+ if (buttons_context_path_scene(path)) {
+ Scene *scene = path->ptr[path->len - 1].data;
+ ViewLayer *view_layer = (win->scene == scene) ? WM_window_get_active_view_layer(win) :
+ BKE_view_layer_default_view(scene);
+
+ RNA_pointer_create(&scene->id, &RNA_ViewLayer, view_layer, &path->ptr[path->len]);
+ path->len++;
+ return 1;
+ }
+
+ return 0;
}
/* note: this function can return 1 without adding a world to the path
* so the buttons stay visible, but be sure to check the ID type if a ID_WO */
static int buttons_context_path_world(ButsContextPath *path)
{
- Scene *scene;
- World *world;
- PointerRNA *ptr = &path->ptr[path->len - 1];
-
- /* if we already have a (pinned) world, we're done */
- if (RNA_struct_is_a(ptr->type, &RNA_World)) {
- return 1;
- }
- /* if we have a scene, use the scene's world */
- else if (buttons_context_path_scene(path)) {
- scene = path->ptr[path->len - 1].data;
- world = scene->world;
-
- if (world) {
- RNA_id_pointer_create(&scene->world->id, &path->ptr[path->len]);
- path->len++;
- return 1;
- }
- else {
- return 1;
- }
- }
-
- /* no path to a world possible */
- return 0;
+ Scene *scene;
+ World *world;
+ PointerRNA *ptr = &path->ptr[path->len - 1];
+
+ /* if we already have a (pinned) world, we're done */
+ if (RNA_struct_is_a(ptr->type, &RNA_World)) {
+ return 1;
+ }
+ /* if we have a scene, use the scene's world */
+ else if (buttons_context_path_scene(path)) {
+ scene = path->ptr[path->len - 1].data;
+ world = scene->world;
+
+ if (world) {
+ RNA_id_pointer_create(&scene->world->id, &path->ptr[path->len]);
+ path->len++;
+ return 1;
+ }
+ else {
+ return 1;
+ }
+ }
+
+ /* no path to a world possible */
+ return 0;
}
static int buttons_context_path_linestyle(ButsContextPath *path, wmWindow *window)
{
- FreestyleLineStyle *linestyle;
- PointerRNA *ptr = &path->ptr[path->len - 1];
-
- /* if we already have a (pinned) linestyle, we're done */
- if (RNA_struct_is_a(ptr->type, &RNA_FreestyleLineStyle)) {
- return 1;
- }
- /* if we have a view layer, use the lineset's linestyle */
- else if (buttons_context_path_view_layer(path, window)) {
- ViewLayer *view_layer = path->ptr[path->len - 1].data;
- linestyle = BKE_linestyle_active_from_view_layer(view_layer);
- if (linestyle) {
- RNA_id_pointer_create(&linestyle->id, &path->ptr[path->len]);
- path->len++;
- return 1;
- }
- }
-
- /* no path to a linestyle possible */
- return 0;
+ FreestyleLineStyle *linestyle;
+ PointerRNA *ptr = &path->ptr[path->len - 1];
+
+ /* if we already have a (pinned) linestyle, we're done */
+ if (RNA_struct_is_a(ptr->type, &RNA_FreestyleLineStyle)) {
+ return 1;
+ }
+ /* if we have a view layer, use the lineset's linestyle */
+ else if (buttons_context_path_view_layer(path, window)) {
+ ViewLayer *view_layer = path->ptr[path->len - 1].data;
+ linestyle = BKE_linestyle_active_from_view_layer(view_layer);
+ if (linestyle) {
+ RNA_id_pointer_create(&linestyle->id, &path->ptr[path->len]);
+ path->len++;
+ return 1;
+ }
+ }
+
+ /* no path to a linestyle possible */
+ return 0;
}
static int buttons_context_path_object(ButsContextPath *path)
{
- PointerRNA *ptr = &path->ptr[path->len - 1];
+ PointerRNA *ptr = &path->ptr[path->len - 1];
- /* if we already have a (pinned) object, we're done */
- if (RNA_struct_is_a(ptr->type, &RNA_Object)) {
- return 1;
- }
- if (!RNA_struct_is_a(ptr->type, &RNA_ViewLayer)) {
- return 0;
- }
+ /* if we already have a (pinned) object, we're done */
+ if (RNA_struct_is_a(ptr->type, &RNA_Object)) {
+ return 1;
+ }
+ if (!RNA_struct_is_a(ptr->type, &RNA_ViewLayer)) {
+ return 0;
+ }
- ViewLayer *view_layer = ptr->data;
- Object *ob = (view_layer->basact) ? view_layer->basact->object : NULL;
+ ViewLayer *view_layer = ptr->data;
+ Object *ob = (view_layer->basact) ? view_layer->basact->object : NULL;
- if (ob) {
- RNA_id_pointer_create(&ob->id, &path->ptr[path->len]);
- path->len++;
+ if (ob) {
+ RNA_id_pointer_create(&ob->id, &path->ptr[path->len]);
+ path->len++;
- return 1;
- }
+ return 1;
+ }
- /* no path to a object possible */
- return 0;
+ /* no path to a object possible */
+ return 0;
}
static int buttons_context_path_data(ButsContextPath *path, int type)
{
- Object *ob;
- PointerRNA *ptr = &path->ptr[path->len - 1];
-
- /* if we already have a data, we're done */
- if (RNA_struct_is_a(ptr->type, &RNA_Mesh) && (type == -1 || type == OB_MESH)) {
- return 1;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_Curve) && (type == -1 || ELEM(type, OB_CURVE, OB_SURF, OB_FONT))) {
- return 1;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_Armature) && (type == -1 || type == OB_ARMATURE)) {
- return 1;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_MetaBall) && (type == -1 || type == OB_MBALL)) {
- return 1;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_Lattice) && (type == -1 || type == OB_LATTICE)) {
- return 1;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_Camera) && (type == -1 || type == OB_CAMERA)) {
- return 1;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_Light) && (type == -1 || type == OB_LAMP)) {
- return 1;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_Speaker) && (type == -1 || type == OB_SPEAKER)) {
- return 1;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_LightProbe) && (type == -1 || type == OB_LIGHTPROBE)) {
- return 1;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_GreasePencil) && (type == -1 || type == OB_GPENCIL)) {
- 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;
-
- if (ob && (type == -1 || type == ob->type)) {
- RNA_id_pointer_create(ob->data, &path->ptr[path->len]);
- path->len++;
-
- return 1;
- }
- }
-
- /* no path to data possible */
- return 0;
+ Object *ob;
+ PointerRNA *ptr = &path->ptr[path->len - 1];
+
+ /* if we already have a data, we're done */
+ if (RNA_struct_is_a(ptr->type, &RNA_Mesh) && (type == -1 || type == OB_MESH)) {
+ return 1;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Curve) &&
+ (type == -1 || ELEM(type, OB_CURVE, OB_SURF, OB_FONT))) {
+ return 1;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Armature) && (type == -1 || type == OB_ARMATURE)) {
+ return 1;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_MetaBall) && (type == -1 || type == OB_MBALL)) {
+ return 1;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Lattice) && (type == -1 || type == OB_LATTICE)) {
+ return 1;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Camera) && (type == -1 || type == OB_CAMERA)) {
+ return 1;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Light) && (type == -1 || type == OB_LAMP)) {
+ return 1;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Speaker) && (type == -1 || type == OB_SPEAKER)) {
+ return 1;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_LightProbe) && (type == -1 || type == OB_LIGHTPROBE)) {
+ return 1;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_GreasePencil) && (type == -1 || type == OB_GPENCIL)) {
+ 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;
+
+ if (ob && (type == -1 || type == ob->type)) {
+ RNA_id_pointer_create(ob->data, &path->ptr[path->len]);
+ path->len++;
+
+ return 1;
+ }
+ }
+
+ /* no path to data possible */
+ return 0;
}
static int buttons_context_path_modifier(ButsContextPath *path)
{
- Object *ob;
+ Object *ob;
- if (buttons_context_path_object(path)) {
- ob = path->ptr[path->len - 1].data;
+ 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)) {
- return 1;
- }
- }
+ if (ob && ELEM(ob->type, OB_MESH, OB_CURVE, OB_FONT, OB_SURF, OB_LATTICE, OB_GPENCIL)) {
+ return 1;
+ }
+ }
- return 0;
+ return 0;
}
static int buttons_context_path_shaderfx(ButsContextPath *path)
{
- Object *ob;
+ Object *ob;
- if (buttons_context_path_object(path)) {
- ob = path->ptr[path->len - 1].data;
+ if (buttons_context_path_object(path)) {
+ ob = path->ptr[path->len - 1].data;
- if (ob && ELEM(ob->type, OB_GPENCIL)) {
- return 1;
- }
- }
+ if (ob && ELEM(ob->type, OB_GPENCIL)) {
+ return 1;
+ }
+ }
- return 0;
+ return 0;
}
static int buttons_context_path_material(ButsContextPath *path)
{
- Object *ob;
- PointerRNA *ptr = &path->ptr[path->len - 1];
- Material *ma;
-
- /* if we already have a (pinned) material, we're done */
- if (RNA_struct_is_a(ptr->type, &RNA_Material)) {
- return 1;
- }
- /* if we have an object, use the object material slot */
- else if (buttons_context_path_object(path)) {
- ob = path->ptr[path->len - 1].data;
-
- if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type)) {
- ma = give_current_material(ob, ob->actcol);
- RNA_id_pointer_create(&ma->id, &path->ptr[path->len]);
- path->len++;
- return 1;
- }
- }
-
- /* no path to a material possible */
- return 0;
+ Object *ob;
+ PointerRNA *ptr = &path->ptr[path->len - 1];
+ Material *ma;
+
+ /* if we already have a (pinned) material, we're done */
+ if (RNA_struct_is_a(ptr->type, &RNA_Material)) {
+ return 1;
+ }
+ /* if we have an object, use the object material slot */
+ else if (buttons_context_path_object(path)) {
+ ob = path->ptr[path->len - 1].data;
+
+ if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type)) {
+ ma = give_current_material(ob, ob->actcol);
+ RNA_id_pointer_create(&ma->id, &path->ptr[path->len]);
+ path->len++;
+ return 1;
+ }
+ }
+
+ /* no path to a material possible */
+ return 0;
}
static int buttons_context_path_bone(ButsContextPath *path)
{
- bArmature *arm;
- EditBone *edbo;
-
- /* if we have an armature, get the active bone */
- if (buttons_context_path_data(path, OB_ARMATURE)) {
- arm = path->ptr[path->len - 1].data;
-
- if (arm->edbo) {
- if (arm->act_edbone) {
- edbo = arm->act_edbone;
- RNA_pointer_create(&arm->id, &RNA_EditBone, edbo, &path->ptr[path->len]);
- path->len++;
- return 1;
- }
- }
- else {
- if (arm->act_bone) {
- RNA_pointer_create(&arm->id, &RNA_Bone, arm->act_bone, &path->ptr[path->len]);
- path->len++;
- return 1;
- }
- }
- }
-
- /* no path to a bone possible */
- return 0;
+ bArmature *arm;
+ EditBone *edbo;
+
+ /* if we have an armature, get the active bone */
+ if (buttons_context_path_data(path, OB_ARMATURE)) {
+ arm = path->ptr[path->len - 1].data;
+
+ if (arm->edbo) {
+ if (arm->act_edbone) {
+ edbo = arm->act_edbone;
+ RNA_pointer_create(&arm->id, &RNA_EditBone, edbo, &path->ptr[path->len]);
+ path->len++;
+ return 1;
+ }
+ }
+ else {
+ if (arm->act_bone) {
+ RNA_pointer_create(&arm->id, &RNA_Bone, arm->act_bone, &path->ptr[path->len]);
+ path->len++;
+ return 1;
+ }
+ }
+ }
+
+ /* no path to a bone possible */
+ return 0;
}
static int buttons_context_path_pose_bone(ButsContextPath *path)
{
- PointerRNA *ptr = &path->ptr[path->len - 1];
-
- /* if we already have a (pinned) PoseBone, we're done */
- if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
- return 1;
- }
-
- /* if we have an armature, get the active bone */
- if (buttons_context_path_object(path)) {
- Object *ob = path->ptr[path->len - 1].data;
- bArmature *arm = ob->data; /* path->ptr[path->len-1].data - works too */
-
- if (ob->type != OB_ARMATURE || arm->edbo) {
- return 0;
- }
- else {
- if (arm->act_bone) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, arm->act_bone->name);
- if (pchan) {
- RNA_pointer_create(&ob->id, &RNA_PoseBone, pchan, &path->ptr[path->len]);
- path->len++;
- return 1;
- }
- }
- }
- }
-
- /* no path to a bone possible */
- return 0;
+ PointerRNA *ptr = &path->ptr[path->len - 1];
+
+ /* if we already have a (pinned) PoseBone, we're done */
+ if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
+ return 1;
+ }
+
+ /* if we have an armature, get the active bone */
+ if (buttons_context_path_object(path)) {
+ Object *ob = path->ptr[path->len - 1].data;
+ bArmature *arm = ob->data; /* path->ptr[path->len-1].data - works too */
+
+ if (ob->type != OB_ARMATURE || arm->edbo) {
+ return 0;
+ }
+ else {
+ if (arm->act_bone) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, arm->act_bone->name);
+ if (pchan) {
+ RNA_pointer_create(&ob->id, &RNA_PoseBone, pchan, &path->ptr[path->len]);
+ path->len++;
+ return 1;
+ }
+ }
+ }
+ }
+
+ /* no path to a bone possible */
+ return 0;
}
-
static int buttons_context_path_particle(ButsContextPath *path)
{
- Object *ob;
- ParticleSystem *psys;
- PointerRNA *ptr = &path->ptr[path->len - 1];
-
- /* if we already have (pinned) particle settings, we're done */
- if (RNA_struct_is_a(ptr->type, &RNA_ParticleSettings)) {
- return 1;
- }
- /* if we have an object, get the active particle system */
- if (buttons_context_path_object(path)) {
- ob = path->ptr[path->len - 1].data;
-
- if (ob && ob->type == OB_MESH) {
- psys = psys_get_current(ob);
-
- RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &path->ptr[path->len]);
- path->len++;
- return 1;
- }
- }
-
- /* no path to a particle system possible */
- return 0;
+ Object *ob;
+ ParticleSystem *psys;
+ PointerRNA *ptr = &path->ptr[path->len - 1];
+
+ /* if we already have (pinned) particle settings, we're done */
+ if (RNA_struct_is_a(ptr->type, &RNA_ParticleSettings)) {
+ return 1;
+ }
+ /* if we have an object, get the active particle system */
+ if (buttons_context_path_object(path)) {
+ ob = path->ptr[path->len - 1].data;
+
+ if (ob && ob->type == OB_MESH) {
+ psys = psys_get_current(ob);
+
+ RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &path->ptr[path->len]);
+ path->len++;
+ return 1;
+ }
+ }
+
+ /* no path to a particle system possible */
+ return 0;
}
static int buttons_context_path_brush(const bContext *C, ButsContextPath *path)
{
- Scene *scene;
- Brush *br = NULL;
- PointerRNA *ptr = &path->ptr[path->len - 1];
-
- /* if we already have a (pinned) brush, we're done */
- if (RNA_struct_is_a(ptr->type, &RNA_Brush)) {
- return 1;
- }
- /* if we have a scene, use the toolsettings brushes */
- else if (buttons_context_path_scene(path)) {
- scene = path->ptr[path->len - 1].data;
-
- if (scene) {
- wmWindow *window = CTX_wm_window(C);
- ViewLayer *view_layer = WM_window_get_active_view_layer(window);
- br = BKE_paint_brush(BKE_paint_get_active(scene, view_layer));
- }
-
- if (br) {
- RNA_id_pointer_create((ID *)br, &path->ptr[path->len]);
- path->len++;
-
- return 1;
- }
- }
-
- /* no path to a brush possible */
- return 0;
+ Scene *scene;
+ Brush *br = NULL;
+ PointerRNA *ptr = &path->ptr[path->len - 1];
+
+ /* if we already have a (pinned) brush, we're done */
+ if (RNA_struct_is_a(ptr->type, &RNA_Brush)) {
+ return 1;
+ }
+ /* if we have a scene, use the toolsettings brushes */
+ else if (buttons_context_path_scene(path)) {
+ scene = path->ptr[path->len - 1].data;
+
+ if (scene) {
+ wmWindow *window = CTX_wm_window(C);
+ ViewLayer *view_layer = WM_window_get_active_view_layer(window);
+ br = BKE_paint_brush(BKE_paint_get_active(scene, view_layer));
+ }
+
+ if (br) {
+ RNA_id_pointer_create((ID *)br, &path->ptr[path->len]);
+ path->len++;
+
+ return 1;
+ }
+ }
+
+ /* no path to a brush possible */
+ return 0;
}
-static int buttons_context_path_texture(const bContext *C, ButsContextPath *path, ButsContextTexture *ct)
+static int buttons_context_path_texture(const bContext *C,
+ ButsContextPath *path,
+ ButsContextTexture *ct)
{
- PointerRNA *ptr = &path->ptr[path->len - 1];
- ID *id;
-
- if (!ct) {
- return 0;
- }
-
- /* if we already have a (pinned) texture, we're done */
- if (RNA_struct_is_a(ptr->type, &RNA_Texture)) {
- return 1;
- }
-
- if (!ct->user) {
- return 0;
- }
-
- id = ct->user->id;
-
- if (id) {
- if (GS(id->name) == ID_BR) {
- buttons_context_path_brush(C, path);
- }
- else if (GS(id->name) == ID_PA) {
- buttons_context_path_particle(path);
- }
- else if (GS(id->name) == ID_OB) {
- buttons_context_path_object(path);
- }
- else if (GS(id->name) == ID_LS) {
- buttons_context_path_linestyle(path, CTX_wm_window(C));
- }
- }
-
- if (ct->texture) {
- RNA_id_pointer_create(&ct->texture->id, &path->ptr[path->len]);
- path->len++;
- }
-
- return 1;
+ PointerRNA *ptr = &path->ptr[path->len - 1];
+ ID *id;
+
+ if (!ct) {
+ return 0;
+ }
+
+ /* if we already have a (pinned) texture, we're done */
+ if (RNA_struct_is_a(ptr->type, &RNA_Texture)) {
+ return 1;
+ }
+
+ if (!ct->user) {
+ return 0;
+ }
+
+ id = ct->user->id;
+
+ if (id) {
+ if (GS(id->name) == ID_BR) {
+ buttons_context_path_brush(C, path);
+ }
+ else if (GS(id->name) == ID_PA) {
+ buttons_context_path_particle(path);
+ }
+ else if (GS(id->name) == ID_OB) {
+ buttons_context_path_object(path);
+ }
+ else if (GS(id->name) == ID_LS) {
+ buttons_context_path_linestyle(path, CTX_wm_window(C));
+ }
+ }
+
+ if (ct->texture) {
+ RNA_id_pointer_create(&ct->texture->id, &path->ptr[path->len]);
+ path->len++;
+ }
+
+ return 1;
}
#ifdef WITH_FREESTYLE
static bool buttons_context_linestyle_pinnable(const bContext *C, ViewLayer *view_layer)
{
- wmWindow *window = CTX_wm_window(C);
- Scene *scene = WM_window_get_active_scene(window);
- FreestyleConfig *config;
- SpaceProperties *sbuts;
-
- /* if Freestyle is disabled in the scene */
- if ((scene->r.mode & R_EDGE_FRS) == 0) {
- return false;
- }
- /* if Freestyle is not in the Parameter Editor mode */
- config = &view_layer->freestyle_config;
- if (config->mode != FREESTYLE_CONTROL_EDITOR_MODE) {
- return false;
- }
- /* if the scene has already been pinned */
- sbuts = CTX_wm_space_properties(C);
- if (sbuts->pinid && sbuts->pinid == &scene->id) {
- return false;
- }
- return true;
+ wmWindow *window = CTX_wm_window(C);
+ Scene *scene = WM_window_get_active_scene(window);
+ FreestyleConfig *config;
+ SpaceProperties *sbuts;
+
+ /* if Freestyle is disabled in the scene */
+ if ((scene->r.mode & R_EDGE_FRS) == 0) {
+ return false;
+ }
+ /* if Freestyle is not in the Parameter Editor mode */
+ config = &view_layer->freestyle_config;
+ if (config->mode != FREESTYLE_CONTROL_EDITOR_MODE) {
+ return false;
+ }
+ /* if the scene has already been pinned */
+ sbuts = CTX_wm_space_properties(C);
+ if (sbuts->pinid && sbuts->pinid == &scene->id) {
+ return false;
+ }
+ return true;
}
#endif
static int buttons_context_path(const bContext *C, ButsContextPath *path, int mainb, int flag)
{
- /* Note we don't use CTX_data here, instead we get it from the window.
- * Otherwise there is a loop reading the context that we are setting. */
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
- wmWindow *window = CTX_wm_window(C);
- Scene *scene = WM_window_get_active_scene(window);
- ViewLayer *view_layer = WM_window_get_active_view_layer(window);
- ID *id;
- int found;
-
- memset(path, 0, sizeof(*path));
- path->flag = flag;
-
- /* If some ID datablock is pinned, set the root pointer. */
- if (sbuts->pinid) {
- id = sbuts->pinid;
-
- RNA_id_pointer_create(id, &path->ptr[0]);
- path->len++;
- }
- /* No pinned root, use scene as initial root. */
- else if (mainb != BCONTEXT_TOOL) {
- RNA_id_pointer_create(&scene->id, &path->ptr[0]);
- path->len++;
-
- if (!ELEM(mainb, BCONTEXT_SCENE, BCONTEXT_RENDER, BCONTEXT_OUTPUT, BCONTEXT_VIEW_LAYER, BCONTEXT_WORLD)) {
- RNA_pointer_create(NULL, &RNA_ViewLayer, view_layer, &path->ptr[path->len]);
- path->len++;
- }
- }
-
- /* now for each buttons context type, we try to construct a path,
- * tracing back recursively */
- switch (mainb) {
- case BCONTEXT_SCENE:
- case BCONTEXT_RENDER:
- case BCONTEXT_OUTPUT:
- found = buttons_context_path_scene(path);
- break;
- case BCONTEXT_VIEW_LAYER:
+ /* Note we don't use CTX_data here, instead we get it from the window.
+ * Otherwise there is a loop reading the context that we are setting. */
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ wmWindow *window = CTX_wm_window(C);
+ Scene *scene = WM_window_get_active_scene(window);
+ ViewLayer *view_layer = WM_window_get_active_view_layer(window);
+ ID *id;
+ int found;
+
+ memset(path, 0, sizeof(*path));
+ path->flag = flag;
+
+ /* If some ID datablock is pinned, set the root pointer. */
+ if (sbuts->pinid) {
+ id = sbuts->pinid;
+
+ RNA_id_pointer_create(id, &path->ptr[0]);
+ path->len++;
+ }
+ /* No pinned root, use scene as initial root. */
+ else if (mainb != BCONTEXT_TOOL) {
+ RNA_id_pointer_create(&scene->id, &path->ptr[0]);
+ path->len++;
+
+ if (!ELEM(mainb,
+ BCONTEXT_SCENE,
+ BCONTEXT_RENDER,
+ BCONTEXT_OUTPUT,
+ BCONTEXT_VIEW_LAYER,
+ BCONTEXT_WORLD)) {
+ RNA_pointer_create(NULL, &RNA_ViewLayer, view_layer, &path->ptr[path->len]);
+ path->len++;
+ }
+ }
+
+ /* now for each buttons context type, we try to construct a path,
+ * tracing back recursively */
+ switch (mainb) {
+ case BCONTEXT_SCENE:
+ case BCONTEXT_RENDER:
+ case BCONTEXT_OUTPUT:
+ found = buttons_context_path_scene(path);
+ break;
+ case BCONTEXT_VIEW_LAYER:
#ifdef WITH_FREESTYLE
- if (buttons_context_linestyle_pinnable(C, view_layer)) {
- found = buttons_context_path_linestyle(path, window);
- if (found) {
- break;
- }
- }
+ if (buttons_context_linestyle_pinnable(C, view_layer)) {
+ found = buttons_context_path_linestyle(path, window);
+ if (found) {
+ break;
+ }
+ }
#endif
- found = buttons_context_path_view_layer(path, window);
- break;
- case BCONTEXT_WORLD:
- found = buttons_context_path_world(path);
- break;
- case BCONTEXT_TOOL:
- found = true;
- break;
- case BCONTEXT_OBJECT:
- case BCONTEXT_PHYSICS:
- case BCONTEXT_CONSTRAINT:
- found = buttons_context_path_object(path);
- break;
- case BCONTEXT_MODIFIER:
- found = buttons_context_path_modifier(path);
- break;
- case BCONTEXT_SHADERFX:
- found = buttons_context_path_shaderfx(path);
- break;
- case BCONTEXT_DATA:
- found = buttons_context_path_data(path, -1);
- break;
- case BCONTEXT_PARTICLE:
- found = buttons_context_path_particle(path);
- break;
- case BCONTEXT_MATERIAL:
- found = buttons_context_path_material(path);
- break;
- case BCONTEXT_TEXTURE:
- found = buttons_context_path_texture(C, path, sbuts->texuser);
- break;
- case BCONTEXT_BONE:
- found = buttons_context_path_bone(path);
- if (!found) {
- found = buttons_context_path_data(path, OB_ARMATURE);
- }
- break;
- case BCONTEXT_BONE_CONSTRAINT:
- found = buttons_context_path_pose_bone(path);
- break;
- default:
- found = 0;
- break;
- }
-
- return found;
+ found = buttons_context_path_view_layer(path, window);
+ break;
+ case BCONTEXT_WORLD:
+ found = buttons_context_path_world(path);
+ break;
+ case BCONTEXT_TOOL:
+ found = true;
+ break;
+ case BCONTEXT_OBJECT:
+ case BCONTEXT_PHYSICS:
+ case BCONTEXT_CONSTRAINT:
+ found = buttons_context_path_object(path);
+ break;
+ case BCONTEXT_MODIFIER:
+ found = buttons_context_path_modifier(path);
+ break;
+ case BCONTEXT_SHADERFX:
+ found = buttons_context_path_shaderfx(path);
+ break;
+ case BCONTEXT_DATA:
+ found = buttons_context_path_data(path, -1);
+ break;
+ case BCONTEXT_PARTICLE:
+ found = buttons_context_path_particle(path);
+ break;
+ case BCONTEXT_MATERIAL:
+ found = buttons_context_path_material(path);
+ break;
+ case BCONTEXT_TEXTURE:
+ found = buttons_context_path_texture(C, path, sbuts->texuser);
+ break;
+ case BCONTEXT_BONE:
+ found = buttons_context_path_bone(path);
+ if (!found) {
+ found = buttons_context_path_data(path, OB_ARMATURE);
+ }
+ break;
+ case BCONTEXT_BONE_CONSTRAINT:
+ found = buttons_context_path_pose_bone(path);
+ break;
+ default:
+ found = 0;
+ break;
+ }
+
+ return found;
}
static int buttons_shading_context(const bContext *C, int mainb)
{
- wmWindow *window = CTX_wm_window(C);
- ViewLayer *view_layer = WM_window_get_active_view_layer(window);
- Object *ob = OBACT(view_layer);
-
- if (ELEM(mainb, BCONTEXT_MATERIAL, BCONTEXT_WORLD, BCONTEXT_TEXTURE)) {
- return 1;
- }
- if (mainb == BCONTEXT_DATA && ob && ELEM(ob->type, OB_LAMP, OB_CAMERA)) {
- return 1;
- }
-
- return 0;
+ wmWindow *window = CTX_wm_window(C);
+ ViewLayer *view_layer = WM_window_get_active_view_layer(window);
+ Object *ob = OBACT(view_layer);
+
+ if (ELEM(mainb, BCONTEXT_MATERIAL, BCONTEXT_WORLD, BCONTEXT_TEXTURE)) {
+ return 1;
+ }
+ if (mainb == BCONTEXT_DATA && ob && ELEM(ob->type, OB_LAMP, OB_CAMERA)) {
+ return 1;
+ }
+
+ return 0;
}
static int buttons_shading_new_context(const bContext *C, int flag)
{
- wmWindow *window = CTX_wm_window(C);
- ViewLayer *view_layer = WM_window_get_active_view_layer(window);
- Object *ob = OBACT(view_layer);
-
- if (flag & (1 << BCONTEXT_MATERIAL)) {
- return BCONTEXT_MATERIAL;
- }
- else if (ob && ELEM(ob->type, OB_LAMP, OB_CAMERA) && (flag & (1 << BCONTEXT_DATA))) {
- return BCONTEXT_DATA;
- }
- else if (flag & (1 << BCONTEXT_WORLD)) {
- return BCONTEXT_WORLD;
- }
-
- return BCONTEXT_RENDER;
+ wmWindow *window = CTX_wm_window(C);
+ ViewLayer *view_layer = WM_window_get_active_view_layer(window);
+ Object *ob = OBACT(view_layer);
+
+ if (flag & (1 << BCONTEXT_MATERIAL)) {
+ return BCONTEXT_MATERIAL;
+ }
+ else if (ob && ELEM(ob->type, OB_LAMP, OB_CAMERA) && (flag & (1 << BCONTEXT_DATA))) {
+ return BCONTEXT_DATA;
+ }
+ else if (flag & (1 << BCONTEXT_WORLD)) {
+ return BCONTEXT_WORLD;
+ }
+
+ return BCONTEXT_RENDER;
}
void buttons_context_compute(const bContext *C, SpaceProperties *sbuts)
{
- ButsContextPath *path;
- PointerRNA *ptr;
- int a, pflag = 0, flag = 0;
-
- if (!sbuts->path) {
- sbuts->path = MEM_callocN(sizeof(ButsContextPath), "ButsContextPath");
- }
-
- path = sbuts->path;
-
- /* Set scene path. */
- buttons_context_path(C, path, BCONTEXT_SCENE, pflag);
-
- buttons_texture_context_compute(C, sbuts);
-
- /* for each context, see if we can compute a valid path to it, if
- * this is the case, we know we have to display the button */
- for (a = 0; a < BCONTEXT_TOT; a++) {
- if (buttons_context_path(C, path, a, pflag)) {
- flag |= (1 << a);
-
- /* setting icon for data context */
- if (a == BCONTEXT_DATA) {
- ptr = &path->ptr[path->len - 1];
-
- if (ptr->type) {
- if (RNA_struct_is_a(ptr->type, &RNA_Light)) {
- sbuts->dataicon = ICON_OUTLINER_DATA_LIGHT;
- }
- else {
- sbuts->dataicon = RNA_struct_ui_icon(ptr->type);
- }
- }
- else {
- sbuts->dataicon = ICON_EMPTY_DATA;
- }
- }
- }
- }
-
- /* always try to use the tab that was explicitly
- * set to the user, so that once that context comes
- * back, the tab is activated again */
- sbuts->mainb = sbuts->mainbuser;
-
- /* in case something becomes invalid, change */
- if ((flag & (1 << sbuts->mainb)) == 0) {
- if (sbuts->flag & SB_SHADING_CONTEXT) {
- /* try to keep showing shading related buttons */
- sbuts->mainb = buttons_shading_new_context(C, flag);
- }
- else if (flag & BCONTEXT_OBJECT) {
- sbuts->mainb = BCONTEXT_OBJECT;
- }
- else {
- for (a = 0; a < BCONTEXT_TOT; a++) {
- if (flag & (1 << a)) {
- sbuts->mainb = a;
- break;
- }
- }
- }
- }
-
- buttons_context_path(C, path, sbuts->mainb, pflag);
-
- if (!(flag & (1 << sbuts->mainb))) {
- if (flag & (1 << BCONTEXT_OBJECT)) {
- sbuts->mainb = BCONTEXT_OBJECT;
- }
- else {
- sbuts->mainb = BCONTEXT_SCENE;
- }
- }
-
- if (buttons_shading_context(C, sbuts->mainb)) {
- sbuts->flag |= SB_SHADING_CONTEXT;
- }
- else {
- sbuts->flag &= ~SB_SHADING_CONTEXT;
- }
-
- sbuts->pathflag = flag;
+ ButsContextPath *path;
+ PointerRNA *ptr;
+ int a, pflag = 0, flag = 0;
+
+ if (!sbuts->path) {
+ sbuts->path = MEM_callocN(sizeof(ButsContextPath), "ButsContextPath");
+ }
+
+ path = sbuts->path;
+
+ /* Set scene path. */
+ buttons_context_path(C, path, BCONTEXT_SCENE, pflag);
+
+ buttons_texture_context_compute(C, sbuts);
+
+ /* for each context, see if we can compute a valid path to it, if
+ * this is the case, we know we have to display the button */
+ for (a = 0; a < BCONTEXT_TOT; a++) {
+ if (buttons_context_path(C, path, a, pflag)) {
+ flag |= (1 << a);
+
+ /* setting icon for data context */
+ if (a == BCONTEXT_DATA) {
+ ptr = &path->ptr[path->len - 1];
+
+ if (ptr->type) {
+ if (RNA_struct_is_a(ptr->type, &RNA_Light)) {
+ sbuts->dataicon = ICON_OUTLINER_DATA_LIGHT;
+ }
+ else {
+ sbuts->dataicon = RNA_struct_ui_icon(ptr->type);
+ }
+ }
+ else {
+ sbuts->dataicon = ICON_EMPTY_DATA;
+ }
+ }
+ }
+ }
+
+ /* always try to use the tab that was explicitly
+ * set to the user, so that once that context comes
+ * back, the tab is activated again */
+ sbuts->mainb = sbuts->mainbuser;
+
+ /* in case something becomes invalid, change */
+ if ((flag & (1 << sbuts->mainb)) == 0) {
+ if (sbuts->flag & SB_SHADING_CONTEXT) {
+ /* try to keep showing shading related buttons */
+ sbuts->mainb = buttons_shading_new_context(C, flag);
+ }
+ else if (flag & BCONTEXT_OBJECT) {
+ sbuts->mainb = BCONTEXT_OBJECT;
+ }
+ else {
+ for (a = 0; a < BCONTEXT_TOT; a++) {
+ if (flag & (1 << a)) {
+ sbuts->mainb = a;
+ break;
+ }
+ }
+ }
+ }
+
+ buttons_context_path(C, path, sbuts->mainb, pflag);
+
+ if (!(flag & (1 << sbuts->mainb))) {
+ if (flag & (1 << BCONTEXT_OBJECT)) {
+ sbuts->mainb = BCONTEXT_OBJECT;
+ }
+ else {
+ sbuts->mainb = BCONTEXT_SCENE;
+ }
+ }
+
+ if (buttons_shading_context(C, sbuts->mainb)) {
+ sbuts->flag |= SB_SHADING_CONTEXT;
+ }
+ else {
+ sbuts->flag &= ~SB_SHADING_CONTEXT;
+ }
+
+ sbuts->pathflag = flag;
}
/************************* Context Callback ************************/
const char *buttons_context_dir[] = {
- "texture_slot", "scene", "world", "object", "mesh", "armature", "lattice", "curve",
- "meta_ball", "light", "speaker", "lightprobe", "camera", "material", "material_slot",
- "texture", "texture_user", "texture_user_property", "bone", "edit_bone",
- "pose_bone", "particle_system", "particle_system_editable", "particle_settings",
- "cloth", "soft_body", "fluid", "smoke", "collision", "brush", "dynamic_paint",
- "line_style", "collection", "gpencil", NULL,
+ "texture_slot",
+ "scene",
+ "world",
+ "object",
+ "mesh",
+ "armature",
+ "lattice",
+ "curve",
+ "meta_ball",
+ "light",
+ "speaker",
+ "lightprobe",
+ "camera",
+ "material",
+ "material_slot",
+ "texture",
+ "texture_user",
+ "texture_user_property",
+ "bone",
+ "edit_bone",
+ "pose_bone",
+ "particle_system",
+ "particle_system_editable",
+ "particle_settings",
+ "cloth",
+ "soft_body",
+ "fluid",
+ "smoke",
+ "collision",
+ "brush",
+ "dynamic_paint",
+ "line_style",
+ "collection",
+ "gpencil",
+ NULL,
};
int buttons_context(const bContext *C, const char *member, bContextDataResult *result)
{
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
- ButsContextPath *path = sbuts ? sbuts->path : NULL;
-
- if (!path) {
- return 0;
- }
-
- /* here we handle context, getting data from precomputed path */
- if (CTX_data_dir(member)) {
- /* in case of new shading system we skip texture_slot, complex python
- * UI script logic depends on checking if this is available */
- if (sbuts->texuser) {
- CTX_data_dir_set(result, buttons_context_dir + 1);
- }
- else {
- CTX_data_dir_set(result, buttons_context_dir);
- }
- return 1;
- }
- else if (CTX_data_equals(member, "scene")) {
- /* Do not return one here if scene not found in path,
- * in this case we want to get default context scene! */
- return set_pointer_type(path, result, &RNA_Scene);
- }
- else if (CTX_data_equals(member, "world")) {
- set_pointer_type(path, result, &RNA_World);
- return 1;
- }
- else if (CTX_data_equals(member, "object")) {
- set_pointer_type(path, result, &RNA_Object);
- return 1;
- }
- else if (CTX_data_equals(member, "mesh")) {
- set_pointer_type(path, result, &RNA_Mesh);
- return 1;
- }
- else if (CTX_data_equals(member, "armature")) {
- set_pointer_type(path, result, &RNA_Armature);
- return 1;
- }
- else if (CTX_data_equals(member, "lattice")) {
- set_pointer_type(path, result, &RNA_Lattice);
- return 1;
- }
- else if (CTX_data_equals(member, "curve")) {
- set_pointer_type(path, result, &RNA_Curve);
- return 1;
- }
- else if (CTX_data_equals(member, "meta_ball")) {
- set_pointer_type(path, result, &RNA_MetaBall);
- return 1;
- }
- else if (CTX_data_equals(member, "light")) {
- set_pointer_type(path, result, &RNA_Light);
- return 1;
- }
- else if (CTX_data_equals(member, "camera")) {
- set_pointer_type(path, result, &RNA_Camera);
- return 1;
- }
- else if (CTX_data_equals(member, "speaker")) {
- set_pointer_type(path, result, &RNA_Speaker);
- return 1;
- }
- else if (CTX_data_equals(member, "lightprobe")) {
- set_pointer_type(path, result, &RNA_LightProbe);
- return 1;
- }
- else if (CTX_data_equals(member, "material")) {
- set_pointer_type(path, result, &RNA_Material);
- return 1;
- }
- else if (CTX_data_equals(member, "texture")) {
- ButsContextTexture *ct = sbuts->texuser;
-
- if (ct) {
- CTX_data_pointer_set(result, &ct->texture->id, &RNA_Texture, ct->texture);
- }
-
- return 1;
- }
- else if (CTX_data_equals(member, "material_slot")) {
- PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
-
- if (ptr) {
- Object *ob = ptr->data;
-
- if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type) && ob->totcol) {
- /* a valid actcol isn't ensured [#27526] */
- int matnr = ob->actcol - 1;
- if (matnr < 0) {
- matnr = 0;
- }
- CTX_data_pointer_set(result, &ob->id, &RNA_MaterialSlot, &ob->mat[matnr]);
- }
- }
-
- return 1;
- }
- else if (CTX_data_equals(member, "texture_user")) {
- ButsContextTexture *ct = sbuts->texuser;
-
- if (!ct) {
- return -1;
- }
-
- if (ct->user && ct->user->ptr.data) {
- ButsTextureUser *user = ct->user;
- CTX_data_pointer_set(result, user->ptr.id.data, user->ptr.type, user->ptr.data);
- }
-
- return 1;
- }
- else if (CTX_data_equals(member, "texture_user_property")) {
- ButsContextTexture *ct = sbuts->texuser;
-
- if (!ct) {
- return -1;
- }
-
- if (ct->user && ct->user->ptr.data) {
- ButsTextureUser *user = ct->user;
- CTX_data_pointer_set(result, NULL, &RNA_Property, user->prop);
- }
-
- return 1;
- }
- else if (CTX_data_equals(member, "texture_node")) {
- ButsContextTexture *ct = sbuts->texuser;
-
- if (ct) {
- /* new shading system */
- if (ct->user && ct->user->node) {
- CTX_data_pointer_set(result, &ct->user->ntree->id, &RNA_Node, ct->user->node);
- }
-
- return 1;
- }
- }
- else if (CTX_data_equals(member, "texture_slot")) {
- ButsContextTexture *ct = sbuts->texuser;
- PointerRNA *ptr;
-
- /* Particles slots are used in both old and new textures handling. */
- if ((ptr = get_pointer_type(path, &RNA_ParticleSystem))) {
- ParticleSettings *part = ((ParticleSystem *)ptr->data)->part;
-
- if (part) {
- CTX_data_pointer_set(result, &part->id, &RNA_ParticleSettingsTextureSlot, part->mtex[(int)part->texact]);
- }
- }
- else if (ct) {
- return 0; /* new shading system */
- }
- else if ((ptr = get_pointer_type(path, &RNA_FreestyleLineStyle))) {
- FreestyleLineStyle *ls = ptr->data;
-
- if (ls) {
- CTX_data_pointer_set(result, &ls->id, &RNA_LineStyleTextureSlot, ls->mtex[(int)ls->texact]);
- }
- }
-
- return 1;
- }
- else if (CTX_data_equals(member, "bone")) {
- set_pointer_type(path, result, &RNA_Bone);
- return 1;
- }
- else if (CTX_data_equals(member, "edit_bone")) {
- set_pointer_type(path, result, &RNA_EditBone);
- return 1;
- }
- else if (CTX_data_equals(member, "pose_bone")) {
- set_pointer_type(path, result, &RNA_PoseBone);
- return 1;
- }
- else if (CTX_data_equals(member, "particle_system")) {
- set_pointer_type(path, result, &RNA_ParticleSystem);
- return 1;
- }
- else if (CTX_data_equals(member, "particle_system_editable")) {
- if (PE_poll((bContext *)C)) {
- set_pointer_type(path, result, &RNA_ParticleSystem);
- }
- else {
- CTX_data_pointer_set(result, NULL, &RNA_ParticleSystem, NULL);
- }
- return 1;
- }
- else if (CTX_data_equals(member, "particle_settings")) {
- /* only available when pinned */
- PointerRNA *ptr = get_pointer_type(path, &RNA_ParticleSettings);
-
- if (ptr && ptr->data) {
- CTX_data_pointer_set(result, ptr->id.data, &RNA_ParticleSettings, ptr->data);
- return 1;
- }
- else {
- /* get settings from active particle system instead */
- ptr = get_pointer_type(path, &RNA_ParticleSystem);
-
- if (ptr && ptr->data) {
- ParticleSettings *part = ((ParticleSystem *)ptr->data)->part;
- CTX_data_pointer_set(result, ptr->id.data, &RNA_ParticleSettings, part);
- return 1;
- }
- }
- set_pointer_type(path, result, &RNA_ParticleSettings);
- return 1;
- }
- else if (CTX_data_equals(member, "cloth")) {
- PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
-
- if (ptr && ptr->data) {
- Object *ob = ptr->data;
- ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
- CTX_data_pointer_set(result, &ob->id, &RNA_ClothModifier, md);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "soft_body")) {
- PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
-
- if (ptr && ptr->data) {
- Object *ob = ptr->data;
- ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody);
- CTX_data_pointer_set(result, &ob->id, &RNA_SoftBodyModifier, md);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "fluid")) {
- PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
-
- if (ptr && ptr->data) {
- Object *ob = ptr->data;
- ModifierData *md = modifiers_findByType(ob, eModifierType_Fluidsim);
- CTX_data_pointer_set(result, &ob->id, &RNA_FluidSimulationModifier, md);
- return 1;
- }
- }
-
- else if (CTX_data_equals(member, "smoke")) {
- PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
-
- if (ptr && ptr->data) {
- Object *ob = ptr->data;
- ModifierData *md = modifiers_findByType(ob, eModifierType_Smoke);
- CTX_data_pointer_set(result, &ob->id, &RNA_SmokeModifier, md);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "collision")) {
- PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
-
- if (ptr && ptr->data) {
- Object *ob = ptr->data;
- ModifierData *md = modifiers_findByType(ob, eModifierType_Collision);
- CTX_data_pointer_set(result, &ob->id, &RNA_CollisionModifier, md);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "brush")) {
- set_pointer_type(path, result, &RNA_Brush);
- return 1;
- }
- else if (CTX_data_equals(member, "dynamic_paint")) {
- PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
-
- if (ptr && ptr->data) {
- Object *ob = ptr->data;
- ModifierData *md = modifiers_findByType(ob, eModifierType_DynamicPaint);
- CTX_data_pointer_set(result, &ob->id, &RNA_DynamicPaintModifier, md);
- return 1;
- }
- }
- else if (CTX_data_equals(member, "line_style")) {
- set_pointer_type(path, result, &RNA_FreestyleLineStyle);
- return 1;
- }
- else if (CTX_data_equals(member, "gpencil")) {
- set_pointer_type(path, result, &RNA_GreasePencil);
- return 1;
- }
- else {
- return 0; /* not found */
- }
-
- return -1; /* found but not available */
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ ButsContextPath *path = sbuts ? sbuts->path : NULL;
+
+ if (!path) {
+ return 0;
+ }
+
+ /* here we handle context, getting data from precomputed path */
+ if (CTX_data_dir(member)) {
+ /* in case of new shading system we skip texture_slot, complex python
+ * UI script logic depends on checking if this is available */
+ if (sbuts->texuser) {
+ CTX_data_dir_set(result, buttons_context_dir + 1);
+ }
+ else {
+ CTX_data_dir_set(result, buttons_context_dir);
+ }
+ return 1;
+ }
+ else if (CTX_data_equals(member, "scene")) {
+ /* Do not return one here if scene not found in path,
+ * in this case we want to get default context scene! */
+ return set_pointer_type(path, result, &RNA_Scene);
+ }
+ else if (CTX_data_equals(member, "world")) {
+ set_pointer_type(path, result, &RNA_World);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "object")) {
+ set_pointer_type(path, result, &RNA_Object);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "mesh")) {
+ set_pointer_type(path, result, &RNA_Mesh);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "armature")) {
+ set_pointer_type(path, result, &RNA_Armature);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "lattice")) {
+ set_pointer_type(path, result, &RNA_Lattice);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "curve")) {
+ set_pointer_type(path, result, &RNA_Curve);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "meta_ball")) {
+ set_pointer_type(path, result, &RNA_MetaBall);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "light")) {
+ set_pointer_type(path, result, &RNA_Light);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "camera")) {
+ set_pointer_type(path, result, &RNA_Camera);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "speaker")) {
+ set_pointer_type(path, result, &RNA_Speaker);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "lightprobe")) {
+ set_pointer_type(path, result, &RNA_LightProbe);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "material")) {
+ set_pointer_type(path, result, &RNA_Material);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "texture")) {
+ ButsContextTexture *ct = sbuts->texuser;
+
+ if (ct) {
+ CTX_data_pointer_set(result, &ct->texture->id, &RNA_Texture, ct->texture);
+ }
+
+ return 1;
+ }
+ else if (CTX_data_equals(member, "material_slot")) {
+ PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
+
+ if (ptr) {
+ Object *ob = ptr->data;
+
+ if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type) && ob->totcol) {
+ /* a valid actcol isn't ensured [#27526] */
+ int matnr = ob->actcol - 1;
+ if (matnr < 0) {
+ matnr = 0;
+ }
+ CTX_data_pointer_set(result, &ob->id, &RNA_MaterialSlot, &ob->mat[matnr]);
+ }
+ }
+
+ return 1;
+ }
+ else if (CTX_data_equals(member, "texture_user")) {
+ ButsContextTexture *ct = sbuts->texuser;
+
+ if (!ct) {
+ return -1;
+ }
+
+ if (ct->user && ct->user->ptr.data) {
+ ButsTextureUser *user = ct->user;
+ CTX_data_pointer_set(result, user->ptr.id.data, user->ptr.type, user->ptr.data);
+ }
+
+ return 1;
+ }
+ else if (CTX_data_equals(member, "texture_user_property")) {
+ ButsContextTexture *ct = sbuts->texuser;
+
+ if (!ct) {
+ return -1;
+ }
+
+ if (ct->user && ct->user->ptr.data) {
+ ButsTextureUser *user = ct->user;
+ CTX_data_pointer_set(result, NULL, &RNA_Property, user->prop);
+ }
+
+ return 1;
+ }
+ else if (CTX_data_equals(member, "texture_node")) {
+ ButsContextTexture *ct = sbuts->texuser;
+
+ if (ct) {
+ /* new shading system */
+ if (ct->user && ct->user->node) {
+ CTX_data_pointer_set(result, &ct->user->ntree->id, &RNA_Node, ct->user->node);
+ }
+
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "texture_slot")) {
+ ButsContextTexture *ct = sbuts->texuser;
+ PointerRNA *ptr;
+
+ /* Particles slots are used in both old and new textures handling. */
+ if ((ptr = get_pointer_type(path, &RNA_ParticleSystem))) {
+ ParticleSettings *part = ((ParticleSystem *)ptr->data)->part;
+
+ if (part) {
+ CTX_data_pointer_set(
+ result, &part->id, &RNA_ParticleSettingsTextureSlot, part->mtex[(int)part->texact]);
+ }
+ }
+ else if (ct) {
+ return 0; /* new shading system */
+ }
+ else if ((ptr = get_pointer_type(path, &RNA_FreestyleLineStyle))) {
+ FreestyleLineStyle *ls = ptr->data;
+
+ if (ls) {
+ CTX_data_pointer_set(
+ result, &ls->id, &RNA_LineStyleTextureSlot, ls->mtex[(int)ls->texact]);
+ }
+ }
+
+ return 1;
+ }
+ else if (CTX_data_equals(member, "bone")) {
+ set_pointer_type(path, result, &RNA_Bone);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "edit_bone")) {
+ set_pointer_type(path, result, &RNA_EditBone);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "pose_bone")) {
+ set_pointer_type(path, result, &RNA_PoseBone);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "particle_system")) {
+ set_pointer_type(path, result, &RNA_ParticleSystem);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "particle_system_editable")) {
+ if (PE_poll((bContext *)C)) {
+ set_pointer_type(path, result, &RNA_ParticleSystem);
+ }
+ else {
+ CTX_data_pointer_set(result, NULL, &RNA_ParticleSystem, NULL);
+ }
+ return 1;
+ }
+ else if (CTX_data_equals(member, "particle_settings")) {
+ /* only available when pinned */
+ PointerRNA *ptr = get_pointer_type(path, &RNA_ParticleSettings);
+
+ if (ptr && ptr->data) {
+ CTX_data_pointer_set(result, ptr->id.data, &RNA_ParticleSettings, ptr->data);
+ return 1;
+ }
+ else {
+ /* get settings from active particle system instead */
+ ptr = get_pointer_type(path, &RNA_ParticleSystem);
+
+ if (ptr && ptr->data) {
+ ParticleSettings *part = ((ParticleSystem *)ptr->data)->part;
+ CTX_data_pointer_set(result, ptr->id.data, &RNA_ParticleSettings, part);
+ return 1;
+ }
+ }
+ set_pointer_type(path, result, &RNA_ParticleSettings);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "cloth")) {
+ PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
+
+ if (ptr && ptr->data) {
+ Object *ob = ptr->data;
+ ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
+ CTX_data_pointer_set(result, &ob->id, &RNA_ClothModifier, md);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "soft_body")) {
+ PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
+
+ if (ptr && ptr->data) {
+ Object *ob = ptr->data;
+ ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody);
+ CTX_data_pointer_set(result, &ob->id, &RNA_SoftBodyModifier, md);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "fluid")) {
+ PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
+
+ if (ptr && ptr->data) {
+ Object *ob = ptr->data;
+ ModifierData *md = modifiers_findByType(ob, eModifierType_Fluidsim);
+ CTX_data_pointer_set(result, &ob->id, &RNA_FluidSimulationModifier, md);
+ return 1;
+ }
+ }
+
+ else if (CTX_data_equals(member, "smoke")) {
+ PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
+
+ if (ptr && ptr->data) {
+ Object *ob = ptr->data;
+ ModifierData *md = modifiers_findByType(ob, eModifierType_Smoke);
+ CTX_data_pointer_set(result, &ob->id, &RNA_SmokeModifier, md);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "collision")) {
+ PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
+
+ if (ptr && ptr->data) {
+ Object *ob = ptr->data;
+ ModifierData *md = modifiers_findByType(ob, eModifierType_Collision);
+ CTX_data_pointer_set(result, &ob->id, &RNA_CollisionModifier, md);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "brush")) {
+ set_pointer_type(path, result, &RNA_Brush);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "dynamic_paint")) {
+ PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
+
+ if (ptr && ptr->data) {
+ Object *ob = ptr->data;
+ ModifierData *md = modifiers_findByType(ob, eModifierType_DynamicPaint);
+ CTX_data_pointer_set(result, &ob->id, &RNA_DynamicPaintModifier, md);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "line_style")) {
+ set_pointer_type(path, result, &RNA_FreestyleLineStyle);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "gpencil")) {
+ set_pointer_type(path, result, &RNA_GreasePencil);
+ return 1;
+ }
+ else {
+ return 0; /* not found */
+ }
+
+ return -1; /* found but not available */
}
/************************* Drawing the Path ************************/
static void pin_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
{
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
- if (sbuts->flag & SB_PIN_CONTEXT) {
- sbuts->pinid = buttons_context_id_path(C);
- }
- else {
- sbuts->pinid = NULL;
- }
+ if (sbuts->flag & SB_PIN_CONTEXT) {
+ sbuts->pinid = buttons_context_id_path(C);
+ }
+ else {
+ sbuts->pinid = NULL;
+ }
- ED_area_tag_redraw(CTX_wm_area(C));
+ ED_area_tag_redraw(CTX_wm_area(C));
}
void buttons_context_draw(const bContext *C, uiLayout *layout)
{
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
- ButsContextPath *path = sbuts->path;
- uiLayout *row;
- uiBlock *block;
- uiBut *but;
- PointerRNA *ptr;
- char namebuf[128], *name;
- int a, icon;
- bool first = true;
-
- if (!path) {
- return;
- }
-
- row = uiLayoutRow(layout, true);
- uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
-
- for (a = 0; a < path->len; a++) {
- ptr = &path->ptr[a];
-
- /* Skip scene and view layer to save space. */
- if ((!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_OUTPUT, BCONTEXT_SCENE, BCONTEXT_VIEW_LAYER, BCONTEXT_WORLD) && ptr->type == &RNA_Scene)) {
- continue;
- }
- else if ((!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_OUTPUT, BCONTEXT_SCENE, BCONTEXT_VIEW_LAYER, BCONTEXT_WORLD) && ptr->type == &RNA_ViewLayer)) {
- continue;
- }
-
- /* Add > triangle. */
- if (!first) {
- uiItemL(row, "", ICON_SMALL_TRI_RIGHT_VEC);
- }
- else {
- first = false;
- }
-
- /* Add icon + name .*/
- if (ptr->data) {
- icon = RNA_struct_ui_icon(ptr->type);
- name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL);
-
- if (name) {
- uiItemLDrag(row, ptr, name, icon);
-
- if (name != namebuf) {
- MEM_freeN(name);
- }
- }
- else {
- uiItemL(row, "", icon);
- }
- }
- }
-
- uiItemSpacer(row);
-
- block = uiLayoutGetBlock(row);
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- but = uiDefIconButBitC(block, UI_BTYPE_ICON_TOGGLE, SB_PIN_CONTEXT, 0, ICON_UNPINNED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &sbuts->flag,
- 0, 0, 0, 0, TIP_("Follow context or keep fixed data-block displayed"));
- UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
- UI_but_func_set(but, pin_cb, NULL, NULL);
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ ButsContextPath *path = sbuts->path;
+ uiLayout *row;
+ uiBlock *block;
+ uiBut *but;
+ PointerRNA *ptr;
+ char namebuf[128], *name;
+ int a, icon;
+ bool first = true;
+
+ if (!path) {
+ return;
+ }
+
+ row = uiLayoutRow(layout, true);
+ uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
+
+ for (a = 0; a < path->len; a++) {
+ ptr = &path->ptr[a];
+
+ /* Skip scene and view layer to save space. */
+ if ((!ELEM(sbuts->mainb,
+ BCONTEXT_RENDER,
+ BCONTEXT_OUTPUT,
+ BCONTEXT_SCENE,
+ BCONTEXT_VIEW_LAYER,
+ BCONTEXT_WORLD) &&
+ ptr->type == &RNA_Scene)) {
+ continue;
+ }
+ else if ((!ELEM(sbuts->mainb,
+ BCONTEXT_RENDER,
+ BCONTEXT_OUTPUT,
+ BCONTEXT_SCENE,
+ BCONTEXT_VIEW_LAYER,
+ BCONTEXT_WORLD) &&
+ ptr->type == &RNA_ViewLayer)) {
+ continue;
+ }
+
+ /* Add > triangle. */
+ if (!first) {
+ uiItemL(row, "", ICON_SMALL_TRI_RIGHT_VEC);
+ }
+ else {
+ first = false;
+ }
+
+ /* Add icon + name .*/
+ if (ptr->data) {
+ icon = RNA_struct_ui_icon(ptr->type);
+ name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL);
+
+ if (name) {
+ uiItemLDrag(row, ptr, name, icon);
+
+ if (name != namebuf) {
+ MEM_freeN(name);
+ }
+ }
+ else {
+ uiItemL(row, "", icon);
+ }
+ }
+ }
+
+ uiItemSpacer(row);
+
+ block = uiLayoutGetBlock(row);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ but = uiDefIconButBitC(block,
+ UI_BTYPE_ICON_TOGGLE,
+ SB_PIN_CONTEXT,
+ 0,
+ ICON_UNPINNED,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &sbuts->flag,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Follow context or keep fixed data-block displayed"));
+ UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+ UI_but_func_set(but, pin_cb, NULL, NULL);
}
#ifdef USE_HEADER_CONTEXT_PATH
@@ -1126,8 +1187,8 @@ static bool buttons_header_context_poll(const bContext *C, HeaderType *UNUSED(ht
static bool buttons_panel_context_poll(const bContext *C, PanelType *UNUSED(pt))
#endif
{
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
- return (sbuts->mainb != BCONTEXT_TOOL);
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ return (sbuts->mainb != BCONTEXT_TOOL);
}
#ifdef USE_HEADER_CONTEXT_PATH
@@ -1136,59 +1197,59 @@ static void buttons_header_context_draw(const bContext *C, Header *ptr)
static void buttons_panel_context_draw(const bContext *C, Panel *ptr)
#endif
{
- buttons_context_draw(C, ptr->layout);
+ buttons_context_draw(C, ptr->layout);
}
void buttons_context_register(ARegionType *art)
{
#ifdef USE_HEADER_CONTEXT_PATH
- HeaderType *ht;
-
- ht = MEM_callocN(sizeof(HeaderType), "spacetype buttons context header");
- strcpy(ht->idname, "BUTTONS_HT_context");
- ht->space_type = SPACE_PROPERTIES;
- ht->region_type = art->regionid;
- ht->poll = buttons_header_context_poll;
- ht->draw = buttons_header_context_draw;
- BLI_addtail(&art->headertypes, ht);
+ HeaderType *ht;
+
+ ht = MEM_callocN(sizeof(HeaderType), "spacetype buttons context header");
+ strcpy(ht->idname, "BUTTONS_HT_context");
+ ht->space_type = SPACE_PROPERTIES;
+ ht->region_type = art->regionid;
+ ht->poll = buttons_header_context_poll;
+ ht->draw = buttons_header_context_draw;
+ BLI_addtail(&art->headertypes, ht);
#else
- PanelType *pt;
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype buttons panel context");
- strcpy(pt->idname, "BUTTONS_PT_context");
- strcpy(pt->label, N_("Context")); /* XXX C panels unavailable through RNA bpy.types! */
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->poll = buttons_panel_context_poll;
- pt->draw = buttons_panel_context_draw;
- pt->flag = PNL_NO_HEADER;
- BLI_addtail(&art->paneltypes, pt);
+ PanelType *pt;
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype buttons panel context");
+ strcpy(pt->idname, "BUTTONS_PT_context");
+ strcpy(pt->label, N_("Context")); /* XXX C panels unavailable through RNA bpy.types! */
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->poll = buttons_panel_context_poll;
+ pt->draw = buttons_panel_context_draw;
+ pt->flag = PNL_NO_HEADER;
+ BLI_addtail(&art->paneltypes, pt);
#endif
}
ID *buttons_context_id_path(const bContext *C)
{
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
- ButsContextPath *path = sbuts->path;
- PointerRNA *ptr;
- int a;
-
- if (path->len) {
- for (a = path->len - 1; a >= 0; a--) {
- ptr = &path->ptr[a];
-
- /* 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;
- return &psys->part->id;
- }
- }
-
- if (ptr->id.data) {
- return ptr->id.data;
- }
- }
- }
-
- return NULL;
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ ButsContextPath *path = sbuts->path;
+ PointerRNA *ptr;
+ int a;
+
+ if (path->len) {
+ for (a = path->len - 1; a >= 0; a--) {
+ ptr = &path->ptr[a];
+
+ /* 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;
+ return &psys->part->id;
+ }
+ }
+
+ if (ptr->id.data) {
+ return ptr->id.data;
+ }
+ }
+ }
+
+ return NULL;
}
diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h
index fa7f0408e15..64166f15ea3 100644
--- a/source/blender/editors/space_buttons/buttons_intern.h
+++ b/source/blender/editors/space_buttons/buttons_intern.h
@@ -44,44 +44,46 @@ struct wmOperatorType;
/* context data */
typedef struct ButsContextPath {
- PointerRNA ptr[8];
- int len;
- int flag;
- int collection_ctx;
+ PointerRNA ptr[8];
+ int len;
+ int flag;
+ int collection_ctx;
} ButsContextPath;
typedef struct ButsTextureUser {
- struct ButsTextureUser *next, *prev;
+ struct ButsTextureUser *next, *prev;
- struct ID *id;
+ struct ID *id;
- PointerRNA ptr;
- PropertyRNA *prop;
+ PointerRNA ptr;
+ PropertyRNA *prop;
- struct bNodeTree *ntree;
- struct bNode *node;
+ struct bNodeTree *ntree;
+ struct bNode *node;
- const char *category;
- int icon;
- const char *name;
+ const char *category;
+ int icon;
+ const char *name;
- int index;
+ int index;
} ButsTextureUser;
typedef struct ButsContextTexture {
- ListBase users;
+ ListBase users;
- struct Tex *texture;
+ struct Tex *texture;
- struct ButsTextureUser *user;
- int index;
+ struct ButsTextureUser *user;
+ int index;
} ButsContextTexture;
/* internal exports only */
/* buttons_context.c */
void buttons_context_compute(const struct bContext *C, struct SpaceProperties *sbuts);
-int buttons_context(const struct bContext *C, const char *member, struct bContextDataResult *result);
+int buttons_context(const struct bContext *C,
+ const char *member,
+ struct bContextDataResult *result);
void buttons_context_draw(const struct bContext *C, struct uiLayout *layout);
void buttons_context_register(struct ARegionType *art);
struct ID *buttons_context_id_path(const struct bContext *C);
diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c
index 3ae88f9cc78..fe4ed0209bf 100644
--- a/source/blender/editors/space_buttons/buttons_ops.c
+++ b/source/blender/editors/space_buttons/buttons_ops.c
@@ -21,7 +21,6 @@
* \ingroup spbuttons
*/
-
#include <stdlib.h>
#include <string.h>
@@ -51,240 +50,251 @@
#include "UI_interface.h"
#include "UI_resources.h"
-#include "buttons_intern.h" /* own include */
+#include "buttons_intern.h" /* own include */
/********************** context_menu operator *********************/
static int context_menu_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
- const ARegion *ar = CTX_wm_region(C);
- uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Context Menu"), ICON_NONE);
- uiLayout *layout = UI_popup_menu_layout(pup);
+ const ARegion *ar = CTX_wm_region(C);
+ uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Context Menu"), ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
- uiItemM(layout, "INFO_MT_area", NULL, ICON_NONE);
- if (ar->regiontype == RGN_TYPE_NAV_BAR) {
- ED_screens_navigation_bar_tools_menu_create(C, layout, NULL);
- }
+ uiItemM(layout, "INFO_MT_area", NULL, ICON_NONE);
+ if (ar->regiontype == RGN_TYPE_NAV_BAR) {
+ ED_screens_navigation_bar_tools_menu_create(C, layout, NULL);
+ }
- UI_popup_menu_end(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
void BUTTONS_OT_context_menu(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Context Menu";
- ot->description = "Display properties editor context_menu";
- ot->idname = "BUTTONS_OT_context_menu";
-
- /* api callbacks */
- ot->invoke = context_menu_invoke;
- ot->poll = ED_operator_buttons_active;
+ /* identifiers */
+ ot->name = "Context Menu";
+ ot->description = "Display properties editor context_menu";
+ ot->idname = "BUTTONS_OT_context_menu";
+
+ /* api callbacks */
+ ot->invoke = context_menu_invoke;
+ ot->poll = ED_operator_buttons_active;
}
/********************** filebrowse operator *********************/
typedef struct FileBrowseOp {
- PointerRNA ptr;
- PropertyRNA *prop;
- bool is_undo;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ bool is_undo;
} FileBrowseOp;
static int file_browse_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- FileBrowseOp *fbo = op->customdata;
- ID *id;
- char *str, path[FILE_MAX];
- const char *path_prop = RNA_struct_find_property(op->ptr, "directory") ? "directory" : "filepath";
-
- if (RNA_struct_property_is_set(op->ptr, path_prop) == 0 || fbo == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- str = RNA_string_get_alloc(op->ptr, path_prop, NULL, 0);
-
- /* add slash for directories, important for some properties */
- if (RNA_property_subtype(fbo->prop) == PROP_DIRPATH) {
- const bool is_relative = RNA_boolean_get(op->ptr, "relative_path");
- id = fbo->ptr.id.data;
-
- BLI_strncpy(path, str, FILE_MAX);
- BLI_path_abs(path, id ? ID_BLEND_PATH(bmain, id) : BKE_main_blendfile_path(bmain));
-
- if (BLI_is_dir(path)) {
- /* do this first so '//' isnt converted to '//\' on windows */
- BLI_add_slash(path);
- if (is_relative) {
- BLI_strncpy(path, str, FILE_MAX);
- BLI_path_rel(path, BKE_main_blendfile_path(bmain));
- str = MEM_reallocN(str, strlen(path) + 2);
- BLI_strncpy(str, path, FILE_MAX);
- }
- else {
- str = MEM_reallocN(str, strlen(str) + 2);
- }
- }
- else {
- char * const lslash = (char *)BLI_last_slash(str);
- if (lslash) {
- lslash[1] = '\0';
- }
- }
- }
-
- RNA_property_string_set(&fbo->ptr, fbo->prop, str);
- RNA_property_update(C, &fbo->ptr, fbo->prop);
- MEM_freeN(str);
-
- if (fbo->is_undo) {
- const char *undostr = RNA_property_identifier(fbo->prop);
- ED_undo_push(C, undostr);
- }
-
- /* special, annoying exception, filesel on redo panel [#26618] */
- {
- wmOperator *redo_op = WM_operator_last_redo(C);
- if (redo_op) {
- if (fbo->ptr.data == redo_op->ptr->data) {
- ED_undo_operator_repeat(C, redo_op);
- }
- }
- }
-
- MEM_freeN(op->customdata);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ FileBrowseOp *fbo = op->customdata;
+ ID *id;
+ char *str, path[FILE_MAX];
+ const char *path_prop = RNA_struct_find_property(op->ptr, "directory") ? "directory" :
+ "filepath";
+
+ if (RNA_struct_property_is_set(op->ptr, path_prop) == 0 || fbo == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ str = RNA_string_get_alloc(op->ptr, path_prop, NULL, 0);
+
+ /* add slash for directories, important for some properties */
+ if (RNA_property_subtype(fbo->prop) == PROP_DIRPATH) {
+ const bool is_relative = RNA_boolean_get(op->ptr, "relative_path");
+ id = fbo->ptr.id.data;
+
+ BLI_strncpy(path, str, FILE_MAX);
+ BLI_path_abs(path, id ? ID_BLEND_PATH(bmain, id) : BKE_main_blendfile_path(bmain));
+
+ if (BLI_is_dir(path)) {
+ /* do this first so '//' isnt converted to '//\' on windows */
+ BLI_add_slash(path);
+ if (is_relative) {
+ BLI_strncpy(path, str, FILE_MAX);
+ BLI_path_rel(path, BKE_main_blendfile_path(bmain));
+ str = MEM_reallocN(str, strlen(path) + 2);
+ BLI_strncpy(str, path, FILE_MAX);
+ }
+ else {
+ str = MEM_reallocN(str, strlen(str) + 2);
+ }
+ }
+ else {
+ char *const lslash = (char *)BLI_last_slash(str);
+ if (lslash) {
+ lslash[1] = '\0';
+ }
+ }
+ }
+
+ RNA_property_string_set(&fbo->ptr, fbo->prop, str);
+ RNA_property_update(C, &fbo->ptr, fbo->prop);
+ MEM_freeN(str);
+
+ if (fbo->is_undo) {
+ const char *undostr = RNA_property_identifier(fbo->prop);
+ ED_undo_push(C, undostr);
+ }
+
+ /* special, annoying exception, filesel on redo panel [#26618] */
+ {
+ wmOperator *redo_op = WM_operator_last_redo(C);
+ if (redo_op) {
+ if (fbo->ptr.data == redo_op->ptr->data) {
+ ED_undo_operator_repeat(C, redo_op);
+ }
+ }
+ }
+
+ MEM_freeN(op->customdata);
+
+ return OPERATOR_FINISHED;
}
static void file_browse_cancel(bContext *UNUSED(C), wmOperator *op)
{
- MEM_freeN(op->customdata);
- op->customdata = NULL;
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
}
static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- PointerRNA ptr;
- PropertyRNA *prop;
- bool is_undo;
- FileBrowseOp *fbo;
- char *str;
-
- if (CTX_wm_space_file(C)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot activate a file selector, one already open");
- return OPERATOR_CANCELLED;
- }
-
- UI_context_active_but_prop_get_filebrowser(C, &ptr, &prop, &is_undo);
-
- if (!prop) {
- return OPERATOR_CANCELLED;
- }
-
- str = RNA_property_string_get_alloc(&ptr, prop, NULL, 0, NULL);
-
- /* useful yet irritating feature, Shift+Click to open the file
- * Alt+Click to browse a folder in the OS's browser */
- if (event->shift || event->alt) {
- wmOperatorType *ot = WM_operatortype_find("WM_OT_path_open", true);
- PointerRNA props_ptr;
-
- if (event->alt) {
- char *lslash = (char *)BLI_last_slash(str);
- if (lslash) {
- *lslash = '\0';
- }
- }
-
-
- WM_operator_properties_create_ptr(&props_ptr, ot);
- RNA_string_set(&props_ptr, "filepath", str);
- WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr);
- WM_operator_properties_free(&props_ptr);
-
- MEM_freeN(str);
- return OPERATOR_CANCELLED;
- }
- else {
- PropertyRNA *prop_relpath;
- const char *path_prop = RNA_struct_find_property(op->ptr, "directory") ? "directory" : "filepath";
- fbo = MEM_callocN(sizeof(FileBrowseOp), "FileBrowseOp");
- fbo->ptr = ptr;
- fbo->prop = prop;
- fbo->is_undo = is_undo;
- op->customdata = fbo;
-
- /* normally ED_fileselect_get_params would handle this but we need to because of stupid
- * user-prefs exception - campbell */
- if ((prop_relpath = RNA_struct_find_property(op->ptr, "relative_path"))) {
- if (!RNA_property_is_set(op->ptr, prop_relpath)) {
- bool is_relative = (U.flag & USER_RELPATHS) != 0;
-
- /* while we want to follow the defaults,
- * we better not switch existing paths relative/absolute state. */
- if (str[0]) {
- is_relative = BLI_path_is_rel(str);
- }
-
- if (UNLIKELY(ptr.data == &U)) {
- is_relative = false;
- }
-
- /* annoying exception!, if were dealing with the user prefs, default relative to be off */
- RNA_property_boolean_set(op->ptr, prop_relpath, is_relative);
- }
- }
-
- RNA_string_set(op->ptr, path_prop, str);
- MEM_freeN(str);
-
- WM_event_add_fileselect(C, op);
-
- return OPERATOR_RUNNING_MODAL;
- }
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ bool is_undo;
+ FileBrowseOp *fbo;
+ char *str;
+
+ if (CTX_wm_space_file(C)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot activate a file selector, one already open");
+ return OPERATOR_CANCELLED;
+ }
+
+ UI_context_active_but_prop_get_filebrowser(C, &ptr, &prop, &is_undo);
+
+ if (!prop) {
+ return OPERATOR_CANCELLED;
+ }
+
+ str = RNA_property_string_get_alloc(&ptr, prop, NULL, 0, NULL);
+
+ /* useful yet irritating feature, Shift+Click to open the file
+ * Alt+Click to browse a folder in the OS's browser */
+ if (event->shift || event->alt) {
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_path_open", true);
+ PointerRNA props_ptr;
+
+ if (event->alt) {
+ char *lslash = (char *)BLI_last_slash(str);
+ if (lslash) {
+ *lslash = '\0';
+ }
+ }
+
+ WM_operator_properties_create_ptr(&props_ptr, ot);
+ RNA_string_set(&props_ptr, "filepath", str);
+ WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr);
+ WM_operator_properties_free(&props_ptr);
+
+ MEM_freeN(str);
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ PropertyRNA *prop_relpath;
+ const char *path_prop = RNA_struct_find_property(op->ptr, "directory") ? "directory" :
+ "filepath";
+ fbo = MEM_callocN(sizeof(FileBrowseOp), "FileBrowseOp");
+ fbo->ptr = ptr;
+ fbo->prop = prop;
+ fbo->is_undo = is_undo;
+ op->customdata = fbo;
+
+ /* normally ED_fileselect_get_params would handle this but we need to because of stupid
+ * user-prefs exception - campbell */
+ if ((prop_relpath = RNA_struct_find_property(op->ptr, "relative_path"))) {
+ if (!RNA_property_is_set(op->ptr, prop_relpath)) {
+ bool is_relative = (U.flag & USER_RELPATHS) != 0;
+
+ /* while we want to follow the defaults,
+ * we better not switch existing paths relative/absolute state. */
+ if (str[0]) {
+ is_relative = BLI_path_is_rel(str);
+ }
+
+ if (UNLIKELY(ptr.data == &U)) {
+ is_relative = false;
+ }
+
+ /* annoying exception!, if were dealing with the user prefs, default relative to be off */
+ RNA_property_boolean_set(op->ptr, prop_relpath, is_relative);
+ }
+ }
+
+ RNA_string_set(op->ptr, path_prop, str);
+ MEM_freeN(str);
+
+ WM_event_add_fileselect(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
}
void BUTTONS_OT_file_browse(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Accept";
- ot->description = "Open a file browser, Hold Shift to open the file, Alt to browse containing directory";
- ot->idname = "BUTTONS_OT_file_browse";
-
- /* api callbacks */
- ot->invoke = file_browse_invoke;
- ot->exec = file_browse_exec;
- ot->cancel = file_browse_cancel;
-
- /* conditional undo based on button flag */
- ot->flag = 0;
-
- /* properties */
- WM_operator_properties_filesel(
- ot, 0, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+ /* identifiers */
+ ot->name = "Accept";
+ ot->description =
+ "Open a file browser, Hold Shift to open the file, Alt to browse containing directory";
+ ot->idname = "BUTTONS_OT_file_browse";
+
+ /* api callbacks */
+ ot->invoke = file_browse_invoke;
+ ot->exec = file_browse_exec;
+ ot->cancel = file_browse_cancel;
+
+ /* conditional undo based on button flag */
+ ot->flag = 0;
+
+ /* properties */
+ WM_operator_properties_filesel(ot,
+ 0,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
}
/* second operator, only difference from BUTTONS_OT_file_browse is WM_FILESEL_DIRECTORY */
void BUTTONS_OT_directory_browse(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Accept";
- ot->description = "Open a directory browser, Hold Shift to open the file, Alt to browse containing directory";
- ot->idname = "BUTTONS_OT_directory_browse";
-
- /* api callbacks */
- ot->invoke = file_browse_invoke;
- ot->exec = file_browse_exec;
- ot->cancel = file_browse_cancel;
-
- /* conditional undo based on button flag */
- ot->flag = 0;
-
- /* properties */
- WM_operator_properties_filesel(
- ot, 0, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+ /* identifiers */
+ ot->name = "Accept";
+ ot->description =
+ "Open a directory browser, Hold Shift to open the file, Alt to browse containing directory";
+ ot->idname = "BUTTONS_OT_directory_browse";
+
+ /* api callbacks */
+ ot->invoke = file_browse_invoke;
+ ot->exec = file_browse_exec;
+ ot->cancel = file_browse_cancel;
+
+ /* conditional undo based on button flag */
+ ot->flag = 0;
+
+ /* properties */
+ WM_operator_properties_filesel(ot,
+ 0,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
}
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 7c1355b6b3c..b9b83abf670 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -21,7 +21,6 @@
* \ingroup spbuttons
*/
-
#include <stdlib.h>
#include <string.h>
@@ -72,458 +71,518 @@
#include "../interface/interface_intern.h"
-#include "buttons_intern.h" // own include
+#include "buttons_intern.h" // own include
/************************* Texture User **************************/
-static void buttons_texture_user_property_add(ListBase *users, ID *id,
- PointerRNA ptr, PropertyRNA *prop,
- const char *category, int icon, const char *name)
+static void buttons_texture_user_property_add(ListBase *users,
+ ID *id,
+ PointerRNA ptr,
+ PropertyRNA *prop,
+ const char *category,
+ int icon,
+ const char *name)
{
- ButsTextureUser *user = MEM_callocN(sizeof(ButsTextureUser), "ButsTextureUser");
+ ButsTextureUser *user = MEM_callocN(sizeof(ButsTextureUser), "ButsTextureUser");
- user->id = id;
- user->ptr = ptr;
- user->prop = prop;
- user->category = category;
- user->icon = icon;
- user->name = name;
- user->index = BLI_listbase_count(users);
+ user->id = id;
+ user->ptr = ptr;
+ user->prop = prop;
+ user->category = category;
+ user->icon = icon;
+ user->name = name;
+ user->index = BLI_listbase_count(users);
- BLI_addtail(users, user);
+ BLI_addtail(users, user);
}
-static void buttons_texture_user_node_add(ListBase *users, ID *id,
- bNodeTree *ntree, bNode *node,
- const char *category, int icon, const char *name)
+static void buttons_texture_user_node_add(ListBase *users,
+ ID *id,
+ bNodeTree *ntree,
+ bNode *node,
+ const char *category,
+ int icon,
+ const char *name)
{
- ButsTextureUser *user = MEM_callocN(sizeof(ButsTextureUser), "ButsTextureUser");
+ ButsTextureUser *user = MEM_callocN(sizeof(ButsTextureUser), "ButsTextureUser");
- user->id = id;
- user->ntree = ntree;
- user->node = node;
- user->category = category;
- user->icon = icon;
- user->name = name;
- user->index = BLI_listbase_count(users);
+ user->id = id;
+ user->ntree = ntree;
+ user->node = node;
+ user->category = category;
+ user->icon = icon;
+ user->name = name;
+ user->index = BLI_listbase_count(users);
- BLI_addtail(users, user);
+ BLI_addtail(users, user);
}
-static void buttons_texture_users_find_nodetree(ListBase *users, ID *id,
- bNodeTree *ntree, const char *category)
+static void buttons_texture_users_find_nodetree(ListBase *users,
+ ID *id,
+ bNodeTree *ntree,
+ const char *category)
{
- bNode *node;
-
- if (ntree) {
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
- PointerRNA ptr;
- /* PropertyRNA *prop; */ /* UNUSED */
-
- RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
- /* prop = RNA_struct_find_property(&ptr, "texture"); */ /* UNUSED */
-
- buttons_texture_user_node_add(users, id, ntree, node,
- category, RNA_struct_ui_icon(ptr.type), node->name);
- }
- else if (node->type == NODE_GROUP && node->id) {
- buttons_texture_users_find_nodetree(users, id, (bNodeTree *)node->id, category);
- }
- }
- }
+ bNode *node;
+
+ if (ntree) {
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
+ PointerRNA ptr;
+ /* PropertyRNA *prop; */ /* UNUSED */
+
+ RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
+ /* prop = RNA_struct_find_property(&ptr, "texture"); */ /* UNUSED */
+
+ buttons_texture_user_node_add(
+ users, id, ntree, node, category, RNA_struct_ui_icon(ptr.type), node->name);
+ }
+ else if (node->type == NODE_GROUP && node->id) {
+ buttons_texture_users_find_nodetree(users, id, (bNodeTree *)node->id, category);
+ }
+ }
+ }
}
-static void buttons_texture_modifier_foreach(void *userData, Object *ob, ModifierData *md, const char *propname)
+static void buttons_texture_modifier_foreach(void *userData,
+ Object *ob,
+ ModifierData *md,
+ const char *propname)
{
- PointerRNA ptr;
- PropertyRNA *prop;
- ListBase *users = userData;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ ListBase *users = userData;
- RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr);
- prop = RNA_struct_find_property(&ptr, propname);
+ RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr);
+ prop = RNA_struct_find_property(&ptr, propname);
- buttons_texture_user_property_add(users, &ob->id, ptr, prop,
- N_("Modifiers"), RNA_struct_ui_icon(ptr.type), md->name);
+ buttons_texture_user_property_add(
+ users, &ob->id, ptr, prop, N_("Modifiers"), RNA_struct_ui_icon(ptr.type), md->name);
}
-static void buttons_texture_modifier_gpencil_foreach(void *userData, Object *ob, GpencilModifierData *md, const char *propname)
+static void buttons_texture_modifier_gpencil_foreach(void *userData,
+ Object *ob,
+ GpencilModifierData *md,
+ const char *propname)
{
- PointerRNA ptr;
- PropertyRNA *prop;
- ListBase *users = userData;
-
- RNA_pointer_create(&ob->id, &RNA_GpencilModifier, md, &ptr);
- prop = RNA_struct_find_property(&ptr, propname);
-
- buttons_texture_user_property_add(
- users, &ob->id, ptr, prop,
- N_("Grease Pencil Modifiers"), RNA_struct_ui_icon(ptr.type), md->name);
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ ListBase *users = userData;
+
+ RNA_pointer_create(&ob->id, &RNA_GpencilModifier, md, &ptr);
+ prop = RNA_struct_find_property(&ptr, propname);
+
+ buttons_texture_user_property_add(users,
+ &ob->id,
+ ptr,
+ prop,
+ N_("Grease Pencil Modifiers"),
+ RNA_struct_ui_icon(ptr.type),
+ md->name);
}
-static void buttons_texture_users_from_context(ListBase *users, const bContext *C, SpaceProperties *sbuts)
+static void buttons_texture_users_from_context(ListBase *users,
+ const bContext *C,
+ SpaceProperties *sbuts)
{
- Scene *scene = NULL;
- Object *ob = NULL;
- FreestyleLineStyle *linestyle = NULL;
- Brush *brush = NULL;
- ID *pinid = sbuts->pinid;
- bool limited_mode = (sbuts->flag & SB_TEX_USER_LIMITED) != 0;
-
- /* get data from context */
- if (pinid) {
- if (GS(pinid->name) == ID_SCE) {
- scene = (Scene *)pinid;
- }
- else if (GS(pinid->name) == ID_OB) {
- ob = (Object *)pinid;
- }
- else if (GS(pinid->name) == ID_BR) {
- brush = (Brush *)pinid;
- }
- else if (GS(pinid->name) == ID_LS) {
- linestyle = (FreestyleLineStyle *)pinid;
- }
- }
-
- if (!scene) {
- scene = CTX_data_scene(C);
- }
-
- const ID_Type id_type = pinid != NULL ? GS(pinid->name) : -1;
- if (!pinid || id_type == ID_SCE) {
- wmWindow *win = CTX_wm_window(C);
- ViewLayer *view_layer = (win->scene == scene) ?
- WM_window_get_active_view_layer(win) :
- BKE_view_layer_default_view(scene);
-
- brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
- linestyle = BKE_linestyle_active_from_view_layer(view_layer);
- ob = OBACT(view_layer);
- }
-
- /* fill users */
- BLI_listbase_clear(users);
-
- if (linestyle && !limited_mode) {
- buttons_texture_users_find_nodetree(users, &linestyle->id, linestyle->nodetree, N_("Line Style"));
- }
-
- if (ob) {
- ParticleSystem *psys = psys_get_current(ob);
- MTex *mtex;
- int a;
-
- /* modifiers */
- modifiers_foreachTexLink(ob, buttons_texture_modifier_foreach, users);
-
- /* grease pencil modifiers */
- BKE_gpencil_modifiers_foreachTexLink(ob, buttons_texture_modifier_gpencil_foreach, users);
-
- /* particle systems */
- if (psys && !limited_mode) {
- for (a = 0; a < MAX_MTEX; a++) {
- mtex = psys->part->mtex[a];
-
- if (mtex) {
- PointerRNA ptr;
- PropertyRNA *prop;
-
- RNA_pointer_create(&psys->part->id, &RNA_ParticleSettingsTextureSlot, mtex, &ptr);
- prop = RNA_struct_find_property(&ptr, "texture");
-
- buttons_texture_user_property_add(users, &psys->part->id, ptr, prop, N_("Particles"),
- RNA_struct_ui_icon(&RNA_ParticleSettings), psys->name);
- }
- }
- }
-
- /* field */
- if (ob->pd && ob->pd->forcefield == PFIELD_TEXTURE) {
- PointerRNA ptr;
- PropertyRNA *prop;
-
- RNA_pointer_create(&ob->id, &RNA_FieldSettings, ob->pd, &ptr);
- prop = RNA_struct_find_property(&ptr, "texture");
-
- buttons_texture_user_property_add(users, &ob->id, ptr, prop,
- N_("Fields"), ICON_FORCE_TEXTURE, IFACE_("Texture Field"));
- }
- }
-
- /* brush */
- if (brush) {
- PointerRNA ptr;
- PropertyRNA *prop;
-
- /* texture */
- RNA_pointer_create(&brush->id, &RNA_BrushTextureSlot, &brush->mtex, &ptr);
- prop = RNA_struct_find_property(&ptr, "texture");
-
- buttons_texture_user_property_add(users, &brush->id, ptr, prop,
- N_("Brush"), ICON_BRUSH_DATA, IFACE_("Brush"));
-
- /* mask texture */
- RNA_pointer_create(&brush->id, &RNA_BrushTextureSlot, &brush->mask_mtex, &ptr);
- prop = RNA_struct_find_property(&ptr, "texture");
-
- buttons_texture_user_property_add(users, &brush->id, ptr, prop,
- N_("Brush"), ICON_BRUSH_DATA, IFACE_("Brush Mask"));
- }
+ Scene *scene = NULL;
+ Object *ob = NULL;
+ FreestyleLineStyle *linestyle = NULL;
+ Brush *brush = NULL;
+ ID *pinid = sbuts->pinid;
+ bool limited_mode = (sbuts->flag & SB_TEX_USER_LIMITED) != 0;
+
+ /* get data from context */
+ if (pinid) {
+ if (GS(pinid->name) == ID_SCE) {
+ scene = (Scene *)pinid;
+ }
+ else if (GS(pinid->name) == ID_OB) {
+ ob = (Object *)pinid;
+ }
+ else if (GS(pinid->name) == ID_BR) {
+ brush = (Brush *)pinid;
+ }
+ else if (GS(pinid->name) == ID_LS) {
+ linestyle = (FreestyleLineStyle *)pinid;
+ }
+ }
+
+ if (!scene) {
+ scene = CTX_data_scene(C);
+ }
+
+ const ID_Type id_type = pinid != NULL ? GS(pinid->name) : -1;
+ if (!pinid || id_type == ID_SCE) {
+ wmWindow *win = CTX_wm_window(C);
+ ViewLayer *view_layer = (win->scene == scene) ? WM_window_get_active_view_layer(win) :
+ BKE_view_layer_default_view(scene);
+
+ brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
+ linestyle = BKE_linestyle_active_from_view_layer(view_layer);
+ ob = OBACT(view_layer);
+ }
+
+ /* fill users */
+ BLI_listbase_clear(users);
+
+ if (linestyle && !limited_mode) {
+ buttons_texture_users_find_nodetree(
+ users, &linestyle->id, linestyle->nodetree, N_("Line Style"));
+ }
+
+ if (ob) {
+ ParticleSystem *psys = psys_get_current(ob);
+ MTex *mtex;
+ int a;
+
+ /* modifiers */
+ modifiers_foreachTexLink(ob, buttons_texture_modifier_foreach, users);
+
+ /* grease pencil modifiers */
+ BKE_gpencil_modifiers_foreachTexLink(ob, buttons_texture_modifier_gpencil_foreach, users);
+
+ /* particle systems */
+ if (psys && !limited_mode) {
+ for (a = 0; a < MAX_MTEX; a++) {
+ mtex = psys->part->mtex[a];
+
+ if (mtex) {
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ RNA_pointer_create(&psys->part->id, &RNA_ParticleSettingsTextureSlot, mtex, &ptr);
+ prop = RNA_struct_find_property(&ptr, "texture");
+
+ buttons_texture_user_property_add(users,
+ &psys->part->id,
+ ptr,
+ prop,
+ N_("Particles"),
+ RNA_struct_ui_icon(&RNA_ParticleSettings),
+ psys->name);
+ }
+ }
+ }
+
+ /* field */
+ if (ob->pd && ob->pd->forcefield == PFIELD_TEXTURE) {
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ RNA_pointer_create(&ob->id, &RNA_FieldSettings, ob->pd, &ptr);
+ prop = RNA_struct_find_property(&ptr, "texture");
+
+ buttons_texture_user_property_add(
+ users, &ob->id, ptr, prop, N_("Fields"), ICON_FORCE_TEXTURE, IFACE_("Texture Field"));
+ }
+ }
+
+ /* brush */
+ if (brush) {
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ /* texture */
+ RNA_pointer_create(&brush->id, &RNA_BrushTextureSlot, &brush->mtex, &ptr);
+ prop = RNA_struct_find_property(&ptr, "texture");
+
+ buttons_texture_user_property_add(
+ users, &brush->id, ptr, prop, N_("Brush"), ICON_BRUSH_DATA, IFACE_("Brush"));
+
+ /* mask texture */
+ RNA_pointer_create(&brush->id, &RNA_BrushTextureSlot, &brush->mask_mtex, &ptr);
+ prop = RNA_struct_find_property(&ptr, "texture");
+
+ buttons_texture_user_property_add(
+ users, &brush->id, ptr, prop, N_("Brush"), ICON_BRUSH_DATA, IFACE_("Brush Mask"));
+ }
}
void buttons_texture_context_compute(const bContext *C, SpaceProperties *sbuts)
{
- /* gather available texture users in context. runs on every draw of
- * properties editor, before the buttons are created. */
- ButsContextTexture *ct = sbuts->texuser;
- ID *pinid = sbuts->pinid;
-
- if (!ct) {
- ct = MEM_callocN(sizeof(ButsContextTexture), "ButsContextTexture");
- sbuts->texuser = ct;
- }
- else {
- BLI_freelistN(&ct->users);
- }
-
- buttons_texture_users_from_context(&ct->users, C, sbuts);
-
- if (pinid && GS(pinid->name) == ID_TE) {
- ct->user = NULL;
- ct->texture = (Tex *)pinid;
- }
- else {
- /* set one user as active based on active index */
- if (ct->index >= BLI_listbase_count_at_most(&ct->users, ct->index + 1)) {
- ct->index = 0;
- }
-
- ct->user = BLI_findlink(&ct->users, ct->index);
- ct->texture = NULL;
-
- if (ct->user) {
- if (ct->user->ptr.data) {
- PointerRNA texptr;
- Tex *tex;
-
- /* get texture datablock pointer if it's a property */
- texptr = RNA_property_pointer_get(&ct->user->ptr, ct->user->prop);
- tex = (RNA_struct_is_a(texptr.type, &RNA_Texture)) ? texptr.data : NULL;
-
- ct->texture = tex;
- }
- else if (ct->user->node && !(ct->user->node->flag & NODE_ACTIVE_TEXTURE)) {
- ButsTextureUser *user;
-
- /* detect change of active texture node in same node tree, in that
- * case we also automatically switch to the other node */
- for (user = ct->users.first; user; user = user->next) {
- if (user->ntree == ct->user->ntree && user->node != ct->user->node) {
- if (user->node->flag & NODE_ACTIVE_TEXTURE) {
- ct->user = user;
- ct->index = BLI_findindex(&ct->users, user);
- break;
- }
- }
- }
- }
- }
- }
+ /* gather available texture users in context. runs on every draw of
+ * properties editor, before the buttons are created. */
+ ButsContextTexture *ct = sbuts->texuser;
+ ID *pinid = sbuts->pinid;
+
+ if (!ct) {
+ ct = MEM_callocN(sizeof(ButsContextTexture), "ButsContextTexture");
+ sbuts->texuser = ct;
+ }
+ else {
+ BLI_freelistN(&ct->users);
+ }
+
+ buttons_texture_users_from_context(&ct->users, C, sbuts);
+
+ if (pinid && GS(pinid->name) == ID_TE) {
+ ct->user = NULL;
+ ct->texture = (Tex *)pinid;
+ }
+ else {
+ /* set one user as active based on active index */
+ if (ct->index >= BLI_listbase_count_at_most(&ct->users, ct->index + 1)) {
+ ct->index = 0;
+ }
+
+ ct->user = BLI_findlink(&ct->users, ct->index);
+ ct->texture = NULL;
+
+ if (ct->user) {
+ if (ct->user->ptr.data) {
+ PointerRNA texptr;
+ Tex *tex;
+
+ /* get texture datablock pointer if it's a property */
+ texptr = RNA_property_pointer_get(&ct->user->ptr, ct->user->prop);
+ tex = (RNA_struct_is_a(texptr.type, &RNA_Texture)) ? texptr.data : NULL;
+
+ ct->texture = tex;
+ }
+ else if (ct->user->node && !(ct->user->node->flag & NODE_ACTIVE_TEXTURE)) {
+ ButsTextureUser *user;
+
+ /* detect change of active texture node in same node tree, in that
+ * case we also automatically switch to the other node */
+ for (user = ct->users.first; user; user = user->next) {
+ if (user->ntree == ct->user->ntree && user->node != ct->user->node) {
+ if (user->node->flag & NODE_ACTIVE_TEXTURE) {
+ ct->user = user;
+ ct->index = BLI_findindex(&ct->users, user);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
}
static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg))
{
- /* callback when selecting a texture user in the menu */
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
- ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL;
- ButsTextureUser *user = (ButsTextureUser *)user_p;
- PointerRNA texptr;
- Tex *tex;
-
- if (!ct) {
- return;
- }
-
- /* set user as active */
- if (user->node) {
- ED_node_set_active(CTX_data_main(C), user->ntree, user->node);
- ct->texture = NULL;
- }
- else {
- texptr = RNA_property_pointer_get(&user->ptr, user->prop);
- tex = (RNA_struct_is_a(texptr.type, &RNA_Texture)) ? texptr.data : NULL;
-
- ct->texture = tex;
-
- if (user->ptr.type == &RNA_ParticleSettingsTextureSlot) {
- /* stupid exception for particle systems which still uses influence
- * from the old texture system, set the active texture slots as well */
- ParticleSettings *part = user->ptr.id.data;
- int a;
-
- for (a = 0; a < MAX_MTEX; a++) {
- if (user->ptr.data == part->mtex[a]) {
- part->texact = a;
- }
- }
- }
-
- if (sbuts && tex) {
- sbuts->preview = 1;
- }
- }
-
- ct->user = user;
- ct->index = user->index;
+ /* callback when selecting a texture user in the menu */
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL;
+ ButsTextureUser *user = (ButsTextureUser *)user_p;
+ PointerRNA texptr;
+ Tex *tex;
+
+ if (!ct) {
+ return;
+ }
+
+ /* set user as active */
+ if (user->node) {
+ ED_node_set_active(CTX_data_main(C), user->ntree, user->node);
+ ct->texture = NULL;
+ }
+ else {
+ texptr = RNA_property_pointer_get(&user->ptr, user->prop);
+ tex = (RNA_struct_is_a(texptr.type, &RNA_Texture)) ? texptr.data : NULL;
+
+ ct->texture = tex;
+
+ if (user->ptr.type == &RNA_ParticleSettingsTextureSlot) {
+ /* stupid exception for particle systems which still uses influence
+ * from the old texture system, set the active texture slots as well */
+ ParticleSettings *part = user->ptr.id.data;
+ int a;
+
+ for (a = 0; a < MAX_MTEX; a++) {
+ if (user->ptr.data == part->mtex[a]) {
+ part->texact = a;
+ }
+ }
+ }
+
+ if (sbuts && tex) {
+ sbuts->preview = 1;
+ }
+ }
+
+ ct->user = user;
+ ct->index = user->index;
}
static void template_texture_user_menu(bContext *C, uiLayout *layout, void *UNUSED(arg))
{
- /* callback when opening texture user selection menu, to create buttons. */
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
- ButsContextTexture *ct = sbuts->texuser;
- ButsTextureUser *user;
- uiBlock *block = uiLayoutGetBlock(layout);
- const char *last_category = NULL;
-
- for (user = ct->users.first; user; user = user->next) {
- uiBut *but;
- char name[UI_MAX_NAME_STR];
-
- /* add label per category */
- if (!last_category || !STREQ(last_category, user->category)) {
- uiItemL(layout, IFACE_(user->category), ICON_NONE);
- but = block->buttons.last;
- but->drawflag = UI_BUT_TEXT_LEFT;
- }
-
- /* create button */
- if (user->prop) {
- PointerRNA texptr = RNA_property_pointer_get(&user->ptr, user->prop);
- Tex *tex = texptr.data;
-
- if (tex) {
- BLI_snprintf(name, UI_MAX_NAME_STR, " %s - %s", user->name, tex->id.name + 2);
- }
- else {
- BLI_snprintf(name, UI_MAX_NAME_STR, " %s", user->name);
- }
- }
- else {
- BLI_snprintf(name, UI_MAX_NAME_STR, " %s", user->name);
- }
-
- but = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, user->icon, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, "");
- UI_but_funcN_set(but, template_texture_select, MEM_dupallocN(user), NULL);
-
- last_category = user->category;
- }
-
- UI_block_flag_enable(block, UI_BLOCK_NO_FLIP);
+ /* callback when opening texture user selection menu, to create buttons. */
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ ButsContextTexture *ct = sbuts->texuser;
+ ButsTextureUser *user;
+ uiBlock *block = uiLayoutGetBlock(layout);
+ const char *last_category = NULL;
+
+ for (user = ct->users.first; user; user = user->next) {
+ uiBut *but;
+ char name[UI_MAX_NAME_STR];
+
+ /* add label per category */
+ if (!last_category || !STREQ(last_category, user->category)) {
+ uiItemL(layout, IFACE_(user->category), ICON_NONE);
+ but = block->buttons.last;
+ but->drawflag = UI_BUT_TEXT_LEFT;
+ }
+
+ /* create button */
+ if (user->prop) {
+ PointerRNA texptr = RNA_property_pointer_get(&user->ptr, user->prop);
+ Tex *tex = texptr.data;
+
+ if (tex) {
+ BLI_snprintf(name, UI_MAX_NAME_STR, " %s - %s", user->name, tex->id.name + 2);
+ }
+ else {
+ BLI_snprintf(name, UI_MAX_NAME_STR, " %s", user->name);
+ }
+ }
+ else {
+ BLI_snprintf(name, UI_MAX_NAME_STR, " %s", user->name);
+ }
+
+ but = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ user->icon,
+ name,
+ 0,
+ 0,
+ UI_UNIT_X * 4,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ "");
+ UI_but_funcN_set(but, template_texture_select, MEM_dupallocN(user), NULL);
+
+ last_category = user->category;
+ }
+
+ UI_block_flag_enable(block, UI_BLOCK_NO_FLIP);
}
void uiTemplateTextureUser(uiLayout *layout, bContext *C)
{
- /* texture user selection dropdown menu. the available users have been
- * gathered before drawing in ButsContextTexture, we merely need to
- * display the current item. */
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
- ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL;
- uiBlock *block = uiLayoutGetBlock(layout);
- uiBut *but;
- ButsTextureUser *user;
- char name[UI_MAX_NAME_STR];
-
- if (!ct) {
- return;
- }
-
- /* get current user */
- user = ct->user;
-
- if (!user) {
- uiItemL(layout, IFACE_("No textures in context"), ICON_NONE);
- return;
- }
-
- /* create button */
- BLI_strncpy(name, user->name, UI_MAX_NAME_STR);
-
- if (user->icon) {
- but = uiDefIconTextMenuBut(block, template_texture_user_menu, NULL,
- user->icon, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y, "");
- }
- else {
- but = uiDefMenuBut(block, template_texture_user_menu, NULL,
- name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y, "");
- }
-
- /* some cosmetic tweaks */
- UI_but_type_set_menu_from_pulldown(but);
-
- but->flag &= ~UI_BUT_ICON_SUBMENU;
+ /* texture user selection dropdown menu. the available users have been
+ * gathered before drawing in ButsContextTexture, we merely need to
+ * display the current item. */
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL;
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiBut *but;
+ ButsTextureUser *user;
+ char name[UI_MAX_NAME_STR];
+
+ if (!ct) {
+ return;
+ }
+
+ /* get current user */
+ user = ct->user;
+
+ if (!user) {
+ uiItemL(layout, IFACE_("No textures in context"), ICON_NONE);
+ return;
+ }
+
+ /* create button */
+ BLI_strncpy(name, user->name, UI_MAX_NAME_STR);
+
+ if (user->icon) {
+ but = uiDefIconTextMenuBut(block,
+ template_texture_user_menu,
+ NULL,
+ user->icon,
+ name,
+ 0,
+ 0,
+ UI_UNIT_X * 4,
+ UI_UNIT_Y,
+ "");
+ }
+ else {
+ but = uiDefMenuBut(
+ block, template_texture_user_menu, NULL, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y, "");
+ }
+
+ /* some cosmetic tweaks */
+ UI_but_type_set_menu_from_pulldown(but);
+
+ but->flag &= ~UI_BUT_ICON_SUBMENU;
}
/************************* Texture Show **************************/
static void template_texture_show(bContext *C, void *data_p, void *prop_p)
{
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
- ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL;
- ButsTextureUser *user;
-
- if (!ct) {
- return;
- }
-
- for (user = ct->users.first; user; user = user->next) {
- if (user->ptr.data == data_p && user->prop == prop_p) {
- break;
- }
- }
-
- if (user) {
- /* select texture */
- template_texture_select(C, user, NULL);
-
- /* change context */
- sbuts->mainb = BCONTEXT_TEXTURE;
- sbuts->mainbuser = sbuts->mainb;
- sbuts->preview = 1;
-
- /* redraw editor */
- ED_area_tag_redraw(CTX_wm_area(C));
- }
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL;
+ ButsTextureUser *user;
+
+ if (!ct) {
+ return;
+ }
+
+ for (user = ct->users.first; user; user = user->next) {
+ if (user->ptr.data == data_p && user->prop == prop_p) {
+ break;
+ }
+ }
+
+ if (user) {
+ /* select texture */
+ template_texture_select(C, user, NULL);
+
+ /* change context */
+ sbuts->mainb = BCONTEXT_TEXTURE;
+ sbuts->mainbuser = sbuts->mainb;
+ sbuts->preview = 1;
+
+ /* redraw editor */
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
}
void uiTemplateTextureShow(uiLayout *layout, bContext *C, PointerRNA *ptr, PropertyRNA *prop)
{
- /* button to quickly show texture in texture tab */
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
- ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL;
- ButsTextureUser *user;
-
- /* only show button in other tabs in properties editor */
- if (!ct || sbuts->mainb == BCONTEXT_TEXTURE) {
- return;
- }
-
- /* find corresponding texture user */
- for (user = ct->users.first; user; user = user->next) {
- if (user->ptr.data == ptr->data && user->prop == prop) {
- break;
- }
- }
-
- /* draw button */
- if (user) {
- uiBlock *block = uiLayoutGetBlock(layout);
- uiBut *but;
-
- but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_PROPERTIES, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Show texture in texture tab"));
- UI_but_func_set(but, template_texture_show, user->ptr.data, user->prop);
- }
+ /* button to quickly show texture in texture tab */
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL;
+ ButsTextureUser *user;
+
+ /* only show button in other tabs in properties editor */
+ if (!ct || sbuts->mainb == BCONTEXT_TEXTURE) {
+ return;
+ }
+
+ /* find corresponding texture user */
+ for (user = ct->users.first; user; user = user->next) {
+ if (user->ptr.data == ptr->data && user->prop == prop) {
+ break;
+ }
+ }
+
+ /* draw button */
+ if (user) {
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiBut *but;
+
+ but = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_PROPERTIES,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Show texture in texture tab"));
+ UI_but_func_set(but, template_texture_show, user->ptr.data, user->prop);
+ }
}
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index 3bf2d632a12..1b1c3bf6d13 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -47,65 +47,65 @@
#include "GPU_glew.h"
-#include "buttons_intern.h" /* own include */
+#include "buttons_intern.h" /* own include */
/* ******************** default callbacks for buttons space ***************** */
static SpaceLink *buttons_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
- SpaceProperties *sbuts;
+ ARegion *ar;
+ SpaceProperties *sbuts;
- sbuts = MEM_callocN(sizeof(SpaceProperties), "initbuts");
- sbuts->spacetype = SPACE_PROPERTIES;
+ sbuts = MEM_callocN(sizeof(SpaceProperties), "initbuts");
+ sbuts->spacetype = SPACE_PROPERTIES;
- sbuts->mainb = sbuts->mainbuser = BCONTEXT_OBJECT;
+ sbuts->mainb = sbuts->mainbuser = BCONTEXT_OBJECT;
- /* header */
- ar = MEM_callocN(sizeof(ARegion), "header for buts");
+ /* header */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_HEADER;
+ ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
- /* navigation bar */
- ar = MEM_callocN(sizeof(ARegion), "navigation bar for buts");
+ /* navigation bar */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_NAV_BAR;
+ ar->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;
+ /* 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;
#endif
- /* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for buts");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for buts");
- BLI_addtail(&sbuts->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&sbuts->regionbase, ar);
+ ar->regiontype = RGN_TYPE_WINDOW;
- return (SpaceLink *)sbuts;
+ return (SpaceLink *)sbuts;
}
/* not spacelink itself */
static void buttons_free(SpaceLink *sl)
{
- SpaceProperties *sbuts = (SpaceProperties *) sl;
+ SpaceProperties *sbuts = (SpaceProperties *)sl;
- if (sbuts->path) {
- MEM_freeN(sbuts->path);
- }
+ if (sbuts->path) {
+ MEM_freeN(sbuts->path);
+ }
- if (sbuts->texuser) {
- ButsContextTexture *ct = sbuts->texuser;
- BLI_freelistN(&ct->users);
- MEM_freeN(ct);
- }
+ if (sbuts->texuser) {
+ ButsContextTexture *ct = sbuts->texuser;
+ BLI_freelistN(&ct->users);
+ MEM_freeN(ct);
+ }
}
/* spacetype; init callback */
@@ -115,650 +115,661 @@ static void buttons_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa)
static SpaceLink *buttons_duplicate(SpaceLink *sl)
{
- SpaceProperties *sbutsn = MEM_dupallocN(sl);
+ SpaceProperties *sbutsn = MEM_dupallocN(sl);
- /* clear or remove stuff from old */
- sbutsn->path = NULL;
- sbutsn->texuser = NULL;
+ /* clear or remove stuff from old */
+ sbutsn->path = NULL;
+ sbutsn->texuser = NULL;
- return (SpaceLink *)sbutsn;
+ return (SpaceLink *)sbutsn;
}
/* add handlers, stuff you only do once or on area/region changes */
static void buttons_main_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, ar);
- keymap = WM_keymap_ensure(wm->defaultconf, "Property Editor", SPACE_PROPERTIES, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Property Editor", SPACE_PROPERTIES, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void buttons_main_region_layout_properties(const bContext *C, SpaceProperties *sbuts, ARegion *ar)
+static void buttons_main_region_layout_properties(const bContext *C,
+ SpaceProperties *sbuts,
+ ARegion *ar)
{
- buttons_context_compute(C, sbuts);
-
- const char *contexts[2] = {NULL, NULL};
-
- switch (sbuts->mainb) {
- case BCONTEXT_SCENE:
- contexts[0] = "scene";
- break;
- case BCONTEXT_RENDER:
- contexts[0] = "render";
- break;
- case BCONTEXT_OUTPUT:
- contexts[0] = "output";
- break;
- case BCONTEXT_VIEW_LAYER:
- contexts[0] = "view_layer";
- break;
- case BCONTEXT_WORLD:
- contexts[0] = "world";
- break;
- case BCONTEXT_OBJECT:
- contexts[0] = "object";
- break;
- case BCONTEXT_DATA:
- contexts[0] = "data";
- break;
- case BCONTEXT_MATERIAL:
- contexts[0] = "material";
- break;
- case BCONTEXT_TEXTURE:
- contexts[0] = "texture";
- break;
- case BCONTEXT_PARTICLE:
- contexts[0] = "particle";
- break;
- case BCONTEXT_PHYSICS:
- contexts[0] = "physics";
- break;
- case BCONTEXT_BONE:
- contexts[0] = "bone";
- break;
- case BCONTEXT_MODIFIER:
- contexts[0] = "modifier";
- break;
- case BCONTEXT_SHADERFX:
- contexts[0] = "shaderfx";
- break;
- case BCONTEXT_CONSTRAINT:
- contexts[0] = "constraint";
- break;
- case BCONTEXT_BONE_CONSTRAINT:
- contexts[0] = "bone_constraint";
- break;
- case BCONTEXT_TOOL:
- contexts[0] = "tool";
- break;
- }
-
- const bool vertical = true;
- ED_region_panels_layout_ex(C, ar, contexts, sbuts->mainb, vertical);
+ buttons_context_compute(C, sbuts);
+
+ const char *contexts[2] = {NULL, NULL};
+
+ switch (sbuts->mainb) {
+ case BCONTEXT_SCENE:
+ contexts[0] = "scene";
+ break;
+ case BCONTEXT_RENDER:
+ contexts[0] = "render";
+ break;
+ case BCONTEXT_OUTPUT:
+ contexts[0] = "output";
+ break;
+ case BCONTEXT_VIEW_LAYER:
+ contexts[0] = "view_layer";
+ break;
+ case BCONTEXT_WORLD:
+ contexts[0] = "world";
+ break;
+ case BCONTEXT_OBJECT:
+ contexts[0] = "object";
+ break;
+ case BCONTEXT_DATA:
+ contexts[0] = "data";
+ break;
+ case BCONTEXT_MATERIAL:
+ contexts[0] = "material";
+ break;
+ case BCONTEXT_TEXTURE:
+ contexts[0] = "texture";
+ break;
+ case BCONTEXT_PARTICLE:
+ contexts[0] = "particle";
+ break;
+ case BCONTEXT_PHYSICS:
+ contexts[0] = "physics";
+ break;
+ case BCONTEXT_BONE:
+ contexts[0] = "bone";
+ break;
+ case BCONTEXT_MODIFIER:
+ contexts[0] = "modifier";
+ break;
+ case BCONTEXT_SHADERFX:
+ contexts[0] = "shaderfx";
+ break;
+ case BCONTEXT_CONSTRAINT:
+ contexts[0] = "constraint";
+ break;
+ case BCONTEXT_BONE_CONSTRAINT:
+ contexts[0] = "bone_constraint";
+ break;
+ case BCONTEXT_TOOL:
+ contexts[0] = "tool";
+ break;
+ }
+
+ const bool vertical = true;
+ ED_region_panels_layout_ex(C, ar, contexts, sbuts->mainb, vertical);
}
static void buttons_main_region_layout_tool(const bContext *C, ARegion *ar)
{
- const WorkSpace *workspace = CTX_wm_workspace(C);
- const enum eContextObjectMode mode = CTX_data_mode_enum(C);
-
- const char *contexts_base[5] = {NULL};
- contexts_base[0] = ".active_tool";
- const char **contexts = &contexts_base[1];
-
- if (workspace->tools_space_type == SPACE_VIEW3D) {
- switch (mode) {
- case CTX_MODE_EDIT_MESH:
- ARRAY_SET_ITEMS(contexts, ".mesh_edit");
- break;
- case CTX_MODE_EDIT_CURVE:
- ARRAY_SET_ITEMS(contexts, ".curve_edit");
- break;
- case CTX_MODE_EDIT_SURFACE:
- ARRAY_SET_ITEMS(contexts, ".curve_edit");
- break;
- case CTX_MODE_EDIT_TEXT:
- ARRAY_SET_ITEMS(contexts, ".text_edit");
- break;
- case CTX_MODE_EDIT_ARMATURE:
- ARRAY_SET_ITEMS(contexts, ".armature_edit");
- break;
- case CTX_MODE_EDIT_METABALL:
- ARRAY_SET_ITEMS(contexts, ".mball_edit");
- break;
- case CTX_MODE_EDIT_LATTICE:
- ARRAY_SET_ITEMS(contexts, ".lattice_edit");
- break;
- case CTX_MODE_POSE:
- ARRAY_SET_ITEMS(contexts, ".posemode");
- break;
- case CTX_MODE_SCULPT:
- ARRAY_SET_ITEMS(contexts, ".paint_common", ".sculpt_mode");
- break;
- case CTX_MODE_PAINT_WEIGHT:
- ARRAY_SET_ITEMS(contexts, ".paint_common", ".weightpaint");
- break;
- case CTX_MODE_PAINT_VERTEX:
- ARRAY_SET_ITEMS(contexts, ".paint_common", ".vertexpaint");
- break;
- case CTX_MODE_PAINT_TEXTURE:
- ARRAY_SET_ITEMS(contexts, ".paint_common", ".imagepaint");
- break;
- case CTX_MODE_PARTICLE:
- ARRAY_SET_ITEMS(contexts, ".paint_common", ".particlemode");
- break;
- case CTX_MODE_OBJECT:
- ARRAY_SET_ITEMS(contexts, ".objectmode");
- break;
- case CTX_MODE_PAINT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_paint");
- break;
- case CTX_MODE_SCULPT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt");
- break;
- case CTX_MODE_WEIGHT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
- break;
- default:
- break;
- }
- }
- else if (workspace->tools_space_type == SPACE_IMAGE) {
- switch (workspace->tools_mode) {
- case SI_MODE_VIEW:
- break;
- case SI_MODE_PAINT:
- ARRAY_SET_ITEMS(contexts, ".paint_common_2d", ".imagepaint_2d");
- break;
- case SI_MODE_MASK:
- break;
- case SI_MODE_UV:
- if (mode == CTX_MODE_EDIT_MESH) {
- ARRAY_SET_ITEMS(contexts, ".uv_sculpt");
- }
- break;
- }
- }
-
- /* for grease pencil we don't use tool system yet, so we need check outside
- * workspace->tools_space_type because this value is not available
- */
- switch (mode) {
- case CTX_MODE_PAINT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_paint");
- break;
- case CTX_MODE_SCULPT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt");
- break;
- case CTX_MODE_WEIGHT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
- break;
- case CTX_MODE_EDIT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_edit");
- break;
- default:
- break;
- }
-
- int i = 0;
- while (contexts_base[i]) {
- i++;
- }
- BLI_assert(i < ARRAY_SIZE(contexts_base));
- contexts_base[i] = ".workspace";
-
- const bool vertical = true;
- ED_region_panels_layout_ex(C, ar, contexts_base, -1, vertical);
+ const WorkSpace *workspace = CTX_wm_workspace(C);
+ const enum eContextObjectMode mode = CTX_data_mode_enum(C);
+
+ const char *contexts_base[5] = {NULL};
+ contexts_base[0] = ".active_tool";
+ const char **contexts = &contexts_base[1];
+
+ if (workspace->tools_space_type == SPACE_VIEW3D) {
+ switch (mode) {
+ case CTX_MODE_EDIT_MESH:
+ ARRAY_SET_ITEMS(contexts, ".mesh_edit");
+ break;
+ case CTX_MODE_EDIT_CURVE:
+ ARRAY_SET_ITEMS(contexts, ".curve_edit");
+ break;
+ case CTX_MODE_EDIT_SURFACE:
+ ARRAY_SET_ITEMS(contexts, ".curve_edit");
+ break;
+ case CTX_MODE_EDIT_TEXT:
+ ARRAY_SET_ITEMS(contexts, ".text_edit");
+ break;
+ case CTX_MODE_EDIT_ARMATURE:
+ ARRAY_SET_ITEMS(contexts, ".armature_edit");
+ break;
+ case CTX_MODE_EDIT_METABALL:
+ ARRAY_SET_ITEMS(contexts, ".mball_edit");
+ break;
+ case CTX_MODE_EDIT_LATTICE:
+ ARRAY_SET_ITEMS(contexts, ".lattice_edit");
+ break;
+ case CTX_MODE_POSE:
+ ARRAY_SET_ITEMS(contexts, ".posemode");
+ break;
+ case CTX_MODE_SCULPT:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".sculpt_mode");
+ break;
+ case CTX_MODE_PAINT_WEIGHT:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".weightpaint");
+ break;
+ case CTX_MODE_PAINT_VERTEX:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".vertexpaint");
+ break;
+ case CTX_MODE_PAINT_TEXTURE:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".imagepaint");
+ break;
+ case CTX_MODE_PARTICLE:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".particlemode");
+ break;
+ case CTX_MODE_OBJECT:
+ ARRAY_SET_ITEMS(contexts, ".objectmode");
+ break;
+ case CTX_MODE_PAINT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_paint");
+ break;
+ case CTX_MODE_SCULPT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt");
+ break;
+ case CTX_MODE_WEIGHT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
+ break;
+ default:
+ break;
+ }
+ }
+ else if (workspace->tools_space_type == SPACE_IMAGE) {
+ switch (workspace->tools_mode) {
+ case SI_MODE_VIEW:
+ break;
+ case SI_MODE_PAINT:
+ ARRAY_SET_ITEMS(contexts, ".paint_common_2d", ".imagepaint_2d");
+ break;
+ case SI_MODE_MASK:
+ break;
+ case SI_MODE_UV:
+ if (mode == CTX_MODE_EDIT_MESH) {
+ ARRAY_SET_ITEMS(contexts, ".uv_sculpt");
+ }
+ break;
+ }
+ }
+
+ /* for grease pencil we don't use tool system yet, so we need check outside
+ * workspace->tools_space_type because this value is not available
+ */
+ switch (mode) {
+ case CTX_MODE_PAINT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_paint");
+ break;
+ case CTX_MODE_SCULPT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt");
+ break;
+ case CTX_MODE_WEIGHT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
+ break;
+ case CTX_MODE_EDIT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_edit");
+ break;
+ default:
+ break;
+ }
+
+ int i = 0;
+ while (contexts_base[i]) {
+ i++;
+ }
+ BLI_assert(i < ARRAY_SIZE(contexts_base));
+ contexts_base[i] = ".workspace";
+
+ const bool vertical = true;
+ ED_region_panels_layout_ex(C, ar, contexts_base, -1, vertical);
}
static void buttons_main_region_layout(const bContext *C, ARegion *ar)
{
- /* draw entirely, view changes should be handled here */
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ /* draw entirely, view changes should be handled here */
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
- if (sbuts->mainb == BCONTEXT_TOOL) {
- buttons_main_region_layout_tool(C, ar);
- }
- else {
- buttons_main_region_layout_properties(C, sbuts, ar);
- }
+ if (sbuts->mainb == BCONTEXT_TOOL) {
+ buttons_main_region_layout_tool(C, ar);
+ }
+ else {
+ buttons_main_region_layout_properties(C, sbuts, ar);
+ }
- sbuts->mainbo = sbuts->mainb;
+ sbuts->mainbo = sbuts->mainb;
}
-static void buttons_main_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn,
- const Scene *UNUSED(scene))
+static void buttons_main_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_SCREEN:
- if (ELEM(wmn->data, ND_LAYER)) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SCREEN:
+ if (ELEM(wmn->data, ND_LAYER)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
}
static void buttons_operatortypes(void)
{
- WM_operatortype_append(BUTTONS_OT_context_menu);
- WM_operatortype_append(BUTTONS_OT_file_browse);
- WM_operatortype_append(BUTTONS_OT_directory_browse);
+ WM_operatortype_append(BUTTONS_OT_context_menu);
+ WM_operatortype_append(BUTTONS_OT_file_browse);
+ WM_operatortype_append(BUTTONS_OT_directory_browse);
}
static void buttons_keymap(struct wmKeyConfig *keyconf)
{
- WM_keymap_ensure(keyconf, "Property Editor", SPACE_PROPERTIES, 0);
+ WM_keymap_ensure(keyconf, "Property Editor", SPACE_PROPERTIES, 0);
}
/* add handlers, stuff you only do once or on area/region changes */
static void buttons_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
#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);
+ /* 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);
#endif
- ED_region_header_init(ar);
+ ED_region_header_init(ar);
}
static void buttons_header_region_draw(const bContext *C, ARegion *ar)
{
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
- /* Needed for RNA to get the good values! */
- buttons_context_compute(C, sbuts);
+ /* Needed for RNA to get the good values! */
+ buttons_context_compute(C, sbuts);
- ED_region_header(C, ar);
+ ED_region_header(C, ar);
}
-static void buttons_header_region_message_subscribe(
- const bContext *UNUSED(C),
- WorkSpace *UNUSED(workspace), Scene *UNUSED(scene),
- bScreen *UNUSED(screen), ScrArea *sa, ARegion *ar,
- struct wmMsgBus *mbus)
+static void buttons_header_region_message_subscribe(const bContext *UNUSED(C),
+ WorkSpace *UNUSED(workspace),
+ Scene *UNUSED(scene),
+ bScreen *UNUSED(screen),
+ ScrArea *sa,
+ ARegion *ar,
+ struct wmMsgBus *mbus)
{
- SpaceProperties *sbuts = sa->spacedata.first;
- wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
- .notify = ED_region_do_msg_notify_tag_redraw,
- };
+ SpaceProperties *sbuts = sa->spacedata.first;
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
- /* Don't check for SpaceProperties.mainb here, we may toggle between view-layers
- * where one has no active object, so that available contexts changes. */
- WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
+ /* Don't check for SpaceProperties.mainb here, we may toggle between view-layers
+ * where one has no active object, so that available contexts changes. */
+ WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
- if (!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_OUTPUT, BCONTEXT_SCENE, BCONTEXT_WORLD)) {
- WM_msg_subscribe_rna_anon_prop(mbus, ViewLayer, name, &msg_sub_value_region_tag_redraw);
- }
+ if (!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_OUTPUT, BCONTEXT_SCENE, BCONTEXT_WORLD)) {
+ WM_msg_subscribe_rna_anon_prop(mbus, ViewLayer, name, &msg_sub_value_region_tag_redraw);
+ }
- if (sbuts->mainb == BCONTEXT_TOOL) {
- WM_msg_subscribe_rna_anon_prop(mbus, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
- }
+ if (sbuts->mainb == BCONTEXT_TOOL) {
+ WM_msg_subscribe_rna_anon_prop(mbus, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
+ }
#ifdef USE_HEADER_CONTEXT_PATH
- WM_msg_subscribe_rna_anon_prop(mbus, SpaceProperties, context, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(mbus, SpaceProperties, context, &msg_sub_value_region_tag_redraw);
#endif
}
static void buttons_navigation_bar_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Property Editor", SPACE_PROPERTIES, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Property Editor", SPACE_PROPERTIES, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
- ar->flag |= RGN_FLAG_PREFSIZE_OR_HIDDEN;
+ ar->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, ar);
+ ar->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y;
}
static void buttons_navigation_bar_region_draw(const bContext *C, ARegion *ar)
{
- for (PanelType *pt = ar->type->paneltypes.first; pt; pt = pt->next) {
- pt->flag |= PNL_LAYOUT_VERT_BAR;
- }
-
- ED_region_panels_layout(C, ar);
- /* ED_region_panels_layout adds vertical scrollbars, we don't want them. */
- ar->v2d.scroll &= ~V2D_SCROLL_VERTICAL;
- ED_region_panels_draw(C, ar);
+ for (PanelType *pt = ar->type->paneltypes.first; pt; pt = pt->next) {
+ pt->flag |= PNL_LAYOUT_VERT_BAR;
+ }
+
+ ED_region_panels_layout(C, ar);
+ /* ED_region_panels_layout adds vertical scrollbars, we don't want them. */
+ ar->v2d.scroll &= ~V2D_SCROLL_VERTICAL;
+ ED_region_panels_draw(C, ar);
}
-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,
- struct wmMsgBus *mbus)
+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,
+ struct wmMsgBus *mbus)
{
- wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
- .notify = ED_region_do_msg_notify_tag_redraw,
- };
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
- WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
}
/* 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)
{
- SpaceProperties *sbuts = sa->spacedata.first;
+ SpaceProperties *sbuts = sa->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);
- }
+ /* if the area's current button set is equal to the one to redraw */
+ if (sbuts->mainb == buttons) {
+ ED_area_tag_redraw(sa);
+ }
}
/* reused! */
-static void buttons_area_listener(
- wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene))
+static void buttons_area_listener(wmWindow *UNUSED(win),
+ ScrArea *sa,
+ wmNotifier *wmn,
+ Scene *UNUSED(scene))
{
- SpaceProperties *sbuts = sa->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_VIEW_LAYER);
- break;
- case ND_WORLD:
- buttons_area_redraw(sa, BCONTEXT_WORLD);
- sbuts->preview = 1;
- break;
- case ND_FRAME:
- /* any buttons area can have animated properties so redraw all */
- ED_area_tag_redraw(sa);
- sbuts->preview = 1;
- break;
- case ND_OB_ACTIVE:
- ED_area_tag_redraw(sa);
- sbuts->preview = 1;
- break;
- case ND_KEYINGSET:
- buttons_area_redraw(sa, BCONTEXT_SCENE);
- break;
- case ND_RENDER_RESULT:
- break;
- case ND_MODE:
- case ND_LAYER:
- default:
- ED_area_tag_redraw(sa);
- 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 */
- break;
- case ND_POSE:
- buttons_area_redraw(sa, BCONTEXT_DATA);
- break;
- 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);
- break;
- case ND_MODIFIER:
- if (wmn->action == NA_RENAME) {
- ED_area_tag_redraw(sa);
- }
- else {
- buttons_area_redraw(sa, BCONTEXT_MODIFIER);
- }
- buttons_area_redraw(sa, BCONTEXT_PHYSICS);
- break;
- case ND_CONSTRAINT:
- buttons_area_redraw(sa, BCONTEXT_CONSTRAINT);
- buttons_area_redraw(sa, BCONTEXT_BONE_CONSTRAINT);
- break;
- case ND_PARTICLE:
- if (wmn->action == NA_EDITED) {
- buttons_area_redraw(sa, 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);
- break;
- case ND_SHADING:
- case ND_SHADING_DRAW:
- case ND_SHADING_LINKS:
- case ND_SHADING_PREVIEW:
- /* currently works by redraws... if preview is set, it (re)starts job */
- sbuts->preview = 1;
- break;
- default:
- /* Not all object RNA props have a ND_ notifier (yet) */
- ED_area_tag_redraw(sa);
- break;
- }
- break;
- case NC_GEOM:
- switch (wmn->data) {
- case ND_SELECT:
- case ND_DATA:
- case ND_VERTEX_GROUP:
- ED_area_tag_redraw(sa);
- break;
- }
- break;
- case NC_MATERIAL:
- ED_area_tag_redraw(sa);
- switch (wmn->data) {
- case ND_SHADING:
- case ND_SHADING_DRAW:
- case ND_SHADING_LINKS:
- case ND_SHADING_PREVIEW:
- case ND_NODES:
- /* currently works by redraws... if preview is set, it (re)starts job */
- sbuts->preview = 1;
- break;
- }
- break;
- case NC_WORLD:
- buttons_area_redraw(sa, BCONTEXT_WORLD);
- sbuts->preview = 1;
- break;
- case NC_LAMP:
- buttons_area_redraw(sa, BCONTEXT_DATA);
- sbuts->preview = 1;
- break;
- case NC_GROUP:
- buttons_area_redraw(sa, BCONTEXT_OBJECT);
- break;
- case NC_BRUSH:
- buttons_area_redraw(sa, BCONTEXT_TEXTURE);
- buttons_area_redraw(sa, BCONTEXT_TOOL);
- sbuts->preview = 1;
- break;
- case NC_TEXTURE:
- case NC_IMAGE:
- if (wmn->action != NA_PAINTING) {
- ED_area_tag_redraw(sa);
- sbuts->preview = 1;
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_PROPERTIES) {
- ED_area_tag_redraw(sa);
- }
- break;
- case NC_ID:
- if (wmn->action == NA_RENAME) {
- ED_area_tag_redraw(sa);
- }
- 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);
- }
- break;
- }
- break;
- case NC_GPENCIL:
- switch (wmn->data) {
- case ND_DATA:
- if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED)) {
- ED_area_tag_redraw(sa);
- }
- break;
- }
- break;
- case NC_NODE:
- if (wmn->action == NA_SELECTED) {
- ED_area_tag_redraw(sa);
- /* new active node, update texture preview */
- if (sbuts->mainb == BCONTEXT_TEXTURE) {
- sbuts->preview = 1;
- }
- }
- break;
- /* Listener for preview render, when doing an global undo. */
- case NC_WM:
- if (wmn->data == ND_UNDO) {
- ED_area_tag_redraw(sa);
- sbuts->preview = 1;
- }
- break;
+ SpaceProperties *sbuts = sa->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_VIEW_LAYER);
+ break;
+ case ND_WORLD:
+ buttons_area_redraw(sa, BCONTEXT_WORLD);
+ sbuts->preview = 1;
+ break;
+ case ND_FRAME:
+ /* any buttons area can have animated properties so redraw all */
+ ED_area_tag_redraw(sa);
+ sbuts->preview = 1;
+ break;
+ case ND_OB_ACTIVE:
+ ED_area_tag_redraw(sa);
+ sbuts->preview = 1;
+ break;
+ case ND_KEYINGSET:
+ buttons_area_redraw(sa, BCONTEXT_SCENE);
+ break;
+ case ND_RENDER_RESULT:
+ break;
+ case ND_MODE:
+ case ND_LAYER:
+ default:
+ ED_area_tag_redraw(sa);
+ 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 */
+ break;
+ case ND_POSE:
+ buttons_area_redraw(sa, BCONTEXT_DATA);
+ break;
+ 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);
+ break;
+ case ND_MODIFIER:
+ if (wmn->action == NA_RENAME) {
+ ED_area_tag_redraw(sa);
+ }
+ else {
+ buttons_area_redraw(sa, BCONTEXT_MODIFIER);
+ }
+ buttons_area_redraw(sa, BCONTEXT_PHYSICS);
+ break;
+ case ND_CONSTRAINT:
+ buttons_area_redraw(sa, BCONTEXT_CONSTRAINT);
+ buttons_area_redraw(sa, BCONTEXT_BONE_CONSTRAINT);
+ break;
+ case ND_PARTICLE:
+ if (wmn->action == NA_EDITED) {
+ buttons_area_redraw(sa, 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);
+ break;
+ case ND_SHADING:
+ case ND_SHADING_DRAW:
+ case ND_SHADING_LINKS:
+ case ND_SHADING_PREVIEW:
+ /* currently works by redraws... if preview is set, it (re)starts job */
+ sbuts->preview = 1;
+ break;
+ default:
+ /* Not all object RNA props have a ND_ notifier (yet) */
+ ED_area_tag_redraw(sa);
+ break;
+ }
+ break;
+ case NC_GEOM:
+ switch (wmn->data) {
+ case ND_SELECT:
+ case ND_DATA:
+ case ND_VERTEX_GROUP:
+ ED_area_tag_redraw(sa);
+ break;
+ }
+ break;
+ case NC_MATERIAL:
+ ED_area_tag_redraw(sa);
+ switch (wmn->data) {
+ case ND_SHADING:
+ case ND_SHADING_DRAW:
+ case ND_SHADING_LINKS:
+ case ND_SHADING_PREVIEW:
+ case ND_NODES:
+ /* currently works by redraws... if preview is set, it (re)starts job */
+ sbuts->preview = 1;
+ break;
+ }
+ break;
+ case NC_WORLD:
+ buttons_area_redraw(sa, BCONTEXT_WORLD);
+ sbuts->preview = 1;
+ break;
+ case NC_LAMP:
+ buttons_area_redraw(sa, BCONTEXT_DATA);
+ sbuts->preview = 1;
+ break;
+ case NC_GROUP:
+ buttons_area_redraw(sa, BCONTEXT_OBJECT);
+ break;
+ case NC_BRUSH:
+ buttons_area_redraw(sa, BCONTEXT_TEXTURE);
+ buttons_area_redraw(sa, BCONTEXT_TOOL);
+ sbuts->preview = 1;
+ break;
+ case NC_TEXTURE:
+ case NC_IMAGE:
+ if (wmn->action != NA_PAINTING) {
+ ED_area_tag_redraw(sa);
+ sbuts->preview = 1;
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_PROPERTIES) {
+ ED_area_tag_redraw(sa);
+ }
+ break;
+ case NC_ID:
+ if (wmn->action == NA_RENAME) {
+ ED_area_tag_redraw(sa);
+ }
+ 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);
+ }
+ break;
+ }
+ break;
+ case NC_GPENCIL:
+ switch (wmn->data) {
+ case ND_DATA:
+ if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED)) {
+ ED_area_tag_redraw(sa);
+ }
+ break;
+ }
+ break;
+ case NC_NODE:
+ if (wmn->action == NA_SELECTED) {
+ ED_area_tag_redraw(sa);
+ /* new active node, update texture preview */
+ if (sbuts->mainb == BCONTEXT_TEXTURE) {
+ sbuts->preview = 1;
+ }
+ }
+ break;
+ /* Listener for preview render, when doing an global undo. */
+ case NC_WM:
+ if (wmn->data == ND_UNDO) {
+ ED_area_tag_redraw(sa);
+ sbuts->preview = 1;
+ }
+ break;
#ifdef WITH_FREESTYLE
- case NC_LINESTYLE:
- ED_area_tag_redraw(sa);
- sbuts->preview = 1;
- break;
+ case NC_LINESTYLE:
+ ED_area_tag_redraw(sa);
+ sbuts->preview = 1;
+ break;
#endif
- }
+ }
- if (wmn->data == ND_KEYS) {
- ED_area_tag_redraw(sa);
- }
+ if (wmn->data == ND_KEYS) {
+ ED_area_tag_redraw(sa);
+ }
}
static void buttons_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
{
- SpaceProperties *sbuts = (SpaceProperties *)slink;
-
- if (sbuts->pinid == old_id) {
- sbuts->pinid = new_id;
- if (new_id == NULL) {
- sbuts->flag &= ~SB_PIN_CONTEXT;
- }
- }
-
- if (sbuts->path) {
- ButsContextPath *path = sbuts->path;
- int i;
-
- for (i = 0; i < path->len; i++) {
- if (path->ptr[i].id.data == old_id) {
- break;
- }
- }
-
- if (i == path->len) {
- /* pass */
- }
- else if (new_id == NULL) {
- if (i == 0) {
- MEM_SAFE_FREE(sbuts->path);
- }
- else {
- memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i));
- path->len = i;
- }
- }
- else {
- RNA_id_pointer_create(new_id, &path->ptr[i]);
- /* There is no easy way to check/make path downwards valid, just nullify it.
- * Next redraw will rebuild this anyway. */
- i++;
- memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i));
- path->len = i;
- }
- }
-
- if (sbuts->texuser) {
- ButsContextTexture *ct = sbuts->texuser;
- if ((ID *)ct->texture == old_id) {
- ct->texture = (Tex *)new_id;
- }
- BLI_freelistN(&ct->users);
- ct->user = NULL;
- }
+ SpaceProperties *sbuts = (SpaceProperties *)slink;
+
+ if (sbuts->pinid == old_id) {
+ sbuts->pinid = new_id;
+ if (new_id == NULL) {
+ sbuts->flag &= ~SB_PIN_CONTEXT;
+ }
+ }
+
+ if (sbuts->path) {
+ ButsContextPath *path = sbuts->path;
+ int i;
+
+ for (i = 0; i < path->len; i++) {
+ if (path->ptr[i].id.data == old_id) {
+ break;
+ }
+ }
+
+ if (i == path->len) {
+ /* pass */
+ }
+ else if (new_id == NULL) {
+ if (i == 0) {
+ MEM_SAFE_FREE(sbuts->path);
+ }
+ else {
+ memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i));
+ path->len = i;
+ }
+ }
+ else {
+ RNA_id_pointer_create(new_id, &path->ptr[i]);
+ /* There is no easy way to check/make path downwards valid, just nullify it.
+ * Next redraw will rebuild this anyway. */
+ i++;
+ memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i));
+ path->len = i;
+ }
+ }
+
+ if (sbuts->texuser) {
+ ButsContextTexture *ct = sbuts->texuser;
+ if ((ID *)ct->texture == old_id) {
+ ct->texture = (Tex *)new_id;
+ }
+ BLI_freelistN(&ct->users);
+ ct->user = NULL;
+ }
}
/* only called once, from space/spacetypes.c */
void ED_spacetype_buttons(void)
{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype buttons");
- ARegionType *art;
-
- st->spaceid = SPACE_PROPERTIES;
- strncpy(st->name, "Buttons", BKE_ST_MAXNAME);
-
- st->new = buttons_new;
- st->free = buttons_free;
- st->init = buttons_init;
- st->duplicate = buttons_duplicate;
- st->operatortypes = buttons_operatortypes;
- st->keymap = buttons_keymap;
- st->listener = buttons_area_listener;
- st->context = buttons_context;
- st->id_remap = buttons_id_remap;
-
- /* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype buttons region");
- art->regionid = RGN_TYPE_WINDOW;
- art->init = buttons_main_region_init;
- art->layout = buttons_main_region_layout;
- art->draw = ED_region_panels_draw;
- art->listener = buttons_main_region_listener;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
+ SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype buttons");
+ ARegionType *art;
+
+ st->spaceid = SPACE_PROPERTIES;
+ strncpy(st->name, "Buttons", BKE_ST_MAXNAME);
+
+ st->new = buttons_new;
+ st->free = buttons_free;
+ st->init = buttons_init;
+ st->duplicate = buttons_duplicate;
+ st->operatortypes = buttons_operatortypes;
+ st->keymap = buttons_keymap;
+ st->listener = buttons_area_listener;
+ st->context = buttons_context;
+ st->id_remap = buttons_id_remap;
+
+ /* regions: main window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype buttons region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init = buttons_main_region_init;
+ art->layout = buttons_main_region_layout;
+ art->draw = ED_region_panels_draw;
+ art->listener = buttons_main_region_listener;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
#ifndef USE_HEADER_CONTEXT_PATH
- buttons_context_register(art);
+ buttons_context_register(art);
#endif
- BLI_addhead(&st->regiontypes, art);
+ BLI_addhead(&st->regiontypes, art);
- /* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype buttons region");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
+ /* regions: header */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype buttons region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = HEADERY;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
- art->init = buttons_header_region_init;
- art->draw = buttons_header_region_draw;
- art->message_subscribe = buttons_header_region_message_subscribe;
+ art->init = buttons_header_region_init;
+ art->draw = buttons_header_region_draw;
+ art->message_subscribe = buttons_header_region_message_subscribe;
#ifdef USE_HEADER_CONTEXT_PATH
- buttons_context_register(art);
+ buttons_context_register(art);
#endif
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: navigation bar */
- art = MEM_callocN(sizeof(ARegionType), "spacetype nav buttons region");
- art->regionid = RGN_TYPE_NAV_BAR;
- art->prefsizex = AREAMINX - 3; /* XXX Works and looks best,
- * should we update AREAMINX accordingly? */
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
- art->init = buttons_navigation_bar_region_init;
- art->draw = buttons_navigation_bar_region_draw;
- art->message_subscribe = buttons_navigation_bar_region_message_subscribe;
- BLI_addhead(&st->regiontypes, art);
-
- BKE_spacetype_register(st);
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: navigation bar */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype nav buttons region");
+ art->regionid = RGN_TYPE_NAV_BAR;
+ art->prefsizex = AREAMINX - 3; /* XXX Works and looks best,
+ * should we update AREAMINX accordingly? */
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
+ art->init = buttons_navigation_bar_region_init;
+ art->draw = buttons_navigation_bar_region_draw;
+ art->message_subscribe = buttons_navigation_bar_region_message_subscribe;
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_clip/CMakeLists.txt b/source/blender/editors/space_clip/CMakeLists.txt
index 49d7efb5669..ed98dcdc159 100644
--- a/source/blender/editors/space_clip/CMakeLists.txt
+++ b/source/blender/editors/space_clip/CMakeLists.txt
@@ -18,60 +18,60 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenfont
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../depsgraph
- ../../imbuf
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenfont
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../depsgraph
+ ../../imbuf
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- clip_buttons.c
- clip_dopesheet_draw.c
- clip_dopesheet_ops.c
- clip_draw.c
- clip_editor.c
- clip_graph_draw.c
- clip_graph_ops.c
- clip_ops.c
- clip_toolbar.c
- clip_utils.c
- space_clip.c
- tracking_ops.c
- tracking_ops_detect.c
- tracking_ops_orient.c
- tracking_ops_plane.c
- tracking_ops_solve.c
- tracking_ops_stabilize.c
- tracking_ops_track.c
- tracking_ops_utils.c
- tracking_select.c
+ clip_buttons.c
+ clip_dopesheet_draw.c
+ clip_dopesheet_ops.c
+ clip_draw.c
+ clip_editor.c
+ clip_graph_draw.c
+ clip_graph_ops.c
+ clip_ops.c
+ clip_toolbar.c
+ clip_utils.c
+ space_clip.c
+ tracking_ops.c
+ tracking_ops_detect.c
+ tracking_ops_orient.c
+ tracking_ops_plane.c
+ tracking_ops_solve.c
+ tracking_ops_stabilize.c
+ tracking_ops_track.c
+ tracking_ops_utils.c
+ tracking_select.c
- clip_intern.h
- tracking_ops_intern.h
+ clip_intern.h
+ tracking_ops_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
+ bf_blenkernel
+ bf_blenlib
)
add_definitions(${GL_DEFINITIONS})
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
blender_add_lib(bf_editor_space_clip "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index 6e4b98af93b..6f950ec5bc4 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -60,554 +60,806 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "clip_intern.h" /* own include */
+#include "clip_intern.h" /* own include */
/* Panels */
static bool metadata_panel_context_poll(const bContext *C, PanelType *UNUSED(pt))
{
- return ED_space_clip_poll((bContext *)C);
+ return ED_space_clip_poll((bContext *)C);
}
static void metadata_panel_context_draw(const bContext *C, Panel *panel)
{
- SpaceClip *space_clip = CTX_wm_space_clip(C);
- /* NOTE: This might not be exactly the same image buffer as shown in the
- * clip editor itself, since that might be coming from proxy, or being
- * postprocessed (stabilized or undistored).
- * Ideally we need to query metadata from an original image or movie without
- * reading actual pixels to speed up the process. */
- ImBuf *ibuf = ED_space_clip_get_buffer(space_clip);
- if (ibuf != NULL) {
- ED_region_image_metadata_panel_draw(ibuf, panel->layout);
- IMB_freeImBuf(ibuf);
- }
+ SpaceClip *space_clip = CTX_wm_space_clip(C);
+ /* NOTE: This might not be exactly the same image buffer as shown in the
+ * clip editor itself, since that might be coming from proxy, or being
+ * postprocessed (stabilized or undistored).
+ * Ideally we need to query metadata from an original image or movie without
+ * reading actual pixels to speed up the process. */
+ ImBuf *ibuf = ED_space_clip_get_buffer(space_clip);
+ if (ibuf != NULL) {
+ ED_region_image_metadata_panel_draw(ibuf, panel->layout);
+ IMB_freeImBuf(ibuf);
+ }
}
void ED_clip_buttons_register(ARegionType *art)
{
- PanelType *pt;
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype clip panel metadata");
- strcpy(pt->idname, "CLIP_PT_metadata");
- strcpy(pt->label, N_("Metadata"));
- strcpy(pt->category, "Footage");
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->poll = metadata_panel_context_poll;
- pt->draw = metadata_panel_context_draw;
- pt->flag |= PNL_DEFAULT_CLOSED;
- BLI_addtail(&art->paneltypes, pt);
+ PanelType *pt;
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype clip panel metadata");
+ strcpy(pt->idname, "CLIP_PT_metadata");
+ strcpy(pt->label, N_("Metadata"));
+ strcpy(pt->category, "Footage");
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->poll = metadata_panel_context_poll;
+ pt->draw = metadata_panel_context_draw;
+ pt->flag |= PNL_DEFAULT_CLOSED;
+ BLI_addtail(&art->paneltypes, pt);
}
/********************* MovieClip Template ************************/
-void uiTemplateMovieClip(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, bool compact)
+void uiTemplateMovieClip(
+ uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, bool compact)
{
- PropertyRNA *prop;
- PointerRNA clipptr;
- MovieClip *clip;
- uiLayout *row, *split;
- uiBlock *block;
-
- if (!ptr->data)
- return;
-
- prop = RNA_struct_find_property(ptr, propname);
- if (!prop) {
- printf("%s: property not found: %s.%s\n",
- __func__, RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- if (RNA_property_type(prop) != PROP_POINTER) {
- printf("%s: expected pointer property for %s.%s\n",
- __func__, RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- clipptr = RNA_property_pointer_get(ptr, prop);
- clip = clipptr.data;
-
- uiLayoutSetContextPointer(layout, "edit_movieclip", &clipptr);
-
- if (!compact)
- uiTemplateID(layout, C, ptr, propname, NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
-
- if (clip) {
- uiLayout *col;
-
- row = uiLayoutRow(layout, false);
- block = uiLayoutGetBlock(row);
- uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("File Path:"), 0, 19, 145, 19, NULL, 0, 0, 0, 0, "");
-
- row = uiLayoutRow(layout, false);
- split = uiLayoutSplit(row, 0.0f, false);
- row = uiLayoutRow(split, true);
-
- uiItemR(row, &clipptr, "filepath", 0, "", ICON_NONE);
- uiItemO(row, "", ICON_FILE_REFRESH, "clip.reload");
-
- col = uiLayoutColumn(layout, false);
- uiTemplateColorspaceSettings(col, &clipptr, "colorspace_settings");
- }
+ PropertyRNA *prop;
+ PointerRNA clipptr;
+ MovieClip *clip;
+ uiLayout *row, *split;
+ uiBlock *block;
+
+ if (!ptr->data)
+ return;
+
+ prop = RNA_struct_find_property(ptr, propname);
+ if (!prop) {
+ printf(
+ "%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ if (RNA_property_type(prop) != PROP_POINTER) {
+ printf("%s: expected pointer property for %s.%s\n",
+ __func__,
+ RNA_struct_identifier(ptr->type),
+ propname);
+ return;
+ }
+
+ clipptr = RNA_property_pointer_get(ptr, prop);
+ clip = clipptr.data;
+
+ uiLayoutSetContextPointer(layout, "edit_movieclip", &clipptr);
+
+ if (!compact)
+ uiTemplateID(
+ layout, C, ptr, propname, NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+
+ if (clip) {
+ uiLayout *col;
+
+ row = uiLayoutRow(layout, false);
+ block = uiLayoutGetBlock(row);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("File Path:"), 0, 19, 145, 19, NULL, 0, 0, 0, 0, "");
+
+ row = uiLayoutRow(layout, false);
+ split = uiLayoutSplit(row, 0.0f, false);
+ row = uiLayoutRow(split, true);
+
+ uiItemR(row, &clipptr, "filepath", 0, "", ICON_NONE);
+ uiItemO(row, "", ICON_FILE_REFRESH, "clip.reload");
+
+ col = uiLayoutColumn(layout, false);
+ uiTemplateColorspaceSettings(col, &clipptr, "colorspace_settings");
+ }
}
/********************* Track Template ************************/
void uiTemplateTrack(uiLayout *layout, PointerRNA *ptr, const char *propname)
{
- PropertyRNA *prop;
- PointerRNA scopesptr;
- uiBlock *block;
- uiLayout *col;
- MovieClipScopes *scopes;
-
- if (!ptr->data)
- return;
-
- prop = RNA_struct_find_property(ptr, propname);
- if (!prop) {
- printf("%s: property not found: %s.%s\n",
- __func__, RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- if (RNA_property_type(prop) != PROP_POINTER) {
- printf("%s: expected pointer property for %s.%s\n",
- __func__, RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- scopesptr = RNA_property_pointer_get(ptr, prop);
- scopes = (MovieClipScopes *)scopesptr.data;
-
- if (scopes->track_preview_height < UI_UNIT_Y) {
- scopes->track_preview_height = UI_UNIT_Y;
- }
- else if (scopes->track_preview_height > UI_UNIT_Y * 20) {
- scopes->track_preview_height = UI_UNIT_Y * 20;
- }
-
- col = uiLayoutColumn(layout, true);
- block = uiLayoutGetBlock(col);
-
- uiDefBut(block, UI_BTYPE_TRACK_PREVIEW, 0, "", 0, 0, UI_UNIT_X * 10, scopes->track_preview_height, scopes, 0, 0, 0, 0, "");
-
- /* Resize grip. */
- uiDefIconButI(block, UI_BTYPE_GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10, (short)(UI_UNIT_Y * 0.8f),
- &scopes->track_preview_height, UI_UNIT_Y, UI_UNIT_Y * 20.0f, 0.0f, 0.0f, "");
+ PropertyRNA *prop;
+ PointerRNA scopesptr;
+ uiBlock *block;
+ uiLayout *col;
+ MovieClipScopes *scopes;
+
+ if (!ptr->data)
+ return;
+
+ prop = RNA_struct_find_property(ptr, propname);
+ if (!prop) {
+ printf(
+ "%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ if (RNA_property_type(prop) != PROP_POINTER) {
+ printf("%s: expected pointer property for %s.%s\n",
+ __func__,
+ RNA_struct_identifier(ptr->type),
+ propname);
+ return;
+ }
+
+ scopesptr = RNA_property_pointer_get(ptr, prop);
+ scopes = (MovieClipScopes *)scopesptr.data;
+
+ if (scopes->track_preview_height < UI_UNIT_Y) {
+ scopes->track_preview_height = UI_UNIT_Y;
+ }
+ else if (scopes->track_preview_height > UI_UNIT_Y * 20) {
+ scopes->track_preview_height = UI_UNIT_Y * 20;
+ }
+
+ col = uiLayoutColumn(layout, true);
+ block = uiLayoutGetBlock(col);
+
+ uiDefBut(block,
+ UI_BTYPE_TRACK_PREVIEW,
+ 0,
+ "",
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ scopes->track_preview_height,
+ scopes,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+
+ /* Resize grip. */
+ uiDefIconButI(block,
+ UI_BTYPE_GRIP,
+ 0,
+ ICON_GRIP,
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ (short)(UI_UNIT_Y * 0.8f),
+ &scopes->track_preview_height,
+ UI_UNIT_Y,
+ UI_UNIT_Y * 20.0f,
+ 0.0f,
+ 0.0f,
+ "");
}
/********************* Marker Template ************************/
-#define B_MARKER_POS 3
-#define B_MARKER_OFFSET 4
-#define B_MARKER_PAT_DIM 5
-#define B_MARKER_SEARCH_POS 6
-#define B_MARKER_SEARCH_DIM 7
-#define B_MARKER_FLAG 8
+#define B_MARKER_POS 3
+#define B_MARKER_OFFSET 4
+#define B_MARKER_PAT_DIM 5
+#define B_MARKER_SEARCH_POS 6
+#define B_MARKER_SEARCH_DIM 7
+#define B_MARKER_FLAG 8
typedef struct {
- /** compact mode */
- int compact;
-
- MovieClip *clip;
- /** user of clip */
- MovieClipUser *user;
- 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 */
- float marker_pat[2];
- /** offset of "parenting" point */
- float track_offset[2];
- /** position and dimensions of marker search in pixel coords */
- float marker_search_pos[2], marker_search[2];
- /** marker's flags */
- int marker_flag;
+ /** compact mode */
+ int compact;
+
+ MovieClip *clip;
+ /** user of clip */
+ MovieClipUser *user;
+ 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 */
+ float marker_pat[2];
+ /** offset of "parenting" point */
+ float track_offset[2];
+ /** position and dimensions of marker search in pixel coords */
+ float marker_search_pos[2], marker_search[2];
+ /** marker's flags */
+ int marker_flag;
} MarkerUpdateCb;
static void to_pixel_space(float r[2], float a[2], int width, int height)
{
- copy_v2_v2(r, a);
- r[0] *= width;
- r[1] *= height;
+ copy_v2_v2(r, a);
+ r[0] *= width;
+ r[1] *= height;
}
static void marker_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
{
- MarkerUpdateCb *cb = (MarkerUpdateCb *) arg_cb;
- MovieTrackingMarker *marker;
+ MarkerUpdateCb *cb = (MarkerUpdateCb *)arg_cb;
+ MovieTrackingMarker *marker;
- if (!cb->compact)
- return;
+ if (!cb->compact)
+ return;
- marker = BKE_tracking_marker_ensure(cb->track, cb->framenr);
+ marker = BKE_tracking_marker_ensure(cb->track, cb->framenr);
- marker->flag = cb->marker_flag;
+ marker->flag = cb->marker_flag;
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
}
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;
+ MarkerUpdateCb *cb = (MarkerUpdateCb *)arg_cb;
+ MovieTrackingMarker *marker;
+ int width, height;
+ bool ok = false;
- BKE_movieclip_get_size(cb->clip, cb->user, &width, &height);
+ BKE_movieclip_get_size(cb->clip, cb->user, &width, &height);
- marker = BKE_tracking_marker_ensure(cb->track, cb->framenr);
+ marker = BKE_tracking_marker_ensure(cb->track, cb->framenr);
- if (event == B_MARKER_POS) {
- marker->pos[0] = cb->marker_pos[0] / width;
- marker->pos[1] = cb->marker_pos[1] / height;
+ if (event == B_MARKER_POS) {
+ marker->pos[0] = cb->marker_pos[0] / width;
+ marker->pos[1] = cb->marker_pos[1] / height;
- /* to update position of "parented" objects */
- DEG_id_tag_update(&cb->clip->id, 0);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ /* to update position of "parented" objects */
+ DEG_id_tag_update(&cb->clip->id, 0);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- ok = true;
- }
- else if (event == B_MARKER_PAT_DIM) {
- float dim[2], pat_dim[2], pat_min[2], pat_max[2];
- float scale_x, scale_y;
- int a;
+ ok = true;
+ }
+ else if (event == B_MARKER_PAT_DIM) {
+ float dim[2], pat_dim[2], pat_min[2], pat_max[2];
+ float scale_x, scale_y;
+ int a;
- BKE_tracking_marker_pattern_minmax(cb->marker, pat_min, pat_max);
+ BKE_tracking_marker_pattern_minmax(cb->marker, pat_min, pat_max);
- sub_v2_v2v2(pat_dim, pat_max, pat_min);
+ sub_v2_v2v2(pat_dim, pat_max, pat_min);
- dim[0] = cb->marker_pat[0] / width;
- dim[1] = cb->marker_pat[1] / height;
+ dim[0] = cb->marker_pat[0] / width;
+ dim[1] = cb->marker_pat[1] / height;
- scale_x = dim[0] / pat_dim[0];
- scale_y = dim[1] / pat_dim[1];
+ scale_x = dim[0] / pat_dim[0];
+ scale_y = dim[1] / pat_dim[1];
- for (a = 0; a < 4; a++) {
- cb->marker->pattern_corners[a][0] *= scale_x;
- cb->marker->pattern_corners[a][1] *= scale_y;
- }
+ for (a = 0; a < 4; a++) {
+ cb->marker->pattern_corners[a][0] *= scale_x;
+ cb->marker->pattern_corners[a][1] *= scale_y;
+ }
- BKE_tracking_marker_clamp(cb->marker, CLAMP_PAT_DIM);
+ BKE_tracking_marker_clamp(cb->marker, CLAMP_PAT_DIM);
- ok = true;
- }
- else if (event == B_MARKER_SEARCH_POS) {
- float delta[2], side[2];
+ ok = true;
+ }
+ else if (event == B_MARKER_SEARCH_POS) {
+ float delta[2], side[2];
- sub_v2_v2v2(side, cb->marker->search_max, cb->marker->search_min);
- mul_v2_fl(side, 0.5f);
+ sub_v2_v2v2(side, cb->marker->search_max, cb->marker->search_min);
+ mul_v2_fl(side, 0.5f);
- delta[0] = cb->marker_search_pos[0] / width;
- delta[1] = cb->marker_search_pos[1] / height;
+ delta[0] = cb->marker_search_pos[0] / width;
+ delta[1] = cb->marker_search_pos[1] / height;
- sub_v2_v2v2(cb->marker->search_min, delta, side);
- add_v2_v2v2(cb->marker->search_max, delta, side);
+ sub_v2_v2v2(cb->marker->search_min, delta, side);
+ add_v2_v2v2(cb->marker->search_max, delta, side);
- BKE_tracking_marker_clamp(cb->marker, CLAMP_SEARCH_POS);
+ BKE_tracking_marker_clamp(cb->marker, CLAMP_SEARCH_POS);
- ok = true;
- }
- else if (event == B_MARKER_SEARCH_DIM) {
- float dim[2], search_dim[2];
+ ok = true;
+ }
+ else if (event == B_MARKER_SEARCH_DIM) {
+ float dim[2], search_dim[2];
- sub_v2_v2v2(search_dim, cb->marker->search_max, cb->marker->search_min);
+ sub_v2_v2v2(search_dim, cb->marker->search_max, cb->marker->search_min);
- dim[0] = cb->marker_search[0] / width;
- dim[1] = cb->marker_search[1] / height;
+ dim[0] = cb->marker_search[0] / width;
+ dim[1] = cb->marker_search[1] / height;
- sub_v2_v2(dim, search_dim);
- mul_v2_fl(dim, 0.5f);
+ sub_v2_v2(dim, search_dim);
+ mul_v2_fl(dim, 0.5f);
- cb->marker->search_min[0] -= dim[0];
- cb->marker->search_min[1] -= dim[1];
+ cb->marker->search_min[0] -= dim[0];
+ cb->marker->search_min[1] -= dim[1];
- cb->marker->search_max[0] += dim[0];
- cb->marker->search_max[1] += dim[1];
+ cb->marker->search_max[0] += dim[0];
+ cb->marker->search_max[1] += dim[1];
- BKE_tracking_marker_clamp(cb->marker, CLAMP_SEARCH_DIM);
+ BKE_tracking_marker_clamp(cb->marker, CLAMP_SEARCH_DIM);
- ok = true;
- }
- else if (event == B_MARKER_FLAG) {
- marker->flag = cb->marker_flag;
+ ok = true;
+ }
+ else if (event == B_MARKER_FLAG) {
+ marker->flag = cb->marker_flag;
- ok = true;
- }
- else if (event == B_MARKER_OFFSET) {
- float offset[2], delta[2];
- int i;
+ ok = true;
+ }
+ else if (event == B_MARKER_OFFSET) {
+ float offset[2], delta[2];
+ int i;
- offset[0] = cb->track_offset[0] / width;
- offset[1] = cb->track_offset[1] / height;
+ offset[0] = cb->track_offset[0] / width;
+ offset[1] = cb->track_offset[1] / height;
- sub_v2_v2v2(delta, offset, cb->track->offset);
- copy_v2_v2(cb->track->offset, offset);
+ sub_v2_v2v2(delta, offset, cb->track->offset);
+ copy_v2_v2(cb->track->offset, offset);
- for (i = 0; i < cb->track->markersnr; i++)
- sub_v2_v2(cb->track->markers[i].pos, delta);
+ for (i = 0; i < cb->track->markersnr; i++)
+ sub_v2_v2(cb->track->markers[i].pos, delta);
- /* to update position of "parented" objects */
- DEG_id_tag_update(&cb->clip->id, 0);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ /* to update position of "parented" objects */
+ DEG_id_tag_update(&cb->clip->id, 0);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- ok = true;
- }
+ ok = true;
+ }
- if (ok)
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, cb->clip);
+ if (ok)
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, cb->clip);
}
-void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *userptr,
- PointerRNA *trackptr, bool compact)
+void uiTemplateMarker(uiLayout *layout,
+ PointerRNA *ptr,
+ const char *propname,
+ PointerRNA *userptr,
+ PointerRNA *trackptr,
+ bool compact)
{
- PropertyRNA *prop;
- uiBlock *block;
- uiBut *bt;
- PointerRNA clipptr;
- MovieClip *clip;
- MovieClipUser *user;
- MovieTrackingTrack *track;
- MovieTrackingMarker *marker;
- MarkerUpdateCb *cb;
- const char *tip;
- float pat_min[2], pat_max[2];
-
- if (!ptr->data)
- return;
-
- prop = RNA_struct_find_property(ptr, propname);
- if (!prop) {
- printf("%s: property not found: %s.%s\n",
- __func__, RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- if (RNA_property_type(prop) != PROP_POINTER) {
- printf("%s: expected pointer property for %s.%s\n",
- __func__, RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- clipptr = RNA_property_pointer_get(ptr, prop);
- clip = (MovieClip *)clipptr.data;
- user = userptr->data;
- track = trackptr->data;
-
- marker = BKE_tracking_marker_get(track, user->framenr);
-
- cb = MEM_callocN(sizeof(MarkerUpdateCb), "uiTemplateMarker update_cb");
- cb->compact = compact;
- cb->clip = clip;
- cb->user = user;
- cb->track = track;
- cb->marker = marker;
- cb->marker_flag = marker->flag;
- cb->framenr = user->framenr;
-
- if (compact) {
- block = uiLayoutGetBlock(layout);
-
- if (cb->marker_flag & MARKER_DISABLED)
- tip = TIP_("Marker is disabled at current frame");
- else
- tip = TIP_("Marker is enabled at current frame");
-
- bt = uiDefIconButBitI(block, UI_BTYPE_TOGGLE_N, MARKER_DISABLED, 0, ICON_HIDE_OFF, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- &cb->marker_flag, 0, 0, 1, 0, tip);
- UI_but_funcN_set(bt, marker_update_cb, cb, NULL);
- UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
- }
- else {
- int width, height, step, digits;
- float pat_dim[2], search_dim[2], search_pos[2];
- uiLayout *col;
-
- BKE_movieclip_get_size(clip, user, &width, &height);
-
- if (track->flag & TRACK_LOCKED) {
- uiLayoutSetActive(layout, false);
- block = uiLayoutAbsoluteBlock(layout);
- uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Track is locked"), 0, 0, UI_UNIT_X * 15.0f, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
-
- return;
- }
-
- step = 100;
- digits = 2;
-
- BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
-
- sub_v2_v2v2(pat_dim, pat_max, pat_min);
- sub_v2_v2v2(search_dim, marker->search_max, marker->search_min);
-
- add_v2_v2v2(search_pos, marker->search_max, marker->search_min);
- mul_v2_fl(search_pos, 0.5);
-
- to_pixel_space(cb->marker_pos, marker->pos, width, height);
- to_pixel_space(cb->marker_pat, pat_dim, width, height);
- to_pixel_space(cb->marker_search, search_dim, width, height);
- to_pixel_space(cb->marker_search_pos, search_pos, width, height);
- to_pixel_space(cb->track_offset, track->offset, width, height);
-
- cb->marker_flag = marker->flag;
-
- block = uiLayoutAbsoluteBlock(layout);
- UI_block_func_handle_set(block, marker_block_handler, cb);
- UI_block_funcN_set(block, marker_update_cb, cb, NULL);
-
- if (cb->marker_flag & MARKER_DISABLED)
- tip = TIP_("Marker is disabled at current frame");
- else
- tip = TIP_("Marker is enabled at current frame");
-
- uiDefButBitI(block, UI_BTYPE_CHECKBOX_N, MARKER_DISABLED, B_MARKER_FLAG, IFACE_("Enabled"), 0.5 * UI_UNIT_X, 9.5 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y,
- &cb->marker_flag, 0, 0, 0, 0, tip);
-
- col = uiLayoutColumn(layout, true);
- uiLayoutSetActive(col, (cb->marker_flag & MARKER_DISABLED) == 0);
-
- block = uiLayoutAbsoluteBlock(col);
- UI_block_align_begin(block);
-
- uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Position:"), 0, 10 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- uiDefButF(block, UI_BTYPE_NUM, B_MARKER_POS, IFACE_("X:"), 0.5 * UI_UNIT_X, 9 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_pos[0],
- -10 * width, 10.0 * width, step, digits, TIP_("X-position of marker at frame in screen coordinates"));
- uiDefButF(block, UI_BTYPE_NUM, B_MARKER_POS, IFACE_("Y:"), 8.25 * UI_UNIT_X, 9 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_pos[1],
- -10 * height, 10.0 * height, step, digits,
- TIP_("Y-position of marker at frame in screen coordinates"));
-
- uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Offset:"), 0, 8 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- uiDefButF(block, UI_BTYPE_NUM, B_MARKER_OFFSET, IFACE_("X:"), 0.5 * UI_UNIT_X, 7 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y, &cb->track_offset[0],
- -10 * width, 10.0 * width, step, digits, TIP_("X-offset to parenting point"));
- uiDefButF(block, UI_BTYPE_NUM, B_MARKER_OFFSET, IFACE_("Y:"), 8.25 * UI_UNIT_X, 7 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y, &cb->track_offset[1],
- -10 * height, 10.0 * height, step, digits, TIP_("Y-offset to parenting point"));
-
- uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Pattern Area:"), 0, 6 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- uiDefButF(block, UI_BTYPE_NUM, B_MARKER_PAT_DIM, IFACE_("Width:"), 0.5 * UI_UNIT_X, 5 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_pat[0], 3.0f,
- 10.0 * width, step, digits, TIP_("Width of marker's pattern in screen coordinates"));
- uiDefButF(block, UI_BTYPE_NUM, B_MARKER_PAT_DIM, IFACE_("Height:"), 0.5 * UI_UNIT_X, 4 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_pat[1], 3.0f,
- 10.0 * height, step, digits, TIP_("Height of marker's pattern in screen coordinates"));
-
- uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Search Area:"), 0, 3 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- uiDefButF(block, UI_BTYPE_NUM, B_MARKER_SEARCH_POS, IFACE_("X:"), 0.5 * UI_UNIT_X, 2 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_search_pos[0],
- -width, width, step, digits, TIP_("X-position of search at frame relative to marker's position"));
- uiDefButF(block, UI_BTYPE_NUM, B_MARKER_SEARCH_POS, IFACE_("Y:"), 8.25 * UI_UNIT_X, 2 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_search_pos[1],
- -height, height, step, digits, TIP_("Y-position of search at frame relative to marker's position"));
- uiDefButF(block, UI_BTYPE_NUM, B_MARKER_SEARCH_DIM, IFACE_("Width:"), 0.5 * UI_UNIT_X, 1 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_search[0], 3.0f,
- 10.0 * width, step, digits, TIP_("Width of marker's search in screen coordinates"));
- uiDefButF(block, UI_BTYPE_NUM, B_MARKER_SEARCH_DIM, IFACE_("Height:"), 0.5 * UI_UNIT_X, 0 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_search[1], 3.0f,
- 10.0 * height, step, digits, TIP_("Height of marker's search in screen coordinates"));
-
- UI_block_align_end(block);
- }
+ PropertyRNA *prop;
+ uiBlock *block;
+ uiBut *bt;
+ PointerRNA clipptr;
+ MovieClip *clip;
+ MovieClipUser *user;
+ MovieTrackingTrack *track;
+ MovieTrackingMarker *marker;
+ MarkerUpdateCb *cb;
+ const char *tip;
+ float pat_min[2], pat_max[2];
+
+ if (!ptr->data)
+ return;
+
+ prop = RNA_struct_find_property(ptr, propname);
+ if (!prop) {
+ printf(
+ "%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ if (RNA_property_type(prop) != PROP_POINTER) {
+ printf("%s: expected pointer property for %s.%s\n",
+ __func__,
+ RNA_struct_identifier(ptr->type),
+ propname);
+ return;
+ }
+
+ clipptr = RNA_property_pointer_get(ptr, prop);
+ clip = (MovieClip *)clipptr.data;
+ user = userptr->data;
+ track = trackptr->data;
+
+ marker = BKE_tracking_marker_get(track, user->framenr);
+
+ cb = MEM_callocN(sizeof(MarkerUpdateCb), "uiTemplateMarker update_cb");
+ cb->compact = compact;
+ cb->clip = clip;
+ cb->user = user;
+ cb->track = track;
+ cb->marker = marker;
+ cb->marker_flag = marker->flag;
+ cb->framenr = user->framenr;
+
+ if (compact) {
+ block = uiLayoutGetBlock(layout);
+
+ if (cb->marker_flag & MARKER_DISABLED)
+ tip = TIP_("Marker is disabled at current frame");
+ else
+ tip = TIP_("Marker is enabled at current frame");
+
+ bt = uiDefIconButBitI(block,
+ UI_BTYPE_TOGGLE_N,
+ MARKER_DISABLED,
+ 0,
+ ICON_HIDE_OFF,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &cb->marker_flag,
+ 0,
+ 0,
+ 1,
+ 0,
+ tip);
+ UI_but_funcN_set(bt, marker_update_cb, cb, NULL);
+ UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ }
+ else {
+ int width, height, step, digits;
+ float pat_dim[2], search_dim[2], search_pos[2];
+ uiLayout *col;
+
+ BKE_movieclip_get_size(clip, user, &width, &height);
+
+ if (track->flag & TRACK_LOCKED) {
+ uiLayoutSetActive(layout, false);
+ block = uiLayoutAbsoluteBlock(layout);
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ IFACE_("Track is locked"),
+ 0,
+ 0,
+ UI_UNIT_X * 15.0f,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+
+ return;
+ }
+
+ step = 100;
+ digits = 2;
+
+ BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
+
+ sub_v2_v2v2(pat_dim, pat_max, pat_min);
+ sub_v2_v2v2(search_dim, marker->search_max, marker->search_min);
+
+ add_v2_v2v2(search_pos, marker->search_max, marker->search_min);
+ mul_v2_fl(search_pos, 0.5);
+
+ to_pixel_space(cb->marker_pos, marker->pos, width, height);
+ to_pixel_space(cb->marker_pat, pat_dim, width, height);
+ to_pixel_space(cb->marker_search, search_dim, width, height);
+ to_pixel_space(cb->marker_search_pos, search_pos, width, height);
+ to_pixel_space(cb->track_offset, track->offset, width, height);
+
+ cb->marker_flag = marker->flag;
+
+ block = uiLayoutAbsoluteBlock(layout);
+ UI_block_func_handle_set(block, marker_block_handler, cb);
+ UI_block_funcN_set(block, marker_update_cb, cb, NULL);
+
+ if (cb->marker_flag & MARKER_DISABLED)
+ tip = TIP_("Marker is disabled at current frame");
+ else
+ tip = TIP_("Marker is enabled at current frame");
+
+ uiDefButBitI(block,
+ UI_BTYPE_CHECKBOX_N,
+ MARKER_DISABLED,
+ B_MARKER_FLAG,
+ IFACE_("Enabled"),
+ 0.5 * UI_UNIT_X,
+ 9.5 * UI_UNIT_Y,
+ 7.25 * UI_UNIT_X,
+ UI_UNIT_Y,
+ &cb->marker_flag,
+ 0,
+ 0,
+ 0,
+ 0,
+ tip);
+
+ col = uiLayoutColumn(layout, true);
+ uiLayoutSetActive(col, (cb->marker_flag & MARKER_DISABLED) == 0);
+
+ block = uiLayoutAbsoluteBlock(col);
+ UI_block_align_begin(block);
+
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ IFACE_("Position:"),
+ 0,
+ 10 * UI_UNIT_Y,
+ 15 * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_MARKER_POS,
+ IFACE_("X:"),
+ 0.5 * UI_UNIT_X,
+ 9 * UI_UNIT_Y,
+ 7.25 * UI_UNIT_X,
+ UI_UNIT_Y,
+ &cb->marker_pos[0],
+ -10 * width,
+ 10.0 * width,
+ step,
+ digits,
+ TIP_("X-position of marker at frame in screen coordinates"));
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_MARKER_POS,
+ IFACE_("Y:"),
+ 8.25 * UI_UNIT_X,
+ 9 * UI_UNIT_Y,
+ 7.25 * UI_UNIT_X,
+ UI_UNIT_Y,
+ &cb->marker_pos[1],
+ -10 * height,
+ 10.0 * height,
+ step,
+ digits,
+ TIP_("Y-position of marker at frame in screen coordinates"));
+
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ IFACE_("Offset:"),
+ 0,
+ 8 * UI_UNIT_Y,
+ 15 * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_MARKER_OFFSET,
+ IFACE_("X:"),
+ 0.5 * UI_UNIT_X,
+ 7 * UI_UNIT_Y,
+ 7.25 * UI_UNIT_X,
+ UI_UNIT_Y,
+ &cb->track_offset[0],
+ -10 * width,
+ 10.0 * width,
+ step,
+ digits,
+ TIP_("X-offset to parenting point"));
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_MARKER_OFFSET,
+ IFACE_("Y:"),
+ 8.25 * UI_UNIT_X,
+ 7 * UI_UNIT_Y,
+ 7.25 * UI_UNIT_X,
+ UI_UNIT_Y,
+ &cb->track_offset[1],
+ -10 * height,
+ 10.0 * height,
+ step,
+ digits,
+ TIP_("Y-offset to parenting point"));
+
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ IFACE_("Pattern Area:"),
+ 0,
+ 6 * UI_UNIT_Y,
+ 15 * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_MARKER_PAT_DIM,
+ IFACE_("Width:"),
+ 0.5 * UI_UNIT_X,
+ 5 * UI_UNIT_Y,
+ 15 * UI_UNIT_X,
+ UI_UNIT_Y,
+ &cb->marker_pat[0],
+ 3.0f,
+ 10.0 * width,
+ step,
+ digits,
+ TIP_("Width of marker's pattern in screen coordinates"));
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_MARKER_PAT_DIM,
+ IFACE_("Height:"),
+ 0.5 * UI_UNIT_X,
+ 4 * UI_UNIT_Y,
+ 15 * UI_UNIT_X,
+ UI_UNIT_Y,
+ &cb->marker_pat[1],
+ 3.0f,
+ 10.0 * height,
+ step,
+ digits,
+ TIP_("Height of marker's pattern in screen coordinates"));
+
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ IFACE_("Search Area:"),
+ 0,
+ 3 * UI_UNIT_Y,
+ 15 * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_MARKER_SEARCH_POS,
+ IFACE_("X:"),
+ 0.5 * UI_UNIT_X,
+ 2 * UI_UNIT_Y,
+ 7.25 * UI_UNIT_X,
+ UI_UNIT_Y,
+ &cb->marker_search_pos[0],
+ -width,
+ width,
+ step,
+ digits,
+ TIP_("X-position of search at frame relative to marker's position"));
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_MARKER_SEARCH_POS,
+ IFACE_("Y:"),
+ 8.25 * UI_UNIT_X,
+ 2 * UI_UNIT_Y,
+ 7.25 * UI_UNIT_X,
+ UI_UNIT_Y,
+ &cb->marker_search_pos[1],
+ -height,
+ height,
+ step,
+ digits,
+ TIP_("Y-position of search at frame relative to marker's position"));
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_MARKER_SEARCH_DIM,
+ IFACE_("Width:"),
+ 0.5 * UI_UNIT_X,
+ 1 * UI_UNIT_Y,
+ 15 * UI_UNIT_X,
+ UI_UNIT_Y,
+ &cb->marker_search[0],
+ 3.0f,
+ 10.0 * width,
+ step,
+ digits,
+ TIP_("Width of marker's search in screen coordinates"));
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_MARKER_SEARCH_DIM,
+ IFACE_("Height:"),
+ 0.5 * UI_UNIT_X,
+ 0 * UI_UNIT_Y,
+ 15 * UI_UNIT_X,
+ UI_UNIT_Y,
+ &cb->marker_search[1],
+ 3.0f,
+ 10.0 * height,
+ step,
+ digits,
+ TIP_("Height of marker's search in screen coordinates"));
+
+ UI_block_align_end(block);
+ }
}
/********************* Footage Information Template ************************/
-void uiTemplateMovieclipInformation(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *userptr)
+void uiTemplateMovieclipInformation(uiLayout *layout,
+ PointerRNA *ptr,
+ const char *propname,
+ PointerRNA *userptr)
{
- PropertyRNA *prop;
- PointerRNA clipptr;
- MovieClip *clip;
- MovieClipUser *user;
- uiLayout *col;
- char str[1024];
- int width, height, framenr;
- ImBuf *ibuf;
- size_t ofs = 0;
-
- if (!ptr->data)
- return;
-
- prop = RNA_struct_find_property(ptr, propname);
- if (!prop) {
- printf("%s: property not found: %s.%s\n",
- __func__, RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- if (RNA_property_type(prop) != PROP_POINTER) {
- printf("%s: expected pointer property for %s.%s\n",
- __func__, RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- clipptr = RNA_property_pointer_get(ptr, prop);
- clip = (MovieClip *)clipptr.data;
- user = userptr->data;
-
- col = uiLayoutColumn(layout, false);
-
- ibuf = BKE_movieclip_get_ibuf_flag(clip, user, clip->flag, MOVIECLIP_CACHE_SKIP);
-
- /* Display frame dimensions, channels number and byffer type. */
- BKE_movieclip_get_size(clip, user, &width, &height);
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Size %d x %d"), width, height);
-
- if (ibuf) {
- if (ibuf->rect_float) {
- if (ibuf->channels != 4)
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_(", %d float channel(s)"), ibuf->channels);
- else if (ibuf->planes == R_IMF_PLANES_RGBA)
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_(", RGBA float"), sizeof(str) - ofs);
- else
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_(", RGB float"), sizeof(str) - ofs);
- }
- else {
- if (ibuf->planes == R_IMF_PLANES_RGBA)
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_(", RGBA byte"), sizeof(str) - ofs);
- else
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_(", RGB byte"), sizeof(str) - ofs);
- }
-
- if (clip->anim != NULL) {
- short frs_sec;
- float frs_sec_base;
- if (IMB_anim_get_fps(clip->anim, &frs_sec, &frs_sec_base, true)) {
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs,
- IFACE_(", %.2f fps"),
- (float)frs_sec / frs_sec_base);
- }
- }
- }
- else {
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_(", failed to load"), sizeof(str) - ofs);
- }
-
- uiItemL(col, str, ICON_NONE);
-
- /* Display current frame number. */
- framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
- if (framenr <= clip->len)
- BLI_snprintf(str, sizeof(str), IFACE_("Frame: %d / %d"), framenr, clip->len);
- else
- BLI_snprintf(str, sizeof(str), IFACE_("Frame: - / %d"), clip->len);
- uiItemL(col, str, ICON_NONE);
-
- /* Display current file name if it's a sequence clip. */
- if (clip->source == MCLIP_SRC_SEQUENCE) {
- char filepath[FILE_MAX];
- const char *file;
-
- if (framenr <= clip->len) {
- BKE_movieclip_filename_for_frame(clip, user, filepath);
- file = BLI_last_slash(filepath);
- }
- else {
- file = "-";
- }
-
- BLI_snprintf(str, sizeof(str), IFACE_("File: %s"), file);
-
- uiItemL(col, str, ICON_NONE);
- }
-
- IMB_freeImBuf(ibuf);
+ PropertyRNA *prop;
+ PointerRNA clipptr;
+ MovieClip *clip;
+ MovieClipUser *user;
+ uiLayout *col;
+ char str[1024];
+ int width, height, framenr;
+ ImBuf *ibuf;
+ size_t ofs = 0;
+
+ if (!ptr->data)
+ return;
+
+ prop = RNA_struct_find_property(ptr, propname);
+ if (!prop) {
+ printf(
+ "%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ if (RNA_property_type(prop) != PROP_POINTER) {
+ printf("%s: expected pointer property for %s.%s\n",
+ __func__,
+ RNA_struct_identifier(ptr->type),
+ propname);
+ return;
+ }
+
+ clipptr = RNA_property_pointer_get(ptr, prop);
+ clip = (MovieClip *)clipptr.data;
+ user = userptr->data;
+
+ col = uiLayoutColumn(layout, false);
+
+ ibuf = BKE_movieclip_get_ibuf_flag(clip, user, clip->flag, MOVIECLIP_CACHE_SKIP);
+
+ /* Display frame dimensions, channels number and byffer type. */
+ BKE_movieclip_get_size(clip, user, &width, &height);
+ ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Size %d x %d"), width, height);
+
+ if (ibuf) {
+ if (ibuf->rect_float) {
+ if (ibuf->channels != 4)
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, IFACE_(", %d float channel(s)"), ibuf->channels);
+ else if (ibuf->planes == R_IMF_PLANES_RGBA)
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(", RGBA float"), sizeof(str) - ofs);
+ else
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(", RGB float"), sizeof(str) - ofs);
+ }
+ else {
+ if (ibuf->planes == R_IMF_PLANES_RGBA)
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(", RGBA byte"), sizeof(str) - ofs);
+ else
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(", RGB byte"), sizeof(str) - ofs);
+ }
+
+ if (clip->anim != NULL) {
+ short frs_sec;
+ float frs_sec_base;
+ if (IMB_anim_get_fps(clip->anim, &frs_sec, &frs_sec_base, true)) {
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, IFACE_(", %.2f fps"), (float)frs_sec / frs_sec_base);
+ }
+ }
+ }
+ else {
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(", failed to load"), sizeof(str) - ofs);
+ }
+
+ uiItemL(col, str, ICON_NONE);
+
+ /* Display current frame number. */
+ framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
+ if (framenr <= clip->len)
+ BLI_snprintf(str, sizeof(str), IFACE_("Frame: %d / %d"), framenr, clip->len);
+ else
+ BLI_snprintf(str, sizeof(str), IFACE_("Frame: - / %d"), clip->len);
+ uiItemL(col, str, ICON_NONE);
+
+ /* Display current file name if it's a sequence clip. */
+ if (clip->source == MCLIP_SRC_SEQUENCE) {
+ char filepath[FILE_MAX];
+ const char *file;
+
+ if (framenr <= clip->len) {
+ BKE_movieclip_filename_for_frame(clip, user, filepath);
+ file = BLI_last_slash(filepath);
+ }
+ else {
+ file = "-";
+ }
+
+ BLI_snprintf(str, sizeof(str), IFACE_("File: %s"), file);
+
+ uiItemL(col, str, ICON_NONE);
+ }
+
+ IMB_freeImBuf(ibuf);
}
diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c
index ef2e5b4ea3a..8ac0870f7f1 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_draw.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c
@@ -48,360 +48,381 @@
#include "GPU_immediate.h"
#include "GPU_state.h"
-#include "clip_intern.h" /* own include */
+#include "clip_intern.h" /* own include */
static void track_channel_color(MovieTrackingTrack *track, float default_color[3], float color[3])
{
- if (track->flag & TRACK_CUSTOMCOLOR) {
- float bg[3];
- UI_GetThemeColor3fv(TH_HEADER, bg);
-
- interp_v3_v3v3(color, track->color, bg, 0.5);
- }
- else {
- if (default_color)
- copy_v3_v3(color, default_color);
- else
- UI_GetThemeColor3fv(TH_HEADER, color);
- }
+ if (track->flag & TRACK_CUSTOMCOLOR) {
+ float bg[3];
+ UI_GetThemeColor3fv(TH_HEADER, bg);
+
+ interp_v3_v3v3(color, track->color, bg, 0.5);
+ }
+ else {
+ if (default_color)
+ copy_v3_v3(color, default_color);
+ else
+ UI_GetThemeColor3fv(TH_HEADER, color);
+ }
}
-static void draw_keyframe_shape(float x, float y, bool sel, float alpha,
- unsigned int pos_id, unsigned int color_id)
+static void draw_keyframe_shape(
+ float x, float y, bool sel, float alpha, unsigned int pos_id, unsigned int color_id)
{
- float color[4] = { 0.91f, 0.91f, 0.91f, alpha };
- if (sel) {
- UI_GetThemeColorShadeAlpha4fv(TH_STRIP_SELECT, 50, -255 * (1.0f - alpha), color);
- }
+ float color[4] = {0.91f, 0.91f, 0.91f, alpha};
+ if (sel) {
+ UI_GetThemeColorShadeAlpha4fv(TH_STRIP_SELECT, 50, -255 * (1.0f - alpha), color);
+ }
- immAttr4fv(color_id, color);
- immVertex2f(pos_id, x, y);
+ immAttr4fv(color_id, color);
+ immVertex2f(pos_id, x, y);
}
static void clip_draw_dopesheet_background(ARegion *ar, MovieClip *clip, unsigned int pos_id)
{
- View2D *v2d = &ar->v2d;
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
- MovieTrackingDopesheetCoverageSegment *coverage_segment;
-
- for (coverage_segment = dopesheet->coverage_segments.first;
- coverage_segment;
- coverage_segment = coverage_segment->next)
- {
- if (coverage_segment->coverage < TRACKING_COVERAGE_OK) {
- int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, coverage_segment->start_frame);
- int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, coverage_segment->end_frame);
-
- if (coverage_segment->coverage == TRACKING_COVERAGE_BAD) {
- immUniformColor4f(1.0f, 0.0f, 0.0f, 0.07f);
- }
- else {
- immUniformColor4f(1.0f, 1.0f, 0.0f, 0.07f);
- }
-
- immRectf(pos_id, start_frame, v2d->cur.ymin, end_frame, v2d->cur.ymax);
- }
- }
+ View2D *v2d = &ar->v2d;
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
+ MovieTrackingDopesheetCoverageSegment *coverage_segment;
+
+ for (coverage_segment = dopesheet->coverage_segments.first; coverage_segment;
+ coverage_segment = coverage_segment->next) {
+ if (coverage_segment->coverage < TRACKING_COVERAGE_OK) {
+ int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip,
+ coverage_segment->start_frame);
+ int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, coverage_segment->end_frame);
+
+ if (coverage_segment->coverage == TRACKING_COVERAGE_BAD) {
+ immUniformColor4f(1.0f, 0.0f, 0.0f, 0.07f);
+ }
+ else {
+ immUniformColor4f(1.0f, 1.0f, 0.0f, 0.07f);
+ }
+
+ immRectf(pos_id, start_frame, v2d->cur.ymin, end_frame, v2d->cur.ymax);
+ }
+ }
}
void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
{
- MovieClip *clip = ED_space_clip_get_clip(sc);
- View2D *v2d = &ar->v2d;
-
- /* frame range */
- clip_draw_sfra_efra(v2d, scene);
-
- if (clip) {
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
- MovieTrackingDopesheetChannel *channel;
- float strip[4], selected_strip[4];
- float height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT);
-
- uint keyframe_len = 0;
-
- GPUVertFormat *format = immVertexFormat();
- uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* don't use totrect set, as the width stays the same
- * (NOTE: this is ok here, the configuration is pretty straightforward)
- */
- v2d->tot.ymin = (float)(-height);
-
- float y = (float) CHANNEL_FIRST;
-
- /* setup colors for regular and selected strips */
- UI_GetThemeColor3fv(TH_STRIP, strip);
- UI_GetThemeColor3fv(TH_STRIP_SELECT, selected_strip);
-
- strip[3] = 0.5f;
- selected_strip[3] = 1.0f;
-
- GPU_blend(true);
-
- clip_draw_dopesheet_background(ar, clip, pos_id);
-
- for (channel = dopesheet->channels.first; channel; channel = channel->next) {
- float yminc = (float) (y - CHANNEL_HEIGHT_HALF);
- float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF);
-
- /* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
- {
- MovieTrackingTrack *track = channel->track;
- int i;
- bool sel = (track->flag & TRACK_DOPE_SEL) != 0;
-
- /* selection background */
- if (sel) {
- float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
- float default_color[4] = {0.8f, 0.93f, 0.8f, 0.3f};
-
- track_channel_color(track, default_color, color);
- immUniformColor4fv(color);
-
- immRectf(pos_id, v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF,
- v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF);
- }
-
- /* tracked segments */
- for (i = 0; i < channel->tot_segment; i++) {
- int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i]);
- int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i + 1]);
-
- immUniformColor4fv(sel ? selected_strip : strip);
-
- if (start_frame != end_frame) {
- immRectf(pos_id, start_frame, (float) y - STRIP_HEIGHT_HALF,
- end_frame, (float) y + STRIP_HEIGHT_HALF);
- keyframe_len += 2;
- }
- else {
- keyframe_len++;
- }
- }
-
- /* keyframes */
- i = 0;
- while (i < track->markersnr) {
- MovieTrackingMarker *marker = &track->markers[i];
-
- if ((marker->flag & (MARKER_DISABLED | MARKER_TRACKED)) == 0) {
- keyframe_len++;
- }
-
- i++;
- }
- }
-
- /* adjust y-position for next one */
- y -= CHANNEL_STEP;
- }
-
- immUnbindProgram();
-
- if (keyframe_len > 0) {
- /* draw keyframe markers */
- format = immVertexFormat();
- pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- uint outline_color_id = GPU_vertformat_attr_add(format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
-
- immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
- GPU_enable_program_point_size();
- immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
- immBegin(GPU_PRIM_POINTS, keyframe_len);
-
- /* all same size with black outline */
- immAttr1f(size_id, 2.0f * STRIP_HEIGHT_HALF);
- immAttr4ub(outline_color_id, 0, 0, 0, 255);
- immAttr1u(flags_id, 0);
-
- y = (float) CHANNEL_FIRST; /* start again at the top */
- for (channel = dopesheet->channels.first; channel; channel = channel->next) {
- float yminc = (float) (y - CHANNEL_HEIGHT_HALF);
- float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF);
-
- /* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
- {
- MovieTrackingTrack *track = channel->track;
- int i;
- bool sel = (track->flag & TRACK_DOPE_SEL) != 0;
- float alpha = (track->flag & TRACK_LOCKED) ? 0.5f : 1.0f;
-
- /* tracked segments */
- for (i = 0; i < channel->tot_segment; i++) {
- int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i]);
- int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i + 1]);
-
- if (start_frame != end_frame) {
- draw_keyframe_shape(start_frame, y, sel, alpha, pos_id, color_id);
- draw_keyframe_shape(end_frame, y, sel, alpha, pos_id, color_id);
- }
- else {
- draw_keyframe_shape(start_frame, y, sel, alpha, pos_id, color_id);
- }
- }
-
- /* keyframes */
- i = 0;
- while (i < track->markersnr) {
- MovieTrackingMarker *marker = &track->markers[i];
-
- if ((marker->flag & (MARKER_DISABLED | MARKER_TRACKED)) == 0) {
- int framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr);
-
- draw_keyframe_shape(framenr, y, sel, alpha, pos_id, color_id);
- }
-
- i++;
- }
- }
-
- /* adjust y-position for next one */
- y -= CHANNEL_STEP;
- }
-
- immEnd();
- GPU_disable_program_point_size();
- immUnbindProgram();
- }
-
- GPU_blend(false);
- }
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ View2D *v2d = &ar->v2d;
+
+ /* frame range */
+ clip_draw_sfra_efra(v2d, scene);
+
+ if (clip) {
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
+ MovieTrackingDopesheetChannel *channel;
+ float strip[4], selected_strip[4];
+ float height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT);
+
+ uint keyframe_len = 0;
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* don't use totrect set, as the width stays the same
+ * (NOTE: this is ok here, the configuration is pretty straightforward)
+ */
+ v2d->tot.ymin = (float)(-height);
+
+ float y = (float)CHANNEL_FIRST;
+
+ /* setup colors for regular and selected strips */
+ UI_GetThemeColor3fv(TH_STRIP, strip);
+ UI_GetThemeColor3fv(TH_STRIP_SELECT, selected_strip);
+
+ strip[3] = 0.5f;
+ selected_strip[3] = 1.0f;
+
+ GPU_blend(true);
+
+ clip_draw_dopesheet_background(ar, clip, pos_id);
+
+ for (channel = dopesheet->channels.first; channel; channel = channel->next) {
+ float yminc = (float)(y - CHANNEL_HEIGHT_HALF);
+ float ymaxc = (float)(y + CHANNEL_HEIGHT_HALF);
+
+ /* check if visible */
+ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ MovieTrackingTrack *track = channel->track;
+ int i;
+ bool sel = (track->flag & TRACK_DOPE_SEL) != 0;
+
+ /* selection background */
+ if (sel) {
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
+ float default_color[4] = {0.8f, 0.93f, 0.8f, 0.3f};
+
+ track_channel_color(track, default_color, color);
+ immUniformColor4fv(color);
+
+ immRectf(pos_id,
+ v2d->cur.xmin,
+ (float)y - CHANNEL_HEIGHT_HALF,
+ v2d->cur.xmax + EXTRA_SCROLL_PAD,
+ (float)y + CHANNEL_HEIGHT_HALF);
+ }
+
+ /* tracked segments */
+ for (i = 0; i < channel->tot_segment; i++) {
+ int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip,
+ channel->segments[2 * i]);
+ int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip,
+ channel->segments[2 * i + 1]);
+
+ immUniformColor4fv(sel ? selected_strip : strip);
+
+ if (start_frame != end_frame) {
+ immRectf(pos_id,
+ start_frame,
+ (float)y - STRIP_HEIGHT_HALF,
+ end_frame,
+ (float)y + STRIP_HEIGHT_HALF);
+ keyframe_len += 2;
+ }
+ else {
+ keyframe_len++;
+ }
+ }
+
+ /* keyframes */
+ i = 0;
+ while (i < track->markersnr) {
+ MovieTrackingMarker *marker = &track->markers[i];
+
+ if ((marker->flag & (MARKER_DISABLED | MARKER_TRACKED)) == 0) {
+ keyframe_len++;
+ }
+
+ i++;
+ }
+ }
+
+ /* adjust y-position for next one */
+ y -= CHANNEL_STEP;
+ }
+
+ immUnbindProgram();
+
+ if (keyframe_len > 0) {
+ /* draw keyframe markers */
+ format = immVertexFormat();
+ pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ uint outline_color_id = GPU_vertformat_attr_add(
+ format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
+
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ GPU_enable_program_point_size();
+ immUniform2f(
+ "ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
+ immBegin(GPU_PRIM_POINTS, keyframe_len);
+
+ /* all same size with black outline */
+ immAttr1f(size_id, 2.0f * STRIP_HEIGHT_HALF);
+ immAttr4ub(outline_color_id, 0, 0, 0, 255);
+ immAttr1u(flags_id, 0);
+
+ y = (float)CHANNEL_FIRST; /* start again at the top */
+ for (channel = dopesheet->channels.first; channel; channel = channel->next) {
+ float yminc = (float)(y - CHANNEL_HEIGHT_HALF);
+ float ymaxc = (float)(y + CHANNEL_HEIGHT_HALF);
+
+ /* check if visible */
+ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ MovieTrackingTrack *track = channel->track;
+ int i;
+ bool sel = (track->flag & TRACK_DOPE_SEL) != 0;
+ float alpha = (track->flag & TRACK_LOCKED) ? 0.5f : 1.0f;
+
+ /* tracked segments */
+ for (i = 0; i < channel->tot_segment; i++) {
+ int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip,
+ channel->segments[2 * i]);
+ int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip,
+ channel->segments[2 * i + 1]);
+
+ if (start_frame != end_frame) {
+ draw_keyframe_shape(start_frame, y, sel, alpha, pos_id, color_id);
+ draw_keyframe_shape(end_frame, y, sel, alpha, pos_id, color_id);
+ }
+ else {
+ draw_keyframe_shape(start_frame, y, sel, alpha, pos_id, color_id);
+ }
+ }
+
+ /* keyframes */
+ i = 0;
+ while (i < track->markersnr) {
+ MovieTrackingMarker *marker = &track->markers[i];
+
+ if ((marker->flag & (MARKER_DISABLED | MARKER_TRACKED)) == 0) {
+ int framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr);
+
+ draw_keyframe_shape(framenr, y, sel, alpha, pos_id, color_id);
+ }
+
+ i++;
+ }
+ }
+
+ /* adjust y-position for next one */
+ y -= CHANNEL_STEP;
+ }
+
+ immEnd();
+ GPU_disable_program_point_size();
+ immUnbindProgram();
+ }
+
+ GPU_blend(false);
+ }
}
void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
{
- ScrArea *sa = CTX_wm_area(C);
- SpaceClip *sc = CTX_wm_space_clip(C);
- View2D *v2d = &ar->v2d;
- MovieClip *clip = ED_space_clip_get_clip(sc);
- uiStyle *style = UI_style_get();
- int fontid = style->widget.uifont_id;
-
- if (!clip)
- return;
-
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
- int height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT);
-
- if (height > BLI_rcti_size_y(&v2d->mask)) {
- /* don't use totrect set, as the width stays the same
- * (NOTE: this is ok here, the configuration is pretty straightforward)
- */
- v2d->tot.ymin = (float)(-height);
- }
-
- /* 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);
-
- /* loop through channels, and set up drawing depending on their type
- * first pass: just the standard GL-drawing for backdrop + text
- */
- float y = (float) CHANNEL_FIRST;
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- MovieTrackingDopesheetChannel *channel;
- for (channel = dopesheet->channels.first; channel; channel = channel->next) {
- float yminc = (float) (y - CHANNEL_HEIGHT_HALF);
- float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF);
-
- /* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
- {
- MovieTrackingTrack *track = channel->track;
- float color[3];
- track_channel_color(track, NULL, color);
- immUniformColor3fv(color);
-
- immRectf(pos, v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF,
- v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF);
- }
-
- /* adjust y-position for next one */
- y -= CHANNEL_STEP;
- }
- immUnbindProgram();
-
- /* second pass: text */
- y = (float) CHANNEL_FIRST;
-
- BLF_size(fontid, 11.0f * U.pixelsize, U.dpi);
-
- for (channel = dopesheet->channels.first; channel; channel = channel->next) {
- float yminc = (float) (y - CHANNEL_HEIGHT_HALF);
- float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF);
-
- /* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
- {
- MovieTrackingTrack *track = channel->track;
- bool sel = (track->flag & TRACK_DOPE_SEL) != 0;
-
- UI_FontThemeColor(fontid, sel ? TH_TEXT_HI : TH_TEXT);
-
- float font_height = BLF_height(fontid, channel->name, sizeof(channel->name));
- BLF_position(fontid, v2d->cur.xmin + CHANNEL_PAD,
- y - font_height / 2.0f, 0.0f);
- BLF_draw(fontid, channel->name, strlen(channel->name));
- }
-
- /* adjust y-position for next one */
- y -= CHANNEL_STEP;
- }
-
- /* third pass: widgets */
- uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
- y = (float) CHANNEL_FIRST;
-
- /* get RNA properties (once) */
- PropertyRNA *chan_prop_lock = RNA_struct_type_find_property(&RNA_MovieTrackingTrack, "lock");
- BLI_assert(chan_prop_lock);
-
- GPU_blend(true);
- for (channel = dopesheet->channels.first; channel; channel = channel->next) {
- float yminc = (float)(y - CHANNEL_HEIGHT_HALF);
- float ymaxc = (float)(y + CHANNEL_HEIGHT_HALF);
-
- /* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
- {
- MovieTrackingTrack *track = channel->track;
- const int icon = (track->flag & TRACK_LOCKED) ? ICON_LOCKED : ICON_UNLOCKED;
- PointerRNA ptr;
-
- RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, &ptr);
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 1, icon,
- v2d->cur.xmax - UI_UNIT_X - CHANNEL_PAD, y - UI_UNIT_Y / 2.0f,
- UI_UNIT_X, UI_UNIT_Y, &ptr, chan_prop_lock, 0, 0, 0, 0, 0, NULL);
- UI_block_emboss_set(block, UI_EMBOSS);
- }
-
- /* adjust y-position for next one */
- y -= CHANNEL_STEP;
- }
- GPU_blend(false);
-
- UI_block_end(C, block);
- UI_block_draw(C, block);
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ View2D *v2d = &ar->v2d;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ uiStyle *style = UI_style_get();
+ int fontid = style->widget.uifont_id;
+
+ if (!clip)
+ return;
+
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
+ int height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT);
+
+ if (height > BLI_rcti_size_y(&v2d->mask)) {
+ /* don't use totrect set, as the width stays the same
+ * (NOTE: this is ok here, the configuration is pretty straightforward)
+ */
+ v2d->tot.ymin = (float)(-height);
+ }
+
+ /* 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);
+
+ /* loop through channels, and set up drawing depending on their type
+ * first pass: just the standard GL-drawing for backdrop + text
+ */
+ float y = (float)CHANNEL_FIRST;
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ MovieTrackingDopesheetChannel *channel;
+ for (channel = dopesheet->channels.first; channel; channel = channel->next) {
+ float yminc = (float)(y - CHANNEL_HEIGHT_HALF);
+ float ymaxc = (float)(y + CHANNEL_HEIGHT_HALF);
+
+ /* check if visible */
+ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ MovieTrackingTrack *track = channel->track;
+ float color[3];
+ track_channel_color(track, NULL, color);
+ immUniformColor3fv(color);
+
+ immRectf(pos,
+ v2d->cur.xmin,
+ (float)y - CHANNEL_HEIGHT_HALF,
+ v2d->cur.xmax + EXTRA_SCROLL_PAD,
+ (float)y + CHANNEL_HEIGHT_HALF);
+ }
+
+ /* adjust y-position for next one */
+ y -= CHANNEL_STEP;
+ }
+ immUnbindProgram();
+
+ /* second pass: text */
+ y = (float)CHANNEL_FIRST;
+
+ BLF_size(fontid, 11.0f * U.pixelsize, U.dpi);
+
+ for (channel = dopesheet->channels.first; channel; channel = channel->next) {
+ float yminc = (float)(y - CHANNEL_HEIGHT_HALF);
+ float ymaxc = (float)(y + CHANNEL_HEIGHT_HALF);
+
+ /* check if visible */
+ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ MovieTrackingTrack *track = channel->track;
+ bool sel = (track->flag & TRACK_DOPE_SEL) != 0;
+
+ UI_FontThemeColor(fontid, sel ? TH_TEXT_HI : TH_TEXT);
+
+ float font_height = BLF_height(fontid, channel->name, sizeof(channel->name));
+ BLF_position(fontid, v2d->cur.xmin + CHANNEL_PAD, y - font_height / 2.0f, 0.0f);
+ BLF_draw(fontid, channel->name, strlen(channel->name));
+ }
+
+ /* adjust y-position for next one */
+ y -= CHANNEL_STEP;
+ }
+
+ /* third pass: widgets */
+ uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ y = (float)CHANNEL_FIRST;
+
+ /* get RNA properties (once) */
+ PropertyRNA *chan_prop_lock = RNA_struct_type_find_property(&RNA_MovieTrackingTrack, "lock");
+ BLI_assert(chan_prop_lock);
+
+ GPU_blend(true);
+ for (channel = dopesheet->channels.first; channel; channel = channel->next) {
+ float yminc = (float)(y - CHANNEL_HEIGHT_HALF);
+ float ymaxc = (float)(y + CHANNEL_HEIGHT_HALF);
+
+ /* check if visible */
+ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ MovieTrackingTrack *track = channel->track;
+ const int icon = (track->flag & TRACK_LOCKED) ? ICON_LOCKED : ICON_UNLOCKED;
+ PointerRNA ptr;
+
+ RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, &ptr);
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 1,
+ icon,
+ v2d->cur.xmax - UI_UNIT_X - CHANNEL_PAD,
+ y - UI_UNIT_Y / 2.0f,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &ptr,
+ chan_prop_lock,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL);
+ UI_block_emboss_set(block, UI_EMBOSS);
+ }
+
+ /* adjust y-position for next one */
+ y -= CHANNEL_STEP;
+ }
+ GPU_blend(false);
+
+ UI_block_end(C, block);
+ UI_block_draw(C, block);
}
diff --git a/source/blender/editors/space_clip/clip_dopesheet_ops.c b/source/blender/editors/space_clip/clip_dopesheet_ops.c
index e2689706452..e7f0f8c3fcc 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_ops.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_ops.c
@@ -43,160 +43,170 @@
#include "UI_view2d.h"
-#include "clip_intern.h" // own include
+#include "clip_intern.h" // own include
static bool space_clip_dopesheet_poll(bContext *C)
{
- if (ED_space_clip_tracking_poll(C)) {
- SpaceClip *sc = CTX_wm_space_clip(C);
+ if (ED_space_clip_tracking_poll(C)) {
+ SpaceClip *sc = CTX_wm_space_clip(C);
- if (sc->view == SC_VIEW_DOPESHEET) {
- ARegion *ar = CTX_wm_region(C);
+ if (sc->view == SC_VIEW_DOPESHEET) {
+ ARegion *ar = CTX_wm_region(C);
- return ar->regiontype == RGN_TYPE_PREVIEW;
- }
- }
+ return ar->regiontype == RGN_TYPE_PREVIEW;
+ }
+ }
- return false;
+ return false;
}
/********************** select channel operator *********************/
static bool dopesheet_select_channel_poll(bContext *C)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
- if (sc && sc->clip)
- return sc->view == SC_VIEW_DOPESHEET;
+ if (sc && sc->clip)
+ return sc->view == SC_VIEW_DOPESHEET;
- return false;
+ return false;
}
static int dopesheet_select_channel_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
- MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
- MovieTrackingDopesheetChannel *channel;
- ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
- float location[2];
- const bool extend = RNA_boolean_get(op->ptr, "extend");
- int current_channel_index = 0, channel_index;
- const bool show_selected_only = (dopesheet->flag & TRACKING_DOPE_SELECTED_ONLY) != 0;
-
- RNA_float_get_array(op->ptr, "location", location);
- channel_index = -(location[1] - (CHANNEL_FIRST + CHANNEL_HEIGHT_HALF)) / CHANNEL_STEP;
-
- for (channel = dopesheet->channels.first; channel; channel = channel->next) {
- MovieTrackingTrack *track = channel->track;
-
- if (current_channel_index == channel_index) {
- if (extend)
- track->flag ^= TRACK_DOPE_SEL;
- else
- track->flag |= TRACK_DOPE_SEL;
-
- if (track->flag & TRACK_DOPE_SEL) {
- tracking->act_track = track;
- BKE_tracking_track_select(tracksbase, track, TRACK_AREA_ALL, true);
- }
- else if (show_selected_only == false) {
- BKE_tracking_track_deselect(track, TRACK_AREA_ALL);
- }
- }
- else if (!extend)
- track->flag &= ~TRACK_DOPE_SEL;
-
- current_channel_index++;
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
+ MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
+ MovieTrackingDopesheetChannel *channel;
+ ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
+ float location[2];
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ int current_channel_index = 0, channel_index;
+ const bool show_selected_only = (dopesheet->flag & TRACKING_DOPE_SELECTED_ONLY) != 0;
+
+ RNA_float_get_array(op->ptr, "location", location);
+ channel_index = -(location[1] - (CHANNEL_FIRST + CHANNEL_HEIGHT_HALF)) / CHANNEL_STEP;
+
+ for (channel = dopesheet->channels.first; channel; channel = channel->next) {
+ MovieTrackingTrack *track = channel->track;
+
+ if (current_channel_index == channel_index) {
+ if (extend)
+ track->flag ^= TRACK_DOPE_SEL;
+ else
+ track->flag |= TRACK_DOPE_SEL;
+
+ if (track->flag & TRACK_DOPE_SEL) {
+ tracking->act_track = track;
+ BKE_tracking_track_select(tracksbase, track, TRACK_AREA_ALL, true);
+ }
+ else if (show_selected_only == false) {
+ BKE_tracking_track_deselect(track, TRACK_AREA_ALL);
+ }
+ }
+ else if (!extend)
+ track->flag &= ~TRACK_DOPE_SEL;
+
+ current_channel_index++;
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+
+ return OPERATOR_FINISHED;
}
static int dopesheet_select_channel_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- float location[2];
+ ARegion *ar = CTX_wm_region(C);
+ float location[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
- RNA_float_set_array(op->ptr, "location", location);
+ UI_view2d_region_to_view(&ar->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);
+ return dopesheet_select_channel_exec(C, op);
}
void CLIP_OT_dopesheet_select_channel(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Channel";
- ot->description = "Select movie tracking channel";
- ot->idname = "CLIP_OT_dopesheet_select_channel";
-
- /* api callbacks */
- ot->invoke = dopesheet_select_channel_invoke;
- ot->exec = dopesheet_select_channel_exec;
- ot->poll = dopesheet_select_channel_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
- "Location", "Mouse location to select channel", -100.0f, 100.0f);
- RNA_def_boolean(ot->srna, "extend", 0,
- "Extend", "Extend selection rather than clearing the existing selection");
+ /* identifiers */
+ ot->name = "Select Channel";
+ ot->description = "Select movie tracking channel";
+ ot->idname = "CLIP_OT_dopesheet_select_channel";
+
+ /* api callbacks */
+ ot->invoke = dopesheet_select_channel_invoke;
+ ot->exec = dopesheet_select_channel_exec;
+ ot->poll = dopesheet_select_channel_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float_vector(ot->srna,
+ "location",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Location",
+ "Mouse location to select channel",
+ -100.0f,
+ 100.0f);
+ RNA_def_boolean(ot->srna,
+ "extend",
+ 0,
+ "Extend",
+ "Extend selection rather than clearing the existing selection");
}
/********************** View All operator *********************/
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;
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
- MovieTrackingDopesheetChannel *channel;
- int frame_min = INT_MAX, frame_max = INT_MIN;
-
- for (channel = dopesheet->channels.first; channel; channel = channel->next) {
- frame_min = min_ii(frame_min, channel->segments[0]);
- frame_max = max_ii(frame_max, channel->segments[channel->tot_segment]);
- }
-
- if (frame_min < frame_max) {
- float extra;
-
- v2d->cur.xmin = frame_min;
- v2d->cur.xmax = frame_max;
-
- /* we need an extra "buffer" factor on either side so that the endpoints are visible */
- extra = 0.01f * BLI_rctf_size_x(&v2d->cur);
- v2d->cur.xmin -= extra;
- v2d->cur.xmax += extra;
-
- ED_region_tag_redraw(ar);
- }
-
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
+ View2D *v2d = &ar->v2d;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
+ MovieTrackingDopesheetChannel *channel;
+ int frame_min = INT_MAX, frame_max = INT_MIN;
+
+ for (channel = dopesheet->channels.first; channel; channel = channel->next) {
+ frame_min = min_ii(frame_min, channel->segments[0]);
+ frame_max = max_ii(frame_max, channel->segments[channel->tot_segment]);
+ }
+
+ if (frame_min < frame_max) {
+ float extra;
+
+ v2d->cur.xmin = frame_min;
+ v2d->cur.xmax = frame_max;
+
+ /* we need an extra "buffer" factor on either side so that the endpoints are visible */
+ extra = 0.01f * BLI_rctf_size_x(&v2d->cur);
+ v2d->cur.xmin -= extra;
+ v2d->cur.xmax += extra;
+
+ ED_region_tag_redraw(ar);
+ }
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_dopesheet_view_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View All";
- ot->description = "Reset viewable area to show full keyframe range";
- ot->idname = "CLIP_OT_dopesheet_view_all";
+ /* identifiers */
+ ot->name = "View All";
+ ot->description = "Reset viewable area to show full keyframe range";
+ ot->idname = "CLIP_OT_dopesheet_view_all";
- /* api callbacks */
- ot->exec = dopesheet_view_all_exec;
- ot->poll = space_clip_dopesheet_poll;
+ /* api callbacks */
+ ot->exec = dopesheet_view_all_exec;
+ ot->poll = space_clip_dopesheet_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index 7c400f8a417..a3aa4f4bed5 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -62,1829 +62,1943 @@
#include "BLF_api.h"
-#include "clip_intern.h" // own include
+#include "clip_intern.h" // own include
/*********************** 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, unsigned int pos)
{
- int height = (frame == cfra) ? 22 : 10;
- int x = (frame - sfra) * framelen;
-
- if (width == 1) {
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2i(pos, x, 0);
- immVertex2i(pos, x, height * UI_DPI_FAC);
- immEnd();
- }
- else {
- immRecti(pos, x, 0, x + width, height * UI_DPI_FAC);
- }
+ int height = (frame == cfra) ? 22 : 10;
+ int x = (frame - sfra) * framelen;
+
+ if (width == 1) {
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2i(pos, x, 0);
+ immVertex2i(pos, x, height * UI_DPI_FAC);
+ immEnd();
+ }
+ else {
+ immRecti(pos, x, 0, x + width, height * UI_DPI_FAC);
+ }
}
-static int generic_track_get_markersnr(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track)
+static int generic_track_get_markersnr(MovieTrackingTrack *track,
+ MovieTrackingPlaneTrack *plane_track)
{
- if (track) {
- return track->markersnr;
- }
- else if (plane_track) {
- return plane_track->markersnr;
- }
-
- return 0;
+ if (track) {
+ return track->markersnr;
+ }
+ else if (plane_track) {
+ return plane_track->markersnr;
+ }
+
+ return 0;
}
-static int generic_track_get_marker_framenr(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track,
+static int generic_track_get_marker_framenr(MovieTrackingTrack *track,
+ MovieTrackingPlaneTrack *plane_track,
int marker_index)
{
- if (track) {
- BLI_assert(marker_index < track->markersnr);
- return track->markers[marker_index].framenr;
- }
- else if (plane_track) {
- BLI_assert(marker_index < plane_track->markersnr);
- return plane_track->markers[marker_index].framenr;
- }
-
- return 0;
+ if (track) {
+ BLI_assert(marker_index < track->markersnr);
+ return track->markers[marker_index].framenr;
+ }
+ else if (plane_track) {
+ BLI_assert(marker_index < plane_track->markersnr);
+ return plane_track->markers[marker_index].framenr;
+ }
+
+ return 0;
}
-static bool generic_track_is_marker_enabled(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track,
+static bool generic_track_is_marker_enabled(MovieTrackingTrack *track,
+ MovieTrackingPlaneTrack *plane_track,
int marker_index)
{
- if (track) {
- BLI_assert(marker_index < track->markersnr);
- return (track->markers[marker_index].flag & MARKER_DISABLED) == 0;
- }
- else if (plane_track) {
- return true;
- }
-
- return false;
+ if (track) {
+ BLI_assert(marker_index < track->markersnr);
+ return (track->markers[marker_index].flag & MARKER_DISABLED) == 0;
+ }
+ else if (plane_track) {
+ return true;
+ }
+
+ return false;
}
-static bool generic_track_is_marker_keyframed(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track,
+static bool generic_track_is_marker_keyframed(MovieTrackingTrack *track,
+ MovieTrackingPlaneTrack *plane_track,
int marker_index)
{
- if (track) {
- BLI_assert(marker_index < track->markersnr);
- return (track->markers[marker_index].flag & MARKER_TRACKED) == 0;
- }
- else if (plane_track) {
- BLI_assert(marker_index < plane_track->markersnr);
- return (plane_track->markers[marker_index].flag & PLANE_MARKER_TRACKED) == 0;
- }
-
- return false;
+ if (track) {
+ BLI_assert(marker_index < track->markersnr);
+ return (track->markers[marker_index].flag & MARKER_TRACKED) == 0;
+ }
+ else if (plane_track) {
+ BLI_assert(marker_index < plane_track->markersnr);
+ return (plane_track->markers[marker_index].flag & PLANE_MARKER_TRACKED) == 0;
+ }
+
+ return false;
}
static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Scene *scene)
{
- float x;
- int *points, totseg, i, a;
- float sfra = SFRA, efra = EFRA, framelen = ar->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);
- MovieTrackingPlaneTrack *act_plane_track = BKE_tracking_plane_track_get_active(&clip->tracking);
- MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking);
-
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- /* cache background */
- ED_region_cache_draw_background(ar);
-
- /* cached segments -- could be usefu lto debug caching strategies */
- BKE_movieclip_get_cache_segments(clip, &sc->user, &totseg, &points);
- ED_region_cache_draw_cached_segments(ar, totseg, points, sfra, efra);
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* track */
- if (act_track || act_plane_track) {
- for (i = sfra - clip->start_frame + 1, a = 0; i <= efra - clip->start_frame + 1; i++) {
- int framenr;
- int markersnr = generic_track_get_markersnr(act_track, act_plane_track);
-
- while (a < markersnr) {
- int marker_framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a);
-
- if (marker_framenr >= i)
- break;
-
- if (a < markersnr - 1 && generic_track_get_marker_framenr(act_track, act_plane_track, a + 1) > i)
- break;
-
- a++;
- }
-
- a = min_ii(a, markersnr - 1);
-
- if (generic_track_is_marker_enabled(act_track, act_plane_track, a)) {
- framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a);
-
- if (framenr != i) {
- immUniformColor4ub(128, 128, 0, 96);
- }
- else if (generic_track_is_marker_keyframed(act_track, act_plane_track, a)) {
- immUniformColor4ub(255, 255, 0, 196);
- }
- else {
- immUniformColor4ub(255, 255, 0, 96);
- }
-
- immRecti(pos, (i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 4 * UI_DPI_FAC);
- }
- }
- }
-
- /* failed frames */
- if (reconstruction->flag & TRACKING_RECONSTRUCTED) {
- int n = reconstruction->camnr;
- MovieReconstructedCamera *cameras = reconstruction->cameras;
-
- immUniformColor4ub(255, 0, 0, 96);
-
- for (i = sfra, a = 0; i <= efra; i++) {
- bool ok = false;
-
- while (a < n) {
- if (cameras[a].framenr == i) {
- ok = true;
- break;
- }
- else if (cameras[a].framenr > i) {
- break;
- }
-
- a++;
- }
-
- if (!ok) {
- immRecti(pos, (i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 8 * UI_DPI_FAC);
- }
- }
- }
-
- GPU_blend(false);
-
- /* current frame */
- x = (sc->user.framenr - sfra) / (efra - sfra + 1) * ar->winx;
-
- immUniformThemeColor(TH_CFRAME);
- immRecti(pos, x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC);
-
- immUnbindProgram();
-
- ED_region_cache_draw_curfra_label(sc->user.framenr, x, 8.0f * UI_DPI_FAC);
-
- pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* solver keyframes */
- immUniformColor4ub(175, 255, 0, 255);
- draw_keyframe(act_object->keyframe1 + clip->start_frame - 1, CFRA, sfra, framelen, 2, pos);
- draw_keyframe(act_object->keyframe2 + clip->start_frame - 1, CFRA, sfra, framelen, 2, pos);
-
- immUnbindProgram();
-
- /* 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);
- }
+ float x;
+ int *points, totseg, i, a;
+ float sfra = SFRA, efra = EFRA, framelen = ar->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);
+ MovieTrackingPlaneTrack *act_plane_track = BKE_tracking_plane_track_get_active(&clip->tracking);
+ MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking);
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ /* cache background */
+ ED_region_cache_draw_background(ar);
+
+ /* cached segments -- could be usefu lto debug caching strategies */
+ BKE_movieclip_get_cache_segments(clip, &sc->user, &totseg, &points);
+ ED_region_cache_draw_cached_segments(ar, totseg, points, sfra, efra);
+
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* track */
+ if (act_track || act_plane_track) {
+ for (i = sfra - clip->start_frame + 1, a = 0; i <= efra - clip->start_frame + 1; i++) {
+ int framenr;
+ int markersnr = generic_track_get_markersnr(act_track, act_plane_track);
+
+ while (a < markersnr) {
+ int marker_framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a);
+
+ if (marker_framenr >= i)
+ break;
+
+ if (a < markersnr - 1 &&
+ generic_track_get_marker_framenr(act_track, act_plane_track, a + 1) > i)
+ break;
+
+ a++;
+ }
+
+ a = min_ii(a, markersnr - 1);
+
+ if (generic_track_is_marker_enabled(act_track, act_plane_track, a)) {
+ framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a);
+
+ if (framenr != i) {
+ immUniformColor4ub(128, 128, 0, 96);
+ }
+ else if (generic_track_is_marker_keyframed(act_track, act_plane_track, a)) {
+ immUniformColor4ub(255, 255, 0, 196);
+ }
+ else {
+ immUniformColor4ub(255, 255, 0, 96);
+ }
+
+ immRecti(pos,
+ (i - sfra + clip->start_frame - 1) * framelen,
+ 0,
+ (i - sfra + clip->start_frame) * framelen,
+ 4 * UI_DPI_FAC);
+ }
+ }
+ }
+
+ /* failed frames */
+ if (reconstruction->flag & TRACKING_RECONSTRUCTED) {
+ int n = reconstruction->camnr;
+ MovieReconstructedCamera *cameras = reconstruction->cameras;
+
+ immUniformColor4ub(255, 0, 0, 96);
+
+ for (i = sfra, a = 0; i <= efra; i++) {
+ bool ok = false;
+
+ while (a < n) {
+ if (cameras[a].framenr == i) {
+ ok = true;
+ break;
+ }
+ else if (cameras[a].framenr > i) {
+ break;
+ }
+
+ a++;
+ }
+
+ if (!ok) {
+ immRecti(pos,
+ (i - sfra + clip->start_frame - 1) * framelen,
+ 0,
+ (i - sfra + clip->start_frame) * framelen,
+ 8 * UI_DPI_FAC);
+ }
+ }
+ }
+
+ GPU_blend(false);
+
+ /* current frame */
+ x = (sc->user.framenr - sfra) / (efra - sfra + 1) * ar->winx;
+
+ immUniformThemeColor(TH_CFRAME);
+ immRecti(pos, x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC);
+
+ immUnbindProgram();
+
+ ED_region_cache_draw_curfra_label(sc->user.framenr, x, 8.0f * UI_DPI_FAC);
+
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* solver keyframes */
+ immUniformColor4ub(175, 255, 0, 255);
+ draw_keyframe(act_object->keyframe1 + clip->start_frame - 1, CFRA, sfra, framelen, 2, pos);
+ draw_keyframe(act_object->keyframe2 + clip->start_frame - 1, CFRA, sfra, framelen, 2, pos);
+
+ immUnbindProgram();
+
+ /* 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);
+ }
}
static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar)
{
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- char str[256] = {0};
- bool full_redraw = false;
-
- if (tracking->stats) {
- BLI_strncpy(str, tracking->stats->message, sizeof(str));
- full_redraw = true;
- }
- else {
- if (sc->flag & SC_LOCK_SELECTION)
- strcpy(str, "Locked");
- }
-
- 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);
- }
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ char str[256] = {0};
+ bool full_redraw = false;
+
+ if (tracking->stats) {
+ BLI_strncpy(str, tracking->stats->message, sizeof(str));
+ full_redraw = true;
+ }
+ else {
+ if (sc->flag & SC_LOCK_SELECTION)
+ strcpy(str, "Locked");
+ }
+
+ 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);
+ }
}
static void draw_movieclip_muted(ARegion *ar, int width, int height, float zoomx, float zoomy)
{
- int x, y;
+ int x, y;
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ 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);
+ /* find window pixel coordinates of origin */
+ UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
- immUniformColor3f(0.0f, 0.0f, 0.0f);
- immRectf(pos, x, y, x + zoomx * width, y + zoomy * height);
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+ immRectf(pos, x, y, x + zoomx * width, y + zoomy * height);
- immUnbindProgram();
+ immUnbindProgram();
}
-static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, ImBuf *ibuf,
- int width, int height, float zoomx, float zoomy)
+static void draw_movieclip_buffer(const bContext *C,
+ SpaceClip *sc,
+ ARegion *ar,
+ ImBuf *ibuf,
+ int width,
+ int height,
+ float zoomx,
+ float zoomy)
{
- MovieClip *clip = ED_space_clip_get_clip(sc);
- int filter = GL_LINEAR;
- int x, y;
-
- /* find window pixel coordinates of origin */
- UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
-
- /* checkerboard for case alpha */
- if (ibuf->planes == 32) {
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- imm_draw_box_checker_2d(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y);
- }
-
- /* non-scaled proxy shouldn't use filtering */
- if ((clip->flag & MCLIP_USE_PROXY) == 0 ||
- ELEM(sc->user.render_size, MCLIP_PROXY_RENDER_SIZE_FULL, MCLIP_PROXY_RENDER_SIZE_100))
- {
- filter = GL_NEAREST;
- }
-
- glaDrawImBuf_glsl_ctx(C, ibuf, x, y, filter, zoomx * width / ibuf->x, zoomy * height / ibuf->y);
-
- if (ibuf->planes == 32) {
- GPU_blend(false);
- }
-
- if (sc->flag & SC_SHOW_METADATA) {
- rctf frame;
- BLI_rctf_init(&frame, 0.0f, ibuf->x, 0.0f, ibuf->y);
- ED_region_image_metadata_draw(x, y, ibuf, &frame, zoomx * width / ibuf->x, zoomy * height / ibuf->y);
- }
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ int filter = GL_LINEAR;
+ int x, y;
+
+ /* find window pixel coordinates of origin */
+ UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
+
+ /* checkerboard for case alpha */
+ if (ibuf->planes == 32) {
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ imm_draw_box_checker_2d(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y);
+ }
+
+ /* non-scaled proxy shouldn't use filtering */
+ if ((clip->flag & MCLIP_USE_PROXY) == 0 ||
+ ELEM(sc->user.render_size, MCLIP_PROXY_RENDER_SIZE_FULL, MCLIP_PROXY_RENDER_SIZE_100)) {
+ filter = GL_NEAREST;
+ }
+
+ glaDrawImBuf_glsl_ctx(C, ibuf, x, y, filter, zoomx * width / ibuf->x, zoomy * height / ibuf->y);
+
+ if (ibuf->planes == 32) {
+ GPU_blend(false);
+ }
+
+ if (sc->flag & SC_SHOW_METADATA) {
+ rctf frame;
+ BLI_rctf_init(&frame, 0.0f, ibuf->x, 0.0f, ibuf->y);
+ ED_region_image_metadata_draw(
+ x, y, ibuf, &frame, zoomx * width / ibuf->x, zoomy * height / ibuf->y);
+ }
}
-static void draw_stabilization_border(SpaceClip *sc, ARegion *ar, int width, int height, float zoomx, float zoomy)
+static void draw_stabilization_border(
+ SpaceClip *sc, ARegion *ar, int width, int height, float zoomx, float zoomy)
{
- int x, y;
- MovieClip *clip = ED_space_clip_get_clip(sc);
+ 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);
+ /* find window pixel coordinates of origin */
+ UI_view2d_view_to_region(&ar->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) {
- const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ /* draw boundary border for frame if stabilization is enabled */
+ if (sc->flag & SC_SHOW_STABLE && clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- /* Exclusive OR allows to get orig value when second operand is 0,
- * and negative of orig value when second operand is 1. */
- glEnable(GL_COLOR_LOGIC_OP);
- glLogicOp(GL_XOR);
+ /* Exclusive OR allows to get orig value when second operand is 0,
+ * and negative of orig value when second operand is 1. */
+ glEnable(GL_COLOR_LOGIC_OP);
+ glLogicOp(GL_XOR);
- GPU_matrix_push();
- GPU_matrix_translate_2f(x, y);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(x, y);
- GPU_matrix_scale_2f(zoomx, zoomy);
- GPU_matrix_mul(sc->stabmat);
+ GPU_matrix_scale_2f(zoomx, zoomy);
+ GPU_matrix_mul(sc->stabmat);
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
- immUniform1i("colors_len", 0); /* "simple" mode */
- immUniformColor4f(1.0f, 1.0f, 1.0f, 0.0f);
- immUniform1f("dash_width", 6.0f);
- immUniform1f("dash_factor", 0.5f);
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.0f);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
- imm_draw_box_wire_2d(shdr_pos, 0.0f, 0.0f, width, height);
+ imm_draw_box_wire_2d(shdr_pos, 0.0f, 0.0f, width, height);
- immUnbindProgram();
+ immUnbindProgram();
- GPU_matrix_pop();
+ GPU_matrix_pop();
- glDisable(GL_COLOR_LOGIC_OP);
- }
+ glDisable(GL_COLOR_LOGIC_OP);
+ }
}
static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackingTrack *track)
{
#define MAX_STATIC_PATH 64
- int count = sc->path_length;
- int i, a, b, curindex = -1;
- float path_static[(MAX_STATIC_PATH + 1) * 2][2];
- float (*path)[2];
- int tiny = sc->flag & SC_SHOW_TINY_MARKER, framenr, start_frame;
- MovieTrackingMarker *marker;
+ int count = sc->path_length;
+ int i, a, b, curindex = -1;
+ float path_static[(MAX_STATIC_PATH + 1) * 2][2];
+ float(*path)[2];
+ int tiny = sc->flag & SC_SHOW_TINY_MARKER, framenr, start_frame;
+ MovieTrackingMarker *marker;
- if (count == 0)
- return;
+ if (count == 0)
+ return;
- start_frame = framenr = ED_space_clip_get_clip_frame_number(sc);
+ start_frame = framenr = ED_space_clip_get_clip_frame_number(sc);
- marker = BKE_tracking_marker_get(track, framenr);
- if (marker->framenr != framenr || marker->flag & MARKER_DISABLED)
- return;
+ marker = BKE_tracking_marker_get(track, framenr);
+ if (marker->framenr != framenr || marker->flag & MARKER_DISABLED)
+ return;
- if (count < MAX_STATIC_PATH) {
- path = path_static;
- }
- else {
- path = MEM_mallocN(sizeof(*path) * (count + 1) * 2, "path");
- }
+ if (count < MAX_STATIC_PATH) {
+ path = path_static;
+ }
+ else {
+ path = MEM_mallocN(sizeof(*path) * (count + 1) * 2, "path");
+ }
- a = count;
- i = framenr - 1;
- while (i >= framenr - count) {
- marker = BKE_tracking_marker_get(track, i);
+ a = count;
+ i = framenr - 1;
+ while (i >= framenr - count) {
+ marker = BKE_tracking_marker_get(track, i);
- if (!marker || marker->flag & MARKER_DISABLED)
- break;
+ if (!marker || marker->flag & MARKER_DISABLED)
+ break;
- if (marker->framenr == i) {
- add_v2_v2v2(path[--a], marker->pos, track->offset);
- ED_clip_point_undistorted_pos(sc, path[a], path[a]);
+ if (marker->framenr == i) {
+ add_v2_v2v2(path[--a], marker->pos, track->offset);
+ ED_clip_point_undistorted_pos(sc, path[a], path[a]);
- if (marker->framenr == start_frame)
- curindex = a;
- }
- else {
- break;
- }
+ if (marker->framenr == start_frame)
+ curindex = a;
+ }
+ else {
+ break;
+ }
- i--;
- }
+ i--;
+ }
- b = count;
- i = framenr;
- while (i <= framenr + count) {
- marker = BKE_tracking_marker_get(track, i);
+ b = count;
+ i = framenr;
+ while (i <= framenr + count) {
+ marker = BKE_tracking_marker_get(track, i);
- if (!marker || marker->flag & MARKER_DISABLED)
- break;
+ if (!marker || marker->flag & MARKER_DISABLED)
+ break;
- if (marker->framenr == i) {
- if (marker->framenr == start_frame)
- curindex = b;
+ if (marker->framenr == i) {
+ if (marker->framenr == start_frame)
+ curindex = b;
- add_v2_v2v2(path[b++], marker->pos, track->offset);
- ED_clip_point_undistorted_pos(sc, path[b - 1], path[b - 1]);
- }
- else
- break;
+ add_v2_v2v2(path[b++], marker->pos, track->offset);
+ ED_clip_point_undistorted_pos(sc, path[b - 1], path[b - 1]);
+ }
+ else
+ break;
- i++;
- }
+ i++;
+ }
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- if (!tiny) {
- immUniformThemeColor(TH_MARKER_OUTLINE);
+ if (!tiny) {
+ immUniformThemeColor(TH_MARKER_OUTLINE);
- if (TRACK_VIEW_SELECTED(sc, track)) {
- if ((b - a - 1) >= 1) {
- GPU_point_size(5.0f);
+ if (TRACK_VIEW_SELECTED(sc, track)) {
+ if ((b - a - 1) >= 1) {
+ GPU_point_size(5.0f);
- immBegin(GPU_PRIM_POINTS, b - a - 1);
+ immBegin(GPU_PRIM_POINTS, b - a - 1);
- for (i = a; i < b; i++) {
- if (i != curindex) {
- immVertex2f(pos, path[i][0], path[i][1]);
- }
- }
+ for (i = a; i < b; i++) {
+ if (i != curindex) {
+ immVertex2f(pos, path[i][0], path[i][1]);
+ }
+ }
- immEnd();
- }
- }
+ immEnd();
+ }
+ }
- if ((b - a) >= 2) {
- GPU_line_width(3.0f);
+ if ((b - a) >= 2) {
+ GPU_line_width(3.0f);
- immBegin(GPU_PRIM_LINE_STRIP, b - a);
+ immBegin(GPU_PRIM_LINE_STRIP, b - a);
- for (i = a; i < b; i++) {
- immVertex2f(pos, path[i][0], path[i][1]);
- }
+ for (i = a; i < b; i++) {
+ immVertex2f(pos, path[i][0], path[i][1]);
+ }
- immEnd();
- }
- }
+ immEnd();
+ }
+ }
- if (TRACK_VIEW_SELECTED(sc, track)) {
- GPU_point_size(3.0f);
+ if (TRACK_VIEW_SELECTED(sc, track)) {
+ GPU_point_size(3.0f);
- if ((curindex - a) >= 1) {
- immUniformThemeColor(TH_PATH_BEFORE);
+ if ((curindex - a) >= 1) {
+ immUniformThemeColor(TH_PATH_BEFORE);
- immBegin(GPU_PRIM_POINTS, curindex - a);
+ immBegin(GPU_PRIM_POINTS, curindex - a);
- for (i = a; i < curindex; i++) {
- immVertex2f(pos, path[i][0], path[i][1]);
- }
+ for (i = a; i < curindex; i++) {
+ immVertex2f(pos, path[i][0], path[i][1]);
+ }
- immEnd();
- }
+ immEnd();
+ }
- if ((b - curindex - 1) >= 1) {
- immUniformThemeColor(TH_PATH_AFTER);
+ if ((b - curindex - 1) >= 1) {
+ immUniformThemeColor(TH_PATH_AFTER);
- immBegin(GPU_PRIM_POINTS, b - curindex - 1);
+ immBegin(GPU_PRIM_POINTS, b - curindex - 1);
- for (i = curindex + 1; i < b; i++) {
- immVertex2f(pos, path[i][0], path[i][1]);
- }
+ for (i = curindex + 1; i < b; i++) {
+ immVertex2f(pos, path[i][0], path[i][1]);
+ }
- immEnd();
- }
- }
+ immEnd();
+ }
+ }
- GPU_line_width(1);
+ GPU_line_width(1);
- if ((curindex - a + 1) >= 2) {
- immUniformThemeColor(TH_PATH_BEFORE);
+ if ((curindex - a + 1) >= 2) {
+ immUniformThemeColor(TH_PATH_BEFORE);
- immBegin(GPU_PRIM_LINE_STRIP, curindex - a + 1);
+ immBegin(GPU_PRIM_LINE_STRIP, curindex - a + 1);
- for (i = a; i <= curindex; i++) {
- immVertex2f(pos, path[i][0], path[i][1]);
- }
+ for (i = a; i <= curindex; i++) {
+ immVertex2f(pos, path[i][0], path[i][1]);
+ }
- immEnd();
- }
+ immEnd();
+ }
- if ((b - curindex) >= 2) {
- immUniformThemeColor(TH_PATH_AFTER);
+ if ((b - curindex) >= 2) {
+ immUniformThemeColor(TH_PATH_AFTER);
- immBegin(GPU_PRIM_LINE_STRIP, b - curindex);
+ immBegin(GPU_PRIM_LINE_STRIP, b - curindex);
- for (i = curindex; i < b; i++) {
- immVertex2f(pos, path[i][0], path[i][1]);
- }
+ for (i = curindex; i < b; i++) {
+ immVertex2f(pos, path[i][0], path[i][1]);
+ }
- immEnd();
- }
+ immEnd();
+ }
- immUnbindProgram();
+ immUnbindProgram();
- if (path != path_static) {
- MEM_freeN(path);
- }
+ if (path != path_static) {
+ MEM_freeN(path);
+ }
#undef MAX_STATIC_PATH
}
-static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
- const float marker_pos[2], int width, int height, unsigned int position)
+static void draw_marker_outline(SpaceClip *sc,
+ MovieTrackingTrack *track,
+ MovieTrackingMarker *marker,
+ const float marker_pos[2],
+ int width,
+ int height,
+ unsigned int position)
{
- int tiny = sc->flag & SC_SHOW_TINY_MARKER;
- bool show_search = false;
- float px[2];
+ int tiny = sc->flag & SC_SHOW_TINY_MARKER;
+ bool show_search = false;
+ float px[2];
- px[0] = 1.0f / width / sc->zoom;
- px[1] = 1.0f / height / sc->zoom;
+ px[0] = 1.0f / width / sc->zoom;
+ px[1] = 1.0f / height / sc->zoom;
- GPU_line_width(tiny ? 1.0f : 3.0f);
+ GPU_line_width(tiny ? 1.0f : 3.0f);
- immUniformThemeColor(TH_MARKER_OUTLINE);
+ immUniformThemeColor(TH_MARKER_OUTLINE);
- if ((marker->flag & MARKER_DISABLED) == 0) {
- float pos[2];
- float p[2];
+ if ((marker->flag & MARKER_DISABLED) == 0) {
+ float pos[2];
+ float p[2];
- add_v2_v2v2(pos, marker->pos, track->offset);
+ add_v2_v2v2(pos, marker->pos, track->offset);
- ED_clip_point_undistorted_pos(sc, pos, pos);
+ ED_clip_point_undistorted_pos(sc, pos, pos);
- sub_v2_v2v2(p, pos, marker_pos);
+ sub_v2_v2v2(p, pos, marker_pos);
- if (isect_point_quad_v2(p, marker->pattern_corners[0], marker->pattern_corners[1],
- marker->pattern_corners[2], marker->pattern_corners[3]))
- {
- GPU_point_size(tiny ? 3.0f : 4.0f);
+ if (isect_point_quad_v2(p,
+ marker->pattern_corners[0],
+ marker->pattern_corners[1],
+ marker->pattern_corners[2],
+ marker->pattern_corners[3])) {
+ GPU_point_size(tiny ? 3.0f : 4.0f);
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex2f(position, pos[0], pos[1]);
- immEnd();
- }
- else {
- immBegin(GPU_PRIM_LINES, 8);
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex2f(position, pos[0], pos[1]);
+ immEnd();
+ }
+ else {
+ immBegin(GPU_PRIM_LINES, 8);
- immVertex2f(position, pos[0] + px[0] * 2, pos[1]);
- immVertex2f(position, pos[0] + px[0] * 8, pos[1]);
+ immVertex2f(position, pos[0] + px[0] * 2, pos[1]);
+ immVertex2f(position, pos[0] + px[0] * 8, pos[1]);
- immVertex2f(position, pos[0] - px[0] * 2, pos[1]);
- immVertex2f(position, pos[0] - px[0] * 8, pos[1]);
+ immVertex2f(position, pos[0] - px[0] * 2, pos[1]);
+ immVertex2f(position, pos[0] - px[0] * 8, pos[1]);
- immVertex2f(position, pos[0], pos[1] - px[1] * 2);
- immVertex2f(position, pos[0], pos[1] - px[1] * 8);
+ immVertex2f(position, pos[0], pos[1] - px[1] * 2);
+ immVertex2f(position, pos[0], pos[1] - px[1] * 8);
- immVertex2f(position, pos[0], pos[1] + px[1] * 2);
- immVertex2f(position, pos[0], pos[1] + px[1] * 8);
+ immVertex2f(position, pos[0], pos[1] + px[1] * 2);
+ immVertex2f(position, pos[0], pos[1] + px[1] * 8);
- immEnd();
- }
- }
+ immEnd();
+ }
+ }
- /* pattern and search outline */
- GPU_matrix_push();
- GPU_matrix_translate_2fv(marker_pos);
+ /* pattern and search outline */
+ GPU_matrix_push();
+ GPU_matrix_translate_2fv(marker_pos);
- if (sc->flag & SC_SHOW_MARKER_PATTERN) {
- immBegin(GPU_PRIM_LINE_LOOP, 4);
- immVertex2fv(position, marker->pattern_corners[0]);
- immVertex2fv(position, marker->pattern_corners[1]);
- immVertex2fv(position, marker->pattern_corners[2]);
- immVertex2fv(position, marker->pattern_corners[3]);
- immEnd();
- }
+ if (sc->flag & SC_SHOW_MARKER_PATTERN) {
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
+ immVertex2fv(position, marker->pattern_corners[0]);
+ immVertex2fv(position, marker->pattern_corners[1]);
+ immVertex2fv(position, marker->pattern_corners[2]);
+ immVertex2fv(position, marker->pattern_corners[3]);
+ immEnd();
+ }
- show_search = (TRACK_VIEW_SELECTED(sc, track) &&
- ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0;
+ show_search = (TRACK_VIEW_SELECTED(sc, track) && ((marker->flag & MARKER_DISABLED) == 0 ||
+ (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) !=
+ 0;
- if (sc->flag & SC_SHOW_MARKER_SEARCH && show_search) {
- imm_draw_box_wire_2d(position, marker->search_min[0],
- marker->search_min[1],
- marker->search_max[0],
- marker->search_max[1]);
- }
+ if (sc->flag & SC_SHOW_MARKER_SEARCH && show_search) {
+ imm_draw_box_wire_2d(position,
+ marker->search_min[0],
+ marker->search_min[1],
+ marker->search_max[0],
+ marker->search_max[1]);
+ }
- GPU_matrix_pop();
+ GPU_matrix_pop();
}
static void track_colors(MovieTrackingTrack *track, int act, float col[3], float scol[3])
{
- if (track->flag & TRACK_CUSTOMCOLOR) {
- if (act)
- UI_GetThemeColor3fv(TH_ACT_MARKER, scol);
- else
- copy_v3_v3(scol, track->color);
-
- mul_v3_v3fl(col, track->color, 0.5f);
- }
- else {
- UI_GetThemeColor3fv(TH_MARKER, col);
-
- if (act)
- UI_GetThemeColor3fv(TH_ACT_MARKER, scol);
- else
- UI_GetThemeColor3fv(TH_SEL_MARKER, scol);
- }
+ if (track->flag & TRACK_CUSTOMCOLOR) {
+ if (act)
+ UI_GetThemeColor3fv(TH_ACT_MARKER, scol);
+ else
+ copy_v3_v3(scol, track->color);
+
+ mul_v3_v3fl(col, track->color, 0.5f);
+ }
+ else {
+ UI_GetThemeColor3fv(TH_MARKER, col);
+
+ if (act)
+ UI_GetThemeColor3fv(TH_ACT_MARKER, scol);
+ else
+ UI_GetThemeColor3fv(TH_SEL_MARKER, scol);
+ }
}
-static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
- const float marker_pos[2], int width, int height, int act, int sel, const uint shdr_pos)
+static void draw_marker_areas(SpaceClip *sc,
+ MovieTrackingTrack *track,
+ MovieTrackingMarker *marker,
+ const float marker_pos[2],
+ int width,
+ int height,
+ int act,
+ int sel,
+ const uint shdr_pos)
{
- int tiny = sc->flag & SC_SHOW_TINY_MARKER;
- bool show_search = false;
- float col[3], scol[3];
- float px[2];
+ int tiny = sc->flag & SC_SHOW_TINY_MARKER;
+ bool show_search = false;
+ float col[3], scol[3];
+ float px[2];
- track_colors(track, act, col, scol);
+ track_colors(track, act, col, scol);
- px[0] = 1.0f / width / sc->zoom;
- px[1] = 1.0f / height / sc->zoom;
-
- GPU_line_width(1.0f);
-
- /* Since we are switching solid and dashed lines in rather complex logic here,
- * just always go with dashed shader. */
- immUnbindProgram();
-
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
-
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
-
- immUniform1i("colors_len", 0); /* "simple" mode */
-
- /* marker position and offset position */
- if ((track->flag & SELECT) == sel && (marker->flag & MARKER_DISABLED) == 0) {
- float pos[2], p[2];
-
- if (track->flag & TRACK_LOCKED) {
- if (act) {
- immUniformThemeColor(TH_ACT_MARKER);
- }
- else if (track->flag & SELECT) {
- immUniformThemeColorShade(TH_LOCK_MARKER, 64);
- }
- else {
- immUniformThemeColor(TH_LOCK_MARKER);
- }
- }
- else {
- immUniformColor3fv((track->flag & SELECT) ? scol : col);
- }
-
- add_v2_v2v2(pos, marker->pos, track->offset);
- ED_clip_point_undistorted_pos(sc, pos, pos);
-
- sub_v2_v2v2(p, pos, marker_pos);
-
- if (isect_point_quad_v2(p, marker->pattern_corners[0], marker->pattern_corners[1],
- marker->pattern_corners[2], marker->pattern_corners[3]))
- {
- GPU_point_size(tiny ? 1.0f : 2.0f);
-
- immUniform1f("dash_factor", 2.0f); /* Solid "line" */
-
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex2f(shdr_pos, pos[0], pos[1]);
- immEnd();
- }
- else {
- immUniform1f("dash_factor", 2.0f); /* Solid line */
-
- immBegin(GPU_PRIM_LINES, 8);
-
- immVertex2f(shdr_pos, pos[0] + px[0] * 3, pos[1]);
- immVertex2f(shdr_pos, pos[0] + px[0] * 7, pos[1]);
-
- immVertex2f(shdr_pos, pos[0] - px[0] * 3, pos[1]);
- immVertex2f(shdr_pos, pos[0] - px[0] * 7, pos[1]);
-
- immVertex2f(shdr_pos, pos[0], pos[1] - px[1] * 3);
- immVertex2f(shdr_pos, pos[0], pos[1] - px[1] * 7);
-
- immVertex2f(shdr_pos, pos[0], pos[1] + px[1] * 3);
- immVertex2f(shdr_pos, pos[0], pos[1] + px[1] * 7);
-
- immEnd();
-
- immUniformColor4f(1.0f, 1.0f, 1.0f, 0.0f);
- immUniform1f("dash_width", 6.0f);
- immUniform1f("dash_factor", 0.5f);
-
- glEnable(GL_COLOR_LOGIC_OP);
- glLogicOp(GL_XOR);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2fv(shdr_pos, pos);
- immVertex2fv(shdr_pos, marker_pos);
- immEnd();
-
- glDisable(GL_COLOR_LOGIC_OP);
- }
- }
-
- /* pattern */
- GPU_matrix_push();
- GPU_matrix_translate_2fv(marker_pos);
-
- if (track->flag & TRACK_LOCKED) {
- if (act) {
- immUniformThemeColor(TH_ACT_MARKER);
- }
- else if (track->pat_flag & SELECT) {
- immUniformThemeColorShade(TH_LOCK_MARKER, 64);
- }
- else {
- immUniformThemeColor(TH_LOCK_MARKER);
- }
- }
- else if (marker->flag & MARKER_DISABLED) {
- if (act) {
- immUniformThemeColor(TH_ACT_MARKER);
- }
- else if (track->pat_flag & SELECT) {
- immUniformThemeColorShade(TH_DIS_MARKER, 128);
- }
- else {
- immUniformThemeColor(TH_DIS_MARKER);
- }
- }
- else {
- immUniformColor3fv((track->pat_flag & SELECT) ? scol : col);
- }
-
- if (tiny) {
- immUniform1f("dash_width", 6.0f);
- immUniform1f("dash_factor", 0.5f);
- }
- else {
- immUniform1f("dash_factor", 2.0f); /* Solid line */
- }
-
- if ((track->pat_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_PATTERN)) {
- immBegin(GPU_PRIM_LINE_LOOP, 4);
- immVertex2fv(shdr_pos, marker->pattern_corners[0]);
- immVertex2fv(shdr_pos, marker->pattern_corners[1]);
- immVertex2fv(shdr_pos, marker->pattern_corners[2]);
- immVertex2fv(shdr_pos, marker->pattern_corners[3]);
- immEnd();
- }
-
- /* search */
- show_search = (TRACK_VIEW_SELECTED(sc, track) &&
- ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0;
-
- if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) {
- imm_draw_box_wire_2d(shdr_pos, marker->search_min[0], marker->search_min[1],
- marker->search_max[0], marker->search_max[1]);
- }
-
- GPU_matrix_pop();
-
- /* Restore default shader */
- immUnbindProgram();
-
- const uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- BLI_assert(pos == shdr_pos);
- UNUSED_VARS_NDEBUG(pos);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ px[0] = 1.0f / width / sc->zoom;
+ px[1] = 1.0f / height / sc->zoom;
+
+ GPU_line_width(1.0f);
+
+ /* Since we are switching solid and dashed lines in rather complex logic here,
+ * just always go with dashed shader. */
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("colors_len", 0); /* "simple" mode */
+
+ /* marker position and offset position */
+ if ((track->flag & SELECT) == sel && (marker->flag & MARKER_DISABLED) == 0) {
+ float pos[2], p[2];
+
+ if (track->flag & TRACK_LOCKED) {
+ if (act) {
+ immUniformThemeColor(TH_ACT_MARKER);
+ }
+ else if (track->flag & SELECT) {
+ immUniformThemeColorShade(TH_LOCK_MARKER, 64);
+ }
+ else {
+ immUniformThemeColor(TH_LOCK_MARKER);
+ }
+ }
+ else {
+ immUniformColor3fv((track->flag & SELECT) ? scol : col);
+ }
+
+ add_v2_v2v2(pos, marker->pos, track->offset);
+ ED_clip_point_undistorted_pos(sc, pos, pos);
+
+ sub_v2_v2v2(p, pos, marker_pos);
+
+ if (isect_point_quad_v2(p,
+ marker->pattern_corners[0],
+ marker->pattern_corners[1],
+ marker->pattern_corners[2],
+ marker->pattern_corners[3])) {
+ GPU_point_size(tiny ? 1.0f : 2.0f);
+
+ immUniform1f("dash_factor", 2.0f); /* Solid "line" */
+
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex2f(shdr_pos, pos[0], pos[1]);
+ immEnd();
+ }
+ else {
+ immUniform1f("dash_factor", 2.0f); /* Solid line */
+
+ immBegin(GPU_PRIM_LINES, 8);
+
+ immVertex2f(shdr_pos, pos[0] + px[0] * 3, pos[1]);
+ immVertex2f(shdr_pos, pos[0] + px[0] * 7, pos[1]);
+
+ immVertex2f(shdr_pos, pos[0] - px[0] * 3, pos[1]);
+ immVertex2f(shdr_pos, pos[0] - px[0] * 7, pos[1]);
+
+ immVertex2f(shdr_pos, pos[0], pos[1] - px[1] * 3);
+ immVertex2f(shdr_pos, pos[0], pos[1] - px[1] * 7);
+
+ immVertex2f(shdr_pos, pos[0], pos[1] + px[1] * 3);
+ immVertex2f(shdr_pos, pos[0], pos[1] + px[1] * 7);
+
+ immEnd();
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.0f);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ glEnable(GL_COLOR_LOGIC_OP);
+ glLogicOp(GL_XOR);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2fv(shdr_pos, pos);
+ immVertex2fv(shdr_pos, marker_pos);
+ immEnd();
+
+ glDisable(GL_COLOR_LOGIC_OP);
+ }
+ }
+
+ /* pattern */
+ GPU_matrix_push();
+ GPU_matrix_translate_2fv(marker_pos);
+
+ if (track->flag & TRACK_LOCKED) {
+ if (act) {
+ immUniformThemeColor(TH_ACT_MARKER);
+ }
+ else if (track->pat_flag & SELECT) {
+ immUniformThemeColorShade(TH_LOCK_MARKER, 64);
+ }
+ else {
+ immUniformThemeColor(TH_LOCK_MARKER);
+ }
+ }
+ else if (marker->flag & MARKER_DISABLED) {
+ if (act) {
+ immUniformThemeColor(TH_ACT_MARKER);
+ }
+ else if (track->pat_flag & SELECT) {
+ immUniformThemeColorShade(TH_DIS_MARKER, 128);
+ }
+ else {
+ immUniformThemeColor(TH_DIS_MARKER);
+ }
+ }
+ else {
+ immUniformColor3fv((track->pat_flag & SELECT) ? scol : col);
+ }
+
+ if (tiny) {
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+ }
+ else {
+ immUniform1f("dash_factor", 2.0f); /* Solid line */
+ }
+
+ if ((track->pat_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_PATTERN)) {
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
+ immVertex2fv(shdr_pos, marker->pattern_corners[0]);
+ immVertex2fv(shdr_pos, marker->pattern_corners[1]);
+ immVertex2fv(shdr_pos, marker->pattern_corners[2]);
+ immVertex2fv(shdr_pos, marker->pattern_corners[3]);
+ immEnd();
+ }
+
+ /* search */
+ show_search = (TRACK_VIEW_SELECTED(sc, track) && ((marker->flag & MARKER_DISABLED) == 0 ||
+ (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) !=
+ 0;
+
+ if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) {
+ imm_draw_box_wire_2d(shdr_pos,
+ marker->search_min[0],
+ marker->search_min[1],
+ marker->search_max[0],
+ marker->search_max[1]);
+ }
+
+ GPU_matrix_pop();
+
+ /* Restore default shader */
+ immUnbindProgram();
+
+ const uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ BLI_assert(pos == shdr_pos);
+ UNUSED_VARS_NDEBUG(pos);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
}
static float get_shortest_pattern_side(MovieTrackingMarker *marker)
{
- int i, next;
- float len_sq = FLT_MAX;
+ int i, next;
+ float len_sq = FLT_MAX;
- for (i = 0; i < 4; i++) {
- float cur_len;
+ for (i = 0; i < 4; i++) {
+ float cur_len;
- next = (i + 1) % 4;
+ next = (i + 1) % 4;
- cur_len = len_squared_v2v2(marker->pattern_corners[i], marker->pattern_corners[next]);
+ cur_len = len_squared_v2v2(marker->pattern_corners[i], marker->pattern_corners[next]);
- len_sq = min_ff(cur_len, len_sq);
- }
+ len_sq = min_ff(cur_len, len_sq);
+ }
- return sqrtf(len_sq);
+ return sqrtf(len_sq);
}
-static void draw_marker_slide_square(float x, float y, float dx, float dy, int outline, float px[2], unsigned int pos)
+static void draw_marker_slide_square(
+ float x, float y, float dx, float dy, int outline, float px[2], unsigned int pos)
{
- float tdx, tdy;
+ float tdx, tdy;
- tdx = dx;
- tdy = dy;
+ tdx = dx;
+ tdy = dy;
- if (outline) {
- tdx += px[0];
- tdy += px[1];
- }
+ if (outline) {
+ tdx += px[0];
+ tdy += px[1];
+ }
- immRectf(pos, x - tdx, y - tdy, x + tdx, y + tdy);
+ immRectf(pos, x - tdx, y - tdy, x + tdx, y + tdy);
}
-static void draw_marker_slide_triangle(float x, float y, float dx, float dy, int outline, float px[2], unsigned int pos)
+static void draw_marker_slide_triangle(
+ float x, float y, float dx, float dy, int outline, float px[2], unsigned int pos)
{
- float tdx, tdy;
+ float tdx, tdy;
- tdx = dx * 2.0f;
- tdy = dy * 2.0f;
+ tdx = dx * 2.0f;
+ tdy = dy * 2.0f;
- if (outline) {
- tdx += px[0];
- tdy += px[1];
- }
+ if (outline) {
+ tdx += px[0];
+ tdy += px[1];
+ }
- immBegin(GPU_PRIM_TRIS, 3);
- immVertex2f(pos, x, y);
- immVertex2f(pos, x - tdx, y);
- immVertex2f(pos, x, y + tdy);
- immEnd();
+ immBegin(GPU_PRIM_TRIS, 3);
+ immVertex2f(pos, x, y);
+ immVertex2f(pos, x - tdx, y);
+ immVertex2f(pos, x, y + tdy);
+ immEnd();
}
-static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
- const float marker_pos[2], int outline, int sel, int act,
- int width, int height, unsigned int pos)
+static void draw_marker_slide_zones(SpaceClip *sc,
+ MovieTrackingTrack *track,
+ MovieTrackingMarker *marker,
+ const float marker_pos[2],
+ int outline,
+ int sel,
+ int act,
+ int width,
+ int height,
+ unsigned int pos)
{
- float dx, dy, patdx, patdy, searchdx, searchdy;
- int tiny = sc->flag & SC_SHOW_TINY_MARKER;
- float col[3], scol[3], px[2], side;
+ float dx, dy, patdx, patdy, searchdx, searchdy;
+ int tiny = sc->flag & SC_SHOW_TINY_MARKER;
+ float col[3], scol[3], px[2], side;
- if ((tiny && outline) || (marker->flag & MARKER_DISABLED))
- return;
+ if ((tiny && outline) || (marker->flag & MARKER_DISABLED))
+ return;
- if (!TRACK_VIEW_SELECTED(sc, track) || track->flag & TRACK_LOCKED)
- return;
+ if (!TRACK_VIEW_SELECTED(sc, track) || track->flag & TRACK_LOCKED)
+ return;
- track_colors(track, act, col, scol);
+ track_colors(track, act, col, scol);
- if (outline) {
- immUniformThemeColor(TH_MARKER_OUTLINE);
- }
+ if (outline) {
+ immUniformThemeColor(TH_MARKER_OUTLINE);
+ }
- GPU_matrix_push();
- GPU_matrix_translate_2fv(marker_pos);
+ GPU_matrix_push();
+ GPU_matrix_translate_2fv(marker_pos);
- dx = 6.0f / width / sc->zoom;
- dy = 6.0f / height / sc->zoom;
+ dx = 6.0f / width / sc->zoom;
+ dy = 6.0f / height / sc->zoom;
- side = get_shortest_pattern_side(marker);
- patdx = min_ff(dx * 2.0f / 3.0f, side / 6.0f) * UI_DPI_FAC;
- patdy = min_ff(dy * 2.0f / 3.0f, side * width / height / 6.0f) * UI_DPI_FAC;
+ side = get_shortest_pattern_side(marker);
+ patdx = min_ff(dx * 2.0f / 3.0f, side / 6.0f) * UI_DPI_FAC;
+ patdy = min_ff(dy * 2.0f / 3.0f, side * width / height / 6.0f) * UI_DPI_FAC;
- searchdx = min_ff(dx, (marker->search_max[0] - marker->search_min[0]) / 6.0f) * UI_DPI_FAC;
- searchdy = min_ff(dy, (marker->search_max[1] - marker->search_min[1]) / 6.0f) * UI_DPI_FAC;
+ searchdx = min_ff(dx, (marker->search_max[0] - marker->search_min[0]) / 6.0f) * UI_DPI_FAC;
+ searchdy = min_ff(dy, (marker->search_max[1] - marker->search_min[1]) / 6.0f) * UI_DPI_FAC;
- px[0] = 1.0f / sc->zoom / width / sc->scale;
- px[1] = 1.0f / sc->zoom / height / sc->scale;
+ px[0] = 1.0f / sc->zoom / width / sc->scale;
+ px[1] = 1.0f / sc->zoom / height / sc->scale;
- if ((sc->flag & SC_SHOW_MARKER_SEARCH) && ((track->search_flag & SELECT) == sel || outline)) {
- if (!outline) {
- immUniformColor3fv((track->search_flag & SELECT) ? scol : col);
- }
+ if ((sc->flag & SC_SHOW_MARKER_SEARCH) && ((track->search_flag & SELECT) == sel || outline)) {
+ if (!outline) {
+ immUniformColor3fv((track->search_flag & SELECT) ? scol : col);
+ }
- /* search offset square */
- draw_marker_slide_square(marker->search_min[0], marker->search_max[1], searchdx, searchdy, outline, px, pos);
+ /* search offset square */
+ draw_marker_slide_square(
+ marker->search_min[0], marker->search_max[1], searchdx, searchdy, outline, px, pos);
- /* search re-sizing triangle */
- draw_marker_slide_triangle(marker->search_max[0], marker->search_min[1], searchdx, searchdy, outline, px, pos);
- }
+ /* search re-sizing triangle */
+ draw_marker_slide_triangle(
+ marker->search_max[0], marker->search_min[1], searchdx, searchdy, outline, px, pos);
+ }
- if ((sc->flag & SC_SHOW_MARKER_PATTERN) && ((track->pat_flag & SELECT) == sel || outline)) {
- int i;
- float pat_min[2], pat_max[2];
-/* float dx = 12.0f / width, dy = 12.0f / height;*/ /* XXX UNUSED */
- float tilt_ctrl[2];
+ if ((sc->flag & SC_SHOW_MARKER_PATTERN) && ((track->pat_flag & SELECT) == sel || outline)) {
+ int i;
+ float pat_min[2], pat_max[2];
+ /* float dx = 12.0f / width, dy = 12.0f / height;*/ /* XXX UNUSED */
+ float tilt_ctrl[2];
- if (!outline) {
- immUniformColor3fv((track->pat_flag & SELECT) ? scol : col);
- }
+ if (!outline) {
+ immUniformColor3fv((track->pat_flag & SELECT) ? scol : col);
+ }
- /* pattern's corners sliding squares */
- for (i = 0; i < 4; i++) {
- draw_marker_slide_square(marker->pattern_corners[i][0], marker->pattern_corners[i][1],
- patdx / 1.5f, patdy / 1.5f, outline, px, pos);
- }
+ /* pattern's corners sliding squares */
+ for (i = 0; i < 4; i++) {
+ draw_marker_slide_square(marker->pattern_corners[i][0],
+ marker->pattern_corners[i][1],
+ patdx / 1.5f,
+ patdy / 1.5f,
+ outline,
+ px,
+ pos);
+ }
- /* ** sliders to control overall pattern ** */
- add_v2_v2v2(tilt_ctrl, marker->pattern_corners[1], marker->pattern_corners[2]);
+ /* ** sliders to control overall pattern ** */
+ add_v2_v2v2(tilt_ctrl, marker->pattern_corners[1], marker->pattern_corners[2]);
- BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
+ BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
- GPU_line_width(outline ? 3.0f : 1.0f);
+ GPU_line_width(outline ? 3.0f : 1.0f);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, 0.0f, 0.0f);
- immVertex2fv(pos, tilt_ctrl);
- immEnd();
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, 0.0f, 0.0f);
+ immVertex2fv(pos, tilt_ctrl);
+ immEnd();
- /* slider to control pattern tilt */
- draw_marker_slide_square(tilt_ctrl[0], tilt_ctrl[1], patdx, patdy, outline, px, pos);
- }
+ /* slider to control pattern tilt */
+ draw_marker_slide_square(tilt_ctrl[0], tilt_ctrl[1], patdx, patdy, outline, px, pos);
+ }
- GPU_matrix_pop();
+ GPU_matrix_pop();
}
-static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
- const float marker_pos[2], int act, int width, int height, float zoomx, float zoomy)
+static void draw_marker_texts(SpaceClip *sc,
+ MovieTrackingTrack *track,
+ MovieTrackingMarker *marker,
+ const float marker_pos[2],
+ int act,
+ int width,
+ int height,
+ float zoomx,
+ float zoomy)
{
- char str[128] = {0}, state[64] = {0};
- float dx = 0.0f, dy = 0.0f, fontsize, pos[3];
- uiStyle *style = U.uistyles.first;
- int fontid = style->widget.uifont_id;
-
- if (!TRACK_VIEW_SELECTED(sc, track))
- return;
-
- BLF_size(fontid, 11.0f * U.pixelsize, U.dpi);
- fontsize = BLF_height_max(fontid);
-
- if (marker->flag & MARKER_DISABLED) {
- if (act) {
- UI_FontThemeColor(fontid, TH_ACT_MARKER);
- }
- else {
- unsigned char color[4];
- UI_GetThemeColorShade4ubv(TH_DIS_MARKER, 128, color);
- BLF_color4ubv(fontid, color);
- }
- }
- else {
- UI_FontThemeColor(fontid, act ? TH_ACT_MARKER : TH_SEL_MARKER);
- }
-
- if ((sc->flag & SC_SHOW_MARKER_SEARCH) &&
- ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0))
- {
- dx = marker->search_min[0];
- dy = marker->search_min[1];
- }
- else if (sc->flag & SC_SHOW_MARKER_PATTERN) {
- float pat_min[2], pat_max[2];
-
- BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
- dx = pat_min[0];
- dy = pat_min[1];
- }
-
- pos[0] = (marker_pos[0] + dx) * width;
- pos[1] = (marker_pos[1] + dy) * height;
- pos[2] = 0.0f;
-
- mul_m4_v3(sc->stabmat, pos);
-
- pos[0] = pos[0] * zoomx;
- pos[1] = pos[1] * zoomy - fontsize;
-
- if (marker->flag & MARKER_DISABLED)
- strcpy(state, "disabled");
- else if (marker->framenr != ED_space_clip_get_clip_frame_number(sc))
- strcpy(state, "estimated");
- else if (marker->flag & MARKER_TRACKED)
- strcpy(state, "tracked");
- else
- strcpy(state, "keyframed");
-
- if (state[0])
- BLI_snprintf(str, sizeof(str), "%s: %s", track->name, state);
- else
- BLI_strncpy(str, track->name, sizeof(str));
-
- BLF_position(fontid, pos[0], pos[1], 0.0f);
- BLF_draw(fontid, str, sizeof(str));
- pos[1] -= fontsize;
-
- if (track->flag & TRACK_HAS_BUNDLE) {
- BLI_snprintf(str, sizeof(str), "Average error: %.3f", track->error);
- BLF_position(fontid, pos[0], pos[1], 0.0f);
- BLF_draw(fontid, str, sizeof(str));
- pos[1] -= fontsize;
- }
-
- if (track->flag & TRACK_LOCKED) {
- BLF_position(fontid, pos[0], pos[1], 0.0f);
- BLF_draw(fontid, "locked", 6);
- }
+ char str[128] = {0}, state[64] = {0};
+ float dx = 0.0f, dy = 0.0f, fontsize, pos[3];
+ uiStyle *style = U.uistyles.first;
+ int fontid = style->widget.uifont_id;
+
+ if (!TRACK_VIEW_SELECTED(sc, track))
+ return;
+
+ BLF_size(fontid, 11.0f * U.pixelsize, U.dpi);
+ fontsize = BLF_height_max(fontid);
+
+ if (marker->flag & MARKER_DISABLED) {
+ if (act) {
+ UI_FontThemeColor(fontid, TH_ACT_MARKER);
+ }
+ else {
+ unsigned char color[4];
+ UI_GetThemeColorShade4ubv(TH_DIS_MARKER, 128, color);
+ BLF_color4ubv(fontid, color);
+ }
+ }
+ else {
+ UI_FontThemeColor(fontid, act ? TH_ACT_MARKER : TH_SEL_MARKER);
+ }
+
+ if ((sc->flag & SC_SHOW_MARKER_SEARCH) &&
+ ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) {
+ dx = marker->search_min[0];
+ dy = marker->search_min[1];
+ }
+ else if (sc->flag & SC_SHOW_MARKER_PATTERN) {
+ float pat_min[2], pat_max[2];
+
+ BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
+ dx = pat_min[0];
+ dy = pat_min[1];
+ }
+
+ pos[0] = (marker_pos[0] + dx) * width;
+ pos[1] = (marker_pos[1] + dy) * height;
+ pos[2] = 0.0f;
+
+ mul_m4_v3(sc->stabmat, pos);
+
+ pos[0] = pos[0] * zoomx;
+ pos[1] = pos[1] * zoomy - fontsize;
+
+ if (marker->flag & MARKER_DISABLED)
+ strcpy(state, "disabled");
+ else if (marker->framenr != ED_space_clip_get_clip_frame_number(sc))
+ strcpy(state, "estimated");
+ else if (marker->flag & MARKER_TRACKED)
+ strcpy(state, "tracked");
+ else
+ strcpy(state, "keyframed");
+
+ if (state[0])
+ BLI_snprintf(str, sizeof(str), "%s: %s", track->name, state);
+ else
+ BLI_strncpy(str, track->name, sizeof(str));
+
+ BLF_position(fontid, pos[0], pos[1], 0.0f);
+ BLF_draw(fontid, str, sizeof(str));
+ pos[1] -= fontsize;
+
+ if (track->flag & TRACK_HAS_BUNDLE) {
+ BLI_snprintf(str, sizeof(str), "Average error: %.3f", track->error);
+ BLF_position(fontid, pos[0], pos[1], 0.0f);
+ BLF_draw(fontid, str, sizeof(str));
+ pos[1] -= fontsize;
+ }
+
+ if (track->flag & TRACK_LOCKED) {
+ BLF_position(fontid, pos[0], pos[1], 0.0f);
+ BLF_draw(fontid, "locked", 6);
+ }
}
static void plane_track_colors(bool is_active, float color[3], float selected_color[3])
{
- UI_GetThemeColor3fv(TH_MARKER, color);
+ UI_GetThemeColor3fv(TH_MARKER, color);
- UI_GetThemeColor3fv(is_active ? TH_ACT_MARKER : TH_SEL_MARKER, selected_color);
+ UI_GetThemeColor3fv(is_active ? TH_ACT_MARKER : TH_SEL_MARKER, selected_color);
}
-static void getArrowEndPoint(const int width, const int height, const float zoom,
- const float start_corner[2], const float end_corner[2],
+static void getArrowEndPoint(const int width,
+ const int height,
+ const float zoom,
+ const float start_corner[2],
+ const float end_corner[2],
float end_point[2])
{
- float direction[2];
- float max_length;
+ float direction[2];
+ float max_length;
- sub_v2_v2v2(direction, end_corner, start_corner);
+ sub_v2_v2v2(direction, end_corner, start_corner);
- direction[0] *= width;
- direction[1] *= height;
- max_length = normalize_v2(direction);
- mul_v2_fl(direction, min_ff(32.0f / zoom, max_length));
- direction[0] /= width;
- direction[1] /= height;
+ direction[0] *= width;
+ direction[1] *= height;
+ max_length = normalize_v2(direction);
+ mul_v2_fl(direction, min_ff(32.0f / zoom, max_length));
+ direction[0] /= width;
+ direction[1] /= height;
- add_v2_v2v2(end_point, start_corner, direction);
+ add_v2_v2v2(end_point, start_corner, direction);
}
-static void homogeneous_2d_to_gl_matrix(/*const*/ float matrix[3][3],
- float gl_matrix[4][4])
+static void homogeneous_2d_to_gl_matrix(/*const*/ float matrix[3][3], float gl_matrix[4][4])
{
- gl_matrix[0][0] = matrix[0][0];
- gl_matrix[0][1] = matrix[0][1];
- gl_matrix[0][2] = 0.0f;
- gl_matrix[0][3] = matrix[0][2];
-
- gl_matrix[1][0] = matrix[1][0];
- gl_matrix[1][1] = matrix[1][1];
- gl_matrix[1][2] = 0.0f;
- gl_matrix[1][3] = matrix[1][2];
-
- gl_matrix[2][0] = 0.0f;
- gl_matrix[2][1] = 0.0f;
- gl_matrix[2][2] = 1.0f;
- gl_matrix[2][3] = 0.0f;
-
- gl_matrix[3][0] = matrix[2][0];
- gl_matrix[3][1] = matrix[2][1];
- gl_matrix[3][2] = 0.0f;
- gl_matrix[3][3] = matrix[2][2];
+ gl_matrix[0][0] = matrix[0][0];
+ gl_matrix[0][1] = matrix[0][1];
+ gl_matrix[0][2] = 0.0f;
+ gl_matrix[0][3] = matrix[0][2];
+
+ gl_matrix[1][0] = matrix[1][0];
+ gl_matrix[1][1] = matrix[1][1];
+ gl_matrix[1][2] = 0.0f;
+ gl_matrix[1][3] = matrix[1][2];
+
+ gl_matrix[2][0] = 0.0f;
+ gl_matrix[2][1] = 0.0f;
+ gl_matrix[2][2] = 1.0f;
+ gl_matrix[2][3] = 0.0f;
+
+ gl_matrix[3][0] = matrix[2][0];
+ gl_matrix[3][1] = matrix[2][1];
+ gl_matrix[3][2] = 0.0f;
+ gl_matrix[3][3] = matrix[2][2];
}
static void draw_plane_marker_image(Scene *scene,
MovieTrackingPlaneTrack *plane_track,
MovieTrackingPlaneMarker *plane_marker)
{
- Image *image = plane_track->image;
- ImBuf *ibuf;
- void *lock;
+ Image *image = plane_track->image;
+ ImBuf *ibuf;
+ void *lock;
- if (image == NULL) {
- return;
- }
+ if (image == NULL) {
+ return;
+ }
- ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
+ ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
- if (ibuf) {
- unsigned char *display_buffer;
- void *cache_handle;
+ if (ibuf) {
+ unsigned char *display_buffer;
+ void *cache_handle;
- if (image->flag & IMA_VIEW_AS_RENDER) {
- display_buffer = IMB_display_buffer_acquire(ibuf,
- &scene->view_settings,
- &scene->display_settings,
- &cache_handle);
- }
- else {
- display_buffer = IMB_display_buffer_acquire(ibuf, NULL,
- &scene->display_settings,
- &cache_handle);
- }
+ if (image->flag & IMA_VIEW_AS_RENDER) {
+ display_buffer = IMB_display_buffer_acquire(
+ ibuf, &scene->view_settings, &scene->display_settings, &cache_handle);
+ }
+ else {
+ display_buffer = IMB_display_buffer_acquire(
+ ibuf, NULL, &scene->display_settings, &cache_handle);
+ }
- if (display_buffer) {
- GLuint texid;
- float frame_corners[4][2] = {{0.0f, 0.0f},
- {1.0f, 0.0f},
- {1.0f, 1.0f},
- {0.0f, 1.0f}};
- float perspective_matrix[3][3];
- float gl_matrix[4][4];
- bool transparent = false;
- BKE_tracking_homography_between_two_quads(frame_corners,
- plane_marker->corners,
- perspective_matrix);
+ if (display_buffer) {
+ GLuint texid;
+ float frame_corners[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}};
+ float perspective_matrix[3][3];
+ float gl_matrix[4][4];
+ bool transparent = false;
+ BKE_tracking_homography_between_two_quads(
+ frame_corners, plane_marker->corners, perspective_matrix);
- homogeneous_2d_to_gl_matrix(perspective_matrix, gl_matrix);
+ homogeneous_2d_to_gl_matrix(perspective_matrix, gl_matrix);
- if (plane_track->image_opacity != 1.0f || ibuf->planes == 32) {
- transparent = true;
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- }
+ if (plane_track->image_opacity != 1.0f || ibuf->planes == 32) {
+ transparent = true;
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ }
- glGenTextures(1, (GLuint *)&texid);
+ glGenTextures(1, (GLuint *)&texid);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, texid);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, texid);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA,
- GL_UNSIGNED_BYTE, display_buffer);
+ glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ GL_RGBA8,
+ ibuf->x,
+ ibuf->y,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ display_buffer);
- GPU_matrix_push();
- GPU_matrix_mul(gl_matrix);
+ GPU_matrix_push();
+ GPU_matrix_mul(gl_matrix);
- GPUVertFormat *imm_format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(imm_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint texCoord = GPU_vertformat_attr_add(imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPUVertFormat *imm_format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(imm_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint texCoord = GPU_vertformat_attr_add(
+ imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
- immUniformColor4f(1.0f, 1.0f, 1.0f, plane_track->image_opacity);
- immUniform1i("image", 0);
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
+ immUniformColor4f(1.0f, 1.0f, 1.0f, plane_track->image_opacity);
+ immUniform1i("image", 0);
- immBegin(GPU_PRIM_TRI_FAN, 4);
+ immBegin(GPU_PRIM_TRI_FAN, 4);
- immAttr2f(texCoord, 0.0f, 0.0f);
- immVertex2f(pos, 0.0f, 0.0f);
+ immAttr2f(texCoord, 0.0f, 0.0f);
+ immVertex2f(pos, 0.0f, 0.0f);
- immAttr2f(texCoord, 1.0f, 0.0f);
- immVertex2f(pos, 1.0f, 0.0f);
+ immAttr2f(texCoord, 1.0f, 0.0f);
+ immVertex2f(pos, 1.0f, 0.0f);
- immAttr2f(texCoord, 1.0f, 1.0f);
- immVertex2f(pos, 1.0f, 1.0f);
+ immAttr2f(texCoord, 1.0f, 1.0f);
+ immVertex2f(pos, 1.0f, 1.0f);
- immAttr2f(texCoord, 0.0f, 1.0f);
- immVertex2f(pos, 0.0f, 1.0f);
+ immAttr2f(texCoord, 0.0f, 1.0f);
+ immVertex2f(pos, 0.0f, 1.0f);
- immEnd();
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
- GPU_matrix_pop();
+ GPU_matrix_pop();
- glBindTexture(GL_TEXTURE_2D, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
- if (transparent) {
- GPU_blend(false);
- }
- }
+ if (transparent) {
+ GPU_blend(false);
+ }
+ }
- IMB_display_buffer_release(cache_handle);
- }
+ IMB_display_buffer_release(cache_handle);
+ }
- BKE_image_release_ibuf(image, ibuf, lock);
+ BKE_image_release_ibuf(image, ibuf, lock);
}
-static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlaneTrack *plane_track,
- MovieTrackingPlaneMarker *plane_marker, bool is_active_track,
- bool draw_outline, int width, int height)
+static void draw_plane_marker_ex(SpaceClip *sc,
+ Scene *scene,
+ MovieTrackingPlaneTrack *plane_track,
+ MovieTrackingPlaneMarker *plane_marker,
+ bool is_active_track,
+ bool draw_outline,
+ int width,
+ int height)
{
- bool tiny = (sc->flag & SC_SHOW_TINY_MARKER) != 0;
- bool is_selected_track = (plane_track->flag & SELECT) != 0;
- const bool has_image = plane_track->image != NULL &&
- BKE_image_has_ibuf(plane_track->image, NULL);
- const bool draw_plane_quad = !has_image || plane_track->image_opacity == 0.0f;
- float px[2];
- float color[3], selected_color[3];
-
- px[0] = 1.0f / width / sc->zoom;
- px[1] = 1.0f / height / sc->zoom;
-
- /* Draw image */
- if (draw_outline == false) {
- draw_plane_marker_image(scene, plane_track, plane_marker);
- }
-
- if (draw_plane_quad || is_selected_track) {
- const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
-
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
-
- immUniform1i("colors_len", 0); /* "simple" mode */
-
- if (draw_plane_quad) {
- const bool stipple = !draw_outline && tiny;
- const bool thick = draw_outline && !tiny;
-
- GPU_line_width(thick ? 3.0f : 1.0f);
-
- if (stipple) {
- immUniform1f("dash_width", 6.0f);
- immUniform1f("dash_factor", 0.5f);
- }
- else {
- immUniform1f("dash_factor", 2.0f); /* Solid line */
- }
-
- if (draw_outline) {
- immUniformThemeColor(TH_MARKER_OUTLINE);
- }
- else {
- plane_track_colors(is_active_track, color, selected_color);
- immUniformColor3fv(is_selected_track ? selected_color : color);
- }
-
- /* Draw rectangle itself. */
- immBegin(GPU_PRIM_LINE_LOOP, 4);
- immVertex2fv(shdr_pos, plane_marker->corners[0]);
- immVertex2fv(shdr_pos, plane_marker->corners[1]);
- immVertex2fv(shdr_pos, plane_marker->corners[2]);
- immVertex2fv(shdr_pos, plane_marker->corners[3]);
- immEnd();
-
- /* Draw axis. */
- if (!draw_outline) {
- float end_point[2];
-
- immUniformColor3f(1.0f, 0.0f, 0.0f);
-
- immBegin(GPU_PRIM_LINES, 2);
-
- getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[1], end_point);
- immVertex2fv(shdr_pos, plane_marker->corners[0]);
- immVertex2fv(shdr_pos, end_point);
-
- immEnd();
-
- immUniformColor3f(0.0f, 1.0f, 0.0f);
-
- immBegin(GPU_PRIM_LINES, 2);
-
- getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[3], end_point);
- immVertex2fv(shdr_pos, plane_marker->corners[0]);
- immVertex2fv(shdr_pos, end_point);
-
- immEnd();
- }
- }
-
- /* Draw sliders. */
- if (is_selected_track) {
- immUniform1f("dash_factor", 2.0f); /* Solid line */
-
- if (draw_outline) {
- immUniformThemeColor(TH_MARKER_OUTLINE);
- }
- else {
- immUniformColor3fv(selected_color);
- }
-
- int i;
- for (i = 0; i < 4; i++) {
- draw_marker_slide_square(plane_marker->corners[i][0], plane_marker->corners[i][1],
- 3.0f * px[0], 3.0f * px[1], draw_outline, px, shdr_pos);
- }
- }
-
- immUnbindProgram();
- }
+ bool tiny = (sc->flag & SC_SHOW_TINY_MARKER) != 0;
+ bool is_selected_track = (plane_track->flag & SELECT) != 0;
+ const bool has_image = plane_track->image != NULL &&
+ BKE_image_has_ibuf(plane_track->image, NULL);
+ const bool draw_plane_quad = !has_image || plane_track->image_opacity == 0.0f;
+ float px[2];
+ float color[3], selected_color[3];
+
+ px[0] = 1.0f / width / sc->zoom;
+ px[1] = 1.0f / height / sc->zoom;
+
+ /* Draw image */
+ if (draw_outline == false) {
+ draw_plane_marker_image(scene, plane_track, plane_marker);
+ }
+
+ if (draw_plane_quad || is_selected_track) {
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("colors_len", 0); /* "simple" mode */
+
+ if (draw_plane_quad) {
+ const bool stipple = !draw_outline && tiny;
+ const bool thick = draw_outline && !tiny;
+
+ GPU_line_width(thick ? 3.0f : 1.0f);
+
+ if (stipple) {
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+ }
+ else {
+ immUniform1f("dash_factor", 2.0f); /* Solid line */
+ }
+
+ if (draw_outline) {
+ immUniformThemeColor(TH_MARKER_OUTLINE);
+ }
+ else {
+ plane_track_colors(is_active_track, color, selected_color);
+ immUniformColor3fv(is_selected_track ? selected_color : color);
+ }
+
+ /* Draw rectangle itself. */
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
+ immVertex2fv(shdr_pos, plane_marker->corners[0]);
+ immVertex2fv(shdr_pos, plane_marker->corners[1]);
+ immVertex2fv(shdr_pos, plane_marker->corners[2]);
+ immVertex2fv(shdr_pos, plane_marker->corners[3]);
+ immEnd();
+
+ /* Draw axis. */
+ if (!draw_outline) {
+ float end_point[2];
+
+ immUniformColor3f(1.0f, 0.0f, 0.0f);
+
+ immBegin(GPU_PRIM_LINES, 2);
+
+ getArrowEndPoint(width,
+ height,
+ sc->zoom,
+ plane_marker->corners[0],
+ plane_marker->corners[1],
+ end_point);
+ immVertex2fv(shdr_pos, plane_marker->corners[0]);
+ immVertex2fv(shdr_pos, end_point);
+
+ immEnd();
+
+ immUniformColor3f(0.0f, 1.0f, 0.0f);
+
+ immBegin(GPU_PRIM_LINES, 2);
+
+ getArrowEndPoint(width,
+ height,
+ sc->zoom,
+ plane_marker->corners[0],
+ plane_marker->corners[3],
+ end_point);
+ immVertex2fv(shdr_pos, plane_marker->corners[0]);
+ immVertex2fv(shdr_pos, end_point);
+
+ immEnd();
+ }
+ }
+
+ /* Draw sliders. */
+ if (is_selected_track) {
+ immUniform1f("dash_factor", 2.0f); /* Solid line */
+
+ if (draw_outline) {
+ immUniformThemeColor(TH_MARKER_OUTLINE);
+ }
+ else {
+ immUniformColor3fv(selected_color);
+ }
+
+ int i;
+ for (i = 0; i < 4; i++) {
+ draw_marker_slide_square(plane_marker->corners[i][0],
+ plane_marker->corners[i][1],
+ 3.0f * px[0],
+ 3.0f * px[1],
+ draw_outline,
+ px,
+ shdr_pos);
+ }
+ }
+
+ immUnbindProgram();
+ }
}
-static void draw_plane_marker_outline(SpaceClip *sc, Scene *scene, MovieTrackingPlaneTrack *plane_track,
- MovieTrackingPlaneMarker *plane_marker, int width, int height)
+static void draw_plane_marker_outline(SpaceClip *sc,
+ Scene *scene,
+ MovieTrackingPlaneTrack *plane_track,
+ MovieTrackingPlaneMarker *plane_marker,
+ int width,
+ int height)
{
- draw_plane_marker_ex(sc, scene, plane_track, plane_marker, false, true, width, height);
+ draw_plane_marker_ex(sc, scene, plane_track, plane_marker, false, true, width, height);
}
-static void draw_plane_marker(SpaceClip *sc, Scene *scene, MovieTrackingPlaneTrack *plane_track,
- MovieTrackingPlaneMarker *plane_marker, bool is_active_track,
- int width, int height)
+static void draw_plane_marker(SpaceClip *sc,
+ Scene *scene,
+ MovieTrackingPlaneTrack *plane_track,
+ MovieTrackingPlaneMarker *plane_marker,
+ bool is_active_track,
+ int width,
+ int height)
{
- draw_plane_marker_ex(sc, scene, plane_track, plane_marker, is_active_track, false, width, height);
+ draw_plane_marker_ex(
+ sc, scene, plane_track, plane_marker, is_active_track, false, width, height);
}
-static void draw_plane_track(SpaceClip *sc, Scene *scene, MovieTrackingPlaneTrack *plane_track,
- int framenr, bool is_active_track, int width, int height)
+static void draw_plane_track(SpaceClip *sc,
+ Scene *scene,
+ MovieTrackingPlaneTrack *plane_track,
+ int framenr,
+ bool is_active_track,
+ int width,
+ int height)
{
- MovieTrackingPlaneMarker *plane_marker;
+ MovieTrackingPlaneMarker *plane_marker;
- plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+ plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
- draw_plane_marker_outline(sc, scene, plane_track, plane_marker, width, height);
- draw_plane_marker(sc, scene, plane_track, plane_marker, is_active_track, width, height);
+ draw_plane_marker_outline(sc, scene, plane_track, plane_marker, width, height);
+ draw_plane_marker(sc, scene, plane_track, plane_marker, is_active_track, width, height);
}
/* Draw all kind of tracks. */
-static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, MovieClip *clip,
- int width, int height, float zoomx, float zoomy)
+static void draw_tracking_tracks(SpaceClip *sc,
+ Scene *scene,
+ ARegion *ar,
+ MovieClip *clip,
+ int width,
+ int height,
+ float zoomx,
+ float zoomy)
{
- float x, y;
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- MovieTrackingTrack *track, *act_track;
- MovieTrackingPlaneTrack *plane_track, *active_plane_track;
- MovieTrackingMarker *marker;
- int framenr = ED_space_clip_get_clip_frame_number(sc);
- int undistort = sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
- float *marker_pos = NULL, *fp, *active_pos = NULL, cur_pos[2];
-
- /* ** find window pixel coordinates of origin ** */
-
- /* UI_view2d_view_to_region_no_clip return integer values, this could
- * lead to 1px flickering when view is locked to selection during playback.
- * 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);
-
- GPU_matrix_push();
- GPU_matrix_translate_2f(x, y);
-
- GPU_matrix_push();
- GPU_matrix_scale_2f(zoomx, zoomy);
- GPU_matrix_mul(sc->stabmat);
- GPU_matrix_scale_2f(width, height);
-
- act_track = BKE_tracking_track_get_active(tracking);
-
- /* Draw plane tracks */
- active_plane_track = BKE_tracking_plane_track_get_active(tracking);
- for (plane_track = plane_tracks_base->first;
- plane_track;
- plane_track = plane_track->next)
- {
- if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
- draw_plane_track(sc, scene, plane_track, framenr, plane_track == active_plane_track, width, height);
- }
- }
-
- if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
- int count = 0;
-
- /* count */
- track = tracksbase->first;
- while (track) {
- if ((track->flag & TRACK_HIDDEN) == 0) {
- marker = BKE_tracking_marker_get(track, framenr);
-
- if (MARKER_VISIBLE(sc, track, marker))
- count++;
- }
-
- track = track->next;
- }
-
- /* undistort */
- if (count) {
- marker_pos = MEM_callocN(2 * sizeof(float) * count, "draw_tracking_tracks marker_pos");
-
- track = tracksbase->first;
- fp = marker_pos;
- while (track) {
- if ((track->flag & TRACK_HIDDEN) == 0) {
- marker = BKE_tracking_marker_get(track, framenr);
-
- if (MARKER_VISIBLE(sc, track, marker)) {
- ED_clip_point_undistorted_pos(sc, marker->pos, fp);
-
- if (track == act_track)
- active_pos = fp;
-
- fp += 2;
- }
- }
-
- track = track->next;
- }
- }
- }
-
- if (sc->flag & SC_SHOW_TRACK_PATH) {
- track = tracksbase->first;
- while (track) {
- if ((track->flag & TRACK_HIDDEN) == 0)
- draw_track_path(sc, clip, track);
-
- track = track->next;
- }
- }
-
- uint position = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* markers outline and non-selected areas */
- track = tracksbase->first;
- fp = marker_pos;
- while (track) {
- if ((track->flag & TRACK_HIDDEN) == 0) {
- marker = BKE_tracking_marker_get(track, framenr);
-
- if (MARKER_VISIBLE(sc, track, marker)) {
- copy_v2_v2(cur_pos, fp ? fp : marker->pos);
-
- draw_marker_outline(sc, track, marker, cur_pos, width, height, position);
- draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 0, position);
- draw_marker_slide_zones(sc, track, marker, cur_pos, 1, 0, 0, width, height, position);
- draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 0, 0, width, height, position);
-
- if (fp)
- fp += 2;
- }
- }
-
- track = track->next;
- }
-
- /* selected areas only, so selection wouldn't be overlapped by
- * non-selected areas */
- track = tracksbase->first;
- fp = marker_pos;
- while (track) {
- if ((track->flag & TRACK_HIDDEN) == 0) {
- int act = track == act_track;
- marker = BKE_tracking_marker_get(track, framenr);
-
- if (MARKER_VISIBLE(sc, track, marker)) {
- if (!act) {
- copy_v2_v2(cur_pos, fp ? fp : marker->pos);
-
- draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 1, position);
- draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 1, 0, width, height, position);
- }
-
- if (fp)
- fp += 2;
- }
- }
-
- track = track->next;
- }
+ float x, y;
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ MovieTrackingTrack *track, *act_track;
+ MovieTrackingPlaneTrack *plane_track, *active_plane_track;
+ MovieTrackingMarker *marker;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+ int undistort = sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
+ float *marker_pos = NULL, *fp, *active_pos = NULL, cur_pos[2];
+
+ /* ** find window pixel coordinates of origin ** */
+
+ /* UI_view2d_view_to_region_no_clip return integer values, this could
+ * lead to 1px flickering when view is locked to selection during playback.
+ * 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);
+
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(x, y);
+
+ GPU_matrix_push();
+ GPU_matrix_scale_2f(zoomx, zoomy);
+ GPU_matrix_mul(sc->stabmat);
+ GPU_matrix_scale_2f(width, height);
+
+ act_track = BKE_tracking_track_get_active(tracking);
+
+ /* Draw plane tracks */
+ active_plane_track = BKE_tracking_plane_track_get_active(tracking);
+ for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
+ if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
+ draw_plane_track(
+ sc, scene, plane_track, framenr, plane_track == active_plane_track, width, height);
+ }
+ }
+
+ if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
+ int count = 0;
+
+ /* count */
+ track = tracksbase->first;
+ while (track) {
+ if ((track->flag & TRACK_HIDDEN) == 0) {
+ marker = BKE_tracking_marker_get(track, framenr);
+
+ if (MARKER_VISIBLE(sc, track, marker))
+ count++;
+ }
+
+ track = track->next;
+ }
+
+ /* undistort */
+ if (count) {
+ marker_pos = MEM_callocN(2 * sizeof(float) * count, "draw_tracking_tracks marker_pos");
+
+ track = tracksbase->first;
+ fp = marker_pos;
+ while (track) {
+ if ((track->flag & TRACK_HIDDEN) == 0) {
+ marker = BKE_tracking_marker_get(track, framenr);
+
+ if (MARKER_VISIBLE(sc, track, marker)) {
+ ED_clip_point_undistorted_pos(sc, marker->pos, fp);
+
+ if (track == act_track)
+ active_pos = fp;
+
+ fp += 2;
+ }
+ }
+
+ track = track->next;
+ }
+ }
+ }
+
+ if (sc->flag & SC_SHOW_TRACK_PATH) {
+ track = tracksbase->first;
+ while (track) {
+ if ((track->flag & TRACK_HIDDEN) == 0)
+ draw_track_path(sc, clip, track);
+
+ track = track->next;
+ }
+ }
+
+ uint position = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* markers outline and non-selected areas */
+ track = tracksbase->first;
+ fp = marker_pos;
+ while (track) {
+ if ((track->flag & TRACK_HIDDEN) == 0) {
+ marker = BKE_tracking_marker_get(track, framenr);
+
+ if (MARKER_VISIBLE(sc, track, marker)) {
+ copy_v2_v2(cur_pos, fp ? fp : marker->pos);
+
+ draw_marker_outline(sc, track, marker, cur_pos, width, height, position);
+ draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 0, position);
+ draw_marker_slide_zones(sc, track, marker, cur_pos, 1, 0, 0, width, height, position);
+ draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 0, 0, width, height, position);
+
+ if (fp)
+ fp += 2;
+ }
+ }
+
+ track = track->next;
+ }
- /* active marker would be displayed on top of everything else */
- if (act_track) {
- if ((act_track->flag & TRACK_HIDDEN) == 0) {
- marker = BKE_tracking_marker_get(act_track, framenr);
+ /* selected areas only, so selection wouldn't be overlapped by
+ * non-selected areas */
+ track = tracksbase->first;
+ fp = marker_pos;
+ while (track) {
+ if ((track->flag & TRACK_HIDDEN) == 0) {
+ int act = track == act_track;
+ marker = BKE_tracking_marker_get(track, framenr);
+
+ if (MARKER_VISIBLE(sc, track, marker)) {
+ if (!act) {
+ copy_v2_v2(cur_pos, fp ? fp : marker->pos);
+
+ draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 1, position);
+ draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 1, 0, width, height, position);
+ }
+
+ if (fp)
+ fp += 2;
+ }
+ }
+
+ track = track->next;
+ }
+
+ /* active marker would be displayed on top of everything else */
+ if (act_track) {
+ if ((act_track->flag & TRACK_HIDDEN) == 0) {
+ marker = BKE_tracking_marker_get(act_track, framenr);
- if (MARKER_VISIBLE(sc, act_track, marker)) {
- copy_v2_v2(cur_pos, active_pos ? active_pos : marker->pos);
+ if (MARKER_VISIBLE(sc, act_track, marker)) {
+ copy_v2_v2(cur_pos, active_pos ? active_pos : marker->pos);
- draw_marker_areas(sc, act_track, marker, cur_pos, width, height, 1, 1, position);
- draw_marker_slide_zones(sc, act_track, marker, cur_pos, 0, 1, 1, width, height, position);
- }
- }
- }
+ draw_marker_areas(sc, act_track, marker, cur_pos, width, height, 1, 1, position);
+ draw_marker_slide_zones(sc, act_track, marker, cur_pos, 0, 1, 1, width, height, position);
+ }
+ }
+ }
- if (sc->flag & SC_SHOW_BUNDLES) {
- MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
- float pos[4], vec[4], mat[4][4], aspy;
+ if (sc->flag & SC_SHOW_BUNDLES) {
+ MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
+ float pos[4], vec[4], mat[4][4], aspy;
- GPU_point_size(3.0f);
+ GPU_point_size(3.0f);
- aspy = 1.0f / clip->tracking.camera.pixel_aspect;
- BKE_tracking_get_projection_matrix(tracking, object, framenr, width, height, mat);
+ aspy = 1.0f / clip->tracking.camera.pixel_aspect;
+ BKE_tracking_get_projection_matrix(tracking, object, framenr, width, height, mat);
- track = tracksbase->first;
- while (track) {
- if ((track->flag & TRACK_HIDDEN) == 0 && track->flag & TRACK_HAS_BUNDLE) {
- marker = BKE_tracking_marker_get(track, framenr);
+ track = tracksbase->first;
+ while (track) {
+ if ((track->flag & TRACK_HIDDEN) == 0 && track->flag & TRACK_HAS_BUNDLE) {
+ marker = BKE_tracking_marker_get(track, framenr);
- if (MARKER_VISIBLE(sc, track, marker)) {
- float npos[2];
- copy_v3_v3(vec, track->bundle_pos);
- vec[3] = 1;
+ if (MARKER_VISIBLE(sc, track, marker)) {
+ float npos[2];
+ copy_v3_v3(vec, track->bundle_pos);
+ vec[3] = 1;
- mul_v4_m4v4(pos, mat, vec);
+ mul_v4_m4v4(pos, mat, vec);
- pos[0] = (pos[0] / (pos[3] * 2.0f) + 0.5f) * width;
- pos[1] = (pos[1] / (pos[3] * 2.0f) + 0.5f) * height * aspy;
+ 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, 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;
- vec[1] = (marker->pos[1] + track->offset[1]) * height * aspy;
+ 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;
+ vec[1] = (marker->pos[1] + track->offset[1]) * height * aspy;
- sub_v2_v2(vec, npos);
+ sub_v2_v2(vec, npos);
- if (len_squared_v2(vec) < (3.0f * 3.0f)) {
- immUniformColor3f(0.0f, 1.0f, 0.0f);
- }
- else {
- immUniformColor3f(1.0f, 0.0f, 0.0f);
- }
+ if (len_squared_v2(vec) < (3.0f * 3.0f)) {
+ immUniformColor3f(0.0f, 1.0f, 0.0f);
+ }
+ else {
+ immUniformColor3f(1.0f, 0.0f, 0.0f);
+ }
- immBegin(GPU_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
- if (undistort) {
- immVertex2f(position, pos[0] / width, pos[1] / (height * aspy));
- }
- else {
- immVertex2f(position, npos[0] / width, npos[1] / (height * aspy));
- }
+ if (undistort) {
+ immVertex2f(position, pos[0] / width, pos[1] / (height * aspy));
+ }
+ else {
+ immVertex2f(position, npos[0] / width, npos[1] / (height * aspy));
+ }
- immEnd();
- }
- }
- }
+ immEnd();
+ }
+ }
+ }
- track = track->next;
- }
- }
+ track = track->next;
+ }
+ }
- immUnbindProgram();
+ immUnbindProgram();
- GPU_matrix_pop();
+ GPU_matrix_pop();
- if (sc->flag & SC_SHOW_NAMES) {
- /* scaling should be cleared before drawing texts, otherwise font would also be scaled */
- track = tracksbase->first;
- fp = marker_pos;
- while (track) {
- if ((track->flag & TRACK_HIDDEN) == 0) {
- marker = BKE_tracking_marker_get(track, framenr);
+ if (sc->flag & SC_SHOW_NAMES) {
+ /* scaling should be cleared before drawing texts, otherwise font would also be scaled */
+ track = tracksbase->first;
+ fp = marker_pos;
+ while (track) {
+ if ((track->flag & TRACK_HIDDEN) == 0) {
+ marker = BKE_tracking_marker_get(track, framenr);
- if (MARKER_VISIBLE(sc, track, marker)) {
- int act = track == act_track;
+ if (MARKER_VISIBLE(sc, track, marker)) {
+ int act = track == act_track;
- copy_v2_v2(cur_pos, fp ? fp : marker->pos);
+ copy_v2_v2(cur_pos, fp ? fp : marker->pos);
- draw_marker_texts(sc, track, marker, cur_pos, act, width, height, zoomx, zoomy);
+ draw_marker_texts(sc, track, marker, cur_pos, act, width, height, zoomx, zoomy);
- if (fp)
- fp += 2;
- }
- }
+ if (fp)
+ fp += 2;
+ }
+ }
- track = track->next;
- }
- }
+ track = track->next;
+ }
+ }
- GPU_matrix_pop();
+ GPU_matrix_pop();
- if (marker_pos)
- MEM_freeN(marker_pos);
+ if (marker_pos)
+ MEM_freeN(marker_pos);
}
-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 *ar, 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];
- MovieTracking *tracking = &clip->tracking;
- bGPdata *gpd = NULL;
- float aspy = 1.0f / tracking->camera.pixel_aspect;
- float dx = (float)width / n, dy = (float)height / n * aspy;
- float offsx = 0.0f, offsy = 0.0f;
+ float x, y;
+ const int n = 10;
+ int i, j, a;
+ float pos[2], tpos[2], grid[11][11][2];
+ MovieTracking *tracking = &clip->tracking;
+ bGPdata *gpd = NULL;
+ float aspy = 1.0f / tracking->camera.pixel_aspect;
+ float dx = (float)width / n, dy = (float)height / n * aspy;
+ float offsx = 0.0f, offsy = 0.0f;
- if (!tracking->camera.focal)
- return;
+ if (!tracking->camera.focal)
+ return;
- if ((sc->flag & SC_SHOW_GRID) == 0 && (sc->flag & SC_MANUAL_CALIBRATION) == 0)
- return;
+ if ((sc->flag & SC_SHOW_GRID) == 0 && (sc->flag & SC_MANUAL_CALIBRATION) == 0)
+ return;
- UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y);
+ UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y);
- GPU_matrix_push();
- GPU_matrix_translate_2f(x, y);
- GPU_matrix_scale_2f(zoomx, zoomy);
- GPU_matrix_mul(sc->stabmat);
- GPU_matrix_scale_2f(width, height);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(x, y);
+ GPU_matrix_scale_2f(zoomx, zoomy);
+ GPU_matrix_mul(sc->stabmat);
+ GPU_matrix_scale_2f(width, height);
- uint position = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint position = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- /* grid */
- if (sc->flag & SC_SHOW_GRID) {
- float val[4][2], idx[4][2];
- float min[2], max[2];
+ /* grid */
+ if (sc->flag & SC_SHOW_GRID) {
+ float val[4][2], idx[4][2];
+ float min[2], max[2];
- for (a = 0; a < 4; a++) {
- if (a < 2)
- val[a][a % 2] = FLT_MAX;
- else
- val[a][a % 2] = -FLT_MAX;
- }
+ for (a = 0; a < 4; a++) {
+ if (a < 2)
+ val[a][a % 2] = FLT_MAX;
+ else
+ val[a][a % 2] = -FLT_MAX;
+ }
- zero_v2(pos);
- for (i = 0; i <= n; i++) {
- for (j = 0; j <= n; j++) {
- if (i == 0 || j == 0 || i == n || j == n) {
- BKE_tracking_distort_v2(tracking, pos, tpos);
+ zero_v2(pos);
+ for (i = 0; i <= n; i++) {
+ for (j = 0; j <= n; j++) {
+ if (i == 0 || j == 0 || i == n || j == n) {
+ BKE_tracking_distort_v2(tracking, pos, tpos);
- for (a = 0; a < 4; a++) {
- int ok;
+ for (a = 0; a < 4; a++) {
+ int ok;
- if (a < 2)
- ok = tpos[a % 2] < val[a][a % 2];
- else
- ok = tpos[a % 2] > val[a][a % 2];
+ if (a < 2)
+ ok = tpos[a % 2] < val[a][a % 2];
+ else
+ ok = tpos[a % 2] > val[a][a % 2];
- if (ok) {
- copy_v2_v2(val[a], tpos);
- idx[a][0] = j;
- idx[a][1] = i;
- }
- }
- }
+ if (ok) {
+ copy_v2_v2(val[a], tpos);
+ idx[a][0] = j;
+ idx[a][1] = i;
+ }
+ }
+ }
- pos[0] += dx;
- }
+ pos[0] += dx;
+ }
- pos[0] = 0.0f;
- pos[1] += dy;
- }
+ pos[0] = 0.0f;
+ pos[1] += dy;
+ }
- INIT_MINMAX2(min, max);
+ INIT_MINMAX2(min, max);
- for (a = 0; a < 4; a++) {
- pos[0] = idx[a][0] * dx;
- pos[1] = idx[a][1] * dy;
+ for (a = 0; a < 4; a++) {
+ pos[0] = idx[a][0] * dx;
+ pos[1] = idx[a][1] * dy;
- BKE_tracking_undistort_v2(tracking, pos, tpos);
+ BKE_tracking_undistort_v2(tracking, pos, tpos);
- minmax_v2v2_v2(min, max, tpos);
- }
+ minmax_v2v2_v2(min, max, tpos);
+ }
- copy_v2_v2(pos, min);
- dx = (max[0] - min[0]) / n;
- dy = (max[1] - min[1]) / n;
+ 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 (i = 0; i <= n; i++) {
+ for (j = 0; j <= n; j++) {
+ BKE_tracking_distort_v2(tracking, pos, grid[i][j]);
- grid[i][j][0] /= width;
- grid[i][j][1] /= height * aspy;
+ grid[i][j][0] /= width;
+ grid[i][j][1] /= height * aspy;
- pos[0] += dx;
- }
+ pos[0] += dx;
+ }
- pos[0] = min[0];
- pos[1] += dy;
- }
+ pos[0] = min[0];
+ pos[1] += dy;
+ }
- immUniformColor3f(1.0f, 0.0f, 0.0f);
+ immUniformColor3f(1.0f, 0.0f, 0.0f);
- for (i = 0; i <= n; i++) {
- immBegin(GPU_PRIM_LINE_STRIP, n + 1);
+ for (i = 0; i <= n; i++) {
+ immBegin(GPU_PRIM_LINE_STRIP, n + 1);
- for (j = 0; j <= n; j++) {
- immVertex2fv(position, grid[i][j]);
- }
+ for (j = 0; j <= n; j++) {
+ immVertex2fv(position, grid[i][j]);
+ }
- immEnd();
- }
+ immEnd();
+ }
- for (j = 0; j <= n; j++) {
- immBegin(GPU_PRIM_LINE_STRIP, n + 1);
+ for (j = 0; j <= n; j++) {
+ immBegin(GPU_PRIM_LINE_STRIP, n + 1);
- for (i = 0; i <= n; i++) {
- immVertex2fv(position, grid[i][j]);
- }
+ for (i = 0; i <= n; i++) {
+ immVertex2fv(position, grid[i][j]);
+ }
- immEnd();
- }
- }
+ immEnd();
+ }
+ }
- if (sc->gpencil_src != SC_GPENCIL_SRC_TRACK) {
- gpd = clip->gpd;
- }
+ if (sc->gpencil_src != SC_GPENCIL_SRC_TRACK) {
+ gpd = clip->gpd;
+ }
- if (sc->flag & SC_MANUAL_CALIBRATION && gpd) {
- bGPDlayer *layer = gpd->layers.first;
+ if (sc->flag & SC_MANUAL_CALIBRATION && gpd) {
+ bGPDlayer *layer = gpd->layers.first;
- while (layer) {
- bGPDframe *frame = layer->frames.first;
+ while (layer) {
+ bGPDframe *frame = layer->frames.first;
- if (layer->flag & GP_LAYER_HIDE) {
- layer = layer->next;
- continue;
- }
+ if (layer->flag & GP_LAYER_HIDE) {
+ layer = layer->next;
+ continue;
+ }
- immUniformColor4fv(layer->color);
+ immUniformColor4fv(layer->color);
- GPU_line_width(layer->thickness);
- GPU_point_size((float)(layer->thickness + 2));
+ GPU_line_width(layer->thickness);
+ GPU_point_size((float)(layer->thickness + 2));
- while (frame) {
- bGPDstroke *stroke = frame->strokes.first;
+ while (frame) {
+ bGPDstroke *stroke = frame->strokes.first;
- 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;
- int steps;
+ 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;
+ int steps;
- pos[0] = (stroke->points[i].x + offsx) * width;
- pos[1] = (stroke->points[i].y + offsy) * height * aspy;
+ pos[0] = (stroke->points[i].x + offsx) * width;
+ pos[1] = (stroke->points[i].y + offsy) * height * aspy;
- npos[0] = (stroke->points[i + 1].x + offsx) * width;
- npos[1] = (stroke->points[i + 1].y + offsy) * height * aspy;
+ npos[0] = (stroke->points[i + 1].x + offsx) * width;
+ npos[1] = (stroke->points[i + 1].y + offsy) * height * aspy;
- len = len_v2v2(pos, npos);
- steps = ceil(len / 5.0f);
+ len = len_v2v2(pos, npos);
+ steps = ceil(len / 5.0f);
- /* 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);
- }
+ /* 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);
+ }
- sub_v2_v2v2(dpos, npos, pos);
- mul_v2_fl(dpos, 1.0f / steps);
+ sub_v2_v2v2(dpos, npos, pos);
+ mul_v2_fl(dpos, 1.0f / steps);
- immBegin(GPU_PRIM_LINE_STRIP, steps + 1);
+ immBegin(GPU_PRIM_LINE_STRIP, steps + 1);
- for (j = 0; j <= steps; j++) {
- BKE_tracking_distort_v2(tracking, pos, tpos);
- immVertex2f(position, tpos[0] / width, tpos[1] / (height * aspy));
+ for (j = 0; j <= steps; j++) {
+ BKE_tracking_distort_v2(tracking, pos, tpos);
+ immVertex2f(position, tpos[0] / width, tpos[1] / (height * aspy));
- add_v2_v2(pos, dpos);
- }
+ add_v2_v2(pos, dpos);
+ }
- immEnd();
- }
- }
- else if (stroke->totpoints == 1) {
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex2f(position, stroke->points[0].x + offsx, stroke->points[0].y + offsy);
- immEnd();
- }
- }
+ immEnd();
+ }
+ }
+ else if (stroke->totpoints == 1) {
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex2f(position, stroke->points[0].x + offsx, stroke->points[0].y + offsy);
+ immEnd();
+ }
+ }
- stroke = stroke->next;
- }
+ stroke = stroke->next;
+ }
- frame = frame->next;
- }
+ frame = frame->next;
+ }
- layer = layer->next;
- }
- }
+ layer = layer->next;
+ }
+ }
- immUnbindProgram();
+ immUnbindProgram();
- GPU_matrix_pop();
+ GPU_matrix_pop();
}
void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
{
- MovieClip *clip = ED_space_clip_get_clip(sc);
- Scene *scene = CTX_data_scene(C);
- ImBuf *ibuf = NULL;
- int width, height;
- float zoomx, zoomy;
-
- ED_space_clip_get_size(sc, &width, &height);
- ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy);
-
- /* if no clip, nothing to do */
- if (!clip) {
- ED_region_grid_draw(ar, zoomx, zoomy);
- return;
- }
-
- if (sc->flag & SC_SHOW_STABLE) {
- float translation[2];
- float aspect = clip->tracking.camera.pixel_aspect;
- float smat[4][4], ismat[4][4];
-
- if ((sc->flag & SC_MUTE_FOOTAGE) == 0) {
- ibuf = ED_space_clip_get_stable_buffer(sc, sc->loc,
- &sc->scale, &sc->angle);
- }
-
- if (ibuf != NULL && width != ibuf->x)
- mul_v2_v2fl(translation, sc->loc, (float)width / ibuf->x);
- else
- copy_v2_v2(translation, sc->loc);
-
- BKE_tracking_stabilization_data_to_mat4(width, height, aspect, translation,
- sc->scale, sc->angle, sc->stabmat);
-
- unit_m4(smat);
- smat[0][0] = 1.0f / width;
- smat[1][1] = 1.0f / height;
- invert_m4_m4(ismat, smat);
-
- mul_m4_series(sc->unistabmat, smat, sc->stabmat, ismat);
- }
- else if ((sc->flag & SC_MUTE_FOOTAGE) == 0) {
- ibuf = ED_space_clip_get_buffer(sc);
-
- zero_v2(sc->loc);
- sc->scale = 1.0f;
- unit_m4(sc->stabmat);
- unit_m4(sc->unistabmat);
- }
-
- if (ibuf) {
- draw_movieclip_buffer(C, sc, ar, ibuf, width, height, zoomx, zoomy);
- IMB_freeImBuf(ibuf);
- }
- else if (sc->flag & SC_MUTE_FOOTAGE) {
- draw_movieclip_muted(ar, width, height, zoomx, zoomy);
- }
- else {
- ED_region_grid_draw(ar, zoomx, zoomy);
- }
-
- 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);
- }
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ Scene *scene = CTX_data_scene(C);
+ ImBuf *ibuf = NULL;
+ int width, height;
+ float zoomx, zoomy;
+
+ ED_space_clip_get_size(sc, &width, &height);
+ ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy);
+
+ /* if no clip, nothing to do */
+ if (!clip) {
+ ED_region_grid_draw(ar, zoomx, zoomy);
+ return;
+ }
+
+ if (sc->flag & SC_SHOW_STABLE) {
+ float translation[2];
+ float aspect = clip->tracking.camera.pixel_aspect;
+ float smat[4][4], ismat[4][4];
+
+ if ((sc->flag & SC_MUTE_FOOTAGE) == 0) {
+ ibuf = ED_space_clip_get_stable_buffer(sc, sc->loc, &sc->scale, &sc->angle);
+ }
+
+ if (ibuf != NULL && width != ibuf->x)
+ mul_v2_v2fl(translation, sc->loc, (float)width / ibuf->x);
+ else
+ copy_v2_v2(translation, sc->loc);
+
+ BKE_tracking_stabilization_data_to_mat4(
+ width, height, aspect, translation, sc->scale, sc->angle, sc->stabmat);
+
+ unit_m4(smat);
+ smat[0][0] = 1.0f / width;
+ smat[1][1] = 1.0f / height;
+ invert_m4_m4(ismat, smat);
+
+ mul_m4_series(sc->unistabmat, smat, sc->stabmat, ismat);
+ }
+ else if ((sc->flag & SC_MUTE_FOOTAGE) == 0) {
+ ibuf = ED_space_clip_get_buffer(sc);
+
+ zero_v2(sc->loc);
+ sc->scale = 1.0f;
+ unit_m4(sc->stabmat);
+ unit_m4(sc->unistabmat);
+ }
+
+ if (ibuf) {
+ draw_movieclip_buffer(C, sc, ar, ibuf, width, height, zoomx, zoomy);
+ IMB_freeImBuf(ibuf);
+ }
+ else if (sc->flag & SC_MUTE_FOOTAGE) {
+ draw_movieclip_muted(ar, width, height, zoomx, zoomy);
+ }
+ else {
+ ED_region_grid_draw(ar, zoomx, zoomy);
+ }
+
+ 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);
+ }
}
void clip_draw_cache_and_notes(const bContext *C, SpaceClip *sc, ARegion *ar)
{
- 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);
- }
+ 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 grease pencil */
void clip_draw_grease_pencil(bContext *C, int onlyv2d)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
-
- if (!clip)
- return;
-
- if (onlyv2d) {
- bool is_track_source = sc->gpencil_src == SC_GPENCIL_SRC_TRACK;
- /* if manual calibration is used then grease pencil data
- * associated with the clip is already drawn in draw_distortion
- */
- if ((sc->flag & SC_MANUAL_CALIBRATION) == 0 || is_track_source) {
- GPU_matrix_push();
- GPU_matrix_mul(sc->unistabmat);
-
- if (is_track_source) {
- MovieTrackingTrack *track = BKE_tracking_track_get_active(&sc->clip->tracking);
-
- if (track) {
- int framenr = ED_space_clip_get_clip_frame_number(sc);
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
-
- GPU_matrix_translate_2fv(marker->pos);
- }
- }
-
- ED_annotation_draw_2dimage(C);
-
- GPU_matrix_pop();
- }
- }
- else {
- ED_annotation_draw_view2d(C, 0);
- }
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+
+ if (!clip)
+ return;
+
+ if (onlyv2d) {
+ bool is_track_source = sc->gpencil_src == SC_GPENCIL_SRC_TRACK;
+ /* if manual calibration is used then grease pencil data
+ * associated with the clip is already drawn in draw_distortion
+ */
+ if ((sc->flag & SC_MANUAL_CALIBRATION) == 0 || is_track_source) {
+ GPU_matrix_push();
+ GPU_matrix_mul(sc->unistabmat);
+
+ if (is_track_source) {
+ MovieTrackingTrack *track = BKE_tracking_track_get_active(&sc->clip->tracking);
+
+ if (track) {
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+
+ GPU_matrix_translate_2fv(marker->pos);
+ }
+ }
+
+ ED_annotation_draw_2dimage(C);
+
+ GPU_matrix_pop();
+ }
+ }
+ else {
+ ED_annotation_draw_view2d(C, 0);
+ }
}
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index 7cfc5257792..8351f79aac7 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -50,7 +50,6 @@
#include "BKE_movieclip.h"
#include "BKE_tracking.h"
-
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -65,1062 +64,1093 @@
#include "UI_view2d.h"
-#include "clip_intern.h" // own include
+#include "clip_intern.h" // own include
/* ******** operactor poll functions ******** */
bool ED_space_clip_poll(bContext *C)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
- if (sc && sc->clip)
- return true;
+ if (sc && sc->clip)
+ return true;
- return false;
+ return false;
}
bool ED_space_clip_view_clip_poll(bContext *C)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
- if (sc) {
- return sc->view == SC_VIEW_CLIP;
- }
+ if (sc) {
+ return sc->view == SC_VIEW_CLIP;
+ }
- return false;
+ return false;
}
bool ED_space_clip_tracking_poll(bContext *C)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
- if (sc && sc->clip)
- return ED_space_clip_check_show_trackedit(sc);
+ if (sc && sc->clip)
+ return ED_space_clip_check_show_trackedit(sc);
- return false;
+ return false;
}
bool ED_space_clip_maskedit_poll(bContext *C)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
- if (sc && sc->clip) {
- return ED_space_clip_check_show_maskedit(sc);
- }
+ if (sc && sc->clip) {
+ return ED_space_clip_check_show_maskedit(sc);
+ }
- return false;
+ return false;
}
bool ED_space_clip_maskedit_mask_poll(bContext *C)
{
- if (ED_space_clip_maskedit_poll(C)) {
- MovieClip *clip = CTX_data_edit_movieclip(C);
+ if (ED_space_clip_maskedit_poll(C)) {
+ MovieClip *clip = CTX_data_edit_movieclip(C);
- if (clip) {
- SpaceClip *sc = CTX_wm_space_clip(C);
+ if (clip) {
+ SpaceClip *sc = CTX_wm_space_clip(C);
- return sc->mask_info.mask != NULL;
- }
- }
+ return sc->mask_info.mask != NULL;
+ }
+ }
- return false;
+ return false;
}
/* ******** common editing functions ******** */
void ED_space_clip_get_size(SpaceClip *sc, int *width, int *height)
{
- if (sc->clip) {
- BKE_movieclip_get_size(sc->clip, &sc->user, width, height);
- }
- else {
- *width = *height = IMG_SIZE_FALLBACK;
- }
+ if (sc->clip) {
+ BKE_movieclip_get_size(sc->clip, &sc->user, width, height);
+ }
+ else {
+ *width = *height = IMG_SIZE_FALLBACK;
+ }
}
void ED_space_clip_get_size_fl(SpaceClip *sc, float size[2])
{
- int size_i[2];
- ED_space_clip_get_size(sc, &size_i[0], &size_i[1]);
- size[0] = size_i[0];
- size[1] = size_i[1];
+ int size_i[2];
+ ED_space_clip_get_size(sc, &size_i[0], &size_i[1]);
+ size[0] = size_i[0];
+ size[1] = size_i[1];
}
void ED_space_clip_get_zoom(SpaceClip *sc, ARegion *ar, float *zoomx, float *zoomy)
{
- int width, height;
+ int width, height;
- ED_space_clip_get_size(sc, &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(&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);
}
void ED_space_clip_get_aspect(SpaceClip *sc, float *aspx, float *aspy)
{
- MovieClip *clip = ED_space_clip_get_clip(sc);
-
- if (clip)
- BKE_movieclip_get_aspect(clip, aspx, aspy);
- else
- *aspx = *aspy = 1.0f;
-
- if (*aspx < *aspy) {
- *aspy = *aspy / *aspx;
- *aspx = 1.0f;
- }
- else {
- *aspx = *aspx / *aspy;
- *aspy = 1.0f;
- }
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+
+ if (clip)
+ BKE_movieclip_get_aspect(clip, aspx, aspy);
+ else
+ *aspx = *aspy = 1.0f;
+
+ if (*aspx < *aspy) {
+ *aspy = *aspy / *aspx;
+ *aspx = 1.0f;
+ }
+ else {
+ *aspx = *aspx / *aspy;
+ *aspy = 1.0f;
+ }
}
void ED_space_clip_get_aspect_dimension_aware(SpaceClip *sc, float *aspx, float *aspy)
{
- int w, h;
-
- /* most of tools does not require aspect to be returned with dimensions correction
- * 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
- */
-
- if (!sc->clip) {
- *aspx = 1.0f;
- *aspy = 1.0f;
-
- return;
- }
-
- ED_space_clip_get_aspect(sc, aspx, aspy);
- BKE_movieclip_get_size(sc->clip, &sc->user, &w, &h);
-
- *aspx *= (float) w;
- *aspy *= (float) h;
-
- if (*aspx < *aspy) {
- *aspy = *aspy / *aspx;
- *aspx = 1.0f;
- }
- else {
- *aspx = *aspx / *aspy;
- *aspy = 1.0f;
- }
+ int w, h;
+
+ /* most of tools does not require aspect to be returned with dimensions correction
+ * 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
+ */
+
+ if (!sc->clip) {
+ *aspx = 1.0f;
+ *aspy = 1.0f;
+
+ return;
+ }
+
+ ED_space_clip_get_aspect(sc, aspx, aspy);
+ BKE_movieclip_get_size(sc->clip, &sc->user, &w, &h);
+
+ *aspx *= (float)w;
+ *aspy *= (float)h;
+
+ if (*aspx < *aspy) {
+ *aspy = *aspy / *aspx;
+ *aspx = 1.0f;
+ }
+ else {
+ *aspx = *aspx / *aspy;
+ *aspy = 1.0f;
+ }
}
/* return current frame number in clip space */
int ED_space_clip_get_clip_frame_number(SpaceClip *sc)
{
- MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
- /* Caller must ensure space does have a valid clip, otherwise it will crash, see T45017. */
- return BKE_movieclip_remap_scene_to_clip_frame(clip, sc->user.framenr);
+ /* Caller must ensure space does have a valid clip, otherwise it will crash, see T45017. */
+ return BKE_movieclip_remap_scene_to_clip_frame(clip, sc->user.framenr);
}
ImBuf *ED_space_clip_get_buffer(SpaceClip *sc)
{
- if (sc->clip) {
- ImBuf *ibuf;
+ if (sc->clip) {
+ ImBuf *ibuf;
- ibuf = BKE_movieclip_get_postprocessed_ibuf(sc->clip, &sc->user, sc->postproc_flag);
+ ibuf = BKE_movieclip_get_postprocessed_ibuf(sc->clip, &sc->user, sc->postproc_flag);
- if (ibuf && (ibuf->rect || ibuf->rect_float))
- return ibuf;
+ if (ibuf && (ibuf->rect || ibuf->rect_float))
+ return ibuf;
- if (ibuf)
- IMB_freeImBuf(ibuf);
- }
+ if (ibuf)
+ IMB_freeImBuf(ibuf);
+ }
- return NULL;
+ return NULL;
}
ImBuf *ED_space_clip_get_stable_buffer(SpaceClip *sc, float loc[2], float *scale, float *angle)
{
- if (sc->clip) {
- ImBuf *ibuf;
+ if (sc->clip) {
+ ImBuf *ibuf;
- ibuf = BKE_movieclip_get_stable_ibuf(sc->clip, &sc->user, loc, scale, angle, sc->postproc_flag);
+ ibuf = BKE_movieclip_get_stable_ibuf(
+ sc->clip, &sc->user, loc, scale, angle, sc->postproc_flag);
- if (ibuf && (ibuf->rect || ibuf->rect_float))
- return ibuf;
+ if (ibuf && (ibuf->rect || ibuf->rect_float))
+ return ibuf;
- if (ibuf)
- IMB_freeImBuf(ibuf);
- }
+ if (ibuf)
+ IMB_freeImBuf(ibuf);
+ }
- return NULL;
+ return NULL;
}
/* 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])
{
- ImBuf *ibuf;
- float fx, fy, co[2];
- bool ret = false;
-
- ibuf = ED_space_clip_get_buffer(sc);
- if (!ibuf) {
- return false;
- }
-
- /* map the mouse coords to the backdrop image space */
- ED_clip_mouse_pos(sc, ar, 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;
- int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
-
- CLAMP(x, 0, ibuf->x - 1);
- CLAMP(y, 0, ibuf->y - 1);
-
- if (ibuf->rect_float) {
- fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
- copy_v3_v3(r_col, fp);
- ret = true;
- }
- else if (ibuf->rect) {
- cp = (unsigned char *)(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;
- }
- }
-
- IMB_freeImBuf(ibuf);
-
- return ret;
+ ImBuf *ibuf;
+ float fx, fy, co[2];
+ bool ret = false;
+
+ ibuf = ED_space_clip_get_buffer(sc);
+ if (!ibuf) {
+ return false;
+ }
+
+ /* map the mouse coords to the backdrop image space */
+ ED_clip_mouse_pos(sc, ar, 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;
+ int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
+
+ CLAMP(x, 0, ibuf->x - 1);
+ CLAMP(y, 0, ibuf->y - 1);
+
+ if (ibuf->rect_float) {
+ fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
+ copy_v3_v3(r_col, fp);
+ ret = true;
+ }
+ else if (ibuf->rect) {
+ cp = (unsigned char *)(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;
+ }
+ }
+
+ IMB_freeImBuf(ibuf);
+
+ return ret;
}
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) {
- 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;
-
- sc->scopes.ok = false;
-
- BKE_movieclip_user_set_frame(&sc->user, 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) {
+ 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;
+
+ sc->scopes.ok = false;
+
+ BKE_movieclip_user_set_frame(&sc->user, cfra);
+ }
+ }
+ }
+ }
}
static bool selected_tracking_boundbox(SpaceClip *sc, float min[2], float max[2])
{
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTrackingTrack *track;
- int width, height;
- bool ok = false;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
- int framenr = ED_space_clip_get_clip_frame_number(sc);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTrackingTrack *track;
+ int width, height;
+ bool ok = false;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
- INIT_MINMAX2(min, max);
+ INIT_MINMAX2(min, max);
- ED_space_clip_get_size(sc, &width, &height);
+ ED_space_clip_get_size(sc, &width, &height);
- track = tracksbase->first;
- while (track) {
- if (TRACK_VIEW_SELECTED(sc, track)) {
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+ track = tracksbase->first;
+ while (track) {
+ if (TRACK_VIEW_SELECTED(sc, track)) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
- if (marker) {
- float pos[3];
+ if (marker) {
+ float pos[3];
- pos[0] = marker->pos[0] + track->offset[0];
- pos[1] = marker->pos[1] + track->offset[1];
- pos[2] = 0.0f;
+ pos[0] = marker->pos[0] + track->offset[0];
+ pos[1] = marker->pos[1] + track->offset[1];
+ pos[2] = 0.0f;
- /* undistortion happens for normalized coords */
- if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
- /* undistortion happens for normalized coords */
- ED_clip_point_undistorted_pos(sc, pos, pos);
- }
+ /* undistortion happens for normalized coords */
+ if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
+ /* undistortion happens for normalized coords */
+ ED_clip_point_undistorted_pos(sc, pos, pos);
+ }
- pos[0] *= width;
- pos[1] *= height;
+ pos[0] *= width;
+ pos[1] *= height;
- mul_v3_m4v3(pos, sc->stabmat, pos);
+ mul_v3_m4v3(pos, sc->stabmat, pos);
- minmax_v2v2_v2(min, max, pos);
+ minmax_v2v2_v2(min, max, pos);
- ok = true;
- }
- }
+ ok = true;
+ }
+ }
- track = track->next;
- }
+ track = track->next;
+ }
- return ok;
+ return ok;
}
static bool selected_boundbox(const bContext *C, float min[2], float max[2])
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- if (sc->mode == SC_MODE_TRACKING) {
- return selected_tracking_boundbox(sc, min, max);
- }
- else {
- if (ED_mask_selected_minmax(C, min, max)) {
- MovieClip *clip = ED_space_clip_get_clip(sc);
- int width, height;
- ED_space_clip_get_size(sc, &width, &height);
- BKE_mask_coord_to_movieclip(clip, &sc->user, min, min);
- BKE_mask_coord_to_movieclip(clip, &sc->user, max, max);
- min[0] *= width;
- min[1] *= height;
- max[0] *= width;
- max[1] *= height;
- return true;
- }
- return false;
- }
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ if (sc->mode == SC_MODE_TRACKING) {
+ return selected_tracking_boundbox(sc, min, max);
+ }
+ else {
+ if (ED_mask_selected_minmax(C, min, max)) {
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ int width, height;
+ ED_space_clip_get_size(sc, &width, &height);
+ BKE_mask_coord_to_movieclip(clip, &sc->user, min, min);
+ BKE_mask_coord_to_movieclip(clip, &sc->user, max, max);
+ min[0] *= width;
+ min[1] *= height;
+ max[0] *= width;
+ max[1] *= height;
+ return true;
+ }
+ return false;
+ }
}
bool ED_clip_view_selection(const bContext *C, ARegion *ar, bool fit)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- int w, h, frame_width, frame_height;
- float min[2], max[2];
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ int w, h, frame_width, frame_height;
+ float min[2], max[2];
- ED_space_clip_get_size(sc, &frame_width, &frame_height);
+ ED_space_clip_get_size(sc, &frame_width, &frame_height);
- if ((frame_width == 0) || (frame_height == 0) || (sc->clip == NULL))
- return false;
+ if ((frame_width == 0) || (frame_height == 0) || (sc->clip == NULL))
+ return false;
- if (!selected_boundbox(C, min, max))
- return false;
+ if (!selected_boundbox(C, min, max))
+ return false;
- /* center view */
- clip_view_center_to_point(sc, (max[0] + min[0]) / (2 * frame_width),
- (max[1] + min[1]) / (2 * frame_height));
+ /* center view */
+ clip_view_center_to_point(
+ sc, (max[0] + min[0]) / (2 * frame_width), (max[1] + min[1]) / (2 * frame_height));
- w = max[0] - min[0];
- h = max[1] - min[1];
+ w = max[0] - min[0];
+ h = max[1] - min[1];
- /* set zoom to see all selection */
- if (w > 0 && h > 0) {
- int width, height;
- float zoomx, zoomy, newzoom, aspx, aspy;
+ /* set zoom to see all selection */
+ if (w > 0 && h > 0) {
+ int width, height;
+ float zoomx, zoomy, newzoom, aspx, aspy;
- ED_space_clip_get_aspect(sc, &aspx, &aspy);
+ 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(&ar->winrct) + 1;
+ height = BLI_rcti_size_y(&ar->winrct) + 1;
- zoomx = (float)width / w / aspx;
- zoomy = (float)height / h / aspy;
+ zoomx = (float)width / w / aspx;
+ zoomy = (float)height / h / aspy;
- newzoom = 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy));
+ newzoom = 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy));
- if (fit || sc->zoom > newzoom)
- sc->zoom = newzoom;
- }
+ if (fit || sc->zoom > newzoom)
+ sc->zoom = newzoom;
+ }
- return true;
+ return true;
}
void ED_clip_select_all(SpaceClip *sc, int action, bool *r_has_selection)
{
- MovieClip *clip = ED_space_clip_get_clip(sc);
- const int framenr = ED_space_clip_get_clip_frame_number(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingTrack *track = NULL; /* selected track */
- MovieTrackingPlaneTrack *plane_track = NULL; /* selected plane track */
- MovieTrackingMarker *marker;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- bool has_selection = false;
-
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
-
- for (track = tracksbase->first; track; track = track->next) {
- if (TRACK_VIEW_SELECTED(sc, track)) {
- marker = BKE_tracking_marker_get(track, framenr);
-
- if (MARKER_VISIBLE(sc, track, marker)) {
- action = SEL_DESELECT;
- break;
- }
- }
- }
-
- for (plane_track = plane_tracks_base->first;
- plane_track;
- plane_track = plane_track->next)
- {
- if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
- action = SEL_DESELECT;
- break;
- }
- }
- }
-
- for (track = tracksbase->first; track; track = track->next) {
- if ((track->flag & TRACK_HIDDEN) == 0) {
- marker = BKE_tracking_marker_get(track, framenr);
-
- if (MARKER_VISIBLE(sc, track, marker)) {
- switch (action) {
- case SEL_SELECT:
- track->flag |= SELECT;
- track->pat_flag |= SELECT;
- track->search_flag |= SELECT;
- break;
- case SEL_DESELECT:
- track->flag &= ~SELECT;
- track->pat_flag &= ~SELECT;
- track->search_flag &= ~SELECT;
- break;
- case SEL_INVERT:
- track->flag ^= SELECT;
- track->pat_flag ^= SELECT;
- track->search_flag ^= SELECT;
- break;
- }
- }
- }
-
- if (TRACK_VIEW_SELECTED(sc, track))
- has_selection = true;
- }
-
- for (plane_track = plane_tracks_base->first;
- plane_track;
- plane_track = plane_track->next)
- {
- if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
- switch (action) {
- case SEL_SELECT:
- plane_track->flag |= SELECT;
- break;
- case SEL_DESELECT:
- plane_track->flag &= ~SELECT;
- break;
- case SEL_INVERT:
- plane_track->flag ^= SELECT;
- break;
- }
- if (plane_track->flag & SELECT) {
- has_selection = true;
- }
- }
- }
-
- if (r_has_selection) {
- *r_has_selection = has_selection;
- }
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ const int framenr = ED_space_clip_get_clip_frame_number(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingTrack *track = NULL; /* selected track */
+ MovieTrackingPlaneTrack *plane_track = NULL; /* selected plane track */
+ MovieTrackingMarker *marker;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ bool has_selection = false;
+
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+
+ for (track = tracksbase->first; track; track = track->next) {
+ if (TRACK_VIEW_SELECTED(sc, track)) {
+ marker = BKE_tracking_marker_get(track, framenr);
+
+ if (MARKER_VISIBLE(sc, track, marker)) {
+ action = SEL_DESELECT;
+ break;
+ }
+ }
+ }
+
+ for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
+ if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
+ action = SEL_DESELECT;
+ break;
+ }
+ }
+ }
+
+ for (track = tracksbase->first; track; track = track->next) {
+ if ((track->flag & TRACK_HIDDEN) == 0) {
+ marker = BKE_tracking_marker_get(track, framenr);
+
+ if (MARKER_VISIBLE(sc, track, marker)) {
+ switch (action) {
+ case SEL_SELECT:
+ track->flag |= SELECT;
+ track->pat_flag |= SELECT;
+ track->search_flag |= SELECT;
+ break;
+ case SEL_DESELECT:
+ track->flag &= ~SELECT;
+ track->pat_flag &= ~SELECT;
+ track->search_flag &= ~SELECT;
+ break;
+ case SEL_INVERT:
+ track->flag ^= SELECT;
+ track->pat_flag ^= SELECT;
+ track->search_flag ^= SELECT;
+ break;
+ }
+ }
+ }
+
+ if (TRACK_VIEW_SELECTED(sc, track))
+ has_selection = true;
+ }
+
+ for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
+ if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
+ switch (action) {
+ case SEL_SELECT:
+ plane_track->flag |= SELECT;
+ break;
+ case SEL_DESELECT:
+ plane_track->flag &= ~SELECT;
+ break;
+ case SEL_INVERT:
+ plane_track->flag ^= SELECT;
+ break;
+ }
+ if (plane_track->flag & SELECT) {
+ has_selection = true;
+ }
+ }
+ }
+
+ if (r_has_selection) {
+ *r_has_selection = has_selection;
+ }
}
void ED_clip_point_undistorted_pos(SpaceClip *sc, const float co[2], float r_co[2])
{
- copy_v2_v2(r_co, co);
+ copy_v2_v2(r_co, co);
- if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
- MovieClip *clip = ED_space_clip_get_clip(sc);
- float aspy = 1.0f / clip->tracking.camera.pixel_aspect;
- int width, height;
+ if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ float aspy = 1.0f / clip->tracking.camera.pixel_aspect;
+ int width, height;
- BKE_movieclip_get_size(sc->clip, &sc->user, &width, &height);
+ BKE_movieclip_get_size(sc->clip, &sc->user, &width, &height);
- r_co[0] *= width;
- r_co[1] *= height * aspy;
+ 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, r_co, r_co);
- r_co[0] /= width;
- r_co[1] /= height * aspy;
- }
+ 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)
{
- int sx, sy, width, height;
- float zoomx, zoomy, pos[3], imat[4][4];
+ 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_size(sc, &width, &height);
+ ED_space_clip_get_zoom(sc, ar, &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(&ar->v2d, 0.0f, 0.0f, &sx, &sy);
- pos[0] = (x - sx) / zoomx;
- pos[1] = (y - sy) / zoomy;
- pos[2] = 0.0f;
+ pos[0] = (x - sx) / zoomx;
+ pos[1] = (y - sy) / zoomy;
+ pos[2] = 0.0f;
- invert_m4_m4(imat, sc->stabmat);
- mul_v3_m4v3(pos, imat, pos);
+ invert_m4_m4(imat, sc->stabmat);
+ mul_v3_m4v3(pos, imat, pos);
- *xr = pos[0] / width;
- *yr = pos[1] / height;
+ *xr = pos[0] / width;
+ *yr = pos[1] / height;
- if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- float aspy = 1.0f / tracking->camera.pixel_aspect;
- float tmp[2] = {*xr * width, *yr * height * aspy};
+ if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ 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, tmp, tmp);
- *xr = tmp[0] / width;
- *yr = tmp[1] / (height * aspy);
- }
+ *xr = tmp[0] / width;
+ *yr = tmp[1] / (height * aspy);
+ }
}
/**
* \brief the reverse of #ED_clip_point_stable_pos(), gets the marker region coords.
* better name here? view_to_track / track_to_view or so?
*/
-void ED_clip_point_stable_pos__reverse(SpaceClip *sc, ARegion *ar, const float co[2], float r_co[2])
+void ED_clip_point_stable_pos__reverse(SpaceClip *sc,
+ ARegion *ar,
+ const float co[2],
+ float r_co[2])
{
- float zoomx, zoomy;
- float pos[3];
- int width, height;
- int sx, sy;
+ float zoomx, zoomy;
+ float pos[3];
+ int width, height;
+ int sx, sy;
- UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &sx, &sy);
- ED_space_clip_get_size(sc, &width, &height);
- ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy);
+ UI_view2d_view_to_region(&ar->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_clip_point_undistorted_pos(sc, co, pos);
- pos[2] = 0.0f;
+ ED_clip_point_undistorted_pos(sc, co, pos);
+ pos[2] = 0.0f;
- /* untested */
- mul_v3_m4v3(pos, sc->stabmat, pos);
+ /* untested */
+ mul_v3_m4v3(pos, sc->stabmat, pos);
- r_co[0] = (pos[0] * width * zoomx) + (float)sx;
- r_co[1] = (pos[1] * height * zoomy) + (float)sy;
+ r_co[0] = (pos[0] * width * zoomx) + (float)sx;
+ r_co[1] = (pos[1] * height * zoomy) + (float)sy;
}
/* takes event->mval */
void ED_clip_mouse_pos(SpaceClip *sc, ARegion *ar, 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, ar, mval[0], mval[1], &co[0], &co[1]);
}
bool ED_space_clip_check_show_trackedit(SpaceClip *sc)
{
- if (sc) {
- return sc->mode == SC_MODE_TRACKING;
- }
+ if (sc) {
+ return sc->mode == SC_MODE_TRACKING;
+ }
- return false;
+ return false;
}
bool ED_space_clip_check_show_maskedit(SpaceClip *sc)
{
- if (sc) {
- return sc->mode == SC_MODE_MASKEDIT;
- }
+ if (sc) {
+ return sc->mode == SC_MODE_MASKEDIT;
+ }
- return false;
+ return false;
}
/* ******** clip editing functions ******** */
MovieClip *ED_space_clip_get_clip(SpaceClip *sc)
{
- return sc->clip;
+ return sc->clip;
}
void ED_space_clip_set_clip(bContext *C, bScreen *screen, SpaceClip *sc, MovieClip *clip)
{
- MovieClip *old_clip;
- bool old_clip_visible = false;
-
- if (!screen && C)
- screen = CTX_wm_screen(C);
-
- old_clip = sc->clip;
- sc->clip = clip;
-
- id_us_ensure_real((ID *)sc->clip);
-
- if (screen && sc->view == SC_VIEW_CLIP) {
- ScrArea *area;
- SpaceLink *sl;
-
- for (area = screen->areabase.first; area; area = area->next) {
- for (sl = area->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_CLIP) {
- SpaceClip *cur_sc = (SpaceClip *) sl;
-
- if (cur_sc != sc) {
- if (cur_sc->view == SC_VIEW_CLIP) {
- if (cur_sc->clip == old_clip)
- old_clip_visible = true;
- }
- else {
- if (cur_sc->clip == old_clip || cur_sc->clip == NULL) {
- cur_sc->clip = clip;
- }
- }
- }
- }
- }
- }
- }
-
- /* If clip is no longer visible on screen, free memory used by it's cache */
- if (old_clip && old_clip != clip && !old_clip_visible) {
- BKE_movieclip_clear_cache(old_clip);
- }
-
- if (C)
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_SELECTED, sc->clip);
+ MovieClip *old_clip;
+ bool old_clip_visible = false;
+
+ if (!screen && C)
+ screen = CTX_wm_screen(C);
+
+ old_clip = sc->clip;
+ sc->clip = clip;
+
+ id_us_ensure_real((ID *)sc->clip);
+
+ if (screen && sc->view == SC_VIEW_CLIP) {
+ ScrArea *area;
+ SpaceLink *sl;
+
+ for (area = screen->areabase.first; area; area = area->next) {
+ for (sl = area->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_CLIP) {
+ SpaceClip *cur_sc = (SpaceClip *)sl;
+
+ if (cur_sc != sc) {
+ if (cur_sc->view == SC_VIEW_CLIP) {
+ if (cur_sc->clip == old_clip)
+ old_clip_visible = true;
+ }
+ else {
+ if (cur_sc->clip == old_clip || cur_sc->clip == NULL) {
+ cur_sc->clip = clip;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* If clip is no longer visible on screen, free memory used by it's cache */
+ if (old_clip && old_clip != clip && !old_clip_visible) {
+ BKE_movieclip_clear_cache(old_clip);
+ }
+
+ if (C)
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_SELECTED, sc->clip);
}
/* ******** masking editing functions ******** */
Mask *ED_space_clip_get_mask(SpaceClip *sc)
{
- return sc->mask_info.mask;
+ return sc->mask_info.mask;
}
void ED_space_clip_set_mask(bContext *C, SpaceClip *sc, Mask *mask)
{
- sc->mask_info.mask = mask;
+ sc->mask_info.mask = mask;
- id_us_ensure_real((ID *)sc->mask_info.mask);
+ id_us_ensure_real((ID *)sc->mask_info.mask);
- if (C) {
- WM_event_add_notifier(C, NC_MASK | NA_SELECTED, mask);
- }
+ if (C) {
+ WM_event_add_notifier(C, NC_MASK | NA_SELECTED, mask);
+ }
}
/* ******** pre-fetching functions ******** */
typedef struct PrefetchJob {
- MovieClip *clip;
- int start_frame, current_frame, end_frame;
- short render_size, render_flag;
+ MovieClip *clip;
+ int start_frame, current_frame, end_frame;
+ short render_size, render_flag;
} PrefetchJob;
typedef struct PrefetchQueue {
- int initial_frame, current_frame, start_frame, end_frame;
- short render_size, render_flag;
+ int initial_frame, current_frame, start_frame, end_frame;
+ short render_size, render_flag;
- /* If true prefecthing goes forward in time,
- * otherwise it goes backwards in time (starting from current frame).
- */
- bool forward;
+ /* If true prefecthing goes forward in time,
+ * otherwise it goes backwards in time (starting from current frame).
+ */
+ bool forward;
- SpinLock spin;
+ SpinLock spin;
- short *stop;
- short *do_update;
- float *progress;
+ short *stop;
+ short *do_update;
+ float *progress;
} PrefetchQueue;
/* check whether pre-fetching is allowed */
static bool check_prefetch_break(void)
{
- return G.is_break;
+ return G.is_break;
}
/* read file for specified frame number to the memory */
static unsigned char *prefetch_read_file_to_memory(
- MovieClip *clip, int current_frame, short render_size, short render_flag,
- size_t *r_size)
+ MovieClip *clip, int current_frame, short render_size, short render_flag, size_t *r_size)
{
- MovieClipUser user = {0};
- user.framenr = current_frame;
- user.render_size = render_size;
- user.render_flag = render_flag;
-
- char name[FILE_MAX];
- BKE_movieclip_filename_for_frame(clip, &user, name);
-
- int file = BLI_open(name, O_BINARY | O_RDONLY, 0);
- if (file == -1) {
- return NULL;
- }
-
- const size_t size = BLI_file_descriptor_size(file);
- if (size < 1) {
- close(file);
- return NULL;
- }
-
- unsigned char *mem = MEM_mallocN(size, "movieclip prefetch memory file");
- if (mem == NULL) {
- close(file);
- return NULL;
- }
-
- if (read(file, mem, size) != size) {
- close(file);
- MEM_freeN(mem);
- return NULL;
- }
-
- *r_size = size;
-
- close(file);
-
- return mem;
+ MovieClipUser user = {0};
+ user.framenr = current_frame;
+ user.render_size = render_size;
+ user.render_flag = render_flag;
+
+ char name[FILE_MAX];
+ BKE_movieclip_filename_for_frame(clip, &user, name);
+
+ int file = BLI_open(name, O_BINARY | O_RDONLY, 0);
+ if (file == -1) {
+ return NULL;
+ }
+
+ const size_t size = BLI_file_descriptor_size(file);
+ if (size < 1) {
+ close(file);
+ return NULL;
+ }
+
+ unsigned char *mem = MEM_mallocN(size, "movieclip prefetch memory file");
+ if (mem == NULL) {
+ close(file);
+ return NULL;
+ }
+
+ if (read(file, mem, size) != size) {
+ close(file);
+ MEM_freeN(mem);
+ return NULL;
+ }
+
+ *r_size = size;
+
+ close(file);
+
+ return mem;
}
/* find first uncached frame within prefetching frame range */
-static int prefetch_find_uncached_frame(MovieClip *clip, int from_frame, int end_frame,
- short render_size, short render_flag, short direction)
+static int prefetch_find_uncached_frame(MovieClip *clip,
+ int from_frame,
+ int end_frame,
+ short render_size,
+ short render_flag,
+ short direction)
{
- int current_frame;
- MovieClipUser user = {0};
-
- user.render_size = render_size;
- user.render_flag = render_flag;
-
- if (direction > 0) {
- for (current_frame = from_frame; current_frame <= end_frame; current_frame++) {
- user.framenr = current_frame;
-
- if (!BKE_movieclip_has_cached_frame(clip, &user))
- break;
- }
- }
- else {
- for (current_frame = from_frame; current_frame >= end_frame; current_frame--) {
- user.framenr = current_frame;
-
- if (!BKE_movieclip_has_cached_frame(clip, &user))
- break;
- }
- }
-
- return current_frame;
+ int current_frame;
+ MovieClipUser user = {0};
+
+ user.render_size = render_size;
+ user.render_flag = render_flag;
+
+ if (direction > 0) {
+ for (current_frame = from_frame; current_frame <= end_frame; current_frame++) {
+ user.framenr = current_frame;
+
+ if (!BKE_movieclip_has_cached_frame(clip, &user))
+ break;
+ }
+ }
+ else {
+ for (current_frame = from_frame; current_frame >= end_frame; current_frame--) {
+ user.framenr = current_frame;
+
+ if (!BKE_movieclip_has_cached_frame(clip, &user))
+ break;
+ }
+ }
+
+ return current_frame;
}
/* 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 unsigned char *prefetch_thread_next_frame(PrefetchQueue *queue,
+ MovieClip *clip,
+ size_t *r_size,
+ int *r_current_frame)
{
- unsigned char *mem = NULL;
-
- BLI_spin_lock(&queue->spin);
- if (!*queue->stop && !check_prefetch_break() &&
- IN_RANGE_INCL(queue->current_frame, queue->start_frame, queue->end_frame))
- {
- int current_frame;
-
- if (queue->forward) {
- current_frame = prefetch_find_uncached_frame(clip, queue->current_frame + 1, queue->end_frame,
- queue->render_size, queue->render_flag, 1);
- /* switch direction if read frames from current up to scene end frames */
- if (current_frame > queue->end_frame) {
- queue->current_frame = queue->initial_frame;
- queue->forward = false;
- }
- }
-
- if (!queue->forward) {
- current_frame = prefetch_find_uncached_frame(clip, queue->current_frame - 1, queue->start_frame,
- queue->render_size, queue->render_flag, -1);
- }
-
- if (IN_RANGE_INCL(current_frame, queue->start_frame, queue->end_frame)) {
- int frames_processed;
-
- mem = prefetch_read_file_to_memory(clip, current_frame, queue->render_size,
- queue->render_flag, r_size);
-
- *r_current_frame = current_frame;
-
- queue->current_frame = current_frame;
-
- if (queue->forward) {
- frames_processed = queue->current_frame - queue->initial_frame;
- }
- else {
- frames_processed = (queue->end_frame - queue->initial_frame) +
- (queue->initial_frame - queue->current_frame);
- }
-
- *queue->do_update = 1;
- *queue->progress = (float)frames_processed / (queue->end_frame - queue->start_frame);
- }
- }
- BLI_spin_unlock(&queue->spin);
-
- return mem;
+ unsigned char *mem = NULL;
+
+ BLI_spin_lock(&queue->spin);
+ if (!*queue->stop && !check_prefetch_break() &&
+ IN_RANGE_INCL(queue->current_frame, queue->start_frame, queue->end_frame)) {
+ int current_frame;
+
+ if (queue->forward) {
+ current_frame = prefetch_find_uncached_frame(clip,
+ queue->current_frame + 1,
+ queue->end_frame,
+ queue->render_size,
+ queue->render_flag,
+ 1);
+ /* switch direction if read frames from current up to scene end frames */
+ if (current_frame > queue->end_frame) {
+ queue->current_frame = queue->initial_frame;
+ queue->forward = false;
+ }
+ }
+
+ if (!queue->forward) {
+ current_frame = prefetch_find_uncached_frame(clip,
+ queue->current_frame - 1,
+ queue->start_frame,
+ queue->render_size,
+ queue->render_flag,
+ -1);
+ }
+
+ if (IN_RANGE_INCL(current_frame, queue->start_frame, queue->end_frame)) {
+ int frames_processed;
+
+ mem = prefetch_read_file_to_memory(
+ clip, current_frame, queue->render_size, queue->render_flag, r_size);
+
+ *r_current_frame = current_frame;
+
+ queue->current_frame = current_frame;
+
+ if (queue->forward) {
+ frames_processed = queue->current_frame - queue->initial_frame;
+ }
+ else {
+ frames_processed = (queue->end_frame - queue->initial_frame) +
+ (queue->initial_frame - queue->current_frame);
+ }
+
+ *queue->do_update = 1;
+ *queue->progress = (float)frames_processed / (queue->end_frame - queue->start_frame);
+ }
+ }
+ BLI_spin_unlock(&queue->spin);
+
+ 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, int UNUSED(threadid))
{
- PrefetchQueue *queue = (PrefetchQueue *)BLI_task_pool_userdata(pool);
- MovieClip *clip = (MovieClip *)task_data;
- unsigned char *mem;
- size_t size;
- int current_frame;
-
- while ((mem = prefetch_thread_next_frame(queue, clip, &size, &current_frame))) {
- ImBuf *ibuf;
- MovieClipUser user = {0};
- int flag = IB_rect | IB_multilayer | IB_alphamode_detect | IB_metadata;
- int result;
- char *colorspace_name = NULL;
- const bool use_proxy = (clip->flag & MCLIP_USE_PROXY) &&
- (queue->render_size != MCLIP_PROXY_RENDER_SIZE_FULL);
-
- user.framenr = current_frame;
- user.render_size = queue->render_size;
- user.render_flag = queue->render_flag;
-
- /* Proxies are stored in the display space. */
- if (!use_proxy) {
- colorspace_name = clip->colorspace_settings.name;
- }
-
- ibuf = IMB_ibImageFromMemory(mem, size, flag, colorspace_name, "prefetch frame");
- if (ibuf == NULL) {
- continue;
- }
- BKE_movieclip_convert_multilayer_ibuf(ibuf);
-
- result = BKE_movieclip_put_frame_if_possible(clip, &user, ibuf);
-
- IMB_freeImBuf(ibuf);
-
- MEM_freeN(mem);
-
- if (!result) {
- /* no more space in the cache, stop reading frames */
- *queue->stop = 1;
- break;
- }
- }
+ PrefetchQueue *queue = (PrefetchQueue *)BLI_task_pool_userdata(pool);
+ MovieClip *clip = (MovieClip *)task_data;
+ unsigned char *mem;
+ size_t size;
+ int current_frame;
+
+ while ((mem = prefetch_thread_next_frame(queue, clip, &size, &current_frame))) {
+ ImBuf *ibuf;
+ MovieClipUser user = {0};
+ int flag = IB_rect | IB_multilayer | IB_alphamode_detect | IB_metadata;
+ int result;
+ char *colorspace_name = NULL;
+ const bool use_proxy = (clip->flag & MCLIP_USE_PROXY) &&
+ (queue->render_size != MCLIP_PROXY_RENDER_SIZE_FULL);
+
+ user.framenr = current_frame;
+ user.render_size = queue->render_size;
+ user.render_flag = queue->render_flag;
+
+ /* Proxies are stored in the display space. */
+ if (!use_proxy) {
+ colorspace_name = clip->colorspace_settings.name;
+ }
+
+ ibuf = IMB_ibImageFromMemory(mem, size, flag, colorspace_name, "prefetch frame");
+ if (ibuf == NULL) {
+ continue;
+ }
+ BKE_movieclip_convert_multilayer_ibuf(ibuf);
+
+ result = BKE_movieclip_put_frame_if_possible(clip, &user, ibuf);
+
+ IMB_freeImBuf(ibuf);
+
+ MEM_freeN(mem);
+
+ if (!result) {
+ /* no more space in the cache, stop reading frames */
+ *queue->stop = 1;
+ break;
+ }
+ }
}
-static void start_prefetch_threads(MovieClip *clip, int start_frame, int current_frame, int end_frame,
- short render_size, short render_flag, short *stop, short *do_update,
+static void start_prefetch_threads(MovieClip *clip,
+ int start_frame,
+ int current_frame,
+ int end_frame,
+ short render_size,
+ short render_flag,
+ short *stop,
+ short *do_update,
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);
-
- /* initialize queue */
- BLI_spin_init(&queue.spin);
-
- queue.current_frame = current_frame;
- queue.initial_frame = current_frame;
- queue.start_frame = start_frame;
- queue.end_frame = end_frame;
- queue.render_size = render_size;
- queue.render_flag = render_flag;
- queue.forward = 1;
-
- queue.stop = stop;
- queue.do_update = do_update;
- queue.progress = progress;
-
- task_pool = BLI_task_pool_create(task_scheduler, &queue);
- for (i = 0; i < tot_thread; i++) {
- BLI_task_pool_push(task_pool,
- prefetch_task_func,
- clip,
- false,
- TASK_PRIORITY_LOW);
- }
- BLI_task_pool_work_and_wait(task_pool);
- BLI_task_pool_free(task_pool);
-
- BLI_spin_end(&queue.spin);
+ PrefetchQueue queue;
+ TaskScheduler *task_scheduler = BLI_task_scheduler_get();
+ TaskPool *task_pool;
+ int i, tot_thread = BLI_task_scheduler_num_threads(task_scheduler);
+
+ /* initialize queue */
+ BLI_spin_init(&queue.spin);
+
+ queue.current_frame = current_frame;
+ queue.initial_frame = current_frame;
+ queue.start_frame = start_frame;
+ queue.end_frame = end_frame;
+ queue.render_size = render_size;
+ queue.render_flag = render_flag;
+ queue.forward = 1;
+
+ queue.stop = stop;
+ queue.do_update = do_update;
+ queue.progress = progress;
+
+ task_pool = BLI_task_pool_create(task_scheduler, &queue);
+ for (i = 0; i < tot_thread; i++) {
+ BLI_task_pool_push(task_pool, prefetch_task_func, clip, false, TASK_PRIORITY_LOW);
+ }
+ BLI_task_pool_work_and_wait(task_pool);
+ BLI_task_pool_free(task_pool);
+
+ BLI_spin_end(&queue.spin);
}
-static bool prefetch_movie_frame(MovieClip *clip, int frame, short render_size,
- short render_flag, short *stop)
+static bool prefetch_movie_frame(
+ MovieClip *clip, int frame, short render_size, short render_flag, short *stop)
{
- MovieClipUser user = {0};
- ImBuf *ibuf;
+ MovieClipUser user = {0};
+ ImBuf *ibuf;
- if (check_prefetch_break() || *stop)
- return false;
+ if (check_prefetch_break() || *stop)
+ return false;
- user.framenr = frame;
- user.render_size = render_size;
- user.render_flag = render_flag;
+ user.framenr = frame;
+ user.render_size = render_size;
+ user.render_flag = render_flag;
- if (!BKE_movieclip_has_cached_frame(clip, &user)) {
- ibuf = BKE_movieclip_anim_ibuf_for_frame(clip, &user);
+ if (!BKE_movieclip_has_cached_frame(clip, &user)) {
+ ibuf = BKE_movieclip_anim_ibuf_for_frame(clip, &user);
- if (ibuf) {
- int result;
+ if (ibuf) {
+ int result;
- result = BKE_movieclip_put_frame_if_possible(clip, &user, ibuf);
+ result = BKE_movieclip_put_frame_if_possible(clip, &user, ibuf);
- if (!result) {
- /* no more space in the cache, we could stop prefetching here */
- *stop = 1;
- }
+ if (!result) {
+ /* no more space in the cache, we could stop prefetching here */
+ *stop = 1;
+ }
- IMB_freeImBuf(ibuf);
- }
- else {
- /* error reading frame, fair enough stop attempting further reading */
- *stop = 1;
- }
- }
+ IMB_freeImBuf(ibuf);
+ }
+ else {
+ /* error reading frame, fair enough stop attempting further reading */
+ *stop = 1;
+ }
+ }
- return true;
+ return true;
}
-static void do_prefetch_movie(MovieClip *clip, int start_frame, int current_frame, int end_frame,
- short render_size, short render_flag, short *stop, short *do_update,
+static void do_prefetch_movie(MovieClip *clip,
+ int start_frame,
+ int current_frame,
+ int end_frame,
+ short render_size,
+ short render_flag,
+ short *stop,
+ short *do_update,
float *progress)
{
- int frame;
- int frames_processed = 0;
+ int frame;
+ int frames_processed = 0;
- /* read frames starting from current frame up to scene end frame */
- for (frame = current_frame; frame <= end_frame; frame++) {
- if (!prefetch_movie_frame(clip, frame, render_size, render_flag, stop))
- return;
+ /* read frames starting from current frame up to scene end frame */
+ for (frame = current_frame; frame <= end_frame; frame++) {
+ if (!prefetch_movie_frame(clip, frame, render_size, render_flag, stop))
+ return;
- frames_processed++;
+ frames_processed++;
- *do_update = 1;
- *progress = (float) frames_processed / (end_frame - start_frame);
- }
+ *do_update = 1;
+ *progress = (float)frames_processed / (end_frame - start_frame);
+ }
- /* read frames starting from current frame up to scene start frame */
- for (frame = current_frame; frame >= start_frame; frame--) {
- if (!prefetch_movie_frame(clip, frame, render_size, render_flag, stop))
- return;
+ /* read frames starting from current frame up to scene start frame */
+ for (frame = current_frame; frame >= start_frame; frame--) {
+ if (!prefetch_movie_frame(clip, frame, render_size, render_flag, stop))
+ return;
- frames_processed++;
+ frames_processed++;
- *do_update = 1;
- *progress = (float) frames_processed / (end_frame - start_frame);
- }
+ *do_update = 1;
+ *progress = (float)frames_processed / (end_frame - start_frame);
+ }
}
static void prefetch_startjob(void *pjv, short *stop, short *do_update, float *progress)
{
- PrefetchJob *pj = pjv;
-
- if (pj->clip->source == MCLIP_SRC_SEQUENCE) {
- /* read sequence files in multiple threads */
- start_prefetch_threads(pj->clip, pj->start_frame, pj->current_frame, pj->end_frame,
- pj->render_size, pj->render_flag,
- stop, do_update, progress);
- }
- else if (pj->clip->source == MCLIP_SRC_MOVIE) {
- /* read movie in a single thread */
- do_prefetch_movie(pj->clip, pj->start_frame, pj->current_frame, pj->end_frame,
- pj->render_size, pj->render_flag,
- stop, do_update, progress);
- }
- else {
- BLI_assert(!"Unknown movie clip source when prefetching frames");
- }
+ PrefetchJob *pj = pjv;
+
+ if (pj->clip->source == MCLIP_SRC_SEQUENCE) {
+ /* read sequence files in multiple threads */
+ start_prefetch_threads(pj->clip,
+ pj->start_frame,
+ pj->current_frame,
+ pj->end_frame,
+ pj->render_size,
+ pj->render_flag,
+ stop,
+ do_update,
+ progress);
+ }
+ else if (pj->clip->source == MCLIP_SRC_MOVIE) {
+ /* read movie in a single thread */
+ do_prefetch_movie(pj->clip,
+ pj->start_frame,
+ pj->current_frame,
+ pj->end_frame,
+ pj->render_size,
+ pj->render_flag,
+ stop,
+ do_update,
+ progress);
+ }
+ else {
+ BLI_assert(!"Unknown movie clip source when prefetching frames");
+ }
}
static void prefetch_freejob(void *pjv)
{
- PrefetchJob *pj = pjv;
+ PrefetchJob *pj = pjv;
- MEM_freeN(pj);
+ MEM_freeN(pj);
}
static int prefetch_get_start_frame(const bContext *C)
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- return SFRA;
+ return SFRA;
}
static int prefetch_get_final_frame(const bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- int end_frame;
+ Scene *scene = CTX_data_scene(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ int end_frame;
- /* check whether all the frames from prefetch range are cached */
- end_frame = EFRA;
+ /* check whether all the frames from prefetch range are cached */
+ end_frame = EFRA;
- if (clip->len) {
- end_frame = min_ii(end_frame, SFRA + clip->len - 1);
- }
+ if (clip->len) {
+ end_frame = min_ii(end_frame, SFRA + clip->len - 1);
+ }
- return end_frame;
+ return end_frame;
}
/* returns true if early out is possible */
static bool prefetch_check_early_out(const bContext *C)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- int first_uncached_frame, end_frame;
- int clip_len;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ int first_uncached_frame, end_frame;
+ int clip_len;
- if (clip == NULL) {
- return true;
- }
+ if (clip == NULL) {
+ return true;
+ }
- clip_len = BKE_movieclip_get_duration(clip);
+ clip_len = BKE_movieclip_get_duration(clip);
- /* check whether all the frames from prefetch range are cached */
- end_frame = prefetch_get_final_frame(C);
+ /* check whether all the frames from prefetch range are cached */
+ end_frame = prefetch_get_final_frame(C);
- first_uncached_frame =
- prefetch_find_uncached_frame(clip, sc->user.framenr, end_frame,
- sc->user.render_size, sc->user.render_flag, 1);
+ first_uncached_frame = prefetch_find_uncached_frame(
+ clip, sc->user.framenr, end_frame, sc->user.render_size, sc->user.render_flag, 1);
- if (first_uncached_frame > end_frame || first_uncached_frame == clip_len) {
- int start_frame = prefetch_get_start_frame(C);
+ if (first_uncached_frame > end_frame || first_uncached_frame == clip_len) {
+ int start_frame = prefetch_get_start_frame(C);
- first_uncached_frame =
- prefetch_find_uncached_frame(clip, sc->user.framenr, start_frame,
- sc->user.render_size, sc->user.render_flag, -1);
+ first_uncached_frame = prefetch_find_uncached_frame(
+ clip, sc->user.framenr, start_frame, sc->user.render_size, sc->user.render_flag, -1);
- if (first_uncached_frame < start_frame)
- return true;
- }
+ if (first_uncached_frame < start_frame)
+ return true;
+ }
- return false;
+ return false;
}
void clip_start_prefetch_job(const bContext *C)
{
- wmJob *wm_job;
- PrefetchJob *pj;
- SpaceClip *sc = CTX_wm_space_clip(C);
-
- if (prefetch_check_early_out(C))
- return;
-
- wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), CTX_wm_area(C), "Prefetching",
- WM_JOB_PROGRESS, WM_JOB_TYPE_CLIP_PREFETCH);
-
- /* create new job */
- pj = MEM_callocN(sizeof(PrefetchJob), "prefetch job");
- pj->clip = ED_space_clip_get_clip(sc);
- pj->start_frame = prefetch_get_start_frame(C);
- pj->current_frame = sc->user.framenr;
- pj->end_frame = prefetch_get_final_frame(C);
- pj->render_size = sc->user.render_size;
- pj->render_flag = sc->user.render_flag;
-
- WM_jobs_customdata_set(wm_job, pj, prefetch_freejob);
- WM_jobs_timer(wm_job, 0.2, NC_MOVIECLIP | ND_DISPLAY, 0);
- WM_jobs_callbacks(wm_job, prefetch_startjob, NULL, NULL, NULL);
-
- G.is_break = false;
-
- /* and finally start the job */
- WM_jobs_start(CTX_wm_manager(C), wm_job);
+ wmJob *wm_job;
+ PrefetchJob *pj;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+
+ if (prefetch_check_early_out(C))
+ return;
+
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ CTX_wm_area(C),
+ "Prefetching",
+ WM_JOB_PROGRESS,
+ WM_JOB_TYPE_CLIP_PREFETCH);
+
+ /* create new job */
+ pj = MEM_callocN(sizeof(PrefetchJob), "prefetch job");
+ pj->clip = ED_space_clip_get_clip(sc);
+ pj->start_frame = prefetch_get_start_frame(C);
+ pj->current_frame = sc->user.framenr;
+ pj->end_frame = prefetch_get_final_frame(C);
+ pj->render_size = sc->user.render_size;
+ pj->render_flag = sc->user.render_flag;
+
+ WM_jobs_customdata_set(wm_job, pj, prefetch_freejob);
+ WM_jobs_timer(wm_job, 0.2, NC_MOVIECLIP | ND_DISPLAY, 0);
+ WM_jobs_callbacks(wm_job, prefetch_startjob, NULL, NULL, NULL);
+
+ G.is_break = false;
+
+ /* and finally start the job */
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
}
diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c
index 63d9a45fa2e..c7602907954 100644
--- a/source/blender/editors/space_clip/clip_graph_draw.c
+++ b/source/blender/editors/space_clip/clip_graph_draw.c
@@ -45,301 +45,328 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-
-#include "clip_intern.h" // own include
+#include "clip_intern.h" // own include
typedef struct TrackMotionCurveUserData {
- MovieTrackingTrack *act_track;
- bool sel;
- float xscale, yscale, hsize;
- unsigned int pos;
+ MovieTrackingTrack *act_track;
+ bool sel;
+ float xscale, yscale, hsize;
+ unsigned int pos;
} TrackMotionCurveUserData;
-static void tracking_segment_point_cb(void *userdata, MovieTrackingTrack *UNUSED(track),
- MovieTrackingMarker *UNUSED(marker), int UNUSED(coord),
- int scene_framenr, float val)
+static void tracking_segment_point_cb(void *userdata,
+ MovieTrackingTrack *UNUSED(track),
+ MovieTrackingMarker *UNUSED(marker),
+ int UNUSED(coord),
+ int scene_framenr,
+ float val)
{
- TrackMotionCurveUserData *data = (TrackMotionCurveUserData *) userdata;
+ TrackMotionCurveUserData *data = (TrackMotionCurveUserData *)userdata;
- immVertex2f(data->pos, scene_framenr, val);
+ immVertex2f(data->pos, scene_framenr, val);
}
-static void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord, bool is_point)
+static void tracking_segment_start_cb(void *userdata,
+ MovieTrackingTrack *track,
+ int coord,
+ bool is_point)
{
- TrackMotionCurveUserData *data = (TrackMotionCurveUserData *) userdata;
- float col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
-
- col[coord] = 1.0f;
-
- if (track == data->act_track) {
- col[3] = 1.0f;
- GPU_line_width(2.0f);
- }
- else {
- col[3] = 0.5f;
- GPU_line_width(1.0f);
- }
-
- immUniformColor4fv(col);
-
- if (is_point) {
- immBeginAtMost(GPU_PRIM_POINTS, 1);
- }
- else {
- /* Graph can be composed of smaller segments, if any marker is disabled */
- immBeginAtMost(GPU_PRIM_LINE_STRIP, track->markersnr);
- }
+ TrackMotionCurveUserData *data = (TrackMotionCurveUserData *)userdata;
+ float col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ col[coord] = 1.0f;
+
+ if (track == data->act_track) {
+ col[3] = 1.0f;
+ GPU_line_width(2.0f);
+ }
+ else {
+ col[3] = 0.5f;
+ GPU_line_width(1.0f);
+ }
+
+ immUniformColor4fv(col);
+
+ if (is_point) {
+ immBeginAtMost(GPU_PRIM_POINTS, 1);
+ }
+ else {
+ /* Graph can be composed of smaller segments, if any marker is disabled */
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, track->markersnr);
+ }
}
static void tracking_segment_end_cb(void *UNUSED(userdata), int UNUSED(coord))
{
- immEnd();
+ immEnd();
}
-static void tracking_segment_knot_cb(void *userdata, MovieTrackingTrack *track,
- MovieTrackingMarker *marker, int coord, int scene_framenr, float val)
+static void tracking_segment_knot_cb(void *userdata,
+ MovieTrackingTrack *track,
+ MovieTrackingMarker *marker,
+ int coord,
+ int scene_framenr,
+ float val)
{
- TrackMotionCurveUserData *data = (TrackMotionCurveUserData *) userdata;
- int sel = 0, sel_flag;
+ TrackMotionCurveUserData *data = (TrackMotionCurveUserData *)userdata;
+ int sel = 0, sel_flag;
- if (track != data->act_track)
- return;
+ if (track != data->act_track)
+ return;
- sel_flag = coord == 0 ? MARKER_GRAPH_SEL_X : MARKER_GRAPH_SEL_Y;
- sel = (marker->flag & sel_flag) ? 1 : 0;
+ sel_flag = coord == 0 ? MARKER_GRAPH_SEL_X : MARKER_GRAPH_SEL_Y;
+ sel = (marker->flag & sel_flag) ? 1 : 0;
- if (sel == data->sel) {
- immUniformThemeColor(sel ? TH_HANDLE_VERTEX_SELECT : TH_HANDLE_VERTEX);
+ if (sel == data->sel) {
+ immUniformThemeColor(sel ? TH_HANDLE_VERTEX_SELECT : TH_HANDLE_VERTEX);
- GPU_matrix_push();
- GPU_matrix_translate_2f(scene_framenr, val);
- GPU_matrix_scale_2f(1.0f / data->xscale * data->hsize, 1.0f / data->yscale * data->hsize);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(scene_framenr, val);
+ GPU_matrix_scale_2f(1.0f / data->xscale * data->hsize, 1.0f / data->yscale * data->hsize);
- imm_draw_circle_wire_2d(data->pos, 0, 0, 0.7, 8);
+ imm_draw_circle_wire_2d(data->pos, 0, 0, 0.7, 8);
- GPU_matrix_pop();
- }
+ GPU_matrix_pop();
+ }
}
static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc, unsigned int pos)
{
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- int width, height;
- TrackMotionCurveUserData userdata;
-
- BKE_movieclip_get_size(clip, &sc->user, &width, &height);
-
- if (!width || !height)
- return;
-
- /* non-selected knot handles */
- userdata.hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE);
- userdata.sel = false;
- userdata.act_track = act_track;
- userdata.pos = pos;
- UI_view2d_scale_get(v2d, &userdata.xscale, &userdata.yscale);
- clip_graph_tracking_values_iterate(sc,
- (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
- (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
- &userdata, tracking_segment_knot_cb, NULL, NULL);
- /* draw graph lines */
- GPU_blend(true);
- clip_graph_tracking_values_iterate(sc,
- (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
- (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
- &userdata, tracking_segment_point_cb, tracking_segment_start_cb,
- tracking_segment_end_cb);
- GPU_blend(false);
-
- /* selected knot handles on top of curves */
- userdata.sel = true;
- clip_graph_tracking_values_iterate(sc,
- (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
- (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
- &userdata, tracking_segment_knot_cb, NULL, NULL);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
+ int width, height;
+ TrackMotionCurveUserData userdata;
+
+ BKE_movieclip_get_size(clip, &sc->user, &width, &height);
+
+ if (!width || !height)
+ return;
+
+ /* non-selected knot handles */
+ userdata.hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE);
+ userdata.sel = false;
+ userdata.act_track = act_track;
+ userdata.pos = pos;
+ UI_view2d_scale_get(v2d, &userdata.xscale, &userdata.yscale);
+ clip_graph_tracking_values_iterate(sc,
+ (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
+ (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
+ &userdata,
+ tracking_segment_knot_cb,
+ NULL,
+ NULL);
+ /* draw graph lines */
+ GPU_blend(true);
+ clip_graph_tracking_values_iterate(sc,
+ (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
+ (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
+ &userdata,
+ tracking_segment_point_cb,
+ tracking_segment_start_cb,
+ tracking_segment_end_cb);
+ GPU_blend(false);
+
+ /* selected knot handles on top of curves */
+ userdata.sel = true;
+ clip_graph_tracking_values_iterate(sc,
+ (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
+ (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
+ &userdata,
+ tracking_segment_knot_cb,
+ NULL,
+ NULL);
}
typedef struct TrackErrorCurveUserData {
- MovieClip *clip;
- MovieTracking *tracking;
- MovieTrackingObject *tracking_object;
- MovieTrackingTrack *active_track;
- bool matrix_initialized;
- int matrix_frame;
- float projection_matrix[4][4];
- int width, height;
- float aspy;
- unsigned int pos;
+ MovieClip *clip;
+ MovieTracking *tracking;
+ MovieTrackingObject *tracking_object;
+ MovieTrackingTrack *active_track;
+ bool matrix_initialized;
+ int matrix_frame;
+ float projection_matrix[4][4];
+ int width, height;
+ float aspy;
+ unsigned int pos;
} TrackErrorCurveUserData;
static void tracking_error_segment_point_cb(void *userdata,
- MovieTrackingTrack *track, MovieTrackingMarker *marker,
- int coord, int scene_framenr, float UNUSED(value))
+ MovieTrackingTrack *track,
+ MovieTrackingMarker *marker,
+ int coord,
+ int scene_framenr,
+ float UNUSED(value))
{
- if (coord == 1) {
- TrackErrorCurveUserData *data = (TrackErrorCurveUserData *) userdata;
- float reprojected_position[4], bundle_position[4], marker_position[2], delta[2];
- float reprojection_error;
- float weight = BKE_tracking_track_get_weight_for_marker(data->clip, track, marker);
-
- if (!data->matrix_initialized || data->matrix_frame != scene_framenr) {
- BKE_tracking_get_projection_matrix(data->tracking, data->tracking_object,
- scene_framenr, data->width, data->height,
- data->projection_matrix);
- }
-
- copy_v3_v3(bundle_position, track->bundle_pos);
- bundle_position[3] = 1;
-
- mul_v4_m4v4(reprojected_position, data->projection_matrix, bundle_position);
- reprojected_position[0] = (reprojected_position[0] /
- (reprojected_position[3] * 2.0f) + 0.5f) * data->width;
- reprojected_position[1] = (reprojected_position[1] /
- (reprojected_position[3] * 2.0f) + 0.5f) * data->height * data->aspy;
-
- BKE_tracking_distort_v2(data->tracking, reprojected_position, reprojected_position);
-
- marker_position[0] = (marker->pos[0] + track->offset[0]) * data->width;
- marker_position[1] = (marker->pos[1] + track->offset[1]) * data->height * data->aspy;
-
- sub_v2_v2v2(delta, reprojected_position, marker_position);
- reprojection_error = len_v2(delta) * weight;
-
- immVertex2f(data->pos, scene_framenr, reprojection_error);
- }
+ if (coord == 1) {
+ TrackErrorCurveUserData *data = (TrackErrorCurveUserData *)userdata;
+ float reprojected_position[4], bundle_position[4], marker_position[2], delta[2];
+ float reprojection_error;
+ float weight = BKE_tracking_track_get_weight_for_marker(data->clip, track, marker);
+
+ if (!data->matrix_initialized || data->matrix_frame != scene_framenr) {
+ BKE_tracking_get_projection_matrix(data->tracking,
+ data->tracking_object,
+ scene_framenr,
+ data->width,
+ data->height,
+ data->projection_matrix);
+ }
+
+ copy_v3_v3(bundle_position, track->bundle_pos);
+ bundle_position[3] = 1;
+
+ mul_v4_m4v4(reprojected_position, data->projection_matrix, bundle_position);
+ reprojected_position[0] = (reprojected_position[0] / (reprojected_position[3] * 2.0f) + 0.5f) *
+ data->width;
+ reprojected_position[1] = (reprojected_position[1] / (reprojected_position[3] * 2.0f) + 0.5f) *
+ data->height * data->aspy;
+
+ BKE_tracking_distort_v2(data->tracking, reprojected_position, reprojected_position);
+
+ marker_position[0] = (marker->pos[0] + track->offset[0]) * data->width;
+ marker_position[1] = (marker->pos[1] + track->offset[1]) * data->height * data->aspy;
+
+ sub_v2_v2v2(delta, reprojected_position, marker_position);
+ reprojection_error = len_v2(delta) * weight;
+
+ immVertex2f(data->pos, scene_framenr, reprojection_error);
+ }
}
-static void tracking_error_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord, bool is_point)
+static void tracking_error_segment_start_cb(void *userdata,
+ MovieTrackingTrack *track,
+ int coord,
+ bool is_point)
{
- if (coord == 1) {
- TrackErrorCurveUserData *data = (TrackErrorCurveUserData *) userdata;
- float col[4] = {0.0f, 0.0f, 1.0f, 1.0f};
-
- if (track == data->active_track) {
- col[3] = 1.0f;
- GPU_line_width(2.0f);
- }
- else {
- col[3] = 0.5f;
- GPU_line_width(1.0f);
- }
-
- immUniformColor4fv(col);
-
- if (is_point) { /* This probably never happens here, but just in case... */
- immBeginAtMost(GPU_PRIM_POINTS, 1);
- }
- else {
- /* Graph can be composed of smaller segments, if any marker is disabled */
- immBeginAtMost(GPU_PRIM_LINE_STRIP, track->markersnr);
- }
- }
+ if (coord == 1) {
+ TrackErrorCurveUserData *data = (TrackErrorCurveUserData *)userdata;
+ float col[4] = {0.0f, 0.0f, 1.0f, 1.0f};
+
+ if (track == data->active_track) {
+ col[3] = 1.0f;
+ GPU_line_width(2.0f);
+ }
+ else {
+ col[3] = 0.5f;
+ GPU_line_width(1.0f);
+ }
+
+ immUniformColor4fv(col);
+
+ if (is_point) { /* This probably never happens here, but just in case... */
+ immBeginAtMost(GPU_PRIM_POINTS, 1);
+ }
+ else {
+ /* Graph can be composed of smaller segments, if any marker is disabled */
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, track->markersnr);
+ }
+ }
}
static void tracking_error_segment_end_cb(void *UNUSED(userdata), int coord)
{
- if (coord == 1) {
- immEnd();
- }
+ if (coord == 1) {
+ immEnd();
+ }
}
static void draw_tracks_error_curves(SpaceClip *sc, unsigned int pos)
{
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- TrackErrorCurveUserData data;
-
- data.clip = clip;
- data.tracking = tracking;
- data.tracking_object = BKE_tracking_object_get_active(tracking);
- data.active_track = BKE_tracking_track_get_active(tracking);
- data.matrix_initialized = false;
- data.pos = pos;
- BKE_movieclip_get_size(clip, &sc->user, &data.width, &data.height);
- data.aspy = 1.0f / tracking->camera.pixel_aspect;
-
- if (!data.width || !data.height) {
- return;
- }
-
- clip_graph_tracking_values_iterate(sc,
- (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
- (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
- &data,
- tracking_error_segment_point_cb,
- tracking_error_segment_start_cb,
- tracking_error_segment_end_cb);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ TrackErrorCurveUserData data;
+
+ data.clip = clip;
+ data.tracking = tracking;
+ data.tracking_object = BKE_tracking_object_get_active(tracking);
+ data.active_track = BKE_tracking_track_get_active(tracking);
+ data.matrix_initialized = false;
+ data.pos = pos;
+ BKE_movieclip_get_size(clip, &sc->user, &data.width, &data.height);
+ data.aspy = 1.0f / tracking->camera.pixel_aspect;
+
+ if (!data.width || !data.height) {
+ return;
+ }
+
+ clip_graph_tracking_values_iterate(sc,
+ (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
+ (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
+ &data,
+ tracking_error_segment_point_cb,
+ tracking_error_segment_start_cb,
+ tracking_error_segment_end_cb);
}
static void draw_frame_curves(SpaceClip *sc, unsigned int 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;
+ 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;
- immUniformColor3f(0.0f, 0.0f, 1.0f);
+ immUniformColor3f(0.0f, 0.0f, 1.0f);
- for (i = 0; i < reconstruction->camnr; i++) {
- MovieReconstructedCamera *camera = &reconstruction->cameras[i];
- int framenr;
+ for (i = 0; i < reconstruction->camnr; i++) {
+ MovieReconstructedCamera *camera = &reconstruction->cameras[i];
+ int framenr;
- if (lines && camera->framenr != prevfra + 1) {
- immEnd();
- lines = 0;
- }
+ if (lines && camera->framenr != prevfra + 1) {
+ immEnd();
+ lines = 0;
+ }
- if (!lines) {
- immBeginAtMost(GPU_PRIM_LINE_STRIP, reconstruction->camnr);
- lines = 1;
- }
+ if (!lines) {
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, reconstruction->camnr);
+ lines = 1;
+ }
- framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, camera->framenr);
- immVertex2f(pos, framenr, camera->error);
+ framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, camera->framenr);
+ immVertex2f(pos, framenr, camera->error);
- prevfra = camera->framenr;
- }
+ prevfra = camera->framenr;
+ }
- if (lines) {
- immEnd();
- }
+ if (lines) {
+ immEnd();
+ }
}
void clip_draw_graph(SpaceClip *sc, ARegion *ar, Scene *scene)
{
- MovieClip *clip = ED_space_clip_get_clip(sc);
- View2D *v2d = &ar->v2d;
- View2DGrid *grid;
- short unitx = V2D_UNIT_FRAMESCALE, unity = V2D_UNIT_VALUES;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ View2D *v2d = &ar->v2d;
+ View2DGrid *grid;
+ short unitx = V2D_UNIT_FRAMESCALE, unity = V2D_UNIT_VALUES;
- /* grid */
- grid = UI_view2d_grid_calc(scene, v2d, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP, ar->winx, ar->winy);
- UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL);
- UI_view2d_grid_free(grid);
+ /* grid */
+ grid = UI_view2d_grid_calc(
+ scene, v2d, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP, ar->winx, ar->winy);
+ UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL);
+ UI_view2d_grid_free(grid);
- if (clip) {
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ if (clip) {
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- GPU_point_size(3.0f);
+ GPU_point_size(3.0f);
- if (sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) {
- draw_tracks_motion_curves(v2d, sc, pos);
- }
+ if (sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) {
+ draw_tracks_motion_curves(v2d, sc, pos);
+ }
- if (sc->flag & SC_SHOW_GRAPH_TRACKS_ERROR) {
- draw_tracks_error_curves(sc, pos);
- }
+ if (sc->flag & SC_SHOW_GRAPH_TRACKS_ERROR) {
+ draw_tracks_error_curves(sc, pos);
+ }
- if (sc->flag & SC_SHOW_GRAPH_FRAMES) {
- draw_frame_curves(sc, pos);
- }
+ if (sc->flag & SC_SHOW_GRAPH_FRAMES) {
+ draw_frame_curves(sc, pos);
+ }
- immUnbindProgram();
- }
+ immUnbindProgram();
+ }
- /* frame range */
- clip_draw_sfra_efra(v2d, scene);
+ /* frame range */
+ clip_draw_sfra_efra(v2d, scene);
}
diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c
index 8a8cb4b8dcb..7a61aced8b5 100644
--- a/source/blender/editors/space_clip/clip_graph_ops.c
+++ b/source/blender/editors/space_clip/clip_graph_ops.c
@@ -44,676 +44,706 @@
#include "UI_view2d.h"
-#include "clip_intern.h" // own include
+#include "clip_intern.h" // own include
/******************** common graph-editing utilities ********************/
static bool ED_space_clip_graph_poll(bContext *C)
{
- if (ED_space_clip_tracking_poll(C)) {
- SpaceClip *sc = CTX_wm_space_clip(C);
+ if (ED_space_clip_tracking_poll(C)) {
+ SpaceClip *sc = CTX_wm_space_clip(C);
- return sc->view == SC_VIEW_GRAPH;
- }
+ return sc->view == SC_VIEW_GRAPH;
+ }
- return false;
+ return false;
}
static bool clip_graph_knots_poll(bContext *C)
{
- if (ED_space_clip_graph_poll(C)) {
- SpaceClip *sc = CTX_wm_space_clip(C);
+ if (ED_space_clip_graph_poll(C)) {
+ SpaceClip *sc = CTX_wm_space_clip(C);
- return (sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) != 0;
- }
- return false;
+ return (sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) != 0;
+ }
+ return false;
}
typedef struct {
- int action;
+ int action;
} SelectUserData;
static void toggle_selection_cb(void *userdata, MovieTrackingMarker *marker)
{
- SelectUserData *data = (SelectUserData *)userdata;
-
- switch (data->action) {
- case SEL_SELECT:
- marker->flag |= MARKER_GRAPH_SEL;
- break;
- case SEL_DESELECT:
- marker->flag &= ~MARKER_GRAPH_SEL;
- break;
- case SEL_INVERT:
- marker->flag ^= MARKER_GRAPH_SEL;
- break;
- }
+ SelectUserData *data = (SelectUserData *)userdata;
+
+ switch (data->action) {
+ case SEL_SELECT:
+ marker->flag |= MARKER_GRAPH_SEL;
+ break;
+ case SEL_DESELECT:
+ marker->flag &= ~MARKER_GRAPH_SEL;
+ break;
+ case SEL_INVERT:
+ marker->flag ^= MARKER_GRAPH_SEL;
+ break;
+ }
}
/******************** mouse select operator ********************/
typedef struct {
- int coord; /* coordinate index of found entuty (0 = X-axis, 1 = Y-axis) */
- bool has_prev; /* if there's valid coordinate of previous point of curve segment */
+ int coord; /* coordinate index of found entuty (0 = X-axis, 1 = Y-axis) */
+ bool has_prev; /* if there's valid coordinate of previous point of curve segment */
- float min_dist_sq, /* minimal distance between mouse and currently found entity */
- mouse_co[2], /* mouse coordinate */
- prev_co[2], /* coordinate of previeous point of segment */
- min_co[2]; /* coordinate of entity with minimal distance */
+ float min_dist_sq, /* minimal distance between mouse and currently found entity */
+ mouse_co[2], /* mouse coordinate */
+ prev_co[2], /* coordinate of previeous point of segment */
+ min_co[2]; /* coordinate of entity with minimal distance */
- MovieTrackingTrack *track; /* nearest found track */
- MovieTrackingMarker *marker; /* nearest found marker */
+ MovieTrackingTrack *track; /* nearest found track */
+ MovieTrackingMarker *marker; /* nearest found marker */
} MouseSelectUserData;
-static void find_nearest_tracking_segment_cb(void *userdata, MovieTrackingTrack *track,
+static void find_nearest_tracking_segment_cb(void *userdata,
+ MovieTrackingTrack *track,
MovieTrackingMarker *UNUSED(marker),
- int coord, int scene_framenr, float val)
+ int coord,
+ int scene_framenr,
+ float val)
{
- MouseSelectUserData *data = userdata;
- float co[2] = {scene_framenr, val};
-
- if (data->has_prev) {
- float dist_sq = dist_squared_to_line_segment_v2(data->mouse_co, data->prev_co, co);
-
- if (data->track == NULL || dist_sq < data->min_dist_sq) {
- data->track = track;
- data->min_dist_sq = dist_sq;
- data->coord = coord;
- copy_v2_v2(data->min_co, co);
- }
- }
-
- data->has_prev = true;
- copy_v2_v2(data->prev_co, co);
+ MouseSelectUserData *data = userdata;
+ float co[2] = {scene_framenr, val};
+
+ if (data->has_prev) {
+ float dist_sq = dist_squared_to_line_segment_v2(data->mouse_co, data->prev_co, co);
+
+ if (data->track == NULL || dist_sq < data->min_dist_sq) {
+ data->track = track;
+ data->min_dist_sq = dist_sq;
+ data->coord = coord;
+ copy_v2_v2(data->min_co, co);
+ }
+ }
+
+ data->has_prev = true;
+ copy_v2_v2(data->prev_co, co);
}
static void find_nearest_tracking_segment_end_cb(void *userdata, int UNUSED(coord))
{
- MouseSelectUserData *data = userdata;
+ MouseSelectUserData *data = userdata;
- data->has_prev = false;
+ data->has_prev = false;
}
-static void find_nearest_tracking_knot_cb(void *userdata, MovieTrackingTrack *track,
- MovieTrackingMarker *marker, int coord, int scene_framenr, float val)
+static void find_nearest_tracking_knot_cb(void *userdata,
+ MovieTrackingTrack *track,
+ MovieTrackingMarker *marker,
+ int coord,
+ int scene_framenr,
+ float val)
{
- MouseSelectUserData *data = userdata;
- float mdiff[2] = {scene_framenr - data->mouse_co[0], val - data->mouse_co[1]};
- float dist_sq = len_squared_v2(mdiff);
-
- if (data->marker == NULL || dist_sq < data->min_dist_sq) {
- float co[2] = {scene_framenr, val};
-
- data->track = track;
- data->marker = marker;
- data->min_dist_sq = dist_sq;
- data->coord = coord;
- copy_v2_v2(data->min_co, co);
- }
-
+ MouseSelectUserData *data = userdata;
+ float mdiff[2] = {scene_framenr - data->mouse_co[0], val - data->mouse_co[1]};
+ float dist_sq = len_squared_v2(mdiff);
+
+ if (data->marker == NULL || dist_sq < data->min_dist_sq) {
+ float co[2] = {scene_framenr, val};
+
+ data->track = track;
+ data->marker = marker;
+ data->min_dist_sq = dist_sq;
+ data->coord = coord;
+ copy_v2_v2(data->min_co, co);
+ }
}
static void mouse_select_init_data(MouseSelectUserData *userdata, const float co[2])
{
- memset(userdata, 0, sizeof(MouseSelectUserData));
- userdata->min_dist_sq = FLT_MAX;
- copy_v2_v2(userdata->mouse_co, co);
+ memset(userdata, 0, sizeof(MouseSelectUserData));
+ userdata->min_dist_sq = FLT_MAX;
+ copy_v2_v2(userdata->mouse_co, co);
}
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;
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- static const int delta = 6;
-
- if (act_track) {
- MouseSelectUserData userdata;
-
- mouse_select_init_data(&userdata, co);
- clip_graph_tracking_values_iterate_track(sc, act_track, &userdata,
- find_nearest_tracking_knot_cb, NULL, NULL);
-
- if (userdata.marker) {
- int x1, y1, x2, y2;
-
- if (UI_view2d_view_to_region_clip(v2d, co[0], co[1], &x1, &y1) &&
- UI_view2d_view_to_region_clip(v2d, userdata.min_co[0], userdata.min_co[1], &x2, &y2) &&
- (abs(x2 - x1) <= delta && abs(y2 - y1) <= delta))
- {
- if (!extend) {
- SelectUserData selectdata = {SEL_DESELECT};
-
- clip_graph_tracking_iterate(sc,
- (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
- (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
- &selectdata,
- toggle_selection_cb);
- }
-
- if (userdata.coord == 0) {
- if (extend && (userdata.marker->flag & MARKER_GRAPH_SEL_X) != 0)
- userdata.marker->flag &= ~MARKER_GRAPH_SEL_X;
- else
- userdata.marker->flag |= MARKER_GRAPH_SEL_X;
- }
- else {
- if (extend && (userdata.marker->flag & MARKER_GRAPH_SEL_Y) != 0)
- userdata.marker->flag &= ~MARKER_GRAPH_SEL_Y;
- else
- userdata.marker->flag |= MARKER_GRAPH_SEL_Y;
- }
-
- return true;
- }
- }
- }
-
- return false;
+ 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;
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
+ static const int delta = 6;
+
+ if (act_track) {
+ MouseSelectUserData userdata;
+
+ mouse_select_init_data(&userdata, co);
+ clip_graph_tracking_values_iterate_track(
+ sc, act_track, &userdata, find_nearest_tracking_knot_cb, NULL, NULL);
+
+ if (userdata.marker) {
+ int x1, y1, x2, y2;
+
+ if (UI_view2d_view_to_region_clip(v2d, co[0], co[1], &x1, &y1) &&
+ UI_view2d_view_to_region_clip(v2d, userdata.min_co[0], userdata.min_co[1], &x2, &y2) &&
+ (abs(x2 - x1) <= delta && abs(y2 - y1) <= delta)) {
+ if (!extend) {
+ SelectUserData selectdata = {SEL_DESELECT};
+
+ clip_graph_tracking_iterate(sc,
+ (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
+ (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
+ &selectdata,
+ toggle_selection_cb);
+ }
+
+ if (userdata.coord == 0) {
+ if (extend && (userdata.marker->flag & MARKER_GRAPH_SEL_X) != 0)
+ userdata.marker->flag &= ~MARKER_GRAPH_SEL_X;
+ else
+ userdata.marker->flag |= MARKER_GRAPH_SEL_X;
+ }
+ else {
+ if (extend && (userdata.marker->flag & MARKER_GRAPH_SEL_Y) != 0)
+ userdata.marker->flag &= ~MARKER_GRAPH_SEL_Y;
+ else
+ userdata.marker->flag |= MARKER_GRAPH_SEL_Y;
+ }
+
+ return true;
+ }
+ }
+ }
+
+ return false;
}
static bool mouse_select_curve(bContext *C, float co[2], bool extend)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- MouseSelectUserData userdata;
-
- mouse_select_init_data(&userdata, co);
- clip_graph_tracking_values_iterate(sc,
- (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
- (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
- &userdata, find_nearest_tracking_segment_cb,
- NULL, find_nearest_tracking_segment_end_cb);
-
- if (userdata.track) {
- if (extend) {
- if (act_track == userdata.track) {
- /* currently only single curve can be selected
- * (selected curve represents active track) */
- act_track = NULL;
- }
- }
- else if (act_track != userdata.track) {
- SelectUserData selectdata = {SEL_DESELECT};
- MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
-
- tracking->act_track = userdata.track;
- if ((sc->flag & SC_SHOW_GRAPH_SEL_ONLY) == 0) {
- ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
- BKE_tracking_track_select(tracksbase, userdata.track, TRACK_AREA_ALL, false);
- }
-
- /* deselect all knots on newly selected curve */
- clip_graph_tracking_iterate(sc,
- (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
- (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
- &selectdata, toggle_selection_cb);
- }
-
- return true;
- }
-
- return false;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
+ MouseSelectUserData userdata;
+
+ mouse_select_init_data(&userdata, co);
+ clip_graph_tracking_values_iterate(sc,
+ (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
+ (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
+ &userdata,
+ find_nearest_tracking_segment_cb,
+ NULL,
+ find_nearest_tracking_segment_end_cb);
+
+ if (userdata.track) {
+ if (extend) {
+ if (act_track == userdata.track) {
+ /* currently only single curve can be selected
+ * (selected curve represents active track) */
+ act_track = NULL;
+ }
+ }
+ else if (act_track != userdata.track) {
+ SelectUserData selectdata = {SEL_DESELECT};
+ MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
+
+ tracking->act_track = userdata.track;
+ if ((sc->flag & SC_SHOW_GRAPH_SEL_ONLY) == 0) {
+ ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
+ BKE_tracking_track_select(tracksbase, userdata.track, TRACK_AREA_ALL, false);
+ }
+
+ /* deselect all knots on newly selected curve */
+ clip_graph_tracking_iterate(sc,
+ (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
+ (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
+ &selectdata,
+ toggle_selection_cb);
+ }
+
+ return true;
+ }
+
+ return false;
}
static int mouse_select(bContext *C, float co[2], bool extend)
{
- bool sel = false;
+ bool sel = false;
- /* first try to select knot on selected curves */
- sel = mouse_select_knot(C, co, extend);
+ /* first try to select knot on selected curves */
+ sel = mouse_select_knot(C, co, extend);
- if (!sel) {
- /* if there's no close enough knot to mouse osition, select nearest curve */
- sel = mouse_select_curve(C, co, extend);
- }
+ if (!sel) {
+ /* if there's no close enough knot to mouse osition, select nearest curve */
+ sel = mouse_select_curve(C, co, extend);
+ }
- if (sel)
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+ if (sel)
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int select_exec(bContext *C, wmOperator *op)
{
- float co[2];
- bool extend = RNA_boolean_get(op->ptr, "extend");
+ float co[2];
+ bool extend = RNA_boolean_get(op->ptr, "extend");
- RNA_float_get_array(op->ptr, "location", co);
+ RNA_float_get_array(op->ptr, "location", co);
- return mouse_select(C, co, extend);
+ return mouse_select(C, co, extend);
}
static int select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- float co[2];
+ 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);
+ 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 select_exec(C, op);
+ return select_exec(C, op);
}
void CLIP_OT_graph_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select";
- ot->description = "Select graph curves";
- ot->idname = "CLIP_OT_graph_select";
-
- /* api callbacks */
- ot->exec = select_exec;
- ot->invoke = select_invoke;
- ot->poll = clip_graph_knots_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
- "Location", "Mouse location to select nearest entity", -100.0f, 100.0f);
- RNA_def_boolean(ot->srna, "extend", 0,
- "Extend", "Extend selection rather than clearing the existing selection");
+ /* identifiers */
+ ot->name = "Select";
+ ot->description = "Select graph curves";
+ ot->idname = "CLIP_OT_graph_select";
+
+ /* api callbacks */
+ ot->exec = select_exec;
+ ot->invoke = select_invoke;
+ ot->poll = clip_graph_knots_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float_vector(ot->srna,
+ "location",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Location",
+ "Mouse location to select nearest entity",
+ -100.0f,
+ 100.0f);
+ RNA_def_boolean(ot->srna,
+ "extend",
+ 0,
+ "Extend",
+ "Extend selection rather than clearing the existing selection");
}
/********************** box select operator *********************/
typedef struct BoxSelectuserData {
- rctf rect;
- bool select, extend, changed;
+ rctf rect;
+ bool select, extend, changed;
} BoxSelectuserData;
-static void box_select_cb(void *userdata, MovieTrackingTrack *UNUSED(track),
- MovieTrackingMarker *marker, int coord, int scene_framenr, float val)
+static void box_select_cb(void *userdata,
+ MovieTrackingTrack *UNUSED(track),
+ MovieTrackingMarker *marker,
+ int coord,
+ int scene_framenr,
+ float val)
{
- BoxSelectuserData *data = (BoxSelectuserData *) userdata;
-
- if (BLI_rctf_isect_pt(&data->rect, scene_framenr, val)) {
- int flag = 0;
-
- if (coord == 0)
- flag = MARKER_GRAPH_SEL_X;
- else
- flag = MARKER_GRAPH_SEL_Y;
-
- if (data->select) {
- marker->flag |= flag;
- }
- else {
- marker->flag &= ~flag;
- }
- data->changed = true;
- }
- else if (!data->extend) {
- marker->flag &= ~MARKER_GRAPH_SEL;
- }
+ BoxSelectuserData *data = (BoxSelectuserData *)userdata;
+
+ if (BLI_rctf_isect_pt(&data->rect, scene_framenr, val)) {
+ int flag = 0;
+
+ if (coord == 0)
+ flag = MARKER_GRAPH_SEL_X;
+ else
+ flag = MARKER_GRAPH_SEL_Y;
+
+ if (data->select) {
+ marker->flag |= flag;
+ }
+ else {
+ marker->flag &= ~flag;
+ }
+ data->changed = true;
+ }
+ else if (!data->extend) {
+ marker->flag &= ~MARKER_GRAPH_SEL;
+ }
}
static int box_select_graph_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- BoxSelectuserData userdata;
- rctf rect;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
+ BoxSelectuserData userdata;
+ rctf rect;
- if (act_track == NULL) {
- return OPERATOR_CANCELLED;
- }
+ if (act_track == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- /* get rectangle from operator */
- WM_operator_properties_border_to_rctf(op, &rect);
- UI_view2d_region_to_view_rctf(&ar->v2d, &rect, &userdata.rect);
+ /* get rectangle from operator */
+ WM_operator_properties_border_to_rctf(op, &rect);
+ UI_view2d_region_to_view_rctf(&ar->v2d, &rect, &userdata.rect);
- userdata.changed = false;
- userdata.select = !RNA_boolean_get(op->ptr, "deselect");
- userdata.extend = RNA_boolean_get(op->ptr, "extend");
+ userdata.changed = false;
+ userdata.select = !RNA_boolean_get(op->ptr, "deselect");
+ userdata.extend = RNA_boolean_get(op->ptr, "extend");
- clip_graph_tracking_values_iterate_track(sc, act_track, &userdata, box_select_cb, NULL, NULL);
+ clip_graph_tracking_values_iterate_track(sc, act_track, &userdata, box_select_cb, NULL, NULL);
- if (userdata.changed) {
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+ if (userdata.changed) {
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
void CLIP_OT_graph_select_box(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Box Select";
- ot->description = "Select curve points using box selection";
- ot->idname = "CLIP_OT_graph_select_box";
-
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = box_select_graph_exec;
- ot->modal = WM_gesture_box_modal;
- ot->poll = clip_graph_knots_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_gesture_box_select(ot);
+ /* identifiers */
+ ot->name = "Box Select";
+ ot->description = "Select curve points using box selection";
+ ot->idname = "CLIP_OT_graph_select_box";
+
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = box_select_graph_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->poll = clip_graph_knots_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_gesture_box_select(ot);
}
/********************** select all operator *********************/
static int graph_select_all_markers_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- MovieTrackingMarker *marker;
- int action = RNA_enum_get(op->ptr, "action");
- int a;
-
- if (!act_track)
- return OPERATOR_CANCELLED;
-
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
-
- for (a = 0; a < act_track->markersnr; a++) {
- marker = &act_track->markers[a];
-
- if (marker->flag & MARKER_GRAPH_SEL) {
- action = SEL_DESELECT;
- break;
- }
- }
- }
-
- for (a = 0; a < act_track->markersnr; a++) {
- marker = &act_track->markers[a];
-
- switch (action) {
- case SEL_SELECT:
- marker->flag |= MARKER_GRAPH_SEL;
- break;
- case SEL_DESELECT:
- marker->flag &= ~MARKER_GRAPH_SEL;
- break;
- case SEL_INVERT:
- marker->flag ^= MARKER_GRAPH_SEL;
- break;
- }
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
+ MovieTrackingMarker *marker;
+ int action = RNA_enum_get(op->ptr, "action");
+ int a;
+
+ if (!act_track)
+ return OPERATOR_CANCELLED;
+
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+
+ for (a = 0; a < act_track->markersnr; a++) {
+ marker = &act_track->markers[a];
+
+ if (marker->flag & MARKER_GRAPH_SEL) {
+ action = SEL_DESELECT;
+ break;
+ }
+ }
+ }
+
+ for (a = 0; a < act_track->markersnr; a++) {
+ marker = &act_track->markers[a];
+
+ switch (action) {
+ case SEL_SELECT:
+ marker->flag |= MARKER_GRAPH_SEL;
+ break;
+ case SEL_DESELECT:
+ marker->flag &= ~MARKER_GRAPH_SEL;
+ break;
+ case SEL_INVERT:
+ marker->flag ^= MARKER_GRAPH_SEL;
+ break;
+ }
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_graph_select_all_markers(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All Markers";
- ot->description = "Change selection of all markers of active track";
- ot->idname = "CLIP_OT_graph_select_all_markers";
+ /* identifiers */
+ ot->name = "(De)select All Markers";
+ ot->description = "Change selection of all markers of active track";
+ ot->idname = "CLIP_OT_graph_select_all_markers";
- /* api callbacks */
- ot->exec = graph_select_all_markers_exec;
- ot->poll = clip_graph_knots_poll;
+ /* api callbacks */
+ ot->exec = graph_select_all_markers_exec;
+ ot->poll = clip_graph_knots_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_select_all(ot);
+ WM_operator_properties_select_all(ot);
}
/******************** delete curve operator ********************/
static int delete_curve_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- if (!act_track)
- return OPERATOR_CANCELLED;
+ if (!act_track)
+ return OPERATOR_CANCELLED;
- clip_delete_track(C, clip, act_track);
+ clip_delete_track(C, clip, act_track);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_graph_delete_curve(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Curve";
- ot->description = "Delete track corresponding to the selected curve";
- ot->idname = "CLIP_OT_graph_delete_curve";
-
- /* api callbacks */
- ot->invoke = WM_operator_confirm;
- ot->exec = delete_curve_exec;
- ot->poll = clip_graph_knots_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Delete Curve";
+ ot->description = "Delete track corresponding to the selected curve";
+ ot->idname = "CLIP_OT_graph_delete_curve";
+
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = delete_curve_exec;
+ ot->poll = clip_graph_knots_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************** delete knot operator ********************/
static int delete_knot_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- if (act_track) {
- int a = 0;
+ if (act_track) {
+ int a = 0;
- while (a < act_track->markersnr) {
- MovieTrackingMarker *marker = &act_track->markers[a];
+ while (a < act_track->markersnr) {
+ MovieTrackingMarker *marker = &act_track->markers[a];
- if (marker->flag & MARKER_GRAPH_SEL)
- clip_delete_marker(C, clip, act_track, marker);
- else
- a++;
- }
- }
+ if (marker->flag & MARKER_GRAPH_SEL)
+ clip_delete_marker(C, clip, act_track, marker);
+ else
+ a++;
+ }
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_graph_delete_knot(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Knot";
- ot->description = "Delete curve knots";
- ot->idname = "CLIP_OT_graph_delete_knot";
+ /* identifiers */
+ ot->name = "Delete Knot";
+ ot->description = "Delete curve knots";
+ ot->idname = "CLIP_OT_graph_delete_knot";
- /* api callbacks */
- ot->exec = delete_knot_exec;
- ot->poll = clip_graph_knots_poll;
+ /* api callbacks */
+ ot->exec = delete_knot_exec;
+ ot->poll = clip_graph_knots_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************** view all operator ********************/
typedef struct {
- float min, max;
+ float min, max;
} ViewAllUserData;
-static void view_all_cb(void *userdata, MovieTrackingTrack *UNUSED(track), MovieTrackingMarker *UNUSED(marker),
- int UNUSED(coord), int UNUSED(scene_framenr), float val)
+static void view_all_cb(void *userdata,
+ MovieTrackingTrack *UNUSED(track),
+ MovieTrackingMarker *UNUSED(marker),
+ int UNUSED(coord),
+ int UNUSED(scene_framenr),
+ float val)
{
- ViewAllUserData *data = (ViewAllUserData *) userdata;
+ ViewAllUserData *data = (ViewAllUserData *)userdata;
- if (val < data->min)
- data->min = val;
+ if (val < data->min)
+ data->min = val;
- if (val > data->max)
- data->max = val;
+ if (val > data->max)
+ data->max = val;
}
static int view_all_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
- SpaceClip *sc = CTX_wm_space_clip(C);
- View2D *v2d = &ar->v2d;
- ViewAllUserData userdata;
- float extra;
-
- userdata.max = -FLT_MAX;
- userdata.min = FLT_MAX;
-
- clip_graph_tracking_values_iterate(sc,
- (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
- (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
- &userdata, view_all_cb, NULL, NULL);
-
- /* set extents of view to start/end frames */
- v2d->cur.xmin = (float) SFRA;
- v2d->cur.xmax = (float) EFRA;
-
- if (userdata.min < userdata.max) {
- v2d->cur.ymin = userdata.min;
- v2d->cur.ymax = userdata.max;
- }
- else {
- v2d->cur.ymin = -10;
- v2d->cur.ymax = 10;
- }
-
- /* we need an extra "buffer" factor on either side so that the endpoints are visible */
- extra = 0.01f * BLI_rctf_size_x(&v2d->cur);
- v2d->cur.xmin -= extra;
- v2d->cur.xmax += extra;
-
- extra = 0.01f * BLI_rctf_size_y(&v2d->cur);
- v2d->cur.ymin -= extra;
- v2d->cur.ymax += extra;
-
- ED_region_tag_redraw(ar);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ ARegion *ar = CTX_wm_region(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ View2D *v2d = &ar->v2d;
+ ViewAllUserData userdata;
+ float extra;
+
+ userdata.max = -FLT_MAX;
+ userdata.min = FLT_MAX;
+
+ clip_graph_tracking_values_iterate(sc,
+ (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
+ (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
+ &userdata,
+ view_all_cb,
+ NULL,
+ NULL);
+
+ /* set extents of view to start/end frames */
+ v2d->cur.xmin = (float)SFRA;
+ v2d->cur.xmax = (float)EFRA;
+
+ if (userdata.min < userdata.max) {
+ v2d->cur.ymin = userdata.min;
+ v2d->cur.ymax = userdata.max;
+ }
+ else {
+ v2d->cur.ymin = -10;
+ v2d->cur.ymax = 10;
+ }
+
+ /* we need an extra "buffer" factor on either side so that the endpoints are visible */
+ extra = 0.01f * BLI_rctf_size_x(&v2d->cur);
+ v2d->cur.xmin -= extra;
+ v2d->cur.xmax += extra;
+
+ extra = 0.01f * BLI_rctf_size_y(&v2d->cur);
+ v2d->cur.ymin -= extra;
+ v2d->cur.ymax += extra;
+
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_graph_view_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View All";
- ot->description = "View all curves in editor";
- ot->idname = "CLIP_OT_graph_view_all";
-
- /* api callbacks */
- ot->exec = view_all_exec;
- ot->poll = ED_space_clip_graph_poll;
+ /* identifiers */
+ ot->name = "View All";
+ ot->description = "View all curves in editor";
+ ot->idname = "CLIP_OT_graph_view_all";
+
+ /* api callbacks */
+ ot->exec = view_all_exec;
+ ot->poll = ED_space_clip_graph_poll;
}
/******************** jump to current frame operator ********************/
void ED_clip_graph_center_current_frame(Scene *scene, ARegion *ar)
{
- View2D *v2d = &ar->v2d;
- float extra = BLI_rctf_size_x(&v2d->cur) / 2.0f;
+ View2D *v2d = &ar->v2d;
+ float extra = BLI_rctf_size_x(&v2d->cur) / 2.0f;
- /* set extents of view to start/end frames */
- v2d->cur.xmin = (float)CFRA - extra;
- v2d->cur.xmax = (float)CFRA + extra;
+ /* set extents of view to start/end frames */
+ v2d->cur.xmin = (float)CFRA - extra;
+ v2d->cur.xmax = (float)CFRA + extra;
}
static int center_current_frame_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+ ARegion *ar = CTX_wm_region(C);
- ED_clip_graph_center_current_frame(scene, ar);
+ ED_clip_graph_center_current_frame(scene, ar);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_graph_center_current_frame(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Center Current Frame";
- ot->description = "Scroll view so current frame would be centered";
- ot->idname = "CLIP_OT_graph_center_current_frame";
-
- /* api callbacks */
- ot->exec = center_current_frame_exec;
- ot->poll = ED_space_clip_graph_poll;
+ /* identifiers */
+ ot->name = "Center Current Frame";
+ ot->description = "Scroll view so current frame would be centered";
+ ot->idname = "CLIP_OT_graph_center_current_frame";
+
+ /* api callbacks */
+ ot->exec = center_current_frame_exec;
+ ot->poll = ED_space_clip_graph_poll;
}
/********************** disable markers operator *********************/
static int graph_disable_markers_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- MovieTrackingMarker *marker;
- int action = RNA_enum_get(op->ptr, "action");
- int a;
-
- if (!act_track || (act_track->flag & TRACK_LOCKED))
- return OPERATOR_CANCELLED;
-
- for (a = 0; a < act_track->markersnr; a++) {
- marker = &act_track->markers[a];
-
- if (marker->flag & MARKER_GRAPH_SEL) {
- if (action == 0)
- marker->flag |= MARKER_DISABLED;
- else if (action == 1)
- marker->flag &= ~MARKER_DISABLED;
- else
- marker->flag ^= MARKER_DISABLED;
- }
- }
-
- DEG_id_tag_update(&clip->id, 0);
-
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
+ MovieTrackingMarker *marker;
+ int action = RNA_enum_get(op->ptr, "action");
+ int a;
+
+ if (!act_track || (act_track->flag & TRACK_LOCKED))
+ return OPERATOR_CANCELLED;
+
+ for (a = 0; a < act_track->markersnr; a++) {
+ marker = &act_track->markers[a];
+
+ if (marker->flag & MARKER_GRAPH_SEL) {
+ if (action == 0)
+ marker->flag |= MARKER_DISABLED;
+ else if (action == 1)
+ marker->flag &= ~MARKER_DISABLED;
+ else
+ marker->flag ^= MARKER_DISABLED;
+ }
+ }
+
+ DEG_id_tag_update(&clip->id, 0);
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_graph_disable_markers(wmOperatorType *ot)
{
- static const EnumPropertyItem actions_items[] = {
- {0, "DISABLE", 0, "Disable", "Disable selected markers"},
- {1, "ENABLE", 0, "Enable", "Enable selected markers"},
- {2, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Disable Markers";
- ot->description = "Disable/enable selected markers";
- ot->idname = "CLIP_OT_graph_disable_markers";
-
- /* api callbacks */
- ot->exec = graph_disable_markers_exec;
- ot->poll = ED_space_clip_graph_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "action", actions_items, 0, "Action", "Disable action to execute");
+ static const EnumPropertyItem actions_items[] = {
+ {0, "DISABLE", 0, "Disable", "Disable selected markers"},
+ {1, "ENABLE", 0, "Enable", "Enable selected markers"},
+ {2, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Disable Markers";
+ ot->description = "Disable/enable selected markers";
+ ot->idname = "CLIP_OT_graph_disable_markers";
+
+ /* api callbacks */
+ ot->exec = graph_disable_markers_exec;
+ ot->poll = ED_space_clip_graph_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "action", actions_items, 0, "Action", "Disable action to execute");
}
diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h
index e85d68431d4..8ecf596fac7 100644
--- a/source/blender/editors/space_clip/clip_intern.h
+++ b/source/blender/editors/space_clip/clip_intern.h
@@ -35,18 +35,18 @@ struct bContext;
struct wmOperatorType;
/* channel heights */
-#define CHANNEL_FIRST (-0.8f * U.widget_unit)
-#define CHANNEL_HEIGHT (0.8f * U.widget_unit)
-#define CHANNEL_HEIGHT_HALF (0.4f * U.widget_unit)
-#define CHANNEL_SKIP (0.1f * U.widget_unit)
-#define CHANNEL_STEP (CHANNEL_HEIGHT + CHANNEL_SKIP)
+#define CHANNEL_FIRST (-0.8f * U.widget_unit)
+#define CHANNEL_HEIGHT (0.8f * U.widget_unit)
+#define CHANNEL_HEIGHT_HALF (0.4f * U.widget_unit)
+#define CHANNEL_SKIP (0.1f * U.widget_unit)
+#define CHANNEL_STEP (CHANNEL_HEIGHT + CHANNEL_SKIP)
-#define CHANNEL_PAD 4
+#define CHANNEL_PAD 4
/* extra padding for lengths (to go under scrollers) */
-#define EXTRA_SCROLL_PAD 100.0f
+#define EXTRA_SCROLL_PAD 100.0f
-#define STRIP_HEIGHT_HALF (0.25f * UI_UNIT_Y)
+#define STRIP_HEIGHT_HALF (0.25f * UI_UNIT_Y)
/* internal exports only */
@@ -114,31 +114,61 @@ void CLIP_OT_tools(struct wmOperatorType *ot);
void CLIP_OT_properties(struct wmOperatorType *ot);
/* clip_utils.c */
-void clip_graph_tracking_values_iterate_track(struct SpaceClip *sc, struct MovieTrackingTrack *track, void *userdata,
- void (*func)(void *userdata, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int coord, int scene_framenr, float val),
- void (*segment_start)(void *userdata, struct MovieTrackingTrack *track, int coord, bool is_point),
- void (*segment_end)(void *userdata, int coord));
-
-void clip_graph_tracking_values_iterate(struct SpaceClip *sc, bool selected_only, bool include_hidden, void *userdata,
- void (*func)(void *userdata, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int coord, int scene_framenr, float val),
- void (*segment_start)(void *userdata, struct MovieTrackingTrack *track, int coord, bool is_point),
+void clip_graph_tracking_values_iterate_track(
+ struct SpaceClip *sc,
+ struct MovieTrackingTrack *track,
+ void *userdata,
+ void (*func)(void *userdata,
+ struct MovieTrackingTrack *track,
+ struct MovieTrackingMarker *marker,
+ int coord,
+ int scene_framenr,
+ float val),
+ void (*segment_start)(
+ void *userdata, struct MovieTrackingTrack *track, int coord, bool is_point),
+ void (*segment_end)(void *userdata, int coord));
+
+void clip_graph_tracking_values_iterate(struct SpaceClip *sc,
+ bool selected_only,
+ bool include_hidden,
+ void *userdata,
+ void (*func)(void *userdata,
+ struct MovieTrackingTrack *track,
+ struct MovieTrackingMarker *marker,
+ int coord,
+ int scene_framenr,
+ float val),
+ void (*segment_start)(void *userdata,
+ struct MovieTrackingTrack *track,
+ int coord,
+ bool is_point),
void (*segment_end)(void *userdata, int coord));
-void clip_graph_tracking_iterate(struct SpaceClip *sc, bool selected_only, bool include_hidden, void *userdata,
+void clip_graph_tracking_iterate(struct SpaceClip *sc,
+ bool selected_only,
+ bool include_hidden,
+ void *userdata,
void (*func)(void *userdata, struct MovieTrackingMarker *marker));
-void clip_delete_track(struct bContext *C, struct MovieClip *clip, struct MovieTrackingTrack *track);
-void clip_delete_marker(struct bContext *C, struct MovieClip *clip, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker);
+void clip_delete_track(struct bContext *C,
+ struct MovieClip *clip,
+ struct MovieTrackingTrack *track);
+void clip_delete_marker(struct bContext *C,
+ struct MovieClip *clip,
+ struct MovieTrackingTrack *track,
+ struct MovieTrackingMarker *marker);
-void clip_delete_plane_track(struct bContext *C, struct MovieClip *clip, struct MovieTrackingPlaneTrack *plane_track);
+void clip_delete_plane_track(struct bContext *C,
+ struct MovieClip *clip,
+ struct MovieTrackingPlaneTrack *plane_track);
void clip_view_center_to_point(SpaceClip *sc, float x, float y);
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 MovieTrackingTrack *tracking_marker_check_slide(
+ struct bContext *C, const struct wmEvent *event, int *area_r, int *action_r, int *corner_r);
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 a86dd7ceb2d..3cebb53d31e 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -34,7 +34,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_userdef_types.h"
-#include "DNA_scene_types.h" /* min/max frames */
+#include "DNA_scene_types.h" /* min/max frames */
#include "BLI_utildefines.h"
#include "BLI_fileops.h"
@@ -76,1035 +76,1080 @@
#include "DEG_depsgraph_build.h"
-#include "clip_intern.h" // own include
+#include "clip_intern.h" // own include
/******************** view navigation utilities *********************/
static void sclip_zoom_set(const bContext *C, float zoom, float location[2])
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
- float oldzoom = sc->zoom;
- int width, height;
+ float oldzoom = sc->zoom;
+ int width, height;
- sc->zoom = zoom;
+ sc->zoom = zoom;
- if (sc->zoom < 0.1f || sc->zoom > 4.0f) {
- /* check zoom limits */
- ED_space_clip_get_size(sc, &width, &height);
+ if (sc->zoom < 0.1f || sc->zoom > 4.0f) {
+ /* check zoom limits */
+ ED_space_clip_get_size(sc, &width, &height);
- width *= sc->zoom;
- height *= sc->zoom;
+ width *= sc->zoom;
+ height *= sc->zoom;
- if ((width < 4) && (height < 4) && sc->zoom < oldzoom)
- sc->zoom = oldzoom;
- else if (BLI_rcti_size_x(&ar->winrct) <= sc->zoom)
- sc->zoom = oldzoom;
- else if (BLI_rcti_size_y(&ar->winrct) <= sc->zoom)
- sc->zoom = oldzoom;
- }
+ if ((width < 4) && (height < 4) && sc->zoom < oldzoom)
+ sc->zoom = oldzoom;
+ else if (BLI_rcti_size_x(&ar->winrct) <= sc->zoom)
+ sc->zoom = oldzoom;
+ else if (BLI_rcti_size_y(&ar->winrct) <= sc->zoom)
+ sc->zoom = oldzoom;
+ }
- if ((U.uiflag & USER_ZOOM_TO_MOUSEPOS) && location) {
- float aspx, aspy, w, h, dx, dy;
+ if ((U.uiflag & USER_ZOOM_TO_MOUSEPOS) && location) {
+ float aspx, aspy, w, h, dx, dy;
- ED_space_clip_get_size(sc, &width, &height);
- ED_space_clip_get_aspect(sc, &aspx, &aspy);
+ ED_space_clip_get_size(sc, &width, &height);
+ ED_space_clip_get_aspect(sc, &aspx, &aspy);
- w = width * aspx;
- h = height * aspy;
+ w = width * aspx;
+ h = height * aspy;
- dx = ((location[0] - 0.5f) * w - sc->xof) * (sc->zoom - oldzoom) / sc->zoom;
- dy = ((location[1] - 0.5f) * h - sc->yof) * (sc->zoom - oldzoom) / sc->zoom;
+ dx = ((location[0] - 0.5f) * w - sc->xof) * (sc->zoom - oldzoom) / sc->zoom;
+ dy = ((location[1] - 0.5f) * h - sc->yof) * (sc->zoom - oldzoom) / sc->zoom;
- if (sc->flag & SC_LOCK_SELECTION) {
- sc->xlockof += dx;
- sc->ylockof += dy;
- }
- else {
- sc->xof += dx;
- sc->yof += dy;
- }
- }
+ if (sc->flag & SC_LOCK_SELECTION) {
+ sc->xlockof += dx;
+ sc->ylockof += dy;
+ }
+ else {
+ sc->xof += dx;
+ sc->yof += dy;
+ }
+ }
}
static void sclip_zoom_set_factor(const bContext *C, float zoomfac, float location[2])
{
- SpaceClip *sc = CTX_wm_space_clip(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
- sclip_zoom_set(C, sc->zoom * zoomfac, location);
+ sclip_zoom_set(C, sc->zoom * zoomfac, location);
}
static void sclip_zoom_set_factor_exec(bContext *C, const wmEvent *event, float factor)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *ar = CTX_wm_region(C);
- float location[2], *mpos = NULL;
+ float location[2], *mpos = NULL;
- if (event) {
- SpaceClip *sc = CTX_wm_space_clip(C);
+ if (event) {
+ SpaceClip *sc = CTX_wm_space_clip(C);
- ED_clip_mouse_pos(sc, ar, event->mval, location);
- mpos = location;
- }
+ ED_clip_mouse_pos(sc, ar, event->mval, location);
+ mpos = location;
+ }
- sclip_zoom_set_factor(C, factor, mpos);
+ sclip_zoom_set_factor(C, factor, mpos);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
}
/******************** open clip operator ********************/
static void clip_filesel(bContext *C, wmOperator *op, const char *path)
{
- RNA_string_set(op->ptr, "directory", path);
+ RNA_string_set(op->ptr, "directory", path);
- WM_event_add_fileselect(C, op);
+ WM_event_add_fileselect(C, op);
}
static void open_init(bContext *C, wmOperator *op)
{
- PropertyPointerRNA *pprop;
+ PropertyPointerRNA *pprop;
- op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
- UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
+ op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
+ UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
}
static void open_cancel(bContext *UNUSED(C), wmOperator *op)
{
- MEM_freeN(op->customdata);
- op->customdata = NULL;
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
}
static int open_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- bScreen *screen = CTX_wm_screen(C);
- Main *bmain = CTX_data_main(C);
- PropertyPointerRNA *pprop;
- PointerRNA idptr;
- MovieClip *clip = NULL;
- char str[FILE_MAX];
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ bScreen *screen = CTX_wm_screen(C);
+ Main *bmain = CTX_data_main(C);
+ PropertyPointerRNA *pprop;
+ PointerRNA idptr;
+ MovieClip *clip = NULL;
+ char str[FILE_MAX];
- if (RNA_collection_length(op->ptr, "files")) {
- PointerRNA fileptr;
- PropertyRNA *prop;
- char dir_only[FILE_MAX], file_only[FILE_MAX];
- bool relative = RNA_boolean_get(op->ptr, "relative_path");
+ if (RNA_collection_length(op->ptr, "files")) {
+ PointerRNA fileptr;
+ PropertyRNA *prop;
+ char dir_only[FILE_MAX], file_only[FILE_MAX];
+ bool relative = RNA_boolean_get(op->ptr, "relative_path");
- RNA_string_get(op->ptr, "directory", dir_only);
- if (relative) {
- BLI_path_rel(dir_only, CTX_data_main(C)->name);
- }
+ RNA_string_get(op->ptr, "directory", dir_only);
+ if (relative) {
+ BLI_path_rel(dir_only, CTX_data_main(C)->name);
+ }
- prop = RNA_struct_find_property(op->ptr, "files");
- RNA_property_collection_lookup_int(op->ptr, prop, 0, &fileptr);
- RNA_string_get(&fileptr, "name", file_only);
+ prop = RNA_struct_find_property(op->ptr, "files");
+ RNA_property_collection_lookup_int(op->ptr, prop, 0, &fileptr);
+ RNA_string_get(&fileptr, "name", file_only);
- BLI_join_dirfile(str, sizeof(str), dir_only, file_only);
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "No files selected to be opened");
+ BLI_join_dirfile(str, sizeof(str), dir_only, file_only);
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No files selected to be opened");
- return OPERATOR_CANCELLED;
- }
+ return OPERATOR_CANCELLED;
+ }
- /* default to frame 1 if there's no scene in context */
+ /* default to frame 1 if there's no scene in context */
- errno = 0;
+ errno = 0;
- clip = BKE_movieclip_file_add_exists(bmain, str);
+ clip = BKE_movieclip_file_add_exists(bmain, str);
- if (!clip) {
- if (op->customdata)
- MEM_freeN(op->customdata);
+ if (!clip) {
+ if (op->customdata)
+ MEM_freeN(op->customdata);
- BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s", str,
- errno ? strerror(errno) : TIP_("unsupported movie clip format"));
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "Cannot read '%s': %s",
+ str,
+ errno ? strerror(errno) : TIP_("unsupported movie clip format"));
- return OPERATOR_CANCELLED;
- }
+ return OPERATOR_CANCELLED;
+ }
- if (!op->customdata)
- open_init(C, op);
+ if (!op->customdata)
+ open_init(C, op);
- /* hook into UI */
- pprop = op->customdata;
+ /* hook into UI */
+ pprop = op->customdata;
- if (pprop->prop) {
- /* when creating new ID blocks, use is already 1, but RNA
- * pointer use also increases user, so this compensates it */
- id_us_min(&clip->id);
+ if (pprop->prop) {
+ /* when creating new ID blocks, use is already 1, but RNA
+ * pointer use also increases user, so this compensates it */
+ id_us_min(&clip->id);
- RNA_id_pointer_create(&clip->id, &idptr);
- RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
- RNA_property_update(C, &pprop->ptr, pprop->prop);
- }
- else if (sc) {
- ED_space_clip_set_clip(C, screen, sc, clip);
- }
+ RNA_id_pointer_create(&clip->id, &idptr);
+ RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
+ RNA_property_update(C, &pprop->ptr, pprop->prop);
+ }
+ else if (sc) {
+ ED_space_clip_set_clip(C, screen, sc, clip);
+ }
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_ADDED, clip);
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_ADDED, clip);
- DEG_relations_tag_update(bmain);
- MEM_freeN(op->customdata);
+ DEG_relations_tag_update(bmain);
+ MEM_freeN(op->customdata);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- char path[FILE_MAX];
- MovieClip *clip = NULL;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ char path[FILE_MAX];
+ MovieClip *clip = NULL;
- if (sc)
- clip = ED_space_clip_get_clip(sc);
+ if (sc)
+ clip = ED_space_clip_get_clip(sc);
- if (clip) {
- BLI_strncpy(path, clip->name, sizeof(path));
+ if (clip) {
+ BLI_strncpy(path, clip->name, sizeof(path));
- BLI_path_abs(path, CTX_data_main(C)->name);
- BLI_parent_dir(path);
- }
- else {
- BLI_strncpy(path, U.textudir, sizeof(path));
- }
+ BLI_path_abs(path, CTX_data_main(C)->name);
+ BLI_parent_dir(path);
+ }
+ else {
+ BLI_strncpy(path, U.textudir, sizeof(path));
+ }
- if (RNA_struct_property_is_set(op->ptr, "files"))
- return open_exec(C, op);
+ if (RNA_struct_property_is_set(op->ptr, "files"))
+ return open_exec(C, op);
- if (!RNA_struct_property_is_set(op->ptr, "relative_path"))
- RNA_boolean_set(op->ptr, "relative_path", (U.flag & USER_RELPATHS) != 0);
+ if (!RNA_struct_property_is_set(op->ptr, "relative_path"))
+ RNA_boolean_set(op->ptr, "relative_path", (U.flag & USER_RELPATHS) != 0);
- open_init(C, op);
+ open_init(C, op);
- clip_filesel(C, op, path);
+ clip_filesel(C, op, path);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void CLIP_OT_open(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Open Clip";
- ot->description = "Load a sequence of frames or a movie file";
- ot->idname = "CLIP_OT_open";
+ /* identifiers */
+ ot->name = "Open Clip";
+ ot->description = "Load a sequence of frames or a movie file";
+ ot->idname = "CLIP_OT_open";
- /* api callbacks */
- ot->exec = open_exec;
- ot->invoke = open_invoke;
- ot->cancel = open_cancel;
+ /* api callbacks */
+ ot->exec = open_exec;
+ ot->invoke = open_invoke;
+ ot->cancel = open_cancel;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_RELPATH | WM_FILESEL_FILES | WM_FILESEL_DIRECTORY, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+ /* properties */
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_RELPATH | WM_FILESEL_FILES | WM_FILESEL_DIRECTORY,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
}
/******************* reload clip operator *********************/
static int reload_exec(bContext *C, wmOperator *UNUSED(op))
{
- MovieClip *clip = CTX_data_edit_movieclip(C);
+ MovieClip *clip = CTX_data_edit_movieclip(C);
- if (!clip)
- return OPERATOR_CANCELLED;
+ if (!clip)
+ return OPERATOR_CANCELLED;
- WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_CLIP_PREFETCH);
- BKE_movieclip_reload(CTX_data_main(C), clip);
+ WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_CLIP_PREFETCH);
+ BKE_movieclip_reload(CTX_data_main(C), clip);
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_reload(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reload Clip";
- ot->description = "Reload clip";
- ot->idname = "CLIP_OT_reload";
+ /* identifiers */
+ ot->name = "Reload Clip";
+ ot->description = "Reload clip";
+ ot->idname = "CLIP_OT_reload";
- /* api callbacks */
- ot->exec = reload_exec;
+ /* api callbacks */
+ ot->exec = reload_exec;
}
/********************** view pan operator *********************/
typedef struct ViewPanData {
- float x, y;
- float xof, yof, xorig, yorig;
- int event_type;
- float *vec;
+ float x, y;
+ float xof, yof, xorig, yorig;
+ int event_type;
+ float *vec;
} ViewPanData;
static void view_pan_init(bContext *C, wmOperator *op, const wmEvent *event)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- ViewPanData *vpd;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ViewPanData *vpd;
- op->customdata = vpd = MEM_callocN(sizeof(ViewPanData), "ClipViewPanData");
- WM_cursor_modal_set(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
+ op->customdata = vpd = MEM_callocN(sizeof(ViewPanData), "ClipViewPanData");
+ WM_cursor_modal_set(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
- vpd->x = event->x;
- vpd->y = event->y;
+ vpd->x = event->x;
+ vpd->y = event->y;
- if (sc->flag & SC_LOCK_SELECTION)
- vpd->vec = &sc->xlockof;
- else
- vpd->vec = &sc->xof;
+ if (sc->flag & SC_LOCK_SELECTION)
+ vpd->vec = &sc->xlockof;
+ else
+ vpd->vec = &sc->xof;
- copy_v2_v2(&vpd->xof, vpd->vec);
- copy_v2_v2(&vpd->xorig, &vpd->xof);
+ copy_v2_v2(&vpd->xof, vpd->vec);
+ copy_v2_v2(&vpd->xorig, &vpd->xof);
- vpd->event_type = event->type;
+ vpd->event_type = event->type;
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
}
static void view_pan_exit(bContext *C, wmOperator *op, bool cancel)
{
- ViewPanData *vpd = op->customdata;
+ ViewPanData *vpd = op->customdata;
- if (cancel) {
- copy_v2_v2(vpd->vec, &vpd->xorig);
+ if (cancel) {
+ copy_v2_v2(vpd->vec, &vpd->xorig);
- ED_region_tag_redraw(CTX_wm_region(C));
- }
+ ED_region_tag_redraw(CTX_wm_region(C));
+ }
- WM_cursor_modal_restore(CTX_wm_window(C));
- MEM_freeN(op->customdata);
+ WM_cursor_modal_restore(CTX_wm_window(C));
+ MEM_freeN(op->customdata);
}
static int view_pan_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- float offset[2];
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ float offset[2];
- RNA_float_get_array(op->ptr, "offset", offset);
+ RNA_float_get_array(op->ptr, "offset", offset);
- if (sc->flag & SC_LOCK_SELECTION) {
- sc->xlockof += offset[0];
- sc->ylockof += offset[1];
- }
- else {
- sc->xof += offset[0];
- sc->yof += offset[1];
- }
+ if (sc->flag & SC_LOCK_SELECTION) {
+ sc->xlockof += offset[0];
+ sc->ylockof += offset[1];
+ }
+ else {
+ sc->xof += offset[0];
+ sc->yof += offset[1];
+ }
- ED_region_tag_redraw(CTX_wm_region(C));
+ ED_region_tag_redraw(CTX_wm_region(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int view_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (event->type == MOUSEPAN) {
- SpaceClip *sc = CTX_wm_space_clip(C);
- float offset[2];
+ if (event->type == MOUSEPAN) {
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ float offset[2];
- offset[0] = (event->prevx - event->x) / sc->zoom;
- offset[1] = (event->prevy - event->y) / sc->zoom;
+ offset[0] = (event->prevx - event->x) / sc->zoom;
+ offset[1] = (event->prevy - event->y) / sc->zoom;
- RNA_float_set_array(op->ptr, "offset", offset);
+ RNA_float_set_array(op->ptr, "offset", offset);
- view_pan_exec(C, op);
+ view_pan_exec(C, op);
- return OPERATOR_FINISHED;
- }
- else {
- view_pan_init(C, op, event);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ view_pan_init(C, op, event);
- return OPERATOR_RUNNING_MODAL;
- }
+ return OPERATOR_RUNNING_MODAL;
+ }
}
static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- ViewPanData *vpd = op->customdata;
- float offset[2];
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ViewPanData *vpd = op->customdata;
+ float offset[2];
- switch (event->type) {
- case MOUSEMOVE:
- copy_v2_v2(vpd->vec, &vpd->xorig);
- offset[0] = (vpd->x - event->x) / sc->zoom;
- offset[1] = (vpd->y - event->y) / sc->zoom;
- RNA_float_set_array(op->ptr, "offset", offset);
- view_pan_exec(C, op);
- break;
- case ESCKEY:
- view_pan_exit(C, op, 1);
+ switch (event->type) {
+ case MOUSEMOVE:
+ copy_v2_v2(vpd->vec, &vpd->xorig);
+ offset[0] = (vpd->x - event->x) / sc->zoom;
+ offset[1] = (vpd->y - event->y) / sc->zoom;
+ RNA_float_set_array(op->ptr, "offset", offset);
+ view_pan_exec(C, op);
+ break;
+ case ESCKEY:
+ view_pan_exit(C, op, 1);
- return OPERATOR_CANCELLED;
- case SPACEKEY:
- view_pan_exit(C, op, 0);
+ return OPERATOR_CANCELLED;
+ case SPACEKEY:
+ view_pan_exit(C, op, 0);
- return OPERATOR_FINISHED;
- default:
- if (event->type == vpd->event_type && event->val == KM_RELEASE) {
- view_pan_exit(C, op, 0);
+ return OPERATOR_FINISHED;
+ default:
+ if (event->type == vpd->event_type && event->val == KM_RELEASE) {
+ view_pan_exit(C, op, 0);
- return OPERATOR_FINISHED;
- }
- break;
- }
+ return OPERATOR_FINISHED;
+ }
+ break;
+ }
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static void view_pan_cancel(bContext *C, wmOperator *op)
{
- view_pan_exit(C, op, true);
+ view_pan_exit(C, op, true);
}
void CLIP_OT_view_pan(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Pan View";
- ot->idname = "CLIP_OT_view_pan";
- ot->description = "Pan the view";
-
- /* api callbacks */
- ot->exec = view_pan_exec;
- ot->invoke = view_pan_invoke;
- ot->modal = view_pan_modal;
- ot->cancel = view_pan_cancel;
- ot->poll = ED_space_clip_view_clip_poll;
-
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
-
- /* properties */
- RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX,
- "Offset", "Offset in floating point units, 1.0 is the width and height of the image", -FLT_MAX, FLT_MAX);
+ /* identifiers */
+ ot->name = "Pan View";
+ ot->idname = "CLIP_OT_view_pan";
+ ot->description = "Pan the view";
+
+ /* api callbacks */
+ ot->exec = view_pan_exec;
+ ot->invoke = view_pan_invoke;
+ ot->modal = view_pan_modal;
+ ot->cancel = view_pan_cancel;
+ ot->poll = ED_space_clip_view_clip_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
+
+ /* properties */
+ RNA_def_float_vector(ot->srna,
+ "offset",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Offset",
+ "Offset in floating point units, 1.0 is the width and height of the image",
+ -FLT_MAX,
+ FLT_MAX);
}
/********************** view zoom operator *********************/
typedef struct ViewZoomData {
- float x, y;
- float zoom;
- int event_type;
- float location[2];
- wmTimer *timer;
- double timer_lastdraw;
+ float x, y;
+ float zoom;
+ int event_type;
+ float location[2];
+ wmTimer *timer;
+ double timer_lastdraw;
} ViewZoomData;
static void view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
- ViewZoomData *vpd;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
+ ViewZoomData *vpd;
- op->customdata = vpd = MEM_callocN(sizeof(ViewZoomData), "ClipViewZoomData");
- WM_cursor_modal_set(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
+ op->customdata = vpd = MEM_callocN(sizeof(ViewZoomData), "ClipViewZoomData");
+ WM_cursor_modal_set(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
- if (U.viewzoom == USER_ZOOM_CONT) {
- /* needs a timer to continue redrawing */
- vpd->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
- vpd->timer_lastdraw = PIL_check_seconds_timer();
- }
+ if (U.viewzoom == USER_ZOOM_CONT) {
+ /* needs a timer to continue redrawing */
+ vpd->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
+ vpd->timer_lastdraw = PIL_check_seconds_timer();
+ }
- vpd->x = event->x;
- vpd->y = event->y;
- vpd->zoom = sc->zoom;
- vpd->event_type = event->type;
+ vpd->x = event->x;
+ vpd->y = event->y;
+ vpd->zoom = sc->zoom;
+ vpd->event_type = event->type;
- ED_clip_mouse_pos(sc, ar, event->mval, vpd->location);
+ ED_clip_mouse_pos(sc, ar, event->mval, vpd->location);
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
}
static void view_zoom_exit(bContext *C, wmOperator *op, bool cancel)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- ViewZoomData *vpd = op->customdata;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ViewZoomData *vpd = op->customdata;
- if (cancel) {
- sc->zoom = vpd->zoom;
- ED_region_tag_redraw(CTX_wm_region(C));
- }
+ if (cancel) {
+ sc->zoom = vpd->zoom;
+ ED_region_tag_redraw(CTX_wm_region(C));
+ }
- if (vpd->timer) {
- WM_event_remove_timer(CTX_wm_manager(C), vpd->timer->win, vpd->timer);
- }
+ if (vpd->timer) {
+ WM_event_remove_timer(CTX_wm_manager(C), vpd->timer->win, vpd->timer);
+ }
- WM_cursor_modal_restore(CTX_wm_window(C));
- MEM_freeN(op->customdata);
+ WM_cursor_modal_restore(CTX_wm_window(C));
+ MEM_freeN(op->customdata);
}
static int view_zoom_exec(bContext *C, wmOperator *op)
{
- sclip_zoom_set_factor(C, RNA_float_get(op->ptr, "factor"), NULL);
+ sclip_zoom_set_factor(C, RNA_float_get(op->ptr, "factor"), NULL);
- ED_region_tag_redraw(CTX_wm_region(C));
+ ED_region_tag_redraw(CTX_wm_region(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int view_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
- float delta, factor;
+ if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
+ float delta, factor;
- delta = event->prevx - event->x + event->prevy - event->y;
+ delta = event->prevx - event->x + event->prevy - event->y;
- if (U.uiflag & USER_ZOOM_INVERT)
- delta *= -1;
+ if (U.uiflag & USER_ZOOM_INVERT)
+ delta *= -1;
- factor = 1.0f + delta / 300.0f;
- RNA_float_set(op->ptr, "factor", factor);
+ factor = 1.0f + delta / 300.0f;
+ RNA_float_set(op->ptr, "factor", factor);
- sclip_zoom_set_factor_exec(C, event, factor);
+ sclip_zoom_set_factor_exec(C, event, factor);
- return OPERATOR_FINISHED;
- }
- else {
- view_zoom_init(C, op, event);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ view_zoom_init(C, op, event);
- return OPERATOR_RUNNING_MODAL;
- }
+ return OPERATOR_RUNNING_MODAL;
+ }
}
-static void view_zoom_apply(bContext *C,
- ViewZoomData *vpd,
- wmOperator *op,
- const wmEvent *event)
+static void view_zoom_apply(bContext *C, ViewZoomData *vpd, wmOperator *op, const wmEvent *event)
{
- float factor;
+ float factor;
- if (U.viewzoom == USER_ZOOM_CONT) {
- SpaceClip *sclip = CTX_wm_space_clip(C);
- double time = PIL_check_seconds_timer();
- float time_step = (float)(time - vpd->timer_lastdraw);
- float fac;
- float zfac;
+ if (U.viewzoom == USER_ZOOM_CONT) {
+ SpaceClip *sclip = CTX_wm_space_clip(C);
+ double time = PIL_check_seconds_timer();
+ float time_step = (float)(time - vpd->timer_lastdraw);
+ float fac;
+ float zfac;
- if (U.uiflag & USER_ZOOM_HORIZ) {
- fac = (float)(event->x - vpd->x);
- }
- else {
- fac = (float)(event->y - vpd->y);
- }
+ if (U.uiflag & USER_ZOOM_HORIZ) {
+ fac = (float)(event->x - vpd->x);
+ }
+ else {
+ fac = (float)(event->y - vpd->y);
+ }
- if (U.uiflag & USER_ZOOM_INVERT) {
- fac = -fac;
- }
+ if (U.uiflag & USER_ZOOM_INVERT) {
+ fac = -fac;
+ }
- zfac = 1.0f + ((fac / 20.0f) * time_step);
- vpd->timer_lastdraw = time;
- factor = (sclip->zoom * zfac) / vpd->zoom;
- }
- else {
- float delta = event->x - vpd->x + event->y - vpd->y;
+ zfac = 1.0f + ((fac / 20.0f) * time_step);
+ vpd->timer_lastdraw = time;
+ factor = (sclip->zoom * zfac) / vpd->zoom;
+ }
+ else {
+ float delta = event->x - vpd->x + event->y - vpd->y;
- if (U.uiflag & USER_ZOOM_INVERT) {
- delta *= -1;
- }
+ if (U.uiflag & USER_ZOOM_INVERT) {
+ delta *= -1;
+ }
- factor = 1.0f + delta / 300.0f;
- }
+ factor = 1.0f + delta / 300.0f;
+ }
- RNA_float_set(op->ptr, "factor", factor);
- sclip_zoom_set(C, vpd->zoom * factor, vpd->location);
- ED_region_tag_redraw(CTX_wm_region(C));
+ RNA_float_set(op->ptr, "factor", factor);
+ sclip_zoom_set(C, vpd->zoom * factor, vpd->location);
+ ED_region_tag_redraw(CTX_wm_region(C));
}
static int view_zoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewZoomData *vpd = op->customdata;
- switch (event->type) {
- case TIMER:
- if (event->customdata == vpd->timer) {
- view_zoom_apply(C, vpd, op, event);
- }
- break;
- case MOUSEMOVE:
- view_zoom_apply(C, vpd, op, event);
- break;
- default:
- if (event->type == vpd->event_type && event->val == KM_RELEASE) {
- view_zoom_exit(C, op, 0);
+ ViewZoomData *vpd = op->customdata;
+ switch (event->type) {
+ case TIMER:
+ if (event->customdata == vpd->timer) {
+ view_zoom_apply(C, vpd, op, event);
+ }
+ break;
+ case MOUSEMOVE:
+ view_zoom_apply(C, vpd, op, event);
+ break;
+ default:
+ if (event->type == vpd->event_type && event->val == KM_RELEASE) {
+ view_zoom_exit(C, op, 0);
- return OPERATOR_FINISHED;
- }
- break;
- }
+ return OPERATOR_FINISHED;
+ }
+ break;
+ }
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static void view_zoom_cancel(bContext *C, wmOperator *op)
{
- view_zoom_exit(C, op, true);
+ view_zoom_exit(C, op, true);
}
void CLIP_OT_view_zoom(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "View Zoom";
- ot->idname = "CLIP_OT_view_zoom";
- ot->description = "Zoom in/out the view";
+ /* identifiers */
+ ot->name = "View Zoom";
+ ot->idname = "CLIP_OT_view_zoom";
+ ot->description = "Zoom in/out the view";
- /* api callbacks */
- ot->exec = view_zoom_exec;
- ot->invoke = view_zoom_invoke;
- ot->modal = view_zoom_modal;
- ot->cancel = view_zoom_cancel;
- ot->poll = ED_space_clip_view_clip_poll;
+ /* api callbacks */
+ ot->exec = view_zoom_exec;
+ ot->invoke = view_zoom_invoke;
+ ot->modal = view_zoom_modal;
+ ot->cancel = view_zoom_cancel;
+ ot->poll = ED_space_clip_view_clip_poll;
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
- /* properties */
- prop = RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Factor",
- "Zoom factor, values higher than 1.0 zoom in, lower values zoom out", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ /* properties */
+ prop = RNA_def_float(ot->srna,
+ "factor",
+ 0.0f,
+ -FLT_MAX,
+ FLT_MAX,
+ "Factor",
+ "Zoom factor, values higher than 1.0 zoom in, lower values zoom out",
+ -FLT_MAX,
+ FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/********************** view zoom in/out operator *********************/
static int view_zoom_in_exec(bContext *C, wmOperator *op)
{
- float location[2];
+ float location[2];
- RNA_float_get_array(op->ptr, "location", location);
+ RNA_float_get_array(op->ptr, "location", location);
- sclip_zoom_set_factor(C, powf(2.0f, 1.0f / 3.0f), location);
+ sclip_zoom_set_factor(C, powf(2.0f, 1.0f / 3.0f), location);
- ED_region_tag_redraw(CTX_wm_region(C));
+ ED_region_tag_redraw(CTX_wm_region(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
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);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
- float location[2];
+ float location[2];
- ED_clip_mouse_pos(sc, ar, event->mval, location);
- RNA_float_set_array(op->ptr, "location", location);
+ ED_clip_mouse_pos(sc, ar, event->mval, location);
+ RNA_float_set_array(op->ptr, "location", location);
- return view_zoom_in_exec(C, op);
+ return view_zoom_in_exec(C, op);
}
void CLIP_OT_view_zoom_in(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "View Zoom In";
- ot->idname = "CLIP_OT_view_zoom_in";
- ot->description = "Zoom in the view";
+ /* identifiers */
+ ot->name = "View Zoom In";
+ ot->idname = "CLIP_OT_view_zoom_in";
+ ot->description = "Zoom in the view";
- /* api callbacks */
- ot->exec = view_zoom_in_exec;
- ot->invoke = view_zoom_in_invoke;
- ot->poll = ED_space_clip_view_clip_poll;
+ /* api callbacks */
+ ot->exec = view_zoom_in_exec;
+ ot->invoke = view_zoom_in_invoke;
+ ot->poll = ED_space_clip_view_clip_poll;
- /* properties */
- prop = RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location",
- "Cursor location in screen coordinates", -10.0f, 10.0f);
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ /* properties */
+ prop = RNA_def_float_vector(ot->srna,
+ "location",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Location",
+ "Cursor location in screen coordinates",
+ -10.0f,
+ 10.0f);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
static int view_zoom_out_exec(bContext *C, wmOperator *op)
{
- float location[2];
+ float location[2];
- RNA_float_get_array(op->ptr, "location", location);
+ RNA_float_get_array(op->ptr, "location", location);
- sclip_zoom_set_factor(C, powf(0.5f, 1.0f / 3.0f), location);
+ sclip_zoom_set_factor(C, powf(0.5f, 1.0f / 3.0f), location);
- ED_region_tag_redraw(CTX_wm_region(C));
+ ED_region_tag_redraw(CTX_wm_region(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
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);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
- float location[2];
+ float location[2];
- ED_clip_mouse_pos(sc, ar, event->mval, location);
- RNA_float_set_array(op->ptr, "location", location);
+ ED_clip_mouse_pos(sc, ar, event->mval, location);
+ RNA_float_set_array(op->ptr, "location", location);
- return view_zoom_out_exec(C, op);
+ return view_zoom_out_exec(C, op);
}
void CLIP_OT_view_zoom_out(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "View Zoom Out";
- ot->idname = "CLIP_OT_view_zoom_out";
- ot->description = "Zoom out the view";
+ /* identifiers */
+ ot->name = "View Zoom Out";
+ ot->idname = "CLIP_OT_view_zoom_out";
+ ot->description = "Zoom out the view";
- /* api callbacks */
- ot->exec = view_zoom_out_exec;
- ot->invoke = view_zoom_out_invoke;
- ot->poll = ED_space_clip_view_clip_poll;
+ /* api callbacks */
+ ot->exec = view_zoom_out_exec;
+ ot->invoke = view_zoom_out_invoke;
+ ot->poll = ED_space_clip_view_clip_poll;
- /* properties */
- prop = RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location",
- "Cursor location in normalized (0.0-1.0) coordinates", -10.0f, 10.0f);
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ /* properties */
+ prop = RNA_def_float_vector(ot->srna,
+ "location",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Location",
+ "Cursor location in normalized (0.0-1.0) coordinates",
+ -10.0f,
+ 10.0f);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/********************** view zoom ratio operator *********************/
static int view_zoom_ratio_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
- sclip_zoom_set(C, RNA_float_get(op->ptr, "ratio"), NULL);
+ sclip_zoom_set(C, RNA_float_get(op->ptr, "ratio"), NULL);
- /* ensure pixel exact locations for draw */
- sc->xof = (int) sc->xof;
- sc->yof = (int) sc->yof;
+ /* ensure pixel exact locations for draw */
+ sc->xof = (int)sc->xof;
+ sc->yof = (int)sc->yof;
- ED_region_tag_redraw(CTX_wm_region(C));
+ ED_region_tag_redraw(CTX_wm_region(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_view_zoom_ratio(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Zoom Ratio";
- ot->idname = "CLIP_OT_view_zoom_ratio";
- ot->description = "Set the zoom ratio (based on clip size)";
+ /* identifiers */
+ ot->name = "View Zoom Ratio";
+ ot->idname = "CLIP_OT_view_zoom_ratio";
+ ot->description = "Set the zoom ratio (based on clip size)";
- /* api callbacks */
- ot->exec = view_zoom_ratio_exec;
- ot->poll = ED_space_clip_view_clip_poll;
+ /* api callbacks */
+ ot->exec = view_zoom_ratio_exec;
+ ot->poll = ED_space_clip_view_clip_poll;
- /* properties */
- RNA_def_float(ot->srna, "ratio", 0.0f, -FLT_MAX, FLT_MAX,
- "Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out", -FLT_MAX, FLT_MAX);
+ /* properties */
+ RNA_def_float(ot->srna,
+ "ratio",
+ 0.0f,
+ -FLT_MAX,
+ FLT_MAX,
+ "Ratio",
+ "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out",
+ -FLT_MAX,
+ FLT_MAX);
}
/********************** view all operator *********************/
static int view_all_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc;
- ARegion *ar;
- int w, h, width, height;
- float aspx, aspy;
- bool fit_view = RNA_boolean_get(op->ptr, "fit_view");
- float zoomx, zoomy;
+ SpaceClip *sc;
+ ARegion *ar;
+ int w, h, width, height;
+ float aspx, aspy;
+ bool fit_view = RNA_boolean_get(op->ptr, "fit_view");
+ float zoomx, zoomy;
- /* retrieve state */
- sc = CTX_wm_space_clip(C);
- ar = CTX_wm_region(C);
+ /* retrieve state */
+ sc = CTX_wm_space_clip(C);
+ ar = CTX_wm_region(C);
- ED_space_clip_get_size(sc, &w, &h);
- ED_space_clip_get_aspect(sc, &aspx, &aspy);
+ ED_space_clip_get_size(sc, &w, &h);
+ ED_space_clip_get_aspect(sc, &aspx, &aspy);
- w = w * aspx;
- h = h * aspy;
+ w = w * aspx;
+ 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;
+ /* 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;
- if (fit_view) {
- const int margin = 5; /* margin from border */
+ if (fit_view) {
+ const int margin = 5; /* margin from border */
- zoomx = (float) width / (w + 2 * margin);
- zoomy = (float) height / (h + 2 * margin);
+ zoomx = (float)width / (w + 2 * margin);
+ zoomy = (float)height / (h + 2 * margin);
- sclip_zoom_set(C, min_ff(zoomx, zoomy), NULL);
- }
- else {
- if ((w >= width || h >= height) && (width > 0 && height > 0)) {
- zoomx = (float) width / w;
- zoomy = (float) height / h;
+ sclip_zoom_set(C, min_ff(zoomx, zoomy), NULL);
+ }
+ else {
+ if ((w >= width || h >= height) && (width > 0 && height > 0)) {
+ zoomx = (float)width / w;
+ zoomy = (float)height / h;
- /* find the zoom value that will fit the image in the image space */
- sclip_zoom_set(C, 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)), NULL);
- }
- else
- sclip_zoom_set(C, 1.0f, NULL);
- }
+ /* find the zoom value that will fit the image in the image space */
+ sclip_zoom_set(C, 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)), NULL);
+ }
+ else
+ sclip_zoom_set(C, 1.0f, NULL);
+ }
- sc->xof = sc->yof = 0.0f;
+ sc->xof = sc->yof = 0.0f;
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_view_all(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "View All";
- ot->idname = "CLIP_OT_view_all";
- ot->description = "View whole image with markers";
+ /* identifiers */
+ ot->name = "View All";
+ ot->idname = "CLIP_OT_view_all";
+ ot->description = "View whole image with markers";
- /* api callbacks */
- ot->exec = view_all_exec;
- ot->poll = ED_space_clip_view_clip_poll;
+ /* api callbacks */
+ ot->exec = view_all_exec;
+ ot->poll = ED_space_clip_view_clip_poll;
- /* properties */
- prop = RNA_def_boolean(ot->srna, "fit_view", 0, "Fit View", "Fit frame to the viewport");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "fit_view", 0, "Fit View", "Fit frame to the viewport");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/********************** view 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);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
- sc->xlockof = 0.0f;
- sc->ylockof = 0.0f;
+ 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, ar, 1);
+ ED_region_tag_redraw(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_view_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Selected";
- ot->idname = "CLIP_OT_view_selected";
- ot->description = "View all selected elements";
+ /* identifiers */
+ ot->name = "View Selected";
+ ot->idname = "CLIP_OT_view_selected";
+ ot->description = "View all selected elements";
- /* api callbacks */
- ot->exec = view_selected_exec;
- ot->poll = ED_space_clip_view_clip_poll;
+ /* api callbacks */
+ ot->exec = view_selected_exec;
+ ot->poll = ED_space_clip_view_clip_poll;
}
/********************** change frame operator *********************/
static bool change_frame_poll(bContext *C)
{
- /* prevent changes during render */
- if (G.is_rendering)
- return 0;
+ /* prevent changes during render */
+ if (G.is_rendering)
+ return 0;
- return ED_space_clip_poll(C);
+ return ED_space_clip_poll(C);
}
static void change_frame_apply(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- /* set the new frame number */
- CFRA = RNA_int_get(op->ptr, "frame");
- FRAMENUMBER_MIN_CLAMP(CFRA);
- SUBFRA = 0.0f;
+ /* set the new frame number */
+ CFRA = RNA_int_get(op->ptr, "frame");
+ FRAMENUMBER_MIN_CLAMP(CFRA);
+ SUBFRA = 0.0f;
- /* do updates */
- BKE_sound_seek_scene(CTX_data_main(C), scene);
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ /* do updates */
+ BKE_sound_seek_scene(CTX_data_main(C), scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
static int change_frame_exec(bContext *C, wmOperator *op)
{
- change_frame_apply(C, op);
+ change_frame_apply(C, op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int frame_from_event(bContext *C, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
- int framenr = 0;
+ ARegion *ar = 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 (ar->regiontype == RGN_TYPE_WINDOW) {
+ float sfra = SFRA, efra = EFRA, framelen = ar->winx / (efra - sfra + 1);
- framenr = sfra + event->mval[0] / framelen;
- }
- else {
- float viewx, viewy;
+ 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(&ar->v2d, event->mval[0], event->mval[1], &viewx, &viewy);
- framenr = round_fl_to_int(viewx);
- }
+ framenr = round_fl_to_int(viewx);
+ }
- return framenr;
+ return framenr;
}
static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *ar = CTX_wm_region(C);
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- if (event->mval[1] > 16)
- return OPERATOR_PASS_THROUGH;
- }
+ if (ar->regiontype == RGN_TYPE_WINDOW) {
+ if (event->mval[1] > 16)
+ return OPERATOR_PASS_THROUGH;
+ }
- RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
+ RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
- change_frame_apply(C, op);
+ change_frame_apply(C, op);
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- switch (event->type) {
- case ESCKEY:
- return OPERATOR_FINISHED;
+ switch (event->type) {
+ case ESCKEY:
+ return OPERATOR_FINISHED;
- case MOUSEMOVE:
- RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
- change_frame_apply(C, op);
- break;
+ case MOUSEMOVE:
+ RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
+ change_frame_apply(C, op);
+ break;
- case LEFTMOUSE:
- case RIGHTMOUSE:
- if (event->val == KM_RELEASE)
- return OPERATOR_FINISHED;
- break;
- }
+ case LEFTMOUSE:
+ case RIGHTMOUSE:
+ if (event->val == KM_RELEASE)
+ return OPERATOR_FINISHED;
+ break;
+ }
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void CLIP_OT_change_frame(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Change Frame";
- ot->idname = "CLIP_OT_change_frame";
- ot->description = "Interactively change the current frame number";
+ /* identifiers */
+ ot->name = "Change Frame";
+ ot->idname = "CLIP_OT_change_frame";
+ ot->description = "Interactively change the current frame number";
- /* api callbacks */
- ot->exec = change_frame_exec;
- ot->invoke = change_frame_invoke;
- ot->modal = change_frame_modal;
- ot->poll = change_frame_poll;
+ /* api callbacks */
+ ot->exec = change_frame_exec;
+ ot->invoke = change_frame_invoke;
+ ot->modal = change_frame_modal;
+ ot->poll = change_frame_poll;
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO;
- /* rna */
- RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
+ /* rna */
+ RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
}
/********************** rebuild proxies operator *********************/
typedef struct ProxyBuildJob {
- Scene *scene;
- struct Main *main;
- MovieClip *clip;
- int clip_flag;
- bool stop;
- struct IndexBuildContext *index_context;
+ Scene *scene;
+ struct Main *main;
+ MovieClip *clip;
+ int clip_flag;
+ bool stop;
+ struct IndexBuildContext *index_context;
} ProxyJob;
static void proxy_freejob(void *pjv)
{
- ProxyJob *pj = pjv;
+ ProxyJob *pj = pjv;
- MEM_freeN(pj);
+ MEM_freeN(pj);
}
static int proxy_bitflag_to_array(int size_flag, int build_sizes[4], int undistort)
{
- int build_count = 0;
- int size_flags[2][4] = {{MCLIP_PROXY_SIZE_25,
- MCLIP_PROXY_SIZE_50,
- MCLIP_PROXY_SIZE_75,
- MCLIP_PROXY_SIZE_100},
- {MCLIP_PROXY_UNDISTORTED_SIZE_25,
- MCLIP_PROXY_UNDISTORTED_SIZE_50,
- MCLIP_PROXY_UNDISTORTED_SIZE_75,
- MCLIP_PROXY_UNDISTORTED_SIZE_100}};
- int size_nr = undistort ? 1 : 0;
+ int build_count = 0;
+ int size_flags[2][4] = {
+ {MCLIP_PROXY_SIZE_25, MCLIP_PROXY_SIZE_50, MCLIP_PROXY_SIZE_75, MCLIP_PROXY_SIZE_100},
+ {MCLIP_PROXY_UNDISTORTED_SIZE_25,
+ MCLIP_PROXY_UNDISTORTED_SIZE_50,
+ MCLIP_PROXY_UNDISTORTED_SIZE_75,
+ MCLIP_PROXY_UNDISTORTED_SIZE_100}};
+ int size_nr = undistort ? 1 : 0;
- if (size_flag & size_flags[size_nr][0])
- build_sizes[build_count++] = MCLIP_PROXY_RENDER_SIZE_25;
+ if (size_flag & size_flags[size_nr][0])
+ build_sizes[build_count++] = MCLIP_PROXY_RENDER_SIZE_25;
- if (size_flag & size_flags[size_nr][1])
- build_sizes[build_count++] = MCLIP_PROXY_RENDER_SIZE_50;
+ if (size_flag & size_flags[size_nr][1])
+ build_sizes[build_count++] = MCLIP_PROXY_RENDER_SIZE_50;
- if (size_flag & size_flags[size_nr][2])
- build_sizes[build_count++] = MCLIP_PROXY_RENDER_SIZE_75;
+ if (size_flag & size_flags[size_nr][2])
+ build_sizes[build_count++] = MCLIP_PROXY_RENDER_SIZE_75;
- if (size_flag & size_flags[size_nr][3])
- build_sizes[build_count++] = MCLIP_PROXY_RENDER_SIZE_100;
+ if (size_flag & size_flags[size_nr][3])
+ build_sizes[build_count++] = MCLIP_PROXY_RENDER_SIZE_100;
- return build_count;
+ return build_count;
}
/* simple case for movies -- handle frame-by-frame, do threading within single frame */
-static void do_movie_proxy(void *pjv, int *UNUSED(build_sizes), int UNUSED(build_count),
- int *build_undistort_sizes, int build_undistort_count,
- short *stop, short *do_update, float *progress)
+static void do_movie_proxy(void *pjv,
+ int *UNUSED(build_sizes),
+ int UNUSED(build_count),
+ int *build_undistort_sizes,
+ int build_undistort_count,
+ short *stop,
+ short *do_update,
+ float *progress)
{
- ProxyJob *pj = pjv;
- Scene *scene = pj->scene;
- MovieClip *clip = pj->clip;
- struct MovieDistortion *distortion = NULL;
- int cfra, sfra = SFRA, efra = EFRA;
+ ProxyJob *pj = pjv;
+ Scene *scene = pj->scene;
+ MovieClip *clip = pj->clip;
+ struct MovieDistortion *distortion = NULL;
+ int cfra, sfra = SFRA, efra = EFRA;
- if (pj->index_context)
- IMB_anim_index_rebuild(pj->index_context, stop, do_update, progress);
+ if (pj->index_context)
+ IMB_anim_index_rebuild(pj->index_context, stop, do_update, progress);
- if (!build_undistort_count) {
- if (*stop)
- pj->stop = 1;
+ if (!build_undistort_count) {
+ if (*stop)
+ pj->stop = 1;
- return;
- }
- else {
- sfra = 1;
- efra = clip->len;
- }
+ return;
+ }
+ else {
+ sfra = 1;
+ efra = clip->len;
+ }
- if (build_undistort_count) {
- int threads = BLI_system_thread_count();
- int width, height;
+ if (build_undistort_count) {
+ int threads = BLI_system_thread_count();
+ int width, height;
- BKE_movieclip_get_size(clip, NULL, &width, &height);
+ BKE_movieclip_get_size(clip, NULL, &width, &height);
- distortion = BKE_tracking_distortion_new(&clip->tracking, width, height);
- BKE_tracking_distortion_set_threads(distortion, threads);
- }
+ distortion = BKE_tracking_distortion_new(&clip->tracking, width, height);
+ BKE_tracking_distortion_set_threads(distortion, threads);
+ }
- for (cfra = sfra; cfra <= efra; cfra++) {
- BKE_movieclip_build_proxy_frame(clip, pj->clip_flag, distortion, cfra,
- build_undistort_sizes, build_undistort_count, 1);
+ for (cfra = sfra; cfra <= efra; cfra++) {
+ BKE_movieclip_build_proxy_frame(
+ clip, pj->clip_flag, distortion, cfra, build_undistort_sizes, build_undistort_count, 1);
- if (*stop || G.is_break)
- break;
+ if (*stop || G.is_break)
+ break;
- *do_update = true;
- *progress = ((float) cfra - sfra) / (efra - sfra);
- }
+ *do_update = true;
+ *progress = ((float)cfra - sfra) / (efra - sfra);
+ }
- if (distortion)
- BKE_tracking_distortion_free(distortion);
+ if (distortion)
+ BKE_tracking_distortion_free(distortion);
- if (*stop)
- pj->stop = 1;
+ if (*stop)
+ pj->stop = 1;
}
/* *****
@@ -1114,296 +1159,325 @@ static void do_movie_proxy(void *pjv, int *UNUSED(build_sizes), int UNUSED(build
*/
typedef struct ProxyQueue {
- int cfra;
- int sfra;
- int efra;
- SpinLock spin;
-
- const short *stop;
- short *do_update;
- float *progress;
+ int cfra;
+ int sfra;
+ int efra;
+ SpinLock spin;
+
+ const short *stop;
+ short *do_update;
+ float *progress;
} ProxyQueue;
typedef struct ProxyThread {
- MovieClip *clip;
- struct MovieDistortion *distortion;
- int *build_sizes, build_count;
- int *build_undistort_sizes, build_undistort_count;
+ MovieClip *clip;
+ struct MovieDistortion *distortion;
+ int *build_sizes, build_count;
+ 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)
-{
- unsigned char *mem = NULL;
-
- BLI_spin_lock(&queue->spin);
- if (!*queue->stop && queue->cfra <= queue->efra) {
- MovieClipUser user = {0};
- char name[FILE_MAX];
- size_t size;
- int file;
-
- user.framenr = queue->cfra;
-
- BKE_movieclip_filename_for_frame(clip, &user, name);
-
- file = BLI_open(name, O_BINARY | O_RDONLY, 0);
- if (file < 0) {
- BLI_spin_unlock(&queue->spin);
- return NULL;
- }
-
- size = BLI_file_descriptor_size(file);
- if (size < 1) {
- close(file);
- BLI_spin_unlock(&queue->spin);
- return NULL;
- }
-
- mem = MEM_mallocN(size, "movieclip proxy memory file");
+static unsigned char *proxy_thread_next_frame(ProxyQueue *queue,
+ MovieClip *clip,
+ size_t *size_r,
+ int *cfra_r)
+{
+ unsigned char *mem = NULL;
+
+ BLI_spin_lock(&queue->spin);
+ if (!*queue->stop && queue->cfra <= queue->efra) {
+ MovieClipUser user = {0};
+ char name[FILE_MAX];
+ size_t size;
+ int file;
- if (read(file, mem, size) != size) {
- close(file);
- BLI_spin_unlock(&queue->spin);
- MEM_freeN(mem);
- return NULL;
- }
+ user.framenr = queue->cfra;
+
+ BKE_movieclip_filename_for_frame(clip, &user, name);
+
+ file = BLI_open(name, O_BINARY | O_RDONLY, 0);
+ if (file < 0) {
+ BLI_spin_unlock(&queue->spin);
+ return NULL;
+ }
+
+ size = BLI_file_descriptor_size(file);
+ if (size < 1) {
+ close(file);
+ BLI_spin_unlock(&queue->spin);
+ return NULL;
+ }
+
+ mem = MEM_mallocN(size, "movieclip proxy memory file");
+
+ if (read(file, mem, size) != size) {
+ close(file);
+ BLI_spin_unlock(&queue->spin);
+ MEM_freeN(mem);
+ return NULL;
+ }
+
+ *size_r = size;
+ *cfra_r = queue->cfra;
+
+ queue->cfra++;
+ close(file);
- *size_r = size;
- *cfra_r = queue->cfra;
+ *queue->do_update = 1;
+ *queue->progress = (float)(queue->cfra - queue->sfra) / (queue->efra - queue->sfra);
+ }
+ BLI_spin_unlock(&queue->spin);
+
+ return mem;
+}
- queue->cfra++;
- close(file);
-
- *queue->do_update = 1;
- *queue->progress = (float)(queue->cfra - queue->sfra) / (queue->efra - queue->sfra);
- }
- BLI_spin_unlock(&queue->spin);
-
- 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, int UNUSED(threadid))
{
- ProxyThread *data = (ProxyThread *)task_data;
- ProxyQueue *queue = (ProxyQueue *)BLI_task_pool_userdata(pool);
- unsigned char *mem;
- size_t size;
- int cfra;
+ ProxyThread *data = (ProxyThread *)task_data;
+ ProxyQueue *queue = (ProxyQueue *)BLI_task_pool_userdata(pool);
+ unsigned char *mem;
+ size_t size;
+ int cfra;
- while ((mem = proxy_thread_next_frame(queue, data->clip, &size, &cfra))) {
- ImBuf *ibuf;
+ while ((mem = proxy_thread_next_frame(queue, data->clip, &size, &cfra))) {
+ ImBuf *ibuf;
- ibuf = IMB_ibImageFromMemory(mem, size, IB_rect | IB_multilayer | IB_alphamode_detect,
- data->clip->colorspace_settings.name, "proxy frame");
+ ibuf = IMB_ibImageFromMemory(mem,
+ size,
+ IB_rect | IB_multilayer | IB_alphamode_detect,
+ data->clip->colorspace_settings.name,
+ "proxy frame");
- BKE_movieclip_build_proxy_frame_for_ibuf(data->clip, ibuf, NULL, cfra,
- data->build_sizes, data->build_count, false);
+ BKE_movieclip_build_proxy_frame_for_ibuf(
+ data->clip, ibuf, NULL, cfra, data->build_sizes, data->build_count, false);
- BKE_movieclip_build_proxy_frame_for_ibuf(data->clip, ibuf, data->distortion, cfra,
- data->build_undistort_sizes, data->build_undistort_count, true);
+ BKE_movieclip_build_proxy_frame_for_ibuf(data->clip,
+ ibuf,
+ data->distortion,
+ cfra,
+ data->build_undistort_sizes,
+ data->build_undistort_count,
+ true);
- IMB_freeImBuf(ibuf);
+ IMB_freeImBuf(ibuf);
- MEM_freeN(mem);
- }
+ MEM_freeN(mem);
+ }
}
-static void do_sequence_proxy(void *pjv, int *build_sizes, int build_count,
- int *build_undistort_sizes, int build_undistort_count,
- short *stop, short *do_update, float *progress)
+static void do_sequence_proxy(void *pjv,
+ int *build_sizes,
+ int build_count,
+ int *build_undistort_sizes,
+ int build_undistort_count,
+ short *stop,
+ short *do_update,
+ float *progress)
{
- 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 width, height;
- ProxyQueue queue;
-
- if (build_undistort_count) {
- BKE_movieclip_get_size(clip, NULL, &width, &height);
- }
+ 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 width, height;
+ ProxyQueue queue;
+
+ if (build_undistort_count) {
+ BKE_movieclip_get_size(clip, NULL, &width, &height);
+ }
- BLI_spin_init(&queue.spin);
+ BLI_spin_init(&queue.spin);
- queue.cfra = sfra;
- queue.sfra = sfra;
- queue.efra = efra;
- queue.stop = stop;
- queue.do_update = do_update;
- queue.progress = progress;
+ queue.cfra = sfra;
+ queue.sfra = sfra;
+ queue.efra = efra;
+ queue.stop = stop;
+ queue.do_update = do_update;
+ queue.progress = progress;
- task_pool = BLI_task_pool_create(task_scheduler, &queue);
- handles = MEM_callocN(sizeof(ProxyThread) * tot_thread,
- "proxy threaded handles");
- for (i = 0; i < tot_thread; i++) {
- ProxyThread *handle = &handles[i];
+ task_pool = BLI_task_pool_create(task_scheduler, &queue);
+ handles = MEM_callocN(sizeof(ProxyThread) * tot_thread, "proxy threaded handles");
+ for (i = 0; i < tot_thread; i++) {
+ ProxyThread *handle = &handles[i];
- handle->clip = clip;
+ handle->clip = clip;
- handle->build_count = build_count;
- handle->build_sizes = build_sizes;
+ handle->build_count = build_count;
+ handle->build_sizes = build_sizes;
- handle->build_undistort_count = build_undistort_count;
- handle->build_undistort_sizes = build_undistort_sizes;
+ handle->build_undistort_count = build_undistort_count;
+ handle->build_undistort_sizes = build_undistort_sizes;
- if (build_undistort_count) {
- handle->distortion = BKE_tracking_distortion_new(&clip->tracking,
- width, height);
- }
+ if (build_undistort_count) {
+ 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, TASK_PRIORITY_LOW);
+ }
- BLI_task_pool_work_and_wait(task_pool);
- BLI_task_pool_free(task_pool);
+ BLI_task_pool_work_and_wait(task_pool);
+ BLI_task_pool_free(task_pool);
- if (build_undistort_count) {
- for (i = 0; i < tot_thread; i++) {
- ProxyThread *handle = &handles[i];
- BKE_tracking_distortion_free(handle->distortion);
- }
- }
+ if (build_undistort_count) {
+ for (i = 0; i < tot_thread; i++) {
+ ProxyThread *handle = &handles[i];
+ BKE_tracking_distortion_free(handle->distortion);
+ }
+ }
- BLI_spin_end(&queue.spin);
- MEM_freeN(handles);
+ BLI_spin_end(&queue.spin);
+ MEM_freeN(handles);
}
static void proxy_startjob(void *pjv, short *stop, short *do_update, float *progress)
{
- ProxyJob *pj = pjv;
- MovieClip *clip = pj->clip;
-
- short size_flag;
- int build_sizes[4], build_count = 0;
- int build_undistort_sizes[4], build_undistort_count = 0;
-
- size_flag = clip->proxy.build_size_flag;
-
- build_count = proxy_bitflag_to_array(size_flag, build_sizes, 0);
- build_undistort_count = proxy_bitflag_to_array(size_flag, build_undistort_sizes, 1);
-
- if (clip->source == MCLIP_SRC_MOVIE) {
- do_movie_proxy(pjv, build_sizes, build_count, build_undistort_sizes,
- build_undistort_count, stop, do_update, progress);
- }
- else {
- do_sequence_proxy(pjv, build_sizes, build_count, build_undistort_sizes,
- build_undistort_count, stop, do_update, progress);
- }
+ ProxyJob *pj = pjv;
+ MovieClip *clip = pj->clip;
+
+ short size_flag;
+ int build_sizes[4], build_count = 0;
+ int build_undistort_sizes[4], build_undistort_count = 0;
+
+ size_flag = clip->proxy.build_size_flag;
+
+ build_count = proxy_bitflag_to_array(size_flag, build_sizes, 0);
+ build_undistort_count = proxy_bitflag_to_array(size_flag, build_undistort_sizes, 1);
+
+ if (clip->source == MCLIP_SRC_MOVIE) {
+ do_movie_proxy(pjv,
+ build_sizes,
+ build_count,
+ build_undistort_sizes,
+ build_undistort_count,
+ stop,
+ do_update,
+ progress);
+ }
+ else {
+ do_sequence_proxy(pjv,
+ build_sizes,
+ build_count,
+ build_undistort_sizes,
+ build_undistort_count,
+ stop,
+ do_update,
+ progress);
+ }
}
static void proxy_endjob(void *pjv)
{
- ProxyJob *pj = pjv;
+ ProxyJob *pj = pjv;
- if (pj->clip->anim)
- IMB_close_anim_proxies(pj->clip->anim);
+ if (pj->clip->anim)
+ IMB_close_anim_proxies(pj->clip->anim);
- if (pj->index_context)
- IMB_anim_index_rebuild_finish(pj->index_context, pj->stop);
+ if (pj->index_context)
+ IMB_anim_index_rebuild_finish(pj->index_context, pj->stop);
- if (pj->clip->source == MCLIP_SRC_MOVIE) {
- /* Timecode might have changed, so do a full reload to deal with this. */
- BKE_movieclip_reload(pj->main, pj->clip);
- }
- else {
- /* For image sequences we'll preserve original cache. */
- BKE_movieclip_clear_proxy_cache(pj->clip);
- }
+ if (pj->clip->source == MCLIP_SRC_MOVIE) {
+ /* Timecode might have changed, so do a full reload to deal with this. */
+ BKE_movieclip_reload(pj->main, pj->clip);
+ }
+ else {
+ /* For image sequences we'll preserve original cache. */
+ BKE_movieclip_clear_proxy_cache(pj->clip);
+ }
- WM_main_add_notifier(NC_MOVIECLIP | ND_DISPLAY, pj->clip);
+ WM_main_add_notifier(NC_MOVIECLIP | ND_DISPLAY, pj->clip);
}
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);
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
+ wmJob *wm_job;
+ ProxyJob *pj;
+ Scene *scene = CTX_data_scene(C);
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
- if ((clip->flag & MCLIP_USE_PROXY) == 0)
- return OPERATOR_CANCELLED;
+ if ((clip->flag & MCLIP_USE_PROXY) == 0)
+ return OPERATOR_CANCELLED;
- wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Building Proxies",
- WM_JOB_PROGRESS, WM_JOB_TYPE_CLIP_BUILD_PROXY);
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ sa,
+ "Building Proxies",
+ WM_JOB_PROGRESS,
+ WM_JOB_TYPE_CLIP_BUILD_PROXY);
- pj = MEM_callocN(sizeof(ProxyJob), "proxy rebuild job");
- pj->scene = scene;
- pj->main = CTX_data_main(C);
- pj->clip = clip;
- pj->clip_flag = clip->flag & MCLIP_TIMECODE_FLAGS;
+ pj = MEM_callocN(sizeof(ProxyJob), "proxy rebuild job");
+ pj->scene = scene;
+ pj->main = CTX_data_main(C);
+ pj->clip = clip;
+ pj->clip_flag = clip->flag & MCLIP_TIMECODE_FLAGS;
- if (clip->anim) {
- pj->index_context = IMB_anim_index_rebuild_context(clip->anim, clip->proxy.build_tc_flag,
- clip->proxy.build_size_flag, clip->proxy.quality,
- true, NULL);
- }
+ if (clip->anim) {
+ pj->index_context = IMB_anim_index_rebuild_context(clip->anim,
+ clip->proxy.build_tc_flag,
+ clip->proxy.build_size_flag,
+ clip->proxy.quality,
+ true,
+ NULL);
+ }
- WM_jobs_customdata_set(wm_job, pj, proxy_freejob);
- WM_jobs_timer(wm_job, 0.2, NC_MOVIECLIP | ND_DISPLAY, 0);
- WM_jobs_callbacks(wm_job, proxy_startjob, NULL, NULL, proxy_endjob);
+ WM_jobs_customdata_set(wm_job, pj, proxy_freejob);
+ WM_jobs_timer(wm_job, 0.2, NC_MOVIECLIP | ND_DISPLAY, 0);
+ WM_jobs_callbacks(wm_job, proxy_startjob, NULL, NULL, proxy_endjob);
- G.is_break = false;
- WM_jobs_start(CTX_wm_manager(C), wm_job);
+ G.is_break = false;
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(sa);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_rebuild_proxy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Rebuild Proxy and Timecode Indices";
- ot->idname = "CLIP_OT_rebuild_proxy";
- ot->description = "Rebuild all selected proxies and timecode indices in the background";
+ /* identifiers */
+ ot->name = "Rebuild Proxy and Timecode Indices";
+ ot->idname = "CLIP_OT_rebuild_proxy";
+ ot->description = "Rebuild all selected proxies and timecode indices in the background";
- /* api callbacks */
- ot->exec = clip_rebuild_proxy_exec;
- ot->poll = ED_space_clip_poll;
+ /* api callbacks */
+ ot->exec = clip_rebuild_proxy_exec;
+ ot->poll = ED_space_clip_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
}
/********************** mode set operator *********************/
static int mode_set_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- int mode = RNA_enum_get(op->ptr, "mode");
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ int mode = RNA_enum_get(op->ptr, "mode");
- sc->mode = mode;
+ sc->mode = mode;
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CLIP, NULL);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CLIP, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_mode_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Clip Mode";
- ot->description = "Set the clip interaction mode";
- ot->idname = "CLIP_OT_mode_set";
+ /* identifiers */
+ ot->name = "Set Clip Mode";
+ ot->description = "Set the clip interaction mode";
+ ot->idname = "CLIP_OT_mode_set";
- /* api callbacks */
- ot->exec = mode_set_exec;
+ /* api callbacks */
+ ot->exec = mode_set_exec;
- ot->poll = ED_space_clip_poll;
+ ot->poll = ED_space_clip_poll;
- /* properties */
- RNA_def_enum(ot->srna, "mode", rna_enum_clip_editor_mode_items, SC_MODE_TRACKING, "Mode", "");
+ /* properties */
+ RNA_def_enum(ot->srna, "mode", rna_enum_clip_editor_mode_items, SC_MODE_TRACKING, "Mode", "");
}
#ifdef WITH_INPUT_NDOF
@@ -1417,41 +1491,41 @@ void CLIP_OT_mode_set(wmOperatorType *ot)
static int clip_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- if (event->type != NDOF_MOTION)
- return OPERATOR_CANCELLED;
- else {
- SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
- float pan_vec[3];
+ if (event->type != NDOF_MOTION)
+ return OPERATOR_CANCELLED;
+ else {
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
+ float pan_vec[3];
- const wmNDOFMotionData *ndof = event->customdata;
- const float speed = NDOF_PIXELS_PER_SECOND;
+ const wmNDOFMotionData *ndof = event->customdata;
+ const float speed = NDOF_PIXELS_PER_SECOND;
- WM_event_ndof_pan_get(ndof, pan_vec, true);
+ WM_event_ndof_pan_get(ndof, pan_vec, true);
- mul_v2_fl(pan_vec, (speed * ndof->dt) / sc->zoom);
- pan_vec[2] *= -ndof->dt;
+ mul_v2_fl(pan_vec, (speed * ndof->dt) / sc->zoom);
+ pan_vec[2] *= -ndof->dt;
- sclip_zoom_set_factor(C, 1.0f + pan_vec[2], NULL);
- sc->xof += pan_vec[0];
- sc->yof += pan_vec[1];
+ sclip_zoom_set_factor(C, 1.0f + pan_vec[2], NULL);
+ sc->xof += pan_vec[0];
+ sc->yof += pan_vec[1];
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
}
void CLIP_OT_view_ndof(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "NDOF Pan/Zoom";
- ot->idname = "CLIP_OT_view_ndof";
- ot->description = "Use a 3D mouse device to pan/zoom the view";
+ /* identifiers */
+ ot->name = "NDOF Pan/Zoom";
+ ot->idname = "CLIP_OT_view_ndof";
+ ot->description = "Use a 3D mouse device to pan/zoom the view";
- /* api callbacks */
- ot->invoke = clip_view_ndof_invoke;
- ot->poll = ED_space_clip_view_clip_poll;
+ /* api callbacks */
+ ot->invoke = clip_view_ndof_invoke;
+ ot->poll = ED_space_clip_view_clip_poll;
}
#endif /* WITH_INPUT_NDOF */
@@ -1459,147 +1533,159 @@ void CLIP_OT_view_ndof(wmOperatorType *ot)
static int clip_prefetch_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- /* no running blender, remove handler and pass through */
- if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_wm_area(C), WM_JOB_TYPE_CLIP_PREFETCH))
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ /* no running blender, remove handler and pass through */
+ if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_wm_area(C), WM_JOB_TYPE_CLIP_PREFETCH))
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
- /* running render */
- switch (event->type) {
- case ESCKEY:
- return OPERATOR_RUNNING_MODAL;
- }
+ /* running render */
+ switch (event->type) {
+ case ESCKEY:
+ return OPERATOR_RUNNING_MODAL;
+ }
- return OPERATOR_PASS_THROUGH;
+ return OPERATOR_PASS_THROUGH;
}
static int clip_prefetch_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(_event))
{
- clip_start_prefetch_job(C);
+ clip_start_prefetch_job(C);
- /* add modal handler for ESC */
- WM_event_add_modal_handler(C, op);
+ /* add modal handler for ESC */
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void CLIP_OT_prefetch(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Prefetch Frames";
- ot->idname = "CLIP_OT_prefetch";
- ot->description = "Prefetch frames from disk for faster playback/tracking";
+ /* identifiers */
+ ot->name = "Prefetch Frames";
+ ot->idname = "CLIP_OT_prefetch";
+ ot->description = "Prefetch frames from disk for faster playback/tracking";
- /* api callbacks */
- ot->poll = ED_space_clip_view_clip_poll;
- ot->invoke = clip_prefetch_invoke;
- ot->modal = clip_prefetch_modal;
+ /* api callbacks */
+ ot->poll = ED_space_clip_view_clip_poll;
+ ot->invoke = clip_prefetch_invoke;
+ ot->modal = clip_prefetch_modal;
}
/********************** Set scene frames *********************/
static int clip_set_scene_frames_exec(bContext *C, wmOperator *UNUSED(op))
{
- MovieClip *clip = CTX_data_edit_movieclip(C);
- Scene *scene = CTX_data_scene(C);
- int clip_length;
+ MovieClip *clip = CTX_data_edit_movieclip(C);
+ Scene *scene = CTX_data_scene(C);
+ int clip_length;
- if (ELEM(NULL, scene, clip))
- return OPERATOR_CANCELLED;
+ if (ELEM(NULL, scene, clip))
+ return OPERATOR_CANCELLED;
- clip_length = BKE_movieclip_get_duration(clip);
+ clip_length = BKE_movieclip_get_duration(clip);
- scene->r.sfra = clip->start_frame;
- scene->r.efra = scene->r.sfra + clip_length - 1;
+ scene->r.sfra = clip->start_frame;
+ scene->r.efra = scene->r.sfra + clip_length - 1;
- scene->r.efra = max_ii(scene->r.sfra, scene->r.efra);
+ scene->r.efra = max_ii(scene->r.sfra, scene->r.efra);
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_set_scene_frames(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Scene Frames";
- ot->idname = "CLIP_OT_set_scene_frames";
- ot->description = "Set scene's start and end frame to match clip's start frame and length";
+ /* identifiers */
+ ot->name = "Set Scene Frames";
+ ot->idname = "CLIP_OT_set_scene_frames";
+ ot->description = "Set scene's start and end frame to match clip's start frame and length";
- /* api callbacks */
- ot->poll = ED_space_clip_view_clip_poll;
- ot->exec = clip_set_scene_frames_exec;
+ /* api callbacks */
+ ot->poll = ED_space_clip_view_clip_poll;
+ ot->exec = clip_set_scene_frames_exec;
}
/******************** set 3d cursor operator ********************/
static int clip_set_2d_cursor_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sclip = CTX_wm_space_clip(C);
- bool show_cursor = false;
+ SpaceClip *sclip = CTX_wm_space_clip(C);
+ bool show_cursor = false;
- show_cursor |= sclip->mode == SC_MODE_MASKEDIT;
- show_cursor |= sclip->around == V3D_AROUND_CURSOR;
+ show_cursor |= sclip->mode == SC_MODE_MASKEDIT;
+ show_cursor |= sclip->around == V3D_AROUND_CURSOR;
- if (!show_cursor) {
- return OPERATOR_CANCELLED;
- }
+ if (!show_cursor) {
+ return OPERATOR_CANCELLED;
+ }
- RNA_float_get_array(op->ptr, "location", sclip->cursor);
+ RNA_float_get_array(op->ptr, "location", sclip->cursor);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CLIP, NULL);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CLIP, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int clip_set_2d_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- SpaceClip *sclip = CTX_wm_space_clip(C);
- float location[2];
+ ARegion *ar = CTX_wm_region(C);
+ SpaceClip *sclip = CTX_wm_space_clip(C);
+ float location[2];
- ED_clip_mouse_pos(sclip, ar, event->mval, location);
- RNA_float_set_array(op->ptr, "location", location);
+ ED_clip_mouse_pos(sclip, ar, event->mval, location);
+ RNA_float_set_array(op->ptr, "location", location);
- return clip_set_2d_cursor_exec(C, op);
+ return clip_set_2d_cursor_exec(C, op);
}
void CLIP_OT_cursor_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set 2D Cursor";
- ot->description = "Set 2D cursor location";
- ot->idname = "CLIP_OT_cursor_set";
+ /* identifiers */
+ ot->name = "Set 2D Cursor";
+ ot->description = "Set 2D cursor location";
+ ot->idname = "CLIP_OT_cursor_set";
- /* api callbacks */
- ot->exec = clip_set_2d_cursor_exec;
- ot->invoke = clip_set_2d_cursor_invoke;
- ot->poll = ED_space_clip_poll;
+ /* api callbacks */
+ ot->exec = clip_set_2d_cursor_exec;
+ ot->invoke = clip_set_2d_cursor_invoke;
+ ot->poll = ED_space_clip_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location",
- "Cursor location in normalized clip coordinates", -10.0f, 10.0f);
+ /* properties */
+ RNA_def_float_vector(ot->srna,
+ "location",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Location",
+ "Cursor location in normalized clip coordinates",
+ -10.0f,
+ 10.0f);
}
/********************** macros *********************/
void ED_operatormacros_clip(void)
{
- wmOperatorType *ot;
- wmOperatorTypeMacro *otmacro;
-
- ot = WM_operatortype_append_macro("CLIP_OT_add_marker_move", "Add Marker and Move",
- "Add new marker and move it on movie", OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "CLIP_OT_add_marker");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_struct_idprops_unset(otmacro->ptr, "release_confirm");
-
- ot = WM_operatortype_append_macro("CLIP_OT_add_marker_slide", "Add Marker and Slide",
- "Add new marker and slide it with mouse until mouse button release",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "CLIP_OT_add_marker");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_boolean_set(otmacro->ptr, "release_confirm", true);
+ wmOperatorType *ot;
+ wmOperatorTypeMacro *otmacro;
+
+ ot = WM_operatortype_append_macro("CLIP_OT_add_marker_move",
+ "Add Marker and Move",
+ "Add new marker and move it on movie",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "CLIP_OT_add_marker");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_struct_idprops_unset(otmacro->ptr, "release_confirm");
+
+ ot = WM_operatortype_append_macro(
+ "CLIP_OT_add_marker_slide",
+ "Add Marker and Slide",
+ "Add new marker and slide it with mouse until mouse button release",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "CLIP_OT_add_marker");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_boolean_set(otmacro->ptr, "release_confirm", true);
}
diff --git a/source/blender/editors/space_clip/clip_toolbar.c b/source/blender/editors/space_clip/clip_toolbar.c
index 3f16982e2c6..acb05e7d542 100644
--- a/source/blender/editors/space_clip/clip_toolbar.c
+++ b/source/blender/editors/space_clip/clip_toolbar.c
@@ -55,118 +55,118 @@
ARegion *ED_clip_has_properties_region(ScrArea *sa)
{
- ARegion *ar, *arnew;
+ ARegion *ar, *arnew;
- ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
- if (ar)
- return ar;
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
+ if (ar)
+ return ar;
- /* add subdiv level; after header */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+ /* add subdiv level; after header */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
- /* is error! */
- if (ar == NULL)
- return NULL;
+ /* is error! */
+ if (ar == NULL)
+ return NULL;
- arnew = MEM_callocN(sizeof(ARegion), "clip properties region");
+ arnew = MEM_callocN(sizeof(ARegion), "clip properties region");
- BLI_insertlinkafter(&sa->regionbase, ar, arnew);
- arnew->regiontype = RGN_TYPE_UI;
- arnew->alignment = RGN_ALIGN_RIGHT;
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype = RGN_TYPE_UI;
+ arnew->alignment = RGN_ALIGN_RIGHT;
- arnew->flag = RGN_FLAG_HIDDEN;
+ arnew->flag = RGN_FLAG_HIDDEN;
- return arnew;
+ return arnew;
}
static bool properties_poll(bContext *C)
{
- return (CTX_wm_space_clip(C) != NULL);
+ return (CTX_wm_space_clip(C) != NULL);
}
static int properties_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = ED_clip_has_properties_region(sa);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = ED_clip_has_properties_region(sa);
- if (ar && ar->alignment != RGN_ALIGN_NONE)
- ED_region_toggle_hidden(C, ar);
+ if (ar && ar->alignment != RGN_ALIGN_NONE)
+ ED_region_toggle_hidden(C, ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_properties(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Sidebar";
- ot->description = "Toggle the properties region visibility";
- ot->idname = "CLIP_OT_properties";
-
- /* api callbacks */
- ot->exec = properties_exec;
- ot->poll = properties_poll;
+ /* identifiers */
+ ot->name = "Toggle Sidebar";
+ ot->description = "Toggle the properties region visibility";
+ ot->idname = "CLIP_OT_properties";
+
+ /* api callbacks */
+ ot->exec = properties_exec;
+ ot->poll = properties_poll;
}
/************************** tools ******************************/
static ARegion *clip_has_tools_region(ScrArea *sa)
{
- ARegion *ar, *artool = NULL, *arhead;
+ ARegion *ar, *artool = NULL, *arhead;
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_TOOLS)
- artool = ar;
- }
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_TOOLS)
+ artool = ar;
+ }
- /* tool region hide/unhide also hides props */
- if (artool) {
- return artool;
- }
+ /* tool region hide/unhide also hides props */
+ if (artool) {
+ return artool;
+ }
- if (artool == NULL) {
- /* add subdiv level; after header */
- arhead = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+ if (artool == NULL) {
+ /* add subdiv level; after header */
+ arhead = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
- /* is error! */
- if (arhead == NULL)
- return NULL;
+ /* is error! */
+ if (arhead == NULL)
+ return NULL;
- artool = MEM_callocN(sizeof(ARegion), "clip tools region");
+ artool = MEM_callocN(sizeof(ARegion), "clip tools region");
- BLI_insertlinkafter(&sa->regionbase, arhead, artool);
- artool->regiontype = RGN_TYPE_TOOLS;
- artool->alignment = RGN_ALIGN_LEFT;
+ BLI_insertlinkafter(&sa->regionbase, arhead, artool);
+ artool->regiontype = RGN_TYPE_TOOLS;
+ artool->alignment = RGN_ALIGN_LEFT;
- artool->flag = RGN_FLAG_HIDDEN;
- }
+ artool->flag = RGN_FLAG_HIDDEN;
+ }
- return artool;
+ return artool;
}
static bool tools_poll(bContext *C)
{
- return (CTX_wm_space_clip(C) != NULL);
+ return (CTX_wm_space_clip(C) != NULL);
}
static int tools_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = clip_has_tools_region(sa);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = clip_has_tools_region(sa);
- if (ar && ar->alignment != RGN_ALIGN_NONE)
- ED_region_toggle_hidden(C, ar);
+ if (ar && ar->alignment != RGN_ALIGN_NONE)
+ ED_region_toggle_hidden(C, ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_tools(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Toolbar";
- ot->description = "Toggle clip tools panel";
- ot->idname = "CLIP_OT_tools";
-
- /* api callbacks */
- ot->exec = tools_exec;
- ot->poll = tools_poll;
+ /* identifiers */
+ ot->name = "Toggle Toolbar";
+ ot->description = "Toggle clip tools panel";
+ ot->idname = "CLIP_OT_tools";
+
+ /* api callbacks */
+ ot->exec = tools_exec;
+ ot->poll = tools_poll;
}
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index 882cafae5f6..37a28e6189a 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -50,245 +50,259 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "clip_intern.h" // own include
+#include "clip_intern.h" // own include
void clip_graph_tracking_values_iterate_track(
- SpaceClip *sc, MovieTrackingTrack *track, void *userdata,
- void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord,
- int scene_framenr, float val),
- void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord, bool is_point),
- void (*segment_end)(void *userdata, int coord))
+ SpaceClip *sc,
+ MovieTrackingTrack *track,
+ void *userdata,
+ void (*func)(void *userdata,
+ MovieTrackingTrack *track,
+ MovieTrackingMarker *marker,
+ int coord,
+ int scene_framenr,
+ float val),
+ void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord, bool is_point),
+ void (*segment_end)(void *userdata, int coord))
{
- MovieClip *clip = ED_space_clip_get_clip(sc);
- int width, height, coord;
-
- BKE_movieclip_get_size(clip, &sc->user, &width, &height);
-
- for (coord = 0; coord < 2; coord++) {
- int i, prevfra = track->markers[0].framenr;
- bool open = false;
- float prevval = 0.0f;
-
- for (i = 0; i < track->markersnr; i++) {
- MovieTrackingMarker *marker = &track->markers[i];
- float val;
-
- if (marker->flag & MARKER_DISABLED) {
- if (open) {
- if (segment_end)
- segment_end(userdata, coord);
-
- open = false;
- }
-
- continue;
- }
-
- if (!open) {
- if (segment_start) {
- if ((i + 1) == track->markersnr) {
- segment_start(userdata, track, coord, true);
- }
- else {
- segment_start(userdata, track, coord, (track->markers[i + 1].flag & MARKER_DISABLED));
- }
- }
-
- open = true;
- prevval = marker->pos[coord];
- }
-
- /* value is a pixels per frame speed */
- val = (marker->pos[coord] - prevval) * ((coord == 0) ? (width) : (height));
- val /= marker->framenr - prevfra;
-
- if (func) {
- int scene_framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr);
-
- func(userdata, track, marker, coord, scene_framenr, val);
- }
-
- prevval = marker->pos[coord];
- prevfra = marker->framenr;
- }
-
- if (open) {
- if (segment_end)
- segment_end(userdata, coord);
- }
- }
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ int width, height, coord;
+
+ BKE_movieclip_get_size(clip, &sc->user, &width, &height);
+
+ for (coord = 0; coord < 2; coord++) {
+ int i, prevfra = track->markers[0].framenr;
+ bool open = false;
+ float prevval = 0.0f;
+
+ for (i = 0; i < track->markersnr; i++) {
+ MovieTrackingMarker *marker = &track->markers[i];
+ float val;
+
+ if (marker->flag & MARKER_DISABLED) {
+ if (open) {
+ if (segment_end)
+ segment_end(userdata, coord);
+
+ open = false;
+ }
+
+ continue;
+ }
+
+ if (!open) {
+ if (segment_start) {
+ if ((i + 1) == track->markersnr) {
+ segment_start(userdata, track, coord, true);
+ }
+ else {
+ segment_start(userdata, track, coord, (track->markers[i + 1].flag & MARKER_DISABLED));
+ }
+ }
+
+ open = true;
+ prevval = marker->pos[coord];
+ }
+
+ /* value is a pixels per frame speed */
+ val = (marker->pos[coord] - prevval) * ((coord == 0) ? (width) : (height));
+ val /= marker->framenr - prevfra;
+
+ if (func) {
+ int scene_framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr);
+
+ func(userdata, track, marker, coord, scene_framenr, val);
+ }
+
+ prevval = marker->pos[coord];
+ prevfra = marker->framenr;
+ }
+
+ if (open) {
+ if (segment_end)
+ segment_end(userdata, coord);
+ }
+ }
}
void clip_graph_tracking_values_iterate(
- SpaceClip *sc, bool selected_only, bool include_hidden, void *userdata,
- void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker,
- int coord, int scene_framenr, float val),
- void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord, bool is_point),
- void (*segment_end)(void *userdata, int coord))
+ SpaceClip *sc,
+ bool selected_only,
+ bool include_hidden,
+ void *userdata,
+ void (*func)(void *userdata,
+ MovieTrackingTrack *track,
+ MovieTrackingMarker *marker,
+ int coord,
+ int scene_framenr,
+ float val),
+ void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord, bool is_point),
+ void (*segment_end)(void *userdata, int coord))
{
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- MovieTrackingTrack *track;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ MovieTrackingTrack *track;
- for (track = tracksbase->first; track; track = track->next) {
- if (!include_hidden && (track->flag & TRACK_HIDDEN) != 0)
- continue;
+ for (track = tracksbase->first; track; track = track->next) {
+ if (!include_hidden && (track->flag & TRACK_HIDDEN) != 0)
+ continue;
- if (selected_only && !TRACK_SELECTED(track))
- continue;
+ if (selected_only && !TRACK_SELECTED(track))
+ continue;
- clip_graph_tracking_values_iterate_track(sc, track, userdata, func, segment_start, segment_end);
- }
+ clip_graph_tracking_values_iterate_track(
+ sc, track, userdata, func, segment_start, segment_end);
+ }
}
-void clip_graph_tracking_iterate(SpaceClip *sc, bool selected_only, bool include_hidden, void *userdata,
+void clip_graph_tracking_iterate(SpaceClip *sc,
+ bool selected_only,
+ bool include_hidden,
+ void *userdata,
void (*func)(void *userdata, MovieTrackingMarker *marker))
{
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- MovieTrackingTrack *track;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ MovieTrackingTrack *track;
- for (track = tracksbase->first; track; track = track->next) {
- int i;
+ for (track = tracksbase->first; track; track = track->next) {
+ int i;
- if (!include_hidden && (track->flag & TRACK_HIDDEN) != 0)
- continue;
+ if (!include_hidden && (track->flag & TRACK_HIDDEN) != 0)
+ continue;
- if (selected_only && !TRACK_SELECTED(track))
- continue;
+ if (selected_only && !TRACK_SELECTED(track))
+ continue;
- for (i = 0; i < track->markersnr; i++) {
- MovieTrackingMarker *marker = &track->markers[i];
+ for (i = 0; i < track->markersnr; i++) {
+ MovieTrackingMarker *marker = &track->markers[i];
- if (marker->flag & MARKER_DISABLED)
- continue;
+ if (marker->flag & MARKER_DISABLED)
+ continue;
- if (func)
- func(userdata, marker);
- }
- }
+ if (func)
+ func(userdata, marker);
+ }
+ }
}
void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track)
{
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- bool has_bundle = false;
- const bool used_for_stabilization =
- (track->flag & (TRACK_USE_2D_STAB | TRACK_USE_2D_STAB_ROT)) != 0;
- if (track == act_track) {
- tracking->act_track = NULL;
- }
- /* Handle reconstruction display in 3d viewport. */
- if (track->flag & TRACK_HAS_BUNDLE) {
- has_bundle = true;
- }
- /* Make sure no plane will use freed track */
- BKE_tracking_plane_tracks_remove_point_track(tracking, track);
- /* Delete f-curves associated with the track (such as weight, i.e.) */
- /* Escaped object name, escaped track name, rest of the path. */
- char rna_path[MAX_NAME * 4 + 64];
- BKE_tracking_get_rna_path_for_track(tracking,
- track,
- rna_path, sizeof(rna_path));
- if (BKE_animdata_fix_paths_remove(&clip->id, rna_path)) {
- DEG_relations_tag_update(CTX_data_main(C));
- }
- /* Delete track itself. */
- BKE_tracking_track_free(track);
- BLI_freelinkN(tracksbase, track);
- /* Send notifiers. */
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
- if (used_for_stabilization) {
- WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
- }
- /* Inform dependency graph. */
- DEG_id_tag_update(&clip->id, 0);
- if (has_bundle) {
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- }
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ bool has_bundle = false;
+ const bool used_for_stabilization = (track->flag &
+ (TRACK_USE_2D_STAB | TRACK_USE_2D_STAB_ROT)) != 0;
+ if (track == act_track) {
+ tracking->act_track = NULL;
+ }
+ /* Handle reconstruction display in 3d viewport. */
+ if (track->flag & TRACK_HAS_BUNDLE) {
+ has_bundle = true;
+ }
+ /* Make sure no plane will use freed track */
+ BKE_tracking_plane_tracks_remove_point_track(tracking, track);
+ /* Delete f-curves associated with the track (such as weight, i.e.) */
+ /* Escaped object name, escaped track name, rest of the path. */
+ char rna_path[MAX_NAME * 4 + 64];
+ BKE_tracking_get_rna_path_for_track(tracking, track, rna_path, sizeof(rna_path));
+ if (BKE_animdata_fix_paths_remove(&clip->id, rna_path)) {
+ DEG_relations_tag_update(CTX_data_main(C));
+ }
+ /* Delete track itself. */
+ BKE_tracking_track_free(track);
+ BLI_freelinkN(tracksbase, track);
+ /* Send notifiers. */
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+ if (used_for_stabilization) {
+ WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
+ }
+ /* Inform dependency graph. */
+ DEG_id_tag_update(&clip->id, 0);
+ if (has_bundle) {
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ }
}
-void clip_delete_marker(bContext *C, MovieClip *clip, MovieTrackingTrack *track,
+void clip_delete_marker(bContext *C,
+ MovieClip *clip,
+ MovieTrackingTrack *track,
MovieTrackingMarker *marker)
{
- if (track->markersnr == 1) {
- clip_delete_track(C, clip, track);
- }
- else {
- BKE_tracking_marker_delete(track, marker->framenr);
-
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
- }
+ if (track->markersnr == 1) {
+ clip_delete_track(C, clip, track);
+ }
+ else {
+ BKE_tracking_marker_delete(track, marker->framenr);
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+ }
}
-void clip_delete_plane_track(bContext *C,
- MovieClip *clip,
- MovieTrackingPlaneTrack *plane_track)
+void clip_delete_plane_track(bContext *C, MovieClip *clip, MovieTrackingPlaneTrack *plane_track)
{
- MovieTracking *tracking = &clip->tracking;
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- /* Delete f-curves associated with the track (such as weight, i.e.) */
- /* Escaped object name, escaped track name, rest of the path. */
- char rna_path[MAX_NAME * 4 + 64];
- BKE_tracking_get_rna_path_for_plane_track(tracking,
- plane_track,
- rna_path, sizeof(rna_path));
- if (BKE_animdata_fix_paths_remove(&clip->id, rna_path)) {
- DEG_relations_tag_update(CTX_data_main(C));
- }
- /* Delete the plane track itself. */
- BKE_tracking_plane_track_free(plane_track);
- BLI_freelinkN(plane_tracks_base, plane_track);
- /* TODO(sergey): Any notifiers to be sent here? */
- (void) C;
- /* Inform dependency graph. */
- DEG_id_tag_update(&clip->id, 0);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ /* Delete f-curves associated with the track (such as weight, i.e.) */
+ /* Escaped object name, escaped track name, rest of the path. */
+ char rna_path[MAX_NAME * 4 + 64];
+ BKE_tracking_get_rna_path_for_plane_track(tracking, plane_track, rna_path, sizeof(rna_path));
+ if (BKE_animdata_fix_paths_remove(&clip->id, rna_path)) {
+ DEG_relations_tag_update(CTX_data_main(C));
+ }
+ /* Delete the plane track itself. */
+ BKE_tracking_plane_track_free(plane_track);
+ BLI_freelinkN(plane_tracks_base, plane_track);
+ /* TODO(sergey): Any notifiers to be sent here? */
+ (void)C;
+ /* Inform dependency graph. */
+ DEG_id_tag_update(&clip->id, 0);
}
void clip_view_center_to_point(SpaceClip *sc, float x, float y)
{
- int width, height;
- float aspx, aspy;
+ int width, height;
+ float aspx, aspy;
- ED_space_clip_get_size(sc, &width, &height);
- ED_space_clip_get_aspect(sc, &aspx, &aspy);
+ ED_space_clip_get_size(sc, &width, &height);
+ ED_space_clip_get_aspect(sc, &aspx, &aspy);
- sc->xof = (x - 0.5f) * width * aspx;
- sc->yof = (y - 0.5f) * height * aspy;
+ sc->xof = (x - 0.5f) * width * aspx;
+ sc->yof = (y - 0.5f) * height * aspy;
}
void clip_draw_sfra_efra(View2D *v2d, Scene *scene)
{
- UI_view2d_view_ortho(v2d);
+ UI_view2d_view_ortho(v2d);
- /* currently clip editor supposes that editing clip length is equal to scene frame range */
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
+ /* currently clip editor supposes that editing clip length is equal to scene frame range */
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
- immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)SFRA, v2d->cur.ymax);
- immRectf(pos, (float)EFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)SFRA, v2d->cur.ymax);
+ immRectf(pos, (float)EFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
- GPU_blend(false);
+ GPU_blend(false);
- immUniformThemeColorShade(TH_BACK, -60);
+ immUniformThemeColorShade(TH_BACK, -60);
- /* thin lines where the actual frames are */
- GPU_line_width(1.0f);
+ /* thin lines where the actual frames are */
+ GPU_line_width(1.0f);
- immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, (float)SFRA, v2d->cur.ymin);
- immVertex2f(pos, (float)SFRA, v2d->cur.ymax);
- immVertex2f(pos, (float)EFRA, v2d->cur.ymin);
- immVertex2f(pos, (float)EFRA, v2d->cur.ymax);
- immEnd();
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex2f(pos, (float)SFRA, v2d->cur.ymin);
+ immVertex2f(pos, (float)SFRA, v2d->cur.ymax);
+ immVertex2f(pos, (float)EFRA, v2d->cur.ymin);
+ immVertex2f(pos, (float)EFRA, v2d->cur.ymax);
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
}
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index b84a5fc90ed..7c62af80a0f 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -27,7 +27,7 @@
#include "DNA_scene_types.h"
#include "DNA_mask_types.h"
#include "DNA_movieclip_types.h"
-#include "DNA_view3d_types.h" /* for pivot point */
+#include "DNA_view3d_types.h" /* for pivot point */
#include "MEM_guardedalloc.h"
@@ -50,7 +50,7 @@
#include "ED_select_utils.h"
#include "ED_clip.h"
#include "ED_transform.h"
-#include "ED_uvedit.h" /* just for ED_image_draw_cursor */
+#include "ED_uvedit.h" /* just for ED_image_draw_cursor */
#include "IMB_imbuf.h"
@@ -67,725 +67,730 @@
#include "RNA_access.h"
+#include "clip_intern.h" /* own include */
-#include "clip_intern.h" /* own include */
-
-static void init_preview_region(const Scene *scene, const ScrArea *sa, const SpaceClip *sc, ARegion *ar)
+static void init_preview_region(const Scene *scene,
+ const ScrArea *sa,
+ const SpaceClip *sc,
+ ARegion *ar)
{
- ar->regiontype = RGN_TYPE_PREVIEW;
- ar->alignment = RGN_ALIGN_TOP;
- ar->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_SCALE_HORIZONTAL);
- 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;
- }
- 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;
-
- ar->v2d.cur = ar->v2d.tot;
-
- ar->v2d.min[0] = FLT_MIN;
- ar->v2d.min[1] = FLT_MIN;
-
- ar->v2d.max[0] = MAXFRAMEF;
- ar->v2d.max[1] = FLT_MAX;
-
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
- ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL);
-
- ar->v2d.minzoom = 0.0f;
- ar->v2d.maxzoom = 0.0f;
- ar->v2d.keepzoom = 0;
- ar->v2d.keepofs = 0;
- ar->v2d.align = 0;
- ar->v2d.flag = 0;
-
- ar->v2d.keeptot = 0;
- }
+ ar->regiontype = RGN_TYPE_PREVIEW;
+ ar->alignment = RGN_ALIGN_TOP;
+ ar->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_SCALE_HORIZONTAL);
+ 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;
+ }
+ 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;
+
+ ar->v2d.cur = ar->v2d.tot;
+
+ ar->v2d.min[0] = FLT_MIN;
+ ar->v2d.min[1] = FLT_MIN;
+
+ ar->v2d.max[0] = MAXFRAMEF;
+ ar->v2d.max[1] = FLT_MAX;
+
+ ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
+ ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL);
+
+ ar->v2d.minzoom = 0.0f;
+ ar->v2d.maxzoom = 0.0f;
+ ar->v2d.keepzoom = 0;
+ ar->v2d.keepofs = 0;
+ ar->v2d.align = 0;
+ ar->v2d.flag = 0;
+
+ ar->v2d.keeptot = 0;
+ }
}
static void reinit_preview_region(const bContext *C, ARegion *ar)
{
- Scene *scene = CTX_data_scene(C);
- ScrArea *sa = 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);
- }
- else {
- if (ar->v2d.flag & V2D_VIEWSYNC_AREA_VERTICAL)
- init_preview_region(scene, sa, sc, ar);
- }
+ Scene *scene = CTX_data_scene(C);
+ ScrArea *sa = 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);
+ }
+ else {
+ if (ar->v2d.flag & V2D_VIEWSYNC_AREA_VERTICAL)
+ init_preview_region(scene, sa, sc, ar);
+ }
}
static ARegion *ED_clip_has_preview_region(const bContext *C, ScrArea *sa)
{
- ARegion *ar, *arnew;
+ ARegion *ar, *arnew;
- ar = BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW);
- if (ar)
- return ar;
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW);
+ if (ar)
+ return ar;
- /* add subdiv level; after header */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ /* add subdiv level; after header */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- /* is error! */
- if (ar == NULL)
- return NULL;
+ /* is error! */
+ if (ar == NULL)
+ return NULL;
- arnew = MEM_callocN(sizeof(ARegion), "clip preview region");
+ 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(&sa->regionbase, ar, arnew);
+ init_preview_region(CTX_data_scene(C), sa, CTX_wm_space_clip(C), arnew);
- return arnew;
+ return arnew;
}
static ARegion *ED_clip_has_channels_region(ScrArea *sa)
{
- ARegion *ar, *arnew;
+ ARegion *ar, *arnew;
- ar = BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS);
- if (ar)
- return ar;
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS);
+ if (ar)
+ return ar;
- /* add subdiv level; after header */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW);
+ /* add subdiv level; after header */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW);
- /* is error! */
- if (ar == NULL)
- return NULL;
+ /* is error! */
+ if (ar == NULL)
+ return NULL;
- arnew = MEM_callocN(sizeof(ARegion), "clip channels region");
+ arnew = MEM_callocN(sizeof(ARegion), "clip channels region");
- BLI_insertlinkbefore(&sa->regionbase, ar, arnew);
- arnew->regiontype = RGN_TYPE_CHANNELS;
- arnew->alignment = RGN_ALIGN_LEFT;
+ BLI_insertlinkbefore(&sa->regionbase, ar, arnew);
+ arnew->regiontype = RGN_TYPE_CHANNELS;
+ arnew->alignment = RGN_ALIGN_LEFT;
- arnew->v2d.scroll = V2D_SCROLL_BOTTOM;
- arnew->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
+ arnew->v2d.scroll = V2D_SCROLL_BOTTOM;
+ arnew->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
- return arnew;
+ return arnew;
}
static void clip_scopes_tag_refresh(ScrArea *sa)
{
- SpaceClip *sc = (SpaceClip *)sa->spacedata.first;
- ARegion *ar;
+ SpaceClip *sc = (SpaceClip *)sa->spacedata.first;
+ ARegion *ar;
- if (sc->mode != SC_MODE_TRACKING)
- return;
+ 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)
- 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)
+ return;
+ }
- sc->scopes.ok = false;
+ sc->scopes.ok = false;
}
static void clip_scopes_check_gpencil_change(ScrArea *sa)
{
- SpaceClip *sc = (SpaceClip *)sa->spacedata.first;
+ SpaceClip *sc = (SpaceClip *)sa->spacedata.first;
- if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
- clip_scopes_tag_refresh(sa);
- }
+ if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
+ clip_scopes_tag_refresh(sa);
+ }
}
static void clip_area_sync_frame_from_scene(ScrArea *sa, Scene *scene)
{
- SpaceClip *space_clip = (SpaceClip *)sa->spacedata.first;
- BKE_movieclip_user_set_frame(&space_clip->user, scene->r.cfra);
+ SpaceClip *space_clip = (SpaceClip *)sa->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)
{
- ARegion *ar;
- SpaceClip *sc;
+ ARegion *ar;
+ SpaceClip *sc;
- sc = MEM_callocN(sizeof(SpaceClip), "initclip");
- sc->spacetype = SPACE_CLIP;
- sc->flag = SC_SHOW_MARKER_PATTERN | SC_SHOW_TRACK_PATH |
- SC_SHOW_GRAPH_TRACKS_MOTION | SC_SHOW_GRAPH_FRAMES | SC_SHOW_ANNOTATION;
- sc->zoom = 1.0f;
- sc->path_length = 20;
- sc->scopes.track_preview_height = 120;
- sc->around = V3D_AROUND_LOCAL_ORIGINS;
+ sc = MEM_callocN(sizeof(SpaceClip), "initclip");
+ sc->spacetype = SPACE_CLIP;
+ sc->flag = SC_SHOW_MARKER_PATTERN | SC_SHOW_TRACK_PATH | SC_SHOW_GRAPH_TRACKS_MOTION |
+ SC_SHOW_GRAPH_FRAMES | SC_SHOW_ANNOTATION;
+ sc->zoom = 1.0f;
+ sc->path_length = 20;
+ sc->scopes.track_preview_height = 120;
+ sc->around = V3D_AROUND_LOCAL_ORIGINS;
- /* header */
- ar = MEM_callocN(sizeof(ARegion), "header for clip");
+ /* header */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_HEADER;
+ ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
- /* tools view */
- ar = MEM_callocN(sizeof(ARegion), "tools for clip");
+ /* tools view */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_TOOLS;
+ ar->alignment = RGN_ALIGN_LEFT;
- /* properties view */
- ar = MEM_callocN(sizeof(ARegion), "properties for clip");
+ /* properties view */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_UI;
+ ar->alignment = RGN_ALIGN_RIGHT;
- /* channels view */
- ar = MEM_callocN(sizeof(ARegion), "channels for clip");
+ /* channels view */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_CHANNELS;
+ ar->alignment = RGN_ALIGN_LEFT;
- ar->v2d.scroll = V2D_SCROLL_BOTTOM;
- ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
+ ar->v2d.scroll = V2D_SCROLL_BOTTOM;
+ ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
- /* preview view */
- ar = MEM_callocN(sizeof(ARegion), "preview for clip");
+ /* preview view */
+ ar = MEM_callocN(sizeof(ARegion), "preview for clip");
- BLI_addtail(&sc->regionbase, ar);
- init_preview_region(scene, sa, sc, ar);
+ BLI_addtail(&sc->regionbase, ar);
+ init_preview_region(scene, sa, sc, ar);
- /* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for clip");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for clip");
- BLI_addtail(&sc->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&sc->regionbase, ar);
+ ar->regiontype = RGN_TYPE_WINDOW;
- return (SpaceLink *) sc;
+ return (SpaceLink *)sc;
}
/* not spacelink itself */
static void clip_free(SpaceLink *sl)
{
- SpaceClip *sc = (SpaceClip *) sl;
+ SpaceClip *sc = (SpaceClip *)sl;
- sc->clip = NULL;
+ sc->clip = NULL;
- if (sc->scopes.track_preview)
- IMB_freeImBuf(sc->scopes.track_preview);
+ if (sc->scopes.track_preview)
+ IMB_freeImBuf(sc->scopes.track_preview);
- if (sc->scopes.track_search)
- IMB_freeImBuf(sc->scopes.track_search);
+ if (sc->scopes.track_search)
+ IMB_freeImBuf(sc->scopes.track_search);
}
/* spacetype; init callback */
static void clip_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
{
- ListBase *lb = WM_dropboxmap_find("Clip", SPACE_CLIP, 0);
+ ListBase *lb = WM_dropboxmap_find("Clip", SPACE_CLIP, 0);
- /* add drop boxes */
- WM_event_add_dropbox_handler(&sa->handlers, lb);
+ /* add drop boxes */
+ WM_event_add_dropbox_handler(&sa->handlers, lb);
}
static SpaceLink *clip_duplicate(SpaceLink *sl)
{
- SpaceClip *scn = MEM_dupallocN(sl);
+ SpaceClip *scn = MEM_dupallocN(sl);
- /* clear or remove stuff from old */
- scn->scopes.track_search = NULL;
- scn->scopes.track_preview = NULL;
- scn->scopes.ok = false;
+ /* clear or remove stuff from old */
+ scn->scopes.track_search = NULL;
+ scn->scopes.track_preview = NULL;
+ scn->scopes.ok = false;
- return (SpaceLink *)scn;
+ return (SpaceLink *)scn;
}
static void clip_listener(wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, Scene *scene)
{
- /* context changes */
- switch (wmn->category) {
- case NC_SCENE:
- switch (wmn->data) {
- case ND_FRAME:
- clip_scopes_tag_refresh(sa);
- ATTR_FALLTHROUGH;
-
- case ND_FRAME_RANGE:
- ED_area_tag_redraw(sa);
- break;
- }
- break;
- case NC_MOVIECLIP:
- switch (wmn->data) {
- case ND_DISPLAY:
- case ND_SELECT:
- clip_scopes_tag_refresh(sa);
- ED_area_tag_redraw(sa);
- break;
- }
- switch (wmn->action) {
- case NA_REMOVED:
- case NA_EDITED:
- case NA_EVALUATED:
- /* fall-through */
-
- case NA_SELECTED:
- clip_scopes_tag_refresh(sa);
- ED_area_tag_redraw(sa);
- break;
- }
- break;
- case NC_MASK:
- switch (wmn->data) {
- case ND_SELECT:
- case ND_DATA:
- case ND_DRAW:
- ED_area_tag_redraw(sa);
- break;
- }
- switch (wmn->action) {
- case NA_SELECTED:
- ED_area_tag_redraw(sa);
- break;
- case NA_EDITED:
- ED_area_tag_redraw(sa);
- break;
- }
- break;
- case NC_GEOM:
- switch (wmn->data) {
- case ND_SELECT:
- clip_scopes_tag_refresh(sa);
- ED_area_tag_redraw(sa);
- break;
- }
- break;
- case NC_SCREEN:
- switch (wmn->data) {
- case ND_ANIMPLAY:
- ED_area_tag_redraw(sa);
- break;
- case ND_LAYOUTSET:
- clip_area_sync_frame_from_scene(sa, scene);
- break;
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_CLIP) {
- clip_scopes_tag_refresh(sa);
- ED_area_tag_redraw(sa);
- }
- break;
- case NC_GPENCIL:
- if (wmn->action == NA_EDITED) {
- clip_scopes_check_gpencil_change(sa);
- ED_area_tag_redraw(sa);
- }
- else if (wmn->data & ND_GPENCIL_EDITMODE) {
- ED_area_tag_redraw(sa);
- }
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_FRAME:
+ clip_scopes_tag_refresh(sa);
+ ATTR_FALLTHROUGH;
+
+ case ND_FRAME_RANGE:
+ ED_area_tag_redraw(sa);
+ break;
+ }
+ break;
+ case NC_MOVIECLIP:
+ switch (wmn->data) {
+ case ND_DISPLAY:
+ case ND_SELECT:
+ clip_scopes_tag_refresh(sa);
+ ED_area_tag_redraw(sa);
+ break;
+ }
+ switch (wmn->action) {
+ case NA_REMOVED:
+ case NA_EDITED:
+ case NA_EVALUATED:
+ /* fall-through */
+
+ case NA_SELECTED:
+ clip_scopes_tag_refresh(sa);
+ ED_area_tag_redraw(sa);
+ break;
+ }
+ break;
+ case NC_MASK:
+ switch (wmn->data) {
+ case ND_SELECT:
+ case ND_DATA:
+ case ND_DRAW:
+ ED_area_tag_redraw(sa);
+ break;
+ }
+ switch (wmn->action) {
+ case NA_SELECTED:
+ ED_area_tag_redraw(sa);
+ break;
+ case NA_EDITED:
+ ED_area_tag_redraw(sa);
+ break;
+ }
+ break;
+ case NC_GEOM:
+ switch (wmn->data) {
+ case ND_SELECT:
+ clip_scopes_tag_refresh(sa);
+ ED_area_tag_redraw(sa);
+ break;
+ }
+ break;
+ case NC_SCREEN:
+ switch (wmn->data) {
+ case ND_ANIMPLAY:
+ ED_area_tag_redraw(sa);
+ break;
+ case ND_LAYOUTSET:
+ clip_area_sync_frame_from_scene(sa, scene);
+ break;
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_CLIP) {
+ clip_scopes_tag_refresh(sa);
+ ED_area_tag_redraw(sa);
+ }
+ break;
+ case NC_GPENCIL:
+ if (wmn->action == NA_EDITED) {
+ clip_scopes_check_gpencil_change(sa);
+ ED_area_tag_redraw(sa);
+ }
+ else if (wmn->data & ND_GPENCIL_EDITMODE) {
+ ED_area_tag_redraw(sa);
+ }
+ break;
+ }
}
static void clip_operatortypes(void)
{
- /* ** clip_ops.c ** */
- WM_operatortype_append(CLIP_OT_open);
- WM_operatortype_append(CLIP_OT_reload);
- WM_operatortype_append(CLIP_OT_view_pan);
- WM_operatortype_append(CLIP_OT_view_zoom);
- WM_operatortype_append(CLIP_OT_view_zoom_in);
- WM_operatortype_append(CLIP_OT_view_zoom_out);
- WM_operatortype_append(CLIP_OT_view_zoom_ratio);
- WM_operatortype_append(CLIP_OT_view_all);
- WM_operatortype_append(CLIP_OT_view_selected);
- WM_operatortype_append(CLIP_OT_change_frame);
- WM_operatortype_append(CLIP_OT_rebuild_proxy);
- WM_operatortype_append(CLIP_OT_mode_set);
+ /* ** clip_ops.c ** */
+ WM_operatortype_append(CLIP_OT_open);
+ WM_operatortype_append(CLIP_OT_reload);
+ WM_operatortype_append(CLIP_OT_view_pan);
+ WM_operatortype_append(CLIP_OT_view_zoom);
+ WM_operatortype_append(CLIP_OT_view_zoom_in);
+ WM_operatortype_append(CLIP_OT_view_zoom_out);
+ WM_operatortype_append(CLIP_OT_view_zoom_ratio);
+ WM_operatortype_append(CLIP_OT_view_all);
+ WM_operatortype_append(CLIP_OT_view_selected);
+ WM_operatortype_append(CLIP_OT_change_frame);
+ WM_operatortype_append(CLIP_OT_rebuild_proxy);
+ WM_operatortype_append(CLIP_OT_mode_set);
#ifdef WITH_INPUT_NDOF
- WM_operatortype_append(CLIP_OT_view_ndof);
+ WM_operatortype_append(CLIP_OT_view_ndof);
#endif
- WM_operatortype_append(CLIP_OT_prefetch);
- WM_operatortype_append(CLIP_OT_set_scene_frames);
- WM_operatortype_append(CLIP_OT_cursor_set);
-
- /* ** clip_toolbar.c ** */
- WM_operatortype_append(CLIP_OT_tools);
- WM_operatortype_append(CLIP_OT_properties);
+ WM_operatortype_append(CLIP_OT_prefetch);
+ WM_operatortype_append(CLIP_OT_set_scene_frames);
+ WM_operatortype_append(CLIP_OT_cursor_set);
+
+ /* ** clip_toolbar.c ** */
+ WM_operatortype_append(CLIP_OT_tools);
+ WM_operatortype_append(CLIP_OT_properties);
- /* ** tracking_ops.c ** */
+ /* ** tracking_ops.c ** */
- /* navigation */
- WM_operatortype_append(CLIP_OT_frame_jump);
+ /* navigation */
+ WM_operatortype_append(CLIP_OT_frame_jump);
- /* set optical center to frame center */
- WM_operatortype_append(CLIP_OT_set_center_principal);
+ /* set optical center to frame center */
+ WM_operatortype_append(CLIP_OT_set_center_principal);
- /* selection */
- WM_operatortype_append(CLIP_OT_select);
- WM_operatortype_append(CLIP_OT_select_all);
- WM_operatortype_append(CLIP_OT_select_box);
- WM_operatortype_append(CLIP_OT_select_lasso);
- WM_operatortype_append(CLIP_OT_select_circle);
- WM_operatortype_append(CLIP_OT_select_grouped);
+ /* selection */
+ WM_operatortype_append(CLIP_OT_select);
+ WM_operatortype_append(CLIP_OT_select_all);
+ WM_operatortype_append(CLIP_OT_select_box);
+ WM_operatortype_append(CLIP_OT_select_lasso);
+ WM_operatortype_append(CLIP_OT_select_circle);
+ WM_operatortype_append(CLIP_OT_select_grouped);
- /* markers */
- WM_operatortype_append(CLIP_OT_add_marker);
- WM_operatortype_append(CLIP_OT_add_marker_at_click);
- WM_operatortype_append(CLIP_OT_slide_marker);
- WM_operatortype_append(CLIP_OT_delete_track);
- WM_operatortype_append(CLIP_OT_delete_marker);
+ /* markers */
+ WM_operatortype_append(CLIP_OT_add_marker);
+ WM_operatortype_append(CLIP_OT_add_marker_at_click);
+ WM_operatortype_append(CLIP_OT_slide_marker);
+ WM_operatortype_append(CLIP_OT_delete_track);
+ WM_operatortype_append(CLIP_OT_delete_marker);
- /* track */
- WM_operatortype_append(CLIP_OT_track_markers);
- WM_operatortype_append(CLIP_OT_refine_markers);
+ /* track */
+ WM_operatortype_append(CLIP_OT_track_markers);
+ WM_operatortype_append(CLIP_OT_refine_markers);
- /* solving */
- WM_operatortype_append(CLIP_OT_solve_camera);
- WM_operatortype_append(CLIP_OT_clear_solution);
+ /* solving */
+ WM_operatortype_append(CLIP_OT_solve_camera);
+ WM_operatortype_append(CLIP_OT_clear_solution);
- WM_operatortype_append(CLIP_OT_disable_markers);
- WM_operatortype_append(CLIP_OT_hide_tracks);
- WM_operatortype_append(CLIP_OT_hide_tracks_clear);
- WM_operatortype_append(CLIP_OT_lock_tracks);
+ WM_operatortype_append(CLIP_OT_disable_markers);
+ WM_operatortype_append(CLIP_OT_hide_tracks);
+ WM_operatortype_append(CLIP_OT_hide_tracks_clear);
+ WM_operatortype_append(CLIP_OT_lock_tracks);
- WM_operatortype_append(CLIP_OT_set_solver_keyframe);
+ WM_operatortype_append(CLIP_OT_set_solver_keyframe);
- /* orientation */
- WM_operatortype_append(CLIP_OT_set_origin);
- WM_operatortype_append(CLIP_OT_set_plane);
- WM_operatortype_append(CLIP_OT_set_axis);
- WM_operatortype_append(CLIP_OT_set_scale);
- WM_operatortype_append(CLIP_OT_set_solution_scale);
- WM_operatortype_append(CLIP_OT_apply_solution_scale);
+ /* orientation */
+ WM_operatortype_append(CLIP_OT_set_origin);
+ WM_operatortype_append(CLIP_OT_set_plane);
+ WM_operatortype_append(CLIP_OT_set_axis);
+ WM_operatortype_append(CLIP_OT_set_scale);
+ WM_operatortype_append(CLIP_OT_set_solution_scale);
+ WM_operatortype_append(CLIP_OT_apply_solution_scale);
- /* detect */
- WM_operatortype_append(CLIP_OT_detect_features);
+ /* detect */
+ WM_operatortype_append(CLIP_OT_detect_features);
- /* stabilization */
- WM_operatortype_append(CLIP_OT_stabilize_2d_add);
- WM_operatortype_append(CLIP_OT_stabilize_2d_remove);
- WM_operatortype_append(CLIP_OT_stabilize_2d_select);
- WM_operatortype_append(CLIP_OT_stabilize_2d_rotation_add);
- WM_operatortype_append(CLIP_OT_stabilize_2d_rotation_remove);
- WM_operatortype_append(CLIP_OT_stabilize_2d_rotation_select);
+ /* stabilization */
+ WM_operatortype_append(CLIP_OT_stabilize_2d_add);
+ WM_operatortype_append(CLIP_OT_stabilize_2d_remove);
+ WM_operatortype_append(CLIP_OT_stabilize_2d_select);
+ WM_operatortype_append(CLIP_OT_stabilize_2d_rotation_add);
+ WM_operatortype_append(CLIP_OT_stabilize_2d_rotation_remove);
+ WM_operatortype_append(CLIP_OT_stabilize_2d_rotation_select);
- /* clean-up */
- WM_operatortype_append(CLIP_OT_clear_track_path);
- WM_operatortype_append(CLIP_OT_join_tracks);
- WM_operatortype_append(CLIP_OT_track_copy_color);
+ /* clean-up */
+ WM_operatortype_append(CLIP_OT_clear_track_path);
+ WM_operatortype_append(CLIP_OT_join_tracks);
+ WM_operatortype_append(CLIP_OT_track_copy_color);
- WM_operatortype_append(CLIP_OT_clean_tracks);
+ WM_operatortype_append(CLIP_OT_clean_tracks);
- /* object tracking */
- WM_operatortype_append(CLIP_OT_tracking_object_new);
- WM_operatortype_append(CLIP_OT_tracking_object_remove);
+ /* object tracking */
+ WM_operatortype_append(CLIP_OT_tracking_object_new);
+ WM_operatortype_append(CLIP_OT_tracking_object_remove);
- /* clipboard */
- WM_operatortype_append(CLIP_OT_copy_tracks);
- WM_operatortype_append(CLIP_OT_paste_tracks);
+ /* clipboard */
+ WM_operatortype_append(CLIP_OT_copy_tracks);
+ WM_operatortype_append(CLIP_OT_paste_tracks);
- /* Plane tracker */
- WM_operatortype_append(CLIP_OT_create_plane_track);
- WM_operatortype_append(CLIP_OT_slide_plane_marker);
+ /* Plane tracker */
+ WM_operatortype_append(CLIP_OT_create_plane_track);
+ WM_operatortype_append(CLIP_OT_slide_plane_marker);
- WM_operatortype_append(CLIP_OT_keyframe_insert);
- WM_operatortype_append(CLIP_OT_keyframe_delete);
+ WM_operatortype_append(CLIP_OT_keyframe_insert);
+ WM_operatortype_append(CLIP_OT_keyframe_delete);
- /* ** clip_graph_ops.c ** */
+ /* ** clip_graph_ops.c ** */
- /* graph editing */
+ /* graph editing */
- /* selection */
- WM_operatortype_append(CLIP_OT_graph_select);
- WM_operatortype_append(CLIP_OT_graph_select_box);
- WM_operatortype_append(CLIP_OT_graph_select_all_markers);
+ /* selection */
+ WM_operatortype_append(CLIP_OT_graph_select);
+ WM_operatortype_append(CLIP_OT_graph_select_box);
+ WM_operatortype_append(CLIP_OT_graph_select_all_markers);
- WM_operatortype_append(CLIP_OT_graph_delete_curve);
- WM_operatortype_append(CLIP_OT_graph_delete_knot);
- WM_operatortype_append(CLIP_OT_graph_view_all);
- WM_operatortype_append(CLIP_OT_graph_center_current_frame);
+ WM_operatortype_append(CLIP_OT_graph_delete_curve);
+ WM_operatortype_append(CLIP_OT_graph_delete_knot);
+ WM_operatortype_append(CLIP_OT_graph_view_all);
+ WM_operatortype_append(CLIP_OT_graph_center_current_frame);
- WM_operatortype_append(CLIP_OT_graph_disable_markers);
+ WM_operatortype_append(CLIP_OT_graph_disable_markers);
- /* ** clip_dopesheet_ops.c ** */
+ /* ** clip_dopesheet_ops.c ** */
- WM_operatortype_append(CLIP_OT_dopesheet_select_channel);
- WM_operatortype_append(CLIP_OT_dopesheet_view_all);
+ WM_operatortype_append(CLIP_OT_dopesheet_select_channel);
+ WM_operatortype_append(CLIP_OT_dopesheet_view_all);
}
static void clip_keymap(struct wmKeyConfig *keyconf)
{
- /* ******** Global hotkeys avalaible for all regions ******** */
- WM_keymap_ensure(keyconf, "Clip", SPACE_CLIP, 0);
+ /* ******** Global hotkeys avalaible for all regions ******** */
+ WM_keymap_ensure(keyconf, "Clip", SPACE_CLIP, 0);
- /* ******** Hotkeys avalaible for main region only ******** */
- WM_keymap_ensure(keyconf, "Clip Editor", SPACE_CLIP, 0);
-// keymap->poll = ED_space_clip_tracking_poll;
+ /* ******** Hotkeys avalaible for main region only ******** */
+ WM_keymap_ensure(keyconf, "Clip Editor", SPACE_CLIP, 0);
+ // keymap->poll = ED_space_clip_tracking_poll;
- /* ******** Hotkeys avalaible for preview region only ******** */
- WM_keymap_ensure(keyconf, "Clip Graph Editor", SPACE_CLIP, 0);
+ /* ******** Hotkeys avalaible for preview region only ******** */
+ WM_keymap_ensure(keyconf, "Clip Graph Editor", SPACE_CLIP, 0);
- /* ******** Hotkeys avalaible for channels region only ******** */
- WM_keymap_ensure(keyconf, "Clip Dopesheet Editor", SPACE_CLIP, 0);
+ /* ******** Hotkeys avalaible for channels region only ******** */
+ WM_keymap_ensure(keyconf, "Clip Dopesheet Editor", SPACE_CLIP, 0);
}
/* DO NOT make this static, this hides the symbol and breaks API generation script. */
-extern const char *clip_context_dir[]; /* quiet warning. */
+extern const char *clip_context_dir[]; /* quiet warning. */
const char *clip_context_dir[] = {"edit_movieclip", "edit_mask", NULL};
static int clip_context(const bContext *C, const char *member, bContextDataResult *result)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
-
- if (CTX_data_dir(member)) {
- CTX_data_dir_set(result, clip_context_dir);
-
- return true;
- }
- else if (CTX_data_equals(member, "edit_movieclip")) {
- if (sc->clip)
- CTX_data_id_pointer_set(result, &sc->clip->id);
- return true;
- }
- else if (CTX_data_equals(member, "edit_mask")) {
- if (sc->mask_info.mask)
- CTX_data_id_pointer_set(result, &sc->mask_info.mask->id);
- return true;
- }
-
- return false;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+
+ if (CTX_data_dir(member)) {
+ CTX_data_dir_set(result, clip_context_dir);
+
+ return true;
+ }
+ else if (CTX_data_equals(member, "edit_movieclip")) {
+ if (sc->clip)
+ CTX_data_id_pointer_set(result, &sc->clip->id);
+ return true;
+ }
+ else if (CTX_data_equals(member, "edit_mask")) {
+ if (sc->mask_info.mask)
+ CTX_data_id_pointer_set(result, &sc->mask_info.mask->id);
+ return true;
+ }
+
+ return false;
}
/* dropboxes */
-static bool clip_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
+static bool clip_drop_poll(bContext *UNUSED(C),
+ wmDrag *drag,
+ const wmEvent *UNUSED(event),
+ const char **UNUSED(tooltip))
{
- 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 true;
- }
- }
-
- 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 true;
+ }
+ }
+
+ return false;
}
static void clip_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- PointerRNA itemptr;
- char dir[FILE_MAX], file[FILE_MAX];
+ PointerRNA itemptr;
+ char dir[FILE_MAX], file[FILE_MAX];
- BLI_split_dirfile(drag->path, dir, file, sizeof(dir), sizeof(file));
+ BLI_split_dirfile(drag->path, dir, file, sizeof(dir), sizeof(file));
- RNA_string_set(drop->ptr, "directory", dir);
+ RNA_string_set(drop->ptr, "directory", dir);
- RNA_collection_clear(drop->ptr, "files");
- RNA_collection_add(drop->ptr, "files", &itemptr);
- RNA_string_set(&itemptr, "name", file);
+ RNA_collection_clear(drop->ptr, "files");
+ RNA_collection_add(drop->ptr, "files", &itemptr);
+ RNA_string_set(&itemptr, "name", file);
}
/* area+region dropbox definition */
static void clip_dropboxes(void)
{
- ListBase *lb = WM_dropboxmap_find("Clip", SPACE_CLIP, 0);
+ ListBase *lb = WM_dropboxmap_find("Clip", SPACE_CLIP, 0);
- WM_dropbox_add(lb, "CLIP_OT_open", clip_drop_poll, clip_drop_copy);
+ WM_dropbox_add(lb, "CLIP_OT_open", clip_drop_poll, clip_drop_copy);
}
static void clip_refresh(const bContext *C, ScrArea *sa)
{
- 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);
- bool main_visible = false, preview_visible = false, tools_visible = false;
- bool properties_visible = false, channels_visible = false;
- bool view_changed = false;
-
- switch (sc->view) {
- case SC_VIEW_CLIP:
- main_visible = true;
- preview_visible = false;
- tools_visible = true;
- properties_visible = true;
- channels_visible = false;
- break;
- case SC_VIEW_GRAPH:
- main_visible = false;
- preview_visible = true;
- tools_visible = false;
- properties_visible = false;
- channels_visible = false;
-
- reinit_preview_region(C, ar_preview);
- break;
- case SC_VIEW_DOPESHEET:
- main_visible = false;
- preview_visible = true;
- tools_visible = false;
- properties_visible = false;
- channels_visible = true;
-
- reinit_preview_region(C, ar_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;
- view_changed = true;
- }
-
- if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
- ar_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);
- view_changed = true;
- }
- if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
- ar_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;
- view_changed = true;
- }
- if (ar_properties && ar_properties->alignment != RGN_ALIGN_RIGHT) {
- ar_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);
- view_changed = true;
- }
- if (ar_properties && ar_properties->alignment != RGN_ALIGN_NONE) {
- ar_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;
- view_changed = true;
- }
- if (ar_tools && ar_tools->alignment != RGN_ALIGN_LEFT) {
- ar_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);
- view_changed = true;
- }
- if (ar_tools && ar_tools->alignment != RGN_ALIGN_NONE) {
- ar_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;
- view_changed = true;
- }
- if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
- ar_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);
- view_changed = true;
- }
- if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
- ar_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;
- view_changed = true;
- }
- if (ar_channels && ar_channels->alignment != RGN_ALIGN_LEFT) {
- ar_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);
- view_changed = true;
- }
- if (ar_channels && ar_channels->alignment != RGN_ALIGN_NONE) {
- ar_channels->alignment = RGN_ALIGN_NONE;
- view_changed = true;
- }
- }
-
- if (view_changed) {
- ED_area_initialize(wm, window, sa);
- ED_area_tag_redraw(sa);
- }
-
- BKE_movieclip_user_set_frame(&sc->user, scene->r.cfra);
+ 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);
+ bool main_visible = false, preview_visible = false, tools_visible = false;
+ bool properties_visible = false, channels_visible = false;
+ bool view_changed = false;
+
+ switch (sc->view) {
+ case SC_VIEW_CLIP:
+ main_visible = true;
+ preview_visible = false;
+ tools_visible = true;
+ properties_visible = true;
+ channels_visible = false;
+ break;
+ case SC_VIEW_GRAPH:
+ main_visible = false;
+ preview_visible = true;
+ tools_visible = false;
+ properties_visible = false;
+ channels_visible = false;
+
+ reinit_preview_region(C, ar_preview);
+ break;
+ case SC_VIEW_DOPESHEET:
+ main_visible = false;
+ preview_visible = true;
+ tools_visible = false;
+ properties_visible = false;
+ channels_visible = true;
+
+ reinit_preview_region(C, ar_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;
+ view_changed = true;
+ }
+
+ if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
+ ar_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);
+ view_changed = true;
+ }
+ if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
+ ar_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;
+ view_changed = true;
+ }
+ if (ar_properties && ar_properties->alignment != RGN_ALIGN_RIGHT) {
+ ar_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);
+ view_changed = true;
+ }
+ if (ar_properties && ar_properties->alignment != RGN_ALIGN_NONE) {
+ ar_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;
+ view_changed = true;
+ }
+ if (ar_tools && ar_tools->alignment != RGN_ALIGN_LEFT) {
+ ar_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);
+ view_changed = true;
+ }
+ if (ar_tools && ar_tools->alignment != RGN_ALIGN_NONE) {
+ ar_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;
+ view_changed = true;
+ }
+ if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
+ ar_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);
+ view_changed = true;
+ }
+ if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
+ ar_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;
+ view_changed = true;
+ }
+ if (ar_channels && ar_channels->alignment != RGN_ALIGN_LEFT) {
+ ar_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);
+ view_changed = true;
+ }
+ if (ar_channels && ar_channels->alignment != RGN_ALIGN_NONE) {
+ ar_channels->alignment = RGN_ALIGN_NONE;
+ view_changed = true;
+ }
+ }
+
+ if (view_changed) {
+ ED_area_initialize(wm, window, sa);
+ ED_area_tag_redraw(sa);
+ }
+
+ BKE_movieclip_user_set_frame(&sc->user, scene->r.cfra);
}
/********************* main region ********************/
@@ -793,300 +798,314 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
/* sets up the fields of the View2D from zoom and offset */
static void movieclip_main_area_set_view2d(const bContext *C, ARegion *ar)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- float x1, y1, w, h, aspx, aspy;
- int width, height, winx, winy;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ float x1, y1, w, h, aspx, aspy;
+ int width, height, winx, winy;
- ED_space_clip_get_size(sc, &width, &height);
- ED_space_clip_get_aspect(sc, &aspx, &aspy);
+ ED_space_clip_get_size(sc, &width, &height);
+ ED_space_clip_get_aspect(sc, &aspx, &aspy);
- w = width * aspx;
- h = height * aspy;
+ 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(&ar->winrct) + 1;
+ winy = BLI_rcti_size_y(&ar->winrct) + 1;
- ar->v2d.tot.xmin = 0;
- ar->v2d.tot.ymin = 0;
- ar->v2d.tot.xmax = w;
- ar->v2d.tot.ymax = h;
+ ar->v2d.tot.xmin = 0;
+ ar->v2d.tot.ymin = 0;
+ ar->v2d.tot.xmax = w;
+ ar->v2d.tot.ymax = h;
- ar->v2d.mask.xmin = ar->v2d.mask.ymin = 0;
- ar->v2d.mask.xmax = winx;
- ar->v2d.mask.ymax = winy;
+ ar->v2d.mask.xmin = ar->v2d.mask.ymin = 0;
+ ar->v2d.mask.xmax = winx;
+ ar->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;
+ /* 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 -= sc->zoom * sc->xof;
- y1 -= sc->zoom * sc->yof;
+ 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);
+ /* 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);
- /* 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);
+ /* 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);
- /* 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;
+ /* 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;
}
/* add handlers, stuff you only do once or on area/region changes */
static void clip_main_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
- /* mask polls mode */
- keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", 0, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ /* mask polls mode */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", 0, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- /* own keymap */
- keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ /* own keymap */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- keymap = WM_keymap_ensure(wm->defaultconf, "Clip Editor", SPACE_CLIP, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Clip Editor", SPACE_CLIP, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
static void clip_main_region_draw(const bContext *C, ARegion *ar)
{
- /* draw entirely, view changes should be handled here */
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- float aspx, aspy, zoomx, zoomy, x, y;
- int width, height;
- bool show_cursor = false;
-
- /* if tracking is in progress, we should synchronize framenr from clipuser
- * so latest tracked frame would be shown */
- if (clip && clip->tracking_context)
- BKE_autotrack_context_sync_user(clip->tracking_context, &sc->user);
-
- if (sc->flag & SC_LOCK_SELECTION) {
- ImBuf *tmpibuf = NULL;
-
- if (clip && clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
- tmpibuf = ED_space_clip_get_stable_buffer(sc, NULL, NULL, NULL);
- }
-
- if (ED_clip_view_selection(C, ar, 0)) {
- sc->xof += sc->xlockof;
- sc->yof += sc->ylockof;
- }
-
- if (tmpibuf)
- IMB_freeImBuf(tmpibuf);
- }
-
- /* clear and setup matrix */
- UI_ThemeClearColor(TH_BACK);
- GPU_clear(GPU_COLOR_BIT);
-
- /* data... */
- movieclip_main_area_set_view2d(C, ar);
-
- /* callback */
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
-
- clip_draw_main(C, sc, ar);
-
- /* 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);
- ED_space_clip_get_size(sc, &width, &height);
- ED_space_clip_get_zoom(sc, ar, &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);
- int mask_width, mask_height;
- ED_mask_get_size(sa, &mask_width, &mask_height);
- ED_mask_draw_region(mask, ar,
- sc->mask_info.draw_flag,
- sc->mask_info.draw_type,
- sc->mask_info.overlay_mode,
- mask_width, mask_height,
- aspx, aspy,
- true, true,
- sc->stabmat, C);
- }
- }
-
- show_cursor |= sc->mode == SC_MODE_MASKEDIT;
- show_cursor |= sc->around == V3D_AROUND_CURSOR;
-
- if (show_cursor) {
- GPU_matrix_push();
- GPU_matrix_translate_2f(x, y);
- GPU_matrix_scale_2f(zoomx, zoomy);
- GPU_matrix_mul(sc->stabmat);
- GPU_matrix_scale_2f(width, height);
- ED_image_draw_cursor(ar, sc->cursor);
- GPU_matrix_pop();
- }
-
- clip_draw_cache_and_notes(C, sc, ar);
-
- if (sc->flag & SC_SHOW_ANNOTATION) {
- /* Grease Pencil */
- clip_draw_grease_pencil((bContext *)C, true);
- }
-
- /* callback */
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
-
- /* reset view matrix */
- UI_view2d_view_restore(C);
-
- if (sc->flag & SC_SHOW_ANNOTATION) {
- /* draw Grease Pencil - screen space only */
- clip_draw_grease_pencil((bContext *)C, false);
- }
+ /* draw entirely, view changes should be handled here */
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ float aspx, aspy, zoomx, zoomy, x, y;
+ int width, height;
+ bool show_cursor = false;
+
+ /* if tracking is in progress, we should synchronize framenr from clipuser
+ * so latest tracked frame would be shown */
+ if (clip && clip->tracking_context)
+ BKE_autotrack_context_sync_user(clip->tracking_context, &sc->user);
+
+ if (sc->flag & SC_LOCK_SELECTION) {
+ ImBuf *tmpibuf = NULL;
+
+ if (clip && clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
+ tmpibuf = ED_space_clip_get_stable_buffer(sc, NULL, NULL, NULL);
+ }
+
+ if (ED_clip_view_selection(C, ar, 0)) {
+ sc->xof += sc->xlockof;
+ sc->yof += sc->ylockof;
+ }
+
+ if (tmpibuf)
+ IMB_freeImBuf(tmpibuf);
+ }
+
+ /* clear and setup matrix */
+ UI_ThemeClearColor(TH_BACK);
+ GPU_clear(GPU_COLOR_BIT);
+
+ /* data... */
+ movieclip_main_area_set_view2d(C, ar);
+
+ /* callback */
+ ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
+
+ clip_draw_main(C, sc, ar);
+
+ /* 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);
+ ED_space_clip_get_size(sc, &width, &height);
+ ED_space_clip_get_zoom(sc, ar, &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);
+ int mask_width, mask_height;
+ ED_mask_get_size(sa, &mask_width, &mask_height);
+ ED_mask_draw_region(mask,
+ ar,
+ sc->mask_info.draw_flag,
+ sc->mask_info.draw_type,
+ sc->mask_info.overlay_mode,
+ mask_width,
+ mask_height,
+ aspx,
+ aspy,
+ true,
+ true,
+ sc->stabmat,
+ C);
+ }
+ }
+
+ show_cursor |= sc->mode == SC_MODE_MASKEDIT;
+ show_cursor |= sc->around == V3D_AROUND_CURSOR;
+
+ if (show_cursor) {
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(x, y);
+ GPU_matrix_scale_2f(zoomx, zoomy);
+ GPU_matrix_mul(sc->stabmat);
+ GPU_matrix_scale_2f(width, height);
+ ED_image_draw_cursor(ar, sc->cursor);
+ GPU_matrix_pop();
+ }
+
+ clip_draw_cache_and_notes(C, sc, ar);
+
+ if (sc->flag & SC_SHOW_ANNOTATION) {
+ /* Grease Pencil */
+ clip_draw_grease_pencil((bContext *)C, true);
+ }
+
+ /* callback */
+ ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ if (sc->flag & SC_SHOW_ANNOTATION) {
+ /* draw Grease Pencil - screen space only */
+ clip_draw_grease_pencil((bContext *)C, false);
+ }
}
-static void clip_main_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void clip_main_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_GPENCIL:
- if (wmn->action == NA_EDITED)
- ED_region_tag_redraw(ar);
- else if (wmn->data & ND_GPENCIL_EDITMODE)
- ED_region_tag_redraw(ar);
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_GPENCIL:
+ if (wmn->action == NA_EDITED)
+ ED_region_tag_redraw(ar);
+ else if (wmn->data & ND_GPENCIL_EDITMODE)
+ ED_region_tag_redraw(ar);
+ break;
+ }
}
/****************** preview region ******************/
static void clip_preview_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
- /* own keymap */
- keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ /* own keymap */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- keymap = WM_keymap_ensure(wm->defaultconf, "Clip Graph Editor", SPACE_CLIP, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Clip Graph Editor", SPACE_CLIP, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- keymap = WM_keymap_ensure(wm->defaultconf, "Clip Dopesheet Editor", SPACE_CLIP, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Clip Dopesheet Editor", SPACE_CLIP, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
static void graph_region_draw(const bContext *C, ARegion *ar)
{
- View2D *v2d = &ar->v2d;
- View2DScrollers *scrollers;
- SpaceClip *sc = CTX_wm_space_clip(C);
- Scene *scene = CTX_data_scene(C);
- short unitx, unity;
- short cfra_flag = 0;
-
- if (sc->flag & SC_LOCK_TIMECURSOR)
- ED_clip_graph_center_current_frame(scene, ar);
-
- /* clear and setup matrix */
- UI_ThemeClearColor(TH_BACK);
- GPU_clear(GPU_COLOR_BIT);
-
- UI_view2d_view_ortho(v2d);
-
- /* data... */
- clip_draw_graph(sc, ar, scene);
-
- /* current frame indicator line */
- if (sc->flag & SC_SHOW_SECONDS) cfra_flag |= DRAWCFRA_UNIT_SECONDS;
- ANIM_draw_cfra(C, v2d, cfra_flag);
-
- /* reset view matrix */
- UI_view2d_view_restore(C);
-
- /* scrollers */
- unitx = (sc->flag & SC_SHOW_SECONDS) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES;
- unity = V2D_UNIT_VALUES;
- scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
-
- /* current frame indicator */
- if (sc->flag & SC_SHOW_SECONDS) cfra_flag |= DRAWCFRA_UNIT_SECONDS;
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- ANIM_draw_cfra_number(C, v2d, cfra_flag);
+ View2D *v2d = &ar->v2d;
+ View2DScrollers *scrollers;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ Scene *scene = CTX_data_scene(C);
+ short unitx, unity;
+ short cfra_flag = 0;
+
+ if (sc->flag & SC_LOCK_TIMECURSOR)
+ ED_clip_graph_center_current_frame(scene, ar);
+
+ /* clear and setup matrix */
+ UI_ThemeClearColor(TH_BACK);
+ GPU_clear(GPU_COLOR_BIT);
+
+ UI_view2d_view_ortho(v2d);
+
+ /* data... */
+ clip_draw_graph(sc, ar, scene);
+
+ /* current frame indicator line */
+ if (sc->flag & SC_SHOW_SECONDS)
+ cfra_flag |= DRAWCFRA_UNIT_SECONDS;
+ ANIM_draw_cfra(C, v2d, cfra_flag);
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ unitx = (sc->flag & SC_SHOW_SECONDS) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES;
+ unity = V2D_UNIT_VALUES;
+ scrollers = UI_view2d_scrollers_calc(
+ C, v2d, NULL, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+
+ /* current frame indicator */
+ if (sc->flag & SC_SHOW_SECONDS)
+ cfra_flag |= DRAWCFRA_UNIT_SECONDS;
+ UI_view2d_view_orthoSpecial(ar, v2d, 1);
+ ANIM_draw_cfra_number(C, v2d, cfra_flag);
}
static void dopesheet_region_draw(const bContext *C, ARegion *ar)
{
- 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;
- View2DGrid *grid;
- View2DScrollers *scrollers;
- short unit = 0, cfra_flag = 0;
-
- if (clip)
- BKE_tracking_dopesheet_update(&clip->tracking);
-
- /* clear and setup matrix */
- UI_ThemeClearColor(TH_BACK);
- GPU_clear(GPU_COLOR_BIT);
-
- UI_view2d_view_ortho(v2d);
-
- /* time grid */
- unit = (sc->flag & SC_SHOW_SECONDS) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES;
- grid = UI_view2d_grid_calc(scene, v2d, unit, V2D_GRID_CLAMP,
- V2D_ARG_DUMMY, V2D_ARG_DUMMY, ar->winx, ar->winy);
- UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL);
- UI_view2d_grid_free(grid);
-
- /* data... */
- clip_draw_dopesheet_main(sc, ar, scene);
-
- /* current frame indicator line */
- if (sc->flag & SC_SHOW_SECONDS) cfra_flag |= DRAWCFRA_UNIT_SECONDS;
- ANIM_draw_cfra(C, v2d, cfra_flag);
-
- /* reset view matrix */
- UI_view2d_view_restore(C);
-
- /* scrollers */
- scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
-
- /* current frame number indicator */
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- ANIM_draw_cfra_number(C, v2d, cfra_flag);
+ 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;
+ View2DGrid *grid;
+ View2DScrollers *scrollers;
+ short unit = 0, cfra_flag = 0;
+
+ if (clip)
+ BKE_tracking_dopesheet_update(&clip->tracking);
+
+ /* clear and setup matrix */
+ UI_ThemeClearColor(TH_BACK);
+ GPU_clear(GPU_COLOR_BIT);
+
+ UI_view2d_view_ortho(v2d);
+
+ /* time grid */
+ unit = (sc->flag & SC_SHOW_SECONDS) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES;
+ grid = UI_view2d_grid_calc(
+ scene, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY, ar->winx, ar->winy);
+ UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL);
+ UI_view2d_grid_free(grid);
+
+ /* data... */
+ clip_draw_dopesheet_main(sc, ar, scene);
+
+ /* current frame indicator line */
+ if (sc->flag & SC_SHOW_SECONDS)
+ cfra_flag |= DRAWCFRA_UNIT_SECONDS;
+ ANIM_draw_cfra(C, v2d, cfra_flag);
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ scrollers = UI_view2d_scrollers_calc(
+ C, v2d, NULL, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+
+ /* current frame number indicator */
+ UI_view2d_view_orthoSpecial(ar, v2d, 1);
+ ANIM_draw_cfra_number(C, v2d, cfra_flag);
}
static void clip_preview_region_draw(const bContext *C, ARegion *ar)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
- if (sc->view == SC_VIEW_GRAPH)
- graph_region_draw(C, ar);
- else if (sc->view == SC_VIEW_DOPESHEET)
- dopesheet_region_draw(C, ar);
+ if (sc->view == SC_VIEW_GRAPH)
+ graph_region_draw(C, ar);
+ else if (sc->view == SC_VIEW_DOPESHEET)
+ dopesheet_region_draw(C, ar);
}
-static void clip_preview_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *UNUSED(ar),
- wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene))
+static void clip_preview_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *UNUSED(ar),
+ wmNotifier *UNUSED(wmn),
+ const Scene *UNUSED(scene))
{
}
@@ -1094,42 +1113,44 @@ static void clip_preview_region_listener(
static void clip_channels_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- /* ensure the 2d view sync works - main region has bottom scroller */
- ar->v2d.scroll = V2D_SCROLL_BOTTOM;
+ /* ensure the 2d view sync works - main region has bottom scroller */
+ ar->v2d.scroll = V2D_SCROLL_BOTTOM;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
- keymap = WM_keymap_ensure(wm->defaultconf, "Clip Dopesheet Editor", SPACE_CLIP, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Clip Dopesheet Editor", SPACE_CLIP, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
static void clip_channels_region_draw(const bContext *C, ARegion *ar)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- View2D *v2d = &ar->v2d;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ View2D *v2d = &ar->v2d;
- if (clip)
- BKE_tracking_dopesheet_update(&clip->tracking);
+ if (clip)
+ BKE_tracking_dopesheet_update(&clip->tracking);
- /* clear and setup matrix */
- UI_ThemeClearColor(TH_BACK);
- GPU_clear(GPU_COLOR_BIT);
+ /* clear and setup matrix */
+ UI_ThemeClearColor(TH_BACK);
+ GPU_clear(GPU_COLOR_BIT);
- UI_view2d_view_ortho(v2d);
+ UI_view2d_view_ortho(v2d);
- /* data... */
- clip_draw_dopesheet_channels(C, ar);
+ /* data... */
+ clip_draw_dopesheet_channels(C, ar);
- /* reset view matrix */
- UI_view2d_view_restore(C);
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
}
-static void clip_channels_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *UNUSED(ar),
- wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene))
+static void clip_channels_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *UNUSED(ar),
+ wmNotifier *UNUSED(wmn),
+ const Scene *UNUSED(scene))
{
}
@@ -1138,79 +1159,82 @@ static void clip_channels_region_listener(
/* add handlers, stuff you only do once or on area/region changes */
static void clip_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
- ED_region_header_init(ar);
+ ED_region_header_init(ar);
}
static void clip_header_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_header(C, ar);
+ ED_region_header(C, ar);
}
-static void clip_header_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void clip_header_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_SCENE:
- switch (wmn->data) {
- /* for proportional editmode only */
- case ND_TOOLSETTINGS:
- /* TODO - should do this when in mask mode only but no datas available */
- // if (sc->mode == SC_MODE_MASKEDIT)
- {
- ED_region_tag_redraw(ar);
- break;
- }
- }
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SCENE:
+ switch (wmn->data) {
+ /* for proportional editmode only */
+ case ND_TOOLSETTINGS:
+ /* TODO - should do this when in mask mode only but no datas available */
+ // if (sc->mode == SC_MODE_MASKEDIT)
+ {
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ }
+ break;
+ }
}
-
/****************** tools region ******************/
/* add handlers, stuff you only do once or on area/region changes */
static void clip_tools_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, ar);
- keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
}
static void clip_tools_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, ar);
}
/****************** tool properties region ******************/
-static void clip_props_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void clip_props_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_WM:
- if (wmn->data == ND_HISTORY)
- ED_region_tag_redraw(ar);
- break;
- case NC_SCENE:
- if (wmn->data == ND_MODE)
- ED_region_tag_redraw(ar);
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_CLIP)
- ED_region_tag_redraw(ar);
- break;
- case NC_GPENCIL:
- if (wmn->action == NA_EDITED)
- ED_region_tag_redraw(ar);
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_WM:
+ if (wmn->data == ND_HISTORY)
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_SCENE:
+ if (wmn->data == ND_MODE)
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_CLIP)
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_GPENCIL:
+ if (wmn->action == NA_EDITED)
+ ED_region_tag_redraw(ar);
+ break;
+ }
}
/****************** properties region ******************/
@@ -1218,151 +1242,153 @@ static void clip_props_region_listener(
/* add handlers, stuff you only do once or on area/region changes */
static void clip_properties_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, ar);
- keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
}
static void clip_properties_region_draw(const bContext *C, ARegion *ar)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
- BKE_movieclip_update_scopes(sc->clip, &sc->user, &sc->scopes);
+ BKE_movieclip_update_scopes(sc->clip, &sc->user, &sc->scopes);
- ED_region_panels(C, ar);
+ ED_region_panels(C, ar);
}
-static void clip_properties_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void clip_properties_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_GPENCIL:
- if (ELEM(wmn->data, ND_DATA, ND_GPENCIL_EDITMODE))
- ED_region_tag_redraw(ar);
- break;
- case NC_BRUSH:
- if (wmn->action == NA_EDITED)
- ED_region_tag_redraw(ar);
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_GPENCIL:
+ if (ELEM(wmn->data, ND_DATA, ND_GPENCIL_EDITMODE))
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_BRUSH:
+ if (wmn->action == NA_EDITED)
+ ED_region_tag_redraw(ar);
+ break;
+ }
}
/********************* registration ********************/
static void clip_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
{
- SpaceClip *sclip = (SpaceClip *)slink;
+ SpaceClip *sclip = (SpaceClip *)slink;
- if (!ELEM(GS(old_id->name), ID_MC, ID_MSK)) {
- return;
- }
+ if (!ELEM(GS(old_id->name), ID_MC, ID_MSK)) {
+ return;
+ }
- if ((ID *)sclip->clip == old_id) {
- sclip->clip = (MovieClip *)new_id;
- id_us_ensure_real(new_id);
- }
+ if ((ID *)sclip->clip == old_id) {
+ sclip->clip = (MovieClip *)new_id;
+ id_us_ensure_real(new_id);
+ }
- if ((ID *)sclip->mask_info.mask == old_id) {
- sclip->mask_info.mask = (Mask *)new_id;
- id_us_ensure_real(new_id);
- }
+ if ((ID *)sclip->mask_info.mask == old_id) {
+ sclip->mask_info.mask = (Mask *)new_id;
+ id_us_ensure_real(new_id);
+ }
}
/* only called once, from space/spacetypes.c */
void ED_spacetype_clip(void)
{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype clip");
- ARegionType *art;
-
- st->spaceid = SPACE_CLIP;
- strncpy(st->name, "Clip", BKE_ST_MAXNAME);
-
- st->new = clip_new;
- st->free = clip_free;
- st->init = clip_init;
- st->duplicate = clip_duplicate;
- st->operatortypes = clip_operatortypes;
- st->keymap = clip_keymap;
- st->listener = clip_listener;
- st->context = clip_context;
- st->dropboxes = clip_dropboxes;
- st->refresh = clip_refresh;
- st->id_remap = clip_id_remap;
-
- /* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype clip region");
- art->regionid = RGN_TYPE_WINDOW;
- art->init = clip_main_region_init;
- art->draw = clip_main_region_draw;
- art->listener = clip_main_region_listener;
- art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI | ED_KEYMAP_GPENCIL;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* preview */
- art = MEM_callocN(sizeof(ARegionType), "spacetype clip region preview");
- art->regionid = RGN_TYPE_PREVIEW;
- art->prefsizey = 240;
- art->init = clip_preview_region_init;
- art->draw = clip_preview_region_draw;
- art->listener = clip_preview_region_listener;
- art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: properties */
- art = MEM_callocN(sizeof(ARegionType), "spacetype clip region properties");
- art->regionid = RGN_TYPE_UI;
- art->prefsizex = UI_COMPACT_PANEL_WIDTH;
- art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI;
- art->init = clip_properties_region_init;
- art->draw = clip_properties_region_draw;
- art->listener = clip_properties_region_listener;
- BLI_addhead(&st->regiontypes, art);
- ED_clip_buttons_register(art);
-
- /* regions: tools */
- art = MEM_callocN(sizeof(ARegionType), "spacetype clip region tools");
- art->regionid = RGN_TYPE_TOOLS;
- art->prefsizex = UI_COMPACT_PANEL_WIDTH;
- art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI;
- art->listener = clip_props_region_listener;
- art->init = clip_tools_region_init;
- art->draw = clip_tools_region_draw;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype clip region");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
-
- art->init = clip_header_region_init;
- art->draw = clip_header_region_draw;
- art->listener = clip_header_region_listener;
-
- BLI_addhead(&st->regiontypes, art);
-
- BKE_spacetype_register(st);
-
- /* channels */
- art = MEM_callocN(sizeof(ARegionType), "spacetype clip channels region");
- art->regionid = RGN_TYPE_CHANNELS;
- art->prefsizex = UI_COMPACT_PANEL_WIDTH;
- art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI;
- art->listener = clip_channels_region_listener;
- art->init = clip_channels_region_init;
- art->draw = clip_channels_region_draw;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: hud */
- art = ED_area_type_hud(st->spaceid);
- BLI_addhead(&st->regiontypes, art);
+ SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype clip");
+ ARegionType *art;
+
+ st->spaceid = SPACE_CLIP;
+ strncpy(st->name, "Clip", BKE_ST_MAXNAME);
+
+ st->new = clip_new;
+ st->free = clip_free;
+ st->init = clip_init;
+ st->duplicate = clip_duplicate;
+ st->operatortypes = clip_operatortypes;
+ st->keymap = clip_keymap;
+ st->listener = clip_listener;
+ st->context = clip_context;
+ st->dropboxes = clip_dropboxes;
+ st->refresh = clip_refresh;
+ st->id_remap = clip_id_remap;
+
+ /* regions: main window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype clip region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init = clip_main_region_init;
+ art->draw = clip_main_region_draw;
+ art->listener = clip_main_region_listener;
+ art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI | ED_KEYMAP_GPENCIL;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* preview */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype clip region preview");
+ art->regionid = RGN_TYPE_PREVIEW;
+ art->prefsizey = 240;
+ art->init = clip_preview_region_init;
+ art->draw = clip_preview_region_draw;
+ art->listener = clip_preview_region_listener;
+ art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: properties */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype clip region properties");
+ art->regionid = RGN_TYPE_UI;
+ art->prefsizex = UI_COMPACT_PANEL_WIDTH;
+ art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI;
+ art->init = clip_properties_region_init;
+ art->draw = clip_properties_region_draw;
+ art->listener = clip_properties_region_listener;
+ BLI_addhead(&st->regiontypes, art);
+ ED_clip_buttons_register(art);
+
+ /* regions: tools */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype clip region tools");
+ art->regionid = RGN_TYPE_TOOLS;
+ art->prefsizex = UI_COMPACT_PANEL_WIDTH;
+ art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI;
+ art->listener = clip_props_region_listener;
+ art->init = clip_tools_region_init;
+ art->draw = clip_tools_region_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype clip region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = HEADERY;
+ art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
+
+ art->init = clip_header_region_init;
+ art->draw = clip_header_region_draw;
+ art->listener = clip_header_region_listener;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
+
+ /* channels */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype clip channels region");
+ art->regionid = RGN_TYPE_CHANNELS;
+ art->prefsizex = UI_COMPACT_PANEL_WIDTH;
+ art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI;
+ art->listener = clip_channels_region_listener;
+ art->init = clip_channels_region_init;
+ art->draw = clip_channels_region_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: hud */
+ art = ED_area_type_hud(st->spaceid);
+ BLI_addhead(&st->regiontypes, art);
}
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index 68d13b63804..ce1ade80823 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -57,329 +57,319 @@
static bool add_marker(const bContext *C, float x, float y)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- MovieTrackingTrack *track;
- int width, height;
- int framenr = ED_space_clip_get_clip_frame_number(sc);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ MovieTrackingTrack *track;
+ int width, height;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
- ED_space_clip_get_size(sc, &width, &height);
+ ED_space_clip_get_size(sc, &width, &height);
- if (width == 0 || height == 0) {
- return false;
- }
+ if (width == 0 || height == 0) {
+ return false;
+ }
- track = BKE_tracking_track_add(tracking, tracksbase, x, y, framenr, width, height);
+ track = BKE_tracking_track_add(tracking, tracksbase, x, y, framenr, width, height);
- BKE_tracking_track_select(tracksbase, track, TRACK_AREA_ALL, 0);
- BKE_tracking_plane_tracks_deselect_all(plane_tracks_base);
+ BKE_tracking_track_select(tracksbase, track, TRACK_AREA_ALL, 0);
+ BKE_tracking_plane_tracks_deselect_all(plane_tracks_base);
- clip->tracking.act_track = track;
- clip->tracking.act_plane_track = NULL;
+ clip->tracking.act_track = track;
+ clip->tracking.act_plane_track = NULL;
- return true;
+ return true;
}
static int add_marker_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- float pos[2];
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ float pos[2];
- RNA_float_get_array(op->ptr, "location", pos);
+ RNA_float_get_array(op->ptr, "location", pos);
- if (!add_marker(C, pos[0], pos[1])) {
- return OPERATOR_CANCELLED;
- }
+ if (!add_marker(C, pos[0], pos[1])) {
+ return OPERATOR_CANCELLED;
+ }
- /* Reset offset from locked position, so frame jumping wouldn't be so
- * confusing.
- */
- sc->xlockof = 0;
- sc->ylockof = 0;
+ /* Reset offset from locked position, so frame jumping wouldn't be so
+ * confusing.
+ */
+ sc->xlockof = 0;
+ sc->ylockof = 0;
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
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);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = 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);
- RNA_float_set_array(op->ptr, "location", co);
- }
+ 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);
+ RNA_float_set_array(op->ptr, "location", co);
+ }
- return add_marker_exec(C, op);
+ return add_marker_exec(C, op);
}
void CLIP_OT_add_marker(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Marker";
- ot->idname = "CLIP_OT_add_marker";
- ot->description = "Place new marker at specified location";
+ /* identifiers */
+ ot->name = "Add Marker";
+ ot->idname = "CLIP_OT_add_marker";
+ ot->description = "Place new marker at specified location";
- /* api callbacks */
- ot->invoke = add_marker_invoke;
- ot->exec = add_marker_exec;
- ot->poll = ED_space_clip_tracking_poll;
+ /* api callbacks */
+ ot->invoke = add_marker_invoke;
+ ot->exec = add_marker_exec;
+ ot->poll = ED_space_clip_tracking_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
- "Location", "Location of marker on frame", -1.0f, 1.0f);
+ /* properties */
+ RNA_def_float_vector(ot->srna,
+ "location",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Location",
+ "Location of marker on frame",
+ -1.0f,
+ 1.0f);
}
/********************** add marker operator *********************/
-static int add_marker_at_click_invoke(bContext *C,
- wmOperator *op,
- const wmEvent *UNUSED(event))
+static int add_marker_at_click_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- ED_workspace_status_text(
- C,
- IFACE_("Use LMB click to define location where place the marker"));
+ ED_workspace_status_text(C, IFACE_("Use LMB click to define location where place the marker"));
- /* Add modal handler for ESC. */
- WM_event_add_modal_handler(C, op);
+ /* Add modal handler for ESC. */
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
-static int add_marker_at_click_modal(bContext *C,
- wmOperator *UNUSED(op),
- const wmEvent *event)
+static int add_marker_at_click_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- switch (event->type) {
- case MOUSEMOVE:
- return OPERATOR_RUNNING_MODAL;
+ switch (event->type) {
+ case MOUSEMOVE:
+ return OPERATOR_RUNNING_MODAL;
- case LEFTMOUSE:
- {
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- ARegion *ar = CTX_wm_region(C);
- float pos[2];
+ case LEFTMOUSE: {
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ ARegion *ar = CTX_wm_region(C);
+ float pos[2];
- ED_workspace_status_text(C, NULL);
+ 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, ar, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin, &pos[0], &pos[1]);
- if (!add_marker(C, pos[0], pos[1])) {
- return OPERATOR_CANCELLED;
- }
+ if (!add_marker(C, pos[0], pos[1])) {
+ return OPERATOR_CANCELLED;
+ }
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
- return OPERATOR_FINISHED;
- }
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+ return OPERATOR_FINISHED;
+ }
- case ESCKEY:
- ED_workspace_status_text(C, NULL);
- return OPERATOR_CANCELLED;
- }
+ case ESCKEY:
+ ED_workspace_status_text(C, NULL);
+ return OPERATOR_CANCELLED;
+ }
- return OPERATOR_PASS_THROUGH;
+ return OPERATOR_PASS_THROUGH;
}
void CLIP_OT_add_marker_at_click(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Marker at Click";
- ot->idname = "CLIP_OT_add_marker_at_click";
- ot->description = "Place new marker at the desired (clicked) position";
+ /* identifiers */
+ ot->name = "Add Marker at Click";
+ ot->idname = "CLIP_OT_add_marker_at_click";
+ ot->description = "Place new marker at the desired (clicked) position";
- /* api callbacks */
- ot->invoke = add_marker_at_click_invoke;
- ot->poll = ED_space_clip_tracking_poll;
- ot->modal = add_marker_at_click_modal;
+ /* api callbacks */
+ ot->invoke = add_marker_at_click_invoke;
+ ot->poll = ED_space_clip_tracking_poll;
+ ot->modal = add_marker_at_click_modal;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
}
/********************** delete track operator *********************/
static int delete_track_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- bool changed = false;
- /* Delete selected plane tracks. */
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first,
- *next_plane_track;
- plane_track != NULL;
- plane_track = next_plane_track)
- {
- next_plane_track = plane_track->next;
- if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
- clip_delete_plane_track(C, clip, plane_track);
- changed = true;
- }
- }
- /* Remove selected point tracks (they'll also be removed from planes which
- * uses them).
- */
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- for (MovieTrackingTrack *track = tracksbase->first, *next_track;
- track != NULL;
- track = next_track)
- {
- next_track = track->next;
- if (TRACK_VIEW_SELECTED(sc, track)) {
- clip_delete_track(C, clip, track);
- changed = true;
- }
- }
- /* Nothing selected now, unlock view so it can be scrolled nice again. */
- sc->flag &= ~SC_LOCK_SELECTION;
- if (changed) {
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
- }
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ bool changed = false;
+ /* Delete selected plane tracks. */
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first, *next_plane_track;
+ plane_track != NULL;
+ plane_track = next_plane_track) {
+ next_plane_track = plane_track->next;
+ if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
+ clip_delete_plane_track(C, clip, plane_track);
+ changed = true;
+ }
+ }
+ /* Remove selected point tracks (they'll also be removed from planes which
+ * uses them).
+ */
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ for (MovieTrackingTrack *track = tracksbase->first, *next_track; track != NULL;
+ track = next_track) {
+ next_track = track->next;
+ if (TRACK_VIEW_SELECTED(sc, track)) {
+ clip_delete_track(C, clip, track);
+ changed = true;
+ }
+ }
+ /* Nothing selected now, unlock view so it can be scrolled nice again. */
+ sc->flag &= ~SC_LOCK_SELECTION;
+ if (changed) {
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+ }
+ return OPERATOR_FINISHED;
}
void CLIP_OT_delete_track(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Track";
- ot->idname = "CLIP_OT_delete_track";
- ot->description = "Delete selected tracks";
+ /* identifiers */
+ ot->name = "Delete Track";
+ ot->idname = "CLIP_OT_delete_track";
+ ot->description = "Delete selected tracks";
- /* api callbacks */
- ot->invoke = WM_operator_confirm;
- ot->exec = delete_track_exec;
- ot->poll = ED_space_clip_tracking_poll;
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = delete_track_exec;
+ ot->poll = ED_space_clip_tracking_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** delete marker operator *********************/
static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- const int framenr = ED_space_clip_get_clip_frame_number(sc);
- bool has_selection = false;
- bool changed = false;
-
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- for (MovieTrackingTrack *track = tracksbase->first, *next_track;
- track != NULL;
- track = next_track)
- {
- next_track = track->next;
- if (TRACK_VIEW_SELECTED(sc, track)) {
- MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr);
- if (marker != NULL) {
- has_selection |= track->markersnr > 1;
- clip_delete_marker(C, clip, track, marker);
- changed = true;
- }
- }
- }
-
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first,
- *plane_track_next;
- plane_track != NULL;
- plane_track = plane_track_next)
- {
- plane_track_next = plane_track->next;
- if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
- MovieTrackingPlaneMarker *plane_marker =
- BKE_tracking_plane_marker_get_exact(plane_track, framenr);
- if (plane_marker != NULL) {
- if (plane_track->markersnr == 1) {
- BKE_tracking_plane_track_free(plane_track);
- BLI_freelinkN(plane_tracks_base, plane_track);
- }
- else {
- BKE_tracking_plane_marker_delete(plane_track, framenr);
- }
- changed = true;
- }
- }
- }
-
- if (!has_selection) {
- /* Nothing selected now, unlock view so it can be scrolled nice again. */
- sc->flag &= ~SC_LOCK_SELECTION;
- }
-
- if (!changed) {
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ const int framenr = ED_space_clip_get_clip_frame_number(sc);
+ bool has_selection = false;
+ bool changed = false;
+
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ for (MovieTrackingTrack *track = tracksbase->first, *next_track; track != NULL;
+ track = next_track) {
+ next_track = track->next;
+ if (TRACK_VIEW_SELECTED(sc, track)) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr);
+ if (marker != NULL) {
+ has_selection |= track->markersnr > 1;
+ clip_delete_marker(C, clip, track, marker);
+ changed = true;
+ }
+ }
+ }
+
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first, *plane_track_next;
+ plane_track != NULL;
+ plane_track = plane_track_next) {
+ plane_track_next = plane_track->next;
+ if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get_exact(plane_track,
+ framenr);
+ if (plane_marker != NULL) {
+ if (plane_track->markersnr == 1) {
+ BKE_tracking_plane_track_free(plane_track);
+ BLI_freelinkN(plane_tracks_base, plane_track);
+ }
+ else {
+ BKE_tracking_plane_marker_delete(plane_track, framenr);
+ }
+ changed = true;
+ }
+ }
+ }
+
+ if (!has_selection) {
+ /* Nothing selected now, unlock view so it can be scrolled nice again. */
+ sc->flag &= ~SC_LOCK_SELECTION;
+ }
+
+ if (!changed) {
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_delete_marker(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Marker";
- ot->idname = "CLIP_OT_delete_marker";
- ot->description = "Delete marker for current frame from selected tracks";
+ /* identifiers */
+ ot->name = "Delete Marker";
+ ot->idname = "CLIP_OT_delete_marker";
+ ot->description = "Delete marker for current frame from selected tracks";
- /* api callbacks */
- ot->invoke = WM_operator_confirm;
- ot->exec = delete_marker_exec;
- ot->poll = ED_space_clip_tracking_poll;
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = delete_marker_exec;
+ ot->poll = ED_space_clip_tracking_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** slide marker operator *********************/
enum {
- SLIDE_ACTION_POS = 0,
- SLIDE_ACTION_SIZE,
- SLIDE_ACTION_OFFSET,
- SLIDE_ACTION_TILT_SIZE,
+ SLIDE_ACTION_POS = 0,
+ SLIDE_ACTION_SIZE,
+ SLIDE_ACTION_OFFSET,
+ SLIDE_ACTION_TILT_SIZE,
};
typedef struct {
- short area, action;
- MovieTrackingTrack *track;
- MovieTrackingMarker *marker;
+ short area, action;
+ MovieTrackingTrack *track;
+ MovieTrackingMarker *marker;
- int mval[2];
- int width, height;
- float *min, *max, *pos, *offset, (*corners)[2];
- float spos[2];
+ int mval[2];
+ int width, height;
+ float *min, *max, *pos, *offset, (*corners)[2];
+ float spos[2];
- bool lock, accurate;
+ bool lock, accurate;
- /* Data to restore on cancel. */
- float old_search_min[2], old_search_max[2], old_pos[2], old_offset[2];
- float old_corners[4][2];
- float (*old_markers)[2];
+ /* Data to restore on cancel. */
+ float old_search_min[2], old_search_max[2], old_pos[2], old_offset[2];
+ float old_corners[4][2];
+ float (*old_markers)[2];
} SlideMarkerData;
-static void slide_marker_tilt_slider(const MovieTrackingMarker *marker,
- float r_slider[2])
+static void slide_marker_tilt_slider(const MovieTrackingMarker *marker, float r_slider[2])
{
- add_v2_v2v2(r_slider, marker->pattern_corners[1], marker->pattern_corners[2]);
- add_v2_v2(r_slider, marker->pos);
+ add_v2_v2v2(r_slider, marker->pattern_corners[1], marker->pattern_corners[2]);
+ add_v2_v2(r_slider, marker->pos);
}
static SlideMarkerData *create_slide_marker_data(SpaceClip *sc,
@@ -392,124 +382,107 @@ static SlideMarkerData *create_slide_marker_data(SpaceClip *sc,
int width,
int height)
{
- SlideMarkerData *data = MEM_callocN(sizeof(SlideMarkerData), "slide marker data");
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- marker = BKE_tracking_marker_ensure(track, framenr);
-
- data->area = area;
- data->action = action;
- data->track = track;
- data->marker = marker;
-
- if (area == TRACK_AREA_POINT) {
- data->pos = marker->pos;
- data->offset = track->offset;
- }
- else if (area == TRACK_AREA_PAT) {
- if (action == SLIDE_ACTION_SIZE) {
- data->corners = marker->pattern_corners;
- }
- else if (action == SLIDE_ACTION_OFFSET) {
- data->pos = marker->pos;
- data->offset = track->offset;
- data->old_markers = MEM_callocN(
- sizeof(*data->old_markers) * track->markersnr,
- "slide marekrs");
- for (int a = 0; a < track->markersnr; a++) {
- copy_v2_v2(data->old_markers[a], track->markers[a].pos);
- }
- }
- else if (action == SLIDE_ACTION_POS) {
- data->corners = marker->pattern_corners;
- data->pos = marker->pattern_corners[corner];
- copy_v2_v2(data->spos, data->pos);
- }
- else if (action == SLIDE_ACTION_TILT_SIZE) {
- data->corners = marker->pattern_corners;
- slide_marker_tilt_slider(marker, data->spos);
- }
- }
- else if (area == TRACK_AREA_SEARCH) {
- data->min = marker->search_min;
- data->max = marker->search_max;
- }
-
- data->mval[0] = event->mval[0];
- data->mval[1] = event->mval[1];
-
- data->width = width;
- data->height = height;
-
- if (action == SLIDE_ACTION_SIZE) {
- data->lock = true;
- }
-
- /* Backup marker's settings. */
- memcpy(data->old_corners, marker->pattern_corners, sizeof(data->old_corners));
- copy_v2_v2(data->old_search_min, marker->search_min);
- copy_v2_v2(data->old_search_max, marker->search_max);
- copy_v2_v2(data->old_pos, marker->pos);
- copy_v2_v2(data->old_offset, track->offset);
-
- return data;
-}
-
-static float mouse_to_slide_zone_distance_squared(
- const float co[2],
- const float slide_zone[2],
- int width,
- int height)
-{
- 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]);
+ SlideMarkerData *data = MEM_callocN(sizeof(SlideMarkerData), "slide marker data");
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ marker = BKE_tracking_marker_ensure(track, framenr);
+
+ data->area = area;
+ data->action = action;
+ data->track = track;
+ data->marker = marker;
+
+ if (area == TRACK_AREA_POINT) {
+ data->pos = marker->pos;
+ data->offset = track->offset;
+ }
+ else if (area == TRACK_AREA_PAT) {
+ if (action == SLIDE_ACTION_SIZE) {
+ data->corners = marker->pattern_corners;
+ }
+ else if (action == SLIDE_ACTION_OFFSET) {
+ data->pos = marker->pos;
+ data->offset = track->offset;
+ data->old_markers = MEM_callocN(sizeof(*data->old_markers) * track->markersnr,
+ "slide marekrs");
+ for (int a = 0; a < track->markersnr; a++) {
+ copy_v2_v2(data->old_markers[a], track->markers[a].pos);
+ }
+ }
+ else if (action == SLIDE_ACTION_POS) {
+ data->corners = marker->pattern_corners;
+ data->pos = marker->pattern_corners[corner];
+ copy_v2_v2(data->spos, data->pos);
+ }
+ else if (action == SLIDE_ACTION_TILT_SIZE) {
+ data->corners = marker->pattern_corners;
+ slide_marker_tilt_slider(marker, data->spos);
+ }
+ }
+ else if (area == TRACK_AREA_SEARCH) {
+ data->min = marker->search_min;
+ data->max = marker->search_max;
+ }
+
+ data->mval[0] = event->mval[0];
+ data->mval[1] = event->mval[1];
+
+ data->width = width;
+ data->height = height;
+
+ if (action == SLIDE_ACTION_SIZE) {
+ data->lock = true;
+ }
+
+ /* Backup marker's settings. */
+ memcpy(data->old_corners, marker->pattern_corners, sizeof(data->old_corners));
+ copy_v2_v2(data->old_search_min, marker->search_min);
+ copy_v2_v2(data->old_search_max, marker->search_max);
+ copy_v2_v2(data->old_pos, marker->pos);
+ copy_v2_v2(data->old_offset, track->offset);
+
+ return data;
+}
+
+static float mouse_to_slide_zone_distance_squared(const float co[2],
+ const float slide_zone[2],
+ int width,
+ int height)
+{
+ 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]);
}
static float mouse_to_search_corner_distance_squared(
- const MovieTrackingMarker *marker,
- const float co[2],
- int corner,
- int width,
- int height)
-{
- float side_zone[2];
- if (corner == 0) {
- side_zone[0] = marker->pos[0] + marker->search_max[0];
- side_zone[1] = marker->pos[1] + marker->search_min[1];
- }
- else {
- side_zone[0] = marker->pos[0] + marker->search_min[0];
- side_zone[1] = marker->pos[1] + marker->search_max[1];
- }
- return mouse_to_slide_zone_distance_squared(co,
- side_zone,
- width,
- height);
+ const MovieTrackingMarker *marker, const float co[2], int corner, int width, int height)
+{
+ float side_zone[2];
+ if (corner == 0) {
+ side_zone[0] = marker->pos[0] + marker->search_max[0];
+ side_zone[1] = marker->pos[1] + marker->search_min[1];
+ }
+ else {
+ side_zone[0] = marker->pos[0] + marker->search_min[0];
+ side_zone[1] = marker->pos[1] + marker->search_max[1];
+ }
+ return mouse_to_slide_zone_distance_squared(co, side_zone, width, height);
}
static float mouse_to_closest_pattern_corner_distance_squared(
- const MovieTrackingMarker *marker,
- const float co[2],
- int width,
- int height,
- int *r_corner)
-{
- float min_distance_squared = FLT_MAX;
- for (int i = 0; i < 4; i++) {
- float corner_co[2];
- add_v2_v2v2(corner_co, marker->pattern_corners[i], marker->pos);
- float distance_squared = mouse_to_slide_zone_distance_squared(co,
- corner_co,
- width,
- height);
- if (distance_squared < min_distance_squared) {
- min_distance_squared = distance_squared;
- *r_corner = i;
- }
- }
- return min_distance_squared;
+ const MovieTrackingMarker *marker, const float co[2], int width, int height, int *r_corner)
+{
+ float min_distance_squared = FLT_MAX;
+ for (int i = 0; i < 4; i++) {
+ float corner_co[2];
+ add_v2_v2v2(corner_co, marker->pattern_corners[i], marker->pos);
+ float distance_squared = mouse_to_slide_zone_distance_squared(co, corner_co, width, height);
+ if (distance_squared < min_distance_squared) {
+ min_distance_squared = distance_squared;
+ *r_corner = i;
+ }
+ }
+ return min_distance_squared;
}
static float mouse_to_offset_distance_squared(const MovieTrackingTrack *track,
@@ -518,12 +491,9 @@ static float mouse_to_offset_distance_squared(const MovieTrackingTrack *track,
int width,
int height)
{
- float pos[2];
- add_v2_v2v2(pos, marker->pos, track->offset);
- return mouse_to_slide_zone_distance_squared(co,
- pos,
- width,
- height);
+ float pos[2];
+ add_v2_v2v2(pos, marker->pos, track->offset);
+ return mouse_to_slide_zone_distance_squared(co, pos, width, height);
}
static int mouse_to_tilt_distance_squared(const MovieTrackingMarker *marker,
@@ -531,1719 +501,1614 @@ static int mouse_to_tilt_distance_squared(const MovieTrackingMarker *marker,
int width,
int height)
{
- float slider[2];
- slide_marker_tilt_slider(marker, slider);
- return mouse_to_slide_zone_distance_squared(co,
- slider,
- width,
- height);
+ float slider[2];
+ slide_marker_tilt_slider(marker, slider);
+ return mouse_to_slide_zone_distance_squared(co, slider, width, height);
}
static bool slide_check_corners(float (*corners)[2])
{
- int i, next, prev;
- float cross = 0.0f;
- float p[2] = {0.0f, 0.0f};
-
- if (!isect_point_quad_v2(p, corners[0], corners[1], corners[2], corners[3]))
- return false;
-
- for (i = 0; i < 4; i++) {
- float v1[2], v2[2], cur_cross;
-
- next = (i + 1) % 4;
- prev = (4 + i - 1) % 4;
-
- sub_v2_v2v2(v1, corners[i], corners[prev]);
- sub_v2_v2v2(v2, corners[next], corners[i]);
-
- cur_cross = cross_v2v2(v1, v2);
-
- if (fabsf(cur_cross) > FLT_EPSILON) {
- if (cross == 0.0f) {
- cross = cur_cross;
- }
- else if (cross * cur_cross < 0.0f) {
- return false;
- }
- }
- }
-
- return true;
-}
-
-MovieTrackingTrack *tracking_marker_check_slide(bContext *C,
- const wmEvent *event,
- int *area_r,
- int *action_r,
- int *corner_r)
-{
- const float distance_clip_squared = 12.0f * 12.0f;
- SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
-
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTrackingTrack *track;
- int width, height;
- float co[2];
- ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
- int framenr = ED_space_clip_get_clip_frame_number(sc);
- float global_min_distance_squared = FLT_MAX;
-
- /* Sliding zone designator which is the closest to the mouse
- * across all the tracks.
- */
- int min_action = -1, min_area = 0, min_corner = -1;
- MovieTrackingTrack *min_track = NULL;
-
- ED_space_clip_get_size(sc, &width, &height);
-
- if (width == 0 || height == 0)
- return NULL;
-
- ED_clip_mouse_pos(sc, ar, event->mval, co);
-
- track = tracksbase->first;
- while (track) {
- if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
- const MovieTrackingMarker *marker = BKE_tracking_marker_get(track,
- framenr);
- /* Sliding zone designator which is the closest to the mouse for
- * the current tracks.
- */
- float min_distance_squared = FLT_MAX;
- int action = -1, area = 0, corner = -1;
-
- if ((marker->flag & MARKER_DISABLED) == 0) {
- float distance_squared;
-
- /* We start checking with whether the mouse is close enough
- * to the pattern offset area.
- */
- distance_squared = mouse_to_offset_distance_squared(track,
- marker,
- co,
- width,
- height);
- area = TRACK_AREA_POINT;
- action = SLIDE_ACTION_POS;
-
- /* NOTE: All checks here are assuming there's no maximum distance
- * limit, so checks are quite simple here.
- * Actual distance clipping happens later once all the sliding
- * zones are checked.
- */
- min_distance_squared = distance_squared;
-
- /* If search area is visible, check how close to it's sliding
- * zones mouse is.
- */
- if (sc->flag & SC_SHOW_MARKER_SEARCH) {
- distance_squared = mouse_to_search_corner_distance_squared(
- marker,
- co,
- 1,
- width,
- height);
- if (distance_squared < min_distance_squared) {
- area = TRACK_AREA_SEARCH;
- action = SLIDE_ACTION_OFFSET;
- min_distance_squared = distance_squared;
- }
-
- distance_squared = mouse_to_search_corner_distance_squared(
- marker,
- co,
- 0,
- width,
- height);
- if (distance_squared < min_distance_squared) {
- area = TRACK_AREA_SEARCH;
- action = SLIDE_ACTION_SIZE;
- min_distance_squared = distance_squared;
- }
- }
-
- /* If pattern area is visible, check which corner is closest to
- * the mouse.
- */
- if (sc->flag & SC_SHOW_MARKER_PATTERN) {
- int current_corner = -1;
- distance_squared =
- mouse_to_closest_pattern_corner_distance_squared(
- marker,
- co,
- width,
- height,
- &current_corner);
- if (distance_squared < min_distance_squared) {
- area = TRACK_AREA_PAT;
- action = SLIDE_ACTION_POS;
- corner = current_corner;
- min_distance_squared = distance_squared;
- }
-
- /* Here we also check whether the mouse is actually closer to
- * the widget which controls scale and tilt.
- */
- distance_squared = mouse_to_tilt_distance_squared(marker,
- co,
- width,
- height);
- if (distance_squared < min_distance_squared) {
- area = TRACK_AREA_PAT;
- action = SLIDE_ACTION_TILT_SIZE;
- min_distance_squared = distance_squared;
- }
- }
-
- if (min_distance_squared < global_min_distance_squared) {
- min_area = area;
- min_action = action;
- min_corner = corner;
- min_track = track;
- global_min_distance_squared = min_distance_squared;
- }
- }
- }
-
- track = track->next;
- }
-
- if (global_min_distance_squared < distance_clip_squared / sc->zoom) {
- if (area_r) {
- *area_r = min_area;
- }
- if (action_r) {
- *action_r = min_action;
- }
- if (corner_r) {
- *corner_r = min_corner;
- }
- return min_track;
- }
- return NULL;
+ int i, next, prev;
+ float cross = 0.0f;
+ float p[2] = {0.0f, 0.0f};
+
+ if (!isect_point_quad_v2(p, corners[0], corners[1], corners[2], corners[3]))
+ return false;
+
+ for (i = 0; i < 4; i++) {
+ float v1[2], v2[2], cur_cross;
+
+ next = (i + 1) % 4;
+ prev = (4 + i - 1) % 4;
+
+ sub_v2_v2v2(v1, corners[i], corners[prev]);
+ sub_v2_v2v2(v2, corners[next], corners[i]);
+
+ cur_cross = cross_v2v2(v1, v2);
+
+ if (fabsf(cur_cross) > FLT_EPSILON) {
+ if (cross == 0.0f) {
+ cross = cur_cross;
+ }
+ else if (cross * cur_cross < 0.0f) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+MovieTrackingTrack *tracking_marker_check_slide(
+ bContext *C, const wmEvent *event, int *area_r, int *action_r, int *corner_r)
+{
+ const float distance_clip_squared = 12.0f * 12.0f;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTrackingTrack *track;
+ int width, height;
+ float co[2];
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+ float global_min_distance_squared = FLT_MAX;
+
+ /* Sliding zone designator which is the closest to the mouse
+ * across all the tracks.
+ */
+ int min_action = -1, min_area = 0, min_corner = -1;
+ MovieTrackingTrack *min_track = NULL;
+
+ ED_space_clip_get_size(sc, &width, &height);
+
+ if (width == 0 || height == 0)
+ return NULL;
+
+ ED_clip_mouse_pos(sc, ar, event->mval, co);
+
+ track = tracksbase->first;
+ while (track) {
+ if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
+ const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+ /* Sliding zone designator which is the closest to the mouse for
+ * the current tracks.
+ */
+ float min_distance_squared = FLT_MAX;
+ int action = -1, area = 0, corner = -1;
+
+ if ((marker->flag & MARKER_DISABLED) == 0) {
+ float distance_squared;
+
+ /* We start checking with whether the mouse is close enough
+ * to the pattern offset area.
+ */
+ distance_squared = mouse_to_offset_distance_squared(track, marker, co, width, height);
+ area = TRACK_AREA_POINT;
+ action = SLIDE_ACTION_POS;
+
+ /* NOTE: All checks here are assuming there's no maximum distance
+ * limit, so checks are quite simple here.
+ * Actual distance clipping happens later once all the sliding
+ * zones are checked.
+ */
+ min_distance_squared = distance_squared;
+
+ /* If search area is visible, check how close to it's sliding
+ * zones mouse is.
+ */
+ if (sc->flag & SC_SHOW_MARKER_SEARCH) {
+ distance_squared = mouse_to_search_corner_distance_squared(marker, co, 1, width, height);
+ if (distance_squared < min_distance_squared) {
+ area = TRACK_AREA_SEARCH;
+ action = SLIDE_ACTION_OFFSET;
+ min_distance_squared = distance_squared;
+ }
+
+ distance_squared = mouse_to_search_corner_distance_squared(marker, co, 0, width, height);
+ if (distance_squared < min_distance_squared) {
+ area = TRACK_AREA_SEARCH;
+ action = SLIDE_ACTION_SIZE;
+ min_distance_squared = distance_squared;
+ }
+ }
+
+ /* If pattern area is visible, check which corner is closest to
+ * the mouse.
+ */
+ if (sc->flag & SC_SHOW_MARKER_PATTERN) {
+ int current_corner = -1;
+ distance_squared = mouse_to_closest_pattern_corner_distance_squared(
+ marker, co, width, height, &current_corner);
+ if (distance_squared < min_distance_squared) {
+ area = TRACK_AREA_PAT;
+ action = SLIDE_ACTION_POS;
+ corner = current_corner;
+ min_distance_squared = distance_squared;
+ }
+
+ /* Here we also check whether the mouse is actually closer to
+ * the widget which controls scale and tilt.
+ */
+ distance_squared = mouse_to_tilt_distance_squared(marker, co, width, height);
+ if (distance_squared < min_distance_squared) {
+ area = TRACK_AREA_PAT;
+ action = SLIDE_ACTION_TILT_SIZE;
+ min_distance_squared = distance_squared;
+ }
+ }
+
+ if (min_distance_squared < global_min_distance_squared) {
+ min_area = area;
+ min_action = action;
+ min_corner = corner;
+ min_track = track;
+ global_min_distance_squared = min_distance_squared;
+ }
+ }
+ }
+
+ track = track->next;
+ }
+
+ if (global_min_distance_squared < distance_clip_squared / sc->zoom) {
+ if (area_r) {
+ *area_r = min_area;
+ }
+ if (action_r) {
+ *action_r = min_action;
+ }
+ if (corner_r) {
+ *corner_r = min_corner;
+ }
+ return min_track;
+ }
+ return NULL;
}
static void *slide_marker_customdata(bContext *C, const wmEvent *event)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
- MovieTrackingTrack *track;
- int width, height;
- float co[2];
- void *customdata = NULL;
- int framenr = ED_space_clip_get_clip_frame_number(sc);
- int area, action, corner;
+ MovieTrackingTrack *track;
+ int width, height;
+ float co[2];
+ void *customdata = NULL;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+ int area, action, corner;
- ED_space_clip_get_size(sc, &width, &height);
+ ED_space_clip_get_size(sc, &width, &height);
- if (width == 0 || height == 0) {
- return NULL;
- }
+ if (width == 0 || height == 0) {
+ return NULL;
+ }
- ED_clip_mouse_pos(sc, ar, event->mval, co);
+ ED_clip_mouse_pos(sc, ar, event->mval, co);
- track = tracking_marker_check_slide(C, event, &area, &action, &corner);
- if (track != NULL) {
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
- customdata = create_slide_marker_data(sc,
- track,
- marker,
- event,
- area,
- corner,
- action,
- width,
- height);
- }
+ track = tracking_marker_check_slide(C, event, &area, &action, &corner);
+ if (track != NULL) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+ customdata = create_slide_marker_data(
+ sc, track, marker, event, area, corner, action, width, height);
+ }
- return customdata;
+ return customdata;
}
static int slide_marker_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- SlideMarkerData *slidedata = slide_marker_customdata(C, event);
- if (slidedata != NULL) {
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
+ SlideMarkerData *slidedata = slide_marker_customdata(C, event);
+ if (slidedata != NULL) {
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
- tracking->act_track = slidedata->track;
- tracking->act_plane_track = NULL;
+ tracking->act_track = slidedata->track;
+ tracking->act_plane_track = NULL;
- op->customdata = slidedata;
+ op->customdata = slidedata;
- clip_tracking_hide_cursor(C);
- WM_event_add_modal_handler(C, op);
+ clip_tracking_hide_cursor(C);
+ WM_event_add_modal_handler(C, op);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
- return OPERATOR_RUNNING_MODAL;
- }
+ return OPERATOR_RUNNING_MODAL;
+ }
- return OPERATOR_PASS_THROUGH;
+ return OPERATOR_PASS_THROUGH;
}
static void cancel_mouse_slide(SlideMarkerData *data)
{
- MovieTrackingTrack *track = data->track;
- MovieTrackingMarker *marker = data->marker;
+ MovieTrackingTrack *track = data->track;
+ MovieTrackingMarker *marker = data->marker;
- memcpy(marker->pattern_corners,
- data->old_corners,
- sizeof(marker->pattern_corners));
- copy_v2_v2(marker->search_min, data->old_search_min);
- copy_v2_v2(marker->search_max, data->old_search_max);
- copy_v2_v2(marker->pos, data->old_pos);
- copy_v2_v2(track->offset, data->old_offset);
+ memcpy(marker->pattern_corners, data->old_corners, sizeof(marker->pattern_corners));
+ copy_v2_v2(marker->search_min, data->old_search_min);
+ copy_v2_v2(marker->search_max, data->old_search_max);
+ copy_v2_v2(marker->pos, data->old_pos);
+ copy_v2_v2(track->offset, data->old_offset);
- if (data->old_markers != NULL) {
- for (int a = 0; a < data->track->markersnr; a++) {
- copy_v2_v2(data->track->markers[a].pos, data->old_markers[a]);
- }
- }
+ if (data->old_markers != NULL) {
+ for (int a = 0; a < data->track->markersnr; a++) {
+ copy_v2_v2(data->track->markers[a].pos, data->old_markers[a]);
+ }
+ }
}
static void apply_mouse_slide(bContext *C, SlideMarkerData *data)
{
- if (data->area == TRACK_AREA_POINT) {
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first;
- plane_track != NULL;
- plane_track = plane_track->next)
- {
- if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
- if (BKE_tracking_plane_track_has_point_track(plane_track,
- data->track))
- {
- BKE_tracking_track_plane_from_existing_motion(plane_track,
- framenr);
- }
- }
- }
- }
+ if (data->area == TRACK_AREA_POINT) {
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first; plane_track != NULL;
+ plane_track = plane_track->next) {
+ if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
+ if (BKE_tracking_plane_track_has_point_track(plane_track, data->track)) {
+ BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
+ }
+ }
+ }
+ }
}
static void free_slide_data(SlideMarkerData *data)
{
- if (data->old_markers != NULL) {
- MEM_freeN(data->old_markers);
- }
- MEM_freeN(data);
+ if (data->old_markers != NULL) {
+ MEM_freeN(data->old_markers);
+ }
+ MEM_freeN(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);
-
- SlideMarkerData *data = (SlideMarkerData *)op->customdata;
- float dx, dy, mdelta[2];
-
- switch (event->type) {
- case LEFTCTRLKEY:
- case RIGHTCTRLKEY:
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
- if (data->action == SLIDE_ACTION_SIZE) {
- if (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY)) {
- data->lock = event->val == KM_RELEASE;
- }
- }
-
- if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) {
- data->accurate = event->val == KM_PRESS;
- }
- ATTR_FALLTHROUGH;
- case MOUSEMOVE:
- mdelta[0] = event->mval[0] - data->mval[0];
- mdelta[1] = event->mval[1] - data->mval[1];
-
- dx = mdelta[0] / data->width / sc->zoom;
-
- if (data->lock) {
- dy = -dx / data->height * data->width;
- }
- else {
- dy = mdelta[1] / data->height / sc->zoom;
- }
-
- if (data->accurate) {
- dx /= 5.0f;
- dy /= 5.0f;
- }
-
- if (data->area == TRACK_AREA_POINT) {
- if (data->action == SLIDE_ACTION_OFFSET) {
- data->offset[0] = data->old_offset[0] + dx;
- data->offset[1] = data->old_offset[1] + dy;
- }
- else {
- data->pos[0] = data->old_pos[0] + dx;
- data->pos[1] = data->old_pos[1] + dy;
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- DEG_id_tag_update(&sc->clip->id, 0);
- }
- else if (data->area == TRACK_AREA_PAT) {
- if (data->action == SLIDE_ACTION_SIZE) {
- float start[2], end[2];
- float scale;
-
- ED_clip_point_stable_pos(sc,
- ar,
- data->mval[0],
- data->mval[1],
- &start[0],
- &start[1]);
-
- sub_v2_v2(start, data->old_pos);
-
- if (len_squared_v2(start) != 0.0f) {
- float mval[2];
-
- if (data->accurate) {
- mval[0] = data->mval[0] + (event->mval[0] - data->mval[0]) / 5.0f;
- mval[1] = data->mval[1] + (event->mval[1] - data->mval[1]) / 5.0f;
- }
- else {
- mval[0] = event->mval[0];
- mval[1] = event->mval[1];
- }
-
- ED_clip_point_stable_pos(sc,
- ar,
- mval[0],
- mval[1],
- &end[0],
- &end[1]);
-
- sub_v2_v2(end, data->old_pos);
- scale = len_v2(end) / len_v2(start);
-
- if (scale > 0.0f) {
- for (int a = 0; a < 4; a++) {
- mul_v2_v2fl(data->corners[a],
- data->old_corners[a],
- scale);
- }
- }
- }
-
- BKE_tracking_marker_clamp(data->marker, CLAMP_PAT_DIM);
- }
- else if (data->action == SLIDE_ACTION_OFFSET) {
- float d[2] = {dx, dy};
- for (int a = 0; a < data->track->markersnr; a++) {
- add_v2_v2v2(data->track->markers[a].pos,
- data->old_markers[a],
- d);
- }
- sub_v2_v2v2(data->offset, data->old_offset, d);
- }
- else if (data->action == SLIDE_ACTION_POS) {
- float spos[2];
-
- copy_v2_v2(spos, data->pos);
-
- data->pos[0] = data->spos[0] + dx;
- data->pos[1] = data->spos[1] + dy;
-
- if (!slide_check_corners(data->corners)) {
- copy_v2_v2(data->pos, spos);
- }
-
- /* Currently only patterns are allowed to have such
- * combination of event and data.
- */
- BKE_tracking_marker_clamp(data->marker, CLAMP_PAT_DIM);
- }
- else if (data->action == SLIDE_ACTION_TILT_SIZE) {
- float start[2], end[2];
- float scale = 1.0f, angle = 0.0f;
- float mval[2];
-
- if (data->accurate) {
- mval[0] = data->mval[0] + (event->mval[0] - data->mval[0]) / 5.0f;
- mval[1] = data->mval[1] + (event->mval[1] - data->mval[1]) / 5.0f;
- }
- else {
- mval[0] = event->mval[0];
- mval[1] = event->mval[1];
- }
-
- sub_v2_v2v2(start, data->spos, data->old_pos);
-
- ED_clip_point_stable_pos(sc, ar, mval[0], mval[1], &end[0], &end[1]);
- sub_v2_v2(end, data->old_pos);
-
- if (len_squared_v2(start) != 0.0f) {
- scale = len_v2(end) / len_v2(start);
-
- if (scale < 0.0f) {
- scale = 0.0;
- }
- }
-
- angle = -angle_signed_v2v2(start, end);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = 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:
+ if (data->action == SLIDE_ACTION_SIZE) {
+ if (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY)) {
+ data->lock = event->val == KM_RELEASE;
+ }
+ }
+
+ if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) {
+ data->accurate = event->val == KM_PRESS;
+ }
+ ATTR_FALLTHROUGH;
+ case MOUSEMOVE:
+ mdelta[0] = event->mval[0] - data->mval[0];
+ mdelta[1] = event->mval[1] - data->mval[1];
+
+ dx = mdelta[0] / data->width / sc->zoom;
+
+ if (data->lock) {
+ dy = -dx / data->height * data->width;
+ }
+ else {
+ dy = mdelta[1] / data->height / sc->zoom;
+ }
+
+ if (data->accurate) {
+ dx /= 5.0f;
+ dy /= 5.0f;
+ }
+
+ if (data->area == TRACK_AREA_POINT) {
+ if (data->action == SLIDE_ACTION_OFFSET) {
+ data->offset[0] = data->old_offset[0] + dx;
+ data->offset[1] = data->old_offset[1] + dy;
+ }
+ else {
+ data->pos[0] = data->old_pos[0] + dx;
+ data->pos[1] = data->old_pos[1] + dy;
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ DEG_id_tag_update(&sc->clip->id, 0);
+ }
+ else if (data->area == TRACK_AREA_PAT) {
+ if (data->action == SLIDE_ACTION_SIZE) {
+ float start[2], end[2];
+ float scale;
+
+ ED_clip_point_stable_pos(sc, ar, data->mval[0], data->mval[1], &start[0], &start[1]);
+
+ sub_v2_v2(start, data->old_pos);
+
+ if (len_squared_v2(start) != 0.0f) {
+ float mval[2];
+
+ if (data->accurate) {
+ mval[0] = data->mval[0] + (event->mval[0] - data->mval[0]) / 5.0f;
+ mval[1] = data->mval[1] + (event->mval[1] - data->mval[1]) / 5.0f;
+ }
+ else {
+ mval[0] = event->mval[0];
+ mval[1] = event->mval[1];
+ }
+
+ ED_clip_point_stable_pos(sc, ar, mval[0], mval[1], &end[0], &end[1]);
+
+ sub_v2_v2(end, data->old_pos);
+ scale = len_v2(end) / len_v2(start);
+
+ if (scale > 0.0f) {
+ for (int a = 0; a < 4; a++) {
+ mul_v2_v2fl(data->corners[a], data->old_corners[a], scale);
+ }
+ }
+ }
+
+ BKE_tracking_marker_clamp(data->marker, CLAMP_PAT_DIM);
+ }
+ else if (data->action == SLIDE_ACTION_OFFSET) {
+ float d[2] = {dx, dy};
+ for (int a = 0; a < data->track->markersnr; a++) {
+ add_v2_v2v2(data->track->markers[a].pos, data->old_markers[a], d);
+ }
+ sub_v2_v2v2(data->offset, data->old_offset, d);
+ }
+ else if (data->action == SLIDE_ACTION_POS) {
+ float spos[2];
+
+ copy_v2_v2(spos, data->pos);
+
+ data->pos[0] = data->spos[0] + dx;
+ data->pos[1] = data->spos[1] + dy;
+
+ if (!slide_check_corners(data->corners)) {
+ copy_v2_v2(data->pos, spos);
+ }
+
+ /* Currently only patterns are allowed to have such
+ * combination of event and data.
+ */
+ BKE_tracking_marker_clamp(data->marker, CLAMP_PAT_DIM);
+ }
+ else if (data->action == SLIDE_ACTION_TILT_SIZE) {
+ float start[2], end[2];
+ float scale = 1.0f, angle = 0.0f;
+ float mval[2];
+
+ if (data->accurate) {
+ mval[0] = data->mval[0] + (event->mval[0] - data->mval[0]) / 5.0f;
+ mval[1] = data->mval[1] + (event->mval[1] - data->mval[1]) / 5.0f;
+ }
+ else {
+ mval[0] = event->mval[0];
+ mval[1] = event->mval[1];
+ }
+
+ sub_v2_v2v2(start, data->spos, data->old_pos);
+
+ ED_clip_point_stable_pos(sc, ar, mval[0], mval[1], &end[0], &end[1]);
+ sub_v2_v2(end, data->old_pos);
- for (int a = 0; a < 4; a++) {
- float vec[2];
+ if (len_squared_v2(start) != 0.0f) {
+ scale = len_v2(end) / len_v2(start);
- mul_v2_v2fl(data->corners[a], data->old_corners[a], scale);
+ if (scale < 0.0f) {
+ scale = 0.0;
+ }
+ }
- copy_v2_v2(vec, data->corners[a]);
- vec[0] *= data->width;
- vec[1] *= data->height;
+ angle = -angle_signed_v2v2(start, end);
- data->corners[a][0] = (vec[0] * cosf(angle) - vec[1] * sinf(angle)) / data->width;
- data->corners[a][1] = (vec[1] * cosf(angle) + vec[0] * sinf(angle)) / data->height;
- }
+ for (int a = 0; a < 4; a++) {
+ float vec[2];
- BKE_tracking_marker_clamp(data->marker, CLAMP_PAT_DIM);
+ mul_v2_v2fl(data->corners[a], data->old_corners[a], scale);
- }
- }
- else if (data->area == TRACK_AREA_SEARCH) {
- if (data->action == SLIDE_ACTION_SIZE) {
- data->min[0] = data->old_search_min[0] - dx;
- data->max[0] = data->old_search_max[0] + dx;
+ copy_v2_v2(vec, data->corners[a]);
+ vec[0] *= data->width;
+ vec[1] *= data->height;
- data->min[1] = data->old_search_min[1] + dy;
- data->max[1] = data->old_search_max[1] - dy;
+ data->corners[a][0] = (vec[0] * cosf(angle) - vec[1] * sinf(angle)) / data->width;
+ data->corners[a][1] = (vec[1] * cosf(angle) + vec[0] * sinf(angle)) / data->height;
+ }
- BKE_tracking_marker_clamp(data->marker, CLAMP_SEARCH_DIM);
- }
- else if (data->area == TRACK_AREA_SEARCH) {
- float d[2] = {dx, dy};
- add_v2_v2v2(data->min, data->old_search_min, d);
- add_v2_v2v2(data->max, data->old_search_max, d);
- }
+ BKE_tracking_marker_clamp(data->marker, CLAMP_PAT_DIM);
+ }
+ }
+ else if (data->area == TRACK_AREA_SEARCH) {
+ if (data->action == SLIDE_ACTION_SIZE) {
+ data->min[0] = data->old_search_min[0] - dx;
+ data->max[0] = data->old_search_max[0] + dx;
- BKE_tracking_marker_clamp(data->marker, CLAMP_SEARCH_POS);
- }
+ data->min[1] = data->old_search_min[1] + dy;
+ data->max[1] = data->old_search_max[1] - dy;
- data->marker->flag &= ~MARKER_TRACKED;
+ BKE_tracking_marker_clamp(data->marker, CLAMP_SEARCH_DIM);
+ }
+ else if (data->area == TRACK_AREA_SEARCH) {
+ float d[2] = {dx, dy};
+ add_v2_v2v2(data->min, data->old_search_min, d);
+ add_v2_v2v2(data->max, data->old_search_max, d);
+ }
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
+ BKE_tracking_marker_clamp(data->marker, CLAMP_SEARCH_POS);
+ }
- break;
+ data->marker->flag &= ~MARKER_TRACKED;
- case LEFTMOUSE:
- if (event->val == KM_RELEASE) {
- apply_mouse_slide(C, op->customdata);
- free_slide_data(op->customdata);
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
- clip_tracking_show_cursor(C);
+ break;
- return OPERATOR_FINISHED;
- }
+ case LEFTMOUSE:
+ if (event->val == KM_RELEASE) {
+ apply_mouse_slide(C, op->customdata);
+ free_slide_data(op->customdata);
- break;
+ clip_tracking_show_cursor(C);
- case ESCKEY:
- cancel_mouse_slide(op->customdata);
+ return OPERATOR_FINISHED;
+ }
- free_slide_data(op->customdata);
+ break;
- clip_tracking_show_cursor(C);
+ case ESCKEY:
+ cancel_mouse_slide(op->customdata);
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
+ free_slide_data(op->customdata);
- return OPERATOR_CANCELLED;
- }
+ clip_tracking_show_cursor(C);
- return OPERATOR_RUNNING_MODAL;
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
+
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
void CLIP_OT_slide_marker(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Slide Marker";
- ot->description = "Slide marker areas";
- ot->idname = "CLIP_OT_slide_marker";
+ /* identifiers */
+ ot->name = "Slide Marker";
+ ot->description = "Slide marker areas";
+ ot->idname = "CLIP_OT_slide_marker";
- /* api callbacks */
- ot->poll = ED_space_clip_tracking_poll;
- ot->invoke = slide_marker_invoke;
- ot->modal = slide_marker_modal;
+ /* api callbacks */
+ ot->poll = ED_space_clip_tracking_poll;
+ ot->invoke = slide_marker_invoke;
+ ot->modal = slide_marker_modal;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
- /* properties */
- RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX,
- "Offset",
- "Offset in floating point units, 1.0 is the width and height of the image",
- -FLT_MAX, FLT_MAX);
+ /* properties */
+ RNA_def_float_vector(ot->srna,
+ "offset",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Offset",
+ "Offset in floating point units, 1.0 is the width and height of the image",
+ -FLT_MAX,
+ FLT_MAX);
}
/********************** clear track operator *********************/
static int clear_track_path_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- int action = RNA_enum_get(op->ptr, "action");
- const bool clear_active = RNA_boolean_get(op->ptr, "clear_active");
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- if (clear_active) {
- MovieTrackingTrack *track = BKE_tracking_track_get_active(tracking);
- if (track != NULL) {
- BKE_tracking_track_path_clear(track, framenr, action);
- }
- }
- else {
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- if (TRACK_VIEW_SELECTED(sc, track)) {
- BKE_tracking_track_path_clear(track, framenr, action);
- }
- }
- }
-
- BKE_tracking_dopesheet_tag_update(tracking);
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ int action = RNA_enum_get(op->ptr, "action");
+ const bool clear_active = RNA_boolean_get(op->ptr, "clear_active");
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ if (clear_active) {
+ MovieTrackingTrack *track = BKE_tracking_track_get_active(tracking);
+ if (track != NULL) {
+ BKE_tracking_track_path_clear(track, framenr, action);
+ }
+ }
+ else {
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ if (TRACK_VIEW_SELECTED(sc, track)) {
+ BKE_tracking_track_path_clear(track, framenr, action);
+ }
+ }
+ }
+
+ BKE_tracking_dopesheet_tag_update(tracking);
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_clear_track_path(wmOperatorType *ot)
{
- static const EnumPropertyItem clear_path_actions[] = {
- {TRACK_CLEAR_UPTO, "UPTO", 0, "Clear up-to", "Clear path up to current frame"},
- {TRACK_CLEAR_REMAINED, "REMAINED", 0, "Clear remained", "Clear path at remaining frames (after current)"},
- {TRACK_CLEAR_ALL, "ALL", 0, "Clear all", "Clear the whole path"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Clear Track Path";
- ot->description = "Clear tracks after/before current position or clear the whole track";
- ot->idname = "CLIP_OT_clear_track_path";
-
- /* api callbacks */
- ot->exec = clear_track_path_exec;
- ot->poll = ED_space_clip_tracking_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "action", clear_path_actions, TRACK_CLEAR_REMAINED, "Action", "Clear action to execute");
- RNA_def_boolean(ot->srna, "clear_active", 0, "Clear Active", "Clear active track only instead of all selected tracks");
+ static const EnumPropertyItem clear_path_actions[] = {
+ {TRACK_CLEAR_UPTO, "UPTO", 0, "Clear up-to", "Clear path up to current frame"},
+ {TRACK_CLEAR_REMAINED,
+ "REMAINED",
+ 0,
+ "Clear remained",
+ "Clear path at remaining frames (after current)"},
+ {TRACK_CLEAR_ALL, "ALL", 0, "Clear all", "Clear the whole path"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Clear Track Path";
+ ot->description = "Clear tracks after/before current position or clear the whole track";
+ ot->idname = "CLIP_OT_clear_track_path";
+
+ /* api callbacks */
+ ot->exec = clear_track_path_exec;
+ ot->poll = ED_space_clip_tracking_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna,
+ "action",
+ clear_path_actions,
+ TRACK_CLEAR_REMAINED,
+ "Action",
+ "Clear action to execute");
+ RNA_def_boolean(ot->srna,
+ "clear_active",
+ 0,
+ "Clear Active",
+ "Clear active track only instead of all selected tracks");
}
/********************** disable markers operator *********************/
enum {
- MARKER_OP_DISABLE = 0,
- MARKER_OP_ENABLE = 1,
- MARKER_OP_TOGGLE = 2,
+ MARKER_OP_DISABLE = 0,
+ MARKER_OP_ENABLE = 1,
+ MARKER_OP_TOGGLE = 2,
};
static int disable_markers_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- int action = RNA_enum_get(op->ptr, "action");
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- if (TRACK_VIEW_SELECTED(sc, track) &&
- (track->flag & TRACK_LOCKED) == 0)
- {
- MovieTrackingMarker *marker = BKE_tracking_marker_ensure(track, framenr);
- switch (action) {
- case MARKER_OP_DISABLE:
- marker->flag |= MARKER_DISABLED;
- break;
- case MARKER_OP_ENABLE:
- marker->flag &= ~MARKER_DISABLED;
- break;
- case MARKER_OP_TOGGLE:
- marker->flag ^= MARKER_DISABLED;
- break;
- }
- }
- }
-
- DEG_id_tag_update(&clip->id, 0);
-
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ int action = RNA_enum_get(op->ptr, "action");
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_ensure(track, framenr);
+ switch (action) {
+ case MARKER_OP_DISABLE:
+ marker->flag |= MARKER_DISABLED;
+ break;
+ case MARKER_OP_ENABLE:
+ marker->flag &= ~MARKER_DISABLED;
+ break;
+ case MARKER_OP_TOGGLE:
+ marker->flag ^= MARKER_DISABLED;
+ break;
+ }
+ }
+ }
+
+ DEG_id_tag_update(&clip->id, 0);
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_disable_markers(wmOperatorType *ot)
{
- static const EnumPropertyItem actions_items[] = {
- {MARKER_OP_DISABLE, "DISABLE", 0, "Disable",
- "Disable selected markers"},
- {MARKER_OP_ENABLE, "ENABLE", 0, "Enable",
- "Enable selected markers"},
- {MARKER_OP_TOGGLE, "TOGGLE", 0, "Toggle",
- "Toggle disabled flag for selected markers"},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem actions_items[] = {
+ {MARKER_OP_DISABLE, "DISABLE", 0, "Disable", "Disable selected markers"},
+ {MARKER_OP_ENABLE, "ENABLE", 0, "Enable", "Enable selected markers"},
+ {MARKER_OP_TOGGLE, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Disable Markers";
- ot->description = "Disable/enable selected markers";
- ot->idname = "CLIP_OT_disable_markers";
+ /* identifiers */
+ ot->name = "Disable Markers";
+ ot->description = "Disable/enable selected markers";
+ ot->idname = "CLIP_OT_disable_markers";
- /* api callbacks */
- ot->exec = disable_markers_exec;
- ot->poll = ED_space_clip_tracking_poll;
+ /* api callbacks */
+ ot->exec = disable_markers_exec;
+ ot->poll = ED_space_clip_tracking_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_enum(ot->srna, "action", actions_items, 0, "Action", "Disable action to execute");
+ /* properties */
+ RNA_def_enum(ot->srna, "action", actions_items, 0, "Action", "Disable action to execute");
}
/********************** set principal center operator *********************/
static int set_center_principal_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- int width, height;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ int width, height;
- BKE_movieclip_get_size(clip, &sc->user, &width, &height);
+ BKE_movieclip_get_size(clip, &sc->user, &width, &height);
- if (width == 0 || height == 0) {
- return OPERATOR_CANCELLED;
- }
+ if (width == 0 || height == 0) {
+ return OPERATOR_CANCELLED;
+ }
- clip->tracking.camera.principal[0] = ((float)width) / 2.0f;
- clip->tracking.camera.principal[1] = ((float)height) / 2.0f;
+ clip->tracking.camera.principal[0] = ((float)width) / 2.0f;
+ clip->tracking.camera.principal[1] = ((float)height) / 2.0f;
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_set_center_principal(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Principal to Center";
- ot->description = "Set optical center to center of footage";
- ot->idname = "CLIP_OT_set_center_principal";
+ /* identifiers */
+ ot->name = "Set Principal to Center";
+ ot->description = "Set optical center to center of footage";
+ ot->idname = "CLIP_OT_set_center_principal";
- /* api callbacks */
- ot->exec = set_center_principal_exec;
- ot->poll = ED_space_clip_tracking_poll;
+ /* api callbacks */
+ ot->exec = set_center_principal_exec;
+ ot->poll = ED_space_clip_tracking_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** hide tracks operator *********************/
static int hide_tracks_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- int unselected;
-
- unselected = RNA_boolean_get(op->ptr, "unselected");
-
- /* Hide point tracks. */
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- if (unselected == 0 && TRACK_VIEW_SELECTED(sc, track)) {
- track->flag |= TRACK_HIDDEN;
- }
- else if (unselected == 1 && !TRACK_VIEW_SELECTED(sc, track)) {
- track->flag |= TRACK_HIDDEN;
- }
- }
-
- if (act_track != NULL && act_track->flag & TRACK_HIDDEN) {
- clip->tracking.act_track = NULL;
- }
-
- /* Hide place tracks. */
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- MovieTrackingPlaneTrack *act_plane_track =
- BKE_tracking_plane_track_get_active(tracking);
- for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first;
- plane_track != NULL;
- plane_track = plane_track->next)
- {
- if (unselected == 0 && plane_track->flag & SELECT) {
- plane_track->flag |= PLANE_TRACK_HIDDEN;
- }
- else if (unselected == 1 && (plane_track->flag & SELECT) == 0) {
- plane_track->flag |= PLANE_TRACK_HIDDEN;
- }
- }
- if (act_plane_track != NULL && act_plane_track->flag & TRACK_HIDDEN) {
- clip->tracking.act_plane_track = NULL;
- }
-
- if (unselected == 0) {
- /* No selection on screen now, unlock view so it can be
- * scrolled nice again.
- */
- sc->flag &= ~SC_LOCK_SELECTION;
- }
-
- BKE_tracking_dopesheet_tag_update(tracking);
- WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, NULL);
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ int unselected;
+
+ unselected = RNA_boolean_get(op->ptr, "unselected");
+
+ /* Hide point tracks. */
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ if (unselected == 0 && TRACK_VIEW_SELECTED(sc, track)) {
+ track->flag |= TRACK_HIDDEN;
+ }
+ else if (unselected == 1 && !TRACK_VIEW_SELECTED(sc, track)) {
+ track->flag |= TRACK_HIDDEN;
+ }
+ }
+
+ if (act_track != NULL && act_track->flag & TRACK_HIDDEN) {
+ clip->tracking.act_track = NULL;
+ }
+
+ /* Hide place tracks. */
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ MovieTrackingPlaneTrack *act_plane_track = BKE_tracking_plane_track_get_active(tracking);
+ for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first; plane_track != NULL;
+ plane_track = plane_track->next) {
+ if (unselected == 0 && plane_track->flag & SELECT) {
+ plane_track->flag |= PLANE_TRACK_HIDDEN;
+ }
+ else if (unselected == 1 && (plane_track->flag & SELECT) == 0) {
+ plane_track->flag |= PLANE_TRACK_HIDDEN;
+ }
+ }
+ if (act_plane_track != NULL && act_plane_track->flag & TRACK_HIDDEN) {
+ clip->tracking.act_plane_track = NULL;
+ }
+
+ if (unselected == 0) {
+ /* No selection on screen now, unlock view so it can be
+ * scrolled nice again.
+ */
+ sc->flag &= ~SC_LOCK_SELECTION;
+ }
+
+ BKE_tracking_dopesheet_tag_update(tracking);
+ WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, NULL);
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_hide_tracks(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Tracks";
- ot->description = "Hide selected tracks";
- ot->idname = "CLIP_OT_hide_tracks";
+ /* identifiers */
+ ot->name = "Hide Tracks";
+ ot->description = "Hide selected tracks";
+ ot->idname = "CLIP_OT_hide_tracks";
- /* api callbacks */
- ot->exec = hide_tracks_exec;
- ot->poll = ED_space_clip_tracking_poll;
+ /* api callbacks */
+ ot->exec = hide_tracks_exec;
+ ot->poll = ED_space_clip_tracking_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected tracks");
+ /* properties */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected tracks");
}
/********************** hide tracks clear operator *********************/
static int hide_tracks_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
- /* Unhide point tracks. */
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- track->flag &= ~TRACK_HIDDEN;
- }
+ /* Unhide point tracks. */
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ track->flag &= ~TRACK_HIDDEN;
+ }
- /* Unhide plane tracks. */
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first;
- plane_track != NULL;
- plane_track = plane_track->next)
- {
- plane_track->flag &= ~PLANE_TRACK_HIDDEN;
- }
+ /* Unhide plane tracks. */
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first; plane_track != NULL;
+ plane_track = plane_track->next) {
+ plane_track->flag &= ~PLANE_TRACK_HIDDEN;
+ }
- BKE_tracking_dopesheet_tag_update(tracking);
+ BKE_tracking_dopesheet_tag_update(tracking);
- WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, NULL);
+ WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_hide_tracks_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Tracks Clear";
- ot->description = "Clear hide selected tracks";
- ot->idname = "CLIP_OT_hide_tracks_clear";
+ /* identifiers */
+ ot->name = "Hide Tracks Clear";
+ ot->description = "Clear hide selected tracks";
+ ot->idname = "CLIP_OT_hide_tracks_clear";
- /* api callbacks */
- ot->exec = hide_tracks_clear_exec;
- ot->poll = ED_space_clip_tracking_poll;
+ /* api callbacks */
+ ot->exec = hide_tracks_clear_exec;
+ ot->poll = ED_space_clip_tracking_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** frame jump operator *********************/
static int frame_jump_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- int pos = RNA_enum_get(op->ptr, "position");
- int delta;
-
- if (pos <= 1) { /* jump to path */
- MovieTrackingTrack *track = BKE_tracking_track_get_active(tracking);
- if (track == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- delta = pos == 1 ? 1 : -1;
- while (sc->user.framenr + delta >= SFRA &&
- sc->user.framenr + delta <= EFRA)
- {
- int framenr = BKE_movieclip_remap_scene_to_clip_frame(
- clip,
- sc->user.framenr + delta);
- MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track,
- framenr);
-
- if (marker == NULL || marker->flag & MARKER_DISABLED) {
- break;
- }
-
- sc->user.framenr += delta;
- }
- }
- else { /* to failed frame */
- if (tracking->reconstruction.flag & TRACKING_RECONSTRUCTED) {
- int framenr = ED_space_clip_get_clip_frame_number(sc);
- MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
-
- delta = pos == 3 ? 1 : -1;
- framenr += delta;
-
- while (framenr + delta >= SFRA &&
- framenr + delta <= EFRA)
- {
- MovieReconstructedCamera *cam =
- BKE_tracking_camera_get_reconstructed(tracking,
- object,
- framenr);
-
- if (cam == NULL) {
- sc->user.framenr =
- BKE_movieclip_remap_clip_to_scene_frame(clip,
- framenr);
- break;
- }
-
- framenr += delta;
- }
- }
- }
-
- if (CFRA != sc->user.framenr) {
- CFRA = sc->user.framenr;
- BKE_sound_seek_scene(CTX_data_main(C), scene);
-
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
- }
-
- WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, NULL);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ int pos = RNA_enum_get(op->ptr, "position");
+ int delta;
+
+ if (pos <= 1) { /* jump to path */
+ MovieTrackingTrack *track = BKE_tracking_track_get_active(tracking);
+ if (track == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ delta = pos == 1 ? 1 : -1;
+ while (sc->user.framenr + delta >= SFRA && sc->user.framenr + delta <= EFRA) {
+ int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, sc->user.framenr + delta);
+ MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr);
+
+ if (marker == NULL || marker->flag & MARKER_DISABLED) {
+ break;
+ }
+
+ sc->user.framenr += delta;
+ }
+ }
+ else { /* to failed frame */
+ if (tracking->reconstruction.flag & TRACKING_RECONSTRUCTED) {
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+ MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
+
+ delta = pos == 3 ? 1 : -1;
+ framenr += delta;
+
+ while (framenr + delta >= SFRA && framenr + delta <= EFRA) {
+ MovieReconstructedCamera *cam = BKE_tracking_camera_get_reconstructed(
+ tracking, object, framenr);
+
+ if (cam == NULL) {
+ sc->user.framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, framenr);
+ break;
+ }
+
+ framenr += delta;
+ }
+ }
+ }
+
+ if (CFRA != sc->user.framenr) {
+ CFRA = sc->user.framenr;
+ BKE_sound_seek_scene(CTX_data_main(C), scene);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ }
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, NULL);
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_frame_jump(wmOperatorType *ot)
{
- static const EnumPropertyItem position_items[] = {
- {0, "PATHSTART", 0, "Path Start", "Jump to start of current path"},
- {1, "PATHEND", 0, "Path End", "Jump to end of current path"},
- {2, "FAILEDPREV", 0, "Previous Failed", "Jump to previous failed frame"},
- {2, "FAILNEXT", 0, "Next Failed", "Jump to next failed frame"},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem position_items[] = {
+ {0, "PATHSTART", 0, "Path Start", "Jump to start of current path"},
+ {1, "PATHEND", 0, "Path End", "Jump to end of current path"},
+ {2, "FAILEDPREV", 0, "Previous Failed", "Jump to previous failed frame"},
+ {2, "FAILNEXT", 0, "Next Failed", "Jump to next failed frame"},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Jump to Frame";
- ot->description = "Jump to special frame";
- ot->idname = "CLIP_OT_frame_jump";
+ /* identifiers */
+ ot->name = "Jump to Frame";
+ ot->description = "Jump to special frame";
+ ot->idname = "CLIP_OT_frame_jump";
- /* api callbacks */
- ot->exec = frame_jump_exec;
- ot->poll = ED_space_clip_poll;
+ /* api callbacks */
+ ot->exec = frame_jump_exec;
+ ot->poll = ED_space_clip_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_enum(ot->srna, "position", position_items, 0, "Position",
- "Position to jump to");
+ /* properties */
+ RNA_def_enum(ot->srna, "position", position_items, 0, "Position", "Position to jump to");
}
/********************** join tracks operator *********************/
static int join_tracks_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingStabilization *stab = &tracking->stabilization;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- bool update_stabilization = false;
-
- MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- if (act_track == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active track to join to");
- return OPERATOR_CANCELLED;
- }
-
- GSet *point_tracks = BLI_gset_ptr_new(__func__);
-
- for (MovieTrackingTrack *track = tracksbase->first, *next_track;
- track != NULL;
- track = next_track)
- {
- next_track = track->next;
- if (TRACK_VIEW_SELECTED(sc, track) && track != act_track) {
- BKE_tracking_tracks_join(tracking, act_track, track);
-
- if (track->flag & TRACK_USE_2D_STAB) {
- update_stabilization = true;
- if ((act_track->flag & TRACK_USE_2D_STAB) == 0) {
- act_track->flag |= TRACK_USE_2D_STAB;
- }
- else {
- stab->tot_track--;
- }
- BLI_assert(0 <= stab->tot_track);
- }
- if (track->flag & TRACK_USE_2D_STAB_ROT) {
- update_stabilization = true;
- if ((act_track->flag & TRACK_USE_2D_STAB_ROT) == 0) {
- act_track->flag |= TRACK_USE_2D_STAB_ROT;
- }
- else {
- stab->tot_rot_track--;
- }
- BLI_assert(0 <= stab->tot_rot_track);
- }
-
- for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first;
- plane_track != NULL;
- plane_track = plane_track->next)
- {
- if (BKE_tracking_plane_track_has_point_track(plane_track, track)) {
- BKE_tracking_plane_track_replace_point_track(plane_track,
- track,
- act_track);
- if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
- BLI_gset_insert(point_tracks, plane_track);
- }
- }
- }
-
- BKE_tracking_track_free(track);
- BLI_freelinkN(tracksbase, track);
- }
- }
-
- if (update_stabilization) {
- WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
- }
-
- GSetIterator gs_iter;
- int framenr = ED_space_clip_get_clip_frame_number(sc);
- GSET_ITER (gs_iter, point_tracks) {
- MovieTrackingPlaneTrack *plane_track = BLI_gsetIterator_getKey(&gs_iter);
- BKE_tracking_track_plane_from_existing_motion( plane_track, framenr);
- }
-
- BLI_gset_free(point_tracks, NULL);
-
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingStabilization *stab = &tracking->stabilization;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ bool update_stabilization = false;
+
+ MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
+ if (act_track == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active track to join to");
+ return OPERATOR_CANCELLED;
+ }
+
+ GSet *point_tracks = BLI_gset_ptr_new(__func__);
+
+ for (MovieTrackingTrack *track = tracksbase->first, *next_track; track != NULL;
+ track = next_track) {
+ next_track = track->next;
+ if (TRACK_VIEW_SELECTED(sc, track) && track != act_track) {
+ BKE_tracking_tracks_join(tracking, act_track, track);
+
+ if (track->flag & TRACK_USE_2D_STAB) {
+ update_stabilization = true;
+ if ((act_track->flag & TRACK_USE_2D_STAB) == 0) {
+ act_track->flag |= TRACK_USE_2D_STAB;
+ }
+ else {
+ stab->tot_track--;
+ }
+ BLI_assert(0 <= stab->tot_track);
+ }
+ if (track->flag & TRACK_USE_2D_STAB_ROT) {
+ update_stabilization = true;
+ if ((act_track->flag & TRACK_USE_2D_STAB_ROT) == 0) {
+ act_track->flag |= TRACK_USE_2D_STAB_ROT;
+ }
+ else {
+ stab->tot_rot_track--;
+ }
+ BLI_assert(0 <= stab->tot_rot_track);
+ }
+
+ for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first; plane_track != NULL;
+ plane_track = plane_track->next) {
+ if (BKE_tracking_plane_track_has_point_track(plane_track, track)) {
+ BKE_tracking_plane_track_replace_point_track(plane_track, track, act_track);
+ if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
+ BLI_gset_insert(point_tracks, plane_track);
+ }
+ }
+ }
+
+ BKE_tracking_track_free(track);
+ BLI_freelinkN(tracksbase, track);
+ }
+ }
+
+ if (update_stabilization) {
+ WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
+ }
+
+ GSetIterator gs_iter;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+ GSET_ITER (gs_iter, point_tracks) {
+ MovieTrackingPlaneTrack *plane_track = BLI_gsetIterator_getKey(&gs_iter);
+ BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
+ }
+
+ BLI_gset_free(point_tracks, NULL);
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_join_tracks(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Join Tracks";
- ot->description = "Join selected tracks";
- ot->idname = "CLIP_OT_join_tracks";
+ /* identifiers */
+ ot->name = "Join Tracks";
+ ot->description = "Join selected tracks";
+ ot->idname = "CLIP_OT_join_tracks";
- /* api callbacks */
- ot->exec = join_tracks_exec;
- ot->poll = ED_space_clip_tracking_poll;
+ /* api callbacks */
+ ot->exec = join_tracks_exec;
+ ot->poll = ED_space_clip_tracking_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** lock tracks operator *********************/
enum {
- TRACK_ACTION_LOCK = 0,
- TRACK_ACTION_UNLOCK = 1,
- TRACK_ACTION_TOGGLE = 2,
+ TRACK_ACTION_LOCK = 0,
+ TRACK_ACTION_UNLOCK = 1,
+ TRACK_ACTION_TOGGLE = 2,
};
static int lock_tracks_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- int action = RNA_enum_get(op->ptr, "action");
-
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- if (TRACK_VIEW_SELECTED(sc, track)) {
- switch (action) {
- case TRACK_ACTION_LOCK:
- track->flag |= TRACK_LOCKED;
- break;
- case TRACK_ACTION_UNLOCK:
- track->flag &= ~TRACK_LOCKED;
- break;
- case TRACK_ACTION_TOGGLE:
- track->flag ^= TRACK_LOCKED;
- break;
- }
- }
- }
-
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ int action = RNA_enum_get(op->ptr, "action");
+
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ if (TRACK_VIEW_SELECTED(sc, track)) {
+ switch (action) {
+ case TRACK_ACTION_LOCK:
+ track->flag |= TRACK_LOCKED;
+ break;
+ case TRACK_ACTION_UNLOCK:
+ track->flag &= ~TRACK_LOCKED;
+ break;
+ case TRACK_ACTION_TOGGLE:
+ track->flag ^= TRACK_LOCKED;
+ break;
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_lock_tracks(wmOperatorType *ot)
{
- static const EnumPropertyItem actions_items[] = {
- {TRACK_ACTION_LOCK, "LOCK", 0, "Lock", "Lock selected tracks"},
- {TRACK_ACTION_UNLOCK, "UNLOCK", 0, "Unlock", "Unlock selected tracks"},
- {TRACK_ACTION_TOGGLE, "TOGGLE", 0, "Toggle",
- "Toggle locked flag for selected tracks"},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem actions_items[] = {
+ {TRACK_ACTION_LOCK, "LOCK", 0, "Lock", "Lock selected tracks"},
+ {TRACK_ACTION_UNLOCK, "UNLOCK", 0, "Unlock", "Unlock selected tracks"},
+ {TRACK_ACTION_TOGGLE, "TOGGLE", 0, "Toggle", "Toggle locked flag for selected tracks"},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Lock Tracks";
- ot->description = "Lock/unlock selected tracks";
- ot->idname = "CLIP_OT_lock_tracks";
+ /* identifiers */
+ ot->name = "Lock Tracks";
+ ot->description = "Lock/unlock selected tracks";
+ ot->idname = "CLIP_OT_lock_tracks";
- /* api callbacks */
- ot->exec = lock_tracks_exec;
- ot->poll = ED_space_clip_tracking_poll;
+ /* api callbacks */
+ ot->exec = lock_tracks_exec;
+ ot->poll = ED_space_clip_tracking_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_enum(ot->srna, "action", actions_items, 0, "Action",
- "Lock action to execute");
+ /* properties */
+ RNA_def_enum(ot->srna, "action", actions_items, 0, "Action", "Lock action to execute");
}
/********************** set keyframe operator *********************/
enum {
- SOLVER_KEYFRAME_A = 0,
- SOLVER_KEYFRAME_B = 1,
+ SOLVER_KEYFRAME_A = 0,
+ SOLVER_KEYFRAME_B = 1,
};
static int set_solver_keyframe_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
- int keyframe = RNA_enum_get(op->ptr, "keyframe");
- int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip,
- sc->user.framenr);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
+ int keyframe = RNA_enum_get(op->ptr, "keyframe");
+ int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, sc->user.framenr);
- if (keyframe == SOLVER_KEYFRAME_A) {
- object->keyframe1 = framenr;
- }
- else {
- object->keyframe2 = framenr;
- }
+ if (keyframe == SOLVER_KEYFRAME_A) {
+ object->keyframe1 = framenr;
+ }
+ else {
+ object->keyframe2 = framenr;
+ }
- WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
+ WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_set_solver_keyframe(wmOperatorType *ot)
{
- static const EnumPropertyItem keyframe_items[] = {
- {SOLVER_KEYFRAME_A, "KEYFRAME_A", 0, "Keyframe A", ""},
- {SOLVER_KEYFRAME_B, "KEYFRAME_B", 0, "Keyframe B", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem keyframe_items[] = {
+ {SOLVER_KEYFRAME_A, "KEYFRAME_A", 0, "Keyframe A", ""},
+ {SOLVER_KEYFRAME_B, "KEYFRAME_B", 0, "Keyframe B", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Set Solver Keyframe";
- ot->description = "Set keyframe used by solver";
- ot->idname = "CLIP_OT_set_solver_keyframe";
+ /* identifiers */
+ ot->name = "Set Solver Keyframe";
+ ot->description = "Set keyframe used by solver";
+ ot->idname = "CLIP_OT_set_solver_keyframe";
- /* api callbacks */
- ot->exec = set_solver_keyframe_exec;
- ot->poll = ED_space_clip_tracking_poll;
+ /* api callbacks */
+ ot->exec = set_solver_keyframe_exec;
+ ot->poll = ED_space_clip_tracking_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_enum(ot->srna, "keyframe", keyframe_items, 0, "Keyframe",
- "Keyframe to set");
+ /* properties */
+ RNA_def_enum(ot->srna, "keyframe", keyframe_items, 0, "Keyframe", "Keyframe to set");
}
/********************** track copy color operator *********************/
static int track_copy_color_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- if (act_track == NULL) {
- return OPERATOR_CANCELLED;
- }
+ MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
+ if (act_track == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- if (TRACK_VIEW_SELECTED(sc, track) && track != act_track) {
- track->flag &= ~TRACK_CUSTOMCOLOR;
- if (act_track->flag & TRACK_CUSTOMCOLOR) {
- copy_v3_v3(track->color, act_track->color);
- track->flag |= TRACK_CUSTOMCOLOR;
- }
- }
- }
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ if (TRACK_VIEW_SELECTED(sc, track) && track != act_track) {
+ track->flag &= ~TRACK_CUSTOMCOLOR;
+ if (act_track->flag & TRACK_CUSTOMCOLOR) {
+ copy_v3_v3(track->color, act_track->color);
+ track->flag |= TRACK_CUSTOMCOLOR;
+ }
+ }
+ }
- WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
+ WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_track_copy_color(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Color";
- ot->description = "Copy color to all selected tracks";
- ot->idname = "CLIP_OT_track_copy_color";
+ /* identifiers */
+ ot->name = "Copy Color";
+ ot->description = "Copy color to all selected tracks";
+ ot->idname = "CLIP_OT_track_copy_color";
- /* api callbacks */
- ot->exec = track_copy_color_exec;
- ot->poll = ED_space_clip_tracking_poll;
+ /* api callbacks */
+ ot->exec = track_copy_color_exec;
+ ot->poll = ED_space_clip_tracking_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** clean tracks operator *********************/
static bool is_track_clean(MovieTrackingTrack *track, int frames, int del)
{
- bool ok = true;
- int prev = -1, count = 0;
- MovieTrackingMarker *markers = track->markers, *new_markers = NULL;
- int start_disabled = 0;
- int markersnr = track->markersnr;
-
- if (del) {
- new_markers = MEM_callocN(markersnr * sizeof(MovieTrackingMarker),
- "track cleaned markers");
- }
-
- for (int a = 0; a < markersnr; a++) {
- int end = 0;
-
- if (prev == -1) {
- if ((markers[a].flag & MARKER_DISABLED) == 0) {
- prev = a;
- }
- else {
- start_disabled = 1;
- }
- }
-
- if (prev >= 0) {
- end = a == markersnr - 1;
- end |= (a < markersnr - 1) && (markers[a].framenr != markers[a + 1].framenr - 1 ||
- markers[a].flag & MARKER_DISABLED);
- }
-
- if (end) {
- int segok = 1, len = 0;
-
- if (a != prev && markers[a].framenr != markers[a - 1].framenr + 1) {
- len = a - prev;
- }
- else if (markers[a].flag & MARKER_DISABLED) {
- len = a - prev;
- }
- else {
- len = a - prev + 1;
- }
-
- if (frames) {
- if (len < frames) {
- segok = 0;
- ok = 0;
-
- if (!del) {
- break;
- }
- }
- }
-
- if (del) {
- if (segok) {
- int t = len;
-
- if (markers[a].flag & MARKER_DISABLED) {
- t++;
- }
-
- /* Place disabled marker in front of current segment. */
- if (start_disabled) {
- memcpy(new_markers + count,
- markers + prev,
- sizeof(MovieTrackingMarker));
- new_markers[count].framenr--;
- new_markers[count].flag |= MARKER_DISABLED;
-
- count++;
- start_disabled = 0;
- }
-
- memcpy(new_markers + count,
- markers + prev,
- t * sizeof(MovieTrackingMarker));
- count += t;
- }
- else if (markers[a].flag & MARKER_DISABLED) {
- /* Current segment which would be deleted was finished by
- * disabled marker, so next segment should be started from
- * disabled marker.
- */
- start_disabled = 1;
- }
- }
-
- prev = -1;
- }
- }
-
- if (del && count == 0) {
- ok = 0;
- }
-
- if (del) {
- MEM_freeN(track->markers);
-
- if (count) {
- track->markers = new_markers;
- }
- else {
- track->markers = NULL;
- MEM_freeN(new_markers);
- }
-
- track->markersnr = count;
- }
-
- return ok;
+ bool ok = true;
+ int prev = -1, count = 0;
+ MovieTrackingMarker *markers = track->markers, *new_markers = NULL;
+ int start_disabled = 0;
+ int markersnr = track->markersnr;
+
+ if (del) {
+ new_markers = MEM_callocN(markersnr * sizeof(MovieTrackingMarker), "track cleaned markers");
+ }
+
+ for (int a = 0; a < markersnr; a++) {
+ int end = 0;
+
+ if (prev == -1) {
+ if ((markers[a].flag & MARKER_DISABLED) == 0) {
+ prev = a;
+ }
+ else {
+ start_disabled = 1;
+ }
+ }
+
+ if (prev >= 0) {
+ end = a == markersnr - 1;
+ end |= (a < markersnr - 1) && (markers[a].framenr != markers[a + 1].framenr - 1 ||
+ markers[a].flag & MARKER_DISABLED);
+ }
+
+ if (end) {
+ int segok = 1, len = 0;
+
+ if (a != prev && markers[a].framenr != markers[a - 1].framenr + 1) {
+ len = a - prev;
+ }
+ else if (markers[a].flag & MARKER_DISABLED) {
+ len = a - prev;
+ }
+ else {
+ len = a - prev + 1;
+ }
+
+ if (frames) {
+ if (len < frames) {
+ segok = 0;
+ ok = 0;
+
+ if (!del) {
+ break;
+ }
+ }
+ }
+
+ if (del) {
+ if (segok) {
+ int t = len;
+
+ if (markers[a].flag & MARKER_DISABLED) {
+ t++;
+ }
+
+ /* Place disabled marker in front of current segment. */
+ if (start_disabled) {
+ memcpy(new_markers + count, markers + prev, sizeof(MovieTrackingMarker));
+ new_markers[count].framenr--;
+ new_markers[count].flag |= MARKER_DISABLED;
+
+ count++;
+ start_disabled = 0;
+ }
+
+ memcpy(new_markers + count, markers + prev, t * sizeof(MovieTrackingMarker));
+ count += t;
+ }
+ else if (markers[a].flag & MARKER_DISABLED) {
+ /* Current segment which would be deleted was finished by
+ * disabled marker, so next segment should be started from
+ * disabled marker.
+ */
+ start_disabled = 1;
+ }
+ }
+
+ prev = -1;
+ }
+ }
+
+ if (del && count == 0) {
+ ok = 0;
+ }
+
+ if (del) {
+ MEM_freeN(track->markers);
+
+ if (count) {
+ track->markers = new_markers;
+ }
+ else {
+ track->markers = NULL;
+ MEM_freeN(new_markers);
+ }
+
+ track->markersnr = count;
+ }
+
+ return ok;
}
static int clean_tracks_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- int frames = RNA_int_get(op->ptr, "frames");
- int action = RNA_enum_get(op->ptr, "action");
- float error = RNA_float_get(op->ptr, "error");
-
- if (error && action == TRACKING_CLEAN_DELETE_SEGMENT) {
- action = TRACKING_CLEAN_DELETE_TRACK;
- }
-
- for (MovieTrackingTrack *track = tracksbase->first, *next_track;
- track != NULL;
- track = next_track)
- {
- next_track = track->next;
-
- if ((track->flag & TRACK_HIDDEN) == 0 &&
- (track->flag & TRACK_LOCKED) == 0)
- {
- bool ok;
-
- ok = (is_track_clean(track,
- frames,
- action == TRACKING_CLEAN_DELETE_SEGMENT)) &&
- ((error == 0.0f) ||
- (track->flag & TRACK_HAS_BUNDLE) == 0 ||
- (track->error < error));
-
- if (!ok) {
- if (action == TRACKING_CLEAN_SELECT) {
- BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT);
- }
- else if (action == TRACKING_CLEAN_DELETE_TRACK) {
- if (track == act_track) {
- clip->tracking.act_track = NULL;
- }
- BKE_tracking_track_free(track);
- BLI_freelinkN(tracksbase, track);
- track = NULL;
- }
-
- /* Happens when all tracking segments are not long enough. */
- if (track && track->markersnr == 0) {
- if (track == act_track) {
- clip->tracking.act_track = NULL;
- }
- BKE_tracking_track_free(track);
- BLI_freelinkN(tracksbase, track);
- }
- }
- }
- }
-
- BKE_tracking_dopesheet_tag_update(tracking);
-
- WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, clip);
-
- return OPERATOR_FINISHED;
-}
-
-static int clean_tracks_invoke(bContext *C,
- wmOperator *op,
- const wmEvent *UNUSED(event))
-{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
-
- if (!RNA_struct_property_is_set(op->ptr, "frames")) {
- RNA_int_set(op->ptr, "frames", clip->tracking.settings.clean_frames);
- }
-
- if (!RNA_struct_property_is_set(op->ptr, "error")) {
- RNA_float_set(op->ptr, "error", clip->tracking.settings.clean_error);
- }
-
- if (!RNA_struct_property_is_set(op->ptr, "action")) {
- RNA_enum_set(op->ptr, "action", clip->tracking.settings.clean_action);
- }
-
- return clean_tracks_exec(C, op);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
+ int frames = RNA_int_get(op->ptr, "frames");
+ int action = RNA_enum_get(op->ptr, "action");
+ float error = RNA_float_get(op->ptr, "error");
+
+ if (error && action == TRACKING_CLEAN_DELETE_SEGMENT) {
+ action = TRACKING_CLEAN_DELETE_TRACK;
+ }
+
+ for (MovieTrackingTrack *track = tracksbase->first, *next_track; track != NULL;
+ track = next_track) {
+ next_track = track->next;
+
+ if ((track->flag & TRACK_HIDDEN) == 0 && (track->flag & TRACK_LOCKED) == 0) {
+ bool ok;
+
+ ok = (is_track_clean(track, frames, action == TRACKING_CLEAN_DELETE_SEGMENT)) &&
+ ((error == 0.0f) || (track->flag & TRACK_HAS_BUNDLE) == 0 || (track->error < error));
+
+ if (!ok) {
+ if (action == TRACKING_CLEAN_SELECT) {
+ BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT);
+ }
+ else if (action == TRACKING_CLEAN_DELETE_TRACK) {
+ if (track == act_track) {
+ clip->tracking.act_track = NULL;
+ }
+ BKE_tracking_track_free(track);
+ BLI_freelinkN(tracksbase, track);
+ track = NULL;
+ }
+
+ /* Happens when all tracking segments are not long enough. */
+ if (track && track->markersnr == 0) {
+ if (track == act_track) {
+ clip->tracking.act_track = NULL;
+ }
+ BKE_tracking_track_free(track);
+ BLI_freelinkN(tracksbase, track);
+ }
+ }
+ }
+ }
+
+ BKE_tracking_dopesheet_tag_update(tracking);
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, clip);
+
+ return OPERATOR_FINISHED;
+}
+
+static int clean_tracks_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+
+ if (!RNA_struct_property_is_set(op->ptr, "frames")) {
+ RNA_int_set(op->ptr, "frames", clip->tracking.settings.clean_frames);
+ }
+
+ if (!RNA_struct_property_is_set(op->ptr, "error")) {
+ RNA_float_set(op->ptr, "error", clip->tracking.settings.clean_error);
+ }
+
+ if (!RNA_struct_property_is_set(op->ptr, "action")) {
+ RNA_enum_set(op->ptr, "action", clip->tracking.settings.clean_action);
+ }
+
+ return clean_tracks_exec(C, op);
}
void CLIP_OT_clean_tracks(wmOperatorType *ot)
{
- static const EnumPropertyItem actions_items[] = {
- {TRACKING_CLEAN_SELECT, "SELECT", 0, "Select",
- "Select unclean tracks"},
- {TRACKING_CLEAN_DELETE_TRACK, "DELETE_TRACK", 0, "Delete Track",
- "Delete unclean tracks"},
- {TRACKING_CLEAN_DELETE_SEGMENT, "DELETE_SEGMENTS", 0, "Delete Segments",
- "Delete unclean segments of tracks"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Clean Tracks";
- ot->description = "Clean tracks with high error values or few frames";
- ot->idname = "CLIP_OT_clean_tracks";
-
- /* api callbacks */
- ot->exec = clean_tracks_exec;
- ot->invoke = clean_tracks_invoke;
- ot->poll = ED_space_clip_tracking_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_int(ot->srna, "frames", 0, 0, INT_MAX, "Tracked Frames",
- "Effect on tracks which are tracked less than "
- "specified amount of frames",
- 0, INT_MAX);
- RNA_def_float(ot->srna, "error", 0.0f, 0.0f, FLT_MAX, "Reprojection Error",
- "Effect on tracks which have got larger re-projection error",
- 0.0f, 100.0f);
- RNA_def_enum(ot->srna, "action", actions_items, 0, "Action",
- "Cleanup action to execute");
+ static const EnumPropertyItem actions_items[] = {
+ {TRACKING_CLEAN_SELECT, "SELECT", 0, "Select", "Select unclean tracks"},
+ {TRACKING_CLEAN_DELETE_TRACK, "DELETE_TRACK", 0, "Delete Track", "Delete unclean tracks"},
+ {TRACKING_CLEAN_DELETE_SEGMENT,
+ "DELETE_SEGMENTS",
+ 0,
+ "Delete Segments",
+ "Delete unclean segments of tracks"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Clean Tracks";
+ ot->description = "Clean tracks with high error values or few frames";
+ ot->idname = "CLIP_OT_clean_tracks";
+
+ /* api callbacks */
+ ot->exec = clean_tracks_exec;
+ ot->invoke = clean_tracks_invoke;
+ ot->poll = ED_space_clip_tracking_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna,
+ "frames",
+ 0,
+ 0,
+ INT_MAX,
+ "Tracked Frames",
+ "Effect on tracks which are tracked less than "
+ "specified amount of frames",
+ 0,
+ INT_MAX);
+ RNA_def_float(ot->srna,
+ "error",
+ 0.0f,
+ 0.0f,
+ FLT_MAX,
+ "Reprojection Error",
+ "Effect on tracks which have got larger re-projection error",
+ 0.0f,
+ 100.0f);
+ RNA_def_enum(ot->srna, "action", actions_items, 0, "Action", "Cleanup action to execute");
}
/********************** add tracking object *********************/
static int tracking_object_new_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
- BKE_tracking_object_add(tracking, "Object");
+ BKE_tracking_object_add(tracking, "Object");
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_tracking_object_new(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Tracking Object";
- ot->description = "Add new object for tracking";
- ot->idname = "CLIP_OT_tracking_object_new";
+ /* identifiers */
+ ot->name = "Add Tracking Object";
+ ot->description = "Add new object for tracking";
+ ot->idname = "CLIP_OT_tracking_object_new";
- /* api callbacks */
- ot->exec = tracking_object_new_exec;
- ot->poll = ED_space_clip_tracking_poll;
+ /* api callbacks */
+ ot->exec = tracking_object_new_exec;
+ ot->poll = ED_space_clip_tracking_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** remove tracking object *********************/
static int tracking_object_remove_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *object;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *object;
- object = BKE_tracking_object_get_active(tracking);
+ object = BKE_tracking_object_get_active(tracking);
- if (object->flag & TRACKING_OBJECT_CAMERA) {
- BKE_report(op->reports,
- RPT_WARNING,
- "Object used for camera tracking cannot be deleted");
- return OPERATOR_CANCELLED;
- }
+ if (object->flag & TRACKING_OBJECT_CAMERA) {
+ BKE_report(op->reports, RPT_WARNING, "Object used for camera tracking cannot be deleted");
+ return OPERATOR_CANCELLED;
+ }
- BKE_tracking_object_delete(tracking, object);
+ BKE_tracking_object_delete(tracking, object);
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_tracking_object_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Tracking Object";
- ot->description = "Remove object for tracking";
- ot->idname = "CLIP_OT_tracking_object_remove";
+ /* identifiers */
+ ot->name = "Remove Tracking Object";
+ ot->description = "Remove object for tracking";
+ ot->idname = "CLIP_OT_tracking_object_remove";
- /* api callbacks */
- ot->exec = tracking_object_remove_exec;
- ot->poll = ED_space_clip_tracking_poll;
+ /* api callbacks */
+ ot->exec = tracking_object_remove_exec;
+ ot->poll = ED_space_clip_tracking_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** copy tracks to clipboard operator *********************/
static int copy_tracks_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
- clip_tracking_clear_invisible_track_selection(sc, clip);
+ clip_tracking_clear_invisible_track_selection(sc, clip);
- BKE_tracking_clipboard_copy_tracks(tracking, object);
+ BKE_tracking_clipboard_copy_tracks(tracking, object);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_copy_tracks(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Tracks";
- ot->description = "Copy selected tracks to clipboard";
- ot->idname = "CLIP_OT_copy_tracks";
+ /* identifiers */
+ ot->name = "Copy Tracks";
+ ot->description = "Copy selected tracks to clipboard";
+ ot->idname = "CLIP_OT_copy_tracks";
- /* api callbacks */
- ot->exec = copy_tracks_exec;
- ot->poll = ED_space_clip_tracking_poll;
+ /* api callbacks */
+ ot->exec = copy_tracks_exec;
+ ot->poll = ED_space_clip_tracking_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
}
/********************* paste tracks from clipboard operator ********************/
static bool paste_tracks_poll(bContext *C)
{
- if (ED_space_clip_tracking_poll(C)) {
- return BKE_tracking_clipboard_has_tracks();
- }
+ if (ED_space_clip_tracking_poll(C)) {
+ return BKE_tracking_clipboard_has_tracks();
+ }
- return 0;
+ return 0;
}
static int paste_tracks_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
- ListBase *tracks_base = BKE_tracking_object_get_tracks(tracking, object);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
+ ListBase *tracks_base = BKE_tracking_object_get_tracks(tracking, object);
- BKE_tracking_tracks_deselect_all(tracks_base);
- BKE_tracking_clipboard_paste_tracks(tracking, object);
+ BKE_tracking_tracks_deselect_all(tracks_base);
+ BKE_tracking_clipboard_paste_tracks(tracking, object);
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_paste_tracks(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Paste Tracks";
- ot->description = "Paste tracks from clipboard";
- ot->idname = "CLIP_OT_paste_tracks";
+ /* identifiers */
+ ot->name = "Paste Tracks";
+ ot->description = "Paste tracks from clipboard";
+ ot->idname = "CLIP_OT_paste_tracks";
- /* api callbacks */
- ot->exec = paste_tracks_exec;
- ot->poll = paste_tracks_poll;
+ /* api callbacks */
+ ot->exec = paste_tracks_exec;
+ ot->poll = paste_tracks_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** Insert track keyframe operator *********************/
static void keyframe_set_flag(bContext *C, bool set)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- ListBase *tracks_base = BKE_tracking_get_active_tracks(tracking);
- for (MovieTrackingTrack *track = tracks_base->first;
- track != NULL;
- track = track->next)
- {
- if (TRACK_VIEW_SELECTED(sc, track)) {
- if (set) {
- MovieTrackingMarker *marker =
- BKE_tracking_marker_ensure(track, framenr);
- marker->flag &= ~MARKER_TRACKED;
- }
- else {
- MovieTrackingMarker *marker =
- BKE_tracking_marker_get_exact(track, framenr);
- if (marker != NULL) {
- marker->flag |= MARKER_TRACKED;
- }
- }
- }
- }
-
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first;
- plane_track != NULL;
- plane_track = plane_track->next)
- {
- if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
- if (set) {
- MovieTrackingPlaneMarker *plane_marker =
- BKE_tracking_plane_marker_ensure(plane_track, framenr);
- if (plane_marker->flag & PLANE_MARKER_TRACKED) {
- plane_marker->flag &= ~PLANE_MARKER_TRACKED;
- BKE_tracking_track_plane_from_existing_motion(
- plane_track,
- plane_marker->framenr);
- }
- }
- else {
- MovieTrackingPlaneMarker *plane_marker =
- BKE_tracking_plane_marker_get_exact(plane_track,
- framenr);
- if (plane_marker) {
- if ((plane_marker->flag & PLANE_MARKER_TRACKED) == 0) {
- plane_marker->flag |= PLANE_MARKER_TRACKED;
- BKE_tracking_retrack_plane_from_existing_motion_at_segment(
- plane_track,
- plane_marker->framenr);
- }
- }
- }
- }
- }
-
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ ListBase *tracks_base = BKE_tracking_get_active_tracks(tracking);
+ for (MovieTrackingTrack *track = tracks_base->first; track != NULL; track = track->next) {
+ if (TRACK_VIEW_SELECTED(sc, track)) {
+ if (set) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_ensure(track, framenr);
+ marker->flag &= ~MARKER_TRACKED;
+ }
+ else {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr);
+ if (marker != NULL) {
+ marker->flag |= MARKER_TRACKED;
+ }
+ }
+ }
+ }
+
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first; plane_track != NULL;
+ plane_track = plane_track->next) {
+ if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
+ if (set) {
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_ensure(plane_track,
+ framenr);
+ if (plane_marker->flag & PLANE_MARKER_TRACKED) {
+ plane_marker->flag &= ~PLANE_MARKER_TRACKED;
+ BKE_tracking_track_plane_from_existing_motion(plane_track, plane_marker->framenr);
+ }
+ }
+ else {
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get_exact(plane_track,
+ framenr);
+ if (plane_marker) {
+ if ((plane_marker->flag & PLANE_MARKER_TRACKED) == 0) {
+ plane_marker->flag |= PLANE_MARKER_TRACKED;
+ BKE_tracking_retrack_plane_from_existing_motion_at_segment(plane_track,
+ plane_marker->framenr);
+ }
+ }
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
}
static int keyframe_insert_exec(bContext *C, wmOperator *UNUSED(op))
{
- keyframe_set_flag(C, true);
- return OPERATOR_FINISHED;
+ keyframe_set_flag(C, true);
+ return OPERATOR_FINISHED;
}
void CLIP_OT_keyframe_insert(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Insert keyframe";
- ot->description = "Insert a keyframe to selected tracks at current frame";
- ot->idname = "CLIP_OT_keyframe_insert";
+ /* identifiers */
+ ot->name = "Insert keyframe";
+ ot->description = "Insert a keyframe to selected tracks at current frame";
+ ot->idname = "CLIP_OT_keyframe_insert";
- /* api callbacks */
- ot->poll = ED_space_clip_tracking_poll;
- ot->exec = keyframe_insert_exec;
+ /* api callbacks */
+ ot->poll = ED_space_clip_tracking_poll;
+ ot->exec = keyframe_insert_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** Delete track keyframe operator *********************/
static int keyframe_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- keyframe_set_flag(C, false);
- return OPERATOR_FINISHED;
+ keyframe_set_flag(C, false);
+ return OPERATOR_FINISHED;
}
void CLIP_OT_keyframe_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete keyframe";
- ot->description = "Delete a keyframe from selected tracks at current frame";
- ot->idname = "CLIP_OT_keyframe_delete";
+ /* identifiers */
+ ot->name = "Delete keyframe";
+ ot->description = "Delete a keyframe from selected tracks at current frame";
+ ot->idname = "CLIP_OT_keyframe_delete";
- /* api callbacks */
- ot->poll = ED_space_clip_tracking_poll;
- ot->exec = keyframe_delete_exec;
+ /* api callbacks */
+ ot->poll = ED_space_clip_tracking_poll;
+ ot->exec = keyframe_delete_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/space_clip/tracking_ops_detect.c b/source/blender/editors/space_clip/tracking_ops_detect.c
index 131ccc05d35..ead150bba7f 100644
--- a/source/blender/editors/space_clip/tracking_ops_detect.c
+++ b/source/blender/editors/space_clip/tracking_ops_detect.c
@@ -52,105 +52,122 @@
static bGPDlayer *detect_get_layer(MovieClip *clip)
{
- if (clip->gpd == NULL) {
- return NULL;
- }
- for (bGPDlayer *layer = clip->gpd->layers.first;
- layer != NULL;
- layer = layer->next)
- {
- if (layer->flag & GP_LAYER_ACTIVE) {
- return layer;
- }
- }
- return NULL;
+ if (clip->gpd == NULL) {
+ return NULL;
+ }
+ for (bGPDlayer *layer = clip->gpd->layers.first; layer != NULL; layer = layer->next) {
+ if (layer->flag & GP_LAYER_ACTIVE) {
+ return layer;
+ }
+ }
+ return NULL;
}
static int detect_features_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- int clip_flag = clip->flag & MCLIP_TIMECODE_FLAGS;
- ImBuf *ibuf = BKE_movieclip_get_ibuf_flag(clip,
- &sc->user,
- clip_flag,
- MOVIECLIP_CACHE_SKIP);
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- int placement = RNA_enum_get(op->ptr, "placement");
- int margin = RNA_int_get(op->ptr, "margin");
- int min_distance = RNA_int_get(op->ptr, "min_distance");
- float threshold = RNA_float_get(op->ptr, "threshold");
- int place_outside_layer = 0;
- int framenr = ED_space_clip_get_clip_frame_number(sc);
- bGPDlayer *layer = NULL;
-
- if (!ibuf) {
- BKE_report(op->reports,
- RPT_ERROR,
- "Feature detection requires valid clip frame");
- return OPERATOR_CANCELLED;
- }
-
- if (placement != 0) {
- layer = detect_get_layer(clip);
- place_outside_layer = placement == 2;
- }
-
- /* Deselect existing tracks. */
- ed_tracking_delect_all_tracks(tracksbase);
- /* Run detector. */
- BKE_tracking_detect_harris(tracking,
- tracksbase,
- ibuf,
- framenr,
- margin,
- threshold / 100000.0f,
- min_distance,
- layer,
- place_outside_layer);
-
- IMB_freeImBuf(ibuf);
-
- BKE_tracking_dopesheet_tag_update(tracking);
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ int clip_flag = clip->flag & MCLIP_TIMECODE_FLAGS;
+ ImBuf *ibuf = BKE_movieclip_get_ibuf_flag(clip, &sc->user, clip_flag, MOVIECLIP_CACHE_SKIP);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ int placement = RNA_enum_get(op->ptr, "placement");
+ int margin = RNA_int_get(op->ptr, "margin");
+ int min_distance = RNA_int_get(op->ptr, "min_distance");
+ float threshold = RNA_float_get(op->ptr, "threshold");
+ int place_outside_layer = 0;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+ bGPDlayer *layer = NULL;
+
+ if (!ibuf) {
+ BKE_report(op->reports, RPT_ERROR, "Feature detection requires valid clip frame");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (placement != 0) {
+ layer = detect_get_layer(clip);
+ place_outside_layer = placement == 2;
+ }
+
+ /* Deselect existing tracks. */
+ ed_tracking_delect_all_tracks(tracksbase);
+ /* Run detector. */
+ BKE_tracking_detect_harris(tracking,
+ tracksbase,
+ ibuf,
+ framenr,
+ margin,
+ threshold / 100000.0f,
+ min_distance,
+ layer,
+ place_outside_layer);
+
+ IMB_freeImBuf(ibuf);
+
+ BKE_tracking_dopesheet_tag_update(tracking);
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_detect_features(wmOperatorType *ot)
{
- static const EnumPropertyItem placement_items[] = {
- {0, "FRAME", 0, "Whole Frame",
- "Place markers across the whole frame"},
- {1, "INSIDE_GPENCIL", 0, "Inside Grease Pencil",
- "Place markers only inside areas outlined with Grease Pencil"},
- {2, "OUTSIDE_GPENCIL", 0, "Outside Grease Pencil",
- "Place markers only outside areas outlined with Grease Pencil"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Detect Features";
- ot->description = "Automatically detect features and place markers to track";
- ot->idname = "CLIP_OT_detect_features";
-
- /* api callbacks */
- ot->exec = detect_features_exec;
- ot->poll = ED_space_clip_tracking_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "placement", placement_items, 0, "Placement",
- "Placement for detected features");
- RNA_def_int(ot->srna, "margin", 16, 0, INT_MAX, "Margin",
- "Only features further than margin pixels from the image "
- "edges are considered", 0, 300);
- RNA_def_float(ot->srna, "threshold", 0.5f, 0.0001f, FLT_MAX, "Threshold",
- "Threshold level to consider feature good enough for tracking",
- 0.0001f, FLT_MAX);
- RNA_def_int(ot->srna, "min_distance", 120, 0, INT_MAX, "Distance",
- "Minimal distance accepted between two features", 0, 300);
+ static const EnumPropertyItem placement_items[] = {
+ {0, "FRAME", 0, "Whole Frame", "Place markers across the whole frame"},
+ {1,
+ "INSIDE_GPENCIL",
+ 0,
+ "Inside Grease Pencil",
+ "Place markers only inside areas outlined with Grease Pencil"},
+ {2,
+ "OUTSIDE_GPENCIL",
+ 0,
+ "Outside Grease Pencil",
+ "Place markers only outside areas outlined with Grease Pencil"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Detect Features";
+ ot->description = "Automatically detect features and place markers to track";
+ ot->idname = "CLIP_OT_detect_features";
+
+ /* api callbacks */
+ ot->exec = detect_features_exec;
+ ot->poll = ED_space_clip_tracking_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(
+ ot->srna, "placement", placement_items, 0, "Placement", "Placement for detected features");
+ RNA_def_int(ot->srna,
+ "margin",
+ 16,
+ 0,
+ INT_MAX,
+ "Margin",
+ "Only features further than margin pixels from the image "
+ "edges are considered",
+ 0,
+ 300);
+ RNA_def_float(ot->srna,
+ "threshold",
+ 0.5f,
+ 0.0001f,
+ FLT_MAX,
+ "Threshold",
+ "Threshold level to consider feature good enough for tracking",
+ 0.0001f,
+ FLT_MAX);
+ RNA_def_int(ot->srna,
+ "min_distance",
+ 120,
+ 0,
+ INT_MAX,
+ "Distance",
+ "Minimal distance accepted between two features",
+ 0,
+ 300);
}
diff --git a/source/blender/editors/space_clip/tracking_ops_intern.h b/source/blender/editors/space_clip/tracking_ops_intern.h
index adf0285540a..8d2d61f050e 100644
--- a/source/blender/editors/space_clip/tracking_ops_intern.h
+++ b/source/blender/editors/space_clip/tracking_ops_intern.h
@@ -31,8 +31,7 @@ struct bContext;
/* tracking_utils.c */
-void clip_tracking_clear_invisible_track_selection(struct SpaceClip *sc,
- struct MovieClip *clip);
+void clip_tracking_clear_invisible_track_selection(struct SpaceClip *sc, struct MovieClip *clip);
void clip_tracking_show_cursor(struct bContext *C);
void clip_tracking_hide_cursor(struct bContext *C);
diff --git a/source/blender/editors/space_clip/tracking_ops_orient.c b/source/blender/editors/space_clip/tracking_ops_orient.c
index 2df74240241..e13598b0322 100644
--- a/source/blender/editors/space_clip/tracking_ops_orient.c
+++ b/source/blender/editors/space_clip/tracking_ops_orient.c
@@ -24,7 +24,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_constraint_types.h"
-#include "DNA_object_types.h" /* SELECT */
+#include "DNA_object_types.h" /* SELECT */
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -54,218 +54,200 @@
static Object *get_camera_with_movieclip(Scene *scene, MovieClip *clip)
{
- Object *camera = scene->camera;
-
- if (camera != NULL &&
- BKE_object_movieclip_get(scene, camera, false) == clip)
- {
- return camera;
- }
-
- FOREACH_SCENE_OBJECT_BEGIN(scene, ob)
- {
- if (ob->type == OB_CAMERA) {
- if (BKE_object_movieclip_get(scene, ob, false) == clip) {
- camera = ob;
- break;
- }
- }
- }
- FOREACH_SCENE_OBJECT_END;
-
- return camera;
+ Object *camera = scene->camera;
+
+ if (camera != NULL && BKE_object_movieclip_get(scene, camera, false) == clip) {
+ return camera;
+ }
+
+ FOREACH_SCENE_OBJECT_BEGIN (scene, ob) {
+ if (ob->type == OB_CAMERA) {
+ if (BKE_object_movieclip_get(scene, ob, false) == clip) {
+ camera = ob;
+ break;
+ }
+ }
+ }
+ FOREACH_SCENE_OBJECT_END;
+
+ return camera;
}
static Object *get_orientation_object(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
- Object *object = NULL;
-
- if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
- object = get_camera_with_movieclip(scene, clip);
- }
- else {
- object = OBACT(view_layer);
- }
-
- if (object != NULL && object->parent != NULL) {
- object = object->parent;
- }
-
- return object;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
+ Object *object = NULL;
+
+ if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
+ object = get_camera_with_movieclip(scene, clip);
+ }
+ else {
+ object = OBACT(view_layer);
+ }
+
+ if (object != NULL && object->parent != NULL) {
+ object = object->parent;
+ }
+
+ return object;
}
static bool set_orientation_poll(bContext *C)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- if (sc != NULL) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- if (clip != NULL) {
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
- if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
- return true;
- }
- else {
- return OBACT(view_layer) != NULL;
- }
- }
- }
- return false;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ if (sc != NULL) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ if (clip != NULL) {
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
+ if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
+ return true;
+ }
+ else {
+ return OBACT(view_layer) != NULL;
+ }
+ }
+ }
+ return false;
}
static int count_selected_bundles(bContext *C)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
- int tot = 0;
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_HAS_BUNDLE)) {
- tot++;
- }
- }
- return tot;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+ int tot = 0;
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_HAS_BUNDLE)) {
+ tot++;
+ }
+ }
+ return tot;
}
-static void object_solver_inverted_matrix(Scene *scene,
- Object *ob,
- float invmat[4][4])
+static void object_solver_inverted_matrix(Scene *scene, Object *ob, float invmat[4][4])
{
- bool found = false;
- for (bConstraint *con = ob->constraints.first;
- con != NULL;
- con = con->next)
- {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- if (cti == NULL) {
- continue;
- }
- if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
- bObjectSolverConstraint *data = (bObjectSolverConstraint *)con->data;
- if (!found) {
- Object *cam = data->camera ? data->camera : scene->camera;
- BKE_object_where_is_calc_mat4(cam, invmat);
- }
- mul_m4_m4m4(invmat, invmat, data->invmat);
- found = true;
- }
- }
- if (found) {
- invert_m4(invmat);
- }
- else {
- unit_m4(invmat);
- }
+ bool found = false;
+ for (bConstraint *con = ob->constraints.first; con != NULL; con = con->next) {
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ if (cti == NULL) {
+ continue;
+ }
+ if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
+ bObjectSolverConstraint *data = (bObjectSolverConstraint *)con->data;
+ if (!found) {
+ Object *cam = data->camera ? data->camera : scene->camera;
+ BKE_object_where_is_calc_mat4(cam, invmat);
+ }
+ mul_m4_m4m4(invmat, invmat, data->invmat);
+ found = true;
+ }
+ }
+ if (found) {
+ invert_m4(invmat);
+ }
+ else {
+ unit_m4(invmat);
+ }
}
static Object *object_solver_camera(Scene *scene, Object *ob)
{
- for (bConstraint *con = ob->constraints.first;
- con != NULL;
- con = con->next)
- {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- if (cti == NULL) {
- continue;
- }
- if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
- bObjectSolverConstraint *data = (bObjectSolverConstraint *)con->data;
- return (data->camera != NULL) ? data->camera : scene->camera;
- }
- }
- return NULL;
+ for (bConstraint *con = ob->constraints.first; con != NULL; con = con->next) {
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ if (cti == NULL) {
+ continue;
+ }
+ if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
+ bObjectSolverConstraint *data = (bObjectSolverConstraint *)con->data;
+ return (data->camera != NULL) ? data->camera : scene->camera;
+ }
+ }
+ return NULL;
}
static int set_origin_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- Scene *scene = CTX_data_scene(C);
- Object *camera = get_camera_with_movieclip(scene, clip);
- int selected_count = count_selected_bundles(C);
-
- if (selected_count == 0) {
- BKE_report(op->reports,
- RPT_ERROR,
- "At least one track with bundle should be selected to "
- "define origin position");
-
- return OPERATOR_CANCELLED;
- }
-
- Object *object = get_orientation_object(C);
- if (object == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No object to apply orientation on");
- return OPERATOR_CANCELLED;
- }
-
- MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
- ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
-
- float median[3] = {0.0f, 0.0f, 0.0f};
- zero_v3(median);
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- if (TRACK_VIEW_SELECTED(sc, track) &&
- (track->flag & TRACK_HAS_BUNDLE))
- {
- add_v3_v3(median, track->bundle_pos);
- }
- }
- mul_v3_fl(median, 1.0f / selected_count);
-
- float mat[4][4], vec[3];
- BKE_tracking_get_camera_object_matrix(scene, camera, mat);
- mul_v3_m4v3(vec, mat, median);
-
- if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
- sub_v3_v3(object->loc, vec);
- }
- else {
- object_solver_inverted_matrix(scene, object, mat);
- mul_v3_m4v3(vec, mat, vec);
- copy_v3_v3(object->loc, vec);
- }
-
- DEG_id_tag_update(&clip->id, 0);
- DEG_id_tag_update(&object->id, ID_RECALC_TRANSFORM);
-
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ Scene *scene = CTX_data_scene(C);
+ Object *camera = get_camera_with_movieclip(scene, clip);
+ int selected_count = count_selected_bundles(C);
+
+ if (selected_count == 0) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "At least one track with bundle should be selected to "
+ "define origin position");
+
+ return OPERATOR_CANCELLED;
+ }
+
+ Object *object = get_orientation_object(C);
+ if (object == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No object to apply orientation on");
+ return OPERATOR_CANCELLED;
+ }
+
+ MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
+ ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
+
+ float median[3] = {0.0f, 0.0f, 0.0f};
+ zero_v3(median);
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_HAS_BUNDLE)) {
+ add_v3_v3(median, track->bundle_pos);
+ }
+ }
+ mul_v3_fl(median, 1.0f / selected_count);
+
+ float mat[4][4], vec[3];
+ BKE_tracking_get_camera_object_matrix(scene, camera, mat);
+ mul_v3_m4v3(vec, mat, median);
+
+ if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
+ sub_v3_v3(object->loc, vec);
+ }
+ else {
+ object_solver_inverted_matrix(scene, object, mat);
+ mul_v3_m4v3(vec, mat, vec);
+ copy_v3_v3(object->loc, vec);
+ }
+
+ DEG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&object->id, ID_RECALC_TRANSFORM);
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_set_origin(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Origin";
- ot->description = "Set active marker as origin by moving camera (or its parent if present) in 3D space";
- ot->idname = "CLIP_OT_set_origin";
-
- /* api callbacks */
- ot->exec = set_origin_exec;
- ot->poll = set_orientation_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "use_median", 0, "Use Median",
- "Set origin to median point of selected bundles");
+ /* identifiers */
+ ot->name = "Set Origin";
+ ot->description =
+ "Set active marker as origin by moving camera (or its parent if present) in 3D space";
+ ot->idname = "CLIP_OT_set_origin";
+
+ /* api callbacks */
+ ot->exec = set_origin_exec;
+ ot->poll = set_orientation_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(
+ ot->srna, "use_median", 0, "Use Median", "Set origin to median point of selected bundles");
}
/********************** set floor operator *********************/
@@ -277,578 +259,596 @@ static void set_axis(Scene *scene,
MovieTrackingTrack *track,
char axis)
{
- Object *camera = get_camera_with_movieclip(scene, clip);
- const bool is_camera = (tracking_object->flag & TRACKING_OBJECT_CAMERA) != 0;
- bool flip = false;
- float mat[4][4], vec[3], obmat[4][4], dvec[3];
-
- BKE_object_to_mat4(ob, obmat);
-
- BKE_tracking_get_camera_object_matrix(scene, camera, mat);
- mul_v3_m4v3(vec, mat, track->bundle_pos);
- copy_v3_v3(dvec, vec);
-
- if (!is_camera) {
- float imat[4][4];
-
- object_solver_inverted_matrix(scene, ob, imat);
- mul_v3_m4v3(vec, imat, vec);
-
- invert_m4_m4(imat, obmat);
- mul_v3_m4v3(dvec, imat, vec);
-
- sub_v3_v3(vec, obmat[3]);
- }
-
- if (len_squared_v2(vec) < (1e-3f * 1e-3f)) {
- return;
- }
-
- unit_m4(mat);
-
- if (axis == 'X') {
- if (fabsf(dvec[1]) < 1e-3f) {
- flip = true;
-
- mat[0][0] = -1.0f; mat[0][1] = 0.0f; mat[0][2] = 0.0f;
- mat[1][0] = 0.0f; mat[1][1] = -1.0f; mat[1][2] = 0.0f;
- mat[2][0] = 0.0f; mat[2][1] = 0.0f; mat[2][2] = 1.0f;
- }
- else {
- copy_v3_v3(mat[0], vec);
-
- if (is_camera || fabsf(vec[2]) < 1e-3f) {
- mat[0][2] = 0.0f;
- mat[2][0] = 0.0f; mat[2][1] = 0.0f; mat[2][2] = 1.0f;
- cross_v3_v3v3(mat[1], mat[2], mat[0]);
- }
- else {
- vec[2] = 0.0f;
-
- cross_v3_v3v3(mat[1], mat[0], vec);
- cross_v3_v3v3(mat[2], mat[0], mat[1]);
- }
- }
- }
- else {
- if (fabsf(dvec[0]) < 1e-3f) {
- flip = true;
-
- mat[0][0] = -1.0f; mat[0][1] = 0.0f; mat[0][2] = 0.0f;
- mat[1][0] = 0.0f; mat[1][1] = -1.0f; mat[1][2] = 0.0f;
- mat[2][0] = 0.0f; mat[2][1] = 0.0f; mat[2][2] = 1.0f;
- }
- else {
- copy_v3_v3(mat[1], vec);
-
- if (is_camera || fabsf(vec[2]) < 1e-3f) {
- mat[1][2] = 0.0f;
- mat[2][0] = 0.0f; mat[2][1] = 0.0f; mat[2][2] = 1.0f;
- cross_v3_v3v3(mat[0], mat[1], mat[2]);
- }
- else {
- vec[2] = 0.0f;
-
- cross_v3_v3v3(mat[0], vec, mat[1]);
- cross_v3_v3v3(mat[2], mat[0], mat[1]);
- }
- }
- }
-
- normalize_v3(mat[0]);
- normalize_v3(mat[1]);
- normalize_v3(mat[2]);
-
- if (is_camera) {
- invert_m4(mat);
-
- mul_m4_m4m4(mat, mat, obmat);
- }
- else {
- if (!flip) {
- float lmat[4][4], ilmat[4][4], rmat[3][3];
-
- BKE_object_rot_to_mat3(ob, rmat, true);
- invert_m3(rmat);
- mul_m4_m4m3(mat, mat, rmat);
-
- unit_m4(lmat);
- copy_v3_v3(lmat[3], obmat[3]);
- invert_m4_m4(ilmat, lmat);
-
- mul_m4_series(mat, lmat, mat, ilmat, obmat);
- }
- else {
- mul_m4_m4m4(mat, obmat, mat);
- }
- }
-
- BKE_object_apply_mat4(ob, mat, 0, 0);
+ Object *camera = get_camera_with_movieclip(scene, clip);
+ const bool is_camera = (tracking_object->flag & TRACKING_OBJECT_CAMERA) != 0;
+ bool flip = false;
+ float mat[4][4], vec[3], obmat[4][4], dvec[3];
+
+ BKE_object_to_mat4(ob, obmat);
+
+ BKE_tracking_get_camera_object_matrix(scene, camera, mat);
+ mul_v3_m4v3(vec, mat, track->bundle_pos);
+ copy_v3_v3(dvec, vec);
+
+ if (!is_camera) {
+ float imat[4][4];
+
+ object_solver_inverted_matrix(scene, ob, imat);
+ mul_v3_m4v3(vec, imat, vec);
+
+ invert_m4_m4(imat, obmat);
+ mul_v3_m4v3(dvec, imat, vec);
+
+ sub_v3_v3(vec, obmat[3]);
+ }
+
+ if (len_squared_v2(vec) < (1e-3f * 1e-3f)) {
+ return;
+ }
+
+ unit_m4(mat);
+
+ if (axis == 'X') {
+ if (fabsf(dvec[1]) < 1e-3f) {
+ flip = true;
+
+ mat[0][0] = -1.0f;
+ mat[0][1] = 0.0f;
+ mat[0][2] = 0.0f;
+ mat[1][0] = 0.0f;
+ mat[1][1] = -1.0f;
+ mat[1][2] = 0.0f;
+ mat[2][0] = 0.0f;
+ mat[2][1] = 0.0f;
+ mat[2][2] = 1.0f;
+ }
+ else {
+ copy_v3_v3(mat[0], vec);
+
+ if (is_camera || fabsf(vec[2]) < 1e-3f) {
+ mat[0][2] = 0.0f;
+ mat[2][0] = 0.0f;
+ mat[2][1] = 0.0f;
+ mat[2][2] = 1.0f;
+ cross_v3_v3v3(mat[1], mat[2], mat[0]);
+ }
+ else {
+ vec[2] = 0.0f;
+
+ cross_v3_v3v3(mat[1], mat[0], vec);
+ cross_v3_v3v3(mat[2], mat[0], mat[1]);
+ }
+ }
+ }
+ else {
+ if (fabsf(dvec[0]) < 1e-3f) {
+ flip = true;
+
+ mat[0][0] = -1.0f;
+ mat[0][1] = 0.0f;
+ mat[0][2] = 0.0f;
+ mat[1][0] = 0.0f;
+ mat[1][1] = -1.0f;
+ mat[1][2] = 0.0f;
+ mat[2][0] = 0.0f;
+ mat[2][1] = 0.0f;
+ mat[2][2] = 1.0f;
+ }
+ else {
+ copy_v3_v3(mat[1], vec);
+
+ if (is_camera || fabsf(vec[2]) < 1e-3f) {
+ mat[1][2] = 0.0f;
+ mat[2][0] = 0.0f;
+ mat[2][1] = 0.0f;
+ mat[2][2] = 1.0f;
+ cross_v3_v3v3(mat[0], mat[1], mat[2]);
+ }
+ else {
+ vec[2] = 0.0f;
+
+ cross_v3_v3v3(mat[0], vec, mat[1]);
+ cross_v3_v3v3(mat[2], mat[0], mat[1]);
+ }
+ }
+ }
+
+ normalize_v3(mat[0]);
+ normalize_v3(mat[1]);
+ normalize_v3(mat[2]);
+
+ if (is_camera) {
+ invert_m4(mat);
+
+ mul_m4_m4m4(mat, mat, obmat);
+ }
+ else {
+ if (!flip) {
+ float lmat[4][4], ilmat[4][4], rmat[3][3];
+
+ BKE_object_rot_to_mat3(ob, rmat, true);
+ invert_m3(rmat);
+ mul_m4_m4m3(mat, mat, rmat);
+
+ unit_m4(lmat);
+ copy_v3_v3(lmat[3], obmat[3]);
+ invert_m4_m4(ilmat, lmat);
+
+ mul_m4_series(mat, lmat, mat, ilmat, obmat);
+ }
+ else {
+ mul_m4_m4m4(mat, obmat, mat);
+ }
+ }
+
+ BKE_object_apply_mat4(ob, mat, 0, 0);
}
static int set_plane_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- Scene *scene = CTX_data_scene(C);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *tracking_object;
- MovieTrackingTrack *track, *axis_track = NULL, *act_track;
- ListBase *tracksbase;
- Object *object;
- Object *camera = get_camera_with_movieclip(scene, clip);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int tot = 0;
- float vec[3][3], mat[4][4], obmat[4][4], newmat[4][4], orig[3] = {0.0f, 0.0f, 0.0f};
- int plane = RNA_enum_get(op->ptr, "plane");
- float rot[4][4] = {{0.0f, 0.0f, -1.0f, 0.0f},
- {0.0f, 1.0f, 0.0f, 0.0f},
- {1.0f, 0.0f, 0.0f, 0.0f},
- {0.0f, 0.0f, 0.0f, 1.0f}}; /* 90 degrees Y-axis rotation matrix */
-
- if (count_selected_bundles(C) != 3) {
- BKE_report(op->reports, RPT_ERROR, "Three tracks with bundles are needed to orient the floor");
-
- return OPERATOR_CANCELLED;
- }
-
- tracking_object = BKE_tracking_object_get_active(tracking);
- tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
- act_track = BKE_tracking_track_get_active(tracking);
-
- object = get_orientation_object(C);
- if (object == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No object to apply orientation on");
- return OPERATOR_CANCELLED;
- }
-
- BKE_tracking_get_camera_object_matrix(scene, camera, mat);
-
- /* Get 3 bundles to use as reference. */
- track = tracksbase->first;
- while (track && tot < 3) {
- if (track->flag & TRACK_HAS_BUNDLE && TRACK_VIEW_SELECTED(sc, track)) {
- mul_v3_m4v3(vec[tot], mat, track->bundle_pos);
- if (tot == 0 || track == act_track) {
- copy_v3_v3(orig, vec[tot]);
- }
- else {
- axis_track = track;
- }
- tot++;
- }
- track = track->next;
- }
-
- sub_v3_v3(vec[1], vec[0]);
- sub_v3_v3(vec[2], vec[0]);
-
- /* Construct ortho-normal basis. */
- unit_m4(mat);
- if (plane == 0) { /* floor */
- cross_v3_v3v3(mat[0], vec[1], vec[2]);
- copy_v3_v3(mat[1], vec[1]);
- cross_v3_v3v3(mat[2], mat[0], mat[1]);
- }
- else if (plane == 1) { /* wall */
- cross_v3_v3v3(mat[2], vec[1], vec[2]);
- copy_v3_v3(mat[1], vec[1]);
- cross_v3_v3v3(mat[0], mat[1], mat[2]);
- }
-
- normalize_v3(mat[0]);
- normalize_v3(mat[1]);
- normalize_v3(mat[2]);
-
- /* Move to origin point. */
- mat[3][0] = orig[0];
- mat[3][1] = orig[1];
- mat[3][2] = orig[2];
-
- if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
- invert_m4(mat);
-
- BKE_object_to_mat4(object, obmat);
- mul_m4_m4m4(mat, mat, obmat);
- mul_m4_m4m4(newmat, rot, mat);
- BKE_object_apply_mat4(object, newmat, 0, 0);
-
- /* Make camera have positive z-coordinate. */
- if (object->loc[2] < 0) {
- invert_m4(rot);
- mul_m4_m4m4(newmat, rot, mat);
- BKE_object_apply_mat4(object, newmat, 0, 0);
- }
- }
- else {
- BKE_object_apply_mat4(object, mat, 0, 0);
- }
-
- BKE_object_where_is_calc(depsgraph, scene, object);
- set_axis(scene, object, clip, tracking_object, axis_track, 'X');
-
- DEG_id_tag_update(&clip->id, 0);
- DEG_id_tag_update(&object->id, ID_RECALC_TRANSFORM);
-
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ Scene *scene = CTX_data_scene(C);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *tracking_object;
+ MovieTrackingTrack *track, *axis_track = NULL, *act_track;
+ ListBase *tracksbase;
+ Object *object;
+ Object *camera = get_camera_with_movieclip(scene, clip);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int tot = 0;
+ float vec[3][3], mat[4][4], obmat[4][4], newmat[4][4], orig[3] = {0.0f, 0.0f, 0.0f};
+ int plane = RNA_enum_get(op->ptr, "plane");
+ float rot[4][4] = {{0.0f, 0.0f, -1.0f, 0.0f},
+ {0.0f, 1.0f, 0.0f, 0.0f},
+ {1.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 0.0f, 1.0f}}; /* 90 degrees Y-axis rotation matrix */
+
+ if (count_selected_bundles(C) != 3) {
+ BKE_report(op->reports, RPT_ERROR, "Three tracks with bundles are needed to orient the floor");
+
+ return OPERATOR_CANCELLED;
+ }
+
+ tracking_object = BKE_tracking_object_get_active(tracking);
+ tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
+ act_track = BKE_tracking_track_get_active(tracking);
+
+ object = get_orientation_object(C);
+ if (object == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No object to apply orientation on");
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_tracking_get_camera_object_matrix(scene, camera, mat);
+
+ /* Get 3 bundles to use as reference. */
+ track = tracksbase->first;
+ while (track && tot < 3) {
+ if (track->flag & TRACK_HAS_BUNDLE && TRACK_VIEW_SELECTED(sc, track)) {
+ mul_v3_m4v3(vec[tot], mat, track->bundle_pos);
+ if (tot == 0 || track == act_track) {
+ copy_v3_v3(orig, vec[tot]);
+ }
+ else {
+ axis_track = track;
+ }
+ tot++;
+ }
+ track = track->next;
+ }
+
+ sub_v3_v3(vec[1], vec[0]);
+ sub_v3_v3(vec[2], vec[0]);
+
+ /* Construct ortho-normal basis. */
+ unit_m4(mat);
+ if (plane == 0) { /* floor */
+ cross_v3_v3v3(mat[0], vec[1], vec[2]);
+ copy_v3_v3(mat[1], vec[1]);
+ cross_v3_v3v3(mat[2], mat[0], mat[1]);
+ }
+ else if (plane == 1) { /* wall */
+ cross_v3_v3v3(mat[2], vec[1], vec[2]);
+ copy_v3_v3(mat[1], vec[1]);
+ cross_v3_v3v3(mat[0], mat[1], mat[2]);
+ }
+
+ normalize_v3(mat[0]);
+ normalize_v3(mat[1]);
+ normalize_v3(mat[2]);
+
+ /* Move to origin point. */
+ mat[3][0] = orig[0];
+ mat[3][1] = orig[1];
+ mat[3][2] = orig[2];
+
+ if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
+ invert_m4(mat);
+
+ BKE_object_to_mat4(object, obmat);
+ mul_m4_m4m4(mat, mat, obmat);
+ mul_m4_m4m4(newmat, rot, mat);
+ BKE_object_apply_mat4(object, newmat, 0, 0);
+
+ /* Make camera have positive z-coordinate. */
+ if (object->loc[2] < 0) {
+ invert_m4(rot);
+ mul_m4_m4m4(newmat, rot, mat);
+ BKE_object_apply_mat4(object, newmat, 0, 0);
+ }
+ }
+ else {
+ BKE_object_apply_mat4(object, mat, 0, 0);
+ }
+
+ BKE_object_where_is_calc(depsgraph, scene, object);
+ set_axis(scene, object, clip, tracking_object, axis_track, 'X');
+
+ DEG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&object->id, ID_RECALC_TRANSFORM);
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_set_plane(wmOperatorType *ot)
{
- static const EnumPropertyItem plane_items[] = {
- {0, "FLOOR", 0, "Floor", "Set floor plane"},
- {1, "WALL", 0, "Wall", "Set wall plane"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Set Plane";
- ot->description = "Set plane based on 3 selected bundles by moving camera "
- "(or its parent if present) in 3D space";
- ot->idname = "CLIP_OT_set_plane";
-
- /* api callbacks */
- ot->exec = set_plane_exec;
- ot->poll = set_orientation_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "plane", plane_items, 0, "Plane",
- "Plane to be used for orientation");
+ static const EnumPropertyItem plane_items[] = {
+ {0, "FLOOR", 0, "Floor", "Set floor plane"},
+ {1, "WALL", 0, "Wall", "Set wall plane"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Set Plane";
+ ot->description =
+ "Set plane based on 3 selected bundles by moving camera "
+ "(or its parent if present) in 3D space";
+ ot->idname = "CLIP_OT_set_plane";
+
+ /* api callbacks */
+ ot->exec = set_plane_exec;
+ ot->poll = set_orientation_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "plane", plane_items, 0, "Plane", "Plane to be used for orientation");
}
/********************** set axis operator *********************/
static int set_axis_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
- Scene *scene = CTX_data_scene(C);
- Object *object;
- int axis = RNA_enum_get(op->ptr, "axis");
-
- if (count_selected_bundles(C) != 1) {
- BKE_report(op->reports,
- RPT_ERROR,
- "Single track with bundle should be selected to define axis");
- return OPERATOR_CANCELLED;
- }
-
- object = get_orientation_object(C);
- if (object == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No object to apply orientation on");
- return OPERATOR_CANCELLED;
- }
-
- ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking,
- tracking_object);
- MovieTrackingTrack *track = tracksbase->first;
- while (track) {
- if (TRACK_VIEW_SELECTED(sc, track) &&
- (track->flag & TRACK_HAS_BUNDLE))
- {
- break;
- }
- track = track->next;
- }
-
- set_axis(scene, object, clip, tracking_object, track, axis == 0 ? 'X' : 'Y');
-
- DEG_id_tag_update(&clip->id, 0);
- DEG_id_tag_update(&object->id, ID_RECALC_TRANSFORM);
-
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
+ Scene *scene = CTX_data_scene(C);
+ Object *object;
+ int axis = RNA_enum_get(op->ptr, "axis");
+
+ if (count_selected_bundles(C) != 1) {
+ BKE_report(
+ op->reports, RPT_ERROR, "Single track with bundle should be selected to define axis");
+ return OPERATOR_CANCELLED;
+ }
+
+ object = get_orientation_object(C);
+ if (object == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No object to apply orientation on");
+ return OPERATOR_CANCELLED;
+ }
+
+ ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
+ MovieTrackingTrack *track = tracksbase->first;
+ while (track) {
+ if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_HAS_BUNDLE)) {
+ break;
+ }
+ track = track->next;
+ }
+
+ set_axis(scene, object, clip, tracking_object, track, axis == 0 ? 'X' : 'Y');
+
+ DEG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&object->id, ID_RECALC_TRANSFORM);
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_set_axis(wmOperatorType *ot)
{
- static const EnumPropertyItem axis_actions[] = {
- {0, "X", 0, "X", "Align bundle align X axis"},
- {1, "Y", 0, "Y", "Align bundle align Y axis"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Set Axis";
- ot->description = "Set direction of scene axis rotating camera "
- "(or its parent if present) and assume selected track "
- "lies on real axis, joining it with the origin";
- ot->idname = "CLIP_OT_set_axis";
-
- /* api callbacks */
- ot->exec = set_axis_exec;
- ot->poll = set_orientation_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "axis", axis_actions, 0, "Axis",
- "Axis to use to align bundle along");
+ static const EnumPropertyItem axis_actions[] = {
+ {0, "X", 0, "X", "Align bundle align X axis"},
+ {1, "Y", 0, "Y", "Align bundle align Y axis"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Set Axis";
+ ot->description =
+ "Set direction of scene axis rotating camera "
+ "(or its parent if present) and assume selected track "
+ "lies on real axis, joining it with the origin";
+ ot->idname = "CLIP_OT_set_axis";
+
+ /* api callbacks */
+ ot->exec = set_axis_exec;
+ ot->poll = set_orientation_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "axis", axis_actions, 0, "Axis", "Axis to use to align bundle along");
}
/********************** set scale operator *********************/
-static int do_set_scale(bContext *C,
- wmOperator *op,
- bool scale_solution,
- bool apply_scale)
+static int do_set_scale(bContext *C, wmOperator *op, bool scale_solution, bool apply_scale)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
- MovieTrackingTrack *track;
- Scene *scene = CTX_data_scene(C);
- Object *object = NULL;
- Object *camera = get_camera_with_movieclip(scene, clip);
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- int tot = 0;
- float vec[2][3], mat[4][4], scale;
- float dist = RNA_float_get(op->ptr, "distance");
-
- if (count_selected_bundles(C) != 2) {
- BKE_report(op->reports,
- RPT_ERROR,
- "Two tracks with bundles should be selected to set scale");
- return OPERATOR_CANCELLED;
- }
-
- if (!scale_solution && !apply_scale) {
- object = get_orientation_object(C);
- if (object == NULL) {
- BKE_report(op->reports,
- RPT_ERROR,
- "No object to apply orientation on");
- return OPERATOR_CANCELLED;
- }
- }
-
- BKE_tracking_get_camera_object_matrix(scene, camera, mat);
-
- track = tracksbase->first;
- while (track) {
- if (TRACK_VIEW_SELECTED(sc, track)) {
- mul_v3_m4v3(vec[tot], mat, track->bundle_pos);
- tot++;
- }
- track = track->next;
- }
-
- sub_v3_v3(vec[0], vec[1]);
-
- if (len_v3(vec[0]) > 1e-5f) {
- scale = dist / len_v3(vec[0]);
- if (apply_scale) {
- /* Apply scale on reconstructed scene itself. */
- MovieTrackingReconstruction *reconstruction =
- BKE_tracking_get_active_reconstruction(tracking);
- MovieReconstructedCamera *reconstructed_cameras;
- int i;
-
- for (track = tracksbase->first; track; track = track->next) {
- mul_v3_fl(track->bundle_pos, scale);
- }
-
- reconstructed_cameras = reconstruction->cameras;
- for (i = 0; i < reconstruction->camnr; i++) {
- mul_v3_fl(reconstructed_cameras[i].mat[3], scale);
- }
-
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- }
- else {
- if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
- mul_v3_fl(object->scale, scale);
- mul_v3_fl(object->loc, scale);
- }
- else if (!scale_solution) {
- Object *solver_camera = object_solver_camera(scene, object);
-
- object->scale[0] = object->scale[1] = object->scale[2] = 1.0f / scale;
-
- if (solver_camera) {
- object->scale[0] /= solver_camera->scale[0];
- object->scale[1] /= solver_camera->scale[1];
- object->scale[2] /= solver_camera->scale[2];
- }
- }
- else {
- tracking_object->scale = scale;
- }
-
- DEG_id_tag_update(&clip->id, 0);
-
- if (object)
- DEG_id_tag_update(&object->id, ID_RECALC_TRANSFORM);
-
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- }
- }
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
+ MovieTrackingTrack *track;
+ Scene *scene = CTX_data_scene(C);
+ Object *object = NULL;
+ Object *camera = get_camera_with_movieclip(scene, clip);
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ int tot = 0;
+ float vec[2][3], mat[4][4], scale;
+ float dist = RNA_float_get(op->ptr, "distance");
+
+ if (count_selected_bundles(C) != 2) {
+ BKE_report(op->reports, RPT_ERROR, "Two tracks with bundles should be selected to set scale");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!scale_solution && !apply_scale) {
+ object = get_orientation_object(C);
+ if (object == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No object to apply orientation on");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ BKE_tracking_get_camera_object_matrix(scene, camera, mat);
+
+ track = tracksbase->first;
+ while (track) {
+ if (TRACK_VIEW_SELECTED(sc, track)) {
+ mul_v3_m4v3(vec[tot], mat, track->bundle_pos);
+ tot++;
+ }
+ track = track->next;
+ }
+
+ sub_v3_v3(vec[0], vec[1]);
+
+ if (len_v3(vec[0]) > 1e-5f) {
+ scale = dist / len_v3(vec[0]);
+ if (apply_scale) {
+ /* Apply scale on reconstructed scene itself. */
+ MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(
+ tracking);
+ MovieReconstructedCamera *reconstructed_cameras;
+ int i;
+
+ for (track = tracksbase->first; track; track = track->next) {
+ mul_v3_fl(track->bundle_pos, scale);
+ }
+
+ reconstructed_cameras = reconstruction->cameras;
+ for (i = 0; i < reconstruction->camnr; i++) {
+ mul_v3_fl(reconstructed_cameras[i].mat[3], scale);
+ }
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ }
+ else {
+ if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
+ mul_v3_fl(object->scale, scale);
+ mul_v3_fl(object->loc, scale);
+ }
+ else if (!scale_solution) {
+ Object *solver_camera = object_solver_camera(scene, object);
+
+ object->scale[0] = object->scale[1] = object->scale[2] = 1.0f / scale;
+
+ if (solver_camera) {
+ object->scale[0] /= solver_camera->scale[0];
+ object->scale[1] /= solver_camera->scale[1];
+ object->scale[2] /= solver_camera->scale[2];
+ }
+ }
+ else {
+ tracking_object->scale = scale;
+ }
+
+ DEG_id_tag_update(&clip->id, 0);
+
+ if (object)
+ DEG_id_tag_update(&object->id, ID_RECALC_TRANSFORM);
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
static int set_scale_exec(bContext *C, wmOperator *op)
{
- return do_set_scale(C, op, false, false);
+ return do_set_scale(C, op, false, false);
}
-static int set_scale_invoke(bContext *C,
- wmOperator *op,
- const wmEvent *UNUSED(event))
+static int set_scale_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
- if (!RNA_struct_property_is_set(op->ptr, "distance"))
- RNA_float_set(op->ptr, "distance", clip->tracking.settings.dist);
+ if (!RNA_struct_property_is_set(op->ptr, "distance"))
+ RNA_float_set(op->ptr, "distance", clip->tracking.settings.dist);
- return set_scale_exec(C, op);
+ return set_scale_exec(C, op);
}
void CLIP_OT_set_scale(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Scale";
- ot->description = "Set scale of scene by scaling camera (or its parent if present)";
- ot->idname = "CLIP_OT_set_scale";
-
- /* api callbacks */
- ot->exec = set_scale_exec;
- ot->invoke = set_scale_invoke;
- ot->poll = set_orientation_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_float(ot->srna, "distance", 0.0f, -FLT_MAX, FLT_MAX,
- "Distance", "Distance between selected tracks", -100.0f, 100.0f);
+ /* identifiers */
+ ot->name = "Set Scale";
+ ot->description = "Set scale of scene by scaling camera (or its parent if present)";
+ ot->idname = "CLIP_OT_set_scale";
+
+ /* api callbacks */
+ ot->exec = set_scale_exec;
+ ot->invoke = set_scale_invoke;
+ ot->poll = set_orientation_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float(ot->srna,
+ "distance",
+ 0.0f,
+ -FLT_MAX,
+ FLT_MAX,
+ "Distance",
+ "Distance between selected tracks",
+ -100.0f,
+ 100.0f);
}
/********************** set solution scale operator *********************/
static bool set_solution_scale_poll(bContext *C)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- if (sc != NULL) {
- MovieClip *clip = ED_space_clip_get_clip(sc);
- if (clip != NULL) {
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *tracking_object =
- BKE_tracking_object_get_active(tracking);
- return (tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0;
- }
- }
- return false;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ if (sc != NULL) {
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ if (clip != NULL) {
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
+ return (tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0;
+ }
+ }
+ return false;
}
static int set_solution_scale_exec(bContext *C, wmOperator *op)
{
- return do_set_scale(C, op, true, false);
+ return do_set_scale(C, op, true, false);
}
-static int set_solution_scale_invoke(bContext *C,
- wmOperator *op,
- const wmEvent *UNUSED(event))
+static int set_solution_scale_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
- if (!RNA_struct_property_is_set(op->ptr, "distance")) {
- RNA_float_set(op->ptr,
- "distance",
- clip->tracking.settings.object_distance);
- }
+ if (!RNA_struct_property_is_set(op->ptr, "distance")) {
+ RNA_float_set(op->ptr, "distance", clip->tracking.settings.object_distance);
+ }
- return set_solution_scale_exec(C, op);
+ return set_solution_scale_exec(C, op);
}
void CLIP_OT_set_solution_scale(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Solution Scale";
- ot->description = "Set object solution scale using distance between "
- "two selected tracks";
- ot->idname = "CLIP_OT_set_solution_scale";
-
- /* api callbacks */
- ot->exec = set_solution_scale_exec;
- ot->invoke = set_solution_scale_invoke;
- ot->poll = set_solution_scale_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_float(ot->srna, "distance", 0.0f, -FLT_MAX, FLT_MAX,
- "Distance", "Distance between selected tracks",
- -100.0f, 100.0f);
+ /* identifiers */
+ ot->name = "Set Solution Scale";
+ ot->description =
+ "Set object solution scale using distance between "
+ "two selected tracks";
+ ot->idname = "CLIP_OT_set_solution_scale";
+
+ /* api callbacks */
+ ot->exec = set_solution_scale_exec;
+ ot->invoke = set_solution_scale_invoke;
+ ot->poll = set_solution_scale_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float(ot->srna,
+ "distance",
+ 0.0f,
+ -FLT_MAX,
+ FLT_MAX,
+ "Distance",
+ "Distance between selected tracks",
+ -100.0f,
+ 100.0f);
}
/********************** apply solution scale operator *********************/
static bool apply_solution_scale_poll(bContext *C)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- if (sc != NULL) {
- MovieClip *clip = ED_space_clip_get_clip(sc);
- if (clip != NULL) {
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *tracking_object =
- BKE_tracking_object_get_active(tracking);
- return (tracking_object->flag & TRACKING_OBJECT_CAMERA) != 0;
- }
- }
- return 0;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ if (sc != NULL) {
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ if (clip != NULL) {
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
+ return (tracking_object->flag & TRACKING_OBJECT_CAMERA) != 0;
+ }
+ }
+ return 0;
}
static int apply_solution_scale_exec(bContext *C, wmOperator *op)
{
- return do_set_scale(C, op, false, true);
+ return do_set_scale(C, op, false, true);
}
static int apply_solution_scale_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- if (!RNA_struct_property_is_set(op->ptr, "distance")) {
- RNA_float_set(op->ptr, "distance", clip->tracking.settings.dist);
- }
- return apply_solution_scale_exec(C, op);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ if (!RNA_struct_property_is_set(op->ptr, "distance")) {
+ RNA_float_set(op->ptr, "distance", clip->tracking.settings.dist);
+ }
+ return apply_solution_scale_exec(C, op);
}
void CLIP_OT_apply_solution_scale(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Apply Solution Scale";
- ot->description = "Apply scale on solution itself to make distance between "
- "selected tracks equals to desired";
- ot->idname = "CLIP_OT_apply_solution_scale";
-
- /* api callbacks */
- ot->exec = apply_solution_scale_exec;
- ot->invoke = apply_solution_scale_invoke;
- ot->poll = apply_solution_scale_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_float(ot->srna, "distance", 0.0f, -FLT_MAX, FLT_MAX,
- "Distance", "Distance between selected tracks",
- -100.0f, 100.0f);
+ /* identifiers */
+ ot->name = "Apply Solution Scale";
+ ot->description =
+ "Apply scale on solution itself to make distance between "
+ "selected tracks equals to desired";
+ ot->idname = "CLIP_OT_apply_solution_scale";
+
+ /* api callbacks */
+ ot->exec = apply_solution_scale_exec;
+ ot->invoke = apply_solution_scale_invoke;
+ ot->poll = apply_solution_scale_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float(ot->srna,
+ "distance",
+ 0.0f,
+ -FLT_MAX,
+ FLT_MAX,
+ "Distance",
+ "Distance between selected tracks",
+ -100.0f,
+ 100.0f);
}
diff --git a/source/blender/editors/space_clip/tracking_ops_plane.c b/source/blender/editors/space_clip/tracking_ops_plane.c
index a12e03a252c..238410da5e1 100644
--- a/source/blender/editors/space_clip/tracking_ops_plane.c
+++ b/source/blender/editors/space_clip/tracking_ops_plane.c
@@ -47,377 +47,349 @@
static int create_plane_track_tracks_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingPlaneTrack *plane_track;
- ListBase *tracks_base = BKE_tracking_get_active_tracks(tracking);
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- plane_track = BKE_tracking_plane_track_add(tracking,
- plane_tracks_base,
- tracks_base,
- framenr);
-
- if (plane_track == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Need at least 4 selected point tracks to create a plane");
- return OPERATOR_CANCELLED;
- }
- else {
- BKE_tracking_tracks_deselect_all(tracks_base);
-
- plane_track->flag |= SELECT;
- clip->tracking.act_track = NULL;
- clip->tracking.act_plane_track = plane_track;
-
- /* Compute homoraphies and apply them on marker's corner, so we've got
- * quite nice motion from the very beginning.
- */
- BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
- }
-
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingPlaneTrack *plane_track;
+ ListBase *tracks_base = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ plane_track = BKE_tracking_plane_track_add(tracking, plane_tracks_base, tracks_base, framenr);
+
+ if (plane_track == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Need at least 4 selected point tracks to create a plane");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ BKE_tracking_tracks_deselect_all(tracks_base);
+
+ plane_track->flag |= SELECT;
+ clip->tracking.act_track = NULL;
+ clip->tracking.act_plane_track = plane_track;
+
+ /* Compute homoraphies and apply them on marker's corner, so we've got
+ * quite nice motion from the very beginning.
+ */
+ BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
+ }
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_create_plane_track(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Create Plane Track";
- ot->description = "Create new plane track out of selected point tracks";
- ot->idname = "CLIP_OT_create_plane_track";
+ /* identifiers */
+ ot->name = "Create Plane Track";
+ ot->description = "Create new plane track out of selected point tracks";
+ ot->idname = "CLIP_OT_create_plane_track";
- /* api callbacks */
- ot->exec = create_plane_track_tracks_exec;
- ot->poll = ED_space_clip_tracking_poll;
+ /* api callbacks */
+ ot->exec = create_plane_track_tracks_exec;
+ ot->poll = ED_space_clip_tracking_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** Slide plane marker corner operator *********************/
typedef struct SlidePlaneMarkerData {
- int event_type;
- MovieTrackingPlaneTrack *plane_track;
- MovieTrackingPlaneMarker *plane_marker;
- int width, height;
- int corner_index;
- float *corner;
- int previous_mval[2];
- float previous_corner[2];
- float old_corner[2];
- bool accurate;
+ int event_type;
+ MovieTrackingPlaneTrack *plane_track;
+ MovieTrackingPlaneMarker *plane_marker;
+ int width, height;
+ int corner_index;
+ float *corner;
+ int previous_mval[2];
+ float previous_corner[2];
+ float old_corner[2];
+ bool accurate;
} SlidePlaneMarkerData;
-static float mouse_to_plane_slide_zone_distance_squared(
- const float co[2],
- const float slide_zone[2],
- int width,
- int height)
+static float mouse_to_plane_slide_zone_distance_squared(const float co[2],
+ const float slide_zone[2],
+ int width,
+ int height)
{
- 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]);
+ 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]);
}
-static MovieTrackingPlaneTrack *tracking_plane_marker_check_slide(
- bContext *C,
- const wmEvent *event,
- int *corner_r)
+static MovieTrackingPlaneTrack *tracking_plane_marker_check_slide(bContext *C,
+ const wmEvent *event,
+ int *corner_r)
{
- const float distance_clip_squared = 12.0f * 12.0f;
- SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- int width, height;
- float co[2];
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- ED_space_clip_get_size(sc, &width, &height);
- if (width == 0 || height == 0) {
- return NULL;
- }
-
- ED_clip_mouse_pos(sc, ar, event->mval, co);
-
- float min_distance_squared = FLT_MAX;
- int min_corner = -1;
- MovieTrackingPlaneTrack *min_plane_track = NULL;
- for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first;
- plane_track != NULL;
- plane_track = plane_track->next)
- {
- if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
- MovieTrackingPlaneMarker *plane_marker =
- BKE_tracking_plane_marker_get(plane_track, framenr);
- for (int i = 0; i < 4; i++) {
- float distance_squared =
- mouse_to_plane_slide_zone_distance_squared(
- co,
- plane_marker->corners[i],
- width,
- height);
-
- if (distance_squared < min_distance_squared) {
- min_distance_squared = distance_squared;
- min_corner = i;
- min_plane_track = plane_track;
- }
- }
- }
- }
-
- if (min_distance_squared < distance_clip_squared / sc->zoom) {
- if (corner_r != NULL) {
- *corner_r = min_corner;
- }
- return min_plane_track;
- }
-
- return NULL;
+ const float distance_clip_squared = 12.0f * 12.0f;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ int width, height;
+ float co[2];
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ ED_space_clip_get_size(sc, &width, &height);
+ if (width == 0 || height == 0) {
+ return NULL;
+ }
+
+ ED_clip_mouse_pos(sc, ar, event->mval, co);
+
+ float min_distance_squared = FLT_MAX;
+ int min_corner = -1;
+ MovieTrackingPlaneTrack *min_plane_track = NULL;
+ for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first; plane_track != NULL;
+ plane_track = plane_track->next) {
+ if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+ for (int i = 0; i < 4; i++) {
+ float distance_squared = mouse_to_plane_slide_zone_distance_squared(
+ co, plane_marker->corners[i], width, height);
+
+ if (distance_squared < min_distance_squared) {
+ min_distance_squared = distance_squared;
+ min_corner = i;
+ min_plane_track = plane_track;
+ }
+ }
+ }
+ }
+
+ if (min_distance_squared < distance_clip_squared / sc->zoom) {
+ if (corner_r != NULL) {
+ *corner_r = min_corner;
+ }
+ return min_plane_track;
+ }
+
+ return NULL;
}
static void *slide_plane_marker_customdata(bContext *C, const wmEvent *event)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
- MovieTrackingPlaneTrack *plane_track;
- int width, height;
- float co[2];
- SlidePlaneMarkerData *customdata = NULL;
- int framenr = ED_space_clip_get_clip_frame_number(sc);
- int corner;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
+ MovieTrackingPlaneTrack *plane_track;
+ int width, height;
+ float co[2];
+ SlidePlaneMarkerData *customdata = NULL;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+ int corner;
- ED_space_clip_get_size(sc, &width, &height);
- if (width == 0 || height == 0) {
- return NULL;
- }
+ ED_space_clip_get_size(sc, &width, &height);
+ if (width == 0 || height == 0) {
+ return NULL;
+ }
- ED_clip_mouse_pos(sc, ar, event->mval, co);
+ ED_clip_mouse_pos(sc, ar, event->mval, co);
- plane_track = tracking_plane_marker_check_slide(C, event, &corner);
- if (plane_track) {
- MovieTrackingPlaneMarker *plane_marker;
+ plane_track = tracking_plane_marker_check_slide(C, event, &corner);
+ if (plane_track) {
+ MovieTrackingPlaneMarker *plane_marker;
- customdata = MEM_callocN(sizeof(SlidePlaneMarkerData), "slide plane marker data");
+ customdata = MEM_callocN(sizeof(SlidePlaneMarkerData), "slide plane marker data");
- customdata->event_type = event->type;
+ customdata->event_type = event->type;
- plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr);
+ plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr);
- customdata->plane_track = plane_track;
- customdata->plane_marker = plane_marker;
- customdata->width = width;
- customdata->height = height;
+ customdata->plane_track = plane_track;
+ customdata->plane_marker = plane_marker;
+ customdata->width = width;
+ customdata->height = height;
- customdata->previous_mval[0] = event->mval[0];
- customdata->previous_mval[1] = event->mval[1];
+ customdata->previous_mval[0] = event->mval[0];
+ customdata->previous_mval[1] = event->mval[1];
- customdata->corner_index = corner;
- customdata->corner = plane_marker->corners[corner];
+ customdata->corner_index = corner;
+ customdata->corner = plane_marker->corners[corner];
- copy_v2_v2(customdata->previous_corner, customdata->corner);
- copy_v2_v2(customdata->old_corner, customdata->corner);
- }
+ copy_v2_v2(customdata->previous_corner, customdata->corner);
+ copy_v2_v2(customdata->old_corner, customdata->corner);
+ }
- return customdata;
+ return customdata;
}
-static int slide_plane_marker_invoke(bContext *C,
- wmOperator *op,
- const wmEvent *event)
+static int slide_plane_marker_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- SlidePlaneMarkerData *slidedata = slide_plane_marker_customdata(C, event);
+ SlidePlaneMarkerData *slidedata = slide_plane_marker_customdata(C, event);
- if (slidedata) {
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
+ if (slidedata) {
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
- tracking->act_plane_track = slidedata->plane_track;
- tracking->act_track = NULL;
+ tracking->act_plane_track = slidedata->plane_track;
+ tracking->act_track = NULL;
- op->customdata = slidedata;
+ op->customdata = slidedata;
- clip_tracking_hide_cursor(C);
- WM_event_add_modal_handler(C, op);
+ clip_tracking_hide_cursor(C);
+ WM_event_add_modal_handler(C, op);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
- return OPERATOR_RUNNING_MODAL;
- }
+ return OPERATOR_RUNNING_MODAL;
+ }
- return OPERATOR_PASS_THROUGH;
+ return OPERATOR_PASS_THROUGH;
}
static void cancel_mouse_slide_plane_marker(SlidePlaneMarkerData *data)
{
- copy_v2_v2(data->corner, data->old_corner);
+ copy_v2_v2(data->corner, data->old_corner);
}
static void free_slide_plane_marker_data(SlidePlaneMarkerData *data)
{
- MEM_freeN(data);
+ MEM_freeN(data);
}
-static void slide_plane_marker_update_homographies(SpaceClip *sc,
- SlidePlaneMarkerData *data)
+static void slide_plane_marker_update_homographies(SpaceClip *sc, SlidePlaneMarkerData *data)
{
- int framenr = ED_space_clip_get_clip_frame_number(sc);
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
- BKE_tracking_track_plane_from_existing_motion(data->plane_track, framenr);
+ BKE_tracking_track_plane_from_existing_motion(data->plane_track, framenr);
}
-static int slide_plane_marker_modal(bContext *C,
- wmOperator *op,
- const wmEvent *event)
+static int slide_plane_marker_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- SlidePlaneMarkerData *data = (SlidePlaneMarkerData *) op->customdata;
- float dx, dy, mdelta[2];
- int next_corner_index, prev_corner_index, diag_corner_index;
- const float *next_corner, *prev_corner, *diag_corner;
- 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)) {
- data->accurate = event->val == KM_PRESS;
- }
- ATTR_FALLTHROUGH;
- case MOUSEMOVE:
- mdelta[0] = event->mval[0] - data->previous_mval[0];
- mdelta[1] = event->mval[1] - data->previous_mval[1];
-
- dx = mdelta[0] / data->width / sc->zoom;
- dy = mdelta[1] / data->height / sc->zoom;
-
- if (data->accurate) {
- dx /= 5.0f;
- dy /= 5.0f;
- }
-
- data->corner[0] = data->previous_corner[0] + dx;
- data->corner[1] = data->previous_corner[1] + dy;
-
-
- /*
- prev_edge
- (Corner 3, current) <----------------------- (Corner 2, previous)
- | ^
- | |
- | |
- | |
- next_edge | | next_diag_edge
- | |
- | |
- | |
- v |
- (Corner 0, next) -----------------------> (Corner 1, diagonal)
- prev_diag_edge
- */
-
- next_corner_index = (data->corner_index + 1) % 4;
- prev_corner_index = (data->corner_index + 3) % 4;
- diag_corner_index = (data->corner_index + 2) % 4;
-
- next_corner = data->plane_marker->corners[next_corner_index];
- prev_corner = data->plane_marker->corners[prev_corner_index];
- diag_corner = data->plane_marker->corners[diag_corner_index];
-
- sub_v2_v2v2(next_edge, next_corner, data->corner);
- sub_v2_v2v2(prev_edge, data->corner, prev_corner);
- sub_v2_v2v2(next_diag_edge, prev_corner, diag_corner);
- sub_v2_v2v2(prev_diag_edge, diag_corner, next_corner);
-
- if (cross_v2v2(prev_edge, next_edge) < 0.0f) {
- closest_to_line_v2(data->corner,
- data->corner,
- prev_corner,
- next_corner);
- }
-
- if (cross_v2v2(next_diag_edge, prev_edge) < 0.0f) {
- closest_to_line_v2(data->corner,
- data->corner,
- prev_corner,
- diag_corner);
- }
-
- if (cross_v2v2(next_edge, prev_diag_edge) < 0.0f) {
- closest_to_line_v2(data->corner,
- data->corner,
- next_corner,
- diag_corner);
- }
-
- data->previous_mval[0] = event->mval[0];
- data->previous_mval[1] = event->mval[1];
- copy_v2_v2(data->previous_corner, data->corner);
-
- DEG_id_tag_update(&sc->clip->id, 0);
-
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
-
- break;
-
- case LEFTMOUSE:
- case RIGHTMOUSE:
- if (event->type == data->event_type && event->val == KM_RELEASE) {
- /* Marker is now keyframed. */
- data->plane_marker->flag &= ~PLANE_MARKER_TRACKED;
-
- slide_plane_marker_update_homographies(sc, data);
-
- free_slide_plane_marker_data(op->customdata);
-
- clip_tracking_show_cursor(C);
-
- DEG_id_tag_update(&sc->clip->id, 0);
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ SlidePlaneMarkerData *data = (SlidePlaneMarkerData *)op->customdata;
+ float dx, dy, mdelta[2];
+ int next_corner_index, prev_corner_index, diag_corner_index;
+ const float *next_corner, *prev_corner, *diag_corner;
+ 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)) {
+ data->accurate = event->val == KM_PRESS;
+ }
+ ATTR_FALLTHROUGH;
+ case MOUSEMOVE:
+ mdelta[0] = event->mval[0] - data->previous_mval[0];
+ mdelta[1] = event->mval[1] - data->previous_mval[1];
+
+ dx = mdelta[0] / data->width / sc->zoom;
+ dy = mdelta[1] / data->height / sc->zoom;
+
+ if (data->accurate) {
+ dx /= 5.0f;
+ dy /= 5.0f;
+ }
+
+ data->corner[0] = data->previous_corner[0] + dx;
+ data->corner[1] = data->previous_corner[1] + dy;
+
+ /*
+ prev_edge
+ (Corner 3, current) <----------------------- (Corner 2, previous)
+ | ^
+ | |
+ | |
+ | |
+ next_edge | | next_diag_edge
+ | |
+ | |
+ | |
+ v |
+ (Corner 0, next) -----------------------> (Corner 1, diagonal)
+ prev_diag_edge
+ */
+
+ next_corner_index = (data->corner_index + 1) % 4;
+ prev_corner_index = (data->corner_index + 3) % 4;
+ diag_corner_index = (data->corner_index + 2) % 4;
+
+ next_corner = data->plane_marker->corners[next_corner_index];
+ prev_corner = data->plane_marker->corners[prev_corner_index];
+ diag_corner = data->plane_marker->corners[diag_corner_index];
+
+ sub_v2_v2v2(next_edge, next_corner, data->corner);
+ sub_v2_v2v2(prev_edge, data->corner, prev_corner);
+ sub_v2_v2v2(next_diag_edge, prev_corner, diag_corner);
+ sub_v2_v2v2(prev_diag_edge, diag_corner, next_corner);
+
+ if (cross_v2v2(prev_edge, next_edge) < 0.0f) {
+ closest_to_line_v2(data->corner, data->corner, prev_corner, next_corner);
+ }
+
+ if (cross_v2v2(next_diag_edge, prev_edge) < 0.0f) {
+ closest_to_line_v2(data->corner, data->corner, prev_corner, diag_corner);
+ }
+
+ if (cross_v2v2(next_edge, prev_diag_edge) < 0.0f) {
+ closest_to_line_v2(data->corner, data->corner, next_corner, diag_corner);
+ }
+
+ data->previous_mval[0] = event->mval[0];
+ data->previous_mval[1] = event->mval[1];
+ copy_v2_v2(data->previous_corner, data->corner);
+
+ DEG_id_tag_update(&sc->clip->id, 0);
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
+
+ break;
+
+ case LEFTMOUSE:
+ case RIGHTMOUSE:
+ if (event->type == data->event_type && event->val == KM_RELEASE) {
+ /* Marker is now keyframed. */
+ data->plane_marker->flag &= ~PLANE_MARKER_TRACKED;
+
+ slide_plane_marker_update_homographies(sc, data);
+
+ free_slide_plane_marker_data(op->customdata);
+
+ clip_tracking_show_cursor(C);
+
+ DEG_id_tag_update(&sc->clip->id, 0);
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+
+ return OPERATOR_FINISHED;
+ }
+
+ break;
- return OPERATOR_FINISHED;
- }
-
- break;
+ case ESCKEY:
+ cancel_mouse_slide_plane_marker(op->customdata);
- case ESCKEY:
- cancel_mouse_slide_plane_marker(op->customdata);
+ free_slide_plane_marker_data(op->customdata);
- free_slide_plane_marker_data(op->customdata);
+ clip_tracking_show_cursor(C);
- clip_tracking_show_cursor(C);
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+ return OPERATOR_CANCELLED;
+ }
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void CLIP_OT_slide_plane_marker(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Slide Plane Marker";
- ot->description = "Slide plane marker areas";
- ot->idname = "CLIP_OT_slide_plane_marker";
-
- /* api callbacks */
- ot->poll = ED_space_clip_tracking_poll;
- ot->invoke = slide_plane_marker_invoke;
- ot->modal = slide_plane_marker_modal;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
+ /* identifiers */
+ ot->name = "Slide Plane Marker";
+ ot->description = "Slide plane marker areas";
+ ot->idname = "CLIP_OT_slide_plane_marker";
+
+ /* api callbacks */
+ ot->poll = ED_space_clip_tracking_poll;
+ ot->invoke = slide_plane_marker_invoke;
+ ot->modal = slide_plane_marker_modal;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
}
diff --git a/source/blender/editors/space_clip/tracking_ops_solve.c b/source/blender/editors/space_clip/tracking_ops_solve.c
index 03e03f94a66..ca57b3ea57f 100644
--- a/source/blender/editors/space_clip/tracking_ops_solve.c
+++ b/source/blender/editors/space_clip/tracking_ops_solve.c
@@ -24,7 +24,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_camera_types.h"
-#include "DNA_object_types.h" /* SELECT */
+#include "DNA_object_types.h" /* SELECT */
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -45,300 +45,270 @@
#include "ED_clip.h"
-
#include "clip_intern.h"
/********************** solve camera operator *********************/
typedef struct {
- Scene *scene;
- MovieClip *clip;
- MovieClipUser user;
+ Scene *scene;
+ MovieClip *clip;
+ MovieClipUser user;
- ReportList *reports;
+ ReportList *reports;
- char stats_message[256];
+ char stats_message[256];
- struct MovieReconstructContext *context;
+ struct MovieReconstructContext *context;
} SolveCameraJob;
-static bool solve_camera_initjob(bContext *C,
- SolveCameraJob *scj,
- wmOperator *op,
- char *error_msg,
- int max_error)
+static bool solve_camera_initjob(
+ bContext *C, SolveCameraJob *scj, wmOperator *op, char *error_msg, int max_error)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- Scene *scene = CTX_data_scene(C);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
- int width, height;
-
- if (!BKE_tracking_reconstruction_check(tracking,
- object,
- error_msg,
- max_error))
- {
- return false;
- }
-
- /* Could fail if footage uses images with different sizes. */
- BKE_movieclip_get_size(clip, &sc->user, &width, &height);
-
- scj->clip = clip;
- scj->scene = scene;
- scj->reports = op->reports;
- scj->user = sc->user;
-
- scj->context = BKE_tracking_reconstruction_context_new(clip,
- object,
- object->keyframe1,
- object->keyframe2,
- width,
- height);
-
- tracking->stats = MEM_callocN(sizeof(MovieTrackingStats), "solve camera stats");
-
- return true;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ Scene *scene = CTX_data_scene(C);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
+ int width, height;
+
+ if (!BKE_tracking_reconstruction_check(tracking, object, error_msg, max_error)) {
+ return false;
+ }
+
+ /* Could fail if footage uses images with different sizes. */
+ BKE_movieclip_get_size(clip, &sc->user, &width, &height);
+
+ scj->clip = clip;
+ scj->scene = scene;
+ scj->reports = op->reports;
+ scj->user = sc->user;
+
+ scj->context = BKE_tracking_reconstruction_context_new(
+ clip, object, object->keyframe1, object->keyframe2, width, height);
+
+ tracking->stats = MEM_callocN(sizeof(MovieTrackingStats), "solve camera stats");
+
+ return true;
}
static void solve_camera_updatejob(void *scv)
{
- SolveCameraJob *scj = (SolveCameraJob *)scv;
- MovieTracking *tracking = &scj->clip->tracking;
+ SolveCameraJob *scj = (SolveCameraJob *)scv;
+ MovieTracking *tracking = &scj->clip->tracking;
- BLI_strncpy(tracking->stats->message,
- scj->stats_message,
- sizeof(tracking->stats->message));
+ BLI_strncpy(tracking->stats->message, scj->stats_message, sizeof(tracking->stats->message));
}
static void solve_camera_startjob(void *scv, short *stop, short *do_update, float *progress)
{
- SolveCameraJob *scj = (SolveCameraJob *)scv;
- BKE_tracking_reconstruction_solve(scj->context,
- stop,
- do_update,
- progress,
- scj->stats_message,
- sizeof(scj->stats_message));
+ SolveCameraJob *scj = (SolveCameraJob *)scv;
+ BKE_tracking_reconstruction_solve(
+ scj->context, stop, do_update, progress, scj->stats_message, sizeof(scj->stats_message));
}
static void solve_camera_freejob(void *scv)
{
- SolveCameraJob *scj = (SolveCameraJob *)scv;
- MovieTracking *tracking = &scj->clip->tracking;
- Scene *scene = scj->scene;
- MovieClip *clip = scj->clip;
- int solved;
-
- if (!scj->context) {
- /* job weren't fully initialized due to some error */
- MEM_freeN(scj);
- return;
- }
-
- solved = BKE_tracking_reconstruction_finish(scj->context, tracking);
- if (!solved) {
- BKE_report(scj->reports,
- RPT_WARNING,
- "Some data failed to reconstruct (see console for details)");
- }
- else {
- BKE_reportf(scj->reports,
- RPT_INFO,
- "Average re-projection error: %.3f",
- tracking->reconstruction.error);
- }
-
- /* Set currently solved clip as active for scene. */
- if (scene->clip != NULL) {
- id_us_min(&clip->id);
- }
- scene->clip = clip;
- id_us_plus(&clip->id);
-
- /* Set blender camera focal length so result would look fine there. */
- if (scene->camera != NULL &&
- scene->camera->data &&
- GS(((ID *) scene->camera->data)->name) == ID_CA)
- {
- Camera *camera = (Camera *)scene->camera->data;
- int width, height;
- BKE_movieclip_get_size(clip, &scj->user, &width, &height);
- BKE_tracking_camera_to_blender(tracking, scene, camera, width, height);
- WM_main_add_notifier(NC_OBJECT, camera);
- }
-
- MEM_freeN(tracking->stats);
- tracking->stats = NULL;
-
- DEG_id_tag_update(&clip->id, 0);
-
- WM_main_add_notifier(NC_MOVIECLIP | NA_EVALUATED, clip);
- WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, NULL);
-
- /* Update active clip displayed in scene buttons. */
- WM_main_add_notifier(NC_SCENE, scene);
-
- BKE_tracking_reconstruction_context_free(scj->context);
- MEM_freeN(scj);
+ SolveCameraJob *scj = (SolveCameraJob *)scv;
+ MovieTracking *tracking = &scj->clip->tracking;
+ Scene *scene = scj->scene;
+ MovieClip *clip = scj->clip;
+ int solved;
+
+ if (!scj->context) {
+ /* job weren't fully initialized due to some error */
+ MEM_freeN(scj);
+ return;
+ }
+
+ solved = BKE_tracking_reconstruction_finish(scj->context, tracking);
+ if (!solved) {
+ BKE_report(
+ scj->reports, RPT_WARNING, "Some data failed to reconstruct (see console for details)");
+ }
+ else {
+ BKE_reportf(scj->reports,
+ RPT_INFO,
+ "Average re-projection error: %.3f",
+ tracking->reconstruction.error);
+ }
+
+ /* Set currently solved clip as active for scene. */
+ if (scene->clip != NULL) {
+ id_us_min(&clip->id);
+ }
+ scene->clip = clip;
+ id_us_plus(&clip->id);
+
+ /* Set blender camera focal length so result would look fine there. */
+ if (scene->camera != NULL && scene->camera->data &&
+ GS(((ID *)scene->camera->data)->name) == ID_CA) {
+ Camera *camera = (Camera *)scene->camera->data;
+ int width, height;
+ BKE_movieclip_get_size(clip, &scj->user, &width, &height);
+ BKE_tracking_camera_to_blender(tracking, scene, camera, width, height);
+ WM_main_add_notifier(NC_OBJECT, camera);
+ }
+
+ MEM_freeN(tracking->stats);
+ tracking->stats = NULL;
+
+ DEG_id_tag_update(&clip->id, 0);
+
+ WM_main_add_notifier(NC_MOVIECLIP | NA_EVALUATED, clip);
+ WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, NULL);
+
+ /* Update active clip displayed in scene buttons. */
+ WM_main_add_notifier(NC_SCENE, scene);
+
+ BKE_tracking_reconstruction_context_free(scj->context);
+ MEM_freeN(scj);
}
static int solve_camera_exec(bContext *C, wmOperator *op)
{
- SolveCameraJob *scj;
- char error_msg[256] = "\0";
- scj = MEM_callocN(sizeof(SolveCameraJob), "SolveCameraJob data");
- if (!solve_camera_initjob(C, scj, op, error_msg, sizeof(error_msg))) {
- if (error_msg[0]) {
- BKE_report(op->reports, RPT_ERROR, error_msg);
- }
- solve_camera_freejob(scj);
- return OPERATOR_CANCELLED;
- }
- solve_camera_startjob(scj, NULL, NULL, NULL);
- solve_camera_freejob(scj);
- return OPERATOR_FINISHED;
+ SolveCameraJob *scj;
+ char error_msg[256] = "\0";
+ scj = MEM_callocN(sizeof(SolveCameraJob), "SolveCameraJob data");
+ if (!solve_camera_initjob(C, scj, op, error_msg, sizeof(error_msg))) {
+ if (error_msg[0]) {
+ BKE_report(op->reports, RPT_ERROR, error_msg);
+ }
+ solve_camera_freejob(scj);
+ return OPERATOR_CANCELLED;
+ }
+ solve_camera_startjob(scj, NULL, NULL, NULL);
+ solve_camera_freejob(scj);
+ return OPERATOR_FINISHED;
}
-static int solve_camera_invoke(bContext *C,
- wmOperator *op,
- const wmEvent *UNUSED(event))
+static int solve_camera_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- SolveCameraJob *scj;
- ScrArea *sa = CTX_wm_area(C);
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingReconstruction *reconstruction =
- BKE_tracking_get_active_reconstruction(tracking);
- wmJob *wm_job;
- char error_msg[256] = "\0";
-
- if (WM_jobs_test(CTX_wm_manager(C), sa, WM_JOB_TYPE_ANY)) {
- /* only one solve is allowed at a time */
- return OPERATOR_CANCELLED;
- }
-
- scj = MEM_callocN(sizeof(SolveCameraJob), "SolveCameraJob data");
- if (!solve_camera_initjob(C, scj, op, error_msg, sizeof(error_msg))) {
- if (error_msg[0]) {
- BKE_report(op->reports, RPT_ERROR, error_msg);
- }
- solve_camera_freejob(scj);
- return OPERATOR_CANCELLED;
- }
-
- BLI_strncpy(tracking->stats->message,
- "Solving camera | Preparing solve",
- sizeof(tracking->stats->message));
-
- /* Hide reconstruction statistics from previous solve. */
- reconstruction->flag &= ~TRACKING_RECONSTRUCTED;
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
-
- /* Setup job. */
- wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Solve Camera",
- WM_JOB_PROGRESS, WM_JOB_TYPE_CLIP_SOLVE_CAMERA);
- WM_jobs_customdata_set(wm_job, scj, solve_camera_freejob);
- WM_jobs_timer(wm_job, 0.1, NC_MOVIECLIP | NA_EVALUATED, 0);
- WM_jobs_callbacks(wm_job,
- solve_camera_startjob,
- NULL,
- solve_camera_updatejob,
- NULL);
-
- G.is_break = false;
-
- WM_jobs_start(CTX_wm_manager(C), wm_job);
- WM_cursor_wait(0);
-
- /* add modal handler for ESC */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
+ SolveCameraJob *scj;
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking);
+ wmJob *wm_job;
+ char error_msg[256] = "\0";
+
+ if (WM_jobs_test(CTX_wm_manager(C), sa, WM_JOB_TYPE_ANY)) {
+ /* only one solve is allowed at a time */
+ return OPERATOR_CANCELLED;
+ }
+
+ scj = MEM_callocN(sizeof(SolveCameraJob), "SolveCameraJob data");
+ if (!solve_camera_initjob(C, scj, op, error_msg, sizeof(error_msg))) {
+ if (error_msg[0]) {
+ BKE_report(op->reports, RPT_ERROR, error_msg);
+ }
+ solve_camera_freejob(scj);
+ return OPERATOR_CANCELLED;
+ }
+
+ BLI_strncpy(tracking->stats->message,
+ "Solving camera | Preparing solve",
+ sizeof(tracking->stats->message));
+
+ /* Hide reconstruction statistics from previous solve. */
+ reconstruction->flag &= ~TRACKING_RECONSTRUCTED;
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
+
+ /* Setup job. */
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ sa,
+ "Solve Camera",
+ WM_JOB_PROGRESS,
+ WM_JOB_TYPE_CLIP_SOLVE_CAMERA);
+ WM_jobs_customdata_set(wm_job, scj, solve_camera_freejob);
+ WM_jobs_timer(wm_job, 0.1, NC_MOVIECLIP | NA_EVALUATED, 0);
+ WM_jobs_callbacks(wm_job, solve_camera_startjob, NULL, solve_camera_updatejob, NULL);
+
+ G.is_break = false;
+
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+ WM_cursor_wait(0);
+
+ /* add modal handler for ESC */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
}
-static int solve_camera_modal(bContext *C,
- wmOperator *UNUSED(op),
- const wmEvent *event)
+static int solve_camera_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- /* No running solver, remove handler and pass through. */
- if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_wm_area(C), WM_JOB_TYPE_ANY))
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ /* No running solver, remove handler and pass through. */
+ if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_wm_area(C), WM_JOB_TYPE_ANY))
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
- /* Running solver. */
- switch (event->type) {
- case ESCKEY:
- return OPERATOR_RUNNING_MODAL;
- }
+ /* Running solver. */
+ switch (event->type) {
+ case ESCKEY:
+ return OPERATOR_RUNNING_MODAL;
+ }
- return OPERATOR_PASS_THROUGH;
+ return OPERATOR_PASS_THROUGH;
}
void CLIP_OT_solve_camera(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Solve Camera";
- ot->description = "Solve camera motion from tracks";
- ot->idname = "CLIP_OT_solve_camera";
-
- /* api callbacks */
- ot->exec = solve_camera_exec;
- ot->invoke = solve_camera_invoke;
- ot->modal = solve_camera_modal;
- ot->poll = ED_space_clip_tracking_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Solve Camera";
+ ot->description = "Solve camera motion from tracks";
+ ot->idname = "CLIP_OT_solve_camera";
+
+ /* api callbacks */
+ ot->exec = solve_camera_exec;
+ ot->invoke = solve_camera_invoke;
+ ot->modal = solve_camera_modal;
+ ot->poll = ED_space_clip_tracking_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** clear solution operator *********************/
static int clear_solution_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
- MovieTrackingReconstruction *reconstruction =
- BKE_tracking_get_active_reconstruction(tracking);
-
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- track->flag &= ~TRACK_HAS_BUNDLE;
- }
-
- if (reconstruction->cameras != NULL) {
- MEM_freeN(reconstruction->cameras);
- reconstruction->cameras = NULL;
- }
-
- reconstruction->camnr = 0;
- reconstruction->flag &= ~TRACKING_RECONSTRUCTED;
-
- DEG_id_tag_update(&clip->id, 0);
-
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+ MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking);
+
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ track->flag &= ~TRACK_HAS_BUNDLE;
+ }
+
+ if (reconstruction->cameras != NULL) {
+ MEM_freeN(reconstruction->cameras);
+ reconstruction->cameras = NULL;
+ }
+
+ reconstruction->camnr = 0;
+ reconstruction->flag &= ~TRACKING_RECONSTRUCTED;
+
+ DEG_id_tag_update(&clip->id, 0);
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_clear_solution(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Solution";
- ot->description = "Clear all calculated data";
- ot->idname = "CLIP_OT_clear_solution";
+ /* identifiers */
+ ot->name = "Clear Solution";
+ ot->description = "Clear all calculated data";
+ ot->idname = "CLIP_OT_clear_solution";
- /* api callbacks */
- ot->exec = clear_solution_exec;
- ot->poll = ED_space_clip_tracking_poll;
+ /* api callbacks */
+ ot->exec = clear_solution_exec;
+ ot->poll = ED_space_clip_tracking_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/space_clip/tracking_ops_stabilize.c b/source/blender/editors/space_clip/tracking_ops_stabilize.c
index ab7585cbf57..5e43b7c7ec6 100644
--- a/source/blender/editors/space_clip/tracking_ops_stabilize.c
+++ b/source/blender/editors/space_clip/tracking_ops_stabilize.c
@@ -44,296 +44,273 @@
static bool stabilize_2d_poll(bContext *C)
{
- if (ED_space_clip_tracking_poll(C)) {
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTrackingObject *tracking_object =
- BKE_tracking_object_get_active(&clip->tracking);
- return (tracking_object->flag & TRACKING_OBJECT_CAMERA) != 0;
- }
- return 0;
+ if (ED_space_clip_tracking_poll(C)) {
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
+ return (tracking_object->flag & TRACKING_OBJECT_CAMERA) != 0;
+ }
+ return 0;
}
static int stabilize_2d_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- MovieTrackingStabilization *stab = &tracking->stabilization;
-
- bool update = false;
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- if (TRACK_VIEW_SELECTED(sc, track) &&
- (track->flag & TRACK_USE_2D_STAB) == 0)
- {
- track->flag |= TRACK_USE_2D_STAB;
- stab->tot_track++;
- update = true;
- }
- }
-
- if (update) {
- DEG_id_tag_update(&clip->id, 0);
- WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
- }
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ MovieTrackingStabilization *stab = &tracking->stabilization;
+
+ bool update = false;
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_USE_2D_STAB) == 0) {
+ track->flag |= TRACK_USE_2D_STAB;
+ stab->tot_track++;
+ update = true;
+ }
+ }
+
+ if (update) {
+ DEG_id_tag_update(&clip->id, 0);
+ WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
+ }
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_stabilize_2d_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Stabilization Tracks";
- ot->description = "Add selected tracks to 2D translation stabilization";
- ot->idname = "CLIP_OT_stabilize_2d_add";
+ /* identifiers */
+ ot->name = "Add Stabilization Tracks";
+ ot->description = "Add selected tracks to 2D translation stabilization";
+ ot->idname = "CLIP_OT_stabilize_2d_add";
- /* api callbacks */
- ot->exec = stabilize_2d_add_exec;
- ot->poll = stabilize_2d_poll;
+ /* api callbacks */
+ ot->exec = stabilize_2d_add_exec;
+ ot->poll = stabilize_2d_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************* remove 2d stabilization tracks operator ******************/
static int stabilize_2d_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingStabilization *stab = &tracking->stabilization;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- int a = 0;
- bool update = false;
-
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- if (track->flag & TRACK_USE_2D_STAB) {
- if (a == stab->act_track) {
- track->flag &= ~TRACK_USE_2D_STAB;
- stab->act_track--;
- stab->tot_track--;
- if (stab->act_track < 0) {
- stab->act_track = 0;
- }
- update = true;
- break;
- }
- a++;
- }
- }
-
- if (update) {
- DEG_id_tag_update(&clip->id, 0);
- WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
- }
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingStabilization *stab = &tracking->stabilization;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ int a = 0;
+ bool update = false;
+
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ if (track->flag & TRACK_USE_2D_STAB) {
+ if (a == stab->act_track) {
+ track->flag &= ~TRACK_USE_2D_STAB;
+ stab->act_track--;
+ stab->tot_track--;
+ if (stab->act_track < 0) {
+ stab->act_track = 0;
+ }
+ update = true;
+ break;
+ }
+ a++;
+ }
+ }
+
+ if (update) {
+ DEG_id_tag_update(&clip->id, 0);
+ WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
+ }
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_stabilize_2d_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Stabilization Track";
- ot->description = "Remove selected track from translation stabilization";
- ot->idname = "CLIP_OT_stabilize_2d_remove";
+ /* identifiers */
+ ot->name = "Remove Stabilization Track";
+ ot->description = "Remove selected track from translation stabilization";
+ ot->idname = "CLIP_OT_stabilize_2d_remove";
- /* api callbacks */
- ot->exec = stabilize_2d_remove_exec;
- ot->poll = stabilize_2d_poll;
+ /* api callbacks */
+ ot->exec = stabilize_2d_remove_exec;
+ ot->poll = stabilize_2d_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************* select 2d stabilization tracks operator ******************/
static int stabilize_2d_select_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- bool update = false;
-
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- if (track->flag & TRACK_USE_2D_STAB) {
- BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT);
- update = true;
- }
- }
-
- if (update) {
- WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, clip);
- }
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ bool update = false;
+
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ if (track->flag & TRACK_USE_2D_STAB) {
+ BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT);
+ update = true;
+ }
+ }
+
+ if (update) {
+ WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, clip);
+ }
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_stabilize_2d_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Stabilization Tracks";
- ot->description = "Select tracks which are used for translation stabilization";
- ot->idname = "CLIP_OT_stabilize_2d_select";
+ /* identifiers */
+ ot->name = "Select Stabilization Tracks";
+ ot->description = "Select tracks which are used for translation stabilization";
+ ot->idname = "CLIP_OT_stabilize_2d_select";
- /* api callbacks */
- ot->exec = stabilize_2d_select_exec;
- ot->poll = stabilize_2d_poll;
+ /* api callbacks */
+ ot->exec = stabilize_2d_select_exec;
+ ot->poll = stabilize_2d_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** add 2d stabilization tracks for rotation operator ****************/
static int stabilize_2d_rotation_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- MovieTrackingStabilization *stab = &tracking->stabilization;
-
- bool update = false;
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- if (TRACK_VIEW_SELECTED(sc, track) &&
- (track->flag & TRACK_USE_2D_STAB_ROT) == 0)
- {
- track->flag |= TRACK_USE_2D_STAB_ROT;
- stab->tot_rot_track++;
- update = true;
- }
- }
-
- if (update) {
- DEG_id_tag_update(&clip->id, 0);
- WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
- }
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ MovieTrackingStabilization *stab = &tracking->stabilization;
+
+ bool update = false;
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_USE_2D_STAB_ROT) == 0) {
+ track->flag |= TRACK_USE_2D_STAB_ROT;
+ stab->tot_rot_track++;
+ update = true;
+ }
+ }
+
+ if (update) {
+ DEG_id_tag_update(&clip->id, 0);
+ WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
+ }
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_stabilize_2d_rotation_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Stabilization Rotation Tracks";
- ot->description = "Add selected tracks to 2D rotation stabilization";
- ot->idname = "CLIP_OT_stabilize_2d_rotation_add";
+ /* identifiers */
+ ot->name = "Add Stabilization Rotation Tracks";
+ ot->description = "Add selected tracks to 2D rotation stabilization";
+ ot->idname = "CLIP_OT_stabilize_2d_rotation_add";
- /* api callbacks */
- ot->exec = stabilize_2d_rotation_add_exec;
- ot->poll = stabilize_2d_poll;
+ /* api callbacks */
+ ot->exec = stabilize_2d_rotation_add_exec;
+ ot->poll = stabilize_2d_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** remove 2d stabilization tracks for rotation operator *************/
static int stabilize_2d_rotation_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingStabilization *stab = &tracking->stabilization;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- int a = 0;
- bool update = false;
-
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- if (track->flag & TRACK_USE_2D_STAB_ROT) {
- if (a == stab->act_rot_track) {
- track->flag &= ~TRACK_USE_2D_STAB_ROT;
- stab->act_rot_track--;
- stab->tot_rot_track--;
- if (stab->act_rot_track < 0) {
- stab->act_rot_track = 0;
- }
- update = true;
- break;
- }
- a++;
- }
- }
-
- if (update) {
- DEG_id_tag_update(&clip->id, 0);
- WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
- }
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingStabilization *stab = &tracking->stabilization;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ int a = 0;
+ bool update = false;
+
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ if (track->flag & TRACK_USE_2D_STAB_ROT) {
+ if (a == stab->act_rot_track) {
+ track->flag &= ~TRACK_USE_2D_STAB_ROT;
+ stab->act_rot_track--;
+ stab->tot_rot_track--;
+ if (stab->act_rot_track < 0) {
+ stab->act_rot_track = 0;
+ }
+ update = true;
+ break;
+ }
+ a++;
+ }
+ }
+
+ if (update) {
+ DEG_id_tag_update(&clip->id, 0);
+ WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
+ }
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_stabilize_2d_rotation_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Stabilization Rotation Track";
- ot->description = "Remove selected track from rotation stabilization";
- ot->idname = "CLIP_OT_stabilize_2d_rotation_remove";
+ /* identifiers */
+ ot->name = "Remove Stabilization Rotation Track";
+ ot->description = "Remove selected track from rotation stabilization";
+ ot->idname = "CLIP_OT_stabilize_2d_rotation_remove";
- /* api callbacks */
- ot->exec = stabilize_2d_rotation_remove_exec;
- ot->poll = stabilize_2d_poll;
+ /* api callbacks */
+ ot->exec = stabilize_2d_rotation_remove_exec;
+ ot->poll = stabilize_2d_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** select 2d stabilization rotation tracks operator *****************/
static int stabilize_2d_rotation_select_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- bool update = false;
-
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- if (track->flag & TRACK_USE_2D_STAB_ROT) {
- BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT);
- update = true;
- }
- }
-
- if (update) {
- WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, clip);
- }
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ bool update = false;
+
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ if (track->flag & TRACK_USE_2D_STAB_ROT) {
+ BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT);
+ update = true;
+ }
+ }
+
+ if (update) {
+ WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, clip);
+ }
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_stabilize_2d_rotation_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Stabilization Rotation Tracks";
- ot->description = "Select tracks which are used for rotation stabilization";
- ot->idname = "CLIP_OT_stabilize_2d_rotation_select";
+ /* identifiers */
+ ot->name = "Select Stabilization Rotation Tracks";
+ ot->description = "Select tracks which are used for rotation stabilization";
+ ot->idname = "CLIP_OT_stabilize_2d_rotation_select";
- /* api callbacks */
- ot->exec = stabilize_2d_rotation_select_exec;
- ot->poll = stabilize_2d_poll;
+ /* api callbacks */
+ ot->exec = stabilize_2d_rotation_select_exec;
+ ot->poll = stabilize_2d_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/space_clip/tracking_ops_track.c b/source/blender/editors/space_clip/tracking_ops_track.c
index 4c14049865b..d985e82fd1a 100644
--- a/source/blender/editors/space_clip/tracking_ops_track.c
+++ b/source/blender/editors/space_clip/tracking_ops_track.c
@@ -44,441 +44,410 @@
#include "PIL_time.h"
-#include "clip_intern.h" // own include
+#include "clip_intern.h" // own include
#include "tracking_ops_intern.h"
/********************** Track operator *********************/
typedef struct TrackMarkersJob {
- struct AutoTrackContext *context; /* Tracking context */
- int sfra, efra, lastfra; /* Start, end and recently tracked frames */
- int backwards; /* Backwards tracking flag */
- MovieClip *clip; /* Clip which is tracking */
- float delay; /* Delay in milliseconds to allow
- * tracking at fixed FPS */
-
- struct Main *main;
- struct Scene *scene;
- struct bScreen *screen;
+ struct AutoTrackContext *context; /* Tracking context */
+ int sfra, efra, lastfra; /* Start, end and recently tracked frames */
+ int backwards; /* Backwards tracking flag */
+ MovieClip *clip; /* Clip which is tracking */
+ float delay; /* Delay in milliseconds to allow
+ * tracking at fixed FPS */
+
+ struct Main *main;
+ struct Scene *scene;
+ struct bScreen *screen;
} TrackMarkersJob;
static bool track_markers_testbreak(void)
{
- return G.is_break;
+ return G.is_break;
}
-static int track_count_markers(SpaceClip *sc,
- MovieClip *clip,
- int framenr)
+static int track_count_markers(SpaceClip *sc, MovieClip *clip, int framenr)
{
- int tot = 0;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- bool selected = (sc != NULL) ? TRACK_VIEW_SELECTED(sc, track)
- : TRACK_SELECTED(track);
- if (selected && (track->flag & TRACK_LOCKED) == 0) {
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track,
- framenr);
- if (!marker || (marker->flag & MARKER_DISABLED) == 0) {
- tot++;
- }
- }
- }
- return tot;
+ int tot = 0;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ bool selected = (sc != NULL) ? TRACK_VIEW_SELECTED(sc, track) : TRACK_SELECTED(track);
+ if (selected && (track->flag & TRACK_LOCKED) == 0) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+ if (!marker || (marker->flag & MARKER_DISABLED) == 0) {
+ tot++;
+ }
+ }
+ }
+ 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 *frames_limit_r)
{
- ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
- int frames_limit = 0;
- if (sc != NULL) {
- clip_tracking_clear_invisible_track_selection(sc, clip);
- }
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- bool selected = (sc != NULL) ? TRACK_VIEW_SELECTED(sc, track)
- : TRACK_SELECTED(track);
- if (selected) {
- if ((track->flag & TRACK_HIDDEN) == 0 &&
- (track->flag & TRACK_LOCKED) == 0)
- {
- BKE_tracking_marker_ensure(track, framenr);
- if (track->frames_limit) {
- if (frames_limit == 0) {
- frames_limit = track->frames_limit;
- }
- else {
- frames_limit = min_ii(frames_limit,
- (int)track->frames_limit);
- }
- }
- }
- }
- }
- *frames_limit_r = frames_limit;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+ int frames_limit = 0;
+ if (sc != NULL) {
+ clip_tracking_clear_invisible_track_selection(sc, clip);
+ }
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ bool selected = (sc != NULL) ? TRACK_VIEW_SELECTED(sc, track) : TRACK_SELECTED(track);
+ if (selected) {
+ if ((track->flag & TRACK_HIDDEN) == 0 && (track->flag & TRACK_LOCKED) == 0) {
+ BKE_tracking_marker_ensure(track, framenr);
+ if (track->frames_limit) {
+ if (frames_limit == 0) {
+ frames_limit = track->frames_limit;
+ }
+ else {
+ frames_limit = min_ii(frames_limit, (int)track->frames_limit);
+ }
+ }
+ }
+ }
+ }
+ *frames_limit_r = frames_limit;
}
static bool track_markers_check_direction(int backwards, int curfra, int efra)
{
- if (backwards) {
- if (curfra < efra) {
- return false;
- }
- }
- else {
- if (curfra > efra) {
- return false;
- }
- }
-
- return true;
+ if (backwards) {
+ if (curfra < efra) {
+ return false;
+ }
+ }
+ else {
+ if (curfra > efra) {
+ return false;
+ }
+ }
+
+ return true;
}
-static int track_markers_initjob(bContext *C,
- TrackMarkersJob *tmj,
- bool backwards,
- bool sequence)
+static int track_markers_initjob(bContext *C, TrackMarkersJob *tmj, bool backwards, bool sequence)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- Scene *scene = CTX_data_scene(C);
- MovieTrackingSettings *settings = &clip->tracking.settings;
- int frames_limit;
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- track_init_markers(sc, clip, framenr, &frames_limit);
-
- tmj->sfra = framenr;
- tmj->clip = clip;
- tmj->backwards = backwards;
-
- if (sequence) {
- if (backwards) {
- tmj->efra = SFRA;
- }
- else {
- tmj->efra = EFRA;
- }
- tmj->efra = BKE_movieclip_remap_scene_to_clip_frame(clip, tmj->efra);
- }
- else {
- if (backwards) {
- tmj->efra = tmj->sfra - 1;
- }
- else {
- tmj->efra = tmj->sfra + 1;
- }
- }
-
- /* Limit frames to be tracked by user setting. */
- if (frames_limit) {
- if (backwards) {
- tmj->efra = MAX2(tmj->efra, tmj->sfra - frames_limit);
- }
- else {
- tmj->efra = MIN2(tmj->efra, tmj->sfra + frames_limit);
- }
- }
-
- if (settings->speed != TRACKING_SPEED_FASTEST) {
- tmj->delay = 1.0f / scene->r.frs_sec * 1000.0f;
-
- if (settings->speed == TRACKING_SPEED_HALF) {
- tmj->delay *= 2;
- }
- else if (settings->speed == TRACKING_SPEED_QUARTER) {
- tmj->delay *= 4;
- }
- else if (settings->speed == TRACKING_SPEED_DOUBLE) {
- tmj->delay /= 2;
- }
- }
-
- tmj->context = BKE_autotrack_context_new(clip, &sc->user, backwards, true);
-
- clip->tracking_context = tmj->context;
-
- tmj->lastfra = tmj->sfra;
-
- /* XXX: silly to store this, but this data is needed to update scene and
- * movie-clip numbers when tracking is finished. This introduces
- * better feedback for artists.
- * Maybe there's another way to solve this problem, but can't think
- * better way atm.
- * Anyway, this way isn't more unstable as animation rendering
- * animation which uses the same approach (except storing screen).
- */
- tmj->scene = scene;
- tmj->main = CTX_data_main(C);
- tmj->screen = CTX_wm_screen(C);
-
- return track_markers_check_direction(backwards, tmj->sfra, tmj->efra);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ Scene *scene = CTX_data_scene(C);
+ MovieTrackingSettings *settings = &clip->tracking.settings;
+ int frames_limit;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ track_init_markers(sc, clip, framenr, &frames_limit);
+
+ tmj->sfra = framenr;
+ tmj->clip = clip;
+ tmj->backwards = backwards;
+
+ if (sequence) {
+ if (backwards) {
+ tmj->efra = SFRA;
+ }
+ else {
+ tmj->efra = EFRA;
+ }
+ tmj->efra = BKE_movieclip_remap_scene_to_clip_frame(clip, tmj->efra);
+ }
+ else {
+ if (backwards) {
+ tmj->efra = tmj->sfra - 1;
+ }
+ else {
+ tmj->efra = tmj->sfra + 1;
+ }
+ }
+
+ /* Limit frames to be tracked by user setting. */
+ if (frames_limit) {
+ if (backwards) {
+ tmj->efra = MAX2(tmj->efra, tmj->sfra - frames_limit);
+ }
+ else {
+ tmj->efra = MIN2(tmj->efra, tmj->sfra + frames_limit);
+ }
+ }
+
+ if (settings->speed != TRACKING_SPEED_FASTEST) {
+ tmj->delay = 1.0f / scene->r.frs_sec * 1000.0f;
+
+ if (settings->speed == TRACKING_SPEED_HALF) {
+ tmj->delay *= 2;
+ }
+ else if (settings->speed == TRACKING_SPEED_QUARTER) {
+ tmj->delay *= 4;
+ }
+ else if (settings->speed == TRACKING_SPEED_DOUBLE) {
+ tmj->delay /= 2;
+ }
+ }
+
+ tmj->context = BKE_autotrack_context_new(clip, &sc->user, backwards, true);
+
+ clip->tracking_context = tmj->context;
+
+ tmj->lastfra = tmj->sfra;
+
+ /* XXX: silly to store this, but this data is needed to update scene and
+ * movie-clip numbers when tracking is finished. This introduces
+ * better feedback for artists.
+ * Maybe there's another way to solve this problem, but can't think
+ * better way atm.
+ * Anyway, this way isn't more unstable as animation rendering
+ * animation which uses the same approach (except storing screen).
+ */
+ tmj->scene = scene;
+ tmj->main = CTX_data_main(C);
+ tmj->screen = CTX_wm_screen(C);
+
+ return track_markers_check_direction(backwards, tmj->sfra, tmj->efra);
}
-static void track_markers_startjob(void *tmv,
- short *stop,
- short *do_update,
- float *progress)
+static void track_markers_startjob(void *tmv, short *stop, short *do_update, float *progress)
{
- TrackMarkersJob *tmj = (TrackMarkersJob *)tmv;
- int framenr = tmj->sfra;
-
- while (framenr != tmj->efra) {
- if (tmj->delay > 0) {
- /* Tracking should happen with fixed fps. Calculate time
- * using current timer value before tracking frame and after.
- *
- * Small (and maybe unneeded optimization): do not calculate
- * exec_time for "Fastest" tracking
- */
-
- double start_time = PIL_check_seconds_timer(), exec_time;
-
- if (!BKE_autotrack_context_step(tmj->context)) {
- break;
- }
-
- exec_time = PIL_check_seconds_timer() - start_time;
- if (tmj->delay > (float)exec_time) {
- PIL_sleep_ms(tmj->delay - (float)exec_time);
- }
- }
- else if (!BKE_autotrack_context_step(tmj->context)) {
- break;
- }
-
- *do_update = true;
- *progress = (float)(framenr - tmj->sfra) / (tmj->efra - tmj->sfra);
-
- if (tmj->backwards) {
- framenr--;
- }
- else {
- framenr++;
- }
-
- tmj->lastfra = framenr;
-
- if (*stop || track_markers_testbreak()) {
- break;
- }
- }
+ TrackMarkersJob *tmj = (TrackMarkersJob *)tmv;
+ int framenr = tmj->sfra;
+
+ while (framenr != tmj->efra) {
+ if (tmj->delay > 0) {
+ /* Tracking should happen with fixed fps. Calculate time
+ * using current timer value before tracking frame and after.
+ *
+ * Small (and maybe unneeded optimization): do not calculate
+ * exec_time for "Fastest" tracking
+ */
+
+ double start_time = PIL_check_seconds_timer(), exec_time;
+
+ if (!BKE_autotrack_context_step(tmj->context)) {
+ break;
+ }
+
+ exec_time = PIL_check_seconds_timer() - start_time;
+ if (tmj->delay > (float)exec_time) {
+ PIL_sleep_ms(tmj->delay - (float)exec_time);
+ }
+ }
+ else if (!BKE_autotrack_context_step(tmj->context)) {
+ break;
+ }
+
+ *do_update = true;
+ *progress = (float)(framenr - tmj->sfra) / (tmj->efra - tmj->sfra);
+
+ if (tmj->backwards) {
+ framenr--;
+ }
+ else {
+ framenr++;
+ }
+
+ tmj->lastfra = framenr;
+
+ if (*stop || track_markers_testbreak()) {
+ break;
+ }
+ }
}
static void track_markers_updatejob(void *tmv)
{
- TrackMarkersJob *tmj = (TrackMarkersJob *)tmv;
- BKE_autotrack_context_sync(tmj->context);
+ TrackMarkersJob *tmj = (TrackMarkersJob *)tmv;
+ BKE_autotrack_context_sync(tmj->context);
}
static void track_markers_endjob(void *tmv)
{
- TrackMarkersJob *tmj = (TrackMarkersJob *)tmv;
- wmWindowManager *wm = tmj->main->wm.first;
+ TrackMarkersJob *tmj = (TrackMarkersJob *)tmv;
+ wmWindowManager *wm = tmj->main->wm.first;
- tmj->clip->tracking_context = NULL;
- tmj->scene->r.cfra = BKE_movieclip_remap_clip_to_scene_frame(tmj->clip,
- tmj->lastfra);
- if (wm != NULL) {
- // XXX: ...
- // ED_update_for_newframe(tmj->main, tmj->scene);
- }
+ tmj->clip->tracking_context = NULL;
+ tmj->scene->r.cfra = BKE_movieclip_remap_clip_to_scene_frame(tmj->clip, tmj->lastfra);
+ if (wm != NULL) {
+ // XXX: ...
+ // ED_update_for_newframe(tmj->main, tmj->scene);
+ }
- BKE_autotrack_context_sync(tmj->context);
- BKE_autotrack_context_finish(tmj->context);
+ BKE_autotrack_context_sync(tmj->context);
+ BKE_autotrack_context_finish(tmj->context);
- WM_main_add_notifier(NC_SCENE | ND_FRAME, tmj->scene);
+ WM_main_add_notifier(NC_SCENE | ND_FRAME, tmj->scene);
}
static void track_markers_freejob(void *tmv)
{
- TrackMarkersJob *tmj = (TrackMarkersJob *)tmv;
- tmj->clip->tracking_context = NULL;
- BKE_autotrack_context_free(tmj->context);
- MEM_freeN(tmj);
+ TrackMarkersJob *tmj = (TrackMarkersJob *)tmv;
+ tmj->clip->tracking_context = NULL;
+ BKE_autotrack_context_free(tmj->context);
+ MEM_freeN(tmj);
}
static int track_markers(bContext *C, wmOperator *op, bool use_job)
{
- TrackMarkersJob *tmj;
- ScrArea *sa = CTX_wm_area(C);
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- wmJob *wm_job;
- bool backwards = RNA_boolean_get(op->ptr, "backwards");
- bool sequence = RNA_boolean_get(op->ptr, "sequence");
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- if (WM_jobs_test(CTX_wm_manager(C), sa, WM_JOB_TYPE_ANY)) {
- /* Only one tracking is allowed at a time. */
- return OPERATOR_CANCELLED;
- }
-
- if (clip->tracking_context) {
- return OPERATOR_CANCELLED;
- }
-
- if (track_count_markers(sc, clip, framenr) == 0) {
- return OPERATOR_CANCELLED;
- }
-
- tmj = MEM_callocN(sizeof(TrackMarkersJob), "TrackMarkersJob data");
- if (!track_markers_initjob(C, tmj, backwards, sequence)) {
- track_markers_freejob(tmj);
- return OPERATOR_CANCELLED;
- }
-
- /* Setup job. */
- if (use_job && sequence) {
- wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa,
- "Track Markers",
- WM_JOB_PROGRESS, WM_JOB_TYPE_CLIP_TRACK_MARKERS);
- WM_jobs_customdata_set(wm_job, tmj, track_markers_freejob);
-
- /* If there's delay set in tracking job, tracking should happen
- * with fixed FPS. To deal with editor refresh we have to synchronize
- * tracks from job and tracks in clip. Do this in timer callback
- * to prevent threading conflicts. */
- if (tmj->delay > 0) {
- WM_jobs_timer(wm_job,
- tmj->delay / 1000.0f, NC_MOVIECLIP | NA_EVALUATED, 0);
- }
- else {
- WM_jobs_timer(wm_job, 0.2, NC_MOVIECLIP | NA_EVALUATED, 0);
- }
-
- WM_jobs_callbacks(wm_job,
- track_markers_startjob,
- NULL,
- track_markers_updatejob,
- track_markers_endjob);
-
- G.is_break = false;
-
- WM_jobs_start(CTX_wm_manager(C), wm_job);
- WM_cursor_wait(0);
-
- /* Add modal handler for ESC. */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
- }
- else {
- short stop = 0, do_update = 0;
- float progress = 0.0f;
- track_markers_startjob(tmj, &stop, &do_update, &progress);
- track_markers_endjob(tmj);
- track_markers_freejob(tmj);
- return OPERATOR_FINISHED;
- }
+ TrackMarkersJob *tmj;
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ wmJob *wm_job;
+ bool backwards = RNA_boolean_get(op->ptr, "backwards");
+ bool sequence = RNA_boolean_get(op->ptr, "sequence");
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ if (WM_jobs_test(CTX_wm_manager(C), sa, WM_JOB_TYPE_ANY)) {
+ /* Only one tracking is allowed at a time. */
+ return OPERATOR_CANCELLED;
+ }
+
+ if (clip->tracking_context) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (track_count_markers(sc, clip, framenr) == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ tmj = MEM_callocN(sizeof(TrackMarkersJob), "TrackMarkersJob data");
+ if (!track_markers_initjob(C, tmj, backwards, sequence)) {
+ track_markers_freejob(tmj);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Setup job. */
+ if (use_job && sequence) {
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ sa,
+ "Track Markers",
+ WM_JOB_PROGRESS,
+ WM_JOB_TYPE_CLIP_TRACK_MARKERS);
+ WM_jobs_customdata_set(wm_job, tmj, track_markers_freejob);
+
+ /* If there's delay set in tracking job, tracking should happen
+ * with fixed FPS. To deal with editor refresh we have to synchronize
+ * tracks from job and tracks in clip. Do this in timer callback
+ * to prevent threading conflicts. */
+ if (tmj->delay > 0) {
+ WM_jobs_timer(wm_job, tmj->delay / 1000.0f, NC_MOVIECLIP | NA_EVALUATED, 0);
+ }
+ else {
+ WM_jobs_timer(wm_job, 0.2, NC_MOVIECLIP | NA_EVALUATED, 0);
+ }
+
+ WM_jobs_callbacks(
+ wm_job, track_markers_startjob, NULL, track_markers_updatejob, track_markers_endjob);
+
+ G.is_break = false;
+
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+ WM_cursor_wait(0);
+
+ /* Add modal handler for ESC. */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ short stop = 0, do_update = 0;
+ float progress = 0.0f;
+ track_markers_startjob(tmj, &stop, &do_update, &progress);
+ track_markers_endjob(tmj);
+ track_markers_freejob(tmj);
+ return OPERATOR_FINISHED;
+ }
}
static int track_markers_exec(bContext *C, wmOperator *op)
{
- return track_markers(C, op, false);
+ return track_markers(C, op, false);
}
-static int track_markers_invoke(bContext *C,
- wmOperator *op,
- const wmEvent *UNUSED(event))
+static int track_markers_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- return track_markers(C, op, true);
+ return track_markers(C, op, true);
}
-static int track_markers_modal(bContext *C,
- wmOperator *UNUSED(op),
- const wmEvent *event)
+static int track_markers_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- /* No running tracking, remove handler and pass through. */
- if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_wm_area(C), WM_JOB_TYPE_ANY)) {
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
- }
-
- /* Running tracking. */
- switch (event->type) {
- case ESCKEY:
- return OPERATOR_RUNNING_MODAL;
- }
-
- return OPERATOR_PASS_THROUGH;
+ /* No running tracking, remove handler and pass through. */
+ if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_wm_area(C), WM_JOB_TYPE_ANY)) {
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ }
+
+ /* Running tracking. */
+ switch (event->type) {
+ case ESCKEY:
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ return OPERATOR_PASS_THROUGH;
}
void CLIP_OT_track_markers(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Track Markers";
- ot->description = "Track selected markers";
- ot->idname = "CLIP_OT_track_markers";
-
- /* api callbacks */
- ot->exec = track_markers_exec;
- ot->invoke = track_markers_invoke;
- ot->modal = track_markers_modal;
- ot->poll = ED_space_clip_tracking_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "backwards", 0, "Backwards",
- "Do backwards tracking");
- RNA_def_boolean(ot->srna, "sequence", 0, "Track Sequence",
- "Track marker during image sequence rather than "
- "single image");
+ /* identifiers */
+ ot->name = "Track Markers";
+ ot->description = "Track selected markers";
+ ot->idname = "CLIP_OT_track_markers";
+
+ /* api callbacks */
+ ot->exec = track_markers_exec;
+ ot->invoke = track_markers_invoke;
+ ot->modal = track_markers_modal;
+ ot->poll = ED_space_clip_tracking_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "backwards", 0, "Backwards", "Do backwards tracking");
+ RNA_def_boolean(ot->srna,
+ "sequence",
+ 0,
+ "Track Sequence",
+ "Track marker during image sequence rather than "
+ "single image");
}
/********************** Refine track position operator *********************/
static int refine_marker_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- bool backwards = RNA_boolean_get(op->ptr, "backwards");
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- if (TRACK_VIEW_SELECTED(sc, track)) {
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track,
- framenr);
- BKE_tracking_refine_marker(clip, track, marker, backwards);
- }
- }
-
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ bool backwards = RNA_boolean_get(op->ptr, "backwards");
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ if (TRACK_VIEW_SELECTED(sc, track)) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+ BKE_tracking_refine_marker(clip, track, marker, backwards);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_refine_markers(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Refine Markers";
- ot->description = "Refine selected markers positions "
- "by running the tracker from track's reference "
- "to current frame";
- ot->idname = "CLIP_OT_refine_markers";
-
- /* api callbacks */
- ot->exec = refine_marker_exec;
- ot->poll = ED_space_clip_tracking_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "backwards", 0, "Backwards",
- "Do backwards tracking");
+ /* identifiers */
+ ot->name = "Refine Markers";
+ ot->description =
+ "Refine selected markers positions "
+ "by running the tracker from track's reference "
+ "to current frame";
+ ot->idname = "CLIP_OT_refine_markers";
+
+ /* api callbacks */
+ ot->exec = refine_marker_exec;
+ ot->poll = ED_space_clip_tracking_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "backwards", 0, "Backwards", "Do backwards tracking");
}
diff --git a/source/blender/editors/space_clip/tracking_ops_utils.c b/source/blender/editors/space_clip/tracking_ops_utils.c
index 8974f6f7ee0..3970f1381bf 100644
--- a/source/blender/editors/space_clip/tracking_ops_utils.c
+++ b/source/blender/editors/space_clip/tracking_ops_utils.c
@@ -33,39 +33,35 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "tracking_ops_intern.h" // own include
+#include "tracking_ops_intern.h" // own include
-void clip_tracking_clear_invisible_track_selection(SpaceClip *sc,
- MovieClip *clip)
+void clip_tracking_clear_invisible_track_selection(SpaceClip *sc, MovieClip *clip)
{
- ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
- int hidden = 0;
- if ((sc->flag & SC_SHOW_MARKER_PATTERN) == 0) {
- hidden |= TRACK_AREA_PAT;
- }
- if ((sc->flag & SC_SHOW_MARKER_SEARCH) == 0) {
- hidden |= TRACK_AREA_SEARCH;
- }
- if (hidden) {
- for (MovieTrackingTrack *track = tracksbase->first;
- track != NULL;
- track = track->next)
- {
- if ((track->flag & TRACK_HIDDEN) == 0) {
- BKE_tracking_track_flag_clear(track, hidden, SELECT);
- }
- }
- }
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+ int hidden = 0;
+ if ((sc->flag & SC_SHOW_MARKER_PATTERN) == 0) {
+ hidden |= TRACK_AREA_PAT;
+ }
+ if ((sc->flag & SC_SHOW_MARKER_SEARCH) == 0) {
+ hidden |= TRACK_AREA_SEARCH;
+ }
+ if (hidden) {
+ for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ if ((track->flag & TRACK_HIDDEN) == 0) {
+ BKE_tracking_track_flag_clear(track, hidden, SELECT);
+ }
+ }
+ }
}
void clip_tracking_hide_cursor(bContext *C)
{
- wmWindow *win = CTX_wm_window(C);
- WM_cursor_set(win, CURSOR_NONE);
+ wmWindow *win = CTX_wm_window(C);
+ WM_cursor_set(win, CURSOR_NONE);
}
void clip_tracking_show_cursor(bContext *C)
{
- wmWindow *win = CTX_wm_window(C);
- WM_cursor_set(win, CURSOR_STD);
+ wmWindow *win = CTX_wm_window(C);
+ WM_cursor_set(win, CURSOR_STD);
}
diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c
index 0c0fe60108f..24282ce0e96 100644
--- a/source/blender/editors/space_clip/tracking_select.c
+++ b/source/blender/editors/space_clip/tracking_select.c
@@ -48,887 +48,907 @@
#include "DEG_depsgraph.h"
-#include "tracking_ops_intern.h" /* own include */
-#include "clip_intern.h" /* own include */
+#include "tracking_ops_intern.h" /* own include */
+#include "clip_intern.h" /* own include */
static float dist_to_crns(float co[2], float pos[2], float crns[4][2]);
/********************** mouse select operator *********************/
-static int mouse_on_side(float co[2], float x1, float y1, float x2, float y2, float epsx, float epsy)
+static int mouse_on_side(
+ float co[2], float x1, float y1, float x2, float y2, float epsx, float epsy)
{
- if (x1 > x2)
- SWAP(float, x1, x2);
+ if (x1 > x2)
+ SWAP(float, x1, x2);
- if (y1 > y2)
- SWAP(float, y1, y2);
+ if (y1 > y2)
+ SWAP(float, y1, y2);
- return (co[0] >= x1 - epsx && co[0] <= x2 + epsx) && (co[1] >= y1 - epsy && co[1] <= y2 + epsy);
+ return (co[0] >= x1 - epsx && co[0] <= x2 + epsx) && (co[1] >= y1 - epsy && co[1] <= y2 + epsy);
}
-static int mouse_on_rect(float co[2], float pos[2], float min[2], float max[2], float epsx, float epsy)
+static int mouse_on_rect(
+ float co[2], float pos[2], float min[2], 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) ||
- mouse_on_side(co, pos[0] + min[0], pos[1] + min[1], pos[0] + min[0], pos[1] + max[1], epsx, epsy) ||
- mouse_on_side(co, pos[0] + min[0], pos[1] + max[1], pos[0] + max[0], pos[1] + max[1], epsx, epsy) ||
- mouse_on_side(co, pos[0] + max[0], pos[1] + min[1], pos[0] + max[0], pos[1] + max[1], epsx, epsy);
+ return mouse_on_side(
+ co, pos[0] + min[0], pos[1] + min[1], pos[0] + max[0], pos[1] + min[1], epsx, epsy) ||
+ mouse_on_side(
+ co, pos[0] + min[0], pos[1] + min[1], pos[0] + min[0], pos[1] + max[1], epsx, epsy) ||
+ mouse_on_side(
+ co, pos[0] + min[0], pos[1] + max[1], pos[0] + max[0], pos[1] + max[1], epsx, epsy) ||
+ mouse_on_side(
+ 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)
{
- float dist = dist_to_crns(co, pos, crns);
+ float dist = dist_to_crns(co, pos, crns);
- return dist < max_ff(epsx, epsy);
+ return dist < max_ff(epsx, epsy);
}
static int track_mouse_area(const bContext *C, float co[2], MovieTrackingTrack *track)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- int framenr = ED_space_clip_get_clip_frame_number(sc);
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
- float pat_min[2], pat_max[2];
- float epsx, epsy;
- int width, height;
-
- ED_space_clip_get_size(sc, &width, &height);
-
- BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
-
- epsx = min_ffff(pat_min[0] - marker->search_min[0], marker->search_max[0] - pat_max[0],
- fabsf(pat_min[0]), fabsf(pat_max[0])) / 2;
- epsy = min_ffff(pat_min[1] - marker->search_min[1], marker->search_max[1] - pat_max[1],
- fabsf(pat_min[1]), fabsf(pat_max[1])) / 2;
-
- epsx = max_ff(epsx, 2.0f / width);
- epsy = max_ff(epsy, 2.0f / height);
-
- if (sc->flag & SC_SHOW_MARKER_SEARCH) {
- if (mouse_on_rect(co, marker->pos, marker->search_min, marker->search_max, epsx, epsy))
- return TRACK_AREA_SEARCH;
- }
-
- if ((marker->flag & MARKER_DISABLED) == 0) {
- if (sc->flag & SC_SHOW_MARKER_PATTERN)
- if (mouse_on_crns(co, marker->pos, marker->pattern_corners, epsx, epsy))
- return TRACK_AREA_PAT;
-
- epsx = 12.0f / width;
- epsy = 12.0f / height;
-
- if (fabsf(co[0] - marker->pos[0] - track->offset[0]) < epsx &&
- fabsf(co[1] - marker->pos[1] - track->offset[1]) <= epsy)
- {
- return TRACK_AREA_POINT;
- }
- }
-
- return TRACK_AREA_NONE;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+ float pat_min[2], pat_max[2];
+ float epsx, epsy;
+ int width, height;
+
+ ED_space_clip_get_size(sc, &width, &height);
+
+ BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
+
+ epsx = min_ffff(pat_min[0] - marker->search_min[0],
+ marker->search_max[0] - pat_max[0],
+ fabsf(pat_min[0]),
+ fabsf(pat_max[0])) /
+ 2;
+ epsy = min_ffff(pat_min[1] - marker->search_min[1],
+ marker->search_max[1] - pat_max[1],
+ fabsf(pat_min[1]),
+ fabsf(pat_max[1])) /
+ 2;
+
+ epsx = max_ff(epsx, 2.0f / width);
+ epsy = max_ff(epsy, 2.0f / height);
+
+ if (sc->flag & SC_SHOW_MARKER_SEARCH) {
+ if (mouse_on_rect(co, marker->pos, marker->search_min, marker->search_max, epsx, epsy))
+ return TRACK_AREA_SEARCH;
+ }
+
+ if ((marker->flag & MARKER_DISABLED) == 0) {
+ if (sc->flag & SC_SHOW_MARKER_PATTERN)
+ if (mouse_on_crns(co, marker->pos, marker->pattern_corners, epsx, epsy))
+ return TRACK_AREA_PAT;
+
+ epsx = 12.0f / width;
+ epsy = 12.0f / height;
+
+ if (fabsf(co[0] - marker->pos[0] - track->offset[0]) < epsx &&
+ fabsf(co[1] - marker->pos[1] - track->offset[1]) <= epsy) {
+ return TRACK_AREA_POINT;
+ }
+ }
+
+ return TRACK_AREA_NONE;
}
static float dist_to_rect(float co[2], float pos[2], float min[2], float max[2])
{
- float d1, d2, d3, d4;
- float p[2] = {co[0] - pos[0], co[1] - pos[1]};
- float v1[2] = {min[0], min[1]}, v2[2] = {max[0], min[1]};
- float v3[2] = {max[0], max[1]}, v4[2] = {min[0], max[1]};
+ float d1, d2, d3, d4;
+ float p[2] = {co[0] - pos[0], co[1] - pos[1]};
+ float v1[2] = {min[0], min[1]}, v2[2] = {max[0], min[1]};
+ float v3[2] = {max[0], max[1]}, v4[2] = {min[0], max[1]};
- d1 = dist_squared_to_line_segment_v2(p, v1, v2);
- d2 = dist_squared_to_line_segment_v2(p, v2, v3);
- d3 = dist_squared_to_line_segment_v2(p, v3, v4);
- d4 = dist_squared_to_line_segment_v2(p, v4, v1);
+ d1 = dist_squared_to_line_segment_v2(p, v1, v2);
+ d2 = dist_squared_to_line_segment_v2(p, v2, v3);
+ d3 = dist_squared_to_line_segment_v2(p, v3, v4);
+ d4 = dist_squared_to_line_segment_v2(p, v4, v1);
- return sqrtf(min_ffff(d1, d2, d3, d4));
+ return sqrtf(min_ffff(d1, d2, d3, d4));
}
/* 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])
{
- float d1, d2, d3, d4;
- float p[2] = {co[0] - pos[0], co[1] - pos[1]};
- const float *v1 = crns[0], *v2 = crns[1];
- const float *v3 = crns[2], *v4 = crns[3];
+ float d1, d2, d3, d4;
+ float p[2] = {co[0] - pos[0], co[1] - pos[1]};
+ const float *v1 = crns[0], *v2 = crns[1];
+ const float *v3 = crns[2], *v4 = crns[3];
- d1 = dist_squared_to_line_segment_v2(p, v1, v2);
- d2 = dist_squared_to_line_segment_v2(p, v2, v3);
- d3 = dist_squared_to_line_segment_v2(p, v3, v4);
- d4 = dist_squared_to_line_segment_v2(p, v4, v1);
+ d1 = dist_squared_to_line_segment_v2(p, v1, v2);
+ d2 = dist_squared_to_line_segment_v2(p, v2, v3);
+ d3 = dist_squared_to_line_segment_v2(p, v3, v4);
+ d4 = dist_squared_to_line_segment_v2(p, v4, v1);
- return sqrtf(min_ffff(d1, d2, d3, d4));
+ return sqrtf(min_ffff(d1, d2, d3, d4));
}
/* Same as above, but all the coordinates are absolute */
static float dist_to_crns_abs(float co[2], float corners[4][2])
{
- float d1, d2, d3, d4;
- const float *v1 = corners[0], *v2 = corners[1];
- const float *v3 = corners[2], *v4 = corners[3];
+ float d1, d2, d3, d4;
+ const float *v1 = corners[0], *v2 = corners[1];
+ const float *v3 = corners[2], *v4 = corners[3];
- d1 = dist_squared_to_line_segment_v2(co, v1, v2);
- d2 = dist_squared_to_line_segment_v2(co, v2, v3);
- d3 = dist_squared_to_line_segment_v2(co, v3, v4);
- d4 = dist_squared_to_line_segment_v2(co, v4, v1);
+ d1 = dist_squared_to_line_segment_v2(co, v1, v2);
+ d2 = dist_squared_to_line_segment_v2(co, v2, v3);
+ d3 = dist_squared_to_line_segment_v2(co, v3, v4);
+ d4 = dist_squared_to_line_segment_v2(co, v4, v1);
- return sqrtf(min_ffff(d1, d2, d3, d4));
+ return sqrtf(min_ffff(d1, d2, d3, d4));
}
-static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbase, float co[2], float *distance_r)
+static MovieTrackingTrack *find_nearest_track(SpaceClip *sc,
+ ListBase *tracksbase,
+ float co[2],
+ float *distance_r)
{
- MovieTrackingTrack *track = NULL, *cur;
- float mindist = 0.0f;
- int framenr = ED_space_clip_get_clip_frame_number(sc);
+ MovieTrackingTrack *track = NULL, *cur;
+ float mindist = 0.0f;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
- cur = tracksbase->first;
- while (cur) {
- MovieTrackingMarker *marker = BKE_tracking_marker_get(cur, framenr);
+ cur = tracksbase->first;
+ while (cur) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(cur, framenr);
- if (((cur->flag & TRACK_HIDDEN) == 0) && MARKER_VISIBLE(sc, cur, marker)) {
- float dist, d1, d2 = FLT_MAX, d3 = FLT_MAX;
+ if (((cur->flag & TRACK_HIDDEN) == 0) && MARKER_VISIBLE(sc, cur, marker)) {
+ float dist, d1, d2 = FLT_MAX, d3 = FLT_MAX;
- /* distance to marker point */
- d1 = sqrtf((co[0] - marker->pos[0] - cur->offset[0]) * (co[0] - marker->pos[0] - cur->offset[0]) +
- (co[1] - marker->pos[1] - cur->offset[1]) * (co[1] - marker->pos[1] - cur->offset[1]));
+ /* distance to marker point */
+ d1 = sqrtf(
+ (co[0] - marker->pos[0] - cur->offset[0]) * (co[0] - marker->pos[0] - cur->offset[0]) +
+ (co[1] - marker->pos[1] - cur->offset[1]) * (co[1] - marker->pos[1] - cur->offset[1]));
- /* distance to pattern boundbox */
- if (sc->flag & SC_SHOW_MARKER_PATTERN)
- d2 = dist_to_crns(co, marker->pos, marker->pattern_corners);
+ /* distance to pattern boundbox */
+ if (sc->flag & SC_SHOW_MARKER_PATTERN)
+ d2 = dist_to_crns(co, marker->pos, marker->pattern_corners);
- /* distance to search boundbox */
- if (sc->flag & SC_SHOW_MARKER_SEARCH && TRACK_VIEW_SELECTED(sc, cur))
- d3 = dist_to_rect(co, marker->pos, marker->search_min, marker->search_max);
+ /* distance to search boundbox */
+ if (sc->flag & SC_SHOW_MARKER_SEARCH && TRACK_VIEW_SELECTED(sc, cur))
+ d3 = dist_to_rect(co, marker->pos, marker->search_min, marker->search_max);
- /* choose minimal distance. useful for cases of overlapped markers. */
- dist = min_fff(d1, d2, d3);
+ /* choose minimal distance. useful for cases of overlapped markers. */
+ dist = min_fff(d1, d2, d3);
- if (track == NULL || dist < mindist) {
- track = cur;
- mindist = dist;
- }
- }
+ if (track == NULL || dist < mindist) {
+ track = cur;
+ mindist = dist;
+ }
+ }
- cur = cur->next;
- }
+ cur = cur->next;
+ }
- *distance_r = mindist;
+ *distance_r = mindist;
- return track;
+ return track;
}
-static MovieTrackingPlaneTrack *find_nearest_plane_track(SpaceClip *sc, ListBase *plane_tracks_base,
- float co[2], float *distance_r)
+static MovieTrackingPlaneTrack *find_nearest_plane_track(SpaceClip *sc,
+ ListBase *plane_tracks_base,
+ float co[2],
+ float *distance_r)
{
- MovieTrackingPlaneTrack *plane_track = NULL, *current_plane_track;
- float min_distance = 0.0f;
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- for (current_plane_track = plane_tracks_base->first;
- current_plane_track;
- current_plane_track = current_plane_track->next)
- {
- MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(current_plane_track, framenr);
-
- if ((current_plane_track->flag & TRACK_HIDDEN) == 0) {
- float distance = dist_to_crns_abs(co, plane_marker->corners);
- if (plane_track == NULL || distance < min_distance) {
- plane_track = current_plane_track;
- min_distance = distance;
- }
- }
- }
-
- *distance_r = min_distance;
-
- return plane_track;
+ MovieTrackingPlaneTrack *plane_track = NULL, *current_plane_track;
+ float min_distance = 0.0f;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ for (current_plane_track = plane_tracks_base->first; current_plane_track;
+ current_plane_track = current_plane_track->next) {
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(current_plane_track,
+ framenr);
+
+ if ((current_plane_track->flag & TRACK_HIDDEN) == 0) {
+ float distance = dist_to_crns_abs(co, plane_marker->corners);
+ if (plane_track == NULL || distance < min_distance) {
+ plane_track = current_plane_track;
+ min_distance = distance;
+ }
+ }
+ }
+
+ *distance_r = min_distance;
+
+ return plane_track;
}
void ed_tracking_delect_all_tracks(ListBase *tracks_base)
{
- MovieTrackingTrack *track;
- for (track = tracks_base->first;
- track != NULL;
- track = track->next)
- {
- BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
- }
+ MovieTrackingTrack *track;
+ for (track = tracks_base->first; track != NULL; track = track->next) {
+ BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
+ }
}
void ed_tracking_delect_all_plane_tracks(ListBase *plane_tracks_base)
{
- MovieTrackingPlaneTrack *plane_track;
- for (plane_track = plane_tracks_base->first;
- plane_track != NULL;
- plane_track = plane_track->next)
- {
- plane_track->flag &= ~SELECT;
- }
+ MovieTrackingPlaneTrack *plane_track;
+ for (plane_track = plane_tracks_base->first; plane_track != NULL;
+ plane_track = plane_track->next) {
+ plane_track->flag &= ~SELECT;
+ }
}
static int mouse_select(bContext *C, float co[2], int extend)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- MovieTrackingTrack *track;
- MovieTrackingPlaneTrack *plane_track;
- float distance_to_track, distance_to_plane_track;
-
- track = find_nearest_track(sc, tracksbase, co, &distance_to_track);
- plane_track = find_nearest_plane_track(sc, plane_tracks_base, co, &distance_to_plane_track);
-
- /* Between track and plane we choose closest to the mouse for selection here. */
- if (track && plane_track) {
- if (distance_to_track < distance_to_plane_track) {
- plane_track = NULL;
- }
- else {
- track = NULL;
- }
- }
-
- if (!extend) {
- ed_tracking_delect_all_plane_tracks(plane_tracks_base);
- }
-
- if (track) {
- int area = track_mouse_area(C, co, track);
-
- if (!extend || !TRACK_VIEW_SELECTED(sc, track))
- area = TRACK_AREA_ALL;
-
- if (extend && TRACK_AREA_SELECTED(track, area)) {
- if (track == act_track) {
- BKE_tracking_track_deselect(track, area);
- }
- else {
- clip->tracking.act_track = track;
- clip->tracking.act_plane_track = NULL;
- }
- }
- else {
- if (area == TRACK_AREA_POINT)
- area = TRACK_AREA_ALL;
-
- BKE_tracking_track_select(tracksbase, track, area, extend);
- clip->tracking.act_track = track;
- clip->tracking.act_plane_track = NULL;
- }
- }
- else if (plane_track) {
- if (!extend) {
- ed_tracking_delect_all_tracks(tracksbase);
- }
-
- if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
- if (extend) {
- plane_track->flag &= ~SELECT;
- }
- }
- else {
- plane_track->flag |= SELECT;
- }
-
- clip->tracking.act_track = NULL;
- clip->tracking.act_plane_track = plane_track;
- }
-
- if (!extend) {
- sc->xlockof = 0.0f;
- sc->ylockof = 0.0f;
- }
-
- BKE_tracking_dopesheet_tag_update(tracking);
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
- DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
+ MovieTrackingTrack *track;
+ MovieTrackingPlaneTrack *plane_track;
+ float distance_to_track, distance_to_plane_track;
+
+ track = find_nearest_track(sc, tracksbase, co, &distance_to_track);
+ plane_track = find_nearest_plane_track(sc, plane_tracks_base, co, &distance_to_plane_track);
+
+ /* Between track and plane we choose closest to the mouse for selection here. */
+ if (track && plane_track) {
+ if (distance_to_track < distance_to_plane_track) {
+ plane_track = NULL;
+ }
+ else {
+ track = NULL;
+ }
+ }
+
+ if (!extend) {
+ ed_tracking_delect_all_plane_tracks(plane_tracks_base);
+ }
+
+ if (track) {
+ int area = track_mouse_area(C, co, track);
+
+ if (!extend || !TRACK_VIEW_SELECTED(sc, track))
+ area = TRACK_AREA_ALL;
+
+ if (extend && TRACK_AREA_SELECTED(track, area)) {
+ if (track == act_track) {
+ BKE_tracking_track_deselect(track, area);
+ }
+ else {
+ clip->tracking.act_track = track;
+ clip->tracking.act_plane_track = NULL;
+ }
+ }
+ else {
+ if (area == TRACK_AREA_POINT)
+ area = TRACK_AREA_ALL;
+
+ BKE_tracking_track_select(tracksbase, track, area, extend);
+ clip->tracking.act_track = track;
+ clip->tracking.act_plane_track = NULL;
+ }
+ }
+ else if (plane_track) {
+ if (!extend) {
+ ed_tracking_delect_all_tracks(tracksbase);
+ }
+
+ if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
+ if (extend) {
+ plane_track->flag &= ~SELECT;
+ }
+ }
+ else {
+ plane_track->flag |= SELECT;
+ }
+
+ clip->tracking.act_track = NULL;
+ clip->tracking.act_plane_track = plane_track;
+ }
+
+ if (!extend) {
+ sc->xlockof = 0.0f;
+ sc->ylockof = 0.0f;
+ }
+
+ BKE_tracking_dopesheet_tag_update(tracking);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+ DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
+
+ return OPERATOR_FINISHED;
}
static bool select_poll(bContext *C)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
- if (sc) {
- return sc->clip && sc->view == SC_VIEW_CLIP;
- }
+ if (sc) {
+ return sc->clip && sc->view == SC_VIEW_CLIP;
+ }
- return false;
+ return false;
}
static int select_exec(bContext *C, wmOperator *op)
{
- float co[2];
- int extend;
+ float co[2];
+ int extend;
- RNA_float_get_array(op->ptr, "location", co);
- extend = RNA_boolean_get(op->ptr, "extend");
+ RNA_float_get_array(op->ptr, "location", co);
+ extend = RNA_boolean_get(op->ptr, "extend");
- return mouse_select(C, co, extend);
+ return mouse_select(C, co, extend);
}
static int select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
- float co[2];
- const bool extend = RNA_boolean_get(op->ptr, "extend");
+ float co[2];
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
- if (!extend) {
- MovieTrackingTrack *track = tracking_marker_check_slide(C, event, NULL, NULL, NULL);
+ if (!extend) {
+ MovieTrackingTrack *track = tracking_marker_check_slide(C, event, NULL, NULL, NULL);
- if (track) {
- MovieClip *clip = ED_space_clip_get_clip(sc);
+ if (track) {
+ MovieClip *clip = ED_space_clip_get_clip(sc);
- clip->tracking.act_track = track;
+ clip->tracking.act_track = track;
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
- DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+ DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
- return OPERATOR_PASS_THROUGH;
- }
- }
+ return OPERATOR_PASS_THROUGH;
+ }
+ }
- ED_clip_mouse_pos(sc, ar, event->mval, co);
- RNA_float_set_array(op->ptr, "location", co);
+ ED_clip_mouse_pos(sc, ar, event->mval, co);
+ RNA_float_set_array(op->ptr, "location", co);
- return select_exec(C, op);
+ return select_exec(C, op);
}
void CLIP_OT_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select";
- ot->description = "Select tracking markers";
- ot->idname = "CLIP_OT_select";
-
- /* api callbacks */
- ot->exec = select_exec;
- ot->invoke = select_invoke;
- ot->poll = select_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* 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);
+ /* identifiers */
+ ot->name = "Select";
+ ot->description = "Select tracking markers";
+ ot->idname = "CLIP_OT_select";
+
+ /* api callbacks */
+ ot->exec = select_exec;
+ ot->invoke = select_invoke;
+ ot->poll = select_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* 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);
}
/********************** box select operator *********************/
static int box_select_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
-
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingTrack *track;
- MovieTrackingPlaneTrack *plane_track;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- rcti rect;
- rctf rectf;
- bool changed = false;
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- /* 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);
-
- 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)) {
- ED_clip_select_all(sc, SEL_DESELECT, NULL);
- changed = true;
- }
-
- /* do actual selection */
- track = tracksbase->first;
- while (track) {
- if ((track->flag & TRACK_HIDDEN) == 0) {
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
-
- if (MARKER_VISIBLE(sc, track, marker)) {
- if (BLI_rctf_isect_pt_v(&rectf, marker->pos)) {
- if (select) {
- BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT);
- }
- else {
- BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
- }
- }
- changed = true;
- }
- }
-
- track = track->next;
- }
-
- for (plane_track = plane_tracks_base->first;
- plane_track;
- plane_track = plane_track->next)
- {
- if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
- MovieTrackingPlaneMarker *plane_marker =
- BKE_tracking_plane_marker_get(plane_track, framenr);
- int i;
-
- for (i = 0; i < 4; i++) {
- if (BLI_rctf_isect_pt_v(&rectf, plane_marker->corners[i])) {
- if (select) {
- plane_track->flag |= SELECT;
- }
- else {
- plane_track->flag &= ~SELECT;
- }
- }
- }
- changed = true;
- }
- }
-
- if (changed) {
- BKE_tracking_dopesheet_tag_update(tracking);
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
- DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
-
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_CANCELLED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingTrack *track;
+ MovieTrackingPlaneTrack *plane_track;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ rcti rect;
+ rctf rectf;
+ bool changed = false;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ /* 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);
+
+ 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)) {
+ ED_clip_select_all(sc, SEL_DESELECT, NULL);
+ changed = true;
+ }
+
+ /* do actual selection */
+ track = tracksbase->first;
+ while (track) {
+ if ((track->flag & TRACK_HIDDEN) == 0) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+
+ if (MARKER_VISIBLE(sc, track, marker)) {
+ if (BLI_rctf_isect_pt_v(&rectf, marker->pos)) {
+ if (select) {
+ BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT);
+ }
+ else {
+ BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
+ }
+ }
+ changed = true;
+ }
+ }
+
+ track = track->next;
+ }
+
+ for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
+ if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (BLI_rctf_isect_pt_v(&rectf, plane_marker->corners[i])) {
+ if (select) {
+ plane_track->flag |= SELECT;
+ }
+ else {
+ plane_track->flag &= ~SELECT;
+ }
+ }
+ }
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ BKE_tracking_dopesheet_tag_update(tracking);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+ DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
}
void CLIP_OT_select_box(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Box Select";
- ot->description = "Select markers using box selection";
- ot->idname = "CLIP_OT_select_box";
-
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = box_select_exec;
- ot->modal = WM_gesture_box_modal;
- ot->poll = ED_space_clip_tracking_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_gesture_box(ot);
- WM_operator_properties_select_operation_simple(ot);
+ /* identifiers */
+ ot->name = "Box Select";
+ ot->description = "Select markers using box selection";
+ ot->idname = "CLIP_OT_select_box";
+
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = box_select_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->poll = ED_space_clip_tracking_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_gesture_box(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
/********************** lasso select operator *********************/
-static int do_lasso_select_marker(bContext *C, const int mcords[][2], const short moves, bool select)
+static int do_lasso_select_marker(bContext *C,
+ const int mcords[][2],
+ const short moves,
+ bool select)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
-
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingTrack *track;
- MovieTrackingPlaneTrack *plane_track;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- rcti rect;
- bool changed = false;
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- /* get rectangle from operator */
- BLI_lasso_boundbox(&rect, mcords, moves);
-
- /* do actual selection */
- track = tracksbase->first;
- while (track) {
- if ((track->flag & TRACK_HIDDEN) == 0) {
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
-
- if (MARKER_VISIBLE(sc, track, marker)) {
- float screen_co[2];
-
- /* marker in screen coords */
- ED_clip_point_stable_pos__reverse(sc, ar, 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))
- {
- if (select)
- BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT);
- else
- BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
- }
-
- changed = true;
- }
- }
-
- track = track->next;
- }
-
- for (plane_track = plane_tracks_base->first;
- plane_track;
- plane_track = plane_track->next)
- {
- if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
- MovieTrackingPlaneMarker *plane_marker =
- BKE_tracking_plane_marker_get(plane_track, framenr);
- int i;
-
- for (i = 0; i < 4; i++) {
- float screen_co[2];
-
- /* marker in screen coords */
- ED_clip_point_stable_pos__reverse(sc, ar, 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))
- {
- if (select) {
- plane_track->flag |= SELECT;
- }
- else {
- plane_track->flag &= ~SELECT;
- }
- }
- }
-
- changed = true;
- }
- }
-
- if (changed) {
- BKE_tracking_dopesheet_tag_update(tracking);
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
- DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
- }
-
- return changed;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingTrack *track;
+ MovieTrackingPlaneTrack *plane_track;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ rcti rect;
+ bool changed = false;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ /* get rectangle from operator */
+ BLI_lasso_boundbox(&rect, mcords, moves);
+
+ /* do actual selection */
+ track = tracksbase->first;
+ while (track) {
+ if ((track->flag & TRACK_HIDDEN) == 0) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+
+ if (MARKER_VISIBLE(sc, track, marker)) {
+ float screen_co[2];
+
+ /* marker in screen coords */
+ ED_clip_point_stable_pos__reverse(sc, ar, 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)) {
+ if (select)
+ BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT);
+ else
+ BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
+ }
+
+ changed = true;
+ }
+ }
+
+ track = track->next;
+ }
+
+ for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
+ if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ float screen_co[2];
+
+ /* marker in screen coords */
+ ED_clip_point_stable_pos__reverse(sc, ar, 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)) {
+ if (select) {
+ plane_track->flag |= SELECT;
+ }
+ else {
+ plane_track->flag &= ~SELECT;
+ }
+ }
+ }
+
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ BKE_tracking_dopesheet_tag_update(tracking);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+ DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
+ }
+
+ return changed;
}
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 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");
+ const bool select = (sel_op != SEL_OP_SUB);
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ED_clip_select_all(sc, SEL_DESELECT, NULL);
+ }
- if (mcords) {
- 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)) {
- SpaceClip *sc = CTX_wm_space_clip(C);
- ED_clip_select_all(sc, SEL_DESELECT, NULL);
- }
+ do_lasso_select_marker(C, mcords, mcords_tot, select);
- do_lasso_select_marker(C, mcords, mcords_tot, select);
+ MEM_freeN((void *)mcords);
- MEM_freeN((void *)mcords);
-
- return OPERATOR_FINISHED;
- }
- return OPERATOR_PASS_THROUGH;
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_PASS_THROUGH;
}
void CLIP_OT_select_lasso(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Lasso Select";
- ot->description = "Select markers using lasso selection";
- ot->idname = "CLIP_OT_select_lasso";
-
- /* api callbacks */
- ot->invoke = WM_gesture_lasso_invoke;
- ot->modal = WM_gesture_lasso_modal;
- ot->exec = clip_lasso_select_exec;
- ot->poll = ED_space_clip_tracking_poll;
- 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);
+ /* identifiers */
+ ot->name = "Lasso Select";
+ ot->description = "Select markers using lasso selection";
+ ot->idname = "CLIP_OT_select_lasso";
+
+ /* api callbacks */
+ ot->invoke = WM_gesture_lasso_invoke;
+ ot->modal = WM_gesture_lasso_modal;
+ ot->exec = clip_lasso_select_exec;
+ ot->poll = ED_space_clip_tracking_poll;
+ 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);
}
/********************** circle select operator *********************/
static int point_inside_ellipse(float point[2], float offset[2], float ellipse[2])
{
- /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */
- float x, y;
+ /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */
+ float x, y;
- x = (point[0] - offset[0]) * ellipse[0];
- y = (point[1] - offset[1]) * ellipse[1];
+ x = (point[0] - offset[0]) * ellipse[0];
+ y = (point[1] - offset[1]) * ellipse[1];
- return x * x + y * y < 1.0f;
+ return x * x + y * y < 1.0f;
}
static int marker_inside_ellipse(MovieTrackingMarker *marker, float offset[2], float ellipse[2])
{
- return point_inside_ellipse(marker->pos, offset, ellipse);
+ return point_inside_ellipse(marker->pos, offset, ellipse);
}
static int circle_select_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
-
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingTrack *track;
- MovieTrackingPlaneTrack *plane_track;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- int width, height;
- bool changed = false;
- float zoomx, zoomy, offset[2], ellipse[2];
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- /* get operator properties */
- const int x = RNA_int_get(op->ptr, "x");
- const int y = RNA_int_get(op->ptr, "y");
- const int radius = RNA_int_get(op->ptr, "radius");
-
- 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);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- ED_clip_select_all(sc, SEL_DESELECT, NULL);
- changed = true;
- }
-
- /* compute ellipse and position in unified coordinates */
- ED_space_clip_get_size(sc, &width, &height);
- ED_space_clip_get_zoom(sc, ar, &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]);
-
- /* do selection */
- track = tracksbase->first;
- while (track) {
- if ((track->flag & TRACK_HIDDEN) == 0) {
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
-
- if (MARKER_VISIBLE(sc, track, marker) && marker_inside_ellipse(marker, offset, ellipse)) {
- if (select) {
- BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT);
- }
- else {
- BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
- }
- changed = true;
- }
- }
-
- track = track->next;
- }
-
- for (plane_track = plane_tracks_base->first;
- plane_track;
- plane_track = plane_track->next)
- {
- if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
- MovieTrackingPlaneMarker *plane_marker =
- BKE_tracking_plane_marker_get(plane_track, framenr);
- int i;
-
- for (i = 0; i < 4; i++) {
- if (point_inside_ellipse(plane_marker->corners[i], offset, ellipse)) {
- if (select) {
- plane_track->flag |= SELECT;
- }
- else {
- plane_track->flag &= ~SELECT;
- }
- }
- }
-
- changed = true;
- }
- }
-
- if (changed) {
- BKE_tracking_dopesheet_tag_update(tracking);
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
- DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
-
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_CANCELLED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingTrack *track;
+ MovieTrackingPlaneTrack *plane_track;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ int width, height;
+ bool changed = false;
+ float zoomx, zoomy, offset[2], ellipse[2];
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ /* get operator properties */
+ const int x = RNA_int_get(op->ptr, "x");
+ const int y = RNA_int_get(op->ptr, "y");
+ const int radius = RNA_int_get(op->ptr, "radius");
+
+ 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);
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ ED_clip_select_all(sc, SEL_DESELECT, NULL);
+ changed = true;
+ }
+
+ /* compute ellipse and position in unified coordinates */
+ ED_space_clip_get_size(sc, &width, &height);
+ ED_space_clip_get_zoom(sc, ar, &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]);
+
+ /* do selection */
+ track = tracksbase->first;
+ while (track) {
+ if ((track->flag & TRACK_HIDDEN) == 0) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+
+ if (MARKER_VISIBLE(sc, track, marker) && marker_inside_ellipse(marker, offset, ellipse)) {
+ if (select) {
+ BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT);
+ }
+ else {
+ BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
+ }
+ changed = true;
+ }
+ }
+
+ track = track->next;
+ }
+
+ for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
+ if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (point_inside_ellipse(plane_marker->corners[i], offset, ellipse)) {
+ if (select) {
+ plane_track->flag |= SELECT;
+ }
+ else {
+ plane_track->flag &= ~SELECT;
+ }
+ }
+ }
+
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ BKE_tracking_dopesheet_tag_update(tracking);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+ DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
}
void CLIP_OT_select_circle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Circle Select";
- ot->description = "Select markers using circle selection";
- ot->idname = "CLIP_OT_select_circle";
-
- /* api callbacks */
- ot->invoke = WM_gesture_circle_invoke;
- ot->modal = WM_gesture_circle_modal;
- ot->exec = circle_select_exec;
- ot->poll = ED_space_clip_tracking_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_gesture_circle(ot);
- WM_operator_properties_select_operation_simple(ot);
+ /* identifiers */
+ ot->name = "Circle Select";
+ ot->description = "Select markers using circle selection";
+ ot->idname = "CLIP_OT_select_circle";
+
+ /* api callbacks */
+ ot->invoke = WM_gesture_circle_invoke;
+ ot->modal = WM_gesture_circle_modal;
+ ot->exec = circle_select_exec;
+ ot->poll = ED_space_clip_tracking_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_gesture_circle(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
/********************** select all operator *********************/
static int select_all_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking = &clip->tracking;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
- int action = RNA_enum_get(op->ptr, "action");
+ int action = RNA_enum_get(op->ptr, "action");
- bool has_selection = false;
+ bool has_selection = false;
- ED_clip_select_all(sc, action, &has_selection);
+ ED_clip_select_all(sc, action, &has_selection);
- if (!has_selection)
- sc->flag &= ~SC_LOCK_SELECTION;
+ if (!has_selection)
+ sc->flag &= ~SC_LOCK_SELECTION;
- BKE_tracking_dopesheet_tag_update(tracking);
+ BKE_tracking_dopesheet_tag_update(tracking);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
- DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+ DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CLIP_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All";
- ot->description = "Change selection of all tracking markers";
- ot->idname = "CLIP_OT_select_all";
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->description = "Change selection of all tracking markers";
+ ot->idname = "CLIP_OT_select_all";
- /* api callbacks */
- ot->exec = select_all_exec;
- ot->poll = ED_space_clip_tracking_poll;
+ /* api callbacks */
+ ot->exec = select_all_exec;
+ ot->poll = ED_space_clip_tracking_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_select_all(ot);
+ WM_operator_properties_select_all(ot);
}
/********************** select grouped operator *********************/
static int select_grouped_exec(bContext *C, wmOperator *op)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTrackingTrack *track;
- MovieTrackingMarker *marker;
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- int group = RNA_enum_get(op->ptr, "group");
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- track = tracksbase->first;
- while (track) {
- bool ok = false;
-
- marker = BKE_tracking_marker_get(track, framenr);
-
- if (group == 0) { /* Keyframed */
- ok = marker->framenr == framenr && (marker->flag & MARKER_TRACKED) == 0;
- }
- else if (group == 1) { /* Estimated */
- ok = marker->framenr != framenr;
- }
- else if (group == 2) { /* tracked */
- ok = marker->framenr == framenr && (marker->flag & MARKER_TRACKED);
- }
- else if (group == 3) { /* locked */
- ok = track->flag & TRACK_LOCKED;
- }
- else if (group == 4) { /* disabled */
- ok = marker->flag & MARKER_DISABLED;
- }
- else if (group == 5) { /* color */
- MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
-
- if (act_track) {
- ok = (track->flag & TRACK_CUSTOMCOLOR) == (act_track->flag & TRACK_CUSTOMCOLOR);
-
- if (ok && track->flag & TRACK_CUSTOMCOLOR)
- ok = equals_v3v3(track->color, act_track->color);
- }
- }
- else if (group == 6) { /* failed */
- ok = (track->flag & TRACK_HAS_BUNDLE) == 0;
- }
-
- if (ok) {
- track->flag |= SELECT;
- if (sc->flag & SC_SHOW_MARKER_PATTERN)
- track->pat_flag |= SELECT;
- if (sc->flag & SC_SHOW_MARKER_SEARCH)
- track->search_flag |= SELECT;
- }
-
- track = track->next;
- }
-
- BKE_tracking_dopesheet_tag_update(tracking);
-
- WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
- DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
-
- return OPERATOR_FINISHED;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTrackingTrack *track;
+ MovieTrackingMarker *marker;
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ int group = RNA_enum_get(op->ptr, "group");
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ track = tracksbase->first;
+ while (track) {
+ bool ok = false;
+
+ marker = BKE_tracking_marker_get(track, framenr);
+
+ if (group == 0) { /* Keyframed */
+ ok = marker->framenr == framenr && (marker->flag & MARKER_TRACKED) == 0;
+ }
+ else if (group == 1) { /* Estimated */
+ ok = marker->framenr != framenr;
+ }
+ else if (group == 2) { /* tracked */
+ ok = marker->framenr == framenr && (marker->flag & MARKER_TRACKED);
+ }
+ else if (group == 3) { /* locked */
+ ok = track->flag & TRACK_LOCKED;
+ }
+ else if (group == 4) { /* disabled */
+ ok = marker->flag & MARKER_DISABLED;
+ }
+ else if (group == 5) { /* color */
+ MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
+
+ if (act_track) {
+ ok = (track->flag & TRACK_CUSTOMCOLOR) == (act_track->flag & TRACK_CUSTOMCOLOR);
+
+ if (ok && track->flag & TRACK_CUSTOMCOLOR)
+ ok = equals_v3v3(track->color, act_track->color);
+ }
+ }
+ else if (group == 6) { /* failed */
+ ok = (track->flag & TRACK_HAS_BUNDLE) == 0;
+ }
+
+ if (ok) {
+ track->flag |= SELECT;
+ if (sc->flag & SC_SHOW_MARKER_PATTERN)
+ track->pat_flag |= SELECT;
+ if (sc->flag & SC_SHOW_MARKER_SEARCH)
+ track->search_flag |= SELECT;
+ }
+
+ track = track->next;
+ }
+
+ BKE_tracking_dopesheet_tag_update(tracking);
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
+ DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
+
+ return OPERATOR_FINISHED;
}
void CLIP_OT_select_grouped(wmOperatorType *ot)
{
- static const EnumPropertyItem select_group_items[] = {
- {0, "KEYFRAMED", 0, "Keyframed tracks", "Select all keyframed tracks"},
- {1, "ESTIMATED", 0, "Estimated tracks", "Select all estimated tracks"},
- {2, "TRACKED", 0, "Tracked tracks", "Select all tracked tracks"},
- {3, "LOCKED", 0, "Locked tracks", "Select all locked tracks"},
- {4, "DISABLED", 0, "Disabled tracks", "Select all disabled tracks"},
- {5, "COLOR", 0, "Tracks with same color", "Select all tracks with same color as active track"},
- {6, "FAILED", 0, "Failed Tracks", "Select all tracks which failed to be reconstructed"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Select Grouped";
- ot->description = "Select all tracks from specified group";
- ot->idname = "CLIP_OT_select_grouped";
-
- /* api callbacks */
- ot->exec = select_grouped_exec;
- ot->poll = ED_space_clip_tracking_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "group", select_group_items, TRACK_CLEAR_REMAINED, "Action", "Clear action to execute");
+ static const EnumPropertyItem select_group_items[] = {
+ {0, "KEYFRAMED", 0, "Keyframed tracks", "Select all keyframed tracks"},
+ {1, "ESTIMATED", 0, "Estimated tracks", "Select all estimated tracks"},
+ {2, "TRACKED", 0, "Tracked tracks", "Select all tracked tracks"},
+ {3, "LOCKED", 0, "Locked tracks", "Select all locked tracks"},
+ {4, "DISABLED", 0, "Disabled tracks", "Select all disabled tracks"},
+ {5,
+ "COLOR",
+ 0,
+ "Tracks with same color",
+ "Select all tracks with same color as active track"},
+ {6, "FAILED", 0, "Failed Tracks", "Select all tracks which failed to be reconstructed"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Select Grouped";
+ ot->description = "Select all tracks from specified group";
+ ot->idname = "CLIP_OT_select_grouped";
+
+ /* api callbacks */
+ ot->exec = select_grouped_exec;
+ ot->poll = ED_space_clip_tracking_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna,
+ "group",
+ select_group_items,
+ TRACK_CLEAR_REMAINED,
+ "Action",
+ "Clear action to execute");
}
diff --git a/source/blender/editors/space_console/CMakeLists.txt b/source/blender/editors/space_console/CMakeLists.txt
index d8645c3674a..5070b6fcf65 100644
--- a/source/blender/editors/space_console/CMakeLists.txt
+++ b/source/blender/editors/space_console/CMakeLists.txt
@@ -16,37 +16,37 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenfont
- ../../blenkernel
- ../../blenlib
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenfont
+ ../../blenkernel
+ ../../blenlib
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- console_draw.c
- console_ops.c
- space_console.c
+ console_draw.c
+ console_ops.c
+ space_console.c
- console_intern.h
+ console_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
+ bf_blenkernel
+ bf_blenlib
)
if(WITH_PYTHON)
- add_definitions(-DWITH_PYTHON)
+ add_definitions(-DWITH_PYTHON)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c
index 042fb366224..4d6b05df609 100644
--- a/source/blender/editors/space_console/console_draw.c
+++ b/source/blender/editors/space_console/console_draw.c
@@ -24,7 +24,6 @@
#include <sys/stat.h>
#include <limits.h>
-
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -41,45 +40,44 @@
#include "console_intern.h"
-
#include "../space_info/textview.h"
static void console_line_color(unsigned char fg[3], int type)
{
- switch (type) {
- case CONSOLE_LINE_OUTPUT:
- UI_GetThemeColor3ubv(TH_CONSOLE_OUTPUT, fg);
- break;
- case CONSOLE_LINE_INPUT:
- UI_GetThemeColor3ubv(TH_CONSOLE_INPUT, fg);
- break;
- case CONSOLE_LINE_INFO:
- UI_GetThemeColor3ubv(TH_CONSOLE_INFO, fg);
- break;
- case CONSOLE_LINE_ERROR:
- UI_GetThemeColor3ubv(TH_CONSOLE_ERROR, fg);
- break;
- }
+ switch (type) {
+ case CONSOLE_LINE_OUTPUT:
+ UI_GetThemeColor3ubv(TH_CONSOLE_OUTPUT, fg);
+ break;
+ case CONSOLE_LINE_INPUT:
+ UI_GetThemeColor3ubv(TH_CONSOLE_INPUT, fg);
+ break;
+ case CONSOLE_LINE_INFO:
+ UI_GetThemeColor3ubv(TH_CONSOLE_INFO, fg);
+ break;
+ case CONSOLE_LINE_ERROR:
+ UI_GetThemeColor3ubv(TH_CONSOLE_ERROR, fg);
+ break;
+ }
}
void console_scrollback_prompt_begin(struct SpaceConsole *sc, ConsoleLine *cl_dummy)
{
- /* fake the edit line being in the scroll buffer */
- ConsoleLine *cl = sc->history.last;
- int prompt_len = strlen(sc->prompt);
-
- cl_dummy->type = CONSOLE_LINE_INPUT;
- cl_dummy->len = prompt_len + cl->len;
- cl_dummy->len_alloc = cl_dummy->len + 1;
- cl_dummy->line = MEM_mallocN(cl_dummy->len_alloc, "cl_dummy");
- memcpy(cl_dummy->line, sc->prompt, prompt_len);
- memcpy(cl_dummy->line + prompt_len, cl->line, cl->len + 1);
- BLI_addtail(&sc->scrollback, cl_dummy);
+ /* fake the edit line being in the scroll buffer */
+ ConsoleLine *cl = sc->history.last;
+ int prompt_len = strlen(sc->prompt);
+
+ cl_dummy->type = CONSOLE_LINE_INPUT;
+ cl_dummy->len = prompt_len + cl->len;
+ cl_dummy->len_alloc = cl_dummy->len + 1;
+ cl_dummy->line = MEM_mallocN(cl_dummy->len_alloc, "cl_dummy");
+ memcpy(cl_dummy->line, sc->prompt, prompt_len);
+ 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)
{
- MEM_freeN(cl_dummy->line);
- BLI_remlink(&sc->scrollback, cl_dummy);
+ MEM_freeN(cl_dummy->line);
+ BLI_remlink(&sc->scrollback, cl_dummy);
}
#define CONSOLE_DRAW_MARGIN 4
@@ -87,165 +85,165 @@ void console_scrollback_prompt_end(struct SpaceConsole *sc, ConsoleLine *cl_dumm
/* console textview callbacks */
static int console_textview_begin(TextViewContext *tvc)
{
- SpaceConsole *sc = (SpaceConsole *)tvc->arg1;
- tvc->lheight = sc->lheight * UI_DPI_FAC;
- tvc->sel_start = sc->sel_start;
- tvc->sel_end = sc->sel_end;
+ SpaceConsole *sc = (SpaceConsole *)tvc->arg1;
+ tvc->lheight = sc->lheight * UI_DPI_FAC;
+ tvc->sel_start = sc->sel_start;
+ tvc->sel_end = sc->sel_end;
- /* iterator */
- tvc->iter = sc->scrollback.last;
+ /* iterator */
+ tvc->iter = sc->scrollback.last;
- return (tvc->iter != NULL);
+ return (tvc->iter != NULL);
}
static void console_textview_end(TextViewContext *tvc)
{
- SpaceConsole *sc = (SpaceConsole *)tvc->arg1;
- (void)sc;
-
+ SpaceConsole *sc = (SpaceConsole *)tvc->arg1;
+ (void)sc;
}
static int console_textview_step(TextViewContext *tvc)
{
- return ((tvc->iter = (void *)((Link *)tvc->iter)->prev) != NULL);
+ return ((tvc->iter = (void *)((Link *)tvc->iter)->prev) != NULL);
}
static int console_textview_line_get(struct TextViewContext *tvc, const char **line, int *len)
{
- ConsoleLine *cl = (ConsoleLine *)tvc->iter;
- *line = cl->line;
- *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;
+ ConsoleLine *cl = (ConsoleLine *)tvc->iter;
+ *line = cl->line;
+ *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(const char *str, int width, int *row, int *column, const char *end)
+static void console_cursor_wrap_offset(
+ const char *str, int width, int *row, int *column, const char *end)
{
- int col;
+ int col;
- for (; *str; str += BLI_str_utf8_size_safe(str)) {
- col = BLI_str_utf8_char_width_safe(str);
+ for (; *str; str += BLI_str_utf8_size_safe(str)) {
+ col = BLI_str_utf8_char_width_safe(str);
- if (*column + col > width) {
- (*row)++;
- *column = 0;
- }
+ if (*column + col > width) {
+ (*row)++;
+ *column = 0;
+ }
- if (end && str >= end) {
- break;
- }
+ if (end && str >= end) {
+ break;
+ }
- *column += col;
- }
- return;
+ *column += col;
+ }
+ return;
}
-static int console_textview_line_color(struct TextViewContext *tvc, unsigned char fg[3], unsigned char UNUSED(bg[3]))
+static int console_textview_line_color(struct TextViewContext *tvc,
+ unsigned char fg[3],
+ unsigned char UNUSED(bg[3]))
{
- ConsoleLine *cl_iter = (ConsoleLine *)tvc->iter;
-
- /* annoying hack, to draw the prompt */
- if (tvc->iter_index == 0) {
- const SpaceConsole *sc = (SpaceConsole *)tvc->arg1;
- const ConsoleLine *cl = (ConsoleLine *)sc->history.last;
- int offl = 0, offc = 0;
- int xy[2] = {CONSOLE_DRAW_MARGIN, CONSOLE_DRAW_MARGIN};
- 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 / 6;
-
- console_cursor_wrap_offset(sc->prompt, tvc->console_width, &offl, &offc, NULL);
- console_cursor_wrap_offset(cl->line, tvc->console_width, &offl, &offc, cl->line + cl->cursor);
- pen[0] = tvc->cwidth * offc;
- pen[1] = -2 - tvc->lheight * offl;
-
- console_cursor_wrap_offset(cl->line + cl->cursor, tvc->console_width, &offl, &offc, NULL);
- pen[1] += tvc->lheight * offl;
-
- /* cursor */
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor(TH_CONSOLE_CURSOR);
-
- immRectf(pos,
- (xy[0] + pen[0]) - 1,
- (xy[1] + pen[1]),
- (xy[0] + pen[0]) + 1,
- (xy[1] + pen[1] + tvc->lheight)
- );
-
- immUnbindProgram();
- }
-
- console_line_color(fg, cl_iter->type);
-
- return TVC_LINE_FG;
+ ConsoleLine *cl_iter = (ConsoleLine *)tvc->iter;
+
+ /* annoying hack, to draw the prompt */
+ if (tvc->iter_index == 0) {
+ const SpaceConsole *sc = (SpaceConsole *)tvc->arg1;
+ const ConsoleLine *cl = (ConsoleLine *)sc->history.last;
+ int offl = 0, offc = 0;
+ int xy[2] = {CONSOLE_DRAW_MARGIN, CONSOLE_DRAW_MARGIN};
+ 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 / 6;
+
+ console_cursor_wrap_offset(sc->prompt, tvc->console_width, &offl, &offc, NULL);
+ console_cursor_wrap_offset(cl->line, tvc->console_width, &offl, &offc, cl->line + cl->cursor);
+ pen[0] = tvc->cwidth * offc;
+ pen[1] = -2 - tvc->lheight * offl;
+
+ console_cursor_wrap_offset(cl->line + cl->cursor, tvc->console_width, &offl, &offc, NULL);
+ pen[1] += tvc->lheight * offl;
+
+ /* cursor */
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_CONSOLE_CURSOR);
+
+ immRectf(pos,
+ (xy[0] + pen[0]) - 1,
+ (xy[1] + pen[1]),
+ (xy[0] + pen[0]) + 1,
+ (xy[1] + pen[1] + tvc->lheight));
+
+ immUnbindProgram();
+ }
+
+ console_line_color(fg, cl_iter->type);
+
+ return TVC_LINE_FG;
}
static void console_textview_const_colors(TextViewContext *UNUSED(tvc), unsigned char bg_sel[4])
{
- UI_GetThemeColor4ubv(TH_CONSOLE_SELECT, bg_sel);
+ UI_GetThemeColor4ubv(TH_CONSOLE_SELECT, bg_sel);
}
-static int console_textview_main__internal(struct SpaceConsole *sc, ARegion *ar, int draw,
- int mval[2], void **mouse_pick, int *pos_pick)
+static int console_textview_main__internal(
+ struct SpaceConsole *sc, ARegion *ar, int draw, int mval[2], void **mouse_pick, int *pos_pick)
{
- ConsoleLine cl_dummy = {NULL};
- int ret = 0;
+ ConsoleLine cl_dummy = {NULL};
+ int ret = 0;
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &ar->v2d;
- TextViewContext tvc = {0};
+ TextViewContext tvc = {0};
- tvc.begin = console_textview_begin;
- tvc.end = console_textview_end;
+ tvc.begin = console_textview_begin;
+ tvc.end = console_textview_end;
- tvc.step = console_textview_step;
- tvc.line_get = console_textview_line_get;
- tvc.line_color = console_textview_line_color;
- tvc.const_colors = console_textview_const_colors;
+ tvc.step = console_textview_step;
+ tvc.line_get = console_textview_line_get;
+ tvc.line_color = console_textview_line_color;
+ tvc.const_colors = console_textview_const_colors;
- tvc.arg1 = sc;
- tvc.arg2 = NULL;
+ tvc.arg1 = sc;
+ tvc.arg2 = NULL;
- /* view */
- tvc.sel_start = sc->sel_start;
- tvc.sel_end = sc->sel_end;
- tvc.lheight = sc->lheight * UI_DPI_FAC;
- tvc.ymin = v2d->cur.ymin;
- tvc.ymax = v2d->cur.ymax;
- tvc.winx = ar->winx - V2D_SCROLL_WIDTH;
+ /* view */
+ tvc.sel_start = sc->sel_start;
+ tvc.sel_end = sc->sel_end;
+ tvc.lheight = sc->lheight * UI_DPI_FAC;
+ tvc.ymin = v2d->cur.ymin;
+ tvc.ymax = v2d->cur.ymax;
+ tvc.winx = ar->winx - V2D_SCROLL_WIDTH;
- console_scrollback_prompt_begin(sc, &cl_dummy);
- ret = textview_draw(&tvc, draw, mval, mouse_pick, pos_pick);
- console_scrollback_prompt_end(sc, &cl_dummy);
+ console_scrollback_prompt_begin(sc, &cl_dummy);
+ ret = textview_draw(&tvc, draw, mval, mouse_pick, pos_pick);
+ console_scrollback_prompt_end(sc, &cl_dummy);
- return ret;
+ return ret;
}
-
void console_textview_main(struct SpaceConsole *sc, ARegion *ar)
{
- int mval[2] = {INT_MAX, INT_MAX};
- console_textview_main__internal(sc, ar, 1, mval, NULL, NULL);
+ int mval[2] = {INT_MAX, INT_MAX};
+ console_textview_main__internal(sc, ar, 1, mval, NULL, NULL);
}
int console_textview_height(struct SpaceConsole *sc, ARegion *ar)
{
- int mval[2] = {INT_MAX, INT_MAX};
- return console_textview_main__internal(sc, ar, 0, mval, NULL, NULL);
+ int mval[2] = {INT_MAX, INT_MAX};
+ return console_textview_main__internal(sc, ar, 0, mval, NULL, NULL);
}
int console_char_pick(struct SpaceConsole *sc, ARegion *ar, const int mval[2])
{
- int pos_pick = 0;
- void *mouse_pick = NULL;
- int mval_clamp[2];
+ int pos_pick = 0;
+ void *mouse_pick = NULL;
+ int mval_clamp[2];
- mval_clamp[0] = CLAMPIS(mval[0], CONSOLE_DRAW_MARGIN, ar->winx - CONSOLE_DRAW_MARGIN);
- mval_clamp[1] = CLAMPIS(mval[1], CONSOLE_DRAW_MARGIN, ar->winy - CONSOLE_DRAW_MARGIN);
+ mval_clamp[0] = CLAMPIS(mval[0], CONSOLE_DRAW_MARGIN, ar->winx - CONSOLE_DRAW_MARGIN);
+ mval_clamp[1] = CLAMPIS(mval[1], CONSOLE_DRAW_MARGIN, ar->winy - CONSOLE_DRAW_MARGIN);
- console_textview_main__internal(sc, ar, 0, mval_clamp, &mouse_pick, &pos_pick);
- return pos_pick;
+ console_textview_main__internal(sc, ar, 0, mval_clamp, &mouse_pick, &pos_pick);
+ return pos_pick;
}
diff --git a/source/blender/editors/space_console/console_intern.h b/source/blender/editors/space_console/console_intern.h
index 1e4a90ca71a..30f7894ea33 100644
--- a/source/blender/editors/space_console/console_intern.h
+++ b/source/blender/editors/space_console/console_intern.h
@@ -65,6 +65,14 @@ void CONSOLE_OT_select_set(struct wmOperatorType *ot);
void CONSOLE_OT_select_word(struct wmOperatorType *ot);
enum { LINE_BEGIN, LINE_END, PREV_CHAR, NEXT_CHAR, PREV_WORD, NEXT_WORD };
-enum { DEL_NEXT_CHAR, DEL_PREV_CHAR, DEL_NEXT_WORD, DEL_PREV_WORD, DEL_SELECTION, DEL_NEXT_SEL, DEL_PREV_SEL };
+enum {
+ DEL_NEXT_CHAR,
+ DEL_PREV_CHAR,
+ DEL_NEXT_WORD,
+ DEL_PREV_WORD,
+ DEL_SELECTION,
+ DEL_NEXT_SEL,
+ DEL_PREV_SEL
+};
#endif /* __CONSOLE_INTERN_H__ */
diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c
index d4489337847..a17c1b675e6 100644
--- a/source/blender/editors/space_console/console_ops.c
+++ b/source/blender/editors/space_console/console_ops.c
@@ -18,7 +18,6 @@
* \ingroup spconsole
*/
-
#include <stdlib.h>
#include <string.h>
#include <ctype.h> /* ispunct */
@@ -52,225 +51,224 @@
/* so when we type - the view scrolls to the bottom */
static void console_scroll_bottom(ARegion *ar)
{
- View2D *v2d = &ar->v2d;
- v2d->cur.ymin = 0.0;
- v2d->cur.ymax = (float)v2d->winy;
+ View2D *v2d = &ar->v2d;
+ v2d->cur.ymin = 0.0;
+ v2d->cur.ymax = (float)v2d->winy;
}
void console_textview_update_rect(SpaceConsole *sc, ARegion *ar)
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &ar->v2d;
- UI_view2d_totRect_set(v2d, ar->winx - 1, console_textview_height(sc, ar));
+ UI_view2d_totRect_set(v2d, ar->winx - 1, console_textview_height(sc, ar));
}
static void console_select_offset(SpaceConsole *sc, const int offset)
{
- sc->sel_start += offset;
- sc->sel_end += offset;
+ sc->sel_start += offset;
+ sc->sel_end += offset;
}
void console_history_free(SpaceConsole *sc, ConsoleLine *cl)
{
- BLI_remlink(&sc->history, cl);
- MEM_freeN(cl->line);
- MEM_freeN(cl);
+ BLI_remlink(&sc->history, cl);
+ MEM_freeN(cl->line);
+ MEM_freeN(cl);
}
void console_scrollback_free(SpaceConsole *sc, ConsoleLine *cl)
{
- BLI_remlink(&sc->scrollback, cl);
- MEM_freeN(cl->line);
- MEM_freeN(cl);
+ BLI_remlink(&sc->scrollback, cl);
+ MEM_freeN(cl->line);
+ MEM_freeN(cl);
}
static void console_scrollback_limit(SpaceConsole *sc)
{
- int tot;
+ int tot;
- if (U.scrollback < 32) {
- U.scrollback = 256; // XXX - save in user defaults
- }
+ if (U.scrollback < 32) {
+ U.scrollback = 256; // XXX - save in user defaults
+ }
- for (tot = BLI_listbase_count(&sc->scrollback); tot > U.scrollback; tot--) {
- console_scrollback_free(sc, sc->scrollback.first);
- }
+ for (tot = BLI_listbase_count(&sc->scrollback); tot > U.scrollback; tot--) {
+ console_scrollback_free(sc, sc->scrollback.first);
+ }
}
static ConsoleLine *console_history_find(SpaceConsole *sc, const char *str, ConsoleLine *cl_ignore)
{
- ConsoleLine *cl;
+ ConsoleLine *cl;
- for (cl = sc->history.last; cl; cl = cl->prev) {
- if (cl == cl_ignore) {
- continue;
- }
+ for (cl = sc->history.last; cl; cl = cl->prev) {
+ if (cl == cl_ignore) {
+ continue;
+ }
- if (STREQ(str, cl->line)) {
- return cl;
- }
- }
+ if (STREQ(str, cl->line)) {
+ return cl;
+ }
+ }
- return NULL;
+ return NULL;
}
/* return 0 if no change made, clamps the range */
static bool console_line_cursor_set(ConsoleLine *cl, int cursor)
{
- int cursor_new;
-
- if (cursor < 0) {
- cursor_new = 0;
- }
- else if (cursor > cl->len) {
- cursor_new = cl->len;
- }
- else {
- cursor_new = cursor;
- }
-
- if (cursor_new == cl->cursor) {
- return false;
- }
-
- cl->cursor = cursor_new;
- return true;
+ int cursor_new;
+
+ if (cursor < 0) {
+ cursor_new = 0;
+ }
+ else if (cursor > cl->len) {
+ cursor_new = cl->len;
+ }
+ else {
+ cursor_new = cursor;
+ }
+
+ if (cursor_new == cl->cursor) {
+ return false;
+ }
+
+ cl->cursor = cursor_new;
+ return true;
}
-#if 0 // XXX unused
+#if 0 // XXX unused
static void console_lb_debug__internal(ListBase *lb)
{
- ConsoleLine *cl;
+ ConsoleLine *cl;
- printf("%d: ", BLI_listbase_count(lb));
- for (cl = lb->first; cl; cl = cl->next)
- printf("<%s> ", cl->line);
- printf("\n");
+ printf("%d: ", BLI_listbase_count(lb));
+ for (cl = lb->first; cl; cl = cl->next)
+ printf("<%s> ", cl->line);
+ printf("\n");
}
static void console_history_debug(const bContext *C)
{
- SpaceConsole *sc = CTX_wm_space_console(C);
+ SpaceConsole *sc = CTX_wm_space_console(C);
- console_lb_debug__internal(&sc->history);
+ console_lb_debug__internal(&sc->history);
}
#endif
static ConsoleLine *console_lb_add__internal(ListBase *lb, ConsoleLine *from)
{
- ConsoleLine *ci = MEM_callocN(sizeof(ConsoleLine), "ConsoleLine Add");
-
- if (from) {
- BLI_assert(strlen(from->line) == from->len);
- ci->line = BLI_strdupn(from->line, from->len);
- ci->len = ci->len_alloc = from->len;
- ci->cursor = from->cursor;
- ci->type = from->type;
- }
- else {
- ci->line = MEM_callocN(64, "console-in-line");
- ci->len_alloc = 64;
- ci->len = 0;
- }
-
- BLI_addtail(lb, ci);
- return ci;
+ ConsoleLine *ci = MEM_callocN(sizeof(ConsoleLine), "ConsoleLine Add");
+
+ if (from) {
+ BLI_assert(strlen(from->line) == from->len);
+ ci->line = BLI_strdupn(from->line, from->len);
+ ci->len = ci->len_alloc = from->len;
+ ci->cursor = from->cursor;
+ ci->type = from->type;
+ }
+ else {
+ ci->line = MEM_callocN(64, "console-in-line");
+ ci->len_alloc = 64;
+ ci->len = 0;
+ }
+
+ BLI_addtail(lb, ci);
+ return ci;
}
static ConsoleLine *console_history_add(SpaceConsole *sc, ConsoleLine *from)
{
- return console_lb_add__internal(&sc->history, from);
+ return console_lb_add__internal(&sc->history, from);
}
#if 0 /* may use later ? */
static ConsoleLine *console_scrollback_add(const bContext *C, ConsoleLine *from)
{
- SpaceConsole *sc = CTX_wm_space_console(C);
+ SpaceConsole *sc = CTX_wm_space_console(C);
- return console_lb_add__internal(&sc->scrollback, from);
+ return console_lb_add__internal(&sc->scrollback, from);
}
#endif
static ConsoleLine *console_lb_add_str__internal(ListBase *lb, char *str, bool own)
{
- ConsoleLine *ci = MEM_callocN(sizeof(ConsoleLine), "ConsoleLine Add");
- if (own) {
- ci->line = str;
- }
- else {
- ci->line = BLI_strdup(str);
- }
-
- ci->len = ci->len_alloc = strlen(str);
-
- BLI_addtail(lb, ci);
- return ci;
+ ConsoleLine *ci = MEM_callocN(sizeof(ConsoleLine), "ConsoleLine Add");
+ if (own) {
+ ci->line = str;
+ }
+ else {
+ ci->line = BLI_strdup(str);
+ }
+
+ ci->len = ci->len_alloc = strlen(str);
+
+ BLI_addtail(lb, ci);
+ return ci;
}
ConsoleLine *console_history_add_str(SpaceConsole *sc, char *str, bool own)
{
- return console_lb_add_str__internal(&sc->history, str, own);
+ return console_lb_add_str__internal(&sc->history, str, own);
}
ConsoleLine *console_scrollback_add_str(SpaceConsole *sc, char *str, bool own)
{
- ConsoleLine *ci = console_lb_add_str__internal(&sc->scrollback, str, own);
- console_select_offset(sc, ci->len + 1);
- return ci;
+ ConsoleLine *ci = console_lb_add_str__internal(&sc->scrollback, str, own);
+ console_select_offset(sc, ci->len + 1);
+ return ci;
}
ConsoleLine *console_history_verify(const bContext *C)
{
- SpaceConsole *sc = CTX_wm_space_console(C);
- ConsoleLine *ci = sc->history.last;
- if (ci == NULL) {
- ci = console_history_add(sc, NULL);
- }
+ SpaceConsole *sc = CTX_wm_space_console(C);
+ ConsoleLine *ci = sc->history.last;
+ if (ci == NULL) {
+ ci = console_history_add(sc, NULL);
+ }
- return ci;
+ return ci;
}
-
static void console_line_verify_length(ConsoleLine *ci, int len)
{
- /* resize the buffer if needed */
- if (len >= ci->len_alloc) {
- /* new length */
+ /* resize the buffer if needed */
+ if (len >= ci->len_alloc) {
+ /* new length */
#ifndef NDEBUG
- int new_len = len + 1;
+ int new_len = len + 1;
#else
- int new_len = (len + 1) * 2;
+ 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);
+ 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->len_alloc = new_len;
- }
+ ci->line = new_line;
+ ci->len_alloc = new_len;
+ }
}
static int console_line_insert(ConsoleLine *ci, char *str)
{
- int len = strlen(str);
+ int len = strlen(str);
- if (len > 0 && str[len - 1] == '\n') { /* stop new lines being pasted at the end of lines */
- str[len - 1] = '\0';
- len--;
- }
+ if (len > 0 && str[len - 1] == '\n') { /* stop new lines being pasted at the end of lines */
+ str[len - 1] = '\0';
+ len--;
+ }
- if (len == 0) {
- return 0;
- }
+ if (len == 0) {
+ return 0;
+ }
- console_line_verify_length(ci, len + ci->len);
+ console_line_verify_length(ci, len + ci->len);
- memmove(ci->line + ci->cursor + len, ci->line + ci->cursor, (ci->len - ci->cursor) + 1);
- memcpy(ci->line + ci->cursor, str, len);
+ memmove(ci->line + ci->cursor + len, ci->line + ci->cursor, (ci->len - ci->cursor) + 1);
+ memcpy(ci->line + ci->cursor, str, len);
- ci->len += len;
- ci->cursor += len;
+ ci->len += len;
+ ci->cursor += len;
- return len;
+ return len;
}
/**
@@ -279,975 +277,977 @@ static int console_line_insert(ConsoleLine *ci, char *str)
* \note be sure to call console_scrollback_prompt_begin first
*/
static bool console_line_column_from_index(
- SpaceConsole *sc, const int pos,
- ConsoleLine **r_cl, int *r_cl_offset, int *r_col)
+ SpaceConsole *sc, const int pos, ConsoleLine **r_cl, int *r_cl_offset, int *r_col)
{
- ConsoleLine *cl;
- int offset = 0;
-
- for (cl = sc->scrollback.last; cl; cl = cl->prev) {
- offset += cl->len + 1;
- if (offset >= pos) {
- break;
- }
- }
-
- if (cl) {
- offset -= 1;
- *r_cl = cl;
- *r_cl_offset = offset;
- *r_col = offset - pos;
- return true;
- }
- else {
- *r_cl = NULL;
- *r_cl_offset = -1;
- *r_col = -1;
- return false;
- }
+ ConsoleLine *cl;
+ int offset = 0;
+
+ for (cl = sc->scrollback.last; cl; cl = cl->prev) {
+ offset += cl->len + 1;
+ if (offset >= pos) {
+ break;
+ }
+ }
+
+ if (cl) {
+ offset -= 1;
+ *r_cl = cl;
+ *r_cl_offset = offset;
+ *r_col = offset - pos;
+ return true;
+ }
+ else {
+ *r_cl = NULL;
+ *r_cl_offset = -1;
+ *r_col = -1;
+ return false;
+ }
}
/* static funcs for text editing */
/* similar to the text editor, with some not used. keep compatible */
static const EnumPropertyItem console_move_type_items[] = {
- {LINE_BEGIN, "LINE_BEGIN", 0, "Line Begin", ""},
- {LINE_END, "LINE_END", 0, "Line End", ""},
- {PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
- {NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
- {PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
- {NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
- {0, NULL, 0, NULL, NULL},
+ {LINE_BEGIN, "LINE_BEGIN", 0, "Line Begin", ""},
+ {LINE_END, "LINE_END", 0, "Line End", ""},
+ {PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
+ {NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
+ {PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
+ {NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int console_move_exec(bContext *C, wmOperator *op)
{
- ConsoleLine *ci = console_history_verify(C);
-
- int type = RNA_enum_get(op->ptr, "type");
- bool done = false;
- int pos;
-
- switch (type) {
- case LINE_BEGIN:
- pos = ci->cursor;
- BLI_str_cursor_step_utf8(ci->line, ci->len,
- &pos, STRCUR_DIR_PREV,
- STRCUR_JUMP_ALL, true);
- done = console_line_cursor_set(ci, pos);
- break;
- case LINE_END:
- pos = ci->cursor;
- BLI_str_cursor_step_utf8(ci->line, ci->len,
- &pos, STRCUR_DIR_NEXT,
- STRCUR_JUMP_ALL, true);
- done = console_line_cursor_set(ci, pos);
- break;
- case PREV_CHAR:
- pos = ci->cursor;
- BLI_str_cursor_step_utf8(ci->line, ci->len,
- &pos, STRCUR_DIR_PREV,
- STRCUR_JUMP_NONE, true);
- done = console_line_cursor_set(ci, pos);
- break;
- case NEXT_CHAR:
- pos = ci->cursor;
- BLI_str_cursor_step_utf8(ci->line, ci->len,
- &pos, STRCUR_DIR_NEXT,
- STRCUR_JUMP_NONE, true);
- done = console_line_cursor_set(ci, pos);
- break;
-
- /* - if the character is a delimiter then skip delimiters (including white space)
- * - when jump over the word */
- case PREV_WORD:
- pos = ci->cursor;
- BLI_str_cursor_step_utf8(ci->line, ci->len,
- &pos, STRCUR_DIR_PREV,
- STRCUR_JUMP_DELIM, true);
- done = console_line_cursor_set(ci, pos);
- break;
- case NEXT_WORD:
- pos = ci->cursor;
- BLI_str_cursor_step_utf8(ci->line, ci->len,
- &pos, STRCUR_DIR_NEXT,
- STRCUR_JUMP_DELIM, true);
- done = console_line_cursor_set(ci, pos);
- break;
- }
-
- if (done) {
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
-
- ED_area_tag_redraw(sa);
- console_scroll_bottom(ar);
- }
-
-
- return OPERATOR_FINISHED;
+ ConsoleLine *ci = console_history_verify(C);
+
+ int type = RNA_enum_get(op->ptr, "type");
+ bool done = false;
+ int pos;
+
+ switch (type) {
+ case LINE_BEGIN:
+ pos = ci->cursor;
+ BLI_str_cursor_step_utf8(ci->line, ci->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_ALL, true);
+ done = console_line_cursor_set(ci, pos);
+ break;
+ case LINE_END:
+ pos = ci->cursor;
+ BLI_str_cursor_step_utf8(ci->line, ci->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_ALL, true);
+ done = console_line_cursor_set(ci, pos);
+ break;
+ case PREV_CHAR:
+ pos = ci->cursor;
+ BLI_str_cursor_step_utf8(ci->line, ci->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_NONE, true);
+ done = console_line_cursor_set(ci, pos);
+ break;
+ case NEXT_CHAR:
+ pos = ci->cursor;
+ BLI_str_cursor_step_utf8(ci->line, ci->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_NONE, true);
+ done = console_line_cursor_set(ci, pos);
+ break;
+
+ /* - if the character is a delimiter then skip delimiters (including white space)
+ * - when jump over the word */
+ case PREV_WORD:
+ pos = ci->cursor;
+ BLI_str_cursor_step_utf8(ci->line, ci->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
+ done = console_line_cursor_set(ci, pos);
+ break;
+ case NEXT_WORD:
+ pos = ci->cursor;
+ BLI_str_cursor_step_utf8(ci->line, ci->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
+ done = console_line_cursor_set(ci, pos);
+ break;
+ }
+
+ if (done) {
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ ED_area_tag_redraw(sa);
+ console_scroll_bottom(ar);
+ }
+
+ return OPERATOR_FINISHED;
}
void CONSOLE_OT_move(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move Cursor";
- ot->description = "Move cursor position";
- ot->idname = "CONSOLE_OT_move";
-
- /* api callbacks */
- ot->exec = console_move_exec;
- ot->poll = ED_operator_console_active;
-
- /* properties */
- RNA_def_enum(ot->srna, "type", console_move_type_items, LINE_BEGIN, "Type", "Where to move cursor to");
+ /* identifiers */
+ ot->name = "Move Cursor";
+ ot->description = "Move cursor position";
+ ot->idname = "CONSOLE_OT_move";
+
+ /* api callbacks */
+ ot->exec = console_move_exec;
+ ot->poll = ED_operator_console_active;
+
+ /* properties */
+ RNA_def_enum(
+ ot->srna, "type", console_move_type_items, LINE_BEGIN, "Type", "Where to move cursor to");
}
#define TAB_LENGTH 4
static int console_insert_exec(bContext *C, wmOperator *op)
{
- SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
- ConsoleLine *ci = console_history_verify(C);
- char *str = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
- int len;
+ SpaceConsole *sc = CTX_wm_space_console(C);
+ ARegion *ar = CTX_wm_region(C);
+ ConsoleLine *ci = console_history_verify(C);
+ char *str = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
+ int len;
- if (str[0] == '\t' && str[1] == '\0') {
- len = TAB_LENGTH;
- MEM_freeN(str);
- str = MEM_mallocN(len + 1, "insert_exec");
- memset(str, ' ', len);
- str[len] = '\0';
- }
+ if (str[0] == '\t' && str[1] == '\0') {
+ len = TAB_LENGTH;
+ MEM_freeN(str);
+ str = MEM_mallocN(len + 1, "insert_exec");
+ memset(str, ' ', len);
+ str[len] = '\0';
+ }
- len = console_line_insert(ci, str);
+ len = console_line_insert(ci, str);
- MEM_freeN(str);
+ MEM_freeN(str);
- if (len == 0) {
- return OPERATOR_CANCELLED;
- }
- else {
- console_select_offset(sc, len);
- }
+ if (len == 0) {
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ console_select_offset(sc, len);
+ }
- console_textview_update_rect(sc, ar);
- ED_area_tag_redraw(CTX_wm_area(C));
+ console_textview_update_rect(sc, ar);
+ ED_area_tag_redraw(CTX_wm_area(C));
- console_scroll_bottom(ar);
+ console_scroll_bottom(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int console_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- // if (!RNA_struct_property_is_set(op->ptr, "text")) { /* always set from keymap XXX */
- if (!RNA_string_length(op->ptr, "text")) {
- /* if alt/ctrl/super are pressed pass through except for utf8 character event
- * (when input method are used for utf8 inputs, the user may assign key event
- * including alt/ctrl/super like ctrl+m to commit utf8 string. in such case,
- * the modifiers in the utf8 character event make no sense.) */
- if ((event->ctrl || event->oskey) && !event->utf8_buf[0]) {
- return OPERATOR_PASS_THROUGH;
- }
- else {
- char str[BLI_UTF8_MAX + 1];
- size_t len;
-
- if (event->utf8_buf[0]) {
- len = BLI_str_utf8_size_safe(event->utf8_buf);
- memcpy(str, event->utf8_buf, len);
- }
- else {
- /* in theory, ghost can set value to extended ascii here */
- len = BLI_str_utf8_from_unicode(event->ascii, str);
- }
- str[len] = '\0';
- RNA_string_set(op->ptr, "text", str);
- }
- }
- return console_insert_exec(C, op);
+ // if (!RNA_struct_property_is_set(op->ptr, "text")) { /* always set from keymap XXX */
+ if (!RNA_string_length(op->ptr, "text")) {
+ /* if alt/ctrl/super are pressed pass through except for utf8 character event
+ * (when input method are used for utf8 inputs, the user may assign key event
+ * including alt/ctrl/super like ctrl+m to commit utf8 string. in such case,
+ * the modifiers in the utf8 character event make no sense.) */
+ if ((event->ctrl || event->oskey) && !event->utf8_buf[0]) {
+ return OPERATOR_PASS_THROUGH;
+ }
+ else {
+ char str[BLI_UTF8_MAX + 1];
+ size_t len;
+
+ if (event->utf8_buf[0]) {
+ len = BLI_str_utf8_size_safe(event->utf8_buf);
+ memcpy(str, event->utf8_buf, len);
+ }
+ else {
+ /* in theory, ghost can set value to extended ascii here */
+ len = BLI_str_utf8_from_unicode(event->ascii, str);
+ }
+ str[len] = '\0';
+ RNA_string_set(op->ptr, "text", str);
+ }
+ }
+ return console_insert_exec(C, op);
}
void CONSOLE_OT_insert(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Insert";
- ot->description = "Insert text at cursor position";
- ot->idname = "CONSOLE_OT_insert";
-
- /* api callbacks */
- ot->exec = console_insert_exec;
- ot->invoke = console_insert_invoke;
- ot->poll = ED_operator_console_active;
-
- /* properties */
- prop = RNA_def_string(ot->srna, "text", NULL, 0, "Text", "Text to insert at the cursor position");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Insert";
+ ot->description = "Insert text at cursor position";
+ ot->idname = "CONSOLE_OT_insert";
+
+ /* api callbacks */
+ ot->exec = console_insert_exec;
+ ot->invoke = console_insert_invoke;
+ ot->poll = ED_operator_console_active;
+
+ /* properties */
+ prop = RNA_def_string(
+ ot->srna, "text", NULL, 0, "Text", "Text to insert at the cursor position");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static int console_indent_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
- ConsoleLine *ci = console_history_verify(C);
- int spaces;
- int len;
+ SpaceConsole *sc = CTX_wm_space_console(C);
+ ARegion *ar = CTX_wm_region(C);
+ ConsoleLine *ci = console_history_verify(C);
+ int spaces;
+ int len;
- for (spaces = 0; spaces < ci->len; spaces++) {
- if (ci->line[spaces] != ' ') {
- break;
- }
- }
+ for (spaces = 0; spaces < ci->len; spaces++) {
+ if (ci->line[spaces] != ' ') {
+ break;
+ }
+ }
- len = TAB_LENGTH - spaces % TAB_LENGTH;
+ len = TAB_LENGTH - spaces % TAB_LENGTH;
- console_line_verify_length(ci, ci->len + len);
+ console_line_verify_length(ci, ci->len + len);
- memmove(ci->line + len, ci->line, ci->len + 1);
- memset(ci->line, ' ', len);
- ci->len += len;
- BLI_assert(ci->len >= 0);
- console_line_cursor_set(ci, ci->cursor + len);
- console_select_offset(sc, len);
+ memmove(ci->line + len, ci->line, ci->len + 1);
+ memset(ci->line, ' ', len);
+ ci->len += len;
+ BLI_assert(ci->len >= 0);
+ console_line_cursor_set(ci, ci->cursor + len);
+ console_select_offset(sc, len);
- console_textview_update_rect(sc, ar);
- ED_area_tag_redraw(CTX_wm_area(C));
+ console_textview_update_rect(sc, ar);
+ ED_area_tag_redraw(CTX_wm_area(C));
- console_scroll_bottom(ar);
+ console_scroll_bottom(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CONSOLE_OT_indent(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Indent";
- ot->description = "Add 4 spaces at line beginning";
- ot->idname = "CONSOLE_OT_indent";
-
- /* api callbacks */
- ot->exec = console_indent_exec;
- ot->poll = ED_operator_console_active;
+ /* identifiers */
+ ot->name = "Indent";
+ ot->description = "Add 4 spaces at line beginning";
+ ot->idname = "CONSOLE_OT_indent";
+
+ /* api callbacks */
+ ot->exec = console_indent_exec;
+ ot->poll = ED_operator_console_active;
}
static int console_unindent_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
- ConsoleLine *ci = console_history_verify(C);
- int spaces;
- int len;
+ SpaceConsole *sc = CTX_wm_space_console(C);
+ ARegion *ar = CTX_wm_region(C);
+ ConsoleLine *ci = console_history_verify(C);
+ int spaces;
+ int len;
- for (spaces = 0; spaces < ci->len; spaces++) {
- if (ci->line[spaces] != ' ') {
- break;
- }
- }
+ for (spaces = 0; spaces < ci->len; spaces++) {
+ if (ci->line[spaces] != ' ') {
+ break;
+ }
+ }
- if (spaces == 0) {
- return OPERATOR_CANCELLED;
- }
+ if (spaces == 0) {
+ return OPERATOR_CANCELLED;
+ }
- len = spaces % TAB_LENGTH;
- if (len == 0) {
- len = TAB_LENGTH;
- }
+ len = spaces % TAB_LENGTH;
+ if (len == 0) {
+ len = TAB_LENGTH;
+ }
- console_line_verify_length(ci, ci->len - len);
+ console_line_verify_length(ci, ci->len - len);
- memmove(ci->line, ci->line + len, (ci->len - len) + 1);
- ci->len -= len;
- BLI_assert(ci->len >= 0);
+ memmove(ci->line, ci->line + len, (ci->len - len) + 1);
+ ci->len -= len;
+ BLI_assert(ci->len >= 0);
- console_line_cursor_set(ci, ci->cursor - len);
- console_select_offset(sc, -len);
+ console_line_cursor_set(ci, ci->cursor - len);
+ console_select_offset(sc, -len);
- console_textview_update_rect(sc, ar);
- ED_area_tag_redraw(CTX_wm_area(C));
+ console_textview_update_rect(sc, ar);
+ ED_area_tag_redraw(CTX_wm_area(C));
- console_scroll_bottom(ar);
+ console_scroll_bottom(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CONSOLE_OT_unindent(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unindent";
- ot->description = "Delete 4 spaces from line beginning";
- ot->idname = "CONSOLE_OT_unindent";
-
- /* api callbacks */
- ot->exec = console_unindent_exec;
- ot->poll = ED_operator_console_active;
+ /* identifiers */
+ ot->name = "Unindent";
+ ot->description = "Delete 4 spaces from line beginning";
+ ot->idname = "CONSOLE_OT_unindent";
+
+ /* api callbacks */
+ ot->exec = console_unindent_exec;
+ ot->poll = ED_operator_console_active;
}
static const EnumPropertyItem console_delete_type_items[] = {
- {DEL_NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
- {DEL_PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
- {DEL_NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
- {DEL_PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
- {0, NULL, 0, NULL, NULL},
+ {DEL_NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
+ {DEL_PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
+ {DEL_NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
+ {DEL_PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int console_delete_exec(bContext *C, wmOperator *op)
{
- SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
- ConsoleLine *ci = console_history_verify(C);
- int pos;
- int stride;
-
- const short type = RNA_enum_get(op->ptr, "type");
- bool done = false;
-
- if (ci->len == 0) {
- return OPERATOR_CANCELLED;
- }
-
- switch (type) {
- case DEL_NEXT_CHAR:
- case DEL_NEXT_WORD:
- if (ci->cursor < ci->len) {
- pos = ci->cursor;
- BLI_str_cursor_step_utf8(ci->line, ci->len,
- &pos, STRCUR_DIR_NEXT,
- (type == DEL_NEXT_CHAR) ? STRCUR_JUMP_NONE : STRCUR_JUMP_DELIM, true);
- stride = pos - ci->cursor;
- if (stride) {
- memmove(ci->line + ci->cursor, ci->line + ci->cursor + stride, (ci->len - (ci->cursor + stride)) + 1);
- ci->len -= stride;
- BLI_assert(ci->len >= 0);
- done = true;
- }
- }
- break;
- case DEL_PREV_CHAR:
- case DEL_PREV_WORD:
- if (ci->cursor > 0) {
- pos = ci->cursor;
- BLI_str_cursor_step_utf8(ci->line, ci->len,
- &pos, STRCUR_DIR_PREV,
- (type == DEL_PREV_CHAR) ? STRCUR_JUMP_NONE : STRCUR_JUMP_DELIM, true);
- stride = ci->cursor - pos;
- if (stride) {
- ci->cursor -= stride; /* same as above */
- memmove(ci->line + ci->cursor, ci->line + ci->cursor + stride, (ci->len - (ci->cursor + stride)) + 1);
- ci->len -= stride;
- BLI_assert(ci->len >= 0);
- done = true;
- }
- }
- break;
- }
-
- if (!done) {
- return OPERATOR_CANCELLED;
- }
- else {
- console_select_offset(sc, -stride);
- }
-
- console_textview_update_rect(sc, ar);
- ED_area_tag_redraw(CTX_wm_area(C));
-
- console_scroll_bottom(ar);
-
- return OPERATOR_FINISHED;
+ SpaceConsole *sc = CTX_wm_space_console(C);
+ ARegion *ar = CTX_wm_region(C);
+ ConsoleLine *ci = console_history_verify(C);
+ int pos;
+ int stride;
+
+ const short type = RNA_enum_get(op->ptr, "type");
+ bool done = false;
+
+ if (ci->len == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (type) {
+ case DEL_NEXT_CHAR:
+ case DEL_NEXT_WORD:
+ if (ci->cursor < ci->len) {
+ pos = ci->cursor;
+ BLI_str_cursor_step_utf8(ci->line,
+ ci->len,
+ &pos,
+ STRCUR_DIR_NEXT,
+ (type == DEL_NEXT_CHAR) ? STRCUR_JUMP_NONE : STRCUR_JUMP_DELIM,
+ true);
+ stride = pos - ci->cursor;
+ if (stride) {
+ memmove(ci->line + ci->cursor,
+ ci->line + ci->cursor + stride,
+ (ci->len - (ci->cursor + stride)) + 1);
+ ci->len -= stride;
+ BLI_assert(ci->len >= 0);
+ done = true;
+ }
+ }
+ break;
+ case DEL_PREV_CHAR:
+ case DEL_PREV_WORD:
+ if (ci->cursor > 0) {
+ pos = ci->cursor;
+ BLI_str_cursor_step_utf8(ci->line,
+ ci->len,
+ &pos,
+ STRCUR_DIR_PREV,
+ (type == DEL_PREV_CHAR) ? STRCUR_JUMP_NONE : STRCUR_JUMP_DELIM,
+ true);
+ stride = ci->cursor - pos;
+ if (stride) {
+ ci->cursor -= stride; /* same as above */
+ memmove(ci->line + ci->cursor,
+ ci->line + ci->cursor + stride,
+ (ci->len - (ci->cursor + stride)) + 1);
+ ci->len -= stride;
+ BLI_assert(ci->len >= 0);
+ done = true;
+ }
+ }
+ break;
+ }
+
+ if (!done) {
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ console_select_offset(sc, -stride);
+ }
+
+ console_textview_update_rect(sc, ar);
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ console_scroll_bottom(ar);
+
+ return OPERATOR_FINISHED;
}
-
void CONSOLE_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete";
- ot->description = "Delete text by cursor position";
- ot->idname = "CONSOLE_OT_delete";
-
- /* api callbacks */
- ot->exec = console_delete_exec;
- ot->poll = ED_operator_console_active;
-
- /* properties */
- RNA_def_enum(ot->srna, "type", console_delete_type_items, DEL_NEXT_CHAR, "Type", "Which part of the text to delete");
+ /* identifiers */
+ ot->name = "Delete";
+ ot->description = "Delete text by cursor position";
+ ot->idname = "CONSOLE_OT_delete";
+
+ /* api callbacks */
+ ot->exec = console_delete_exec;
+ ot->poll = ED_operator_console_active;
+
+ /* properties */
+ RNA_def_enum(ot->srna,
+ "type",
+ console_delete_type_items,
+ DEL_NEXT_CHAR,
+ "Type",
+ "Which part of the text to delete");
}
static int console_clear_line_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
- ConsoleLine *ci = console_history_verify(C);
+ SpaceConsole *sc = CTX_wm_space_console(C);
+ ARegion *ar = CTX_wm_region(C);
+ ConsoleLine *ci = console_history_verify(C);
- if (ci->len == 0) {
- return OPERATOR_CANCELLED;
- }
+ if (ci->len == 0) {
+ return OPERATOR_CANCELLED;
+ }
- console_history_add(sc, ci);
- console_history_add(sc, NULL);
- console_select_offset(sc, -ci->len);
+ console_history_add(sc, ci);
+ console_history_add(sc, NULL);
+ console_select_offset(sc, -ci->len);
- console_textview_update_rect(sc, ar);
+ console_textview_update_rect(sc, ar);
- ED_area_tag_redraw(CTX_wm_area(C));
+ ED_area_tag_redraw(CTX_wm_area(C));
- console_scroll_bottom(ar);
+ console_scroll_bottom(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CONSOLE_OT_clear_line(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Line";
- ot->description = "Clear the line and store in history";
- ot->idname = "CONSOLE_OT_clear_line";
-
- /* api callbacks */
- ot->exec = console_clear_line_exec;
- ot->poll = ED_operator_console_active;
+ /* identifiers */
+ ot->name = "Clear Line";
+ ot->description = "Clear the line and store in history";
+ ot->idname = "CONSOLE_OT_clear_line";
+
+ /* api callbacks */
+ ot->exec = console_clear_line_exec;
+ ot->poll = ED_operator_console_active;
}
/* the python exec operator uses this */
static int console_clear_exec(bContext *C, wmOperator *op)
{
- SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
+ SpaceConsole *sc = CTX_wm_space_console(C);
+ ARegion *ar = CTX_wm_region(C);
- const bool scrollback = RNA_boolean_get(op->ptr, "scrollback");
- const bool history = RNA_boolean_get(op->ptr, "history");
+ const bool scrollback = RNA_boolean_get(op->ptr, "scrollback");
+ const bool history = RNA_boolean_get(op->ptr, "history");
- /*ConsoleLine *ci = */ console_history_verify(C);
+ /*ConsoleLine *ci = */ console_history_verify(C);
- if (scrollback) { /* last item in mistory */
- while (sc->scrollback.first) {
- console_scrollback_free(sc, sc->scrollback.first);
- }
- }
+ if (scrollback) { /* last item in mistory */
+ while (sc->scrollback.first) {
+ console_scrollback_free(sc, sc->scrollback.first);
+ }
+ }
- if (history) {
- while (sc->history.first) {
- console_history_free(sc, sc->history.first);
- }
- console_history_verify(C);
- }
+ if (history) {
+ while (sc->history.first) {
+ console_history_free(sc, sc->history.first);
+ }
+ console_history_verify(C);
+ }
- console_textview_update_rect(sc, ar);
- ED_area_tag_redraw(CTX_wm_area(C));
+ console_textview_update_rect(sc, ar);
+ ED_area_tag_redraw(CTX_wm_area(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CONSOLE_OT_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear";
- ot->description = "Clear text by type";
- ot->idname = "CONSOLE_OT_clear";
-
- /* api callbacks */
- ot->exec = console_clear_exec;
- ot->poll = ED_operator_console_active;
-
- /* properties */
- RNA_def_boolean(ot->srna, "scrollback", 1, "Scrollback", "Clear the scrollback history");
- RNA_def_boolean(ot->srna, "history", 0, "History", "Clear the command history");
+ /* identifiers */
+ ot->name = "Clear";
+ ot->description = "Clear text by type";
+ ot->idname = "CONSOLE_OT_clear";
+
+ /* api callbacks */
+ ot->exec = console_clear_exec;
+ ot->poll = ED_operator_console_active;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "scrollback", 1, "Scrollback", "Clear the scrollback history");
+ RNA_def_boolean(ot->srna, "history", 0, "History", "Clear the command history");
}
-
-
/* the python exec operator uses this */
static int console_history_cycle_exec(bContext *C, wmOperator *op)
{
- SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
-
- /* TODO - stupid, just prevents crashes when no command line */
- ConsoleLine *ci = console_history_verify(C);
- const bool reverse = RNA_boolean_get(op->ptr, "reverse"); /* assumes down, reverse is up */
- int prev_len = ci->len;
-
- /* keep a copy of the line above so when history is cycled
- * this is the only function that needs to know about the double-up */
- if (ci->prev) {
- ConsoleLine *ci_prev = (ConsoleLine *)ci->prev;
-
- if (STREQ(ci->line, ci_prev->line)) {
- console_history_free(sc, ci_prev);
- }
- }
-
- if (reverse) { /* last item in history */
- ci = sc->history.last;
- BLI_remlink(&sc->history, ci);
- BLI_addhead(&sc->history, ci);
- }
- else {
- ci = sc->history.first;
- BLI_remlink(&sc->history, ci);
- BLI_addtail(&sc->history, ci);
- }
-
- { /* add a duplicate of the new arg and remove all other instances */
- ConsoleLine *cl;
- while ((cl = console_history_find(sc, ci->line, ci))) {
- console_history_free(sc, cl);
- }
-
- console_history_add(sc, (ConsoleLine *)sc->history.last);
- }
-
- ci = sc->history.last;
- console_select_offset(sc, ci->len - prev_len);
-
- /* could be wrapped so update scroll rect */
- console_textview_update_rect(sc, ar);
- ED_area_tag_redraw(CTX_wm_area(C));
-
- console_scroll_bottom(ar);
-
- return OPERATOR_FINISHED;
+ SpaceConsole *sc = CTX_wm_space_console(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ /* TODO - stupid, just prevents crashes when no command line */
+ ConsoleLine *ci = console_history_verify(C);
+ const bool reverse = RNA_boolean_get(op->ptr, "reverse"); /* assumes down, reverse is up */
+ int prev_len = ci->len;
+
+ /* keep a copy of the line above so when history is cycled
+ * this is the only function that needs to know about the double-up */
+ if (ci->prev) {
+ ConsoleLine *ci_prev = (ConsoleLine *)ci->prev;
+
+ if (STREQ(ci->line, ci_prev->line)) {
+ console_history_free(sc, ci_prev);
+ }
+ }
+
+ if (reverse) { /* last item in history */
+ ci = sc->history.last;
+ BLI_remlink(&sc->history, ci);
+ BLI_addhead(&sc->history, ci);
+ }
+ else {
+ ci = sc->history.first;
+ BLI_remlink(&sc->history, ci);
+ BLI_addtail(&sc->history, ci);
+ }
+
+ { /* add a duplicate of the new arg and remove all other instances */
+ ConsoleLine *cl;
+ while ((cl = console_history_find(sc, ci->line, ci))) {
+ console_history_free(sc, cl);
+ }
+
+ console_history_add(sc, (ConsoleLine *)sc->history.last);
+ }
+
+ ci = sc->history.last;
+ console_select_offset(sc, ci->len - prev_len);
+
+ /* could be wrapped so update scroll rect */
+ console_textview_update_rect(sc, ar);
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ console_scroll_bottom(ar);
+
+ return OPERATOR_FINISHED;
}
void CONSOLE_OT_history_cycle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "History Cycle";
- ot->description = "Cycle through history";
- ot->idname = "CONSOLE_OT_history_cycle";
+ /* identifiers */
+ ot->name = "History Cycle";
+ ot->description = "Cycle through history";
+ ot->idname = "CONSOLE_OT_history_cycle";
- /* api callbacks */
- ot->exec = console_history_cycle_exec;
- ot->poll = ED_operator_console_active;
+ /* api callbacks */
+ ot->exec = console_history_cycle_exec;
+ ot->poll = ED_operator_console_active;
- /* properties */
- RNA_def_boolean(ot->srna, "reverse", 0, "Reverse", "Reverse cycle history");
+ /* properties */
+ RNA_def_boolean(ot->srna, "reverse", 0, "Reverse", "Reverse cycle history");
}
-
/* the python exec operator uses this */
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);
- 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);
- int cursor = RNA_int_get(op->ptr, "current_character");
- const bool rem_dupes = RNA_boolean_get(op->ptr, "remove_duplicates");
- int prev_len = ci->len;
-
- if (rem_dupes) {
- ConsoleLine *cl;
-
- while ((cl = console_history_find(sc, ci->line, ci))) {
- console_history_free(sc, cl);
- }
-
- if (STREQ(str, ci->line)) {
- MEM_freeN(str);
- return OPERATOR_FINISHED;
- }
- }
-
- ci = console_history_add_str(sc, str, 1); /* own the string */
- console_select_offset(sc, ci->len - prev_len);
- console_line_cursor_set(ci, cursor);
-
- ED_area_tag_redraw(sa);
-
- /* when calling render modally this can be NULL when calling:
- * bpy.ops.render.render('INVOKE_DEFAULT') */
- if (ar) {
- console_scroll_bottom(ar);
- }
-
- return OPERATOR_FINISHED;
+ SpaceConsole *sc = CTX_wm_space_console(C);
+ ARegion *ar = CTX_wm_region(C);
+ ScrArea *sa = 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);
+ int cursor = RNA_int_get(op->ptr, "current_character");
+ const bool rem_dupes = RNA_boolean_get(op->ptr, "remove_duplicates");
+ int prev_len = ci->len;
+
+ if (rem_dupes) {
+ ConsoleLine *cl;
+
+ while ((cl = console_history_find(sc, ci->line, ci))) {
+ console_history_free(sc, cl);
+ }
+
+ if (STREQ(str, ci->line)) {
+ MEM_freeN(str);
+ return OPERATOR_FINISHED;
+ }
+ }
+
+ ci = console_history_add_str(sc, str, 1); /* own the string */
+ console_select_offset(sc, ci->len - prev_len);
+ console_line_cursor_set(ci, cursor);
+
+ ED_area_tag_redraw(sa);
+
+ /* when calling render modally this can be NULL when calling:
+ * bpy.ops.render.render('INVOKE_DEFAULT') */
+ if (ar) {
+ console_scroll_bottom(ar);
+ }
+
+ return OPERATOR_FINISHED;
}
void CONSOLE_OT_history_append(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "History Append";
- ot->description = "Append history at cursor position";
- ot->idname = "CONSOLE_OT_history_append";
-
- /* api callbacks */
- ot->exec = console_history_append_exec;
- ot->poll = ED_operator_console_active;
-
- /* properties */
- RNA_def_string(ot->srna, "text", NULL, 0, "Text", "Text to insert at the cursor position");
- RNA_def_int(ot->srna, "current_character", 0, 0, INT_MAX, "Cursor", "The index of the cursor", 0, 10000);
- RNA_def_boolean(ot->srna, "remove_duplicates", 0, "Remove Duplicates", "Remove duplicate items in the history");
+ /* identifiers */
+ ot->name = "History Append";
+ ot->description = "Append history at cursor position";
+ ot->idname = "CONSOLE_OT_history_append";
+
+ /* api callbacks */
+ ot->exec = console_history_append_exec;
+ ot->poll = ED_operator_console_active;
+
+ /* properties */
+ RNA_def_string(ot->srna, "text", NULL, 0, "Text", "Text to insert at the cursor position");
+ RNA_def_int(
+ ot->srna, "current_character", 0, 0, INT_MAX, "Cursor", "The index of the cursor", 0, 10000);
+ RNA_def_boolean(ot->srna,
+ "remove_duplicates",
+ 0,
+ "Remove Duplicates",
+ "Remove duplicate items in the history");
}
-
/* the python exec operator uses this */
static int console_scrollback_append_exec(bContext *C, wmOperator *op)
{
- SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
- ConsoleLine *ci;
+ SpaceConsole *sc = CTX_wm_space_console(C);
+ ARegion *ar = CTX_wm_region(C);
+ ConsoleLine *ci;
- /* own this text in the new line, don't free */
- char *str = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
- int type = RNA_enum_get(op->ptr, "type");
+ /* own this text in the new line, don't free */
+ char *str = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
+ int type = RNA_enum_get(op->ptr, "type");
- console_history_verify(C);
+ console_history_verify(C);
- ci = console_scrollback_add_str(sc, str, 1); /* own the string */
- ci->type = type;
+ ci = console_scrollback_add_str(sc, str, 1); /* own the string */
+ ci->type = type;
- console_scrollback_limit(sc);
+ console_scrollback_limit(sc);
- /* 'ar' 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);
- }
+ /* 'ar' 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);
+ }
- ED_area_tag_redraw(CTX_wm_area(C));
+ ED_area_tag_redraw(CTX_wm_area(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CONSOLE_OT_scrollback_append(wmOperatorType *ot)
{
- /* defined in DNA_space_types.h */
- static const EnumPropertyItem console_line_type_items[] = {
- {CONSOLE_LINE_OUTPUT, "OUTPUT", 0, "Output", ""},
- {CONSOLE_LINE_INPUT, "INPUT", 0, "Input", ""},
- {CONSOLE_LINE_INFO, "INFO", 0, "Information", ""},
- {CONSOLE_LINE_ERROR, "ERROR", 0, "Error", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Scrollback Append";
- ot->description = "Append scrollback text by type";
- ot->idname = "CONSOLE_OT_scrollback_append";
-
- /* api callbacks */
- ot->exec = console_scrollback_append_exec;
- ot->poll = ED_operator_console_active;
-
- /* properties */
- RNA_def_string(ot->srna, "text", NULL, 0, "Text", "Text to insert at the cursor position");
- RNA_def_enum(ot->srna, "type", console_line_type_items, CONSOLE_LINE_OUTPUT, "Type", "Console output type");
+ /* defined in DNA_space_types.h */
+ static const EnumPropertyItem console_line_type_items[] = {
+ {CONSOLE_LINE_OUTPUT, "OUTPUT", 0, "Output", ""},
+ {CONSOLE_LINE_INPUT, "INPUT", 0, "Input", ""},
+ {CONSOLE_LINE_INFO, "INFO", 0, "Information", ""},
+ {CONSOLE_LINE_ERROR, "ERROR", 0, "Error", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Scrollback Append";
+ ot->description = "Append scrollback text by type";
+ ot->idname = "CONSOLE_OT_scrollback_append";
+
+ /* api callbacks */
+ ot->exec = console_scrollback_append_exec;
+ ot->poll = ED_operator_console_active;
+
+ /* properties */
+ RNA_def_string(ot->srna, "text", NULL, 0, "Text", "Text to insert at the cursor position");
+ RNA_def_enum(ot->srna,
+ "type",
+ console_line_type_items,
+ CONSOLE_LINE_OUTPUT,
+ "Type",
+ "Console output type");
}
-
static int console_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceConsole *sc = CTX_wm_space_console(C);
+ SpaceConsole *sc = CTX_wm_space_console(C);
- DynStr *buf_dyn;
- char *buf_str;
+ DynStr *buf_dyn;
+ char *buf_str;
- ConsoleLine *cl;
- int sel[2];
- int offset = 0;
+ ConsoleLine *cl;
+ int sel[2];
+ int offset = 0;
- ConsoleLine cl_dummy = {NULL};
+ ConsoleLine cl_dummy = {NULL};
- if (sc->sel_start == sc->sel_end) {
- return OPERATOR_CANCELLED;
- }
+ if (sc->sel_start == sc->sel_end) {
+ return OPERATOR_CANCELLED;
+ }
- console_scrollback_prompt_begin(sc, &cl_dummy);
+ console_scrollback_prompt_begin(sc, &cl_dummy);
- for (cl = sc->scrollback.first; cl; cl = cl->next) {
- offset += cl->len + 1;
- }
+ for (cl = sc->scrollback.first; cl; cl = cl->next) {
+ offset += cl->len + 1;
+ }
- if (offset == 0) {
- console_scrollback_prompt_end(sc, &cl_dummy);
- return OPERATOR_CANCELLED;
- }
+ if (offset == 0) {
+ console_scrollback_prompt_end(sc, &cl_dummy);
+ return OPERATOR_CANCELLED;
+ }
- buf_dyn = BLI_dynstr_new();
- offset -= 1;
- sel[0] = offset - sc->sel_end;
- sel[1] = offset - sc->sel_start;
+ buf_dyn = BLI_dynstr_new();
+ offset -= 1;
+ sel[0] = offset - sc->sel_end;
+ sel[1] = offset - sc->sel_start;
- for (cl = sc->scrollback.first; cl; cl = cl->next) {
- if (sel[0] <= cl->len && sel[1] >= 0) {
- int sta = max_ii(sel[0], 0);
- int end = min_ii(sel[1], cl->len);
+ for (cl = sc->scrollback.first; cl; cl = cl->next) {
+ if (sel[0] <= cl->len && sel[1] >= 0) {
+ int sta = max_ii(sel[0], 0);
+ int end = min_ii(sel[1], cl->len);
- if (BLI_dynstr_get_len(buf_dyn)) {
- BLI_dynstr_append(buf_dyn, "\n");
- }
+ if (BLI_dynstr_get_len(buf_dyn)) {
+ BLI_dynstr_append(buf_dyn, "\n");
+ }
- BLI_dynstr_nappend(buf_dyn, cl->line + sta, end - sta);
- }
+ BLI_dynstr_nappend(buf_dyn, cl->line + sta, end - sta);
+ }
- sel[0] -= cl->len + 1;
- sel[1] -= cl->len + 1;
- }
+ sel[0] -= cl->len + 1;
+ sel[1] -= cl->len + 1;
+ }
- buf_str = BLI_dynstr_get_cstring(buf_dyn);
+ buf_str = BLI_dynstr_get_cstring(buf_dyn);
- BLI_dynstr_free(buf_dyn);
- WM_clipboard_text_set(buf_str, 0);
+ BLI_dynstr_free(buf_dyn);
+ WM_clipboard_text_set(buf_str, 0);
- MEM_freeN(buf_str);
+ MEM_freeN(buf_str);
- console_scrollback_prompt_end(sc, &cl_dummy);
+ console_scrollback_prompt_end(sc, &cl_dummy);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CONSOLE_OT_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy to Clipboard";
- ot->description = "Copy selected text to clipboard";
- ot->idname = "CONSOLE_OT_copy";
+ /* identifiers */
+ ot->name = "Copy to Clipboard";
+ ot->description = "Copy selected text to clipboard";
+ ot->idname = "CONSOLE_OT_copy";
- /* api callbacks */
- ot->poll = ED_operator_console_active;
- ot->exec = console_copy_exec;
+ /* api callbacks */
+ ot->poll = ED_operator_console_active;
+ ot->exec = console_copy_exec;
- /* properties */
+ /* properties */
}
static int console_paste_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
- ConsoleLine *ci = console_history_verify(C);
- int buf_len;
+ SpaceConsole *sc = CTX_wm_space_console(C);
+ ARegion *ar = CTX_wm_region(C);
+ ConsoleLine *ci = console_history_verify(C);
+ int buf_len;
- char *buf_str = WM_clipboard_text_get(false, &buf_len);
- char *buf_step, *buf_next;
+ char *buf_str = WM_clipboard_text_get(false, &buf_len);
+ char *buf_step, *buf_next;
- if (buf_str == NULL) {
- return OPERATOR_CANCELLED;
- }
+ if (buf_str == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- buf_step = buf_str;
+ buf_step = buf_str;
- while ((buf_next = buf_step) && buf_next[0] != '\0') {
- buf_step = strchr(buf_next, '\n');
- if (buf_step) {
- *buf_step = '\0';
- buf_step++;
- }
+ while ((buf_next = buf_step) && buf_next[0] != '\0') {
+ buf_step = strchr(buf_next, '\n');
+ if (buf_step) {
+ *buf_step = '\0';
+ buf_step++;
+ }
- if (buf_next != buf_str) {
- WM_operator_name_call(C, "CONSOLE_OT_execute", WM_OP_EXEC_DEFAULT, NULL);
- ci = console_history_verify(C);
- }
+ if (buf_next != buf_str) {
+ WM_operator_name_call(C, "CONSOLE_OT_execute", WM_OP_EXEC_DEFAULT, NULL);
+ ci = console_history_verify(C);
+ }
- console_select_offset(sc, console_line_insert(ci, buf_next));
- }
+ console_select_offset(sc, console_line_insert(ci, buf_next));
+ }
- MEM_freeN(buf_str);
+ MEM_freeN(buf_str);
- console_textview_update_rect(sc, ar);
- ED_area_tag_redraw(CTX_wm_area(C));
+ console_textview_update_rect(sc, ar);
+ ED_area_tag_redraw(CTX_wm_area(C));
- console_scroll_bottom(ar);
+ console_scroll_bottom(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void CONSOLE_OT_paste(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Paste from Clipboard";
- ot->description = "Paste text from clipboard";
- ot->idname = "CONSOLE_OT_paste";
+ /* identifiers */
+ ot->name = "Paste from Clipboard";
+ ot->description = "Paste text from clipboard";
+ ot->idname = "CONSOLE_OT_paste";
- /* api callbacks */
- ot->poll = ED_operator_console_active;
- ot->exec = console_paste_exec;
+ /* api callbacks */
+ ot->poll = ED_operator_console_active;
+ ot->exec = console_paste_exec;
- /* properties */
+ /* properties */
}
typedef struct SetConsoleCursor {
- int sel_old[2];
- int sel_init;
+ int sel_old[2];
+ int sel_init;
} SetConsoleCursor;
// TODO, cursor placement without selection
-static void console_cursor_set_to_pos(SpaceConsole *sc, ARegion *ar, SetConsoleCursor *scu, int mval[2], int UNUSED(sel))
+static void console_cursor_set_to_pos(
+ SpaceConsole *sc, ARegion *ar, SetConsoleCursor *scu, int mval[2], int UNUSED(sel))
{
- int pos;
- pos = console_char_pick(sc, ar, mval);
-
- if (scu->sel_init == INT_MAX) {
- scu->sel_init = pos;
- sc->sel_start = sc->sel_end = pos;
- return;
- }
-
- if (pos < scu->sel_init) {
- sc->sel_start = pos;
- sc->sel_end = scu->sel_init;
- }
- else if (pos > sc->sel_start) {
- sc->sel_start = scu->sel_init;
- sc->sel_end = pos;
- }
- else {
- sc->sel_start = sc->sel_end = pos;
- }
+ int pos;
+ pos = console_char_pick(sc, ar, mval);
+
+ if (scu->sel_init == INT_MAX) {
+ scu->sel_init = pos;
+ sc->sel_start = sc->sel_end = pos;
+ return;
+ }
+
+ if (pos < scu->sel_init) {
+ sc->sel_start = pos;
+ sc->sel_end = scu->sel_init;
+ }
+ else if (pos > sc->sel_start) {
+ sc->sel_start = scu->sel_init;
+ sc->sel_end = pos;
+ }
+ else {
+ sc->sel_start = sc->sel_end = 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);
- SetConsoleCursor *scu = op->customdata;
- int mval[2];
- int sel_prev[2];
+ SpaceConsole *sc = CTX_wm_space_console(C);
+ ARegion *ar = CTX_wm_region(C);
+ SetConsoleCursor *scu = op->customdata;
+ int mval[2];
+ int sel_prev[2];
- mval[0] = event->mval[0];
- mval[1] = event->mval[1];
+ mval[0] = event->mval[0];
+ mval[1] = event->mval[1];
- sel_prev[0] = sc->sel_start;
- sel_prev[1] = sc->sel_end;
+ 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, ar, scu, mval, true);
- /* only redraw if the selection changed */
- if (sel_prev[0] != sc->sel_start || sel_prev[1] != sc->sel_end) {
- ED_area_tag_redraw(CTX_wm_area(C));
- }
+ /* only redraw if the selection changed */
+ if (sel_prev[0] != sc->sel_start || sel_prev[1] != sc->sel_end) {
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
}
static void console_cursor_set_exit(bContext *UNUSED(C), wmOperator *op)
{
-// SpaceConsole *sc = CTX_wm_space_console(C);
- SetConsoleCursor *scu = op->customdata;
+ // SpaceConsole *sc = CTX_wm_space_console(C);
+ SetConsoleCursor *scu = op->customdata;
#if 0
- if (txt_has_sel(text)) {
- buffer = txt_sel_to_buf(text);
- WM_clipboard_text_set(buffer, 1);
- MEM_freeN(buffer);
- }
+ if (txt_has_sel(text)) {
+ buffer = txt_sel_to_buf(text);
+ WM_clipboard_text_set(buffer, 1);
+ MEM_freeN(buffer);
+ }
#endif
- MEM_freeN(scu);
+ MEM_freeN(scu);
}
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);
- SetConsoleCursor *scu;
+ SpaceConsole *sc = CTX_wm_space_console(C);
+ // ARegion *ar = CTX_wm_region(C);
+ SetConsoleCursor *scu;
- op->customdata = MEM_callocN(sizeof(SetConsoleCursor), "SetConsoleCursor");
- scu = op->customdata;
+ op->customdata = MEM_callocN(sizeof(SetConsoleCursor), "SetConsoleCursor");
+ scu = op->customdata;
- scu->sel_old[0] = sc->sel_start;
- scu->sel_old[1] = sc->sel_end;
+ scu->sel_old[0] = sc->sel_start;
+ scu->sel_old[1] = sc->sel_end;
- scu->sel_init = INT_MAX;
+ scu->sel_init = INT_MAX;
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
- console_modal_select_apply(C, op, event);
+ console_modal_select_apply(C, op, event);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static int console_modal_select(bContext *C, wmOperator *op, const wmEvent *event)
{
- switch (event->type) {
- case LEFTMOUSE:
- case MIDDLEMOUSE:
- case RIGHTMOUSE:
- if (event->val == KM_RELEASE) {
- console_cursor_set_exit(C, op);
- return OPERATOR_FINISHED;
- }
- break;
- case MOUSEMOVE:
- console_modal_select_apply(C, op, event);
- break;
- }
-
- return OPERATOR_RUNNING_MODAL;
+ switch (event->type) {
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ case RIGHTMOUSE:
+ if (event->val == KM_RELEASE) {
+ console_cursor_set_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ break;
+ case MOUSEMOVE:
+ console_modal_select_apply(C, op, event);
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
static void console_modal_select_cancel(bContext *C, wmOperator *op)
{
- console_cursor_set_exit(C, op);
+ console_cursor_set_exit(C, op);
}
void CONSOLE_OT_select_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Selection";
- ot->idname = "CONSOLE_OT_select_set";
- ot->description = "Set the console selection";
-
- /* api callbacks */
- ot->invoke = console_modal_select_invoke;
- ot->modal = console_modal_select;
- ot->cancel = console_modal_select_cancel;
- ot->poll = ED_operator_console_active;
+ /* identifiers */
+ ot->name = "Set Selection";
+ ot->idname = "CONSOLE_OT_select_set";
+ ot->description = "Set the console selection";
+
+ /* api callbacks */
+ ot->invoke = console_modal_select_invoke;
+ ot->modal = console_modal_select;
+ ot->cancel = console_modal_select_cancel;
+ ot->poll = ED_operator_console_active;
}
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);
+ SpaceConsole *sc = CTX_wm_space_console(C);
+ ARegion *ar = CTX_wm_region(C);
- ConsoleLine cl_dummy = {NULL};
- ConsoleLine *cl;
- int ret = OPERATOR_CANCELLED;
- int pos, offset, n;
+ 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, ar, event->mval);
- console_scrollback_prompt_begin(sc, &cl_dummy);
+ console_scrollback_prompt_begin(sc, &cl_dummy);
- if (console_line_column_from_index(sc, pos, &cl, &offset, &n)) {
- int sel[2] = {n, n};
+ if (console_line_column_from_index(sc, pos, &cl, &offset, &n)) {
+ int sel[2] = {n, n};
- BLI_str_cursor_step_utf8(
- cl->line, cl->len,
- &sel[0], STRCUR_DIR_NEXT,
- STRCUR_JUMP_DELIM, true);
+ BLI_str_cursor_step_utf8(cl->line, cl->len, &sel[0], STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
- BLI_str_cursor_step_utf8(
- cl->line, cl->len,
- &sel[1], STRCUR_DIR_PREV,
- STRCUR_JUMP_DELIM, true);
+ BLI_str_cursor_step_utf8(cl->line, cl->len, &sel[1], STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
- sel[0] = offset - sel[0];
- sel[1] = offset - sel[1];
+ sel[0] = offset - sel[0];
+ sel[1] = offset - sel[1];
- if ((sel[0] != sc->sel_start) || (sel[1] != sc->sel_end)) {
- sc->sel_start = sel[0];
- sc->sel_end = sel[1];
- ED_area_tag_redraw(CTX_wm_area(C));
- ret = OPERATOR_FINISHED;
- }
- }
+ if ((sel[0] != sc->sel_start) || (sel[1] != sc->sel_end)) {
+ sc->sel_start = sel[0];
+ sc->sel_end = sel[1];
+ ED_area_tag_redraw(CTX_wm_area(C));
+ ret = OPERATOR_FINISHED;
+ }
+ }
- console_scrollback_prompt_end(sc, &cl_dummy);
- return ret;
+ console_scrollback_prompt_end(sc, &cl_dummy);
+ return ret;
}
void CONSOLE_OT_select_word(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Word";
- ot->description = "Select word at cursor position";
- ot->idname = "CONSOLE_OT_select_word";
-
- /* api callbacks */
- ot->invoke = console_selectword_invoke;
- ot->poll = ED_operator_console_active;
+ /* identifiers */
+ ot->name = "Select Word";
+ ot->description = "Select word at cursor position";
+ ot->idname = "CONSOLE_OT_select_word";
+
+ /* api callbacks */
+ ot->invoke = console_selectword_invoke;
+ ot->poll = ED_operator_console_active;
}
diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c
index 5d4623e6fe6..2cf8f6c46b9 100644
--- a/source/blender/editors/space_console/space_console.c
+++ b/source/blender/editors/space_console/space_console.c
@@ -40,227 +40,229 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "console_intern.h" // own include
+#include "console_intern.h" // own include
#include "GPU_framebuffer.h"
/* ******************** default callbacks for console space ***************** */
static SpaceLink *console_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
- SpaceConsole *sconsole;
+ ARegion *ar;
+ SpaceConsole *sconsole;
- sconsole = MEM_callocN(sizeof(SpaceConsole), "initconsole");
- sconsole->spacetype = SPACE_CONSOLE;
+ sconsole = MEM_callocN(sizeof(SpaceConsole), "initconsole");
+ sconsole->spacetype = SPACE_CONSOLE;
- sconsole->lheight = 14;
+ sconsole->lheight = 14;
- /* header */
- ar = MEM_callocN(sizeof(ARegion), "header for console");
+ /* header */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_HEADER;
+ ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for text");
- /* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for text");
+ BLI_addtail(&sconsole->regionbase, ar);
+ ar->regiontype = RGN_TYPE_WINDOW;
- BLI_addtail(&sconsole->regionbase, ar);
- ar->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;
- /* 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;
+ /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
+ //ar->v2d.keepzoom = (V2D_KEEPASPECT|V2D_LIMITZOOM);
- /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
- //ar->v2d.keepzoom = (V2D_KEEPASPECT|V2D_LIMITZOOM);
-
- return (SpaceLink *)sconsole;
+ return (SpaceLink *)sconsole;
}
/* not spacelink itself */
static void console_free(SpaceLink *sl)
{
- SpaceConsole *sc = (SpaceConsole *) sl;
+ SpaceConsole *sc = (SpaceConsole *)sl;
- while (sc->scrollback.first) {
- console_scrollback_free(sc, sc->scrollback.first);
- }
+ while (sc->scrollback.first) {
+ console_scrollback_free(sc, sc->scrollback.first);
+ }
- while (sc->history.first) {
- console_history_free(sc, sc->history.first);
- }
+ while (sc->history.first) {
+ console_history_free(sc, sc->history.first);
+ }
}
-
/* spacetype; init callback */
static void console_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
{
-
}
static SpaceLink *console_duplicate(SpaceLink *sl)
{
- SpaceConsole *sconsolen = MEM_dupallocN(sl);
+ SpaceConsole *sconsolen = MEM_dupallocN(sl);
- /* clear or remove stuff from old */
+ /* clear or remove stuff from old */
- /* TODO - duplicate?, then we also need to duplicate the py namespace */
- BLI_listbase_clear(&sconsolen->scrollback);
- BLI_listbase_clear(&sconsolen->history);
+ /* TODO - duplicate?, then we also need to duplicate the py namespace */
+ BLI_listbase_clear(&sconsolen->scrollback);
+ BLI_listbase_clear(&sconsolen->history);
- return (SpaceLink *)sconsolen;
+ return (SpaceLink *)sconsolen;
}
-
-
/* add handlers, stuff you only do once or on area/region changes */
static void console_main_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
- ListBase *lb;
+ 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 = ar->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);
+ /* force it on init, for old files, until it becomes config */
+ ar->v2d.scroll = (V2D_SCROLL_RIGHT);
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->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;
- }
+ /* 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;
+ }
- /* own keymap */
- keymap = WM_keymap_ensure(wm->defaultconf, "Console", SPACE_CONSOLE, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ /* own keymap */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Console", SPACE_CONSOLE, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- /* add drop boxes */
- lb = WM_dropboxmap_find("Console", SPACE_CONSOLE, RGN_TYPE_WINDOW);
+ /* 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(&ar->handlers, lb);
}
/* same as 'text_cursor' */
static void console_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
{
- SpaceText *st = sa->spacedata.first;
- int wmcursor = BC_TEXTEDITCURSOR;
+ SpaceText *st = sa->spacedata.first;
+ int wmcursor = BC_TEXTEDITCURSOR;
- if (st->text && BLI_rcti_isect_pt(&st->txtbar, win->eventstate->x - ar->winrct.xmin, st->txtbar.ymin)) {
- wmcursor = CURSOR_STD;
- }
+ if (st->text &&
+ BLI_rcti_isect_pt(&st->txtbar, win->eventstate->x - ar->winrct.xmin, st->txtbar.ymin)) {
+ wmcursor = CURSOR_STD;
+ }
- WM_cursor_set(win, wmcursor);
+ WM_cursor_set(win, wmcursor);
}
/* ************* dropboxes ************* */
-static bool id_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
+static bool id_drop_poll(bContext *UNUSED(C),
+ wmDrag *drag,
+ const wmEvent *UNUSED(event),
+ const char **UNUSED(tooltip))
{
- return WM_drag_ID(drag, 0) != NULL;
+ return WM_drag_ID(drag, 0) != NULL;
}
static void id_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = WM_drag_ID(drag, 0);
+ ID *id = WM_drag_ID(drag, 0);
- /* copy drag path to properties */
- char *text = RNA_path_full_ID_py(id);
- RNA_string_set(drop->ptr, "text", text);
- MEM_freeN(text);
+ /* copy drag path to properties */
+ char *text = RNA_path_full_ID_py(id);
+ RNA_string_set(drop->ptr, "text", text);
+ MEM_freeN(text);
}
-static bool path_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
+static bool path_drop_poll(bContext *UNUSED(C),
+ wmDrag *drag,
+ const wmEvent *UNUSED(event),
+ const char **UNUSED(tooltip))
{
- return (drag->type == WM_DRAG_PATH);
+ return (drag->type == WM_DRAG_PATH);
}
static void path_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- char pathname[FILE_MAX + 2];
- BLI_snprintf(pathname, sizeof(pathname), "\"%s\"", drag->path);
- RNA_string_set(drop->ptr, "text", pathname);
+ char pathname[FILE_MAX + 2];
+ BLI_snprintf(pathname, sizeof(pathname), "\"%s\"", drag->path);
+ RNA_string_set(drop->ptr, "text", pathname);
}
-
/* this region dropbox definition */
static void console_dropboxes(void)
{
- ListBase *lb = WM_dropboxmap_find("Console", SPACE_CONSOLE, RGN_TYPE_WINDOW);
+ ListBase *lb = WM_dropboxmap_find("Console", SPACE_CONSOLE, RGN_TYPE_WINDOW);
- WM_dropbox_add(lb, "CONSOLE_OT_insert", id_drop_poll, id_drop_copy);
- WM_dropbox_add(lb, "CONSOLE_OT_insert", path_drop_poll, path_drop_copy);
+ WM_dropbox_add(lb, "CONSOLE_OT_insert", id_drop_poll, id_drop_copy);
+ WM_dropbox_add(lb, "CONSOLE_OT_insert", path_drop_poll, path_drop_copy);
}
/* ************* end drop *********** */
static void console_main_region_draw(const bContext *C, ARegion *ar)
{
- /* draw entirely, view changes should be handled here */
- SpaceConsole *sc = CTX_wm_space_console(C);
- View2D *v2d = &ar->v2d;
- View2DScrollers *scrollers;
+ /* draw entirely, view changes should be handled here */
+ SpaceConsole *sc = CTX_wm_space_console(C);
+ View2D *v2d = &ar->v2d;
+ View2DScrollers *scrollers;
- if (BLI_listbase_is_empty(&sc->scrollback)) {
- WM_operator_name_call((bContext *)C, "CONSOLE_OT_banner", WM_OP_EXEC_DEFAULT, NULL);
- }
+ if (BLI_listbase_is_empty(&sc->scrollback)) {
+ WM_operator_name_call((bContext *)C, "CONSOLE_OT_banner", WM_OP_EXEC_DEFAULT, NULL);
+ }
- /* clear and setup matrix */
- UI_ThemeClearColor(TH_BACK);
- GPU_clear(GPU_COLOR_BIT);
+ /* clear and setup matrix */
+ UI_ThemeClearColor(TH_BACK);
+ GPU_clear(GPU_COLOR_BIT);
- /* worlks best with no view2d matrix set */
- UI_view2d_view_ortho(v2d);
+ /* worlks best with no view2d matrix set */
+ UI_view2d_view_ortho(v2d);
- /* data... */
+ /* data... */
- console_history_verify(C); /* make sure we have some command line */
- console_textview_main(sc, ar);
+ console_history_verify(C); /* make sure we have some command line */
+ console_textview_main(sc, ar);
- /* reset view matrix */
- UI_view2d_view_restore(C);
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
- /* scrollers */
- scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_GRID_CLAMP);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
+ /* scrollers */
+ scrollers = UI_view2d_scrollers_calc(
+ C, v2d, NULL, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_GRID_CLAMP);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
}
static void console_operatortypes(void)
{
- /* console_ops.c */
- WM_operatortype_append(CONSOLE_OT_move);
- WM_operatortype_append(CONSOLE_OT_delete);
- WM_operatortype_append(CONSOLE_OT_insert);
-
- WM_operatortype_append(CONSOLE_OT_indent);
- WM_operatortype_append(CONSOLE_OT_unindent);
-
- /* for use by python only */
- WM_operatortype_append(CONSOLE_OT_history_append);
- WM_operatortype_append(CONSOLE_OT_scrollback_append);
-
- WM_operatortype_append(CONSOLE_OT_clear);
- WM_operatortype_append(CONSOLE_OT_clear_line);
- WM_operatortype_append(CONSOLE_OT_history_cycle);
- WM_operatortype_append(CONSOLE_OT_copy);
- WM_operatortype_append(CONSOLE_OT_paste);
- WM_operatortype_append(CONSOLE_OT_select_set);
- WM_operatortype_append(CONSOLE_OT_select_word);
+ /* console_ops.c */
+ WM_operatortype_append(CONSOLE_OT_move);
+ WM_operatortype_append(CONSOLE_OT_delete);
+ WM_operatortype_append(CONSOLE_OT_insert);
+
+ WM_operatortype_append(CONSOLE_OT_indent);
+ WM_operatortype_append(CONSOLE_OT_unindent);
+
+ /* for use by python only */
+ WM_operatortype_append(CONSOLE_OT_history_append);
+ WM_operatortype_append(CONSOLE_OT_scrollback_append);
+
+ WM_operatortype_append(CONSOLE_OT_clear);
+ WM_operatortype_append(CONSOLE_OT_clear_line);
+ WM_operatortype_append(CONSOLE_OT_history_cycle);
+ WM_operatortype_append(CONSOLE_OT_copy);
+ WM_operatortype_append(CONSOLE_OT_paste);
+ WM_operatortype_append(CONSOLE_OT_select_set);
+ WM_operatortype_append(CONSOLE_OT_select_word);
}
static void console_keymap(struct wmKeyConfig *keyconf)
{
- WM_keymap_ensure(keyconf, "Console", SPACE_CONSOLE, 0);
+ WM_keymap_ensure(keyconf, "Console", SPACE_CONSOLE, 0);
}
/****************** header region ******************/
@@ -268,84 +270,79 @@ static void console_keymap(struct wmKeyConfig *keyconf)
/* add handlers, stuff you only do once or on area/region changes */
static void console_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
- ED_region_header_init(ar);
+ ED_region_header_init(ar);
}
static void console_header_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_header(C, ar);
+ ED_region_header(C, ar);
}
static void console_main_region_listener(
- wmWindow *UNUSED(win), ScrArea *sa, ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+ wmWindow *UNUSED(win), ScrArea *sa, ARegion *ar, wmNotifier *wmn, const Scene *UNUSED(scene))
{
- // SpaceInfo *sinfo = sa->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)) {
- /* we've modified the geometry (font size), re-calculate rect */
- console_textview_update_rect(wmn->reference, ar);
- ED_region_tag_redraw(ar);
- }
- }
- else {
- /* generic redraw request */
- ED_region_tag_redraw(ar);
- }
- }
- break;
- }
- }
+ // SpaceInfo *sinfo = sa->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)) {
+ /* we've modified the geometry (font size), re-calculate rect */
+ console_textview_update_rect(wmn->reference, ar);
+ ED_region_tag_redraw(ar);
+ }
+ }
+ else {
+ /* generic redraw request */
+ ED_region_tag_redraw(ar);
+ }
+ }
+ break;
+ }
+ }
}
/* only called once, from space/spacetypes.c */
void ED_spacetype_console(void)
{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype console");
- ARegionType *art;
-
- st->spaceid = SPACE_CONSOLE;
- strncpy(st->name, "Console", BKE_ST_MAXNAME);
-
- st->new = console_new;
- st->free = console_free;
- st->init = console_init;
- st->duplicate = console_duplicate;
- st->operatortypes = console_operatortypes;
- st->keymap = console_keymap;
- st->dropboxes = console_dropboxes;
-
- /* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype console region");
- art->regionid = RGN_TYPE_WINDOW;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
+ SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype console");
+ ARegionType *art;
- art->init = console_main_region_init;
- art->draw = console_main_region_draw;
- art->cursor = console_cursor;
- art->listener = console_main_region_listener;
+ st->spaceid = SPACE_CONSOLE;
+ strncpy(st->name, "Console", BKE_ST_MAXNAME);
+ st->new = console_new;
+ st->free = console_free;
+ st->init = console_init;
+ st->duplicate = console_duplicate;
+ st->operatortypes = console_operatortypes;
+ st->keymap = console_keymap;
+ st->dropboxes = console_dropboxes;
+ /* regions: main window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype console region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
- BLI_addhead(&st->regiontypes, art);
+ art->init = console_main_region_init;
+ art->draw = console_main_region_draw;
+ art->cursor = console_cursor;
+ art->listener = console_main_region_listener;
- /* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype console region");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
+ BLI_addhead(&st->regiontypes, art);
- art->init = console_header_region_init;
- art->draw = console_header_region_draw;
+ /* regions: header */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype console region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = HEADERY;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
- BLI_addhead(&st->regiontypes, art);
+ art->init = console_header_region_init;
+ art->draw = console_header_region_draw;
+ BLI_addhead(&st->regiontypes, art);
- BKE_spacetype_register(st);
+ BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_file/CMakeLists.txt b/source/blender/editors/space_file/CMakeLists.txt
index a92ed62cae2..6bf975b98e0 100644
--- a/source/blender/editors/space_file/CMakeLists.txt
+++ b/source/blender/editors/space_file/CMakeLists.txt
@@ -16,85 +16,85 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenfont
- ../../blenkernel
- ../../blenlib
- ../../blenloader
- ../../blentranslation
- ../../imbuf
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../render/extern/include
- ../../windowmanager
- ../../../../intern/atomic
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenfont
+ ../../blenkernel
+ ../../blenlib
+ ../../blenloader
+ ../../blentranslation
+ ../../imbuf
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../render/extern/include
+ ../../windowmanager
+ ../../../../intern/atomic
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- file_draw.c
- file_ops.c
- file_panels.c
- file_utils.c
- filelist.c
- filesel.c
- fsmenu.c
- space_file.c
-
- file_intern.h
- filelist.h
- fsmenu.h
+ file_draw.c
+ file_ops.c
+ file_panels.c
+ file_utils.c
+ filelist.c
+ filesel.c
+ fsmenu.c
+ space_file.c
+
+ file_intern.h
+ filelist.h
+ fsmenu.h
)
set(LIB
)
if(WITH_HEADLESS)
- add_definitions(-DWITH_HEADLESS)
+ add_definitions(-DWITH_HEADLESS)
endif()
if(WITH_IMAGE_OPENEXR)
- add_definitions(-DWITH_OPENEXR)
+ add_definitions(-DWITH_OPENEXR)
endif()
if(WITH_OPENIMAGEIO)
- add_definitions(-DWITH_OPENIMAGEIO)
+ add_definitions(-DWITH_OPENIMAGEIO)
endif()
if(WITH_IMAGE_TIFF)
- add_definitions(-DWITH_TIFF)
+ add_definitions(-DWITH_TIFF)
endif()
if(WITH_IMAGE_OPENJPEG)
- add_definitions(-DWITH_OPENJPEG)
+ add_definitions(-DWITH_OPENJPEG)
endif()
if(WITH_IMAGE_DDS)
- add_definitions(-DWITH_DDS)
+ add_definitions(-DWITH_DDS)
endif()
if(WITH_IMAGE_CINEON)
- add_definitions(-DWITH_CINEON)
+ add_definitions(-DWITH_CINEON)
endif()
if(WITH_IMAGE_HDR)
- add_definitions(-DWITH_HDR)
+ add_definitions(-DWITH_HDR)
endif()
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
add_definitions(${GL_DEFINITIONS})
if(WITH_FREESTYLE)
- add_definitions(-DWITH_FREESTYLE)
+ add_definitions(-DWITH_FREESTYLE)
endif()
blender_add_lib(bf_editor_space_file "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index c0aa03abece..87560436d52 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -21,7 +21,6 @@
* \ingroup spfile
*/
-
#include <math.h>
#include <string.h>
#include <errno.h>
@@ -69,13 +68,13 @@
#include "filelist.h"
-#include "file_intern.h" // own include
+#include "file_intern.h" // own include
/* Dummy helper - we need dynamic tooltips here. */
static char *file_draw_tooltip_func(bContext *UNUSED(C), void *argN, const char *UNUSED(tip))
{
- char *dyn_tooltip = argN;
- return BLI_strdup(dyn_tooltip);
+ char *dyn_tooltip = argN;
+ return BLI_strdup(dyn_tooltip);
}
/* Note: This function uses pixelspace (0, 0, winx, winy), not view2d.
@@ -93,673 +92,804 @@ static char *file_draw_tooltip_func(bContext *UNUSED(C), void *argN, const char
*/
void file_draw_buttons(const bContext *C, ARegion *ar)
{
- /* Button layout. */
- const int max_x = ar->winx - 10;
- const int line1_y = ar->winy - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN);
- const int line2_y = line1_y - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN);
- const int input_minw = 20;
- const int btn_h = UI_UNIT_Y;
- const int btn_fn_w = UI_UNIT_X;
- const int btn_minw = 80;
- const int btn_margin = 20;
- const int separator = 4;
-
- /* Additional locals. */
- char uiblockstr[32];
- int loadbutton;
- int fnumbuttons;
- int min_x = 10;
- int chan_offs = 0;
- int available_w = max_x - min_x;
- int line1_w = available_w;
- int line2_w = available_w;
-
- uiBut *but;
- uiBlock *block;
- SpaceFile *sfile = CTX_wm_space_file(C);
- FileSelectParams *params = ED_fileselect_get_params(sfile);
- ARegion *artmp;
- const bool is_browse_only = (sfile->op == NULL);
-
- /* Initialize UI block. */
- BLI_snprintf(uiblockstr, sizeof(uiblockstr), "win %p", (void *)ar);
- block = UI_block_begin(C, ar, uiblockstr, UI_EMBOSS);
-
- /* exception to make space for collapsed region icon */
- for (artmp = CTX_wm_area(C)->regionbase.first; artmp; artmp = artmp->next) {
- if (artmp->regiontype == RGN_TYPE_TOOLS && artmp->flag & RGN_FLAG_HIDDEN) {
- chan_offs = 16;
- min_x += chan_offs;
- available_w -= chan_offs;
- }
- }
-
- /* Is there enough space for the execute / cancel buttons? */
-
-
- if (is_browse_only) {
- loadbutton = 0;
- }
- else {
- const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- loadbutton = UI_fontstyle_string_width(fstyle, params->title) + btn_margin;
- CLAMP_MIN(loadbutton, btn_minw);
- if (available_w <= loadbutton + separator + input_minw) {
- loadbutton = 0;
- }
- }
-
- if (loadbutton) {
- line1_w -= (loadbutton + separator);
- line2_w = line1_w;
- }
-
- /* Is there enough space for file number increment/decrement buttons? */
- fnumbuttons = 2 * btn_fn_w;
- if (!loadbutton || line2_w <= fnumbuttons + separator + input_minw) {
- fnumbuttons = 0;
- }
- else {
- line2_w -= (fnumbuttons + separator);
- }
-
- /* Text input fields for directory and file. */
- if (available_w > 0) {
- const struct FileDirEntry *file = sfile->files ? filelist_file(sfile->files, params->active_file) : NULL;
- int overwrite_alert = file_draw_check_exists(sfile);
- const bool is_active_dir = file && (file->typeflag & FILE_TYPE_FOLDER);
-
- /* callbacks for operator check functions */
- UI_block_func_set(block, file_draw_check_cb, NULL, NULL);
-
- but = uiDefBut(block, UI_BTYPE_TEXT, -1, "",
- min_x, line1_y, line1_w - chan_offs, btn_h,
- params->dir, 0.0, (float)FILE_MAX, 0, 0,
- TIP_("File path"));
- UI_but_func_complete_set(but, autocomplete_directory, NULL);
- UI_but_flag_enable(but, UI_BUT_NO_UTF8);
- UI_but_flag_disable(but, UI_BUT_UNDO);
- UI_but_funcN_set(but, file_directory_enter_handle, NULL, but);
-
- /* TODO, directory editing is non-functional while a library is loaded
- * until this is properly supported just disable it. */
- if (sfile->files && filelist_lib(sfile->files))
- UI_but_flag_enable(but, UI_BUT_DISABLED);
-
- if ((params->flag & FILE_DIRSEL_ONLY) == 0) {
- but = uiDefBut(block, UI_BTYPE_TEXT, -1, "",
- min_x, line2_y, line2_w - chan_offs, btn_h,
- is_active_dir ? (char *)"" : params->file,
- 0.0, (float)FILE_MAXFILE, 0, 0,
- TIP_(overwrite_alert ? N_("File name, overwrite existing") : N_("File name")));
- UI_but_func_complete_set(but, autocomplete_file, NULL);
- UI_but_flag_enable(but, UI_BUT_NO_UTF8);
- UI_but_flag_disable(but, UI_BUT_UNDO);
- /* silly workaround calling NFunc to ensure this does not get called
- * immediate ui_apply_but_func but only after button deactivates */
- UI_but_funcN_set(but, file_filename_enter_handle, NULL, but);
-
- /* check if this overrides a file and if the operator option is used */
- if (overwrite_alert) {
- UI_but_flag_enable(but, UI_BUT_REDALERT);
- }
- }
-
- /* clear func */
- UI_block_func_set(block, NULL, NULL, NULL);
- }
-
- /* Filename number increment / decrement buttons. */
- if (fnumbuttons && (params->flag & FILE_DIRSEL_ONLY) == 0) {
- UI_block_align_begin(block);
- but = uiDefIconButO(block, UI_BTYPE_BUT, "FILE_OT_filenum", 0, ICON_REMOVE,
- min_x + line2_w + separator - chan_offs, line2_y,
- btn_fn_w, btn_h,
- TIP_("Decrement the filename number"));
- RNA_int_set(UI_but_operator_ptr_get(but), "increment", -1);
-
- but = uiDefIconButO(block, UI_BTYPE_BUT, "FILE_OT_filenum", 0, ICON_ADD,
- min_x + line2_w + separator + btn_fn_w - chan_offs, line2_y,
- btn_fn_w, btn_h,
- TIP_("Increment the filename number"));
- RNA_int_set(UI_but_operator_ptr_get(but), "increment", 1);
- UI_block_align_end(block);
- }
-
- /* Execute / cancel buttons. */
- if (loadbutton) {
- const struct FileDirEntry *file = sfile->files ? filelist_file(sfile->files, params->active_file) : NULL;
- char const *str_exec;
-
- if (file && FILENAME_IS_PARENT(file->relpath)) {
- str_exec = IFACE_("Parent Directory");
- }
- else if (file && file->typeflag & FILE_TYPE_DIR) {
- str_exec = IFACE_("Open Directory");
- }
- else {
- str_exec = params->title; /* params->title is already translated! */
- }
-
- but = uiDefButO(
- block, UI_BTYPE_BUT, "FILE_OT_execute", WM_OP_EXEC_REGION_WIN, str_exec,
- max_x - loadbutton, line1_y, loadbutton, btn_h, "");
- /* Just a display hint. */
- UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT);
-
- uiDefButO(block, UI_BTYPE_BUT, "FILE_OT_cancel", WM_OP_EXEC_REGION_WIN, IFACE_("Cancel"),
- max_x - loadbutton, line2_y, loadbutton, btn_h, "");
- }
-
- UI_block_end(C, block);
- UI_block_draw(C, block);
+ /* Button layout. */
+ const int max_x = ar->winx - 10;
+ const int line1_y = ar->winy - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN);
+ const int line2_y = line1_y - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN);
+ const int input_minw = 20;
+ const int btn_h = UI_UNIT_Y;
+ const int btn_fn_w = UI_UNIT_X;
+ const int btn_minw = 80;
+ const int btn_margin = 20;
+ const int separator = 4;
+
+ /* Additional locals. */
+ char uiblockstr[32];
+ int loadbutton;
+ int fnumbuttons;
+ int min_x = 10;
+ int chan_offs = 0;
+ int available_w = max_x - min_x;
+ int line1_w = available_w;
+ int line2_w = available_w;
+
+ uiBut *but;
+ uiBlock *block;
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelectParams *params = ED_fileselect_get_params(sfile);
+ ARegion *artmp;
+ const bool is_browse_only = (sfile->op == NULL);
+
+ /* Initialize UI block. */
+ BLI_snprintf(uiblockstr, sizeof(uiblockstr), "win %p", (void *)ar);
+ block = UI_block_begin(C, ar, uiblockstr, UI_EMBOSS);
+
+ /* exception to make space for collapsed region icon */
+ for (artmp = CTX_wm_area(C)->regionbase.first; artmp; artmp = artmp->next) {
+ if (artmp->regiontype == RGN_TYPE_TOOLS && artmp->flag & RGN_FLAG_HIDDEN) {
+ chan_offs = 16;
+ min_x += chan_offs;
+ available_w -= chan_offs;
+ }
+ }
+
+ /* Is there enough space for the execute / cancel buttons? */
+
+ if (is_browse_only) {
+ loadbutton = 0;
+ }
+ else {
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ loadbutton = UI_fontstyle_string_width(fstyle, params->title) + btn_margin;
+ CLAMP_MIN(loadbutton, btn_minw);
+ if (available_w <= loadbutton + separator + input_minw) {
+ loadbutton = 0;
+ }
+ }
+
+ if (loadbutton) {
+ line1_w -= (loadbutton + separator);
+ line2_w = line1_w;
+ }
+
+ /* Is there enough space for file number increment/decrement buttons? */
+ fnumbuttons = 2 * btn_fn_w;
+ if (!loadbutton || line2_w <= fnumbuttons + separator + input_minw) {
+ fnumbuttons = 0;
+ }
+ else {
+ line2_w -= (fnumbuttons + separator);
+ }
+
+ /* Text input fields for directory and file. */
+ if (available_w > 0) {
+ const struct FileDirEntry *file = sfile->files ?
+ filelist_file(sfile->files, params->active_file) :
+ NULL;
+ int overwrite_alert = file_draw_check_exists(sfile);
+ const bool is_active_dir = file && (file->typeflag & FILE_TYPE_FOLDER);
+
+ /* callbacks for operator check functions */
+ UI_block_func_set(block, file_draw_check_cb, NULL, NULL);
+
+ but = uiDefBut(block,
+ UI_BTYPE_TEXT,
+ -1,
+ "",
+ min_x,
+ line1_y,
+ line1_w - chan_offs,
+ btn_h,
+ params->dir,
+ 0.0,
+ (float)FILE_MAX,
+ 0,
+ 0,
+ TIP_("File path"));
+ UI_but_func_complete_set(but, autocomplete_directory, NULL);
+ UI_but_flag_enable(but, UI_BUT_NO_UTF8);
+ UI_but_flag_disable(but, UI_BUT_UNDO);
+ UI_but_funcN_set(but, file_directory_enter_handle, NULL, but);
+
+ /* TODO, directory editing is non-functional while a library is loaded
+ * until this is properly supported just disable it. */
+ if (sfile->files && filelist_lib(sfile->files))
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+
+ if ((params->flag & FILE_DIRSEL_ONLY) == 0) {
+ but = uiDefBut(
+ block,
+ UI_BTYPE_TEXT,
+ -1,
+ "",
+ min_x,
+ line2_y,
+ line2_w - chan_offs,
+ btn_h,
+ is_active_dir ? (char *)"" : params->file,
+ 0.0,
+ (float)FILE_MAXFILE,
+ 0,
+ 0,
+ TIP_(overwrite_alert ? N_("File name, overwrite existing") : N_("File name")));
+ UI_but_func_complete_set(but, autocomplete_file, NULL);
+ UI_but_flag_enable(but, UI_BUT_NO_UTF8);
+ UI_but_flag_disable(but, UI_BUT_UNDO);
+ /* silly workaround calling NFunc to ensure this does not get called
+ * immediate ui_apply_but_func but only after button deactivates */
+ UI_but_funcN_set(but, file_filename_enter_handle, NULL, but);
+
+ /* check if this overrides a file and if the operator option is used */
+ if (overwrite_alert) {
+ UI_but_flag_enable(but, UI_BUT_REDALERT);
+ }
+ }
+
+ /* clear func */
+ UI_block_func_set(block, NULL, NULL, NULL);
+ }
+
+ /* Filename number increment / decrement buttons. */
+ if (fnumbuttons && (params->flag & FILE_DIRSEL_ONLY) == 0) {
+ UI_block_align_begin(block);
+ but = uiDefIconButO(block,
+ UI_BTYPE_BUT,
+ "FILE_OT_filenum",
+ 0,
+ ICON_REMOVE,
+ min_x + line2_w + separator - chan_offs,
+ line2_y,
+ btn_fn_w,
+ btn_h,
+ TIP_("Decrement the filename number"));
+ RNA_int_set(UI_but_operator_ptr_get(but), "increment", -1);
+
+ but = uiDefIconButO(block,
+ UI_BTYPE_BUT,
+ "FILE_OT_filenum",
+ 0,
+ ICON_ADD,
+ min_x + line2_w + separator + btn_fn_w - chan_offs,
+ line2_y,
+ btn_fn_w,
+ btn_h,
+ TIP_("Increment the filename number"));
+ RNA_int_set(UI_but_operator_ptr_get(but), "increment", 1);
+ UI_block_align_end(block);
+ }
+
+ /* Execute / cancel buttons. */
+ if (loadbutton) {
+ const struct FileDirEntry *file = sfile->files ?
+ filelist_file(sfile->files, params->active_file) :
+ NULL;
+ char const *str_exec;
+
+ if (file && FILENAME_IS_PARENT(file->relpath)) {
+ str_exec = IFACE_("Parent Directory");
+ }
+ else if (file && file->typeflag & FILE_TYPE_DIR) {
+ str_exec = IFACE_("Open Directory");
+ }
+ else {
+ str_exec = params->title; /* params->title is already translated! */
+ }
+
+ but = uiDefButO(block,
+ UI_BTYPE_BUT,
+ "FILE_OT_execute",
+ WM_OP_EXEC_REGION_WIN,
+ str_exec,
+ max_x - loadbutton,
+ line1_y,
+ loadbutton,
+ btn_h,
+ "");
+ /* Just a display hint. */
+ UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT);
+
+ uiDefButO(block,
+ UI_BTYPE_BUT,
+ "FILE_OT_cancel",
+ WM_OP_EXEC_REGION_WIN,
+ IFACE_("Cancel"),
+ max_x - loadbutton,
+ line2_y,
+ loadbutton,
+ btn_h,
+ "");
+ }
+
+ UI_block_end(C, block);
+ UI_block_draw(C, block);
}
-
static void draw_tile(int sx, int sy, int width, int height, int colorid, int shade)
{
- float color[4];
- UI_GetThemeColorShade4fv(colorid, shade, color);
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_aa(true, (float)sx, (float)(sy - height), (float)(sx + width), (float)sy, 5.0f, color);
+ float color[4];
+ UI_GetThemeColorShade4fv(colorid, shade, color);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_aa(
+ 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)
{
- uiBut *but;
- int x, y;
- // float alpha = 1.0f;
+ uiBut *but;
+ int x, y;
+ // float alpha = 1.0f;
- x = sx;
- y = sy - height;
+ x = sx;
+ y = sy - height;
- /*if (icon == ICON_FILE_BLANK) alpha = 0.375f;*/
+ /*if (icon == ICON_FILE_BLANK) alpha = 0.375f;*/
- but = uiDefIconBut(block, UI_BTYPE_LABEL, 0, icon, x, y, width, height, NULL, 0.0f, 0.0f, 0.0f, 0.0f, NULL);
- UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path));
+ but = uiDefIconBut(
+ block, UI_BTYPE_LABEL, 0, icon, x, y, width, height, NULL, 0.0f, 0.0f, 0.0f, 0.0f, NULL);
+ UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path));
- if (drag) {
- /* path is no more static, cannot give it directly to but... */
- UI_but_drag_set_path(but, BLI_strdup(path), true);
- }
+ if (drag) {
+ /* path is no more static, cannot give it directly to but... */
+ UI_but_drag_set_path(but, BLI_strdup(path), true);
+ }
}
-
-static void file_draw_string(
- int sx, int sy, const char *string, float width, int height, eFontStyle_Align align,
- const uchar col[4])
+static void file_draw_string(int sx,
+ int sy,
+ const char *string,
+ float width,
+ int height,
+ eFontStyle_Align align,
+ const uchar col[4])
{
- uiStyle *style;
- uiFontStyle fs;
- rcti rect;
- char fname[FILE_MAXFILE];
-
- if (string[0] == '\0') {
- return;
- }
-
- style = UI_style_get();
- fs = style->widgetlabel;
-
- BLI_strncpy(fname, string, FILE_MAXFILE);
- UI_text_clip_middle_ex(&fs, fname, width, UI_DPI_ICON_SIZE, sizeof(fname), '\0');
-
- /* no text clipping needed, UI_fontstyle_draw does it but is a bit too strict
- * (for buttons it works) */
- rect.xmin = sx;
- rect.xmax = (int)(sx + ceil(width + 5.0f / UI_DPI_FAC));
- rect.ymin = sy - height;
- rect.ymax = sy;
-
- UI_fontstyle_draw(
- &fs, &rect, fname, col,
- &(struct uiFontStyleDraw_Params) { .align = align, });
+ uiStyle *style;
+ uiFontStyle fs;
+ rcti rect;
+ char fname[FILE_MAXFILE];
+
+ if (string[0] == '\0') {
+ return;
+ }
+
+ style = UI_style_get();
+ fs = style->widgetlabel;
+
+ BLI_strncpy(fname, string, FILE_MAXFILE);
+ UI_text_clip_middle_ex(&fs, fname, width, UI_DPI_ICON_SIZE, sizeof(fname), '\0');
+
+ /* no text clipping needed, UI_fontstyle_draw does it but is a bit too strict
+ * (for buttons it works) */
+ rect.xmin = sx;
+ rect.xmax = (int)(sx + ceil(width + 5.0f / UI_DPI_FAC));
+ rect.ymin = sy - height;
+ rect.ymax = sy;
+
+ UI_fontstyle_draw(&fs,
+ &rect,
+ fname,
+ col,
+ &(struct uiFontStyleDraw_Params){
+ .align = align,
+ });
}
void file_calc_previews(const bContext *C, ARegion *ar)
{
- SpaceFile *sfile = CTX_wm_space_file(C);
- View2D *v2d = &ar->v2d;
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ View2D *v2d = &ar->v2d;
- ED_fileselect_init_layout(sfile, ar);
- UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height);
+ ED_fileselect_init_layout(sfile, ar);
+ UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height);
}
-static void file_draw_preview(
- uiBlock *block, const char *path, int sx, int sy, const float icon_aspect,
- ImBuf *imb, const int icon, FileLayout *layout, const bool is_icon, const int typeflags, const bool drag)
+static void file_draw_preview(uiBlock *block,
+ const char *path,
+ int sx,
+ int sy,
+ const float icon_aspect,
+ ImBuf *imb,
+ const int icon,
+ FileLayout *layout,
+ const bool is_icon,
+ const int typeflags,
+ const bool drag)
{
- uiBut *but;
- float fx, fy;
- float dx, dy;
- int xco, yco;
- float ui_imbx, ui_imby;
- float scaledx, scaledy;
- float scale;
- int ex, ey;
- bool use_dropshadow = !is_icon && (typeflags & FILE_TYPE_IMAGE);
- float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
-
- BLI_assert(imb != NULL);
-
- ui_imbx = imb->x * UI_DPI_FAC;
- ui_imby = imb->y * UI_DPI_FAC;
- /* Unlike thumbnails, icons are not scaled up. */
- if (((ui_imbx > layout->prv_w) || (ui_imby > layout->prv_h)) ||
- (!is_icon && ((ui_imbx < layout->prv_w) || (ui_imby < layout->prv_h))))
- {
- if (imb->x > imb->y) {
- scaledx = (float)layout->prv_w;
- scaledy = ((float)imb->y / (float)imb->x) * layout->prv_w;
- scale = scaledx / imb->x;
- }
- else {
- scaledy = (float)layout->prv_h;
- scaledx = ((float)imb->x / (float)imb->y) * layout->prv_h;
- scale = scaledy / imb->y;
- }
- }
- else {
- scaledx = ui_imbx;
- scaledy = ui_imby;
- scale = UI_DPI_FAC;
- }
-
- ex = (int)scaledx;
- ey = (int)scaledy;
- fx = ((float)layout->prv_w - (float)ex) / 2.0f;
- fy = ((float)layout->prv_h - (float)ey) / 2.0f;
- dx = (fx + 0.5f + layout->prv_border_x);
- dy = (fy + 0.5f - layout->prv_border_y);
- xco = sx + (int)dx;
- yco = sy - layout->prv_h + (int)dy;
-
- /* shadow */
- if (use_dropshadow) {
- UI_draw_box_shadow(220, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
- }
-
- GPU_blend(true);
-
- /* the image */
- if (!is_icon && typeflags & FILE_TYPE_FTFONT) {
- UI_GetThemeColor4fv(TH_TEXT, col);
- }
-
- if (!is_icon && typeflags & FILE_TYPE_BLENDERLIB) {
- /* Datablock preview images use premultiplied alpha. */
- GPU_blend_set_func_separate(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- }
-
- IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
- immDrawPixelsTexScaled(&state, (float)xco, (float)yco, imb->x, imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, imb->rect,
- scale, scale, 1.0f, 1.0f, col);
-
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- if (icon) {
- UI_icon_draw_aspect((float)xco, (float)yco, icon, icon_aspect, 1.0f, NULL);
- }
-
- /* border */
- if (use_dropshadow) {
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
- imm_draw_box_wire_2d(pos, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
- immUnbindProgram();
- }
-
- but = uiDefBut(block, UI_BTYPE_LABEL, 0, "", xco, yco, ex, ey, NULL, 0.0, 0.0, 0, 0, NULL);
- UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path));
-
- /* dragregion */
- if (drag) {
- /* path is no more static, cannot give it directly to but... */
- UI_but_drag_set_image(but, BLI_strdup(path), icon, imb, scale, true);
- }
-
- GPU_blend(false);
+ uiBut *but;
+ float fx, fy;
+ float dx, dy;
+ int xco, yco;
+ float ui_imbx, ui_imby;
+ float scaledx, scaledy;
+ float scale;
+ int ex, ey;
+ bool use_dropshadow = !is_icon && (typeflags & FILE_TYPE_IMAGE);
+ float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+
+ BLI_assert(imb != NULL);
+
+ ui_imbx = imb->x * UI_DPI_FAC;
+ ui_imby = imb->y * UI_DPI_FAC;
+ /* Unlike thumbnails, icons are not scaled up. */
+ if (((ui_imbx > layout->prv_w) || (ui_imby > layout->prv_h)) ||
+ (!is_icon && ((ui_imbx < layout->prv_w) || (ui_imby < layout->prv_h)))) {
+ if (imb->x > imb->y) {
+ scaledx = (float)layout->prv_w;
+ scaledy = ((float)imb->y / (float)imb->x) * layout->prv_w;
+ scale = scaledx / imb->x;
+ }
+ else {
+ scaledy = (float)layout->prv_h;
+ scaledx = ((float)imb->x / (float)imb->y) * layout->prv_h;
+ scale = scaledy / imb->y;
+ }
+ }
+ else {
+ scaledx = ui_imbx;
+ scaledy = ui_imby;
+ scale = UI_DPI_FAC;
+ }
+
+ ex = (int)scaledx;
+ ey = (int)scaledy;
+ fx = ((float)layout->prv_w - (float)ex) / 2.0f;
+ fy = ((float)layout->prv_h - (float)ey) / 2.0f;
+ dx = (fx + 0.5f + layout->prv_border_x);
+ dy = (fy + 0.5f - layout->prv_border_y);
+ xco = sx + (int)dx;
+ yco = sy - layout->prv_h + (int)dy;
+
+ /* shadow */
+ if (use_dropshadow) {
+ UI_draw_box_shadow(220, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
+ }
+
+ GPU_blend(true);
+
+ /* the image */
+ if (!is_icon && typeflags & FILE_TYPE_FTFONT) {
+ UI_GetThemeColor4fv(TH_TEXT, col);
+ }
+
+ if (!is_icon && typeflags & FILE_TYPE_BLENDERLIB) {
+ /* Datablock preview images use premultiplied alpha. */
+ GPU_blend_set_func_separate(
+ GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ }
+
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTexScaled(&state,
+ (float)xco,
+ (float)yco,
+ imb->x,
+ imb->y,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ GL_NEAREST,
+ imb->rect,
+ scale,
+ scale,
+ 1.0f,
+ 1.0f,
+ col);
+
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ if (icon) {
+ UI_icon_draw_aspect((float)xco, (float)yco, icon, icon_aspect, 1.0f, NULL);
+ }
+
+ /* border */
+ if (use_dropshadow) {
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
+ imm_draw_box_wire_2d(pos, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
+ immUnbindProgram();
+ }
+
+ but = uiDefBut(block, UI_BTYPE_LABEL, 0, "", xco, yco, ex, ey, NULL, 0.0, 0.0, 0, 0, NULL);
+ UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path));
+
+ /* dragregion */
+ if (drag) {
+ /* path is no more static, cannot give it directly to but... */
+ UI_but_drag_set_image(but, BLI_strdup(path), icon, imb, scale, true);
+ }
+
+ GPU_blend(false);
}
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);
-
- const char *blendfile_path = BKE_main_blendfile_path(bmain);
- BLI_make_file_string(blendfile_path, 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);
-
- if (!STREQ(orgname, newname)) {
- if (!BLI_exists(newname)) {
- errno = 0;
- if ((BLI_rename(orgname, newname) != 0) ||
- !BLI_exists(newname))
- {
- WM_reportf(RPT_ERROR,
- "Could not rename: %s",
- errno ? strerror(errno) : "unknown error");
- WM_report_banner_show();
- }
- else {
- /* If rename is sucessfull, scroll to newly renamed entry. */
- BLI_strncpy(sfile->params->renamefile, filename, sizeof(sfile->params->renamefile));
- sfile->params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_PENDING;
-
- if (sfile->smoothscroll_timer != NULL) {
- WM_event_remove_timer(CTX_wm_manager(C), 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;
- }
-
- /* to make sure we show what is on disk */
- ED_fileselect_clear(wm, sa, sfile);
- }
-
- ED_region_tag_redraw(ar);
- }
+ 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);
+
+ const char *blendfile_path = BKE_main_blendfile_path(bmain);
+ BLI_make_file_string(blendfile_path, 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);
+
+ if (!STREQ(orgname, newname)) {
+ if (!BLI_exists(newname)) {
+ errno = 0;
+ if ((BLI_rename(orgname, newname) != 0) || !BLI_exists(newname)) {
+ WM_reportf(RPT_ERROR, "Could not rename: %s", errno ? strerror(errno) : "unknown error");
+ WM_report_banner_show();
+ }
+ else {
+ /* If rename is sucessfull, scroll to newly renamed entry. */
+ BLI_strncpy(sfile->params->renamefile, filename, sizeof(sfile->params->renamefile));
+ sfile->params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_PENDING;
+
+ if (sfile->smoothscroll_timer != NULL) {
+ WM_event_remove_timer(CTX_wm_manager(C), 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;
+ }
+
+ /* to make sure we show what is on disk */
+ ED_fileselect_clear(wm, sa, sfile);
+ }
+
+ ED_region_tag_redraw(ar);
+ }
}
-
static void draw_background(FileLayout *layout, View2D *v2d)
{
- int i;
- int sy;
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColorShade(TH_BACK, -7);
-
- /* alternating flat shade background */
- for (i = 0; (i <= layout->rows); i += 2) {
- sy = (int)v2d->cur.ymax - i * (layout->tile_h + 2 * layout->tile_border_y) - layout->tile_border_y;
-
- immRectf(pos, v2d->cur.xmin, (float)sy, v2d->cur.xmax, (float)(sy + layout->tile_h + 2 * layout->tile_border_y));
- }
-
- immUnbindProgram();
+ int i;
+ int sy;
+
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShade(TH_BACK, -7);
+
+ /* alternating flat shade background */
+ for (i = 0; (i <= layout->rows); i += 2) {
+ sy = (int)v2d->cur.ymax - i * (layout->tile_h + 2 * layout->tile_border_y) -
+ layout->tile_border_y;
+
+ immRectf(pos,
+ v2d->cur.xmin,
+ (float)sy,
+ v2d->cur.xmax,
+ (float)(sy + layout->tile_h + 2 * layout->tile_border_y));
+ }
+
+ immUnbindProgram();
}
static void draw_dividers(FileLayout *layout, View2D *v2d)
{
- /* vertical column dividers */
-
- const int step = (layout->tile_w + 2 * layout->tile_border_x);
-
- unsigned int vertex_len = 0;
- int sx = (int)v2d->tot.xmin;
- while (sx < v2d->cur.xmax) {
- sx += step;
- vertex_len += 4; /* vertex_count = 2 points per line * 2 lines per divider */
- }
-
- if (vertex_len > 0) {
- int v1[2], v2[2];
- unsigned char col_hi[3], col_lo[3];
-
- UI_GetThemeColorShade3ubv(TH_BACK, 30, col_hi);
- UI_GetThemeColorShade3ubv(TH_BACK, -30, col_lo);
-
- v1[1] = v2d->cur.ymax - layout->tile_border_y;
- v2[1] = v2d->cur.ymin;
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- immBegin(GPU_PRIM_LINES, vertex_len);
-
- sx = (int)v2d->tot.xmin;
- while (sx < v2d->cur.xmax) {
- sx += step;
-
- v1[0] = v2[0] = sx;
- immAttrSkip(color);
- immVertex2iv(pos, v1);
- immAttr3ubv(color, col_lo);
- immVertex2iv(pos, v2);
-
- v1[0] = v2[0] = sx + 1;
- immAttrSkip(color);
- immVertex2iv(pos, v1);
- immAttr3ubv(color, col_hi);
- immVertex2iv(pos, v2);
- }
-
- immEnd();
- immUnbindProgram();
- }
+ /* vertical column dividers */
+
+ const int step = (layout->tile_w + 2 * layout->tile_border_x);
+
+ unsigned int vertex_len = 0;
+ int sx = (int)v2d->tot.xmin;
+ while (sx < v2d->cur.xmax) {
+ sx += step;
+ vertex_len += 4; /* vertex_count = 2 points per line * 2 lines per divider */
+ }
+
+ if (vertex_len > 0) {
+ int v1[2], v2[2];
+ unsigned char col_hi[3], col_lo[3];
+
+ UI_GetThemeColorShade3ubv(TH_BACK, 30, col_hi);
+ UI_GetThemeColorShade3ubv(TH_BACK, -30, col_lo);
+
+ v1[1] = v2d->cur.ymax - layout->tile_border_y;
+ v2[1] = v2d->cur.ymin;
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ uint color = GPU_vertformat_attr_add(
+ format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GPU_PRIM_LINES, vertex_len);
+
+ sx = (int)v2d->tot.xmin;
+ while (sx < v2d->cur.xmax) {
+ sx += step;
+
+ v1[0] = v2[0] = sx;
+ immAttrSkip(color);
+ immVertex2iv(pos, v1);
+ immAttr3ubv(color, col_lo);
+ immVertex2iv(pos, v2);
+
+ v1[0] = v2[0] = sx + 1;
+ immAttrSkip(color);
+ immVertex2iv(pos, v1);
+ immAttr3ubv(color, col_hi);
+ immVertex2iv(pos, v2);
+ }
+
+ immEnd();
+ immUnbindProgram();
+ }
}
void file_draw_list(const bContext *C, ARegion *ar)
{
- 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;
- 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);
- int numfiles;
- int numfiles_layout;
- int sx, sy;
- int offset;
- int textwidth, textheight;
- int i;
- bool is_icon;
- eFontStyle_Align align;
- bool do_drag;
- int column_space = 0.6f * UI_UNIT_X;
- unsigned char text_col[4];
- const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size);
- const bool update_stat_strings = small_size != SMALL_SIZE_CHECK(layout->curr_size);
- const float thumb_icon_aspect = sqrtf(64.0f / (float)(params->thumbnail_size));
-
- numfiles = filelist_files_ensure(files);
-
- if (params->display != FILE_IMGDISPLAY) {
-
- draw_background(layout, v2d);
-
- draw_dividers(layout, v2d);
- }
-
- offset = ED_fileselect_layout_offset(layout, (int)ar->v2d.cur.xmin, (int)-ar->v2d.cur.ymax);
- if (offset < 0) offset = 0;
-
- numfiles_layout = ED_fileselect_layout_numfiles(layout, ar);
-
- /* adjust, so the next row is already drawn when scrolling */
- if (layout->flag & FILE_LAYOUT_HOR) {
- numfiles_layout += layout->rows;
- }
- else {
- numfiles_layout += layout->columns;
- }
-
- filelist_file_cache_slidingwindow_set(files, numfiles_layout);
-
- textwidth = (FILE_IMGDISPLAY == params->display) ? layout->tile_w : (int)layout->column_widths[COLUMN_NAME];
- textheight = (int)(layout->textheight * 3.0 / 2.0 + 0.5);
-
- align = (FILE_IMGDISPLAY == params->display) ? UI_STYLE_TEXT_CENTER : UI_STYLE_TEXT_LEFT;
-
- if (numfiles > 0) {
- const bool success = filelist_file_cache_block(files, min_ii(offset + (numfiles_layout / 2), numfiles - 1));
- BLI_assert(success);
- UNUSED_VARS_NDEBUG(success);
-
- filelist_cache_previews_update(files);
-
- /* Handle preview timer here, since it's filelist_file_cache_block() and filelist_cache_previews_update()
- * which controls previews task. */
- {
- const bool previews_running = filelist_cache_previews_running(files);
-// printf("%s: preview task: %d\n", __func__, previews_running);
- if (previews_running && !sfile->previews_timer) {
- sfile->previews_timer = WM_event_add_timer_notifier(CTX_wm_manager(C), CTX_wm_window(C),
- NC_SPACE | ND_SPACE_FILE_PREVIEW, 0.01);
- }
- if (!previews_running && sfile->previews_timer) {
- /* Preview is not running, no need to keep generating update events! */
-// printf("%s: Inactive preview task, sleeping!\n", __func__);
- WM_event_remove_timer_notifier(CTX_wm_manager(C), CTX_wm_window(C), sfile->previews_timer);
- sfile->previews_timer = NULL;
- }
- }
- }
-
- BLF_batch_draw_begin();
-
- for (i = offset; (i < numfiles) && (i < offset + numfiles_layout); i++) {
- unsigned int file_selflag;
- char path[FILE_MAX_LIBEXTRA];
- ED_fileselect_layout_tilepos(layout, i, &sx, &sy);
- sx += (int)(v2d->tot.xmin + 0.1f * UI_UNIT_X);
- sy = (int)(v2d->tot.ymax - sy);
-
- file = filelist_file(files, i);
- file_selflag = filelist_entry_select_get(sfile->files, file, CHECK_ALL);
-
- BLI_join_dirfile(path, sizeof(path), root, file->relpath);
-
- if (!(file_selflag & FILE_SEL_EDITING)) {
- if ((params->highlight_file == i) || (file_selflag & FILE_SEL_HIGHLIGHTED) ||
- (file_selflag & FILE_SEL_SELECTED))
- {
- int colorid = (file_selflag & FILE_SEL_SELECTED) ? TH_HILITE : TH_BACK;
- int shade = (params->highlight_file == i) || (file_selflag & FILE_SEL_HIGHLIGHTED) ? 35 : 0;
-
- BLI_assert(i == 0 || !FILENAME_IS_CURRPAR(file->relpath));
-
- draw_tile(sx, sy - 1, layout->tile_w + 4, sfile->layout->tile_h + layout->tile_border_y, colorid, shade);
- }
- }
- UI_draw_roundbox_corner_set(UI_CNR_NONE);
-
- /* don't drag parent or refresh items */
- do_drag = !(FILENAME_IS_CURRPAR(file->relpath));
-
- if (FILE_IMGDISPLAY == params->display) {
- const int icon = filelist_geticon(files, i, false);
- is_icon = 0;
- imb = filelist_getimage(files, i);
- if (!imb) {
- imb = filelist_geticon_image(files, i);
- is_icon = 1;
- }
-
- file_draw_preview(block, path, sx, sy, thumb_icon_aspect,
- imb, icon, layout, is_icon, file->typeflag, do_drag);
- }
- else {
- file_draw_icon(block, path, sx, sy - (UI_UNIT_Y / 6), filelist_geticon(files, i, true),
- ICON_DEFAULT_WIDTH_SCALE, ICON_DEFAULT_HEIGHT_SCALE, do_drag);
- sx += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X;
- }
-
- UI_GetThemeColor4ubv(TH_TEXT, text_col);
-
- if (file_selflag & FILE_SEL_EDITING) {
- uiBut *but;
- short width;
-
- if (params->display == FILE_SHORTDISPLAY) {
- width = layout->tile_w - (ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X);
- }
- else if (params->display == FILE_LONGDISPLAY) {
- width = layout->column_widths[COLUMN_NAME] + (column_space * 3.5f);
- }
- else {
- BLI_assert(params->display == FILE_IMGDISPLAY);
- width = textwidth;
- }
-
- but = uiDefBut(block, UI_BTYPE_TEXT, 1, "", sx, sy - layout->tile_h - 0.15f * UI_UNIT_X,
- width, textheight, sfile->params->renamefile, 1.0f,
- (float)sizeof(sfile->params->renamefile), 0, 0, "");
- 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)) {
- file_selflag = filelist_entry_select_set(
- sfile->files, file, FILE_SEL_REMOVE, FILE_SEL_EDITING, CHECK_ALL);
- }
- }
-
- if (!(file_selflag& FILE_SEL_EDITING)) {
- int tpos = (FILE_IMGDISPLAY == params->display) ? sy - layout->tile_h + layout->textheight : sy;
- file_draw_string(sx + 1, tpos, file->name, (float)textwidth, textheight, align, text_col);
- }
-
- sx += (int)layout->column_widths[COLUMN_NAME] + column_space;
- if (params->display == FILE_SHORTDISPLAY) {
- if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) ||
- !(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB)))
- {
- if ((file->entry->size_str[0] == '\0') || update_stat_strings) {
- BLI_filelist_entry_size_to_string(NULL, file->entry->size, small_size, file->entry->size_str);
- }
- file_draw_string(
- sx, sy, file->entry->size_str, layout->column_widths[COLUMN_SIZE], layout->tile_h,
- align, text_col);
- }
- sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
- }
- else if (params->display == FILE_LONGDISPLAY) {
- if (!(file->typeflag & FILE_TYPE_BLENDERLIB) && !FILENAME_IS_CURRPAR(file->relpath)) {
- if ((file->entry->date_str[0] == '\0') || update_stat_strings) {
- BLI_filelist_entry_datetime_to_string(
- NULL, file->entry->time, small_size, file->entry->time_str, file->entry->date_str);
- }
- file_draw_string(
- sx, sy, file->entry->date_str, layout->column_widths[COLUMN_DATE], layout->tile_h,
- align, text_col);
- sx += (int)layout->column_widths[COLUMN_DATE] + column_space;
- file_draw_string(
- sx, sy, file->entry->time_str, layout->column_widths[COLUMN_TIME], layout->tile_h,
- align, text_col);
- sx += (int)layout->column_widths[COLUMN_TIME] + column_space;
- }
- else {
- sx += (int)layout->column_widths[COLUMN_DATE] + column_space;
- sx += (int)layout->column_widths[COLUMN_TIME] + column_space;
- }
-
- if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) ||
- !(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB)))
- {
- if ((file->entry->size_str[0] == '\0') || update_stat_strings) {
- BLI_filelist_entry_size_to_string(NULL, file->entry->size, small_size, file->entry->size_str);
- }
- file_draw_string(
- sx, sy, file->entry->size_str, layout->column_widths[COLUMN_SIZE], layout->tile_h,
- align, text_col);
- }
- sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
- }
- }
-
- BLF_batch_draw_end();
-
- UI_block_end(C, block);
- UI_block_draw(C, block);
-
- layout->curr_size = params->thumbnail_size;
+ 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;
+ 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);
+ int numfiles;
+ int numfiles_layout;
+ int sx, sy;
+ int offset;
+ int textwidth, textheight;
+ int i;
+ bool is_icon;
+ eFontStyle_Align align;
+ bool do_drag;
+ int column_space = 0.6f * UI_UNIT_X;
+ unsigned char text_col[4];
+ const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size);
+ const bool update_stat_strings = small_size != SMALL_SIZE_CHECK(layout->curr_size);
+ const float thumb_icon_aspect = sqrtf(64.0f / (float)(params->thumbnail_size));
+
+ numfiles = filelist_files_ensure(files);
+
+ if (params->display != FILE_IMGDISPLAY) {
+
+ draw_background(layout, v2d);
+
+ draw_dividers(layout, v2d);
+ }
+
+ offset = ED_fileselect_layout_offset(layout, (int)ar->v2d.cur.xmin, (int)-ar->v2d.cur.ymax);
+ if (offset < 0)
+ offset = 0;
+
+ numfiles_layout = ED_fileselect_layout_numfiles(layout, ar);
+
+ /* adjust, so the next row is already drawn when scrolling */
+ if (layout->flag & FILE_LAYOUT_HOR) {
+ numfiles_layout += layout->rows;
+ }
+ else {
+ numfiles_layout += layout->columns;
+ }
+
+ filelist_file_cache_slidingwindow_set(files, numfiles_layout);
+
+ textwidth = (FILE_IMGDISPLAY == params->display) ? layout->tile_w :
+ (int)layout->column_widths[COLUMN_NAME];
+ textheight = (int)(layout->textheight * 3.0 / 2.0 + 0.5);
+
+ align = (FILE_IMGDISPLAY == params->display) ? UI_STYLE_TEXT_CENTER : UI_STYLE_TEXT_LEFT;
+
+ if (numfiles > 0) {
+ const bool success = filelist_file_cache_block(
+ files, min_ii(offset + (numfiles_layout / 2), numfiles - 1));
+ BLI_assert(success);
+ UNUSED_VARS_NDEBUG(success);
+
+ filelist_cache_previews_update(files);
+
+ /* Handle preview timer here, since it's filelist_file_cache_block() and filelist_cache_previews_update()
+ * which controls previews task. */
+ {
+ const bool previews_running = filelist_cache_previews_running(files);
+ // printf("%s: preview task: %d\n", __func__, previews_running);
+ if (previews_running && !sfile->previews_timer) {
+ sfile->previews_timer = WM_event_add_timer_notifier(
+ CTX_wm_manager(C), CTX_wm_window(C), NC_SPACE | ND_SPACE_FILE_PREVIEW, 0.01);
+ }
+ if (!previews_running && sfile->previews_timer) {
+ /* Preview is not running, no need to keep generating update events! */
+ // printf("%s: Inactive preview task, sleeping!\n", __func__);
+ WM_event_remove_timer_notifier(CTX_wm_manager(C), CTX_wm_window(C), sfile->previews_timer);
+ sfile->previews_timer = NULL;
+ }
+ }
+ }
+
+ BLF_batch_draw_begin();
+
+ for (i = offset; (i < numfiles) && (i < offset + numfiles_layout); i++) {
+ unsigned int file_selflag;
+ char path[FILE_MAX_LIBEXTRA];
+ ED_fileselect_layout_tilepos(layout, i, &sx, &sy);
+ sx += (int)(v2d->tot.xmin + 0.1f * UI_UNIT_X);
+ sy = (int)(v2d->tot.ymax - sy);
+
+ file = filelist_file(files, i);
+ file_selflag = filelist_entry_select_get(sfile->files, file, CHECK_ALL);
+
+ BLI_join_dirfile(path, sizeof(path), root, file->relpath);
+
+ if (!(file_selflag & FILE_SEL_EDITING)) {
+ if ((params->highlight_file == i) || (file_selflag & FILE_SEL_HIGHLIGHTED) ||
+ (file_selflag & FILE_SEL_SELECTED)) {
+ int colorid = (file_selflag & FILE_SEL_SELECTED) ? TH_HILITE : TH_BACK;
+ int shade = (params->highlight_file == i) || (file_selflag & FILE_SEL_HIGHLIGHTED) ? 35 :
+ 0;
+
+ BLI_assert(i == 0 || !FILENAME_IS_CURRPAR(file->relpath));
+
+ draw_tile(sx,
+ sy - 1,
+ layout->tile_w + 4,
+ sfile->layout->tile_h + layout->tile_border_y,
+ colorid,
+ shade);
+ }
+ }
+ UI_draw_roundbox_corner_set(UI_CNR_NONE);
+
+ /* don't drag parent or refresh items */
+ do_drag = !(FILENAME_IS_CURRPAR(file->relpath));
+
+ if (FILE_IMGDISPLAY == params->display) {
+ const int icon = filelist_geticon(files, i, false);
+ is_icon = 0;
+ imb = filelist_getimage(files, i);
+ if (!imb) {
+ imb = filelist_geticon_image(files, i);
+ is_icon = 1;
+ }
+
+ file_draw_preview(block,
+ path,
+ sx,
+ sy,
+ thumb_icon_aspect,
+ imb,
+ icon,
+ layout,
+ is_icon,
+ file->typeflag,
+ do_drag);
+ }
+ else {
+ file_draw_icon(block,
+ path,
+ sx,
+ sy - (UI_UNIT_Y / 6),
+ filelist_geticon(files, i, true),
+ ICON_DEFAULT_WIDTH_SCALE,
+ ICON_DEFAULT_HEIGHT_SCALE,
+ do_drag);
+ sx += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X;
+ }
+
+ UI_GetThemeColor4ubv(TH_TEXT, text_col);
+
+ if (file_selflag & FILE_SEL_EDITING) {
+ uiBut *but;
+ short width;
+
+ if (params->display == FILE_SHORTDISPLAY) {
+ width = layout->tile_w - (ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X);
+ }
+ else if (params->display == FILE_LONGDISPLAY) {
+ width = layout->column_widths[COLUMN_NAME] + (column_space * 3.5f);
+ }
+ else {
+ BLI_assert(params->display == FILE_IMGDISPLAY);
+ width = textwidth;
+ }
+
+ but = uiDefBut(block,
+ UI_BTYPE_TEXT,
+ 1,
+ "",
+ sx,
+ sy - layout->tile_h - 0.15f * UI_UNIT_X,
+ width,
+ textheight,
+ sfile->params->renamefile,
+ 1.0f,
+ (float)sizeof(sfile->params->renamefile),
+ 0,
+ 0,
+ "");
+ 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)) {
+ file_selflag = filelist_entry_select_set(
+ sfile->files, file, FILE_SEL_REMOVE, FILE_SEL_EDITING, CHECK_ALL);
+ }
+ }
+
+ if (!(file_selflag & FILE_SEL_EDITING)) {
+ int tpos = (FILE_IMGDISPLAY == params->display) ? sy - layout->tile_h + layout->textheight :
+ sy;
+ file_draw_string(sx + 1, tpos, file->name, (float)textwidth, textheight, align, text_col);
+ }
+
+ sx += (int)layout->column_widths[COLUMN_NAME] + column_space;
+ if (params->display == FILE_SHORTDISPLAY) {
+ if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) ||
+ !(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB))) {
+ if ((file->entry->size_str[0] == '\0') || update_stat_strings) {
+ BLI_filelist_entry_size_to_string(
+ NULL, file->entry->size, small_size, file->entry->size_str);
+ }
+ file_draw_string(sx,
+ sy,
+ file->entry->size_str,
+ layout->column_widths[COLUMN_SIZE],
+ layout->tile_h,
+ align,
+ text_col);
+ }
+ sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
+ }
+ else if (params->display == FILE_LONGDISPLAY) {
+ if (!(file->typeflag & FILE_TYPE_BLENDERLIB) && !FILENAME_IS_CURRPAR(file->relpath)) {
+ if ((file->entry->date_str[0] == '\0') || update_stat_strings) {
+ BLI_filelist_entry_datetime_to_string(
+ NULL, file->entry->time, small_size, file->entry->time_str, file->entry->date_str);
+ }
+ file_draw_string(sx,
+ sy,
+ file->entry->date_str,
+ layout->column_widths[COLUMN_DATE],
+ layout->tile_h,
+ align,
+ text_col);
+ sx += (int)layout->column_widths[COLUMN_DATE] + column_space;
+ file_draw_string(sx,
+ sy,
+ file->entry->time_str,
+ layout->column_widths[COLUMN_TIME],
+ layout->tile_h,
+ align,
+ text_col);
+ sx += (int)layout->column_widths[COLUMN_TIME] + column_space;
+ }
+ else {
+ sx += (int)layout->column_widths[COLUMN_DATE] + column_space;
+ sx += (int)layout->column_widths[COLUMN_TIME] + column_space;
+ }
+
+ if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) ||
+ !(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB))) {
+ if ((file->entry->size_str[0] == '\0') || update_stat_strings) {
+ BLI_filelist_entry_size_to_string(
+ NULL, file->entry->size, small_size, file->entry->size_str);
+ }
+ file_draw_string(sx,
+ sy,
+ file->entry->size_str,
+ layout->column_widths[COLUMN_SIZE],
+ layout->tile_h,
+ align,
+ text_col);
+ }
+ sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
+ }
+ }
+
+ BLF_batch_draw_end();
+
+ UI_block_end(C, block);
+ UI_block_draw(C, block);
+
+ layout->curr_size = params->thumbnail_size;
}
diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h
index 46e30e556d1..bad25511dd5 100644
--- a/source/blender/editors/space_file/file_intern.h
+++ b/source/blender/editors/space_file/file_intern.h
@@ -42,7 +42,7 @@ struct ARegion *file_tools_region(struct ScrArea *sa);
#define IMASEL_BUTTONS_HEIGHT (UI_UNIT_Y * 2)
#define IMASEL_BUTTONS_MARGIN (UI_UNIT_Y / 6)
-#define SMALL_SIZE_CHECK(_size) ((_size) < 64) /* Related to FileSelectParams.thumbnail_size. */
+#define SMALL_SIZE_CHECK(_size) ((_size) < 64) /* Related to FileSelectParams.thumbnail_size. */
void file_draw_buttons(const bContext *C, ARegion *ar);
void file_calc_previews(const bContext *C, ARegion *ar);
@@ -57,10 +57,10 @@ struct wmOperator;
struct wmOperatorType;
typedef enum WalkSelectDirection {
- FILE_SELECT_WALK_UP,
- FILE_SELECT_WALK_DOWN,
- FILE_SELECT_WALK_LEFT,
- FILE_SELECT_WALK_RIGHT,
+ FILE_SELECT_WALK_UP,
+ FILE_SELECT_WALK_DOWN,
+ FILE_SELECT_WALK_LEFT,
+ FILE_SELECT_WALK_RIGHT,
} WalkSelectDirections;
void FILE_OT_highlight(struct wmOperatorType *ot);
@@ -103,7 +103,10 @@ 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);
void file_sfile_filepath_set(struct SpaceFile *sfile, const char *filepath);
-void file_sfile_to_operator_ex(bContext *C, struct wmOperator *op, struct SpaceFile *sfile, char *filepath);
+void file_sfile_to_operator_ex(bContext *C,
+ struct wmOperator *op,
+ struct SpaceFile *sfile,
+ char *filepath);
void file_sfile_to_operator(bContext *C, struct wmOperator *op, struct SpaceFile *sfile);
void file_operator_to_sfile(bContext *C, struct SpaceFile *sfile, struct wmOperator *op);
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index 482774c8131..073b6d0f487 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -69,161 +69,158 @@
/* ---------- FILE SELECTION ------------ */
static FileSelection find_file_mouse_rect(SpaceFile *sfile, ARegion *ar, const rcti *rect_region)
{
- FileSelection sel;
+ FileSelection sel;
- View2D *v2d = &ar->v2d;
- rcti rect_view;
- rctf rect_view_fl;
- rctf rect_region_fl;
+ View2D *v2d = &ar->v2d;
+ rcti rect_view;
+ rctf rect_view_fl;
+ rctf rect_region_fl;
- BLI_rctf_rcti_copy(&rect_region_fl, rect_region);
+ BLI_rctf_rcti_copy(&rect_region_fl, rect_region);
- UI_view2d_region_to_view_rctf(v2d, &rect_region_fl, &rect_view_fl);
+ UI_view2d_region_to_view_rctf(v2d, &rect_region_fl, &rect_view_fl);
- BLI_rcti_init(&rect_view,
- (int)(v2d->tot.xmin + rect_view_fl.xmin),
- (int)(v2d->tot.xmin + rect_view_fl.xmax),
- (int)(v2d->tot.ymax - rect_view_fl.ymin),
- (int)(v2d->tot.ymax - rect_view_fl.ymax));
+ BLI_rcti_init(&rect_view,
+ (int)(v2d->tot.xmin + rect_view_fl.xmin),
+ (int)(v2d->tot.xmin + rect_view_fl.xmax),
+ (int)(v2d->tot.ymax - rect_view_fl.ymin),
+ (int)(v2d->tot.ymax - rect_view_fl.ymax));
- sel = ED_fileselect_layout_offset_rect(sfile->layout, &rect_view);
+ sel = ED_fileselect_layout_offset_rect(sfile->layout, &rect_view);
- return sel;
+ return sel;
}
static void file_deselect_all(SpaceFile *sfile, unsigned int flag)
{
- FileSelection sel;
- sel.first = 0;
- sel.last = filelist_files_ensure(sfile->files) - 1;
+ FileSelection sel;
+ sel.first = 0;
+ sel.last = filelist_files_ensure(sfile->files) - 1;
- filelist_entries_select_index_range_set(sfile->files, &sel, FILE_SEL_REMOVE, flag, CHECK_ALL);
+ filelist_entries_select_index_range_set(sfile->files, &sel, FILE_SEL_REMOVE, flag, CHECK_ALL);
}
typedef enum FileSelect {
- FILE_SELECT_NOTHING = 0,
- FILE_SELECT_DIR = 1,
- FILE_SELECT_FILE = 2,
+ FILE_SELECT_NOTHING = 0,
+ FILE_SELECT_DIR = 1,
+ FILE_SELECT_FILE = 2,
} FileSelect;
static void clamp_to_filelist(int numfiles, FileSelection *sel)
{
- /* box select before the first file */
- if ( (sel->first < 0) && (sel->last >= 0) ) {
- sel->first = 0;
- }
- /* don't select if everything is outside filelist */
- if ( (sel->first >= numfiles) && ((sel->last < 0) || (sel->last >= numfiles)) ) {
- sel->first = -1;
- sel->last = -1;
- }
-
- /* fix if last file invalid */
- if ( (sel->first > 0) && (sel->last < 0) )
- sel->last = numfiles - 1;
-
- /* clamp */
- if ( (sel->first >= numfiles) ) {
- sel->first = numfiles - 1;
- }
- if ( (sel->last >= numfiles) ) {
- sel->last = numfiles - 1;
- }
+ /* box select before the first file */
+ if ((sel->first < 0) && (sel->last >= 0)) {
+ sel->first = 0;
+ }
+ /* don't select if everything is outside filelist */
+ if ((sel->first >= numfiles) && ((sel->last < 0) || (sel->last >= numfiles))) {
+ sel->first = -1;
+ sel->last = -1;
+ }
+
+ /* fix if last file invalid */
+ if ((sel->first > 0) && (sel->last < 0))
+ sel->last = numfiles - 1;
+
+ /* clamp */
+ if ((sel->first >= numfiles)) {
+ sel->first = numfiles - 1;
+ }
+ if ((sel->last >= numfiles)) {
+ sel->last = numfiles - 1;
+ }
}
static FileSelection file_selection_get(bContext *C, const rcti *rect, bool fill)
{
- ARegion *ar = 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);
- if (!((sel.first == -1) && (sel.last == -1)) ) {
- clamp_to_filelist(numfiles, &sel);
- }
-
-
- /* if desired, fill the selection up from the last selected file to the current one */
- if (fill && (sel.last >= 0) && (sel.last < numfiles) ) {
- int f;
- /* Try to find a smaller-index selected item. */
- for (f = sel.last; f >= 0; f--) {
- if (filelist_entry_select_index_get(sfile->files, f, CHECK_ALL) )
- break;
- }
- if (f >= 0) {
- sel.first = f + 1;
- }
- /* If none found, try to find a higher-index selected item. */
- else {
- for (f = sel.first; f < numfiles; f++) {
- if (filelist_entry_select_index_get(sfile->files, f, CHECK_ALL) )
- break;
- }
- if (f < numfiles) {
- sel.last = f - 1;
- }
- }
- }
- return sel;
+ ARegion *ar = 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);
+ if (!((sel.first == -1) && (sel.last == -1))) {
+ clamp_to_filelist(numfiles, &sel);
+ }
+
+ /* if desired, fill the selection up from the last selected file to the current one */
+ if (fill && (sel.last >= 0) && (sel.last < numfiles)) {
+ int f;
+ /* Try to find a smaller-index selected item. */
+ for (f = sel.last; f >= 0; f--) {
+ if (filelist_entry_select_index_get(sfile->files, f, CHECK_ALL))
+ break;
+ }
+ if (f >= 0) {
+ sel.first = f + 1;
+ }
+ /* If none found, try to find a higher-index selected item. */
+ else {
+ for (f = sel.first; f < numfiles; f++) {
+ if (filelist_entry_select_index_get(sfile->files, f, CHECK_ALL))
+ break;
+ }
+ if (f < numfiles) {
+ sel.last = f - 1;
+ }
+ }
+ }
+ return sel;
}
static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen)
{
- Main *bmain = CTX_data_main(C);
- FileSelect retval = FILE_SELECT_NOTHING;
- SpaceFile *sfile = CTX_wm_space_file(C);
- FileSelectParams *params = ED_fileselect_get_params(sfile);
- int numfiles = filelist_files_ensure(sfile->files);
- const FileDirEntry *file;
-
- /* make the selected file active */
- if ((selected_idx >= 0) &&
- (selected_idx < numfiles) &&
- (file = filelist_file(sfile->files, selected_idx)))
- {
- params->highlight_file = selected_idx;
- params->active_file = selected_idx;
-
- if (file->typeflag & FILE_TYPE_DIR) {
- const bool is_parent_dir = FILENAME_IS_PARENT(file->relpath);
-
- if (do_diropen == false) {
- params->file[0] = '\0';
- retval = FILE_SELECT_DIR;
- }
- /* the path is too long and we are not going up! */
- else if (!is_parent_dir && strlen(params->dir) + strlen(file->relpath) >= FILE_MAX) {
- // XXX error("Path too long, cannot enter this directory");
- }
- else {
- if (is_parent_dir) {
- /* avoids /../../ */
- BLI_parent_dir(params->dir);
-
- if (params->recursion_level > 1) {
- /* Disable 'dirtree' recursion when going up in tree. */
- params->recursion_level = 0;
- filelist_setrecursion(sfile->files, params->recursion_level);
- }
- }
- else {
- BLI_cleanup_dir(BKE_main_blendfile_path(bmain), params->dir);
- strcat(params->dir, file->relpath);
- BLI_add_slash(params->dir);
- }
-
- ED_file_change_dir(C);
- retval = FILE_SELECT_DIR;
- }
- }
- else {
- retval = FILE_SELECT_FILE;
- }
- fileselect_file_set(sfile, selected_idx);
- }
- return retval;
+ Main *bmain = CTX_data_main(C);
+ FileSelect retval = FILE_SELECT_NOTHING;
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelectParams *params = ED_fileselect_get_params(sfile);
+ int numfiles = filelist_files_ensure(sfile->files);
+ const FileDirEntry *file;
+
+ /* make the selected file active */
+ if ((selected_idx >= 0) && (selected_idx < numfiles) &&
+ (file = filelist_file(sfile->files, selected_idx))) {
+ params->highlight_file = selected_idx;
+ params->active_file = selected_idx;
+
+ if (file->typeflag & FILE_TYPE_DIR) {
+ const bool is_parent_dir = FILENAME_IS_PARENT(file->relpath);
+
+ if (do_diropen == false) {
+ params->file[0] = '\0';
+ retval = FILE_SELECT_DIR;
+ }
+ /* the path is too long and we are not going up! */
+ else if (!is_parent_dir && strlen(params->dir) + strlen(file->relpath) >= FILE_MAX) {
+ // XXX error("Path too long, cannot enter this directory");
+ }
+ else {
+ if (is_parent_dir) {
+ /* avoids /../../ */
+ BLI_parent_dir(params->dir);
+
+ if (params->recursion_level > 1) {
+ /* Disable 'dirtree' recursion when going up in tree. */
+ params->recursion_level = 0;
+ filelist_setrecursion(sfile->files, params->recursion_level);
+ }
+ }
+ else {
+ BLI_cleanup_dir(BKE_main_blendfile_path(bmain), params->dir);
+ strcat(params->dir, file->relpath);
+ BLI_add_slash(params->dir);
+ }
+
+ ED_file_change_dir(C);
+ retval = FILE_SELECT_DIR;
+ }
+ }
+ else {
+ retval = FILE_SELECT_FILE;
+ }
+ fileselect_file_set(sfile, selected_idx);
+ }
+ return retval;
}
/**
@@ -231,17 +228,17 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen)
*/
static bool file_is_any_selected(struct FileList *files)
{
- const int numfiles = filelist_files_ensure(files);
- int i;
+ const int numfiles = filelist_files_ensure(files);
+ int i;
- /* Is any file selected ? */
- for (i = 0; i < numfiles; ++i) {
- if (filelist_entry_select_index_get(files, i, CHECK_ALL)) {
- return true;
- }
- }
+ /* Is any file selected ? */
+ for (i = 0; i < numfiles; ++i) {
+ if (filelist_entry_select_index_get(files, i, CHECK_ALL)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
/**
@@ -249,577 +246,607 @@ static bool file_is_any_selected(struct FileList *files)
*/
static void file_ensure_inside_viewbounds(ARegion *ar, SpaceFile *sfile, const int file)
{
- FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
- rctf *cur = &ar->v2d.cur;
- rcti rect;
- bool changed = true;
-
- file_tile_boundbox(ar, 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) {
- cur->ymin = rect.ymin - (2 * layout->tile_border_y);
- cur->ymax = cur->ymin + ar->winy;
- }
- /* up */
- else if (cur->ymax < rect.ymax) {
- cur->ymax = rect.ymax + layout->tile_border_y;
- cur->ymin = cur->ymax - ar->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) {
- cur->xmin = rect.xmin - layout->tile_border_x;
- cur->xmax = cur->xmin + ar->winx;
- }
- /* right */
- else if (cur->xmax < rect.xmax) {
- cur->xmax = rect.xmax + (2 * layout->tile_border_x);
- cur->xmin = cur->xmax - ar->winx;
- }
- else {
- BLI_assert(cur->xmin <= rect.xmin && cur->xmax >= rect.xmax &&
- cur->ymin <= rect.ymin && cur->ymax >= rect.ymax);
- changed = false;
- }
-
- if (changed) {
- UI_view2d_curRect_validate(&ar->v2d);
- }
-}
-
-
-static FileSelect file_select(bContext *C, const rcti *rect, FileSelType select, bool fill, bool do_diropen)
-{
- SpaceFile *sfile = CTX_wm_space_file(C);
- FileSelect retval = FILE_SELECT_NOTHING;
- FileSelection sel = file_selection_get(C, rect, fill); /* get the selection */
- const FileCheckType check_type = (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_ALL;
-
- /* flag the files as selected in the filelist */
- filelist_entries_select_index_range_set(sfile->files, &sel, select, FILE_SEL_SELECTED, check_type);
-
- /* Don't act on multiple selected files */
- if (sel.first != sel.last) select = 0;
-
- /* Do we have a valid selection and are we actually selecting */
- if ((sel.last >= 0) && (select != FILE_SEL_REMOVE)) {
- /* Check last selection, if selected, act on the file or dir */
- if (filelist_entry_select_index_get(sfile->files, sel.last, check_type)) {
- retval = file_select_do(C, sel.last, do_diropen);
- }
- }
-
- if (select != FILE_SEL_ADD && !file_is_any_selected(sfile->files)) {
- sfile->params->active_file = -1;
- }
- else {
- ARegion *ar = CTX_wm_region(C);
- const FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
-
- /* 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);
- }
- }
-
- /* update operator for name change event */
- file_draw_check(C);
-
- return retval;
-}
-
-static int file_box_select_find_last_selected(
- SpaceFile *sfile, ARegion *ar, const FileSelection *sel,
- const int mouse_xy[2])
-{
- FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
- 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]);
-
- file_tile_boundbox(ar, layout, sel->first, &bounds_first);
- file_tile_boundbox(ar, 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) ||
- (layout->flag & FILE_LAYOUT_VER && bounds_first.ymin != bounds_last.ymin))
- {
- /* use vertical distance */
- const int my_loc = (int)mouseco_view[1];
- dist_first = BLI_rcti_length_y(&bounds_first, my_loc);
- dist_last = BLI_rcti_length_y(&bounds_last, my_loc);
- }
- else {
- /* use horizontal distance */
- const int mx_loc = (int)mouseco_view[0];
- dist_first = BLI_rcti_length_x(&bounds_first, mx_loc);
- dist_last = BLI_rcti_length_x(&bounds_last, mx_loc);
- }
-
- return (dist_first < dist_last) ? sel->first : sel->last;
+ FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
+ rctf *cur = &ar->v2d.cur;
+ rcti rect;
+ bool changed = true;
+
+ file_tile_boundbox(ar, 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) {
+ cur->ymin = rect.ymin - (2 * layout->tile_border_y);
+ cur->ymax = cur->ymin + ar->winy;
+ }
+ /* up */
+ else if (cur->ymax < rect.ymax) {
+ cur->ymax = rect.ymax + layout->tile_border_y;
+ cur->ymin = cur->ymax - ar->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) {
+ cur->xmin = rect.xmin - layout->tile_border_x;
+ cur->xmax = cur->xmin + ar->winx;
+ }
+ /* right */
+ else if (cur->xmax < rect.xmax) {
+ cur->xmax = rect.xmax + (2 * layout->tile_border_x);
+ cur->xmin = cur->xmax - ar->winx;
+ }
+ else {
+ BLI_assert(cur->xmin <= rect.xmin && cur->xmax >= rect.xmax && cur->ymin <= rect.ymin &&
+ cur->ymax >= rect.ymax);
+ changed = false;
+ }
+
+ if (changed) {
+ UI_view2d_curRect_validate(&ar->v2d);
+ }
+}
+
+static FileSelect file_select(
+ bContext *C, const rcti *rect, FileSelType select, bool fill, bool do_diropen)
+{
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelect retval = FILE_SELECT_NOTHING;
+ FileSelection sel = file_selection_get(C, rect, fill); /* get the selection */
+ const FileCheckType check_type = (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS :
+ CHECK_ALL;
+
+ /* flag the files as selected in the filelist */
+ filelist_entries_select_index_range_set(
+ sfile->files, &sel, select, FILE_SEL_SELECTED, check_type);
+
+ /* Don't act on multiple selected files */
+ if (sel.first != sel.last)
+ select = 0;
+
+ /* Do we have a valid selection and are we actually selecting */
+ if ((sel.last >= 0) && (select != FILE_SEL_REMOVE)) {
+ /* Check last selection, if selected, act on the file or dir */
+ if (filelist_entry_select_index_get(sfile->files, sel.last, check_type)) {
+ retval = file_select_do(C, sel.last, do_diropen);
+ }
+ }
+
+ if (select != FILE_SEL_ADD && !file_is_any_selected(sfile->files)) {
+ sfile->params->active_file = -1;
+ }
+ else {
+ ARegion *ar = CTX_wm_region(C);
+ const FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
+
+ /* 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);
+ }
+ }
+
+ /* update operator for name change event */
+ file_draw_check(C);
+
+ return retval;
+}
+
+static int file_box_select_find_last_selected(SpaceFile *sfile,
+ ARegion *ar,
+ const FileSelection *sel,
+ const int mouse_xy[2])
+{
+ FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
+ 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]);
+
+ file_tile_boundbox(ar, layout, sel->first, &bounds_first);
+ file_tile_boundbox(ar, 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) ||
+ (layout->flag & FILE_LAYOUT_VER && bounds_first.ymin != bounds_last.ymin)) {
+ /* use vertical distance */
+ const int my_loc = (int)mouseco_view[1];
+ dist_first = BLI_rcti_length_y(&bounds_first, my_loc);
+ dist_last = BLI_rcti_length_y(&bounds_last, my_loc);
+ }
+ else {
+ /* use horizontal distance */
+ const int mx_loc = (int)mouseco_view[0];
+ dist_first = BLI_rcti_length_x(&bounds_first, mx_loc);
+ dist_last = BLI_rcti_length_x(&bounds_last, mx_loc);
+ }
+
+ return (dist_first < dist_last) ? sel->first : sel->last;
}
static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
- FileSelectParams *params = ED_fileselect_get_params(sfile);
- FileSelection sel;
- rcti rect;
+ ARegion *ar = CTX_wm_region(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelectParams *params = ED_fileselect_get_params(sfile);
+ FileSelection sel;
+ rcti rect;
- int result;
+ int result;
- result = WM_gesture_box_modal(C, op, event);
+ result = WM_gesture_box_modal(C, op, event);
- if (result == OPERATOR_RUNNING_MODAL) {
- WM_operator_properties_border_to_rcti(op, &rect);
+ if (result == OPERATOR_RUNNING_MODAL) {
+ WM_operator_properties_border_to_rcti(op, &rect);
- BLI_rcti_isect(&(ar->v2d.mask), &rect, &rect);
+ BLI_rcti_isect(&(ar->v2d.mask), &rect, &rect);
- sel = file_selection_get(C, &rect, 0);
- if ((sel.first != params->sel_first) || (sel.last != params->sel_last)) {
- int idx;
+ sel = file_selection_get(C, &rect, 0);
+ if ((sel.first != params->sel_first) || (sel.last != params->sel_last)) {
+ int idx;
- file_deselect_all(sfile, FILE_SEL_HIGHLIGHTED);
- filelist_entries_select_index_range_set(sfile->files, &sel, FILE_SEL_ADD, FILE_SEL_HIGHLIGHTED, CHECK_ALL);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+ file_deselect_all(sfile, FILE_SEL_HIGHLIGHTED);
+ filelist_entries_select_index_range_set(
+ sfile->files, &sel, FILE_SEL_ADD, FILE_SEL_HIGHLIGHTED, CHECK_ALL);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
- for (idx = sel.last; idx >= 0; idx--) {
- const FileDirEntry *file = filelist_file(sfile->files, idx);
+ for (idx = sel.last; idx >= 0; idx--) {
+ const FileDirEntry *file = filelist_file(sfile->files, idx);
- /* dont highlight readonly file (".." or ".") on box select */
- if (FILENAME_IS_CURRPAR(file->relpath)) {
- filelist_entry_select_set(sfile->files, file, FILE_SEL_REMOVE, FILE_SEL_HIGHLIGHTED, CHECK_ALL);
- }
+ /* dont highlight readonly file (".." or ".") on box select */
+ if (FILENAME_IS_CURRPAR(file->relpath)) {
+ filelist_entry_select_set(
+ sfile->files, file, FILE_SEL_REMOVE, FILE_SEL_HIGHLIGHTED, CHECK_ALL);
+ }
- /* make sure highlight_file is no readonly file */
- if (sel.last == idx) {
- params->highlight_file = idx;
- }
- }
- }
- params->sel_first = sel.first; params->sel_last = sel.last;
- params->active_file = file_box_select_find_last_selected(sfile, ar, &sel, event->mval);
- }
- else {
- params->highlight_file = -1;
- params->sel_first = params->sel_last = -1;
- fileselect_file_set(sfile, params->active_file);
- file_deselect_all(sfile, FILE_SEL_HIGHLIGHTED);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
- }
+ /* make sure highlight_file is no readonly file */
+ if (sel.last == idx) {
+ params->highlight_file = idx;
+ }
+ }
+ }
+ params->sel_first = sel.first;
+ params->sel_last = sel.last;
+ params->active_file = file_box_select_find_last_selected(sfile, ar, &sel, event->mval);
+ }
+ else {
+ params->highlight_file = -1;
+ params->sel_first = params->sel_last = -1;
+ fileselect_file_set(sfile, params->active_file);
+ file_deselect_all(sfile, FILE_SEL_HIGHLIGHTED);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+ }
- return result;
+ return result;
}
static int file_box_select_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
- rcti rect;
- FileSelect ret;
+ ARegion *ar = CTX_wm_region(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ rcti rect;
+ FileSelect ret;
- WM_operator_properties_border_to_rcti(op, &rect);
+ WM_operator_properties_border_to_rcti(op, &rect);
- 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)) {
- file_deselect_all(sfile, FILE_SEL_SELECTED);
- }
+ 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)) {
+ file_deselect_all(sfile, FILE_SEL_SELECTED);
+ }
- BLI_rcti_isect(&(ar->v2d.mask), &rect, &rect);
+ BLI_rcti_isect(&(ar->v2d.mask), &rect, &rect);
- ret = file_select(C, &rect, select ? FILE_SEL_ADD : FILE_SEL_REMOVE, false, false);
+ ret = file_select(C, &rect, select ? FILE_SEL_ADD : FILE_SEL_REMOVE, false, false);
- /* unselect '..' parent entry - it's not supposed to be selected if more than
- * one file is selected */
- filelist_entry_select_index_set(sfile->files, 0, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
+ /* unselect '..' parent entry - it's not supposed to be selected if more than
+ * one file is selected */
+ filelist_entry_select_index_set(sfile->files, 0, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
- if (FILE_SELECT_DIR == ret) {
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
- }
- else if (FILE_SELECT_FILE == ret) {
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
- }
- return OPERATOR_FINISHED;
+ if (FILE_SELECT_DIR == ret) {
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+ }
+ else if (FILE_SELECT_FILE == ret) {
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+ }
+ return OPERATOR_FINISHED;
}
void FILE_OT_select_box(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Box Select";
- ot->description = "Activate/select the file(s) contained in the border";
- ot->idname = "FILE_OT_select_box";
+ /* identifiers */
+ ot->name = "Box Select";
+ ot->description = "Activate/select the file(s) contained in the border";
+ ot->idname = "FILE_OT_select_box";
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = file_box_select_exec;
- ot->modal = file_box_select_modal;
- ot->poll = ED_operator_file_active;
- ot->cancel = WM_gesture_box_cancel;
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = file_box_select_exec;
+ ot->modal = file_box_select_modal;
+ ot->poll = ED_operator_file_active;
+ ot->cancel = WM_gesture_box_cancel;
- /* properties */
- WM_operator_properties_gesture_box(ot);
- WM_operator_properties_select_operation_simple(ot);
+ /* properties */
+ WM_operator_properties_gesture_box(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
- FileSelect ret;
- rcti rect;
- const bool extend = RNA_boolean_get(op->ptr, "extend");
- const bool fill = RNA_boolean_get(op->ptr, "fill");
- const bool do_diropen = RNA_boolean_get(op->ptr, "open");
+ ARegion *ar = CTX_wm_region(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelect ret;
+ rcti rect;
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool fill = RNA_boolean_get(op->ptr, "fill");
+ const bool do_diropen = RNA_boolean_get(op->ptr, "open");
- if (ar->regiontype != RGN_TYPE_WINDOW)
- return OPERATOR_CANCELLED;
+ if (ar->regiontype != RGN_TYPE_WINDOW)
+ return OPERATOR_CANCELLED;
- rect.xmin = rect.xmax = event->mval[0];
- rect.ymin = rect.ymax = event->mval[1];
+ rect.xmin = rect.xmax = event->mval[0];
+ rect.ymin = rect.ymax = event->mval[1];
- if (!BLI_rcti_isect_pt(&ar->v2d.mask, rect.xmin, rect.ymin))
- return OPERATOR_CANCELLED;
+ if (!BLI_rcti_isect_pt(&ar->v2d.mask, rect.xmin, rect.ymin))
+ return OPERATOR_CANCELLED;
- if (sfile && sfile->params) {
- int idx = sfile->params->highlight_file;
- int numfiles = filelist_files_ensure(sfile->files);
+ if (sfile && sfile->params) {
+ int idx = sfile->params->highlight_file;
+ int numfiles = filelist_files_ensure(sfile->files);
- if ((idx >= 0) && (idx < numfiles)) {
- /* single select, deselect all selected first */
- if (!extend) {
- file_deselect_all(sfile, FILE_SEL_SELECTED);
- }
- }
- }
+ if ((idx >= 0) && (idx < numfiles)) {
+ /* single select, deselect all selected first */
+ if (!extend) {
+ file_deselect_all(sfile, FILE_SEL_SELECTED);
+ }
+ }
+ }
- ret = file_select(C, &rect, extend ? FILE_SEL_TOGGLE : FILE_SEL_ADD, fill, do_diropen);
+ ret = file_select(C, &rect, extend ? FILE_SEL_TOGGLE : FILE_SEL_ADD, fill, do_diropen);
- if (extend) {
- /* unselect '..' parent entry - it's not supposed to be selected if more
- * than one file is selected */
- filelist_entry_select_index_set(sfile->files, 0, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
- }
+ if (extend) {
+ /* unselect '..' parent entry - it's not supposed to be selected if more
+ * than one file is selected */
+ filelist_entry_select_index_set(
+ sfile->files, 0, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
+ }
- if (FILE_SELECT_DIR == ret)
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
- else if (FILE_SELECT_FILE == ret)
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+ if (FILE_SELECT_DIR == ret)
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+ else if (FILE_SELECT_FILE == ret)
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
- WM_event_add_mousemove(C); /* for directory changes */
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+ WM_event_add_mousemove(C); /* for directory changes */
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void FILE_OT_select(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Select";
- ot->description = "Activate/select file";
- ot->idname = "FILE_OT_select";
+ /* identifiers */
+ ot->name = "Select";
+ ot->description = "Activate/select file";
+ ot->idname = "FILE_OT_select";
- /* api callbacks */
- ot->invoke = file_select_invoke;
- ot->poll = ED_operator_file_active;
+ /* api callbacks */
+ ot->invoke = file_select_invoke;
+ ot->poll = ED_operator_file_active;
- /* properties */
- prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "fill", false, "Fill", "Select everything beginning with the last selection");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "open", true, "Open", "Open a directory when selecting it");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ prop = RNA_def_boolean(ot->srna,
+ "extend",
+ false,
+ "Extend",
+ "Extend selection instead of deselecting everything first");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(
+ ot->srna, "fill", false, "Fill", "Select everything beginning with the last selection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "open", true, "Open", "Open a directory when selecting it");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/**
* \returns true if selection has changed
*/
-static bool file_walk_select_selection_set(
- bContext *C, SpaceFile *sfile,
- const int direction, const int numfiles,
- const int active_old, const int active_new, const int other_site,
- const bool has_selection, const bool extend, const bool fill)
-{
- FileSelectParams *params = sfile->params;
- struct FileList *files = sfile->files;
- const int last_sel = params->active_file; /* store old value */
- int active = active_old; /* could use active_old instead, just for readability */
- bool deselect = false;
-
- BLI_assert(params);
-
- if (has_selection) {
- if (extend &&
- filelist_entry_select_index_get(files, active_old, CHECK_ALL) &&
- filelist_entry_select_index_get(files, active_new, CHECK_ALL))
- {
- /* conditions for deselecting: initial file is selected, new file is
- * selected and either other_side isn't selected/found or we use fill */
- deselect = (fill || other_site == -1 ||
- !filelist_entry_select_index_get(files, other_site, CHECK_ALL));
-
- /* don't change highlight_file here since we either want to deselect active or we want
- * to walk through a block of selected files without selecting/deselecting anything */
- params->active_file = active_new;
- /* but we want to change active if we use fill
- * (needed to get correct selection bounds) */
- if (deselect && fill) {
- active = active_new;
- }
- }
- else {
- /* regular selection change */
- params->active_file = active = active_new;
- }
- }
- else {
- /* select last file */
- if (ELEM(direction, FILE_SELECT_WALK_UP, FILE_SELECT_WALK_LEFT)) {
- params->active_file = active = numfiles - 1;
- }
- /* select first file */
- else if (ELEM(direction, FILE_SELECT_WALK_DOWN, FILE_SELECT_WALK_RIGHT)) {
- params->active_file = active = extend ? 1 : 0;
- }
- else {
- BLI_assert(0);
- }
- }
-
- if (active < 0) {
- return false;
- }
-
- if (extend) {
- /* highlight the active walker file for extended selection for better visual feedback */
- params->highlight_file = params->active_file;
-
- /* unselect '..' parent entry - it's not supposed to be selected if more
- * than one file is selected */
- filelist_entry_select_index_set(files, 0, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
- }
- else {
- /* deselect all first */
- file_deselect_all(sfile, FILE_SEL_SELECTED);
-
- /* highlight file under mouse pos */
- params->highlight_file = -1;
- WM_event_add_mousemove(C);
- }
-
- /* do the actual selection */
- if (fill) {
- FileSelection sel = { MIN2(active, last_sel), MAX2(active, last_sel) };
-
- /* clamping selection to not include '..' parent entry */
- if (sel.first == 0) {
- sel.first = 1;
- }
-
- /* fill selection between last and first selected file */
- filelist_entries_select_index_range_set(
- files, &sel, deselect ? FILE_SEL_REMOVE : FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
- /* entire sel is cleared here, so select active again */
- if (deselect) {
- filelist_entry_select_index_set(files, active, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
- }
- }
- else {
- filelist_entry_select_index_set(
- files, active, deselect ? FILE_SEL_REMOVE : FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
- }
-
- BLI_assert(IN_RANGE(active, -1, numfiles));
- 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);
-
- /* selection changed */
- return true;
+static bool file_walk_select_selection_set(bContext *C,
+ SpaceFile *sfile,
+ const int direction,
+ const int numfiles,
+ const int active_old,
+ const int active_new,
+ const int other_site,
+ const bool has_selection,
+ const bool extend,
+ const bool fill)
+{
+ FileSelectParams *params = sfile->params;
+ struct FileList *files = sfile->files;
+ const int last_sel = params->active_file; /* store old value */
+ int active = active_old; /* could use active_old instead, just for readability */
+ bool deselect = false;
+
+ BLI_assert(params);
+
+ if (has_selection) {
+ if (extend && filelist_entry_select_index_get(files, active_old, CHECK_ALL) &&
+ filelist_entry_select_index_get(files, active_new, CHECK_ALL)) {
+ /* conditions for deselecting: initial file is selected, new file is
+ * selected and either other_side isn't selected/found or we use fill */
+ deselect = (fill || other_site == -1 ||
+ !filelist_entry_select_index_get(files, other_site, CHECK_ALL));
+
+ /* don't change highlight_file here since we either want to deselect active or we want
+ * to walk through a block of selected files without selecting/deselecting anything */
+ params->active_file = active_new;
+ /* but we want to change active if we use fill
+ * (needed to get correct selection bounds) */
+ if (deselect && fill) {
+ active = active_new;
+ }
+ }
+ else {
+ /* regular selection change */
+ params->active_file = active = active_new;
+ }
+ }
+ else {
+ /* select last file */
+ if (ELEM(direction, FILE_SELECT_WALK_UP, FILE_SELECT_WALK_LEFT)) {
+ params->active_file = active = numfiles - 1;
+ }
+ /* select first file */
+ else if (ELEM(direction, FILE_SELECT_WALK_DOWN, FILE_SELECT_WALK_RIGHT)) {
+ params->active_file = active = extend ? 1 : 0;
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+
+ if (active < 0) {
+ return false;
+ }
+
+ if (extend) {
+ /* highlight the active walker file for extended selection for better visual feedback */
+ params->highlight_file = params->active_file;
+
+ /* unselect '..' parent entry - it's not supposed to be selected if more
+ * than one file is selected */
+ filelist_entry_select_index_set(files, 0, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
+ }
+ else {
+ /* deselect all first */
+ file_deselect_all(sfile, FILE_SEL_SELECTED);
+
+ /* highlight file under mouse pos */
+ params->highlight_file = -1;
+ WM_event_add_mousemove(C);
+ }
+
+ /* do the actual selection */
+ if (fill) {
+ FileSelection sel = {MIN2(active, last_sel), MAX2(active, last_sel)};
+
+ /* clamping selection to not include '..' parent entry */
+ if (sel.first == 0) {
+ sel.first = 1;
+ }
+
+ /* fill selection between last and first selected file */
+ filelist_entries_select_index_range_set(
+ files, &sel, deselect ? FILE_SEL_REMOVE : FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
+ /* entire sel is cleared here, so select active again */
+ if (deselect) {
+ filelist_entry_select_index_set(files, active, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
+ }
+ }
+ else {
+ filelist_entry_select_index_set(
+ files, active, deselect ? FILE_SEL_REMOVE : FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
+ }
+
+ BLI_assert(IN_RANGE(active, -1, numfiles));
+ 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);
+
+ /* selection changed */
+ return true;
}
/**
* \returns true if selection has changed
*/
-static bool file_walk_select_do(
- bContext *C, SpaceFile *sfile,
- FileSelectParams *params, const int direction,
- const bool extend, const bool fill)
-{
- struct FileList *files = sfile->files;
- const int numfiles = filelist_files_ensure(files);
- const bool has_selection = file_is_any_selected(files);
- const int active_old = params->active_file;
- int active_new = -1;
- int other_site = -1; /* file on the other site of active_old */
-
-
- /* *** get all needed files for handling selection *** */
-
- if (has_selection) {
- ARegion *ar = CTX_wm_region(C);
- FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
- const int idx_shift = (layout->flag & FILE_LAYOUT_HOR) ? layout->rows : layout->columns;
-
- if ((layout->flag & FILE_LAYOUT_HOR && direction == FILE_SELECT_WALK_UP) ||
- (layout->flag & FILE_LAYOUT_VER && direction == FILE_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))
- {
- 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))
- {
- 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))
- {
-
- active_new = active_old + idx_shift;
- other_site = active_old - idx_shift;
- }
- else {
- BLI_assert(0);
- }
-
- if (!IN_RANGE(active_new, 0, numfiles)) {
- if (extend) {
- /* extend to invalid file -> abort */
- return false;
- }
- /* if we don't extend, selecting '..' (index == 0) is allowed so
- * using key selection to go to parent directory is possible */
- else if (active_new != 0) {
- /* select initial file */
- active_new = active_old;
- }
- }
- if (!IN_RANGE(other_site, 0, numfiles)) {
- other_site = -1;
- }
- }
-
- return file_walk_select_selection_set(
- C, sfile, direction, numfiles, active_old, active_new, other_site, has_selection, extend, fill);
+static bool file_walk_select_do(bContext *C,
+ SpaceFile *sfile,
+ FileSelectParams *params,
+ const int direction,
+ const bool extend,
+ const bool fill)
+{
+ struct FileList *files = sfile->files;
+ const int numfiles = filelist_files_ensure(files);
+ const bool has_selection = file_is_any_selected(files);
+ const int active_old = params->active_file;
+ int active_new = -1;
+ int other_site = -1; /* file on the other site of active_old */
+
+ /* *** get all needed files for handling selection *** */
+
+ if (has_selection) {
+ ARegion *ar = CTX_wm_region(C);
+ FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
+ const int idx_shift = (layout->flag & FILE_LAYOUT_HOR) ? layout->rows : layout->columns;
+
+ if ((layout->flag & FILE_LAYOUT_HOR && direction == FILE_SELECT_WALK_UP) ||
+ (layout->flag & FILE_LAYOUT_VER && direction == FILE_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)) {
+ 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)) {
+ 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)) {
+
+ active_new = active_old + idx_shift;
+ other_site = active_old - idx_shift;
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ if (!IN_RANGE(active_new, 0, numfiles)) {
+ if (extend) {
+ /* extend to invalid file -> abort */
+ return false;
+ }
+ /* if we don't extend, selecting '..' (index == 0) is allowed so
+ * using key selection to go to parent directory is possible */
+ else if (active_new != 0) {
+ /* select initial file */
+ active_new = active_old;
+ }
+ }
+ if (!IN_RANGE(other_site, 0, numfiles)) {
+ other_site = -1;
+ }
+ }
+
+ return file_walk_select_selection_set(C,
+ sfile,
+ direction,
+ numfiles,
+ active_old,
+ active_new,
+ other_site,
+ has_selection,
+ extend,
+ fill);
}
static int file_walk_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
- FileSelectParams *params = sfile->params;
- const int direction = RNA_enum_get(op->ptr, "direction");
- const bool extend = RNA_boolean_get(op->ptr, "extend");
- const bool fill = RNA_boolean_get(op->ptr, "fill");
+ SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
+ FileSelectParams *params = sfile->params;
+ const int direction = RNA_enum_get(op->ptr, "direction");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool fill = RNA_boolean_get(op->ptr, "fill");
- if (file_walk_select_do(C, sfile, params, direction, extend, fill)) {
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
- return OPERATOR_FINISHED;
- }
+ if (file_walk_select_do(C, sfile, params, direction, extend, fill)) {
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
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 */
- ot->name = "Walk Select/Deselect File";
- ot->description = "Select/Deselect files by walking through them";
- ot->idname = "FILE_OT_select_walk";
-
- /* api callbacks */
- ot->invoke = file_walk_select_invoke;
- 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);
- prop = RNA_def_boolean(ot->srna, "extend", false, "Extend",
- "Extend selection instead of deselecting everything first");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "fill", false, "Fill", "Select everything beginning with the last selection");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ 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 */
+ ot->name = "Walk Select/Deselect File";
+ ot->description = "Select/Deselect files by walking through them";
+ ot->idname = "FILE_OT_select_walk";
+
+ /* api callbacks */
+ ot->invoke = file_walk_select_invoke;
+ 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);
+ prop = RNA_def_boolean(ot->srna,
+ "extend",
+ false,
+ "Extend",
+ "Extend selection instead of deselecting everything first");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(
+ ot->srna, "fill", false, "Fill", "Select everything beginning with the last selection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static int file_select_all_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
- FileSelection sel;
- const int numfiles = filelist_files_ensure(sfile->files);
- const bool has_selection = file_is_any_selected(sfile->files);
-
- sel.first = 0;
- sel.last = numfiles - 1;
-
- /* select all only if previously no file was selected */
- if (has_selection) {
- filelist_entries_select_index_range_set(sfile->files, &sel, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
- sfile->params->active_file = -1;
- }
- else {
- const FileCheckType check_type = (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_FILES;
- int i;
-
- filelist_entries_select_index_range_set(sfile->files, &sel, FILE_SEL_ADD, FILE_SEL_SELECTED, check_type);
-
- /* set active_file to first selected */
- for (i = 0; i < numfiles; i++) {
- if (filelist_entry_select_index_get(sfile->files, i, check_type)) {
- sfile->params->active_file = i;
- break;
- }
- }
- }
-
- file_draw_check(C);
- WM_event_add_mousemove(C);
- ED_area_tag_redraw(sa);
-
- return OPERATOR_FINISHED;
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelection sel;
+ const int numfiles = filelist_files_ensure(sfile->files);
+ const bool has_selection = file_is_any_selected(sfile->files);
+
+ sel.first = 0;
+ sel.last = numfiles - 1;
+
+ /* select all only if previously no file was selected */
+ if (has_selection) {
+ filelist_entries_select_index_range_set(
+ sfile->files, &sel, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
+ sfile->params->active_file = -1;
+ }
+ else {
+ const FileCheckType check_type = (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS :
+ CHECK_FILES;
+ int i;
+
+ filelist_entries_select_index_range_set(
+ sfile->files, &sel, FILE_SEL_ADD, FILE_SEL_SELECTED, check_type);
+
+ /* set active_file to first selected */
+ for (i = 0; i < numfiles; i++) {
+ if (filelist_entry_select_index_get(sfile->files, i, check_type)) {
+ sfile->params->active_file = i;
+ break;
+ }
+ }
+ }
+
+ file_draw_check(C);
+ WM_event_add_mousemove(C);
+ ED_area_tag_redraw(sa);
+
+ return OPERATOR_FINISHED;
}
void FILE_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All Files";
- ot->description = "Select or deselect all files";
- ot->idname = "FILE_OT_select_all";
+ /* identifiers */
+ ot->name = "(De)select All Files";
+ ot->description = "Select or deselect all files";
+ ot->idname = "FILE_OT_select_all";
- /* api callbacks */
- ot->exec = file_select_all_exec;
- ot->poll = ED_operator_file_active;
+ /* api callbacks */
+ ot->exec = file_select_all_exec;
+ ot->poll = ED_operator_file_active;
- /* properties */
+ /* properties */
}
/* ---------- BOOKMARKS ----------- */
@@ -828,487 +855,500 @@ void FILE_OT_select_all(wmOperatorType *ot)
* Does not hurt keeping it around for now. */
static int bookmark_select_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
- PropertyRNA *prop;
+ Main *bmain = CTX_data_main(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ PropertyRNA *prop;
- if ((prop = RNA_struct_find_property(op->ptr, "dir"))) {
- char entry[256];
- FileSelectParams *params = sfile->params;
+ if ((prop = RNA_struct_find_property(op->ptr, "dir"))) {
+ char entry[256];
+ FileSelectParams *params = sfile->params;
- 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);
- ED_file_change_dir(C);
+ 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);
+ ED_file_change_dir(C);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
- }
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void FILE_OT_select_bookmark(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Select Directory";
- ot->description = "Select a bookmarked directory";
- ot->idname = "FILE_OT_select_bookmark";
+ /* identifiers */
+ ot->name = "Select Directory";
+ ot->description = "Select a bookmarked directory";
+ ot->idname = "FILE_OT_select_bookmark";
- /* api callbacks */
- ot->exec = bookmark_select_exec;
- ot->poll = ED_operator_file_active;
+ /* api callbacks */
+ ot->exec = bookmark_select_exec;
+ ot->poll = ED_operator_file_active;
- /* properties */
- prop = RNA_def_string(ot->srna, "dir", NULL, FILE_MAXDIR, "Dir", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ prop = RNA_def_string(ot->srna, "dir", NULL, FILE_MAXDIR, "Dir", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static int bookmark_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = 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);
+ ScrArea *sa = 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);
- if (params->dir[0] != '\0') {
- char name[FILE_MAX];
+ if (params->dir[0] != '\0') {
+ char name[FILE_MAX];
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir, NULL, FS_INSERT_SAVE);
- BLI_make_file_string("/", name, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
- fsmenu_write_file(fsmenu, name);
- }
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir, NULL, FS_INSERT_SAVE);
+ BLI_make_file_string(
+ "/", 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);
- return OPERATOR_FINISHED;
+ ED_area_tag_refresh(sa);
+ ED_area_tag_redraw(sa);
+ return OPERATOR_FINISHED;
}
void FILE_OT_bookmark_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Bookmark";
- ot->description = "Add a bookmark for the selected/active directory";
- ot->idname = "FILE_OT_bookmark_add";
+ /* identifiers */
+ ot->name = "Add Bookmark";
+ ot->description = "Add a bookmark for the selected/active directory";
+ ot->idname = "FILE_OT_bookmark_add";
- /* api callbacks */
- ot->exec = bookmark_add_exec;
- ot->poll = ED_operator_file_active;
+ /* api callbacks */
+ ot->exec = bookmark_add_exec;
+ ot->poll = ED_operator_file_active;
}
static int bookmark_delete_exec(bContext *C, wmOperator *op)
{
- ScrArea *sa = 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);
-
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, "index");
-
- if (prop) {
- int index;
- if (RNA_property_is_set(op->ptr, prop)) {
- index = RNA_property_int_get(op->ptr, prop);
- }
- else { /* if index unset, use active bookmark... */
- index = sfile->bookmarknr;
- }
- if ((index > -1) && (index < nentries)) {
- 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);
- fsmenu_write_file(fsmenu, name);
- ED_area_tag_refresh(sa);
- ED_area_tag_redraw(sa);
- }
- }
-
- return OPERATOR_FINISHED;
+ ScrArea *sa = 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);
+
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "index");
+
+ if (prop) {
+ int index;
+ if (RNA_property_is_set(op->ptr, prop)) {
+ index = RNA_property_int_get(op->ptr, prop);
+ }
+ else { /* if index unset, use active bookmark... */
+ index = sfile->bookmarknr;
+ }
+ if ((index > -1) && (index < nentries)) {
+ 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);
+ fsmenu_write_file(fsmenu, name);
+ ED_area_tag_refresh(sa);
+ ED_area_tag_redraw(sa);
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void FILE_OT_bookmark_delete(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Delete Bookmark";
- ot->description = "Delete selected bookmark";
- ot->idname = "FILE_OT_bookmark_delete";
+ /* identifiers */
+ ot->name = "Delete Bookmark";
+ ot->description = "Delete selected bookmark";
+ ot->idname = "FILE_OT_bookmark_delete";
- /* api callbacks */
- ot->exec = bookmark_delete_exec;
- ot->poll = ED_operator_file_active;
+ /* api callbacks */
+ ot->exec = bookmark_delete_exec;
+ ot->poll = ED_operator_file_active;
- /* properties */
- prop = RNA_def_int(ot->srna, "index", -1, -1, 20000, "Index", "", -1, 20000);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ prop = RNA_def_int(ot->srna, "index", -1, -1, 20000, "Index", "", -1, 20000);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static int bookmark_cleanup_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = 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;
- bool changed = false;
+ ScrArea *sa = 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;
+ bool changed = false;
- for (index = 0; fsme; fsme = fsme_next) {
- fsme_next = fsme->next;
+ for (index = 0; fsme; fsme = fsme_next) {
+ fsme_next = fsme->next;
- if (!BLI_is_dir(fsme->path)) {
- fsmenu_remove_entry(fsmenu, FS_CATEGORY_BOOKMARKS, index);
- changed = true;
- }
- else {
- index++;
- }
- }
+ if (!BLI_is_dir(fsme->path)) {
+ fsmenu_remove_entry(fsmenu, FS_CATEGORY_BOOKMARKS, index);
+ changed = true;
+ }
+ else {
+ index++;
+ }
+ }
- if (changed) {
- char name[FILE_MAX];
+ if (changed) {
+ char name[FILE_MAX];
- BLI_make_file_string("/", name, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
- fsmenu_write_file(fsmenu, name);
- fsmenu_refresh_bookmarks_status(fsmenu);
- ED_area_tag_refresh(sa);
- ED_area_tag_redraw(sa);
- }
+ BLI_make_file_string(
+ "/", name, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
+ fsmenu_write_file(fsmenu, name);
+ fsmenu_refresh_bookmarks_status(fsmenu);
+ ED_area_tag_refresh(sa);
+ ED_area_tag_redraw(sa);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void FILE_OT_bookmark_cleanup(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Cleanup Bookmarks";
- ot->description = "Delete all invalid bookmarks";
- ot->idname = "FILE_OT_bookmark_cleanup";
+ /* identifiers */
+ ot->name = "Cleanup Bookmarks";
+ ot->description = "Delete all invalid bookmarks";
+ ot->idname = "FILE_OT_bookmark_cleanup";
- /* api callbacks */
- ot->exec = bookmark_cleanup_exec;
- ot->poll = ED_operator_file_active;
+ /* api callbacks */
+ ot->exec = bookmark_cleanup_exec;
+ ot->poll = ED_operator_file_active;
- /* properties */
+ /* properties */
}
enum {
- FILE_BOOKMARK_MOVE_TOP = -2,
- FILE_BOOKMARK_MOVE_UP = -1,
- FILE_BOOKMARK_MOVE_DOWN = 1,
- FILE_BOOKMARK_MOVE_BOTTOM = 2,
+ FILE_BOOKMARK_MOVE_TOP = -2,
+ FILE_BOOKMARK_MOVE_UP = -1,
+ FILE_BOOKMARK_MOVE_DOWN = 1,
+ FILE_BOOKMARK_MOVE_BOTTOM = 2,
};
static int bookmark_move_exec(bContext *C, wmOperator *op)
{
- ScrArea *sa = 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);
- const struct FSMenuEntry *fsmentry_org = fsmentry;
-
- char fname[FILE_MAX];
-
- const int direction = RNA_enum_get(op->ptr, "direction");
- const int totitems = ED_fsmenu_get_nentries(fsmenu, FS_CATEGORY_BOOKMARKS);
- const int act_index = sfile->bookmarknr;
- int new_index;
-
- if (totitems < 2) {
- return OPERATOR_CANCELLED;
- }
-
- switch (direction) {
- case FILE_BOOKMARK_MOVE_TOP:
- new_index = 0;
- break;
- case FILE_BOOKMARK_MOVE_BOTTOM:
- new_index = totitems - 1;
- break;
- case FILE_BOOKMARK_MOVE_UP:
- case FILE_BOOKMARK_MOVE_DOWN:
- default:
- new_index = (totitems + act_index + direction) % totitems;
- break;
- }
-
- if (new_index == act_index) {
- return OPERATOR_CANCELLED;
- }
-
- BLI_linklist_move_item((LinkNode **)&fsmentry, act_index, new_index);
- if (fsmentry != fsmentry_org) {
- ED_fsmenu_set_category(fsmenu, FS_CATEGORY_BOOKMARKS, fsmentry);
- }
-
- /* 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);
- fsmenu_write_file(fsmenu, fname);
-
- ED_area_tag_redraw(sa);
- return OPERATOR_FINISHED;
+ ScrArea *sa = 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);
+ const struct FSMenuEntry *fsmentry_org = fsmentry;
+
+ char fname[FILE_MAX];
+
+ const int direction = RNA_enum_get(op->ptr, "direction");
+ const int totitems = ED_fsmenu_get_nentries(fsmenu, FS_CATEGORY_BOOKMARKS);
+ const int act_index = sfile->bookmarknr;
+ int new_index;
+
+ if (totitems < 2) {
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (direction) {
+ case FILE_BOOKMARK_MOVE_TOP:
+ new_index = 0;
+ break;
+ case FILE_BOOKMARK_MOVE_BOTTOM:
+ new_index = totitems - 1;
+ break;
+ case FILE_BOOKMARK_MOVE_UP:
+ case FILE_BOOKMARK_MOVE_DOWN:
+ default:
+ new_index = (totitems + act_index + direction) % totitems;
+ break;
+ }
+
+ if (new_index == act_index) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BLI_linklist_move_item((LinkNode **)&fsmentry, act_index, new_index);
+ if (fsmentry != fsmentry_org) {
+ ED_fsmenu_set_category(fsmenu, FS_CATEGORY_BOOKMARKS, fsmentry);
+ }
+
+ /* 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);
+ fsmenu_write_file(fsmenu, fname);
+
+ ED_area_tag_redraw(sa);
+ return OPERATOR_FINISHED;
}
void FILE_OT_bookmark_move(wmOperatorType *ot)
{
- static const EnumPropertyItem slot_move[] = {
- {FILE_BOOKMARK_MOVE_TOP, "TOP", 0, "Top", "Top of the list"},
- {FILE_BOOKMARK_MOVE_UP, "UP", 0, "Up", ""},
- {FILE_BOOKMARK_MOVE_DOWN, "DOWN", 0, "Down", ""},
- {FILE_BOOKMARK_MOVE_BOTTOM, "BOTTOM", 0, "Bottom", "Bottom of the list"},
- { 0, NULL, 0, NULL, NULL }
- };
+ static const EnumPropertyItem slot_move[] = {
+ {FILE_BOOKMARK_MOVE_TOP, "TOP", 0, "Top", "Top of the list"},
+ {FILE_BOOKMARK_MOVE_UP, "UP", 0, "Up", ""},
+ {FILE_BOOKMARK_MOVE_DOWN, "DOWN", 0, "Down", ""},
+ {FILE_BOOKMARK_MOVE_BOTTOM, "BOTTOM", 0, "Bottom", "Bottom of the list"},
+ {0, NULL, 0, NULL, NULL}};
- /* identifiers */
- ot->name = "Move Bookmark";
- ot->idname = "FILE_OT_bookmark_move";
- ot->description = "Move the active bookmark up/down in the list";
+ /* identifiers */
+ ot->name = "Move Bookmark";
+ ot->idname = "FILE_OT_bookmark_move";
+ ot->description = "Move the active bookmark up/down in the list";
- /* api callbacks */
- ot->poll = ED_operator_file_active;
- ot->exec = bookmark_move_exec;
+ /* api callbacks */
+ ot->poll = ED_operator_file_active;
+ ot->exec = bookmark_move_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER; /* No undo! */
+ /* flags */
+ ot->flag = OPTYPE_REGISTER; /* No undo! */
- RNA_def_enum(ot->srna, "direction", slot_move, 0, "Direction",
- "Direction to move the active bookmark towards");
+ RNA_def_enum(ot->srna,
+ "direction",
+ slot_move,
+ 0,
+ "Direction",
+ "Direction to move the active bookmark towards");
}
static int reset_recent_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- char name[FILE_MAX];
- struct FSMenu *fsmenu = ED_fsmenu_get();
+ ScrArea *sa = 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);
- fsmenu_write_file(fsmenu, name);
- ED_area_tag_redraw(sa);
+ 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);
+ fsmenu_write_file(fsmenu, name);
+ ED_area_tag_redraw(sa);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void FILE_OT_reset_recent(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reset Recent";
- ot->description = "Reset Recent files";
- ot->idname = "FILE_OT_reset_recent";
-
- /* api callbacks */
- ot->exec = reset_recent_exec;
- ot->poll = ED_operator_file_active;
+ /* identifiers */
+ ot->name = "Reset Recent";
+ ot->description = "Reset Recent files";
+ ot->idname = "FILE_OT_reset_recent";
+ /* api callbacks */
+ ot->exec = reset_recent_exec;
+ ot->poll = ED_operator_file_active;
}
int file_highlight_set(SpaceFile *sfile, ARegion *ar, int mx, int my)
{
- View2D *v2d = &ar->v2d;
- FileSelectParams *params;
- int numfiles, origfile;
+ View2D *v2d = &ar->v2d;
+ FileSelectParams *params;
+ int numfiles, origfile;
- if (sfile == NULL || sfile->files == NULL) return 0;
+ if (sfile == NULL || sfile->files == NULL)
+ return 0;
- numfiles = filelist_files_ensure(sfile->files);
- params = ED_fileselect_get_params(sfile);
+ numfiles = filelist_files_ensure(sfile->files);
+ params = ED_fileselect_get_params(sfile);
- origfile = params->highlight_file;
+ origfile = params->highlight_file;
- mx -= ar->winrct.xmin;
- my -= ar->winrct.ymin;
+ mx -= ar->winrct.xmin;
+ my -= ar->winrct.ymin;
- if (BLI_rcti_isect_pt(&ar->v2d.mask, mx, my)) {
- float fx, fy;
- int highlight_file;
+ if (BLI_rcti_isect_pt(&ar->v2d.mask, mx, my)) {
+ float fx, fy;
+ int highlight_file;
- UI_view2d_region_to_view(v2d, mx, my, &fx, &fy);
+ UI_view2d_region_to_view(v2d, mx, my, &fx, &fy);
- highlight_file = ED_fileselect_layout_offset(sfile->layout, (int)(v2d->tot.xmin + fx), (int)(v2d->tot.ymax - fy));
+ highlight_file = ED_fileselect_layout_offset(
+ sfile->layout, (int)(v2d->tot.xmin + fx), (int)(v2d->tot.ymax - fy));
- if ((highlight_file >= 0) && (highlight_file < numfiles))
- params->highlight_file = highlight_file;
- else
- params->highlight_file = -1;
- }
- else
- params->highlight_file = -1;
+ if ((highlight_file >= 0) && (highlight_file < numfiles))
+ params->highlight_file = highlight_file;
+ else
+ params->highlight_file = -1;
+ }
+ else
+ params->highlight_file = -1;
- return (params->highlight_file != origfile);
+ return (params->highlight_file != origfile);
}
static int file_highlight_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
+ ARegion *ar = CTX_wm_region(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
- if (!file_highlight_set(sfile, ar, event->x, event->y))
- return OPERATOR_PASS_THROUGH;
+ if (!file_highlight_set(sfile, ar, event->x, event->y))
+ return OPERATOR_PASS_THROUGH;
- ED_area_tag_redraw(CTX_wm_area(C));
+ ED_area_tag_redraw(CTX_wm_area(C));
- return OPERATOR_PASS_THROUGH;
+ return OPERATOR_PASS_THROUGH;
}
void FILE_OT_highlight(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Highlight File";
- ot->description = "Highlight selected file(s)";
- ot->idname = "FILE_OT_highlight";
+ /* identifiers */
+ ot->name = "Highlight File";
+ ot->description = "Highlight selected file(s)";
+ ot->idname = "FILE_OT_highlight";
- /* api callbacks */
- ot->invoke = file_highlight_invoke;
- ot->poll = ED_operator_file_active;
+ /* api callbacks */
+ ot->invoke = file_highlight_invoke;
+ ot->poll = ED_operator_file_active;
}
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;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ wmOperator *op = sfile->op;
- sfile->op = NULL;
+ sfile->op = NULL;
- WM_event_fileselect_event(wm, op, EVT_FILESELECT_CANCEL);
+ WM_event_fileselect_event(wm, op, EVT_FILESELECT_CANCEL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static bool file_operator_poll(bContext *C)
{
- bool poll = ED_operator_file_active(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
+ bool poll = ED_operator_file_active(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
- if (!sfile || !sfile->op) poll = 0;
+ if (!sfile || !sfile->op)
+ poll = 0;
- return poll;
+ return poll;
}
void FILE_OT_cancel(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Cancel File Load";
- ot->description = "Cancel loading of selected file";
- ot->idname = "FILE_OT_cancel";
+ /* identifiers */
+ ot->name = "Cancel File Load";
+ ot->description = "Cancel loading of selected file";
+ ot->idname = "FILE_OT_cancel";
- /* api callbacks */
- ot->exec = file_cancel_exec;
- ot->poll = file_operator_poll;
+ /* api callbacks */
+ ot->exec = file_cancel_exec;
+ ot->poll = file_operator_poll;
}
-
void file_sfile_to_operator_ex(bContext *C, wmOperator *op, SpaceFile *sfile, char *filepath)
{
- Main *bmain = CTX_data_main(C);
- PropertyRNA *prop;
-
- /* XXX, not real length */
- BLI_join_dirfile(filepath, FILE_MAX, sfile->params->dir, sfile->params->file);
-
- if ((prop = RNA_struct_find_property(op->ptr, "relative_path"))) {
- if (RNA_property_boolean_get(op->ptr, prop)) {
- BLI_path_rel(filepath, BKE_main_blendfile_path(bmain));
- }
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "filename"))) {
- RNA_property_string_set(op->ptr, prop, sfile->params->file);
- }
- if ((prop = RNA_struct_find_property(op->ptr, "directory"))) {
- RNA_property_string_set(op->ptr, prop, sfile->params->dir);
- }
- if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) {
- RNA_property_string_set(op->ptr, prop, filepath);
- }
-
- /* some ops have multiple files to select */
- /* this is called on operators check() so clear collections first since
- * they may be already set. */
- {
- int i, numfiles = filelist_files_ensure(sfile->files);
-
- if ((prop = RNA_struct_find_property(op->ptr, "files"))) {
- PointerRNA itemptr;
- int num_files = 0;
- RNA_property_collection_clear(op->ptr, prop);
- for (i = 0; i < numfiles; i++) {
- if (filelist_entry_select_index_get(sfile->files, i, CHECK_FILES)) {
- FileDirEntry *file = filelist_file(sfile->files, i);
- RNA_property_collection_add(op->ptr, prop, &itemptr);
- RNA_string_set(&itemptr, "name", file->relpath);
- num_files++;
- }
- }
- /* make sure the file specified in the filename button is added even if no
- * files selected */
- if (0 == num_files) {
- RNA_property_collection_add(op->ptr, prop, &itemptr);
- RNA_string_set(&itemptr, "name", sfile->params->file);
- }
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "dirs"))) {
- PointerRNA itemptr;
- int num_dirs = 0;
- RNA_property_collection_clear(op->ptr, prop);
- for (i = 0; i < numfiles; i++) {
- if (filelist_entry_select_index_get(sfile->files, i, CHECK_DIRS)) {
- FileDirEntry *file = filelist_file(sfile->files, i);
- RNA_property_collection_add(op->ptr, prop, &itemptr);
- RNA_string_set(&itemptr, "name", file->relpath);
- num_dirs++;
- }
- }
-
- /* make sure the directory specified in the button is added even if no
- * directory selected */
- if (0 == num_dirs) {
- RNA_property_collection_add(op->ptr, prop, &itemptr);
- RNA_string_set(&itemptr, "name", sfile->params->dir);
- }
- }
-
-
- }
+ Main *bmain = CTX_data_main(C);
+ PropertyRNA *prop;
+
+ /* XXX, not real length */
+ BLI_join_dirfile(filepath, FILE_MAX, sfile->params->dir, sfile->params->file);
+
+ if ((prop = RNA_struct_find_property(op->ptr, "relative_path"))) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ BLI_path_rel(filepath, BKE_main_blendfile_path(bmain));
+ }
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "filename"))) {
+ RNA_property_string_set(op->ptr, prop, sfile->params->file);
+ }
+ if ((prop = RNA_struct_find_property(op->ptr, "directory"))) {
+ RNA_property_string_set(op->ptr, prop, sfile->params->dir);
+ }
+ if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) {
+ RNA_property_string_set(op->ptr, prop, filepath);
+ }
+
+ /* some ops have multiple files to select */
+ /* this is called on operators check() so clear collections first since
+ * they may be already set. */
+ {
+ int i, numfiles = filelist_files_ensure(sfile->files);
+
+ if ((prop = RNA_struct_find_property(op->ptr, "files"))) {
+ PointerRNA itemptr;
+ int num_files = 0;
+ RNA_property_collection_clear(op->ptr, prop);
+ for (i = 0; i < numfiles; i++) {
+ if (filelist_entry_select_index_get(sfile->files, i, CHECK_FILES)) {
+ FileDirEntry *file = filelist_file(sfile->files, i);
+ RNA_property_collection_add(op->ptr, prop, &itemptr);
+ RNA_string_set(&itemptr, "name", file->relpath);
+ num_files++;
+ }
+ }
+ /* make sure the file specified in the filename button is added even if no
+ * files selected */
+ if (0 == num_files) {
+ RNA_property_collection_add(op->ptr, prop, &itemptr);
+ RNA_string_set(&itemptr, "name", sfile->params->file);
+ }
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "dirs"))) {
+ PointerRNA itemptr;
+ int num_dirs = 0;
+ RNA_property_collection_clear(op->ptr, prop);
+ for (i = 0; i < numfiles; i++) {
+ if (filelist_entry_select_index_get(sfile->files, i, CHECK_DIRS)) {
+ FileDirEntry *file = filelist_file(sfile->files, i);
+ RNA_property_collection_add(op->ptr, prop, &itemptr);
+ RNA_string_set(&itemptr, "name", file->relpath);
+ num_dirs++;
+ }
+ }
+
+ /* make sure the directory specified in the button is added even if no
+ * directory selected */
+ if (0 == num_dirs) {
+ RNA_property_collection_add(op->ptr, prop, &itemptr);
+ RNA_string_set(&itemptr, "name", sfile->params->dir);
+ }
+ }
+ }
}
void file_sfile_to_operator(bContext *C, wmOperator *op, SpaceFile *sfile)
{
- char filepath[FILE_MAX];
+ char filepath[FILE_MAX];
- file_sfile_to_operator_ex(C, op, sfile, filepath);
+ file_sfile_to_operator_ex(C, op, sfile, filepath);
}
void file_operator_to_sfile(bContext *C, SpaceFile *sfile, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- PropertyRNA *prop;
-
- /* If neither of the above are set, split the filepath back */
- if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) {
- char filepath[FILE_MAX];
- RNA_property_string_get(op->ptr, prop, filepath);
- BLI_split_dirfile(filepath, sfile->params->dir, sfile->params->file, sizeof(sfile->params->dir), sizeof(sfile->params->file));
- }
- else {
- if ((prop = RNA_struct_find_property(op->ptr, "filename"))) {
- RNA_property_string_get(op->ptr, prop, sfile->params->file);
- }
- if ((prop = RNA_struct_find_property(op->ptr, "directory"))) {
- RNA_property_string_get(op->ptr, prop, sfile->params->dir);
- }
- }
-
- /* we could check for relative_path property which is used when converting
- * in the other direction but doesn't hurt to do this every time */
- BLI_path_abs(sfile->params->dir, BKE_main_blendfile_path(bmain));
-
- /* XXX, files and dirs updates missing, not really so important though */
+ Main *bmain = CTX_data_main(C);
+ PropertyRNA *prop;
+
+ /* If neither of the above are set, split the filepath back */
+ if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) {
+ char filepath[FILE_MAX];
+ RNA_property_string_get(op->ptr, prop, filepath);
+ BLI_split_dirfile(filepath,
+ sfile->params->dir,
+ sfile->params->file,
+ sizeof(sfile->params->dir),
+ sizeof(sfile->params->file));
+ }
+ else {
+ if ((prop = RNA_struct_find_property(op->ptr, "filename"))) {
+ RNA_property_string_get(op->ptr, prop, sfile->params->file);
+ }
+ if ((prop = RNA_struct_find_property(op->ptr, "directory"))) {
+ RNA_property_string_get(op->ptr, prop, sfile->params->dir);
+ }
+ }
+
+ /* we could check for relative_path property which is used when converting
+ * in the other direction but doesn't hurt to do this every time */
+ BLI_path_abs(sfile->params->dir, BKE_main_blendfile_path(bmain));
+
+ /* XXX, files and dirs updates missing, not really so important though */
}
/**
@@ -1316,433 +1356,439 @@ void file_operator_to_sfile(bContext *C, SpaceFile *sfile, wmOperator *op)
*/
void file_sfile_filepath_set(SpaceFile *sfile, const char *filepath)
{
- BLI_assert(BLI_exists(filepath));
-
- if (BLI_is_dir(filepath)) {
- BLI_strncpy(sfile->params->dir, filepath, sizeof(sfile->params->dir));
- }
- else {
- if ((sfile->params->flag & FILE_DIRSEL_ONLY) == 0) {
- BLI_split_dirfile(filepath, sfile->params->dir, sfile->params->file,
- sizeof(sfile->params->dir), sizeof(sfile->params->file));
- }
- else {
- BLI_split_dir_part(filepath, sfile->params->dir, sizeof(sfile->params->dir));
- }
- }
+ BLI_assert(BLI_exists(filepath));
+
+ if (BLI_is_dir(filepath)) {
+ BLI_strncpy(sfile->params->dir, filepath, sizeof(sfile->params->dir));
+ }
+ else {
+ if ((sfile->params->flag & FILE_DIRSEL_ONLY) == 0) {
+ BLI_split_dirfile(filepath,
+ sfile->params->dir,
+ sfile->params->file,
+ sizeof(sfile->params->dir),
+ sizeof(sfile->params->file));
+ }
+ else {
+ BLI_split_dir_part(filepath, sfile->params->dir, sizeof(sfile->params->dir));
+ }
+ }
}
void file_draw_check(bContext *C)
{
- SpaceFile *sfile = CTX_wm_space_file(C);
- wmOperator *op = sfile->op;
- if (op) { /* fail on reload */
- if (op->type->check) {
- file_sfile_to_operator(C, op, sfile);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ wmOperator *op = sfile->op;
+ if (op) { /* fail on reload */
+ if (op->type->check) {
+ file_sfile_to_operator(C, op, sfile);
- /* redraw */
- if (op->type->check(C, op)) {
- file_operator_to_sfile(C, sfile, op);
+ /* redraw */
+ if (op->type->check(C, op)) {
+ file_operator_to_sfile(C, sfile, op);
- /* redraw, else the changed settings wont get updated */
- ED_area_tag_redraw(CTX_wm_area(C));
- }
- }
- }
+ /* redraw, else the changed settings wont get updated */
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+ }
+ }
}
/* for use with; UI_block_func_set */
void file_draw_check_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
{
- file_draw_check(C);
+ file_draw_check(C);
}
bool file_draw_check_exists(SpaceFile *sfile)
{
- if (sfile->op) { /* fails on reload */
- PropertyRNA *prop;
- if ((prop = RNA_struct_find_property(sfile->op->ptr, "check_existing"))) {
- if (RNA_property_boolean_get(sfile->op->ptr, prop)) {
- char filepath[FILE_MAX];
- BLI_join_dirfile(filepath, sizeof(filepath), sfile->params->dir, sfile->params->file);
- if (BLI_is_file(filepath)) {
- return true;
- }
- }
- }
- }
+ if (sfile->op) { /* fails on reload */
+ PropertyRNA *prop;
+ if ((prop = RNA_struct_find_property(sfile->op->ptr, "check_existing"))) {
+ if (RNA_property_boolean_get(sfile->op->ptr, prop)) {
+ char filepath[FILE_MAX];
+ BLI_join_dirfile(filepath, sizeof(filepath), sfile->params->dir, sfile->params->file);
+ if (BLI_is_file(filepath)) {
+ return true;
+ }
+ }
+ }
+ }
- return false;
+ return false;
}
int file_exec(bContext *C, wmOperator *exec_op)
{
- Main *bmain = CTX_data_main(C);
- wmWindowManager *wm = CTX_wm_manager(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
- const struct FileDirEntry *file = filelist_file(sfile->files, sfile->params->active_file);
- char filepath[FILE_MAX];
-
- /* directory change */
- if (file && (file->typeflag & FILE_TYPE_DIR)) {
- if (!file->relpath) {
- return OPERATOR_CANCELLED;
- }
-
- if (FILENAME_IS_PARENT(file->relpath)) {
- BLI_parent_dir(sfile->params->dir);
- }
- else {
- BLI_cleanup_path(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);
- }
-
- ED_file_change_dir(C);
- }
- /* opening file - sends events now, so things get handled on windowqueue level */
- else if (sfile->op) {
- wmOperator *op = sfile->op;
-
- /* when used as a macro, for doubleclick,
- * to prevent closing when doubleclicking on .. item */
- if (RNA_boolean_get(exec_op->ptr, "need_active")) {
- const int numfiles = filelist_files_ensure(sfile->files);
- int i, active = 0;
-
- for (i = 0; i < numfiles; i++) {
- if (filelist_entry_select_index_get(sfile->files, i, CHECK_ALL)) {
- active = 1;
- break;
- }
- }
- if (active == 0)
- return OPERATOR_CANCELLED;
- }
-
- sfile->op = NULL;
-
- file_sfile_to_operator_ex(C, op, sfile, filepath);
-
- if (BLI_exists(sfile->params->dir)) {
- fsmenu_insert_entry(ED_fsmenu_get(), FS_CATEGORY_RECENT, sfile->params->dir, NULL,
- 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);
- fsmenu_write_file(ED_fsmenu_get(), filepath);
- WM_event_fileselect_event(wm, op, EVT_FILESELECT_EXEC);
-
- }
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ const struct FileDirEntry *file = filelist_file(sfile->files, sfile->params->active_file);
+ char filepath[FILE_MAX];
+
+ /* directory change */
+ if (file && (file->typeflag & FILE_TYPE_DIR)) {
+ if (!file->relpath) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (FILENAME_IS_PARENT(file->relpath)) {
+ BLI_parent_dir(sfile->params->dir);
+ }
+ else {
+ BLI_cleanup_path(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);
+ }
+
+ ED_file_change_dir(C);
+ }
+ /* opening file - sends events now, so things get handled on windowqueue level */
+ else if (sfile->op) {
+ wmOperator *op = sfile->op;
+
+ /* when used as a macro, for doubleclick,
+ * to prevent closing when doubleclicking on .. item */
+ if (RNA_boolean_get(exec_op->ptr, "need_active")) {
+ const int numfiles = filelist_files_ensure(sfile->files);
+ int i, active = 0;
+
+ for (i = 0; i < numfiles; i++) {
+ if (filelist_entry_select_index_get(sfile->files, i, CHECK_ALL)) {
+ active = 1;
+ break;
+ }
+ }
+ if (active == 0)
+ return OPERATOR_CANCELLED;
+ }
+
+ sfile->op = NULL;
+
+ file_sfile_to_operator_ex(C, op, sfile, filepath);
+
+ if (BLI_exists(sfile->params->dir)) {
+ fsmenu_insert_entry(ED_fsmenu_get(),
+ FS_CATEGORY_RECENT,
+ sfile->params->dir,
+ NULL,
+ 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);
+ fsmenu_write_file(ED_fsmenu_get(), filepath);
+ WM_event_fileselect_event(wm, op, EVT_FILESELECT_EXEC);
+ }
+
+ return OPERATOR_FINISHED;
}
void FILE_OT_execute(struct wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Execute File Window";
- ot->description = "Execute selected file";
- ot->idname = "FILE_OT_execute";
+ /* identifiers */
+ ot->name = "Execute File Window";
+ ot->description = "Execute selected file";
+ ot->idname = "FILE_OT_execute";
- /* api callbacks */
- ot->exec = file_exec;
- ot->poll = file_operator_poll;
+ /* api callbacks */
+ ot->exec = file_exec;
+ ot->poll = file_operator_poll;
- /* properties */
- prop = RNA_def_boolean(ot->srna, "need_active", 0, "Need Active",
- "Only execute if there's an active selected file in the file list");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ prop = RNA_def_boolean(ot->srna,
+ "need_active",
+ 0,
+ "Need Active",
+ "Only execute if there's an active selected file in the file list");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-
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);
- ED_file_change_dir(C);
- if (sfile->params->recursion_level > 1) {
- /* Disable 'dirtree' recursion when going up in tree. */
- sfile->params->recursion_level = 0;
- filelist_setrecursion(sfile->files, sfile->params->recursion_level);
- }
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
- }
- }
+ Main *bmain = CTX_data_main(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
- return OPERATOR_FINISHED;
+ if (sfile->params) {
+ if (BLI_parent_dir(sfile->params->dir)) {
+ BLI_cleanup_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. */
+ sfile->params->recursion_level = 0;
+ filelist_setrecursion(sfile->files, sfile->params->recursion_level);
+ }
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+ }
+ }
+ return OPERATOR_FINISHED;
}
-
void FILE_OT_parent(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Parent File";
- ot->description = "Move to parent directory";
- ot->idname = "FILE_OT_parent";
+ /* identifiers */
+ ot->name = "Parent File";
+ ot->description = "Move to parent directory";
+ ot->idname = "FILE_OT_parent";
- /* api callbacks */
- ot->exec = file_parent_exec;
- ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
+ /* api callbacks */
+ ot->exec = file_parent_exec;
+ ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
}
-
static int file_refresh_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);
- struct FSMenu *fsmenu = ED_fsmenu_get();
-
- ED_fileselect_clear(wm, sa, sfile);
+ 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();
- /* refresh system directory menu */
- fsmenu_refresh_system_category(fsmenu);
+ ED_fileselect_clear(wm, sa, sfile);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+ /* refresh system directory menu */
+ fsmenu_refresh_system_category(fsmenu);
- return OPERATOR_FINISHED;
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+ return OPERATOR_FINISHED;
}
void FILE_OT_previous(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Previous Folder";
- ot->description = "Move to previous folder";
- ot->idname = "FILE_OT_previous";
+ /* identifiers */
+ ot->name = "Previous Folder";
+ ot->description = "Move to previous folder";
+ ot->idname = "FILE_OT_previous";
- /* api callbacks */
- ot->exec = file_previous_exec;
- ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
+ /* api callbacks */
+ ot->exec = file_previous_exec;
+ ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
}
int file_previous_exec(bContext *C, wmOperator *UNUSED(unused))
{
- SpaceFile *sfile = CTX_wm_space_file(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
- if (sfile->params) {
- if (!sfile->folders_next)
- sfile->folders_next = folderlist_new();
+ 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_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);
+ ED_file_change_dir(C);
+ }
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void FILE_OT_next(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Next Folder";
- ot->description = "Move to next folder";
- ot->idname = "FILE_OT_next";
+ /* identifiers */
+ ot->name = "Next Folder";
+ ot->description = "Move to next folder";
+ ot->idname = "FILE_OT_next";
- /* api callbacks */
- ot->exec = file_next_exec;
- ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
+ /* api callbacks */
+ ot->exec = file_next_exec;
+ 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();
+ 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);
+ 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);
+ // 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);
+ ED_file_change_dir(C);
+ }
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
/* only meant for timer usage */
static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- ScrArea *sa = CTX_wm_area(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
- ARegion *ar, *oldar = CTX_wm_region(C);
- int offset;
- int numfiles, numfiles_layout;
- int edit_idx = -1;
- int i;
-
- /* escape if not our timer */
- if (sfile->smoothscroll_timer == NULL || sfile->smoothscroll_timer != event->customdata)
- return OPERATOR_PASS_THROUGH;
-
- numfiles = filelist_files_ensure(sfile->files);
-
- /* Due to async nature of file listing, we may execute this code before `file_refresh()`
- * editing entry is available in our listing, so we also have to handle switching to rename mode here. */
- FileSelectParams *params = ED_fileselect_get_params(sfile);
- if ((params->rename_flag & (FILE_PARAMS_RENAME_PENDING | FILE_PARAMS_RENAME_POSTSCROLL_PENDING)) != 0) {
- file_params_renamefile_activate(sfile, params);
- }
-
- /* check if we are editing a name */
- for (i = 0; i < numfiles; ++i) {
- if (filelist_entry_select_index_get(sfile->files, i, CHECK_ALL) & (FILE_SEL_EDITING | FILE_SEL_HIGHLIGHTED)) {
- edit_idx = i;
- break;
- }
- }
-
- /* if we are not editing, we are done */
- if (edit_idx == -1) {
- /* Do not invalidate timer if filerename is still pending, we might still be building the filelist
- * and yet have to find edited entry... */
- if (params->rename_flag == 0) {
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
- sfile->smoothscroll_timer = NULL;
- }
- return OPERATOR_PASS_THROUGH;
- }
-
- /* we need the correct area for scrolling */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (!ar || ar->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;
- }
-
- offset = max_ii(0, ED_fileselect_layout_offset(sfile->layout, (int)ar->v2d.cur.xmin, (int)-ar->v2d.cur.ymax));
-
- /* scroll offset is the first file in the row/column we are editing in */
- if (sfile->scroll_offset == 0) {
- if (sfile->layout->flag & FILE_LAYOUT_HOR) {
- sfile->scroll_offset = (edit_idx / sfile->layout->rows) * sfile->layout->rows;
- if (sfile->scroll_offset <= offset) sfile->scroll_offset -= sfile->layout->rows;
- }
- else {
- sfile->scroll_offset = (edit_idx / sfile->layout->columns) * sfile->layout->columns;
- if (sfile->scroll_offset <= offset) sfile->scroll_offset -= sfile->layout->columns;
- }
- }
-
- numfiles_layout = ED_fileselect_layout_numfiles(sfile->layout, ar);
- /* Using margins helps avoiding scrolling to stop when target item is barely visible on one side of the screen
- * (i.e. it centers a bit more the target). */
- int numfiles_layout_margin = max_ii(0, numfiles_layout / 3);
-
- /* check if we have reached our final scroll position */
- if ((sfile->scroll_offset >= offset + numfiles_layout_margin) &&
- (sfile->scroll_offset < offset + numfiles_layout - numfiles_layout_margin))
- {
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
- sfile->smoothscroll_timer = NULL;
- /* Postscroll (after rename has been validated by user) is done, rename process is totally finisehd, cleanup. */
- if ((params->rename_flag & FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE) != 0) {
- params->renamefile[0] = '\0';
- params->rename_flag = 0;
- }
- return OPERATOR_FINISHED;
- }
-
- /* temporarily set context to the main window region,
- * so the scroll operators work */
- CTX_wm_region_set(C, ar);
-
- /* scroll one step in the desired direction */
- if (sfile->scroll_offset < offset) {
- if (sfile->layout->flag & FILE_LAYOUT_HOR) {
- WM_operator_name_call(C, "VIEW2D_OT_scroll_left", 0, NULL);
- }
- else {
- WM_operator_name_call(C, "VIEW2D_OT_scroll_up", 0, NULL);
- }
-
- }
- else {
- if (sfile->layout->flag & FILE_LAYOUT_HOR) {
- WM_operator_name_call(C, "VIEW2D_OT_scroll_right", 0, NULL);
- }
- else {
- WM_operator_name_call(C, "VIEW2D_OT_scroll_down", 0, NULL);
- }
- }
-
- ED_region_tag_redraw(ar);
-
- /* and restore context */
- CTX_wm_region_set(C, oldar);
-
- return OPERATOR_FINISHED;
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ ARegion *ar, *oldar = CTX_wm_region(C);
+ int offset;
+ int numfiles, numfiles_layout;
+ int edit_idx = -1;
+ int i;
+
+ /* escape if not our timer */
+ if (sfile->smoothscroll_timer == NULL || sfile->smoothscroll_timer != event->customdata)
+ return OPERATOR_PASS_THROUGH;
+
+ numfiles = filelist_files_ensure(sfile->files);
+
+ /* Due to async nature of file listing, we may execute this code before `file_refresh()`
+ * editing entry is available in our listing, so we also have to handle switching to rename mode here. */
+ FileSelectParams *params = ED_fileselect_get_params(sfile);
+ if ((params->rename_flag &
+ (FILE_PARAMS_RENAME_PENDING | FILE_PARAMS_RENAME_POSTSCROLL_PENDING)) != 0) {
+ file_params_renamefile_activate(sfile, params);
+ }
+
+ /* check if we are editing a name */
+ for (i = 0; i < numfiles; ++i) {
+ if (filelist_entry_select_index_get(sfile->files, i, CHECK_ALL) &
+ (FILE_SEL_EDITING | FILE_SEL_HIGHLIGHTED)) {
+ edit_idx = i;
+ break;
+ }
+ }
+
+ /* if we are not editing, we are done */
+ if (edit_idx == -1) {
+ /* Do not invalidate timer if filerename is still pending, we might still be building the filelist
+ * and yet have to find edited entry... */
+ if (params->rename_flag == 0) {
+ WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
+ sfile->smoothscroll_timer = NULL;
+ }
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ /* we need the correct area for scrolling */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ if (!ar || ar->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;
+ }
+
+ offset = max_ii(
+ 0,
+ ED_fileselect_layout_offset(sfile->layout, (int)ar->v2d.cur.xmin, (int)-ar->v2d.cur.ymax));
+
+ /* scroll offset is the first file in the row/column we are editing in */
+ if (sfile->scroll_offset == 0) {
+ if (sfile->layout->flag & FILE_LAYOUT_HOR) {
+ sfile->scroll_offset = (edit_idx / sfile->layout->rows) * sfile->layout->rows;
+ if (sfile->scroll_offset <= offset)
+ sfile->scroll_offset -= sfile->layout->rows;
+ }
+ else {
+ sfile->scroll_offset = (edit_idx / sfile->layout->columns) * sfile->layout->columns;
+ if (sfile->scroll_offset <= offset)
+ sfile->scroll_offset -= sfile->layout->columns;
+ }
+ }
+
+ numfiles_layout = ED_fileselect_layout_numfiles(sfile->layout, ar);
+ /* Using margins helps avoiding scrolling to stop when target item is barely visible on one side of the screen
+ * (i.e. it centers a bit more the target). */
+ int numfiles_layout_margin = max_ii(0, numfiles_layout / 3);
+
+ /* check if we have reached our final scroll position */
+ if ((sfile->scroll_offset >= offset + numfiles_layout_margin) &&
+ (sfile->scroll_offset < offset + numfiles_layout - numfiles_layout_margin)) {
+ WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
+ sfile->smoothscroll_timer = NULL;
+ /* Postscroll (after rename has been validated by user) is done, rename process is totally finisehd, cleanup. */
+ if ((params->rename_flag & FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE) != 0) {
+ params->renamefile[0] = '\0';
+ params->rename_flag = 0;
+ }
+ return OPERATOR_FINISHED;
+ }
+
+ /* temporarily set context to the main window region,
+ * so the scroll operators work */
+ CTX_wm_region_set(C, ar);
+
+ /* scroll one step in the desired direction */
+ if (sfile->scroll_offset < offset) {
+ if (sfile->layout->flag & FILE_LAYOUT_HOR) {
+ WM_operator_name_call(C, "VIEW2D_OT_scroll_left", 0, NULL);
+ }
+ else {
+ WM_operator_name_call(C, "VIEW2D_OT_scroll_up", 0, NULL);
+ }
+ }
+ else {
+ if (sfile->layout->flag & FILE_LAYOUT_HOR) {
+ WM_operator_name_call(C, "VIEW2D_OT_scroll_right", 0, NULL);
+ }
+ else {
+ WM_operator_name_call(C, "VIEW2D_OT_scroll_down", 0, NULL);
+ }
+ }
+
+ ED_region_tag_redraw(ar);
+
+ /* and restore context */
+ CTX_wm_region_set(C, oldar);
+
+ return OPERATOR_FINISHED;
}
-
void FILE_OT_smoothscroll(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Smooth Scroll";
- ot->idname = "FILE_OT_smoothscroll";
- ot->description = "Smooth scroll to make editable file visible";
+ /* identifiers */
+ ot->name = "Smooth Scroll";
+ ot->idname = "FILE_OT_smoothscroll";
+ ot->description = "Smooth scroll to make editable file visible";
- /* api callbacks */
- ot->invoke = file_smoothscroll_invoke;
+ /* api callbacks */
+ ot->invoke = file_smoothscroll_invoke;
- ot->poll = ED_operator_file_active;
+ ot->poll = ED_operator_file_active;
}
-
static int filepath_drop_exec(bContext *C, wmOperator *op)
{
- SpaceFile *sfile = CTX_wm_space_file(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
- if (sfile) {
- char filepath[FILE_MAX];
+ if (sfile) {
+ char filepath[FILE_MAX];
- RNA_string_get(op->ptr, "filepath", filepath);
- if (!BLI_exists(filepath)) {
- BKE_report(op->reports, RPT_ERROR, "File does not exist");
- return OPERATOR_CANCELLED;
- }
+ RNA_string_get(op->ptr, "filepath", filepath);
+ if (!BLI_exists(filepath)) {
+ BKE_report(op->reports, RPT_ERROR, "File does not exist");
+ return OPERATOR_CANCELLED;
+ }
- file_sfile_filepath_set(sfile, filepath);
+ file_sfile_filepath_set(sfile, filepath);
- if (sfile->op) {
- file_sfile_to_operator(C, sfile->op, sfile);
- file_draw_check(C);
- }
+ if (sfile->op) {
+ file_sfile_to_operator(C, sfile->op, sfile);
+ file_draw_check(C);
+ }
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
- return OPERATOR_FINISHED;
- }
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
void FILE_OT_filepath_drop(wmOperatorType *ot)
{
- ot->name = "File Selector Drop";
- ot->idname = "FILE_OT_filepath_drop";
+ ot->name = "File Selector Drop";
+ ot->idname = "FILE_OT_filepath_drop";
- ot->exec = filepath_drop_exec;
- ot->poll = WM_operator_winactive;
+ ot->exec = filepath_drop_exec;
+ ot->poll = WM_operator_winactive;
- RNA_def_string_file_path(ot->srna, "filepath", "Path", FILE_MAX, "", "");
+ RNA_def_string_file_path(ot->srna, "filepath", "Path", FILE_MAX, "", "");
}
/* create a new, non-existing folder name, returns 1 if successful, 0 if name couldn't be created.
@@ -1750,616 +1796,615 @@ void FILE_OT_filepath_drop(wmOperatorType *ot)
*/
static int new_folder_path(const char *parent, char *folder, char *name)
{
- int i = 1;
- int len = 0;
+ int i = 1;
+ int len = 0;
- BLI_strncpy(name, "New Folder", FILE_MAXFILE);
- BLI_join_dirfile(folder, FILE_MAX, parent, name); /* XXX, not real length */
- /* check whether folder with the name already exists, in this case
- * add number to the name. Check length of generated name to avoid
- * crazy case of huge number of folders each named 'New Folder (x)' */
- while (BLI_exists(folder) && (len < FILE_MAXFILE)) {
- len = BLI_snprintf(name, FILE_MAXFILE, "New Folder(%d)", i);
- BLI_join_dirfile(folder, FILE_MAX, parent, name); /* XXX, not real length */
- i++;
- }
+ BLI_strncpy(name, "New Folder", FILE_MAXFILE);
+ BLI_join_dirfile(folder, FILE_MAX, parent, name); /* XXX, not real length */
+ /* check whether folder with the name already exists, in this case
+ * add number to the name. Check length of generated name to avoid
+ * crazy case of huge number of folders each named 'New Folder (x)' */
+ while (BLI_exists(folder) && (len < FILE_MAXFILE)) {
+ len = BLI_snprintf(name, FILE_MAXFILE, "New Folder(%d)", i);
+ BLI_join_dirfile(folder, FILE_MAX, parent, name); /* XXX, not real length */
+ i++;
+ }
- return (len < FILE_MAXFILE);
+ return (len < FILE_MAXFILE);
}
int file_directory_new_exec(bContext *C, wmOperator *op)
{
- char name[FILE_MAXFILE];
- char path[FILE_MAX];
- bool generate_name = true;
- PropertyRNA *prop;
-
- wmWindowManager *wm = CTX_wm_manager(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
- ScrArea *sa = CTX_wm_area(C);
-
- if (!sfile->params) {
- BKE_report(op->reports, RPT_WARNING, "No parent directory given");
- return OPERATOR_CANCELLED;
- }
-
- path[0] = '\0';
-
- if ((prop = RNA_struct_find_property(op->ptr, "directory"))) {
- RNA_property_string_get(op->ptr, prop, path);
- if (path[0] != '\0') {
- generate_name = false;
- }
- }
-
- if (generate_name) {
- /* create a new, non-existing folder name */
- if (!new_folder_path(sfile->params->dir, path, name)) {
- BKE_report(op->reports, RPT_ERROR, "Could not create new folder name");
- return OPERATOR_CANCELLED;
- }
- }
- else { /* We assume we are able to generate a valid name! */
- char org_path[FILE_MAX];
-
- BLI_strncpy(org_path, path, sizeof(org_path));
- if (BLI_path_make_safe(path)) {
- BKE_reportf(op->reports, RPT_WARNING, "'%s' given path is OS-invalid, creating '%s' path instead",
- org_path, path);
- }
- }
-
- /* create the file */
- errno = 0;
- if (!BLI_dir_create_recursive(path) ||
- /* Should no more be needed,
- * now that BLI_dir_create_recursive returns a success state - but kept just in case. */
- !BLI_exists(path))
- {
- BKE_reportf(op->reports, RPT_ERROR,
- "Could not create new folder: %s",
- errno ? strerror(errno) : "unknown error");
- return OPERATOR_CANCELLED;
- }
-
-
- /* now remember file to jump into editing */
- BLI_strncpy(sfile->params->renamefile, name, FILE_MAXFILE);
- sfile->params->rename_flag = FILE_PARAMS_RENAME_PENDING;
-
- /* 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);
- }
- 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);
-
- if (RNA_boolean_get(op->ptr, "open")) {
- BLI_strncpy(sfile->params->dir, path, sizeof(sfile->params->dir));
- ED_file_change_dir(C);
- }
-
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
-
- return OPERATOR_FINISHED;
+ char name[FILE_MAXFILE];
+ char path[FILE_MAX];
+ bool generate_name = true;
+ PropertyRNA *prop;
+
+ wmWindowManager *wm = CTX_wm_manager(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ ScrArea *sa = CTX_wm_area(C);
+
+ if (!sfile->params) {
+ BKE_report(op->reports, RPT_WARNING, "No parent directory given");
+ return OPERATOR_CANCELLED;
+ }
+
+ path[0] = '\0';
+
+ if ((prop = RNA_struct_find_property(op->ptr, "directory"))) {
+ RNA_property_string_get(op->ptr, prop, path);
+ if (path[0] != '\0') {
+ generate_name = false;
+ }
+ }
+
+ if (generate_name) {
+ /* create a new, non-existing folder name */
+ if (!new_folder_path(sfile->params->dir, path, name)) {
+ BKE_report(op->reports, RPT_ERROR, "Could not create new folder name");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else { /* We assume we are able to generate a valid name! */
+ char org_path[FILE_MAX];
+
+ BLI_strncpy(org_path, path, sizeof(org_path));
+ if (BLI_path_make_safe(path)) {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "'%s' given path is OS-invalid, creating '%s' path instead",
+ org_path,
+ path);
+ }
+ }
+
+ /* create the file */
+ errno = 0;
+ if (!BLI_dir_create_recursive(path) ||
+ /* Should no more be needed,
+ * now that BLI_dir_create_recursive returns a success state - but kept just in case. */
+ !BLI_exists(path)) {
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "Could not create new folder: %s",
+ errno ? strerror(errno) : "unknown error");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* now remember file to jump into editing */
+ BLI_strncpy(sfile->params->renamefile, name, FILE_MAXFILE);
+ sfile->params->rename_flag = FILE_PARAMS_RENAME_PENDING;
+
+ /* 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);
+ }
+ 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);
+
+ if (RNA_boolean_get(op->ptr, "open")) {
+ BLI_strncpy(sfile->params->dir, path, sizeof(sfile->params->dir));
+ ED_file_change_dir(C);
+ }
+
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+
+ return OPERATOR_FINISHED;
}
-
void FILE_OT_directory_new(struct wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Create New Directory";
- ot->description = "Create a new directory";
- ot->idname = "FILE_OT_directory_new";
+ /* identifiers */
+ ot->name = "Create New Directory";
+ ot->description = "Create a new directory";
+ ot->idname = "FILE_OT_directory_new";
- /* api callbacks */
- ot->invoke = WM_operator_confirm;
- ot->exec = file_directory_new_exec;
- ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = file_directory_new_exec;
+ ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
- prop = RNA_def_string_dir_path(ot->srna, "directory", NULL, FILE_MAX, "Directory", "Name of new directory");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "open", false, "Open", "Open new directory");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_string_dir_path(
+ ot->srna, "directory", NULL, FILE_MAX, "Directory", "Name of new directory");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "open", false, "Open", "Open new directory");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-
/* TODO This should go to BLI_path_utils. */
static void file_expand_directory(bContext *C)
{
- Main *bmain = CTX_data_main(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
-
- if (sfile->params) {
- if (BLI_path_is_rel(sfile->params->dir)) {
- /* Use of 'default' folder here is just to avoid an error message on '//' prefix. */
- BLI_path_abs(sfile->params->dir, G.relbase_valid ? BKE_main_blendfile_path(bmain) : BKE_appdir_folder_default());
- }
- else if (sfile->params->dir[0] == '~') {
- char tmpstr[sizeof(sfile->params->dir) - 1];
- BLI_strncpy(tmpstr, sfile->params->dir + 1, sizeof(tmpstr));
- BLI_join_dirfile(sfile->params->dir, sizeof(sfile->params->dir), BKE_appdir_folder_default(), tmpstr);
- }
-
- else if (sfile->params->dir[0] == '\0')
+ Main *bmain = CTX_data_main(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+
+ if (sfile->params) {
+ if (BLI_path_is_rel(sfile->params->dir)) {
+ /* Use of 'default' folder here is just to avoid an error message on '//' prefix. */
+ BLI_path_abs(sfile->params->dir,
+ G.relbase_valid ? BKE_main_blendfile_path(bmain) : BKE_appdir_folder_default());
+ }
+ else if (sfile->params->dir[0] == '~') {
+ char tmpstr[sizeof(sfile->params->dir) - 1];
+ BLI_strncpy(tmpstr, sfile->params->dir + 1, sizeof(tmpstr));
+ BLI_join_dirfile(
+ sfile->params->dir, sizeof(sfile->params->dir), BKE_appdir_folder_default(), tmpstr);
+ }
+
+ else if (sfile->params->dir[0] == '\0')
#ifndef WIN32
- {
- sfile->params->dir[0] = '/';
- sfile->params->dir[1] = '\0';
- }
+ {
+ sfile->params->dir[0] = '/';
+ sfile->params->dir[1] = '\0';
+ }
#else
- {
- get_default_root(sfile->params->dir);
- }
- /* change "C:" --> "C:\", [#28102] */
- else if ((isalpha(sfile->params->dir[0]) &&
- (sfile->params->dir[1] == ':')) &&
- (sfile->params->dir[2] == '\0'))
- {
- sfile->params->dir[2] = '\\';
- sfile->params->dir[3] = '\0';
- }
- else if (BLI_path_is_unc(sfile->params->dir)) {
- BLI_cleanup_unc(sfile->params->dir, FILE_MAX_LIBEXTRA);
- }
+ {
+ get_default_root(sfile->params->dir);
+ }
+ /* change "C:" --> "C:\", [#28102] */
+ else if ((isalpha(sfile->params->dir[0]) && (sfile->params->dir[1] == ':')) &&
+ (sfile->params->dir[2] == '\0')) {
+ sfile->params->dir[2] = '\\';
+ sfile->params->dir[3] = '\0';
+ }
+ else if (BLI_path_is_unc(sfile->params->dir)) {
+ BLI_cleanup_unc(sfile->params->dir, FILE_MAX_LIBEXTRA);
+ }
#endif
- }
+ }
}
/* TODO check we still need this, it's annoying to have OS-specific code here... :/ */
#if defined(WIN32)
static bool can_create_dir(const char *dir)
{
- /* for UNC paths we need to check whether the parent of the new
- * directory is a proper directory itself and not a share or the
- * UNC root (server name) itself. Calling BLI_is_dir does this
- */
- if (BLI_path_is_unc(dir)) {
- char parent[PATH_MAX];
- BLI_strncpy(parent, dir, PATH_MAX);
- BLI_parent_dir(parent);
- return BLI_is_dir(parent);
- }
- return true;
+ /* for UNC paths we need to check whether the parent of the new
+ * directory is a proper directory itself and not a share or the
+ * UNC root (server name) itself. Calling BLI_is_dir does this
+ */
+ if (BLI_path_is_unc(dir)) {
+ char parent[PATH_MAX];
+ BLI_strncpy(parent, dir, PATH_MAX);
+ BLI_parent_dir(parent);
+ return BLI_is_dir(parent);
+ }
+ return true;
}
#endif
void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UNUSED(arg_but))
{
- Main *bmain = CTX_data_main(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
-
- if (sfile->params) {
- file_expand_directory(C);
-
- /* special case, user may have pasted a filepath into the directory */
- if (!filelist_is_dir(sfile->files, sfile->params->dir)) {
- char tdir[FILE_MAX_LIBEXTRA];
- char *group, *name;
-
- if (BLI_is_file(sfile->params->dir)) {
- char path[sizeof(sfile->params->dir)];
- BLI_strncpy(path, sfile->params->dir, sizeof(path));
- BLI_split_dirfile(path, sfile->params->dir, sfile->params->file,
- sizeof(sfile->params->dir), sizeof(sfile->params->file));
- }
- else if (BLO_library_path_explode(sfile->params->dir, tdir, &group, &name)) {
- if (group) {
- BLI_path_append(tdir, sizeof(tdir), group);
- }
- BLI_strncpy(sfile->params->dir, tdir, sizeof(sfile->params->dir));
- if (name) {
- BLI_strncpy(sfile->params->file, name, sizeof(sfile->params->file));
- }
- else {
- sfile->params->file[0] = '\0';
- }
- }
- }
-
- BLI_cleanup_dir(BKE_main_blendfile_path(bmain), sfile->params->dir);
-
- if (filelist_is_dir(sfile->files, sfile->params->dir)) {
- /* if directory exists, enter it immediately */
- ED_file_change_dir(C);
-
- /* don't do for now because it selects entire text instead of
- * placing cursor at the end */
- /* UI_textbutton_activate_but(C, but); */
- }
+ Main *bmain = CTX_data_main(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+
+ if (sfile->params) {
+ file_expand_directory(C);
+
+ /* special case, user may have pasted a filepath into the directory */
+ if (!filelist_is_dir(sfile->files, sfile->params->dir)) {
+ char tdir[FILE_MAX_LIBEXTRA];
+ char *group, *name;
+
+ if (BLI_is_file(sfile->params->dir)) {
+ char path[sizeof(sfile->params->dir)];
+ BLI_strncpy(path, sfile->params->dir, sizeof(path));
+ BLI_split_dirfile(path,
+ sfile->params->dir,
+ sfile->params->file,
+ sizeof(sfile->params->dir),
+ sizeof(sfile->params->file));
+ }
+ else if (BLO_library_path_explode(sfile->params->dir, tdir, &group, &name)) {
+ if (group) {
+ BLI_path_append(tdir, sizeof(tdir), group);
+ }
+ BLI_strncpy(sfile->params->dir, tdir, sizeof(sfile->params->dir));
+ if (name) {
+ BLI_strncpy(sfile->params->file, name, sizeof(sfile->params->file));
+ }
+ else {
+ sfile->params->file[0] = '\0';
+ }
+ }
+ }
+
+ BLI_cleanup_dir(BKE_main_blendfile_path(bmain), sfile->params->dir);
+
+ if (filelist_is_dir(sfile->files, sfile->params->dir)) {
+ /* if directory exists, enter it immediately */
+ ED_file_change_dir(C);
+
+ /* don't do for now because it selects entire text instead of
+ * placing cursor at the end */
+ /* UI_textbutton_activate_but(C, but); */
+ }
#if defined(WIN32)
- else if (!can_create_dir(sfile->params->dir)) {
- const char *lastdir = folderlist_peeklastdir(sfile->folders_prev);
- if (lastdir)
- BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir));
- }
+ else if (!can_create_dir(sfile->params->dir)) {
+ const char *lastdir = folderlist_peeklastdir(sfile->folders_prev);
+ if (lastdir)
+ BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir));
+ }
#endif
- else {
- const char *lastdir = folderlist_peeklastdir(sfile->folders_prev);
- char tdir[FILE_MAX_LIBEXTRA];
-
- /* If we are 'inside' a blend library, we cannot do anything... */
- if (lastdir && BLO_library_path_explode(lastdir, tdir, NULL, NULL)) {
- BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir));
- }
- else {
- /* if not, ask to create it and enter if confirmed */
- wmOperatorType *ot = WM_operatortype_find("FILE_OT_directory_new", false);
- PointerRNA ptr;
- WM_operator_properties_create_ptr(&ptr, ot);
- RNA_string_set(&ptr, "directory", sfile->params->dir);
- RNA_boolean_set(&ptr, "open", true);
-
- if (lastdir)
- BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir));
-
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
- WM_operator_properties_free(&ptr);
- }
- }
-
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
- }
+ else {
+ const char *lastdir = folderlist_peeklastdir(sfile->folders_prev);
+ char tdir[FILE_MAX_LIBEXTRA];
+
+ /* If we are 'inside' a blend library, we cannot do anything... */
+ if (lastdir && BLO_library_path_explode(lastdir, tdir, NULL, NULL)) {
+ BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir));
+ }
+ else {
+ /* if not, ask to create it and enter if confirmed */
+ wmOperatorType *ot = WM_operatortype_find("FILE_OT_directory_new", false);
+ PointerRNA ptr;
+ WM_operator_properties_create_ptr(&ptr, ot);
+ RNA_string_set(&ptr, "directory", sfile->params->dir);
+ RNA_boolean_set(&ptr, "open", true);
+
+ if (lastdir)
+ BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir));
+
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
+ WM_operator_properties_free(&ptr);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+ }
}
void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg_but)
{
- Main *bmain = CTX_data_main(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
- uiBut *but = arg_but;
- char matched_file[FILE_MAX];
- char filepath[sizeof(sfile->params->dir)];
+ Main *bmain = CTX_data_main(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ uiBut *but = arg_but;
+ char matched_file[FILE_MAX];
+ char filepath[sizeof(sfile->params->dir)];
- if (sfile->params) {
- int matches;
- matched_file[0] = '\0';
- filepath[0] = '\0';
+ if (sfile->params) {
+ int matches;
+ matched_file[0] = '\0';
+ filepath[0] = '\0';
- file_expand_directory(C);
+ file_expand_directory(C);
- matches = file_select_match(sfile, sfile->params->file, matched_file);
+ matches = file_select_match(sfile, sfile->params->file, matched_file);
- /* *After* file_select_match! */
- BLI_filename_make_safe(sfile->params->file);
+ /* *After* file_select_match! */
+ BLI_filename_make_safe(sfile->params->file);
- if (matches) {
- /* replace the pattern (or filename that the user typed in,
- * with the first selected file of the match */
- BLI_strncpy(sfile->params->file, matched_file, sizeof(sfile->params->file));
+ if (matches) {
+ /* replace the pattern (or filename that the user typed in,
+ * with the first selected file of the match */
+ BLI_strncpy(sfile->params->file, matched_file, sizeof(sfile->params->file));
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
- }
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+ }
- if (matches == 1) {
- BLI_join_dirfile(filepath, sizeof(sfile->params->dir), sfile->params->dir, sfile->params->file);
+ if (matches == 1) {
+ BLI_join_dirfile(
+ filepath, sizeof(sfile->params->dir), sfile->params->dir, sfile->params->file);
- /* 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_strncpy(sfile->params->dir, filepath, sizeof(sfile->params->dir));
- sfile->params->file[0] = '\0';
- ED_file_change_dir(C);
- UI_textbutton_activate_but(C, but);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
- }
- }
- else if (matches > 1) {
- file_draw_check(C);
- }
- }
+ /* 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_strncpy(sfile->params->dir, filepath, sizeof(sfile->params->dir));
+ sfile->params->file[0] = '\0';
+ ED_file_change_dir(C);
+ UI_textbutton_activate_but(C, but);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+ }
+ }
+ else if (matches > 1) {
+ file_draw_check(C);
+ }
+ }
}
void FILE_OT_refresh(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Refresh Filelist";
- ot->description = "Refresh the file list";
- ot->idname = "FILE_OT_refresh";
+ /* 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 */
+ /* api callbacks */
+ ot->exec = file_refresh_exec;
+ ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
}
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);
+ 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);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
- }
+ if (sfile->params) {
+ sfile->params->flag ^= FILE_HIDE_DOT;
+ ED_fileselect_clear(wm, sa, sfile);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
void FILE_OT_hidedot(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Hide Dot Files";
- ot->description = "Toggle hide hidden dot files";
- ot->idname = "FILE_OT_hidedot";
+ /* identifiers */
+ ot->name = "Toggle Hide Dot Files";
+ ot->description = "Toggle hide hidden dot files";
+ ot->idname = "FILE_OT_hidedot";
- /* api callbacks */
- ot->exec = file_hidedot_exec;
- ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
+ /* api callbacks */
+ ot->exec = file_hidedot_exec;
+ ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
}
ARegion *file_tools_region(ScrArea *sa)
{
- ARegion *ar, *arnew;
+ ARegion *ar, *arnew;
- if ((ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS)) != NULL)
- return ar;
+ if ((ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS)) != NULL)
+ return ar;
- /* add subdiv level; after header */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+ /* add subdiv level; after header */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
- /* is error! */
- if (ar == NULL)
- return NULL;
+ /* is error! */
+ if (ar == NULL)
+ return NULL;
- arnew = MEM_callocN(sizeof(ARegion), "tools for file");
- BLI_insertlinkafter(&sa->regionbase, ar, arnew);
- arnew->regiontype = RGN_TYPE_TOOLS;
- arnew->alignment = RGN_ALIGN_LEFT;
+ arnew = MEM_callocN(sizeof(ARegion), "tools for file");
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype = RGN_TYPE_TOOLS;
+ arnew->alignment = RGN_ALIGN_LEFT;
- ar = MEM_callocN(sizeof(ARegion), "tool props for file");
- BLI_insertlinkafter(&sa->regionbase, arnew, ar);
- ar->regiontype = RGN_TYPE_TOOL_PROPS;
- ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
+ ar = MEM_callocN(sizeof(ARegion), "tool props for file");
+ BLI_insertlinkafter(&sa->regionbase, arnew, ar);
+ ar->regiontype = RGN_TYPE_TOOL_PROPS;
+ ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
- return arnew;
+ return arnew;
}
static int file_bookmark_toggle_exec(bContext *C, wmOperator *UNUSED(unused))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = file_tools_region(sa);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = file_tools_region(sa);
- if (ar)
- ED_region_toggle_hidden(C, ar);
+ if (ar)
+ ED_region_toggle_hidden(C, ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void FILE_OT_bookmark_toggle(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Bookmarks";
- ot->description = "Toggle bookmarks display";
- ot->idname = "FILE_OT_bookmark_toggle";
+ /* identifiers */
+ ot->name = "Toggle Bookmarks";
+ ot->description = "Toggle bookmarks display";
+ ot->idname = "FILE_OT_bookmark_toggle";
- /* api callbacks */
- ot->exec = file_bookmark_toggle_exec;
- ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
+ /* api callbacks */
+ ot->exec = file_bookmark_toggle_exec;
+ ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
}
-
/**
* Looks for a string of digits within name (using BLI_stringdec) 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;
+ char head[FILE_MAXFILE], tail[FILE_MAXFILE];
+ char name_temp[FILE_MAXFILE];
+ int pic;
+ unsigned short digits;
- pic = BLI_stringdec(name, head, tail, &digits);
+ pic = BLI_stringdec(name, head, tail, &digits);
- /* are we going from 100 -> 99 or from 10 -> 9 */
- if (add < 0 && digits > 0) {
- int i, exp;
- exp = 1;
- for (i = digits; i > 1; i--) {
- exp *= 10;
- }
- if (pic >= exp && (pic + add) < exp) {
- digits--;
- }
- }
+ /* are we going from 100 -> 99 or from 10 -> 9 */
+ if (add < 0 && digits > 0) {
+ int i, exp;
+ exp = 1;
+ for (i = digits; i > 1; i--) {
+ exp *= 10;
+ }
+ if (pic >= exp && (pic + add) < exp) {
+ digits--;
+ }
+ }
- pic += add;
- if (pic < 0)
- pic = 0;
- BLI_stringenc(name_temp, head, tail, digits, pic);
- BLI_strncpy(name, name_temp, name_size);
+ pic += add;
+ if (pic < 0)
+ pic = 0;
+ BLI_stringenc(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);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ ScrArea *sa = 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);
- file_draw_check(C);
- // WM_event_add_notifier(C, NC_WINDOW, NULL);
- }
-
- return OPERATOR_FINISHED;
+ 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);
+ file_draw_check(C);
+ // WM_event_add_notifier(C, NC_WINDOW, NULL);
+ }
+ return OPERATOR_FINISHED;
}
void FILE_OT_filenum(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Increment Number in Filename";
- ot->description = "Increment number in filename";
- ot->idname = "FILE_OT_filenum";
+ /* identifiers */
+ ot->name = "Increment Number in Filename";
+ ot->description = "Increment number in filename";
+ ot->idname = "FILE_OT_filenum";
- /* api callbacks */
- ot->exec = file_filenum_exec;
- ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
+ /* api callbacks */
+ ot->exec = file_filenum_exec;
+ ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
- /* props */
- RNA_def_int(ot->srna, "increment", 1, -100, 100, "Increment", "", -100, 100);
+ /* props */
+ RNA_def_int(ot->srna, "increment", 1, -100, 100, "Increment", "", -100, 100);
}
static int file_rename_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
-
- if (sfile->params) {
- int idx = sfile->params->highlight_file;
- int numfiles = filelist_files_ensure(sfile->files);
- if ((0 <= idx) && (idx < numfiles)) {
- FileDirEntry *file = filelist_file(sfile->files, idx);
- filelist_entry_select_index_set(sfile->files, idx, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL);
- BLI_strncpy(sfile->params->renamefile, file->relpath, FILE_MAXFILE);
- /* We can skip the pending state, as we can directly set FILE_SEL_EDITING on the expected entry here. */
- sfile->params->rename_flag = FILE_PARAMS_RENAME_ACTIVE;
- }
- ED_area_tag_redraw(sa);
- }
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
- return OPERATOR_FINISHED;
+ if (sfile->params) {
+ int idx = sfile->params->highlight_file;
+ int numfiles = filelist_files_ensure(sfile->files);
+ if ((0 <= idx) && (idx < numfiles)) {
+ FileDirEntry *file = filelist_file(sfile->files, idx);
+ filelist_entry_select_index_set(
+ sfile->files, idx, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL);
+ BLI_strncpy(sfile->params->renamefile, file->relpath, FILE_MAXFILE);
+ /* We can skip the pending state, as we can directly set FILE_SEL_EDITING on the expected entry here. */
+ sfile->params->rename_flag = FILE_PARAMS_RENAME_ACTIVE;
+ }
+ ED_area_tag_redraw(sa);
+ }
+ return OPERATOR_FINISHED;
}
static bool file_rename_poll(bContext *C)
{
- bool poll = ED_operator_file_active(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
-
- if (sfile && sfile->params) {
- int idx = sfile->params->highlight_file;
- int numfiles = filelist_files_ensure(sfile->files);
-
- if ((0 <= idx) && (idx < numfiles)) {
- FileDirEntry *file = filelist_file(sfile->files, idx);
- if (FILENAME_IS_CURRPAR(file->relpath)) {
- poll = false;
- }
- }
-
- if (sfile->params->highlight_file < 0) {
- poll = false;
- }
- else {
- char dir[FILE_MAX_LIBEXTRA];
- if (filelist_islibrary(sfile->files, dir, NULL)) {
- poll = false;
- }
- }
- }
- else {
- poll = false;
- }
-
- return poll;
+ bool poll = ED_operator_file_active(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+
+ if (sfile && sfile->params) {
+ int idx = sfile->params->highlight_file;
+ int numfiles = filelist_files_ensure(sfile->files);
+
+ if ((0 <= idx) && (idx < numfiles)) {
+ FileDirEntry *file = filelist_file(sfile->files, idx);
+ if (FILENAME_IS_CURRPAR(file->relpath)) {
+ poll = false;
+ }
+ }
+
+ if (sfile->params->highlight_file < 0) {
+ poll = false;
+ }
+ else {
+ char dir[FILE_MAX_LIBEXTRA];
+ if (filelist_islibrary(sfile->files, dir, NULL)) {
+ poll = false;
+ }
+ }
+ }
+ else {
+ poll = false;
+ }
+
+ return poll;
}
void FILE_OT_rename(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Rename File or Directory";
- ot->description = "Rename file or file directory";
- ot->idname = "FILE_OT_rename";
-
- /* api callbacks */
- ot->exec = file_rename_exec;
- ot->poll = file_rename_poll;
+ /* identifiers */
+ ot->name = "Rename File or Directory";
+ ot->description = "Rename file or file directory";
+ ot->idname = "FILE_OT_rename";
+ /* api callbacks */
+ ot->exec = file_rename_exec;
+ ot->poll = file_rename_poll;
}
static bool file_delete_poll(bContext *C)
{
- bool poll = ED_operator_file_active(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
+ bool poll = ED_operator_file_active(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
- if (sfile && sfile->params) {
- char dir[FILE_MAX_LIBEXTRA];
- int numfiles = filelist_files_ensure(sfile->files);
- int i;
- int num_selected = 0;
+ if (sfile && sfile->params) {
+ char dir[FILE_MAX_LIBEXTRA];
+ int numfiles = filelist_files_ensure(sfile->files);
+ int i;
+ int num_selected = 0;
- if (filelist_islibrary(sfile->files, dir, NULL)) poll = 0;
- for (i = 0; i < numfiles; i++) {
- if (filelist_entry_select_index_get(sfile->files, i, CHECK_FILES)) {
- num_selected++;
- }
- }
- if (num_selected <= 0) {
- poll = 0;
- }
- }
- else
- poll = 0;
+ if (filelist_islibrary(sfile->files, dir, NULL))
+ poll = 0;
+ for (i = 0; i < numfiles; i++) {
+ if (filelist_entry_select_index_get(sfile->files, i, CHECK_FILES)) {
+ num_selected++;
+ }
+ }
+ if (num_selected <= 0) {
+ poll = 0;
+ }
+ }
+ else
+ poll = 0;
- return poll;
+ return poll;
}
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;
-
- bool report_error = false;
- errno = 0;
- for (i = 0; i < numfiles; i++) {
- if (filelist_entry_select_index_get(sfile->files, i, CHECK_FILES)) {
- file = filelist_file(sfile->files, i);
- BLI_make_file_string(BKE_main_blendfile_path(bmain), str, sfile->params->dir, file->relpath);
- if (BLI_delete(str, false, false) != 0 ||
- BLI_exists(str))
- {
- report_error = true;
- }
- }
- }
-
- if (report_error) {
- BKE_reportf(op->reports, RPT_ERROR,
- "Could not delete file: %s",
- errno ? strerror(errno) : "unknown error");
- }
-
- ED_fileselect_clear(wm, sa, sfile);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
-
- return OPERATOR_FINISHED;
-
+ 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;
+
+ bool report_error = false;
+ errno = 0;
+ for (i = 0; i < numfiles; i++) {
+ if (filelist_entry_select_index_get(sfile->files, i, CHECK_FILES)) {
+ file = filelist_file(sfile->files, i);
+ BLI_make_file_string(BKE_main_blendfile_path(bmain), str, sfile->params->dir, file->relpath);
+ if (BLI_delete(str, false, false) != 0 || BLI_exists(str)) {
+ report_error = true;
+ }
+ }
+ }
+
+ if (report_error) {
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "Could not delete file: %s",
+ errno ? strerror(errno) : "unknown error");
+ }
+
+ ED_fileselect_clear(wm, sa, sfile);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+
+ return OPERATOR_FINISHED;
}
void FILE_OT_delete(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Selected Files";
- ot->description = "Delete selected files";
- ot->idname = "FILE_OT_delete";
+ /* identifiers */
+ ot->name = "Delete Selected Files";
+ ot->description = "Delete selected files";
+ ot->idname = "FILE_OT_delete";
- /* api callbacks */
- ot->invoke = WM_operator_confirm;
- ot->exec = file_delete_exec;
- ot->poll = file_delete_poll; /* <- important, handler is on window level */
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = file_delete_exec;
+ ot->poll = file_delete_poll; /* <- important, handler is on window level */
}
-
void ED_operatormacros_file(void)
{
-// wmOperatorType *ot;
-// wmOperatorTypeMacro *otmacro;
+ // wmOperatorType *ot;
+ // wmOperatorTypeMacro *otmacro;
- /* future macros */
+ /* future macros */
}
diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c
index 058ba9bfef3..023dff704c7 100644
--- a/source/blender/editors/space_file/file_panels.c
+++ b/source/blender/editors/space_file/file_panels.c
@@ -53,59 +53,58 @@
static bool file_panel_operator_poll(const bContext *C, PanelType *UNUSED(pt))
{
- SpaceFile *sfile = CTX_wm_space_file(C);
- return (sfile && sfile->op);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ return (sfile && sfile->op);
}
static void file_panel_operator_header(const bContext *C, Panel *pa)
{
- SpaceFile *sfile = CTX_wm_space_file(C);
- wmOperator *op = sfile->op;
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ wmOperator *op = sfile->op;
- BLI_strncpy(pa->drawname, RNA_struct_ui_name(op->type->srna), sizeof(pa->drawname));
+ BLI_strncpy(pa->drawname, RNA_struct_ui_name(op->type->srna), sizeof(pa->drawname));
}
static void file_panel_operator(const bContext *C, Panel *pa)
{
- SpaceFile *sfile = CTX_wm_space_file(C);
- wmOperator *op = sfile->op;
-
- UI_block_func_set(uiLayoutGetBlock(pa->layout), file_draw_check_cb, NULL, NULL);
-
- /* Hack: temporary hide.*/
- const char *hide[] = {"filepath", "files", "directory", "filename"};
- for (int i = 0; i < ARRAY_SIZE(hide); i++) {
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, hide[i]);
- if (prop) {
- RNA_def_property_flag(prop, PROP_HIDDEN);
- }
- }
-
- uiTemplateOperatorPropertyButs(
- C, pa->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++) {
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, hide[i]);
- if (prop) {
- RNA_def_property_clear_flag(prop, PROP_HIDDEN);
- }
- }
-
- UI_block_func_set(uiLayoutGetBlock(pa->layout), NULL, NULL, NULL);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ wmOperator *op = sfile->op;
+
+ UI_block_func_set(uiLayoutGetBlock(pa->layout), file_draw_check_cb, NULL, NULL);
+
+ /* Hack: temporary hide.*/
+ const char *hide[] = {"filepath", "files", "directory", "filename"};
+ for (int i = 0; i < ARRAY_SIZE(hide); i++) {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, hide[i]);
+ if (prop) {
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ }
+ }
+
+ uiTemplateOperatorPropertyButs(
+ C, pa->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++) {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, hide[i]);
+ if (prop) {
+ RNA_def_property_clear_flag(prop, PROP_HIDDEN);
+ }
+ }
+
+ UI_block_func_set(uiLayoutGetBlock(pa->layout), NULL, NULL, NULL);
}
void file_panels_register(ARegionType *art)
{
- PanelType *pt;
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype file operator properties");
- strcpy(pt->idname, "FILE_PT_operator");
- strcpy(pt->label, N_("Operator"));
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->poll = file_panel_operator_poll;
- pt->draw_header = file_panel_operator_header;
- pt->draw = file_panel_operator;
- BLI_addtail(&art->paneltypes, pt);
+ PanelType *pt;
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype file operator properties");
+ strcpy(pt->idname, "FILE_PT_operator");
+ strcpy(pt->label, N_("Operator"));
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->poll = file_panel_operator_poll;
+ pt->draw_header = file_panel_operator_header;
+ pt->draw = file_panel_operator;
+ BLI_addtail(&art->paneltypes, pt);
}
diff --git a/source/blender/editors/space_file/file_utils.c b/source/blender/editors/space_file/file_utils.c
index 0294b635910..a432afc4d99 100644
--- a/source/blender/editors/space_file/file_utils.c
+++ b/source/blender/editors/space_file/file_utils.c
@@ -32,13 +32,15 @@
#include "file_intern.h"
-
void file_tile_boundbox(const ARegion *ar, 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 */
- BLI_rcti_init(r_bounds, xmin, xmin + layout->tile_w + layout->tile_border_x,
- ymax - layout->tile_h - layout->tile_border_y, ymax);
+ int xmin, ymax;
+
+ ED_fileselect_layout_tilepos(layout, file, &xmin, &ymax);
+ ymax = (int)ar->v2d.tot.ymax - ymax; /* real, view space ymax */
+ BLI_rcti_init(r_bounds,
+ xmin,
+ xmin + layout->tile_w + layout->tile_border_x,
+ ymax - layout->tile_h - layout->tile_border_y,
+ ymax);
}
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 623442b753a..31a59f06079 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -21,7 +21,6 @@
* \ingroup spfile
*/
-
/* global includes */
#include <stdlib.h>
@@ -83,249 +82,246 @@
#include "filelist.h"
-
/* ----------------- FOLDERLIST (previous/next) -------------- */
typedef struct FolderList {
- struct FolderList *next, *prev;
- char *foldername;
+ struct FolderList *next, *prev;
+ char *foldername;
} FolderList;
ListBase *folderlist_new(void)
{
- ListBase *p = MEM_callocN(sizeof(*p), __func__);
- return p;
+ ListBase *p = MEM_callocN(sizeof(*p), __func__);
+ return p;
}
void folderlist_popdir(struct ListBase *folderlist, char *dir)
{
- const char *prev_dir;
- struct FolderList *folder;
- folder = folderlist->last;
+ const char *prev_dir;
+ struct FolderList *folder;
+ folder = folderlist->last;
- if (folder) {
- /* remove the current directory */
- MEM_freeN(folder->foldername);
- BLI_freelinkN(folderlist, folder);
+ if (folder) {
+ /* remove the current directory */
+ MEM_freeN(folder->foldername);
+ BLI_freelinkN(folderlist, folder);
- folder = folderlist->last;
- if (folder) {
- prev_dir = folder->foldername;
- BLI_strncpy(dir, prev_dir, FILE_MAXDIR);
- }
- }
- /* delete the folder next or use setdir directly before PREVIOUS OP */
+ folder = folderlist->last;
+ if (folder) {
+ prev_dir = folder->foldername;
+ BLI_strncpy(dir, prev_dir, FILE_MAXDIR);
+ }
+ }
+ /* delete the folder next or use setdir directly before PREVIOUS OP */
}
void folderlist_pushdir(ListBase *folderlist, const char *dir)
{
- struct FolderList *folder, *previous_folder;
- previous_folder = folderlist->last;
+ struct FolderList *folder, *previous_folder;
+ previous_folder = folderlist->last;
- /* check if already exists */
- if (previous_folder && previous_folder->foldername) {
- if (BLI_path_cmp(previous_folder->foldername, dir) == 0) {
- return;
- }
- }
+ /* check if already exists */
+ if (previous_folder && previous_folder->foldername) {
+ if (BLI_path_cmp(previous_folder->foldername, dir) == 0) {
+ return;
+ }
+ }
- /* create next folder element */
- folder = MEM_mallocN(sizeof(*folder), __func__);
- folder->foldername = BLI_strdup(dir);
+ /* create next folder element */
+ folder = MEM_mallocN(sizeof(*folder), __func__);
+ folder->foldername = BLI_strdup(dir);
- /* add it to the end of the list */
- BLI_addtail(folderlist, folder);
+ /* add it to the end of the list */
+ BLI_addtail(folderlist, folder);
}
const char *folderlist_peeklastdir(ListBase *folderlist)
{
- struct FolderList *folder;
+ struct FolderList *folder;
- if (!folderlist->last)
- return NULL;
+ if (!folderlist->last)
+ return NULL;
- folder = folderlist->last;
- return folder->foldername;
+ folder = folderlist->last;
+ return folder->foldername;
}
int folderlist_clear_next(struct SpaceFile *sfile)
{
- struct FolderList *folder;
+ struct FolderList *folder;
- /* if there is no folder_next there is nothing we can clear */
- if (!sfile->folders_next)
- return 0;
+ /* if there is no folder_next there is nothing we can clear */
+ if (!sfile->folders_next)
+ return 0;
- /* if previous_folder, next_folder or refresh_folder operators are executed
- * it doesn't clear folder_next */
- folder = sfile->folders_prev->last;
- if ((!folder) || (BLI_path_cmp(folder->foldername, sfile->params->dir) == 0))
- return 0;
+ /* if previous_folder, next_folder or refresh_folder operators are executed
+ * it doesn't clear folder_next */
+ folder = sfile->folders_prev->last;
+ if ((!folder) || (BLI_path_cmp(folder->foldername, sfile->params->dir) == 0))
+ return 0;
- /* eventually clear flist->folders_next */
- return 1;
+ /* eventually clear flist->folders_next */
+ return 1;
}
/* not listbase itself */
void folderlist_free(ListBase *folderlist)
{
- if (folderlist) {
- FolderList *folder;
- for (folder = folderlist->first; folder; folder = folder->next)
- MEM_freeN(folder->foldername);
- BLI_freelistN(folderlist);
- }
+ if (folderlist) {
+ FolderList *folder;
+ for (folder = folderlist->first; folder; folder = folder->next)
+ MEM_freeN(folder->foldername);
+ BLI_freelistN(folderlist);
+ }
}
ListBase *folderlist_duplicate(ListBase *folderlist)
{
- if (folderlist) {
- ListBase *folderlistn = MEM_callocN(sizeof(*folderlistn), __func__);
- FolderList *folder;
+ if (folderlist) {
+ ListBase *folderlistn = MEM_callocN(sizeof(*folderlistn), __func__);
+ FolderList *folder;
- BLI_duplicatelist(folderlistn, folderlist);
+ BLI_duplicatelist(folderlistn, folderlist);
- for (folder = folderlistn->first; folder; folder = folder->next) {
- folder->foldername = MEM_dupallocN(folder->foldername);
- }
- return folderlistn;
- }
- return NULL;
+ for (folder = folderlistn->first; folder; folder = folder->next) {
+ folder->foldername = MEM_dupallocN(folder->foldername);
+ }
+ return folderlistn;
+ }
+ return NULL;
}
-
/* ------------------FILELIST------------------------ */
typedef struct FileListInternEntry {
- struct FileListInternEntry *next, *prev;
+ struct FileListInternEntry *next, *prev;
- /** ASSET_UUID_LENGTH */
- char uuid[16];
+ /** ASSET_UUID_LENGTH */
+ char uuid[16];
- /** eFileSel_File_Types */
- int typeflag;
- /** ID type, in case typeflag has FILE_TYPE_BLENDERLIB set. */
- int blentype;
+ /** eFileSel_File_Types */
+ int typeflag;
+ /** ID type, in case typeflag has FILE_TYPE_BLENDERLIB set. */
+ int blentype;
- char *relpath;
- /** not strictly needed, but used during sorting, avoids to have to recompute it there... */
- char *name;
+ char *relpath;
+ /** not strictly needed, but used during sorting, avoids to have to recompute it there... */
+ char *name;
- BLI_stat_t st;
+ BLI_stat_t st;
} FileListInternEntry;
typedef struct FileListIntern {
- /** FileListInternEntry items. */
- ListBase entries;
- FileListInternEntry **filtered;
+ /** FileListInternEntry items. */
+ ListBase entries;
+ FileListInternEntry **filtered;
- char curr_uuid[16]; /* Used to generate uuid during internal listing. */
+ char curr_uuid[16]; /* Used to generate uuid during internal listing. */
} FileListIntern;
-#define FILELIST_ENTRYCACHESIZE_DEFAULT 1024 /* Keep it a power of two! */
+#define FILELIST_ENTRYCACHESIZE_DEFAULT 1024 /* Keep it a power of two! */
typedef struct FileListEntryCache {
- size_t size; /* The size of the cache... */
+ size_t size; /* The size of the cache... */
- int flags;
+ int flags;
- /* This one gathers all entries from both block and misc caches. Used for easy bulk-freing. */
- ListBase cached_entries;
+ /* This one gathers all entries from both block and misc caches. Used for easy bulk-freing. */
+ ListBase cached_entries;
- /* Block cache: all entries between start and end index.
- * used for part of the list on display. */
- FileDirEntry **block_entries;
- int block_start_index, block_end_index, block_center_index, block_cursor;
+ /* Block cache: all entries between start and end index.
+ * used for part of the list on display. */
+ FileDirEntry **block_entries;
+ int block_start_index, block_end_index, block_center_index, block_cursor;
- /* Misc cache: random indices, FIFO behavior.
- * Note: Not 100% sure we actually need that, time will say. */
- int misc_cursor;
- int *misc_entries_indices;
- GHash *misc_entries;
+ /* Misc cache: random indices, FIFO behavior.
+ * Note: Not 100% sure we actually need that, time will say. */
+ int misc_cursor;
+ int *misc_entries_indices;
+ GHash *misc_entries;
- /* Allows to quickly get a cached entry from its UUID. */
- GHash *uuids;
+ /* Allows to quickly get a cached entry from its UUID. */
+ GHash *uuids;
- /* Previews handling. */
- TaskPool *previews_pool;
- ThreadQueue *previews_done;
+ /* Previews handling. */
+ TaskPool *previews_pool;
+ ThreadQueue *previews_done;
} FileListEntryCache;
/* FileListCache.flags */
enum {
- FLC_IS_INIT = 1 << 0,
- FLC_PREVIEWS_ACTIVE = 1 << 1,
+ FLC_IS_INIT = 1 << 0,
+ FLC_PREVIEWS_ACTIVE = 1 << 1,
};
typedef struct FileListEntryPreview {
- char path[FILE_MAX];
- unsigned int flags;
- int index;
- ImBuf *img;
+ char path[FILE_MAX];
+ unsigned int flags;
+ int index;
+ ImBuf *img;
} FileListEntryPreview;
-
typedef struct FileListFilter {
- unsigned int filter;
- unsigned int filter_id;
- char filter_glob[FILE_MAXFILE];
- char filter_search[66]; /* + 2 for heading/trailing implicit '*' wildcards. */
- short flags;
+ unsigned int filter;
+ unsigned int filter_id;
+ char filter_glob[FILE_MAXFILE];
+ char filter_search[66]; /* + 2 for heading/trailing implicit '*' wildcards. */
+ short flags;
} FileListFilter;
/* FileListFilter.flags */
enum {
- FLF_DO_FILTER = 1 << 0,
- FLF_HIDE_DOT = 1 << 1,
- FLF_HIDE_PARENT = 1 << 2,
- FLF_HIDE_LIB_DIR = 1 << 3,
+ FLF_DO_FILTER = 1 << 0,
+ FLF_HIDE_DOT = 1 << 1,
+ FLF_HIDE_PARENT = 1 << 2,
+ FLF_HIDE_LIB_DIR = 1 << 3,
};
typedef struct FileList {
- FileDirEntryArr filelist;
+ FileDirEntryArr filelist;
- short prv_w;
- short prv_h;
+ short prv_w;
+ short prv_h;
- short flags;
+ short flags;
- short sort;
+ short sort;
- FileListFilter filter_data;
+ FileListFilter filter_data;
- struct FileListIntern filelist_intern;
+ struct FileListIntern filelist_intern;
- struct FileListEntryCache filelist_cache;
+ struct FileListEntryCache filelist_cache;
- /* We need to keep those info outside of actual filelist items, because those are no more persistent
- * (only generated on demand, and freed as soon as possible).
- * Persistent part (mere list of paths + stat info) is kept as small as possible, and filebrowser-agnostic.
- */
- GHash *selection_state;
+ /* We need to keep those info outside of actual filelist items, because those are no more persistent
+ * (only generated on demand, and freed as soon as possible).
+ * Persistent part (mere list of paths + stat info) is kept as small as possible, and filebrowser-agnostic.
+ */
+ GHash *selection_state;
- short max_recursion;
- short recursion_level;
+ short max_recursion;
+ short recursion_level;
- struct BlendHandle *libfiledata;
+ struct BlendHandle *libfiledata;
- /* Set given path as root directory, if last bool is true may change given string in place to a valid value.
- * Returns True if valid dir. */
- bool (*checkdirf)(struct FileList *, char *, const bool);
+ /* Set given path as root directory, if last bool is true may change given string in place to a valid value.
+ * Returns True if valid dir. */
+ bool (*checkdirf)(struct FileList *, char *, const bool);
- /* Fill filelist (to be called by read job). */
- void (*read_jobf)(struct FileList *, const char *, short *, short *, float *, ThreadMutex *);
+ /* Fill filelist (to be called by read job). */
+ void (*read_jobf)(struct FileList *, const char *, short *, short *, float *, ThreadMutex *);
- /* Filter an entry of current filelist. */
- bool (*filterf)(struct FileListInternEntry *, const char *, FileListFilter *);
+ /* Filter an entry of current filelist. */
+ bool (*filterf)(struct FileListInternEntry *, const char *, FileListFilter *);
} FileList;
/* FileList.flags */
enum {
- FL_FORCE_RESET = 1 << 0,
- FL_IS_READY = 1 << 1,
- FL_IS_PENDING = 1 << 2,
- FL_NEED_SORTING = 1 << 3,
- FL_NEED_FILTERING = 1 << 4,
+ FL_FORCE_RESET = 1 << 0,
+ FL_IS_READY = 1 << 1,
+ FL_IS_PENDING = 1 << 2,
+ FL_NEED_SORTING = 1 << 3,
+ FL_NEED_FILTERING = 1 << 4,
};
#define SPECIAL_IMG_SIZE 48
@@ -333,27 +329,29 @@ enum {
#define SPECIAL_IMG_COLS 4
enum {
- SPECIAL_IMG_FOLDER = 0,
- SPECIAL_IMG_PARENT = 1,
- SPECIAL_IMG_REFRESH = 2,
- SPECIAL_IMG_BLENDFILE = 3,
- SPECIAL_IMG_SOUNDFILE = 4,
- SPECIAL_IMG_MOVIEFILE = 5,
- SPECIAL_IMG_PYTHONFILE = 6,
- SPECIAL_IMG_TEXTFILE = 7,
- SPECIAL_IMG_FONTFILE = 8,
- SPECIAL_IMG_UNKNOWNFILE = 9,
- SPECIAL_IMG_LOADING = 10,
- SPECIAL_IMG_BACKUP = 11,
- SPECIAL_IMG_MAX,
+ SPECIAL_IMG_FOLDER = 0,
+ SPECIAL_IMG_PARENT = 1,
+ SPECIAL_IMG_REFRESH = 2,
+ SPECIAL_IMG_BLENDFILE = 3,
+ SPECIAL_IMG_SOUNDFILE = 4,
+ SPECIAL_IMG_MOVIEFILE = 5,
+ SPECIAL_IMG_PYTHONFILE = 6,
+ SPECIAL_IMG_TEXTFILE = 7,
+ SPECIAL_IMG_FONTFILE = 8,
+ SPECIAL_IMG_UNKNOWNFILE = 9,
+ SPECIAL_IMG_LOADING = 10,
+ SPECIAL_IMG_BACKUP = 11,
+ SPECIAL_IMG_MAX,
};
static ImBuf *gSpecialFileImages[SPECIAL_IMG_MAX];
-
-static void filelist_readjob_main(struct FileList *, const char *, short *, short *, float *, ThreadMutex *);
-static void filelist_readjob_lib(struct FileList *, const char *, short *, short *, float *, ThreadMutex *);
-static void filelist_readjob_dir(struct FileList *, const char *, short *, short *, float *, ThreadMutex *);
+static void filelist_readjob_main(
+ struct FileList *, const char *, short *, short *, float *, ThreadMutex *);
+static void filelist_readjob_lib(
+ struct FileList *, const char *, short *, short *, float *, ThreadMutex *);
+static void filelist_readjob_dir(
+ struct FileList *, const char *, short *, short *, float *, ThreadMutex *);
/* helper, could probably go in BKE actually? */
static int groupname_to_code(const char *group);
@@ -364,1053 +362,1114 @@ static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size);
/* ********** Sort helpers ********** */
-static int compare_direntry_generic(const FileListInternEntry *entry1, const FileListInternEntry *entry2)
-{
- /* type is equal to stat.st_mode */
-
- if (entry1->typeflag & FILE_TYPE_DIR) {
- if (entry2->typeflag & FILE_TYPE_DIR) {
- /* If both entries are tagged as dirs, we make a 'sub filter' that shows first the real dirs,
- * then libs (.blend files), then categories in libs. */
- if (entry1->typeflag & FILE_TYPE_BLENDERLIB) {
- if (!(entry2->typeflag & FILE_TYPE_BLENDERLIB)) {
- return 1;
- }
- }
- else if (entry2->typeflag & FILE_TYPE_BLENDERLIB) {
- return -1;
- }
- else if (entry1->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
- if (!(entry2->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) {
- return 1;
- }
- }
- else if (entry2->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
- return -1;
- }
- }
- else {
- return -1;
- }
- }
- else if (entry2->typeflag & FILE_TYPE_DIR) {
- return 1;
- }
-
- /* make sure "." and ".." are always first */
- if (FILENAME_IS_CURRENT(entry1->relpath)) return -1;
- if (FILENAME_IS_CURRENT(entry2->relpath)) return 1;
- if (FILENAME_IS_PARENT(entry1->relpath)) return -1;
- if (FILENAME_IS_PARENT(entry2->relpath)) return 1;
-
- return 0;
+static int compare_direntry_generic(const FileListInternEntry *entry1,
+ const FileListInternEntry *entry2)
+{
+ /* type is equal to stat.st_mode */
+
+ if (entry1->typeflag & FILE_TYPE_DIR) {
+ if (entry2->typeflag & FILE_TYPE_DIR) {
+ /* If both entries are tagged as dirs, we make a 'sub filter' that shows first the real dirs,
+ * then libs (.blend files), then categories in libs. */
+ if (entry1->typeflag & FILE_TYPE_BLENDERLIB) {
+ if (!(entry2->typeflag & FILE_TYPE_BLENDERLIB)) {
+ return 1;
+ }
+ }
+ else if (entry2->typeflag & FILE_TYPE_BLENDERLIB) {
+ return -1;
+ }
+ else if (entry1->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
+ if (!(entry2->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) {
+ return 1;
+ }
+ }
+ else if (entry2->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
+ return -1;
+ }
+ }
+ else {
+ return -1;
+ }
+ }
+ else if (entry2->typeflag & FILE_TYPE_DIR) {
+ return 1;
+ }
+
+ /* make sure "." and ".." are always first */
+ if (FILENAME_IS_CURRENT(entry1->relpath))
+ return -1;
+ if (FILENAME_IS_CURRENT(entry2->relpath))
+ return 1;
+ if (FILENAME_IS_PARENT(entry1->relpath))
+ return -1;
+ if (FILENAME_IS_PARENT(entry2->relpath))
+ return 1;
+
+ return 0;
}
static int compare_name(void *UNUSED(user_data), const void *a1, const void *a2)
{
- const FileListInternEntry *entry1 = a1;
- const FileListInternEntry *entry2 = a2;
- char *name1, *name2;
- int ret;
+ const FileListInternEntry *entry1 = a1;
+ const FileListInternEntry *entry2 = a2;
+ char *name1, *name2;
+ int ret;
- if ((ret = compare_direntry_generic(entry1, entry2))) {
- return ret;
- }
+ if ((ret = compare_direntry_generic(entry1, entry2))) {
+ return ret;
+ }
- name1 = entry1->name;
- name2 = entry2->name;
+ name1 = entry1->name;
+ name2 = entry2->name;
- return BLI_natstrcmp(name1, name2);
+ return BLI_natstrcmp(name1, name2);
}
static int compare_date(void *UNUSED(user_data), const void *a1, const void *a2)
{
- const FileListInternEntry *entry1 = a1;
- const FileListInternEntry *entry2 = a2;
- char *name1, *name2;
- int64_t time1, time2;
- int ret;
+ const FileListInternEntry *entry1 = a1;
+ const FileListInternEntry *entry2 = a2;
+ char *name1, *name2;
+ int64_t time1, time2;
+ int ret;
- if ((ret = compare_direntry_generic(entry1, entry2))) {
- return ret;
- }
+ if ((ret = compare_direntry_generic(entry1, entry2))) {
+ return ret;
+ }
- time1 = (int64_t)entry1->st.st_mtime;
- time2 = (int64_t)entry2->st.st_mtime;
- if (time1 < time2) return 1;
- if (time1 > time2) return -1;
+ time1 = (int64_t)entry1->st.st_mtime;
+ time2 = (int64_t)entry2->st.st_mtime;
+ if (time1 < time2)
+ return 1;
+ if (time1 > time2)
+ return -1;
- name1 = entry1->name;
- name2 = entry2->name;
+ name1 = entry1->name;
+ name2 = entry2->name;
- return BLI_natstrcmp(name1, name2);
+ return BLI_natstrcmp(name1, name2);
}
static int compare_size(void *UNUSED(user_data), const void *a1, const void *a2)
{
- const FileListInternEntry *entry1 = a1;
- const FileListInternEntry *entry2 = a2;
- char *name1, *name2;
- uint64_t size1, size2;
- int ret;
+ const FileListInternEntry *entry1 = a1;
+ const FileListInternEntry *entry2 = a2;
+ char *name1, *name2;
+ uint64_t size1, size2;
+ int ret;
- if ((ret = compare_direntry_generic(entry1, entry2))) {
- return ret;
- }
+ if ((ret = compare_direntry_generic(entry1, entry2))) {
+ return ret;
+ }
- size1 = entry1->st.st_size;
- size2 = entry2->st.st_size;
- if (size1 < size2) return 1;
- if (size1 > size2) return -1;
+ size1 = entry1->st.st_size;
+ size2 = entry2->st.st_size;
+ if (size1 < size2)
+ return 1;
+ if (size1 > size2)
+ return -1;
- name1 = entry1->name;
- name2 = entry2->name;
+ name1 = entry1->name;
+ name2 = entry2->name;
- return BLI_natstrcmp(name1, name2);
+ return BLI_natstrcmp(name1, name2);
}
static int compare_extension(void *UNUSED(user_data), const void *a1, const void *a2)
{
- const FileListInternEntry *entry1 = a1;
- const FileListInternEntry *entry2 = a2;
- char *name1, *name2;
- int ret;
-
- if ((ret = compare_direntry_generic(entry1, entry2))) {
- return ret;
- }
-
- if ((entry1->typeflag & FILE_TYPE_BLENDERLIB) && !(entry2->typeflag & FILE_TYPE_BLENDERLIB)) return -1;
- if (!(entry1->typeflag & FILE_TYPE_BLENDERLIB) && (entry2->typeflag & FILE_TYPE_BLENDERLIB)) return 1;
- if ((entry1->typeflag & FILE_TYPE_BLENDERLIB) && (entry2->typeflag & FILE_TYPE_BLENDERLIB)) {
- if ((entry1->typeflag & FILE_TYPE_DIR) && !(entry2->typeflag & FILE_TYPE_DIR)) return 1;
- if (!(entry1->typeflag & FILE_TYPE_DIR) && (entry2->typeflag & FILE_TYPE_DIR)) return -1;
- if (entry1->blentype < entry2->blentype) return -1;
- if (entry1->blentype > entry2->blentype) return 1;
- }
- else {
- const char *sufix1, *sufix2;
-
- if (!(sufix1 = strstr(entry1->relpath, ".blend.gz")))
- sufix1 = strrchr(entry1->relpath, '.');
- if (!(sufix2 = strstr(entry2->relpath, ".blend.gz")))
- sufix2 = strrchr(entry2->relpath, '.');
- if (!sufix1) sufix1 = "";
- if (!sufix2) sufix2 = "";
-
- if ((ret = BLI_strcasecmp(sufix1, sufix2))) {
- return ret;
- }
- }
-
- name1 = entry1->name;
- name2 = entry2->name;
-
- return BLI_natstrcmp(name1, name2);
+ const FileListInternEntry *entry1 = a1;
+ const FileListInternEntry *entry2 = a2;
+ char *name1, *name2;
+ int ret;
+
+ if ((ret = compare_direntry_generic(entry1, entry2))) {
+ return ret;
+ }
+
+ if ((entry1->typeflag & FILE_TYPE_BLENDERLIB) && !(entry2->typeflag & FILE_TYPE_BLENDERLIB))
+ return -1;
+ if (!(entry1->typeflag & FILE_TYPE_BLENDERLIB) && (entry2->typeflag & FILE_TYPE_BLENDERLIB))
+ return 1;
+ if ((entry1->typeflag & FILE_TYPE_BLENDERLIB) && (entry2->typeflag & FILE_TYPE_BLENDERLIB)) {
+ if ((entry1->typeflag & FILE_TYPE_DIR) && !(entry2->typeflag & FILE_TYPE_DIR))
+ return 1;
+ if (!(entry1->typeflag & FILE_TYPE_DIR) && (entry2->typeflag & FILE_TYPE_DIR))
+ return -1;
+ if (entry1->blentype < entry2->blentype)
+ return -1;
+ if (entry1->blentype > entry2->blentype)
+ return 1;
+ }
+ else {
+ const char *sufix1, *sufix2;
+
+ if (!(sufix1 = strstr(entry1->relpath, ".blend.gz")))
+ sufix1 = strrchr(entry1->relpath, '.');
+ if (!(sufix2 = strstr(entry2->relpath, ".blend.gz")))
+ sufix2 = strrchr(entry2->relpath, '.');
+ if (!sufix1)
+ sufix1 = "";
+ if (!sufix2)
+ sufix2 = "";
+
+ if ((ret = BLI_strcasecmp(sufix1, sufix2))) {
+ return ret;
+ }
+ }
+
+ name1 = entry1->name;
+ name2 = entry2->name;
+
+ return BLI_natstrcmp(name1, name2);
}
void filelist_sort(struct FileList *filelist)
{
- if ((filelist->flags & FL_NEED_SORTING) && (filelist->sort != FILE_SORT_NONE)) {
- switch (filelist->sort) {
- case FILE_SORT_ALPHA:
- BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_name, NULL);
- break;
- case FILE_SORT_TIME:
- BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_date, NULL);
- break;
- case FILE_SORT_SIZE:
- BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_size, NULL);
- break;
- case FILE_SORT_EXTENSION:
- BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_extension, NULL);
- break;
- case FILE_SORT_NONE: /* Should never reach this point! */
- default:
- BLI_assert(0);
- break;
- }
-
- filelist_filter_clear(filelist);
- filelist->flags &= ~FL_NEED_SORTING;
- }
+ if ((filelist->flags & FL_NEED_SORTING) && (filelist->sort != FILE_SORT_NONE)) {
+ switch (filelist->sort) {
+ case FILE_SORT_ALPHA:
+ BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_name, NULL);
+ break;
+ case FILE_SORT_TIME:
+ BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_date, NULL);
+ break;
+ case FILE_SORT_SIZE:
+ BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_size, NULL);
+ break;
+ case FILE_SORT_EXTENSION:
+ BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_extension, NULL);
+ break;
+ case FILE_SORT_NONE: /* Should never reach this point! */
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ filelist_filter_clear(filelist);
+ filelist->flags &= ~FL_NEED_SORTING;
+ }
}
void filelist_setsorting(struct FileList *filelist, const short sort)
{
- if (filelist->sort != sort) {
- filelist->sort = sort;
- filelist->flags |= FL_NEED_SORTING;
- }
+ if (filelist->sort != sort) {
+ filelist->sort = sort;
+ filelist->flags |= FL_NEED_SORTING;
+ }
}
/* ********** Filter helpers ********** */
static bool is_hidden_file(const char *filename, FileListFilter *filter)
{
- 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 (!is_hidden && (filter->flags & FLF_HIDE_PARENT)) {
- if (filename[0] == '.' && filename[1] == '.' && filename[2] == '\0') {
- is_hidden = true; /* ignore .. */
- }
- }
- 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) {
- char tmp_filename[FILE_MAX_LIBEXTRA];
-
- BLI_strncpy(tmp_filename, filename, sizeof(tmp_filename));
- sep = tmp_filename + (sep - filename);
- while (sep) {
- BLI_assert(sep[1] != '\0');
- if (is_hidden_file(sep + 1, filter)) {
- is_hidden = true;
- break;
- }
- *sep = '\0';
- sep = (char *)BLI_last_slash(tmp_filename);
- }
- }
- return is_hidden;
-}
-
-static bool is_filtered_file(FileListInternEntry *file, const char *UNUSED(root), FileListFilter *filter)
-{
- bool is_filtered = !is_hidden_file(file->relpath, filter);
-
- if (is_filtered && (filter->flags & FLF_DO_FILTER) && !FILENAME_IS_CURRPAR(file->relpath)) {
- /* We only check for types if some type are enabled in filtering. */
- if (filter->filter) {
- if (file->typeflag & FILE_TYPE_DIR) {
- if (file->typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
- if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) {
- is_filtered = false;
- }
- }
- else {
- if (!(filter->filter & FILE_TYPE_FOLDER)) {
- is_filtered = false;
- }
- }
- }
- else {
- if (!(file->typeflag & filter->filter)) {
- is_filtered = false;
- }
- }
- }
- if (is_filtered && (filter->filter_search[0] != '\0')) {
- if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) {
- is_filtered = false;
- }
- }
- }
-
- return is_filtered;
+ 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 (!is_hidden && (filter->flags & FLF_HIDE_PARENT)) {
+ if (filename[0] == '.' && filename[1] == '.' && filename[2] == '\0') {
+ is_hidden = true; /* ignore .. */
+ }
+ }
+ 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) {
+ char tmp_filename[FILE_MAX_LIBEXTRA];
+
+ BLI_strncpy(tmp_filename, filename, sizeof(tmp_filename));
+ sep = tmp_filename + (sep - filename);
+ while (sep) {
+ BLI_assert(sep[1] != '\0');
+ if (is_hidden_file(sep + 1, filter)) {
+ is_hidden = true;
+ break;
+ }
+ *sep = '\0';
+ sep = (char *)BLI_last_slash(tmp_filename);
+ }
+ }
+ return is_hidden;
+}
+
+static bool is_filtered_file(FileListInternEntry *file,
+ const char *UNUSED(root),
+ FileListFilter *filter)
+{
+ bool is_filtered = !is_hidden_file(file->relpath, filter);
+
+ if (is_filtered && (filter->flags & FLF_DO_FILTER) && !FILENAME_IS_CURRPAR(file->relpath)) {
+ /* We only check for types if some type are enabled in filtering. */
+ if (filter->filter) {
+ if (file->typeflag & FILE_TYPE_DIR) {
+ if (file->typeflag &
+ (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
+ if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) {
+ is_filtered = false;
+ }
+ }
+ else {
+ if (!(filter->filter & FILE_TYPE_FOLDER)) {
+ is_filtered = false;
+ }
+ }
+ }
+ else {
+ if (!(file->typeflag & filter->filter)) {
+ is_filtered = false;
+ }
+ }
+ }
+ if (is_filtered && (filter->filter_search[0] != '\0')) {
+ if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) {
+ is_filtered = false;
+ }
+ }
+ }
+
+ return is_filtered;
}
static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileListFilter *filter)
{
- bool is_filtered;
- char path[FILE_MAX_LIBEXTRA], dir[FILE_MAX_LIBEXTRA], *group, *name;
-
- 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);
- if (is_filtered && (filter->flags & FLF_DO_FILTER) && !FILENAME_IS_CURRPAR(file->relpath)) {
- /* We only check for types if some type are enabled in filtering. */
- if (filter->filter || filter->filter_id) {
- if (file->typeflag & FILE_TYPE_DIR) {
- if (file->typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
- if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) {
- is_filtered = false;
- }
- }
- else {
- if (!(filter->filter & FILE_TYPE_FOLDER)) {
- is_filtered = false;
- }
- }
- }
- if (is_filtered && group) {
- if (!name && (filter->flags & FLF_HIDE_LIB_DIR)) {
- is_filtered = false;
- }
- else {
- unsigned int filter_id = groupname_to_filter_id(group);
- if (!(filter_id & filter->filter_id)) {
- is_filtered = false;
- }
- }
- }
- }
- if (is_filtered && (filter->filter_search[0] != '\0')) {
- if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) {
- is_filtered = false;
- }
- }
- }
- }
- else {
- is_filtered = is_filtered_file(file, root, filter);
- }
-
- return is_filtered;
-}
-
-static bool is_filtered_main(FileListInternEntry *file, const char *UNUSED(dir), FileListFilter *filter)
-{
- return !is_hidden_file(file->relpath, filter);
+ bool is_filtered;
+ char path[FILE_MAX_LIBEXTRA], dir[FILE_MAX_LIBEXTRA], *group, *name;
+
+ 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);
+ if (is_filtered && (filter->flags & FLF_DO_FILTER) && !FILENAME_IS_CURRPAR(file->relpath)) {
+ /* We only check for types if some type are enabled in filtering. */
+ if (filter->filter || filter->filter_id) {
+ if (file->typeflag & FILE_TYPE_DIR) {
+ if (file->typeflag &
+ (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
+ if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) {
+ is_filtered = false;
+ }
+ }
+ else {
+ if (!(filter->filter & FILE_TYPE_FOLDER)) {
+ is_filtered = false;
+ }
+ }
+ }
+ if (is_filtered && group) {
+ if (!name && (filter->flags & FLF_HIDE_LIB_DIR)) {
+ is_filtered = false;
+ }
+ else {
+ unsigned int filter_id = groupname_to_filter_id(group);
+ if (!(filter_id & filter->filter_id)) {
+ is_filtered = false;
+ }
+ }
+ }
+ }
+ if (is_filtered && (filter->filter_search[0] != '\0')) {
+ if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) {
+ is_filtered = false;
+ }
+ }
+ }
+ }
+ else {
+ is_filtered = is_filtered_file(file, root, filter);
+ }
+
+ return is_filtered;
+}
+
+static bool is_filtered_main(FileListInternEntry *file,
+ const char *UNUSED(dir),
+ FileListFilter *filter)
+{
+ return !is_hidden_file(file->relpath, filter);
}
static void filelist_filter_clear(FileList *filelist)
{
- filelist->flags |= FL_NEED_FILTERING;
+ filelist->flags |= FL_NEED_FILTERING;
}
void filelist_filter(FileList *filelist)
{
- int num_filtered = 0;
- const int num_files = filelist->filelist.nbr_entries;
- FileListInternEntry **filtered_tmp, *file;
-
- if (filelist->filelist.nbr_entries == 0) {
- return;
- }
-
- if (!(filelist->flags & FL_NEED_FILTERING)) {
- /* Assume it has already been filtered, nothing else to do! */
- return;
- }
-
- filelist->filter_data.flags &= ~FLF_HIDE_LIB_DIR;
- if (filelist->max_recursion) {
- /* Never show lib ID 'categories' directories when we are in 'flat' mode, unless
- * root path is a blend file. */
- char dir[FILE_MAX_LIBEXTRA];
- if (!filelist_islibrary(filelist, dir, NULL)) {
- filelist->filter_data.flags |= FLF_HIDE_LIB_DIR;
- }
- }
-
- filtered_tmp = MEM_mallocN(sizeof(*filtered_tmp) * (size_t)num_files, __func__);
-
- /* Filter remap & count how many files are left after filter in a single loop. */
- for (file = filelist->filelist_intern.entries.first; file; file = file->next) {
- if (filelist->filterf(file, filelist->filelist.root, &filelist->filter_data)) {
- filtered_tmp[num_filtered++] = file;
- }
- }
-
- if (filelist->filelist_intern.filtered) {
- MEM_freeN(filelist->filelist_intern.filtered);
- }
- filelist->filelist_intern.filtered = MEM_mallocN(sizeof(*filelist->filelist_intern.filtered) * (size_t)num_filtered,
- __func__);
- memcpy(filelist->filelist_intern.filtered, filtered_tmp,
- sizeof(*filelist->filelist_intern.filtered) * (size_t)num_filtered);
- filelist->filelist.nbr_entries_filtered = num_filtered;
-// printf("Filetered: %d over %d entries\n", num_filtered, filelist->filelist.nbr_entries);
-
- filelist_cache_clear(&filelist->filelist_cache, filelist->filelist_cache.size);
- filelist->flags &= ~FL_NEED_FILTERING;
-
- MEM_freeN(filtered_tmp);
-}
-
-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 char *filter_glob, const char *filter_search)
-{
- bool update = false;
-
- if (((filelist->filter_data.flags & FLF_DO_FILTER) != 0) != (do_filter != 0)) {
- filelist->filter_data.flags ^= FLF_DO_FILTER;
- update = true;
- }
- if (((filelist->filter_data.flags & FLF_HIDE_DOT) != 0) != (hide_dot != 0)) {
- filelist->filter_data.flags ^= FLF_HIDE_DOT;
- update = true;
- }
- if (((filelist->filter_data.flags & FLF_HIDE_PARENT) != 0) != (hide_parent != 0)) {
- filelist->filter_data.flags ^= FLF_HIDE_PARENT;
- update = true;
- }
- if ((filelist->filter_data.filter != filter) || (filelist->filter_data.filter_id != filter_id)) {
- filelist->filter_data.filter = filter;
- filelist->filter_data.filter_id = filter_id;
- update = true;
- }
- if (!STREQ(filelist->filter_data.filter_glob, filter_glob)) {
- BLI_strncpy(filelist->filter_data.filter_glob, filter_glob, sizeof(filelist->filter_data.filter_glob));
- update = true;
- }
- if ((BLI_strcmp_ignore_pad(filelist->filter_data.filter_search, filter_search, '*') != 0)) {
- BLI_strncpy_ensure_pad(filelist->filter_data.filter_search, filter_search, '*',
- sizeof(filelist->filter_data.filter_search));
- update = true;
- }
-
- if (update) {
- /* And now, free filtered data so that we know we have to filter again. */
- filelist_filter_clear(filelist);
- }
+ int num_filtered = 0;
+ const int num_files = filelist->filelist.nbr_entries;
+ FileListInternEntry **filtered_tmp, *file;
+
+ if (filelist->filelist.nbr_entries == 0) {
+ return;
+ }
+
+ if (!(filelist->flags & FL_NEED_FILTERING)) {
+ /* Assume it has already been filtered, nothing else to do! */
+ return;
+ }
+
+ filelist->filter_data.flags &= ~FLF_HIDE_LIB_DIR;
+ if (filelist->max_recursion) {
+ /* Never show lib ID 'categories' directories when we are in 'flat' mode, unless
+ * root path is a blend file. */
+ char dir[FILE_MAX_LIBEXTRA];
+ if (!filelist_islibrary(filelist, dir, NULL)) {
+ filelist->filter_data.flags |= FLF_HIDE_LIB_DIR;
+ }
+ }
+
+ filtered_tmp = MEM_mallocN(sizeof(*filtered_tmp) * (size_t)num_files, __func__);
+
+ /* Filter remap & count how many files are left after filter in a single loop. */
+ for (file = filelist->filelist_intern.entries.first; file; file = file->next) {
+ if (filelist->filterf(file, filelist->filelist.root, &filelist->filter_data)) {
+ filtered_tmp[num_filtered++] = file;
+ }
+ }
+
+ if (filelist->filelist_intern.filtered) {
+ MEM_freeN(filelist->filelist_intern.filtered);
+ }
+ filelist->filelist_intern.filtered = MEM_mallocN(
+ sizeof(*filelist->filelist_intern.filtered) * (size_t)num_filtered, __func__);
+ memcpy(filelist->filelist_intern.filtered,
+ filtered_tmp,
+ sizeof(*filelist->filelist_intern.filtered) * (size_t)num_filtered);
+ filelist->filelist.nbr_entries_filtered = num_filtered;
+ // printf("Filetered: %d over %d entries\n", num_filtered, filelist->filelist.nbr_entries);
+
+ filelist_cache_clear(&filelist->filelist_cache, filelist->filelist_cache.size);
+ filelist->flags &= ~FL_NEED_FILTERING;
+
+ MEM_freeN(filtered_tmp);
+}
+
+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 char *filter_glob,
+ const char *filter_search)
+{
+ bool update = false;
+
+ if (((filelist->filter_data.flags & FLF_DO_FILTER) != 0) != (do_filter != 0)) {
+ filelist->filter_data.flags ^= FLF_DO_FILTER;
+ update = true;
+ }
+ if (((filelist->filter_data.flags & FLF_HIDE_DOT) != 0) != (hide_dot != 0)) {
+ filelist->filter_data.flags ^= FLF_HIDE_DOT;
+ update = true;
+ }
+ if (((filelist->filter_data.flags & FLF_HIDE_PARENT) != 0) != (hide_parent != 0)) {
+ filelist->filter_data.flags ^= FLF_HIDE_PARENT;
+ update = true;
+ }
+ if ((filelist->filter_data.filter != filter) || (filelist->filter_data.filter_id != filter_id)) {
+ filelist->filter_data.filter = filter;
+ filelist->filter_data.filter_id = filter_id;
+ update = true;
+ }
+ if (!STREQ(filelist->filter_data.filter_glob, filter_glob)) {
+ BLI_strncpy(
+ filelist->filter_data.filter_glob, filter_glob, sizeof(filelist->filter_data.filter_glob));
+ update = true;
+ }
+ if ((BLI_strcmp_ignore_pad(filelist->filter_data.filter_search, filter_search, '*') != 0)) {
+ BLI_strncpy_ensure_pad(filelist->filter_data.filter_search,
+ filter_search,
+ '*',
+ sizeof(filelist->filter_data.filter_search));
+ update = true;
+ }
+
+ if (update) {
+ /* And now, free filtered data so that we know we have to filter again. */
+ filelist_filter_clear(filelist);
+ }
}
/* ********** Icon/image helpers ********** */
void filelist_init_icons(void)
{
- short x, y, k;
- ImBuf *bbuf;
- ImBuf *ibuf;
+ short x, y, k;
+ ImBuf *bbuf;
+ ImBuf *ibuf;
- BLI_assert(G.background == false);
+ BLI_assert(G.background == false);
#ifdef WITH_HEADLESS
- bbuf = NULL;
+ bbuf = NULL;
#else
- bbuf = IMB_ibImageFromMemory((const uchar *)datatoc_prvicons_png, datatoc_prvicons_png_size, IB_rect, NULL, "<splash>");
+ bbuf = IMB_ibImageFromMemory(
+ (const uchar *)datatoc_prvicons_png, datatoc_prvicons_png_size, IB_rect, NULL, "<splash>");
#endif
- if (bbuf) {
- for (y = 0; y < SPECIAL_IMG_ROWS; y++) {
- for (x = 0; x < SPECIAL_IMG_COLS; x++) {
- int tile = SPECIAL_IMG_COLS * y + x;
- if (tile < SPECIAL_IMG_MAX) {
- ibuf = IMB_allocImBuf(SPECIAL_IMG_SIZE, SPECIAL_IMG_SIZE, 32, IB_rect);
- for (k = 0; k < SPECIAL_IMG_SIZE; k++) {
- memcpy(&ibuf->rect[k * SPECIAL_IMG_SIZE], &bbuf->rect[(k + y * SPECIAL_IMG_SIZE) * SPECIAL_IMG_SIZE * SPECIAL_IMG_COLS + x * SPECIAL_IMG_SIZE], SPECIAL_IMG_SIZE * sizeof(int));
- }
- gSpecialFileImages[tile] = ibuf;
- }
- }
- }
- IMB_freeImBuf(bbuf);
- }
+ if (bbuf) {
+ for (y = 0; y < SPECIAL_IMG_ROWS; y++) {
+ for (x = 0; x < SPECIAL_IMG_COLS; x++) {
+ int tile = SPECIAL_IMG_COLS * y + x;
+ if (tile < SPECIAL_IMG_MAX) {
+ ibuf = IMB_allocImBuf(SPECIAL_IMG_SIZE, SPECIAL_IMG_SIZE, 32, IB_rect);
+ for (k = 0; k < SPECIAL_IMG_SIZE; k++) {
+ memcpy(&ibuf->rect[k * SPECIAL_IMG_SIZE],
+ &bbuf->rect[(k + y * SPECIAL_IMG_SIZE) * SPECIAL_IMG_SIZE * SPECIAL_IMG_COLS +
+ x * SPECIAL_IMG_SIZE],
+ SPECIAL_IMG_SIZE * sizeof(int));
+ }
+ gSpecialFileImages[tile] = ibuf;
+ }
+ }
+ }
+ IMB_freeImBuf(bbuf);
+ }
}
void filelist_free_icons(void)
{
- int i;
+ int i;
- BLI_assert(G.background == false);
+ BLI_assert(G.background == false);
- for (i = 0; i < SPECIAL_IMG_MAX; ++i) {
- IMB_freeImBuf(gSpecialFileImages[i]);
- gSpecialFileImages[i] = NULL;
- }
+ for (i = 0; i < SPECIAL_IMG_MAX; ++i) {
+ IMB_freeImBuf(gSpecialFileImages[i]);
+ gSpecialFileImages[i] = NULL;
+ }
}
void filelist_imgsize(struct FileList *filelist, short w, short h)
{
- filelist->prv_w = w;
- filelist->prv_h = h;
+ filelist->prv_w = w;
+ filelist->prv_h = h;
}
static FileDirEntry *filelist_geticon_get_file(struct FileList *filelist, const int index)
{
- BLI_assert(G.background == false);
+ BLI_assert(G.background == false);
- return filelist_file(filelist, index);
+ return filelist_file(filelist, index);
}
ImBuf *filelist_getimage(struct FileList *filelist, const int index)
{
- FileDirEntry *file = filelist_geticon_get_file(filelist, index);
+ FileDirEntry *file = filelist_geticon_get_file(filelist, index);
- return file->image;
+ return file->image;
}
static ImBuf *filelist_geticon_image_ex(const unsigned int typeflag, const char *relpath)
{
- ImBuf *ibuf = NULL;
-
- if (typeflag & FILE_TYPE_DIR) {
- if (FILENAME_IS_PARENT(relpath)) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
- }
- else if (FILENAME_IS_CURRENT(relpath)) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH];
- }
- else {
- ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER];
- }
- }
- else if (typeflag & FILE_TYPE_BLENDER) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE];
- }
- else if (typeflag & FILE_TYPE_BLENDERLIB) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
- }
- else if (typeflag & (FILE_TYPE_MOVIE)) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE];
- }
- else if (typeflag & FILE_TYPE_SOUND) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE];
- }
- else if (typeflag & FILE_TYPE_PYSCRIPT) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE];
- }
- else if (typeflag & FILE_TYPE_FTFONT) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE];
- }
- else if (typeflag & FILE_TYPE_TEXT) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE];
- }
- else if (typeflag & FILE_TYPE_IMAGE) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_LOADING];
- }
- else if (typeflag & FILE_TYPE_BLENDER_BACKUP) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_BACKUP];
- }
- else {
- ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
- }
-
- return ibuf;
+ ImBuf *ibuf = NULL;
+
+ if (typeflag & FILE_TYPE_DIR) {
+ if (FILENAME_IS_PARENT(relpath)) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
+ }
+ else if (FILENAME_IS_CURRENT(relpath)) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH];
+ }
+ else {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER];
+ }
+ }
+ else if (typeflag & FILE_TYPE_BLENDER) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE];
+ }
+ else if (typeflag & FILE_TYPE_BLENDERLIB) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
+ }
+ else if (typeflag & (FILE_TYPE_MOVIE)) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE];
+ }
+ else if (typeflag & FILE_TYPE_SOUND) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE];
+ }
+ else if (typeflag & FILE_TYPE_PYSCRIPT) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE];
+ }
+ else if (typeflag & FILE_TYPE_FTFONT) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE];
+ }
+ else if (typeflag & FILE_TYPE_TEXT) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE];
+ }
+ else if (typeflag & FILE_TYPE_IMAGE) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_LOADING];
+ }
+ else if (typeflag & FILE_TYPE_BLENDER_BACKUP) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_BACKUP];
+ }
+ else {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
+ }
+
+ return ibuf;
}
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);
-}
-
-static int filelist_geticon_ex(
- const int typeflag, const int blentype, const char *relpath, const bool is_main, const bool ignore_libdir)
-{
- if ((typeflag & FILE_TYPE_DIR) && !(ignore_libdir && (typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER)))) {
- if (FILENAME_IS_PARENT(relpath)) {
- return is_main ? ICON_FILE_PARENT : ICON_NONE;
- }
- else if (typeflag & FILE_TYPE_APPLICATIONBUNDLE) {
- return ICON_UGLYPACKAGE;
- }
- else if (typeflag & FILE_TYPE_BLENDER) {
- return ICON_FILE_BLEND;
- }
- 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;
- }
- }
-
- if (typeflag & FILE_TYPE_BLENDER)
- return ICON_FILE_BLEND;
- else if (typeflag & FILE_TYPE_BLENDER_BACKUP)
- return ICON_FILE_BACKUP;
- else if (typeflag & FILE_TYPE_IMAGE)
- return ICON_FILE_IMAGE;
- else if (typeflag & FILE_TYPE_MOVIE)
- return ICON_FILE_MOVIE;
- else if (typeflag & FILE_TYPE_PYSCRIPT)
- return ICON_FILE_SCRIPT;
- else if (typeflag & FILE_TYPE_SOUND)
- return ICON_FILE_SOUND;
- else if (typeflag & FILE_TYPE_FTFONT)
- return ICON_FILE_FONT;
- else if (typeflag & FILE_TYPE_BTX)
- return ICON_FILE_BLANK;
- else if (typeflag & FILE_TYPE_COLLADA)
- return ICON_FILE_BLANK;
- else if (typeflag & FILE_TYPE_ALEMBIC)
- return ICON_FILE_BLANK;
- else if (typeflag & FILE_TYPE_TEXT)
- return ICON_FILE_TEXT;
- else if (typeflag & FILE_TYPE_BLENDERLIB) {
- const int ret = UI_idcode_icon_get(blentype);
- if (ret != ICON_NONE) {
- return ret;
- }
- }
- return is_main ? ICON_FILE_BLANK : ICON_NONE;
+ FileDirEntry *file = filelist_geticon_get_file(filelist, index);
+
+ return filelist_geticon_image_ex(file->typeflag, file->relpath);
+}
+
+static int filelist_geticon_ex(const int typeflag,
+ const int blentype,
+ const char *relpath,
+ const bool is_main,
+ const bool ignore_libdir)
+{
+ if ((typeflag & FILE_TYPE_DIR) &&
+ !(ignore_libdir && (typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER)))) {
+ if (FILENAME_IS_PARENT(relpath)) {
+ return is_main ? ICON_FILE_PARENT : ICON_NONE;
+ }
+ else if (typeflag & FILE_TYPE_APPLICATIONBUNDLE) {
+ return ICON_UGLYPACKAGE;
+ }
+ else if (typeflag & FILE_TYPE_BLENDER) {
+ return ICON_FILE_BLEND;
+ }
+ 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;
+ }
+ }
+
+ if (typeflag & FILE_TYPE_BLENDER)
+ return ICON_FILE_BLEND;
+ else if (typeflag & FILE_TYPE_BLENDER_BACKUP)
+ return ICON_FILE_BACKUP;
+ else if (typeflag & FILE_TYPE_IMAGE)
+ return ICON_FILE_IMAGE;
+ else if (typeflag & FILE_TYPE_MOVIE)
+ return ICON_FILE_MOVIE;
+ else if (typeflag & FILE_TYPE_PYSCRIPT)
+ return ICON_FILE_SCRIPT;
+ else if (typeflag & FILE_TYPE_SOUND)
+ return ICON_FILE_SOUND;
+ else if (typeflag & FILE_TYPE_FTFONT)
+ return ICON_FILE_FONT;
+ else if (typeflag & FILE_TYPE_BTX)
+ return ICON_FILE_BLANK;
+ else if (typeflag & FILE_TYPE_COLLADA)
+ return ICON_FILE_BLANK;
+ else if (typeflag & FILE_TYPE_ALEMBIC)
+ return ICON_FILE_BLANK;
+ else if (typeflag & FILE_TYPE_TEXT)
+ return ICON_FILE_TEXT;
+ else if (typeflag & FILE_TYPE_BLENDERLIB) {
+ const int ret = UI_idcode_icon_get(blentype);
+ if (ret != ICON_NONE) {
+ return ret;
+ }
+ }
+ return is_main ? ICON_FILE_BLANK : ICON_NONE;
}
int filelist_geticon(struct FileList *filelist, const int index, const bool is_main)
{
- FileDirEntry *file = filelist_geticon_get_file(filelist, index);
+ FileDirEntry *file = filelist_geticon_get_file(filelist, index);
- return filelist_geticon_ex(file->typeflag, file->blentype, file->relpath, is_main, false);
+ return filelist_geticon_ex(file->typeflag, file->blentype, file->relpath, is_main, false);
}
/* ********** Main ********** */
-static bool filelist_checkdir_dir(struct FileList *UNUSED(filelist), char *r_dir, const bool do_change)
+static bool filelist_checkdir_dir(struct FileList *UNUSED(filelist),
+ char *r_dir,
+ const bool do_change)
{
- if (do_change) {
- BLI_make_exist(r_dir);
- return true;
- }
- else {
- return BLI_is_dir(r_dir);
- }
+ if (do_change) {
+ BLI_make_exist(r_dir);
+ return true;
+ }
+ else {
+ return BLI_is_dir(r_dir);
+ }
}
-static bool filelist_checkdir_lib(struct FileList *UNUSED(filelist), char *r_dir, const bool do_change)
+static bool filelist_checkdir_lib(struct FileList *UNUSED(filelist),
+ char *r_dir,
+ const bool do_change)
{
- char tdir[FILE_MAX_LIBEXTRA];
- char *name;
+ char tdir[FILE_MAX_LIBEXTRA];
+ char *name;
- const bool is_valid = (BLI_is_dir(r_dir) ||
- (BLO_library_path_explode(r_dir, tdir, NULL, &name) && BLI_is_file(tdir) && !name));
+ const bool is_valid = (BLI_is_dir(r_dir) ||
+ (BLO_library_path_explode(r_dir, tdir, NULL, &name) &&
+ BLI_is_file(tdir) && !name));
- if (do_change && !is_valid) {
- /* if not a valid library, we need it to be a valid directory! */
- BLI_make_exist(r_dir);
- return true;
- }
- return is_valid;
+ if (do_change && !is_valid) {
+ /* if not a valid library, we need it to be a valid directory! */
+ BLI_make_exist(r_dir);
+ return true;
+ }
+ return is_valid;
}
static bool filelist_checkdir_main(struct FileList *filelist, char *r_dir, const bool do_change)
{
- /* TODO */
- return filelist_checkdir_lib(filelist, r_dir, do_change);
+ /* TODO */
+ return filelist_checkdir_lib(filelist, r_dir, do_change);
}
static void filelist_entry_clear(FileDirEntry *entry)
{
- if (entry->name) {
- MEM_freeN(entry->name);
- }
- if (entry->description) {
- MEM_freeN(entry->description);
- }
- if (entry->relpath) {
- MEM_freeN(entry->relpath);
- }
- if (entry->image) {
- IMB_freeImBuf(entry->image);
- }
- /* For now, consider FileDirEntryRevision::poin as not owned here,
- * so no need to do anything about it */
-
- if (!BLI_listbase_is_empty(&entry->variants)) {
- FileDirEntryVariant *var;
-
- for (var = entry->variants.first; var; var = var->next) {
- if (var->name) {
- MEM_freeN(var->name);
- }
- if (var->description) {
- MEM_freeN(var->description);
- }
-
- if (!BLI_listbase_is_empty(&var->revisions)) {
- FileDirEntryRevision *rev;
-
- for (rev = var->revisions.first; rev; rev = rev->next) {
- if (rev->comment) {
- MEM_freeN(rev->comment);
- }
- }
-
- BLI_freelistN(&var->revisions);
- }
- }
-
- /* TODO: tags! */
-
- BLI_freelistN(&entry->variants);
- }
- else if (entry->entry) {
- MEM_freeN(entry->entry);
- }
+ if (entry->name) {
+ MEM_freeN(entry->name);
+ }
+ if (entry->description) {
+ MEM_freeN(entry->description);
+ }
+ if (entry->relpath) {
+ MEM_freeN(entry->relpath);
+ }
+ if (entry->image) {
+ IMB_freeImBuf(entry->image);
+ }
+ /* For now, consider FileDirEntryRevision::poin as not owned here,
+ * so no need to do anything about it */
+
+ if (!BLI_listbase_is_empty(&entry->variants)) {
+ FileDirEntryVariant *var;
+
+ for (var = entry->variants.first; var; var = var->next) {
+ if (var->name) {
+ MEM_freeN(var->name);
+ }
+ if (var->description) {
+ MEM_freeN(var->description);
+ }
+
+ if (!BLI_listbase_is_empty(&var->revisions)) {
+ FileDirEntryRevision *rev;
+
+ for (rev = var->revisions.first; rev; rev = rev->next) {
+ if (rev->comment) {
+ MEM_freeN(rev->comment);
+ }
+ }
+
+ BLI_freelistN(&var->revisions);
+ }
+ }
+
+ /* TODO: tags! */
+
+ BLI_freelistN(&entry->variants);
+ }
+ else if (entry->entry) {
+ MEM_freeN(entry->entry);
+ }
}
static void filelist_entry_free(FileDirEntry *entry)
{
- filelist_entry_clear(entry);
- MEM_freeN(entry);
+ filelist_entry_clear(entry);
+ MEM_freeN(entry);
}
static void filelist_direntryarr_free(FileDirEntryArr *array)
{
#if 0
- FileDirEntry *entry, *entry_next;
+ FileDirEntry *entry, *entry_next;
- for (entry = array->entries.first; entry; entry = entry_next) {
- entry_next = entry->next;
- filelist_entry_free(entry);
- }
- BLI_listbase_clear(&array->entries);
+ for (entry = array->entries.first; entry; entry = entry_next) {
+ entry_next = entry->next;
+ filelist_entry_free(entry);
+ }
+ BLI_listbase_clear(&array->entries);
#else
- BLI_assert(BLI_listbase_is_empty(&array->entries));
+ BLI_assert(BLI_listbase_is_empty(&array->entries));
#endif
- array->nbr_entries = 0;
- array->nbr_entries_filtered = -1;
- array->entry_idx_start = -1;
- array->entry_idx_end = -1;
+ array->nbr_entries = 0;
+ array->nbr_entries_filtered = -1;
+ array->entry_idx_start = -1;
+ array->entry_idx_end = -1;
}
static void filelist_intern_entry_free(FileListInternEntry *entry)
{
- if (entry->relpath) {
- MEM_freeN(entry->relpath);
- }
- if (entry->name) {
- MEM_freeN(entry->name);
- }
- MEM_freeN(entry);
+ if (entry->relpath) {
+ MEM_freeN(entry->relpath);
+ }
+ if (entry->name) {
+ MEM_freeN(entry->name);
+ }
+ MEM_freeN(entry);
}
static void filelist_intern_free(FileListIntern *filelist_intern)
{
- FileListInternEntry *entry, *entry_next;
+ FileListInternEntry *entry, *entry_next;
- for (entry = filelist_intern->entries.first; entry; entry = entry_next) {
- entry_next = entry->next;
- filelist_intern_entry_free(entry);
- }
- BLI_listbase_clear(&filelist_intern->entries);
+ for (entry = filelist_intern->entries.first; entry; entry = entry_next) {
+ entry_next = entry->next;
+ filelist_intern_entry_free(entry);
+ }
+ BLI_listbase_clear(&filelist_intern->entries);
- MEM_SAFE_FREE(filelist_intern->filtered);
+ 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,
+ int UNUSED(threadid))
{
- FileListEntryCache *cache = BLI_task_pool_userdata(pool);
- FileListEntryPreview *preview = taskdata;
+ FileListEntryCache *cache = BLI_task_pool_userdata(pool);
+ FileListEntryPreview *preview = taskdata;
- ThumbSource source = 0;
+ ThumbSource source = 0;
-// printf("%s: Start (%d)...\n", __func__, threadid);
+ // printf("%s: Start (%d)...\n", __func__, threadid);
-// printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
- BLI_assert(preview->flags & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT |
- FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB));
+ // printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
+ BLI_assert(preview->flags &
+ (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT | FILE_TYPE_BLENDER |
+ FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB));
- if (preview->flags & FILE_TYPE_IMAGE) {
- source = THB_SOURCE_IMAGE;
- }
- else if (preview->flags & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB)) {
- source = THB_SOURCE_BLEND;
- }
- else if (preview->flags & FILE_TYPE_MOVIE) {
- source = THB_SOURCE_MOVIE;
- }
- else if (preview->flags & FILE_TYPE_FTFONT) {
- source = THB_SOURCE_FONT;
- }
+ if (preview->flags & FILE_TYPE_IMAGE) {
+ source = THB_SOURCE_IMAGE;
+ }
+ else if (preview->flags &
+ (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB)) {
+ source = THB_SOURCE_BLEND;
+ }
+ else if (preview->flags & FILE_TYPE_MOVIE) {
+ source = THB_SOURCE_MOVIE;
+ }
+ else if (preview->flags & FILE_TYPE_FTFONT) {
+ source = THB_SOURCE_FONT;
+ }
- IMB_thumb_path_lock(preview->path);
- preview->img = IMB_thumb_manage(preview->path, THB_LARGE, source);
- IMB_thumb_path_unlock(preview->path);
+ IMB_thumb_path_lock(preview->path);
+ 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);
- BLI_thread_queue_push(cache->previews_done, preview);
+ /* 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);
+ BLI_thread_queue_push(cache->previews_done, preview);
-// printf("%s: End (%d)...\n", __func__, threadid);
+ // 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,
+ int UNUSED(threadid))
{
- FileListEntryPreview *preview = taskdata;
+ FileListEntryPreview *preview = taskdata;
- /* 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) {
- if (preview->img) {
- IMB_freeImBuf(preview->img);
- }
- MEM_freeN(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) {
+ if (preview->img) {
+ IMB_freeImBuf(preview->img);
+ }
+ MEM_freeN(preview);
+ }
}
static void filelist_cache_preview_ensure_running(FileListEntryCache *cache)
{
- if (!cache->previews_pool) {
- TaskScheduler *scheduler = BLI_task_scheduler_get();
+ if (!cache->previews_pool) {
+ TaskScheduler *scheduler = BLI_task_scheduler_get();
- cache->previews_pool = BLI_task_pool_create_background(scheduler, cache);
- cache->previews_done = BLI_thread_queue_init();
+ cache->previews_pool = BLI_task_pool_create_background(scheduler, cache);
+ cache->previews_done = BLI_thread_queue_init();
- IMB_thumb_locks_acquire();
- }
+ IMB_thumb_locks_acquire();
+ }
}
static void filelist_cache_previews_clear(FileListEntryCache *cache)
{
- FileListEntryPreview *preview;
+ FileListEntryPreview *preview;
- if (cache->previews_pool) {
- BLI_task_pool_cancel(cache->previews_pool);
+ if (cache->previews_pool) {
+ BLI_task_pool_cancel(cache->previews_pool);
- 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);
- if (preview->img) {
- IMB_freeImBuf(preview->img);
- }
- MEM_freeN(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);
+ if (preview->img) {
+ IMB_freeImBuf(preview->img);
+ }
+ MEM_freeN(preview);
+ }
+ }
}
static void filelist_cache_previews_free(FileListEntryCache *cache)
{
- if (cache->previews_pool) {
- BLI_thread_queue_nowait(cache->previews_done);
+ if (cache->previews_pool) {
+ BLI_thread_queue_nowait(cache->previews_done);
- filelist_cache_previews_clear(cache);
+ filelist_cache_previews_clear(cache);
- BLI_thread_queue_free(cache->previews_done);
- BLI_task_pool_free(cache->previews_pool);
- cache->previews_pool = NULL;
- cache->previews_done = NULL;
+ BLI_thread_queue_free(cache->previews_done);
+ BLI_task_pool_free(cache->previews_pool);
+ cache->previews_pool = NULL;
+ cache->previews_done = NULL;
- IMB_thumb_locks_release();
- }
+ IMB_thumb_locks_release();
+ }
- cache->flags &= ~FLC_PREVIEWS_ACTIVE;
+ cache->flags &= ~FLC_PREVIEWS_ACTIVE;
}
static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry, const int index)
{
- FileListEntryCache *cache = &filelist->filelist_cache;
+ FileListEntryCache *cache = &filelist->filelist_cache;
- BLI_assert(cache->flags & FLC_PREVIEWS_ACTIVE);
+ BLI_assert(cache->flags & FLC_PREVIEWS_ACTIVE);
- if (!entry->image &&
- !(entry->flags & FILE_ENTRY_INVALID_PREVIEW) &&
- (entry->typeflag & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT |
- FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB)))
- {
- FileListEntryPreview *preview = MEM_mallocN(sizeof(*preview), __func__);
- BLI_join_dirfile(preview->path, sizeof(preview->path), filelist->filelist.root, entry->relpath);
- preview->index = index;
- preview->flags = entry->typeflag;
- preview->img = NULL;
-// printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
+ if (!entry->image && !(entry->flags & FILE_ENTRY_INVALID_PREVIEW) &&
+ (entry->typeflag & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT |
+ FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB))) {
+ FileListEntryPreview *preview = MEM_mallocN(sizeof(*preview), __func__);
+ BLI_join_dirfile(
+ preview->path, sizeof(preview->path), filelist->filelist.root, entry->relpath);
+ preview->index = index;
+ preview->flags = entry->typeflag;
+ preview->img = NULL;
+ // 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);
- }
+ 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);
+ }
}
static void filelist_cache_init(FileListEntryCache *cache, size_t cache_size)
{
- BLI_listbase_clear(&cache->cached_entries);
+ BLI_listbase_clear(&cache->cached_entries);
- cache->block_cursor = cache->block_start_index = cache->block_center_index = cache->block_end_index = 0;
- cache->block_entries = MEM_mallocN(sizeof(*cache->block_entries) * cache_size, __func__);
+ cache->block_cursor = cache->block_start_index = cache->block_center_index =
+ cache->block_end_index = 0;
+ cache->block_entries = MEM_mallocN(sizeof(*cache->block_entries) * cache_size, __func__);
- cache->misc_entries = BLI_ghash_ptr_new_ex(__func__, cache_size);
- cache->misc_entries_indices = MEM_mallocN(sizeof(*cache->misc_entries_indices) * cache_size, __func__);
- copy_vn_i(cache->misc_entries_indices, cache_size, -1);
- cache->misc_cursor = 0;
+ cache->misc_entries = BLI_ghash_ptr_new_ex(__func__, cache_size);
+ cache->misc_entries_indices = MEM_mallocN(sizeof(*cache->misc_entries_indices) * cache_size,
+ __func__);
+ copy_vn_i(cache->misc_entries_indices, cache_size, -1);
+ cache->misc_cursor = 0;
- /* XXX This assumes uint is 32 bits and uuid is 128 bits (char[16]), be careful! */
- cache->uuids = BLI_ghash_new_ex(
- BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__, cache_size * 2);
+ /* XXX This assumes uint is 32 bits and uuid is 128 bits (char[16]), be careful! */
+ cache->uuids = BLI_ghash_new_ex(
+ BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__, cache_size * 2);
- cache->size = cache_size;
- cache->flags = FLC_IS_INIT;
+ cache->size = cache_size;
+ cache->flags = FLC_IS_INIT;
}
static void filelist_cache_free(FileListEntryCache *cache)
{
- FileDirEntry *entry, *entry_next;
+ FileDirEntry *entry, *entry_next;
- if (!(cache->flags & FLC_IS_INIT)) {
- return;
- }
+ if (!(cache->flags & FLC_IS_INIT)) {
+ return;
+ }
- filelist_cache_previews_free(cache);
+ filelist_cache_previews_free(cache);
- MEM_freeN(cache->block_entries);
+ MEM_freeN(cache->block_entries);
- BLI_ghash_free(cache->misc_entries, NULL, NULL);
- MEM_freeN(cache->misc_entries_indices);
+ BLI_ghash_free(cache->misc_entries, NULL, NULL);
+ MEM_freeN(cache->misc_entries_indices);
- BLI_ghash_free(cache->uuids, NULL, NULL);
+ BLI_ghash_free(cache->uuids, NULL, NULL);
- for (entry = cache->cached_entries.first; entry; entry = entry_next) {
- entry_next = entry->next;
- filelist_entry_free(entry);
- }
- BLI_listbase_clear(&cache->cached_entries);
+ for (entry = cache->cached_entries.first; entry; entry = entry_next) {
+ entry_next = entry->next;
+ filelist_entry_free(entry);
+ }
+ BLI_listbase_clear(&cache->cached_entries);
}
static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size)
{
- FileDirEntry *entry, *entry_next;
+ FileDirEntry *entry, *entry_next;
- if (!(cache->flags & FLC_IS_INIT)) {
- return;
- }
+ if (!(cache->flags & FLC_IS_INIT)) {
+ return;
+ }
- filelist_cache_previews_clear(cache);
+ filelist_cache_previews_clear(cache);
- cache->block_cursor = cache->block_start_index = cache->block_center_index = cache->block_end_index = 0;
- if (new_size != cache->size) {
- cache->block_entries = MEM_reallocN(cache->block_entries, sizeof(*cache->block_entries) * new_size);
- }
+ cache->block_cursor = cache->block_start_index = cache->block_center_index =
+ cache->block_end_index = 0;
+ if (new_size != cache->size) {
+ cache->block_entries = MEM_reallocN(cache->block_entries,
+ sizeof(*cache->block_entries) * new_size);
+ }
- BLI_ghash_clear_ex(cache->misc_entries, NULL, NULL, new_size);
- if (new_size != cache->size) {
- cache->misc_entries_indices = MEM_reallocN(cache->misc_entries_indices,
- sizeof(*cache->misc_entries_indices) * new_size);
- }
- copy_vn_i(cache->misc_entries_indices, new_size, -1);
+ BLI_ghash_clear_ex(cache->misc_entries, NULL, NULL, new_size);
+ if (new_size != cache->size) {
+ cache->misc_entries_indices = MEM_reallocN(cache->misc_entries_indices,
+ sizeof(*cache->misc_entries_indices) * new_size);
+ }
+ copy_vn_i(cache->misc_entries_indices, new_size, -1);
- BLI_ghash_clear_ex(cache->uuids, NULL, NULL, new_size * 2);
+ BLI_ghash_clear_ex(cache->uuids, NULL, NULL, new_size * 2);
- cache->size = new_size;
+ cache->size = new_size;
- for (entry = cache->cached_entries.first; entry; entry = entry_next) {
- entry_next = entry->next;
- filelist_entry_free(entry);
- }
- BLI_listbase_clear(&cache->cached_entries);
+ for (entry = cache->cached_entries.first; entry; entry = entry_next) {
+ entry_next = entry->next;
+ filelist_entry_free(entry);
+ }
+ BLI_listbase_clear(&cache->cached_entries);
}
FileList *filelist_new(short type)
{
- FileList *p = MEM_callocN(sizeof(*p), __func__);
-
- filelist_cache_init(&p->filelist_cache, FILELIST_ENTRYCACHESIZE_DEFAULT);
-
- p->selection_state = BLI_ghash_new(BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__);
-
- switch (type) {
- case FILE_MAIN:
- p->checkdirf = filelist_checkdir_main;
- p->read_jobf = filelist_readjob_main;
- p->filterf = is_filtered_main;
- break;
- case FILE_LOADLIB:
- p->checkdirf = filelist_checkdir_lib;
- p->read_jobf = filelist_readjob_lib;
- p->filterf = is_filtered_lib;
- break;
- default:
- p->checkdirf = filelist_checkdir_dir;
- p->read_jobf = filelist_readjob_dir;
- p->filterf = is_filtered_file;
- break;
- }
- return p;
+ FileList *p = MEM_callocN(sizeof(*p), __func__);
+
+ filelist_cache_init(&p->filelist_cache, FILELIST_ENTRYCACHESIZE_DEFAULT);
+
+ p->selection_state = BLI_ghash_new(
+ BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__);
+
+ switch (type) {
+ case FILE_MAIN:
+ p->checkdirf = filelist_checkdir_main;
+ p->read_jobf = filelist_readjob_main;
+ p->filterf = is_filtered_main;
+ break;
+ case FILE_LOADLIB:
+ p->checkdirf = filelist_checkdir_lib;
+ p->read_jobf = filelist_readjob_lib;
+ p->filterf = is_filtered_lib;
+ break;
+ default:
+ p->checkdirf = filelist_checkdir_dir;
+ p->read_jobf = filelist_readjob_dir;
+ p->filterf = is_filtered_file;
+ break;
+ }
+ return p;
}
void filelist_clear_ex(struct FileList *filelist, const bool do_cache, const bool do_selection)
{
- if (!filelist) {
- return;
- }
+ if (!filelist) {
+ return;
+ }
- filelist_filter_clear(filelist);
+ filelist_filter_clear(filelist);
- if (do_cache) {
- filelist_cache_clear(&filelist->filelist_cache, filelist->filelist_cache.size);
- }
+ if (do_cache) {
+ filelist_cache_clear(&filelist->filelist_cache, filelist->filelist_cache.size);
+ }
- filelist_intern_free(&filelist->filelist_intern);
+ filelist_intern_free(&filelist->filelist_intern);
- filelist_direntryarr_free(&filelist->filelist);
+ filelist_direntryarr_free(&filelist->filelist);
- if (do_selection && filelist->selection_state) {
- BLI_ghash_clear(filelist->selection_state, MEM_freeN, NULL);
- }
+ if (do_selection && filelist->selection_state) {
+ BLI_ghash_clear(filelist->selection_state, MEM_freeN, NULL);
+ }
}
void filelist_clear(struct FileList *filelist)
{
- filelist_clear_ex(filelist, true, true);
+ filelist_clear_ex(filelist, true, true);
}
void filelist_free(struct FileList *filelist)
{
- if (!filelist) {
- printf("Attempting to delete empty filelist.\n");
- return;
- }
+ if (!filelist) {
+ printf("Attempting to delete empty filelist.\n");
+ return;
+ }
- /* No need to clear cache & selection_state, we free them anyway. */
- filelist_clear_ex(filelist, false, false);
- filelist_cache_free(&filelist->filelist_cache);
+ /* No need to clear cache & selection_state, we free them anyway. */
+ filelist_clear_ex(filelist, false, false);
+ filelist_cache_free(&filelist->filelist_cache);
- if (filelist->selection_state) {
- BLI_ghash_free(filelist->selection_state, MEM_freeN, NULL);
- filelist->selection_state = NULL;
- }
+ if (filelist->selection_state) {
+ BLI_ghash_free(filelist->selection_state, MEM_freeN, NULL);
+ filelist->selection_state = NULL;
+ }
- memset(&filelist->filter_data, 0, sizeof(filelist->filter_data));
+ memset(&filelist->filter_data, 0, sizeof(filelist->filter_data));
- filelist->flags &= ~(FL_NEED_SORTING | FL_NEED_FILTERING);
- filelist->sort = FILE_SORT_NONE;
+ filelist->flags &= ~(FL_NEED_SORTING | FL_NEED_FILTERING);
+ filelist->sort = FILE_SORT_NONE;
}
void filelist_freelib(struct FileList *filelist)
{
- if (filelist->libfiledata)
- BLO_blendhandle_close(filelist->libfiledata);
- filelist->libfiledata = NULL;
+ if (filelist->libfiledata)
+ BLO_blendhandle_close(filelist->libfiledata);
+ filelist->libfiledata = NULL;
}
BlendHandle *filelist_lib(struct FileList *filelist)
{
- return filelist->libfiledata;
+ return filelist->libfiledata;
}
-static const char *fileentry_uiname(const char *root, const char *relpath, const int typeflag, char *buff)
+static const char *fileentry_uiname(const char *root,
+ const char *relpath,
+ const int typeflag,
+ char *buff)
{
- char *name = NULL;
+ char *name = NULL;
- if (typeflag & FILE_TYPE_BLENDERLIB) {
- char abspath[FILE_MAX_LIBEXTRA];
- char *group;
+ if (typeflag & FILE_TYPE_BLENDERLIB) {
+ char abspath[FILE_MAX_LIBEXTRA];
+ char *group;
- BLI_join_dirfile(abspath, sizeof(abspath), root, relpath);
- BLO_library_path_explode(abspath, buff, &group, &name);
- if (!name) {
- name = group;
- }
- }
- /* Depending on platforms, 'my_file.blend/..' might be viewed as dir or not... */
- if (!name) {
- if (typeflag & FILE_TYPE_DIR) {
- name = (char *)relpath;
- }
- else {
- name = (char *)BLI_path_basename(relpath);
- }
- }
- BLI_assert(name);
+ BLI_join_dirfile(abspath, sizeof(abspath), root, relpath);
+ BLO_library_path_explode(abspath, buff, &group, &name);
+ if (!name) {
+ name = group;
+ }
+ }
+ /* Depending on platforms, 'my_file.blend/..' might be viewed as dir or not... */
+ if (!name) {
+ if (typeflag & FILE_TYPE_DIR) {
+ name = (char *)relpath;
+ }
+ else {
+ name = (char *)BLI_path_basename(relpath);
+ }
+ }
+ BLI_assert(name);
- return name;
+ return name;
}
const char *filelist_dir(struct FileList *filelist)
{
- return filelist->filelist.root;
+ return filelist->filelist.root;
}
bool filelist_is_dir(struct FileList *filelist, const char *path)
{
- return filelist->checkdirf(filelist, (char *)path, false);
+ return filelist->checkdirf(filelist, (char *)path, false);
}
/**
@@ -1418,40 +1477,40 @@ bool filelist_is_dir(struct FileList *filelist, const char *path)
*/
void filelist_setdir(struct FileList *filelist, char *r_dir)
{
- BLI_assert(strlen(r_dir) < FILE_MAX_LIBEXTRA);
+ BLI_assert(strlen(r_dir) < FILE_MAX_LIBEXTRA);
- BLI_cleanup_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);
+ BLI_cleanup_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);
- if (!STREQ(filelist->filelist.root, r_dir)) {
- BLI_strncpy(filelist->filelist.root, r_dir, sizeof(filelist->filelist.root));
- filelist->flags |= FL_FORCE_RESET;
- }
+ if (!STREQ(filelist->filelist.root, r_dir)) {
+ BLI_strncpy(filelist->filelist.root, r_dir, sizeof(filelist->filelist.root));
+ filelist->flags |= FL_FORCE_RESET;
+ }
}
void filelist_setrecursion(struct FileList *filelist, const int recursion_level)
{
- if (filelist->max_recursion != recursion_level) {
- filelist->max_recursion = recursion_level;
- filelist->flags |= FL_FORCE_RESET;
- }
+ if (filelist->max_recursion != recursion_level) {
+ filelist->max_recursion = recursion_level;
+ filelist->flags |= FL_FORCE_RESET;
+ }
}
bool filelist_force_reset(struct FileList *filelist)
{
- return (filelist->flags & FL_FORCE_RESET) != 0;
+ return (filelist->flags & FL_FORCE_RESET) != 0;
}
bool filelist_is_ready(struct FileList *filelist)
{
- return (filelist->flags & FL_IS_READY) != 0;
+ return (filelist->flags & FL_IS_READY) != 0;
}
bool filelist_pending(struct FileList *filelist)
{
- return (filelist->flags & FL_IS_PENDING) != 0;
+ return (filelist->flags & FL_IS_PENDING) != 0;
}
/**
@@ -1460,740 +1519,759 @@ bool filelist_pending(struct FileList *filelist)
*/
int filelist_files_ensure(FileList *filelist)
{
- if (!filelist_force_reset(filelist) || !filelist_empty(filelist)) {
- filelist_sort(filelist);
- filelist_filter(filelist);
- }
+ if (!filelist_force_reset(filelist) || !filelist_empty(filelist)) {
+ filelist_sort(filelist);
+ filelist_filter(filelist);
+ }
- return filelist->filelist.nbr_entries_filtered;
+ return filelist->filelist.nbr_entries_filtered;
}
static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int index)
{
- FileListInternEntry *entry = filelist->filelist_intern.filtered[index];
- FileListEntryCache *cache = &filelist->filelist_cache;
- FileDirEntry *ret;
- FileDirEntryRevision *rev;
+ FileListInternEntry *entry = filelist->filelist_intern.filtered[index];
+ FileListEntryCache *cache = &filelist->filelist_cache;
+ FileDirEntry *ret;
+ FileDirEntryRevision *rev;
- ret = MEM_callocN(sizeof(*ret), __func__);
- rev = MEM_callocN(sizeof(*rev), __func__);
+ ret = MEM_callocN(sizeof(*ret), __func__);
+ rev = MEM_callocN(sizeof(*rev), __func__);
- rev->size = (uint64_t)entry->st.st_size;
+ rev->size = (uint64_t)entry->st.st_size;
- rev->time = (int64_t)entry->st.st_mtime;
+ rev->time = (int64_t)entry->st.st_mtime;
- ret->entry = rev;
- ret->relpath = BLI_strdup(entry->relpath);
- ret->name = BLI_strdup(entry->name);
- ret->description = BLI_strdupcat(filelist->filelist.root, entry->relpath);
- memcpy(ret->uuid, entry->uuid, sizeof(ret->uuid));
- ret->blentype = entry->blentype;
- ret->typeflag = entry->typeflag;
+ ret->entry = rev;
+ ret->relpath = BLI_strdup(entry->relpath);
+ ret->name = BLI_strdup(entry->name);
+ ret->description = BLI_strdupcat(filelist->filelist.root, entry->relpath);
+ memcpy(ret->uuid, entry->uuid, sizeof(ret->uuid));
+ ret->blentype = entry->blentype;
+ ret->typeflag = entry->typeflag;
- BLI_addtail(&cache->cached_entries, ret);
- return ret;
+ BLI_addtail(&cache->cached_entries, ret);
+ return ret;
}
static void filelist_file_release_entry(FileList *filelist, FileDirEntry *entry)
{
- BLI_remlink(&filelist->filelist_cache.cached_entries, entry);
- filelist_entry_free(entry);
+ BLI_remlink(&filelist->filelist_cache.cached_entries, entry);
+ filelist_entry_free(entry);
}
-static FileDirEntry *filelist_file_ex(struct FileList *filelist, const int index, const bool use_request)
+static FileDirEntry *filelist_file_ex(struct FileList *filelist,
+ const int index,
+ const bool use_request)
{
- FileDirEntry *ret = NULL, *old;
- FileListEntryCache *cache = &filelist->filelist_cache;
- const size_t cache_size = cache->size;
- int old_index;
+ FileDirEntry *ret = NULL, *old;
+ FileListEntryCache *cache = &filelist->filelist_cache;
+ const size_t cache_size = cache->size;
+ int old_index;
- if ((index < 0) || (index >= filelist->filelist.nbr_entries_filtered)) {
- return ret;
- }
+ if ((index < 0) || (index >= filelist->filelist.nbr_entries_filtered)) {
+ return ret;
+ }
- if (index >= cache->block_start_index && index < cache->block_end_index) {
- const int idx = (index - cache->block_start_index + cache->block_cursor) % cache_size;
- return cache->block_entries[idx];
- }
+ if (index >= cache->block_start_index && index < cache->block_end_index) {
+ const int idx = (index - cache->block_start_index + cache->block_cursor) % cache_size;
+ return cache->block_entries[idx];
+ }
- if ((ret = BLI_ghash_lookup(cache->misc_entries, POINTER_FROM_INT(index)))) {
- return ret;
- }
+ if ((ret = BLI_ghash_lookup(cache->misc_entries, POINTER_FROM_INT(index)))) {
+ return ret;
+ }
- if (!use_request) {
- return NULL;
- }
+ if (!use_request) {
+ return NULL;
+ }
-// printf("requesting file %d (not yet cached)\n", index);
+ // printf("requesting file %d (not yet cached)\n", index);
- /* Else, we have to add new entry to 'misc' cache - and possibly make room for it first! */
- ret = filelist_file_create_entry(filelist, index);
- old_index = cache->misc_entries_indices[cache->misc_cursor];
- if ((old = BLI_ghash_popkey(cache->misc_entries, POINTER_FROM_INT(old_index), NULL))) {
- BLI_ghash_remove(cache->uuids, old->uuid, NULL, NULL);
- filelist_file_release_entry(filelist, old);
- }
- BLI_ghash_insert(cache->misc_entries, POINTER_FROM_INT(index), ret);
- BLI_ghash_insert(cache->uuids, ret->uuid, ret);
+ /* Else, we have to add new entry to 'misc' cache - and possibly make room for it first! */
+ ret = filelist_file_create_entry(filelist, index);
+ old_index = cache->misc_entries_indices[cache->misc_cursor];
+ if ((old = BLI_ghash_popkey(cache->misc_entries, POINTER_FROM_INT(old_index), NULL))) {
+ BLI_ghash_remove(cache->uuids, old->uuid, NULL, NULL);
+ filelist_file_release_entry(filelist, old);
+ }
+ BLI_ghash_insert(cache->misc_entries, POINTER_FROM_INT(index), ret);
+ BLI_ghash_insert(cache->uuids, ret->uuid, ret);
- cache->misc_entries_indices[cache->misc_cursor] = index;
- cache->misc_cursor = (cache->misc_cursor + 1) % cache_size;
+ cache->misc_entries_indices[cache->misc_cursor] = index;
+ cache->misc_cursor = (cache->misc_cursor + 1) % cache_size;
-#if 0 /* Actually no, only block cached entries should have preview imho. */
- if (cache->previews_pool) {
- filelist_cache_previews_push(filelist, ret, index);
- }
+#if 0 /* Actually no, only block cached entries should have preview imho. */
+ if (cache->previews_pool) {
+ filelist_cache_previews_push(filelist, ret, index);
+ }
#endif
- return ret;
+ return ret;
}
FileDirEntry *filelist_file(struct FileList *filelist, int index)
{
- return filelist_file_ex(filelist, index, true);
+ return filelist_file_ex(filelist, index, true);
}
int filelist_file_findpath(struct FileList *filelist, const char *filename)
{
- int fidx = -1;
+ int fidx = -1;
- if (filelist->filelist.nbr_entries_filtered < 0) {
- return fidx;
- }
+ if (filelist->filelist.nbr_entries_filtered < 0) {
+ return fidx;
+ }
- /* XXX TODO Cache could probably use a ghash on paths too? Not really urgent though.
- * This is only used to find again renamed entry,
- * annoying but looks hairy to get rid of it currently. */
+ /* XXX TODO Cache could probably use a ghash on paths too? Not really urgent though.
+ * This is only used to find again renamed entry,
+ * annoying but looks hairy to get rid of it currently. */
- for (fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) {
- FileListInternEntry *entry = filelist->filelist_intern.filtered[fidx];
- if (STREQ(entry->relpath, filename)) {
- return fidx;
- }
- }
+ for (fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) {
+ FileListInternEntry *entry = filelist->filelist_intern.filtered[fidx];
+ if (STREQ(entry->relpath, filename)) {
+ return fidx;
+ }
+ }
- return -1;
+ return -1;
}
FileDirEntry *filelist_entry_find_uuid(struct FileList *filelist, const int uuid[4])
{
- if (filelist->filelist.nbr_entries_filtered < 0) {
- return NULL;
- }
+ if (filelist->filelist.nbr_entries_filtered < 0) {
+ return NULL;
+ }
- if (filelist->filelist_cache.uuids) {
- FileDirEntry *entry = BLI_ghash_lookup(filelist->filelist_cache.uuids, uuid);
- if (entry) {
- return entry;
- }
- }
+ if (filelist->filelist_cache.uuids) {
+ FileDirEntry *entry = BLI_ghash_lookup(filelist->filelist_cache.uuids, uuid);
+ if (entry) {
+ return entry;
+ }
+ }
- {
- int fidx;
+ {
+ int fidx;
- for (fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) {
- FileListInternEntry *entry = filelist->filelist_intern.filtered[fidx];
- if (memcmp(entry->uuid, uuid, sizeof(entry->uuid)) == 0) {
- return filelist_file(filelist, fidx);
- }
- }
- }
+ for (fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) {
+ FileListInternEntry *entry = filelist->filelist_intern.filtered[fidx];
+ if (memcmp(entry->uuid, uuid, sizeof(entry->uuid)) == 0) {
+ return filelist_file(filelist, fidx);
+ }
+ }
+ }
- return NULL;
+ return NULL;
}
void filelist_file_cache_slidingwindow_set(FileList *filelist, size_t window_size)
{
- /* Always keep it power of 2, in [256, 8192] range for now,
- * cache being app. twice bigger than requested window. */
- size_t size = 256;
- window_size *= 2;
+ /* Always keep it power of 2, in [256, 8192] range for now,
+ * cache being app. twice bigger than requested window. */
+ size_t size = 256;
+ window_size *= 2;
- while (size < window_size && size < 8192) {
- size *= 2;
- }
+ while (size < window_size && size < 8192) {
+ size *= 2;
+ }
- if (size != filelist->filelist_cache.size) {
- filelist_cache_clear(&filelist->filelist_cache, size);
- }
+ if (size != filelist->filelist_cache.size) {
+ filelist_cache_clear(&filelist->filelist_cache, size);
+ }
}
/* Helpers, low-level, they assume cursor + size <= cache_size */
-static bool filelist_file_cache_block_create(FileList *filelist, const int start_index, const int size, int cursor)
+static bool filelist_file_cache_block_create(FileList *filelist,
+ const int start_index,
+ const int size,
+ int cursor)
{
- FileListEntryCache *cache = &filelist->filelist_cache;
+ FileListEntryCache *cache = &filelist->filelist_cache;
- {
- int i, idx;
+ {
+ int i, idx;
- for (i = 0, idx = start_index; i < size; i++, idx++, cursor++) {
- FileDirEntry *entry;
+ for (i = 0, idx = start_index; i < size; i++, idx++, cursor++) {
+ FileDirEntry *entry;
- /* That entry might have already been requested and stored in misc cache... */
- if ((entry = BLI_ghash_popkey(cache->misc_entries, POINTER_FROM_INT(idx), NULL)) == NULL) {
- entry = filelist_file_create_entry(filelist, idx);
- BLI_ghash_insert(cache->uuids, entry->uuid, entry);
- }
- cache->block_entries[cursor] = entry;
- }
- return true;
- }
+ /* That entry might have already been requested and stored in misc cache... */
+ if ((entry = BLI_ghash_popkey(cache->misc_entries, POINTER_FROM_INT(idx), NULL)) == NULL) {
+ entry = filelist_file_create_entry(filelist, idx);
+ BLI_ghash_insert(cache->uuids, entry->uuid, entry);
+ }
+ cache->block_entries[cursor] = entry;
+ }
+ return true;
+ }
- return false;
+ return false;
}
-static void filelist_file_cache_block_release(struct FileList *filelist, const int size, int cursor)
+static void filelist_file_cache_block_release(struct FileList *filelist,
+ const int size,
+ int cursor)
{
- FileListEntryCache *cache = &filelist->filelist_cache;
+ FileListEntryCache *cache = &filelist->filelist_cache;
- {
- int i;
+ {
+ int i;
- for (i = 0; i < size; i++, cursor++) {
- FileDirEntry *entry = cache->block_entries[cursor];
-// printf("%s: release cacheidx %d (%%p %%s)\n", __func__, cursor/*, cache->block_entries[cursor], cache->block_entries[cursor]->relpath*/);
- BLI_ghash_remove(cache->uuids, entry->uuid, NULL, NULL);
- filelist_file_release_entry(filelist, entry);
+ for (i = 0; i < size; i++, cursor++) {
+ FileDirEntry *entry = cache->block_entries[cursor];
+ // printf("%s: release cacheidx %d (%%p %%s)\n", __func__, cursor/*, cache->block_entries[cursor], cache->block_entries[cursor]->relpath*/);
+ BLI_ghash_remove(cache->uuids, entry->uuid, NULL, NULL);
+ filelist_file_release_entry(filelist, entry);
#ifndef NDEBUG
- cache->block_entries[cursor] = NULL;
+ cache->block_entries[cursor] = NULL;
#endif
- }
- }
+ }
+ }
}
/* Load in cache all entries "around" given index (as much as block cache may hold). */
bool filelist_file_cache_block(struct FileList *filelist, const int index)
{
- FileListEntryCache *cache = &filelist->filelist_cache;
- const size_t cache_size = cache->size;
-
- const int nbr_entries = filelist->filelist.nbr_entries_filtered;
- int start_index = max_ii(0, index - (cache_size / 2));
- int end_index = min_ii(nbr_entries, index + (cache_size / 2));
- int i;
- const bool full_refresh = (filelist->flags & FL_IS_READY) == 0;
-
- if ((index < 0) || (index >= nbr_entries)) {
-// printf("Wrong index %d ([%d:%d])", index, 0, nbr_entries);
- return false;
- }
-
- /* Maximize cached range! */
- if ((end_index - start_index) < cache_size) {
- if (start_index == 0) {
- end_index = min_ii(nbr_entries, start_index + cache_size);
- }
- else if (end_index == nbr_entries) {
- start_index = max_ii(0, end_index - cache_size);
- }
- }
-
- BLI_assert((end_index - start_index) <= cache_size) ;
-
-// printf("%s: [%d:%d] around index %d (current cache: [%d:%d])\n", __func__,
-// start_index, end_index, index, cache->block_start_index, cache->block_end_index);
-
- /* If we have something to (re)cache... */
- if (full_refresh || (start_index != cache->block_start_index) || (end_index != cache->block_end_index)) {
- if (full_refresh || (start_index >= cache->block_end_index) || (end_index <= cache->block_start_index)) {
- int size1 = cache->block_end_index - cache->block_start_index;
- int size2 = 0;
- int idx1 = cache->block_cursor, idx2 = 0;
-
-// printf("Full Recaching!\n");
-
- if (cache->flags & FLC_PREVIEWS_ACTIVE) {
- filelist_cache_previews_clear(cache);
- }
-
- if (idx1 + size1 > cache_size) {
- size2 = idx1 + size1 - cache_size;
- size1 -= size2;
- filelist_file_cache_block_release(filelist, size2, idx2);
- }
- filelist_file_cache_block_release(filelist, size1, idx1);
-
- cache->block_start_index = cache->block_end_index = cache->block_cursor = 0;
-
- /* New cached block does not overlap existing one, simple. */
- if (!filelist_file_cache_block_create(filelist, start_index, end_index - start_index, 0)) {
- return false;
- }
-
- cache->block_start_index = start_index;
- cache->block_end_index = end_index;
- }
- else {
-// printf("Partial Recaching!\n");
-
- /* At this point, we know we keep part of currently cached entries, so update previews
- * if needed, and remove everything from working queue - we'll add all newly needed
- * entries at the end. */
- if (cache->flags & FLC_PREVIEWS_ACTIVE) {
- filelist_cache_previews_update(filelist);
- filelist_cache_previews_clear(cache);
- }
-
-// printf("\tpreview cleaned up...\n");
-
- if (start_index > cache->block_start_index) {
- int size1 = start_index - cache->block_start_index;
- int size2 = 0;
- int idx1 = cache->block_cursor, idx2 = 0;
-
-// printf("\tcache releasing: [%d:%d] (%d, %d)\n",
-// cache->block_start_index, cache->block_start_index + size1,
-// cache->block_cursor, size1);
-
- if (idx1 + size1 > cache_size) {
- size2 = idx1 + size1 - cache_size;
- size1 -= size2;
- filelist_file_cache_block_release(filelist, size2, idx2);
- }
- filelist_file_cache_block_release(filelist, size1, idx1);
-
- cache->block_cursor = (idx1 + size1 + size2) % cache_size;
- cache->block_start_index = start_index;
- }
- if (end_index < cache->block_end_index) {
- int size1 = cache->block_end_index - end_index;
- int size2 = 0;
- int idx1, idx2 = 0;
-
-// printf("\tcache releasing: [%d:%d] (%d)\n",
-// cache->block_end_index - size1, cache->block_end_index, cache->block_cursor);
-
- idx1 = (cache->block_cursor + end_index - cache->block_start_index) % cache_size;
- if (idx1 + size1 > cache_size) {
- size2 = idx1 + size1 - cache_size;
- size1 -= size2;
- filelist_file_cache_block_release(filelist, size2, idx2);
- }
- filelist_file_cache_block_release(filelist, size1, idx1);
-
- cache->block_end_index = end_index;
- }
-
-// printf("\tcache cleaned up...\n");
-
- if (start_index < cache->block_start_index) {
- /* Add (request) needed entries before already cached ones. */
- /* Note: We need some index black magic to wrap around (cycle)
- * inside our cache_size array... */
- int size1 = cache->block_start_index - start_index;
- int size2 = 0;
- int idx1, idx2;
-
- if (size1 > cache->block_cursor) {
- size2 = size1;
- size1 -= cache->block_cursor;
- size2 -= size1;
- idx2 = 0;
- idx1 = cache_size - size1;
- }
- else {
- idx1 = cache->block_cursor - size1;
- }
-
- if (size2) {
- if (!filelist_file_cache_block_create(filelist, start_index + size1, size2, idx2)) {
- return false;
- }
- }
- if (!filelist_file_cache_block_create(filelist, start_index, size1, idx1)) {
- return false;
- }
-
- cache->block_cursor = idx1;
- cache->block_start_index = start_index;
- }
-// printf("\tstart-extended...\n");
- if (end_index > cache->block_end_index) {
- /* Add (request) needed entries after already cached ones. */
- /* Note: We need some index black magic to wrap around (cycle)
- * inside our cache_size array... */
- int size1 = end_index - cache->block_end_index;
- int size2 = 0;
- int idx1, idx2;
-
- idx1 = (cache->block_cursor + end_index - cache->block_start_index - size1) % cache_size;
- if ((idx1 + size1) > cache_size) {
- size2 = size1;
- size1 = cache_size - idx1;
- size2 -= size1;
- idx2 = 0;
- }
-
- if (size2) {
- if (!filelist_file_cache_block_create(filelist, end_index - size2, size2, idx2)) {
- return false;
- }
- }
- if (!filelist_file_cache_block_create(filelist, end_index - size1 - size2, size1, idx1)) {
- return false;
- }
-
- cache->block_end_index = end_index;
- }
-
-// printf("\tend-extended...\n");
- }
- }
- else if ((cache->block_center_index != index) && (cache->flags & FLC_PREVIEWS_ACTIVE)) {
- /* We try to always preview visible entries first, so 'restart' preview background task. */
- filelist_cache_previews_update(filelist);
- filelist_cache_previews_clear(cache);
- }
-
-// printf("Re-queueing previews...\n");
-
- /* Note we try to preview first images around given index - i.e. assumed visible ones. */
- if (cache->flags & FLC_PREVIEWS_ACTIVE) {
- for (i = 0; ((index + i) < end_index) || ((index - i) >= start_index); i++) {
- if ((index - i) >= start_index) {
- const int idx = (cache->block_cursor + (index - start_index) - i) % cache_size;
- filelist_cache_previews_push(filelist, cache->block_entries[idx], index - i);
- }
- if ((index + i) < end_index) {
- const int idx = (cache->block_cursor + (index - start_index) + i) % cache_size;
- filelist_cache_previews_push(filelist, cache->block_entries[idx], index + i);
- }
- }
- }
-
- cache->block_center_index = index;
-
-// printf("%s Finished!\n", __func__);
-
- return true;
+ FileListEntryCache *cache = &filelist->filelist_cache;
+ const size_t cache_size = cache->size;
+
+ const int nbr_entries = filelist->filelist.nbr_entries_filtered;
+ int start_index = max_ii(0, index - (cache_size / 2));
+ int end_index = min_ii(nbr_entries, index + (cache_size / 2));
+ int i;
+ const bool full_refresh = (filelist->flags & FL_IS_READY) == 0;
+
+ if ((index < 0) || (index >= nbr_entries)) {
+ // printf("Wrong index %d ([%d:%d])", index, 0, nbr_entries);
+ return false;
+ }
+
+ /* Maximize cached range! */
+ if ((end_index - start_index) < cache_size) {
+ if (start_index == 0) {
+ end_index = min_ii(nbr_entries, start_index + cache_size);
+ }
+ else if (end_index == nbr_entries) {
+ start_index = max_ii(0, end_index - cache_size);
+ }
+ }
+
+ BLI_assert((end_index - start_index) <= cache_size);
+
+ // printf("%s: [%d:%d] around index %d (current cache: [%d:%d])\n", __func__,
+ // start_index, end_index, index, cache->block_start_index, cache->block_end_index);
+
+ /* If we have something to (re)cache... */
+ if (full_refresh || (start_index != cache->block_start_index) ||
+ (end_index != cache->block_end_index)) {
+ if (full_refresh || (start_index >= cache->block_end_index) ||
+ (end_index <= cache->block_start_index)) {
+ int size1 = cache->block_end_index - cache->block_start_index;
+ int size2 = 0;
+ int idx1 = cache->block_cursor, idx2 = 0;
+
+ // printf("Full Recaching!\n");
+
+ if (cache->flags & FLC_PREVIEWS_ACTIVE) {
+ filelist_cache_previews_clear(cache);
+ }
+
+ if (idx1 + size1 > cache_size) {
+ size2 = idx1 + size1 - cache_size;
+ size1 -= size2;
+ filelist_file_cache_block_release(filelist, size2, idx2);
+ }
+ filelist_file_cache_block_release(filelist, size1, idx1);
+
+ cache->block_start_index = cache->block_end_index = cache->block_cursor = 0;
+
+ /* New cached block does not overlap existing one, simple. */
+ if (!filelist_file_cache_block_create(filelist, start_index, end_index - start_index, 0)) {
+ return false;
+ }
+
+ cache->block_start_index = start_index;
+ cache->block_end_index = end_index;
+ }
+ else {
+ // printf("Partial Recaching!\n");
+
+ /* At this point, we know we keep part of currently cached entries, so update previews
+ * if needed, and remove everything from working queue - we'll add all newly needed
+ * entries at the end. */
+ if (cache->flags & FLC_PREVIEWS_ACTIVE) {
+ filelist_cache_previews_update(filelist);
+ filelist_cache_previews_clear(cache);
+ }
+
+ // printf("\tpreview cleaned up...\n");
+
+ if (start_index > cache->block_start_index) {
+ int size1 = start_index - cache->block_start_index;
+ int size2 = 0;
+ int idx1 = cache->block_cursor, idx2 = 0;
+
+ // printf("\tcache releasing: [%d:%d] (%d, %d)\n",
+ // cache->block_start_index, cache->block_start_index + size1,
+ // cache->block_cursor, size1);
+
+ if (idx1 + size1 > cache_size) {
+ size2 = idx1 + size1 - cache_size;
+ size1 -= size2;
+ filelist_file_cache_block_release(filelist, size2, idx2);
+ }
+ filelist_file_cache_block_release(filelist, size1, idx1);
+
+ cache->block_cursor = (idx1 + size1 + size2) % cache_size;
+ cache->block_start_index = start_index;
+ }
+ if (end_index < cache->block_end_index) {
+ int size1 = cache->block_end_index - end_index;
+ int size2 = 0;
+ int idx1, idx2 = 0;
+
+ // printf("\tcache releasing: [%d:%d] (%d)\n",
+ // cache->block_end_index - size1, cache->block_end_index, cache->block_cursor);
+
+ idx1 = (cache->block_cursor + end_index - cache->block_start_index) % cache_size;
+ if (idx1 + size1 > cache_size) {
+ size2 = idx1 + size1 - cache_size;
+ size1 -= size2;
+ filelist_file_cache_block_release(filelist, size2, idx2);
+ }
+ filelist_file_cache_block_release(filelist, size1, idx1);
+
+ cache->block_end_index = end_index;
+ }
+
+ // printf("\tcache cleaned up...\n");
+
+ if (start_index < cache->block_start_index) {
+ /* Add (request) needed entries before already cached ones. */
+ /* Note: We need some index black magic to wrap around (cycle)
+ * inside our cache_size array... */
+ int size1 = cache->block_start_index - start_index;
+ int size2 = 0;
+ int idx1, idx2;
+
+ if (size1 > cache->block_cursor) {
+ size2 = size1;
+ size1 -= cache->block_cursor;
+ size2 -= size1;
+ idx2 = 0;
+ idx1 = cache_size - size1;
+ }
+ else {
+ idx1 = cache->block_cursor - size1;
+ }
+
+ if (size2) {
+ if (!filelist_file_cache_block_create(filelist, start_index + size1, size2, idx2)) {
+ return false;
+ }
+ }
+ if (!filelist_file_cache_block_create(filelist, start_index, size1, idx1)) {
+ return false;
+ }
+
+ cache->block_cursor = idx1;
+ cache->block_start_index = start_index;
+ }
+ // printf("\tstart-extended...\n");
+ if (end_index > cache->block_end_index) {
+ /* Add (request) needed entries after already cached ones. */
+ /* Note: We need some index black magic to wrap around (cycle)
+ * inside our cache_size array... */
+ int size1 = end_index - cache->block_end_index;
+ int size2 = 0;
+ int idx1, idx2;
+
+ idx1 = (cache->block_cursor + end_index - cache->block_start_index - size1) % cache_size;
+ if ((idx1 + size1) > cache_size) {
+ size2 = size1;
+ size1 = cache_size - idx1;
+ size2 -= size1;
+ idx2 = 0;
+ }
+
+ if (size2) {
+ if (!filelist_file_cache_block_create(filelist, end_index - size2, size2, idx2)) {
+ return false;
+ }
+ }
+ if (!filelist_file_cache_block_create(filelist, end_index - size1 - size2, size1, idx1)) {
+ return false;
+ }
+
+ cache->block_end_index = end_index;
+ }
+
+ // printf("\tend-extended...\n");
+ }
+ }
+ else if ((cache->block_center_index != index) && (cache->flags & FLC_PREVIEWS_ACTIVE)) {
+ /* We try to always preview visible entries first, so 'restart' preview background task. */
+ filelist_cache_previews_update(filelist);
+ filelist_cache_previews_clear(cache);
+ }
+
+ // printf("Re-queueing previews...\n");
+
+ /* Note we try to preview first images around given index - i.e. assumed visible ones. */
+ if (cache->flags & FLC_PREVIEWS_ACTIVE) {
+ for (i = 0; ((index + i) < end_index) || ((index - i) >= start_index); i++) {
+ if ((index - i) >= start_index) {
+ const int idx = (cache->block_cursor + (index - start_index) - i) % cache_size;
+ filelist_cache_previews_push(filelist, cache->block_entries[idx], index - i);
+ }
+ if ((index + i) < end_index) {
+ const int idx = (cache->block_cursor + (index - start_index) + i) % cache_size;
+ filelist_cache_previews_push(filelist, cache->block_entries[idx], index + i);
+ }
+ }
+ }
+
+ cache->block_center_index = index;
+
+ // printf("%s Finished!\n", __func__);
+
+ return true;
}
void filelist_cache_previews_set(FileList *filelist, const bool use_previews)
{
- FileListEntryCache *cache = &filelist->filelist_cache;
+ FileListEntryCache *cache = &filelist->filelist_cache;
- if (use_previews == ((cache->flags & FLC_PREVIEWS_ACTIVE) != 0)) {
- return;
- }
- /* Do not start preview work while listing, gives nasty flickering! */
- else if (use_previews && (filelist->flags & FL_IS_READY)) {
- cache->flags |= FLC_PREVIEWS_ACTIVE;
+ if (use_previews == ((cache->flags & FLC_PREVIEWS_ACTIVE) != 0)) {
+ return;
+ }
+ /* Do not start preview work while listing, gives nasty flickering! */
+ else if (use_previews && (filelist->flags & FL_IS_READY)) {
+ cache->flags |= FLC_PREVIEWS_ACTIVE;
- BLI_assert((cache->previews_pool == NULL) && (cache->previews_done == NULL));
+ BLI_assert((cache->previews_pool == NULL) && (cache->previews_done == NULL));
-// printf("%s: Init Previews...\n", __func__);
+ // printf("%s: Init Previews...\n", __func__);
- /* No need to populate preview queue here, filelist_file_cache_block() handles this. */
- }
- else {
-// printf("%s: Clear Previews...\n", __func__);
+ /* No need to populate preview queue here, filelist_file_cache_block() handles this. */
+ }
+ else {
+ // printf("%s: Clear Previews...\n", __func__);
- filelist_cache_previews_free(cache);
- }
+ filelist_cache_previews_free(cache);
+ }
}
bool filelist_cache_previews_update(FileList *filelist)
{
- FileListEntryCache *cache = &filelist->filelist_cache;
- TaskPool *pool = cache->previews_pool;
- bool changed = false;
-
- if (!pool) {
- return changed;
- }
-
-// printf("%s: Update Previews...\n", __func__);
-
- while (!BLI_thread_queue_is_empty(cache->previews_done)) {
- FileListEntryPreview *preview = BLI_thread_queue_pop(cache->previews_done);
- FileDirEntry *entry;
-
- /* Paranoid (should never happen currently
- * since we consume this queue from a single thread), but... */
- if (!preview) {
- continue;
- }
- /* entry might have been removed from cache in the mean time,
- * we do not want to cache it again here. */
- entry = filelist_file_ex(filelist, preview->index, false);
-
-// printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
-
- if (preview->img) {
- /* Due to asynchronous process, a preview for a given image may be generated several times, i.e.
- * entry->image may already be set at this point. */
- if (entry && !entry->image) {
- entry->image = preview->img;
- changed = true;
- }
- else {
- IMB_freeImBuf(preview->img);
- }
- }
- else if (entry) {
- /* We want to avoid re-processing this entry continuously!
- * Note that, since entries only live in cache,
- * preview will be retried quite often anyway. */
- entry->flags |= FILE_ENTRY_INVALID_PREVIEW;
- }
-
- MEM_freeN(preview);
- }
-
- return changed;
+ FileListEntryCache *cache = &filelist->filelist_cache;
+ TaskPool *pool = cache->previews_pool;
+ bool changed = false;
+
+ if (!pool) {
+ return changed;
+ }
+
+ // printf("%s: Update Previews...\n", __func__);
+
+ while (!BLI_thread_queue_is_empty(cache->previews_done)) {
+ FileListEntryPreview *preview = BLI_thread_queue_pop(cache->previews_done);
+ FileDirEntry *entry;
+
+ /* Paranoid (should never happen currently
+ * since we consume this queue from a single thread), but... */
+ if (!preview) {
+ continue;
+ }
+ /* entry might have been removed from cache in the mean time,
+ * we do not want to cache it again here. */
+ entry = filelist_file_ex(filelist, preview->index, false);
+
+ // printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
+
+ if (preview->img) {
+ /* Due to asynchronous process, a preview for a given image may be generated several times, i.e.
+ * entry->image may already be set at this point. */
+ if (entry && !entry->image) {
+ entry->image = preview->img;
+ changed = true;
+ }
+ else {
+ IMB_freeImBuf(preview->img);
+ }
+ }
+ else if (entry) {
+ /* We want to avoid re-processing this entry continuously!
+ * Note that, since entries only live in cache,
+ * preview will be retried quite often anyway. */
+ entry->flags |= FILE_ENTRY_INVALID_PREVIEW;
+ }
+
+ MEM_freeN(preview);
+ }
+
+ return changed;
}
bool filelist_cache_previews_running(FileList *filelist)
{
- FileListEntryCache *cache = &filelist->filelist_cache;
+ FileListEntryCache *cache = &filelist->filelist_cache;
- return (cache->previews_pool != NULL);
+ return (cache->previews_pool != NULL);
}
/* would recognize .blend as well */
static bool file_is_blend_backup(const char *str)
{
- const size_t a = strlen(str);
- size_t b = 7;
- bool retval = 0;
+ const size_t a = strlen(str);
+ size_t b = 7;
+ bool retval = 0;
- if (a == 0 || b >= a) {
- /* pass */
- }
- else {
- const char *loc;
+ if (a == 0 || b >= a) {
+ /* pass */
+ }
+ else {
+ const char *loc;
- if (a > b + 1)
- b++;
+ if (a > b + 1)
+ b++;
- /* allow .blend1 .blend2 .blend32 */
- loc = BLI_strcasestr(str + a - b, ".blend");
+ /* allow .blend1 .blend2 .blend32 */
+ loc = BLI_strcasestr(str + a - b, ".blend");
- if (loc)
- retval = 1;
- }
+ if (loc)
+ retval = 1;
+ }
- return (retval);
+ return (retval);
}
/* TODO: Maybe we should move this to BLI?
* On the other hand, it's using defines from spacefile area, so not sure... */
int ED_path_extension_type(const char *path)
{
- if (BLO_has_bfile_extension(path)) {
- return FILE_TYPE_BLENDER;
- }
- else if (file_is_blend_backup(path)) {
- return FILE_TYPE_BLENDER_BACKUP;
- }
- else if (BLI_path_extension_check(path, ".app")) {
- return FILE_TYPE_APPLICATIONBUNDLE;
- }
- 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)) {
- return FILE_TYPE_TEXT;
- }
- else if (BLI_path_extension_check_n(path, ".ttf", ".ttc", ".pfb", ".otf", ".otc", NULL)) {
- return FILE_TYPE_FTFONT;
- }
- else if (BLI_path_extension_check(path, ".btx")) {
- return FILE_TYPE_BTX;
- }
- else if (BLI_path_extension_check(path, ".dae")) {
- return FILE_TYPE_COLLADA;
- }
- else if (BLI_path_extension_check(path, ".abc")) {
- return FILE_TYPE_ALEMBIC;
- }
- else if (BLI_path_extension_check_array(path, imb_ext_image)) {
- return FILE_TYPE_IMAGE;
- }
- else if (BLI_path_extension_check(path, ".ogg")) {
- if (IMB_isanim(path)) {
- return FILE_TYPE_MOVIE;
- }
- else {
- return FILE_TYPE_SOUND;
- }
- }
- else if (BLI_path_extension_check_array(path, imb_ext_movie)) {
- return FILE_TYPE_MOVIE;
- }
- else if (BLI_path_extension_check_array(path, imb_ext_audio)) {
- return FILE_TYPE_SOUND;
- }
- return 0;
+ if (BLO_has_bfile_extension(path)) {
+ return FILE_TYPE_BLENDER;
+ }
+ else if (file_is_blend_backup(path)) {
+ return FILE_TYPE_BLENDER_BACKUP;
+ }
+ else if (BLI_path_extension_check(path, ".app")) {
+ return FILE_TYPE_APPLICATIONBUNDLE;
+ }
+ 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)) {
+ return FILE_TYPE_TEXT;
+ }
+ else if (BLI_path_extension_check_n(path, ".ttf", ".ttc", ".pfb", ".otf", ".otc", NULL)) {
+ return FILE_TYPE_FTFONT;
+ }
+ else if (BLI_path_extension_check(path, ".btx")) {
+ return FILE_TYPE_BTX;
+ }
+ else if (BLI_path_extension_check(path, ".dae")) {
+ return FILE_TYPE_COLLADA;
+ }
+ else if (BLI_path_extension_check(path, ".abc")) {
+ return FILE_TYPE_ALEMBIC;
+ }
+ else if (BLI_path_extension_check_array(path, imb_ext_image)) {
+ return FILE_TYPE_IMAGE;
+ }
+ else if (BLI_path_extension_check(path, ".ogg")) {
+ if (IMB_isanim(path)) {
+ return FILE_TYPE_MOVIE;
+ }
+ else {
+ return FILE_TYPE_SOUND;
+ }
+ }
+ else if (BLI_path_extension_check_array(path, imb_ext_movie)) {
+ return FILE_TYPE_MOVIE;
+ }
+ else if (BLI_path_extension_check_array(path, imb_ext_audio)) {
+ return FILE_TYPE_SOUND;
+ }
+ return 0;
}
static int file_extension_type(const char *dir, const char *relpath)
{
- char path[FILE_MAX];
- BLI_join_dirfile(path, sizeof(path), dir, relpath);
- return ED_path_extension_type(path);
+ char path[FILE_MAX];
+ BLI_join_dirfile(path, sizeof(path), dir, relpath);
+ return ED_path_extension_type(path);
}
int ED_file_extension_icon(const char *path)
{
- const int type = ED_path_extension_type(path);
-
- switch (type) {
- case FILE_TYPE_BLENDER:
- return ICON_FILE_BLEND;
- case FILE_TYPE_BLENDER_BACKUP:
- return ICON_FILE_BACKUP;
- case FILE_TYPE_IMAGE:
- return ICON_FILE_IMAGE;
- case FILE_TYPE_MOVIE:
- return ICON_FILE_MOVIE;
- case FILE_TYPE_PYSCRIPT:
- return ICON_FILE_SCRIPT;
- case FILE_TYPE_SOUND:
- return ICON_FILE_SOUND;
- case FILE_TYPE_FTFONT:
- return ICON_FILE_FONT;
- case FILE_TYPE_BTX:
- return ICON_FILE_BLANK;
- case FILE_TYPE_COLLADA:
- return ICON_FILE_BLANK;
- case FILE_TYPE_ALEMBIC:
- return ICON_FILE_BLANK;
- case FILE_TYPE_TEXT:
- return ICON_FILE_TEXT;
- default:
- return ICON_FILE_BLANK;
- }
+ const int type = ED_path_extension_type(path);
+
+ switch (type) {
+ case FILE_TYPE_BLENDER:
+ return ICON_FILE_BLEND;
+ case FILE_TYPE_BLENDER_BACKUP:
+ return ICON_FILE_BACKUP;
+ case FILE_TYPE_IMAGE:
+ return ICON_FILE_IMAGE;
+ case FILE_TYPE_MOVIE:
+ return ICON_FILE_MOVIE;
+ case FILE_TYPE_PYSCRIPT:
+ return ICON_FILE_SCRIPT;
+ case FILE_TYPE_SOUND:
+ return ICON_FILE_SOUND;
+ case FILE_TYPE_FTFONT:
+ return ICON_FILE_FONT;
+ case FILE_TYPE_BTX:
+ return ICON_FILE_BLANK;
+ case FILE_TYPE_COLLADA:
+ return ICON_FILE_BLANK;
+ case FILE_TYPE_ALEMBIC:
+ return ICON_FILE_BLANK;
+ case FILE_TYPE_TEXT:
+ return ICON_FILE_TEXT;
+ default:
+ return ICON_FILE_BLANK;
+ }
}
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)
+ 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)
{
- /* 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;
+ /* 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;
- BLI_assert(entry);
- BLI_assert(ELEM(check, CHECK_DIRS, CHECK_FILES, CHECK_ALL));
+ BLI_assert(entry);
+ BLI_assert(ELEM(check, CHECK_DIRS, CHECK_FILES, CHECK_ALL));
- if (((check == CHECK_ALL)) ||
- ((check == CHECK_DIRS) && (entry->typeflag & FILE_TYPE_DIR)) ||
- ((check == CHECK_FILES) && !(entry->typeflag & FILE_TYPE_DIR)))
- {
- switch (select) {
- case FILE_SEL_REMOVE:
- entry_flag &= ~flag;
- break;
- case FILE_SEL_ADD:
- entry_flag |= flag;
- break;
- case FILE_SEL_TOGGLE:
- entry_flag ^= flag;
- break;
- }
- }
+ if (((check == CHECK_ALL)) || ((check == CHECK_DIRS) && (entry->typeflag & FILE_TYPE_DIR)) ||
+ ((check == CHECK_FILES) && !(entry->typeflag & FILE_TYPE_DIR))) {
+ switch (select) {
+ case FILE_SEL_REMOVE:
+ entry_flag &= ~flag;
+ break;
+ case FILE_SEL_ADD:
+ entry_flag |= flag;
+ break;
+ case FILE_SEL_TOGGLE:
+ entry_flag ^= flag;
+ break;
+ }
+ }
- if (entry_flag != org_entry_flag) {
- if (es_p) {
- if (entry_flag) {
- *es_p = POINTER_FROM_UINT(entry_flag);
- }
- else {
- BLI_ghash_remove(filelist->selection_state, entry->uuid, MEM_freeN, NULL);
- }
- }
- else if (entry_flag) {
- void *key = MEM_mallocN(sizeof(entry->uuid), __func__);
- memcpy(key, entry->uuid, sizeof(entry->uuid));
- BLI_ghash_insert(filelist->selection_state, key, POINTER_FROM_UINT(entry_flag));
- }
- }
+ if (entry_flag != org_entry_flag) {
+ if (es_p) {
+ if (entry_flag) {
+ *es_p = POINTER_FROM_UINT(entry_flag);
+ }
+ else {
+ BLI_ghash_remove(filelist->selection_state, entry->uuid, MEM_freeN, NULL);
+ }
+ }
+ else if (entry_flag) {
+ void *key = MEM_mallocN(sizeof(entry->uuid), __func__);
+ memcpy(key, entry->uuid, sizeof(entry->uuid));
+ BLI_ghash_insert(filelist->selection_state, key, POINTER_FROM_UINT(entry_flag));
+ }
+ }
- return entry_flag;
+ 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,
+ unsigned int flag,
+ FileCheckType check)
{
- FileDirEntry *entry = filelist_file(filelist, index);
+ FileDirEntry *entry = filelist_file(filelist, index);
- if (entry) {
- filelist_entry_select_set(filelist, entry, select, flag, check);
- }
+ if (entry) {
+ filelist_entry_select_set(filelist, entry, select, flag, check);
+ }
}
-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,
+ unsigned int flag,
+ FileCheckType check)
{
- /* select all valid files between first and last indicated */
- if ((sel->first >= 0) && (sel->first < filelist->filelist.nbr_entries_filtered) &&
- (sel->last >= 0) && (sel->last < filelist->filelist.nbr_entries_filtered))
- {
- int current_file;
- for (current_file = sel->first; current_file <= sel->last; current_file++) {
- filelist_entry_select_index_set(filelist, current_file, select, flag, check);
- }
- }
+ /* select all valid files between first and last indicated */
+ if ((sel->first >= 0) && (sel->first < filelist->filelist.nbr_entries_filtered) &&
+ (sel->last >= 0) && (sel->last < filelist->filelist.nbr_entries_filtered)) {
+ int current_file;
+ for (current_file = sel->first; current_file <= sel->last; current_file++) {
+ filelist_entry_select_index_set(filelist, current_file, select, flag, check);
+ }
+ }
}
-unsigned int filelist_entry_select_get(FileList *filelist, FileDirEntry *entry, FileCheckType check)
+unsigned int filelist_entry_select_get(FileList *filelist,
+ FileDirEntry *entry,
+ FileCheckType check)
{
- BLI_assert(entry);
- BLI_assert(ELEM(check, CHECK_DIRS, CHECK_FILES, CHECK_ALL));
+ BLI_assert(entry);
+ BLI_assert(ELEM(check, CHECK_DIRS, CHECK_FILES, CHECK_ALL));
- if (((check == CHECK_ALL)) ||
- ((check == CHECK_DIRS) && (entry->typeflag & FILE_TYPE_DIR)) ||
- ((check == CHECK_FILES) && !(entry->typeflag & FILE_TYPE_DIR)))
- {
- /* Default NULL pointer if not found is fine here! */
- return POINTER_AS_UINT(BLI_ghash_lookup(filelist->selection_state, entry->uuid));
- }
+ if (((check == CHECK_ALL)) || ((check == CHECK_DIRS) && (entry->typeflag & FILE_TYPE_DIR)) ||
+ ((check == CHECK_FILES) && !(entry->typeflag & FILE_TYPE_DIR))) {
+ /* Default NULL pointer if not found is fine here! */
+ return POINTER_AS_UINT(BLI_ghash_lookup(filelist->selection_state, entry->uuid));
+ }
- return 0;
+ return 0;
}
-unsigned int filelist_entry_select_index_get(FileList *filelist, const int index, FileCheckType check)
+unsigned int filelist_entry_select_index_get(FileList *filelist,
+ const int index,
+ FileCheckType check)
{
- FileDirEntry *entry = filelist_file(filelist, index);
-
- if (entry) {
- return filelist_entry_select_get(filelist, entry, check);
- }
-
- return 0;
+ FileDirEntry *entry = filelist_file(filelist, index);
+
+ if (entry) {
+ return filelist_entry_select_get(filelist, entry, check);
+ }
+
+ return 0;
}
/* WARNING! dir must be FILE_MAX_LIBEXTRA long! */
bool filelist_islibrary(struct FileList *filelist, char *dir, char **group)
{
- return BLO_library_path_explode(filelist->filelist.root, dir, group, NULL);
+ return BLO_library_path_explode(filelist->filelist.root, dir, group, NULL);
}
static int groupname_to_code(const char *group)
{
- char buf[BLO_GROUP_MAX];
- char *lslash;
+ char buf[BLO_GROUP_MAX];
+ char *lslash;
- BLI_assert(group);
+ BLI_assert(group);
- BLI_strncpy(buf, group, sizeof(buf));
- lslash = (char *)BLI_last_slash(buf);
- if (lslash)
- lslash[0] = '\0';
+ BLI_strncpy(buf, group, sizeof(buf));
+ lslash = (char *)BLI_last_slash(buf);
+ if (lslash)
+ lslash[0] = '\0';
- return buf[0] ? BKE_idcode_from_name(buf) : 0;
+ return buf[0] ? BKE_idcode_from_name(buf) : 0;
}
static unsigned int groupname_to_filter_id(const char *group)
{
- int id_code = groupname_to_code(group);
+ int id_code = groupname_to_code(group);
- return BKE_idcode_to_idfilter(id_code);
+ return BKE_idcode_to_idfilter(id_code);
}
/**
@@ -2201,127 +2279,130 @@ static unsigned int groupname_to_filter_id(const char *group)
* and main one (used by UI among other things).
*/
typedef struct TodoDir {
- int level;
- char *dir;
+ int level;
+ char *dir;
} TodoDir;
-static int filelist_readjob_list_dir(
- const char *root, ListBase *entries, const char *filter_glob,
- const bool do_lib, const char *main_name, const bool skip_currpar)
-{
- struct direntry *files;
- int nbr_files, nbr_entries = 0;
-
- nbr_files = BLI_filelist_dir_contents(root, &files);
- if (files) {
- int i = nbr_files;
- while (i--) {
- FileListInternEntry *entry;
-
- if (skip_currpar && FILENAME_IS_CURRPAR(files[i].relname)) {
- continue;
- }
-
- entry = MEM_callocN(sizeof(*entry), __func__);
- entry->relpath = MEM_dupallocN(files[i].relname);
- entry->st = files[i].s;
-
- /* 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) {
- entry->typeflag |= FILE_TYPE_DIR;
- }
- }
- /* Otherwise, do not check extensions for directories! */
- else if (!(entry->typeflag & FILE_TYPE_DIR)) {
- entry->typeflag = file_extension_type(root, entry->relpath);
- if (filter_glob[0] && BLI_path_extension_check_glob(entry->relpath, filter_glob)) {
- entry->typeflag |= FILE_TYPE_OPERATOR;
- }
- }
-
- BLI_addtail(entries, entry);
- nbr_entries++;
- }
- BLI_filelist_free(files, nbr_files);
- }
- return nbr_entries;
+static int filelist_readjob_list_dir(const char *root,
+ ListBase *entries,
+ const char *filter_glob,
+ const bool do_lib,
+ const char *main_name,
+ const bool skip_currpar)
+{
+ struct direntry *files;
+ int nbr_files, nbr_entries = 0;
+
+ nbr_files = BLI_filelist_dir_contents(root, &files);
+ if (files) {
+ int i = nbr_files;
+ while (i--) {
+ FileListInternEntry *entry;
+
+ if (skip_currpar && FILENAME_IS_CURRPAR(files[i].relname)) {
+ continue;
+ }
+
+ entry = MEM_callocN(sizeof(*entry), __func__);
+ entry->relpath = MEM_dupallocN(files[i].relname);
+ entry->st = files[i].s;
+
+ /* 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) {
+ entry->typeflag |= FILE_TYPE_DIR;
+ }
+ }
+ /* Otherwise, do not check extensions for directories! */
+ else if (!(entry->typeflag & FILE_TYPE_DIR)) {
+ entry->typeflag = file_extension_type(root, entry->relpath);
+ if (filter_glob[0] && BLI_path_extension_check_glob(entry->relpath, filter_glob)) {
+ entry->typeflag |= FILE_TYPE_OPERATOR;
+ }
+ }
+
+ BLI_addtail(entries, entry);
+ nbr_entries++;
+ }
+ BLI_filelist_free(files, nbr_files);
+ }
+ return nbr_entries;
}
static int filelist_readjob_list_lib(const char *root, ListBase *entries, const bool skip_currpar)
{
- FileListInternEntry *entry;
- LinkNode *ln, *names;
- int i, nnames, idcode = 0, nbr_entries = 0;
- char dir[FILE_MAX_LIBEXTRA], *group;
- bool ok;
-
- struct BlendHandle *libfiledata = NULL;
-
- /* name test */
- ok = BLO_library_path_explode(root, dir, &group, NULL);
- if (!ok) {
- return nbr_entries;
- }
-
- /* there we go */
- libfiledata = BLO_blendhandle_from_file(dir, NULL);
- if (libfiledata == NULL) {
- return nbr_entries;
- }
-
- /* memory for strings is passed into filelist[i].entry->relpath
- * and freed in filelist_entry_free. */
- if (group) {
- idcode = groupname_to_code(group);
- names = BLO_blendhandle_get_datablock_names(libfiledata, idcode, &nnames);
- }
- else {
- names = BLO_blendhandle_get_linkable_groups(libfiledata);
- nnames = BLI_linklist_count(names);
- }
-
- BLO_blendhandle_close(libfiledata);
-
- if (!skip_currpar) {
- entry = MEM_callocN(sizeof(*entry), __func__);
- entry->relpath = BLI_strdup(FILENAME_PARENT);
- entry->typeflag |= (FILE_TYPE_BLENDERLIB | FILE_TYPE_DIR);
- BLI_addtail(entries, entry);
- nbr_entries++;
- }
-
- for (i = 0, ln = names; i < nnames; i++, ln = ln->next) {
- const char *blockname = ln->link;
-
- entry = MEM_callocN(sizeof(*entry), __func__);
- entry->relpath = BLI_strdup(blockname);
- entry->typeflag |= FILE_TYPE_BLENDERLIB;
- if (!(group && idcode)) {
- entry->typeflag |= FILE_TYPE_DIR;
- entry->blentype = groupname_to_code(blockname);
- }
- else {
- entry->blentype = idcode;
- }
- BLI_addtail(entries, entry);
- nbr_entries++;
- }
-
- BLI_linklist_free(names, free);
-
- return nbr_entries;
+ FileListInternEntry *entry;
+ LinkNode *ln, *names;
+ int i, nnames, idcode = 0, nbr_entries = 0;
+ char dir[FILE_MAX_LIBEXTRA], *group;
+ bool ok;
+
+ struct BlendHandle *libfiledata = NULL;
+
+ /* name test */
+ ok = BLO_library_path_explode(root, dir, &group, NULL);
+ if (!ok) {
+ return nbr_entries;
+ }
+
+ /* there we go */
+ libfiledata = BLO_blendhandle_from_file(dir, NULL);
+ if (libfiledata == NULL) {
+ return nbr_entries;
+ }
+
+ /* memory for strings is passed into filelist[i].entry->relpath
+ * and freed in filelist_entry_free. */
+ if (group) {
+ idcode = groupname_to_code(group);
+ names = BLO_blendhandle_get_datablock_names(libfiledata, idcode, &nnames);
+ }
+ else {
+ names = BLO_blendhandle_get_linkable_groups(libfiledata);
+ nnames = BLI_linklist_count(names);
+ }
+
+ BLO_blendhandle_close(libfiledata);
+
+ if (!skip_currpar) {
+ entry = MEM_callocN(sizeof(*entry), __func__);
+ entry->relpath = BLI_strdup(FILENAME_PARENT);
+ entry->typeflag |= (FILE_TYPE_BLENDERLIB | FILE_TYPE_DIR);
+ BLI_addtail(entries, entry);
+ nbr_entries++;
+ }
+
+ for (i = 0, ln = names; i < nnames; i++, ln = ln->next) {
+ const char *blockname = ln->link;
+
+ entry = MEM_callocN(sizeof(*entry), __func__);
+ entry->relpath = BLI_strdup(blockname);
+ entry->typeflag |= FILE_TYPE_BLENDERLIB;
+ if (!(group && idcode)) {
+ entry->typeflag |= FILE_TYPE_DIR;
+ entry->blentype = groupname_to_code(blockname);
+ }
+ else {
+ entry->blentype = idcode;
+ }
+ BLI_addtail(entries, entry);
+ nbr_entries++;
+ }
+
+ BLI_linklist_free(names, free);
+
+ return nbr_entries;
}
#if 0
@@ -2330,428 +2411,453 @@ static int filelist_readjob_list_lib(const char *root, ListBase *entries, const
/* Code ***NOT*** updated for job stuff! */
static void filelist_readjob_main_rec(Main *bmain, FileList *filelist)
{
- ID *id;
- FileDirEntry *files, *firstlib = NULL;
- ListBase *lb;
- int a, fake, idcode, ok, totlib, totbl;
-
- // filelist->type = FILE_MAIN; // XXX TODO: add modes to filebrowser
-
- BLI_assert(filelist->filelist.entries == NULL);
-
- if (filelist->filelist.root[0] == '/') filelist->filelist.root[0] = '\0';
-
- if (filelist->filelist.root[0]) {
- idcode = groupname_to_code(filelist->filelist.root);
- if (idcode == 0) filelist->filelist.root[0] = '\0';
- }
-
- if (filelist->dir[0] == 0) {
- /* make directories */
-#ifdef WITH_FREESTYLE
- filelist->filelist.nbr_entries = 24;
-#else
- filelist->filelist.nbr_entries = 23;
-#endif
- filelist_resize(filelist, filelist->filelist.nbr_entries);
-
- for (a = 0; a < filelist->filelist.nbr_entries; a++) {
- filelist->filelist.entries[a].typeflag |= FILE_TYPE_DIR;
- }
-
- filelist->filelist.entries[0].entry->relpath = BLI_strdup(FILENAME_PARENT);
- filelist->filelist.entries[1].entry->relpath = BLI_strdup("Scene");
- filelist->filelist.entries[2].entry->relpath = BLI_strdup("Object");
- filelist->filelist.entries[3].entry->relpath = BLI_strdup("Mesh");
- filelist->filelist.entries[4].entry->relpath = BLI_strdup("Curve");
- filelist->filelist.entries[5].entry->relpath = BLI_strdup("Metaball");
- filelist->filelist.entries[6].entry->relpath = BLI_strdup("Material");
- filelist->filelist.entries[7].entry->relpath = BLI_strdup("Texture");
- filelist->filelist.entries[8].entry->relpath = BLI_strdup("Image");
- filelist->filelist.entries[9].entry->relpath = BLI_strdup("Ika");
- filelist->filelist.entries[10].entry->relpath = BLI_strdup("Wave");
- filelist->filelist.entries[11].entry->relpath = BLI_strdup("Lattice");
- filelist->filelist.entries[12].entry->relpath = BLI_strdup("Light");
- filelist->filelist.entries[13].entry->relpath = BLI_strdup("Camera");
- filelist->filelist.entries[14].entry->relpath = BLI_strdup("Ipo");
- filelist->filelist.entries[15].entry->relpath = BLI_strdup("World");
- filelist->filelist.entries[16].entry->relpath = BLI_strdup("Screen");
- filelist->filelist.entries[17].entry->relpath = BLI_strdup("VFont");
- filelist->filelist.entries[18].entry->relpath = BLI_strdup("Text");
- filelist->filelist.entries[19].entry->relpath = BLI_strdup("Armature");
- 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");
-#ifdef WITH_FREESTYLE
- filelist->filelist.entries[23].entry->relpath = BLI_strdup("FreestyleLineStyle");
-#endif
- }
- else {
- /* make files */
- idcode = groupname_to_code(filelist->filelist.root);
-
- lb = which_libbase(bmain, idcode);
- if (lb == NULL) return;
-
- filelist->filelist.nbr_entries = 0;
- for (id = lb->first; id; id = id->next) {
- if (!(filelist->filter_data.flags & FLF_HIDE_DOT) || id->name[2] != '.') {
- filelist->filelist.nbr_entries++;
- }
- }
-
- /* XXX TODO: if databrowse F4 or append/link
- * filelist->flags & FLF_HIDE_PARENT has to be set */
- if (!(filelist->filter_data.flags & FLF_HIDE_PARENT))
- filelist->filelist.nbr_entries++;
-
- if (filelist->filelist.nbr_entries > 0) {
- filelist_resize(filelist, filelist->filelist.nbr_entries);
- }
-
- files = filelist->filelist.entries;
-
- if (!(filelist->filter_data.flags & FLF_HIDE_PARENT)) {
- files->entry->relpath = BLI_strdup(FILENAME_PARENT);
- files->typeflag |= FILE_TYPE_DIR;
-
- files++;
- }
-
- totlib = totbl = 0;
- for (id = lb->first; id; id = id->next) {
- ok = 1;
- if (ok) {
- if (!(filelist->filter_data.flags & FLF_HIDE_DOT) || id->name[2] != '.') {
- if (id->lib == NULL) {
- files->entry->relpath = BLI_strdup(id->name + 2);
- }
- else {
- char relname[FILE_MAX + (MAX_ID_NAME - 2) + 3];
- BLI_snprintf(relname, sizeof(relname), "%s | %s", id->lib->name, id->name + 2);
- files->entry->relpath = BLI_strdup(relname);
- }
-// files->type |= S_IFREG;
-#if 0 /* XXX TODO show the selection status of the objects */
- if (!filelist->has_func) { /* F4 DATA BROWSE */
- if (idcode == ID_OB) {
- if ( ((Object *)id)->flag & SELECT) files->entry->selflag |= FILE_SEL_SELECTED;
- }
- else if (idcode == ID_SCE) {
- if ( ((Scene *)id)->r.scemode & R_BG_RENDER) files->entry->selflag |= FILE_SEL_SELECTED;
- }
- }
-#endif
-// files->entry->nr = totbl + 1;
- files->entry->poin = id;
- fake = id->flag & LIB_FAKEUSER;
- if (idcode == ID_MA || idcode == ID_TE || idcode == ID_LA || idcode == ID_WO || idcode == ID_IM) {
- files->typeflag |= FILE_TYPE_IMAGE;
- }
-// if (id->lib && fake) BLI_snprintf(files->extra, sizeof(files->entry->extra), "LF %d", id->us);
-// else if (id->lib) BLI_snprintf(files->extra, sizeof(files->entry->extra), "L %d", id->us);
-// else if (fake) BLI_snprintf(files->extra, sizeof(files->entry->extra), "F %d", id->us);
-// else BLI_snprintf(files->extra, sizeof(files->entry->extra), " %d", id->us);
-
- if (id->lib) {
- if (totlib == 0) firstlib = files;
- totlib++;
- }
-
- files++;
- }
- totbl++;
- }
- }
-
- /* only qsort of library blocks */
- if (totlib > 1) {
- qsort(firstlib, totlib, sizeof(*files), compare_name);
- }
- }
+ ID *id;
+ FileDirEntry *files, *firstlib = NULL;
+ ListBase *lb;
+ int a, fake, idcode, ok, totlib, totbl;
+
+ // filelist->type = FILE_MAIN; // XXX TODO: add modes to filebrowser
+
+ BLI_assert(filelist->filelist.entries == NULL);
+
+ if (filelist->filelist.root[0] == '/') filelist->filelist.root[0] = '\0';
+
+ if (filelist->filelist.root[0]) {
+ idcode = groupname_to_code(filelist->filelist.root);
+ if (idcode == 0) filelist->filelist.root[0] = '\0';
+ }
+
+ if (filelist->dir[0] == 0) {
+ /* make directories */
+# ifdef WITH_FREESTYLE
+ filelist->filelist.nbr_entries = 24;
+# else
+ filelist->filelist.nbr_entries = 23;
+# endif
+ filelist_resize(filelist, filelist->filelist.nbr_entries);
+
+ for (a = 0; a < filelist->filelist.nbr_entries; a++) {
+ filelist->filelist.entries[a].typeflag |= FILE_TYPE_DIR;
+ }
+
+ filelist->filelist.entries[0].entry->relpath = BLI_strdup(FILENAME_PARENT);
+ filelist->filelist.entries[1].entry->relpath = BLI_strdup("Scene");
+ filelist->filelist.entries[2].entry->relpath = BLI_strdup("Object");
+ filelist->filelist.entries[3].entry->relpath = BLI_strdup("Mesh");
+ filelist->filelist.entries[4].entry->relpath = BLI_strdup("Curve");
+ filelist->filelist.entries[5].entry->relpath = BLI_strdup("Metaball");
+ filelist->filelist.entries[6].entry->relpath = BLI_strdup("Material");
+ filelist->filelist.entries[7].entry->relpath = BLI_strdup("Texture");
+ filelist->filelist.entries[8].entry->relpath = BLI_strdup("Image");
+ filelist->filelist.entries[9].entry->relpath = BLI_strdup("Ika");
+ filelist->filelist.entries[10].entry->relpath = BLI_strdup("Wave");
+ filelist->filelist.entries[11].entry->relpath = BLI_strdup("Lattice");
+ filelist->filelist.entries[12].entry->relpath = BLI_strdup("Light");
+ filelist->filelist.entries[13].entry->relpath = BLI_strdup("Camera");
+ filelist->filelist.entries[14].entry->relpath = BLI_strdup("Ipo");
+ filelist->filelist.entries[15].entry->relpath = BLI_strdup("World");
+ filelist->filelist.entries[16].entry->relpath = BLI_strdup("Screen");
+ filelist->filelist.entries[17].entry->relpath = BLI_strdup("VFont");
+ filelist->filelist.entries[18].entry->relpath = BLI_strdup("Text");
+ filelist->filelist.entries[19].entry->relpath = BLI_strdup("Armature");
+ 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");
+# ifdef WITH_FREESTYLE
+ filelist->filelist.entries[23].entry->relpath = BLI_strdup("FreestyleLineStyle");
+# endif
+ }
+ else {
+ /* make files */
+ idcode = groupname_to_code(filelist->filelist.root);
+
+ lb = which_libbase(bmain, idcode);
+ if (lb == NULL) return;
+
+ filelist->filelist.nbr_entries = 0;
+ for (id = lb->first; id; id = id->next) {
+ if (!(filelist->filter_data.flags & FLF_HIDE_DOT) || id->name[2] != '.') {
+ filelist->filelist.nbr_entries++;
+ }
+ }
+
+ /* XXX TODO: if databrowse F4 or append/link
+ * filelist->flags & FLF_HIDE_PARENT has to be set */
+ if (!(filelist->filter_data.flags & FLF_HIDE_PARENT))
+ filelist->filelist.nbr_entries++;
+
+ if (filelist->filelist.nbr_entries > 0) {
+ filelist_resize(filelist, filelist->filelist.nbr_entries);
+ }
+
+ files = filelist->filelist.entries;
+
+ if (!(filelist->filter_data.flags & FLF_HIDE_PARENT)) {
+ files->entry->relpath = BLI_strdup(FILENAME_PARENT);
+ files->typeflag |= FILE_TYPE_DIR;
+
+ files++;
+ }
+
+ totlib = totbl = 0;
+ for (id = lb->first; id; id = id->next) {
+ ok = 1;
+ if (ok) {
+ if (!(filelist->filter_data.flags & FLF_HIDE_DOT) || id->name[2] != '.') {
+ if (id->lib == NULL) {
+ files->entry->relpath = BLI_strdup(id->name + 2);
+ }
+ else {
+ char relname[FILE_MAX + (MAX_ID_NAME - 2) + 3];
+ BLI_snprintf(relname, sizeof(relname), "%s | %s", id->lib->name, id->name + 2);
+ files->entry->relpath = BLI_strdup(relname);
+ }
+// files->type |= S_IFREG;
+# if 0 /* XXX TODO show the selection status of the objects */
+ if (!filelist->has_func) { /* F4 DATA BROWSE */
+ if (idcode == ID_OB) {
+ if ( ((Object *)id)->flag & SELECT) files->entry->selflag |= FILE_SEL_SELECTED;
+ }
+ else if (idcode == ID_SCE) {
+ if ( ((Scene *)id)->r.scemode & R_BG_RENDER) files->entry->selflag |= FILE_SEL_SELECTED;
+ }
+ }
+# endif
+// files->entry->nr = totbl + 1;
+ files->entry->poin = id;
+ fake = id->flag & LIB_FAKEUSER;
+ if (idcode == ID_MA || idcode == ID_TE || idcode == ID_LA || idcode == ID_WO || idcode == ID_IM) {
+ files->typeflag |= FILE_TYPE_IMAGE;
+ }
+// if (id->lib && fake) BLI_snprintf(files->extra, sizeof(files->entry->extra), "LF %d", id->us);
+// else if (id->lib) BLI_snprintf(files->extra, sizeof(files->entry->extra), "L %d", id->us);
+// else if (fake) BLI_snprintf(files->extra, sizeof(files->entry->extra), "F %d", id->us);
+// else BLI_snprintf(files->extra, sizeof(files->entry->extra), " %d", id->us);
+
+ if (id->lib) {
+ if (totlib == 0) firstlib = files;
+ totlib++;
+ }
+
+ files++;
+ }
+ totbl++;
+ }
+ }
+
+ /* only qsort of library blocks */
+ if (totlib > 1) {
+ qsort(firstlib, totlib, sizeof(*files), compare_name);
+ }
+ }
}
#endif
-static void filelist_readjob_do(
- const bool do_lib,
- FileList *filelist, const char *main_name, short *stop, short *do_update, float *progress, ThreadMutex *lock)
-{
- ListBase entries = {0};
- BLI_Stack *todo_dirs;
- TodoDir *td_dir;
- char dir[FILE_MAX_LIBEXTRA];
- char filter_glob[FILE_MAXFILE];
- const char *root = filelist->filelist.root;
- const int max_recursion = filelist->max_recursion;
- int nbr_done_dirs = 0, nbr_todo_dirs = 1;
-
-// BLI_assert(filelist->filtered == NULL);
- BLI_assert(BLI_listbase_is_empty(&filelist->filelist.entries) && (filelist->filelist.nbr_entries == 0));
-
- todo_dirs = BLI_stack_new(sizeof(*td_dir), __func__);
- td_dir = BLI_stack_push_r(todo_dirs);
- td_dir->level = 1;
-
- 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);
- td_dir->dir = BLI_strdup(dir);
-
- while (!BLI_stack_is_empty(todo_dirs) && !(*stop)) {
- FileListInternEntry *entry;
- int nbr_entries = 0;
- bool is_lib = do_lib;
-
- char *subdir;
- char rel_subdir[FILE_MAX_LIBEXTRA];
- int recursion_level;
- bool skip_currpar;
-
- td_dir = BLI_stack_peek(todo_dirs);
- subdir = td_dir->dir;
- recursion_level = td_dir->level;
- skip_currpar = (recursion_level > 1);
-
- BLI_stack_discard(todo_dirs);
-
- /* ARRRG! We have to be very careful *not to use* common BLI_path_util helpers over
- * entry->relpath itself (nor any path containing it), since it may actually be a datablock
- * name inside .blend file, which can have slashes and backslashes! See T46827.
- * 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_rel(rel_subdir, root);
-
- if (do_lib) {
- nbr_entries = filelist_readjob_list_lib(subdir, &entries, skip_currpar);
- }
- if (!nbr_entries) {
- is_lib = false;
- nbr_entries = filelist_readjob_list_dir(subdir, &entries, filter_glob, do_lib, main_name, skip_currpar);
- }
-
- for (entry = entries.first; entry; entry = entry->next) {
- BLI_join_dirfile(dir, sizeof(dir), rel_subdir, entry->relpath);
-
- /* Generate our entry uuid. Abusing uuid as an uint32, shall be more than enough here,
- * things would crash way before we overflow that counter!
- * Using an atomic operation to avoid having to lock thread...
- * Note that we do not really need this here currently,
- * since there is a single listing thread, but better
- * remain consistent about threading! */
- *((uint32_t *)entry->uuid) = atomic_add_and_fetch_uint32((uint32_t *)filelist->filelist_intern.curr_uuid, 1);
-
- /* Only thing we change in direntry here, so we need to free it first. */
- MEM_freeN(entry->relpath);
- entry->relpath = BLI_strdup(dir + 2); /* + 2 to remove '//'
- * added by BLI_path_rel to rel_subdir */
- entry->name = BLI_strdup(fileentry_uiname(root, entry->relpath, entry->typeflag, dir));
-
- /* Here we decide whether current filedirentry is to be listed too, or not. */
- if (max_recursion && (is_lib || (recursion_level <= max_recursion))) {
- if (((entry->typeflag & FILE_TYPE_DIR) == 0) || FILENAME_IS_CURRPAR(entry->relpath)) {
- /* Skip... */
- }
- else if (!is_lib && (recursion_level >= max_recursion) &&
- ((entry->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) == 0))
- {
- /* Do not recurse in real directories in this case, only in .blend libs. */
- }
- 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);
- td_dir = BLI_stack_push_r(todo_dirs);
- td_dir->level = recursion_level + 1;
- td_dir->dir = BLI_strdup(dir);
- nbr_todo_dirs++;
- }
- }
- }
-
- if (nbr_entries) {
- BLI_mutex_lock(lock);
-
- *do_update = true;
-
- BLI_movelisttolist(&filelist->filelist.entries, &entries);
- filelist->filelist.nbr_entries += nbr_entries;
-
- BLI_mutex_unlock(lock);
- }
-
- nbr_done_dirs++;
- *progress = (float)nbr_done_dirs / (float)nbr_todo_dirs;
- MEM_freeN(subdir);
- }
-
- /* If we were interrupted by stop, stack may not be empty and we need to free
- * pending dir paths. */
- while (!BLI_stack_is_empty(todo_dirs)) {
- td_dir = BLI_stack_peek(todo_dirs);
- MEM_freeN(td_dir->dir);
- BLI_stack_discard(todo_dirs);
- }
- BLI_stack_free(todo_dirs);
+static void filelist_readjob_do(const bool do_lib,
+ FileList *filelist,
+ const char *main_name,
+ short *stop,
+ short *do_update,
+ float *progress,
+ ThreadMutex *lock)
+{
+ ListBase entries = {0};
+ BLI_Stack *todo_dirs;
+ TodoDir *td_dir;
+ char dir[FILE_MAX_LIBEXTRA];
+ char filter_glob[FILE_MAXFILE];
+ const char *root = filelist->filelist.root;
+ const int max_recursion = filelist->max_recursion;
+ int nbr_done_dirs = 0, nbr_todo_dirs = 1;
+
+ // BLI_assert(filelist->filtered == NULL);
+ BLI_assert(BLI_listbase_is_empty(&filelist->filelist.entries) &&
+ (filelist->filelist.nbr_entries == 0));
+
+ todo_dirs = BLI_stack_new(sizeof(*td_dir), __func__);
+ td_dir = BLI_stack_push_r(todo_dirs);
+ td_dir->level = 1;
+
+ 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);
+ td_dir->dir = BLI_strdup(dir);
+
+ while (!BLI_stack_is_empty(todo_dirs) && !(*stop)) {
+ FileListInternEntry *entry;
+ int nbr_entries = 0;
+ bool is_lib = do_lib;
+
+ char *subdir;
+ char rel_subdir[FILE_MAX_LIBEXTRA];
+ int recursion_level;
+ bool skip_currpar;
+
+ td_dir = BLI_stack_peek(todo_dirs);
+ subdir = td_dir->dir;
+ recursion_level = td_dir->level;
+ skip_currpar = (recursion_level > 1);
+
+ BLI_stack_discard(todo_dirs);
+
+ /* ARRRG! We have to be very careful *not to use* common BLI_path_util helpers over
+ * entry->relpath itself (nor any path containing it), since it may actually be a datablock
+ * name inside .blend file, which can have slashes and backslashes! See T46827.
+ * 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_rel(rel_subdir, root);
+
+ if (do_lib) {
+ nbr_entries = filelist_readjob_list_lib(subdir, &entries, skip_currpar);
+ }
+ if (!nbr_entries) {
+ is_lib = false;
+ nbr_entries = filelist_readjob_list_dir(
+ subdir, &entries, filter_glob, do_lib, main_name, skip_currpar);
+ }
+
+ for (entry = entries.first; entry; entry = entry->next) {
+ BLI_join_dirfile(dir, sizeof(dir), rel_subdir, entry->relpath);
+
+ /* Generate our entry uuid. Abusing uuid as an uint32, shall be more than enough here,
+ * things would crash way before we overflow that counter!
+ * Using an atomic operation to avoid having to lock thread...
+ * Note that we do not really need this here currently,
+ * since there is a single listing thread, but better
+ * remain consistent about threading! */
+ *((uint32_t *)entry->uuid) = atomic_add_and_fetch_uint32(
+ (uint32_t *)filelist->filelist_intern.curr_uuid, 1);
+
+ /* Only thing we change in direntry here, so we need to free it first. */
+ MEM_freeN(entry->relpath);
+ entry->relpath = BLI_strdup(dir + 2); /* + 2 to remove '//'
+ * added by BLI_path_rel to rel_subdir */
+ entry->name = BLI_strdup(fileentry_uiname(root, entry->relpath, entry->typeflag, dir));
+
+ /* Here we decide whether current filedirentry is to be listed too, or not. */
+ if (max_recursion && (is_lib || (recursion_level <= max_recursion))) {
+ if (((entry->typeflag & FILE_TYPE_DIR) == 0) || FILENAME_IS_CURRPAR(entry->relpath)) {
+ /* Skip... */
+ }
+ else if (!is_lib && (recursion_level >= max_recursion) &&
+ ((entry->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) == 0)) {
+ /* Do not recurse in real directories in this case, only in .blend libs. */
+ }
+ 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);
+ td_dir = BLI_stack_push_r(todo_dirs);
+ td_dir->level = recursion_level + 1;
+ td_dir->dir = BLI_strdup(dir);
+ nbr_todo_dirs++;
+ }
+ }
+ }
+
+ if (nbr_entries) {
+ BLI_mutex_lock(lock);
+
+ *do_update = true;
+
+ BLI_movelisttolist(&filelist->filelist.entries, &entries);
+ filelist->filelist.nbr_entries += nbr_entries;
+
+ BLI_mutex_unlock(lock);
+ }
+
+ nbr_done_dirs++;
+ *progress = (float)nbr_done_dirs / (float)nbr_todo_dirs;
+ MEM_freeN(subdir);
+ }
+
+ /* If we were interrupted by stop, stack may not be empty and we need to free
+ * pending dir paths. */
+ while (!BLI_stack_is_empty(todo_dirs)) {
+ td_dir = BLI_stack_peek(todo_dirs);
+ MEM_freeN(td_dir->dir);
+ BLI_stack_discard(todo_dirs);
+ }
+ BLI_stack_free(todo_dirs);
+}
+
+static void filelist_readjob_dir(FileList *filelist,
+ const char *main_name,
+ short *stop,
+ short *do_update,
+ float *progress,
+ ThreadMutex *lock)
+{
+ filelist_readjob_do(false, filelist, main_name, stop, do_update, progress, lock);
+}
+
+static void filelist_readjob_lib(FileList *filelist,
+ const char *main_name,
+ short *stop,
+ short *do_update,
+ float *progress,
+ ThreadMutex *lock)
+{
+ filelist_readjob_do(true, filelist, main_name, stop, do_update, progress, lock);
+}
+
+static void filelist_readjob_main(FileList *filelist,
+ const char *main_name,
+ short *stop,
+ short *do_update,
+ float *progress,
+ ThreadMutex *lock)
+{
+ /* TODO! */
+ filelist_readjob_dir(filelist, main_name, stop, do_update, progress, lock);
}
-static void filelist_readjob_dir(
- FileList *filelist, const char *main_name, short *stop, short *do_update, float *progress, ThreadMutex *lock)
-{
- filelist_readjob_do(false, filelist, main_name, stop, do_update, progress, lock);
-}
-
-static void filelist_readjob_lib(
- FileList *filelist, const char *main_name, short *stop, short *do_update, float *progress, ThreadMutex *lock)
-{
- filelist_readjob_do(true, filelist, main_name, stop, do_update, progress, lock);
-}
-
-static void filelist_readjob_main(
- FileList *filelist, const char *main_name, short *stop, short *do_update, float *progress, ThreadMutex *lock)
-{
- /* TODO! */
- filelist_readjob_dir(filelist, main_name, stop, do_update, progress, lock);
-}
-
-
typedef struct FileListReadJob {
- ThreadMutex lock;
- char main_name[FILE_MAX];
- struct FileList *filelist;
- /** XXX We may use a simpler struct here... just a linked list and root path? */
- struct FileList *tmp_filelist;
+ ThreadMutex lock;
+ char main_name[FILE_MAX];
+ struct FileList *filelist;
+ /** XXX We may use a simpler struct here... just a linked list and root path? */
+ struct FileList *tmp_filelist;
} FileListReadJob;
static void filelist_readjob_startjob(void *flrjv, short *stop, short *do_update, float *progress)
{
- FileListReadJob *flrj = flrjv;
+ FileListReadJob *flrj = flrjv;
-// printf("START filelist reading (%d files, main thread: %d)\n",
-// flrj->filelist->filelist.nbr_entries, BLI_thread_is_main());
+ // printf("START filelist reading (%d files, main thread: %d)\n",
+ // flrj->filelist->filelist.nbr_entries, BLI_thread_is_main());
- BLI_mutex_lock(&flrj->lock);
+ BLI_mutex_lock(&flrj->lock);
- BLI_assert((flrj->tmp_filelist == NULL) && flrj->filelist);
+ BLI_assert((flrj->tmp_filelist == NULL) && flrj->filelist);
- flrj->tmp_filelist = MEM_dupallocN(flrj->filelist);
+ flrj->tmp_filelist = MEM_dupallocN(flrj->filelist);
- BLI_listbase_clear(&flrj->tmp_filelist->filelist.entries);
- flrj->tmp_filelist->filelist.nbr_entries = 0;
+ BLI_listbase_clear(&flrj->tmp_filelist->filelist.entries);
+ flrj->tmp_filelist->filelist.nbr_entries = 0;
- flrj->tmp_filelist->filelist_intern.filtered = NULL;
- BLI_listbase_clear(&flrj->tmp_filelist->filelist_intern.entries);
- memset(flrj->tmp_filelist->filelist_intern.curr_uuid, 0, sizeof(flrj->tmp_filelist->filelist_intern.curr_uuid));
+ flrj->tmp_filelist->filelist_intern.filtered = NULL;
+ BLI_listbase_clear(&flrj->tmp_filelist->filelist_intern.entries);
+ memset(flrj->tmp_filelist->filelist_intern.curr_uuid,
+ 0,
+ sizeof(flrj->tmp_filelist->filelist_intern.curr_uuid));
- flrj->tmp_filelist->libfiledata = NULL;
- memset(&flrj->tmp_filelist->filelist_cache, 0, sizeof(flrj->tmp_filelist->filelist_cache));
- flrj->tmp_filelist->selection_state = NULL;
+ flrj->tmp_filelist->libfiledata = NULL;
+ memset(&flrj->tmp_filelist->filelist_cache, 0, sizeof(flrj->tmp_filelist->filelist_cache));
+ flrj->tmp_filelist->selection_state = NULL;
- BLI_mutex_unlock(&flrj->lock);
+ BLI_mutex_unlock(&flrj->lock);
- flrj->tmp_filelist->read_jobf(flrj->tmp_filelist, flrj->main_name, stop, do_update, progress, &flrj->lock);
+ flrj->tmp_filelist->read_jobf(
+ flrj->tmp_filelist, flrj->main_name, stop, do_update, progress, &flrj->lock);
}
static void filelist_readjob_update(void *flrjv)
{
- FileListReadJob *flrj = flrjv;
- FileListIntern *fl_intern = &flrj->filelist->filelist_intern;
- ListBase new_entries = {NULL};
- int nbr_entries, new_nbr_entries = 0;
+ FileListReadJob *flrj = flrjv;
+ FileListIntern *fl_intern = &flrj->filelist->filelist_intern;
+ ListBase new_entries = {NULL};
+ int nbr_entries, new_nbr_entries = 0;
- BLI_movelisttolist(&new_entries, &fl_intern->entries);
- nbr_entries = flrj->filelist->filelist.nbr_entries;
+ BLI_movelisttolist(&new_entries, &fl_intern->entries);
+ nbr_entries = flrj->filelist->filelist.nbr_entries;
- BLI_mutex_lock(&flrj->lock);
+ BLI_mutex_lock(&flrj->lock);
- if (flrj->tmp_filelist->filelist.nbr_entries) {
- /* We just move everything out of 'thread context' into final list. */
- new_nbr_entries = flrj->tmp_filelist->filelist.nbr_entries;
- BLI_movelisttolist(&new_entries, &flrj->tmp_filelist->filelist.entries);
- flrj->tmp_filelist->filelist.nbr_entries = 0;
- }
+ if (flrj->tmp_filelist->filelist.nbr_entries) {
+ /* We just move everything out of 'thread context' into final list. */
+ new_nbr_entries = flrj->tmp_filelist->filelist.nbr_entries;
+ BLI_movelisttolist(&new_entries, &flrj->tmp_filelist->filelist.entries);
+ flrj->tmp_filelist->filelist.nbr_entries = 0;
+ }
- BLI_mutex_unlock(&flrj->lock);
+ BLI_mutex_unlock(&flrj->lock);
- if (new_nbr_entries) {
- /* Do not clear selection cache, we can assume already 'selected' uuids are still valid! */
- filelist_clear_ex(flrj->filelist, true, false);
+ if (new_nbr_entries) {
+ /* Do not clear selection cache, we can assume already 'selected' uuids are still valid! */
+ filelist_clear_ex(flrj->filelist, true, false);
- flrj->filelist->flags |= (FL_NEED_SORTING | FL_NEED_FILTERING);
- }
+ flrj->filelist->flags |= (FL_NEED_SORTING | FL_NEED_FILTERING);
+ }
- /* if no new_nbr_entries, this is NOP */
- BLI_movelisttolist(&fl_intern->entries, &new_entries);
- flrj->filelist->filelist.nbr_entries = nbr_entries + new_nbr_entries;
+ /* if no new_nbr_entries, this is NOP */
+ BLI_movelisttolist(&fl_intern->entries, &new_entries);
+ flrj->filelist->filelist.nbr_entries = nbr_entries + new_nbr_entries;
}
static void filelist_readjob_endjob(void *flrjv)
{
- FileListReadJob *flrj = flrjv;
+ FileListReadJob *flrj = flrjv;
- /* In case there would be some dangling update... */
- filelist_readjob_update(flrjv);
+ /* In case there would be some dangling update... */
+ filelist_readjob_update(flrjv);
- flrj->filelist->flags &= ~FL_IS_PENDING;
- flrj->filelist->flags |= FL_IS_READY;
+ flrj->filelist->flags &= ~FL_IS_PENDING;
+ flrj->filelist->flags |= FL_IS_READY;
}
static void filelist_readjob_free(void *flrjv)
{
- FileListReadJob *flrj = flrjv;
+ FileListReadJob *flrj = flrjv;
-// printf("END filelist reading (%d files)\n", flrj->filelist->filelist.nbr_entries);
+ // printf("END filelist reading (%d files)\n", flrj->filelist->filelist.nbr_entries);
- if (flrj->tmp_filelist) {
- /* tmp_filelist shall never ever be filtered! */
- BLI_assert(flrj->tmp_filelist->filelist.nbr_entries == 0);
- BLI_assert(BLI_listbase_is_empty(&flrj->tmp_filelist->filelist.entries));
+ if (flrj->tmp_filelist) {
+ /* tmp_filelist shall never ever be filtered! */
+ BLI_assert(flrj->tmp_filelist->filelist.nbr_entries == 0);
+ BLI_assert(BLI_listbase_is_empty(&flrj->tmp_filelist->filelist.entries));
- filelist_freelib(flrj->tmp_filelist);
- filelist_free(flrj->tmp_filelist);
- MEM_freeN(flrj->tmp_filelist);
- }
+ filelist_freelib(flrj->tmp_filelist);
+ filelist_free(flrj->tmp_filelist);
+ MEM_freeN(flrj->tmp_filelist);
+ }
- BLI_mutex_end(&flrj->lock);
+ BLI_mutex_end(&flrj->lock);
- MEM_freeN(flrj);
+ MEM_freeN(flrj);
}
void filelist_readjob_start(FileList *filelist, const bContext *C)
{
- Main *bmain = CTX_data_main(C);
- wmJob *wm_job;
- FileListReadJob *flrj;
+ Main *bmain = CTX_data_main(C);
+ wmJob *wm_job;
+ FileListReadJob *flrj;
- /* prepare job data */
- flrj = MEM_callocN(sizeof(*flrj), __func__);
- flrj->filelist = filelist;
- BLI_strncpy(flrj->main_name, BKE_main_blendfile_path(bmain), sizeof(flrj->main_name));
+ /* prepare job data */
+ flrj = MEM_callocN(sizeof(*flrj), __func__);
+ flrj->filelist = filelist;
+ BLI_strncpy(flrj->main_name, BKE_main_blendfile_path(bmain), sizeof(flrj->main_name));
- filelist->flags &= ~(FL_FORCE_RESET | FL_IS_READY);
- filelist->flags |= FL_IS_PENDING;
+ filelist->flags &= ~(FL_FORCE_RESET | FL_IS_READY);
+ filelist->flags |= FL_IS_PENDING;
- BLI_mutex_init(&flrj->lock);
+ BLI_mutex_init(&flrj->lock);
- /* setup job */
- wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), CTX_wm_area(C), "Listing Dirs...",
- WM_JOB_PROGRESS, WM_JOB_TYPE_FILESEL_READDIR);
- WM_jobs_customdata_set(wm_job, flrj, filelist_readjob_free);
- WM_jobs_timer(wm_job, 0.01, NC_SPACE | ND_SPACE_FILE_LIST, NC_SPACE | ND_SPACE_FILE_LIST);
- WM_jobs_callbacks(wm_job, filelist_readjob_startjob, NULL, filelist_readjob_update, filelist_readjob_endjob);
+ /* setup job */
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ CTX_wm_area(C),
+ "Listing Dirs...",
+ WM_JOB_PROGRESS,
+ WM_JOB_TYPE_FILESEL_READDIR);
+ WM_jobs_customdata_set(wm_job, flrj, filelist_readjob_free);
+ WM_jobs_timer(wm_job, 0.01, NC_SPACE | ND_SPACE_FILE_LIST, NC_SPACE | ND_SPACE_FILE_LIST);
+ WM_jobs_callbacks(
+ wm_job, filelist_readjob_startjob, NULL, filelist_readjob_update, filelist_readjob_endjob);
- /* start the job */
- WM_jobs_start(CTX_wm_manager(C), wm_job);
+ /* start the job */
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
}
void filelist_readjob_stop(wmWindowManager *wm, ScrArea *sa)
{
- WM_jobs_kill_type(wm, sa, WM_JOB_TYPE_FILESEL_READDIR);
+ WM_jobs_kill_type(wm, sa, WM_JOB_TYPE_FILESEL_READDIR);
}
int filelist_readjob_running(wmWindowManager *wm, ScrArea *sa)
{
- return WM_jobs_test(wm, sa, WM_JOB_TYPE_FILESEL_READDIR);
+ return WM_jobs_test(wm, sa, WM_JOB_TYPE_FILESEL_READDIR);
}
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
index 0cfef16c00d..caf77246797 100644
--- a/source/blender/editors/space_file/filelist.h
+++ b/source/blender/editors/space_file/filelist.h
@@ -21,7 +21,6 @@
* \ingroup spfile
*/
-
#ifndef __FILELIST_H__
#define __FILELIST_H__
@@ -37,82 +36,101 @@ struct wmWindowManager;
struct FileDirEntry;
typedef enum FileSelType {
- FILE_SEL_REMOVE = 0,
- FILE_SEL_ADD = 1,
- FILE_SEL_TOGGLE = 2,
+ FILE_SEL_REMOVE = 0,
+ FILE_SEL_ADD = 1,
+ FILE_SEL_TOGGLE = 2,
} FileSelType;
typedef enum FileCheckType {
- CHECK_DIRS = 1,
- CHECK_FILES = 2,
- CHECK_ALL = 3,
+ CHECK_DIRS = 1,
+ CHECK_FILES = 2,
+ CHECK_ALL = 3,
} FileCheckType;
-struct ListBase *folderlist_new(void);
-void folderlist_free(struct ListBase *folderlist);
-struct ListBase *folderlist_duplicate(ListBase *folderlist);
-void folderlist_popdir(struct ListBase *folderlist, char *dir);
-void folderlist_pushdir(struct ListBase *folderlist, const char *dir);
-const char *folderlist_peeklastdir(struct ListBase *folderdist);
-int folderlist_clear_next(struct SpaceFile *sfile);
-
-
-void filelist_setsorting(struct FileList *filelist, const short sort);
-void filelist_sort(struct FileList *filelist);
-
-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 char *filter_glob, const char *filter_search);
-void filelist_filter(struct FileList *filelist);
-
-void filelist_init_icons(void);
-void filelist_free_icons(void);
-void filelist_imgsize(struct FileList *filelist, short w, short h);
-struct ImBuf *filelist_getimage(struct FileList *filelist, const int index);
-struct ImBuf *filelist_geticon_image(struct FileList *filelist, const int index);
-int filelist_geticon(struct FileList *filelist, const int index, const bool is_main);
-
-struct FileList *filelist_new(short type);
-void filelist_clear(struct FileList *filelist);
-void filelist_clear_ex(struct FileList *filelist, const bool do_cache, const bool do_selection);
-void filelist_free(struct FileList *filelist);
-
-const char *filelist_dir(struct FileList *filelist);
-bool filelist_is_dir(struct FileList *filelist, const char *path);
-void filelist_setdir(struct FileList *filelist, char *r_dir);
-
-int filelist_files_ensure(struct FileList *filelist);
-int filelist_empty(struct FileList *filelist);
-FileDirEntry *filelist_file(struct FileList *filelist, int index);
-int filelist_file_findpath(struct FileList *filelist, const char *file);
-FileDirEntry *filelist_entry_find_uuid(struct FileList *filelist, const int uuid[4]);
-void filelist_file_cache_slidingwindow_set(struct FileList *filelist, size_t window_size);
-bool filelist_file_cache_block(struct FileList *filelist, const int index);
-
-bool filelist_force_reset(struct FileList *filelist);
-bool filelist_pending(struct FileList *filelist);
-bool filelist_is_ready(struct FileList *filelist);
-
-unsigned int filelist_entry_select_set(const struct FileList *filelist, const struct FileDirEntry *entry, FileSelType select, unsigned int flag, FileCheckType check);
-void filelist_entry_select_index_set(struct FileList *filelist, const int index, FileSelType select, unsigned int flag, FileCheckType check);
-void filelist_entries_select_index_range_set(struct FileList *filelist, FileSelection *sel, FileSelType select, unsigned int flag, FileCheckType check);
-unsigned int filelist_entry_select_get(struct FileList *filelist, struct FileDirEntry *entry, FileCheckType check);
-unsigned int filelist_entry_select_index_get(struct FileList *filelist, const int index, FileCheckType check);
-
-void filelist_setrecursion(struct FileList *filelist, const int recursion_level);
+struct ListBase *folderlist_new(void);
+void folderlist_free(struct ListBase *folderlist);
+struct ListBase *folderlist_duplicate(ListBase *folderlist);
+void folderlist_popdir(struct ListBase *folderlist, char *dir);
+void folderlist_pushdir(struct ListBase *folderlist, const char *dir);
+const char *folderlist_peeklastdir(struct ListBase *folderdist);
+int folderlist_clear_next(struct SpaceFile *sfile);
+
+void filelist_setsorting(struct FileList *filelist, const short sort);
+void filelist_sort(struct FileList *filelist);
+
+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 char *filter_glob,
+ const char *filter_search);
+void filelist_filter(struct FileList *filelist);
+
+void filelist_init_icons(void);
+void filelist_free_icons(void);
+void filelist_imgsize(struct FileList *filelist, short w, short h);
+struct ImBuf *filelist_getimage(struct FileList *filelist, const int index);
+struct ImBuf *filelist_geticon_image(struct FileList *filelist, const int index);
+int filelist_geticon(struct FileList *filelist, const int index, const bool is_main);
+
+struct FileList *filelist_new(short type);
+void filelist_clear(struct FileList *filelist);
+void filelist_clear_ex(struct FileList *filelist, const bool do_cache, const bool do_selection);
+void filelist_free(struct FileList *filelist);
+
+const char *filelist_dir(struct FileList *filelist);
+bool filelist_is_dir(struct FileList *filelist, const char *path);
+void filelist_setdir(struct FileList *filelist, char *r_dir);
+
+int filelist_files_ensure(struct FileList *filelist);
+int filelist_empty(struct FileList *filelist);
+FileDirEntry *filelist_file(struct FileList *filelist, int index);
+int filelist_file_findpath(struct FileList *filelist, const char *file);
+FileDirEntry *filelist_entry_find_uuid(struct FileList *filelist, const int uuid[4]);
+void filelist_file_cache_slidingwindow_set(struct FileList *filelist, size_t window_size);
+bool filelist_file_cache_block(struct FileList *filelist, const int index);
+
+bool filelist_force_reset(struct FileList *filelist);
+bool filelist_pending(struct FileList *filelist);
+bool filelist_is_ready(struct FileList *filelist);
+
+unsigned int filelist_entry_select_set(const struct FileList *filelist,
+ const struct FileDirEntry *entry,
+ FileSelType select,
+ unsigned int flag,
+ FileCheckType check);
+void filelist_entry_select_index_set(struct FileList *filelist,
+ const int index,
+ FileSelType select,
+ unsigned int flag,
+ FileCheckType check);
+void filelist_entries_select_index_range_set(struct FileList *filelist,
+ FileSelection *sel,
+ FileSelType select,
+ unsigned int flag,
+ FileCheckType check);
+unsigned int filelist_entry_select_get(struct FileList *filelist,
+ struct FileDirEntry *entry,
+ FileCheckType check);
+unsigned int filelist_entry_select_index_get(struct FileList *filelist,
+ const int index,
+ FileCheckType check);
+
+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);
-void filelist_freelib(struct FileList *filelist);
+bool filelist_islibrary(struct FileList *filelist, char *dir, char **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_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);
-bool filelist_cache_previews_update(struct FileList *filelist);
-void filelist_cache_previews_set(struct FileList *filelist, const bool use_previews);
-bool filelist_cache_previews_running(struct FileList *filelist);
+bool filelist_cache_previews_update(struct FileList *filelist);
+void filelist_cache_previews_set(struct FileList *filelist, const bool use_previews);
+bool filelist_cache_previews_running(struct FileList *filelist);
#ifdef __cplusplus
}
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 3ab08b5ac71..24689d52110 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -21,7 +21,6 @@
* \ingroup spfile
*/
-
#include <string.h>
#include <stdio.h>
#include <math.h>
@@ -72,10 +71,10 @@
FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile)
{
- if (!sfile->params) {
- ED_fileselect_set_params(sfile);
- }
- return sfile->params;
+ if (!sfile->params) {
+ ED_fileselect_set_params(sfile);
+ }
+ return sfile->params;
}
/**
@@ -83,237 +82,245 @@ FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile)
* the previously used settings to be used here rather then overriding them */
short ED_fileselect_set_params(SpaceFile *sfile)
{
- FileSelectParams *params;
- wmOperator *op = sfile->op;
-
- const char *blendfile_path = BKE_main_blendfile_path_from_global();
-
- /* create new parameters if necessary */
- if (!sfile->params) {
- sfile->params = MEM_callocN(sizeof(FileSelectParams), "fileselparams");
- /* set path to most recently opened .blend */
- BLI_split_dirfile(blendfile_path, sfile->params->dir, sfile->params->file, sizeof(sfile->params->dir), sizeof(sfile->params->file));
- sfile->params->filter_glob[0] = '\0';
- /* set the default thumbnails size */
- sfile->params->thumbnail_size = 128;
- }
-
- params = sfile->params;
-
- /* set the parameters from the operator, if it exists */
- if (op) {
- PropertyRNA *prop;
- const bool is_files = (RNA_struct_find_property(op->ptr, "files") != NULL);
- const bool is_filepath = (RNA_struct_find_property(op->ptr, "filepath") != NULL);
- const bool is_filename = (RNA_struct_find_property(op->ptr, "filename") != NULL);
- const bool is_directory = (RNA_struct_find_property(op->ptr, "directory") != NULL);
- const bool is_relative_path = (RNA_struct_find_property(op->ptr, "relative_path") != NULL);
-
- BLI_strncpy_utf8(params->title, RNA_struct_ui_name(op->type->srna), sizeof(params->title));
-
- if ((prop = RNA_struct_find_property(op->ptr, "filemode"))) {
- params->type = RNA_property_int_get(op->ptr, prop);
- }
- else {
- params->type = FILE_SPECIAL;
- }
-
- if (is_filepath && RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) {
- char name[FILE_MAX];
- RNA_string_get(op->ptr, "filepath", name);
- if (params->type == FILE_LOADLIB) {
- BLI_strncpy(params->dir, name, sizeof(params->dir));
- sfile->params->file[0] = '\0';
- }
- else {
- BLI_split_dirfile(name, sfile->params->dir, sfile->params->file, sizeof(sfile->params->dir), sizeof(sfile->params->file));
- }
- }
- else {
- if (is_directory && RNA_struct_property_is_set_ex(op->ptr, "directory", false)) {
- RNA_string_get(op->ptr, "directory", params->dir);
- sfile->params->file[0] = '\0';
- }
-
- if (is_filename && RNA_struct_property_is_set_ex(op->ptr, "filename", false)) {
- RNA_string_get(op->ptr, "filename", params->file);
- }
- }
-
- if (params->dir[0]) {
- BLI_cleanup_dir(blendfile_path, params->dir);
- BLI_path_abs(params->dir, blendfile_path);
- }
-
- if (is_directory == true && is_filename == false && is_filepath == false && is_files == false) {
- params->flag |= FILE_DIRSEL_ONLY;
- }
- else {
- params->flag &= ~FILE_DIRSEL_ONLY;
- }
-
- params->filter = 0;
- if ((prop = RNA_struct_find_property(op->ptr, "filter_blender")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BLENDER : 0;
- if ((prop = RNA_struct_find_property(op->ptr, "filter_blenlib")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BLENDERLIB : 0;
- if ((prop = RNA_struct_find_property(op->ptr, "filter_backup")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BLENDER_BACKUP : 0;
- if ((prop = RNA_struct_find_property(op->ptr, "filter_image")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_IMAGE : 0;
- if ((prop = RNA_struct_find_property(op->ptr, "filter_movie")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_MOVIE : 0;
- if ((prop = RNA_struct_find_property(op->ptr, "filter_python")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_PYSCRIPT : 0;
- if ((prop = RNA_struct_find_property(op->ptr, "filter_font")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_FTFONT : 0;
- if ((prop = RNA_struct_find_property(op->ptr, "filter_sound")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_SOUND : 0;
- if ((prop = RNA_struct_find_property(op->ptr, "filter_text")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_TEXT : 0;
- if ((prop = RNA_struct_find_property(op->ptr, "filter_folder")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_FOLDER : 0;
- if ((prop = RNA_struct_find_property(op->ptr, "filter_btx")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BTX : 0;
- if ((prop = RNA_struct_find_property(op->ptr, "filter_collada")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_COLLADA : 0;
- if ((prop = RNA_struct_find_property(op->ptr, "filter_alembic")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_ALEMBIC : 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(
- op->ptr, prop, params->filter_glob, sizeof(params->filter_glob), NULL);
- if (tmp != params->filter_glob) {
- BLI_strncpy(params->filter_glob, tmp, sizeof(params->filter_glob));
- MEM_freeN(tmp);
-
- /* Fix stupid things that truncating might have generated,
- * like last group being a 'match everything' wildcard-only one... */
- BLI_path_extension_glob_validate(params->filter_glob);
- }
- params->filter |= (FILE_TYPE_OPERATOR | FILE_TYPE_FOLDER);
- }
- else {
- params->filter_glob[0] = '\0';
- }
-
- if (params->filter != 0) {
- if (U.uiflag & USER_FILTERFILEEXTS) {
- params->flag |= FILE_FILTER;
- }
- else {
- params->flag &= ~FILE_FILTER;
- }
- }
-
- /* For now, always init filterid to 'all true' */
- params->filter_id = FILTER_ID_AC | FILTER_ID_AR | FILTER_ID_BR | FILTER_ID_CA | FILTER_ID_CU | FILTER_ID_GD |
- FILTER_ID_GR | FILTER_ID_IM | FILTER_ID_LA | FILTER_ID_LS | FILTER_ID_LT | FILTER_ID_MA |
- FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME | FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB |
- FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | FILTER_ID_SPK | FILTER_ID_SO |
- FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF | FILTER_ID_WS |
- FILTER_ID_LP;
-
- if (U.uiflag & USER_HIDE_DOT) {
- params->flag |= FILE_HIDE_DOT;
- }
- else {
- params->flag &= ~FILE_HIDE_DOT;
- }
-
-
- if (params->type == FILE_LOADLIB) {
- params->flag |= RNA_boolean_get(op->ptr, "link") ? FILE_LINK : 0;
- params->flag |= RNA_boolean_get(op->ptr, "autoselect") ? FILE_AUTOSELECT : 0;
- params->flag |= RNA_boolean_get(op->ptr, "active_collection") ? FILE_ACTIVE_COLLECTION : 0;
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "display_type"))) {
- params->display = RNA_property_enum_get(op->ptr, prop);
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "sort_method"))) {
- params->sort = RNA_property_enum_get(op->ptr, prop);
- }
- else {
- params->sort = FILE_SORT_ALPHA;
- }
-
- if (params->display == FILE_DEFAULTDISPLAY) {
- if(params->display_previous == FILE_DEFAULTDISPLAY){
- if (U.uiflag & USER_SHOW_THUMBNAILS) {
- if (params->filter & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT)) {
- params->display = FILE_IMGDISPLAY;
- }
- else {
- params->display = FILE_SHORTDISPLAY;
- }
- }
- else {
- params->display = FILE_SHORTDISPLAY;
- }
- }
- else {
- params->display = params->display_previous;
- }
- }
-
- if (is_relative_path) {
- if ((prop = RNA_struct_find_property(op->ptr, "relative_path"))) {
- if (!RNA_property_is_set_ex(op->ptr, prop, false)) {
- RNA_property_boolean_set(op->ptr, prop, (U.flag & USER_RELPATHS) != 0);
- }
- }
- }
- }
- else {
- /* default values, if no operator */
- params->type = FILE_UNIX;
- params->flag |= FILE_HIDE_DOT;
- params->flag &= ~FILE_DIRSEL_ONLY;
- params->display = FILE_SHORTDISPLAY;
- params->display_previous = FILE_DEFAULTDISPLAY;
- params->sort = FILE_SORT_ALPHA;
- params->filter = 0;
- params->filter_glob[0] = '\0';
- }
-
- /* operator has no setting for this */
- params->active_file = -1;
-
-
- /* initialize the list with previous folders */
- if (!sfile->folders_prev)
- sfile->folders_prev = folderlist_new();
-
- if (!sfile->params->dir[0]) {
- if (blendfile_path[0] != '\0') {
- BLI_split_dir_part(blendfile_path, sfile->params->dir, sizeof(sfile->params->dir));
- }
- else {
- const char *doc_path = BKE_appdir_folder_default();
- if (doc_path) {
- BLI_strncpy(sfile->params->dir, doc_path, sizeof(sfile->params->dir));
- }
- }
- }
-
- folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
-
- /* switching thumbnails needs to recalc layout [#28809] */
- if (sfile->layout) {
- sfile->layout->dirty = true;
- }
-
- return 1;
+ FileSelectParams *params;
+ wmOperator *op = sfile->op;
+
+ const char *blendfile_path = BKE_main_blendfile_path_from_global();
+
+ /* create new parameters if necessary */
+ if (!sfile->params) {
+ sfile->params = MEM_callocN(sizeof(FileSelectParams), "fileselparams");
+ /* set path to most recently opened .blend */
+ BLI_split_dirfile(blendfile_path,
+ sfile->params->dir,
+ sfile->params->file,
+ sizeof(sfile->params->dir),
+ sizeof(sfile->params->file));
+ sfile->params->filter_glob[0] = '\0';
+ /* set the default thumbnails size */
+ sfile->params->thumbnail_size = 128;
+ }
+
+ params = sfile->params;
+
+ /* set the parameters from the operator, if it exists */
+ if (op) {
+ PropertyRNA *prop;
+ const bool is_files = (RNA_struct_find_property(op->ptr, "files") != NULL);
+ const bool is_filepath = (RNA_struct_find_property(op->ptr, "filepath") != NULL);
+ const bool is_filename = (RNA_struct_find_property(op->ptr, "filename") != NULL);
+ const bool is_directory = (RNA_struct_find_property(op->ptr, "directory") != NULL);
+ const bool is_relative_path = (RNA_struct_find_property(op->ptr, "relative_path") != NULL);
+
+ BLI_strncpy_utf8(params->title, RNA_struct_ui_name(op->type->srna), sizeof(params->title));
+
+ if ((prop = RNA_struct_find_property(op->ptr, "filemode"))) {
+ params->type = RNA_property_int_get(op->ptr, prop);
+ }
+ else {
+ params->type = FILE_SPECIAL;
+ }
+
+ if (is_filepath && RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) {
+ char name[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", name);
+ if (params->type == FILE_LOADLIB) {
+ BLI_strncpy(params->dir, name, sizeof(params->dir));
+ sfile->params->file[0] = '\0';
+ }
+ else {
+ BLI_split_dirfile(name,
+ sfile->params->dir,
+ sfile->params->file,
+ sizeof(sfile->params->dir),
+ sizeof(sfile->params->file));
+ }
+ }
+ else {
+ if (is_directory && RNA_struct_property_is_set_ex(op->ptr, "directory", false)) {
+ RNA_string_get(op->ptr, "directory", params->dir);
+ sfile->params->file[0] = '\0';
+ }
+
+ if (is_filename && RNA_struct_property_is_set_ex(op->ptr, "filename", false)) {
+ RNA_string_get(op->ptr, "filename", params->file);
+ }
+ }
+
+ if (params->dir[0]) {
+ BLI_cleanup_dir(blendfile_path, params->dir);
+ BLI_path_abs(params->dir, blendfile_path);
+ }
+
+ if (is_directory == true && is_filename == false && is_filepath == false &&
+ is_files == false) {
+ params->flag |= FILE_DIRSEL_ONLY;
+ }
+ else {
+ params->flag &= ~FILE_DIRSEL_ONLY;
+ }
+
+ params->filter = 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_blender")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BLENDER : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_blenlib")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BLENDERLIB : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_backup")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BLENDER_BACKUP : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_image")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_IMAGE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_movie")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_MOVIE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_python")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_PYSCRIPT : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_font")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_FTFONT : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_sound")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_SOUND : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_text")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_TEXT : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_folder")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_FOLDER : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_btx")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BTX : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_collada")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_COLLADA : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_alembic")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_ALEMBIC : 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(
+ op->ptr, prop, params->filter_glob, sizeof(params->filter_glob), NULL);
+ if (tmp != params->filter_glob) {
+ BLI_strncpy(params->filter_glob, tmp, sizeof(params->filter_glob));
+ MEM_freeN(tmp);
+
+ /* Fix stupid things that truncating might have generated,
+ * like last group being a 'match everything' wildcard-only one... */
+ BLI_path_extension_glob_validate(params->filter_glob);
+ }
+ params->filter |= (FILE_TYPE_OPERATOR | FILE_TYPE_FOLDER);
+ }
+ else {
+ params->filter_glob[0] = '\0';
+ }
+
+ if (params->filter != 0) {
+ if (U.uiflag & USER_FILTERFILEEXTS) {
+ params->flag |= FILE_FILTER;
+ }
+ else {
+ params->flag &= ~FILE_FILTER;
+ }
+ }
+
+ /* For now, always init filterid to 'all true' */
+ params->filter_id = FILTER_ID_AC | FILTER_ID_AR | FILTER_ID_BR | FILTER_ID_CA | FILTER_ID_CU |
+ FILTER_ID_GD | FILTER_ID_GR | FILTER_ID_IM | FILTER_ID_LA | FILTER_ID_LS |
+ FILTER_ID_LT | FILTER_ID_MA | FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME |
+ FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB | FILTER_ID_PA |
+ FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | FILTER_ID_SPK |
+ FILTER_ID_SO | FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO |
+ FILTER_ID_CF | FILTER_ID_WS | FILTER_ID_LP;
+
+ if (U.uiflag & USER_HIDE_DOT) {
+ params->flag |= FILE_HIDE_DOT;
+ }
+ else {
+ params->flag &= ~FILE_HIDE_DOT;
+ }
+
+ if (params->type == FILE_LOADLIB) {
+ params->flag |= RNA_boolean_get(op->ptr, "link") ? FILE_LINK : 0;
+ params->flag |= RNA_boolean_get(op->ptr, "autoselect") ? FILE_AUTOSELECT : 0;
+ params->flag |= RNA_boolean_get(op->ptr, "active_collection") ? FILE_ACTIVE_COLLECTION : 0;
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "display_type"))) {
+ params->display = RNA_property_enum_get(op->ptr, prop);
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "sort_method"))) {
+ params->sort = RNA_property_enum_get(op->ptr, prop);
+ }
+ else {
+ params->sort = FILE_SORT_ALPHA;
+ }
+
+ if (params->display == FILE_DEFAULTDISPLAY) {
+ if (params->display_previous == FILE_DEFAULTDISPLAY) {
+ if (U.uiflag & USER_SHOW_THUMBNAILS) {
+ if (params->filter & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT)) {
+ params->display = FILE_IMGDISPLAY;
+ }
+ else {
+ params->display = FILE_SHORTDISPLAY;
+ }
+ }
+ else {
+ params->display = FILE_SHORTDISPLAY;
+ }
+ }
+ else {
+ params->display = params->display_previous;
+ }
+ }
+
+ if (is_relative_path) {
+ if ((prop = RNA_struct_find_property(op->ptr, "relative_path"))) {
+ if (!RNA_property_is_set_ex(op->ptr, prop, false)) {
+ RNA_property_boolean_set(op->ptr, prop, (U.flag & USER_RELPATHS) != 0);
+ }
+ }
+ }
+ }
+ else {
+ /* default values, if no operator */
+ params->type = FILE_UNIX;
+ params->flag |= FILE_HIDE_DOT;
+ params->flag &= ~FILE_DIRSEL_ONLY;
+ params->display = FILE_SHORTDISPLAY;
+ params->display_previous = FILE_DEFAULTDISPLAY;
+ params->sort = FILE_SORT_ALPHA;
+ params->filter = 0;
+ params->filter_glob[0] = '\0';
+ }
+
+ /* operator has no setting for this */
+ params->active_file = -1;
+
+ /* initialize the list with previous folders */
+ if (!sfile->folders_prev)
+ sfile->folders_prev = folderlist_new();
+
+ if (!sfile->params->dir[0]) {
+ if (blendfile_path[0] != '\0') {
+ BLI_split_dir_part(blendfile_path, sfile->params->dir, sizeof(sfile->params->dir));
+ }
+ else {
+ const char *doc_path = BKE_appdir_folder_default();
+ if (doc_path) {
+ BLI_strncpy(sfile->params->dir, doc_path, sizeof(sfile->params->dir));
+ }
+ }
+ }
+
+ folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
+
+ /* switching thumbnails needs to recalc layout [#28809] */
+ if (sfile->layout) {
+ sfile->layout->dirty = true;
+ }
+
+ return 1;
}
void ED_fileselect_reset_params(SpaceFile *sfile)
{
- sfile->params->type = FILE_UNIX;
- sfile->params->flag = 0;
- sfile->params->title[0] = '\0';
- sfile->params->active_file = -1;
+ sfile->params->type = FILE_UNIX;
+ sfile->params->flag = 0;
+ sfile->params->title[0] = '\0';
+ sfile->params->active_file = -1;
}
/**
@@ -321,458 +328,467 @@ void ED_fileselect_reset_params(SpaceFile *sfile)
*/
void fileselect_file_set(SpaceFile *sfile, const int index)
{
- const struct FileDirEntry *file = filelist_file(sfile->files, index);
- if (file && file->relpath && file->relpath[0] && !(file->typeflag & FILE_TYPE_FOLDER)) {
- BLI_strncpy(sfile->params->file, file->relpath, FILE_MAXFILE);
- }
+ const struct FileDirEntry *file = filelist_file(sfile->files, index);
+ if (file && file->relpath && file->relpath[0] && !(file->typeflag & FILE_TYPE_FOLDER)) {
+ BLI_strncpy(sfile->params->file, file->relpath, FILE_MAXFILE);
+ }
}
int ED_fileselect_layout_numfiles(FileLayout *layout, ARegion *ar)
{
- int numfiles;
-
- /* Values in pixels.
- *
- * - *_item: size of each (row|col), (including padding)
- * - *_view: (x|y) size of the view.
- * - *_over: extra pixels, to take into account, when the fit isnt exact
- * (needed since you may see the end of the previous column and the beginning of the next).
- *
- * Could be more clever and take scrolling into account,
- * but for now don't bother.
- */
- 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_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));
- const int y_over = y_item - (y_view % y_item);
- numfiles = (int)((float)(y_view + y_over) / (float)(y_item));
- return numfiles * layout->columns;
- }
+ int numfiles;
+
+ /* Values in pixels.
+ *
+ * - *_item: size of each (row|col), (including padding)
+ * - *_view: (x|y) size of the view.
+ * - *_over: extra pixels, to take into account, when the fit isnt exact
+ * (needed since you may see the end of the previous column and the beginning of the next).
+ *
+ * Could be more clever and take scrolling into account,
+ * but for now don't bother.
+ */
+ 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_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));
+ const int y_over = y_item - (y_view % y_item);
+ numfiles = (int)((float)(y_view + y_over) / (float)(y_item));
+ return numfiles * layout->columns;
+ }
}
static bool is_inside(int x, int y, int cols, int rows)
{
- return ((x >= 0) && (x < cols) && (y >= 0) && (y < rows));
+ return ((x >= 0) && (x < cols) && (y >= 0) && (y < rows));
}
FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const rcti *rect)
{
- int colmin, colmax, rowmin, rowmax;
- FileSelection sel;
- sel.first = sel.last = -1;
-
- if (layout == NULL)
- return sel;
-
- colmin = (rect->xmin) / (layout->tile_w + 2 * layout->tile_border_x);
- rowmin = (rect->ymin) / (layout->tile_h + 2 * layout->tile_border_y);
- colmax = (rect->xmax) / (layout->tile_w + 2 * layout->tile_border_x);
- rowmax = (rect->ymax) / (layout->tile_h + 2 * layout->tile_border_y);
-
- if (is_inside(colmin, rowmin, layout->columns, layout->rows) ||
- is_inside(colmax, rowmax, layout->columns, layout->rows) )
- {
- CLAMP(colmin, 0, layout->columns - 1);
- CLAMP(rowmin, 0, layout->rows - 1);
- CLAMP(colmax, 0, layout->columns - 1);
- CLAMP(rowmax, 0, layout->rows - 1);
- }
-
- if ((colmin > layout->columns - 1) || (rowmin > layout->rows - 1)) {
- sel.first = -1;
- }
- else {
- if (layout->flag & FILE_LAYOUT_HOR)
- sel.first = layout->rows * colmin + rowmin;
- else
- sel.first = colmin + layout->columns * rowmin;
- }
- if ((colmax > layout->columns - 1) || (rowmax > layout->rows - 1)) {
- sel.last = -1;
- }
- else {
- if (layout->flag & FILE_LAYOUT_HOR)
- sel.last = layout->rows * colmax + rowmax;
- else
- sel.last = colmax + layout->columns * rowmax;
- }
-
- return sel;
+ int colmin, colmax, rowmin, rowmax;
+ FileSelection sel;
+ sel.first = sel.last = -1;
+
+ if (layout == NULL)
+ return sel;
+
+ colmin = (rect->xmin) / (layout->tile_w + 2 * layout->tile_border_x);
+ rowmin = (rect->ymin) / (layout->tile_h + 2 * layout->tile_border_y);
+ colmax = (rect->xmax) / (layout->tile_w + 2 * layout->tile_border_x);
+ rowmax = (rect->ymax) / (layout->tile_h + 2 * layout->tile_border_y);
+
+ if (is_inside(colmin, rowmin, layout->columns, layout->rows) ||
+ is_inside(colmax, rowmax, layout->columns, layout->rows)) {
+ CLAMP(colmin, 0, layout->columns - 1);
+ CLAMP(rowmin, 0, layout->rows - 1);
+ CLAMP(colmax, 0, layout->columns - 1);
+ CLAMP(rowmax, 0, layout->rows - 1);
+ }
+
+ if ((colmin > layout->columns - 1) || (rowmin > layout->rows - 1)) {
+ sel.first = -1;
+ }
+ else {
+ if (layout->flag & FILE_LAYOUT_HOR)
+ sel.first = layout->rows * colmin + rowmin;
+ else
+ sel.first = colmin + layout->columns * rowmin;
+ }
+ if ((colmax > layout->columns - 1) || (rowmax > layout->rows - 1)) {
+ sel.last = -1;
+ }
+ else {
+ if (layout->flag & FILE_LAYOUT_HOR)
+ sel.last = layout->rows * colmax + rowmax;
+ else
+ sel.last = colmax + layout->columns * rowmax;
+ }
+
+ return sel;
}
int ED_fileselect_layout_offset(FileLayout *layout, int x, int y)
{
- int offsetx, offsety;
- int active_file;
+ int offsetx, offsety;
+ int active_file;
- if (layout == NULL)
- return -1;
+ if (layout == NULL)
+ return -1;
- offsetx = (x) / (layout->tile_w + 2 * layout->tile_border_x);
- offsety = (y) / (layout->tile_h + 2 * layout->tile_border_y);
+ offsetx = (x) / (layout->tile_w + 2 * layout->tile_border_x);
+ offsety = (y) / (layout->tile_h + 2 * layout->tile_border_y);
- if (offsetx > layout->columns - 1) return -1;
- if (offsety > layout->rows - 1) return -1;
+ if (offsetx > layout->columns - 1)
+ return -1;
+ if (offsety > layout->rows - 1)
+ return -1;
- if (layout->flag & FILE_LAYOUT_HOR)
- active_file = layout->rows * offsetx + offsety;
- else
- active_file = offsetx + layout->columns * offsety;
- return active_file;
+ if (layout->flag & FILE_LAYOUT_HOR)
+ active_file = layout->rows * offsetx + offsety;
+ else
+ active_file = offsetx + layout->columns * offsety;
+ return active_file;
}
void ED_fileselect_layout_tilepos(FileLayout *layout, int tile, int *x, int *y)
{
- if (layout->flag == FILE_LAYOUT_HOR) {
- *x = layout->tile_border_x + (tile / layout->rows) * (layout->tile_w + 2 * layout->tile_border_x);
- *y = layout->tile_border_y + (tile % layout->rows) * (layout->tile_h + 2 * layout->tile_border_y);
- }
- else {
- *x = layout->tile_border_x + ((tile) % layout->columns) * (layout->tile_w + 2 * layout->tile_border_x);
- *y = layout->tile_border_y + ((tile) / layout->columns) * (layout->tile_h + 2 * layout->tile_border_y);
- }
+ if (layout->flag == FILE_LAYOUT_HOR) {
+ *x = layout->tile_border_x +
+ (tile / layout->rows) * (layout->tile_w + 2 * layout->tile_border_x);
+ *y = layout->tile_border_y +
+ (tile % layout->rows) * (layout->tile_h + 2 * layout->tile_border_y);
+ }
+ else {
+ *x = layout->tile_border_x +
+ ((tile) % layout->columns) * (layout->tile_w + 2 * layout->tile_border_x);
+ *y = layout->tile_border_y +
+ ((tile) / layout->columns) * (layout->tile_h + 2 * layout->tile_border_y);
+ }
}
float file_string_width(const char *str)
{
- uiStyle *style = UI_style_get();
- float width;
+ uiStyle *style = UI_style_get();
+ float width;
- UI_fontstyle_set(&style->widget);
- if (style->widget.kerning == 1) { /* for BLF_width */
- BLF_enable(style->widget.uifont_id, BLF_KERNING_DEFAULT);
- }
+ UI_fontstyle_set(&style->widget);
+ if (style->widget.kerning == 1) { /* for BLF_width */
+ BLF_enable(style->widget.uifont_id, BLF_KERNING_DEFAULT);
+ }
- width = BLF_width(style->widget.uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+ width = BLF_width(style->widget.uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
- if (style->widget.kerning == 1) {
- BLF_disable(style->widget.uifont_id, BLF_KERNING_DEFAULT);
- }
+ if (style->widget.kerning == 1) {
+ BLF_disable(style->widget.uifont_id, BLF_KERNING_DEFAULT);
+ }
- return width;
+ return width;
}
float file_font_pointsize(void)
{
#if 0
- float s;
- char tmp[2] = "X";
- uiStyle *style = UI_style_get();
- UI_fontstyle_set(&style->widget);
- s = BLF_height(style->widget.uifont_id, tmp);
- return style->widget.points;
+ float s;
+ char tmp[2] = "X";
+ 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();
- UI_fontstyle_set(&style->widget);
- return style->widget.points * UI_DPI_FAC;
+ uiStyle *style = UI_style_get();
+ UI_fontstyle_set(&style->widget);
+ return style->widget.points * UI_DPI_FAC;
#endif
}
static void column_widths(FileSelectParams *params, struct FileLayout *layout)
{
- int i;
- const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size);
-
- for (i = 0; i < MAX_FILE_COLUMN; ++i) {
- layout->column_widths[i] = 0;
- }
-
- layout->column_widths[COLUMN_NAME] = ((float)params->thumbnail_size / 8.0f) * UI_UNIT_X;
- /* Biggest possible reasonable values... */
- layout->column_widths[COLUMN_DATE] = file_string_width(small_size ? "23/08/89" : "23-Dec-89");
- layout->column_widths[COLUMN_TIME] = file_string_width("23:59");
- layout->column_widths[COLUMN_SIZE] = file_string_width(small_size ? "98.7 M" : "98.7 MiB");
+ int i;
+ const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size);
+
+ for (i = 0; i < MAX_FILE_COLUMN; ++i) {
+ layout->column_widths[i] = 0;
+ }
+
+ layout->column_widths[COLUMN_NAME] = ((float)params->thumbnail_size / 8.0f) * UI_UNIT_X;
+ /* Biggest possible reasonable values... */
+ layout->column_widths[COLUMN_DATE] = file_string_width(small_size ? "23/08/89" : "23-Dec-89");
+ layout->column_widths[COLUMN_TIME] = file_string_width("23:59");
+ layout->column_widths[COLUMN_SIZE] = file_string_width(small_size ? "98.7 M" : "98.7 MiB");
}
void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
{
- FileSelectParams *params = ED_fileselect_get_params(sfile);
- FileLayout *layout = NULL;
- View2D *v2d = &ar->v2d;
- int maxlen = 0;
- int numfiles;
- int textheight;
-
- if (sfile->layout == NULL) {
- sfile->layout = MEM_callocN(sizeof(struct FileLayout), "file_layout");
- sfile->layout->dirty = true;
- }
- else if (sfile->layout->dirty == false) {
- return;
- }
-
- numfiles = filelist_files_ensure(sfile->files);
- textheight = (int)file_font_pointsize();
- layout = sfile->layout;
- layout->textheight = textheight;
-
- if (params->display == FILE_IMGDISPLAY) {
- layout->prv_w = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_X;
- layout->prv_h = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_Y;
- layout->tile_border_x = 0.3f * UI_UNIT_X;
- layout->tile_border_y = 0.3f * UI_UNIT_X;
- layout->prv_border_x = 0.3f * UI_UNIT_X;
- layout->prv_border_y = 0.3f * UI_UNIT_Y;
- layout->tile_w = layout->prv_w + 2 * layout->prv_border_x;
- layout->tile_h = layout->prv_h + 2 * layout->prv_border_y + textheight;
- layout->width = (int)(BLI_rctf_size_x(&v2d->cur) - 2 * layout->tile_border_x);
- layout->columns = layout->width / (layout->tile_w + 2 * layout->tile_border_x);
- if (layout->columns > 0)
- layout->rows = numfiles / layout->columns + 1; // XXX dirty, modulo is zero
- else {
- layout->columns = 1;
- layout->rows = numfiles + 1; // XXX dirty, modulo is zero
- }
- layout->height = sfile->layout->rows * (layout->tile_h + 2 * layout->tile_border_y) + layout->tile_border_y * 2;
- layout->flag = FILE_LAYOUT_VER;
- }
- else {
- int column_space = 0.6f * UI_UNIT_X;
- int column_icon_space = 0.2f * UI_UNIT_X;
-
- layout->prv_w = 0;
- layout->prv_h = 0;
- layout->tile_border_x = 0.4f * UI_UNIT_X;
- layout->tile_border_y = 0.1f * UI_UNIT_Y;
- layout->prv_border_x = 0;
- layout->prv_border_y = 0;
- layout->tile_h = textheight * 3 / 2;
- layout->height = (int)(BLI_rctf_size_y(&v2d->cur) - 2 * layout->tile_border_y);
- /* Padding by full scrollbar H is too much, can overlap tile border Y. */
- layout->rows = (layout->height - V2D_SCROLL_HEIGHT + layout->tile_border_y) /
- (layout->tile_h + 2 * layout->tile_border_y);
-
- column_widths(params, layout);
-
- if (params->display == FILE_SHORTDISPLAY) {
- maxlen = ICON_DEFAULT_WIDTH_SCALE + column_icon_space +
- (int)layout->column_widths[COLUMN_NAME] + column_space +
- (int)layout->column_widths[COLUMN_SIZE] + column_space;
- }
- else {
- maxlen = ICON_DEFAULT_WIDTH_SCALE + column_icon_space +
- (int)layout->column_widths[COLUMN_NAME] + column_space +
- (int)layout->column_widths[COLUMN_DATE] + column_space +
- (int)layout->column_widths[COLUMN_TIME] + column_space +
- (int)layout->column_widths[COLUMN_SIZE] + column_space;
- }
- layout->tile_w = maxlen;
- if (layout->rows > 0)
- layout->columns = numfiles / layout->rows + 1; // XXX dirty, modulo is zero
- else {
- layout->rows = 1;
- layout->columns = numfiles + 1; // XXX dirty, modulo is zero
- }
- layout->width = sfile->layout->columns * (layout->tile_w + 2 * layout->tile_border_x) + layout->tile_border_x * 2;
- layout->flag = FILE_LAYOUT_HOR;
- }
- params->display_previous = params->display;
- layout->dirty = false;
+ FileSelectParams *params = ED_fileselect_get_params(sfile);
+ FileLayout *layout = NULL;
+ View2D *v2d = &ar->v2d;
+ int maxlen = 0;
+ int numfiles;
+ int textheight;
+
+ if (sfile->layout == NULL) {
+ sfile->layout = MEM_callocN(sizeof(struct FileLayout), "file_layout");
+ sfile->layout->dirty = true;
+ }
+ else if (sfile->layout->dirty == false) {
+ return;
+ }
+
+ numfiles = filelist_files_ensure(sfile->files);
+ textheight = (int)file_font_pointsize();
+ layout = sfile->layout;
+ layout->textheight = textheight;
+
+ if (params->display == FILE_IMGDISPLAY) {
+ layout->prv_w = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_X;
+ layout->prv_h = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_Y;
+ layout->tile_border_x = 0.3f * UI_UNIT_X;
+ layout->tile_border_y = 0.3f * UI_UNIT_X;
+ layout->prv_border_x = 0.3f * UI_UNIT_X;
+ layout->prv_border_y = 0.3f * UI_UNIT_Y;
+ layout->tile_w = layout->prv_w + 2 * layout->prv_border_x;
+ layout->tile_h = layout->prv_h + 2 * layout->prv_border_y + textheight;
+ layout->width = (int)(BLI_rctf_size_x(&v2d->cur) - 2 * layout->tile_border_x);
+ layout->columns = layout->width / (layout->tile_w + 2 * layout->tile_border_x);
+ if (layout->columns > 0)
+ layout->rows = numfiles / layout->columns + 1; // XXX dirty, modulo is zero
+ else {
+ layout->columns = 1;
+ layout->rows = numfiles + 1; // XXX dirty, modulo is zero
+ }
+ layout->height = sfile->layout->rows * (layout->tile_h + 2 * layout->tile_border_y) +
+ layout->tile_border_y * 2;
+ layout->flag = FILE_LAYOUT_VER;
+ }
+ else {
+ int column_space = 0.6f * UI_UNIT_X;
+ int column_icon_space = 0.2f * UI_UNIT_X;
+
+ layout->prv_w = 0;
+ layout->prv_h = 0;
+ layout->tile_border_x = 0.4f * UI_UNIT_X;
+ layout->tile_border_y = 0.1f * UI_UNIT_Y;
+ layout->prv_border_x = 0;
+ layout->prv_border_y = 0;
+ layout->tile_h = textheight * 3 / 2;
+ layout->height = (int)(BLI_rctf_size_y(&v2d->cur) - 2 * layout->tile_border_y);
+ /* Padding by full scrollbar H is too much, can overlap tile border Y. */
+ layout->rows = (layout->height - V2D_SCROLL_HEIGHT + layout->tile_border_y) /
+ (layout->tile_h + 2 * layout->tile_border_y);
+
+ column_widths(params, layout);
+
+ if (params->display == FILE_SHORTDISPLAY) {
+ maxlen = ICON_DEFAULT_WIDTH_SCALE + column_icon_space +
+ (int)layout->column_widths[COLUMN_NAME] + column_space +
+ (int)layout->column_widths[COLUMN_SIZE] + column_space;
+ }
+ else {
+ maxlen = ICON_DEFAULT_WIDTH_SCALE + column_icon_space +
+ (int)layout->column_widths[COLUMN_NAME] + column_space +
+ (int)layout->column_widths[COLUMN_DATE] + column_space +
+ (int)layout->column_widths[COLUMN_TIME] + column_space +
+ (int)layout->column_widths[COLUMN_SIZE] + column_space;
+ }
+ layout->tile_w = maxlen;
+ if (layout->rows > 0)
+ layout->columns = numfiles / layout->rows + 1; // XXX dirty, modulo is zero
+ else {
+ layout->rows = 1;
+ layout->columns = numfiles + 1; // XXX dirty, modulo is zero
+ }
+ layout->width = sfile->layout->columns * (layout->tile_w + 2 * layout->tile_border_x) +
+ layout->tile_border_x * 2;
+ layout->flag = FILE_LAYOUT_HOR;
+ }
+ params->display_previous = params->display;
+ layout->dirty = false;
}
FileLayout *ED_fileselect_get_layout(struct SpaceFile *sfile, ARegion *ar)
{
- if (!sfile->layout) {
- ED_fileselect_init_layout(sfile, ar);
- }
- return sfile->layout;
+ if (!sfile->layout) {
+ ED_fileselect_init_layout(sfile, ar);
+ }
+ return sfile->layout;
}
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);
+ 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);
+ if (sfile->params) {
+ ED_fileselect_clear(wm, sa, 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! */
- sfile->params->filter_search[0] = '\0';
- sfile->params->active_file = -1;
+ /* Clear search string, it is very rare to want to keep that filter while changing dir,
+ * and usually very annoying to keep it actually! */
+ sfile->params->filter_search[0] = '\0';
+ sfile->params->active_file = -1;
- if (!filelist_is_dir(sfile->files, sfile->params->dir)) {
- BLI_strncpy(sfile->params->dir, filelist_dir(sfile->files), sizeof(sfile->params->dir));
- /* could return but just refresh the current dir */
- }
- filelist_setdir(sfile->files, sfile->params->dir);
+ if (!filelist_is_dir(sfile->files, sfile->params->dir)) {
+ BLI_strncpy(sfile->params->dir, filelist_dir(sfile->files), sizeof(sfile->params->dir));
+ /* could return but just refresh the current dir */
+ }
+ filelist_setdir(sfile->files, sfile->params->dir);
- if (folderlist_clear_next(sfile))
- folderlist_free(sfile->folders_next);
+ if (folderlist_clear_next(sfile))
+ folderlist_free(sfile->folders_next);
- folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
+ folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
- file_draw_check(C);
- }
+ file_draw_check(C);
+ }
}
int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matched_file)
{
- int match = 0;
-
- int i;
- FileDirEntry *file;
- int n = filelist_files_ensure(sfile->files);
-
- /* select any file that matches the pattern, this includes exact match
- * if the user selects a single file by entering the filename
- */
- for (i = 0; i < n; i++) {
- file = filelist_file(sfile->files, i);
- /* Do not check whether file is a file or dir here! Causes T44243
- * (we do accept dirs at this stage). */
- if (fnmatch(pattern, file->relpath, 0) == 0) {
- filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
- if (!match) {
- BLI_strncpy(matched_file, file->relpath, FILE_MAX);
- }
- match++;
- }
- }
-
- return match;
+ int match = 0;
+
+ int i;
+ FileDirEntry *file;
+ int n = filelist_files_ensure(sfile->files);
+
+ /* select any file that matches the pattern, this includes exact match
+ * if the user selects a single file by entering the filename
+ */
+ for (i = 0; i < n; i++) {
+ file = filelist_file(sfile->files, i);
+ /* Do not check whether file is a file or dir here! Causes T44243
+ * (we do accept dirs at this stage). */
+ if (fnmatch(pattern, file->relpath, 0) == 0) {
+ filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
+ if (!match) {
+ BLI_strncpy(matched_file, file->relpath, FILE_MAX);
+ }
+ match++;
+ }
+ }
+
+ return match;
}
int autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v))
{
- SpaceFile *sfile = CTX_wm_space_file(C);
- int match = AUTOCOMPLETE_NO_MATCH;
-
- /* search if str matches the beginning of name */
- if (str[0] && sfile->files) {
- char dirname[FILE_MAX];
-
- DIR *dir;
- struct dirent *de;
-
- BLI_split_dir_part(str, dirname, sizeof(dirname));
-
- dir = opendir(dirname);
-
- if (dir) {
- AutoComplete *autocpl = UI_autocomplete_begin(str, FILE_MAX);
-
- while ((de = readdir(dir)) != NULL) {
- if (FILENAME_IS_CURRPAR(de->d_name)) {
- /* pass */
- }
- else {
- char path[FILE_MAX];
- BLI_stat_t status;
-
- BLI_join_dirfile(path, sizeof(path), dirname, de->d_name);
-
- if (BLI_stat(path, &status) == 0) {
- if (S_ISDIR(status.st_mode)) { /* is subdir */
- UI_autocomplete_update_name(autocpl, path);
- }
- }
- }
- }
- closedir(dir);
-
- match = UI_autocomplete_end(autocpl, str);
- if (match == AUTOCOMPLETE_FULL_MATCH) {
- BLI_add_slash(str);
- }
- }
- }
-
- return match;
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ int match = AUTOCOMPLETE_NO_MATCH;
+
+ /* search if str matches the beginning of name */
+ if (str[0] && sfile->files) {
+ char dirname[FILE_MAX];
+
+ DIR *dir;
+ struct dirent *de;
+
+ BLI_split_dir_part(str, dirname, sizeof(dirname));
+
+ dir = opendir(dirname);
+
+ if (dir) {
+ AutoComplete *autocpl = UI_autocomplete_begin(str, FILE_MAX);
+
+ while ((de = readdir(dir)) != NULL) {
+ if (FILENAME_IS_CURRPAR(de->d_name)) {
+ /* pass */
+ }
+ else {
+ char path[FILE_MAX];
+ BLI_stat_t status;
+
+ BLI_join_dirfile(path, sizeof(path), dirname, de->d_name);
+
+ if (BLI_stat(path, &status) == 0) {
+ if (S_ISDIR(status.st_mode)) { /* is subdir */
+ UI_autocomplete_update_name(autocpl, path);
+ }
+ }
+ }
+ }
+ closedir(dir);
+
+ match = UI_autocomplete_end(autocpl, str);
+ if (match == AUTOCOMPLETE_FULL_MATCH) {
+ BLI_add_slash(str);
+ }
+ }
+ }
+
+ return match;
}
int autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v))
{
- SpaceFile *sfile = CTX_wm_space_file(C);
- int match = AUTOCOMPLETE_NO_MATCH;
-
- /* search if str matches the beginning of name */
- if (str[0] && sfile->files) {
- AutoComplete *autocpl = UI_autocomplete_begin(str, FILE_MAX);
- int nentries = filelist_files_ensure(sfile->files);
- int i;
-
- for (i = 0; i < nentries; ++i) {
- FileDirEntry *file = filelist_file(sfile->files, i);
- UI_autocomplete_update_name(autocpl, file->relpath);
- }
- match = UI_autocomplete_end(autocpl, str);
- }
-
- return match;
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ int match = AUTOCOMPLETE_NO_MATCH;
+
+ /* search if str matches the beginning of name */
+ if (str[0] && sfile->files) {
+ AutoComplete *autocpl = UI_autocomplete_begin(str, FILE_MAX);
+ int nentries = filelist_files_ensure(sfile->files);
+ int i;
+
+ for (i = 0; i < nentries; ++i) {
+ FileDirEntry *file = filelist_file(sfile->files, i);
+ UI_autocomplete_update_name(autocpl, file->relpath);
+ }
+ match = UI_autocomplete_end(autocpl, str);
+ }
+
+ return match;
}
void ED_fileselect_clear(wmWindowManager *wm, ScrArea *sa, SpaceFile *sfile)
{
- /* only NULL in rare cases - [#29734] */
- if (sfile->files) {
- filelist_readjob_stop(wm, sa);
- filelist_freelib(sfile->files);
- filelist_clear(sfile->files);
- }
-
- sfile->params->highlight_file = -1;
- WM_main_add_notifier(NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+ /* only NULL in rare cases - [#29734] */
+ if (sfile->files) {
+ filelist_readjob_stop(wm, sa);
+ filelist_freelib(sfile->files);
+ filelist_clear(sfile->files);
+ }
+
+ sfile->params->highlight_file = -1;
+ WM_main_add_notifier(NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
void ED_fileselect_exit(wmWindowManager *wm, ScrArea *sa, SpaceFile *sfile)
{
- if (!sfile) return;
- if (sfile->op) {
- WM_event_fileselect_event(wm, sfile->op, EVT_FILESELECT_EXTERNAL_CANCEL);
- sfile->op = NULL;
- }
-
- folderlist_free(sfile->folders_prev);
- folderlist_free(sfile->folders_next);
-
- if (sfile->files) {
- ED_fileselect_clear(wm, sa, sfile);
- filelist_free(sfile->files);
- MEM_freeN(sfile->files);
- sfile->files = NULL;
- }
+ if (!sfile)
+ return;
+ if (sfile->op) {
+ WM_event_fileselect_event(wm, sfile->op, EVT_FILESELECT_EXTERNAL_CANCEL);
+ sfile->op = NULL;
+ }
+
+ folderlist_free(sfile->folders_prev);
+ folderlist_free(sfile->folders_next);
+
+ if (sfile->files) {
+ ED_fileselect_clear(wm, sa, sfile);
+ filelist_free(sfile->files);
+ MEM_freeN(sfile->files);
+ sfile->files = NULL;
+ }
}
/** Helper used by both main update code, and smoothscroll timer, to try to enable rename editing from
* params->renamefile name. */
void file_params_renamefile_activate(SpaceFile *sfile, FileSelectParams *params)
{
- BLI_assert(params->rename_flag != 0);
-
- if ((params->rename_flag & (FILE_PARAMS_RENAME_ACTIVE | FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE)) != 0) {
- return;
- }
-
- BLI_assert(params->renamefile[0] != '\0');
-
- const int idx = filelist_file_findpath(sfile->files, params->renamefile);
- if (idx >= 0) {
- FileDirEntry *file = filelist_file(sfile->files, idx);
- BLI_assert(file != NULL);
-
- if ((params->rename_flag & FILE_PARAMS_RENAME_PENDING) != 0) {
- filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL);
- params->rename_flag = FILE_PARAMS_RENAME_ACTIVE;
- }
- else if ((params->rename_flag & FILE_PARAMS_RENAME_POSTSCROLL_PENDING) != 0) {
- filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_HIGHLIGHTED, CHECK_ALL);
- params->renamefile[0] = '\0';
- params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE;
- }
- }
- /* File listing is now async, only reset renaming if matching entry is not found
- * when file listing is not done. */
- else if (filelist_is_ready(sfile->files)) {
- params->renamefile[0] = '\0';
- params->rename_flag = 0;
- }
+ BLI_assert(params->rename_flag != 0);
+
+ if ((params->rename_flag & (FILE_PARAMS_RENAME_ACTIVE | FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE)) !=
+ 0) {
+ return;
+ }
+
+ BLI_assert(params->renamefile[0] != '\0');
+
+ const int idx = filelist_file_findpath(sfile->files, params->renamefile);
+ if (idx >= 0) {
+ FileDirEntry *file = filelist_file(sfile->files, idx);
+ BLI_assert(file != NULL);
+
+ if ((params->rename_flag & FILE_PARAMS_RENAME_PENDING) != 0) {
+ filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL);
+ params->rename_flag = FILE_PARAMS_RENAME_ACTIVE;
+ }
+ else if ((params->rename_flag & FILE_PARAMS_RENAME_POSTSCROLL_PENDING) != 0) {
+ filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_HIGHLIGHTED, CHECK_ALL);
+ params->renamefile[0] = '\0';
+ params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE;
+ }
+ }
+ /* File listing is now async, only reset renaming if matching entry is not found
+ * when file listing is not done. */
+ else if (filelist_is_ready(sfile->files)) {
+ params->renamefile[0] = '\0';
+ params->rename_flag = 0;
+ }
}
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index c3c85600121..f14148abe86 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -21,7 +21,6 @@
* \ingroup spfile
*/
-
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@@ -37,698 +36,721 @@
#include "ED_fileselect.h"
#ifdef WIN32
- /* Need to include windows.h so _WIN32_IE is defined. */
+/* Need to include windows.h so _WIN32_IE is defined. */
# include <windows.h>
- /* For SHGetSpecialFolderPath, has to be done before BLI_winstuff
+/* For SHGetSpecialFolderPath, has to be done before BLI_winstuff
* because 'near' is disabled through BLI_windstuff. */
# include <shlobj.h>
# include "BLI_winstuff.h"
#endif
#ifdef __APPLE__
-#include <Carbon/Carbon.h>
+# include <Carbon/Carbon.h>
#endif /* __APPLE__ */
#ifdef __linux__
-#include <mntent.h>
-#include "BLI_fileops_types.h"
+# include <mntent.h>
+# include "BLI_fileops_types.h"
#endif
-#include "fsmenu.h" /* include ourselves */
-
+#include "fsmenu.h" /* include ourselves */
/* FSMENU HANDLING */
typedef struct FSMenu {
- FSMenuEntry *fsmenu_system;
- FSMenuEntry *fsmenu_system_bookmarks;
- FSMenuEntry *fsmenu_bookmarks;
- FSMenuEntry *fsmenu_recent;
+ FSMenuEntry *fsmenu_system;
+ FSMenuEntry *fsmenu_system_bookmarks;
+ FSMenuEntry *fsmenu_bookmarks;
+ FSMenuEntry *fsmenu_recent;
} FSMenu;
static FSMenu *g_fsmenu = NULL;
FSMenu *ED_fsmenu_get(void)
{
- if (!g_fsmenu) {
- g_fsmenu = MEM_callocN(sizeof(struct FSMenu), "fsmenu");
- }
- return g_fsmenu;
+ if (!g_fsmenu) {
+ g_fsmenu = MEM_callocN(sizeof(struct FSMenu), "fsmenu");
+ }
+ return g_fsmenu;
}
struct FSMenuEntry *ED_fsmenu_get_category(struct FSMenu *fsmenu, FSMenuCategory category)
{
- FSMenuEntry *fsm_head = NULL;
-
- switch (category) {
- case FS_CATEGORY_SYSTEM:
- fsm_head = fsmenu->fsmenu_system;
- break;
- case FS_CATEGORY_SYSTEM_BOOKMARKS:
- fsm_head = fsmenu->fsmenu_system_bookmarks;
- break;
- case FS_CATEGORY_BOOKMARKS:
- fsm_head = fsmenu->fsmenu_bookmarks;
- break;
- case FS_CATEGORY_RECENT:
- fsm_head = fsmenu->fsmenu_recent;
- break;
- }
- return fsm_head;
+ FSMenuEntry *fsm_head = NULL;
+
+ switch (category) {
+ case FS_CATEGORY_SYSTEM:
+ fsm_head = fsmenu->fsmenu_system;
+ break;
+ case FS_CATEGORY_SYSTEM_BOOKMARKS:
+ fsm_head = fsmenu->fsmenu_system_bookmarks;
+ break;
+ case FS_CATEGORY_BOOKMARKS:
+ fsm_head = fsmenu->fsmenu_bookmarks;
+ break;
+ case FS_CATEGORY_RECENT:
+ fsm_head = fsmenu->fsmenu_recent;
+ break;
+ }
+ return fsm_head;
}
void ED_fsmenu_set_category(struct FSMenu *fsmenu, FSMenuCategory category, FSMenuEntry *fsm_head)
{
- switch (category) {
- case FS_CATEGORY_SYSTEM:
- fsmenu->fsmenu_system = fsm_head;
- break;
- case FS_CATEGORY_SYSTEM_BOOKMARKS:
- fsmenu->fsmenu_system_bookmarks = fsm_head;
- break;
- case FS_CATEGORY_BOOKMARKS:
- fsmenu->fsmenu_bookmarks = fsm_head;
- break;
- case FS_CATEGORY_RECENT:
- fsmenu->fsmenu_recent = fsm_head;
- break;
- }
+ switch (category) {
+ case FS_CATEGORY_SYSTEM:
+ fsmenu->fsmenu_system = fsm_head;
+ break;
+ case FS_CATEGORY_SYSTEM_BOOKMARKS:
+ fsmenu->fsmenu_system_bookmarks = fsm_head;
+ break;
+ case FS_CATEGORY_BOOKMARKS:
+ fsmenu->fsmenu_bookmarks = fsm_head;
+ break;
+ case FS_CATEGORY_RECENT:
+ fsmenu->fsmenu_recent = fsm_head;
+ break;
+ }
}
int ED_fsmenu_get_nentries(struct FSMenu *fsmenu, FSMenuCategory category)
{
- FSMenuEntry *fsm_iter;
- int count = 0;
+ FSMenuEntry *fsm_iter;
+ int count = 0;
- for (fsm_iter = ED_fsmenu_get_category(fsmenu, category); fsm_iter; fsm_iter = fsm_iter->next) {
- count++;
- }
+ for (fsm_iter = ED_fsmenu_get_category(fsmenu, category); fsm_iter; fsm_iter = fsm_iter->next) {
+ count++;
+ }
- return count;
+ return count;
}
FSMenuEntry *ED_fsmenu_get_entry(struct FSMenu *fsmenu, FSMenuCategory category, int index)
{
- FSMenuEntry *fsm_iter;
+ FSMenuEntry *fsm_iter;
- for (fsm_iter = ED_fsmenu_get_category(fsmenu, category); fsm_iter && index; fsm_iter = fsm_iter->next) {
- index--;
- }
+ for (fsm_iter = ED_fsmenu_get_category(fsmenu, category); fsm_iter && index;
+ fsm_iter = fsm_iter->next) {
+ index--;
+ }
- return fsm_iter;
+ return fsm_iter;
}
char *ED_fsmenu_entry_get_path(struct FSMenuEntry *fsentry)
{
- return fsentry->path;
+ return fsentry->path;
}
void ED_fsmenu_entry_set_path(struct FSMenuEntry *fsentry, const char *path)
{
- if ((!fsentry->path || !path || !STREQ(path, fsentry->path)) && (fsentry->path != path)) {
- char tmp_name[FILE_MAXFILE];
+ if ((!fsentry->path || !path || !STREQ(path, fsentry->path)) && (fsentry->path != path)) {
+ char tmp_name[FILE_MAXFILE];
- MEM_SAFE_FREE(fsentry->path);
+ MEM_SAFE_FREE(fsentry->path);
- fsentry->path = (path && path[0]) ? BLI_strdup(path) : NULL;
+ 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);
- fsmenu_write_file(ED_fsmenu_get(), tmp_name);
- }
+ BLI_make_file_string("/",
+ tmp_name,
+ BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL),
+ BLENDER_BOOKMARK_FILE);
+ fsmenu_write_file(ED_fsmenu_get(), tmp_name);
+ }
}
static void fsmenu_entry_generate_name(struct FSMenuEntry *fsentry, char *name, size_t name_size)
{
- int offset = 0;
- int len = name_size;
-
- if (BLI_path_name_at_index(fsentry->path, -1, &offset, &len)) {
- /* use as size */
- len += 1;
- }
-
- BLI_strncpy(name, &fsentry->path[offset], MIN2(len, name_size));
- if (!name[0]) {
- name[0] = '/';
- name[1] = '\0';
- }
+ int offset = 0;
+ int len = name_size;
+
+ if (BLI_path_name_at_index(fsentry->path, -1, &offset, &len)) {
+ /* use as size */
+ len += 1;
+ }
+
+ BLI_strncpy(name, &fsentry->path[offset], MIN2(len, name_size));
+ if (!name[0]) {
+ name[0] = '/';
+ name[1] = '\0';
+ }
}
char *ED_fsmenu_entry_get_name(struct FSMenuEntry *fsentry)
{
- if (fsentry->name[0]) {
- return fsentry->name;
- }
- else {
- /* Here we abuse fsm_iter->name, keeping first char NULL. */
- char *name = fsentry->name + 1;
- size_t name_size = sizeof(fsentry->name) - 1;
-
- fsmenu_entry_generate_name(fsentry, name, name_size);
- return name;
- }
+ if (fsentry->name[0]) {
+ return fsentry->name;
+ }
+ else {
+ /* Here we abuse fsm_iter->name, keeping first char NULL. */
+ char *name = fsentry->name + 1;
+ size_t name_size = sizeof(fsentry->name) - 1;
+
+ fsmenu_entry_generate_name(fsentry, name, name_size);
+ return name;
+ }
}
void ED_fsmenu_entry_set_name(struct FSMenuEntry *fsentry, const char *name)
{
- if (!STREQ(name, fsentry->name)) {
- char tmp_name[FILE_MAXFILE];
- size_t tmp_name_size = sizeof(tmp_name);
-
- fsmenu_entry_generate_name(fsentry, tmp_name, tmp_name_size);
- if (!name[0] || STREQ(tmp_name, name)) {
- /* reset name to default behavior. */
- fsentry->name[0] = '\0';
- }
- else {
- 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);
- fsmenu_write_file(ED_fsmenu_get(), tmp_name);
- }
+ if (!STREQ(name, fsentry->name)) {
+ char tmp_name[FILE_MAXFILE];
+ size_t tmp_name_size = sizeof(tmp_name);
+
+ fsmenu_entry_generate_name(fsentry, tmp_name, tmp_name_size);
+ if (!name[0] || STREQ(tmp_name, name)) {
+ /* reset name to default behavior. */
+ fsentry->name[0] = '\0';
+ }
+ else {
+ 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);
+ fsmenu_write_file(ED_fsmenu_get(), tmp_name);
+ }
}
void fsmenu_entry_refresh_valid(struct FSMenuEntry *fsentry)
{
- if (fsentry->path && fsentry->path[0]) {
+ if (fsentry->path && fsentry->path[0]) {
#ifdef WIN32
- /* XXX Special case, always consider those as valid.
- * Thanks to Windows, which can spend five seconds to perform a mere stat() call on those paths...
- * See T43684.
- */
- const char *exceptions[] = {"A:\\", "B:\\", NULL};
- const size_t exceptions_len[] = {strlen(exceptions[0]), strlen(exceptions[1]), 0};
- int i;
-
- for (i = 0; exceptions[i]; i++) {
- if (STRCASEEQLEN(fsentry->path, exceptions[i], exceptions_len[i])) {
- fsentry->valid = true;
- return;
- }
- }
+ /* XXX Special case, always consider those as valid.
+ * Thanks to Windows, which can spend five seconds to perform a mere stat() call on those paths...
+ * See T43684.
+ */
+ const char *exceptions[] = {"A:\\", "B:\\", NULL};
+ const size_t exceptions_len[] = {strlen(exceptions[0]), strlen(exceptions[1]), 0};
+ int i;
+
+ for (i = 0; exceptions[i]; i++) {
+ if (STRCASEEQLEN(fsentry->path, exceptions[i], exceptions_len[i])) {
+ fsentry->valid = true;
+ return;
+ }
+ }
#endif
- fsentry->valid = BLI_is_dir(fsentry->path);
- }
- else {
- fsentry->valid = false;
- }
+ fsentry->valid = BLI_is_dir(fsentry->path);
+ }
+ else {
+ fsentry->valid = false;
+ }
}
short fsmenu_can_save(struct FSMenu *fsmenu, FSMenuCategory category, int idx)
{
- FSMenuEntry *fsm_iter;
+ FSMenuEntry *fsm_iter;
- for (fsm_iter = ED_fsmenu_get_category(fsmenu, category); fsm_iter && idx; fsm_iter = fsm_iter->next) {
- idx--;
- }
+ for (fsm_iter = ED_fsmenu_get_category(fsmenu, category); fsm_iter && idx;
+ fsm_iter = fsm_iter->next) {
+ idx--;
+ }
- return fsm_iter ? fsm_iter->save : 0;
+ return fsm_iter ? fsm_iter->save : 0;
}
-void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const char *path, const char *name, FSMenuInsert flag)
+void fsmenu_insert_entry(struct FSMenu *fsmenu,
+ FSMenuCategory category,
+ const char *path,
+ const char *name,
+ FSMenuInsert flag)
{
- FSMenuEntry *fsm_prev;
- FSMenuEntry *fsm_iter;
- FSMenuEntry *fsm_head;
-
- fsm_head = ED_fsmenu_get_category(fsmenu, category);
- fsm_prev = fsm_head; /* this is odd and not really correct? */
-
- 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) {
- if (flag & FS_INSERT_FIRST) {
- if (fsm_iter != fsm_head) {
- fsm_prev->next = fsm_iter->next;
- fsm_iter->next = fsm_head;
- ED_fsmenu_set_category(fsmenu, category, fsm_iter);
- }
- }
- return;
- }
- else if ((flag & FS_INSERT_SORTED) && cmp_ret < 0) {
- break;
- }
- }
- else {
- /* if we're bookmarking this, file should come
- * before the last separator, only automatically added
- * current dir go after the last sep. */
- if (flag & FS_INSERT_SAVE) {
- break;
- }
- }
- }
-
- fsm_iter = MEM_mallocN(sizeof(*fsm_iter), "fsme");
- fsm_iter->path = BLI_strdup(path);
- fsm_iter->save = (flag & FS_INSERT_SAVE) != 0;
-
- if ((category == FS_CATEGORY_RECENT) && (!name || !name[0])) {
- /* Special handling when adding new recent entry - check if dir exists in some other categories,
- * and try to use name from there if so. */
- FSMenuCategory cats[] = {FS_CATEGORY_SYSTEM, FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS};
- int i = ARRAY_SIZE(cats);
-
- while (i--) {
- FSMenuEntry *tfsm = ED_fsmenu_get_category(fsmenu, cats[i]);
-
- for (; tfsm; tfsm = tfsm->next) {
- if (STREQ(tfsm->path, fsm_iter->path)) {
- if (tfsm->name[0]) {
- name = tfsm->name;
- }
- break;
- }
- }
- if (tfsm) {
- break;
- }
- }
- }
-
- if (name && name[0]) {
- BLI_strncpy(fsm_iter->name, name, sizeof(fsm_iter->name));
- }
- else {
- fsm_iter->name[0] = '\0';
- }
- fsmenu_entry_refresh_valid(fsm_iter);
-
- if (fsm_prev) {
- if (flag & FS_INSERT_FIRST) {
- fsm_iter->next = fsm_head;
- ED_fsmenu_set_category(fsmenu, category, fsm_iter);
- }
- else {
- fsm_iter->next = fsm_prev->next;
- fsm_prev->next = fsm_iter;
- }
- }
- else {
- fsm_iter->next = fsm_head;
- ED_fsmenu_set_category(fsmenu, category, fsm_iter);
- }
+ FSMenuEntry *fsm_prev;
+ FSMenuEntry *fsm_iter;
+ FSMenuEntry *fsm_head;
+
+ fsm_head = ED_fsmenu_get_category(fsmenu, category);
+ fsm_prev = fsm_head; /* this is odd and not really correct? */
+
+ 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) {
+ if (flag & FS_INSERT_FIRST) {
+ if (fsm_iter != fsm_head) {
+ fsm_prev->next = fsm_iter->next;
+ fsm_iter->next = fsm_head;
+ ED_fsmenu_set_category(fsmenu, category, fsm_iter);
+ }
+ }
+ return;
+ }
+ else if ((flag & FS_INSERT_SORTED) && cmp_ret < 0) {
+ break;
+ }
+ }
+ else {
+ /* if we're bookmarking this, file should come
+ * before the last separator, only automatically added
+ * current dir go after the last sep. */
+ if (flag & FS_INSERT_SAVE) {
+ break;
+ }
+ }
+ }
+
+ fsm_iter = MEM_mallocN(sizeof(*fsm_iter), "fsme");
+ fsm_iter->path = BLI_strdup(path);
+ fsm_iter->save = (flag & FS_INSERT_SAVE) != 0;
+
+ if ((category == FS_CATEGORY_RECENT) && (!name || !name[0])) {
+ /* Special handling when adding new recent entry - check if dir exists in some other categories,
+ * and try to use name from there if so. */
+ FSMenuCategory cats[] = {
+ FS_CATEGORY_SYSTEM, FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS};
+ int i = ARRAY_SIZE(cats);
+
+ while (i--) {
+ FSMenuEntry *tfsm = ED_fsmenu_get_category(fsmenu, cats[i]);
+
+ for (; tfsm; tfsm = tfsm->next) {
+ if (STREQ(tfsm->path, fsm_iter->path)) {
+ if (tfsm->name[0]) {
+ name = tfsm->name;
+ }
+ break;
+ }
+ }
+ if (tfsm) {
+ break;
+ }
+ }
+ }
+
+ if (name && name[0]) {
+ BLI_strncpy(fsm_iter->name, name, sizeof(fsm_iter->name));
+ }
+ else {
+ fsm_iter->name[0] = '\0';
+ }
+ fsmenu_entry_refresh_valid(fsm_iter);
+
+ if (fsm_prev) {
+ if (flag & FS_INSERT_FIRST) {
+ fsm_iter->next = fsm_head;
+ ED_fsmenu_set_category(fsmenu, category, fsm_iter);
+ }
+ else {
+ fsm_iter->next = fsm_prev->next;
+ fsm_prev->next = fsm_iter;
+ }
+ }
+ else {
+ fsm_iter->next = fsm_head;
+ ED_fsmenu_set_category(fsmenu, category, fsm_iter);
+ }
}
void fsmenu_remove_entry(struct FSMenu *fsmenu, FSMenuCategory category, int idx)
{
- FSMenuEntry *fsm_prev = NULL;
- FSMenuEntry *fsm_iter;
- FSMenuEntry *fsm_head;
-
- fsm_head = ED_fsmenu_get_category(fsmenu, category);
-
- for (fsm_iter = fsm_head; fsm_iter && idx; fsm_prev = fsm_iter, fsm_iter = fsm_iter->next)
- idx--;
-
- if (fsm_iter) {
- /* you should only be able to remove entries that were
- * not added by default, like windows drives.
- * also separators (where path == NULL) shouldn't be removed */
- if (fsm_iter->save && fsm_iter->path) {
-
- /* remove fsme from list */
- if (fsm_prev) {
- fsm_prev->next = fsm_iter->next;
- }
- else {
- fsm_head = fsm_iter->next;
- ED_fsmenu_set_category(fsmenu, category, fsm_head);
- }
- /* free entry */
- MEM_freeN(fsm_iter->path);
- MEM_freeN(fsm_iter);
- }
- }
+ FSMenuEntry *fsm_prev = NULL;
+ FSMenuEntry *fsm_iter;
+ FSMenuEntry *fsm_head;
+
+ fsm_head = ED_fsmenu_get_category(fsmenu, category);
+
+ for (fsm_iter = fsm_head; fsm_iter && idx; fsm_prev = fsm_iter, fsm_iter = fsm_iter->next)
+ idx--;
+
+ if (fsm_iter) {
+ /* you should only be able to remove entries that were
+ * not added by default, like windows drives.
+ * also separators (where path == NULL) shouldn't be removed */
+ if (fsm_iter->save && fsm_iter->path) {
+
+ /* remove fsme from list */
+ if (fsm_prev) {
+ fsm_prev->next = fsm_iter->next;
+ }
+ else {
+ fsm_head = fsm_iter->next;
+ ED_fsmenu_set_category(fsmenu, category, fsm_head);
+ }
+ /* free entry */
+ MEM_freeN(fsm_iter->path);
+ MEM_freeN(fsm_iter);
+ }
+ }
}
void fsmenu_write_file(struct FSMenu *fsmenu, const char *filename)
{
- FSMenuEntry *fsm_iter = NULL;
- char fsm_name[FILE_MAX];
- int nwritten = 0;
-
- FILE *fp = BLI_fopen(filename, "w");
- if (!fp) return;
-
- fprintf(fp, "[Bookmarks]\n");
- for (fsm_iter = ED_fsmenu_get_category(fsmenu, FS_CATEGORY_BOOKMARKS); fsm_iter; fsm_iter = fsm_iter->next) {
- if (fsm_iter->path && fsm_iter->save) {
- fsmenu_entry_generate_name(fsm_iter, fsm_name, sizeof(fsm_name));
- if (fsm_iter->name[0] && !STREQ(fsm_iter->name, fsm_name)) {
- fprintf(fp, "!%s\n", fsm_iter->name);
- }
- fprintf(fp, "%s\n", fsm_iter->path);
- }
- }
- fprintf(fp, "[Recent]\n");
- for (fsm_iter = ED_fsmenu_get_category(fsmenu, FS_CATEGORY_RECENT); fsm_iter && (nwritten < FSMENU_RECENT_MAX); fsm_iter = fsm_iter->next, ++nwritten) {
- if (fsm_iter->path && fsm_iter->save) {
- fsmenu_entry_generate_name(fsm_iter, fsm_name, sizeof(fsm_name));
- if (fsm_iter->name[0] && !STREQ(fsm_iter->name, fsm_name)) {
- fprintf(fp, "!%s\n", fsm_iter->name);
- }
- fprintf(fp, "%s\n", fsm_iter->path);
- }
- }
- fclose(fp);
+ FSMenuEntry *fsm_iter = NULL;
+ char fsm_name[FILE_MAX];
+ int nwritten = 0;
+
+ FILE *fp = BLI_fopen(filename, "w");
+ if (!fp)
+ return;
+
+ fprintf(fp, "[Bookmarks]\n");
+ for (fsm_iter = ED_fsmenu_get_category(fsmenu, FS_CATEGORY_BOOKMARKS); fsm_iter;
+ fsm_iter = fsm_iter->next) {
+ if (fsm_iter->path && fsm_iter->save) {
+ fsmenu_entry_generate_name(fsm_iter, fsm_name, sizeof(fsm_name));
+ if (fsm_iter->name[0] && !STREQ(fsm_iter->name, fsm_name)) {
+ fprintf(fp, "!%s\n", fsm_iter->name);
+ }
+ fprintf(fp, "%s\n", fsm_iter->path);
+ }
+ }
+ fprintf(fp, "[Recent]\n");
+ for (fsm_iter = ED_fsmenu_get_category(fsmenu, FS_CATEGORY_RECENT);
+ fsm_iter && (nwritten < FSMENU_RECENT_MAX);
+ fsm_iter = fsm_iter->next, ++nwritten) {
+ if (fsm_iter->path && fsm_iter->save) {
+ fsmenu_entry_generate_name(fsm_iter, fsm_name, sizeof(fsm_name));
+ if (fsm_iter->name[0] && !STREQ(fsm_iter->name, fsm_name)) {
+ fprintf(fp, "!%s\n", fsm_iter->name);
+ }
+ fprintf(fp, "%s\n", fsm_iter->path);
+ }
+ }
+ fclose(fp);
}
void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filename)
{
- char line[FILE_MAXDIR];
- char name[FILE_MAXFILE];
- FSMenuCategory category = FS_CATEGORY_BOOKMARKS;
- FILE *fp;
-
- fp = BLI_fopen(filename, "r");
- if (!fp) return;
-
- name[0] = '\0';
-
- while (fgets(line, sizeof(line), fp) != NULL) { /* read a line */
- if (STREQLEN(line, "[Bookmarks]", 11)) {
- category = FS_CATEGORY_BOOKMARKS;
- }
- else if (STREQLEN(line, "[Recent]", 8)) {
- category = FS_CATEGORY_RECENT;
- }
- else if (line[0] == '!') {
- int len = strlen(line);
- if (len > 0) {
- if (line[len - 1] == '\n') {
- line[len - 1] = '\0';
- }
- BLI_strncpy(name, line + 1, sizeof(name));
- }
- }
- else {
- int len = strlen(line);
- if (len > 0) {
- if (line[len - 1] == '\n') {
- line[len - 1] = '\0';
- }
- /* don't do this because it can be slow on network drives,
- * having a bookmark from a drive that's ejected or so isn't
- * all _that_ bad */
+ char line[FILE_MAXDIR];
+ char name[FILE_MAXFILE];
+ FSMenuCategory category = FS_CATEGORY_BOOKMARKS;
+ FILE *fp;
+
+ fp = BLI_fopen(filename, "r");
+ if (!fp)
+ return;
+
+ name[0] = '\0';
+
+ while (fgets(line, sizeof(line), fp) != NULL) { /* read a line */
+ if (STREQLEN(line, "[Bookmarks]", 11)) {
+ category = FS_CATEGORY_BOOKMARKS;
+ }
+ else if (STREQLEN(line, "[Recent]", 8)) {
+ category = FS_CATEGORY_RECENT;
+ }
+ else if (line[0] == '!') {
+ int len = strlen(line);
+ if (len > 0) {
+ if (line[len - 1] == '\n') {
+ line[len - 1] = '\0';
+ }
+ BLI_strncpy(name, line + 1, sizeof(name));
+ }
+ }
+ else {
+ int len = strlen(line);
+ if (len > 0) {
+ if (line[len - 1] == '\n') {
+ line[len - 1] = '\0';
+ }
+ /* don't do this because it can be slow on network drives,
+ * having a bookmark from a drive that's ejected or so isn't
+ * all _that_ bad */
#if 0
- if (BLI_exists(line))
+ if (BLI_exists(line))
#endif
- {
- fsmenu_insert_entry(fsmenu, category, line, name, FS_INSERT_SAVE);
- }
- }
- /* always reset name. */
- name[0] = '\0';
- }
- }
- fclose(fp);
+ {
+ fsmenu_insert_entry(fsmenu, category, line, name, FS_INSERT_SAVE);
+ }
+ }
+ /* always reset name. */
+ name[0] = '\0';
+ }
+ }
+ fclose(fp);
}
void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
{
- char line[FILE_MAXDIR];
+ char line[FILE_MAXDIR];
#ifdef WIN32
- /* Add the drive names to the listing */
- {
- wchar_t wline[FILE_MAXDIR];
- __int64 tmp;
- char tmps[4], *name;
- int i;
-
- tmp = GetLogicalDrives();
-
- for (i = 0; i < 26; i++) {
- if ((tmp >> i) & 1) {
- tmps[0] = 'A' + i;
- tmps[1] = ':';
- tmps[2] = '\\';
- tmps[3] = '\0';
- name = NULL;
-
- /* Flee from horrible win querying hover floppy drives! */
- if (i > 1) {
- /* Try to get volume label as well... */
- BLI_strncpy_wchar_from_utf8(wline, tmps, 4);
- if (GetVolumeInformationW(wline, wline + 4, FILE_MAXDIR - 4, NULL, NULL, NULL, NULL, 0)) {
- size_t label_len;
-
- BLI_strncpy_wchar_as_utf8(line, wline + 4, FILE_MAXDIR - 4);
-
- label_len = MIN2(strlen(line), FILE_MAXDIR - 6);
- BLI_snprintf(line + label_len, 6, " (%.2s)", tmps);
-
- name = line;
- }
- }
-
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, tmps, name, FS_INSERT_SORTED);
- }
- }
-
- /* Adding Desktop and My Documents */
- if (read_bookmarks) {
- SHGetSpecialFolderPathW(0, wline, CSIDL_PERSONAL, 0);
- BLI_strncpy_wchar_as_utf8(line, wline, FILE_MAXDIR);
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
- SHGetSpecialFolderPathW(0, wline, CSIDL_DESKTOPDIRECTORY, 0);
- BLI_strncpy_wchar_as_utf8(line, wline, FILE_MAXDIR);
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
- }
- }
-#else
-#ifdef __APPLE__
- {
- /* Get mounted volumes better method OSX 10.6 and higher, see: */
- /*https://developer.apple.com/library/mac/#documentation/CoreFOundation/Reference/CFURLRef/Reference/reference.html*/
-
- /* we get all volumes sorted including network and do not relay
- * on user-defined finder visibility, less confusing */
-
- CFURLRef cfURL = NULL;
- CFURLEnumeratorResult result = kCFURLEnumeratorSuccess;
- CFURLEnumeratorRef volEnum = CFURLEnumeratorCreateForMountedVolumes(NULL, kCFURLEnumeratorSkipInvisibles, NULL);
-
- while (result != kCFURLEnumeratorEnd) {
- char defPath[FILE_MAX];
-
- result = CFURLEnumeratorGetNextURL(volEnum, &cfURL, NULL);
- if (result != kCFURLEnumeratorSuccess)
- continue;
-
- CFURLGetFileSystemRepresentation(cfURL, false, (UInt8 *)defPath, FILE_MAX);
-
- /* Add end slash for consistency with other platforms */
- BLI_add_slash(defPath);
-
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, defPath, NULL, FS_INSERT_SORTED);
- }
-
- CFRelease(volEnum);
-
- /* Finally get user favorite places */
- if (read_bookmarks) {
- UInt32 seed;
- LSSharedFileListRef list = LSSharedFileListCreate(NULL, kLSSharedFileListFavoriteItems, NULL);
- CFArrayRef pathesArray = LSSharedFileListCopySnapshot(list, &seed);
- CFIndex pathesCount = CFArrayGetCount(pathesArray);
-
- for (CFIndex i = 0; i < pathesCount; i++) {
- LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(pathesArray, i);
-
- CFURLRef cfURL = NULL;
- OSErr err = LSSharedFileListItemResolve(itemRef,
- kLSSharedFileListNoUserInteraction |
- kLSSharedFileListDoNotMountVolumes,
- &cfURL, NULL);
- if (err != noErr || !cfURL)
- continue;
-
- CFStringRef pathString = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle);
-
- if (pathString == NULL || !CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingUTF8))
- continue;
-
- /* Add end slash for consistency with other platforms */
- BLI_add_slash(line);
-
- /* 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')) {
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_LAST);
- }
-
- CFRelease(pathString);
- CFRelease(cfURL);
- }
-
- CFRelease(pathesArray);
- CFRelease(list);
- }
- }
+ /* Add the drive names to the listing */
+ {
+ wchar_t wline[FILE_MAXDIR];
+ __int64 tmp;
+ char tmps[4], *name;
+ int i;
+
+ tmp = GetLogicalDrives();
+
+ for (i = 0; i < 26; i++) {
+ if ((tmp >> i) & 1) {
+ tmps[0] = 'A' + i;
+ tmps[1] = ':';
+ tmps[2] = '\\';
+ tmps[3] = '\0';
+ name = NULL;
+
+ /* Flee from horrible win querying hover floppy drives! */
+ if (i > 1) {
+ /* Try to get volume label as well... */
+ BLI_strncpy_wchar_from_utf8(wline, tmps, 4);
+ if (GetVolumeInformationW(
+ wline, wline + 4, FILE_MAXDIR - 4, NULL, NULL, NULL, NULL, 0)) {
+ size_t label_len;
+
+ BLI_strncpy_wchar_as_utf8(line, wline + 4, FILE_MAXDIR - 4);
+
+ label_len = MIN2(strlen(line), FILE_MAXDIR - 6);
+ BLI_snprintf(line + label_len, 6, " (%.2s)", tmps);
+
+ name = line;
+ }
+ }
+
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, tmps, name, FS_INSERT_SORTED);
+ }
+ }
+
+ /* Adding Desktop and My Documents */
+ if (read_bookmarks) {
+ SHGetSpecialFolderPathW(0, wline, CSIDL_PERSONAL, 0);
+ BLI_strncpy_wchar_as_utf8(line, wline, FILE_MAXDIR);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
+ SHGetSpecialFolderPathW(0, wline, CSIDL_DESKTOPDIRECTORY, 0);
+ BLI_strncpy_wchar_as_utf8(line, wline, FILE_MAXDIR);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
+ }
+ }
#else
- /* unix */
- {
- const char *home = BLI_getenv("HOME");
-
- if (read_bookmarks && home) {
- BLI_snprintf(line, sizeof(line), "%s/", home);
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
- BLI_snprintf(line, sizeof(line), "%s/Desktop/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
- }
- }
-
- {
- int found = 0;
-#ifdef __linux__
- /* loop over mount points */
- struct mntent *mnt;
- int len;
- FILE *fp;
-
- fp = setmntent(MOUNTED, "r");
- if (fp == NULL) {
- fprintf(stderr, "could not get a list of mounted filesystems\n");
- }
- else {
- while ((mnt = getmntent(fp))) {
- if (STRPREFIX(mnt->mnt_dir, "/boot")) {
- /* Hide share not usable to the user. */
- continue;
- }
- else if (!STRPREFIX(mnt->mnt_fsname, "/dev")) {
- continue;
- }
- else if (STRPREFIX(mnt->mnt_fsname, "/dev/loop")) {
- /* The dev/loop* entries are SNAPS used by desktop environment
- * (Gnome) no need for them to show up in the list. */
- 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, FS_INSERT_SORTED);
- }
- else {
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, mnt->mnt_dir, NULL, FS_INSERT_SORTED);
- }
-
- found = 1;
- }
- if (endmntent(fp) == 0) {
- fprintf(stderr, "could not close the list of mounted filesystems\n");
- }
- }
- /* Check gvfs shares. */
- const char * const xdg_runtime_dir = BLI_getenv("XDG_RUNTIME_DIR");
- if (xdg_runtime_dir != NULL) {
- struct direntry *dir;
- char name[FILE_MAX];
- BLI_join_dirfile(name, sizeof(name), xdg_runtime_dir, "gvfs/");
- const uint dir_len = BLI_filelist_dir_contents(name, &dir);
- for (uint i = 0; i < dir_len; i++) {
- if ((dir[i].type & S_IFDIR)) {
- const char *dirname = dir[i].relname;
- if (dirname[0] != '.') {
- /* Dir names contain a lot of unwanted text.
- * Assuming every entry ends with the share name */
- const char *label = strstr(dirname, "share=");
- if (label != NULL) {
- /* Move pointer so "share=" is trimmed off
- * or use full dirname as label. */
- const char *label_test = label + 6;
- label = *label_test ? label_test : dirname;
- }
- BLI_snprintf(line, sizeof(line), "%s%s/", name, dirname);
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, line, label, FS_INSERT_SORTED);
- found = 1;
- }
- }
- }
- BLI_filelist_free(dir, dir_len);
- }
-#endif
-
- /* fallback */
- if (!found)
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, "/", NULL, FS_INSERT_SORTED);
- }
- }
-#endif
+# ifdef __APPLE__
+ {
+ /* Get mounted volumes better method OSX 10.6 and higher, see: */
+ /*https://developer.apple.com/library/mac/#documentation/CoreFOundation/Reference/CFURLRef/Reference/reference.html*/
+
+ /* we get all volumes sorted including network and do not relay
+ * on user-defined finder visibility, less confusing */
+
+ CFURLRef cfURL = NULL;
+ CFURLEnumeratorResult result = kCFURLEnumeratorSuccess;
+ CFURLEnumeratorRef volEnum = CFURLEnumeratorCreateForMountedVolumes(
+ NULL, kCFURLEnumeratorSkipInvisibles, NULL);
+
+ while (result != kCFURLEnumeratorEnd) {
+ char defPath[FILE_MAX];
+
+ result = CFURLEnumeratorGetNextURL(volEnum, &cfURL, NULL);
+ if (result != kCFURLEnumeratorSuccess)
+ continue;
+
+ CFURLGetFileSystemRepresentation(cfURL, false, (UInt8 *)defPath, FILE_MAX);
+
+ /* Add end slash for consistency with other platforms */
+ BLI_add_slash(defPath);
+
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, defPath, NULL, FS_INSERT_SORTED);
+ }
+
+ CFRelease(volEnum);
+
+ /* Finally get user favorite places */
+ if (read_bookmarks) {
+ UInt32 seed;
+ LSSharedFileListRef list = LSSharedFileListCreate(
+ NULL, kLSSharedFileListFavoriteItems, NULL);
+ CFArrayRef pathesArray = LSSharedFileListCopySnapshot(list, &seed);
+ CFIndex pathesCount = CFArrayGetCount(pathesArray);
+
+ for (CFIndex i = 0; i < pathesCount; i++) {
+ LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(
+ pathesArray, i);
+
+ CFURLRef cfURL = NULL;
+ OSErr err = LSSharedFileListItemResolve(itemRef,
+ kLSSharedFileListNoUserInteraction |
+ kLSSharedFileListDoNotMountVolumes,
+ &cfURL,
+ NULL);
+ if (err != noErr || !cfURL)
+ continue;
+
+ CFStringRef pathString = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle);
+
+ if (pathString == NULL ||
+ !CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingUTF8))
+ continue;
+
+ /* Add end slash for consistency with other platforms */
+ BLI_add_slash(line);
+
+ /* 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')) {
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_LAST);
+ }
+
+ CFRelease(pathString);
+ CFRelease(cfURL);
+ }
+
+ CFRelease(pathesArray);
+ CFRelease(list);
+ }
+ }
+# else
+ /* unix */
+ {
+ const char *home = BLI_getenv("HOME");
+
+ if (read_bookmarks && home) {
+ BLI_snprintf(line, sizeof(line), "%s/", home);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
+ BLI_snprintf(line, sizeof(line), "%s/Desktop/", home);
+ if (BLI_exists(line)) {
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
+ }
+ }
+
+ {
+ int found = 0;
+# ifdef __linux__
+ /* loop over mount points */
+ struct mntent *mnt;
+ int len;
+ FILE *fp;
+
+ fp = setmntent(MOUNTED, "r");
+ if (fp == NULL) {
+ fprintf(stderr, "could not get a list of mounted filesystems\n");
+ }
+ else {
+ while ((mnt = getmntent(fp))) {
+ if (STRPREFIX(mnt->mnt_dir, "/boot")) {
+ /* Hide share not usable to the user. */
+ continue;
+ }
+ else if (!STRPREFIX(mnt->mnt_fsname, "/dev")) {
+ continue;
+ }
+ else if (STRPREFIX(mnt->mnt_fsname, "/dev/loop")) {
+ /* The dev/loop* entries are SNAPS used by desktop environment
+ * (Gnome) no need for them to show up in the list. */
+ 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, FS_INSERT_SORTED);
+ }
+ else {
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, mnt->mnt_dir, NULL, FS_INSERT_SORTED);
+ }
+
+ found = 1;
+ }
+ if (endmntent(fp) == 0) {
+ fprintf(stderr, "could not close the list of mounted filesystems\n");
+ }
+ }
+ /* Check gvfs shares. */
+ const char *const xdg_runtime_dir = BLI_getenv("XDG_RUNTIME_DIR");
+ if (xdg_runtime_dir != NULL) {
+ struct direntry *dir;
+ char name[FILE_MAX];
+ BLI_join_dirfile(name, sizeof(name), xdg_runtime_dir, "gvfs/");
+ const uint dir_len = BLI_filelist_dir_contents(name, &dir);
+ for (uint i = 0; i < dir_len; i++) {
+ if ((dir[i].type & S_IFDIR)) {
+ const char *dirname = dir[i].relname;
+ if (dirname[0] != '.') {
+ /* Dir names contain a lot of unwanted text.
+ * Assuming every entry ends with the share name */
+ const char *label = strstr(dirname, "share=");
+ if (label != NULL) {
+ /* Move pointer so "share=" is trimmed off
+ * or use full dirname as label. */
+ const char *label_test = label + 6;
+ label = *label_test ? label_test : dirname;
+ }
+ BLI_snprintf(line, sizeof(line), "%s%s/", name, dirname);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, line, label, FS_INSERT_SORTED);
+ found = 1;
+ }
+ }
+ }
+ BLI_filelist_free(dir, dir_len);
+ }
+# endif
+
+ /* fallback */
+ if (!found)
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, "/", NULL, FS_INSERT_SORTED);
+ }
+ }
+# endif
#endif
}
-
static void fsmenu_free_category(struct FSMenu *fsmenu, FSMenuCategory category)
{
- FSMenuEntry *fsm_iter = ED_fsmenu_get_category(fsmenu, category);
+ FSMenuEntry *fsm_iter = ED_fsmenu_get_category(fsmenu, category);
- while (fsm_iter) {
- FSMenuEntry *fsm_next = fsm_iter->next;
+ while (fsm_iter) {
+ FSMenuEntry *fsm_next = fsm_iter->next;
- if (fsm_iter->path) {
- MEM_freeN(fsm_iter->path);
- }
- MEM_freeN(fsm_iter);
+ if (fsm_iter->path) {
+ MEM_freeN(fsm_iter->path);
+ }
+ MEM_freeN(fsm_iter);
- fsm_iter = fsm_next;
- }
+ fsm_iter = fsm_next;
+ }
}
void fsmenu_refresh_system_category(struct FSMenu *fsmenu)
{
- fsmenu_free_category(fsmenu, FS_CATEGORY_SYSTEM);
- ED_fsmenu_set_category(fsmenu, FS_CATEGORY_SYSTEM, NULL);
+ fsmenu_free_category(fsmenu, FS_CATEGORY_SYSTEM);
+ ED_fsmenu_set_category(fsmenu, FS_CATEGORY_SYSTEM, NULL);
- fsmenu_free_category(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS);
- ED_fsmenu_set_category(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, NULL);
+ fsmenu_free_category(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS);
+ ED_fsmenu_set_category(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, NULL);
- /* Add all entries to system category */
- fsmenu_read_system(fsmenu, true);
+ /* Add all entries to system category */
+ fsmenu_read_system(fsmenu, true);
}
void fsmenu_refresh_bookmarks_status(struct FSMenu *fsmenu)
{
- int categories[] = {FS_CATEGORY_SYSTEM, FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS, FS_CATEGORY_RECENT};
- int i;
-
- for (i = sizeof(categories) / sizeof(*categories); i--; ) {
- FSMenuEntry *fsm_iter = ED_fsmenu_get_category(fsmenu, categories[i]);
- for ( ; fsm_iter; fsm_iter = fsm_iter->next) {
- fsmenu_entry_refresh_valid(fsm_iter);
- }
- }
+ int categories[] = {
+ FS_CATEGORY_SYSTEM, FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS, FS_CATEGORY_RECENT};
+ int i;
+
+ for (i = sizeof(categories) / sizeof(*categories); i--;) {
+ FSMenuEntry *fsm_iter = ED_fsmenu_get_category(fsmenu, categories[i]);
+ for (; fsm_iter; fsm_iter = fsm_iter->next) {
+ fsmenu_entry_refresh_valid(fsm_iter);
+ }
+ }
}
void fsmenu_free(void)
{
- if (g_fsmenu) {
- fsmenu_free_category(g_fsmenu, FS_CATEGORY_SYSTEM);
- fsmenu_free_category(g_fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS);
- fsmenu_free_category(g_fsmenu, FS_CATEGORY_BOOKMARKS);
- fsmenu_free_category(g_fsmenu, FS_CATEGORY_RECENT);
- MEM_freeN(g_fsmenu);
- }
-
- g_fsmenu = NULL;
+ if (g_fsmenu) {
+ fsmenu_free_category(g_fsmenu, FS_CATEGORY_SYSTEM);
+ fsmenu_free_category(g_fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS);
+ fsmenu_free_category(g_fsmenu, FS_CATEGORY_BOOKMARKS);
+ fsmenu_free_category(g_fsmenu, FS_CATEGORY_RECENT);
+ MEM_freeN(g_fsmenu);
+ }
+
+ g_fsmenu = NULL;
}
int fsmenu_get_active_indices(struct FSMenu *fsmenu, enum FSMenuCategory category, const char *dir)
{
- FSMenuEntry *fsm_iter = ED_fsmenu_get_category(fsmenu, category);
- int i;
+ FSMenuEntry *fsm_iter = ED_fsmenu_get_category(fsmenu, category);
+ int i;
- for (i = 0; fsm_iter; fsm_iter = fsm_iter->next, i++) {
- if (BLI_path_cmp(dir, fsm_iter->path) == 0) {
- return i;
- }
- }
+ for (i = 0; fsm_iter; fsm_iter = fsm_iter->next, i++) {
+ if (BLI_path_cmp(dir, fsm_iter->path) == 0) {
+ return i;
+ }
+ }
- return -1;
+ return -1;
}
diff --git a/source/blender/editors/space_file/fsmenu.h b/source/blender/editors/space_file/fsmenu.h
index f20016e6895..cb0dccf0499 100644
--- a/source/blender/editors/space_file/fsmenu.h
+++ b/source/blender/editors/space_file/fsmenu.h
@@ -21,7 +21,6 @@
* \ingroup spfile
*/
-
#ifndef __FSMENU_H__
#define __FSMENU_H__
@@ -38,36 +37,42 @@ struct FSMenuEntry;
* Duplicate entries are not added.
* \param flag: Options for inserting the entry.
*/
-void fsmenu_insert_entry(struct FSMenu *fsmenu, enum FSMenuCategory category, const char *path, const char *name, const enum FSMenuInsert flag);
+void fsmenu_insert_entry(struct FSMenu *fsmenu,
+ enum FSMenuCategory category,
+ const char *path,
+ const char *name,
+ const enum FSMenuInsert flag);
/** Refresh 'valid' status of given menu entry */
void fsmenu_entry_refresh_valid(struct FSMenuEntry *fsentry);
/** Return whether the entry was created by the user and can be saved and deleted */
-short fsmenu_can_save(struct FSMenu *fsmenu, enum FSMenuCategory category, int index);
+short fsmenu_can_save(struct FSMenu *fsmenu, enum FSMenuCategory category, int index);
/** Removes the fsmenu entry at the given \a index. */
-void fsmenu_remove_entry(struct FSMenu *fsmenu, enum FSMenuCategory category, int index);
+void fsmenu_remove_entry(struct FSMenu *fsmenu, enum FSMenuCategory category, int index);
/** saves the 'bookmarks' to the specified file */
-void fsmenu_write_file(struct FSMenu *fsmenu, const char *filename);
+void fsmenu_write_file(struct FSMenu *fsmenu, const char *filename);
/** reads the 'bookmarks' from the specified file */
-void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filename);
+void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filename);
/** adds system specific directories */
-void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks);
+void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks);
/** Free's all the memory associated with the fsmenu */
-void fsmenu_free(void);
+void fsmenu_free(void);
/** Refresh system directory menu */
-void fsmenu_refresh_system_category(struct FSMenu *fsmenu);
+void fsmenu_refresh_system_category(struct FSMenu *fsmenu);
/** Refresh 'valid' status of all menu entries */
-void fsmenu_refresh_bookmarks_status(struct FSMenu *fsmenu);
+void fsmenu_refresh_bookmarks_status(struct FSMenu *fsmenu);
/** Get active index based on given directory. */
-int fsmenu_get_active_indices(struct FSMenu *fsmenu, enum FSMenuCategory category, const char *dir);
+int fsmenu_get_active_indices(struct FSMenu *fsmenu,
+ enum FSMenuCategory category,
+ const char *dir);
#endif
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 5a4b0e36ae1..53bcf7068f4 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -26,11 +26,9 @@
#include "MEM_guardedalloc.h"
-
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-
#include "BKE_appdir.h"
#include "BKE_context.h"
#include "BKE_screen.h"
@@ -52,8 +50,7 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-
-#include "file_intern.h" // own include
+#include "file_intern.h" // own include
#include "fsmenu.h"
#include "filelist.h"
#include "GPU_framebuffer.h"
@@ -62,653 +59,666 @@
static SpaceLink *file_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
- 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;
- /* Ignore user preference "USER_HEADER_BOTTOM" here (always show top for new types). */
- ar->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;
-
- /* Tool props (aka operator) region */
- ar = MEM_callocN(sizeof(ARegion), "tool props region for file");
- BLI_addtail(&sfile->regionbase, ar);
- ar->regiontype = RGN_TYPE_TOOL_PROPS;
- ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
-
- /* 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;
-
- /* 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;
-
- return (SpaceLink *)sfile;
+ ARegion *ar;
+ 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;
+ /* Ignore user preference "USER_HEADER_BOTTOM" here (always show top for new types). */
+ ar->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;
+
+ /* Tool props (aka operator) region */
+ ar = MEM_callocN(sizeof(ARegion), "tool props region for file");
+ BLI_addtail(&sfile->regionbase, ar);
+ ar->regiontype = RGN_TYPE_TOOL_PROPS;
+ ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
+
+ /* 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;
+
+ /* 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;
+
+ return (SpaceLink *)sfile;
}
/* not spacelink itself */
static void file_free(SpaceLink *sl)
{
- SpaceFile *sfile = (SpaceFile *) sl;
-
- BLI_assert(sfile->previews_timer == NULL);
-
- if (sfile->files) {
- // XXXXX would need to do thumbnails_stop here, but no context available
- filelist_freelib(sfile->files);
- filelist_free(sfile->files);
- MEM_freeN(sfile->files);
- sfile->files = NULL;
- }
-
- if (sfile->folders_prev) {
- folderlist_free(sfile->folders_prev);
- MEM_freeN(sfile->folders_prev);
- sfile->folders_prev = NULL;
- }
-
- if (sfile->folders_next) {
- folderlist_free(sfile->folders_next);
- MEM_freeN(sfile->folders_next);
- sfile->folders_next = NULL;
- }
-
- if (sfile->params) {
- MEM_freeN(sfile->params);
- sfile->params = NULL;
- }
-
- if (sfile->layout) {
- MEM_freeN(sfile->layout);
- sfile->layout = NULL;
- }
+ SpaceFile *sfile = (SpaceFile *)sl;
+
+ BLI_assert(sfile->previews_timer == NULL);
+
+ if (sfile->files) {
+ // XXXXX would need to do thumbnails_stop here, but no context available
+ filelist_freelib(sfile->files);
+ filelist_free(sfile->files);
+ MEM_freeN(sfile->files);
+ sfile->files = NULL;
+ }
+
+ if (sfile->folders_prev) {
+ folderlist_free(sfile->folders_prev);
+ MEM_freeN(sfile->folders_prev);
+ sfile->folders_prev = NULL;
+ }
+
+ if (sfile->folders_next) {
+ folderlist_free(sfile->folders_next);
+ MEM_freeN(sfile->folders_next);
+ sfile->folders_next = NULL;
+ }
+
+ if (sfile->params) {
+ MEM_freeN(sfile->params);
+ sfile->params = NULL;
+ }
+
+ if (sfile->layout) {
+ MEM_freeN(sfile->layout);
+ sfile->layout = NULL;
+ }
}
-
/* spacetype; init callback, area size changes, screen set, etc */
static void file_init(wmWindowManager *UNUSED(wm), ScrArea *sa)
{
- SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
+ SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
- /* refresh system directory list */
- fsmenu_refresh_system_category(ED_fsmenu_get());
+ /* refresh system directory list */
+ fsmenu_refresh_system_category(ED_fsmenu_get());
- /* Update bookmarks 'valid' state.
- * Done here, because it seems BLI_is_dir() can have huge impact on performances
- * in some cases, on win systems... See T43684.
- */
- fsmenu_refresh_bookmarks_status(ED_fsmenu_get());
+ /* Update bookmarks 'valid' state.
+ * Done here, because it seems BLI_is_dir() can have huge impact on performances
+ * in some cases, on win systems... See T43684.
+ */
+ fsmenu_refresh_bookmarks_status(ED_fsmenu_get());
- if (sfile->layout) sfile->layout->dirty = true;
+ if (sfile->layout)
+ sfile->layout->dirty = true;
}
static void file_exit(wmWindowManager *wm, ScrArea *sa)
{
- SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
+ SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
- if (sfile->previews_timer) {
- WM_event_remove_timer_notifier(wm, NULL, sfile->previews_timer);
- sfile->previews_timer = NULL;
- }
+ 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, sa, sfile);
}
static SpaceLink *file_duplicate(SpaceLink *sl)
{
- SpaceFile *sfileo = (SpaceFile *)sl;
- SpaceFile *sfilen = MEM_dupallocN(sl);
+ SpaceFile *sfileo = (SpaceFile *)sl;
+ SpaceFile *sfilen = MEM_dupallocN(sl);
- /* clear or remove stuff from old */
- sfilen->op = NULL; /* file window doesn't own operators */
+ /* clear or remove stuff from old */
+ sfilen->op = NULL; /* file window doesn't own operators */
- sfilen->previews_timer = NULL;
- sfilen->smoothscroll_timer = NULL;
+ sfilen->previews_timer = NULL;
+ sfilen->smoothscroll_timer = NULL;
- if (sfileo->params) {
- sfilen->files = filelist_new(sfileo->params->type);
- sfilen->params = MEM_dupallocN(sfileo->params);
- filelist_setdir(sfilen->files, sfilen->params->dir);
- }
+ if (sfileo->params) {
+ sfilen->files = filelist_new(sfileo->params->type);
+ sfilen->params = MEM_dupallocN(sfileo->params);
+ filelist_setdir(sfilen->files, sfilen->params->dir);
+ }
- if (sfileo->folders_prev)
- sfilen->folders_prev = folderlist_duplicate(sfileo->folders_prev);
+ if (sfileo->folders_prev)
+ sfilen->folders_prev = folderlist_duplicate(sfileo->folders_prev);
- if (sfileo->folders_next)
- sfilen->folders_next = folderlist_duplicate(sfileo->folders_next);
+ if (sfileo->folders_next)
+ sfilen->folders_next = folderlist_duplicate(sfileo->folders_next);
- if (sfileo->layout) {
- sfilen->layout = MEM_dupallocN(sfileo->layout);
- }
- return (SpaceLink *)sfilen;
+ if (sfileo->layout) {
+ sfilen->layout = MEM_dupallocN(sfileo->layout);
+ }
+ return (SpaceLink *)sfilen;
}
static void file_refresh(const bContext *C, ScrArea *sa)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
- FileSelectParams *params = ED_fileselect_get_params(sfile);
- struct FSMenu *fsmenu = ED_fsmenu_get();
-
- if (!sfile->folders_prev) {
- sfile->folders_prev = folderlist_new();
- }
- if (!sfile->files) {
- sfile->files = filelist_new(params->type);
- params->highlight_file = -1; /* added this so it opens nicer (ton) */
- }
- filelist_setdir(sfile->files, params->dir);
- filelist_setrecursion(sfile->files, params->recursion_level);
- filelist_setsorting(sfile->files, params->sort);
- filelist_setfilter_options(sfile->files, (params->flag & FILE_FILTER) != 0,
- (params->flag & FILE_HIDE_DOT) != 0,
- false, /* TODO hide_parent, should be controllable? */
- params->filter,
- params->filter_id,
- params->filter_glob,
- params->filter_search);
-
- /* Update the active indices of bookmarks & co. */
- sfile->systemnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_SYSTEM, params->dir);
- sfile->system_bookmarknr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, params->dir);
- sfile->bookmarknr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir);
- sfile->recentnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_RECENT, params->dir);
-
- if (filelist_force_reset(sfile->files)) {
- filelist_readjob_stop(wm, sa);
- filelist_clear(sfile->files);
- }
-
- if (filelist_empty(sfile->files)) {
- if (!filelist_pending(sfile->files)) {
- filelist_readjob_start(sfile->files, C);
- }
- }
-
- filelist_sort(sfile->files);
- filelist_filter(sfile->files);
-
- if (params->display == FILE_IMGDISPLAY) {
- filelist_cache_previews_set(sfile->files, true);
- }
- else {
- filelist_cache_previews_set(sfile->files, false);
- if (sfile->previews_timer) {
- WM_event_remove_timer_notifier(wm, CTX_wm_window(C), sfile->previews_timer);
- sfile->previews_timer = NULL;
- }
- }
-
- if (params->rename_flag != 0) {
- file_params_renamefile_activate(sfile, params);
- }
-
- if (sfile->layout) {
- sfile->layout->dirty = true;
- }
-
- /* Might be called with NULL sa, see file_main_region_draw() below. */
- if (sa && BKE_area_find_region_type(sa, RGN_TYPE_TOOLS) == NULL) {
- /* Create TOOLS/TOOL_PROPS regions. */
- file_tools_region(sa);
-
- ED_area_initialize(wm, CTX_wm_window(C), sa);
- }
-
- ED_area_tag_redraw(sa);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ FileSelectParams *params = ED_fileselect_get_params(sfile);
+ struct FSMenu *fsmenu = ED_fsmenu_get();
+
+ if (!sfile->folders_prev) {
+ sfile->folders_prev = folderlist_new();
+ }
+ if (!sfile->files) {
+ sfile->files = filelist_new(params->type);
+ params->highlight_file = -1; /* added this so it opens nicer (ton) */
+ }
+ filelist_setdir(sfile->files, params->dir);
+ filelist_setrecursion(sfile->files, params->recursion_level);
+ filelist_setsorting(sfile->files, params->sort);
+ filelist_setfilter_options(sfile->files,
+ (params->flag & FILE_FILTER) != 0,
+ (params->flag & FILE_HIDE_DOT) != 0,
+ false, /* TODO hide_parent, should be controllable? */
+ params->filter,
+ params->filter_id,
+ params->filter_glob,
+ params->filter_search);
+
+ /* Update the active indices of bookmarks & co. */
+ sfile->systemnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_SYSTEM, params->dir);
+ sfile->system_bookmarknr = fsmenu_get_active_indices(
+ fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, params->dir);
+ sfile->bookmarknr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir);
+ sfile->recentnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_RECENT, params->dir);
+
+ if (filelist_force_reset(sfile->files)) {
+ filelist_readjob_stop(wm, sa);
+ filelist_clear(sfile->files);
+ }
+
+ if (filelist_empty(sfile->files)) {
+ if (!filelist_pending(sfile->files)) {
+ filelist_readjob_start(sfile->files, C);
+ }
+ }
+
+ filelist_sort(sfile->files);
+ filelist_filter(sfile->files);
+
+ if (params->display == FILE_IMGDISPLAY) {
+ filelist_cache_previews_set(sfile->files, true);
+ }
+ else {
+ filelist_cache_previews_set(sfile->files, false);
+ if (sfile->previews_timer) {
+ WM_event_remove_timer_notifier(wm, CTX_wm_window(C), sfile->previews_timer);
+ sfile->previews_timer = NULL;
+ }
+ }
+
+ if (params->rename_flag != 0) {
+ file_params_renamefile_activate(sfile, params);
+ }
+
+ if (sfile->layout) {
+ sfile->layout->dirty = true;
+ }
+
+ /* Might be called with NULL sa, see file_main_region_draw() below. */
+ if (sa && BKE_area_find_region_type(sa, RGN_TYPE_TOOLS) == NULL) {
+ /* Create TOOLS/TOOL_PROPS regions. */
+ file_tools_region(sa);
+
+ ED_area_initialize(wm, CTX_wm_window(C), sa);
+ }
+
+ ED_area_tag_redraw(sa);
}
-static void file_listener(wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene))
+static void file_listener(wmWindow *UNUSED(win),
+ ScrArea *sa,
+ wmNotifier *wmn,
+ Scene *UNUSED(scene))
{
- SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
-
- /* context changes */
- switch (wmn->category) {
- case NC_SPACE:
- switch (wmn->data) {
- case ND_SPACE_FILE_LIST:
- ED_area_tag_refresh(sa);
- break;
- case ND_SPACE_FILE_PARAMS:
- ED_area_tag_refresh(sa);
- break;
- case ND_SPACE_FILE_PREVIEW:
- if (sfile->files && filelist_cache_previews_update(sfile->files)) {
- ED_area_tag_refresh(sa);
- }
- break;
- }
- break;
- }
+ SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
+
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SPACE:
+ switch (wmn->data) {
+ case ND_SPACE_FILE_LIST:
+ ED_area_tag_refresh(sa);
+ break;
+ case ND_SPACE_FILE_PARAMS:
+ ED_area_tag_refresh(sa);
+ break;
+ case ND_SPACE_FILE_PREVIEW:
+ if (sfile->files && filelist_cache_previews_update(sfile->files)) {
+ ED_area_tag_refresh(sa);
+ }
+ break;
+ }
+ break;
+ }
}
/* add handlers, stuff you only do once or on area/region changes */
static void file_main_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
- /* own keymaps */
- keymap = WM_keymap_ensure(wm->defaultconf, "File Browser", SPACE_FILE, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ /* own keymaps */
+ keymap = WM_keymap_ensure(wm->defaultconf, "File Browser", SPACE_FILE, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- keymap = WM_keymap_ensure(wm->defaultconf, "File Browser Main", SPACE_FILE, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "File Browser Main", SPACE_FILE, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
-static void file_main_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void file_main_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_SPACE:
- switch (wmn->data) {
- case ND_SPACE_FILE_LIST:
- ED_region_tag_redraw(ar);
- break;
- case ND_SPACE_FILE_PARAMS:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SPACE:
+ switch (wmn->data) {
+ case ND_SPACE_FILE_LIST:
+ ED_region_tag_redraw(ar);
+ break;
+ case ND_SPACE_FILE_PARAMS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ }
}
-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 wmMsgBus *mbus)
+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 wmMsgBus *mbus)
{
- SpaceFile *sfile = sa->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,
- .notify = ED_area_do_msg_notify_tag_refresh,
- };
-
- /* SpaceFile itself. */
- {
- PointerRNA ptr;
- RNA_pointer_create(&screen->id, &RNA_SpaceFileBrowser, sfile, &ptr);
-
- /* All properties for this space type. */
- WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_area_tag_refresh, __func__);
- }
-
- /* FileSelectParams */
- {
- PointerRNA ptr;
- RNA_pointer_create(&screen->id, &RNA_FileSelectParams, params, &ptr);
-
- /* All properties for this space type. */
- WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_area_tag_refresh, __func__);
- }
+ SpaceFile *sfile = sa->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,
+ .notify = ED_area_do_msg_notify_tag_refresh,
+ };
+
+ /* SpaceFile itself. */
+ {
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_SpaceFileBrowser, sfile, &ptr);
+
+ /* All properties for this space type. */
+ WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_area_tag_refresh, __func__);
+ }
+
+ /* FileSelectParams */
+ {
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_FileSelectParams, params, &ptr);
+
+ /* All properties for this space type. */
+ WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_area_tag_refresh, __func__);
+ }
}
static void file_main_region_draw(const bContext *C, ARegion *ar)
{
- /* 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;
- View2DScrollers *scrollers;
- float col[3];
-
- /* Needed, because filelist is not initialized on loading */
- if (!sfile->files || filelist_empty(sfile->files))
- file_refresh(C, NULL);
-
- /* clear and setup matrix */
- UI_GetThemeColor3fv(TH_BACK, col);
- GPU_clear_color(col[0], col[1], col[2], 0.0);
- GPU_clear(GPU_COLOR_BIT);
-
- /* Allow dynamically sliders to be set, saves notifiers etc. */
-
- if (params->display == FILE_IMGDISPLAY) {
- v2d->scroll = V2D_SCROLL_RIGHT;
- v2d->keepofs &= ~V2D_LOCKOFS_Y;
- v2d->keepofs |= V2D_LOCKOFS_X;
- }
- else {
- v2d->scroll = V2D_SCROLL_BOTTOM;
- v2d->keepofs &= ~V2D_LOCKOFS_X;
- v2d->keepofs |= V2D_LOCKOFS_Y;
-
- /* XXX this happens on scaling down Screen (like from startup.blend) */
- /* view2d has no type specific for filewindow case, which doesn't scroll vertically */
- if (v2d->cur.ymax < 0) {
- v2d->cur.ymin -= v2d->cur.ymax;
- v2d->cur.ymax = 0;
- }
- }
- /* 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);
-
- /* sets tile/border settings in sfile */
- file_calc_previews(C, ar);
-
- /* set view */
- UI_view2d_view_ortho(v2d);
-
- /* 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_draw_list(C, ar);
-
- /* reset view matrix */
- UI_view2d_view_restore(C);
-
- /* scrollers */
- scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
-
+ /* 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;
+ View2DScrollers *scrollers;
+ float col[3];
+
+ /* Needed, because filelist is not initialized on loading */
+ if (!sfile->files || filelist_empty(sfile->files))
+ file_refresh(C, NULL);
+
+ /* clear and setup matrix */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ GPU_clear_color(col[0], col[1], col[2], 0.0);
+ GPU_clear(GPU_COLOR_BIT);
+
+ /* Allow dynamically sliders to be set, saves notifiers etc. */
+
+ if (params->display == FILE_IMGDISPLAY) {
+ v2d->scroll = V2D_SCROLL_RIGHT;
+ v2d->keepofs &= ~V2D_LOCKOFS_Y;
+ v2d->keepofs |= V2D_LOCKOFS_X;
+ }
+ else {
+ v2d->scroll = V2D_SCROLL_BOTTOM;
+ v2d->keepofs &= ~V2D_LOCKOFS_X;
+ v2d->keepofs |= V2D_LOCKOFS_Y;
+
+ /* XXX this happens on scaling down Screen (like from startup.blend) */
+ /* view2d has no type specific for filewindow case, which doesn't scroll vertically */
+ if (v2d->cur.ymax < 0) {
+ v2d->cur.ymin -= v2d->cur.ymax;
+ v2d->cur.ymax = 0;
+ }
+ }
+ /* 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);
+
+ /* sets tile/border settings in sfile */
+ file_calc_previews(C, ar);
+
+ /* set view */
+ UI_view2d_view_ortho(v2d);
+
+ /* 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_draw_list(C, ar);
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ scrollers = UI_view2d_scrollers_calc(
+ C, v2d, NULL, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
}
static void file_operatortypes(void)
{
- WM_operatortype_append(FILE_OT_select);
- WM_operatortype_append(FILE_OT_select_walk);
- WM_operatortype_append(FILE_OT_select_all);
- WM_operatortype_append(FILE_OT_select_box);
- WM_operatortype_append(FILE_OT_select_bookmark);
- WM_operatortype_append(FILE_OT_highlight);
- WM_operatortype_append(FILE_OT_execute);
- WM_operatortype_append(FILE_OT_cancel);
- WM_operatortype_append(FILE_OT_parent);
- WM_operatortype_append(FILE_OT_previous);
- WM_operatortype_append(FILE_OT_next);
- WM_operatortype_append(FILE_OT_refresh);
- WM_operatortype_append(FILE_OT_bookmark_toggle);
- WM_operatortype_append(FILE_OT_bookmark_add);
- WM_operatortype_append(FILE_OT_bookmark_delete);
- WM_operatortype_append(FILE_OT_bookmark_cleanup);
- WM_operatortype_append(FILE_OT_bookmark_move);
- WM_operatortype_append(FILE_OT_reset_recent);
- WM_operatortype_append(FILE_OT_hidedot);
- WM_operatortype_append(FILE_OT_filenum);
- WM_operatortype_append(FILE_OT_directory_new);
- WM_operatortype_append(FILE_OT_delete);
- WM_operatortype_append(FILE_OT_rename);
- WM_operatortype_append(FILE_OT_smoothscroll);
- WM_operatortype_append(FILE_OT_filepath_drop);
+ WM_operatortype_append(FILE_OT_select);
+ WM_operatortype_append(FILE_OT_select_walk);
+ WM_operatortype_append(FILE_OT_select_all);
+ WM_operatortype_append(FILE_OT_select_box);
+ WM_operatortype_append(FILE_OT_select_bookmark);
+ WM_operatortype_append(FILE_OT_highlight);
+ WM_operatortype_append(FILE_OT_execute);
+ WM_operatortype_append(FILE_OT_cancel);
+ WM_operatortype_append(FILE_OT_parent);
+ WM_operatortype_append(FILE_OT_previous);
+ WM_operatortype_append(FILE_OT_next);
+ WM_operatortype_append(FILE_OT_refresh);
+ WM_operatortype_append(FILE_OT_bookmark_toggle);
+ WM_operatortype_append(FILE_OT_bookmark_add);
+ WM_operatortype_append(FILE_OT_bookmark_delete);
+ WM_operatortype_append(FILE_OT_bookmark_cleanup);
+ WM_operatortype_append(FILE_OT_bookmark_move);
+ WM_operatortype_append(FILE_OT_reset_recent);
+ WM_operatortype_append(FILE_OT_hidedot);
+ WM_operatortype_append(FILE_OT_filenum);
+ WM_operatortype_append(FILE_OT_directory_new);
+ WM_operatortype_append(FILE_OT_delete);
+ WM_operatortype_append(FILE_OT_rename);
+ WM_operatortype_append(FILE_OT_smoothscroll);
+ WM_operatortype_append(FILE_OT_filepath_drop);
}
/* NOTE: do not add .blend file reading on this level */
static void file_keymap(struct wmKeyConfig *keyconf)
{
- /* keys for all regions */
- WM_keymap_ensure(keyconf, "File Browser", SPACE_FILE, 0);
+ /* keys for all regions */
+ WM_keymap_ensure(keyconf, "File Browser", SPACE_FILE, 0);
- /* keys for main region */
- WM_keymap_ensure(keyconf, "File Browser Main", SPACE_FILE, 0);
+ /* keys for main region */
+ WM_keymap_ensure(keyconf, "File Browser Main", SPACE_FILE, 0);
- /* keys for button region (top) */
- WM_keymap_ensure(keyconf, "File Browser Buttons", SPACE_FILE, 0);
+ /* keys for button region (top) */
+ WM_keymap_ensure(keyconf, "File Browser Buttons", SPACE_FILE, 0);
}
-
static void file_tools_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
- ED_region_panels_init(wm, ar);
+ ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
+ ED_region_panels_init(wm, ar);
- /* own keymaps */
- keymap = WM_keymap_ensure(wm->defaultconf, "File Browser", SPACE_FILE, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ /* own keymaps */
+ keymap = WM_keymap_ensure(wm->defaultconf, "File Browser", SPACE_FILE, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
static void file_tools_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, ar);
}
-static void file_tools_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *UNUSED(ar),
- wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene))
+static void file_tools_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *UNUSED(ar),
+ wmNotifier *UNUSED(wmn),
+ const Scene *UNUSED(scene))
{
#if 0
- /* context changes */
- switch (wmn->category) {
- /* pass */
- }
+ /* context changes */
+ switch (wmn->category) {
+ /* pass */
+ }
#endif
}
/* add handlers, stuff you only do once or on area/region changes */
static void file_header_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- ED_region_header_init(ar);
+ ED_region_header_init(ar);
- keymap = WM_keymap_ensure(wm->defaultconf, "File Browser", SPACE_FILE, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "File Browser", SPACE_FILE, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
static void file_header_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_header(C, ar);
+ ED_region_header(C, ar);
}
/* add handlers, stuff you only do once or on area/region changes */
static void file_ui_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
- /* own keymap */
- keymap = WM_keymap_ensure(wm->defaultconf, "File Browser", SPACE_FILE, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ /* own keymap */
+ keymap = WM_keymap_ensure(wm->defaultconf, "File Browser", SPACE_FILE, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- keymap = WM_keymap_ensure(wm->defaultconf, "File Browser Buttons", SPACE_FILE, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "File Browser Buttons", SPACE_FILE, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
static void file_ui_region_draw(const bContext *C, ARegion *ar)
{
- float col[3];
- /* clear */
- UI_GetThemeColor3fv(TH_BACK, col);
- GPU_clear_color(col[0], col[1], col[2], 0.0);
- GPU_clear(GPU_COLOR_BIT);
+ float col[3];
+ /* clear */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ GPU_clear_color(col[0], col[1], col[2], 0.0);
+ GPU_clear(GPU_COLOR_BIT);
- /* scrolling here is just annoying, disable it */
- ar->v2d.cur.ymax = BLI_rctf_size_y(&ar->v2d.cur);
- ar->v2d.cur.ymin = 0;
+ /* scrolling here is just annoying, disable it */
+ ar->v2d.cur.ymax = BLI_rctf_size_y(&ar->v2d.cur);
+ ar->v2d.cur.ymin = 0;
- /* set view2d view matrix for scrolling (without scrollers) */
- UI_view2d_view_ortho(&ar->v2d);
+ /* set view2d view matrix for scrolling (without scrollers) */
+ UI_view2d_view_ortho(&ar->v2d);
+ file_draw_buttons(C, ar);
- file_draw_buttons(C, ar);
-
- UI_view2d_view_restore(C);
+ UI_view2d_view_restore(C);
}
-static void file_ui_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void file_ui_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_SPACE:
- switch (wmn->data) {
- case ND_SPACE_FILE_LIST:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SPACE:
+ switch (wmn->data) {
+ case ND_SPACE_FILE_LIST:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ }
}
-static bool filepath_drop_poll(bContext *C, wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
+static bool filepath_drop_poll(bContext *C,
+ wmDrag *drag,
+ const wmEvent *UNUSED(event),
+ const char **UNUSED(tooltip))
{
- if (drag->type == WM_DRAG_PATH) {
- SpaceFile *sfile = CTX_wm_space_file(C);
- if (sfile) {
- return 1;
- }
- }
- return 0;
+ if (drag->type == WM_DRAG_PATH) {
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ if (sfile) {
+ return 1;
+ }
+ }
+ return 0;
}
static void filepath_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- RNA_string_set(drop->ptr, "filepath", drag->path);
+ RNA_string_set(drop->ptr, "filepath", drag->path);
}
/* region dropbox definition */
static void file_dropboxes(void)
{
- ListBase *lb = WM_dropboxmap_find("Window", SPACE_EMPTY, RGN_TYPE_WINDOW);
+ ListBase *lb = WM_dropboxmap_find("Window", SPACE_EMPTY, RGN_TYPE_WINDOW);
- WM_dropbox_add(lb, "FILE_OT_filepath_drop", filepath_drop_poll, filepath_drop_copy);
+ WM_dropbox_add(lb, "FILE_OT_filepath_drop", filepath_drop_poll, filepath_drop_copy);
}
/* only called once, from space/spacetypes.c */
void ED_spacetype_file(void)
{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype file");
- ARegionType *art;
-
- st->spaceid = SPACE_FILE;
- strncpy(st->name, "File", BKE_ST_MAXNAME);
-
- st->new = file_new;
- st->free = file_free;
- st->init = file_init;
- st->exit = file_exit;
- st->duplicate = file_duplicate;
- st->refresh = file_refresh;
- st->listener = file_listener;
- st->operatortypes = file_operatortypes;
- st->keymap = file_keymap;
- st->dropboxes = file_dropboxes;
-
- /* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
- art->regionid = RGN_TYPE_WINDOW;
- art->init = file_main_region_init;
- art->draw = file_main_region_draw;
- art->listener = file_main_region_listener;
- art->message_subscribe = file_main_region_message_subscribe;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
- art->init = file_header_region_init;
- art->draw = file_header_region_draw;
- // art->listener = file_header_region_listener;
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: ui */
- art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
- art->regionid = RGN_TYPE_UI;
- art->prefsizey = 60;
- art->keymapflag = ED_KEYMAP_UI;
- art->listener = file_ui_region_listener;
- art->init = file_ui_region_init;
- art->draw = file_ui_region_draw;
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: channels (directories) */
- art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
- art->regionid = RGN_TYPE_TOOLS;
- art->prefsizex = 240;
- art->prefsizey = 60;
- art->keymapflag = ED_KEYMAP_UI;
- art->listener = file_tools_region_listener;
- art->init = file_tools_region_init;
- art->draw = file_tools_region_draw;
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: tool properties */
- art = MEM_callocN(sizeof(ARegionType), "spacetype file operator region");
- art->regionid = RGN_TYPE_TOOL_PROPS;
- art->prefsizex = 0;
- art->prefsizey = 360;
- art->keymapflag = ED_KEYMAP_UI;
- art->listener = file_tools_region_listener;
- art->init = file_tools_region_init;
- art->draw = file_tools_region_draw;
- BLI_addhead(&st->regiontypes, art);
- file_panels_register(art);
-
- BKE_spacetype_register(st);
-
+ SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype file");
+ ARegionType *art;
+
+ st->spaceid = SPACE_FILE;
+ strncpy(st->name, "File", BKE_ST_MAXNAME);
+
+ st->new = file_new;
+ st->free = file_free;
+ st->init = file_init;
+ st->exit = file_exit;
+ st->duplicate = file_duplicate;
+ st->refresh = file_refresh;
+ st->listener = file_listener;
+ st->operatortypes = file_operatortypes;
+ st->keymap = file_keymap;
+ st->dropboxes = file_dropboxes;
+
+ /* regions: main window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init = file_main_region_init;
+ art->draw = file_main_region_draw;
+ art->listener = file_main_region_listener;
+ art->message_subscribe = file_main_region_message_subscribe;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = HEADERY;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
+ art->init = file_header_region_init;
+ art->draw = file_header_region_draw;
+ // art->listener = file_header_region_listener;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: ui */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
+ art->regionid = RGN_TYPE_UI;
+ art->prefsizey = 60;
+ art->keymapflag = ED_KEYMAP_UI;
+ art->listener = file_ui_region_listener;
+ art->init = file_ui_region_init;
+ art->draw = file_ui_region_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: channels (directories) */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
+ art->regionid = RGN_TYPE_TOOLS;
+ art->prefsizex = 240;
+ art->prefsizey = 60;
+ art->keymapflag = ED_KEYMAP_UI;
+ art->listener = file_tools_region_listener;
+ art->init = file_tools_region_init;
+ art->draw = file_tools_region_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: tool properties */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype file operator region");
+ art->regionid = RGN_TYPE_TOOL_PROPS;
+ art->prefsizex = 0;
+ art->prefsizey = 360;
+ art->keymapflag = ED_KEYMAP_UI;
+ art->listener = file_tools_region_listener;
+ art->init = file_tools_region_init;
+ art->draw = file_tools_region_draw;
+ BLI_addhead(&st->regiontypes, art);
+ file_panels_register(art);
+
+ BKE_spacetype_register(st);
}
void ED_file_init(void)
{
- ED_file_read_bookmarks();
+ ED_file_read_bookmarks();
- if (G.background == false) {
- filelist_init_icons();
- }
+ if (G.background == false) {
+ filelist_init_icons();
+ }
- IMB_thumb_makedirs();
+ IMB_thumb_makedirs();
}
void ED_file_exit(void)
{
- fsmenu_free();
+ fsmenu_free();
- if (G.background == false) {
- filelist_free_icons();
- }
+ if (G.background == false) {
+ filelist_free_icons();
+ }
}
void ED_file_read_bookmarks(void)
{
- const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
+ const char *const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
- fsmenu_free();
+ fsmenu_free();
- fsmenu_read_system(ED_fsmenu_get(), true);
+ fsmenu_read_system(ED_fsmenu_get(), true);
- if (cfgdir) {
- char name[FILE_MAX];
- BLI_make_file_string("/", name, cfgdir, BLENDER_BOOKMARK_FILE);
- fsmenu_read_bookmarks(ED_fsmenu_get(), name);
- }
+ if (cfgdir) {
+ char name[FILE_MAX];
+ BLI_make_file_string("/", name, cfgdir, BLENDER_BOOKMARK_FILE);
+ fsmenu_read_bookmarks(ED_fsmenu_get(), name);
+ }
}
diff --git a/source/blender/editors/space_graph/CMakeLists.txt b/source/blender/editors/space_graph/CMakeLists.txt
index e0fc7500f94..cf5ffdb2be5 100644
--- a/source/blender/editors/space_graph/CMakeLists.txt
+++ b/source/blender/editors/space_graph/CMakeLists.txt
@@ -16,52 +16,52 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../depsgraph
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../depsgraph
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- graph_buttons.c
- graph_draw.c
- graph_edit.c
- graph_ops.c
- graph_select.c
- graph_utils.c
- space_graph.c
+ graph_buttons.c
+ graph_draw.c
+ graph_edit.c
+ graph_ops.c
+ graph_select.c
+ graph_utils.c
+ space_graph.c
- graph_intern.h
+ graph_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
+ bf_blenkernel
+ bf_blenlib
)
if(WITH_AUDASPACE)
- list(APPEND INC_SYS
- ${AUDASPACE_C_INCLUDE_DIRS}
- )
- list(APPEND LIB
- bf_intern_audaspace
- )
- add_definitions(-DWITH_AUDASPACE)
+ list(APPEND INC_SYS
+ ${AUDASPACE_C_INCLUDE_DIRS}
+ )
+ list(APPEND LIB
+ bf_intern_audaspace
+ )
+ add_definitions(-DWITH_AUDASPACE)
endif()
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index a4d7b5e9fc9..ac77095cbe2 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -21,7 +21,6 @@
* \ingroup spgraph
*/
-
#include <string.h>
#include <stdio.h>
#include <math.h>
@@ -64,7 +63,7 @@
#include "UI_interface.h"
#include "UI_resources.h"
-#include "graph_intern.h" // own include
+#include "graph_intern.h" // own include
/* ******************* graph editor space & buttons ************** */
@@ -74,33 +73,33 @@
static int graph_panel_context(const bContext *C, bAnimListElem **ale, FCurve **fcu)
{
- bAnimContext ac;
- bAnimListElem *elem = NULL;
-
- /* for now, only draw if we could init the anim-context info (necessary for all animation-related tools)
- * to work correctly is able to be correctly retrieved. There's no point showing empty panels?
- */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return 0;
-
- /* try to find 'active' F-Curve */
- elem = get_active_fcurve_channel(&ac);
- if (elem == NULL)
- return 0;
-
- if (fcu)
- *fcu = (FCurve *)elem->data;
- if (ale)
- *ale = elem;
- else
- MEM_freeN(elem);
-
- return 1;
+ bAnimContext ac;
+ bAnimListElem *elem = NULL;
+
+ /* for now, only draw if we could init the anim-context info (necessary for all animation-related tools)
+ * to work correctly is able to be correctly retrieved. There's no point showing empty panels?
+ */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return 0;
+
+ /* try to find 'active' F-Curve */
+ elem = get_active_fcurve_channel(&ac);
+ if (elem == NULL)
+ return 0;
+
+ if (fcu)
+ *fcu = (FCurve *)elem->data;
+ if (ale)
+ *ale = elem;
+ else
+ MEM_freeN(elem);
+
+ return 1;
}
static bool graph_panel_poll(const bContext *C, PanelType *UNUSED(pt))
{
- return graph_panel_context(C, NULL, NULL);
+ return graph_panel_context(C, NULL, NULL);
}
/* -------------- */
@@ -108,104 +107,104 @@ 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)
{
- bScreen *sc = CTX_wm_screen(C);
- SpaceGraph *sipo = CTX_wm_space_graph(C);
- Scene *scene = CTX_data_scene(C);
- PointerRNA spaceptr, sceneptr;
- uiLayout *col, *sub, *row;
-
- /* 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);
-
- /* 2D-Cursor */
- col = uiLayoutColumn(pa->layout, false);
- uiItemR(col, &spaceptr, "show_cursor", 0, NULL, 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");
-
- 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);
- else
- uiItemR(row, &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);
+ bScreen *sc = CTX_wm_screen(C);
+ SpaceGraph *sipo = CTX_wm_space_graph(C);
+ Scene *scene = CTX_data_scene(C);
+ PointerRNA spaceptr, sceneptr;
+ uiLayout *col, *sub, *row;
+
+ /* 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);
+
+ /* 2D-Cursor */
+ col = uiLayoutColumn(pa->layout, false);
+ uiItemR(col, &spaceptr, "show_cursor", 0, NULL, 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");
+
+ 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);
+ else
+ uiItemR(row, &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);
}
/* ******************* active F-Curve ************** */
static void graph_panel_properties(const bContext *C, Panel *pa)
{
- bAnimListElem *ale;
- FCurve *fcu;
- PointerRNA fcu_ptr;
- uiLayout *layout = pa->layout;
- uiLayout *col, *row, *sub;
- char name[256];
- int icon = 0;
-
- if (!graph_panel_context(C, &ale, &fcu))
- return;
-
- /* F-Curve pointer */
- RNA_pointer_create(ale->id, &RNA_FCurve, fcu, &fcu_ptr);
-
- /* user-friendly 'name' for F-Curve */
- col = uiLayoutColumn(layout, false);
- if (ale->type == ANIMTYPE_FCURVE) {
- /* get user-friendly name for F-Curve */
- icon = getname_anim_fcurve(name, ale->id, fcu);
- }
- else {
- /* NLA Control Curve, etc. */
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
-
- /* get name */
- if (acf && acf->name) {
- acf->name(ale, name);
- }
- else {
- strcpy(name, IFACE_("<invalid>"));
- icon = ICON_ERROR;
- }
-
- /* icon */
- if (ale->type == ANIMTYPE_NLACURVE)
- icon = ICON_NLA;
- }
- uiItemL(col, name, icon);
-
- /* RNA-Path Editing - only really should be enabled when things aren't working */
- col = uiLayoutColumn(layout, true);
- uiLayoutSetEnabled(col, (fcu->flag & FCURVE_DISABLED) != 0);
- uiItemR(col, &fcu_ptr, "data_path", 0, "", ICON_RNA);
- uiItemR(col, &fcu_ptr, "array_index", 0, NULL, ICON_NONE);
-
- /* color settings */
- col = uiLayoutColumn(layout, true);
- uiItemL(col, IFACE_("Display Color:"), ICON_NONE);
-
- row = uiLayoutRow(col, true);
- uiItemR(row, &fcu_ptr, "color_mode", 0, "", ICON_NONE);
-
- sub = uiLayoutRow(row, true);
- uiLayoutSetEnabled(sub, (fcu->color_mode == FCURVE_COLOR_CUSTOM));
- uiItemR(sub, &fcu_ptr, "color", 0, "", ICON_NONE);
-
- /* smoothing setting */
- col = uiLayoutColumn(layout, true);
- uiItemL(col, IFACE_("Auto Handle Smoothing:"), ICON_NONE);
- uiItemR(col, &fcu_ptr, "auto_smoothing", 0, "", ICON_NONE);
-
- MEM_freeN(ale);
+ bAnimListElem *ale;
+ FCurve *fcu;
+ PointerRNA fcu_ptr;
+ uiLayout *layout = pa->layout;
+ uiLayout *col, *row, *sub;
+ char name[256];
+ int icon = 0;
+
+ if (!graph_panel_context(C, &ale, &fcu))
+ return;
+
+ /* F-Curve pointer */
+ RNA_pointer_create(ale->id, &RNA_FCurve, fcu, &fcu_ptr);
+
+ /* user-friendly 'name' for F-Curve */
+ col = uiLayoutColumn(layout, false);
+ if (ale->type == ANIMTYPE_FCURVE) {
+ /* get user-friendly name for F-Curve */
+ icon = getname_anim_fcurve(name, ale->id, fcu);
+ }
+ else {
+ /* NLA Control Curve, etc. */
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+
+ /* get name */
+ if (acf && acf->name) {
+ acf->name(ale, name);
+ }
+ else {
+ strcpy(name, IFACE_("<invalid>"));
+ icon = ICON_ERROR;
+ }
+
+ /* icon */
+ if (ale->type == ANIMTYPE_NLACURVE)
+ icon = ICON_NLA;
+ }
+ uiItemL(col, name, icon);
+
+ /* RNA-Path Editing - only really should be enabled when things aren't working */
+ col = uiLayoutColumn(layout, true);
+ uiLayoutSetEnabled(col, (fcu->flag & FCURVE_DISABLED) != 0);
+ uiItemR(col, &fcu_ptr, "data_path", 0, "", ICON_RNA);
+ uiItemR(col, &fcu_ptr, "array_index", 0, NULL, ICON_NONE);
+
+ /* color settings */
+ col = uiLayoutColumn(layout, true);
+ uiItemL(col, IFACE_("Display Color:"), ICON_NONE);
+
+ row = uiLayoutRow(col, true);
+ uiItemR(row, &fcu_ptr, "color_mode", 0, "", ICON_NONE);
+
+ sub = uiLayoutRow(row, true);
+ uiLayoutSetEnabled(sub, (fcu->color_mode == FCURVE_COLOR_CUSTOM));
+ uiItemR(sub, &fcu_ptr, "color", 0, "", ICON_NONE);
+
+ /* smoothing setting */
+ col = uiLayoutColumn(layout, true);
+ uiItemL(col, IFACE_("Auto Handle Smoothing:"), ICON_NONE);
+ uiItemR(col, &fcu_ptr, "auto_smoothing", 0, "", ICON_NONE);
+
+ MEM_freeN(ale);
}
/* ******************* active Keyframe ************** */
@@ -213,66 +212,68 @@ static void graph_panel_properties(const bContext *C, Panel *pa)
/* get 'active' keyframe for panel editing */
static short get_active_fcurve_keyframe_edit(FCurve *fcu, BezTriple **bezt, BezTriple **prevbezt)
{
- BezTriple *b;
- int i;
-
- /* zero the pointers */
- *bezt = *prevbezt = NULL;
-
- /* sanity checks */
- if ((fcu->bezt == NULL) || (fcu->totvert == 0))
- return 0;
-
- /* find first selected keyframe for now, and call it the active one
- * - this is a reasonable assumption, given that whenever anyone
- * wants to edit numerically, there is likely to only be 1 vert selected
- */
- for (i = 0, b = fcu->bezt; i < fcu->totvert; i++, b++) {
- if (BEZT_ISSEL_ANY(b)) {
- /* found
- * - 'previous' is either the one before, of the keyframe itself (which is still fine)
- * XXX: we can just make this null instead if needed
- */
- *prevbezt = (i > 0) ? b - 1 : b;
- *bezt = b;
-
- return 1;
- }
- }
-
- /* not found */
- return 0;
+ BezTriple *b;
+ int i;
+
+ /* zero the pointers */
+ *bezt = *prevbezt = NULL;
+
+ /* sanity checks */
+ if ((fcu->bezt == NULL) || (fcu->totvert == 0))
+ return 0;
+
+ /* find first selected keyframe for now, and call it the active one
+ * - this is a reasonable assumption, given that whenever anyone
+ * wants to edit numerically, there is likely to only be 1 vert selected
+ */
+ for (i = 0, b = fcu->bezt; i < fcu->totvert; i++, b++) {
+ if (BEZT_ISSEL_ANY(b)) {
+ /* found
+ * - 'previous' is either the one before, of the keyframe itself (which is still fine)
+ * XXX: we can just make this null instead if needed
+ */
+ *prevbezt = (i > 0) ? b - 1 : b;
+ *bezt = b;
+
+ return 1;
+ }
+ }
+
+ /* not found */
+ return 0;
}
/* update callback for active keyframe properties - base updates stuff */
-static void graphedit_activekey_update_cb(bContext *UNUSED(C), void *fcu_ptr, void *UNUSED(bezt_ptr))
+static void graphedit_activekey_update_cb(bContext *UNUSED(C),
+ void *fcu_ptr,
+ void *UNUSED(bezt_ptr))
{
- FCurve *fcu = (FCurve *)fcu_ptr;
+ FCurve *fcu = (FCurve *)fcu_ptr;
- /* make sure F-Curve and its handles are still valid after this editing */
- sort_time_fcurve(fcu);
- calchandles_fcurve(fcu);
+ /* make sure F-Curve and its handles are still valid after this editing */
+ sort_time_fcurve(fcu);
+ calchandles_fcurve(fcu);
}
/* update callback for active keyframe properties - handle-editing wrapper */
static void graphedit_activekey_handles_cb(bContext *C, void *fcu_ptr, void *bezt_ptr)
{
- BezTriple *bezt = (BezTriple *)bezt_ptr;
-
- /* since editing the handles, make sure they're set to types which are receptive to editing
- * see transform_conversions.c :: createTransGraphEditData(), last step in second loop
- */
- if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) && ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) {
- /* by changing to aligned handles, these can now be moved... */
- bezt->h1 = HD_ALIGN;
- bezt->h2 = HD_ALIGN;
- }
- else {
- BKE_nurb_bezt_handle_test(bezt, true);
- }
-
- /* now call standard updates */
- graphedit_activekey_update_cb(C, fcu_ptr, bezt_ptr);
+ BezTriple *bezt = (BezTriple *)bezt_ptr;
+
+ /* since editing the handles, make sure they're set to types which are receptive to editing
+ * see transform_conversions.c :: createTransGraphEditData(), last step in second loop
+ */
+ if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) && ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) {
+ /* by changing to aligned handles, these can now be moved... */
+ bezt->h1 = HD_ALIGN;
+ bezt->h2 = HD_ALIGN;
+ }
+ else {
+ BKE_nurb_bezt_handle_test(bezt, true);
+ }
+
+ /* now call standard updates */
+ graphedit_activekey_update_cb(C, fcu_ptr, bezt_ptr);
}
/* update callback for editing coordinates of right handle in active keyframe properties
@@ -281,766 +282,943 @@ static void graphedit_activekey_handles_cb(bContext *C, void *fcu_ptr, void *bez
*/
static void graphedit_activekey_left_handle_coord_cb(bContext *C, void *fcu_ptr, void *bezt_ptr)
{
- BezTriple *bezt = (BezTriple *)bezt_ptr;
+ BezTriple *bezt = (BezTriple *)bezt_ptr;
- const char f1 = bezt->f1;
- const char f3 = bezt->f3;
+ const char f1 = bezt->f1;
+ const char f3 = bezt->f3;
- bezt->f1 |= SELECT;
- bezt->f3 &= ~SELECT;
+ bezt->f1 |= SELECT;
+ bezt->f3 &= ~SELECT;
- /* perform normal updates NOW */
- graphedit_activekey_handles_cb(C, fcu_ptr, bezt_ptr);
+ /* perform normal updates NOW */
+ graphedit_activekey_handles_cb(C, fcu_ptr, bezt_ptr);
- /* restore selection state so that no-one notices this hack */
- bezt->f1 = f1;
- bezt->f3 = f3;
+ /* restore selection state so that no-one notices this hack */
+ bezt->f1 = f1;
+ bezt->f3 = f3;
}
static void graphedit_activekey_right_handle_coord_cb(bContext *C, void *fcu_ptr, void *bezt_ptr)
{
- BezTriple *bezt = (BezTriple *)bezt_ptr;
+ BezTriple *bezt = (BezTriple *)bezt_ptr;
- /* original state of handle selection - to be restored after performing the recalculation */
- const char f1 = bezt->f1;
- const char f3 = bezt->f3;
+ /* original state of handle selection - to be restored after performing the recalculation */
+ const char f1 = bezt->f1;
+ const char f3 = bezt->f3;
- /* temporarily make it so that only the right handle is selected, so that updates go correctly
- * (i.e. it now acts as if we've just transforming the vert when it is selected by itself)
- */
- bezt->f1 &= ~SELECT;
- bezt->f3 |= SELECT;
+ /* temporarily make it so that only the right handle is selected, so that updates go correctly
+ * (i.e. it now acts as if we've just transforming the vert when it is selected by itself)
+ */
+ bezt->f1 &= ~SELECT;
+ bezt->f3 |= SELECT;
- /* perform normal updates NOW */
- graphedit_activekey_handles_cb(C, fcu_ptr, bezt_ptr);
+ /* perform normal updates NOW */
+ graphedit_activekey_handles_cb(C, fcu_ptr, bezt_ptr);
- /* restore selection state so that no-one notices this hack */
- bezt->f1 = f1;
- bezt->f3 = f3;
+ /* restore selection state so that no-one notices this hack */
+ bezt->f1 = f1;
+ bezt->f3 = f3;
}
static void graph_panel_key_properties(const bContext *C, Panel *pa)
{
- bAnimListElem *ale;
- FCurve *fcu;
- BezTriple *bezt, *prevbezt;
-
- uiLayout *layout = pa->layout;
- uiLayout *col;
- uiBlock *block;
-
- if (!graph_panel_context(C, &ale, &fcu))
- return;
-
- block = uiLayoutGetBlock(layout);
- /* UI_block_func_handle_set(block, do_graph_region_buttons, NULL); */
-
- /* only show this info if there are keyframes to edit */
- if (get_active_fcurve_keyframe_edit(fcu, &bezt, &prevbezt)) {
- PointerRNA bezt_ptr, id_ptr, fcu_prop_ptr;
- PropertyRNA *fcu_prop = NULL;
- uiBut *but;
- int unit = B_UNIT_NONE;
-
- /* RNA pointer to keyframe, to allow editing */
- RNA_pointer_create(ale->id, &RNA_Keyframe, bezt, &bezt_ptr);
-
- /* get property that F-Curve affects, for some unit-conversion magic */
- RNA_id_pointer_create(ale->id, &id_ptr);
- if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &fcu_prop_ptr, &fcu_prop)) {
- /* determine the unit for this property */
- unit = RNA_SUBTYPE_UNIT(RNA_property_subtype(fcu_prop));
- }
-
- /* interpolation */
- col = uiLayoutColumn(layout, false);
- if (fcu->flag & FCURVE_DISCRETE_VALUES) {
- uiLayout *split = uiLayoutSplit(col, 0.33f, true);
- uiItemL(split, IFACE_("Interpolation:"), ICON_NONE);
- uiItemL(split, IFACE_("None for Enum/Boolean"), ICON_IPO_CONSTANT);
- }
- else {
- uiItemR(col, &bezt_ptr, "interpolation", 0, NULL, ICON_NONE);
- }
-
- /* easing type */
- if (bezt->ipo > BEZT_IPO_BEZ)
- uiItemR(col, &bezt_ptr, "easing", 0, NULL, 0);
-
- /* easing extra */
- switch (bezt->ipo) {
- case BEZT_IPO_BACK:
- col = uiLayoutColumn(layout, 1);
- uiItemR(col, &bezt_ptr, "back", 0, NULL, 0);
- break;
- case BEZT_IPO_ELASTIC:
- col = uiLayoutColumn(layout, 1);
- uiItemR(col, &bezt_ptr, "amplitude", 0, NULL, 0);
- uiItemR(col, &bezt_ptr, "period", 0, NULL, 0);
- break;
- default:
- break;
- }
-
- /* numerical coordinate editing
- * - we use the button-versions of the calls so that we can attach special update handlers
- * and unit conversion magic that cannot be achieved using a purely RNA-approach
- */
- col = uiLayoutColumn(layout, true);
- /* keyframe itself */
- {
- uiItemL(col, IFACE_("Key:"), ICON_NONE);
-
- but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, IFACE_("Frame:"), 0, 0, UI_UNIT_X, UI_UNIT_Y,
- &bezt_ptr, "co", 0, 0, 0, -1, -1, NULL);
- UI_but_func_set(but, graphedit_activekey_update_cb, fcu, bezt);
-
- but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, IFACE_("Value:"), 0, 0, UI_UNIT_X, UI_UNIT_Y,
- &bezt_ptr, "co", 1, 0, 0, -1, -1, NULL);
- UI_but_func_set(but, graphedit_activekey_update_cb, fcu, bezt);
- UI_but_unit_type_set(but, unit);
- }
-
- /* previous handle - only if previous was Bezier interpolation */
- if ((prevbezt) && (prevbezt->ipo == BEZT_IPO_BEZ)) {
- uiItemL(col, IFACE_("Left Handle:"), ICON_NONE);
-
- but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, "X:", 0, 0, UI_UNIT_X, UI_UNIT_Y,
- &bezt_ptr, "handle_left", 0, 0, 0, -1, -1, NULL);
- UI_but_func_set(but, graphedit_activekey_left_handle_coord_cb, fcu, bezt);
-
- but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, "Y:", 0, 0, UI_UNIT_X, UI_UNIT_Y,
- &bezt_ptr, "handle_left", 1, 0, 0, -1, -1, NULL);
- UI_but_func_set(but, graphedit_activekey_left_handle_coord_cb, fcu, bezt);
- UI_but_unit_type_set(but, unit);
-
- /* XXX: with label? */
- but = uiDefButR(block, UI_BTYPE_MENU, B_REDR, NULL, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- &bezt_ptr, "handle_left_type", 0, 0, 0, -1, -1, "Type of left handle");
- UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt);
- }
-
- /* next handle - only if current is Bezier interpolation */
- if (bezt->ipo == BEZT_IPO_BEZ) {
- /* NOTE: special update callbacks are needed on the coords here due to T39911 */
- uiItemL(col, IFACE_("Right Handle:"), ICON_NONE);
-
- but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, "X:", 0, 0, UI_UNIT_X, UI_UNIT_Y,
- &bezt_ptr, "handle_right", 0, 0, 0, -1, -1, NULL);
- UI_but_func_set(but, graphedit_activekey_right_handle_coord_cb, fcu, bezt);
-
- but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, "Y:", 0, 0, UI_UNIT_X, UI_UNIT_Y,
- &bezt_ptr, "handle_right", 1, 0, 0, -1, -1, NULL);
- UI_but_func_set(but, graphedit_activekey_right_handle_coord_cb, fcu, bezt);
- UI_but_unit_type_set(but, unit);
-
- /* XXX: with label? */
- but = uiDefButR(block, UI_BTYPE_MENU, B_REDR, NULL, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- &bezt_ptr, "handle_right_type", 0, 0, 0, -1, -1, "Type of right handle");
- UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt);
- }
- }
- else {
- if ((fcu->bezt == NULL) && (fcu->modifiers.first)) {
- /* modifiers only - so no keyframes to be active */
- uiItemL(layout, IFACE_("F-Curve only has F-Modifiers"), ICON_NONE);
- uiItemL(layout, IFACE_("See Modifiers panel below"), ICON_INFO);
- }
- else if (fcu->fpt) {
- /* samples only */
- uiItemL(layout, IFACE_("F-Curve doesn't have any keyframes as it only contains sampled points"),
- ICON_NONE);
- }
- else
- uiItemL(layout, IFACE_("No active keyframe on F-Curve"), ICON_NONE);
- }
-
- MEM_freeN(ale);
+ bAnimListElem *ale;
+ FCurve *fcu;
+ BezTriple *bezt, *prevbezt;
+
+ uiLayout *layout = pa->layout;
+ uiLayout *col;
+ uiBlock *block;
+
+ if (!graph_panel_context(C, &ale, &fcu))
+ return;
+
+ block = uiLayoutGetBlock(layout);
+ /* UI_block_func_handle_set(block, do_graph_region_buttons, NULL); */
+
+ /* only show this info if there are keyframes to edit */
+ if (get_active_fcurve_keyframe_edit(fcu, &bezt, &prevbezt)) {
+ PointerRNA bezt_ptr, id_ptr, fcu_prop_ptr;
+ PropertyRNA *fcu_prop = NULL;
+ uiBut *but;
+ int unit = B_UNIT_NONE;
+
+ /* RNA pointer to keyframe, to allow editing */
+ RNA_pointer_create(ale->id, &RNA_Keyframe, bezt, &bezt_ptr);
+
+ /* get property that F-Curve affects, for some unit-conversion magic */
+ RNA_id_pointer_create(ale->id, &id_ptr);
+ if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &fcu_prop_ptr, &fcu_prop)) {
+ /* determine the unit for this property */
+ unit = RNA_SUBTYPE_UNIT(RNA_property_subtype(fcu_prop));
+ }
+
+ /* interpolation */
+ col = uiLayoutColumn(layout, false);
+ if (fcu->flag & FCURVE_DISCRETE_VALUES) {
+ uiLayout *split = uiLayoutSplit(col, 0.33f, true);
+ uiItemL(split, IFACE_("Interpolation:"), ICON_NONE);
+ uiItemL(split, IFACE_("None for Enum/Boolean"), ICON_IPO_CONSTANT);
+ }
+ else {
+ uiItemR(col, &bezt_ptr, "interpolation", 0, NULL, ICON_NONE);
+ }
+
+ /* easing type */
+ if (bezt->ipo > BEZT_IPO_BEZ)
+ uiItemR(col, &bezt_ptr, "easing", 0, NULL, 0);
+
+ /* easing extra */
+ switch (bezt->ipo) {
+ case BEZT_IPO_BACK:
+ col = uiLayoutColumn(layout, 1);
+ uiItemR(col, &bezt_ptr, "back", 0, NULL, 0);
+ break;
+ case BEZT_IPO_ELASTIC:
+ col = uiLayoutColumn(layout, 1);
+ uiItemR(col, &bezt_ptr, "amplitude", 0, NULL, 0);
+ uiItemR(col, &bezt_ptr, "period", 0, NULL, 0);
+ break;
+ default:
+ break;
+ }
+
+ /* numerical coordinate editing
+ * - we use the button-versions of the calls so that we can attach special update handlers
+ * and unit conversion magic that cannot be achieved using a purely RNA-approach
+ */
+ col = uiLayoutColumn(layout, true);
+ /* keyframe itself */
+ {
+ uiItemL(col, IFACE_("Key:"), ICON_NONE);
+
+ but = uiDefButR(block,
+ UI_BTYPE_NUM,
+ B_REDR,
+ IFACE_("Frame:"),
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &bezt_ptr,
+ "co",
+ 0,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ UI_but_func_set(but, graphedit_activekey_update_cb, fcu, bezt);
+
+ but = uiDefButR(block,
+ UI_BTYPE_NUM,
+ B_REDR,
+ IFACE_("Value:"),
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &bezt_ptr,
+ "co",
+ 1,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ UI_but_func_set(but, graphedit_activekey_update_cb, fcu, bezt);
+ UI_but_unit_type_set(but, unit);
+ }
+
+ /* previous handle - only if previous was Bezier interpolation */
+ if ((prevbezt) && (prevbezt->ipo == BEZT_IPO_BEZ)) {
+ uiItemL(col, IFACE_("Left Handle:"), ICON_NONE);
+
+ but = uiDefButR(block,
+ UI_BTYPE_NUM,
+ B_REDR,
+ "X:",
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &bezt_ptr,
+ "handle_left",
+ 0,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ UI_but_func_set(but, graphedit_activekey_left_handle_coord_cb, fcu, bezt);
+
+ but = uiDefButR(block,
+ UI_BTYPE_NUM,
+ B_REDR,
+ "Y:",
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &bezt_ptr,
+ "handle_left",
+ 1,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ UI_but_func_set(but, graphedit_activekey_left_handle_coord_cb, fcu, bezt);
+ UI_but_unit_type_set(but, unit);
+
+ /* XXX: with label? */
+ but = uiDefButR(block,
+ UI_BTYPE_MENU,
+ B_REDR,
+ NULL,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &bezt_ptr,
+ "handle_left_type",
+ 0,
+ 0,
+ 0,
+ -1,
+ -1,
+ "Type of left handle");
+ UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt);
+ }
+
+ /* next handle - only if current is Bezier interpolation */
+ if (bezt->ipo == BEZT_IPO_BEZ) {
+ /* NOTE: special update callbacks are needed on the coords here due to T39911 */
+ uiItemL(col, IFACE_("Right Handle:"), ICON_NONE);
+
+ but = uiDefButR(block,
+ UI_BTYPE_NUM,
+ B_REDR,
+ "X:",
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &bezt_ptr,
+ "handle_right",
+ 0,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ UI_but_func_set(but, graphedit_activekey_right_handle_coord_cb, fcu, bezt);
+
+ but = uiDefButR(block,
+ UI_BTYPE_NUM,
+ B_REDR,
+ "Y:",
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &bezt_ptr,
+ "handle_right",
+ 1,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ UI_but_func_set(but, graphedit_activekey_right_handle_coord_cb, fcu, bezt);
+ UI_but_unit_type_set(but, unit);
+
+ /* XXX: with label? */
+ but = uiDefButR(block,
+ UI_BTYPE_MENU,
+ B_REDR,
+ NULL,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &bezt_ptr,
+ "handle_right_type",
+ 0,
+ 0,
+ 0,
+ -1,
+ -1,
+ "Type of right handle");
+ UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt);
+ }
+ }
+ else {
+ if ((fcu->bezt == NULL) && (fcu->modifiers.first)) {
+ /* modifiers only - so no keyframes to be active */
+ uiItemL(layout, IFACE_("F-Curve only has F-Modifiers"), ICON_NONE);
+ uiItemL(layout, IFACE_("See Modifiers panel below"), ICON_INFO);
+ }
+ else if (fcu->fpt) {
+ /* samples only */
+ uiItemL(layout,
+ IFACE_("F-Curve doesn't have any keyframes as it only contains sampled points"),
+ ICON_NONE);
+ }
+ else
+ uiItemL(layout, IFACE_("No active keyframe on F-Curve"), ICON_NONE);
+ }
+
+ MEM_freeN(ale);
}
/* ******************* drivers ******************************** */
-#define B_IPO_DEPCHANGE 10
+#define B_IPO_DEPCHANGE 10
static void do_graph_region_driver_buttons(bContext *C, void *id_v, int event)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
-
- switch (event) {
- case B_IPO_DEPCHANGE:
- {
- /* Was not actually run ever (NULL always passed as arg to this callback).
- * If needed again, will need to check how to pass both fcurve and ID... :/ */
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+
+ switch (event) {
+ case B_IPO_DEPCHANGE: {
+ /* Was not actually run ever (NULL always passed as arg to this callback).
+ * If needed again, will need to check how to pass both fcurve and ID... :/ */
#if 0
- /* force F-Curve & Driver to get re-evaluated (same as the old Update Dependencies) */
- FCurve *fcu = (FCurve *)fcu_v;
- ChannelDriver *driver = (fcu) ? fcu->driver : NULL;
-
- /* clear invalid flags */
- if (fcu) {
- fcu->flag &= ~FCURVE_DISABLED;
- driver->flag &= ~DRIVER_FLAG_INVALID;
- }
+ /* force F-Curve & Driver to get re-evaluated (same as the old Update Dependencies) */
+ FCurve *fcu = (FCurve *)fcu_v;
+ ChannelDriver *driver = (fcu) ? fcu->driver : NULL;
+
+ /* clear invalid flags */
+ if (fcu) {
+ fcu->flag &= ~FCURVE_DISABLED;
+ driver->flag &= ~DRIVER_FLAG_INVALID;
+ }
#endif
- ID *id = id_v;
- AnimData *adt = BKE_animdata_from_id(id);
-
- /* rebuild depsgraph for the new deps, and ensure COW copies get flushed. */
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update_ex(bmain, id, ID_RECALC_COPY_ON_WRITE);
- if (adt != NULL) {
- if (adt->action != NULL) {
- DEG_id_tag_update_ex(bmain, &adt->action->id, ID_RECALC_COPY_ON_WRITE);
- }
- if (adt->tmpact != NULL) {
- DEG_id_tag_update_ex(bmain, &adt->tmpact->id, ID_RECALC_COPY_ON_WRITE);
- }
- }
-
- break;
- }
- }
-
- /* default for now */
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); // XXX could use better notifier
+ ID *id = id_v;
+ AnimData *adt = BKE_animdata_from_id(id);
+
+ /* rebuild depsgraph for the new deps, and ensure COW copies get flushed. */
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update_ex(bmain, id, ID_RECALC_COPY_ON_WRITE);
+ if (adt != NULL) {
+ if (adt->action != NULL) {
+ DEG_id_tag_update_ex(bmain, &adt->action->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ if (adt->tmpact != NULL) {
+ DEG_id_tag_update_ex(bmain, &adt->tmpact->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ }
+
+ break;
+ }
+ }
+
+ /* default for now */
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); // XXX could use better notifier
}
/* callback to add a target variable to the active driver */
static void driver_add_var_cb(bContext *C, void *driver_v, void *UNUSED(arg))
{
- ChannelDriver *driver = (ChannelDriver *)driver_v;
+ ChannelDriver *driver = (ChannelDriver *)driver_v;
- /* add a new variable */
- driver_add_new_variable(driver);
- ED_undo_push(C, "Add Driver Variable");
+ /* add a new variable */
+ driver_add_new_variable(driver);
+ ED_undo_push(C, "Add Driver Variable");
}
/* callback to remove target variable from active driver */
static void driver_delete_var_cb(bContext *C, void *driver_v, void *dvar_v)
{
- ChannelDriver *driver = (ChannelDriver *)driver_v;
- DriverVar *dvar = (DriverVar *)dvar_v;
+ ChannelDriver *driver = (ChannelDriver *)driver_v;
+ DriverVar *dvar = (DriverVar *)dvar_v;
- /* remove the active variable */
- driver_free_variable_ex(driver, dvar);
- ED_undo_push(C, "Delete Driver Variable");
+ /* remove the active variable */
+ driver_free_variable_ex(driver, dvar);
+ ED_undo_push(C, "Delete Driver Variable");
}
/* callback to report why a driver variable is invalid */
static void driver_dvar_invalid_name_query_cb(bContext *C, void *dvar_v, void *UNUSED(arg))
{
- uiPopupMenu *pup = UI_popup_menu_begin(C, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Invalid Variable Name"), ICON_NONE);
- uiLayout *layout = UI_popup_menu_layout(pup);
-
- DriverVar *dvar = (DriverVar *)dvar_v;
-
- if (dvar->flag & DVAR_FLAG_INVALID_EMPTY) {
- uiItemL(layout, "It cannot be left blank", ICON_ERROR);
- }
- if (dvar->flag & DVAR_FLAG_INVALID_START_NUM) {
- uiItemL(layout, "It cannot start with a number", ICON_ERROR);
- }
- if (dvar->flag & DVAR_FLAG_INVALID_START_CHAR) {
- uiItemL(layout,
- "It cannot start with a special character,"
- " including '$', '@', '!', '~', '+', '-', '_', '.', or ' '",
- ICON_NONE);
- }
- if (dvar->flag & DVAR_FLAG_INVALID_HAS_SPACE) {
- uiItemL(layout, "It cannot contain spaces (e.g. 'a space')", ICON_ERROR);
- }
- if (dvar->flag & DVAR_FLAG_INVALID_HAS_DOT) {
- uiItemL(layout, "It cannot contain dots (e.g. 'a.dot')", ICON_ERROR);
- }
- if (dvar->flag & DVAR_FLAG_INVALID_HAS_SPECIAL) {
- uiItemL(layout, "It cannot contain special (non-alphabetical/numeric) characters", ICON_ERROR);
- }
- if (dvar->flag & DVAR_FLAG_INVALID_PY_KEYWORD) {
- uiItemL(layout, "It cannot be a reserved keyword in Python", ICON_INFO);
- }
-
- UI_popup_menu_end(C, pup);
+ uiPopupMenu *pup = UI_popup_menu_begin(
+ C, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Invalid Variable Name"), ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+
+ DriverVar *dvar = (DriverVar *)dvar_v;
+
+ if (dvar->flag & DVAR_FLAG_INVALID_EMPTY) {
+ uiItemL(layout, "It cannot be left blank", ICON_ERROR);
+ }
+ if (dvar->flag & DVAR_FLAG_INVALID_START_NUM) {
+ uiItemL(layout, "It cannot start with a number", ICON_ERROR);
+ }
+ if (dvar->flag & DVAR_FLAG_INVALID_START_CHAR) {
+ uiItemL(layout,
+ "It cannot start with a special character,"
+ " including '$', '@', '!', '~', '+', '-', '_', '.', or ' '",
+ ICON_NONE);
+ }
+ if (dvar->flag & DVAR_FLAG_INVALID_HAS_SPACE) {
+ uiItemL(layout, "It cannot contain spaces (e.g. 'a space')", ICON_ERROR);
+ }
+ if (dvar->flag & DVAR_FLAG_INVALID_HAS_DOT) {
+ uiItemL(layout, "It cannot contain dots (e.g. 'a.dot')", ICON_ERROR);
+ }
+ if (dvar->flag & DVAR_FLAG_INVALID_HAS_SPECIAL) {
+ uiItemL(layout, "It cannot contain special (non-alphabetical/numeric) characters", ICON_ERROR);
+ }
+ if (dvar->flag & DVAR_FLAG_INVALID_PY_KEYWORD) {
+ uiItemL(layout, "It cannot be a reserved keyword in Python", ICON_INFO);
+ }
+
+ UI_popup_menu_end(C, pup);
}
/* callback to reset the driver's flags */
static void driver_update_flags_cb(bContext *UNUSED(C), void *fcu_v, void *UNUSED(arg))
{
- FCurve *fcu = (FCurve *)fcu_v;
- ChannelDriver *driver = fcu->driver;
+ FCurve *fcu = (FCurve *)fcu_v;
+ ChannelDriver *driver = fcu->driver;
- /* clear invalid flags */
- fcu->flag &= ~FCURVE_DISABLED;
- driver->flag &= ~DRIVER_FLAG_INVALID;
+ /* clear invalid flags */
+ fcu->flag &= ~FCURVE_DISABLED;
+ driver->flag &= ~DRIVER_FLAG_INVALID;
}
/* drivers panel poll */
static bool graph_panel_drivers_poll(const bContext *C, PanelType *UNUSED(pt))
{
- SpaceGraph *sipo = CTX_wm_space_graph(C);
+ SpaceGraph *sipo = CTX_wm_space_graph(C);
- if (sipo->mode != SIPO_MODE_DRIVERS)
- return 0;
+ if (sipo->mode != SIPO_MODE_DRIVERS)
+ return 0;
- return graph_panel_context(C, NULL, NULL);
+ return graph_panel_context(C, NULL, NULL);
}
/* settings for 'single property' driver variable type */
static void graph_panel_driverVar__singleProp(uiLayout *layout, ID *id, DriverVar *dvar)
{
- DriverTarget *dtar = &dvar->targets[0];
- PointerRNA dtar_ptr;
- uiLayout *row, *col;
-
- /* initialize RNA pointer to the target */
- RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
-
- /* Target ID */
- row = uiLayoutRow(layout, false);
- uiLayoutSetRedAlert(row, ((dtar->flag & DTAR_FLAG_INVALID) && !dtar->id));
- uiTemplateAnyID(row, &dtar_ptr, "id", "id_type", IFACE_("Prop:"));
-
- /* Target Property */
- if (dtar->id) {
- PointerRNA root_ptr;
-
- /* get pointer for resolving the property selected */
- RNA_id_pointer_create(dtar->id, &root_ptr);
-
- /* rna path */
- col = uiLayoutColumn(layout, true);
- uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID));
- uiTemplatePathBuilder(col, &dtar_ptr, "data_path", &root_ptr, IFACE_("Path"));
- }
+ DriverTarget *dtar = &dvar->targets[0];
+ PointerRNA dtar_ptr;
+ uiLayout *row, *col;
+
+ /* initialize RNA pointer to the target */
+ RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
+
+ /* Target ID */
+ row = uiLayoutRow(layout, false);
+ uiLayoutSetRedAlert(row, ((dtar->flag & DTAR_FLAG_INVALID) && !dtar->id));
+ uiTemplateAnyID(row, &dtar_ptr, "id", "id_type", IFACE_("Prop:"));
+
+ /* Target Property */
+ if (dtar->id) {
+ PointerRNA root_ptr;
+
+ /* get pointer for resolving the property selected */
+ RNA_id_pointer_create(dtar->id, &root_ptr);
+
+ /* rna path */
+ col = uiLayoutColumn(layout, true);
+ uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID));
+ uiTemplatePathBuilder(col, &dtar_ptr, "data_path", &root_ptr, IFACE_("Path"));
+ }
}
/* settings for 'rotation difference' driver variable type */
/* FIXME: 1) Must be same armature for both dtars, 2) Alignment issues... */
static void graph_panel_driverVar__rotDiff(uiLayout *layout, ID *id, DriverVar *dvar)
{
- DriverTarget *dtar = &dvar->targets[0];
- DriverTarget *dtar2 = &dvar->targets[1];
- Object *ob1 = (Object *)dtar->id;
- Object *ob2 = (Object *)dtar2->id;
- PointerRNA dtar_ptr, dtar2_ptr;
- uiLayout *col;
-
- /* initialize RNA pointer to the target */
- RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
- RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr);
-
- /* Object 1 */
- col = uiLayoutColumn(layout, true);
- uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
- uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object 1"), ICON_NONE);
-
- if (dtar->id && GS(dtar->id->name) == ID_OB && ob1->pose) {
- PointerRNA tar_ptr;
-
- RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr);
- uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA);
- }
-
- /* Object 2 */
- col = uiLayoutColumn(layout, true);
- uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
- uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Object 2"), ICON_NONE);
-
- if (dtar2->id && GS(dtar2->id->name) == ID_OB && ob2->pose) {
- PointerRNA tar_ptr;
-
- RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr);
- uiItemPointerR(col, &dtar2_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA);
- }
+ DriverTarget *dtar = &dvar->targets[0];
+ DriverTarget *dtar2 = &dvar->targets[1];
+ Object *ob1 = (Object *)dtar->id;
+ Object *ob2 = (Object *)dtar2->id;
+ PointerRNA dtar_ptr, dtar2_ptr;
+ uiLayout *col;
+
+ /* initialize RNA pointer to the target */
+ RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
+ RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr);
+
+ /* Object 1 */
+ col = uiLayoutColumn(layout, true);
+ uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
+ uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object 1"), ICON_NONE);
+
+ if (dtar->id && GS(dtar->id->name) == ID_OB && ob1->pose) {
+ PointerRNA tar_ptr;
+
+ RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr);
+ uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA);
+ }
+
+ /* Object 2 */
+ col = uiLayoutColumn(layout, true);
+ uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
+ uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Object 2"), ICON_NONE);
+
+ if (dtar2->id && GS(dtar2->id->name) == ID_OB && ob2->pose) {
+ PointerRNA tar_ptr;
+
+ RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr);
+ uiItemPointerR(col, &dtar2_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA);
+ }
}
/* settings for 'location difference' driver variable type */
static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar *dvar)
{
- DriverTarget *dtar = &dvar->targets[0];
- DriverTarget *dtar2 = &dvar->targets[1];
- Object *ob1 = (Object *)dtar->id;
- Object *ob2 = (Object *)dtar2->id;
- PointerRNA dtar_ptr, dtar2_ptr;
- uiLayout *col;
+ DriverTarget *dtar = &dvar->targets[0];
+ DriverTarget *dtar2 = &dvar->targets[1];
+ Object *ob1 = (Object *)dtar->id;
+ Object *ob2 = (Object *)dtar2->id;
+ PointerRNA dtar_ptr, dtar2_ptr;
+ uiLayout *col;
- /* initialize RNA pointer to the target */
- RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
- RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr);
+ /* initialize RNA pointer to the target */
+ RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
+ RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr);
- /* Object 1 */
- col = uiLayoutColumn(layout, true);
- uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
- uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object 1"), ICON_NONE);
+ /* Object 1 */
+ col = uiLayoutColumn(layout, true);
+ uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
+ uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object 1"), ICON_NONE);
- if (dtar->id && GS(dtar->id->name) == ID_OB && ob1->pose) {
- PointerRNA tar_ptr;
+ if (dtar->id && GS(dtar->id->name) == ID_OB && ob1->pose) {
+ PointerRNA tar_ptr;
- RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr);
- uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", IFACE_("Bone"), ICON_BONE_DATA);
- }
+ RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr);
+ uiItemPointerR(
+ col, &dtar_ptr, "bone_target", &tar_ptr, "bones", IFACE_("Bone"), ICON_BONE_DATA);
+ }
- /* we can clear it again now - it's only needed when creating the ID/Bone fields */
- uiLayoutSetRedAlert(col, false);
+ /* we can clear it again now - it's only needed when creating the ID/Bone fields */
+ uiLayoutSetRedAlert(col, false);
- uiItemR(col, &dtar_ptr, "transform_space", 0, NULL, ICON_NONE);
+ uiItemR(col, &dtar_ptr, "transform_space", 0, NULL, ICON_NONE);
- /* Object 2 */
- col = uiLayoutColumn(layout, true);
- uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
- uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Object 2"), ICON_NONE);
+ /* Object 2 */
+ col = uiLayoutColumn(layout, true);
+ uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
+ uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Object 2"), ICON_NONE);
- if (dtar2->id && GS(dtar2->id->name) == ID_OB && ob2->pose) {
- PointerRNA tar_ptr;
+ if (dtar2->id && GS(dtar2->id->name) == ID_OB && ob2->pose) {
+ PointerRNA tar_ptr;
- RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr);
- uiItemPointerR(col, &dtar2_ptr, "bone_target", &tar_ptr, "bones", IFACE_("Bone"), ICON_BONE_DATA);
- }
+ RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr);
+ uiItemPointerR(
+ col, &dtar2_ptr, "bone_target", &tar_ptr, "bones", IFACE_("Bone"), ICON_BONE_DATA);
+ }
- /* we can clear it again now - it's only needed when creating the ID/Bone fields */
- uiLayoutSetRedAlert(col, false);
+ /* we can clear it again now - it's only needed when creating the ID/Bone fields */
+ uiLayoutSetRedAlert(col, false);
- uiItemR(col, &dtar2_ptr, "transform_space", 0, NULL, ICON_NONE);
+ uiItemR(col, &dtar2_ptr, "transform_space", 0, NULL, ICON_NONE);
}
/* settings for 'transform channel' driver variable type */
static void graph_panel_driverVar__transChan(uiLayout *layout, ID *id, DriverVar *dvar)
{
- DriverTarget *dtar = &dvar->targets[0];
- Object *ob = (Object *)dtar->id;
- PointerRNA dtar_ptr;
- uiLayout *col, *sub;
-
- /* initialize RNA pointer to the target */
- RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
-
- /* properties */
- col = uiLayoutColumn(layout, true);
- uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
- uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object"), ICON_NONE);
-
- if (dtar->id && GS(dtar->id->name) == ID_OB && ob->pose) {
- PointerRNA tar_ptr;
-
- RNA_pointer_create(dtar->id, &RNA_Pose, ob->pose, &tar_ptr);
- uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", IFACE_("Bone"), ICON_BONE_DATA);
- }
-
- sub = uiLayoutColumn(layout, true);
- uiItemR(sub, &dtar_ptr, "transform_type", 0, NULL, ICON_NONE);
- uiItemR(sub, &dtar_ptr, "transform_space", 0, IFACE_("Space"), ICON_NONE);
+ DriverTarget *dtar = &dvar->targets[0];
+ Object *ob = (Object *)dtar->id;
+ PointerRNA dtar_ptr;
+ uiLayout *col, *sub;
+
+ /* initialize RNA pointer to the target */
+ RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
+
+ /* properties */
+ col = uiLayoutColumn(layout, true);
+ uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
+ uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object"), ICON_NONE);
+
+ if (dtar->id && GS(dtar->id->name) == ID_OB && ob->pose) {
+ PointerRNA tar_ptr;
+
+ RNA_pointer_create(dtar->id, &RNA_Pose, ob->pose, &tar_ptr);
+ uiItemPointerR(
+ col, &dtar_ptr, "bone_target", &tar_ptr, "bones", IFACE_("Bone"), ICON_BONE_DATA);
+ }
+
+ sub = uiLayoutColumn(layout, true);
+ uiItemR(sub, &dtar_ptr, "transform_type", 0, NULL, ICON_NONE);
+ uiItemR(sub, &dtar_ptr, "transform_space", 0, IFACE_("Space"), ICON_NONE);
}
/* ----------------------------------------------------------------- */
-
/* property driven by the driver - duplicates Active FCurve, but useful for clarity */
static void graph_draw_driven_property_panel(uiLayout *layout, ID *id, FCurve *fcu)
{
- PointerRNA fcu_ptr;
- uiLayout *row;
- char name[256];
- int icon = 0;
+ PointerRNA fcu_ptr;
+ uiLayout *row;
+ char name[256];
+ int icon = 0;
- /* F-Curve pointer */
- RNA_pointer_create(id, &RNA_FCurve, fcu, &fcu_ptr);
+ /* F-Curve pointer */
+ RNA_pointer_create(id, &RNA_FCurve, fcu, &fcu_ptr);
- /* get user-friendly 'name' for F-Curve */
- icon = getname_anim_fcurve(name, id, fcu);
+ /* get user-friendly 'name' for F-Curve */
+ icon = getname_anim_fcurve(name, id, fcu);
- /* panel layout... */
- row = uiLayoutRow(layout, true);
- uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
+ /* panel layout... */
+ row = uiLayoutRow(layout, true);
+ uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
- /* -> user friendly 'name' for datablock that owns F-Curve */
- /* XXX: Actually, we may need the datablock icons only... (e.g. right now will show bone for bone props) */
- uiItemL(row, id->name + 2, icon);
+ /* -> user friendly 'name' for datablock that owns F-Curve */
+ /* XXX: Actually, we may need the datablock icons only... (e.g. right now will show bone for bone props) */
+ uiItemL(row, id->name + 2, icon);
- /* -> user friendly 'name' for F-Curve/driver target */
- uiItemL(row, "", ICON_SMALL_TRI_RIGHT_VEC);
- uiItemL(row, name, ICON_RNA);
+ /* -> user friendly 'name' for F-Curve/driver target */
+ uiItemL(row, "", ICON_SMALL_TRI_RIGHT_VEC);
+ uiItemL(row, name, ICON_RNA);
}
/* UI properties panel layout for driver settings - shared for Drivers Editor and for */
-static void graph_draw_driver_settings_panel(uiLayout *layout, ID *id, FCurve *fcu, const bool is_popover)
+static void graph_draw_driver_settings_panel(uiLayout *layout,
+ ID *id,
+ FCurve *fcu,
+ const bool is_popover)
{
- ChannelDriver *driver = fcu->driver;
- DriverVar *dvar;
-
- PointerRNA driver_ptr;
- uiLayout *col, *row;
- uiBlock *block;
- uiBut *but;
-
- /* set event handler for panel */
- block = uiLayoutGetBlock(layout);
- UI_block_func_handle_set(block, do_graph_region_driver_buttons, id);
-
- /* driver-level settings - type, expressions, and errors */
- RNA_pointer_create(id, &RNA_Driver, driver, &driver_ptr);
-
- col = uiLayoutColumn(layout, true);
- block = uiLayoutGetBlock(col);
- uiItemR(col, &driver_ptr, "type", 0, NULL, ICON_NONE);
-
- {
- char valBuf[32];
-
- /* value of driver */
- row = uiLayoutRow(col, true);
- uiItemL(row, IFACE_("Driver Value:"), ICON_NONE);
- BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", driver->curval);
- uiItemL(row, valBuf, ICON_NONE);
- }
-
- uiItemS(layout);
- uiItemS(layout);
-
- /* show expression box if doing scripted drivers, and/or error messages when invalid drivers exist */
- if (driver->type == DRIVER_TYPE_PYTHON) {
- bool bpy_data_expr_error = (strstr(driver->expression, "bpy.data.") != NULL);
- bool bpy_ctx_expr_error = (strstr(driver->expression, "bpy.context.") != NULL);
-
- /* expression */
- /* TODO: "Show syntax hints" button */
- col = uiLayoutColumn(layout, true);
- block = uiLayoutGetBlock(col);
-
- uiItemL(col, IFACE_("Expression:"), ICON_NONE);
- uiItemR(col, &driver_ptr, "expression", 0, "", ICON_NONE);
- uiItemR(col, &driver_ptr, "use_self", 0, NULL, ICON_NONE);
-
- /* errors? */
- col = uiLayoutColumn(layout, true);
- block = uiLayoutGetBlock(col);
-
- if (driver->flag & DRIVER_FLAG_INVALID) {
- uiItemL(col, IFACE_("ERROR: Invalid Python expression"), ICON_CANCEL);
- }
- else if (!BKE_driver_has_simple_expression(driver)) {
- if ((G.f & G_FLAG_SCRIPT_AUTOEXEC) == 0) {
- /* TODO: Add button to enable? */
- uiItemL(col, IFACE_("WARNING: Python expressions limited for security"), ICON_ERROR);
- }
- else {
- uiItemL(col, IFACE_("Slow Python expression"), ICON_INFO);
- }
- }
-
- /* Explicit bpy-references are evil. Warn about these to prevent errors */
- /* TODO: put these in a box? */
- if (bpy_data_expr_error || bpy_ctx_expr_error) {
- uiItemL(col, IFACE_("WARNING: Driver expression may not work correctly"), ICON_HELP);
-
- if (bpy_data_expr_error) {
- uiItemL(col, IFACE_("TIP: Use variables instead of bpy.data paths (see below)"), ICON_ERROR);
- }
- if (bpy_ctx_expr_error) {
- uiItemL(col, IFACE_("TIP: bpy.context is not safe for renderfarm usage"), ICON_ERROR);
- }
- }
- }
- else {
- /* errors? */
- col = uiLayoutColumn(layout, true);
- block = uiLayoutGetBlock(col);
-
- if (driver->flag & DRIVER_FLAG_INVALID)
- uiItemL(col, IFACE_("ERROR: Invalid target channel(s)"), ICON_ERROR);
-
- /* Warnings about a lack of variables
- * NOTE: The lack of variables is generally a bad thing, since it indicates
- * that the driver doesn't work at all. This particular scenario arises
- * primarily when users mistakenly try to use drivers for procedural
- * property animation
- */
- if (BLI_listbase_is_empty(&driver->variables)) {
- uiItemL(col, IFACE_("ERROR: Driver is useless without any inputs"), ICON_ERROR);
-
- if (!BLI_listbase_is_empty(&fcu->modifiers)) {
- uiItemL(col, IFACE_("TIP: Use F-Curves for procedural animation instead"), ICON_INFO);
- uiItemL(col, IFACE_("F-Modifiers can generate curves for those too"), ICON_INFO);
- }
- }
- }
-
- uiItemS(layout);
-
- /* add/copy/paste driver variables */
- if (is_popover) {
- /* add driver variable - add blank */
- row = uiLayoutRow(layout, true);
- block = uiLayoutGetBlock(row);
- but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ADD, IFACE_("Add Input Variable"),
- 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0, 0,
- TIP_("Add a Driver Variable to keep track an input used by the driver"));
- UI_but_func_set(but, driver_add_var_cb, driver, NULL);
-
- /* add driver variable - add using eyedropper */
- /* XXX: will this operator work like this? */
- uiItemO(row, "", ICON_EYEDROPPER, "UI_OT_eyedropper_driver");
- }
- else {
- /* add driver variable */
- row = uiLayoutRow(layout, false);
- block = uiLayoutGetBlock(row);
- but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ADD, IFACE_("Add Input Variable"),
- 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0, 0,
- TIP_("Driver variables ensure that all dependencies will be accounted for, ensuring that drivers will update correctly"));
- UI_but_func_set(but, driver_add_var_cb, driver, NULL);
-
- /* copy/paste (as sub-row) */
- row = uiLayoutRow(row, true);
- block = uiLayoutGetBlock(row);
-
- uiItemO(row, "", ICON_COPYDOWN, "GRAPH_OT_driver_variables_copy");
- uiItemO(row, "", ICON_PASTEDOWN, "GRAPH_OT_driver_variables_paste");
- }
-
- /* loop over targets, drawing them */
- for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
- PointerRNA dvar_ptr;
- uiLayout *box;
- uiLayout *subrow, *sub;
-
- /* sub-layout column for this variable's settings */
- col = uiLayoutColumn(layout, true);
-
- /* 1) header panel */
- box = uiLayoutBox(col);
- RNA_pointer_create(id, &RNA_DriverVariable, dvar, &dvar_ptr);
-
- row = uiLayoutRow(box, false);
- block = uiLayoutGetBlock(row);
-
- /* 1.1) variable type and name */
- subrow = uiLayoutRow(row, true);
-
- /* 1.1.1) variable type */
-
- /* HACK: special group just for the enum,
- * otherwise we get ugly layout with text included too... */
- sub = uiLayoutRow(subrow, true);
-
- uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
-
- uiItemR(sub, &dvar_ptr, "type", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
-
- /* 1.1.2) variable name */
-
- /* HACK: special group to counteract the effects of the previous enum,
- * which now pushes everything too far right */
- sub = uiLayoutRow(subrow, true);
-
- uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_EXPAND);
-
- uiItemR(sub, &dvar_ptr, "name", 0, "", ICON_NONE);
-
- /* 1.2) invalid name? */
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
- if (dvar->flag & DVAR_FLAG_INVALID_NAME) {
- but = uiDefIconBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ERROR, 290, 0, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, IFACE_("Invalid variable name, click here for details"));
- UI_but_func_set(but, driver_dvar_invalid_name_query_cb, dvar, NULL); // XXX: reports?
- }
-
- /* 1.3) remove button */
- but = uiDefIconBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_X, 290, 0, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, IFACE_("Delete target variable"));
- UI_but_func_set(but, driver_delete_var_cb, driver, dvar);
- UI_block_emboss_set(block, UI_EMBOSS);
-
-
- /* 2) variable type settings */
- box = uiLayoutBox(col);
- /* controls to draw depends on the type of variable */
- switch (dvar->type) {
- case DVAR_TYPE_SINGLE_PROP: /* single property */
- graph_panel_driverVar__singleProp(box, id, dvar);
- break;
- case DVAR_TYPE_ROT_DIFF: /* rotational difference */
- graph_panel_driverVar__rotDiff(box, id, dvar);
- break;
- case DVAR_TYPE_LOC_DIFF: /* location difference */
- graph_panel_driverVar__locDiff(box, id, dvar);
- break;
- case DVAR_TYPE_TRANSFORM_CHAN: /* transform channel */
- graph_panel_driverVar__transChan(box, id, dvar);
- break;
- }
-
- /* 3) value of variable */
- {
- char valBuf[32];
-
- box = uiLayoutBox(col);
- row = uiLayoutRow(box, true);
- uiItemL(row, IFACE_("Value:"), ICON_NONE);
-
- if ((dvar->type == DVAR_TYPE_ROT_DIFF) ||
- (dvar->type == DVAR_TYPE_TRANSFORM_CHAN &&
- dvar->targets[0].transChan >= DTAR_TRANSCHAN_ROTX &&
- dvar->targets[0].transChan < DTAR_TRANSCHAN_SCALEX))
- {
- BLI_snprintf(valBuf, sizeof(valBuf), "%.3f (%4.1f°)", dvar->curval, RAD2DEGF(dvar->curval));
- }
- else {
- BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", dvar->curval);
- }
-
- uiItemL(row, valBuf, ICON_NONE);
- }
- }
-
- uiItemS(layout);
- uiItemS(layout);
-
- /* XXX: This should become redundant. But sometimes the flushing fails,
- * so keep this around for a while longer as a "last resort" */
- row = uiLayoutRow(layout, true);
- block = uiLayoutGetBlock(row);
- but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_FILE_REFRESH, IFACE_("Update Dependencies"),
- 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0, 0,
- TIP_("Force updates of dependencies - Only use this if drivers are not updating correctly"));
- UI_but_func_set(but, driver_update_flags_cb, fcu, NULL);
+ ChannelDriver *driver = fcu->driver;
+ DriverVar *dvar;
+
+ PointerRNA driver_ptr;
+ uiLayout *col, *row;
+ uiBlock *block;
+ uiBut *but;
+
+ /* set event handler for panel */
+ block = uiLayoutGetBlock(layout);
+ UI_block_func_handle_set(block, do_graph_region_driver_buttons, id);
+
+ /* driver-level settings - type, expressions, and errors */
+ RNA_pointer_create(id, &RNA_Driver, driver, &driver_ptr);
+
+ col = uiLayoutColumn(layout, true);
+ block = uiLayoutGetBlock(col);
+ uiItemR(col, &driver_ptr, "type", 0, NULL, ICON_NONE);
+
+ {
+ char valBuf[32];
+
+ /* value of driver */
+ row = uiLayoutRow(col, true);
+ uiItemL(row, IFACE_("Driver Value:"), ICON_NONE);
+ BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", driver->curval);
+ uiItemL(row, valBuf, ICON_NONE);
+ }
+
+ uiItemS(layout);
+ uiItemS(layout);
+
+ /* show expression box if doing scripted drivers, and/or error messages when invalid drivers exist */
+ if (driver->type == DRIVER_TYPE_PYTHON) {
+ bool bpy_data_expr_error = (strstr(driver->expression, "bpy.data.") != NULL);
+ bool bpy_ctx_expr_error = (strstr(driver->expression, "bpy.context.") != NULL);
+
+ /* expression */
+ /* TODO: "Show syntax hints" button */
+ col = uiLayoutColumn(layout, true);
+ block = uiLayoutGetBlock(col);
+
+ uiItemL(col, IFACE_("Expression:"), ICON_NONE);
+ uiItemR(col, &driver_ptr, "expression", 0, "", ICON_NONE);
+ uiItemR(col, &driver_ptr, "use_self", 0, NULL, ICON_NONE);
+
+ /* errors? */
+ col = uiLayoutColumn(layout, true);
+ block = uiLayoutGetBlock(col);
+
+ if (driver->flag & DRIVER_FLAG_INVALID) {
+ uiItemL(col, IFACE_("ERROR: Invalid Python expression"), ICON_CANCEL);
+ }
+ else if (!BKE_driver_has_simple_expression(driver)) {
+ if ((G.f & G_FLAG_SCRIPT_AUTOEXEC) == 0) {
+ /* TODO: Add button to enable? */
+ uiItemL(col, IFACE_("WARNING: Python expressions limited for security"), ICON_ERROR);
+ }
+ else {
+ uiItemL(col, IFACE_("Slow Python expression"), ICON_INFO);
+ }
+ }
+
+ /* Explicit bpy-references are evil. Warn about these to prevent errors */
+ /* TODO: put these in a box? */
+ if (bpy_data_expr_error || bpy_ctx_expr_error) {
+ uiItemL(col, IFACE_("WARNING: Driver expression may not work correctly"), ICON_HELP);
+
+ if (bpy_data_expr_error) {
+ uiItemL(
+ col, IFACE_("TIP: Use variables instead of bpy.data paths (see below)"), ICON_ERROR);
+ }
+ if (bpy_ctx_expr_error) {
+ uiItemL(col, IFACE_("TIP: bpy.context is not safe for renderfarm usage"), ICON_ERROR);
+ }
+ }
+ }
+ else {
+ /* errors? */
+ col = uiLayoutColumn(layout, true);
+ block = uiLayoutGetBlock(col);
+
+ if (driver->flag & DRIVER_FLAG_INVALID)
+ uiItemL(col, IFACE_("ERROR: Invalid target channel(s)"), ICON_ERROR);
+
+ /* Warnings about a lack of variables
+ * NOTE: The lack of variables is generally a bad thing, since it indicates
+ * that the driver doesn't work at all. This particular scenario arises
+ * primarily when users mistakenly try to use drivers for procedural
+ * property animation
+ */
+ if (BLI_listbase_is_empty(&driver->variables)) {
+ uiItemL(col, IFACE_("ERROR: Driver is useless without any inputs"), ICON_ERROR);
+
+ if (!BLI_listbase_is_empty(&fcu->modifiers)) {
+ uiItemL(col, IFACE_("TIP: Use F-Curves for procedural animation instead"), ICON_INFO);
+ uiItemL(col, IFACE_("F-Modifiers can generate curves for those too"), ICON_INFO);
+ }
+ }
+ }
+
+ uiItemS(layout);
+
+ /* add/copy/paste driver variables */
+ if (is_popover) {
+ /* add driver variable - add blank */
+ row = uiLayoutRow(layout, true);
+ block = uiLayoutGetBlock(row);
+ but = uiDefIconTextBut(
+ block,
+ UI_BTYPE_BUT,
+ B_IPO_DEPCHANGE,
+ ICON_ADD,
+ IFACE_("Add Input Variable"),
+ 0,
+ 0,
+ 10 * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ TIP_("Add a Driver Variable to keep track an input used by the driver"));
+ UI_but_func_set(but, driver_add_var_cb, driver, NULL);
+
+ /* add driver variable - add using eyedropper */
+ /* XXX: will this operator work like this? */
+ uiItemO(row, "", ICON_EYEDROPPER, "UI_OT_eyedropper_driver");
+ }
+ else {
+ /* add driver variable */
+ row = uiLayoutRow(layout, false);
+ block = uiLayoutGetBlock(row);
+ but = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ B_IPO_DEPCHANGE,
+ ICON_ADD,
+ IFACE_("Add Input Variable"),
+ 0,
+ 0,
+ 10 * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ TIP_("Driver variables ensure that all dependencies will be accounted "
+ "for, ensuring that drivers will update correctly"));
+ UI_but_func_set(but, driver_add_var_cb, driver, NULL);
+
+ /* copy/paste (as sub-row) */
+ row = uiLayoutRow(row, true);
+ block = uiLayoutGetBlock(row);
+
+ uiItemO(row, "", ICON_COPYDOWN, "GRAPH_OT_driver_variables_copy");
+ uiItemO(row, "", ICON_PASTEDOWN, "GRAPH_OT_driver_variables_paste");
+ }
+
+ /* loop over targets, drawing them */
+ for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
+ PointerRNA dvar_ptr;
+ uiLayout *box;
+ uiLayout *subrow, *sub;
+
+ /* sub-layout column for this variable's settings */
+ col = uiLayoutColumn(layout, true);
+
+ /* 1) header panel */
+ box = uiLayoutBox(col);
+ RNA_pointer_create(id, &RNA_DriverVariable, dvar, &dvar_ptr);
+
+ row = uiLayoutRow(box, false);
+ block = uiLayoutGetBlock(row);
+
+ /* 1.1) variable type and name */
+ subrow = uiLayoutRow(row, true);
+
+ /* 1.1.1) variable type */
+
+ /* HACK: special group just for the enum,
+ * otherwise we get ugly layout with text included too... */
+ sub = uiLayoutRow(subrow, true);
+
+ uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
+
+ uiItemR(sub, &dvar_ptr, "type", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+
+ /* 1.1.2) variable name */
+
+ /* HACK: special group to counteract the effects of the previous enum,
+ * which now pushes everything too far right */
+ sub = uiLayoutRow(subrow, true);
+
+ uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_EXPAND);
+
+ uiItemR(sub, &dvar_ptr, "name", 0, "", ICON_NONE);
+
+ /* 1.2) invalid name? */
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+
+ if (dvar->flag & DVAR_FLAG_INVALID_NAME) {
+ but = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ B_IPO_DEPCHANGE,
+ ICON_ERROR,
+ 290,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ IFACE_("Invalid variable name, click here for details"));
+ UI_but_func_set(but, driver_dvar_invalid_name_query_cb, dvar, NULL); // XXX: reports?
+ }
+
+ /* 1.3) remove button */
+ but = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ B_IPO_DEPCHANGE,
+ ICON_X,
+ 290,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ IFACE_("Delete target variable"));
+ UI_but_func_set(but, driver_delete_var_cb, driver, dvar);
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ /* 2) variable type settings */
+ box = uiLayoutBox(col);
+ /* controls to draw depends on the type of variable */
+ switch (dvar->type) {
+ case DVAR_TYPE_SINGLE_PROP: /* single property */
+ graph_panel_driverVar__singleProp(box, id, dvar);
+ break;
+ case DVAR_TYPE_ROT_DIFF: /* rotational difference */
+ graph_panel_driverVar__rotDiff(box, id, dvar);
+ break;
+ case DVAR_TYPE_LOC_DIFF: /* location difference */
+ graph_panel_driverVar__locDiff(box, id, dvar);
+ break;
+ case DVAR_TYPE_TRANSFORM_CHAN: /* transform channel */
+ graph_panel_driverVar__transChan(box, id, dvar);
+ break;
+ }
+
+ /* 3) value of variable */
+ {
+ char valBuf[32];
+
+ box = uiLayoutBox(col);
+ row = uiLayoutRow(box, true);
+ uiItemL(row, IFACE_("Value:"), ICON_NONE);
+
+ if ((dvar->type == DVAR_TYPE_ROT_DIFF) ||
+ (dvar->type == DVAR_TYPE_TRANSFORM_CHAN &&
+ dvar->targets[0].transChan >= DTAR_TRANSCHAN_ROTX &&
+ dvar->targets[0].transChan < DTAR_TRANSCHAN_SCALEX)) {
+ BLI_snprintf(
+ valBuf, sizeof(valBuf), "%.3f (%4.1f°)", dvar->curval, RAD2DEGF(dvar->curval));
+ }
+ else {
+ BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", dvar->curval);
+ }
+
+ uiItemL(row, valBuf, ICON_NONE);
+ }
+ }
+
+ uiItemS(layout);
+ uiItemS(layout);
+
+ /* XXX: This should become redundant. But sometimes the flushing fails,
+ * so keep this around for a while longer as a "last resort" */
+ row = uiLayoutRow(layout, true);
+ block = uiLayoutGetBlock(row);
+ but = uiDefIconTextBut(
+ block,
+ UI_BTYPE_BUT,
+ B_IPO_DEPCHANGE,
+ ICON_FILE_REFRESH,
+ IFACE_("Update Dependencies"),
+ 0,
+ 0,
+ 10 * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ TIP_("Force updates of dependencies - Only use this if drivers are not updating correctly"));
+ UI_but_func_set(but, driver_update_flags_cb, fcu, NULL);
}
/* ----------------------------------------------------------------- */
-
/* 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)
{
- bAnimListElem *ale;
- FCurve *fcu;
+ bAnimListElem *ale;
+ FCurve *fcu;
- if (!graph_panel_context(C, &ale, &fcu))
- return;
+ if (!graph_panel_context(C, &ale, &fcu))
+ return;
- graph_draw_driven_property_panel(pa->layout, ale->id, fcu);
+ graph_draw_driven_property_panel(pa->layout, ale->id, fcu);
- MEM_freeN(ale);
+ 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)
{
- bAnimListElem *ale;
- FCurve *fcu;
+ bAnimListElem *ale;
+ FCurve *fcu;
- /* Get settings from context */
- if (!graph_panel_context(C, &ale, &fcu))
- return;
+ /* Get settings from context */
+ if (!graph_panel_context(C, &ale, &fcu))
+ return;
- graph_draw_driver_settings_panel(pa->layout, ale->id, fcu, false);
+ graph_draw_driver_settings_panel(pa->layout, ale->id, fcu, false);
- /* cleanup */
- MEM_freeN(ale);
+ /* cleanup */
+ MEM_freeN(ale);
}
/* ----------------------------------------------------------------- */
@@ -1048,205 +1226,206 @@ static void graph_panel_drivers(const bContext *C, Panel *pa)
/* poll to make this not show up in the graph editor, as this is only to be used as a popup elsewhere */
static bool graph_panel_drivers_popover_poll(const bContext *C, PanelType *UNUSED(pt))
{
- return ED_operator_graphedit_active((bContext *)C) == false;
+ return ED_operator_graphedit_active((bContext *)C) == false;
}
/* popover panel for driver editing anywhere in ui */
static void graph_panel_drivers_popover(const bContext *C, Panel *pa)
{
- uiLayout *layout = pa->layout;
-
- PointerRNA ptr = {{NULL}};
- PropertyRNA *prop = NULL;
- int index = -1;
- uiBut *but = NULL;
-
- /* Get active property to show driver properties for */
- but = UI_context_active_but_prop_get((bContext *)C, &ptr, &prop, &index);
- if (but) {
- FCurve *fcu;
- bool driven, special;
-
- fcu = rna_get_fcurve_context_ui((bContext *)C,
- &ptr, prop, index,
- NULL, NULL, &driven, &special);
-
- /* Hack: Force all buttons in this panel to be able to know the driver button
- * this panel is getting spawned from, so that things like the "Open Drivers Editor"
- * button will work.
- */
- uiLayoutSetContextFromBut(layout, but);
-
- /* Populate Panel - With a combination of the contents of the Driven and Driver panels */
- if (fcu) {
- ID *id = ptr.id.data;
-
- /* Driven Property Settings */
- uiItemL(layout, IFACE_("Driven Property:"), ICON_NONE);
- graph_draw_driven_property_panel(pa->layout, id, fcu);
- /* TODO: All vs Single */
-
- uiItemS(layout);
- uiItemS(layout);
-
- /* Drivers Settings */
- uiItemL(layout, IFACE_("Driver Settings:"), ICON_NONE);
- graph_draw_driver_settings_panel(pa->layout, id, fcu, true);
- }
- }
-
- /* Show drivers editor is always visible */
- uiItemO(layout, IFACE_("Show in Drivers Editor"), ICON_DRIVER, "SCREEN_OT_drivers_editor_show");
+ uiLayout *layout = pa->layout;
+
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop = NULL;
+ int index = -1;
+ uiBut *but = NULL;
+
+ /* Get active property to show driver properties for */
+ but = UI_context_active_but_prop_get((bContext *)C, &ptr, &prop, &index);
+ if (but) {
+ FCurve *fcu;
+ bool driven, special;
+
+ fcu = rna_get_fcurve_context_ui(
+ (bContext *)C, &ptr, prop, index, NULL, NULL, &driven, &special);
+
+ /* Hack: Force all buttons in this panel to be able to know the driver button
+ * this panel is getting spawned from, so that things like the "Open Drivers Editor"
+ * button will work.
+ */
+ uiLayoutSetContextFromBut(layout, but);
+
+ /* Populate Panel - With a combination of the contents of the Driven and Driver panels */
+ if (fcu) {
+ ID *id = ptr.id.data;
+
+ /* Driven Property Settings */
+ uiItemL(layout, IFACE_("Driven Property:"), ICON_NONE);
+ graph_draw_driven_property_panel(pa->layout, id, fcu);
+ /* TODO: All vs Single */
+
+ uiItemS(layout);
+ uiItemS(layout);
+
+ /* Drivers Settings */
+ uiItemL(layout, IFACE_("Driver Settings:"), ICON_NONE);
+ graph_draw_driver_settings_panel(pa->layout, id, fcu, true);
+ }
+ }
+
+ /* Show drivers editor is always visible */
+ uiItemO(layout, IFACE_("Show in Drivers Editor"), ICON_DRIVER, "SCREEN_OT_drivers_editor_show");
}
/* ******************* F-Modifiers ******************************** */
/* All the drawing code is in editors/animation/fmodifier_ui.c */
-#define B_FMODIFIER_REDRAW 20
+#define B_FMODIFIER_REDRAW 20
static void do_graph_region_modifier_buttons(bContext *C, void *UNUSED(arg), int event)
{
- switch (event) {
- case B_FMODIFIER_REDRAW: // XXX this should send depsgraph updates too
- WM_event_add_notifier(C, NC_ANIMATION, NULL); // XXX need a notifier specially for F-Modifiers
- break;
- }
+ switch (event) {
+ case B_FMODIFIER_REDRAW: // XXX this should send depsgraph updates too
+ WM_event_add_notifier(
+ C, NC_ANIMATION, NULL); // XXX need a notifier specially for F-Modifiers
+ break;
+ }
}
static void graph_panel_modifiers(const bContext *C, Panel *pa)
{
- bAnimListElem *ale;
- FCurve *fcu;
- FModifier *fcm;
- uiLayout *col, *row;
- uiBlock *block;
- bool active;
-
- if (!graph_panel_context(C, &ale, &fcu))
- return;
-
- block = uiLayoutGetBlock(pa->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);
-
- /* 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
- */
- uiItemMenuEnumO(row, (bContext *)C, "GRAPH_OT_fmodifier_add", "type", IFACE_("Add Modifier"), ICON_NONE);
-
- /* copy/paste (as sub-row) */
- row = uiLayoutRow(row, true);
- uiItemO(row, "", ICON_COPYDOWN, "GRAPH_OT_fmodifier_copy");
- uiItemO(row, "", ICON_PASTEDOWN, "GRAPH_OT_fmodifier_paste");
- }
-
- active = !(fcu->flag & FCURVE_MOD_OFF);
- /* draw each modifier */
- for (fcm = fcu->modifiers.first; fcm; fcm = fcm->next) {
- col = uiLayoutColumn(pa->layout, true);
- uiLayoutSetActive(col, active);
-
- ANIM_uiTemplate_fmodifier_draw(col, ale->fcurve_owner_id, &fcu->modifiers, fcm);
- }
-
- MEM_freeN(ale);
+ bAnimListElem *ale;
+ FCurve *fcu;
+ FModifier *fcm;
+ uiLayout *col, *row;
+ uiBlock *block;
+ bool active;
+
+ if (!graph_panel_context(C, &ale, &fcu))
+ return;
+
+ block = uiLayoutGetBlock(pa->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);
+
+ /* 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
+ */
+ uiItemMenuEnumO(
+ row, (bContext *)C, "GRAPH_OT_fmodifier_add", "type", IFACE_("Add Modifier"), ICON_NONE);
+
+ /* copy/paste (as sub-row) */
+ row = uiLayoutRow(row, true);
+ uiItemO(row, "", ICON_COPYDOWN, "GRAPH_OT_fmodifier_copy");
+ uiItemO(row, "", ICON_PASTEDOWN, "GRAPH_OT_fmodifier_paste");
+ }
+
+ active = !(fcu->flag & FCURVE_MOD_OFF);
+ /* draw each modifier */
+ for (fcm = fcu->modifiers.first; fcm; fcm = fcm->next) {
+ col = uiLayoutColumn(pa->layout, true);
+ uiLayoutSetActive(col, active);
+
+ ANIM_uiTemplate_fmodifier_draw(col, ale->fcurve_owner_id, &fcu->modifiers, fcm);
+ }
+
+ MEM_freeN(ale);
}
/* ******************* general ******************************** */
void graph_buttons_register(ARegionType *art)
{
- PanelType *pt;
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel properties");
- strcpy(pt->idname, "GRAPH_PT_properties");
- strcpy(pt->label, N_("Active F-Curve"));
- strcpy(pt->category, "F-Curve");
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = graph_panel_properties;
- pt->poll = graph_panel_poll;
- BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel properties");
- strcpy(pt->idname, "GRAPH_PT_key_properties");
- strcpy(pt->label, N_("Active Keyframe"));
- strcpy(pt->category, "F-Curve");
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = graph_panel_key_properties;
- pt->poll = graph_panel_poll;
- BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel drivers driven");
- strcpy(pt->idname, "GRAPH_PT_driven_property");
- strcpy(pt->label, N_("Driven Property"));
- strcpy(pt->category, "Drivers");
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = graph_panel_driven_property;
- pt->poll = graph_panel_drivers_poll;
- BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel drivers");
- strcpy(pt->idname, "GRAPH_PT_drivers");
- strcpy(pt->label, N_("Driver"));
- strcpy(pt->category, "Drivers");
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = graph_panel_drivers;
- pt->poll = graph_panel_drivers_poll;
- BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel drivers pover");
- strcpy(pt->idname, "GRAPH_PT_drivers_popover");
- strcpy(pt->label, N_("Add/Edit Driver"));
- strcpy(pt->category, "Drivers");
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = graph_panel_drivers_popover;
- pt->poll = graph_panel_drivers_popover_poll;
- BLI_addtail(&art->paneltypes, pt);
- /* This panel isn't used in this region.
- * Add explicitly to global list (so popovers work). */
- WM_paneltype_add(pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel modifiers");
- strcpy(pt->idname, "GRAPH_PT_modifiers");
- strcpy(pt->label, N_("Modifiers"));
- strcpy(pt->category, "Modifiers");
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = graph_panel_modifiers;
- pt->poll = graph_panel_poll;
- BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel view");
- strcpy(pt->idname, "GRAPH_PT_view");
- strcpy(pt->label, N_("View Properties"));
- strcpy(pt->category, "View");
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = graph_panel_view;
- BLI_addtail(&art->paneltypes, pt);
+ PanelType *pt;
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel properties");
+ strcpy(pt->idname, "GRAPH_PT_properties");
+ strcpy(pt->label, N_("Active F-Curve"));
+ strcpy(pt->category, "F-Curve");
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = graph_panel_properties;
+ pt->poll = graph_panel_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel properties");
+ strcpy(pt->idname, "GRAPH_PT_key_properties");
+ strcpy(pt->label, N_("Active Keyframe"));
+ strcpy(pt->category, "F-Curve");
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = graph_panel_key_properties;
+ pt->poll = graph_panel_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel drivers driven");
+ strcpy(pt->idname, "GRAPH_PT_driven_property");
+ strcpy(pt->label, N_("Driven Property"));
+ strcpy(pt->category, "Drivers");
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = graph_panel_driven_property;
+ pt->poll = graph_panel_drivers_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel drivers");
+ strcpy(pt->idname, "GRAPH_PT_drivers");
+ strcpy(pt->label, N_("Driver"));
+ strcpy(pt->category, "Drivers");
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = graph_panel_drivers;
+ pt->poll = graph_panel_drivers_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel drivers pover");
+ strcpy(pt->idname, "GRAPH_PT_drivers_popover");
+ strcpy(pt->label, N_("Add/Edit Driver"));
+ strcpy(pt->category, "Drivers");
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = graph_panel_drivers_popover;
+ pt->poll = graph_panel_drivers_popover_poll;
+ BLI_addtail(&art->paneltypes, pt);
+ /* This panel isn't used in this region.
+ * Add explicitly to global list (so popovers work). */
+ WM_paneltype_add(pt);
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel modifiers");
+ strcpy(pt->idname, "GRAPH_PT_modifiers");
+ strcpy(pt->label, N_("Modifiers"));
+ strcpy(pt->category, "Modifiers");
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = graph_panel_modifiers;
+ pt->poll = graph_panel_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel view");
+ strcpy(pt->idname, "GRAPH_PT_view");
+ strcpy(pt->label, N_("View Properties"));
+ strcpy(pt->category, "View");
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = graph_panel_view;
+ BLI_addtail(&art->paneltypes, pt);
}
static int graph_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = graph_has_buttons_region(sa);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = graph_has_buttons_region(sa);
- if (ar)
- ED_region_toggle_hidden(C, ar);
+ if (ar)
+ ED_region_toggle_hidden(C, ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_properties(wmOperatorType *ot)
{
- ot->name = "Toggle Sidebar";
- ot->idname = "GRAPH_OT_properties";
- ot->description = "Toggle the properties region visibility";
+ ot->name = "Toggle Sidebar";
+ ot->idname = "GRAPH_OT_properties";
+ ot->description = "Toggle the properties region visibility";
- ot->exec = graph_properties_toggle_exec;
- ot->poll = ED_operator_graphedit_active;
+ ot->exec = graph_properties_toggle_exec;
+ ot->poll = ED_operator_graphedit_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 52f45a66c0d..5bfe1c1aadd 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -20,7 +20,6 @@
* \ingroup spgraph
*/
-
#include <stdio.h>
#include <math.h>
#include <string.h>
@@ -40,7 +39,6 @@
#include "BKE_curve.h"
#include "BKE_fcurve.h"
-
#include "GPU_draw.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
@@ -63,7 +61,7 @@
*/
static float fcurve_display_alpha(FCurve *fcu)
{
- return (fcu->flag & FCURVE_SELECTED) ? 1.0f : U.fcu_inactive_alpha;
+ return (fcu->flag & FCURVE_SELECTED) ? 1.0f : U.fcu_inactive_alpha;
}
/* *************************** */
@@ -74,63 +72,64 @@ static float fcurve_display_alpha(FCurve *fcu)
/* TODO: draw a shaded poly showing the region of influence too!!! */
static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d)
{
- FMod_Envelope *env = (FMod_Envelope *)fcm->data;
- FCM_EnvelopeData *fed;
- const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur);
- int i;
+ FMod_Envelope *env = (FMod_Envelope *)fcm->data;
+ FCM_EnvelopeData *fed;
+ const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur);
+ int i;
- const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- GPU_line_width(1.0f);
+ GPU_line_width(1.0f);
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
- immUniform1i("colors_len", 0); /* Simple dashes. */
- immUniformColor3f(0.0f, 0.0f, 0.0f);
- immUniform1f("dash_width", 10.0f);
- immUniform1f("dash_factor", 0.5f);
+ immUniform1i("colors_len", 0); /* Simple dashes. */
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+ immUniform1f("dash_width", 10.0f);
+ immUniform1f("dash_factor", 0.5f);
- /* draw two black lines showing the standard reference levels */
+ /* draw two black lines showing the standard reference levels */
- immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(shdr_pos, v2d->cur.xmin, env->midval + env->min);
- immVertex2f(shdr_pos, v2d->cur.xmax, env->midval + env->min);
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex2f(shdr_pos, v2d->cur.xmin, env->midval + env->min);
+ immVertex2f(shdr_pos, v2d->cur.xmax, env->midval + env->min);
- immVertex2f(shdr_pos, v2d->cur.xmin, env->midval + env->max);
- immVertex2f(shdr_pos, v2d->cur.xmax, env->midval + env->max);
- immEnd();
+ immVertex2f(shdr_pos, v2d->cur.xmin, env->midval + env->max);
+ immVertex2f(shdr_pos, v2d->cur.xmax, env->midval + env->max);
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
- if (env->totvert > 0) {
- /* set size of vertices (non-adjustable for now) */
- GPU_point_size(2.0f);
+ if (env->totvert > 0) {
+ /* set size of vertices (non-adjustable for now) */
+ GPU_point_size(2.0f);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- /* for now, point color is fixed, and is white */
- immUniformColor3f(1.0f, 1.0f, 1.0f);
+ /* for now, point color is fixed, and is white */
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
- immBeginAtMost(GPU_PRIM_POINTS, env->totvert * 2);
+ immBeginAtMost(GPU_PRIM_POINTS, env->totvert * 2);
- for (i = 0, fed = env->data; i < env->totvert; i++, fed++) {
- /* only draw if visible
- * - min/max here are fixed, not relative
- */
- if (IN_RANGE(fed->time, (v2d->cur.xmin - fac), (v2d->cur.xmax + fac))) {
- immVertex2f(shdr_pos, fed->time, fed->min);
- immVertex2f(shdr_pos, fed->time, fed->max);
- }
- }
+ for (i = 0, fed = env->data; i < env->totvert; i++, fed++) {
+ /* only draw if visible
+ * - min/max here are fixed, not relative
+ */
+ if (IN_RANGE(fed->time, (v2d->cur.xmin - fac), (v2d->cur.xmax + fac))) {
+ immVertex2f(shdr_pos, fed->time, fed->min);
+ immVertex2f(shdr_pos, fed->time, fed->max);
+ }
+ }
- immEnd();
+ immEnd();
- immUnbindProgram();
- }
+ immUnbindProgram();
+ }
}
/* *************************** */
@@ -141,283 +140,282 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d)
/* helper func - set color to draw F-Curve data with */
static void set_fcurve_vertex_color(FCurve *fcu, bool sel)
{
- float color[4];
- float diff;
-
- /* Set color of curve vertex based on state of curve (i.e. 'Edit' Mode) */
- if ((fcu->flag & FCURVE_PROTECTED) == 0) {
- /* Curve's points ARE BEING edited */
- UI_GetThemeColor3fv(sel ? TH_VERTEX_SELECT : TH_VERTEX, color);
- }
- else {
- /* Curve's points CANNOT BE edited */
- UI_GetThemeColor3fv(sel ? TH_TEXT_HI : TH_TEXT, color);
- }
-
- /* Fade the 'intensity' of the vertices based on the selection of the curves too
- * - Only fade by 50% the amount the curves were faded by, so that the points
- * still stand out for easier selection
- */
- diff = 1.0f - fcurve_display_alpha(fcu);
- color[3] = 1.0f - (diff * 0.5f);
- CLAMP(color[3], 0.2f, 1.0f);
-
- immUniformColor4fv(color);
+ float color[4];
+ float diff;
+
+ /* Set color of curve vertex based on state of curve (i.e. 'Edit' Mode) */
+ if ((fcu->flag & FCURVE_PROTECTED) == 0) {
+ /* Curve's points ARE BEING edited */
+ UI_GetThemeColor3fv(sel ? TH_VERTEX_SELECT : TH_VERTEX, color);
+ }
+ else {
+ /* Curve's points CANNOT BE edited */
+ UI_GetThemeColor3fv(sel ? TH_TEXT_HI : TH_TEXT, color);
+ }
+
+ /* Fade the 'intensity' of the vertices based on the selection of the curves too
+ * - Only fade by 50% the amount the curves were faded by, so that the points
+ * still stand out for easier selection
+ */
+ diff = 1.0f - fcurve_display_alpha(fcu);
+ color[3] = 1.0f - (diff * 0.5f);
+ CLAMP(color[3], 0.2f, 1.0f);
+
+ immUniformColor4fv(color);
}
-static void draw_fcurve_selected_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, bool sel, unsigned pos)
+static void draw_fcurve_selected_keyframe_vertices(
+ FCurve *fcu, View2D *v2d, bool edit, bool sel, unsigned pos)
{
- const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur);
-
- set_fcurve_vertex_color(fcu, sel);
-
- immBeginAtMost(GPU_PRIM_POINTS, fcu->totvert);
-
- BezTriple *bezt = fcu->bezt;
- for (int i = 0; i < fcu->totvert; i++, bezt++) {
- /* as an optimization step, only draw those in view
- * - we apply a correction factor to ensure that points don't pop in/out due to slight twitches of view size
- */
- if (IN_RANGE(bezt->vec[1][0], (v2d->cur.xmin - fac), (v2d->cur.xmax + fac))) {
- if (edit) {
- /* 'Keyframe' vertex only, as handle lines and handles have already been drawn
- * - only draw those with correct selection state for the current drawing color
- * -
- */
- if ((bezt->f2 & SELECT) == sel)
- immVertex2fv(pos, bezt->vec[1]);
- }
- else {
- /* no check for selection here, as curve is not editable... */
- /* XXX perhaps we don't want to even draw points? maybe add an option for that later */
- immVertex2fv(pos, bezt->vec[1]);
- }
- }
- }
-
- immEnd();
+ const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur);
+
+ set_fcurve_vertex_color(fcu, sel);
+
+ immBeginAtMost(GPU_PRIM_POINTS, fcu->totvert);
+
+ BezTriple *bezt = fcu->bezt;
+ for (int i = 0; i < fcu->totvert; i++, bezt++) {
+ /* as an optimization step, only draw those in view
+ * - we apply a correction factor to ensure that points don't pop in/out due to slight twitches of view size
+ */
+ if (IN_RANGE(bezt->vec[1][0], (v2d->cur.xmin - fac), (v2d->cur.xmax + fac))) {
+ if (edit) {
+ /* 'Keyframe' vertex only, as handle lines and handles have already been drawn
+ * - only draw those with correct selection state for the current drawing color
+ * -
+ */
+ if ((bezt->f2 & SELECT) == sel)
+ immVertex2fv(pos, bezt->vec[1]);
+ }
+ else {
+ /* no check for selection here, as curve is not editable... */
+ /* XXX perhaps we don't want to even draw points? maybe add an option for that later */
+ immVertex2fv(pos, bezt->vec[1]);
+ }
+ }
+ }
+
+ immEnd();
}
/* helper func - draw keyframe vertices only for an F-Curve */
static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, unsigned pos)
{
- immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
- immUniform1f("size", UI_GetThemeValuef(TH_VERTEX_SIZE) * U.pixelsize);
+ immUniform1f("size", UI_GetThemeValuef(TH_VERTEX_SIZE) * U.pixelsize);
- draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, false, pos);
- draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, true, pos);
+ draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, false, pos);
+ draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, true, pos);
- immUnbindProgram();
+ immUnbindProgram();
}
-
/* 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)
+static void draw_fcurve_selected_handle_vertices(
+ FCurve *fcu, View2D *v2d, bool sel, bool sel_handle_only, unsigned pos)
{
- (void) v2d; /* TODO: use this to draw only points in view */
-
- /* set handle color */
- float hcolor[3];
- UI_GetThemeColor3fv(sel ? TH_HANDLE_VERTEX_SELECT : TH_HANDLE_VERTEX, hcolor);
- immUniform4f("outlineColor", hcolor[0], hcolor[1], hcolor[2], 1.0f);
- immUniformColor3fvAlpha(hcolor, 0.01f); /* almost invisible - only keep for smoothness */
-
- immBeginAtMost(GPU_PRIM_POINTS, fcu->totvert * 2);
-
- BezTriple *bezt = fcu->bezt;
- BezTriple *prevbezt = NULL;
- for (int i = 0; i < fcu->totvert; i++, prevbezt = bezt, bezt++) {
- /* Draw the editmode handles for a bezier curve (others don't have handles)
- * if their selection status matches the selection status we're drawing for
- * - first handle only if previous beztriple was bezier-mode
- * - second handle only if current beztriple is bezier-mode
- *
- * Also, need to take into account whether the keyframe was selected
- * if a Graph Editor option to only show handles of selected keys is on.
- */
- if (!sel_handle_only || BEZT_ISSEL_ANY(bezt)) {
- if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
- if ((bezt->f1 & SELECT) == sel
- /* && v2d->cur.xmin < bezt->vec[0][0] < v2d->cur.xmax) */ )
- {
- immVertex2fv(pos, bezt->vec[0]);
- }
- }
-
- if (bezt->ipo == BEZT_IPO_BEZ) {
- if ((bezt->f3 & SELECT) == sel
- /* && v2d->cur.xmin < bezt->vec[2][0] < v2d->cur.xmax) */ )
- {
- immVertex2fv(pos, bezt->vec[2]);
- }
- }
- }
- }
-
- immEnd();
+ (void)v2d; /* TODO: use this to draw only points in view */
+
+ /* set handle color */
+ float hcolor[3];
+ UI_GetThemeColor3fv(sel ? TH_HANDLE_VERTEX_SELECT : TH_HANDLE_VERTEX, hcolor);
+ immUniform4f("outlineColor", hcolor[0], hcolor[1], hcolor[2], 1.0f);
+ immUniformColor3fvAlpha(hcolor, 0.01f); /* almost invisible - only keep for smoothness */
+
+ immBeginAtMost(GPU_PRIM_POINTS, fcu->totvert * 2);
+
+ BezTriple *bezt = fcu->bezt;
+ BezTriple *prevbezt = NULL;
+ for (int i = 0; i < fcu->totvert; i++, prevbezt = bezt, bezt++) {
+ /* Draw the editmode handles for a bezier curve (others don't have handles)
+ * if their selection status matches the selection status we're drawing for
+ * - first handle only if previous beztriple was bezier-mode
+ * - second handle only if current beztriple is bezier-mode
+ *
+ * Also, need to take into account whether the keyframe was selected
+ * if a Graph Editor option to only show handles of selected keys is on.
+ */
+ if (!sel_handle_only || BEZT_ISSEL_ANY(bezt)) {
+ if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) ||
+ (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
+ if ((bezt->f1 & SELECT) == sel
+ /* && v2d->cur.xmin < bezt->vec[0][0] < v2d->cur.xmax) */) {
+ immVertex2fv(pos, bezt->vec[0]);
+ }
+ }
+
+ if (bezt->ipo == BEZT_IPO_BEZ) {
+ if ((bezt->f3 & SELECT) == sel
+ /* && v2d->cur.xmin < bezt->vec[2][0] < v2d->cur.xmax) */) {
+ immVertex2fv(pos, bezt->vec[2]);
+ }
+ }
+ }
+ }
+
+ immEnd();
}
/* 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,
+ unsigned pos)
{
- /* smooth outlines for more consistent appearance */
- immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
+ /* smooth outlines for more consistent appearance */
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
- /* set handle size */
- immUniform1f("size", (1.4f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE)) * U.pixelsize);
- immUniform1f("outlineWidth", 1.5f * U.pixelsize);
+ /* set handle size */
+ immUniform1f("size", (1.4f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE)) * U.pixelsize);
+ immUniform1f("outlineWidth", 1.5f * U.pixelsize);
- draw_fcurve_selected_handle_vertices(fcu, v2d, false, sel_handle_only, pos);
- draw_fcurve_selected_handle_vertices(fcu, v2d, true, sel_handle_only, pos);
+ draw_fcurve_selected_handle_vertices(fcu, v2d, false, sel_handle_only, pos);
+ draw_fcurve_selected_handle_vertices(fcu, v2d, true, sel_handle_only, pos);
- immUnbindProgram();
+ immUnbindProgram();
}
-
static void draw_fcurve_vertices(ARegion *ar, FCurve *fcu, bool do_handles, bool sel_handle_only)
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &ar->v2d;
- /* only draw points if curve is visible
- * - draw unselected points before selected points as separate passes
- * to make sure in the case of overlapping points that the selected is always visible
- * - draw handles before keyframes, so that keyframes will overlap handles (keyframes are more important for users)
- */
+ /* only draw points if curve is visible
+ * - draw unselected points before selected points as separate passes
+ * to make sure in the case of overlapping points that the selected is always visible
+ * - draw handles before keyframes, so that keyframes will overlap handles (keyframes are more important for users)
+ */
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- GPU_blend(true);
- GPU_enable_program_point_size();
+ GPU_blend(true);
+ GPU_enable_program_point_size();
- /* draw the two handles first (if they're shown, the curve doesn't
- * have just a single keyframe, and the curve is being edited) */
- if (do_handles) {
- draw_fcurve_handle_vertices(fcu, v2d, sel_handle_only, pos);
- }
+ /* draw the two handles first (if they're shown, the curve doesn't
+ * have just a single keyframe, and the curve is being edited) */
+ if (do_handles) {
+ draw_fcurve_handle_vertices(fcu, v2d, sel_handle_only, pos);
+ }
- /* draw keyframes over the handles */
- draw_fcurve_keyframe_vertices(fcu, v2d, !(fcu->flag & FCURVE_PROTECTED), pos);
+ /* draw keyframes over the handles */
+ draw_fcurve_keyframe_vertices(fcu, v2d, !(fcu->flag & FCURVE_PROTECTED), pos);
- GPU_disable_program_point_size();
- GPU_blend(false);
+ GPU_disable_program_point_size();
+ GPU_blend(false);
}
/* Handles ---------------- */
static bool draw_fcurve_handles_check(SpaceGraph *sipo, FCurve *fcu)
{
- /* don't draw handle lines if handles are not to be shown */
- if (
- /* handles shouldn't be shown anywhere */
- (sipo->flag & SIPO_NOHANDLES) ||
- /* keyframes aren't editable */
- (fcu->flag & FCURVE_PROTECTED) ||
-#if 0 /* handles can still be selected and handle types set, better draw - campbell */
- /* editing the handles here will cause weird/incorrect interpolation issues */
- (fcu->flag & FCURVE_INT_VALUES) ||
+ /* don't draw handle lines if handles are not to be shown */
+ if (
+ /* handles shouldn't be shown anywhere */
+ (sipo->flag & SIPO_NOHANDLES) ||
+ /* keyframes aren't editable */
+ (fcu->flag & FCURVE_PROTECTED) ||
+#if 0 /* handles can still be selected and handle types set, better draw - campbell */
+ /* editing the handles here will cause weird/incorrect interpolation issues */
+ (fcu->flag & FCURVE_INT_VALUES) ||
#endif
- /* group that curve belongs to is not editable */
- ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
- /* do not show handles if there is only 1 keyframe,
- * otherwise they all clump together in an ugly ball */
- (fcu->totvert <= 1)
- )
- {
- return false;
- }
- else {
- return true;
- }
+ /* group that curve belongs to is not editable */
+ ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
+ /* do not show handles if there is only 1 keyframe,
+ * otherwise they all clump together in an ugly ball */
+ (fcu->totvert <= 1)) {
+ return false;
+ }
+ else {
+ return true;
+ }
}
/* draw lines for F-Curve handles only (this is only done in EditMode)
* note: draw_fcurve_handles_check must be checked before running this. */
static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu)
{
- int sel, b;
-
- GPUVertFormat *format = immVertexFormat();
- 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_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
-
- immBeginAtMost(GPU_PRIM_LINES, 4 * 2 * fcu->totvert);
-
- /* slightly hacky, but we want to draw unselected points before selected ones
- * so that selected points are clearly visible
- */
- for (sel = 0; sel < 2; sel++) {
- BezTriple *bezt = fcu->bezt, *prevbezt = NULL;
- int basecol = (sel) ? TH_HANDLE_SEL_FREE : TH_HANDLE_FREE;
- const float *fp;
- unsigned char col[4];
-
- for (b = 0; b < fcu->totvert; b++, prevbezt = bezt, bezt++) {
- /* if only selected keyframes can get their handles shown,
- * check that keyframe is selected
- */
- if (sipo->flag & SIPO_SELVHANDLESONLY) {
- if (BEZT_ISSEL_ANY(bezt) == 0)
- continue;
- }
-
- /* draw handle with appropriate set of colors if selection is ok */
- if ((bezt->f2 & SELECT) == sel) {
- fp = bezt->vec[0];
-
- /* only draw first handle if previous segment had handles */
- if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
- UI_GetThemeColor3ubv(basecol + bezt->h1, col);
- col[3] = fcurve_display_alpha(fcu) * 255;
- immAttr4ubv(color, col);
- immVertex2fv(pos, fp);
- immAttr4ubv(color, col);
- immVertex2fv(pos, fp + 3);
- }
-
- /* only draw second handle if this segment is bezier */
- if (bezt->ipo == BEZT_IPO_BEZ) {
- UI_GetThemeColor3ubv(basecol + bezt->h2, col);
- col[3] = fcurve_display_alpha(fcu) * 255;
- immAttr4ubv(color, col);
- immVertex2fv(pos, fp + 3);
- immAttr4ubv(color, col);
- immVertex2fv(pos, fp + 6);
- }
- }
- else {
- /* only draw first handle if previous segment was had handles, and selection is ok */
- if (((bezt->f1 & SELECT) == sel) &&
- ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))))
- {
- fp = bezt->vec[0];
- UI_GetThemeColor3ubv(basecol + bezt->h1, col);
- col[3] = fcurve_display_alpha(fcu) * 255;
- immAttr4ubv(color, col);
- immVertex2fv(pos, fp);
- immAttr4ubv(color, col);
- immVertex2fv(pos, fp + 3);
- }
-
- /* only draw second handle if this segment is bezier, and selection is ok */
- if (((bezt->f3 & SELECT) == sel) &&
- (bezt->ipo == BEZT_IPO_BEZ))
- {
- fp = bezt->vec[1];
- UI_GetThemeColor3ubv(basecol + bezt->h2, col);
- col[3] = fcurve_display_alpha(fcu) * 255;
- immAttr4ubv(color, col);
- immVertex2fv(pos, fp);
- immAttr4ubv(color, col);
- immVertex2fv(pos, fp + 3);
- }
- }
- }
- }
-
- immEnd();
- immUnbindProgram();
+ int sel, b;
+
+ GPUVertFormat *format = immVertexFormat();
+ 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_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
+ immBeginAtMost(GPU_PRIM_LINES, 4 * 2 * fcu->totvert);
+
+ /* slightly hacky, but we want to draw unselected points before selected ones
+ * so that selected points are clearly visible
+ */
+ for (sel = 0; sel < 2; sel++) {
+ BezTriple *bezt = fcu->bezt, *prevbezt = NULL;
+ int basecol = (sel) ? TH_HANDLE_SEL_FREE : TH_HANDLE_FREE;
+ const float *fp;
+ unsigned char col[4];
+
+ for (b = 0; b < fcu->totvert; b++, prevbezt = bezt, bezt++) {
+ /* if only selected keyframes can get their handles shown,
+ * check that keyframe is selected
+ */
+ if (sipo->flag & SIPO_SELVHANDLESONLY) {
+ if (BEZT_ISSEL_ANY(bezt) == 0)
+ continue;
+ }
+
+ /* draw handle with appropriate set of colors if selection is ok */
+ if ((bezt->f2 & SELECT) == sel) {
+ fp = bezt->vec[0];
+
+ /* only draw first handle if previous segment had handles */
+ if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) ||
+ (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
+ UI_GetThemeColor3ubv(basecol + bezt->h1, col);
+ col[3] = fcurve_display_alpha(fcu) * 255;
+ immAttr4ubv(color, col);
+ immVertex2fv(pos, fp);
+ immAttr4ubv(color, col);
+ immVertex2fv(pos, fp + 3);
+ }
+
+ /* only draw second handle if this segment is bezier */
+ if (bezt->ipo == BEZT_IPO_BEZ) {
+ UI_GetThemeColor3ubv(basecol + bezt->h2, col);
+ col[3] = fcurve_display_alpha(fcu) * 255;
+ immAttr4ubv(color, col);
+ immVertex2fv(pos, fp + 3);
+ immAttr4ubv(color, col);
+ immVertex2fv(pos, fp + 6);
+ }
+ }
+ else {
+ /* only draw first handle if previous segment was had handles, and selection is ok */
+ if (((bezt->f1 & SELECT) == sel) && ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) ||
+ (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ)))) {
+ fp = bezt->vec[0];
+ UI_GetThemeColor3ubv(basecol + bezt->h1, col);
+ col[3] = fcurve_display_alpha(fcu) * 255;
+ immAttr4ubv(color, col);
+ immVertex2fv(pos, fp);
+ immAttr4ubv(color, col);
+ immVertex2fv(pos, fp + 3);
+ }
+
+ /* only draw second handle if this segment is bezier, and selection is ok */
+ if (((bezt->f3 & SELECT) == sel) && (bezt->ipo == BEZT_IPO_BEZ)) {
+ fp = bezt->vec[1];
+ UI_GetThemeColor3ubv(basecol + bezt->h2, col);
+ col[3] = fcurve_display_alpha(fcu) * 255;
+ immAttr4ubv(color, col);
+ immVertex2fv(pos, fp);
+ immAttr4ubv(color, col);
+ immVertex2fv(pos, fp + 3);
+ }
+ }
+ }
+ }
+
+ immEnd();
+ immUnbindProgram();
}
/* Samples ---------------- */
@@ -426,230 +424,236 @@ static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu)
* NOTE: the caller MUST HAVE GL_LINE_SMOOTH & GL_BLEND ENABLED, otherwise, the controls don't
* 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)
+static void draw_fcurve_sample_control(
+ float x, float y, float xscale, float yscale, float hsize, unsigned int pos)
{
- /* adjust view transform before starting */
- GPU_matrix_push();
- GPU_matrix_translate_2f(x, y);
- GPU_matrix_scale_2f(1.0f / xscale * hsize, 1.0f / yscale * hsize);
-
- /* draw X shape */
- immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, -0.7f, -0.7f);
- immVertex2f(pos, +0.7f, +0.7f);
-
- immVertex2f(pos, -0.7f, +0.7f);
- immVertex2f(pos, +0.7f, -0.7f);
- immEnd();
-
- /* restore view transform */
- GPU_matrix_pop();
+ /* adjust view transform before starting */
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(x, y);
+ GPU_matrix_scale_2f(1.0f / xscale * hsize, 1.0f / yscale * hsize);
+
+ /* draw X shape */
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex2f(pos, -0.7f, -0.7f);
+ immVertex2f(pos, +0.7f, +0.7f);
+
+ immVertex2f(pos, -0.7f, +0.7f);
+ immVertex2f(pos, +0.7f, -0.7f);
+ immEnd();
+
+ /* restore view transform */
+ GPU_matrix_pop();
}
/* helper func - draw keyframe vertices only for an F-Curve */
static void draw_fcurve_samples(SpaceGraph *sipo, ARegion *ar, FCurve *fcu)
{
- FPoint *first, *last;
- float hsize, xscale, yscale;
+ FPoint *first, *last;
+ float hsize, xscale, yscale;
- /* get view settings */
- hsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
- UI_view2d_scale_get(&ar->v2d, &xscale, &yscale);
+ /* get view settings */
+ hsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
+ UI_view2d_scale_get(&ar->v2d, &xscale, &yscale);
- /* get verts */
- first = fcu->fpt;
- last = (first) ? (first + (fcu->totvert - 1)) : (NULL);
+ /* get verts */
+ first = fcu->fpt;
+ last = (first) ? (first + (fcu->totvert - 1)) : (NULL);
- /* draw */
- if (first && last) {
- /* anti-aliased lines for more consistent appearance */
- if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) GPU_line_smooth(true);
- GPU_blend(true);
+ /* draw */
+ if (first && last) {
+ /* anti-aliased lines for more consistent appearance */
+ if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0)
+ GPU_line_smooth(true);
+ GPU_blend(true);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor((fcu->flag & FCURVE_SELECTED) ? TH_TEXT_HI : TH_TEXT);
+ immUniformThemeColor((fcu->flag & FCURVE_SELECTED) ? TH_TEXT_HI : TH_TEXT);
- draw_fcurve_sample_control(first->vec[0], first->vec[1], xscale, yscale, hsize, pos);
- draw_fcurve_sample_control(last->vec[0], last->vec[1], xscale, yscale, hsize, pos);
+ draw_fcurve_sample_control(first->vec[0], first->vec[1], xscale, yscale, hsize, pos);
+ draw_fcurve_sample_control(last->vec[0], last->vec[1], xscale, yscale, hsize, pos);
- immUnbindProgram();
+ immUnbindProgram();
- GPU_blend(false);
- if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) GPU_line_smooth(false);
- }
+ GPU_blend(false);
+ if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0)
+ GPU_line_smooth(false);
+ }
}
/* Curve ---------------- */
/* 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, View2DGrid *grid, unsigned int pos)
+static void draw_fcurve_curve(
+ bAnimContext *ac, ID *id, FCurve *fcu_, View2D *v2d, View2DGrid *grid, unsigned int pos)
{
- SpaceGraph *sipo = (SpaceGraph *)ac->sl;
- float samplefreq;
- float stime, etime;
- float unitFac, offset;
- float dx, dy;
- short mapping_flag = ANIM_get_normalization_flags(ac);
- int i, n;
-
- /* when opening a blend file on a different sized screen or while dragging the toolbar this can happen
- * best just bail out in this case */
- UI_view2d_grid_size(grid, &dx, &dy);
- if (dx <= 0.0f)
- return;
-
-
- /* disable any drivers */
- FCurve fcurve_for_draw = *fcu_;
- fcurve_for_draw.driver = NULL;
-
- /* compute unit correction factor */
- unitFac = ANIM_unit_mapping_get_factor(ac->scene, id, &fcurve_for_draw, mapping_flag, &offset);
-
- /* Note about sampling frequency:
- * Ideally, this is chosen such that we have 1-2 pixels = 1 segment
- * which means that our curves can be as smooth as possible. However,
- * this does mean that curves may not be fully accurate (i.e. if they have
- * sudden spikes which happen at the sampling point, we may have problems).
- * Also, this may introduce lower performance on less densely detailed curves,
- * though it is impossible to predict this from the modifiers!
- *
- * If the automatically determined sampling frequency is likely to cause an infinite
- * loop (i.e. too close to 0), then clamp it to a determined "safe" value. The value
- * chosen here is just the coarsest value which still looks reasonable...
- */
- /* grid->dx represents the number of 'frames' between gridlines,
- * but we divide by U.v2d_min_gridsize to get pixels-steps */
- /* TODO: perhaps we should have 1.0 frames as upper limit so that curves don't get too distorted? */
- samplefreq = dx / (U.v2d_min_gridsize * U.pixelsize);
-
- if (sipo->flag & SIPO_BEAUTYDRAW_OFF) {
- /* Low Precision = coarse lower-bound clamping
- *
- * Although the "Beauty Draw" flag was originally for AA'd
- * line drawing, the sampling rate here has a much greater
- * impact on performance (e.g. for T40372)!
- *
- * This one still amounts to 10 sample-frames for each 1-frame interval
- * which should be quite a decent approximation in many situations.
- */
- if (samplefreq < 0.1f)
- samplefreq = 0.1f;
- }
- else {
- /* "Higher Precision" but slower - especially on larger windows (e.g. T40372) */
- if (samplefreq < 0.00001f)
- samplefreq = 0.00001f;
- }
-
-
- /* the start/end times are simply the horizontal extents of the 'cur' rect */
- stime = v2d->cur.xmin;
- etime = v2d->cur.xmax + samplefreq; /* + samplefreq here so that last item gets included... */
-
-
- /* at each sampling interval, add a new vertex
- * - apply the unit correction factor to the calculated values so that
- * the displayed values appear correctly in the viewport
- */
-
- n = (etime - stime) / samplefreq + 0.5f;
-
- if (n > 0) {
- immBegin(GPU_PRIM_LINE_STRIP, (n + 1));
-
- for (i = 0; i <= n; i++) {
- float ctime = stime + i * samplefreq;
- immVertex2f(pos, ctime, (evaluate_fcurve(&fcurve_for_draw, ctime) + offset) * unitFac);
- }
-
- immEnd();
- }
+ SpaceGraph *sipo = (SpaceGraph *)ac->sl;
+ float samplefreq;
+ float stime, etime;
+ float unitFac, offset;
+ float dx, dy;
+ short mapping_flag = ANIM_get_normalization_flags(ac);
+ int i, n;
+
+ /* when opening a blend file on a different sized screen or while dragging the toolbar this can happen
+ * best just bail out in this case */
+ UI_view2d_grid_size(grid, &dx, &dy);
+ if (dx <= 0.0f)
+ return;
+
+ /* disable any drivers */
+ FCurve fcurve_for_draw = *fcu_;
+ fcurve_for_draw.driver = NULL;
+
+ /* compute unit correction factor */
+ unitFac = ANIM_unit_mapping_get_factor(ac->scene, id, &fcurve_for_draw, mapping_flag, &offset);
+
+ /* Note about sampling frequency:
+ * Ideally, this is chosen such that we have 1-2 pixels = 1 segment
+ * which means that our curves can be as smooth as possible. However,
+ * this does mean that curves may not be fully accurate (i.e. if they have
+ * sudden spikes which happen at the sampling point, we may have problems).
+ * Also, this may introduce lower performance on less densely detailed curves,
+ * though it is impossible to predict this from the modifiers!
+ *
+ * If the automatically determined sampling frequency is likely to cause an infinite
+ * loop (i.e. too close to 0), then clamp it to a determined "safe" value. The value
+ * chosen here is just the coarsest value which still looks reasonable...
+ */
+ /* grid->dx represents the number of 'frames' between gridlines,
+ * but we divide by U.v2d_min_gridsize to get pixels-steps */
+ /* TODO: perhaps we should have 1.0 frames as upper limit so that curves don't get too distorted? */
+ samplefreq = dx / (U.v2d_min_gridsize * U.pixelsize);
+
+ if (sipo->flag & SIPO_BEAUTYDRAW_OFF) {
+ /* Low Precision = coarse lower-bound clamping
+ *
+ * Although the "Beauty Draw" flag was originally for AA'd
+ * line drawing, the sampling rate here has a much greater
+ * impact on performance (e.g. for T40372)!
+ *
+ * This one still amounts to 10 sample-frames for each 1-frame interval
+ * which should be quite a decent approximation in many situations.
+ */
+ if (samplefreq < 0.1f)
+ samplefreq = 0.1f;
+ }
+ else {
+ /* "Higher Precision" but slower - especially on larger windows (e.g. T40372) */
+ if (samplefreq < 0.00001f)
+ samplefreq = 0.00001f;
+ }
+
+ /* the start/end times are simply the horizontal extents of the 'cur' rect */
+ stime = v2d->cur.xmin;
+ etime = v2d->cur.xmax + samplefreq; /* + samplefreq here so that last item gets included... */
+
+ /* at each sampling interval, add a new vertex
+ * - apply the unit correction factor to the calculated values so that
+ * the displayed values appear correctly in the viewport
+ */
+
+ n = (etime - stime) / samplefreq + 0.5f;
+
+ if (n > 0) {
+ immBegin(GPU_PRIM_LINE_STRIP, (n + 1));
+
+ for (i = 0; i <= n; i++) {
+ float ctime = stime + i * samplefreq;
+ immVertex2f(pos, ctime, (evaluate_fcurve(&fcurve_for_draw, ctime) + offset) * unitFac);
+ }
+
+ immEnd();
+ }
}
/* helper func - draw a samples-based F-Curve */
-static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, const uint shdr_pos)
+static void draw_fcurve_curve_samples(
+ bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, const uint shdr_pos)
{
- FPoint *prevfpt = fcu->fpt;
- FPoint *fpt = prevfpt + 1;
- float fac, v[2];
- int b = fcu->totvert;
- float unit_scale, offset;
- short mapping_flag = ANIM_get_normalization_flags(ac);
- int count = fcu->totvert;
-
- if (prevfpt->vec[0] > v2d->cur.xmin) {
- count++;
- }
-
- if ((prevfpt + b - 1)->vec[0] < v2d->cur.xmax) {
- count++;
- }
-
- /* apply unit mapping */
- GPU_matrix_push();
- unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
- GPU_matrix_scale_2f(1.0f, unit_scale);
- GPU_matrix_translate_2f(0.0f, offset);
-
- immBegin(GPU_PRIM_LINE_STRIP, count);
-
- /* extrapolate to left? - left-side of view comes before first keyframe? */
- if (prevfpt->vec[0] > v2d->cur.xmin) {
- v[0] = v2d->cur.xmin;
-
- /* y-value depends on the interpolation */
- if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert == 1)) {
- /* just extend across the first keyframe's value */
- v[1] = prevfpt->vec[1];
- }
- else {
- /* extrapolate linear doesn't use the handle, use the next points center instead */
- fac = (prevfpt->vec[0] - fpt->vec[0]) / (prevfpt->vec[0] - v[0]);
- if (fac) fac = 1.0f / fac;
- v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]);
- }
-
- immVertex2fv(shdr_pos, v);
- }
-
- /* loop over samples, drawing segments */
- /* draw curve between first and last keyframe (if there are enough to do so) */
- while (b--) {
- /* Linear interpolation: just add one point (which should add a new line segment) */
- immVertex2fv(shdr_pos, prevfpt->vec);
-
- /* get next pointers */
- if (b > 0) {
- prevfpt++;
- }
- }
-
- /* extrapolate to right? (see code for left-extrapolation above too) */
- if (prevfpt->vec[0] < v2d->cur.xmax) {
- v[0] = v2d->cur.xmax;
-
- /* y-value depends on the interpolation */
- if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert == 1)) {
- /* based on last keyframe's value */
- v[1] = prevfpt->vec[1];
- }
- else {
- /* extrapolate linear doesn't use the handle, use the previous points center instead */
- fpt = prevfpt - 1;
- fac = (prevfpt->vec[0] - fpt->vec[0]) / (prevfpt->vec[0] - v[0]);
- if (fac) fac = 1.0f / fac;
- v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]);
- }
-
- immVertex2fv(shdr_pos, v);
- }
-
- immEnd();
-
- GPU_matrix_pop();
+ FPoint *prevfpt = fcu->fpt;
+ FPoint *fpt = prevfpt + 1;
+ float fac, v[2];
+ int b = fcu->totvert;
+ float unit_scale, offset;
+ short mapping_flag = ANIM_get_normalization_flags(ac);
+ int count = fcu->totvert;
+
+ if (prevfpt->vec[0] > v2d->cur.xmin) {
+ count++;
+ }
+
+ if ((prevfpt + b - 1)->vec[0] < v2d->cur.xmax) {
+ count++;
+ }
+
+ /* apply unit mapping */
+ GPU_matrix_push();
+ unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
+ GPU_matrix_scale_2f(1.0f, unit_scale);
+ GPU_matrix_translate_2f(0.0f, offset);
+
+ immBegin(GPU_PRIM_LINE_STRIP, count);
+
+ /* extrapolate to left? - left-side of view comes before first keyframe? */
+ if (prevfpt->vec[0] > v2d->cur.xmin) {
+ v[0] = v2d->cur.xmin;
+
+ /* y-value depends on the interpolation */
+ if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) ||
+ (fcu->totvert == 1)) {
+ /* just extend across the first keyframe's value */
+ v[1] = prevfpt->vec[1];
+ }
+ else {
+ /* extrapolate linear doesn't use the handle, use the next points center instead */
+ fac = (prevfpt->vec[0] - fpt->vec[0]) / (prevfpt->vec[0] - v[0]);
+ if (fac)
+ fac = 1.0f / fac;
+ v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]);
+ }
+
+ immVertex2fv(shdr_pos, v);
+ }
+
+ /* loop over samples, drawing segments */
+ /* draw curve between first and last keyframe (if there are enough to do so) */
+ while (b--) {
+ /* Linear interpolation: just add one point (which should add a new line segment) */
+ immVertex2fv(shdr_pos, prevfpt->vec);
+
+ /* get next pointers */
+ if (b > 0) {
+ prevfpt++;
+ }
+ }
+
+ /* extrapolate to right? (see code for left-extrapolation above too) */
+ if (prevfpt->vec[0] < v2d->cur.xmax) {
+ v[0] = v2d->cur.xmax;
+
+ /* y-value depends on the interpolation */
+ if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) ||
+ (fcu->totvert == 1)) {
+ /* based on last keyframe's value */
+ v[1] = prevfpt->vec[1];
+ }
+ else {
+ /* extrapolate linear doesn't use the handle, use the previous points center instead */
+ fpt = prevfpt - 1;
+ fac = (prevfpt->vec[0] - fpt->vec[0]) / (prevfpt->vec[0] - v[0]);
+ if (fac)
+ fac = 1.0f / fac;
+ v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]);
+ }
+
+ immVertex2fv(shdr_pos, v);
+ }
+
+ immEnd();
+
+ GPU_matrix_pop();
}
/* helper func - check if the F-Curve only contains easily drawable segments
@@ -657,183 +661,192 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie
*/
static bool fcurve_can_use_simple_bezt_drawing(FCurve *fcu)
{
- BezTriple *bezt;
- int i;
+ BezTriple *bezt;
+ int i;
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- if (ELEM(bezt->ipo, BEZT_IPO_CONST, BEZT_IPO_LIN, BEZT_IPO_BEZ) == false) {
- return false;
- }
- }
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (ELEM(bezt->ipo, BEZT_IPO_CONST, BEZT_IPO_LIN, BEZT_IPO_BEZ) == false) {
+ return false;
+ }
+ }
- return true;
+ return true;
}
/* 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, unsigned int pos)
{
- BezTriple *prevbezt = fcu->bezt;
- BezTriple *bezt = prevbezt + 1;
- float v1[2], v2[2], v3[2], v4[2];
- float *fp, data[120];
- float fac = 0.0f;
- int b = fcu->totvert - 1;
- int resol;
- float unit_scale, offset;
- short mapping_flag = ANIM_get_normalization_flags(ac);
-
- /* apply unit mapping */
- GPU_matrix_push();
- unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
- GPU_matrix_scale_2f(1.0f, unit_scale);
- GPU_matrix_translate_2f(0.0f, offset);
-
- /* For now, this assumes the worst case scenario, where all the keyframes have
- * bezier interpolation, and are drawn at full res.
- * This is tricky to optimize, but maybe can be improved at some point... */
- immBeginAtMost(GPU_PRIM_LINE_STRIP, (b * 32 + 3));
-
- /* extrapolate to left? */
- if (prevbezt->vec[1][0] > v2d->cur.xmin) {
- /* left-side of view comes before first keyframe, so need to extend as not cyclic */
- v1[0] = v2d->cur.xmin;
-
- /* y-value depends on the interpolation */
- if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (prevbezt->ipo == BEZT_IPO_CONST) || (fcu->totvert == 1)) {
- /* just extend across the first keyframe's value */
- v1[1] = prevbezt->vec[1][1];
- }
- else if (prevbezt->ipo == BEZT_IPO_LIN) {
- /* extrapolate linear dosnt use the handle, use the next points center instead */
- fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
- if (fac) fac = 1.0f / fac;
- v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]);
- }
- else {
- /* based on angle of handle 1 (relative to keyframe) */
- fac = (prevbezt->vec[0][0] - prevbezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
- if (fac) fac = 1.0f / fac;
- v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[0][1] - prevbezt->vec[1][1]);
- }
-
- immVertex2fv(pos, v1);
- }
-
- /* if only one keyframe, add it now */
- if (fcu->totvert == 1) {
- v1[0] = prevbezt->vec[1][0];
- v1[1] = prevbezt->vec[1][1];
- immVertex2fv(pos, v1);
- }
-
- /* draw curve between first and last keyframe (if there are enough to do so) */
- /* TODO: optimize this to not have to calc stuff out of view too? */
- while (b--) {
- if (prevbezt->ipo == BEZT_IPO_CONST) {
- /* Constant-Interpolation: draw segment between previous keyframe and next,
- * but holding same value */
- v1[0] = prevbezt->vec[1][0];
- v1[1] = prevbezt->vec[1][1];
- immVertex2fv(pos, v1);
-
- v1[0] = bezt->vec[1][0];
- v1[1] = prevbezt->vec[1][1];
- immVertex2fv(pos, v1);
- }
- else if (prevbezt->ipo == BEZT_IPO_LIN) {
- /* Linear interpolation: just add one point (which should add a new line segment) */
- v1[0] = prevbezt->vec[1][0];
- v1[1] = prevbezt->vec[1][1];
- immVertex2fv(pos, v1);
- }
- else if (prevbezt->ipo == BEZT_IPO_BEZ) {
- /* Bezier-Interpolation: draw curve as series of segments between keyframes
- * - resol determines number of points to sample in between keyframes
- */
-
- /* resol depends on distance between points
- * (not just horizontal) OR is a fixed high res */
- /* TODO: view scale should factor into this someday too... */
- if (fcu->driver) {
- resol = 32;
- }
- else {
- resol = (int)(5.0f * len_v2v2(bezt->vec[1], prevbezt->vec[1]));
- }
-
- if (resol < 2) {
- /* only draw one */
- v1[0] = prevbezt->vec[1][0];
- v1[1] = prevbezt->vec[1][1];
- immVertex2fv(pos, v1);
- }
- else {
- /* clamp resolution to max of 32 */
- /* NOTE: higher values will crash */
- if (resol > 32) resol = 32;
-
- v1[0] = prevbezt->vec[1][0];
- v1[1] = prevbezt->vec[1][1];
- v2[0] = prevbezt->vec[2][0];
- v2[1] = prevbezt->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 (fp = data; resol; resol--, fp += 3) {
- immVertex2fv(pos, fp);
- }
- }
- }
-
- /* get next pointers */
- prevbezt = bezt;
- bezt++;
-
- /* last point? */
- if (b == 0) {
- v1[0] = prevbezt->vec[1][0];
- v1[1] = prevbezt->vec[1][1];
- immVertex2fv(pos, v1);
- }
- }
-
- /* extrapolate to right? (see code for left-extrapolation above too) */
- if (prevbezt->vec[1][0] < v2d->cur.xmax) {
- v1[0] = v2d->cur.xmax;
-
- /* y-value depends on the interpolation */
- if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (prevbezt->ipo == BEZT_IPO_CONST) || (fcu->totvert == 1)) {
- /* based on last keyframe's value */
- v1[1] = prevbezt->vec[1][1];
- }
- else if (prevbezt->ipo == BEZT_IPO_LIN) {
- /* extrapolate linear dosnt use the handle, use the previous points center instead */
- bezt = prevbezt - 1;
- fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
- if (fac) fac = 1.0f / fac;
- v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]);
- }
- else {
- /* based on angle of handle 1 (relative to keyframe) */
- fac = (prevbezt->vec[2][0] - prevbezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
- if (fac) fac = 1.0f / fac;
- v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[2][1] - prevbezt->vec[1][1]);
- }
-
- immVertex2fv(pos, v1);
- }
-
- immEnd();
-
- GPU_matrix_pop();
+ BezTriple *prevbezt = fcu->bezt;
+ BezTriple *bezt = prevbezt + 1;
+ float v1[2], v2[2], v3[2], v4[2];
+ float *fp, data[120];
+ float fac = 0.0f;
+ int b = fcu->totvert - 1;
+ int resol;
+ float unit_scale, offset;
+ short mapping_flag = ANIM_get_normalization_flags(ac);
+
+ /* apply unit mapping */
+ GPU_matrix_push();
+ unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
+ GPU_matrix_scale_2f(1.0f, unit_scale);
+ GPU_matrix_translate_2f(0.0f, offset);
+
+ /* For now, this assumes the worst case scenario, where all the keyframes have
+ * bezier interpolation, and are drawn at full res.
+ * This is tricky to optimize, but maybe can be improved at some point... */
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, (b * 32 + 3));
+
+ /* extrapolate to left? */
+ if (prevbezt->vec[1][0] > v2d->cur.xmin) {
+ /* left-side of view comes before first keyframe, so need to extend as not cyclic */
+ v1[0] = v2d->cur.xmin;
+
+ /* y-value depends on the interpolation */
+ if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (prevbezt->ipo == BEZT_IPO_CONST) ||
+ (fcu->totvert == 1)) {
+ /* just extend across the first keyframe's value */
+ v1[1] = prevbezt->vec[1][1];
+ }
+ else if (prevbezt->ipo == BEZT_IPO_LIN) {
+ /* extrapolate linear dosnt use the handle, use the next points center instead */
+ fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
+ if (fac)
+ fac = 1.0f / fac;
+ v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]);
+ }
+ else {
+ /* based on angle of handle 1 (relative to keyframe) */
+ fac = (prevbezt->vec[0][0] - prevbezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
+ if (fac)
+ fac = 1.0f / fac;
+ v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[0][1] - prevbezt->vec[1][1]);
+ }
+
+ immVertex2fv(pos, v1);
+ }
+
+ /* if only one keyframe, add it now */
+ if (fcu->totvert == 1) {
+ v1[0] = prevbezt->vec[1][0];
+ v1[1] = prevbezt->vec[1][1];
+ immVertex2fv(pos, v1);
+ }
+
+ /* draw curve between first and last keyframe (if there are enough to do so) */
+ /* TODO: optimize this to not have to calc stuff out of view too? */
+ while (b--) {
+ if (prevbezt->ipo == BEZT_IPO_CONST) {
+ /* Constant-Interpolation: draw segment between previous keyframe and next,
+ * but holding same value */
+ v1[0] = prevbezt->vec[1][0];
+ v1[1] = prevbezt->vec[1][1];
+ immVertex2fv(pos, v1);
+
+ v1[0] = bezt->vec[1][0];
+ v1[1] = prevbezt->vec[1][1];
+ immVertex2fv(pos, v1);
+ }
+ else if (prevbezt->ipo == BEZT_IPO_LIN) {
+ /* Linear interpolation: just add one point (which should add a new line segment) */
+ v1[0] = prevbezt->vec[1][0];
+ v1[1] = prevbezt->vec[1][1];
+ immVertex2fv(pos, v1);
+ }
+ else if (prevbezt->ipo == BEZT_IPO_BEZ) {
+ /* Bezier-Interpolation: draw curve as series of segments between keyframes
+ * - resol determines number of points to sample in between keyframes
+ */
+
+ /* resol depends on distance between points
+ * (not just horizontal) OR is a fixed high res */
+ /* TODO: view scale should factor into this someday too... */
+ if (fcu->driver) {
+ resol = 32;
+ }
+ else {
+ resol = (int)(5.0f * len_v2v2(bezt->vec[1], prevbezt->vec[1]));
+ }
+
+ if (resol < 2) {
+ /* only draw one */
+ v1[0] = prevbezt->vec[1][0];
+ v1[1] = prevbezt->vec[1][1];
+ immVertex2fv(pos, v1);
+ }
+ else {
+ /* clamp resolution to max of 32 */
+ /* NOTE: higher values will crash */
+ if (resol > 32)
+ resol = 32;
+
+ v1[0] = prevbezt->vec[1][0];
+ v1[1] = prevbezt->vec[1][1];
+ v2[0] = prevbezt->vec[2][0];
+ v2[1] = prevbezt->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 (fp = data; resol; resol--, fp += 3) {
+ immVertex2fv(pos, fp);
+ }
+ }
+ }
+
+ /* get next pointers */
+ prevbezt = bezt;
+ bezt++;
+
+ /* last point? */
+ if (b == 0) {
+ v1[0] = prevbezt->vec[1][0];
+ v1[1] = prevbezt->vec[1][1];
+ immVertex2fv(pos, v1);
+ }
+ }
+
+ /* extrapolate to right? (see code for left-extrapolation above too) */
+ if (prevbezt->vec[1][0] < v2d->cur.xmax) {
+ v1[0] = v2d->cur.xmax;
+
+ /* y-value depends on the interpolation */
+ if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) ||
+ (prevbezt->ipo == BEZT_IPO_CONST) || (fcu->totvert == 1)) {
+ /* based on last keyframe's value */
+ v1[1] = prevbezt->vec[1][1];
+ }
+ else if (prevbezt->ipo == BEZT_IPO_LIN) {
+ /* extrapolate linear dosnt use the handle, use the previous points center instead */
+ bezt = prevbezt - 1;
+ fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
+ if (fac)
+ fac = 1.0f / fac;
+ v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]);
+ }
+ else {
+ /* based on angle of handle 1 (relative to keyframe) */
+ fac = (prevbezt->vec[2][0] - prevbezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
+ if (fac)
+ fac = 1.0f / fac;
+ v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[2][1] - prevbezt->vec[1][1]);
+ }
+
+ immVertex2fv(pos, v1);
+ }
+
+ immEnd();
+
+ GPU_matrix_pop();
}
/* Debugging -------------------------------- */
@@ -845,116 +858,117 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
*/
static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
{
- ChannelDriver *driver = fcu->driver;
- View2D *v2d = &ac->ar->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);
+ ChannelDriver *driver = fcu->driver;
+ View2D *v2d = &ac->ar->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);
- /* for now, only show when debugging driver... */
- //if ((driver->flag & DRIVER_FLAG_SHOWDEBUG) == 0)
- // return;
+ /* for now, only show when debugging driver... */
+ //if ((driver->flag & DRIVER_FLAG_SHOWDEBUG) == 0)
+ // return;
- const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
- immUniform1i("colors_len", 0); /* Simple dashes. */
+ immUniform1i("colors_len", 0); /* Simple dashes. */
- /* No curve to modify/visualize the result?
- * => We still want to show the 1-1 default...
- */
- if ((fcu->totvert == 0) && BLI_listbase_is_empty(&fcu->modifiers)) {
- float t;
+ /* No curve to modify/visualize the result?
+ * => We still want to show the 1-1 default...
+ */
+ if ((fcu->totvert == 0) && BLI_listbase_is_empty(&fcu->modifiers)) {
+ float t;
- /* draw with thin dotted lines in style of what curve would have been */
- immUniformColor3fv(fcu->color);
+ /* draw with thin dotted lines in style of what curve would have been */
+ immUniformColor3fv(fcu->color);
- immUniform1f("dash_width", 40.0f);
- immUniform1f("dash_factor", 0.5f);
- GPU_line_width(2.0f);
+ immUniform1f("dash_width", 40.0f);
+ immUniform1f("dash_factor", 0.5f);
+ GPU_line_width(2.0f);
- /* draw 1-1 line, stretching just past the screen limits
- * NOTE: we need to scale the y-values to be valid for the units
- */
- immBegin(GPU_PRIM_LINES, 2);
+ /* draw 1-1 line, stretching just past the screen limits
+ * NOTE: we need to scale the y-values to be valid for the units
+ */
+ immBegin(GPU_PRIM_LINES, 2);
- t = v2d->cur.xmin;
- immVertex2f(shdr_pos, t, (t + offset) * unitfac);
+ t = v2d->cur.xmin;
+ immVertex2f(shdr_pos, t, (t + offset) * unitfac);
- t = v2d->cur.xmax;
- immVertex2f(shdr_pos, t, (t + offset) * unitfac);
+ t = v2d->cur.xmax;
+ immVertex2f(shdr_pos, t, (t + offset) * unitfac);
- immEnd();
- }
+ immEnd();
+ }
- /* draw driver only if actually functional */
- if ((driver->flag & DRIVER_FLAG_INVALID) == 0) {
- /* grab "coordinates" for driver outputs */
- float x = driver->curval;
- float y = fcu->curval * unitfac;
+ /* draw driver only if actually functional */
+ if ((driver->flag & DRIVER_FLAG_INVALID) == 0) {
+ /* grab "coordinates" for driver outputs */
+ float x = driver->curval;
+ float y = fcu->curval * unitfac;
- /* only draw indicators if the point is in range*/
- if (x >= v2d->cur.xmin) {
- float co[2];
+ /* only draw indicators if the point is in range*/
+ if (x >= v2d->cur.xmin) {
+ float co[2];
- /* draw dotted lines leading towards this point from both axes ....... */
- immUniformColor3f(0.9f, 0.9f, 0.9f);
- immUniform1f("dash_width", 10.0f);
- immUniform1f("dash_factor", 0.5f);
+ /* draw dotted lines leading towards this point from both axes ....... */
+ immUniformColor3f(0.9f, 0.9f, 0.9f);
+ immUniform1f("dash_width", 10.0f);
+ immUniform1f("dash_factor", 0.5f);
- immBegin(GPU_PRIM_LINES, (y >= v2d->cur.ymin) ? 4 : 2);
+ immBegin(GPU_PRIM_LINES, (y >= v2d->cur.ymin) ? 4 : 2);
- /* x-axis lookup */
- co[0] = x;
+ /* x-axis lookup */
+ co[0] = x;
- if (y >= v2d->cur.ymin) {
- co[1] = v2d->cur.ymin - 1.0f;
- immVertex2fv(shdr_pos, co);
+ if (y >= v2d->cur.ymin) {
+ co[1] = v2d->cur.ymin - 1.0f;
+ immVertex2fv(shdr_pos, co);
- co[1] = y;
- immVertex2fv(shdr_pos, co);
- }
+ co[1] = y;
+ immVertex2fv(shdr_pos, co);
+ }
- /* y-axis lookup */
- co[1] = y;
+ /* y-axis lookup */
+ co[1] = y;
- co[0] = v2d->cur.xmin - 1.0f;
- immVertex2fv(shdr_pos, co);
+ co[0] = v2d->cur.xmin - 1.0f;
+ immVertex2fv(shdr_pos, co);
- co[0] = x;
- immVertex2fv(shdr_pos, co);
+ co[0] = x;
+ immVertex2fv(shdr_pos, co);
- immEnd();
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
- /* GPU_PRIM_POINTS do not survive dashed line geometry shader... */
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ /* GPU_PRIM_POINTS do not survive dashed line geometry shader... */
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- /* x marks the spot .................................................... */
- /* -> outer frame */
- immUniformColor3f(0.9f, 0.9f, 0.9f);
- GPU_point_size(7.0);
+ /* x marks the spot .................................................... */
+ /* -> outer frame */
+ immUniformColor3f(0.9f, 0.9f, 0.9f);
+ GPU_point_size(7.0);
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex2f(shdr_pos, x, y);
- immEnd();
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex2f(shdr_pos, x, y);
+ immEnd();
- /* inner frame */
- immUniformColor3f(0.9f, 0.0f, 0.0f);
- GPU_point_size(3.0);
+ /* inner frame */
+ immUniformColor3f(0.9f, 0.0f, 0.0f);
+ GPU_point_size(3.0);
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex2f(shdr_pos, x, y);
- immEnd();
- }
- }
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex2f(shdr_pos, x, y);
+ immEnd();
+ }
+ }
- immUnbindProgram();
+ immUnbindProgram();
}
/* Public Curve-Drawing API ---------------- */
@@ -964,224 +978,227 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
*/
void graph_draw_ghost_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *ar)
{
- FCurve *fcu;
+ FCurve *fcu;
- /* draw with thick dotted lines */
- GPU_line_width(3.0f);
+ /* draw with thick dotted lines */
+ GPU_line_width(3.0f);
- /* anti-aliased lines for less jagged appearance */
- if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
- GPU_line_smooth(true);
- }
- GPU_blend(true);
+ /* anti-aliased lines for less jagged appearance */
+ if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
+ GPU_line_smooth(true);
+ }
+ GPU_blend(true);
- const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
- immUniform1i("colors_len", 0); /* Simple dashes. */
- immUniform1f("dash_width", 20.0f);
- immUniform1f("dash_factor", 0.5f);
+ immUniform1i("colors_len", 0); /* Simple dashes. */
+ immUniform1f("dash_width", 20.0f);
+ immUniform1f("dash_factor", 0.5f);
- /* the ghost curves are simply sampled F-Curves stored in sipo->runtime.ghost_curves */
- for (fcu = sipo->runtime.ghost_curves.first; fcu; fcu = fcu->next) {
- /* set whatever color the curve has set
- * - this is set by the function which creates these
- * - draw with a fixed opacity of 2
- */
- immUniformColor3fvAlpha(fcu->color, 0.5f);
+ /* the ghost curves are simply sampled F-Curves stored in sipo->runtime.ghost_curves */
+ for (fcu = sipo->runtime.ghost_curves.first; fcu; fcu = fcu->next) {
+ /* set whatever color the curve has set
+ * - this is set by the function which creates these
+ * - draw with a fixed opacity of 2
+ */
+ immUniformColor3fvAlpha(fcu->color, 0.5f);
- /* simply draw the stored samples */
- draw_fcurve_curve_samples(ac, NULL, fcu, &ar->v2d, shdr_pos);
- }
+ /* simply draw the stored samples */
+ draw_fcurve_curve_samples(ac, NULL, fcu, &ar->v2d, shdr_pos);
+ }
- immUnbindProgram();
+ immUnbindProgram();
- if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
- GPU_line_smooth(false);
- }
- GPU_blend(false);
+ if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
+ GPU_line_smooth(false);
+ }
+ GPU_blend(false);
}
/* 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, View2DGrid *grid, short sel)
+void graph_draw_curves(
+ bAnimContext *ac, SpaceGraph *sipo, ARegion *ar, View2DGrid *grid, short sel)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* build list of curves to draw */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE);
- filter |= ((sel) ? (ANIMFILTER_SEL) : (ANIMFILTER_UNSEL));
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* for each curve:
- * draw curve, then handle-lines, and finally vertices in this order so that
- * the data will be layered correctly
- */
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
- FModifier *fcm = find_active_fmodifier(&fcu->modifiers);
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-
- /* map keyframes for drawing if scaled F-Curve */
- if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
- }
-
- /* draw curve:
- * - curve line may be result of one or more destructive modifiers or just the raw data,
- * so we need to check which method should be used
- * - controls from active modifier take precedence over keyframes
- * (XXX! editing tools need to take this into account!)
- */
-
- /* 1) draw curve line */
- if (((fcu->modifiers.first) || (fcu->flag & FCURVE_INT_VALUES)) ||
- (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)))
- {
- /* set color/drawing style for curve itself */
- /* draw active F-Curve thicker than the rest to make it stand out */
- if (fcu->flag & FCURVE_ACTIVE) {
- GPU_line_width(2.5);
- }
- else {
- GPU_line_width(1.0);
- }
-
- /* anti-aliased lines for less jagged appearance */
- if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
- GPU_line_smooth(true);
- }
- GPU_blend(true);
-
- const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
-
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
-
- immUniform1i("colors_len", 0); /* Simple dashes. */
-
- if (BKE_fcurve_is_protected(fcu)) {
- /* protected curves (non editable) are drawn with dotted lines */
- immUniform1f("dash_width", 4.0f);
- immUniform1f("dash_factor", 0.5f);
- }
- else {
- immUniform1f("dash_factor", 2.0f); /* solid line */
- }
-
- if (((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) || (fcu->flag & FCURVE_MUTED)) {
- /* muted curves are drawn in a grayish hue */
- /* XXX should we have some variations? */
- immUniformThemeColorShade(TH_HEADER, 50);
- }
- else {
- /* set whatever color the curve has set
- * - unselected curves draw less opaque to help distinguish the selected ones
- */
- immUniformColor3fvAlpha(fcu->color, fcurve_display_alpha(fcu));
- }
-
- /* draw F-Curve */
- if ((fcu->modifiers.first) || (fcu->flag & FCURVE_INT_VALUES)) {
- /* 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, grid, 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);
- }
- else {
- draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid, shdr_pos);
- }
- }
- else if (fcu->fpt) {
- draw_fcurve_curve_samples(ac, ale->id, fcu, &ar->v2d, shdr_pos);
- }
- }
-
- immUnbindProgram();
-
- if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
- GPU_line_smooth(false);
- }
- GPU_blend(false);
- }
-
- /* 2) draw handles and vertices as appropriate based on active
- * - if the option to only show controls if the F-Curve is selected is enabled, we must obey this
- */
- if (!(sipo->flag & SIPO_SELCUVERTSONLY) || (fcu->flag & FCURVE_SELECTED)) {
- if (!fcurve_are_keyframes_usable(fcu) && !(fcu->fpt && fcu->totvert)) {
- /* only draw controls if this is the active modifier */
- if ((fcu->flag & FCURVE_ACTIVE) && (fcm)) {
- switch (fcm->type) {
- case FMODIFIER_TYPE_ENVELOPE: /* envelope */
- draw_fcurve_modifier_controls_envelope(fcm, &ar->v2d);
- break;
- }
- }
- }
- else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) {
- short mapping_flag = ANIM_get_normalization_flags(ac);
- float offset;
- float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
-
- /* apply unit-scaling to all values via OpenGL */
- GPU_matrix_push();
- GPU_matrix_scale_2f(1.0f, unit_scale);
- GPU_matrix_translate_2f(0.0f, offset);
-
- /* set this once and for all - all handles and handle-verts should use the same thickness */
- GPU_line_width(1.0);
-
- if (fcu->bezt) {
- bool do_handles = draw_fcurve_handles_check(sipo, fcu);
-
- 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));
- }
- else {
- /* samples: only draw two indicators at either end as indicators */
- draw_fcurve_samples(sipo, ar, fcu);
- }
-
- GPU_matrix_pop();
- }
- }
-
- /* 3) draw driver debugging stuff */
- if ((ac->datatype == ANIMCONT_DRIVERS) && (fcu->flag & FCURVE_ACTIVE)) {
- graph_draw_driver_debug(ac, ale->id, fcu);
- }
-
- /* undo mapping of keyframes for drawing if scaled F-Curve */
- if (adt)
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
- }
-
- /* free list of curves */
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* build list of curves to draw */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE);
+ filter |= ((sel) ? (ANIMFILTER_SEL) : (ANIMFILTER_UNSEL));
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* for each curve:
+ * draw curve, then handle-lines, and finally vertices in this order so that
+ * the data will be layered correctly
+ */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
+ FModifier *fcm = find_active_fmodifier(&fcu->modifiers);
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ /* map keyframes for drawing if scaled F-Curve */
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
+ }
+
+ /* draw curve:
+ * - curve line may be result of one or more destructive modifiers or just the raw data,
+ * so we need to check which method should be used
+ * - controls from active modifier take precedence over keyframes
+ * (XXX! editing tools need to take this into account!)
+ */
+
+ /* 1) draw curve line */
+ if (((fcu->modifiers.first) || (fcu->flag & FCURVE_INT_VALUES)) ||
+ (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert))) {
+ /* set color/drawing style for curve itself */
+ /* draw active F-Curve thicker than the rest to make it stand out */
+ if (fcu->flag & FCURVE_ACTIVE) {
+ GPU_line_width(2.5);
+ }
+ else {
+ GPU_line_width(1.0);
+ }
+
+ /* anti-aliased lines for less jagged appearance */
+ if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
+ GPU_line_smooth(true);
+ }
+ GPU_blend(true);
+
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("colors_len", 0); /* Simple dashes. */
+
+ if (BKE_fcurve_is_protected(fcu)) {
+ /* protected curves (non editable) are drawn with dotted lines */
+ immUniform1f("dash_width", 4.0f);
+ immUniform1f("dash_factor", 0.5f);
+ }
+ else {
+ immUniform1f("dash_factor", 2.0f); /* solid line */
+ }
+
+ if (((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) || (fcu->flag & FCURVE_MUTED)) {
+ /* muted curves are drawn in a grayish hue */
+ /* XXX should we have some variations? */
+ immUniformThemeColorShade(TH_HEADER, 50);
+ }
+ else {
+ /* set whatever color the curve has set
+ * - unselected curves draw less opaque to help distinguish the selected ones
+ */
+ immUniformColor3fvAlpha(fcu->color, fcurve_display_alpha(fcu));
+ }
+
+ /* draw F-Curve */
+ if ((fcu->modifiers.first) || (fcu->flag & FCURVE_INT_VALUES)) {
+ /* 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, grid, 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);
+ }
+ else {
+ draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid, shdr_pos);
+ }
+ }
+ else if (fcu->fpt) {
+ draw_fcurve_curve_samples(ac, ale->id, fcu, &ar->v2d, shdr_pos);
+ }
+ }
+
+ immUnbindProgram();
+
+ if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
+ GPU_line_smooth(false);
+ }
+ GPU_blend(false);
+ }
+
+ /* 2) draw handles and vertices as appropriate based on active
+ * - if the option to only show controls if the F-Curve is selected is enabled, we must obey this
+ */
+ if (!(sipo->flag & SIPO_SELCUVERTSONLY) || (fcu->flag & FCURVE_SELECTED)) {
+ if (!fcurve_are_keyframes_usable(fcu) && !(fcu->fpt && fcu->totvert)) {
+ /* only draw controls if this is the active modifier */
+ if ((fcu->flag & FCURVE_ACTIVE) && (fcm)) {
+ switch (fcm->type) {
+ case FMODIFIER_TYPE_ENVELOPE: /* envelope */
+ draw_fcurve_modifier_controls_envelope(fcm, &ar->v2d);
+ break;
+ }
+ }
+ }
+ else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) {
+ short mapping_flag = ANIM_get_normalization_flags(ac);
+ float offset;
+ float unit_scale = ANIM_unit_mapping_get_factor(
+ ac->scene, ale->id, fcu, mapping_flag, &offset);
+
+ /* apply unit-scaling to all values via OpenGL */
+ GPU_matrix_push();
+ GPU_matrix_scale_2f(1.0f, unit_scale);
+ GPU_matrix_translate_2f(0.0f, offset);
+
+ /* set this once and for all - all handles and handle-verts should use the same thickness */
+ GPU_line_width(1.0);
+
+ if (fcu->bezt) {
+ bool do_handles = draw_fcurve_handles_check(sipo, fcu);
+
+ 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));
+ }
+ else {
+ /* samples: only draw two indicators at either end as indicators */
+ draw_fcurve_samples(sipo, ar, fcu);
+ }
+
+ GPU_matrix_pop();
+ }
+ }
+
+ /* 3) draw driver debugging stuff */
+ if ((ac->datatype == ANIMCONT_DRIVERS) && (fcu->flag & FCURVE_ACTIVE)) {
+ graph_draw_driver_debug(ac, ale->id, fcu);
+ }
+
+ /* undo mapping of keyframes for drawing if scaled F-Curve */
+ if (adt)
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
+ }
+
+ /* free list of curves */
+ ANIM_animdata_freelist(&anim_data);
}
/* ************************************************************************* */
@@ -1190,86 +1207,85 @@ void graph_draw_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *ar, View2DGr
/* left hand part */
void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- View2D *v2d = &ar->v2d;
- float y = 0.0f, height;
- size_t items;
- int i = 0;
-
- /* build list of channels to draw */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* Update max-extent of channels here (taking into account scrollers):
- * - this is done to allow the channel list to be scrollable, but must be done here
- * to avoid regenerating the list again and/or also because channels list is drawn first
- * - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
- * start of list offset, and the second is as a correction for the scrollers.
- */
- height = (float)((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac) * 2));
- UI_view2d_totRect_set(v2d, BLI_rcti_size_x(&ar->v2d.mask), height);
-
- /* loop through channels, and set up drawing depending on their type */
- { /* first pass: just the standard GL-drawing for backdrop + text */
- size_t channel_index = 0;
-
- y = (float)ACHANNEL_FIRST(ac);
-
- for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) {
- const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
- const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
-
- /* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
- {
- /* draw all channels using standard channel-drawing API */
- ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index);
- }
-
- /* adjust y-position for next one */
- y -= ACHANNEL_STEP(ac);
- channel_index++;
- }
- }
- { /* second pass: widgets */
- uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
- size_t channel_index = 0;
-
- y = (float)ACHANNEL_FIRST(ac);
-
- /* set blending again, as may not be set in previous step */
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
-
- for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) {
- const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
- const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
-
- /* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
- {
- /* draw all channels using standard channel-drawing API */
- rctf channel_rect;
- BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax - V2D_SCROLL_WIDTH, yminc, ymaxc);
- ANIM_channel_draw_widgets(C, ac, ale, block, &channel_rect, channel_index);
- }
-
- /* adjust y-position for next one */
- y -= ACHANNEL_STEP(ac);
- channel_index++;
- }
-
- UI_block_end(C, block);
- UI_block_draw(C, block);
-
- GPU_blend(false);
- }
-
- /* free tempolary channels */
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ View2D *v2d = &ar->v2d;
+ float y = 0.0f, height;
+ size_t items;
+ int i = 0;
+
+ /* build list of channels to draw */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* Update max-extent of channels here (taking into account scrollers):
+ * - this is done to allow the channel list to be scrollable, but must be done here
+ * to avoid regenerating the list again and/or also because channels list is drawn first
+ * - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
+ * start of list offset, and the second is as a correction for the scrollers.
+ */
+ height = (float)((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac) * 2));
+ UI_view2d_totRect_set(v2d, BLI_rcti_size_x(&ar->v2d.mask), height);
+
+ /* loop through channels, and set up drawing depending on their type */
+ { /* first pass: just the standard GL-drawing for backdrop + text */
+ size_t channel_index = 0;
+
+ y = (float)ACHANNEL_FIRST(ac);
+
+ for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) {
+ const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
+ const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
+
+ /* check if visible */
+ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ /* draw all channels using standard channel-drawing API */
+ ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index);
+ }
+
+ /* adjust y-position for next one */
+ y -= ACHANNEL_STEP(ac);
+ channel_index++;
+ }
+ }
+ { /* second pass: widgets */
+ uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ size_t channel_index = 0;
+
+ y = (float)ACHANNEL_FIRST(ac);
+
+ /* set blending again, as may not be set in previous step */
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
+
+ for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) {
+ const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
+ const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
+
+ /* check if visible */
+ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ /* draw all channels using standard channel-drawing API */
+ rctf channel_rect;
+ BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax - V2D_SCROLL_WIDTH, yminc, ymaxc);
+ ANIM_channel_draw_widgets(C, ac, ale, block, &channel_rect, channel_index);
+ }
+
+ /* adjust y-position for next one */
+ y -= ACHANNEL_STEP(ac);
+ channel_index++;
+ }
+
+ UI_block_end(C, block);
+ UI_block_draw(C, block);
+
+ GPU_blend(false);
+ }
+
+ /* free tempolary channels */
+ ANIM_animdata_freelist(&anim_data);
}
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index a85e638e6d8..29058e47199 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -21,7 +21,6 @@
* \ingroup spgraph
*/
-
#include <math.h>
#include <stdlib.h>
#include <string.h>
@@ -76,253 +75,288 @@
/* Get the min/max keyframes*/
/* note: it should return total boundbox, filter for selection only can be argument... */
-void get_graph_keyframe_extents(bAnimContext *ac, float *xmin, float *xmax, float *ymin, float *ymax,
- const bool do_sel_only, const bool include_handles)
-{
- Scene *scene = ac->scene;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* get data to filter, from Dopesheet */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* set large values initial values that will be easy to override */
- if (xmin) *xmin = 999999999.0f;
- if (xmax) *xmax = -999999999.0f;
- if (ymin) *ymin = 999999999.0f;
- if (ymax) *ymax = -999999999.0f;
-
- /* check if any channels to set range with */
- if (anim_data.first) {
- bool foundBounds = false;
-
- /* go through channels, finding max extents */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
- FCurve *fcu = (FCurve *)ale->key_data;
- float txmin, txmax, tymin, tymax;
- float unitFac, offset;
-
- /* get range */
- if (calc_fcurve_bounds(fcu, &txmin, &txmax, &tymin, &tymax, do_sel_only, include_handles)) {
- short mapping_flag = ANIM_get_normalization_flags(ac);
-
- /* apply NLA scaling */
- if (adt) {
- txmin = BKE_nla_tweakedit_remap(adt, txmin, NLATIME_CONVERT_MAP);
- txmax = BKE_nla_tweakedit_remap(adt, txmax, NLATIME_CONVERT_MAP);
- }
-
- /* apply unit corrections */
- unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
- tymin += offset;
- tymax += offset;
- tymin *= unitFac;
- tymax *= unitFac;
-
- /* try to set cur using these values, if they're more extreme than previously set values */
- if ((xmin) && (txmin < *xmin)) *xmin = txmin;
- if ((xmax) && (txmax > *xmax)) *xmax = txmax;
- if ((ymin) && (tymin < *ymin)) *ymin = tymin;
- if ((ymax) && (tymax > *ymax)) *ymax = tymax;
-
- foundBounds = true;
- }
- }
-
- /* ensure that the extents are not too extreme that view implodes...*/
- if (foundBounds) {
- if ((xmin && xmax) && (fabsf(*xmax - *xmin) < 0.001f)) {
- *xmin -= 0.0005f;
- *xmax += 0.0005f;
- }
- if ((ymin && ymax) && (fabsf(*ymax - *ymin) < 0.001f)) {
- *ymax -= 0.0005f;
- *ymax += 0.0005f;
- }
- }
- else {
- if (xmin) *xmin = (float)PSFRA;
- if (xmax) *xmax = (float)PEFRA;
- if (ymin) *ymin = -5;
- if (ymax) *ymax = 5;
- }
-
- /* free memory */
- ANIM_animdata_freelist(&anim_data);
- }
- else {
- /* set default range */
- if (ac->scene) {
- if (xmin) *xmin = (float)PSFRA;
- if (xmax) *xmax = (float)PEFRA;
- }
- else {
- if (xmin) *xmin = -5;
- if (xmax) *xmax = 100;
- }
-
- if (ymin) *ymin = -5;
- if (ymax) *ymax = 5;
- }
+void get_graph_keyframe_extents(bAnimContext *ac,
+ float *xmin,
+ float *xmax,
+ float *ymin,
+ float *ymax,
+ const bool do_sel_only,
+ const bool include_handles)
+{
+ Scene *scene = ac->scene;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get data to filter, from Dopesheet */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* set large values initial values that will be easy to override */
+ if (xmin)
+ *xmin = 999999999.0f;
+ if (xmax)
+ *xmax = -999999999.0f;
+ if (ymin)
+ *ymin = 999999999.0f;
+ if (ymax)
+ *ymax = -999999999.0f;
+
+ /* check if any channels to set range with */
+ if (anim_data.first) {
+ bool foundBounds = false;
+
+ /* go through channels, finding max extents */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+ FCurve *fcu = (FCurve *)ale->key_data;
+ float txmin, txmax, tymin, tymax;
+ float unitFac, offset;
+
+ /* get range */
+ if (calc_fcurve_bounds(fcu, &txmin, &txmax, &tymin, &tymax, do_sel_only, include_handles)) {
+ short mapping_flag = ANIM_get_normalization_flags(ac);
+
+ /* apply NLA scaling */
+ if (adt) {
+ txmin = BKE_nla_tweakedit_remap(adt, txmin, NLATIME_CONVERT_MAP);
+ txmax = BKE_nla_tweakedit_remap(adt, txmax, NLATIME_CONVERT_MAP);
+ }
+
+ /* apply unit corrections */
+ unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
+ tymin += offset;
+ tymax += offset;
+ tymin *= unitFac;
+ tymax *= unitFac;
+
+ /* try to set cur using these values, if they're more extreme than previously set values */
+ if ((xmin) && (txmin < *xmin))
+ *xmin = txmin;
+ if ((xmax) && (txmax > *xmax))
+ *xmax = txmax;
+ if ((ymin) && (tymin < *ymin))
+ *ymin = tymin;
+ if ((ymax) && (tymax > *ymax))
+ *ymax = tymax;
+
+ foundBounds = true;
+ }
+ }
+
+ /* ensure that the extents are not too extreme that view implodes...*/
+ if (foundBounds) {
+ if ((xmin && xmax) && (fabsf(*xmax - *xmin) < 0.001f)) {
+ *xmin -= 0.0005f;
+ *xmax += 0.0005f;
+ }
+ if ((ymin && ymax) && (fabsf(*ymax - *ymin) < 0.001f)) {
+ *ymax -= 0.0005f;
+ *ymax += 0.0005f;
+ }
+ }
+ else {
+ if (xmin)
+ *xmin = (float)PSFRA;
+ if (xmax)
+ *xmax = (float)PEFRA;
+ if (ymin)
+ *ymin = -5;
+ if (ymax)
+ *ymax = 5;
+ }
+
+ /* free memory */
+ ANIM_animdata_freelist(&anim_data);
+ }
+ else {
+ /* set default range */
+ if (ac->scene) {
+ if (xmin)
+ *xmin = (float)PSFRA;
+ if (xmax)
+ *xmax = (float)PEFRA;
+ }
+ else {
+ if (xmin)
+ *xmin = -5;
+ if (xmax)
+ *xmax = 100;
+ }
+
+ if (ymin)
+ *ymin = -5;
+ if (ymax)
+ *ymax = 5;
+ }
}
/* ****************** Automatic Preview-Range Operator ****************** */
static int graphkeys_previewrange_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
- Scene *scene;
- float min, max;
+ bAnimContext ac;
+ Scene *scene;
+ float min, max;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
- if (ac.scene == NULL)
- return OPERATOR_CANCELLED;
- else
- scene = ac.scene;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ if (ac.scene == NULL)
+ return OPERATOR_CANCELLED;
+ else
+ scene = ac.scene;
- /* set the range directly */
- get_graph_keyframe_extents(&ac, &min, &max, NULL, NULL, false, false);
- scene->r.flag |= SCER_PRV_RANGE;
- scene->r.psfra = round_fl_to_int(min);
- scene->r.pefra = round_fl_to_int(max);
+ /* set the range directly */
+ get_graph_keyframe_extents(&ac, &min, &max, NULL, NULL, false, false);
+ scene->r.flag |= SCER_PRV_RANGE;
+ scene->r.psfra = round_fl_to_int(min);
+ scene->r.pefra = round_fl_to_int(max);
- /* set notifier that things have changed */
- // XXX err... there's nothing for frame ranges yet, but this should do fine too
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene);
+ /* set notifier that things have changed */
+ // XXX err... there's nothing for frame ranges yet, but this should do fine too
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_previewrange_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Auto-Set Preview Range";
- ot->idname = "GRAPH_OT_previewrange_set";
- ot->description = "Automatically set Preview Range based on range of keyframes";
+ /* identifiers */
+ ot->name = "Auto-Set Preview Range";
+ ot->idname = "GRAPH_OT_previewrange_set";
+ ot->description = "Automatically set Preview Range based on range of keyframes";
- /* api callbacks */
- ot->exec = graphkeys_previewrange_exec;
- ot->poll = ED_operator_graphedit_active; // XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier...
+ /* api callbacks */
+ ot->exec = graphkeys_previewrange_exec;
+ ot->poll =
+ ED_operator_graphedit_active; // XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier...
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** View-All Operator ****************** */
-static int graphkeys_viewall(bContext *C, const bool do_sel_only, const bool include_handles,
+static int graphkeys_viewall(bContext *C,
+ const bool do_sel_only,
+ const bool include_handles,
const int smooth_viewtx)
{
- bAnimContext ac;
- rctf cur_new;
+ bAnimContext ac;
+ rctf cur_new;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* set the horizontal range, with an extra offset so that the extreme keys will be in view */
- get_graph_keyframe_extents(&ac,
- &cur_new.xmin, &cur_new.xmax,
- &cur_new.ymin, &cur_new.ymax,
- do_sel_only, include_handles);
+ /* set the horizontal range, with an extra offset so that the extreme keys will be in view */
+ get_graph_keyframe_extents(&ac,
+ &cur_new.xmin,
+ &cur_new.xmax,
+ &cur_new.ymin,
+ &cur_new.ymax,
+ do_sel_only,
+ include_handles);
- BLI_rctf_scale(&cur_new, 1.1f);
+ BLI_rctf_scale(&cur_new, 1.1f);
- UI_view2d_smooth_view(C, ac.ar, &cur_new, smooth_viewtx);
+ UI_view2d_smooth_view(C, ac.ar, &cur_new, smooth_viewtx);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* ......... */
static int graphkeys_viewall_exec(bContext *C, wmOperator *op)
{
- const bool include_handles = RNA_boolean_get(op->ptr, "include_handles");
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ const bool include_handles = RNA_boolean_get(op->ptr, "include_handles");
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- /* whole range */
- return graphkeys_viewall(C, false, include_handles, smooth_viewtx);
+ /* whole range */
+ return graphkeys_viewall(C, false, include_handles, smooth_viewtx);
}
static int graphkeys_view_selected_exec(bContext *C, wmOperator *op)
{
- const bool include_handles = RNA_boolean_get(op->ptr, "include_handles");
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ const bool include_handles = RNA_boolean_get(op->ptr, "include_handles");
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- /* only selected */
- return graphkeys_viewall(C, true, include_handles, smooth_viewtx);
+ /* only selected */
+ return graphkeys_viewall(C, true, include_handles, smooth_viewtx);
}
/* ......... */
void GRAPH_OT_view_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View All";
- ot->idname = "GRAPH_OT_view_all";
- ot->description = "Reset viewable area to show full keyframe range";
+ /* identifiers */
+ ot->name = "View All";
+ ot->idname = "GRAPH_OT_view_all";
+ ot->description = "Reset viewable area to show full keyframe range";
- /* api callbacks */
- ot->exec = graphkeys_viewall_exec;
- /* XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier... */
- ot->poll = ED_operator_graphedit_active;
+ /* api callbacks */
+ ot->exec = graphkeys_viewall_exec;
+ /* XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier... */
+ ot->poll = ED_operator_graphedit_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- ot->prop = RNA_def_boolean(ot->srna, "include_handles", true, "Include Handles",
- "Include handles of keyframes when calculating extents");
+ /* props */
+ ot->prop = RNA_def_boolean(ot->srna,
+ "include_handles",
+ true,
+ "Include Handles",
+ "Include handles of keyframes when calculating extents");
}
void GRAPH_OT_view_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Selected";
- ot->idname = "GRAPH_OT_view_selected";
- ot->description = "Reset viewable area to show selected keyframe range";
+ /* identifiers */
+ ot->name = "View Selected";
+ ot->idname = "GRAPH_OT_view_selected";
+ ot->description = "Reset viewable area to show selected keyframe range";
- /* api callbacks */
- ot->exec = graphkeys_view_selected_exec;
- /* XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier... */
- ot->poll = ED_operator_graphedit_active;
+ /* api callbacks */
+ ot->exec = graphkeys_view_selected_exec;
+ /* XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier... */
+ ot->poll = ED_operator_graphedit_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- ot->prop = RNA_def_boolean(ot->srna, "include_handles", true, "Include Handles",
- "Include handles of keyframes when calculating extents");
+ /* props */
+ ot->prop = RNA_def_boolean(ot->srna,
+ "include_handles",
+ true,
+ "Include Handles",
+ "Include handles of keyframes when calculating extents");
}
/* ********************** View Frame Operator ****************************** */
static int graphkeys_view_frame_exec(bContext *C, wmOperator *op)
{
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- ANIM_center_frame(C, smooth_viewtx);
- return OPERATOR_FINISHED;
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ ANIM_center_frame(C, smooth_viewtx);
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_view_frame(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Frame";
- ot->idname = "GRAPH_OT_view_frame";
- ot->description = "Reset viewable area to show range around current frame";
+ /* identifiers */
+ ot->name = "View Frame";
+ ot->idname = "GRAPH_OT_view_frame";
+ ot->description = "Reset viewable area to show range around current frame";
- /* api callbacks */
- ot->exec = graphkeys_view_frame_exec;
- ot->poll = ED_operator_graphedit_active;
+ /* api callbacks */
+ ot->exec = graphkeys_view_frame_exec;
+ ot->poll = ED_operator_graphedit_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Create Ghost-Curves Operator *********************** */
@@ -333,114 +367,116 @@ void GRAPH_OT_view_frame(wmOperatorType *ot)
/* Bake each F-Curve into a set of samples, and store as a ghost curve */
static void create_ghost_curves(bAnimContext *ac, int start, int end)
{
- SpaceGraph *sipo = (SpaceGraph *)ac->sl;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* free existing ghost curves */
- free_fcurves(&sipo->runtime.ghost_curves);
-
- /* sanity check */
- if (start >= end) {
- printf("Error: Frame range for Ghost F-Curve creation is inappropriate\n");
- return;
- }
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* loop through filtered data and add keys between selected keyframes on every frame */
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
- FCurve *gcu = MEM_callocN(sizeof(FCurve), "Ghost FCurve");
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
- ChannelDriver *driver = fcu->driver;
- FPoint *fpt;
- float unitFac, offset;
- int cfra;
- short mapping_flag = ANIM_get_normalization_flags(ac);
-
- /* disable driver so that it don't muck up the sampling process */
- fcu->driver = NULL;
-
- /* calculate unit-mapping factor */
- unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
-
- /* create samples, but store them in a new curve
- * - we cannot use fcurve_store_samples() as that will only overwrite the original curve
- */
- gcu->fpt = fpt = MEM_callocN(sizeof(FPoint) * (end - start + 1), "Ghost FPoint Samples");
- gcu->totvert = end - start + 1;
-
- /* use the sampling callback at 1-frame intervals from start to end frames */
- for (cfra = start; cfra <= end; cfra++, fpt++) {
- float cfrae = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
-
- fpt->vec[0] = cfrae;
- fpt->vec[1] = (fcurve_samplingcb_evalcurve(fcu, NULL, cfrae) + offset) * unitFac;
- }
-
- /* set color of ghost curve
- * - make the color slightly darker
- */
- gcu->color[0] = fcu->color[0] - 0.07f;
- gcu->color[1] = fcu->color[1] - 0.07f;
- gcu->color[2] = fcu->color[2] - 0.07f;
-
- /* store new ghost curve */
- BLI_addtail(&sipo->runtime.ghost_curves, gcu);
-
- /* restore driver */
- fcu->driver = driver;
- }
-
- /* admin and redraws */
- ANIM_animdata_freelist(&anim_data);
+ SpaceGraph *sipo = (SpaceGraph *)ac->sl;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* free existing ghost curves */
+ free_fcurves(&sipo->runtime.ghost_curves);
+
+ /* sanity check */
+ if (start >= end) {
+ printf("Error: Frame range for Ghost F-Curve creation is inappropriate\n");
+ return;
+ }
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through filtered data and add keys between selected keyframes on every frame */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
+ FCurve *gcu = MEM_callocN(sizeof(FCurve), "Ghost FCurve");
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+ ChannelDriver *driver = fcu->driver;
+ FPoint *fpt;
+ float unitFac, offset;
+ int cfra;
+ short mapping_flag = ANIM_get_normalization_flags(ac);
+
+ /* disable driver so that it don't muck up the sampling process */
+ fcu->driver = NULL;
+
+ /* calculate unit-mapping factor */
+ unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
+
+ /* create samples, but store them in a new curve
+ * - we cannot use fcurve_store_samples() as that will only overwrite the original curve
+ */
+ gcu->fpt = fpt = MEM_callocN(sizeof(FPoint) * (end - start + 1), "Ghost FPoint Samples");
+ gcu->totvert = end - start + 1;
+
+ /* use the sampling callback at 1-frame intervals from start to end frames */
+ for (cfra = start; cfra <= end; cfra++, fpt++) {
+ float cfrae = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
+
+ fpt->vec[0] = cfrae;
+ fpt->vec[1] = (fcurve_samplingcb_evalcurve(fcu, NULL, cfrae) + offset) * unitFac;
+ }
+
+ /* set color of ghost curve
+ * - make the color slightly darker
+ */
+ gcu->color[0] = fcu->color[0] - 0.07f;
+ gcu->color[1] = fcu->color[1] - 0.07f;
+ gcu->color[2] = fcu->color[2] - 0.07f;
+
+ /* store new ghost curve */
+ BLI_addtail(&sipo->runtime.ghost_curves, gcu);
+
+ /* restore driver */
+ fcu->driver = driver;
+ }
+
+ /* admin and redraws */
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int graphkeys_create_ghostcurves_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
- View2D *v2d;
- int start, end;
+ bAnimContext ac;
+ View2D *v2d;
+ int start, end;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* ghost curves are snapshots of the visible portions of the curves, so set range to be the visible range */
- v2d = &ac.ar->v2d;
- start = (int)v2d->cur.xmin;
- end = (int)v2d->cur.xmax;
+ /* ghost curves are snapshots of the visible portions of the curves, so set range to be the visible range */
+ v2d = &ac.ar->v2d;
+ start = (int)v2d->cur.xmin;
+ end = (int)v2d->cur.xmax;
- /* bake selected curves into a ghost curve */
- create_ghost_curves(&ac, start, end);
+ /* bake selected curves into a ghost curve */
+ create_ghost_curves(&ac, start, end);
- /* update this editor only */
- ED_area_tag_redraw(CTX_wm_area(C));
+ /* update this editor only */
+ ED_area_tag_redraw(CTX_wm_area(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_ghost_curves_create(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Create Ghost Curves";
- ot->idname = "GRAPH_OT_ghost_curves_create";
- ot->description = "Create snapshot (Ghosts) of selected F-Curves as background aid for active Graph Editor";
+ /* identifiers */
+ ot->name = "Create Ghost Curves";
+ ot->idname = "GRAPH_OT_ghost_curves_create";
+ ot->description =
+ "Create snapshot (Ghosts) of selected F-Curves as background aid for active Graph Editor";
- /* api callbacks */
- ot->exec = graphkeys_create_ghostcurves_exec;
- ot->poll = graphop_visible_keyframes_poll;
+ /* api callbacks */
+ ot->exec = graphkeys_create_ghostcurves_exec;
+ ot->poll = graphop_visible_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- // todo: add props for start/end frames
+ // todo: add props for start/end frames
}
/* ******************** Clear Ghost-Curves Operator *********************** */
@@ -448,40 +484,40 @@ void GRAPH_OT_ghost_curves_create(wmOperatorType *ot)
static int graphkeys_clear_ghostcurves_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
- SpaceGraph *sipo;
+ bAnimContext ac;
+ SpaceGraph *sipo;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
- sipo = (SpaceGraph *)ac.sl;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ sipo = (SpaceGraph *)ac.sl;
- /* if no ghost curves, don't do anything */
- if (BLI_listbase_is_empty(&sipo->runtime.ghost_curves)) {
- return OPERATOR_CANCELLED;
- }
- /* free ghost curves */
- free_fcurves(&sipo->runtime.ghost_curves);
+ /* if no ghost curves, don't do anything */
+ if (BLI_listbase_is_empty(&sipo->runtime.ghost_curves)) {
+ return OPERATOR_CANCELLED;
+ }
+ /* free ghost curves */
+ free_fcurves(&sipo->runtime.ghost_curves);
- /* update this editor only */
- ED_area_tag_redraw(CTX_wm_area(C));
+ /* update this editor only */
+ ED_area_tag_redraw(CTX_wm_area(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_ghost_curves_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Ghost Curves";
- ot->idname = "GRAPH_OT_ghost_curves_clear";
- ot->description = "Clear F-Curve snapshots (Ghosts) for active Graph Editor";
+ /* identifiers */
+ ot->name = "Clear Ghost Curves";
+ ot->idname = "GRAPH_OT_ghost_curves_clear";
+ ot->description = "Clear F-Curve snapshots (Ghosts) for active Graph Editor";
- /* api callbacks */
- ot->exec = graphkeys_clear_ghostcurves_exec;
- ot->poll = ED_operator_graphedit_active;
+ /* api callbacks */
+ ot->exec = graphkeys_clear_ghostcurves_exec;
+ ot->poll = ED_operator_graphedit_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ************************************************************************** */
@@ -491,310 +527,350 @@ void GRAPH_OT_ghost_curves_clear(wmOperatorType *ot)
/* Mode defines for insert keyframes tool */
typedef enum eGraphKeys_InsertKey_Types {
- GRAPHKEYS_INSERTKEY_ALL = (1 << 0),
- GRAPHKEYS_INSERTKEY_SEL = (1 << 1),
- GRAPHKEYS_INSERTKEY_CURSOR = (1 << 2),
- GRAPHKEYS_INSERTKEY_ACTIVE = (1 << 3),
+ GRAPHKEYS_INSERTKEY_ALL = (1 << 0),
+ GRAPHKEYS_INSERTKEY_SEL = (1 << 1),
+ GRAPHKEYS_INSERTKEY_CURSOR = (1 << 2),
+ GRAPHKEYS_INSERTKEY_ACTIVE = (1 << 3),
} eGraphKeys_InsertKey_Types;
/* RNA mode types for insert keyframes tool */
static const EnumPropertyItem prop_graphkeys_insertkey_types[] = {
- {GRAPHKEYS_INSERTKEY_ALL, "ALL", 0, "All Channels",
- "Insert a keyframe on all visible and editable F-Curves using each curve's current value"},
- {GRAPHKEYS_INSERTKEY_SEL, "SEL", 0, "Only Selected Channels",
- "Insert a keyframe on selected F-Curves using each curve's current value"},
- {0, "", 0, "", ""},
- {GRAPHKEYS_INSERTKEY_ACTIVE | GRAPHKEYS_INSERTKEY_CURSOR, "CURSOR_ACTIVE", 0,
- "Active Channels At Cursor", "Insert a keyframe for the active F-Curve at the cursor point"},
- {GRAPHKEYS_INSERTKEY_SEL | GRAPHKEYS_INSERTKEY_CURSOR, "CURSOR_SEL", 0,
- "Selected Channels At Cursor", "Insert a keyframe for selected F-Curves at the cursor point"},
- {0, NULL, 0, NULL, NULL},
+ {GRAPHKEYS_INSERTKEY_ALL,
+ "ALL",
+ 0,
+ "All Channels",
+ "Insert a keyframe on all visible and editable F-Curves using each curve's current value"},
+ {GRAPHKEYS_INSERTKEY_SEL,
+ "SEL",
+ 0,
+ "Only Selected Channels",
+ "Insert a keyframe on selected F-Curves using each curve's current value"},
+ {0, "", 0, "", ""},
+ {GRAPHKEYS_INSERTKEY_ACTIVE | GRAPHKEYS_INSERTKEY_CURSOR,
+ "CURSOR_ACTIVE",
+ 0,
+ "Active Channels At Cursor",
+ "Insert a keyframe for the active F-Curve at the cursor point"},
+ {GRAPHKEYS_INSERTKEY_SEL | GRAPHKEYS_INSERTKEY_CURSOR,
+ "CURSOR_SEL",
+ 0,
+ "Selected Channels At Cursor",
+ "Insert a keyframe for selected F-Curves at the cursor point"},
+ {0, NULL, 0, NULL, NULL},
};
/* this function is responsible for snapping keyframes to frame-times */
static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
{
- ListBase anim_data = {NULL, NULL};
- ListBase nla_cache = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- size_t num_items;
-
- ReportList *reports = ac->reports;
- SpaceGraph *sipo = (SpaceGraph *)ac->sl;
- struct Depsgraph *depsgraph = ac->depsgraph;
- Scene *scene = ac->scene;
- ToolSettings *ts = scene->toolsettings;
- short flag = 0;
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- if (mode & GRAPHKEYS_INSERTKEY_SEL)
- filter |= ANIMFILTER_SEL;
- else if (mode & GRAPHKEYS_INSERTKEY_ACTIVE)
- filter |= ANIMFILTER_ACTIVE;
-
- num_items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- if (num_items == 0) {
- if (mode & GRAPHKEYS_INSERTKEY_ACTIVE)
- BKE_report(reports, RPT_ERROR, "No active F-Curve to add a keyframe to. Select an editable F-Curve first");
- else if (mode & GRAPHKEYS_INSERTKEY_SEL)
- BKE_report(reports, RPT_ERROR, "No selected F-Curves to add keyframes to");
- else
- BKE_report(reports, RPT_ERROR, "No channels to add keyframes to");
-
- return;
- }
-
- /* init keyframing flag */
- flag = ANIM_get_keyframing_flags(scene, 1);
-
- /* insert keyframes */
- if (mode & GRAPHKEYS_INSERTKEY_CURSOR) {
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
- FCurve *fcu = (FCurve *)ale->key_data;
-
- short mapping_flag = ANIM_get_normalization_flags(ac);
- float offset;
- float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag, &offset);
-
- float x, y;
-
-
- /* perform time remapping for x-coordinate (if necessary) */
- if ((sipo) && (sipo->mode == SIPO_MODE_DRIVERS))
- x = sipo->cursorTime;
- else if (adt)
- x = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
- else
- x = (float)CFRA;
-
- /* normalise units of cursor's value */
- if (sipo)
- y = (sipo->cursorVal / unit_scale) - offset;
- else
- y = 0.0f;
-
- /* insert keyframe directly into the F-Curve */
- insert_vert_fcurve(fcu, x, y, ts->keyframe_type, 0);
-
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
- }
- else {
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
- float cfra = (float)CFRA;
-
- /* read value from property the F-Curve represents, or from the curve only?
- * - ale->id != NULL: Typically, this means that we have enough info to try resolving the path
- * - ale->owner != NULL: If this is set, then the path may not be resolvable from the ID alone,
- * so it's easier for now to just read the F-Curve directly.
- * (TODO: add the full-blown PointerRNA relative parsing case here...)
- * - fcu->driver != NULL: If this is set, then it's a driver. If we don't check for this, we'd end
- * up adding the keyframes on a new F-Curve in the action data instead.
- */
- if (ale->id && !ale->owner && !fcu->driver) {
- insert_keyframe(ac->bmain, depsgraph, reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)),
- fcu->rna_path, fcu->array_index, cfra, ts->keyframe_type, &nla_cache, flag);
- }
- else {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-
- /* adjust current frame for NLA-mapping */
- if ((sipo) && (sipo->mode == SIPO_MODE_DRIVERS))
- cfra = sipo->cursorTime;
- else if (adt)
- cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
-
- const float curval = evaluate_fcurve_only_curve(fcu, cfra);
- insert_vert_fcurve(fcu, cfra, curval, ts->keyframe_type, 0);
- }
-
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
- }
-
- BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ ListBase nla_cache = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ size_t num_items;
+
+ ReportList *reports = ac->reports;
+ SpaceGraph *sipo = (SpaceGraph *)ac->sl;
+ struct Depsgraph *depsgraph = ac->depsgraph;
+ Scene *scene = ac->scene;
+ ToolSettings *ts = scene->toolsettings;
+ short flag = 0;
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_NODUPLIS);
+ if (mode & GRAPHKEYS_INSERTKEY_SEL)
+ filter |= ANIMFILTER_SEL;
+ else if (mode & GRAPHKEYS_INSERTKEY_ACTIVE)
+ filter |= ANIMFILTER_ACTIVE;
+
+ num_items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ if (num_items == 0) {
+ if (mode & GRAPHKEYS_INSERTKEY_ACTIVE)
+ BKE_report(reports,
+ RPT_ERROR,
+ "No active F-Curve to add a keyframe to. Select an editable F-Curve first");
+ else if (mode & GRAPHKEYS_INSERTKEY_SEL)
+ BKE_report(reports, RPT_ERROR, "No selected F-Curves to add keyframes to");
+ else
+ BKE_report(reports, RPT_ERROR, "No channels to add keyframes to");
+
+ return;
+ }
+
+ /* init keyframing flag */
+ flag = ANIM_get_keyframing_flags(scene, 1);
+
+ /* insert keyframes */
+ if (mode & GRAPHKEYS_INSERTKEY_CURSOR) {
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+ FCurve *fcu = (FCurve *)ale->key_data;
+
+ short mapping_flag = ANIM_get_normalization_flags(ac);
+ float offset;
+ float unit_scale = ANIM_unit_mapping_get_factor(
+ ac->scene, ale->id, ale->key_data, mapping_flag, &offset);
+
+ float x, y;
+
+ /* perform time remapping for x-coordinate (if necessary) */
+ if ((sipo) && (sipo->mode == SIPO_MODE_DRIVERS))
+ x = sipo->cursorTime;
+ else if (adt)
+ x = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+ else
+ x = (float)CFRA;
+
+ /* normalise units of cursor's value */
+ if (sipo)
+ y = (sipo->cursorVal / unit_scale) - offset;
+ else
+ y = 0.0f;
+
+ /* insert keyframe directly into the F-Curve */
+ insert_vert_fcurve(fcu, x, y, ts->keyframe_type, 0);
+
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
+ }
+ else {
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
+ float cfra = (float)CFRA;
+
+ /* read value from property the F-Curve represents, or from the curve only?
+ * - ale->id != NULL: Typically, this means that we have enough info to try resolving the path
+ * - ale->owner != NULL: If this is set, then the path may not be resolvable from the ID alone,
+ * so it's easier for now to just read the F-Curve directly.
+ * (TODO: add the full-blown PointerRNA relative parsing case here...)
+ * - fcu->driver != NULL: If this is set, then it's a driver. If we don't check for this, we'd end
+ * up adding the keyframes on a new F-Curve in the action data instead.
+ */
+ if (ale->id && !ale->owner && !fcu->driver) {
+ insert_keyframe(ac->bmain,
+ depsgraph,
+ reports,
+ ale->id,
+ NULL,
+ ((fcu->grp) ? (fcu->grp->name) : (NULL)),
+ fcu->rna_path,
+ fcu->array_index,
+ cfra,
+ ts->keyframe_type,
+ &nla_cache,
+ flag);
+ }
+ else {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ /* adjust current frame for NLA-mapping */
+ if ((sipo) && (sipo->mode == SIPO_MODE_DRIVERS))
+ cfra = sipo->cursorTime;
+ else if (adt)
+ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+
+ const float curval = evaluate_fcurve_only_curve(fcu, cfra);
+ insert_vert_fcurve(fcu, cfra, curval, ts->keyframe_type, 0);
+ }
+
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
+ }
+
+ BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int graphkeys_insertkey_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- eGraphKeys_InsertKey_Types mode;
+ bAnimContext ac;
+ eGraphKeys_InsertKey_Types mode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* which channels to affect? */
- mode = RNA_enum_get(op->ptr, "type");
+ /* which channels to affect? */
+ mode = RNA_enum_get(op->ptr, "type");
- /* insert keyframes */
- insert_graph_keys(&ac, mode);
+ /* insert keyframes */
+ insert_graph_keys(&ac, mode);
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_keyframe_insert(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Insert Keyframes";
- ot->idname = "GRAPH_OT_keyframe_insert";
- ot->description = "Insert keyframes for the specified channels";
+ /* identifiers */
+ ot->name = "Insert Keyframes";
+ ot->idname = "GRAPH_OT_keyframe_insert";
+ ot->description = "Insert keyframes for the specified channels";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = graphkeys_insertkey_exec;
- ot->poll = graphop_editable_keyframes_poll;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = graphkeys_insertkey_exec;
+ ot->poll = graphop_editable_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* id-props */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_insertkey_types, 0, "Type", "");
+ /* id-props */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_insertkey_types, 0, "Type", "");
}
/* ******************** Click-Insert Keyframes Operator ************************* */
static int graphkeys_click_insert_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- bAnimListElem *ale;
- AnimData *adt;
- FCurve *fcu;
- float frame, val;
-
- /* get animation context */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get active F-Curve 'anim-list-element' */
- ale = get_active_fcurve_channel(&ac);
- if (ELEM(NULL, ale, ale->data)) {
- if (ale) MEM_freeN(ale);
- return OPERATOR_CANCELLED;
- }
- fcu = ale->data;
-
- /* when there are F-Modifiers on the curve, only allow adding
- * keyframes if these will be visible after doing so...
- */
- if (fcurve_is_keyframable(fcu)) {
- ListBase anim_data;
- ToolSettings *ts = ac.scene->toolsettings;
-
- short mapping_flag = ANIM_get_normalization_flags(&ac);
- float scale, offset;
-
- /* preserve selection? */
- if (RNA_boolean_get(op->ptr, "extend") == false) {
- /* deselect all keyframes first, so that we can immediately start manipulating the newly added one(s)
- * - only affect the keyframes themselves, as we don't want channels popping in and out...
- */
- deselect_graph_keys(&ac, false, SELECT_SUBTRACT, false);
- }
-
- /* get frame and value from props */
- frame = RNA_float_get(op->ptr, "frame");
- val = RNA_float_get(op->ptr, "value");
-
- /* apply inverse NLA-mapping to frame to get correct time in un-scaled action */
- adt = ANIM_nla_mapping_get(&ac, ale);
- frame = BKE_nla_tweakedit_remap(adt, frame, NLATIME_CONVERT_UNMAP);
-
- /* apply inverse unit-mapping to value to get correct value for F-Curves */
- scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, fcu, mapping_flag | ANIM_UNITCONV_RESTORE, &offset);
-
- val = val * scale - offset;
-
- /* insert keyframe on the specified frame + value */
- insert_vert_fcurve(fcu, frame, val, ts->keyframe_type, 0);
-
- ale->update |= ANIM_UPDATE_DEPS;
-
- BLI_listbase_clear(&anim_data);
- BLI_addtail(&anim_data, ale);
-
- ANIM_animdata_update(&ac, &anim_data);
- }
- else {
- /* warn about why this can't happen */
- if (fcu->fpt)
- BKE_report(op->reports, RPT_ERROR, "Keyframes cannot be added to sampled F-Curves");
- else if (fcu->flag & FCURVE_PROTECTED)
- BKE_report(op->reports, RPT_ERROR, "Active F-Curve is not editable");
- else
- BKE_report(op->reports, RPT_ERROR, "Remove F-Modifiers from F-Curve to add keyframes");
- }
-
- /* free temp data */
- MEM_freeN(ale);
-
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ bAnimListElem *ale;
+ AnimData *adt;
+ FCurve *fcu;
+ float frame, val;
+
+ /* get animation context */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get active F-Curve 'anim-list-element' */
+ ale = get_active_fcurve_channel(&ac);
+ if (ELEM(NULL, ale, ale->data)) {
+ if (ale)
+ MEM_freeN(ale);
+ return OPERATOR_CANCELLED;
+ }
+ fcu = ale->data;
+
+ /* when there are F-Modifiers on the curve, only allow adding
+ * keyframes if these will be visible after doing so...
+ */
+ if (fcurve_is_keyframable(fcu)) {
+ ListBase anim_data;
+ ToolSettings *ts = ac.scene->toolsettings;
+
+ short mapping_flag = ANIM_get_normalization_flags(&ac);
+ float scale, offset;
+
+ /* preserve selection? */
+ if (RNA_boolean_get(op->ptr, "extend") == false) {
+ /* deselect all keyframes first, so that we can immediately start manipulating the newly added one(s)
+ * - only affect the keyframes themselves, as we don't want channels popping in and out...
+ */
+ deselect_graph_keys(&ac, false, SELECT_SUBTRACT, false);
+ }
+
+ /* get frame and value from props */
+ frame = RNA_float_get(op->ptr, "frame");
+ val = RNA_float_get(op->ptr, "value");
+
+ /* apply inverse NLA-mapping to frame to get correct time in un-scaled action */
+ adt = ANIM_nla_mapping_get(&ac, ale);
+ frame = BKE_nla_tweakedit_remap(adt, frame, NLATIME_CONVERT_UNMAP);
+
+ /* apply inverse unit-mapping to value to get correct value for F-Curves */
+ scale = ANIM_unit_mapping_get_factor(
+ ac.scene, ale->id, fcu, mapping_flag | ANIM_UNITCONV_RESTORE, &offset);
+
+ val = val * scale - offset;
+
+ /* insert keyframe on the specified frame + value */
+ insert_vert_fcurve(fcu, frame, val, ts->keyframe_type, 0);
+
+ ale->update |= ANIM_UPDATE_DEPS;
+
+ BLI_listbase_clear(&anim_data);
+ BLI_addtail(&anim_data, ale);
+
+ ANIM_animdata_update(&ac, &anim_data);
+ }
+ else {
+ /* warn about why this can't happen */
+ if (fcu->fpt)
+ BKE_report(op->reports, RPT_ERROR, "Keyframes cannot be added to sampled F-Curves");
+ else if (fcu->flag & FCURVE_PROTECTED)
+ BKE_report(op->reports, RPT_ERROR, "Active F-Curve is not editable");
+ else
+ BKE_report(op->reports, RPT_ERROR, "Remove F-Modifiers from F-Curve to add keyframes");
+ }
+
+ /* free temp data */
+ MEM_freeN(ale);
+
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
static int graphkeys_click_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bAnimContext ac;
- ARegion *ar;
- View2D *v2d;
- int mval[2];
- float x, y;
+ bAnimContext ac;
+ ARegion *ar;
+ View2D *v2d;
+ int mval[2];
+ float x, y;
- /* get animation context */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get animation context */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* store mouse coordinates in View2D space, into the operator's properties */
- ar = ac.ar;
- v2d = &ar->v2d;
+ /* store mouse coordinates in View2D space, into the operator's properties */
+ ar = ac.ar;
+ v2d = &ar->v2d;
- mval[0] = (event->x - ar->winrct.xmin);
- mval[1] = (event->y - ar->winrct.ymin);
+ mval[0] = (event->x - ar->winrct.xmin);
+ mval[1] = (event->y - ar->winrct.ymin);
- UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
- RNA_float_set(op->ptr, "frame", x);
- RNA_float_set(op->ptr, "value", y);
+ RNA_float_set(op->ptr, "frame", x);
+ RNA_float_set(op->ptr, "value", y);
- /* run exec now */
- return graphkeys_click_insert_exec(C, op);
+ /* run exec now */
+ return graphkeys_click_insert_exec(C, op);
}
void GRAPH_OT_click_insert(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Click-Insert Keyframes";
- ot->idname = "GRAPH_OT_click_insert";
- ot->description = "Insert new keyframe at the cursor position for the active F-Curve";
-
- /* api callbacks */
- ot->invoke = graphkeys_click_insert_invoke;
- ot->exec = graphkeys_click_insert_exec;
- ot->poll = graphop_active_fcurve_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_float(ot->srna, "frame", 1.0f, -FLT_MAX, FLT_MAX, "Frame Number", "Frame to insert keyframe on", 0, 100);
- RNA_def_float(ot->srna, "value", 1.0f, -FLT_MAX, FLT_MAX, "Value", "Value for keyframe on", 0, 100);
-
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
+ /* identifiers */
+ ot->name = "Click-Insert Keyframes";
+ ot->idname = "GRAPH_OT_click_insert";
+ ot->description = "Insert new keyframe at the cursor position for the active F-Curve";
+
+ /* api callbacks */
+ ot->invoke = graphkeys_click_insert_invoke;
+ ot->exec = graphkeys_click_insert_exec;
+ ot->poll = graphop_active_fcurve_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float(ot->srna,
+ "frame",
+ 1.0f,
+ -FLT_MAX,
+ FLT_MAX,
+ "Frame Number",
+ "Frame to insert keyframe on",
+ 0,
+ 100);
+ RNA_def_float(
+ ot->srna, "value", 1.0f, -FLT_MAX, FLT_MAX, "Value", "Value for keyframe on", 0, 100);
+
+ RNA_def_boolean(ot->srna,
+ "extend",
+ false,
+ "Extend",
+ "Extend selection instead of deselecting everything first");
}
/* ******************** Copy/Paste Keyframes Operator ************************* */
@@ -802,342 +878,359 @@ void GRAPH_OT_click_insert(wmOperatorType *ot)
static short copy_graph_keys(bAnimContext *ac)
{
- ListBase anim_data = {NULL, NULL};
- int filter, ok = 0;
+ ListBase anim_data = {NULL, NULL};
+ int filter, ok = 0;
- /* clear buffer first */
- ANIM_fcurves_copybuf_free();
+ /* clear buffer first */
+ ANIM_fcurves_copybuf_free();
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* copy keyframes */
- ok = copy_animedit_keys(ac, &anim_data);
+ /* copy keyframes */
+ ok = copy_animedit_keys(ac, &anim_data);
- /* clean up */
- ANIM_animdata_freelist(&anim_data);
+ /* clean up */
+ ANIM_animdata_freelist(&anim_data);
- return ok;
+ return ok;
}
static short paste_graph_keys(bAnimContext *ac,
- const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip)
+ const eKeyPasteOffset offset_mode,
+ const eKeyMergeMode merge_mode,
+ bool flip)
{
- ListBase anim_data = {NULL, NULL};
- int filter, ok = 0;
+ ListBase anim_data = {NULL, NULL};
+ int filter, ok = 0;
- /* filter data
- * - First time we try to filter more strictly, allowing only selected channels
- * to allow copying animation between channels
- * - Second time, we loosen things up if nothing was found the first time, allowing
- * users to just paste keyframes back into the original curve again [#31670]
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+ /* filter data
+ * - First time we try to filter more strictly, allowing only selected channels
+ * to allow copying animation between channels
+ * - Second time, we loosen things up if nothing was found the first time, allowing
+ * users to just paste keyframes back into the original curve again [#31670]
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_NODUPLIS);
- if (ANIM_animdata_filter(ac, &anim_data, filter | ANIMFILTER_SEL, ac->data, ac->datatype) == 0)
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ if (ANIM_animdata_filter(ac, &anim_data, filter | ANIMFILTER_SEL, ac->data, ac->datatype) == 0)
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* paste keyframes */
- ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode, flip);
+ /* paste keyframes */
+ ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode, flip);
- /* clean up */
- ANIM_animdata_freelist(&anim_data);
+ /* clean up */
+ ANIM_animdata_freelist(&anim_data);
- return ok;
+ return ok;
}
/* ------------------- */
static int graphkeys_copy_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
+ bAnimContext ac;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* copy keyframes */
- if (copy_graph_keys(&ac)) {
- BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
- return OPERATOR_CANCELLED;
- }
+ /* copy keyframes */
+ if (copy_graph_keys(&ac)) {
+ BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
+ return OPERATOR_CANCELLED;
+ }
- /* just return - no operator needed here (no changes) */
- return OPERATOR_FINISHED;
+ /* just return - no operator needed here (no changes) */
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Keyframes";
- ot->idname = "GRAPH_OT_copy";
- ot->description = "Copy selected keyframes to the copy/paste buffer";
+ /* identifiers */
+ ot->name = "Copy Keyframes";
+ ot->idname = "GRAPH_OT_copy";
+ ot->description = "Copy selected keyframes to the copy/paste buffer";
- /* api callbacks */
- ot->exec = graphkeys_copy_exec;
- ot->poll = graphop_editable_keyframes_poll;
+ /* api callbacks */
+ ot->exec = graphkeys_copy_exec;
+ ot->poll = graphop_editable_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
-
static int graphkeys_paste_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
+ bAnimContext ac;
- const eKeyPasteOffset offset_mode = RNA_enum_get(op->ptr, "offset");
- const eKeyMergeMode merge_mode = RNA_enum_get(op->ptr, "merge");
- const bool flipped = RNA_boolean_get(op->ptr, "flipped");
+ const eKeyPasteOffset offset_mode = RNA_enum_get(op->ptr, "offset");
+ const eKeyMergeMode merge_mode = RNA_enum_get(op->ptr, "merge");
+ const bool flipped = RNA_boolean_get(op->ptr, "flipped");
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* ac.reports by default will be the global reports list, which won't show warnings */
- ac.reports = op->reports;
+ /* ac.reports by default will be the global reports list, which won't show warnings */
+ ac.reports = op->reports;
- /* paste keyframes - non-zero return means an error occurred while trying to paste */
- if (paste_graph_keys(&ac, offset_mode, merge_mode, flipped)) {
- return OPERATOR_CANCELLED;
- }
+ /* paste keyframes - non-zero return means an error occurred while trying to paste */
+ if (paste_graph_keys(&ac, offset_mode, merge_mode, flipped)) {
+ return OPERATOR_CANCELLED;
+ }
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_paste(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Paste Keyframes";
- ot->idname = "GRAPH_OT_paste";
- ot->description = "Paste keyframes from copy/paste buffer for the selected channels, starting on the current frame";
-
- /* api callbacks */
-// ot->invoke = WM_operator_props_popup; // better wait for graph redo panel
- ot->exec = graphkeys_paste_exec;
- ot->poll = graphop_editable_keyframes_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- RNA_def_enum(ot->srna, "offset", rna_enum_keyframe_paste_offset_items, KEYFRAME_PASTE_OFFSET_CFRA_START, "Offset", "Paste time offset of keys");
- RNA_def_enum(ot->srna, "merge", rna_enum_keyframe_paste_merge_items, KEYFRAME_PASTE_MERGE_MIX, "Type", "Method of merging pasted keys and existing");
- prop = RNA_def_boolean(ot->srna, "flipped", false, "Flipped", "Paste keyframes from mirrored bones if they exist");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Paste Keyframes";
+ ot->idname = "GRAPH_OT_paste";
+ ot->description =
+ "Paste keyframes from copy/paste buffer for the selected channels, starting on the current "
+ "frame";
+
+ /* api callbacks */
+ // ot->invoke = WM_operator_props_popup; // better wait for graph redo panel
+ ot->exec = graphkeys_paste_exec;
+ ot->poll = graphop_editable_keyframes_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna,
+ "offset",
+ rna_enum_keyframe_paste_offset_items,
+ KEYFRAME_PASTE_OFFSET_CFRA_START,
+ "Offset",
+ "Paste time offset of keys");
+ RNA_def_enum(ot->srna,
+ "merge",
+ rna_enum_keyframe_paste_merge_items,
+ KEYFRAME_PASTE_MERGE_MIX,
+ "Type",
+ "Method of merging pasted keys and existing");
+ prop = RNA_def_boolean(
+ ot->srna, "flipped", false, "Flipped", "Paste keyframes from mirrored bones if they exist");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ******************** Duplicate Keyframes Operator ************************* */
static void duplicate_graph_keys(bAnimContext *ac)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* loop through filtered data and delete selected keys */
- for (ale = anim_data.first; ale; ale = ale->next) {
- duplicate_fcurve_keys((FCurve *)ale->key_data);
+ /* loop through filtered data and delete selected keys */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ duplicate_fcurve_keys((FCurve *)ale->key_data);
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int graphkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
+ bAnimContext ac;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* duplicate keyframes */
- duplicate_graph_keys(&ac);
+ /* duplicate keyframes */
+ duplicate_graph_keys(&ac);
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_duplicate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Duplicate Keyframes";
- ot->idname = "GRAPH_OT_duplicate";
- ot->description = "Make a copy of all selected keyframes";
+ /* identifiers */
+ ot->name = "Duplicate Keyframes";
+ ot->idname = "GRAPH_OT_duplicate";
+ ot->description = "Make a copy of all selected keyframes";
- /* api callbacks */
- ot->exec = graphkeys_duplicate_exec;
- ot->poll = graphop_editable_keyframes_poll;
+ /* api callbacks */
+ ot->exec = graphkeys_duplicate_exec;
+ ot->poll = graphop_editable_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* to give to transform */
- RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
+ /* to give to transform */
+ RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
}
/* ******************** Delete Keyframes Operator ************************* */
static bool delete_graph_keys(bAnimContext *ac)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- bool changed_final = false;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ bool changed_final = false;
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* loop through filtered data and delete selected keys */
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
- AnimData *adt = ale->adt;
- bool changed;
+ /* loop through filtered data and delete selected keys */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
+ AnimData *adt = ale->adt;
+ bool changed;
- /* delete selected keyframes only */
- changed = delete_fcurve_keys(fcu);
+ /* delete selected keyframes only */
+ changed = delete_fcurve_keys(fcu);
- if (changed) {
- ale->update |= ANIM_UPDATE_DEFAULT;
- changed_final = true;
- }
+ if (changed) {
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ changed_final = true;
+ }
- /* Only delete curve too if it won't be doing anything anymore */
- if ((fcu->totvert == 0) &&
- (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0) &&
- (fcu->driver == NULL))
- {
- ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
- ale->key_data = NULL;
- }
- }
+ /* Only delete curve too if it won't be doing anything anymore */
+ if ((fcu->totvert == 0) &&
+ (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0) &&
+ (fcu->driver == NULL)) {
+ ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
+ ale->key_data = NULL;
+ }
+ }
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
- return changed_final;
+ return changed_final;
}
/* ------------------- */
static int graphkeys_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
+ bAnimContext ac;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* delete keyframes */
- if (!delete_graph_keys(&ac))
- return OPERATOR_CANCELLED;
+ /* delete keyframes */
+ if (!delete_graph_keys(&ac))
+ return OPERATOR_CANCELLED;
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Keyframes";
- ot->idname = "GRAPH_OT_delete";
- ot->description = "Remove all selected keyframes";
+ /* identifiers */
+ ot->name = "Delete Keyframes";
+ ot->idname = "GRAPH_OT_delete";
+ ot->description = "Remove all selected keyframes";
- /* api callbacks */
- ot->invoke = WM_operator_confirm;
- ot->exec = graphkeys_delete_exec;
- ot->poll = graphop_editable_keyframes_poll;
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = graphkeys_delete_exec;
+ ot->poll = graphop_editable_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Clean Keyframes Operator ************************* */
static void clean_graph_keys(bAnimContext *ac, float thresh, bool clean_chan)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* loop through filtered data and clean curves */
- for (ale = anim_data.first; ale; ale = ale->next) {
- clean_fcurve(ac, ale, thresh, clean_chan);
+ /* loop through filtered data and clean curves */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ clean_fcurve(ac, ale, thresh, clean_chan);
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int graphkeys_clean_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- float thresh;
- bool clean_chan;
+ bAnimContext ac;
+ float thresh;
+ bool clean_chan;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* get cleaning threshold */
- thresh = RNA_float_get(op->ptr, "threshold");
- clean_chan = RNA_boolean_get(op->ptr, "channels");
- /* clean keyframes */
- clean_graph_keys(&ac, thresh, clean_chan);
+ /* get cleaning threshold */
+ thresh = RNA_float_get(op->ptr, "threshold");
+ clean_chan = RNA_boolean_get(op->ptr, "channels");
+ /* clean keyframes */
+ clean_graph_keys(&ac, thresh, clean_chan);
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_clean(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clean Keyframes";
- ot->idname = "GRAPH_OT_clean";
- ot->description = "Simplify F-Curves by removing closely spaced keyframes";
+ /* identifiers */
+ ot->name = "Clean Keyframes";
+ ot->idname = "GRAPH_OT_clean";
+ ot->description = "Simplify F-Curves by removing closely spaced keyframes";
- /* api callbacks */
- //ot->invoke = // XXX we need that number popup for this!
- ot->exec = graphkeys_clean_exec;
- ot->poll = graphop_editable_keyframes_poll;
+ /* api callbacks */
+ //ot->invoke = // XXX we need that number popup for this!
+ ot->exec = graphkeys_clean_exec;
+ ot->poll = graphop_editable_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_float(ot->srna, "threshold", 0.001f, 0.0f, FLT_MAX, "Threshold", "", 0.0f, 1000.0f);
- RNA_def_boolean(ot->srna, "channels", false, "Channels", "");
+ /* properties */
+ ot->prop = RNA_def_float(
+ ot->srna, "threshold", 0.001f, 0.0f, FLT_MAX, "Threshold", "", 0.0f, 1000.0f);
+ RNA_def_boolean(ot->srna, "channels", false, "Channels", "");
}
/* ******************** Bake F-Curve Operator *********************** */
@@ -1146,79 +1239,80 @@ void GRAPH_OT_clean(wmOperatorType *ot)
/* Bake each F-Curve into a set of samples */
static void bake_graph_curves(bAnimContext *ac, int start, int end)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL |
+ ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* loop through filtered data and add keys between selected keyframes on every frame */
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
- ChannelDriver *driver = fcu->driver;
+ /* loop through filtered data and add keys between selected keyframes on every frame */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
+ ChannelDriver *driver = fcu->driver;
- /* disable driver so that it don't muck up the sampling process */
- fcu->driver = NULL;
+ /* disable driver so that it don't muck up the sampling process */
+ fcu->driver = NULL;
- /* create samples */
- fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve);
+ /* create samples */
+ fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve);
- /* restore driver */
- fcu->driver = driver;
+ /* restore driver */
+ fcu->driver = driver;
- ale->update |= ANIM_UPDATE_DEPS;
- }
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int graphkeys_bake_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
- Scene *scene = NULL;
- int start, end;
+ bAnimContext ac;
+ Scene *scene = NULL;
+ int start, end;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* for now, init start/end from preview-range extents */
- // TODO: add properties for this
- scene = ac.scene;
- start = PSFRA;
- end = PEFRA;
+ /* for now, init start/end from preview-range extents */
+ // TODO: add properties for this
+ scene = ac.scene;
+ start = PSFRA;
+ end = PEFRA;
- /* bake keyframes */
- bake_graph_curves(&ac, start, end);
+ /* bake keyframes */
+ bake_graph_curves(&ac, start, end);
- /* set notifier that keyframes have changed */
- // NOTE: some distinction between order/number of keyframes and type should be made?
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ /* set notifier that keyframes have changed */
+ // NOTE: some distinction between order/number of keyframes and type should be made?
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_bake(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Bake Curve";
- ot->idname = "GRAPH_OT_bake";
- ot->description = "Bake selected F-Curves to a set of sampled points defining a similar curve";
+ /* identifiers */
+ ot->name = "Bake Curve";
+ ot->idname = "GRAPH_OT_bake";
+ ot->description = "Bake selected F-Curves to a set of sampled points defining a similar curve";
- /* api callbacks */
- ot->invoke = WM_operator_confirm; // FIXME...
- ot->exec = graphkeys_bake_exec;
- ot->poll = graphop_selected_fcurve_poll;
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm; // FIXME...
+ ot->exec = graphkeys_bake_exec;
+ ot->poll = graphop_selected_fcurve_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- // todo: add props for start/end frames
+ // todo: add props for start/end frames
}
#ifdef WITH_AUDASPACE
@@ -1232,9 +1326,9 @@ void GRAPH_OT_bake(wmOperatorType *ot)
* which provides the necessary info for baking the sound
*/
typedef struct tSoundBakeInfo {
- float *samples;
- int length;
- int cfra;
+ float *samples;
+ int length;
+ int cfra;
} tSoundBakeInfo;
/* ------------------- */
@@ -1244,154 +1338,214 @@ typedef struct tSoundBakeInfo {
*/
static float fcurve_samplingcb_sound(FCurve *UNUSED(fcu), void *data, float evaltime)
{
- tSoundBakeInfo *sbi = (tSoundBakeInfo *)data;
+ tSoundBakeInfo *sbi = (tSoundBakeInfo *)data;
- int position = evaltime - sbi->cfra;
- if ((position < 0) || (position >= sbi->length))
- return 0.0f;
+ int position = evaltime - sbi->cfra;
+ if ((position < 0) || (position >= sbi->length))
+ return 0.0f;
- return sbi->samples[position];
+ return sbi->samples[position];
}
/* ------------------- */
static int graphkeys_sound_bake_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- tSoundBakeInfo sbi;
- Scene *scene = NULL;
- int start, end;
+ tSoundBakeInfo sbi;
+ Scene *scene = NULL;
+ int start, end;
- char path[FILE_MAX];
+ char path[FILE_MAX];
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- RNA_string_get(op->ptr, "filepath", path);
+ RNA_string_get(op->ptr, "filepath", path);
- if (!BLI_is_file(path)) {
- BKE_reportf(op->reports, RPT_ERROR, "File not found '%s'", path);
- return OPERATOR_CANCELLED;
- }
+ if (!BLI_is_file(path)) {
+ BKE_reportf(op->reports, RPT_ERROR, "File not found '%s'", path);
+ return OPERATOR_CANCELLED;
+ }
- scene = ac.scene; /* current scene */
+ scene = ac.scene; /* current scene */
- /* store necessary data for the baking steps */
- sbi.samples = AUD_readSoundBuffer(path,
- RNA_float_get(op->ptr, "low"),
- RNA_float_get(op->ptr, "high"),
- RNA_float_get(op->ptr, "attack"),
- RNA_float_get(op->ptr, "release"),
- RNA_float_get(op->ptr, "threshold"),
- RNA_boolean_get(op->ptr, "use_accumulate"),
- RNA_boolean_get(op->ptr, "use_additive"),
- RNA_boolean_get(op->ptr, "use_square"),
- RNA_float_get(op->ptr, "sthreshold"),
- FPS, &sbi.length);
+ /* store necessary data for the baking steps */
+ sbi.samples = AUD_readSoundBuffer(path,
+ RNA_float_get(op->ptr, "low"),
+ RNA_float_get(op->ptr, "high"),
+ RNA_float_get(op->ptr, "attack"),
+ RNA_float_get(op->ptr, "release"),
+ RNA_float_get(op->ptr, "threshold"),
+ RNA_boolean_get(op->ptr, "use_accumulate"),
+ RNA_boolean_get(op->ptr, "use_additive"),
+ RNA_boolean_get(op->ptr, "use_square"),
+ RNA_float_get(op->ptr, "sthreshold"),
+ FPS,
+ &sbi.length);
- if (sbi.samples == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
- return OPERATOR_CANCELLED;
- }
+ if (sbi.samples == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
+ return OPERATOR_CANCELLED;
+ }
- /* determine extents of the baking */
- sbi.cfra = start = CFRA;
- end = CFRA + sbi.length - 1;
+ /* determine extents of the baking */
+ sbi.cfra = start = CFRA;
+ end = CFRA + sbi.length - 1;
- /* filter anim channels */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* filter anim channels */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL |
+ ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* loop through all selected F-Curves, replacing its data with the sound samples */
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
+ /* loop through all selected F-Curves, replacing its data with the sound samples */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
- /* sample the sound */
- fcurve_store_samples(fcu, &sbi, start, end, fcurve_samplingcb_sound);
+ /* sample the sound */
+ fcurve_store_samples(fcu, &sbi, start, end, fcurve_samplingcb_sound);
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
- /* free sample data */
- free(sbi.samples);
+ /* free sample data */
+ free(sbi.samples);
- /* validate keyframes after editing */
- ANIM_animdata_update(&ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ /* validate keyframes after editing */
+ ANIM_animdata_update(&ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
- /* set notifier that 'keyframes' have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ /* set notifier that 'keyframes' have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-#else //WITH_AUDASPACE
+#else //WITH_AUDASPACE
static int graphkeys_sound_bake_exec(bContext *UNUSED(C), wmOperator *op)
{
- BKE_report(op->reports, RPT_ERROR, "Compiled without sound support");
+ BKE_report(op->reports, RPT_ERROR, "Compiled without sound support");
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
-#endif //WITH_AUDASPACE
+#endif //WITH_AUDASPACE
static int graphkeys_sound_bake_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bAnimContext ac;
+ bAnimContext ac;
- /* verify editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* verify editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- return WM_operator_filesel(C, op, event);
+ return WM_operator_filesel(C, op, event);
}
void GRAPH_OT_sound_bake(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Bake Sound to F-Curves";
- ot->idname = "GRAPH_OT_sound_bake";
- ot->description = "Bakes a sound wave to selected F-Curves";
-
- /* api callbacks */
- ot->invoke = graphkeys_sound_bake_invoke;
- ot->exec = graphkeys_sound_bake_exec;
- ot->poll = graphop_selected_fcurve_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
- RNA_def_float(ot->srna, "low", 0.0f, 0.0, 100000.0, "Lowest frequency",
- "Cutoff frequency of a high-pass filter that is applied to the audio data", 0.1, 1000.00);
- RNA_def_float(ot->srna, "high", 100000.0, 0.0, 100000.0, "Highest frequency",
- "Cutoff frequency of a low-pass filter that is applied to the audio data", 0.1, 1000.00);
- RNA_def_float(ot->srna, "attack", 0.005, 0.0, 2.0, "Attack time",
- "Value for the hull curve calculation that tells how fast the hull curve can rise "
- "(the lower the value the steeper it can rise)", 0.01, 0.1);
- RNA_def_float(ot->srna, "release", 0.2, 0.0, 5.0, "Release time",
- "Value for the hull curve calculation that tells how fast the hull curve can fall "
- "(the lower the value the steeper it can fall)", 0.01, 0.2);
- RNA_def_float(ot->srna, "threshold", 0.0, 0.0, 1.0, "Threshold",
- "Minimum amplitude value needed to influence the hull curve", 0.01, 0.1);
- RNA_def_boolean(ot->srna, "use_accumulate", 0, "Accumulate",
- "Only the positive differences of the hull curve amplitudes are summarized to produce the output");
- RNA_def_boolean(ot->srna, "use_additive", 0, "Additive",
- "The amplitudes of the hull curve are summarized (or, when Accumulate is enabled, "
- "both positive and negative differences are accumulated)");
- RNA_def_boolean(ot->srna, "use_square", 0, "Square",
- "The output is a square curve (negative values always result in -1, and positive ones in 1)");
- RNA_def_float(ot->srna, "sthreshold", 0.1, 0.0, 1.0, "Square Threshold",
- "Square only: all values with an absolute amplitude lower than that result in 0", 0.01, 0.1);
+ /* identifiers */
+ ot->name = "Bake Sound to F-Curves";
+ ot->idname = "GRAPH_OT_sound_bake";
+ ot->description = "Bakes a sound wave to selected F-Curves";
+
+ /* api callbacks */
+ ot->invoke = graphkeys_sound_bake_invoke;
+ ot->exec = graphkeys_sound_bake_exec;
+ ot->poll = graphop_selected_fcurve_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_FILEPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
+ RNA_def_float(ot->srna,
+ "low",
+ 0.0f,
+ 0.0,
+ 100000.0,
+ "Lowest frequency",
+ "Cutoff frequency of a high-pass filter that is applied to the audio data",
+ 0.1,
+ 1000.00);
+ RNA_def_float(ot->srna,
+ "high",
+ 100000.0,
+ 0.0,
+ 100000.0,
+ "Highest frequency",
+ "Cutoff frequency of a low-pass filter that is applied to the audio data",
+ 0.1,
+ 1000.00);
+ RNA_def_float(ot->srna,
+ "attack",
+ 0.005,
+ 0.0,
+ 2.0,
+ "Attack time",
+ "Value for the hull curve calculation that tells how fast the hull curve can rise "
+ "(the lower the value the steeper it can rise)",
+ 0.01,
+ 0.1);
+ RNA_def_float(ot->srna,
+ "release",
+ 0.2,
+ 0.0,
+ 5.0,
+ "Release time",
+ "Value for the hull curve calculation that tells how fast the hull curve can fall "
+ "(the lower the value the steeper it can fall)",
+ 0.01,
+ 0.2);
+ RNA_def_float(ot->srna,
+ "threshold",
+ 0.0,
+ 0.0,
+ 1.0,
+ "Threshold",
+ "Minimum amplitude value needed to influence the hull curve",
+ 0.01,
+ 0.1);
+ RNA_def_boolean(ot->srna,
+ "use_accumulate",
+ 0,
+ "Accumulate",
+ "Only the positive differences of the hull curve amplitudes are summarized to "
+ "produce the output");
+ RNA_def_boolean(
+ ot->srna,
+ "use_additive",
+ 0,
+ "Additive",
+ "The amplitudes of the hull curve are summarized (or, when Accumulate is enabled, "
+ "both positive and negative differences are accumulated)");
+ RNA_def_boolean(ot->srna,
+ "use_square",
+ 0,
+ "Square",
+ "The output is a square curve (negative values always result in -1, and "
+ "positive ones in 1)");
+ RNA_def_float(ot->srna,
+ "sthreshold",
+ 0.1,
+ 0.0,
+ 1.0,
+ "Square Threshold",
+ "Square only: all values with an absolute amplitude lower than that result in 0",
+ 0.01,
+ 0.1);
}
/* ******************** Sample Keyframes Operator *********************** */
@@ -1402,171 +1556,188 @@ void GRAPH_OT_sound_bake(wmOperatorType *ot)
/* Evaluates the curves between each selected keyframe on each frame, and keys the value */
static void sample_graph_keys(bAnimContext *ac)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* loop through filtered data and add keys between selected keyframes on every frame */
- for (ale = anim_data.first; ale; ale = ale->next) {
- sample_fcurve((FCurve *)ale->key_data);
+ /* loop through filtered data and add keys between selected keyframes on every frame */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ sample_fcurve((FCurve *)ale->key_data);
- ale->update |= ANIM_UPDATE_DEPS;
- }
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int graphkeys_sample_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
+ bAnimContext ac;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* sample keyframes */
- sample_graph_keys(&ac);
+ /* sample keyframes */
+ sample_graph_keys(&ac);
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_sample(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Sample Keyframes";
- ot->idname = "GRAPH_OT_sample";
- ot->description = "Add keyframes on every frame between the selected keyframes";
+ /* identifiers */
+ ot->name = "Sample Keyframes";
+ ot->idname = "GRAPH_OT_sample";
+ ot->description = "Add keyframes on every frame between the selected keyframes";
- /* api callbacks */
- ot->exec = graphkeys_sample_exec;
- ot->poll = graphop_editable_keyframes_poll;
+ /* api callbacks */
+ ot->exec = graphkeys_sample_exec;
+ ot->poll = graphop_editable_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/* ************************************************************************** */
/* SETTINGS STUFF */
/* ******************** Set Extrapolation-Type Operator *********************** */
/* defines for make/clear cyclic extrapolation tools */
-#define MAKE_CYCLIC_EXPO -1
-#define CLEAR_CYCLIC_EXPO -2
+#define MAKE_CYCLIC_EXPO -1
+#define CLEAR_CYCLIC_EXPO -2
/* defines for set extrapolation-type for selected keyframes tool */
static const EnumPropertyItem prop_graphkeys_expo_types[] = {
- {FCURVE_EXTRAPOLATE_CONSTANT, "CONSTANT", 0, "Constant Extrapolation", "Values on endpoint keyframes are held"},
- {FCURVE_EXTRAPOLATE_LINEAR, "LINEAR", 0, "Linear Extrapolation", "Straight-line slope of end segments are extended past the endpoint keyframes"},
-
- {MAKE_CYCLIC_EXPO, "MAKE_CYCLIC", 0, "Make Cyclic (F-Modifier)", "Add Cycles F-Modifier if one doesn't exist already"},
- {CLEAR_CYCLIC_EXPO, "CLEAR_CYCLIC", 0, "Clear Cyclic (F-Modifier)", "Remove Cycles F-Modifier if not needed anymore"},
- {0, NULL, 0, NULL, NULL},
+ {FCURVE_EXTRAPOLATE_CONSTANT,
+ "CONSTANT",
+ 0,
+ "Constant Extrapolation",
+ "Values on endpoint keyframes are held"},
+ {FCURVE_EXTRAPOLATE_LINEAR,
+ "LINEAR",
+ 0,
+ "Linear Extrapolation",
+ "Straight-line slope of end segments are extended past the endpoint keyframes"},
+
+ {MAKE_CYCLIC_EXPO,
+ "MAKE_CYCLIC",
+ 0,
+ "Make Cyclic (F-Modifier)",
+ "Add Cycles F-Modifier if one doesn't exist already"},
+ {CLEAR_CYCLIC_EXPO,
+ "CLEAR_CYCLIC",
+ 0,
+ "Clear Cyclic (F-Modifier)",
+ "Remove Cycles F-Modifier if not needed anymore"},
+ {0, NULL, 0, NULL, NULL},
};
/* this function is responsible for setting extrapolation mode for keyframes */
static void setexpo_graph_keys(bAnimContext *ac, short mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* loop through setting mode per F-Curve */
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->data;
-
- if (mode >= 0) {
- /* just set mode setting */
- fcu->extend = mode;
-
- ale->update |= ANIM_UPDATE_HANDLES;
- }
- else {
- /* shortcuts for managing Cycles F-Modifiers to make it easier to toggle cyclic animation
- * without having to go through FModifier UI in Graph Editor to do so
- */
- if (mode == MAKE_CYCLIC_EXPO) {
- /* only add if one doesn't exist */
- if (list_has_suitable_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, -1) == 0) {
- // TODO: add some more preset versions which set different extrapolation options?
- add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, fcu);
- }
- }
- else if (mode == CLEAR_CYCLIC_EXPO) {
- /* remove all the modifiers fitting this description */
- FModifier *fcm, *fcn = NULL;
-
- for (fcm = fcu->modifiers.first; fcm; fcm = fcn) {
- fcn = fcm->next;
-
- if (fcm->type == FMODIFIER_TYPE_CYCLES)
- remove_fmodifier(&fcu->modifiers, fcm);
- }
- }
- }
-
- ale->update |= ANIM_UPDATE_DEPS;
- }
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL |
+ ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through setting mode per F-Curve */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->data;
+
+ if (mode >= 0) {
+ /* just set mode setting */
+ fcu->extend = mode;
+
+ ale->update |= ANIM_UPDATE_HANDLES;
+ }
+ else {
+ /* shortcuts for managing Cycles F-Modifiers to make it easier to toggle cyclic animation
+ * without having to go through FModifier UI in Graph Editor to do so
+ */
+ if (mode == MAKE_CYCLIC_EXPO) {
+ /* only add if one doesn't exist */
+ if (list_has_suitable_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, -1) == 0) {
+ // TODO: add some more preset versions which set different extrapolation options?
+ add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, fcu);
+ }
+ }
+ else if (mode == CLEAR_CYCLIC_EXPO) {
+ /* remove all the modifiers fitting this description */
+ FModifier *fcm, *fcn = NULL;
+
+ for (fcm = fcu->modifiers.first; fcm; fcm = fcn) {
+ fcn = fcm->next;
+
+ if (fcm->type == FMODIFIER_TYPE_CYCLES)
+ remove_fmodifier(&fcu->modifiers, fcm);
+ }
+ }
+ }
+
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int graphkeys_expo_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- short mode;
+ bAnimContext ac;
+ short mode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* 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");
+ /* get handle setting mode */
+ mode = RNA_enum_get(op->ptr, "type");
- /* set handle type */
- setexpo_graph_keys(&ac, mode);
+ /* set handle type */
+ setexpo_graph_keys(&ac, mode);
- /* set notifier that keyframe properties have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
+ /* set notifier that keyframe properties have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_extrapolation_type(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Keyframe Extrapolation";
- ot->idname = "GRAPH_OT_extrapolation_type";
- ot->description = "Set extrapolation mode for selected F-Curves";
+ /* identifiers */
+ ot->name = "Set Keyframe Extrapolation";
+ ot->idname = "GRAPH_OT_extrapolation_type";
+ ot->description = "Set extrapolation mode for selected F-Curves";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = graphkeys_expo_exec;
- ot->poll = graphop_editable_keyframes_poll;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = graphkeys_expo_exec;
+ ot->poll = graphop_editable_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* id-props */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_expo_types, 0, "Type", "");
+ /* id-props */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_expo_types, 0, "Type", "");
}
/* ******************** Set Interpolation-Type Operator *********************** */
@@ -1574,134 +1745,140 @@ void GRAPH_OT_extrapolation_type(wmOperatorType *ot)
/* this function is responsible for setting interpolation mode for keyframes */
static void setipo_graph_keys(bAnimContext *ac, short mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- KeyframeEditFunc set_cb = ANIM_editkeyframes_ipo(mode);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ KeyframeEditFunc set_cb = ANIM_editkeyframes_ipo(mode);
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
+ 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);
+ /* 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_NOHANDLES;
- }
+ ale->update |= ANIM_UPDATE_DEFAULT_NOHANDLES;
+ }
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int graphkeys_ipo_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- short mode;
+ bAnimContext ac;
+ short mode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* 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");
+ /* get handle setting mode */
+ mode = RNA_enum_get(op->ptr, "type");
- /* set handle type */
- setipo_graph_keys(&ac, mode);
+ /* set handle type */
+ setipo_graph_keys(&ac, mode);
- /* set notifier that keyframe properties have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
+ /* set notifier that keyframe properties have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_interpolation_type(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Keyframe Interpolation";
- ot->idname = "GRAPH_OT_interpolation_type";
- ot->description = "Set interpolation mode for the F-Curve segments starting from the selected keyframes";
+ /* identifiers */
+ ot->name = "Set Keyframe Interpolation";
+ ot->idname = "GRAPH_OT_interpolation_type";
+ ot->description =
+ "Set interpolation mode for the F-Curve segments starting from the selected keyframes";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = graphkeys_ipo_exec;
- ot->poll = graphop_editable_keyframes_poll;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = graphkeys_ipo_exec;
+ ot->poll = graphop_editable_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* id-props */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_beztriple_interpolation_mode_items, 0, "Type", "");
+ /* id-props */
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", rna_enum_beztriple_interpolation_mode_items, 0, "Type", "");
}
/* ******************** Set Easing Operator *********************** */
static void seteasing_graph_keys(bAnimContext *ac, short mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- KeyframeEditFunc set_cb = ANIM_editkeyframes_easing(mode);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ KeyframeEditFunc set_cb = ANIM_editkeyframes_easing(mode);
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* loop through setting BezTriple easing
- * 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);
+ /* loop through setting BezTriple easing
+ * 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_NOHANDLES;
- }
+ ale->update |= ANIM_UPDATE_DEFAULT_NOHANDLES;
+ }
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
static int graphkeys_easing_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- short mode;
+ bAnimContext ac;
+ short mode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* 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");
+ /* get handle setting mode */
+ mode = RNA_enum_get(op->ptr, "type");
- /* set handle type */
- seteasing_graph_keys(&ac, mode);
+ /* set handle type */
+ seteasing_graph_keys(&ac, mode);
- /* set notifier that keyframe properties have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
+ /* set notifier that keyframe properties have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_easing_type(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Keyframe Easing Type";
- ot->idname = "GRAPH_OT_easing_type";
- ot->description = "Set easing type for the F-Curve segments starting from the selected keyframes";
+ /* identifiers */
+ ot->name = "Set Keyframe Easing Type";
+ ot->idname = "GRAPH_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 = graphkeys_easing_exec;
- ot->poll = graphop_editable_keyframes_poll;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = graphkeys_easing_exec;
+ ot->poll = graphop_editable_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* 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", "");
+ /* id-props */
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", rna_enum_beztriple_interpolation_easing_items, 0, "Type", "");
}
/* ******************** Set Handle-Type Operator *********************** */
@@ -1709,75 +1886,76 @@ void GRAPH_OT_easing_type(wmOperatorType *ot)
/* this function is responsible for setting handle-type of selected keyframes */
static void sethandles_graph_keys(bAnimContext *ac, short mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- KeyframeEditFunc edit_cb = ANIM_editkeyframes_handles(mode);
- KeyframeEditFunc sel_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
+ KeyframeEditFunc edit_cb = ANIM_editkeyframes_handles(mode);
+ KeyframeEditFunc sel_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* loop through setting flags for handles
- * 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) {
- FCurve *fcu = (FCurve *)ale->key_data;
+ /* loop through setting flags for handles
+ * 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) {
+ FCurve *fcu = (FCurve *)ale->key_data;
- /* any selected keyframes for editing? */
- if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL)) {
- /* change type of selected handles */
- ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, edit_cb, calchandles_fcurve);
+ /* any selected keyframes for editing? */
+ if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL)) {
+ /* change type of selected handles */
+ ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, edit_cb, calchandles_fcurve);
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
- }
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
+ }
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int graphkeys_handletype_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- short mode;
+ bAnimContext ac;
+ short mode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* 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");
+ /* get handle setting mode */
+ mode = RNA_enum_get(op->ptr, "type");
- /* set handle type */
- sethandles_graph_keys(&ac, mode);
+ /* set handle type */
+ sethandles_graph_keys(&ac, mode);
- /* set notifier that keyframe properties have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
+ /* set notifier that keyframe properties have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_handle_type(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Keyframe Handle Type";
- ot->idname = "GRAPH_OT_handle_type";
- ot->description = "Set type of handle for selected keyframes";
+ /* identifiers */
+ ot->name = "Set Keyframe Handle Type";
+ ot->idname = "GRAPH_OT_handle_type";
+ ot->description = "Set type of handle for selected keyframes";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = graphkeys_handletype_exec;
- ot->poll = graphop_editable_keyframes_poll;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = graphkeys_handletype_exec;
+ ot->poll = graphop_editable_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* id-props */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_keyframe_handle_type_items, 0, "Type", "");
+ /* id-props */
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_keyframe_handle_type_items, 0, "Type", "");
}
/* ************************************************************************** */
@@ -1792,599 +1970,652 @@ void GRAPH_OT_handle_type(wmOperatorType *ot)
/* set of three euler-rotation F-Curves */
typedef struct tEulerFilter {
- struct tEulerFilter *next, *prev;
-
- /** ID-block which owns the channels */
- ID *id;
- /** 3 Pointers to F-Curves */
- FCurve *(fcurves[3]);
- /** Pointer to one of the RNA Path's used by one of the F-Curves */
- const char *rna_path;
+ struct tEulerFilter *next, *prev;
+
+ /** ID-block which owns the channels */
+ ID *id;
+ /** 3 Pointers to F-Curves */
+ FCurve *(fcurves[3]);
+ /** Pointer to one of the RNA Path's used by one of the F-Curves */
+ const char *rna_path;
} tEulerFilter;
static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- ListBase eulers = {NULL, NULL};
- tEulerFilter *euf = NULL;
- int groups = 0, failed = 0;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* The process is done in two passes:
- * 1) Sets of three related rotation curves are identified from the selected channels,
- * and are stored as a single 'operation unit' for the next step
- * 2) Each set of three F-Curves is processed for each keyframe, with the values being
- * processed as necessary
- */
-
- /* step 1: extract only the rotation f-curves */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->data;
-
- /* check if this is an appropriate F-Curve
- * - only rotation curves
- * - for pchan curves, make sure we're only using the euler curves
- */
- if (strstr(fcu->rna_path, "rotation_euler") == NULL)
- continue;
- else if (ELEM(fcu->array_index, 0, 1, 2) == 0) {
- BKE_reportf(op->reports, RPT_WARNING,
- "Euler Rotation F-Curve has invalid index (ID='%s', Path='%s', Index=%d)",
- (ale->id) ? ale->id->name : TIP_("<No ID>"), fcu->rna_path, fcu->array_index);
- continue;
- }
-
- /* optimization: assume that xyz curves will always be stored consecutively,
- * so if the paths or the ID's don't match up, then a curve needs to be added
- * to a new group
- */
- if ((euf) && (euf->id == ale->id) && (STREQ(euf->rna_path, fcu->rna_path))) {
- /* this should be fine to add to the existing group then */
- euf->fcurves[fcu->array_index] = fcu;
- }
- else {
- /* just add to a new block */
- euf = MEM_callocN(sizeof(tEulerFilter), "tEulerFilter");
- BLI_addtail(&eulers, euf);
- groups++;
-
- euf->id = ale->id;
- /* this should be safe, since we're only using it for a short time */
- euf->rna_path = fcu->rna_path;
- euf->fcurves[fcu->array_index] = fcu;
- }
-
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
-
- if (groups == 0) {
- ANIM_animdata_freelist(&anim_data);
- BKE_report(op->reports, RPT_WARNING, "No Euler Rotation F-Curves to fix up");
- return OPERATOR_CANCELLED;
- }
-
- /* step 2: go through each set of curves, processing the values at each keyframe
- * - it is assumed that there must be a full set of keyframes at each keyframe position
- */
- for (euf = eulers.first; euf; euf = euf->next) {
- int f;
-
- /* sanity check: ensure that there are enough F-Curves to work on in this group */
- /* TODO: also enforce assumption that there be a full set of keyframes
- * at each position by ensuring that totvert counts are same? */
- if (ELEM(NULL, euf->fcurves[0], euf->fcurves[1], euf->fcurves[2])) {
- /* report which components are missing */
- BKE_reportf(op->reports, RPT_WARNING,
- "Missing %s%s%s component(s) of euler rotation for ID='%s' and RNA-Path='%s'",
- (euf->fcurves[0] == NULL) ? "X" : "",
- (euf->fcurves[1] == NULL) ? "Y" : "",
- (euf->fcurves[2] == NULL) ? "Z" : "",
- euf->id->name, euf->rna_path);
-
- /* keep track of number of failed sets, and carry on to next group */
- failed++;
- continue;
- }
-
- /* simple method: just treat any difference between keys of greater than 180 degrees as being a flip */
- /* FIXME: there are more complicated methods that will be needed to fix more cases than just some */
- for (f = 0; f < 3; f++) {
- FCurve *fcu = euf->fcurves[f];
- BezTriple *bezt, *prev;
- unsigned int i;
-
- /* skip if not enough vets to do a decent analysis of... */
- if (fcu->totvert <= 2)
- continue;
-
- /* prev follows bezt, bezt = "current" point to be fixed */
- /* our method depends on determining a "difference" from the previous vert */
- for (i = 1, prev = fcu->bezt, bezt = fcu->bezt + 1; i < fcu->totvert; i++, prev = bezt++) {
- const float sign = (prev->vec[1][1] > bezt->vec[1][1]) ? 1.0f : -1.0f;
-
- /* > 180 degree flip? */
- if ((sign * (prev->vec[1][1] - bezt->vec[1][1])) >= (float)M_PI) {
- /* 360 degrees to add/subtract frame value until difference
- * is acceptably small that there's no more flip */
- const float fac = sign * 2.0f * (float)M_PI;
-
- while ((sign * (prev->vec[1][1] - bezt->vec[1][1])) >= (float)M_PI) {
- bezt->vec[0][1] += fac;
- bezt->vec[1][1] += fac;
- bezt->vec[2][1] += fac;
- }
- }
- }
- }
- }
- BLI_freelistN(&eulers);
-
- ANIM_animdata_update(&ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
-
- /* updates + finishing warnings */
- if (failed == groups) {
- BKE_report(op->reports, RPT_ERROR,
- "No Euler Rotations could be corrected, ensure each rotation has keys for all components, "
- "and that F-Curves for these are in consecutive XYZ order and selected");
- return OPERATOR_CANCELLED;
- }
- else {
- if (failed) {
- BKE_report(op->reports, RPT_ERROR,
- "Some Euler Rotations could not be corrected due to missing/unselected/out-of-order F-Curves, "
- "ensure each rotation has keys for all components, and that F-Curves for these are in "
- "consecutive XYZ order and selected");
- }
-
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
-
- /* done at last */
- return OPERATOR_FINISHED;
- }
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ ListBase eulers = {NULL, NULL};
+ tEulerFilter *euf = NULL;
+ int groups = 0, failed = 0;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* The process is done in two passes:
+ * 1) Sets of three related rotation curves are identified from the selected channels,
+ * and are stored as a single 'operation unit' for the next step
+ * 2) Each set of three F-Curves is processed for each keyframe, with the values being
+ * processed as necessary
+ */
+
+ /* step 1: extract only the rotation f-curves */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CURVE_VISIBLE |
+ ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->data;
+
+ /* check if this is an appropriate F-Curve
+ * - only rotation curves
+ * - for pchan curves, make sure we're only using the euler curves
+ */
+ if (strstr(fcu->rna_path, "rotation_euler") == NULL)
+ continue;
+ else if (ELEM(fcu->array_index, 0, 1, 2) == 0) {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Euler Rotation F-Curve has invalid index (ID='%s', Path='%s', Index=%d)",
+ (ale->id) ? ale->id->name : TIP_("<No ID>"),
+ fcu->rna_path,
+ fcu->array_index);
+ continue;
+ }
+
+ /* optimization: assume that xyz curves will always be stored consecutively,
+ * so if the paths or the ID's don't match up, then a curve needs to be added
+ * to a new group
+ */
+ if ((euf) && (euf->id == ale->id) && (STREQ(euf->rna_path, fcu->rna_path))) {
+ /* this should be fine to add to the existing group then */
+ euf->fcurves[fcu->array_index] = fcu;
+ }
+ else {
+ /* just add to a new block */
+ euf = MEM_callocN(sizeof(tEulerFilter), "tEulerFilter");
+ BLI_addtail(&eulers, euf);
+ groups++;
+
+ euf->id = ale->id;
+ /* this should be safe, since we're only using it for a short time */
+ euf->rna_path = fcu->rna_path;
+ euf->fcurves[fcu->array_index] = fcu;
+ }
+
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
+
+ if (groups == 0) {
+ ANIM_animdata_freelist(&anim_data);
+ BKE_report(op->reports, RPT_WARNING, "No Euler Rotation F-Curves to fix up");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* step 2: go through each set of curves, processing the values at each keyframe
+ * - it is assumed that there must be a full set of keyframes at each keyframe position
+ */
+ for (euf = eulers.first; euf; euf = euf->next) {
+ int f;
+
+ /* sanity check: ensure that there are enough F-Curves to work on in this group */
+ /* TODO: also enforce assumption that there be a full set of keyframes
+ * at each position by ensuring that totvert counts are same? */
+ if (ELEM(NULL, euf->fcurves[0], euf->fcurves[1], euf->fcurves[2])) {
+ /* report which components are missing */
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Missing %s%s%s component(s) of euler rotation for ID='%s' and RNA-Path='%s'",
+ (euf->fcurves[0] == NULL) ? "X" : "",
+ (euf->fcurves[1] == NULL) ? "Y" : "",
+ (euf->fcurves[2] == NULL) ? "Z" : "",
+ euf->id->name,
+ euf->rna_path);
+
+ /* keep track of number of failed sets, and carry on to next group */
+ failed++;
+ continue;
+ }
+
+ /* simple method: just treat any difference between keys of greater than 180 degrees as being a flip */
+ /* FIXME: there are more complicated methods that will be needed to fix more cases than just some */
+ for (f = 0; f < 3; f++) {
+ FCurve *fcu = euf->fcurves[f];
+ BezTriple *bezt, *prev;
+ unsigned int i;
+
+ /* skip if not enough vets to do a decent analysis of... */
+ if (fcu->totvert <= 2)
+ continue;
+
+ /* prev follows bezt, bezt = "current" point to be fixed */
+ /* our method depends on determining a "difference" from the previous vert */
+ for (i = 1, prev = fcu->bezt, bezt = fcu->bezt + 1; i < fcu->totvert; i++, prev = bezt++) {
+ const float sign = (prev->vec[1][1] > bezt->vec[1][1]) ? 1.0f : -1.0f;
+
+ /* > 180 degree flip? */
+ if ((sign * (prev->vec[1][1] - bezt->vec[1][1])) >= (float)M_PI) {
+ /* 360 degrees to add/subtract frame value until difference
+ * is acceptably small that there's no more flip */
+ const float fac = sign * 2.0f * (float)M_PI;
+
+ while ((sign * (prev->vec[1][1] - bezt->vec[1][1])) >= (float)M_PI) {
+ bezt->vec[0][1] += fac;
+ bezt->vec[1][1] += fac;
+ bezt->vec[2][1] += fac;
+ }
+ }
+ }
+ }
+ }
+ BLI_freelistN(&eulers);
+
+ ANIM_animdata_update(&ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+
+ /* updates + finishing warnings */
+ if (failed == groups) {
+ BKE_report(
+ op->reports,
+ RPT_ERROR,
+ "No Euler Rotations could be corrected, ensure each rotation has keys for all components, "
+ "and that F-Curves for these are in consecutive XYZ order and selected");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ if (failed) {
+ BKE_report(
+ op->reports,
+ RPT_ERROR,
+ "Some Euler Rotations could not be corrected due to missing/unselected/out-of-order "
+ "F-Curves, "
+ "ensure each rotation has keys for all components, and that F-Curves for these are in "
+ "consecutive XYZ order and selected");
+ }
+
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+
+ /* done at last */
+ return OPERATOR_FINISHED;
+ }
}
void GRAPH_OT_euler_filter(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Euler Discontinuity Filter";
- ot->idname = "GRAPH_OT_euler_filter";
- ot->description = "Fix large jumps and flips in the selected "
- "Euler Rotation F-Curves arising from rotation "
- "values being clipped when baking physics";
+ /* identifiers */
+ ot->name = "Euler Discontinuity Filter";
+ ot->idname = "GRAPH_OT_euler_filter";
+ ot->description =
+ "Fix large jumps and flips in the selected "
+ "Euler Rotation F-Curves arising from rotation "
+ "values being clipped when baking physics";
- /* api callbacks */
- ot->exec = graphkeys_euler_filter_exec;
- ot->poll = graphop_editable_keyframes_poll;
+ /* api callbacks */
+ ot->exec = graphkeys_euler_filter_exec;
+ ot->poll = graphop_editable_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ***************** Jump to Selected Frames Operator *********************** */
static bool graphkeys_framejump_poll(bContext *C)
{
- /* prevent changes during render */
- if (G.is_rendering)
- return 0;
+ /* prevent changes during render */
+ if (G.is_rendering)
+ return 0;
- return graphop_visible_keyframes_poll(C);
+ return graphop_visible_keyframes_poll(C);
}
/* snap current-frame indicator to 'average time' of selected keyframe */
static int graphkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- KeyframeEditData ked;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* init edit data */
- memset(&ked, 0, sizeof(KeyframeEditData));
-
- /* loop over action data, averaging values */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
- short mapping_flag = ANIM_get_normalization_flags(&ac);
- KeyframeEditData current_ked;
- float offset;
- float unit_scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS, &offset);
-
- memset(&current_ked, 0, sizeof(current_ked));
-
- if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
- ANIM_fcurve_keyframes_loop(&current_ked, ale->key_data, NULL, bezt_calc_average, NULL);
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
- }
- else
- ANIM_fcurve_keyframes_loop(&current_ked, ale->key_data, NULL, bezt_calc_average, NULL);
-
- ked.f1 += current_ked.f1;
- ked.i1 += current_ked.i1;
- ked.f2 += (current_ked.f2 + offset) * unit_scale;
- ked.i2 += current_ked.i2;
- }
-
- ANIM_animdata_freelist(&anim_data);
-
- /* set the new current frame and cursor values, based on the average time and value */
- if (ked.i1) {
- SpaceGraph *sipo = (SpaceGraph *)ac.sl;
- Scene *scene = ac.scene;
-
- /* take the average values, rounding to the nearest int as necessary for int results */
- if (sipo->mode == SIPO_MODE_DRIVERS) {
- /* Drivers Mode - Affects cursor (float) */
- sipo->cursorTime = ked.f1 / (float)ked.i1;
- sipo->cursorVal = ked.f2 / (float)ked.i1;
- }
- else {
- /* Animation Mode - Affects current frame (int) */
- CFRA = round_fl_to_int(ked.f1 / ked.i1);
- SUBFRA = 0.f;
- sipo->cursorVal = ked.f2 / (float)ked.i1;
- }
- }
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ KeyframeEditData ked;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* init edit data */
+ memset(&ked, 0, sizeof(KeyframeEditData));
+
+ /* loop over action data, averaging values */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
+ short mapping_flag = ANIM_get_normalization_flags(&ac);
+ KeyframeEditData current_ked;
+ float offset;
+ float unit_scale = ANIM_unit_mapping_get_factor(
+ ac.scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS, &offset);
+
+ memset(&current_ked, 0, sizeof(current_ked));
+
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
+ ANIM_fcurve_keyframes_loop(&current_ked, ale->key_data, NULL, bezt_calc_average, NULL);
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
+ }
+ else
+ ANIM_fcurve_keyframes_loop(&current_ked, ale->key_data, NULL, bezt_calc_average, NULL);
+
+ ked.f1 += current_ked.f1;
+ ked.i1 += current_ked.i1;
+ ked.f2 += (current_ked.f2 + offset) * unit_scale;
+ ked.i2 += current_ked.i2;
+ }
+
+ ANIM_animdata_freelist(&anim_data);
+
+ /* set the new current frame and cursor values, based on the average time and value */
+ if (ked.i1) {
+ SpaceGraph *sipo = (SpaceGraph *)ac.sl;
+ Scene *scene = ac.scene;
+
+ /* take the average values, rounding to the nearest int as necessary for int results */
+ if (sipo->mode == SIPO_MODE_DRIVERS) {
+ /* Drivers Mode - Affects cursor (float) */
+ sipo->cursorTime = ked.f1 / (float)ked.i1;
+ sipo->cursorVal = ked.f2 / (float)ked.i1;
+ }
+ else {
+ /* Animation Mode - Affects current frame (int) */
+ CFRA = round_fl_to_int(ked.f1 / ked.i1);
+ SUBFRA = 0.f;
+ sipo->cursorVal = ked.f2 / (float)ked.i1;
+ }
+ }
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene);
+
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_frame_jump(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Jump to Keyframes";
- ot->idname = "GRAPH_OT_frame_jump";
- ot->description = "Place the cursor on the midpoint of selected keyframes";
+ /* identifiers */
+ ot->name = "Jump to Keyframes";
+ ot->idname = "GRAPH_OT_frame_jump";
+ ot->description = "Place the cursor on the midpoint of selected keyframes";
- /* api callbacks */
- ot->exec = graphkeys_framejump_exec;
- ot->poll = graphkeys_framejump_poll;
+ /* api callbacks */
+ ot->exec = graphkeys_framejump_exec;
+ ot->poll = graphkeys_framejump_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Snap Keyframes Operator *********************** */
/* defines for snap keyframes tool */
static const EnumPropertyItem prop_graphkeys_snap_types[] = {
- {GRAPHKEYS_SNAP_CFRA, "CFRA", 0, "Current Frame",
- "Snap selected keyframes to the current frame"},
- {GRAPHKEYS_SNAP_VALUE, "VALUE", 0, "Cursor Value",
- "Set values of selected keyframes to the cursor value (Y/Horizontal component)"},
- {GRAPHKEYS_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame",
- "Snap selected keyframes to the nearest (whole) frame (use to fix accidental sub-frame offsets)"},
- {GRAPHKEYS_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Nearest Second",
- "Snap selected keyframes to the nearest second"},
- {GRAPHKEYS_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker",
- "Snap selected keyframes to the nearest marker"},
- {GRAPHKEYS_SNAP_HORIZONTAL, "HORIZONTAL", 0, "Flatten Handles",
- "Flatten handles for a smoother transition"},
- {0, NULL, 0, NULL, NULL},
+ {GRAPHKEYS_SNAP_CFRA,
+ "CFRA",
+ 0,
+ "Current Frame",
+ "Snap selected keyframes to the current frame"},
+ {GRAPHKEYS_SNAP_VALUE,
+ "VALUE",
+ 0,
+ "Cursor Value",
+ "Set values of selected keyframes to the cursor value (Y/Horizontal component)"},
+ {GRAPHKEYS_SNAP_NEAREST_FRAME,
+ "NEAREST_FRAME",
+ 0,
+ "Nearest Frame",
+ "Snap selected keyframes to the nearest (whole) frame (use to fix accidental sub-frame "
+ "offsets)"},
+ {GRAPHKEYS_SNAP_NEAREST_SECOND,
+ "NEAREST_SECOND",
+ 0,
+ "Nearest Second",
+ "Snap selected keyframes to the nearest second"},
+ {GRAPHKEYS_SNAP_NEAREST_MARKER,
+ "NEAREST_MARKER",
+ 0,
+ "Nearest Marker",
+ "Snap selected keyframes to the nearest marker"},
+ {GRAPHKEYS_SNAP_HORIZONTAL,
+ "HORIZONTAL",
+ 0,
+ "Flatten Handles",
+ "Flatten handles for a smoother transition"},
+ {0, NULL, 0, NULL, NULL},
};
/* this function is responsible for snapping keyframes to frame-times */
static void snap_graph_keys(bAnimContext *ac, short mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- SpaceGraph *sipo = (SpaceGraph *)ac->sl;
- KeyframeEditData ked;
- KeyframeEditFunc edit_cb;
- float cursor_value = 0.0f;
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* init custom data for iterating over keyframes */
- memset(&ked, 0, sizeof(KeyframeEditData));
- ked.scene = ac->scene;
- if (mode == GRAPHKEYS_SNAP_NEAREST_MARKER) {
- ked.list.first = (ac->markers) ? ac->markers->first : NULL;
- ked.list.last = (ac->markers) ? ac->markers->last : NULL;
- }
- else if (mode == GRAPHKEYS_SNAP_VALUE) {
- cursor_value = (sipo) ? sipo->cursorVal : 0.0f;
- }
- else if (mode == GRAPHKEYS_SNAP_CFRA) {
- /* In drivers mode, use the cursor value instead
- * (We need to use a different callback for that though)
- */
- if (sipo->mode == SIPO_MODE_DRIVERS) {
- ked.f1 = sipo->cursorTime;
- mode = SNAP_KEYS_TIME;
- }
- }
-
- /* get beztriple editing callbacks */
- edit_cb = ANIM_editkeyframes_snap(mode);
-
- /* snap keyframes */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-
- /* normalise cursor value (for normalised F-Curves display) */
- if (mode == GRAPHKEYS_SNAP_VALUE) {
- short mapping_flag = ANIM_get_normalization_flags(ac);
- float offset;
- float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag, &offset);
-
- ked.f1 = (cursor_value / unit_scale) - offset;
- }
-
- /* perform snapping */
- if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
- }
- else
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
-
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ SpaceGraph *sipo = (SpaceGraph *)ac->sl;
+ KeyframeEditData ked;
+ KeyframeEditFunc edit_cb;
+ float cursor_value = 0.0f;
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* init custom data for iterating over keyframes */
+ memset(&ked, 0, sizeof(KeyframeEditData));
+ ked.scene = ac->scene;
+ if (mode == GRAPHKEYS_SNAP_NEAREST_MARKER) {
+ ked.list.first = (ac->markers) ? ac->markers->first : NULL;
+ ked.list.last = (ac->markers) ? ac->markers->last : NULL;
+ }
+ else if (mode == GRAPHKEYS_SNAP_VALUE) {
+ cursor_value = (sipo) ? sipo->cursorVal : 0.0f;
+ }
+ else if (mode == GRAPHKEYS_SNAP_CFRA) {
+ /* In drivers mode, use the cursor value instead
+ * (We need to use a different callback for that though)
+ */
+ if (sipo->mode == SIPO_MODE_DRIVERS) {
+ ked.f1 = sipo->cursorTime;
+ mode = SNAP_KEYS_TIME;
+ }
+ }
+
+ /* get beztriple editing callbacks */
+ edit_cb = ANIM_editkeyframes_snap(mode);
+
+ /* snap keyframes */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ /* normalise cursor value (for normalised F-Curves display) */
+ if (mode == GRAPHKEYS_SNAP_VALUE) {
+ short mapping_flag = ANIM_get_normalization_flags(ac);
+ float offset;
+ float unit_scale = ANIM_unit_mapping_get_factor(
+ ac->scene, ale->id, ale->key_data, mapping_flag, &offset);
+
+ ked.f1 = (cursor_value / unit_scale) - offset;
+ }
+
+ /* perform snapping */
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
+ }
+ else
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int graphkeys_snap_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- short mode;
+ bAnimContext ac;
+ short mode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* get snapping mode */
- mode = RNA_enum_get(op->ptr, "type");
+ /* get snapping mode */
+ mode = RNA_enum_get(op->ptr, "type");
- /* snap keyframes */
- snap_graph_keys(&ac, mode);
+ /* snap keyframes */
+ snap_graph_keys(&ac, mode);
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_snap(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Snap Keys";
- ot->idname = "GRAPH_OT_snap";
- ot->description = "Snap selected keyframes to the chosen times/values";
+ /* identifiers */
+ ot->name = "Snap Keys";
+ ot->idname = "GRAPH_OT_snap";
+ ot->description = "Snap selected keyframes to the chosen times/values";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = graphkeys_snap_exec;
- ot->poll = graphop_editable_keyframes_poll;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = graphkeys_snap_exec;
+ ot->poll = graphop_editable_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* id-props */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_snap_types, 0, "Type", "");
+ /* id-props */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_snap_types, 0, "Type", "");
}
/* ******************** Mirror Keyframes Operator *********************** */
/* defines for mirror keyframes tool */
static const EnumPropertyItem prop_graphkeys_mirror_types[] = {
- {GRAPHKEYS_MIRROR_CFRA, "CFRA", 0, "By Times over Current Frame",
- "Flip times of selected keyframes using the current frame as the mirror line"},
- {GRAPHKEYS_MIRROR_VALUE, "VALUE", 0, "By Values over Cursor Value",
- "Flip values of selected keyframes using the cursor value (Y/Horizontal component) as the mirror line"},
- {GRAPHKEYS_MIRROR_YAXIS, "YAXIS", 0, "By Times over Time=0",
- "Flip times of selected keyframes, effectively reversing the order they appear in"},
- {GRAPHKEYS_MIRROR_XAXIS, "XAXIS", 0, "By Values over Value=0",
- "Flip values of selected keyframes (i.e. negative values become positive, and vice versa)"},
- {GRAPHKEYS_MIRROR_MARKER, "MARKER", 0, "By Times over First Selected Marker",
- "Flip times of selected keyframes using the first selected marker as the reference point"},
- {0, NULL, 0, NULL, NULL},
+ {GRAPHKEYS_MIRROR_CFRA,
+ "CFRA",
+ 0,
+ "By Times over Current Frame",
+ "Flip times of selected keyframes using the current frame as the mirror line"},
+ {GRAPHKEYS_MIRROR_VALUE,
+ "VALUE",
+ 0,
+ "By Values over Cursor Value",
+ "Flip values of selected keyframes using the cursor value (Y/Horizontal component) as the "
+ "mirror line"},
+ {GRAPHKEYS_MIRROR_YAXIS,
+ "YAXIS",
+ 0,
+ "By Times over Time=0",
+ "Flip times of selected keyframes, effectively reversing the order they appear in"},
+ {GRAPHKEYS_MIRROR_XAXIS,
+ "XAXIS",
+ 0,
+ "By Values over Value=0",
+ "Flip values of selected keyframes (i.e. negative values become positive, and vice versa)"},
+ {GRAPHKEYS_MIRROR_MARKER,
+ "MARKER",
+ 0,
+ "By Times over First Selected Marker",
+ "Flip times of selected keyframes using the first selected marker as the reference point"},
+ {0, NULL, 0, NULL, NULL},
};
/* this function is responsible for mirroring keyframes */
static void mirror_graph_keys(bAnimContext *ac, short mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- SpaceGraph *sipo = (SpaceGraph *)ac->sl;
- KeyframeEditData ked;
- KeyframeEditFunc edit_cb;
- float cursor_value = 0.0f;
-
- /* init custom data for looping over keyframes */
- memset(&ked, 0, sizeof(KeyframeEditData));
- ked.scene = ac->scene;
-
- /* store mode-specific custom data... */
- if (mode == GRAPHKEYS_MIRROR_MARKER) {
- TimeMarker *marker = NULL;
-
- /* find first selected marker */
- marker = ED_markers_get_first_selected(ac->markers);
-
- /* store marker's time (if available) */
- if (marker)
- ked.f1 = (float)marker->frame;
- else
- return;
- }
- else if (mode == GRAPHKEYS_MIRROR_VALUE) {
- cursor_value = (sipo) ? sipo->cursorVal : 0.0f;
- }
- else if (mode == GRAPHKEYS_MIRROR_CFRA) {
- /* In drivers mode, use the cursor value instead
- * (We need to use a different callback for that though)
- */
- if (sipo->mode == SIPO_MODE_DRIVERS) {
- ked.f1 = sipo->cursorTime;
- mode = MIRROR_KEYS_TIME;
- }
- }
-
- /* get beztriple editing callbacks */
- edit_cb = ANIM_editkeyframes_mirror(mode);
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* mirror keyframes */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-
- /* apply unit corrections */
- if (mode == GRAPHKEYS_MIRROR_VALUE) {
- short mapping_flag = ANIM_get_normalization_flags(ac);
- float offset;
- float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS, &offset);
-
- ked.f1 = (cursor_value + offset) * unit_scale;
- }
-
- /* perform actual mirroring */
- if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
- }
- else
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
-
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ SpaceGraph *sipo = (SpaceGraph *)ac->sl;
+ KeyframeEditData ked;
+ KeyframeEditFunc edit_cb;
+ float cursor_value = 0.0f;
+
+ /* init custom data for looping over keyframes */
+ memset(&ked, 0, sizeof(KeyframeEditData));
+ ked.scene = ac->scene;
+
+ /* store mode-specific custom data... */
+ if (mode == GRAPHKEYS_MIRROR_MARKER) {
+ TimeMarker *marker = NULL;
+
+ /* find first selected marker */
+ marker = ED_markers_get_first_selected(ac->markers);
+
+ /* store marker's time (if available) */
+ if (marker)
+ ked.f1 = (float)marker->frame;
+ else
+ return;
+ }
+ else if (mode == GRAPHKEYS_MIRROR_VALUE) {
+ cursor_value = (sipo) ? sipo->cursorVal : 0.0f;
+ }
+ else if (mode == GRAPHKEYS_MIRROR_CFRA) {
+ /* In drivers mode, use the cursor value instead
+ * (We need to use a different callback for that though)
+ */
+ if (sipo->mode == SIPO_MODE_DRIVERS) {
+ ked.f1 = sipo->cursorTime;
+ mode = MIRROR_KEYS_TIME;
+ }
+ }
+
+ /* get beztriple editing callbacks */
+ edit_cb = ANIM_editkeyframes_mirror(mode);
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* mirror keyframes */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ /* apply unit corrections */
+ if (mode == GRAPHKEYS_MIRROR_VALUE) {
+ short mapping_flag = ANIM_get_normalization_flags(ac);
+ float offset;
+ float unit_scale = ANIM_unit_mapping_get_factor(
+ ac->scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS, &offset);
+
+ ked.f1 = (cursor_value + offset) * unit_scale;
+ }
+
+ /* perform actual mirroring */
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
+ }
+ else
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int graphkeys_mirror_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- short mode;
+ bAnimContext ac;
+ short mode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* get mirroring mode */
- mode = RNA_enum_get(op->ptr, "type");
+ /* get mirroring mode */
+ mode = RNA_enum_get(op->ptr, "type");
- /* mirror keyframes */
- mirror_graph_keys(&ac, mode);
+ /* mirror keyframes */
+ mirror_graph_keys(&ac, mode);
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_mirror(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Mirror Keys";
- ot->idname = "GRAPH_OT_mirror";
- ot->description = "Flip selected keyframes over the selected mirror line";
+ /* identifiers */
+ ot->name = "Mirror Keys";
+ ot->idname = "GRAPH_OT_mirror";
+ ot->description = "Flip selected keyframes over the selected mirror line";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = graphkeys_mirror_exec;
- ot->poll = graphop_editable_keyframes_poll;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = graphkeys_mirror_exec;
+ ot->poll = graphop_editable_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* id-props */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_mirror_types, 0, "Type", "");
+ /* id-props */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_mirror_types, 0, "Type", "");
}
/* ******************** Smooth Keyframes Operator *********************** */
static int graphkeys_smooth_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* smooth keyframes */
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* For now, we can only smooth by flattening handles AND smoothing curve values.
- * Perhaps the mode argument could be removed, as that functionality is offered through
- * Snap->Flatten Handles anyway.
- */
- smooth_fcurve(ale->key_data);
+ /* smooth keyframes */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* For now, we can only smooth by flattening handles AND smoothing curve values.
+ * Perhaps the mode argument could be removed, as that functionality is offered through
+ * Snap->Flatten Handles anyway.
+ */
+ smooth_fcurve(ale->key_data);
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
- ANIM_animdata_update(&ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ANIM_animdata_update(&ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_smooth(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Smooth Keys";
- ot->idname = "GRAPH_OT_smooth";
- ot->description = "Apply weighted moving means to make selected F-Curves less bumpy";
+ /* identifiers */
+ ot->name = "Smooth Keys";
+ ot->idname = "GRAPH_OT_smooth";
+ ot->description = "Apply weighted moving means to make selected F-Curves less bumpy";
- /* api callbacks */
- ot->exec = graphkeys_smooth_exec;
- ot->poll = graphop_editable_keyframes_poll;
+ /* api callbacks */
+ ot->exec = graphkeys_smooth_exec;
+ ot->poll = graphop_editable_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ************************************************************************** */
@@ -2392,246 +2623,258 @@ void GRAPH_OT_smooth(wmOperatorType *ot)
/* ******************** Add F-Modifier Operator *********************** */
-static const EnumPropertyItem *graph_fmodifier_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *graph_fmodifier_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- EnumPropertyItem *item = NULL;
- int totitem = 0;
- int i = 0;
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+ int i = 0;
- if (C == NULL) {
- return rna_enum_fmodifier_type_items;
- }
+ if (C == NULL) {
+ return rna_enum_fmodifier_type_items;
+ }
- /* start from 1 to skip the 'Invalid' modifier type */
- for (i = 1; i < FMODIFIER_NUM_TYPES; i++) {
- const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(i);
- int index;
+ /* start from 1 to skip the 'Invalid' modifier type */
+ for (i = 1; i < FMODIFIER_NUM_TYPES; i++) {
+ const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(i);
+ int index;
- /* check if modifier is valid for this context */
- if (fmi == NULL)
- continue;
+ /* check if modifier is valid for this context */
+ if (fmi == NULL)
+ continue;
- index = RNA_enum_from_value(rna_enum_fmodifier_type_items, fmi->type);
- if (index != -1) { /* Not all types are implemented yet... */
- RNA_enum_item_add(&item, &totitem, &rna_enum_fmodifier_type_items[index]);
- }
- }
+ index = RNA_enum_from_value(rna_enum_fmodifier_type_items, fmi->type);
+ if (index != -1) { /* Not all types are implemented yet... */
+ RNA_enum_item_add(&item, &totitem, &rna_enum_fmodifier_type_items[index]);
+ }
+ }
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
- return item;
+ return item;
}
static int graph_fmodifier_add_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- short type;
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ short type;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* get type of modifier to add */
- type = RNA_enum_get(op->ptr, "type");
+ /* get type of modifier to add */
+ type = RNA_enum_get(op->ptr, "type");
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- if (RNA_boolean_get(op->ptr, "only_active"))
- filter |= ANIMFILTER_ACTIVE; // FIXME: enforce in this case only a single channel to get handled?
- else
- filter |= (ANIMFILTER_SEL | ANIMFILTER_CURVE_VISIBLE);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+ if (RNA_boolean_get(op->ptr, "only_active"))
+ filter |=
+ ANIMFILTER_ACTIVE; // FIXME: enforce in this case only a single channel to get handled?
+ else
+ filter |= (ANIMFILTER_SEL | ANIMFILTER_CURVE_VISIBLE);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* add f-modifier to each curve */
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->data;
- FModifier *fcm;
+ /* add f-modifier to each curve */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->data;
+ FModifier *fcm;
- /* add F-Modifier of specified type to active F-Curve, and make it the active one */
- fcm = add_fmodifier(&fcu->modifiers, type, fcu);
- if (fcm) {
- set_active_fmodifier(&fcu->modifiers, fcm);
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Modifier could not be added (see console for details)");
- break;
- }
+ /* add F-Modifier of specified type to active F-Curve, and make it the active one */
+ fcm = add_fmodifier(&fcu->modifiers, type, fcu);
+ if (fcm) {
+ set_active_fmodifier(&fcu->modifiers, fcm);
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Modifier could not be added (see console for details)");
+ break;
+ }
- ale->update |= ANIM_UPDATE_DEPS;
- }
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
- ANIM_animdata_update(&ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ ANIM_animdata_update(&ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_fmodifier_add(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Add F-Curve Modifier";
- ot->idname = "GRAPH_OT_fmodifier_add";
- ot->description = "Add F-Modifier to the active/selected F-Curves";
+ /* identifiers */
+ ot->name = "Add F-Curve Modifier";
+ ot->idname = "GRAPH_OT_fmodifier_add";
+ ot->description = "Add F-Modifier to the active/selected F-Curves";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = graph_fmodifier_add_exec;
- ot->poll = graphop_selected_fcurve_poll;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = graph_fmodifier_add_exec;
+ ot->poll = graphop_selected_fcurve_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* id-props */
- prop = RNA_def_enum(ot->srna, "type", rna_enum_fmodifier_type_items, 0, "Type", "");
- RNA_def_enum_funcs(prop, graph_fmodifier_itemf);
- ot->prop = prop;
+ /* id-props */
+ prop = RNA_def_enum(ot->srna, "type", rna_enum_fmodifier_type_items, 0, "Type", "");
+ RNA_def_enum_funcs(prop, graph_fmodifier_itemf);
+ ot->prop = prop;
- RNA_def_boolean(ot->srna, "only_active", 1, "Only Active", "Only add F-Modifier to active F-Curve");
+ RNA_def_boolean(
+ ot->srna, "only_active", 1, "Only Active", "Only add F-Modifier to active F-Curve");
}
/* ******************** Copy F-Modifiers Operator *********************** */
static int graph_fmodifier_copy_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- bAnimListElem *ale;
- bool ok = false;
+ bAnimContext ac;
+ bAnimListElem *ale;
+ bool ok = false;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* clear buffer first */
- ANIM_fmodifiers_copybuf_free();
+ /* clear buffer first */
+ ANIM_fmodifiers_copybuf_free();
- /* get the active F-Curve */
- ale = get_active_fcurve_channel(&ac);
+ /* get the active F-Curve */
+ ale = get_active_fcurve_channel(&ac);
- /* if this exists, call the copy F-Modifiers API function */
- if (ale && ale->data) {
- FCurve *fcu = (FCurve *)ale->data;
+ /* if this exists, call the copy F-Modifiers API function */
+ if (ale && ale->data) {
+ FCurve *fcu = (FCurve *)ale->data;
- /* TODO: when 'active' vs 'all' boolean is added, change last param! */
- ok = ANIM_fmodifiers_copy_to_buf(&fcu->modifiers, 0);
+ /* TODO: when 'active' vs 'all' boolean is added, change last param! */
+ ok = ANIM_fmodifiers_copy_to_buf(&fcu->modifiers, 0);
- /* free temp data now */
- MEM_freeN(ale);
- }
+ /* free temp data now */
+ MEM_freeN(ale);
+ }
- /* successful or not? */
- if (ok == 0) {
- BKE_report(op->reports, RPT_ERROR, "No F-Modifiers available to be copied");
- return OPERATOR_CANCELLED;
- }
- else
- return OPERATOR_FINISHED;
+ /* successful or not? */
+ if (ok == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No F-Modifiers available to be copied");
+ return OPERATOR_CANCELLED;
+ }
+ else
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_fmodifier_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy F-Modifiers";
- ot->idname = "GRAPH_OT_fmodifier_copy";
- ot->description = "Copy the F-Modifier(s) of the active F-Curve";
+ /* identifiers */
+ ot->name = "Copy F-Modifiers";
+ ot->idname = "GRAPH_OT_fmodifier_copy";
+ ot->description = "Copy the F-Modifier(s) of the active F-Curve";
- /* api callbacks */
- ot->exec = graph_fmodifier_copy_exec;
- ot->poll = graphop_active_fcurve_poll;
+ /* api callbacks */
+ ot->exec = graph_fmodifier_copy_exec;
+ ot->poll = graphop_active_fcurve_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* id-props */
- //ot->prop = RNA_def_boolean(ot->srna, "all", 1, "All F-Modifiers", "Copy all the F-Modifiers, instead of just the active one");
+ /* id-props */
+ //ot->prop = RNA_def_boolean(ot->srna, "all", 1, "All F-Modifiers", "Copy all the F-Modifiers, instead of just the active one");
}
/* ******************** Paste F-Modifiers Operator *********************** */
static int graph_fmodifier_paste_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
+ bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- const bool replace = RNA_boolean_get(op->ptr, "replace");
- bool ok = false;
+ const bool replace = RNA_boolean_get(op->ptr, "replace");
+ bool ok = false;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* filter data */
- if (RNA_boolean_get(op->ptr, "only_active")) {
- /* This should be the default (for buttons) - Just paste to the active FCurve */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- }
- else {
- /* This is only if the operator gets called from a hotkey or search - Paste to all visible curves */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- }
+ /* filter data */
+ if (RNA_boolean_get(op->ptr, "only_active")) {
+ /* This should be the default (for buttons) - Just paste to the active FCurve */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_NODUPLIS);
+ }
+ else {
+ /* This is only if the operator gets called from a hotkey or search - Paste to all visible curves */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL |
+ ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+ }
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* paste modifiers */
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->data;
- int tot;
+ /* paste modifiers */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->data;
+ int tot;
- tot = ANIM_fmodifiers_paste_from_buf(&fcu->modifiers, replace, fcu);
+ tot = ANIM_fmodifiers_paste_from_buf(&fcu->modifiers, replace, fcu);
- if (tot) {
- ale->update |= ANIM_UPDATE_DEPS;
- ok = true;
- }
- }
+ if (tot) {
+ ale->update |= ANIM_UPDATE_DEPS;
+ ok = true;
+ }
+ }
- if (ok) {
- ANIM_animdata_update(&ac, &anim_data);
- }
- ANIM_animdata_freelist(&anim_data);
+ if (ok) {
+ ANIM_animdata_update(&ac, &anim_data);
+ }
+ ANIM_animdata_freelist(&anim_data);
- /* successful or not? */
- if (ok) {
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ /* successful or not? */
+ if (ok) {
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "No F-Modifiers to paste");
- return OPERATOR_CANCELLED;
- }
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No F-Modifiers to paste");
+ return OPERATOR_CANCELLED;
+ }
}
void GRAPH_OT_fmodifier_paste(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Paste F-Modifiers";
- ot->idname = "GRAPH_OT_fmodifier_paste";
- ot->description = "Add copied F-Modifiers to the selected F-Curves";
+ /* identifiers */
+ ot->name = "Paste F-Modifiers";
+ ot->idname = "GRAPH_OT_fmodifier_paste";
+ ot->description = "Add copied F-Modifiers to the selected F-Curves";
- /* api callbacks */
- ot->exec = graph_fmodifier_paste_exec;
- ot->poll = graphop_active_fcurve_poll;
+ /* api callbacks */
+ ot->exec = graph_fmodifier_paste_exec;
+ ot->poll = graphop_active_fcurve_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "only_active", true, "Only Active", "Only paste F-Modifiers on active F-Curve");
- RNA_def_boolean(ot->srna, "replace", false, "Replace Existing",
- "Replace existing F-Modifiers, instead of just appending to the end of the existing list");
+ /* properties */
+ RNA_def_boolean(
+ ot->srna, "only_active", true, "Only Active", "Only paste F-Modifiers on active F-Curve");
+ RNA_def_boolean(
+ ot->srna,
+ "replace",
+ false,
+ "Replace Existing",
+ "Replace existing F-Modifiers, instead of just appending to the end of the existing list");
}
/* ************************************************************************** */
@@ -2641,200 +2884,204 @@ void GRAPH_OT_fmodifier_paste(wmOperatorType *ot)
static int graph_driver_vars_copy_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- bAnimListElem *ale;
- bool ok = false;
+ bAnimContext ac;
+ bAnimListElem *ale;
+ bool ok = false;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* clear buffer first */
- ANIM_driver_vars_copybuf_free();
+ /* clear buffer first */
+ ANIM_driver_vars_copybuf_free();
- /* get the active F-Curve */
- ale = get_active_fcurve_channel(&ac);
+ /* get the active F-Curve */
+ ale = get_active_fcurve_channel(&ac);
- /* if this exists, call the copy driver vars API function */
- if (ale && ale->data) {
- FCurve *fcu = (FCurve *)ale->data;
+ /* if this exists, call the copy driver vars API function */
+ if (ale && ale->data) {
+ FCurve *fcu = (FCurve *)ale->data;
- ok = ANIM_driver_vars_copy(op->reports, fcu);
+ ok = ANIM_driver_vars_copy(op->reports, fcu);
- /* free temp data now */
- MEM_freeN(ale);
- }
+ /* free temp data now */
+ MEM_freeN(ale);
+ }
- /* successful or not? */
- if (ok)
- return OPERATOR_FINISHED;
- else
- return OPERATOR_CANCELLED;
+ /* successful or not? */
+ if (ok)
+ return OPERATOR_FINISHED;
+ else
+ return OPERATOR_CANCELLED;
}
void GRAPH_OT_driver_variables_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Driver Variables";
- ot->idname = "GRAPH_OT_driver_variables_copy";
- ot->description = "Copy the driver variables of the active F-Curve";
+ /* identifiers */
+ ot->name = "Copy Driver Variables";
+ ot->idname = "GRAPH_OT_driver_variables_copy";
+ ot->description = "Copy the driver variables of the active F-Curve";
- /* api callbacks */
- ot->exec = graph_driver_vars_copy_exec;
- ot->poll = graphop_active_fcurve_poll;
+ /* api callbacks */
+ ot->exec = graph_driver_vars_copy_exec;
+ ot->poll = graphop_active_fcurve_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Paste Driver Vars Operator *********************** */
static int graph_driver_vars_paste_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
+ bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- const bool replace = RNA_boolean_get(op->ptr, "replace");
- bool ok = false;
+ const bool replace = RNA_boolean_get(op->ptr, "replace");
+ bool ok = false;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* paste variables */
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->data;
- ok |= ANIM_driver_vars_paste(op->reports, fcu, replace);
- }
+ /* paste variables */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->data;
+ ok |= ANIM_driver_vars_paste(op->reports, fcu, replace);
+ }
- /* cleanup */
- ANIM_animdata_freelist(&anim_data);
+ /* cleanup */
+ ANIM_animdata_freelist(&anim_data);
- /* successful or not? */
- if (ok) {
- /* rebuild depsgraph, now that there are extra deps here */
- DEG_relations_tag_update(CTX_data_main(C));
+ /* successful or not? */
+ if (ok) {
+ /* rebuild depsgraph, now that there are extra deps here */
+ DEG_relations_tag_update(CTX_data_main(C));
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, CTX_data_scene(C));
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, CTX_data_scene(C));
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void GRAPH_OT_driver_variables_paste(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Paste Driver Variables";
- ot->idname = "GRAPH_OT_driver_variables_paste";
- ot->description = "Add copied driver variables to the active driver";
+ /* identifiers */
+ ot->name = "Paste Driver Variables";
+ ot->idname = "GRAPH_OT_driver_variables_paste";
+ ot->description = "Add copied driver variables to the active driver";
- /* api callbacks */
- ot->exec = graph_driver_vars_paste_exec;
- ot->poll = graphop_active_fcurve_poll;
+ /* api callbacks */
+ ot->exec = graph_driver_vars_paste_exec;
+ ot->poll = graphop_active_fcurve_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "replace", false, "Replace Existing",
- "Replace existing driver variables, instead of just appending to the end of the existing list");
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "replace",
+ false,
+ "Replace Existing",
+ "Replace existing driver variables, instead of just appending to the end of the "
+ "existing list");
}
/* ************************************************************************** */
static int graph_driver_delete_invalid_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- bool ok = false;
- unsigned int deleted = 0;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* NOTE: we might need a scene update to evaluate the driver flags */
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* find invalid drivers */
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->data;
- if (ELEM(NULL, fcu, fcu->driver)) {
- continue;
- }
- if (!(fcu->driver->flag & DRIVER_FLAG_INVALID)) {
- continue;
- }
-
- ok |= ANIM_remove_driver(op->reports, ale->id, fcu->rna_path, fcu->array_index, 0);
- if (!ok) {
- break;
- }
- deleted += 1;
- }
-
- /* cleanup */
- ANIM_animdata_freelist(&anim_data);
-
- if (deleted > 0) {
- /* notify the world of any changes */
- DEG_relations_tag_update(CTX_data_main(C));
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
- WM_reportf(RPT_INFO, "Deleted %u drivers", deleted);
- }
- else {
- WM_report(RPT_INFO, "No drivers deleted");
- }
-
- /* successful or not? */
- if (!ok) {
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ bool ok = false;
+ unsigned int deleted = 0;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* NOTE: we might need a scene update to evaluate the driver flags */
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* find invalid drivers */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->data;
+ if (ELEM(NULL, fcu, fcu->driver)) {
+ continue;
+ }
+ if (!(fcu->driver->flag & DRIVER_FLAG_INVALID)) {
+ continue;
+ }
+
+ ok |= ANIM_remove_driver(op->reports, ale->id, fcu->rna_path, fcu->array_index, 0);
+ if (!ok) {
+ break;
+ }
+ deleted += 1;
+ }
+
+ /* cleanup */
+ ANIM_animdata_freelist(&anim_data);
+
+ if (deleted > 0) {
+ /* notify the world of any changes */
+ DEG_relations_tag_update(CTX_data_main(C));
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
+ WM_reportf(RPT_INFO, "Deleted %u drivers", deleted);
+ }
+ else {
+ WM_report(RPT_INFO, "No drivers deleted");
+ }
+
+ /* successful or not? */
+ if (!ok) {
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
static bool graph_driver_delete_invalid_poll(bContext *C)
{
- bAnimContext ac;
- ScrArea *sa = CTX_wm_area(C);
+ bAnimContext ac;
+ ScrArea *sa = CTX_wm_area(C);
- /* firstly, check if in Graph Editor */
- if ((sa == NULL) || (sa->spacetype != SPACE_GRAPH))
- return 0;
+ /* firstly, check if in Graph Editor */
+ if ((sa == NULL) || (sa->spacetype != SPACE_GRAPH))
+ return 0;
- /* try to init Anim-Context stuff ourselves and check */
- return ANIM_animdata_get_context(C, &ac) != 0;
+ /* try to init Anim-Context stuff ourselves and check */
+ return ANIM_animdata_get_context(C, &ac) != 0;
}
-
void GRAPH_OT_driver_delete_invalid(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Invalid Drivers";
- ot->idname = "GRAPH_OT_driver_delete_invalid";
- ot->description = "Delete all visible drivers considered invalid";
+ /* identifiers */
+ ot->name = "Delete Invalid Drivers";
+ ot->idname = "GRAPH_OT_driver_delete_invalid";
+ ot->description = "Delete all visible drivers considered invalid";
- /* api callbacks */
- ot->exec = graph_driver_delete_invalid_exec;
- ot->poll = graph_driver_delete_invalid_poll;
+ /* api callbacks */
+ ot->exec = graph_driver_delete_invalid_exec;
+ ot->poll = graph_driver_delete_invalid_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h
index 617233f2a20..7d0a3a1f13d 100644
--- a/source/blender/editors/space_graph/graph_intern.h
+++ b/source/blender/editors/space_graph/graph_intern.h
@@ -43,7 +43,11 @@ struct ARegion *graph_has_buttons_region(struct ScrArea *sa);
/* graph_draw.c */
void graph_draw_channel_names(struct bContext *C, struct bAnimContext *ac, struct ARegion *ar);
-void graph_draw_curves(struct bAnimContext *ac, struct SpaceGraph *sipo, struct ARegion *ar, struct View2DGrid *grid, short sel);
+void graph_draw_curves(struct bAnimContext *ac,
+ struct SpaceGraph *sipo,
+ struct ARegion *ar,
+ struct View2DGrid *grid,
+ short sel);
void graph_draw_ghost_curves(struct bAnimContext *ac, struct SpaceGraph *sipo, struct ARegion *ar);
/* ***************************************** */
@@ -64,24 +68,29 @@ void GRAPH_OT_clickselect(struct wmOperatorType *ot);
/* defines for left-right select tool */
enum eGraphKeys_LeftRightSelect_Mode {
- GRAPHKEYS_LRSEL_TEST = 0,
- GRAPHKEYS_LRSEL_LEFT,
- GRAPHKEYS_LRSEL_RIGHT,
+ GRAPHKEYS_LRSEL_TEST = 0,
+ GRAPHKEYS_LRSEL_LEFT,
+ GRAPHKEYS_LRSEL_RIGHT,
};
/* defines for column-select mode */
enum eGraphKeys_ColumnSelect_Mode {
- GRAPHKEYS_COLUMNSEL_KEYS = 0,
- GRAPHKEYS_COLUMNSEL_CFRA,
- GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN,
- GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN,
+ GRAPHKEYS_COLUMNSEL_KEYS = 0,
+ GRAPHKEYS_COLUMNSEL_CFRA,
+ GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN,
+ GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN,
};
/* ***************************************** */
/* graph_edit.c */
-void get_graph_keyframe_extents(struct bAnimContext *ac, float *xmin, float *xmax, float *ymin, float *ymax,
- const bool do_selected, const bool include_handles);
+void get_graph_keyframe_extents(struct bAnimContext *ac,
+ float *xmin,
+ float *xmax,
+ float *ymin,
+ float *ymax,
+ const bool do_selected,
+ const bool include_handles);
void GRAPH_OT_previewrange_set(struct wmOperatorType *ot);
void GRAPH_OT_view_all(struct wmOperatorType *ot);
@@ -116,23 +125,23 @@ void GRAPH_OT_mirror(struct wmOperatorType *ot);
* NOTE: keep in sync with eEditKeyframes_Snap (in ED_keyframes_edit.h)
*/
enum eGraphKeys_Snap_Mode {
- GRAPHKEYS_SNAP_CFRA = 1,
- GRAPHKEYS_SNAP_NEAREST_FRAME,
- GRAPHKEYS_SNAP_NEAREST_SECOND,
- GRAPHKEYS_SNAP_NEAREST_MARKER,
- GRAPHKEYS_SNAP_HORIZONTAL,
- GRAPHKEYS_SNAP_VALUE,
+ GRAPHKEYS_SNAP_CFRA = 1,
+ GRAPHKEYS_SNAP_NEAREST_FRAME,
+ GRAPHKEYS_SNAP_NEAREST_SECOND,
+ GRAPHKEYS_SNAP_NEAREST_MARKER,
+ GRAPHKEYS_SNAP_HORIZONTAL,
+ GRAPHKEYS_SNAP_VALUE,
};
/* defines for mirror keyframes
* NOTE: keep in sync with eEditKeyframes_Mirror (in ED_keyframes_edit.h)
*/
enum eGraphKeys_Mirror_Mode {
- GRAPHKEYS_MIRROR_CFRA = 1,
- GRAPHKEYS_MIRROR_YAXIS,
- GRAPHKEYS_MIRROR_XAXIS,
- GRAPHKEYS_MIRROR_MARKER,
- GRAPHKEYS_MIRROR_VALUE,
+ GRAPHKEYS_MIRROR_CFRA = 1,
+ GRAPHKEYS_MIRROR_YAXIS,
+ GRAPHKEYS_MIRROR_XAXIS,
+ GRAPHKEYS_MIRROR_MARKER,
+ GRAPHKEYS_MIRROR_VALUE,
};
/* ----------- */
@@ -173,5 +182,4 @@ bool graphop_selected_fcurve_poll(struct bContext *C);
void graphedit_keymap(struct wmKeyConfig *keyconf);
void graphedit_operatortypes(void);
-
#endif /* __GRAPH_INTERN_H__ */
diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c
index 1c9bbbcdae5..6bbc6a2de1c 100644
--- a/source/blender/editors/space_graph/graph_ops.c
+++ b/source/blender/editors/space_graph/graph_ops.c
@@ -21,7 +21,6 @@
* \ingroup spgraph
*/
-
#include <stdlib.h>
#include <math.h>
@@ -64,55 +63,55 @@
static bool graphview_cursor_poll(bContext *C)
{
- /* prevent changes during render */
- if (G.is_rendering)
- return 0;
+ /* prevent changes during render */
+ if (G.is_rendering)
+ return 0;
- return ED_operator_graphedit_active(C);
+ return ED_operator_graphedit_active(C);
}
/* Set the new frame number */
static void graphview_cursor_apply(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- SpaceGraph *sipo = CTX_wm_space_graph(C);
- /* this isn't technically "frame", but it'll do... */
- float frame = RNA_float_get(op->ptr, "frame");
-
- /* adjust the frame or the cursor x-value */
- if (sipo->mode == SIPO_MODE_DRIVERS) {
- /* adjust cursor x-value */
- sipo->cursorTime = frame;
- }
- else {
- /* adjust the frame
- * NOTE: sync this part of the code with ANIM_OT_change_frame
- */
- /* 1) frame is rounded to the nearest int, since frames are ints */
- CFRA = round_fl_to_int(frame);
-
- if (scene->r.flag & SCER_LOCK_FRAME_SELECTION) {
- /* Clip to preview range
- * NOTE: Preview range won't go into negative values,
- * so only clamping once should be fine.
- */
- CLAMP(CFRA, PSFRA, PEFRA);
- }
- else {
- /* Prevent negative frames */
- FRAMENUMBER_MIN_CLAMP(CFRA);
- }
-
- SUBFRA = 0.0f;
- BKE_sound_seek_scene(bmain, scene);
- }
-
- /* set the cursor value */
- sipo->cursorVal = RNA_float_get(op->ptr, "value");
-
- /* send notifiers - notifiers for frame should force an update for both vars ok... */
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ SpaceGraph *sipo = CTX_wm_space_graph(C);
+ /* this isn't technically "frame", but it'll do... */
+ float frame = RNA_float_get(op->ptr, "frame");
+
+ /* adjust the frame or the cursor x-value */
+ if (sipo->mode == SIPO_MODE_DRIVERS) {
+ /* adjust cursor x-value */
+ sipo->cursorTime = frame;
+ }
+ else {
+ /* adjust the frame
+ * NOTE: sync this part of the code with ANIM_OT_change_frame
+ */
+ /* 1) frame is rounded to the nearest int, since frames are ints */
+ CFRA = round_fl_to_int(frame);
+
+ if (scene->r.flag & SCER_LOCK_FRAME_SELECTION) {
+ /* Clip to preview range
+ * NOTE: Preview range won't go into negative values,
+ * so only clamping once should be fine.
+ */
+ CLAMP(CFRA, PSFRA, PEFRA);
+ }
+ else {
+ /* Prevent negative frames */
+ FRAMENUMBER_MIN_CLAMP(CFRA);
+ }
+
+ SUBFRA = 0.0f;
+ BKE_sound_seek_scene(bmain, scene);
+ }
+
+ /* set the cursor value */
+ sipo->cursorVal = RNA_float_get(op->ptr, "value");
+
+ /* send notifiers - notifiers for frame should force an update for both vars ok... */
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
/* ... */
@@ -120,8 +119,8 @@ static void graphview_cursor_apply(bContext *C, wmOperator *op)
/* Non-modal callback for running operator without user input */
static int graphview_cursor_exec(bContext *C, wmOperator *op)
{
- graphview_cursor_apply(C, op);
- return OPERATOR_FINISHED;
+ graphview_cursor_apply(C, op);
+ return OPERATOR_FINISHED;
}
/* ... */
@@ -129,374 +128,377 @@ 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);
- float viewx, viewy;
+ ARegion *ar = CTX_wm_region(C);
+ float viewx, viewy;
- /* abort if not active region (should not really be possible) */
- if (ar == NULL)
- return;
+ /* abort if not active region (should not really be possible) */
+ if (ar == 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);
+ /* convert from region coordinates to View2D 'tot' space */
+ UI_view2d_region_to_view(&ar->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 */
- RNA_float_set(op->ptr, "frame", viewx);
- RNA_float_set(op->ptr, "value", viewy);
+ /* store the values in the operator properties */
+ /* NOTE: we don't clamp frame here, as it might be used for the drivers cursor */
+ RNA_float_set(op->ptr, "frame", viewx);
+ RNA_float_set(op->ptr, "value", viewy);
}
/* Modal Operator init */
static int graphview_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bScreen *screen = CTX_wm_screen(C);
-
- /* Change to frame that mouse is over before adding modal handler,
- * as user could click on a single frame (jump to frame) as well as
- * click-dragging over a range (modal scrubbing). Apply this change.
- */
- graphview_cursor_setprops(C, op, event);
- graphview_cursor_apply(C, op);
-
- /* Signal that a scrubbing operating is starting */
- if (screen)
- screen->scrubbing = true;
-
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ bScreen *screen = CTX_wm_screen(C);
+
+ /* Change to frame that mouse is over before adding modal handler,
+ * as user could click on a single frame (jump to frame) as well as
+ * click-dragging over a range (modal scrubbing). Apply this change.
+ */
+ graphview_cursor_setprops(C, op, event);
+ graphview_cursor_apply(C, op);
+
+ /* Signal that a scrubbing operating is starting */
+ if (screen)
+ screen->scrubbing = true;
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
}
/* Modal event handling of cursor changing */
static int graphview_cursor_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- bScreen *screen = CTX_wm_screen(C);
- Scene *scene = CTX_data_scene(C);
-
- /* execute the events */
- switch (event->type) {
- case ESCKEY:
- if (screen)
- screen->scrubbing = false;
-
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
- return OPERATOR_FINISHED;
-
- case MOUSEMOVE:
- /* set the new values */
- graphview_cursor_setprops(C, op, event);
- graphview_cursor_apply(C, op);
- break;
-
- case LEFTMOUSE:
- case RIGHTMOUSE:
- case MIDDLEMOUSE:
- /* We check for either mouse-button to end, to work with all user keymaps. */
- if (event->val == KM_RELEASE) {
- if (screen)
- screen->scrubbing = false;
-
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
- return OPERATOR_FINISHED;
- }
- break;
- }
-
- return OPERATOR_RUNNING_MODAL;
+ bScreen *screen = CTX_wm_screen(C);
+ Scene *scene = CTX_data_scene(C);
+
+ /* execute the events */
+ switch (event->type) {
+ case ESCKEY:
+ if (screen)
+ screen->scrubbing = false;
+
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ return OPERATOR_FINISHED;
+
+ case MOUSEMOVE:
+ /* set the new values */
+ graphview_cursor_setprops(C, op, event);
+ graphview_cursor_apply(C, op);
+ break;
+
+ case LEFTMOUSE:
+ case RIGHTMOUSE:
+ case MIDDLEMOUSE:
+ /* We check for either mouse-button to end, to work with all user keymaps. */
+ if (event->val == KM_RELEASE) {
+ if (screen)
+ screen->scrubbing = false;
+
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ return OPERATOR_FINISHED;
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
static void GRAPH_OT_cursor_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Cursor";
- ot->idname = "GRAPH_OT_cursor_set";
- ot->description = "Interactively set the current frame and value cursor";
-
- /* api callbacks */
- ot->exec = graphview_cursor_exec;
- ot->invoke = graphview_cursor_invoke;
- ot->modal = graphview_cursor_modal;
- ot->poll = graphview_cursor_poll;
-
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO;
-
- /* rna */
- RNA_def_float(ot->srna, "frame", 0, MINAFRAMEF, MAXFRAMEF, "Frame", "", MINAFRAMEF, MAXFRAMEF);
- RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Value", "", -100.0f, 100.0f);
+ /* identifiers */
+ ot->name = "Set Cursor";
+ ot->idname = "GRAPH_OT_cursor_set";
+ ot->description = "Interactively set the current frame and value cursor";
+
+ /* api callbacks */
+ ot->exec = graphview_cursor_exec;
+ ot->invoke = graphview_cursor_invoke;
+ ot->modal = graphview_cursor_modal;
+ ot->poll = graphview_cursor_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO;
+
+ /* rna */
+ RNA_def_float(ot->srna, "frame", 0, MINAFRAMEF, MAXFRAMEF, "Frame", "", MINAFRAMEF, MAXFRAMEF);
+ RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Value", "", -100.0f, 100.0f);
}
/* Hide/Reveal ------------------------------------------------------------ */
static int graphview_curves_hide_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- ListBase all_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- const bool unselected = RNA_boolean_get(op->ptr, "unselected");
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get list of all channels that selection may need to be flushed to
- * - hierarchy must not affect what we have access to here...
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
-
- /* filter data
- * - of the remaining visible curves, we want to hide the ones that are
- * selected/unselected (depending on "unselected" prop)
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- if (unselected)
- filter |= ANIMFILTER_UNSEL;
- else
- filter |= ANIMFILTER_SEL;
-
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* hack: skip object channels for now, since flushing those will always flush everything,
- * but they are always included */
- /* TODO: find out why this is the case, and fix that */
- if (ale->type == ANIMTYPE_OBJECT)
- continue;
-
- /* change the hide setting, and unselect it... */
- ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR);
- ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_CLEAR);
-
- /* now, also flush selection status up/down as appropriate */
- ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR);
- }
-
- /* cleanup */
- ANIM_animdata_freelist(&anim_data);
- BLI_freelistN(&all_data);
-
- /* unhide selected */
- if (unselected) {
- /* turn off requirement for visible */
- filter = ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_LIST_CHANNELS;
-
- /* flushing has been done */
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* hack: skip object channels for now, since flushing those
- * will always flush everything, but they are always included */
-
- /* TODO: find out why this is the case, and fix that */
- if (ale->type == ANIMTYPE_OBJECT)
- continue;
-
- /* change the hide setting, and unselect it... */
- ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
- ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_ADD);
-
- /* now, also flush selection status up/down as appropriate */
- ANIM_flush_setting_anim_channels(&ac, &anim_data, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
- }
- ANIM_animdata_freelist(&anim_data);
- }
-
-
- /* send notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ ListBase all_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ const bool unselected = RNA_boolean_get(op->ptr, "unselected");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get list of all channels that selection may need to be flushed to
+ * - hierarchy must not affect what we have access to here...
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
+
+ /* filter data
+ * - of the remaining visible curves, we want to hide the ones that are
+ * selected/unselected (depending on "unselected" prop)
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+ if (unselected)
+ filter |= ANIMFILTER_UNSEL;
+ else
+ filter |= ANIMFILTER_SEL;
+
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* hack: skip object channels for now, since flushing those will always flush everything,
+ * but they are always included */
+ /* TODO: find out why this is the case, and fix that */
+ if (ale->type == ANIMTYPE_OBJECT)
+ continue;
+
+ /* change the hide setting, and unselect it... */
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR);
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_CLEAR);
+
+ /* now, also flush selection status up/down as appropriate */
+ ANIM_flush_setting_anim_channels(
+ &ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR);
+ }
+
+ /* cleanup */
+ ANIM_animdata_freelist(&anim_data);
+ BLI_freelistN(&all_data);
+
+ /* unhide selected */
+ if (unselected) {
+ /* turn off requirement for visible */
+ filter = ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_LIST_CHANNELS;
+
+ /* flushing has been done */
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* hack: skip object channels for now, since flushing those
+ * will always flush everything, but they are always included */
+
+ /* TODO: find out why this is the case, and fix that */
+ if (ale->type == ANIMTYPE_OBJECT)
+ continue;
+
+ /* change the hide setting, and unselect it... */
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_ADD);
+
+ /* now, also flush selection status up/down as appropriate */
+ ANIM_flush_setting_anim_channels(
+ &ac, &anim_data, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
+ }
+ ANIM_animdata_freelist(&anim_data);
+ }
+
+ /* send notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
}
static void GRAPH_OT_hide(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Curves";
- ot->idname = "GRAPH_OT_hide";
- ot->description = "Hide selected curves from Graph Editor view";
+ /* identifiers */
+ ot->name = "Hide Curves";
+ ot->idname = "GRAPH_OT_hide";
+ ot->description = "Hide selected curves from Graph Editor view";
- /* api callbacks */
- ot->exec = graphview_curves_hide_exec;
- ot->poll = ED_operator_graphedit_active;
+ /* api callbacks */
+ ot->exec = graphview_curves_hide_exec;
+ ot->poll = ED_operator_graphedit_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected curves");
+ /* props */
+ RNA_def_boolean(
+ ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected curves");
}
/* ........ */
static int graphview_curves_reveal_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- ListBase all_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- const bool select = RNA_boolean_get(op->ptr, "select");
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get list of all channels that selection may need to be flushed to
- * - hierarchy must not affect what we have access to here...
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
-
- /* filter data
- * - just go through all visible channels, ensuring that everything is set to be curve-visible
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* hack: skip object channels for now, since flushing those will always flush everything,
- * but they are always included. */
- /* TODO: find out why this is the case, and fix that */
- if (ale->type == ANIMTYPE_OBJECT)
- continue;
-
- /* select if it is not visible */
- if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE) == 0) {
- ANIM_channel_setting_set(
- &ac, ale, ACHANNEL_SETTING_SELECT,
- select ? ACHANNEL_SETFLAG_ADD : ACHANNEL_SETFLAG_CLEAR);
- }
-
- /* change the visibility setting */
- ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
-
- /* now, also flush selection status up/down as appropriate */
- ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, true);
- }
-
- /* cleanup */
- ANIM_animdata_freelist(&anim_data);
- BLI_freelistN(&all_data);
-
- /* send notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ ListBase all_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ const bool select = RNA_boolean_get(op->ptr, "select");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get list of all channels that selection may need to be flushed to
+ * - hierarchy must not affect what we have access to here...
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
+
+ /* filter data
+ * - just go through all visible channels, ensuring that everything is set to be curve-visible
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* hack: skip object channels for now, since flushing those will always flush everything,
+ * but they are always included. */
+ /* TODO: find out why this is the case, and fix that */
+ if (ale->type == ANIMTYPE_OBJECT)
+ continue;
+
+ /* select if it is not visible */
+ if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE) == 0) {
+ ANIM_channel_setting_set(&ac,
+ ale,
+ ACHANNEL_SETTING_SELECT,
+ select ? ACHANNEL_SETFLAG_ADD : ACHANNEL_SETFLAG_CLEAR);
+ }
+
+ /* change the visibility setting */
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
+
+ /* now, also flush selection status up/down as appropriate */
+ ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, true);
+ }
+
+ /* cleanup */
+ ANIM_animdata_freelist(&anim_data);
+ BLI_freelistN(&all_data);
+
+ /* send notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
}
static void GRAPH_OT_reveal(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reveal Curves";
- ot->idname = "GRAPH_OT_reveal";
- ot->description = "Make previously hidden curves visible again in Graph Editor view";
+ /* identifiers */
+ ot->name = "Reveal Curves";
+ ot->idname = "GRAPH_OT_reveal";
+ ot->description = "Make previously hidden curves visible again in Graph Editor view";
- /* api callbacks */
- ot->exec = graphview_curves_reveal_exec;
- ot->poll = ED_operator_graphedit_active;
+ /* api callbacks */
+ ot->exec = graphview_curves_reveal_exec;
+ ot->poll = ED_operator_graphedit_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "select", true, "Select", "");
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
/* ************************** registration - operator types **********************************/
void graphedit_operatortypes(void)
{
- /* view */
- WM_operatortype_append(GRAPH_OT_cursor_set);
-
- WM_operatortype_append(GRAPH_OT_previewrange_set);
- WM_operatortype_append(GRAPH_OT_view_all);
- WM_operatortype_append(GRAPH_OT_view_selected);
- WM_operatortype_append(GRAPH_OT_properties);
- WM_operatortype_append(GRAPH_OT_view_frame);
-
- WM_operatortype_append(GRAPH_OT_ghost_curves_create);
- WM_operatortype_append(GRAPH_OT_ghost_curves_clear);
-
- WM_operatortype_append(GRAPH_OT_hide);
- WM_operatortype_append(GRAPH_OT_reveal);
-
- /* keyframes */
- /* selection */
- WM_operatortype_append(GRAPH_OT_clickselect);
- WM_operatortype_append(GRAPH_OT_select_all);
- WM_operatortype_append(GRAPH_OT_select_box);
- WM_operatortype_append(GRAPH_OT_select_lasso);
- WM_operatortype_append(GRAPH_OT_select_circle);
- WM_operatortype_append(GRAPH_OT_select_column);
- WM_operatortype_append(GRAPH_OT_select_linked);
- WM_operatortype_append(GRAPH_OT_select_more);
- WM_operatortype_append(GRAPH_OT_select_less);
- WM_operatortype_append(GRAPH_OT_select_leftright);
-
- /* editing */
- WM_operatortype_append(GRAPH_OT_snap);
- WM_operatortype_append(GRAPH_OT_mirror);
- WM_operatortype_append(GRAPH_OT_frame_jump);
- WM_operatortype_append(GRAPH_OT_handle_type);
- WM_operatortype_append(GRAPH_OT_interpolation_type);
- WM_operatortype_append(GRAPH_OT_extrapolation_type);
- WM_operatortype_append(GRAPH_OT_easing_type);
- WM_operatortype_append(GRAPH_OT_sample);
- WM_operatortype_append(GRAPH_OT_bake);
- WM_operatortype_append(GRAPH_OT_sound_bake);
- WM_operatortype_append(GRAPH_OT_smooth);
- WM_operatortype_append(GRAPH_OT_clean);
- WM_operatortype_append(GRAPH_OT_euler_filter);
- WM_operatortype_append(GRAPH_OT_delete);
- WM_operatortype_append(GRAPH_OT_duplicate);
-
- WM_operatortype_append(GRAPH_OT_copy);
- WM_operatortype_append(GRAPH_OT_paste);
-
- WM_operatortype_append(GRAPH_OT_keyframe_insert);
- WM_operatortype_append(GRAPH_OT_click_insert);
-
- /* F-Curve Modifiers */
- WM_operatortype_append(GRAPH_OT_fmodifier_add);
- WM_operatortype_append(GRAPH_OT_fmodifier_copy);
- WM_operatortype_append(GRAPH_OT_fmodifier_paste);
-
- /* Drivers */
- WM_operatortype_append(GRAPH_OT_driver_variables_copy);
- WM_operatortype_append(GRAPH_OT_driver_variables_paste);
- WM_operatortype_append(GRAPH_OT_driver_delete_invalid);
+ /* view */
+ WM_operatortype_append(GRAPH_OT_cursor_set);
+
+ WM_operatortype_append(GRAPH_OT_previewrange_set);
+ WM_operatortype_append(GRAPH_OT_view_all);
+ WM_operatortype_append(GRAPH_OT_view_selected);
+ WM_operatortype_append(GRAPH_OT_properties);
+ WM_operatortype_append(GRAPH_OT_view_frame);
+
+ WM_operatortype_append(GRAPH_OT_ghost_curves_create);
+ WM_operatortype_append(GRAPH_OT_ghost_curves_clear);
+
+ WM_operatortype_append(GRAPH_OT_hide);
+ WM_operatortype_append(GRAPH_OT_reveal);
+
+ /* keyframes */
+ /* selection */
+ WM_operatortype_append(GRAPH_OT_clickselect);
+ WM_operatortype_append(GRAPH_OT_select_all);
+ WM_operatortype_append(GRAPH_OT_select_box);
+ WM_operatortype_append(GRAPH_OT_select_lasso);
+ WM_operatortype_append(GRAPH_OT_select_circle);
+ WM_operatortype_append(GRAPH_OT_select_column);
+ WM_operatortype_append(GRAPH_OT_select_linked);
+ WM_operatortype_append(GRAPH_OT_select_more);
+ WM_operatortype_append(GRAPH_OT_select_less);
+ WM_operatortype_append(GRAPH_OT_select_leftright);
+
+ /* editing */
+ WM_operatortype_append(GRAPH_OT_snap);
+ WM_operatortype_append(GRAPH_OT_mirror);
+ WM_operatortype_append(GRAPH_OT_frame_jump);
+ WM_operatortype_append(GRAPH_OT_handle_type);
+ WM_operatortype_append(GRAPH_OT_interpolation_type);
+ WM_operatortype_append(GRAPH_OT_extrapolation_type);
+ WM_operatortype_append(GRAPH_OT_easing_type);
+ WM_operatortype_append(GRAPH_OT_sample);
+ WM_operatortype_append(GRAPH_OT_bake);
+ WM_operatortype_append(GRAPH_OT_sound_bake);
+ WM_operatortype_append(GRAPH_OT_smooth);
+ WM_operatortype_append(GRAPH_OT_clean);
+ WM_operatortype_append(GRAPH_OT_euler_filter);
+ WM_operatortype_append(GRAPH_OT_delete);
+ WM_operatortype_append(GRAPH_OT_duplicate);
+
+ WM_operatortype_append(GRAPH_OT_copy);
+ WM_operatortype_append(GRAPH_OT_paste);
+
+ WM_operatortype_append(GRAPH_OT_keyframe_insert);
+ WM_operatortype_append(GRAPH_OT_click_insert);
+
+ /* F-Curve Modifiers */
+ WM_operatortype_append(GRAPH_OT_fmodifier_add);
+ WM_operatortype_append(GRAPH_OT_fmodifier_copy);
+ WM_operatortype_append(GRAPH_OT_fmodifier_paste);
+
+ /* Drivers */
+ WM_operatortype_append(GRAPH_OT_driver_variables_copy);
+ WM_operatortype_append(GRAPH_OT_driver_variables_paste);
+ WM_operatortype_append(GRAPH_OT_driver_delete_invalid);
}
void ED_operatormacros_graph(void)
{
- wmOperatorType *ot;
- wmOperatorTypeMacro *otmacro;
-
- ot = WM_operatortype_append_macro("GRAPH_OT_duplicate_move", "Duplicate",
- "Make a copy of all selected keyframes and move them",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "GRAPH_OT_duplicate");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_transform");
- RNA_enum_set(otmacro->ptr, "mode", TFM_TIME_DUPLICATE);
- RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
+ wmOperatorType *ot;
+ wmOperatorTypeMacro *otmacro;
+
+ ot = WM_operatortype_append_macro("GRAPH_OT_duplicate_move",
+ "Duplicate",
+ "Make a copy of all selected keyframes and move them",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "GRAPH_OT_duplicate");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_transform");
+ RNA_enum_set(otmacro->ptr, "mode", TFM_TIME_DUPLICATE);
+ RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
}
-
/* ************************** registration - keymaps **********************************/
void graphedit_keymap(wmKeyConfig *keyconf)
{
- /* keymap for all regions */
- WM_keymap_ensure(keyconf, "Graph Editor Generic", SPACE_GRAPH, 0);
+ /* keymap for all regions */
+ WM_keymap_ensure(keyconf, "Graph Editor Generic", SPACE_GRAPH, 0);
- /* channels */
- /* Channels are not directly handled by the Graph Editor module, but are inherited from the Animation module.
- * All the relevant operations, keymaps, drawing, etc. can therefore all be found in that module instead, as these
- * are all used for the Graph Editor too.
- */
+ /* channels */
+ /* Channels are not directly handled by the Graph Editor module, but are inherited from the Animation module.
+ * All the relevant operations, keymaps, drawing, etc. can therefore all be found in that module instead, as these
+ * are all used for the Graph Editor too.
+ */
- /* keyframes */
- WM_keymap_ensure(keyconf, "Graph Editor", SPACE_GRAPH, 0);
+ /* keyframes */
+ WM_keymap_ensure(keyconf, "Graph Editor", SPACE_GRAPH, 0);
}
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 6c6c0d451cc..a109282978c 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -20,7 +20,6 @@
* \ingroup spgraph
*/
-
#include <math.h>
#include <stdlib.h>
#include <string.h>
@@ -57,7 +56,6 @@
#include "graph_intern.h"
-
/* ************************************************************************** */
/* KEYFRAMES STUFF */
@@ -80,137 +78,137 @@
*/
void deselect_graph_keys(bAnimContext *ac, bool test, short sel, bool do_channels)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- SpaceGraph *sipo = (SpaceGraph *)ac->sl;
- KeyframeEditData ked = {{NULL}};
- KeyframeEditFunc test_cb, sel_cb;
-
- /* determine type-based settings */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
-
- /* filter data */
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* init BezTriple looping data */
- test_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
-
- /* See if we should be selecting or deselecting */
- if (test) {
- for (ale = anim_data.first; ale; ale = ale->next) {
- if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) {
- sel = SELECT_SUBTRACT;
- break;
- }
- }
- }
-
- /* convert sel to selectmode, and use that to get editor */
- sel_cb = ANIM_editkeyframes_select(sel);
-
- /* Now set the flags */
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
-
- /* Keyframes First */
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL);
-
- /* affect channel selection status? */
- if (do_channels) {
- /* only change selection of channel when the visibility of keyframes doesn't depend on this */
- if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
- /* deactivate the F-Curve, and deselect if deselecting keyframes.
- * otherwise select the F-Curve too since we've selected all the keyframes
- */
- if (sel == SELECT_SUBTRACT)
- fcu->flag &= ~FCURVE_SELECTED;
- else
- fcu->flag |= FCURVE_SELECTED;
- }
-
- /* always deactivate all F-Curves if we perform batch ops for selection */
- fcu->flag &= ~FCURVE_ACTIVE;
- }
- }
-
- /* Cleanup */
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ SpaceGraph *sipo = (SpaceGraph *)ac->sl;
+ KeyframeEditData ked = {{NULL}};
+ KeyframeEditFunc test_cb, sel_cb;
+
+ /* determine type-based settings */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+
+ /* filter data */
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* init BezTriple looping data */
+ test_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
+
+ /* See if we should be selecting or deselecting */
+ if (test) {
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) {
+ sel = SELECT_SUBTRACT;
+ break;
+ }
+ }
+ }
+
+ /* convert sel to selectmode, and use that to get editor */
+ sel_cb = ANIM_editkeyframes_select(sel);
+
+ /* Now set the flags */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
+
+ /* Keyframes First */
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL);
+
+ /* affect channel selection status? */
+ if (do_channels) {
+ /* only change selection of channel when the visibility of keyframes doesn't depend on this */
+ if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
+ /* deactivate the F-Curve, and deselect if deselecting keyframes.
+ * otherwise select the F-Curve too since we've selected all the keyframes
+ */
+ if (sel == SELECT_SUBTRACT)
+ fcu->flag &= ~FCURVE_SELECTED;
+ else
+ fcu->flag |= FCURVE_SELECTED;
+ }
+
+ /* always deactivate all F-Curves if we perform batch ops for selection */
+ fcu->flag &= ~FCURVE_ACTIVE;
+ }
+ }
+
+ /* Cleanup */
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int graphkeys_deselectall_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- bAnimListElem *ale_active = NULL;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* find active F-Curve, and preserve this for later
- * or else it becomes annoying with the current active
- * curve keeps fading out even while you're editing it
- */
- ale_active = get_active_fcurve_channel(&ac);
-
- /* 'standard' behavior - check if selected, then apply relevant selection */
- const int action = RNA_enum_get(op->ptr, "action");
- switch (action) {
- case SEL_TOGGLE:
- deselect_graph_keys(&ac, 1, SELECT_ADD, true);
- break;
- case SEL_SELECT:
- deselect_graph_keys(&ac, 0, SELECT_ADD, true);
- break;
- case SEL_DESELECT:
- deselect_graph_keys(&ac, 0, SELECT_SUBTRACT, true);
- break;
- case SEL_INVERT:
- deselect_graph_keys(&ac, 0, SELECT_INVERT, true);
- break;
- default:
- BLI_assert(0);
- break;
- }
-
- /* restore active F-Curve... */
- if (ale_active) {
- FCurve *fcu = (FCurve *)ale_active->data;
-
- /* all others should not be disabled, so we should be able to just set this directly...
- * - selection needs to be set too, or else this won't work...
- */
- fcu->flag |= (FCURVE_SELECTED | FCURVE_ACTIVE);
-
- MEM_freeN(ale_active);
- ale_active = NULL;
- }
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ bAnimListElem *ale_active = NULL;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* find active F-Curve, and preserve this for later
+ * or else it becomes annoying with the current active
+ * curve keeps fading out even while you're editing it
+ */
+ ale_active = get_active_fcurve_channel(&ac);
+
+ /* 'standard' behavior - check if selected, then apply relevant selection */
+ const int action = RNA_enum_get(op->ptr, "action");
+ switch (action) {
+ case SEL_TOGGLE:
+ deselect_graph_keys(&ac, 1, SELECT_ADD, true);
+ break;
+ case SEL_SELECT:
+ deselect_graph_keys(&ac, 0, SELECT_ADD, true);
+ break;
+ case SEL_DESELECT:
+ deselect_graph_keys(&ac, 0, SELECT_SUBTRACT, true);
+ break;
+ case SEL_INVERT:
+ deselect_graph_keys(&ac, 0, SELECT_INVERT, true);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ /* restore active F-Curve... */
+ if (ale_active) {
+ FCurve *fcu = (FCurve *)ale_active->data;
+
+ /* all others should not be disabled, so we should be able to just set this directly...
+ * - selection needs to be set too, or else this won't work...
+ */
+ fcu->flag |= (FCURVE_SELECTED | FCURVE_ACTIVE);
+
+ MEM_freeN(ale_active);
+ ale_active = NULL;
+ }
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select All";
- ot->idname = "GRAPH_OT_select_all";
- ot->description = "Toggle selection of all keyframes";
+ /* identifiers */
+ ot->name = "Select All";
+ ot->idname = "GRAPH_OT_select_all";
+ ot->description = "Toggle selection of all keyframes";
- /* api callbacks */
- ot->exec = graphkeys_deselectall_exec;
- ot->poll = graphop_visible_keyframes_poll;
+ /* api callbacks */
+ ot->exec = graphkeys_deselectall_exec;
+ ot->poll = graphop_visible_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_select_all(ot);
+ /* properties */
+ WM_operator_properties_select_all(ot);
}
/* ******************** Box Select Operator **************************** */
@@ -228,336 +226,341 @@ void GRAPH_OT_select_all(wmOperatorType *ot)
* this, and allow handles to be considered independently too.
* Also, for convenience, handles should get same status as keyframe (if it was within bounds).
*/
-static void box_select_graphkeys(
- bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, bool incl_handles,
- void *data)
+static void box_select_graphkeys(bAnimContext *ac,
+ const rctf *rectf_view,
+ short mode,
+ short selectmode,
+ bool incl_handles,
+ void *data)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter, mapping_flag;
-
- SpaceGraph *sipo = (SpaceGraph *)ac->sl;
- KeyframeEditData ked;
- KeyframeEditFunc ok_cb, select_cb;
- View2D *v2d = &ac->ar->v2d;
- rctf rectf, scaled_rectf;
-
- /* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
- UI_view2d_region_to_view_rctf(v2d, rectf_view, &rectf);
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* get beztriple editing/validation funcs */
- select_cb = ANIM_editkeyframes_select(selectmode);
- ok_cb = ANIM_editkeyframes_ok(mode);
-
- /* init editing data */
- memset(&ked, 0, sizeof(KeyframeEditData));
- if (mode == BEZT_OK_REGION_LASSO) {
- KeyframeEdit_LassoData *data_lasso = data;
- data_lasso->rectf_scaled = &scaled_rectf;
- ked.data = data_lasso;
- }
- else if (mode == BEZT_OK_REGION_CIRCLE) {
- KeyframeEdit_CircleData *data_circle = data;
- data_circle->rectf_scaled = &scaled_rectf;
- ked.data = data;
- }
- else {
- ked.data = &scaled_rectf;
- }
-
- /* treat handles separately? */
- if (incl_handles) {
- ked.iterflags |= KEYFRAME_ITER_INCL_HANDLES;
- mapping_flag = 0;
- }
- else
- mapping_flag = ANIM_UNITCONV_ONLYKEYS;
-
- mapping_flag |= ANIM_get_normalization_flags(ac);
-
- /* loop over data, doing box select */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
- FCurve *fcu = (FCurve *)ale->key_data;
- float offset;
- float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
-
- /* apply NLA mapping to all the keyframes, since it's easier than trying to
- * guess when a callback might use something different
- */
- if (adt)
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, incl_handles == 0);
-
- scaled_rectf.xmin = rectf.xmin;
- scaled_rectf.xmax = rectf.xmax;
- scaled_rectf.ymin = rectf.ymin / unit_scale - offset;
- scaled_rectf.ymax = rectf.ymax / unit_scale - offset;
-
- /* set horizontal range (if applicable)
- * NOTE: these values are only used for x-range and y-range but not region
- * (which uses ked.data, i.e. rectf)
- */
- if (mode != BEZT_OK_VALUERANGE) {
- ked.f1 = rectf.xmin;
- ked.f2 = rectf.xmax;
- }
- else {
- ked.f1 = rectf.ymin;
- ked.f2 = rectf.ymax;
- }
-
- /* firstly, check if any keyframes will be hit by this */
- if (ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, ok_cb, NULL)) {
- /* select keyframes that are in the appropriate places */
- ANIM_fcurve_keyframes_loop(&ked, fcu, ok_cb, select_cb, NULL);
-
- /* only change selection of channel when the visibility of keyframes doesn't depend on this */
- if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
- /* select the curve too now that curve will be touched */
- if (selectmode == SELECT_ADD)
- fcu->flag |= FCURVE_SELECTED;
- }
- }
-
- /* un-apply NLA mapping from all the keyframes */
- if (adt)
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, incl_handles == 0);
- }
-
- /* cleanup */
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter, mapping_flag;
+
+ SpaceGraph *sipo = (SpaceGraph *)ac->sl;
+ KeyframeEditData ked;
+ KeyframeEditFunc ok_cb, select_cb;
+ View2D *v2d = &ac->ar->v2d;
+ rctf rectf, scaled_rectf;
+
+ /* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
+ UI_view2d_region_to_view_rctf(v2d, rectf_view, &rectf);
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* get beztriple editing/validation funcs */
+ select_cb = ANIM_editkeyframes_select(selectmode);
+ ok_cb = ANIM_editkeyframes_ok(mode);
+
+ /* init editing data */
+ memset(&ked, 0, sizeof(KeyframeEditData));
+ if (mode == BEZT_OK_REGION_LASSO) {
+ KeyframeEdit_LassoData *data_lasso = data;
+ data_lasso->rectf_scaled = &scaled_rectf;
+ ked.data = data_lasso;
+ }
+ else if (mode == BEZT_OK_REGION_CIRCLE) {
+ KeyframeEdit_CircleData *data_circle = data;
+ data_circle->rectf_scaled = &scaled_rectf;
+ ked.data = data;
+ }
+ else {
+ ked.data = &scaled_rectf;
+ }
+
+ /* treat handles separately? */
+ if (incl_handles) {
+ ked.iterflags |= KEYFRAME_ITER_INCL_HANDLES;
+ mapping_flag = 0;
+ }
+ else
+ mapping_flag = ANIM_UNITCONV_ONLYKEYS;
+
+ mapping_flag |= ANIM_get_normalization_flags(ac);
+
+ /* loop over data, doing box select */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+ FCurve *fcu = (FCurve *)ale->key_data;
+ float offset;
+ float unit_scale = ANIM_unit_mapping_get_factor(
+ ac->scene, ale->id, fcu, mapping_flag, &offset);
+
+ /* apply NLA mapping to all the keyframes, since it's easier than trying to
+ * guess when a callback might use something different
+ */
+ if (adt)
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, incl_handles == 0);
+
+ scaled_rectf.xmin = rectf.xmin;
+ scaled_rectf.xmax = rectf.xmax;
+ scaled_rectf.ymin = rectf.ymin / unit_scale - offset;
+ scaled_rectf.ymax = rectf.ymax / unit_scale - offset;
+
+ /* set horizontal range (if applicable)
+ * NOTE: these values are only used for x-range and y-range but not region
+ * (which uses ked.data, i.e. rectf)
+ */
+ if (mode != BEZT_OK_VALUERANGE) {
+ ked.f1 = rectf.xmin;
+ ked.f2 = rectf.xmax;
+ }
+ else {
+ ked.f1 = rectf.ymin;
+ ked.f2 = rectf.ymax;
+ }
+
+ /* firstly, check if any keyframes will be hit by this */
+ if (ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, ok_cb, NULL)) {
+ /* select keyframes that are in the appropriate places */
+ ANIM_fcurve_keyframes_loop(&ked, fcu, ok_cb, select_cb, NULL);
+
+ /* only change selection of channel when the visibility of keyframes doesn't depend on this */
+ if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
+ /* select the curve too now that curve will be touched */
+ if (selectmode == SELECT_ADD)
+ fcu->flag |= FCURVE_SELECTED;
+ }
+ }
+
+ /* un-apply NLA mapping from all the keyframes */
+ if (adt)
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, incl_handles == 0);
+ }
+
+ /* cleanup */
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int graphkeys_box_select_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- rcti rect;
- rctf rect_fl;
- short mode = 0;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
- const int selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- deselect_graph_keys(&ac, 1, SELECT_SUBTRACT, true);
- }
-
- /* 'include_handles' from the operator specifies whether to include handles in the selection. */
- const bool incl_handles = RNA_boolean_get(op->ptr, "include_handles");
-
- /* get settings from operator */
- WM_operator_properties_border_to_rcti(op, &rect);
-
- /* selection 'mode' depends on whether box_select region only matters on one axis */
- if (RNA_boolean_get(op->ptr, "axis_range")) {
- /* mode depends on which axis of the range is larger to determine which axis to use
- * - checking this in region-space is fine, as it's fundamentally still going to be a different rect size
- * - the frame-range select option is favored over the channel one (x over y), as frame-range one is often
- * used for tweaking timing when "blocking", while channels is not that useful...
- */
- if ((BLI_rcti_size_x(&rect)) >= (BLI_rcti_size_y(&rect)))
- mode = BEZT_OK_FRAMERANGE;
- else
- mode = BEZT_OK_VALUERANGE;
- }
- else
- mode = BEZT_OK_REGION;
-
- BLI_rctf_rcti_copy(&rect_fl, &rect);
-
- /* apply box_select action */
- box_select_graphkeys(&ac, &rect_fl, mode, selectmode, incl_handles, NULL);
-
- /* send notifier that keyframe selection has changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ rcti rect;
+ rctf rect_fl;
+ short mode = 0;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
+ const int selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ deselect_graph_keys(&ac, 1, SELECT_SUBTRACT, true);
+ }
+
+ /* 'include_handles' from the operator specifies whether to include handles in the selection. */
+ const bool incl_handles = RNA_boolean_get(op->ptr, "include_handles");
+
+ /* get settings from operator */
+ WM_operator_properties_border_to_rcti(op, &rect);
+
+ /* selection 'mode' depends on whether box_select region only matters on one axis */
+ if (RNA_boolean_get(op->ptr, "axis_range")) {
+ /* mode depends on which axis of the range is larger to determine which axis to use
+ * - checking this in region-space is fine, as it's fundamentally still going to be a different rect size
+ * - the frame-range select option is favored over the channel one (x over y), as frame-range one is often
+ * used for tweaking timing when "blocking", while channels is not that useful...
+ */
+ if ((BLI_rcti_size_x(&rect)) >= (BLI_rcti_size_y(&rect)))
+ mode = BEZT_OK_FRAMERANGE;
+ else
+ mode = BEZT_OK_VALUERANGE;
+ }
+ else
+ mode = BEZT_OK_REGION;
+
+ BLI_rctf_rcti_copy(&rect_fl, &rect);
+
+ /* apply box_select action */
+ box_select_graphkeys(&ac, &rect_fl, mode, selectmode, incl_handles, NULL);
+
+ /* send notifier that keyframe selection has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_select_box(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Box Select";
- ot->idname = "GRAPH_OT_select_box";
- ot->description = "Select all keyframes within the specified region";
-
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = graphkeys_box_select_exec;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
-
- ot->poll = graphop_visible_keyframes_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
- RNA_def_boolean(ot->srna, "include_handles", 0, "Include Handles", "Are handles tested individually against the selection criteria");
-
- WM_operator_properties_gesture_box(ot);
- WM_operator_properties_select_operation_simple(ot);
+ /* identifiers */
+ ot->name = "Box Select";
+ ot->idname = "GRAPH_OT_select_box";
+ ot->description = "Select all keyframes within the specified region";
+
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = graphkeys_box_select_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
+
+ ot->poll = graphop_visible_keyframes_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
+ RNA_def_boolean(ot->srna,
+ "include_handles",
+ 0,
+ "Include Handles",
+ "Are handles tested individually against the selection criteria");
+
+ WM_operator_properties_gesture_box(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
-
/* ------------------- */
static int graphkeys_lassoselect_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
+ bAnimContext ac;
- KeyframeEdit_LassoData data_lasso = {0};
- rcti rect;
- rctf rect_fl;
+ KeyframeEdit_LassoData data_lasso = {0};
+ rcti rect;
+ rctf rect_fl;
- bool incl_handles;
+ bool incl_handles;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- 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)
- return OPERATOR_CANCELLED;
+ 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)
+ return OPERATOR_CANCELLED;
- const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
- const short selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- deselect_graph_keys(&ac, 0, SELECT_SUBTRACT, true);
- }
+ const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
+ const short selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ deselect_graph_keys(&ac, 0, SELECT_SUBTRACT, true);
+ }
- {
- SpaceGraph *sipo = (SpaceGraph *)ac.sl;
- if (selectmode == SELECT_ADD) {
- incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) ||
- (sipo->flag & SIPO_NOHANDLES)) == 0;
- }
- else {
- incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0;
- }
- }
+ {
+ SpaceGraph *sipo = (SpaceGraph *)ac.sl;
+ if (selectmode == SELECT_ADD) {
+ incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) || (sipo->flag & SIPO_NOHANDLES)) == 0;
+ }
+ else {
+ incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0;
+ }
+ }
- /* get settings from operator */
- BLI_lasso_boundbox(&rect, data_lasso.mcords, data_lasso.mcords_tot);
- BLI_rctf_rcti_copy(&rect_fl, &rect);
+ /* get settings from operator */
+ BLI_lasso_boundbox(&rect, data_lasso.mcords, data_lasso.mcords_tot);
+ 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);
+ /* 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.mcords);
- /* send notifier that keyframe selection has changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ /* send notifier that keyframe selection has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_select_lasso(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Lasso Select";
- ot->description = "Select keyframe points using lasso selection";
- ot->idname = "GRAPH_OT_select_lasso";
-
- /* api callbacks */
- ot->invoke = WM_gesture_lasso_invoke;
- ot->modal = WM_gesture_lasso_modal;
- ot->exec = graphkeys_lassoselect_exec;
- ot->poll = graphop_visible_keyframes_poll;
- 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);
+ /* identifiers */
+ ot->name = "Lasso Select";
+ ot->description = "Select keyframe points using lasso selection";
+ ot->idname = "GRAPH_OT_select_lasso";
+
+ /* api callbacks */
+ ot->invoke = WM_gesture_lasso_invoke;
+ ot->modal = WM_gesture_lasso_modal;
+ ot->exec = graphkeys_lassoselect_exec;
+ ot->poll = graphop_visible_keyframes_poll;
+ 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);
}
/* ------------------- */
static int graph_circle_select_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- bool incl_handles = false;
-
- KeyframeEdit_CircleData data = {0};
- rctf rect_fl;
-
- float x = RNA_int_get(op->ptr, "x");
- float y = RNA_int_get(op->ptr, "y");
- float radius = RNA_int_get(op->ptr, "radius");
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- const eSelectOp sel_op = ED_select_op_modal(
- RNA_enum_get(op->ptr, "mode"), WM_gesture_is_modal_first(op->customdata));
- const short selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- deselect_graph_keys(&ac, 0, SELECT_SUBTRACT, true);
- }
-
- data.mval[0] = x;
- data.mval[1] = y;
- data.radius_squared = radius * radius;
- data.rectf_view = &rect_fl;
-
- rect_fl.xmin = x - radius;
- rect_fl.xmax = x + radius;
- rect_fl.ymin = y - radius;
- rect_fl.ymax = y + radius;
-
- {
- SpaceGraph *sipo = (SpaceGraph *)ac.sl;
- if (selectmode == SELECT_ADD) {
- incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) ||
- (sipo->flag & SIPO_NOHANDLES)) == 0;
- }
- else {
- incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0;
- }
- }
-
- /* apply box_select action */
- box_select_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_CIRCLE, selectmode, incl_handles, &data);
-
- /* send notifier that keyframe selection has changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ bool incl_handles = false;
+
+ KeyframeEdit_CircleData data = {0};
+ rctf rect_fl;
+
+ float x = RNA_int_get(op->ptr, "x");
+ float y = RNA_int_get(op->ptr, "y");
+ float radius = RNA_int_get(op->ptr, "radius");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"),
+ WM_gesture_is_modal_first(op->customdata));
+ const short selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ deselect_graph_keys(&ac, 0, SELECT_SUBTRACT, true);
+ }
+
+ data.mval[0] = x;
+ data.mval[1] = y;
+ data.radius_squared = radius * radius;
+ data.rectf_view = &rect_fl;
+
+ rect_fl.xmin = x - radius;
+ rect_fl.xmax = x + radius;
+ rect_fl.ymin = y - radius;
+ rect_fl.ymax = y + radius;
+
+ {
+ SpaceGraph *sipo = (SpaceGraph *)ac.sl;
+ if (selectmode == SELECT_ADD) {
+ incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) || (sipo->flag & SIPO_NOHANDLES)) == 0;
+ }
+ else {
+ incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0;
+ }
+ }
+
+ /* apply box_select action */
+ box_select_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_CIRCLE, selectmode, incl_handles, &data);
+
+ /* send notifier that keyframe selection has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_select_circle(wmOperatorType *ot)
{
- ot->name = "Circle Select";
- ot->description = "Select keyframe points using circle selection";
- ot->idname = "GRAPH_OT_select_circle";
-
- ot->invoke = WM_gesture_circle_invoke;
- ot->modal = WM_gesture_circle_modal;
- ot->exec = graph_circle_select_exec;
- ot->poll = graphop_visible_keyframes_poll;
- 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);
+ ot->name = "Circle Select";
+ ot->description = "Select keyframe points using circle selection";
+ ot->idname = "GRAPH_OT_select_circle";
+
+ ot->invoke = WM_gesture_circle_invoke;
+ ot->modal = WM_gesture_circle_modal;
+ ot->exec = graph_circle_select_exec;
+ ot->poll = graphop_visible_keyframes_poll;
+ 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);
}
/* ******************** Column Select Operator **************************** */
@@ -570,11 +573,15 @@ void GRAPH_OT_select_circle(wmOperatorType *ot)
/* defines for column-select mode */
static const EnumPropertyItem prop_column_select_types[] = {
- {GRAPHKEYS_COLUMNSEL_KEYS, "KEYS", 0, "On Selected Keyframes", ""},
- {GRAPHKEYS_COLUMNSEL_CFRA, "CFRA", 0, "On Current Frame", ""},
- {GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN, "MARKERS_COLUMN", 0, "On Selected Markers", ""},
- {GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN, "MARKERS_BETWEEN", 0, "Between Min/Max Selected Markers", ""},
- {0, NULL, 0, NULL, NULL},
+ {GRAPHKEYS_COLUMNSEL_KEYS, "KEYS", 0, "On Selected Keyframes", ""},
+ {GRAPHKEYS_COLUMNSEL_CFRA, "CFRA", 0, "On Current Frame", ""},
+ {GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN, "MARKERS_COLUMN", 0, "On Selected Markers", ""},
+ {GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN,
+ "MARKERS_BETWEEN",
+ 0,
+ "Between Min/Max Selected Markers",
+ ""},
+ {0, NULL, 0, NULL, NULL},
};
/* ------------------- */
@@ -584,218 +591,217 @@ static const EnumPropertyItem prop_column_select_types[] = {
* should de-duplicate - campbell */
static void markers_selectkeys_between(bAnimContext *ac)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- KeyframeEditFunc ok_cb, select_cb;
- KeyframeEditData ked = {{NULL}};
- float min, max;
-
- /* get extreme markers */
- ED_markers_get_minmax(ac->markers, 1, &min, &max);
- min -= 0.5f;
- max += 0.5f;
-
- /* get editing funcs + data */
- ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
- select_cb = ANIM_editkeyframes_select(SELECT_ADD);
-
- ked.f1 = min;
- ked.f2 = max;
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* select keys in-between */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-
- if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
- }
- else {
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
- }
- }
-
- /* Cleanup */
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ KeyframeEditFunc ok_cb, select_cb;
+ KeyframeEditData ked = {{NULL}};
+ float min, max;
+
+ /* get extreme markers */
+ ED_markers_get_minmax(ac->markers, 1, &min, &max);
+ min -= 0.5f;
+ max += 0.5f;
+
+ /* get editing funcs + data */
+ ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
+ select_cb = ANIM_editkeyframes_select(SELECT_ADD);
+
+ ked.f1 = min;
+ ked.f2 = max;
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* select keys in-between */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
+ }
+ else {
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
+ }
+ }
+
+ /* Cleanup */
+ ANIM_animdata_freelist(&anim_data);
}
-
/* Selects all visible keyframes in the same frames as the specified elements */
static void columnselect_graph_keys(bAnimContext *ac, short mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- Scene *scene = ac->scene;
- CfraElem *ce;
- KeyframeEditFunc select_cb, ok_cb;
- KeyframeEditData ked;
-
- /* initialize keyframe editing data */
- memset(&ked, 0, sizeof(KeyframeEditData));
-
- /* build list of columns */
- switch (mode) {
- case GRAPHKEYS_COLUMNSEL_KEYS: /* list of selected keys */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next)
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_to_cfraelem, NULL);
-
- ANIM_animdata_freelist(&anim_data);
- break;
-
- case GRAPHKEYS_COLUMNSEL_CFRA: /* current frame */
- /* make a single CfraElem for storing this */
- ce = MEM_callocN(sizeof(CfraElem), "cfraElem");
- BLI_addtail(&ked.list, ce);
-
- ce->cfra = (float)CFRA;
- break;
-
- case GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
- ED_markers_make_cfra_list(ac->markers, &ked.list, SELECT);
- break;
-
- default: /* invalid option */
- return;
- }
-
- /* set up BezTriple edit callbacks */
- select_cb = ANIM_editkeyframes_select(SELECT_ADD);
- ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME);
-
- /* loop through all of the keys and select additional keyframes
- * based on the keys found to be selected above
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-
- /* loop over cfraelems (stored in the KeyframeEditData->list)
- * - we need to do this here, as we can apply fewer NLA-mapping conversions
- */
- for (ce = ked.list.first; ce; ce = ce->next) {
- /* set frame for validation callback to refer to */
- ked.f1 = BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP);
-
- /* select elements with frame number matching cfraelem */
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
- }
- }
-
- /* free elements */
- BLI_freelistN(&ked.list);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ Scene *scene = ac->scene;
+ CfraElem *ce;
+ KeyframeEditFunc select_cb, ok_cb;
+ KeyframeEditData ked;
+
+ /* initialize keyframe editing data */
+ memset(&ked, 0, sizeof(KeyframeEditData));
+
+ /* build list of columns */
+ switch (mode) {
+ case GRAPHKEYS_COLUMNSEL_KEYS: /* list of selected keys */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next)
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_to_cfraelem, NULL);
+
+ ANIM_animdata_freelist(&anim_data);
+ break;
+
+ case GRAPHKEYS_COLUMNSEL_CFRA: /* current frame */
+ /* make a single CfraElem for storing this */
+ ce = MEM_callocN(sizeof(CfraElem), "cfraElem");
+ BLI_addtail(&ked.list, ce);
+
+ ce->cfra = (float)CFRA;
+ break;
+
+ case GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
+ ED_markers_make_cfra_list(ac->markers, &ked.list, SELECT);
+ break;
+
+ default: /* invalid option */
+ return;
+ }
+
+ /* set up BezTriple edit callbacks */
+ select_cb = ANIM_editkeyframes_select(SELECT_ADD);
+ ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME);
+
+ /* loop through all of the keys and select additional keyframes
+ * based on the keys found to be selected above
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ /* loop over cfraelems (stored in the KeyframeEditData->list)
+ * - we need to do this here, as we can apply fewer NLA-mapping conversions
+ */
+ for (ce = ked.list.first; ce; ce = ce->next) {
+ /* set frame for validation callback to refer to */
+ ked.f1 = BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP);
+
+ /* select elements with frame number matching cfraelem */
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
+ }
+ }
+
+ /* free elements */
+ BLI_freelistN(&ked.list);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int graphkeys_columnselect_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- short mode;
+ bAnimContext ac;
+ short mode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* action to take depends on the mode */
- mode = RNA_enum_get(op->ptr, "mode");
+ /* action to take depends on the mode */
+ mode = RNA_enum_get(op->ptr, "mode");
- if (mode == GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN)
- markers_selectkeys_between(&ac);
- else
- columnselect_graph_keys(&ac, mode);
+ if (mode == GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN)
+ markers_selectkeys_between(&ac);
+ else
+ columnselect_graph_keys(&ac, mode);
- /* set notifier that keyframe selection has changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ /* set notifier that keyframe selection has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_select_column(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select All";
- ot->idname = "GRAPH_OT_select_column";
- ot->description = "Select all keyframes on the specified frame(s)";
+ /* identifiers */
+ ot->name = "Select All";
+ ot->idname = "GRAPH_OT_select_column";
+ ot->description = "Select all keyframes on the specified frame(s)";
- /* api callbacks */
- ot->exec = graphkeys_columnselect_exec;
- ot->poll = graphop_visible_keyframes_poll;
+ /* api callbacks */
+ ot->exec = graphkeys_columnselect_exec;
+ ot->poll = graphop_visible_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- ot->prop = RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
+ /* props */
+ ot->prop = RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
}
/* ******************** Select Linked Operator *********************** */
static int graphkeys_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
+ bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- KeyframeEditFunc ok_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
- KeyframeEditFunc sel_cb = ANIM_editkeyframes_select(SELECT_ADD);
+ KeyframeEditFunc ok_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
+ KeyframeEditFunc sel_cb = ANIM_editkeyframes_select(SELECT_ADD);
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* loop through all of the keys and select additional keyframes based on these */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* loop through all of the keys and select additional keyframes based on these */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
- /* check if anything selected? */
- if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ok_cb, NULL)) {
- /* select every keyframe in this curve then */
- ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL);
- }
- }
+ /* check if anything selected? */
+ if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ok_cb, NULL)) {
+ /* select every keyframe in this curve then */
+ ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL);
+ }
+ }
- /* Cleanup */
- ANIM_animdata_freelist(&anim_data);
+ /* Cleanup */
+ ANIM_animdata_freelist(&anim_data);
- /* set notifier that keyframe selection has changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ /* set notifier that keyframe selection has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_select_linked(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Linked";
- ot->idname = "GRAPH_OT_select_linked";
- ot->description = "Select keyframes occurring in the same F-Curves as selected ones";
+ /* identifiers */
+ ot->name = "Select Linked";
+ ot->idname = "GRAPH_OT_select_linked";
+ ot->description = "Select keyframes occurring in the same F-Curves as selected ones";
- /* api callbacks */
- ot->exec = graphkeys_select_linked_exec;
- ot->poll = graphop_visible_keyframes_poll;
+ /* api callbacks */
+ ot->exec = graphkeys_select_linked_exec;
+ ot->poll = graphop_visible_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Select More/Less Operators *********************** */
@@ -803,111 +809,110 @@ void GRAPH_OT_select_linked(wmOperatorType *ot)
/* Common code to perform selection */
static void select_moreless_graph_keys(bAnimContext *ac, short mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- KeyframeEditData ked;
- KeyframeEditFunc build_cb;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ KeyframeEditData ked;
+ KeyframeEditFunc build_cb;
- /* init selmap building data */
- build_cb = ANIM_editkeyframes_buildselmap(mode);
- memset(&ked, 0, sizeof(KeyframeEditData));
+ /* init selmap building data */
+ build_cb = ANIM_editkeyframes_buildselmap(mode);
+ memset(&ked, 0, sizeof(KeyframeEditData));
- /* loop through all of the keys and select additional keyframes based on these */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ /* loop through all of the keys and select additional keyframes based on these */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
- /* only continue if F-Curve has keyframes */
- if (fcu->bezt == NULL)
- continue;
+ /* only continue if F-Curve has keyframes */
+ if (fcu->bezt == NULL)
+ continue;
- /* build up map of whether F-Curve's keyframes should be selected or not */
- ked.data = MEM_callocN(fcu->totvert, "selmap graphEdit");
- ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, build_cb, NULL);
+ /* build up map of whether F-Curve's keyframes should be selected or not */
+ ked.data = MEM_callocN(fcu->totvert, "selmap graphEdit");
+ ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, build_cb, NULL);
- /* based on this map, adjust the selection status of the keyframes */
- ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, bezt_selmap_flush, NULL);
+ /* based on this map, adjust the selection status of the keyframes */
+ ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, bezt_selmap_flush, NULL);
- /* free the selmap used here */
- MEM_freeN(ked.data);
- ked.data = NULL;
- }
+ /* free the selmap used here */
+ MEM_freeN(ked.data);
+ ked.data = NULL;
+ }
- /* Cleanup */
- ANIM_animdata_freelist(&anim_data);
+ /* Cleanup */
+ ANIM_animdata_freelist(&anim_data);
}
/* ----------------- */
static int graphkeys_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
+ bAnimContext ac;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* perform select changes */
- select_moreless_graph_keys(&ac, SELMAP_MORE);
+ /* perform select changes */
+ select_moreless_graph_keys(&ac, SELMAP_MORE);
- /* set notifier that keyframe selection has changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ /* set notifier that keyframe selection has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_select_more(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select More";
- ot->idname = "GRAPH_OT_select_more";
- ot->description = "Select keyframes beside already selected ones";
+ /* identifiers */
+ ot->name = "Select More";
+ ot->idname = "GRAPH_OT_select_more";
+ ot->description = "Select keyframes beside already selected ones";
- /* api callbacks */
- ot->exec = graphkeys_select_more_exec;
- ot->poll = graphop_visible_keyframes_poll;
+ /* api callbacks */
+ ot->exec = graphkeys_select_more_exec;
+ ot->poll = graphop_visible_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ----------------- */
static int graphkeys_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
+ bAnimContext ac;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* perform select changes */
- select_moreless_graph_keys(&ac, SELMAP_LESS);
+ /* perform select changes */
+ select_moreless_graph_keys(&ac, SELMAP_LESS);
- /* set notifier that keyframe selection has changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ /* set notifier that keyframe selection has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void GRAPH_OT_select_less(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Less";
- ot->idname = "GRAPH_OT_select_less";
- ot->description = "Deselect keyframes on ends of selection islands";
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->idname = "GRAPH_OT_select_less";
+ ot->description = "Deselect keyframes on ends of selection islands";
- /* api callbacks */
- ot->exec = graphkeys_select_less_exec;
- ot->poll = graphop_visible_keyframes_poll;
+ /* api callbacks */
+ ot->exec = graphkeys_select_less_exec;
+ ot->poll = graphop_visible_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Select Left/Right Operator ************************* */
@@ -915,151 +920,152 @@ void GRAPH_OT_select_less(wmOperatorType *ot)
/* defines for left-right select tool */
static const EnumPropertyItem prop_graphkeys_leftright_select_types[] = {
- {GRAPHKEYS_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""},
- {GRAPHKEYS_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""},
- {GRAPHKEYS_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""},
- {0, NULL, 0, NULL, NULL},
+ {GRAPHKEYS_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""},
+ {GRAPHKEYS_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""},
+ {GRAPHKEYS_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""},
+ {0, NULL, 0, NULL, NULL},
};
/* --------------------------------- */
static void graphkeys_select_leftright(bAnimContext *ac, short leftright, short select_mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- KeyframeEditFunc ok_cb, select_cb;
- KeyframeEditData ked = {{NULL}};
- Scene *scene = ac->scene;
-
- /* if select mode is replace, deselect all keyframes (and channels) first */
- if (select_mode == SELECT_REPLACE) {
- select_mode = SELECT_ADD;
-
- /* - deselect all other keyframes, so that just the newly selected remain
- * - channels aren't deselected, since we don't re-select any as a consequence
- */
- deselect_graph_keys(ac, 0, SELECT_SUBTRACT, false);
- }
-
- /* set callbacks and editing data */
- ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
- select_cb = ANIM_editkeyframes_select(select_mode);
-
- if (leftright == GRAPHKEYS_LRSEL_LEFT) {
- ked.f1 = MINAFRAMEF;
- ked.f2 = (float)(CFRA + 0.1f);
- }
- else {
- ked.f1 = (float)(CFRA - 0.1f);
- ked.f2 = MAXFRAMEF;
- }
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* select keys */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-
- if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
- }
- else
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
- }
-
- /* Cleanup */
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ KeyframeEditFunc ok_cb, select_cb;
+ KeyframeEditData ked = {{NULL}};
+ Scene *scene = ac->scene;
+
+ /* if select mode is replace, deselect all keyframes (and channels) first */
+ if (select_mode == SELECT_REPLACE) {
+ select_mode = SELECT_ADD;
+
+ /* - deselect all other keyframes, so that just the newly selected remain
+ * - channels aren't deselected, since we don't re-select any as a consequence
+ */
+ deselect_graph_keys(ac, 0, SELECT_SUBTRACT, false);
+ }
+
+ /* set callbacks and editing data */
+ ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
+ select_cb = ANIM_editkeyframes_select(select_mode);
+
+ if (leftright == GRAPHKEYS_LRSEL_LEFT) {
+ ked.f1 = MINAFRAMEF;
+ ked.f2 = (float)(CFRA + 0.1f);
+ }
+ else {
+ ked.f1 = (float)(CFRA - 0.1f);
+ ked.f2 = MAXFRAMEF;
+ }
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* select keys */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
+ }
+ else
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
+ }
+
+ /* Cleanup */
+ ANIM_animdata_freelist(&anim_data);
}
/* ----------------- */
static int graphkeys_select_leftright_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- short leftright = RNA_enum_get(op->ptr, "mode");
- short selectmode;
+ bAnimContext ac;
+ short leftright = RNA_enum_get(op->ptr, "mode");
+ short selectmode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* select mode is either replace (deselect all, then add) or add/extend */
- if (RNA_boolean_get(op->ptr, "extend"))
- selectmode = SELECT_INVERT;
- else
- selectmode = SELECT_REPLACE;
+ /* select mode is either replace (deselect all, then add) or add/extend */
+ if (RNA_boolean_get(op->ptr, "extend"))
+ selectmode = SELECT_INVERT;
+ else
+ selectmode = SELECT_REPLACE;
- /* if "test" mode is set, we don't have any info to set this with */
- if (leftright == GRAPHKEYS_LRSEL_TEST)
- return OPERATOR_CANCELLED;
+ /* if "test" mode is set, we don't have any info to set this with */
+ if (leftright == GRAPHKEYS_LRSEL_TEST)
+ return OPERATOR_CANCELLED;
- /* do the selecting now */
- graphkeys_select_leftright(&ac, leftright, selectmode);
+ /* do the selecting now */
+ graphkeys_select_leftright(&ac, leftright, selectmode);
- /* set notifier that keyframe selection (and channels too) have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
+ /* set notifier that keyframe selection (and channels too) have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int graphkeys_select_leftright_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bAnimContext ac;
- short leftright = RNA_enum_get(op->ptr, "mode");
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* handle mode-based testing */
- if (leftright == GRAPHKEYS_LRSEL_TEST) {
- Scene *scene = ac.scene;
- ARegion *ar = ac.ar;
- View2D *v2d = &ar->v2d;
- float x;
-
- /* determine which side of the current frame mouse is on */
- x = UI_view2d_region_to_view_x(v2d, event->mval[0]);
- if (x < CFRA)
- RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_LEFT);
- else
- RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_RIGHT);
- }
-
- /* perform selection */
- return graphkeys_select_leftright_exec(C, op);
+ bAnimContext ac;
+ short leftright = RNA_enum_get(op->ptr, "mode");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* handle mode-based testing */
+ if (leftright == GRAPHKEYS_LRSEL_TEST) {
+ Scene *scene = ac.scene;
+ ARegion *ar = ac.ar;
+ View2D *v2d = &ar->v2d;
+ float x;
+
+ /* determine which side of the current frame mouse is on */
+ x = UI_view2d_region_to_view_x(v2d, event->mval[0]);
+ if (x < CFRA)
+ RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_LEFT);
+ else
+ RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_RIGHT);
+ }
+
+ /* perform selection */
+ return graphkeys_select_leftright_exec(C, op);
}
void GRAPH_OT_select_leftright(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Select Left/Right";
- ot->idname = "GRAPH_OT_select_leftright";
- ot->description = "Select keyframes to the left or the right of the current frame";
+ /* identifiers */
+ ot->name = "Select Left/Right";
+ ot->idname = "GRAPH_OT_select_leftright";
+ ot->description = "Select keyframes to the left or the right of the current frame";
- /* api callbacks */
- ot->invoke = graphkeys_select_leftright_invoke;
- ot->exec = graphkeys_select_leftright_exec;
- ot->poll = graphop_visible_keyframes_poll;
+ /* api callbacks */
+ ot->invoke = graphkeys_select_leftright_invoke;
+ ot->exec = graphkeys_select_leftright_exec;
+ ot->poll = graphop_visible_keyframes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* id-props */
- ot->prop = RNA_def_enum(ot->srna, "mode", prop_graphkeys_leftright_select_types, GRAPHKEYS_LRSEL_TEST, "Mode", "");
- RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+ /* id-props */
+ ot->prop = RNA_def_enum(
+ ot->srna, "mode", prop_graphkeys_leftright_select_types, GRAPHKEYS_LRSEL_TEST, "Mode", "");
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ******************** Mouse-Click Select Operator *********************** */
@@ -1074,32 +1080,32 @@ void GRAPH_OT_select_leftright(wmOperatorType *ot)
/* temp info for caching handle vertices close */
typedef struct tNearestVertInfo {
- struct tNearestVertInfo *next, *prev;
+ struct tNearestVertInfo *next, *prev;
- FCurve *fcu; /* F-Curve that keyframe comes from */
+ FCurve *fcu; /* F-Curve that keyframe comes from */
- BezTriple *bezt; /* keyframe to consider */
- FPoint *fpt; /* sample point to consider */
+ BezTriple *bezt; /* keyframe to consider */
+ FPoint *fpt; /* sample point to consider */
- short hpoint; /* the handle index that we hit (eHandleIndex) */
- short sel; /* whether the handle is selected or not */
- int dist; /* distance from mouse to vert */
+ short hpoint; /* the handle index that we hit (eHandleIndex) */
+ short sel; /* whether the handle is selected or not */
+ int dist; /* distance from mouse to vert */
- eAnim_ChannelType ctype; /* type of animation channel this FCurve comes from */
+ eAnim_ChannelType ctype; /* type of animation channel this FCurve comes from */
- float frame; /* frame that point was on when it matched (global time) */
+ float frame; /* frame that point was on when it matched (global time) */
} tNearestVertInfo;
/* Tags for the type of graph vert that we have */
typedef enum eGraphVertIndex {
- NEAREST_HANDLE_LEFT = -1,
- NEAREST_HANDLE_KEY,
- NEAREST_HANDLE_RIGHT,
+ NEAREST_HANDLE_LEFT = -1,
+ NEAREST_HANDLE_KEY,
+ NEAREST_HANDLE_RIGHT,
} eGraphVertIndex;
/* Tolerance for absolute radius (in pixels) of the vert from the cursor to use */
// TODO: perhaps this should depend a bit on the size that the user set the vertices to be?
-#define GVERTSEL_TOL 10
+#define GVERTSEL_TOL 10
/* ....... */
@@ -1107,171 +1113,210 @@ typedef enum eGraphVertIndex {
// XXX also need to check for int-values only?
static bool fcurve_handle_sel_check(SpaceGraph *sipo, BezTriple *bezt)
{
- if (sipo->flag & SIPO_NOHANDLES) return 0;
- if ((sipo->flag & SIPO_SELVHANDLESONLY) && BEZT_ISSEL_ANY(bezt) == 0) return 0;
- return 1;
+ if (sipo->flag & SIPO_NOHANDLES)
+ return 0;
+ if ((sipo->flag & SIPO_SELVHANDLESONLY) && BEZT_ISSEL_ANY(bezt) == 0)
+ return 0;
+ return 1;
}
/* check if the given vertex is within bounds or not */
// TODO: should we return if we hit something?
-static void nearest_fcurve_vert_store(
- ListBase *matches, View2D *v2d, FCurve *fcu, eAnim_ChannelType ctype,
- BezTriple *bezt, FPoint *fpt, short hpoint, const int mval[2], float unit_scale, float offset)
+static void nearest_fcurve_vert_store(ListBase *matches,
+ View2D *v2d,
+ FCurve *fcu,
+ eAnim_ChannelType ctype,
+ BezTriple *bezt,
+ FPoint *fpt,
+ short hpoint,
+ const int mval[2],
+ float unit_scale,
+ float offset)
{
- /* Keyframes or Samples? */
- if (bezt) {
- int screen_co[2], dist;
-
- /* convert from data-space to screen coordinates
- * NOTE: hpoint+1 gives us 0,1,2 respectively for each handle,
- * needed to access the relevant vertex coordinates in the 3x3
- * 'vec' matrix
- */
- if (UI_view2d_view_to_region_clip(v2d,
- bezt->vec[hpoint + 1][0], (bezt->vec[hpoint + 1][1] + offset) * unit_scale,
- &screen_co[0], &screen_co[1]) &&
- /* check if distance from mouse cursor to vert in screen space is within tolerance */
- ((dist = len_v2v2_int(mval, screen_co)) <= GVERTSEL_TOL))
- {
- tNearestVertInfo *nvi = (tNearestVertInfo *)matches->last;
- bool replace = false;
-
- /* if there is already a point for the F-Curve, check if this point is closer than that was */
- if ((nvi) && (nvi->fcu == fcu)) {
- /* replace if we are closer, or if equal and that one wasn't selected but we are... */
- if ((nvi->dist > dist) || ((nvi->sel == 0) && BEZT_ISSEL_ANY(bezt)))
- replace = 1;
- }
- /* add new if not replacing... */
- if (replace == 0)
- nvi = MEM_callocN(sizeof(tNearestVertInfo), "Nearest Graph Vert Info - Bezt");
-
- /* store values */
- nvi->fcu = fcu;
- nvi->ctype = ctype;
-
- nvi->bezt = bezt;
- nvi->hpoint = hpoint;
- nvi->dist = dist;
-
- nvi->frame = bezt->vec[1][0]; /* currently in global time... */
-
- nvi->sel = BEZT_ISSEL_ANY(bezt); // XXX... should this use the individual verts instead?
-
- /* add to list of matches if appropriate... */
- if (replace == 0)
- BLI_addtail(matches, nvi);
- }
- }
- else if (fpt) {
- /* TODO... */
- }
+ /* Keyframes or Samples? */
+ if (bezt) {
+ int screen_co[2], dist;
+
+ /* convert from data-space to screen coordinates
+ * NOTE: hpoint+1 gives us 0,1,2 respectively for each handle,
+ * needed to access the relevant vertex coordinates in the 3x3
+ * 'vec' matrix
+ */
+ if (UI_view2d_view_to_region_clip(v2d,
+ bezt->vec[hpoint + 1][0],
+ (bezt->vec[hpoint + 1][1] + offset) * unit_scale,
+ &screen_co[0],
+ &screen_co[1]) &&
+ /* check if distance from mouse cursor to vert in screen space is within tolerance */
+ ((dist = len_v2v2_int(mval, screen_co)) <= GVERTSEL_TOL)) {
+ tNearestVertInfo *nvi = (tNearestVertInfo *)matches->last;
+ bool replace = false;
+
+ /* if there is already a point for the F-Curve, check if this point is closer than that was */
+ if ((nvi) && (nvi->fcu == fcu)) {
+ /* replace if we are closer, or if equal and that one wasn't selected but we are... */
+ if ((nvi->dist > dist) || ((nvi->sel == 0) && BEZT_ISSEL_ANY(bezt)))
+ replace = 1;
+ }
+ /* add new if not replacing... */
+ if (replace == 0)
+ nvi = MEM_callocN(sizeof(tNearestVertInfo), "Nearest Graph Vert Info - Bezt");
+
+ /* store values */
+ nvi->fcu = fcu;
+ nvi->ctype = ctype;
+
+ nvi->bezt = bezt;
+ nvi->hpoint = hpoint;
+ nvi->dist = dist;
+
+ nvi->frame = bezt->vec[1][0]; /* currently in global time... */
+
+ nvi->sel = BEZT_ISSEL_ANY(bezt); // XXX... should this use the individual verts instead?
+
+ /* add to list of matches if appropriate... */
+ if (replace == 0)
+ BLI_addtail(matches, nvi);
+ }
+ }
+ else if (fpt) {
+ /* TODO... */
+ }
}
/* helper for find_nearest_fcurve_vert() - build the list of nearest matches */
static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], ListBase *matches)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- SpaceGraph *sipo = (SpaceGraph *)ac->sl;
- View2D *v2d = &ac->ar->v2d;
- short mapping_flag = 0;
-
- /* get curves to search through
- * - if the option to only show keyframes that belong to selected F-Curves is enabled,
- * include the 'only selected' flag...
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- if (sipo->flag & SIPO_SELCUVERTSONLY) // FIXME: this should really be check for by the filtering code...
- filter |= ANIMFILTER_SEL;
- mapping_flag |= ANIM_get_normalization_flags(ac);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
- float offset;
- float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
-
- /* apply NLA mapping to all the keyframes */
- if (adt)
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
-
- if (fcu->bezt) {
- BezTriple *bezt1 = fcu->bezt, *prevbezt = NULL;
- int i;
-
- for (i = 0; i < fcu->totvert; i++, prevbezt = bezt1, bezt1++) {
- /* keyframe */
- nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_KEY, mval, unit_scale, offset);
-
- /* handles - only do them if they're visible */
- if (fcurve_handle_sel_check(sipo, bezt1) && (fcu->totvert > 1)) {
- /* first handle only visible if previous segment had handles */
- if ((!prevbezt && (bezt1->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
- nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_LEFT, mval, unit_scale, offset);
- }
-
- /* second handle only visible if this segment is bezier */
- if (bezt1->ipo == BEZT_IPO_BEZ) {
- nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_RIGHT, mval, unit_scale, offset);
- }
- }
- }
- }
- else if (fcu->fpt) {
- // TODO; do this for samples too
-
- }
-
- /* un-apply NLA mapping from all the keyframes */
- if (adt)
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
- }
-
- /* free channels */
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ SpaceGraph *sipo = (SpaceGraph *)ac->sl;
+ View2D *v2d = &ac->ar->v2d;
+ short mapping_flag = 0;
+
+ /* get curves to search through
+ * - if the option to only show keyframes that belong to selected F-Curves is enabled,
+ * include the 'only selected' flag...
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+ if (sipo->flag &
+ SIPO_SELCUVERTSONLY) // FIXME: this should really be check for by the filtering code...
+ filter |= ANIMFILTER_SEL;
+ mapping_flag |= ANIM_get_normalization_flags(ac);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+ float offset;
+ float unit_scale = ANIM_unit_mapping_get_factor(
+ ac->scene, ale->id, fcu, mapping_flag, &offset);
+
+ /* apply NLA mapping to all the keyframes */
+ if (adt)
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
+
+ if (fcu->bezt) {
+ BezTriple *bezt1 = fcu->bezt, *prevbezt = NULL;
+ int i;
+
+ for (i = 0; i < fcu->totvert; i++, prevbezt = bezt1, bezt1++) {
+ /* keyframe */
+ nearest_fcurve_vert_store(matches,
+ v2d,
+ fcu,
+ ale->type,
+ bezt1,
+ NULL,
+ NEAREST_HANDLE_KEY,
+ mval,
+ unit_scale,
+ offset);
+
+ /* handles - only do them if they're visible */
+ if (fcurve_handle_sel_check(sipo, bezt1) && (fcu->totvert > 1)) {
+ /* first handle only visible if previous segment had handles */
+ if ((!prevbezt && (bezt1->ipo == BEZT_IPO_BEZ)) ||
+ (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
+ nearest_fcurve_vert_store(matches,
+ v2d,
+ fcu,
+ ale->type,
+ bezt1,
+ NULL,
+ NEAREST_HANDLE_LEFT,
+ mval,
+ unit_scale,
+ offset);
+ }
+
+ /* second handle only visible if this segment is bezier */
+ if (bezt1->ipo == BEZT_IPO_BEZ) {
+ nearest_fcurve_vert_store(matches,
+ v2d,
+ fcu,
+ ale->type,
+ bezt1,
+ NULL,
+ NEAREST_HANDLE_RIGHT,
+ mval,
+ unit_scale,
+ offset);
+ }
+ }
+ }
+ }
+ else if (fcu->fpt) {
+ // TODO; do this for samples too
+ }
+
+ /* un-apply NLA mapping from all the keyframes */
+ if (adt)
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
+ }
+
+ /* free channels */
+ ANIM_animdata_freelist(&anim_data);
}
/* helper for find_nearest_fcurve_vert() - get the best match to use */
static tNearestVertInfo *get_best_nearest_fcurve_vert(ListBase *matches)
{
- tNearestVertInfo *nvi = NULL;
- short found = 0;
-
- /* abort if list is empty */
- if (BLI_listbase_is_empty(matches))
- return NULL;
-
- /* if list only has 1 item, remove it from the list and return */
- if (BLI_listbase_is_single(matches)) {
- /* need to remove from the list, otherwise it gets freed and then we can't return it */
- return BLI_pophead(matches);
- }
-
- /* try to find the first selected F-Curve vert, then take the one after it */
- for (nvi = matches->first; nvi; nvi = nvi->next) {
- /* which mode of search are we in: find first selected, or find vert? */
- if (found) {
- /* just take this vert now that we've found the selected one
- * - we'll need to remove this from the list so that it can be returned to the original caller
- */
- BLI_remlink(matches, nvi);
- return nvi;
- }
- else {
- /* if vert is selected, we've got what we want... */
- if (nvi->sel)
- found = 1;
- }
- }
-
- /* if we're still here, this means that we failed to find anything appropriate in the first pass,
- * so just take the first item now...
- */
- return BLI_pophead(matches);
+ tNearestVertInfo *nvi = NULL;
+ short found = 0;
+
+ /* abort if list is empty */
+ if (BLI_listbase_is_empty(matches))
+ return NULL;
+
+ /* if list only has 1 item, remove it from the list and return */
+ if (BLI_listbase_is_single(matches)) {
+ /* need to remove from the list, otherwise it gets freed and then we can't return it */
+ return BLI_pophead(matches);
+ }
+
+ /* try to find the first selected F-Curve vert, then take the one after it */
+ for (nvi = matches->first; nvi; nvi = nvi->next) {
+ /* which mode of search are we in: find first selected, or find vert? */
+ if (found) {
+ /* just take this vert now that we've found the selected one
+ * - we'll need to remove this from the list so that it can be returned to the original caller
+ */
+ BLI_remlink(matches, nvi);
+ return nvi;
+ }
+ else {
+ /* if vert is selected, we've got what we want... */
+ if (nvi->sel)
+ found = 1;
+ }
+ }
+
+ /* if we're still here, this means that we failed to find anything appropriate in the first pass,
+ * so just take the first item now...
+ */
+ return BLI_pophead(matches);
}
/* Find the nearest vertices (either a handle or the keyframe) that are nearest to the mouse cursor (in area coordinates)
@@ -1279,142 +1324,145 @@ static tNearestVertInfo *get_best_nearest_fcurve_vert(ListBase *matches)
*/
static tNearestVertInfo *find_nearest_fcurve_vert(bAnimContext *ac, const int mval[2])
{
- ListBase matches = {NULL, NULL};
- tNearestVertInfo *nvi;
+ ListBase matches = {NULL, NULL};
+ tNearestVertInfo *nvi;
- /* step 1: get the nearest verts */
- get_nearest_fcurve_verts_list(ac, mval, &matches);
+ /* step 1: get the nearest verts */
+ get_nearest_fcurve_verts_list(ac, mval, &matches);
- /* step 2: find the best vert */
- nvi = get_best_nearest_fcurve_vert(&matches);
+ /* step 2: find the best vert */
+ nvi = get_best_nearest_fcurve_vert(&matches);
- BLI_freelistN(&matches);
+ BLI_freelistN(&matches);
- /* return the best vert found */
- return nvi;
+ /* return the best vert found */
+ return nvi;
}
/* ------------------- */
/* option 1) select keyframe directly under mouse */
-static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_mode, short curves_only)
+static void mouse_graph_keys(bAnimContext *ac,
+ const int mval[2],
+ short select_mode,
+ short curves_only)
{
- SpaceGraph *sipo = (SpaceGraph *)ac->sl;
- tNearestVertInfo *nvi;
- BezTriple *bezt = NULL;
-
- /* find the beztriple that we're selecting, and the handle that was clicked on */
- nvi = find_nearest_fcurve_vert(ac, mval);
-
- /* check if anything to select */
- if (nvi == NULL)
- return;
-
- /* deselect all other curves? */
- if (select_mode == SELECT_REPLACE) {
- /* reset selection mode */
- select_mode = SELECT_ADD;
-
- /* deselect all other keyframes (+ F-Curves too) */
- deselect_graph_keys(ac, 0, SELECT_SUBTRACT, true);
-
- /* deselect other channels too, but only only do this if
- * selection of channel when the visibility of keyframes
- * doesn't depend on this
- */
- if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0)
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
- }
-
- /* if points can be selected on this F-Curve */
- // TODO: what about those with no keyframes?
- if ((curves_only == 0) && ((nvi->fcu->flag & FCURVE_PROTECTED) == 0)) {
- /* only if there's keyframe */
- if (nvi->bezt) {
- bezt = nvi->bezt; /* used to check bezt seletion is set */
- /* depends on selection mode */
- if (select_mode == SELECT_INVERT) {
- /* keyframe - invert select of all */
- if (nvi->hpoint == NEAREST_HANDLE_KEY) {
- if (BEZT_ISSEL_ANY(bezt)) {
- BEZT_DESEL_ALL(bezt);
- }
- else {
- BEZT_SEL_ALL(bezt);
- }
- }
-
- /* handles - toggle selection of relevant handle */
- else if (nvi->hpoint == NEAREST_HANDLE_LEFT) {
- /* toggle selection */
- bezt->f1 ^= SELECT;
- }
- else {
- /* toggle selection */
- bezt->f3 ^= SELECT;
- }
- }
- else {
- /* if the keyframe was clicked on, select all verts of given beztriple */
- if (nvi->hpoint == NEAREST_HANDLE_KEY) {
- BEZT_SEL_ALL(bezt);
- }
- /* otherwise, select the handle that applied */
- else if (nvi->hpoint == NEAREST_HANDLE_LEFT)
- bezt->f1 |= SELECT;
- else
- bezt->f3 |= SELECT;
- }
- }
- else if (nvi->fpt) {
- // TODO: need to handle sample points
- }
- }
- else {
- KeyframeEditFunc select_cb;
- KeyframeEditData ked;
-
- /* initialize keyframe editing data */
- memset(&ked, 0, sizeof(KeyframeEditData));
-
- /* set up BezTriple edit callbacks */
- select_cb = ANIM_editkeyframes_select(select_mode);
-
- /* select all keyframes */
- ANIM_fcurve_keyframes_loop(&ked, nvi->fcu, NULL, select_cb, NULL);
- }
-
- /* only change selection of channel when the visibility of keyframes doesn't depend on this */
- if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
- /* select or deselect curve? */
- if (bezt) {
- /* take selection status from item that got hit, to prevent flip/flop on channel
- * selection status when shift-selecting (i.e. "SELECT_INVERT") points
- */
- if (BEZT_ISSEL_ANY(bezt))
- nvi->fcu->flag |= FCURVE_SELECTED;
- else
- nvi->fcu->flag &= ~FCURVE_SELECTED;
- }
- else {
- /* didn't hit any channel, so just apply that selection mode to the curve's selection status */
- if (select_mode == SELECT_INVERT)
- nvi->fcu->flag ^= FCURVE_SELECTED;
- else if (select_mode == SELECT_ADD)
- nvi->fcu->flag |= FCURVE_SELECTED;
- }
- }
-
- /* set active F-Curve (NOTE: sync the filter flags with findnearest_fcurve_vert) */
- /* needs to be called with (sipo->flag & SIPO_SELCUVERTSONLY)
- * otherwise the active flag won't be set T26452. */
- if (nvi->fcu->flag & FCURVE_SELECTED) {
- int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, nvi->ctype);
- }
-
- /* free temp sample data for filtering */
- MEM_freeN(nvi);
+ SpaceGraph *sipo = (SpaceGraph *)ac->sl;
+ tNearestVertInfo *nvi;
+ BezTriple *bezt = NULL;
+
+ /* find the beztriple that we're selecting, and the handle that was clicked on */
+ nvi = find_nearest_fcurve_vert(ac, mval);
+
+ /* check if anything to select */
+ if (nvi == NULL)
+ return;
+
+ /* deselect all other curves? */
+ if (select_mode == SELECT_REPLACE) {
+ /* reset selection mode */
+ select_mode = SELECT_ADD;
+
+ /* deselect all other keyframes (+ F-Curves too) */
+ deselect_graph_keys(ac, 0, SELECT_SUBTRACT, true);
+
+ /* deselect other channels too, but only only do this if
+ * selection of channel when the visibility of keyframes
+ * doesn't depend on this
+ */
+ if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0)
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ }
+
+ /* if points can be selected on this F-Curve */
+ // TODO: what about those with no keyframes?
+ if ((curves_only == 0) && ((nvi->fcu->flag & FCURVE_PROTECTED) == 0)) {
+ /* only if there's keyframe */
+ if (nvi->bezt) {
+ bezt = nvi->bezt; /* used to check bezt seletion is set */
+ /* depends on selection mode */
+ if (select_mode == SELECT_INVERT) {
+ /* keyframe - invert select of all */
+ if (nvi->hpoint == NEAREST_HANDLE_KEY) {
+ if (BEZT_ISSEL_ANY(bezt)) {
+ BEZT_DESEL_ALL(bezt);
+ }
+ else {
+ BEZT_SEL_ALL(bezt);
+ }
+ }
+
+ /* handles - toggle selection of relevant handle */
+ else if (nvi->hpoint == NEAREST_HANDLE_LEFT) {
+ /* toggle selection */
+ bezt->f1 ^= SELECT;
+ }
+ else {
+ /* toggle selection */
+ bezt->f3 ^= SELECT;
+ }
+ }
+ else {
+ /* if the keyframe was clicked on, select all verts of given beztriple */
+ if (nvi->hpoint == NEAREST_HANDLE_KEY) {
+ BEZT_SEL_ALL(bezt);
+ }
+ /* otherwise, select the handle that applied */
+ else if (nvi->hpoint == NEAREST_HANDLE_LEFT)
+ bezt->f1 |= SELECT;
+ else
+ bezt->f3 |= SELECT;
+ }
+ }
+ else if (nvi->fpt) {
+ // TODO: need to handle sample points
+ }
+ }
+ else {
+ KeyframeEditFunc select_cb;
+ KeyframeEditData ked;
+
+ /* initialize keyframe editing data */
+ memset(&ked, 0, sizeof(KeyframeEditData));
+
+ /* set up BezTriple edit callbacks */
+ select_cb = ANIM_editkeyframes_select(select_mode);
+
+ /* select all keyframes */
+ ANIM_fcurve_keyframes_loop(&ked, nvi->fcu, NULL, select_cb, NULL);
+ }
+
+ /* only change selection of channel when the visibility of keyframes doesn't depend on this */
+ if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
+ /* select or deselect curve? */
+ if (bezt) {
+ /* take selection status from item that got hit, to prevent flip/flop on channel
+ * selection status when shift-selecting (i.e. "SELECT_INVERT") points
+ */
+ if (BEZT_ISSEL_ANY(bezt))
+ nvi->fcu->flag |= FCURVE_SELECTED;
+ else
+ nvi->fcu->flag &= ~FCURVE_SELECTED;
+ }
+ else {
+ /* didn't hit any channel, so just apply that selection mode to the curve's selection status */
+ if (select_mode == SELECT_INVERT)
+ nvi->fcu->flag ^= FCURVE_SELECTED;
+ else if (select_mode == SELECT_ADD)
+ nvi->fcu->flag |= FCURVE_SELECTED;
+ }
+ }
+
+ /* set active F-Curve (NOTE: sync the filter flags with findnearest_fcurve_vert) */
+ /* needs to be called with (sipo->flag & SIPO_SELCUVERTSONLY)
+ * otherwise the active flag won't be set T26452. */
+ if (nvi->fcu->flag & FCURVE_SELECTED) {
+ int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, nvi->ctype);
+ }
+
+ /* free temp sample data for filtering */
+ MEM_freeN(nvi);
}
/* Option 2) Selects all the keyframes on either side of the current frame
@@ -1424,67 +1472,67 @@ static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_m
/* Option 3) Selects all visible keyframes in the same frame as the mouse click */
static void graphkeys_mselect_column(bAnimContext *ac, const int mval[2], short select_mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- KeyframeEditFunc select_cb, ok_cb;
- KeyframeEditData ked;
- tNearestVertInfo *nvi;
- float selx = (float)ac->scene->r.cfra;
-
- /* find the beztriple that we're selecting, and the handle that was clicked on */
- nvi = find_nearest_fcurve_vert(ac, mval);
-
- /* check if anything to select */
- if (nvi == NULL)
- return;
-
- /* get frame number on which elements should be selected */
- // TODO: should we restrict to integer frames only?
- selx = nvi->frame;
-
- /* if select mode is replace, deselect all keyframes first */
- if (select_mode == SELECT_REPLACE) {
- /* reset selection mode to add to selection */
- select_mode = SELECT_ADD;
-
- /* - deselect all other keyframes, so that just the newly selected remain
- * - channels aren't deselected, since we don't re-select any as a consequence
- */
- deselect_graph_keys(ac, 0, SELECT_SUBTRACT, false);
- }
-
- /* initialize keyframe editing data */
- memset(&ked, 0, sizeof(KeyframeEditData));
-
- /* set up BezTriple edit callbacks */
- select_cb = ANIM_editkeyframes_select(select_mode);
- ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME);
-
- /* loop through all of the keys and select additional keyframes
- * based on the keys found to be selected above
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-
- /* set frame for validation callback to refer to */
- if (adt)
- ked.f1 = BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP);
- else
- ked.f1 = selx;
-
- /* select elements with frame number matching cfra */
- ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
- }
-
- /* free elements */
- MEM_freeN(nvi);
- BLI_freelistN(&ked.list);
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ KeyframeEditFunc select_cb, ok_cb;
+ KeyframeEditData ked;
+ tNearestVertInfo *nvi;
+ float selx = (float)ac->scene->r.cfra;
+
+ /* find the beztriple that we're selecting, and the handle that was clicked on */
+ nvi = find_nearest_fcurve_vert(ac, mval);
+
+ /* check if anything to select */
+ if (nvi == NULL)
+ return;
+
+ /* get frame number on which elements should be selected */
+ // TODO: should we restrict to integer frames only?
+ selx = nvi->frame;
+
+ /* if select mode is replace, deselect all keyframes first */
+ if (select_mode == SELECT_REPLACE) {
+ /* reset selection mode to add to selection */
+ select_mode = SELECT_ADD;
+
+ /* - deselect all other keyframes, so that just the newly selected remain
+ * - channels aren't deselected, since we don't re-select any as a consequence
+ */
+ deselect_graph_keys(ac, 0, SELECT_SUBTRACT, false);
+ }
+
+ /* initialize keyframe editing data */
+ memset(&ked, 0, sizeof(KeyframeEditData));
+
+ /* set up BezTriple edit callbacks */
+ select_cb = ANIM_editkeyframes_select(select_mode);
+ ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME);
+
+ /* loop through all of the keys and select additional keyframes
+ * based on the keys found to be selected above
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ /* set frame for validation callback to refer to */
+ if (adt)
+ ked.f1 = BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP);
+ else
+ ked.f1 = selx;
+
+ /* select elements with frame number matching cfra */
+ ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
+ }
+
+ /* free elements */
+ MEM_freeN(nvi);
+ BLI_freelistN(&ked.list);
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
@@ -1492,69 +1540,80 @@ static void graphkeys_mselect_column(bAnimContext *ac, const int mval[2], short
/* handle clicking */
static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bAnimContext ac;
- short selectmode;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* select mode is either replace (deselect all, then add) or add/extend */
- if (RNA_boolean_get(op->ptr, "extend"))
- selectmode = SELECT_INVERT;
- else
- selectmode = SELECT_REPLACE;
-
- /* figure out action to take */
- if (RNA_boolean_get(op->ptr, "column")) {
- /* select all keyframes in the same frame as the one that was under the mouse */
- graphkeys_mselect_column(&ac, event->mval, selectmode);
- }
- else if (RNA_boolean_get(op->ptr, "curves")) {
- /* select all keyframes in the same F-Curve as the one under the mouse */
- mouse_graph_keys(&ac, event->mval, selectmode, 1);
- }
- else {
- /* select keyframe under mouse */
- mouse_graph_keys(&ac, event->mval, selectmode, 0);
- }
-
- /* set notifier that keyframe selection (and also channel selection in some cases) has changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
-
- /* for tweak grab to work */
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ bAnimContext ac;
+ short selectmode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* select mode is either replace (deselect all, then add) or add/extend */
+ if (RNA_boolean_get(op->ptr, "extend"))
+ selectmode = SELECT_INVERT;
+ else
+ selectmode = SELECT_REPLACE;
+
+ /* figure out action to take */
+ if (RNA_boolean_get(op->ptr, "column")) {
+ /* select all keyframes in the same frame as the one that was under the mouse */
+ graphkeys_mselect_column(&ac, event->mval, selectmode);
+ }
+ else if (RNA_boolean_get(op->ptr, "curves")) {
+ /* select all keyframes in the same F-Curve as the one under the mouse */
+ mouse_graph_keys(&ac, event->mval, selectmode, 1);
+ }
+ else {
+ /* select keyframe under mouse */
+ mouse_graph_keys(&ac, event->mval, selectmode, 0);
+ }
+
+ /* set notifier that keyframe selection (and also channel selection in some cases) has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
+
+ /* for tweak grab to work */
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
}
void GRAPH_OT_clickselect(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Select Keyframes";
- ot->idname = "GRAPH_OT_clickselect";
- ot->description = "Select keyframes by clicking on them";
-
- /* callbacks */
- ot->invoke = graphkeys_clickselect_invoke;
- ot->poll = graphop_visible_keyframes_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select",
- "Toggle keyframe selection instead of leaving newly selected keyframes only"); // SHIFTKEY
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- prop = RNA_def_boolean(ot->srna, "column", 0, "Column Select",
- "Select all keyframes that occur on the same frame as the one under the mouse"); // ALTKEY
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- prop = RNA_def_boolean(ot->srna, "curves", 0, "Only Curves",
- "Select all the keyframes in the curve"); // CTRLKEY + ALTKEY
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Keyframes";
+ ot->idname = "GRAPH_OT_clickselect";
+ ot->description = "Select keyframes by clicking on them";
+
+ /* callbacks */
+ ot->invoke = graphkeys_clickselect_invoke;
+ ot->poll = graphop_visible_keyframes_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_boolean(
+ ot->srna,
+ "extend",
+ 0,
+ "Extend Select",
+ "Toggle keyframe selection instead of leaving newly selected keyframes only"); // SHIFTKEY
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(
+ ot->srna,
+ "column",
+ 0,
+ "Column Select",
+ "Select all keyframes that occur on the same frame as the one under the mouse"); // ALTKEY
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(ot->srna,
+ "curves",
+ 0,
+ "Only Curves",
+ "Select all the keyframes in the curve"); // CTRLKEY + ALTKEY
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ************************************************************************** */
diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c
index 6bef5072a78..1c3b4f1377b 100644
--- a/source/blender/editors/space_graph/graph_utils.c
+++ b/source/blender/editors/space_graph/graph_utils.c
@@ -21,7 +21,6 @@
* \ingroup spgraph
*/
-
#include <string.h>
#include <stdio.h>
#include <math.h>
@@ -39,16 +38,13 @@
#include "BKE_fcurve.h"
#include "BKE_screen.h"
-
#include "WM_api.h"
-
#include "ED_anim_api.h"
#include "ED_screen.h"
#include "UI_interface.h"
-
-#include "graph_intern.h" // own include
+#include "graph_intern.h" // own include
/* ************************************************************** */
/* Set Up Drivers Editor */
@@ -57,39 +53,39 @@
/* NOTE: Currently called from windowmanager (new drivers editor window) and RNA (mode switching) */
void ED_drivers_editor_init(bContext *C, ScrArea *sa)
{
- SpaceGraph *sipo = (SpaceGraph *)sa->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");
-
- ar_props->flag &= ~RGN_FLAG_HIDDEN;
- /* XXX: Adjust width of this too? */
-
- ED_region_visibility_change_update(C, ar_props);
- }
- else {
- printf("%s: Couldn't find properties region for Drivers Editor - %p\n", __func__, sa);
- }
-
- /* 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) {
- /* 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;
-
- ar_main->v2d.cur = ar_main->v2d.tot;
- }
+ SpaceGraph *sipo = (SpaceGraph *)sa->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");
+
+ ar_props->flag &= ~RGN_FLAG_HIDDEN;
+ /* XXX: Adjust width of this too? */
+
+ ED_region_visibility_change_update(C, ar_props);
+ }
+ else {
+ printf("%s: Couldn't find properties region for Drivers Editor - %p\n", __func__, sa);
+ }
+
+ /* 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) {
+ /* 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;
+
+ ar_main->v2d.cur = ar_main->v2d.tot;
+ }
}
/* ************************************************************** */
@@ -103,25 +99,25 @@ void ED_drivers_editor_init(bContext *C, ScrArea *sa)
*/
bAnimListElem *get_active_fcurve_channel(bAnimContext *ac)
{
- ListBase anim_data = {NULL, NULL};
- int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_ACTIVE);
- size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ ListBase anim_data = {NULL, NULL};
+ int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_ACTIVE);
+ size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* We take the first F-Curve only, since some other ones may have had 'active' flag set
- * if they were from linked data.
- */
- if (items) {
- bAnimListElem *ale = (bAnimListElem *)anim_data.first;
+ /* We take the first F-Curve only, since some other ones may have had 'active' flag set
+ * if they were from linked data.
+ */
+ if (items) {
+ bAnimListElem *ale = (bAnimListElem *)anim_data.first;
- /* remove first item from list, then free the rest of the list and return the stored one */
- BLI_remlink(&anim_data, ale);
- ANIM_animdata_freelist(&anim_data);
+ /* remove first item from list, then free the rest of the list and return the stored one */
+ BLI_remlink(&anim_data, ale);
+ ANIM_animdata_freelist(&anim_data);
- return ale;
- }
+ return ale;
+ }
- /* no active F-Curve */
- return NULL;
+ /* no active F-Curve */
+ return NULL;
}
/* ************************************************************** */
@@ -130,171 +126,171 @@ bAnimListElem *get_active_fcurve_channel(bAnimContext *ac)
/* Check if there are any visible keyframes (for selection tools) */
bool graphop_visible_keyframes_poll(bContext *C)
{
- bAnimContext ac;
- bAnimListElem *ale;
- ListBase anim_data = {NULL, NULL};
- ScrArea *sa = 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))
- return 0;
-
- /* try to init Anim-Context stuff ourselves and check */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return 0;
-
- /* loop over the visible (selection doesn't matter) F-Curves, and see if they're suitable
- * stopping on the first successful match
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE);
- items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- if (items == 0)
- return 0;
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->data;
-
- /* visible curves for selection must fulfill the following criteria:
- * - it has bezier keyframes
- * - F-Curve modifiers do not interfere with the result too much
- * (i.e. the modifier-control drawing check returns false)
- */
- if (fcu->bezt == NULL)
- continue;
- if (fcurve_are_keyframes_usable(fcu)) {
- found = 1;
- break;
- }
- }
-
- /* cleanup and return findings */
- ANIM_animdata_freelist(&anim_data);
- return found;
+ bAnimContext ac;
+ bAnimListElem *ale;
+ ListBase anim_data = {NULL, NULL};
+ ScrArea *sa = 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))
+ return 0;
+
+ /* try to init Anim-Context stuff ourselves and check */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return 0;
+
+ /* loop over the visible (selection doesn't matter) F-Curves, and see if they're suitable
+ * stopping on the first successful match
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE);
+ items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ if (items == 0)
+ return 0;
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->data;
+
+ /* visible curves for selection must fulfill the following criteria:
+ * - it has bezier keyframes
+ * - F-Curve modifiers do not interfere with the result too much
+ * (i.e. the modifier-control drawing check returns false)
+ */
+ if (fcu->bezt == NULL)
+ continue;
+ if (fcurve_are_keyframes_usable(fcu)) {
+ found = 1;
+ break;
+ }
+ }
+
+ /* cleanup and return findings */
+ ANIM_animdata_freelist(&anim_data);
+ return found;
}
/* Check if there are any visible + editable keyframes (for editing tools) */
bool graphop_editable_keyframes_poll(bContext *C)
{
- bAnimContext ac;
- bAnimListElem *ale;
- ListBase anim_data = {NULL, NULL};
- ScrArea *sa = 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))
- return 0;
-
- /* try to init Anim-Context stuff ourselves and check */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return 0;
-
- /* loop over the editable F-Curves, and see if they're suitable
- * stopping on the first successful match
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
- items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- if (items == 0)
- return 0;
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->data;
-
- /* editable curves must fulfill the following criteria:
- * - it has bezier keyframes
- * - it must not be protected from editing (this is already checked for with the edit flag
- * - F-Curve modifiers do not interfere with the result too much
- * (i.e. the modifier-control drawing check returns false)
- */
- if (fcu->bezt == NULL)
- continue;
- if (fcurve_is_keyframable(fcu)) {
- found = 1;
- break;
- }
- }
-
- /* cleanup and return findings */
- ANIM_animdata_freelist(&anim_data);
- return found;
+ bAnimContext ac;
+ bAnimListElem *ale;
+ ListBase anim_data = {NULL, NULL};
+ ScrArea *sa = 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))
+ return 0;
+
+ /* try to init Anim-Context stuff ourselves and check */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return 0;
+
+ /* loop over the editable F-Curves, and see if they're suitable
+ * stopping on the first successful match
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
+ items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ if (items == 0)
+ return 0;
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->data;
+
+ /* editable curves must fulfill the following criteria:
+ * - it has bezier keyframes
+ * - it must not be protected from editing (this is already checked for with the edit flag
+ * - F-Curve modifiers do not interfere with the result too much
+ * (i.e. the modifier-control drawing check returns false)
+ */
+ if (fcu->bezt == NULL)
+ continue;
+ if (fcurve_is_keyframable(fcu)) {
+ found = 1;
+ break;
+ }
+ }
+
+ /* cleanup and return findings */
+ ANIM_animdata_freelist(&anim_data);
+ return found;
}
/* has active F-Curve that's editable */
bool graphop_active_fcurve_poll(bContext *C)
{
- bAnimContext ac;
- bAnimListElem *ale;
- ScrArea *sa = 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))
- return 0;
-
- /* try to init Anim-Context stuff ourselves and check */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return 0;
-
- /* try to get the Active F-Curve */
- ale = get_active_fcurve_channel(&ac);
- if (ale == NULL)
- return 0;
-
- /* do we have a suitable F-Curves?
- * - For most cases, NLA Control Curves are sufficiently similar to NLA curves to serve this role too.
- * Under the hood, they are F-Curves too. The only problems which will arise here are if these need to be
- * in an Action too (but drivers would then also be affected!)
- */
- has_fcurve = ((ale->data) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE));
- if (has_fcurve) {
- FCurve *fcu = (FCurve *)ale->data;
- has_fcurve = (fcu->flag & FCURVE_VISIBLE) != 0;
- }
-
- /* free temp data... */
- MEM_freeN(ale);
-
- /* return success */
- return has_fcurve;
+ bAnimContext ac;
+ bAnimListElem *ale;
+ ScrArea *sa = 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))
+ return 0;
+
+ /* try to init Anim-Context stuff ourselves and check */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return 0;
+
+ /* try to get the Active F-Curve */
+ ale = get_active_fcurve_channel(&ac);
+ if (ale == NULL)
+ return 0;
+
+ /* do we have a suitable F-Curves?
+ * - For most cases, NLA Control Curves are sufficiently similar to NLA curves to serve this role too.
+ * Under the hood, they are F-Curves too. The only problems which will arise here are if these need to be
+ * in an Action too (but drivers would then also be affected!)
+ */
+ has_fcurve = ((ale->data) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE));
+ if (has_fcurve) {
+ FCurve *fcu = (FCurve *)ale->data;
+ has_fcurve = (fcu->flag & FCURVE_VISIBLE) != 0;
+ }
+
+ /* free temp data... */
+ MEM_freeN(ale);
+
+ /* return success */
+ return has_fcurve;
}
/* has selected F-Curve that's editable */
bool graphop_selected_fcurve_poll(bContext *C)
{
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- ScrArea *sa = 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))
- return 0;
-
- /* try to init Anim-Context stuff ourselves and check */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return 0;
-
- /* get the editable + selected F-Curves, and as long as we got some, we can return
- * NOTE: curve-visible flag isn't included, otherwise selecting a curve via list to edit is too cumbersome
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT);
- items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- if (items == 0)
- return 0;
-
- /* cleanup and return findings */
- ANIM_animdata_freelist(&anim_data);
- return 1;
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ ScrArea *sa = 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))
+ return 0;
+
+ /* try to init Anim-Context stuff ourselves and check */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return 0;
+
+ /* get the editable + selected F-Curves, and as long as we got some, we can return
+ * NOTE: curve-visible flag isn't included, otherwise selecting a curve via list to edit is too cumbersome
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT);
+ items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ if (items == 0)
+ return 0;
+
+ /* cleanup and return findings */
+ ANIM_animdata_freelist(&anim_data);
+ return 1;
}
/* ************************************************************** */
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index 9892660c59c..d03431468d8 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -21,7 +21,6 @@
* \ingroup spgraph
*/
-
#include <string.h>
#include <stdio.h>
@@ -59,848 +58,865 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "graph_intern.h" // own include
+#include "graph_intern.h" // own include
/* ******************** manage regions ********************* */
ARegion *graph_has_buttons_region(ScrArea *sa)
{
- ARegion *ar, *arnew;
+ ARegion *ar, *arnew;
- ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
- if (ar) return ar;
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
+ if (ar)
+ return ar;
- /* add subdiv level; after main */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ /* add subdiv level; after main */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- /* is error! */
- if (ar == NULL) return NULL;
+ /* is error! */
+ if (ar == NULL)
+ return NULL;
- arnew = MEM_callocN(sizeof(ARegion), "buttons for graph");
+ arnew = MEM_callocN(sizeof(ARegion), "buttons for graph");
- BLI_insertlinkafter(&sa->regionbase, ar, arnew);
- arnew->regiontype = RGN_TYPE_UI;
- arnew->alignment = RGN_ALIGN_RIGHT;
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype = RGN_TYPE_UI;
+ arnew->alignment = RGN_ALIGN_RIGHT;
- arnew->flag = RGN_FLAG_HIDDEN;
+ arnew->flag = RGN_FLAG_HIDDEN;
- return arnew;
+ return arnew;
}
-
/* ******************** default callbacks for ipo space ***************** */
static SpaceLink *graph_new(const ScrArea *UNUSED(sa), const Scene *scene)
{
- ARegion *ar;
- SpaceGraph *sipo;
+ ARegion *ar;
+ SpaceGraph *sipo;
- /* Graph Editor - general stuff */
- sipo = MEM_callocN(sizeof(SpaceGraph), "init graphedit");
- sipo->spacetype = SPACE_GRAPH;
+ /* Graph Editor - general stuff */
+ sipo = MEM_callocN(sizeof(SpaceGraph), "init graphedit");
+ sipo->spacetype = SPACE_GRAPH;
- sipo->autosnap = SACTSNAP_FRAME;
+ sipo->autosnap = SACTSNAP_FRAME;
- /* allocate DopeSheet data for Graph Editor */
- sipo->ads = MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
- sipo->ads->source = (ID *)scene;
+ /* allocate DopeSheet data for Graph Editor */
+ sipo->ads = MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
+ sipo->ads->source = (ID *)scene;
- /* settings for making it easier by default to just see what you're interested in tweaking */
- sipo->ads->filterflag |= ADS_FILTER_ONLYSEL;
- sipo->flag |= SIPO_SELVHANDLESONLY;
+ /* settings for making it easier by default to just see what you're interested in tweaking */
+ sipo->ads->filterflag |= ADS_FILTER_ONLYSEL;
+ sipo->flag |= SIPO_SELVHANDLESONLY;
- /* header */
- ar = MEM_callocN(sizeof(ARegion), "header for graphedit");
+ /* header */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_HEADER;
+ ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
- /* channels */
- ar = MEM_callocN(sizeof(ARegion), "channels region for graphedit");
+ /* channels */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_CHANNELS;
+ ar->alignment = RGN_ALIGN_LEFT;
- ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
+ ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
- /* ui buttons */
- ar = MEM_callocN(sizeof(ARegion), "buttons region for graphedit");
+ /* ui buttons */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_UI;
+ ar->alignment = RGN_ALIGN_RIGHT;
+ ar->flag = RGN_FLAG_HIDDEN;
- /* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for graphedit");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for graphedit");
- BLI_addtail(&sipo->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&sipo->regionbase, ar);
+ ar->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;
+ 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;
- ar->v2d.cur = ar->v2d.tot;
+ ar->v2d.cur = ar->v2d.tot;
- ar->v2d.min[0] = FLT_MIN;
- ar->v2d.min[1] = FLT_MIN;
+ ar->v2d.min[0] = FLT_MIN;
+ ar->v2d.min[1] = FLT_MIN;
- ar->v2d.max[0] = MAXFRAMEF;
- ar->v2d.max[1] = FLT_MAX;
+ ar->v2d.max[0] = MAXFRAMEF;
+ ar->v2d.max[1] = FLT_MAX;
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
- ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL);
+ ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
+ ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL);
- ar->v2d.keeptot = 0;
+ ar->v2d.keeptot = 0;
- return (SpaceLink *)sipo;
+ return (SpaceLink *)sipo;
}
/* not spacelink itself */
static void graph_free(SpaceLink *sl)
{
- SpaceGraph *si = (SpaceGraph *)sl;
+ SpaceGraph *si = (SpaceGraph *)sl;
- if (si->ads) {
- BLI_freelistN(&si->ads->chanbase);
- MEM_freeN(si->ads);
- }
+ if (si->ads) {
+ BLI_freelistN(&si->ads->chanbase);
+ MEM_freeN(si->ads);
+ }
- if (si->runtime.ghost_curves.first) {
- free_fcurves(&si->runtime.ghost_curves);
- }
+ if (si->runtime.ghost_curves.first) {
+ free_fcurves(&si->runtime.ghost_curves);
+ }
}
-
/* spacetype; init callback */
static void graph_init(struct wmWindowManager *wm, ScrArea *sa)
{
- SpaceGraph *sipo = (SpaceGraph *)sa->spacedata.first;
-
- /* init dopesheet data if non-existent (i.e. for old files) */
- if (sipo->ads == NULL) {
- sipo->ads = MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
- sipo->ads->source = (ID *)WM_window_get_active_scene(wm->winactive);
- }
-
- /* force immediate init of any invalid F-Curve colors */
- /* XXX: but, don't do SIPO_TEMP_NEEDCHANSYNC (i.e. channel select state sync)
- * 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);
+ SpaceGraph *sipo = (SpaceGraph *)sa->spacedata.first;
+
+ /* init dopesheet data if non-existent (i.e. for old files) */
+ if (sipo->ads == NULL) {
+ sipo->ads = MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
+ sipo->ads->source = (ID *)WM_window_get_active_scene(wm->winactive);
+ }
+
+ /* force immediate init of any invalid F-Curve colors */
+ /* XXX: but, don't do SIPO_TEMP_NEEDCHANSYNC (i.e. channel select state sync)
+ * 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);
}
static SpaceLink *graph_duplicate(SpaceLink *sl)
{
- SpaceGraph *sipon = MEM_dupallocN(sl);
+ SpaceGraph *sipon = MEM_dupallocN(sl);
- /* clear or remove stuff from old */
- BLI_duplicatelist(&sipon->runtime.ghost_curves, &((SpaceGraph *)sl)->runtime.ghost_curves);
- sipon->ads = MEM_dupallocN(sipon->ads);
+ /* clear or remove stuff from old */
+ BLI_duplicatelist(&sipon->runtime.ghost_curves, &((SpaceGraph *)sl)->runtime.ghost_curves);
+ sipon->ads = MEM_dupallocN(sipon->ads);
- return (SpaceLink *)sipon;
+ return (SpaceLink *)sipon;
}
/* add handlers, stuff you only do once or on area/region changes */
static void graph_main_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
- /* own keymap */
- keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor", SPACE_GRAPH, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor Generic", SPACE_GRAPH, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ /* own keymap */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor", SPACE_GRAPH, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor Generic", SPACE_GRAPH, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
}
static void graph_main_region_draw(const bContext *C, ARegion *ar)
{
- /* 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;
- View2DGrid *grid;
- View2DScrollers *scrollers;
- float col[3];
- short unitx = 0, unity = V2D_UNIT_VALUES, cfra_flag = 0;
-
- /* clear and setup matrix */
- UI_GetThemeColor3fv(TH_BACK, col);
- GPU_clear_color(col[0], col[1], col[2], 0.0);
- GPU_clear(GPU_COLOR_BIT);
-
- UI_view2d_view_ortho(v2d);
-
- /* grid */
- unitx = ((sipo->mode == SIPO_MODE_ANIMATION) && (sipo->flag & SIPO_DRAWTIME)) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMESCALE;
- grid = UI_view2d_grid_calc(CTX_data_scene(C), v2d, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP, ar->winx, ar->winy);
- UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL);
-
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
-
- /* start and end frame (in F-Curve mode only) */
- if (sipo->mode != SIPO_MODE_DRIVERS) {
- ANIM_draw_framerange(scene, v2d);
- }
-
- /* draw data */
- if (ANIM_animdata_get_context(C, &ac)) {
- /* draw ghost curves */
- graph_draw_ghost_curves(&ac, sipo, ar);
-
- /* draw curves twice - unselected, then selected, so that the are fewer occlusion problems */
- graph_draw_curves(&ac, sipo, ar, grid, 0);
- graph_draw_curves(&ac, sipo, ar, grid, 1);
-
- /* XXX the slow way to set tot rect... but for nice sliders needed (ton) */
- get_graph_keyframe_extents(&ac, &v2d->tot.xmin, &v2d->tot.xmax, &v2d->tot.ymin, &v2d->tot.ymax, false, true);
- /* extra offset so that these items are visible */
- v2d->tot.xmin -= 10.0f;
- v2d->tot.xmax += 10.0f;
- }
-
- /* only free grid after drawing data, as we need to use it to determine sampling rate */
- UI_view2d_grid_free(grid);
-
- if (((sipo->flag & SIPO_NODRAWCURSOR) == 0) || (sipo->mode == SIPO_MODE_DRIVERS)) {
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* horizontal component of value-cursor (value line before the current frame line) */
- if ((sipo->flag & SIPO_NODRAWCURSOR) == 0) {
- float y = sipo->cursorVal;
-
- /* Draw a green line to indicate the cursor value */
- immUniformThemeColorShadeAlpha(TH_CFRAME, -10, -50);
- GPU_blend(true);
- GPU_line_width(2.0);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, v2d->cur.xmin, y);
- immVertex2f(pos, v2d->cur.xmax, y);
- immEnd();
-
- GPU_blend(false);
- }
-
- /* current frame or vertical component of vertical component of the cursor */
- if (sipo->mode == SIPO_MODE_DRIVERS) {
- /* cursor x-value */
- float x = sipo->cursorTime;
-
- /* to help differentiate this from the current frame,
- * draw slightly darker like the horizontal one */
- immUniformThemeColorShadeAlpha(TH_CFRAME, -40, -50);
- GPU_blend(true);
- GPU_line_width(2.0);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, x, v2d->cur.ymin);
- immVertex2f(pos, x, v2d->cur.ymax);
- immEnd();
-
- GPU_blend(false);
- }
-
- immUnbindProgram();
- }
-
- if (sipo->mode != SIPO_MODE_DRIVERS) {
- /* current frame */
- if (sipo->flag & SIPO_DRAWTIME) 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 (sipo->flag & SIPO_MARKER_LINES) {
- marker_draw_flag |= DRAW_MARKERS_LINES;
- }
- ED_markers_draw(C, marker_draw_flag);
-
- /* preview range */
- UI_view2d_view_ortho(v2d);
- ANIM_draw_previewrange(C, v2d, 0);
-
- /* callback */
- UI_view2d_view_ortho(v2d);
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
-
- /* reset view matrix */
- UI_view2d_view_restore(C);
-
- /* scrollers */
- // FIXME: args for scrollers depend on the type of data being shown...
- scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
-
- /* draw current frame number-indicator on top of scrollers */
- if ((sipo->mode != SIPO_MODE_DRIVERS) && ((sipo->flag & SIPO_NODRAWCFRANUM) == 0)) {
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- ANIM_draw_cfra_number(C, v2d, cfra_flag);
- }
+ /* 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;
+ View2DGrid *grid;
+ View2DScrollers *scrollers;
+ float col[3];
+ short unitx = 0, unity = V2D_UNIT_VALUES, cfra_flag = 0;
+
+ /* clear and setup matrix */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ GPU_clear_color(col[0], col[1], col[2], 0.0);
+ GPU_clear(GPU_COLOR_BIT);
+
+ UI_view2d_view_ortho(v2d);
+
+ /* grid */
+ unitx = ((sipo->mode == SIPO_MODE_ANIMATION) && (sipo->flag & SIPO_DRAWTIME)) ?
+ V2D_UNIT_SECONDS :
+ V2D_UNIT_FRAMESCALE;
+ grid = UI_view2d_grid_calc(CTX_data_scene(C),
+ v2d,
+ unitx,
+ V2D_GRID_NOCLAMP,
+ unity,
+ V2D_GRID_NOCLAMP,
+ ar->winx,
+ ar->winy);
+ UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL);
+
+ ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
+
+ /* start and end frame (in F-Curve mode only) */
+ if (sipo->mode != SIPO_MODE_DRIVERS) {
+ ANIM_draw_framerange(scene, v2d);
+ }
+
+ /* draw data */
+ if (ANIM_animdata_get_context(C, &ac)) {
+ /* draw ghost curves */
+ graph_draw_ghost_curves(&ac, sipo, ar);
+
+ /* draw curves twice - unselected, then selected, so that the are fewer occlusion problems */
+ graph_draw_curves(&ac, sipo, ar, grid, 0);
+ graph_draw_curves(&ac, sipo, ar, grid, 1);
+
+ /* XXX the slow way to set tot rect... but for nice sliders needed (ton) */
+ get_graph_keyframe_extents(
+ &ac, &v2d->tot.xmin, &v2d->tot.xmax, &v2d->tot.ymin, &v2d->tot.ymax, false, true);
+ /* extra offset so that these items are visible */
+ v2d->tot.xmin -= 10.0f;
+ v2d->tot.xmax += 10.0f;
+ }
+
+ /* only free grid after drawing data, as we need to use it to determine sampling rate */
+ UI_view2d_grid_free(grid);
+
+ if (((sipo->flag & SIPO_NODRAWCURSOR) == 0) || (sipo->mode == SIPO_MODE_DRIVERS)) {
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* horizontal component of value-cursor (value line before the current frame line) */
+ if ((sipo->flag & SIPO_NODRAWCURSOR) == 0) {
+ float y = sipo->cursorVal;
+
+ /* Draw a green line to indicate the cursor value */
+ immUniformThemeColorShadeAlpha(TH_CFRAME, -10, -50);
+ GPU_blend(true);
+ GPU_line_width(2.0);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, v2d->cur.xmin, y);
+ immVertex2f(pos, v2d->cur.xmax, y);
+ immEnd();
+
+ GPU_blend(false);
+ }
+
+ /* current frame or vertical component of vertical component of the cursor */
+ if (sipo->mode == SIPO_MODE_DRIVERS) {
+ /* cursor x-value */
+ float x = sipo->cursorTime;
+
+ /* to help differentiate this from the current frame,
+ * draw slightly darker like the horizontal one */
+ immUniformThemeColorShadeAlpha(TH_CFRAME, -40, -50);
+ GPU_blend(true);
+ GPU_line_width(2.0);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, x, v2d->cur.ymin);
+ immVertex2f(pos, x, v2d->cur.ymax);
+ immEnd();
+
+ GPU_blend(false);
+ }
+
+ immUnbindProgram();
+ }
+
+ if (sipo->mode != SIPO_MODE_DRIVERS) {
+ /* current frame */
+ if (sipo->flag & SIPO_DRAWTIME)
+ 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 (sipo->flag & SIPO_MARKER_LINES) {
+ marker_draw_flag |= DRAW_MARKERS_LINES;
+ }
+ ED_markers_draw(C, marker_draw_flag);
+
+ /* preview range */
+ UI_view2d_view_ortho(v2d);
+ ANIM_draw_previewrange(C, v2d, 0);
+
+ /* callback */
+ UI_view2d_view_ortho(v2d);
+ ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ // FIXME: args for scrollers depend on the type of data being shown...
+ scrollers = UI_view2d_scrollers_calc(
+ C, v2d, NULL, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+
+ /* draw current frame number-indicator on top of scrollers */
+ if ((sipo->mode != SIPO_MODE_DRIVERS) && ((sipo->flag & SIPO_NODRAWCFRANUM) == 0)) {
+ UI_view2d_view_orthoSpecial(ar, v2d, 1);
+ ANIM_draw_cfra_number(C, v2d, cfra_flag);
+ }
}
static void graph_channel_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- /* make sure we keep the hide flags */
- ar->v2d.scroll |= V2D_SCROLL_RIGHT;
+ /* make sure we keep the hide flags */
+ ar->v2d.scroll |= V2D_SCROLL_RIGHT;
- /* prevent any noise of past */
- ar->v2d.scroll &= ~(V2D_SCROLL_LEFT | V2D_SCROLL_TOP | V2D_SCROLL_BOTTOM);
+ /* prevent any noise of past */
+ ar->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;
+ ar->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
+ ar->v2d.scroll |= V2D_SCROLL_VERTICAL_HIDE;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
- /* own keymap */
- keymap = WM_keymap_ensure(wm->defaultconf, "Animation Channels", 0, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor Generic", SPACE_GRAPH, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ /* own keymap */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Animation Channels", 0, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor Generic", SPACE_GRAPH, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
}
static void graph_channel_region_draw(const bContext *C, ARegion *ar)
{
- bAnimContext ac;
- View2D *v2d = &ar->v2d;
- View2DScrollers *scrollers;
- float col[3];
-
- /* clear and setup matrix */
- UI_GetThemeColor3fv(TH_BACK, col);
- GPU_clear_color(col[0], col[1], col[2], 0.0);
- GPU_clear(GPU_COLOR_BIT);
-
- UI_view2d_view_ortho(v2d);
-
- /* draw channels */
- if (ANIM_animdata_get_context(C, &ac)) {
- graph_draw_channel_names((bContext *)C, &ac, ar);
- }
-
- /* reset view matrix */
- UI_view2d_view_restore(C);
-
- /* scrollers */
- scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
+ bAnimContext ac;
+ View2D *v2d = &ar->v2d;
+ View2DScrollers *scrollers;
+ float col[3];
+
+ /* clear and setup matrix */
+ UI_GetThemeColor3fv(TH_BACK, col);
+ GPU_clear_color(col[0], col[1], col[2], 0.0);
+ GPU_clear(GPU_COLOR_BIT);
+
+ UI_view2d_view_ortho(v2d);
+
+ /* draw channels */
+ if (ANIM_animdata_get_context(C, &ac)) {
+ graph_draw_channel_names((bContext *)C, &ac, ar);
+ }
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ scrollers = UI_view2d_scrollers_calc(
+ C, v2d, NULL, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
}
/* add handlers, stuff you only do once or on area/region changes */
static void graph_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
- ED_region_header_init(ar);
+ ED_region_header_init(ar);
}
static void graph_header_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_header(C, ar);
+ ED_region_header(C, ar);
}
/* add handlers, stuff you only do once or on area/region changes */
static void graph_buttons_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, ar);
- keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor Generic", SPACE_GRAPH, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor Generic", SPACE_GRAPH, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
static void graph_buttons_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, ar);
}
-static void graph_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void graph_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_ANIMATION:
- ED_region_tag_redraw(ar);
- break;
- case NC_SCENE:
- switch (wmn->data) {
- case ND_RENDER_OPTIONS:
- case ND_OB_ACTIVE:
- case ND_FRAME:
- case ND_FRAME_RANGE:
- case ND_MARKERS:
- ED_region_tag_redraw(ar);
- break;
- case ND_SEQUENCER:
- if (wmn->action == NA_SELECTED)
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_OBJECT:
- switch (wmn->data) {
- case ND_BONE_ACTIVE:
- case ND_BONE_SELECT:
- case ND_KEYS:
- ED_region_tag_redraw(ar);
- break;
- case ND_MODIFIER:
- if (wmn->action == NA_RENAME)
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_NODE:
- switch (wmn->action) {
- case NA_EDITED:
- case NA_SELECTED:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_ID:
- if (wmn->action == NA_RENAME)
- ED_region_tag_redraw(ar);
- break;
- case NC_SCREEN:
- if (ELEM(wmn->data, ND_LAYER)) {
- ED_region_tag_redraw(ar);
- }
- break;
- default:
- if (wmn->data == ND_KEYS)
- ED_region_tag_redraw(ar);
- break;
-
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_ANIMATION:
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_RENDER_OPTIONS:
+ case ND_OB_ACTIVE:
+ case ND_FRAME:
+ case ND_FRAME_RANGE:
+ case ND_MARKERS:
+ ED_region_tag_redraw(ar);
+ break;
+ case ND_SEQUENCER:
+ if (wmn->action == NA_SELECTED)
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch (wmn->data) {
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_KEYS:
+ ED_region_tag_redraw(ar);
+ break;
+ case ND_MODIFIER:
+ if (wmn->action == NA_RENAME)
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_NODE:
+ switch (wmn->action) {
+ case NA_EDITED:
+ case NA_SELECTED:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_ID:
+ if (wmn->action == NA_RENAME)
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_SCREEN:
+ if (ELEM(wmn->data, ND_LAYER)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ default:
+ if (wmn->data == ND_KEYS)
+ ED_region_tag_redraw(ar);
+ break;
+ }
}
-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 wmMsgBus *mbus)
+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 wmMsgBus *mbus)
{
- PointerRNA ptr;
- RNA_pointer_create(&screen->id, &RNA_SpaceGraphEditor, sa->spacedata.first, &ptr);
-
- wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
- .notify = ED_region_do_msg_notify_tag_redraw,
- };
-
- /* Timeline depends on scene properties. */
- {
- bool use_preview = (scene->r.flag & SCER_PRV_RANGE);
- extern PropertyRNA rna_Scene_frame_start;
- extern PropertyRNA rna_Scene_frame_end;
- extern PropertyRNA rna_Scene_frame_preview_start;
- extern PropertyRNA rna_Scene_frame_preview_end;
- extern PropertyRNA rna_Scene_use_preview_range;
- extern PropertyRNA rna_Scene_frame_current;
- const PropertyRNA *props[] = {
- use_preview ? &rna_Scene_frame_preview_start : &rna_Scene_frame_start,
- use_preview ? &rna_Scene_frame_preview_end : &rna_Scene_frame_end,
- &rna_Scene_use_preview_range,
- &rna_Scene_frame_current,
- };
-
- PointerRNA idptr;
- RNA_id_pointer_create(&scene->id, &idptr);
-
- for (int i = 0; i < ARRAY_SIZE(props); i++) {
- WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__);
- }
- }
-
- /* All dopesheet filter settings, etc. affect the drawing of this editor,
- * also same applies for all animation-related datatypes that may appear here,
- * so just whitelist the entire structs for updates
- */
- {
- wmMsgParams_RNA msg_key_params = {{{0}}};
- StructRNA *type_array[] = {
- &RNA_DopeSheet, /* dopesheet filters */
-
- &RNA_ActionGroup, /* channel groups */
- &RNA_FCurve, /* F-Curve */
- &RNA_Keyframe,
- &RNA_FCurveSample,
-
- &RNA_FModifier, /* F-Modifiers (XXX: Why can't we just do all subclasses too?) */
- &RNA_FModifierCycles,
- &RNA_FModifierEnvelope,
- &RNA_FModifierEnvelopeControlPoint,
- &RNA_FModifierFunctionGenerator,
- &RNA_FModifierGenerator,
- &RNA_FModifierLimits,
- &RNA_FModifierNoise,
- &RNA_FModifierPython,
- &RNA_FModifierStepped,
- };
-
- for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
- msg_key_params.ptr.type = type_array[i];
- WM_msg_subscribe_rna_params(
- mbus,
- &msg_key_params,
- &msg_sub_value_region_tag_redraw,
- __func__);
- }
- }
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_SpaceGraphEditor, sa->spacedata.first, &ptr);
+
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ /* Timeline depends on scene properties. */
+ {
+ bool use_preview = (scene->r.flag & SCER_PRV_RANGE);
+ extern PropertyRNA rna_Scene_frame_start;
+ extern PropertyRNA rna_Scene_frame_end;
+ extern PropertyRNA rna_Scene_frame_preview_start;
+ extern PropertyRNA rna_Scene_frame_preview_end;
+ extern PropertyRNA rna_Scene_use_preview_range;
+ extern PropertyRNA rna_Scene_frame_current;
+ const PropertyRNA *props[] = {
+ use_preview ? &rna_Scene_frame_preview_start : &rna_Scene_frame_start,
+ use_preview ? &rna_Scene_frame_preview_end : &rna_Scene_frame_end,
+ &rna_Scene_use_preview_range,
+ &rna_Scene_frame_current,
+ };
+
+ PointerRNA idptr;
+ RNA_id_pointer_create(&scene->id, &idptr);
+
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__);
+ }
+ }
+
+ /* All dopesheet filter settings, etc. affect the drawing of this editor,
+ * also same applies for all animation-related datatypes that may appear here,
+ * so just whitelist the entire structs for updates
+ */
+ {
+ wmMsgParams_RNA msg_key_params = {{{0}}};
+ StructRNA *type_array[] = {
+ &RNA_DopeSheet, /* dopesheet filters */
+
+ &RNA_ActionGroup, /* channel groups */
+ &RNA_FCurve, /* F-Curve */
+ &RNA_Keyframe,
+ &RNA_FCurveSample,
+
+ &RNA_FModifier, /* F-Modifiers (XXX: Why can't we just do all subclasses too?) */
+ &RNA_FModifierCycles,
+ &RNA_FModifierEnvelope,
+ &RNA_FModifierEnvelopeControlPoint,
+ &RNA_FModifierFunctionGenerator,
+ &RNA_FModifierGenerator,
+ &RNA_FModifierLimits,
+ &RNA_FModifierNoise,
+ &RNA_FModifierPython,
+ &RNA_FModifierStepped,
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
+ msg_key_params.ptr.type = type_array[i];
+ WM_msg_subscribe_rna_params(
+ mbus, &msg_key_params, &msg_sub_value_region_tag_redraw, __func__);
+ }
+ }
}
/* editor level listener */
-static void graph_listener(wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene))
+static void graph_listener(wmWindow *UNUSED(win),
+ ScrArea *sa,
+ wmNotifier *wmn,
+ Scene *UNUSED(scene))
{
- SpaceGraph *sipo = (SpaceGraph *)sa->spacedata.first;
-
- /* context changes */
- switch (wmn->category) {
- case NC_ANIMATION:
- /* 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);
- else
- ED_area_tag_refresh(sa);
- break;
- case NC_SCENE:
- switch (wmn->data) {
- case ND_OB_ACTIVE: /* selection changed, so force refresh to flush
- * (needs flag set to do syncing) */
- case ND_OB_SELECT:
- sipo->runtime.flag |= SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC;
- ED_area_tag_refresh(sa);
- break;
-
- default: /* just redrawing the view will do */
- ED_area_tag_redraw(sa);
- break;
- }
- break;
- case NC_OBJECT:
- switch (wmn->data) {
- case ND_BONE_SELECT: /* selection changed, so force refresh to flush
- * (needs flag set to do syncing) */
- case ND_BONE_ACTIVE:
- sipo->runtime.flag |= SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC;
- ED_area_tag_refresh(sa);
- break;
- case ND_TRANSFORM:
- break; /*do nothing*/
-
- default: /* just redrawing the view will do */
- ED_area_tag_redraw(sa);
- break;
- }
- break;
- case NC_NODE:
- 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);
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_GRAPH)
- ED_area_tag_redraw(sa);
- 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);
- }
- break;
-
- // XXX: restore the case below if not enough updates occur...
- //default:
- // if (wmn->data == ND_KEYS)
- // ED_area_tag_redraw(sa);
- }
+ SpaceGraph *sipo = (SpaceGraph *)sa->spacedata.first;
+
+ /* context changes */
+ switch (wmn->category) {
+ case NC_ANIMATION:
+ /* 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);
+ else
+ ED_area_tag_refresh(sa);
+ break;
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_OB_ACTIVE: /* selection changed, so force refresh to flush
+ * (needs flag set to do syncing) */
+ case ND_OB_SELECT:
+ sipo->runtime.flag |= SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC;
+ ED_area_tag_refresh(sa);
+ break;
+
+ default: /* just redrawing the view will do */
+ ED_area_tag_redraw(sa);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch (wmn->data) {
+ case ND_BONE_SELECT: /* selection changed, so force refresh to flush
+ * (needs flag set to do syncing) */
+ case ND_BONE_ACTIVE:
+ sipo->runtime.flag |= SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC;
+ ED_area_tag_refresh(sa);
+ break;
+ case ND_TRANSFORM:
+ break; /*do nothing*/
+
+ default: /* just redrawing the view will do */
+ ED_area_tag_redraw(sa);
+ break;
+ }
+ break;
+ case NC_NODE:
+ 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);
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_GRAPH)
+ ED_area_tag_redraw(sa);
+ 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);
+ }
+ break;
+
+ // XXX: restore the case below if not enough updates occur...
+ //default:
+ // if (wmn->data == ND_KEYS)
+ // ED_area_tag_redraw(sa);
+ }
}
/* Update F-Curve colors */
static void graph_refresh_fcurve_colors(const bContext *C)
{
- bAnimContext ac;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- size_t items;
- int filter;
- int i;
-
- if (ANIM_animdata_get_context(C, &ac) == false)
- return;
-
- UI_SetTheme(SPACE_GRAPH, RGN_TYPE_WINDOW);
-
- /* build list of F-Curves which will be visible as channels in channel-region
- * - we don't include ANIMFILTER_CURVEVISIBLE filter, as that will result in a
- * mismatch between channel-colors and the drawn curves
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS);
- items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* loop over F-Curves, assigning colors */
- for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) {
- FCurve *fcu = (FCurve *)ale->data;
-
- /* set color of curve here */
- switch (fcu->color_mode) {
- case FCURVE_COLOR_CUSTOM:
- {
- /* User has defined a custom color for this curve already (we assume it's not going to cause clashes with text colors),
- * which should be left alone... Nothing needs to be done here.
- */
- break;
- }
- case FCURVE_COLOR_AUTO_RGB:
- {
- /* F-Curve's array index is automatically mapped to RGB values. This works best of 3-value vectors.
- * TODO: find a way to module the hue so that not all curves have same color...
- */
- float *col = fcu->color;
-
- switch (fcu->array_index) {
- case 0:
- UI_GetThemeColor3fv(TH_AXIS_X, col);
- break;
- case 1:
- UI_GetThemeColor3fv(TH_AXIS_Y, col);
- break;
- case 2:
- UI_GetThemeColor3fv(TH_AXIS_Z, col);
- break;
- default:
- /* 'unknown' color - bluish so as to not conflict with handles */
- col[0] = 0.3f; col[1] = 0.8f; col[2] = 1.0f;
- break;
- }
- break;
- }
- case FCURVE_COLOR_AUTO_YRGB:
- {
- /* Like FCURVE_COLOR_AUTO_RGB, except this is for quaternions... */
- float *col = fcu->color;
-
- switch (fcu->array_index) {
- case 1:
- UI_GetThemeColor3fv(TH_AXIS_X, col);
- break;
- case 2:
- UI_GetThemeColor3fv(TH_AXIS_Y, col);
- break;
- case 3:
- UI_GetThemeColor3fv(TH_AXIS_Z, col);
- break;
-
- case 0:
- {
- /* Special Case: "W" channel should be yellowish, so blend X and Y channel colors... */
- float c1[3], c2[3];
- float h1[3], h2[3];
- float hresult[3];
-
- /* - get colors (rgb) */
- UI_GetThemeColor3fv(TH_AXIS_X, c1);
- UI_GetThemeColor3fv(TH_AXIS_Y, c2);
-
- /* - perform blending in HSV space (to keep brightness similar) */
- rgb_to_hsv_v(c1, h1);
- rgb_to_hsv_v(c2, h2);
-
- interp_v3_v3v3(hresult, h1, h2, 0.5f);
-
- /* - convert back to RGB for display */
- hsv_to_rgb_v(hresult, col);
- break;
- }
-
- default:
- /* 'unknown' color - bluish so as to not conflict with handles */
- col[0] = 0.3f; col[1] = 0.8f; col[2] = 1.0f;
- break;
- }
- break;
- }
- case FCURVE_COLOR_AUTO_RAINBOW:
- default:
- {
- /* determine color 'automatically' using 'magic function' which uses the given args
- * of current item index + total items to determine some RGB color
- */
- getcolor_fcurve_rainbow(i, items, fcu->color);
- break;
- }
- }
- }
-
- /* free temp list */
- ANIM_animdata_freelist(&anim_data);
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ size_t items;
+ int filter;
+ int i;
+
+ if (ANIM_animdata_get_context(C, &ac) == false)
+ return;
+
+ UI_SetTheme(SPACE_GRAPH, RGN_TYPE_WINDOW);
+
+ /* build list of F-Curves which will be visible as channels in channel-region
+ * - we don't include ANIMFILTER_CURVEVISIBLE filter, as that will result in a
+ * mismatch between channel-colors and the drawn curves
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS);
+ items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* loop over F-Curves, assigning colors */
+ for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) {
+ FCurve *fcu = (FCurve *)ale->data;
+
+ /* set color of curve here */
+ switch (fcu->color_mode) {
+ case FCURVE_COLOR_CUSTOM: {
+ /* User has defined a custom color for this curve already (we assume it's not going to cause clashes with text colors),
+ * which should be left alone... Nothing needs to be done here.
+ */
+ break;
+ }
+ case FCURVE_COLOR_AUTO_RGB: {
+ /* F-Curve's array index is automatically mapped to RGB values. This works best of 3-value vectors.
+ * TODO: find a way to module the hue so that not all curves have same color...
+ */
+ float *col = fcu->color;
+
+ switch (fcu->array_index) {
+ case 0:
+ UI_GetThemeColor3fv(TH_AXIS_X, col);
+ break;
+ case 1:
+ UI_GetThemeColor3fv(TH_AXIS_Y, col);
+ break;
+ case 2:
+ UI_GetThemeColor3fv(TH_AXIS_Z, col);
+ break;
+ default:
+ /* 'unknown' color - bluish so as to not conflict with handles */
+ col[0] = 0.3f;
+ col[1] = 0.8f;
+ col[2] = 1.0f;
+ break;
+ }
+ break;
+ }
+ case FCURVE_COLOR_AUTO_YRGB: {
+ /* Like FCURVE_COLOR_AUTO_RGB, except this is for quaternions... */
+ float *col = fcu->color;
+
+ switch (fcu->array_index) {
+ case 1:
+ UI_GetThemeColor3fv(TH_AXIS_X, col);
+ break;
+ case 2:
+ UI_GetThemeColor3fv(TH_AXIS_Y, col);
+ break;
+ case 3:
+ UI_GetThemeColor3fv(TH_AXIS_Z, col);
+ break;
+
+ case 0: {
+ /* Special Case: "W" channel should be yellowish, so blend X and Y channel colors... */
+ float c1[3], c2[3];
+ float h1[3], h2[3];
+ float hresult[3];
+
+ /* - get colors (rgb) */
+ UI_GetThemeColor3fv(TH_AXIS_X, c1);
+ UI_GetThemeColor3fv(TH_AXIS_Y, c2);
+
+ /* - perform blending in HSV space (to keep brightness similar) */
+ rgb_to_hsv_v(c1, h1);
+ rgb_to_hsv_v(c2, h2);
+
+ interp_v3_v3v3(hresult, h1, h2, 0.5f);
+
+ /* - convert back to RGB for display */
+ hsv_to_rgb_v(hresult, col);
+ break;
+ }
+
+ default:
+ /* 'unknown' color - bluish so as to not conflict with handles */
+ col[0] = 0.3f;
+ col[1] = 0.8f;
+ col[2] = 1.0f;
+ break;
+ }
+ break;
+ }
+ case FCURVE_COLOR_AUTO_RAINBOW:
+ default: {
+ /* determine color 'automatically' using 'magic function' which uses the given args
+ * of current item index + total items to determine some RGB color
+ */
+ getcolor_fcurve_rainbow(i, items, fcu->color);
+ break;
+ }
+ }
+ }
+
+ /* free temp list */
+ ANIM_animdata_freelist(&anim_data);
}
static void graph_refresh(const bContext *C, ScrArea *sa)
{
- SpaceGraph *sipo = (SpaceGraph *)sa->spacedata.first;
-
- /* updates to data needed depends on Graph Editor mode... */
- switch (sipo->mode) {
- case SIPO_MODE_ANIMATION: /* all animation */
- {
- break;
- }
-
- case SIPO_MODE_DRIVERS: /* drivers only */
- {
- break;
- }
- }
-
- /* region updates? */
- // XXX re-sizing y-extents of tot should go here?
-
- /* 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 (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);
- }
-
- /* We could check 'SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR', but color is recalculated anyway. */
- if (sipo->runtime.flag & SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR) {
- sipo->runtime.flag &= ~SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR;
-#if 0 /* Done below. */
- graph_refresh_fcurve_colors(C);
+ SpaceGraph *sipo = (SpaceGraph *)sa->spacedata.first;
+
+ /* updates to data needed depends on Graph Editor mode... */
+ switch (sipo->mode) {
+ case SIPO_MODE_ANIMATION: /* all animation */
+ {
+ break;
+ }
+
+ case SIPO_MODE_DRIVERS: /* drivers only */
+ {
+ break;
+ }
+ }
+
+ /* region updates? */
+ // XXX re-sizing y-extents of tot should go here?
+
+ /* 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 (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);
+ }
+
+ /* We could check 'SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR', but color is recalculated anyway. */
+ if (sipo->runtime.flag & SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR) {
+ sipo->runtime.flag &= ~SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR;
+#if 0 /* Done below. */
+ graph_refresh_fcurve_colors(C);
#endif
- ED_area_tag_redraw(sa);
- }
+ ED_area_tag_redraw(sa);
+ }
- /* init/adjust F-Curve colors */
- graph_refresh_fcurve_colors(C);
+ /* init/adjust F-Curve colors */
+ graph_refresh_fcurve_colors(C);
}
static void graph_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
{
- SpaceGraph *sgraph = (SpaceGraph *)slink;
-
- if (sgraph->ads) {
- if ((ID *)sgraph->ads->filter_grp == old_id) {
- sgraph->ads->filter_grp = (Collection *)new_id;
- }
- if ((ID *)sgraph->ads->source == old_id) {
- sgraph->ads->source = new_id;
- }
- }
+ SpaceGraph *sgraph = (SpaceGraph *)slink;
+
+ if (sgraph->ads) {
+ if ((ID *)sgraph->ads->filter_grp == old_id) {
+ sgraph->ads->filter_grp = (Collection *)new_id;
+ }
+ if ((ID *)sgraph->ads->source == old_id) {
+ sgraph->ads->source = new_id;
+ }
+ }
}
static int graph_space_subtype_get(ScrArea *sa)
{
- SpaceGraph *sgraph = sa->spacedata.first;
- return sgraph->mode;
+ SpaceGraph *sgraph = sa->spacedata.first;
+ return sgraph->mode;
}
static void graph_space_subtype_set(ScrArea *sa, int value)
{
- SpaceGraph *sgraph = sa->spacedata.first;
- sgraph->mode = value;
+ SpaceGraph *sgraph = sa->spacedata.first;
+ sgraph->mode = value;
}
-static void graph_space_subtype_item_extend(
- bContext *UNUSED(C), EnumPropertyItem **item, int *totitem)
+static void graph_space_subtype_item_extend(bContext *UNUSED(C),
+ EnumPropertyItem **item,
+ int *totitem)
{
- RNA_enum_items_add(item, totitem, rna_enum_space_graph_mode_items);
+ RNA_enum_items_add(item, totitem, rna_enum_space_graph_mode_items);
}
/* only called once, from space/spacetypes.c */
void ED_spacetype_ipo(void)
{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype ipo");
- ARegionType *art;
-
- st->spaceid = SPACE_GRAPH;
- strncpy(st->name, "Graph", BKE_ST_MAXNAME);
-
- st->new = graph_new;
- st->free = graph_free;
- st->init = graph_init;
- st->duplicate = graph_duplicate;
- st->operatortypes = graphedit_operatortypes;
- st->keymap = graphedit_keymap;
- st->listener = graph_listener;
- st->refresh = graph_refresh;
- st->id_remap = graph_id_remap;
- st->space_subtype_item_extend = graph_space_subtype_item_extend;
- st->space_subtype_get = graph_space_subtype_get;
- st->space_subtype_set = graph_space_subtype_set;
-
- /* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
- art->regionid = RGN_TYPE_WINDOW;
- art->init = graph_main_region_init;
- art->draw = graph_main_region_draw;
- art->listener = graph_region_listener;
- art->message_subscribe = graph_region_message_subscribe;
- art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
- art->listener = graph_region_listener;
- art->init = graph_header_region_init;
- art->draw = graph_header_region_draw;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: channels */
- art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
- art->regionid = RGN_TYPE_CHANNELS;
- /* 200 is the 'standard', but due to scrollers, we want a bit more to fit the lock icons in */
- art->prefsizex = 200 + V2D_SCROLL_WIDTH;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES;
- art->listener = graph_region_listener;
- art->message_subscribe = graph_region_message_subscribe;
- art->init = graph_channel_region_init;
- art->draw = graph_channel_region_draw;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: UI buttons */
- art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
- art->regionid = RGN_TYPE_UI;
- art->prefsizex = 200;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
- art->listener = graph_region_listener;
- art->init = graph_buttons_region_init;
- art->draw = graph_buttons_region_draw;
-
- BLI_addhead(&st->regiontypes, art);
-
- graph_buttons_register(art);
-
- BKE_spacetype_register(st);
+ SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype ipo");
+ ARegionType *art;
+
+ st->spaceid = SPACE_GRAPH;
+ strncpy(st->name, "Graph", BKE_ST_MAXNAME);
+
+ st->new = graph_new;
+ st->free = graph_free;
+ st->init = graph_init;
+ st->duplicate = graph_duplicate;
+ st->operatortypes = graphedit_operatortypes;
+ st->keymap = graphedit_keymap;
+ st->listener = graph_listener;
+ st->refresh = graph_refresh;
+ st->id_remap = graph_id_remap;
+ st->space_subtype_item_extend = graph_space_subtype_item_extend;
+ st->space_subtype_get = graph_space_subtype_get;
+ st->space_subtype_set = graph_space_subtype_set;
+
+ /* regions: main window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init = graph_main_region_init;
+ art->draw = graph_main_region_draw;
+ art->listener = graph_region_listener;
+ art->message_subscribe = graph_region_message_subscribe;
+ art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = HEADERY;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
+ art->listener = graph_region_listener;
+ art->init = graph_header_region_init;
+ art->draw = graph_header_region_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: channels */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
+ art->regionid = RGN_TYPE_CHANNELS;
+ /* 200 is the 'standard', but due to scrollers, we want a bit more to fit the lock icons in */
+ art->prefsizex = 200 + V2D_SCROLL_WIDTH;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES;
+ art->listener = graph_region_listener;
+ art->message_subscribe = graph_region_message_subscribe;
+ art->init = graph_channel_region_init;
+ art->draw = graph_channel_region_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: UI buttons */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
+ art->regionid = RGN_TYPE_UI;
+ art->prefsizex = 200;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
+ art->listener = graph_region_listener;
+ art->init = graph_buttons_region_init;
+ art->draw = graph_buttons_region_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ graph_buttons_register(art);
+
+ BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt
index 2687849f211..70b7387bf6b 100644
--- a/source/blender/editors/space_image/CMakeLists.txt
+++ b/source/blender/editors/space_image/CMakeLists.txt
@@ -16,65 +16,65 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenfont
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../bmesh
- ../../depsgraph
- ../../imbuf
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../render/extern/include
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenfont
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../bmesh
+ ../../depsgraph
+ ../../imbuf
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../render/extern/include
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- image_buttons.c
- image_draw.c
- image_edit.c
- image_ops.c
- space_image.c
+ image_buttons.c
+ image_draw.c
+ image_edit.c
+ image_ops.c
+ space_image.c
- image_intern.h
+ image_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
- bf_editor_uvedit
+ bf_blenkernel
+ bf_blenlib
+ bf_editor_uvedit
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
if(WITH_OPENIMAGEIO)
- add_definitions(-DWITH_OPENIMAGEIO)
+ add_definitions(-DWITH_OPENIMAGEIO)
endif()
if(WITH_IMAGE_OPENJPEG)
- add_definitions(-DWITH_OPENJPEG)
+ add_definitions(-DWITH_OPENJPEG)
endif()
if(WITH_IMAGE_OPENEXR)
- add_definitions(-DWITH_OPENEXR)
+ add_definitions(-DWITH_OPENEXR)
endif()
if(WITH_IMAGE_TIFF)
- add_definitions(-DWITH_TIFF)
+ add_definitions(-DWITH_TIFF)
endif()
if(WITH_IMAGE_CINEON)
- add_definitions(-DWITH_CINEON)
+ add_definitions(-DWITH_CINEON)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 47b3f9995c5..e217987f212 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -60,97 +60,100 @@
#include "image_intern.h"
#define B_NOP -1
-#define MAX_IMAGE_INFO_LEN 128
+#define MAX_IMAGE_INFO_LEN 128
/* proto */
-static void image_info(Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf, char *str, size_t len)
+static void image_info(
+ Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf, char *str, size_t len)
{
- size_t ofs = 0;
-
- str[0] = 0;
- if (ima == NULL) {
- return;
- }
-
- if (ibuf == NULL) {
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Can't Load Image"), len - ofs);
- }
- else {
- if (ima->source == IMA_SRC_MOVIE) {
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Movie"), len - ofs);
- if (BKE_image_has_anim(ima)) {
- ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(" %d frs"),
- IMB_anim_get_duration(((ImageAnim *)ima->anims.first)->anim, IMB_TC_RECORD_RUN));
- }
- }
- else {
- ofs += BLI_strncpy_rlen(str, IFACE_("Image"), len - ofs);
- }
-
- ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(": size %d x %d,"), ibuf->x, ibuf->y);
-
- if (ibuf->rect_float) {
- if (ibuf->channels != 4) {
- ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_("%d float channel(s)"), ibuf->channels);
- }
- else if (ibuf->planes == R_IMF_PLANES_RGBA) {
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA float"), len - ofs);
- }
- else {
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB float"), len - ofs);
- }
- }
- else {
- if (ibuf->planes == R_IMF_PLANES_RGBA) {
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA byte"), len - ofs);
- }
- else {
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB byte"), len - ofs);
- }
- }
- if (ibuf->zbuf || ibuf->zbuf_float) {
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" + Z"), len - ofs);
- }
-
- if (ima->source == IMA_SRC_SEQUENCE) {
- const char *file = BLI_last_slash(ibuf->name);
- if (file == NULL) {
- file = ibuf->name;
- }
- else {
- file++;
- }
- ofs += BLI_snprintf(str + ofs, len - ofs, ", %s", file);
- }
- }
-
- /* the frame number, even if we cant */
- if (ima->source == IMA_SRC_SEQUENCE) {
- /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */
- const int framenr = BKE_image_user_frame_get(iuser, CFRA, NULL);
- ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(", Frame: %d"), framenr);
- }
+ size_t ofs = 0;
+
+ str[0] = 0;
+ if (ima == NULL) {
+ return;
+ }
+
+ if (ibuf == NULL) {
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Can't Load Image"), len - ofs);
+ }
+ else {
+ if (ima->source == IMA_SRC_MOVIE) {
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Movie"), len - ofs);
+ if (BKE_image_has_anim(ima)) {
+ ofs += BLI_snprintf(
+ str + ofs,
+ len - ofs,
+ IFACE_(" %d frs"),
+ IMB_anim_get_duration(((ImageAnim *)ima->anims.first)->anim, IMB_TC_RECORD_RUN));
+ }
+ }
+ else {
+ ofs += BLI_strncpy_rlen(str, IFACE_("Image"), len - ofs);
+ }
+
+ ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(": size %d x %d,"), ibuf->x, ibuf->y);
+
+ if (ibuf->rect_float) {
+ if (ibuf->channels != 4) {
+ ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_("%d float channel(s)"), ibuf->channels);
+ }
+ else if (ibuf->planes == R_IMF_PLANES_RGBA) {
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA float"), len - ofs);
+ }
+ else {
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB float"), len - ofs);
+ }
+ }
+ else {
+ if (ibuf->planes == R_IMF_PLANES_RGBA) {
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA byte"), len - ofs);
+ }
+ else {
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB byte"), len - ofs);
+ }
+ }
+ if (ibuf->zbuf || ibuf->zbuf_float) {
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" + Z"), len - ofs);
+ }
+
+ if (ima->source == IMA_SRC_SEQUENCE) {
+ const char *file = BLI_last_slash(ibuf->name);
+ if (file == NULL) {
+ file = ibuf->name;
+ }
+ else {
+ file++;
+ }
+ ofs += BLI_snprintf(str + ofs, len - ofs, ", %s", file);
+ }
+ }
+
+ /* the frame number, even if we cant */
+ if (ima->source == IMA_SRC_SEQUENCE) {
+ /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */
+ const int framenr = BKE_image_user_frame_get(iuser, CFRA, NULL);
+ ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(", Frame: %d"), framenr);
+ }
}
/* gets active viewer user */
struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree)
{
- bNode *node;
-
- if (ntree) {
- for (node = ntree->nodes.first; node; node = node->next) {
- if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
- if (node->flag & NODE_DO_OUTPUT) {
- return node->storage;
- }
- }
- }
- }
- return NULL;
+ bNode *node;
+
+ if (ntree) {
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+ if (node->flag & NODE_DO_OUTPUT) {
+ return node->storage;
+ }
+ }
+ }
+ }
+ return NULL;
}
-
/* ************ panel stuff ************* */
#if 0
@@ -160,1203 +163,1351 @@ struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree)
* XXX if you put this back, also check XXX in image_main_region_draw() */
void image_preview_event(int event)
{
- int exec = 0;
+ int exec = 0;
- if (event == 0) {
- G.scene->r.scemode &= ~R_COMP_CROP;
- exec = 1;
- }
- else {
- if (image_preview_active(curarea, NULL, NULL)) {
- G.scene->r.scemode |= R_COMP_CROP;
- exec = 1;
- }
- else
- G.scene->r.scemode &= ~R_COMP_CROP;
- }
+ if (event == 0) {
+ G.scene->r.scemode &= ~R_COMP_CROP;
+ exec = 1;
+ }
+ else {
+ if (image_preview_active(curarea, NULL, NULL)) {
+ G.scene->r.scemode |= R_COMP_CROP;
+ exec = 1;
+ }
+ else
+ G.scene->r.scemode &= ~R_COMP_CROP;
+ }
- if (exec && G.scene->nodetree) {
- Scene *scene = G.scene;
- /* should work when no node editor in screen..., so we execute right away */
+ if (exec && G.scene->nodetree) {
+ Scene *scene = G.scene;
+ /* should work when no node editor in screen..., so we execute right away */
- ntreeCompositTagGenerators(G.scene->nodetree);
+ ntreeCompositTagGenerators(G.scene->nodetree);
- G.is_break = false;
- G.scene->nodetree->timecursor = set_timecursor;
- G.scene->nodetree->test_break = BKE_blender_test_break;
+ G.is_break = false;
+ G.scene->nodetree->timecursor = set_timecursor;
+ G.scene->nodetree->test_break = BKE_blender_test_break;
- BIF_store_spare();
+ BIF_store_spare();
- /* 1 is do_previews */
- ntreeCompositExecTree(scene->nodetree, &scene->r, 1, &scene->view_settings, &scene->display_settings);
+ /* 1 is do_previews */
+ ntreeCompositExecTree(scene->nodetree, &scene->r, 1, &scene->view_settings, &scene->display_settings);
- G.scene->nodetree->timecursor = NULL;
- G.scene->nodetree->test_break = NULL;
+ G.scene->nodetree->timecursor = NULL;
+ G.scene->nodetree->test_break = NULL;
- scrarea_do_windraw(curarea);
- waitcursor(0);
+ scrarea_do_windraw(curarea);
+ waitcursor(0);
- WM_event_add_notifier(C, NC_IMAGE, ima_v);
- }
+ WM_event_add_notifier(C, NC_IMAGE, ima_v);
+ }
}
/* nothing drawn here, we use it to store values */
static void preview_cb(ScrArea *sa, struct uiBlock *block)
{
- SpaceImage *sima = sa->spacedata.first;
- rctf dispf;
- rcti *disprect = &G.scene->r.disprect;
- int winx = (G.scene->r.size * G.scene->r.xsch) / 100;
- int winy = (G.scene->r.size * G.scene->r.ysch) / 100;
- int mval[2];
-
- if (G.scene->r.mode & R_BORDER) {
- winx *= BLI_rcti_size_x(&G.scene->r.border);
- winy *= BLI_rctf_size_y(&G.scene->r.border);
- }
-
- /* while dragging we need to update the rects, otherwise it doesn't end with correct one */
-
- BLI_rctf_init(&dispf, 15.0f, BLI_rcti_size_x(&block->rect) - 15.0f, 15.0f, (BLI_rctf_size_y(&block->rect)) - 15.0f);
- ui_graphics_to_window_rct(sa->win, &dispf, disprect);
-
- /* correction for gla draw */
- BLI_rcti_translate(disprect, -curarea->winrct.xmin, -curarea->winrct.ymin);
-
- calc_image_view(sima, 'p');
-// printf("winrct %d %d %d %d\n", disprect->xmin, disprect->ymin, disprect->xmax, disprect->ymax);
- /* map to image space coordinates */
- mval[0] = disprect->xmin; mval[1] = disprect->ymin;
- areamouseco_to_ipoco(v2d, mval, &dispf.xmin, &dispf.ymin);
- mval[0] = disprect->xmax; mval[1] = disprect->ymax;
- areamouseco_to_ipoco(v2d, mval, &dispf.xmax, &dispf.ymax);
-
- /* map to render coordinates */
- disprect->xmin = dispf.xmin;
- disprect->xmax = dispf.xmax;
- disprect->ymin = dispf.ymin;
- disprect->ymax = dispf.ymax;
-
- CLAMP(disprect->xmin, 0, winx);
- CLAMP(disprect->xmax, 0, winx);
- CLAMP(disprect->ymin, 0, winy);
- CLAMP(disprect->ymax, 0, winy);
-// printf("drawrct %d %d %d %d\n", disprect->xmin, disprect->ymin, disprect->xmax, disprect->ymax);
+ SpaceImage *sima = sa->spacedata.first;
+ rctf dispf;
+ rcti *disprect = &G.scene->r.disprect;
+ int winx = (G.scene->r.size * G.scene->r.xsch) / 100;
+ int winy = (G.scene->r.size * G.scene->r.ysch) / 100;
+ int mval[2];
+
+ if (G.scene->r.mode & R_BORDER) {
+ winx *= BLI_rcti_size_x(&G.scene->r.border);
+ winy *= BLI_rctf_size_y(&G.scene->r.border);
+ }
+
+ /* while dragging we need to update the rects, otherwise it doesn't end with correct one */
+
+ BLI_rctf_init(&dispf, 15.0f, BLI_rcti_size_x(&block->rect) - 15.0f, 15.0f, (BLI_rctf_size_y(&block->rect)) - 15.0f);
+ ui_graphics_to_window_rct(sa->win, &dispf, disprect);
+
+ /* correction for gla draw */
+ BLI_rcti_translate(disprect, -curarea->winrct.xmin, -curarea->winrct.ymin);
+
+ calc_image_view(sima, 'p');
+// printf("winrct %d %d %d %d\n", disprect->xmin, disprect->ymin, disprect->xmax, disprect->ymax);
+ /* map to image space coordinates */
+ mval[0] = disprect->xmin; mval[1] = disprect->ymin;
+ areamouseco_to_ipoco(v2d, mval, &dispf.xmin, &dispf.ymin);
+ mval[0] = disprect->xmax; mval[1] = disprect->ymax;
+ areamouseco_to_ipoco(v2d, mval, &dispf.xmax, &dispf.ymax);
+
+ /* map to render coordinates */
+ disprect->xmin = dispf.xmin;
+ disprect->xmax = dispf.xmax;
+ disprect->ymin = dispf.ymin;
+ disprect->ymax = dispf.ymax;
+
+ CLAMP(disprect->xmin, 0, winx);
+ CLAMP(disprect->xmax, 0, winx);
+ CLAMP(disprect->ymin, 0, winy);
+ CLAMP(disprect->ymax, 0, winy);
+// printf("drawrct %d %d %d %d\n", disprect->xmin, disprect->ymin, disprect->xmax, disprect->ymax);
}
static bool is_preview_allowed(ScrArea *cur)
{
- SpaceImage *sima = cur->spacedata.first;
- ScrArea *sa;
-
- /* check if another areawindow has preview set */
- for (sa = G.curscreen->areabase.first; sa; sa = sa->next) {
- if (sa != cur && sa->spacetype == SPACE_IMAGE) {
- if (image_preview_active(sa, NULL, NULL))
- return 0;
- }
- }
- /* check image type */
- if (sima->image == NULL || sima->image->type != IMA_TYPE_COMPOSITE)
- return 0;
-
- return 1;
+ SpaceImage *sima = cur->spacedata.first;
+ ScrArea *sa;
+
+ /* check if another areawindow has preview set */
+ for (sa = G.curscreen->areabase.first; sa; sa = sa->next) {
+ if (sa != cur && sa->spacetype == SPACE_IMAGE) {
+ if (image_preview_active(sa, NULL, NULL))
+ return 0;
+ }
+ }
+ /* check image type */
+ if (sima->image == NULL || sima->image->type != IMA_TYPE_COMPOSITE)
+ return 0;
+
+ return 1;
}
static void image_panel_preview(ScrArea *sa, short cntrl) // IMAGE_HANDLER_PREVIEW
{
- uiBlock *block;
- SpaceImage *sima = sa->spacedata.first;
- int ofsx, ofsy;
+ uiBlock *block;
+ SpaceImage *sima = sa->spacedata.first;
+ int ofsx, ofsy;
- if (is_preview_allowed(sa) == 0) {
- rem_blockhandler(sa, IMAGE_HANDLER_PREVIEW);
- G.scene->r.scemode &= ~R_COMP_CROP; /* quite weak */
- return;
- }
+ if (is_preview_allowed(sa) == 0) {
+ rem_blockhandler(sa, IMAGE_HANDLER_PREVIEW);
+ G.scene->r.scemode &= ~R_COMP_CROP; /* quite weak */
+ return;
+ }
- block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
- uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | UI_PNL_SCALE | cntrl);
- uiSetPanelHandler(IMAGE_HANDLER_PREVIEW); // for close and esc
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | UI_PNL_SCALE | cntrl);
+ uiSetPanelHandler(IMAGE_HANDLER_PREVIEW); // for close and esc
- ofsx = -150 + (sa->winx / 2) / sima->blockscale;
- ofsy = -100 + (sa->winy / 2) / sima->blockscale;
- if (uiNewPanel(C, ar, block, "Preview", "Image", ofsx, ofsy, 300, 200) == 0) return;
+ ofsx = -150 + (sa->winx / 2) / sima->blockscale;
+ ofsy = -100 + (sa->winy / 2) / sima->blockscale;
+ if (uiNewPanel(C, ar, block, "Preview", "Image", ofsx, ofsy, 300, 200) == 0) return;
- UI_but_func_drawextra_set(block, preview_cb);
+ UI_but_func_drawextra_set(block, preview_cb);
}
#endif
-
/* ********************* callbacks for standard image buttons *************** */
static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void *image_p)
{
- uiBlock *block = uiLayoutGetBlock(layout);
- Image *image = image_p;
- int slot_id;
-
- uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Slot"),
- 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- uiItemS(layout);
-
- slot_id = BLI_listbase_count(&image->renderslots) - 1;
- for (RenderSlot *slot = image->renderslots.last; slot; slot = slot->prev) {
- char str[64];
- if (slot->name[0] != '\0') {
- BLI_strncpy(str, slot->name, sizeof(str));
- }
- else {
- BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), slot_id + 1);
- }
- uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, str, 0, 0,
- UI_UNIT_X * 5, UI_UNIT_X, &image->render_slot, (float) slot_id, 0.0, 0, -1, "");
- slot_id--;
- }
+ uiBlock *block = uiLayoutGetBlock(layout);
+ Image *image = image_p;
+ int slot_id;
+
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ IFACE_("Slot"),
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ uiItemS(layout);
+
+ slot_id = BLI_listbase_count(&image->renderslots) - 1;
+ for (RenderSlot *slot = image->renderslots.last; slot; slot = slot->prev) {
+ char str[64];
+ if (slot->name[0] != '\0') {
+ BLI_strncpy(str, slot->name, sizeof(str));
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), slot_id + 1);
+ }
+ uiDefButS(block,
+ UI_BTYPE_BUT_MENU,
+ B_NOP,
+ str,
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_X,
+ &image->render_slot,
+ (float)slot_id,
+ 0.0,
+ 0,
+ -1,
+ "");
+ slot_id--;
+ }
}
static bool ui_imageuser_slot_menu_step(bContext *C, int direction, void *image_p)
{
- Image *image = image_p;
-
- if (ED_image_slot_cycle(image, direction)) {
- WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
- return true;
- }
- else {
- return true;
- }
+ Image *image = image_p;
+
+ if (ED_image_slot_cycle(image, direction)) {
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+ return true;
+ }
+ else {
+ return true;
+ }
}
static const char *ui_imageuser_layer_fake_name(RenderResult *rr)
{
- RenderView *rv = RE_RenderViewGetById(rr, 0);
- if (rv->rectf) {
- return IFACE_("Composite");
- }
- else if (rv->rect32) {
- return IFACE_("Sequence");
- }
- else {
- return NULL;
- }
+ RenderView *rv = RE_RenderViewGetById(rr, 0);
+ if (rv->rectf) {
+ return IFACE_("Composite");
+ }
+ else if (rv->rect32) {
+ return IFACE_("Sequence");
+ }
+ else {
+ return NULL;
+ }
}
/* workaround for passing many args */
struct ImageUI_Data {
- Image *image;
- ImageUser *iuser;
- int rpass_index;
+ Image *image;
+ ImageUser *iuser;
+ int rpass_index;
};
static struct ImageUI_Data *ui_imageuser_data_copy(const struct ImageUI_Data *rnd_pt_src)
{
- struct ImageUI_Data *rnd_pt_dst = MEM_mallocN(sizeof(*rnd_pt_src), __func__);
- memcpy(rnd_pt_dst, rnd_pt_src, sizeof(*rnd_pt_src));
- return rnd_pt_dst;
+ struct ImageUI_Data *rnd_pt_dst = MEM_mallocN(sizeof(*rnd_pt_src), __func__);
+ memcpy(rnd_pt_dst, rnd_pt_src, sizeof(*rnd_pt_src));
+ return rnd_pt_dst;
}
static void ui_imageuser_layer_menu(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt)
{
- struct ImageUI_Data *rnd_data = rnd_pt;
- uiBlock *block = uiLayoutGetBlock(layout);
- Image *image = rnd_data->image;
- ImageUser *iuser = rnd_data->iuser;
- Scene *scene = iuser->scene;
- RenderResult *rr;
- RenderLayer *rl;
- RenderLayer rl_fake = {NULL};
- const char *fake_name;
- int nr;
-
- /* may have been freed since drawing */
- rr = BKE_image_acquire_renderresult(scene, image);
- if (UNLIKELY(rr == NULL)) {
- return;
- }
-
- UI_block_layout_set_current(block, layout);
- uiLayoutColumn(layout, false);
-
- uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Layer"),
- 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- uiItemS(layout);
-
- nr = BLI_listbase_count(&rr->layers) - 1;
- fake_name = ui_imageuser_layer_fake_name(rr);
-
- if (fake_name) {
- BLI_strncpy(rl_fake.name, fake_name, sizeof(rl_fake.name));
- nr += 1;
- }
-
- for (rl = rr->layers.last; rl; rl = rl->prev, nr--) {
-final:
- uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, rl->name, 0, 0,
- UI_UNIT_X * 5, UI_UNIT_X, &iuser->layer, (float) nr, 0.0, 0, -1, "");
- }
-
- if (fake_name) {
- fake_name = NULL;
- rl = &rl_fake;
- goto final;
- }
-
- BLI_assert(nr == -1);
-
- BKE_image_release_renderresult(scene, image);
+ struct ImageUI_Data *rnd_data = rnd_pt;
+ uiBlock *block = uiLayoutGetBlock(layout);
+ Image *image = rnd_data->image;
+ ImageUser *iuser = rnd_data->iuser;
+ Scene *scene = iuser->scene;
+ RenderResult *rr;
+ RenderLayer *rl;
+ RenderLayer rl_fake = {NULL};
+ const char *fake_name;
+ int nr;
+
+ /* may have been freed since drawing */
+ rr = BKE_image_acquire_renderresult(scene, image);
+ if (UNLIKELY(rr == NULL)) {
+ return;
+ }
+
+ UI_block_layout_set_current(block, layout);
+ uiLayoutColumn(layout, false);
+
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ IFACE_("Layer"),
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ uiItemS(layout);
+
+ nr = BLI_listbase_count(&rr->layers) - 1;
+ fake_name = ui_imageuser_layer_fake_name(rr);
+
+ if (fake_name) {
+ BLI_strncpy(rl_fake.name, fake_name, sizeof(rl_fake.name));
+ nr += 1;
+ }
+
+ for (rl = rr->layers.last; rl; rl = rl->prev, nr--) {
+ final:
+ uiDefButS(block,
+ UI_BTYPE_BUT_MENU,
+ B_NOP,
+ rl->name,
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_X,
+ &iuser->layer,
+ (float)nr,
+ 0.0,
+ 0,
+ -1,
+ "");
+ }
+
+ if (fake_name) {
+ fake_name = NULL;
+ rl = &rl_fake;
+ goto final;
+ }
+
+ BLI_assert(nr == -1);
+
+ BKE_image_release_renderresult(scene, image);
}
static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt)
{
- struct ImageUI_Data *rnd_data = rnd_pt;
- uiBlock *block = uiLayoutGetBlock(layout);
- Image *image = rnd_data->image;
- ImageUser *iuser = rnd_data->iuser;
- /* (rpass_index == -1) means composite result */
- const int rpass_index = rnd_data->rpass_index;
- Scene *scene = iuser->scene;
- RenderResult *rr;
- RenderLayer *rl;
- RenderPass *rpass;
- int nr;
-
- /* may have been freed since drawing */
- rr = BKE_image_acquire_renderresult(scene, image);
- if (UNLIKELY(rr == NULL)) {
- return;
- }
-
- rl = BLI_findlink(&rr->layers, rpass_index);
-
- UI_block_layout_set_current(block, layout);
- uiLayoutColumn(layout, false);
-
- uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Pass"),
- 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
-
- uiItemS(layout);
-
- nr = (rl == NULL) ? 1 : 0;
-
- ListBase added_passes;
- BLI_listbase_clear(&added_passes);
-
- /* rendered results don't have a Combined pass */
- /* multiview: the ordering must be ascending, so the left-most pass is always the one picked */
- for (rpass = rl ? rl->passes.first : NULL; rpass; rpass = rpass->next, nr++) {
- /* just show one pass of each kind */
- if (BLI_findstring_ptr(&added_passes, rpass->name, offsetof(LinkData, data))) {
- continue;
- }
- BLI_addtail(&added_passes, BLI_genericNodeN(rpass->name));
-
- uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->name), 0, 0,
- UI_UNIT_X * 5, UI_UNIT_X, &iuser->pass, (float) nr, 0.0, 0, -1, "");
- }
-
- BLI_freelistN(&added_passes);
-
- BKE_image_release_renderresult(scene, image);
+ struct ImageUI_Data *rnd_data = rnd_pt;
+ uiBlock *block = uiLayoutGetBlock(layout);
+ Image *image = rnd_data->image;
+ ImageUser *iuser = rnd_data->iuser;
+ /* (rpass_index == -1) means composite result */
+ const int rpass_index = rnd_data->rpass_index;
+ Scene *scene = iuser->scene;
+ RenderResult *rr;
+ RenderLayer *rl;
+ RenderPass *rpass;
+ int nr;
+
+ /* may have been freed since drawing */
+ rr = BKE_image_acquire_renderresult(scene, image);
+ if (UNLIKELY(rr == NULL)) {
+ return;
+ }
+
+ rl = BLI_findlink(&rr->layers, rpass_index);
+
+ UI_block_layout_set_current(block, layout);
+ uiLayoutColumn(layout, false);
+
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ IFACE_("Pass"),
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+
+ uiItemS(layout);
+
+ nr = (rl == NULL) ? 1 : 0;
+
+ ListBase added_passes;
+ BLI_listbase_clear(&added_passes);
+
+ /* rendered results don't have a Combined pass */
+ /* multiview: the ordering must be ascending, so the left-most pass is always the one picked */
+ for (rpass = rl ? rl->passes.first : NULL; rpass; rpass = rpass->next, nr++) {
+ /* just show one pass of each kind */
+ if (BLI_findstring_ptr(&added_passes, rpass->name, offsetof(LinkData, data))) {
+ continue;
+ }
+ BLI_addtail(&added_passes, BLI_genericNodeN(rpass->name));
+
+ uiDefButS(block,
+ UI_BTYPE_BUT_MENU,
+ B_NOP,
+ IFACE_(rpass->name),
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_X,
+ &iuser->pass,
+ (float)nr,
+ 0.0,
+ 0,
+ -1,
+ "");
+ }
+
+ BLI_freelistN(&added_passes);
+
+ BKE_image_release_renderresult(scene, image);
}
/**************************** view menus *****************************/
static void ui_imageuser_view_menu_rr(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt)
{
- struct ImageUI_Data *rnd_data = rnd_pt;
- uiBlock *block = uiLayoutGetBlock(layout);
- Image *image = rnd_data->image;
- ImageUser *iuser = rnd_data->iuser;
- RenderResult *rr;
- RenderView *rview;
- int nr;
- Scene *scene = iuser->scene;
-
- /* may have been freed since drawing */
- rr = BKE_image_acquire_renderresult(scene, image);
- if (UNLIKELY(rr == NULL)) {
- return;
- }
-
- UI_block_layout_set_current(block, layout);
- uiLayoutColumn(layout, false);
-
- uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("View"),
- 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
-
- uiItemS(layout);
-
- nr = (rr ? BLI_listbase_count(&rr->views) : 0) - 1;
- for (rview = rr ? rr->views.last : NULL; rview; rview = rview->prev, nr--) {
- uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rview->name), 0, 0,
- UI_UNIT_X * 5, UI_UNIT_X, &iuser->view, (float) nr, 0.0, 0, -1, "");
- }
-
- BKE_image_release_renderresult(scene, image);
+ struct ImageUI_Data *rnd_data = rnd_pt;
+ uiBlock *block = uiLayoutGetBlock(layout);
+ Image *image = rnd_data->image;
+ ImageUser *iuser = rnd_data->iuser;
+ RenderResult *rr;
+ RenderView *rview;
+ int nr;
+ Scene *scene = iuser->scene;
+
+ /* may have been freed since drawing */
+ rr = BKE_image_acquire_renderresult(scene, image);
+ if (UNLIKELY(rr == NULL)) {
+ return;
+ }
+
+ UI_block_layout_set_current(block, layout);
+ uiLayoutColumn(layout, false);
+
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ IFACE_("View"),
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+
+ uiItemS(layout);
+
+ nr = (rr ? BLI_listbase_count(&rr->views) : 0) - 1;
+ for (rview = rr ? rr->views.last : NULL; rview; rview = rview->prev, nr--) {
+ uiDefButS(block,
+ UI_BTYPE_BUT_MENU,
+ B_NOP,
+ IFACE_(rview->name),
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_X,
+ &iuser->view,
+ (float)nr,
+ 0.0,
+ 0,
+ -1,
+ "");
+ }
+
+ BKE_image_release_renderresult(scene, image);
}
static void ui_imageuser_view_menu_multiview(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt)
{
- struct ImageUI_Data *rnd_data = rnd_pt;
- uiBlock *block = uiLayoutGetBlock(layout);
- Image *image = rnd_data->image;
- ImageUser *iuser = rnd_data->iuser;
- int nr;
- ImageView *iv;
-
- UI_block_layout_set_current(block, layout);
- uiLayoutColumn(layout, false);
-
- uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("View"),
- 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
-
- uiItemS(layout);
-
- nr = BLI_listbase_count(&image->views) - 1;
- for (iv = image->views.last; iv; iv = iv->prev, nr--) {
- uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(iv->name), 0, 0,
- UI_UNIT_X * 5, UI_UNIT_X, &iuser->view, (float) nr, 0.0, 0, -1, "");
- }
+ struct ImageUI_Data *rnd_data = rnd_pt;
+ uiBlock *block = uiLayoutGetBlock(layout);
+ Image *image = rnd_data->image;
+ ImageUser *iuser = rnd_data->iuser;
+ int nr;
+ ImageView *iv;
+
+ UI_block_layout_set_current(block, layout);
+ uiLayoutColumn(layout, false);
+
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ IFACE_("View"),
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+
+ uiItemS(layout);
+
+ nr = BLI_listbase_count(&image->views) - 1;
+ for (iv = image->views.last; iv; iv = iv->prev, nr--) {
+ uiDefButS(block,
+ UI_BTYPE_BUT_MENU,
+ B_NOP,
+ IFACE_(iv->name),
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_X,
+ &iuser->view,
+ (float)nr,
+ 0.0,
+ 0,
+ -1,
+ "");
+ }
}
/* 5 layer button callbacks... */
static void image_multi_cb(bContext *C, void *rnd_pt, void *rr_v)
{
- struct ImageUI_Data *rnd_data = rnd_pt;
- ImageUser *iuser = rnd_data->iuser;
+ struct ImageUI_Data *rnd_data = rnd_pt;
+ ImageUser *iuser = rnd_data->iuser;
- BKE_image_multilayer_index(rr_v, iuser);
- WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+ BKE_image_multilayer_index(rr_v, iuser);
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
}
static bool ui_imageuser_layer_menu_step(bContext *C, int direction, void *rnd_pt)
{
- Scene *scene = CTX_data_scene(C);
- struct ImageUI_Data *rnd_data = rnd_pt;
- Image *image = rnd_data->image;
- ImageUser *iuser = rnd_data->iuser;
- RenderResult *rr;
- bool changed = false;
-
- rr = BKE_image_acquire_renderresult(scene, image);
- if (UNLIKELY(rr == NULL)) {
- return false;
- }
-
- if (direction == -1) {
- if (iuser->layer > 0) {
- iuser->layer--;
- changed = true;
- }
- }
- else if (direction == 1) {
- int tot = BLI_listbase_count(&rr->layers);
-
- if (RE_HasCombinedLayer(rr)) {
- tot++; /* fake compo/sequencer layer */
- }
-
- if (iuser->layer < tot - 1) {
- iuser->layer++;
- changed = true;
- }
- }
- else {
- BLI_assert(0);
- }
-
- BKE_image_release_renderresult(scene, image);
-
- if (changed) {
- BKE_image_multilayer_index(rr, iuser);
- WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
- }
-
- return changed;
+ Scene *scene = CTX_data_scene(C);
+ struct ImageUI_Data *rnd_data = rnd_pt;
+ Image *image = rnd_data->image;
+ ImageUser *iuser = rnd_data->iuser;
+ RenderResult *rr;
+ bool changed = false;
+
+ rr = BKE_image_acquire_renderresult(scene, image);
+ if (UNLIKELY(rr == NULL)) {
+ return false;
+ }
+
+ if (direction == -1) {
+ if (iuser->layer > 0) {
+ iuser->layer--;
+ changed = true;
+ }
+ }
+ else if (direction == 1) {
+ int tot = BLI_listbase_count(&rr->layers);
+
+ if (RE_HasCombinedLayer(rr)) {
+ tot++; /* fake compo/sequencer layer */
+ }
+
+ if (iuser->layer < tot - 1) {
+ iuser->layer++;
+ changed = true;
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ BKE_image_release_renderresult(scene, image);
+
+ if (changed) {
+ BKE_image_multilayer_index(rr, iuser);
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+ }
+
+ return changed;
}
static bool ui_imageuser_pass_menu_step(bContext *C, int direction, void *rnd_pt)
{
- Scene *scene = CTX_data_scene(C);
- struct ImageUI_Data *rnd_data = rnd_pt;
- Image *image = rnd_data->image;
- ImageUser *iuser = rnd_data->iuser;
- RenderResult *rr;
- bool changed = false;
- int layer = iuser->layer;
- RenderLayer *rl;
- RenderPass *rpass;
-
- rr = BKE_image_acquire_renderresult(scene, image);
- if (UNLIKELY(rr == NULL)) {
- BKE_image_release_renderresult(scene, image);
- return false;
- }
-
- if (RE_HasCombinedLayer(rr)) {
- layer -= 1;
- }
-
- rl = BLI_findlink(&rr->layers, layer);
- if (rl == NULL) {
- BKE_image_release_renderresult(scene, image);
- return false;
- }
-
- rpass = BLI_findlink(&rl->passes, iuser->pass);
- if (rpass == NULL) {
- BKE_image_release_renderresult(scene, image);
- return false;
- }
-
- /* note, this looks reversed, but matches menu direction */
- if (direction == -1) {
- RenderPass *rp;
- int rp_index = iuser->pass + 1;
-
- for (rp = rpass->next; rp; rp = rp->next, rp_index++) {
- if (!STREQ(rp->name, rpass->name)) {
- iuser->pass = rp_index;
- changed = true;
- break;
- }
- }
- }
- else if (direction == 1) {
- RenderPass *rp;
- int rp_index = 0;
-
- if (iuser->pass == 0) {
- BKE_image_release_renderresult(scene, image);
- return false;
- }
-
- for (rp = rl->passes.first; rp; rp = rp->next, rp_index++) {
- if (STREQ(rp->name, rpass->name)) {
- iuser->pass = rp_index - 1;
- changed = true;
- break;
- }
- }
- }
- else {
- BLI_assert(0);
- }
-
- BKE_image_release_renderresult(scene, image);
-
- if (changed) {
- BKE_image_multilayer_index(rr, iuser);
- WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
- }
-
- return changed;
+ Scene *scene = CTX_data_scene(C);
+ struct ImageUI_Data *rnd_data = rnd_pt;
+ Image *image = rnd_data->image;
+ ImageUser *iuser = rnd_data->iuser;
+ RenderResult *rr;
+ bool changed = false;
+ int layer = iuser->layer;
+ RenderLayer *rl;
+ RenderPass *rpass;
+
+ rr = BKE_image_acquire_renderresult(scene, image);
+ if (UNLIKELY(rr == NULL)) {
+ BKE_image_release_renderresult(scene, image);
+ return false;
+ }
+
+ if (RE_HasCombinedLayer(rr)) {
+ layer -= 1;
+ }
+
+ rl = BLI_findlink(&rr->layers, layer);
+ if (rl == NULL) {
+ BKE_image_release_renderresult(scene, image);
+ return false;
+ }
+
+ rpass = BLI_findlink(&rl->passes, iuser->pass);
+ if (rpass == NULL) {
+ BKE_image_release_renderresult(scene, image);
+ return false;
+ }
+
+ /* note, this looks reversed, but matches menu direction */
+ if (direction == -1) {
+ RenderPass *rp;
+ int rp_index = iuser->pass + 1;
+
+ for (rp = rpass->next; rp; rp = rp->next, rp_index++) {
+ if (!STREQ(rp->name, rpass->name)) {
+ iuser->pass = rp_index;
+ changed = true;
+ break;
+ }
+ }
+ }
+ else if (direction == 1) {
+ RenderPass *rp;
+ int rp_index = 0;
+
+ if (iuser->pass == 0) {
+ BKE_image_release_renderresult(scene, image);
+ return false;
+ }
+
+ for (rp = rl->passes.first; rp; rp = rp->next, rp_index++) {
+ if (STREQ(rp->name, rpass->name)) {
+ iuser->pass = rp_index - 1;
+ changed = true;
+ break;
+ }
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ BKE_image_release_renderresult(scene, image);
+
+ if (changed) {
+ BKE_image_multilayer_index(rr, iuser);
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+ }
+
+ return changed;
}
/* 5 view button callbacks... */
static void image_multiview_cb(bContext *C, void *rnd_pt, void *UNUSED(arg_v))
{
- struct ImageUI_Data *rnd_data = rnd_pt;
- Image *ima = rnd_data->image;
- ImageUser *iuser = rnd_data->iuser;
+ struct ImageUI_Data *rnd_data = rnd_pt;
+ Image *ima = rnd_data->image;
+ ImageUser *iuser = rnd_data->iuser;
- BKE_image_multiview_index(ima, iuser);
- WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+ BKE_image_multiview_index(ima, iuser);
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
}
#if 0
static void image_freecache_cb(bContext *C, void *ima_v, void *unused)
{
- Scene *scene = CTX_data_scene(C);
- BKE_image_free_anim_ibufs(ima_v, scene->r.cfra);
- WM_event_add_notifier(C, NC_IMAGE, ima_v);
+ Scene *scene = CTX_data_scene(C);
+ BKE_image_free_anim_ibufs(ima_v, scene->r.cfra);
+ WM_event_add_notifier(C, NC_IMAGE, ima_v);
}
#endif
#if 0
static void image_user_change(bContext *C, void *iuser_v, void *unused)
{
- Scene *scene = CTX_data_scene(C);
- BKE_image_user_calc_imanr(iuser_v, scene->r.cfra, 0);
+ Scene *scene = CTX_data_scene(C);
+ BKE_image_user_calc_imanr(iuser_v, scene->r.cfra, 0);
}
#endif
static void uiblock_layer_pass_buttons(
- uiLayout *layout, Image *image, RenderResult *rr, ImageUser *iuser, int w,
- short *render_slot)
+ uiLayout *layout, Image *image, RenderResult *rr, ImageUser *iuser, int w, short *render_slot)
{
- struct ImageUI_Data rnd_pt_local, *rnd_pt = NULL;
- uiBlock *block = uiLayoutGetBlock(layout);
- uiBut *but;
- RenderLayer *rl = NULL;
- int wmenu1, wmenu2, wmenu3, wmenu4;
- const char *fake_name;
- const char *display_name = "";
- const bool show_stereo = (iuser->flag & IMA_SHOW_STEREO) != 0;
-
- if (iuser->scene == NULL) {
- return;
- }
-
- uiLayoutRow(layout, true);
-
- /* layer menu is 1/3 larger than pass */
- wmenu1 = (2 * w) / 5;
- wmenu2 = (3 * w) / 5;
- wmenu3 = (3 * w) / 6;
- wmenu4 = (3 * w) / 6;
-
- rnd_pt_local.image = image;
- rnd_pt_local.iuser = iuser;
- rnd_pt_local.rpass_index = 0;
-
- /* menu buts */
- if (render_slot) {
- char str[64];
- RenderSlot *slot = BKE_image_get_renderslot(image, *render_slot);
- if (slot && slot->name[0] != '\0') {
- BLI_strncpy(str, slot->name, sizeof(str));
- }
- else {
- BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), *render_slot + 1);
- }
-
- rnd_pt = ui_imageuser_data_copy(&rnd_pt_local);
- but = uiDefMenuBut(block, ui_imageuser_slot_menu, image, str, 0, 0, wmenu1, UI_UNIT_Y, TIP_("Select Slot"));
- UI_but_func_menu_step_set(but, ui_imageuser_slot_menu_step);
- UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr);
- UI_but_type_set_menu_from_pulldown(but);
- rnd_pt = NULL;
- }
-
- if (rr) {
- RenderPass *rpass;
- RenderView *rview;
- int rpass_index;
-
- /* layer */
- fake_name = ui_imageuser_layer_fake_name(rr);
- rpass_index = iuser->layer - (fake_name ? 1 : 0);
- rl = BLI_findlink(&rr->layers, rpass_index);
- rnd_pt_local.rpass_index = rpass_index;
-
- if (RE_layers_have_name(rr)) {
- display_name = rl ? rl->name : (fake_name ? fake_name : "");
- rnd_pt = ui_imageuser_data_copy(&rnd_pt_local);
- but = uiDefMenuBut(
- block, ui_imageuser_layer_menu, rnd_pt, display_name,
- 0, 0, wmenu2, UI_UNIT_Y, TIP_("Select Layer"));
- UI_but_func_menu_step_set(but, ui_imageuser_layer_menu_step);
- UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr);
- UI_but_type_set_menu_from_pulldown(but);
- rnd_pt = NULL;
- }
-
- /* pass */
- rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass) : NULL);
-
- if (rpass && RE_passes_have_name(rl)) {
- display_name = rpass->name;
- rnd_pt = ui_imageuser_data_copy(&rnd_pt_local);
- but = uiDefMenuBut(
- block, ui_imageuser_pass_menu, rnd_pt, IFACE_(display_name),
- 0, 0, wmenu3, UI_UNIT_Y, TIP_("Select Pass"));
- UI_but_func_menu_step_set(but, ui_imageuser_pass_menu_step);
- UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr);
- UI_but_type_set_menu_from_pulldown(but);
- rnd_pt = NULL;
- }
-
- /* view */
- if (BLI_listbase_count_at_most(&rr->views, 2) > 1 &&
- ((!show_stereo) || (!RE_RenderResult_is_stereo(rr))))
- {
- rview = BLI_findlink(&rr->views, iuser->view);
- display_name = rview ? rview->name : "";
-
- rnd_pt = ui_imageuser_data_copy(&rnd_pt_local);
- but = uiDefMenuBut(
- block, ui_imageuser_view_menu_rr, rnd_pt, display_name,
- 0, 0, wmenu4, UI_UNIT_Y, TIP_("Select View"));
- UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr);
- UI_but_type_set_menu_from_pulldown(but);
- rnd_pt = NULL;
- }
- }
-
- /* stereo image */
- else if ((BKE_image_is_stereo(image) && (!show_stereo)) ||
- (BKE_image_is_multiview(image) && !BKE_image_is_stereo(image)))
- {
- ImageView *iv;
- int nr = 0;
-
- for (iv = image->views.first; iv; iv = iv->next) {
- if (nr++ == iuser->view) {
- display_name = iv->name;
- break;
- }
- }
-
- rnd_pt = ui_imageuser_data_copy(&rnd_pt_local);
- but = uiDefMenuBut(
- block, ui_imageuser_view_menu_multiview, rnd_pt, display_name,
- 0, 0, wmenu1, UI_UNIT_Y, TIP_("Select View"));
- UI_but_funcN_set(but, image_multiview_cb, rnd_pt, NULL);
- UI_but_type_set_menu_from_pulldown(but);
- rnd_pt = NULL;
- }
+ struct ImageUI_Data rnd_pt_local, *rnd_pt = NULL;
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiBut *but;
+ RenderLayer *rl = NULL;
+ int wmenu1, wmenu2, wmenu3, wmenu4;
+ const char *fake_name;
+ const char *display_name = "";
+ const bool show_stereo = (iuser->flag & IMA_SHOW_STEREO) != 0;
+
+ if (iuser->scene == NULL) {
+ return;
+ }
+
+ uiLayoutRow(layout, true);
+
+ /* layer menu is 1/3 larger than pass */
+ wmenu1 = (2 * w) / 5;
+ wmenu2 = (3 * w) / 5;
+ wmenu3 = (3 * w) / 6;
+ wmenu4 = (3 * w) / 6;
+
+ rnd_pt_local.image = image;
+ rnd_pt_local.iuser = iuser;
+ rnd_pt_local.rpass_index = 0;
+
+ /* menu buts */
+ if (render_slot) {
+ char str[64];
+ RenderSlot *slot = BKE_image_get_renderslot(image, *render_slot);
+ if (slot && slot->name[0] != '\0') {
+ BLI_strncpy(str, slot->name, sizeof(str));
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), *render_slot + 1);
+ }
+
+ rnd_pt = ui_imageuser_data_copy(&rnd_pt_local);
+ but = uiDefMenuBut(
+ block, ui_imageuser_slot_menu, image, str, 0, 0, wmenu1, UI_UNIT_Y, TIP_("Select Slot"));
+ UI_but_func_menu_step_set(but, ui_imageuser_slot_menu_step);
+ UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr);
+ UI_but_type_set_menu_from_pulldown(but);
+ rnd_pt = NULL;
+ }
+
+ if (rr) {
+ RenderPass *rpass;
+ RenderView *rview;
+ int rpass_index;
+
+ /* layer */
+ fake_name = ui_imageuser_layer_fake_name(rr);
+ rpass_index = iuser->layer - (fake_name ? 1 : 0);
+ rl = BLI_findlink(&rr->layers, rpass_index);
+ rnd_pt_local.rpass_index = rpass_index;
+
+ if (RE_layers_have_name(rr)) {
+ display_name = rl ? rl->name : (fake_name ? fake_name : "");
+ rnd_pt = ui_imageuser_data_copy(&rnd_pt_local);
+ but = uiDefMenuBut(block,
+ ui_imageuser_layer_menu,
+ rnd_pt,
+ display_name,
+ 0,
+ 0,
+ wmenu2,
+ UI_UNIT_Y,
+ TIP_("Select Layer"));
+ UI_but_func_menu_step_set(but, ui_imageuser_layer_menu_step);
+ UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr);
+ UI_but_type_set_menu_from_pulldown(but);
+ rnd_pt = NULL;
+ }
+
+ /* pass */
+ rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass) : NULL);
+
+ if (rpass && RE_passes_have_name(rl)) {
+ display_name = rpass->name;
+ rnd_pt = ui_imageuser_data_copy(&rnd_pt_local);
+ but = uiDefMenuBut(block,
+ ui_imageuser_pass_menu,
+ rnd_pt,
+ IFACE_(display_name),
+ 0,
+ 0,
+ wmenu3,
+ UI_UNIT_Y,
+ TIP_("Select Pass"));
+ UI_but_func_menu_step_set(but, ui_imageuser_pass_menu_step);
+ UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr);
+ UI_but_type_set_menu_from_pulldown(but);
+ rnd_pt = NULL;
+ }
+
+ /* view */
+ if (BLI_listbase_count_at_most(&rr->views, 2) > 1 &&
+ ((!show_stereo) || (!RE_RenderResult_is_stereo(rr)))) {
+ rview = BLI_findlink(&rr->views, iuser->view);
+ display_name = rview ? rview->name : "";
+
+ rnd_pt = ui_imageuser_data_copy(&rnd_pt_local);
+ but = uiDefMenuBut(block,
+ ui_imageuser_view_menu_rr,
+ rnd_pt,
+ display_name,
+ 0,
+ 0,
+ wmenu4,
+ UI_UNIT_Y,
+ TIP_("Select View"));
+ UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr);
+ UI_but_type_set_menu_from_pulldown(but);
+ rnd_pt = NULL;
+ }
+ }
+
+ /* stereo image */
+ else if ((BKE_image_is_stereo(image) && (!show_stereo)) ||
+ (BKE_image_is_multiview(image) && !BKE_image_is_stereo(image))) {
+ ImageView *iv;
+ int nr = 0;
+
+ for (iv = image->views.first; iv; iv = iv->next) {
+ if (nr++ == iuser->view) {
+ display_name = iv->name;
+ break;
+ }
+ }
+
+ rnd_pt = ui_imageuser_data_copy(&rnd_pt_local);
+ but = uiDefMenuBut(block,
+ ui_imageuser_view_menu_multiview,
+ rnd_pt,
+ display_name,
+ 0,
+ 0,
+ wmenu1,
+ UI_UNIT_Y,
+ TIP_("Select View"));
+ UI_but_funcN_set(but, image_multiview_cb, rnd_pt, NULL);
+ UI_but_type_set_menu_from_pulldown(but);
+ rnd_pt = NULL;
+ }
}
// XXX HACK!
// static int packdummy=0;
typedef struct RNAUpdateCb {
- PointerRNA ptr;
- PropertyRNA *prop;
- ImageUser *iuser;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ ImageUser *iuser;
} RNAUpdateCb;
static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
{
- RNAUpdateCb *cb = (RNAUpdateCb *)arg_cb;
+ RNAUpdateCb *cb = (RNAUpdateCb *)arg_cb;
- /* ideally this would be done by RNA itself, but there we have
- * no image user available, so we just update this flag here */
- cb->iuser->ok = 1;
+ /* ideally this would be done by RNA itself, but there we have
+ * no image user available, so we just update this flag here */
+ cb->iuser->ok = 1;
- /* we call update here on the pointer property, this way the
- * owner of the image pointer can still define it's own update
- * and notifier */
- RNA_property_update(C, &cb->ptr, cb->prop);
+ /* we call update here on the pointer property, this way the
+ * owner of the image pointer can still define it's own update
+ * and notifier */
+ RNA_property_update(C, &cb->ptr, cb->prop);
}
-void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *userptr, bool compact, bool multiview)
+void uiTemplateImage(uiLayout *layout,
+ bContext *C,
+ PointerRNA *ptr,
+ const char *propname,
+ PointerRNA *userptr,
+ bool compact,
+ bool multiview)
{
- PropertyRNA *prop;
- PointerRNA imaptr;
- RNAUpdateCb *cb;
- Image *ima;
- ImageUser *iuser;
- Scene *scene = CTX_data_scene(C);
- uiLayout *row, *split, *col;
- uiBlock *block;
- char str[MAX_IMAGE_INFO_LEN];
-
- void *lock;
-
- if (!ptr->data) {
- return;
- }
-
- prop = RNA_struct_find_property(ptr, propname);
- if (!prop) {
- printf("%s: property not found: %s.%s\n",
- __func__, RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- if (RNA_property_type(prop) != PROP_POINTER) {
- printf("%s: expected pointer property for %s.%s\n",
- __func__, RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- block = uiLayoutGetBlock(layout);
-
- imaptr = RNA_property_pointer_get(ptr, prop);
- ima = imaptr.data;
- iuser = userptr->data;
-
- BKE_image_user_frame_calc(iuser, (int)scene->r.cfra);
-
- cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
- cb->ptr = *ptr;
- cb->prop = prop;
- cb->iuser = iuser;
-
- uiLayoutSetContextPointer(layout, "edit_image", &imaptr);
- uiLayoutSetContextPointer(layout, "edit_image_user", userptr);
-
- if (!compact) {
- uiTemplateID(
- layout, C, ptr, propname,
- ima ? NULL : "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
- }
-
- if (ima) {
- UI_block_funcN_set(block, rna_update_cb, MEM_dupallocN(cb), NULL);
-
- if (ima->source == IMA_SRC_VIEWER) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
- image_info(scene, iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN);
- BKE_image_release_ibuf(ima, ibuf, lock);
-
- uiItemL(layout, ima->id.name + 2, ICON_NONE);
- uiItemL(layout, str, ICON_NONE);
-
- if (ima->type == IMA_TYPE_COMPOSITE) {
- // XXX not working yet
+ PropertyRNA *prop;
+ PointerRNA imaptr;
+ RNAUpdateCb *cb;
+ Image *ima;
+ ImageUser *iuser;
+ Scene *scene = CTX_data_scene(C);
+ uiLayout *row, *split, *col;
+ uiBlock *block;
+ char str[MAX_IMAGE_INFO_LEN];
+
+ void *lock;
+
+ if (!ptr->data) {
+ return;
+ }
+
+ prop = RNA_struct_find_property(ptr, propname);
+ if (!prop) {
+ printf(
+ "%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ if (RNA_property_type(prop) != PROP_POINTER) {
+ printf("%s: expected pointer property for %s.%s\n",
+ __func__,
+ RNA_struct_identifier(ptr->type),
+ propname);
+ return;
+ }
+
+ block = uiLayoutGetBlock(layout);
+
+ imaptr = RNA_property_pointer_get(ptr, prop);
+ ima = imaptr.data;
+ iuser = userptr->data;
+
+ BKE_image_user_frame_calc(iuser, (int)scene->r.cfra);
+
+ cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
+ cb->ptr = *ptr;
+ cb->prop = prop;
+ cb->iuser = iuser;
+
+ uiLayoutSetContextPointer(layout, "edit_image", &imaptr);
+ uiLayoutSetContextPointer(layout, "edit_image_user", userptr);
+
+ if (!compact) {
+ uiTemplateID(layout,
+ C,
+ ptr,
+ propname,
+ ima ? NULL : "IMAGE_OT_new",
+ "IMAGE_OT_open",
+ NULL,
+ UI_TEMPLATE_ID_FILTER_ALL,
+ false);
+ }
+
+ if (ima) {
+ UI_block_funcN_set(block, rna_update_cb, MEM_dupallocN(cb), NULL);
+
+ if (ima->source == IMA_SRC_VIEWER) {
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
+ image_info(scene, iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN);
+ BKE_image_release_ibuf(ima, ibuf, lock);
+
+ uiItemL(layout, ima->id.name + 2, ICON_NONE);
+ uiItemL(layout, str, ICON_NONE);
+
+ if (ima->type == IMA_TYPE_COMPOSITE) {
+ // XXX not working yet
#if 0
- iuser = ntree_get_active_iuser(scene->nodetree);
- if (iuser) {
- UI_block_align_begin(block);
- uiDefIconTextBut(block, UI_BTYPE_BUT, B_SIMA_RECORD, ICON_REC, "Record", 10, 120, 100, 20, 0, 0, 0, 0, 0, "");
- uiDefIconTextBut(block, UI_BTYPE_BUT, B_SIMA_PLAY, ICON_PLAY, "Play", 110, 120, 100, 20, 0, 0, 0, 0, 0, "");
- but = uiDefBut(block, UI_BTYPE_BUT, B_NOP, "Free Cache", 210, 120, 100, 20, 0, 0, 0, 0, 0, "");
- UI_but_func_set(but, image_freecache_cb, ima, NULL);
-
- if (iuser->frames)
- BLI_snprintf(str, sizeof(str), "(%d) Frames:", iuser->framenr);
- else strcpy(str, "Frames:");
- UI_block_align_begin(block);
- uiDefButI(block, UI_BTYPE_NUM, imagechanged, str, 10, 90, 150, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Number of images of a movie to use");
- uiDefButI(block, UI_BTYPE_NUM, imagechanged, "StartFr:", 160, 90, 150, 20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Global starting frame of the movie");
- }
+ iuser = ntree_get_active_iuser(scene->nodetree);
+ if (iuser) {
+ UI_block_align_begin(block);
+ uiDefIconTextBut(block, UI_BTYPE_BUT, B_SIMA_RECORD, ICON_REC, "Record", 10, 120, 100, 20, 0, 0, 0, 0, 0, "");
+ uiDefIconTextBut(block, UI_BTYPE_BUT, B_SIMA_PLAY, ICON_PLAY, "Play", 110, 120, 100, 20, 0, 0, 0, 0, 0, "");
+ but = uiDefBut(block, UI_BTYPE_BUT, B_NOP, "Free Cache", 210, 120, 100, 20, 0, 0, 0, 0, 0, "");
+ UI_but_func_set(but, image_freecache_cb, ima, NULL);
+
+ if (iuser->frames)
+ BLI_snprintf(str, sizeof(str), "(%d) Frames:", iuser->framenr);
+ else strcpy(str, "Frames:");
+ UI_block_align_begin(block);
+ uiDefButI(block, UI_BTYPE_NUM, imagechanged, str, 10, 90, 150, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Number of images of a movie to use");
+ uiDefButI(block, UI_BTYPE_NUM, imagechanged, "StartFr:", 160, 90, 150, 20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Global starting frame of the movie");
+ }
#endif
- }
- else if (ima->type == IMA_TYPE_R_RESULT) {
- /* browse layer/passes */
- RenderResult *rr;
- const float dpi_fac = UI_DPI_FAC;
- const int menus_width = 230 * dpi_fac;
-
- /* use BKE_image_acquire_renderresult so we get the correct slot in the menu */
- rr = BKE_image_acquire_renderresult(scene, ima);
- uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot);
- BKE_image_release_renderresult(scene, ima);
- }
- }
- else {
- uiItemR(layout, &imaptr, "source", 0, NULL, ICON_NONE);
-
- if (ima->source != IMA_SRC_GENERATED) {
- row = uiLayoutRow(layout, true);
- if (BKE_image_has_packedfile(ima)) {
- uiItemO(row, "", ICON_PACKAGE, "image.unpack");
- }
- else {
- uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
- }
-
- row = uiLayoutRow(row, true);
- uiLayoutSetEnabled(row, BKE_image_has_packedfile(ima) == false);
- uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
- uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
- }
-
- /* multilayer? */
- if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
- const float dpi_fac = UI_DPI_FAC;
- uiblock_layer_pass_buttons(layout, ima, ima->rr, iuser, 230 * dpi_fac, NULL);
- }
- else if (ima->source != IMA_SRC_GENERATED) {
- if (compact == 0) {
- uiTemplateImageInfo(layout, C, ima, iuser);
- }
- }
-
- col = uiLayoutColumn(layout, false);
- uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings");
- uiItemR(col, &imaptr, "use_view_as_render", 0, NULL, ICON_NONE);
-
- if (ima->source != IMA_SRC_GENERATED) {
- if (compact == 0) { /* background image view doesn't need these */
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
- bool has_alpha = true;
-
- if (ibuf) {
- int imtype = BKE_image_ftype_to_imtype(ibuf->ftype, &ibuf->foptions);
- char valid_channels = BKE_imtype_valid_channels(imtype, false);
-
- has_alpha = (valid_channels & IMA_CHAN_FLAG_ALPHA) != 0;
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
-
- if (multiview) {
- if ((scene->r.scemode & R_MULTIVIEW) != 0) {
- uiItemR(layout, &imaptr, "use_multiview", 0, NULL, ICON_NONE);
-
- if (RNA_boolean_get(&imaptr, "use_multiview")) {
- uiTemplateImageViews(layout, &imaptr);
- }
- }
- }
-
- if (has_alpha) {
- col = uiLayoutColumn(layout, false);
- uiItemR(col, &imaptr, "use_alpha", 0, NULL, ICON_NONE);
- row = uiLayoutRow(col, false);
- uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_alpha"));
- uiItemR(row, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE);
- }
-
- if (ima->source == IMA_SRC_MOVIE) {
- col = uiLayoutColumn(layout, false);
- uiItemR(col, &imaptr, "use_deinterlace", 0, IFACE_("Deinterlace"), ICON_NONE);
- }
- }
- }
-
- if (BKE_image_is_animated(ima)) {
- uiItemS(layout);
-
- split = uiLayoutSplit(layout, 0.0f, false);
-
- col = uiLayoutColumn(split, false);
-
- BLI_snprintf(str, sizeof(str), IFACE_("(%d) Frames"), iuser->framenr);
- uiItemR(col, userptr, "frame_duration", 0, str, ICON_NONE);
- uiItemR(col, userptr, "frame_start", 0, IFACE_("Start"), ICON_NONE);
- uiItemR(col, userptr, "frame_offset", 0, NULL, ICON_NONE);
-
- col = uiLayoutColumn(split, false);
- uiItemO(col, NULL, ICON_NONE, "IMAGE_OT_match_movie_length");
- uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE);
- uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE);
- }
- else if (ima->source == IMA_SRC_GENERATED) {
- split = uiLayoutSplit(layout, 0.0f, false);
-
- col = uiLayoutColumn(split, true);
- uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE);
- uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE);
-
- uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE);
-
- uiItemR(split, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
-
- if (ima->gen_type == IMA_GENTYPE_BLANK) {
- uiItemR(layout, &imaptr, "generated_color", 0, NULL, ICON_NONE);
- }
- }
-
- }
-
- UI_block_funcN_set(block, NULL, NULL, NULL);
- }
-
- MEM_freeN(cb);
+ }
+ else if (ima->type == IMA_TYPE_R_RESULT) {
+ /* browse layer/passes */
+ RenderResult *rr;
+ const float dpi_fac = UI_DPI_FAC;
+ const int menus_width = 230 * dpi_fac;
+
+ /* use BKE_image_acquire_renderresult so we get the correct slot in the menu */
+ rr = BKE_image_acquire_renderresult(scene, ima);
+ uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot);
+ BKE_image_release_renderresult(scene, ima);
+ }
+ }
+ else {
+ uiItemR(layout, &imaptr, "source", 0, NULL, ICON_NONE);
+
+ if (ima->source != IMA_SRC_GENERATED) {
+ row = uiLayoutRow(layout, true);
+ if (BKE_image_has_packedfile(ima)) {
+ uiItemO(row, "", ICON_PACKAGE, "image.unpack");
+ }
+ else {
+ uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
+ }
+
+ row = uiLayoutRow(row, true);
+ uiLayoutSetEnabled(row, BKE_image_has_packedfile(ima) == false);
+ uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
+ uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
+ }
+
+ /* multilayer? */
+ if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
+ const float dpi_fac = UI_DPI_FAC;
+ uiblock_layer_pass_buttons(layout, ima, ima->rr, iuser, 230 * dpi_fac, NULL);
+ }
+ else if (ima->source != IMA_SRC_GENERATED) {
+ if (compact == 0) {
+ uiTemplateImageInfo(layout, C, ima, iuser);
+ }
+ }
+
+ col = uiLayoutColumn(layout, false);
+ uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings");
+ uiItemR(col, &imaptr, "use_view_as_render", 0, NULL, ICON_NONE);
+
+ if (ima->source != IMA_SRC_GENERATED) {
+ if (compact == 0) { /* background image view doesn't need these */
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
+ bool has_alpha = true;
+
+ if (ibuf) {
+ int imtype = BKE_image_ftype_to_imtype(ibuf->ftype, &ibuf->foptions);
+ char valid_channels = BKE_imtype_valid_channels(imtype, false);
+
+ has_alpha = (valid_channels & IMA_CHAN_FLAG_ALPHA) != 0;
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+
+ if (multiview) {
+ if ((scene->r.scemode & R_MULTIVIEW) != 0) {
+ uiItemR(layout, &imaptr, "use_multiview", 0, NULL, ICON_NONE);
+
+ if (RNA_boolean_get(&imaptr, "use_multiview")) {
+ uiTemplateImageViews(layout, &imaptr);
+ }
+ }
+ }
+
+ if (has_alpha) {
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, &imaptr, "use_alpha", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(col, false);
+ uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_alpha"));
+ uiItemR(row, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE);
+ }
+
+ if (ima->source == IMA_SRC_MOVIE) {
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, &imaptr, "use_deinterlace", 0, IFACE_("Deinterlace"), ICON_NONE);
+ }
+ }
+ }
+
+ if (BKE_image_is_animated(ima)) {
+ uiItemS(layout);
+
+ split = uiLayoutSplit(layout, 0.0f, false);
+
+ col = uiLayoutColumn(split, false);
+
+ BLI_snprintf(str, sizeof(str), IFACE_("(%d) Frames"), iuser->framenr);
+ uiItemR(col, userptr, "frame_duration", 0, str, ICON_NONE);
+ uiItemR(col, userptr, "frame_start", 0, IFACE_("Start"), ICON_NONE);
+ uiItemR(col, userptr, "frame_offset", 0, NULL, ICON_NONE);
+
+ col = uiLayoutColumn(split, false);
+ uiItemO(col, NULL, ICON_NONE, "IMAGE_OT_match_movie_length");
+ uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE);
+ uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE);
+ }
+ else if (ima->source == IMA_SRC_GENERATED) {
+ split = uiLayoutSplit(layout, 0.0f, false);
+
+ col = uiLayoutColumn(split, true);
+ uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE);
+ uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE);
+
+ uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE);
+
+ uiItemR(split, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+
+ if (ima->gen_type == IMA_GENTYPE_BLANK) {
+ uiItemR(layout, &imaptr, "generated_color", 0, NULL, ICON_NONE);
+ }
+ }
+ }
+
+ UI_block_funcN_set(block, NULL, NULL, NULL);
+ }
+
+ MEM_freeN(cb);
}
void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, bool color_management)
{
- ImageFormatData *imf = imfptr->data;
- ID *id = imfptr->id.data;
- PointerRNA display_settings_ptr;
- PropertyRNA *prop;
- const int depth_ok = BKE_imtype_valid_depths(imf->imtype);
- /* some settings depend on this being a scene that's rendered */
- const bool is_render_out = (id && GS(id->name) == ID_SCE);
-
- uiLayout *col;
- bool show_preview = false;
-
- col = uiLayoutColumn(layout, false);
-
- uiLayoutSetPropSep(col, true);
- uiLayoutSetPropDecorate(col, false);
-
- uiItemR(col, imfptr, "file_format", 0, NULL, ICON_NONE);
- uiItemR(uiLayoutRow(col, true), imfptr, "color_mode", UI_ITEM_R_EXPAND, IFACE_("Color"), ICON_NONE);
-
- /* only display depth setting if multiple depths can be used */
- if ((ELEM(depth_ok,
- R_IMF_CHAN_DEPTH_1,
- R_IMF_CHAN_DEPTH_8,
- R_IMF_CHAN_DEPTH_10,
- R_IMF_CHAN_DEPTH_12,
- R_IMF_CHAN_DEPTH_16,
- R_IMF_CHAN_DEPTH_24,
- R_IMF_CHAN_DEPTH_32)) == 0)
- {
- uiItemR(uiLayoutRow(col, true), imfptr, "color_depth", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
- }
-
- if (BKE_imtype_supports_quality(imf->imtype)) {
- uiItemR(col, imfptr, "quality", 0, NULL, ICON_NONE);
- }
-
- if (BKE_imtype_supports_compress(imf->imtype)) {
- uiItemR(col, imfptr, "compression", 0, NULL, ICON_NONE);
- }
-
- if (ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) {
- uiItemR(col, imfptr, "exr_codec", 0, NULL, ICON_NONE);
- }
-
- if (BKE_imtype_supports_zbuf(imf->imtype)) {
- uiItemR(col, imfptr, "use_zbuffer", 0, NULL, ICON_NONE);
- }
-
- if (is_render_out && ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) {
- show_preview = true;
- uiItemR(col, imfptr, "use_preview", 0, NULL, ICON_NONE);
- }
-
- if (imf->imtype == R_IMF_IMTYPE_JP2) {
- uiItemR(col, imfptr, "jpeg2k_codec", 0, NULL, ICON_NONE);
-
- uiItemR(col, imfptr, "use_jpeg2k_cinema_preset", 0, NULL, ICON_NONE);
- uiItemR(col, imfptr, "use_jpeg2k_cinema_48", 0, NULL, ICON_NONE);
-
- uiItemR(col, imfptr, "use_jpeg2k_ycc", 0, NULL, ICON_NONE);
- }
-
- if (imf->imtype == R_IMF_IMTYPE_DPX) {
- uiItemR(col, imfptr, "use_cineon_log", 0, NULL, ICON_NONE);
- }
-
- if (imf->imtype == R_IMF_IMTYPE_CINEON) {
+ ImageFormatData *imf = imfptr->data;
+ ID *id = imfptr->id.data;
+ PointerRNA display_settings_ptr;
+ PropertyRNA *prop;
+ const int depth_ok = BKE_imtype_valid_depths(imf->imtype);
+ /* some settings depend on this being a scene that's rendered */
+ const bool is_render_out = (id && GS(id->name) == ID_SCE);
+
+ uiLayout *col;
+ bool show_preview = false;
+
+ col = uiLayoutColumn(layout, false);
+
+ uiLayoutSetPropSep(col, true);
+ uiLayoutSetPropDecorate(col, false);
+
+ uiItemR(col, imfptr, "file_format", 0, NULL, ICON_NONE);
+ uiItemR(
+ uiLayoutRow(col, true), imfptr, "color_mode", UI_ITEM_R_EXPAND, IFACE_("Color"), ICON_NONE);
+
+ /* only display depth setting if multiple depths can be used */
+ if ((ELEM(depth_ok,
+ R_IMF_CHAN_DEPTH_1,
+ R_IMF_CHAN_DEPTH_8,
+ R_IMF_CHAN_DEPTH_10,
+ R_IMF_CHAN_DEPTH_12,
+ R_IMF_CHAN_DEPTH_16,
+ R_IMF_CHAN_DEPTH_24,
+ R_IMF_CHAN_DEPTH_32)) == 0) {
+ uiItemR(uiLayoutRow(col, true), imfptr, "color_depth", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ }
+
+ if (BKE_imtype_supports_quality(imf->imtype)) {
+ uiItemR(col, imfptr, "quality", 0, NULL, ICON_NONE);
+ }
+
+ if (BKE_imtype_supports_compress(imf->imtype)) {
+ uiItemR(col, imfptr, "compression", 0, NULL, ICON_NONE);
+ }
+
+ if (ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) {
+ uiItemR(col, imfptr, "exr_codec", 0, NULL, ICON_NONE);
+ }
+
+ if (BKE_imtype_supports_zbuf(imf->imtype)) {
+ uiItemR(col, imfptr, "use_zbuffer", 0, NULL, ICON_NONE);
+ }
+
+ if (is_render_out && ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) {
+ show_preview = true;
+ uiItemR(col, imfptr, "use_preview", 0, NULL, ICON_NONE);
+ }
+
+ if (imf->imtype == R_IMF_IMTYPE_JP2) {
+ uiItemR(col, imfptr, "jpeg2k_codec", 0, NULL, ICON_NONE);
+
+ uiItemR(col, imfptr, "use_jpeg2k_cinema_preset", 0, NULL, ICON_NONE);
+ uiItemR(col, imfptr, "use_jpeg2k_cinema_48", 0, NULL, ICON_NONE);
+
+ uiItemR(col, imfptr, "use_jpeg2k_ycc", 0, NULL, ICON_NONE);
+ }
+
+ if (imf->imtype == R_IMF_IMTYPE_DPX) {
+ uiItemR(col, imfptr, "use_cineon_log", 0, NULL, ICON_NONE);
+ }
+
+ if (imf->imtype == R_IMF_IMTYPE_CINEON) {
#if 1
- uiItemL(col, IFACE_("Hard coded Non-Linear, Gamma:1.7"), ICON_NONE);
+ uiItemL(col, IFACE_("Hard coded Non-Linear, Gamma:1.7"), ICON_NONE);
#else
- uiItemR(col, imfptr, "use_cineon_log", 0, NULL, ICON_NONE);
- uiItemR(col, imfptr, "cineon_black", 0, NULL, ICON_NONE);
- uiItemR(col, imfptr, "cineon_white", 0, NULL, ICON_NONE);
- uiItemR(col, imfptr, "cineon_gamma", 0, NULL, ICON_NONE);
+ uiItemR(col, imfptr, "use_cineon_log", 0, NULL, ICON_NONE);
+ uiItemR(col, imfptr, "cineon_black", 0, NULL, ICON_NONE);
+ uiItemR(col, imfptr, "cineon_white", 0, NULL, ICON_NONE);
+ uiItemR(col, imfptr, "cineon_gamma", 0, NULL, ICON_NONE);
#endif
- }
+ }
- if (imf->imtype == R_IMF_IMTYPE_TIFF) {
- uiItemR(col, imfptr, "tiff_codec", 0, NULL, ICON_NONE);
- }
+ if (imf->imtype == R_IMF_IMTYPE_TIFF) {
+ uiItemR(col, imfptr, "tiff_codec", 0, NULL, ICON_NONE);
+ }
- /* color management */
- if (color_management &&
- (!BKE_imtype_requires_linear_float(imf->imtype) ||
- (show_preview && imf->flag & R_IMF_FLAG_PREVIEW_JPG)))
- {
- prop = RNA_struct_find_property(imfptr, "display_settings");
- display_settings_ptr = RNA_property_pointer_get(imfptr, prop);
+ /* color management */
+ if (color_management && (!BKE_imtype_requires_linear_float(imf->imtype) ||
+ (show_preview && imf->flag & R_IMF_FLAG_PREVIEW_JPG))) {
+ prop = RNA_struct_find_property(imfptr, "display_settings");
+ display_settings_ptr = RNA_property_pointer_get(imfptr, prop);
- col = uiLayoutColumn(layout, false);
- uiItemL(col, IFACE_("Color Management"), ICON_NONE);
+ col = uiLayoutColumn(layout, false);
+ uiItemL(col, IFACE_("Color Management"), ICON_NONE);
- uiItemR(col, &display_settings_ptr, "display_device", 0, NULL, ICON_NONE);
+ uiItemR(col, &display_settings_ptr, "display_device", 0, NULL, ICON_NONE);
- uiTemplateColormanagedViewSettings(col, NULL, imfptr, "view_settings");
- }
+ uiTemplateColormanagedViewSettings(col, NULL, imfptr, "view_settings");
+ }
}
void uiTemplateImageStereo3d(uiLayout *layout, PointerRNA *stereo3d_format_ptr)
{
- Stereo3dFormat *stereo3d_format = stereo3d_format_ptr->data;
- uiLayout *col;
-
- col = uiLayoutColumn(layout, false);
- uiItemR(col, stereo3d_format_ptr, "display_mode", 0, NULL, ICON_NONE);
-
- switch (stereo3d_format->display_mode) {
- case S3D_DISPLAY_ANAGLYPH:
- {
- uiItemR(col, stereo3d_format_ptr, "anaglyph_type", 0, NULL, ICON_NONE);
- break;
- }
- case S3D_DISPLAY_INTERLACE:
- {
- uiItemR(col, stereo3d_format_ptr, "interlace_type", 0, NULL, ICON_NONE);
- uiItemR(col, stereo3d_format_ptr, "use_interlace_swap", 0, NULL, ICON_NONE);
- break;
- }
- case S3D_DISPLAY_SIDEBYSIDE:
- {
- uiItemR(col, stereo3d_format_ptr, "use_sidebyside_crosseyed", 0, NULL, ICON_NONE);
- ATTR_FALLTHROUGH;
- }
- case S3D_DISPLAY_TOPBOTTOM:
- {
- uiItemR(col, stereo3d_format_ptr, "use_squeezed_frame", 0, NULL, ICON_NONE);
- break;
- }
- }
+ Stereo3dFormat *stereo3d_format = stereo3d_format_ptr->data;
+ uiLayout *col;
+
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, stereo3d_format_ptr, "display_mode", 0, NULL, ICON_NONE);
+
+ switch (stereo3d_format->display_mode) {
+ case S3D_DISPLAY_ANAGLYPH: {
+ uiItemR(col, stereo3d_format_ptr, "anaglyph_type", 0, NULL, ICON_NONE);
+ break;
+ }
+ case S3D_DISPLAY_INTERLACE: {
+ uiItemR(col, stereo3d_format_ptr, "interlace_type", 0, NULL, ICON_NONE);
+ uiItemR(col, stereo3d_format_ptr, "use_interlace_swap", 0, NULL, ICON_NONE);
+ break;
+ }
+ case S3D_DISPLAY_SIDEBYSIDE: {
+ uiItemR(col, stereo3d_format_ptr, "use_sidebyside_crosseyed", 0, NULL, ICON_NONE);
+ ATTR_FALLTHROUGH;
+ }
+ case S3D_DISPLAY_TOPBOTTOM: {
+ uiItemR(col, stereo3d_format_ptr, "use_squeezed_frame", 0, NULL, ICON_NONE);
+ break;
+ }
+ }
}
-static void uiTemplateViewsFormat(uiLayout *layout, PointerRNA *ptr, PointerRNA *stereo3d_format_ptr)
+static void uiTemplateViewsFormat(uiLayout *layout,
+ PointerRNA *ptr,
+ PointerRNA *stereo3d_format_ptr)
{
- uiLayout *col;
+ uiLayout *col;
- col = uiLayoutColumn(layout, false);
+ col = uiLayoutColumn(layout, false);
- uiLayoutSetPropSep(col, true);
- uiLayoutSetPropDecorate(col, false);
+ uiLayoutSetPropSep(col, true);
+ uiLayoutSetPropDecorate(col, false);
- uiItemR(col, ptr, "views_format", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(col, ptr, "views_format", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
- if (stereo3d_format_ptr &&
- RNA_enum_get(ptr, "views_format") == R_IMF_VIEWS_STEREO_3D)
- {
- uiTemplateImageStereo3d(col, stereo3d_format_ptr);
- }
+ if (stereo3d_format_ptr && RNA_enum_get(ptr, "views_format") == R_IMF_VIEWS_STEREO_3D) {
+ uiTemplateImageStereo3d(col, stereo3d_format_ptr);
+ }
}
void uiTemplateImageViews(uiLayout *layout, PointerRNA *imaptr)
{
- Image *ima = imaptr->data;
+ Image *ima = imaptr->data;
- if (ima->type != IMA_TYPE_MULTILAYER) {
- PropertyRNA *prop;
- PointerRNA stereo3d_format_ptr;
+ if (ima->type != IMA_TYPE_MULTILAYER) {
+ PropertyRNA *prop;
+ PointerRNA stereo3d_format_ptr;
- prop = RNA_struct_find_property(imaptr, "stereo_3d_format");
- stereo3d_format_ptr = RNA_property_pointer_get(imaptr, prop);
+ prop = RNA_struct_find_property(imaptr, "stereo_3d_format");
+ stereo3d_format_ptr = RNA_property_pointer_get(imaptr, prop);
- uiTemplateViewsFormat(layout, imaptr, &stereo3d_format_ptr);
- }
- else {
- uiTemplateViewsFormat(layout, imaptr, NULL);
- }
+ uiTemplateViewsFormat(layout, imaptr, &stereo3d_format_ptr);
+ }
+ else {
+ uiTemplateViewsFormat(layout, imaptr, NULL);
+ }
}
void uiTemplateImageFormatViews(uiLayout *layout, PointerRNA *imfptr, PointerRNA *ptr)
{
- ImageFormatData *imf = imfptr->data;
+ ImageFormatData *imf = imfptr->data;
- if (ptr == NULL) {
- return;
- }
+ if (ptr == NULL) {
+ return;
+ }
- uiItemR(layout, ptr, "use_multiview", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_multiview", 0, NULL, ICON_NONE);
- if (RNA_boolean_get(ptr, "use_multiview")) {
- if (imf->imtype != R_IMF_IMTYPE_MULTILAYER) {
- PropertyRNA *prop;
- PointerRNA stereo3d_format_ptr;
+ if (RNA_boolean_get(ptr, "use_multiview")) {
+ if (imf->imtype != R_IMF_IMTYPE_MULTILAYER) {
+ PropertyRNA *prop;
+ PointerRNA stereo3d_format_ptr;
- prop = RNA_struct_find_property(imfptr, "stereo_3d_format");
- stereo3d_format_ptr = RNA_property_pointer_get(imfptr, prop);
+ prop = RNA_struct_find_property(imfptr, "stereo_3d_format");
+ stereo3d_format_ptr = RNA_property_pointer_get(imfptr, prop);
- uiTemplateViewsFormat(layout, imfptr, &stereo3d_format_ptr);
- }
- else {
- uiTemplateViewsFormat(layout, imfptr, NULL);
- }
- }
+ uiTemplateViewsFormat(layout, imfptr, &stereo3d_format_ptr);
+ }
+ else {
+ uiTemplateViewsFormat(layout, imfptr, NULL);
+ }
+ }
}
void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
{
- Scene *scene = CTX_data_scene(C);
-
- /* render layers and passes */
- if (ima && iuser) {
- RenderResult *rr;
- const float dpi_fac = UI_DPI_FAC;
- const int menus_width = 160 * dpi_fac;
- const bool is_render_result = (ima->type == IMA_TYPE_R_RESULT);
-
- /* use BKE_image_acquire_renderresult so we get the correct slot in the menu */
- rr = BKE_image_acquire_renderresult(scene, ima);
- uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width,
- is_render_result ? &ima->render_slot : NULL);
- BKE_image_release_renderresult(scene, ima);
- }
+ Scene *scene = CTX_data_scene(C);
+
+ /* render layers and passes */
+ if (ima && iuser) {
+ RenderResult *rr;
+ const float dpi_fac = UI_DPI_FAC;
+ const int menus_width = 160 * dpi_fac;
+ const bool is_render_result = (ima->type == IMA_TYPE_R_RESULT);
+
+ /* use BKE_image_acquire_renderresult so we get the correct slot in the menu */
+ rr = BKE_image_acquire_renderresult(scene, ima);
+ uiblock_layer_pass_buttons(
+ layout, ima, rr, iuser, menus_width, is_render_result ? &ima->render_slot : NULL);
+ BKE_image_release_renderresult(scene, ima);
+ }
}
void uiTemplateImageInfo(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
{
- Scene *scene = CTX_data_scene(C);
- ImBuf *ibuf;
- char str[MAX_IMAGE_INFO_LEN];
- void *lock;
+ Scene *scene = CTX_data_scene(C);
+ ImBuf *ibuf;
+ char str[MAX_IMAGE_INFO_LEN];
+ void *lock;
- if (!ima || !iuser) {
- return;
- }
+ if (!ima || !iuser) {
+ return;
+ }
- ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
+ ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
- BKE_image_user_frame_calc(iuser, (int)scene->r.cfra);
- image_info(scene, iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN);
- BKE_image_release_ibuf(ima, ibuf, lock);
- uiItemL(layout, str, ICON_NONE);
+ BKE_image_user_frame_calc(iuser, (int)scene->r.cfra);
+ image_info(scene, iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN);
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ uiItemL(layout, str, ICON_NONE);
}
#undef MAX_IMAGE_INFO_LEN
static bool metadata_panel_context_poll(const bContext *C, PanelType *UNUSED(pt))
{
- SpaceImage *space_image = CTX_wm_space_image(C);
- return space_image != NULL && space_image->image != NULL;
+ SpaceImage *space_image = CTX_wm_space_image(C);
+ return space_image != NULL && space_image->image != NULL;
}
static void metadata_panel_context_draw(const bContext *C, Panel *panel)
{
- void *lock;
- SpaceImage *space_image = CTX_wm_space_image(C);
- Image *image = space_image->image;
- ImBuf *ibuf = BKE_image_acquire_ibuf(image, &space_image->iuser, &lock);
- if (ibuf != NULL) {
- ED_region_image_metadata_panel_draw(ibuf, panel->layout);
- }
- BKE_image_release_ibuf(image, ibuf, lock);
+ void *lock;
+ SpaceImage *space_image = CTX_wm_space_image(C);
+ Image *image = space_image->image;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(image, &space_image->iuser, &lock);
+ if (ibuf != NULL) {
+ ED_region_image_metadata_panel_draw(ibuf, panel->layout);
+ }
+ BKE_image_release_ibuf(image, ibuf, lock);
}
void image_buttons_register(ARegionType *art)
{
- PanelType *pt;
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype image panel metadata");
- strcpy(pt->idname, "IMAGE_PT_metadata");
- strcpy(pt->label, N_("Metadata"));
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->poll = metadata_panel_context_poll;
- pt->draw = metadata_panel_context_draw;
- pt->flag |= PNL_DEFAULT_CLOSED;
- BLI_addtail(&art->paneltypes, pt);
+ PanelType *pt;
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype image panel metadata");
+ strcpy(pt->idname, "IMAGE_PT_metadata");
+ strcpy(pt->label, N_("Metadata"));
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->poll = metadata_panel_context_poll;
+ pt->draw = metadata_panel_context_draw;
+ pt->flag |= PNL_DEFAULT_CLOSED;
+ BLI_addtail(&art->paneltypes, pt);
}
static int image_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = image_has_buttons_region(sa);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = image_has_buttons_region(sa);
- if (ar) {
- ED_region_toggle_hidden(C, ar);
- }
+ if (ar) {
+ ED_region_toggle_hidden(C, ar);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void IMAGE_OT_properties(wmOperatorType *ot)
{
- ot->name = "Toggle Sidebar";
- ot->idname = "IMAGE_OT_properties";
- ot->description = "Toggle the properties region visibility";
+ ot->name = "Toggle Sidebar";
+ ot->idname = "IMAGE_OT_properties";
+ ot->description = "Toggle the properties region visibility";
- ot->exec = image_properties_toggle_exec;
- ot->poll = ED_operator_image_active;
+ ot->exec = image_properties_toggle_exec;
+ ot->poll = ED_operator_image_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
static int image_scopes_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = image_has_tools_region(sa);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = image_has_tools_region(sa);
- if (ar) {
- ED_region_toggle_hidden(C, ar);
- }
+ if (ar) {
+ ED_region_toggle_hidden(C, ar);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void IMAGE_OT_toolshelf(wmOperatorType *ot)
{
- ot->name = "Toggle Toolbar";
- ot->idname = "IMAGE_OT_toolshelf";
- ot->description = "Toggles tool shelf display";
+ ot->name = "Toggle Toolbar";
+ ot->idname = "IMAGE_OT_toolshelf";
+ ot->description = "Toggles tool shelf display";
- ot->exec = image_scopes_toggle_exec;
- ot->poll = ED_operator_image_active;
+ ot->exec = image_scopes_toggle_exec;
+ ot->poll = ED_operator_image_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index ca0f9bd013f..a87808e1601 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -21,7 +21,6 @@
* \ingroup spimage
*/
-
#include <math.h>
#include <stdlib.h>
#include <string.h>
@@ -77,523 +76,589 @@
#include "image_intern.h"
-static void draw_render_info(const bContext *C,
- Scene *scene,
- Image *ima,
- ARegion *ar,
- float zoomx,
- float zoomy)
+static void draw_render_info(
+ const bContext *C, Scene *scene, Image *ima, ARegion *ar, float zoomx, float zoomy)
{
- Render *re = RE_GetSceneRender(scene);
- RenderData *rd = RE_engine_get_render_data(re);
- Scene *stats_scene = ED_render_job_get_scene(C);
- if (stats_scene == NULL) {
- stats_scene = CTX_data_scene(C);
- }
-
- RenderResult *rr = BKE_image_acquire_renderresult(stats_scene, ima);
-
- 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);
- }
-
- BKE_image_release_renderresult(stats_scene, ima);
-
- if (re) {
- int total_tiles;
- bool need_free_tiles;
- rcti *tiles = RE_engine_get_current_tiles(re, &total_tiles, &need_free_tiles);
-
- 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);
-
- GPU_matrix_push();
- GPU_matrix_translate_2f(x, y);
- GPU_matrix_scale_2f(zoomx, zoomy);
-
- if (rd->mode & R_BORDER) {
- /* TODO: round or floor instead of casting to int */
- GPU_matrix_translate_2f((int)(-rd->border.xmin * rd->xsch * rd->size * 0.01f),
- (int)(-rd->border.ymin * rd->ysch * rd->size * 0.01f));
- }
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor(TH_FACE_SELECT);
-
- GPU_line_width(1.0f);
-
- rcti *tile = tiles;
- for (int i = 0; i < total_tiles; i++, tile++) {
- immDrawBorderCorners(pos, tile, zoomx, zoomy);
- }
-
- immUnbindProgram();
-
- if (need_free_tiles) {
- MEM_freeN(tiles);
- }
-
- GPU_matrix_pop();
- }
- }
+ Render *re = RE_GetSceneRender(scene);
+ RenderData *rd = RE_engine_get_render_data(re);
+ Scene *stats_scene = ED_render_job_get_scene(C);
+ if (stats_scene == NULL) {
+ stats_scene = CTX_data_scene(C);
+ }
+
+ RenderResult *rr = BKE_image_acquire_renderresult(stats_scene, ima);
+
+ 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);
+ }
+
+ BKE_image_release_renderresult(stats_scene, ima);
+
+ if (re) {
+ int total_tiles;
+ bool need_free_tiles;
+ rcti *tiles = RE_engine_get_current_tiles(re, &total_tiles, &need_free_tiles);
+
+ 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);
+
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(x, y);
+ GPU_matrix_scale_2f(zoomx, zoomy);
+
+ if (rd->mode & R_BORDER) {
+ /* TODO: round or floor instead of casting to int */
+ GPU_matrix_translate_2f((int)(-rd->border.xmin * rd->xsch * rd->size * 0.01f),
+ (int)(-rd->border.ymin * rd->ysch * rd->size * 0.01f));
+ }
+
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_FACE_SELECT);
+
+ GPU_line_width(1.0f);
+
+ rcti *tile = tiles;
+ for (int i = 0; i < total_tiles; i++, tile++) {
+ immDrawBorderCorners(pos, tile, zoomx, zoomy);
+ }
+
+ immUnbindProgram();
+
+ if (need_free_tiles) {
+ MEM_freeN(tiles);
+ }
+
+ GPU_matrix_pop();
+ }
+ }
}
/* used by node view too */
-void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_default_view, int channels, int x, int y,
- const unsigned char cp[4], const float fp[4], const float linearcol[4], int *zp, float *zpf)
+void ED_image_draw_info(Scene *scene,
+ ARegion *ar,
+ bool color_manage,
+ bool use_default_view,
+ int channels,
+ int x,
+ int y,
+ const unsigned char cp[4],
+ const float fp[4],
+ const float linearcol[4],
+ int *zp,
+ float *zpf)
{
- rcti color_rect;
- char str[256];
- int dx = 6;
- /* local coordinate visible rect inside region, to accommodate overlapping ui */
- rcti rect;
- ED_region_visible_rect(ar, &rect);
- const int ymin = rect.ymin;
- const int dy = ymin + 0.3f * UI_UNIT_Y;
-
- /* text colors */
- /* XXX colored text not allowed in Blender UI */
+ rcti color_rect;
+ char str[256];
+ int dx = 6;
+ /* local coordinate visible rect inside region, to accommodate overlapping ui */
+ rcti rect;
+ ED_region_visible_rect(ar, &rect);
+ 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};
+ unsigned char red[3] = {255, 50, 50};
+ unsigned char green[3] = {0, 255, 0};
+ unsigned char 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};
+ unsigned char red[3] = {255, 255, 255};
+ unsigned char green[3] = {255, 255, 255};
+ unsigned char blue[3] = {255, 255, 255};
#endif
- float hue = 0, sat = 0, val = 0, lum = 0, u = 0, v = 0;
- float col[4], finalcol[4];
-
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* 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);
-
- immUnbindProgram();
-
- GPU_blend(false);
-
- BLF_size(blf_mono_font, 11 * U.pixelsize, U.dpi);
-
- BLF_color3ub(blf_mono_font, 255, 255, 255);
- SNPRINTF(str, "X:%-4d Y:%-4d |", x, y);
- BLF_position(blf_mono_font, dx, dy, 0);
- BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str, sizeof(str));
-
- if (zp) {
- BLF_color3ub(blf_mono_font, 255, 255, 255);
- SNPRINTF(str, " Z:%-.4f |", 0.5f + 0.5f * (((float)*zp) / (float)0x7fffffff));
- BLF_position(blf_mono_font, dx, dy, 0);
- BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str, sizeof(str));
- }
- if (zpf) {
- BLF_color3ub(blf_mono_font, 255, 255, 255);
- SNPRINTF(str, " Z:%-.3f |", *zpf);
- BLF_position(blf_mono_font, dx, dy, 0);
- BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str, sizeof(str));
- }
-
- if (channels == 1 && (cp != NULL || fp != NULL)) {
- if (fp != NULL) {
- SNPRINTF(str, " Val:%-.3f |", fp[0]);
- }
- else if (cp != NULL) {
- SNPRINTF(str, " Val:%-.3f |", cp[0] / 255.0f);
- }
- BLF_color3ub(blf_mono_font, 255, 255, 255);
- BLF_position(blf_mono_font, dx, dy, 0);
- BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str, sizeof(str));
- }
-
- if (channels >= 3) {
- BLF_color3ubv(blf_mono_font, red);
- if (fp) {
- SNPRINTF(str, " R:%-.5f", fp[0]);
- }
- else if (cp) {
- SNPRINTF(str, " R:%-3d", cp[0]);
- }
- else {
- STRNCPY(str, " R:-");
- }
- BLF_position(blf_mono_font, dx, dy, 0);
- BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str, sizeof(str));
-
- BLF_color3ubv(blf_mono_font, green);
- if (fp) {
- SNPRINTF(str, " G:%-.5f", fp[1]);
- }
- else if (cp) {
- SNPRINTF(str, " G:%-3d", cp[1]);
- }
- else {
- STRNCPY(str, " G:-");
- }
- BLF_position(blf_mono_font, dx, dy, 0);
- BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str, sizeof(str));
-
- BLF_color3ubv(blf_mono_font, blue);
- if (fp) {
- SNPRINTF(str, " B:%-.5f", fp[2]);
- }
- else if (cp) {
- SNPRINTF(str, " B:%-3d", cp[2]);
- }
- else {
- STRNCPY(str, " B:-");
- }
- BLF_position(blf_mono_font, dx, dy, 0);
- BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str, sizeof(str));
-
- if (channels == 4) {
- BLF_color3ub(blf_mono_font, 255, 255, 255);
- if (fp) {
- SNPRINTF(str, " A:%-.4f", fp[3]);
- }
- else if (cp) {
- SNPRINTF(str, " A:%-3d", cp[3]);
- }
- else {
- STRNCPY(str, "- ");
- }
- BLF_position(blf_mono_font, dx, dy, 0);
- BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str, sizeof(str));
- }
-
- if (color_manage) {
- float rgba[4];
-
- copy_v3_v3(rgba, linearcol);
- if (channels == 3) {
- rgba[3] = 1.0f;
- }
- else {
- rgba[3] = linearcol[3];
- }
-
- if (use_default_view) {
- IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, NULL, &scene->display_settings);
- }
- else {
- IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, &scene->view_settings, &scene->display_settings);
- }
-
- SNPRINTF(str, " | CM R:%-.4f G:%-.4f B:%-.4f", rgba[0], rgba[1], rgba[2]);
- BLF_position(blf_mono_font, dx, dy, 0);
- BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str, sizeof(str));
- }
- }
-
- /* color rectangle */
- if (channels == 1) {
- if (fp) {
- col[0] = col[1] = col[2] = fp[0];
- }
- else if (cp) {
- col[0] = col[1] = col[2] = (float)cp[0] / 255.0f;
- }
- else {
- col[0] = col[1] = col[2] = 0.0f;
- }
- col[3] = 1.0f;
- }
- else if (channels == 3) {
- copy_v3_v3(col, linearcol);
- col[3] = 1.0f;
- }
- else if (channels == 4) {
- copy_v4_v4(col, linearcol);
- }
- else {
- BLI_assert(0);
- zero_v4(col);
- }
-
- if (color_manage) {
- if (use_default_view) {
- IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, NULL, &scene->display_settings);
- }
- else {
- IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, &scene->view_settings, &scene->display_settings);
- }
- }
- else {
- copy_v4_v4(finalcol, col);
- }
-
- GPU_blend(false);
- dx += 0.25f * UI_UNIT_X;
-
- BLI_rcti_init(&color_rect, dx, dx + (1.5f * UI_UNIT_X), ymin + 0.15f * UI_UNIT_Y, ymin + 0.85f * UI_UNIT_Y);
-
- /* BLF uses immediate mode too, so we must reset our vertex format */
- pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- if (channels == 4) {
- rcti color_rect_half;
- int color_quater_x, color_quater_y;
-
- color_rect_half = color_rect;
- color_rect_half.xmax = BLI_rcti_cent_x(&color_rect);
- /* what color ??? */
- immRecti(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
-
- color_rect_half = color_rect;
- color_rect_half.xmin = BLI_rcti_cent_x(&color_rect);
-
- color_quater_x = BLI_rcti_cent_x(&color_rect_half);
- color_quater_y = BLI_rcti_cent_y(&color_rect_half);
-
- immUniformColor3ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK);
- immRecti(pos, color_rect_half.xmin, color_rect_half.ymin, color_rect_half.xmax, color_rect_half.ymax);
-
- immUniformColor3ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT);
- immRecti(pos, color_quater_x, color_quater_y, color_rect_half.xmax, color_rect_half.ymax);
- immRecti(pos, color_rect_half.xmin, color_rect_half.ymin, color_quater_x, color_quater_y);
-
- GPU_blend(true);
- immUniformColor3fvAlpha(finalcol, fp ? fp[3] : (cp[3] / 255.0f));
- immRecti(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
- GPU_blend(false);
- }
- else {
- immUniformColor3fv(finalcol);
- immRecti(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
- }
- immUnbindProgram();
-
- /* draw outline */
- pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3ub(128, 128, 128);
- imm_draw_box_wire_2d(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
- immUnbindProgram();
-
- dx += 1.75f * UI_UNIT_X;
-
- BLF_color3ub(blf_mono_font, 255, 255, 255);
- if (channels == 1) {
- if (fp) {
- rgb_to_hsv(fp[0], fp[0], fp[0], &hue, &sat, &val);
- rgb_to_yuv(fp[0], fp[0], fp[0], &lum, &u, &v, BLI_YUV_ITU_BT709);
- }
- else if (cp) {
- rgb_to_hsv((float)cp[0] / 255.0f, (float)cp[0] / 255.0f, (float)cp[0] / 255.0f, &hue, &sat, &val);
- rgb_to_yuv((float)cp[0] / 255.0f, (float)cp[0] / 255.0f, (float)cp[0] / 255.0f, &lum, &u, &v, BLI_YUV_ITU_BT709);
- }
-
- SNPRINTF(str, "V:%-.4f", val);
- BLF_position(blf_mono_font, dx, dy, 0);
- BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str, sizeof(str));
-
- SNPRINTF(str, " L:%-.4f", lum);
- BLF_position(blf_mono_font, dx, dy, 0);
- BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- }
- else if (channels >= 3) {
- rgb_to_hsv(finalcol[0], finalcol[1], finalcol[2], &hue, &sat, &val);
- rgb_to_yuv(finalcol[0], finalcol[1], finalcol[2], &lum, &u, &v, BLI_YUV_ITU_BT709);
-
- SNPRINTF(str, "H:%-.4f", hue);
- BLF_position(blf_mono_font, dx, dy, 0);
- BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str, sizeof(str));
-
- SNPRINTF(str, " S:%-.4f", sat);
- BLF_position(blf_mono_font, dx, dy, 0);
- BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str, sizeof(str));
-
- SNPRINTF(str, " V:%-.4f", val);
- BLF_position(blf_mono_font, dx, dy, 0);
- BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str, sizeof(str));
-
- SNPRINTF(str, " L:%-.4f", lum);
- BLF_position(blf_mono_font, dx, dy, 0);
- BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- }
+ float hue = 0, sat = 0, val = 0, lum = 0, u = 0, v = 0;
+ float col[4], finalcol[4];
+
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
+
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* 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);
+
+ immUnbindProgram();
+
+ GPU_blend(false);
+
+ BLF_size(blf_mono_font, 11 * U.pixelsize, U.dpi);
+
+ BLF_color3ub(blf_mono_font, 255, 255, 255);
+ SNPRINTF(str, "X:%-4d Y:%-4d |", x, y);
+ BLF_position(blf_mono_font, dx, dy, 0);
+ BLF_draw_ascii(blf_mono_font, str, sizeof(str));
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
+
+ if (zp) {
+ BLF_color3ub(blf_mono_font, 255, 255, 255);
+ SNPRINTF(str, " Z:%-.4f |", 0.5f + 0.5f * (((float)*zp) / (float)0x7fffffff));
+ BLF_position(blf_mono_font, dx, dy, 0);
+ BLF_draw_ascii(blf_mono_font, str, sizeof(str));
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
+ }
+ if (zpf) {
+ BLF_color3ub(blf_mono_font, 255, 255, 255);
+ SNPRINTF(str, " Z:%-.3f |", *zpf);
+ BLF_position(blf_mono_font, dx, dy, 0);
+ BLF_draw_ascii(blf_mono_font, str, sizeof(str));
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
+ }
+
+ if (channels == 1 && (cp != NULL || fp != NULL)) {
+ if (fp != NULL) {
+ SNPRINTF(str, " Val:%-.3f |", fp[0]);
+ }
+ else if (cp != NULL) {
+ SNPRINTF(str, " Val:%-.3f |", cp[0] / 255.0f);
+ }
+ BLF_color3ub(blf_mono_font, 255, 255, 255);
+ BLF_position(blf_mono_font, dx, dy, 0);
+ BLF_draw_ascii(blf_mono_font, str, sizeof(str));
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
+ }
+
+ if (channels >= 3) {
+ BLF_color3ubv(blf_mono_font, red);
+ if (fp) {
+ SNPRINTF(str, " R:%-.5f", fp[0]);
+ }
+ else if (cp) {
+ SNPRINTF(str, " R:%-3d", cp[0]);
+ }
+ else {
+ STRNCPY(str, " R:-");
+ }
+ BLF_position(blf_mono_font, dx, dy, 0);
+ BLF_draw_ascii(blf_mono_font, str, sizeof(str));
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
+
+ BLF_color3ubv(blf_mono_font, green);
+ if (fp) {
+ SNPRINTF(str, " G:%-.5f", fp[1]);
+ }
+ else if (cp) {
+ SNPRINTF(str, " G:%-3d", cp[1]);
+ }
+ else {
+ STRNCPY(str, " G:-");
+ }
+ BLF_position(blf_mono_font, dx, dy, 0);
+ BLF_draw_ascii(blf_mono_font, str, sizeof(str));
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
+
+ BLF_color3ubv(blf_mono_font, blue);
+ if (fp) {
+ SNPRINTF(str, " B:%-.5f", fp[2]);
+ }
+ else if (cp) {
+ SNPRINTF(str, " B:%-3d", cp[2]);
+ }
+ else {
+ STRNCPY(str, " B:-");
+ }
+ BLF_position(blf_mono_font, dx, dy, 0);
+ BLF_draw_ascii(blf_mono_font, str, sizeof(str));
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
+
+ if (channels == 4) {
+ BLF_color3ub(blf_mono_font, 255, 255, 255);
+ if (fp) {
+ SNPRINTF(str, " A:%-.4f", fp[3]);
+ }
+ else if (cp) {
+ SNPRINTF(str, " A:%-3d", cp[3]);
+ }
+ else {
+ STRNCPY(str, "- ");
+ }
+ BLF_position(blf_mono_font, dx, dy, 0);
+ BLF_draw_ascii(blf_mono_font, str, sizeof(str));
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
+ }
+
+ if (color_manage) {
+ float rgba[4];
+
+ copy_v3_v3(rgba, linearcol);
+ if (channels == 3) {
+ rgba[3] = 1.0f;
+ }
+ else {
+ rgba[3] = linearcol[3];
+ }
+
+ if (use_default_view) {
+ IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, NULL, &scene->display_settings);
+ }
+ else {
+ IMB_colormanagement_pixel_to_display_space_v4(
+ rgba, rgba, &scene->view_settings, &scene->display_settings);
+ }
+
+ SNPRINTF(str, " | CM R:%-.4f G:%-.4f B:%-.4f", rgba[0], rgba[1], rgba[2]);
+ BLF_position(blf_mono_font, dx, dy, 0);
+ BLF_draw_ascii(blf_mono_font, str, sizeof(str));
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
+ }
+ }
+
+ /* color rectangle */
+ if (channels == 1) {
+ if (fp) {
+ col[0] = col[1] = col[2] = fp[0];
+ }
+ else if (cp) {
+ col[0] = col[1] = col[2] = (float)cp[0] / 255.0f;
+ }
+ else {
+ col[0] = col[1] = col[2] = 0.0f;
+ }
+ col[3] = 1.0f;
+ }
+ else if (channels == 3) {
+ copy_v3_v3(col, linearcol);
+ col[3] = 1.0f;
+ }
+ else if (channels == 4) {
+ copy_v4_v4(col, linearcol);
+ }
+ else {
+ BLI_assert(0);
+ zero_v4(col);
+ }
+
+ if (color_manage) {
+ if (use_default_view) {
+ IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, NULL, &scene->display_settings);
+ }
+ else {
+ IMB_colormanagement_pixel_to_display_space_v4(
+ finalcol, col, &scene->view_settings, &scene->display_settings);
+ }
+ }
+ else {
+ copy_v4_v4(finalcol, col);
+ }
+
+ GPU_blend(false);
+ dx += 0.25f * UI_UNIT_X;
+
+ BLI_rcti_init(&color_rect,
+ dx,
+ dx + (1.5f * UI_UNIT_X),
+ ymin + 0.15f * UI_UNIT_Y,
+ ymin + 0.85f * UI_UNIT_Y);
+
+ /* BLF uses immediate mode too, so we must reset our vertex format */
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ if (channels == 4) {
+ rcti color_rect_half;
+ int color_quater_x, color_quater_y;
+
+ color_rect_half = color_rect;
+ color_rect_half.xmax = BLI_rcti_cent_x(&color_rect);
+ /* what color ??? */
+ immRecti(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
+
+ color_rect_half = color_rect;
+ color_rect_half.xmin = BLI_rcti_cent_x(&color_rect);
+
+ color_quater_x = BLI_rcti_cent_x(&color_rect_half);
+ color_quater_y = BLI_rcti_cent_y(&color_rect_half);
+
+ immUniformColor3ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK);
+ immRecti(pos,
+ color_rect_half.xmin,
+ color_rect_half.ymin,
+ color_rect_half.xmax,
+ color_rect_half.ymax);
+
+ immUniformColor3ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT);
+ immRecti(pos, color_quater_x, color_quater_y, color_rect_half.xmax, color_rect_half.ymax);
+ immRecti(pos, color_rect_half.xmin, color_rect_half.ymin, color_quater_x, color_quater_y);
+
+ GPU_blend(true);
+ immUniformColor3fvAlpha(finalcol, fp ? fp[3] : (cp[3] / 255.0f));
+ immRecti(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
+ GPU_blend(false);
+ }
+ else {
+ immUniformColor3fv(finalcol);
+ immRecti(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
+ }
+ immUnbindProgram();
+
+ /* draw outline */
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3ub(128, 128, 128);
+ imm_draw_box_wire_2d(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
+ immUnbindProgram();
+
+ dx += 1.75f * UI_UNIT_X;
+
+ BLF_color3ub(blf_mono_font, 255, 255, 255);
+ if (channels == 1) {
+ if (fp) {
+ rgb_to_hsv(fp[0], fp[0], fp[0], &hue, &sat, &val);
+ rgb_to_yuv(fp[0], fp[0], fp[0], &lum, &u, &v, BLI_YUV_ITU_BT709);
+ }
+ else if (cp) {
+ rgb_to_hsv(
+ (float)cp[0] / 255.0f, (float)cp[0] / 255.0f, (float)cp[0] / 255.0f, &hue, &sat, &val);
+ rgb_to_yuv((float)cp[0] / 255.0f,
+ (float)cp[0] / 255.0f,
+ (float)cp[0] / 255.0f,
+ &lum,
+ &u,
+ &v,
+ BLI_YUV_ITU_BT709);
+ }
+
+ SNPRINTF(str, "V:%-.4f", val);
+ BLF_position(blf_mono_font, dx, dy, 0);
+ BLF_draw_ascii(blf_mono_font, str, sizeof(str));
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
+
+ SNPRINTF(str, " L:%-.4f", lum);
+ BLF_position(blf_mono_font, dx, dy, 0);
+ BLF_draw_ascii(blf_mono_font, str, sizeof(str));
+ }
+ else if (channels >= 3) {
+ rgb_to_hsv(finalcol[0], finalcol[1], finalcol[2], &hue, &sat, &val);
+ rgb_to_yuv(finalcol[0], finalcol[1], finalcol[2], &lum, &u, &v, BLI_YUV_ITU_BT709);
+
+ SNPRINTF(str, "H:%-.4f", hue);
+ BLF_position(blf_mono_font, dx, dy, 0);
+ BLF_draw_ascii(blf_mono_font, str, sizeof(str));
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
+
+ SNPRINTF(str, " S:%-.4f", sat);
+ BLF_position(blf_mono_font, dx, dy, 0);
+ BLF_draw_ascii(blf_mono_font, str, sizeof(str));
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
+
+ SNPRINTF(str, " V:%-.4f", val);
+ BLF_position(blf_mono_font, dx, dy, 0);
+ BLF_draw_ascii(blf_mono_font, str, sizeof(str));
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
+
+ SNPRINTF(str, " L:%-.4f", lum);
+ BLF_position(blf_mono_font, dx, dy, 0);
+ BLF_draw_ascii(blf_mono_font, str, sizeof(str));
+ }
}
/* image drawing */
-static void sima_draw_zbuf_pixels(float x1, float y1, int rectx, int recty, int *rect,
- float zoomx, float zoomy)
+static void sima_draw_zbuf_pixels(
+ float x1, float y1, int rectx, int recty, int *rect, float zoomx, float zoomy)
{
- float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
+ float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
- /* Slowwww */
- int *recti = MEM_mallocN(rectx * recty * sizeof(int), "temp");
- for (int a = rectx * recty - 1; a >= 0; a--) {
- /* zbuffer values are signed, so we need to shift color range */
- recti[a] = rect[a] * 0.5f + 0.5f;
- }
+ /* Slowwww */
+ int *recti = MEM_mallocN(rectx * recty * sizeof(int), "temp");
+ for (int a = rectx * recty - 1; a >= 0; a--) {
+ /* zbuffer values are signed, so we need to shift color range */
+ recti[a] = rect[a] * 0.5f + 0.5f;
+ }
- IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
- GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red);
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_uniform_vector(
+ state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red);
- immDrawPixelsTex(&state, x1, y1, rectx, recty, GL_RED, GL_INT, GL_NEAREST, recti, zoomx, zoomy, NULL);
+ immDrawPixelsTex(
+ &state, x1, y1, rectx, recty, GL_RED, GL_INT, GL_NEAREST, recti, zoomx, zoomy, NULL);
- MEM_freeN(recti);
+ MEM_freeN(recti);
}
-static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rectx, int recty,
- float *rect_float, float zoomx, float zoomy)
+static void sima_draw_zbuffloat_pixels(Scene *scene,
+ float x1,
+ float y1,
+ int rectx,
+ int recty,
+ float *rect_float,
+ float zoomx,
+ float zoomy)
{
- float bias, scale, *rectf, clip_end;
- int a;
- float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
-
- if (scene->camera && scene->camera->type == OB_CAMERA) {
- bias = ((Camera *)scene->camera->data)->clip_start;
- clip_end = ((Camera *)scene->camera->data)->clip_end;
- scale = 1.0f / (clip_end - bias);
- }
- else {
- bias = 0.1f;
- scale = 0.01f;
- clip_end = 100.0f;
- }
-
- rectf = MEM_mallocN(rectx * recty * sizeof(float), "temp");
- for (a = rectx * recty - 1; a >= 0; a--) {
- if (rect_float[a] > clip_end) {
- rectf[a] = 0.0f;
- }
- else if (rect_float[a] < bias) {
- rectf[a] = 1.0f;
- }
- else {
- rectf[a] = 1.0f - (rect_float[a] - bias) * scale;
- rectf[a] *= rectf[a];
- }
- }
-
- IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
- GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red);
-
- immDrawPixelsTex(&state, x1, y1, rectx, recty, GL_RED, GL_FLOAT, GL_NEAREST, rectf, zoomx, zoomy, NULL);
-
- MEM_freeN(rectf);
+ float bias, scale, *rectf, clip_end;
+ int a;
+ float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
+
+ if (scene->camera && scene->camera->type == OB_CAMERA) {
+ bias = ((Camera *)scene->camera->data)->clip_start;
+ clip_end = ((Camera *)scene->camera->data)->clip_end;
+ scale = 1.0f / (clip_end - bias);
+ }
+ else {
+ bias = 0.1f;
+ scale = 0.01f;
+ clip_end = 100.0f;
+ }
+
+ rectf = MEM_mallocN(rectx * recty * sizeof(float), "temp");
+ for (a = rectx * recty - 1; a >= 0; a--) {
+ if (rect_float[a] > clip_end) {
+ rectf[a] = 0.0f;
+ }
+ else if (rect_float[a] < bias) {
+ rectf[a] = 1.0f;
+ }
+ else {
+ rectf[a] = 1.0f - (rect_float[a] - bias) * scale;
+ rectf[a] *= rectf[a];
+ }
+ }
+
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_uniform_vector(
+ state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red);
+
+ immDrawPixelsTex(
+ &state, x1, y1, rectx, recty, GL_RED, GL_FLOAT, GL_NEAREST, rectf, zoomx, zoomy, NULL);
+
+ MEM_freeN(rectf);
}
-static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, Scene *scene, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy)
+static void draw_image_buffer(const bContext *C,
+ SpaceImage *sima,
+ ARegion *ar,
+ Scene *scene,
+ ImBuf *ibuf,
+ float fx,
+ float fy,
+ float zoomx,
+ float zoomy)
{
- int x, y;
-
- /* find window pixel coordinates of origin */
- UI_view2d_view_to_region(&ar->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 (ibuf->zbuf) {
- sima_draw_zbuf_pixels(x, y, ibuf->x, ibuf->y, ibuf->zbuf, zoomx, zoomy);
- }
- else if (ibuf->zbuf_float) {
- sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->zbuf_float, zoomx, zoomy);
- }
- else if (ibuf->channels == 1) {
- sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float, zoomx, zoomy);
- }
- }
- 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);
-
- if (sima->flag & SI_USE_ALPHA) {
- imm_draw_box_checker_2d(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy);
-
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- }
-
- /* If RGBA display with color management */
- if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) == 0) {
-
- glaDrawImBuf_glsl_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;
- void *cache_handle;
- ColorManagedViewSettings *view_settings;
- ColorManagedDisplaySettings *display_settings;
-
- if (sima->flag & SI_SHOW_R) {
- shuffle[0] = 1.0f;
- }
- else if (sima->flag & SI_SHOW_G) {
- shuffle[1] = 1.0f;
- }
- else if (sima->flag & SI_SHOW_B) {
- shuffle[2] = 1.0f;
- }
- else if (sima->flag & SI_SHOW_ALPHA) {
- shuffle[3] = 1.0f;
- }
-
- IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
- GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, shuffle);
-
- IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings);
- display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, display_settings, &cache_handle);
-
- if (display_buffer) {
- immDrawPixelsTex_clipping(&state, x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer,
- 0, 0, clip_max_x, clip_max_y, zoomx, zoomy, NULL);
- }
-
- IMB_display_buffer_release(cache_handle);
- }
-
- if (sima->flag & SI_USE_ALPHA) {
- GPU_blend(false);
- }
- }
+ int x, y;
+
+ /* find window pixel coordinates of origin */
+ UI_view2d_view_to_region(&ar->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 (ibuf->zbuf) {
+ sima_draw_zbuf_pixels(x, y, ibuf->x, ibuf->y, ibuf->zbuf, zoomx, zoomy);
+ }
+ else if (ibuf->zbuf_float) {
+ sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->zbuf_float, zoomx, zoomy);
+ }
+ else if (ibuf->channels == 1) {
+ sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float, zoomx, zoomy);
+ }
+ }
+ 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);
+
+ if (sima->flag & SI_USE_ALPHA) {
+ imm_draw_box_checker_2d(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy);
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ }
+
+ /* If RGBA display with color management */
+ if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) == 0) {
+
+ glaDrawImBuf_glsl_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;
+ void *cache_handle;
+ ColorManagedViewSettings *view_settings;
+ ColorManagedDisplaySettings *display_settings;
+
+ if (sima->flag & SI_SHOW_R) {
+ shuffle[0] = 1.0f;
+ }
+ else if (sima->flag & SI_SHOW_G) {
+ shuffle[1] = 1.0f;
+ }
+ else if (sima->flag & SI_SHOW_B) {
+ shuffle[2] = 1.0f;
+ }
+ else if (sima->flag & SI_SHOW_ALPHA) {
+ shuffle[3] = 1.0f;
+ }
+
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_uniform_vector(
+ state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, shuffle);
+
+ IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings);
+ display_buffer = IMB_display_buffer_acquire(
+ ibuf, view_settings, display_settings, &cache_handle);
+
+ if (display_buffer) {
+ immDrawPixelsTex_clipping(&state,
+ x,
+ y,
+ ibuf->x,
+ ibuf->y,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ GL_NEAREST,
+ display_buffer,
+ 0,
+ 0,
+ clip_max_x,
+ clip_max_y,
+ zoomx,
+ zoomy,
+ NULL);
+ }
+
+ IMB_display_buffer_release(cache_handle);
+ }
+
+ if (sima->flag & SI_USE_ALPHA) {
+ GPU_blend(false);
+ }
+ }
}
-static void draw_image_buffer_repeated(const bContext *C, SpaceImage *sima, ARegion *ar, Scene *scene, ImBuf *ibuf, float zoomx, float zoomy)
+static void draw_image_buffer_repeated(const bContext *C,
+ SpaceImage *sima,
+ ARegion *ar,
+ Scene *scene,
+ ImBuf *ibuf,
+ float zoomx,
+ float zoomy)
{
- 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);
-
- 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);
-
- /* only draw until running out of time */
- if ((PIL_check_seconds_timer() - time_current) > 0.25) {
- return;
- }
- }
- }
+ 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);
+
+ 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);
+
+ /* only draw until running out of time */
+ if ((PIL_check_seconds_timer() - time_current) > 0.25) {
+ return;
+ }
+ }
+ }
}
/* draw uv edit */
@@ -601,249 +666,269 @@ static void draw_image_buffer_repeated(const bContext *C, SpaceImage *sima, AReg
/* draw grease pencil */
void draw_image_grease_pencil(bContext *C, bool onlyv2d)
{
- /* draw in View2D space? */
- if (onlyv2d) {
- /* draw grease-pencil ('image' strokes) */
- ED_annotation_draw_2dimage(C);
- }
- else {
- /* assume that UI_view2d_restore(C) has been called... */
- //SpaceImage *sima = (SpaceImage *)CTX_wm_space_data(C);
-
- /* draw grease-pencil ('screen' strokes) */
- ED_annotation_draw_view2d(C, 0);
- }
+ /* draw in View2D space? */
+ if (onlyv2d) {
+ /* draw grease-pencil ('image' strokes) */
+ ED_annotation_draw_2dimage(C);
+ }
+ else {
+ /* assume that UI_view2d_restore(C) has been called... */
+ //SpaceImage *sima = (SpaceImage *)CTX_wm_space_data(C);
+
+ /* draw grease-pencil ('screen' strokes) */
+ ED_annotation_draw_view2d(C, 0);
+ }
}
void draw_image_sample_line(SpaceImage *sima)
{
- if (sima->sample_line_hist.flag & HISTO_FLAG_SAMPLELINE) {
- Histogram *hist = &sima->sample_line_hist;
+ if (sima->sample_line_hist.flag & HISTO_FLAG_SAMPLELINE) {
+ Histogram *hist = &sima->sample_line_hist;
- GPUVertFormat *format = immVertexFormat();
- uint shdr_dashed_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint shdr_dashed_pos = GPU_vertformat_attr_add(
+ format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
- immUniform1i("colors_len", 2); /* Advanced dashes. */
- immUniformArray4fv("colors", (float *)(float[][4]){{1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2);
- immUniform1f("dash_width", 2.0f);
+ immUniform1i("colors_len", 2); /* Advanced dashes. */
+ immUniformArray4fv(
+ "colors", (float *)(float[][4]){{1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2);
+ immUniform1f("dash_width", 2.0f);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2fv(shdr_dashed_pos, hist->co[0]);
- immVertex2fv(shdr_dashed_pos, hist->co[1]);
- immEnd();
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2fv(shdr_dashed_pos, hist->co[0]);
+ immVertex2fv(shdr_dashed_pos, hist->co[1]);
+ immEnd();
- immUnbindProgram();
- }
+ immUnbindProgram();
+ }
}
-static void draw_image_paint_helpers(const bContext *C, ARegion *ar, Scene *scene, float zoomx, float zoomy)
+static void draw_image_paint_helpers(
+ const bContext *C, ARegion *ar, Scene *scene, float zoomx, float zoomy)
{
- Brush *brush;
- int x, y;
- ImBuf *ibuf;
-
- brush = BKE_paint_brush(&scene->toolsettings->imapaint.paint);
-
- if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE) && brush->clone.image) {
- ibuf = BKE_image_acquire_ibuf(brush->clone.image, NULL, NULL);
-
- 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);
-
- unsigned char *display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
-
- if (!display_buffer) {
- BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
- IMB_display_buffer_release(cache_handle);
- return;
- }
-
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
- immDrawPixelsTex(&state, x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer, zoomx, zoomy, col);
-
- GPU_blend(false);
-
- BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
- IMB_display_buffer_release(cache_handle);
- }
- }
+ Brush *brush;
+ int x, y;
+ ImBuf *ibuf;
+
+ brush = BKE_paint_brush(&scene->toolsettings->imapaint.paint);
+
+ if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE) && brush->clone.image) {
+ ibuf = BKE_image_acquire_ibuf(brush->clone.image, NULL, NULL);
+
+ 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);
+
+ unsigned char *display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
+
+ if (!display_buffer) {
+ BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
+ IMB_display_buffer_release(cache_handle);
+ return;
+ }
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(&state,
+ x,
+ y,
+ ibuf->x,
+ ibuf->y,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ GL_NEAREST,
+ display_buffer,
+ zoomx,
+ zoomy,
+ col);
+
+ GPU_blend(false);
+
+ BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
+ IMB_display_buffer_release(cache_handle);
+ }
+ }
}
/* draw main image region */
void draw_image_main(const bContext *C, ARegion *ar)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- Scene *scene = CTX_data_scene(C);
- Image *ima;
- ImBuf *ibuf;
- float zoomx, zoomy;
- bool show_viewer, show_render, show_paint, show_stereo3d, show_multilayer;
- void *lock;
-
- /* XXX can we do this in refresh? */
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Scene *scene = CTX_data_scene(C);
+ Image *ima;
+ ImBuf *ibuf;
+ float zoomx, zoomy;
+ bool show_viewer, show_render, show_paint, show_stereo3d, show_multilayer;
+ void *lock;
+
+ /* XXX can we do this in refresh? */
#if 0
- what_image(sima);
-
- if (sima->image) {
- ED_image_get_aspect(sima->image, &xuser_asp, &yuser_asp);
-
- /* UGLY hack? until now iusers worked fine... but for flipbook viewer we need this */
- if (sima->image->type == IMA_TYPE_COMPOSITE) {
- ImageUser *iuser = ntree_get_active_iuser(scene->nodetree);
- if (iuser) {
- BKE_image_user_calc_imanr(iuser, scene->r.cfra, 0);
- sima->iuser = *iuser;
- }
- }
- /* and we check for spare */
- ibuf = ED_space_image_buffer(sima);
- }
+ what_image(sima);
+
+ if (sima->image) {
+ ED_image_get_aspect(sima->image, &xuser_asp, &yuser_asp);
+
+ /* UGLY hack? until now iusers worked fine... but for flipbook viewer we need this */
+ if (sima->image->type == IMA_TYPE_COMPOSITE) {
+ ImageUser *iuser = ntree_get_active_iuser(scene->nodetree);
+ if (iuser) {
+ BKE_image_user_calc_imanr(iuser, scene->r.cfra, 0);
+ sima->iuser = *iuser;
+ }
+ }
+ /* and we check for spare */
+ ibuf = ED_space_image_buffer(sima);
+ }
#endif
- /* retrieve the image and information about it */
- ima = ED_space_image(sima);
- ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
-
- show_viewer = (ima && ima->source == IMA_SRC_VIEWER) != 0;
- show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT) != 0;
- show_paint = (ima && (sima->mode == SI_MODE_PAINT) && (show_viewer == false) && (show_render == false));
- show_stereo3d = (ima && BKE_image_is_stereo(ima) && (sima->iuser.flag & IMA_SHOW_STEREO));
- show_multilayer = ima && BKE_image_is_multilayer(ima);
-
- if (show_viewer) {
- /* use locked draw for drawing viewer image buffer since the compositor
- * is running in separated thread and compositor could free this buffers.
- * other images are not modifying in such a way so they does not require
- * lock (sergey)
- */
- BLI_thread_lock(LOCK_DRAW_IMAGE);
- }
-
- if (show_stereo3d) {
- if (show_multilayer) {
- /* update multiindex and pass for the current eye */
- BKE_image_multilayer_index(ima->rr, &sima->iuser);
- }
- else {
- BKE_image_multiview_index(ima, &sima->iuser);
- }
- }
-
- ibuf = ED_space_image_acquire_buffer(sima, &lock);
-
- /* draw the image or grid */
- if (ibuf == NULL) {
- ED_region_grid_draw(ar, zoomx, zoomy);
- }
- else {
- if (sima->flag & SI_DRAW_TILE) {
- draw_image_buffer_repeated(C, sima, ar, scene, ibuf, zoomx, zoomy);
- }
- else {
- draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy);
- }
-
- if (sima->flag & SI_DRAW_METADATA) {
- int x, y;
- 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);
-
- ED_region_image_metadata_draw(x, y, ibuf, &frame, zoomx, zoomy);
- }
- }
-
- ED_space_image_release_buffer(sima, ibuf, lock);
-
- /* paint helpers */
- if (show_paint) {
- draw_image_paint_helpers(C, ar, scene, zoomx, zoomy);
- }
-
- if (show_viewer) {
- BLI_thread_unlock(LOCK_DRAW_IMAGE);
- }
-
- /* render info */
- if (ima && show_render) {
- draw_render_info(C, sima->iuser.scene, ima, ar, zoomx, zoomy);
- }
+ /* retrieve the image and information about it */
+ ima = ED_space_image(sima);
+ ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
+
+ show_viewer = (ima && ima->source == IMA_SRC_VIEWER) != 0;
+ show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT) != 0;
+ show_paint = (ima && (sima->mode == SI_MODE_PAINT) && (show_viewer == false) &&
+ (show_render == false));
+ show_stereo3d = (ima && BKE_image_is_stereo(ima) && (sima->iuser.flag & IMA_SHOW_STEREO));
+ show_multilayer = ima && BKE_image_is_multilayer(ima);
+
+ if (show_viewer) {
+ /* use locked draw for drawing viewer image buffer since the compositor
+ * is running in separated thread and compositor could free this buffers.
+ * other images are not modifying in such a way so they does not require
+ * lock (sergey)
+ */
+ BLI_thread_lock(LOCK_DRAW_IMAGE);
+ }
+
+ if (show_stereo3d) {
+ if (show_multilayer) {
+ /* update multiindex and pass for the current eye */
+ BKE_image_multilayer_index(ima->rr, &sima->iuser);
+ }
+ else {
+ BKE_image_multiview_index(ima, &sima->iuser);
+ }
+ }
+
+ ibuf = ED_space_image_acquire_buffer(sima, &lock);
+
+ /* draw the image or grid */
+ if (ibuf == NULL) {
+ ED_region_grid_draw(ar, zoomx, zoomy);
+ }
+ else {
+ if (sima->flag & SI_DRAW_TILE) {
+ draw_image_buffer_repeated(C, sima, ar, scene, ibuf, zoomx, zoomy);
+ }
+ else {
+ draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy);
+ }
+
+ if (sima->flag & SI_DRAW_METADATA) {
+ int x, y;
+ 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);
+
+ ED_region_image_metadata_draw(x, y, ibuf, &frame, zoomx, zoomy);
+ }
+ }
+
+ ED_space_image_release_buffer(sima, ibuf, lock);
+
+ /* paint helpers */
+ if (show_paint) {
+ draw_image_paint_helpers(C, ar, scene, zoomx, zoomy);
+ }
+
+ if (show_viewer) {
+ BLI_thread_unlock(LOCK_DRAW_IMAGE);
+ }
+
+ /* render info */
+ if (ima && show_render) {
+ draw_render_info(C, sima->iuser.scene, ima, ar, zoomx, zoomy);
+ }
}
bool ED_space_image_show_cache(SpaceImage *sima)
{
- Image *image = ED_space_image(sima);
- Mask *mask = NULL;
- if (sima->mode == SI_MODE_MASK) {
- mask = ED_space_image_get_mask(sima);
- }
- if (image == NULL && mask == NULL) {
- return false;
- }
- if (mask == NULL) {
- return ELEM(image->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE);
- }
- return true;
+ Image *image = ED_space_image(sima);
+ Mask *mask = NULL;
+ if (sima->mode == SI_MODE_MASK) {
+ mask = ED_space_image_get_mask(sima);
+ }
+ if (image == NULL && mask == NULL) {
+ return false;
+ }
+ if (mask == NULL) {
+ return ELEM(image->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE);
+ }
+ return true;
}
void draw_image_cache(const bContext *C, ARegion *ar)
{
- 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);
- Mask *mask = NULL;
-
- if (!ED_space_image_show_cache(sima)) {
- return;
- }
-
- if (sima->mode == SI_MODE_MASK) {
- mask = ED_space_image_get_mask(sima);
- }
-
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- /* Draw cache background. */
- ED_region_cache_draw_background(ar);
-
- /* Draw cached segments. */
- if (image != NULL && image->cache != NULL && ELEM(image->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
- int num_segments = 0;
- int *points = NULL;
-
- 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);
- }
-
- GPU_blend(false);
-
- /* Draw current frame. */
- x = (cfra - sfra) / (efra - sfra + 1) * ar->winx;
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor(TH_CFRAME);
- immRecti(pos, x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC);
- immUnbindProgram();
-
- ED_region_cache_draw_curfra_label(cfra, x, 8.0f * UI_DPI_FAC);
-
- if (mask != NULL) {
- ED_mask_draw_frames(mask, ar, cfra, sfra, efra);
- }
+ 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);
+ Mask *mask = NULL;
+
+ if (!ED_space_image_show_cache(sima)) {
+ return;
+ }
+
+ if (sima->mode == SI_MODE_MASK) {
+ mask = ED_space_image_get_mask(sima);
+ }
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ /* Draw cache background. */
+ ED_region_cache_draw_background(ar);
+
+ /* Draw cached segments. */
+ if (image != NULL && image->cache != NULL &&
+ ELEM(image->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
+ int num_segments = 0;
+ int *points = NULL;
+
+ 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);
+ }
+
+ GPU_blend(false);
+
+ /* Draw current frame. */
+ x = (cfra - sfra) / (efra - sfra + 1) * ar->winx;
+
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_CFRAME);
+ immRecti(pos, x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC);
+ immUnbindProgram();
+
+ ED_region_cache_draw_curfra_label(cfra, x, 8.0f * UI_DPI_FAC);
+
+ if (mask != NULL) {
+ ED_mask_draw_frames(mask, ar, cfra, sfra, efra);
+ }
}
diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c
index c838c6a87fe..fc6546f0079 100644
--- a/source/blender/editors/space_image/image_edit.c
+++ b/source/blender/editors/space_image/image_edit.c
@@ -41,7 +41,7 @@
#include "DEG_depsgraph.h"
-#include "ED_image.h" /* own include */
+#include "ED_image.h" /* own include */
#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_uvedit.h"
@@ -54,276 +54,276 @@
/* note; image_panel_properties() uses pointer to sima->image directly */
Image *ED_space_image(SpaceImage *sima)
{
- return sima->image;
+ return sima->image;
}
void ED_space_image_set(Main *bmain, SpaceImage *sima, Object *obedit, Image *ima, bool automatic)
{
- /* Automatically pin image when manually assigned, otherwise it follows object. */
- if (!automatic && sima->image != ima && sima->mode == SI_MODE_UV) {
- sima->pin = true;
- }
+ /* Automatically pin image when manually assigned, otherwise it follows object. */
+ if (!automatic && sima->image != ima && sima->mode == SI_MODE_UV) {
+ sima->pin = true;
+ }
- /* change the space ima after because uvedit_face_visible_test uses the space ima
- * to check if the face is displayed in UV-localview */
- sima->image = ima;
+ /* change the space ima after because uvedit_face_visible_test uses the space ima
+ * to check if the face is displayed in UV-localview */
+ sima->image = ima;
- if (ima == NULL || ima->type == IMA_TYPE_R_RESULT || ima->type == IMA_TYPE_COMPOSITE) {
- if (sima->mode == SI_MODE_PAINT) {
- sima->mode = SI_MODE_VIEW;
- }
- }
+ if (ima == NULL || ima->type == IMA_TYPE_R_RESULT || ima->type == IMA_TYPE_COMPOSITE) {
+ if (sima->mode == SI_MODE_PAINT) {
+ sima->mode = SI_MODE_VIEW;
+ }
+ }
- if (sima->image) {
- BKE_image_signal(bmain, sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
- }
+ if (sima->image) {
+ BKE_image_signal(bmain, sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
+ }
- id_us_ensure_real((ID *)sima->image);
+ id_us_ensure_real((ID *)sima->image);
- if (obedit) {
- WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
- }
+ if (obedit) {
+ WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
+ }
- WM_main_add_notifier(NC_SPACE | ND_SPACE_IMAGE, NULL);
+ WM_main_add_notifier(NC_SPACE | ND_SPACE_IMAGE, NULL);
}
void ED_space_image_auto_set(const bContext *C, SpaceImage *sima)
{
- if (sima->mode != SI_MODE_UV || sima->pin) {
- return;
- }
-
- /* Track image assigned to active face in edit mode. */
- Object *ob = CTX_data_active_object(C);
- if (!(ob && (ob->mode & OB_MODE_EDIT) && ED_space_image_show_uvedit(sima, ob))) {
- return;
- }
-
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em->bm;
- BMFace *efa = BM_mesh_active_face_get(bm, true, false);
- if (efa == NULL) {
- return;
- }
-
- Image *ima = NULL;
- ED_object_get_active_image(ob, efa->mat_nr + 1, &ima, NULL, NULL, NULL);
-
- if (ima != sima->image) {
- sima->image = ima;
-
- if (sima->image) {
- Main *bmain = CTX_data_main(C);
- BKE_image_signal(bmain, sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
- }
- }
+ if (sima->mode != SI_MODE_UV || sima->pin) {
+ return;
+ }
+
+ /* Track image assigned to active face in edit mode. */
+ Object *ob = CTX_data_active_object(C);
+ if (!(ob && (ob->mode & OB_MODE_EDIT) && ED_space_image_show_uvedit(sima, ob))) {
+ return;
+ }
+
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
+ BMFace *efa = BM_mesh_active_face_get(bm, true, false);
+ if (efa == NULL) {
+ return;
+ }
+
+ Image *ima = NULL;
+ ED_object_get_active_image(ob, efa->mat_nr + 1, &ima, NULL, NULL, NULL);
+
+ if (ima != sima->image) {
+ sima->image = ima;
+
+ if (sima->image) {
+ Main *bmain = CTX_data_main(C);
+ BKE_image_signal(bmain, sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
+ }
+ }
}
Mask *ED_space_image_get_mask(SpaceImage *sima)
{
- return sima->mask_info.mask;
+ return sima->mask_info.mask;
}
void ED_space_image_set_mask(bContext *C, SpaceImage *sima, Mask *mask)
{
- sima->mask_info.mask = mask;
+ sima->mask_info.mask = mask;
- /* weak, but same as image/space */
- id_us_ensure_real((ID *)sima->mask_info.mask);
+ /* weak, but same as image/space */
+ id_us_ensure_real((ID *)sima->mask_info.mask);
- if (C) {
- WM_event_add_notifier(C, NC_MASK | NA_SELECTED, mask);
- }
+ if (C) {
+ WM_event_add_notifier(C, NC_MASK | NA_SELECTED, mask);
+ }
}
ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **r_lock)
{
- ImBuf *ibuf;
+ ImBuf *ibuf;
- if (sima && sima->image) {
+ if (sima && sima->image) {
#if 0
- if (sima->image->type == IMA_TYPE_R_RESULT && BIF_show_render_spare())
- return BIF_render_spare_imbuf();
- else
+ if (sima->image->type == IMA_TYPE_R_RESULT && BIF_show_render_spare())
+ return BIF_render_spare_imbuf();
+ else
#endif
- ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, r_lock);
-
- if (ibuf) {
- if (ibuf->rect || ibuf->rect_float) {
- return ibuf;
- }
- BKE_image_release_ibuf(sima->image, ibuf, *r_lock);
- *r_lock = NULL;
- }
- }
- else {
- *r_lock = NULL;
- }
-
- return NULL;
+ ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, r_lock);
+
+ if (ibuf) {
+ if (ibuf->rect || ibuf->rect_float) {
+ return ibuf;
+ }
+ BKE_image_release_ibuf(sima->image, ibuf, *r_lock);
+ *r_lock = NULL;
+ }
+ }
+ else {
+ *r_lock = NULL;
+ }
+
+ return NULL;
}
void ED_space_image_release_buffer(SpaceImage *sima, ImBuf *ibuf, void *lock)
{
- if (sima && sima->image) {
- BKE_image_release_ibuf(sima->image, ibuf, lock);
- }
+ if (sima && sima->image) {
+ BKE_image_release_ibuf(sima->image, ibuf, lock);
+ }
}
bool ED_space_image_has_buffer(SpaceImage *sima)
{
- ImBuf *ibuf;
- void *lock;
- bool has_buffer;
+ ImBuf *ibuf;
+ void *lock;
+ bool has_buffer;
- ibuf = ED_space_image_acquire_buffer(sima, &lock);
- has_buffer = (ibuf != NULL);
- ED_space_image_release_buffer(sima, ibuf, lock);
+ ibuf = ED_space_image_acquire_buffer(sima, &lock);
+ has_buffer = (ibuf != NULL);
+ ED_space_image_release_buffer(sima, ibuf, lock);
- return has_buffer;
+ return has_buffer;
}
void ED_space_image_get_size(SpaceImage *sima, int *width, int *height)
{
- Scene *scene = sima->iuser.scene;
- ImBuf *ibuf;
- void *lock;
-
- ibuf = ED_space_image_acquire_buffer(sima, &lock);
-
- if (ibuf && ibuf->x > 0 && ibuf->y > 0) {
- *width = ibuf->x;
- *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;
-
- 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);
- }
-
- }
- /* I know a bit weak... but preview uses not actual image size */
- // XXX else if (image_preview_active(sima, width, height));
- else {
- *width = IMG_SIZE_FALLBACK;
- *height = IMG_SIZE_FALLBACK;
- }
-
- ED_space_image_release_buffer(sima, ibuf, lock);
+ Scene *scene = sima->iuser.scene;
+ ImBuf *ibuf;
+ void *lock;
+
+ ibuf = ED_space_image_acquire_buffer(sima, &lock);
+
+ if (ibuf && ibuf->x > 0 && ibuf->y > 0) {
+ *width = ibuf->x;
+ *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;
+
+ 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);
+ }
+ }
+ /* I know a bit weak... but preview uses not actual image size */
+ // XXX else if (image_preview_active(sima, width, height));
+ else {
+ *width = IMG_SIZE_FALLBACK;
+ *height = IMG_SIZE_FALLBACK;
+ }
+
+ ED_space_image_release_buffer(sima, ibuf, lock);
}
void ED_space_image_get_size_fl(SpaceImage *sima, float 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];
+ 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];
}
-
void ED_space_image_get_aspect(SpaceImage *sima, float *aspx, float *aspy)
{
- Image *ima = sima->image;
- if ((ima == NULL) || (ima->aspx == 0.0f || ima->aspy == 0.0f)) {
- *aspx = *aspy = 1.0;
- }
- else {
- BKE_image_get_aspect(ima, aspx, aspy);
- }
+ Image *ima = sima->image;
+ if ((ima == NULL) || (ima->aspx == 0.0f || ima->aspy == 0.0f)) {
+ *aspx = *aspy = 1.0;
+ }
+ else {
+ BKE_image_get_aspect(ima, aspx, aspy);
+ }
}
void ED_space_image_get_zoom(SpaceImage *sima, ARegion *ar, float *zoomx, float *zoomy)
{
- int width, height;
+ int width, height;
- ED_space_image_get_size(sima, &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);
+ *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);
}
void ED_space_image_get_uv_aspect(SpaceImage *sima, float *aspx, float *aspy)
{
- int w, h;
-
- ED_space_image_get_aspect(sima, aspx, aspy);
- ED_space_image_get_size(sima, &w, &h);
-
- *aspx *= (float)w;
- *aspy *= (float)h;
-
- if (*aspx < *aspy) {
- *aspy = *aspy / *aspx;
- *aspx = 1.0f;
- }
- else {
- *aspx = *aspx / *aspy;
- *aspy = 1.0f;
- }
+ int w, h;
+
+ ED_space_image_get_aspect(sima, aspx, aspy);
+ ED_space_image_get_size(sima, &w, &h);
+
+ *aspx *= (float)w;
+ *aspy *= (float)h;
+
+ if (*aspx < *aspy) {
+ *aspy = *aspy / *aspx;
+ *aspx = 1.0f;
+ }
+ else {
+ *aspx = *aspx / *aspy;
+ *aspy = 1.0f;
+ }
}
void ED_image_get_uv_aspect(Image *ima, ImageUser *iuser, float *aspx, float *aspy)
{
- if (ima) {
- int w, h;
-
- BKE_image_get_aspect(ima, aspx, aspy);
- BKE_image_get_size(ima, iuser, &w, &h);
-
- *aspx *= (float)w;
- *aspy *= (float)h;
- }
- else {
- *aspx = 1.0f;
- *aspy = 1.0f;
- }
+ if (ima) {
+ int w, h;
+
+ BKE_image_get_aspect(ima, aspx, aspy);
+ BKE_image_get_size(ima, iuser, &w, &h);
+
+ *aspx *= (float)w;
+ *aspy *= (float)h;
+ }
+ else {
+ *aspx = 1.0f;
+ *aspy = 1.0f;
+ }
}
/* takes event->mval */
void ED_image_mouse_pos(SpaceImage *sima, ARegion *ar, const int mval[2], float co[2])
{
- int sx, sy, width, height;
- float zoomx, zoomy;
+ int sx, sy, width, height;
+ float zoomx, zoomy;
- ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
- ED_space_image_get_size(sima, &width, &height);
+ ED_space_image_get_zoom(sima, ar, &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(&ar->v2d, 0.0f, 0.0f, &sx, &sy);
- co[0] = ((mval[0] - sx) / zoomx) / width;
- co[1] = ((mval[1] - sy) / zoomy) / height;
+ co[0] = ((mval[0] - sx) / zoomx) / width;
+ co[1] = ((mval[1] - sy) / zoomy) / height;
}
void ED_image_point_pos(SpaceImage *sima, ARegion *ar, float x, float y, float *xr, float *yr)
{
- int sx, sy, width, height;
- float zoomx, zoomy;
+ int sx, sy, width, height;
+ float zoomx, zoomy;
- ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
- ED_space_image_get_size(sima, &width, &height);
+ ED_space_image_get_zoom(sima, ar, &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(&ar->v2d, 0.0f, 0.0f, &sx, &sy);
- *xr = ((x - sx) / zoomx) / width;
- *yr = ((y - sy) / zoomy) / height;
+ *xr = ((x - sx) / zoomx) / width;
+ *yr = ((y - sy) / zoomy) / height;
}
void ED_image_point_pos__reverse(SpaceImage *sima, ARegion *ar, const float co[2], float r_co[2])
{
- float zoomx, zoomy;
- int width, height;
- int sx, sy;
+ float zoomx, zoomy;
+ int width, height;
+ int sx, sy;
- UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &sx, &sy);
- ED_space_image_get_size(sima, &width, &height);
- ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
+ UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &sx, &sy);
+ ED_space_image_get_size(sima, &width, &height);
+ ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
- r_co[0] = (co[0] * width * zoomx) + (float)sx;
- r_co[1] = (co[1] * height * zoomy) + (float)sy;
+ r_co[0] = (co[0] * width * zoomx) + (float)sx;
+ r_co[1] = (co[1] * height * zoomy) + (float)sy;
}
/**
@@ -332,141 +332,144 @@ void ED_image_point_pos__reverse(SpaceImage *sima, ARegion *ar, const float co[2
*/
bool ED_image_slot_cycle(struct Image *image, int direction)
{
- const int cur = image->render_slot;
- int i, slot;
-
- BLI_assert(ELEM(direction, -1, 1));
-
- int num_slots = BLI_listbase_count(&image->renderslots);
- for (i = 1; i < num_slots; i++) {
- slot = (cur + ((direction == -1) ? -i : i)) % num_slots;
- if (slot < 0) {
- slot += num_slots;
- }
-
- RenderSlot *render_slot = BKE_image_get_renderslot(image, slot);
- if ((render_slot && render_slot->render) || slot == image->last_render_slot) {
- image->render_slot = slot;
- break;
- }
- }
-
- if (i == num_slots) {
- image->render_slot = ((cur == 1) ? 0 : 1);
- }
-
- return (cur != image->render_slot);
+ const int cur = image->render_slot;
+ int i, slot;
+
+ BLI_assert(ELEM(direction, -1, 1));
+
+ int num_slots = BLI_listbase_count(&image->renderslots);
+ for (i = 1; i < num_slots; i++) {
+ slot = (cur + ((direction == -1) ? -i : i)) % num_slots;
+ if (slot < 0) {
+ slot += num_slots;
+ }
+
+ RenderSlot *render_slot = BKE_image_get_renderslot(image, slot);
+ if ((render_slot && render_slot->render) || slot == image->last_render_slot) {
+ image->render_slot = slot;
+ break;
+ }
+ }
+
+ if (i == num_slots) {
+ image->render_slot = ((cur == 1) ? 0 : 1);
+ }
+
+ return (cur != image->render_slot);
}
-void ED_space_image_scopes_update(const struct bContext *C, struct SpaceImage *sima, struct ImBuf *ibuf, bool use_view_settings)
+void ED_space_image_scopes_update(const struct bContext *C,
+ struct SpaceImage *sima,
+ struct ImBuf *ibuf,
+ bool use_view_settings)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
-
- /* scope update can be expensive, don't update during paint modes */
- if (sima->mode == SI_MODE_PAINT) {
- return;
- }
- if (ob && ((ob->mode & (OB_MODE_TEXTURE_PAINT | OB_MODE_EDIT)) != 0)) {
- return;
- }
-
- /* We also don't update scopes of render result during render. */
- if (G.is_rendering) {
- const Image *image = sima->image;
- if (image != NULL &&
- (image->type == IMA_TYPE_R_RESULT || image->type == IMA_TYPE_COMPOSITE))
- {
- return;
- }
- }
-
- scopes_update(&sima->scopes, ibuf, use_view_settings ? &scene->view_settings : NULL, &scene->display_settings);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+
+ /* scope update can be expensive, don't update during paint modes */
+ if (sima->mode == SI_MODE_PAINT) {
+ return;
+ }
+ if (ob && ((ob->mode & (OB_MODE_TEXTURE_PAINT | OB_MODE_EDIT)) != 0)) {
+ return;
+ }
+
+ /* We also don't update scopes of render result during render. */
+ if (G.is_rendering) {
+ const Image *image = sima->image;
+ if (image != NULL && (image->type == IMA_TYPE_R_RESULT || image->type == IMA_TYPE_COMPOSITE)) {
+ return;
+ }
+ }
+
+ scopes_update(&sima->scopes,
+ ibuf,
+ use_view_settings ? &scene->view_settings : NULL,
+ &scene->display_settings);
}
bool ED_space_image_show_render(SpaceImage *sima)
{
- return (sima->image && ELEM(sima->image->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE));
+ return (sima->image && ELEM(sima->image->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE));
}
bool ED_space_image_show_paint(SpaceImage *sima)
{
- if (ED_space_image_show_render(sima)) {
- return false;
- }
+ if (ED_space_image_show_render(sima)) {
+ return false;
+ }
- return (sima->mode == SI_MODE_PAINT);
+ return (sima->mode == SI_MODE_PAINT);
}
bool ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit)
{
- if (sima) {
- if (ED_space_image_show_render(sima)) {
- return false;
- }
- if (sima->mode != SI_MODE_UV) {
- return false;
- }
- }
+ if (sima) {
+ if (ED_space_image_show_render(sima)) {
+ return false;
+ }
+ if (sima->mode != SI_MODE_UV) {
+ return false;
+ }
+ }
- if (obedit && obedit->type == OB_MESH) {
- struct BMEditMesh *em = BKE_editmesh_from_object(obedit);
- bool ret;
+ if (obedit && obedit->type == OB_MESH) {
+ struct BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ bool ret;
- ret = EDBM_uv_check(em);
+ ret = EDBM_uv_check(em);
- return ret;
- }
+ return ret;
+ }
- return false;
+ return false;
}
/* matches clip function */
bool ED_space_image_check_show_maskedit(SpaceImage *sima, ViewLayer *view_layer)
{
- /* check editmode - this is reserved for UV editing */
- Object *ob = OBACT(view_layer);
- if (ob && ob->mode & OB_MODE_EDIT && ED_space_image_show_uvedit(sima, ob)) {
- return false;
- }
+ /* check editmode - this is reserved for UV editing */
+ Object *ob = OBACT(view_layer);
+ if (ob && ob->mode & OB_MODE_EDIT && ED_space_image_show_uvedit(sima, ob)) {
+ return false;
+ }
- return (sima->mode == SI_MODE_MASK);
+ return (sima->mode == SI_MODE_MASK);
}
bool ED_space_image_maskedit_poll(bContext *C)
{
- SpaceImage *sima = CTX_wm_space_image(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
- if (sima) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- return ED_space_image_check_show_maskedit(sima, view_layer);
- }
+ if (sima) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ return ED_space_image_check_show_maskedit(sima, view_layer);
+ }
- return false;
+ return false;
}
bool ED_space_image_paint_curve(const bContext *C)
{
- SpaceImage *sima = CTX_wm_space_image(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
- if (sima && sima->mode == SI_MODE_PAINT) {
- Brush *br = CTX_data_tool_settings(C)->imapaint.paint.brush;
+ if (sima && sima->mode == SI_MODE_PAINT) {
+ Brush *br = CTX_data_tool_settings(C)->imapaint.paint.brush;
- if (br && (br->flag & BRUSH_CURVE)) {
- return true;
- }
- }
+ if (br && (br->flag & BRUSH_CURVE)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
-
bool ED_space_image_maskedit_mask_poll(bContext *C)
{
- if (ED_space_image_maskedit_poll(C)) {
- SpaceImage *sima = CTX_wm_space_image(C);
- return sima->mask_info.mask != NULL;
- }
+ if (ED_space_image_maskedit_poll(C)) {
+ SpaceImage *sima = CTX_wm_space_image(C);
+ return sima->mask_info.mask != NULL;
+ }
- return false;
+ return false;
}
diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h
index 55ae664decd..db56f1051c5 100644
--- a/source/blender/editors/space_image/image_intern.h
+++ b/source/blender/editors/space_image/image_intern.h
@@ -21,7 +21,6 @@
* \ingroup spimage
*/
-
#ifndef __IMAGE_INTERN_H__
#define __IMAGE_INTERN_H__
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 85c7d2d8fa9..06bacabe6fa 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -21,7 +21,6 @@
* \ingroup spimage
*/
-
#include <stddef.h>
#include <string.h>
#include <fcntl.h>
@@ -105,46 +104,49 @@
static void sima_zoom_set(SpaceImage *sima, ARegion *ar, float zoom, const float location[2])
{
- float oldzoom = sima->zoom;
- int width, height;
+ float oldzoom = sima->zoom;
+ int width, height;
- sima->zoom = zoom;
+ sima->zoom = zoom;
- if (sima->zoom < 0.1f || sima->zoom > 4.0f) {
- /* check zoom limits */
- ED_space_image_get_size(sima, &width, &height);
+ if (sima->zoom < 0.1f || sima->zoom > 4.0f) {
+ /* check zoom limits */
+ ED_space_image_get_size(sima, &width, &height);
- width *= sima->zoom;
- height *= sima->zoom;
+ width *= sima->zoom;
+ height *= sima->zoom;
- if ((width < 4) && (height < 4) && sima->zoom < oldzoom) {
- sima->zoom = oldzoom;
- }
- else if (BLI_rcti_size_x(&ar->winrct) <= sima->zoom) {
- sima->zoom = oldzoom;
- }
- else if (BLI_rcti_size_y(&ar->winrct) <= sima->zoom) {
- sima->zoom = oldzoom;
- }
- }
+ if ((width < 4) && (height < 4) && sima->zoom < oldzoom) {
+ sima->zoom = oldzoom;
+ }
+ else if (BLI_rcti_size_x(&ar->winrct) <= sima->zoom) {
+ sima->zoom = oldzoom;
+ }
+ else if (BLI_rcti_size_y(&ar->winrct) <= sima->zoom) {
+ sima->zoom = oldzoom;
+ }
+ }
- if ((U.uiflag & USER_ZOOM_TO_MOUSEPOS) && location) {
- float aspx, aspy, w, h;
+ if ((U.uiflag & USER_ZOOM_TO_MOUSEPOS) && location) {
+ float aspx, aspy, w, h;
- ED_space_image_get_size(sima, &width, &height);
- ED_space_image_get_aspect(sima, &aspx, &aspy);
+ ED_space_image_get_size(sima, &width, &height);
+ ED_space_image_get_aspect(sima, &aspx, &aspy);
- w = width * aspx;
- h = height * aspy;
+ w = width * aspx;
+ h = height * aspy;
- sima->xof += ((location[0] - 0.5f) * w - sima->xof) * (sima->zoom - oldzoom) / sima->zoom;
- sima->yof += ((location[1] - 0.5f) * h - sima->yof) * (sima->zoom - oldzoom) / sima->zoom;
- }
+ sima->xof += ((location[0] - 0.5f) * w - sima->xof) * (sima->zoom - oldzoom) / sima->zoom;
+ sima->yof += ((location[1] - 0.5f) * h - sima->yof) * (sima->zoom - oldzoom) / sima->zoom;
+ }
}
-static void sima_zoom_set_factor(SpaceImage *sima, ARegion *ar, float zoomfac, const float location[2])
+static void sima_zoom_set_factor(SpaceImage *sima,
+ ARegion *ar,
+ float zoomfac,
+ const float location[2])
{
- sima_zoom_set(sima, ar, sima->zoom * zoomfac, location);
+ sima_zoom_set(sima, ar, sima->zoom * zoomfac, location);
}
/**
@@ -152,509 +154,530 @@ static void sima_zoom_set_factor(SpaceImage *sima, ARegion *ar, float zoomfac, c
*/
static void sima_zoom_set_from_bounds(SpaceImage *sima, ARegion *ar, const rctf *bounds)
{
- int image_size[2];
- float aspx, aspy;
+ int image_size[2];
+ float aspx, aspy;
- ED_space_image_get_size(sima, &image_size[0], &image_size[1]);
- ED_space_image_get_aspect(sima, &aspx, &aspy);
+ ED_space_image_get_size(sima, &image_size[0], &image_size[1]);
+ ED_space_image_get_aspect(sima, &aspx, &aspy);
- image_size[0] = image_size[0] * aspx;
- image_size[1] = image_size[1] * aspy;
+ image_size[0] = image_size[0] * aspx;
+ image_size[1] = image_size[1] * aspy;
- /* adjust offset and zoom */
- sima->xof = roundf((BLI_rctf_cent_x(bounds) - 0.5f) * image_size[0]);
- sima->yof = roundf((BLI_rctf_cent_y(bounds) - 0.5f) * image_size[1]);
+ /* adjust offset and zoom */
+ sima->xof = roundf((BLI_rctf_cent_x(bounds) - 0.5f) * image_size[0]);
+ 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]);
+ 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 = min_ff(size_xy[0], size_xy[1]);
- CLAMP_MAX(size, 100.0f);
+ size = min_ff(size_xy[0], size_xy[1]);
+ CLAMP_MAX(size, 100.0f);
- sima_zoom_set(sima, ar, size, NULL);
+ sima_zoom_set(sima, ar, size, NULL);
}
-#if 0 // currently unused
+#if 0 // currently unused
static bool image_poll(bContext *C)
{
- return (CTX_data_edit_image(C) != NULL);
+ return (CTX_data_edit_image(C) != NULL);
}
#endif
static bool space_image_buffer_exists_poll(bContext *C)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- if (sima && ED_space_image_has_buffer(sima)) {
- return true;
- }
- return false;
+ SpaceImage *sima = CTX_wm_space_image(C);
+ if (sima && ED_space_image_has_buffer(sima)) {
+ return true;
+ }
+ return false;
}
static bool image_not_packed_poll(bContext *C)
{
- SpaceImage *sima = CTX_wm_space_image(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
- /* Do not run 'replace' on packed images, it does not give user expected results at all. */
- if (sima && sima->image && BLI_listbase_is_empty(&sima->image->packedfiles)) {
- return true;
- }
- return false;
+ /* Do not run 'replace' on packed images, it does not give user expected results at all. */
+ if (sima && sima->image && BLI_listbase_is_empty(&sima->image->packedfiles)) {
+ return true;
+ }
+ return false;
}
static bool imbuf_format_writeable(const ImBuf *ibuf)
{
- ImageFormatData im_format;
- ImbFormatOptions options_dummy;
- BKE_imbuf_to_image_format(&im_format, ibuf);
- return (BKE_image_imtype_to_ftype(im_format.imtype, &options_dummy) == ibuf->ftype);
+ ImageFormatData im_format;
+ ImbFormatOptions options_dummy;
+ BKE_imbuf_to_image_format(&im_format, ibuf);
+ return (BKE_image_imtype_to_ftype(im_format.imtype, &options_dummy) == ibuf->ftype);
}
static bool space_image_file_exists_poll(bContext *C)
{
- if (space_image_buffer_exists_poll(C)) {
- Main *bmain = CTX_data_main(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- ImBuf *ibuf;
- void *lock;
- bool ret = false;
- char name[FILE_MAX];
-
- ibuf = ED_space_image_acquire_buffer(sima, &lock);
- if (ibuf) {
- BLI_strncpy(name, ibuf->name, FILE_MAX);
- BLI_path_abs(name, BKE_main_blendfile_path(bmain));
-
- if (BLI_exists(name) == false) {
- CTX_wm_operator_poll_msg_set(C, "image file not found");
- }
- else if (!BLI_file_is_writable(name)) {
- CTX_wm_operator_poll_msg_set(C, "image path can't be written to");
- }
- else if (!imbuf_format_writeable(ibuf)) {
- CTX_wm_operator_poll_msg_set(C, "image format is read-only");
- }
- else {
- ret = true;
- }
- }
- ED_space_image_release_buffer(sima, ibuf, lock);
-
- return ret;
- }
- return false;
-}
-
-#if 0 /* UNUSED */
+ if (space_image_buffer_exists_poll(C)) {
+ Main *bmain = CTX_data_main(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ImBuf *ibuf;
+ void *lock;
+ bool ret = false;
+ char name[FILE_MAX];
+
+ ibuf = ED_space_image_acquire_buffer(sima, &lock);
+ if (ibuf) {
+ BLI_strncpy(name, ibuf->name, FILE_MAX);
+ BLI_path_abs(name, BKE_main_blendfile_path(bmain));
+
+ if (BLI_exists(name) == false) {
+ CTX_wm_operator_poll_msg_set(C, "image file not found");
+ }
+ else if (!BLI_file_is_writable(name)) {
+ CTX_wm_operator_poll_msg_set(C, "image path can't be written to");
+ }
+ else if (!imbuf_format_writeable(ibuf)) {
+ CTX_wm_operator_poll_msg_set(C, "image format is read-only");
+ }
+ else {
+ ret = true;
+ }
+ }
+ ED_space_image_release_buffer(sima, ibuf, lock);
+
+ return ret;
+ }
+ return false;
+}
+
+#if 0 /* UNUSED */
static bool space_image_poll(bContext *C)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- if (sima && sima->image) {
- return true;
- }
- return false;
+ SpaceImage *sima = CTX_wm_space_image(C);
+ if (sima && sima->image) {
+ return true;
+ }
+ return false;
}
#endif
bool space_image_main_region_poll(bContext *C)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- /* XXX ARegion *ar = CTX_wm_region(C); */
+ SpaceImage *sima = CTX_wm_space_image(C);
+ /* XXX ARegion *ar = CTX_wm_region(C); */
- if (sima) {
- return true; /* XXX (ar && ar->type->regionid == RGN_TYPE_WINDOW); */
- }
- return false;
+ if (sima) {
+ return true; /* XXX (ar && ar->type->regionid == RGN_TYPE_WINDOW); */
+ }
+ return false;
}
/* For IMAGE_OT_curves_point_set to avoid sampling when in uv smooth mode or editmode */
static bool space_image_main_area_not_uv_brush_poll(bContext *C)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- Scene *scene = CTX_data_scene(C);
- ToolSettings *toolsettings = scene->toolsettings;
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *toolsettings = scene->toolsettings;
- if (sima && !toolsettings->uvsculpt && (CTX_data_edit_object(C) == NULL)) {
- return 1;
- }
+ if (sima && !toolsettings->uvsculpt && (CTX_data_edit_object(C) == NULL)) {
+ return 1;
+ }
- return 0;
+ return 0;
}
static bool image_sample_poll(bContext *C)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- if (sima) {
- Object *obedit = CTX_data_edit_object(C);
- if (obedit) {
- /* Disable when UV editing so it doesn't swallow all click events (use for setting cursor). */
- if (ED_space_image_show_uvedit(sima, obedit)) {
- return false;
- }
- }
- else if (sima->mode != SI_MODE_VIEW) {
- return false;
- }
-
- return space_image_main_region_poll(C);
- }
- else {
- return false;
- }
+ SpaceImage *sima = CTX_wm_space_image(C);
+ if (sima) {
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit) {
+ /* Disable when UV editing so it doesn't swallow all click events (use for setting cursor). */
+ if (ED_space_image_show_uvedit(sima, obedit)) {
+ return false;
+ }
+ }
+ else if (sima->mode != SI_MODE_VIEW) {
+ return false;
+ }
+
+ return space_image_main_region_poll(C);
+ }
+ else {
+ return false;
+ }
}
/********************** view pan operator *********************/
typedef struct ViewPanData {
- float x, y;
- float xof, yof;
- int event_type;
+ float x, y;
+ float xof, yof;
+ int event_type;
} ViewPanData;
static void image_view_pan_init(bContext *C, wmOperator *op, const wmEvent *event)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- ViewPanData *vpd;
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ViewPanData *vpd;
- op->customdata = vpd = MEM_callocN(sizeof(ViewPanData), "ImageViewPanData");
- WM_cursor_modal_set(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
+ op->customdata = vpd = MEM_callocN(sizeof(ViewPanData), "ImageViewPanData");
+ WM_cursor_modal_set(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
- vpd->x = event->x;
- vpd->y = event->y;
- vpd->xof = sima->xof;
- vpd->yof = sima->yof;
- vpd->event_type = event->type;
+ vpd->x = event->x;
+ vpd->y = event->y;
+ vpd->xof = sima->xof;
+ vpd->yof = sima->yof;
+ vpd->event_type = event->type;
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
}
static void image_view_pan_exit(bContext *C, wmOperator *op, bool cancel)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- ViewPanData *vpd = op->customdata;
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ViewPanData *vpd = op->customdata;
- if (cancel) {
- sima->xof = vpd->xof;
- sima->yof = vpd->yof;
- ED_region_tag_redraw(CTX_wm_region(C));
- }
+ if (cancel) {
+ sima->xof = vpd->xof;
+ sima->yof = vpd->yof;
+ ED_region_tag_redraw(CTX_wm_region(C));
+ }
- WM_cursor_modal_restore(CTX_wm_window(C));
- MEM_freeN(op->customdata);
+ WM_cursor_modal_restore(CTX_wm_window(C));
+ MEM_freeN(op->customdata);
}
static int image_view_pan_exec(bContext *C, wmOperator *op)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- float offset[2];
+ SpaceImage *sima = CTX_wm_space_image(C);
+ float offset[2];
- RNA_float_get_array(op->ptr, "offset", offset);
- sima->xof += offset[0];
- sima->yof += offset[1];
+ RNA_float_get_array(op->ptr, "offset", offset);
+ sima->xof += offset[0];
+ sima->yof += offset[1];
- ED_region_tag_redraw(CTX_wm_region(C));
+ ED_region_tag_redraw(CTX_wm_region(C));
- /* XXX notifier? */
+ /* XXX notifier? */
#if 0
- if (image_preview_active(curarea, NULL, NULL)) {
- /* recalculates new preview rect */
- scrarea_do_windraw(curarea);
- image_preview_event(2);
- }
+ if (image_preview_active(curarea, NULL, NULL)) {
+ /* recalculates new preview rect */
+ scrarea_do_windraw(curarea);
+ image_preview_event(2);
+ }
#endif
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int image_view_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (event->type == MOUSEPAN) {
- SpaceImage *sima = CTX_wm_space_image(C);
- float offset[2];
+ if (event->type == MOUSEPAN) {
+ SpaceImage *sima = CTX_wm_space_image(C);
+ float offset[2];
- offset[0] = (event->prevx - event->x) / sima->zoom;
- offset[1] = (event->prevy - event->y) / sima->zoom;
- RNA_float_set_array(op->ptr, "offset", offset);
+ offset[0] = (event->prevx - event->x) / sima->zoom;
+ offset[1] = (event->prevy - event->y) / sima->zoom;
+ RNA_float_set_array(op->ptr, "offset", offset);
- image_view_pan_exec(C, op);
- return OPERATOR_FINISHED;
- }
- else {
- image_view_pan_init(C, op, event);
- return OPERATOR_RUNNING_MODAL;
- }
+ image_view_pan_exec(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ image_view_pan_init(C, op, event);
+ return OPERATOR_RUNNING_MODAL;
+ }
}
static int image_view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- ViewPanData *vpd = op->customdata;
- float offset[2];
-
- switch (event->type) {
- case MOUSEMOVE:
- sima->xof = vpd->xof;
- sima->yof = vpd->yof;
- offset[0] = (vpd->x - event->x) / sima->zoom;
- offset[1] = (vpd->y - event->y) / sima->zoom;
- RNA_float_set_array(op->ptr, "offset", offset);
- image_view_pan_exec(C, op);
- break;
- default:
- if (event->type == vpd->event_type && event->val == KM_RELEASE) {
- image_view_pan_exit(C, op, false);
- return OPERATOR_FINISHED;
- }
- break;
- }
-
- return OPERATOR_RUNNING_MODAL;
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ViewPanData *vpd = op->customdata;
+ float offset[2];
+
+ switch (event->type) {
+ case MOUSEMOVE:
+ sima->xof = vpd->xof;
+ sima->yof = vpd->yof;
+ offset[0] = (vpd->x - event->x) / sima->zoom;
+ offset[1] = (vpd->y - event->y) / sima->zoom;
+ RNA_float_set_array(op->ptr, "offset", offset);
+ image_view_pan_exec(C, op);
+ break;
+ default:
+ if (event->type == vpd->event_type && event->val == KM_RELEASE) {
+ image_view_pan_exit(C, op, false);
+ return OPERATOR_FINISHED;
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
static void image_view_pan_cancel(bContext *C, wmOperator *op)
{
- image_view_pan_exit(C, op, true);
+ image_view_pan_exit(C, op, true);
}
void IMAGE_OT_view_pan(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Pan View";
- ot->idname = "IMAGE_OT_view_pan";
- ot->description = "Pan the view";
-
- /* api callbacks */
- ot->exec = image_view_pan_exec;
- ot->invoke = image_view_pan_invoke;
- ot->modal = image_view_pan_modal;
- ot->cancel = image_view_pan_cancel;
- ot->poll = space_image_main_region_poll;
-
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_LOCK_BYPASS;
-
- /* properties */
- RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX,
- "Offset", "Offset in floating point units, 1.0 is the width and height of the image", -FLT_MAX, FLT_MAX);
+ /* identifiers */
+ ot->name = "Pan View";
+ ot->idname = "IMAGE_OT_view_pan";
+ ot->description = "Pan the view";
+
+ /* api callbacks */
+ ot->exec = image_view_pan_exec;
+ ot->invoke = image_view_pan_invoke;
+ ot->modal = image_view_pan_modal;
+ ot->cancel = image_view_pan_cancel;
+ ot->poll = space_image_main_region_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_LOCK_BYPASS;
+
+ /* properties */
+ RNA_def_float_vector(ot->srna,
+ "offset",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Offset",
+ "Offset in floating point units, 1.0 is the width and height of the image",
+ -FLT_MAX,
+ FLT_MAX);
}
/********************** view zoom operator *********************/
typedef struct ViewZoomData {
- float origx, origy;
- float zoom;
- int event_type;
- float location[2];
-
- /* needed for continuous zoom */
- wmTimer *timer;
- double timer_lastdraw;
-
- /* */
- SpaceImage *sima;
- ARegion *ar;
+ float origx, origy;
+ float zoom;
+ int event_type;
+ float location[2];
+
+ /* needed for continuous zoom */
+ wmTimer *timer;
+ double timer_lastdraw;
+
+ /* */
+ SpaceImage *sima;
+ ARegion *ar;
} ViewZoomData;
static void image_view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
- ViewZoomData *vpd;
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ARegion *ar = CTX_wm_region(C);
+ ViewZoomData *vpd;
- op->customdata = vpd = MEM_callocN(sizeof(ViewZoomData), "ImageViewZoomData");
- WM_cursor_modal_set(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
+ op->customdata = vpd = MEM_callocN(sizeof(ViewZoomData), "ImageViewZoomData");
+ WM_cursor_modal_set(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
- vpd->origx = event->x;
- vpd->origy = event->y;
- vpd->zoom = sima->zoom;
- vpd->event_type = event->type;
+ vpd->origx = event->x;
+ vpd->origy = event->y;
+ vpd->zoom = sima->zoom;
+ vpd->event_type = event->type;
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &vpd->location[0], &vpd->location[1]);
+ UI_view2d_region_to_view(
+ &ar->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 */
- vpd->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
- vpd->timer_lastdraw = PIL_check_seconds_timer();
- }
+ if (U.viewzoom == USER_ZOOM_CONT) {
+ /* needs a timer to continue redrawing */
+ vpd->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
+ vpd->timer_lastdraw = PIL_check_seconds_timer();
+ }
- vpd->sima = sima;
- vpd->ar = ar;
+ vpd->sima = sima;
+ vpd->ar = ar;
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
}
static void image_view_zoom_exit(bContext *C, wmOperator *op, bool cancel)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- ViewZoomData *vpd = op->customdata;
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ViewZoomData *vpd = op->customdata;
- if (cancel) {
- sima->zoom = vpd->zoom;
- ED_region_tag_redraw(CTX_wm_region(C));
- }
+ if (cancel) {
+ sima->zoom = vpd->zoom;
+ ED_region_tag_redraw(CTX_wm_region(C));
+ }
- if (vpd->timer) {
- WM_event_remove_timer(CTX_wm_manager(C), vpd->timer->win, vpd->timer);
- }
+ if (vpd->timer) {
+ WM_event_remove_timer(CTX_wm_manager(C), vpd->timer->win, vpd->timer);
+ }
- WM_cursor_modal_restore(CTX_wm_window(C));
- MEM_freeN(op->customdata);
+ WM_cursor_modal_restore(CTX_wm_window(C));
+ MEM_freeN(op->customdata);
}
static int image_view_zoom_exec(bContext *C, wmOperator *op)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ARegion *ar = CTX_wm_region(C);
- sima_zoom_set_factor(sima, ar, RNA_float_get(op->ptr, "factor"), NULL);
+ sima_zoom_set_factor(sima, ar, RNA_float_get(op->ptr, "factor"), NULL);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- /* XXX notifier? */
+ /* XXX notifier? */
#if 0
- if (image_preview_active(curarea, NULL, NULL)) {
- /* recalculates new preview rect */
- scrarea_do_windraw(curarea);
- image_preview_event(2);
- }
+ if (image_preview_active(curarea, NULL, NULL)) {
+ /* recalculates new preview rect */
+ scrarea_do_windraw(curarea);
+ image_preview_event(2);
+ }
#endif
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
enum {
- VIEW_PASS = 0,
- VIEW_APPLY,
- VIEW_CONFIRM,
+ VIEW_PASS = 0,
+ VIEW_APPLY,
+ VIEW_CONFIRM,
};
static int image_view_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
- SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = 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]);
-
- delta = event->prevx - event->x + event->prevy - event->y;
-
- if (U.uiflag & USER_ZOOM_INVERT) {
- delta *= -1;
- }
-
- factor = 1.0f + delta / 300.0f;
- RNA_float_set(op->ptr, "factor", factor);
- sima_zoom_set(sima, ar, sima->zoom * factor, location);
- ED_region_tag_redraw(ar);
-
- return OPERATOR_FINISHED;
- }
- else {
- image_view_zoom_init(C, op, event);
- return OPERATOR_RUNNING_MODAL;
- }
-}
-
-static void image_zoom_apply(ViewZoomData *vpd, wmOperator *op, const int x, const int y, const short viewzoom, const short zoom_invert)
-{
- float factor;
-
- if (viewzoom == USER_ZOOM_CONT) {
- double time = PIL_check_seconds_timer();
- float time_step = (float)(time - vpd->timer_lastdraw);
- float fac;
- float zfac;
-
- if (U.uiflag & USER_ZOOM_HORIZ) {
- fac = (float)(x - vpd->origx);
- }
- else {
- fac = (float)(y - vpd->origy);
- }
-
- if (zoom_invert) {
- fac = -fac;
- }
-
- /* oldstyle zoom */
- zfac = 1.0f + ((fac / 20.0f) * time_step);
- vpd->timer_lastdraw = time;
- /* this is the final zoom, but instead make it into a factor */
- //zoom = vpd->sima->zoom * zfac;
- factor = (vpd->sima->zoom * zfac) / vpd->zoom;
- }
- else {
- /* for now do the same things for scale and dolly */
- float delta = x - vpd->origx + y - vpd->origy;
-
- if (zoom_invert) {
- delta *= -1.0f;
- }
-
- factor = 1.0f + delta / 300.0f;
- }
-
- RNA_float_set(op->ptr, "factor", factor);
- sima_zoom_set(vpd->sima, vpd->ar, vpd->zoom * factor, vpd->location);
- ED_region_tag_redraw(vpd->ar);
+ if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ARegion *ar = 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]);
+
+ delta = event->prevx - event->x + event->prevy - event->y;
+
+ if (U.uiflag & USER_ZOOM_INVERT) {
+ delta *= -1;
+ }
+
+ factor = 1.0f + delta / 300.0f;
+ RNA_float_set(op->ptr, "factor", factor);
+ sima_zoom_set(sima, ar, sima->zoom * factor, location);
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ image_view_zoom_init(C, op, event);
+ return OPERATOR_RUNNING_MODAL;
+ }
+}
+
+static void image_zoom_apply(ViewZoomData *vpd,
+ wmOperator *op,
+ const int x,
+ const int y,
+ const short viewzoom,
+ const short zoom_invert)
+{
+ float factor;
+
+ if (viewzoom == USER_ZOOM_CONT) {
+ double time = PIL_check_seconds_timer();
+ float time_step = (float)(time - vpd->timer_lastdraw);
+ float fac;
+ float zfac;
+
+ if (U.uiflag & USER_ZOOM_HORIZ) {
+ fac = (float)(x - vpd->origx);
+ }
+ else {
+ fac = (float)(y - vpd->origy);
+ }
+
+ if (zoom_invert) {
+ fac = -fac;
+ }
+
+ /* oldstyle zoom */
+ zfac = 1.0f + ((fac / 20.0f) * time_step);
+ vpd->timer_lastdraw = time;
+ /* this is the final zoom, but instead make it into a factor */
+ //zoom = vpd->sima->zoom * zfac;
+ factor = (vpd->sima->zoom * zfac) / vpd->zoom;
+ }
+ else {
+ /* for now do the same things for scale and dolly */
+ float delta = x - vpd->origx + y - vpd->origy;
+
+ if (zoom_invert) {
+ delta *= -1.0f;
+ }
+
+ factor = 1.0f + delta / 300.0f;
+ }
+
+ RNA_float_set(op->ptr, "factor", factor);
+ sima_zoom_set(vpd->sima, vpd->ar, vpd->zoom * factor, vpd->location);
+ ED_region_tag_redraw(vpd->ar);
}
static int image_view_zoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewZoomData *vpd = op->customdata;
- short event_code = VIEW_PASS;
+ ViewZoomData *vpd = op->customdata;
+ short event_code = VIEW_PASS;
- /* execute the events */
- if (event->type == TIMER && event->customdata == vpd->timer) {
- /* continuous zoom */
- event_code = VIEW_APPLY;
- }
- else if (event->type == MOUSEMOVE) {
- event_code = VIEW_APPLY;
- }
- else if (event->type == vpd->event_type && event->val == KM_RELEASE) {
- event_code = VIEW_CONFIRM;
- }
+ /* execute the events */
+ if (event->type == TIMER && event->customdata == vpd->timer) {
+ /* continuous zoom */
+ event_code = VIEW_APPLY;
+ }
+ else if (event->type == MOUSEMOVE) {
+ event_code = VIEW_APPLY;
+ }
+ else if (event->type == vpd->event_type && event->val == KM_RELEASE) {
+ event_code = VIEW_CONFIRM;
+ }
- if (event_code == VIEW_APPLY) {
- image_zoom_apply(vpd, op, event->x, event->y, U.viewzoom, (U.uiflag & USER_ZOOM_INVERT) != 0);
- }
- else if (event_code == VIEW_CONFIRM) {
- image_view_zoom_exit(C, op, false);
- return OPERATOR_FINISHED;
- }
+ if (event_code == VIEW_APPLY) {
+ image_zoom_apply(vpd, op, event->x, event->y, U.viewzoom, (U.uiflag & USER_ZOOM_INVERT) != 0);
+ }
+ else if (event_code == VIEW_CONFIRM) {
+ image_view_zoom_exit(C, op, false);
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static void image_view_zoom_cancel(bContext *C, wmOperator *op)
{
- image_view_zoom_exit(C, op, true);
+ image_view_zoom_exit(C, op, true);
}
void IMAGE_OT_view_zoom(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Zoom View";
- ot->idname = "IMAGE_OT_view_zoom";
- ot->description = "Zoom in/out the image";
+ /* identifiers */
+ ot->name = "Zoom View";
+ ot->idname = "IMAGE_OT_view_zoom";
+ ot->description = "Zoom in/out the image";
- /* api callbacks */
- ot->exec = image_view_zoom_exec;
- ot->invoke = image_view_zoom_invoke;
- ot->modal = image_view_zoom_modal;
- ot->cancel = image_view_zoom_cancel;
- ot->poll = space_image_main_region_poll;
+ /* api callbacks */
+ ot->exec = image_view_zoom_exec;
+ ot->invoke = image_view_zoom_invoke;
+ ot->modal = image_view_zoom_modal;
+ ot->cancel = image_view_zoom_cancel;
+ ot->poll = space_image_main_region_poll;
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_LOCK_BYPASS;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_LOCK_BYPASS;
- /* properties */
- prop = RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Factor",
- "Zoom factor, values higher than 1.0 zoom in, lower values zoom out", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ /* properties */
+ prop = RNA_def_float(ot->srna,
+ "factor",
+ 0.0f,
+ -FLT_MAX,
+ FLT_MAX,
+ "Factor",
+ "Zoom factor, values higher than 1.0 zoom in, lower values zoom out",
+ -FLT_MAX,
+ FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
#ifdef WITH_INPUT_NDOF
@@ -668,45 +691,45 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot)
static int image_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- if (event->type != NDOF_MOTION) {
- return OPERATOR_CANCELLED;
- }
- else {
- SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
- float pan_vec[3];
+ if (event->type != NDOF_MOTION) {
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ARegion *ar = CTX_wm_region(C);
+ float pan_vec[3];
- const wmNDOFMotionData *ndof = event->customdata;
- const float speed = NDOF_PIXELS_PER_SECOND;
+ const wmNDOFMotionData *ndof = event->customdata;
+ const float speed = NDOF_PIXELS_PER_SECOND;
- WM_event_ndof_pan_get(ndof, pan_vec, true);
+ WM_event_ndof_pan_get(ndof, pan_vec, true);
- mul_v2_fl(pan_vec, (speed * ndof->dt) / sima->zoom);
- pan_vec[2] *= -ndof->dt;
+ 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);
- sima->xof += pan_vec[0];
- sima->yof += pan_vec[1];
+ sima_zoom_set_factor(sima, ar, 1.0f + pan_vec[2], NULL);
+ sima->xof += pan_vec[0];
+ sima->yof += pan_vec[1];
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
}
void IMAGE_OT_view_ndof(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "NDOF Pan/Zoom";
- ot->idname = "IMAGE_OT_view_ndof";
- ot->description = "Use a 3D mouse device to pan/zoom the view";
+ /* identifiers */
+ ot->name = "NDOF Pan/Zoom";
+ ot->idname = "IMAGE_OT_view_ndof";
+ ot->description = "Use a 3D mouse device to pan/zoom the view";
- /* api callbacks */
- ot->invoke = image_view_ndof_invoke;
- ot->poll = space_image_main_region_poll;
+ /* api callbacks */
+ ot->invoke = image_view_ndof_invoke;
+ ot->poll = space_image_main_region_poll;
- /* flags */
- ot->flag = OPTYPE_LOCK_BYPASS;
+ /* flags */
+ ot->flag = OPTYPE_LOCK_BYPASS;
}
#endif /* WITH_INPUT_NDOF */
@@ -718,380 +741,405 @@ void IMAGE_OT_view_ndof(wmOperatorType *ot)
static int image_view_all_exec(bContext *C, wmOperator *op)
{
- SpaceImage *sima;
- ARegion *ar;
- float aspx, aspy, zoomx, zoomy, w, h;
- int width, height;
- const bool fit_view = RNA_boolean_get(op->ptr, "fit_view");
+ SpaceImage *sima;
+ ARegion *ar;
+ 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);
+ /* retrieve state */
+ sima = CTX_wm_space_image(C);
+ ar = CTX_wm_region(C);
- ED_space_image_get_size(sima, &width, &height);
- ED_space_image_get_aspect(sima, &aspx, &aspy);
+ ED_space_image_get_size(sima, &width, &height);
+ ED_space_image_get_aspect(sima, &aspx, &aspy);
- w = width * aspx;
- h = height * aspy;
+ w = width * aspx;
+ h = height * 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;
+ /* 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;
- if (fit_view) {
- const int margin = 5; /* margin from border */
+ if (fit_view) {
+ const int margin = 5; /* margin from border */
- zoomx = (float) width / (w + 2 * margin);
- zoomy = (float) height / (h + 2 * margin);
+ zoomx = (float)width / (w + 2 * margin);
+ zoomy = (float)height / (h + 2 * margin);
- sima_zoom_set(sima, ar, min_ff(zoomx, zoomy), NULL);
- }
- else {
- if ((w >= width || h >= height) && (width > 0 && height > 0)) {
- zoomx = (float) width / w;
- zoomy = (float) height / h;
+ sima_zoom_set(sima, ar, min_ff(zoomx, zoomy), NULL);
+ }
+ else {
+ if ((w >= width || h >= height) && (width > 0 && height > 0)) {
+ zoomx = (float)width / w;
+ 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);
- }
- else {
- sima_zoom_set(sima, ar, 1.0f, NULL);
- }
- }
+ /* 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);
+ }
+ else {
+ sima_zoom_set(sima, ar, 1.0f, NULL);
+ }
+ }
- sima->xof = sima->yof = 0.0f;
+ sima->xof = sima->yof = 0.0f;
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void IMAGE_OT_view_all(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "View All";
- ot->idname = "IMAGE_OT_view_all";
- ot->description = "View the entire image";
+ /* identifiers */
+ ot->name = "View All";
+ ot->idname = "IMAGE_OT_view_all";
+ ot->description = "View the entire image";
- /* api callbacks */
- ot->exec = image_view_all_exec;
- ot->poll = space_image_main_region_poll;
+ /* api callbacks */
+ ot->exec = image_view_all_exec;
+ ot->poll = space_image_main_region_poll;
- /* flags */
- ot->flag = OPTYPE_LOCK_BYPASS;
+ /* flags */
+ ot->flag = OPTYPE_LOCK_BYPASS;
- /* properties */
- prop = RNA_def_boolean(ot->srna, "fit_view", 0, "Fit View", "Fit frame to the viewport");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "fit_view", 0, "Fit View", "Fit frame to the viewport");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/********************** view selected operator *********************/
static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceImage *sima;
- ARegion *ar;
- Scene *scene;
- ViewLayer *view_layer;
- Object *obedit;
- Image *ima;
-
- /* retrieve state */
- sima = CTX_wm_space_image(C);
- ar = CTX_wm_region(C);
- scene = CTX_data_scene(C);
- view_layer = CTX_data_view_layer(C);
- obedit = CTX_data_edit_object(C);
-
- ima = ED_space_image(sima);
-
- /* get bounds */
- float min[2], max[2];
- if (ED_space_image_show_uvedit(sima, obedit)) {
- if (!ED_uvedit_minmax(scene, ima, obedit, min, max)) {
- return OPERATOR_CANCELLED;
- }
- }
- else if (ED_space_image_check_show_maskedit(sima, view_layer)) {
- if (!ED_mask_selected_minmax(C, min, max)) {
- return OPERATOR_CANCELLED;
- }
- }
- rctf bounds = {
- .xmin = min[0], .ymin = min[1],
- .xmax = max[0], .ymax = max[1],
- };
-
- /* add some margin */
- BLI_rctf_scale(&bounds, 1.4f);
-
- sima_zoom_set_from_bounds(sima, ar, &bounds);
-
- ED_region_tag_redraw(ar);
-
- return OPERATOR_FINISHED;
+ SpaceImage *sima;
+ ARegion *ar;
+ Scene *scene;
+ ViewLayer *view_layer;
+ Object *obedit;
+ Image *ima;
+
+ /* retrieve state */
+ sima = CTX_wm_space_image(C);
+ ar = CTX_wm_region(C);
+ scene = CTX_data_scene(C);
+ view_layer = CTX_data_view_layer(C);
+ obedit = CTX_data_edit_object(C);
+
+ ima = ED_space_image(sima);
+
+ /* get bounds */
+ float min[2], max[2];
+ if (ED_space_image_show_uvedit(sima, obedit)) {
+ if (!ED_uvedit_minmax(scene, ima, obedit, min, max)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else if (ED_space_image_check_show_maskedit(sima, view_layer)) {
+ if (!ED_mask_selected_minmax(C, min, max)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+ rctf bounds = {
+ .xmin = min[0],
+ .ymin = min[1],
+ .xmax = max[0],
+ .ymax = max[1],
+ };
+
+ /* add some margin */
+ BLI_rctf_scale(&bounds, 1.4f);
+
+ sima_zoom_set_from_bounds(sima, ar, &bounds);
+
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_FINISHED;
}
static bool image_view_selected_poll(bContext *C)
{
- return (space_image_main_region_poll(C) && (ED_operator_uvedit(C) || ED_operator_mask(C)));
+ return (space_image_main_region_poll(C) && (ED_operator_uvedit(C) || ED_operator_mask(C)));
}
void IMAGE_OT_view_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Center";
- ot->idname = "IMAGE_OT_view_selected";
- ot->description = "View all selected UVs";
+ /* identifiers */
+ ot->name = "View Center";
+ ot->idname = "IMAGE_OT_view_selected";
+ ot->description = "View all selected UVs";
- /* api callbacks */
- ot->exec = image_view_selected_exec;
- ot->poll = image_view_selected_poll;
+ /* api callbacks */
+ ot->exec = image_view_selected_exec;
+ ot->poll = image_view_selected_poll;
}
/********************** view zoom in/out operator *********************/
static int image_view_zoom_in_exec(bContext *C, wmOperator *op)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
- float location[2];
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ARegion *ar = CTX_wm_region(C);
+ float location[2];
- RNA_float_get_array(op->ptr, "location", location);
+ RNA_float_get_array(op->ptr, "location", location);
- sima_zoom_set_factor(sima, ar, powf(2.0f, 1.0f / 3.0f), location);
+ sima_zoom_set_factor(sima, ar, powf(2.0f, 1.0f / 3.0f), location);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int image_view_zoom_in_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- float location[2];
+ ARegion *ar = CTX_wm_region(C);
+ float location[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
- RNA_float_set_array(op->ptr, "location", location);
+ UI_view2d_region_to_view(&ar->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);
+ return image_view_zoom_in_exec(C, op);
}
void IMAGE_OT_view_zoom_in(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "View Zoom In";
- ot->idname = "IMAGE_OT_view_zoom_in";
- ot->description = "Zoom in the image (centered around 2D cursor)";
+ /* identifiers */
+ ot->name = "View Zoom In";
+ ot->idname = "IMAGE_OT_view_zoom_in";
+ ot->description = "Zoom in the image (centered around 2D cursor)";
- /* api callbacks */
- ot->invoke = image_view_zoom_in_invoke;
- ot->exec = image_view_zoom_in_exec;
- ot->poll = space_image_main_region_poll;
+ /* api callbacks */
+ ot->invoke = image_view_zoom_in_invoke;
+ ot->exec = image_view_zoom_in_exec;
+ ot->poll = space_image_main_region_poll;
- /* flags */
- ot->flag = OPTYPE_LOCK_BYPASS;
+ /* flags */
+ ot->flag = OPTYPE_LOCK_BYPASS;
- /* properties */
- prop = RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
- "Location", "Cursor location in screen coordinates", -10.0f, 10.0f);
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ /* properties */
+ prop = RNA_def_float_vector(ot->srna,
+ "location",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Location",
+ "Cursor location in screen coordinates",
+ -10.0f,
+ 10.0f);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
static int image_view_zoom_out_exec(bContext *C, wmOperator *op)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
- float location[2];
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ARegion *ar = CTX_wm_region(C);
+ float location[2];
- RNA_float_get_array(op->ptr, "location", location);
+ RNA_float_get_array(op->ptr, "location", location);
- sima_zoom_set_factor(sima, ar, powf(0.5f, 1.0f / 3.0f), location);
+ sima_zoom_set_factor(sima, ar, powf(0.5f, 1.0f / 3.0f), location);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int image_view_zoom_out_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- float location[2];
+ ARegion *ar = CTX_wm_region(C);
+ float location[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
- RNA_float_set_array(op->ptr, "location", location);
+ UI_view2d_region_to_view(&ar->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);
+ return image_view_zoom_out_exec(C, op);
}
void IMAGE_OT_view_zoom_out(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "View Zoom Out";
- ot->idname = "IMAGE_OT_view_zoom_out";
- ot->description = "Zoom out the image (centered around 2D cursor)";
+ /* identifiers */
+ ot->name = "View Zoom Out";
+ ot->idname = "IMAGE_OT_view_zoom_out";
+ ot->description = "Zoom out the image (centered around 2D cursor)";
- /* api callbacks */
- ot->invoke = image_view_zoom_out_invoke;
- ot->exec = image_view_zoom_out_exec;
- ot->poll = space_image_main_region_poll;
+ /* api callbacks */
+ ot->invoke = image_view_zoom_out_invoke;
+ ot->exec = image_view_zoom_out_exec;
+ ot->poll = space_image_main_region_poll;
- /* flags */
- ot->flag = OPTYPE_LOCK_BYPASS;
+ /* flags */
+ ot->flag = OPTYPE_LOCK_BYPASS;
- /* properties */
- prop = RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
- "Location", "Cursor location in screen coordinates", -10.0f, 10.0f);
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ /* properties */
+ prop = RNA_def_float_vector(ot->srna,
+ "location",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Location",
+ "Cursor location in screen coordinates",
+ -10.0f,
+ 10.0f);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/********************** view zoom ratio operator *********************/
static int image_view_zoom_ratio_exec(bContext *C, wmOperator *op)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ARegion *ar = CTX_wm_region(C);
- sima_zoom_set(sima, ar, RNA_float_get(op->ptr, "ratio"), NULL);
+ sima_zoom_set(sima, ar, RNA_float_get(op->ptr, "ratio"), NULL);
- /* ensure pixel exact locations for draw */
- sima->xof = (int)sima->xof;
- sima->yof = (int)sima->yof;
+ /* ensure pixel exact locations for draw */
+ sima->xof = (int)sima->xof;
+ sima->yof = (int)sima->yof;
- /* XXX notifier? */
+ /* XXX notifier? */
#if 0
- if (image_preview_active(curarea, NULL, NULL)) {
- /* recalculates new preview rect */
- scrarea_do_windraw(curarea);
- image_preview_event(2);
- }
+ if (image_preview_active(curarea, NULL, NULL)) {
+ /* recalculates new preview rect */
+ scrarea_do_windraw(curarea);
+ image_preview_event(2);
+ }
#endif
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void IMAGE_OT_view_zoom_ratio(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Zoom Ratio";
- ot->idname = "IMAGE_OT_view_zoom_ratio";
- ot->description = "Set zoom ratio of the view";
+ /* identifiers */
+ ot->name = "View Zoom Ratio";
+ ot->idname = "IMAGE_OT_view_zoom_ratio";
+ ot->description = "Set zoom ratio of the view";
- /* api callbacks */
- ot->exec = image_view_zoom_ratio_exec;
- ot->poll = space_image_main_region_poll;
+ /* api callbacks */
+ ot->exec = image_view_zoom_ratio_exec;
+ ot->poll = space_image_main_region_poll;
- /* flags */
- ot->flag = OPTYPE_LOCK_BYPASS;
+ /* flags */
+ ot->flag = OPTYPE_LOCK_BYPASS;
- /* properties */
- RNA_def_float(ot->srna, "ratio", 0.0f, -FLT_MAX, FLT_MAX,
- "Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out", -FLT_MAX, FLT_MAX);
+ /* properties */
+ RNA_def_float(ot->srna,
+ "ratio",
+ 0.0f,
+ -FLT_MAX,
+ FLT_MAX,
+ "Ratio",
+ "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out",
+ -FLT_MAX,
+ FLT_MAX);
}
/********************** view border-zoom operator *********************/
static int image_view_zoom_border_exec(bContext *C, wmOperator *op)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
- rctf bounds;
- const bool zoom_in = !RNA_boolean_get(op->ptr, "zoom_out");
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ARegion *ar = 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);
+ WM_operator_properties_border_to_rctf(op, &bounds);
- UI_view2d_region_to_view_rctf(&ar->v2d, &bounds, &bounds);
+ UI_view2d_region_to_view_rctf(&ar->v2d, &bounds, &bounds);
- const struct {
- float xof;
- float yof;
- float zoom;
- } sima_view_prev = {
- .xof = sima->xof,
- .yof = sima->yof,
- .zoom = sima->zoom,
- };
+ const struct {
+ float xof;
+ float yof;
+ float zoom;
+ } sima_view_prev = {
+ .xof = sima->xof,
+ .yof = sima->yof,
+ .zoom = sima->zoom,
+ };
- sima_zoom_set_from_bounds(sima, ar, &bounds);
+ sima_zoom_set_from_bounds(sima, ar, &bounds);
- /* zoom out */
- if (!zoom_in) {
- sima->xof = sima_view_prev.xof + (sima->xof - sima_view_prev.xof);
- sima->yof = sima_view_prev.yof + (sima->yof - sima_view_prev.yof);
- sima->zoom = sima_view_prev.zoom * (sima_view_prev.zoom / sima->zoom);
- }
+ /* zoom out */
+ if (!zoom_in) {
+ sima->xof = sima_view_prev.xof + (sima->xof - sima_view_prev.xof);
+ sima->yof = sima_view_prev.yof + (sima->yof - sima_view_prev.yof);
+ sima->zoom = sima_view_prev.zoom * (sima_view_prev.zoom / sima->zoom);
+ }
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void IMAGE_OT_view_zoom_border(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Zoom to Border";
- ot->description = "Zoom in the view to the nearest item contained in the border";
- ot->idname = "IMAGE_OT_view_zoom_border";
+ /* identifiers */
+ ot->name = "Zoom to Border";
+ ot->description = "Zoom in the view to the nearest item contained in the border";
+ ot->idname = "IMAGE_OT_view_zoom_border";
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = image_view_zoom_border_exec;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = image_view_zoom_border_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
- ot->poll = space_image_main_region_poll;
+ ot->poll = space_image_main_region_poll;
- /* rna */
- WM_operator_properties_gesture_box_zoom(ot);
+ /* rna */
+ WM_operator_properties_gesture_box_zoom(ot);
}
/**************** load/replace/save callbacks ******************/
static void image_filesel(bContext *C, wmOperator *op, const char *path)
{
- RNA_string_set(op->ptr, "filepath", path);
- WM_event_add_fileselect(C, op);
+ RNA_string_set(op->ptr, "filepath", path);
+ WM_event_add_fileselect(C, op);
}
/******************** open image operator ********************/
typedef struct ImageOpenData {
- PropertyPointerRNA pprop;
- ImageUser *iuser;
- ImageFormatData im_format;
+ PropertyPointerRNA pprop;
+ ImageUser *iuser;
+ 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];
+ 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;
+ struct ImageFrame *next, *prev;
+ int framenr;
} ImageFrame;
static void image_open_init(bContext *C, wmOperator *op)
{
- ImageOpenData *iod;
- op->customdata = iod = MEM_callocN(sizeof(ImageOpenData), __func__);
- iod->iuser = CTX_data_pointer_get_type(C, "image_user", &RNA_ImageUser).data;
- UI_context_active_but_prop_get_templateID(C, &iod->pprop.ptr, &iod->pprop.prop);
+ ImageOpenData *iod;
+ op->customdata = iod = MEM_callocN(sizeof(ImageOpenData), __func__);
+ iod->iuser = CTX_data_pointer_get_type(C, "image_user", &RNA_ImageUser).data;
+ UI_context_active_but_prop_get_templateID(C, &iod->pprop.ptr, &iod->pprop.prop);
}
static void image_open_cancel(bContext *UNUSED(C), wmOperator *op)
{
- MEM_freeN(op->customdata);
- op->customdata = NULL;
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
}
/**
@@ -1101,58 +1149,54 @@ static void image_open_cancel(bContext *UNUSED(C), wmOperator *op)
*/
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;
+ 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;
+ 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;
+ if (frame_a->framenr < frame_b->framenr) {
+ return -1;
+ }
+ if (frame_a->framenr > frame_b->framenr) {
+ return 1;
+ }
+ return 0;
}
/**
@@ -1164,673 +1208,724 @@ static int image_cmp_frame(const void *a, const void *b)
*/
static int image_sequence_get_len(ListBase *frames, int *ofs)
{
- ImageFrame *frame;
-
- BLI_listbase_sort(frames, image_cmp_frame);
-
- frame = frames->first;
- if (frame) {
- int frame_curr = frame->framenr;
- (*ofs) = frame_curr;
- while (frame && (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, const char *relbase,
- bool is_relative_path, bool use_multiview, int frame_seq_len)
-{
- bool exists = false;
- Image *ima = NULL;
-
- errno = 0;
- ima = BKE_image_load_exists_ex(bmain, filepath, &exists);
-
- if (!ima) {
- if (op->customdata) {
- MEM_freeN(op->customdata);
- }
- BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s",
- filepath, errno ? strerror(errno) : TIP_("unsupported image format"));
- return NULL;
- }
-
- if (!exists) {
- /* only image path after save, never ibuf */
- if (is_relative_path) {
- BLI_path_rel(ima->name, relbase);
- }
-
- /* handle multiview images */
- if (use_multiview) {
- ImageOpenData *iod = op->customdata;
- ImageFormatData *imf = &iod->im_format;
-
- ima->flag |= IMA_USE_VIEWS;
- ima->views_format = imf->views_format;
- *ima->stereo3d_format = imf->stereo3d_format;
- }
- else {
- ima->flag &= ~IMA_USE_VIEWS;
- BKE_image_free_views(ima);
- }
-
- if ((frame_seq_len > 1) && (ima->source == IMA_SRC_FILE)) {
- ima->source = IMA_SRC_SEQUENCE;
- }
- }
-
- return ima;
+ ImageFrame *frame;
+
+ BLI_listbase_sort(frames, image_cmp_frame);
+
+ frame = frames->first;
+ if (frame) {
+ int frame_curr = frame->framenr;
+ (*ofs) = frame_curr;
+ while (frame && (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,
+ const char *relbase,
+ bool is_relative_path,
+ bool use_multiview,
+ int frame_seq_len)
+{
+ bool exists = false;
+ Image *ima = NULL;
+
+ errno = 0;
+ ima = BKE_image_load_exists_ex(bmain, filepath, &exists);
+
+ if (!ima) {
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ }
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "Cannot read '%s': %s",
+ filepath,
+ errno ? strerror(errno) : TIP_("unsupported image format"));
+ return NULL;
+ }
+
+ if (!exists) {
+ /* only image path after save, never ibuf */
+ if (is_relative_path) {
+ BLI_path_rel(ima->name, relbase);
+ }
+
+ /* handle multiview images */
+ if (use_multiview) {
+ ImageOpenData *iod = op->customdata;
+ ImageFormatData *imf = &iod->im_format;
+
+ ima->flag |= IMA_USE_VIEWS;
+ ima->views_format = imf->views_format;
+ *ima->stereo3d_format = imf->stereo3d_format;
+ }
+ else {
+ ima->flag &= ~IMA_USE_VIEWS;
+ BKE_image_free_views(ima);
+ }
+
+ if ((frame_seq_len > 1) && (ima->source == IMA_SRC_FILE)) {
+ ima->source = IMA_SRC_SEQUENCE;
+ }
+ }
+
+ return ima;
}
-
static int image_open_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- ScrArea *sa = 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;
-
- const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
- const bool use_multiview = RNA_boolean_get(op->ptr, "use_multiview");
-
- if (!op->customdata) {
- 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;
- int frame_range_seq_len = image_sequence_get_len(&frame_range->frames, &frame_range_ofs);
- BLI_freelistN(&frame_range->frames);
-
- char filepath_range[FILE_MAX];
- BLI_strncpy(filepath_range, frame_range->filepath, sizeof(filepath_range));
-
- if (was_relative) {
- BLI_path_rel(filepath_range, BKE_main_blendfile_path(bmain));
- }
-
- Image *ima_range = image_open_single(
- bmain, op, filepath_range, BKE_main_blendfile_path(bmain),
- is_relative_path, use_multiview, frame_range_seq_len);
-
- /* 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_freelistN(&frame_ranges_all);
- }
- else {
- /* for drag & drop etc. */
- ima = image_open_single(
- bmain, op, filepath, BKE_main_blendfile_path(bmain),
- is_relative_path, use_multiview, 1);
- }
-
- if (ima == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- /* hook into UI */
- iod = op->customdata;
-
- if (iod->pprop.prop) {
- /* when creating new ID blocks, use is already 1, but RNA
- * pointer use also increases user, so this compensates it */
- id_us_min(&ima->id);
-
- PointerRNA imaptr;
- RNA_id_pointer_create(&ima->id, &imaptr);
- RNA_property_pointer_set(&iod->pprop.ptr, iod->pprop.prop, imaptr);
- RNA_property_update(C, &iod->pprop.ptr, iod->pprop.prop);
- }
-
- if (iod->iuser) {
- iuser = iod->iuser;
- }
- else if (sa && sa->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = sa->spacedata.first;
- ED_space_image_set(bmain, sima, obedit, ima, false);
- iuser = &sima->iuser;
- }
- else {
- Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
- if (tex && tex->type == TEX_IMAGE) {
- iuser = &tex->iuser;
- }
-
- 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) {
- if (bgpic->ima == ima) {
- iuser = &bgpic->iuser;
- break;
- }
- }
- }
- }
- }
-
- /* initialize because of new image */
- if (iuser) {
- iuser->frames = frame_seq_len;
- iuser->sfra = 1;
- iuser->framenr = 1;
- if (ima->source == IMA_SRC_MOVIE) {
- iuser->offset = 0;
- }
- else {
- iuser->offset = frame_ofs - 1;
- }
- iuser->scene = scene;
- BKE_image_init_imageuser(ima, iuser);
- }
-
- /* XXX unpackImage frees image buffers */
- ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
-
- BKE_image_signal(bmain, ima, iuser, IMA_SIGNAL_RELOAD);
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
-
- MEM_freeN(op->customdata);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ ScrArea *sa = 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;
+
+ const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
+ const bool use_multiview = RNA_boolean_get(op->ptr, "use_multiview");
+
+ if (!op->customdata) {
+ 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;
+ int frame_range_seq_len = image_sequence_get_len(&frame_range->frames, &frame_range_ofs);
+ BLI_freelistN(&frame_range->frames);
+
+ char filepath_range[FILE_MAX];
+ BLI_strncpy(filepath_range, frame_range->filepath, sizeof(filepath_range));
+
+ if (was_relative) {
+ BLI_path_rel(filepath_range, BKE_main_blendfile_path(bmain));
+ }
+
+ Image *ima_range = image_open_single(bmain,
+ op,
+ filepath_range,
+ BKE_main_blendfile_path(bmain),
+ is_relative_path,
+ use_multiview,
+ frame_range_seq_len);
+
+ /* 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_freelistN(&frame_ranges_all);
+ }
+ else {
+ /* for drag & drop etc. */
+ ima = image_open_single(
+ bmain, op, filepath, BKE_main_blendfile_path(bmain), is_relative_path, use_multiview, 1);
+ }
+
+ if (ima == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* hook into UI */
+ iod = op->customdata;
+
+ if (iod->pprop.prop) {
+ /* when creating new ID blocks, use is already 1, but RNA
+ * pointer use also increases user, so this compensates it */
+ id_us_min(&ima->id);
+
+ PointerRNA imaptr;
+ RNA_id_pointer_create(&ima->id, &imaptr);
+ RNA_property_pointer_set(&iod->pprop.ptr, iod->pprop.prop, imaptr);
+ RNA_property_update(C, &iod->pprop.ptr, iod->pprop.prop);
+ }
+
+ if (iod->iuser) {
+ iuser = iod->iuser;
+ }
+ else if (sa && sa->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = sa->spacedata.first;
+ ED_space_image_set(bmain, sima, obedit, ima, false);
+ iuser = &sima->iuser;
+ }
+ else {
+ Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
+ if (tex && tex->type == TEX_IMAGE) {
+ iuser = &tex->iuser;
+ }
+
+ 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) {
+ if (bgpic->ima == ima) {
+ iuser = &bgpic->iuser;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* initialize because of new image */
+ if (iuser) {
+ iuser->frames = frame_seq_len;
+ iuser->sfra = 1;
+ iuser->framenr = 1;
+ if (ima->source == IMA_SRC_MOVIE) {
+ iuser->offset = 0;
+ }
+ else {
+ iuser->offset = frame_ofs - 1;
+ }
+ iuser->scene = scene;
+ BKE_image_init_imageuser(ima, iuser);
+ }
+
+ /* XXX unpackImage frees image buffers */
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
+
+ BKE_image_signal(bmain, ima, iuser, IMA_SIGNAL_RELOAD);
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+
+ MEM_freeN(op->customdata);
+
+ return OPERATOR_FINISHED;
}
static int image_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- SpaceImage *sima = CTX_wm_space_image(C); /* XXX other space types can call */
- const char *path = U.textudir;
- Image *ima = NULL;
- Scene *scene = CTX_data_scene(C);
+ SpaceImage *sima = CTX_wm_space_image(C); /* XXX other space types can call */
+ const char *path = U.textudir;
+ Image *ima = NULL;
+ Scene *scene = CTX_data_scene(C);
- if (sima) {
- ima = sima->image;
- }
+ if (sima) {
+ ima = sima->image;
+ }
- if (ima == NULL) {
- Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
- if (tex && tex->type == TEX_IMAGE) {
- ima = tex->ima;
- }
- }
+ if (ima == NULL) {
+ Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
+ if (tex && tex->type == TEX_IMAGE) {
+ ima = tex->ima;
+ }
+ }
- if (ima == NULL) {
- PointerRNA ptr;
- PropertyRNA *prop;
+ if (ima == NULL) {
+ PointerRNA ptr;
+ PropertyRNA *prop;
- /* hook into UI */
- UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
+ /* hook into UI */
+ UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
- if (prop) {
- PointerRNA oldptr;
- Image *oldima;
+ if (prop) {
+ PointerRNA oldptr;
+ Image *oldima;
- oldptr = RNA_property_pointer_get(&ptr, prop);
- oldima = (Image *)oldptr.id.data;
- /* unlikely to fail but better avoid strange crash */
- if (oldima && GS(oldima->id.name) == ID_IM) {
- ima = oldima;
- }
- }
- }
+ oldptr = RNA_property_pointer_get(&ptr, prop);
+ oldima = (Image *)oldptr.id.data;
+ /* unlikely to fail but better avoid strange crash */
+ if (oldima && GS(oldima->id.name) == ID_IM) {
+ ima = oldima;
+ }
+ }
+ }
- if (ima) {
- path = ima->name;
- }
+ if (ima) {
+ path = ima->name;
+ }
- if (RNA_struct_property_is_set(op->ptr, "filepath")) {
- return image_open_exec(C, op);
- }
+ if (RNA_struct_property_is_set(op->ptr, "filepath")) {
+ return image_open_exec(C, op);
+ }
- image_open_init(C, op);
+ image_open_init(C, op);
- /* show multiview save options only if scene has multiviews */
- PropertyRNA *prop;
- prop = RNA_struct_find_property(op->ptr, "show_multiview");
- RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0);
+ /* show multiview save options only if scene has multiviews */
+ PropertyRNA *prop;
+ prop = RNA_struct_find_property(op->ptr, "show_multiview");
+ RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0);
- image_filesel(C, op, path);
+ image_filesel(C, op, path);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
-static bool image_open_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop, void *UNUSED(user_data))
+static bool image_open_draw_check_prop(PointerRNA *UNUSED(ptr),
+ PropertyRNA *prop,
+ void *UNUSED(user_data))
{
- const char *prop_id = RNA_property_identifier(prop);
+ const char *prop_id = RNA_property_identifier(prop);
- return !(STREQ(prop_id, "filepath") ||
- STREQ(prop_id, "directory") ||
- STREQ(prop_id, "filename")
- );
+ return !(STREQ(prop_id, "filepath") || STREQ(prop_id, "directory") ||
+ STREQ(prop_id, "filename"));
}
static void image_open_draw(bContext *UNUSED(C), wmOperator *op)
{
- uiLayout *layout = op->layout;
- ImageOpenData *iod = op->customdata;
- ImageFormatData *imf = &iod->im_format;
- PointerRNA imf_ptr, ptr;
+ uiLayout *layout = op->layout;
+ ImageOpenData *iod = op->customdata;
+ ImageFormatData *imf = &iod->im_format;
+ PointerRNA imf_ptr, ptr;
- /* main draw call */
- RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
- uiDefAutoButsRNA(layout, &ptr, image_open_draw_check_prop, NULL, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
+ /* main draw call */
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+ uiDefAutoButsRNA(
+ layout, &ptr, image_open_draw_check_prop, NULL, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
- /* image template */
- RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr);
+ /* image template */
+ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr);
- /* multiview template */
- if (RNA_boolean_get(op->ptr, "show_multiview")) {
- uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr);
- }
+ /* multiview template */
+ if (RNA_boolean_get(op->ptr, "show_multiview")) {
+ uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr);
+ }
}
/* called by other space types too */
void IMAGE_OT_open(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Open Image";
- ot->description = "Open image";
- ot->idname = "IMAGE_OT_open";
-
- /* api callbacks */
- ot->exec = image_open_exec;
- ot->invoke = image_open_invoke;
- ot->cancel = image_open_cancel;
- ot->ui = image_open_draw;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, 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 images (based on file names)");
+ /* identifiers */
+ ot->name = "Open Image";
+ ot->description = "Open image";
+ ot->idname = "IMAGE_OT_open";
+
+ /* api callbacks */
+ ot->exec = image_open_exec;
+ ot->invoke = image_open_invoke;
+ ot->cancel = image_open_cancel;
+ ot->ui = image_open_draw;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE,
+ 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 images (based on file names)");
}
/******************** Match movie length operator ********************/
static int image_match_len_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Image *ima = CTX_data_pointer_get_type(C, "edit_image", &RNA_Image).data;
- ImageUser *iuser = CTX_data_pointer_get_type(C, "edit_image_user", &RNA_ImageUser).data;
-
- if (!ima || !iuser) {
- /* Try to get a Texture, or a SpaceImage from context... */
- SpaceImage *sima = CTX_wm_space_image(C);
- Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
- if (tex && tex->type == TEX_IMAGE) {
- ima = tex->ima;
- iuser = &tex->iuser;
- }
- else if (sima) {
- ima = sima->image;
- iuser = &sima->iuser;
- }
-
- }
-
- if (!ima || !iuser || !BKE_image_has_anim(ima)) {
- return OPERATOR_CANCELLED;
- }
-
- struct anim *anim = ((ImageAnim *)ima->anims.first)->anim;
- if (!anim) {
- return OPERATOR_CANCELLED;
- }
- iuser->frames = IMB_anim_get_duration(anim, IMB_TC_RECORD_RUN);
- BKE_image_user_frame_calc(iuser, scene->r.cfra);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Image *ima = CTX_data_pointer_get_type(C, "edit_image", &RNA_Image).data;
+ ImageUser *iuser = CTX_data_pointer_get_type(C, "edit_image_user", &RNA_ImageUser).data;
+
+ if (!ima || !iuser) {
+ /* Try to get a Texture, or a SpaceImage from context... */
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
+ if (tex && tex->type == TEX_IMAGE) {
+ ima = tex->ima;
+ iuser = &tex->iuser;
+ }
+ else if (sima) {
+ ima = sima->image;
+ iuser = &sima->iuser;
+ }
+ }
+
+ if (!ima || !iuser || !BKE_image_has_anim(ima)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ struct anim *anim = ((ImageAnim *)ima->anims.first)->anim;
+ if (!anim) {
+ return OPERATOR_CANCELLED;
+ }
+ iuser->frames = IMB_anim_get_duration(anim, IMB_TC_RECORD_RUN);
+ BKE_image_user_frame_calc(iuser, scene->r.cfra);
+
+ return OPERATOR_FINISHED;
}
/* called by other space types too */
void IMAGE_OT_match_movie_length(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Match Movie Length";
- ot->description = "Set image's user's length to the one of this video";
- ot->idname = "IMAGE_OT_match_movie_length";
+ /* identifiers */
+ ot->name = "Match Movie Length";
+ ot->description = "Set image's user's length to the one of this video";
+ ot->idname = "IMAGE_OT_match_movie_length";
- /* api callbacks */
- ot->exec = image_match_len_exec;
+ /* api callbacks */
+ ot->exec = image_match_len_exec;
- /* flags */
- /* Don't think we need undo for that. */
- ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL/* | OPTYPE_UNDO */;
+ /* flags */
+ /* Don't think we need undo for that. */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL /* | OPTYPE_UNDO */;
}
/******************** replace image operator ********************/
static int image_replace_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- char str[FILE_MAX];
+ Main *bmain = CTX_data_main(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ char str[FILE_MAX];
- if (!sima->image) {
- return OPERATOR_CANCELLED;
- }
+ if (!sima->image) {
+ return OPERATOR_CANCELLED;
+ }
- RNA_string_get(op->ptr, "filepath", str);
+ RNA_string_get(op->ptr, "filepath", str);
- /* we cant do much if the str is longer then FILE_MAX :/ */
- BLI_strncpy(sima->image->name, str, sizeof(sima->image->name));
+ /* we cant do much if the str is longer then FILE_MAX :/ */
+ BLI_strncpy(sima->image->name, str, sizeof(sima->image->name));
- if (sima->image->source == IMA_SRC_GENERATED) {
- sima->image->source = IMA_SRC_FILE;
- BKE_image_signal(bmain, sima->image, &sima->iuser, IMA_SIGNAL_SRC_CHANGE);
- }
+ if (sima->image->source == IMA_SRC_GENERATED) {
+ sima->image->source = IMA_SRC_FILE;
+ BKE_image_signal(bmain, sima->image, &sima->iuser, IMA_SIGNAL_SRC_CHANGE);
+ }
- if (BLI_path_extension_check_array(str, imb_ext_movie)) {
- sima->image->source = IMA_SRC_MOVIE;
- }
- else {
- sima->image->source = IMA_SRC_FILE;
- }
+ if (BLI_path_extension_check_array(str, imb_ext_movie)) {
+ sima->image->source = IMA_SRC_MOVIE;
+ }
+ else {
+ sima->image->source = IMA_SRC_FILE;
+ }
- /* XXX unpackImage frees image buffers */
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ /* XXX unpackImage frees image buffers */
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
- BKE_icon_changed(BKE_icon_id_ensure(&sima->image->id));
- BKE_image_signal(bmain, sima->image, &sima->iuser, IMA_SIGNAL_RELOAD);
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, sima->image);
+ BKE_icon_changed(BKE_icon_id_ensure(&sima->image->id));
+ BKE_image_signal(bmain, sima->image, &sima->iuser, IMA_SIGNAL_RELOAD);
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, sima->image);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int image_replace_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- SpaceImage *sima = CTX_wm_space_image(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
- if (!sima->image) {
- return OPERATOR_CANCELLED;
- }
+ if (!sima->image) {
+ return OPERATOR_CANCELLED;
+ }
- if (RNA_struct_property_is_set(op->ptr, "filepath")) {
- return image_replace_exec(C, op);
- }
+ if (RNA_struct_property_is_set(op->ptr, "filepath")) {
+ return image_replace_exec(C, op);
+ }
- if (!RNA_struct_property_is_set(op->ptr, "relative_path")) {
- RNA_boolean_set(op->ptr, "relative_path", BLI_path_is_rel(sima->image->name));
- }
+ if (!RNA_struct_property_is_set(op->ptr, "relative_path")) {
+ RNA_boolean_set(op->ptr, "relative_path", BLI_path_is_rel(sima->image->name));
+ }
- image_filesel(C, op, sima->image->name);
+ image_filesel(C, op, sima->image->name);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void IMAGE_OT_replace(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Replace Image";
- ot->idname = "IMAGE_OT_replace";
- ot->description = "Replace current image by another one from disk";
+ /* identifiers */
+ ot->name = "Replace Image";
+ ot->idname = "IMAGE_OT_replace";
+ ot->description = "Replace current image by another one from disk";
- /* api callbacks */
- ot->exec = image_replace_exec;
- ot->invoke = image_replace_invoke;
- ot->poll = image_not_packed_poll;
+ /* api callbacks */
+ ot->exec = image_replace_exec;
+ ot->invoke = image_replace_invoke;
+ ot->poll = image_not_packed_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+ /* properties */
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
}
/******************** save image as operator ********************/
typedef struct {
- /* matching scene->r settings */
- //short planes, imtype, subimtype, quality;
- ImageFormatData im_format;
- char filepath[FILE_MAX]; /* keep absolute */
+ /* matching scene->r settings */
+ //short planes, imtype, subimtype, quality;
+ ImageFormatData im_format;
+ char filepath[FILE_MAX]; /* keep absolute */
} SaveImageOptions;
static void save_image_options_defaults(SaveImageOptions *simopts)
{
- BKE_imformat_defaults(&simopts->im_format);
- simopts->filepath[0] = '\0';
+ BKE_imformat_defaults(&simopts->im_format);
+ simopts->filepath[0] = '\0';
}
static char imtype_best_depth(ImBuf *ibuf, const char imtype)
{
- const char depth_ok = BKE_imtype_valid_depths(imtype);
-
- if (ibuf->rect_float) {
- if (depth_ok & R_IMF_CHAN_DEPTH_32) { return R_IMF_CHAN_DEPTH_32; }
- if (depth_ok & R_IMF_CHAN_DEPTH_24) { return R_IMF_CHAN_DEPTH_24; }
- if (depth_ok & R_IMF_CHAN_DEPTH_16) { return R_IMF_CHAN_DEPTH_16; }
- if (depth_ok & R_IMF_CHAN_DEPTH_12) { return R_IMF_CHAN_DEPTH_12; }
- return R_IMF_CHAN_DEPTH_8;
- }
- else {
- if (depth_ok & R_IMF_CHAN_DEPTH_8) { return R_IMF_CHAN_DEPTH_8; }
- if (depth_ok & R_IMF_CHAN_DEPTH_12) { return R_IMF_CHAN_DEPTH_12; }
- if (depth_ok & R_IMF_CHAN_DEPTH_16) { return R_IMF_CHAN_DEPTH_16; }
- if (depth_ok & R_IMF_CHAN_DEPTH_24) { return R_IMF_CHAN_DEPTH_24; }
- if (depth_ok & R_IMF_CHAN_DEPTH_32) { return R_IMF_CHAN_DEPTH_32; }
- return R_IMF_CHAN_DEPTH_8; /* fallback, should not get here */
- }
-}
-
-static int save_image_options_init(Main *bmain, SaveImageOptions *simopts, SpaceImage *sima, Scene *scene,
- const bool guess_path, const bool save_as_render)
-{
- void *lock;
- ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
-
- if (ibuf) {
- Image *ima = sima->image;
- bool is_depth_set = false;
-
- if (ELEM(ima->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE)) {
- /* imtype */
- simopts->im_format = scene->r.im_format;
- is_depth_set = true;
- if (!BKE_image_is_multiview(ima)) {
- /* In case multiview is disabled,
- * render settings would be invalid for render result in this area. */
- simopts->im_format.stereo3d_format = *ima->stereo3d_format;
- simopts->im_format.views_format = ima->views_format;
- }
- }
- else {
- if (ima->source == IMA_SRC_GENERATED) {
- simopts->im_format.imtype = R_IMF_IMTYPE_PNG;
- simopts->im_format.compress = ibuf->foptions.quality;
- simopts->im_format.planes = ibuf->planes;
- }
- else {
- BKE_imbuf_to_image_format(&simopts->im_format, ibuf);
- }
-
- /* use the multiview image settings as the default */
- simopts->im_format.stereo3d_format = *ima->stereo3d_format;
- simopts->im_format.views_format = ima->views_format;
- }
-
- ///* XXX - this is lame, we need to make these available too! */
- //simopts->subimtype = scene->r.subimtype;
-
- BLI_strncpy(simopts->filepath, ibuf->name, sizeof(simopts->filepath));
-
- /* sanitize all settings */
-
- /* unlikely but just in case */
- if (ELEM(simopts->im_format.planes, R_IMF_PLANES_BW, R_IMF_PLANES_RGB, R_IMF_PLANES_RGBA) == 0) {
- simopts->im_format.planes = R_IMF_PLANES_RGBA;
- }
-
- /* depth, account for float buffer and format support */
- if (is_depth_set == false) {
- simopts->im_format.depth = imtype_best_depth(ibuf, simopts->im_format.imtype);
- }
-
- /* some formats don't use quality so fallback to scenes quality */
- if (simopts->im_format.quality == 0) {
- simopts->im_format.quality = scene->r.im_format.quality;
- }
-
- /* check for empty path */
- if (guess_path && simopts->filepath[0] == 0) {
- const bool is_prev_save = !STREQ(G.ima, "//");
- if (save_as_render) {
- if (is_prev_save) {
- BLI_strncpy(simopts->filepath, G.ima, sizeof(simopts->filepath));
- }
- else {
- BLI_strncpy(simopts->filepath, "//untitled", sizeof(simopts->filepath));
- BLI_path_abs(simopts->filepath, BKE_main_blendfile_path(bmain));
- }
- }
- else {
- BLI_snprintf(simopts->filepath, sizeof(simopts->filepath), "//%s", ima->id.name + 2);
- BLI_path_abs(simopts->filepath, is_prev_save ? G.ima : BKE_main_blendfile_path(bmain));
- }
- }
-
- /* color management */
- BKE_color_managed_display_settings_copy(&simopts->im_format.display_settings, &scene->display_settings);
- BKE_color_managed_view_settings_copy(&simopts->im_format.view_settings, &scene->view_settings);
- }
-
- ED_space_image_release_buffer(sima, ibuf, lock);
-
- return (ibuf != NULL);
+ const char depth_ok = BKE_imtype_valid_depths(imtype);
+
+ if (ibuf->rect_float) {
+ if (depth_ok & R_IMF_CHAN_DEPTH_32) {
+ return R_IMF_CHAN_DEPTH_32;
+ }
+ if (depth_ok & R_IMF_CHAN_DEPTH_24) {
+ return R_IMF_CHAN_DEPTH_24;
+ }
+ if (depth_ok & R_IMF_CHAN_DEPTH_16) {
+ return R_IMF_CHAN_DEPTH_16;
+ }
+ if (depth_ok & R_IMF_CHAN_DEPTH_12) {
+ return R_IMF_CHAN_DEPTH_12;
+ }
+ return R_IMF_CHAN_DEPTH_8;
+ }
+ else {
+ if (depth_ok & R_IMF_CHAN_DEPTH_8) {
+ return R_IMF_CHAN_DEPTH_8;
+ }
+ if (depth_ok & R_IMF_CHAN_DEPTH_12) {
+ return R_IMF_CHAN_DEPTH_12;
+ }
+ if (depth_ok & R_IMF_CHAN_DEPTH_16) {
+ return R_IMF_CHAN_DEPTH_16;
+ }
+ if (depth_ok & R_IMF_CHAN_DEPTH_24) {
+ return R_IMF_CHAN_DEPTH_24;
+ }
+ if (depth_ok & R_IMF_CHAN_DEPTH_32) {
+ return R_IMF_CHAN_DEPTH_32;
+ }
+ return R_IMF_CHAN_DEPTH_8; /* fallback, should not get here */
+ }
+}
+
+static int save_image_options_init(Main *bmain,
+ SaveImageOptions *simopts,
+ SpaceImage *sima,
+ Scene *scene,
+ const bool guess_path,
+ const bool save_as_render)
+{
+ void *lock;
+ ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
+
+ if (ibuf) {
+ Image *ima = sima->image;
+ bool is_depth_set = false;
+
+ if (ELEM(ima->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE)) {
+ /* imtype */
+ simopts->im_format = scene->r.im_format;
+ is_depth_set = true;
+ if (!BKE_image_is_multiview(ima)) {
+ /* In case multiview is disabled,
+ * render settings would be invalid for render result in this area. */
+ simopts->im_format.stereo3d_format = *ima->stereo3d_format;
+ simopts->im_format.views_format = ima->views_format;
+ }
+ }
+ else {
+ if (ima->source == IMA_SRC_GENERATED) {
+ simopts->im_format.imtype = R_IMF_IMTYPE_PNG;
+ simopts->im_format.compress = ibuf->foptions.quality;
+ simopts->im_format.planes = ibuf->planes;
+ }
+ else {
+ BKE_imbuf_to_image_format(&simopts->im_format, ibuf);
+ }
+
+ /* use the multiview image settings as the default */
+ simopts->im_format.stereo3d_format = *ima->stereo3d_format;
+ simopts->im_format.views_format = ima->views_format;
+ }
+
+ ///* XXX - this is lame, we need to make these available too! */
+ //simopts->subimtype = scene->r.subimtype;
+
+ BLI_strncpy(simopts->filepath, ibuf->name, sizeof(simopts->filepath));
+
+ /* sanitize all settings */
+
+ /* unlikely but just in case */
+ if (ELEM(simopts->im_format.planes, R_IMF_PLANES_BW, R_IMF_PLANES_RGB, R_IMF_PLANES_RGBA) ==
+ 0) {
+ simopts->im_format.planes = R_IMF_PLANES_RGBA;
+ }
+
+ /* depth, account for float buffer and format support */
+ if (is_depth_set == false) {
+ simopts->im_format.depth = imtype_best_depth(ibuf, simopts->im_format.imtype);
+ }
+
+ /* some formats don't use quality so fallback to scenes quality */
+ if (simopts->im_format.quality == 0) {
+ simopts->im_format.quality = scene->r.im_format.quality;
+ }
+
+ /* check for empty path */
+ if (guess_path && simopts->filepath[0] == 0) {
+ const bool is_prev_save = !STREQ(G.ima, "//");
+ if (save_as_render) {
+ if (is_prev_save) {
+ BLI_strncpy(simopts->filepath, G.ima, sizeof(simopts->filepath));
+ }
+ else {
+ BLI_strncpy(simopts->filepath, "//untitled", sizeof(simopts->filepath));
+ BLI_path_abs(simopts->filepath, BKE_main_blendfile_path(bmain));
+ }
+ }
+ else {
+ BLI_snprintf(simopts->filepath, sizeof(simopts->filepath), "//%s", ima->id.name + 2);
+ BLI_path_abs(simopts->filepath, is_prev_save ? G.ima : BKE_main_blendfile_path(bmain));
+ }
+ }
+
+ /* color management */
+ BKE_color_managed_display_settings_copy(&simopts->im_format.display_settings,
+ &scene->display_settings);
+ BKE_color_managed_view_settings_copy(&simopts->im_format.view_settings, &scene->view_settings);
+ }
+
+ ED_space_image_release_buffer(sima, ibuf, lock);
+
+ return (ibuf != NULL);
}
static void save_image_options_from_op(Main *bmain, SaveImageOptions *simopts, wmOperator *op)
{
- if (op->customdata) {
- BKE_color_managed_view_settings_free(&simopts->im_format.view_settings);
+ if (op->customdata) {
+ BKE_color_managed_view_settings_free(&simopts->im_format.view_settings);
- simopts->im_format = *(ImageFormatData *)op->customdata;
- }
+ simopts->im_format = *(ImageFormatData *)op->customdata;
+ }
- if (RNA_struct_property_is_set(op->ptr, "filepath")) {
- RNA_string_get(op->ptr, "filepath", simopts->filepath);
- BLI_path_abs(simopts->filepath, BKE_main_blendfile_path(bmain));
- }
+ if (RNA_struct_property_is_set(op->ptr, "filepath")) {
+ RNA_string_get(op->ptr, "filepath", simopts->filepath);
+ BLI_path_abs(simopts->filepath, BKE_main_blendfile_path(bmain));
+ }
}
static void save_image_options_to_op(SaveImageOptions *simopts, wmOperator *op)
{
- if (op->customdata) {
- BKE_color_managed_view_settings_free(&((ImageFormatData *)op->customdata)->view_settings);
-
- *(ImageFormatData *)op->customdata = simopts->im_format;
- }
-
- RNA_string_set(op->ptr, "filepath", simopts->filepath);
-}
-
-static void save_image_post(
- Main *bmain, wmOperator *op, ImBuf *ibuf, Image *ima, int ok, int save_copy,
- const char *relbase, int relative, int do_newpath, const char *filepath)
-{
- if (ok) {
- if (!save_copy) {
- ColorManagedColorspaceSettings old_colorspace_settings;
-
- if (do_newpath) {
- BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name));
- BLI_strncpy(ima->name, filepath, sizeof(ima->name));
- }
-
- ibuf->userflags &= ~IB_BITMAPDIRTY;
-
- /* change type? */
- if (ima->type == IMA_TYPE_R_RESULT) {
- ima->type = IMA_TYPE_IMAGE;
-
- /* workaround to ensure the render result buffer is no longer used
- * by this image, otherwise can crash when a new render result is
- * created. */
- if (ibuf->rect && !(ibuf->mall & IB_rect)) {
- imb_freerectImBuf(ibuf);
- }
- if (ibuf->rect_float && !(ibuf->mall & IB_rectfloat)) {
- imb_freerectfloatImBuf(ibuf);
- }
- if (ibuf->zbuf && !(ibuf->mall & IB_zbuf)) {
- IMB_freezbufImBuf(ibuf);
- }
- if (ibuf->zbuf_float && !(ibuf->mall & IB_zbuffloat)) {
- IMB_freezbuffloatImBuf(ibuf);
- }
- }
- if (ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER)) {
- ima->source = IMA_SRC_FILE;
- ima->type = IMA_TYPE_IMAGE;
- }
-
- /* only image path, never ibuf */
- if (relative) {
- BLI_path_rel(ima->name, relbase); /* only after saving */
- }
-
- BKE_color_managed_colorspace_settings_copy(&old_colorspace_settings,
- &ima->colorspace_settings);
- IMB_colormanagement_colorspace_from_ibuf_ftype(&ima->colorspace_settings, ibuf);
- if (!BKE_color_managed_colorspace_settings_equals(&old_colorspace_settings,
- &ima->colorspace_settings))
- {
- BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_COLORMANAGE);
- }
- }
- }
- else {
- BKE_reportf(op->reports, RPT_ERROR, "Could not write image: %s", strerror(errno));
- }
+ if (op->customdata) {
+ BKE_color_managed_view_settings_free(&((ImageFormatData *)op->customdata)->view_settings);
+
+ *(ImageFormatData *)op->customdata = simopts->im_format;
+ }
+
+ RNA_string_set(op->ptr, "filepath", simopts->filepath);
+}
+
+static void save_image_post(Main *bmain,
+ wmOperator *op,
+ ImBuf *ibuf,
+ Image *ima,
+ int ok,
+ int save_copy,
+ const char *relbase,
+ int relative,
+ int do_newpath,
+ const char *filepath)
+{
+ if (ok) {
+ if (!save_copy) {
+ ColorManagedColorspaceSettings old_colorspace_settings;
+
+ if (do_newpath) {
+ BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name));
+ BLI_strncpy(ima->name, filepath, sizeof(ima->name));
+ }
+
+ ibuf->userflags &= ~IB_BITMAPDIRTY;
+
+ /* change type? */
+ if (ima->type == IMA_TYPE_R_RESULT) {
+ ima->type = IMA_TYPE_IMAGE;
+
+ /* workaround to ensure the render result buffer is no longer used
+ * by this image, otherwise can crash when a new render result is
+ * created. */
+ if (ibuf->rect && !(ibuf->mall & IB_rect)) {
+ imb_freerectImBuf(ibuf);
+ }
+ if (ibuf->rect_float && !(ibuf->mall & IB_rectfloat)) {
+ imb_freerectfloatImBuf(ibuf);
+ }
+ if (ibuf->zbuf && !(ibuf->mall & IB_zbuf)) {
+ IMB_freezbufImBuf(ibuf);
+ }
+ if (ibuf->zbuf_float && !(ibuf->mall & IB_zbuffloat)) {
+ IMB_freezbuffloatImBuf(ibuf);
+ }
+ }
+ if (ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER)) {
+ ima->source = IMA_SRC_FILE;
+ ima->type = IMA_TYPE_IMAGE;
+ }
+
+ /* only image path, never ibuf */
+ if (relative) {
+ BLI_path_rel(ima->name, relbase); /* only after saving */
+ }
+
+ BKE_color_managed_colorspace_settings_copy(&old_colorspace_settings,
+ &ima->colorspace_settings);
+ IMB_colormanagement_colorspace_from_ibuf_ftype(&ima->colorspace_settings, ibuf);
+ if (!BKE_color_managed_colorspace_settings_equals(&old_colorspace_settings,
+ &ima->colorspace_settings)) {
+ BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_COLORMANAGE);
+ }
+ }
+ }
+ else {
+ BKE_reportf(op->reports, RPT_ERROR, "Could not write image: %s", strerror(errno));
+ }
}
static void save_imbuf_post(ImBuf *ibuf, ImBuf *colormanaged_ibuf)
{
- if (colormanaged_ibuf != ibuf) {
- /* This guys might be modified by image buffer write functions,
- * need to copy them back from color managed image buffer to an
- * original one, so file type of image is being properly updated.
- */
- ibuf->ftype = colormanaged_ibuf->ftype;
- ibuf->foptions = colormanaged_ibuf->foptions;
- ibuf->planes = colormanaged_ibuf->planes;
+ if (colormanaged_ibuf != ibuf) {
+ /* This guys might be modified by image buffer write functions,
+ * need to copy them back from color managed image buffer to an
+ * original one, so file type of image is being properly updated.
+ */
+ ibuf->ftype = colormanaged_ibuf->ftype;
+ ibuf->foptions = colormanaged_ibuf->foptions;
+ ibuf->planes = colormanaged_ibuf->planes;
- IMB_freeImBuf(colormanaged_ibuf);
- }
+ IMB_freeImBuf(colormanaged_ibuf);
+ }
}
/**
@@ -1838,780 +1933,830 @@ static void save_imbuf_post(ImBuf *ibuf, ImBuf *colormanaged_ibuf)
* \note ``ima->name`` and ``ibuf->name`` should end up the same.
* \note for multiview the first ``ibuf`` is important to get the settings.
*/
-static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveImageOptions *simopts, bool do_newpath)
-{
- Main *bmain = CTX_data_main(C);
- Image *ima = ED_space_image(sima);
- void *lock;
- ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
- Scene *scene;
- RenderResult *rr = NULL;
- bool ok = false;
-
- WM_cursor_wait(1);
-
- if (ibuf) {
- ImBuf *colormanaged_ibuf = NULL;
- const char *relbase = ID_BLEND_PATH(CTX_data_main(C), &ima->id);
- const bool relative = (RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path"));
- const bool save_copy = (RNA_struct_find_property(op->ptr, "copy") && RNA_boolean_get(op->ptr, "copy"));
- const bool save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") && RNA_boolean_get(op->ptr, "save_as_render"));
- ImageFormatData *imf = &simopts->im_format;
-
- /* old global to ensure a 2nd save goes to same dir */
- BLI_strncpy(G.ima, simopts->filepath, sizeof(G.ima));
-
- if (ima->type == IMA_TYPE_R_RESULT) {
- /* enforce user setting for RGB or RGBA, but skip BW */
- if (simopts->im_format.planes == R_IMF_PLANES_RGBA) {
- ibuf->planes = R_IMF_PLANES_RGBA;
- }
- else if (simopts->im_format.planes == R_IMF_PLANES_RGB) {
- ibuf->planes = R_IMF_PLANES_RGB;
- }
- }
- else {
- /* TODO, better solution, if a 24bit image is painted onto it may contain alpha */
- if ((simopts->im_format.planes == R_IMF_PLANES_RGBA) &&
- /* it has been painted onto */
- (ibuf->userflags & IB_BITMAPDIRTY))
- {
- /* checks each pixel, not ideal */
- ibuf->planes = BKE_imbuf_alpha_test(ibuf) ? R_IMF_PLANES_RGBA : R_IMF_PLANES_RGB;
- }
- }
-
- /* we need renderresult for exr and rendered multiview */
- scene = CTX_data_scene(C);
- rr = BKE_image_acquire_renderresult(scene, ima);
- bool is_mono = rr ? BLI_listbase_count_at_most(&rr->views, 2) < 2 : BLI_listbase_count_at_most(&ima->views, 2) < 2;
- bool is_exr_rr = rr && ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER) && RE_HasFloatPixels(rr);
- bool is_multilayer = is_exr_rr && (imf->imtype == R_IMF_IMTYPE_MULTILAYER);
- int layer = (is_multilayer) ? -1 : sima->iuser.layer;
-
- /* error handling */
- if (!rr) {
- if (imf->imtype == R_IMF_IMTYPE_MULTILAYER) {
- BKE_report(op->reports, RPT_ERROR, "Did not write, no Multilayer Image");
- goto cleanup;
- }
- }
- else {
- if (imf->views_format == R_IMF_VIEWS_STEREO_3D) {
- if (!BKE_image_is_stereo(ima)) {
- BKE_reportf(op->reports, RPT_ERROR, "Did not write, the image doesn't have a \"%s\" and \"%s\" views",
- STEREO_LEFT_NAME, STEREO_RIGHT_NAME);
- goto cleanup;
- }
-
- /* it shouldn't ever happen*/
- if ((BLI_findstring(&rr->views, STEREO_LEFT_NAME, offsetof(RenderView, name)) == NULL) ||
- (BLI_findstring(&rr->views, STEREO_RIGHT_NAME, offsetof(RenderView, name)) == NULL))
- {
- BKE_reportf(op->reports, RPT_ERROR, "Did not write, the image doesn't have a \"%s\" and \"%s\" views",
- STEREO_LEFT_NAME, STEREO_RIGHT_NAME);
- goto cleanup;
- }
- }
- BKE_imbuf_stamp_info(rr, ibuf);
- }
-
- /* fancy multiview OpenEXR */
- if (imf->views_format == R_IMF_VIEWS_MULTIVIEW && is_exr_rr) {
- /* save render result */
- ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, NULL, layer);
- save_image_post(bmain, op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath);
- ED_space_image_release_buffer(sima, ibuf, lock);
- }
- /* regular mono pipeline */
- else if (is_mono) {
- if (is_exr_rr) {
- ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, NULL, layer);
- }
- else {
- colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf);
- ok = BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, imf, save_copy);
- save_imbuf_post(ibuf, colormanaged_ibuf);
- }
- save_image_post(bmain, op, ibuf, ima, ok, (is_exr_rr ? true : save_copy), relbase, relative, do_newpath, simopts->filepath);
- ED_space_image_release_buffer(sima, ibuf, lock);
- }
- /* individual multiview images */
- else if (imf->views_format == R_IMF_VIEWS_INDIVIDUAL) {
- int i;
- unsigned char planes = ibuf->planes;
- const int totviews = (rr ? BLI_listbase_count(&rr->views) : BLI_listbase_count(&ima->views));
-
- if (!is_exr_rr) {
- ED_space_image_release_buffer(sima, ibuf, lock);
- }
-
- for (i = 0; i < totviews; i++) {
- char filepath[FILE_MAX];
- bool ok_view = false;
- const char *view = rr ? ((RenderView *) BLI_findlink(&rr->views, i))->name :
- ((ImageView *) BLI_findlink(&ima->views, i))->name;
-
- if (is_exr_rr) {
- BKE_scene_multiview_view_filepath_get(&scene->r, simopts->filepath, view, filepath);
- ok_view = RE_WriteRenderResult(op->reports, rr, filepath, imf, view, layer);
- save_image_post(bmain, op, ibuf, ima, ok_view, true, relbase, relative, do_newpath, filepath);
- }
- else {
- /* copy iuser to get the correct ibuf for this view */
- ImageUser iuser = sima->iuser;
- iuser.view = i;
- iuser.flag &= ~IMA_SHOW_STEREO;
-
- if (rr) {
- BKE_image_multilayer_index(rr, &iuser);
- }
- else {
- BKE_image_multiview_index(ima, &iuser);
- }
-
- ibuf = BKE_image_acquire_ibuf(sima->image, &iuser, &lock);
- ibuf->planes = planes;
-
- BKE_scene_multiview_view_filepath_get(&scene->r, simopts->filepath, view, filepath);
-
- colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf);
- ok_view = BKE_imbuf_write_as(colormanaged_ibuf, filepath, &simopts->im_format, save_copy);
- save_imbuf_post(ibuf, colormanaged_ibuf);
- save_image_post(bmain, op, ibuf, ima, ok_view, true, relbase, relative, do_newpath, filepath);
- BKE_image_release_ibuf(sima->image, ibuf, lock);
- }
- ok &= ok_view;
- }
-
- if (is_exr_rr) {
- ED_space_image_release_buffer(sima, ibuf, lock);
- }
- }
- /* stereo (multiview) images */
- else if (simopts->im_format.views_format == R_IMF_VIEWS_STEREO_3D) {
- if (imf->imtype == R_IMF_IMTYPE_MULTILAYER) {
- ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, NULL, layer);
- save_image_post(bmain, op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath);
- ED_space_image_release_buffer(sima, ibuf, lock);
- }
- else {
- ImBuf *ibuf_stereo[2] = {NULL};
-
- unsigned char planes = ibuf->planes;
- const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
- int i;
-
- /* we need to get the specific per-view buffers */
- ED_space_image_release_buffer(sima, ibuf, lock);
-
- for (i = 0; i < 2; i ++) {
- ImageUser iuser = sima->iuser;
- iuser.flag &= ~IMA_SHOW_STEREO;
-
- if (rr) {
- int id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name));
- iuser.view = id;
- BKE_image_multilayer_index(rr, &iuser);
- }
- else {
- iuser.view = i;
- BKE_image_multiview_index(ima, &iuser);
- }
-
- ibuf = BKE_image_acquire_ibuf(sima->image, &iuser, &lock);
-
- if (ibuf == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Did not write, unexpected error when saving stereo image");
- goto cleanup;
- }
-
- ibuf->planes = planes;
-
- /* color manage the ImBuf leaving it ready for saving */
- colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true,
- &imf->view_settings, &imf->display_settings, imf);
-
- BKE_imbuf_write_prepare(colormanaged_ibuf, imf);
- IMB_prepare_write_ImBuf(IMB_isfloat(colormanaged_ibuf), colormanaged_ibuf);
-
- /* duplicate buffer to prevent locker issue when using render result */
- ibuf_stereo[i] = IMB_dupImBuf(colormanaged_ibuf);
-
- save_imbuf_post(ibuf, colormanaged_ibuf);
- BKE_image_release_ibuf(sima->image, ibuf, lock);
- }
-
- ibuf = IMB_stereo3d_ImBuf(imf, ibuf_stereo[0], ibuf_stereo[1]);
-
- /* save via traditional path */
- ok = BKE_imbuf_write_as(ibuf, simopts->filepath, imf, save_copy);
-
- IMB_freeImBuf(ibuf);
-
- for (i = 0; i < 2; i ++) {
- IMB_freeImBuf(ibuf_stereo[i]);
- }
- }
- }
-
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, sima->image);
-
- }
- else {
-cleanup:
- ED_space_image_release_buffer(sima, ibuf, lock);
- }
-
- if (rr) {
- BKE_image_release_renderresult(scene, ima);
- }
-
- WM_cursor_wait(0);
-
- return ok;
+static bool save_image_doit(
+ bContext *C, SpaceImage *sima, wmOperator *op, SaveImageOptions *simopts, bool do_newpath)
+{
+ Main *bmain = CTX_data_main(C);
+ Image *ima = ED_space_image(sima);
+ void *lock;
+ ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
+ Scene *scene;
+ RenderResult *rr = NULL;
+ bool ok = false;
+
+ WM_cursor_wait(1);
+
+ if (ibuf) {
+ ImBuf *colormanaged_ibuf = NULL;
+ const char *relbase = ID_BLEND_PATH(CTX_data_main(C), &ima->id);
+ const bool relative = (RNA_struct_find_property(op->ptr, "relative_path") &&
+ RNA_boolean_get(op->ptr, "relative_path"));
+ const bool save_copy = (RNA_struct_find_property(op->ptr, "copy") &&
+ RNA_boolean_get(op->ptr, "copy"));
+ const bool save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") &&
+ RNA_boolean_get(op->ptr, "save_as_render"));
+ ImageFormatData *imf = &simopts->im_format;
+
+ /* old global to ensure a 2nd save goes to same dir */
+ BLI_strncpy(G.ima, simopts->filepath, sizeof(G.ima));
+
+ if (ima->type == IMA_TYPE_R_RESULT) {
+ /* enforce user setting for RGB or RGBA, but skip BW */
+ if (simopts->im_format.planes == R_IMF_PLANES_RGBA) {
+ ibuf->planes = R_IMF_PLANES_RGBA;
+ }
+ else if (simopts->im_format.planes == R_IMF_PLANES_RGB) {
+ ibuf->planes = R_IMF_PLANES_RGB;
+ }
+ }
+ else {
+ /* TODO, better solution, if a 24bit image is painted onto it may contain alpha */
+ if ((simopts->im_format.planes == R_IMF_PLANES_RGBA) &&
+ /* it has been painted onto */
+ (ibuf->userflags & IB_BITMAPDIRTY)) {
+ /* checks each pixel, not ideal */
+ ibuf->planes = BKE_imbuf_alpha_test(ibuf) ? R_IMF_PLANES_RGBA : R_IMF_PLANES_RGB;
+ }
+ }
+
+ /* we need renderresult for exr and rendered multiview */
+ scene = CTX_data_scene(C);
+ rr = BKE_image_acquire_renderresult(scene, ima);
+ bool is_mono = rr ? BLI_listbase_count_at_most(&rr->views, 2) < 2 :
+ BLI_listbase_count_at_most(&ima->views, 2) < 2;
+ bool is_exr_rr = rr && ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER) &&
+ RE_HasFloatPixels(rr);
+ bool is_multilayer = is_exr_rr && (imf->imtype == R_IMF_IMTYPE_MULTILAYER);
+ int layer = (is_multilayer) ? -1 : sima->iuser.layer;
+
+ /* error handling */
+ if (!rr) {
+ if (imf->imtype == R_IMF_IMTYPE_MULTILAYER) {
+ BKE_report(op->reports, RPT_ERROR, "Did not write, no Multilayer Image");
+ goto cleanup;
+ }
+ }
+ else {
+ if (imf->views_format == R_IMF_VIEWS_STEREO_3D) {
+ if (!BKE_image_is_stereo(ima)) {
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "Did not write, the image doesn't have a \"%s\" and \"%s\" views",
+ STEREO_LEFT_NAME,
+ STEREO_RIGHT_NAME);
+ goto cleanup;
+ }
+
+ /* it shouldn't ever happen*/
+ if ((BLI_findstring(&rr->views, STEREO_LEFT_NAME, offsetof(RenderView, name)) == NULL) ||
+ (BLI_findstring(&rr->views, STEREO_RIGHT_NAME, offsetof(RenderView, name)) == NULL)) {
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "Did not write, the image doesn't have a \"%s\" and \"%s\" views",
+ STEREO_LEFT_NAME,
+ STEREO_RIGHT_NAME);
+ goto cleanup;
+ }
+ }
+ BKE_imbuf_stamp_info(rr, ibuf);
+ }
+
+ /* fancy multiview OpenEXR */
+ if (imf->views_format == R_IMF_VIEWS_MULTIVIEW && is_exr_rr) {
+ /* save render result */
+ ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, NULL, layer);
+ save_image_post(
+ bmain, op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath);
+ ED_space_image_release_buffer(sima, ibuf, lock);
+ }
+ /* regular mono pipeline */
+ else if (is_mono) {
+ if (is_exr_rr) {
+ ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, NULL, layer);
+ }
+ else {
+ colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(
+ ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf);
+ ok = BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, imf, save_copy);
+ save_imbuf_post(ibuf, colormanaged_ibuf);
+ }
+ save_image_post(bmain,
+ op,
+ ibuf,
+ ima,
+ ok,
+ (is_exr_rr ? true : save_copy),
+ relbase,
+ relative,
+ do_newpath,
+ simopts->filepath);
+ ED_space_image_release_buffer(sima, ibuf, lock);
+ }
+ /* individual multiview images */
+ else if (imf->views_format == R_IMF_VIEWS_INDIVIDUAL) {
+ int i;
+ unsigned char planes = ibuf->planes;
+ const int totviews = (rr ? BLI_listbase_count(&rr->views) : BLI_listbase_count(&ima->views));
+
+ if (!is_exr_rr) {
+ ED_space_image_release_buffer(sima, ibuf, lock);
+ }
+
+ for (i = 0; i < totviews; i++) {
+ char filepath[FILE_MAX];
+ bool ok_view = false;
+ const char *view = rr ? ((RenderView *)BLI_findlink(&rr->views, i))->name :
+ ((ImageView *)BLI_findlink(&ima->views, i))->name;
+
+ if (is_exr_rr) {
+ BKE_scene_multiview_view_filepath_get(&scene->r, simopts->filepath, view, filepath);
+ ok_view = RE_WriteRenderResult(op->reports, rr, filepath, imf, view, layer);
+ save_image_post(
+ bmain, op, ibuf, ima, ok_view, true, relbase, relative, do_newpath, filepath);
+ }
+ else {
+ /* copy iuser to get the correct ibuf for this view */
+ ImageUser iuser = sima->iuser;
+ iuser.view = i;
+ iuser.flag &= ~IMA_SHOW_STEREO;
+
+ if (rr) {
+ BKE_image_multilayer_index(rr, &iuser);
+ }
+ else {
+ BKE_image_multiview_index(ima, &iuser);
+ }
+
+ ibuf = BKE_image_acquire_ibuf(sima->image, &iuser, &lock);
+ ibuf->planes = planes;
+
+ BKE_scene_multiview_view_filepath_get(&scene->r, simopts->filepath, view, filepath);
+
+ colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(
+ ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf);
+ ok_view = BKE_imbuf_write_as(
+ colormanaged_ibuf, filepath, &simopts->im_format, save_copy);
+ save_imbuf_post(ibuf, colormanaged_ibuf);
+ save_image_post(
+ bmain, op, ibuf, ima, ok_view, true, relbase, relative, do_newpath, filepath);
+ BKE_image_release_ibuf(sima->image, ibuf, lock);
+ }
+ ok &= ok_view;
+ }
+
+ if (is_exr_rr) {
+ ED_space_image_release_buffer(sima, ibuf, lock);
+ }
+ }
+ /* stereo (multiview) images */
+ else if (simopts->im_format.views_format == R_IMF_VIEWS_STEREO_3D) {
+ if (imf->imtype == R_IMF_IMTYPE_MULTILAYER) {
+ ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, NULL, layer);
+ save_image_post(
+ bmain, op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath);
+ ED_space_image_release_buffer(sima, ibuf, lock);
+ }
+ else {
+ ImBuf *ibuf_stereo[2] = {NULL};
+
+ unsigned char planes = ibuf->planes;
+ const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
+ int i;
+
+ /* we need to get the specific per-view buffers */
+ ED_space_image_release_buffer(sima, ibuf, lock);
+
+ for (i = 0; i < 2; i++) {
+ ImageUser iuser = sima->iuser;
+ iuser.flag &= ~IMA_SHOW_STEREO;
+
+ if (rr) {
+ int id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name));
+ iuser.view = id;
+ BKE_image_multilayer_index(rr, &iuser);
+ }
+ else {
+ iuser.view = i;
+ BKE_image_multiview_index(ima, &iuser);
+ }
+
+ ibuf = BKE_image_acquire_ibuf(sima->image, &iuser, &lock);
+
+ if (ibuf == NULL) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Did not write, unexpected error when saving stereo image");
+ goto cleanup;
+ }
+
+ ibuf->planes = planes;
+
+ /* color manage the ImBuf leaving it ready for saving */
+ colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(
+ ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf);
+
+ BKE_imbuf_write_prepare(colormanaged_ibuf, imf);
+ IMB_prepare_write_ImBuf(IMB_isfloat(colormanaged_ibuf), colormanaged_ibuf);
+
+ /* duplicate buffer to prevent locker issue when using render result */
+ ibuf_stereo[i] = IMB_dupImBuf(colormanaged_ibuf);
+
+ save_imbuf_post(ibuf, colormanaged_ibuf);
+ BKE_image_release_ibuf(sima->image, ibuf, lock);
+ }
+
+ ibuf = IMB_stereo3d_ImBuf(imf, ibuf_stereo[0], ibuf_stereo[1]);
+
+ /* save via traditional path */
+ ok = BKE_imbuf_write_as(ibuf, simopts->filepath, imf, save_copy);
+
+ IMB_freeImBuf(ibuf);
+
+ for (i = 0; i < 2; i++) {
+ IMB_freeImBuf(ibuf_stereo[i]);
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, sima->image);
+ }
+ else {
+ cleanup:
+ ED_space_image_release_buffer(sima, ibuf, lock);
+ }
+
+ if (rr) {
+ BKE_image_release_renderresult(scene, ima);
+ }
+
+ WM_cursor_wait(0);
+
+ return ok;
}
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);
+ if (op->customdata) {
+ ImageFormatData *im_format = (ImageFormatData *)op->customdata;
+ BKE_color_managed_view_settings_free(&im_format->view_settings);
- MEM_freeN(op->customdata);
- op->customdata = NULL;
- }
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+ }
}
static int image_save_as_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- SaveImageOptions simopts;
+ Main *bmain = CTX_data_main(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ SaveImageOptions simopts;
- save_image_options_defaults(&simopts);
+ save_image_options_defaults(&simopts);
- /* just in case to initialize values,
- * these should be set on invoke or by the caller. */
- save_image_options_init(bmain, &simopts, sima, CTX_data_scene(C), false, false);
+ /* just in case to initialize values,
+ * these should be set on invoke or by the caller. */
+ save_image_options_init(bmain, &simopts, sima, CTX_data_scene(C), false, false);
- save_image_options_from_op(bmain, &simopts, op);
+ save_image_options_from_op(bmain, &simopts, op);
- save_image_doit(C, sima, op, &simopts, true);
+ save_image_doit(C, sima, op, &simopts, true);
- image_save_as_free(op);
- return OPERATOR_FINISHED;
+ image_save_as_free(op);
+ return OPERATOR_FINISHED;
}
-
static bool image_save_as_check(bContext *UNUSED(C), wmOperator *op)
{
- ImageFormatData *imf = op->customdata;
- return WM_operator_filesel_ensure_ext_imtype(op, imf);
+ ImageFormatData *imf = op->customdata;
+ return WM_operator_filesel_ensure_ext_imtype(op, imf);
}
static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Main *bmain = CTX_data_main(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = ED_space_image(sima);
- Scene *scene = CTX_data_scene(C);
- SaveImageOptions simopts;
- PropertyRNA *prop;
- const bool save_as_render = ((ima->source == IMA_SRC_VIEWER) || (ima->flag & IMA_VIEW_AS_RENDER));
+ Main *bmain = CTX_data_main(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = ED_space_image(sima);
+ Scene *scene = CTX_data_scene(C);
+ SaveImageOptions simopts;
+ PropertyRNA *prop;
+ const bool save_as_render = ((ima->source == IMA_SRC_VIEWER) ||
+ (ima->flag & IMA_VIEW_AS_RENDER));
- if (RNA_struct_property_is_set(op->ptr, "filepath")) {
- return image_save_as_exec(C, op);
- }
+ if (RNA_struct_property_is_set(op->ptr, "filepath")) {
+ return image_save_as_exec(C, op);
+ }
- save_image_options_defaults(&simopts);
+ save_image_options_defaults(&simopts);
- if (save_image_options_init(bmain, &simopts, sima, scene, true, save_as_render) == 0) {
- return OPERATOR_CANCELLED;
- }
- save_image_options_to_op(&simopts, op);
+ if (save_image_options_init(bmain, &simopts, sima, scene, true, save_as_render) == 0) {
+ return OPERATOR_CANCELLED;
+ }
+ save_image_options_to_op(&simopts, op);
- /* enable save_copy by default for render results */
- if (ELEM(ima->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE) && !RNA_struct_property_is_set(op->ptr, "copy")) {
- RNA_boolean_set(op->ptr, "copy", true);
- }
+ /* enable save_copy by default for render results */
+ if (ELEM(ima->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE) &&
+ !RNA_struct_property_is_set(op->ptr, "copy")) {
+ RNA_boolean_set(op->ptr, "copy", true);
+ }
- RNA_boolean_set(op->ptr, "save_as_render", save_as_render);
+ RNA_boolean_set(op->ptr, "save_as_render", save_as_render);
- op->customdata = MEM_mallocN(sizeof(simopts.im_format), __func__);
- memcpy(op->customdata, &simopts.im_format, sizeof(simopts.im_format));
+ op->customdata = MEM_mallocN(sizeof(simopts.im_format), __func__);
+ memcpy(op->customdata, &simopts.im_format, sizeof(simopts.im_format));
- /* show multiview save options only if image has multiviews */
- prop = RNA_struct_find_property(op->ptr, "show_multiview");
- RNA_property_boolean_set(op->ptr, prop, BKE_image_is_multiview(ima));
- prop = RNA_struct_find_property(op->ptr, "use_multiview");
- RNA_property_boolean_set(op->ptr, prop, BKE_image_is_multiview(ima));
+ /* show multiview save options only if image has multiviews */
+ prop = RNA_struct_find_property(op->ptr, "show_multiview");
+ RNA_property_boolean_set(op->ptr, prop, BKE_image_is_multiview(ima));
+ prop = RNA_struct_find_property(op->ptr, "use_multiview");
+ RNA_property_boolean_set(op->ptr, prop, BKE_image_is_multiview(ima));
- image_filesel(C, op, simopts.filepath);
+ image_filesel(C, op, simopts.filepath);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static void image_save_as_cancel(bContext *UNUSED(C), wmOperator *op)
{
- image_save_as_free(op);
+ image_save_as_free(op);
}
-static bool image_save_as_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop, void *UNUSED(user_data))
+static bool image_save_as_draw_check_prop(PointerRNA *ptr,
+ PropertyRNA *prop,
+ void *UNUSED(user_data))
{
- const char *prop_id = RNA_property_identifier(prop);
+ const char *prop_id = RNA_property_identifier(prop);
- return !(STREQ(prop_id, "filepath") ||
- STREQ(prop_id, "directory") ||
- STREQ(prop_id, "filename") ||
- /* when saving a copy, relative path has no effect */
- ((STREQ(prop_id, "relative_path")) && RNA_boolean_get(ptr, "copy"))
- );
+ return !(STREQ(prop_id, "filepath") || STREQ(prop_id, "directory") ||
+ STREQ(prop_id, "filename") ||
+ /* when saving a copy, relative path has no effect */
+ ((STREQ(prop_id, "relative_path")) && RNA_boolean_get(ptr, "copy")));
}
static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op)
{
- uiLayout *layout = op->layout;
- ImageFormatData *imf = op->customdata;
- PointerRNA imf_ptr, ptr;
- const bool is_multiview = RNA_boolean_get(op->ptr, "show_multiview");
+ uiLayout *layout = op->layout;
+ ImageFormatData *imf = 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);
- uiTemplateImageSettings(layout, &imf_ptr, false);
+ /* image template */
+ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr);
+ uiTemplateImageSettings(layout, &imf_ptr, false);
- /* main draw call */
- RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
- uiDefAutoButsRNA(layout, &ptr, image_save_as_draw_check_prop, NULL, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
+ /* main draw call */
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+ uiDefAutoButsRNA(
+ layout, &ptr, image_save_as_draw_check_prop, NULL, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
- /* multiview template */
- if (is_multiview) {
- uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr);
- }
+ /* multiview template */
+ if (is_multiview) {
+ uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr);
+ }
}
static bool image_save_as_poll(bContext *C)
{
- if (space_image_buffer_exists_poll(C)) {
- if (G.is_rendering) {
- /* no need to NULL check here */
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = ED_space_image(sima);
+ if (space_image_buffer_exists_poll(C)) {
+ if (G.is_rendering) {
+ /* no need to NULL check here */
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = ED_space_image(sima);
- if (ima->source == IMA_SRC_VIEWER) {
- CTX_wm_operator_poll_msg_set(C, "can't save image while rendering");
- return false;
- }
- }
- return true;
- }
- return false;
+ if (ima->source == IMA_SRC_VIEWER) {
+ CTX_wm_operator_poll_msg_set(C, "can't save image while rendering");
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
}
void IMAGE_OT_save_as(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Save As Image";
- ot->idname = "IMAGE_OT_save_as";
- ot->description = "Save the image with another name and/or settings";
-
- /* api callbacks */
- ot->exec = image_save_as_exec;
- ot->check = image_save_as_check;
- ot->invoke = image_save_as_invoke;
- ot->cancel = image_save_as_cancel;
- ot->ui = image_save_as_draw;
- ot->poll = image_save_as_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "save_as_render", 0, "Save As Render", "Apply render part of display transform when saving byte image");
- RNA_def_boolean(ot->srna, "copy", 0, "Copy", "Create a new image file without modifying the current image in blender");
-
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_SAVE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+ /* identifiers */
+ ot->name = "Save As Image";
+ ot->idname = "IMAGE_OT_save_as";
+ ot->description = "Save the image with another name and/or settings";
+
+ /* api callbacks */
+ ot->exec = image_save_as_exec;
+ ot->check = image_save_as_check;
+ ot->invoke = image_save_as_invoke;
+ ot->cancel = image_save_as_cancel;
+ ot->ui = image_save_as_draw;
+ ot->poll = image_save_as_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "save_as_render",
+ 0,
+ "Save As Render",
+ "Apply render part of display transform when saving byte image");
+ RNA_def_boolean(ot->srna,
+ "copy",
+ 0,
+ "Copy",
+ "Create a new image file without modifying the current image in blender");
+
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE,
+ FILE_SPECIAL,
+ FILE_SAVE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
}
/******************** save image operator ********************/
static int image_save_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- Scene *scene = CTX_data_scene(C);
- SaveImageOptions simopts;
+ Main *bmain = CTX_data_main(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Scene *scene = CTX_data_scene(C);
+ SaveImageOptions simopts;
- save_image_options_defaults(&simopts);
- if (save_image_options_init(bmain, &simopts, sima, scene, false, false) == 0) {
- return OPERATOR_CANCELLED;
- }
- save_image_options_from_op(bmain, &simopts, op);
+ save_image_options_defaults(&simopts);
+ if (save_image_options_init(bmain, &simopts, sima, scene, false, false) == 0) {
+ return OPERATOR_CANCELLED;
+ }
+ save_image_options_from_op(bmain, &simopts, op);
- if (BLI_exists(simopts.filepath) && BLI_file_is_writable(simopts.filepath)) {
- if (save_image_doit(C, sima, op, &simopts, false)) {
- /* report since this can be called from key-shortcuts */
- BKE_reportf(op->reports, RPT_INFO, "Saved Image '%s'", simopts.filepath);
- }
- }
- else {
- BKE_reportf(op->reports, RPT_ERROR, "Cannot save image, path '%s' is not writable", simopts.filepath);
- return OPERATOR_CANCELLED;
- }
+ if (BLI_exists(simopts.filepath) && BLI_file_is_writable(simopts.filepath)) {
+ if (save_image_doit(C, sima, op, &simopts, false)) {
+ /* report since this can be called from key-shortcuts */
+ BKE_reportf(op->reports, RPT_INFO, "Saved Image '%s'", simopts.filepath);
+ }
+ }
+ else {
+ BKE_reportf(
+ op->reports, RPT_ERROR, "Cannot save image, path '%s' is not writable", simopts.filepath);
+ return OPERATOR_CANCELLED;
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void IMAGE_OT_save(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Save Image";
- ot->idname = "IMAGE_OT_save";
- ot->description = "Save the image with current name and settings";
+ /* identifiers */
+ ot->name = "Save Image";
+ ot->idname = "IMAGE_OT_save";
+ ot->description = "Save the image with current name and settings";
- /* api callbacks */
- ot->exec = image_save_exec;
- ot->poll = space_image_file_exists_poll;
+ /* api callbacks */
+ ot->exec = image_save_exec;
+ ot->poll = space_image_file_exists_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************* save sequence operator ********************/
static int image_save_sequence_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- ImBuf *ibuf, *first_ibuf = NULL;
- int tot = 0;
- char di[FILE_MAX];
- struct MovieCacheIter *iter;
-
- if (sima->image == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- if (sima->image->source != IMA_SRC_SEQUENCE) {
- BKE_report(op->reports, RPT_ERROR, "Can only save sequence on image sequences");
- return OPERATOR_CANCELLED;
- }
-
- if (sima->image->type == IMA_TYPE_MULTILAYER) {
- BKE_report(op->reports, RPT_ERROR, "Cannot save multilayer sequences");
- return OPERATOR_CANCELLED;
- }
-
- /* get total dirty buffers and first dirty buffer which is used for menu */
- ibuf = NULL;
- if (sima->image->cache != NULL) {
- iter = IMB_moviecacheIter_new(sima->image->cache);
- while (!IMB_moviecacheIter_done(iter)) {
- ibuf = IMB_moviecacheIter_getImBuf(iter);
- if (ibuf->userflags & IB_BITMAPDIRTY) {
- if (first_ibuf == NULL) {
- first_ibuf = ibuf;
- }
- tot++;
- }
- IMB_moviecacheIter_step(iter);
- }
- IMB_moviecacheIter_free(iter);
- }
-
- if (tot == 0) {
- BKE_report(op->reports, RPT_WARNING, "No images have been changed");
- return OPERATOR_CANCELLED;
- }
-
- /* get a filename for menu */
- BLI_split_dir_part(first_ibuf->name, di, sizeof(di));
- BKE_reportf(op->reports, RPT_INFO, "%d image(s) will be saved in %s", tot, di);
-
- iter = IMB_moviecacheIter_new(sima->image->cache);
- while (!IMB_moviecacheIter_done(iter)) {
- ibuf = IMB_moviecacheIter_getImBuf(iter);
-
- if (ibuf->userflags & IB_BITMAPDIRTY) {
- char name[FILE_MAX];
- BLI_strncpy(name, ibuf->name, sizeof(name));
-
- BLI_path_abs(name, BKE_main_blendfile_path(bmain));
-
- if (0 == IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat)) {
- BKE_reportf(op->reports, RPT_ERROR, "Could not write image: %s", strerror(errno));
- break;
- }
-
- BKE_reportf(op->reports, RPT_INFO, "Saved %s", ibuf->name);
- ibuf->userflags &= ~IB_BITMAPDIRTY;
- }
-
- IMB_moviecacheIter_step(iter);
- }
- IMB_moviecacheIter_free(iter);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ImBuf *ibuf, *first_ibuf = NULL;
+ int tot = 0;
+ char di[FILE_MAX];
+ struct MovieCacheIter *iter;
+
+ if (sima->image == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (sima->image->source != IMA_SRC_SEQUENCE) {
+ BKE_report(op->reports, RPT_ERROR, "Can only save sequence on image sequences");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (sima->image->type == IMA_TYPE_MULTILAYER) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot save multilayer sequences");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get total dirty buffers and first dirty buffer which is used for menu */
+ ibuf = NULL;
+ if (sima->image->cache != NULL) {
+ iter = IMB_moviecacheIter_new(sima->image->cache);
+ while (!IMB_moviecacheIter_done(iter)) {
+ ibuf = IMB_moviecacheIter_getImBuf(iter);
+ if (ibuf->userflags & IB_BITMAPDIRTY) {
+ if (first_ibuf == NULL) {
+ first_ibuf = ibuf;
+ }
+ tot++;
+ }
+ IMB_moviecacheIter_step(iter);
+ }
+ IMB_moviecacheIter_free(iter);
+ }
+
+ if (tot == 0) {
+ BKE_report(op->reports, RPT_WARNING, "No images have been changed");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get a filename for menu */
+ BLI_split_dir_part(first_ibuf->name, di, sizeof(di));
+ BKE_reportf(op->reports, RPT_INFO, "%d image(s) will be saved in %s", tot, di);
+
+ iter = IMB_moviecacheIter_new(sima->image->cache);
+ while (!IMB_moviecacheIter_done(iter)) {
+ ibuf = IMB_moviecacheIter_getImBuf(iter);
+
+ if (ibuf->userflags & IB_BITMAPDIRTY) {
+ char name[FILE_MAX];
+ BLI_strncpy(name, ibuf->name, sizeof(name));
+
+ BLI_path_abs(name, BKE_main_blendfile_path(bmain));
+
+ if (0 == IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat)) {
+ BKE_reportf(op->reports, RPT_ERROR, "Could not write image: %s", strerror(errno));
+ break;
+ }
+
+ BKE_reportf(op->reports, RPT_INFO, "Saved %s", ibuf->name);
+ ibuf->userflags &= ~IB_BITMAPDIRTY;
+ }
+
+ IMB_moviecacheIter_step(iter);
+ }
+ IMB_moviecacheIter_free(iter);
+
+ return OPERATOR_FINISHED;
}
void IMAGE_OT_save_sequence(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Save Sequence";
- ot->idname = "IMAGE_OT_save_sequence";
- ot->description = "Save a sequence of images";
+ /* identifiers */
+ ot->name = "Save Sequence";
+ ot->idname = "IMAGE_OT_save_sequence";
+ ot->description = "Save a sequence of images";
- /* api callbacks */
- ot->exec = image_save_sequence_exec;
- ot->poll = space_image_buffer_exists_poll;
+ /* api callbacks */
+ ot->exec = image_save_sequence_exec;
+ ot->poll = space_image_buffer_exists_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************** reload image operator ********************/
static int image_reload_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Image *ima = CTX_data_edit_image(C);
- SpaceImage *sima = CTX_wm_space_image(C);
+ Main *bmain = CTX_data_main(C);
+ Image *ima = CTX_data_edit_image(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
- if (!ima) {
- return OPERATOR_CANCELLED;
- }
+ if (!ima) {
+ return OPERATOR_CANCELLED;
+ }
- /* XXX unpackImage frees image buffers */
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ /* XXX unpackImage frees image buffers */
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
- BKE_image_signal(bmain, ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_RELOAD);
- DEG_id_tag_update(&ima->id, 0);
+ BKE_image_signal(bmain, ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_RELOAD);
+ DEG_id_tag_update(&ima->id, 0);
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void IMAGE_OT_reload(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reload Image";
- ot->idname = "IMAGE_OT_reload";
- ot->description = "Reload current image from disk";
+ /* identifiers */
+ ot->name = "Reload Image";
+ ot->idname = "IMAGE_OT_reload";
+ ot->description = "Reload current image from disk";
- /* api callbacks */
- ot->exec = image_reload_exec;
+ /* api callbacks */
+ ot->exec = image_reload_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER; /* no undo, image buffer is not handled by undo */
+ /* flags */
+ ot->flag = OPTYPE_REGISTER; /* no undo, image buffer is not handled by undo */
}
/********************** new image operator *********************/
#define IMA_DEF_NAME N_("Untitled")
enum {
- GEN_CONTEXT_NONE = 0,
- GEN_CONTEXT_PAINT_CANVAS = 1,
- GEN_CONTEXT_PAINT_STENCIL = 2,
+ GEN_CONTEXT_NONE = 0,
+ GEN_CONTEXT_PAINT_CANVAS = 1,
+ GEN_CONTEXT_PAINT_STENCIL = 2,
};
typedef struct ImageNewData {
- PropertyPointerRNA pprop;
+ PropertyPointerRNA pprop;
} ImageNewData;
static ImageNewData *image_new_init(bContext *C, wmOperator *op)
{
- if (op->customdata) {
- return op->customdata;
- }
+ if (op->customdata) {
+ return op->customdata;
+ }
- ImageNewData *data = MEM_callocN(sizeof(ImageNewData), __func__);
- UI_context_active_but_prop_get_templateID(C, &data->pprop.ptr, &data->pprop.prop);
- op->customdata = data;
- return data;
+ ImageNewData *data = MEM_callocN(sizeof(ImageNewData), __func__);
+ UI_context_active_but_prop_get_templateID(C, &data->pprop.ptr, &data->pprop.prop);
+ op->customdata = data;
+ return data;
}
static void image_new_free(wmOperator *op)
{
- if (op->customdata) {
- MEM_freeN(op->customdata);
- op->customdata = NULL;
- }
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+ }
}
static int image_new_exec(bContext *C, wmOperator *op)
{
- SpaceImage *sima;
- Object *obedit;
- Image *ima;
- Main *bmain;
- PropertyRNA *prop;
- char name_buffer[MAX_ID_NAME - 2];
- const char *name;
- float color[4];
- int width, height, floatbuf, gen_type, alpha;
- int stereo3d;
-
- /* retrieve state */
- sima = CTX_wm_space_image(C);
- obedit = CTX_data_edit_object(C);
- bmain = CTX_data_main(C);
-
- prop = RNA_struct_find_property(op->ptr, "name");
- RNA_property_string_get(op->ptr, prop, name_buffer);
- if (!RNA_property_is_set(op->ptr, prop)) {
- /* Default value, we can translate! */
- name = DATA_(name_buffer);
- }
- else {
- name = name_buffer;
- }
- width = RNA_int_get(op->ptr, "width");
- height = RNA_int_get(op->ptr, "height");
- floatbuf = RNA_boolean_get(op->ptr, "float");
- gen_type = RNA_enum_get(op->ptr, "generated_type");
- RNA_float_get_array(op->ptr, "color", color);
- alpha = RNA_boolean_get(op->ptr, "alpha");
- stereo3d = RNA_boolean_get(op->ptr, "use_stereo_3d");
-
- if (!alpha) {
- color[3] = 1.0f;
- }
-
- ima = BKE_image_add_generated(bmain, width, height, name, alpha ? 32 : 24, floatbuf, gen_type, color, stereo3d);
-
- if (!ima) {
- image_new_free(op);
- return OPERATOR_CANCELLED;
- }
-
- /* hook into UI */
- ImageNewData *data = image_new_init(C, op);
-
- if (data->pprop.prop) {
- /* when creating new ID blocks, use is already 1, but RNA
- * pointer use also increases user, so this compensates it */
- id_us_min(&ima->id);
-
- PointerRNA imaptr;
- RNA_id_pointer_create(&ima->id, &imaptr);
- RNA_property_pointer_set(&data->pprop.ptr, data->pprop.prop, imaptr);
- RNA_property_update(C, &data->pprop.ptr, data->pprop.prop);
- }
- else if (sima) {
- ED_space_image_set(bmain, sima, obedit, ima, false);
- }
-
- BKE_image_signal(bmain, ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_USER_NEW_IMAGE);
-
- WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
-
- image_new_free(op);
-
- return OPERATOR_FINISHED;
+ SpaceImage *sima;
+ Object *obedit;
+ Image *ima;
+ Main *bmain;
+ PropertyRNA *prop;
+ char name_buffer[MAX_ID_NAME - 2];
+ const char *name;
+ float color[4];
+ int width, height, floatbuf, gen_type, alpha;
+ int stereo3d;
+
+ /* retrieve state */
+ sima = CTX_wm_space_image(C);
+ obedit = CTX_data_edit_object(C);
+ bmain = CTX_data_main(C);
+
+ prop = RNA_struct_find_property(op->ptr, "name");
+ RNA_property_string_get(op->ptr, prop, name_buffer);
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ /* Default value, we can translate! */
+ name = DATA_(name_buffer);
+ }
+ else {
+ name = name_buffer;
+ }
+ width = RNA_int_get(op->ptr, "width");
+ height = RNA_int_get(op->ptr, "height");
+ floatbuf = RNA_boolean_get(op->ptr, "float");
+ gen_type = RNA_enum_get(op->ptr, "generated_type");
+ RNA_float_get_array(op->ptr, "color", color);
+ alpha = RNA_boolean_get(op->ptr, "alpha");
+ stereo3d = RNA_boolean_get(op->ptr, "use_stereo_3d");
+
+ if (!alpha) {
+ color[3] = 1.0f;
+ }
+
+ ima = BKE_image_add_generated(
+ bmain, width, height, name, alpha ? 32 : 24, floatbuf, gen_type, color, stereo3d);
+
+ if (!ima) {
+ image_new_free(op);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* hook into UI */
+ ImageNewData *data = image_new_init(C, op);
+
+ if (data->pprop.prop) {
+ /* when creating new ID blocks, use is already 1, but RNA
+ * pointer use also increases user, so this compensates it */
+ id_us_min(&ima->id);
+
+ PointerRNA imaptr;
+ RNA_id_pointer_create(&ima->id, &imaptr);
+ RNA_property_pointer_set(&data->pprop.ptr, data->pprop.prop, imaptr);
+ RNA_property_update(C, &data->pprop.ptr, data->pprop.prop);
+ }
+ else if (sima) {
+ ED_space_image_set(bmain, sima, obedit, ima, false);
+ }
+
+ BKE_image_signal(bmain, ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_USER_NEW_IMAGE);
+
+ WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
+
+ image_new_free(op);
+
+ return OPERATOR_FINISHED;
}
static int image_new_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- /* Get property in advance, it doesn't work after WM_operator_props_dialog_popup. */
- ImageNewData *data;
- op->customdata = data = MEM_callocN(sizeof(ImageNewData), __func__);
- UI_context_active_but_prop_get_templateID(C, &data->pprop.ptr, &data->pprop.prop);
+ /* Get property in advance, it doesn't work after WM_operator_props_dialog_popup. */
+ ImageNewData *data;
+ op->customdata = data = MEM_callocN(sizeof(ImageNewData), __func__);
+ UI_context_active_but_prop_get_templateID(C, &data->pprop.ptr, &data->pprop.prop);
- /* Better for user feedback. */
- RNA_string_set(op->ptr, "name", DATA_(IMA_DEF_NAME));
- return WM_operator_props_dialog_popup(C, op, 300, 100);
+ /* Better for user feedback. */
+ RNA_string_set(op->ptr, "name", DATA_(IMA_DEF_NAME));
+ return WM_operator_props_dialog_popup(C, op, 300, 100);
}
static void image_new_draw(bContext *UNUSED(C), wmOperator *op)
{
- uiLayout *split, *col[2];
- uiLayout *layout = op->layout;
- PointerRNA ptr;
+ uiLayout *split, *col[2];
+ uiLayout *layout = op->layout;
+ PointerRNA ptr;
#if 0
- Scene *scene = CTX_data_scene(C);
- const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
+ Scene *scene = CTX_data_scene(C);
+ const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
#endif
- RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
- /* copy of WM_operator_props_dialog_popup() layout */
+ /* copy of WM_operator_props_dialog_popup() layout */
- split = uiLayoutSplit(layout, 0.5f, false);
- col[0] = uiLayoutColumn(split, false);
- col[1] = uiLayoutColumn(split, false);
+ split = uiLayoutSplit(layout, 0.5f, false);
+ col[0] = uiLayoutColumn(split, false);
+ col[1] = uiLayoutColumn(split, false);
- uiItemL(col[0], IFACE_("Name"), ICON_NONE);
- uiItemR(col[1], &ptr, "name", 0, "", ICON_NONE);
+ uiItemL(col[0], IFACE_("Name"), ICON_NONE);
+ uiItemR(col[1], &ptr, "name", 0, "", ICON_NONE);
- uiItemL(col[0], IFACE_("Width"), ICON_NONE);
- uiItemR(col[1], &ptr, "width", 0, "", ICON_NONE);
+ uiItemL(col[0], IFACE_("Width"), ICON_NONE);
+ uiItemR(col[1], &ptr, "width", 0, "", ICON_NONE);
- uiItemL(col[0], IFACE_("Height"), ICON_NONE);
- uiItemR(col[1], &ptr, "height", 0, "", ICON_NONE);
+ uiItemL(col[0], IFACE_("Height"), ICON_NONE);
+ uiItemR(col[1], &ptr, "height", 0, "", ICON_NONE);
- uiItemL(col[0], IFACE_("Color"), ICON_NONE);
- uiItemR(col[1], &ptr, "color", 0, "", ICON_NONE);
+ uiItemL(col[0], IFACE_("Color"), ICON_NONE);
+ uiItemR(col[1], &ptr, "color", 0, "", ICON_NONE);
- uiItemL(col[0], "", ICON_NONE);
- uiItemR(col[1], &ptr, "alpha", 0, NULL, ICON_NONE);
+ uiItemL(col[0], "", ICON_NONE);
+ uiItemR(col[1], &ptr, "alpha", 0, NULL, ICON_NONE);
- uiItemL(col[0], IFACE_("Generated Type"), ICON_NONE);
- uiItemR(col[1], &ptr, "generated_type", 0, "", ICON_NONE);
+ uiItemL(col[0], IFACE_("Generated Type"), ICON_NONE);
+ uiItemR(col[1], &ptr, "generated_type", 0, "", ICON_NONE);
- uiItemL(col[0], "", ICON_NONE);
- uiItemR(col[1], &ptr, "float", 0, NULL, ICON_NONE);
+ uiItemL(col[0], "", ICON_NONE);
+ uiItemR(col[1], &ptr, "float", 0, NULL, ICON_NONE);
#if 0
- if (is_multiview) {
- uiItemL(col[0], "", ICON_NONE);
- uiItemR(col[1], &ptr, "use_stereo_3d", 0, NULL, ICON_NONE);
- }
+ if (is_multiview) {
+ uiItemL(col[0], "", ICON_NONE);
+ uiItemR(col[1], &ptr, "use_stereo_3d", 0, NULL, ICON_NONE);
+ }
#endif
}
static void image_new_cancel(bContext *UNUSED(C), wmOperator *op)
{
- image_new_free(op);
+ image_new_free(op);
}
void IMAGE_OT_new(wmOperatorType *ot)
{
- PropertyRNA *prop;
- static float default_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
-
- /* identifiers */
- ot->name = "New Image";
- ot->description = "Create a new image";
- ot->idname = "IMAGE_OT_new";
-
- /* api callbacks */
- ot->exec = image_new_exec;
- ot->invoke = image_new_invoke;
- ot->ui = image_new_draw;
- ot->cancel = image_new_cancel;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- RNA_def_string(ot->srna, "name", IMA_DEF_NAME, MAX_ID_NAME - 2, "Name", "Image data-block name");
- prop = RNA_def_int(ot->srna, "width", 1024, 1, INT_MAX, "Width", "Image width", 1, 16384);
- RNA_def_property_subtype(prop, PROP_PIXEL);
- prop = RNA_def_int(ot->srna, "height", 1024, 1, INT_MAX, "Height", "Image height", 1, 16384);
- RNA_def_property_subtype(prop, PROP_PIXEL);
- prop = RNA_def_float_color(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_enum(ot->srna, "generated_type", rna_enum_image_generated_type_items, IMA_GENTYPE_BLANK,
- "Generated Type", "Fill the image with a grid for UV map testing");
- RNA_def_boolean(ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth");
- RNA_def_property_flag(prop, PROP_HIDDEN);
- prop = RNA_def_boolean(ot->srna, "use_stereo_3d", 0, "Stereo 3D", "Create an image with left and right views");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ PropertyRNA *prop;
+ static float default_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+
+ /* identifiers */
+ ot->name = "New Image";
+ ot->description = "Create a new image";
+ ot->idname = "IMAGE_OT_new";
+
+ /* api callbacks */
+ ot->exec = image_new_exec;
+ ot->invoke = image_new_invoke;
+ ot->ui = image_new_draw;
+ ot->cancel = image_new_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_string(ot->srna, "name", IMA_DEF_NAME, MAX_ID_NAME - 2, "Name", "Image data-block name");
+ prop = RNA_def_int(ot->srna, "width", 1024, 1, INT_MAX, "Width", "Image width", 1, 16384);
+ RNA_def_property_subtype(prop, PROP_PIXEL);
+ prop = RNA_def_int(ot->srna, "height", 1024, 1, INT_MAX, "Height", "Image height", 1, 16384);
+ RNA_def_property_subtype(prop, PROP_PIXEL);
+ prop = RNA_def_float_color(
+ 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_enum(ot->srna,
+ "generated_type",
+ rna_enum_image_generated_type_items,
+ IMA_GENTYPE_BLANK,
+ "Generated Type",
+ "Fill the image with a grid for UV map testing");
+ RNA_def_boolean(
+ ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_boolean(
+ ot->srna, "use_stereo_3d", 0, "Stereo 3D", "Create an image with left and right views");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
#undef IMA_DEF_NAME
@@ -2620,437 +2765,475 @@ void IMAGE_OT_new(wmOperatorType *ot)
static bool image_invert_poll(bContext *C)
{
- Image *ima = CTX_data_edit_image(C);
+ Image *ima = CTX_data_edit_image(C);
- return BKE_image_has_ibuf(ima, NULL);
+ return BKE_image_has_ibuf(ima, NULL);
}
static int image_invert_exec(bContext *C, wmOperator *op)
{
- Image *ima = CTX_data_edit_image(C);
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
- SpaceImage *sima = CTX_wm_space_image(C);
- /* undo is supported only on image paint mode currently */
- bool support_undo = ((sima != NULL) && (sima->mode == SI_MODE_PAINT));
-
- /* flags indicate if this channel should be inverted */
- const bool r = RNA_boolean_get(op->ptr, "invert_r");
- const bool g = RNA_boolean_get(op->ptr, "invert_g");
- const bool b = RNA_boolean_get(op->ptr, "invert_b");
- const bool a = RNA_boolean_get(op->ptr, "invert_a");
-
- size_t i;
-
- if (ibuf == NULL) {
- /* TODO: this should actually never happen, but does for render-results -> cleanup */
- return OPERATOR_CANCELLED;
- }
-
- if (support_undo) {
- ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_2D);
- /* not strictly needed, because we only imapaint_dirty_region to invalidate all tiles
- * but better do this right in case someone copies this for a tool that uses partial
- * redraw better */
- ED_imapaint_clear_partial_redraw();
- ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false);
- }
- /* TODO: make this into an IMB_invert_channels(ibuf,r,g,b,a) method!? */
- if (ibuf->rect_float) {
-
- float *fp = (float *) ibuf->rect_float;
- for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, fp += 4) {
- if (r) { fp[0] = 1.0f - fp[0]; }
- if (g) { fp[1] = 1.0f - fp[1]; }
- if (b) { fp[2] = 1.0f - fp[2]; }
- if (a) { fp[3] = 1.0f - fp[3]; }
- }
-
- if (ibuf->rect) {
- IMB_rect_from_float(ibuf);
- }
- }
- else if (ibuf->rect) {
-
- char *cp = (char *) ibuf->rect;
- for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, cp += 4) {
- if (r) { cp[0] = 255 - cp[0]; }
- if (g) { cp[1] = 255 - cp[1]; }
- if (b) { cp[2] = 255 - cp[2]; }
- if (a) { cp[3] = 255 - cp[3]; }
- }
- }
- else {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- return OPERATOR_CANCELLED;
- }
-
- ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID;
-
- if (ibuf->mipmap[0]) {
- ibuf->userflags |= IB_MIPMAP_INVALID;
- }
-
- if (support_undo) {
- ED_image_undo_push_end();
- }
-
- /* force GPU reupload, all image is invalid */
- GPU_free_image(ima);
-
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
-
- return OPERATOR_FINISHED;
+ Image *ima = CTX_data_edit_image(C);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ /* undo is supported only on image paint mode currently */
+ bool support_undo = ((sima != NULL) && (sima->mode == SI_MODE_PAINT));
+
+ /* flags indicate if this channel should be inverted */
+ const bool r = RNA_boolean_get(op->ptr, "invert_r");
+ const bool g = RNA_boolean_get(op->ptr, "invert_g");
+ const bool b = RNA_boolean_get(op->ptr, "invert_b");
+ const bool a = RNA_boolean_get(op->ptr, "invert_a");
+
+ size_t i;
+
+ if (ibuf == NULL) {
+ /* TODO: this should actually never happen, but does for render-results -> cleanup */
+ return OPERATOR_CANCELLED;
+ }
+
+ if (support_undo) {
+ ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_2D);
+ /* not strictly needed, because we only imapaint_dirty_region to invalidate all tiles
+ * but better do this right in case someone copies this for a tool that uses partial
+ * redraw better */
+ ED_imapaint_clear_partial_redraw();
+ ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false);
+ }
+ /* TODO: make this into an IMB_invert_channels(ibuf,r,g,b,a) method!? */
+ if (ibuf->rect_float) {
+
+ float *fp = (float *)ibuf->rect_float;
+ for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, fp += 4) {
+ if (r) {
+ fp[0] = 1.0f - fp[0];
+ }
+ if (g) {
+ fp[1] = 1.0f - fp[1];
+ }
+ if (b) {
+ fp[2] = 1.0f - fp[2];
+ }
+ if (a) {
+ fp[3] = 1.0f - fp[3];
+ }
+ }
+
+ if (ibuf->rect) {
+ IMB_rect_from_float(ibuf);
+ }
+ }
+ else if (ibuf->rect) {
+
+ char *cp = (char *)ibuf->rect;
+ for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, cp += 4) {
+ if (r) {
+ cp[0] = 255 - cp[0];
+ }
+ if (g) {
+ cp[1] = 255 - cp[1];
+ }
+ if (b) {
+ cp[2] = 255 - cp[2];
+ }
+ if (a) {
+ cp[3] = 255 - cp[3];
+ }
+ }
+ }
+ else {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ return OPERATOR_CANCELLED;
+ }
+
+ ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID;
+
+ if (ibuf->mipmap[0]) {
+ ibuf->userflags |= IB_MIPMAP_INVALID;
+ }
+
+ if (support_undo) {
+ ED_image_undo_push_end();
+ }
+
+ /* force GPU reupload, all image is invalid */
+ GPU_free_image(ima);
+
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+
+ return OPERATOR_FINISHED;
}
void IMAGE_OT_invert(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Invert Channels";
- ot->idname = "IMAGE_OT_invert";
- ot->description = "Invert image's channels";
+ /* identifiers */
+ ot->name = "Invert Channels";
+ ot->idname = "IMAGE_OT_invert";
+ ot->description = "Invert image's channels";
- /* api callbacks */
- ot->exec = image_invert_exec;
- ot->poll = image_invert_poll;
+ /* api callbacks */
+ ot->exec = image_invert_exec;
+ ot->poll = image_invert_poll;
- /* properties */
- prop = RNA_def_boolean(ot->srna, "invert_r", 0, "Red", "Invert Red Channel");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "invert_g", 0, "Green", "Invert Green Channel");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "invert_b", 0, "Blue", "Invert Blue Channel");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "invert_a", 0, "Alpha", "Invert Alpha Channel");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "invert_r", 0, "Red", "Invert Red Channel");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "invert_g", 0, "Green", "Invert Green Channel");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "invert_b", 0, "Blue", "Invert Blue Channel");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "invert_a", 0, "Alpha", "Invert Alpha Channel");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************* pack operator *********************/
static bool image_pack_test(bContext *C, wmOperator *op)
{
- Image *ima = CTX_data_edit_image(C);
- const bool as_png = RNA_boolean_get(op->ptr, "as_png");
+ Image *ima = CTX_data_edit_image(C);
+ const bool as_png = RNA_boolean_get(op->ptr, "as_png");
- if (!ima) {
- return 0;
- }
- if (!as_png && BKE_image_has_packedfile(ima)) {
- return 0;
- }
+ if (!ima) {
+ return 0;
+ }
+ if (!as_png && BKE_image_has_packedfile(ima)) {
+ return 0;
+ }
- if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) {
- BKE_report(op->reports, RPT_ERROR, "Packing movies or image sequences not supported");
- return 0;
- }
+ if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) {
+ BKE_report(op->reports, RPT_ERROR, "Packing movies or image sequences not supported");
+ return 0;
+ }
- return 1;
+ return 1;
}
static int image_pack_exec(bContext *C, wmOperator *op)
{
- struct Main *bmain = CTX_data_main(C);
- Image *ima = CTX_data_edit_image(C);
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
- const bool as_png = RNA_boolean_get(op->ptr, "as_png");
+ struct Main *bmain = CTX_data_main(C);
+ Image *ima = CTX_data_edit_image(C);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ const bool as_png = RNA_boolean_get(op->ptr, "as_png");
- if (!image_pack_test(C, op)) {
- return OPERATOR_CANCELLED;
- }
+ if (!image_pack_test(C, op)) {
+ return OPERATOR_CANCELLED;
+ }
- if (!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) {
- BKE_report(op->reports, RPT_ERROR, "Cannot pack edited image from disk, only as internal PNG");
- return OPERATOR_CANCELLED;
- }
+ if (!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot pack edited image from disk, only as internal PNG");
+ return OPERATOR_CANCELLED;
+ }
- if (as_png) {
- BKE_image_memorypack(ima);
- }
- else {
- BKE_image_packfiles(op->reports, ima, ID_BLEND_PATH(bmain, &ima->id));
- }
+ if (as_png) {
+ BKE_image_memorypack(ima);
+ }
+ else {
+ BKE_image_packfiles(op->reports, ima, ID_BLEND_PATH(bmain, &ima->id));
+ }
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_release_ibuf(ima, ibuf, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int image_pack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Image *ima = CTX_data_edit_image(C);
- ImBuf *ibuf;
- uiPopupMenu *pup;
- uiLayout *layout;
- const bool as_png = RNA_boolean_get(op->ptr, "as_png");
+ Image *ima = CTX_data_edit_image(C);
+ ImBuf *ibuf;
+ uiPopupMenu *pup;
+ uiLayout *layout;
+ const bool as_png = RNA_boolean_get(op->ptr, "as_png");
- if (!image_pack_test(C, op)) {
- return OPERATOR_CANCELLED;
- }
+ if (!image_pack_test(C, op)) {
+ return OPERATOR_CANCELLED;
+ }
- ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
- if (!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) {
- pup = UI_popup_menu_begin(C, IFACE_("OK"), ICON_QUESTION);
- layout = UI_popup_menu_layout(pup);
- uiItemBooleanO(layout, IFACE_("Can't pack edited image from disk, pack as internal PNG?"), ICON_NONE,
- op->idname, "as_png", 1);
- UI_popup_menu_end(C, pup);
+ if (!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) {
+ pup = UI_popup_menu_begin(C, IFACE_("OK"), ICON_QUESTION);
+ layout = UI_popup_menu_layout(pup);
+ uiItemBooleanO(layout,
+ IFACE_("Can't pack edited image from disk, pack as internal PNG?"),
+ ICON_NONE,
+ op->idname,
+ "as_png",
+ 1);
+ UI_popup_menu_end(C, pup);
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_release_ibuf(ima, ibuf, NULL);
- return OPERATOR_INTERFACE;
- }
+ return OPERATOR_INTERFACE;
+ }
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_release_ibuf(ima, ibuf, NULL);
- return image_pack_exec(C, op);
+ return image_pack_exec(C, op);
}
void IMAGE_OT_pack(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Pack Image";
- ot->description = "Pack an image as embedded data into the .blend file";
- ot->idname = "IMAGE_OT_pack";
+ /* identifiers */
+ ot->name = "Pack Image";
+ ot->description = "Pack an image as embedded data into the .blend file";
+ ot->idname = "IMAGE_OT_pack";
- /* api callbacks */
- ot->exec = image_pack_exec;
- ot->invoke = image_pack_invoke;
+ /* api callbacks */
+ ot->exec = image_pack_exec;
+ ot->invoke = image_pack_invoke;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "as_png", 0, "Pack As PNG", "Pack image as lossless PNG");
+ /* properties */
+ RNA_def_boolean(ot->srna, "as_png", 0, "Pack As PNG", "Pack image as lossless PNG");
}
/********************* unpack operator *********************/
static int image_unpack_exec(bContext *C, wmOperator *op)
{
- Image *ima = CTX_data_edit_image(C);
- int method = RNA_enum_get(op->ptr, "method");
+ Image *ima = CTX_data_edit_image(C);
+ int method = RNA_enum_get(op->ptr, "method");
- /* find the suppplied 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);
- if (!ima) {
- ima = CTX_data_edit_image(C);
- }
- }
+ /* find the suppplied 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);
+ if (!ima) {
+ ima = CTX_data_edit_image(C);
+ }
+ }
- if (!ima || !BKE_image_has_packedfile(ima)) {
- return OPERATOR_CANCELLED;
- }
+ if (!ima || !BKE_image_has_packedfile(ima)) {
+ return OPERATOR_CANCELLED;
+ }
- if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) {
- BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
- return OPERATOR_CANCELLED;
- }
+ if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) {
+ BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
+ return OPERATOR_CANCELLED;
+ }
- if (G.fileflags & G_FILE_AUTOPACK) {
- BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so image will be packed again on file save");
- }
+ if (G.fileflags & G_FILE_AUTOPACK) {
+ BKE_report(op->reports,
+ RPT_WARNING,
+ "AutoPack is enabled, so image will be packed again on file save");
+ }
- /* XXX unpackImage frees image buffers */
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ /* XXX unpackImage frees image buffers */
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
- unpackImage(CTX_data_main(C), op->reports, ima, method);
+ unpackImage(CTX_data_main(C), op->reports, ima, method);
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Image *ima = CTX_data_edit_image(C);
+ Image *ima = CTX_data_edit_image(C);
- if (RNA_struct_property_is_set(op->ptr, "id")) {
- return image_unpack_exec(C, op);
- }
+ if (RNA_struct_property_is_set(op->ptr, "id")) {
+ return image_unpack_exec(C, op);
+ }
- if (!ima || !BKE_image_has_packedfile(ima)) {
- return OPERATOR_CANCELLED;
- }
+ if (!ima || !BKE_image_has_packedfile(ima)) {
+ return OPERATOR_CANCELLED;
+ }
- if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) {
- BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
- return OPERATOR_CANCELLED;
- }
+ if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) {
+ BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
+ return OPERATOR_CANCELLED;
+ }
- if (G.fileflags & G_FILE_AUTOPACK) {
- BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so image will be packed again on file save");
- }
+ if (G.fileflags & G_FILE_AUTOPACK) {
+ BKE_report(op->reports,
+ RPT_WARNING,
+ "AutoPack is enabled, so image will be packed again on file save");
+ }
- unpack_menu(C, "IMAGE_OT_unpack", ima->id.name + 2, ima->name, "textures", BKE_image_has_packedfile(ima) ? ((ImagePackedFile *)ima->packedfiles.first)->packedfile : NULL);
+ unpack_menu(C,
+ "IMAGE_OT_unpack",
+ ima->id.name + 2,
+ ima->name,
+ "textures",
+ BKE_image_has_packedfile(ima) ?
+ ((ImagePackedFile *)ima->packedfiles.first)->packedfile :
+ NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void IMAGE_OT_unpack(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unpack Image";
- ot->description = "Save an image packed in the .blend file to disk";
- ot->idname = "IMAGE_OT_unpack";
+ /* identifiers */
+ ot->name = "Unpack Image";
+ ot->description = "Save an image packed in the .blend file to disk";
+ ot->idname = "IMAGE_OT_unpack";
- /* api callbacks */
- ot->exec = image_unpack_exec;
- ot->invoke = image_unpack_invoke;
+ /* api callbacks */
+ ot->exec = image_unpack_exec;
+ ot->invoke = image_unpack_invoke;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_enum(ot->srna, "method", rna_enum_unpack_method_items, PF_USE_LOCAL, "Method", "How to unpack");
- /* XXX, weak!, will fail with library, name collisions */
- RNA_def_string(ot->srna, "id", NULL, MAX_ID_NAME - 2, "Image Name", "Image data-block name to unpack");
+ /* properties */
+ RNA_def_enum(
+ ot->srna, "method", rna_enum_unpack_method_items, PF_USE_LOCAL, "Method", "How to unpack");
+ /* XXX, weak!, will fail with library, name collisions */
+ RNA_def_string(
+ ot->srna, "id", NULL, MAX_ID_NAME - 2, "Image Name", "Image data-block name to unpack");
}
/******************** 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;
+ 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);
- 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();
- }
+ 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);
+ 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])
{
- void *lock;
- ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
- float fx, fy;
- bool ret = false;
+ void *lock;
+ ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
+ float fx, fy;
+ bool ret = false;
- if (ibuf == NULL) {
- ED_space_image_release_buffer(sima, ibuf, lock);
- return false;
- }
+ if (ibuf == NULL) {
+ ED_space_image_release_buffer(sima, ibuf, lock);
+ return false;
+ }
- UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &fx, &fy);
+ UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &fx, &fy);
- if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
- const float *fp;
- unsigned char *cp;
- int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
+ if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
+ const float *fp;
+ unsigned char *cp;
+ int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
- CLAMP(x, 0, ibuf->x - 1);
- CLAMP(y, 0, ibuf->y - 1);
+ CLAMP(x, 0, ibuf->x - 1);
+ CLAMP(y, 0, ibuf->y - 1);
- if (ibuf->rect_float) {
- fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
- copy_v3_v3(r_col, fp);
- ret = true;
- }
- else if (ibuf->rect) {
- cp = (unsigned char *)(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;
- }
- }
+ if (ibuf->rect_float) {
+ fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
+ copy_v3_v3(r_col, fp);
+ ret = true;
+ }
+ else if (ibuf->rect) {
+ cp = (unsigned char *)(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;
+ }
+ }
- ED_space_image_release_buffer(sima, ibuf, lock);
- return ret;
+ ED_space_image_release_buffer(sima, ibuf, lock);
+ 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])
+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);
+ 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])
+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);
+ const float *cp = ibuf->rect_float + (ibuf->channels) * (coord[1] * ibuf->x + coord[0]);
+ copy_v4_v4(r_col, cp);
}
/** \} */
@@ -3059,541 +3242,541 @@ static void image_sample_pixel_color_float(
/** \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_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);
- void *lock;
- ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
- ImageSampleInfo *info = op->customdata;
- float fx, fy;
- 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;
- }
-
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fx, &fy);
-
- if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
- int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
- Image *image = ED_space_image(sima);
-
- 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) {
- curvemapping_set_black_white(curve_mapping, NULL, info->linearcol);
- }
- else if (point == 0) {
- curvemapping_set_black_white(curve_mapping, info->linearcol, NULL);
- }
- WM_event_add_notifier(C, NC_WINDOW, NULL);
- }
- }
-
- // XXX node curve integration ..
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ARegion *ar = CTX_wm_region(C);
+ void *lock;
+ ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
+ ImageSampleInfo *info = op->customdata;
+ float fx, fy;
+ 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;
+ }
+
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fx, &fy);
+
+ if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
+ int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
+ Image *image = ED_space_image(sima);
+
+ 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) {
+ curvemapping_set_black_white(curve_mapping, NULL, info->linearcol);
+ }
+ else if (point == 0) {
+ 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;
- }
+ {
+ 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;
- }
+ }
+ else {
+ info->draw = 0;
+ }
- ED_space_image_release_buffer(sima, ibuf, lock);
- ED_area_tag_redraw(CTX_wm_area(C));
+ 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;
+ 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);
+ 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;
+ 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 (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;
- }
+ if (!ED_space_image_has_buffer(sima)) {
+ return OPERATOR_CANCELLED;
+ }
- info = MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo");
+ 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;
+ 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);
+ image_sample_apply(C, op, event);
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ 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;
- }
+ 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;
+ return OPERATOR_RUNNING_MODAL;
}
static void image_sample_cancel(bContext *C, wmOperator *op)
{
- image_sample_exit(C, op);
+ image_sample_exit(C, op);
}
void IMAGE_OT_sample(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Sample Color";
- ot->idname = "IMAGE_OT_sample";
- ot->description = "Use mouse to sample a color in current image";
+ /* identifiers */
+ ot->name = "Sample Color";
+ ot->idname = "IMAGE_OT_sample";
+ 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;
+ /* api callbacks */
+ ot->invoke = image_sample_invoke;
+ ot->modal = image_sample_modal;
+ ot->cancel = image_sample_cancel;
+ ot->poll = image_sample_poll;
- /* flags */
- ot->flag = OPTYPE_BLOCKING;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
- 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);
+ 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);
}
/******************** sample line operator ********************/
static int image_sample_line_exec(bContext *C, wmOperator *op)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
- int x_start = RNA_int_get(op->ptr, "xstart");
- int y_start = RNA_int_get(op->ptr, "ystart");
- int x_end = RNA_int_get(op->ptr, "xend");
- int y_end = RNA_int_get(op->ptr, "yend");
+ int x_start = RNA_int_get(op->ptr, "xstart");
+ int y_start = RNA_int_get(op->ptr, "ystart");
+ int x_end = RNA_int_get(op->ptr, "xend");
+ int y_end = RNA_int_get(op->ptr, "yend");
- void *lock;
- ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
- Histogram *hist = &sima->sample_line_hist;
+ void *lock;
+ ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
+ Histogram *hist = &sima->sample_line_hist;
- float x1f, y1f, x2f, y2f;
+ float x1f, y1f, x2f, y2f;
- if (ibuf == NULL) {
- ED_space_image_release_buffer(sima, ibuf, lock);
- return OPERATOR_CANCELLED;
- }
- /* hmmmm */
- if (ibuf->channels < 3) {
- ED_space_image_release_buffer(sima, ibuf, lock);
- return OPERATOR_CANCELLED;
- }
+ if (ibuf == NULL) {
+ ED_space_image_release_buffer(sima, ibuf, lock);
+ return OPERATOR_CANCELLED;
+ }
+ /* hmmmm */
+ if (ibuf->channels < 3) {
+ ED_space_image_release_buffer(sima, ibuf, lock);
+ return OPERATOR_CANCELLED;
+ }
- UI_view2d_region_to_view(&ar->v2d, x_start, y_start, &x1f, &y1f);
- UI_view2d_region_to_view(&ar->v2d, x_end, y_end, &x2f, &y2f);
+ UI_view2d_region_to_view(&ar->v2d, x_start, y_start, &x1f, &y1f);
+ UI_view2d_region_to_view(&ar->v2d, x_end, y_end, &x2f, &y2f);
- hist->co[0][0] = x1f;
- hist->co[0][1] = y1f;
- hist->co[1][0] = x2f;
- hist->co[1][1] = y2f;
+ hist->co[0][0] = x1f;
+ hist->co[0][1] = y1f;
+ hist->co[1][0] = x2f;
+ hist->co[1][1] = y2f;
- /* enable line drawing */
- hist->flag |= HISTO_FLAG_SAMPLELINE;
+ /* enable line drawing */
+ hist->flag |= HISTO_FLAG_SAMPLELINE;
- BKE_histogram_update_sample_line(hist, ibuf, &scene->view_settings, &scene->display_settings);
+ BKE_histogram_update_sample_line(hist, ibuf, &scene->view_settings, &scene->display_settings);
- /* reset y zoom */
- hist->ymax = 1.0f;
+ /* reset y zoom */
+ hist->ymax = 1.0f;
- ED_space_image_release_buffer(sima, ibuf, lock);
+ ED_space_image_release_buffer(sima, ibuf, lock);
- ED_area_tag_redraw(CTX_wm_area(C));
+ ED_area_tag_redraw(CTX_wm_area(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int image_sample_line_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- SpaceImage *sima = CTX_wm_space_image(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
- Histogram *hist = &sima->sample_line_hist;
- hist->flag &= ~HISTO_FLAG_SAMPLELINE;
+ Histogram *hist = &sima->sample_line_hist;
+ hist->flag &= ~HISTO_FLAG_SAMPLELINE;
- if (!ED_space_image_has_buffer(sima)) {
- return OPERATOR_CANCELLED;
- }
+ if (!ED_space_image_has_buffer(sima)) {
+ return OPERATOR_CANCELLED;
+ }
- return WM_gesture_straightline_invoke(C, op, event);
+ return WM_gesture_straightline_invoke(C, op, event);
}
void IMAGE_OT_sample_line(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Sample Line";
- ot->idname = "IMAGE_OT_sample_line";
- ot->description = "Sample a line and show it in Scope panels";
+ /* identifiers */
+ ot->name = "Sample Line";
+ ot->idname = "IMAGE_OT_sample_line";
+ ot->description = "Sample a line and show it in Scope panels";
- /* api callbacks */
- ot->invoke = image_sample_line_invoke;
- ot->modal = WM_gesture_straightline_modal;
- ot->exec = image_sample_line_exec;
- ot->poll = space_image_main_region_poll;
- ot->cancel = WM_gesture_straightline_cancel;
+ /* api callbacks */
+ ot->invoke = image_sample_line_invoke;
+ ot->modal = WM_gesture_straightline_modal;
+ ot->exec = image_sample_line_exec;
+ ot->poll = space_image_main_region_poll;
+ ot->cancel = WM_gesture_straightline_cancel;
- /* flags */
- ot->flag = 0; /* no undo/register since this operates on the space */
+ /* flags */
+ ot->flag = 0; /* no undo/register since this operates on the space */
- WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT);
+ WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT);
}
/******************** set curve point operator ********************/
void IMAGE_OT_curves_point_set(wmOperatorType *ot)
{
- static const EnumPropertyItem point_items[] = {
- {0, "BLACK_POINT", 0, "Black Point", ""},
- {1, "WHITE_POINT", 0, "White Point", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem point_items[] = {
+ {0, "BLACK_POINT", 0, "Black Point", ""},
+ {1, "WHITE_POINT", 0, "White Point", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Set Curves Point";
- ot->idname = "IMAGE_OT_curves_point_set";
- ot->description = "Set black point or white point for curves";
+ /* identifiers */
+ ot->name = "Set Curves Point";
+ ot->idname = "IMAGE_OT_curves_point_set";
+ ot->description = "Set black point or white point for curves";
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* api callbacks */
- ot->invoke = image_sample_invoke;
- ot->modal = image_sample_modal;
- ot->cancel = image_sample_cancel;
- ot->poll = space_image_main_area_not_uv_brush_poll;
+ /* api callbacks */
+ ot->invoke = image_sample_invoke;
+ ot->modal = image_sample_modal;
+ ot->cancel = image_sample_cancel;
+ ot->poll = space_image_main_area_not_uv_brush_poll;
- /* properties */
- RNA_def_enum(ot->srna, "point", point_items, 0, "Point", "Set black point or white point for curves");
+ /* properties */
+ RNA_def_enum(
+ ot->srna, "point", point_items, 0, "Point", "Set black point or white point for curves");
- 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);
+ 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);
}
#if 0 /* Not ported to 2.5x yet */
/******************** record composite operator *********************/
typedef struct RecordCompositeData {
- wmTimer *timer;
- int old_cfra;
- int sfra, efra;
+ wmTimer *timer;
+ int old_cfra;
+ int sfra, efra;
} RecordCompositeData;
static int image_record_composite_apply(bContext *C, wmOperator *op)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- RecordCompositeData *rcd = op->customdata;
- Scene *scene = CTX_data_scene(C);
- ImBuf *ibuf;
+ SpaceImage *sima = CTX_wm_space_image(C);
+ RecordCompositeData *rcd = op->customdata;
+ Scene *scene = CTX_data_scene(C);
+ ImBuf *ibuf;
- WM_cursor_time(CTX_wm_window(C), scene->r.cfra);
+ WM_cursor_time(CTX_wm_window(C), scene->r.cfra);
- // XXX scene->nodetree->test_break = BKE_blender_test_break;
- // XXX scene->nodetree->test_break = NULL;
+ // XXX scene->nodetree->test_break = BKE_blender_test_break;
+ // XXX scene->nodetree->test_break = NULL;
- BKE_image_all_free_anim_ibufs(scene->r.cfra);
- ntreeCompositTagAnimated(scene->nodetree);
- ntreeCompositExecTree(scene->nodetree, &scene->r, 0, scene->r.cfra != rcd->old_cfra,
- &scene->view_settings, &scene->display_settings); /* 1 is no previews */
+ BKE_image_all_free_anim_ibufs(scene->r.cfra);
+ ntreeCompositTagAnimated(scene->nodetree);
+ ntreeCompositExecTree(scene->nodetree, &scene->r, 0, scene->r.cfra != rcd->old_cfra,
+ &scene->view_settings, &scene->display_settings); /* 1 is no previews */
- ED_area_tag_redraw(CTX_wm_area(C));
+ ED_area_tag_redraw(CTX_wm_area(C));
- ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, NULL);
- /* save memory in flipbooks */
- if (ibuf)
- imb_freerectfloatImBuf(ibuf);
+ ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, NULL);
+ /* save memory in flipbooks */
+ if (ibuf)
+ imb_freerectfloatImBuf(ibuf);
- BKE_image_release_ibuf(sima->image, ibuf, NULL);
+ BKE_image_release_ibuf(sima->image, ibuf, NULL);
- scene->r.cfra++;
+ scene->r.cfra++;
- return (scene->r.cfra <= rcd->efra);
+ return (scene->r.cfra <= rcd->efra);
}
static int image_record_composite_init(bContext *C, wmOperator *op)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- Scene *scene = CTX_data_scene(C);
- RecordCompositeData *rcd;
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Scene *scene = CTX_data_scene(C);
+ RecordCompositeData *rcd;
- if (sima->iuser.frames < 2)
- return 0;
- if (scene->nodetree == NULL)
- return 0;
+ if (sima->iuser.frames < 2)
+ return 0;
+ if (scene->nodetree == NULL)
+ return 0;
- op->customdata = rcd = MEM_callocN(sizeof(RecordCompositeData), "ImageRecordCompositeData");
+ op->customdata = rcd = MEM_callocN(sizeof(RecordCompositeData), "ImageRecordCompositeData");
- rcd->old_cfra = scene->r.cfra;
- rcd->sfra = sima->iuser.sfra;
- rcd->efra = sima->iuser.sfra + sima->iuser.frames - 1;
- scene->r.cfra = rcd->sfra;
+ rcd->old_cfra = scene->r.cfra;
+ rcd->sfra = sima->iuser.sfra;
+ rcd->efra = sima->iuser.sfra + sima->iuser.frames - 1;
+ scene->r.cfra = rcd->sfra;
- return 1;
+ return 1;
}
static void image_record_composite_exit(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- RecordCompositeData *rcd = op->customdata;
+ Scene *scene = CTX_data_scene(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ RecordCompositeData *rcd = op->customdata;
- scene->r.cfra = rcd->old_cfra;
+ scene->r.cfra = rcd->old_cfra;
- WM_cursor_modal_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
- if (rcd->timer)
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), rcd->timer);
+ if (rcd->timer)
+ WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), rcd->timer);
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, sima->image);
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, sima->image);
- // XXX play_anim(0);
- // XXX allqueue(REDRAWNODE, 1);
+ // XXX play_anim(0);
+ // XXX allqueue(REDRAWNODE, 1);
- MEM_freeN(rcd);
+ MEM_freeN(rcd);
}
static int image_record_composite_exec(bContext *C, wmOperator *op)
{
- if (!image_record_composite_init(C, op))
- return OPERATOR_CANCELLED;
+ if (!image_record_composite_init(C, op))
+ return OPERATOR_CANCELLED;
- while (image_record_composite_apply(C, op)) {}
+ while (image_record_composite_apply(C, op)) {}
- image_record_composite_exit(C, op);
+ image_record_composite_exit(C, op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int image_record_composite_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- RecordCompositeData *rcd;
+ RecordCompositeData *rcd;
- if (!image_record_composite_init(C, op))
- return OPERATOR_CANCELLED;
+ if (!image_record_composite_init(C, op))
+ return OPERATOR_CANCELLED;
- rcd = op->customdata;
- rcd->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.0f);
- WM_event_add_modal_handler(C, op);
+ rcd = op->customdata;
+ rcd->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.0f);
+ WM_event_add_modal_handler(C, op);
- if (!image_record_composite_apply(C, op))
- return OPERATOR_FINISHED;
+ if (!image_record_composite_apply(C, op))
+ return OPERATOR_FINISHED;
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static int image_record_composite_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- RecordCompositeData *rcd = op->customdata;
+ RecordCompositeData *rcd = op->customdata;
- switch (event->type) {
- case TIMER:
- if (rcd->timer == event->customdata) {
- if (!image_record_composite_apply(C, op)) {
- image_record_composite_exit(C, op);
- return OPERATOR_FINISHED;
- }
- }
- break;
- case ESCKEY:
- image_record_composite_exit(C, op);
- return OPERATOR_FINISHED;
- }
+ switch (event->type) {
+ case TIMER:
+ if (rcd->timer == event->customdata) {
+ if (!image_record_composite_apply(C, op)) {
+ image_record_composite_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ }
+ break;
+ case ESCKEY:
+ image_record_composite_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static void image_record_composite_cancel(bContext *C, wmOperator *op)
{
- image_record_composite_exit(C, op);
- return OPERATOR_CANCELLED;
+ image_record_composite_exit(C, op);
+ return OPERATOR_CANCELLED;
}
void IMAGE_OT_record_composite(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Record Composite";
- ot->idname = "IMAGE_OT_record_composite";
+ /* identifiers */
+ ot->name = "Record Composite";
+ ot->idname = "IMAGE_OT_record_composite";
- /* api callbacks */
- ot->exec = image_record_composite_exec;
- ot->invoke = image_record_composite_invoke;
- ot->modal = image_record_composite_modal;
- ot->cancel = image_record_composite_cancel;
- ot->poll = space_image_buffer_exists_poll;
+ /* api callbacks */
+ ot->exec = image_record_composite_exec;
+ ot->invoke = image_record_composite_invoke;
+ ot->modal = image_record_composite_modal;
+ ot->cancel = image_record_composite_cancel;
+ ot->poll = space_image_buffer_exists_poll;
}
#endif
@@ -3602,385 +3785,381 @@ void IMAGE_OT_record_composite(wmOperatorType *ot)
static bool image_cycle_render_slot_poll(bContext *C)
{
- Image *ima = CTX_data_edit_image(C);
+ Image *ima = CTX_data_edit_image(C);
- return (ima && ima->type == IMA_TYPE_R_RESULT);
+ return (ima && ima->type == IMA_TYPE_R_RESULT);
}
static int image_cycle_render_slot_exec(bContext *C, wmOperator *op)
{
- Image *ima = CTX_data_edit_image(C);
- const int direction = RNA_boolean_get(op->ptr, "reverse") ? -1 : 1;
+ Image *ima = CTX_data_edit_image(C);
+ const int direction = RNA_boolean_get(op->ptr, "reverse") ? -1 : 1;
- if (!ED_image_slot_cycle(ima, direction)) {
- return OPERATOR_CANCELLED;
- }
+ if (!ED_image_slot_cycle(ima, direction)) {
+ return OPERATOR_CANCELLED;
+ }
- WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
- /* no undo push for browsing existing */
- RenderSlot *slot = BKE_image_get_renderslot(ima, ima->render_slot);
- if ((slot && slot->render) || ima->render_slot == ima->last_render_slot) {
- return OPERATOR_CANCELLED;
- }
+ /* no undo push for browsing existing */
+ RenderSlot *slot = BKE_image_get_renderslot(ima, ima->render_slot);
+ if ((slot && slot->render) || ima->render_slot == ima->last_render_slot) {
+ return OPERATOR_CANCELLED;
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void IMAGE_OT_cycle_render_slot(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Cycle Render Slot";
- ot->idname = "IMAGE_OT_cycle_render_slot";
- ot->description = "Cycle through all non-void render slots";
+ /* identifiers */
+ ot->name = "Cycle Render Slot";
+ ot->idname = "IMAGE_OT_cycle_render_slot";
+ ot->description = "Cycle through all non-void render slots";
- /* api callbacks */
- ot->exec = image_cycle_render_slot_exec;
- ot->poll = image_cycle_render_slot_poll;
+ /* api callbacks */
+ ot->exec = image_cycle_render_slot_exec;
+ ot->poll = image_cycle_render_slot_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
- RNA_def_boolean(ot->srna, "reverse", 0, "Cycle in Reverse", "");
+ RNA_def_boolean(ot->srna, "reverse", 0, "Cycle in Reverse", "");
}
/********************* clear render slot operator *********************/
static int image_clear_render_slot_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = CTX_data_edit_image(C);
- if (!BKE_image_clear_renderslot(ima, &sima->iuser, ima->render_slot)) {
- return OPERATOR_CANCELLED;
- }
+ if (!BKE_image_clear_renderslot(ima, &sima->iuser, ima->render_slot)) {
+ return OPERATOR_CANCELLED;
+ }
- WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void IMAGE_OT_clear_render_slot(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Render Slot";
- ot->idname = "IMAGE_OT_clear_render_slot";
- ot->description = "Clear the currently selected render slot";
+ /* identifiers */
+ ot->name = "Clear Render Slot";
+ ot->idname = "IMAGE_OT_clear_render_slot";
+ ot->description = "Clear the currently selected render slot";
- /* api callbacks */
- ot->exec = image_clear_render_slot_exec;
- ot->poll = image_cycle_render_slot_poll;
+ /* api callbacks */
+ ot->exec = image_clear_render_slot_exec;
+ ot->poll = image_cycle_render_slot_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
}
/********************* add render slot operator *********************/
static int image_add_render_slot_exec(bContext *C, wmOperator *UNUSED(op))
{
- Image *ima = CTX_data_edit_image(C);
+ Image *ima = CTX_data_edit_image(C);
- RenderSlot *slot = BKE_image_add_renderslot(ima, NULL);
- ima->render_slot = BLI_findindex(&ima->renderslots, slot);
+ RenderSlot *slot = BKE_image_add_renderslot(ima, NULL);
+ ima->render_slot = BLI_findindex(&ima->renderslots, slot);
- WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void IMAGE_OT_add_render_slot(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Render Slot";
- ot->idname = "IMAGE_OT_add_render_slot";
- ot->description = "Add a new render slot";
+ /* identifiers */
+ ot->name = "Add Render Slot";
+ ot->idname = "IMAGE_OT_add_render_slot";
+ ot->description = "Add a new render slot";
- /* api callbacks */
- ot->exec = image_add_render_slot_exec;
- ot->poll = image_cycle_render_slot_poll;
+ /* api callbacks */
+ ot->exec = image_add_render_slot_exec;
+ ot->poll = image_cycle_render_slot_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
}
/********************* remove render slot operator *********************/
static int image_remove_render_slot_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = CTX_data_edit_image(C);
- if (!BKE_image_remove_renderslot(ima, &sima->iuser, ima->render_slot)) {
- return OPERATOR_CANCELLED;
- }
+ if (!BKE_image_remove_renderslot(ima, &sima->iuser, ima->render_slot)) {
+ return OPERATOR_CANCELLED;
+ }
- WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void IMAGE_OT_remove_render_slot(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Render Slot";
- ot->idname = "IMAGE_OT_remove_render_slot";
- ot->description = "Remove the current render slot";
+ /* identifiers */
+ ot->name = "Remove Render Slot";
+ ot->idname = "IMAGE_OT_remove_render_slot";
+ ot->description = "Remove the current render slot";
- /* api callbacks */
- ot->exec = image_remove_render_slot_exec;
- ot->poll = image_cycle_render_slot_poll;
+ /* api callbacks */
+ ot->exec = image_remove_render_slot_exec;
+ ot->poll = image_cycle_render_slot_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
}
/********************** change frame operator *********************/
static bool change_frame_poll(bContext *C)
{
- /* prevent changes during render */
- if (G.is_rendering) {
- return 0;
- }
+ /* prevent changes during render */
+ if (G.is_rendering) {
+ return 0;
+ }
- return space_image_main_region_poll(C);
+ return space_image_main_region_poll(C);
}
static void change_frame_apply(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- /* set the new frame number */
- CFRA = RNA_int_get(op->ptr, "frame");
- FRAMENUMBER_MIN_CLAMP(CFRA);
- SUBFRA = 0.0f;
+ /* set the new frame number */
+ CFRA = RNA_int_get(op->ptr, "frame");
+ FRAMENUMBER_MIN_CLAMP(CFRA);
+ SUBFRA = 0.0f;
- /* do updates */
- BKE_sound_seek_scene(CTX_data_main(C), scene);
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ /* do updates */
+ BKE_sound_seek_scene(CTX_data_main(C), scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
static int change_frame_exec(bContext *C, wmOperator *op)
{
- change_frame_apply(C, op);
+ change_frame_apply(C, op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int frame_from_event(bContext *C, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
- int framenr = 0;
+ ARegion *ar = 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 (ar->regiontype == RGN_TYPE_WINDOW) {
+ float sfra = SFRA, efra = EFRA, framelen = ar->winx / (efra - sfra + 1);
- framenr = sfra + event->mval[0] / framelen;
- }
- else {
- float viewx, viewy;
+ 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(&ar->v2d, event->mval[0], event->mval[1], &viewx, &viewy);
- framenr = round_fl_to_int(viewx);
- }
+ framenr = round_fl_to_int(viewx);
+ }
- return framenr;
+ return framenr;
}
static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *ar = CTX_wm_region(C);
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- SpaceImage *sima = CTX_wm_space_image(C);
- if (event->mval[1] > 16 || !ED_space_image_show_cache(sima)) {
- return OPERATOR_PASS_THROUGH;
- }
- }
+ if (ar->regiontype == RGN_TYPE_WINDOW) {
+ SpaceImage *sima = CTX_wm_space_image(C);
+ if (event->mval[1] > 16 || !ED_space_image_show_cache(sima)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+ }
- RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
+ RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
- change_frame_apply(C, op);
+ change_frame_apply(C, op);
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- switch (event->type) {
- case ESCKEY:
- return OPERATOR_FINISHED;
+ switch (event->type) {
+ case ESCKEY:
+ return OPERATOR_FINISHED;
- case MOUSEMOVE:
- RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
- change_frame_apply(C, op);
- break;
+ case MOUSEMOVE:
+ RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
+ change_frame_apply(C, op);
+ break;
- case LEFTMOUSE:
- case RIGHTMOUSE:
- if (event->val == KM_RELEASE) {
- return OPERATOR_FINISHED;
- }
- break;
- }
+ case LEFTMOUSE:
+ case RIGHTMOUSE:
+ if (event->val == KM_RELEASE) {
+ return OPERATOR_FINISHED;
+ }
+ break;
+ }
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void IMAGE_OT_change_frame(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Change Frame";
- ot->idname = "IMAGE_OT_change_frame";
- ot->description = "Interactively change the current frame number";
+ /* identifiers */
+ ot->name = "Change Frame";
+ ot->idname = "IMAGE_OT_change_frame";
+ ot->description = "Interactively change the current frame number";
- /* api callbacks */
- ot->exec = change_frame_exec;
- ot->invoke = change_frame_invoke;
- ot->modal = change_frame_modal;
- ot->poll = change_frame_poll;
+ /* api callbacks */
+ ot->exec = change_frame_exec;
+ ot->invoke = change_frame_invoke;
+ ot->modal = change_frame_modal;
+ ot->poll = change_frame_poll;
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO;
- /* rna */
- RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
+ /* rna */
+ RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
}
/* Reload cached render results... */
/* goes over all scenes, reads render layers */
static int image_read_viewlayers_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima;
- ima = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result");
- if (sima->image == NULL) {
- ED_space_image_set(bmain, sima, NULL, ima, false);
- }
+ ima = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result");
+ if (sima->image == NULL) {
+ ED_space_image_set(bmain, sima, NULL, ima, false);
+ }
- RE_ReadRenderResult(scene, scene);
+ RE_ReadRenderResult(scene, scene);
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
- return OPERATOR_FINISHED;
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+ return OPERATOR_FINISHED;
}
void IMAGE_OT_read_viewlayers(wmOperatorType *ot)
{
- ot->name = "Open Cached Render";
- ot->idname = "IMAGE_OT_read_viewlayers";
- ot->description = "Read all the current scene's view layers from cache, as needed";
+ ot->name = "Open Cached Render";
+ ot->idname = "IMAGE_OT_read_viewlayers";
+ ot->description = "Read all the current scene's view layers from cache, as needed";
- ot->poll = space_image_main_region_poll;
- ot->exec = image_read_viewlayers_exec;
+ ot->poll = space_image_main_region_poll;
+ ot->exec = image_read_viewlayers_exec;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
/* ********************* Render border operator ****************** */
static int render_border_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
- Render *re = RE_GetSceneRender(scene);
- RenderData *rd;
- rctf border;
-
- if (re == NULL) {
- /* Shouldn't happen, but better be safe close to the release. */
- return OPERATOR_CANCELLED;
- }
-
- rd = RE_engine_get_render_data(re);
- if ((rd->mode & (R_BORDER | R_CROP)) == (R_BORDER | R_CROP)) {
- BKE_report(op->reports, RPT_INFO, "Can not set border from a cropped render");
- return OPERATOR_CANCELLED;
- }
-
- /* get rectangle from operator */
- WM_operator_properties_border_to_rctf(op, &border);
- UI_view2d_region_to_view_rctf(&ar->v2d, &border, &border);
-
- /* actually set border */
- CLAMP(border.xmin, 0.0f, 1.0f);
- CLAMP(border.ymin, 0.0f, 1.0f);
- CLAMP(border.xmax, 0.0f, 1.0f);
- CLAMP(border.ymax, 0.0f, 1.0f);
- scene->r.border = border;
-
- /* drawing a border surrounding the entire camera view switches off border rendering
- * or the border covers no pixels */
- if ((border.xmin <= 0.0f && border.xmax >= 1.0f &&
- border.ymin <= 0.0f && border.ymax >= 1.0f) ||
- (border.xmin == border.xmax || border.ymin == border.ymax))
- {
- scene->r.mode &= ~R_BORDER;
- }
- else {
- scene->r.mode |= R_BORDER;
- }
-
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-
- return OPERATOR_FINISHED;
-
+ ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+ Render *re = RE_GetSceneRender(scene);
+ RenderData *rd;
+ rctf border;
+
+ if (re == NULL) {
+ /* Shouldn't happen, but better be safe close to the release. */
+ return OPERATOR_CANCELLED;
+ }
+
+ rd = RE_engine_get_render_data(re);
+ if ((rd->mode & (R_BORDER | R_CROP)) == (R_BORDER | R_CROP)) {
+ BKE_report(op->reports, RPT_INFO, "Can not set border from a cropped render");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get rectangle from operator */
+ WM_operator_properties_border_to_rctf(op, &border);
+ UI_view2d_region_to_view_rctf(&ar->v2d, &border, &border);
+
+ /* actually set border */
+ CLAMP(border.xmin, 0.0f, 1.0f);
+ CLAMP(border.ymin, 0.0f, 1.0f);
+ CLAMP(border.xmax, 0.0f, 1.0f);
+ CLAMP(border.ymax, 0.0f, 1.0f);
+ scene->r.border = border;
+
+ /* drawing a border surrounding the entire camera view switches off border rendering
+ * or the border covers no pixels */
+ if ((border.xmin <= 0.0f && border.xmax >= 1.0f && border.ymin <= 0.0f && border.ymax >= 1.0f) ||
+ (border.xmin == border.xmax || border.ymin == border.ymax)) {
+ scene->r.mode &= ~R_BORDER;
+ }
+ else {
+ scene->r.mode |= R_BORDER;
+ }
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
+ return OPERATOR_FINISHED;
}
void IMAGE_OT_render_border(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Render Region";
- ot->description = "Set the boundaries of the render region and enable render region";
- ot->idname = "IMAGE_OT_render_border";
+ /* identifiers */
+ ot->name = "Render Region";
+ ot->description = "Set the boundaries of the render region and enable render region";
+ ot->idname = "IMAGE_OT_render_border";
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = render_border_exec;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
- ot->poll = image_cycle_render_slot_poll;
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = render_border_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
+ ot->poll = image_cycle_render_slot_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* rna */
- WM_operator_properties_border(ot);
+ /* rna */
+ WM_operator_properties_border(ot);
}
/* ********************* Clear render border operator ****************** */
static int clear_render_border_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- scene->r.mode &= ~R_BORDER;
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL);
- BLI_rctf_init(&scene->r.border, 0.0f, 1.0f, 0.0f, 1.0f);
- return OPERATOR_FINISHED;
-
+ Scene *scene = CTX_data_scene(C);
+ scene->r.mode &= ~R_BORDER;
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ BLI_rctf_init(&scene->r.border, 0.0f, 1.0f, 0.0f, 1.0f);
+ return OPERATOR_FINISHED;
}
void IMAGE_OT_clear_render_border(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Render Region";
- ot->description = "Clear the boundaries of the render region and disable render region";
- ot->idname = "IMAGE_OT_clear_render_border";
+ /* identifiers */
+ ot->name = "Clear Render Region";
+ ot->description = "Clear the boundaries of the render region and disable render region";
+ ot->idname = "IMAGE_OT_clear_render_border";
- /* api callbacks */
- ot->exec = clear_render_border_exec;
- ot->poll = image_cycle_render_slot_poll;
+ /* api callbacks */
+ ot->exec = clear_render_border_exec;
+ ot->poll = image_cycle_render_slot_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index d5eb0b485a1..e1875fd6129 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -64,7 +64,6 @@
#include "ED_uvedit.h"
#include "ED_transform.h"
-
#include "WM_api.h"
#include "WM_types.h"
#include "WM_message.h"
@@ -86,254 +85,255 @@
static void image_scopes_tag_refresh(ScrArea *sa)
{
- SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
- ARegion *ar;
+ SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
+ ARegion *ar;
- /* 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) {
- return;
- }
- }
+ /* 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) {
+ return;
+ }
+ }
- sima->scopes.ok = 0;
+ sima->scopes.ok = 0;
}
static void image_user_refresh_scene(const bContext *C, SpaceImage *sima)
{
- /* Update scene image user for acquiring render results. */
- sima->iuser.scene = CTX_data_scene(C);
-
- if (sima->image && sima->image->type == IMA_TYPE_R_RESULT) {
- /* While rendering, prefer scene that is being rendered. */
- Scene *render_scene = ED_render_job_get_current_scene(C);
- if (render_scene) {
- sima->iuser.scene = render_scene;
- }
- }
-
- /* Auto switch image to show in UV editor when selection changes. */
- ED_space_image_auto_set(C, sima);
+ /* Update scene image user for acquiring render results. */
+ sima->iuser.scene = CTX_data_scene(C);
+
+ if (sima->image && sima->image->type == IMA_TYPE_R_RESULT) {
+ /* While rendering, prefer scene that is being rendered. */
+ Scene *render_scene = ED_render_job_get_current_scene(C);
+ if (render_scene) {
+ sima->iuser.scene = render_scene;
+ }
+ }
+
+ /* Auto switch image to show in UV editor when selection changes. */
+ ED_space_image_auto_set(C, sima);
}
/* ******************** manage regions ********************* */
ARegion *image_has_buttons_region(ScrArea *sa)
{
- ARegion *ar, *arnew;
+ ARegion *ar, *arnew;
- ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
- if (ar) {
- return ar;
- }
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
+ if (ar) {
+ return ar;
+ }
- /* add subdiv level; after header */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+ /* add subdiv level; after header */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
- /* is error! */
- if (ar == NULL) {
- return NULL;
- }
+ /* is error! */
+ if (ar == NULL) {
+ return NULL;
+ }
- arnew = MEM_callocN(sizeof(ARegion), "buttons for image");
+ arnew = MEM_callocN(sizeof(ARegion), "buttons for image");
- BLI_insertlinkafter(&sa->regionbase, ar, arnew);
- arnew->regiontype = RGN_TYPE_UI;
- arnew->alignment = RGN_ALIGN_RIGHT;
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype = RGN_TYPE_UI;
+ arnew->alignment = RGN_ALIGN_RIGHT;
- arnew->flag = RGN_FLAG_HIDDEN;
+ arnew->flag = RGN_FLAG_HIDDEN;
- return arnew;
+ return arnew;
}
ARegion *image_has_tools_region(ScrArea *sa)
{
- ARegion *ar, *arnew;
+ ARegion *ar, *arnew;
- ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
- if (ar) {
- return ar;
- }
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
+ if (ar) {
+ return ar;
+ }
- /* add subdiv level; after buttons */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
+ /* add subdiv level; after buttons */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
- /* is error! */
- if (ar == NULL) {
- return NULL;
- }
+ /* is error! */
+ if (ar == NULL) {
+ return NULL;
+ }
- arnew = MEM_callocN(sizeof(ARegion), "scopes for image");
+ arnew = MEM_callocN(sizeof(ARegion), "scopes for image");
- BLI_insertlinkafter(&sa->regionbase, ar, arnew);
- arnew->regiontype = RGN_TYPE_TOOLS;
- arnew->alignment = RGN_ALIGN_LEFT;
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype = RGN_TYPE_TOOLS;
+ arnew->alignment = RGN_ALIGN_LEFT;
- arnew->flag = RGN_FLAG_HIDDEN;
+ arnew->flag = RGN_FLAG_HIDDEN;
- image_scopes_tag_refresh(sa);
+ image_scopes_tag_refresh(sa);
- return arnew;
+ return arnew;
}
/* ******************** default callbacks for image space ***************** */
static SpaceLink *image_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
- SpaceImage *simage;
+ ARegion *ar;
+ SpaceImage *simage;
- simage = MEM_callocN(sizeof(SpaceImage), "initimage");
- simage->spacetype = SPACE_IMAGE;
- simage->zoom = 1.0f;
- simage->lock = true;
- simage->flag = SI_SHOW_GPENCIL | SI_USE_ALPHA | SI_COORDFLOATS;
+ simage = MEM_callocN(sizeof(SpaceImage), "initimage");
+ simage->spacetype = SPACE_IMAGE;
+ simage->zoom = 1.0f;
+ simage->lock = true;
+ simage->flag = SI_SHOW_GPENCIL | SI_USE_ALPHA | SI_COORDFLOATS;
- simage->iuser.ok = true;
- simage->iuser.frames = 100;
- simage->iuser.flag = IMA_SHOW_STEREO | IMA_ANIM_ALWAYS;
+ simage->iuser.ok = true;
+ simage->iuser.frames = 100;
+ simage->iuser.flag = IMA_SHOW_STEREO | IMA_ANIM_ALWAYS;
- scopes_new(&simage->scopes);
- simage->sample_line_hist.height = 100;
+ scopes_new(&simage->scopes);
+ simage->sample_line_hist.height = 100;
- /* header */
- ar = MEM_callocN(sizeof(ARegion), "header for image");
+ /* header */
+ ar = 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, 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 image");
+ /* buttons/list view */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_UI;
+ ar->alignment = RGN_ALIGN_RIGHT;
+ ar->flag = RGN_FLAG_HIDDEN;
- /* scopes/uv sculpt/paint */
- ar = MEM_callocN(sizeof(ARegion), "buttons for image");
+ /* scopes/uv sculpt/paint */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_TOOLS;
+ ar->alignment = RGN_ALIGN_LEFT;
+ ar->flag = RGN_FLAG_HIDDEN;
- /* main area */
- ar = MEM_callocN(sizeof(ARegion), "main area for image");
+ /* main area */
+ ar = MEM_callocN(sizeof(ARegion), "main area for image");
- BLI_addtail(&simage->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&simage->regionbase, ar);
+ ar->regiontype = RGN_TYPE_WINDOW;
- return (SpaceLink *)simage;
+ return (SpaceLink *)simage;
}
/* not spacelink itself */
static void image_free(SpaceLink *sl)
{
- SpaceImage *simage = (SpaceImage *) sl;
+ SpaceImage *simage = (SpaceImage *)sl;
- scopes_free(&simage->scopes);
+ scopes_free(&simage->scopes);
}
-
/* spacetype; init callback, add handlers */
static void image_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
{
- ListBase *lb = WM_dropboxmap_find("Image", SPACE_IMAGE, 0);
-
- /* add drop boxes */
- WM_event_add_dropbox_handler(&sa->handlers, lb);
+ ListBase *lb = WM_dropboxmap_find("Image", SPACE_IMAGE, 0);
+ /* add drop boxes */
+ WM_event_add_dropbox_handler(&sa->handlers, lb);
}
static SpaceLink *image_duplicate(SpaceLink *sl)
{
- SpaceImage *simagen = MEM_dupallocN(sl);
+ SpaceImage *simagen = MEM_dupallocN(sl);
- /* clear or remove stuff from old */
+ /* clear or remove stuff from old */
- scopes_new(&simagen->scopes);
+ scopes_new(&simagen->scopes);
- return (SpaceLink *)simagen;
+ return (SpaceLink *)simagen;
}
static void image_operatortypes(void)
{
- WM_operatortype_append(IMAGE_OT_view_all);
- WM_operatortype_append(IMAGE_OT_view_pan);
- WM_operatortype_append(IMAGE_OT_view_selected);
- WM_operatortype_append(IMAGE_OT_view_zoom);
- WM_operatortype_append(IMAGE_OT_view_zoom_in);
- WM_operatortype_append(IMAGE_OT_view_zoom_out);
- WM_operatortype_append(IMAGE_OT_view_zoom_ratio);
- WM_operatortype_append(IMAGE_OT_view_zoom_border);
+ WM_operatortype_append(IMAGE_OT_view_all);
+ WM_operatortype_append(IMAGE_OT_view_pan);
+ WM_operatortype_append(IMAGE_OT_view_selected);
+ WM_operatortype_append(IMAGE_OT_view_zoom);
+ WM_operatortype_append(IMAGE_OT_view_zoom_in);
+ WM_operatortype_append(IMAGE_OT_view_zoom_out);
+ WM_operatortype_append(IMAGE_OT_view_zoom_ratio);
+ WM_operatortype_append(IMAGE_OT_view_zoom_border);
#ifdef WITH_INPUT_NDOF
- WM_operatortype_append(IMAGE_OT_view_ndof);
+ WM_operatortype_append(IMAGE_OT_view_ndof);
#endif
- WM_operatortype_append(IMAGE_OT_new);
- WM_operatortype_append(IMAGE_OT_open);
- WM_operatortype_append(IMAGE_OT_match_movie_length);
- WM_operatortype_append(IMAGE_OT_replace);
- WM_operatortype_append(IMAGE_OT_reload);
- WM_operatortype_append(IMAGE_OT_save);
- WM_operatortype_append(IMAGE_OT_save_as);
- WM_operatortype_append(IMAGE_OT_save_sequence);
- WM_operatortype_append(IMAGE_OT_pack);
- WM_operatortype_append(IMAGE_OT_unpack);
+ WM_operatortype_append(IMAGE_OT_new);
+ WM_operatortype_append(IMAGE_OT_open);
+ WM_operatortype_append(IMAGE_OT_match_movie_length);
+ WM_operatortype_append(IMAGE_OT_replace);
+ WM_operatortype_append(IMAGE_OT_reload);
+ WM_operatortype_append(IMAGE_OT_save);
+ WM_operatortype_append(IMAGE_OT_save_as);
+ WM_operatortype_append(IMAGE_OT_save_sequence);
+ WM_operatortype_append(IMAGE_OT_pack);
+ WM_operatortype_append(IMAGE_OT_unpack);
- WM_operatortype_append(IMAGE_OT_invert);
+ WM_operatortype_append(IMAGE_OT_invert);
- WM_operatortype_append(IMAGE_OT_cycle_render_slot);
- WM_operatortype_append(IMAGE_OT_clear_render_slot);
- WM_operatortype_append(IMAGE_OT_add_render_slot);
- WM_operatortype_append(IMAGE_OT_remove_render_slot);
+ WM_operatortype_append(IMAGE_OT_cycle_render_slot);
+ WM_operatortype_append(IMAGE_OT_clear_render_slot);
+ WM_operatortype_append(IMAGE_OT_add_render_slot);
+ WM_operatortype_append(IMAGE_OT_remove_render_slot);
- WM_operatortype_append(IMAGE_OT_sample);
- WM_operatortype_append(IMAGE_OT_sample_line);
- WM_operatortype_append(IMAGE_OT_curves_point_set);
+ WM_operatortype_append(IMAGE_OT_sample);
+ WM_operatortype_append(IMAGE_OT_sample_line);
+ WM_operatortype_append(IMAGE_OT_curves_point_set);
- WM_operatortype_append(IMAGE_OT_properties);
- WM_operatortype_append(IMAGE_OT_toolshelf);
+ WM_operatortype_append(IMAGE_OT_properties);
+ WM_operatortype_append(IMAGE_OT_toolshelf);
- WM_operatortype_append(IMAGE_OT_change_frame);
+ WM_operatortype_append(IMAGE_OT_change_frame);
- WM_operatortype_append(IMAGE_OT_read_viewlayers);
- WM_operatortype_append(IMAGE_OT_render_border);
- WM_operatortype_append(IMAGE_OT_clear_render_border);
+ WM_operatortype_append(IMAGE_OT_read_viewlayers);
+ WM_operatortype_append(IMAGE_OT_render_border);
+ WM_operatortype_append(IMAGE_OT_clear_render_border);
}
static void image_keymap(struct wmKeyConfig *keyconf)
{
- WM_keymap_ensure(keyconf, "Image Generic", SPACE_IMAGE, 0);
- WM_keymap_ensure(keyconf, "Image", SPACE_IMAGE, 0);
+ WM_keymap_ensure(keyconf, "Image Generic", SPACE_IMAGE, 0);
+ WM_keymap_ensure(keyconf, "Image", SPACE_IMAGE, 0);
}
/* dropboxes */
-static bool image_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
+static bool image_drop_poll(bContext *UNUSED(C),
+ wmDrag *drag,
+ const wmEvent *UNUSED(event),
+ const char **UNUSED(tooltip))
{
- 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 0;
+ 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 0;
}
static void image_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- /* copy drag path to properties */
- RNA_string_set(drop->ptr, "filepath", drag->path);
+ /* copy drag path to properties */
+ RNA_string_set(drop->ptr, "filepath", drag->path);
}
/* area+region dropbox definition */
static void image_dropboxes(void)
{
- ListBase *lb = WM_dropboxmap_find("Image", SPACE_IMAGE, 0);
+ ListBase *lb = WM_dropboxmap_find("Image", SPACE_IMAGE, 0);
- WM_dropbox_add(lb, "IMAGE_OT_open", image_drop_poll, image_drop_copy);
+ WM_dropbox_add(lb, "IMAGE_OT_open", image_drop_poll, image_drop_copy);
}
/**
@@ -342,192 +342,187 @@ static void image_dropboxes(void)
*/
static void image_refresh(const bContext *C, ScrArea *sa)
{
- Scene *scene = CTX_data_scene(C);
- SpaceImage *sima = sa->spacedata.first;
- Image *ima;
-
- ima = ED_space_image(sima);
-
- BKE_image_user_frame_calc(&sima->iuser, scene->r.cfra);
-
- /* check if we have to set the image from the editmesh */
- if (ima && (ima->source == IMA_SRC_VIEWER && sima->mode == SI_MODE_MASK)) {
- if (scene->nodetree) {
- Mask *mask = ED_space_image_get_mask(sima);
- if (mask) {
- ED_node_composite_job(C, scene->nodetree, scene);
- }
- }
- }
+ Scene *scene = CTX_data_scene(C);
+ SpaceImage *sima = sa->spacedata.first;
+ Image *ima;
+
+ ima = ED_space_image(sima);
+
+ BKE_image_user_frame_calc(&sima->iuser, scene->r.cfra);
+
+ /* check if we have to set the image from the editmesh */
+ if (ima && (ima->source == IMA_SRC_VIEWER && sima->mode == SI_MODE_MASK)) {
+ if (scene->nodetree) {
+ Mask *mask = ED_space_image_get_mask(sima);
+ if (mask) {
+ ED_node_composite_job(C, scene->nodetree, scene);
+ }
+ }
+ }
}
static void image_listener(wmWindow *win, ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene))
{
- SpaceImage *sima = (SpaceImage *)sa->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);
- 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);
- break;
- case ND_MODE:
- if (wmn->subtype == NS_EDITMODE_MESH) {
- ED_area_tag_refresh(sa);
- }
- ED_area_tag_redraw(sa);
- 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);
- }
- ED_area_tag_redraw(sa);
- 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);
- }
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_IMAGE) {
- image_scopes_tag_refresh(sa);
- ED_area_tag_redraw(sa);
- }
- break;
- case NC_MASK:
- {
- // Scene *scene = wmn->window->screen->scene;
- /* ideally would check for: ED_space_image_check_show_maskedit(scene, sima)
- * but we cant get the scene */
- if (sima->mode == SI_MODE_MASK) {
- switch (wmn->data) {
- case ND_SELECT:
- ED_area_tag_redraw(sa);
- break;
- case ND_DATA:
- case ND_DRAW:
- /* causes node-recalc */
- ED_area_tag_redraw(sa);
- ED_area_tag_refresh(sa);
- break;
- }
- switch (wmn->action) {
- case NA_SELECTED:
- ED_area_tag_redraw(sa);
- break;
- case NA_EDITED:
- /* causes node-recalc */
- ED_area_tag_redraw(sa);
- ED_area_tag_refresh(sa);
- break;
- }
- }
- break;
- }
- case NC_GEOM:
- {
- switch (wmn->data) {
- case ND_DATA:
- case ND_SELECT:
- image_scopes_tag_refresh(sa);
- ED_area_tag_refresh(sa);
- ED_area_tag_redraw(sa);
- break;
- }
- break;
- }
- case NC_OBJECT:
- {
- switch (wmn->data) {
- case ND_TRANSFORM:
- case ND_MODIFIER:
- {
- ViewLayer *view_layer = WM_window_get_active_view_layer(win);
- 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);
- }
- }
- break;
- }
- }
-
- break;
- }
- case NC_ID:
- {
- if (wmn->action == NA_RENAME) {
- ED_area_tag_redraw(sa);
- }
- break;
- }
- case NC_WM:
- if (wmn->data == ND_UNDO) {
- ED_area_tag_redraw(sa);
- ED_area_tag_refresh(sa);
- }
- break;
- }
+ SpaceImage *sima = (SpaceImage *)sa->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);
+ 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);
+ break;
+ case ND_MODE:
+ if (wmn->subtype == NS_EDITMODE_MESH) {
+ ED_area_tag_refresh(sa);
+ }
+ ED_area_tag_redraw(sa);
+ 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);
+ }
+ ED_area_tag_redraw(sa);
+ 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);
+ }
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_IMAGE) {
+ image_scopes_tag_refresh(sa);
+ ED_area_tag_redraw(sa);
+ }
+ break;
+ case NC_MASK: {
+ // Scene *scene = wmn->window->screen->scene;
+ /* ideally would check for: ED_space_image_check_show_maskedit(scene, sima)
+ * but we cant get the scene */
+ if (sima->mode == SI_MODE_MASK) {
+ switch (wmn->data) {
+ case ND_SELECT:
+ ED_area_tag_redraw(sa);
+ break;
+ case ND_DATA:
+ case ND_DRAW:
+ /* causes node-recalc */
+ ED_area_tag_redraw(sa);
+ ED_area_tag_refresh(sa);
+ break;
+ }
+ switch (wmn->action) {
+ case NA_SELECTED:
+ ED_area_tag_redraw(sa);
+ break;
+ case NA_EDITED:
+ /* causes node-recalc */
+ ED_area_tag_redraw(sa);
+ ED_area_tag_refresh(sa);
+ break;
+ }
+ }
+ break;
+ }
+ case NC_GEOM: {
+ switch (wmn->data) {
+ case ND_DATA:
+ case ND_SELECT:
+ image_scopes_tag_refresh(sa);
+ ED_area_tag_refresh(sa);
+ ED_area_tag_redraw(sa);
+ break;
+ }
+ break;
+ }
+ case NC_OBJECT: {
+ switch (wmn->data) {
+ case ND_TRANSFORM:
+ case ND_MODIFIER: {
+ ViewLayer *view_layer = WM_window_get_active_view_layer(win);
+ 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);
+ }
+ }
+ break;
+ }
+ }
+
+ break;
+ }
+ case NC_ID: {
+ if (wmn->action == NA_RENAME) {
+ ED_area_tag_redraw(sa);
+ }
+ break;
+ }
+ case NC_WM:
+ if (wmn->data == ND_UNDO) {
+ ED_area_tag_redraw(sa);
+ ED_area_tag_refresh(sa);
+ }
+ break;
+ }
}
const char *image_context_dir[] = {"edit_image", "edit_mask", NULL};
static int image_context(const bContext *C, const char *member, bContextDataResult *result)
{
- SpaceImage *sima = CTX_wm_space_image(C);
-
- if (CTX_data_dir(member)) {
- CTX_data_dir_set(result, image_context_dir);
- }
- else if (CTX_data_equals(member, "edit_image")) {
- CTX_data_id_pointer_set(result, (ID *)ED_space_image(sima));
- return 1;
- }
- else if (CTX_data_equals(member, "edit_mask")) {
- Mask *mask = ED_space_image_get_mask(sima);
- if (mask) {
- CTX_data_id_pointer_set(result, &mask->id);
- }
- return true;
- }
- return 0;
+ SpaceImage *sima = CTX_wm_space_image(C);
+
+ if (CTX_data_dir(member)) {
+ CTX_data_dir_set(result, image_context_dir);
+ }
+ else if (CTX_data_equals(member, "edit_image")) {
+ CTX_data_id_pointer_set(result, (ID *)ED_space_image(sima));
+ return 1;
+ }
+ else if (CTX_data_equals(member, "edit_mask")) {
+ Mask *mask = ED_space_image_get_mask(sima);
+ if (mask) {
+ CTX_data_id_pointer_set(result, &mask->id);
+ }
+ return true;
+ }
+ return 0;
}
static void IMAGE_GGT_gizmo2d(wmGizmoGroupType *gzgt)
{
- gzgt->name = "UV Transform Gizmo";
- gzgt->idname = "IMAGE_GGT_gizmo2d";
+ gzgt->name = "UV Transform Gizmo";
+ gzgt->idname = "IMAGE_GGT_gizmo2d";
- gzgt->gzmap_params.spaceid = SPACE_IMAGE;
- gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_IMAGE;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- gzgt->poll = ED_widgetgroup_gizmo2d_poll;
- gzgt->setup = ED_widgetgroup_gizmo2d_setup;
- gzgt->refresh = ED_widgetgroup_gizmo2d_refresh;
- gzgt->draw_prepare = ED_widgetgroup_gizmo2d_draw_prepare;
+ gzgt->poll = ED_widgetgroup_gizmo2d_poll;
+ gzgt->setup = ED_widgetgroup_gizmo2d_setup;
+ gzgt->refresh = ED_widgetgroup_gizmo2d_refresh;
+ gzgt->draw_prepare = ED_widgetgroup_gizmo2d_draw_prepare;
}
static void image_widgets(void)
{
- WM_gizmogrouptype_append(IMAGE_GGT_gizmo2d);
+ WM_gizmogrouptype_append(IMAGE_GGT_gizmo2d);
}
/************************** main region ***************************/
@@ -535,261 +530,266 @@ static void image_widgets(void)
/* sets up the fields of the View2D from zoom and offset */
static void image_main_region_set_view2d(SpaceImage *sima, ARegion *ar)
{
- Image *ima = ED_space_image(sima);
+ Image *ima = ED_space_image(sima);
- int width, height;
- ED_space_image_get_size(sima, &width, &height);
+ int width, height;
+ ED_space_image_get_size(sima, &width, &height);
- float w = width;
- float h = height;
+ float w = width;
+ float h = height;
- if (ima) {
- h *= ima->aspy / ima->aspx;
- }
+ if (ima) {
+ 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(&ar->winrct) + 1;
+ int winy = BLI_rcti_size_y(&ar->winrct) + 1;
- /* For region overlap, move center so image doesn't overlap header. */
- rcti visible_rect;
- ED_region_visible_rect(ar, &visible_rect);
- 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;
+ /* For region overlap, move center so image doesn't overlap header. */
+ rcti visible_rect;
+ ED_region_visible_rect(ar, &visible_rect);
+ 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;
+ ar->v2d.tot.xmin = 0;
+ ar->v2d.tot.ymin = 0;
+ ar->v2d.tot.xmax = w;
+ ar->v2d.tot.ymax = h;
- ar->v2d.mask.xmin = ar->v2d.mask.ymin = 0;
- ar->v2d.mask.xmax = winx;
- ar->v2d.mask.ymax = winy;
+ ar->v2d.mask.xmin = ar->v2d.mask.ymin = 0;
+ ar->v2d.mask.xmax = winx;
+ ar->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;
+ /* 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;
- x1 -= sima->zoom * sima->xof;
- y1 -= sima->zoom * sima->yof;
+ 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);
+ /* 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);
- /* 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);
+ /* 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);
- /* 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;
+ /* 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;
}
/* add handlers, stuff you only do once or on area/region changes */
static void image_main_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- // image space manages own v2d
- // UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
+ // image space manages own v2d
+ // UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
- /* mask polls mode */
- keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", 0, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ /* mask polls mode */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", 0, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- /* image paint polls for mode */
- keymap = WM_keymap_ensure(wm->defaultconf, "Curve", 0, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ /* image paint polls for mode */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Curve", 0, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- keymap = WM_keymap_ensure(wm->defaultconf, "Paint Curve", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Paint Curve", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
- keymap = WM_keymap_ensure(wm->defaultconf, "Image Paint", 0, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Image Paint", 0, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- keymap = WM_keymap_ensure(wm->defaultconf, "UV Editor", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "UV Editor", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
- keymap = WM_keymap_ensure(wm->defaultconf, "UV Sculpt", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "UV Sculpt", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
- /* own keymaps */
- keymap = WM_keymap_ensure(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
- keymap = WM_keymap_ensure(wm->defaultconf, "Image", SPACE_IMAGE, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ /* own keymaps */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Image", SPACE_IMAGE, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
static void image_main_region_draw(const bContext *C, ARegion *ar)
{
- /* draw entirely, view changes should be handled here */
- SpaceImage *sima = CTX_wm_space_image(C);
- Object *obact = CTX_data_active_object(C);
- Object *obedit = CTX_data_edit_object(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Mask *mask = NULL;
- bool curve = false;
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View2D *v2d = &ar->v2d;
- //View2DScrollers *scrollers;
- float col[3];
-
- /* XXX This is in order to draw UI batches with the DRW
- * olg context since we now use it for drawing the entire area */
- gpu_batch_presets_reset();
-
- /* TODO(fclem) port to draw manager and remove the depth buffer allocation. */
- GPUViewport *viewport = ar->draw_buffer->viewport[ar->draw_buffer->stereo ? sima->iuser.multiview_eye : 0];
- DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport);
- GPU_framebuffer_bind(fbl->color_only_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.0);
- GPU_clear(GPU_COLOR_BIT);
-
- image_user_refresh_scene(C, sima);
-
- /* we set view2d from own zoom and offset each time */
- image_main_region_set_view2d(sima, ar);
-
- /* we draw image in pixelspace */
- draw_image_main(C, ar);
-
- /* 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_uvedit_draw_main(sima, ar, scene, view_layer, obedit, obact, depsgraph);
-
- /* check for mask (delay draw) */
- if (ED_space_image_show_uvedit(sima, obedit)) {
- /* pass */
- }
- else if (sima->mode == SI_MODE_MASK) {
- mask = ED_space_image_get_mask(sima);
- }
- else if (ED_space_image_paint_curve(C)) {
- curve = true;
- }
-
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
-
- if (sima->flag & SI_SHOW_GPENCIL) {
- /* Grease Pencil too (in addition to UV's) */
- draw_image_grease_pencil((bContext *)C, true);
- }
-
- /* sample line */
- draw_image_sample_line(sima);
-
- UI_view2d_view_restore(C);
-
- if (sima->flag & SI_SHOW_GPENCIL) {
- /* draw Grease Pencil - screen space only */
- draw_image_grease_pencil((bContext *)C, false);
- }
-
- if (mask) {
- Image *image = ED_space_image(sima);
- int width, height, show_viewer;
- float aspx, aspy;
-
- show_viewer = (image && image->source == IMA_SRC_VIEWER);
-
- if (show_viewer) {
- /* ED_space_image_get* will acquire image buffer which requires
- * lock here by the same reason why lock is needed in draw_image_main
- */
- BLI_thread_lock(LOCK_DRAW_IMAGE);
- }
-
- ED_space_image_get_size(sima, &width, &height);
- ED_space_image_get_aspect(sima, &aspx, &aspy);
-
- if (show_viewer) {
- BLI_thread_unlock(LOCK_DRAW_IMAGE);
- }
-
- ED_mask_draw_region(mask, ar,
- sima->mask_info.draw_flag,
- sima->mask_info.draw_type,
- sima->mask_info.overlay_mode,
- width, height,
- aspx, aspy,
- true, false,
- NULL, C);
-
- UI_view2d_view_ortho(v2d);
- ED_image_draw_cursor(ar, sima->cursor);
- UI_view2d_view_restore(C);
- }
- else if (curve) {
- UI_view2d_view_ortho(v2d);
- ED_image_draw_cursor(ar, sima->cursor);
- UI_view2d_view_restore(C);
- }
-
- WM_gizmomap_draw(ar->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
-
- draw_image_cache(C, ar);
-
- /* scrollers? */
+ /* draw entirely, view changes should be handled here */
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Object *obact = CTX_data_active_object(C);
+ Object *obedit = CTX_data_edit_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Mask *mask = NULL;
+ bool curve = false;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View2D *v2d = &ar->v2d;
+ //View2DScrollers *scrollers;
+ float col[3];
+
+ /* XXX This is in order to draw UI batches with the DRW
+ * olg context since we now use it for drawing the entire area */
+ gpu_batch_presets_reset();
+
+ /* TODO(fclem) port to draw manager and remove the depth buffer allocation. */
+ GPUViewport *viewport =
+ ar->draw_buffer->viewport[ar->draw_buffer->stereo ? sima->iuser.multiview_eye : 0];
+ DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport);
+ GPU_framebuffer_bind(fbl->color_only_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.0);
+ GPU_clear(GPU_COLOR_BIT);
+
+ image_user_refresh_scene(C, sima);
+
+ /* we set view2d from own zoom and offset each time */
+ image_main_region_set_view2d(sima, ar);
+
+ /* we draw image in pixelspace */
+ draw_image_main(C, ar);
+
+ /* 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_uvedit_draw_main(sima, ar, scene, view_layer, obedit, obact, depsgraph);
+
+ /* check for mask (delay draw) */
+ if (ED_space_image_show_uvedit(sima, obedit)) {
+ /* pass */
+ }
+ else if (sima->mode == SI_MODE_MASK) {
+ mask = ED_space_image_get_mask(sima);
+ }
+ else if (ED_space_image_paint_curve(C)) {
+ curve = true;
+ }
+
+ ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+
+ if (sima->flag & SI_SHOW_GPENCIL) {
+ /* Grease Pencil too (in addition to UV's) */
+ draw_image_grease_pencil((bContext *)C, true);
+ }
+
+ /* sample line */
+ draw_image_sample_line(sima);
+
+ UI_view2d_view_restore(C);
+
+ if (sima->flag & SI_SHOW_GPENCIL) {
+ /* draw Grease Pencil - screen space only */
+ draw_image_grease_pencil((bContext *)C, false);
+ }
+
+ if (mask) {
+ Image *image = ED_space_image(sima);
+ int width, height, show_viewer;
+ float aspx, aspy;
+
+ show_viewer = (image && image->source == IMA_SRC_VIEWER);
+
+ if (show_viewer) {
+ /* ED_space_image_get* will acquire image buffer which requires
+ * lock here by the same reason why lock is needed in draw_image_main
+ */
+ BLI_thread_lock(LOCK_DRAW_IMAGE);
+ }
+
+ ED_space_image_get_size(sima, &width, &height);
+ ED_space_image_get_aspect(sima, &aspx, &aspy);
+
+ if (show_viewer) {
+ BLI_thread_unlock(LOCK_DRAW_IMAGE);
+ }
+
+ ED_mask_draw_region(mask,
+ ar,
+ sima->mask_info.draw_flag,
+ sima->mask_info.draw_type,
+ sima->mask_info.overlay_mode,
+ width,
+ height,
+ aspx,
+ aspy,
+ true,
+ false,
+ NULL,
+ C);
+
+ UI_view2d_view_ortho(v2d);
+ ED_image_draw_cursor(ar, sima->cursor);
+ UI_view2d_view_restore(C);
+ }
+ else if (curve) {
+ UI_view2d_view_ortho(v2d);
+ ED_image_draw_cursor(ar, sima->cursor);
+ UI_view2d_view_restore(C);
+ }
+
+ WM_gizmomap_draw(ar->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
+
+ draw_image_cache(C, ar);
+
+ /* scrollers? */
#if 0
- scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_UNIT_VALUES, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
+ scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_UNIT_VALUES, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
#endif
}
static void image_main_region_listener(
- wmWindow *UNUSED(win), ScrArea *sa, ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+ wmWindow *UNUSED(win), ScrArea *sa, ARegion *ar, 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);
- }
- break;
- case NC_GPENCIL:
- if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
- }
- else if (wmn->data & ND_GPENCIL_EDITMODE) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_IMAGE:
- if (wmn->action == NA_PAINTING) {
- ED_region_tag_redraw(ar);
- }
- WM_gizmomap_tag_refresh(ar->gizmo_map);
- break;
- case NC_MATERIAL:
- if (wmn->data == ND_SHADING_LINKS) {
- SpaceImage *sima = sa->spacedata.first;
-
- if (sima->iuser.scene && (sima->iuser.scene->toolsettings->uv_flag & UV_SHOW_SAME_IMAGE)) {
- ED_region_tag_redraw(ar);
- }
- }
- break;
- case NC_SCREEN:
- if (ELEM(wmn->data, ND_LAYER)) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_GEOM:
+ if (ELEM(wmn->data, ND_DATA, ND_SELECT)) {
+ WM_gizmomap_tag_refresh(ar->gizmo_map);
+ }
+ break;
+ case NC_GPENCIL:
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
+ ED_region_tag_redraw(ar);
+ }
+ else if (wmn->data & ND_GPENCIL_EDITMODE) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_IMAGE:
+ if (wmn->action == NA_PAINTING) {
+ ED_region_tag_redraw(ar);
+ }
+ WM_gizmomap_tag_refresh(ar->gizmo_map);
+ break;
+ case NC_MATERIAL:
+ if (wmn->data == ND_SHADING_LINKS) {
+ SpaceImage *sima = sa->spacedata.first;
+
+ if (sima->iuser.scene && (sima->iuser.scene->toolsettings->uv_flag & UV_SHOW_SAME_IMAGE)) {
+ ED_region_tag_redraw(ar);
+ }
+ }
+ break;
+ case NC_SCREEN:
+ if (ELEM(wmn->data, ND_LAYER)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
}
/* *********************** buttons region ************************ */
@@ -797,78 +797,81 @@ static void image_main_region_listener(
/* add handlers, stuff you only do once or on area/region changes */
static void image_buttons_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
- ED_region_panels_init(wm, ar);
+ ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
+ ED_region_panels_init(wm, ar);
- keymap = WM_keymap_ensure(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
}
static void image_buttons_region_draw(const bContext *C, ARegion *ar)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- Scene *scene = CTX_data_scene(C);
- void *lock;
- ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
- /* XXX performance regression if name of scopes category changes! */
- PanelCategoryStack *category = UI_panel_category_active_find(ar, "Scopes");
-
- /* only update scopes if scope category is active */
- if (category) {
- if (ibuf) {
- if (!sima->scopes.ok) {
- BKE_histogram_update_sample_line(&sima->sample_line_hist, ibuf, &scene->view_settings, &scene->display_settings);
- }
- if (sima->image->flag & IMA_VIEW_AS_RENDER) {
- ED_space_image_scopes_update(C, sima, ibuf, true);
- }
- else {
- ED_space_image_scopes_update(C, sima, ibuf, false);
- }
- }
- }
- ED_space_image_release_buffer(sima, ibuf, lock);
-
- ED_region_panels(C, ar);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Scene *scene = CTX_data_scene(C);
+ void *lock;
+ ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
+ /* XXX performance regression if name of scopes category changes! */
+ PanelCategoryStack *category = UI_panel_category_active_find(ar, "Scopes");
+
+ /* only update scopes if scope category is active */
+ if (category) {
+ if (ibuf) {
+ if (!sima->scopes.ok) {
+ BKE_histogram_update_sample_line(
+ &sima->sample_line_hist, ibuf, &scene->view_settings, &scene->display_settings);
+ }
+ if (sima->image->flag & IMA_VIEW_AS_RENDER) {
+ ED_space_image_scopes_update(C, sima, ibuf, true);
+ }
+ else {
+ ED_space_image_scopes_update(C, sima, ibuf, false);
+ }
+ }
+ }
+ ED_space_image_release_buffer(sima, ibuf, lock);
+
+ ED_region_panels(C, ar);
}
-static void image_buttons_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void image_buttons_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_TEXTURE:
- case NC_MATERIAL:
- /* sending by texture render job and needed to properly update displaying
- * brush texture icon */
- ED_region_tag_redraw(ar);
- break;
- case NC_SCENE:
- switch (wmn->data) {
- case ND_MODE:
- case ND_RENDER_RESULT:
- case ND_COMPO_RESULT:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_IMAGE:
- if (wmn->action != NA_PAINTING) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_NODE:
- ED_region_tag_redraw(ar);
- break;
- case NC_GPENCIL:
- if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_TEXTURE:
+ case NC_MATERIAL:
+ /* sending by texture render job and needed to properly update displaying
+ * brush texture icon */
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_MODE:
+ case ND_RENDER_RESULT:
+ case ND_COMPO_RESULT:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_IMAGE:
+ if (wmn->action != NA_PAINTING) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_NODE:
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_GPENCIL:
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
}
/* *********************** scopes region ************************ */
@@ -876,56 +879,57 @@ static void image_buttons_region_listener(
/* add handlers, stuff you only do once or on area/region changes */
static void image_tools_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
- ED_region_panels_init(wm, ar);
+ ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
+ ED_region_panels_init(wm, ar);
- keymap = WM_keymap_ensure(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
}
static void image_tools_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, ar);
}
-static void image_tools_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void image_tools_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_GPENCIL:
- if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_BRUSH:
- /* NA_SELECTED is used on brush changes */
- if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SCENE:
- switch (wmn->data) {
- case ND_MODE:
- case ND_RENDER_RESULT:
- case ND_COMPO_RESULT:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_IMAGE:
- if (wmn->action != NA_PAINTING) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_NODE:
- ED_region_tag_redraw(ar);
- break;
-
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_GPENCIL:
+ if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_BRUSH:
+ /* NA_SELECTED is used on brush changes */
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_MODE:
+ case ND_RENDER_RESULT:
+ case ND_COMPO_RESULT:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_IMAGE:
+ if (wmn->action != NA_PAINTING) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_NODE:
+ ED_region_tag_redraw(ar);
+ break;
+ }
}
/************************* header region **************************/
@@ -933,67 +937,69 @@ static void image_tools_region_listener(
/* add handlers, stuff you only do once or on area/region changes */
static void image_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
- ED_region_header_init(ar);
+ ED_region_header_init(ar);
}
static void image_header_region_draw(const bContext *C, ARegion *ar)
{
- ScrArea *sa = CTX_wm_area(C);
- SpaceImage *sima = sa->spacedata.first;
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceImage *sima = sa->spacedata.first;
- image_user_refresh_scene(C, sima);
+ image_user_refresh_scene(C, sima);
- ED_region_header(C, ar);
+ ED_region_header(C, ar);
}
-static void image_header_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void image_header_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_SCENE:
- switch (wmn->data) {
- case ND_MODE:
- case ND_TOOLSETTINGS:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_GEOM:
- switch (wmn->data) {
- case ND_DATA:
- case ND_SELECT:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_MODE:
+ case ND_TOOLSETTINGS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_GEOM:
+ switch (wmn->data) {
+ case ND_DATA:
+ case ND_SELECT:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ }
}
static void image_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
{
- SpaceImage *simg = (SpaceImage *)slink;
-
- if (!ELEM(GS(old_id->name), ID_IM, ID_GD, ID_MSK)) {
- return;
- }
-
- if ((ID *)simg->image == old_id) {
- simg->image = (Image *)new_id;
- id_us_ensure_real(new_id);
- }
-
- if ((ID *)simg->gpd == old_id) {
- simg->gpd = (bGPdata *)new_id;
- id_us_min(old_id);
- id_us_plus(new_id);
- }
-
- if ((ID *)simg->mask_info.mask == old_id) {
- simg->mask_info.mask = (Mask *)new_id;
- id_us_ensure_real(new_id);
- }
+ SpaceImage *simg = (SpaceImage *)slink;
+
+ if (!ELEM(GS(old_id->name), ID_IM, ID_GD, ID_MSK)) {
+ return;
+ }
+
+ if ((ID *)simg->image == old_id) {
+ simg->image = (Image *)new_id;
+ id_us_ensure_real(new_id);
+ }
+
+ if ((ID *)simg->gpd == old_id) {
+ simg->gpd = (bGPdata *)new_id;
+ id_us_min(old_id);
+ id_us_plus(new_id);
+ }
+
+ if ((ID *)simg->mask_info.mask == old_id) {
+ simg->mask_info.mask = (Mask *)new_id;
+ id_us_ensure_real(new_id);
+ }
}
/**
@@ -1003,28 +1009,29 @@ static void image_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID
*/
static int image_space_subtype_get(ScrArea *sa)
{
- SpaceImage *sima = sa->spacedata.first;
- return sima->mode == SI_MODE_UV ? SI_MODE_UV : SI_MODE_VIEW;
+ SpaceImage *sima = sa->spacedata.first;
+ return sima->mode == SI_MODE_UV ? SI_MODE_UV : SI_MODE_VIEW;
}
static void image_space_subtype_set(ScrArea *sa, int value)
{
- SpaceImage *sima = sa->spacedata.first;
- if (value == SI_MODE_UV) {
- if (sima->mode != SI_MODE_UV) {
- sima->mode_prev = sima->mode;
- }
- sima->mode = value;
- }
- else {
- sima->mode = sima->mode_prev;
- }
+ SpaceImage *sima = sa->spacedata.first;
+ if (value == SI_MODE_UV) {
+ if (sima->mode != SI_MODE_UV) {
+ sima->mode_prev = sima->mode;
+ }
+ sima->mode = value;
+ }
+ else {
+ sima->mode = sima->mode_prev;
+ }
}
-static void image_space_subtype_item_extend(
- bContext *UNUSED(C), EnumPropertyItem **item, int *totitem)
+static void image_space_subtype_item_extend(bContext *UNUSED(C),
+ EnumPropertyItem **item,
+ int *totitem)
{
- RNA_enum_items_add(item, totitem, rna_enum_space_image_mode_items);
+ RNA_enum_items_add(item, totitem, rna_enum_space_image_mode_items);
}
/**************************** spacetype *****************************/
@@ -1032,77 +1039,77 @@ static void image_space_subtype_item_extend(
/* only called once, from space/spacetypes.c */
void ED_spacetype_image(void)
{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype image");
- ARegionType *art;
-
- st->spaceid = SPACE_IMAGE;
- strncpy(st->name, "Image", BKE_ST_MAXNAME);
-
- st->new = image_new;
- st->free = image_free;
- st->init = image_init;
- st->duplicate = image_duplicate;
- st->operatortypes = image_operatortypes;
- st->keymap = image_keymap;
- st->dropboxes = image_dropboxes;
- st->refresh = image_refresh;
- st->listener = image_listener;
- st->context = image_context;
- st->gizmos = image_widgets;
- st->id_remap = image_id_remap;
- st->space_subtype_item_extend = image_space_subtype_item_extend;
- st->space_subtype_get = image_space_subtype_get;
- st->space_subtype_set = image_space_subtype_set;
-
- /* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype image region");
- art->regionid = RGN_TYPE_WINDOW;
- art->keymapflag = ED_KEYMAP_GIZMO | ED_KEYMAP_TOOL | ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL;
- art->init = image_main_region_init;
- art->draw = image_main_region_draw;
- art->listener = image_main_region_listener;
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: listview/buttons/scopes */
- art = MEM_callocN(sizeof(ARegionType), "spacetype image region");
- art->regionid = RGN_TYPE_UI;
- art->prefsizex = 220; // XXX
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
- art->listener = image_buttons_region_listener;
- art->init = image_buttons_region_init;
- art->draw = image_buttons_region_draw;
- BLI_addhead(&st->regiontypes, art);
-
- ED_uvedit_buttons_register(art);
- image_buttons_register(art);
-
- /* regions: tool(bar) */
- art = MEM_callocN(sizeof(ARegionType), "spacetype image region");
- art->regionid = RGN_TYPE_TOOLS;
- art->prefsizex = 58; /* XXX */
- art->prefsizey = 50; /* XXX */
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
- art->listener = image_tools_region_listener;
- art->message_subscribe = ED_region_generic_tools_region_message_subscribe;
- art->snap_size = ED_region_generic_tools_region_snap_size;
- art->init = image_tools_region_init;
- art->draw = image_tools_region_draw;
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype image region");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
- art->listener = image_header_region_listener;
- art->init = image_header_region_init;
- art->draw = image_header_region_draw;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: hud */
- art = ED_area_type_hud(st->spaceid);
- BLI_addhead(&st->regiontypes, art);
-
- BKE_spacetype_register(st);
+ SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype image");
+ ARegionType *art;
+
+ st->spaceid = SPACE_IMAGE;
+ strncpy(st->name, "Image", BKE_ST_MAXNAME);
+
+ st->new = image_new;
+ st->free = image_free;
+ st->init = image_init;
+ st->duplicate = image_duplicate;
+ st->operatortypes = image_operatortypes;
+ st->keymap = image_keymap;
+ st->dropboxes = image_dropboxes;
+ st->refresh = image_refresh;
+ st->listener = image_listener;
+ st->context = image_context;
+ st->gizmos = image_widgets;
+ st->id_remap = image_id_remap;
+ st->space_subtype_item_extend = image_space_subtype_item_extend;
+ st->space_subtype_get = image_space_subtype_get;
+ st->space_subtype_set = image_space_subtype_set;
+
+ /* regions: main window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype image region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->keymapflag = ED_KEYMAP_GIZMO | ED_KEYMAP_TOOL | ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL;
+ art->init = image_main_region_init;
+ art->draw = image_main_region_draw;
+ art->listener = image_main_region_listener;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: listview/buttons/scopes */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype image region");
+ art->regionid = RGN_TYPE_UI;
+ art->prefsizex = 220; // XXX
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
+ art->listener = image_buttons_region_listener;
+ art->init = image_buttons_region_init;
+ art->draw = image_buttons_region_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ ED_uvedit_buttons_register(art);
+ image_buttons_register(art);
+
+ /* regions: tool(bar) */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype image region");
+ art->regionid = RGN_TYPE_TOOLS;
+ art->prefsizex = 58; /* XXX */
+ art->prefsizey = 50; /* XXX */
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
+ art->listener = image_tools_region_listener;
+ art->message_subscribe = ED_region_generic_tools_region_message_subscribe;
+ art->snap_size = ED_region_generic_tools_region_snap_size;
+ art->init = image_tools_region_init;
+ art->draw = image_tools_region_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype image region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = HEADERY;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
+ art->listener = image_header_region_listener;
+ art->init = image_header_region_init;
+ art->draw = image_header_region_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: hud */
+ art = ED_area_type_hud(st->spaceid);
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_info/CMakeLists.txt b/source/blender/editors/space_info/CMakeLists.txt
index 665d130e072..bb403751fe2 100644
--- a/source/blender/editors/space_info/CMakeLists.txt
+++ b/source/blender/editors/space_info/CMakeLists.txt
@@ -16,44 +16,44 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenfont
- ../../blenkernel
- ../../blenlib
- ../../blenloader
- ../../blentranslation
- ../../depsgraph
- ../../imbuf
- ../../bmesh
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenfont
+ ../../blenkernel
+ ../../blenlib
+ ../../blenloader
+ ../../blentranslation
+ ../../depsgraph
+ ../../imbuf
+ ../../bmesh
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- info_draw.c
- info_ops.c
- info_report.c
- info_stats.c
- space_info.c
- textview.c
-
- info_intern.h
- textview.h
+ info_draw.c
+ info_ops.c
+ info_report.c
+ info_stats.c
+ space_info.c
+ textview.c
+
+ info_intern.h
+ textview.h
)
set(LIB
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/space_info/info_draw.c b/source/blender/editors/space_info/info_draw.c
index 39d255427cc..a7d6694b362 100644
--- a/source/blender/editors/space_info/info_draw.c
+++ b/source/blender/editors/space_info/info_draw.c
@@ -46,236 +46,246 @@
/* complicates things a bit, so leaving in old simple code */
#define USE_INFO_NEWLINE
-static void info_report_color(unsigned char *fg, unsigned char *bg, Report *report, const short do_tint)
+static void info_report_color(unsigned char *fg,
+ unsigned char *bg,
+ Report *report,
+ const short do_tint)
{
- int bg_id = TH_BACK, fg_id = TH_TEXT;
- int shade = do_tint ? 0 : -6;
-
- if (report->flag & SELECT) {
- bg_id = TH_INFO_SELECTED;
- fg_id = TH_INFO_SELECTED_TEXT;
- }
- else if (report->type & RPT_ERROR_ALL) {
- bg_id = TH_INFO_ERROR;
- fg_id = TH_INFO_ERROR_TEXT;
- }
- else if (report->type & RPT_WARNING_ALL) {
- bg_id = TH_INFO_WARNING;
- fg_id = TH_INFO_WARNING_TEXT;
- }
- else if (report->type & RPT_INFO_ALL) {
- bg_id = TH_INFO_INFO;
- fg_id = TH_INFO_INFO_TEXT;
- }
- else if (report->type & RPT_DEBUG_ALL) {
- bg_id = TH_INFO_DEBUG;
- fg_id = TH_INFO_DEBUG_TEXT;
- }
- else {
- bg_id = TH_BACK;
- fg_id = TH_TEXT;
- }
-
- UI_GetThemeColorShade3ubv(bg_id, shade, bg);
- UI_GetThemeColor3ubv(fg_id, fg);
+ int bg_id = TH_BACK, fg_id = TH_TEXT;
+ int shade = do_tint ? 0 : -6;
+
+ if (report->flag & SELECT) {
+ bg_id = TH_INFO_SELECTED;
+ fg_id = TH_INFO_SELECTED_TEXT;
+ }
+ else if (report->type & RPT_ERROR_ALL) {
+ bg_id = TH_INFO_ERROR;
+ fg_id = TH_INFO_ERROR_TEXT;
+ }
+ else if (report->type & RPT_WARNING_ALL) {
+ bg_id = TH_INFO_WARNING;
+ fg_id = TH_INFO_WARNING_TEXT;
+ }
+ else if (report->type & RPT_INFO_ALL) {
+ bg_id = TH_INFO_INFO;
+ fg_id = TH_INFO_INFO_TEXT;
+ }
+ else if (report->type & RPT_DEBUG_ALL) {
+ bg_id = TH_INFO_DEBUG;
+ fg_id = TH_INFO_DEBUG_TEXT;
+ }
+ else {
+ bg_id = TH_BACK;
+ fg_id = TH_TEXT;
+ }
+
+ UI_GetThemeColorShade3ubv(bg_id, shade, bg);
+ UI_GetThemeColor3ubv(fg_id, fg);
}
/* reports! */
#ifdef USE_INFO_NEWLINE
static void report_textview_init__internal(TextViewContext *tvc)
{
- Report *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;
- }
+ Report *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;
+ }
}
static int report_textview_skip__internal(TextViewContext *tvc)
{
- SpaceInfo *sinfo = (SpaceInfo *)tvc->arg1;
- const int report_mask = info_report_mask(sinfo);
- while (tvc->iter && (((Report *)tvc->iter)->type & report_mask) == 0) {
- tvc->iter = (void *)((Link *)tvc->iter)->prev;
- }
- return (tvc->iter != NULL);
+ SpaceInfo *sinfo = (SpaceInfo *)tvc->arg1;
+ const int report_mask = info_report_mask(sinfo);
+ while (tvc->iter && (((Report *)tvc->iter)->type & report_mask) == 0) {
+ tvc->iter = (void *)((Link *)tvc->iter)->prev;
+ }
+ return (tvc->iter != NULL);
}
-#endif // USE_INFO_NEWLINE
+#endif // USE_INFO_NEWLINE
static int report_textview_begin(TextViewContext *tvc)
{
- // SpaceConsole *sc = (SpaceConsole *)tvc->arg1;
- ReportList *reports = (ReportList *)tvc->arg2;
+ // SpaceConsole *sc = (SpaceConsole *)tvc->arg1;
+ ReportList *reports = (ReportList *)tvc->arg2;
- tvc->lheight = 14 * UI_DPI_FAC; //sc->lheight;
- tvc->sel_start = 0;
- tvc->sel_end = 0;
+ tvc->lheight = 14 * UI_DPI_FAC; //sc->lheight;
+ tvc->sel_start = 0;
+ tvc->sel_end = 0;
- /* iterator */
- tvc->iter = reports->list.last;
+ /* iterator */
+ tvc->iter = reports->list.last;
- UI_ThemeClearColor(TH_BACK);
- GPU_clear(GPU_COLOR_BIT);
+ UI_ThemeClearColor(TH_BACK);
+ GPU_clear(GPU_COLOR_BIT);
#ifdef USE_INFO_NEWLINE
- tvc->iter_tmp = 0;
- if (tvc->iter && report_textview_skip__internal(tvc)) {
- /* init the newline iterator */
- tvc->iter_char = 0;
- report_textview_init__internal(tvc);
-
- return true;
- }
- else {
- return false;
- }
+ tvc->iter_tmp = 0;
+ if (tvc->iter && report_textview_skip__internal(tvc)) {
+ /* init the newline iterator */
+ tvc->iter_char = 0;
+ report_textview_init__internal(tvc);
+
+ return true;
+ }
+ else {
+ return false;
+ }
#else
- return (tvc->iter != NULL);
+ return (tvc->iter != NULL);
#endif
}
static void report_textview_end(TextViewContext *UNUSED(tvc))
{
- /* pass */
+ /* pass */
}
#ifdef USE_INFO_NEWLINE
static int report_textview_step(TextViewContext *tvc)
{
- /* simple case, but no newline support */
- Report *report = (Report *)tvc->iter;
-
- if (report->len <= tvc->iter_char_next) {
- 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_textview_init__internal(tvc);
-
- return true;
- }
- else {
- return false;
- }
- }
- else {
- /* step to the next newline */
- tvc->iter_char = tvc->iter_char_next + 1;
- report_textview_init__internal(tvc);
-
- return true;
- }
+ /* simple case, but no newline support */
+ Report *report = (Report *)tvc->iter;
+
+ if (report->len <= tvc->iter_char_next) {
+ 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_textview_init__internal(tvc);
+
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ else {
+ /* step to the next newline */
+ tvc->iter_char = tvc->iter_char_next + 1;
+ report_textview_init__internal(tvc);
+
+ return true;
+ }
}
static int report_textview_line_get(struct TextViewContext *tvc, const char **line, int *len)
{
- Report *report = (Report *)tvc->iter;
- *line = report->message + tvc->iter_char;
- *len = tvc->iter_char_next - tvc->iter_char;
- return 1;
+ Report *report = (Report *)tvc->iter;
+ *line = report->message + tvc->iter_char;
+ *len = tvc->iter_char_next - tvc->iter_char;
+ return 1;
}
-static int report_textview_line_color(struct TextViewContext *tvc, unsigned char fg[3], unsigned char bg[3])
+static int report_textview_line_color(struct TextViewContext *tvc,
+ unsigned char fg[3],
+ unsigned char bg[3])
{
- Report *report = (Report *)tvc->iter;
- info_report_color(fg, bg, report, tvc->iter_tmp % 2);
- return TVC_LINE_FG | TVC_LINE_BG;
+ Report *report = (Report *)tvc->iter;
+ info_report_color(fg, bg, report, tvc->iter_tmp % 2);
+ return TVC_LINE_FG | TVC_LINE_BG;
}
-
-#else // USE_INFO_NEWLINE
+#else // USE_INFO_NEWLINE
static int report_textview_step(TextViewContext *tvc)
{
- SpaceInfo *sinfo = (SpaceInfo *)tvc->arg1;
- const int report_mask = info_report_mask(sinfo);
- do {
- tvc->iter = (void *)((Link *)tvc->iter)->prev;
- } while (tvc->iter && (((Report *)tvc->iter)->type & report_mask) == 0);
+ SpaceInfo *sinfo = (SpaceInfo *)tvc->arg1;
+ const int report_mask = info_report_mask(sinfo);
+ do {
+ tvc->iter = (void *)((Link *)tvc->iter)->prev;
+ } while (tvc->iter && (((Report *)tvc->iter)->type & report_mask) == 0);
- return (tvc->iter != NULL);
+ return (tvc->iter != NULL);
}
static int report_textview_line_get(struct TextViewContext *tvc, const char **line, int *len)
{
- Report *report = (Report *)tvc->iter;
- *line = report->message;
- *len = report->len;
+ Report *report = (Report *)tvc->iter;
+ *line = report->message;
+ *len = report->len;
- return 1;
+ return 1;
}
-static int report_textview_line_color(struct TextViewContext *tvc, unsigned char fg[3], unsigned char bg[3])
+static int report_textview_line_color(struct TextViewContext *tvc,
+ unsigned char fg[3],
+ unsigned char bg[3])
{
- Report *report = (Report *)tvc->iter;
- info_report_color(fg, bg, report, tvc->iter_tmp % 2);
- return TVC_LINE_FG | TVC_LINE_BG;
+ Report *report = (Report *)tvc->iter;
+ info_report_color(fg, bg, report, tvc->iter_tmp % 2);
+ return TVC_LINE_FG | TVC_LINE_BG;
}
-#endif // USE_INFO_NEWLINE
+#endif // USE_INFO_NEWLINE
#undef USE_INFO_NEWLINE
-static int info_textview_main__internal(struct SpaceInfo *sinfo, ARegion *ar, ReportList *reports,
- int draw, int mval[2], void **mouse_pick, int *pos_pick)
+static int info_textview_main__internal(struct SpaceInfo *sinfo,
+ ARegion *ar,
+ ReportList *reports,
+ int draw,
+ int mval[2],
+ void **mouse_pick,
+ int *pos_pick)
{
- int ret = 0;
+ int ret = 0;
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &ar->v2d;
- TextViewContext tvc = {0};
- tvc.begin = report_textview_begin;
- tvc.end = report_textview_end;
+ TextViewContext tvc = {0};
+ tvc.begin = report_textview_begin;
+ tvc.end = report_textview_end;
- tvc.step = report_textview_step;
- tvc.line_get = report_textview_line_get;
- tvc.line_color = report_textview_line_color;
- tvc.const_colors = NULL;
+ tvc.step = report_textview_step;
+ tvc.line_get = report_textview_line_get;
+ tvc.line_color = report_textview_line_color;
+ tvc.const_colors = NULL;
- tvc.arg1 = sinfo;
- tvc.arg2 = reports;
+ tvc.arg1 = sinfo;
+ tvc.arg2 = reports;
- /* view */
- tvc.sel_start = 0;
- tvc.sel_end = 0;
- tvc.lheight = 14 * UI_DPI_FAC; //sc->lheight;
- tvc.ymin = v2d->cur.ymin;
- tvc.ymax = v2d->cur.ymax;
- tvc.winx = ar->winx - V2D_SCROLL_WIDTH;
+ /* view */
+ tvc.sel_start = 0;
+ tvc.sel_end = 0;
+ tvc.lheight = 14 * UI_DPI_FAC; //sc->lheight;
+ tvc.ymin = v2d->cur.ymin;
+ tvc.ymax = v2d->cur.ymax;
+ tvc.winx = ar->winx - V2D_SCROLL_WIDTH;
- ret = textview_draw(&tvc, draw, mval, mouse_pick, pos_pick);
+ ret = textview_draw(&tvc, draw, mval, mouse_pick, pos_pick);
- return ret;
+ return ret;
}
void *info_text_pick(struct SpaceInfo *sinfo, ARegion *ar, ReportList *reports, int mouse_y)
{
- void *mouse_pick = NULL;
- int mval[2];
+ void *mouse_pick = NULL;
+ int mval[2];
- mval[0] = 0;
- mval[1] = mouse_y;
+ mval[0] = 0;
+ mval[1] = mouse_y;
- info_textview_main__internal(sinfo, ar, reports, 0, mval, &mouse_pick, NULL);
- return (void *)mouse_pick;
+ info_textview_main__internal(sinfo, ar, reports, 0, mval, &mouse_pick, NULL);
+ return (void *)mouse_pick;
}
-
int info_textview_height(struct SpaceInfo *sinfo, ARegion *ar, ReportList *reports)
{
- int mval[2] = {INT_MAX, INT_MAX};
- return info_textview_main__internal(sinfo, ar, reports, 0, mval, NULL, NULL);
+ int mval[2] = {INT_MAX, INT_MAX};
+ return info_textview_main__internal(sinfo, ar, reports, 0, mval, NULL, NULL);
}
void info_textview_main(struct SpaceInfo *sinfo, ARegion *ar, ReportList *reports)
{
- int mval[2] = {INT_MAX, INT_MAX};
- info_textview_main__internal(sinfo, ar, reports, 1, mval, NULL, NULL);
+ int mval[2] = {INT_MAX, INT_MAX};
+ info_textview_main__internal(sinfo, ar, reports, 1, mval, NULL, NULL);
}
diff --git a/source/blender/editors/space_info/info_intern.h b/source/blender/editors/space_info/info_intern.h
index 7903a462ce1..7d4d6e5ab90 100644
--- a/source/blender/editors/space_info/info_intern.h
+++ b/source/blender/editors/space_info/info_intern.h
@@ -42,11 +42,13 @@ void FILE_OT_make_paths_absolute(struct wmOperatorType *ot);
void FILE_OT_report_missing_files(struct wmOperatorType *ot);
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, struct ARegion *ar, ReportList *reports, int mouse_y);
+void *info_text_pick(struct SpaceInfo *sinfo,
+ struct ARegion *ar,
+ ReportList *reports,
+ int mouse_y);
int info_textview_height(struct SpaceInfo *sinfo, struct ARegion *ar, struct ReportList *reports);
void info_textview_main(struct SpaceInfo *sinfo, struct ARegion *ar, struct ReportList *reports);
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
index 0abad05cc76..171d8505222 100644
--- a/source/blender/editors/space_info/info_ops.c
+++ b/source/blender/editors/space_info/info_ops.c
@@ -21,7 +21,6 @@
* \ingroup spinfo
*/
-
#include <string.h>
#include <stdio.h>
@@ -47,11 +46,9 @@
#include "BKE_report.h"
#include "BKE_screen.h"
-
#include "WM_api.h"
#include "WM_types.h"
-
#include "UI_interface.h"
#include "UI_resources.h"
@@ -60,432 +57,473 @@
#include "RNA_access.h"
#include "RNA_define.h"
-
#include "info_intern.h"
/********************* pack blend file libraries operator *********************/
static int pack_libraries_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
+ Main *bmain = CTX_data_main(C);
- packLibraries(bmain, op->reports);
+ packLibraries(bmain, op->reports);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void FILE_OT_pack_libraries(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Pack Blender Libraries";
- ot->idname = "FILE_OT_pack_libraries";
- ot->description = "Pack all used Blender library files into the current .blend";
+ /* identifiers */
+ ot->name = "Pack Blender Libraries";
+ ot->idname = "FILE_OT_pack_libraries";
+ ot->description = "Pack all used Blender library files into the current .blend";
- /* api callbacks */
- ot->exec = pack_libraries_exec;
+ /* api callbacks */
+ ot->exec = pack_libraries_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int unpack_libraries_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
+ Main *bmain = CTX_data_main(C);
- unpackLibraries(bmain, op->reports);
+ unpackLibraries(bmain, op->reports);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int unpack_libraries_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- return WM_operator_confirm_message(C, op, "Unpack Blender Libraries - creates directories, all new paths should work");
+ return WM_operator_confirm_message(
+ C, op, "Unpack Blender Libraries - creates directories, all new paths should work");
}
void FILE_OT_unpack_libraries(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unpack Blender Libraries";
- ot->idname = "FILE_OT_unpack_libraries";
- ot->description = "Unpack all used Blender library files from this .blend file";
+ /* identifiers */
+ ot->name = "Unpack Blender Libraries";
+ ot->idname = "FILE_OT_unpack_libraries";
+ ot->description = "Unpack all used Blender library files from this .blend file";
- /* api callbacks */
- ot->invoke = unpack_libraries_invoke;
- ot->exec = unpack_libraries_exec;
+ /* api callbacks */
+ ot->invoke = unpack_libraries_invoke;
+ ot->exec = unpack_libraries_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************* toggle auto-pack operator *********************/
static int autopack_toggle_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
+ Main *bmain = CTX_data_main(C);
- if (G.fileflags & G_FILE_AUTOPACK) {
- G.fileflags &= ~G_FILE_AUTOPACK;
- }
- else {
- packAll(bmain, op->reports, true);
- G.fileflags |= G_FILE_AUTOPACK;
- }
+ if (G.fileflags & G_FILE_AUTOPACK) {
+ G.fileflags &= ~G_FILE_AUTOPACK;
+ }
+ else {
+ packAll(bmain, op->reports, true);
+ G.fileflags |= G_FILE_AUTOPACK;
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void FILE_OT_autopack_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Automatically Pack Into .blend";
- ot->idname = "FILE_OT_autopack_toggle";
- ot->description = "Automatically pack all external files into the .blend file";
+ /* identifiers */
+ ot->name = "Automatically Pack Into .blend";
+ ot->idname = "FILE_OT_autopack_toggle";
+ ot->description = "Automatically pack all external files into the .blend file";
- /* api callbacks */
- ot->exec = autopack_toggle_exec;
+ /* api callbacks */
+ ot->exec = autopack_toggle_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************* pack all operator *********************/
static int pack_all_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
+ Main *bmain = CTX_data_main(C);
- packAll(bmain, op->reports, true);
+ packAll(bmain, op->reports, true);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int pack_all_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Main *bmain = CTX_data_main(C);
- Image *ima;
- ImBuf *ibuf;
-
- // first check for dirty images
- for (ima = bmain->images.first; ima; ima = ima->id.next) {
- if (BKE_image_has_loaded_ibuf(ima)) { /* XXX FIX */
- ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
-
- if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- break;
- }
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
- }
-
- if (ima) {
- return WM_operator_confirm_message(C, op, "Some images are painted on. These changes will be lost. Continue?");
- }
-
- return pack_all_exec(C, op);
+ Main *bmain = CTX_data_main(C);
+ Image *ima;
+ ImBuf *ibuf;
+
+ // first check for dirty images
+ for (ima = bmain->images.first; ima; ima = ima->id.next) {
+ if (BKE_image_has_loaded_ibuf(ima)) { /* XXX FIX */
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+
+ if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ break;
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+ }
+
+ if (ima) {
+ return WM_operator_confirm_message(
+ C, op, "Some images are painted on. These changes will be lost. Continue?");
+ }
+
+ return pack_all_exec(C, op);
}
void FILE_OT_pack_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Pack All Into .blend";
- ot->idname = "FILE_OT_pack_all";
- ot->description = "Pack all used external files into the .blend";
+ /* identifiers */
+ ot->name = "Pack All Into .blend";
+ ot->idname = "FILE_OT_pack_all";
+ ot->description = "Pack all used external files into the .blend";
- /* api callbacks */
- ot->exec = pack_all_exec;
- ot->invoke = pack_all_invoke;
+ /* api callbacks */
+ ot->exec = pack_all_exec;
+ ot->invoke = pack_all_invoke;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/********************* unpack all operator *********************/
static const EnumPropertyItem unpack_all_method_items[] = {
- {PF_USE_LOCAL, "USE_LOCAL", 0, "Use files in current directory (create when necessary)", ""},
- {PF_WRITE_LOCAL, "WRITE_LOCAL", 0, "Write files to current directory (overwrite existing files)", ""},
- {PF_USE_ORIGINAL, "USE_ORIGINAL", 0, "Use files in original location (create when necessary)", ""},
- {PF_WRITE_ORIGINAL, "WRITE_ORIGINAL", 0, "Write files to original location (overwrite existing files)", ""},
- {PF_KEEP, "KEEP", 0, "Disable Auto-pack, keep all packed files", ""},
- /* {PF_ASK, "ASK", 0, "Ask for each file", ""}, */
- {0, NULL, 0, NULL, NULL},
+ {PF_USE_LOCAL, "USE_LOCAL", 0, "Use files in current directory (create when necessary)", ""},
+ {PF_WRITE_LOCAL,
+ "WRITE_LOCAL",
+ 0,
+ "Write files to current directory (overwrite existing files)",
+ ""},
+ {PF_USE_ORIGINAL,
+ "USE_ORIGINAL",
+ 0,
+ "Use files in original location (create when necessary)",
+ ""},
+ {PF_WRITE_ORIGINAL,
+ "WRITE_ORIGINAL",
+ 0,
+ "Write files to original location (overwrite existing files)",
+ ""},
+ {PF_KEEP, "KEEP", 0, "Disable Auto-pack, keep all packed files", ""},
+ /* {PF_ASK, "ASK", 0, "Ask for each file", ""}, */
+ {0, NULL, 0, NULL, NULL},
};
static int unpack_all_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- int method = RNA_enum_get(op->ptr, "method");
+ Main *bmain = CTX_data_main(C);
+ int method = RNA_enum_get(op->ptr, "method");
- if (method != PF_KEEP) {
- unpackAll(bmain, op->reports, method); /* XXX PF_ASK can't work here */
- }
- G.fileflags &= ~G_FILE_AUTOPACK;
+ if (method != PF_KEEP) {
+ unpackAll(bmain, op->reports, method); /* XXX PF_ASK can't work here */
+ }
+ G.fileflags &= ~G_FILE_AUTOPACK;
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int unpack_all_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Main *bmain = CTX_data_main(C);
- uiPopupMenu *pup;
- uiLayout *layout;
- char title[64];
- int count = 0;
+ Main *bmain = CTX_data_main(C);
+ uiPopupMenu *pup;
+ uiLayout *layout;
+ char title[64];
+ int count = 0;
- count = countPackedFiles(bmain);
+ count = countPackedFiles(bmain);
- if (!count) {
- BKE_report(op->reports, RPT_WARNING, "No packed files to unpack");
- G.fileflags &= ~G_FILE_AUTOPACK;
- return OPERATOR_CANCELLED;
- }
+ if (!count) {
+ BKE_report(op->reports, RPT_WARNING, "No packed files to unpack");
+ G.fileflags &= ~G_FILE_AUTOPACK;
+ return OPERATOR_CANCELLED;
+ }
- if (count == 1) {
- BLI_strncpy(title, IFACE_("Unpack 1 File"), sizeof(title));
- }
- else {
- BLI_snprintf(title, sizeof(title), IFACE_("Unpack %d Files"), count);
- }
+ if (count == 1) {
+ BLI_strncpy(title, IFACE_("Unpack 1 File"), sizeof(title));
+ }
+ else {
+ BLI_snprintf(title, sizeof(title), IFACE_("Unpack %d Files"), count);
+ }
- pup = UI_popup_menu_begin(C, title, ICON_NONE);
- layout = UI_popup_menu_layout(pup);
+ pup = UI_popup_menu_begin(C, title, ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
- uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
- uiItemsEnumO(layout, "FILE_OT_unpack_all", "method");
+ uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
+ uiItemsEnumO(layout, "FILE_OT_unpack_all", "method");
- UI_popup_menu_end(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
void FILE_OT_unpack_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unpack All Into Files";
- ot->idname = "FILE_OT_unpack_all";
- ot->description = "Unpack all files packed into this .blend to external ones";
+ /* identifiers */
+ ot->name = "Unpack All Into Files";
+ ot->idname = "FILE_OT_unpack_all";
+ ot->description = "Unpack all files packed into this .blend to external ones";
- /* api callbacks */
- ot->exec = unpack_all_exec;
- ot->invoke = unpack_all_invoke;
+ /* api callbacks */
+ ot->exec = unpack_all_exec;
+ ot->invoke = unpack_all_invoke;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_enum(ot->srna, "method", unpack_all_method_items, PF_USE_LOCAL, "Method", "How to unpack");
+ /* properties */
+ RNA_def_enum(
+ ot->srna, "method", unpack_all_method_items, PF_USE_LOCAL, "Method", "How to unpack");
}
/********************* unpack single item operator *********************/
static const EnumPropertyItem unpack_item_method_items[] = {
- {PF_USE_LOCAL, "USE_LOCAL", 0, "Use file from current directory (create when necessary)", ""},
- {PF_WRITE_LOCAL, "WRITE_LOCAL", 0, "Write file to current directory (overwrite existing file)", ""},
- {PF_USE_ORIGINAL, "USE_ORIGINAL", 0, "Use file in original location (create when necessary)", ""},
- {PF_WRITE_ORIGINAL, "WRITE_ORIGINAL", 0, "Write file to original location (overwrite existing file)", ""},
- /* {PF_ASK, "ASK", 0, "Ask for each file", ""}, */
- {0, NULL, 0, NULL, NULL},
+ {PF_USE_LOCAL, "USE_LOCAL", 0, "Use file from current directory (create when necessary)", ""},
+ {PF_WRITE_LOCAL,
+ "WRITE_LOCAL",
+ 0,
+ "Write file to current directory (overwrite existing file)",
+ ""},
+ {PF_USE_ORIGINAL,
+ "USE_ORIGINAL",
+ 0,
+ "Use file in original location (create when necessary)",
+ ""},
+ {PF_WRITE_ORIGINAL,
+ "WRITE_ORIGINAL",
+ 0,
+ "Write file to original location (overwrite existing file)",
+ ""},
+ /* {PF_ASK, "ASK", 0, "Ask for each file", ""}, */
+ {0, NULL, 0, NULL, NULL},
};
-
static int unpack_item_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- ID *id;
- char idname[MAX_ID_NAME - 2];
- int type = RNA_int_get(op->ptr, "id_type");
- int method = RNA_enum_get(op->ptr, "method");
+ Main *bmain = CTX_data_main(C);
+ ID *id;
+ char idname[MAX_ID_NAME - 2];
+ int type = RNA_int_get(op->ptr, "id_type");
+ int method = RNA_enum_get(op->ptr, "method");
- RNA_string_get(op->ptr, "id_name", idname);
- id = BKE_libblock_find_name(bmain, type, idname);
+ RNA_string_get(op->ptr, "id_name", idname);
+ id = BKE_libblock_find_name(bmain, type, idname);
- if (id == NULL) {
- BKE_report(op->reports, RPT_WARNING, "No packed file");
- return OPERATOR_CANCELLED;
- }
+ if (id == NULL) {
+ BKE_report(op->reports, RPT_WARNING, "No packed file");
+ return OPERATOR_CANCELLED;
+ }
- if (method != PF_KEEP) {
- BKE_unpack_id(bmain, id, op->reports, method); /* XXX PF_ASK can't work here */
- }
+ if (method != PF_KEEP) {
+ BKE_unpack_id(bmain, id, op->reports, method); /* XXX PF_ASK can't work here */
+ }
- G.fileflags &= ~G_FILE_AUTOPACK;
+ G.fileflags &= ~G_FILE_AUTOPACK;
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int unpack_item_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- uiPopupMenu *pup;
- uiLayout *layout;
+ uiPopupMenu *pup;
+ uiLayout *layout;
- pup = UI_popup_menu_begin(C, IFACE_("Unpack"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
+ pup = UI_popup_menu_begin(C, IFACE_("Unpack"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
- uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
- uiItemsFullEnumO(layout, op->type->idname, "method", op->ptr->data, WM_OP_EXEC_REGION_WIN, 0);
+ uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
+ uiItemsFullEnumO(layout, op->type->idname, "method", op->ptr->data, WM_OP_EXEC_REGION_WIN, 0);
- UI_popup_menu_end(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
void FILE_OT_unpack_item(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unpack Item";
- ot->idname = "FILE_OT_unpack_item";
- ot->description = "Unpack this file to an external file";
-
- /* api callbacks */
- ot->exec = unpack_item_exec;
- ot->invoke = unpack_item_invoke;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "method", unpack_item_method_items, PF_USE_LOCAL, "Method", "How to unpack");
- RNA_def_string(ot->srna, "id_name", NULL, BKE_ST_MAXNAME, "ID name", "Name of ID block to unpack");
- RNA_def_int(ot->srna, "id_type", ID_IM, 0, INT_MAX, "ID Type", "Identifier type of ID block", 0, INT_MAX);
+ /* identifiers */
+ ot->name = "Unpack Item";
+ ot->idname = "FILE_OT_unpack_item";
+ ot->description = "Unpack this file to an external file";
+
+ /* api callbacks */
+ ot->exec = unpack_item_exec;
+ ot->invoke = unpack_item_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(
+ ot->srna, "method", unpack_item_method_items, PF_USE_LOCAL, "Method", "How to unpack");
+ RNA_def_string(
+ ot->srna, "id_name", NULL, BKE_ST_MAXNAME, "ID name", "Name of ID block to unpack");
+ RNA_def_int(ot->srna,
+ "id_type",
+ ID_IM,
+ 0,
+ INT_MAX,
+ "ID Type",
+ "Identifier type of ID block",
+ 0,
+ INT_MAX);
}
-
/********************* make paths relative operator *********************/
static int make_paths_relative_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
+ Main *bmain = CTX_data_main(C);
- if (!G.relbase_valid) {
- BKE_report(op->reports, RPT_WARNING, "Cannot set relative paths with an unsaved blend file");
- return OPERATOR_CANCELLED;
- }
+ if (!G.relbase_valid) {
+ BKE_report(op->reports, RPT_WARNING, "Cannot set relative paths with an unsaved blend file");
+ return OPERATOR_CANCELLED;
+ }
- BKE_bpath_relative_convert(bmain, BKE_main_blendfile_path(bmain), op->reports);
+ BKE_bpath_relative_convert(bmain, BKE_main_blendfile_path(bmain), op->reports);
- /* redraw everything so any changed paths register */
- WM_main_add_notifier(NC_WINDOW, NULL);
+ /* redraw everything so any changed paths register */
+ WM_main_add_notifier(NC_WINDOW, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void FILE_OT_make_paths_relative(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make All Paths Relative";
- ot->idname = "FILE_OT_make_paths_relative";
- ot->description = "Make all paths to external files relative to current .blend";
+ /* identifiers */
+ ot->name = "Make All Paths Relative";
+ ot->idname = "FILE_OT_make_paths_relative";
+ ot->description = "Make all paths to external files relative to current .blend";
- /* api callbacks */
- ot->exec = make_paths_relative_exec;
+ /* api callbacks */
+ ot->exec = make_paths_relative_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************* make paths absolute operator *********************/
static int make_paths_absolute_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
+ Main *bmain = CTX_data_main(C);
- if (!G.relbase_valid) {
- BKE_report(op->reports, RPT_WARNING, "Cannot set absolute paths with an unsaved blend file");
- return OPERATOR_CANCELLED;
- }
+ if (!G.relbase_valid) {
+ BKE_report(op->reports, RPT_WARNING, "Cannot set absolute paths with an unsaved blend file");
+ return OPERATOR_CANCELLED;
+ }
- BKE_bpath_absolute_convert(bmain, BKE_main_blendfile_path(bmain), op->reports);
+ BKE_bpath_absolute_convert(bmain, BKE_main_blendfile_path(bmain), op->reports);
- /* redraw everything so any changed paths register */
- WM_main_add_notifier(NC_WINDOW, NULL);
+ /* redraw everything so any changed paths register */
+ WM_main_add_notifier(NC_WINDOW, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void FILE_OT_make_paths_absolute(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make All Paths Absolute";
- ot->idname = "FILE_OT_make_paths_absolute";
- ot->description = "Make all paths to external files absolute";
+ /* identifiers */
+ ot->name = "Make All Paths Absolute";
+ ot->idname = "FILE_OT_make_paths_absolute";
+ ot->description = "Make all paths to external files absolute";
- /* api callbacks */
- ot->exec = make_paths_absolute_exec;
+ /* api callbacks */
+ ot->exec = make_paths_absolute_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************* report missing files operator *********************/
static int report_missing_files_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
+ Main *bmain = CTX_data_main(C);
- /* run the missing file check */
- BKE_bpath_missing_files_check(bmain, op->reports);
+ /* run the missing file check */
+ BKE_bpath_missing_files_check(bmain, op->reports);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void FILE_OT_report_missing_files(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Report Missing Files";
- ot->idname = "FILE_OT_report_missing_files";
- ot->description = "Report all missing external files";
+ /* identifiers */
+ ot->name = "Report Missing Files";
+ ot->idname = "FILE_OT_report_missing_files";
+ ot->description = "Report all missing external files";
- /* api callbacks */
- ot->exec = report_missing_files_exec;
+ /* api callbacks */
+ ot->exec = report_missing_files_exec;
- /* flags */
- ot->flag = 0; /* only reports so no need to undo/register */
+ /* flags */
+ ot->flag = 0; /* only reports so no need to undo/register */
}
/********************* find missing files operator *********************/
static int find_missing_files_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- const char *searchpath = RNA_string_get_alloc(op->ptr, "directory", NULL, 0);
- const bool find_all = RNA_boolean_get(op->ptr, "find_all");
+ Main *bmain = CTX_data_main(C);
+ const char *searchpath = RNA_string_get_alloc(op->ptr, "directory", NULL, 0);
+ const bool find_all = RNA_boolean_get(op->ptr, "find_all");
- BKE_bpath_missing_files_find(bmain, searchpath, op->reports, find_all);
- MEM_freeN((void *)searchpath);
+ BKE_bpath_missing_files_find(bmain, searchpath, op->reports, find_all);
+ MEM_freeN((void *)searchpath);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int find_missing_files_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- /* XXX file open button text "Find Missing Files" */
- WM_event_add_fileselect(C, op);
- return OPERATOR_RUNNING_MODAL;
+ /* XXX file open button text "Find Missing Files" */
+ WM_event_add_fileselect(C, op);
+ return OPERATOR_RUNNING_MODAL;
}
void FILE_OT_find_missing_files(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Find Missing Files";
- ot->idname = "FILE_OT_find_missing_files";
- ot->description = "Try to find missing external files";
-
- /* api callbacks */
- ot->exec = find_missing_files_exec;
- ot->invoke = find_missing_files_invoke;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "find_all", false, "Find All", "Find all files in the search path (not just missing)");
-
- WM_operator_properties_filesel(
- ot, 0, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_DIRECTORY, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+ /* identifiers */
+ ot->name = "Find Missing Files";
+ ot->idname = "FILE_OT_find_missing_files";
+ ot->description = "Try to find missing external files";
+
+ /* api callbacks */
+ ot->exec = find_missing_files_exec;
+ ot->invoke = find_missing_files_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "find_all",
+ false,
+ "Find All",
+ "Find all files in the search path (not just missing)");
+
+ WM_operator_properties_filesel(ot,
+ 0,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_DIRECTORY,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
}
/********************* report box operator *********************/
@@ -497,108 +535,106 @@ void FILE_OT_find_missing_files(wmOperatorType *ot)
* inactive regions, so use this for now. --matt
*/
-#define INFO_TIMEOUT 5.0f
-#define ERROR_TIMEOUT 10.0f
-#define FLASH_TIMEOUT 1.0f
-#define COLLAPSE_TIMEOUT 0.25f
-#define BRIGHTEN_AMOUNT 0.1f
+#define INFO_TIMEOUT 5.0f
+#define ERROR_TIMEOUT 10.0f
+#define FLASH_TIMEOUT 1.0f
+#define COLLAPSE_TIMEOUT 0.25f
+#define BRIGHTEN_AMOUNT 0.1f
static int update_reports_display_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- ReportList *reports = CTX_wm_reports(C);
- Report *report;
- ReportTimerInfo *rti;
- float target_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- float progress = 0.0, flash_progress = 0.0;
- float timeout = 0.0, flash_timeout = FLASH_TIMEOUT;
- int send_note = 0;
-
- /* escape if not our timer */
- if ((reports->reporttimer == NULL) ||
- (reports->reporttimer != event->customdata) ||
- ((report = BKE_reports_last_displayable(reports)) == NULL) /* may have been deleted */
- )
- {
- return OPERATOR_PASS_THROUGH;
- }
-
- rti = (ReportTimerInfo *)reports->reporttimer->customdata;
-
- timeout = (report->type & RPT_ERROR_ALL) ? ERROR_TIMEOUT : INFO_TIMEOUT;
-
- /* clear the report display after timeout */
- if ((float)reports->reporttimer->duration > timeout) {
- WM_event_remove_timer(wm, NULL, reports->reporttimer);
- reports->reporttimer = NULL;
-
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL);
-
- return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
- }
-
- /* set target color based on report type */
- if (report->type & RPT_ERROR_ALL) {
- UI_GetThemeColorType3fv(TH_INFO_ERROR, SPACE_INFO, target_col);
- }
- else if (report->type & RPT_WARNING_ALL) {
- UI_GetThemeColorType3fv(TH_INFO_WARNING, SPACE_INFO, target_col);
- }
- else if (report->type & RPT_INFO_ALL) {
- UI_GetThemeColorType3fv(TH_INFO_INFO, SPACE_INFO, target_col);
- }
- target_col[3] = 0.65f;
-
- if (rti->widthfac == 0.0f) {
- /* initialize color to a brighter shade of the target color */
- rti->col[0] = target_col[0] + BRIGHTEN_AMOUNT;
- rti->col[1] = target_col[1] + BRIGHTEN_AMOUNT;
- rti->col[2] = target_col[2] + BRIGHTEN_AMOUNT;
- rti->col[3] = 1.0f;
-
- CLAMP3(rti->col, 0.0, 1.0);
-
- rti->widthfac = 1.0f;
- }
-
- progress = powf((float)reports->reporttimer->duration / timeout, 2.0f);
- flash_progress = powf((float)reports->reporttimer->duration / flash_timeout, 2.0);
-
- /* save us from too many draws */
- if (flash_progress <= 1.0f) {
- send_note = 1;
-
- /* flash report briefly according to progress through fade-out duration */
- interp_v4_v4v4(rti->col, rti->col, target_col, flash_progress);
- }
-
- /* collapse report at end of timeout */
- if (progress * timeout > timeout - COLLAPSE_TIMEOUT) {
- rti->widthfac = (progress * timeout - (timeout - COLLAPSE_TIMEOUT)) / COLLAPSE_TIMEOUT;
- rti->widthfac = 1.0f - rti->widthfac;
- send_note = 1;
- }
-
- if (send_note) {
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL);
- }
-
- return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ ReportList *reports = CTX_wm_reports(C);
+ Report *report;
+ ReportTimerInfo *rti;
+ float target_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float progress = 0.0, flash_progress = 0.0;
+ float timeout = 0.0, flash_timeout = FLASH_TIMEOUT;
+ int send_note = 0;
+
+ /* escape if not our timer */
+ if ((reports->reporttimer == NULL) || (reports->reporttimer != event->customdata) ||
+ ((report = BKE_reports_last_displayable(reports)) == NULL) /* may have been deleted */
+ ) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ rti = (ReportTimerInfo *)reports->reporttimer->customdata;
+
+ timeout = (report->type & RPT_ERROR_ALL) ? ERROR_TIMEOUT : INFO_TIMEOUT;
+
+ /* clear the report display after timeout */
+ if ((float)reports->reporttimer->duration > timeout) {
+ WM_event_remove_timer(wm, NULL, reports->reporttimer);
+ reports->reporttimer = NULL;
+
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL);
+
+ return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
+ }
+
+ /* set target color based on report type */
+ if (report->type & RPT_ERROR_ALL) {
+ UI_GetThemeColorType3fv(TH_INFO_ERROR, SPACE_INFO, target_col);
+ }
+ else if (report->type & RPT_WARNING_ALL) {
+ UI_GetThemeColorType3fv(TH_INFO_WARNING, SPACE_INFO, target_col);
+ }
+ else if (report->type & RPT_INFO_ALL) {
+ UI_GetThemeColorType3fv(TH_INFO_INFO, SPACE_INFO, target_col);
+ }
+ target_col[3] = 0.65f;
+
+ if (rti->widthfac == 0.0f) {
+ /* initialize color to a brighter shade of the target color */
+ rti->col[0] = target_col[0] + BRIGHTEN_AMOUNT;
+ rti->col[1] = target_col[1] + BRIGHTEN_AMOUNT;
+ rti->col[2] = target_col[2] + BRIGHTEN_AMOUNT;
+ rti->col[3] = 1.0f;
+
+ CLAMP3(rti->col, 0.0, 1.0);
+
+ rti->widthfac = 1.0f;
+ }
+
+ progress = powf((float)reports->reporttimer->duration / timeout, 2.0f);
+ flash_progress = powf((float)reports->reporttimer->duration / flash_timeout, 2.0);
+
+ /* save us from too many draws */
+ if (flash_progress <= 1.0f) {
+ send_note = 1;
+
+ /* flash report briefly according to progress through fade-out duration */
+ interp_v4_v4v4(rti->col, rti->col, target_col, flash_progress);
+ }
+
+ /* collapse report at end of timeout */
+ if (progress * timeout > timeout - COLLAPSE_TIMEOUT) {
+ rti->widthfac = (progress * timeout - (timeout - COLLAPSE_TIMEOUT)) / COLLAPSE_TIMEOUT;
+ rti->widthfac = 1.0f - rti->widthfac;
+ send_note = 1;
+ }
+
+ if (send_note) {
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL);
+ }
+
+ return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
}
void INFO_OT_reports_display_update(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Update Reports Display";
- ot->idname = "INFO_OT_reports_display_update";
- ot->description = "Update the display of reports in Blender UI (internal use)";
+ /* identifiers */
+ ot->name = "Update Reports Display";
+ ot->idname = "INFO_OT_reports_display_update";
+ ot->description = "Update the display of reports in Blender UI (internal use)";
- /* api callbacks */
- ot->invoke = update_reports_display_invoke;
+ /* api callbacks */
+ ot->invoke = update_reports_display_invoke;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
- /* properties */
+ /* properties */
}
/* report operators */
diff --git a/source/blender/editors/space_info/info_report.c b/source/blender/editors/space_info/info_report.c
index e4202483574..707838cf7e5 100644
--- a/source/blender/editors/space_info/info_report.c
+++ b/source/blender/editors/space_info/info_report.c
@@ -18,7 +18,6 @@
* \ingroup spinfo
*/
-
#include <stdlib.h>
#include <string.h>
#include <limits.h>
@@ -45,346 +44,344 @@
int info_report_mask(SpaceInfo *UNUSED(sinfo))
{
#if 0
- int report_mask = 0;
+ int report_mask = 0;
- if (sinfo->rpt_mask & INFO_RPT_DEBUG) report_mask |= RPT_DEBUG_ALL;
- if (sinfo->rpt_mask & INFO_RPT_INFO) report_mask |= RPT_INFO_ALL;
- if (sinfo->rpt_mask & INFO_RPT_OP) report_mask |= RPT_OPERATOR_ALL;
- if (sinfo->rpt_mask & INFO_RPT_WARN) report_mask |= RPT_WARNING_ALL;
- if (sinfo->rpt_mask & INFO_RPT_ERR) report_mask |= RPT_ERROR_ALL;
+ if (sinfo->rpt_mask & INFO_RPT_DEBUG) report_mask |= RPT_DEBUG_ALL;
+ if (sinfo->rpt_mask & INFO_RPT_INFO) report_mask |= RPT_INFO_ALL;
+ if (sinfo->rpt_mask & INFO_RPT_OP) report_mask |= RPT_OPERATOR_ALL;
+ if (sinfo->rpt_mask & INFO_RPT_WARN) report_mask |= RPT_WARNING_ALL;
+ if (sinfo->rpt_mask & INFO_RPT_ERR) report_mask |= RPT_ERROR_ALL;
- return report_mask;
+ return report_mask;
#endif
- return RPT_DEBUG_ALL | RPT_INFO_ALL | RPT_OPERATOR_ALL | RPT_PROPERTY_ALL | RPT_WARNING_ALL | RPT_ERROR_ALL;
+ return RPT_DEBUG_ALL | RPT_INFO_ALL | RPT_OPERATOR_ALL | RPT_PROPERTY_ALL | RPT_WARNING_ALL |
+ RPT_ERROR_ALL;
}
// TODO, get this working again!
static int report_replay_exec(bContext *C, wmOperator *UNUSED(op))
{
-// SpaceInfo *sc = CTX_wm_space_info(C);
-// ReportList *reports = CTX_wm_reports(C);
-// int report_mask = info_report_mask(sc);
-// Report *report;
+ // SpaceInfo *sc = CTX_wm_space_info(C);
+ // ReportList *reports = CTX_wm_reports(C);
+ // int report_mask = info_report_mask(sc);
+ // Report *report;
#if 0
- sc->type = CONSOLE_TYPE_PYTHON;
+ sc->type = CONSOLE_TYPE_PYTHON;
- for (report = reports->list.last; report; report = report->prev) {
- if ((report->type & report_mask) &&
- (report->type & RPT_OPERATOR_ALL | RPT_PROPERTY_ALL) &&
- (report->flag & SELECT))
- {
- console_history_add_str(sc, report->message, 0);
- WM_operator_name_call(C, "CONSOLE_OT_execute", WM_OP_EXEC_DEFAULT, NULL);
+ for (report = reports->list.last; report; report = report->prev) {
+ if ((report->type & report_mask) &&
+ (report->type & RPT_OPERATOR_ALL | RPT_PROPERTY_ALL) &&
+ (report->flag & SELECT))
+ {
+ console_history_add_str(sc, report->message, 0);
+ WM_operator_name_call(C, "CONSOLE_OT_execute", WM_OP_EXEC_DEFAULT, NULL);
- ED_area_tag_redraw(CTX_wm_area(C));
- }
- }
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+ }
- sc->type = CONSOLE_TYPE_REPORT;
+ sc->type = CONSOLE_TYPE_REPORT;
#endif
- ED_area_tag_redraw(CTX_wm_area(C));
+ ED_area_tag_redraw(CTX_wm_area(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void INFO_OT_report_replay(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Replay Operators";
- ot->description = "Replay selected reports";
- ot->idname = "INFO_OT_report_replay";
+ /* identifiers */
+ ot->name = "Replay Operators";
+ ot->description = "Replay selected reports";
+ ot->idname = "INFO_OT_report_replay";
- /* api callbacks */
- ot->poll = ED_operator_info_active;
- ot->exec = report_replay_exec;
+ /* api callbacks */
+ ot->poll = ED_operator_info_active;
+ ot->exec = report_replay_exec;
- /* flags */
- /* ot->flag = OPTYPE_REGISTER; */
+ /* flags */
+ /* ot->flag = OPTYPE_REGISTER; */
- /* properties */
+ /* properties */
}
static int select_report_pick_exec(bContext *C, wmOperator *op)
{
- int report_index = RNA_int_get(op->ptr, "report_index");
- Report *report = BLI_findlink(&CTX_wm_reports(C)->list, report_index);
+ int report_index = RNA_int_get(op->ptr, "report_index");
+ Report *report = BLI_findlink(&CTX_wm_reports(C)->list, report_index);
- if (!report) {
- return OPERATOR_CANCELLED;
- }
+ if (!report) {
+ return OPERATOR_CANCELLED;
+ }
- report->flag ^= SELECT; /* toggle */
+ report->flag ^= SELECT; /* toggle */
- ED_area_tag_redraw(CTX_wm_area(C));
+ ED_area_tag_redraw(CTX_wm_area(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
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);
- ReportList *reports = CTX_wm_reports(C);
- Report *report;
+ SpaceInfo *sinfo = CTX_wm_space_info(C);
+ ARegion *ar = 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, ar, reports, event->mval[1]);
- RNA_int_set(op->ptr, "report_index", BLI_findindex(&reports->list, report));
+ RNA_int_set(op->ptr, "report_index", BLI_findindex(&reports->list, report));
- return select_report_pick_exec(C, op);
+ return select_report_pick_exec(C, op);
}
-
void INFO_OT_select_pick(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Report";
- ot->description = "Select reports by index";
- ot->idname = "INFO_OT_select_pick";
-
- /* api callbacks */
- ot->poll = ED_operator_info_active;
- ot->invoke = select_report_pick_invoke;
- ot->exec = select_report_pick_exec;
-
- /* flags */
- /* ot->flag = OPTYPE_REGISTER; */
-
- /* properties */
- RNA_def_int(ot->srna, "report_index", 0, 0, INT_MAX, "Report", "Index of the report", 0, INT_MAX);
+ /* identifiers */
+ ot->name = "Select Report";
+ ot->description = "Select reports by index";
+ ot->idname = "INFO_OT_select_pick";
+
+ /* api callbacks */
+ ot->poll = ED_operator_info_active;
+ ot->invoke = select_report_pick_invoke;
+ ot->exec = select_report_pick_exec;
+
+ /* flags */
+ /* ot->flag = OPTYPE_REGISTER; */
+
+ /* properties */
+ RNA_def_int(
+ ot->srna, "report_index", 0, 0, INT_MAX, "Report", "Index of the report", 0, INT_MAX);
}
static int report_select_all_exec(bContext *C, wmOperator *op)
{
- SpaceInfo *sinfo = CTX_wm_space_info(C);
- ReportList *reports = CTX_wm_reports(C);
- const int report_mask = info_report_mask(sinfo);
-
- int action = RNA_enum_get(op->ptr, "action");
-
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
- for (Report *report = reports->list.last; report; report = report->prev) {
- if ((report->type & report_mask) && (report->flag & SELECT)) {
- action = SEL_DESELECT;
- break;
- }
- }
- }
-
- for (Report *report = reports->list.last; report; report = report->prev) {
- if (report->type & report_mask) {
- switch (action) {
- case SEL_SELECT:
- report->flag = SELECT;
- break;
- case SEL_DESELECT:
- report->flag = ~SELECT;
- break;
- case SEL_INVERT:
- report->flag ^= SELECT;
- break;
- default:
- BLI_assert(0);
- }
- }
- }
-
- ED_area_tag_redraw(CTX_wm_area(C));
-
- return OPERATOR_FINISHED;
+ SpaceInfo *sinfo = CTX_wm_space_info(C);
+ ReportList *reports = CTX_wm_reports(C);
+ const int report_mask = info_report_mask(sinfo);
+
+ int action = RNA_enum_get(op->ptr, "action");
+
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+ for (Report *report = reports->list.last; report; report = report->prev) {
+ if ((report->type & report_mask) && (report->flag & SELECT)) {
+ action = SEL_DESELECT;
+ break;
+ }
+ }
+ }
+
+ for (Report *report = reports->list.last; report; report = report->prev) {
+ if (report->type & report_mask) {
+ switch (action) {
+ case SEL_SELECT:
+ report->flag = SELECT;
+ break;
+ case SEL_DESELECT:
+ report->flag = ~SELECT;
+ break;
+ case SEL_INVERT:
+ report->flag ^= SELECT;
+ break;
+ default:
+ BLI_assert(0);
+ }
+ }
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
}
void INFO_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All";
- ot->description = "Change selection of all visible reports";
- ot->idname = "INFO_OT_select_all";
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->description = "Change selection of all visible reports";
+ ot->idname = "INFO_OT_select_all";
- /* api callbacks */
- ot->poll = ED_operator_info_active;
- ot->exec = report_select_all_exec;
+ /* api callbacks */
+ ot->poll = ED_operator_info_active;
+ ot->exec = report_select_all_exec;
- /* properties */
- WM_operator_properties_select_action(ot, SEL_SELECT, true);
+ /* properties */
+ WM_operator_properties_select_action(ot, SEL_SELECT, true);
}
/* box_select operator */
static int box_select_exec(bContext *C, wmOperator *op)
{
- SpaceInfo *sinfo = CTX_wm_space_info(C);
- ARegion *ar = CTX_wm_region(C);
- ReportList *reports = CTX_wm_reports(C);
- int report_mask = info_report_mask(sinfo);
- Report *report_min, *report_max;
- rcti rect;
-
- WM_operator_properties_border_to_rcti(op, &rect);
-
- 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) {
- if ((report->type & report_mask) == 0) {
- continue;
- }
- report->flag &= ~SELECT;
- }
- }
-
- report_min = info_text_pick(sinfo, ar, reports, rect.ymax);
- report_max = info_text_pick(sinfo, ar, 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) {
- if (report->type & report_mask) {
- report_min = report;
- break;
- }
- }
- }
-
- if (report_max == NULL) {
- // printf("find_max\n");
- for (Report *report = reports->list.last; report; report = report->prev) {
- if (report->type & report_mask) {
- report_max = report;
- break;
- }
- }
- }
-
- if (report_min == NULL || report_max == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- for (Report *report = report_min; (report != report_max->next); report = report->next) {
- if ((report->type & report_mask) == 0) {
- continue;
- }
- SET_FLAG_FROM_TEST(report->flag, select, SELECT);
- }
-
- ED_area_tag_redraw(CTX_wm_area(C));
-
- return OPERATOR_FINISHED;
+ SpaceInfo *sinfo = CTX_wm_space_info(C);
+ ARegion *ar = CTX_wm_region(C);
+ ReportList *reports = CTX_wm_reports(C);
+ int report_mask = info_report_mask(sinfo);
+ Report *report_min, *report_max;
+ rcti rect;
+
+ WM_operator_properties_border_to_rcti(op, &rect);
+
+ 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) {
+ if ((report->type & report_mask) == 0) {
+ continue;
+ }
+ report->flag &= ~SELECT;
+ }
+ }
+
+ report_min = info_text_pick(sinfo, ar, reports, rect.ymax);
+ report_max = info_text_pick(sinfo, ar, 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) {
+ if (report->type & report_mask) {
+ report_min = report;
+ break;
+ }
+ }
+ }
+
+ if (report_max == NULL) {
+ // printf("find_max\n");
+ for (Report *report = reports->list.last; report; report = report->prev) {
+ if (report->type & report_mask) {
+ report_max = report;
+ break;
+ }
+ }
+ }
+
+ if (report_min == NULL || report_max == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ for (Report *report = report_min; (report != report_max->next); report = report->next) {
+ if ((report->type & report_mask) == 0) {
+ continue;
+ }
+ SET_FLAG_FROM_TEST(report->flag, select, SELECT);
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
}
-
/* ****** Box Select ****** */
void INFO_OT_select_box(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Box Select";
- ot->description = "Toggle box selection";
- ot->idname = "INFO_OT_select_box";
+ /* identifiers */
+ ot->name = "Box Select";
+ ot->description = "Toggle box selection";
+ ot->idname = "INFO_OT_select_box";
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = box_select_exec;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = box_select_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
- ot->poll = ED_operator_info_active;
+ ot->poll = ED_operator_info_active;
- /* flags */
- /* ot->flag = OPTYPE_REGISTER; */
+ /* flags */
+ /* ot->flag = OPTYPE_REGISTER; */
- /* properties */
- WM_operator_properties_gesture_box(ot);
- WM_operator_properties_select_operation_simple(ot);
+ /* properties */
+ WM_operator_properties_gesture_box(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
static int report_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceInfo *sinfo = CTX_wm_space_info(C);
- ReportList *reports = CTX_wm_reports(C);
- int report_mask = info_report_mask(sinfo);
+ SpaceInfo *sinfo = CTX_wm_space_info(C);
+ ReportList *reports = CTX_wm_reports(C);
+ int report_mask = info_report_mask(sinfo);
+ Report *report, *report_next;
- Report *report, *report_next;
+ for (report = reports->list.first; report;) {
- for (report = reports->list.first; report; ) {
+ report_next = report->next;
- report_next = report->next;
+ if ((report->type & report_mask) && (report->flag & SELECT)) {
+ BLI_remlink(&reports->list, report);
+ MEM_freeN((void *)report->message);
+ MEM_freeN(report);
+ }
- if ((report->type & report_mask) && (report->flag & SELECT)) {
- BLI_remlink(&reports->list, report);
- MEM_freeN((void *)report->message);
- MEM_freeN(report);
- }
+ report = report_next;
+ }
- report = report_next;
- }
+ ED_area_tag_redraw(CTX_wm_area(C));
- ED_area_tag_redraw(CTX_wm_area(C));
-
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void INFO_OT_report_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Reports";
- ot->description = "Delete selected reports";
- ot->idname = "INFO_OT_report_delete";
+ /* identifiers */
+ ot->name = "Delete Reports";
+ ot->description = "Delete selected reports";
+ ot->idname = "INFO_OT_report_delete";
- /* api callbacks */
- ot->poll = ED_operator_info_active;
- ot->exec = report_delete_exec;
+ /* api callbacks */
+ ot->poll = ED_operator_info_active;
+ ot->exec = report_delete_exec;
- /* flags */
- /*ot->flag = OPTYPE_REGISTER;*/
+ /* flags */
+ /*ot->flag = OPTYPE_REGISTER;*/
- /* properties */
+ /* properties */
}
-
static int report_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceInfo *sinfo = CTX_wm_space_info(C);
- ReportList *reports = CTX_wm_reports(C);
- int report_mask = info_report_mask(sinfo);
+ SpaceInfo *sinfo = CTX_wm_space_info(C);
+ ReportList *reports = CTX_wm_reports(C);
+ int report_mask = info_report_mask(sinfo);
- Report *report;
+ Report *report;
- DynStr *buf_dyn = BLI_dynstr_new();
- char *buf_str;
+ DynStr *buf_dyn = BLI_dynstr_new();
+ char *buf_str;
- for (report = reports->list.first; report; report = report->next) {
- if ((report->type & report_mask) && (report->flag & SELECT)) {
- BLI_dynstr_append(buf_dyn, report->message);
- BLI_dynstr_append(buf_dyn, "\n");
- }
- }
+ for (report = reports->list.first; report; report = report->next) {
+ if ((report->type & report_mask) && (report->flag & SELECT)) {
+ BLI_dynstr_append(buf_dyn, report->message);
+ BLI_dynstr_append(buf_dyn, "\n");
+ }
+ }
- buf_str = BLI_dynstr_get_cstring(buf_dyn);
- BLI_dynstr_free(buf_dyn);
+ buf_str = BLI_dynstr_get_cstring(buf_dyn);
+ BLI_dynstr_free(buf_dyn);
- WM_clipboard_text_set(buf_str, 0);
+ WM_clipboard_text_set(buf_str, 0);
- MEM_freeN(buf_str);
- return OPERATOR_FINISHED;
+ MEM_freeN(buf_str);
+ return OPERATOR_FINISHED;
}
void INFO_OT_report_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Reports to Clipboard";
- ot->description = "Copy selected reports to Clipboard";
- ot->idname = "INFO_OT_report_copy";
+ /* identifiers */
+ ot->name = "Copy Reports to Clipboard";
+ ot->description = "Copy selected reports to Clipboard";
+ ot->idname = "INFO_OT_report_copy";
- /* api callbacks */
- ot->poll = ED_operator_info_active;
- ot->exec = report_copy_exec;
+ /* api callbacks */
+ ot->poll = ED_operator_info_active;
+ ot->exec = report_copy_exec;
- /* flags */
- /*ot->flag = OPTYPE_REGISTER;*/
+ /* flags */
+ /*ot->flag = OPTYPE_REGISTER;*/
- /* properties */
+ /* properties */
}
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 054e9cd0026..3ef9a12e0c9 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -18,7 +18,6 @@
* \ingroup spinfo
*/
-
#include <stdio.h>
#include <string.h>
@@ -67,457 +66,480 @@
#define MAX_INFO_NUM_LEN 16
typedef struct SceneStats {
- uint64_t totvert, totvertsel;
- uint64_t totedge, totedgesel;
- uint64_t totface, totfacesel;
- uint64_t totbone, totbonesel;
- uint64_t totobj, totobjsel;
- uint64_t totlamp, totlampsel;
- uint64_t tottri;
- uint64_t totgplayer, totgpframe, totgpstroke, totgppoint;
-
- char infostr[MAX_INFO_LEN];
+ uint64_t totvert, totvertsel;
+ uint64_t totedge, totedgesel;
+ uint64_t totface, totfacesel;
+ uint64_t totbone, totbonesel;
+ uint64_t totobj, totobjsel;
+ uint64_t totlamp, totlampsel;
+ uint64_t tottri;
+ uint64_t totgplayer, totgpframe, totgpstroke, totgppoint;
+
+ char infostr[MAX_INFO_LEN];
} SceneStats;
typedef struct SceneStatsFmt {
- /* Totals */
- char totvert[MAX_INFO_NUM_LEN], totvertsel[MAX_INFO_NUM_LEN];
- char totface[MAX_INFO_NUM_LEN], totfacesel[MAX_INFO_NUM_LEN];
- char totedge[MAX_INFO_NUM_LEN], totedgesel[MAX_INFO_NUM_LEN];
- char totbone[MAX_INFO_NUM_LEN], totbonesel[MAX_INFO_NUM_LEN];
- char totobj[MAX_INFO_NUM_LEN], totobjsel[MAX_INFO_NUM_LEN];
- char totlamp[MAX_INFO_NUM_LEN], totlampsel[MAX_INFO_NUM_LEN];
- char tottri[MAX_INFO_NUM_LEN];
- char totgplayer[MAX_INFO_NUM_LEN], totgpframe[MAX_INFO_NUM_LEN];
- char totgpstroke[MAX_INFO_NUM_LEN], totgppoint[MAX_INFO_NUM_LEN];
+ /* Totals */
+ char totvert[MAX_INFO_NUM_LEN], totvertsel[MAX_INFO_NUM_LEN];
+ char totface[MAX_INFO_NUM_LEN], totfacesel[MAX_INFO_NUM_LEN];
+ char totedge[MAX_INFO_NUM_LEN], totedgesel[MAX_INFO_NUM_LEN];
+ char totbone[MAX_INFO_NUM_LEN], totbonesel[MAX_INFO_NUM_LEN];
+ char totobj[MAX_INFO_NUM_LEN], totobjsel[MAX_INFO_NUM_LEN];
+ char totlamp[MAX_INFO_NUM_LEN], totlampsel[MAX_INFO_NUM_LEN];
+ char tottri[MAX_INFO_NUM_LEN];
+ char totgplayer[MAX_INFO_NUM_LEN], totgpframe[MAX_INFO_NUM_LEN];
+ char totgpstroke[MAX_INFO_NUM_LEN], totgppoint[MAX_INFO_NUM_LEN];
} SceneStatsFmt;
static bool stats_mesheval(Mesh *me_eval, bool is_selected, SceneStats *stats)
{
- if (me_eval == NULL) {
- return false;
- }
-
- int totvert, totedge, totface, totloop;
- if (me_eval->runtime.subdiv_ccg != NULL) {
- const SubdivCCG *subdiv_ccg = me_eval->runtime.subdiv_ccg;
- BKE_subdiv_ccg_topology_counters(
- subdiv_ccg, &totvert, &totedge, &totface, &totloop);
- }
- else {
- totvert = me_eval->totvert;
- totedge = me_eval->totedge;
- totface = me_eval->totpoly;
- totloop = me_eval->totloop;
- }
-
- stats->totvert += totvert;
- stats->totedge += totedge;
- stats->totface += totface;
- stats->tottri += poly_to_tri_count(totface, totloop);
-
- if (is_selected) {
- stats->totvertsel += totvert;
- stats->totfacesel += totface;
- }
- return true;
+ if (me_eval == NULL) {
+ return false;
+ }
+
+ int totvert, totedge, totface, totloop;
+ if (me_eval->runtime.subdiv_ccg != NULL) {
+ const SubdivCCG *subdiv_ccg = me_eval->runtime.subdiv_ccg;
+ BKE_subdiv_ccg_topology_counters(subdiv_ccg, &totvert, &totedge, &totface, &totloop);
+ }
+ else {
+ totvert = me_eval->totvert;
+ totedge = me_eval->totedge;
+ totface = me_eval->totpoly;
+ totloop = me_eval->totloop;
+ }
+
+ stats->totvert += totvert;
+ stats->totedge += totedge;
+ stats->totface += totface;
+ stats->tottri += poly_to_tri_count(totface, totloop);
+
+ if (is_selected) {
+ stats->totvertsel += totvert;
+ stats->totfacesel += totface;
+ }
+ return true;
}
static void stats_object(Object *ob, SceneStats *stats)
{
- const bool is_selected = (ob->base_flag & BASE_SELECTED) != 0;
-
- stats->totobj++;
- if (is_selected) {
- stats->totobjsel++;
- }
-
- 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;
- stats_mesheval(me_eval, is_selected, stats);
- break;
- }
- case OB_LAMP:
- stats->totlamp++;
- if (is_selected) {
- stats->totlampsel++;
- }
- break;
- case OB_SURF:
- case OB_CURVE:
- case OB_FONT:
- {
- Mesh *me_eval = ob->runtime.mesh_eval;
- if (stats_mesheval(me_eval, is_selected, stats)) {
- break;
- }
- ATTR_FALLTHROUGH; /* Falltrough to displist. */
- }
- case OB_MBALL:
- {
- int totv = 0, totf = 0, tottri = 0;
-
- if (ob->runtime.curve_cache && ob->runtime.curve_cache->disp.first) {
- BKE_displist_count(&ob->runtime.curve_cache->disp, &totv, &totf, &tottri);
- }
-
- stats->totvert += totv;
- stats->totface += totf;
- stats->tottri += tottri;
-
- if (is_selected) {
- stats->totvertsel += totv;
- stats->totfacesel += totf;
- }
- break;
- }
- case OB_GPENCIL:
- {
- if (is_selected) {
- bGPdata *gpd = (bGPdata *)ob->data;
- /* GPXX Review if we can move to other place when object change
- * maybe to depsgraph evaluation
- */
- BKE_gpencil_stats_update(gpd);
-
- stats->totgplayer += gpd->totlayer;
- stats->totgpframe += gpd->totframe;
- stats->totgpstroke += gpd->totstroke;
- stats->totgppoint += gpd->totpoint;
- }
- break;
- }
- }
+ const bool is_selected = (ob->base_flag & BASE_SELECTED) != 0;
+
+ stats->totobj++;
+ if (is_selected) {
+ stats->totobjsel++;
+ }
+
+ 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;
+ stats_mesheval(me_eval, is_selected, stats);
+ break;
+ }
+ case OB_LAMP:
+ stats->totlamp++;
+ if (is_selected) {
+ stats->totlampsel++;
+ }
+ break;
+ case OB_SURF:
+ case OB_CURVE:
+ case OB_FONT: {
+ Mesh *me_eval = ob->runtime.mesh_eval;
+ if (stats_mesheval(me_eval, is_selected, stats)) {
+ break;
+ }
+ ATTR_FALLTHROUGH; /* Falltrough to displist. */
+ }
+ case OB_MBALL: {
+ int totv = 0, totf = 0, tottri = 0;
+
+ if (ob->runtime.curve_cache && ob->runtime.curve_cache->disp.first) {
+ BKE_displist_count(&ob->runtime.curve_cache->disp, &totv, &totf, &tottri);
+ }
+
+ stats->totvert += totv;
+ stats->totface += totf;
+ stats->tottri += tottri;
+
+ if (is_selected) {
+ stats->totvertsel += totv;
+ stats->totfacesel += totf;
+ }
+ break;
+ }
+ case OB_GPENCIL: {
+ if (is_selected) {
+ bGPdata *gpd = (bGPdata *)ob->data;
+ /* GPXX Review if we can move to other place when object change
+ * maybe to depsgraph evaluation
+ */
+ BKE_gpencil_stats_update(gpd);
+
+ stats->totgplayer += gpd->totlayer;
+ stats->totgpframe += gpd->totframe;
+ stats->totgpstroke += gpd->totstroke;
+ stats->totgppoint += gpd->totpoint;
+ }
+ break;
+ }
+ }
}
static void stats_object_edit(Object *obedit, SceneStats *stats)
{
- if (obedit->type == OB_MESH) {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- stats->totvert += em->bm->totvert;
- stats->totvertsel += em->bm->totvertsel;
-
- stats->totedge += em->bm->totedge;
- stats->totedgesel += em->bm->totedgesel;
-
- stats->totface += em->bm->totface;
- stats->totfacesel += em->bm->totfacesel;
-
- stats->tottri += em->tottri;
- }
- else if (obedit->type == OB_ARMATURE) {
- /* Armature Edit */
- bArmature *arm = obedit->data;
- EditBone *ebo;
-
- for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
- stats->totbone++;
-
- if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
- stats->totvert--;
- }
-
- if (ebo->flag & BONE_TIPSEL) {
- stats->totvertsel++;
- }
- if (ebo->flag & BONE_ROOTSEL) {
- stats->totvertsel++;
- }
-
- if (ebo->flag & BONE_SELECTED) {
- stats->totbonesel++;
- }
-
- /* if this is a connected child and it's parent is being moved, remove our root */
- if ((ebo->flag & BONE_CONNECTED) && (ebo->flag & BONE_ROOTSEL) &&
- ebo->parent && (ebo->parent->flag & BONE_TIPSEL))
- {
- stats->totvertsel--;
- }
-
- stats->totvert += 2;
- }
- }
- else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { /* OB_FONT has no cu->editnurb */
- /* Curve Edit */
- Curve *cu = obedit->data;
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
- ListBase *nurbs = BKE_curve_editNurbs_get(cu);
-
- for (nu = nurbs->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- stats->totvert += 3;
- if (bezt->f1 & SELECT) {
- stats->totvertsel++;
- }
- if (bezt->f2 & SELECT) {
- stats->totvertsel++;
- }
- if (bezt->f3 & SELECT) {
- stats->totvertsel++;
- }
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- stats->totvert++;
- if (bp->f1 & SELECT) {
- stats->totvertsel++;
- }
- bp++;
- }
- }
- }
- }
- else if (obedit->type == OB_MBALL) {
- /* MetaBall Edit */
- MetaBall *mball = obedit->data;
- MetaElem *ml;
-
- for (ml = mball->editelems->first; ml; ml = ml->next) {
- stats->totvert++;
- if (ml->flag & SELECT) {
- stats->totvertsel++;
- }
- }
- }
- else if (obedit->type == OB_LATTICE) {
- /* Lattice Edit */
- Lattice *lt = obedit->data;
- Lattice *editlatt = lt->editlatt->latt;
- BPoint *bp;
- int a;
-
- bp = editlatt->def;
-
- a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
- while (a--) {
- stats->totvert++;
- if (bp->f1 & SELECT) {
- stats->totvertsel++;
- }
- bp++;
- }
- }
+ if (obedit->type == OB_MESH) {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ stats->totvert += em->bm->totvert;
+ stats->totvertsel += em->bm->totvertsel;
+
+ stats->totedge += em->bm->totedge;
+ stats->totedgesel += em->bm->totedgesel;
+
+ stats->totface += em->bm->totface;
+ stats->totfacesel += em->bm->totfacesel;
+
+ stats->tottri += em->tottri;
+ }
+ else if (obedit->type == OB_ARMATURE) {
+ /* Armature Edit */
+ bArmature *arm = obedit->data;
+ EditBone *ebo;
+
+ for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ stats->totbone++;
+
+ if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
+ stats->totvert--;
+ }
+
+ if (ebo->flag & BONE_TIPSEL) {
+ stats->totvertsel++;
+ }
+ if (ebo->flag & BONE_ROOTSEL) {
+ stats->totvertsel++;
+ }
+
+ if (ebo->flag & BONE_SELECTED) {
+ stats->totbonesel++;
+ }
+
+ /* if this is a connected child and it's parent is being moved, remove our root */
+ if ((ebo->flag & BONE_CONNECTED) && (ebo->flag & BONE_ROOTSEL) && ebo->parent &&
+ (ebo->parent->flag & BONE_TIPSEL)) {
+ stats->totvertsel--;
+ }
+
+ stats->totvert += 2;
+ }
+ }
+ else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { /* OB_FONT has no cu->editnurb */
+ /* Curve Edit */
+ Curve *cu = obedit->data;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+
+ for (nu = nurbs->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ stats->totvert += 3;
+ if (bezt->f1 & SELECT) {
+ stats->totvertsel++;
+ }
+ if (bezt->f2 & SELECT) {
+ stats->totvertsel++;
+ }
+ if (bezt->f3 & SELECT) {
+ stats->totvertsel++;
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ stats->totvert++;
+ if (bp->f1 & SELECT) {
+ stats->totvertsel++;
+ }
+ bp++;
+ }
+ }
+ }
+ }
+ else if (obedit->type == OB_MBALL) {
+ /* MetaBall Edit */
+ MetaBall *mball = obedit->data;
+ MetaElem *ml;
+
+ for (ml = mball->editelems->first; ml; ml = ml->next) {
+ stats->totvert++;
+ if (ml->flag & SELECT) {
+ stats->totvertsel++;
+ }
+ }
+ }
+ else if (obedit->type == OB_LATTICE) {
+ /* Lattice Edit */
+ Lattice *lt = obedit->data;
+ Lattice *editlatt = lt->editlatt->latt;
+ BPoint *bp;
+ int a;
+
+ bp = editlatt->def;
+
+ a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
+ while (a--) {
+ stats->totvert++;
+ if (bp->f1 & SELECT) {
+ stats->totvertsel++;
+ }
+ bp++;
+ }
+ }
}
static void stats_object_pose(Object *ob, SceneStats *stats)
{
- if (ob->pose) {
- bArmature *arm = ob->data;
- bPoseChannel *pchan;
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- stats->totbone++;
- if (pchan->bone && (pchan->bone->flag & BONE_SELECTED)) {
- if (pchan->bone->layer & arm->layer) {
- stats->totbonesel++;
- }
- }
- }
- }
+ if (ob->pose) {
+ bArmature *arm = ob->data;
+ bPoseChannel *pchan;
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ stats->totbone++;
+ if (pchan->bone && (pchan->bone->flag & BONE_SELECTED)) {
+ if (pchan->bone->layer & arm->layer) {
+ stats->totbonesel++;
+ }
+ }
+ }
+ }
}
static void stats_object_sculpt_dynamic_topology(Object *ob, SceneStats *stats)
{
- stats->totvert = ob->sculpt->bm->totvert;
- stats->tottri = ob->sculpt->bm->totface;
+ stats->totvert = ob->sculpt->bm->totvert;
+ stats->tottri = ob->sculpt->bm->totface;
}
static bool stats_is_object_dynamic_topology_sculpt(Object *ob, const eObjectMode object_mode)
{
- return (ob &&
- (object_mode & OB_MODE_SCULPT) &&
- ob->sculpt && ob->sculpt->bm);
+ return (ob && (object_mode & OB_MODE_SCULPT) && ob->sculpt && ob->sculpt->bm);
}
/* Statistics displayed in info header. Called regularly on scene changes. */
static void stats_update(Depsgraph *depsgraph, ViewLayer *view_layer)
{
- SceneStats stats = {0};
- Object *ob = OBACT(view_layer);
- Object *obedit = OBEDIT_FROM_VIEW_LAYER(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_IN_MODE_END;
- }
- else if (ob && (ob->mode & OB_MODE_POSE)) {
- /* Pose Mode */
- stats_object_pose(ob, &stats);
- }
- else if (ob && stats_is_object_dynamic_topology_sculpt(ob, ob->mode)) {
- /* Dynamic-topology sculpt mode */
- stats_object_sculpt_dynamic_topology(ob, &stats);
- }
- else {
- /* Objects */
- DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN(depsgraph, ob_iter)
- {
- stats_object(ob_iter, &stats);
- }
- DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
- }
-
- if (!view_layer->stats) {
- view_layer->stats = MEM_callocN(sizeof(SceneStats), "SceneStats");
- }
-
- *(view_layer->stats) = stats;
+ SceneStats stats = {0};
+ Object *ob = OBACT(view_layer);
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(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_IN_MODE_END;
+ }
+ else if (ob && (ob->mode & OB_MODE_POSE)) {
+ /* Pose Mode */
+ stats_object_pose(ob, &stats);
+ }
+ else if (ob && stats_is_object_dynamic_topology_sculpt(ob, ob->mode)) {
+ /* Dynamic-topology sculpt mode */
+ stats_object_sculpt_dynamic_topology(ob, &stats);
+ }
+ else {
+ /* Objects */
+ DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob_iter) {
+ stats_object(ob_iter, &stats);
+ }
+ DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
+ }
+
+ if (!view_layer->stats) {
+ view_layer->stats = MEM_callocN(sizeof(SceneStats), "SceneStats");
+ }
+
+ *(view_layer->stats) = stats;
}
static void stats_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();
+#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();
- /* Generate formatted numbers */
-#define SCENE_STATS_FMT_INT(_id) \
- BLI_str_format_uint64_grouped(stats_fmt._id, stats->_id)
+ /* Generate formatted numbers */
+#define SCENE_STATS_FMT_INT(_id) BLI_str_format_uint64_grouped(stats_fmt._id, stats->_id)
- SCENE_STATS_FMT_INT(totvert);
- SCENE_STATS_FMT_INT(totvertsel);
+ SCENE_STATS_FMT_INT(totvert);
+ SCENE_STATS_FMT_INT(totvertsel);
- SCENE_STATS_FMT_INT(totedge);
- SCENE_STATS_FMT_INT(totedgesel);
+ SCENE_STATS_FMT_INT(totedge);
+ SCENE_STATS_FMT_INT(totedgesel);
- SCENE_STATS_FMT_INT(totface);
- SCENE_STATS_FMT_INT(totfacesel);
+ SCENE_STATS_FMT_INT(totface);
+ SCENE_STATS_FMT_INT(totfacesel);
- SCENE_STATS_FMT_INT(totbone);
- SCENE_STATS_FMT_INT(totbonesel);
+ SCENE_STATS_FMT_INT(totbone);
+ SCENE_STATS_FMT_INT(totbonesel);
- SCENE_STATS_FMT_INT(totobj);
- SCENE_STATS_FMT_INT(totobjsel);
+ SCENE_STATS_FMT_INT(totobj);
+ SCENE_STATS_FMT_INT(totobjsel);
- SCENE_STATS_FMT_INT(totlamp);
- SCENE_STATS_FMT_INT(totlampsel);
+ SCENE_STATS_FMT_INT(totlamp);
+ SCENE_STATS_FMT_INT(totlampsel);
- SCENE_STATS_FMT_INT(tottri);
+ SCENE_STATS_FMT_INT(tottri);
- SCENE_STATS_FMT_INT(totgplayer);
- SCENE_STATS_FMT_INT(totgpframe);
- SCENE_STATS_FMT_INT(totgpstroke);
- SCENE_STATS_FMT_INT(totgppoint);
+ SCENE_STATS_FMT_INT(totgplayer);
+ SCENE_STATS_FMT_INT(totgpframe);
+ SCENE_STATS_FMT_INT(totgpstroke);
+ SCENE_STATS_FMT_INT(totgppoint);
#undef SCENE_STATS_FMT_INT
-
- /* get memory statistics */
- BLI_str_format_byte_unit(formatted_mem, mem_in_use - mmap_in_use, true);
- ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, IFACE_(" | Mem: %s"), formatted_mem);
-
- if (mmap_in_use) {
- BLI_str_format_byte_unit(formatted_mem, mmap_in_use, true);
- BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%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, true);
- ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, IFACE_(" | Free GPU Mem: %s"), formatted_mem);
-
- if (gpu_tot_memory) {
- BLI_str_format_byte_unit(formatted_mem, gpu_tot_memory, true);
- BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_("/%s"), formatted_mem);
- }
- }
-
- s = stats->infostr;
- ofs = 0;
-
- 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);
- }
-
- if (obedit) {
- if (BKE_keyblock_from_object(obedit)) {
- ofs += BLI_strncpy_rlen(s + ofs, IFACE_("(Key) "), MAX_INFO_LEN - ofs);
- }
-
- if (obedit->type == OB_MESH) {
- ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs,
- IFACE_("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);
- }
- else if (obedit->type == OB_ARMATURE) {
- ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s/%s | Bones:%s/%s"), stats_fmt.totvertsel,
- stats_fmt.totvert, stats_fmt.totbonesel, stats_fmt.totbone);
- }
- else {
- ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s/%s"), stats_fmt.totvertsel,
- stats_fmt.totvert);
- }
-
- 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, IFACE_("Bones:%s/%s %s%s"),
- stats_fmt.totbonesel, stats_fmt.totbone, memstr, gpumemstr);
- }
- else if ((ob) && (ob->type == OB_GPENCIL)) {
- ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs,
- IFACE_("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);
- }
- else if (stats_is_object_dynamic_topology_sculpt(ob, object_mode)) {
- ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s | Tris:%s%s"), stats_fmt.totvert,
- stats_fmt.tottri, gpumemstr);
- }
- else {
- ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs,
- IFACE_("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);
+ /* get memory statistics */
+ BLI_str_format_byte_unit(formatted_mem, mem_in_use - mmap_in_use, true);
+ ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, IFACE_(" | Mem: %s"), formatted_mem);
+
+ if (mmap_in_use) {
+ BLI_str_format_byte_unit(formatted_mem, mmap_in_use, true);
+ BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%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, true);
+ ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, IFACE_(" | Free GPU Mem: %s"), formatted_mem);
+
+ if (gpu_tot_memory) {
+ BLI_str_format_byte_unit(formatted_mem, gpu_tot_memory, true);
+ BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_("/%s"), formatted_mem);
+ }
+ }
+
+ s = stats->infostr;
+ ofs = 0;
+
+ 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);
+ }
+
+ if (obedit) {
+ if (BKE_keyblock_from_object(obedit)) {
+ ofs += BLI_strncpy_rlen(s + ofs, IFACE_("(Key) "), MAX_INFO_LEN - ofs);
+ }
+
+ if (obedit->type == OB_MESH) {
+ ofs += BLI_snprintf(s + ofs,
+ MAX_INFO_LEN - ofs,
+ IFACE_("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);
+ }
+ else if (obedit->type == OB_ARMATURE) {
+ ofs += BLI_snprintf(s + ofs,
+ MAX_INFO_LEN - ofs,
+ IFACE_("Verts:%s/%s | Bones:%s/%s"),
+ stats_fmt.totvertsel,
+ stats_fmt.totvert,
+ stats_fmt.totbonesel,
+ stats_fmt.totbone);
+ }
+ else {
+ ofs += BLI_snprintf(s + ofs,
+ MAX_INFO_LEN - ofs,
+ IFACE_("Verts:%s/%s"),
+ stats_fmt.totvertsel,
+ stats_fmt.totvert);
+ }
+
+ 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,
+ IFACE_("Bones:%s/%s %s%s"),
+ stats_fmt.totbonesel,
+ stats_fmt.totbone,
+ memstr,
+ gpumemstr);
+ }
+ else if ((ob) && (ob->type == OB_GPENCIL)) {
+ ofs += BLI_snprintf(s + ofs,
+ MAX_INFO_LEN - ofs,
+ IFACE_("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);
+ }
+ else if (stats_is_object_dynamic_topology_sculpt(ob, object_mode)) {
+ ofs += BLI_snprintf(s + ofs,
+ MAX_INFO_LEN - ofs,
+ IFACE_("Verts:%s | Tris:%s%s"),
+ stats_fmt.totvert,
+ stats_fmt.tottri,
+ gpumemstr);
+ }
+ else {
+ ofs += BLI_snprintf(s + ofs,
+ MAX_INFO_LEN - ofs,
+ IFACE_("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
}
@@ -525,25 +547,25 @@ static void stats_string(ViewLayer *view_layer)
void ED_info_stats_clear(ViewLayer *view_layer)
{
- if (view_layer->stats) {
- MEM_freeN(view_layer->stats);
- view_layer->stats = NULL;
- }
+ if (view_layer->stats) {
+ MEM_freeN(view_layer->stats);
+ view_layer->stats = NULL;
+ }
}
const char *ED_info_stats_string(Main *bmain, Scene *scene, ViewLayer *view_layer)
{
- /* Loopin 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(scene, view_layer, true);
- if (!view_layer->stats) {
- stats_update(depsgraph, view_layer);
- }
- stats_string(view_layer);
- return view_layer->stats->infostr;
+ /* Loopin 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(scene, view_layer, true);
+ if (!view_layer->stats) {
+ stats_update(depsgraph, view_layer);
+ }
+ stats_string(view_layer);
+ return view_layer->stats->infostr;
}
diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c
index 997a40839ac..6ed9d80d145 100644
--- a/source/blender/editors/space_info/space_info.c
+++ b/source/blender/editors/space_info/space_info.c
@@ -21,7 +21,6 @@
* \ingroup spinfo
*/
-
#include <string.h>
#include <stdio.h>
@@ -48,7 +47,7 @@
#include "UI_interface.h"
#include "UI_view2d.h"
-#include "info_intern.h" /* own include */
+#include "info_intern.h" /* own include */
#include "BLO_readfile.h"
#include "GPU_framebuffer.h"
@@ -56,270 +55,271 @@
static SpaceLink *info_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
- SpaceInfo *sinfo;
+ ARegion *ar;
+ SpaceInfo *sinfo;
- sinfo = MEM_callocN(sizeof(SpaceInfo), "initinfo");
- sinfo->spacetype = SPACE_INFO;
+ sinfo = MEM_callocN(sizeof(SpaceInfo), "initinfo");
+ sinfo->spacetype = SPACE_INFO;
- sinfo->rpt_mask = INFO_RPT_OP;
+ sinfo->rpt_mask = INFO_RPT_OP;
- /* header */
- ar = MEM_callocN(sizeof(ARegion), "header for info");
+ /* header */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_HEADER;
+ ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
- /* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for info");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for info");
- BLI_addtail(&sinfo->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&sinfo->regionbase, ar);
+ ar->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;
+ /* 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;
- /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
- //ar->v2d.keepzoom = (V2D_KEEPASPECT|V2D_LIMITZOOM);
+ /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
+ //ar->v2d.keepzoom = (V2D_KEEPASPECT|V2D_LIMITZOOM);
- return (SpaceLink *)sinfo;
+ return (SpaceLink *)sinfo;
}
/* not spacelink itself */
static void info_free(SpaceLink *UNUSED(sl))
{
-// SpaceInfo *sinfo = (SpaceInfo *) sl;
-
+ // SpaceInfo *sinfo = (SpaceInfo *) sl;
}
-
/* spacetype; init callback */
static void info_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
{
-
}
static SpaceLink *info_duplicate(SpaceLink *sl)
{
- SpaceInfo *sinfon = MEM_dupallocN(sl);
+ SpaceInfo *sinfon = MEM_dupallocN(sl);
- /* clear or remove stuff from old */
+ /* clear or remove stuff from old */
- return (SpaceLink *)sinfon;
+ return (SpaceLink *)sinfon;
}
-
-
/* add handlers, stuff you only do once or on area/region changes */
static void info_main_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- /* force it on init, for old files, until it becomes config */
- ar->v2d.scroll = (V2D_SCROLL_RIGHT);
+ /* force it on init, for old files, until it becomes config */
+ ar->v2d.scroll = (V2D_SCROLL_RIGHT);
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
- /* own keymap */
- keymap = WM_keymap_ensure(wm->defaultconf, "Info", SPACE_INFO, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ /* own keymap */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Info", SPACE_INFO, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
}
static void info_textview_update_rect(const bContext *C, ARegion *ar)
{
- SpaceInfo *sinfo = CTX_wm_space_info(C);
- View2D *v2d = &ar->v2d;
+ SpaceInfo *sinfo = CTX_wm_space_info(C);
+ View2D *v2d = &ar->v2d;
- UI_view2d_totRect_set(v2d, ar->winx - 1, info_textview_height(sinfo, ar, CTX_wm_reports(C)));
+ UI_view2d_totRect_set(v2d, ar->winx - 1, info_textview_height(sinfo, ar, CTX_wm_reports(C)));
}
static void info_main_region_draw(const bContext *C, ARegion *ar)
{
- /* draw entirely, view changes should be handled here */
- SpaceInfo *sinfo = CTX_wm_space_info(C);
- View2D *v2d = &ar->v2d;
- View2DScrollers *scrollers;
+ /* draw entirely, view changes should be handled here */
+ SpaceInfo *sinfo = CTX_wm_space_info(C);
+ View2D *v2d = &ar->v2d;
+ View2DScrollers *scrollers;
- /* clear and setup matrix */
- UI_ThemeClearColor(TH_BACK);
- GPU_clear(GPU_COLOR_BIT);
+ /* clear and setup matrix */
+ UI_ThemeClearColor(TH_BACK);
+ GPU_clear(GPU_COLOR_BIT);
- /* quick way to avoid drawing if not bug enough */
- if (ar->winy < 16) {
- return;
- }
+ /* quick way to avoid drawing if not bug enough */
+ if (ar->winy < 16) {
+ return;
+ }
- info_textview_update_rect(C, ar);
+ info_textview_update_rect(C, ar);
- /* worlks best with no view2d matrix set */
- UI_view2d_view_ortho(v2d);
+ /* 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, ar, CTX_wm_reports(C));
- /* reset view matrix */
- UI_view2d_view_restore(C);
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
- /* scrollers */
- scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_GRID_CLAMP);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
+ /* scrollers */
+ scrollers = UI_view2d_scrollers_calc(
+ C, v2d, NULL, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_GRID_CLAMP);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
}
static void info_operatortypes(void)
{
- WM_operatortype_append(FILE_OT_autopack_toggle);
- WM_operatortype_append(FILE_OT_pack_all);
- WM_operatortype_append(FILE_OT_pack_libraries);
- WM_operatortype_append(FILE_OT_unpack_all);
- WM_operatortype_append(FILE_OT_unpack_item);
- WM_operatortype_append(FILE_OT_unpack_libraries);
-
- WM_operatortype_append(FILE_OT_make_paths_relative);
- WM_operatortype_append(FILE_OT_make_paths_absolute);
- WM_operatortype_append(FILE_OT_report_missing_files);
- WM_operatortype_append(FILE_OT_find_missing_files);
- WM_operatortype_append(INFO_OT_reports_display_update);
-
- /* info_report.c */
- WM_operatortype_append(INFO_OT_select_pick);
- WM_operatortype_append(INFO_OT_select_all);
- WM_operatortype_append(INFO_OT_select_box);
-
- WM_operatortype_append(INFO_OT_report_replay);
- WM_operatortype_append(INFO_OT_report_delete);
- WM_operatortype_append(INFO_OT_report_copy);
+ WM_operatortype_append(FILE_OT_autopack_toggle);
+ WM_operatortype_append(FILE_OT_pack_all);
+ WM_operatortype_append(FILE_OT_pack_libraries);
+ WM_operatortype_append(FILE_OT_unpack_all);
+ WM_operatortype_append(FILE_OT_unpack_item);
+ WM_operatortype_append(FILE_OT_unpack_libraries);
+
+ WM_operatortype_append(FILE_OT_make_paths_relative);
+ WM_operatortype_append(FILE_OT_make_paths_absolute);
+ WM_operatortype_append(FILE_OT_report_missing_files);
+ WM_operatortype_append(FILE_OT_find_missing_files);
+ WM_operatortype_append(INFO_OT_reports_display_update);
+
+ /* info_report.c */
+ WM_operatortype_append(INFO_OT_select_pick);
+ WM_operatortype_append(INFO_OT_select_all);
+ WM_operatortype_append(INFO_OT_select_box);
+
+ WM_operatortype_append(INFO_OT_report_replay);
+ WM_operatortype_append(INFO_OT_report_delete);
+ WM_operatortype_append(INFO_OT_report_copy);
}
static void info_keymap(struct wmKeyConfig *keyconf)
{
- WM_keymap_ensure(keyconf, "Window", 0, 0);
- WM_keymap_ensure(keyconf, "Info", SPACE_INFO, 0);
+ WM_keymap_ensure(keyconf, "Window", 0, 0);
+ WM_keymap_ensure(keyconf, "Info", SPACE_INFO, 0);
}
/* add handlers, stuff you only do once or on area/region changes */
static void info_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
- ED_region_header_init(ar);
+ ED_region_header_init(ar);
}
static void info_header_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_header(C, ar);
+ ED_region_header(C, ar);
}
-static void info_main_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void info_main_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- // SpaceInfo *sinfo = sa->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);
- }
- break;
- }
+ // SpaceInfo *sinfo = sa->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);
+ }
+ break;
+ }
}
-static void info_header_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void info_header_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_SCREEN:
- if (ELEM(wmn->data, ND_LAYER, ND_ANIMPLAY)) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_WM:
- if (wmn->data == ND_JOB) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SCENE:
- if (wmn->data == ND_RENDER_RESULT) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_INFO) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_ID:
- if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
-
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SCREEN:
+ if (ELEM(wmn->data, ND_LAYER, ND_ANIMPLAY)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_WM:
+ if (wmn->data == ND_JOB) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SCENE:
+ if (wmn->data == ND_RENDER_RESULT) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_INFO) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_ID:
+ if (wmn->action == NA_RENAME) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
}
-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,
- struct wmMsgBus *mbus)
+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,
+ struct wmMsgBus *mbus)
{
- wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
- .notify = ED_region_do_msg_notify_tag_redraw,
- };
-
- WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
- WM_msg_subscribe_rna_anon_prop(mbus, ViewLayer, name, &msg_sub_value_region_tag_redraw);
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(mbus, ViewLayer, name, &msg_sub_value_region_tag_redraw);
}
/* only called once, from space/spacetypes.c */
void ED_spacetype_info(void)
{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype info");
- ARegionType *art;
+ SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype info");
+ ARegionType *art;
- st->spaceid = SPACE_INFO;
- strncpy(st->name, "Info", BKE_ST_MAXNAME);
+ st->spaceid = SPACE_INFO;
+ strncpy(st->name, "Info", BKE_ST_MAXNAME);
- st->new = info_new;
- st->free = info_free;
- st->init = info_init;
- st->duplicate = info_duplicate;
- st->operatortypes = info_operatortypes;
- st->keymap = info_keymap;
+ st->new = info_new;
+ st->free = info_free;
+ st->init = info_init;
+ st->duplicate = info_duplicate;
+ st->operatortypes = info_operatortypes;
+ st->keymap = info_keymap;
- /* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype info region");
- art->regionid = RGN_TYPE_WINDOW;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES;
+ /* regions: main window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype info region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES;
- art->init = info_main_region_init;
- art->draw = info_main_region_draw;
- art->listener = info_main_region_listener;
+ art->init = info_main_region_init;
+ art->draw = info_main_region_draw;
+ art->listener = info_main_region_listener;
- BLI_addhead(&st->regiontypes, art);
+ BLI_addhead(&st->regiontypes, art);
- /* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype info region");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = HEADERY;
+ /* regions: header */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype info region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
- art->listener = info_header_listener;
- art->message_subscribe = info_header_region_message_subscribe;
- art->init = info_header_region_init;
- art->draw = info_header_region_draw;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
+ art->listener = info_header_listener;
+ art->message_subscribe = info_header_region_message_subscribe;
+ art->init = info_header_region_init;
+ art->draw = info_header_region_draw;
- BLI_addhead(&st->regiontypes, art);
+ BLI_addhead(&st->regiontypes, art);
- BKE_spacetype_register(st);
+ BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index 7585cda5e19..c81e7574186 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -18,7 +18,6 @@
* \ingroup spinfo
*/
-
#include <math.h>
#include <string.h>
#include <sys/stat.h>
@@ -36,344 +35,357 @@
#include "GPU_immediate.h"
#include "GPU_state.h"
-
#include "BKE_text.h"
#include "textview.h"
static void console_font_begin(const int font_id, const int lheight)
{
- /* 0.875 is based on: 16 pixels lines get 14 pixel text */
- BLF_size(font_id, 0.875 * lheight, 72);
+ /* 0.875 is based on: 16 pixels lines get 14 pixel text */
+ BLF_size(font_id, 0.875 * lheight, 72);
}
typedef struct ConsoleDrawContext {
- int font_id;
- int cwidth;
- int lheight;
- /** text vertical offset */
- int lofs;
- /** number of characters that fit into the width of the console (fixed width) */
- int console_width;
- int winx;
- int ymin, ymax;
- int *xy; // [2]
- int *sel; // [2]
- /* bottom of view == 0, top of file == combine chars, end of line is lower then start. */
- int *pos_pick;
- const int *mval; // [2]
- int draw;
+ int font_id;
+ int cwidth;
+ int lheight;
+ /** text vertical offset */
+ int lofs;
+ /** number of characters that fit into the width of the console (fixed width) */
+ int console_width;
+ int winx;
+ int ymin, ymax;
+ int *xy; // [2]
+ int *sel; // [2]
+ /* bottom of view == 0, top of file == combine chars, end of line is lower then start. */
+ int *pos_pick;
+ const int *mval; // [2]
+ int draw;
} ConsoleDrawContext;
BLI_INLINE void console_step_sel(ConsoleDrawContext *cdc, const int step)
{
- cdc->sel[0] += step;
- cdc->sel[1] += step;
+ cdc->sel[0] += step;
+ cdc->sel[1] += step;
}
-static void console_draw_sel(const char *str, const int sel[2], const int xy[2], const int str_len_draw,
- int cwidth, int lheight, const unsigned char bg_sel[4])
+static void console_draw_sel(const char *str,
+ const int sel[2],
+ const int xy[2],
+ const int str_len_draw,
+ int cwidth,
+ int lheight,
+ const unsigned char bg_sel[4])
{
- if (sel[0] <= str_len_draw && sel[1] >= 0) {
- const int sta = txt_utf8_offset_to_column(str, max_ii(sel[0], 0));
- const int end = txt_utf8_offset_to_column(str, min_ii(sel[1], str_len_draw));
+ if (sel[0] <= str_len_draw && sel[1] >= 0) {
+ const int sta = txt_utf8_offset_to_column(str, max_ii(sel[0], 0));
+ const int end = txt_utf8_offset_to_column(str, min_ii(sel[1], str_len_draw));
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ GPUVertFormat *format = immVertexFormat();
+ 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_sel);
- immRecti(pos, xy[0] + (cwidth * sta), xy[1] - 2 + lheight, xy[0] + (cwidth * end), xy[1] - 2);
+ immUniformColor4ubv(bg_sel);
+ immRecti(pos, xy[0] + (cwidth * sta), xy[1] - 2 + lheight, xy[0] + (cwidth * end), xy[1] - 2);
- immUnbindProgram();
+ immUnbindProgram();
- GPU_blend(false);
- }
+ GPU_blend(false);
+ }
}
/* warning: allocated memory for 'offsets' must be freed by caller */
static int console_wrap_offsets(const char *str, int len, int width, int *lines, int **offsets)
{
- int i, end; /* column */
- int j; /* mem */
+ int i, end; /* column */
+ int j; /* mem */
- *lines = 1;
+ *lines = 1;
- *offsets = MEM_callocN(sizeof(**offsets) * (len * BLI_UTF8_WIDTH_MAX / MAX2(1, width - (BLI_UTF8_WIDTH_MAX - 1)) + 1),
- "console_wrap_offsets");
- (*offsets)[0] = 0;
+ *offsets = MEM_callocN(
+ sizeof(**offsets) *
+ (len * BLI_UTF8_WIDTH_MAX / MAX2(1, width - (BLI_UTF8_WIDTH_MAX - 1)) + 1),
+ "console_wrap_offsets");
+ (*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);
+ 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)++;
+ if (i + columns > end) {
+ (*offsets)[*lines] = j;
+ (*lines)++;
- end = i + width;
- }
- i += columns;
- }
- return j; /* return actual length */
+ end = i + width;
+ }
+ i += columns;
+ }
+ return j; /* return actual length */
}
/* return 0 if the last line is off the screen
* should be able to use this for any string type */
-static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str_len,
- const unsigned char fg[3], const unsigned char bg[3], const unsigned char bg_sel[4])
+static int console_draw_string(ConsoleDrawContext *cdc,
+ const char *str,
+ int str_len,
+ const unsigned char fg[3],
+ const unsigned char bg[3],
+ const unsigned char bg_sel[4])
{
- int tot_lines; /* total number of lines for wrapping */
- int *offsets; /* offsets of line beginnings for wrapping */
- int y_next;
-
- str_len = console_wrap_offsets(str, str_len, cdc->console_width, &tot_lines, &offsets);
- y_next = cdc->xy[1] + cdc->lheight * tot_lines;
-
- /* just advance the height */
- if (cdc->draw == 0) {
- if (cdc->pos_pick && cdc->mval[1] != INT_MAX && cdc->xy[1] <= cdc->mval[1]) {
- if (y_next >= cdc->mval[1]) {
- int ofs = 0;
-
- /* wrap */
- if (tot_lines > 1) {
- int iofs = (int)((float)(y_next - cdc->mval[1]) / cdc->lheight);
- ofs += offsets[MIN2(iofs, tot_lines - 1)];
- }
-
- /* last part */
- ofs += txt_utf8_column_to_offset(str + ofs,
- (int)floor((float)cdc->mval[0] / cdc->cwidth));
-
- CLAMP(ofs, 0, str_len);
- *cdc->pos_pick += str_len - ofs;
- }
- else
- *cdc->pos_pick += str_len + 1;
- }
-
- cdc->xy[1] = y_next;
- MEM_freeN(offsets);
- return 1;
- }
- else if (y_next < cdc->ymin) {
- /* have not reached the drawable area so don't break */
- cdc->xy[1] = y_next;
-
- /* adjust selection even if not drawing */
- if (cdc->sel[0] != cdc->sel[1]) {
- console_step_sel(cdc, -(str_len + 1));
- }
-
- MEM_freeN(offsets);
- return 1;
- }
-
- if (tot_lines > 1) { /* wrap? */
- const int initial_offset = offsets[tot_lines - 1];
- size_t len = str_len - initial_offset;
- const char *s = str + initial_offset;
- int i;
-
- int sel_orig[2];
- copy_v2_v2_int(sel_orig, cdc->sel);
-
- /* invert and swap for wrapping */
- cdc->sel[0] = str_len - sel_orig[1];
- cdc->sel[1] = str_len - sel_orig[0];
-
- if (bg) {
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- immUniformColor3ubv(bg);
- immRecti(pos, 0, cdc->xy[1], cdc->winx, (cdc->xy[1] + (cdc->lheight * tot_lines)));
-
- immUnbindProgram();
- }
-
- /* last part needs no clipping */
- BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0);
- BLF_color3ubv(cdc->font_id, fg);
- BLF_draw_mono(cdc->font_id, s, len, cdc->cwidth);
-
- if (cdc->sel[0] != cdc->sel[1]) {
- console_step_sel(cdc, -initial_offset);
- /* BLF_color3ub(cdc->font_id, 255, 0, 0); // debug */
- console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel);
- }
-
- cdc->xy[1] += cdc->lheight;
-
- for (i = tot_lines - 1; i > 0; i--) {
- len = offsets[i] - offsets[i - 1];
- s = str + offsets[i - 1];
-
- BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0);
- BLF_draw_mono(cdc->font_id, s, len, cdc->cwidth);
-
- if (cdc->sel[0] != cdc->sel[1]) {
- console_step_sel(cdc, len);
- /* BLF_color3ub(cdc->font_id, 0, 255, 0); // debug */
- console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel);
- }
-
- cdc->xy[1] += cdc->lheight;
-
- /* check if were out of view bounds */
- if (cdc->xy[1] > cdc->ymax) {
- MEM_freeN(offsets);
- return 0;
- }
- }
-
- copy_v2_v2_int(cdc->sel, sel_orig);
- console_step_sel(cdc, -(str_len + 1));
- }
- else { /* simple, no wrap */
-
- if (bg) {
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- immUniformColor3ubv(bg);
- immRecti(pos, 0, cdc->xy[1], cdc->winx, cdc->xy[1] + cdc->lheight);
-
- immUnbindProgram();
- }
-
- BLF_color3ubv(cdc->font_id, fg);
- BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0);
- BLF_draw_mono(cdc->font_id, str, str_len, cdc->cwidth);
-
- if (cdc->sel[0] != cdc->sel[1]) {
- int isel[2];
-
- isel[0] = str_len - cdc->sel[1];
- isel[1] = str_len - cdc->sel[0];
-
- /* BLF_color3ub(cdc->font_id, 255, 255, 0); // debug */
- console_draw_sel(str, isel, cdc->xy, str_len, cdc->cwidth, cdc->lheight, bg_sel);
- console_step_sel(cdc, -(str_len + 1));
- }
+ int tot_lines; /* total number of lines for wrapping */
+ int *offsets; /* offsets of line beginnings for wrapping */
+ int y_next;
+
+ str_len = console_wrap_offsets(str, str_len, cdc->console_width, &tot_lines, &offsets);
+ y_next = cdc->xy[1] + cdc->lheight * tot_lines;
+
+ /* just advance the height */
+ if (cdc->draw == 0) {
+ if (cdc->pos_pick && cdc->mval[1] != INT_MAX && cdc->xy[1] <= cdc->mval[1]) {
+ if (y_next >= cdc->mval[1]) {
+ int ofs = 0;
+
+ /* wrap */
+ if (tot_lines > 1) {
+ int iofs = (int)((float)(y_next - cdc->mval[1]) / cdc->lheight);
+ ofs += offsets[MIN2(iofs, tot_lines - 1)];
+ }
+
+ /* last part */
+ ofs += txt_utf8_column_to_offset(str + ofs, (int)floor((float)cdc->mval[0] / cdc->cwidth));
+
+ CLAMP(ofs, 0, str_len);
+ *cdc->pos_pick += str_len - ofs;
+ }
+ else
+ *cdc->pos_pick += str_len + 1;
+ }
+
+ cdc->xy[1] = y_next;
+ MEM_freeN(offsets);
+ return 1;
+ }
+ else if (y_next < cdc->ymin) {
+ /* have not reached the drawable area so don't break */
+ cdc->xy[1] = y_next;
+
+ /* adjust selection even if not drawing */
+ if (cdc->sel[0] != cdc->sel[1]) {
+ console_step_sel(cdc, -(str_len + 1));
+ }
+
+ MEM_freeN(offsets);
+ return 1;
+ }
+
+ if (tot_lines > 1) { /* wrap? */
+ const int initial_offset = offsets[tot_lines - 1];
+ size_t len = str_len - initial_offset;
+ const char *s = str + initial_offset;
+ int i;
+
+ int sel_orig[2];
+ copy_v2_v2_int(sel_orig, cdc->sel);
+
+ /* invert and swap for wrapping */
+ cdc->sel[0] = str_len - sel_orig[1];
+ cdc->sel[1] = str_len - sel_orig[0];
+
+ if (bg) {
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3ubv(bg);
+ immRecti(pos, 0, cdc->xy[1], cdc->winx, (cdc->xy[1] + (cdc->lheight * tot_lines)));
+
+ immUnbindProgram();
+ }
+
+ /* last part needs no clipping */
+ BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0);
+ BLF_color3ubv(cdc->font_id, fg);
+ BLF_draw_mono(cdc->font_id, s, len, cdc->cwidth);
+
+ if (cdc->sel[0] != cdc->sel[1]) {
+ console_step_sel(cdc, -initial_offset);
+ /* BLF_color3ub(cdc->font_id, 255, 0, 0); // debug */
+ console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel);
+ }
+
+ cdc->xy[1] += cdc->lheight;
+
+ for (i = tot_lines - 1; i > 0; i--) {
+ len = offsets[i] - offsets[i - 1];
+ s = str + offsets[i - 1];
+
+ BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0);
+ BLF_draw_mono(cdc->font_id, s, len, cdc->cwidth);
+
+ if (cdc->sel[0] != cdc->sel[1]) {
+ console_step_sel(cdc, len);
+ /* BLF_color3ub(cdc->font_id, 0, 255, 0); // debug */
+ console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel);
+ }
+
+ cdc->xy[1] += cdc->lheight;
+
+ /* check if were out of view bounds */
+ if (cdc->xy[1] > cdc->ymax) {
+ MEM_freeN(offsets);
+ return 0;
+ }
+ }
+
+ copy_v2_v2_int(cdc->sel, sel_orig);
+ console_step_sel(cdc, -(str_len + 1));
+ }
+ else { /* simple, no wrap */
+
+ if (bg) {
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3ubv(bg);
+ immRecti(pos, 0, cdc->xy[1], cdc->winx, cdc->xy[1] + cdc->lheight);
+
+ immUnbindProgram();
+ }
+
+ BLF_color3ubv(cdc->font_id, fg);
+ BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0);
+ BLF_draw_mono(cdc->font_id, str, str_len, cdc->cwidth);
+
+ if (cdc->sel[0] != cdc->sel[1]) {
+ int isel[2];
+
+ isel[0] = str_len - cdc->sel[1];
+ isel[1] = str_len - cdc->sel[0];
+
+ /* BLF_color3ub(cdc->font_id, 255, 255, 0); // debug */
+ console_draw_sel(str, isel, cdc->xy, str_len, cdc->cwidth, cdc->lheight, bg_sel);
+ console_step_sel(cdc, -(str_len + 1));
+ }
- cdc->xy[1] += cdc->lheight;
-
- if (cdc->xy[1] > cdc->ymax) {
- MEM_freeN(offsets);
- return 0;
- }
- }
+ cdc->xy[1] += cdc->lheight;
+
+ if (cdc->xy[1] > cdc->ymax) {
+ MEM_freeN(offsets);
+ return 0;
+ }
+ }
- MEM_freeN(offsets);
- return 1;
+ MEM_freeN(offsets);
+ return 1;
}
#define CONSOLE_DRAW_MARGIN 4
-int textview_draw(TextViewContext *tvc, const int draw, int mval[2], void **mouse_pick, int *pos_pick)
+int textview_draw(
+ TextViewContext *tvc, const int draw, int mval[2], void **mouse_pick, int *pos_pick)
{
- ConsoleDrawContext cdc = {0};
-
- int x_orig = CONSOLE_DRAW_MARGIN, y_orig = CONSOLE_DRAW_MARGIN + tvc->lheight / 6;
- int xy[2], y_prev;
- int sel[2] = {-1, -1}; /* defaults disabled */
- unsigned char fg[3], bg[3];
- const int font_id = blf_mono_font;
-
- console_font_begin(font_id, tvc->lheight);
-
- xy[0] = x_orig; xy[1] = y_orig;
-
- if (mval[1] != INT_MAX) {
- mval[1] += (tvc->ymin + CONSOLE_DRAW_MARGIN);
- }
-
- if (pos_pick) {
- *pos_pick = 0;
- }
-
- /* constants for the sequencer context */
- cdc.font_id = font_id;
- cdc.cwidth = (int)BLF_fixed_width(font_id);
- assert(cdc.cwidth > 0);
- cdc.lheight = tvc->lheight;
- cdc.lofs = -BLF_descender(font_id);
- /* note, scroll bar must be already subtracted () */
- cdc.console_width = (tvc->winx - (CONSOLE_DRAW_MARGIN * 2)) / cdc.cwidth;
- /* avoid divide by zero on small windows */
- if (cdc.console_width < 1) {
- cdc.console_width = 1;
- }
- cdc.winx = tvc->winx - CONSOLE_DRAW_MARGIN;
- cdc.ymin = tvc->ymin;
- cdc.ymax = tvc->ymax;
- cdc.xy = xy;
- cdc.sel = sel;
- cdc.pos_pick = pos_pick;
- cdc.mval = mval;
- cdc.draw = draw;
-
- /* shouldnt be needed */
- tvc->cwidth = cdc.cwidth;
- tvc->console_width = cdc.console_width;
- 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};
-
- if (draw && tvc->const_colors) {
- tvc->const_colors(tvc, bg_sel);
- }
-
- do {
- const char *ext_line;
- int ext_len;
- int color_flag = 0;
-
- y_prev = xy[1];
-
- if (draw) {
- color_flag = tvc->line_color(tvc, fg, bg);
- }
-
- tvc->line_get(tvc, &ext_line, &ext_len);
-
- if (!console_draw_string(&cdc, ext_line, ext_len,
- (color_flag & TVC_LINE_FG) ? fg : NULL,
- (color_flag & TVC_LINE_BG) ? bg : NULL,
- bg_sel))
- {
- /* when drawing, if we pass v2d->cur.ymax, then quit */
- if (draw) {
- break; /* past the y limits */
- }
- }
-
- if ((mval[1] != INT_MAX) && (mval[1] >= y_prev && mval[1] <= xy[1])) {
- *mouse_pick = (void *)tvc->iter;
- break;
- }
-
- tvc->iter_index++;
-
- } while (tvc->step(tvc));
- }
-
- tvc->end(tvc);
-
- xy[1] += tvc->lheight * 2;
-
- return xy[1] - y_orig;
+ ConsoleDrawContext cdc = {0};
+
+ int x_orig = CONSOLE_DRAW_MARGIN, y_orig = CONSOLE_DRAW_MARGIN + tvc->lheight / 6;
+ int xy[2], y_prev;
+ int sel[2] = {-1, -1}; /* defaults disabled */
+ unsigned char fg[3], bg[3];
+ const int font_id = blf_mono_font;
+
+ console_font_begin(font_id, tvc->lheight);
+
+ xy[0] = x_orig;
+ xy[1] = y_orig;
+
+ if (mval[1] != INT_MAX) {
+ mval[1] += (tvc->ymin + CONSOLE_DRAW_MARGIN);
+ }
+
+ if (pos_pick) {
+ *pos_pick = 0;
+ }
+
+ /* constants for the sequencer context */
+ cdc.font_id = font_id;
+ cdc.cwidth = (int)BLF_fixed_width(font_id);
+ assert(cdc.cwidth > 0);
+ cdc.lheight = tvc->lheight;
+ cdc.lofs = -BLF_descender(font_id);
+ /* note, scroll bar must be already subtracted () */
+ cdc.console_width = (tvc->winx - (CONSOLE_DRAW_MARGIN * 2)) / cdc.cwidth;
+ /* avoid divide by zero on small windows */
+ if (cdc.console_width < 1) {
+ cdc.console_width = 1;
+ }
+ cdc.winx = tvc->winx - CONSOLE_DRAW_MARGIN;
+ cdc.ymin = tvc->ymin;
+ cdc.ymax = tvc->ymax;
+ cdc.xy = xy;
+ cdc.sel = sel;
+ cdc.pos_pick = pos_pick;
+ cdc.mval = mval;
+ cdc.draw = draw;
+
+ /* shouldnt be needed */
+ tvc->cwidth = cdc.cwidth;
+ tvc->console_width = cdc.console_width;
+ 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};
+
+ if (draw && tvc->const_colors) {
+ tvc->const_colors(tvc, bg_sel);
+ }
+
+ do {
+ const char *ext_line;
+ int ext_len;
+ int color_flag = 0;
+
+ y_prev = xy[1];
+
+ if (draw) {
+ color_flag = tvc->line_color(tvc, fg, bg);
+ }
+
+ tvc->line_get(tvc, &ext_line, &ext_len);
+
+ if (!console_draw_string(&cdc,
+ ext_line,
+ ext_len,
+ (color_flag & TVC_LINE_FG) ? fg : NULL,
+ (color_flag & TVC_LINE_BG) ? bg : NULL,
+ bg_sel)) {
+ /* when drawing, if we pass v2d->cur.ymax, then quit */
+ if (draw) {
+ break; /* past the y limits */
+ }
+ }
+
+ if ((mval[1] != INT_MAX) && (mval[1] >= y_prev && mval[1] <= xy[1])) {
+ *mouse_pick = (void *)tvc->iter;
+ break;
+ }
+
+ tvc->iter_index++;
+
+ } while (tvc->step(tvc));
+ }
+
+ tvc->end(tvc);
+
+ xy[1] += tvc->lheight * 2;
+
+ return xy[1] - y_orig;
}
diff --git a/source/blender/editors/space_info/textview.h b/source/blender/editors/space_info/textview.h
index 40478e30f37..aa0e924b461 100644
--- a/source/blender/editors/space_info/textview.h
+++ b/source/blender/editors/space_info/textview.h
@@ -22,39 +22,40 @@
#define __TEXTVIEW_H__
typedef struct TextViewContext {
- int lheight;
- int sel_start, sel_end;
-
- /* view settings */
- int cwidth; /* shouldnt be needed! */
- int console_width; /* shouldnt be needed! */
-
- int winx;
- int ymin, ymax;
-
- /* callbacks */
- int (*begin)(struct TextViewContext *tvc);
- void (*end)(struct TextViewContext *tvc);
- void *arg1;
- void *arg2;
-
- /* iterator */
- int (*step)(struct TextViewContext *tvc);
- int (*line_get)(struct TextViewContext *tvc, const char **, int *);
- int (*line_color)(struct TextViewContext *tvc, unsigned char fg[3], unsigned char bg[3]);
- /* constant theme colors */
- void (*const_colors)(struct TextViewContext *tvc, unsigned char bg_sel[4]);
- void *iter;
- int iter_index;
- int iter_char; /* char intex, used for multi-line report display */
- int iter_char_next; /* same as above, next \n */
- int iter_tmp; /* internal iterator use */
+ int lheight;
+ int sel_start, sel_end;
+
+ /* view settings */
+ int cwidth; /* shouldnt be needed! */
+ int console_width; /* shouldnt be needed! */
+
+ int winx;
+ int ymin, ymax;
+
+ /* callbacks */
+ int (*begin)(struct TextViewContext *tvc);
+ void (*end)(struct TextViewContext *tvc);
+ void *arg1;
+ void *arg2;
+
+ /* iterator */
+ int (*step)(struct TextViewContext *tvc);
+ int (*line_get)(struct TextViewContext *tvc, const char **, int *);
+ int (*line_color)(struct TextViewContext *tvc, unsigned char fg[3], unsigned char bg[3]);
+ /* constant theme colors */
+ void (*const_colors)(struct TextViewContext *tvc, unsigned char bg_sel[4]);
+ void *iter;
+ int iter_index;
+ int iter_char; /* char intex, used for multi-line report display */
+ int iter_char_next; /* same as above, next \n */
+ int iter_tmp; /* internal iterator use */
} TextViewContext;
-int textview_draw(struct TextViewContext *tvc, const int draw, int mval[2], void **mouse_pick, int *pos_pick);
+int textview_draw(
+ struct TextViewContext *tvc, const int draw, int mval[2], void **mouse_pick, int *pos_pick);
-#define TVC_LINE_FG (1<<0)
-#define TVC_LINE_BG (1<<1)
+#define TVC_LINE_FG (1 << 0)
+#define TVC_LINE_BG (1 << 1)
-#endif /* __TEXTVIEW_H__ */
+#endif /* __TEXTVIEW_H__ */
diff --git a/source/blender/editors/space_nla/CMakeLists.txt b/source/blender/editors/space_nla/CMakeLists.txt
index f22cc378a60..3048c64c49e 100644
--- a/source/blender/editors/space_nla/CMakeLists.txt
+++ b/source/blender/editors/space_nla/CMakeLists.txt
@@ -16,42 +16,42 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../depsgraph
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../depsgraph
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- nla_buttons.c
- nla_channels.c
- nla_draw.c
- nla_edit.c
- nla_ops.c
- nla_select.c
- space_nla.c
-
- nla_intern.h
+ nla_buttons.c
+ nla_channels.c
+ nla_draw.c
+ nla_edit.c
+ nla_ops.c
+ nla_select.c
+ space_nla.c
+
+ nla_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
+ bf_blenkernel
+ bf_blenlib
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index b06b7120faf..b19dc3680bf 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -21,7 +21,6 @@
* \ingroup spnla
*/
-
#include <string.h>
#include <stdio.h>
#include <math.h>
@@ -41,7 +40,6 @@
#include "BKE_context.h"
#include "BKE_screen.h"
-
#include "WM_api.h"
#include "WM_types.h"
@@ -53,8 +51,7 @@
#include "UI_interface.h"
#include "UI_resources.h"
-#include "nla_intern.h" // own include
-
+#include "nla_intern.h" // own include
/* ******************* nla editor space & buttons ************** */
@@ -62,177 +59,180 @@
static void do_nla_region_buttons(bContext *C, void *UNUSED(arg), int UNUSED(event))
{
- //Scene *scene = CTX_data_scene(C);
+ //Scene *scene = CTX_data_scene(C);
#if 0
- switch (event) {
- /* pass */
- }
+ switch (event) {
+ /* pass */
+ }
#endif
- /* default for now */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM, NULL);
+ /* default for now */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM, NULL);
}
-bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_ptr, PointerRNA *strip_ptr)
+bool nla_panel_context(const bContext *C,
+ PointerRNA *adt_ptr,
+ PointerRNA *nlt_ptr,
+ PointerRNA *strip_ptr)
{
- bAnimContext ac;
- bAnimListElem *ale = NULL;
- ListBase anim_data = {NULL, NULL};
- short found = 0; /* not bool, since we need to indicate "found but not ideal" status */
- int filter;
-
- /* for now, only draw if we could init the anim-context info (necessary for all animation-related tools)
- * to work correctly is able to be correctly retrieved. There's no point showing empty panels?
- */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return false;
-
- /* extract list of active channel(s), of which we should only take the first one
- * - we need the channels flag to get the active AnimData block when there are no NLA Tracks
- */
- // XXX: double-check active!
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_LIST_CHANNELS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- switch (ale->type) {
- case ANIMTYPE_NLATRACK: /* NLA Track - The primary data type which should get caught */
- {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- AnimData *adt = ale->adt;
-
- /* found it, now set the pointers */
- if (adt_ptr) {
- /* AnimData pointer */
- RNA_pointer_create(ale->id, &RNA_AnimData, adt, adt_ptr);
- }
- if (nlt_ptr) {
- /* NLA-Track pointer */
- RNA_pointer_create(ale->id, &RNA_NlaTrack, nlt, nlt_ptr);
- }
- if (strip_ptr) {
- /* NLA-Strip pointer */
- NlaStrip *strip = BKE_nlastrip_find_active(nlt);
- RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, strip_ptr);
- }
-
- found = 1;
- break;
- }
- case ANIMTYPE_SCENE: /* Top-Level Widgets doubling up as datablocks */
- case ANIMTYPE_OBJECT:
- case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
- case ANIMTYPE_DSLAM:
- case ANIMTYPE_DSCAM:
- case ANIMTYPE_DSCACHEFILE:
- case ANIMTYPE_DSCUR:
- case ANIMTYPE_DSSKEY:
- case ANIMTYPE_DSWOR:
- case ANIMTYPE_DSNTREE:
- case ANIMTYPE_DSPART:
- case ANIMTYPE_DSMBALL:
- case ANIMTYPE_DSARM:
- case ANIMTYPE_DSMESH:
- case ANIMTYPE_DSTEX:
- case ANIMTYPE_DSLAT:
- case ANIMTYPE_DSLINESTYLE:
- case ANIMTYPE_DSSPK:
- case ANIMTYPE_DSGPENCIL:
- case ANIMTYPE_PALETTE:
- {
- /* for these channels, we only do AnimData */
- if (ale->adt && adt_ptr) {
- ID *id;
-
- if ((ale->data == NULL) || (ale->type == ANIMTYPE_OBJECT)) {
- /* ale->data is not an ID block! */
- id = ale->id;
- }
- else {
- /* ale->data is always the proper ID block we need,
- * but ale->id may not be (i.e. for textures) */
- id = (ID *)ale->data;
- }
-
- /* AnimData pointer */
- if (adt_ptr) {
- RNA_pointer_create(id, &RNA_AnimData, ale->adt, adt_ptr);
- }
-
- /* set found status to -1, since setting to 1 would break the loop
- * and potentially skip an active NLA-Track in some cases...
- */
- found = -1;
- }
- break;
- }
- }
-
- if (found > 0)
- break;
- }
-
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
-
- return (found != 0);
+ bAnimContext ac;
+ bAnimListElem *ale = NULL;
+ ListBase anim_data = {NULL, NULL};
+ short found = 0; /* not bool, since we need to indicate "found but not ideal" status */
+ int filter;
+
+ /* for now, only draw if we could init the anim-context info (necessary for all animation-related tools)
+ * to work correctly is able to be correctly retrieved. There's no point showing empty panels?
+ */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return false;
+
+ /* extract list of active channel(s), of which we should only take the first one
+ * - we need the channels flag to get the active AnimData block when there are no NLA Tracks
+ */
+ // XXX: double-check active!
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ACTIVE |
+ ANIMFILTER_LIST_CHANNELS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ switch (ale->type) {
+ case ANIMTYPE_NLATRACK: /* NLA Track - The primary data type which should get caught */
+ {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ AnimData *adt = ale->adt;
+
+ /* found it, now set the pointers */
+ if (adt_ptr) {
+ /* AnimData pointer */
+ RNA_pointer_create(ale->id, &RNA_AnimData, adt, adt_ptr);
+ }
+ if (nlt_ptr) {
+ /* NLA-Track pointer */
+ RNA_pointer_create(ale->id, &RNA_NlaTrack, nlt, nlt_ptr);
+ }
+ if (strip_ptr) {
+ /* NLA-Strip pointer */
+ NlaStrip *strip = BKE_nlastrip_find_active(nlt);
+ RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, strip_ptr);
+ }
+
+ found = 1;
+ break;
+ }
+ case ANIMTYPE_SCENE: /* Top-Level Widgets doubling up as datablocks */
+ case ANIMTYPE_OBJECT:
+ case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
+ case ANIMTYPE_DSLAM:
+ case ANIMTYPE_DSCAM:
+ case ANIMTYPE_DSCACHEFILE:
+ case ANIMTYPE_DSCUR:
+ case ANIMTYPE_DSSKEY:
+ case ANIMTYPE_DSWOR:
+ case ANIMTYPE_DSNTREE:
+ case ANIMTYPE_DSPART:
+ case ANIMTYPE_DSMBALL:
+ case ANIMTYPE_DSARM:
+ case ANIMTYPE_DSMESH:
+ case ANIMTYPE_DSTEX:
+ case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
+ case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSGPENCIL:
+ case ANIMTYPE_PALETTE: {
+ /* for these channels, we only do AnimData */
+ if (ale->adt && adt_ptr) {
+ ID *id;
+
+ if ((ale->data == NULL) || (ale->type == ANIMTYPE_OBJECT)) {
+ /* ale->data is not an ID block! */
+ id = ale->id;
+ }
+ else {
+ /* ale->data is always the proper ID block we need,
+ * but ale->id may not be (i.e. for textures) */
+ id = (ID *)ale->data;
+ }
+
+ /* AnimData pointer */
+ if (adt_ptr) {
+ RNA_pointer_create(id, &RNA_AnimData, ale->adt, adt_ptr);
+ }
+
+ /* set found status to -1, since setting to 1 would break the loop
+ * and potentially skip an active NLA-Track in some cases...
+ */
+ found = -1;
+ }
+ break;
+ }
+ }
+
+ if (found > 0)
+ break;
+ }
+
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
+
+ return (found != 0);
}
#if 0
static bool nla_panel_poll(const bContext *C, PanelType *pt)
{
- return nla_panel_context(C, NULL, NULL);
+ return nla_panel_context(C, NULL, NULL);
}
#endif
static bool nla_animdata_panel_poll(const bContext *C, PanelType *UNUSED(pt))
{
- PointerRNA ptr;
- return (nla_panel_context(C, &ptr, NULL, NULL) && (ptr.data != NULL));
+ PointerRNA ptr;
+ return (nla_panel_context(C, &ptr, NULL, NULL) && (ptr.data != NULL));
}
static bool nla_track_panel_poll(const bContext *C, PanelType *UNUSED(pt))
{
- PointerRNA ptr;
- return (nla_panel_context(C, NULL, &ptr, NULL) && (ptr.data != NULL));
+ PointerRNA ptr;
+ return (nla_panel_context(C, NULL, &ptr, NULL) && (ptr.data != NULL));
}
static bool nla_strip_panel_poll(const bContext *C, PanelType *UNUSED(pt))
{
- PointerRNA ptr;
- return (nla_panel_context(C, NULL, NULL, &ptr) && (ptr.data != NULL));
+ PointerRNA ptr;
+ return (nla_panel_context(C, NULL, NULL, &ptr) && (ptr.data != NULL));
}
static bool nla_strip_actclip_panel_poll(const bContext *C, PanelType *UNUSED(pt))
{
- PointerRNA ptr;
- NlaStrip *strip;
+ PointerRNA ptr;
+ NlaStrip *strip;
- if (!nla_panel_context(C, NULL, NULL, &ptr))
- return 0;
- if (ptr.data == NULL)
- return 0;
+ if (!nla_panel_context(C, NULL, NULL, &ptr))
+ return 0;
+ if (ptr.data == NULL)
+ return 0;
- strip = ptr.data;
- return (strip->type == NLASTRIP_TYPE_CLIP);
+ strip = ptr.data;
+ return (strip->type == NLASTRIP_TYPE_CLIP);
}
static bool nla_strip_eval_panel_poll(const bContext *C, PanelType *UNUSED(pt))
{
- PointerRNA ptr;
- NlaStrip *strip;
+ PointerRNA ptr;
+ NlaStrip *strip;
- if (!nla_panel_context(C, NULL, NULL, &ptr))
- return 0;
- if (ptr.data == NULL)
- return 0;
+ if (!nla_panel_context(C, NULL, NULL, &ptr))
+ return 0;
+ if (ptr.data == NULL)
+ return 0;
- strip = ptr.data;
+ strip = ptr.data;
- if (strip->type == NLASTRIP_TYPE_SOUND)
- return 0;
+ if (strip->type == NLASTRIP_TYPE_SOUND)
+ return 0;
- return 1;
+ return 1;
}
/* -------------- */
@@ -240,342 +240,349 @@ 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)
{
- PointerRNA adt_ptr;
- /* AnimData *adt; */
- uiLayout *layout = pa->layout;
- uiLayout *row;
- uiBlock *block;
-
- /* check context and also validity of pointer */
- if (!nla_panel_context(C, &adt_ptr, NULL, NULL))
- return;
-
- /* adt = adt_ptr.data; */
-
- block = uiLayoutGetBlock(layout);
- UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
-
- /* AnimData Source Properties ----------------------------------- */
-
- /* icon + id-block name of block where AnimData came from to prevent
- * accidentally changing the properties of the wrong action
- */
- if (adt_ptr.id.data) {
- ID *id = adt_ptr.id.data;
- PointerRNA id_ptr;
-
- RNA_id_pointer_create(id, &id_ptr);
-
- /* ID-block name > AnimData */
- row = uiLayoutRow(layout, true);
- uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
-
- uiItemL(row, id->name + 2, RNA_struct_ui_icon(id_ptr.type)); /* id-block (src) */
- uiItemL(row, "", ICON_SMALL_TRI_RIGHT_VEC); /* expander */
- uiItemL(row, IFACE_("Animation Data"), ICON_ANIM_DATA); /* animdata */
-
- uiItemS(layout);
- }
-
- /* Active Action Properties ------------------------------------- */
- /* action */
- row = uiLayoutRow(layout, true);
- uiTemplateID(
- row, (bContext *)C, &adt_ptr, "action",
- "ACTION_OT_new", NULL, "NLA_OT_action_unlink", UI_TEMPLATE_ID_FILTER_ALL, false);
-
- /* extrapolation */
- row = uiLayoutRow(layout, true);
- uiItemR(row, &adt_ptr, "action_extrapolation", 0, NULL, ICON_NONE);
-
- /* blending */
- row = uiLayoutRow(layout, true);
- uiItemR(row, &adt_ptr, "action_blend_type", 0, NULL, ICON_NONE);
-
- /* influence */
- row = uiLayoutRow(layout, true);
- uiItemR(row, &adt_ptr, "action_influence", 0, NULL, ICON_NONE);
+ PointerRNA adt_ptr;
+ /* AnimData *adt; */
+ uiLayout *layout = pa->layout;
+ uiLayout *row;
+ uiBlock *block;
+
+ /* check context and also validity of pointer */
+ if (!nla_panel_context(C, &adt_ptr, NULL, NULL))
+ return;
+
+ /* adt = adt_ptr.data; */
+
+ block = uiLayoutGetBlock(layout);
+ UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
+
+ /* AnimData Source Properties ----------------------------------- */
+
+ /* icon + id-block name of block where AnimData came from to prevent
+ * accidentally changing the properties of the wrong action
+ */
+ if (adt_ptr.id.data) {
+ ID *id = adt_ptr.id.data;
+ PointerRNA id_ptr;
+
+ RNA_id_pointer_create(id, &id_ptr);
+
+ /* ID-block name > AnimData */
+ row = uiLayoutRow(layout, true);
+ uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
+
+ uiItemL(row, id->name + 2, RNA_struct_ui_icon(id_ptr.type)); /* id-block (src) */
+ uiItemL(row, "", ICON_SMALL_TRI_RIGHT_VEC); /* expander */
+ uiItemL(row, IFACE_("Animation Data"), ICON_ANIM_DATA); /* animdata */
+
+ uiItemS(layout);
+ }
+
+ /* Active Action Properties ------------------------------------- */
+ /* action */
+ row = uiLayoutRow(layout, true);
+ uiTemplateID(row,
+ (bContext *)C,
+ &adt_ptr,
+ "action",
+ "ACTION_OT_new",
+ NULL,
+ "NLA_OT_action_unlink",
+ UI_TEMPLATE_ID_FILTER_ALL,
+ false);
+
+ /* extrapolation */
+ row = uiLayoutRow(layout, true);
+ uiItemR(row, &adt_ptr, "action_extrapolation", 0, NULL, ICON_NONE);
+
+ /* blending */
+ row = uiLayoutRow(layout, true);
+ uiItemR(row, &adt_ptr, "action_blend_type", 0, NULL, ICON_NONE);
+
+ /* influence */
+ row = uiLayoutRow(layout, true);
+ uiItemR(row, &adt_ptr, "action_influence", 0, NULL, ICON_NONE);
}
/* active NLA-Track */
static void nla_panel_track(const bContext *C, Panel *pa)
{
- PointerRNA nlt_ptr;
- uiLayout *layout = pa->layout;
- uiLayout *row;
- uiBlock *block;
+ PointerRNA nlt_ptr;
+ uiLayout *layout = pa->layout;
+ uiLayout *row;
+ uiBlock *block;
- /* check context and also validity of pointer */
- if (!nla_panel_context(C, NULL, &nlt_ptr, NULL))
- return;
+ /* check context and also validity of pointer */
+ if (!nla_panel_context(C, NULL, &nlt_ptr, NULL))
+ return;
- block = uiLayoutGetBlock(layout);
- UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
+ block = uiLayoutGetBlock(layout);
+ UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
- /* Info - Active NLA-Context:Track ---------------------- */
- row = uiLayoutRow(layout, true);
- uiItemR(row, &nlt_ptr, "name", 0, NULL, ICON_NLA);
+ /* Info - Active NLA-Context:Track ---------------------- */
+ row = uiLayoutRow(layout, true);
+ uiItemR(row, &nlt_ptr, "name", 0, NULL, ICON_NLA);
}
/* generic settings for active NLA-Strip */
static void nla_panel_properties(const bContext *C, Panel *pa)
{
- PointerRNA strip_ptr;
- uiLayout *layout = pa->layout;
- uiLayout *column, *row, *sub;
- uiBlock *block;
- short showEvalProps = 1;
-
- if (!nla_panel_context(C, NULL, NULL, &strip_ptr))
- return;
-
- block = uiLayoutGetBlock(layout);
- UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
-
- /* Strip Properties ------------------------------------- */
- /* strip type */
- row = uiLayoutColumn(layout, true);
- uiItemR(row, &strip_ptr, "name", 0, NULL, ICON_NLA); // XXX icon?
- uiItemR(row, &strip_ptr, "type", 0, NULL, ICON_NONE);
-
- /* strip extents */
- column = uiLayoutColumn(layout, true);
- uiItemL(column, IFACE_("Strip Extents:"), ICON_NONE);
- uiItemR(column, &strip_ptr, "frame_start", 0, NULL, ICON_NONE);
- uiItemR(column, &strip_ptr, "frame_end", 0, NULL, ICON_NONE);
-
- /* Evaluation-Related Strip Properties ------------------ */
-
- /* sound properties strips don't have these settings */
- if (RNA_enum_get(&strip_ptr, "type") == NLASTRIP_TYPE_SOUND)
- showEvalProps = 0;
-
- /* only show if allowed to... */
- if (showEvalProps) {
- /* extrapolation */
- row = uiLayoutRow(layout, true);
- uiItemR(row, &strip_ptr, "extrapolation", 0, NULL, ICON_NONE);
-
- /* blending */
- row = uiLayoutRow(layout, true);
- uiItemR(row, &strip_ptr, "blend_type", 0, NULL, ICON_NONE);
-
- /* Blend in/out + auto-blending:
- * - blend in/out can only be set when autoblending is off
- */
- 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?
-
- sub = uiLayoutColumn(column, true);
- uiLayoutSetActive(sub, RNA_boolean_get(&strip_ptr, "use_auto_blend") == false);
- uiItemR(sub, &strip_ptr, "blend_in", 0, NULL, ICON_NONE);
- uiItemR(sub, &strip_ptr, "blend_out", 0, NULL, ICON_NONE);
-
- /* settings */
- column = uiLayoutColumn(layout, true);
- uiLayoutSetActive(column, !(RNA_boolean_get(&strip_ptr, "use_animated_influence") || RNA_boolean_get(&strip_ptr, "use_animated_time")));
- uiItemL(column, IFACE_("Playback Settings:"), ICON_NONE);
- uiItemR(column, &strip_ptr, "mute", 0, NULL, ICON_NONE);
- uiItemR(column, &strip_ptr, "use_reverse", 0, NULL, ICON_NONE);
- }
+ PointerRNA strip_ptr;
+ uiLayout *layout = pa->layout;
+ uiLayout *column, *row, *sub;
+ uiBlock *block;
+ short showEvalProps = 1;
+
+ if (!nla_panel_context(C, NULL, NULL, &strip_ptr))
+ return;
+
+ block = uiLayoutGetBlock(layout);
+ UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
+
+ /* Strip Properties ------------------------------------- */
+ /* strip type */
+ row = uiLayoutColumn(layout, true);
+ uiItemR(row, &strip_ptr, "name", 0, NULL, ICON_NLA); // XXX icon?
+ uiItemR(row, &strip_ptr, "type", 0, NULL, ICON_NONE);
+
+ /* strip extents */
+ column = uiLayoutColumn(layout, true);
+ uiItemL(column, IFACE_("Strip Extents:"), ICON_NONE);
+ uiItemR(column, &strip_ptr, "frame_start", 0, NULL, ICON_NONE);
+ uiItemR(column, &strip_ptr, "frame_end", 0, NULL, ICON_NONE);
+
+ /* Evaluation-Related Strip Properties ------------------ */
+
+ /* sound properties strips don't have these settings */
+ if (RNA_enum_get(&strip_ptr, "type") == NLASTRIP_TYPE_SOUND)
+ showEvalProps = 0;
+
+ /* only show if allowed to... */
+ if (showEvalProps) {
+ /* extrapolation */
+ row = uiLayoutRow(layout, true);
+ uiItemR(row, &strip_ptr, "extrapolation", 0, NULL, ICON_NONE);
+
+ /* blending */
+ row = uiLayoutRow(layout, true);
+ uiItemR(row, &strip_ptr, "blend_type", 0, NULL, ICON_NONE);
+
+ /* Blend in/out + auto-blending:
+ * - blend in/out can only be set when autoblending is off
+ */
+ 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?
+
+ sub = uiLayoutColumn(column, true);
+ uiLayoutSetActive(sub, RNA_boolean_get(&strip_ptr, "use_auto_blend") == false);
+ uiItemR(sub, &strip_ptr, "blend_in", 0, NULL, ICON_NONE);
+ uiItemR(sub, &strip_ptr, "blend_out", 0, NULL, ICON_NONE);
+
+ /* settings */
+ column = uiLayoutColumn(layout, true);
+ uiLayoutSetActive(column,
+ !(RNA_boolean_get(&strip_ptr, "use_animated_influence") ||
+ RNA_boolean_get(&strip_ptr, "use_animated_time")));
+ uiItemL(column, IFACE_("Playback Settings:"), ICON_NONE);
+ uiItemR(column, &strip_ptr, "mute", 0, NULL, ICON_NONE);
+ uiItemR(column, &strip_ptr, "use_reverse", 0, NULL, ICON_NONE);
+ }
}
-
/* action-clip only settings for active NLA-Strip */
static void nla_panel_actclip(const bContext *C, Panel *pa)
{
- PointerRNA strip_ptr;
- uiLayout *layout = pa->layout;
- uiLayout *column, *row;
- uiBlock *block;
-
- /* check context and also validity of pointer */
- if (!nla_panel_context(C, NULL, NULL, &strip_ptr))
- return;
-
- block = uiLayoutGetBlock(layout);
- UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
-
- /* Strip Properties ------------------------------------- */
- /* action pointer */
- row = uiLayoutRow(layout, true);
- 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);
- uiItemL(column, IFACE_("Action Extents:"), ICON_NONE);
- uiItemR(column, &strip_ptr, "action_frame_start", 0, IFACE_("Start Frame"), ICON_NONE);
- uiItemR(column, &strip_ptr, "action_frame_end", 0, IFACE_("End Frame"), 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);
- uiItemO(row, IFACE_("Now"), ICON_FILE_REFRESH, "NLA_OT_action_sync_length");
-
- /* action usage */
- column = uiLayoutColumn(layout, true);
- uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "use_animated_time") == false);
- uiItemL(column, IFACE_("Playback Settings:"), ICON_NONE);
- uiItemR(column, &strip_ptr, "scale", 0, NULL, ICON_NONE);
- uiItemR(column, &strip_ptr, "repeat", 0, NULL, ICON_NONE);
+ PointerRNA strip_ptr;
+ uiLayout *layout = pa->layout;
+ uiLayout *column, *row;
+ uiBlock *block;
+
+ /* check context and also validity of pointer */
+ if (!nla_panel_context(C, NULL, NULL, &strip_ptr))
+ return;
+
+ block = uiLayoutGetBlock(layout);
+ UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
+
+ /* Strip Properties ------------------------------------- */
+ /* action pointer */
+ row = uiLayoutRow(layout, true);
+ 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);
+ uiItemL(column, IFACE_("Action Extents:"), ICON_NONE);
+ uiItemR(column, &strip_ptr, "action_frame_start", 0, IFACE_("Start Frame"), ICON_NONE);
+ uiItemR(column, &strip_ptr, "action_frame_end", 0, IFACE_("End Frame"), 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);
+ uiItemO(row, IFACE_("Now"), ICON_FILE_REFRESH, "NLA_OT_action_sync_length");
+
+ /* action usage */
+ column = uiLayoutColumn(layout, true);
+ uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "use_animated_time") == false);
+ uiItemL(column, IFACE_("Playback Settings:"), ICON_NONE);
+ uiItemR(column, &strip_ptr, "scale", 0, NULL, ICON_NONE);
+ uiItemR(column, &strip_ptr, "repeat", 0, NULL, ICON_NONE);
}
/* evaluation settings for active NLA-Strip */
static void nla_panel_evaluation(const bContext *C, Panel *pa)
{
- PointerRNA strip_ptr;
- uiLayout *layout = pa->layout;
- uiLayout *col, *sub;
- uiBlock *block;
+ PointerRNA strip_ptr;
+ uiLayout *layout = pa->layout;
+ uiLayout *col, *sub;
+ uiBlock *block;
- /* check context and also validity of pointer */
- if (!nla_panel_context(C, NULL, NULL, &strip_ptr))
- return;
+ /* check context and also validity of pointer */
+ if (!nla_panel_context(C, NULL, NULL, &strip_ptr))
+ return;
- block = uiLayoutGetBlock(layout);
- UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
+ block = uiLayoutGetBlock(layout);
+ UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
- col = uiLayoutColumn(layout, true);
- uiItemR(col, &strip_ptr, "use_animated_influence", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(layout, true);
+ uiItemR(col, &strip_ptr, "use_animated_influence", 0, NULL, ICON_NONE);
- sub = uiLayoutColumn(col, true);
- uiLayoutSetEnabled(sub, RNA_boolean_get(&strip_ptr, "use_animated_influence"));
- uiItemR(sub, &strip_ptr, "influence", 0, NULL, ICON_NONE);
+ sub = uiLayoutColumn(col, true);
+ uiLayoutSetEnabled(sub, RNA_boolean_get(&strip_ptr, "use_animated_influence"));
+ uiItemR(sub, &strip_ptr, "influence", 0, NULL, ICON_NONE);
- col = uiLayoutColumn(layout, true);
- sub = uiLayoutRow(col, false);
- uiItemR(sub, &strip_ptr, "use_animated_time", 0, NULL, ICON_NONE);
- uiItemR(sub, &strip_ptr, "use_animated_time_cyclic", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(layout, true);
+ sub = uiLayoutRow(col, false);
+ uiItemR(sub, &strip_ptr, "use_animated_time", 0, NULL, ICON_NONE);
+ uiItemR(sub, &strip_ptr, "use_animated_time_cyclic", 0, NULL, ICON_NONE);
- sub = uiLayoutRow(col, false);
- uiLayoutSetEnabled(sub, RNA_boolean_get(&strip_ptr, "use_animated_time"));
- uiItemR(sub, &strip_ptr, "strip_time", 0, NULL, ICON_NONE);
+ sub = uiLayoutRow(col, false);
+ uiLayoutSetEnabled(sub, RNA_boolean_get(&strip_ptr, "use_animated_time"));
+ uiItemR(sub, &strip_ptr, "strip_time", 0, NULL, ICON_NONE);
}
/* F-Modifiers for active NLA-Strip */
static void nla_panel_modifiers(const bContext *C, Panel *pa)
{
- PointerRNA strip_ptr;
- NlaStrip *strip;
- FModifier *fcm;
- uiLayout *col, *row;
- uiBlock *block;
-
- /* check context and also validity of pointer */
- if (!nla_panel_context(C, NULL, NULL, &strip_ptr))
- return;
- strip = strip_ptr.data;
-
- block = uiLayoutGetBlock(pa->layout);
- UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
-
- /* 'add modifier' button at top of panel */
- {
- row = uiLayoutRow(pa->layout, false);
- block = uiLayoutGetBlock(row);
-
- // FIXME: we need to set the only-active property so that this will only add modifiers for the active strip (not all selected)
- uiItemMenuEnumO(row, (bContext *)C, "NLA_OT_fmodifier_add", "type", IFACE_("Add Modifier"), ICON_NONE);
-
- /* copy/paste (as sub-row) */
- row = uiLayoutRow(row, true);
- uiItemO(row, "", ICON_COPYDOWN, "NLA_OT_fmodifier_copy");
- uiItemO(row, "", ICON_PASTEDOWN, "NLA_OT_fmodifier_paste");
- }
-
- /* draw each modifier */
- for (fcm = strip->modifiers.first; fcm; fcm = fcm->next) {
- col = uiLayoutColumn(pa->layout, true);
-
- ANIM_uiTemplate_fmodifier_draw(col, strip_ptr.id.data, &strip->modifiers, fcm);
- }
+ PointerRNA strip_ptr;
+ NlaStrip *strip;
+ FModifier *fcm;
+ uiLayout *col, *row;
+ uiBlock *block;
+
+ /* check context and also validity of pointer */
+ if (!nla_panel_context(C, NULL, NULL, &strip_ptr))
+ return;
+ strip = strip_ptr.data;
+
+ block = uiLayoutGetBlock(pa->layout);
+ UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
+
+ /* 'add modifier' button at top of panel */
+ {
+ row = uiLayoutRow(pa->layout, false);
+ block = uiLayoutGetBlock(row);
+
+ // FIXME: we need to set the only-active property so that this will only add modifiers for the active strip (not all selected)
+ uiItemMenuEnumO(
+ row, (bContext *)C, "NLA_OT_fmodifier_add", "type", IFACE_("Add Modifier"), ICON_NONE);
+
+ /* copy/paste (as sub-row) */
+ row = uiLayoutRow(row, true);
+ uiItemO(row, "", ICON_COPYDOWN, "NLA_OT_fmodifier_copy");
+ uiItemO(row, "", ICON_PASTEDOWN, "NLA_OT_fmodifier_paste");
+ }
+
+ /* draw each modifier */
+ for (fcm = strip->modifiers.first; fcm; fcm = fcm->next) {
+ col = uiLayoutColumn(pa->layout, true);
+
+ ANIM_uiTemplate_fmodifier_draw(col, strip_ptr.id.data, &strip->modifiers, fcm);
+ }
}
/* ******************* general ******************************** */
-
void nla_buttons_register(ARegionType *art)
{
- PanelType *pt;
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel animdata");
- strcpy(pt->idname, "NLA_PT_animdata");
- strcpy(pt->label, N_("Animation Data"));
- strcpy(pt->category, "Animations");
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = nla_panel_animdata;
- pt->poll = nla_animdata_panel_poll;
- pt->flag = PNL_DEFAULT_CLOSED;
- BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel track");
- strcpy(pt->idname, "NLA_PT_track");
- strcpy(pt->label, N_("Active Track"));
- strcpy(pt->category, "Animations");
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = nla_panel_track;
- pt->poll = nla_track_panel_poll;
- BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
- strcpy(pt->idname, "NLA_PT_properties");
- strcpy(pt->label, N_("Active Strip"));
- strcpy(pt->category, "Animations");
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = nla_panel_properties;
- pt->poll = nla_strip_panel_poll;
- BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
- strcpy(pt->idname, "NLA_PT_actionclip");
- strcpy(pt->label, N_("Action Clip"));
- strcpy(pt->category, "Animations");
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = nla_panel_actclip;
- pt->poll = nla_strip_actclip_panel_poll;
- BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel evaluation");
- strcpy(pt->idname, "NLA_PT_evaluation");
- strcpy(pt->label, N_("Evaluation"));
- strcpy(pt->category, "Animations");
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = nla_panel_evaluation;
- pt->poll = nla_strip_eval_panel_poll;
- BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers");
- strcpy(pt->idname, "NLA_PT_modifiers");
- strcpy(pt->label, N_("Modifiers"));
- strcpy(pt->category, "Modifiers");
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = nla_panel_modifiers;
- pt->poll = nla_strip_eval_panel_poll;
- BLI_addtail(&art->paneltypes, pt);
+ PanelType *pt;
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel animdata");
+ strcpy(pt->idname, "NLA_PT_animdata");
+ strcpy(pt->label, N_("Animation Data"));
+ strcpy(pt->category, "Animations");
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = nla_panel_animdata;
+ pt->poll = nla_animdata_panel_poll;
+ pt->flag = PNL_DEFAULT_CLOSED;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel track");
+ strcpy(pt->idname, "NLA_PT_track");
+ strcpy(pt->label, N_("Active Track"));
+ strcpy(pt->category, "Animations");
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = nla_panel_track;
+ pt->poll = nla_track_panel_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
+ strcpy(pt->idname, "NLA_PT_properties");
+ strcpy(pt->label, N_("Active Strip"));
+ strcpy(pt->category, "Animations");
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = nla_panel_properties;
+ pt->poll = nla_strip_panel_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
+ strcpy(pt->idname, "NLA_PT_actionclip");
+ strcpy(pt->label, N_("Action Clip"));
+ strcpy(pt->category, "Animations");
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = nla_panel_actclip;
+ pt->poll = nla_strip_actclip_panel_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel evaluation");
+ strcpy(pt->idname, "NLA_PT_evaluation");
+ strcpy(pt->label, N_("Evaluation"));
+ strcpy(pt->category, "Animations");
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = nla_panel_evaluation;
+ pt->poll = nla_strip_eval_panel_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers");
+ strcpy(pt->idname, "NLA_PT_modifiers");
+ strcpy(pt->label, N_("Modifiers"));
+ strcpy(pt->category, "Modifiers");
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = nla_panel_modifiers;
+ pt->poll = nla_strip_eval_panel_poll;
+ BLI_addtail(&art->paneltypes, pt);
}
static int nla_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = nla_has_buttons_region(sa);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = nla_has_buttons_region(sa);
- if (ar)
- ED_region_toggle_hidden(C, ar);
+ if (ar)
+ ED_region_toggle_hidden(C, ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NLA_OT_properties(wmOperatorType *ot)
{
- ot->name = "Toggle Sidebar";
- ot->idname = "NLA_OT_properties";
- ot->description = "Toggle the properties region visibility";
+ ot->name = "Toggle Sidebar";
+ ot->idname = "NLA_OT_properties";
+ ot->description = "Toggle the properties region visibility";
- ot->exec = nla_properties_toggle_exec;
- ot->poll = ED_operator_nla_active;
+ ot->exec = nla_properties_toggle_exec;
+ ot->poll = ED_operator_nla_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index ae3888f6ae0..90e70b835f8 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -21,7 +21,6 @@
* \ingroup spnla
*/
-
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
@@ -58,7 +57,7 @@
#include "UI_view2d.h"
-#include "nla_intern.h" // own include
+#include "nla_intern.h" // own include
/* *********************************************** */
/* Operators for NLA channels-list which need to be different
@@ -72,271 +71,273 @@
* --> Most channels are now selection only...
*/
-static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channel_index, short selectmode)
+static int mouse_nla_channels(
+ bContext *C, bAnimContext *ac, float x, int channel_index, short selectmode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- View2D *v2d = &ac->ar->v2d;
- int notifierFlags = 0;
-
- /* get the channel that was clicked on */
- /* filter channels */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* get channel from index */
- ale = BLI_findlink(&anim_data, channel_index);
- if (ale == NULL) {
- /* channel not found */
- if (G.debug & G_DEBUG)
- printf("Error: animation channel (index = %d) not found in mouse_anim_channels()\n", channel_index);
-
- ANIM_animdata_freelist(&anim_data);
- return 0;
- }
-
- /* action to take depends on what channel we've got */
- // WARNING: must keep this in sync with the equivalent function in anim_channels_edit.c
- switch (ale->type) {
- case ANIMTYPE_SCENE:
- {
- Scene *sce = (Scene *)ale->data;
- AnimData *adt = sce->adt;
-
- /* set selection status */
- if (selectmode == SELECT_INVERT) {
- /* swap select */
- sce->flag ^= SCE_DS_SELECTED;
- if (adt) adt->flag ^= ADT_UI_SELECTED;
- }
- else {
- sce->flag |= SCE_DS_SELECTED;
- if (adt) adt->flag |= ADT_UI_SELECTED;
- }
-
- notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
- break;
- }
- case ANIMTYPE_OBJECT:
- {
- ViewLayer *view_layer = ac->view_layer;
- Base *base = (Base *)ale->data;
- Object *ob = base->object;
- AnimData *adt = ob->adt;
-
- if (nlaedit_is_tweakmode_on(ac) == 0 && (base->flag & BASE_SELECTABLE)) {
- /* set selection status */
- if (selectmode == SELECT_INVERT) {
- /* swap select */
- ED_object_base_select(base, BA_INVERT);
- BKE_scene_object_base_flag_sync_from_base(base);
-
- if (adt) adt->flag ^= ADT_UI_SELECTED;
- }
- 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) {
- ED_object_base_select(b, BA_DESELECT);
- BKE_scene_object_base_flag_sync_from_base(b);
- if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE);
- }
-
- /* select object now */
- ED_object_base_select(base, BA_SELECT);
- BKE_scene_object_base_flag_sync_from_base(base);
- if (adt) adt->flag |= ADT_UI_SELECTED;
- }
-
- /* change active object - regardless of whether it is now selected [T37883] */
- ED_object_base_activate(C, base); /* adds notifier */
-
- if ((adt) && (adt->flag & ADT_UI_SELECTED))
- adt->flag |= ADT_UI_ACTIVE;
-
- /* notifiers - channel was selected */
- notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
- }
- break;
- }
- case ANIMTYPE_FILLACTD: /* Action Expander */
- case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
- case ANIMTYPE_DSLAM:
- case ANIMTYPE_DSCAM:
- case ANIMTYPE_DSCACHEFILE:
- case ANIMTYPE_DSCUR:
- case ANIMTYPE_DSSKEY:
- case ANIMTYPE_DSWOR:
- case ANIMTYPE_DSNTREE:
- case ANIMTYPE_DSPART:
- case ANIMTYPE_DSMBALL:
- case ANIMTYPE_DSARM:
- case ANIMTYPE_DSMESH:
- case ANIMTYPE_DSTEX:
- case ANIMTYPE_DSLAT:
- case ANIMTYPE_DSLINESTYLE:
- case ANIMTYPE_DSSPK:
- case ANIMTYPE_DSGPENCIL:
- case ANIMTYPE_PALETTE:
- {
- /* sanity checking... */
- if (ale->adt) {
- /* select/deselect */
- if (selectmode == SELECT_INVERT) {
- /* inverse selection status of this AnimData block only */
- ale->adt->flag ^= ADT_UI_SELECTED;
- }
- else {
- /* select AnimData block by itself */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
- ale->adt->flag |= ADT_UI_SELECTED;
- }
-
- /* set active? */
- if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED))
- ale->adt->flag |= ADT_UI_ACTIVE;
- }
-
- notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
- break;
- }
- case ANIMTYPE_NLATRACK:
- {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- AnimData *adt = ale->adt;
- short offset;
-
- /* offset for start of channel (on LHS of channel-list) */
- if (ale->id) {
- /* special exception for materials and particles */
- if (ELEM(GS(ale->id->name), ID_MA, ID_PA))
- offset = 21 + NLACHANNEL_BUTTON_WIDTH;
- else
- offset = 14;
- }
- else
- offset = 0;
-
- if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) {
- /* toggle protection (only if there's a toggle there) */
- nlt->flag ^= NLATRACK_PROTECTED;
-
- /* notifier flags - channel was edited */
- notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
- }
- else if (x >= (v2d->cur.xmax - 2 * NLACHANNEL_BUTTON_WIDTH)) {
- /* toggle mute */
- nlt->flag ^= NLATRACK_MUTED;
-
- /* notifier flags - channel was edited */
- notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
- ale->update |= ANIM_UPDATE_DEPS;
- }
- else if (x <= ((NLACHANNEL_BUTTON_WIDTH * 2) + offset)) {
- /* toggle 'solo' */
- BKE_nlatrack_solo_toggle(adt, nlt);
-
- /* notifier flags - channel was edited */
- notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
- ale->update |= ANIM_UPDATE_DEPS;
- }
- else if (nlaedit_is_tweakmode_on(ac) == 0) {
- /* set selection */
- if (selectmode == SELECT_INVERT) {
- /* inverse selection status of this F-Curve only */
- nlt->flag ^= NLATRACK_SELECTED;
- }
- else {
- /* select F-Curve by itself */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
- nlt->flag |= NLATRACK_SELECTED;
- }
-
- /* if NLA-Track is selected now,
- * make NLA-Track the 'active' one in the visible list */
- if (nlt->flag & NLATRACK_SELECTED)
- ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK);
-
- /* notifier flags - channel was selected */
- notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
- }
- break;
- }
- case ANIMTYPE_NLAACTION:
- {
- AnimData *adt = BKE_animdata_from_id(ale->id);
-
- /* button region... */
- if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) {
- if (nlaedit_is_tweakmode_on(ac) == 0) {
- /* 'push-down' action - only usable when not in TweakMode */
- /* TODO: make this use the operator instead of calling the function directly
- * however, calling the operator requires that we supply the args,
- * and that works with proper buttons only */
- BKE_nla_action_pushdown(adt);
- }
- else {
- /* when in tweakmode, this button becomes the toggle for mapped editing */
- adt->flag ^= ADT_NLA_EDIT_NOMAP;
- }
-
- /* changes to NLA-Action occurred */
- notifierFlags |= ND_NLA_ACTCHANGE;
- ale->update |= ANIM_UPDATE_DEPS;
- }
- /* OR rest of name... */
- else {
- /* NOTE: rest of NLA-Action name doubles for operating on the AnimData block
- * - this is useful when there's no clear divider, and makes more sense in
- * the case of users trying to use this to change actions
- * - in tweakmode, clicking here gets us out of tweakmode, as changing selection
- * while in tweakmode is really evil!
- * - we disable "solo" flags too, to make it easier to work with stashed actions
- * with less trouble
- */
- if (nlaedit_is_tweakmode_on(ac)) {
- /* exit tweakmode immediately */
- nlaedit_disable_tweakmode(ac, true);
-
- /* changes to NLA-Action occurred */
- notifierFlags |= ND_NLA_ACTCHANGE;
- ale->update |= ANIM_UPDATE_DEPS;
- }
- else {
- /* select/deselect */
- if (selectmode == SELECT_INVERT) {
- /* inverse selection status of this AnimData block only */
- adt->flag ^= ADT_UI_SELECTED;
- }
- else {
- /* select AnimData block by itself */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
- adt->flag |= ADT_UI_SELECTED;
- }
-
- /* set active? */
- if (adt->flag & ADT_UI_SELECTED)
- adt->flag |= ADT_UI_ACTIVE;
-
- notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
- }
- }
- break;
- }
- default:
- if (G.debug & G_DEBUG)
- printf("Error: Invalid channel type in mouse_nla_channels()\n");
- break;
- }
-
- /* free channels */
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
-
- /* return the notifier-flags set */
- return notifierFlags;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ View2D *v2d = &ac->ar->v2d;
+ int notifierFlags = 0;
+
+ /* get the channel that was clicked on */
+ /* filter channels */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* get channel from index */
+ ale = BLI_findlink(&anim_data, channel_index);
+ if (ale == NULL) {
+ /* channel not found */
+ if (G.debug & G_DEBUG)
+ printf("Error: animation channel (index = %d) not found in mouse_anim_channels()\n",
+ channel_index);
+
+ ANIM_animdata_freelist(&anim_data);
+ return 0;
+ }
+
+ /* action to take depends on what channel we've got */
+ // WARNING: must keep this in sync with the equivalent function in anim_channels_edit.c
+ switch (ale->type) {
+ case ANIMTYPE_SCENE: {
+ Scene *sce = (Scene *)ale->data;
+ AnimData *adt = sce->adt;
+
+ /* set selection status */
+ if (selectmode == SELECT_INVERT) {
+ /* swap select */
+ sce->flag ^= SCE_DS_SELECTED;
+ if (adt)
+ adt->flag ^= ADT_UI_SELECTED;
+ }
+ else {
+ sce->flag |= SCE_DS_SELECTED;
+ if (adt)
+ adt->flag |= ADT_UI_SELECTED;
+ }
+
+ notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
+ break;
+ }
+ case ANIMTYPE_OBJECT: {
+ ViewLayer *view_layer = ac->view_layer;
+ Base *base = (Base *)ale->data;
+ Object *ob = base->object;
+ AnimData *adt = ob->adt;
+
+ if (nlaedit_is_tweakmode_on(ac) == 0 && (base->flag & BASE_SELECTABLE)) {
+ /* set selection status */
+ if (selectmode == SELECT_INVERT) {
+ /* swap select */
+ ED_object_base_select(base, BA_INVERT);
+ BKE_scene_object_base_flag_sync_from_base(base);
+
+ if (adt)
+ adt->flag ^= ADT_UI_SELECTED;
+ }
+ 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) {
+ ED_object_base_select(b, BA_DESELECT);
+ BKE_scene_object_base_flag_sync_from_base(b);
+ if (b->object->adt)
+ b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE);
+ }
+
+ /* select object now */
+ ED_object_base_select(base, BA_SELECT);
+ BKE_scene_object_base_flag_sync_from_base(base);
+ if (adt)
+ adt->flag |= ADT_UI_SELECTED;
+ }
+
+ /* change active object - regardless of whether it is now selected [T37883] */
+ ED_object_base_activate(C, base); /* adds notifier */
+
+ if ((adt) && (adt->flag & ADT_UI_SELECTED))
+ adt->flag |= ADT_UI_ACTIVE;
+
+ /* notifiers - channel was selected */
+ notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
+ }
+ break;
+ }
+ case ANIMTYPE_FILLACTD: /* Action Expander */
+ case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
+ case ANIMTYPE_DSLAM:
+ case ANIMTYPE_DSCAM:
+ case ANIMTYPE_DSCACHEFILE:
+ case ANIMTYPE_DSCUR:
+ case ANIMTYPE_DSSKEY:
+ case ANIMTYPE_DSWOR:
+ case ANIMTYPE_DSNTREE:
+ case ANIMTYPE_DSPART:
+ case ANIMTYPE_DSMBALL:
+ case ANIMTYPE_DSARM:
+ case ANIMTYPE_DSMESH:
+ case ANIMTYPE_DSTEX:
+ case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
+ case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSGPENCIL:
+ case ANIMTYPE_PALETTE: {
+ /* sanity checking... */
+ if (ale->adt) {
+ /* select/deselect */
+ if (selectmode == SELECT_INVERT) {
+ /* inverse selection status of this AnimData block only */
+ ale->adt->flag ^= ADT_UI_SELECTED;
+ }
+ else {
+ /* select AnimData block by itself */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ ale->adt->flag |= ADT_UI_SELECTED;
+ }
+
+ /* set active? */
+ if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED))
+ ale->adt->flag |= ADT_UI_ACTIVE;
+ }
+
+ notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
+ break;
+ }
+ case ANIMTYPE_NLATRACK: {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ AnimData *adt = ale->adt;
+ short offset;
+
+ /* offset for start of channel (on LHS of channel-list) */
+ if (ale->id) {
+ /* special exception for materials and particles */
+ if (ELEM(GS(ale->id->name), ID_MA, ID_PA))
+ offset = 21 + NLACHANNEL_BUTTON_WIDTH;
+ else
+ offset = 14;
+ }
+ else
+ offset = 0;
+
+ if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) {
+ /* toggle protection (only if there's a toggle there) */
+ nlt->flag ^= NLATRACK_PROTECTED;
+
+ /* notifier flags - channel was edited */
+ notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
+ }
+ else if (x >= (v2d->cur.xmax - 2 * NLACHANNEL_BUTTON_WIDTH)) {
+ /* toggle mute */
+ nlt->flag ^= NLATRACK_MUTED;
+
+ /* notifier flags - channel was edited */
+ notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else if (x <= ((NLACHANNEL_BUTTON_WIDTH * 2) + offset)) {
+ /* toggle 'solo' */
+ BKE_nlatrack_solo_toggle(adt, nlt);
+
+ /* notifier flags - channel was edited */
+ notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else if (nlaedit_is_tweakmode_on(ac) == 0) {
+ /* set selection */
+ if (selectmode == SELECT_INVERT) {
+ /* inverse selection status of this F-Curve only */
+ nlt->flag ^= NLATRACK_SELECTED;
+ }
+ else {
+ /* select F-Curve by itself */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ nlt->flag |= NLATRACK_SELECTED;
+ }
+
+ /* if NLA-Track is selected now,
+ * make NLA-Track the 'active' one in the visible list */
+ if (nlt->flag & NLATRACK_SELECTED)
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK);
+
+ /* notifier flags - channel was selected */
+ notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
+ }
+ break;
+ }
+ case ANIMTYPE_NLAACTION: {
+ AnimData *adt = BKE_animdata_from_id(ale->id);
+
+ /* button region... */
+ if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) {
+ if (nlaedit_is_tweakmode_on(ac) == 0) {
+ /* 'push-down' action - only usable when not in TweakMode */
+ /* TODO: make this use the operator instead of calling the function directly
+ * however, calling the operator requires that we supply the args,
+ * and that works with proper buttons only */
+ BKE_nla_action_pushdown(adt);
+ }
+ else {
+ /* when in tweakmode, this button becomes the toggle for mapped editing */
+ adt->flag ^= ADT_NLA_EDIT_NOMAP;
+ }
+
+ /* changes to NLA-Action occurred */
+ notifierFlags |= ND_NLA_ACTCHANGE;
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ /* OR rest of name... */
+ else {
+ /* NOTE: rest of NLA-Action name doubles for operating on the AnimData block
+ * - this is useful when there's no clear divider, and makes more sense in
+ * the case of users trying to use this to change actions
+ * - in tweakmode, clicking here gets us out of tweakmode, as changing selection
+ * while in tweakmode is really evil!
+ * - we disable "solo" flags too, to make it easier to work with stashed actions
+ * with less trouble
+ */
+ if (nlaedit_is_tweakmode_on(ac)) {
+ /* exit tweakmode immediately */
+ nlaedit_disable_tweakmode(ac, true);
+
+ /* changes to NLA-Action occurred */
+ notifierFlags |= ND_NLA_ACTCHANGE;
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else {
+ /* select/deselect */
+ if (selectmode == SELECT_INVERT) {
+ /* inverse selection status of this AnimData block only */
+ adt->flag ^= ADT_UI_SELECTED;
+ }
+ else {
+ /* select AnimData block by itself */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ adt->flag |= ADT_UI_SELECTED;
+ }
+
+ /* set active? */
+ if (adt->flag & ADT_UI_SELECTED)
+ adt->flag |= ADT_UI_ACTIVE;
+
+ notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
+ }
+ }
+ break;
+ }
+ default:
+ if (G.debug & G_DEBUG)
+ printf("Error: Invalid channel type in mouse_nla_channels()\n");
+ break;
+ }
+
+ /* free channels */
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+
+ /* return the notifier-flags set */
+ return notifierFlags;
}
/* ------------------- */
@@ -344,66 +345,74 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
/* handle clicking */
static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bAnimContext ac;
- SpaceNla *snla;
- ARegion *ar;
- View2D *v2d;
- int channel_index;
- int notifierFlags = 0;
- short selectmode;
- float x, y;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get useful pointers from animation context data */
- snla = (SpaceNla *)ac.sl;
- ar = ac.ar;
- v2d = &ar->v2d;
-
- /* select mode is either replace (deselect all, then add) or add/extend */
- if (RNA_boolean_get(op->ptr, "extend"))
- selectmode = SELECT_INVERT;
- else
- selectmode = SELECT_REPLACE;
-
- /* figure out which channel user clicked in
- * Note: although channels technically start at y= NLACHANNEL_FIRST, we need to adjust by half a channel's height
- * so that the tops of channels get caught ok. Since NLACHANNEL_FIRST is really NLACHANNEL_HEIGHT, we simply use
- * NLACHANNEL_HEIGHT_HALF.
- */
- UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y);
- UI_view2d_listview_view_to_cell(v2d, NLACHANNEL_NAMEWIDTH, NLACHANNEL_STEP(snla), 0, (float)NLACHANNEL_HEIGHT_HALF(snla), x, y, NULL, &channel_index);
-
- /* handle mouse-click in the relevant channel then */
- notifierFlags = mouse_nla_channels(C, &ac, x, channel_index, selectmode);
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | notifierFlags, NULL);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ SpaceNla *snla;
+ ARegion *ar;
+ View2D *v2d;
+ int channel_index;
+ int notifierFlags = 0;
+ short selectmode;
+ float x, y;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get useful pointers from animation context data */
+ snla = (SpaceNla *)ac.sl;
+ ar = ac.ar;
+ v2d = &ar->v2d;
+
+ /* select mode is either replace (deselect all, then add) or add/extend */
+ if (RNA_boolean_get(op->ptr, "extend"))
+ selectmode = SELECT_INVERT;
+ else
+ selectmode = SELECT_REPLACE;
+
+ /* figure out which channel user clicked in
+ * Note: although channels technically start at y= NLACHANNEL_FIRST, we need to adjust by half a channel's height
+ * so that the tops of channels get caught ok. Since NLACHANNEL_FIRST is really NLACHANNEL_HEIGHT, we simply use
+ * NLACHANNEL_HEIGHT_HALF.
+ */
+ UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y);
+ UI_view2d_listview_view_to_cell(v2d,
+ NLACHANNEL_NAMEWIDTH,
+ NLACHANNEL_STEP(snla),
+ 0,
+ (float)NLACHANNEL_HEIGHT_HALF(snla),
+ x,
+ y,
+ NULL,
+ &channel_index);
+
+ /* handle mouse-click in the relevant channel then */
+ notifierFlags = mouse_nla_channels(C, &ac, x, channel_index, selectmode);
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | notifierFlags, NULL);
+
+ return OPERATOR_FINISHED;
}
void NLA_OT_channels_click(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Mouse Click on NLA Channels";
- ot->idname = "NLA_OT_channels_click";
- ot->description = "Handle clicks to select NLA channels";
+ /* identifiers */
+ ot->name = "Mouse Click on NLA Channels";
+ ot->idname = "NLA_OT_channels_click";
+ ot->description = "Handle clicks to select NLA channels";
- /* api callbacks */
- ot->invoke = nlachannels_mouseclick_invoke;
- ot->poll = ED_operator_nla_active;
+ /* api callbacks */
+ ot->invoke = nlachannels_mouseclick_invoke;
+ ot->poll = ED_operator_nla_active;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- /* props */
- prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* props */
+ prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* *********************************************** */
@@ -413,169 +422,185 @@ void NLA_OT_channels_click(wmOperatorType *ot)
static int nlachannels_pushdown_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- ID *id = NULL;
- AnimData *adt = NULL;
- int channel_index = RNA_int_get(op->ptr, "channel_index");
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get anim-channel to use (or more specifically, the animdata block behind it) */
- if (channel_index == -1) {
- PointerRNA adt_ptr = {{NULL}};
-
- /* active animdata block */
- if (nla_panel_context(C, &adt_ptr, NULL, NULL) == 0 || (adt_ptr.data == NULL)) {
- BKE_report(op->reports, RPT_ERROR, "No active AnimData block to use "
- "(select a data-block expander first or set the appropriate flags on an AnimData block)");
- return OPERATOR_CANCELLED;
- }
- else {
- id = adt_ptr.id.data;
- adt = adt_ptr.data;
- }
- }
- else {
- /* indexed channel */
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* filter channels */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* get channel from index */
- ale = BLI_findlink(&anim_data, channel_index);
- if (ale == NULL) {
- BKE_reportf(op->reports, RPT_ERROR, "No animation channel found at index %d", channel_index);
- ANIM_animdata_freelist(&anim_data);
- return OPERATOR_CANCELLED;
- }
- else if (ale->type != ANIMTYPE_NLAACTION) {
- BKE_reportf(op->reports, RPT_ERROR, "Animation channel at index %d is not a NLA 'Active Action' channel", channel_index);
- ANIM_animdata_freelist(&anim_data);
- return OPERATOR_CANCELLED;
- }
-
- /* grab AnimData from the channel */
- adt = ale->adt;
- id = ale->id;
-
- /* we don't need anything here anymore, so free it all */
- ANIM_animdata_freelist(&anim_data);
- }
-
- /* double-check that we are free to push down here... */
- if (adt == NULL) {
- BKE_report(op->reports, RPT_WARNING, "Internal Error - AnimData block is not valid");
- return OPERATOR_CANCELLED;
- }
- else if (nlaedit_is_tweakmode_on(&ac)) {
- BKE_report(op->reports, RPT_WARNING,
- "Cannot push down actions while tweaking a strip's action, exit tweak mode first");
- return OPERATOR_CANCELLED;
- }
- else if (adt->action == NULL) {
- BKE_report(op->reports, RPT_WARNING, "No active action to push down");
- return OPERATOR_CANCELLED;
- }
- else {
- /* 'push-down' action - only usable when not in TweakMode */
- BKE_nla_action_pushdown(adt);
-
- DEG_id_tag_update_ex(CTX_data_main(C), id, ID_RECALC_ANIMATION | ID_RECALC_COPY_ON_WRITE);
- }
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ ID *id = NULL;
+ AnimData *adt = NULL;
+ int channel_index = RNA_int_get(op->ptr, "channel_index");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get anim-channel to use (or more specifically, the animdata block behind it) */
+ if (channel_index == -1) {
+ PointerRNA adt_ptr = {{NULL}};
+
+ /* active animdata block */
+ if (nla_panel_context(C, &adt_ptr, NULL, NULL) == 0 || (adt_ptr.data == NULL)) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "No active AnimData block to use "
+ "(select a data-block expander first or set the appropriate flags on an AnimData "
+ "block)");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ id = adt_ptr.id.data;
+ adt = adt_ptr.data;
+ }
+ }
+ else {
+ /* indexed channel */
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter channels */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* get channel from index */
+ ale = BLI_findlink(&anim_data, channel_index);
+ if (ale == NULL) {
+ BKE_reportf(op->reports, RPT_ERROR, "No animation channel found at index %d", channel_index);
+ ANIM_animdata_freelist(&anim_data);
+ return OPERATOR_CANCELLED;
+ }
+ else if (ale->type != ANIMTYPE_NLAACTION) {
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "Animation channel at index %d is not a NLA 'Active Action' channel",
+ channel_index);
+ ANIM_animdata_freelist(&anim_data);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* grab AnimData from the channel */
+ adt = ale->adt;
+ id = ale->id;
+
+ /* we don't need anything here anymore, so free it all */
+ ANIM_animdata_freelist(&anim_data);
+ }
+
+ /* double-check that we are free to push down here... */
+ if (adt == NULL) {
+ BKE_report(op->reports, RPT_WARNING, "Internal Error - AnimData block is not valid");
+ return OPERATOR_CANCELLED;
+ }
+ else if (nlaedit_is_tweakmode_on(&ac)) {
+ BKE_report(op->reports,
+ RPT_WARNING,
+ "Cannot push down actions while tweaking a strip's action, exit tweak mode first");
+ return OPERATOR_CANCELLED;
+ }
+ else if (adt->action == NULL) {
+ BKE_report(op->reports, RPT_WARNING, "No active action to push down");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* 'push-down' action - only usable when not in TweakMode */
+ BKE_nla_action_pushdown(adt);
+
+ DEG_id_tag_update_ex(CTX_data_main(C), id, ID_RECALC_ANIMATION | ID_RECALC_COPY_ON_WRITE);
+ }
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
+ return OPERATOR_FINISHED;
}
void NLA_OT_action_pushdown(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Push Down Action";
- ot->idname = "NLA_OT_action_pushdown";
- ot->description = "Push action down onto the top of the NLA stack as a new strip";
-
- /* callbacks */
- ot->exec = nlachannels_pushdown_exec;
- ot->poll = nlaop_poll_tweakmode_off;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_int(ot->srna, "channel_index", -1, -1, INT_MAX, "Channel Index",
- "Index of NLA action channel to perform pushdown operation on",
- 0, INT_MAX);
- RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+ /* identifiers */
+ ot->name = "Push Down Action";
+ ot->idname = "NLA_OT_action_pushdown";
+ ot->description = "Push action down onto the top of the NLA stack as a new strip";
+
+ /* callbacks */
+ ot->exec = nlachannels_pushdown_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_int(ot->srna,
+ "channel_index",
+ -1,
+ -1,
+ INT_MAX,
+ "Channel Index",
+ "Index of NLA action channel to perform pushdown operation on",
+ 0,
+ INT_MAX);
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
}
/* ******************** Action Unlink ******************************** */
static bool nla_action_unlink_poll(bContext *C)
{
- if (ED_operator_nla_active(C)) {
- return nla_panel_context(C, NULL, NULL, NULL);
- }
+ if (ED_operator_nla_active(C)) {
+ return nla_panel_context(C, NULL, NULL, NULL);
+ }
- /* something failed... */
- return false;
+ /* something failed... */
+ return false;
}
static int nla_action_unlink_exec(bContext *C, wmOperator *op)
{
- PointerRNA adt_ptr;
- AnimData *adt;
+ PointerRNA adt_ptr;
+ AnimData *adt;
- /* check context and also validity of pointer */
- if (!nla_panel_context(C, &adt_ptr, NULL, NULL))
- return OPERATOR_CANCELLED;
+ /* check context and also validity of pointer */
+ if (!nla_panel_context(C, &adt_ptr, NULL, NULL))
+ return OPERATOR_CANCELLED;
- /* get animdata */
- adt = adt_ptr.data;
- if (adt == NULL)
- return OPERATOR_CANCELLED;
+ /* get animdata */
+ adt = adt_ptr.data;
+ if (adt == NULL)
+ return OPERATOR_CANCELLED;
- /* do unlinking */
- if (adt && adt->action) {
- bool force_delete = RNA_boolean_get(op->ptr, "force_delete");
- ED_animedit_unlink_action(C, adt_ptr.id.data, adt, adt->action, op->reports, force_delete);
- }
+ /* do unlinking */
+ if (adt && adt->action) {
+ bool force_delete = RNA_boolean_get(op->ptr, "force_delete");
+ ED_animedit_unlink_action(C, adt_ptr.id.data, adt, adt->action, op->reports, force_delete);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int nla_action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
{
- /* NOTE: this is hardcoded to match the behavior for the unlink button
- * (in interface_templates.c) */
- RNA_boolean_set(op->ptr, "force_delete", evt->shift != 0);
- return nla_action_unlink_exec(C, op);
+ /* NOTE: this is hardcoded to match the behavior for the unlink button
+ * (in interface_templates.c) */
+ RNA_boolean_set(op->ptr, "force_delete", evt->shift != 0);
+ return nla_action_unlink_exec(C, op);
}
void NLA_OT_action_unlink(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Unlink Action";
- ot->idname = "NLA_OT_action_unlink";
- ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)";
-
- /* callbacks */
- ot->invoke = nla_action_unlink_invoke;
- ot->exec = nla_action_unlink_exec;
- ot->poll = nla_action_unlink_poll;
-
- /* properties */
- prop = RNA_def_boolean(ot->srna, "force_delete", false, "Force Delete",
- "Clear Fake User and remove copy stashed in this datablock's NLA stack");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Unlink Action";
+ ot->idname = "NLA_OT_action_unlink";
+ ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)";
+
+ /* callbacks */
+ ot->invoke = nla_action_unlink_invoke;
+ ot->exec = nla_action_unlink_exec;
+ ot->poll = nla_action_unlink_poll;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna,
+ "force_delete",
+ false,
+ "Force Delete",
+ "Clear Fake User and remove copy stashed in this datablock's NLA stack");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ******************** Add Tracks Operator ***************************** */
@@ -584,136 +609,142 @@ void NLA_OT_action_unlink(wmOperatorType *ot)
/* helper - add NLA Tracks alongside existing ones */
bool nlaedit_add_tracks_existing(bAnimContext *ac, bool above_sel)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- AnimData *lastAdt = NULL;
- bool added = false;
-
- /* get a list of the (selected) NLA Tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* add tracks... */
- for (ale = anim_data.first; ale; ale = ale->next) {
- if (ale->type == ANIMTYPE_NLATRACK) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- AnimData *adt = ale->adt;
-
- /* check if just adding a new track above this one,
- * or whether we're adding a new one to the top of the stack that this one belongs to
- */
- if (above_sel) {
- /* just add a new one above this one */
- BKE_nlatrack_add(adt, nlt);
- ale->update = ANIM_UPDATE_DEPS;
- added = true;
- }
- else if ((lastAdt == NULL) || (adt != lastAdt)) {
- /* add one track to the top of the owning AnimData's stack,
- * then don't add anymore to this stack */
- BKE_nlatrack_add(adt, NULL);
- lastAdt = adt;
- ale->update = ANIM_UPDATE_DEPS;
- added = true;
- }
- }
- }
-
- /* free temp data */
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
-
- return added;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ AnimData *lastAdt = NULL;
+ bool added = false;
+
+ /* get a list of the (selected) NLA Tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* add tracks... */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (ale->type == ANIMTYPE_NLATRACK) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ AnimData *adt = ale->adt;
+
+ /* check if just adding a new track above this one,
+ * or whether we're adding a new one to the top of the stack that this one belongs to
+ */
+ if (above_sel) {
+ /* just add a new one above this one */
+ BKE_nlatrack_add(adt, nlt);
+ ale->update = ANIM_UPDATE_DEPS;
+ added = true;
+ }
+ else if ((lastAdt == NULL) || (adt != lastAdt)) {
+ /* add one track to the top of the owning AnimData's stack,
+ * then don't add anymore to this stack */
+ BKE_nlatrack_add(adt, NULL);
+ lastAdt = adt;
+ ale->update = ANIM_UPDATE_DEPS;
+ added = true;
+ }
+ }
+ }
+
+ /* free temp data */
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+
+ return added;
}
/* helper - add NLA Tracks to empty (and selected) AnimData blocks */
bool nlaedit_add_tracks_empty(bAnimContext *ac)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- bool added = false;
-
- /* get a list of the selected AnimData blocks in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* check if selected AnimData blocks are empty, and add tracks if so... */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ale->adt;
-
- /* sanity check */
- BLI_assert(adt->flag & ADT_UI_SELECTED);
-
- /* ensure it is empty */
- if (BLI_listbase_is_empty(&adt->nla_tracks)) {
- /* add new track to this AnimData block then */
- BKE_nlatrack_add(adt, NULL);
- ale->update = ANIM_UPDATE_DEPS;
- added = true;
- }
- }
-
- /* cleanup */
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
-
- return added;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ bool added = false;
+
+ /* get a list of the selected AnimData blocks in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA |
+ ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* check if selected AnimData blocks are empty, and add tracks if so... */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ale->adt;
+
+ /* sanity check */
+ BLI_assert(adt->flag & ADT_UI_SELECTED);
+
+ /* ensure it is empty */
+ if (BLI_listbase_is_empty(&adt->nla_tracks)) {
+ /* add new track to this AnimData block then */
+ BKE_nlatrack_add(adt, NULL);
+ ale->update = ANIM_UPDATE_DEPS;
+ added = true;
+ }
+ }
+
+ /* cleanup */
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+
+ return added;
}
/* ----- */
static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- bool above_sel = RNA_boolean_get(op->ptr, "above_selected");
- bool op_done = false;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* perform adding in two passes - existing first so that we don't double up for empty */
- op_done |= nlaedit_add_tracks_existing(&ac, above_sel);
- op_done |= nlaedit_add_tracks_empty(&ac);
-
- /* done? */
- if (op_done) {
- DEG_relations_tag_update(CTX_data_main(C));
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
- }
- else {
- /* failed to add any tracks */
- BKE_report(op->reports, RPT_WARNING,
- "Select an existing NLA Track or an empty action line first");
-
- /* not done */
- return OPERATOR_CANCELLED;
- }
+ bAnimContext ac;
+ bool above_sel = RNA_boolean_get(op->ptr, "above_selected");
+ bool op_done = false;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* perform adding in two passes - existing first so that we don't double up for empty */
+ op_done |= nlaedit_add_tracks_existing(&ac, above_sel);
+ op_done |= nlaedit_add_tracks_empty(&ac);
+
+ /* done? */
+ if (op_done) {
+ DEG_relations_tag_update(CTX_data_main(C));
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+ }
+ else {
+ /* failed to add any tracks */
+ BKE_report(
+ op->reports, RPT_WARNING, "Select an existing NLA Track or an empty action line first");
+
+ /* not done */
+ return OPERATOR_CANCELLED;
+ }
}
void NLA_OT_tracks_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Tracks";
- ot->idname = "NLA_OT_tracks_add";
- ot->description = "Add NLA-Tracks above/after the selected tracks";
-
- /* api callbacks */
- ot->exec = nlaedit_add_tracks_exec;
- ot->poll = nlaop_poll_tweakmode_off;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "above_selected", 0, "Above Selected", "Add a new NLA Track above every existing selected one");
+ /* identifiers */
+ ot->name = "Add Tracks";
+ ot->idname = "NLA_OT_tracks_add";
+ ot->description = "Add NLA-Tracks above/after the selected tracks";
+
+ /* api callbacks */
+ ot->exec = nlaedit_add_tracks_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "above_selected",
+ 0,
+ "Above Selected",
+ "Add a new NLA Track above every existing selected one");
}
/* ******************** Delete Tracks Operator ***************************** */
@@ -721,64 +752,65 @@ void NLA_OT_tracks_add(wmOperatorType *ot)
static int nlaedit_delete_tracks_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get a list of the AnimData blocks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* delete tracks */
- for (ale = anim_data.first; ale; ale = ale->next) {
- if (ale->type == ANIMTYPE_NLATRACK) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- AnimData *adt = ale->adt;
-
- /* if track is currently 'solo', then AnimData should have its
- * 'has solo' flag disabled
- */
- if (nlt->flag & NLATRACK_SOLO)
- adt->flag &= ~ADT_NLA_SOLO_TRACK;
-
- /* call delete on this track - deletes all strips too */
- BKE_nlatrack_free(&adt->nla_tracks, nlt, true);
- ale->update = ANIM_UPDATE_DEPS;
- }
- }
-
- /* free temp data */
- ANIM_animdata_update(&ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
-
- DEG_relations_tag_update(ac.bmain);
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the AnimData blocks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* delete tracks */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (ale->type == ANIMTYPE_NLATRACK) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ AnimData *adt = ale->adt;
+
+ /* if track is currently 'solo', then AnimData should have its
+ * 'has solo' flag disabled
+ */
+ if (nlt->flag & NLATRACK_SOLO)
+ adt->flag &= ~ADT_NLA_SOLO_TRACK;
+
+ /* call delete on this track - deletes all strips too */
+ BKE_nlatrack_free(&adt->nla_tracks, nlt, true);
+ ale->update = ANIM_UPDATE_DEPS;
+ }
+ }
+
+ /* free temp data */
+ ANIM_animdata_update(&ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+
+ DEG_relations_tag_update(ac.bmain);
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_tracks_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Tracks";
- ot->idname = "NLA_OT_tracks_delete";
- ot->description = "Delete selected NLA-Tracks and the strips they contain";
+ /* identifiers */
+ ot->name = "Delete Tracks";
+ ot->idname = "NLA_OT_tracks_delete";
+ ot->description = "Delete selected NLA-Tracks and the strips they contain";
- /* api callbacks */
- ot->exec = nlaedit_delete_tracks_exec;
- ot->poll = nlaop_poll_tweakmode_off;
+ /* api callbacks */
+ ot->exec = nlaedit_delete_tracks_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* *********************************************** */
@@ -794,47 +826,46 @@ void NLA_OT_tracks_delete(wmOperatorType *ot)
static int nlaedit_objects_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
- SpaceNla *snla;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* ensure that filters are set so that the effect will be immediately visible */
- snla = (SpaceNla *)ac.sl;
- if (snla && snla->ads) {
- snla->ads->filterflag &= ~ADS_FILTER_NLA_NOACT;
- }
-
- /* operate on selected objects... */
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- /* ensure that object has AnimData... that's all */
- BKE_animdata_add_id(&ob->id);
- }
- CTX_DATA_END;
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ SpaceNla *snla;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* ensure that filters are set so that the effect will be immediately visible */
+ snla = (SpaceNla *)ac.sl;
+ if (snla && snla->ads) {
+ snla->ads->filterflag &= ~ADS_FILTER_NLA_NOACT;
+ }
+
+ /* operate on selected objects... */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ /* ensure that object has AnimData... that's all */
+ BKE_animdata_add_id(&ob->id);
+ }
+ CTX_DATA_END;
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_selected_objects_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Include Selected Objects";
- ot->idname = "NLA_OT_selected_objects_add";
- ot->description = "Make selected objects appear in NLA Editor by adding Animation Data";
+ /* identifiers */
+ ot->name = "Include Selected Objects";
+ ot->idname = "NLA_OT_selected_objects_add";
+ ot->description = "Make selected objects appear in NLA Editor by adding Animation Data";
- /* api callbacks */
- ot->exec = nlaedit_objects_add_exec;
- ot->poll = nlaop_poll_tweakmode_off;
+ /* api callbacks */
+ ot->exec = nlaedit_objects_add_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* *********************************************** */
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index 48eb2bdb82b..65115819874 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -21,7 +21,6 @@
* \ingroup spnla
*/
-
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
@@ -46,7 +45,6 @@
#include "ED_anim_api.h"
#include "ED_keyframes_draw.h"
-
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_draw.h"
@@ -61,7 +59,6 @@
#include "nla_private.h"
#include "nla_intern.h" /* own include */
-
/* *********************************************** */
/* Strips */
@@ -72,163 +69,179 @@
*/
void nla_action_get_color(AnimData *adt, bAction *act, float color[4])
{
- if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
- /* greenish color (same as tweaking strip) */
- UI_GetThemeColor4fv(TH_NLA_TWEAK, color);
- }
- else {
- if (act) {
- /* reddish color - same as dopesheet summary */
- UI_GetThemeColor4fv(TH_ANIM_ACTIVE, color);
- }
- else {
- /* grayish-red color */
- UI_GetThemeColor4fv(TH_ANIM_INACTIVE, color);
- }
- }
-
- /* when an NLA track is tagged "solo", action doesn't contribute,
- * so shouldn't be as prominent */
- if (adt && (adt->flag & ADT_NLA_SOLO_TRACK))
- color[3] *= 0.15f;
+ if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
+ /* greenish color (same as tweaking strip) */
+ UI_GetThemeColor4fv(TH_NLA_TWEAK, color);
+ }
+ else {
+ if (act) {
+ /* reddish color - same as dopesheet summary */
+ UI_GetThemeColor4fv(TH_ANIM_ACTIVE, color);
+ }
+ else {
+ /* grayish-red color */
+ UI_GetThemeColor4fv(TH_ANIM_INACTIVE, color);
+ }
+ }
+
+ /* when an NLA track is tagged "solo", action doesn't contribute,
+ * so shouldn't be as prominent */
+ if (adt && (adt->flag & ADT_NLA_SOLO_TRACK))
+ color[3] *= 0.15f;
}
/* draw the keyframes in the specified Action */
-static void nla_action_draw_keyframes(View2D *v2d, AnimData *adt, bAction *act, float y, float ymin, float ymax)
+static void nla_action_draw_keyframes(
+ View2D *v2d, AnimData *adt, bAction *act, float y, float ymin, float ymax)
{
- /* get a list of the keyframes with NLA-scaling applied */
- DLRBT_Tree keys;
- BLI_dlrbTree_init(&keys);
- action_to_keylist(adt, act, &keys, 0);
-
- if (ELEM(NULL, act, keys.first))
- return;
-
- /* draw a darkened region behind the strips
- * - get and reset the background color, this time without the alpha to stand out better
- * (amplified alpha is used instead)
- */
- float color[4];
- nla_action_get_color(adt, act, color);
- color[3] *= 2.5f;
-
- GPUVertFormat *format = immVertexFormat();
- uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- immUniformColor4fv(color);
-
- /* - draw a rect from the first to the last frame (no extra overlaps for now)
- * that is slightly stumpier than the track background (hardcoded 2-units here)
- */
- float f1 = ((ActKeyColumn *)keys.first)->cfra;
- float f2 = ((ActKeyColumn *)keys.last)->cfra;
-
- immRectf(pos_id, f1, ymin + 2, f2, ymax - 2);
- immUnbindProgram();
-
- /* count keys before drawing */
- /* Note: It's safe to cast DLRBT_Tree, as it's designed to degrade down to a ListBase */
- uint key_len = BLI_listbase_count((ListBase *)&keys);
-
- if (key_len > 0) {
- format = immVertexFormat();
- pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- uint outline_color_id = GPU_vertformat_attr_add(format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
- immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
- GPU_enable_program_point_size();
- immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
- immBegin(GPU_PRIM_POINTS, key_len);
-
- /* - 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) {
- draw_keyframe_shape(ak->cfra, y, 6.0f, false, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f,
- pos_id, size_id, color_id, outline_color_id,
- flags_id, KEYFRAME_HANDLE_NONE, KEYFRAME_EXTREME_NONE);
- }
-
- immEnd();
- GPU_disable_program_point_size();
- immUnbindProgram();
- }
-
- /* free icons */
- BLI_dlrbTree_free(&keys);
+ /* get a list of the keyframes with NLA-scaling applied */
+ DLRBT_Tree keys;
+ BLI_dlrbTree_init(&keys);
+ action_to_keylist(adt, act, &keys, 0);
+
+ if (ELEM(NULL, act, keys.first))
+ return;
+
+ /* draw a darkened region behind the strips
+ * - get and reset the background color, this time without the alpha to stand out better
+ * (amplified alpha is used instead)
+ */
+ float color[4];
+ nla_action_get_color(adt, act, color);
+ color[3] *= 2.5f;
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4fv(color);
+
+ /* - draw a rect from the first to the last frame (no extra overlaps for now)
+ * that is slightly stumpier than the track background (hardcoded 2-units here)
+ */
+ float f1 = ((ActKeyColumn *)keys.first)->cfra;
+ float f2 = ((ActKeyColumn *)keys.last)->cfra;
+
+ immRectf(pos_id, f1, ymin + 2, f2, ymax - 2);
+ immUnbindProgram();
+
+ /* count keys before drawing */
+ /* Note: It's safe to cast DLRBT_Tree, as it's designed to degrade down to a ListBase */
+ uint key_len = BLI_listbase_count((ListBase *)&keys);
+
+ if (key_len > 0) {
+ format = immVertexFormat();
+ pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uint color_id = GPU_vertformat_attr_add(
+ format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ uint outline_color_id = GPU_vertformat_attr_add(
+ format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ GPU_enable_program_point_size();
+ immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
+ immBegin(GPU_PRIM_POINTS, key_len);
+
+ /* - 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) {
+ draw_keyframe_shape(ak->cfra,
+ y,
+ 6.0f,
+ false,
+ ak->key_type,
+ KEYFRAME_SHAPE_FRAME,
+ 1.0f,
+ pos_id,
+ size_id,
+ color_id,
+ outline_color_id,
+ flags_id,
+ KEYFRAME_HANDLE_NONE,
+ KEYFRAME_EXTREME_NONE);
+ }
+
+ immEnd();
+ GPU_disable_program_point_size();
+ immUnbindProgram();
+ }
+
+ /* free icons */
+ BLI_dlrbTree_free(&keys);
}
/* Strip Markers ------------------------ */
/* Markers inside an action strip */
-static void nla_actionclip_draw_markers(NlaStrip *strip, float yminc, float ymaxc, int shade, const bool dashed)
+static void nla_actionclip_draw_markers(
+ NlaStrip *strip, float yminc, float ymaxc, int shade, const bool dashed)
{
- const bAction *act = strip->act;
-
- if (ELEM(NULL, act, act->markers.first))
- return;
-
- const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- if (dashed) {
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
-
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
-
- immUniform1i("colors_len", 0); /* "simple" mode */
- immUniform1f("dash_width", 6.0f);
- immUniform1f("dash_factor", 0.5f);
- }
- else {
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- }
- 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) {
- if ((marker->frame > strip->actstart) && (marker->frame < strip->actend)) {
- float frame = nlastrip_get_frame(strip, marker->frame, NLATIME_CONVERT_MAP);
-
- /* just a simple line for now */
- /* XXX: draw a triangle instead... */
- immVertex2f(shdr_pos, frame, yminc + 1);
- immVertex2f(shdr_pos, frame, ymaxc - 1);
- }
- }
- immEnd();
-
- immUnbindProgram();
+ const bAction *act = strip->act;
+
+ if (ELEM(NULL, act, act->markers.first))
+ return;
+
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ if (dashed) {
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ }
+ 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) {
+ if ((marker->frame > strip->actstart) && (marker->frame < strip->actend)) {
+ float frame = nlastrip_get_frame(strip, marker->frame, NLATIME_CONVERT_MAP);
+
+ /* just a simple line for now */
+ /* XXX: draw a triangle instead... */
+ immVertex2f(shdr_pos, frame, yminc + 1);
+ immVertex2f(shdr_pos, frame, ymaxc - 1);
+ }
+ }
+ immEnd();
+
+ immUnbindProgram();
}
/* Markers inside a NLA-Strip */
static void nla_strip_draw_markers(NlaStrip *strip, float yminc, float ymaxc)
{
- GPU_line_width(2.0f);
-
- if (strip->type == NLASTRIP_TYPE_CLIP) {
- /* try not to be too conspicuous, while being visible enough when transforming */
- int shade = (strip->flag & NLASTRIP_FLAG_SELECT) ? -60 : -40;
-
- /* just draw the markers in this clip */
- nla_actionclip_draw_markers(strip, yminc, ymaxc, shade, true);
- }
- else if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
- /* 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) {
- if (nls->type == NLASTRIP_TYPE_CLIP) {
- nla_actionclip_draw_markers(nls, yminc, ymaxc, shade, false);
- }
- }
- }
-
- GPU_line_width(1.0f);
+ GPU_line_width(2.0f);
+
+ if (strip->type == NLASTRIP_TYPE_CLIP) {
+ /* try not to be too conspicuous, while being visible enough when transforming */
+ int shade = (strip->flag & NLASTRIP_FLAG_SELECT) ? -60 : -40;
+
+ /* just draw the markers in this clip */
+ nla_actionclip_draw_markers(strip, yminc, ymaxc, shade, true);
+ }
+ else if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
+ /* 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) {
+ if (nls->type == NLASTRIP_TYPE_CLIP) {
+ nla_actionclip_draw_markers(nls, yminc, ymaxc, shade, false);
+ }
+ }
+ }
+
+ GPU_line_width(1.0f);
}
/* Strips (Proper) ---------------------- */
@@ -236,535 +249,551 @@ static void nla_strip_draw_markers(NlaStrip *strip, float yminc, float ymaxc)
/* get colors for drawing NLA-Strips */
static void nla_strip_get_color_inside(AnimData *adt, NlaStrip *strip, float color[3])
{
- if (strip->type == NLASTRIP_TYPE_TRANSITION) {
- /* Transition Clip */
- if (strip->flag & NLASTRIP_FLAG_SELECT) {
- /* selected - use a bright blue color */
- UI_GetThemeColor3fv(TH_NLA_TRANSITION_SEL, color);
- }
- else {
- /* normal, unselected strip - use (hardly noticeable) blue tinge */
- UI_GetThemeColor3fv(TH_NLA_TRANSITION, color);
- }
- }
- else if (strip->type == NLASTRIP_TYPE_META) {
- /* Meta Clip */
- // TODO: should temporary metas get different colors too?
- if (strip->flag & NLASTRIP_FLAG_SELECT) {
- /* selected - use a bold purple color */
- UI_GetThemeColor3fv(TH_NLA_META_SEL, color);
- }
- else {
- /* normal, unselected strip - use (hardly noticeable) dark purple tinge */
- UI_GetThemeColor3fv(TH_NLA_META, color);
- }
- }
- else if (strip->type == NLASTRIP_TYPE_SOUND) {
- /* Sound Clip */
- if (strip->flag & NLASTRIP_FLAG_SELECT) {
- /* selected - use a bright teal color */
- UI_GetThemeColor3fv(TH_NLA_SOUND_SEL, color);
- }
- else {
- /* normal, unselected strip - use (hardly noticeable) teal tinge */
- UI_GetThemeColor3fv(TH_NLA_SOUND, color);
- }
- }
- else {
- /* Action Clip (default/normal type of strip) */
- if (adt && (adt->flag & ADT_NLA_EDIT_ON) && (adt->actstrip == strip)) {
- /* active strip should be drawn green when it is acting as the tweaking strip.
- * however, this case should be skipped for when not in EditMode...
- */
- UI_GetThemeColor3fv(TH_NLA_TWEAK, color);
- }
- else if (strip->flag & NLASTRIP_FLAG_TWEAKUSER) {
- /* alert user that this strip is also used by the tweaking track (this is set when going into
- * 'editmode' for that strip), since the edits made here may not be what the user anticipated
- */
- UI_GetThemeColor3fv(TH_NLA_TWEAK_DUPLI, color);
- }
- else if (strip->flag & NLASTRIP_FLAG_SELECT) {
- /* selected strip - use theme color for selected */
- UI_GetThemeColor3fv(TH_STRIP_SELECT, color);
- }
- else {
- /* normal, unselected strip - use standard strip theme color */
- UI_GetThemeColor3fv(TH_STRIP, color);
- }
- }
+ if (strip->type == NLASTRIP_TYPE_TRANSITION) {
+ /* Transition Clip */
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ /* selected - use a bright blue color */
+ UI_GetThemeColor3fv(TH_NLA_TRANSITION_SEL, color);
+ }
+ else {
+ /* normal, unselected strip - use (hardly noticeable) blue tinge */
+ UI_GetThemeColor3fv(TH_NLA_TRANSITION, color);
+ }
+ }
+ else if (strip->type == NLASTRIP_TYPE_META) {
+ /* Meta Clip */
+ // TODO: should temporary metas get different colors too?
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ /* selected - use a bold purple color */
+ UI_GetThemeColor3fv(TH_NLA_META_SEL, color);
+ }
+ else {
+ /* normal, unselected strip - use (hardly noticeable) dark purple tinge */
+ UI_GetThemeColor3fv(TH_NLA_META, color);
+ }
+ }
+ else if (strip->type == NLASTRIP_TYPE_SOUND) {
+ /* Sound Clip */
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ /* selected - use a bright teal color */
+ UI_GetThemeColor3fv(TH_NLA_SOUND_SEL, color);
+ }
+ else {
+ /* normal, unselected strip - use (hardly noticeable) teal tinge */
+ UI_GetThemeColor3fv(TH_NLA_SOUND, color);
+ }
+ }
+ else {
+ /* Action Clip (default/normal type of strip) */
+ if (adt && (adt->flag & ADT_NLA_EDIT_ON) && (adt->actstrip == strip)) {
+ /* active strip should be drawn green when it is acting as the tweaking strip.
+ * however, this case should be skipped for when not in EditMode...
+ */
+ UI_GetThemeColor3fv(TH_NLA_TWEAK, color);
+ }
+ else if (strip->flag & NLASTRIP_FLAG_TWEAKUSER) {
+ /* alert user that this strip is also used by the tweaking track (this is set when going into
+ * 'editmode' for that strip), since the edits made here may not be what the user anticipated
+ */
+ UI_GetThemeColor3fv(TH_NLA_TWEAK_DUPLI, color);
+ }
+ else if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ /* selected strip - use theme color for selected */
+ UI_GetThemeColor3fv(TH_STRIP_SELECT, color);
+ }
+ else {
+ /* normal, unselected strip - use standard strip theme color */
+ UI_GetThemeColor3fv(TH_STRIP, color);
+ }
+ }
}
/* 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)
{
- const float yheight = ymaxc - yminc;
-
- immUniformColor3f(0.7f, 0.7f, 0.7f);
-
- /* draw with AA'd line */
- GPU_line_smooth(true);
- GPU_blend(true);
-
- /* influence -------------------------- */
- if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) {
- FCurve *fcu = list_find_fcurve(&strip->fcurves, "influence", 0);
- float cfra;
-
- /* plot the curve (over the strip's main region) */
- if (fcu) {
- immBegin(GPU_PRIM_LINE_STRIP, abs((int)(strip->end - strip->start) + 1));
-
- /* sample at 1 frame intervals, and draw
- * - min y-val is yminc, max is y-maxc, so clamp in those regions
- */
- for (cfra = strip->start; cfra <= strip->end; cfra += 1.0f) {
- float y = evaluate_fcurve(fcu, cfra); /* assume this to be in 0-1 range */
- CLAMP(y, 0.0f, 1.0f);
- immVertex2f(pos, cfra, ((y * yheight) + yminc));
- }
-
- immEnd();
- }
- }
- else {
- /* use blend in/out values only if both aren't zero */
- if ((IS_EQF(strip->blendin, 0.0f) && IS_EQF(strip->blendout, 0.0f)) == 0) {
- immBeginAtMost(GPU_PRIM_LINE_STRIP, 4);
-
- /* start of strip - if no blendin, start straight at 1,
- * otherwise from 0 to 1 over blendin frames */
- if (IS_EQF(strip->blendin, 0.0f) == 0) {
- immVertex2f(pos, strip->start, yminc);
- immVertex2f(pos, strip->start + strip->blendin, ymaxc);
- }
- else
- immVertex2f(pos, strip->start, ymaxc);
-
- /* end of strip */
- if (IS_EQF(strip->blendout, 0.0f) == 0) {
- immVertex2f(pos, strip->end - strip->blendout, ymaxc);
- immVertex2f(pos, strip->end, yminc);
- }
- else
- immVertex2f(pos, strip->end, ymaxc);
-
- immEnd();
- }
- }
-
- /* turn off AA'd lines */
- GPU_line_smooth(false);
- GPU_blend(false);
+ const float yheight = ymaxc - yminc;
+
+ immUniformColor3f(0.7f, 0.7f, 0.7f);
+
+ /* draw with AA'd line */
+ GPU_line_smooth(true);
+ GPU_blend(true);
+
+ /* influence -------------------------- */
+ if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) {
+ FCurve *fcu = list_find_fcurve(&strip->fcurves, "influence", 0);
+ float cfra;
+
+ /* plot the curve (over the strip's main region) */
+ if (fcu) {
+ immBegin(GPU_PRIM_LINE_STRIP, abs((int)(strip->end - strip->start) + 1));
+
+ /* sample at 1 frame intervals, and draw
+ * - min y-val is yminc, max is y-maxc, so clamp in those regions
+ */
+ for (cfra = strip->start; cfra <= strip->end; cfra += 1.0f) {
+ float y = evaluate_fcurve(fcu, cfra); /* assume this to be in 0-1 range */
+ CLAMP(y, 0.0f, 1.0f);
+ immVertex2f(pos, cfra, ((y * yheight) + yminc));
+ }
+
+ immEnd();
+ }
+ }
+ else {
+ /* use blend in/out values only if both aren't zero */
+ if ((IS_EQF(strip->blendin, 0.0f) && IS_EQF(strip->blendout, 0.0f)) == 0) {
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, 4);
+
+ /* start of strip - if no blendin, start straight at 1,
+ * otherwise from 0 to 1 over blendin frames */
+ if (IS_EQF(strip->blendin, 0.0f) == 0) {
+ immVertex2f(pos, strip->start, yminc);
+ immVertex2f(pos, strip->start + strip->blendin, ymaxc);
+ }
+ else
+ immVertex2f(pos, strip->start, ymaxc);
+
+ /* end of strip */
+ if (IS_EQF(strip->blendout, 0.0f) == 0) {
+ immVertex2f(pos, strip->end - strip->blendout, ymaxc);
+ immVertex2f(pos, strip->end, yminc);
+ }
+ else
+ immVertex2f(pos, strip->end, ymaxc);
+
+ immEnd();
+ }
+ }
+
+ /* turn off AA'd lines */
+ GPU_line_smooth(false);
+ GPU_blend(false);
}
/* helper call to setup dashed-lines for strip outlines */
static uint nla_draw_use_dashed_outlines(float color[4], bool muted)
{
- /* Note that we use dashed shader here, and make it draw solid lines if not muted... */
- uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
-
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
-
- immUniform1i("colors_len", 0); /* Simple dashes. */
- immUniformColor3fv(color);
-
- /* line style: dotted for muted */
- if (muted) {
- /* dotted - and slightly thicker for readability of the dashes */
- immUniform1f("dash_width", 5.0f);
- immUniform1f("dash_factor", 0.4f);
- GPU_line_width(1.5f);
- }
- else {
- /* solid line */
- immUniform1f("dash_factor", 2.0f);
- GPU_line_width(1.0f);
- }
-
- return shdr_pos;
+ /* Note that we use dashed shader here, and make it draw solid lines if not muted... */
+ uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("colors_len", 0); /* Simple dashes. */
+ immUniformColor3fv(color);
+
+ /* line style: dotted for muted */
+ if (muted) {
+ /* dotted - and slightly thicker for readability of the dashes */
+ immUniform1f("dash_width", 5.0f);
+ immUniform1f("dash_factor", 0.4f);
+ GPU_line_width(1.5f);
+ }
+ else {
+ /* solid line */
+ immUniform1f("dash_factor", 2.0f);
+ GPU_line_width(1.0f);
+ }
+
+ return shdr_pos;
}
/* main call for drawing a single NLA-strip */
-static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float yminc, float ymaxc)
+static void nla_draw_strip(SpaceNla *snla,
+ AnimData *adt,
+ NlaTrack *nlt,
+ NlaStrip *strip,
+ View2D *v2d,
+ float yminc,
+ float ymaxc)
{
- const bool non_solo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && (nlt->flag & NLATRACK_SOLO) == 0);
- const bool muted = ((nlt->flag & NLATRACK_MUTED) || (strip->flag & NLASTRIP_FLAG_MUTED));
- float color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
- uint shdr_pos;
-
- /* get color of strip */
- nla_strip_get_color_inside(adt, strip, color);
-
- shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* draw extrapolation info first (as backdrop)
- * - but this should only be drawn if track has some contribution
- */
- if ((strip->extendmode != NLASTRIP_EXTEND_NOTHING) && (non_solo == 0)) {
- /* enable transparency... */
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
-
- switch (strip->extendmode) {
- /* since this does both sides,
- * only do the 'before' side, and leave the rest to the next case */
- case NLASTRIP_EXTEND_HOLD:
- /* only need to draw here if there's no strip before since
- * it only applies in such a situation
- */
- if (strip->prev == NULL) {
- /* set the drawing color to the color of the strip, but with very faint alpha */
- immUniformColor3fvAlpha(color, 0.15f);
-
- /* draw the rect to the edge of the screen */
- immRectf(shdr_pos, v2d->cur.xmin, yminc, strip->start, ymaxc);
- }
- ATTR_FALLTHROUGH;
-
- /* this only draws after the strip */
- case NLASTRIP_EXTEND_HOLD_FORWARD:
- /* only need to try and draw if the next strip doesn't occur immediately after */
- if ((strip->next == NULL) || (IS_EQF(strip->next->start, strip->end) == 0)) {
- /* set the drawing color to the color of the strip, but this time less faint */
- immUniformColor3fvAlpha(color, 0.3f);
-
- /* draw the rect to the next strip or the edge of the screen */
- float x2 = strip->next ? strip->next->start : v2d->cur.xmax;
- immRectf(shdr_pos, strip->end, yminc, x2, ymaxc);
- }
- break;
- }
-
- GPU_blend(false);
- }
-
-
- /* draw 'inside' of strip itself */
- if (non_solo == 0) {
- immUnbindProgram();
-
- /* strip is in normal track */
- UI_draw_roundbox_corner_set(UI_CNR_ALL); /* all corners rounded */
- UI_draw_roundbox_shade_x(true, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1, color);
-
- /* restore current vertex format & program (roundbox trashes it) */
- shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- }
- else {
- /* strip is in disabled track - make less visible */
- immUniformColor3fvAlpha(color, 0.1f);
-
- GPU_blend(true);
- immRectf(shdr_pos, strip->start, yminc, strip->end, ymaxc);
- GPU_blend(false);
- }
-
-
- /* draw strip's control 'curves'
- * - only if user hasn't hidden them...
- */
- if ((snla->flag & SNLA_NOSTRIPCURVES) == 0)
- nla_draw_strip_curves(strip, yminc, ymaxc, shdr_pos);
-
- immUnbindProgram();
-
- /* draw markings indicating locations of local markers
- * (useful for lining up different actions) */
- if ((snla->flag & SNLA_NOLOCALMARKERS) == 0)
- nla_strip_draw_markers(strip, yminc, ymaxc);
-
- /* draw strip outline
- * - color used here is to indicate active vs non-active
- */
- if (strip->flag & NLASTRIP_FLAG_ACTIVE) {
- /* strip should appear 'sunken', so draw a light border around it */
- color[0] = 0.9f; /* FIXME: hardcoded temp-hack colors */
- color[1] = 1.0f;
- color[2] = 0.9f;
- }
- else {
- /* strip should appear to stand out, so draw a dark border around it */
- color[0] = color[1] = color[2] = 0.0f; /* FIXME: or 1.0f ?? */
- }
-
- /* draw outline
- * - dashed-line shader is loaded after this block
- */
- if (muted) {
- /* muted - draw dotted, squarish outline (for simplicity) */
- shdr_pos = nla_draw_use_dashed_outlines(color, muted);
- imm_draw_box_wire_2d(shdr_pos, strip->start, yminc, strip->end, ymaxc);
- }
- else {
- /* non-muted - draw solid, rounded outline */
- UI_draw_roundbox_shade_x(false, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1, color);
-
- /* restore current vertex format & program (roundbox trashes it) */
- shdr_pos = nla_draw_use_dashed_outlines(color, muted);
- }
-
- /* if action-clip strip, draw lines delimiting repeats too (in the same color as outline) */
- if ((strip->type == NLASTRIP_TYPE_CLIP) && strip->repeat > 1.0f) {
- float repeatLen = (strip->actend - strip->actstart) * strip->scale;
-
- /* only draw lines for whole-numbered repeats, starting from the first full-repeat
- * up to the last full repeat (but not if it lies on the end of the strip)
- */
- immBeginAtMost(GPU_PRIM_LINES, 2 * floorf(strip->repeat));
- for (int i = 1; i < strip->repeat; i++) {
- float repeatPos = strip->start + (repeatLen * i);
-
- /* don't draw if line would end up on or after the end of the strip */
- if (repeatPos < strip->end) {
- immVertex2f(shdr_pos, repeatPos, yminc + 4);
- immVertex2f(shdr_pos, repeatPos, ymaxc - 4);
- }
- }
- immEnd();
- }
- /* or if meta-strip, draw lines delimiting extents of sub-strips
- * (in same color as outline, if more than 1 exists) */
- else if ((strip->type == NLASTRIP_TYPE_META) && (strip->strips.first != strip->strips.last)) {
- const float y = (ymaxc - yminc) * 0.5f + yminc;
-
- /* up to 2 lines per strip */
- 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) {
- /* draw start-line if not same as end of previous (and only if not the first strip)
- * - on upper half of strip
- */
- if ((cs->prev) && IS_EQF(cs->prev->end, cs->start) == 0) {
- immVertex2f(shdr_pos, cs->start, y);
- immVertex2f(shdr_pos, cs->start, ymaxc);
- }
-
- /* draw end-line if not the last strip
- * - on lower half of strip
- */
- if (cs->next) {
- immVertex2f(shdr_pos, cs->end, yminc);
- immVertex2f(shdr_pos, cs->end, y);
- }
- }
-
- immEnd();
- }
-
- immUnbindProgram();
+ const bool non_solo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) &&
+ (nlt->flag & NLATRACK_SOLO) == 0);
+ const bool muted = ((nlt->flag & NLATRACK_MUTED) || (strip->flag & NLASTRIP_FLAG_MUTED));
+ float color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ uint shdr_pos;
+
+ /* get color of strip */
+ nla_strip_get_color_inside(adt, strip, color);
+
+ shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* draw extrapolation info first (as backdrop)
+ * - but this should only be drawn if track has some contribution
+ */
+ if ((strip->extendmode != NLASTRIP_EXTEND_NOTHING) && (non_solo == 0)) {
+ /* enable transparency... */
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
+
+ switch (strip->extendmode) {
+ /* since this does both sides,
+ * only do the 'before' side, and leave the rest to the next case */
+ case NLASTRIP_EXTEND_HOLD:
+ /* only need to draw here if there's no strip before since
+ * it only applies in such a situation
+ */
+ if (strip->prev == NULL) {
+ /* set the drawing color to the color of the strip, but with very faint alpha */
+ immUniformColor3fvAlpha(color, 0.15f);
+
+ /* draw the rect to the edge of the screen */
+ immRectf(shdr_pos, v2d->cur.xmin, yminc, strip->start, ymaxc);
+ }
+ ATTR_FALLTHROUGH;
+
+ /* this only draws after the strip */
+ case NLASTRIP_EXTEND_HOLD_FORWARD:
+ /* only need to try and draw if the next strip doesn't occur immediately after */
+ if ((strip->next == NULL) || (IS_EQF(strip->next->start, strip->end) == 0)) {
+ /* set the drawing color to the color of the strip, but this time less faint */
+ immUniformColor3fvAlpha(color, 0.3f);
+
+ /* draw the rect to the next strip or the edge of the screen */
+ float x2 = strip->next ? strip->next->start : v2d->cur.xmax;
+ immRectf(shdr_pos, strip->end, yminc, x2, ymaxc);
+ }
+ break;
+ }
+
+ GPU_blend(false);
+ }
+
+ /* draw 'inside' of strip itself */
+ if (non_solo == 0) {
+ immUnbindProgram();
+
+ /* strip is in normal track */
+ UI_draw_roundbox_corner_set(UI_CNR_ALL); /* all corners rounded */
+ UI_draw_roundbox_shade_x(true, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1, color);
+
+ /* restore current vertex format & program (roundbox trashes it) */
+ shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ }
+ else {
+ /* strip is in disabled track - make less visible */
+ immUniformColor3fvAlpha(color, 0.1f);
+
+ GPU_blend(true);
+ immRectf(shdr_pos, strip->start, yminc, strip->end, ymaxc);
+ GPU_blend(false);
+ }
+
+ /* draw strip's control 'curves'
+ * - only if user hasn't hidden them...
+ */
+ if ((snla->flag & SNLA_NOSTRIPCURVES) == 0)
+ nla_draw_strip_curves(strip, yminc, ymaxc, shdr_pos);
+
+ immUnbindProgram();
+
+ /* draw markings indicating locations of local markers
+ * (useful for lining up different actions) */
+ if ((snla->flag & SNLA_NOLOCALMARKERS) == 0)
+ nla_strip_draw_markers(strip, yminc, ymaxc);
+
+ /* draw strip outline
+ * - color used here is to indicate active vs non-active
+ */
+ if (strip->flag & NLASTRIP_FLAG_ACTIVE) {
+ /* strip should appear 'sunken', so draw a light border around it */
+ color[0] = 0.9f; /* FIXME: hardcoded temp-hack colors */
+ color[1] = 1.0f;
+ color[2] = 0.9f;
+ }
+ else {
+ /* strip should appear to stand out, so draw a dark border around it */
+ color[0] = color[1] = color[2] = 0.0f; /* FIXME: or 1.0f ?? */
+ }
+
+ /* draw outline
+ * - dashed-line shader is loaded after this block
+ */
+ if (muted) {
+ /* muted - draw dotted, squarish outline (for simplicity) */
+ shdr_pos = nla_draw_use_dashed_outlines(color, muted);
+ imm_draw_box_wire_2d(shdr_pos, strip->start, yminc, strip->end, ymaxc);
+ }
+ else {
+ /* non-muted - draw solid, rounded outline */
+ UI_draw_roundbox_shade_x(false, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1, color);
+
+ /* restore current vertex format & program (roundbox trashes it) */
+ shdr_pos = nla_draw_use_dashed_outlines(color, muted);
+ }
+
+ /* if action-clip strip, draw lines delimiting repeats too (in the same color as outline) */
+ if ((strip->type == NLASTRIP_TYPE_CLIP) && strip->repeat > 1.0f) {
+ float repeatLen = (strip->actend - strip->actstart) * strip->scale;
+
+ /* only draw lines for whole-numbered repeats, starting from the first full-repeat
+ * up to the last full repeat (but not if it lies on the end of the strip)
+ */
+ immBeginAtMost(GPU_PRIM_LINES, 2 * floorf(strip->repeat));
+ for (int i = 1; i < strip->repeat; i++) {
+ float repeatPos = strip->start + (repeatLen * i);
+
+ /* don't draw if line would end up on or after the end of the strip */
+ if (repeatPos < strip->end) {
+ immVertex2f(shdr_pos, repeatPos, yminc + 4);
+ immVertex2f(shdr_pos, repeatPos, ymaxc - 4);
+ }
+ }
+ immEnd();
+ }
+ /* or if meta-strip, draw lines delimiting extents of sub-strips
+ * (in same color as outline, if more than 1 exists) */
+ else if ((strip->type == NLASTRIP_TYPE_META) && (strip->strips.first != strip->strips.last)) {
+ const float y = (ymaxc - yminc) * 0.5f + yminc;
+
+ /* up to 2 lines per strip */
+ 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) {
+ /* draw start-line if not same as end of previous (and only if not the first strip)
+ * - on upper half of strip
+ */
+ if ((cs->prev) && IS_EQF(cs->prev->end, cs->start) == 0) {
+ immVertex2f(shdr_pos, cs->start, y);
+ immVertex2f(shdr_pos, cs->start, ymaxc);
+ }
+
+ /* draw end-line if not the last strip
+ * - on lower half of strip
+ */
+ if (cs->next) {
+ immVertex2f(shdr_pos, cs->end, yminc);
+ immVertex2f(shdr_pos, cs->end, y);
+ }
+ }
+
+ immEnd();
+ }
+
+ immUnbindProgram();
}
/* add the relevant text to the cache of text-strings to draw in pixelspace */
-static void nla_draw_strip_text(
- AnimData *adt, NlaTrack *nlt, NlaStrip *strip, int index, View2D *v2d,
- float xminc, float xmaxc, float yminc, float ymaxc)
+static void nla_draw_strip_text(AnimData *adt,
+ NlaTrack *nlt,
+ NlaStrip *strip,
+ int index,
+ View2D *v2d,
+ float xminc,
+ float xmaxc,
+ float yminc,
+ float ymaxc)
{
- const bool non_solo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && (nlt->flag & NLATRACK_SOLO) == 0);
- char str[256];
- size_t str_len;
- char col[4];
-
- /* just print the name and the range */
- if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
- str_len = BLI_snprintf_rlen(str, sizeof(str), "%d) Temp-Meta", index);
- }
- else {
- str_len = BLI_strncpy_rlen(str, strip->name, sizeof(str));
- }
-
- /* set text color - if colors (see above) are light, draw black text, otherwise draw white */
- if (strip->flag & (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_TWEAKUSER)) {
- col[0] = col[1] = col[2] = 0;
- }
- else {
- col[0] = col[1] = col[2] = 255;
- }
-
- /* text opacity depends on whether if there's a solo'd track, this isn't it */
- if (non_solo == 0)
- col[3] = 255;
- else
- col[3] = 128;
-
- /* set bounding-box for text
- * - padding of 2 'units' on either side
- */
- /* TODO: make this centered? */
- rctf rect = {
- .xmin = xminc,
- .ymin = yminc,
- .xmax = xmaxc,
- .ymax = ymaxc,
- };
-
- /* add this string to the cache of texts to draw */
- UI_view2d_text_cache_add_rectf(v2d, &rect, str, str_len, col);
+ const bool non_solo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) &&
+ (nlt->flag & NLATRACK_SOLO) == 0);
+ char str[256];
+ size_t str_len;
+ char col[4];
+
+ /* just print the name and the range */
+ if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
+ str_len = BLI_snprintf_rlen(str, sizeof(str), "%d) Temp-Meta", index);
+ }
+ else {
+ str_len = BLI_strncpy_rlen(str, strip->name, sizeof(str));
+ }
+
+ /* set text color - if colors (see above) are light, draw black text, otherwise draw white */
+ if (strip->flag & (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_TWEAKUSER)) {
+ col[0] = col[1] = col[2] = 0;
+ }
+ else {
+ col[0] = col[1] = col[2] = 255;
+ }
+
+ /* text opacity depends on whether if there's a solo'd track, this isn't it */
+ if (non_solo == 0)
+ col[3] = 255;
+ else
+ col[3] = 128;
+
+ /* set bounding-box for text
+ * - padding of 2 'units' on either side
+ */
+ /* TODO: make this centered? */
+ rctf rect = {
+ .xmin = xminc,
+ .ymin = yminc,
+ .xmax = xmaxc,
+ .ymax = ymaxc,
+ };
+
+ /* add this string to the cache of texts to draw */
+ UI_view2d_text_cache_add_rectf(v2d, &rect, str, str_len, col);
}
/* add frame extents to cache of text-strings to draw in pixelspace
* for now, only used when transforming strips
*/
-static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, View2D *v2d, float UNUSED(yminc), float ymaxc)
+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 */
- char numstr[32];
- size_t numstr_len;
-
- /* Always draw times above the strip, whereas sequencer drew below + above.
- * However, we should be fine having everything on top, since these tend to be
- * quite spaced out.
- * - 1 dp is compromise between lack of precision (ints only, as per sequencer)
- * while also preserving some accuracy, since we do use floats
- */
- /* start frame */
- numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->start);
- UI_view2d_text_cache_add(v2d, strip->start - 1.0f, ymaxc + ytol, numstr, numstr_len, col);
-
- /* end frame */
- numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->end);
- UI_view2d_text_cache_add(v2d, strip->end, ymaxc + ytol, numstr, numstr_len, col);
+ const float ytol = 1.0f; /* small offset to vertical positioning of text, for legibility */
+ const char col[4] = {220, 220, 220, 255}; /* light gray */
+ char numstr[32];
+ size_t numstr_len;
+
+ /* Always draw times above the strip, whereas sequencer drew below + above.
+ * However, we should be fine having everything on top, since these tend to be
+ * quite spaced out.
+ * - 1 dp is compromise between lack of precision (ints only, as per sequencer)
+ * while also preserving some accuracy, since we do use floats
+ */
+ /* start frame */
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->start);
+ UI_view2d_text_cache_add(v2d, strip->start - 1.0f, ymaxc + ytol, numstr, numstr_len, col);
+
+ /* end frame */
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->end);
+ UI_view2d_text_cache_add(v2d, strip->end, ymaxc + ytol, numstr, numstr_len, col);
}
/* ---------------------- */
void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
{
- View2D *v2d = &ar->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;
-
- /* build list of channels to draw */
- ListBase anim_data = {NULL, NULL};
- int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* Update max-extent of channels here (taking into account scrollers):
- * - this is done to allow the channel list to be scrollable, but must be done here
- * to avoid regenerating the list again and/or also because channels list is drawn first
- * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
- * start of list offset, and the second is as a correction for the scrollers.
- */
- int height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2));
-
- /* don't use totrect set, as the width stays the same
- * (NOTE: this is ok here, the configuration is pretty straightforward)
- */
- v2d->tot.ymin = (float)(-height);
-
- /* loop through channels, and set up drawing depending on their type */
- float y = (float)(-NLACHANNEL_HEIGHT(snla));
-
- for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) {
- const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla));
- const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla));
-
- /* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
- {
- /* data to draw depends on the type of channel */
- switch (ale->type) {
- case ANIMTYPE_NLATRACK:
- {
- AnimData *adt = ale->adt;
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
- int index;
-
- /* draw each strip in the track (if visible) */
- for (strip = nlt->strips.first, index = 1; strip; strip = strip->next, index++) {
- if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) {
- const float xminc = strip->start + text_margin_x;
- const float xmaxc = strip->end + text_margin_x;
-
- /* draw the visualization of the strip */
- nla_draw_strip(snla, adt, nlt, strip, v2d, yminc, ymaxc);
-
- /* add the text for this strip to the cache */
- if (xminc < xmaxc) {
- nla_draw_strip_text(adt, nlt, strip, index, v2d, xminc, xmaxc, yminc, ymaxc);
- }
-
- /* if transforming strips (only real reason for temp-metas currently),
- * add to the cache the frame numbers of the strip's extents
- */
- if (strip->flag & NLASTRIP_FLAG_TEMP_META)
- nla_draw_strip_frames_text(nlt, strip, v2d, yminc, ymaxc);
- }
- }
- break;
- }
- case ANIMTYPE_NLAACTION:
- {
- AnimData *adt = ale->adt;
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* just draw a semi-shaded rect spanning the width of the viewable area if there's data,
- * and a second darker rect within which we draw keyframe indicator dots if there's data
- */
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
-
- /* get colors for drawing */
- float color[4];
- nla_action_get_color(adt, ale->data, color);
- immUniformColor4fv(color);
-
- /* draw slightly shifted up for greater separation from standard channels,
- * but also slightly shorter for some more contrast when viewing the strips
- */
- immRectf(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
-
- /* draw 'embossed' lines above and below the strip for effect */
- /* white base-lines */
- GPU_line_width(2.0f);
- immUniformColor4f(1.0f, 1.0f, 1.0f, 0.3f);
- immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP);
- immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP);
- immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP);
- immVertex2f(pos, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
- immEnd();
-
- /* black top-lines */
- GPU_line_width(1.0f);
- immUniformColor3f(0.0f, 0.0f, 0.0f);
- immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP);
- immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP);
- immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP);
- immVertex2f(pos, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
- immEnd();
-
- /* TODO: these lines but better --^ */
-
- immUnbindProgram();
-
- /* draw keyframes in the action */
- nla_action_draw_keyframes(v2d, adt, ale->data, y, yminc + NLACHANNEL_SKIP, ymaxc - NLACHANNEL_SKIP);
-
- GPU_blend(false);
- break;
- }
- }
- }
-
- /* adjust y-position for next one */
- y -= NLACHANNEL_STEP(snla);
- }
-
- /* free tempolary channels */
- ANIM_animdata_freelist(&anim_data);
+ View2D *v2d = &ar->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;
+
+ /* build list of channels to draw */
+ ListBase anim_data = {NULL, NULL};
+ int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* Update max-extent of channels here (taking into account scrollers):
+ * - this is done to allow the channel list to be scrollable, but must be done here
+ * to avoid regenerating the list again and/or also because channels list is drawn first
+ * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
+ * start of list offset, and the second is as a correction for the scrollers.
+ */
+ int height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2));
+
+ /* don't use totrect set, as the width stays the same
+ * (NOTE: this is ok here, the configuration is pretty straightforward)
+ */
+ v2d->tot.ymin = (float)(-height);
+
+ /* loop through channels, and set up drawing depending on their type */
+ float y = (float)(-NLACHANNEL_HEIGHT(snla));
+
+ for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) {
+ const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla));
+ const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla));
+
+ /* check if visible */
+ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ /* data to draw depends on the type of channel */
+ switch (ale->type) {
+ case ANIMTYPE_NLATRACK: {
+ AnimData *adt = ale->adt;
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
+ int index;
+
+ /* draw each strip in the track (if visible) */
+ for (strip = nlt->strips.first, index = 1; strip; strip = strip->next, index++) {
+ if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) {
+ const float xminc = strip->start + text_margin_x;
+ const float xmaxc = strip->end + text_margin_x;
+
+ /* draw the visualization of the strip */
+ nla_draw_strip(snla, adt, nlt, strip, v2d, yminc, ymaxc);
+
+ /* add the text for this strip to the cache */
+ if (xminc < xmaxc) {
+ nla_draw_strip_text(adt, nlt, strip, index, v2d, xminc, xmaxc, yminc, ymaxc);
+ }
+
+ /* if transforming strips (only real reason for temp-metas currently),
+ * add to the cache the frame numbers of the strip's extents
+ */
+ if (strip->flag & NLASTRIP_FLAG_TEMP_META)
+ nla_draw_strip_frames_text(nlt, strip, v2d, yminc, ymaxc);
+ }
+ }
+ break;
+ }
+ case ANIMTYPE_NLAACTION: {
+ AnimData *adt = ale->adt;
+
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* just draw a semi-shaded rect spanning the width of the viewable area if there's data,
+ * and a second darker rect within which we draw keyframe indicator dots if there's data
+ */
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
+
+ /* get colors for drawing */
+ float color[4];
+ nla_action_get_color(adt, ale->data, color);
+ immUniformColor4fv(color);
+
+ /* draw slightly shifted up for greater separation from standard channels,
+ * but also slightly shorter for some more contrast when viewing the strips
+ */
+ immRectf(
+ pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
+
+ /* draw 'embossed' lines above and below the strip for effect */
+ /* white base-lines */
+ GPU_line_width(2.0f);
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.3f);
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
+ immEnd();
+
+ /* black top-lines */
+ GPU_line_width(1.0f);
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
+ immEnd();
+
+ /* TODO: these lines but better --^ */
+
+ immUnbindProgram();
+
+ /* draw keyframes in the action */
+ nla_action_draw_keyframes(
+ v2d, adt, ale->data, y, yminc + NLACHANNEL_SKIP, ymaxc - NLACHANNEL_SKIP);
+
+ GPU_blend(false);
+ break;
+ }
+ }
+ }
+
+ /* adjust y-position for next one */
+ y -= NLACHANNEL_STEP(snla);
+ }
+
+ /* free tempolary channels */
+ ANIM_animdata_freelist(&anim_data);
}
/* *********************************************** */
@@ -772,95 +801,94 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- SpaceNla *snla = (SpaceNla *)ac->sl;
- View2D *v2d = &ar->v2d;
- float y = 0.0f;
- size_t items;
-
- /* build list of channels to draw */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* Update max-extent of channels here (taking into account scrollers):
- * - this is done to allow the channel list to be scrollable, but must be done here
- * to avoid regenerating the list again and/or also because channels list is drawn first
- * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
- * start of list offset, and the second is as a correction for the scrollers.
- */
- int height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2));
- /* don't use totrect set, as the width stays the same
- * (NOTE: this is ok here, the configuration is pretty straightforward)
- */
- v2d->tot.ymin = (float)(-height);
- /* 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);
-
- /* draw channels */
- { /* first pass: just the standard GL-drawing for backdrop + text */
- size_t channel_index = 0;
-
- y = (float)(-NLACHANNEL_HEIGHT(snla));
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla));
- float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla));
-
- /* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
- {
- /* draw all channels using standard channel-drawing API */
- ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index);
- }
-
- /* adjust y-position for next one */
- y -= NLACHANNEL_STEP(snla);
- channel_index++;
- }
- }
- { /* second pass: UI widgets */
- uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
- size_t channel_index = 0;
-
- y = (float)(-NLACHANNEL_HEIGHT(snla));
-
- /* set blending again, as may not be set in previous step */
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
-
- /* loop through channels, and set up drawing depending on their type */
- for (ale = anim_data.first; ale; ale = ale->next) {
- const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla));
- const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla));
-
- /* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
- {
- /* draw all channels using standard channel-drawing API */
- rctf channel_rect;
- BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax, yminc, ymaxc);
- ANIM_channel_draw_widgets(C, ac, ale, block, &channel_rect, channel_index);
- }
-
- /* adjust y-position for next one */
- y -= NLACHANNEL_STEP(snla);
- channel_index++;
- }
-
- UI_block_end(C, block);
- UI_block_draw(C, block);
-
- GPU_blend(false);
- }
-
- /* free temporary channels */
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ SpaceNla *snla = (SpaceNla *)ac->sl;
+ View2D *v2d = &ar->v2d;
+ float y = 0.0f;
+ size_t items;
+
+ /* build list of channels to draw */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* Update max-extent of channels here (taking into account scrollers):
+ * - this is done to allow the channel list to be scrollable, but must be done here
+ * to avoid regenerating the list again and/or also because channels list is drawn first
+ * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
+ * start of list offset, and the second is as a correction for the scrollers.
+ */
+ int height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2));
+ /* don't use totrect set, as the width stays the same
+ * (NOTE: this is ok here, the configuration is pretty straightforward)
+ */
+ v2d->tot.ymin = (float)(-height);
+ /* 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);
+
+ /* draw channels */
+ { /* first pass: just the standard GL-drawing for backdrop + text */
+ size_t channel_index = 0;
+
+ y = (float)(-NLACHANNEL_HEIGHT(snla));
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla));
+ float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla));
+
+ /* check if visible */
+ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ /* draw all channels using standard channel-drawing API */
+ ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index);
+ }
+
+ /* adjust y-position for next one */
+ y -= NLACHANNEL_STEP(snla);
+ channel_index++;
+ }
+ }
+ { /* second pass: UI widgets */
+ uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ size_t channel_index = 0;
+
+ y = (float)(-NLACHANNEL_HEIGHT(snla));
+
+ /* set blending again, as may not be set in previous step */
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
+
+ /* loop through channels, and set up drawing depending on their type */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla));
+ const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla));
+
+ /* check if visible */
+ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ /* draw all channels using standard channel-drawing API */
+ rctf channel_rect;
+ BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax, yminc, ymaxc);
+ ANIM_channel_draw_widgets(C, ac, ale, block, &channel_rect, channel_index);
+ }
+
+ /* adjust y-position for next one */
+ y -= NLACHANNEL_STEP(snla);
+ channel_index++;
+ }
+
+ UI_block_end(C, block);
+ UI_block_draw(C, block);
+
+ GPU_blend(false);
+ }
+
+ /* free temporary channels */
+ ANIM_animdata_freelist(&anim_data);
}
/* *********************************************** */
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index 1d21619fbd1..79c2242cd01 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -21,7 +21,6 @@
* \ingroup spnla
*/
-
#include <string.h>
#include <stdio.h>
#include <math.h>
@@ -66,8 +65,8 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "nla_intern.h" // own include
-#include "nla_private.h" // FIXME... maybe this shouldn't be included?
+#include "nla_intern.h" // own include
+#include "nla_private.h" // FIXME... maybe this shouldn't be included?
/* *********************************************** */
/* Utilities exported to other places... */
@@ -75,23 +74,23 @@
/* Perform validation for blending/extend settings */
void ED_nla_postop_refresh(bAnimContext *ac)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA | ANIMFILTER_FOREDIT);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA | ANIMFILTER_FOREDIT);
- /* get blocks to work on */
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ /* get blocks to work on */
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* performing auto-blending, extend-mode validation, etc. */
- BKE_nla_validate_state(ale->data);
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* performing auto-blending, extend-mode validation, etc. */
+ BKE_nla_validate_state(ale->data);
- ale->update |= ANIM_UPDATE_DEPS;
- }
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
- /* free temp memory */
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ /* free temp memory */
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
}
/* *********************************************** */
@@ -104,92 +103,96 @@ void ED_nla_postop_refresh(bAnimContext *ac)
static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- const bool do_solo = RNA_boolean_get(op->ptr, "isolate_action");
- bool ok = false;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get a list of the AnimData blocks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* if no blocks, popup error? */
- if (BLI_listbase_is_empty(&anim_data)) {
- BKE_report(op->reports, RPT_ERROR, "No AnimData blocks to enter tweak mode for");
- return OPERATOR_CANCELLED;
- }
-
- /* for each AnimData block with NLA-data, try setting it in tweak-mode */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ale->data;
-
- /* try entering tweakmode if valid */
- ok |= BKE_nla_tweakmode_enter(adt);
-
- /* mark the active track as being "solo"? */
- if (do_solo && adt->actstrip) {
- NlaTrack *nlt = BKE_nlatrack_find_tweaked(adt);
-
- if (nlt && !(nlt->flag & NLATRACK_SOLO)) {
- BKE_nlatrack_solo_toggle(adt, nlt);
- }
- }
-
- ale->update |= ANIM_UPDATE_DEPS;
- }
-
- /* free temp data */
- ANIM_animdata_update(&ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
-
- /* if we managed to enter tweakmode on at least one AnimData block,
- * set the flag for this in the active scene and send notifiers
- */
- if (ac.scene && ok) {
- /* set editing flag */
- ac.scene->flag |= SCE_NLA_EDIT_ON;
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "No active strip(s) to enter tweak mode on");
- return OPERATOR_CANCELLED;
- }
-
- /* done */
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ const bool do_solo = RNA_boolean_get(op->ptr, "isolate_action");
+ bool ok = false;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the AnimData blocks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* if no blocks, popup error? */
+ if (BLI_listbase_is_empty(&anim_data)) {
+ BKE_report(op->reports, RPT_ERROR, "No AnimData blocks to enter tweak mode for");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* for each AnimData block with NLA-data, try setting it in tweak-mode */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ale->data;
+
+ /* try entering tweakmode if valid */
+ ok |= BKE_nla_tweakmode_enter(adt);
+
+ /* mark the active track as being "solo"? */
+ if (do_solo && adt->actstrip) {
+ NlaTrack *nlt = BKE_nlatrack_find_tweaked(adt);
+
+ if (nlt && !(nlt->flag & NLATRACK_SOLO)) {
+ BKE_nlatrack_solo_toggle(adt, nlt);
+ }
+ }
+
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+
+ /* free temp data */
+ ANIM_animdata_update(&ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+
+ /* if we managed to enter tweakmode on at least one AnimData block,
+ * set the flag for this in the active scene and send notifiers
+ */
+ if (ac.scene && ok) {
+ /* set editing flag */
+ ac.scene->flag |= SCE_NLA_EDIT_ON;
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No active strip(s) to enter tweak mode on");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_tweakmode_enter(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Enter Tweak Mode";
- ot->idname = "NLA_OT_tweakmode_enter";
- ot->description = "Enter tweaking mode for the action referenced by the active strip to edit its keyframes";
-
- /* api callbacks */
- ot->exec = nlaedit_enable_tweakmode_exec;
- ot->poll = nlaop_poll_tweakmode_off;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_boolean(ot->srna, "isolate_action", 0, "Isolate Action",
- "Enable 'solo' on the NLA Track containing the active strip, "
- "to edit it without seeing the effects of the NLA stack");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Enter Tweak Mode";
+ ot->idname = "NLA_OT_tweakmode_enter";
+ ot->description =
+ "Enter tweaking mode for the action referenced by the active strip to edit its keyframes";
+
+ /* api callbacks */
+ ot->exec = nlaedit_enable_tweakmode_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna,
+ "isolate_action",
+ 0,
+ "Isolate Action",
+ "Enable 'solo' on the NLA Track containing the active strip, "
+ "to edit it without seeing the effects of the NLA stack");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ------------- */
@@ -197,99 +200,100 @@ void NLA_OT_tweakmode_enter(wmOperatorType *ot)
/* NLA Editor internal API function for exiting tweakmode */
bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* get a list of the AnimData blocks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* if no blocks, popup error? */
- if (BLI_listbase_is_empty(&anim_data)) {
- BKE_report(ac->reports, RPT_ERROR, "No AnimData blocks in tweak mode to exit from");
- return false;
- }
-
- /* for each AnimData block with NLA-data, try exitting tweak-mode */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ale->data;
-
- /* clear solo flags */
- if ((do_solo) & (adt->flag & ADT_NLA_SOLO_TRACK) &&
- (adt->flag & ADT_NLA_EDIT_ON))
- {
- BKE_nlatrack_solo_toggle(adt, NULL);
- }
-
- /* to be sure that we're doing everything right, just exit tweakmode... */
- BKE_nla_tweakmode_exit(adt);
-
- ale->update |= ANIM_UPDATE_DEPS;
- }
-
- /* free temp data */
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
-
- /* if we managed to enter tweakmode on at least one AnimData block,
- * set the flag for this in the active scene and send notifiers
- */
- if (ac->scene) {
- /* clear editing flag */
- ac->scene->flag &= ~SCE_NLA_EDIT_ON;
-
- /* set notifier that things have changed */
- WM_main_add_notifier(NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
- }
-
- /* done */
- return true;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get a list of the AnimData blocks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* if no blocks, popup error? */
+ if (BLI_listbase_is_empty(&anim_data)) {
+ BKE_report(ac->reports, RPT_ERROR, "No AnimData blocks in tweak mode to exit from");
+ return false;
+ }
+
+ /* for each AnimData block with NLA-data, try exitting tweak-mode */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ale->data;
+
+ /* clear solo flags */
+ if ((do_solo) & (adt->flag & ADT_NLA_SOLO_TRACK) && (adt->flag & ADT_NLA_EDIT_ON)) {
+ BKE_nlatrack_solo_toggle(adt, NULL);
+ }
+
+ /* to be sure that we're doing everything right, just exit tweakmode... */
+ BKE_nla_tweakmode_exit(adt);
+
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+
+ /* free temp data */
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+
+ /* if we managed to enter tweakmode on at least one AnimData block,
+ * set the flag for this in the active scene and send notifiers
+ */
+ if (ac->scene) {
+ /* clear editing flag */
+ ac->scene->flag &= ~SCE_NLA_EDIT_ON;
+
+ /* set notifier that things have changed */
+ WM_main_add_notifier(NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
+ }
+
+ /* done */
+ return true;
}
/* exit tweakmode operator callback */
static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
+ bAnimContext ac;
- const bool do_solo = RNA_boolean_get(op->ptr, "isolate_action");
- bool ok = false;
+ const bool do_solo = RNA_boolean_get(op->ptr, "isolate_action");
+ bool ok = false;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* perform operation */
- ok = nlaedit_disable_tweakmode(&ac, do_solo);
+ /* perform operation */
+ ok = nlaedit_disable_tweakmode(&ac, do_solo);
- /* success? */
- if (ok)
- return OPERATOR_FINISHED;
- else
- return OPERATOR_CANCELLED;
+ /* success? */
+ if (ok)
+ return OPERATOR_FINISHED;
+ else
+ return OPERATOR_CANCELLED;
}
void NLA_OT_tweakmode_exit(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Exit Tweak Mode";
- ot->idname = "NLA_OT_tweakmode_exit";
- ot->description = "Exit tweaking mode for the action referenced by the active strip";
-
- /* api callbacks */
- ot->exec = nlaedit_disable_tweakmode_exec;
- ot->poll = nlaop_poll_tweakmode_on;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_boolean(ot->srna, "isolate_action", 0, "Isolate Action",
- "Disable 'solo' on any of the NLA Tracks after exiting tweak mode "
- "to get things back to normal");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Exit Tweak Mode";
+ ot->idname = "NLA_OT_tweakmode_exit";
+ ot->description = "Exit tweaking mode for the action referenced by the active strip";
+
+ /* api callbacks */
+ ot->exec = nlaedit_disable_tweakmode_exec;
+ ot->poll = nlaop_poll_tweakmode_on;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna,
+ "isolate_action",
+ 0,
+ "Isolate Action",
+ "Disable 'solo' on any of the NLA Tracks after exiting tweak mode "
+ "to get things back to normal");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* *********************************************** */
@@ -300,98 +304,98 @@ void NLA_OT_tweakmode_exit(wmOperatorType *ot)
/* Get the min/max strip extents */
static void get_nlastrip_extents(bAnimContext *ac, float *min, float *max, const bool only_sel)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- bool found_bounds = false;
-
- /* get data to filter */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* set large values to try to override */
- *min = 999999999.0f;
- *max = -999999999.0f;
-
- /* check if any channels to set range with */
- if (anim_data.first) {
- /* go through channels, finding max extents */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
-
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- /* only consider selected strips? */
- if ((only_sel == false) || (strip->flag & NLASTRIP_FLAG_SELECT)) {
- /* extend range if appropriate */
- *min = min_ff(*min, strip->start);
- *max = max_ff(*max, strip->end);
-
- found_bounds = true;
- }
- }
- }
-
- /* free memory */
- ANIM_animdata_freelist(&anim_data);
- }
-
- /* set default range if nothing happened */
- if (found_bounds == false) {
- if (ac->scene) {
- *min = (float)ac->scene->r.sfra;
- *max = (float)ac->scene->r.efra;
- }
- else {
- *min = -5;
- *max = 100;
- }
- }
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ bool found_bounds = false;
+
+ /* get data to filter */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* set large values to try to override */
+ *min = 999999999.0f;
+ *max = -999999999.0f;
+
+ /* check if any channels to set range with */
+ if (anim_data.first) {
+ /* go through channels, finding max extents */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ /* only consider selected strips? */
+ if ((only_sel == false) || (strip->flag & NLASTRIP_FLAG_SELECT)) {
+ /* extend range if appropriate */
+ *min = min_ff(*min, strip->start);
+ *max = max_ff(*max, strip->end);
+
+ found_bounds = true;
+ }
+ }
+ }
+
+ /* free memory */
+ ANIM_animdata_freelist(&anim_data);
+ }
+
+ /* set default range if nothing happened */
+ if (found_bounds == false) {
+ if (ac->scene) {
+ *min = (float)ac->scene->r.sfra;
+ *max = (float)ac->scene->r.efra;
+ }
+ else {
+ *min = -5;
+ *max = 100;
+ }
+ }
}
/* ****************** Automatic Preview-Range Operator ****************** */
static int nlaedit_previewrange_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
- Scene *scene;
- float min, max;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- if (ac.scene == NULL)
- return OPERATOR_CANCELLED;
- else
- scene = ac.scene;
-
- /* set the range directly */
- get_nlastrip_extents(&ac, &min, &max, true);
- scene->r.flag |= SCER_PRV_RANGE;
- scene->r.psfra = round_fl_to_int(min);
- scene->r.pefra = round_fl_to_int(max);
-
- /* set notifier that things have changed */
- // XXX err... there's nothing for frame ranges yet, but this should do fine too
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ Scene *scene;
+ float min, max;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ if (ac.scene == NULL)
+ return OPERATOR_CANCELLED;
+ else
+ scene = ac.scene;
+
+ /* set the range directly */
+ get_nlastrip_extents(&ac, &min, &max, true);
+ scene->r.flag |= SCER_PRV_RANGE;
+ scene->r.psfra = round_fl_to_int(min);
+ scene->r.pefra = round_fl_to_int(max);
+
+ /* set notifier that things have changed */
+ // XXX err... there's nothing for frame ranges yet, but this should do fine too
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene);
+
+ return OPERATOR_FINISHED;
}
void NLA_OT_previewrange_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Auto-Set Preview Range";
- ot->idname = "NLA_OT_previewrange_set";
- ot->description = "Automatically set Preview Range based on range of keyframes";
+ /* identifiers */
+ ot->name = "Auto-Set Preview Range";
+ ot->idname = "NLA_OT_previewrange_set";
+ ot->description = "Automatically set Preview Range based on range of keyframes";
- /* api callbacks */
- ot->exec = nlaedit_previewrange_exec;
- ot->poll = ED_operator_nla_active;
+ /* api callbacks */
+ ot->exec = nlaedit_previewrange_exec;
+ ot->poll = ED_operator_nla_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** View-All Operator ****************** */
@@ -405,170 +409,169 @@ void NLA_OT_previewrange_set(wmOperatorType *ot)
*/
static bool nla_channels_get_selected_extents(bAnimContext *ac, float *min, float *max)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- SpaceNla *snla = (SpaceNla *)ac->sl;
- const float half_height = NLACHANNEL_HEIGHT_HALF(snla);
- /* NOTE: not bool, since we want prioritise individual channels over expanders */
- short found = 0;
- float y;
-
- /* get all items - we need to do it this way */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* loop through all channels, finding the first one that's selected */
- y = (float)NLACHANNEL_FIRST;
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
-
- /* must be selected... */
- if (acf && acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT) &&
- ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT))
- {
- /* update best estimate */
- *min = (float)(y - half_height);
- *max = (float)(y + half_height);
-
- /* is this high enough priority yet? */
- found = acf->channel_role;
-
- /* only stop our search when we've found an actual channel
- * - datablock expanders get less priority so that we don't abort prematurely
- */
- if (found == ACHANNEL_ROLE_CHANNEL) {
- break;
- }
- }
-
- /* adjust y-position for next one */
- y -= NLACHANNEL_STEP(snla);
- }
-
- /* free all temp data */
- ANIM_animdata_freelist(&anim_data);
-
- return (found != 0);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ SpaceNla *snla = (SpaceNla *)ac->sl;
+ const float half_height = NLACHANNEL_HEIGHT_HALF(snla);
+ /* NOTE: not bool, since we want prioritise individual channels over expanders */
+ short found = 0;
+ float y;
+
+ /* get all items - we need to do it this way */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through all channels, finding the first one that's selected */
+ y = (float)NLACHANNEL_FIRST;
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+
+ /* must be selected... */
+ if (acf && acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT) &&
+ ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT)) {
+ /* update best estimate */
+ *min = (float)(y - half_height);
+ *max = (float)(y + half_height);
+
+ /* is this high enough priority yet? */
+ found = acf->channel_role;
+
+ /* only stop our search when we've found an actual channel
+ * - datablock expanders get less priority so that we don't abort prematurely
+ */
+ if (found == ACHANNEL_ROLE_CHANNEL) {
+ break;
+ }
+ }
+
+ /* adjust y-position for next one */
+ y -= NLACHANNEL_STEP(snla);
+ }
+
+ /* free all temp data */
+ ANIM_animdata_freelist(&anim_data);
+
+ return (found != 0);
}
static int nlaedit_viewall(bContext *C, const bool only_sel)
{
- bAnimContext ac;
- View2D *v2d;
- float extra;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
- v2d = &ac.ar->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);
-
- extra = 0.1f * BLI_rctf_size_x(&v2d->cur);
- v2d->cur.xmin -= extra;
- v2d->cur.xmax += extra;
-
- /* set vertical range */
- if (only_sel == false) {
- /* view all -> the summary channel is usually the shows everything,
- * and resides right at the top... */
- v2d->cur.ymax = 0.0f;
- v2d->cur.ymin = (float)-BLI_rcti_size_y(&v2d->mask);
- }
- else {
- /* locate first selected channel (or the active one), and frame those */
- float ymin = v2d->cur.ymin;
- float ymax = v2d->cur.ymax;
-
- if (nla_channels_get_selected_extents(&ac, &ymin, &ymax)) {
- /* recenter the view so that this range is in the middle */
- float ymid = (ymax - ymin) / 2.0f + ymin;
- float x_center;
-
- UI_view2d_center_get(v2d, &x_center, NULL);
- UI_view2d_center_set(v2d, x_center, ymid);
- }
- }
-
- /* do View2D syncing */
- UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
-
- /* just redraw this view */
- ED_area_tag_redraw(CTX_wm_area(C));
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ View2D *v2d;
+ float extra;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ v2d = &ac.ar->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);
+
+ extra = 0.1f * BLI_rctf_size_x(&v2d->cur);
+ v2d->cur.xmin -= extra;
+ v2d->cur.xmax += extra;
+
+ /* set vertical range */
+ if (only_sel == false) {
+ /* view all -> the summary channel is usually the shows everything,
+ * and resides right at the top... */
+ v2d->cur.ymax = 0.0f;
+ v2d->cur.ymin = (float)-BLI_rcti_size_y(&v2d->mask);
+ }
+ else {
+ /* locate first selected channel (or the active one), and frame those */
+ float ymin = v2d->cur.ymin;
+ float ymax = v2d->cur.ymax;
+
+ if (nla_channels_get_selected_extents(&ac, &ymin, &ymax)) {
+ /* recenter the view so that this range is in the middle */
+ float ymid = (ymax - ymin) / 2.0f + ymin;
+ float x_center;
+
+ UI_view2d_center_get(v2d, &x_center, NULL);
+ UI_view2d_center_set(v2d, x_center, ymid);
+ }
+ }
+
+ /* do View2D syncing */
+ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
+
+ /* just redraw this view */
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
}
/* ......... */
static int nlaedit_viewall_exec(bContext *C, wmOperator *UNUSED(op))
{
- /* whole range */
- return nlaedit_viewall(C, false);
+ /* whole range */
+ return nlaedit_viewall(C, false);
}
static int nlaedit_viewsel_exec(bContext *C, wmOperator *UNUSED(op))
{
- /* only selected */
- return nlaedit_viewall(C, true);
+ /* only selected */
+ return nlaedit_viewall(C, true);
}
void NLA_OT_view_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View All";
- ot->idname = "NLA_OT_view_all";
- ot->description = "Reset viewable area to show full strips range";
+ /* identifiers */
+ ot->name = "View All";
+ ot->idname = "NLA_OT_view_all";
+ ot->description = "Reset viewable area to show full strips range";
- /* api callbacks */
- ot->exec = nlaedit_viewall_exec;
- ot->poll = ED_operator_nla_active;
+ /* api callbacks */
+ ot->exec = nlaedit_viewall_exec;
+ ot->poll = ED_operator_nla_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void NLA_OT_view_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Selected";
- ot->idname = "NLA_OT_view_selected";
- ot->description = "Reset viewable area to show selected strips range";
+ /* identifiers */
+ ot->name = "View Selected";
+ ot->idname = "NLA_OT_view_selected";
+ ot->description = "Reset viewable area to show selected strips range";
- /* api callbacks */
- ot->exec = nlaedit_viewsel_exec;
- ot->poll = ED_operator_nla_active;
+ /* api callbacks */
+ ot->exec = nlaedit_viewsel_exec;
+ ot->poll = ED_operator_nla_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* *********************************************** */
static int nlaedit_viewframe_exec(bContext *C, wmOperator *op)
{
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- ANIM_center_frame(C, smooth_viewtx);
- return OPERATOR_FINISHED;
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ ANIM_center_frame(C, smooth_viewtx);
+ return OPERATOR_FINISHED;
}
void NLA_OT_view_frame(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Frame";
- ot->idname = "NLA_OT_view_frame";
- ot->description = "Reset viewable area to show range around current frame";
+ /* identifiers */
+ ot->name = "View Frame";
+ ot->idname = "NLA_OT_view_frame";
+ ot->description = "Reset viewable area to show range around current frame";
- /* api callbacks */
- ot->exec = nlaedit_viewframe_exec;
- ot->poll = ED_operator_nla_active;
+ /* api callbacks */
+ ot->exec = nlaedit_viewframe_exec;
+ ot->poll = ED_operator_nla_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* *********************************************** */
@@ -578,138 +581,144 @@ void NLA_OT_view_frame(wmOperatorType *ot)
/* Add a new Action-Clip strip to the active track
* (or the active block if no space in the track) */
-
/* add the specified action as new strip */
static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- Scene *scene;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- size_t items;
- int filter;
-
- bAction *act;
-
- float cfra;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- scene = ac.scene;
- cfra = (float)CFRA;
-
- /* get action to use */
- act = BLI_findlink(&CTX_data_main(C)->actions, RNA_enum_get(op->ptr, "action"));
-
- if (act == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No valid action to add");
- //printf("Add strip - actname = '%s'\n", actname);
- return OPERATOR_CANCELLED;
- }
- else if (act->idroot == 0) {
- /* hopefully in this case (i.e. library of userless actions),
- * the user knows what they're doing... */
- BKE_reportf(op->reports, RPT_WARNING,
- "Action '%s' does not specify what data-blocks it can be used on "
- "(try setting the 'ID Root Type' setting from the data-blocks editor "
- "for this action to avoid future problems)",
- act->id.name + 2);
- }
-
- /* add tracks to empty but selected animdata blocks so that strips can be added to those directly
- * without having to manually add tracks first
- */
- nlaedit_add_tracks_empty(&ac);
-
- /* get a list of the editable tracks being shown in the NLA
- * - this is limited to active ones for now, but could be expanded to
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT);
- items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- if (items == 0) {
- BKE_report(op->reports, RPT_ERROR,
- "No active track(s) to add strip to, select an existing track or add one before trying again");
- return OPERATOR_CANCELLED;
- }
-
- /* for every active track,
- * try to add strip to free space in track or to the top of the stack if no space */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- AnimData *adt = ale->adt;
- NlaStrip *strip = NULL;
-
- /* sanity check: only apply actions of the right type for this ID
- * NOTE: in the case that this hasn't been set, we've already warned the user about this already
- */
- if ((act->idroot) && (act->idroot != GS(ale->id->name))) {
- BKE_reportf(op->reports, RPT_ERROR,
- "Could not add action '%s' as it cannot be used relative to ID-blocks of type '%s'",
- act->id.name + 2, ale->id->name);
- continue;
- }
-
- /* create a new strip, and offset it to start on the current frame */
- strip = BKE_nlastrip_new(act);
-
- strip->end += (cfra - strip->start);
- strip->start = cfra;
-
- /* firstly try adding strip to our current track, but if that fails, add to a new track */
- if (BKE_nlatrack_add_strip(nlt, strip) == 0) {
- /* trying to add to the current failed (no space),
- * so add a new track to the stack, and add to that...
- */
- nlt = BKE_nlatrack_add(adt, NULL);
- BKE_nlatrack_add_strip(nlt, strip);
- }
-
- /* auto-name it */
- BKE_nlastrip_validate_name(adt, strip);
- }
-
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
-
- /* refresh auto strip properties */
- ED_nla_postop_refresh(&ac);
-
- DEG_relations_tag_update(ac.bmain);
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ Scene *scene;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ size_t items;
+ int filter;
+
+ bAction *act;
+
+ float cfra;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ scene = ac.scene;
+ cfra = (float)CFRA;
+
+ /* get action to use */
+ act = BLI_findlink(&CTX_data_main(C)->actions, RNA_enum_get(op->ptr, "action"));
+
+ if (act == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No valid action to add");
+ //printf("Add strip - actname = '%s'\n", actname);
+ return OPERATOR_CANCELLED;
+ }
+ else if (act->idroot == 0) {
+ /* hopefully in this case (i.e. library of userless actions),
+ * the user knows what they're doing... */
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Action '%s' does not specify what data-blocks it can be used on "
+ "(try setting the 'ID Root Type' setting from the data-blocks editor "
+ "for this action to avoid future problems)",
+ act->id.name + 2);
+ }
+
+ /* add tracks to empty but selected animdata blocks so that strips can be added to those directly
+ * without having to manually add tracks first
+ */
+ nlaedit_add_tracks_empty(&ac);
+
+ /* get a list of the editable tracks being shown in the NLA
+ * - this is limited to active ones for now, but could be expanded to
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT);
+ items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ if (items == 0) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "No active track(s) to add strip to, select an existing track or add one before "
+ "trying again");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* for every active track,
+ * try to add strip to free space in track or to the top of the stack if no space */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ AnimData *adt = ale->adt;
+ NlaStrip *strip = NULL;
+
+ /* sanity check: only apply actions of the right type for this ID
+ * NOTE: in the case that this hasn't been set, we've already warned the user about this already
+ */
+ if ((act->idroot) && (act->idroot != GS(ale->id->name))) {
+ BKE_reportf(
+ op->reports,
+ RPT_ERROR,
+ "Could not add action '%s' as it cannot be used relative to ID-blocks of type '%s'",
+ act->id.name + 2,
+ ale->id->name);
+ continue;
+ }
+
+ /* create a new strip, and offset it to start on the current frame */
+ strip = BKE_nlastrip_new(act);
+
+ strip->end += (cfra - strip->start);
+ strip->start = cfra;
+
+ /* firstly try adding strip to our current track, but if that fails, add to a new track */
+ if (BKE_nlatrack_add_strip(nlt, strip) == 0) {
+ /* trying to add to the current failed (no space),
+ * so add a new track to the stack, and add to that...
+ */
+ nlt = BKE_nlatrack_add(adt, NULL);
+ BKE_nlatrack_add_strip(nlt, strip);
+ }
+
+ /* auto-name it */
+ BKE_nlastrip_validate_name(adt, strip);
+ }
+
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
+
+ /* refresh auto strip properties */
+ ED_nla_postop_refresh(&ac);
+
+ DEG_relations_tag_update(ac.bmain);
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_actionclip_add(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Add Action Strip";
- ot->idname = "NLA_OT_actionclip_add";
- ot->description = "Add an Action-Clip strip (i.e. an NLA Strip referencing an Action) to the active track";
-
- /* api callbacks */
- ot->invoke = WM_enum_search_invoke;
- ot->exec = nlaedit_add_actionclip_exec;
- ot->poll = nlaop_poll_tweakmode_off;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- // TODO: this would be nicer as an ID-pointer...
- prop = RNA_def_enum(ot->srna, "action", DummyRNA_NULL_items, 0, "Action", "");
- RNA_def_enum_funcs(prop, RNA_action_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Add Action Strip";
+ ot->idname = "NLA_OT_actionclip_add";
+ ot->description =
+ "Add an Action-Clip strip (i.e. an NLA Strip referencing an Action) to the active track";
+
+ /* api callbacks */
+ ot->invoke = WM_enum_search_invoke;
+ ot->exec = nlaedit_add_actionclip_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ // TODO: this would be nicer as an ID-pointer...
+ prop = RNA_def_enum(ot->srna, "action", DummyRNA_NULL_items, 0, "Action", "");
+ RNA_def_enum_funcs(prop, RNA_action_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
/* ******************** Add Transition Operator ***************************** */
@@ -717,117 +726,119 @@ void NLA_OT_actionclip_add(wmOperatorType *ot)
static int nlaedit_add_transition_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- bool done = false;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get a list of the editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* for each track, find pairs of strips to add transitions to */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- AnimData *adt = ale->adt;
- NlaStrip *s1, *s2;
-
- /* get initial pair of strips */
- if (ELEM(nlt->strips.first, NULL, nlt->strips.last))
- continue;
- s1 = nlt->strips.first;
- s2 = s1->next;
-
- /* loop over strips */
- for (; s1 && s2; s1 = s2, s2 = s2->next) {
- NlaStrip *strip;
-
- /* check if both are selected */
- if (ELEM(0, (s1->flag & NLASTRIP_FLAG_SELECT), (s2->flag & NLASTRIP_FLAG_SELECT)))
- continue;
- /* check if there's space between the two */
- if (IS_EQF(s1->end, s2->start))
- continue;
- /* make sure neither one is a transition
- * - although this is impossible to create with the standard tools,
- * the user may have altered the settings
- */
- if (ELEM(NLASTRIP_TYPE_TRANSITION, s1->type, s2->type))
- continue;
- /* also make sure neither one is a soundclip */
- if (ELEM(NLASTRIP_TYPE_SOUND, s1->type, s2->type))
- continue;
-
- /* allocate new strip */
- strip = MEM_callocN(sizeof(NlaStrip), "NlaStrip");
- BLI_insertlinkafter(&nlt->strips, s1, strip);
-
- /* set the type */
- strip->type = NLASTRIP_TYPE_TRANSITION;
-
- /* generic settings
- * - selected flag to highlight this to the user
- * - auto-blends to ensure that blend in/out values are automatically
- * determined by overlaps of strips
- */
- strip->flag = NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_AUTO_BLENDS;
-
- /* range is simply defined as the endpoints of the adjacent strips */
- strip->start = s1->end;
- strip->end = s2->start;
-
- /* scale and repeat aren't of any use, but shouldn't ever be 0 */
- strip->scale = 1.0f;
- strip->repeat = 1.0f;
-
- /* auto-name it */
- BKE_nlastrip_validate_name(adt, strip);
-
- /* make note of this */
- done = true;
- }
- }
-
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
-
- /* was anything added? */
- if (done) {
- /* refresh auto strip properties */
- ED_nla_postop_refresh(&ac);
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Needs at least a pair of adjacent selected strips with a gap between them");
- return OPERATOR_CANCELLED;
- }
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ bool done = false;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* for each track, find pairs of strips to add transitions to */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ AnimData *adt = ale->adt;
+ NlaStrip *s1, *s2;
+
+ /* get initial pair of strips */
+ if (ELEM(nlt->strips.first, NULL, nlt->strips.last))
+ continue;
+ s1 = nlt->strips.first;
+ s2 = s1->next;
+
+ /* loop over strips */
+ for (; s1 && s2; s1 = s2, s2 = s2->next) {
+ NlaStrip *strip;
+
+ /* check if both are selected */
+ if (ELEM(0, (s1->flag & NLASTRIP_FLAG_SELECT), (s2->flag & NLASTRIP_FLAG_SELECT)))
+ continue;
+ /* check if there's space between the two */
+ if (IS_EQF(s1->end, s2->start))
+ continue;
+ /* make sure neither one is a transition
+ * - although this is impossible to create with the standard tools,
+ * the user may have altered the settings
+ */
+ if (ELEM(NLASTRIP_TYPE_TRANSITION, s1->type, s2->type))
+ continue;
+ /* also make sure neither one is a soundclip */
+ if (ELEM(NLASTRIP_TYPE_SOUND, s1->type, s2->type))
+ continue;
+
+ /* allocate new strip */
+ strip = MEM_callocN(sizeof(NlaStrip), "NlaStrip");
+ BLI_insertlinkafter(&nlt->strips, s1, strip);
+
+ /* set the type */
+ strip->type = NLASTRIP_TYPE_TRANSITION;
+
+ /* generic settings
+ * - selected flag to highlight this to the user
+ * - auto-blends to ensure that blend in/out values are automatically
+ * determined by overlaps of strips
+ */
+ strip->flag = NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_AUTO_BLENDS;
+
+ /* range is simply defined as the endpoints of the adjacent strips */
+ strip->start = s1->end;
+ strip->end = s2->start;
+
+ /* scale and repeat aren't of any use, but shouldn't ever be 0 */
+ strip->scale = 1.0f;
+ strip->repeat = 1.0f;
+
+ /* auto-name it */
+ BKE_nlastrip_validate_name(adt, strip);
+
+ /* make note of this */
+ done = true;
+ }
+ }
+
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
+
+ /* was anything added? */
+ if (done) {
+ /* refresh auto strip properties */
+ ED_nla_postop_refresh(&ac);
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Needs at least a pair of adjacent selected strips with a gap between them");
+ return OPERATOR_CANCELLED;
+ }
}
void NLA_OT_transition_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Transition";
- ot->idname = "NLA_OT_transition_add";
- ot->description = "Add a transition strip between two adjacent selected strips";
+ /* identifiers */
+ ot->name = "Add Transition";
+ ot->idname = "NLA_OT_transition_add";
+ ot->description = "Add a transition strip between two adjacent selected strips";
- /* api callbacks */
- ot->exec = nlaedit_add_transition_exec;
- ot->poll = nlaop_poll_tweakmode_off;
+ /* api callbacks */
+ ot->exec = nlaedit_add_transition_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Add Sound Clip Operator ***************************** */
@@ -835,84 +846,85 @@ void NLA_OT_transition_add(wmOperatorType *ot)
static int nlaedit_add_sound_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
+ bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- Scene *scene;
- int cfra;
+ Scene *scene;
+ int cfra;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- scene = ac.scene;
- cfra = CFRA;
+ scene = ac.scene;
+ cfra = CFRA;
- /* get a list of the editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* get a list of the editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL |
+ ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* for each track, add sound clips if it belongs to a speaker */
- // TODO: what happens if there aren't any tracks... well that's a more general problem for later
- for (ale = anim_data.first; ale; ale = ale->next) {
- Object *ob = (Object *)ale->id; /* may not be object until we actually check! */
+ /* for each track, add sound clips if it belongs to a speaker */
+ // TODO: what happens if there aren't any tracks... well that's a more general problem for later
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ Object *ob = (Object *)ale->id; /* may not be object until we actually check! */
- AnimData *adt = ale->adt;
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
+ AnimData *adt = ale->adt;
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
- /* does this belong to speaker - assumed to live on Object level only */
- if ((GS(ale->id->name) != ID_OB) || (ob->type != OB_SPEAKER))
- continue;
+ /* does this belong to speaker - assumed to live on Object level only */
+ if ((GS(ale->id->name) != ID_OB) || (ob->type != OB_SPEAKER))
+ continue;
- /* create a new strip, and offset it to start on the current frame */
- strip = BKE_nla_add_soundstrip(ac.scene, ob->data);
+ /* create a new strip, and offset it to start on the current frame */
+ strip = BKE_nla_add_soundstrip(ac.scene, ob->data);
- strip->start += cfra;
- strip->end += cfra;
+ strip->start += cfra;
+ strip->end += cfra;
- /* firstly try adding strip to our current track, but if that fails, add to a new track */
- if (BKE_nlatrack_add_strip(nlt, strip) == 0) {
- /* trying to add to the current failed (no space),
- * so add a new track to the stack, and add to that...
- */
- nlt = BKE_nlatrack_add(adt, NULL);
- BKE_nlatrack_add_strip(nlt, strip);
- }
+ /* firstly try adding strip to our current track, but if that fails, add to a new track */
+ if (BKE_nlatrack_add_strip(nlt, strip) == 0) {
+ /* trying to add to the current failed (no space),
+ * so add a new track to the stack, and add to that...
+ */
+ nlt = BKE_nlatrack_add(adt, NULL);
+ BKE_nlatrack_add_strip(nlt, strip);
+ }
- /* auto-name it */
- BKE_nlastrip_validate_name(adt, strip);
- }
+ /* auto-name it */
+ BKE_nlastrip_validate_name(adt, strip);
+ }
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
- /* refresh auto strip properties */
- ED_nla_postop_refresh(&ac);
+ /* refresh auto strip properties */
+ ED_nla_postop_refresh(&ac);
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
- /* done */
- return OPERATOR_FINISHED;
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_soundclip_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Sound Clip";
- ot->idname = "NLA_OT_soundclip_add";
- ot->description = "Add a strip for controlling when speaker plays its sound clip";
+ /* identifiers */
+ ot->name = "Add Sound Clip";
+ ot->idname = "NLA_OT_soundclip_add";
+ ot->description = "Add a strip for controlling when speaker plays its sound clip";
- /* api callbacks */
- ot->exec = nlaedit_add_sound_exec;
- ot->poll = nlaop_poll_tweakmode_off;
+ /* api callbacks */
+ ot->exec = nlaedit_add_sound_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Add Meta-Strip Operator ***************************** */
@@ -921,63 +933,63 @@ void NLA_OT_soundclip_add(wmOperatorType *ot)
/* add the specified action as new strip */
static int nlaedit_add_meta_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
+ bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* get a list of the editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* get a list of the editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* for each track, find pairs of strips to add transitions to */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- AnimData *adt = ale->adt;
- NlaStrip *strip;
+ /* for each track, find pairs of strips to add transitions to */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ AnimData *adt = ale->adt;
+ NlaStrip *strip;
- /* create meta-strips from the continuous chains of selected strips */
- BKE_nlastrips_make_metas(&nlt->strips, 0);
+ /* create meta-strips from the continuous chains of selected strips */
+ BKE_nlastrips_make_metas(&nlt->strips, 0);
- /* name the metas */
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- /* auto-name this strip if selected (that means it is a meta) */
- if (strip->flag & NLASTRIP_FLAG_SELECT)
- BKE_nlastrip_validate_name(adt, strip);
- }
+ /* name the metas */
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ /* auto-name this strip if selected (that means it is a meta) */
+ if (strip->flag & NLASTRIP_FLAG_SELECT)
+ BKE_nlastrip_validate_name(adt, strip);
+ }
- ale->update |= ANIM_UPDATE_DEPS;
- }
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
- /* free temp data */
- ANIM_animdata_update(&ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ /* free temp data */
+ ANIM_animdata_update(&ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
- /* done */
- return OPERATOR_FINISHED;
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_meta_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Meta-Strips";
- ot->idname = "NLA_OT_meta_add";
- ot->description = "Add new meta-strips incorporating the selected strips";
+ /* identifiers */
+ ot->name = "Add Meta-Strips";
+ ot->idname = "NLA_OT_meta_add";
+ ot->description = "Add new meta-strips incorporating the selected strips";
- /* api callbacks */
- ot->exec = nlaedit_add_meta_exec;
- ot->poll = nlaop_poll_tweakmode_off;
+ /* api callbacks */
+ ot->exec = nlaedit_add_meta_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Remove Meta-Strip Operator ***************************** */
@@ -985,54 +997,54 @@ void NLA_OT_meta_add(wmOperatorType *ot)
static int nlaedit_remove_meta_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
+ bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* get a list of the editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* get a list of the editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* for each track, find pairs of strips to add transitions to */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
+ /* for each track, find pairs of strips to add transitions to */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
- /* clear all selected meta-strips, regardless of whether they are temporary or not */
- BKE_nlastrips_clear_metas(&nlt->strips, 1, 0);
+ /* clear all selected meta-strips, regardless of whether they are temporary or not */
+ BKE_nlastrips_clear_metas(&nlt->strips, 1, 0);
- ale->update |= ANIM_UPDATE_DEPS;
- }
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
- /* free temp data */
- ANIM_animdata_update(&ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
+ /* free temp data */
+ ANIM_animdata_update(&ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
- /* done */
- return OPERATOR_FINISHED;
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_meta_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Meta-Strips";
- ot->idname = "NLA_OT_meta_remove";
- ot->description = "Separate out the strips held by the selected meta-strips";
+ /* identifiers */
+ ot->name = "Remove Meta-Strips";
+ ot->idname = "NLA_OT_meta_remove";
+ ot->description = "Separate out the strips held by the selected meta-strips";
- /* api callbacks */
- ot->exec = nlaedit_remove_meta_exec;
- ot->poll = nlaop_poll_tweakmode_off;
+ /* api callbacks */
+ ot->exec = nlaedit_remove_meta_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Duplicate Strips Operator ************************** */
@@ -1042,113 +1054,118 @@ void NLA_OT_meta_remove(wmOperatorType *ot)
static int nlaedit_duplicate_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- bool linked = RNA_boolean_get(op->ptr, "linked");
- bool done = false;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get a list of editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* duplicate strips in tracks starting from the last one so that we're
- * less likely to duplicate strips we just duplicated...
- */
- for (ale = anim_data.last; ale; ale = ale->prev) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- AnimData *adt = ale->adt;
- NlaStrip *strip, *nstrip, *next;
- NlaTrack *track;
-
- for (strip = nlt->strips.first; strip; strip = next) {
- next = strip->next;
-
- /* if selected, split the strip at its midpoint */
- if (strip->flag & NLASTRIP_FLAG_SELECT) {
- /* make a copy (assume that this is possible) */
- nstrip = BKE_nlastrip_copy(ac.bmain, strip, linked, 0);
-
- /* in case there's no space in the track above,
- * or we haven't got a reference to it yet, try adding */
- if (BKE_nlatrack_add_strip(nlt->next, nstrip) == 0) {
- /* need to add a new track above the one above the current one
- * - if the current one is the last one, nlt->next will be NULL, which defaults to adding
- * at the top of the stack anyway...
- */
- track = BKE_nlatrack_add(adt, nlt->next);
- BKE_nlatrack_add_strip(track, nstrip);
- }
-
- /* deselect the original and the active flag */
- strip->flag &= ~(NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_ACTIVE);
-
- /* auto-name newly created strip */
- BKE_nlastrip_validate_name(adt, nstrip);
-
- done = true;
- }
- }
- }
-
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
-
- if (done) {
- /* refresh auto strip properties */
- ED_nla_postop_refresh(&ac);
-
- if (!linked) {
- DEG_relations_tag_update(ac.bmain);
- }
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
- }
- else
- return OPERATOR_CANCELLED;
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ bool linked = RNA_boolean_get(op->ptr, "linked");
+ bool done = false;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* duplicate strips in tracks starting from the last one so that we're
+ * less likely to duplicate strips we just duplicated...
+ */
+ for (ale = anim_data.last; ale; ale = ale->prev) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ AnimData *adt = ale->adt;
+ NlaStrip *strip, *nstrip, *next;
+ NlaTrack *track;
+
+ for (strip = nlt->strips.first; strip; strip = next) {
+ next = strip->next;
+
+ /* if selected, split the strip at its midpoint */
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ /* make a copy (assume that this is possible) */
+ nstrip = BKE_nlastrip_copy(ac.bmain, strip, linked, 0);
+
+ /* in case there's no space in the track above,
+ * or we haven't got a reference to it yet, try adding */
+ if (BKE_nlatrack_add_strip(nlt->next, nstrip) == 0) {
+ /* need to add a new track above the one above the current one
+ * - if the current one is the last one, nlt->next will be NULL, which defaults to adding
+ * at the top of the stack anyway...
+ */
+ track = BKE_nlatrack_add(adt, nlt->next);
+ BKE_nlatrack_add_strip(track, nstrip);
+ }
+
+ /* deselect the original and the active flag */
+ strip->flag &= ~(NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_ACTIVE);
+
+ /* auto-name newly created strip */
+ BKE_nlastrip_validate_name(adt, nstrip);
+
+ done = true;
+ }
+ }
+ }
+
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
+
+ if (done) {
+ /* refresh auto strip properties */
+ ED_nla_postop_refresh(&ac);
+
+ if (!linked) {
+ DEG_relations_tag_update(ac.bmain);
+ }
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+ }
+ else
+ return OPERATOR_CANCELLED;
}
static int nlaedit_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- nlaedit_duplicate_exec(C, op);
+ nlaedit_duplicate_exec(C, op);
- RNA_enum_set(op->ptr, "mode", TFM_TRANSLATION);
- WM_operator_name_call(C, "TRANSFORM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+ RNA_enum_set(op->ptr, "mode", TFM_TRANSLATION);
+ WM_operator_name_call(C, "TRANSFORM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NLA_OT_duplicate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Duplicate Strips";
- ot->idname = "NLA_OT_duplicate";
- ot->description = "Duplicate selected NLA-Strips, adding the new strips in new tracks above the originals";
-
- /* api callbacks */
- ot->invoke = nlaedit_duplicate_invoke;
- ot->exec = nlaedit_duplicate_exec;
- ot->poll = nlaop_poll_tweakmode_off;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* own properties */
- ot->prop = RNA_def_boolean(ot->srna, "linked", false, "Linked", "When duplicating strips, assign new copies of the actions they use");
-
- /* to give to transform */
- RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
+ /* identifiers */
+ ot->name = "Duplicate Strips";
+ ot->idname = "NLA_OT_duplicate";
+ ot->description =
+ "Duplicate selected NLA-Strips, adding the new strips in new tracks above the originals";
+
+ /* api callbacks */
+ ot->invoke = nlaedit_duplicate_invoke;
+ ot->exec = nlaedit_duplicate_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* own properties */
+ ot->prop = RNA_def_boolean(ot->srna,
+ "linked",
+ false,
+ "Linked",
+ "When duplicating strips, assign new copies of the actions they use");
+
+ /* to give to transform */
+ RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
}
/* ******************** Delete Strips Operator ***************************** */
@@ -1156,72 +1173,72 @@ void NLA_OT_duplicate(wmOperatorType *ot)
static int nlaedit_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
+ bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* get a list of the editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* get a list of the editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* for each NLA-Track, delete all selected strips */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip, *nstrip;
+ /* for each NLA-Track, delete all selected strips */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip, *nstrip;
- for (strip = nlt->strips.first; strip; strip = nstrip) {
- nstrip = strip->next;
+ for (strip = nlt->strips.first; strip; strip = nstrip) {
+ nstrip = strip->next;
- /* if selected, delete */
- if (strip->flag & NLASTRIP_FLAG_SELECT) {
- /* if a strip either side of this was a transition, delete those too */
- if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION))
- BKE_nlastrip_free(&nlt->strips, strip->prev, true);
- if ((nstrip) && (nstrip->type == NLASTRIP_TYPE_TRANSITION)) {
- nstrip = nstrip->next;
- BKE_nlastrip_free(&nlt->strips, strip->next, true);
- }
+ /* if selected, delete */
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ /* if a strip either side of this was a transition, delete those too */
+ if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION))
+ BKE_nlastrip_free(&nlt->strips, strip->prev, true);
+ if ((nstrip) && (nstrip->type == NLASTRIP_TYPE_TRANSITION)) {
+ nstrip = nstrip->next;
+ BKE_nlastrip_free(&nlt->strips, strip->next, true);
+ }
- /* finally, delete this strip */
- BKE_nlastrip_free(&nlt->strips, strip, true);
- }
- }
- }
+ /* finally, delete this strip */
+ BKE_nlastrip_free(&nlt->strips, strip, true);
+ }
+ }
+ }
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
- /* refresh auto strip properties */
- ED_nla_postop_refresh(&ac);
+ /* refresh auto strip properties */
+ ED_nla_postop_refresh(&ac);
- DEG_relations_tag_update(ac.bmain);
+ DEG_relations_tag_update(ac.bmain);
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
- /* done */
- return OPERATOR_FINISHED;
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Strips";
- ot->idname = "NLA_OT_delete";
- ot->description = "Delete selected strips";
+ /* identifiers */
+ ot->name = "Delete Strips";
+ ot->idname = "NLA_OT_delete";
+ ot->description = "Delete selected strips";
- /* api callbacks */
- ot->exec = nlaedit_delete_exec;
- ot->poll = nlaop_poll_tweakmode_off;
+ /* api callbacks */
+ ot->exec = nlaedit_delete_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Split Strips Operator ***************************** */
@@ -1231,142 +1248,143 @@ void NLA_OT_delete(wmOperatorType *ot)
// - variable-length splits?
/* split a given Action-Clip strip */
-static void nlaedit_split_strip_actclip(Main *bmain, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, float cfra)
+static void nlaedit_split_strip_actclip(
+ Main *bmain, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, float cfra)
{
- NlaStrip *nstrip;
- float splitframe, splitaframe;
-
- /* calculate the frames to do the splitting at
- * - use current frame if within extents of strip
- */
- if ((cfra > strip->start) && (cfra < strip->end)) {
- /* use the current frame */
- splitframe = cfra;
- splitaframe = nlastrip_get_frame(strip, cfra, NLATIME_CONVERT_UNMAP);
- }
- else {
- /* split in the middle */
- float len;
-
- /* strip extents */
- len = strip->end - strip->start;
- if (IS_EQF(len, 0.0f))
- return;
- else
- splitframe = strip->start + (len / 2.0f);
-
- /* action range */
- len = strip->actend - strip->actstart;
- if (IS_EQF(len, 0.0f))
- splitaframe = strip->actend;
- else
- splitaframe = strip->actstart + (len / 2.0f);
- }
-
- /* make a copy (assume that this is possible) and append
- * it immediately after the current strip
- */
- nstrip = BKE_nlastrip_copy(bmain, strip, true, 0);
- BLI_insertlinkafter(&nlt->strips, strip, nstrip);
-
- /* Set the endpoint of the first strip and the start of the new strip
- * to the split-frame values calculated above.
- */
- strip->end = splitframe;
- nstrip->start = splitframe;
-
- if ((splitaframe > strip->actstart) && (splitaframe < strip->actend)) {
- /* only do this if we're splitting down the middle... */
- strip->actend = splitaframe;
- nstrip->actstart = splitaframe;
- }
-
- /* clear the active flag from the copy */
- nstrip->flag &= ~NLASTRIP_FLAG_ACTIVE;
-
- /* auto-name the new strip */
- BKE_nlastrip_validate_name(adt, nstrip);
+ NlaStrip *nstrip;
+ float splitframe, splitaframe;
+
+ /* calculate the frames to do the splitting at
+ * - use current frame if within extents of strip
+ */
+ if ((cfra > strip->start) && (cfra < strip->end)) {
+ /* use the current frame */
+ splitframe = cfra;
+ splitaframe = nlastrip_get_frame(strip, cfra, NLATIME_CONVERT_UNMAP);
+ }
+ else {
+ /* split in the middle */
+ float len;
+
+ /* strip extents */
+ len = strip->end - strip->start;
+ if (IS_EQF(len, 0.0f))
+ return;
+ else
+ splitframe = strip->start + (len / 2.0f);
+
+ /* action range */
+ len = strip->actend - strip->actstart;
+ if (IS_EQF(len, 0.0f))
+ splitaframe = strip->actend;
+ else
+ splitaframe = strip->actstart + (len / 2.0f);
+ }
+
+ /* make a copy (assume that this is possible) and append
+ * it immediately after the current strip
+ */
+ nstrip = BKE_nlastrip_copy(bmain, strip, true, 0);
+ BLI_insertlinkafter(&nlt->strips, strip, nstrip);
+
+ /* Set the endpoint of the first strip and the start of the new strip
+ * to the split-frame values calculated above.
+ */
+ strip->end = splitframe;
+ nstrip->start = splitframe;
+
+ if ((splitaframe > strip->actstart) && (splitaframe < strip->actend)) {
+ /* only do this if we're splitting down the middle... */
+ strip->actend = splitaframe;
+ nstrip->actstart = splitaframe;
+ }
+
+ /* clear the active flag from the copy */
+ nstrip->flag &= ~NLASTRIP_FLAG_ACTIVE;
+
+ /* auto-name the new strip */
+ BKE_nlastrip_validate_name(adt, nstrip);
}
/* split a given Meta strip */
static void nlaedit_split_strip_meta(NlaTrack *nlt, NlaStrip *strip)
{
- /* simply ungroup it for now... */
- BKE_nlastrips_clear_metastrip(&nlt->strips, strip);
+ /* simply ungroup it for now... */
+ BKE_nlastrips_clear_metastrip(&nlt->strips, strip);
}
/* ----- */
static int nlaedit_split_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get a list of editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* for each NLA-Track, split all selected strips into two strips */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- AnimData *adt = ale->adt;
- NlaStrip *strip, *next;
-
- for (strip = nlt->strips.first; strip; strip = next) {
- next = strip->next;
-
- /* if selected, split the strip at its midpoint */
- if (strip->flag & NLASTRIP_FLAG_SELECT) {
- /* splitting method depends on the type of strip */
- switch (strip->type) {
- case NLASTRIP_TYPE_CLIP: /* action-clip */
- nlaedit_split_strip_actclip(ac.bmain, adt, nlt, strip, (float)ac.scene->r.cfra);
- break;
-
- case NLASTRIP_TYPE_META: /* meta-strips need special handling */
- nlaedit_split_strip_meta(nlt, strip);
- break;
-
- default: /* for things like Transitions, do not split! */
- break;
- }
- }
- }
- }
-
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
-
- /* refresh auto strip properties */
- ED_nla_postop_refresh(&ac);
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* for each NLA-Track, split all selected strips into two strips */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ AnimData *adt = ale->adt;
+ NlaStrip *strip, *next;
+
+ for (strip = nlt->strips.first; strip; strip = next) {
+ next = strip->next;
+
+ /* if selected, split the strip at its midpoint */
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ /* splitting method depends on the type of strip */
+ switch (strip->type) {
+ case NLASTRIP_TYPE_CLIP: /* action-clip */
+ nlaedit_split_strip_actclip(ac.bmain, adt, nlt, strip, (float)ac.scene->r.cfra);
+ break;
+
+ case NLASTRIP_TYPE_META: /* meta-strips need special handling */
+ nlaedit_split_strip_meta(nlt, strip);
+ break;
+
+ default: /* for things like Transitions, do not split! */
+ break;
+ }
+ }
+ }
+ }
+
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
+
+ /* refresh auto strip properties */
+ ED_nla_postop_refresh(&ac);
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_split(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Split Strips";
- ot->idname = "NLA_OT_split";
- ot->description = "Split selected strips at their midpoints";
+ /* identifiers */
+ ot->name = "Split Strips";
+ ot->idname = "NLA_OT_split";
+ ot->description = "Split selected strips at their midpoints";
- /* api callbacks */
- ot->exec = nlaedit_split_exec;
- ot->poll = nlaop_poll_tweakmode_off;
+ /* api callbacks */
+ ot->exec = nlaedit_split_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* *********************************************** */
@@ -1377,62 +1395,62 @@ void NLA_OT_split(wmOperatorType *ot)
static int nlaedit_toggle_mute_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get a list of the editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* go over all selected strips */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
-
- /* for every selected strip, toggle muting */
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- if (strip->flag & NLASTRIP_FLAG_SELECT) {
- /* just flip the mute flag for now */
- // TODO: have a pre-pass to check if mute all or unmute all?
- strip->flag ^= NLASTRIP_FLAG_MUTED;
-
- /* tag AnimData to get recalculated */
- ale->update |= ANIM_UPDATE_DEPS;
- }
- }
- }
-
- /* cleanup */
- ANIM_animdata_update(&ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* go over all selected strips */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ /* for every selected strip, toggle muting */
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ /* just flip the mute flag for now */
+ // TODO: have a pre-pass to check if mute all or unmute all?
+ strip->flag ^= NLASTRIP_FLAG_MUTED;
+
+ /* tag AnimData to get recalculated */
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ }
+ }
+
+ /* cleanup */
+ ANIM_animdata_update(&ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_mute_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Muting";
- ot->idname = "NLA_OT_mute_toggle";
- ot->description = "Mute or un-mute selected strips";
+ /* identifiers */
+ ot->name = "Toggle Muting";
+ ot->idname = "NLA_OT_mute_toggle";
+ ot->description = "Mute or un-mute selected strips";
- /* api callbacks */
- ot->exec = nlaedit_toggle_mute_exec;
- ot->poll = nlaop_poll_tweakmode_off;
+ /* api callbacks */
+ ot->exec = nlaedit_toggle_mute_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Swap Strips Operator ************************** */
@@ -1440,160 +1458,167 @@ void NLA_OT_mute_toggle(wmOperatorType *ot)
static int nlaedit_swap_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get a list of the editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* consider each track in turn */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
-
- NlaStrip *strip, *stripN = NULL;
- NlaStrip *sa = NULL, *sb = NULL;
-
- /* make temporary metastrips so that entire islands of selections can be moved around */
- BKE_nlastrips_make_metas(&nlt->strips, 1);
-
- /* special case: if there is only 1 island (i.e. temp meta BUT NOT unselected/normal/normal-meta strips) left after this,
- * and this island has two strips inside it, then we should be able to just swap these still...
- */
- if (BLI_listbase_is_empty(&nlt->strips) == false) {
- NlaStrip *mstrip = (NlaStrip *)nlt->strips.first;
-
- if ((mstrip->flag & NLASTRIP_FLAG_TEMP_META) &&
- (BLI_listbase_count_at_most(&mstrip->strips, 3) == 2))
- {
- /* remove this temp meta, so that we can see the strips inside */
- BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
- }
- }
-
- /* get two selected strips only (these will be metas due to prev step) to operate on
- * - only allow swapping 2, as with more the context becomes unclear
- */
- for (strip = nlt->strips.first; strip; strip = stripN) {
- stripN = strip->next;
-
- if (strip->flag & NLASTRIP_FLAG_SELECT) {
- /* first or second strip? */
- if (sa == NULL) {
- /* store as first */
- sa = strip;
- }
- else if (sb == NULL) {
- /* store as second */
- sb = strip;
- }
- else {
- /* too many selected */
- break;
- }
- }
- }
-
- if (strip) {
- /* too many selected warning */
- BKE_reportf(op->reports, RPT_WARNING,
- "Too many clusters of strips selected in NLA Track (%s): needs exactly 2 to be selected",
- nlt->name);
- }
- else if (sa == NULL) {
- /* no warning as this is just a common case,
- * and it may get annoying when doing multiple tracks */
- }
- else if (sb == NULL) {
- /* too few selected warning */
- BKE_reportf(op->reports, RPT_WARNING,
- "Too few clusters of strips selected in NLA Track (%s): needs exactly 2 to be selected",
- nlt->name);
- }
- else {
- float nsa[2], nsb[2];
-
- /* 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, sb);
-
- /* calculate new extents for strips */
- /* a --> b */
- nsa[0] = sb->start;
- nsa[1] = sb->start + (sa->end - sa->start);
- /* b --> a */
- nsb[0] = sa->start;
- nsb[1] = sa->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);
-
- sb->start = nsb[0];
- sb->end = nsb[1];
- BKE_nlameta_flush_transforms(sb);
- }
- else {
- /* not enough room to swap, so show message */
- if ((sa->flag & NLASTRIP_FLAG_TEMP_META) || (sb->flag & NLASTRIP_FLAG_TEMP_META)) {
- BKE_report(op->reports, RPT_WARNING,
- "Cannot swap selected strips as they will not be able to fit in their new places");
- }
- else {
- BKE_reportf(op->reports, RPT_WARNING,
- "Cannot swap '%s' and '%s' as one or both will not be able to fit in their new places",
- sa->name, sb->name);
- }
- }
-
- /* add strips back to track now */
- BKE_nlatrack_add_strip(nlt, sa);
- BKE_nlatrack_add_strip(nlt, sb);
- }
-
- /* clear (temp) metastrips */
- BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
- }
-
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
-
- /* refresh auto strip properties */
- ED_nla_postop_refresh(&ac);
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* consider each track in turn */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+
+ NlaStrip *strip, *stripN = NULL;
+ NlaStrip *sa = NULL, *sb = NULL;
+
+ /* make temporary metastrips so that entire islands of selections can be moved around */
+ BKE_nlastrips_make_metas(&nlt->strips, 1);
+
+ /* special case: if there is only 1 island (i.e. temp meta BUT NOT unselected/normal/normal-meta strips) left after this,
+ * and this island has two strips inside it, then we should be able to just swap these still...
+ */
+ if (BLI_listbase_is_empty(&nlt->strips) == false) {
+ NlaStrip *mstrip = (NlaStrip *)nlt->strips.first;
+
+ if ((mstrip->flag & NLASTRIP_FLAG_TEMP_META) &&
+ (BLI_listbase_count_at_most(&mstrip->strips, 3) == 2)) {
+ /* remove this temp meta, so that we can see the strips inside */
+ BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
+ }
+ }
+
+ /* get two selected strips only (these will be metas due to prev step) to operate on
+ * - only allow swapping 2, as with more the context becomes unclear
+ */
+ for (strip = nlt->strips.first; strip; strip = stripN) {
+ stripN = strip->next;
+
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ /* first or second strip? */
+ if (sa == NULL) {
+ /* store as first */
+ sa = strip;
+ }
+ else if (sb == NULL) {
+ /* store as second */
+ sb = strip;
+ }
+ else {
+ /* too many selected */
+ break;
+ }
+ }
+ }
+
+ if (strip) {
+ /* too many selected warning */
+ BKE_reportf(
+ op->reports,
+ RPT_WARNING,
+ "Too many clusters of strips selected in NLA Track (%s): needs exactly 2 to be selected",
+ nlt->name);
+ }
+ else if (sa == NULL) {
+ /* no warning as this is just a common case,
+ * and it may get annoying when doing multiple tracks */
+ }
+ else if (sb == NULL) {
+ /* too few selected warning */
+ BKE_reportf(
+ op->reports,
+ RPT_WARNING,
+ "Too few clusters of strips selected in NLA Track (%s): needs exactly 2 to be selected",
+ nlt->name);
+ }
+ else {
+ float nsa[2], nsb[2];
+
+ /* 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, sb);
+
+ /* calculate new extents for strips */
+ /* a --> b */
+ nsa[0] = sb->start;
+ nsa[1] = sb->start + (sa->end - sa->start);
+ /* b --> a */
+ nsb[0] = sa->start;
+ nsb[1] = sa->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);
+
+ sb->start = nsb[0];
+ sb->end = nsb[1];
+ BKE_nlameta_flush_transforms(sb);
+ }
+ else {
+ /* not enough room to swap, so show message */
+ if ((sa->flag & NLASTRIP_FLAG_TEMP_META) || (sb->flag & NLASTRIP_FLAG_TEMP_META)) {
+ BKE_report(
+ op->reports,
+ RPT_WARNING,
+ "Cannot swap selected strips as they will not be able to fit in their new places");
+ }
+ else {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Cannot swap '%s' and '%s' as one or both will not be able to fit in their "
+ "new places",
+ sa->name,
+ sb->name);
+ }
+ }
+
+ /* add strips back to track now */
+ BKE_nlatrack_add_strip(nlt, sa);
+ BKE_nlatrack_add_strip(nlt, sb);
+ }
+
+ /* clear (temp) metastrips */
+ BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
+ }
+
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
+
+ /* refresh auto strip properties */
+ ED_nla_postop_refresh(&ac);
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_swap(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Swap Strips";
- ot->idname = "NLA_OT_swap";
- ot->description = "Swap order of selected strips within tracks";
+ /* identifiers */
+ ot->name = "Swap Strips";
+ ot->idname = "NLA_OT_swap";
+ ot->description = "Swap order of selected strips within tracks";
- /* api callbacks */
- ot->exec = nlaedit_swap_exec;
- ot->poll = nlaop_poll_tweakmode_off;
+ /* api callbacks */
+ ot->exec = nlaedit_swap_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Move Strips Up Operator ************************** */
@@ -1601,74 +1626,74 @@ void NLA_OT_swap(wmOperatorType *ot)
static int nlaedit_move_up_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get a list of the editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* since we're potentially moving strips from lower tracks to higher tracks, we should
- * loop over the tracks in reverse order to avoid moving earlier strips up multiple tracks
- */
- for (ale = anim_data.last; ale; ale = ale->prev) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaTrack *nltn = nlt->next;
- NlaStrip *strip, *stripn;
-
- /* if this track has no tracks after it, skip for now... */
- if (nltn == NULL)
- continue;
-
- /* for every selected strip, try to move */
- for (strip = nlt->strips.first; strip; strip = stripn) {
- stripn = strip->next;
-
- if (strip->flag & NLASTRIP_FLAG_SELECT) {
- /* check if the track above has room for this strip */
- if (BKE_nlatrack_has_space(nltn, strip->start, strip->end)) {
- /* remove from its current track, and add to the one above
- * (it 'should' work, so no need to worry) */
- BLI_remlink(&nlt->strips, strip);
- BKE_nlatrack_add_strip(nltn, strip);
- }
- }
- }
- }
-
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
-
- /* refresh auto strip properties */
- ED_nla_postop_refresh(&ac);
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* since we're potentially moving strips from lower tracks to higher tracks, we should
+ * loop over the tracks in reverse order to avoid moving earlier strips up multiple tracks
+ */
+ for (ale = anim_data.last; ale; ale = ale->prev) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaTrack *nltn = nlt->next;
+ NlaStrip *strip, *stripn;
+
+ /* if this track has no tracks after it, skip for now... */
+ if (nltn == NULL)
+ continue;
+
+ /* for every selected strip, try to move */
+ for (strip = nlt->strips.first; strip; strip = stripn) {
+ stripn = strip->next;
+
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ /* check if the track above has room for this strip */
+ if (BKE_nlatrack_has_space(nltn, strip->start, strip->end)) {
+ /* remove from its current track, and add to the one above
+ * (it 'should' work, so no need to worry) */
+ BLI_remlink(&nlt->strips, strip);
+ BKE_nlatrack_add_strip(nltn, strip);
+ }
+ }
+ }
+ }
+
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
+
+ /* refresh auto strip properties */
+ ED_nla_postop_refresh(&ac);
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_move_up(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move Strips Up";
- ot->idname = "NLA_OT_move_up";
- ot->description = "Move selected strips up a track if there's room";
+ /* identifiers */
+ ot->name = "Move Strips Up";
+ ot->idname = "NLA_OT_move_up";
+ ot->description = "Move selected strips up a track if there's room";
- /* api callbacks */
- ot->exec = nlaedit_move_up_exec;
- ot->poll = nlaop_poll_tweakmode_off;
+ /* api callbacks */
+ ot->exec = nlaedit_move_up_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Move Strips Down Operator ************************** */
@@ -1676,74 +1701,74 @@ void NLA_OT_move_up(wmOperatorType *ot)
static int nlaedit_move_down_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get a list of the editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* loop through the tracks in normal order, since we're pushing strips down,
- * strips won't get operated on twice
- */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaTrack *nltp = nlt->prev;
- NlaStrip *strip, *stripn;
-
- /* if this track has no tracks before it, skip for now... */
- if (nltp == NULL)
- continue;
-
- /* for every selected strip, try to move */
- for (strip = nlt->strips.first; strip; strip = stripn) {
- stripn = strip->next;
-
- if (strip->flag & NLASTRIP_FLAG_SELECT) {
- /* check if the track below has room for this strip */
- if (BKE_nlatrack_has_space(nltp, strip->start, strip->end)) {
- /* remove from its current track, and add to the one above
- * (it 'should' work, so no need to worry) */
- BLI_remlink(&nlt->strips, strip);
- BKE_nlatrack_add_strip(nltp, strip);
- }
- }
- }
- }
-
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
-
- /* refresh auto strip properties */
- ED_nla_postop_refresh(&ac);
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* loop through the tracks in normal order, since we're pushing strips down,
+ * strips won't get operated on twice
+ */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaTrack *nltp = nlt->prev;
+ NlaStrip *strip, *stripn;
+
+ /* if this track has no tracks before it, skip for now... */
+ if (nltp == NULL)
+ continue;
+
+ /* for every selected strip, try to move */
+ for (strip = nlt->strips.first; strip; strip = stripn) {
+ stripn = strip->next;
+
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ /* check if the track below has room for this strip */
+ if (BKE_nlatrack_has_space(nltp, strip->start, strip->end)) {
+ /* remove from its current track, and add to the one above
+ * (it 'should' work, so no need to worry) */
+ BLI_remlink(&nlt->strips, strip);
+ BKE_nlatrack_add_strip(nltp, strip);
+ }
+ }
+ }
+ }
+
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
+
+ /* refresh auto strip properties */
+ ED_nla_postop_refresh(&ac);
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_move_down(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move Strips Down";
- ot->idname = "NLA_OT_move_down";
- ot->description = "Move selected strips down a track if there's room";
+ /* identifiers */
+ ot->name = "Move Strips Down";
+ ot->idname = "NLA_OT_move_down";
+ ot->description = "Move selected strips down a track if there's room";
- /* api callbacks */
- ot->exec = nlaedit_move_down_exec;
- ot->poll = nlaop_poll_tweakmode_off;
+ /* api callbacks */
+ ot->exec = nlaedit_move_down_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Sync Action Length Operator ***************************** */
@@ -1751,81 +1776,87 @@ void NLA_OT_move_down(wmOperatorType *ot)
static int nlaedit_sync_actlen_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- const bool active_only = RNA_boolean_get(op->ptr, "active");
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get a list of the editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- if (active_only) filter |= ANIMFILTER_ACTIVE;
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* for each NLA-Track, apply scale of all selected strips */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
-
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- /* strip selection/active status check */
- if (active_only) {
- if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0)
- continue;
- }
- else {
- if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0)
- continue;
- }
-
- /* must be action-clip only (transitions don't have scale) */
- if (strip->type == NLASTRIP_TYPE_CLIP) {
- if (strip->act == NULL)
- continue;
-
- /* recalculate the length of the action */
- calc_action_range(strip->act, &strip->actstart, &strip->actend, 0);
-
- /* adjust the strip extents in response to this */
- BKE_nlastrip_recalculate_bounds(strip);
-
- ale->update |= ANIM_UPDATE_DEPS;
- }
- }
- }
-
- /* free temp data */
- ANIM_animdata_update(&ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ const bool active_only = RNA_boolean_get(op->ptr, "active");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ if (active_only)
+ filter |= ANIMFILTER_ACTIVE;
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* for each NLA-Track, apply scale of all selected strips */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ /* strip selection/active status check */
+ if (active_only) {
+ if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0)
+ continue;
+ }
+ else {
+ if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0)
+ continue;
+ }
+
+ /* must be action-clip only (transitions don't have scale) */
+ if (strip->type == NLASTRIP_TYPE_CLIP) {
+ if (strip->act == NULL)
+ continue;
+
+ /* recalculate the length of the action */
+ calc_action_range(strip->act, &strip->actstart, &strip->actend, 0);
+
+ /* adjust the strip extents in response to this */
+ BKE_nlastrip_recalculate_bounds(strip);
+
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ }
+ }
+
+ /* free temp data */
+ ANIM_animdata_update(&ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_action_sync_length(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Sync Action Length";
- ot->idname = "NLA_OT_action_sync_length";
- ot->description = "Synchronize the length of the referenced Action with the length used in the strip";
-
- /* api callbacks */
- ot->exec = nlaedit_sync_actlen_exec;
- ot->poll = nlaop_poll_tweakmode_off;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_boolean(ot->srna, "active", 1, "Active Strip Only", "Only sync the active length for the active strip");
+ /* identifiers */
+ ot->name = "Sync Action Length";
+ ot->idname = "NLA_OT_action_sync_length";
+ ot->description =
+ "Synchronize the length of the referenced Action with the length used in the strip";
+
+ /* api callbacks */
+ ot->exec = nlaedit_sync_actlen_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_boolean(ot->srna,
+ "active",
+ 1,
+ "Active Strip Only",
+ "Only sync the active length for the active strip");
}
/* ******************** Make Single User ********************************* */
@@ -1833,83 +1864,83 @@ void NLA_OT_action_sync_length(wmOperatorType *ot)
static int nlaedit_make_single_user_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- bAnimContext ac;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- bool copied = false;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get a list of the editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* Ensure that each action used only has a single user
- * - This is done in reverse order so that the original strips are
- * likely to still get to keep their action
- */
- for (ale = anim_data.last; ale; ale = ale->prev) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
-
- for (strip = nlt->strips.last; strip; strip = strip->prev) {
- /* must be action-clip only (as only these have actions) */
- if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) {
- if (strip->act == NULL)
- continue;
-
- /* multi-user? */
- if (ID_REAL_USERS(strip->act) > 1) {
- /* make a new copy of the action for us to use (it will have 1 user already) */
- bAction *new_action = BKE_action_copy(bmain, strip->act);
-
- /* decrement user count of our existing action */
- id_us_min(&strip->act->id);
-
- /* switch to the new copy */
- strip->act = new_action;
-
- ale->update |= ANIM_UPDATE_DEPS;
- copied = true;
- }
- }
- }
- }
-
- /* free temp data */
- ANIM_animdata_update(&ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
-
- if (copied) {
- DEG_relations_tag_update(ac.bmain);
- }
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ bool copied = false;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* Ensure that each action used only has a single user
+ * - This is done in reverse order so that the original strips are
+ * likely to still get to keep their action
+ */
+ for (ale = anim_data.last; ale; ale = ale->prev) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ for (strip = nlt->strips.last; strip; strip = strip->prev) {
+ /* must be action-clip only (as only these have actions) */
+ if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) {
+ if (strip->act == NULL)
+ continue;
+
+ /* multi-user? */
+ if (ID_REAL_USERS(strip->act) > 1) {
+ /* make a new copy of the action for us to use (it will have 1 user already) */
+ bAction *new_action = BKE_action_copy(bmain, strip->act);
+
+ /* decrement user count of our existing action */
+ id_us_min(&strip->act->id);
+
+ /* switch to the new copy */
+ strip->act = new_action;
+
+ ale->update |= ANIM_UPDATE_DEPS;
+ copied = true;
+ }
+ }
+ }
+ }
+
+ /* free temp data */
+ ANIM_animdata_update(&ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+
+ if (copied) {
+ DEG_relations_tag_update(ac.bmain);
+ }
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_make_single_user(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Single User";
- ot->idname = "NLA_OT_make_single_user";
- ot->description = "Ensure that each action is only used once in the set of strips selected";
-
- /* api callbacks */
- ot->invoke = WM_operator_confirm;
- ot->exec = nlaedit_make_single_user_exec;
- ot->poll = nlaop_poll_tweakmode_off;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Make Single User";
+ ot->idname = "NLA_OT_make_single_user";
+ ot->description = "Ensure that each action is only used once in the set of strips selected";
+
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = nlaedit_make_single_user_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Apply Scale Operator ***************************** */
@@ -1918,108 +1949,109 @@ void NLA_OT_make_single_user(wmOperatorType *ot)
/* apply scaling to keyframe */
static short bezt_apply_nlamapping(KeyframeEditData *ked, BezTriple *bezt)
{
- /* NLA-strip which has this scaling is stored in ked->data */
- NlaStrip *strip = (NlaStrip *)ked->data;
+ /* NLA-strip which has this scaling is stored in ked->data */
+ NlaStrip *strip = (NlaStrip *)ked->data;
- /* adjust all the times */
- bezt->vec[0][0] = nlastrip_get_frame(strip, bezt->vec[0][0], NLATIME_CONVERT_MAP);
- bezt->vec[1][0] = nlastrip_get_frame(strip, bezt->vec[1][0], NLATIME_CONVERT_MAP);
- bezt->vec[2][0] = nlastrip_get_frame(strip, bezt->vec[2][0], NLATIME_CONVERT_MAP);
+ /* adjust all the times */
+ bezt->vec[0][0] = nlastrip_get_frame(strip, bezt->vec[0][0], NLATIME_CONVERT_MAP);
+ bezt->vec[1][0] = nlastrip_get_frame(strip, bezt->vec[1][0], NLATIME_CONVERT_MAP);
+ bezt->vec[2][0] = nlastrip_get_frame(strip, bezt->vec[2][0], NLATIME_CONVERT_MAP);
- /* nothing to return or else we exit */
- return 0;
+ /* nothing to return or else we exit */
+ return 0;
}
static int nlaedit_apply_scale_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- bAnimContext ac;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- bool copied = false;
-
- KeyframeEditData ked = {{NULL}};
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get a list of the editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* for each NLA-Track, apply scale of all selected strips */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
-
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- /* strip must be selected, and must be action-clip only
- * (transitions don't have scale) */
- if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) {
- /* if the referenced action is used by other strips,
- * make this strip use its own copy */
- if (strip->act == NULL)
- continue;
- if (strip->act->id.us > 1) {
- /* make a copy of the Action to work on */
- bAction *act = BKE_action_copy(bmain, strip->act);
-
- /* set this as the new referenced action,
- * decrementing the users of the old one */
- id_us_min(&strip->act->id);
- strip->act = act;
-
- copied = true;
- }
-
- /* setup iterator, and iterate over all the keyframes in the action,
- * applying this scaling */
- ked.data = strip;
- ANIM_animchanneldata_keyframes_loop(&ked, ac.ads, strip->act, ALE_ACT, NULL, bezt_apply_nlamapping, calchandles_fcurve);
-
- /* clear scale of strip now that it has been applied,
- * and recalculate the extents of the action now that it has been scaled
- * but leave everything else alone
- */
- strip->scale = 1.0f;
- calc_action_range(strip->act, &strip->actstart, &strip->actend, 0);
-
- ale->update |= ANIM_UPDATE_DEPS;
- }
- }
- }
-
- /* free temp data */
- ANIM_animdata_update(&ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
-
- if (copied) {
- DEG_relations_tag_update(ac.bmain);
- }
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ bool copied = false;
+
+ KeyframeEditData ked = {{NULL}};
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* for each NLA-Track, apply scale of all selected strips */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ /* strip must be selected, and must be action-clip only
+ * (transitions don't have scale) */
+ if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) {
+ /* if the referenced action is used by other strips,
+ * make this strip use its own copy */
+ if (strip->act == NULL)
+ continue;
+ if (strip->act->id.us > 1) {
+ /* make a copy of the Action to work on */
+ bAction *act = BKE_action_copy(bmain, strip->act);
+
+ /* set this as the new referenced action,
+ * decrementing the users of the old one */
+ id_us_min(&strip->act->id);
+ strip->act = act;
+
+ copied = true;
+ }
+
+ /* setup iterator, and iterate over all the keyframes in the action,
+ * applying this scaling */
+ ked.data = strip;
+ ANIM_animchanneldata_keyframes_loop(
+ &ked, ac.ads, strip->act, ALE_ACT, NULL, bezt_apply_nlamapping, calchandles_fcurve);
+
+ /* clear scale of strip now that it has been applied,
+ * and recalculate the extents of the action now that it has been scaled
+ * but leave everything else alone
+ */
+ strip->scale = 1.0f;
+ calc_action_range(strip->act, &strip->actstart, &strip->actend, 0);
+
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ }
+ }
+
+ /* free temp data */
+ ANIM_animdata_update(&ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+
+ if (copied) {
+ DEG_relations_tag_update(ac.bmain);
+ }
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_apply_scale(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Apply Scale";
- ot->idname = "NLA_OT_apply_scale";
- ot->description = "Apply scaling of selected strips to their referenced Actions";
+ /* identifiers */
+ ot->name = "Apply Scale";
+ ot->idname = "NLA_OT_apply_scale";
+ ot->description = "Apply scaling of selected strips to their referenced Actions";
- /* api callbacks */
- ot->exec = nlaedit_apply_scale_exec;
- ot->poll = nlaop_poll_tweakmode_off;
+ /* api callbacks */
+ ot->exec = nlaedit_apply_scale_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Clear Scale Operator ***************************** */
@@ -2027,63 +2059,63 @@ void NLA_OT_apply_scale(wmOperatorType *ot)
static int nlaedit_clear_scale_exec(bContext *C, wmOperator *UNUSED(op))
{
- bAnimContext ac;
+ bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* get a list of the editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* get a list of the editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* for each NLA-Track, reset scale of all selected strips */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
+ /* for each NLA-Track, reset scale of all selected strips */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- /* strip must be selected, and must be action-clip only
- * (transitions don't have scale) */
- if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) {
- PointerRNA strip_ptr;
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ /* strip must be selected, and must be action-clip only
+ * (transitions don't have scale) */
+ if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) {
+ PointerRNA strip_ptr;
- RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
- RNA_float_set(&strip_ptr, "scale", 1.0f);
- }
- }
- }
+ RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
+ RNA_float_set(&strip_ptr, "scale", 1.0f);
+ }
+ }
+ }
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
- /* refresh auto strip properties */
- ED_nla_postop_refresh(&ac);
+ /* refresh auto strip properties */
+ ED_nla_postop_refresh(&ac);
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
- /* done */
- return OPERATOR_FINISHED;
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_clear_scale(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Scale";
- ot->idname = "NLA_OT_clear_scale";
- ot->description = "Reset scaling of selected strips";
+ /* identifiers */
+ ot->name = "Clear Scale";
+ ot->idname = "NLA_OT_clear_scale";
+ ot->description = "Reset scaling of selected strips";
- /* api callbacks */
- ot->exec = nlaedit_clear_scale_exec;
- ot->poll = nlaop_poll_tweakmode_off;
+ /* api callbacks */
+ ot->exec = nlaedit_clear_scale_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Snap Strips Operator ************************** */
@@ -2091,149 +2123,153 @@ void NLA_OT_clear_scale(wmOperatorType *ot)
/* defines for snap keyframes tool */
static const EnumPropertyItem prop_nlaedit_snap_types[] = {
- {NLAEDIT_SNAP_CFRA, "CFRA", 0, "Current Frame", ""},
- {NLAEDIT_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame", ""}, // XXX as single entry?
- {NLAEDIT_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Nearest Second", ""}, // XXX as single entry?
- {NLAEDIT_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker", ""},
- {0, NULL, 0, NULL, NULL},
+ {NLAEDIT_SNAP_CFRA, "CFRA", 0, "Current Frame", ""},
+ {NLAEDIT_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame", ""}, // XXX as single entry?
+ {NLAEDIT_SNAP_NEAREST_SECOND,
+ "NEAREST_SECOND",
+ 0,
+ "Nearest Second",
+ ""}, // XXX as single entry?
+ {NLAEDIT_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int nlaedit_snap_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- Scene *scene;
- int mode = RNA_enum_get(op->ptr, "type");
- float secf;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get a list of the editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* get some necessary vars */
- scene = ac.scene;
- secf = (float)FPS;
-
- /* since we may add tracks, perform this in reverse order */
- for (ale = anim_data.last; ale; ale = ale->prev) {
- ListBase tmp_strips = {NULL, NULL};
- AnimData *adt = ale->adt;
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip, *stripn;
- NlaTrack *track;
-
- /* create meta-strips from the continuous chains of selected strips */
- BKE_nlastrips_make_metas(&nlt->strips, 1);
-
- /* apply the snapping to all the temp meta-strips, then put them in a separate list to be added
- * back to the original only if they still fit
- */
- for (strip = nlt->strips.first; strip; strip = stripn) {
- stripn = strip->next;
-
- if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
- float start, end;
-
- /* get the existing end-points */
- start = strip->start;
- end = strip->end;
-
- /* calculate new start position based on snapping mode */
- switch (mode) {
- case NLAEDIT_SNAP_CFRA: /* to current frame */
- strip->start = (float)CFRA;
- break;
- case NLAEDIT_SNAP_NEAREST_FRAME: /* to nearest frame */
- strip->start = floorf(start + 0.5f);
- break;
- case NLAEDIT_SNAP_NEAREST_SECOND: /* to nearest second */
- strip->start = floorf(start / secf + 0.5f) * secf;
- break;
- case NLAEDIT_SNAP_NEAREST_MARKER: /* to nearest marker */
- strip->start = (float)ED_markers_find_nearest_marker_time(ac.markers, start);
- break;
- default: /* just in case... no snapping */
- strip->start = start;
- break;
- }
-
- /* get new endpoint based on start-point (and old length) */
- strip->end = strip->start + (end - start);
-
- /* apply transforms to meta-strip to its children */
- BKE_nlameta_flush_transforms(strip);
-
- /* remove strip from track, and add to the temp buffer */
- BLI_remlink(&nlt->strips, strip);
- BLI_addtail(&tmp_strips, strip);
- }
- }
-
- /* try adding each meta-strip back to the track one at a time, to make sure they'll fit */
- for (strip = tmp_strips.first; strip; strip = stripn) {
- stripn = strip->next;
-
- /* remove from temp-strips list */
- BLI_remlink(&tmp_strips, strip);
-
- /* in case there's no space in the current track, try adding */
- if (BKE_nlatrack_add_strip(nlt, strip) == 0) {
- /* need to add a new track above the current one */
- track = BKE_nlatrack_add(adt, nlt);
- BKE_nlatrack_add_strip(track, strip);
-
- /* clear temp meta-strips on this new track,
- * as we may not be able to get back to it */
- BKE_nlastrips_clear_metas(&track->strips, 0, 1);
- }
- }
-
- /* remove the meta-strips now that we're done */
- BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
-
- /* tag for recalculating the animation */
- ale->update |= ANIM_UPDATE_DEPS;
- }
-
- /* cleanup */
- ANIM_animdata_update(&ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
-
- /* refresh auto strip properties */
- ED_nla_postop_refresh(&ac);
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ Scene *scene;
+ int mode = RNA_enum_get(op->ptr, "type");
+ float secf;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* get some necessary vars */
+ scene = ac.scene;
+ secf = (float)FPS;
+
+ /* since we may add tracks, perform this in reverse order */
+ for (ale = anim_data.last; ale; ale = ale->prev) {
+ ListBase tmp_strips = {NULL, NULL};
+ AnimData *adt = ale->adt;
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip, *stripn;
+ NlaTrack *track;
+
+ /* create meta-strips from the continuous chains of selected strips */
+ BKE_nlastrips_make_metas(&nlt->strips, 1);
+
+ /* apply the snapping to all the temp meta-strips, then put them in a separate list to be added
+ * back to the original only if they still fit
+ */
+ for (strip = nlt->strips.first; strip; strip = stripn) {
+ stripn = strip->next;
+
+ if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
+ float start, end;
+
+ /* get the existing end-points */
+ start = strip->start;
+ end = strip->end;
+
+ /* calculate new start position based on snapping mode */
+ switch (mode) {
+ case NLAEDIT_SNAP_CFRA: /* to current frame */
+ strip->start = (float)CFRA;
+ break;
+ case NLAEDIT_SNAP_NEAREST_FRAME: /* to nearest frame */
+ strip->start = floorf(start + 0.5f);
+ break;
+ case NLAEDIT_SNAP_NEAREST_SECOND: /* to nearest second */
+ strip->start = floorf(start / secf + 0.5f) * secf;
+ break;
+ case NLAEDIT_SNAP_NEAREST_MARKER: /* to nearest marker */
+ strip->start = (float)ED_markers_find_nearest_marker_time(ac.markers, start);
+ break;
+ default: /* just in case... no snapping */
+ strip->start = start;
+ break;
+ }
+
+ /* get new endpoint based on start-point (and old length) */
+ strip->end = strip->start + (end - start);
+
+ /* apply transforms to meta-strip to its children */
+ BKE_nlameta_flush_transforms(strip);
+
+ /* remove strip from track, and add to the temp buffer */
+ BLI_remlink(&nlt->strips, strip);
+ BLI_addtail(&tmp_strips, strip);
+ }
+ }
+
+ /* try adding each meta-strip back to the track one at a time, to make sure they'll fit */
+ for (strip = tmp_strips.first; strip; strip = stripn) {
+ stripn = strip->next;
+
+ /* remove from temp-strips list */
+ BLI_remlink(&tmp_strips, strip);
+
+ /* in case there's no space in the current track, try adding */
+ if (BKE_nlatrack_add_strip(nlt, strip) == 0) {
+ /* need to add a new track above the current one */
+ track = BKE_nlatrack_add(adt, nlt);
+ BKE_nlatrack_add_strip(track, strip);
+
+ /* clear temp meta-strips on this new track,
+ * as we may not be able to get back to it */
+ BKE_nlastrips_clear_metas(&track->strips, 0, 1);
+ }
+ }
+
+ /* remove the meta-strips now that we're done */
+ BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
+
+ /* tag for recalculating the animation */
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+
+ /* cleanup */
+ ANIM_animdata_update(&ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+
+ /* refresh auto strip properties */
+ ED_nla_postop_refresh(&ac);
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_snap(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Snap Strips";
- ot->idname = "NLA_OT_snap";
- ot->description = "Move start of strips to specified time";
+ /* identifiers */
+ ot->name = "Snap Strips";
+ ot->idname = "NLA_OT_snap";
+ ot->description = "Move start of strips to specified time";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = nlaedit_snap_exec;
- ot->poll = nlaop_poll_tweakmode_off;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = nlaedit_snap_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_nlaedit_snap_types, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_nlaedit_snap_types, 0, "Type", "");
}
/* *********************************************** */
@@ -2241,275 +2277,289 @@ void NLA_OT_snap(wmOperatorType *ot)
/* ******************** Add F-Modifier Operator *********************** */
-static const EnumPropertyItem *nla_fmodifier_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *nla_fmodifier_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- EnumPropertyItem *item = NULL;
- int totitem = 0;
- int i = 0;
-
- if (C == NULL) {
- return rna_enum_fmodifier_type_items;
- }
-
- /* start from 1 to skip the 'Invalid' modifier type */
- for (i = 1; i < FMODIFIER_NUM_TYPES; i++) {
- const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(i);
- int index;
-
- /* check if modifier is valid for this context */
- if (fmi == NULL)
- continue;
- if (i == FMODIFIER_TYPE_CYCLES) /* we already have repeat... */
- continue;
-
- index = RNA_enum_from_value(rna_enum_fmodifier_type_items, fmi->type);
- if (index != -1) { /* Not all types are implemented yet... */
- RNA_enum_item_add(&item, &totitem, &rna_enum_fmodifier_type_items[index]);
- }
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+ int i = 0;
+
+ if (C == NULL) {
+ return rna_enum_fmodifier_type_items;
+ }
+
+ /* start from 1 to skip the 'Invalid' modifier type */
+ for (i = 1; i < FMODIFIER_NUM_TYPES; i++) {
+ const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(i);
+ int index;
+
+ /* check if modifier is valid for this context */
+ if (fmi == NULL)
+ continue;
+ if (i == FMODIFIER_TYPE_CYCLES) /* we already have repeat... */
+ continue;
+
+ index = RNA_enum_from_value(rna_enum_fmodifier_type_items, fmi->type);
+ if (index != -1) { /* Not all types are implemented yet... */
+ RNA_enum_item_add(&item, &totitem, &rna_enum_fmodifier_type_items[index]);
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
-
static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- FModifier *fcm;
- int type = RNA_enum_get(op->ptr, "type");
- const bool active_only = RNA_boolean_get(op->ptr, "only_active");
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get a list of the editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* for each NLA-Track, add the specified modifier to all selected strips */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
-
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- /* can F-Modifier be added to the current strip? */
- if (active_only) {
- /* if not active, cannot add since we're only adding to active strip */
- if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0)
- continue;
- }
- else {
- /* strip must be selected, since we're not just doing active */
- if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0)
- continue;
- }
-
- /* sound clips are not affected by FModifiers */
- if (strip->type == NLASTRIP_TYPE_SOUND)
- continue;
-
- /* add F-Modifier of specified type to selected, and make it the active one */
- fcm = add_fmodifier(&strip->modifiers, type, NULL);
-
- if (fcm) {
- set_active_fmodifier(&strip->modifiers, fcm);
- ale->update |= ANIM_UPDATE_DEPS;
- }
- else {
- BKE_reportf(op->reports, RPT_ERROR,
- "Modifier could not be added to (%s : %s) (see console for details)",
- nlt->name, strip->name);
- }
- }
- }
-
- /* free temp data */
- ANIM_animdata_update(&ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ FModifier *fcm;
+ int type = RNA_enum_get(op->ptr, "type");
+ const bool active_only = RNA_boolean_get(op->ptr, "only_active");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* for each NLA-Track, add the specified modifier to all selected strips */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ /* can F-Modifier be added to the current strip? */
+ if (active_only) {
+ /* if not active, cannot add since we're only adding to active strip */
+ if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0)
+ continue;
+ }
+ else {
+ /* strip must be selected, since we're not just doing active */
+ if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0)
+ continue;
+ }
+
+ /* sound clips are not affected by FModifiers */
+ if (strip->type == NLASTRIP_TYPE_SOUND)
+ continue;
+
+ /* add F-Modifier of specified type to selected, and make it the active one */
+ fcm = add_fmodifier(&strip->modifiers, type, NULL);
+
+ if (fcm) {
+ set_active_fmodifier(&strip->modifiers, fcm);
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else {
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "Modifier could not be added to (%s : %s) (see console for details)",
+ nlt->name,
+ strip->name);
+ }
+ }
+ }
+
+ /* free temp data */
+ ANIM_animdata_update(&ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void NLA_OT_fmodifier_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add F-Modifier";
- ot->idname = "NLA_OT_fmodifier_add";
- ot->description = "Add F-Modifier to the active/selected NLA-Strips";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = nla_fmodifier_add_exec;
- ot->poll = nlaop_poll_tweakmode_off;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* id-props */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_fmodifier_type_items, 0, "Type", "");
- RNA_def_enum_funcs(ot->prop, nla_fmodifier_itemf);
-
- RNA_def_boolean(ot->srna, "only_active", true, "Only Active", "Only add a F-Modifier of the specified type to the active strip");
+ /* identifiers */
+ ot->name = "Add F-Modifier";
+ ot->idname = "NLA_OT_fmodifier_add";
+ ot->description = "Add F-Modifier to the active/selected NLA-Strips";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = nla_fmodifier_add_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* id-props */
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_fmodifier_type_items, 0, "Type", "");
+ RNA_def_enum_funcs(ot->prop, nla_fmodifier_itemf);
+
+ RNA_def_boolean(ot->srna,
+ "only_active",
+ true,
+ "Only Active",
+ "Only add a F-Modifier of the specified type to the active strip");
}
/* ******************** Copy F-Modifiers Operator *********************** */
static int nla_fmodifier_copy_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- bool ok = false;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* clear buffer first */
- ANIM_fmodifiers_copybuf_free();
-
- /* get a list of the editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* for each NLA-Track, add the specified modifier to all selected strips */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
-
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- /* only add F-Modifier if on active strip? */
- if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0)
- continue;
-
- // TODO: when 'active' vs 'all' boolean is added, change last param!
- ok |= ANIM_fmodifiers_copy_to_buf(&strip->modifiers, 0);
- }
- }
-
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
-
- /* successful or not? */
- if (ok == 0) {
- BKE_report(op->reports, RPT_ERROR, "No F-Modifiers available to be copied");
- return OPERATOR_CANCELLED;
- }
- else {
- /* no updates needed - copy is non-destructive operation */
- return OPERATOR_FINISHED;
- }
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ bool ok = false;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* clear buffer first */
+ ANIM_fmodifiers_copybuf_free();
+
+ /* get a list of the editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* for each NLA-Track, add the specified modifier to all selected strips */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ /* only add F-Modifier if on active strip? */
+ if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0)
+ continue;
+
+ // TODO: when 'active' vs 'all' boolean is added, change last param!
+ ok |= ANIM_fmodifiers_copy_to_buf(&strip->modifiers, 0);
+ }
+ }
+
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
+
+ /* successful or not? */
+ if (ok == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No F-Modifiers available to be copied");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* no updates needed - copy is non-destructive operation */
+ return OPERATOR_FINISHED;
+ }
}
void NLA_OT_fmodifier_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy F-Modifiers";
- ot->idname = "NLA_OT_fmodifier_copy";
- ot->description = "Copy the F-Modifier(s) of the active NLA-Strip";
+ /* identifiers */
+ ot->name = "Copy F-Modifiers";
+ ot->idname = "NLA_OT_fmodifier_copy";
+ ot->description = "Copy the F-Modifier(s) of the active NLA-Strip";
- /* api callbacks */
- ot->exec = nla_fmodifier_copy_exec;
- ot->poll = nlaop_poll_tweakmode_off;
+ /* api callbacks */
+ ot->exec = nla_fmodifier_copy_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* id-props */
- //ot->prop = RNA_def_boolean(ot->srna, "all", 1, "All F-Modifiers", "Copy all the F-Modifiers, instead of just the active one");
+ /* id-props */
+ //ot->prop = RNA_def_boolean(ot->srna, "all", 1, "All F-Modifiers", "Copy all the F-Modifiers, instead of just the active one");
}
/* ******************** Paste F-Modifiers Operator *********************** */
static int nla_fmodifier_paste_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter, ok = 0;
-
- const bool active_only = RNA_boolean_get(op->ptr, "only_active");
- const bool replace = RNA_boolean_get(op->ptr, "replace");
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get a list of the editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* for each NLA-Track, add the specified modifier to all selected strips */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
-
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- /* can F-Modifier be added to the current strip? */
- if (active_only) {
- /* if not active, cannot add since we're only adding to active strip */
- if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0)
- continue;
- }
- else {
- /* strip must be selected, since we're not just doing active */
- if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0)
- continue;
- }
-
- /* paste FModifiers from buffer */
- ok += ANIM_fmodifiers_paste_from_buf(&strip->modifiers, replace, NULL);
- ale->update |= ANIM_UPDATE_DEPS;
- }
- }
-
- /* clean up */
- ANIM_animdata_update(&ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
-
- /* successful or not? */
- if (ok) {
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "No F-Modifiers to paste");
- return OPERATOR_CANCELLED;
- }
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter, ok = 0;
+
+ const bool active_only = RNA_boolean_get(op->ptr, "only_active");
+ const bool replace = RNA_boolean_get(op->ptr, "replace");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the editable tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
+ ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* for each NLA-Track, add the specified modifier to all selected strips */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ /* can F-Modifier be added to the current strip? */
+ if (active_only) {
+ /* if not active, cannot add since we're only adding to active strip */
+ if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0)
+ continue;
+ }
+ else {
+ /* strip must be selected, since we're not just doing active */
+ if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0)
+ continue;
+ }
+
+ /* paste FModifiers from buffer */
+ ok += ANIM_fmodifiers_paste_from_buf(&strip->modifiers, replace, NULL);
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ }
+
+ /* clean up */
+ ANIM_animdata_update(&ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+
+ /* successful or not? */
+ if (ok) {
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No F-Modifiers to paste");
+ return OPERATOR_CANCELLED;
+ }
}
void NLA_OT_fmodifier_paste(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Paste F-Modifiers";
- ot->idname = "NLA_OT_fmodifier_paste";
- ot->description = "Add copied F-Modifiers to the selected NLA-Strips";
-
- /* api callbacks */
- ot->exec = nla_fmodifier_paste_exec;
- ot->poll = nlaop_poll_tweakmode_off;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "only_active", true, "Only Active", "Only paste F-Modifiers on active strip");
- RNA_def_boolean(ot->srna, "replace", false, "Replace Existing",
- "Replace existing F-Modifiers, instead of just appending to the end of the existing list");
+ /* identifiers */
+ ot->name = "Paste F-Modifiers";
+ ot->idname = "NLA_OT_fmodifier_paste";
+ ot->description = "Add copied F-Modifiers to the selected NLA-Strips";
+
+ /* api callbacks */
+ ot->exec = nla_fmodifier_paste_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(
+ ot->srna, "only_active", true, "Only Active", "Only paste F-Modifiers on active strip");
+ RNA_def_boolean(
+ ot->srna,
+ "replace",
+ false,
+ "Replace Existing",
+ "Replace existing F-Modifiers, instead of just appending to the end of the existing list");
}
/* *********************************************** */
diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h
index bb52d9d7f76..291dfe17343 100644
--- a/source/blender/editors/space_nla/nla_intern.h
+++ b/source/blender/editors/space_nla/nla_intern.h
@@ -34,7 +34,10 @@
ARegion *nla_has_buttons_region(ScrArea *sa);
-bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_ptr, PointerRNA *strip_ptr);
+bool nla_panel_context(const bContext *C,
+ PointerRNA *adt_ptr,
+ PointerRNA *nlt_ptr,
+ PointerRNA *strip_ptr);
void nla_buttons_register(ARegionType *art);
void NLA_OT_properties(wmOperatorType *ot);
@@ -50,10 +53,10 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar);
/* defines for left-right select tool */
enum eNlaEdit_LeftRightSelect_Mode {
- NLAEDIT_LRSEL_TEST = -1,
- NLAEDIT_LRSEL_NONE,
- NLAEDIT_LRSEL_LEFT,
- NLAEDIT_LRSEL_RIGHT,
+ NLAEDIT_LRSEL_TEST = -1,
+ NLAEDIT_LRSEL_NONE,
+ NLAEDIT_LRSEL_LEFT,
+ NLAEDIT_LRSEL_RIGHT,
};
/* --- */
@@ -68,10 +71,10 @@ void NLA_OT_click_select(wmOperatorType *ot);
/* defines for snap strips */
enum eNlaEdit_Snap_Mode {
- NLAEDIT_SNAP_CFRA = 1,
- NLAEDIT_SNAP_NEAREST_FRAME,
- NLAEDIT_SNAP_NEAREST_SECOND,
- NLAEDIT_SNAP_NEAREST_MARKER,
+ NLAEDIT_SNAP_CFRA = 1,
+ NLAEDIT_SNAP_NEAREST_FRAME,
+ NLAEDIT_SNAP_NEAREST_SECOND,
+ NLAEDIT_SNAP_NEAREST_MARKER,
};
/* --- */
@@ -119,7 +122,6 @@ void NLA_OT_fmodifier_add(wmOperatorType *ot);
void NLA_OT_fmodifier_copy(wmOperatorType *ot);
void NLA_OT_fmodifier_paste(wmOperatorType *ot);
-
/* **************************************** */
/* nla_channels.c */
diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c
index 6653c3995b5..51d6232cf71 100644
--- a/source/blender/editors/space_nla/nla_ops.c
+++ b/source/blender/editors/space_nla/nla_ops.c
@@ -40,7 +40,6 @@
#include "RNA_access.h"
-
#include "nla_intern.h" /* own include */
/* ************************** poll callbacks for operators **********************************/
@@ -48,138 +47,138 @@
/* tweakmode is NOT enabled */
bool nlaop_poll_tweakmode_off(bContext *C)
{
- Scene *scene;
-
- /* for now, we check 2 things:
- * 1) active editor must be NLA
- * 2) tweakmode is currently set as a 'per-scene' flag
- * so that it will affect entire NLA data-sets,
- * but not all AnimData blocks will be in tweakmode for
- * various reasons
- */
- if (ED_operator_nla_active(C) == 0)
- return 0;
-
- scene = CTX_data_scene(C);
- if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON))
- return 0;
-
- return 1;
+ Scene *scene;
+
+ /* for now, we check 2 things:
+ * 1) active editor must be NLA
+ * 2) tweakmode is currently set as a 'per-scene' flag
+ * so that it will affect entire NLA data-sets,
+ * but not all AnimData blocks will be in tweakmode for
+ * various reasons
+ */
+ if (ED_operator_nla_active(C) == 0)
+ return 0;
+
+ scene = CTX_data_scene(C);
+ if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON))
+ return 0;
+
+ return 1;
}
/* tweakmode IS enabled */
bool nlaop_poll_tweakmode_on(bContext *C)
{
- Scene *scene;
-
- /* for now, we check 2 things:
- * 1) active editor must be NLA
- * 2) tweakmode is currently set as a 'per-scene' flag
- * so that it will affect entire NLA data-sets,
- * but not all AnimData blocks will be in tweakmode for
- * various reasons
- */
- if (ED_operator_nla_active(C) == 0)
- return 0;
-
- scene = CTX_data_scene(C);
- if ((scene == NULL) || !(scene->flag & SCE_NLA_EDIT_ON))
- return 0;
-
- return 1;
+ Scene *scene;
+
+ /* for now, we check 2 things:
+ * 1) active editor must be NLA
+ * 2) tweakmode is currently set as a 'per-scene' flag
+ * so that it will affect entire NLA data-sets,
+ * but not all AnimData blocks will be in tweakmode for
+ * various reasons
+ */
+ if (ED_operator_nla_active(C) == 0)
+ return 0;
+
+ scene = CTX_data_scene(C);
+ if ((scene == NULL) || !(scene->flag & SCE_NLA_EDIT_ON))
+ return 0;
+
+ return 1;
}
/* is tweakmode enabled - for use in NLA operator code */
bool nlaedit_is_tweakmode_on(bAnimContext *ac)
{
- if (ac && ac->scene)
- return (ac->scene->flag & SCE_NLA_EDIT_ON) != 0;
- return 0;
+ if (ac && ac->scene)
+ return (ac->scene->flag & SCE_NLA_EDIT_ON) != 0;
+ return 0;
}
/* ************************** registration - operator types **********************************/
void nla_operatortypes(void)
{
- /* view */
- WM_operatortype_append(NLA_OT_properties);
+ /* view */
+ WM_operatortype_append(NLA_OT_properties);
- /* channels */
- WM_operatortype_append(NLA_OT_channels_click);
+ /* channels */
+ WM_operatortype_append(NLA_OT_channels_click);
- WM_operatortype_append(NLA_OT_action_pushdown);
- WM_operatortype_append(NLA_OT_action_unlink);
+ WM_operatortype_append(NLA_OT_action_pushdown);
+ WM_operatortype_append(NLA_OT_action_unlink);
- WM_operatortype_append(NLA_OT_tracks_add);
- WM_operatortype_append(NLA_OT_tracks_delete);
+ WM_operatortype_append(NLA_OT_tracks_add);
+ WM_operatortype_append(NLA_OT_tracks_delete);
- WM_operatortype_append(NLA_OT_selected_objects_add);
+ WM_operatortype_append(NLA_OT_selected_objects_add);
- /* select */
- WM_operatortype_append(NLA_OT_click_select);
- WM_operatortype_append(NLA_OT_select_box);
- WM_operatortype_append(NLA_OT_select_all);
- WM_operatortype_append(NLA_OT_select_leftright);
+ /* select */
+ WM_operatortype_append(NLA_OT_click_select);
+ WM_operatortype_append(NLA_OT_select_box);
+ WM_operatortype_append(NLA_OT_select_all);
+ WM_operatortype_append(NLA_OT_select_leftright);
- /* view */
- WM_operatortype_append(NLA_OT_view_all);
- WM_operatortype_append(NLA_OT_view_selected);
- WM_operatortype_append(NLA_OT_view_frame);
+ /* view */
+ WM_operatortype_append(NLA_OT_view_all);
+ WM_operatortype_append(NLA_OT_view_selected);
+ WM_operatortype_append(NLA_OT_view_frame);
- WM_operatortype_append(NLA_OT_previewrange_set);
+ WM_operatortype_append(NLA_OT_previewrange_set);
- /* edit */
- WM_operatortype_append(NLA_OT_tweakmode_enter);
- WM_operatortype_append(NLA_OT_tweakmode_exit);
+ /* edit */
+ WM_operatortype_append(NLA_OT_tweakmode_enter);
+ WM_operatortype_append(NLA_OT_tweakmode_exit);
- WM_operatortype_append(NLA_OT_actionclip_add);
- WM_operatortype_append(NLA_OT_transition_add);
- WM_operatortype_append(NLA_OT_soundclip_add);
+ WM_operatortype_append(NLA_OT_actionclip_add);
+ WM_operatortype_append(NLA_OT_transition_add);
+ WM_operatortype_append(NLA_OT_soundclip_add);
- WM_operatortype_append(NLA_OT_meta_add);
- WM_operatortype_append(NLA_OT_meta_remove);
+ WM_operatortype_append(NLA_OT_meta_add);
+ WM_operatortype_append(NLA_OT_meta_remove);
- WM_operatortype_append(NLA_OT_duplicate);
- WM_operatortype_append(NLA_OT_delete);
- WM_operatortype_append(NLA_OT_split);
+ WM_operatortype_append(NLA_OT_duplicate);
+ WM_operatortype_append(NLA_OT_delete);
+ WM_operatortype_append(NLA_OT_split);
- WM_operatortype_append(NLA_OT_mute_toggle);
+ WM_operatortype_append(NLA_OT_mute_toggle);
- WM_operatortype_append(NLA_OT_swap);
- WM_operatortype_append(NLA_OT_move_up);
- WM_operatortype_append(NLA_OT_move_down);
+ WM_operatortype_append(NLA_OT_swap);
+ WM_operatortype_append(NLA_OT_move_up);
+ WM_operatortype_append(NLA_OT_move_down);
- WM_operatortype_append(NLA_OT_action_sync_length);
+ WM_operatortype_append(NLA_OT_action_sync_length);
- WM_operatortype_append(NLA_OT_make_single_user);
+ WM_operatortype_append(NLA_OT_make_single_user);
- WM_operatortype_append(NLA_OT_apply_scale);
- WM_operatortype_append(NLA_OT_clear_scale);
+ WM_operatortype_append(NLA_OT_apply_scale);
+ WM_operatortype_append(NLA_OT_clear_scale);
- WM_operatortype_append(NLA_OT_snap);
+ WM_operatortype_append(NLA_OT_snap);
- WM_operatortype_append(NLA_OT_fmodifier_add);
- WM_operatortype_append(NLA_OT_fmodifier_copy);
- WM_operatortype_append(NLA_OT_fmodifier_paste);
+ WM_operatortype_append(NLA_OT_fmodifier_add);
+ WM_operatortype_append(NLA_OT_fmodifier_copy);
+ WM_operatortype_append(NLA_OT_fmodifier_paste);
}
/* ************************** registration - keymaps **********************************/
void nla_keymap(wmKeyConfig *keyconf)
{
- /* keymap for all regions ------------------------------------------- */
- WM_keymap_ensure(keyconf, "NLA Generic", SPACE_NLA, 0);
-
- /* channels ---------------------------------------------------------- */
- /* Channels are not directly handled by the NLA Editor module, but are inherited from the Animation module.
- * Most of the relevant operations, keymaps, drawing, etc. can therefore all
- * be found in that module instead, as there are many similarities with the other Animation Editors.
- *
- * However, those operations which involve clicking on channels and/or
- * the placement of them in the view are implemented here instead
- */
- WM_keymap_ensure(keyconf, "NLA Channels", SPACE_NLA, 0);
-
- /* data ------------------------------------------------------------- */
- WM_keymap_ensure(keyconf, "NLA Editor", SPACE_NLA, 0);
+ /* keymap for all regions ------------------------------------------- */
+ WM_keymap_ensure(keyconf, "NLA Generic", SPACE_NLA, 0);
+
+ /* channels ---------------------------------------------------------- */
+ /* Channels are not directly handled by the NLA Editor module, but are inherited from the Animation module.
+ * Most of the relevant operations, keymaps, drawing, etc. can therefore all
+ * be found in that module instead, as there are many similarities with the other Animation Editors.
+ *
+ * However, those operations which involve clicking on channels and/or
+ * the placement of them in the view are implemented here instead
+ */
+ WM_keymap_ensure(keyconf, "NLA Channels", SPACE_NLA, 0);
+
+ /* data ------------------------------------------------------------- */
+ WM_keymap_ensure(keyconf, "NLA Editor", SPACE_NLA, 0);
}
diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c
index f326637f1cd..0df0c5a99da 100644
--- a/source/blender/editors/space_nla/nla_select.c
+++ b/source/blender/editors/space_nla/nla_select.c
@@ -21,7 +21,6 @@
* \ingroup spnla
*/
-
#include <string.h>
#include <stdio.h>
@@ -49,28 +48,27 @@
#include "UI_view2d.h"
-#include "nla_intern.h" // own include
+#include "nla_intern.h" // own include
/* ******************** Utilities ***************************************** */
/* Convert SELECT_* flags to ACHANNEL_SETFLAG_* flags */
static short selmodes_to_flagmodes(short sel)
{
- /* convert selection modes to selection modes */
- switch (sel) {
- case SELECT_SUBTRACT:
- return ACHANNEL_SETFLAG_CLEAR;
-
- case SELECT_INVERT:
- return ACHANNEL_SETFLAG_INVERT;
-
- case SELECT_ADD:
- default:
- return ACHANNEL_SETFLAG_ADD;
- }
+ /* convert selection modes to selection modes */
+ switch (sel) {
+ case SELECT_SUBTRACT:
+ return ACHANNEL_SETFLAG_CLEAR;
+
+ case SELECT_INVERT:
+ return ACHANNEL_SETFLAG_INVERT;
+
+ case SELECT_ADD:
+ default:
+ return ACHANNEL_SETFLAG_ADD;
+ }
}
-
/* ******************** Deselect All Operator ***************************** */
/* This operator works in one of three ways:
* 1) (de)select all (AKEY) - test if select all or deselect all
@@ -79,9 +77,9 @@ static short selmodes_to_flagmodes(short sel)
*/
enum {
- DESELECT_STRIPS_NOTEST = 0,
- DESELECT_STRIPS_TEST,
- DESELECT_STRIPS_CLEARACTIVE,
+ DESELECT_STRIPS_NOTEST = 0,
+ DESELECT_STRIPS_TEST,
+ DESELECT_STRIPS_CLEARACTIVE,
} /*eDeselectNlaStrips*/;
/* Deselects strips in the NLA Editor
@@ -95,113 +93,113 @@ enum {
*/
static void deselect_nla_strips(bAnimContext *ac, short test, short sel)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- short smode;
-
- /* determine type-based settings */
- // FIXME: double check whether ANIMFILTER_LIST_VISIBLE is needed!
- filter = (ANIMFILTER_DATA_VISIBLE);
-
- /* filter data */
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* See if we should be selecting or deselecting */
- if (test == DESELECT_STRIPS_TEST) {
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
-
- /* if any strip is selected, break out, since we should now be deselecting */
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- if (strip->flag & NLASTRIP_FLAG_SELECT) {
- sel = SELECT_SUBTRACT;
- break;
- }
- }
-
- if (sel == SELECT_SUBTRACT)
- break;
- }
- }
-
- /* convert selection modes to selection modes */
- smode = selmodes_to_flagmodes(sel);
-
- /* Now set the flags */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
-
- /* apply same selection to all strips */
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- /* set selection */
- if (test != DESELECT_STRIPS_CLEARACTIVE)
- ACHANNEL_SET_FLAG(strip, smode, NLASTRIP_FLAG_SELECT);
-
- /* clear active flag */
- // TODO: for clear active, do we want to limit this to only doing this on a certain set of tracks though?
- strip->flag &= ~NLASTRIP_FLAG_ACTIVE;
- }
- }
-
- /* Cleanup */
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ short smode;
+
+ /* determine type-based settings */
+ // FIXME: double check whether ANIMFILTER_LIST_VISIBLE is needed!
+ filter = (ANIMFILTER_DATA_VISIBLE);
+
+ /* filter data */
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* See if we should be selecting or deselecting */
+ if (test == DESELECT_STRIPS_TEST) {
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ /* if any strip is selected, break out, since we should now be deselecting */
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ sel = SELECT_SUBTRACT;
+ break;
+ }
+ }
+
+ if (sel == SELECT_SUBTRACT)
+ break;
+ }
+ }
+
+ /* convert selection modes to selection modes */
+ smode = selmodes_to_flagmodes(sel);
+
+ /* Now set the flags */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ /* apply same selection to all strips */
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ /* set selection */
+ if (test != DESELECT_STRIPS_CLEARACTIVE)
+ ACHANNEL_SET_FLAG(strip, smode, NLASTRIP_FLAG_SELECT);
+
+ /* clear active flag */
+ // TODO: for clear active, do we want to limit this to only doing this on a certain set of tracks though?
+ strip->flag &= ~NLASTRIP_FLAG_ACTIVE;
+ }
+ }
+
+ /* Cleanup */
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int nlaedit_deselectall_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* 'standard' behavior - check if selected, then apply relevant selection */
- const int action = RNA_enum_get(op->ptr, "action");
- switch (action) {
- case SEL_TOGGLE:
- deselect_nla_strips(&ac, DESELECT_STRIPS_TEST, SELECT_ADD);
- break;
- case SEL_SELECT:
- deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_ADD);
- break;
- case SEL_DESELECT:
- deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_SUBTRACT);
- break;
- case SEL_INVERT:
- deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_INVERT);
- break;
- default:
- BLI_assert(0);
- break;
- }
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* 'standard' behavior - check if selected, then apply relevant selection */
+ const int action = RNA_enum_get(op->ptr, "action");
+ switch (action) {
+ case SEL_TOGGLE:
+ deselect_nla_strips(&ac, DESELECT_STRIPS_TEST, SELECT_ADD);
+ break;
+ case SEL_SELECT:
+ deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_ADD);
+ break;
+ case SEL_DESELECT:
+ deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_SUBTRACT);
+ break;
+ case SEL_INVERT:
+ deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_INVERT);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL);
+
+ return OPERATOR_FINISHED;
}
void NLA_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All";
- ot->idname = "NLA_OT_select_all";
- ot->description = "Select or deselect all NLA-Strips";
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->idname = "NLA_OT_select_all";
+ ot->description = "Select or deselect all NLA-Strips";
- /* api callbacks */
- ot->exec = nlaedit_deselectall_exec;
- ot->poll = nlaop_poll_tweakmode_off;
+ /* api callbacks */
+ ot->exec = nlaedit_deselectall_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/;
- /* properties */
- WM_operator_properties_select_all(ot);
+ /* properties */
+ WM_operator_properties_select_all(ot);
}
/* ******************** Box Select Operator **************************** */
@@ -214,138 +212,134 @@ void NLA_OT_select_all(wmOperatorType *ot)
/* defines for box_select mode */
enum {
- NLA_BOXSEL_ALLSTRIPS = 0,
- NLA_BOXSEL_FRAMERANGE,
- NLA_BOXSEL_CHANNELS,
+ NLA_BOXSEL_ALLSTRIPS = 0,
+ NLA_BOXSEL_FRAMERANGE,
+ NLA_BOXSEL_CHANNELS,
} /* eNLAEDIT_BoxSelect_Mode */;
-
static void box_select_nla_strips(bAnimContext *ac, rcti rect, short mode, short selectmode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- SpaceNla *snla = (SpaceNla *)ac->sl;
- View2D *v2d = &ac->ar->v2d;
- rctf rectf;
- float ymin /* =(float)(-NLACHANNEL_HEIGHT(snla)) */ /* UNUSED */, ymax = 0;
-
- /* convert border-region to view coordinates */
- UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin + 2, &rectf.xmin, &rectf.ymin);
- UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax - 2, &rectf.xmax, &rectf.ymax);
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* convert selection modes to selection modes */
- selectmode = selmodes_to_flagmodes(selectmode);
-
- /* loop over data, doing box select */
- for (ale = anim_data.first; ale; ale = ale->next) {
- ymin = ymax - NLACHANNEL_STEP(snla);
-
- /* perform vertical suitability check (if applicable) */
- if ((mode == NLA_BOXSEL_FRAMERANGE) ||
- !((ymax < rectf.ymin) || (ymin > rectf.ymax)))
- {
- /* loop over data selecting (only if NLA-Track) */
- if (ale->type == ANIMTYPE_NLATRACK) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
-
- /* only select strips if they fall within the required ranges (if applicable) */
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- if ((mode == NLA_BOXSEL_CHANNELS) ||
- BKE_nlastrip_within_bounds(strip, rectf.xmin, rectf.xmax))
- {
- /* set selection */
- ACHANNEL_SET_FLAG(strip, selectmode, NLASTRIP_FLAG_SELECT);
-
- /* clear active flag */
- strip->flag &= ~NLASTRIP_FLAG_ACTIVE;
- }
- }
- }
- }
-
- /* set minimum extent to be the maximum of the next channel */
- ymax = ymin;
- }
-
- /* cleanup */
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ SpaceNla *snla = (SpaceNla *)ac->sl;
+ View2D *v2d = &ac->ar->v2d;
+ rctf rectf;
+ float ymin /* =(float)(-NLACHANNEL_HEIGHT(snla)) */ /* UNUSED */, ymax = 0;
+
+ /* convert border-region to view coordinates */
+ UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin + 2, &rectf.xmin, &rectf.ymin);
+ UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax - 2, &rectf.xmax, &rectf.ymax);
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* convert selection modes to selection modes */
+ selectmode = selmodes_to_flagmodes(selectmode);
+
+ /* loop over data, doing box select */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ ymin = ymax - NLACHANNEL_STEP(snla);
+
+ /* perform vertical suitability check (if applicable) */
+ if ((mode == NLA_BOXSEL_FRAMERANGE) || !((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
+ /* loop over data selecting (only if NLA-Track) */
+ if (ale->type == ANIMTYPE_NLATRACK) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ /* only select strips if they fall within the required ranges (if applicable) */
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ if ((mode == NLA_BOXSEL_CHANNELS) ||
+ BKE_nlastrip_within_bounds(strip, rectf.xmin, rectf.xmax)) {
+ /* set selection */
+ ACHANNEL_SET_FLAG(strip, selectmode, NLASTRIP_FLAG_SELECT);
+
+ /* clear active flag */
+ strip->flag &= ~NLASTRIP_FLAG_ACTIVE;
+ }
+ }
+ }
+ }
+
+ /* set minimum extent to be the maximum of the next channel */
+ ymax = ymin;
+ }
+
+ /* cleanup */
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int nlaedit_box_select_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- rcti rect;
- short mode = 0;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
- const int selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- deselect_nla_strips(&ac, DESELECT_STRIPS_TEST, SELECT_SUBTRACT);
- }
-
- /* get settings from operator */
- WM_operator_properties_border_to_rcti(op, &rect);
-
- /* selection 'mode' depends on whether box_select region only matters on one axis */
- if (RNA_boolean_get(op->ptr, "axis_range")) {
- /* mode depends on which axis of the range is larger to determine which axis to use
- * - checking this in region-space is fine, as it's fundamentally still going to be a different rect size
- * - the frame-range select option is favored over the channel one (x over y), as frame-range one is often
- * used for tweaking timing when "blocking", while channels is not that useful...
- */
- if (BLI_rcti_size_x(&rect) >= BLI_rcti_size_y(&rect))
- mode = NLA_BOXSEL_FRAMERANGE;
- else
- mode = NLA_BOXSEL_CHANNELS;
- }
- else
- mode = NLA_BOXSEL_ALLSTRIPS;
-
- /* apply box_select action */
- box_select_nla_strips(&ac, rect, mode, selectmode);
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL);
-
- return OPERATOR_FINISHED;
+ bAnimContext ac;
+ rcti rect;
+ short mode = 0;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
+ const int selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ deselect_nla_strips(&ac, DESELECT_STRIPS_TEST, SELECT_SUBTRACT);
+ }
+
+ /* get settings from operator */
+ WM_operator_properties_border_to_rcti(op, &rect);
+
+ /* selection 'mode' depends on whether box_select region only matters on one axis */
+ if (RNA_boolean_get(op->ptr, "axis_range")) {
+ /* mode depends on which axis of the range is larger to determine which axis to use
+ * - checking this in region-space is fine, as it's fundamentally still going to be a different rect size
+ * - the frame-range select option is favored over the channel one (x over y), as frame-range one is often
+ * used for tweaking timing when "blocking", while channels is not that useful...
+ */
+ if (BLI_rcti_size_x(&rect) >= BLI_rcti_size_y(&rect))
+ mode = NLA_BOXSEL_FRAMERANGE;
+ else
+ mode = NLA_BOXSEL_CHANNELS;
+ }
+ else
+ mode = NLA_BOXSEL_ALLSTRIPS;
+
+ /* apply box_select action */
+ box_select_nla_strips(&ac, rect, mode, selectmode);
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL);
+
+ return OPERATOR_FINISHED;
}
void NLA_OT_select_box(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Box Select";
- ot->idname = "NLA_OT_select_box";
- ot->description = "Use box selection to grab NLA-Strips";
+ /* identifiers */
+ ot->name = "Box Select";
+ ot->idname = "NLA_OT_select_box";
+ ot->description = "Use box selection to grab NLA-Strips";
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = nlaedit_box_select_exec;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = nlaedit_box_select_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
- ot->poll = nlaop_poll_tweakmode_off;
+ ot->poll = nlaop_poll_tweakmode_off;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
+ /* properties */
+ RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
- WM_operator_properties_gesture_box(ot);
- WM_operator_properties_select_operation_simple(ot);
+ WM_operator_properties_gesture_box(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
/* ******************** Select Left/Right Operator ************************* */
@@ -353,266 +347,276 @@ void NLA_OT_select_box(wmOperatorType *ot)
/* defines for left-right select tool */
static const EnumPropertyItem prop_nlaedit_leftright_select_types[] = {
- {NLAEDIT_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""},
- {NLAEDIT_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""},
- {NLAEDIT_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""},
- {0, NULL, 0, NULL, NULL},
+ {NLAEDIT_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""},
+ {NLAEDIT_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""},
+ {NLAEDIT_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""},
+ {0, NULL, 0, NULL, NULL},
};
/* ------------------- */
-static void nlaedit_select_leftright(bContext *C, bAnimContext *ac, short leftright, short select_mode)
+static void nlaedit_select_leftright(bContext *C,
+ bAnimContext *ac,
+ short leftright,
+ short select_mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- Scene *scene = ac->scene;
- float xmin, xmax;
-
- /* if currently in tweakmode, exit tweakmode first */
- if (scene->flag & SCE_NLA_EDIT_ON)
- WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL);
-
- /* if select mode is replace, deselect all keyframes (and channels) first */
- if (select_mode == SELECT_REPLACE) {
- select_mode = SELECT_ADD;
-
- /* - deselect all other keyframes, so that just the newly selected remain
- * - channels aren't deselected, since we don't re-select any as a consequence
- */
- deselect_nla_strips(ac, 0, SELECT_SUBTRACT);
- }
-
- /* get range, and get the right flag-setting mode */
- if (leftright == NLAEDIT_LRSEL_LEFT) {
- xmin = MINAFRAMEF;
- xmax = (float)(CFRA + 0.1f);
- }
- else {
- xmin = (float)(CFRA - 0.1f);
- xmax = MAXFRAMEF;
- }
-
- select_mode = selmodes_to_flagmodes(select_mode);
-
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* select strips on the side where most data occurs */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
-
- /* check each strip to see if it is appropriate */
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- if (BKE_nlastrip_within_bounds(strip, xmin, xmax)) {
- ACHANNEL_SET_FLAG(strip, select_mode, NLASTRIP_FLAG_SELECT);
- }
- }
- }
-
- /* Cleanup */
- ANIM_animdata_freelist(&anim_data);
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ Scene *scene = ac->scene;
+ float xmin, xmax;
+
+ /* if currently in tweakmode, exit tweakmode first */
+ if (scene->flag & SCE_NLA_EDIT_ON)
+ WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL);
+
+ /* if select mode is replace, deselect all keyframes (and channels) first */
+ if (select_mode == SELECT_REPLACE) {
+ select_mode = SELECT_ADD;
+
+ /* - deselect all other keyframes, so that just the newly selected remain
+ * - channels aren't deselected, since we don't re-select any as a consequence
+ */
+ deselect_nla_strips(ac, 0, SELECT_SUBTRACT);
+ }
+
+ /* get range, and get the right flag-setting mode */
+ if (leftright == NLAEDIT_LRSEL_LEFT) {
+ xmin = MINAFRAMEF;
+ xmax = (float)(CFRA + 0.1f);
+ }
+ else {
+ xmin = (float)(CFRA - 0.1f);
+ xmax = MAXFRAMEF;
+ }
+
+ select_mode = selmodes_to_flagmodes(select_mode);
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* select strips on the side where most data occurs */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ /* check each strip to see if it is appropriate */
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ if (BKE_nlastrip_within_bounds(strip, xmin, xmax)) {
+ ACHANNEL_SET_FLAG(strip, select_mode, NLASTRIP_FLAG_SELECT);
+ }
+ }
+ }
+
+ /* Cleanup */
+ ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int nlaedit_select_leftright_exec(bContext *C, wmOperator *op)
{
- bAnimContext ac;
- short leftright = RNA_enum_get(op->ptr, "mode");
- short selectmode;
+ bAnimContext ac;
+ short leftright = RNA_enum_get(op->ptr, "mode");
+ short selectmode;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
- /* select mode is either replace (deselect all, then add) or add/extend */
- if (RNA_boolean_get(op->ptr, "extend"))
- selectmode = SELECT_INVERT;
- else
- selectmode = SELECT_REPLACE;
+ /* select mode is either replace (deselect all, then add) or add/extend */
+ if (RNA_boolean_get(op->ptr, "extend"))
+ selectmode = SELECT_INVERT;
+ else
+ selectmode = SELECT_REPLACE;
- /* if "test" mode is set, we don't have any info to set this with */
- if (leftright == NLAEDIT_LRSEL_TEST)
- return OPERATOR_CANCELLED;
+ /* if "test" mode is set, we don't have any info to set this with */
+ if (leftright == NLAEDIT_LRSEL_TEST)
+ return OPERATOR_CANCELLED;
- /* do the selecting now */
- nlaedit_select_leftright(C, &ac, leftright, selectmode);
+ /* do the selecting now */
+ nlaedit_select_leftright(C, &ac, leftright, selectmode);
- /* set notifier that keyframe selection (and channels too) have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
+ /* set notifier that keyframe selection (and channels too) have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int nlaedit_select_leftright_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bAnimContext ac;
- short leftright = RNA_enum_get(op->ptr, "mode");
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* handle mode-based testing */
- if (leftright == NLAEDIT_LRSEL_TEST) {
- Scene *scene = ac.scene;
- ARegion *ar = ac.ar;
- View2D *v2d = &ar->v2d;
- float x;
-
- /* determine which side of the current frame mouse is on */
- x = UI_view2d_region_to_view_x(v2d, event->mval[0]);
- if (x < CFRA)
- RNA_enum_set(op->ptr, "mode", NLAEDIT_LRSEL_LEFT);
- else
- RNA_enum_set(op->ptr, "mode", NLAEDIT_LRSEL_RIGHT);
- }
-
- /* perform selection */
- return nlaedit_select_leftright_exec(C, op);
+ bAnimContext ac;
+ short leftright = RNA_enum_get(op->ptr, "mode");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* handle mode-based testing */
+ if (leftright == NLAEDIT_LRSEL_TEST) {
+ Scene *scene = ac.scene;
+ ARegion *ar = ac.ar;
+ View2D *v2d = &ar->v2d;
+ float x;
+
+ /* determine which side of the current frame mouse is on */
+ x = UI_view2d_region_to_view_x(v2d, event->mval[0]);
+ if (x < CFRA)
+ RNA_enum_set(op->ptr, "mode", NLAEDIT_LRSEL_LEFT);
+ else
+ RNA_enum_set(op->ptr, "mode", NLAEDIT_LRSEL_RIGHT);
+ }
+
+ /* perform selection */
+ return nlaedit_select_leftright_exec(C, op);
}
void NLA_OT_select_leftright(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Select Left/Right";
- ot->idname = "NLA_OT_select_leftright";
- ot->description = "Select strips to the left or the right of the current frame";
+ /* identifiers */
+ ot->name = "Select Left/Right";
+ ot->idname = "NLA_OT_select_leftright";
+ ot->description = "Select strips to the left or the right of the current frame";
- /* api callbacks */
- ot->invoke = nlaedit_select_leftright_invoke;
- ot->exec = nlaedit_select_leftright_exec;
- ot->poll = ED_operator_nla_active;
+ /* api callbacks */
+ ot->invoke = nlaedit_select_leftright_invoke;
+ ot->exec = nlaedit_select_leftright_exec;
+ ot->poll = ED_operator_nla_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "mode", prop_nlaedit_leftright_select_types, NLAEDIT_LRSEL_TEST, "Mode", "");
- RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+ /* properties */
+ ot->prop = RNA_def_enum(
+ ot->srna, "mode", prop_nlaedit_leftright_select_types, NLAEDIT_LRSEL_TEST, "Mode", "");
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-
/* ******************** Mouse-Click Select Operator *********************** */
/* select strip directly under mouse */
static void mouse_nla_strips(bContext *C, bAnimContext *ac, const int mval[2], short select_mode)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale = NULL;
- int filter;
-
- SpaceNla *snla = (SpaceNla *)ac->sl;
- View2D *v2d = &ac->ar->v2d;
- Scene *scene = ac->scene;
- NlaStrip *strip = NULL;
- int channel_index;
- float xmin, xmax;
- float x, y;
-
-
- /* use View2D to determine the index of the channel
- * (i.e a row in the list) where keyframe was */
- UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
- UI_view2d_listview_view_to_cell(v2d, 0, NLACHANNEL_STEP(snla), 0, (float)NLACHANNEL_HEIGHT_HALF(snla), x, y, NULL, &channel_index);
-
- /* x-range to check is +/- 7 (in screen/region-space) on either side of mouse click
- * (that is the size of keyframe icons, so user should be expecting similar tolerances)
- */
- xmin = UI_view2d_region_to_view_x(v2d, mval[0] - 7);
- xmax = UI_view2d_region_to_view_x(v2d, mval[0] + 7);
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* try to get channel */
- ale = BLI_findlink(&anim_data, channel_index);
- if (ale == NULL) {
- /* channel not found */
- printf("Error: animation channel (index = %d) not found in mouse_nla_strips()\n", channel_index);
- ANIM_animdata_freelist(&anim_data);
- return;
- }
- else {
- /* found some channel - we only really should do something when its an Nla-Track */
- if (ale->type == ANIMTYPE_NLATRACK) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
-
- /* loop over NLA-strips in this track,
- * trying to find one which occurs in the necessary bounds */
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- if (BKE_nlastrip_within_bounds(strip, xmin, xmax))
- break;
- }
- }
-
- /* remove active channel from list of channels for separate treatment
- * (since it's needed later on) */
- BLI_remlink(&anim_data, ale);
-
- /* free list of channels, since it's not used anymore */
- ANIM_animdata_freelist(&anim_data);
- }
-
- /* if currently in tweakmode, exit tweakmode before changing selection states
- * now that we've found our target...
- */
- if (scene->flag & SCE_NLA_EDIT_ON)
- WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL);
-
- /* for replacing selection, firstly need to clear existing selection */
- if (select_mode == SELECT_REPLACE) {
- /* reset selection mode for next steps */
- select_mode = SELECT_ADD;
-
- /* deselect all strips */
- deselect_nla_strips(ac, 0, SELECT_SUBTRACT);
-
- /* deselect all other channels first */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
- }
-
- /* only select strip if we clicked on a valid channel and hit something */
- if (ale) {
- /* select the strip accordingly (if a matching one was found) */
- if (strip) {
- select_mode = selmodes_to_flagmodes(select_mode);
- ACHANNEL_SET_FLAG(strip, select_mode, NLASTRIP_FLAG_SELECT);
-
- /* if we selected it, we can make it active too
- * - we always need to clear the active strip flag though...
- * - as well as selecting its track...
- */
- deselect_nla_strips(ac, DESELECT_STRIPS_CLEARACTIVE, 0);
-
- if (strip->flag & NLASTRIP_FLAG_SELECT) {
- strip->flag |= NLASTRIP_FLAG_ACTIVE;
-
- /* Highlight NLA-Track */
- if (ale->type == ANIMTYPE_NLATRACK) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
-
- nlt->flag |= NLATRACK_SELECTED;
- ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK);
- }
- }
- }
-
- /* free this channel */
- MEM_freeN(ale);
- }
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale = NULL;
+ int filter;
+
+ SpaceNla *snla = (SpaceNla *)ac->sl;
+ View2D *v2d = &ac->ar->v2d;
+ Scene *scene = ac->scene;
+ NlaStrip *strip = NULL;
+ int channel_index;
+ float xmin, xmax;
+ float x, y;
+
+ /* use View2D to determine the index of the channel
+ * (i.e a row in the list) where keyframe was */
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
+ UI_view2d_listview_view_to_cell(v2d,
+ 0,
+ NLACHANNEL_STEP(snla),
+ 0,
+ (float)NLACHANNEL_HEIGHT_HALF(snla),
+ x,
+ y,
+ NULL,
+ &channel_index);
+
+ /* x-range to check is +/- 7 (in screen/region-space) on either side of mouse click
+ * (that is the size of keyframe icons, so user should be expecting similar tolerances)
+ */
+ xmin = UI_view2d_region_to_view_x(v2d, mval[0] - 7);
+ xmax = UI_view2d_region_to_view_x(v2d, mval[0] + 7);
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* try to get channel */
+ ale = BLI_findlink(&anim_data, channel_index);
+ if (ale == NULL) {
+ /* channel not found */
+ printf("Error: animation channel (index = %d) not found in mouse_nla_strips()\n",
+ channel_index);
+ ANIM_animdata_freelist(&anim_data);
+ return;
+ }
+ else {
+ /* found some channel - we only really should do something when its an Nla-Track */
+ if (ale->type == ANIMTYPE_NLATRACK) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+
+ /* loop over NLA-strips in this track,
+ * trying to find one which occurs in the necessary bounds */
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ if (BKE_nlastrip_within_bounds(strip, xmin, xmax))
+ break;
+ }
+ }
+
+ /* remove active channel from list of channels for separate treatment
+ * (since it's needed later on) */
+ BLI_remlink(&anim_data, ale);
+
+ /* free list of channels, since it's not used anymore */
+ ANIM_animdata_freelist(&anim_data);
+ }
+
+ /* if currently in tweakmode, exit tweakmode before changing selection states
+ * now that we've found our target...
+ */
+ if (scene->flag & SCE_NLA_EDIT_ON)
+ WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL);
+
+ /* for replacing selection, firstly need to clear existing selection */
+ if (select_mode == SELECT_REPLACE) {
+ /* reset selection mode for next steps */
+ select_mode = SELECT_ADD;
+
+ /* deselect all strips */
+ deselect_nla_strips(ac, 0, SELECT_SUBTRACT);
+
+ /* deselect all other channels first */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ }
+
+ /* only select strip if we clicked on a valid channel and hit something */
+ if (ale) {
+ /* select the strip accordingly (if a matching one was found) */
+ if (strip) {
+ select_mode = selmodes_to_flagmodes(select_mode);
+ ACHANNEL_SET_FLAG(strip, select_mode, NLASTRIP_FLAG_SELECT);
+
+ /* if we selected it, we can make it active too
+ * - we always need to clear the active strip flag though...
+ * - as well as selecting its track...
+ */
+ deselect_nla_strips(ac, DESELECT_STRIPS_CLEARACTIVE, 0);
+
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ strip->flag |= NLASTRIP_FLAG_ACTIVE;
+
+ /* Highlight NLA-Track */
+ if (ale->type == ANIMTYPE_NLATRACK) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+
+ nlt->flag |= NLATRACK_SELECTED;
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK);
+ }
+ }
+ }
+
+ /* free this channel */
+ MEM_freeN(ale);
+ }
}
/* ------------------- */
@@ -620,56 +624,56 @@ static void mouse_nla_strips(bContext *C, bAnimContext *ac, const int mval[2], s
/* handle clicking */
static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bAnimContext ac;
- /* Scene *scene; */ /* UNUSED */
- /* ARegion *ar; */ /* UNUSED */
- // View2D *v2d; /*UNUSED*/
- short selectmode;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get useful pointers from animation context data */
- /* scene= ac.scene; */ /* UNUSED */
- /* ar= ac.ar; */ /* UNUSED */
- // v2d= &ar->v2d;
-
- /* select mode is either replace (deselect all, then add) or add/extend */
- if (RNA_boolean_get(op->ptr, "extend"))
- selectmode = SELECT_INVERT;
- else
- selectmode = SELECT_REPLACE;
-
- /* select strips based upon mouse position */
- mouse_nla_strips(C, &ac, event->mval, selectmode);
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL);
-
- /* for tweak grab to work */
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ bAnimContext ac;
+ /* Scene *scene; */ /* UNUSED */
+ /* ARegion *ar; */ /* UNUSED */
+ // View2D *v2d; /*UNUSED*/
+ short selectmode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get useful pointers from animation context data */
+ /* scene= ac.scene; */ /* UNUSED */
+ /* ar= ac.ar; */ /* UNUSED */
+ // v2d= &ar->v2d;
+
+ /* select mode is either replace (deselect all, then add) or add/extend */
+ if (RNA_boolean_get(op->ptr, "extend"))
+ selectmode = SELECT_INVERT;
+ else
+ selectmode = SELECT_REPLACE;
+
+ /* select strips based upon mouse position */
+ mouse_nla_strips(C, &ac, event->mval, selectmode);
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL);
+
+ /* for tweak grab to work */
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
}
void NLA_OT_click_select(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Select";
- ot->idname = "NLA_OT_click_select";
- ot->description = "Handle clicks to select NLA Strips";
+ /* identifiers */
+ ot->name = "Select";
+ ot->idname = "NLA_OT_click_select";
+ ot->description = "Handle clicks to select NLA Strips";
- /* api callbacks - absolutely no exec() this yet... */
- ot->invoke = nlaedit_clickselect_invoke;
- ot->poll = ED_operator_nla_active;
+ /* api callbacks - absolutely no exec() this yet... */
+ ot->invoke = nlaedit_clickselect_invoke;
+ ot->poll = ED_operator_nla_active;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- /* properties */
- prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* *********************************************** */
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index 84b8a64bc62..ccf2e552644 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -21,7 +21,6 @@
* \ingroup spnla
*/
-
#include <string.h>
#include <stdio.h>
@@ -42,7 +41,6 @@
#include "ED_markers.h"
#include "ED_screen.h"
-
#include "WM_api.h"
#include "WM_types.h"
#include "WM_message.h"
@@ -59,619 +57,632 @@
ARegion *nla_has_buttons_region(ScrArea *sa)
{
- ARegion *ar, *arnew;
+ ARegion *ar, *arnew;
- ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
- if (ar) return ar;
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
+ if (ar)
+ return ar;
- /* add subdiv level; after main */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ /* add subdiv level; after main */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- /* is error! */
- if (ar == NULL) return NULL;
+ /* is error! */
+ if (ar == NULL)
+ return NULL;
- arnew = MEM_callocN(sizeof(ARegion), "buttons for nla");
+ arnew = MEM_callocN(sizeof(ARegion), "buttons for nla");
- BLI_insertlinkafter(&sa->regionbase, ar, arnew);
- arnew->regiontype = RGN_TYPE_UI;
- arnew->alignment = RGN_ALIGN_RIGHT;
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype = RGN_TYPE_UI;
+ arnew->alignment = RGN_ALIGN_RIGHT;
- arnew->flag = RGN_FLAG_HIDDEN;
+ arnew->flag = RGN_FLAG_HIDDEN;
- return arnew;
+ return arnew;
}
-
-
/* ******************** default callbacks for nla space ***************** */
static SpaceLink *nla_new(const ScrArea *sa, const Scene *scene)
{
- ARegion *ar;
- SpaceNla *snla;
+ ARegion *ar;
+ SpaceNla *snla;
- snla = MEM_callocN(sizeof(SpaceNla), "initnla");
- snla->spacetype = SPACE_NLA;
+ snla = MEM_callocN(sizeof(SpaceNla), "initnla");
+ snla->spacetype = SPACE_NLA;
- /* allocate DopeSheet data for NLA Editor */
- snla->ads = MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
- snla->ads->source = (ID *)scene;
+ /* allocate DopeSheet data for NLA Editor */
+ snla->ads = MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
+ snla->ads->source = (ID *)scene;
- /* set auto-snapping settings */
- snla->autosnap = SACTSNAP_FRAME;
+ /* set auto-snapping settings */
+ snla->autosnap = SACTSNAP_FRAME;
- /* header */
- ar = MEM_callocN(sizeof(ARegion), "header for nla");
+ /* header */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_HEADER;
+ ar->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;
+ /* 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;
- /* 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;
+ /* 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;
- /* ui buttons */
- ar = MEM_callocN(sizeof(ARegion), "buttons region for nla");
+ /* ui buttons */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_UI;
+ ar->alignment = RGN_ALIGN_RIGHT;
+ ar->flag = RGN_FLAG_HIDDEN;
- /* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for nla");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for nla");
- BLI_addtail(&snla->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&snla->regionbase, ar);
+ ar->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;
+ 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;
- ar->v2d.cur = ar->v2d.tot;
+ ar->v2d.cur = ar->v2d.tot;
- ar->v2d.min[0] = 0.0f;
- ar->v2d.min[1] = 0.0f;
+ ar->v2d.min[0] = 0.0f;
+ ar->v2d.min[1] = 0.0f;
- ar->v2d.max[0] = MAXFRAMEF;
- ar->v2d.max[1] = 10000.0f;
+ ar->v2d.max[0] = MAXFRAMEF;
+ ar->v2d.max[1] = 10000.0f;
- ar->v2d.minzoom = 0.01f;
- ar->v2d.maxzoom = 50;
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
- 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;
+ ar->v2d.minzoom = 0.01f;
+ ar->v2d.maxzoom = 50;
+ ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
+ 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;
- return (SpaceLink *)snla;
+ return (SpaceLink *)snla;
}
/* not spacelink itself */
static void nla_free(SpaceLink *sl)
{
- SpaceNla *snla = (SpaceNla *) sl;
+ SpaceNla *snla = (SpaceNla *)sl;
- if (snla->ads) {
- BLI_freelistN(&snla->ads->chanbase);
- MEM_freeN(snla->ads);
- }
+ if (snla->ads) {
+ BLI_freelistN(&snla->ads->chanbase);
+ MEM_freeN(snla->ads);
+ }
}
-
/* spacetype; init callback */
static void nla_init(struct wmWindowManager *wm, ScrArea *sa)
{
- SpaceNla *snla = (SpaceNla *)sa->spacedata.first;
+ SpaceNla *snla = (SpaceNla *)sa->spacedata.first;
- /* init dopesheet data if non-existent (i.e. for old files) */
- if (snla->ads == NULL) {
- snla->ads = MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
- snla->ads->source = (ID *)WM_window_get_active_scene(wm->winactive);
- }
+ /* init dopesheet data if non-existent (i.e. for old files) */
+ if (snla->ads == NULL) {
+ snla->ads = MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
+ snla->ads->source = (ID *)WM_window_get_active_scene(wm->winactive);
+ }
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(sa);
}
static SpaceLink *nla_duplicate(SpaceLink *sl)
{
- SpaceNla *snlan = MEM_dupallocN(sl);
+ SpaceNla *snlan = MEM_dupallocN(sl);
- /* clear or remove stuff from old */
- snlan->ads = MEM_dupallocN(snlan->ads);
+ /* clear or remove stuff from old */
+ snlan->ads = MEM_dupallocN(snlan->ads);
- return (SpaceLink *)snlan;
+ return (SpaceLink *)snlan;
}
/* add handlers, stuff you only do once or on area/region changes */
static void nla_channel_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- /* ensure the 2d view sync works - main region has bottom scroller */
- ar->v2d.scroll = V2D_SCROLL_BOTTOM;
+ /* ensure the 2d view sync works - main region has bottom scroller */
+ ar->v2d.scroll = V2D_SCROLL_BOTTOM;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->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_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- /* 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_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ /* 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_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ /* 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_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- keymap = WM_keymap_ensure(wm->defaultconf, "NLA Generic", SPACE_NLA, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "NLA Generic", SPACE_NLA, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
/* draw entirely, view changes should be handled here */
static void nla_channel_region_draw(const bContext *C, ARegion *ar)
{
- bAnimContext ac;
- View2D *v2d = &ar->v2d;
- View2DScrollers *scrollers;
+ bAnimContext ac;
+ View2D *v2d = &ar->v2d;
+ View2DScrollers *scrollers;
- /* clear and setup matrix */
- UI_ThemeClearColor(TH_BACK);
- GPU_clear(GPU_COLOR_BIT);
+ /* clear and setup matrix */
+ UI_ThemeClearColor(TH_BACK);
+ GPU_clear(GPU_COLOR_BIT);
- UI_view2d_view_ortho(v2d);
+ UI_view2d_view_ortho(v2d);
- /* data */
- if (ANIM_animdata_get_context(C, &ac)) {
- draw_nla_channel_list(C, &ac, ar);
- }
+ /* data */
+ if (ANIM_animdata_get_context(C, &ac)) {
+ draw_nla_channel_list(C, &ac, ar);
+ }
- /* reset view matrix */
- UI_view2d_view_restore(C);
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
- /* scrollers */
- scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
+ /* scrollers */
+ scrollers = UI_view2d_scrollers_calc(
+ C, v2d, NULL, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
}
-
/* add handlers, stuff you only do once or on area/region changes */
static void nla_main_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
- /* own keymap */
- keymap = WM_keymap_ensure(wm->defaultconf, "NLA Editor", SPACE_NLA, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- keymap = WM_keymap_ensure(wm->defaultconf, "NLA Generic", SPACE_NLA, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ /* own keymap */
+ keymap = WM_keymap_ensure(wm->defaultconf, "NLA Editor", SPACE_NLA, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "NLA Generic", SPACE_NLA, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
}
static void nla_main_region_draw(const bContext *C, ARegion *ar)
{
- /* 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;
- View2DGrid *grid;
- View2DScrollers *scrollers;
- short unit = 0, cfra_flag = 0;
-
- /* clear and setup matrix */
- UI_ThemeClearColor(TH_BACK);
- GPU_clear(GPU_COLOR_BIT);
-
- UI_view2d_view_ortho(v2d);
-
- /* time grid */
- unit = (snla->flag & SNLA_DRAWTIME) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES;
- grid = UI_view2d_grid_calc(CTX_data_scene(C), v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY, ar->winx, ar->winy);
- UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL);
- UI_view2d_grid_free(grid);
-
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
-
- /* start and end frame */
- ANIM_draw_framerange(scene, v2d);
-
- /* data */
- if (ANIM_animdata_get_context(C, &ac)) {
- /* strips and backdrops */
- draw_nla_main_data(&ac, snla, ar);
-
- /* text draw cached, in pixelspace now */
- UI_view2d_text_cache_draw(ar);
- }
-
- UI_view2d_view_ortho(v2d);
-
- /* current frame */
- if (snla->flag & SNLA_DRAWTIME) 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 (snla->flag & SNLA_SHOW_MARKER_LINES) marker_draw_flag |= DRAW_MARKERS_LINES;
- ED_markers_draw(C, marker_draw_flag);
-
- /* preview range */
- UI_view2d_view_ortho(v2d);
- ANIM_draw_previewrange(C, v2d, 0);
-
- /* callback */
- UI_view2d_view_ortho(v2d);
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
-
- /* reset view matrix */
- UI_view2d_view_restore(C);
-
- /* scrollers */
- scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
-
- /* draw current frame number-indicator on top of scrollers */
- if ((snla->flag & SNLA_NODRAWCFRANUM) == 0) {
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- ANIM_draw_cfra_number(C, v2d, cfra_flag);
- }
+ /* 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;
+ View2DGrid *grid;
+ View2DScrollers *scrollers;
+ short unit = 0, cfra_flag = 0;
+
+ /* clear and setup matrix */
+ UI_ThemeClearColor(TH_BACK);
+ GPU_clear(GPU_COLOR_BIT);
+
+ UI_view2d_view_ortho(v2d);
+
+ /* time grid */
+ unit = (snla->flag & SNLA_DRAWTIME) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES;
+ grid = UI_view2d_grid_calc(CTX_data_scene(C),
+ v2d,
+ unit,
+ V2D_GRID_CLAMP,
+ V2D_ARG_DUMMY,
+ V2D_ARG_DUMMY,
+ ar->winx,
+ ar->winy);
+ UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL);
+ UI_view2d_grid_free(grid);
+
+ ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
+
+ /* start and end frame */
+ ANIM_draw_framerange(scene, v2d);
+
+ /* data */
+ if (ANIM_animdata_get_context(C, &ac)) {
+ /* strips and backdrops */
+ draw_nla_main_data(&ac, snla, ar);
+
+ /* text draw cached, in pixelspace now */
+ UI_view2d_text_cache_draw(ar);
+ }
+
+ UI_view2d_view_ortho(v2d);
+
+ /* current frame */
+ if (snla->flag & SNLA_DRAWTIME)
+ 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 (snla->flag & SNLA_SHOW_MARKER_LINES)
+ marker_draw_flag |= DRAW_MARKERS_LINES;
+ ED_markers_draw(C, marker_draw_flag);
+
+ /* preview range */
+ UI_view2d_view_ortho(v2d);
+ ANIM_draw_previewrange(C, v2d, 0);
+
+ /* callback */
+ UI_view2d_view_ortho(v2d);
+ ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ scrollers = UI_view2d_scrollers_calc(
+ C, v2d, NULL, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+
+ /* draw current frame number-indicator on top of scrollers */
+ if ((snla->flag & SNLA_NODRAWCFRANUM) == 0) {
+ UI_view2d_view_orthoSpecial(ar, v2d, 1);
+ ANIM_draw_cfra_number(C, v2d, cfra_flag);
+ }
}
-
/* add handlers, stuff you only do once or on area/region changes */
static void nla_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
- ED_region_header_init(ar);
+ ED_region_header_init(ar);
}
static void nla_header_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_header(C, ar);
+ ED_region_header(C, ar);
}
/* add handlers, stuff you only do once or on area/region changes */
static void nla_buttons_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, ar);
- keymap = WM_keymap_ensure(wm->defaultconf, "NLA Generic", SPACE_NLA, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "NLA Generic", SPACE_NLA, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
static void nla_buttons_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, ar);
}
-static void nla_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void nla_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_ANIMATION:
- ED_region_tag_redraw(ar);
- break;
- case NC_SCENE:
- switch (wmn->data) {
- case ND_OB_ACTIVE:
- case ND_FRAME:
- case ND_MARKERS:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_OBJECT:
- switch (wmn->data) {
- case ND_BONE_ACTIVE:
- case ND_BONE_SELECT:
- case ND_KEYS:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- default:
- if (wmn->data == ND_KEYS)
- ED_region_tag_redraw(ar);
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_ANIMATION:
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_OB_ACTIVE:
+ case ND_FRAME:
+ case ND_MARKERS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch (wmn->data) {
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_KEYS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ default:
+ if (wmn->data == ND_KEYS)
+ ED_region_tag_redraw(ar);
+ break;
+ }
}
-
-static void nla_main_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void nla_main_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_ANIMATION:
- ED_region_tag_redraw(ar);
- break;
- case NC_SCENE:
- switch (wmn->data) {
- case ND_RENDER_OPTIONS:
- case ND_OB_ACTIVE:
- case ND_FRAME:
- case ND_FRAME_RANGE:
- case ND_MARKERS:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_OBJECT:
- switch (wmn->data) {
- case ND_BONE_ACTIVE:
- case ND_BONE_SELECT:
- case ND_KEYS:
- case ND_TRANSFORM:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_NODE:
- switch (wmn->action) {
- case NA_EDITED:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_ID:
- if (wmn->action == NA_RENAME)
- ED_region_tag_redraw(ar);
- break;
- case NC_SCREEN:
- if (ELEM(wmn->data, ND_LAYER)) {
- ED_region_tag_redraw(ar);
- }
- break;
- default:
- if (wmn->data == ND_KEYS)
- ED_region_tag_redraw(ar);
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_ANIMATION:
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_RENDER_OPTIONS:
+ case ND_OB_ACTIVE:
+ case ND_FRAME:
+ case ND_FRAME_RANGE:
+ case ND_MARKERS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch (wmn->data) {
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_KEYS:
+ case ND_TRANSFORM:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_NODE:
+ switch (wmn->action) {
+ case NA_EDITED:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_ID:
+ if (wmn->action == NA_RENAME)
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_SCREEN:
+ if (ELEM(wmn->data, ND_LAYER)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ default:
+ if (wmn->data == ND_KEYS)
+ ED_region_tag_redraw(ar);
+ break;
+ }
}
-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 wmMsgBus *mbus)
+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 wmMsgBus *mbus)
{
- PointerRNA ptr;
- RNA_pointer_create(&screen->id, &RNA_SpaceNLA, sa->spacedata.first, &ptr);
-
- wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
- .notify = ED_region_do_msg_notify_tag_redraw,
- };
-
- /* Timeline depends on scene properties. */
- {
- bool use_preview = (scene->r.flag & SCER_PRV_RANGE);
- extern PropertyRNA rna_Scene_frame_start;
- extern PropertyRNA rna_Scene_frame_end;
- extern PropertyRNA rna_Scene_frame_preview_start;
- extern PropertyRNA rna_Scene_frame_preview_end;
- extern PropertyRNA rna_Scene_use_preview_range;
- extern PropertyRNA rna_Scene_frame_current;
- const PropertyRNA *props[] = {
- use_preview ? &rna_Scene_frame_preview_start : &rna_Scene_frame_start,
- use_preview ? &rna_Scene_frame_preview_end : &rna_Scene_frame_end,
- &rna_Scene_use_preview_range,
- &rna_Scene_frame_current,
- };
-
- PointerRNA idptr;
- RNA_id_pointer_create(&scene->id, &idptr);
-
- for (int i = 0; i < ARRAY_SIZE(props); i++) {
- WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__);
- }
- }
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_SpaceNLA, sa->spacedata.first, &ptr);
+
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ /* Timeline depends on scene properties. */
+ {
+ bool use_preview = (scene->r.flag & SCER_PRV_RANGE);
+ extern PropertyRNA rna_Scene_frame_start;
+ extern PropertyRNA rna_Scene_frame_end;
+ extern PropertyRNA rna_Scene_frame_preview_start;
+ extern PropertyRNA rna_Scene_frame_preview_end;
+ extern PropertyRNA rna_Scene_use_preview_range;
+ extern PropertyRNA rna_Scene_frame_current;
+ const PropertyRNA *props[] = {
+ use_preview ? &rna_Scene_frame_preview_start : &rna_Scene_frame_start,
+ use_preview ? &rna_Scene_frame_preview_end : &rna_Scene_frame_end,
+ &rna_Scene_use_preview_range,
+ &rna_Scene_frame_current,
+ };
+
+ PointerRNA idptr;
+ RNA_id_pointer_create(&scene->id, &idptr);
+
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__);
+ }
+ }
}
-static void nla_channel_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void nla_channel_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_ANIMATION:
- ED_region_tag_redraw(ar);
- break;
- case NC_SCENE:
- switch (wmn->data) {
- case ND_OB_ACTIVE:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_OBJECT:
- switch (wmn->data) {
- case ND_BONE_ACTIVE:
- case ND_BONE_SELECT:
- case ND_KEYS:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_ID:
- if (wmn->action == NA_RENAME)
- ED_region_tag_redraw(ar);
- break;
- default:
- if (wmn->data == ND_KEYS)
- ED_region_tag_redraw(ar);
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_ANIMATION:
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_OB_ACTIVE:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch (wmn->data) {
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_KEYS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_ID:
+ if (wmn->action == NA_RENAME)
+ ED_region_tag_redraw(ar);
+ break;
+ default:
+ if (wmn->data == ND_KEYS)
+ ED_region_tag_redraw(ar);
+ break;
+ }
}
-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 wmMsgBus *mbus)
+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 wmMsgBus *mbus)
{
- PointerRNA ptr;
- RNA_pointer_create(&screen->id, &RNA_SpaceNLA, sa->spacedata.first, &ptr);
-
- wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
- .notify = ED_region_do_msg_notify_tag_redraw,
- };
-
- /* All dopesheet filter settings, etc. affect the drawing of this editor,
- * so just whitelist the entire struct for updates
- */
- {
- wmMsgParams_RNA msg_key_params = {{{0}}};
- StructRNA *type_array[] = {
- &RNA_DopeSheet,
- };
-
- for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
- msg_key_params.ptr.type = type_array[i];
- WM_msg_subscribe_rna_params(
- mbus,
- &msg_key_params,
- &msg_sub_value_region_tag_redraw,
- __func__);
- }
- }
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_SpaceNLA, sa->spacedata.first, &ptr);
+
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ /* All dopesheet filter settings, etc. affect the drawing of this editor,
+ * so just whitelist the entire struct for updates
+ */
+ {
+ wmMsgParams_RNA msg_key_params = {{{0}}};
+ StructRNA *type_array[] = {
+ &RNA_DopeSheet,
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
+ msg_key_params.ptr.type = type_array[i];
+ WM_msg_subscribe_rna_params(
+ mbus, &msg_key_params, &msg_sub_value_region_tag_redraw, __func__);
+ }
+ }
}
/* editor level listener */
static void nla_listener(wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_ANIMATION:
- // TODO: filter specific types of changes?
- ED_area_tag_refresh(sa);
- break;
- case NC_SCENE:
+ /* context changes */
+ switch (wmn->category) {
+ case NC_ANIMATION:
+ // TODO: filter specific types of changes?
+ ED_area_tag_refresh(sa);
+ break;
+ case NC_SCENE:
#if 0
- switch (wmn->data) {
- case ND_OB_ACTIVE:
- case ND_OB_SELECT:
- ED_area_tag_refresh(sa);
- break;
- }
+ switch (wmn->data) {
+ case ND_OB_ACTIVE:
+ case ND_OB_SELECT:
+ ED_area_tag_refresh(sa);
+ break;
+ }
#endif
- ED_area_tag_refresh(sa);
- break;
- case NC_OBJECT:
- switch (wmn->data) {
- case ND_TRANSFORM:
- /* do nothing */
- break;
- default:
- ED_area_tag_refresh(sa);
- break;
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_NLA)
- ED_area_tag_redraw(sa);
- break;
- }
+ ED_area_tag_refresh(sa);
+ break;
+ case NC_OBJECT:
+ switch (wmn->data) {
+ case ND_TRANSFORM:
+ /* do nothing */
+ break;
+ default:
+ ED_area_tag_refresh(sa);
+ break;
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_NLA)
+ ED_area_tag_redraw(sa);
+ break;
+ }
}
static void nla_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
{
- SpaceNla *snla = (SpaceNla *)slink;
-
- if (snla->ads) {
- if ((ID *)snla->ads->filter_grp == old_id) {
- snla->ads->filter_grp = (Collection *)new_id;
- }
- if ((ID *)snla->ads->source == old_id) {
- snla->ads->source = new_id;
- }
- }
+ SpaceNla *snla = (SpaceNla *)slink;
+
+ if (snla->ads) {
+ if ((ID *)snla->ads->filter_grp == old_id) {
+ snla->ads->filter_grp = (Collection *)new_id;
+ }
+ if ((ID *)snla->ads->source == old_id) {
+ snla->ads->source = new_id;
+ }
+ }
}
/* only called once, from space/spacetypes.c */
void ED_spacetype_nla(void)
{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype nla");
- ARegionType *art;
-
- st->spaceid = SPACE_NLA;
- strncpy(st->name, "NLA", BKE_ST_MAXNAME);
-
- st->new = nla_new;
- st->free = nla_free;
- st->init = nla_init;
- st->duplicate = nla_duplicate;
- st->operatortypes = nla_operatortypes;
- st->listener = nla_listener;
- st->keymap = nla_keymap;
- st->id_remap = nla_id_remap;
-
- /* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype nla region");
- art->regionid = RGN_TYPE_WINDOW;
- art->init = nla_main_region_init;
- art->draw = nla_main_region_draw;
- art->listener = nla_main_region_listener;
- art->message_subscribe = nla_main_region_message_subscribe;
- art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype nla region");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
-
- art->init = nla_header_region_init;
- art->draw = nla_header_region_draw;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: channels */
- art = MEM_callocN(sizeof(ARegionType), "spacetype nla region");
- art->regionid = RGN_TYPE_CHANNELS;
- art->prefsizex = 200;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES;
-
- art->init = nla_channel_region_init;
- art->draw = nla_channel_region_draw;
- art->listener = nla_channel_region_listener;
- art->message_subscribe = nla_channel_region_message_subscribe;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: UI buttons */
- art = MEM_callocN(sizeof(ARegionType), "spacetype nla region");
- art->regionid = RGN_TYPE_UI;
- art->prefsizex = 200;
- art->keymapflag = ED_KEYMAP_UI;
- art->listener = nla_region_listener;
- art->init = nla_buttons_region_init;
- art->draw = nla_buttons_region_draw;
-
- BLI_addhead(&st->regiontypes, art);
-
- nla_buttons_register(art);
-
-
- BKE_spacetype_register(st);
+ SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype nla");
+ ARegionType *art;
+
+ st->spaceid = SPACE_NLA;
+ strncpy(st->name, "NLA", BKE_ST_MAXNAME);
+
+ st->new = nla_new;
+ st->free = nla_free;
+ st->init = nla_init;
+ st->duplicate = nla_duplicate;
+ st->operatortypes = nla_operatortypes;
+ st->listener = nla_listener;
+ st->keymap = nla_keymap;
+ st->id_remap = nla_id_remap;
+
+ /* regions: main window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype nla region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init = nla_main_region_init;
+ art->draw = nla_main_region_draw;
+ art->listener = nla_main_region_listener;
+ art->message_subscribe = nla_main_region_message_subscribe;
+ art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype nla region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = HEADERY;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
+
+ art->init = nla_header_region_init;
+ art->draw = nla_header_region_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: channels */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype nla region");
+ art->regionid = RGN_TYPE_CHANNELS;
+ art->prefsizex = 200;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES;
+
+ art->init = nla_channel_region_init;
+ art->draw = nla_channel_region_draw;
+ art->listener = nla_channel_region_listener;
+ art->message_subscribe = nla_channel_region_message_subscribe;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: UI buttons */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype nla region");
+ art->regionid = RGN_TYPE_UI;
+ art->prefsizex = 200;
+ art->keymapflag = ED_KEYMAP_UI;
+ art->listener = nla_region_listener;
+ art->init = nla_buttons_region_init;
+ art->draw = nla_buttons_region_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ nla_buttons_register(art);
+
+ BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt
index 5e2437c99ca..df1b7c03aab 100644
--- a/source/blender/editors/space_node/CMakeLists.txt
+++ b/source/blender/editors/space_node/CMakeLists.txt
@@ -16,59 +16,59 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenfont
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../depsgraph
- ../../imbuf
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../nodes
- ../../render/extern/include
- ../../windowmanager
- ../../compositor
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenfont
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../depsgraph
+ ../../imbuf
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../nodes
+ ../../render/extern/include
+ ../../windowmanager
+ ../../compositor
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- drawnode.c
- node_add.c
- node_buttons.c
- node_draw.c
- node_edit.c
- node_gizmo.c
- node_group.c
- node_ops.c
- node_relationships.c
- node_select.c
- node_templates.c
- node_toolbar.c
- node_view.c
- space_node.c
+ drawnode.c
+ node_add.c
+ node_buttons.c
+ node_draw.c
+ node_edit.c
+ node_gizmo.c
+ node_group.c
+ node_ops.c
+ node_relationships.c
+ node_select.c
+ node_templates.c
+ node_toolbar.c
+ node_view.c
+ space_node.c
- node_intern.h
+ node_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
- bf_editor_screen
+ bf_blenkernel
+ bf_blenlib
+ bf_editor_screen
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
if(WITH_COMPOSITOR)
- add_definitions(-DWITH_COMPOSITOR)
+ add_definitions(-DWITH_COMPOSITOR)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index be26f67b936..7072f34ee4d 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -65,93 +65,95 @@
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
-#include "node_intern.h" /* own include */
+#include "node_intern.h" /* own include */
#include "NOD_composite.h"
#include "NOD_shader.h"
#include "NOD_texture.h"
-
/* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */
-static void node_socket_button_label(bContext *UNUSED(C), uiLayout *layout, PointerRNA *UNUSED(ptr), PointerRNA *UNUSED(node_ptr),
+static void node_socket_button_label(bContext *UNUSED(C),
+ uiLayout *layout,
+ PointerRNA *UNUSED(ptr),
+ PointerRNA *UNUSED(node_ptr),
const char *text)
{
- uiItemL(layout, text, 0);
+ uiItemL(layout, text, 0);
}
/* ****************** BUTTON CALLBACKS FOR ALL TREES ***************** */
static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- bNode *node = ptr->data;
- /* first output stores value */
- bNodeSocket *output = node->outputs.first;
- PointerRNA sockptr;
- RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr);
+ bNode *node = ptr->data;
+ /* first output stores value */
+ bNodeSocket *output = node->outputs.first;
+ PointerRNA sockptr;
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr);
- uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE);
+ uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE);
}
static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- bNode *node = ptr->data;
- /* first output stores value */
- bNodeSocket *output = node->outputs.first;
- PointerRNA sockptr;
- uiLayout *col;
- RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr);
+ bNode *node = ptr->data;
+ /* first output stores value */
+ bNodeSocket *output = node->outputs.first;
+ PointerRNA sockptr;
+ uiLayout *col;
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr);
- col = uiLayoutColumn(layout, false);
- uiTemplateColorPicker(col, &sockptr, "default_value", 1, 0, 0, 0);
- uiItemR(col, &sockptr, "default_value", UI_ITEM_R_SLIDER, "", ICON_NONE);
+ col = uiLayoutColumn(layout, false);
+ uiTemplateColorPicker(col, &sockptr, "default_value", 1, 0, 0, 0);
+ uiItemR(col, &sockptr, "default_value", UI_ITEM_R_SLIDER, "", ICON_NONE);
}
static void node_buts_mix_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *row, *col;
+ uiLayout *row, *col;
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- col = uiLayoutColumn(layout, false);
- row = uiLayoutRow(col, true);
- uiItemR(row, ptr, "blend_type", 0, "", ICON_NONE);
- if (ELEM(ntree->type, NTREE_COMPOSIT, NTREE_TEXTURE)) {
- uiItemR(row, ptr, "use_alpha", 0, "", ICON_IMAGE_RGB_ALPHA);
- }
+ col = uiLayoutColumn(layout, false);
+ row = uiLayoutRow(col, true);
+ uiItemR(row, ptr, "blend_type", 0, "", ICON_NONE);
+ if (ELEM(ntree->type, NTREE_COMPOSIT, NTREE_TEXTURE)) {
+ uiItemR(row, ptr, "use_alpha", 0, "", ICON_IMAGE_RGB_ALPHA);
+ }
- uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE);
}
static void node_buts_time(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *row;
+ uiLayout *row;
#if 0
- /* XXX no context access here .. */
- bNode *node = ptr->data;
- CurveMapping *cumap = node->storage;
-
- if (cumap) {
- cumap->flag |= CUMA_DRAW_CFRA;
- if (node->custom1 < node->custom2)
- cumap->sample[0] = (float)(CFRA - node->custom1) / (float)(node->custom2 - node->custom1);
- }
+ /* XXX no context access here .. */
+ bNode *node = ptr->data;
+ CurveMapping *cumap = node->storage;
+
+ if (cumap) {
+ cumap->flag |= CUMA_DRAW_CFRA;
+ if (node->custom1 < node->custom2)
+ cumap->sample[0] = (float)(CFRA - node->custom1) / (float)(node->custom2 - node->custom1);
+ }
#endif
- uiTemplateCurveMapping(layout, ptr, "curve", 's', false, false, false, false);
+ 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);
+ row = uiLayoutRow(layout, true);
+ uiItemR(row, ptr, "frame_start", 0, IFACE_("Sta"), ICON_NONE);
+ uiItemR(row, ptr, "frame_end", 0, IFACE_("End"), ICON_NONE);
}
static void node_buts_colorramp(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiTemplateColorRamp(layout, ptr, "color_ramp", 0);
+ uiTemplateColorRamp(layout, ptr, "color_ramp", 0);
}
static void node_buts_curvevec(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiTemplateCurveMapping(layout, ptr, "mapping", 'v', false, false, false, false);
+ uiTemplateCurveMapping(layout, ptr, "mapping", 'v', false, false, false, false);
}
#define SAMPLE_FLT_ISNONE FLT_MAX
@@ -159,133 +161,128 @@ static void node_buts_curvevec(uiLayout *layout, bContext *UNUSED(C), PointerRNA
static float _sample_col[4] = {SAMPLE_FLT_ISNONE};
void ED_node_sample_set(const float col[4])
{
- if (col) {
- copy_v4_v4(_sample_col, col);
- }
- else {
- copy_v4_fl(_sample_col, SAMPLE_FLT_ISNONE);
- }
+ if (col) {
+ copy_v4_v4(_sample_col, col);
+ }
+ else {
+ copy_v4_fl(_sample_col, SAMPLE_FLT_ISNONE);
+ }
}
static void node_buts_curvecol(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- bNode *node = ptr->data;
- CurveMapping *cumap = node->storage;
+ bNode *node = ptr->data;
+ CurveMapping *cumap = node->storage;
- if (_sample_col[0] != SAMPLE_FLT_ISNONE) {
- cumap->flag |= CUMA_DRAW_SAMPLE;
- copy_v3_v3(cumap->sample, _sample_col);
- }
- else {
- cumap->flag &= ~CUMA_DRAW_SAMPLE;
- }
+ if (_sample_col[0] != SAMPLE_FLT_ISNONE) {
+ cumap->flag |= CUMA_DRAW_SAMPLE;
+ copy_v3_v3(cumap->sample, _sample_col);
+ }
+ else {
+ cumap->flag &= ~CUMA_DRAW_SAMPLE;
+ }
- uiTemplateCurveMapping(layout, ptr, "mapping", 'c', false, false, false, true);
+ uiTemplateCurveMapping(layout, ptr, "mapping", 'c', false, false, false, true);
}
static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- bNode *node = ptr->data;
- /* first output stores normal */
- bNodeSocket *output = node->outputs.first;
- PointerRNA sockptr;
- RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr);
+ bNode *node = ptr->data;
+ /* first output stores normal */
+ bNodeSocket *output = node->outputs.first;
+ PointerRNA sockptr;
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr);
- uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE);
+ uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE);
}
#if 0 /* not used in 2.5x yet */
static void node_browse_tex_cb(bContext *C, void *ntree_v, void *node_v)
{
- Main *bmain = CTX_data_main(C);
- bNodeTree *ntree = ntree_v;
- bNode *node = node_v;
- Tex *tex;
+ Main *bmain = CTX_data_main(C);
+ bNodeTree *ntree = ntree_v;
+ bNode *node = node_v;
+ Tex *tex;
- if (node->menunr < 1) return;
+ if (node->menunr < 1) return;
- if (node->id) {
- id_us_min(node->id);
- node->id = NULL;
- }
- tex = BLI_findlink(&bmain->tex, node->menunr - 1);
+ if (node->id) {
+ id_us_min(node->id);
+ node->id = NULL;
+ }
+ tex = BLI_findlink(&bmain->tex, node->menunr - 1);
- node->id = &tex->id;
- id_us_plus(node->id);
- BLI_strncpy(node->name, node->id->name + 2, sizeof(node->name));
+ node->id = &tex->id;
+ id_us_plus(node->id);
+ BLI_strncpy(node->name, node->id->name + 2, sizeof(node->name));
- nodeSetActive(ntree, node);
+ nodeSetActive(ntree, node);
- if (ntree->type == NTREE_TEXTURE)
- ntreeTexCheckCyclics(ntree);
+ if (ntree->type == NTREE_TEXTURE)
+ ntreeTexCheckCyclics(ntree);
- // allqueue(REDRAWBUTSSHADING, 0);
- // allqueue(REDRAWNODE, 0);
- NodeTagChanged(ntree, node);
+ // allqueue(REDRAWBUTSSHADING, 0);
+ // allqueue(REDRAWNODE, 0);
+ NodeTagChanged(ntree, node);
- node->menunr = 0;
+ node->menunr = 0;
}
#endif
static void node_buts_texture(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- bNode *node = ptr->data;
+ bNode *node = ptr->data;
- short multi = (
- node->id &&
- ((Tex *)node->id)->use_nodes &&
- (node->type != CMP_NODE_TEXTURE) &&
- (node->type != TEX_NODE_TEXTURE)
- );
+ 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", 0, "", ICON_NONE);
- if (multi) {
- /* Number Drawing not optimal here, better have a list*/
- uiItemR(layout, ptr, "node_output", 0, "", ICON_NONE);
- }
+ if (multi) {
+ /* Number Drawing not optimal here, better have a list*/
+ uiItemR(layout, ptr, "node_output", 0, "", 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", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "use_clamp", 0, NULL, ICON_NONE);
}
static int node_resize_area_default(bNode *node, int x, int y)
{
- if (node->flag & NODE_HIDDEN) {
- rctf totr = node->totr;
- /* right part of node */
- totr.xmin = node->totr.xmax - 20.0f;
- if (BLI_rctf_isect_pt(&totr, x, y)) {
- return NODE_RESIZE_RIGHT;
- }
- else {
- return 0;
- }
- }
- else {
- const float size = NODE_RESIZE_MARGIN;
- rctf totr = node->totr;
- int dir = 0;
-
- if (x >= totr.xmax - size && x < totr.xmax && y >= totr.ymin && y < totr.ymax) {
- dir |= NODE_RESIZE_RIGHT;
- }
- if (x >= totr.xmin && x < totr.xmin + size && y >= totr.ymin && y < totr.ymax) {
- dir |= NODE_RESIZE_LEFT;
- }
- return dir;
- }
+ if (node->flag & NODE_HIDDEN) {
+ rctf totr = node->totr;
+ /* right part of node */
+ totr.xmin = node->totr.xmax - 20.0f;
+ if (BLI_rctf_isect_pt(&totr, x, y)) {
+ return NODE_RESIZE_RIGHT;
+ }
+ else {
+ return 0;
+ }
+ }
+ else {
+ const float size = NODE_RESIZE_MARGIN;
+ rctf totr = node->totr;
+ int dir = 0;
+
+ if (x >= totr.xmax - size && x < totr.xmax && y >= totr.ymin && y < totr.ymax) {
+ dir |= NODE_RESIZE_RIGHT;
+ }
+ if (x >= totr.xmin && x < totr.xmin + size && y >= totr.ymin && y < totr.ymax) {
+ dir |= NODE_RESIZE_LEFT;
+ }
+ return dir;
+ }
}
/* ****************** BUTTON CALLBACKS FOR COMMON NODES ***************** */
-
static void node_draw_buttons_group(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- uiTemplateIDBrowse(layout, C, ptr, "node_tree", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ uiTemplateIDBrowse(layout, C, ptr, "node_tree", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL);
}
/* XXX Does a bounding box update by iterating over all children.
@@ -294,318 +291,336 @@ static void node_draw_buttons_group(uiLayout *layout, bContext *C, PointerRNA *p
*/
static void node_draw_frame_prepare(const bContext *UNUSED(C), bNodeTree *ntree, bNode *node)
{
- const float margin = 1.5f * U.widget_unit;
- NodeFrame *data = (NodeFrame *)node->storage;
- bool bbinit;
- bNode *tnode;
- rctf rect, noderect;
- float xmax, ymax;
-
- /* init rect from current frame size */
- node_to_view(node, node->offsetx, node->offsety, &rect.xmin, &rect.ymax);
- node_to_view(node, node->offsetx + node->width, node->offsety - node->height, &rect.xmax, &rect.ymin);
-
- /* frame can be resized manually only if shrinking is disabled or no children are attached */
- data->flag |= NODE_FRAME_RESIZEABLE;
- /* for shrinking bbox, initialize the rect from first child node */
- bbinit = (data->flag & NODE_FRAME_SHRINK);
- /* fit bounding box to all children */
- for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
- if (tnode->parent != node) {
- continue;
- }
-
- /* add margin to node rect */
- noderect = tnode->totr;
- noderect.xmin -= margin;
- noderect.xmax += margin;
- noderect.ymin -= margin;
- noderect.ymax += margin;
-
- /* first child initializes frame */
- if (bbinit) {
- bbinit = 0;
- rect = noderect;
- data->flag &= ~NODE_FRAME_RESIZEABLE;
- }
- else {
- BLI_rctf_union(&rect, &noderect);
- }
- }
-
- /* now adjust the frame size from view-space bounding box */
- node_from_view(node, rect.xmin, rect.ymax, &node->offsetx, &node->offsety);
- node_from_view(node, rect.xmax, rect.ymin, &xmax, &ymax);
- node->width = xmax - node->offsetx;
- node->height = -ymax + node->offsety;
-
- node->totr = rect;
+ const float margin = 1.5f * U.widget_unit;
+ NodeFrame *data = (NodeFrame *)node->storage;
+ bool bbinit;
+ bNode *tnode;
+ rctf rect, noderect;
+ float xmax, ymax;
+
+ /* init rect from current frame size */
+ node_to_view(node, node->offsetx, node->offsety, &rect.xmin, &rect.ymax);
+ node_to_view(
+ node, node->offsetx + node->width, node->offsety - node->height, &rect.xmax, &rect.ymin);
+
+ /* frame can be resized manually only if shrinking is disabled or no children are attached */
+ data->flag |= NODE_FRAME_RESIZEABLE;
+ /* for shrinking bbox, initialize the rect from first child node */
+ bbinit = (data->flag & NODE_FRAME_SHRINK);
+ /* fit bounding box to all children */
+ for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
+ if (tnode->parent != node) {
+ continue;
+ }
+
+ /* add margin to node rect */
+ noderect = tnode->totr;
+ noderect.xmin -= margin;
+ noderect.xmax += margin;
+ noderect.ymin -= margin;
+ noderect.ymax += margin;
+
+ /* first child initializes frame */
+ if (bbinit) {
+ bbinit = 0;
+ rect = noderect;
+ data->flag &= ~NODE_FRAME_RESIZEABLE;
+ }
+ else {
+ BLI_rctf_union(&rect, &noderect);
+ }
+ }
+
+ /* now adjust the frame size from view-space bounding box */
+ node_from_view(node, rect.xmin, rect.ymax, &node->offsetx, &node->offsety);
+ node_from_view(node, rect.xmax, rect.ymin, &xmax, &ymax);
+ node->width = xmax - node->offsetx;
+ node->height = -ymax + node->offsety;
+
+ node->totr = rect;
}
static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float aspect)
{
- /* XXX font id is crap design */
- const int fontid = UI_style_get()->widgetlabel.uifont_id;
- NodeFrame *data = (NodeFrame *)node->storage;
- rctf *rct = &node->totr;
- int color_id = node_get_colorid(node);
- char label[MAX_NAME];
- /* XXX a bit hacky, should use separate align values for x and y */
- float width, ascender;
- float x, y;
- const int font_size = data->label_size / aspect;
- const float margin = (float)(NODE_DY / 4);
- int label_height;
- unsigned char color[3];
-
- nodeLabel(ntree, node, label, sizeof(label));
-
- BLF_enable(fontid, BLF_ASPECT);
- BLF_aspect(fontid, aspect, aspect, 1.0f);
- /* clamp otherwise it can suck up a LOT of memory */
- BLF_size(fontid, MIN2(24, font_size), U.dpi);
-
- /* title color */
- UI_GetThemeColorBlendShade3ubv(TH_TEXT, color_id, 0.4f, 10, color);
- BLF_color3ubv(fontid, color);
-
- width = BLF_width(fontid, label, sizeof(label));
- ascender = BLF_ascender(fontid);
- label_height = ((margin / aspect) + (ascender * aspect));
-
- /* 'x' doesn't need aspect correction */
- x = BLI_rctf_cent_x(rct) - (0.5f * width);
- y = rct->ymax - label_height;
-
- BLF_position(fontid, x, y, 0);
- BLF_draw(fontid, label, BLF_DRAW_STR_DUMMY_MAX);
-
- /* draw text body */
- if (node->id) {
- Text *text = (Text *)node->id;
- TextLine *line;
- const int line_height_max = BLF_height_max(fontid);
- const float line_spacing = (line_height_max * aspect);
- const float line_width = (BLI_rctf_size_x(rct) - margin) / aspect;
- int y_min;
-
- /* 'x' doesn't need aspect correction */
- x = rct->xmin + margin;
- y = rct->ymax - (label_height + line_spacing);
- /* early exit */
- y_min = y + ((margin * 2) - (y - rct->ymin));
-
- BLF_enable(fontid, BLF_CLIPPING | BLF_WORD_WRAP);
- BLF_clipping(
- fontid,
- rct->xmin,
- /* round to avoid clipping half-way through a line */
- y - (floorf(((y - rct->ymin) - (margin * 2)) / line_spacing) * line_spacing),
- rct->xmin + line_width,
- rct->ymax);
-
- BLF_wordwrap(fontid, line_width);
-
- for (line = text->lines.first; line; line = line->next) {
- struct ResultBLF info;
- if (line->line[0]) {
- BLF_position(fontid, x, y, 0);
- BLF_draw_ex(fontid, line->line, line->len, &info);
- y -= line_spacing * info.lines;
- }
- else {
- y -= line_spacing;
- }
- if (y < y_min) {
- break;
- }
- }
-
- BLF_disable(fontid, BLF_CLIPPING | BLF_WORD_WRAP);
- }
-
- BLF_disable(fontid, BLF_ASPECT);
-}
-
-static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode,
- bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key))
-{
- rctf *rct = &node->totr;
- int color_id = node_get_colorid(node);
- float color[4];
- float alpha;
-
- /* skip if out of view */
- if (BLI_rctf_isect(&node->totr, &ar->v2d.cur, NULL) == false) {
- UI_block_end(C, node->block);
- node->block = NULL;
- return;
- }
-
- UI_GetThemeColor4fv(TH_NODE_FRAME, color);
- alpha = color[3];
-
- /* shadow */
- node_draw_shadow(snode, node, BASIS_RAD, alpha);
-
- /* body */
- if (node->flag & NODE_CUSTOM_COLOR) {
- rgba_float_args_set(color, node->color[0], node->color[1], node->color[2], alpha);
- }
- else {
- UI_GetThemeColor4fv(TH_NODE_FRAME, color);
- }
-
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color);
-
- /* outline active and selected emphasis */
- if (node->flag & SELECT) {
- if (node->flag & NODE_ACTIVE) {
- UI_GetThemeColorShadeAlpha4fv(TH_ACTIVE, 0, -40, color);
- }
- else {
- UI_GetThemeColorShadeAlpha4fv(TH_SELECT, 0, -40, color);
- }
-
- UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color);
- }
-
- /* label */
- node_draw_frame_label(ntree, node, snode->aspect);
-
- UI_ThemeClearColor(color_id);
-
- UI_block_end(C, node->block);
- UI_block_draw(C, node->block);
- node->block = NULL;
+ /* XXX font id is crap design */
+ const int fontid = UI_style_get()->widgetlabel.uifont_id;
+ NodeFrame *data = (NodeFrame *)node->storage;
+ rctf *rct = &node->totr;
+ int color_id = node_get_colorid(node);
+ char label[MAX_NAME];
+ /* XXX a bit hacky, should use separate align values for x and y */
+ float width, ascender;
+ float x, y;
+ const int font_size = data->label_size / aspect;
+ const float margin = (float)(NODE_DY / 4);
+ int label_height;
+ unsigned char color[3];
+
+ nodeLabel(ntree, node, label, sizeof(label));
+
+ BLF_enable(fontid, BLF_ASPECT);
+ BLF_aspect(fontid, aspect, aspect, 1.0f);
+ /* clamp otherwise it can suck up a LOT of memory */
+ BLF_size(fontid, MIN2(24, font_size), U.dpi);
+
+ /* title color */
+ UI_GetThemeColorBlendShade3ubv(TH_TEXT, color_id, 0.4f, 10, color);
+ BLF_color3ubv(fontid, color);
+
+ width = BLF_width(fontid, label, sizeof(label));
+ ascender = BLF_ascender(fontid);
+ label_height = ((margin / aspect) + (ascender * aspect));
+
+ /* 'x' doesn't need aspect correction */
+ x = BLI_rctf_cent_x(rct) - (0.5f * width);
+ y = rct->ymax - label_height;
+
+ BLF_position(fontid, x, y, 0);
+ BLF_draw(fontid, label, BLF_DRAW_STR_DUMMY_MAX);
+
+ /* draw text body */
+ if (node->id) {
+ Text *text = (Text *)node->id;
+ TextLine *line;
+ const int line_height_max = BLF_height_max(fontid);
+ const float line_spacing = (line_height_max * aspect);
+ const float line_width = (BLI_rctf_size_x(rct) - margin) / aspect;
+ int y_min;
+
+ /* 'x' doesn't need aspect correction */
+ x = rct->xmin + margin;
+ y = rct->ymax - (label_height + line_spacing);
+ /* early exit */
+ y_min = y + ((margin * 2) - (y - rct->ymin));
+
+ BLF_enable(fontid, BLF_CLIPPING | BLF_WORD_WRAP);
+ BLF_clipping(fontid,
+ rct->xmin,
+ /* round to avoid clipping half-way through a line */
+ y - (floorf(((y - rct->ymin) - (margin * 2)) / line_spacing) * line_spacing),
+ rct->xmin + line_width,
+ rct->ymax);
+
+ BLF_wordwrap(fontid, line_width);
+
+ for (line = text->lines.first; line; line = line->next) {
+ struct ResultBLF info;
+ if (line->line[0]) {
+ BLF_position(fontid, x, y, 0);
+ BLF_draw_ex(fontid, line->line, line->len, &info);
+ y -= line_spacing * info.lines;
+ }
+ else {
+ y -= line_spacing;
+ }
+ if (y < y_min) {
+ break;
+ }
+ }
+
+ BLF_disable(fontid, BLF_CLIPPING | BLF_WORD_WRAP);
+ }
+
+ BLF_disable(fontid, BLF_ASPECT);
+}
+
+static void node_draw_frame(const bContext *C,
+ ARegion *ar,
+ SpaceNode *snode,
+ bNodeTree *ntree,
+ bNode *node,
+ bNodeInstanceKey UNUSED(key))
+{
+ rctf *rct = &node->totr;
+ int color_id = node_get_colorid(node);
+ float color[4];
+ float alpha;
+
+ /* skip if out of view */
+ if (BLI_rctf_isect(&node->totr, &ar->v2d.cur, NULL) == false) {
+ UI_block_end(C, node->block);
+ node->block = NULL;
+ return;
+ }
+
+ UI_GetThemeColor4fv(TH_NODE_FRAME, color);
+ alpha = color[3];
+
+ /* shadow */
+ node_draw_shadow(snode, node, BASIS_RAD, alpha);
+
+ /* body */
+ if (node->flag & NODE_CUSTOM_COLOR) {
+ rgba_float_args_set(color, node->color[0], node->color[1], node->color[2], alpha);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_NODE_FRAME, color);
+ }
+
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color);
+
+ /* outline active and selected emphasis */
+ if (node->flag & SELECT) {
+ if (node->flag & NODE_ACTIVE) {
+ UI_GetThemeColorShadeAlpha4fv(TH_ACTIVE, 0, -40, color);
+ }
+ else {
+ UI_GetThemeColorShadeAlpha4fv(TH_SELECT, 0, -40, color);
+ }
+
+ UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color);
+ }
+
+ /* label */
+ node_draw_frame_label(ntree, node, snode->aspect);
+
+ UI_ThemeClearColor(color_id);
+
+ UI_block_end(C, node->block);
+ UI_block_draw(C, node->block);
+ node->block = NULL;
}
static int node_resize_area_frame(bNode *node, int x, int y)
{
- const float size = 10.0f;
- NodeFrame *data = (NodeFrame *)node->storage;
- rctf totr = node->totr;
- int dir = 0;
+ const float size = 10.0f;
+ NodeFrame *data = (NodeFrame *)node->storage;
+ rctf totr = node->totr;
+ int dir = 0;
- /* shrinking frame size is determined by child nodes */
- if (!(data->flag & NODE_FRAME_RESIZEABLE)) {
- return 0;
- }
+ /* shrinking frame size is determined by child nodes */
+ if (!(data->flag & NODE_FRAME_RESIZEABLE)) {
+ return 0;
+ }
- if (x >= totr.xmax - size && x < totr.xmax && y >= totr.ymin && y < totr.ymax) {
- dir |= NODE_RESIZE_RIGHT;
- }
- if (x >= totr.xmin && x < totr.xmin + size && y >= totr.ymin && y < totr.ymax) {
- dir |= NODE_RESIZE_LEFT;
- }
- if (x >= totr.xmin && x < totr.xmax && y >= totr.ymax - size && y < totr.ymax) {
- dir |= NODE_RESIZE_TOP;
- }
- if (x >= totr.xmin && x < totr.xmax && y >= totr.ymin && y < totr.ymin + size) {
- dir |= NODE_RESIZE_BOTTOM;
- }
+ if (x >= totr.xmax - size && x < totr.xmax && y >= totr.ymin && y < totr.ymax) {
+ dir |= NODE_RESIZE_RIGHT;
+ }
+ if (x >= totr.xmin && x < totr.xmin + size && y >= totr.ymin && y < totr.ymax) {
+ dir |= NODE_RESIZE_LEFT;
+ }
+ if (x >= totr.xmin && x < totr.xmax && y >= totr.ymax - size && y < totr.ymax) {
+ dir |= NODE_RESIZE_TOP;
+ }
+ if (x >= totr.xmin && x < totr.xmax && y >= totr.ymin && y < totr.ymin + size) {
+ dir |= NODE_RESIZE_BOTTOM;
+ }
- return dir;
+ return dir;
}
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", 0, IFACE_("Label Size"), ICON_NONE);
+ uiItemR(layout, ptr, "shrink", 0, IFACE_("Shrink"), ICON_NONE);
+ uiItemR(layout, ptr, "text", 0, NULL, ICON_NONE);
}
+#define NODE_REROUTE_SIZE 8.0f
-#define NODE_REROUTE_SIZE 8.0f
-
-static void node_draw_reroute_prepare(const bContext *UNUSED(C), bNodeTree *UNUSED(ntree), bNode *node)
+static void node_draw_reroute_prepare(const bContext *UNUSED(C),
+ bNodeTree *UNUSED(ntree),
+ bNode *node)
{
- bNodeSocket *nsock;
- float locx, locy;
- float size = NODE_REROUTE_SIZE;
+ bNodeSocket *nsock;
+ float locx, locy;
+ float size = NODE_REROUTE_SIZE;
- /* get "global" coords */
- node_to_view(node, 0.0f, 0.0f, &locx, &locy);
+ /* get "global" coords */
+ node_to_view(node, 0.0f, 0.0f, &locx, &locy);
- /* reroute node has exactly one input and one output, both in the same place */
- nsock = node->outputs.first;
- nsock->locx = locx;
- nsock->locy = locy;
+ /* reroute node has exactly one input and one output, both in the same place */
+ nsock = node->outputs.first;
+ nsock->locx = locx;
+ nsock->locy = locy;
- nsock = node->inputs.first;
- nsock->locx = locx;
- nsock->locy = locy;
+ nsock = node->inputs.first;
+ nsock->locx = locx;
+ nsock->locy = locy;
- node->width = size * 2;
- node->totr.xmin = locx - size;
- node->totr.xmax = locx + size;
- node->totr.ymax = locy + size;
- node->totr.ymin = locy - size;
+ node->width = size * 2;
+ node->totr.xmin = locx - size;
+ node->totr.xmax = locx + size;
+ node->totr.ymax = locy + size;
+ node->totr.ymin = locy - size;
}
-static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode),
- bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key))
+static void node_draw_reroute(const bContext *C,
+ ARegion *ar,
+ SpaceNode *UNUSED(snode),
+ bNodeTree *ntree,
+ bNode *node,
+ bNodeInstanceKey UNUSED(key))
{
- char showname[128]; /* 128 used below */
- rctf *rct = &node->totr;
+ char showname[128]; /* 128 used below */
+ 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)
- {
- UI_block_end(C, node->block);
- node->block = NULL;
- return;
- }
+ /* 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) {
+ UI_block_end(C, node->block);
+ node->block = NULL;
+ return;
+ }
- /* XXX only kept for debugging
- * selection state is indicated by socket outline below!
- */
+ /* XXX only kept for debugging
+ * selection state is indicated by socket outline below!
+ */
#if 0
- float size = NODE_REROUTE_SIZE;
-
- /* body */
- float debug_color[4];
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_GetThemeColor4fv(TH_NODE, debug_color);
- UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size, debug_color);
-
- /* outline active and selected emphasis */
- if (node->flag & SELECT) {
- GPU_blend(true);
- GPU_line_smooth(true);
- /* using different shades of TH_TEXT_HI for the empasis, like triangle */
- if (node->flag & NODE_ACTIVE) {
- UI_GetThemeColorShadeAlpha4fv(TH_TEXT_HI, 0, -40, debug_color);
- }
- else {
- UI_GetThemeColorShadeAlpha4fv(TH_TEXT_HI, -20, -120, debug_color);
- }
- UI_draw_roundbox_4fv(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size, debug_color);
-
- GPU_line_smooth(false);
- GPU_blend(false);
- }
+ float size = NODE_REROUTE_SIZE;
+
+ /* body */
+ float debug_color[4];
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_GetThemeColor4fv(TH_NODE, debug_color);
+ UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size, debug_color);
+
+ /* outline active and selected emphasis */
+ if (node->flag & SELECT) {
+ GPU_blend(true);
+ GPU_line_smooth(true);
+ /* using different shades of TH_TEXT_HI for the empasis, like triangle */
+ if (node->flag & NODE_ACTIVE) {
+ UI_GetThemeColorShadeAlpha4fv(TH_TEXT_HI, 0, -40, debug_color);
+ }
+ else {
+ UI_GetThemeColorShadeAlpha4fv(TH_TEXT_HI, -20, -120, debug_color);
+ }
+ UI_draw_roundbox_4fv(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size, debug_color);
+
+ GPU_line_smooth(false);
+ GPU_blend(false);
+ }
#endif
- if (node->label[0] != '\0') {
- /* draw title (node label) */
- BLI_strncpy(showname, node->label, sizeof(showname));
- uiDefBut(node->block, UI_BTYPE_LABEL, 0, showname,
- (int)(rct->xmin - NODE_DYS), (int)(rct->ymax),
- (short)512, (short)NODE_DY,
- NULL, 0, 0, 0, 0, NULL);
- }
-
- /* 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);
-
- UI_block_end(C, node->block);
- UI_block_draw(C, node->block);
- node->block = NULL;
+ if (node->label[0] != '\0') {
+ /* draw title (node label) */
+ BLI_strncpy(showname, node->label, sizeof(showname));
+ uiDefBut(node->block,
+ UI_BTYPE_LABEL,
+ 0,
+ showname,
+ (int)(rct->xmin - NODE_DYS),
+ (int)(rct->ymax),
+ (short)512,
+ (short)NODE_DY,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL);
+ }
+
+ /* 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);
+
+ UI_block_end(C, node->block);
+ UI_block_draw(C, node->block);
+ node->block = NULL;
}
/* Special tweak area for reroute node.
@@ -613,3175 +628,3353 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
*/
static int node_tweak_area_reroute(bNode *node, int x, int y)
{
- /* square of tweak radius */
- const float tweak_radius_sq = SQUARE(24);
+ /* square of tweak radius */
+ const float tweak_radius_sq = SQUARE(24);
- bNodeSocket *sock = node->inputs.first;
- float dx = sock->locx - x;
- float dy = sock->locy - y;
- return (dx * dx + dy * dy <= tweak_radius_sq);
+ bNodeSocket *sock = node->inputs.first;
+ float dx = sock->locx - x;
+ float dy = sock->locy - y;
+ return (dx * dx + dy * dy <= tweak_radius_sq);
}
static void node_common_set_butfunc(bNodeType *ntype)
{
- switch (ntype->type) {
- case NODE_GROUP:
- ntype->draw_buttons = node_draw_buttons_group;
- break;
- case NODE_FRAME:
- ntype->draw_nodetype = node_draw_frame;
- ntype->draw_nodetype_prepare = node_draw_frame_prepare;
- ntype->draw_buttons_ex = node_buts_frame_ex;
- ntype->resize_area_func = node_resize_area_frame;
- break;
- case NODE_REROUTE:
- ntype->draw_nodetype = node_draw_reroute;
- ntype->draw_nodetype_prepare = node_draw_reroute_prepare;
- ntype->tweak_area_func = node_tweak_area_reroute;
- break;
- }
+ switch (ntype->type) {
+ case NODE_GROUP:
+ ntype->draw_buttons = node_draw_buttons_group;
+ break;
+ case NODE_FRAME:
+ ntype->draw_nodetype = node_draw_frame;
+ ntype->draw_nodetype_prepare = node_draw_frame_prepare;
+ ntype->draw_buttons_ex = node_buts_frame_ex;
+ ntype->resize_area_func = node_resize_area_frame;
+ break;
+ case NODE_REROUTE:
+ ntype->draw_nodetype = node_draw_reroute;
+ ntype->draw_nodetype_prepare = node_draw_reroute_prepare;
+ ntype->tweak_area_func = node_tweak_area_reroute;
+ break;
+ }
}
/* ****************** BUTTON CALLBACKS FOR SHADER NODES ***************** */
-static void node_buts_image_user(uiLayout *layout, bContext *C, PointerRNA *ptr,
- PointerRNA *imaptr, PointerRNA *iuserptr,
+static void node_buts_image_user(uiLayout *layout,
+ bContext *C,
+ PointerRNA *ptr,
+ PointerRNA *imaptr,
+ PointerRNA *iuserptr,
bool compositor)
{
- uiLayout *col;
- int source;
+ uiLayout *col;
+ int source;
- if (!imaptr->data) {
- return;
- }
+ if (!imaptr->data) {
+ return;
+ }
- col = uiLayoutColumn(layout, false);
+ col = uiLayoutColumn(layout, false);
- uiItemR(col, imaptr, "source", 0, "", ICON_NONE);
+ uiItemR(col, imaptr, "source", 0, "", ICON_NONE);
- source = RNA_enum_get(imaptr, "source");
+ source = RNA_enum_get(imaptr, "source");
- if (source == IMA_SRC_SEQUENCE) {
- /* don't use iuser->framenr directly
- * because it may not be updated if auto-refresh is off */
- Scene *scene = CTX_data_scene(C);
- ImageUser *iuser = iuserptr->data;
- /* Image *ima = imaptr->data; */ /* UNUSED */
+ if (source == IMA_SRC_SEQUENCE) {
+ /* don't use iuser->framenr directly
+ * because it may not be updated if auto-refresh is off */
+ Scene *scene = CTX_data_scene(C);
+ ImageUser *iuser = iuserptr->data;
+ /* Image *ima = imaptr->data; */ /* UNUSED */
- char numstr[32];
- const int framenr = BKE_image_user_frame_get(iuser, CFRA, NULL);
- BLI_snprintf(numstr, sizeof(numstr), IFACE_("Frame: %d"), framenr);
- uiItemL(layout, numstr, ICON_NONE);
- }
+ char numstr[32];
+ const int framenr = BKE_image_user_frame_get(iuser, CFRA, NULL);
+ BLI_snprintf(numstr, sizeof(numstr), IFACE_("Frame: %d"), framenr);
+ uiItemL(layout, numstr, ICON_NONE);
+ }
- 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);
- }
+ 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);
+ }
- 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);
- }
+ 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);
+ }
}
static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *row, *col, *sub;
+ uiLayout *row, *col, *sub;
- uiItemR(layout, ptr, "vector_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "vector_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
- row = uiLayoutRow(layout, false);
+ row = uiLayoutRow(layout, false);
- col = uiLayoutColumn(row, true);
- uiItemL(col, IFACE_("Location:"), ICON_NONE);
- uiItemR(col, ptr, "translation", 0, "", ICON_NONE);
+ col = uiLayoutColumn(row, true);
+ uiItemL(col, IFACE_("Location:"), ICON_NONE);
+ uiItemR(col, ptr, "translation", 0, "", ICON_NONE);
- col = uiLayoutColumn(row, true);
- uiItemL(col, IFACE_("Rotation:"), ICON_NONE);
- uiItemR(col, ptr, "rotation", 0, "", ICON_NONE);
+ col = uiLayoutColumn(row, true);
+ uiItemL(col, IFACE_("Rotation:"), ICON_NONE);
+ uiItemR(col, ptr, "rotation", 0, "", ICON_NONE);
- col = uiLayoutColumn(row, true);
- uiItemL(col, IFACE_("Scale:"), ICON_NONE);
- uiItemR(col, ptr, "scale", 0, "", ICON_NONE);
+ col = uiLayoutColumn(row, true);
+ uiItemL(col, IFACE_("Scale:"), ICON_NONE);
+ uiItemR(col, ptr, "scale", 0, "", ICON_NONE);
- row = uiLayoutRow(layout, false);
+ row = uiLayoutRow(layout, false);
- col = uiLayoutColumn(row, true);
- uiItemR(col, ptr, "use_min", 0, IFACE_("Min"), ICON_NONE);
- sub = uiLayoutColumn(col, true);
- uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_min"));
- uiItemR(sub, ptr, "min", 0, "", ICON_NONE);
+ col = uiLayoutColumn(row, true);
+ uiItemR(col, ptr, "use_min", 0, IFACE_("Min"), ICON_NONE);
+ sub = uiLayoutColumn(col, true);
+ uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_min"));
+ uiItemR(sub, ptr, "min", 0, "", ICON_NONE);
- col = uiLayoutColumn(row, true);
- uiItemR(col, ptr, "use_max", 0, IFACE_("Max"), ICON_NONE);
- sub = uiLayoutColumn(col, true);
- uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max"));
- uiItemR(sub, ptr, "max", 0, "", ICON_NONE);
+ col = uiLayoutColumn(row, true);
+ uiItemR(col, ptr, "use_max", 0, IFACE_("Max"), ICON_NONE);
+ sub = uiLayoutColumn(col, true);
+ uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max"));
+ uiItemR(sub, ptr, "max", 0, "", ICON_NONE);
}
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", 0, "", 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", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "convert_from", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "convert_to", 0, "", 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", 0, 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", 0, NULL, 0);
}
static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- PointerRNA imaptr = RNA_pointer_get(ptr, "image");
- PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
+ PointerRNA imaptr = RNA_pointer_get(ptr, "image");
+ PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
- uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
- uiTemplateID(layout, C, ptr, "image", "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
- uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
+ uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
+ uiTemplateID(layout,
+ C,
+ ptr,
+ "image",
+ "IMAGE_OT_new",
+ "IMAGE_OT_open",
+ NULL,
+ UI_TEMPLATE_ID_FILTER_ALL,
+ false);
+ uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
- if (RNA_enum_get(ptr, "projection") == SHD_PROJ_BOX) {
- uiItemR(layout, ptr, "projection_blend", 0, "Blend", ICON_NONE);
- }
+ if (RNA_enum_get(ptr, "projection") == SHD_PROJ_BOX) {
+ uiItemR(layout, ptr, "projection_blend", 0, "Blend", ICON_NONE);
+ }
- uiItemR(layout, ptr, "extension", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "extension", 0, "", 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.
- */
- node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false);
+ /* note: image user properties used directly here, unlike compositor image node,
+ * which redefines them in the node struct RNA to get proper updates.
+ */
+ node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false);
}
static void node_shader_buts_tex_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
- uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 0);
+ PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
+ uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 0);
}
static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- PointerRNA imaptr = RNA_pointer_get(ptr, "image");
- PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
+ PointerRNA imaptr = RNA_pointer_get(ptr, "image");
+ PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
- uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
- uiTemplateID(
- layout, C, ptr, "image",
- "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+ uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
+ uiTemplateID(layout,
+ C,
+ ptr,
+ "image",
+ "IMAGE_OT_new",
+ "IMAGE_OT_open",
+ NULL,
+ UI_TEMPLATE_ID_FILTER_ALL,
+ false);
- node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false);
+ node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false);
- uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
}
static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- PointerRNA imaptr = RNA_pointer_get(ptr, "image");
- PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
- Image *ima = imaptr.data;
-
- uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
- uiTemplateID(
- layout, C, ptr, "image",
- "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
-
- if (!ima) {
- return;
- }
-
- uiItemR(layout, &imaptr, "source", 0, IFACE_("Source"), ICON_NONE);
-
- if (!(ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER))) {
- uiLayout *row = uiLayoutRow(layout, true);
- const bool is_packed = BKE_image_has_packedfile(ima);
-
- if (is_packed) {
- uiItemO(row, "", ICON_PACKAGE, "image.unpack");
- }
- else {
- uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
- }
-
- row = uiLayoutRow(row, true);
- uiLayoutSetEnabled(row, !is_packed);
- uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
- uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
- }
-
- /* multilayer? */
- if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
- uiTemplateImageLayers(layout, C, ima, iuserptr.data);
- }
- else if (ima->source != IMA_SRC_GENERATED) {
- uiTemplateImageInfo(layout, C, ima, iuserptr.data);
- }
-
- uiItemR(layout, ptr, "color_space", 0, IFACE_("Color Space"), ICON_NONE);
- uiItemR(layout, ptr, "interpolation", 0, IFACE_("Interpolation"), ICON_NONE);
- uiItemR(layout, ptr, "projection", 0, IFACE_("Projection"), ICON_NONE);
+ PointerRNA imaptr = RNA_pointer_get(ptr, "image");
+ PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
+ Image *ima = imaptr.data;
+
+ uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
+ uiTemplateID(layout,
+ C,
+ ptr,
+ "image",
+ "IMAGE_OT_new",
+ "IMAGE_OT_open",
+ NULL,
+ UI_TEMPLATE_ID_FILTER_ALL,
+ false);
+
+ if (!ima) {
+ return;
+ }
+
+ uiItemR(layout, &imaptr, "source", 0, IFACE_("Source"), ICON_NONE);
+
+ if (!(ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER))) {
+ uiLayout *row = uiLayoutRow(layout, true);
+ const bool is_packed = BKE_image_has_packedfile(ima);
+
+ if (is_packed) {
+ uiItemO(row, "", ICON_PACKAGE, "image.unpack");
+ }
+ else {
+ uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
+ }
+
+ row = uiLayoutRow(row, true);
+ uiLayoutSetEnabled(row, !is_packed);
+ uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
+ uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
+ }
+
+ /* multilayer? */
+ if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
+ uiTemplateImageLayers(layout, C, ima, iuserptr.data);
+ }
+ else if (ima->source != IMA_SRC_GENERATED) {
+ uiTemplateImageInfo(layout, C, ima, iuserptr.data);
+ }
+
+ uiItemR(layout, ptr, "color_space", 0, IFACE_("Color Space"), ICON_NONE);
+ uiItemR(layout, ptr, "interpolation", 0, IFACE_("Interpolation"), ICON_NONE);
+ uiItemR(layout, ptr, "projection", 0, IFACE_("Projection"), ICON_NONE);
}
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", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "sun_direction", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "turbidity", 0, NULL, ICON_NONE);
- if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_NEW) {
- uiItemR(layout, ptr, "ground_albedo", 0, NULL, ICON_NONE);
- }
+ if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_NEW) {
+ uiItemR(layout, ptr, "ground_albedo", 0, 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", 0, "", 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", 0, NULL, ICON_NONE);
}
static void node_shader_buts_tex_brick(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ 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);
+ 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);
- col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "squash", 0, IFACE_("Squash"), ICON_NONE);
- uiItemR(col, ptr, "squash_frequency", 0, 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);
}
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", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "wave_profile", 0, "", ICON_NONE);
}
static void node_shader_buts_tex_musgrave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "musgrave_type", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "musgrave_type", 0, "", ICON_NONE);
}
static void node_shader_buts_tex_voronoi(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "coloring", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "distance", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "feature", 0, "", ICON_NONE);
-}
-
-static void node_shader_buts_tex_pointdensity(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
-{
- bNode *node = ptr->data;
- NodeShaderTexPointDensity *shader_point_density = node->storage;
- Object *ob = (Object *)node->id;
- PointerRNA ob_ptr, obdata_ptr;
-
- RNA_id_pointer_create((ID *)ob, &ob_ptr);
- 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);
-
- if (node->id && shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) {
- PointerRNA dataptr;
- RNA_id_pointer_create((ID *)node->id, &dataptr);
- 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);
- if (shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) {
- uiItemR(layout, ptr, "particle_color_source", 0, NULL, ICON_NONE);
- }
- else {
- uiItemR(layout, ptr, "vertex_color_source", 0, NULL, ICON_NONE);
- if (shader_point_density->ob_color_source == SHD_POINTDENSITY_COLOR_VERTWEIGHT) {
- if (ob_ptr.data) {
- uiItemPointerR(layout, ptr, "vertex_attribute_name", &ob_ptr, "vertex_groups", "", ICON_NONE);
- }
- }
- if (shader_point_density->ob_color_source == SHD_POINTDENSITY_COLOR_VERTCOL) {
- if (obdata_ptr.data) {
- uiItemPointerR(layout, ptr, "vertex_attribute_name", &obdata_ptr, "vertex_colors", "", ICON_NONE);
- }
- }
- }
+ uiItemR(layout, ptr, "coloring", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "distance", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "feature", 0, "", ICON_NONE);
+}
+
+static void node_shader_buts_tex_pointdensity(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ NodeShaderTexPointDensity *shader_point_density = node->storage;
+ Object *ob = (Object *)node->id;
+ PointerRNA ob_ptr, obdata_ptr;
+
+ RNA_id_pointer_create((ID *)ob, &ob_ptr);
+ 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);
+
+ if (node->id && shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) {
+ PointerRNA dataptr;
+ RNA_id_pointer_create((ID *)node->id, &dataptr);
+ 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);
+ if (shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) {
+ uiItemR(layout, ptr, "particle_color_source", 0, NULL, ICON_NONE);
+ }
+ else {
+ uiItemR(layout, ptr, "vertex_color_source", 0, NULL, ICON_NONE);
+ if (shader_point_density->ob_color_source == SHD_POINTDENSITY_COLOR_VERTWEIGHT) {
+ if (ob_ptr.data) {
+ uiItemPointerR(
+ layout, ptr, "vertex_attribute_name", &ob_ptr, "vertex_groups", "", ICON_NONE);
+ }
+ }
+ if (shader_point_density->ob_color_source == SHD_POINTDENSITY_COLOR_VERTCOL) {
+ if (obdata_ptr.data) {
+ uiItemPointerR(
+ layout, ptr, "vertex_attribute_name", &obdata_ptr, "vertex_colors", "", ICON_NONE);
+ }
+ }
+ }
}
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", 0, NULL, 0);
+ uiItemR(layout, ptr, "from_instancer", 0, 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", 0, 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", 0, NULL, 0);
- if (!RNA_boolean_get(ptr, "from_instancer")) {
- PointerRNA obptr = CTX_data_pointer_get(C, "active_object");
+ if (!RNA_boolean_get(ptr, "from_instancer")) {
+ PointerRNA obptr = CTX_data_pointer_get(C, "active_object");
- if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
- PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
- uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE);
- }
- }
+ if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
+ PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
+ uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE);
+ }
+ }
}
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", 0, 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", 0, "", 0);
- if (RNA_enum_get(ptr, "space") == SHD_SPACE_TANGENT) {
- PointerRNA obptr = CTX_data_pointer_get(C, "active_object");
+ if (RNA_enum_get(ptr, "space") == SHD_SPACE_TANGENT) {
+ PointerRNA obptr = CTX_data_pointer_get(C, "active_object");
- if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
- PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
- uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE);
- }
- else {
- uiItemR(layout, ptr, "uv_map", 0, "", 0);
- }
- }
+ if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
+ PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
+ uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE);
+ }
+ else {
+ uiItemR(layout, ptr, "uv_map", 0, "", 0);
+ }
+ }
}
static void node_shader_buts_displacement(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "space", 0, "", 0);
+ uiItemR(layout, ptr, "space", 0, "", 0);
}
static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- uiLayout *split, *row;
+ uiLayout *split, *row;
- split = uiLayoutSplit(layout, 0.0f, false);
+ split = uiLayoutSplit(layout, 0.0f, false);
- uiItemR(split, ptr, "direction_type", 0, "", 0);
+ uiItemR(split, ptr, "direction_type", 0, "", 0);
- row = uiLayoutRow(split, false);
+ row = uiLayoutRow(split, false);
- if (RNA_enum_get(ptr, "direction_type") == SHD_TANGENT_UVMAP) {
- PointerRNA obptr = CTX_data_pointer_get(C, "active_object");
+ if (RNA_enum_get(ptr, "direction_type") == SHD_TANGENT_UVMAP) {
+ PointerRNA obptr = CTX_data_pointer_get(C, "active_object");
- if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
- PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
- uiItemPointerR(row, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE);
- }
- else {
- uiItemR(row, ptr, "uv_map", 0, "", 0);
- }
- }
- else {
- uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, 0);
- }
+ if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
+ PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
+ uiItemPointerR(row, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE);
+ }
+ else {
+ uiItemR(row, ptr, "uv_map", 0, "", 0);
+ }
+ }
+ else {
+ uiItemR(row, ptr, "axis", 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", 0, "", 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", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "subsurface_method", 0, "", 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", 0, "", 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", 0, "", 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", 0, "", 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", 0, "", ICON_NONE);
}
-static void node_shader_buts_principled_hair(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+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", 0, "", ICON_NONE);
}
static void node_shader_buts_ies(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *row;
+ uiLayout *row;
- row = uiLayoutRow(layout, false);
- uiItemR(row, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
+ row = uiLayoutRow(layout, true);
- if (RNA_enum_get(ptr, "mode") == NODE_IES_INTERNAL) {
- uiItemR(row, ptr, "ies", 0, "", ICON_NONE);
- }
- else {
- uiItemR(row, ptr, "filepath", 0, "", ICON_NONE);
- }
+ if (RNA_enum_get(ptr, "mode") == NODE_IES_INTERNAL) {
+ uiItemR(row, ptr, "ies", 0, "", ICON_NONE);
+ }
+ else {
+ uiItemR(row, ptr, "filepath", 0, "", ICON_NONE);
+ }
}
static void node_shader_buts_script(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *row;
+ uiLayout *row;
- row = uiLayoutRow(layout, false);
- uiItemR(row, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
+ row = uiLayoutRow(layout, true);
- if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_INTERNAL) {
- uiItemR(row, ptr, "script", 0, "", ICON_NONE);
- }
- else {
- uiItemR(row, ptr, "filepath", 0, "", ICON_NONE);
- }
+ if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_INTERNAL) {
+ uiItemR(row, ptr, "script", 0, "", ICON_NONE);
+ }
+ else {
+ uiItemR(row, ptr, "filepath", 0, "", ICON_NONE);
+ }
- uiItemO(row, "", ICON_FILE_REFRESH, "node.shader_script_update");
+ uiItemO(row, "", ICON_FILE_REFRESH, "node.shader_script_update");
}
static void node_shader_buts_script_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- uiItemS(layout);
+ uiItemS(layout);
- node_shader_buts_script(layout, C, ptr);
+ node_shader_buts_script(layout, C, ptr);
-#if 0 /* not implemented yet */
- if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_EXTERNAL)
- uiItemR(layout, ptr, "use_auto_update", 0, NULL, ICON_NONE);
+#if 0 /* not implemented yet */
+ if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_EXTERNAL)
+ uiItemR(layout, ptr, "use_auto_update", 0, 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", 0, "", ICON_NONE);
}
static void node_buts_output_linestyle(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *row, *col;
+ uiLayout *row, *col;
- 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);
+ 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);
}
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", 0, NULL, ICON_NONE);
}
-static void node_shader_buts_ambient_occlusion(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+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", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "inside", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "only_local", 0, NULL, ICON_NONE);
}
/* only once called */
static void node_shader_set_butfunc(bNodeType *ntype)
{
- switch (ntype->type) {
- case SH_NODE_NORMAL:
- ntype->draw_buttons = node_buts_normal;
- break;
- case SH_NODE_CURVE_VEC:
- ntype->draw_buttons = node_buts_curvevec;
- break;
- case SH_NODE_CURVE_RGB:
- ntype->draw_buttons = node_buts_curvecol;
- break;
- case SH_NODE_MAPPING:
- ntype->draw_buttons = node_shader_buts_mapping;
- break;
- case SH_NODE_VALUE:
- ntype->draw_buttons = node_buts_value;
- break;
- case SH_NODE_RGB:
- ntype->draw_buttons = node_buts_rgb;
- break;
- case SH_NODE_MIX_RGB:
- ntype->draw_buttons = node_buts_mix_rgb;
- break;
- case SH_NODE_VALTORGB:
- ntype->draw_buttons = node_buts_colorramp;
- break;
- case SH_NODE_MATH:
- ntype->draw_buttons = node_buts_math;
- break;
- case SH_NODE_VECT_MATH:
- ntype->draw_buttons = node_shader_buts_vect_math;
- break;
- case SH_NODE_VECT_TRANSFORM:
- ntype->draw_buttons = node_shader_buts_vect_transform;
- break;
- case SH_NODE_ATTRIBUTE:
- ntype->draw_buttons = node_shader_buts_attribute;
- break;
- case SH_NODE_WIREFRAME:
- ntype->draw_buttons = node_shader_buts_wireframe;
- break;
- case SH_NODE_TEX_SKY:
- ntype->draw_buttons = node_shader_buts_tex_sky;
- break;
- case SH_NODE_TEX_IMAGE:
- ntype->draw_buttons = node_shader_buts_tex_image;
- ntype->draw_buttons_ex = node_shader_buts_tex_image_ex;
- break;
- case SH_NODE_TEX_ENVIRONMENT:
- ntype->draw_buttons = node_shader_buts_tex_environment;
- ntype->draw_buttons_ex = node_shader_buts_tex_environment_ex;
- break;
- case SH_NODE_TEX_GRADIENT:
- ntype->draw_buttons = node_shader_buts_tex_gradient;
- break;
- case SH_NODE_TEX_MAGIC:
- ntype->draw_buttons = node_shader_buts_tex_magic;
- break;
- case SH_NODE_TEX_BRICK:
- ntype->draw_buttons = node_shader_buts_tex_brick;
- break;
- case SH_NODE_TEX_WAVE:
- ntype->draw_buttons = node_shader_buts_tex_wave;
- break;
- case SH_NODE_TEX_MUSGRAVE:
- ntype->draw_buttons = node_shader_buts_tex_musgrave;
- break;
- case SH_NODE_TEX_VORONOI:
- ntype->draw_buttons = node_shader_buts_tex_voronoi;
- break;
- case SH_NODE_TEX_POINTDENSITY:
- ntype->draw_buttons = node_shader_buts_tex_pointdensity;
- break;
- case SH_NODE_TEX_COORD:
- ntype->draw_buttons = node_shader_buts_tex_coord;
- break;
- case SH_NODE_BUMP:
- ntype->draw_buttons = node_shader_buts_bump;
- break;
- case SH_NODE_NORMAL_MAP:
- ntype->draw_buttons = node_shader_buts_normal_map;
- break;
- case SH_NODE_DISPLACEMENT:
- case SH_NODE_VECTOR_DISPLACEMENT:
- ntype->draw_buttons = node_shader_buts_displacement;
- break;
- case SH_NODE_TANGENT:
- ntype->draw_buttons = node_shader_buts_tangent;
- break;
- case SH_NODE_BSDF_GLOSSY:
- case SH_NODE_BSDF_GLASS:
- case SH_NODE_BSDF_REFRACTION:
- ntype->draw_buttons = node_shader_buts_glossy;
- break;
- case SH_NODE_BSDF_PRINCIPLED:
- ntype->draw_buttons = node_shader_buts_principled;
- break;
- case SH_NODE_BSDF_ANISOTROPIC:
- ntype->draw_buttons = node_shader_buts_anisotropic;
- break;
- case SH_NODE_SUBSURFACE_SCATTERING:
- ntype->draw_buttons = node_shader_buts_subsurface;
- break;
- case SH_NODE_BSDF_TOON:
- ntype->draw_buttons = node_shader_buts_toon;
- break;
- case SH_NODE_BSDF_HAIR:
- ntype->draw_buttons = node_shader_buts_hair;
- break;
- case SH_NODE_BSDF_HAIR_PRINCIPLED:
- ntype->draw_buttons = node_shader_buts_principled_hair;
- break;
- case SH_NODE_SCRIPT:
- ntype->draw_buttons = node_shader_buts_script;
- ntype->draw_buttons_ex = node_shader_buts_script_ex;
- break;
- case SH_NODE_UVMAP:
- ntype->draw_buttons = node_shader_buts_uvmap;
- break;
- case SH_NODE_UVALONGSTROKE:
- ntype->draw_buttons = node_shader_buts_uvalongstroke;
- break;
- case SH_NODE_OUTPUT_MATERIAL:
- case SH_NODE_OUTPUT_LIGHT:
- case SH_NODE_OUTPUT_WORLD:
- ntype->draw_buttons = node_buts_output_shader;
- break;
- case SH_NODE_OUTPUT_LINESTYLE:
- ntype->draw_buttons = node_buts_output_linestyle;
- break;
- case SH_NODE_TEX_IES:
- ntype->draw_buttons = node_shader_buts_ies;
- break;
- case SH_NODE_BEVEL:
- ntype->draw_buttons = node_shader_buts_bevel;
- break;
- case SH_NODE_AMBIENT_OCCLUSION:
- ntype->draw_buttons = node_shader_buts_ambient_occlusion;
- break;
- }
+ switch (ntype->type) {
+ case SH_NODE_NORMAL:
+ ntype->draw_buttons = node_buts_normal;
+ break;
+ case SH_NODE_CURVE_VEC:
+ ntype->draw_buttons = node_buts_curvevec;
+ break;
+ case SH_NODE_CURVE_RGB:
+ ntype->draw_buttons = node_buts_curvecol;
+ break;
+ case SH_NODE_MAPPING:
+ ntype->draw_buttons = node_shader_buts_mapping;
+ break;
+ case SH_NODE_VALUE:
+ ntype->draw_buttons = node_buts_value;
+ break;
+ case SH_NODE_RGB:
+ ntype->draw_buttons = node_buts_rgb;
+ break;
+ case SH_NODE_MIX_RGB:
+ ntype->draw_buttons = node_buts_mix_rgb;
+ break;
+ case SH_NODE_VALTORGB:
+ ntype->draw_buttons = node_buts_colorramp;
+ break;
+ case SH_NODE_MATH:
+ ntype->draw_buttons = node_buts_math;
+ break;
+ case SH_NODE_VECT_MATH:
+ ntype->draw_buttons = node_shader_buts_vect_math;
+ break;
+ case SH_NODE_VECT_TRANSFORM:
+ ntype->draw_buttons = node_shader_buts_vect_transform;
+ break;
+ case SH_NODE_ATTRIBUTE:
+ ntype->draw_buttons = node_shader_buts_attribute;
+ break;
+ case SH_NODE_WIREFRAME:
+ ntype->draw_buttons = node_shader_buts_wireframe;
+ break;
+ case SH_NODE_TEX_SKY:
+ ntype->draw_buttons = node_shader_buts_tex_sky;
+ break;
+ case SH_NODE_TEX_IMAGE:
+ ntype->draw_buttons = node_shader_buts_tex_image;
+ ntype->draw_buttons_ex = node_shader_buts_tex_image_ex;
+ break;
+ case SH_NODE_TEX_ENVIRONMENT:
+ ntype->draw_buttons = node_shader_buts_tex_environment;
+ ntype->draw_buttons_ex = node_shader_buts_tex_environment_ex;
+ break;
+ case SH_NODE_TEX_GRADIENT:
+ ntype->draw_buttons = node_shader_buts_tex_gradient;
+ break;
+ case SH_NODE_TEX_MAGIC:
+ ntype->draw_buttons = node_shader_buts_tex_magic;
+ break;
+ case SH_NODE_TEX_BRICK:
+ ntype->draw_buttons = node_shader_buts_tex_brick;
+ break;
+ case SH_NODE_TEX_WAVE:
+ ntype->draw_buttons = node_shader_buts_tex_wave;
+ break;
+ case SH_NODE_TEX_MUSGRAVE:
+ ntype->draw_buttons = node_shader_buts_tex_musgrave;
+ break;
+ case SH_NODE_TEX_VORONOI:
+ ntype->draw_buttons = node_shader_buts_tex_voronoi;
+ break;
+ case SH_NODE_TEX_POINTDENSITY:
+ ntype->draw_buttons = node_shader_buts_tex_pointdensity;
+ break;
+ case SH_NODE_TEX_COORD:
+ ntype->draw_buttons = node_shader_buts_tex_coord;
+ break;
+ case SH_NODE_BUMP:
+ ntype->draw_buttons = node_shader_buts_bump;
+ break;
+ case SH_NODE_NORMAL_MAP:
+ ntype->draw_buttons = node_shader_buts_normal_map;
+ break;
+ case SH_NODE_DISPLACEMENT:
+ case SH_NODE_VECTOR_DISPLACEMENT:
+ ntype->draw_buttons = node_shader_buts_displacement;
+ break;
+ case SH_NODE_TANGENT:
+ ntype->draw_buttons = node_shader_buts_tangent;
+ break;
+ case SH_NODE_BSDF_GLOSSY:
+ case SH_NODE_BSDF_GLASS:
+ case SH_NODE_BSDF_REFRACTION:
+ ntype->draw_buttons = node_shader_buts_glossy;
+ break;
+ case SH_NODE_BSDF_PRINCIPLED:
+ ntype->draw_buttons = node_shader_buts_principled;
+ break;
+ case SH_NODE_BSDF_ANISOTROPIC:
+ ntype->draw_buttons = node_shader_buts_anisotropic;
+ break;
+ case SH_NODE_SUBSURFACE_SCATTERING:
+ ntype->draw_buttons = node_shader_buts_subsurface;
+ break;
+ case SH_NODE_BSDF_TOON:
+ ntype->draw_buttons = node_shader_buts_toon;
+ break;
+ case SH_NODE_BSDF_HAIR:
+ ntype->draw_buttons = node_shader_buts_hair;
+ break;
+ case SH_NODE_BSDF_HAIR_PRINCIPLED:
+ ntype->draw_buttons = node_shader_buts_principled_hair;
+ break;
+ case SH_NODE_SCRIPT:
+ ntype->draw_buttons = node_shader_buts_script;
+ ntype->draw_buttons_ex = node_shader_buts_script_ex;
+ break;
+ case SH_NODE_UVMAP:
+ ntype->draw_buttons = node_shader_buts_uvmap;
+ break;
+ case SH_NODE_UVALONGSTROKE:
+ ntype->draw_buttons = node_shader_buts_uvalongstroke;
+ break;
+ case SH_NODE_OUTPUT_MATERIAL:
+ case SH_NODE_OUTPUT_LIGHT:
+ case SH_NODE_OUTPUT_WORLD:
+ ntype->draw_buttons = node_buts_output_shader;
+ break;
+ case SH_NODE_OUTPUT_LINESTYLE:
+ ntype->draw_buttons = node_buts_output_linestyle;
+ break;
+ case SH_NODE_TEX_IES:
+ ntype->draw_buttons = node_shader_buts_ies;
+ break;
+ case SH_NODE_BEVEL:
+ ntype->draw_buttons = node_shader_buts_bevel;
+ break;
+ case SH_NODE_AMBIENT_OCCLUSION:
+ ntype->draw_buttons = node_shader_buts_ambient_occlusion;
+ break;
+ }
}
/* ****************** BUTTON CALLBACKS FOR COMPOSITE NODES ***************** */
-static void node_buts_image_views(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr,
- PointerRNA *imaptr)
+static void node_buts_image_views(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr,
+ PointerRNA *imaptr)
{
- uiLayout *col;
+ uiLayout *col;
- if (!imaptr->data) {
- return;
- }
+ if (!imaptr->data) {
+ return;
+ }
- col = uiLayoutColumn(layout, false);
+ col = uiLayoutColumn(layout, false);
- if (RNA_boolean_get(ptr, "has_views")) {
- if (RNA_enum_get(ptr, "view") == 0) {
- uiItemR(col, ptr, "view", 0, NULL, ICON_CAMERA_STEREO);
- }
- else {
- uiItemR(col, ptr, "view", 0, NULL, ICON_SCENE);
- }
- }
+ if (RNA_boolean_get(ptr, "has_views")) {
+ if (RNA_enum_get(ptr, "view") == 0) {
+ uiItemR(col, ptr, "view", 0, NULL, ICON_CAMERA_STEREO);
+ }
+ else {
+ uiItemR(col, ptr, "view", 0, NULL, ICON_SCENE);
+ }
+ }
}
static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- bNode *node = ptr->data;
- PointerRNA imaptr, iuserptr;
+ bNode *node = ptr->data;
+ PointerRNA imaptr, iuserptr;
- RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr);
- uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
- uiTemplateID(
- layout, C, ptr, "image",
- "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
- if (!node->id) {
- return;
- }
+ RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr);
+ uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
+ uiTemplateID(layout,
+ C,
+ ptr,
+ "image",
+ "IMAGE_OT_new",
+ "IMAGE_OT_open",
+ NULL,
+ UI_TEMPLATE_ID_FILTER_ALL,
+ false);
+ if (!node->id) {
+ return;
+ }
- imaptr = RNA_pointer_get(ptr, "image");
+ imaptr = RNA_pointer_get(ptr, "image");
- node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr, true);
+ node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr, true);
- node_buts_image_views(layout, C, ptr, &imaptr);
+ node_buts_image_views(layout, C, ptr, &imaptr);
}
static void node_composit_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- bNode *node = ptr->data;
- PointerRNA iuserptr;
+ bNode *node = ptr->data;
+ PointerRNA iuserptr;
- RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr);
- uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
- uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 1);
+ RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr);
+ uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
+ uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 1);
}
static void node_composit_buts_viewlayers(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- bNode *node = ptr->data;
- uiLayout *col, *row;
- PointerRNA op_ptr;
- PointerRNA scn_ptr;
- PropertyRNA *prop;
- const char *layer_name;
- char scene_name[MAX_ID_NAME - 2];
+ bNode *node = ptr->data;
+ uiLayout *col, *row;
+ PointerRNA op_ptr;
+ PointerRNA scn_ptr;
+ PropertyRNA *prop;
+ const char *layer_name;
+ char scene_name[MAX_ID_NAME - 2];
- uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+ uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
- if (!node->id) {
- return;
- }
+ if (!node->id) {
+ return;
+ }
- col = uiLayoutColumn(layout, false);
- row = uiLayoutRow(col, true);
- uiItemR(row, ptr, "layer", 0, "", ICON_NONE);
+ col = uiLayoutColumn(layout, false);
+ row = uiLayoutRow(col, true);
+ uiItemR(row, ptr, "layer", 0, "", ICON_NONE);
- prop = RNA_struct_find_property(ptr, "layer");
- if (!(RNA_property_enum_identifier(C, ptr, prop, RNA_property_enum_get(ptr, prop), &layer_name))) {
- return;
- }
+ prop = RNA_struct_find_property(ptr, "layer");
+ if (!(RNA_property_enum_identifier(
+ C, ptr, prop, RNA_property_enum_get(ptr, prop), &layer_name))) {
+ return;
+ }
- scn_ptr = RNA_pointer_get(ptr, "scene");
- RNA_string_get(&scn_ptr, "name", scene_name);
+ scn_ptr = RNA_pointer_get(ptr, "scene");
+ RNA_string_get(&scn_ptr, "name", scene_name);
- uiItemFullO(row, "RENDER_OT_render", "", ICON_RENDER_STILL, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
- RNA_string_set(&op_ptr, "layer", layer_name);
- RNA_string_set(&op_ptr, "scene", scene_name);
+ uiItemFullO(
+ row, "RENDER_OT_render", "", ICON_RENDER_STILL, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_string_set(&op_ptr, "layer", layer_name);
+ RNA_string_set(&op_ptr, "scene", scene_name);
}
-
static void node_composit_buts_blur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col, *row;
- int reference;
- int filter;
-
- col = uiLayoutColumn(layout, false);
- filter = RNA_enum_get(ptr, "filter_type");
- reference = RNA_boolean_get(ptr, "use_variable_size");
-
- uiItemR(col, ptr, "filter_type", 0, "", ICON_NONE);
- if (filter != R_FILTER_FAST_GAUSS) {
- uiItemR(col, ptr, "use_variable_size", 0, NULL, ICON_NONE);
- if (!reference) {
- uiItemR(col, ptr, "use_bokeh", 0, NULL, ICON_NONE);
- }
- uiItemR(col, ptr, "use_gamma_correction", 0, NULL, ICON_NONE);
- }
-
- uiItemR(col, ptr, "use_relative", 0, 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);
-
- col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "factor_x", 0, IFACE_("X"), ICON_NONE);
- uiItemR(col, ptr, "factor_y", 0, 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, "use_extended_bounds", 0, NULL, ICON_NONE);
+ uiLayout *col, *row;
+ int reference;
+ int filter;
+
+ col = uiLayoutColumn(layout, false);
+ filter = RNA_enum_get(ptr, "filter_type");
+ reference = RNA_boolean_get(ptr, "use_variable_size");
+
+ uiItemR(col, ptr, "filter_type", 0, "", ICON_NONE);
+ if (filter != R_FILTER_FAST_GAUSS) {
+ uiItemR(col, ptr, "use_variable_size", 0, NULL, ICON_NONE);
+ if (!reference) {
+ uiItemR(col, ptr, "use_bokeh", 0, NULL, ICON_NONE);
+ }
+ uiItemR(col, ptr, "use_gamma_correction", 0, NULL, ICON_NONE);
+ }
+
+ uiItemR(col, ptr, "use_relative", 0, 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);
+
+ col = uiLayoutColumn(layout, true);
+ uiItemR(col, ptr, "factor_x", 0, IFACE_("X"), ICON_NONE);
+ uiItemR(col, ptr, "factor_y", 0, 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, "use_extended_bounds", 0, NULL, ICON_NONE);
}
static void node_composit_buts_dblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ uiLayout *col;
- uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "use_wrap", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_wrap", 0, 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);
+ 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);
- uiItemS(layout);
+ uiItemS(layout);
- col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "distance", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "angle", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(layout, true);
+ uiItemR(col, ptr, "distance", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "angle", 0, NULL, ICON_NONE);
- uiItemS(layout);
+ uiItemS(layout);
- uiItemR(layout, ptr, "spin", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "zoom", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "spin", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "zoom", 0, NULL, ICON_NONE);
}
-static void node_composit_buts_bilateralblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_composit_buts_bilateralblur(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
{
- uiLayout *col;
+ 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);
+ 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);
}
static void node_composit_buts_defocus(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- uiLayout *sub, *col;
+ uiLayout *sub, *col;
- 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);
+ 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(layout, ptr, "use_gamma_correction", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_gamma_correction", 0, 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);
+ col = uiLayoutColumn(layout, false);
+ uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_zbuffer") == true);
+ uiItemR(col, ptr, "f_stop", 0, 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", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "threshold", 0, NULL, ICON_NONE);
- col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "use_preview", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, ptr, "use_preview", 0, NULL, ICON_NONE);
- uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+ uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
- col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "use_zbuffer", 0, 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);
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, ptr, "use_zbuffer", 0, 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);
}
/* 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", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "quality", 0, "", ICON_NONE);
- if (RNA_enum_get(ptr, "glare_type") != 1) {
- uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE);
+ if (RNA_enum_get(ptr, "glare_type") != 1) {
+ uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE);
- if (RNA_enum_get(ptr, "glare_type") != 0) {
- uiItemR(layout, ptr, "color_modulation", UI_ITEM_R_SLIDER, 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, "mix", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "threshold", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "mix", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "threshold", 0, 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);
- }
- 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);
+ 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);
+ }
+ 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);
- if (RNA_enum_get(ptr, "glare_type") == 0) {
- uiItemR(layout, ptr, "use_rotate_45", 0, NULL, ICON_NONE);
- }
- }
- if (RNA_enum_get(ptr, "glare_type") == 1) {
- uiItemR(layout, ptr, "size", 0, NULL, ICON_NONE);
- }
+ if (RNA_enum_get(ptr, "glare_type") == 0) {
+ uiItemR(layout, ptr, "use_rotate_45", 0, NULL, ICON_NONE);
+ }
+ }
+ if (RNA_enum_get(ptr, "glare_type") == 1) {
+ uiItemR(layout, ptr, "size", 0, NULL, ICON_NONE);
+ }
}
static void node_composit_buts_tonemap(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ uiLayout *col;
- col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "tonemap_type", 0, "", 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);
- }
- 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);
- }
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, ptr, "tonemap_type", 0, "", 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);
+ }
+ 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);
+ }
}
static void node_composit_buts_lensdist(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ uiLayout *col;
- col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "use_projector", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, ptr, "use_projector", 0, 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);
+ 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);
}
static void node_composit_buts_vecblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ uiLayout *col;
- col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "samples", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "factor", 0, IFACE_("Blur"), ICON_NONE);
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, ptr, "samples", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "factor", 0, 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);
+ 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(layout, ptr, "use_curved", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_curved", 0, 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", 0, "", 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", 0, "", ICON_NONE);
}
static void node_composit_buts_crop(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ 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", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "relative", 0, 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);
- }
- 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);
- }
+ 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);
+ }
+ 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);
+ }
}
static void node_composit_buts_splitviewer(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *row, *col;
+ uiLayout *row, *col;
- 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);
+ 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);
}
-static void node_composit_buts_double_edge_mask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_composit_buts_double_edge_mask(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
{
- uiLayout *col;
+ uiLayout *col;
- col = uiLayoutColumn(layout, false);
+ col = uiLayoutColumn(layout, false);
- uiItemL(col, IFACE_("Inner Edge:"), ICON_NONE);
- uiItemR(col, ptr, "inner_mode", 0, "", ICON_NONE);
- uiItemL(col, IFACE_("Buffer Edge:"), ICON_NONE);
- uiItemR(col, ptr, "edge_mode", 0, "", ICON_NONE);
+ uiItemL(col, IFACE_("Inner Edge:"), ICON_NONE);
+ uiItemR(col, ptr, "inner_mode", 0, "", ICON_NONE);
+ uiItemL(col, IFACE_("Buffer Edge:"), ICON_NONE);
+ uiItemR(col, ptr, "edge_mode", 0, "", ICON_NONE);
}
static void node_composit_buts_map_range(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ uiLayout *col;
- col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(layout, true);
+ uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE);
}
static void node_composit_buts_map_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *sub, *col;
+ uiLayout *sub, *col;
- col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "offset", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "size", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(layout, true);
+ uiItemR(col, ptr, "offset", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "size", 0, NULL, ICON_NONE);
- col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "use_min", 0, NULL, ICON_NONE);
- sub = uiLayoutColumn(col, false);
- uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_min"));
- uiItemR(sub, ptr, "min", 0, "", ICON_NONE);
+ col = uiLayoutColumn(layout, true);
+ uiItemR(col, ptr, "use_min", 0, NULL, ICON_NONE);
+ sub = uiLayoutColumn(col, false);
+ uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_min"));
+ uiItemR(sub, ptr, "min", 0, "", ICON_NONE);
- col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "use_max", 0, NULL, ICON_NONE);
- sub = uiLayoutColumn(col, false);
- uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max"));
- uiItemR(sub, ptr, "max", 0, "", ICON_NONE);
+ col = uiLayoutColumn(layout, true);
+ uiItemR(col, ptr, "use_max", 0, NULL, ICON_NONE);
+ sub = uiLayoutColumn(col, false);
+ uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max"));
+ uiItemR(sub, ptr, "max", 0, "", ICON_NONE);
}
static void node_composit_buts_alphaover(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ uiLayout *col;
- col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "use_premultiply", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "premul", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(layout, true);
+ uiItemR(col, ptr, "use_premultiply", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "premul", 0, NULL, ICON_NONE);
}
static void node_composit_buts_zcombine(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ 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);
+ col = uiLayoutColumn(layout, true);
+ uiItemR(col, ptr, "use_alpha", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_antialias_z", 0, 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);
- switch (RNA_enum_get(ptr, "mode")) {
- case CMP_NODE_DILATEERODE_DISTANCE_THRESH:
- uiItemR(layout, ptr, "edge", 0, NULL, ICON_NONE);
- break;
- case CMP_NODE_DILATEERODE_DISTANCE_FEATHER:
- uiItemR(layout, ptr, "falloff", 0, NULL, ICON_NONE);
- break;
- }
+ uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE);
+ switch (RNA_enum_get(ptr, "mode")) {
+ case CMP_NODE_DILATEERODE_DISTANCE_THRESH:
+ uiItemR(layout, ptr, "edge", 0, NULL, ICON_NONE);
+ break;
+ case CMP_NODE_DILATEERODE_DISTANCE_FEATHER:
+ uiItemR(layout, ptr, "falloff", 0, 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", 0, NULL, ICON_NONE);
}
static void node_composit_buts_despeckle(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ uiLayout *col;
- col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "threshold_neighbor", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "threshold_neighbor", 0, NULL, ICON_NONE);
}
static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ 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);
+ 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);
}
-static void node_composit_buts_distance_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_composit_buts_distance_matte(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
{
- uiLayout *col, *row;
+ uiLayout *col, *row;
- col = uiLayoutColumn(layout, true);
+ col = uiLayoutColumn(layout, true);
- uiItemL(layout, IFACE_("Color Space:"), ICON_NONE);
- row = uiLayoutRow(layout, false);
- uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemL(layout, IFACE_("Color Space:"), ICON_NONE);
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, ptr, "channel", 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", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "falloff", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
}
static void node_composit_buts_color_spill(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *row, *col;
+ uiLayout *row, *col;
- uiItemL(layout, IFACE_("Despill Channel:"), ICON_NONE);
- row = uiLayoutRow(layout, false);
- uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemL(layout, IFACE_("Despill Channel:"), ICON_NONE);
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
- col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "limit_method", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, ptr, "limit_method", 0, 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);
- }
+ 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(col, ptr, "ratio", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(col, ptr, "use_unspill", 0, 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, "ratio", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_unspill", 0, 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);
+ }
}
static void node_composit_buts_chroma_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ uiLayout *col;
- col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "tolerance", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, ptr, "tolerance", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "threshold", 0, 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, "shadow_adjust", UI_ITEM_R_SLIDER, NULL, ICON_NONE); Removed for now*/
+ 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, "shadow_adjust", UI_ITEM_R_SLIDER, NULL, ICON_NONE); Removed for now*/
}
static void node_composit_buts_color_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ 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);
+ 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);
}
-static void node_composit_buts_channel_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_composit_buts_channel_matte(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
{
- uiLayout *col, *row;
+ uiLayout *col, *row;
- uiItemL(layout, IFACE_("Color Space:"), ICON_NONE);
- row = uiLayoutRow(layout, false);
- uiItemR(row, ptr, "color_space", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemL(layout, IFACE_("Color Space:"), ICON_NONE);
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, ptr, "color_space", 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);
+ 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);
- col = uiLayoutColumn(layout, false);
+ col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "limit_method", 0, 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(col, ptr, "limit_method", 0, 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(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", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "limit_min", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
}
static void node_composit_buts_luma_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ 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);
+ 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);
}
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", 0, 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", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_antialiasing", 0, NULL, ICON_NONE);
}
static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- PointerRNA imfptr = RNA_pointer_get(ptr, "format");
- const bool multilayer = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER;
+ PointerRNA imfptr = RNA_pointer_get(ptr, "format");
+ const bool multilayer = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER;
- if (multilayer) {
- uiItemL(layout, IFACE_("Path:"), ICON_NONE);
- }
- else {
- uiItemL(layout, IFACE_("Base Path:"), ICON_NONE);
- }
- uiItemR(layout, ptr, "base_path", 0, "", ICON_NONE);
+ if (multilayer) {
+ uiItemL(layout, IFACE_("Path:"), ICON_NONE);
+ }
+ else {
+ uiItemL(layout, IFACE_("Base Path:"), ICON_NONE);
+ }
+ uiItemR(layout, ptr, "base_path", 0, "", ICON_NONE);
}
static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- Scene *scene = CTX_data_scene(C);
- PointerRNA imfptr = RNA_pointer_get(ptr, "format");
- PointerRNA active_input_ptr, op_ptr;
- wmOperatorType *ot;
- uiLayout *row, *col;
- int active_index;
- const bool multilayer = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER;
- const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
-
- node_composit_buts_file_output(layout, C, ptr);
- uiTemplateImageSettings(layout, &imfptr, false);
-
- /* disable stereo output for multilayer, too much work for something that no one will use */
- /* if someone asks for that we can implement it */
- if (is_multiview) {
- uiTemplateImageFormatViews(layout, &imfptr, NULL);
- }
-
- uiItemS(layout);
-
- uiItemO(layout, IFACE_("Add Input"), ICON_ADD, "NODE_OT_output_file_add_socket");
-
- row = uiLayoutRow(layout, false);
- col = uiLayoutColumn(row, true);
-
- active_index = RNA_int_get(ptr, "active_input_index");
- /* using different collection properties if multilayer format is enabled */
- if (multilayer) {
- uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "layer_slots", ptr, "active_input_index",
- NULL, 0, 0, 0, 0, false, false);
- RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "layer_slots"),
- active_index, &active_input_ptr);
- }
- else {
- uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "file_slots", ptr, "active_input_index",
- NULL, 0, 0, 0, 0, false, false);
- RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "file_slots"),
- active_index, &active_input_ptr);
- }
- /* XXX collection lookup does not return the ID part of the pointer,
- * setting this manually here */
- active_input_ptr.id.data = ptr->id.data;
-
- col = uiLayoutColumn(row, true);
- ot = WM_operatortype_find("NODE_OT_output_file_move_active_socket", false);
- uiItemFullO_ptr(col, ot, "", ICON_TRIA_UP, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
- RNA_enum_set(&op_ptr, "direction", 1);
- uiItemFullO_ptr(col, ot, "", ICON_TRIA_DOWN, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
- RNA_enum_set(&op_ptr, "direction", 2);
-
- if (active_input_ptr.data) {
- if (multilayer) {
- col = uiLayoutColumn(layout, true);
-
- uiItemL(col, IFACE_("Layer:"), ICON_NONE);
- row = uiLayoutRow(col, false);
- uiItemR(row, &active_input_ptr, "name", 0, "", ICON_NONE);
- uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "",
- ICON_X, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY, NULL);
- }
- else {
- col = uiLayoutColumn(layout, true);
-
- uiItemL(col, IFACE_("File Subpath:"), ICON_NONE);
- row = uiLayoutRow(col, false);
- uiItemR(row, &active_input_ptr, "path", 0, "", ICON_NONE);
- uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "",
- ICON_X, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY, NULL);
-
- /* format details for individual files */
- imfptr = RNA_pointer_get(&active_input_ptr, "format");
-
- col = uiLayoutColumn(layout, true);
- uiItemL(col, IFACE_("Format:"), ICON_NONE);
- uiItemR(col, &active_input_ptr, "use_node_format", 0, NULL, ICON_NONE);
-
- col = uiLayoutColumn(layout, false);
- uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format") == false);
- uiTemplateImageSettings(col, &imfptr, false);
-
- if (is_multiview) {
- uiTemplateImageFormatViews(layout, &imfptr, NULL);
- }
- }
- }
+ Scene *scene = CTX_data_scene(C);
+ PointerRNA imfptr = RNA_pointer_get(ptr, "format");
+ PointerRNA active_input_ptr, op_ptr;
+ wmOperatorType *ot;
+ uiLayout *row, *col;
+ int active_index;
+ const bool multilayer = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER;
+ const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
+
+ node_composit_buts_file_output(layout, C, ptr);
+ uiTemplateImageSettings(layout, &imfptr, false);
+
+ /* disable stereo output for multilayer, too much work for something that no one will use */
+ /* if someone asks for that we can implement it */
+ if (is_multiview) {
+ uiTemplateImageFormatViews(layout, &imfptr, NULL);
+ }
+
+ uiItemS(layout);
+
+ uiItemO(layout, IFACE_("Add Input"), ICON_ADD, "NODE_OT_output_file_add_socket");
+
+ row = uiLayoutRow(layout, false);
+ col = uiLayoutColumn(row, true);
+
+ active_index = RNA_int_get(ptr, "active_input_index");
+ /* using different collection properties if multilayer format is enabled */
+ if (multilayer) {
+ uiTemplateList(col,
+ C,
+ "UI_UL_list",
+ "file_output_node",
+ ptr,
+ "layer_slots",
+ ptr,
+ "active_input_index",
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ false,
+ false);
+ RNA_property_collection_lookup_int(
+ ptr, RNA_struct_find_property(ptr, "layer_slots"), active_index, &active_input_ptr);
+ }
+ else {
+ uiTemplateList(col,
+ C,
+ "UI_UL_list",
+ "file_output_node",
+ ptr,
+ "file_slots",
+ ptr,
+ "active_input_index",
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ false,
+ false);
+ RNA_property_collection_lookup_int(
+ ptr, RNA_struct_find_property(ptr, "file_slots"), active_index, &active_input_ptr);
+ }
+ /* XXX collection lookup does not return the ID part of the pointer,
+ * setting this manually here */
+ active_input_ptr.id.data = ptr->id.data;
+
+ col = uiLayoutColumn(row, true);
+ ot = WM_operatortype_find("NODE_OT_output_file_move_active_socket", false);
+ uiItemFullO_ptr(col, ot, "", ICON_TRIA_UP, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_enum_set(&op_ptr, "direction", 1);
+ uiItemFullO_ptr(col, ot, "", ICON_TRIA_DOWN, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_enum_set(&op_ptr, "direction", 2);
+
+ if (active_input_ptr.data) {
+ if (multilayer) {
+ col = uiLayoutColumn(layout, true);
+
+ uiItemL(col, IFACE_("Layer:"), ICON_NONE);
+ row = uiLayoutRow(col, false);
+ uiItemR(row, &active_input_ptr, "name", 0, "", ICON_NONE);
+ uiItemFullO(row,
+ "NODE_OT_output_file_remove_active_socket",
+ "",
+ ICON_X,
+ NULL,
+ WM_OP_EXEC_DEFAULT,
+ UI_ITEM_R_ICON_ONLY,
+ NULL);
+ }
+ else {
+ col = uiLayoutColumn(layout, true);
+
+ uiItemL(col, IFACE_("File Subpath:"), ICON_NONE);
+ row = uiLayoutRow(col, false);
+ uiItemR(row, &active_input_ptr, "path", 0, "", ICON_NONE);
+ uiItemFullO(row,
+ "NODE_OT_output_file_remove_active_socket",
+ "",
+ ICON_X,
+ NULL,
+ WM_OP_EXEC_DEFAULT,
+ UI_ITEM_R_ICON_ONLY,
+ NULL);
+
+ /* format details for individual files */
+ imfptr = RNA_pointer_get(&active_input_ptr, "format");
+
+ col = uiLayoutColumn(layout, true);
+ uiItemL(col, IFACE_("Format:"), ICON_NONE);
+ uiItemR(col, &active_input_ptr, "use_node_format", 0, NULL, ICON_NONE);
+
+ col = uiLayoutColumn(layout, false);
+ uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format") == false);
+ uiTemplateImageSettings(col, &imfptr, false);
+
+ if (is_multiview) {
+ uiTemplateImageFormatViews(layout, &imfptr, NULL);
+ }
+ }
+ }
}
static void node_composit_buts_scale(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "space", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "space", 0, "", 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);
- row = uiLayoutRow(layout, true);
- uiItemR(row, ptr, "offset_x", 0, "X", ICON_NONE);
- uiItemR(row, ptr, "offset_y", 0, "Y", 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);
+ row = uiLayoutRow(layout, true);
+ uiItemR(row, ptr, "offset_x", 0, "X", ICON_NONE);
+ uiItemR(row, ptr, "offset_y", 0, "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", 0, "", ICON_NONE);
}
static void node_composit_buts_invert(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ uiLayout *col;
- col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "invert_rgb", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "invert_alpha", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, ptr, "invert_rgb", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "invert_alpha", 0, 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", 0, "", 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", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
}
static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *split, *col, *row;
+ uiLayout *split, *col, *row;
- uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE);
- if (RNA_enum_get(ptr, "correction_method") == 0) {
+ if (RNA_enum_get(ptr, "correction_method") == 0) {
- split = uiLayoutSplit(layout, 0.0f, false);
- col = uiLayoutColumn(split, false);
- uiTemplateColorPicker(col, ptr, "lift", 1, 1, 0, 1);
- row = uiLayoutRow(col, false);
- uiItemR(row, ptr, "lift", 0, NULL, ICON_NONE);
+ split = uiLayoutSplit(layout, 0.0f, false);
+ col = uiLayoutColumn(split, false);
+ uiTemplateColorPicker(col, ptr, "lift", 1, 1, 0, 1);
+ row = uiLayoutRow(col, false);
+ uiItemR(row, ptr, "lift", 0, 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);
+ col = uiLayoutColumn(split, false);
+ uiTemplateColorPicker(col, ptr, "gamma", 1, 1, 1, 1);
+ row = uiLayoutRow(col, false);
+ uiItemR(row, ptr, "gamma", 0, 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);
+ col = uiLayoutColumn(split, false);
+ uiTemplateColorPicker(col, ptr, "gain", 1, 1, 1, 1);
+ row = uiLayoutRow(col, false);
+ uiItemR(row, ptr, "gain", 0, NULL, ICON_NONE);
+ }
+ else {
- }
- else {
+ split = uiLayoutSplit(layout, 0.0f, false);
+ 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);
- split = uiLayoutSplit(layout, 0.0f, false);
- 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);
-
- col = uiLayoutColumn(split, false);
- uiTemplateColorPicker(col, ptr, "power", 1, 1, 0, 1);
- row = uiLayoutRow(col, false);
- uiItemR(row, ptr, "power", 0, 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);
- }
+ col = uiLayoutColumn(split, false);
+ uiTemplateColorPicker(col, ptr, "power", 1, 1, 0, 1);
+ row = uiLayoutRow(col, false);
+ uiItemR(row, ptr, "power", 0, 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);
+ }
}
-static void node_composit_buts_colorbalance_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+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", 0, NULL, ICON_NONE);
- if (RNA_enum_get(ptr, "correction_method") == 0) {
+ if (RNA_enum_get(ptr, "correction_method") == 0) {
- uiTemplateColorPicker(layout, ptr, "lift", 1, 1, 0, 1);
- uiItemR(layout, ptr, "lift", 0, NULL, ICON_NONE);
+ uiTemplateColorPicker(layout, ptr, "lift", 1, 1, 0, 1);
+ uiItemR(layout, ptr, "lift", 0, NULL, ICON_NONE);
- uiTemplateColorPicker(layout, ptr, "gamma", 1, 1, 1, 1);
- uiItemR(layout, ptr, "gamma", 0, NULL, ICON_NONE);
+ uiTemplateColorPicker(layout, ptr, "gamma", 1, 1, 1, 1);
+ uiItemR(layout, ptr, "gamma", 0, NULL, ICON_NONE);
- uiTemplateColorPicker(layout, ptr, "gain", 1, 1, 1, 1);
- uiItemR(layout, ptr, "gain", 0, NULL, ICON_NONE);
- }
- else {
- uiTemplateColorPicker(layout, ptr, "offset", 1, 1, 0, 1);
- uiItemR(layout, ptr, "offset", 0, NULL, ICON_NONE);
+ uiTemplateColorPicker(layout, ptr, "gain", 1, 1, 1, 1);
+ uiItemR(layout, ptr, "gain", 0, NULL, ICON_NONE);
+ }
+ else {
+ uiTemplateColorPicker(layout, ptr, "offset", 1, 1, 0, 1);
+ uiItemR(layout, ptr, "offset", 0, NULL, ICON_NONE);
- uiTemplateColorPicker(layout, ptr, "power", 1, 1, 0, 1);
- uiItemR(layout, ptr, "power", 0, NULL, ICON_NONE);
+ uiTemplateColorPicker(layout, ptr, "power", 1, 1, 0, 1);
+ uiItemR(layout, ptr, "power", 0, NULL, ICON_NONE);
- uiTemplateColorPicker(layout, ptr, "slope", 1, 1, 0, 1);
- uiItemR(layout, ptr, "slope", 0, NULL, ICON_NONE);
- }
+ uiTemplateColorPicker(layout, ptr, "slope", 1, 1, 0, 1);
+ uiItemR(layout, ptr, "slope", 0, NULL, ICON_NONE);
+ }
}
-
static void node_composit_buts_huecorrect(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- bNode *node = ptr->data;
- CurveMapping *cumap = node->storage;
+ bNode *node = ptr->data;
+ CurveMapping *cumap = node->storage;
- if (_sample_col[0] != SAMPLE_FLT_ISNONE) {
- cumap->flag |= CUMA_DRAW_SAMPLE;
- copy_v3_v3(cumap->sample, _sample_col);
- }
- else {
- cumap->flag &= ~CUMA_DRAW_SAMPLE;
- }
+ if (_sample_col[0] != SAMPLE_FLT_ISNONE) {
+ cumap->flag |= CUMA_DRAW_SAMPLE;
+ copy_v3_v3(cumap->sample, _sample_col);
+ }
+ else {
+ cumap->flag &= ~CUMA_DRAW_SAMPLE;
+ }
- uiTemplateCurveMapping(layout, ptr, "mapping", 'h', false, false, false, false);
+ uiTemplateCurveMapping(layout, ptr, "mapping", 'h', false, false, false, false);
}
static void node_composit_buts_ycc(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
}
static void node_composit_buts_movieclip(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+ uiTemplateID(
+ layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
}
static void node_composit_buts_movieclip_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- bNode *node = ptr->data;
- PointerRNA clipptr;
+ bNode *node = ptr->data;
+ PointerRNA clipptr;
- uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+ uiTemplateID(
+ layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
- if (!node->id) {
- return;
- }
+ if (!node->id) {
+ return;
+ }
- clipptr = RNA_pointer_get(ptr, "clip");
+ clipptr = RNA_pointer_get(ptr, "clip");
- uiTemplateColorspaceSettings(layout, &clipptr, "colorspace_settings");
+ uiTemplateColorspaceSettings(layout, &clipptr, "colorspace_settings");
}
static void node_composit_buts_stabilize2d(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- bNode *node = ptr->data;
+ bNode *node = ptr->data;
- uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+ uiTemplateID(
+ layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
- if (!node->id) {
- return;
- }
+ if (!node->id) {
+ return;
+ }
- uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "invert", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "invert", 0, 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", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "wrap_axis", 0, 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", 0, "", ICON_NONE);
}
static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- bNode *node = ptr->data;
-
- uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
-
- if (!node->id) {
- return;
- }
-
- uiItemR(layout, ptr, "distortion_type", 0, "", ICON_NONE);
-}
-
-static void node_composit_buts_colorcorrection(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
-{
- 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);
-
- row = uiLayoutRow(layout, false);
- uiItemL(row, "", ICON_NONE);
- uiItemL(row, IFACE_("Saturation"), ICON_NONE);
- uiItemL(row, IFACE_("Contrast"), ICON_NONE);
- uiItemL(row, IFACE_("Gamma"), ICON_NONE);
- uiItemL(row, IFACE_("Gain"), ICON_NONE);
- uiItemL(row, IFACE_("Lift"), ICON_NONE);
-
- 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);
-
- 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);
-
- 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);
-
- 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);
-
- 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);
-}
-
-static void node_composit_buts_colorcorrection_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
-{
- 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);
- 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);
-
- 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);
-
- 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);
-
- 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);
-
- 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);
-
- row = uiLayoutRow(layout, false);
- uiItemR(row, ptr, "midtones_start", 0, NULL, ICON_NONE);
- uiItemR(row, ptr, "midtones_end", 0, NULL, ICON_NONE);
+ bNode *node = ptr->data;
+
+ uiTemplateID(
+ layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+
+ if (!node->id) {
+ return;
+ }
+
+ uiItemR(layout, ptr, "distortion_type", 0, "", ICON_NONE);
+}
+
+static void node_composit_buts_colorcorrection(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ 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);
+
+ row = uiLayoutRow(layout, false);
+ uiItemL(row, "", ICON_NONE);
+ uiItemL(row, IFACE_("Saturation"), ICON_NONE);
+ uiItemL(row, IFACE_("Contrast"), ICON_NONE);
+ uiItemL(row, IFACE_("Gamma"), ICON_NONE);
+ uiItemL(row, IFACE_("Gain"), ICON_NONE);
+ uiItemL(row, IFACE_("Lift"), ICON_NONE);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ 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);
+}
+
+static void node_composit_buts_colorcorrection_ex(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ 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);
+ 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);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, ptr, "midtones_start", 0, NULL, ICON_NONE);
+ uiItemR(row, ptr, "midtones_end", 0, 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", 0, NULL, ICON_NONE);
}
-static void node_composit_buts_switch_view_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *UNUSED(ptr))
+static void node_composit_buts_switch_view_ex(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *UNUSED(ptr))
{
- uiItemFullO(
- layout, "NODE_OT_switch_view_update",
- "Update Views", ICON_FILE_REFRESH, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL);
+ uiItemFullO(layout,
+ "NODE_OT_switch_view_update",
+ "Update Views",
+ ICON_FILE_REFRESH,
+ NULL,
+ WM_OP_INVOKE_DEFAULT,
+ 0,
+ NULL);
}
static void node_composit_buts_boxmask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *row;
+ uiLayout *row;
- row = uiLayoutRow(layout, true);
- uiItemR(row, ptr, "x", 0, NULL, ICON_NONE);
- uiItemR(row, ptr, "y", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(layout, true);
+ uiItemR(row, ptr, "x", 0, NULL, ICON_NONE);
+ uiItemR(row, ptr, "y", 0, 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);
+ 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(layout, ptr, "rotation", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "mask_type", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "rotation", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "mask_type", 0, 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", 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);
}
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", 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);
}
-static void node_composit_backdrop_viewer(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
+static void node_composit_backdrop_viewer(
+ SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
{
-// node_composit_backdrop_canvas(snode, backdrop, node, x, y);
- if (node->custom1 == 0) {
- const float backdropWidth = backdrop->x;
- const float backdropHeight = backdrop->y;
- const float cx = x + snode->zoom * backdropWidth * node->custom3;
- const float cy = y + snode->zoom * backdropHeight * node->custom4;
- const float cross_size = 12 * U.pixelsize;
+ // node_composit_backdrop_canvas(snode, backdrop, node, x, y);
+ if (node->custom1 == 0) {
+ const float backdropWidth = backdrop->x;
+ const float backdropHeight = backdrop->y;
+ const float cx = x + snode->zoom * backdropWidth * node->custom3;
+ const float cy = y + snode->zoom * backdropHeight * node->custom4;
+ const float cross_size = 12 * U.pixelsize;
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3f(1.0f, 1.0f, 1.0f);
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
- immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, cx - cross_size, cy - cross_size);
- immVertex2f(pos, cx + cross_size, cy + cross_size);
- immVertex2f(pos, cx + cross_size, cy - cross_size);
- immVertex2f(pos, cx - cross_size, cy + cross_size);
- immEnd();
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex2f(pos, cx - cross_size, cy - cross_size);
+ immVertex2f(pos, cx + cross_size, cy + cross_size);
+ immVertex2f(pos, cx + cross_size, cy - cross_size);
+ immVertex2f(pos, cx - cross_size, cy + cross_size);
+ immEnd();
- immUnbindProgram();
- }
+ immUnbindProgram();
+ }
}
-static void node_composit_backdrop_boxmask(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
+static void node_composit_backdrop_boxmask(
+ SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
{
- NodeBoxMask *boxmask = node->storage;
- const float backdropWidth = backdrop->x;
- const float backdropHeight = backdrop->y;
- const float aspect = backdropWidth / backdropHeight;
- const float rad = -boxmask->rotation;
- const float cosine = cosf(rad);
- const float sine = sinf(rad);
- const float halveBoxWidth = backdropWidth * (boxmask->width / 2.0f);
- const float halveBoxHeight = backdropHeight * (boxmask->height / 2.0f) * aspect;
+ NodeBoxMask *boxmask = node->storage;
+ const float backdropWidth = backdrop->x;
+ const float backdropHeight = backdrop->y;
+ const float aspect = backdropWidth / backdropHeight;
+ const float rad = -boxmask->rotation;
+ const float cosine = cosf(rad);
+ const float sine = sinf(rad);
+ const float halveBoxWidth = backdropWidth * (boxmask->width / 2.0f);
+ const float halveBoxHeight = backdropHeight * (boxmask->height / 2.0f) * aspect;
- float cx, cy, x1, x2, x3, x4;
- float y1, y2, y3, y4;
+ float cx, cy, x1, x2, x3, x4;
+ float y1, y2, y3, y4;
- cx = x + snode->zoom * backdropWidth * boxmask->x;
- cy = y + snode->zoom * backdropHeight * boxmask->y;
+ cx = x + snode->zoom * backdropWidth * boxmask->x;
+ cy = y + snode->zoom * backdropHeight * boxmask->y;
- x1 = cx - (cosine * halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
- x2 = cx - (cosine * -halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
- x3 = cx - (cosine * -halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
- x4 = cx - (cosine * halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
- y1 = cy - (-sine * halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
- y2 = cy - (-sine * -halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
- y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
- y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
+ x1 = cx - (cosine * halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
+ x2 = cx - (cosine * -halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
+ x3 = cx - (cosine * -halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
+ x4 = cx - (cosine * halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
+ y1 = cy - (-sine * halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
+ y2 = cy - (-sine * -halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
+ y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
+ y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3f(1.0f, 1.0f, 1.0f);
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
- immBegin(GPU_PRIM_LINE_LOOP, 4);
- immVertex2f(pos, x1, y1);
- immVertex2f(pos, x2, y2);
- immVertex2f(pos, x3, y3);
- immVertex2f(pos, x4, y4);
- immEnd();
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x3, y3);
+ immVertex2f(pos, x4, y4);
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
}
-static void node_composit_backdrop_ellipsemask(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
+static void node_composit_backdrop_ellipsemask(
+ SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
{
- NodeEllipseMask *ellipsemask = node->storage;
- const float backdropWidth = backdrop->x;
- const float backdropHeight = backdrop->y;
- const float aspect = backdropWidth / backdropHeight;
- const float rad = -ellipsemask->rotation;
- const float cosine = cosf(rad);
- const float sine = sinf(rad);
- const float halveBoxWidth = backdropWidth * (ellipsemask->width / 2.0f);
- const float halveBoxHeight = backdropHeight * (ellipsemask->height / 2.0f) * aspect;
+ NodeEllipseMask *ellipsemask = node->storage;
+ const float backdropWidth = backdrop->x;
+ const float backdropHeight = backdrop->y;
+ const float aspect = backdropWidth / backdropHeight;
+ const float rad = -ellipsemask->rotation;
+ const float cosine = cosf(rad);
+ const float sine = sinf(rad);
+ const float halveBoxWidth = backdropWidth * (ellipsemask->width / 2.0f);
+ const float halveBoxHeight = backdropHeight * (ellipsemask->height / 2.0f) * aspect;
- float cx, cy, x1, x2, x3, x4;
- float y1, y2, y3, y4;
+ float cx, cy, x1, x2, x3, x4;
+ float y1, y2, y3, y4;
- cx = x + snode->zoom * backdropWidth * ellipsemask->x;
- cy = y + snode->zoom * backdropHeight * ellipsemask->y;
+ cx = x + snode->zoom * backdropWidth * ellipsemask->x;
+ cy = y + snode->zoom * backdropHeight * ellipsemask->y;
- x1 = cx - (cosine * halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
- x2 = cx - (cosine * -halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
- x3 = cx - (cosine * -halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
- x4 = cx - (cosine * halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
- y1 = cy - (-sine * halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
- y2 = cy - (-sine * -halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
- y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
- y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
+ x1 = cx - (cosine * halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
+ x2 = cx - (cosine * -halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
+ x3 = cx - (cosine * -halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
+ x4 = cx - (cosine * halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
+ y1 = cy - (-sine * halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
+ y2 = cy - (-sine * -halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
+ y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
+ y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3f(1.0f, 1.0f, 1.0f);
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
- immBegin(GPU_PRIM_LINE_LOOP, 4);
- immVertex2f(pos, x1, y1);
- immVertex2f(pos, x2, y2);
- immVertex2f(pos, x3, y3);
- immVertex2f(pos, x4, y4);
- immEnd();
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x3, y3);
+ immVertex2f(pos, x4, y4);
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
}
static void node_composit_buts_ellipsemask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *row;
- row = uiLayoutRow(layout, true);
- uiItemR(row, ptr, "x", 0, NULL, ICON_NONE);
- uiItemR(row, ptr, "y", 0, 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);
+ uiLayout *row;
+ row = uiLayoutRow(layout, true);
+ uiItemR(row, ptr, "x", 0, NULL, ICON_NONE);
+ uiItemR(row, ptr, "y", 0, 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(layout, ptr, "rotation", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "mask_type", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "rotation", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "mask_type", 0, 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", 0, 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", 0, NULL, ICON_NONE);
}
static void node_composit_buts_viewer_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ uiLayout *col;
- uiItemR(layout, ptr, "use_alpha", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "tile_order", 0, 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(layout, ptr, "use_alpha", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "tile_order", 0, 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);
+ }
}
static void node_composit_buts_mask(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- bNode *node = ptr->data;
+ bNode *node = ptr->data;
- uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
- uiItemR(layout, ptr, "use_feather", 0, NULL, ICON_NONE);
+ uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+ uiItemR(layout, ptr, "use_feather", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "size_source", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "size_source", 0, "", 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);
- }
+ 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, "use_motion_blur", 0, 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, "use_motion_blur", 0, 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);
+ }
}
static void node_composit_buts_keyingscreen(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- bNode *node = ptr->data;
+ bNode *node = ptr->data;
- uiTemplateID(layout, C, ptr, "clip", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+ uiTemplateID(layout, C, ptr, "clip", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
- if (node->id) {
- MovieClip *clip = (MovieClip *) node->id;
- uiLayout *col;
- PointerRNA tracking_ptr;
+ if (node->id) {
+ MovieClip *clip = (MovieClip *)node->id;
+ uiLayout *col;
+ PointerRNA tracking_ptr;
- RNA_pointer_create(&clip->id, &RNA_MovieTracking, &clip->tracking, &tracking_ptr);
+ RNA_pointer_create(&clip->id, &RNA_MovieTracking, &clip->tracking, &tracking_ptr);
- col = uiLayoutColumn(layout, true);
- uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA);
- }
+ col = uiLayoutColumn(layout, true);
+ uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA);
+ }
}
static void node_composit_buts_keying(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- /* bNode *node = ptr->data; */ /* UNUSED */
+ /* 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", 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);
}
static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- bNode *node = ptr->data;
+ bNode *node = ptr->data;
- uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+ uiTemplateID(
+ layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
- if (node->id) {
- MovieClip *clip = (MovieClip *) node->id;
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *object;
- uiLayout *col;
- PointerRNA tracking_ptr;
- NodeTrackPosData *data = node->storage;
+ if (node->id) {
+ MovieClip *clip = (MovieClip *)node->id;
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *object;
+ uiLayout *col;
+ PointerRNA tracking_ptr;
+ NodeTrackPosData *data = node->storage;
- RNA_pointer_create(&clip->id, &RNA_MovieTracking, tracking, &tracking_ptr);
+ RNA_pointer_create(&clip->id, &RNA_MovieTracking, tracking, &tracking_ptr);
- col = uiLayoutColumn(layout, false);
- uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA);
+ col = uiLayoutColumn(layout, false);
+ uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA);
- object = BKE_tracking_object_get_named(tracking, data->tracking_object);
- if (object) {
- PointerRNA object_ptr;
+ object = BKE_tracking_object_get_named(tracking, data->tracking_object);
+ if (object) {
+ PointerRNA object_ptr;
- RNA_pointer_create(&clip->id, &RNA_MovieTrackingObject, object, &object_ptr);
+ RNA_pointer_create(&clip->id, &RNA_MovieTrackingObject, object, &object_ptr);
- uiItemPointerR(col, ptr, "track_name", &object_ptr, "tracks", "", ICON_ANIM_DATA);
- }
- else {
- uiItemR(layout, ptr, "track_name", 0, "", ICON_ANIM_DATA);
- }
+ uiItemPointerR(col, ptr, "track_name", &object_ptr, "tracks", "", ICON_ANIM_DATA);
+ }
+ else {
+ uiItemR(layout, ptr, "track_name", 0, "", ICON_ANIM_DATA);
+ }
- uiItemR(layout, ptr, "position", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "position", 0, NULL, ICON_NONE);
- if (ELEM(node->custom1, CMP_TRACKPOS_RELATIVE_FRAME, CMP_TRACKPOS_ABSOLUTE_FRAME)) {
- uiItemR(layout, ptr, "frame_relative", 0, NULL, ICON_NONE);
- }
- }
+ if (ELEM(node->custom1, CMP_TRACKPOS_RELATIVE_FRAME, CMP_TRACKPOS_ABSOLUTE_FRAME)) {
+ uiItemR(layout, ptr, "frame_relative", 0, NULL, ICON_NONE);
+ }
+ }
}
static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- bNode *node = ptr->data;
- NodePlaneTrackDeformData *data = node->storage;
+ bNode *node = ptr->data;
+ NodePlaneTrackDeformData *data = node->storage;
- uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+ uiTemplateID(
+ layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
- if (node->id) {
- MovieClip *clip = (MovieClip *) node->id;
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *object;
- uiLayout *col;
- PointerRNA tracking_ptr;
+ if (node->id) {
+ MovieClip *clip = (MovieClip *)node->id;
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *object;
+ uiLayout *col;
+ PointerRNA tracking_ptr;
- RNA_pointer_create(&clip->id, &RNA_MovieTracking, tracking, &tracking_ptr);
+ RNA_pointer_create(&clip->id, &RNA_MovieTracking, tracking, &tracking_ptr);
- col = uiLayoutColumn(layout, false);
- uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA);
+ col = uiLayoutColumn(layout, false);
+ uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA);
- object = BKE_tracking_object_get_named(tracking, data->tracking_object);
- if (object) {
- PointerRNA object_ptr;
+ object = BKE_tracking_object_get_named(tracking, data->tracking_object);
+ if (object) {
+ PointerRNA object_ptr;
- RNA_pointer_create(&clip->id, &RNA_MovieTrackingObject, object, &object_ptr);
+ RNA_pointer_create(&clip->id, &RNA_MovieTrackingObject, object, &object_ptr);
- uiItemPointerR(col, ptr, "plane_track_name", &object_ptr, "plane_tracks", "", ICON_ANIM_DATA);
- }
- else {
- uiItemR(layout, ptr, "plane_track_name", 0, "", ICON_ANIM_DATA);
- }
- }
+ uiItemPointerR(
+ col, ptr, "plane_track_name", &object_ptr, "plane_tracks", "", ICON_ANIM_DATA);
+ }
+ else {
+ uiItemR(layout, ptr, "plane_track_name", 0, "", ICON_ANIM_DATA);
+ }
+ }
- uiItemR(layout, ptr, "use_motion_blur", 0, 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, "use_motion_blur", 0, 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);
+ }
}
-static void node_composit_buts_cornerpin(uiLayout *UNUSED(layout), bContext *UNUSED(C), PointerRNA *UNUSED(ptr))
+static void node_composit_buts_cornerpin(uiLayout *UNUSED(layout),
+ bContext *UNUSED(C),
+ PointerRNA *UNUSED(ptr))
{
}
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", UI_ITEM_R_EXPAND, "", ICON_NONE);
+ uiItemR(layout, ptr, "ray_length", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
}
static void node_composit_buts_cryptomatte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col = uiLayoutColumn(layout, true);
+ uiLayout *col = uiLayoutColumn(layout, true);
- uiItemL(col, IFACE_("Matte Objects:"), ICON_NONE);
+ uiItemL(col, IFACE_("Matte Objects:"), ICON_NONE);
- uiLayout *row = uiLayoutRow(col, true);
- uiTemplateCryptoPicker(row, ptr, "add");
- uiTemplateCryptoPicker(row, ptr, "remove");
+ uiLayout *row = uiLayoutRow(col, true);
+ uiTemplateCryptoPicker(row, ptr, "add");
+ uiTemplateCryptoPicker(row, ptr, "remove");
- uiItemR(col, ptr, "matte_id", 0, "", ICON_NONE);
+ uiItemR(col, ptr, "matte_id", 0, "", ICON_NONE);
}
-static void node_composit_buts_cryptomatte_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *UNUSED(ptr))
+static void node_composit_buts_cryptomatte_ex(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *UNUSED(ptr))
{
- uiItemO(layout, IFACE_("Add Crypto Layer"), ICON_ADD, "NODE_OT_cryptomatte_layer_add");
- uiItemO(layout, IFACE_("Remove Crypto Layer"), ICON_REMOVE, "NODE_OT_cryptomatte_layer_remove");
+ uiItemO(layout, IFACE_("Add Crypto Layer"), ICON_ADD, "NODE_OT_cryptomatte_layer_add");
+ uiItemO(layout, IFACE_("Remove Crypto Layer"), ICON_REMOVE, "NODE_OT_cryptomatte_layer_remove");
}
-static void node_composit_buts_brightcontrast(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+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", 0, NULL, ICON_NONE);
}
/* only once called */
static void node_composit_set_butfunc(bNodeType *ntype)
{
- switch (ntype->type) {
- case CMP_NODE_IMAGE:
- ntype->draw_buttons = node_composit_buts_image;
- ntype->draw_buttons_ex = node_composit_buts_image_ex;
- break;
- case CMP_NODE_R_LAYERS:
- ntype->draw_buttons = node_composit_buts_viewlayers;
- break;
- case CMP_NODE_NORMAL:
- ntype->draw_buttons = node_buts_normal;
- break;
- case CMP_NODE_CURVE_VEC:
- ntype->draw_buttons = node_buts_curvevec;
- break;
- case CMP_NODE_CURVE_RGB:
- ntype->draw_buttons = node_buts_curvecol;
- break;
- case CMP_NODE_VALUE:
- ntype->draw_buttons = node_buts_value;
- break;
- case CMP_NODE_RGB:
- ntype->draw_buttons = node_buts_rgb;
- break;
- case CMP_NODE_FLIP:
- ntype->draw_buttons = node_composit_buts_flip;
- break;
- case CMP_NODE_SPLITVIEWER:
- ntype->draw_buttons = node_composit_buts_splitviewer;
- break;
- case CMP_NODE_MIX_RGB:
- ntype->draw_buttons = node_buts_mix_rgb;
- break;
- case CMP_NODE_VALTORGB:
- ntype->draw_buttons = node_buts_colorramp;
- break;
- case CMP_NODE_CROP:
- ntype->draw_buttons = node_composit_buts_crop;
- break;
- case CMP_NODE_BLUR:
- ntype->draw_buttons = node_composit_buts_blur;
- break;
- case CMP_NODE_DBLUR:
- ntype->draw_buttons = node_composit_buts_dblur;
- break;
- case CMP_NODE_BILATERALBLUR:
- ntype->draw_buttons = node_composit_buts_bilateralblur;
- break;
- case CMP_NODE_DEFOCUS:
- ntype->draw_buttons = node_composit_buts_defocus;
- break;
- case CMP_NODE_GLARE:
- ntype->draw_buttons = node_composit_buts_glare;
- break;
- case CMP_NODE_TONEMAP:
- ntype->draw_buttons = node_composit_buts_tonemap;
- break;
- case CMP_NODE_LENSDIST:
- ntype->draw_buttons = node_composit_buts_lensdist;
- break;
- case CMP_NODE_VECBLUR:
- ntype->draw_buttons = node_composit_buts_vecblur;
- break;
- case CMP_NODE_FILTER:
- ntype->draw_buttons = node_composit_buts_filter;
- break;
- case CMP_NODE_MAP_VALUE:
- ntype->draw_buttons = node_composit_buts_map_value;
- break;
- case CMP_NODE_MAP_RANGE:
- ntype->draw_buttons = node_composit_buts_map_range;
- break;
- case CMP_NODE_TIME:
- ntype->draw_buttons = node_buts_time;
- break;
- case CMP_NODE_ALPHAOVER:
- ntype->draw_buttons = node_composit_buts_alphaover;
- break;
- case CMP_NODE_TEXTURE:
- ntype->draw_buttons = node_buts_texture;
- break;
- case CMP_NODE_DILATEERODE:
- ntype->draw_buttons = node_composit_buts_dilateerode;
- break;
- case CMP_NODE_INPAINT:
- ntype->draw_buttons = node_composit_buts_inpaint;
- break;
- case CMP_NODE_DESPECKLE:
- ntype->draw_buttons = node_composit_buts_despeckle;
- break;
- case CMP_NODE_OUTPUT_FILE:
- ntype->draw_buttons = node_composit_buts_file_output;
- ntype->draw_buttons_ex = node_composit_buts_file_output_ex;
- break;
- case CMP_NODE_DIFF_MATTE:
- ntype->draw_buttons = node_composit_buts_diff_matte;
- break;
- case CMP_NODE_DIST_MATTE:
- ntype->draw_buttons = node_composit_buts_distance_matte;
- break;
- case CMP_NODE_COLOR_SPILL:
- ntype->draw_buttons = node_composit_buts_color_spill;
- break;
- case CMP_NODE_CHROMA_MATTE:
- ntype->draw_buttons = node_composit_buts_chroma_matte;
- break;
- case CMP_NODE_COLOR_MATTE:
- ntype->draw_buttons = node_composit_buts_color_matte;
- break;
- case CMP_NODE_SCALE:
- ntype->draw_buttons = node_composit_buts_scale;
- break;
- case CMP_NODE_ROTATE:
- ntype->draw_buttons = node_composit_buts_rotate;
- break;
- case CMP_NODE_CHANNEL_MATTE:
- ntype->draw_buttons = node_composit_buts_channel_matte;
- break;
- case CMP_NODE_LUMA_MATTE:
- ntype->draw_buttons = node_composit_buts_luma_matte;
- break;
- case CMP_NODE_MAP_UV:
- ntype->draw_buttons = node_composit_buts_map_uv;
- break;
- case CMP_NODE_ID_MASK:
- ntype->draw_buttons = node_composit_buts_id_mask;
- break;
- case CMP_NODE_DOUBLEEDGEMASK:
- ntype->draw_buttons = node_composit_buts_double_edge_mask;
- break;
- case CMP_NODE_MATH:
- ntype->draw_buttons = node_buts_math;
- break;
- case CMP_NODE_INVERT:
- ntype->draw_buttons = node_composit_buts_invert;
- break;
- case CMP_NODE_PREMULKEY:
- ntype->draw_buttons = node_composit_buts_premulkey;
- break;
- case CMP_NODE_VIEW_LEVELS:
- ntype->draw_buttons = node_composit_buts_view_levels;
- break;
- case CMP_NODE_COLORBALANCE:
- ntype->draw_buttons = node_composit_buts_colorbalance;
- ntype->draw_buttons_ex = node_composit_buts_colorbalance_ex;
- break;
- case CMP_NODE_HUECORRECT:
- ntype->draw_buttons = node_composit_buts_huecorrect;
- break;
- case CMP_NODE_ZCOMBINE:
- ntype->draw_buttons = node_composit_buts_zcombine;
- break;
- case CMP_NODE_COMBYCCA:
- case CMP_NODE_SEPYCCA:
- ntype->draw_buttons = node_composit_buts_ycc;
- break;
- case CMP_NODE_MOVIECLIP:
- ntype->draw_buttons = node_composit_buts_movieclip;
- ntype->draw_buttons_ex = node_composit_buts_movieclip_ex;
- break;
- case CMP_NODE_STABILIZE2D:
- ntype->draw_buttons = node_composit_buts_stabilize2d;
- break;
- case CMP_NODE_TRANSFORM:
- ntype->draw_buttons = node_composit_buts_transform;
- break;
- case CMP_NODE_TRANSLATE:
- ntype->draw_buttons = node_composit_buts_translate;
- break;
- case CMP_NODE_MOVIEDISTORTION:
- ntype->draw_buttons = node_composit_buts_moviedistortion;
- break;
- case CMP_NODE_COLORCORRECTION:
- ntype->draw_buttons = node_composit_buts_colorcorrection;
- ntype->draw_buttons_ex = node_composit_buts_colorcorrection_ex;
- break;
- case CMP_NODE_SWITCH:
- ntype->draw_buttons = node_composit_buts_switch;
- break;
- case CMP_NODE_SWITCH_VIEW:
- ntype->draw_buttons_ex = node_composit_buts_switch_view_ex;
- break;
- case CMP_NODE_MASK_BOX:
- ntype->draw_buttons = node_composit_buts_boxmask;
- ntype->draw_backdrop = node_composit_backdrop_boxmask;
- break;
- case CMP_NODE_MASK_ELLIPSE:
- ntype->draw_buttons = node_composit_buts_ellipsemask;
- ntype->draw_backdrop = node_composit_backdrop_ellipsemask;
- break;
- case CMP_NODE_BOKEHIMAGE:
- ntype->draw_buttons = node_composit_buts_bokehimage;
- break;
- case CMP_NODE_BOKEHBLUR:
- ntype->draw_buttons = node_composit_buts_bokehblur;
- break;
- case CMP_NODE_VIEWER:
- ntype->draw_buttons = node_composit_buts_viewer;
- ntype->draw_buttons_ex = node_composit_buts_viewer_ex;
- ntype->draw_backdrop = node_composit_backdrop_viewer;
- break;
- case CMP_NODE_COMPOSITE:
- ntype->draw_buttons = node_composit_buts_composite;
- break;
- case CMP_NODE_MASK:
- ntype->draw_buttons = node_composit_buts_mask;
- break;
- case CMP_NODE_KEYINGSCREEN:
- ntype->draw_buttons = node_composit_buts_keyingscreen;
- break;
- case CMP_NODE_KEYING:
- ntype->draw_buttons = node_composit_buts_keying;
- break;
- case CMP_NODE_TRACKPOS:
- ntype->draw_buttons = node_composit_buts_trackpos;
- break;
- case CMP_NODE_PLANETRACKDEFORM:
- ntype->draw_buttons = node_composit_buts_planetrackdeform;
- break;
- case CMP_NODE_CORNERPIN:
- ntype->draw_buttons = node_composit_buts_cornerpin;
- break;
- case CMP_NODE_SUNBEAMS:
- ntype->draw_buttons = node_composit_buts_sunbeams;
- break;
- case CMP_NODE_CRYPTOMATTE:
- ntype->draw_buttons = node_composit_buts_cryptomatte;
- ntype->draw_buttons_ex = node_composit_buts_cryptomatte_ex;
- break;
- case CMP_NODE_BRIGHTCONTRAST:
- ntype->draw_buttons = node_composit_buts_brightcontrast;
- }
+ switch (ntype->type) {
+ case CMP_NODE_IMAGE:
+ ntype->draw_buttons = node_composit_buts_image;
+ ntype->draw_buttons_ex = node_composit_buts_image_ex;
+ break;
+ case CMP_NODE_R_LAYERS:
+ ntype->draw_buttons = node_composit_buts_viewlayers;
+ break;
+ case CMP_NODE_NORMAL:
+ ntype->draw_buttons = node_buts_normal;
+ break;
+ case CMP_NODE_CURVE_VEC:
+ ntype->draw_buttons = node_buts_curvevec;
+ break;
+ case CMP_NODE_CURVE_RGB:
+ ntype->draw_buttons = node_buts_curvecol;
+ break;
+ case CMP_NODE_VALUE:
+ ntype->draw_buttons = node_buts_value;
+ break;
+ case CMP_NODE_RGB:
+ ntype->draw_buttons = node_buts_rgb;
+ break;
+ case CMP_NODE_FLIP:
+ ntype->draw_buttons = node_composit_buts_flip;
+ break;
+ case CMP_NODE_SPLITVIEWER:
+ ntype->draw_buttons = node_composit_buts_splitviewer;
+ break;
+ case CMP_NODE_MIX_RGB:
+ ntype->draw_buttons = node_buts_mix_rgb;
+ break;
+ case CMP_NODE_VALTORGB:
+ ntype->draw_buttons = node_buts_colorramp;
+ break;
+ case CMP_NODE_CROP:
+ ntype->draw_buttons = node_composit_buts_crop;
+ break;
+ case CMP_NODE_BLUR:
+ ntype->draw_buttons = node_composit_buts_blur;
+ break;
+ case CMP_NODE_DBLUR:
+ ntype->draw_buttons = node_composit_buts_dblur;
+ break;
+ case CMP_NODE_BILATERALBLUR:
+ ntype->draw_buttons = node_composit_buts_bilateralblur;
+ break;
+ case CMP_NODE_DEFOCUS:
+ ntype->draw_buttons = node_composit_buts_defocus;
+ break;
+ case CMP_NODE_GLARE:
+ ntype->draw_buttons = node_composit_buts_glare;
+ break;
+ case CMP_NODE_TONEMAP:
+ ntype->draw_buttons = node_composit_buts_tonemap;
+ break;
+ case CMP_NODE_LENSDIST:
+ ntype->draw_buttons = node_composit_buts_lensdist;
+ break;
+ case CMP_NODE_VECBLUR:
+ ntype->draw_buttons = node_composit_buts_vecblur;
+ break;
+ case CMP_NODE_FILTER:
+ ntype->draw_buttons = node_composit_buts_filter;
+ break;
+ case CMP_NODE_MAP_VALUE:
+ ntype->draw_buttons = node_composit_buts_map_value;
+ break;
+ case CMP_NODE_MAP_RANGE:
+ ntype->draw_buttons = node_composit_buts_map_range;
+ break;
+ case CMP_NODE_TIME:
+ ntype->draw_buttons = node_buts_time;
+ break;
+ case CMP_NODE_ALPHAOVER:
+ ntype->draw_buttons = node_composit_buts_alphaover;
+ break;
+ case CMP_NODE_TEXTURE:
+ ntype->draw_buttons = node_buts_texture;
+ break;
+ case CMP_NODE_DILATEERODE:
+ ntype->draw_buttons = node_composit_buts_dilateerode;
+ break;
+ case CMP_NODE_INPAINT:
+ ntype->draw_buttons = node_composit_buts_inpaint;
+ break;
+ case CMP_NODE_DESPECKLE:
+ ntype->draw_buttons = node_composit_buts_despeckle;
+ break;
+ case CMP_NODE_OUTPUT_FILE:
+ ntype->draw_buttons = node_composit_buts_file_output;
+ ntype->draw_buttons_ex = node_composit_buts_file_output_ex;
+ break;
+ case CMP_NODE_DIFF_MATTE:
+ ntype->draw_buttons = node_composit_buts_diff_matte;
+ break;
+ case CMP_NODE_DIST_MATTE:
+ ntype->draw_buttons = node_composit_buts_distance_matte;
+ break;
+ case CMP_NODE_COLOR_SPILL:
+ ntype->draw_buttons = node_composit_buts_color_spill;
+ break;
+ case CMP_NODE_CHROMA_MATTE:
+ ntype->draw_buttons = node_composit_buts_chroma_matte;
+ break;
+ case CMP_NODE_COLOR_MATTE:
+ ntype->draw_buttons = node_composit_buts_color_matte;
+ break;
+ case CMP_NODE_SCALE:
+ ntype->draw_buttons = node_composit_buts_scale;
+ break;
+ case CMP_NODE_ROTATE:
+ ntype->draw_buttons = node_composit_buts_rotate;
+ break;
+ case CMP_NODE_CHANNEL_MATTE:
+ ntype->draw_buttons = node_composit_buts_channel_matte;
+ break;
+ case CMP_NODE_LUMA_MATTE:
+ ntype->draw_buttons = node_composit_buts_luma_matte;
+ break;
+ case CMP_NODE_MAP_UV:
+ ntype->draw_buttons = node_composit_buts_map_uv;
+ break;
+ case CMP_NODE_ID_MASK:
+ ntype->draw_buttons = node_composit_buts_id_mask;
+ break;
+ case CMP_NODE_DOUBLEEDGEMASK:
+ ntype->draw_buttons = node_composit_buts_double_edge_mask;
+ break;
+ case CMP_NODE_MATH:
+ ntype->draw_buttons = node_buts_math;
+ break;
+ case CMP_NODE_INVERT:
+ ntype->draw_buttons = node_composit_buts_invert;
+ break;
+ case CMP_NODE_PREMULKEY:
+ ntype->draw_buttons = node_composit_buts_premulkey;
+ break;
+ case CMP_NODE_VIEW_LEVELS:
+ ntype->draw_buttons = node_composit_buts_view_levels;
+ break;
+ case CMP_NODE_COLORBALANCE:
+ ntype->draw_buttons = node_composit_buts_colorbalance;
+ ntype->draw_buttons_ex = node_composit_buts_colorbalance_ex;
+ break;
+ case CMP_NODE_HUECORRECT:
+ ntype->draw_buttons = node_composit_buts_huecorrect;
+ break;
+ case CMP_NODE_ZCOMBINE:
+ ntype->draw_buttons = node_composit_buts_zcombine;
+ break;
+ case CMP_NODE_COMBYCCA:
+ case CMP_NODE_SEPYCCA:
+ ntype->draw_buttons = node_composit_buts_ycc;
+ break;
+ case CMP_NODE_MOVIECLIP:
+ ntype->draw_buttons = node_composit_buts_movieclip;
+ ntype->draw_buttons_ex = node_composit_buts_movieclip_ex;
+ break;
+ case CMP_NODE_STABILIZE2D:
+ ntype->draw_buttons = node_composit_buts_stabilize2d;
+ break;
+ case CMP_NODE_TRANSFORM:
+ ntype->draw_buttons = node_composit_buts_transform;
+ break;
+ case CMP_NODE_TRANSLATE:
+ ntype->draw_buttons = node_composit_buts_translate;
+ break;
+ case CMP_NODE_MOVIEDISTORTION:
+ ntype->draw_buttons = node_composit_buts_moviedistortion;
+ break;
+ case CMP_NODE_COLORCORRECTION:
+ ntype->draw_buttons = node_composit_buts_colorcorrection;
+ ntype->draw_buttons_ex = node_composit_buts_colorcorrection_ex;
+ break;
+ case CMP_NODE_SWITCH:
+ ntype->draw_buttons = node_composit_buts_switch;
+ break;
+ case CMP_NODE_SWITCH_VIEW:
+ ntype->draw_buttons_ex = node_composit_buts_switch_view_ex;
+ break;
+ case CMP_NODE_MASK_BOX:
+ ntype->draw_buttons = node_composit_buts_boxmask;
+ ntype->draw_backdrop = node_composit_backdrop_boxmask;
+ break;
+ case CMP_NODE_MASK_ELLIPSE:
+ ntype->draw_buttons = node_composit_buts_ellipsemask;
+ ntype->draw_backdrop = node_composit_backdrop_ellipsemask;
+ break;
+ case CMP_NODE_BOKEHIMAGE:
+ ntype->draw_buttons = node_composit_buts_bokehimage;
+ break;
+ case CMP_NODE_BOKEHBLUR:
+ ntype->draw_buttons = node_composit_buts_bokehblur;
+ break;
+ case CMP_NODE_VIEWER:
+ ntype->draw_buttons = node_composit_buts_viewer;
+ ntype->draw_buttons_ex = node_composit_buts_viewer_ex;
+ ntype->draw_backdrop = node_composit_backdrop_viewer;
+ break;
+ case CMP_NODE_COMPOSITE:
+ ntype->draw_buttons = node_composit_buts_composite;
+ break;
+ case CMP_NODE_MASK:
+ ntype->draw_buttons = node_composit_buts_mask;
+ break;
+ case CMP_NODE_KEYINGSCREEN:
+ ntype->draw_buttons = node_composit_buts_keyingscreen;
+ break;
+ case CMP_NODE_KEYING:
+ ntype->draw_buttons = node_composit_buts_keying;
+ break;
+ case CMP_NODE_TRACKPOS:
+ ntype->draw_buttons = node_composit_buts_trackpos;
+ break;
+ case CMP_NODE_PLANETRACKDEFORM:
+ ntype->draw_buttons = node_composit_buts_planetrackdeform;
+ break;
+ case CMP_NODE_CORNERPIN:
+ ntype->draw_buttons = node_composit_buts_cornerpin;
+ break;
+ case CMP_NODE_SUNBEAMS:
+ ntype->draw_buttons = node_composit_buts_sunbeams;
+ break;
+ case CMP_NODE_CRYPTOMATTE:
+ ntype->draw_buttons = node_composit_buts_cryptomatte;
+ ntype->draw_buttons_ex = node_composit_buts_cryptomatte_ex;
+ break;
+ case CMP_NODE_BRIGHTCONTRAST:
+ ntype->draw_buttons = node_composit_buts_brightcontrast;
+ }
}
/* ****************** BUTTON CALLBACKS FOR TEXTURE NODES ***************** */
static void node_texture_buts_bricks(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ 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);
+ 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);
- col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "squash", 0, IFACE_("Squash"), ICON_NONE);
- uiItemR(col, ptr, "squash_frequency", 0, 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);
}
static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- PointerRNA tex_ptr;
- bNode *node = ptr->data;
- ID *id = ptr->id.data;
- Tex *tex = (Tex *)node->storage;
- uiLayout *col, *row;
-
- RNA_pointer_create(id, &RNA_Texture, tex, &tex_ptr);
-
- col = uiLayoutColumn(layout, false);
-
- switch (tex->type) {
- case TEX_BLEND:
- uiItemR(col, &tex_ptr, "progression", 0, "", ICON_NONE);
- row = uiLayoutRow(col, false);
- uiItemR(row, &tex_ptr, "use_flip_axis", 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);
- row = uiLayoutRow(col, false);
- uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
- row = uiLayoutRow(col, false);
- uiItemR(row, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
- row = uiLayoutRow(col, false);
- uiItemR(row, &tex_ptr, "noise_basis_2", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
- break;
-
- case TEX_MAGIC:
- uiItemR(col, &tex_ptr, "noise_depth", 0, NULL, ICON_NONE);
- break;
-
- case TEX_STUCCI:
- row = uiLayoutRow(col, false);
- uiItemR(row, &tex_ptr, "stucci_type", 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);
- break;
-
- case TEX_WOOD:
- uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
- uiItemR(col, &tex_ptr, "wood_type", 0, "", ICON_NONE);
- row = uiLayoutRow(col, false);
- uiItemR(row, &tex_ptr, "noise_basis_2", 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);
- break;
-
- case TEX_CLOUDS:
- uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
- row = uiLayoutRow(col, false);
- uiItemR(row, &tex_ptr, "cloud_type", 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);
- break;
-
- case TEX_DISTNOISE:
- uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
- uiItemR(col, &tex_ptr, "noise_distortion", 0, "", ICON_NONE);
- break;
-
- case TEX_MUSGRAVE:
- uiItemR(col, &tex_ptr, "musgrave_type", 0, "", ICON_NONE);
- uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
- break;
- case TEX_VORONOI:
- uiItemR(col, &tex_ptr, "distance_metric", 0, "", ICON_NONE);
- if (tex->vn_distm == TEX_MINKOVSKY) {
- uiItemR(col, &tex_ptr, "minkovsky_exponent", 0, NULL, ICON_NONE);
- }
- uiItemR(col, &tex_ptr, "color_mode", 0, "", ICON_NONE);
- break;
- }
+ PointerRNA tex_ptr;
+ bNode *node = ptr->data;
+ ID *id = ptr->id.data;
+ Tex *tex = (Tex *)node->storage;
+ uiLayout *col, *row;
+
+ RNA_pointer_create(id, &RNA_Texture, tex, &tex_ptr);
+
+ col = uiLayoutColumn(layout, false);
+
+ switch (tex->type) {
+ case TEX_BLEND:
+ uiItemR(col, &tex_ptr, "progression", 0, "", ICON_NONE);
+ row = uiLayoutRow(col, false);
+ uiItemR(row, &tex_ptr, "use_flip_axis", 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);
+ row = uiLayoutRow(col, false);
+ uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ row = uiLayoutRow(col, false);
+ uiItemR(row, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
+ row = uiLayoutRow(col, false);
+ uiItemR(row, &tex_ptr, "noise_basis_2", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ break;
+
+ case TEX_MAGIC:
+ uiItemR(col, &tex_ptr, "noise_depth", 0, NULL, ICON_NONE);
+ break;
+
+ case TEX_STUCCI:
+ row = uiLayoutRow(col, false);
+ uiItemR(row, &tex_ptr, "stucci_type", 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);
+ break;
+
+ case TEX_WOOD:
+ uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
+ uiItemR(col, &tex_ptr, "wood_type", 0, "", ICON_NONE);
+ row = uiLayoutRow(col, false);
+ uiItemR(row, &tex_ptr, "noise_basis_2", 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);
+ break;
+
+ case TEX_CLOUDS:
+ uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
+ row = uiLayoutRow(col, false);
+ uiItemR(row, &tex_ptr, "cloud_type", 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);
+ break;
+
+ case TEX_DISTNOISE:
+ uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
+ uiItemR(col, &tex_ptr, "noise_distortion", 0, "", ICON_NONE);
+ break;
+
+ case TEX_MUSGRAVE:
+ uiItemR(col, &tex_ptr, "musgrave_type", 0, "", ICON_NONE);
+ uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
+ break;
+ case TEX_VORONOI:
+ uiItemR(col, &tex_ptr, "distance_metric", 0, "", ICON_NONE);
+ if (tex->vn_distm == TEX_MINKOVSKY) {
+ uiItemR(col, &tex_ptr, "minkovsky_exponent", 0, NULL, ICON_NONE);
+ }
+ uiItemR(col, &tex_ptr, "color_mode", 0, "", ICON_NONE);
+ break;
+ }
}
static void node_texture_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- uiTemplateID(layout, C, ptr, "image", "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
+ uiTemplateID(layout,
+ C,
+ ptr,
+ "image",
+ "IMAGE_OT_new",
+ "IMAGE_OT_open",
+ NULL,
+ UI_TEMPLATE_ID_FILTER_ALL,
+ false);
}
static void node_texture_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- bNode *node = ptr->data;
- PointerRNA iuserptr;
+ bNode *node = ptr->data;
+ PointerRNA iuserptr;
- RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr);
- uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 0);
+ RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr);
+ uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 0);
}
static void node_texture_buts_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "filepath", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "filepath", 0, "", ICON_NONE);
}
/* only once called */
static void node_texture_set_butfunc(bNodeType *ntype)
{
- if (ntype->type >= TEX_NODE_PROC && ntype->type < TEX_NODE_PROC_MAX) {
- ntype->draw_buttons = node_texture_buts_proc;
- }
- else {
- switch (ntype->type) {
+ if (ntype->type >= TEX_NODE_PROC && ntype->type < TEX_NODE_PROC_MAX) {
+ ntype->draw_buttons = node_texture_buts_proc;
+ }
+ else {
+ switch (ntype->type) {
- case TEX_NODE_MATH:
- ntype->draw_buttons = node_buts_math;
- break;
+ case TEX_NODE_MATH:
+ ntype->draw_buttons = node_buts_math;
+ break;
- case TEX_NODE_MIX_RGB:
- ntype->draw_buttons = node_buts_mix_rgb;
- break;
+ case TEX_NODE_MIX_RGB:
+ ntype->draw_buttons = node_buts_mix_rgb;
+ break;
- case TEX_NODE_VALTORGB:
- ntype->draw_buttons = node_buts_colorramp;
- break;
+ case TEX_NODE_VALTORGB:
+ ntype->draw_buttons = node_buts_colorramp;
+ break;
- case TEX_NODE_CURVE_RGB:
- ntype->draw_buttons = node_buts_curvecol;
- break;
+ case TEX_NODE_CURVE_RGB:
+ ntype->draw_buttons = node_buts_curvecol;
+ break;
- case TEX_NODE_CURVE_TIME:
- ntype->draw_buttons = node_buts_time;
- break;
+ case TEX_NODE_CURVE_TIME:
+ ntype->draw_buttons = node_buts_time;
+ break;
- case TEX_NODE_TEXTURE:
- ntype->draw_buttons = node_buts_texture;
- break;
+ case TEX_NODE_TEXTURE:
+ ntype->draw_buttons = node_buts_texture;
+ break;
- case TEX_NODE_BRICKS:
- ntype->draw_buttons = node_texture_buts_bricks;
- break;
+ case TEX_NODE_BRICKS:
+ ntype->draw_buttons = node_texture_buts_bricks;
+ break;
- case TEX_NODE_IMAGE:
- ntype->draw_buttons = node_texture_buts_image;
- ntype->draw_buttons_ex = node_texture_buts_image_ex;
- break;
+ case TEX_NODE_IMAGE:
+ ntype->draw_buttons = node_texture_buts_image;
+ ntype->draw_buttons_ex = node_texture_buts_image_ex;
+ break;
- case TEX_NODE_OUTPUT:
- ntype->draw_buttons = node_texture_buts_output;
- break;
- }
- }
+ case TEX_NODE_OUTPUT:
+ ntype->draw_buttons = node_texture_buts_output;
+ 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)
{
- bNodeTree *ntree = ptr->id.data;
- bNode *node = ptr->data;
- ED_node_tag_update_nodetree(bmain, ntree, node);
+ bNodeTree *ntree = ptr->id.data;
+ bNode *node = ptr->data;
+ ED_node_tag_update_nodetree(bmain, ntree, node);
}
static void node_socket_template_properties_update(bNodeType *ntype, bNodeSocketTemplate *stemp)
{
- StructRNA *srna = ntype->ext.srna;
- PropertyRNA *prop = RNA_struct_type_find_property(srna, stemp->identifier);
+ StructRNA *srna = ntype->ext.srna;
+ PropertyRNA *prop = RNA_struct_type_find_property(srna, stemp->identifier);
- if (prop) {
- RNA_def_property_update_runtime(prop, node_property_update_default);
- }
+ if (prop) {
+ RNA_def_property_update_runtime(prop, node_property_update_default);
+ }
}
static void node_template_properties_update(bNodeType *ntype)
{
- bNodeSocketTemplate *stemp;
+ bNodeSocketTemplate *stemp;
- if (ntype->inputs) {
- for (stemp = ntype->inputs; stemp->type >= 0; ++stemp) {
- node_socket_template_properties_update(ntype, stemp);
- }
- }
- if (ntype->outputs) {
- for (stemp = ntype->outputs; stemp->type >= 0; ++stemp) {
- node_socket_template_properties_update(ntype, stemp);
- }
- }
+ if (ntype->inputs) {
+ for (stemp = ntype->inputs; stemp->type >= 0; ++stemp) {
+ node_socket_template_properties_update(ntype, stemp);
+ }
+ }
+ if (ntype->outputs) {
+ for (stemp = ntype->outputs; stemp->type >= 0; ++stemp) {
+ node_socket_template_properties_update(ntype, stemp);
+ }
+ }
}
-static void node_socket_undefined_draw(bContext *UNUSED(C), uiLayout *layout, PointerRNA *UNUSED(ptr), PointerRNA *UNUSED(node_ptr),
+static void node_socket_undefined_draw(bContext *UNUSED(C),
+ uiLayout *layout,
+ PointerRNA *UNUSED(ptr),
+ PointerRNA *UNUSED(node_ptr),
const char *UNUSED(text))
{
- uiItemL(layout, IFACE_("Undefined Socket Type"), ICON_ERROR);
+ uiItemL(layout, IFACE_("Undefined Socket Type"), ICON_ERROR);
}
-static void node_socket_undefined_draw_color(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PointerRNA *UNUSED(node_ptr), float *r_color)
+static void node_socket_undefined_draw_color(bContext *UNUSED(C),
+ PointerRNA *UNUSED(ptr),
+ PointerRNA *UNUSED(node_ptr),
+ float *r_color)
{
- r_color[0] = 1.0f;
- r_color[1] = 0.0f;
- r_color[2] = 0.0f;
- r_color[3] = 1.0f;
+ r_color[0] = 1.0f;
+ r_color[1] = 0.0f;
+ r_color[2] = 0.0f;
+ r_color[3] = 1.0f;
}
-static void node_socket_undefined_interface_draw(bContext *UNUSED(C), uiLayout *layout, PointerRNA *UNUSED(ptr))
+static void node_socket_undefined_interface_draw(bContext *UNUSED(C),
+ uiLayout *layout,
+ PointerRNA *UNUSED(ptr))
{
- uiItemL(layout, IFACE_("Undefined Socket Type"), ICON_ERROR);
+ uiItemL(layout, IFACE_("Undefined Socket Type"), ICON_ERROR);
}
-static void node_socket_undefined_interface_draw_color(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), float *r_color)
+static void node_socket_undefined_interface_draw_color(bContext *UNUSED(C),
+ PointerRNA *UNUSED(ptr),
+ float *r_color)
{
- r_color[0] = 1.0f;
- r_color[1] = 0.0f;
- r_color[2] = 0.0f;
- r_color[3] = 1.0f;
+ r_color[0] = 1.0f;
+ r_color[1] = 0.0f;
+ r_color[2] = 0.0f;
+ r_color[3] = 1.0f;
}
void ED_node_init_butfuncs(void)
{
- /* Fallback types for undefined tree, nodes, sockets
- * Defined in blenkernel, but not registered in type hashes.
- */
-
- /* default ui functions */
- NodeTypeUndefined.draw_nodetype = node_draw_default;
- NodeTypeUndefined.draw_nodetype_prepare = node_update_default;
- NodeTypeUndefined.select_area_func = node_select_area_default;
- NodeTypeUndefined.tweak_area_func = node_tweak_area_default;
- NodeTypeUndefined.draw_buttons = NULL;
- NodeTypeUndefined.draw_buttons_ex = NULL;
- NodeTypeUndefined.resize_area_func = node_resize_area_default;
-
- NodeSocketTypeUndefined.draw = node_socket_undefined_draw;
- NodeSocketTypeUndefined.draw_color = node_socket_undefined_draw_color;
- NodeSocketTypeUndefined.interface_draw = node_socket_undefined_interface_draw;
- NodeSocketTypeUndefined.interface_draw_color = node_socket_undefined_interface_draw_color;
-
- /* node type ui functions */
- NODE_TYPES_BEGIN(ntype) {
- /* default ui functions */
- ntype->draw_nodetype = node_draw_default;
- ntype->draw_nodetype_prepare = node_update_default;
- ntype->select_area_func = node_select_area_default;
- ntype->tweak_area_func = node_tweak_area_default;
- ntype->draw_buttons = NULL;
- ntype->draw_buttons_ex = NULL;
- ntype->resize_area_func = node_resize_area_default;
-
- node_common_set_butfunc(ntype);
-
- node_composit_set_butfunc(ntype);
- node_shader_set_butfunc(ntype);
- node_texture_set_butfunc(ntype);
-
- /* define update callbacks for socket properties */
- node_template_properties_update(ntype);
- } NODE_TYPES_END;
-
- /* tree type icons */
- ntreeType_Composite->ui_icon = ICON_NODE_COMPOSITING;
- ntreeType_Shader->ui_icon = ICON_NODE_MATERIAL;
- ntreeType_Texture->ui_icon = ICON_NODE_TEXTURE;
+ /* Fallback types for undefined tree, nodes, sockets
+ * Defined in blenkernel, but not registered in type hashes.
+ */
+
+ /* default ui functions */
+ NodeTypeUndefined.draw_nodetype = node_draw_default;
+ NodeTypeUndefined.draw_nodetype_prepare = node_update_default;
+ NodeTypeUndefined.select_area_func = node_select_area_default;
+ NodeTypeUndefined.tweak_area_func = node_tweak_area_default;
+ NodeTypeUndefined.draw_buttons = NULL;
+ NodeTypeUndefined.draw_buttons_ex = NULL;
+ NodeTypeUndefined.resize_area_func = node_resize_area_default;
+
+ NodeSocketTypeUndefined.draw = node_socket_undefined_draw;
+ NodeSocketTypeUndefined.draw_color = node_socket_undefined_draw_color;
+ NodeSocketTypeUndefined.interface_draw = node_socket_undefined_interface_draw;
+ NodeSocketTypeUndefined.interface_draw_color = node_socket_undefined_interface_draw_color;
+
+ /* node type ui functions */
+ NODE_TYPES_BEGIN (ntype) {
+ /* default ui functions */
+ ntype->draw_nodetype = node_draw_default;
+ ntype->draw_nodetype_prepare = node_update_default;
+ ntype->select_area_func = node_select_area_default;
+ ntype->tweak_area_func = node_tweak_area_default;
+ ntype->draw_buttons = NULL;
+ ntype->draw_buttons_ex = NULL;
+ ntype->resize_area_func = node_resize_area_default;
+
+ node_common_set_butfunc(ntype);
+
+ node_composit_set_butfunc(ntype);
+ node_shader_set_butfunc(ntype);
+ node_texture_set_butfunc(ntype);
+
+ /* define update callbacks for socket properties */
+ node_template_properties_update(ntype);
+ }
+ NODE_TYPES_END;
+
+ /* tree type icons */
+ ntreeType_Composite->ui_icon = ICON_NODE_COMPOSITING;
+ ntreeType_Shader->ui_icon = ICON_NODE_MATERIAL;
+ ntreeType_Texture->ui_icon = ICON_NODE_TEXTURE;
}
void ED_init_custom_node_type(bNodeType *ntype)
{
- /* default ui functions */
- ntype->draw_nodetype = node_draw_default;
- ntype->draw_nodetype_prepare = node_update_default;
- ntype->resize_area_func = node_resize_area_default;
- ntype->select_area_func = node_select_area_default;
- ntype->tweak_area_func = node_tweak_area_default;
+ /* default ui functions */
+ ntype->draw_nodetype = node_draw_default;
+ ntype->draw_nodetype_prepare = node_update_default;
+ ntype->resize_area_func = node_resize_area_default;
+ ntype->select_area_func = node_select_area_default;
+ ntype->tweak_area_func = node_tweak_area_default;
}
void ED_init_custom_node_socket_type(bNodeSocketType *stype)
{
- /* default ui functions */
- stype->draw = node_socket_button_label;
+ /* default ui functions */
+ stype->draw = node_socket_button_label;
}
/* maps standard socket integer type to a color */
static const float std_node_socket_colors[][4] = {
- {0.63, 0.63, 0.63, 1.0}, /* SOCK_FLOAT */
- {0.39, 0.39, 0.78, 1.0}, /* SOCK_VECTOR */
- {0.78, 0.78, 0.16, 1.0}, /* SOCK_RGBA */
- {0.39, 0.78, 0.39, 1.0}, /* SOCK_SHADER */
- {0.70, 0.65, 0.19, 1.0}, /* SOCK_BOOLEAN */
- {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.63, 0.63, 0.63, 1.0}, /* SOCK_FLOAT */
+ {0.39, 0.39, 0.78, 1.0}, /* SOCK_VECTOR */
+ {0.78, 0.78, 0.16, 1.0}, /* SOCK_RGBA */
+ {0.39, 0.78, 0.39, 1.0}, /* SOCK_SHADER */
+ {0.70, 0.65, 0.19, 1.0}, /* SOCK_BOOLEAN */
+ {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 */
};
/* common color callbacks for standard types */
-static void std_node_socket_draw_color(bContext *UNUSED(C), PointerRNA *ptr, PointerRNA *UNUSED(node_ptr), float *r_color)
+static void std_node_socket_draw_color(bContext *UNUSED(C),
+ PointerRNA *ptr,
+ PointerRNA *UNUSED(node_ptr),
+ float *r_color)
{
- bNodeSocket *sock = ptr->data;
- int type = sock->typeinfo->type;
- copy_v4_v4(r_color, std_node_socket_colors[type]);
+ bNodeSocket *sock = ptr->data;
+ int type = sock->typeinfo->type;
+ copy_v4_v4(r_color, std_node_socket_colors[type]);
}
-static void std_node_socket_interface_draw_color(bContext *UNUSED(C), PointerRNA *ptr, float *r_color)
+static void std_node_socket_interface_draw_color(bContext *UNUSED(C),
+ PointerRNA *ptr,
+ float *r_color)
{
- bNodeSocket *sock = ptr->data;
- int type = sock->typeinfo->type;
- copy_v4_v4(r_color, std_node_socket_colors[type]);
+ bNodeSocket *sock = ptr->data;
+ int type = sock->typeinfo->type;
+ copy_v4_v4(r_color, std_node_socket_colors[type]);
}
/* draw function for file output node sockets,
* displays only sub-path and format, no value button */
-static void node_file_output_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr)
-{
- bNodeTree *ntree = ptr->id.data;
- bNodeSocket *sock = ptr->data;
- uiLayout *row;
- PointerRNA inputptr, imfptr;
- int imtype;
-
- row = uiLayoutRow(layout, false);
-
- imfptr = RNA_pointer_get(node_ptr, "format");
- imtype = RNA_enum_get(&imfptr, "file_format");
-
- if (imtype == R_IMF_IMTYPE_MULTILAYER) {
- NodeImageMultiFileSocket *input = sock->storage;
- RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotLayer, input, &inputptr);
-
- uiItemL(row, input->layer, ICON_NONE);
- }
- else {
- NodeImageMultiFileSocket *input = sock->storage;
- PropertyRNA *imtype_prop;
- const char *imtype_name;
- uiBlock *block;
- RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotFile, input, &inputptr);
-
- uiItemL(row, input->path, ICON_NONE);
-
- if (!RNA_boolean_get(&inputptr, "use_node_format")) {
- imfptr = RNA_pointer_get(&inputptr, "format");
- }
-
- imtype_prop = RNA_struct_find_property(&imfptr, "file_format");
- RNA_property_enum_name((bContext *)C, &imfptr, imtype_prop,
- RNA_property_enum_get(&imfptr, imtype_prop), &imtype_name);
- block = uiLayoutGetBlock(row);
- UI_block_emboss_set(block, UI_EMBOSS_PULLDOWN);
- uiItemL(row, imtype_name, ICON_NONE);
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- }
-}
-
-static void std_node_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, const char *text)
-{
- bNode *node = node_ptr->data;
- bNodeSocket *sock = ptr->data;
- int type = sock->typeinfo->type;
- /*int subtype = sock->typeinfo->subtype;*/
-
- /* XXX not nice, eventually give this node its own socket type ... */
- if (node->type == CMP_NODE_OUTPUT_FILE) {
- node_file_output_socket_draw(C, layout, ptr, node_ptr);
- return;
- }
-
- if ((sock->in_out == SOCK_OUT) || (sock->flag & SOCK_IN_USE) || (sock->flag & SOCK_HIDE_VALUE)) {
- node_socket_button_label(C, layout, ptr, node_ptr, text);
- return;
- }
-
- switch (type) {
- case SOCK_FLOAT:
- case SOCK_INT:
- case SOCK_BOOLEAN:
- uiItemR(layout, ptr, "default_value", 0, text, 0);
- break;
- case SOCK_VECTOR:
- uiTemplateComponentMenu(layout, ptr, "default_value", text);
- break;
- case SOCK_RGBA:
- case SOCK_STRING:
- {
- uiLayout *row = uiLayoutSplit(layout, 0.5f, false);
- uiItemL(row, text, 0);
- uiItemR(row, ptr, "default_value", 0, "", 0);
- break;
- }
- default:
- node_socket_button_label(C, layout, ptr, node_ptr, text);
- break;
- }
+static void node_file_output_socket_draw(bContext *C,
+ uiLayout *layout,
+ PointerRNA *ptr,
+ PointerRNA *node_ptr)
+{
+ bNodeTree *ntree = ptr->id.data;
+ bNodeSocket *sock = ptr->data;
+ uiLayout *row;
+ PointerRNA inputptr, imfptr;
+ int imtype;
+
+ row = uiLayoutRow(layout, false);
+
+ imfptr = RNA_pointer_get(node_ptr, "format");
+ imtype = RNA_enum_get(&imfptr, "file_format");
+
+ if (imtype == R_IMF_IMTYPE_MULTILAYER) {
+ NodeImageMultiFileSocket *input = sock->storage;
+ RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotLayer, input, &inputptr);
+
+ uiItemL(row, input->layer, ICON_NONE);
+ }
+ else {
+ NodeImageMultiFileSocket *input = sock->storage;
+ PropertyRNA *imtype_prop;
+ const char *imtype_name;
+ uiBlock *block;
+ RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotFile, input, &inputptr);
+
+ uiItemL(row, input->path, ICON_NONE);
+
+ if (!RNA_boolean_get(&inputptr, "use_node_format")) {
+ imfptr = RNA_pointer_get(&inputptr, "format");
+ }
+
+ imtype_prop = RNA_struct_find_property(&imfptr, "file_format");
+ RNA_property_enum_name((bContext *)C,
+ &imfptr,
+ imtype_prop,
+ RNA_property_enum_get(&imfptr, imtype_prop),
+ &imtype_name);
+ block = uiLayoutGetBlock(row);
+ UI_block_emboss_set(block, UI_EMBOSS_PULLDOWN);
+ uiItemL(row, imtype_name, ICON_NONE);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ }
+}
+
+static void std_node_socket_draw(
+ bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, const char *text)
+{
+ bNode *node = node_ptr->data;
+ bNodeSocket *sock = ptr->data;
+ int type = sock->typeinfo->type;
+ /*int subtype = sock->typeinfo->subtype;*/
+
+ /* XXX not nice, eventually give this node its own socket type ... */
+ if (node->type == CMP_NODE_OUTPUT_FILE) {
+ node_file_output_socket_draw(C, layout, ptr, node_ptr);
+ return;
+ }
+
+ if ((sock->in_out == SOCK_OUT) || (sock->flag & SOCK_IN_USE) || (sock->flag & SOCK_HIDE_VALUE)) {
+ node_socket_button_label(C, layout, ptr, node_ptr, text);
+ return;
+ }
+
+ switch (type) {
+ case SOCK_FLOAT:
+ case SOCK_INT:
+ case SOCK_BOOLEAN:
+ uiItemR(layout, ptr, "default_value", 0, text, 0);
+ break;
+ case SOCK_VECTOR:
+ uiTemplateComponentMenu(layout, ptr, "default_value", text);
+ break;
+ case SOCK_RGBA:
+ case SOCK_STRING: {
+ uiLayout *row = uiLayoutSplit(layout, 0.5f, false);
+ uiItemL(row, text, 0);
+ uiItemR(row, ptr, "default_value", 0, "", 0);
+ break;
+ }
+ default:
+ node_socket_button_label(C, layout, ptr, node_ptr, text);
+ break;
+ }
}
static void std_node_socket_interface_draw(bContext *UNUSED(C), uiLayout *layout, PointerRNA *ptr)
{
- bNodeSocket *sock = ptr->data;
- int type = sock->typeinfo->type;
- /*int subtype = sock->typeinfo->subtype;*/
-
- switch (type) {
- case SOCK_FLOAT:
- {
- uiLayout *row;
- uiItemR(layout, ptr, "default_value", 0, NULL, 0);
- row = uiLayoutRow(layout, true);
- uiItemR(row, ptr, "min_value", 0, IFACE_("Min"), 0);
- uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0);
- break;
- }
- case SOCK_INT:
- {
- uiLayout *row;
- uiItemR(layout, ptr, "default_value", 0, NULL, 0);
- row = uiLayoutRow(layout, true);
- uiItemR(row, ptr, "min_value", 0, IFACE_("Min"), 0);
- uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0);
- break;
- }
- case SOCK_VECTOR:
- {
- uiLayout *row;
- uiItemR(layout, ptr, "default_value", UI_ITEM_R_EXPAND, NULL, 0);
- row = uiLayoutRow(layout, true);
- uiItemR(row, ptr, "min_value", 0, IFACE_("Min"), 0);
- uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0);
- break;
- }
- case SOCK_BOOLEAN:
- case SOCK_RGBA:
- case SOCK_STRING:
- {
- uiItemR(layout, ptr, "default_value", 0, NULL, 0);
- break;
- }
- }
+ bNodeSocket *sock = ptr->data;
+ int type = sock->typeinfo->type;
+ /*int subtype = sock->typeinfo->subtype;*/
+
+ switch (type) {
+ case SOCK_FLOAT: {
+ uiLayout *row;
+ uiItemR(layout, ptr, "default_value", 0, NULL, 0);
+ row = uiLayoutRow(layout, true);
+ uiItemR(row, ptr, "min_value", 0, IFACE_("Min"), 0);
+ uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0);
+ break;
+ }
+ case SOCK_INT: {
+ uiLayout *row;
+ uiItemR(layout, ptr, "default_value", 0, NULL, 0);
+ row = uiLayoutRow(layout, true);
+ uiItemR(row, ptr, "min_value", 0, IFACE_("Min"), 0);
+ uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0);
+ break;
+ }
+ case SOCK_VECTOR: {
+ uiLayout *row;
+ uiItemR(layout, ptr, "default_value", UI_ITEM_R_EXPAND, NULL, 0);
+ row = uiLayoutRow(layout, true);
+ uiItemR(row, ptr, "min_value", 0, IFACE_("Min"), 0);
+ uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0);
+ break;
+ }
+ case SOCK_BOOLEAN:
+ case SOCK_RGBA:
+ case SOCK_STRING: {
+ uiItemR(layout, ptr, "default_value", 0, NULL, 0);
+ break;
+ }
+ }
}
void ED_init_standard_node_socket_type(bNodeSocketType *stype)
{
- stype->draw = std_node_socket_draw;
- stype->draw_color = std_node_socket_draw_color;
- stype->interface_draw = std_node_socket_interface_draw;
- stype->interface_draw_color = std_node_socket_interface_draw_color;
+ stype->draw = std_node_socket_draw;
+ stype->draw_color = std_node_socket_draw_color;
+ stype->interface_draw = std_node_socket_interface_draw;
+ stype->interface_draw_color = std_node_socket_interface_draw_color;
}
-static void node_socket_virtual_draw_color(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PointerRNA *UNUSED(node_ptr), float *r_color)
+static void node_socket_virtual_draw_color(bContext *UNUSED(C),
+ PointerRNA *UNUSED(ptr),
+ PointerRNA *UNUSED(node_ptr),
+ float *r_color)
{
- /* alpha = 0, empty circle */
- zero_v4(r_color);
+ /* alpha = 0, empty circle */
+ zero_v4(r_color);
}
void ED_init_node_socket_type_virtual(bNodeSocketType *stype)
{
- stype->draw = node_socket_button_label;
- stype->draw_color = node_socket_virtual_draw_color;
+ stype->draw = node_socket_button_label;
+ stype->draw_color = node_socket_virtual_draw_color;
}
/* ************** Generic drawing ************** */
-void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeInstanceKey parent_key)
-{
- Main *bmain = CTX_data_main(C);
- bNodeInstanceKey active_viewer_key = (snode->nodetree ? snode->nodetree->active_viewer_key : NODE_INSTANCE_KEY_NONE);
- float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- Image *ima;
- void *lock;
- ImBuf *ibuf;
-
- if (!(snode->flag & SNODE_BACKDRAW) || !ED_node_is_compositor(snode)) {
- return;
- }
-
- if (parent_key.value != active_viewer_key.value) {
- return;
- }
-
- ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
- ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
- if (ibuf) {
- float x, y;
-
- GPU_matrix_push_projection();
- GPU_matrix_push();
-
- /* somehow the offset has to be calculated inverse */
- wmOrtho2_region_pixelspace(ar);
-
- x = (ar->winx - snode->zoom * ibuf->x) / 2 + snode->xof;
- y = (ar->winy - snode->zoom * ibuf->y) / 2 + snode->yof;
-
- if (ibuf->rect || ibuf->rect_float) {
- unsigned char *display_buffer = NULL;
- void *cache_handle = NULL;
-
- if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B | SNODE_SHOW_ALPHA)) {
-
- display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
-
- if (snode->flag & SNODE_SHOW_R) {
- shuffle[0] = 1.0f;
- }
- else if (snode->flag & SNODE_SHOW_G) {
- shuffle[1] = 1.0f;
- }
- else if (snode->flag & SNODE_SHOW_B) {
- shuffle[2] = 1.0f;
- }
- else {
- shuffle[3] = 1.0f;
- }
-
- IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
- GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, shuffle);
-
- immDrawPixelsTex(&state, x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST,
- display_buffer, snode->zoom, snode->zoom, NULL);
-
- GPU_shader_unbind();
- }
- else if (snode->flag & SNODE_USE_ALPHA) {
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST, snode->zoom, snode->zoom);
-
- GPU_blend(false);
- }
- else {
- glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST, snode->zoom, snode->zoom);
- }
-
- if (cache_handle) {
- IMB_display_buffer_release(cache_handle);
- }
- }
-
- /** \note draw selected info on backdrop */
- if (snode->edittree) {
- bNode *node = snode->edittree->nodes.first;
- rctf *viewer_border = &snode->nodetree->viewer_border;
- while (node) {
- if (node->flag & NODE_SELECT) {
- if (node->typeinfo->draw_backdrop) {
- node->typeinfo->draw_backdrop(snode, ibuf, node, x, y);
- }
- }
- node = node->next;
- }
-
- if ((snode->nodetree->flag & NTREE_VIEWER_BORDER) &&
- viewer_border->xmin < viewer_border->xmax &&
- viewer_border->ymin < viewer_border->ymax)
- {
- rcti pixel_border;
- BLI_rcti_init(&pixel_border,
- x + snode->zoom * viewer_border->xmin * ibuf->x,
- x + snode->zoom * viewer_border->xmax * ibuf->x,
- y + snode->zoom * viewer_border->ymin * ibuf->y,
- y + snode->zoom * viewer_border->ymax * ibuf->y);
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor(TH_ACTIVE);
-
- immDrawBorderCorners(pos, &pixel_border, 1.0f, 1.0f);
-
- immUnbindProgram();
- }
- }
-
- GPU_matrix_pop_projection();
- GPU_matrix_pop();
- }
-
- BKE_image_release_ibuf(ima, ibuf, lock);
+void draw_nodespace_back_pix(const bContext *C,
+ ARegion *ar,
+ SpaceNode *snode,
+ bNodeInstanceKey parent_key)
+{
+ Main *bmain = CTX_data_main(C);
+ bNodeInstanceKey active_viewer_key = (snode->nodetree ? snode->nodetree->active_viewer_key :
+ NODE_INSTANCE_KEY_NONE);
+ float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ Image *ima;
+ void *lock;
+ ImBuf *ibuf;
+
+ if (!(snode->flag & SNODE_BACKDRAW) || !ED_node_is_compositor(snode)) {
+ return;
+ }
+
+ if (parent_key.value != active_viewer_key.value) {
+ return;
+ }
+
+ ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+ if (ibuf) {
+ float x, y;
+
+ GPU_matrix_push_projection();
+ GPU_matrix_push();
+
+ /* somehow the offset has to be calculated inverse */
+ wmOrtho2_region_pixelspace(ar);
+
+ x = (ar->winx - snode->zoom * ibuf->x) / 2 + snode->xof;
+ y = (ar->winy - snode->zoom * ibuf->y) / 2 + snode->yof;
+
+ if (ibuf->rect || ibuf->rect_float) {
+ unsigned char *display_buffer = NULL;
+ void *cache_handle = NULL;
+
+ if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B | SNODE_SHOW_ALPHA)) {
+
+ display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
+
+ if (snode->flag & SNODE_SHOW_R) {
+ shuffle[0] = 1.0f;
+ }
+ else if (snode->flag & SNODE_SHOW_G) {
+ shuffle[1] = 1.0f;
+ }
+ else if (snode->flag & SNODE_SHOW_B) {
+ shuffle[2] = 1.0f;
+ }
+ else {
+ shuffle[3] = 1.0f;
+ }
+
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_uniform_vector(
+ state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, shuffle);
+
+ immDrawPixelsTex(&state,
+ x,
+ y,
+ ibuf->x,
+ ibuf->y,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ GL_NEAREST,
+ display_buffer,
+ snode->zoom,
+ snode->zoom,
+ NULL);
+
+ GPU_shader_unbind();
+ }
+ else if (snode->flag & SNODE_USE_ALPHA) {
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST, snode->zoom, snode->zoom);
+
+ GPU_blend(false);
+ }
+ else {
+ glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST, snode->zoom, snode->zoom);
+ }
+
+ if (cache_handle) {
+ IMB_display_buffer_release(cache_handle);
+ }
+ }
+
+ /** \note draw selected info on backdrop */
+ if (snode->edittree) {
+ bNode *node = snode->edittree->nodes.first;
+ rctf *viewer_border = &snode->nodetree->viewer_border;
+ while (node) {
+ if (node->flag & NODE_SELECT) {
+ if (node->typeinfo->draw_backdrop) {
+ node->typeinfo->draw_backdrop(snode, ibuf, node, x, y);
+ }
+ }
+ node = node->next;
+ }
+
+ if ((snode->nodetree->flag & NTREE_VIEWER_BORDER) &&
+ viewer_border->xmin < viewer_border->xmax && viewer_border->ymin < viewer_border->ymax) {
+ rcti pixel_border;
+ BLI_rcti_init(&pixel_border,
+ x + snode->zoom * viewer_border->xmin * ibuf->x,
+ x + snode->zoom * viewer_border->xmax * ibuf->x,
+ y + snode->zoom * viewer_border->ymin * ibuf->y,
+ y + snode->zoom * viewer_border->ymax * ibuf->y);
+
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_ACTIVE);
+
+ immDrawBorderCorners(pos, &pixel_border, 1.0f, 1.0f);
+
+ immUnbindProgram();
+ }
+ }
+
+ GPU_matrix_pop_projection();
+ GPU_matrix_pop();
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
}
/* return quadratic beziers points for a given nodelink and clip if v2d is not NULL. */
-static bool node_link_bezier_handles(View2D *v2d, SpaceNode *snode, bNodeLink *link, float vec[4][2])
-{
- float dist;
- float deltax, deltay;
- float cursor[2] = {0.0f, 0.0f};
- int toreroute, fromreroute;
-
- /* this function can be called with snode null (via cut_links_intersect) */
- /* XXX map snode->cursor back to view space */
- if (snode) {
- cursor[0] = snode->cursor[0] * UI_DPI_FAC;
- cursor[1] = snode->cursor[1] * UI_DPI_FAC;
- }
-
- /* in v0 and v3 we put begin/end points */
- if (link->fromsock) {
- vec[0][0] = link->fromsock->locx;
- vec[0][1] = link->fromsock->locy;
- fromreroute = (link->fromnode && link->fromnode->type == NODE_REROUTE);
- }
- else {
- if (snode == NULL) {
- return 0;
- }
- copy_v2_v2(vec[0], cursor);
- fromreroute = 0;
- }
- if (link->tosock) {
- vec[3][0] = link->tosock->locx;
- vec[3][1] = link->tosock->locy;
- toreroute = (link->tonode && link->tonode->type == NODE_REROUTE);
- }
- else {
- if (snode == NULL) {
- return 0;
- }
- copy_v2_v2(vec[3], cursor);
- toreroute = 0;
- }
-
- /* may be called outside of drawing (so pass spacetype) */
- int curving = UI_GetThemeValueType(TH_NODE_CURVING, SPACE_NODE);
-
- if (curving == 0) {
- /* Straight line: align all points. */
- mid_v2_v2v2(vec[1], vec[0], vec[3]);
- mid_v2_v2v2(vec[2], vec[1], vec[3]);
- return 1;
- }
-
- dist = curving * 0.10f * fabsf(vec[0][0] - vec[3][0]);
- deltax = vec[3][0] - vec[0][0];
- deltay = vec[3][1] - vec[0][1];
- /* check direction later, for top sockets */
- if (fromreroute) {
- if (ABS(deltax) > ABS(deltay)) {
- vec[1][1] = vec[0][1];
- vec[1][0] = vec[0][0] + (deltax > 0 ? dist : -dist);
- }
- else {
- vec[1][0] = vec[0][0];
- vec[1][1] = vec[0][1] + (deltay > 0 ? dist : -dist);
- }
- }
- else {
- vec[1][0] = vec[0][0] + dist;
- vec[1][1] = vec[0][1];
- }
- if (toreroute) {
- if (ABS(deltax) > ABS(deltay)) {
- vec[2][1] = vec[3][1];
- vec[2][0] = vec[3][0] + (deltax > 0 ? -dist : dist);
- }
- else {
- vec[2][0] = vec[3][0];
- vec[2][1] = vec[3][1] + (deltay > 0 ? -dist : dist);
- }
-
- }
- else {
- vec[2][0] = vec[3][0] - dist;
- vec[2][1] = vec[3][1];
- }
-
- if (v2d && min_ffff(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > v2d->cur.xmax) {
- return 0; /* clipped */
- }
- else if (v2d && max_ffff(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) < v2d->cur.xmin) {
- return 0; /* clipped */
- }
-
- return 1;
+static bool node_link_bezier_handles(View2D *v2d,
+ SpaceNode *snode,
+ bNodeLink *link,
+ float vec[4][2])
+{
+ float dist;
+ float deltax, deltay;
+ float cursor[2] = {0.0f, 0.0f};
+ int toreroute, fromreroute;
+
+ /* this function can be called with snode null (via cut_links_intersect) */
+ /* XXX map snode->cursor back to view space */
+ if (snode) {
+ cursor[0] = snode->cursor[0] * UI_DPI_FAC;
+ cursor[1] = snode->cursor[1] * UI_DPI_FAC;
+ }
+
+ /* in v0 and v3 we put begin/end points */
+ if (link->fromsock) {
+ vec[0][0] = link->fromsock->locx;
+ vec[0][1] = link->fromsock->locy;
+ fromreroute = (link->fromnode && link->fromnode->type == NODE_REROUTE);
+ }
+ else {
+ if (snode == NULL) {
+ return 0;
+ }
+ copy_v2_v2(vec[0], cursor);
+ fromreroute = 0;
+ }
+ if (link->tosock) {
+ vec[3][0] = link->tosock->locx;
+ vec[3][1] = link->tosock->locy;
+ toreroute = (link->tonode && link->tonode->type == NODE_REROUTE);
+ }
+ else {
+ if (snode == NULL) {
+ return 0;
+ }
+ copy_v2_v2(vec[3], cursor);
+ toreroute = 0;
+ }
+
+ /* may be called outside of drawing (so pass spacetype) */
+ int curving = UI_GetThemeValueType(TH_NODE_CURVING, SPACE_NODE);
+
+ if (curving == 0) {
+ /* Straight line: align all points. */
+ mid_v2_v2v2(vec[1], vec[0], vec[3]);
+ mid_v2_v2v2(vec[2], vec[1], vec[3]);
+ return 1;
+ }
+
+ dist = curving * 0.10f * fabsf(vec[0][0] - vec[3][0]);
+ deltax = vec[3][0] - vec[0][0];
+ deltay = vec[3][1] - vec[0][1];
+ /* check direction later, for top sockets */
+ if (fromreroute) {
+ if (ABS(deltax) > ABS(deltay)) {
+ vec[1][1] = vec[0][1];
+ vec[1][0] = vec[0][0] + (deltax > 0 ? dist : -dist);
+ }
+ else {
+ vec[1][0] = vec[0][0];
+ vec[1][1] = vec[0][1] + (deltay > 0 ? dist : -dist);
+ }
+ }
+ else {
+ vec[1][0] = vec[0][0] + dist;
+ vec[1][1] = vec[0][1];
+ }
+ if (toreroute) {
+ if (ABS(deltax) > ABS(deltay)) {
+ vec[2][1] = vec[3][1];
+ vec[2][0] = vec[3][0] + (deltax > 0 ? -dist : dist);
+ }
+ else {
+ vec[2][0] = vec[3][0];
+ vec[2][1] = vec[3][1] + (deltay > 0 ? -dist : dist);
+ }
+ }
+ else {
+ vec[2][0] = vec[3][0] - dist;
+ vec[2][1] = vec[3][1];
+ }
+
+ if (v2d && min_ffff(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > v2d->cur.xmax) {
+ return 0; /* clipped */
+ }
+ else if (v2d && max_ffff(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) < v2d->cur.xmin) {
+ return 0; /* clipped */
+ }
+
+ return 1;
}
/* if v2d not NULL, it clips and returns 0 if not visible */
-bool node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol)
+bool node_link_bezier_points(
+ View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol)
{
- float vec[4][2];
+ float vec[4][2];
- if (node_link_bezier_handles(v2d, snode, link, vec)) {
- /* always do all three, to prevent data hanging around */
- BKE_curve_forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0],
- coord_array[0] + 0, resol, sizeof(float) * 2);
- BKE_curve_forward_diff_bezier(vec[0][1], vec[1][1], vec[2][1], vec[3][1],
- coord_array[0] + 1, resol, sizeof(float) * 2);
+ if (node_link_bezier_handles(v2d, snode, link, vec)) {
+ /* always do all three, to prevent data hanging around */
+ BKE_curve_forward_diff_bezier(
+ vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0] + 0, resol, sizeof(float) * 2);
+ BKE_curve_forward_diff_bezier(
+ vec[0][1], vec[1][1], vec[2][1], vec[3][1], coord_array[0] + 1, resol, sizeof(float) * 2);
- return 1;
- }
- return 0;
+ return 1;
+ }
+ return 0;
}
#define NODELINK_GROUP_SIZE 256
-#define LINK_RESOL 24
-#define LINK_WIDTH (2.5f * UI_DPI_FAC)
-#define ARROW_SIZE (7 * UI_DPI_FAC)
+#define LINK_RESOL 24
+#define LINK_WIDTH (2.5f * UI_DPI_FAC)
+#define ARROW_SIZE (7 * UI_DPI_FAC)
static float arrow_verts[3][2] = {{-1.0f, 1.0f}, {0.0f, 0.0f}, {-1.0f, -1.0f}};
static float arrow_expand_axis[3][2] = {{0.7071f, 0.7071f}, {M_SQRT2, 0.0f}, {0.7071f, -0.7071f}};
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;
- GPUVertBufRaw p0_step, p1_step, p2_step, p3_step;
- GPUVertBufRaw colid_step;
- unsigned int count;
- bool enabled;
+ 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;
+ GPUVertBufRaw p0_step, p1_step, p2_step, p3_step;
+ GPUVertBufRaw colid_step;
+ unsigned int count;
+ bool enabled;
} g_batch_link = {0};
static void nodelink_batch_reset(void)
{
- GPU_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p0_id, &g_batch_link.p0_step);
- GPU_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p1_id, &g_batch_link.p1_step);
- GPU_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p2_id, &g_batch_link.p2_step);
- GPU_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p3_id, &g_batch_link.p3_step);
- GPU_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.colid_id, &g_batch_link.colid_step);
- g_batch_link.count = 0;
+ GPU_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p0_id, &g_batch_link.p0_step);
+ GPU_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p1_id, &g_batch_link.p1_step);
+ GPU_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p2_id, &g_batch_link.p2_step);
+ GPU_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p3_id, &g_batch_link.p3_step);
+ GPU_vertbuf_attr_get_raw_data(
+ g_batch_link.inst_vbo, g_batch_link.colid_id, &g_batch_link.colid_step);
+ g_batch_link.count = 0;
}
-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], const float pos[2], const float exp[2])
+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],
+ const float pos[2],
+ const float exp[2])
{
- GPU_vertbuf_attr_set(vbo, uv_id, v, uv);
- GPU_vertbuf_attr_set(vbo, pos_id, v, pos);
- GPU_vertbuf_attr_set(vbo, exp_id, v, exp);
+ GPU_vertbuf_attr_set(vbo, uv_id, v, uv);
+ GPU_vertbuf_attr_set(vbo, pos_id, v, pos);
+ GPU_vertbuf_attr_set(vbo, exp_id, v, exp);
}
static void nodelink_batch_init(void)
{
- GPUVertFormat format = {0};
- uint uv_id = GPU_vertformat_attr_add(&format, "uv", GPU_COMP_U8, 2, GPU_FETCH_INT_TO_FLOAT_UNIT);
- uint pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint expand_id = GPU_vertformat_attr_add(&format, "expand", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_STATIC);
- int vcount = LINK_RESOL * 2; /* curve */
- vcount += 2; /* restart strip */
- vcount += 3 * 2; /* arrow */
- vcount *= 2; /* shadow */
- vcount += 2; /* restart strip */
- GPU_vertbuf_data_alloc(vbo, vcount);
- int v = 0;
-
- for (int k = 0; k < 2; ++k) {
- unsigned char uv[2] = {0, 0};
- float pos[2] = {0.0f, 0.0f};
- float exp[2] = {0.0f, 1.0f};
-
- /* restart */
- if (k == 1) {
- set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
- }
-
- /* curve strip */
- for (int i = 0; i < LINK_RESOL; ++i) {
- uv[0] = 255 * (i / (float)(LINK_RESOL - 1));
- uv[1] = 0;
- set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
- uv[1] = 255;
- set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
- }
- /* restart */
- set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
-
- uv[0] = 127;
- uv[1] = 0;
- copy_v2_v2(pos, arrow_verts[0]);
- copy_v2_v2(exp, arrow_expand_axis[0]);
- set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
- /* arrow */
- for (int i = 0; i < 3; ++i) {
- uv[1] = 0;
- copy_v2_v2(pos, arrow_verts[i]);
- copy_v2_v2(exp, arrow_expand_axis[i]);
- set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
-
- uv[1] = 255;
- set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
- }
-
- /* restart */
- if (k == 0) {
- set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
- }
- }
-
- g_batch_link.batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
- gpu_batch_presets_register(g_batch_link.batch);
-
- g_batch_link.batch_single = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, 0);
- gpu_batch_presets_register(g_batch_link.batch_single);
-
- /* Instances data */
- GPUVertFormat format_inst = {0};
- g_batch_link.p0_id = GPU_vertformat_attr_add(&format_inst, "P0", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- g_batch_link.p1_id = GPU_vertformat_attr_add(&format_inst, "P1", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- g_batch_link.p2_id = GPU_vertformat_attr_add(&format_inst, "P2", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- g_batch_link.p3_id = GPU_vertformat_attr_add(&format_inst, "P3", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- g_batch_link.colid_id = GPU_vertformat_attr_add(&format_inst, "colid_doarrow", GPU_COMP_U8, 4, GPU_FETCH_INT);
- g_batch_link.inst_vbo = GPU_vertbuf_create_with_format_ex(&format_inst, GPU_USAGE_STREAM);
- /* Alloc max count but only draw the range we need. */
- GPU_vertbuf_data_alloc(g_batch_link.inst_vbo, NODELINK_GROUP_SIZE);
-
- GPU_batch_instbuf_set(g_batch_link.batch, g_batch_link.inst_vbo, true);
-
- nodelink_batch_reset();
+ GPUVertFormat format = {0};
+ uint uv_id = GPU_vertformat_attr_add(&format, "uv", GPU_COMP_U8, 2, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ uint pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint expand_id = GPU_vertformat_attr_add(&format, "expand", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_STATIC);
+ int vcount = LINK_RESOL * 2; /* curve */
+ vcount += 2; /* restart strip */
+ vcount += 3 * 2; /* arrow */
+ vcount *= 2; /* shadow */
+ vcount += 2; /* restart strip */
+ GPU_vertbuf_data_alloc(vbo, vcount);
+ int v = 0;
+
+ for (int k = 0; k < 2; ++k) {
+ unsigned char uv[2] = {0, 0};
+ float pos[2] = {0.0f, 0.0f};
+ float exp[2] = {0.0f, 1.0f};
+
+ /* restart */
+ if (k == 1) {
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+ }
+
+ /* curve strip */
+ for (int i = 0; i < LINK_RESOL; ++i) {
+ uv[0] = 255 * (i / (float)(LINK_RESOL - 1));
+ uv[1] = 0;
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+ uv[1] = 255;
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+ }
+ /* restart */
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+
+ uv[0] = 127;
+ uv[1] = 0;
+ copy_v2_v2(pos, arrow_verts[0]);
+ copy_v2_v2(exp, arrow_expand_axis[0]);
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+ /* arrow */
+ for (int i = 0; i < 3; ++i) {
+ uv[1] = 0;
+ copy_v2_v2(pos, arrow_verts[i]);
+ copy_v2_v2(exp, arrow_expand_axis[i]);
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+
+ uv[1] = 255;
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+ }
+
+ /* restart */
+ if (k == 0) {
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+ }
+ }
+
+ g_batch_link.batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ gpu_batch_presets_register(g_batch_link.batch);
+
+ g_batch_link.batch_single = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, 0);
+ gpu_batch_presets_register(g_batch_link.batch_single);
+
+ /* Instances data */
+ GPUVertFormat format_inst = {0};
+ g_batch_link.p0_id = GPU_vertformat_attr_add(
+ &format_inst, "P0", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ g_batch_link.p1_id = GPU_vertformat_attr_add(
+ &format_inst, "P1", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ g_batch_link.p2_id = GPU_vertformat_attr_add(
+ &format_inst, "P2", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ g_batch_link.p3_id = GPU_vertformat_attr_add(
+ &format_inst, "P3", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ g_batch_link.colid_id = GPU_vertformat_attr_add(
+ &format_inst, "colid_doarrow", GPU_COMP_U8, 4, GPU_FETCH_INT);
+ g_batch_link.inst_vbo = GPU_vertbuf_create_with_format_ex(&format_inst, GPU_USAGE_STREAM);
+ /* Alloc max count but only draw the range we need. */
+ GPU_vertbuf_data_alloc(g_batch_link.inst_vbo, NODELINK_GROUP_SIZE);
+
+ GPU_batch_instbuf_set(g_batch_link.batch, g_batch_link.inst_vbo, true);
+
+ nodelink_batch_reset();
}
static char nodelink_get_color_id(int th_col)
{
- switch (th_col) {
- case TH_WIRE: return 1;
- case TH_WIRE_INNER: return 2;
- case TH_ACTIVE: return 3;
- case TH_EDGE_SELECT: return 4;
- case TH_REDALERT: return 5;
- }
- return 0;
+ switch (th_col) {
+ case TH_WIRE:
+ return 1;
+ case TH_WIRE_INNER:
+ return 2;
+ case TH_ACTIVE:
+ return 3;
+ case TH_EDGE_SELECT:
+ return 4;
+ case TH_REDALERT:
+ return 5;
+ }
+ return 0;
}
static void nodelink_batch_draw(SpaceNode *snode)
{
- if (g_batch_link.count == 0) {
- return;
- }
+ if (g_batch_link.count == 0) {
+ return;
+ }
- GPU_blend(true);
+ GPU_blend(true);
- float colors[6][4] = {{0.0f}};
- UI_GetThemeColor4fv(TH_WIRE_INNER, colors[nodelink_get_color_id(TH_WIRE_INNER)]);
- UI_GetThemeColor4fv(TH_WIRE, colors[nodelink_get_color_id(TH_WIRE)]);
- UI_GetThemeColor4fv(TH_ACTIVE, colors[nodelink_get_color_id(TH_ACTIVE)]);
- UI_GetThemeColor4fv(TH_EDGE_SELECT, colors[nodelink_get_color_id(TH_EDGE_SELECT)]);
- UI_GetThemeColor4fv(TH_REDALERT, colors[nodelink_get_color_id(TH_REDALERT)]);
+ float colors[6][4] = {{0.0f}};
+ UI_GetThemeColor4fv(TH_WIRE_INNER, colors[nodelink_get_color_id(TH_WIRE_INNER)]);
+ UI_GetThemeColor4fv(TH_WIRE, colors[nodelink_get_color_id(TH_WIRE)]);
+ UI_GetThemeColor4fv(TH_ACTIVE, colors[nodelink_get_color_id(TH_ACTIVE)]);
+ UI_GetThemeColor4fv(TH_EDGE_SELECT, colors[nodelink_get_color_id(TH_EDGE_SELECT)]);
+ UI_GetThemeColor4fv(TH_REDALERT, colors[nodelink_get_color_id(TH_REDALERT)]);
- GPU_vertbuf_data_len_set(g_batch_link.inst_vbo, g_batch_link.count);
- GPU_vertbuf_use(g_batch_link.inst_vbo); /* force update. */
+ GPU_vertbuf_data_len_set(g_batch_link.inst_vbo, g_batch_link.count);
+ GPU_vertbuf_use(g_batch_link.inst_vbo); /* force update. */
- GPU_batch_program_set_builtin(g_batch_link.batch, GPU_SHADER_2D_NODELINK_INST);
- GPU_batch_uniform_4fv_array(g_batch_link.batch, "colors", 6, (float *)colors);
- GPU_batch_uniform_1f(g_batch_link.batch, "expandSize", snode->aspect * LINK_WIDTH);
- GPU_batch_uniform_1f(g_batch_link.batch, "arrowSize", ARROW_SIZE);
- GPU_batch_draw(g_batch_link.batch);
+ GPU_batch_program_set_builtin(g_batch_link.batch, GPU_SHADER_2D_NODELINK_INST);
+ GPU_batch_uniform_4fv_array(g_batch_link.batch, "colors", 6, (float *)colors);
+ GPU_batch_uniform_1f(g_batch_link.batch, "expandSize", snode->aspect * LINK_WIDTH);
+ GPU_batch_uniform_1f(g_batch_link.batch, "arrowSize", ARROW_SIZE);
+ GPU_batch_draw(g_batch_link.batch);
- nodelink_batch_reset();
+ nodelink_batch_reset();
- GPU_blend(false);
+ GPU_blend(false);
}
void nodelink_batch_start(SpaceNode *UNUSED(snode))
{
- g_batch_link.enabled = true;
+ g_batch_link.enabled = true;
}
void nodelink_batch_end(SpaceNode *snode)
{
- nodelink_batch_draw(snode);
- g_batch_link.enabled = false;
-}
-
-static void nodelink_batch_add_link(
- SpaceNode *snode,
- const float p0[2], const float p1[2], const float p2[2], const float p3[2],
- int th_col1, int th_col2, int th_col3, bool drawarrow)
-{
- /* Only allow these colors. If more is needed, you need to modify the shader accordingly. */
- BLI_assert(ELEM(th_col1, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT));
- BLI_assert(ELEM(th_col2, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT));
- BLI_assert(ELEM(th_col3, TH_WIRE, -1));
-
- g_batch_link.count++;
- copy_v2_v2(GPU_vertbuf_raw_step(&g_batch_link.p0_step), p0);
- copy_v2_v2(GPU_vertbuf_raw_step(&g_batch_link.p1_step), p1);
- copy_v2_v2(GPU_vertbuf_raw_step(&g_batch_link.p2_step), p2);
- copy_v2_v2(GPU_vertbuf_raw_step(&g_batch_link.p3_step), p3);
- char *colid = GPU_vertbuf_raw_step(&g_batch_link.colid_step);
- colid[0] = nodelink_get_color_id(th_col1);
- colid[1] = nodelink_get_color_id(th_col2);
- colid[2] = nodelink_get_color_id(th_col3);
- colid[3] = drawarrow;
-
- if (g_batch_link.count == NODELINK_GROUP_SIZE) {
- nodelink_batch_draw(snode);
- }
+ nodelink_batch_draw(snode);
+ g_batch_link.enabled = false;
+}
+
+static void nodelink_batch_add_link(SpaceNode *snode,
+ const float p0[2],
+ const float p1[2],
+ const float p2[2],
+ const float p3[2],
+ int th_col1,
+ int th_col2,
+ int th_col3,
+ bool drawarrow)
+{
+ /* Only allow these colors. If more is needed, you need to modify the shader accordingly. */
+ BLI_assert(ELEM(th_col1, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT));
+ BLI_assert(ELEM(th_col2, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT));
+ BLI_assert(ELEM(th_col3, TH_WIRE, -1));
+
+ g_batch_link.count++;
+ copy_v2_v2(GPU_vertbuf_raw_step(&g_batch_link.p0_step), p0);
+ copy_v2_v2(GPU_vertbuf_raw_step(&g_batch_link.p1_step), p1);
+ copy_v2_v2(GPU_vertbuf_raw_step(&g_batch_link.p2_step), p2);
+ copy_v2_v2(GPU_vertbuf_raw_step(&g_batch_link.p3_step), p3);
+ char *colid = GPU_vertbuf_raw_step(&g_batch_link.colid_step);
+ colid[0] = nodelink_get_color_id(th_col1);
+ colid[1] = nodelink_get_color_id(th_col2);
+ colid[2] = nodelink_get_color_id(th_col3);
+ colid[3] = drawarrow;
+
+ if (g_batch_link.count == NODELINK_GROUP_SIZE) {
+ nodelink_batch_draw(snode);
+ }
}
/* don't do shadows if th_col3 is -1. */
-void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
- int th_col1, int th_col2, int th_col3)
-{
- float vec[4][2];
-
- if (node_link_bezier_handles(v2d, snode, link, vec)) {
- int drawarrow = ((link->tonode && (link->tonode->type == NODE_REROUTE)) &&
- (link->fromnode && (link->fromnode->type == NODE_REROUTE)));
-
- if (g_batch_link.batch == NULL) {
- nodelink_batch_init();
- }
-
- if (g_batch_link.enabled) {
- /* Add link to batch. */
- nodelink_batch_add_link(snode, vec[0], vec[1], vec[2], vec[3], th_col1, th_col2, th_col3, drawarrow);
- }
- else {
- /* Draw single link. */
- float colors[3][4] = {{0.0f}};
- if (th_col3 != -1) {
- UI_GetThemeColor4fv(th_col3, colors[0]);
- }
- UI_GetThemeColor4fv(th_col1, colors[1]);
- UI_GetThemeColor4fv(th_col2, colors[2]);
-
- GPUBatch *batch = g_batch_link.batch_single;
- GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODELINK);
- GPU_batch_uniform_2fv_array(batch, "bezierPts", 4, (float *)vec);
- GPU_batch_uniform_4fv_array(batch, "colors", 3, (float *)colors);
- GPU_batch_uniform_1f(batch, "expandSize", snode->aspect * LINK_WIDTH);
- GPU_batch_uniform_1f(batch, "arrowSize", ARROW_SIZE);
- GPU_batch_uniform_1i(batch, "doArrow", drawarrow);
- GPU_batch_draw(batch);
- }
- }
+void node_draw_link_bezier(
+ View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int th_col2, int th_col3)
+{
+ float vec[4][2];
+
+ if (node_link_bezier_handles(v2d, snode, link, vec)) {
+ int drawarrow = ((link->tonode && (link->tonode->type == NODE_REROUTE)) &&
+ (link->fromnode && (link->fromnode->type == NODE_REROUTE)));
+
+ if (g_batch_link.batch == NULL) {
+ nodelink_batch_init();
+ }
+
+ if (g_batch_link.enabled) {
+ /* Add link to batch. */
+ nodelink_batch_add_link(
+ snode, vec[0], vec[1], vec[2], vec[3], th_col1, th_col2, th_col3, drawarrow);
+ }
+ else {
+ /* Draw single link. */
+ float colors[3][4] = {{0.0f}};
+ if (th_col3 != -1) {
+ UI_GetThemeColor4fv(th_col3, colors[0]);
+ }
+ UI_GetThemeColor4fv(th_col1, colors[1]);
+ UI_GetThemeColor4fv(th_col2, colors[2]);
+
+ GPUBatch *batch = g_batch_link.batch_single;
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODELINK);
+ GPU_batch_uniform_2fv_array(batch, "bezierPts", 4, (float *)vec);
+ GPU_batch_uniform_4fv_array(batch, "colors", 3, (float *)colors);
+ GPU_batch_uniform_1f(batch, "expandSize", snode->aspect * LINK_WIDTH);
+ GPU_batch_uniform_1f(batch, "arrowSize", ARROW_SIZE);
+ GPU_batch_uniform_1i(batch, "doArrow", drawarrow);
+ GPU_batch_draw(batch);
+ }
+ }
}
/* note; this is used for fake links in groups too */
void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
{
- int th_col1 = TH_WIRE_INNER, th_col2 = TH_WIRE_INNER, th_col3 = TH_WIRE;
-
- if (link->fromsock == NULL && link->tosock == NULL) {
- return;
- }
-
- /* new connection */
- if (!link->fromsock || !link->tosock) {
- th_col1 = th_col2 = TH_ACTIVE;
- }
- else {
- /* going to give issues once... */
- if (link->tosock->flag & SOCK_UNAVAIL) {
- return;
- }
- if (link->fromsock->flag & SOCK_UNAVAIL) {
- return;
- }
-
- if (link->flag & NODE_LINK_VALID) {
- /* special indicated link, on drop-node */
- if (link->flag & NODE_LINKFLAG_HILITE) {
- th_col1 = th_col2 = TH_ACTIVE;
- }
- else {
- /* regular link */
- if (link->fromnode && link->fromnode->flag & SELECT) {
- th_col1 = TH_EDGE_SELECT;
- }
- if (link->tonode && link->tonode->flag & SELECT) {
- th_col2 = TH_EDGE_SELECT;
- }
- }
- }
- else {
- th_col1 = th_col2 = TH_REDALERT;
- // th_col3 = -1; /* no shadow */
- }
- }
-
- node_draw_link_bezier(v2d, snode, link, th_col1, th_col2, th_col3);
-// 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)
-{
- immBegin(GPU_PRIM_LINES, 4);
-
- if (border & (NODE_LEFT | NODE_RIGHT)) {
- immVertex2f(pos, cent[0], v2d->cur.ymin);
- immVertex2f(pos, cent[0], v2d->cur.ymax);
- }
- else {
- immVertex2f(pos, cent[0], cent[1] - size);
- immVertex2f(pos, cent[0], cent[1] + size);
- }
-
- if (border & (NODE_TOP | NODE_BOTTOM)) {
- immVertex2f(pos, v2d->cur.xmin, cent[1]);
- immVertex2f(pos, v2d->cur.xmax, cent[1]);
- }
- else {
- immVertex2f(pos, cent[0] - size, cent[1]);
- immVertex2f(pos, cent[0] + size, cent[1]);
- }
-
- immEnd();
+ int th_col1 = TH_WIRE_INNER, th_col2 = TH_WIRE_INNER, th_col3 = TH_WIRE;
+
+ if (link->fromsock == NULL && link->tosock == NULL) {
+ return;
+ }
+
+ /* new connection */
+ if (!link->fromsock || !link->tosock) {
+ th_col1 = th_col2 = TH_ACTIVE;
+ }
+ else {
+ /* going to give issues once... */
+ if (link->tosock->flag & SOCK_UNAVAIL) {
+ return;
+ }
+ if (link->fromsock->flag & SOCK_UNAVAIL) {
+ return;
+ }
+
+ if (link->flag & NODE_LINK_VALID) {
+ /* special indicated link, on drop-node */
+ if (link->flag & NODE_LINKFLAG_HILITE) {
+ th_col1 = th_col2 = TH_ACTIVE;
+ }
+ else {
+ /* regular link */
+ if (link->fromnode && link->fromnode->flag & SELECT) {
+ th_col1 = TH_EDGE_SELECT;
+ }
+ if (link->tonode && link->tonode->flag & SELECT) {
+ th_col2 = TH_EDGE_SELECT;
+ }
+ }
+ }
+ else {
+ th_col1 = th_col2 = TH_REDALERT;
+ // th_col3 = -1; /* no shadow */
+ }
+ }
+
+ node_draw_link_bezier(v2d, snode, link, th_col1, th_col2, th_col3);
+ // 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)
+{
+ immBegin(GPU_PRIM_LINES, 4);
+
+ if (border & (NODE_LEFT | NODE_RIGHT)) {
+ immVertex2f(pos, cent[0], v2d->cur.ymin);
+ immVertex2f(pos, cent[0], v2d->cur.ymax);
+ }
+ else {
+ immVertex2f(pos, cent[0], cent[1] - size);
+ immVertex2f(pos, cent[0], cent[1] + size);
+ }
+
+ if (border & (NODE_TOP | NODE_BOTTOM)) {
+ immVertex2f(pos, v2d->cur.xmin, cent[1]);
+ immVertex2f(pos, v2d->cur.xmax, cent[1]);
+ }
+ else {
+ immVertex2f(pos, cent[0] - size, cent[1]);
+ immVertex2f(pos, cent[0] + size, cent[1]);
+ }
+
+ immEnd();
}
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index 814496cf59e..8d754087855 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -39,7 +39,7 @@
#include "BKE_scene.h"
#include "BKE_texture.h"
-#include "ED_node.h" /* own include */
+#include "ED_node.h" /* own include */
#include "ED_screen.h"
#include "ED_render.h"
@@ -52,487 +52,509 @@
#include "UI_view2d.h"
-#include "node_intern.h" /* own include */
+#include "node_intern.h" /* own include */
/* XXX Does some additional initialization on top of nodeAddNode
* Can be used with both custom and static nodes, if idname==NULL the static int type will be used instead.
*/
bNode *node_add_node(const bContext *C, const char *idname, int type, float locx, float locy)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- Main *bmain = CTX_data_main(C);
- bNode *node = NULL;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ Main *bmain = CTX_data_main(C);
+ bNode *node = NULL;
- node_deselect_all(snode);
+ node_deselect_all(snode);
- if (idname) {
- node = nodeAddNode(C, snode->edittree, idname);
- }
- else {
- node = nodeAddStaticNode(C, snode->edittree, type);
- }
- BLI_assert(node && node->typeinfo);
+ if (idname) {
+ node = nodeAddNode(C, snode->edittree, idname);
+ }
+ else {
+ node = nodeAddStaticNode(C, snode->edittree, type);
+ }
+ BLI_assert(node && node->typeinfo);
- /* Position mouse in node header. */
- node->locx = locx - NODE_DY * 1.5f / UI_DPI_FAC;
- node->locy = locy + NODE_DY * 0.5f / UI_DPI_FAC;
+ /* Position mouse in node header. */
+ node->locx = locx - NODE_DY * 1.5f / UI_DPI_FAC;
+ node->locy = locy + NODE_DY * 0.5f / UI_DPI_FAC;
- nodeSetSelected(node, true);
+ nodeSetSelected(node, true);
- ntreeUpdateTree(bmain, snode->edittree);
- ED_node_set_active(bmain, snode->edittree, node);
+ ntreeUpdateTree(bmain, snode->edittree);
+ ED_node_set_active(bmain, snode->edittree, node);
- snode_update(snode, node);
+ snode_update(snode, node);
- if (snode->nodetree->type == NTREE_TEXTURE) {
- ntreeTexCheckCyclics(snode->edittree);
- }
+ if (snode->nodetree->type == NTREE_TEXTURE) {
+ ntreeTexCheckCyclics(snode->edittree);
+ }
- return node;
+ return node;
}
/* ********************** Add reroute operator ***************** */
-static bool add_reroute_intersect_check(bNodeLink *link, float mcoords[][2], int tot, float result[2])
+static bool add_reroute_intersect_check(bNodeLink *link,
+ float mcoords[][2],
+ int tot,
+ float result[2])
{
- float coord_array[NODE_LINK_RESOL + 1][2];
- int i, b;
-
- if (node_link_bezier_points(NULL, NULL, link, coord_array, NODE_LINK_RESOL)) {
-
- for (i = 0; i < tot - 1; i++) {
- for (b = 0; b < NODE_LINK_RESOL; b++) {
- if (isect_seg_seg_v2(mcoords[i], mcoords[i + 1], coord_array[b], coord_array[b + 1]) > 0) {
- result[0] = (mcoords[i][0] + mcoords[i + 1][0]) / 2.0f;
- result[1] = (mcoords[i][1] + mcoords[i + 1][1]) / 2.0f;
- return 1;
- }
- }
- }
- }
- return 0;
+ float coord_array[NODE_LINK_RESOL + 1][2];
+ int i, b;
+
+ if (node_link_bezier_points(NULL, NULL, link, coord_array, NODE_LINK_RESOL)) {
+
+ for (i = 0; i < tot - 1; i++) {
+ for (b = 0; b < NODE_LINK_RESOL; b++) {
+ if (isect_seg_seg_v2(mcoords[i], mcoords[i + 1], coord_array[b], coord_array[b + 1]) > 0) {
+ result[0] = (mcoords[i][0] + mcoords[i + 1][0]) / 2.0f;
+ result[1] = (mcoords[i][1] + mcoords[i + 1][1]) / 2.0f;
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
}
typedef struct bNodeSocketLink {
- struct bNodeSocketLink *next, *prev;
+ struct bNodeSocketLink *next, *prev;
- struct bNodeSocket *sock;
- struct bNodeLink *link;
- float point[2];
+ struct bNodeSocket *sock;
+ struct bNodeLink *link;
+ float point[2];
} bNodeSocketLink;
-static bNodeSocketLink *add_reroute_insert_socket_link(ListBase *lb, bNodeSocket *sock, bNodeLink *link, const float point[2])
+static bNodeSocketLink *add_reroute_insert_socket_link(ListBase *lb,
+ bNodeSocket *sock,
+ bNodeLink *link,
+ const float point[2])
{
- bNodeSocketLink *socklink, *prev;
-
- socklink = MEM_callocN(sizeof(bNodeSocketLink), "socket link");
- socklink->sock = sock;
- socklink->link = link;
- copy_v2_v2(socklink->point, point);
-
- for (prev = lb->last; prev; prev = prev->prev) {
- if (prev->sock == sock) {
- break;
- }
- }
- BLI_insertlinkafter(lb, prev, socklink);
- return socklink;
+ bNodeSocketLink *socklink, *prev;
+
+ socklink = MEM_callocN(sizeof(bNodeSocketLink), "socket link");
+ socklink->sock = sock;
+ socklink->link = link;
+ copy_v2_v2(socklink->point, point);
+
+ for (prev = lb->last; prev; prev = prev->prev) {
+ if (prev->sock == sock) {
+ break;
+ }
+ }
+ BLI_insertlinkafter(lb, prev, socklink);
+ return socklink;
}
-static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, bNodeSocketLink *socklink, int in_out)
+static bNodeSocketLink *add_reroute_do_socket_section(bContext *C,
+ bNodeSocketLink *socklink,
+ int in_out)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree = snode->edittree;
- bNode *reroute_node = NULL;
- bNodeSocket *cursock = socklink->sock;
- float insert_point[2];
- int num_links;
-
- zero_v2(insert_point);
- num_links = 0;
-
- while (socklink && socklink->sock == cursock) {
- if (!(socklink->link->flag & NODE_LINK_TEST)) {
- socklink->link->flag |= NODE_LINK_TEST;
-
- /* create the reroute node for this cursock */
- if (!reroute_node) {
- reroute_node = nodeAddStaticNode(C, ntree, NODE_REROUTE);
-
- /* add a single link to/from the reroute node to replace multiple links */
- if (in_out == SOCK_OUT) {
- nodeAddLink(ntree, socklink->link->fromnode, socklink->link->fromsock, reroute_node, reroute_node->inputs.first);
- }
- else {
- nodeAddLink(ntree, reroute_node, reroute_node->outputs.first, socklink->link->tonode, socklink->link->tosock);
- }
- }
-
- /* insert the reroute node into the link */
- if (in_out == SOCK_OUT) {
- socklink->link->fromnode = reroute_node;
- socklink->link->fromsock = reroute_node->outputs.first;
- }
- else {
- socklink->link->tonode = reroute_node;
- socklink->link->tosock = reroute_node->inputs.first;
- }
-
- add_v2_v2(insert_point, socklink->point);
- num_links++;
- }
- socklink = socklink->next;
- }
-
- if (num_links > 0) {
- /* average cut point from shared links */
- mul_v2_fl(insert_point, 1.0f / num_links);
-
- reroute_node->locx = insert_point[0] / UI_DPI_FAC;
- reroute_node->locy = insert_point[1] / UI_DPI_FAC;
- }
-
- return socklink;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNode *reroute_node = NULL;
+ bNodeSocket *cursock = socklink->sock;
+ float insert_point[2];
+ int num_links;
+
+ zero_v2(insert_point);
+ num_links = 0;
+
+ while (socklink && socklink->sock == cursock) {
+ if (!(socklink->link->flag & NODE_LINK_TEST)) {
+ socklink->link->flag |= NODE_LINK_TEST;
+
+ /* create the reroute node for this cursock */
+ if (!reroute_node) {
+ reroute_node = nodeAddStaticNode(C, ntree, NODE_REROUTE);
+
+ /* add a single link to/from the reroute node to replace multiple links */
+ if (in_out == SOCK_OUT) {
+ nodeAddLink(ntree,
+ socklink->link->fromnode,
+ socklink->link->fromsock,
+ reroute_node,
+ reroute_node->inputs.first);
+ }
+ else {
+ nodeAddLink(ntree,
+ reroute_node,
+ reroute_node->outputs.first,
+ socklink->link->tonode,
+ socklink->link->tosock);
+ }
+ }
+
+ /* insert the reroute node into the link */
+ if (in_out == SOCK_OUT) {
+ socklink->link->fromnode = reroute_node;
+ socklink->link->fromsock = reroute_node->outputs.first;
+ }
+ else {
+ socklink->link->tonode = reroute_node;
+ socklink->link->tosock = reroute_node->inputs.first;
+ }
+
+ add_v2_v2(insert_point, socklink->point);
+ num_links++;
+ }
+ socklink = socklink->next;
+ }
+
+ if (num_links > 0) {
+ /* average cut point from shared links */
+ mul_v2_fl(insert_point, 1.0f / num_links);
+
+ reroute_node->locx = insert_point[0] / UI_DPI_FAC;
+ reroute_node->locy = insert_point[1] / UI_DPI_FAC;
+ }
+
+ return socklink;
}
static int add_reroute_exec(bContext *C, wmOperator *op)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
- bNodeTree *ntree = snode->edittree;
- float mcoords[256][2];
- int i = 0;
-
- /* Get the cut path */
- RNA_BEGIN (op->ptr, itemptr, "path")
- {
- float loc[2];
-
- 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]);
- i++;
- if (i >= 256) {
- break;
- }
- }
- RNA_END;
-
- if (i > 1) {
- ListBase output_links, input_links;
- bNodeLink *link;
- bNodeSocketLink *socklink;
- float insert_point[2];
-
- /* always first */
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
-
- node_deselect_all(snode);
-
- /* Find cut links and sort them by sockets */
- BLI_listbase_clear(&output_links);
- BLI_listbase_clear(&input_links);
-
- for (link = ntree->links.first; link; link = link->next) {
- if (nodeLinkIsHidden(link)) {
- continue;
- }
- if (add_reroute_intersect_check(link, mcoords, i, insert_point)) {
- add_reroute_insert_socket_link(&output_links, link->fromsock, link, insert_point);
- add_reroute_insert_socket_link(&input_links, link->tosock, link, insert_point);
-
- /* Clear flag */
- link->flag &= ~NODE_LINK_TEST;
- }
- }
-
- /* Create reroute nodes for intersected links.
- * Only one reroute if links share the same input/output socket.
- */
- socklink = output_links.first;
- while (socklink) {
- socklink = add_reroute_do_socket_section(C, socklink, SOCK_OUT);
- }
- socklink = input_links.first;
- while (socklink) {
- socklink = add_reroute_do_socket_section(C, socklink, SOCK_IN);
- }
-
- BLI_freelistN(&output_links);
- BLI_freelistN(&input_links);
-
- /* always last */
- ntreeUpdateTree(CTX_data_main(C), ntree);
- snode_notify(C, snode);
- snode_dag_update(C, snode);
-
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
+ bNodeTree *ntree = snode->edittree;
+ float mcoords[256][2];
+ int i = 0;
+
+ /* Get the cut path */
+ RNA_BEGIN (op->ptr, itemptr, "path") {
+ float loc[2];
+
+ 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]);
+ i++;
+ if (i >= 256) {
+ break;
+ }
+ }
+ RNA_END;
+
+ if (i > 1) {
+ ListBase output_links, input_links;
+ bNodeLink *link;
+ bNodeSocketLink *socklink;
+ float insert_point[2];
+
+ /* always first */
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+
+ node_deselect_all(snode);
+
+ /* Find cut links and sort them by sockets */
+ BLI_listbase_clear(&output_links);
+ BLI_listbase_clear(&input_links);
+
+ for (link = ntree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link)) {
+ continue;
+ }
+ if (add_reroute_intersect_check(link, mcoords, i, insert_point)) {
+ add_reroute_insert_socket_link(&output_links, link->fromsock, link, insert_point);
+ add_reroute_insert_socket_link(&input_links, link->tosock, link, insert_point);
+
+ /* Clear flag */
+ link->flag &= ~NODE_LINK_TEST;
+ }
+ }
+
+ /* Create reroute nodes for intersected links.
+ * Only one reroute if links share the same input/output socket.
+ */
+ socklink = output_links.first;
+ while (socklink) {
+ socklink = add_reroute_do_socket_section(C, socklink, SOCK_OUT);
+ }
+ socklink = input_links.first;
+ while (socklink) {
+ socklink = add_reroute_do_socket_section(C, socklink, SOCK_IN);
+ }
+
+ BLI_freelistN(&output_links);
+ BLI_freelistN(&input_links);
+
+ /* always last */
+ ntreeUpdateTree(CTX_data_main(C), ntree);
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
}
void NODE_OT_add_reroute(wmOperatorType *ot)
{
- ot->name = "Add Reroute";
- ot->idname = "NODE_OT_add_reroute";
- ot->description = "Add a reroute node";
-
- ot->invoke = WM_gesture_lines_invoke;
- ot->modal = WM_gesture_lines_modal;
- ot->exec = add_reroute_exec;
- ot->cancel = WM_gesture_lines_cancel;
-
- ot->poll = ED_operator_node_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- PropertyRNA *prop;
- prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- /* internal */
- RNA_def_int(ot->srna, "cursor", BC_CROSSCURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
+ ot->name = "Add Reroute";
+ ot->idname = "NODE_OT_add_reroute";
+ ot->description = "Add a reroute node";
+
+ ot->invoke = WM_gesture_lines_invoke;
+ ot->modal = WM_gesture_lines_modal;
+ ot->exec = add_reroute_exec;
+ ot->cancel = WM_gesture_lines_cancel;
+
+ ot->poll = ED_operator_node_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ PropertyRNA *prop;
+ prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ /* internal */
+ RNA_def_int(ot->srna, "cursor", BC_CROSSCURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
}
-
/* ****************** Add File Node Operator ******************* */
static int node_add_file_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node;
- Image *ima;
- int type = 0;
-
- ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
- if (!ima) {
- return OPERATOR_CANCELLED;
- }
-
- switch (snode->nodetree->type) {
- case NTREE_SHADER:
- type = SH_NODE_TEX_IMAGE;
- break;
- case NTREE_TEXTURE:
- type = TEX_NODE_IMAGE;
- break;
- case NTREE_COMPOSIT:
- type = CMP_NODE_IMAGE;
- break;
- default:
- return OPERATOR_CANCELLED;
- }
-
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
-
- node = node_add_node(C, NULL, type, snode->cursor[0], snode->cursor[1]);
-
- if (!node) {
- BKE_report(op->reports, RPT_WARNING, "Could not add an image node");
- return OPERATOR_CANCELLED;
- }
-
- node->id = (ID *)ima;
-
- /* When adding new image file via drag-drop we need to load imbuf in order
- * to get proper image source.
- */
- if (RNA_struct_property_is_set(op->ptr, "filepath")) {
- BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_RELOAD);
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
- }
-
- snode_notify(C, snode);
- snode_dag_update(C, snode);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node;
+ Image *ima;
+ int type = 0;
+
+ ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
+ if (!ima) {
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (snode->nodetree->type) {
+ case NTREE_SHADER:
+ type = SH_NODE_TEX_IMAGE;
+ break;
+ case NTREE_TEXTURE:
+ type = TEX_NODE_IMAGE;
+ break;
+ case NTREE_COMPOSIT:
+ type = CMP_NODE_IMAGE;
+ break;
+ default:
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+
+ node = node_add_node(C, NULL, type, snode->cursor[0], snode->cursor[1]);
+
+ if (!node) {
+ BKE_report(op->reports, RPT_WARNING, "Could not add an image node");
+ return OPERATOR_CANCELLED;
+ }
+
+ node->id = (ID *)ima;
+
+ /* When adding new image file via drag-drop we need to load imbuf in order
+ * to get proper image source.
+ */
+ if (RNA_struct_property_is_set(op->ptr, "filepath")) {
+ BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_RELOAD);
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+ }
+
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
+
+ return OPERATOR_FINISHED;
}
static int node_add_file_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = 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]);
-
- snode->cursor[0] /= UI_DPI_FAC;
- snode->cursor[1] /= UI_DPI_FAC;
-
- if (RNA_struct_property_is_set(op->ptr, "filepath") || RNA_struct_property_is_set(op->ptr, "name")) {
- return node_add_file_exec(C, op);
- }
- else {
- return WM_operator_filesel(C, op, event);
- }
+ ARegion *ar = 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]);
+
+ snode->cursor[0] /= UI_DPI_FAC;
+ snode->cursor[1] /= UI_DPI_FAC;
+
+ if (RNA_struct_property_is_set(op->ptr, "filepath") ||
+ RNA_struct_property_is_set(op->ptr, "name")) {
+ return node_add_file_exec(C, op);
+ }
+ else {
+ return WM_operator_filesel(C, op, event);
+ }
}
void NODE_OT_add_file(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add File Node";
- ot->description = "Add a file node to the current node editor";
- ot->idname = "NODE_OT_add_file";
-
- /* callbacks */
- ot->exec = node_add_file_exec;
- ot->invoke = node_add_file_invoke;
- ot->poll = ED_operator_node_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
- RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Data-block name to assign");
+ /* identifiers */
+ ot->name = "Add File Node";
+ ot->description = "Add a file node to the current node editor";
+ ot->idname = "NODE_OT_add_file";
+
+ /* callbacks */
+ ot->exec = node_add_file_exec;
+ ot->invoke = node_add_file_invoke;
+ ot->poll = ED_operator_node_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
+ RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Data-block name to assign");
}
/* ****************** Add Mask Node Operator ******************* */
static bool node_add_mask_poll(bContext *C)
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
- return ED_operator_node_editable(C) && snode->nodetree->type == NTREE_COMPOSIT;
+ return ED_operator_node_editable(C) && snode->nodetree->type == NTREE_COMPOSIT;
}
static int node_add_mask_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node;
- ID *mask = NULL;
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node;
+ ID *mask = NULL;
- /* check input variables */
- char name[MAX_ID_NAME - 2];
- RNA_string_get(op->ptr, "name", name);
- mask = BKE_libblock_find_name(bmain, ID_MSK, name);
- if (!mask) {
- BKE_reportf(op->reports, RPT_ERROR, "Mask '%s' not found", name);
- return OPERATOR_CANCELLED;
- }
+ /* check input variables */
+ char name[MAX_ID_NAME - 2];
+ RNA_string_get(op->ptr, "name", name);
+ mask = BKE_libblock_find_name(bmain, ID_MSK, name);
+ if (!mask) {
+ BKE_reportf(op->reports, RPT_ERROR, "Mask '%s' not found", name);
+ return OPERATOR_CANCELLED;
+ }
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
- node = node_add_node(C, NULL, CMP_NODE_MASK, snode->cursor[0], snode->cursor[1]);
+ node = node_add_node(C, NULL, CMP_NODE_MASK, snode->cursor[0], snode->cursor[1]);
- if (!node) {
- BKE_report(op->reports, RPT_WARNING, "Could not add a mask node");
- return OPERATOR_CANCELLED;
- }
+ if (!node) {
+ BKE_report(op->reports, RPT_WARNING, "Could not add a mask node");
+ return OPERATOR_CANCELLED;
+ }
- node->id = mask;
- id_us_plus(mask);
+ node->id = mask;
+ id_us_plus(mask);
- snode_notify(C, snode);
- snode_dag_update(C, snode);
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_add_mask(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Mask Node";
- ot->description = "Add a mask node to the current node editor";
- ot->idname = "NODE_OT_add_mask";
+ /* identifiers */
+ ot->name = "Add Mask Node";
+ ot->description = "Add a mask node to the current node editor";
+ ot->idname = "NODE_OT_add_mask";
- /* callbacks */
- ot->exec = node_add_mask_exec;
- ot->poll = node_add_mask_poll;
+ /* callbacks */
+ ot->exec = node_add_mask_exec;
+ ot->poll = node_add_mask_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- RNA_def_string(ot->srna, "name", "Mask", MAX_ID_NAME - 2, "Name", "Data-block name to assign");
+ RNA_def_string(ot->srna, "name", "Mask", MAX_ID_NAME - 2, "Name", "Data-block name to assign");
}
/********************** New node tree operator *********************/
static int new_node_tree_exec(bContext *C, wmOperator *op)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- Main *bmain = CTX_data_main(C);
- bNodeTree *ntree;
- PointerRNA ptr, idptr;
- PropertyRNA *prop;
- const char *idname;
- char treename_buf[MAX_ID_NAME - 2];
- const char *treename;
-
- if (RNA_struct_property_is_set(op->ptr, "type")) {
- prop = RNA_struct_find_property(op->ptr, "type");
- RNA_property_enum_identifier(C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &idname);
- }
- else if (snode) {
- idname = snode->tree_idname;
- }
- else {
- return OPERATOR_CANCELLED;
- }
-
- if (RNA_struct_property_is_set(op->ptr, "name")) {
- RNA_string_get(op->ptr, "name", treename_buf);
- treename = treename_buf;
- }
- else {
- treename = DATA_("NodeTree");
- }
-
- if (!ntreeTypeFind(idname)) {
- BKE_reportf(op->reports, RPT_ERROR, "Node tree type %s undefined", idname);
- return OPERATOR_CANCELLED;
- }
-
- ntree = ntreeAddTree(bmain, treename, idname);
-
- /* hook into UI */
- UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
-
- if (prop) {
- /* RNA_property_pointer_set increases the user count,
- * fixed here as the editor is the initial user.
- */
- id_us_min(&ntree->id);
-
- RNA_id_pointer_create(&ntree->id, &idptr);
- RNA_property_pointer_set(&ptr, prop, idptr);
- RNA_property_update(C, &ptr, prop);
- }
- else if (snode) {
- snode->nodetree = ntree;
-
- ED_node_tree_update(C);
- }
-
- return OPERATOR_FINISHED;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ Main *bmain = CTX_data_main(C);
+ bNodeTree *ntree;
+ PointerRNA ptr, idptr;
+ PropertyRNA *prop;
+ const char *idname;
+ char treename_buf[MAX_ID_NAME - 2];
+ const char *treename;
+
+ if (RNA_struct_property_is_set(op->ptr, "type")) {
+ prop = RNA_struct_find_property(op->ptr, "type");
+ RNA_property_enum_identifier(C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &idname);
+ }
+ else if (snode) {
+ idname = snode->tree_idname;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (RNA_struct_property_is_set(op->ptr, "name")) {
+ RNA_string_get(op->ptr, "name", treename_buf);
+ treename = treename_buf;
+ }
+ else {
+ treename = DATA_("NodeTree");
+ }
+
+ if (!ntreeTypeFind(idname)) {
+ BKE_reportf(op->reports, RPT_ERROR, "Node tree type %s undefined", idname);
+ return OPERATOR_CANCELLED;
+ }
+
+ ntree = ntreeAddTree(bmain, treename, idname);
+
+ /* hook into UI */
+ UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
+
+ if (prop) {
+ /* RNA_property_pointer_set increases the user count,
+ * fixed here as the editor is the initial user.
+ */
+ id_us_min(&ntree->id);
+
+ RNA_id_pointer_create(&ntree->id, &idptr);
+ RNA_property_pointer_set(&ptr, prop, idptr);
+ RNA_property_update(C, &ptr, prop);
+ }
+ else if (snode) {
+ snode->nodetree = ntree;
+
+ ED_node_tree_update(C);
+ }
+
+ return OPERATOR_FINISHED;
}
-static const EnumPropertyItem *new_node_tree_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *new_node_tree_type_itemf(bContext *UNUSED(C),
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- return rna_node_tree_type_itemf(NULL, NULL, r_free);
+ return rna_node_tree_type_itemf(NULL, NULL, r_free);
}
void NODE_OT_new_node_tree(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "New Node Tree";
- ot->idname = "NODE_OT_new_node_tree";
- ot->description = "Create a new node tree";
+ /* identifiers */
+ ot->name = "New Node Tree";
+ ot->idname = "NODE_OT_new_node_tree";
+ ot->description = "Create a new node tree";
- /* api callbacks */
- ot->exec = new_node_tree_exec;
+ /* api callbacks */
+ ot->exec = new_node_tree_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, 0, "Tree Type", "");
- RNA_def_enum_funcs(prop, new_node_tree_type_itemf);
- RNA_def_string(ot->srna, "name", "NodeTree", MAX_ID_NAME - 2, "Name", "");
+ prop = RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, 0, "Tree Type", "");
+ RNA_def_enum_funcs(prop, new_node_tree_type_itemf);
+ RNA_def_string(ot->srna, "name", "NodeTree", MAX_ID_NAME - 2, "Name", "");
}
diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c
index 13f8eb0729e..63e97ecd955 100644
--- a/source/blender/editors/space_node/node_buttons.c
+++ b/source/blender/editors/space_node/node_buttons.c
@@ -45,8 +45,7 @@
#include "UI_resources.h"
-#include "node_intern.h" /* own include */
-
+#include "node_intern.h" /* own include */
/* ******************* node space & buttons ************** */
@@ -54,181 +53,208 @@
/* poll for active nodetree */
static bool active_nodetree_poll(const bContext *C, PanelType *UNUSED(pt))
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
- return (snode && snode->nodetree);
+ return (snode && snode->nodetree);
}
#endif
static bool node_sockets_poll(const bContext *C, PanelType *UNUSED(pt))
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
- return (snode && snode->nodetree && G.debug_value == 777);
+ return (snode && snode->nodetree && G.debug_value == 777);
}
static void node_sockets_panel(const bContext *C, Panel *pa)
{
- 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;
- char name[UI_MAX_NAME_STR];
-
- if (ELEM(NULL, ntree, node)) {
- return;
- }
-
- for (sock = node->inputs.first; sock; sock = sock->next) {
- BLI_snprintf(name, sizeof(name), "%s:", sock->name);
-
- split = uiLayoutSplit(layout, 0.35f, false);
- uiItemL(split, name, ICON_NONE);
- uiTemplateNodeLink(split, ntree, node, sock);
- }
+ 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;
+ char name[UI_MAX_NAME_STR];
+
+ if (ELEM(NULL, ntree, node)) {
+ return;
+ }
+
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ BLI_snprintf(name, sizeof(name), "%s:", sock->name);
+
+ split = uiLayoutSplit(layout, 0.35f, false);
+ uiItemL(split, name, ICON_NONE);
+ uiTemplateNodeLink(split, ntree, node, sock);
+ }
}
static bool node_tree_interface_poll(const bContext *C, PanelType *UNUSED(pt))
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
- return (snode && snode->edittree && (snode->edittree->inputs.first || snode->edittree->outputs.first));
+ return (snode && snode->edittree &&
+ (snode->edittree->inputs.first || snode->edittree->outputs.first));
}
static bool node_tree_find_active_socket(bNodeTree *ntree, bNodeSocket **r_sock, int *r_in_out)
{
- bNodeSocket *sock;
- for (sock = ntree->inputs.first; sock; sock = sock->next) {
- if (sock->flag & SELECT) {
- *r_sock = sock;
- *r_in_out = SOCK_IN;
- return true;
- }
- }
- for (sock = ntree->outputs.first; sock; sock = sock->next) {
- if (sock->flag & SELECT) {
- *r_sock = sock;
- *r_in_out = SOCK_OUT;
- return true;
- }
- }
-
- *r_sock = NULL;
- *r_in_out = 0;
- return false;
+ bNodeSocket *sock;
+ for (sock = ntree->inputs.first; sock; sock = sock->next) {
+ if (sock->flag & SELECT) {
+ *r_sock = sock;
+ *r_in_out = SOCK_IN;
+ return true;
+ }
+ }
+ for (sock = ntree->outputs.first; sock; sock = sock->next) {
+ if (sock->flag & SELECT) {
+ *r_sock = sock;
+ *r_in_out = SOCK_OUT;
+ return true;
+ }
+ }
+
+ *r_sock = NULL;
+ *r_in_out = 0;
+ return false;
}
static void node_tree_interface_panel(const bContext *C, Panel *pa)
{
- 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;
- PointerRNA ptr, sockptr, opptr;
- wmOperatorType *ot;
-
- if (!ntree) {
- return;
- }
-
- RNA_id_pointer_create((ID *)ntree, &ptr);
-
- node_tree_find_active_socket(ntree, &sock, &in_out);
- RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, sock, &sockptr);
-
- row = uiLayoutRow(layout, false);
-
- split = uiLayoutRow(row, true);
- col = uiLayoutColumn(split, true);
- ot = WM_operatortype_find("NODE_OT_tree_socket_add", false);
- uiItemL(col, IFACE_("Inputs:"), ICON_NONE);
- uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "inputs", &ptr, "inputs", &ptr, "active_input",
- NULL, 0, 0, 0, 0, false, false);
- uiItemFullO_ptr(col, ot, "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
- RNA_enum_set(&opptr, "in_out", SOCK_IN);
-
- col = uiLayoutColumn(split, true);
- uiItemL(col, IFACE_("Outputs:"), ICON_NONE);
- uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "outputs", &ptr, "outputs", &ptr, "active_output",
- NULL, 0, 0, 0, 0, false, false);
- uiItemFullO_ptr(col, ot, "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
- RNA_enum_set(&opptr, "in_out", SOCK_OUT);
-
- ot = WM_operatortype_find("NODE_OT_tree_socket_move", false);
- col = uiLayoutColumn(row, true);
- uiItemFullO_ptr(col, ot, "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
- RNA_enum_set(&opptr, "direction", 1);
- uiItemFullO_ptr(col, ot, "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
- RNA_enum_set(&opptr, "direction", 2);
-
- if (sock) {
- row = uiLayoutRow(layout, true);
- uiItemR(row, &sockptr, "name", 0, NULL, ICON_NONE);
- uiItemO(row, "", ICON_X, "NODE_OT_tree_socket_remove");
-
- if (sock->typeinfo->interface_draw) {
- uiItemS(layout);
- sock->typeinfo->interface_draw((bContext *)C, layout, &sockptr);
- }
- }
+ 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;
+ PointerRNA ptr, sockptr, opptr;
+ wmOperatorType *ot;
+
+ if (!ntree) {
+ return;
+ }
+
+ RNA_id_pointer_create((ID *)ntree, &ptr);
+
+ node_tree_find_active_socket(ntree, &sock, &in_out);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, sock, &sockptr);
+
+ row = uiLayoutRow(layout, false);
+
+ split = uiLayoutRow(row, true);
+ col = uiLayoutColumn(split, true);
+ ot = WM_operatortype_find("NODE_OT_tree_socket_add", false);
+ uiItemL(col, IFACE_("Inputs:"), ICON_NONE);
+ uiTemplateList(col,
+ (bContext *)C,
+ "NODE_UL_interface_sockets",
+ "inputs",
+ &ptr,
+ "inputs",
+ &ptr,
+ "active_input",
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ false,
+ false);
+ uiItemFullO_ptr(col, ot, "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
+ RNA_enum_set(&opptr, "in_out", SOCK_IN);
+
+ col = uiLayoutColumn(split, true);
+ uiItemL(col, IFACE_("Outputs:"), ICON_NONE);
+ uiTemplateList(col,
+ (bContext *)C,
+ "NODE_UL_interface_sockets",
+ "outputs",
+ &ptr,
+ "outputs",
+ &ptr,
+ "active_output",
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ false,
+ false);
+ uiItemFullO_ptr(col, ot, "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
+ RNA_enum_set(&opptr, "in_out", SOCK_OUT);
+
+ ot = WM_operatortype_find("NODE_OT_tree_socket_move", false);
+ col = uiLayoutColumn(row, true);
+ uiItemFullO_ptr(col, ot, "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
+ RNA_enum_set(&opptr, "direction", 1);
+ uiItemFullO_ptr(col, ot, "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
+ RNA_enum_set(&opptr, "direction", 2);
+
+ if (sock) {
+ row = uiLayoutRow(layout, true);
+ uiItemR(row, &sockptr, "name", 0, NULL, ICON_NONE);
+ uiItemO(row, "", ICON_X, "NODE_OT_tree_socket_remove");
+
+ if (sock->typeinfo->interface_draw) {
+ uiItemS(layout);
+ sock->typeinfo->interface_draw((bContext *)C, layout, &sockptr);
+ }
+ }
}
/* ******************* node buttons registration ************** */
void node_buttons_register(ARegionType *art)
{
- PanelType *pt;
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype node panel node sockets");
- strcpy(pt->idname, "NODE_PT_sockets");
- strcpy(pt->category, N_("Node"));
- strcpy(pt->label, N_("Sockets"));
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = node_sockets_panel;
- pt->poll = node_sockets_poll;
- pt->flag |= PNL_DEFAULT_CLOSED;
- BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype node panel tree interface");
- strcpy(pt->idname, "NODE_PT_node_tree_interface");
- strcpy(pt->category, N_("Node"));
- strcpy(pt->label, N_("Interface"));
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = node_tree_interface_panel;
- pt->poll = node_tree_interface_poll;
- BLI_addtail(&art->paneltypes, pt);
+ PanelType *pt;
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype node panel node sockets");
+ strcpy(pt->idname, "NODE_PT_sockets");
+ strcpy(pt->category, N_("Node"));
+ strcpy(pt->label, N_("Sockets"));
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = node_sockets_panel;
+ pt->poll = node_sockets_poll;
+ pt->flag |= PNL_DEFAULT_CLOSED;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype node panel tree interface");
+ strcpy(pt->idname, "NODE_PT_node_tree_interface");
+ strcpy(pt->category, N_("Node"));
+ strcpy(pt->label, N_("Interface"));
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = node_tree_interface_panel;
+ pt->poll = node_tree_interface_poll;
+ BLI_addtail(&art->paneltypes, pt);
}
static int node_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = node_has_buttons_region(sa);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = node_has_buttons_region(sa);
- if (ar) {
- ED_region_toggle_hidden(C, ar);
- }
+ if (ar) {
+ ED_region_toggle_hidden(C, ar);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* non-standard poll operator which doesn't care if there are any nodes */
static bool node_properties_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- return (sa && (sa->spacetype == SPACE_NODE));
+ ScrArea *sa = CTX_wm_area(C);
+ return (sa && (sa->spacetype == SPACE_NODE));
}
void NODE_OT_properties(wmOperatorType *ot)
{
- ot->name = "Toggle Sidebar";
- ot->description = "Toggle the properties region visibility";
- ot->idname = "NODE_OT_properties";
+ ot->name = "Toggle Sidebar";
+ ot->description = "Toggle the properties region visibility";
+ ot->idname = "NODE_OT_properties";
- ot->exec = node_properties_toggle_exec;
- ot->poll = node_properties_poll;
+ ot->exec = node_properties_toggle_exec;
+ ot->poll = node_properties_poll;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 6f7ebd36c09..a694ac2c38b 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -66,181 +66,183 @@
#include "RNA_access.h"
-#include "node_intern.h" /* own include */
+#include "node_intern.h" /* own include */
#ifdef WITH_COMPOSITOR
# include "COM_compositor.h"
#endif
/* XXX interface.h */
-extern void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select);
+extern void ui_draw_dropshadow(
+ const rctf *rct, float radius, float aspect, float alpha, int select);
float ED_node_grid_size(void)
{
- return U.widget_unit;
+ return U.widget_unit;
}
void ED_node_tree_update(const bContext *C)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- if (snode) {
- snode_set_context(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ if (snode) {
+ snode_set_context(C);
- id_us_ensure_real(&snode->nodetree->id);
- }
+ id_us_ensure_real(&snode->nodetree->id);
+ }
}
/* id is supposed to contain a node tree */
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;
- }
- }
-
- return NULL;
+ 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;
+ }
+ }
+
+ return NULL;
}
void ED_node_tag_update_id(ID *id)
{
- bNodeTree *ntree = node_tree_from_ID(id);
- if (id == NULL || ntree == NULL) {
- return;
- }
-
- /* TODO(sergey): With the new dependency graph it
- * should be just enough to only tag ntree itself,
- * all the users of this tree will have update
- * flushed from the tree,
- */
- DEG_id_tag_update(&ntree->id, 0);
-
- if (ntree->type == NTREE_SHADER) {
- DEG_id_tag_update(id, 0);
-
- if (GS(id->name) == ID_MA) {
- WM_main_add_notifier(NC_MATERIAL | ND_SHADING, id);
- }
- else if (GS(id->name) == ID_LA) {
- WM_main_add_notifier(NC_LAMP | ND_LIGHTING, id);
- }
- else if (GS(id->name) == ID_WO) {
- WM_main_add_notifier(NC_WORLD | ND_WORLD, id);
- }
- }
- else if (ntree->type == NTREE_COMPOSIT) {
- WM_main_add_notifier(NC_SCENE | ND_NODES, id);
- }
- else if (ntree->type == NTREE_TEXTURE) {
- DEG_id_tag_update(id, 0);
- WM_main_add_notifier(NC_TEXTURE | ND_NODES, id);
- }
- else if (id == &ntree->id) {
- /* node groups */
- DEG_id_tag_update(id, 0);
- }
+ bNodeTree *ntree = node_tree_from_ID(id);
+ if (id == NULL || ntree == NULL) {
+ return;
+ }
+
+ /* TODO(sergey): With the new dependency graph it
+ * should be just enough to only tag ntree itself,
+ * all the users of this tree will have update
+ * flushed from the tree,
+ */
+ DEG_id_tag_update(&ntree->id, 0);
+
+ if (ntree->type == NTREE_SHADER) {
+ DEG_id_tag_update(id, 0);
+
+ if (GS(id->name) == ID_MA) {
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING, id);
+ }
+ else if (GS(id->name) == ID_LA) {
+ WM_main_add_notifier(NC_LAMP | ND_LIGHTING, id);
+ }
+ else if (GS(id->name) == ID_WO) {
+ WM_main_add_notifier(NC_WORLD | ND_WORLD, id);
+ }
+ }
+ else if (ntree->type == NTREE_COMPOSIT) {
+ WM_main_add_notifier(NC_SCENE | ND_NODES, id);
+ }
+ else if (ntree->type == NTREE_TEXTURE) {
+ DEG_id_tag_update(id, 0);
+ WM_main_add_notifier(NC_TEXTURE | ND_NODES, id);
+ }
+ else if (id == &ntree->id) {
+ /* node groups */
+ DEG_id_tag_update(id, 0);
+ }
}
void ED_node_tag_update_nodetree(Main *bmain, bNodeTree *ntree, bNode *node)
{
- if (!ntree) {
- return;
- }
-
- bool do_tag_update = true;
- if (node != NULL) {
- if (!node_connected_to_output(bmain, ntree, node)) {
- do_tag_update = false;
- }
- }
-
- /* look through all datablocks, to support groups */
- if (do_tag_update) {
- FOREACH_NODETREE_BEGIN(bmain, tntree, id) {
- /* check if nodetree uses the group */
- if (ntreeHasTree(tntree, ntree)) {
- ED_node_tag_update_id(id);
- }
- } FOREACH_NODETREE_END;
- }
-
- if (ntree->type == NTREE_TEXTURE) {
- ntreeTexCheckCyclics(ntree);
- }
+ if (!ntree) {
+ return;
+ }
+
+ bool do_tag_update = true;
+ if (node != NULL) {
+ if (!node_connected_to_output(bmain, ntree, node)) {
+ do_tag_update = false;
+ }
+ }
+
+ /* look through all datablocks, to support groups */
+ if (do_tag_update) {
+ FOREACH_NODETREE_BEGIN (bmain, tntree, id) {
+ /* check if nodetree uses the group */
+ if (ntreeHasTree(tntree, ntree)) {
+ ED_node_tag_update_id(id);
+ }
+ }
+ FOREACH_NODETREE_END;
+ }
+
+ if (ntree->type == NTREE_TEXTURE) {
+ ntreeTexCheckCyclics(ntree);
+ }
}
static bool compare_nodes(const bNode *a, const bNode *b)
{
- bNode *parent;
- /* These tell if either the node or any of the parent nodes is selected.
- * A selected parent means an unselected node is also in foreground!
- */
- bool a_select = (a->flag & NODE_SELECT) != 0, b_select = (b->flag & NODE_SELECT) != 0;
- bool a_active = (a->flag & NODE_ACTIVE) != 0, b_active = (b->flag & NODE_ACTIVE) != 0;
-
- /* if one is an ancestor of the other */
- /* XXX there might be a better sorting algorithm for stable topological sort,
- * this is O(n^2) worst case */
- for (parent = a->parent; parent; parent = parent->parent) {
- /* if b is an ancestor, it is always behind a */
- if (parent == b) {
- return 1;
- }
- /* any selected ancestor moves the node forward */
- if (parent->flag & NODE_ACTIVE) {
- a_active = 1;
- }
- if (parent->flag & NODE_SELECT) {
- a_select = 1;
- }
- }
- for (parent = b->parent; parent; parent = parent->parent) {
- /* if a is an ancestor, it is always behind b */
- if (parent == a) {
- return 0;
- }
- /* any selected ancestor moves the node forward */
- if (parent->flag & NODE_ACTIVE) {
- b_active = 1;
- }
- if (parent->flag & NODE_SELECT) {
- b_select = 1;
- }
- }
-
- /* if one of the nodes is in the background and the other not */
- if ((a->flag & NODE_BACKGROUND) && !(b->flag & NODE_BACKGROUND)) {
- return 0;
- }
- else if (!(a->flag & NODE_BACKGROUND) && (b->flag & NODE_BACKGROUND)) {
- return 1;
- }
-
- /* if one has a higher selection state (active > selected > nothing) */
- if (!b_active && a_active) {
- return 1;
- }
- else if (!b_select && (a_active || a_select)) {
- return 1;
- }
-
- return 0;
+ bNode *parent;
+ /* These tell if either the node or any of the parent nodes is selected.
+ * A selected parent means an unselected node is also in foreground!
+ */
+ bool a_select = (a->flag & NODE_SELECT) != 0, b_select = (b->flag & NODE_SELECT) != 0;
+ bool a_active = (a->flag & NODE_ACTIVE) != 0, b_active = (b->flag & NODE_ACTIVE) != 0;
+
+ /* if one is an ancestor of the other */
+ /* XXX there might be a better sorting algorithm for stable topological sort,
+ * this is O(n^2) worst case */
+ for (parent = a->parent; parent; parent = parent->parent) {
+ /* if b is an ancestor, it is always behind a */
+ if (parent == b) {
+ return 1;
+ }
+ /* any selected ancestor moves the node forward */
+ if (parent->flag & NODE_ACTIVE) {
+ a_active = 1;
+ }
+ if (parent->flag & NODE_SELECT) {
+ a_select = 1;
+ }
+ }
+ for (parent = b->parent; parent; parent = parent->parent) {
+ /* if a is an ancestor, it is always behind b */
+ if (parent == a) {
+ return 0;
+ }
+ /* any selected ancestor moves the node forward */
+ if (parent->flag & NODE_ACTIVE) {
+ b_active = 1;
+ }
+ if (parent->flag & NODE_SELECT) {
+ b_select = 1;
+ }
+ }
+
+ /* if one of the nodes is in the background and the other not */
+ if ((a->flag & NODE_BACKGROUND) && !(b->flag & NODE_BACKGROUND)) {
+ return 0;
+ }
+ else if (!(a->flag & NODE_BACKGROUND) && (b->flag & NODE_BACKGROUND)) {
+ return 1;
+ }
+
+ /* if one has a higher selection state (active > selected > nothing) */
+ if (!b_active && a_active) {
+ return 1;
+ }
+ else if (!b_select && (a_active || a_select)) {
+ return 1;
+ }
+
+ return 0;
}
/* Sorts nodes by selection: unselected nodes first, then selected,
@@ -248,418 +250,451 @@ static bool compare_nodes(const bNode *a, const bNode *b)
*/
void ED_node_sort(bNodeTree *ntree)
{
- /* merge sort is the algorithm of choice here */
- bNode *first_a, *first_b, *node_a, *node_b, *tmp;
- int totnodes = BLI_listbase_count(&ntree->nodes);
- int k, a, b;
-
- k = 1;
- while (k < totnodes) {
- first_a = first_b = ntree->nodes.first;
-
- do {
- /* setup first_b pointer */
- for (b = 0; b < k && first_b; ++b) {
- first_b = first_b->next;
- }
- /* all batches merged? */
- if (first_b == NULL) {
- break;
- }
-
- /* merge batches */
- node_a = first_a;
- node_b = first_b;
- a = b = 0;
- while (a < k && b < k && node_b) {
- if (compare_nodes(node_a, node_b) == 0) {
- node_a = node_a->next;
- a++;
- }
- else {
- tmp = node_b;
- node_b = node_b->next;
- b++;
- BLI_remlink(&ntree->nodes, tmp);
- BLI_insertlinkbefore(&ntree->nodes, node_a, tmp);
- }
- }
-
- /* setup first pointers for next batch */
- first_b = node_b;
- for (; b < k; ++b) {
- /* all nodes sorted? */
- if (first_b == NULL) {
- break;
- }
- first_b = first_b->next;
- }
- first_a = first_b;
- } while (first_b);
-
- k = k << 1;
- }
+ /* merge sort is the algorithm of choice here */
+ bNode *first_a, *first_b, *node_a, *node_b, *tmp;
+ int totnodes = BLI_listbase_count(&ntree->nodes);
+ int k, a, b;
+
+ k = 1;
+ while (k < totnodes) {
+ first_a = first_b = ntree->nodes.first;
+
+ do {
+ /* setup first_b pointer */
+ for (b = 0; b < k && first_b; ++b) {
+ first_b = first_b->next;
+ }
+ /* all batches merged? */
+ if (first_b == NULL) {
+ break;
+ }
+
+ /* merge batches */
+ node_a = first_a;
+ node_b = first_b;
+ a = b = 0;
+ while (a < k && b < k && node_b) {
+ if (compare_nodes(node_a, node_b) == 0) {
+ node_a = node_a->next;
+ a++;
+ }
+ else {
+ tmp = node_b;
+ node_b = node_b->next;
+ b++;
+ BLI_remlink(&ntree->nodes, tmp);
+ BLI_insertlinkbefore(&ntree->nodes, node_a, tmp);
+ }
+ }
+
+ /* setup first pointers for next batch */
+ first_b = node_b;
+ for (; b < k; ++b) {
+ /* all nodes sorted? */
+ if (first_b == NULL) {
+ break;
+ }
+ first_b = first_b->next;
+ }
+ first_a = first_b;
+ } while (first_b);
+
+ k = k << 1;
+ }
}
-
static void do_node_internal_buttons(bContext *C, void *UNUSED(node_v), int event)
{
- if (event == B_NODE_EXEC) {
- SpaceNode *snode = CTX_wm_space_node(C);
- if (snode && snode->id) {
- ED_node_tag_update_id(snode->id);
- }
- }
+ if (event == B_NODE_EXEC) {
+ SpaceNode *snode = CTX_wm_space_node(C);
+ if (snode && snode->id) {
+ ED_node_tag_update_id(snode->id);
+ }
+ }
}
static void node_uiblocks_init(const bContext *C, bNodeTree *ntree)
{
- bNode *node;
- char uiblockstr[32];
+ bNode *node;
+ char uiblockstr[32];
- /* add node uiBlocks in drawing order - prevents events going to overlapping nodes */
+ /* add node uiBlocks in drawing order - prevents events going to overlapping nodes */
- for (node = ntree->nodes.first; node; node = node->next) {
- /* ui block */
- BLI_snprintf(uiblockstr, sizeof(uiblockstr), "node buttons %p", (void *)node);
- node->block = UI_block_begin(C, CTX_wm_region(C), uiblockstr, UI_EMBOSS);
- UI_block_func_handle_set(node->block, do_node_internal_buttons, node);
+ for (node = ntree->nodes.first; node; node = node->next) {
+ /* ui block */
+ BLI_snprintf(uiblockstr, sizeof(uiblockstr), "node buttons %p", (void *)node);
+ node->block = UI_block_begin(C, CTX_wm_region(C), uiblockstr, UI_EMBOSS);
+ UI_block_func_handle_set(node->block, do_node_internal_buttons, node);
- /* this cancels events for background nodes */
- UI_block_flag_enable(node->block, UI_BLOCK_CLIP_EVENTS);
- }
+ /* this cancels events for background nodes */
+ UI_block_flag_enable(node->block, UI_BLOCK_CLIP_EVENTS);
+ }
}
void node_to_view(struct bNode *node, float x, float y, float *rx, float *ry)
{
- nodeToView(node, x, y, rx, ry);
- *rx *= UI_DPI_FAC;
- *ry *= UI_DPI_FAC;
+ nodeToView(node, x, y, rx, ry);
+ *rx *= UI_DPI_FAC;
+ *ry *= UI_DPI_FAC;
}
void node_to_updated_rect(struct bNode *node, rctf *r_rect)
{
- node_to_view(node, node->offsetx, node->offsety, &r_rect->xmin, &r_rect->ymax);
- node_to_view(node, node->offsetx + node->width, node->offsety - node->height, &r_rect->xmax, &r_rect->ymin);
+ node_to_view(node, node->offsetx, node->offsety, &r_rect->xmin, &r_rect->ymax);
+ node_to_view(node,
+ node->offsetx + node->width,
+ node->offsety - node->height,
+ &r_rect->xmax,
+ &r_rect->ymin);
}
void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry)
{
- x /= UI_DPI_FAC;
- y /= UI_DPI_FAC;
- nodeFromView(node, x, y, rx, ry);
+ x /= UI_DPI_FAC;
+ y /= UI_DPI_FAC;
+ nodeFromView(node, x, y, rx, ry);
}
-
/* based on settings in node, sets drawing rect info. each redraw! */
static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
{
- uiLayout *layout, *row;
- PointerRNA nodeptr, sockptr;
- bNodeSocket *nsock;
- float locx, locy;
- float dy;
- int buty;
-
- RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
-
- /* get "global" coords */
- node_to_view(node, 0.0f, 0.0f, &locx, &locy);
- dy = locy;
-
- /* header */
- dy -= NODE_DY;
-
- /* little bit space in top */
- if (node->outputs.first) {
- dy -= NODE_DYS / 2;
- }
-
- /* output sockets */
- bool add_output_space = false;
-
- for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
- if (nodeSocketIsHidden(nsock)) {
- continue;
- }
-
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
-
- layout = UI_block_layout(
- node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
- locx + NODE_DYS, dy, NODE_WIDTH(node) - NODE_DY, NODE_DY, 0, UI_style_get());
-
- if (node->flag & NODE_MUTED) {
- uiLayoutSetActive(layout, false);
- }
-
- /* context pointers for current node and socket */
- uiLayoutSetContextPointer(layout, "node", &nodeptr);
- uiLayoutSetContextPointer(layout, "socket", &sockptr);
-
- /* 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));
-
- UI_block_align_end(node->block);
- UI_block_layout_resolve(node->block, NULL, &buty);
-
- /* ensure minimum socket height in case layout is empty */
- buty = min_ii(buty, dy - NODE_DY);
-
- nsock->locx = locx + NODE_WIDTH(node);
- /* place the socket circle in the middle of the layout */
- nsock->locy = 0.5f * (dy + buty);
-
- dy = buty;
- if (nsock->next) {
- dy -= NODE_SOCKDY;
- }
-
- add_output_space = true;
- }
-
- if (add_output_space) {
- dy -= NODE_DY / 4;
- }
-
- node->prvr.xmin = locx + NODE_DYS;
- node->prvr.xmax = locx + NODE_WIDTH(node) - NODE_DYS;
-
- /* preview rect? */
- if (node->flag & NODE_PREVIEW) {
- float aspect = 1.0f;
-
- if (node->preview_xsize && node->preview_ysize) {
- aspect = (float)node->preview_ysize / (float)node->preview_xsize;
- }
-
- dy -= NODE_DYS / 2;
- node->prvr.ymax = dy;
-
- if (aspect <= 1.0f) {
- node->prvr.ymin = dy - aspect * (NODE_WIDTH(node) - NODE_DY);
- }
- else {
- /* width correction of image */
- /* XXX huh? (ton) */
- float dx = (NODE_WIDTH(node) - NODE_DYS) - (NODE_WIDTH(node) - NODE_DYS) / aspect;
+ uiLayout *layout, *row;
+ PointerRNA nodeptr, sockptr;
+ bNodeSocket *nsock;
+ float locx, locy;
+ float dy;
+ int buty;
- node->prvr.ymin = dy - (NODE_WIDTH(node) - NODE_DY);
+ RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
- node->prvr.xmin += 0.5f * dx;
- node->prvr.xmax -= 0.5f * dx;
- }
-
- dy = node->prvr.ymin - NODE_DYS / 2;
-
- /* make sure that maximums are bigger or equal to minimums */
- if (node->prvr.xmax < node->prvr.xmin) {
- SWAP(float, node->prvr.xmax, node->prvr.xmin);
- }
- if (node->prvr.ymax < node->prvr.ymin) {
- SWAP(float, node->prvr.ymax, node->prvr.ymin);
- }
- }
-
- /* buttons rect? */
- if (node->typeinfo->draw_buttons && (node->flag & NODE_OPTIONS)) {
- dy -= NODE_DYS / 2;
-
- /* set this for uifunc() that don't use layout engine yet */
- node->butr.xmin = 0;
- node->butr.xmax = NODE_WIDTH(node) - 2 * NODE_DYS;
- node->butr.ymin = 0;
- node->butr.ymax = 0;
-
-
- layout = UI_block_layout(
- node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
- locx + NODE_DYS, dy, node->butr.xmax, 0, 0, UI_style_get());
-
- if (node->flag & NODE_MUTED) {
- uiLayoutSetActive(layout, false);
- }
-
- uiLayoutSetContextPointer(layout, "node", &nodeptr);
-
- node->typeinfo->draw_buttons(layout, (bContext *)C, &nodeptr);
-
- UI_block_align_end(node->block);
- UI_block_layout_resolve(node->block, NULL, &buty);
-
- dy = buty - NODE_DYS / 2;
- }
-
- /* input sockets */
- for (nsock = node->inputs.first; nsock; nsock = nsock->next) {
- if (nodeSocketIsHidden(nsock)) {
- continue;
- }
-
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
-
- layout = UI_block_layout(
- node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
- locx + NODE_DYS, dy, NODE_WIDTH(node) - NODE_DY, NODE_DY, 0, UI_style_get());
-
- if (node->flag & NODE_MUTED) {
- uiLayoutSetActive(layout, false);
- }
-
- /* context pointers for current node and socket */
- uiLayoutSetContextPointer(layout, "node", &nodeptr);
- uiLayoutSetContextPointer(layout, "socket", &sockptr);
-
- row = uiLayoutRow(layout, 1);
-
- nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(nsock->name));
-
- UI_block_align_end(node->block);
- UI_block_layout_resolve(node->block, NULL, &buty);
-
- /* ensure minimum socket height in case layout is empty */
- buty = min_ii(buty, dy - NODE_DY);
-
- nsock->locx = locx;
- /* place the socket circle in the middle of the layout */
- nsock->locy = 0.5f * (dy + buty);
-
- dy = buty;
- if (nsock->next) {
- dy -= NODE_SOCKDY;
- }
- }
-
- /* little bit space in end */
- if (node->inputs.first || (node->flag & (NODE_OPTIONS | NODE_PREVIEW)) == 0) {
- dy -= NODE_DYS / 2;
- }
-
- node->totr.xmin = locx;
- node->totr.xmax = locx + NODE_WIDTH(node);
- node->totr.ymax = locy;
- node->totr.ymin = min_ff(dy, locy - 2 * NODE_DY);
-
- /* Set the block bounds to clip mouse events from underlying nodes.
- * Add a margin for sockets on each side.
- */
- UI_block_bounds_set_explicit(
- node->block,
- node->totr.xmin - NODE_SOCKSIZE,
- node->totr.ymin,
- node->totr.xmax + NODE_SOCKSIZE,
- node->totr.ymax);
+ /* get "global" coords */
+ node_to_view(node, 0.0f, 0.0f, &locx, &locy);
+ dy = locy;
+
+ /* header */
+ dy -= NODE_DY;
+
+ /* little bit space in top */
+ if (node->outputs.first) {
+ dy -= NODE_DYS / 2;
+ }
+
+ /* output sockets */
+ bool add_output_space = false;
+
+ for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
+ if (nodeSocketIsHidden(nsock)) {
+ continue;
+ }
+
+ RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
+
+ layout = UI_block_layout(node->block,
+ UI_LAYOUT_VERTICAL,
+ UI_LAYOUT_PANEL,
+ locx + NODE_DYS,
+ dy,
+ NODE_WIDTH(node) - NODE_DY,
+ NODE_DY,
+ 0,
+ UI_style_get());
+
+ if (node->flag & NODE_MUTED) {
+ uiLayoutSetActive(layout, false);
+ }
+
+ /* context pointers for current node and socket */
+ uiLayoutSetContextPointer(layout, "node", &nodeptr);
+ uiLayoutSetContextPointer(layout, "socket", &sockptr);
+
+ /* 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));
+
+ UI_block_align_end(node->block);
+ UI_block_layout_resolve(node->block, NULL, &buty);
+
+ /* ensure minimum socket height in case layout is empty */
+ buty = min_ii(buty, dy - NODE_DY);
+
+ nsock->locx = locx + NODE_WIDTH(node);
+ /* place the socket circle in the middle of the layout */
+ nsock->locy = 0.5f * (dy + buty);
+
+ dy = buty;
+ if (nsock->next) {
+ dy -= NODE_SOCKDY;
+ }
+
+ add_output_space = true;
+ }
+
+ if (add_output_space) {
+ dy -= NODE_DY / 4;
+ }
+
+ node->prvr.xmin = locx + NODE_DYS;
+ node->prvr.xmax = locx + NODE_WIDTH(node) - NODE_DYS;
+
+ /* preview rect? */
+ if (node->flag & NODE_PREVIEW) {
+ float aspect = 1.0f;
+
+ if (node->preview_xsize && node->preview_ysize) {
+ aspect = (float)node->preview_ysize / (float)node->preview_xsize;
+ }
+
+ dy -= NODE_DYS / 2;
+ node->prvr.ymax = dy;
+
+ if (aspect <= 1.0f) {
+ node->prvr.ymin = dy - aspect * (NODE_WIDTH(node) - NODE_DY);
+ }
+ else {
+ /* width correction of image */
+ /* XXX huh? (ton) */
+ float dx = (NODE_WIDTH(node) - NODE_DYS) - (NODE_WIDTH(node) - NODE_DYS) / aspect;
+
+ node->prvr.ymin = dy - (NODE_WIDTH(node) - NODE_DY);
+
+ node->prvr.xmin += 0.5f * dx;
+ node->prvr.xmax -= 0.5f * dx;
+ }
+
+ dy = node->prvr.ymin - NODE_DYS / 2;
+
+ /* make sure that maximums are bigger or equal to minimums */
+ if (node->prvr.xmax < node->prvr.xmin) {
+ SWAP(float, node->prvr.xmax, node->prvr.xmin);
+ }
+ if (node->prvr.ymax < node->prvr.ymin) {
+ SWAP(float, node->prvr.ymax, node->prvr.ymin);
+ }
+ }
+
+ /* buttons rect? */
+ if (node->typeinfo->draw_buttons && (node->flag & NODE_OPTIONS)) {
+ dy -= NODE_DYS / 2;
+
+ /* set this for uifunc() that don't use layout engine yet */
+ node->butr.xmin = 0;
+ node->butr.xmax = NODE_WIDTH(node) - 2 * NODE_DYS;
+ node->butr.ymin = 0;
+ node->butr.ymax = 0;
+
+ layout = UI_block_layout(node->block,
+ UI_LAYOUT_VERTICAL,
+ UI_LAYOUT_PANEL,
+ locx + NODE_DYS,
+ dy,
+ node->butr.xmax,
+ 0,
+ 0,
+ UI_style_get());
+
+ if (node->flag & NODE_MUTED) {
+ uiLayoutSetActive(layout, false);
+ }
+
+ uiLayoutSetContextPointer(layout, "node", &nodeptr);
+
+ node->typeinfo->draw_buttons(layout, (bContext *)C, &nodeptr);
+
+ UI_block_align_end(node->block);
+ UI_block_layout_resolve(node->block, NULL, &buty);
+
+ dy = buty - NODE_DYS / 2;
+ }
+
+ /* input sockets */
+ for (nsock = node->inputs.first; nsock; nsock = nsock->next) {
+ if (nodeSocketIsHidden(nsock)) {
+ continue;
+ }
+
+ RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
+
+ layout = UI_block_layout(node->block,
+ UI_LAYOUT_VERTICAL,
+ UI_LAYOUT_PANEL,
+ locx + NODE_DYS,
+ dy,
+ NODE_WIDTH(node) - NODE_DY,
+ NODE_DY,
+ 0,
+ UI_style_get());
+
+ if (node->flag & NODE_MUTED) {
+ uiLayoutSetActive(layout, false);
+ }
+
+ /* context pointers for current node and socket */
+ uiLayoutSetContextPointer(layout, "node", &nodeptr);
+ uiLayoutSetContextPointer(layout, "socket", &sockptr);
+
+ row = uiLayoutRow(layout, 1);
+
+ nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(nsock->name));
+
+ UI_block_align_end(node->block);
+ UI_block_layout_resolve(node->block, NULL, &buty);
+
+ /* ensure minimum socket height in case layout is empty */
+ buty = min_ii(buty, dy - NODE_DY);
+
+ nsock->locx = locx;
+ /* place the socket circle in the middle of the layout */
+ nsock->locy = 0.5f * (dy + buty);
+
+ dy = buty;
+ if (nsock->next) {
+ dy -= NODE_SOCKDY;
+ }
+ }
+
+ /* little bit space in end */
+ if (node->inputs.first || (node->flag & (NODE_OPTIONS | NODE_PREVIEW)) == 0) {
+ dy -= NODE_DYS / 2;
+ }
+
+ node->totr.xmin = locx;
+ node->totr.xmax = locx + NODE_WIDTH(node);
+ node->totr.ymax = locy;
+ node->totr.ymin = min_ff(dy, locy - 2 * NODE_DY);
+
+ /* Set the block bounds to clip mouse events from underlying nodes.
+ * Add a margin for sockets on each side.
+ */
+ UI_block_bounds_set_explicit(node->block,
+ node->totr.xmin - NODE_SOCKSIZE,
+ node->totr.ymin,
+ node->totr.xmax + NODE_SOCKSIZE,
+ node->totr.ymax);
}
/* based on settings in node, sets drawing rect info. each redraw! */
static void node_update_hidden(bNode *node)
{
- bNodeSocket *nsock;
- float locx, locy;
- float rad, drad, hiddenrad = HIDDEN_RAD;
- int totin = 0, totout = 0, tot;
-
- /* get "global" coords */
- node_to_view(node, 0.0f, 0.0f, &locx, &locy);
-
- /* calculate minimal radius */
- for (nsock = node->inputs.first; nsock; nsock = nsock->next) {
- if (!nodeSocketIsHidden(nsock)) {
- totin++;
- }
- }
- for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
- if (!nodeSocketIsHidden(nsock)) {
- totout++;
- }
- }
-
- tot = MAX2(totin, totout);
- if (tot > 4) {
- hiddenrad += 5.0f * (float)(tot - 4);
- }
-
- node->totr.xmin = locx;
- node->totr.xmax = locx + max_ff(NODE_WIDTH(node), 2 * hiddenrad);
- node->totr.ymax = locy + (hiddenrad - 0.5f * NODE_DY);
- node->totr.ymin = node->totr.ymax - 2 * hiddenrad;
-
- /* output sockets */
- rad = drad = (float)M_PI / (1.0f + (float)totout);
-
- for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
- if (!nodeSocketIsHidden(nsock)) {
- nsock->locx = node->totr.xmax - hiddenrad + sinf(rad) * hiddenrad;
- nsock->locy = node->totr.ymin + hiddenrad + cosf(rad) * hiddenrad;
- rad += drad;
- }
- }
-
- /* input sockets */
- rad = drad = -(float)M_PI / (1.0f + (float)totin);
-
- for (nsock = node->inputs.first; nsock; nsock = nsock->next) {
- if (!nodeSocketIsHidden(nsock)) {
- nsock->locx = node->totr.xmin + hiddenrad + sinf(rad) * hiddenrad;
- nsock->locy = node->totr.ymin + hiddenrad + cosf(rad) * hiddenrad;
- rad += drad;
- }
- }
-
- /* Set the block bounds to clip mouse events from underlying nodes.
- * Add a margin for sockets on each side.
- */
- UI_block_bounds_set_explicit(
- node->block,
- node->totr.xmin - NODE_SOCKSIZE,
- node->totr.ymin,
- node->totr.xmax + NODE_SOCKSIZE,
- node->totr.ymax);
+ bNodeSocket *nsock;
+ float locx, locy;
+ float rad, drad, hiddenrad = HIDDEN_RAD;
+ int totin = 0, totout = 0, tot;
+
+ /* get "global" coords */
+ node_to_view(node, 0.0f, 0.0f, &locx, &locy);
+
+ /* calculate minimal radius */
+ for (nsock = node->inputs.first; nsock; nsock = nsock->next) {
+ if (!nodeSocketIsHidden(nsock)) {
+ totin++;
+ }
+ }
+ for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
+ if (!nodeSocketIsHidden(nsock)) {
+ totout++;
+ }
+ }
+
+ tot = MAX2(totin, totout);
+ if (tot > 4) {
+ hiddenrad += 5.0f * (float)(tot - 4);
+ }
+
+ node->totr.xmin = locx;
+ node->totr.xmax = locx + max_ff(NODE_WIDTH(node), 2 * hiddenrad);
+ node->totr.ymax = locy + (hiddenrad - 0.5f * NODE_DY);
+ node->totr.ymin = node->totr.ymax - 2 * hiddenrad;
+
+ /* output sockets */
+ rad = drad = (float)M_PI / (1.0f + (float)totout);
+
+ for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
+ if (!nodeSocketIsHidden(nsock)) {
+ nsock->locx = node->totr.xmax - hiddenrad + sinf(rad) * hiddenrad;
+ nsock->locy = node->totr.ymin + hiddenrad + cosf(rad) * hiddenrad;
+ rad += drad;
+ }
+ }
+
+ /* input sockets */
+ rad = drad = -(float)M_PI / (1.0f + (float)totin);
+
+ for (nsock = node->inputs.first; nsock; nsock = nsock->next) {
+ if (!nodeSocketIsHidden(nsock)) {
+ nsock->locx = node->totr.xmin + hiddenrad + sinf(rad) * hiddenrad;
+ nsock->locy = node->totr.ymin + hiddenrad + cosf(rad) * hiddenrad;
+ rad += drad;
+ }
+ }
+
+ /* Set the block bounds to clip mouse events from underlying nodes.
+ * Add a margin for sockets on each side.
+ */
+ UI_block_bounds_set_explicit(node->block,
+ node->totr.xmin - NODE_SOCKSIZE,
+ node->totr.ymin,
+ node->totr.xmax + NODE_SOCKSIZE,
+ node->totr.ymax);
}
void node_update_default(const bContext *C, bNodeTree *ntree, bNode *node)
{
- if (node->flag & NODE_HIDDEN) {
- node_update_hidden(node);
- }
- else {
- node_update_basis(C, ntree, node);
- }
+ if (node->flag & NODE_HIDDEN) {
+ node_update_hidden(node);
+ }
+ else {
+ node_update_basis(C, ntree, node);
+ }
}
int node_select_area_default(bNode *node, int x, int y)
{
- return BLI_rctf_isect_pt(&node->totr, x, y);
+ return BLI_rctf_isect_pt(&node->totr, x, y);
}
int node_tweak_area_default(bNode *node, int x, int y)
{
- return BLI_rctf_isect_pt(&node->totr, x, y);
+ return BLI_rctf_isect_pt(&node->totr, x, y);
}
int node_get_colorid(bNode *node)
{
- switch (node->typeinfo->nclass) {
- case NODE_CLASS_INPUT: return TH_NODE_INPUT;
- case NODE_CLASS_OUTPUT: return (node->flag & NODE_DO_OUTPUT) ? TH_NODE_OUTPUT : TH_NODE;
- case NODE_CLASS_CONVERTOR: return TH_NODE_CONVERTOR;
- case NODE_CLASS_OP_COLOR: return TH_NODE_COLOR;
- case NODE_CLASS_OP_VECTOR: return TH_NODE_VECTOR;
- case NODE_CLASS_OP_FILTER: return TH_NODE_FILTER;
- case NODE_CLASS_GROUP: return TH_NODE_GROUP;
- case NODE_CLASS_INTERFACE: return TH_NODE_INTERFACE;
- case NODE_CLASS_MATTE: return TH_NODE_MATTE;
- case NODE_CLASS_DISTORT: return TH_NODE_DISTORT;
- case NODE_CLASS_TEXTURE: return TH_NODE_TEXTURE;
- case NODE_CLASS_SHADER: return TH_NODE_SHADER;
- case NODE_CLASS_SCRIPT: return TH_NODE_SCRIPT;
- case NODE_CLASS_PATTERN: return TH_NODE_PATTERN;
- case NODE_CLASS_LAYOUT: return TH_NODE_LAYOUT;
- default: return TH_NODE;
- }
+ switch (node->typeinfo->nclass) {
+ case NODE_CLASS_INPUT:
+ return TH_NODE_INPUT;
+ case NODE_CLASS_OUTPUT:
+ return (node->flag & NODE_DO_OUTPUT) ? TH_NODE_OUTPUT : TH_NODE;
+ case NODE_CLASS_CONVERTOR:
+ return TH_NODE_CONVERTOR;
+ case NODE_CLASS_OP_COLOR:
+ return TH_NODE_COLOR;
+ case NODE_CLASS_OP_VECTOR:
+ return TH_NODE_VECTOR;
+ case NODE_CLASS_OP_FILTER:
+ return TH_NODE_FILTER;
+ case NODE_CLASS_GROUP:
+ return TH_NODE_GROUP;
+ case NODE_CLASS_INTERFACE:
+ return TH_NODE_INTERFACE;
+ case NODE_CLASS_MATTE:
+ return TH_NODE_MATTE;
+ case NODE_CLASS_DISTORT:
+ return TH_NODE_DISTORT;
+ case NODE_CLASS_TEXTURE:
+ return TH_NODE_TEXTURE;
+ case NODE_CLASS_SHADER:
+ return TH_NODE_SHADER;
+ case NODE_CLASS_SCRIPT:
+ return TH_NODE_SCRIPT;
+ case NODE_CLASS_PATTERN:
+ return TH_NODE_PATTERN;
+ case NODE_CLASS_LAYOUT:
+ return TH_NODE_LAYOUT;
+ default:
+ return TH_NODE;
+ }
}
/* note: in cmp_util.c is similar code, for node_compo_pass_on()
@@ -667,898 +702,1034 @@ int node_get_colorid(bNode *node)
/* note: in node_edit.c is similar code, for untangle node */
static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node)
{
- bNodeLink *link;
+ bNodeLink *link;
- GPU_blend(true);
+ GPU_blend(true);
- for (link = node->internal_links.first; link; link = link->next) {
- node_draw_link_bezier(v2d, snode, link, TH_REDALERT, TH_REDALERT, -1);
- }
+ for (link = node->internal_links.first; link; link = link->next) {
+ node_draw_link_bezier(v2d, snode, link, TH_REDALERT, TH_REDALERT, -1);
+ }
- GPU_blend(false);
+ GPU_blend(false);
}
-static void node_socket_circle_draw(const bContext *C, bNodeTree *ntree, PointerRNA node_ptr, bNodeSocket *sock, unsigned pos, unsigned col)
+static void node_socket_circle_draw(const bContext *C,
+ bNodeTree *ntree,
+ PointerRNA node_ptr,
+ bNodeSocket *sock,
+ unsigned pos,
+ unsigned col)
{
- PointerRNA ptr;
- float color[4];
+ PointerRNA ptr;
+ float color[4];
- RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
- sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color);
+ 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;
- }
+ bNode *node = node_ptr.data;
+ if (node->flag & NODE_MUTED) {
+ color[3] *= 0.25f;
+ }
- immAttr4fv(col, color);
- immVertex2f(pos, sock->locx, sock->locy);
+ immAttr4fv(col, color);
+ immVertex2f(pos, sock->locx, sock->locy);
}
/* ************** Socket callbacks *********** */
static void node_draw_preview_background(float tile, rctf *rect)
{
- float x, y;
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* draw checkerboard backdrop to show alpha */
- immUniformColor3ub(120, 120, 120);
- immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
- immUniformColor3ub(160, 160, 160);
-
- for (y = rect->ymin; y < rect->ymax; y += tile * 2) {
- for (x = rect->xmin; x < rect->xmax; x += tile * 2) {
- float tilex = tile, tiley = tile;
-
- if (x + tile > rect->xmax) {
- tilex = rect->xmax - x;
- }
- if (y + tile > rect->ymax) {
- tiley = rect->ymax - y;
- }
-
- immRectf(pos, x, y, x + tilex, y + tiley);
- }
- }
- for (y = rect->ymin + tile; y < rect->ymax; y += tile * 2) {
- for (x = rect->xmin + tile; x < rect->xmax; x += tile * 2) {
- float tilex = tile, tiley = tile;
-
- if (x + tile > rect->xmax) {
- tilex = rect->xmax - x;
- }
- if (y + tile > rect->ymax) {
- tiley = rect->ymax - y;
- }
-
- immRectf(pos, x, y, x + tilex, y + tiley);
- }
- }
- immUnbindProgram();
+ float x, y;
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* draw checkerboard backdrop to show alpha */
+ immUniformColor3ub(120, 120, 120);
+ immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ immUniformColor3ub(160, 160, 160);
+
+ for (y = rect->ymin; y < rect->ymax; y += tile * 2) {
+ for (x = rect->xmin; x < rect->xmax; x += tile * 2) {
+ float tilex = tile, tiley = tile;
+
+ if (x + tile > rect->xmax) {
+ tilex = rect->xmax - x;
+ }
+ if (y + tile > rect->ymax) {
+ tiley = rect->ymax - y;
+ }
+
+ immRectf(pos, x, y, x + tilex, y + tiley);
+ }
+ }
+ for (y = rect->ymin + tile; y < rect->ymax; y += tile * 2) {
+ for (x = rect->xmin + tile; x < rect->xmax; x += tile * 2) {
+ float tilex = tile, tiley = tile;
+
+ if (x + tile > rect->xmax) {
+ tilex = rect->xmax - x;
+ }
+ if (y + tile > rect->ymax) {
+ tiley = rect->ymax - y;
+ }
+
+ immRectf(pos, x, y, x + tilex, y + tiley);
+ }
+ }
+ immUnbindProgram();
}
/* not a callback */
static void node_draw_preview(bNodePreview *preview, rctf *prv)
{
- float xrect = BLI_rctf_size_x(prv);
- float yrect = BLI_rctf_size_y(prv);
- float xscale = xrect / ((float)preview->xsize);
- float yscale = yrect / ((float)preview->ysize);
- float scale;
- rctf draw_rect;
-
- /* uniform scale and offset */
- draw_rect = *prv;
- if (xscale < yscale) {
- float offset = 0.5f * (yrect - ((float)preview->ysize) * xscale);
- draw_rect.ymin += offset;
- draw_rect.ymax -= offset;
- scale = xscale;
- }
- else {
- float offset = 0.5f * (xrect - ((float)preview->xsize) * yscale);
- draw_rect.xmin += offset;
- draw_rect.xmax -= offset;
- scale = yscale;
- }
-
- node_draw_preview_background(BLI_rctf_size_x(prv) / 10.0f, &draw_rect);
-
- GPU_blend(true);
- /* premul graphics */
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
- immDrawPixelsTex(&state, draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect,
- scale, scale, NULL);
-
- GPU_blend(false);
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColorShadeAlpha(TH_BACK, -15, +100);
- imm_draw_box_wire_2d(pos, draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax);
- immUnbindProgram();
+ float xrect = BLI_rctf_size_x(prv);
+ float yrect = BLI_rctf_size_y(prv);
+ float xscale = xrect / ((float)preview->xsize);
+ float yscale = yrect / ((float)preview->ysize);
+ float scale;
+ rctf draw_rect;
+
+ /* uniform scale and offset */
+ draw_rect = *prv;
+ if (xscale < yscale) {
+ float offset = 0.5f * (yrect - ((float)preview->ysize) * xscale);
+ draw_rect.ymin += offset;
+ draw_rect.ymax -= offset;
+ scale = xscale;
+ }
+ else {
+ float offset = 0.5f * (xrect - ((float)preview->xsize) * yscale);
+ draw_rect.xmin += offset;
+ draw_rect.xmax -= offset;
+ scale = yscale;
+ }
+
+ node_draw_preview_background(BLI_rctf_size_x(prv) / 10.0f, &draw_rect);
+
+ GPU_blend(true);
+ /* premul graphics */
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(&state,
+ draw_rect.xmin,
+ draw_rect.ymin,
+ preview->xsize,
+ preview->ysize,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ GL_LINEAR,
+ preview->rect,
+ scale,
+ scale,
+ NULL);
+
+ GPU_blend(false);
+
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShadeAlpha(TH_BACK, -15, +100);
+ imm_draw_box_wire_2d(pos, draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax);
+ immUnbindProgram();
}
/* common handle function for operator buttons that need to select the node first */
static void node_toggle_button_cb(struct bContext *C, void *node_argv, void *op_argv)
{
- bNode *node = (bNode *)node_argv;
- const char *opname = (const char *)op_argv;
+ bNode *node = (bNode *)node_argv;
+ const char *opname = (const char *)op_argv;
- /* select & activate only the button's node */
- node_select_single(C, node);
+ /* select & activate only the button's node */
+ node_select_single(C, node);
- WM_operator_name_call(C, opname, WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, opname, WM_OP_INVOKE_DEFAULT, NULL);
}
void node_draw_shadow(SpaceNode *snode, bNode *node, float radius, float alpha)
{
- rctf *rct = &node->totr;
-
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- if (node->parent == NULL) {
- ui_draw_dropshadow(rct, radius, snode->aspect, alpha, node->flag & SELECT);
- }
- else {
- const float margin = 3.0f;
-
- float color[4] = {0.0f, 0.0f, 0.0f, 0.33f};
- UI_draw_roundbox_aa(true, rct->xmin - margin, rct->ymin - margin,
- rct->xmax + margin, rct->ymax + margin, radius + margin, color);
- }
+ rctf *rct = &node->totr;
+
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ if (node->parent == NULL) {
+ ui_draw_dropshadow(rct, radius, snode->aspect, alpha, node->flag & SELECT);
+ }
+ else {
+ const float margin = 3.0f;
+
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.33f};
+ UI_draw_roundbox_aa(true,
+ rct->xmin - margin,
+ rct->ymin - margin,
+ rct->xmax + margin,
+ rct->ymax + margin,
+ radius + margin,
+ color);
+ }
}
-void node_draw_sockets(View2D *v2d, const bContext *C, bNodeTree *ntree, bNode *node, bool draw_outputs, bool select_all)
+void node_draw_sockets(View2D *v2d,
+ const bContext *C,
+ bNodeTree *ntree,
+ bNode *node,
+ bool draw_outputs,
+ bool select_all)
{
- const uint total_input_len = BLI_listbase_count(&node->inputs);
- const uint total_output_len = BLI_listbase_count(&node->outputs);
-
- if (total_input_len + total_output_len == 0) {
- return;
- }
-
- PointerRNA node_ptr;
- RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
-
- float scale;
- UI_view2d_scale_get(v2d, &scale, NULL);
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
-
- GPU_blend(true);
- GPU_enable_program_point_size();
-
- immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA);
-
- /* set handle size */
- immUniform1f("size", 2.0f * NODE_SOCKSIZE * scale); /* 2 * size to have diameter */
-
- if (!select_all) {
- /* outline for unselected sockets */
- immUniform1f("outlineWidth", 1.0f);
- immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 0.6f);
-
- immBeginAtMost(GPU_PRIM_POINTS, total_input_len + total_output_len);
- }
-
- /* socket inputs */
- short selected_input_len = 0;
- bNodeSocket *sock;
- for (sock = node->inputs.first; sock; sock = sock->next) {
- if (nodeSocketIsHidden(sock)) {
- continue;
- }
- if (select_all || (sock->flag & SELECT)) {
- ++selected_input_len;
- continue;
- }
-
- node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
- }
-
- /* socket outputs */
- short selected_output_len = 0;
- if (draw_outputs) {
- for (sock = node->outputs.first; sock; sock = sock->next) {
- if (nodeSocketIsHidden(sock)) {
- continue;
- }
- if (select_all || (sock->flag & SELECT)) {
- ++selected_output_len;
- continue;
- }
-
- node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
- }
- }
-
- if (!select_all) {
- immEnd();
- }
-
- /* go back and draw selected sockets */
- if (selected_input_len + selected_output_len > 0) {
- /* outline for selected sockets */
- float c[3];
- UI_GetThemeColor3fv(TH_TEXT_HI, c);
- immUniform4f("outlineColor", c[0], c[1], c[2], 1.0f);
- immUniform1f("outlineWidth", 1.5f);
-
- immBegin(GPU_PRIM_POINTS, selected_input_len + selected_output_len);
-
- if (selected_input_len) {
- /* socket inputs */
- for (sock = node->inputs.first; sock; sock = sock->next) {
- if (nodeSocketIsHidden(sock)) {
- continue;
- }
- if (select_all || (sock->flag & SELECT)) {
- node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
- if (--selected_input_len == 0) {
- break; /* stop as soon as last one is drawn */
- }
- }
- }
- }
-
- if (selected_output_len) {
- /* socket outputs */
- for (sock = node->outputs.first; sock; sock = sock->next) {
- if (nodeSocketIsHidden(sock)) {
- continue;
- }
- if (select_all || (sock->flag & SELECT)) {
- node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
- if (--selected_output_len == 0) {
- break; /* stop as soon as last one is drawn */
- }
- }
- }
- }
-
- immEnd();
- }
-
- immUnbindProgram();
-
- GPU_disable_program_point_size();
- GPU_blend(false);
+ const uint total_input_len = BLI_listbase_count(&node->inputs);
+ const uint total_output_len = BLI_listbase_count(&node->outputs);
+
+ if (total_input_len + total_output_len == 0) {
+ return;
+ }
+
+ PointerRNA node_ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
+
+ float scale;
+ UI_view2d_scale_get(v2d, &scale, NULL);
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+
+ GPU_blend(true);
+ GPU_enable_program_point_size();
+
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA);
+
+ /* set handle size */
+ immUniform1f("size", 2.0f * NODE_SOCKSIZE * scale); /* 2 * size to have diameter */
+
+ if (!select_all) {
+ /* outline for unselected sockets */
+ immUniform1f("outlineWidth", 1.0f);
+ immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 0.6f);
+
+ immBeginAtMost(GPU_PRIM_POINTS, total_input_len + total_output_len);
+ }
+
+ /* socket inputs */
+ short selected_input_len = 0;
+ bNodeSocket *sock;
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (nodeSocketIsHidden(sock)) {
+ continue;
+ }
+ if (select_all || (sock->flag & SELECT)) {
+ ++selected_input_len;
+ continue;
+ }
+
+ node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
+ }
+
+ /* socket outputs */
+ short selected_output_len = 0;
+ if (draw_outputs) {
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ if (nodeSocketIsHidden(sock)) {
+ continue;
+ }
+ if (select_all || (sock->flag & SELECT)) {
+ ++selected_output_len;
+ continue;
+ }
+
+ node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
+ }
+ }
+
+ if (!select_all) {
+ immEnd();
+ }
+
+ /* go back and draw selected sockets */
+ if (selected_input_len + selected_output_len > 0) {
+ /* outline for selected sockets */
+ float c[3];
+ UI_GetThemeColor3fv(TH_TEXT_HI, c);
+ immUniform4f("outlineColor", c[0], c[1], c[2], 1.0f);
+ immUniform1f("outlineWidth", 1.5f);
+
+ immBegin(GPU_PRIM_POINTS, selected_input_len + selected_output_len);
+
+ if (selected_input_len) {
+ /* socket inputs */
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (nodeSocketIsHidden(sock)) {
+ continue;
+ }
+ if (select_all || (sock->flag & SELECT)) {
+ node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
+ if (--selected_input_len == 0) {
+ break; /* stop as soon as last one is drawn */
+ }
+ }
+ }
+ }
+
+ if (selected_output_len) {
+ /* socket outputs */
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ if (nodeSocketIsHidden(sock)) {
+ continue;
+ }
+ if (select_all || (sock->flag & SELECT)) {
+ node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
+ if (--selected_output_len == 0) {
+ break; /* stop as soon as last one is drawn */
+ }
+ }
+ }
+ }
+
+ immEnd();
+ }
+
+ immUnbindProgram();
+
+ GPU_disable_program_point_size();
+ GPU_blend(false);
}
-static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
+static void node_draw_basis(const bContext *C,
+ ARegion *ar,
+ SpaceNode *snode,
+ bNodeTree *ntree,
+ bNode *node,
+ bNodeInstanceKey key)
{
- bNodeInstanceHash *previews = CTX_data_pointer_get(C, "node_previews").data;
- rctf *rct = &node->totr;
- float iconofs;
- /* float socket_size = NODE_SOCKSIZE*U.dpi/72; */ /* UNUSED */
- float iconbutw = 0.8f * UI_UNIT_X;
- int color_id = node_get_colorid(node);
- float color[4];
- char showname[128]; /* 128 used below */
- View2D *v2d = &ar->v2d;
-
- /* skip if out of view */
- if (BLI_rctf_isect(&node->totr, &v2d->cur, NULL) == false) {
- UI_block_end(C, node->block);
- node->block = NULL;
- return;
- }
-
- /* shadow */
- node_draw_shadow(snode, node, BASIS_RAD, 1.0f);
-
- if (node->flag & NODE_MUTED) {
- /* Muted nodes are semi-transparent and colorless. */
- UI_GetThemeColor3fv(TH_NODE, color);
- color[3] = 0.25f;
- }
- else {
- /* Opaque headers for regular nodes. */
- UI_GetThemeColor3fv(color_id, color);
- color[3] = 1.0f;
- }
-
- GPU_line_width(1.0f);
-
- UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
- UI_draw_roundbox_aa(true, rct->xmin, rct->ymax - NODE_DY, rct->xmax, rct->ymax, BASIS_RAD, color);
-
- /* show/hide icons */
- iconofs = rct->xmax - 0.35f * U.widget_unit;
-
- /* preview */
- if (node->typeinfo->flag & NODE_PREVIEW) {
- uiBut *but;
- iconofs -= iconbutw;
- UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
- but = uiDefIconBut(node->block, UI_BTYPE_BUT_TOGGLE, B_REDR, ICON_MATERIAL,
- iconofs, rct->ymax - NODE_DY, iconbutw, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_preview_toggle");
- /* XXX this does not work when node is activated and the operator called right afterwards,
- * since active ID is not updated yet (needs to process the notifier).
- * This can only work as visual indicator!
- */
-// if (!(node->flag & (NODE_ACTIVE_ID|NODE_DO_OUTPUT)))
-// UI_but_flag_enable(but, UI_BUT_DISABLED);
- UI_block_emboss_set(node->block, UI_EMBOSS);
- }
- /* group edit */
- if (node->type == NODE_GROUP) {
- uiBut *but;
- iconofs -= iconbutw;
- UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
- but = uiDefIconBut(node->block, UI_BTYPE_BUT_TOGGLE, B_REDR, ICON_NODETREE,
- iconofs, rct->ymax - NODE_DY, iconbutw, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_group_edit");
- UI_block_emboss_set(node->block, UI_EMBOSS);
- }
-
- /* title */
- if (node->flag & SELECT) {
- UI_GetThemeColor4fv(TH_SELECT, color);
- }
- else {
- UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color);
- }
-
- /* open/close entirely? */
- {
- uiBut *but;
- int but_size = U.widget_unit * 0.8f;
- /* XXX button uses a custom triangle draw below, so make it invisible without icon */
- UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
- but = uiDefBut(node->block, UI_BTYPE_BUT_TOGGLE, B_REDR, "",
- rct->xmin + 0.35f * U.widget_unit, rct->ymax - NODE_DY / 2.2f - but_size / 2,
- but_size, but_size, NULL, 0, 0, 0, 0, "");
- UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_hide_toggle");
- UI_block_emboss_set(node->block, UI_EMBOSS);
-
- UI_GetThemeColor4fv(TH_TEXT, color);
- /* custom draw function for this button */
- UI_draw_icon_tri(rct->xmin + 0.65f * U.widget_unit, rct->ymax - NODE_DY / 2.2f, 'v', color);
- }
-
- nodeLabel(ntree, node, showname, sizeof(showname));
-
- uiBut *but = uiDefBut(node->block, UI_BTYPE_LABEL, 0, showname,
- (int)(rct->xmin + (NODE_MARGIN_X)), (int)(rct->ymax - NODE_DY),
- (short)(iconofs - rct->xmin - 18.0f), (short)NODE_DY,
- NULL, 0, 0, 0, 0, "");
- if (node->flag & NODE_MUTED) {
- UI_but_flag_enable(but, UI_BUT_INACTIVE);
- }
-
- /* body */
- if (!nodeIsRegistered(node)) {
- /* use warning color to indicate undefined types */
- UI_GetThemeColor4fv(TH_REDALERT, color);
-
- }
- else if (node->flag & NODE_MUTED) {
- /* Muted nodes are semi-transparent and colorless. */
- UI_GetThemeColor4fv(TH_NODE, color);
- }
- else if (node->flag & NODE_CUSTOM_COLOR) {
- rgba_float_args_set(color, node->color[0], node->color[1], node->color[2], 1.0f);
- }
- else {
- UI_GetThemeColor4fv(TH_NODE, color);
- }
-
- if (node->flag & NODE_MUTED) {
- color[3] = 0.5f;
- }
-
- UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT);
- UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax - NODE_DY, BASIS_RAD, color);
-
- /* outline active and selected emphasis */
- if (node->flag & SELECT) {
- UI_GetThemeColorShadeAlpha4fv((node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color);
-
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color);
- }
-
- /* disable lines */
- if (node->flag & NODE_MUTED) {
- node_draw_mute_line(v2d, snode, node);
- }
-
- node_draw_sockets(v2d, C, ntree, node, true, false);
-
- /* preview */
- if (node->flag & NODE_PREVIEW && previews) {
- bNodePreview *preview = BKE_node_instance_hash_lookup(previews, key);
- if (preview && (preview->xsize && preview->ysize)) {
- if (preview->rect && !BLI_rctf_is_empty(&node->prvr)) {
- node_draw_preview(preview, &node->prvr);
- }
- }
- }
-
- UI_ThemeClearColor(color_id);
-
- UI_block_end(C, node->block);
- UI_block_draw(C, node->block);
- node->block = NULL;
+ bNodeInstanceHash *previews = CTX_data_pointer_get(C, "node_previews").data;
+ rctf *rct = &node->totr;
+ float iconofs;
+ /* float socket_size = NODE_SOCKSIZE*U.dpi/72; */ /* UNUSED */
+ float iconbutw = 0.8f * UI_UNIT_X;
+ int color_id = node_get_colorid(node);
+ float color[4];
+ char showname[128]; /* 128 used below */
+ View2D *v2d = &ar->v2d;
+
+ /* skip if out of view */
+ if (BLI_rctf_isect(&node->totr, &v2d->cur, NULL) == false) {
+ UI_block_end(C, node->block);
+ node->block = NULL;
+ return;
+ }
+
+ /* shadow */
+ node_draw_shadow(snode, node, BASIS_RAD, 1.0f);
+
+ if (node->flag & NODE_MUTED) {
+ /* Muted nodes are semi-transparent and colorless. */
+ UI_GetThemeColor3fv(TH_NODE, color);
+ color[3] = 0.25f;
+ }
+ else {
+ /* Opaque headers for regular nodes. */
+ UI_GetThemeColor3fv(color_id, color);
+ color[3] = 1.0f;
+ }
+
+ GPU_line_width(1.0f);
+
+ UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
+ UI_draw_roundbox_aa(
+ true, rct->xmin, rct->ymax - NODE_DY, rct->xmax, rct->ymax, BASIS_RAD, color);
+
+ /* show/hide icons */
+ iconofs = rct->xmax - 0.35f * U.widget_unit;
+
+ /* preview */
+ if (node->typeinfo->flag & NODE_PREVIEW) {
+ uiBut *but;
+ iconofs -= iconbutw;
+ UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
+ but = uiDefIconBut(node->block,
+ UI_BTYPE_BUT_TOGGLE,
+ B_REDR,
+ ICON_MATERIAL,
+ iconofs,
+ rct->ymax - NODE_DY,
+ iconbutw,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_preview_toggle");
+ /* XXX this does not work when node is activated and the operator called right afterwards,
+ * since active ID is not updated yet (needs to process the notifier).
+ * This can only work as visual indicator!
+ */
+ // if (!(node->flag & (NODE_ACTIVE_ID|NODE_DO_OUTPUT)))
+ // UI_but_flag_enable(but, UI_BUT_DISABLED);
+ UI_block_emboss_set(node->block, UI_EMBOSS);
+ }
+ /* group edit */
+ if (node->type == NODE_GROUP) {
+ uiBut *but;
+ iconofs -= iconbutw;
+ UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
+ but = uiDefIconBut(node->block,
+ UI_BTYPE_BUT_TOGGLE,
+ B_REDR,
+ ICON_NODETREE,
+ iconofs,
+ rct->ymax - NODE_DY,
+ iconbutw,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_group_edit");
+ UI_block_emboss_set(node->block, UI_EMBOSS);
+ }
+
+ /* title */
+ if (node->flag & SELECT) {
+ UI_GetThemeColor4fv(TH_SELECT, color);
+ }
+ else {
+ UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color);
+ }
+
+ /* open/close entirely? */
+ {
+ uiBut *but;
+ int but_size = U.widget_unit * 0.8f;
+ /* XXX button uses a custom triangle draw below, so make it invisible without icon */
+ UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
+ but = uiDefBut(node->block,
+ UI_BTYPE_BUT_TOGGLE,
+ B_REDR,
+ "",
+ rct->xmin + 0.35f * U.widget_unit,
+ rct->ymax - NODE_DY / 2.2f - but_size / 2,
+ but_size,
+ but_size,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_hide_toggle");
+ UI_block_emboss_set(node->block, UI_EMBOSS);
+
+ UI_GetThemeColor4fv(TH_TEXT, color);
+ /* custom draw function for this button */
+ UI_draw_icon_tri(rct->xmin + 0.65f * U.widget_unit, rct->ymax - NODE_DY / 2.2f, 'v', color);
+ }
+
+ nodeLabel(ntree, node, showname, sizeof(showname));
+
+ uiBut *but = uiDefBut(node->block,
+ UI_BTYPE_LABEL,
+ 0,
+ showname,
+ (int)(rct->xmin + (NODE_MARGIN_X)),
+ (int)(rct->ymax - NODE_DY),
+ (short)(iconofs - rct->xmin - 18.0f),
+ (short)NODE_DY,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ if (node->flag & NODE_MUTED) {
+ UI_but_flag_enable(but, UI_BUT_INACTIVE);
+ }
+
+ /* body */
+ if (!nodeIsRegistered(node)) {
+ /* use warning color to indicate undefined types */
+ UI_GetThemeColor4fv(TH_REDALERT, color);
+ }
+ else if (node->flag & NODE_MUTED) {
+ /* Muted nodes are semi-transparent and colorless. */
+ UI_GetThemeColor4fv(TH_NODE, color);
+ }
+ else if (node->flag & NODE_CUSTOM_COLOR) {
+ rgba_float_args_set(color, node->color[0], node->color[1], node->color[2], 1.0f);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_NODE, color);
+ }
+
+ if (node->flag & NODE_MUTED) {
+ color[3] = 0.5f;
+ }
+
+ UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT);
+ UI_draw_roundbox_aa(
+ true, rct->xmin, rct->ymin, rct->xmax, rct->ymax - NODE_DY, BASIS_RAD, color);
+
+ /* outline active and selected emphasis */
+ if (node->flag & SELECT) {
+ UI_GetThemeColorShadeAlpha4fv(
+ (node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color);
+
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color);
+ }
+
+ /* disable lines */
+ if (node->flag & NODE_MUTED) {
+ node_draw_mute_line(v2d, snode, node);
+ }
+
+ node_draw_sockets(v2d, C, ntree, node, true, false);
+
+ /* preview */
+ if (node->flag & NODE_PREVIEW && previews) {
+ bNodePreview *preview = BKE_node_instance_hash_lookup(previews, key);
+ if (preview && (preview->xsize && preview->ysize)) {
+ if (preview->rect && !BLI_rctf_is_empty(&node->prvr)) {
+ node_draw_preview(preview, &node->prvr);
+ }
+ }
+ }
+
+ UI_ThemeClearColor(color_id);
+
+ UI_block_end(C, node->block);
+ UI_block_draw(C, node->block);
+ node->block = NULL;
}
-static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key))
+static void node_draw_hidden(const bContext *C,
+ ARegion *ar,
+ SpaceNode *snode,
+ bNodeTree *ntree,
+ bNode *node,
+ bNodeInstanceKey UNUSED(key))
{
- rctf *rct = &node->totr;
- float dx, centy = BLI_rctf_cent_y(rct);
- float hiddenrad = BLI_rctf_size_y(rct) / 2.0f;
- int color_id = node_get_colorid(node);
- float color[4];
- char showname[128]; /* 128 is used below */
- View2D *v2d = &ar->v2d;
- float scale;
-
- UI_view2d_scale_get(v2d, &scale, NULL);
-
- /* shadow */
- node_draw_shadow(snode, node, hiddenrad, 1.0f);
-
- /* body */
- if (node->flag & NODE_MUTED) {
- /* Muted nodes are semi-transparent and colorless. */
- UI_GetThemeColor4fv(TH_NODE, color);
- color[3] = 0.25f;
- }
- else {
- UI_GetThemeColor4fv(color_id, color);
- }
-
- UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad, color);
-
- /* outline active and selected emphasis */
- if (node->flag & SELECT) {
- UI_GetThemeColorShadeAlpha4fv((node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color);
-
- UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad, color);
- }
-
- /* custom color inline */
- if (node->flag & NODE_CUSTOM_COLOR) {
- 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);
-
- GPU_line_smooth(false);
- GPU_blend(false);
- }
-
- /* title */
- if (node->flag & SELECT) {
- UI_GetThemeColor4fv(TH_SELECT, color);
- }
- else {
- UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color);
- }
-
- /* open entirely icon */
- {
- uiBut *but;
- int but_size = U.widget_unit * 0.8f;
- /* XXX button uses a custom triangle draw below, so make it invisible without icon */
- UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
- but = uiDefBut(node->block, UI_BTYPE_BUT_TOGGLE, B_REDR, "",
- rct->xmin + 0.35f * U.widget_unit, centy - but_size / 2,
- but_size, but_size, NULL, 0, 0, 0, 0, "");
- UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_hide_toggle");
- UI_block_emboss_set(node->block, UI_EMBOSS);
-
- UI_GetThemeColor4fv(TH_TEXT, color);
- /* custom draw function for this button */
- UI_draw_icon_tri(rct->xmin + 0.65f * U.widget_unit, centy, 'h', color);
- }
-
- /* disable lines */
- if (node->flag & NODE_MUTED) {
- node_draw_mute_line(&ar->v2d, snode, node);
- }
-
- nodeLabel(ntree, node, showname, sizeof(showname));
-
- /* XXX - don't print into self! */
- //if (node->flag & NODE_MUTED)
- // BLI_snprintf(showname, sizeof(showname), "[%s]", showname);
-
- uiBut *but = uiDefBut(node->block, UI_BTYPE_LABEL, 0, showname,
- round_fl_to_int(rct->xmin + NODE_MARGIN_X), round_fl_to_int(centy - NODE_DY * 0.5f),
- (short)(BLI_rctf_size_x(rct) - 18.0f - 12.0f), (short)NODE_DY,
- NULL, 0, 0, 0, 0, "");
- if (node->flag & NODE_MUTED) {
- UI_but_flag_enable(but, UI_BUT_INACTIVE);
- }
-
- /* scale widget thing */
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- immUniformThemeColorShade(color_id, -10);
- dx = 10.0f;
-
- immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, rct->xmax - dx, centy - 4.0f);
- immVertex2f(pos, rct->xmax - dx, centy + 4.0f);
-
- immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f);
- immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f);
- immEnd();
-
- immUniformThemeColorShade(color_id, 30);
- dx -= snode->aspect;
-
- immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, rct->xmax - dx, centy - 4.0f);
- immVertex2f(pos, rct->xmax - dx, centy + 4.0f);
-
- immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f);
- immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f);
- immEnd();
-
- immUnbindProgram();
-
- node_draw_sockets(v2d, C, ntree, node, true, false);
-
- UI_block_end(C, node->block);
- UI_block_draw(C, node->block);
- node->block = NULL;
+ rctf *rct = &node->totr;
+ float dx, centy = BLI_rctf_cent_y(rct);
+ float hiddenrad = BLI_rctf_size_y(rct) / 2.0f;
+ int color_id = node_get_colorid(node);
+ float color[4];
+ char showname[128]; /* 128 is used below */
+ View2D *v2d = &ar->v2d;
+ float scale;
+
+ UI_view2d_scale_get(v2d, &scale, NULL);
+
+ /* shadow */
+ node_draw_shadow(snode, node, hiddenrad, 1.0f);
+
+ /* body */
+ if (node->flag & NODE_MUTED) {
+ /* Muted nodes are semi-transparent and colorless. */
+ UI_GetThemeColor4fv(TH_NODE, color);
+ color[3] = 0.25f;
+ }
+ else {
+ UI_GetThemeColor4fv(color_id, color);
+ }
+
+ UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad, color);
+
+ /* outline active and selected emphasis */
+ if (node->flag & SELECT) {
+ UI_GetThemeColorShadeAlpha4fv(
+ (node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color);
+
+ UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad, color);
+ }
+
+ /* custom color inline */
+ if (node->flag & NODE_CUSTOM_COLOR) {
+ 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);
+
+ GPU_line_smooth(false);
+ GPU_blend(false);
+ }
+
+ /* title */
+ if (node->flag & SELECT) {
+ UI_GetThemeColor4fv(TH_SELECT, color);
+ }
+ else {
+ UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color);
+ }
+
+ /* open entirely icon */
+ {
+ uiBut *but;
+ int but_size = U.widget_unit * 0.8f;
+ /* XXX button uses a custom triangle draw below, so make it invisible without icon */
+ UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
+ but = uiDefBut(node->block,
+ UI_BTYPE_BUT_TOGGLE,
+ B_REDR,
+ "",
+ rct->xmin + 0.35f * U.widget_unit,
+ centy - but_size / 2,
+ but_size,
+ but_size,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_hide_toggle");
+ UI_block_emboss_set(node->block, UI_EMBOSS);
+
+ UI_GetThemeColor4fv(TH_TEXT, color);
+ /* custom draw function for this button */
+ UI_draw_icon_tri(rct->xmin + 0.65f * U.widget_unit, centy, 'h', color);
+ }
+
+ /* disable lines */
+ if (node->flag & NODE_MUTED) {
+ node_draw_mute_line(&ar->v2d, snode, node);
+ }
+
+ nodeLabel(ntree, node, showname, sizeof(showname));
+
+ /* XXX - don't print into self! */
+ //if (node->flag & NODE_MUTED)
+ // BLI_snprintf(showname, sizeof(showname), "[%s]", showname);
+
+ uiBut *but = uiDefBut(node->block,
+ UI_BTYPE_LABEL,
+ 0,
+ showname,
+ round_fl_to_int(rct->xmin + NODE_MARGIN_X),
+ round_fl_to_int(centy - NODE_DY * 0.5f),
+ (short)(BLI_rctf_size_x(rct) - 18.0f - 12.0f),
+ (short)NODE_DY,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ if (node->flag & NODE_MUTED) {
+ UI_but_flag_enable(but, UI_BUT_INACTIVE);
+ }
+
+ /* scale widget thing */
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformThemeColorShade(color_id, -10);
+ dx = 10.0f;
+
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex2f(pos, rct->xmax - dx, centy - 4.0f);
+ immVertex2f(pos, rct->xmax - dx, centy + 4.0f);
+
+ immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f);
+ immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f);
+ immEnd();
+
+ immUniformThemeColorShade(color_id, 30);
+ dx -= snode->aspect;
+
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex2f(pos, rct->xmax - dx, centy - 4.0f);
+ immVertex2f(pos, rct->xmax - dx, centy + 4.0f);
+
+ immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f);
+ immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f);
+ immEnd();
+
+ immUnbindProgram();
+
+ node_draw_sockets(v2d, C, ntree, node, true, false);
+
+ UI_block_end(C, node->block);
+ UI_block_draw(C, node->block);
+ node->block = NULL;
}
int node_get_resize_cursor(int directions)
{
- if (directions == 0) {
- return CURSOR_STD;
- }
- else if ((directions & ~(NODE_RESIZE_TOP | NODE_RESIZE_BOTTOM)) == 0) {
- return CURSOR_Y_MOVE;
- }
- else if ((directions & ~(NODE_RESIZE_RIGHT | NODE_RESIZE_LEFT)) == 0) {
- return CURSOR_X_MOVE;
- }
- else {
- return CURSOR_EDIT;
- }
+ if (directions == 0) {
+ return CURSOR_STD;
+ }
+ else if ((directions & ~(NODE_RESIZE_TOP | NODE_RESIZE_BOTTOM)) == 0) {
+ return CURSOR_Y_MOVE;
+ }
+ else if ((directions & ~(NODE_RESIZE_RIGHT | NODE_RESIZE_LEFT)) == 0) {
+ return CURSOR_X_MOVE;
+ }
+ else {
+ return CURSOR_EDIT;
+ }
}
void node_set_cursor(wmWindow *win, SpaceNode *snode, float cursor[2])
{
- bNodeTree *ntree = snode->edittree;
- bNode *node;
- bNodeSocket *sock;
- int wmcursor = CURSOR_STD;
-
- if (ntree) {
- if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN | SOCK_OUT)) {
- /* pass */
- }
- else {
- /* check nodes front to back */
- for (node = ntree->nodes.last; node; node = node->prev) {
- if (BLI_rctf_isect_pt(&node->totr, cursor[0], cursor[1])) {
- break; /* first hit on node stops */
- }
- }
- if (node) {
- int dir = node->typeinfo->resize_area_func(node, cursor[0], cursor[1]);
- wmcursor = node_get_resize_cursor(dir);
- }
- }
- }
-
- WM_cursor_set(win, wmcursor);
+ bNodeTree *ntree = snode->edittree;
+ bNode *node;
+ bNodeSocket *sock;
+ int wmcursor = CURSOR_STD;
+
+ if (ntree) {
+ if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN | SOCK_OUT)) {
+ /* pass */
+ }
+ else {
+ /* check nodes front to back */
+ for (node = ntree->nodes.last; node; node = node->prev) {
+ if (BLI_rctf_isect_pt(&node->totr, cursor[0], cursor[1])) {
+ break; /* first hit on node stops */
+ }
+ }
+ if (node) {
+ int dir = node->typeinfo->resize_area_func(node, cursor[0], cursor[1]);
+ wmcursor = node_get_resize_cursor(dir);
+ }
+ }
+ }
+
+ WM_cursor_set(win, wmcursor);
}
-void node_draw_default(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
+void node_draw_default(const bContext *C,
+ ARegion *ar,
+ SpaceNode *snode,
+ bNodeTree *ntree,
+ bNode *node,
+ bNodeInstanceKey key)
{
- if (node->flag & NODE_HIDDEN) {
- node_draw_hidden(C, ar, snode, ntree, node, key);
- }
- else {
- node_draw_basis(C, ar, snode, ntree, node, key);
- }
+ if (node->flag & NODE_HIDDEN) {
+ node_draw_hidden(C, ar, snode, ntree, node, key);
+ }
+ else {
+ node_draw_basis(C, ar, snode, ntree, node, key);
+ }
}
static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
{
- if (node->typeinfo->draw_nodetype_prepare) {
- node->typeinfo->draw_nodetype_prepare(C, ntree, node);
- }
+ if (node->typeinfo->draw_nodetype_prepare) {
+ node->typeinfo->draw_nodetype_prepare(C, ntree, node);
+ }
}
void node_update_nodetree(const bContext *C, bNodeTree *ntree)
{
- bNode *node;
+ bNode *node;
- /* make sure socket "used" tags are correct, for displaying value buttons */
- ntreeTagUsedSockets(ntree);
+ /* make sure socket "used" tags are correct, for displaying value buttons */
+ ntreeTagUsedSockets(ntree);
- /* update nodes front to back, so children sizes get updated before parents */
- for (node = ntree->nodes.last; node; node = node->prev) {
- node_update(C, ntree, node);
- }
+ /* update nodes front to back, so children sizes get updated before parents */
+ for (node = ntree->nodes.last; node; node = node->prev) {
+ node_update(C, ntree, node);
+ }
}
-static void node_draw(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
+static void node_draw(const bContext *C,
+ ARegion *ar,
+ SpaceNode *snode,
+ bNodeTree *ntree,
+ bNode *node,
+ bNodeInstanceKey key)
{
- if (node->typeinfo->draw_nodetype) {
- node->typeinfo->draw_nodetype(C, ar, snode, ntree, node, key);
- }
+ if (node->typeinfo->draw_nodetype) {
+ node->typeinfo->draw_nodetype(C, ar, snode, ntree, node, key);
+ }
}
#define USE_DRAW_TOT_UPDATE
-void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNodeInstanceKey parent_key)
+void node_draw_nodetree(const bContext *C,
+ ARegion *ar,
+ SpaceNode *snode,
+ bNodeTree *ntree,
+ bNodeInstanceKey parent_key)
{
- bNode *node;
- bNodeLink *link;
- int a;
+ bNode *node;
+ bNodeLink *link;
+ int a;
- if (ntree == NULL) {
- return; /* groups... */
- }
+ if (ntree == NULL) {
+ return; /* groups... */
+ }
#ifdef USE_DRAW_TOT_UPDATE
- if (ntree->nodes.first) {
- BLI_rctf_init_minmax(&ar->v2d.tot);
- }
+ if (ntree->nodes.first) {
+ BLI_rctf_init_minmax(&ar->v2d.tot);
+ }
#endif
- /* draw background nodes, last nodes in front */
- for (a = 0, node = ntree->nodes.first; node; node = node->next, a++) {
- bNodeInstanceKey key;
+ /* draw background nodes, last nodes in front */
+ for (a = 0, node = ntree->nodes.first; node; node = node->next, a++) {
+ bNodeInstanceKey key;
#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);
+ /* 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);
#endif
- if (!(node->flag & NODE_BACKGROUND)) {
- continue;
- }
-
- 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 lines */
- GPU_blend(true);
- nodelink_batch_start(snode);
- for (link = ntree->links.first; link; link = link->next) {
- if (!nodeLinkIsHidden(link)) {
- node_draw_link(&ar->v2d, snode, link);
- }
- }
- nodelink_batch_end(snode);
- GPU_blend(false);
-
- /* draw foreground nodes, last nodes in front */
- for (a = 0, node = ntree->nodes.first; node; node = node->next, a++) {
- bNodeInstanceKey key;
- if (node->flag & NODE_BACKGROUND) {
- continue;
- }
-
- 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);
- }
+ if (!(node->flag & NODE_BACKGROUND)) {
+ continue;
+ }
+
+ 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 lines */
+ GPU_blend(true);
+ nodelink_batch_start(snode);
+ for (link = ntree->links.first; link; link = link->next) {
+ if (!nodeLinkIsHidden(link)) {
+ node_draw_link(&ar->v2d, snode, link);
+ }
+ }
+ nodelink_batch_end(snode);
+ GPU_blend(false);
+
+ /* draw foreground nodes, last nodes in front */
+ for (a = 0, node = ntree->nodes.first; node; node = node->next, a++) {
+ bNodeInstanceKey key;
+ if (node->flag & NODE_BACKGROUND) {
+ continue;
+ }
+
+ 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);
+ }
}
/* draw tree path info in lower left corner */
static void draw_tree_path(SpaceNode *snode)
{
- char info[256];
+ char info[256];
- ED_node_tree_path_get_fixedbuf(snode, info, sizeof(info));
+ ED_node_tree_path_get_fixedbuf(snode, info, sizeof(info));
- UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
- BLF_draw_default(1.5f * UI_UNIT_X, 1.5f * UI_UNIT_Y, 0.0f, info, sizeof(info));
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
+ 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])
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &ar->v2d;
- /* shift view to node tree center */
- UI_view2d_center_set(v2d, center[0], center[1]);
- UI_view2d_view_ortho(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;
- // XXX snode->curfont = uiSetCurFont_ext(snode->aspect);
+ /* aspect+font, set each time */
+ snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)ar->winx;
+ // XXX snode->curfont = uiSetCurFont_ext(snode->aspect);
}
-static void draw_nodetree(const bContext *C, ARegion *ar, bNodeTree *ntree, bNodeInstanceKey parent_key)
+static void draw_nodetree(const bContext *C,
+ ARegion *ar,
+ bNodeTree *ntree,
+ bNodeInstanceKey parent_key)
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
- node_uiblocks_init(C, ntree);
+ node_uiblocks_init(C, ntree);
- node_update_nodetree(C, ntree);
- node_draw_nodetree(C, ar, snode, ntree, parent_key);
+ node_update_nodetree(C, ntree);
+ node_draw_nodetree(C, ar, 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)
{
- View2D *v2d = &ar->v2d;
- rctf rect = v2d->cur;
- uiBlock *block;
- float color[4];
-
- /* shade node groups to separate them visually */
- GPU_blend(true);
-
- UI_GetThemeColorShadeAlpha4fv(TH_NODE_GROUP, 0, 0, color);
- UI_draw_roundbox_corner_set(UI_CNR_NONE);
- UI_draw_roundbox_4fv(true, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0, color);
- 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);
- 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);
+ View2D *v2d = &ar->v2d;
+ rctf rect = v2d->cur;
+ uiBlock *block;
+ float color[4];
+
+ /* shade node groups to separate them visually */
+ GPU_blend(true);
+
+ UI_GetThemeColorShadeAlpha4fv(TH_NODE_GROUP, 0, 0, color);
+ UI_draw_roundbox_corner_set(UI_CNR_NONE);
+ UI_draw_roundbox_4fv(true, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0, color);
+ 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);
+ 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)
{
- wmWindow *win = CTX_wm_window(C);
- View2DScrollers *scrollers;
- SpaceNode *snode = CTX_wm_space_node(C);
- View2D *v2d = &ar->v2d;
-
- UI_ThemeClearColor(TH_BACK);
- GPU_clear(GPU_COLOR_BIT);
-
- UI_view2d_view_ortho(v2d);
+ wmWindow *win = CTX_wm_window(C);
+ View2DScrollers *scrollers;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ View2D *v2d = &ar->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,
- &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);
-
- /* only set once */
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- /* nodes */
- snode_set_context(C);
-
- /* draw parent node trees */
- if (snode->treepath.last) {
- static const int max_depth = 2;
- bNodeTreePath *path;
- int depth, curdepth;
- float center[2];
- bNodeTree *ntree;
- bNodeLinkDrag *nldrag;
- LinkData *linkdata;
-
- path = snode->treepath.last;
-
- /* update tree path name (drawn in the bottom left) */
- ID *name_id = (path->nodetree && path->nodetree != snode->nodetree) ? &path->nodetree->id : snode->id;
-
- if (name_id && UNLIKELY(!STREQ(path->node_name, name_id->name + 2))) {
- BLI_strncpy(path->node_name, name_id->name + 2, sizeof(path->node_name));
- }
-
- /* current View2D center, will be set temporarily for parent node trees */
- UI_view2d_center_get(v2d, &center[0], &center[1]);
-
- /* store new view center in path and current edittree */
- copy_v2_v2(path->view_center, center);
- if (snode->edittree) {
- copy_v2_v2(snode->edittree->view_center, center);
- }
-
- depth = 0;
- while (path->prev && depth < max_depth) {
- path = path->prev;
- ++depth;
- }
-
- /* parent node trees in the background */
- for (curdepth = depth; curdepth > 0; path = path->next, --curdepth) {
- ntree = path->nodetree;
- if (ntree) {
- snode_setup_v2d(snode, ar, path->view_center);
-
- draw_nodetree(C, ar, ntree, path->parent_key);
-
- draw_group_overlay(C, ar);
- }
- }
-
- /* top-level edit tree */
- ntree = path->nodetree;
- if (ntree) {
- snode_setup_v2d(snode, ar, 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);
-
- /* backdrop */
- draw_nodespace_back_pix(C, ar, snode, path->parent_key);
-
- {
- float original_proj[4][4];
- GPU_matrix_projection_get(original_proj);
-
- GPU_matrix_push();
- GPU_matrix_identity_set();
-
- wmOrtho2_pixelspace(ar->winx, ar->winy);
-
- WM_gizmomap_draw(ar->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
-
- GPU_matrix_pop();
- GPU_matrix_projection_set(original_proj);
- }
-
- draw_nodetree(C, ar, ntree, path->parent_key);
- }
-
- /* temporary links */
- GPU_blend(true);
- GPU_line_smooth(true);
- for (nldrag = snode->linkdrag.first; nldrag; nldrag = nldrag->next) {
- for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
- node_draw_link(v2d, snode, (bNodeLink *)linkdata->data);
- }
- }
- GPU_line_smooth(false);
- GPU_blend(false);
-
- if (snode->flag & SNODE_SHOW_GPENCIL) {
- /* draw grease-pencil ('canvas' strokes) */
- ED_annotation_draw_view2d(C, true);
- }
- }
- else {
- /* default grid */
- UI_view2d_multi_grid_draw(v2d, TH_BACK, ED_node_grid_size(), NODE_GRID_STEPS, 2);
-
- /* backdrop */
- draw_nodespace_back_pix(C, ar, snode, NODE_INSTANCE_KEY_NONE);
- }
-
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
-
- /* reset view matrix */
- UI_view2d_view_restore(C);
-
- if (snode->treepath.last) {
- if (snode->flag & SNODE_SHOW_GPENCIL) {
- /* draw grease-pencil (screen strokes, and also paintbuffer) */
- ED_annotation_draw_view2d(C, false);
- }
- }
-
- /* tree path info */
- draw_tree_path(snode);
-
- /* scrollers */
- scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, 10, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
+ UI_ThemeClearColor(TH_BACK);
+ GPU_clear(GPU_COLOR_BIT);
+
+ 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,
+ &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);
+
+ /* only set once */
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ /* nodes */
+ snode_set_context(C);
+
+ /* draw parent node trees */
+ if (snode->treepath.last) {
+ static const int max_depth = 2;
+ bNodeTreePath *path;
+ int depth, curdepth;
+ float center[2];
+ bNodeTree *ntree;
+ bNodeLinkDrag *nldrag;
+ LinkData *linkdata;
+
+ path = snode->treepath.last;
+
+ /* update tree path name (drawn in the bottom left) */
+ ID *name_id = (path->nodetree && path->nodetree != snode->nodetree) ? &path->nodetree->id :
+ snode->id;
+
+ if (name_id && UNLIKELY(!STREQ(path->node_name, name_id->name + 2))) {
+ BLI_strncpy(path->node_name, name_id->name + 2, sizeof(path->node_name));
+ }
+
+ /* current View2D center, will be set temporarily for parent node trees */
+ UI_view2d_center_get(v2d, &center[0], &center[1]);
+
+ /* store new view center in path and current edittree */
+ copy_v2_v2(path->view_center, center);
+ if (snode->edittree) {
+ copy_v2_v2(snode->edittree->view_center, center);
+ }
+
+ depth = 0;
+ while (path->prev && depth < max_depth) {
+ path = path->prev;
+ ++depth;
+ }
+
+ /* parent node trees in the background */
+ for (curdepth = depth; curdepth > 0; path = path->next, --curdepth) {
+ ntree = path->nodetree;
+ if (ntree) {
+ snode_setup_v2d(snode, ar, path->view_center);
+
+ draw_nodetree(C, ar, ntree, path->parent_key);
+
+ draw_group_overlay(C, ar);
+ }
+ }
+
+ /* top-level edit tree */
+ ntree = path->nodetree;
+ if (ntree) {
+ snode_setup_v2d(snode, ar, 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);
+
+ /* backdrop */
+ draw_nodespace_back_pix(C, ar, snode, path->parent_key);
+
+ {
+ float original_proj[4][4];
+ GPU_matrix_projection_get(original_proj);
+
+ GPU_matrix_push();
+ GPU_matrix_identity_set();
+
+ wmOrtho2_pixelspace(ar->winx, ar->winy);
+
+ WM_gizmomap_draw(ar->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
+
+ GPU_matrix_pop();
+ GPU_matrix_projection_set(original_proj);
+ }
+
+ draw_nodetree(C, ar, ntree, path->parent_key);
+ }
+
+ /* temporary links */
+ GPU_blend(true);
+ GPU_line_smooth(true);
+ for (nldrag = snode->linkdrag.first; nldrag; nldrag = nldrag->next) {
+ for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
+ node_draw_link(v2d, snode, (bNodeLink *)linkdata->data);
+ }
+ }
+ GPU_line_smooth(false);
+ GPU_blend(false);
+
+ if (snode->flag & SNODE_SHOW_GPENCIL) {
+ /* draw grease-pencil ('canvas' strokes) */
+ ED_annotation_draw_view2d(C, true);
+ }
+ }
+ else {
+ /* default grid */
+ UI_view2d_multi_grid_draw(v2d, TH_BACK, ED_node_grid_size(), NODE_GRID_STEPS, 2);
+
+ /* backdrop */
+ draw_nodespace_back_pix(C, ar, snode, NODE_INSTANCE_KEY_NONE);
+ }
+
+ ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ if (snode->treepath.last) {
+ if (snode->flag & SNODE_SHOW_GPENCIL) {
+ /* draw grease-pencil (screen strokes, and also paintbuffer) */
+ ED_annotation_draw_view2d(C, false);
+ }
+ }
+
+ /* tree path info */
+ draw_tree_path(snode);
+
+ /* scrollers */
+ scrollers = UI_view2d_scrollers_calc(
+ C, v2d, NULL, 10, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
}
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 27efb6c9a10..84f512957c7 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -46,8 +46,7 @@
#include "RE_engine.h"
#include "RE_pipeline.h"
-
-#include "ED_node.h" /* own include */
+#include "ED_node.h" /* own include */
#include "ED_select_utils.h"
#include "ED_screen.h"
#include "ED_render.h"
@@ -65,199 +64,210 @@
#include "IMB_imbuf_types.h"
-#include "node_intern.h" /* own include */
+#include "node_intern.h" /* own include */
#include "NOD_composite.h"
#include "NOD_shader.h"
#include "NOD_texture.h"
-
#define USE_ESC_COMPO
/* ***************** composite job manager ********************** */
enum {
- COM_RECALC_COMPOSITE = 1,
- COM_RECALC_VIEWER = 2,
+ COM_RECALC_COMPOSITE = 1,
+ COM_RECALC_VIEWER = 2,
};
typedef struct CompoJob {
- Main *bmain;
- Scene *scene;
- bNodeTree *ntree;
- bNodeTree *localtree;
- const short *stop;
- short *do_update;
- float *progress;
- int recalc_flags;
+ Main *bmain;
+ Scene *scene;
+ bNodeTree *ntree;
+ bNodeTree *localtree;
+ const short *stop;
+ short *do_update;
+ float *progress;
+ int recalc_flags;
} CompoJob;
static void compo_tag_output_nodes(bNodeTree *nodetree, int recalc_flags)
{
- bNode *node;
-
- for (node = nodetree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_COMPOSITE) {
- if (recalc_flags & COM_RECALC_COMPOSITE) {
- node->flag |= NODE_DO_OUTPUT_RECALC;
- }
- }
- else if (node->type == CMP_NODE_VIEWER || node->type == CMP_NODE_SPLITVIEWER) {
- if (recalc_flags & COM_RECALC_VIEWER) {
- node->flag |= NODE_DO_OUTPUT_RECALC;
- }
- }
- else if (node->type == NODE_GROUP) {
- if (node->id) {
- compo_tag_output_nodes((bNodeTree *)node->id, recalc_flags);
- }
- }
- }
+ bNode *node;
+
+ for (node = nodetree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_COMPOSITE) {
+ if (recalc_flags & COM_RECALC_COMPOSITE) {
+ node->flag |= NODE_DO_OUTPUT_RECALC;
+ }
+ }
+ else if (node->type == CMP_NODE_VIEWER || node->type == CMP_NODE_SPLITVIEWER) {
+ if (recalc_flags & COM_RECALC_VIEWER) {
+ node->flag |= NODE_DO_OUTPUT_RECALC;
+ }
+ }
+ else if (node->type == NODE_GROUP) {
+ if (node->id) {
+ compo_tag_output_nodes((bNodeTree *)node->id, recalc_flags);
+ }
+ }
+ }
}
static int compo_get_recalc_flags(const bContext *C)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win;
- int recalc_flags = 0;
-
- for (win = wm->windows.first; win; win = win->next) {
- const bScreen *sc = WM_window_get_active_screen(win);
- ScrArea *sa;
-
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = sa->spacedata.first;
- if (sima->image) {
- if (sima->image->type == IMA_TYPE_R_RESULT) {
- recalc_flags |= COM_RECALC_COMPOSITE;
- }
- else if (sima->image->type == IMA_TYPE_COMPOSITE) {
- recalc_flags |= COM_RECALC_VIEWER;
- }
- }
- }
- else if (sa->spacetype == SPACE_NODE) {
- SpaceNode *snode = sa->spacedata.first;
- if (snode->flag & SNODE_BACKDRAW) {
- recalc_flags |= COM_RECALC_VIEWER;
- }
- }
- }
- }
-
- return recalc_flags;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win;
+ int recalc_flags = 0;
+
+ for (win = wm->windows.first; win; win = win->next) {
+ const bScreen *sc = WM_window_get_active_screen(win);
+ ScrArea *sa;
+
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ if (sa->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = sa->spacedata.first;
+ if (sima->image) {
+ if (sima->image->type == IMA_TYPE_R_RESULT) {
+ recalc_flags |= COM_RECALC_COMPOSITE;
+ }
+ else if (sima->image->type == IMA_TYPE_COMPOSITE) {
+ recalc_flags |= COM_RECALC_VIEWER;
+ }
+ }
+ }
+ else if (sa->spacetype == SPACE_NODE) {
+ SpaceNode *snode = sa->spacedata.first;
+ if (snode->flag & SNODE_BACKDRAW) {
+ recalc_flags |= COM_RECALC_VIEWER;
+ }
+ }
+ }
+ }
+
+ return recalc_flags;
}
/* called by compo, only to check job 'stop' value */
static int compo_breakjob(void *cjv)
{
- CompoJob *cj = cjv;
+ CompoJob *cj = cjv;
- /* without G.is_break 'ESC' wont quit - which annoys users */
- return (*(cj->stop)
+ /* without G.is_break 'ESC' wont quit - which annoys users */
+ return (*(cj->stop)
#ifdef USE_ESC_COMPO
- ||
- G.is_break
+ || G.is_break
#endif
- );
+ );
}
/* called by compo, wmJob sends notifier */
static void compo_statsdrawjob(void *cjv, const char *UNUSED(str))
{
- CompoJob *cj = cjv;
+ CompoJob *cj = cjv;
- *(cj->do_update) = true;
+ *(cj->do_update) = true;
}
/* called by compo, wmJob sends notifier */
static void compo_redrawjob(void *cjv)
{
- CompoJob *cj = cjv;
+ CompoJob *cj = cjv;
- *(cj->do_update) = true;
+ *(cj->do_update) = true;
}
static void compo_freejob(void *cjv)
{
- CompoJob *cj = cjv;
+ CompoJob *cj = cjv;
- if (cj->localtree) {
- ntreeLocalMerge(cj->bmain, cj->localtree, cj->ntree);
- }
- MEM_freeN(cj);
+ if (cj->localtree) {
+ ntreeLocalMerge(cj->bmain, cj->localtree, cj->ntree);
+ }
+ MEM_freeN(cj);
}
/* only now we copy the nodetree, so adding many jobs while
* sliding buttons doesn't frustrate */
static void compo_initjob(void *cjv)
{
- CompoJob *cj = cjv;
+ CompoJob *cj = cjv;
- cj->localtree = ntreeLocalize(cj->ntree);
+ cj->localtree = ntreeLocalize(cj->ntree);
- if (cj->recalc_flags) {
- compo_tag_output_nodes(cj->localtree, cj->recalc_flags);
- }
+ if (cj->recalc_flags) {
+ compo_tag_output_nodes(cj->localtree, cj->recalc_flags);
+ }
}
/* called before redraw notifiers, it moves finished previews over */
static void compo_updatejob(void *UNUSED(cjv))
{
- WM_main_add_notifier(NC_SCENE | ND_COMPO_RESULT, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_COMPO_RESULT, NULL);
}
static void compo_progressjob(void *cjv, float progress)
{
- CompoJob *cj = cjv;
+ CompoJob *cj = cjv;
- *(cj->progress) = progress;
+ *(cj->progress) = progress;
}
/* only this runs inside thread */
static void compo_startjob(void *cjv, short *stop, short *do_update, float *progress)
{
- CompoJob *cj = cjv;
- bNodeTree *ntree = cj->localtree;
- Scene *scene = cj->scene;
- SceneRenderView *srv;
-
- if (scene->use_nodes == false) {
- return;
- }
-
- cj->stop = stop;
- cj->do_update = do_update;
- cj->progress = progress;
-
- ntree->test_break = compo_breakjob;
- ntree->tbh = cj;
- ntree->stats_draw = compo_statsdrawjob;
- ntree->sdh = cj;
- ntree->progress = compo_progressjob;
- ntree->prh = cj;
- ntree->update_draw = compo_redrawjob;
- ntree->udh = cj;
-
- // XXX BIF_store_spare();
- /* 1 is do_previews */
-
- if ((cj->scene->r.scemode & R_MULTIVIEW) == 0) {
- ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, &scene->view_settings, &scene->display_settings, "");
- }
- else {
- for (srv = scene->r.views.first; srv; srv = srv->next) {
- if (BKE_scene_multiview_is_render_view_active(&scene->r, srv) == false) {
- continue;
- }
- ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, &scene->view_settings, &scene->display_settings, srv->name);
- }
- }
-
- ntree->test_break = NULL;
- ntree->stats_draw = NULL;
- ntree->progress = NULL;
-
+ CompoJob *cj = cjv;
+ bNodeTree *ntree = cj->localtree;
+ Scene *scene = cj->scene;
+ SceneRenderView *srv;
+
+ if (scene->use_nodes == false) {
+ return;
+ }
+
+ cj->stop = stop;
+ cj->do_update = do_update;
+ cj->progress = progress;
+
+ ntree->test_break = compo_breakjob;
+ ntree->tbh = cj;
+ ntree->stats_draw = compo_statsdrawjob;
+ ntree->sdh = cj;
+ ntree->progress = compo_progressjob;
+ ntree->prh = cj;
+ ntree->update_draw = compo_redrawjob;
+ ntree->udh = cj;
+
+ // XXX BIF_store_spare();
+ /* 1 is do_previews */
+
+ if ((cj->scene->r.scemode & R_MULTIVIEW) == 0) {
+ ntreeCompositExecTree(cj->scene,
+ ntree,
+ &cj->scene->r,
+ false,
+ true,
+ &scene->view_settings,
+ &scene->display_settings,
+ "");
+ }
+ else {
+ for (srv = scene->r.views.first; srv; srv = srv->next) {
+ if (BKE_scene_multiview_is_render_view_active(&scene->r, srv) == false) {
+ continue;
+ }
+ ntreeCompositExecTree(cj->scene,
+ ntree,
+ &cj->scene->r,
+ false,
+ true,
+ &scene->view_settings,
+ &scene->display_settings,
+ srv->name);
+ }
+ }
+
+ ntree->test_break = NULL;
+ ntree->stats_draw = NULL;
+ ntree->progress = NULL;
}
/**
@@ -269,38 +279,43 @@ static void compo_startjob(void *cjv, short *stop, short *do_update, float *prog
*/
void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene *scene_owner)
{
- wmJob *wm_job;
- CompoJob *cj;
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
+ wmJob *wm_job;
+ CompoJob *cj;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
- /* to fix bug: [#32272] */
- if (G.is_rendering) {
- return;
- }
+ /* to fix bug: [#32272] */
+ if (G.is_rendering) {
+ return;
+ }
#ifdef USE_ESC_COMPO
- G.is_break = false;
+ G.is_break = false;
#endif
- BKE_image_backup_render(scene, BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"), false);
+ BKE_image_backup_render(
+ scene, BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"), false);
- wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene_owner, "Compositing",
- WM_JOB_EXCL_RENDER | WM_JOB_PROGRESS, WM_JOB_TYPE_COMPOSITE);
- cj = MEM_callocN(sizeof(CompoJob), "compo job");
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ scene_owner,
+ "Compositing",
+ WM_JOB_EXCL_RENDER | WM_JOB_PROGRESS,
+ WM_JOB_TYPE_COMPOSITE);
+ cj = MEM_callocN(sizeof(CompoJob), "compo job");
- /* customdata for preview thread */
- cj->bmain = bmain;
- cj->scene = scene;
- cj->ntree = nodetree;
- cj->recalc_flags = compo_get_recalc_flags(C);
+ /* customdata for preview thread */
+ cj->bmain = bmain;
+ cj->scene = scene;
+ cj->ntree = nodetree;
+ cj->recalc_flags = compo_get_recalc_flags(C);
- /* setup job */
- WM_jobs_customdata_set(wm_job, cj, compo_freejob);
- WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_COMPO_RESULT, NC_SCENE | ND_COMPO_RESULT);
- WM_jobs_callbacks(wm_job, compo_startjob, compo_initjob, compo_updatejob, NULL);
+ /* setup job */
+ WM_jobs_customdata_set(wm_job, cj, compo_freejob);
+ WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_COMPO_RESULT, NC_SCENE | ND_COMPO_RESULT);
+ WM_jobs_callbacks(wm_job, compo_startjob, compo_initjob, compo_updatejob, NULL);
- WM_jobs_start(CTX_wm_manager(C), wm_job);
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
}
/* ***************************************** */
@@ -308,447 +323,449 @@ void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene
/* operator poll callback */
bool composite_node_active(bContext *C)
{
- if (ED_operator_node_active(C)) {
- SpaceNode *snode = CTX_wm_space_node(C);
- if (ED_node_is_compositor(snode)) {
- return 1;
- }
- }
- return 0;
+ if (ED_operator_node_active(C)) {
+ SpaceNode *snode = CTX_wm_space_node(C);
+ if (ED_node_is_compositor(snode)) {
+ return 1;
+ }
+ }
+ return 0;
}
/* operator poll callback */
bool composite_node_editable(bContext *C)
{
- if (ED_operator_node_editable(C)) {
- SpaceNode *snode = CTX_wm_space_node(C);
- if (ED_node_is_compositor(snode)) {
- return 1;
- }
- }
- return 0;
+ if (ED_operator_node_editable(C)) {
+ SpaceNode *snode = CTX_wm_space_node(C);
+ if (ED_node_is_compositor(snode)) {
+ return 1;
+ }
+ }
+ return 0;
}
void snode_dag_update(bContext *C, SpaceNode *snode)
{
- Main *bmain = CTX_data_main(C);
+ Main *bmain = CTX_data_main(C);
- /* for groups, update all ID's using this */
- if (snode->edittree != snode->nodetree) {
- FOREACH_NODETREE_BEGIN(bmain, tntree, id) {
- if (ntreeHasTree(tntree, snode->edittree)) {
- DEG_id_tag_update(id, 0);
- }
- } FOREACH_NODETREE_END;
- }
+ /* for groups, update all ID's using this */
+ if (snode->edittree != snode->nodetree) {
+ FOREACH_NODETREE_BEGIN (bmain, tntree, id) {
+ if (ntreeHasTree(tntree, snode->edittree)) {
+ DEG_id_tag_update(id, 0);
+ }
+ }
+ FOREACH_NODETREE_END;
+ }
- DEG_id_tag_update(snode->id, 0);
+ DEG_id_tag_update(snode->id, 0);
}
void snode_notify(bContext *C, SpaceNode *snode)
{
- ID *id = snode->id;
-
- WM_event_add_notifier(C, NC_NODE | NA_EDITED, NULL);
-
- if (ED_node_is_shader(snode)) {
- if (GS(id->name) == ID_MA) {
- WM_main_add_notifier(NC_MATERIAL | ND_SHADING, id);
- }
- else if (GS(id->name) == ID_LA) {
- WM_main_add_notifier(NC_LAMP | ND_LIGHTING, id);
- }
- else if (GS(id->name) == ID_WO) {
- WM_main_add_notifier(NC_WORLD | ND_WORLD, id);
- }
- }
- else if (ED_node_is_compositor(snode)) {
- WM_event_add_notifier(C, NC_SCENE | ND_NODES, id);
- }
- else if (ED_node_is_texture(snode)) {
- WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, id);
- }
+ ID *id = snode->id;
+
+ WM_event_add_notifier(C, NC_NODE | NA_EDITED, NULL);
+
+ if (ED_node_is_shader(snode)) {
+ if (GS(id->name) == ID_MA) {
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING, id);
+ }
+ else if (GS(id->name) == ID_LA) {
+ WM_main_add_notifier(NC_LAMP | ND_LIGHTING, id);
+ }
+ else if (GS(id->name) == ID_WO) {
+ WM_main_add_notifier(NC_WORLD | ND_WORLD, id);
+ }
+ }
+ else if (ED_node_is_compositor(snode)) {
+ WM_event_add_notifier(C, NC_SCENE | ND_NODES, id);
+ }
+ else if (ED_node_is_texture(snode)) {
+ WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, id);
+ }
}
void ED_node_set_tree_type(SpaceNode *snode, bNodeTreeType *typeinfo)
{
- if (typeinfo) {
- BLI_strncpy(snode->tree_idname, typeinfo->idname, sizeof(snode->tree_idname));
- }
- else {
- snode->tree_idname[0] = '\0';
- }
+ if (typeinfo) {
+ BLI_strncpy(snode->tree_idname, typeinfo->idname, sizeof(snode->tree_idname));
+ }
+ else {
+ snode->tree_idname[0] = '\0';
+ }
}
bool ED_node_is_compositor(struct SpaceNode *snode)
{
- return STREQ(snode->tree_idname, ntreeType_Composite->idname);
+ return STREQ(snode->tree_idname, ntreeType_Composite->idname);
}
bool ED_node_is_shader(struct SpaceNode *snode)
{
- return STREQ(snode->tree_idname, ntreeType_Shader->idname);
+ return STREQ(snode->tree_idname, ntreeType_Shader->idname);
}
bool ED_node_is_texture(struct SpaceNode *snode)
{
- return STREQ(snode->tree_idname, ntreeType_Texture->idname);
+ return STREQ(snode->tree_idname, ntreeType_Texture->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;
-
- output_type = SH_NODE_OUTPUT_MATERIAL;
- shader_type = SH_NODE_BSDF_PRINCIPLED;
-
- copy_v3_v3(color, &ma->r);
- strength = 0.0f;
- break;
- }
- 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;
- }
- case ID_LA:
- {
- Light *la = (Light *)id;
- la->nodetree = ntree;
-
- output_type = SH_NODE_OUTPUT_LIGHT;
- shader_type = SH_NODE_EMISSION;
-
- copy_v3_v3(color, &la->r);
- if (la->type == LA_LOCAL || la->type == LA_SPOT || la->type == LA_AREA) {
- strength = 100.0f;
- }
- else {
- strength = 1.0f;
- }
- break;
- }
- default:
- printf("ED_node_shader_default called on wrong ID type.\n");
- return;
- }
-
- out = nodeAddStaticNode(C, ntree, output_type);
- out->locx = 300.0f; out->locy = 300.0f;
-
- in = nodeAddStaticNode(C, ntree, shader_type);
- in->locx = 10.0f; in->locy = 300.0f;
- nodeSetActive(ntree, in);
-
- /* 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);
-
- RNA_float_set_array(&sockptr, "default_value", color);
-
- if (strength != 0.0f) {
- sock = in->inputs.last;
- RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr);
- RNA_float_set(&sockptr, "default_value", strength);
- }
-
- ntreeUpdateTree(CTX_data_main(C), ntree);
+ 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;
+
+ output_type = SH_NODE_OUTPUT_MATERIAL;
+ shader_type = SH_NODE_BSDF_PRINCIPLED;
+
+ copy_v3_v3(color, &ma->r);
+ strength = 0.0f;
+ break;
+ }
+ 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;
+ }
+ case ID_LA: {
+ Light *la = (Light *)id;
+ la->nodetree = ntree;
+
+ output_type = SH_NODE_OUTPUT_LIGHT;
+ shader_type = SH_NODE_EMISSION;
+
+ copy_v3_v3(color, &la->r);
+ if (la->type == LA_LOCAL || la->type == LA_SPOT || la->type == LA_AREA) {
+ strength = 100.0f;
+ }
+ else {
+ strength = 1.0f;
+ }
+ break;
+ }
+ default:
+ printf("ED_node_shader_default called on wrong ID type.\n");
+ return;
+ }
+
+ out = nodeAddStaticNode(C, ntree, output_type);
+ out->locx = 300.0f;
+ out->locy = 300.0f;
+
+ in = nodeAddStaticNode(C, ntree, shader_type);
+ in->locx = 10.0f;
+ in->locy = 300.0f;
+ nodeSetActive(ntree, in);
+
+ /* 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);
+
+ RNA_float_set_array(&sockptr, "default_value", color);
+
+ if (strength != 0.0f) {
+ sock = in->inputs.last;
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr);
+ RNA_float_set(&sockptr, "default_value", strength);
+ }
+
+ ntreeUpdateTree(CTX_data_main(C), ntree);
}
/* assumes nothing being done in ntree yet, sets the default in/out node */
/* called from shading buttons or header */
void ED_node_composit_default(const bContext *C, struct Scene *sce)
{
- bNode *in, *out;
- bNodeSocket *fromsock, *tosock;
+ bNode *in, *out;
+ bNodeSocket *fromsock, *tosock;
- /* but lets check it anyway */
- if (sce->nodetree) {
- if (G.debug & G_DEBUG) {
- printf("error in composite initialize\n");
- }
- return;
- }
+ /* but lets check it anyway */
+ if (sce->nodetree) {
+ if (G.debug & G_DEBUG) {
+ printf("error in composite initialize\n");
+ }
+ return;
+ }
- sce->nodetree = ntreeAddTree(NULL, "Compositing Nodetree", ntreeType_Composite->idname);
+ sce->nodetree = ntreeAddTree(NULL, "Compositing Nodetree", ntreeType_Composite->idname);
- sce->nodetree->chunksize = 256;
- sce->nodetree->edit_quality = NTREE_QUALITY_HIGH;
- sce->nodetree->render_quality = NTREE_QUALITY_HIGH;
+ sce->nodetree->chunksize = 256;
+ sce->nodetree->edit_quality = NTREE_QUALITY_HIGH;
+ sce->nodetree->render_quality = NTREE_QUALITY_HIGH;
- out = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_COMPOSITE);
- out->locx = 300.0f; out->locy = 400.0f;
+ out = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_COMPOSITE);
+ out->locx = 300.0f;
+ out->locy = 400.0f;
- in = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_R_LAYERS);
- in->locx = 10.0f; in->locy = 400.0f;
- nodeSetActive(sce->nodetree, in);
+ in = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_R_LAYERS);
+ in->locx = 10.0f;
+ in->locy = 400.0f;
+ nodeSetActive(sce->nodetree, in);
- /* links from color to color */
- fromsock = in->outputs.first;
- tosock = out->inputs.first;
- nodeAddLink(sce->nodetree, in, fromsock, out, tosock);
+ /* links from color to color */
+ fromsock = in->outputs.first;
+ tosock = out->inputs.first;
+ nodeAddLink(sce->nodetree, in, fromsock, out, tosock);
- ntreeUpdateTree(CTX_data_main(C), sce->nodetree);
+ ntreeUpdateTree(CTX_data_main(C), sce->nodetree);
}
/* assumes nothing being done in ntree yet, sets the default in/out node */
/* called from shading buttons or header */
void ED_node_texture_default(const bContext *C, Tex *tx)
{
- bNode *in, *out;
- bNodeSocket *fromsock, *tosock;
+ bNode *in, *out;
+ bNodeSocket *fromsock, *tosock;
- /* but lets check it anyway */
- if (tx->nodetree) {
- if (G.debug & G_DEBUG) {
- printf("error in texture initialize\n");
- }
- return;
- }
+ /* but lets check it anyway */
+ if (tx->nodetree) {
+ if (G.debug & G_DEBUG) {
+ printf("error in texture initialize\n");
+ }
+ return;
+ }
- tx->nodetree = ntreeAddTree(NULL, "Texture Nodetree", ntreeType_Texture->idname);
+ tx->nodetree = ntreeAddTree(NULL, "Texture Nodetree", ntreeType_Texture->idname);
- out = nodeAddStaticNode(C, tx->nodetree, TEX_NODE_OUTPUT);
- out->locx = 300.0f; out->locy = 300.0f;
+ out = nodeAddStaticNode(C, tx->nodetree, TEX_NODE_OUTPUT);
+ out->locx = 300.0f;
+ out->locy = 300.0f;
- in = nodeAddStaticNode(C, tx->nodetree, TEX_NODE_CHECKER);
- in->locx = 10.0f; in->locy = 300.0f;
- nodeSetActive(tx->nodetree, in);
+ in = nodeAddStaticNode(C, tx->nodetree, TEX_NODE_CHECKER);
+ in->locx = 10.0f;
+ in->locy = 300.0f;
+ nodeSetActive(tx->nodetree, in);
- fromsock = in->outputs.first;
- tosock = out->inputs.first;
- nodeAddLink(tx->nodetree, in, fromsock, out, tosock);
+ fromsock = in->outputs.first;
+ tosock = out->inputs.first;
+ nodeAddLink(tx->nodetree, in, fromsock, out, tosock);
- ntreeUpdateTree(CTX_data_main(C), tx->nodetree);
+ ntreeUpdateTree(CTX_data_main(C), tx->nodetree);
}
/* Here we set the active tree(s), even called for each redraw now, so keep it fast :) */
void snode_set_context(const bContext *C)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTreeType *treetype = ntreeTypeFind(snode->tree_idname);
- bNodeTree *ntree = snode->nodetree;
- ID *id = snode->id, *from = snode->from;
-
- /* check the tree type */
- if (!treetype ||
- (treetype->poll && !treetype->poll(C, treetype)))
- {
- /* invalid tree type, skip
- * NB: not resetting the node path here, invalid bNodeTreeType
- * may still be registered at a later point.
- */
- return;
- }
-
- if (snode->nodetree && !STREQ(snode->nodetree->idname, snode->tree_idname)) {
- /* current tree does not match selected type, clear tree path */
- ntree = NULL;
- id = NULL;
- from = NULL;
- }
-
- if (!(snode->flag & SNODE_PIN) || ntree == NULL) {
- if (treetype->get_from_context) {
- /* reset and update from context */
- ntree = NULL;
- id = NULL;
- from = NULL;
-
- treetype->get_from_context(C, treetype, &ntree, &id, &from);
- }
- }
-
- if (snode->nodetree != ntree || snode->id != id || snode->from != from ||
- (snode->treepath.last == NULL && ntree))
- {
- ED_node_tree_start(snode, ntree, id, from);
- }
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTreeType *treetype = ntreeTypeFind(snode->tree_idname);
+ bNodeTree *ntree = snode->nodetree;
+ ID *id = snode->id, *from = snode->from;
+
+ /* check the tree type */
+ if (!treetype || (treetype->poll && !treetype->poll(C, treetype))) {
+ /* invalid tree type, skip
+ * NB: not resetting the node path here, invalid bNodeTreeType
+ * may still be registered at a later point.
+ */
+ return;
+ }
+
+ if (snode->nodetree && !STREQ(snode->nodetree->idname, snode->tree_idname)) {
+ /* current tree does not match selected type, clear tree path */
+ ntree = NULL;
+ id = NULL;
+ from = NULL;
+ }
+
+ if (!(snode->flag & SNODE_PIN) || ntree == NULL) {
+ if (treetype->get_from_context) {
+ /* reset and update from context */
+ ntree = NULL;
+ id = NULL;
+ from = NULL;
+
+ treetype->get_from_context(C, treetype, &ntree, &id, &from);
+ }
+ }
+
+ if (snode->nodetree != ntree || snode->id != id || snode->from != from ||
+ (snode->treepath.last == NULL && ntree)) {
+ ED_node_tree_start(snode, ntree, id, from);
+ }
}
void snode_update(SpaceNode *snode, bNode *node)
{
- bNodeTreePath *path;
+ bNodeTreePath *path;
- /* XXX this only updates nodes in the current node space tree path.
- * The function supposedly should update any potential group node linking to changed tree,
- * this really requires a working depsgraph ...
- */
+ /* XXX this only updates nodes in the current node space tree path.
+ * The function supposedly should update any potential group node linking to changed tree,
+ * this really requires a working depsgraph ...
+ */
- /* update all edited group nodes */
- path = snode->treepath.last;
- if (path) {
- bNodeTree *ngroup = path->nodetree;
- for (path = path->prev; path; path = path->prev) {
- nodeUpdateID(path->nodetree, (ID *)ngroup);
- ngroup = path->nodetree;
- }
- }
+ /* update all edited group nodes */
+ path = snode->treepath.last;
+ if (path) {
+ bNodeTree *ngroup = path->nodetree;
+ for (path = path->prev; path; path = path->prev) {
+ nodeUpdateID(path->nodetree, (ID *)ngroup);
+ ngroup = path->nodetree;
+ }
+ }
- if (node) {
- nodeUpdate(snode->edittree, node);
- }
+ if (node) {
+ nodeUpdate(snode->edittree, node);
+ }
}
void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
{
- const bool was_active_texture = (node->flag & NODE_ACTIVE_TEXTURE) != 0;
-
- nodeSetActive(ntree, node);
-
- if (node->type != NODE_GROUP) {
- const bool was_output = (node->flag & NODE_DO_OUTPUT) != 0;
- bool do_update = false;
-
- /* generic node group output: set node as active output */
- if (node->type == NODE_GROUP_OUTPUT) {
- bNode *tnode;
- for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
- if (tnode->type == NODE_GROUP_OUTPUT) {
- tnode->flag &= ~NODE_DO_OUTPUT;
- }
- }
-
- node->flag |= NODE_DO_OUTPUT;
- if (!was_output) {
- do_update = 1;
- }
- }
-
- /* tree specific activate calls */
- if (ntree->type == NTREE_SHADER) {
- /* when we select a material, active texture is cleared, for buttons */
- if (node->id && ELEM(GS(node->id->name), ID_MA, ID_LA, ID_WO)) {
- nodeClearActiveID(ntree, ID_TE);
- }
-
- if (ELEM(node->type, SH_NODE_OUTPUT_MATERIAL,
- SH_NODE_OUTPUT_WORLD, SH_NODE_OUTPUT_LIGHT, SH_NODE_OUTPUT_LINESTYLE))
- {
- bNode *tnode;
-
- for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
- if (tnode->type == node->type) {
- tnode->flag &= ~NODE_DO_OUTPUT;
- }
- }
-
- node->flag |= NODE_DO_OUTPUT;
- if (was_output == 0) {
- ED_node_tag_update_nodetree(bmain, ntree, node);
- }
- }
- else if (do_update) {
- ED_node_tag_update_nodetree(bmain, ntree, node);
- }
-
- /* if active texture changed, free glsl materials */
- if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
- Material *ma;
- World *wo;
-
- for (ma = bmain->materials.first; ma; ma = ma->id.next) {
- if (ma->nodetree && ma->use_nodes && ntreeHasTree(ma->nodetree, ntree)) {
- GPU_material_free(&ma->gpumaterial);
- }
- }
-
- for (wo = bmain->worlds.first; wo; wo = wo->id.next) {
- if (wo->nodetree && wo->use_nodes && ntreeHasTree(wo->nodetree, ntree)) {
- GPU_material_free(&wo->gpumaterial);
- }
- }
-
- ED_node_tag_update_nodetree(bmain, ntree, node);
- WM_main_add_notifier(NC_IMAGE, NULL);
- }
-
- WM_main_add_notifier(NC_MATERIAL | ND_NODES, node->id);
- }
- else if (ntree->type == NTREE_COMPOSIT) {
- /* make active viewer, currently only 1 supported... */
- if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
- bNode *tnode;
-
-
- for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
- if (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
- tnode->flag &= ~NODE_DO_OUTPUT;
- }
- }
-
- node->flag |= NODE_DO_OUTPUT;
- if (was_output == 0) {
- ED_node_tag_update_nodetree(bmain, ntree, node);
- }
-
- /* addnode() doesn't link this yet... */
- node->id = (ID *)BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
- }
- else if (node->type == CMP_NODE_COMPOSITE) {
- if (was_output == 0) {
- bNode *tnode;
-
- for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
- if (tnode->type == CMP_NODE_COMPOSITE) {
- tnode->flag &= ~NODE_DO_OUTPUT;
- }
- }
-
- node->flag |= NODE_DO_OUTPUT;
- ED_node_tag_update_nodetree(bmain, ntree, node);
- }
- }
- else if (do_update) {
- ED_node_tag_update_nodetree(bmain, ntree, node);
- }
- }
- else if (ntree->type == NTREE_TEXTURE) {
- // XXX
+ const bool was_active_texture = (node->flag & NODE_ACTIVE_TEXTURE) != 0;
+
+ nodeSetActive(ntree, node);
+
+ if (node->type != NODE_GROUP) {
+ const bool was_output = (node->flag & NODE_DO_OUTPUT) != 0;
+ bool do_update = false;
+
+ /* generic node group output: set node as active output */
+ if (node->type == NODE_GROUP_OUTPUT) {
+ bNode *tnode;
+ for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
+ if (tnode->type == NODE_GROUP_OUTPUT) {
+ tnode->flag &= ~NODE_DO_OUTPUT;
+ }
+ }
+
+ node->flag |= NODE_DO_OUTPUT;
+ if (!was_output) {
+ do_update = 1;
+ }
+ }
+
+ /* tree specific activate calls */
+ if (ntree->type == NTREE_SHADER) {
+ /* when we select a material, active texture is cleared, for buttons */
+ if (node->id && ELEM(GS(node->id->name), ID_MA, ID_LA, ID_WO)) {
+ nodeClearActiveID(ntree, ID_TE);
+ }
+
+ if (ELEM(node->type,
+ SH_NODE_OUTPUT_MATERIAL,
+ SH_NODE_OUTPUT_WORLD,
+ SH_NODE_OUTPUT_LIGHT,
+ SH_NODE_OUTPUT_LINESTYLE)) {
+ bNode *tnode;
+
+ for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
+ if (tnode->type == node->type) {
+ tnode->flag &= ~NODE_DO_OUTPUT;
+ }
+ }
+
+ node->flag |= NODE_DO_OUTPUT;
+ if (was_output == 0) {
+ ED_node_tag_update_nodetree(bmain, ntree, node);
+ }
+ }
+ else if (do_update) {
+ ED_node_tag_update_nodetree(bmain, ntree, node);
+ }
+
+ /* if active texture changed, free glsl materials */
+ if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
+ Material *ma;
+ World *wo;
+
+ for (ma = bmain->materials.first; ma; ma = ma->id.next) {
+ if (ma->nodetree && ma->use_nodes && ntreeHasTree(ma->nodetree, ntree)) {
+ GPU_material_free(&ma->gpumaterial);
+ }
+ }
+
+ for (wo = bmain->worlds.first; wo; wo = wo->id.next) {
+ if (wo->nodetree && wo->use_nodes && ntreeHasTree(wo->nodetree, ntree)) {
+ GPU_material_free(&wo->gpumaterial);
+ }
+ }
+
+ ED_node_tag_update_nodetree(bmain, ntree, node);
+ WM_main_add_notifier(NC_IMAGE, NULL);
+ }
+
+ WM_main_add_notifier(NC_MATERIAL | ND_NODES, node->id);
+ }
+ else if (ntree->type == NTREE_COMPOSIT) {
+ /* make active viewer, currently only 1 supported... */
+ if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+ bNode *tnode;
+
+ for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
+ if (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+ tnode->flag &= ~NODE_DO_OUTPUT;
+ }
+ }
+
+ node->flag |= NODE_DO_OUTPUT;
+ if (was_output == 0) {
+ ED_node_tag_update_nodetree(bmain, ntree, node);
+ }
+
+ /* addnode() doesn't link this yet... */
+ node->id = (ID *)BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ }
+ else if (node->type == CMP_NODE_COMPOSITE) {
+ if (was_output == 0) {
+ bNode *tnode;
+
+ for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
+ if (tnode->type == CMP_NODE_COMPOSITE) {
+ tnode->flag &= ~NODE_DO_OUTPUT;
+ }
+ }
+
+ node->flag |= NODE_DO_OUTPUT;
+ ED_node_tag_update_nodetree(bmain, ntree, node);
+ }
+ }
+ else if (do_update) {
+ ED_node_tag_update_nodetree(bmain, ntree, node);
+ }
+ }
+ else if (ntree->type == NTREE_TEXTURE) {
+ // XXX
#if 0
- if (node->id)
- ; // XXX BIF_preview_changed(-1);
- // allqueue(REDRAWBUTSSHADING, 1);
- // allqueue(REDRAWIPO, 0);
+ if (node->id)
+ ; // XXX BIF_preview_changed(-1);
+ // allqueue(REDRAWBUTSSHADING, 1);
+ // allqueue(REDRAWIPO, 0);
#endif
- }
- }
+ }
+ }
}
void ED_node_post_apply_transform(bContext *UNUSED(C), bNodeTree *UNUSED(ntree))
{
- /* XXX This does not work due to layout functions relying on node->block,
- * which only exists during actual drawing. Can we rely on valid totr rects?
- */
- /* make sure nodes have correct bounding boxes after transform */
- /* node_update_nodetree(C, ntree, 0.0f, 0.0f); */
+ /* XXX This does not work due to layout functions relying on node->block,
+ * which only exists during actual drawing. Can we rely on valid totr rects?
+ */
+ /* make sure nodes have correct bounding boxes after transform */
+ /* node_update_nodetree(C, ntree, 0.0f, 0.0f); */
}
/* ***************** generic operator functions for nodes ***************** */
@@ -757,61 +774,61 @@ void ED_node_post_apply_transform(bContext *UNUSED(C), bNodeTree *UNUSED(ntree))
static bool edit_node_poll(bContext *C)
{
- return ED_operator_node_active(C);
+ return ED_operator_node_active(C);
}
static void edit_node_properties(wmOperatorType *ot)
{
- /* XXX could node be a context pointer? */
- RNA_def_string(ot->srna, "node", NULL, MAX_NAME, "Node", "");
- RNA_def_int(ot->srna, "socket", 0, 0, MAX_SOCKET, "Socket", "", 0, MAX_SOCKET);
- RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Side", "");
+ /* XXX could node be a context pointer? */
+ RNA_def_string(ot->srna, "node", NULL, MAX_NAME, "Node", "");
+ RNA_def_int(ot->srna, "socket", 0, 0, MAX_SOCKET, "Socket", "", 0, MAX_SOCKET);
+ RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Side", "");
}
static int edit_node_invoke_properties(bContext *C, wmOperator *op)
{
- if (!RNA_struct_property_is_set(op->ptr, "node")) {
- bNode *node = CTX_data_pointer_get_type(C, "node", &RNA_Node).data;
- if (!node)
- return 0;
- else
- RNA_string_set(op->ptr, "node", node->name);
- }
+ if (!RNA_struct_property_is_set(op->ptr, "node")) {
+ bNode *node = CTX_data_pointer_get_type(C, "node", &RNA_Node).data;
+ if (!node)
+ return 0;
+ else
+ RNA_string_set(op->ptr, "node", node->name);
+ }
- if (!RNA_struct_property_is_set(op->ptr, "in_out"))
- RNA_enum_set(op->ptr, "in_out", SOCK_IN);
+ if (!RNA_struct_property_is_set(op->ptr, "in_out"))
+ RNA_enum_set(op->ptr, "in_out", SOCK_IN);
- if (!RNA_struct_property_is_set(op->ptr, "socket"))
- RNA_int_set(op->ptr, "socket", 0);
+ if (!RNA_struct_property_is_set(op->ptr, "socket"))
+ RNA_int_set(op->ptr, "socket", 0);
- return 1;
+ return 1;
}
static void edit_node_properties_get(wmOperator *op, bNodeTree *ntree, bNode **rnode, bNodeSocket **rsock, int *rin_out)
{
- bNode *node;
- bNodeSocket *sock = NULL;
- char nodename[MAX_NAME];
- int sockindex;
- int in_out;
+ bNode *node;
+ bNodeSocket *sock = NULL;
+ char nodename[MAX_NAME];
+ int sockindex;
+ int in_out;
- RNA_string_get(op->ptr, "node", nodename);
- node = nodeFindNodebyName(ntree, nodename);
+ RNA_string_get(op->ptr, "node", nodename);
+ node = nodeFindNodebyName(ntree, nodename);
- in_out = RNA_enum_get(op->ptr, "in_out");
+ in_out = RNA_enum_get(op->ptr, "in_out");
- sockindex = RNA_int_get(op->ptr, "socket");
- switch (in_out) {
- case SOCK_IN: sock = BLI_findlink(&node->inputs, sockindex); break;
- case SOCK_OUT: sock = BLI_findlink(&node->outputs, sockindex); break;
- }
+ sockindex = RNA_int_get(op->ptr, "socket");
+ switch (in_out) {
+ case SOCK_IN: sock = BLI_findlink(&node->inputs, sockindex); break;
+ case SOCK_OUT: sock = BLI_findlink(&node->outputs, sockindex); break;
+ }
- if (rnode)
- *rnode = node;
- if (rsock)
- *rsock = sock;
- if (rin_out)
- *rin_out = in_out;
+ if (rnode)
+ *rnode = node;
+ if (rsock)
+ *rsock = sock;
+ if (rin_out)
+ *rin_out = in_out;
}
#endif
@@ -820,1929 +837,1940 @@ static void edit_node_properties_get(wmOperator *op, bNodeTree *ntree, bNode **r
/* is rct in visible part of node? */
static bNode *visible_node(SpaceNode *snode, const rctf *rct)
{
- bNode *node;
+ bNode *node;
- for (node = snode->edittree->nodes.last; node; node = node->prev) {
- if (BLI_rctf_isect(&node->totr, rct, NULL)) {
- break;
- }
- }
- return node;
+ for (node = snode->edittree->nodes.last; node; node = node->prev) {
+ if (BLI_rctf_isect(&node->totr, rct, NULL)) {
+ break;
+ }
+ }
+ return node;
}
/* ********************** size widget operator ******************** */
typedef struct NodeSizeWidget {
- float mxstart, mystart;
- float oldlocx, oldlocy;
- float oldoffsetx, oldoffsety;
- float oldwidth, oldheight;
- int directions;
+ float mxstart, mystart;
+ float oldlocx, oldlocy;
+ float oldoffsetx, oldoffsety;
+ float oldwidth, oldheight;
+ int directions;
} NodeSizeWidget;
-static void node_resize_init(bContext *C, wmOperator *op, const wmEvent *UNUSED(event), bNode *node, int dir)
+static void node_resize_init(
+ bContext *C, wmOperator *op, const wmEvent *UNUSED(event), bNode *node, int dir)
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
- NodeSizeWidget *nsw = MEM_callocN(sizeof(NodeSizeWidget), "size widget op data");
+ NodeSizeWidget *nsw = MEM_callocN(sizeof(NodeSizeWidget), "size widget op data");
- op->customdata = nsw;
- nsw->mxstart = snode->cursor[0] * UI_DPI_FAC;
- nsw->mystart = snode->cursor[1] * UI_DPI_FAC;
+ op->customdata = nsw;
+ nsw->mxstart = snode->cursor[0] * UI_DPI_FAC;
+ nsw->mystart = snode->cursor[1] * UI_DPI_FAC;
- /* store old */
- nsw->oldlocx = node->locx;
- nsw->oldlocy = node->locy;
- nsw->oldoffsetx = node->offsetx;
- nsw->oldoffsety = node->offsety;
- nsw->oldwidth = node->width;
- nsw->oldheight = node->height;
- nsw->directions = dir;
+ /* store old */
+ nsw->oldlocx = node->locx;
+ nsw->oldlocy = node->locy;
+ nsw->oldoffsetx = node->offsetx;
+ nsw->oldoffsety = node->offsety;
+ nsw->oldwidth = node->width;
+ nsw->oldheight = node->height;
+ nsw->directions = dir;
- WM_cursor_modal_set(CTX_wm_window(C), node_get_resize_cursor(dir));
- /* add modal handler */
- WM_event_add_modal_handler(C, op);
+ WM_cursor_modal_set(CTX_wm_window(C), node_get_resize_cursor(dir));
+ /* add modal handler */
+ WM_event_add_modal_handler(C, op);
}
static void node_resize_exit(bContext *C, wmOperator *op, bool UNUSED(cancel))
{
- WM_cursor_modal_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
- MEM_freeN(op->customdata);
- op->customdata = NULL;
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
}
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);
- bNode *node = nodeGetActive(snode->edittree);
- NodeSizeWidget *nsw = op->customdata;
- float mx, my, dx, dy;
-
- switch (event->type) {
- case MOUSEMOVE:
-
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &mx, &my);
- dx = (mx - nsw->mxstart) / UI_DPI_FAC;
- dy = (my - nsw->mystart) / UI_DPI_FAC;
-
- if (node) {
- float *pwidth;
- float oldwidth, widthmin, widthmax;
-
- pwidth = &node->width;
- oldwidth = nsw->oldwidth;
- widthmin = node->typeinfo->minwidth;
- widthmax = node->typeinfo->maxwidth;
-
- {
- if (nsw->directions & NODE_RESIZE_RIGHT) {
- *pwidth = oldwidth + dx;
- CLAMP(*pwidth, widthmin, widthmax);
- }
- if (nsw->directions & NODE_RESIZE_LEFT) {
- float locmax = nsw->oldlocx + oldwidth;
-
- node->locx = nsw->oldlocx + dx;
- CLAMP(node->locx, locmax - widthmax, locmax - widthmin);
- *pwidth = locmax - node->locx;
- }
- }
-
- /* height works the other way round ... */
- {
- float heightmin = UI_DPI_FAC * node->typeinfo->minheight;
- float heightmax = UI_DPI_FAC * node->typeinfo->maxheight;
- if (nsw->directions & NODE_RESIZE_TOP) {
- float locmin = nsw->oldlocy - nsw->oldheight;
-
- node->locy = nsw->oldlocy + dy;
- CLAMP(node->locy, locmin + heightmin, locmin + heightmax);
- node->height = node->locy - locmin;
- }
- if (nsw->directions & NODE_RESIZE_BOTTOM) {
- node->height = nsw->oldheight - dy;
- CLAMP(node->height, heightmin, heightmax);
- }
- }
-
- /* XXX make callback? */
- if (node->type == NODE_FRAME) {
- /* keep the offset symmetric around center point */
- if (nsw->directions & NODE_RESIZE_LEFT) {
- node->locx = nsw->oldlocx + 0.5f * dx;
- node->offsetx = nsw->oldoffsetx + 0.5f * dx;
- }
- if (nsw->directions & NODE_RESIZE_RIGHT) {
- node->locx = nsw->oldlocx + 0.5f * dx;
- node->offsetx = nsw->oldoffsetx - 0.5f * dx;
- }
- if (nsw->directions & NODE_RESIZE_TOP) {
- node->locy = nsw->oldlocy + 0.5f * dy;
- node->offsety = nsw->oldoffsety + 0.5f * dy;
- }
- if (nsw->directions & NODE_RESIZE_BOTTOM) {
- node->locy = nsw->oldlocy + 0.5f * dy;
- node->offsety = nsw->oldoffsety - 0.5f * dy;
- }
- }
- }
-
- ED_region_tag_redraw(ar);
-
- break;
-
- case LEFTMOUSE:
- case MIDDLEMOUSE:
- case RIGHTMOUSE:
- if (event->val == KM_RELEASE) {
- node_resize_exit(C, op, false);
- ED_node_post_apply_transform(C, snode->edittree);
-
- return OPERATOR_FINISHED;
- }
- break;
- }
-
- return OPERATOR_RUNNING_MODAL;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
+ bNode *node = nodeGetActive(snode->edittree);
+ NodeSizeWidget *nsw = op->customdata;
+ float mx, my, dx, dy;
+
+ switch (event->type) {
+ case MOUSEMOVE:
+
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &mx, &my);
+ dx = (mx - nsw->mxstart) / UI_DPI_FAC;
+ dy = (my - nsw->mystart) / UI_DPI_FAC;
+
+ if (node) {
+ float *pwidth;
+ float oldwidth, widthmin, widthmax;
+
+ pwidth = &node->width;
+ oldwidth = nsw->oldwidth;
+ widthmin = node->typeinfo->minwidth;
+ widthmax = node->typeinfo->maxwidth;
+
+ {
+ if (nsw->directions & NODE_RESIZE_RIGHT) {
+ *pwidth = oldwidth + dx;
+ CLAMP(*pwidth, widthmin, widthmax);
+ }
+ if (nsw->directions & NODE_RESIZE_LEFT) {
+ float locmax = nsw->oldlocx + oldwidth;
+
+ node->locx = nsw->oldlocx + dx;
+ CLAMP(node->locx, locmax - widthmax, locmax - widthmin);
+ *pwidth = locmax - node->locx;
+ }
+ }
+
+ /* height works the other way round ... */
+ {
+ float heightmin = UI_DPI_FAC * node->typeinfo->minheight;
+ float heightmax = UI_DPI_FAC * node->typeinfo->maxheight;
+ if (nsw->directions & NODE_RESIZE_TOP) {
+ float locmin = nsw->oldlocy - nsw->oldheight;
+
+ node->locy = nsw->oldlocy + dy;
+ CLAMP(node->locy, locmin + heightmin, locmin + heightmax);
+ node->height = node->locy - locmin;
+ }
+ if (nsw->directions & NODE_RESIZE_BOTTOM) {
+ node->height = nsw->oldheight - dy;
+ CLAMP(node->height, heightmin, heightmax);
+ }
+ }
+
+ /* XXX make callback? */
+ if (node->type == NODE_FRAME) {
+ /* keep the offset symmetric around center point */
+ if (nsw->directions & NODE_RESIZE_LEFT) {
+ node->locx = nsw->oldlocx + 0.5f * dx;
+ node->offsetx = nsw->oldoffsetx + 0.5f * dx;
+ }
+ if (nsw->directions & NODE_RESIZE_RIGHT) {
+ node->locx = nsw->oldlocx + 0.5f * dx;
+ node->offsetx = nsw->oldoffsetx - 0.5f * dx;
+ }
+ if (nsw->directions & NODE_RESIZE_TOP) {
+ node->locy = nsw->oldlocy + 0.5f * dy;
+ node->offsety = nsw->oldoffsety + 0.5f * dy;
+ }
+ if (nsw->directions & NODE_RESIZE_BOTTOM) {
+ node->locy = nsw->oldlocy + 0.5f * dy;
+ node->offsety = nsw->oldoffsety - 0.5f * dy;
+ }
+ }
+ }
+
+ ED_region_tag_redraw(ar);
+
+ break;
+
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ case RIGHTMOUSE:
+ if (event->val == KM_RELEASE) {
+ node_resize_exit(C, op, false);
+ ED_node_post_apply_transform(C, snode->edittree);
+
+ return OPERATOR_FINISHED;
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
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);
- bNode *node = nodeGetActive(snode->edittree);
- int dir;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
+ bNode *node = nodeGetActive(snode->edittree);
+ int dir;
- if (node) {
- float cursor[2];
+ if (node) {
+ 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]);
- dir = node->typeinfo->resize_area_func(node, cursor[0], cursor[1]);
- if (dir != 0) {
- node_resize_init(C, op, event, node, dir);
- return OPERATOR_RUNNING_MODAL;
- }
- }
- return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
+ /* convert mouse coordinates to v2d space */
+ UI_view2d_region_to_view(&ar->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);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+ return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
}
static void node_resize_cancel(bContext *C, wmOperator *op)
{
- node_resize_exit(C, op, true);
+ node_resize_exit(C, op, true);
}
void NODE_OT_resize(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Resize Node";
- ot->idname = "NODE_OT_resize";
- ot->description = "Resize a node";
+ /* identifiers */
+ ot->name = "Resize Node";
+ ot->idname = "NODE_OT_resize";
+ ot->description = "Resize a node";
- /* api callbacks */
- ot->invoke = node_resize_invoke;
- ot->modal = node_resize_modal;
- ot->poll = ED_operator_node_active;
- ot->cancel = node_resize_cancel;
+ /* api callbacks */
+ ot->invoke = node_resize_invoke;
+ ot->modal = node_resize_modal;
+ ot->poll = ED_operator_node_active;
+ ot->cancel = node_resize_cancel;
- /* flags */
- ot->flag = OPTYPE_BLOCKING;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
}
-
/* ********************** hidden sockets ******************** */
int node_has_hidden_sockets(bNode *node)
{
- bNodeSocket *sock;
+ bNodeSocket *sock;
- for (sock = node->inputs.first; sock; sock = sock->next) {
- if (sock->flag & SOCK_HIDDEN) {
- return 1;
- }
- }
- for (sock = node->outputs.first; sock; sock = sock->next) {
- if (sock->flag & SOCK_HIDDEN) {
- return 1;
- }
- }
- return 0;
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (sock->flag & SOCK_HIDDEN) {
+ return 1;
+ }
+ }
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ if (sock->flag & SOCK_HIDDEN) {
+ return 1;
+ }
+ }
+ return 0;
}
void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
{
- bNodeSocket *sock;
-
- if (set == 0) {
- for (sock = node->inputs.first; sock; sock = sock->next) {
- sock->flag &= ~SOCK_HIDDEN;
- }
- for (sock = node->outputs.first; sock; sock = sock->next) {
- sock->flag &= ~SOCK_HIDDEN;
- }
- }
- else {
- /* hide unused sockets */
- for (sock = node->inputs.first; sock; sock = sock->next) {
- if (sock->link == NULL) {
- sock->flag |= SOCK_HIDDEN;
- }
- }
- for (sock = node->outputs.first; sock; sock = sock->next) {
- if (nodeCountSocketLinks(snode->edittree, sock) == 0) {
- sock->flag |= SOCK_HIDDEN;
- }
- }
- }
+ bNodeSocket *sock;
+
+ if (set == 0) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ sock->flag &= ~SOCK_HIDDEN;
+ }
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ sock->flag &= ~SOCK_HIDDEN;
+ }
+ }
+ else {
+ /* hide unused sockets */
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (sock->link == NULL) {
+ sock->flag |= SOCK_HIDDEN;
+ }
+ }
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ if (nodeCountSocketLinks(snode->edittree, sock) == 0) {
+ sock->flag |= SOCK_HIDDEN;
+ }
+ }
+ }
}
-
/* checks snode->mouse position, and returns found node/socket */
/* type is SOCK_IN and/or SOCK_OUT */
-int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, float cursor[2], int in_out)
-{
- bNode *node;
- bNodeSocket *sock;
- rctf rect;
-
- *nodep = NULL;
- *sockp = NULL;
-
- /* check if we click in a socket */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
-
- BLI_rctf_init_pt_radius(&rect, cursor, NODE_SOCKSIZE + 4);
-
- if (!(node->flag & NODE_HIDDEN)) {
- /* extra padding inside and out - allow dragging on the text areas too */
- if (in_out == SOCK_IN) {
- rect.xmax += NODE_SOCKSIZE;
- rect.xmin -= NODE_SOCKSIZE * 4;
- }
- else if (in_out == SOCK_OUT) {
- rect.xmax += NODE_SOCKSIZE * 4;
- rect.xmin -= NODE_SOCKSIZE;
- }
- }
-
- if (in_out & SOCK_IN) {
- for (sock = node->inputs.first; sock; sock = sock->next) {
- if (!nodeSocketIsHidden(sock)) {
- if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) {
- if (node == visible_node(snode, &rect)) {
- *nodep = node;
- *sockp = sock;
- return 1;
- }
- }
- }
- }
- }
- if (in_out & SOCK_OUT) {
- for (sock = node->outputs.first; sock; sock = sock->next) {
- if (!nodeSocketIsHidden(sock)) {
- if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) {
- if (node == visible_node(snode, &rect)) {
- *nodep = node;
- *sockp = sock;
- return 1;
- }
- }
- }
- }
- }
- }
-
- return 0;
+int node_find_indicated_socket(
+ SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, float cursor[2], int in_out)
+{
+ bNode *node;
+ bNodeSocket *sock;
+ rctf rect;
+
+ *nodep = NULL;
+ *sockp = NULL;
+
+ /* check if we click in a socket */
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+
+ BLI_rctf_init_pt_radius(&rect, cursor, NODE_SOCKSIZE + 4);
+
+ if (!(node->flag & NODE_HIDDEN)) {
+ /* extra padding inside and out - allow dragging on the text areas too */
+ if (in_out == SOCK_IN) {
+ rect.xmax += NODE_SOCKSIZE;
+ rect.xmin -= NODE_SOCKSIZE * 4;
+ }
+ else if (in_out == SOCK_OUT) {
+ rect.xmax += NODE_SOCKSIZE * 4;
+ rect.xmin -= NODE_SOCKSIZE;
+ }
+ }
+
+ if (in_out & SOCK_IN) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (!nodeSocketIsHidden(sock)) {
+ if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) {
+ if (node == visible_node(snode, &rect)) {
+ *nodep = node;
+ *sockp = sock;
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ if (in_out & SOCK_OUT) {
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ if (!nodeSocketIsHidden(sock)) {
+ if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) {
+ if (node == visible_node(snode, &rect)) {
+ *nodep = node;
+ *sockp = sock;
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
}
/* ****************** Duplicate *********************** */
static void node_duplicate_reparent_recursive(bNode *node)
{
- bNode *parent;
+ bNode *parent;
- node->flag |= NODE_TEST;
+ node->flag |= NODE_TEST;
- /* find first selected parent */
- for (parent = node->parent; parent; parent = parent->parent) {
- if (parent->flag & SELECT) {
- if (!(parent->flag & NODE_TEST)) {
- node_duplicate_reparent_recursive(parent);
- }
- break;
- }
- }
- /* reparent node copy to parent copy */
- if (parent) {
- nodeDetachNode(node->new_node);
- nodeAttachNode(node->new_node, parent->new_node);
- }
+ /* find first selected parent */
+ for (parent = node->parent; parent; parent = parent->parent) {
+ if (parent->flag & SELECT) {
+ if (!(parent->flag & NODE_TEST)) {
+ node_duplicate_reparent_recursive(parent);
+ }
+ break;
+ }
+ }
+ /* reparent node copy to parent copy */
+ if (parent) {
+ nodeDetachNode(node->new_node);
+ nodeAttachNode(node->new_node, parent->new_node);
+ }
}
static int node_duplicate_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree = snode->edittree;
- bNode *node, *newnode, *lastnode;
- bNodeLink *link, *newlink, *lastlink;
- const bool keep_inputs = RNA_boolean_get(op->ptr, "keep_inputs");
- bool do_tag_update = false;
-
- ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
-
- lastnode = ntree->nodes.last;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->flag & SELECT) {
- newnode = BKE_node_copy_ex(ntree, node, LIB_ID_COPY_DEFAULT);
-
- /* to ensure redraws or rerenders happen */
- ED_node_tag_update_id(snode->id);
- }
-
- /* make sure we don't copy new nodes again! */
- if (node == lastnode) {
- break;
- }
- }
-
- /* copy links between selected nodes
- * NB: this depends on correct node->new_node and sock->new_sock pointers from above copy!
- */
- lastlink = ntree->links.last;
- for (link = ntree->links.first; link; link = link->next) {
- /* This creates new links between copied nodes.
- * If keep_inputs is set, also copies input links from unselected (when fromnode==NULL)!
- */
- if (link->tonode && (link->tonode->flag & NODE_SELECT) &&
- (keep_inputs || (link->fromnode && (link->fromnode->flag & NODE_SELECT))))
- {
- newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink");
- newlink->flag = link->flag;
- newlink->tonode = link->tonode->new_node;
- newlink->tosock = link->tosock->new_sock;
- if (link->fromnode && (link->fromnode->flag & NODE_SELECT)) {
- newlink->fromnode = link->fromnode->new_node;
- newlink->fromsock = link->fromsock->new_sock;
- }
- else {
- /* input node not copied, this keeps the original input linked */
- newlink->fromnode = link->fromnode;
- newlink->fromsock = link->fromsock;
- }
-
- BLI_addtail(&ntree->links, newlink);
- }
-
- /* make sure we don't copy new links again! */
- if (link == lastlink) {
- break;
- }
- }
-
- /* clear flags for recursive depth-first iteration */
- for (node = ntree->nodes.first; node; node = node->next) {
- node->flag &= ~NODE_TEST;
- }
- /* reparent copied nodes */
- for (node = ntree->nodes.first; node; node = node->next) {
- if ((node->flag & SELECT) && !(node->flag & NODE_TEST)) {
- node_duplicate_reparent_recursive(node);
- }
-
- /* only has to check old nodes */
- if (node == lastnode) {
- break;
- }
- }
-
- /* deselect old nodes, select the copies instead */
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->flag & SELECT) {
- /* has been set during copy above */
- newnode = node->new_node;
-
- nodeSetSelected(node, false);
- node->flag &= ~NODE_ACTIVE;
- nodeSetSelected(newnode, true);
-
- do_tag_update |= (do_tag_update || node_connected_to_output(bmain, ntree, newnode));
- }
-
- /* make sure we don't copy new nodes again! */
- if (node == lastnode) {
- break;
- }
- }
-
- ntreeUpdateTree(CTX_data_main(C), snode->edittree);
-
- snode_notify(C, snode);
- if (do_tag_update) {
- snode_dag_update(C, snode);
- }
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNode *node, *newnode, *lastnode;
+ bNodeLink *link, *newlink, *lastlink;
+ const bool keep_inputs = RNA_boolean_get(op->ptr, "keep_inputs");
+ bool do_tag_update = false;
+
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
+
+ lastnode = ntree->nodes.last;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->flag & SELECT) {
+ newnode = BKE_node_copy_ex(ntree, node, LIB_ID_COPY_DEFAULT);
+
+ /* to ensure redraws or rerenders happen */
+ ED_node_tag_update_id(snode->id);
+ }
+
+ /* make sure we don't copy new nodes again! */
+ if (node == lastnode) {
+ break;
+ }
+ }
+
+ /* copy links between selected nodes
+ * NB: this depends on correct node->new_node and sock->new_sock pointers from above copy!
+ */
+ lastlink = ntree->links.last;
+ for (link = ntree->links.first; link; link = link->next) {
+ /* This creates new links between copied nodes.
+ * If keep_inputs is set, also copies input links from unselected (when fromnode==NULL)!
+ */
+ if (link->tonode && (link->tonode->flag & NODE_SELECT) &&
+ (keep_inputs || (link->fromnode && (link->fromnode->flag & NODE_SELECT)))) {
+ newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink");
+ newlink->flag = link->flag;
+ newlink->tonode = link->tonode->new_node;
+ newlink->tosock = link->tosock->new_sock;
+ if (link->fromnode && (link->fromnode->flag & NODE_SELECT)) {
+ newlink->fromnode = link->fromnode->new_node;
+ newlink->fromsock = link->fromsock->new_sock;
+ }
+ else {
+ /* input node not copied, this keeps the original input linked */
+ newlink->fromnode = link->fromnode;
+ newlink->fromsock = link->fromsock;
+ }
+
+ BLI_addtail(&ntree->links, newlink);
+ }
+
+ /* make sure we don't copy new links again! */
+ if (link == lastlink) {
+ break;
+ }
+ }
+
+ /* clear flags for recursive depth-first iteration */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ node->flag &= ~NODE_TEST;
+ }
+ /* reparent copied nodes */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if ((node->flag & SELECT) && !(node->flag & NODE_TEST)) {
+ node_duplicate_reparent_recursive(node);
+ }
+
+ /* only has to check old nodes */
+ if (node == lastnode) {
+ break;
+ }
+ }
+
+ /* deselect old nodes, select the copies instead */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->flag & SELECT) {
+ /* has been set during copy above */
+ newnode = node->new_node;
+
+ nodeSetSelected(node, false);
+ node->flag &= ~NODE_ACTIVE;
+ nodeSetSelected(newnode, true);
+
+ do_tag_update |= (do_tag_update || node_connected_to_output(bmain, ntree, newnode));
+ }
+
+ /* make sure we don't copy new nodes again! */
+ if (node == lastnode) {
+ break;
+ }
+ }
+
+ ntreeUpdateTree(CTX_data_main(C), snode->edittree);
+
+ snode_notify(C, snode);
+ if (do_tag_update) {
+ snode_dag_update(C, snode);
+ }
+
+ return OPERATOR_FINISHED;
}
void NODE_OT_duplicate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Duplicate Nodes";
- ot->description = "Duplicate selected nodes";
- ot->idname = "NODE_OT_duplicate";
+ /* identifiers */
+ ot->name = "Duplicate Nodes";
+ ot->description = "Duplicate selected nodes";
+ ot->idname = "NODE_OT_duplicate";
- /* api callbacks */
- ot->exec = node_duplicate_exec;
- ot->poll = ED_operator_node_editable;
+ /* api callbacks */
+ ot->exec = node_duplicate_exec;
+ ot->poll = ED_operator_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "keep_inputs", 0, "Keep Inputs", "Keep the input links to duplicated nodes");
+ RNA_def_boolean(
+ ot->srna, "keep_inputs", 0, "Keep Inputs", "Keep the input links to duplicated nodes");
}
bool ED_node_select_check(ListBase *lb)
{
- for (bNode *node = lb->first; node; node = node->next) {
- if (node->flag & NODE_SELECT) {
- return true;
- }
- }
+ for (bNode *node = lb->first; node; node = node->next) {
+ if (node->flag & NODE_SELECT) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
void ED_node_select_all(ListBase *lb, int action)
{
- if (action == SEL_TOGGLE) {
- if (ED_node_select_check(lb)) {
- action = SEL_DESELECT;
- }
- else {
- action = SEL_SELECT;
- }
- }
-
- for (bNode *node = lb->first; node; node = node->next) {
- switch (action) {
- case SEL_SELECT:
- nodeSetSelected(node, true);
- break;
- case SEL_DESELECT:
- nodeSetSelected(node, false);
- break;
- case SEL_INVERT:
- nodeSetSelected(node, !(node->flag & SELECT));
- break;
- }
- }
+ if (action == SEL_TOGGLE) {
+ if (ED_node_select_check(lb)) {
+ action = SEL_DESELECT;
+ }
+ else {
+ action = SEL_SELECT;
+ }
+ }
+
+ for (bNode *node = lb->first; node; node = node->next) {
+ switch (action) {
+ case SEL_SELECT:
+ nodeSetSelected(node, true);
+ break;
+ case SEL_DESELECT:
+ nodeSetSelected(node, false);
+ break;
+ case SEL_INVERT:
+ nodeSetSelected(node, !(node->flag & SELECT));
+ break;
+ }
+ }
}
/* ******************************** */
// XXX some code needing updating to operators...
-
/* goes over all scenes, reads render layers */
static int node_read_viewlayers_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- Scene *curscene = CTX_data_scene(C), *scene;
- bNode *node;
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ Scene *curscene = CTX_data_scene(C), *scene;
+ bNode *node;
- ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
- /* first tag scenes unread */
- for (scene = bmain->scenes.first; scene; scene = scene->id.next) {
- scene->id.tag |= LIB_TAG_DOIT;
- }
+ /* first tag scenes unread */
+ for (scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ scene->id.tag |= LIB_TAG_DOIT;
+ }
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_R_LAYERS) {
- ID *id = node->id;
- if (id->tag & LIB_TAG_DOIT) {
- RE_ReadRenderResult(curscene, (Scene *)id);
- ntreeCompositTagRender((Scene *)id);
- id->tag &= ~LIB_TAG_DOIT;
- }
- }
- }
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_R_LAYERS) {
+ ID *id = node->id;
+ if (id->tag & LIB_TAG_DOIT) {
+ RE_ReadRenderResult(curscene, (Scene *)id);
+ ntreeCompositTagRender((Scene *)id);
+ id->tag &= ~LIB_TAG_DOIT;
+ }
+ }
+ }
- snode_notify(C, snode);
- snode_dag_update(C, snode);
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_read_viewlayers(wmOperatorType *ot)
{
- ot->name = "Read View Layers";
- ot->idname = "NODE_OT_read_viewlayers";
- ot->description = "Read all render layers of all used scenes";
+ ot->name = "Read View Layers";
+ ot->idname = "NODE_OT_read_viewlayers";
+ ot->description = "Read all render layers of all used scenes";
- ot->exec = node_read_viewlayers_exec;
+ ot->exec = node_read_viewlayers_exec;
- ot->poll = composite_node_active;
+ ot->poll = composite_node_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *sce = CTX_data_scene(C);
- bNode *node;
+ Scene *sce = CTX_data_scene(C);
+ bNode *node;
- for (node = sce->nodetree->nodes.first; node; node = node->next) {
- if (node->id == (ID *)sce && node->need_exec) {
- break;
- }
- }
- if (node) {
- ViewLayer *view_layer = BLI_findlink(&sce->view_layers, node->custom1);
+ for (node = sce->nodetree->nodes.first; node; node = node->next) {
+ if (node->id == (ID *)sce && node->need_exec) {
+ break;
+ }
+ }
+ if (node) {
+ ViewLayer *view_layer = BLI_findlink(&sce->view_layers, node->custom1);
- if (view_layer) {
- PointerRNA op_ptr;
+ if (view_layer) {
+ PointerRNA op_ptr;
- WM_operator_properties_create(&op_ptr, "RENDER_OT_render");
- RNA_string_set(&op_ptr, "layer", view_layer->name);
- RNA_string_set(&op_ptr, "scene", sce->id.name + 2);
+ WM_operator_properties_create(&op_ptr, "RENDER_OT_render");
+ RNA_string_set(&op_ptr, "layer", view_layer->name);
+ RNA_string_set(&op_ptr, "scene", sce->id.name + 2);
- /* to keep keypositions */
- sce->r.scemode |= R_NO_FRAME_UPDATE;
+ /* to keep keypositions */
+ sce->r.scemode |= R_NO_FRAME_UPDATE;
- WM_operator_name_call(C, "RENDER_OT_render", WM_OP_INVOKE_DEFAULT, &op_ptr);
+ WM_operator_name_call(C, "RENDER_OT_render", WM_OP_INVOKE_DEFAULT, &op_ptr);
- WM_operator_properties_free(&op_ptr);
+ WM_operator_properties_free(&op_ptr);
- return OPERATOR_FINISHED;
- }
- }
- return OPERATOR_CANCELLED;
+ return OPERATOR_FINISHED;
+ }
+ }
+ return OPERATOR_CANCELLED;
}
void NODE_OT_render_changed(wmOperatorType *ot)
{
- ot->name = "Render Changed Layer";
- ot->idname = "NODE_OT_render_changed";
- ot->description = "Render current scene, when input node's layer has been changed";
+ ot->name = "Render Changed Layer";
+ ot->idname = "NODE_OT_render_changed";
+ ot->description = "Render current scene, when input node's layer has been changed";
- ot->exec = node_render_changed_exec;
+ ot->exec = node_render_changed_exec;
- ot->poll = composite_node_active;
+ ot->poll = composite_node_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
-
/* ****************** Hide operator *********************** */
static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
{
- bNode *node;
- int tot_eq = 0, tot_neq = 0;
-
- /* Toggles the flag on all selected nodes.
- * If the flag is set on all nodes it is unset.
- * If the flag is not set on all nodes, it is set.
- */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & SELECT) {
-
- if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0) {
- continue;
- }
- if (toggle_flag == NODE_OPTIONS && !(node->typeinfo->draw_buttons || node->typeinfo->draw_buttons_ex)) {
- continue;
- }
-
- if (node->flag & toggle_flag) {
- tot_eq++;
- }
- else {
- tot_neq++;
- }
- }
- }
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & SELECT) {
-
- if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0) {
- continue;
- }
- if (toggle_flag == NODE_OPTIONS && !(node->typeinfo->draw_buttons || node->typeinfo->draw_buttons_ex)) {
- continue;
- }
-
- if ((tot_eq && tot_neq) || tot_eq == 0) {
- node->flag |= toggle_flag;
- }
- else {
- node->flag &= ~toggle_flag;
- }
- }
- }
+ bNode *node;
+ int tot_eq = 0, tot_neq = 0;
+
+ /* Toggles the flag on all selected nodes.
+ * If the flag is set on all nodes it is unset.
+ * If the flag is not set on all nodes, it is set.
+ */
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (node->flag & SELECT) {
+
+ if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0) {
+ continue;
+ }
+ if (toggle_flag == NODE_OPTIONS &&
+ !(node->typeinfo->draw_buttons || node->typeinfo->draw_buttons_ex)) {
+ continue;
+ }
+
+ if (node->flag & toggle_flag) {
+ tot_eq++;
+ }
+ else {
+ tot_neq++;
+ }
+ }
+ }
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (node->flag & SELECT) {
+
+ if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0) {
+ continue;
+ }
+ if (toggle_flag == NODE_OPTIONS &&
+ !(node->typeinfo->draw_buttons || node->typeinfo->draw_buttons_ex)) {
+ continue;
+ }
+
+ if ((tot_eq && tot_neq) || tot_eq == 0) {
+ node->flag |= toggle_flag;
+ }
+ else {
+ node->flag &= ~toggle_flag;
+ }
+ }
+ }
}
static int node_hide_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
- /* sanity checking (poll callback checks this already) */
- if ((snode == NULL) || (snode->edittree == NULL)) {
- return OPERATOR_CANCELLED;
- }
+ /* sanity checking (poll callback checks this already) */
+ if ((snode == NULL) || (snode->edittree == NULL)) {
+ return OPERATOR_CANCELLED;
+ }
- node_flag_toggle_exec(snode, NODE_HIDDEN);
+ node_flag_toggle_exec(snode, NODE_HIDDEN);
- WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_hide_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide";
- ot->description = "Toggle hiding of selected nodes";
- ot->idname = "NODE_OT_hide_toggle";
+ /* identifiers */
+ ot->name = "Hide";
+ ot->description = "Toggle hiding of selected nodes";
+ ot->idname = "NODE_OT_hide_toggle";
- /* callbacks */
- ot->exec = node_hide_toggle_exec;
- ot->poll = ED_operator_node_active;
+ /* callbacks */
+ ot->exec = node_hide_toggle_exec;
+ ot->poll = ED_operator_node_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int node_preview_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
- /* sanity checking (poll callback checks this already) */
- if ((snode == NULL) || (snode->edittree == NULL)) {
- return OPERATOR_CANCELLED;
- }
+ /* sanity checking (poll callback checks this already) */
+ if ((snode == NULL) || (snode->edittree == NULL)) {
+ return OPERATOR_CANCELLED;
+ }
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
- node_flag_toggle_exec(snode, NODE_PREVIEW);
+ node_flag_toggle_exec(snode, NODE_PREVIEW);
- snode_notify(C, snode);
+ snode_notify(C, snode);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_preview_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Node Preview";
- ot->description = "Toggle preview display for selected nodes";
- ot->idname = "NODE_OT_preview_toggle";
+ /* identifiers */
+ ot->name = "Toggle Node Preview";
+ ot->description = "Toggle preview display for selected nodes";
+ ot->idname = "NODE_OT_preview_toggle";
- /* callbacks */
- ot->exec = node_preview_toggle_exec;
- ot->poll = ED_operator_node_active;
+ /* callbacks */
+ ot->exec = node_preview_toggle_exec;
+ ot->poll = ED_operator_node_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int node_options_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
- /* sanity checking (poll callback checks this already) */
- if ((snode == NULL) || (snode->edittree == NULL)) {
- return OPERATOR_CANCELLED;
- }
+ /* sanity checking (poll callback checks this already) */
+ if ((snode == NULL) || (snode->edittree == NULL)) {
+ return OPERATOR_CANCELLED;
+ }
- node_flag_toggle_exec(snode, NODE_OPTIONS);
+ node_flag_toggle_exec(snode, NODE_OPTIONS);
- WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_options_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Node Options";
- ot->description = "Toggle option buttons display for selected nodes";
- ot->idname = "NODE_OT_options_toggle";
+ /* identifiers */
+ ot->name = "Toggle Node Options";
+ ot->description = "Toggle option buttons display for selected nodes";
+ ot->idname = "NODE_OT_options_toggle";
- /* callbacks */
- ot->exec = node_options_toggle_exec;
- ot->poll = ED_operator_node_active;
+ /* callbacks */
+ ot->exec = node_options_toggle_exec;
+ ot->poll = ED_operator_node_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node;
- int hidden;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node;
+ int hidden;
- /* sanity checking (poll callback checks this already) */
- if ((snode == NULL) || (snode->edittree == NULL)) {
- return OPERATOR_CANCELLED;
- }
+ /* sanity checking (poll callback checks this already) */
+ if ((snode == NULL) || (snode->edittree == NULL)) {
+ return OPERATOR_CANCELLED;
+ }
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
- /* Toggle for all selected nodes */
- hidden = 0;
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & SELECT) {
- if (node_has_hidden_sockets(node)) {
- hidden = 1;
- break;
- }
- }
- }
+ /* Toggle for all selected nodes */
+ hidden = 0;
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (node->flag & SELECT) {
+ if (node_has_hidden_sockets(node)) {
+ hidden = 1;
+ break;
+ }
+ }
+ }
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & SELECT) {
- node_set_hidden_sockets(snode, node, !hidden);
- }
- }
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (node->flag & SELECT) {
+ node_set_hidden_sockets(snode, node, !hidden);
+ }
+ }
- ntreeUpdateTree(CTX_data_main(C), snode->edittree);
+ ntreeUpdateTree(CTX_data_main(C), snode->edittree);
- WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_hide_socket_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Hidden Node Sockets";
- ot->description = "Toggle unused node socket display";
- ot->idname = "NODE_OT_hide_socket_toggle";
+ /* identifiers */
+ ot->name = "Toggle Hidden Node Sockets";
+ ot->description = "Toggle unused node socket display";
+ ot->idname = "NODE_OT_hide_socket_toggle";
- /* callbacks */
- ot->exec = node_socket_toggle_exec;
- ot->poll = ED_operator_node_active;
+ /* callbacks */
+ ot->exec = node_socket_toggle_exec;
+ ot->poll = ED_operator_node_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** Mute operator *********************** */
static int node_mute_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node;
- bool do_tag_update = false;
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node;
+ bool do_tag_update = false;
- ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- /* Only allow muting of nodes having a mute func! */
- if ((node->flag & SELECT) && node->typeinfo->update_internal_links) {
- node->flag ^= NODE_MUTED;
- snode_update(snode, node);
- do_tag_update |= (do_tag_update || node_connected_to_output(bmain, snode->edittree, node));
- }
- }
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ /* Only allow muting of nodes having a mute func! */
+ if ((node->flag & SELECT) && node->typeinfo->update_internal_links) {
+ node->flag ^= NODE_MUTED;
+ snode_update(snode, node);
+ do_tag_update |= (do_tag_update || node_connected_to_output(bmain, snode->edittree, node));
+ }
+ }
- snode_notify(C, snode);
- if (do_tag_update) {
- snode_dag_update(C, snode);
- }
+ snode_notify(C, snode);
+ if (do_tag_update) {
+ snode_dag_update(C, snode);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_mute_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Node Mute";
- ot->description = "Toggle muting of the nodes";
- ot->idname = "NODE_OT_mute_toggle";
+ /* identifiers */
+ ot->name = "Toggle Node Mute";
+ ot->description = "Toggle muting of the nodes";
+ ot->idname = "NODE_OT_mute_toggle";
- /* callbacks */
- ot->exec = node_mute_exec;
- ot->poll = ED_operator_node_editable;
+ /* callbacks */
+ ot->exec = node_mute_exec;
+ ot->poll = ED_operator_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** Delete operator ******************* */
static int node_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node, *next;
- bool do_tag_update = false;
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node, *next;
+ bool do_tag_update = false;
- ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
- for (node = snode->edittree->nodes.first; node; node = next) {
- next = node->next;
- if (node->flag & SELECT) {
- do_tag_update |= (do_tag_update || node_connected_to_output(bmain, snode->edittree, node));
- nodeRemoveNode(bmain, snode->edittree, node, true);
- }
- }
+ for (node = snode->edittree->nodes.first; node; node = next) {
+ next = node->next;
+ if (node->flag & SELECT) {
+ do_tag_update |= (do_tag_update || node_connected_to_output(bmain, snode->edittree, node));
+ nodeRemoveNode(bmain, snode->edittree, node, true);
+ }
+ }
- ntreeUpdateTree(CTX_data_main(C), snode->edittree);
+ ntreeUpdateTree(CTX_data_main(C), snode->edittree);
- snode_notify(C, snode);
- if (do_tag_update) {
- snode_dag_update(C, snode);
- }
+ snode_notify(C, snode);
+ if (do_tag_update) {
+ snode_dag_update(C, snode);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete";
- ot->description = "Delete selected nodes";
- ot->idname = "NODE_OT_delete";
+ /* identifiers */
+ ot->name = "Delete";
+ ot->description = "Delete selected nodes";
+ ot->idname = "NODE_OT_delete";
- /* api callbacks */
- ot->exec = node_delete_exec;
- ot->poll = ED_operator_node_editable;
+ /* api callbacks */
+ ot->exec = node_delete_exec;
+ ot->poll = ED_operator_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** Switch View ******************* */
static bool node_switch_view_poll(bContext *C)
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
- if (snode && snode->edittree) {
- return true;
- }
+ if (snode && snode->edittree) {
+ return true;
+ }
- return false;
+ return false;
}
static int node_switch_view_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node, *next;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node, *next;
- for (node = snode->edittree->nodes.first; node; node = next) {
- next = node->next;
- if (node->flag & SELECT) {
- /* call the update function from the Switch View node */
- node->update = NODE_UPDATE_OPERATOR;
- }
- }
+ for (node = snode->edittree->nodes.first; node; node = next) {
+ next = node->next;
+ if (node->flag & SELECT) {
+ /* call the update function from the Switch View node */
+ node->update = NODE_UPDATE_OPERATOR;
+ }
+ }
- ntreeUpdateTree(CTX_data_main(C), snode->edittree);
+ ntreeUpdateTree(CTX_data_main(C), snode->edittree);
- snode_notify(C, snode);
- snode_dag_update(C, snode);
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_switch_view_update(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Update Views";
- ot->description = "Update views of selected node";
- ot->idname = "NODE_OT_switch_view_update";
+ /* identifiers */
+ ot->name = "Update Views";
+ ot->description = "Update views of selected node";
+ ot->idname = "NODE_OT_switch_view_update";
- /* api callbacks */
- ot->exec = node_switch_view_exec;
- ot->poll = node_switch_view_poll;
+ /* api callbacks */
+ ot->exec = node_switch_view_exec;
+ ot->poll = node_switch_view_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** Delete with reconnect ******************* */
static int node_delete_reconnect_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node, *next;
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node, *next;
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
- for (node = snode->edittree->nodes.first; node; node = next) {
- next = node->next;
- if (node->flag & SELECT) {
- nodeInternalRelink(snode->edittree, node);
- nodeRemoveNode(bmain, snode->edittree, node, true);
- }
- }
+ for (node = snode->edittree->nodes.first; node; node = next) {
+ next = node->next;
+ if (node->flag & SELECT) {
+ nodeInternalRelink(snode->edittree, node);
+ nodeRemoveNode(bmain, snode->edittree, node, true);
+ }
+ }
- ntreeUpdateTree(CTX_data_main(C), snode->edittree);
+ ntreeUpdateTree(CTX_data_main(C), snode->edittree);
- snode_notify(C, snode);
- snode_dag_update(C, snode);
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_delete_reconnect(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete with Reconnect";
- ot->description = "Delete nodes; will reconnect nodes as if deletion was muted";
- ot->idname = "NODE_OT_delete_reconnect";
+ /* identifiers */
+ ot->name = "Delete with Reconnect";
+ ot->description = "Delete nodes; will reconnect nodes as if deletion was muted";
+ ot->idname = "NODE_OT_delete_reconnect";
- /* api callbacks */
- ot->exec = node_delete_reconnect_exec;
- ot->poll = ED_operator_node_editable;
+ /* api callbacks */
+ ot->exec = node_delete_reconnect_exec;
+ ot->poll = ED_operator_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/* ****************** File Output Add Socket ******************* */
static int node_output_file_add_socket_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- PointerRNA ptr = CTX_data_pointer_get(C, "node");
- bNodeTree *ntree = NULL;
- bNode *node = NULL;
- char file_path[MAX_NAME];
+ Scene *scene = CTX_data_scene(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ PointerRNA ptr = CTX_data_pointer_get(C, "node");
+ bNodeTree *ntree = NULL;
+ bNode *node = NULL;
+ char file_path[MAX_NAME];
- if (ptr.data) {
- node = ptr.data;
- ntree = ptr.id.data;
- }
- else if (snode && snode->edittree) {
- ntree = snode->edittree;
- node = nodeGetActive(snode->edittree);
- }
+ if (ptr.data) {
+ node = ptr.data;
+ ntree = ptr.id.data;
+ }
+ else if (snode && snode->edittree) {
+ ntree = snode->edittree;
+ node = nodeGetActive(snode->edittree);
+ }
- if (!node || node->type != CMP_NODE_OUTPUT_FILE) {
- return OPERATOR_CANCELLED;
- }
+ if (!node || node->type != CMP_NODE_OUTPUT_FILE) {
+ return OPERATOR_CANCELLED;
+ }
- RNA_string_get(op->ptr, "file_path", file_path);
- ntreeCompositOutputFileAddSocket(ntree, node, file_path, &scene->r.im_format);
+ RNA_string_get(op->ptr, "file_path", file_path);
+ ntreeCompositOutputFileAddSocket(ntree, node, file_path, &scene->r.im_format);
- snode_notify(C, snode);
+ snode_notify(C, snode);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_output_file_add_socket(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add File Node Socket";
- ot->description = "Add a new input to a file output node";
- ot->idname = "NODE_OT_output_file_add_socket";
+ /* identifiers */
+ ot->name = "Add File Node Socket";
+ ot->description = "Add a new input to a file output node";
+ ot->idname = "NODE_OT_output_file_add_socket";
- /* callbacks */
- ot->exec = node_output_file_add_socket_exec;
- ot->poll = composite_node_editable;
+ /* callbacks */
+ ot->exec = node_output_file_add_socket_exec;
+ ot->poll = composite_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_string(ot->srna, "file_path", "Image", MAX_NAME, "File Path", "Sub-path of the output file");
+ RNA_def_string(
+ ot->srna, "file_path", "Image", MAX_NAME, "File Path", "Sub-path of the output file");
}
/* ****************** Multi File Output Remove Socket ******************* */
static int node_output_file_remove_active_socket_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
- PointerRNA ptr = CTX_data_pointer_get(C, "node");
- bNodeTree *ntree = NULL;
- bNode *node = NULL;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ PointerRNA ptr = CTX_data_pointer_get(C, "node");
+ bNodeTree *ntree = NULL;
+ bNode *node = NULL;
- if (ptr.data) {
- node = ptr.data;
- ntree = ptr.id.data;
- }
- else if (snode && snode->edittree) {
- ntree = snode->edittree;
- node = nodeGetActive(snode->edittree);
- }
+ if (ptr.data) {
+ node = ptr.data;
+ ntree = ptr.id.data;
+ }
+ else if (snode && snode->edittree) {
+ ntree = snode->edittree;
+ node = nodeGetActive(snode->edittree);
+ }
- if (!node || node->type != CMP_NODE_OUTPUT_FILE) {
- return OPERATOR_CANCELLED;
- }
+ if (!node || node->type != CMP_NODE_OUTPUT_FILE) {
+ return OPERATOR_CANCELLED;
+ }
- if (!ntreeCompositOutputFileRemoveActiveSocket(ntree, node)) {
- return OPERATOR_CANCELLED;
- }
+ if (!ntreeCompositOutputFileRemoveActiveSocket(ntree, node)) {
+ return OPERATOR_CANCELLED;
+ }
- snode_notify(C, snode);
+ snode_notify(C, snode);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_output_file_remove_active_socket(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove File Node Socket";
- ot->description = "Remove active input from a file output node";
- ot->idname = "NODE_OT_output_file_remove_active_socket";
+ /* identifiers */
+ ot->name = "Remove File Node Socket";
+ ot->description = "Remove active input from a file output node";
+ ot->idname = "NODE_OT_output_file_remove_active_socket";
- /* callbacks */
- ot->exec = node_output_file_remove_active_socket_exec;
- ot->poll = composite_node_editable;
+ /* callbacks */
+ ot->exec = node_output_file_remove_active_socket_exec;
+ ot->poll = composite_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** Multi File Output Move Socket ******************* */
static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- PointerRNA ptr = CTX_data_pointer_get(C, "node");
- bNode *node = NULL;
- NodeImageMultiFile *nimf;
- bNodeSocket *sock;
- int direction;
-
- if (ptr.data) {
- node = ptr.data;
- }
- else if (snode && snode->edittree) {
- node = nodeGetActive(snode->edittree);
- }
-
- if (!node || node->type != CMP_NODE_OUTPUT_FILE) {
- return OPERATOR_CANCELLED;
- }
-
- nimf = node->storage;
-
- sock = BLI_findlink(&node->inputs, nimf->active_input);
- if (!sock) {
- return OPERATOR_CANCELLED;
- }
-
- direction = RNA_enum_get(op->ptr, "direction");
-
- if (direction == 1) {
- bNodeSocket *before = sock->prev;
- if (!before) {
- return OPERATOR_CANCELLED;
- }
- BLI_remlink(&node->inputs, sock);
- BLI_insertlinkbefore(&node->inputs, before, sock);
- nimf->active_input--;
- }
- else {
- bNodeSocket *after = sock->next;
- if (!after) {
- return OPERATOR_CANCELLED;
- }
- BLI_remlink(&node->inputs, sock);
- BLI_insertlinkafter(&node->inputs, after, sock);
- nimf->active_input++;
- }
-
- snode_notify(C, snode);
-
- return OPERATOR_FINISHED;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ PointerRNA ptr = CTX_data_pointer_get(C, "node");
+ bNode *node = NULL;
+ NodeImageMultiFile *nimf;
+ bNodeSocket *sock;
+ int direction;
+
+ if (ptr.data) {
+ node = ptr.data;
+ }
+ else if (snode && snode->edittree) {
+ node = nodeGetActive(snode->edittree);
+ }
+
+ if (!node || node->type != CMP_NODE_OUTPUT_FILE) {
+ return OPERATOR_CANCELLED;
+ }
+
+ nimf = node->storage;
+
+ sock = BLI_findlink(&node->inputs, nimf->active_input);
+ if (!sock) {
+ return OPERATOR_CANCELLED;
+ }
+
+ direction = RNA_enum_get(op->ptr, "direction");
+
+ if (direction == 1) {
+ bNodeSocket *before = sock->prev;
+ if (!before) {
+ return OPERATOR_CANCELLED;
+ }
+ BLI_remlink(&node->inputs, sock);
+ BLI_insertlinkbefore(&node->inputs, before, sock);
+ nimf->active_input--;
+ }
+ else {
+ bNodeSocket *after = sock->next;
+ if (!after) {
+ return OPERATOR_CANCELLED;
+ }
+ BLI_remlink(&node->inputs, sock);
+ BLI_insertlinkafter(&node->inputs, after, sock);
+ nimf->active_input++;
+ }
+
+ snode_notify(C, snode);
+
+ return OPERATOR_FINISHED;
}
void NODE_OT_output_file_move_active_socket(wmOperatorType *ot)
{
- static const EnumPropertyItem direction_items[] = {
- {1, "UP", 0, "Up", ""},
- {2, "DOWN", 0, "Down", ""},
- { 0, NULL, 0, NULL, NULL }
- };
+ static const EnumPropertyItem direction_items[] = {
+ {1, "UP", 0, "Up", ""}, {2, "DOWN", 0, "Down", ""}, {0, NULL, 0, NULL, NULL}};
- /* identifiers */
- ot->name = "Move File Node Socket";
- ot->description = "Move the active input of a file output node up or down the list";
- ot->idname = "NODE_OT_output_file_move_active_socket";
+ /* identifiers */
+ ot->name = "Move File Node Socket";
+ ot->description = "Move the active input of a file output node up or down the list";
+ ot->idname = "NODE_OT_output_file_move_active_socket";
- /* callbacks */
- ot->exec = node_output_file_move_active_socket_exec;
- ot->poll = composite_node_editable;
+ /* callbacks */
+ ot->exec = node_output_file_move_active_socket_exec;
+ ot->poll = composite_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_enum(ot->srna, "direction", direction_items, 2, "Direction", "");
+ RNA_def_enum(ot->srna, "direction", direction_items, 2, "Direction", "");
}
/* ****************** Copy Node Color ******************* */
static int node_copy_color_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree = snode->edittree;
- bNode *node, *tnode;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNode *node, *tnode;
- if (!ntree) {
- return OPERATOR_CANCELLED;
- }
- node = nodeGetActive(ntree);
- if (!node) {
- return OPERATOR_CANCELLED;
- }
+ if (!ntree) {
+ return OPERATOR_CANCELLED;
+ }
+ node = nodeGetActive(ntree);
+ if (!node) {
+ return OPERATOR_CANCELLED;
+ }
- for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
- if (tnode->flag & NODE_SELECT && tnode != node) {
- if (node->flag & NODE_CUSTOM_COLOR) {
- tnode->flag |= NODE_CUSTOM_COLOR;
- copy_v3_v3(tnode->color, node->color);
- }
- else {
- tnode->flag &= ~NODE_CUSTOM_COLOR;
- }
- }
- }
+ for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
+ if (tnode->flag & NODE_SELECT && tnode != node) {
+ if (node->flag & NODE_CUSTOM_COLOR) {
+ tnode->flag |= NODE_CUSTOM_COLOR;
+ copy_v3_v3(tnode->color, node->color);
+ }
+ else {
+ tnode->flag &= ~NODE_CUSTOM_COLOR;
+ }
+ }
+ }
- ED_node_sort(ntree);
- WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+ ED_node_sort(ntree);
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_node_copy_color(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Color";
- ot->description = "Copy color to all selected nodes";
- ot->idname = "NODE_OT_node_copy_color";
+ /* identifiers */
+ ot->name = "Copy Color";
+ ot->description = "Copy color to all selected nodes";
+ ot->idname = "NODE_OT_node_copy_color";
- /* api callbacks */
- ot->exec = node_copy_color_exec;
- ot->poll = ED_operator_node_editable;
+ /* api callbacks */
+ ot->exec = node_copy_color_exec;
+ ot->poll = ED_operator_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** Copy to clipboard ******************* */
static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree = snode->edittree;
- bNode *node;
- bNodeLink *link, *newlink;
-
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
-
- /* clear current clipboard */
- BKE_node_clipboard_clear();
- BKE_node_clipboard_init(ntree);
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->flag & SELECT) {
- /* No ID refcounting, this node is virtual, detached from any actual Blender data currently. */
- bNode *new_node = BKE_node_copy_ex(NULL, node, LIB_ID_CREATE_NO_USER_REFCOUNT);
- BKE_node_clipboard_add_node(new_node);
- }
- }
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->flag & SELECT) {
- bNode *new_node = node->new_node;
-
- /* ensure valid pointers */
- if (new_node->parent) {
- /* parent pointer must be redirected to new node or detached if parent is
- * not copied */
- if (new_node->parent->flag & NODE_SELECT) {
- new_node->parent = new_node->parent->new_node;
- }
- else {
- nodeDetachNode(new_node);
- }
- }
- }
- }
-
- /* copy links between selected nodes
- * NB: this depends on correct node->new_node and sock->new_sock pointers from above copy!
- */
- for (link = ntree->links.first; link; link = link->next) {
- /* This creates new links between copied nodes. */
- if (link->tonode && (link->tonode->flag & NODE_SELECT) &&
- link->fromnode && (link->fromnode->flag & NODE_SELECT))
- {
- newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink");
- newlink->flag = link->flag;
- newlink->tonode = link->tonode->new_node;
- newlink->tosock = link->tosock->new_sock;
- newlink->fromnode = link->fromnode->new_node;
- newlink->fromsock = link->fromsock->new_sock;
-
- BKE_node_clipboard_add_link(newlink);
- }
- }
-
- return OPERATOR_FINISHED;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNode *node;
+ bNodeLink *link, *newlink;
+
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+
+ /* clear current clipboard */
+ BKE_node_clipboard_clear();
+ BKE_node_clipboard_init(ntree);
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->flag & SELECT) {
+ /* No ID refcounting, this node is virtual, detached from any actual Blender data currently. */
+ bNode *new_node = BKE_node_copy_ex(NULL, node, LIB_ID_CREATE_NO_USER_REFCOUNT);
+ BKE_node_clipboard_add_node(new_node);
+ }
+ }
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->flag & SELECT) {
+ bNode *new_node = node->new_node;
+
+ /* ensure valid pointers */
+ if (new_node->parent) {
+ /* parent pointer must be redirected to new node or detached if parent is
+ * not copied */
+ if (new_node->parent->flag & NODE_SELECT) {
+ new_node->parent = new_node->parent->new_node;
+ }
+ else {
+ nodeDetachNode(new_node);
+ }
+ }
+ }
+ }
+
+ /* copy links between selected nodes
+ * NB: this depends on correct node->new_node and sock->new_sock pointers from above copy!
+ */
+ for (link = ntree->links.first; link; link = link->next) {
+ /* This creates new links between copied nodes. */
+ if (link->tonode && (link->tonode->flag & NODE_SELECT) && link->fromnode &&
+ (link->fromnode->flag & NODE_SELECT)) {
+ newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink");
+ newlink->flag = link->flag;
+ newlink->tonode = link->tonode->new_node;
+ newlink->tosock = link->tosock->new_sock;
+ newlink->fromnode = link->fromnode->new_node;
+ newlink->fromsock = link->fromsock->new_sock;
+
+ BKE_node_clipboard_add_link(newlink);
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void NODE_OT_clipboard_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy to Clipboard";
- ot->description = "Copies selected nodes to the clipboard";
- ot->idname = "NODE_OT_clipboard_copy";
+ /* identifiers */
+ ot->name = "Copy to Clipboard";
+ ot->description = "Copies selected nodes to the clipboard";
+ ot->idname = "NODE_OT_clipboard_copy";
- /* api callbacks */
- ot->exec = node_clipboard_copy_exec;
- ot->poll = ED_operator_node_active;
+ /* api callbacks */
+ ot->exec = node_clipboard_copy_exec;
+ ot->poll = ED_operator_node_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** Paste from clipboard ******************* */
static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree = snode->edittree;
- const ListBase *clipboard_nodes_lb;
- const ListBase *clipboard_links_lb;
- bNode *node;
- bNodeLink *link;
- int num_nodes;
- float center[2];
- bool is_clipboard_valid, all_nodes_valid;
-
- /* validate pointers in the clipboard */
- is_clipboard_valid = BKE_node_clipboard_validate();
- clipboard_nodes_lb = BKE_node_clipboard_get_nodes();
- clipboard_links_lb = BKE_node_clipboard_get_links();
-
- if (BLI_listbase_is_empty(clipboard_nodes_lb)) {
- BKE_report(op->reports, RPT_ERROR, "Clipboard is empty");
- return OPERATOR_CANCELLED;
- }
-
- if (BKE_node_clipboard_get_type() != ntree->type) {
- BKE_report(op->reports, RPT_ERROR, "Clipboard nodes are an incompatible type");
- return OPERATOR_CANCELLED;
- }
-
- /* only warn */
- if (is_clipboard_valid == false) {
- BKE_report(op->reports, RPT_WARNING, "Some nodes references could not be restored, will be left empty");
- }
-
- /* make sure all clipboard nodes would be valid in the target tree */
- all_nodes_valid = true;
- for (node = clipboard_nodes_lb->first; node; node = node->next) {
- if (!node->typeinfo->poll_instance || !node->typeinfo->poll_instance(node, ntree)) {
- all_nodes_valid = false;
- BKE_reportf(op->reports, RPT_ERROR, "Cannot add node %s into node tree %s", node->name, ntree->id.name + 2);
- }
- }
- if (!all_nodes_valid) {
- return OPERATOR_CANCELLED;
- }
-
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
-
- /* deselect old nodes */
- node_deselect_all(snode);
-
- /* calculate "barycenter" for placing on mouse cursor */
- zero_v2(center);
- for (node = clipboard_nodes_lb->first, num_nodes = 0; node; node = node->next, num_nodes++) {
- center[0] += BLI_rctf_cent_x(&node->totr);
- center[1] += BLI_rctf_cent_y(&node->totr);
- }
- mul_v2_fl(center, 1.0 / num_nodes);
-
- /* copy nodes from clipboard */
- for (node = clipboard_nodes_lb->first; node; node = node->next) {
- bNode *new_node = BKE_node_copy_ex(ntree, node, LIB_ID_COPY_DEFAULT);
-
- /* pasted nodes are selected */
- nodeSetSelected(new_node, true);
- }
-
- /* reparent copied nodes */
- for (node = clipboard_nodes_lb->first; node; node = node->next) {
- bNode *new_node = node->new_node;
- if (new_node->parent) {
- new_node->parent = new_node->parent->new_node;
- }
- }
-
- for (link = clipboard_links_lb->first; link; link = link->next) {
- nodeAddLink(ntree, link->fromnode->new_node, link->fromsock->new_sock,
- link->tonode->new_node, link->tosock->new_sock);
- }
-
- ntreeUpdateTree(CTX_data_main(C), snode->edittree);
-
- snode_notify(C, snode);
- snode_dag_update(C, snode);
-
- return OPERATOR_FINISHED;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ const ListBase *clipboard_nodes_lb;
+ const ListBase *clipboard_links_lb;
+ bNode *node;
+ bNodeLink *link;
+ int num_nodes;
+ float center[2];
+ bool is_clipboard_valid, all_nodes_valid;
+
+ /* validate pointers in the clipboard */
+ is_clipboard_valid = BKE_node_clipboard_validate();
+ clipboard_nodes_lb = BKE_node_clipboard_get_nodes();
+ clipboard_links_lb = BKE_node_clipboard_get_links();
+
+ if (BLI_listbase_is_empty(clipboard_nodes_lb)) {
+ BKE_report(op->reports, RPT_ERROR, "Clipboard is empty");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (BKE_node_clipboard_get_type() != ntree->type) {
+ BKE_report(op->reports, RPT_ERROR, "Clipboard nodes are an incompatible type");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* only warn */
+ if (is_clipboard_valid == false) {
+ BKE_report(op->reports,
+ RPT_WARNING,
+ "Some nodes references could not be restored, will be left empty");
+ }
+
+ /* make sure all clipboard nodes would be valid in the target tree */
+ all_nodes_valid = true;
+ for (node = clipboard_nodes_lb->first; node; node = node->next) {
+ if (!node->typeinfo->poll_instance || !node->typeinfo->poll_instance(node, ntree)) {
+ all_nodes_valid = false;
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "Cannot add node %s into node tree %s",
+ node->name,
+ ntree->id.name + 2);
+ }
+ }
+ if (!all_nodes_valid) {
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+
+ /* deselect old nodes */
+ node_deselect_all(snode);
+
+ /* calculate "barycenter" for placing on mouse cursor */
+ zero_v2(center);
+ for (node = clipboard_nodes_lb->first, num_nodes = 0; node; node = node->next, num_nodes++) {
+ center[0] += BLI_rctf_cent_x(&node->totr);
+ center[1] += BLI_rctf_cent_y(&node->totr);
+ }
+ mul_v2_fl(center, 1.0 / num_nodes);
+
+ /* copy nodes from clipboard */
+ for (node = clipboard_nodes_lb->first; node; node = node->next) {
+ bNode *new_node = BKE_node_copy_ex(ntree, node, LIB_ID_COPY_DEFAULT);
+
+ /* pasted nodes are selected */
+ nodeSetSelected(new_node, true);
+ }
+
+ /* reparent copied nodes */
+ for (node = clipboard_nodes_lb->first; node; node = node->next) {
+ bNode *new_node = node->new_node;
+ if (new_node->parent) {
+ new_node->parent = new_node->parent->new_node;
+ }
+ }
+
+ for (link = clipboard_links_lb->first; link; link = link->next) {
+ nodeAddLink(ntree,
+ link->fromnode->new_node,
+ link->fromsock->new_sock,
+ link->tonode->new_node,
+ link->tosock->new_sock);
+ }
+
+ ntreeUpdateTree(CTX_data_main(C), snode->edittree);
+
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
+
+ return OPERATOR_FINISHED;
}
void NODE_OT_clipboard_paste(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Paste from Clipboard";
- ot->description = "Pastes nodes from the clipboard to the active node tree";
- ot->idname = "NODE_OT_clipboard_paste";
+ /* identifiers */
+ ot->name = "Paste from Clipboard";
+ ot->description = "Pastes nodes from the clipboard to the active node tree";
+ ot->idname = "NODE_OT_clipboard_paste";
- /* api callbacks */
- ot->exec = node_clipboard_paste_exec;
- ot->poll = ED_operator_node_editable;
+ /* api callbacks */
+ ot->exec = node_clipboard_paste_exec;
+ ot->poll = ED_operator_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** Add interface socket operator *********************/
static bNodeSocket *ntree_get_active_interface_socket(ListBase *lb)
{
- bNodeSocket *sock;
- for (sock = lb->first; sock; sock = sock->next) {
- if (sock->flag & SELECT) {
- return sock;
- }
- }
- return NULL;
+ bNodeSocket *sock;
+ for (sock = lb->first; sock; sock = sock->next) {
+ if (sock->flag & SELECT) {
+ return sock;
+ }
+ }
+ return NULL;
}
static int ntree_socket_add_exec(bContext *C, wmOperator *op)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree = snode->edittree;
- int in_out = RNA_enum_get(op->ptr, "in_out");
- PointerRNA ntree_ptr;
- bNodeSocket *sock, *tsock, *active_sock;
- const char *default_name;
-
- RNA_id_pointer_create((ID *)ntree, &ntree_ptr);
-
- if (in_out == SOCK_IN) {
- active_sock = ntree_get_active_interface_socket(&ntree->inputs);
- default_name = "Input";
- }
- else {
- active_sock = ntree_get_active_interface_socket(&ntree->outputs);
- default_name = "Output";
- }
-
- if (active_sock) {
- /* insert a copy of the active socket right after it */
- sock = ntreeInsertSocketInterface(ntree, in_out, active_sock->idname, active_sock->next, active_sock->name);
- /* XXX this only works for actual sockets, not interface templates! */
- /*nodeSocketCopyValue(sock, &ntree_ptr, active_sock, &ntree_ptr);*/
- }
- else {
- /* XXX TODO define default socket type for a tree! */
- sock = ntreeAddSocketInterface(ntree, in_out, "NodeSocketFloat", default_name);
- }
-
- /* deactivate sockets (has to check both lists) */
- for (tsock = ntree->inputs.first; tsock; tsock = tsock->next) {
- tsock->flag &= ~SELECT;
- }
- for (tsock = ntree->outputs.first; tsock; tsock = tsock->next) {
- tsock->flag &= ~SELECT;
- }
- /* make the new socket active */
- sock->flag |= SELECT;
-
- ntreeUpdateTree(CTX_data_main(C), ntree);
-
- snode_notify(C, snode);
- snode_dag_update(C, snode);
-
- WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
-
- return OPERATOR_FINISHED;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ int in_out = RNA_enum_get(op->ptr, "in_out");
+ PointerRNA ntree_ptr;
+ bNodeSocket *sock, *tsock, *active_sock;
+ const char *default_name;
+
+ RNA_id_pointer_create((ID *)ntree, &ntree_ptr);
+
+ if (in_out == SOCK_IN) {
+ active_sock = ntree_get_active_interface_socket(&ntree->inputs);
+ default_name = "Input";
+ }
+ else {
+ active_sock = ntree_get_active_interface_socket(&ntree->outputs);
+ default_name = "Output";
+ }
+
+ if (active_sock) {
+ /* insert a copy of the active socket right after it */
+ sock = ntreeInsertSocketInterface(
+ ntree, in_out, active_sock->idname, active_sock->next, active_sock->name);
+ /* XXX this only works for actual sockets, not interface templates! */
+ /*nodeSocketCopyValue(sock, &ntree_ptr, active_sock, &ntree_ptr);*/
+ }
+ else {
+ /* XXX TODO define default socket type for a tree! */
+ sock = ntreeAddSocketInterface(ntree, in_out, "NodeSocketFloat", default_name);
+ }
+
+ /* deactivate sockets (has to check both lists) */
+ for (tsock = ntree->inputs.first; tsock; tsock = tsock->next) {
+ tsock->flag &= ~SELECT;
+ }
+ for (tsock = ntree->outputs.first; tsock; tsock = tsock->next) {
+ tsock->flag &= ~SELECT;
+ }
+ /* make the new socket active */
+ sock->flag |= SELECT;
+
+ ntreeUpdateTree(CTX_data_main(C), ntree);
+
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
+
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+
+ return OPERATOR_FINISHED;
}
void NODE_OT_tree_socket_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Node Tree Interface Socket";
- ot->description = "Add an input or output socket to the current node tree";
- ot->idname = "NODE_OT_tree_socket_add";
+ /* identifiers */
+ ot->name = "Add Node Tree Interface Socket";
+ ot->description = "Add an input or output socket to the current node tree";
+ ot->idname = "NODE_OT_tree_socket_add";
- /* api callbacks */
- ot->exec = ntree_socket_add_exec;
- ot->poll = ED_operator_node_editable;
+ /* api callbacks */
+ ot->exec = ntree_socket_add_exec;
+ ot->poll = ED_operator_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", "");
+ RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", "");
}
/********************** Remove interface socket operator *********************/
static int ntree_socket_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree = snode->edittree;
- bNodeSocket *iosock, *active_sock;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNodeSocket *iosock, *active_sock;
- iosock = ntree_get_active_interface_socket(&ntree->inputs);
- if (!iosock) {
- iosock = ntree_get_active_interface_socket(&ntree->outputs);
- }
- if (!iosock) {
- return OPERATOR_CANCELLED;
- }
+ iosock = ntree_get_active_interface_socket(&ntree->inputs);
+ if (!iosock) {
+ iosock = ntree_get_active_interface_socket(&ntree->outputs);
+ }
+ if (!iosock) {
+ return OPERATOR_CANCELLED;
+ }
- /* preferably next socket becomes active, otherwise try previous socket */
- active_sock = (iosock->next ? iosock->next : iosock->prev);
- ntreeRemoveSocketInterface(ntree, iosock);
+ /* preferably next socket becomes active, otherwise try previous socket */
+ active_sock = (iosock->next ? iosock->next : iosock->prev);
+ ntreeRemoveSocketInterface(ntree, iosock);
- /* set active socket */
- if (active_sock) {
- active_sock->flag |= SELECT;
- }
+ /* set active socket */
+ if (active_sock) {
+ active_sock->flag |= SELECT;
+ }
- ntreeUpdateTree(CTX_data_main(C), ntree);
+ ntreeUpdateTree(CTX_data_main(C), ntree);
- snode_notify(C, snode);
- snode_dag_update(C, snode);
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
- WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_tree_socket_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Node Tree Interface Socket";
- ot->description = "Remove an input or output socket to the current node tree";
- ot->idname = "NODE_OT_tree_socket_remove";
+ /* identifiers */
+ ot->name = "Remove Node Tree Interface Socket";
+ ot->description = "Remove an input or output socket to the current node tree";
+ ot->idname = "NODE_OT_tree_socket_remove";
- /* api callbacks */
- ot->exec = ntree_socket_remove_exec;
- ot->poll = ED_operator_node_editable;
+ /* api callbacks */
+ ot->exec = ntree_socket_remove_exec;
+ ot->poll = ED_operator_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** Move interface socket operator *********************/
static const EnumPropertyItem move_direction_items[] = {
- { 1, "UP", 0, "Up", "" },
- { 2, "DOWN", 0, "Down", "" },
- { 0, NULL, 0, NULL, NULL },
+ {1, "UP", 0, "Up", ""},
+ {2, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int ntree_socket_move_exec(bContext *C, wmOperator *op)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree = snode->edittree;
- int direction = RNA_enum_get(op->ptr, "direction");
- bNodeSocket *iosock;
- ListBase *lb;
-
- lb = &ntree->inputs;
- iosock = ntree_get_active_interface_socket(lb);
- if (!iosock) {
- lb = &ntree->outputs;
- iosock = ntree_get_active_interface_socket(lb);
- }
- if (!iosock) {
- return OPERATOR_CANCELLED;
- }
-
- switch (direction) {
- case 1:
- { /* up */
- bNodeSocket *before = iosock->prev;
- BLI_remlink(lb, iosock);
- if (before) {
- BLI_insertlinkbefore(lb, before, iosock);
- }
- else {
- BLI_addhead(lb, iosock);
- }
- break;
- }
- case 2:
- { /* down */
- bNodeSocket *after = iosock->next;
- BLI_remlink(lb, iosock);
- if (after) {
- BLI_insertlinkafter(lb, after, iosock);
- }
- else {
- BLI_addtail(lb, iosock);
- }
- break;
- }
- }
-
- ntreeUpdateTree(CTX_data_main(C), ntree);
-
- snode_notify(C, snode);
- snode_dag_update(C, snode);
-
- WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
-
- return OPERATOR_FINISHED;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ int direction = RNA_enum_get(op->ptr, "direction");
+ bNodeSocket *iosock;
+ ListBase *lb;
+
+ lb = &ntree->inputs;
+ iosock = ntree_get_active_interface_socket(lb);
+ if (!iosock) {
+ lb = &ntree->outputs;
+ iosock = ntree_get_active_interface_socket(lb);
+ }
+ if (!iosock) {
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (direction) {
+ case 1: { /* up */
+ bNodeSocket *before = iosock->prev;
+ BLI_remlink(lb, iosock);
+ if (before) {
+ BLI_insertlinkbefore(lb, before, iosock);
+ }
+ else {
+ BLI_addhead(lb, iosock);
+ }
+ break;
+ }
+ case 2: { /* down */
+ bNodeSocket *after = iosock->next;
+ BLI_remlink(lb, iosock);
+ if (after) {
+ BLI_insertlinkafter(lb, after, iosock);
+ }
+ else {
+ BLI_addtail(lb, iosock);
+ }
+ break;
+ }
+ }
+
+ ntreeUpdateTree(CTX_data_main(C), ntree);
+
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
+
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+
+ return OPERATOR_FINISHED;
}
void NODE_OT_tree_socket_move(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move Node Tree Socket";
- ot->description = "Move a socket up or down in the current node tree's sockets stack";
- ot->idname = "NODE_OT_tree_socket_move";
+ /* identifiers */
+ ot->name = "Move Node Tree Socket";
+ ot->description = "Move a socket up or down in the current node tree's sockets stack";
+ ot->idname = "NODE_OT_tree_socket_move";
- /* api callbacks */
- ot->exec = ntree_socket_move_exec;
- ot->poll = ED_operator_node_editable;
+ /* api callbacks */
+ ot->exec = ntree_socket_move_exec;
+ ot->poll = ED_operator_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_enum(ot->srna, "direction", move_direction_items, 1, "Direction", "");
+ RNA_def_enum(ot->srna, "direction", move_direction_items, 1, "Direction", "");
}
/* ********************** Shader Script Update ******************/
static bool node_shader_script_update_poll(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- RenderEngineType *type = RE_engines_find(scene->r.engine);
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node;
- Text *text;
+ Scene *scene = CTX_data_scene(C);
+ RenderEngineType *type = RE_engines_find(scene->r.engine);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node;
+ Text *text;
- /* test if we have a render engine that supports shaders scripts */
- if (!(type && type->update_script_node)) {
- return 0;
- }
+ /* test if we have a render engine that supports shaders scripts */
+ if (!(type && type->update_script_node)) {
+ return 0;
+ }
- /* see if we have a shader script node in context */
- node = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript).data;
+ /* see if we have a shader script node in context */
+ node = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript).data;
- if (!node && snode && snode->edittree) {
- node = nodeGetActive(snode->edittree);
- }
+ if (!node && snode && snode->edittree) {
+ node = nodeGetActive(snode->edittree);
+ }
- if (node && node->type == SH_NODE_SCRIPT) {
- NodeShaderScript *nss = node->storage;
+ if (node && node->type == SH_NODE_SCRIPT) {
+ NodeShaderScript *nss = node->storage;
- if (node->id || nss->filepath[0]) {
- return ED_operator_node_editable(C);
- }
- }
+ if (node->id || nss->filepath[0]) {
+ return ED_operator_node_editable(C);
+ }
+ }
- /* see if we have a text datablock in context */
- text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
- if (text) {
- return 1;
- }
+ /* see if we have a text datablock in context */
+ text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
+ if (text) {
+ return 1;
+ }
- /* we don't check if text datablock is actually in use, too slow for poll */
+ /* we don't check if text datablock is actually in use, too slow for poll */
- return 0;
+ return 0;
}
/* recursively check for script nodes in groups using this text and update */
-static bool node_shader_script_update_text_recursive(RenderEngine *engine, RenderEngineType *type, bNodeTree *ntree, Text *text)
+static bool node_shader_script_update_text_recursive(RenderEngine *engine,
+ RenderEngineType *type,
+ bNodeTree *ntree,
+ Text *text)
{
- bool found = false;
- bNode *node;
+ bool found = false;
+ bNode *node;
- ntree->done = true;
+ ntree->done = true;
- /* update each script that is using this text datablock */
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == NODE_GROUP) {
- bNodeTree *ngroup = (bNodeTree *)node->id;
- if (ngroup && !ngroup->done) {
- found |= node_shader_script_update_text_recursive(engine, type, ngroup, text);
- }
- }
- else if (node->type == SH_NODE_SCRIPT && node->id == &text->id) {
- type->update_script_node(engine, ntree, node);
- found = true;
- }
- }
+ /* update each script that is using this text datablock */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP) {
+ bNodeTree *ngroup = (bNodeTree *)node->id;
+ if (ngroup && !ngroup->done) {
+ found |= node_shader_script_update_text_recursive(engine, type, ngroup, text);
+ }
+ }
+ else if (node->type == SH_NODE_SCRIPT && node->id == &text->id) {
+ type->update_script_node(engine, ntree, node);
+ found = true;
+ }
+ }
- return found;
+ return found;
}
static int node_shader_script_update_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- PointerRNA nodeptr = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript);
- bNodeTree *ntree_base = NULL;
- bNode *node = NULL;
- RenderEngine *engine;
- RenderEngineType *type;
- bool found = false;
-
- /* setup render engine */
- type = RE_engines_find(scene->r.engine);
- engine = RE_engine_create(type);
- engine->reports = op->reports;
-
- /* get node */
- if (nodeptr.data) {
- ntree_base = nodeptr.id.data;
- node = nodeptr.data;
- }
- else if (snode && snode->edittree) {
- ntree_base = snode->edittree;
- node = nodeGetActive(snode->edittree);
- }
-
- if (node) {
- /* update single node */
- type->update_script_node(engine, ntree_base, node);
-
- found = true;
- }
- else {
- /* update all nodes using text datablock */
- Text *text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
-
- if (text) {
- /* clear flags for recursion check */
- FOREACH_NODETREE_BEGIN(bmain, ntree, id) {
- if (ntree->type == NTREE_SHADER) {
- ntree->done = false;
- }
- } FOREACH_NODETREE_END;
-
- FOREACH_NODETREE_BEGIN(bmain, ntree, id) {
- if (ntree->type == NTREE_SHADER) {
- if (!ntree->done) {
- found |= node_shader_script_update_text_recursive(engine, type, ntree, text);
- }
- }
- } FOREACH_NODETREE_END;
-
- if (!found) {
- BKE_report(op->reports, RPT_INFO, "Text not used by any node, no update done");
- }
- }
- }
-
- RE_engine_free(engine);
-
- return (found) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ PointerRNA nodeptr = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript);
+ bNodeTree *ntree_base = NULL;
+ bNode *node = NULL;
+ RenderEngine *engine;
+ RenderEngineType *type;
+ bool found = false;
+
+ /* setup render engine */
+ type = RE_engines_find(scene->r.engine);
+ engine = RE_engine_create(type);
+ engine->reports = op->reports;
+
+ /* get node */
+ if (nodeptr.data) {
+ ntree_base = nodeptr.id.data;
+ node = nodeptr.data;
+ }
+ else if (snode && snode->edittree) {
+ ntree_base = snode->edittree;
+ node = nodeGetActive(snode->edittree);
+ }
+
+ if (node) {
+ /* update single node */
+ type->update_script_node(engine, ntree_base, node);
+
+ found = true;
+ }
+ else {
+ /* update all nodes using text datablock */
+ Text *text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
+
+ if (text) {
+ /* clear flags for recursion check */
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ ntree->done = false;
+ }
+ }
+ FOREACH_NODETREE_END;
+
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ if (!ntree->done) {
+ found |= node_shader_script_update_text_recursive(engine, type, ntree, text);
+ }
+ }
+ }
+ FOREACH_NODETREE_END;
+
+ if (!found) {
+ BKE_report(op->reports, RPT_INFO, "Text not used by any node, no update done");
+ }
+ }
+ }
+
+ RE_engine_free(engine);
+
+ return (found) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void NODE_OT_shader_script_update(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Script Node Update";
- ot->description = "Update shader script node with new sockets and options from the script";
- ot->idname = "NODE_OT_shader_script_update";
+ /* identifiers */
+ ot->name = "Script Node Update";
+ ot->description = "Update shader script node with new sockets and options from the script";
+ ot->idname = "NODE_OT_shader_script_update";
- /* api callbacks */
- ot->exec = node_shader_script_update_exec;
- ot->poll = node_shader_script_update_poll;
+ /* api callbacks */
+ ot->exec = node_shader_script_update_exec;
+ ot->poll = node_shader_script_update_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************** Viewer border ******************/
-static void viewer_border_corner_to_backdrop(SpaceNode *snode, ARegion *ar, int x, int y,
- int backdrop_width, int backdrop_height,
- float *fx, float *fy)
+static void viewer_border_corner_to_backdrop(SpaceNode *snode,
+ ARegion *ar,
+ int x,
+ int y,
+ int backdrop_width,
+ int backdrop_height,
+ float *fx,
+ float *fy)
{
- float bufx, bufy;
+ float bufx, bufy;
- bufx = backdrop_width * snode->zoom;
- bufy = backdrop_height * snode->zoom;
+ 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 * 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);
}
static int viewer_border_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Image *ima;
- void *lock;
- ImBuf *ibuf;
+ Main *bmain = CTX_data_main(C);
+ Image *ima;
+ void *lock;
+ ImBuf *ibuf;
- ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
- ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
- ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+ ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
- if (ibuf) {
- ARegion *ar = CTX_wm_region(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *btree = snode->nodetree;
- rcti rect;
- rctf rectf;
+ if (ibuf) {
+ ARegion *ar = CTX_wm_region(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *btree = snode->nodetree;
+ rcti rect;
+ rctf rectf;
- /* get border from operator */
- WM_operator_properties_border_to_rcti(op, &rect);
+ /* get border from operator */
+ WM_operator_properties_border_to_rcti(op, &rect);
- /* 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);
+ /* 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);
- viewer_border_corner_to_backdrop(snode, ar, rect.xmax, rect.ymax, ibuf->x, ibuf->y,
- &rectf.xmax, &rectf.ymax);
+ viewer_border_corner_to_backdrop(
+ snode, ar, rect.xmax, rect.ymax, ibuf->x, ibuf->y, &rectf.xmax, &rectf.ymax);
- /* clamp coordinates */
- rectf.xmin = max_ff(rectf.xmin, 0.0f);
- rectf.ymin = max_ff(rectf.ymin, 0.0f);
- rectf.xmax = min_ff(rectf.xmax, 1.0f);
- rectf.ymax = min_ff(rectf.ymax, 1.0f);
+ /* clamp coordinates */
+ rectf.xmin = max_ff(rectf.xmin, 0.0f);
+ rectf.ymin = max_ff(rectf.ymin, 0.0f);
+ rectf.xmax = min_ff(rectf.xmax, 1.0f);
+ rectf.ymax = min_ff(rectf.ymax, 1.0f);
- if (rectf.xmin < rectf.xmax && rectf.ymin < rectf.ymax) {
- btree->viewer_border = rectf;
+ if (rectf.xmin < rectf.xmax && rectf.ymin < rectf.ymax) {
+ btree->viewer_border = rectf;
- if (rectf.xmin == 0.0f && rectf.ymin == 0.0f &&
- rectf.xmax == 1.0f && rectf.ymax == 1.0f)
- {
- btree->flag &= ~NTREE_VIEWER_BORDER;
- }
- else {
- btree->flag |= NTREE_VIEWER_BORDER;
- }
+ if (rectf.xmin == 0.0f && rectf.ymin == 0.0f && rectf.xmax == 1.0f && rectf.ymax == 1.0f) {
+ btree->flag &= ~NTREE_VIEWER_BORDER;
+ }
+ else {
+ btree->flag |= NTREE_VIEWER_BORDER;
+ }
- snode_notify(C, snode);
- WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
- }
- else {
- btree->flag &= ~NTREE_VIEWER_BORDER;
- }
- }
+ snode_notify(C, snode);
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+ }
+ else {
+ btree->flag &= ~NTREE_VIEWER_BORDER;
+ }
+ }
- BKE_image_release_ibuf(ima, ibuf, lock);
+ BKE_image_release_ibuf(ima, ibuf, lock);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_viewer_border(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Viewer Border";
- ot->description = "Set the boundaries for viewer operations";
- ot->idname = "NODE_OT_viewer_border";
+ /* identifiers */
+ ot->name = "Viewer Border";
+ ot->description = "Set the boundaries for viewer operations";
+ ot->idname = "NODE_OT_viewer_border";
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = viewer_border_exec;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
- ot->poll = composite_node_active;
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = viewer_border_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
+ ot->poll = composite_node_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_gesture_box_select(ot);
+ /* properties */
+ WM_operator_properties_gesture_box_select(ot);
}
static int clear_viewer_border_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *btree = snode->nodetree;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *btree = snode->nodetree;
- btree->flag &= ~NTREE_VIEWER_BORDER;
- snode_notify(C, snode);
- WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+ btree->flag &= ~NTREE_VIEWER_BORDER;
+ snode_notify(C, snode);
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_clear_viewer_border(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Viewer Border";
- ot->description = "Clear the boundaries for viewer operations";
- ot->idname = "NODE_OT_clear_viewer_border";
+ /* identifiers */
+ ot->name = "Clear Viewer Border";
+ ot->description = "Clear the boundaries for viewer operations";
+ ot->idname = "NODE_OT_clear_viewer_border";
- /* api callbacks */
- ot->exec = clear_viewer_border_exec;
- ot->poll = composite_node_active;
+ /* api callbacks */
+ ot->exec = clear_viewer_border_exec;
+ ot->poll = composite_node_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** Cryptomatte Add Socket ******************* */
static int node_cryptomatte_add_socket_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
- PointerRNA ptr = CTX_data_pointer_get(C, "node");
- bNodeTree *ntree = NULL;
- bNode *node = NULL;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ PointerRNA ptr = CTX_data_pointer_get(C, "node");
+ bNodeTree *ntree = NULL;
+ bNode *node = NULL;
- if (ptr.data) {
- node = ptr.data;
- ntree = ptr.id.data;
- }
- else if (snode && snode->edittree) {
- ntree = snode->edittree;
- node = nodeGetActive(snode->edittree);
- }
+ if (ptr.data) {
+ node = ptr.data;
+ ntree = ptr.id.data;
+ }
+ else if (snode && snode->edittree) {
+ ntree = snode->edittree;
+ node = nodeGetActive(snode->edittree);
+ }
- if (!node || node->type != CMP_NODE_CRYPTOMATTE) {
- return OPERATOR_CANCELLED;
- }
+ if (!node || node->type != CMP_NODE_CRYPTOMATTE) {
+ return OPERATOR_CANCELLED;
+ }
- ntreeCompositCryptomatteAddSocket(ntree, node);
+ ntreeCompositCryptomatteAddSocket(ntree, node);
- snode_notify(C, snode);
+ snode_notify(C, snode);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_cryptomatte_layer_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Cryptomatte Socket";
- ot->description = "Add a new input layer to a Cryptomatte node";
- ot->idname = "NODE_OT_cryptomatte_layer_add";
+ /* identifiers */
+ ot->name = "Add Cryptomatte Socket";
+ ot->description = "Add a new input layer to a Cryptomatte node";
+ ot->idname = "NODE_OT_cryptomatte_layer_add";
- /* callbacks */
- ot->exec = node_cryptomatte_add_socket_exec;
- ot->poll = composite_node_editable;
+ /* callbacks */
+ ot->exec = node_cryptomatte_add_socket_exec;
+ ot->poll = composite_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** Cryptomatte Remove Socket ******************* */
static int node_cryptomatte_remove_socket_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
- PointerRNA ptr = CTX_data_pointer_get(C, "node");
- bNodeTree *ntree = NULL;
- bNode *node = NULL;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ PointerRNA ptr = CTX_data_pointer_get(C, "node");
+ bNodeTree *ntree = NULL;
+ bNode *node = NULL;
- if (ptr.data) {
- node = ptr.data;
- ntree = ptr.id.data;
- }
- else if (snode && snode->edittree) {
- ntree = snode->edittree;
- node = nodeGetActive(snode->edittree);
- }
+ if (ptr.data) {
+ node = ptr.data;
+ ntree = ptr.id.data;
+ }
+ else if (snode && snode->edittree) {
+ ntree = snode->edittree;
+ node = nodeGetActive(snode->edittree);
+ }
- if (!node || node->type != CMP_NODE_CRYPTOMATTE) {
- return OPERATOR_CANCELLED;
- }
+ if (!node || node->type != CMP_NODE_CRYPTOMATTE) {
+ return OPERATOR_CANCELLED;
+ }
- if (!ntreeCompositCryptomatteRemoveSocket(ntree, node)) {
- return OPERATOR_CANCELLED;
- }
+ if (!ntreeCompositCryptomatteRemoveSocket(ntree, node)) {
+ return OPERATOR_CANCELLED;
+ }
- snode_notify(C, snode);
+ snode_notify(C, snode);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_cryptomatte_layer_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Cryptomatte Socket";
- ot->description = "Remove layer from a Cryptomatte node";
- ot->idname = "NODE_OT_cryptomatte_layer_remove";
+ /* identifiers */
+ ot->name = "Remove Cryptomatte Socket";
+ ot->description = "Remove layer from a Cryptomatte node";
+ ot->idname = "NODE_OT_cryptomatte_layer_remove";
- /* callbacks */
- ot->exec = node_cryptomatte_remove_socket_exec;
- ot->poll = composite_node_editable;
+ /* callbacks */
+ ot->exec = node_cryptomatte_remove_socket_exec;
+ ot->poll = composite_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/space_node/node_gizmo.c b/source/blender/editors/space_node/node_gizmo.c
index a511d6b9bd4..dbbef222250 100644
--- a/source/blender/editors/space_node/node_gizmo.c
+++ b/source/blender/editors/space_node/node_gizmo.c
@@ -43,153 +43,154 @@
#include "node_intern.h"
-
/* -------------------------------------------------------------------- */
/** \name Local Utilities
* \{ */
-static void node_gizmo_calc_matrix_space(
- const SpaceNode *snode, const ARegion *ar, float matrix_space[4][4])
+static void node_gizmo_calc_matrix_space(const SpaceNode *snode,
+ const ARegion *ar,
+ 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;
+ 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;
}
-static void node_gizmo_calc_matrix_space_with_image_dims(
- const SpaceNode *snode, const ARegion *ar, const float image_dims[2], float matrix_space[4][4])
+static void node_gizmo_calc_matrix_space_with_image_dims(const SpaceNode *snode,
+ const ARegion *ar,
+ 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);
+ 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);
}
/** \} */
-
-
/* -------------------------------------------------------------------- */
/** \name Backdrop Gizmo
* \{ */
-static void gizmo_node_backdrop_prop_matrix_get(
- const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
- void *value_p)
+static void gizmo_node_backdrop_prop_matrix_get(const wmGizmo *UNUSED(gz),
+ wmGizmoProperty *gz_prop,
+ void *value_p)
{
- float (*matrix)[4] = value_p;
- BLI_assert(gz_prop->type->array_length == 16);
- const SpaceNode *snode = gz_prop->custom_func.user_data;
- matrix[0][0] = snode->zoom;
- matrix[1][1] = snode->zoom;
- matrix[3][0] = snode->xof;
- matrix[3][1] = snode->yof;
+ float(*matrix)[4] = value_p;
+ BLI_assert(gz_prop->type->array_length == 16);
+ const SpaceNode *snode = gz_prop->custom_func.user_data;
+ matrix[0][0] = snode->zoom;
+ matrix[1][1] = snode->zoom;
+ matrix[3][0] = snode->xof;
+ matrix[3][1] = snode->yof;
}
-static void gizmo_node_backdrop_prop_matrix_set(
- const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
- const void *value_p)
+static void gizmo_node_backdrop_prop_matrix_set(const wmGizmo *UNUSED(gz),
+ wmGizmoProperty *gz_prop,
+ const void *value_p)
{
- const float (*matrix)[4] = value_p;
- BLI_assert(gz_prop->type->array_length == 16);
- SpaceNode *snode = gz_prop->custom_func.user_data;
- snode->zoom = matrix[0][0];
- snode->zoom = matrix[1][1];
- snode->xof = matrix[3][0];
- snode->yof = matrix[3][1];
+ const float(*matrix)[4] = value_p;
+ BLI_assert(gz_prop->type->array_length == 16);
+ SpaceNode *snode = gz_prop->custom_func.user_data;
+ snode->zoom = matrix[0][0];
+ snode->zoom = matrix[1][1];
+ snode->xof = matrix[3][0];
+ snode->yof = matrix[3][1];
}
static bool WIDGETGROUP_node_transform_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
- if ((snode->flag & SNODE_BACKDRAW) == 0) {
- return false;
- }
+ if ((snode->flag & SNODE_BACKDRAW) == 0) {
+ return false;
+ }
- if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) {
- bNode *node = nodeGetActive(snode->edittree);
+ if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) {
+ bNode *node = nodeGetActive(snode->edittree);
- if (node && ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
- return true;
- }
- }
+ if (node && ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
static void WIDGETGROUP_node_transform_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
+ wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
- wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
+ wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
- RNA_enum_set(wwrapper->gizmo->ptr, "transform",
- ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM);
+ RNA_enum_set(wwrapper->gizmo->ptr,
+ "transform",
+ ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM);
- gzgroup->customdata = wwrapper;
+ gzgroup->customdata = wwrapper;
}
static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- Main *bmain = CTX_data_main(C);
- wmGizmo *cage = ((wmGizmoWrapper *)gzgroup->customdata)->gizmo;
- const ARegion *ar = CTX_wm_region(C);
- /* center is always at the origin */
- const float origin[3] = {ar->winx / 2, ar->winy / 2};
-
- void *lock;
- Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
-
- if (ibuf) {
- const float dims[2] = {
- (ibuf->x > 0) ? ibuf->x : 64.0f,
- (ibuf->y > 0) ? ibuf->y : 64.0f,
- };
-
- RNA_float_set_array(cage->ptr, "dimensions", dims);
- WM_gizmo_set_matrix_location(cage, origin);
- WM_gizmo_set_flag(cage, WM_GIZMO_HIDDEN, false);
-
- /* need to set property here for undo. TODO would prefer to do this in _init */
- SpaceNode *snode = CTX_wm_space_node(C);
+ Main *bmain = CTX_data_main(C);
+ wmGizmo *cage = ((wmGizmoWrapper *)gzgroup->customdata)->gizmo;
+ const ARegion *ar = CTX_wm_region(C);
+ /* center is always at the origin */
+ const float origin[3] = {ar->winx / 2, ar->winy / 2};
+
+ void *lock;
+ Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+
+ if (ibuf) {
+ const float dims[2] = {
+ (ibuf->x > 0) ? ibuf->x : 64.0f,
+ (ibuf->y > 0) ? ibuf->y : 64.0f,
+ };
+
+ RNA_float_set_array(cage->ptr, "dimensions", dims);
+ WM_gizmo_set_matrix_location(cage, origin);
+ WM_gizmo_set_flag(cage, WM_GIZMO_HIDDEN, false);
+
+ /* need to set property here for undo. TODO would prefer to do this in _init */
+ SpaceNode *snode = CTX_wm_space_node(C);
#if 0
- PointerRNA nodeptr;
- RNA_pointer_create(snode->id, &RNA_SpaceNodeEditor, snode, &nodeptr);
- WM_gizmo_target_property_def_rna(cage, "offset", &nodeptr, "backdrop_offset", -1);
- WM_gizmo_target_property_def_rna(cage, "scale", &nodeptr, "backdrop_zoom", -1);
+ PointerRNA nodeptr;
+ RNA_pointer_create(snode->id, &RNA_SpaceNodeEditor, snode, &nodeptr);
+ WM_gizmo_target_property_def_rna(cage, "offset", &nodeptr, "backdrop_offset", -1);
+ WM_gizmo_target_property_def_rna(cage, "scale", &nodeptr, "backdrop_zoom", -1);
#endif
- WM_gizmo_target_property_def_func(
- cage, "matrix",
- &(const struct wmGizmoPropertyFnParams) {
- .value_get_fn = gizmo_node_backdrop_prop_matrix_get,
- .value_set_fn = gizmo_node_backdrop_prop_matrix_set,
- .range_get_fn = NULL,
- .user_data = snode,
- });
- }
- else {
- WM_gizmo_set_flag(cage, WM_GIZMO_HIDDEN, true);
- }
-
- BKE_image_release_ibuf(ima, ibuf, lock);
+ WM_gizmo_target_property_def_func(cage,
+ "matrix",
+ &(const struct wmGizmoPropertyFnParams){
+ .value_get_fn = gizmo_node_backdrop_prop_matrix_get,
+ .value_set_fn = gizmo_node_backdrop_prop_matrix_set,
+ .range_get_fn = NULL,
+ .user_data = snode,
+ });
+ }
+ else {
+ WM_gizmo_set_flag(cage, WM_GIZMO_HIDDEN, true);
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
}
void NODE_GGT_backdrop_transform(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Backdrop Transform Widget";
- gzgt->idname = "NODE_GGT_backdrop_transform";
+ gzgt->name = "Backdrop Transform Widget";
+ gzgt->idname = "NODE_GGT_backdrop_transform";
- gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
- gzgt->poll = WIDGETGROUP_node_transform_poll;
- gzgt->setup = WIDGETGROUP_node_transform_setup;
- gzgt->refresh = WIDGETGROUP_node_transform_refresh;
+ gzgt->poll = WIDGETGROUP_node_transform_poll;
+ gzgt->setup = WIDGETGROUP_node_transform_setup;
+ gzgt->refresh = WIDGETGROUP_node_transform_refresh;
}
/** \} */
@@ -199,199 +200,218 @@ void NODE_GGT_backdrop_transform(wmGizmoGroupType *gzgt)
* \{ */
struct NodeCropWidgetGroup {
- wmGizmo *border;
+ wmGizmo *border;
- struct {
- float dims[2];
- } state;
+ struct {
+ float dims[2];
+ } state;
- struct {
- PointerRNA ptr;
- PropertyRNA *prop;
- bContext *context;
- } update_data;
+ struct {
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ bContext *context;
+ } update_data;
};
static void gizmo_node_crop_update(struct NodeCropWidgetGroup *crop_group)
{
- RNA_property_update(crop_group->update_data.context, &crop_group->update_data.ptr, crop_group->update_data.prop);
+ RNA_property_update(
+ crop_group->update_data.context, &crop_group->update_data.ptr, crop_group->update_data.prop);
}
-static void two_xy_to_rect(const NodeTwoXYs *nxy, rctf *rect, const float dims[2], bool is_relative)
+static void two_xy_to_rect(const NodeTwoXYs *nxy,
+ rctf *rect,
+ const float dims[2],
+ bool is_relative)
{
- if (is_relative) {
- rect->xmin = nxy->fac_x1;
- rect->xmax = nxy->fac_x2;
- rect->ymin = nxy->fac_y1;
- rect->ymax = nxy->fac_y2;
- }
- else {
- rect->xmin = nxy->x1 / dims[0];
- rect->xmax = nxy->x2 / dims[0];
- rect->ymin = nxy->y1 / dims[1];
- rect->ymax = nxy->y2 / dims[1];
- }
+ if (is_relative) {
+ rect->xmin = nxy->fac_x1;
+ rect->xmax = nxy->fac_x2;
+ rect->ymin = nxy->fac_y1;
+ rect->ymax = nxy->fac_y2;
+ }
+ else {
+ rect->xmin = nxy->x1 / dims[0];
+ rect->xmax = nxy->x2 / dims[0];
+ rect->ymin = nxy->y1 / dims[1];
+ rect->ymax = nxy->y2 / dims[1];
+ }
}
-static void two_xy_from_rect(NodeTwoXYs *nxy, const rctf *rect, const float dims[2], bool is_relative)
+static void two_xy_from_rect(NodeTwoXYs *nxy,
+ const rctf *rect,
+ const float dims[2],
+ bool is_relative)
{
- if (is_relative) {
- nxy->fac_x1 = rect->xmin;
- nxy->fac_x2 = rect->xmax;
- nxy->fac_y1 = rect->ymin;
- nxy->fac_y2 = rect->ymax;
- }
- else {
- nxy->x1 = rect->xmin * dims[0];
- nxy->x2 = rect->xmax * dims[0];
- nxy->y1 = rect->ymin * dims[1];
- nxy->y2 = rect->ymax * dims[1];
- }
+ if (is_relative) {
+ nxy->fac_x1 = rect->xmin;
+ nxy->fac_x2 = rect->xmax;
+ nxy->fac_y1 = rect->ymin;
+ nxy->fac_y2 = rect->ymax;
+ }
+ else {
+ nxy->x1 = rect->xmin * dims[0];
+ nxy->x2 = rect->xmax * dims[0];
+ nxy->y1 = rect->ymin * dims[1];
+ nxy->y2 = rect->ymax * dims[1];
+ }
}
/* scale callbacks */
-static void gizmo_node_crop_prop_matrix_get(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- void *value_p)
+static void gizmo_node_crop_prop_matrix_get(const wmGizmo *gz,
+ wmGizmoProperty *gz_prop,
+ void *value_p)
{
- float (*matrix)[4] = value_p;
- BLI_assert(gz_prop->type->array_length == 16);
- struct NodeCropWidgetGroup *crop_group = gz->parent_gzgroup->customdata;
- const float *dims = crop_group->state.dims;
- const bNode *node = gz_prop->custom_func.user_data;
- const NodeTwoXYs *nxy = node->storage;
- bool is_relative = (bool)node->custom2;
- rctf rct;
- two_xy_to_rect(nxy, &rct, dims, is_relative);
- matrix[0][0] = fabsf(BLI_rctf_size_x(&rct));
- matrix[1][1] = fabsf(BLI_rctf_size_y(&rct));
- matrix[3][0] = (BLI_rctf_cent_x(&rct) - 0.5f) * dims[0];
- matrix[3][1] = (BLI_rctf_cent_y(&rct) - 0.5f) * dims[1];
+ float(*matrix)[4] = value_p;
+ BLI_assert(gz_prop->type->array_length == 16);
+ struct NodeCropWidgetGroup *crop_group = gz->parent_gzgroup->customdata;
+ const float *dims = crop_group->state.dims;
+ const bNode *node = gz_prop->custom_func.user_data;
+ const NodeTwoXYs *nxy = node->storage;
+ bool is_relative = (bool)node->custom2;
+ rctf rct;
+ two_xy_to_rect(nxy, &rct, dims, is_relative);
+ matrix[0][0] = fabsf(BLI_rctf_size_x(&rct));
+ matrix[1][1] = fabsf(BLI_rctf_size_y(&rct));
+ matrix[3][0] = (BLI_rctf_cent_x(&rct) - 0.5f) * dims[0];
+ matrix[3][1] = (BLI_rctf_cent_y(&rct) - 0.5f) * dims[1];
}
-static void gizmo_node_crop_prop_matrix_set(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- const void *value_p)
+static void gizmo_node_crop_prop_matrix_set(const wmGizmo *gz,
+ wmGizmoProperty *gz_prop,
+ const void *value_p)
{
- const float (*matrix)[4] = value_p;
- BLI_assert(gz_prop->type->array_length == 16);
- struct NodeCropWidgetGroup *crop_group = gz->parent_gzgroup->customdata;
- const float *dims = crop_group->state.dims;
- bNode *node = gz_prop->custom_func.user_data;
- NodeTwoXYs *nxy = node->storage;
- bool is_relative = (bool)node->custom2;
- rctf rct;
- two_xy_to_rect(nxy, &rct, dims, is_relative);
- const bool nx = rct.xmin > rct.xmax;
- const bool ny = rct.ymin > rct.ymax;
- BLI_rctf_resize(&rct, fabsf(matrix[0][0]), fabsf(matrix[1][1]));
- BLI_rctf_recenter(&rct, (matrix[3][0] / dims[0]) + 0.5f, (matrix[3][1] / dims[1]) + 0.5f);
- BLI_rctf_isect(&(rctf){ .xmin = 0, .ymin = 0, .xmax = 1, .ymax = 1, }, &rct, &rct);
- if (nx) {
- SWAP(float, rct.xmin, rct.xmax);
- }
- if (ny) {
- SWAP(float, rct.ymin, rct.ymax);
- }
- two_xy_from_rect(nxy, &rct, dims, is_relative);
- gizmo_node_crop_update(crop_group);
+ const float(*matrix)[4] = value_p;
+ BLI_assert(gz_prop->type->array_length == 16);
+ struct NodeCropWidgetGroup *crop_group = gz->parent_gzgroup->customdata;
+ const float *dims = crop_group->state.dims;
+ bNode *node = gz_prop->custom_func.user_data;
+ NodeTwoXYs *nxy = node->storage;
+ bool is_relative = (bool)node->custom2;
+ rctf rct;
+ two_xy_to_rect(nxy, &rct, dims, is_relative);
+ const bool nx = rct.xmin > rct.xmax;
+ const bool ny = rct.ymin > rct.ymax;
+ BLI_rctf_resize(&rct, fabsf(matrix[0][0]), fabsf(matrix[1][1]));
+ BLI_rctf_recenter(&rct, (matrix[3][0] / dims[0]) + 0.5f, (matrix[3][1] / dims[1]) + 0.5f);
+ BLI_rctf_isect(
+ &(rctf){
+ .xmin = 0,
+ .ymin = 0,
+ .xmax = 1,
+ .ymax = 1,
+ },
+ &rct,
+ &rct);
+ if (nx) {
+ SWAP(float, rct.xmin, rct.xmax);
+ }
+ if (ny) {
+ SWAP(float, rct.ymin, rct.ymax);
+ }
+ two_xy_from_rect(nxy, &rct, dims, is_relative);
+ gizmo_node_crop_update(crop_group);
}
static bool WIDGETGROUP_node_crop_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
- if ((snode->flag & SNODE_BACKDRAW) == 0) {
- return false;
- }
+ if ((snode->flag & SNODE_BACKDRAW) == 0) {
+ return false;
+ }
- if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) {
- bNode *node = nodeGetActive(snode->edittree);
+ if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) {
+ bNode *node = nodeGetActive(snode->edittree);
- if (node && ELEM(node->type, CMP_NODE_CROP)) {
- /* ignore 'use_crop_size', we can't usefully edit the crop in this case. */
- if ((node->custom1 & (1 << 0)) == 0) {
- return true;
- }
- }
- }
+ if (node && ELEM(node->type, CMP_NODE_CROP)) {
+ /* ignore 'use_crop_size', we can't usefully edit the crop in this case. */
+ if ((node->custom1 & (1 << 0)) == 0) {
+ return true;
+ }
+ }
+ }
- return false;
+ return false;
}
static void WIDGETGROUP_node_crop_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- struct NodeCropWidgetGroup *crop_group = MEM_mallocN(sizeof(struct NodeCropWidgetGroup), __func__);
+ struct NodeCropWidgetGroup *crop_group = MEM_mallocN(sizeof(struct NodeCropWidgetGroup),
+ __func__);
- crop_group->border = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
+ crop_group->border = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
- RNA_enum_set(crop_group->border->ptr, "transform",
- ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
+ RNA_enum_set(crop_group->border->ptr,
+ "transform",
+ ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
- gzgroup->customdata = crop_group;
+ gzgroup->customdata = crop_group;
}
static void WIDGETGROUP_node_crop_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- ARegion *ar = CTX_wm_region(C);
- wmGizmo *gz = gzgroup->gizmos.first;
+ ARegion *ar = CTX_wm_region(C);
+ wmGizmo *gz = gzgroup->gizmos.first;
- SpaceNode *snode = CTX_wm_space_node(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
- node_gizmo_calc_matrix_space(snode, ar, gz->matrix_space);
+ node_gizmo_calc_matrix_space(snode, ar, gz->matrix_space);
}
static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- Main *bmain = CTX_data_main(C);
- struct NodeCropWidgetGroup *crop_group = gzgroup->customdata;
- wmGizmo *gz = crop_group->border;
-
- void *lock;
- Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
-
- if (ibuf) {
- crop_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f;
- crop_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f;
-
- RNA_float_set_array(gz->ptr, "dimensions", crop_group->state.dims);
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
-
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node = nodeGetActive(snode->edittree);
-
- crop_group->update_data.context = (bContext *)C;
- RNA_pointer_create((ID *)snode->edittree, &RNA_CompositorNodeCrop, node, &crop_group->update_data.ptr);
- crop_group->update_data.prop = RNA_struct_find_property(&crop_group->update_data.ptr, "relative");
-
- WM_gizmo_target_property_def_func(
- gz, "matrix",
- &(const struct wmGizmoPropertyFnParams) {
- .value_get_fn = gizmo_node_crop_prop_matrix_get,
- .value_set_fn = gizmo_node_crop_prop_matrix_set,
- .range_get_fn = NULL,
- .user_data = node,
- });
- }
- else {
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
- }
-
- BKE_image_release_ibuf(ima, ibuf, lock);
+ Main *bmain = CTX_data_main(C);
+ struct NodeCropWidgetGroup *crop_group = gzgroup->customdata;
+ wmGizmo *gz = crop_group->border;
+
+ void *lock;
+ Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+
+ if (ibuf) {
+ crop_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f;
+ crop_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f;
+
+ RNA_float_set_array(gz->ptr, "dimensions", crop_group->state.dims);
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
+
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node = nodeGetActive(snode->edittree);
+
+ crop_group->update_data.context = (bContext *)C;
+ RNA_pointer_create(
+ (ID *)snode->edittree, &RNA_CompositorNodeCrop, node, &crop_group->update_data.ptr);
+ crop_group->update_data.prop = RNA_struct_find_property(&crop_group->update_data.ptr,
+ "relative");
+
+ WM_gizmo_target_property_def_func(gz,
+ "matrix",
+ &(const struct wmGizmoPropertyFnParams){
+ .value_get_fn = gizmo_node_crop_prop_matrix_get,
+ .value_set_fn = gizmo_node_crop_prop_matrix_set,
+ .range_get_fn = NULL,
+ .user_data = node,
+ });
+ }
+ else {
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
}
void NODE_GGT_backdrop_crop(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Backdrop Crop Widget";
- gzgt->idname = "NODE_GGT_backdrop_crop";
+ gzgt->name = "Backdrop Crop Widget";
+ gzgt->idname = "NODE_GGT_backdrop_crop";
- gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
- gzgt->poll = WIDGETGROUP_node_crop_poll;
- gzgt->setup = WIDGETGROUP_node_crop_setup;
- gzgt->draw_prepare = WIDGETGROUP_node_crop_draw_prepare;
- gzgt->refresh = WIDGETGROUP_node_crop_refresh;
+ gzgt->poll = WIDGETGROUP_node_crop_poll;
+ gzgt->setup = WIDGETGROUP_node_crop_setup;
+ gzgt->draw_prepare = WIDGETGROUP_node_crop_draw_prepare;
+ gzgt->refresh = WIDGETGROUP_node_crop_refresh;
}
/** \} */
@@ -401,220 +421,221 @@ void NODE_GGT_backdrop_crop(wmGizmoGroupType *gzgt)
* \{ */
struct NodeSunBeamsWidgetGroup {
- wmGizmo *gizmo;
+ wmGizmo *gizmo;
- struct {
- float dims[2];
- } state;
+ struct {
+ float dims[2];
+ } state;
};
static bool WIDGETGROUP_node_sbeam_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
- if ((snode->flag & SNODE_BACKDRAW) == 0) {
- return false;
- }
+ if ((snode->flag & SNODE_BACKDRAW) == 0) {
+ return false;
+ }
- if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) {
- bNode *node = nodeGetActive(snode->edittree);
+ if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) {
+ bNode *node = nodeGetActive(snode->edittree);
- if (node && ELEM(node->type, CMP_NODE_SUNBEAMS)) {
- return true;
- }
- }
+ if (node && ELEM(node->type, CMP_NODE_SUNBEAMS)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
static void WIDGETGROUP_node_sbeam_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- struct NodeSunBeamsWidgetGroup *sbeam_group = MEM_mallocN(sizeof(struct NodeSunBeamsWidgetGroup), __func__);
+ struct NodeSunBeamsWidgetGroup *sbeam_group = MEM_mallocN(sizeof(struct NodeSunBeamsWidgetGroup),
+ __func__);
- sbeam_group->gizmo = WM_gizmo_new("GIZMO_GT_move_3d", gzgroup, NULL);
- wmGizmo *gz = sbeam_group->gizmo;
+ sbeam_group->gizmo = WM_gizmo_new("GIZMO_GT_move_3d", gzgroup, NULL);
+ wmGizmo *gz = sbeam_group->gizmo;
- RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_CROSS_2D);
+ RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_CROSS_2D);
- gz->scale_basis = 0.05f;
+ gz->scale_basis = 0.05f;
- gzgroup->customdata = sbeam_group;
+ gzgroup->customdata = sbeam_group;
}
static void WIDGETGROUP_node_sbeam_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct NodeSunBeamsWidgetGroup *sbeam_group = gzgroup->customdata;
- ARegion *ar = CTX_wm_region(C);
- wmGizmo *gz = gzgroup->gizmos.first;
+ struct NodeSunBeamsWidgetGroup *sbeam_group = gzgroup->customdata;
+ ARegion *ar = CTX_wm_region(C);
+ wmGizmo *gz = gzgroup->gizmos.first;
- SpaceNode *snode = CTX_wm_space_node(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
- node_gizmo_calc_matrix_space_with_image_dims(snode, ar, sbeam_group->state.dims, gz->matrix_space);
+ node_gizmo_calc_matrix_space_with_image_dims(
+ snode, ar, sbeam_group->state.dims, gz->matrix_space);
}
static void WIDGETGROUP_node_sbeam_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- Main *bmain = CTX_data_main(C);
- struct NodeSunBeamsWidgetGroup *sbeam_group = gzgroup->customdata;
- wmGizmo *gz = sbeam_group->gizmo;
+ Main *bmain = CTX_data_main(C);
+ struct NodeSunBeamsWidgetGroup *sbeam_group = gzgroup->customdata;
+ wmGizmo *gz = sbeam_group->gizmo;
- void *lock;
- Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+ void *lock;
+ Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
- if (ibuf) {
- sbeam_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f;
- sbeam_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f;
+ if (ibuf) {
+ sbeam_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f;
+ sbeam_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f;
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node = nodeGetActive(snode->edittree);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node = nodeGetActive(snode->edittree);
- /* need to set property here for undo. TODO would prefer to do this in _init */
- PointerRNA nodeptr;
- RNA_pointer_create((ID *)snode->edittree, &RNA_CompositorNodeSunBeams, node, &nodeptr);
- WM_gizmo_target_property_def_rna(gz, "offset", &nodeptr, "source", -1);
+ /* need to set property here for undo. TODO would prefer to do this in _init */
+ PointerRNA nodeptr;
+ RNA_pointer_create((ID *)snode->edittree, &RNA_CompositorNodeSunBeams, node, &nodeptr);
+ WM_gizmo_target_property_def_rna(gz, "offset", &nodeptr, "source", -1);
- WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_MODAL, true);
- }
- else {
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
- }
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_MODAL, true);
+ }
+ else {
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
+ }
- BKE_image_release_ibuf(ima, ibuf, lock);
+ BKE_image_release_ibuf(ima, ibuf, lock);
}
void NODE_GGT_backdrop_sun_beams(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Sun Beams Widget";
- gzgt->idname = "NODE_GGT_sbeam";
+ gzgt->name = "Sun Beams Widget";
+ gzgt->idname = "NODE_GGT_sbeam";
- gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
- gzgt->poll = WIDGETGROUP_node_sbeam_poll;
- gzgt->setup = WIDGETGROUP_node_sbeam_setup;
- gzgt->draw_prepare = WIDGETGROUP_node_sbeam_draw_prepare;
- gzgt->refresh = WIDGETGROUP_node_sbeam_refresh;
+ gzgt->poll = WIDGETGROUP_node_sbeam_poll;
+ gzgt->setup = WIDGETGROUP_node_sbeam_setup;
+ gzgt->draw_prepare = WIDGETGROUP_node_sbeam_draw_prepare;
+ gzgt->refresh = WIDGETGROUP_node_sbeam_refresh;
}
/** \} */
-
-
/* -------------------------------------------------------------------- */
/** \name Corner Pin
* \{ */
struct NodeCornerPinWidgetGroup {
- wmGizmo *gizmos[4];
+ wmGizmo *gizmos[4];
- struct {
- float dims[2];
- } state;
+ struct {
+ float dims[2];
+ } state;
};
static bool WIDGETGROUP_node_corner_pin_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
- if ((snode->flag & SNODE_BACKDRAW) == 0) {
- return false;
- }
+ if ((snode->flag & SNODE_BACKDRAW) == 0) {
+ return false;
+ }
- if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) {
- bNode *node = nodeGetActive(snode->edittree);
+ if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) {
+ bNode *node = nodeGetActive(snode->edittree);
- if (node && ELEM(node->type, CMP_NODE_CORNERPIN)) {
- return true;
- }
- }
+ if (node && ELEM(node->type, CMP_NODE_CORNERPIN)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
static void WIDGETGROUP_node_corner_pin_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- struct NodeCornerPinWidgetGroup *cpin_group = MEM_mallocN(sizeof(struct NodeCornerPinWidgetGroup), __func__);
- const wmGizmoType *gzt_move_3d = WM_gizmotype_find("GIZMO_GT_move_3d", false);
+ struct NodeCornerPinWidgetGroup *cpin_group = MEM_mallocN(
+ sizeof(struct NodeCornerPinWidgetGroup), __func__);
+ const wmGizmoType *gzt_move_3d = WM_gizmotype_find("GIZMO_GT_move_3d", false);
- for (int i = 0; i < 4; i++) {
- cpin_group->gizmos[i] = WM_gizmo_new_ptr(gzt_move_3d, gzgroup, NULL);
- wmGizmo *gz = cpin_group->gizmos[i];
+ for (int i = 0; i < 4; i++) {
+ cpin_group->gizmos[i] = WM_gizmo_new_ptr(gzt_move_3d, gzgroup, NULL);
+ wmGizmo *gz = cpin_group->gizmos[i];
- RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_CROSS_2D);
+ RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_CROSS_2D);
- gz->scale_basis = 0.01f;
- }
+ gz->scale_basis = 0.01f;
+ }
- gzgroup->customdata = cpin_group;
+ gzgroup->customdata = cpin_group;
}
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);
+ struct NodeCornerPinWidgetGroup *cpin_group = gzgroup->customdata;
+ ARegion *ar = CTX_wm_region(C);
- SpaceNode *snode = CTX_wm_space_node(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);
+ float matrix_space[4][4];
+ node_gizmo_calc_matrix_space_with_image_dims(snode, ar, cpin_group->state.dims, matrix_space);
- for (int i = 0; i < 4; i++) {
- wmGizmo *gz = cpin_group->gizmos[i];
- copy_m4_m4(gz->matrix_space, matrix_space);
- }
+ for (int i = 0; i < 4; i++) {
+ wmGizmo *gz = cpin_group->gizmos[i];
+ copy_m4_m4(gz->matrix_space, matrix_space);
+ }
}
static void WIDGETGROUP_node_corner_pin_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- Main *bmain = CTX_data_main(C);
- struct NodeCornerPinWidgetGroup *cpin_group = gzgroup->customdata;
-
- void *lock;
- Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
-
- if (ibuf) {
- cpin_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f;
- cpin_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f;
-
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node = nodeGetActive(snode->edittree);
-
- /* need to set property here for undo. TODO would prefer to do this in _init */
- int i = 0;
- for (bNodeSocket *sock = node->inputs.first; sock && i < 4; sock = sock->next) {
- if (sock->type == SOCK_VECTOR) {
- wmGizmo *gz = cpin_group->gizmos[i++];
-
- PointerRNA sockptr;
- RNA_pointer_create((ID *)snode->edittree, &RNA_NodeSocket, sock, &sockptr);
- WM_gizmo_target_property_def_rna(gz, "offset", &sockptr, "default_value", -1);
-
- WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_MODAL, true);
- }
- }
- }
- else {
- for (int i = 0; i < 4; i++) {
- wmGizmo *gz = cpin_group->gizmos[i];
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
- }
- }
-
- BKE_image_release_ibuf(ima, ibuf, lock);
+ Main *bmain = CTX_data_main(C);
+ struct NodeCornerPinWidgetGroup *cpin_group = gzgroup->customdata;
+
+ void *lock;
+ Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+
+ if (ibuf) {
+ cpin_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f;
+ cpin_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f;
+
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node = nodeGetActive(snode->edittree);
+
+ /* need to set property here for undo. TODO would prefer to do this in _init */
+ int i = 0;
+ for (bNodeSocket *sock = node->inputs.first; sock && i < 4; sock = sock->next) {
+ if (sock->type == SOCK_VECTOR) {
+ wmGizmo *gz = cpin_group->gizmos[i++];
+
+ PointerRNA sockptr;
+ RNA_pointer_create((ID *)snode->edittree, &RNA_NodeSocket, sock, &sockptr);
+ WM_gizmo_target_property_def_rna(gz, "offset", &sockptr, "default_value", -1);
+
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_MODAL, true);
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < 4; i++) {
+ wmGizmo *gz = cpin_group->gizmos[i];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
+ }
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
}
void NODE_GGT_backdrop_corner_pin(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Corner Pin Widget";
- gzgt->idname = "NODE_GGT_backdrop_corner_pin";
+ gzgt->name = "Corner Pin Widget";
+ gzgt->idname = "NODE_GGT_backdrop_corner_pin";
- gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
- gzgt->poll = WIDGETGROUP_node_corner_pin_poll;
- gzgt->setup = WIDGETGROUP_node_corner_pin_setup;
- gzgt->draw_prepare = WIDGETGROUP_node_corner_pin_draw_prepare;
- gzgt->refresh = WIDGETGROUP_node_corner_pin_refresh;
+ gzgt->poll = WIDGETGROUP_node_corner_pin_poll;
+ gzgt->setup = WIDGETGROUP_node_corner_pin_setup;
+ gzgt->draw_prepare = WIDGETGROUP_node_corner_pin_draw_prepare;
+ gzgt->refresh = WIDGETGROUP_node_corner_pin_refresh;
}
/** \} */
diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c
index e38d29454dc..3c65c4854b8 100644
--- a/source/blender/editors/space_node/node_group.c
+++ b/source/blender/editors/space_node/node_group.c
@@ -43,7 +43,7 @@
#include "DEG_depsgraph_build.h"
-#include "ED_node.h" /* own include */
+#include "ED_node.h" /* own include */
#include "ED_screen.h"
#include "ED_render.h"
@@ -55,127 +55,123 @@
#include "UI_resources.h"
-#include "node_intern.h" /* own include */
+#include "node_intern.h" /* own include */
#include "NOD_common.h"
static bool node_group_operator_active(bContext *C)
{
- if (ED_operator_node_active(C)) {
- SpaceNode *snode = CTX_wm_space_node(C);
-
- /* Group operators only defined for standard node tree types.
- * Disabled otherwise to allow pynodes define their own operators
- * with same keymap.
- */
- if (STREQ(snode->tree_idname, "ShaderNodeTree") ||
- STREQ(snode->tree_idname, "CompositorNodeTree") ||
- STREQ(snode->tree_idname, "TextureNodeTree"))
- {
- return true;
- }
- }
- return false;
+ if (ED_operator_node_active(C)) {
+ SpaceNode *snode = CTX_wm_space_node(C);
+
+ /* Group operators only defined for standard node tree types.
+ * Disabled otherwise to allow pynodes define their own operators
+ * with same keymap.
+ */
+ if (STREQ(snode->tree_idname, "ShaderNodeTree") ||
+ STREQ(snode->tree_idname, "CompositorNodeTree") ||
+ STREQ(snode->tree_idname, "TextureNodeTree")) {
+ return true;
+ }
+ }
+ return false;
}
static bool node_group_operator_editable(bContext *C)
{
- if (ED_operator_node_editable(C)) {
- SpaceNode *snode = CTX_wm_space_node(C);
-
- /* Group operators only defined for standard node tree types.
- * 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))
- {
- return true;
- }
- }
- return false;
+ if (ED_operator_node_editable(C)) {
+ SpaceNode *snode = CTX_wm_space_node(C);
+
+ /* Group operators only defined for standard node tree types.
+ * 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)) {
+ return true;
+ }
+ }
+ return false;
}
static const char *group_ntree_idname(bContext *C)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- return snode->tree_idname;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ return snode->tree_idname;
}
static const char *group_node_idname(bContext *C)
{
- SpaceNode *snode = CTX_wm_space_node(C);
-
- if (ED_node_is_shader(snode)) {
- return "ShaderNodeGroup";
- }
- else if (ED_node_is_compositor(snode)) {
- return "CompositorNodeGroup";
- }
- else if (ED_node_is_texture(snode)) {
- return "TextureNodeGroup";
- }
-
- return "";
+ SpaceNode *snode = CTX_wm_space_node(C);
+
+ if (ED_node_is_shader(snode)) {
+ return "ShaderNodeGroup";
+ }
+ else if (ED_node_is_compositor(snode)) {
+ return "CompositorNodeGroup";
+ }
+ else if (ED_node_is_texture(snode)) {
+ return "TextureNodeGroup";
+ }
+
+ return "";
}
static bNode *node_group_get_active(bContext *C, const char *node_idname)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node = nodeGetActive(snode->edittree);
-
- if (node && STREQ(node->idname, node_idname)) {
- return node;
- }
- else {
- return NULL;
- }
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node = nodeGetActive(snode->edittree);
+
+ if (node && STREQ(node->idname, node_idname)) {
+ return node;
+ }
+ else {
+ return NULL;
+ }
}
/* ***************** Edit Group operator ************* */
static int node_group_edit_exec(bContext *C, wmOperator *op)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- const char *node_idname = group_node_idname(C);
- bNode *gnode;
- const bool exit = RNA_boolean_get(op->ptr, "exit");
+ SpaceNode *snode = CTX_wm_space_node(C);
+ const char *node_idname = group_node_idname(C);
+ bNode *gnode;
+ const bool exit = RNA_boolean_get(op->ptr, "exit");
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
- gnode = node_group_get_active(C, node_idname);
+ gnode = node_group_get_active(C, node_idname);
- if (gnode && !exit) {
- bNodeTree *ngroup = (bNodeTree *)gnode->id;
+ if (gnode && !exit) {
+ bNodeTree *ngroup = (bNodeTree *)gnode->id;
- if (ngroup) {
- ED_node_tree_push(snode, ngroup, gnode);
- }
- }
- else {
- ED_node_tree_pop(snode);
- }
+ if (ngroup) {
+ ED_node_tree_push(snode, ngroup, gnode);
+ }
+ }
+ else {
+ ED_node_tree_pop(snode);
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_group_edit(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Edit Group";
- ot->description = "Edit node group";
- ot->idname = "NODE_OT_group_edit";
+ /* identifiers */
+ ot->name = "Edit Group";
+ ot->description = "Edit node group";
+ ot->idname = "NODE_OT_group_edit";
- /* api callbacks */
- ot->exec = node_group_edit_exec;
- ot->poll = node_group_operator_active;
+ /* api callbacks */
+ ot->exec = node_group_edit_exec;
+ ot->poll = node_group_operator_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "exit", false, "Exit", "");
+ RNA_def_boolean(ot->srna, "exit", false, "Exit", "");
}
/* ******************** Ungroup operator ********************** */
@@ -183,882 +179,900 @@ void NODE_OT_group_edit(wmOperatorType *ot)
/* returns 1 if its OK */
static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode)
{
- bNodeLink *link, *linkn, *tlink;
- bNode *node, *nextnode;
- bNodeTree *ngroup, *wgroup;
- ListBase anim_basepaths = {NULL, NULL};
- LinkNode *nodes_delayed_free = NULL;
-
- ngroup = (bNodeTree *)gnode->id;
-
- /* clear new pointers, set in copytree */
- for (node = ntree->nodes.first; node; node = node->next) {
- node->new_node = NULL;
- }
-
- /* wgroup is a temporary copy of the NodeTree we're merging in
- * - all of wgroup's nodes are transferred across to their new home
- * - ngroup (i.e. the source NodeTree) is left unscathed
- * - temp copy. don't change ID usercount
- */
- wgroup = ntreeCopyTree_ex(ngroup, bmain, false);
-
- /* Add the nodes into the ntree */
- for (node = wgroup->nodes.first; node; node = nextnode) {
- nextnode = node->next;
-
- /* Remove interface nodes.
- * This also removes remaining links to and from interface nodes.
- */
- if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
- /* We must delay removal since sockets will reference this node. see: T52092 */
- BLI_linklist_prepend(&nodes_delayed_free, node);
- }
-
- /* keep track of this node's RNA "base" path (the part of the path identifying the node)
- * if the old nodetree has animation data which potentially covers this node
- */
- if (wgroup->adt) {
- PointerRNA ptr;
- char *path;
-
- RNA_pointer_create(&wgroup->id, &RNA_Node, node, &ptr);
- path = RNA_path_from_ID_to_struct(&ptr);
-
- if (path) {
- BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
- }
- }
-
- /* migrate node */
- BLI_remlink(&wgroup->nodes, node);
- BLI_addtail(&ntree->nodes, node);
-
- /* ensure unique node name in the node tree */
- nodeUniqueName(ntree, node);
-
- if (!node->parent) {
- node->locx += gnode->locx;
- node->locy += gnode->locy;
- }
-
- node->flag |= NODE_SELECT;
- }
-
- /* Add internal links to the ntree */
- for (link = wgroup->links.first; link; link = linkn) {
- linkn = link->next;
- BLI_remlink(&wgroup->links, link);
- BLI_addtail(&ntree->links, link);
- }
-
- /* and copy across the animation,
- * note that the animation data's action can be NULL here */
- if (wgroup->adt) {
- LinkData *ld, *ldn = NULL;
- bAction *waction;
-
- /* firstly, wgroup needs to temporary dummy action
- * that can be destroyed, as it shares copies */
- waction = wgroup->adt->action = BKE_action_copy(bmain, wgroup->adt->action);
-
- /* now perform the moving */
- BKE_animdata_separate_by_basepath(bmain, &wgroup->id, &ntree->id, &anim_basepaths);
-
- /* paths + their wrappers need to be freed */
- for (ld = anim_basepaths.first; ld; ld = ldn) {
- ldn = ld->next;
-
- MEM_freeN(ld->data);
- BLI_freelinkN(&anim_basepaths, ld);
- }
-
- /* free temp action too */
- if (waction) {
- BKE_id_free(bmain, waction);
- wgroup->adt->action = NULL;
- }
- }
-
- /* free the group tree (takes care of user count) */
- BKE_id_free(bmain, wgroup);
-
- /* restore external links to and from the gnode */
- /* note: the nodes have been copied to intermediate wgroup first (so need to use new_node),
- * then transferred to ntree (new_node pointers remain valid).
- */
-
- /* input links */
- for (link = ngroup->links.first; link; link = link->next) {
- if (link->fromnode->type == NODE_GROUP_INPUT) {
- const char *identifier = link->fromsock->identifier;
- int num_external_links = 0;
-
- /* find external links to this input */
- for (tlink = ntree->links.first; tlink; tlink = tlink->next) {
- if (tlink->tonode == gnode && STREQ(tlink->tosock->identifier, identifier)) {
- nodeAddLink(ntree, tlink->fromnode, tlink->fromsock, link->tonode->new_node, link->tosock->new_sock);
- ++num_external_links;
- }
- }
-
- /* if group output is not externally linked,
- * convert the constant input value to ensure somewhat consistent behavior */
- if (num_external_links == 0) {
- /* XXX TODO bNodeSocket *sock = node_group_find_input_socket(gnode, identifier);
- BLI_assert(sock);*/
-
- /* XXX TODO
- * nodeSocketCopy(ntree, link->tosock->new_sock, link->tonode->new_node,
- * ntree, sock, gnode);*/
- }
- }
- }
-
- /* output links */
- for (link = ntree->links.first; link; link = link->next) {
- if (link->fromnode == gnode) {
- const char *identifier = link->fromsock->identifier;
- int num_internal_links = 0;
-
- /* find internal links to this output */
- for (tlink = ngroup->links.first; tlink; tlink = tlink->next) {
- /* only use active output node */
- if (tlink->tonode->type == NODE_GROUP_OUTPUT && (tlink->tonode->flag & NODE_DO_OUTPUT)) {
- if (STREQ(tlink->tosock->identifier, identifier)) {
- nodeAddLink(ntree, tlink->fromnode->new_node, tlink->fromsock->new_sock, link->tonode, link->tosock);
- ++num_internal_links;
- }
- }
- }
-
- /* if group output is not internally linked,
- * convert the constant output value to ensure somewhat consistent behavior */
- if (num_internal_links == 0) {
- /* XXX TODO bNodeSocket *sock = node_group_find_output_socket(gnode, identifier);
- BLI_assert(sock);*/
-
- /* XXX TODO
- * nodeSocketCopy(ntree, link->tosock, link->tonode, ntree, sock, gnode); */
- }
- }
- }
-
- while (nodes_delayed_free) {
- node = BLI_linklist_pop(&nodes_delayed_free);
- nodeRemoveNode(bmain, ntree, node, false);
- }
-
- /* delete the group instance */
- nodeRemoveNode(bmain, ntree, gnode, false);
-
- ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
-
- return 1;
+ bNodeLink *link, *linkn, *tlink;
+ bNode *node, *nextnode;
+ bNodeTree *ngroup, *wgroup;
+ ListBase anim_basepaths = {NULL, NULL};
+ LinkNode *nodes_delayed_free = NULL;
+
+ ngroup = (bNodeTree *)gnode->id;
+
+ /* clear new pointers, set in copytree */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ node->new_node = NULL;
+ }
+
+ /* wgroup is a temporary copy of the NodeTree we're merging in
+ * - all of wgroup's nodes are transferred across to their new home
+ * - ngroup (i.e. the source NodeTree) is left unscathed
+ * - temp copy. don't change ID usercount
+ */
+ wgroup = ntreeCopyTree_ex(ngroup, bmain, false);
+
+ /* Add the nodes into the ntree */
+ for (node = wgroup->nodes.first; node; node = nextnode) {
+ nextnode = node->next;
+
+ /* Remove interface nodes.
+ * This also removes remaining links to and from interface nodes.
+ */
+ if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
+ /* We must delay removal since sockets will reference this node. see: T52092 */
+ BLI_linklist_prepend(&nodes_delayed_free, node);
+ }
+
+ /* keep track of this node's RNA "base" path (the part of the path identifying the node)
+ * if the old nodetree has animation data which potentially covers this node
+ */
+ if (wgroup->adt) {
+ PointerRNA ptr;
+ char *path;
+
+ RNA_pointer_create(&wgroup->id, &RNA_Node, node, &ptr);
+ path = RNA_path_from_ID_to_struct(&ptr);
+
+ if (path) {
+ BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
+ }
+ }
+
+ /* migrate node */
+ BLI_remlink(&wgroup->nodes, node);
+ BLI_addtail(&ntree->nodes, node);
+
+ /* ensure unique node name in the node tree */
+ nodeUniqueName(ntree, node);
+
+ if (!node->parent) {
+ node->locx += gnode->locx;
+ node->locy += gnode->locy;
+ }
+
+ node->flag |= NODE_SELECT;
+ }
+
+ /* Add internal links to the ntree */
+ for (link = wgroup->links.first; link; link = linkn) {
+ linkn = link->next;
+ BLI_remlink(&wgroup->links, link);
+ BLI_addtail(&ntree->links, link);
+ }
+
+ /* and copy across the animation,
+ * note that the animation data's action can be NULL here */
+ if (wgroup->adt) {
+ LinkData *ld, *ldn = NULL;
+ bAction *waction;
+
+ /* firstly, wgroup needs to temporary dummy action
+ * that can be destroyed, as it shares copies */
+ waction = wgroup->adt->action = BKE_action_copy(bmain, wgroup->adt->action);
+
+ /* now perform the moving */
+ BKE_animdata_separate_by_basepath(bmain, &wgroup->id, &ntree->id, &anim_basepaths);
+
+ /* paths + their wrappers need to be freed */
+ for (ld = anim_basepaths.first; ld; ld = ldn) {
+ ldn = ld->next;
+
+ MEM_freeN(ld->data);
+ BLI_freelinkN(&anim_basepaths, ld);
+ }
+
+ /* free temp action too */
+ if (waction) {
+ BKE_id_free(bmain, waction);
+ wgroup->adt->action = NULL;
+ }
+ }
+
+ /* free the group tree (takes care of user count) */
+ BKE_id_free(bmain, wgroup);
+
+ /* restore external links to and from the gnode */
+ /* note: the nodes have been copied to intermediate wgroup first (so need to use new_node),
+ * then transferred to ntree (new_node pointers remain valid).
+ */
+
+ /* input links */
+ for (link = ngroup->links.first; link; link = link->next) {
+ if (link->fromnode->type == NODE_GROUP_INPUT) {
+ const char *identifier = link->fromsock->identifier;
+ int num_external_links = 0;
+
+ /* find external links to this input */
+ for (tlink = ntree->links.first; tlink; tlink = tlink->next) {
+ if (tlink->tonode == gnode && STREQ(tlink->tosock->identifier, identifier)) {
+ nodeAddLink(ntree,
+ tlink->fromnode,
+ tlink->fromsock,
+ link->tonode->new_node,
+ link->tosock->new_sock);
+ ++num_external_links;
+ }
+ }
+
+ /* if group output is not externally linked,
+ * convert the constant input value to ensure somewhat consistent behavior */
+ if (num_external_links == 0) {
+ /* XXX TODO bNodeSocket *sock = node_group_find_input_socket(gnode, identifier);
+ BLI_assert(sock);*/
+
+ /* XXX TODO
+ * nodeSocketCopy(ntree, link->tosock->new_sock, link->tonode->new_node,
+ * ntree, sock, gnode);*/
+ }
+ }
+ }
+
+ /* output links */
+ for (link = ntree->links.first; link; link = link->next) {
+ if (link->fromnode == gnode) {
+ const char *identifier = link->fromsock->identifier;
+ int num_internal_links = 0;
+
+ /* find internal links to this output */
+ for (tlink = ngroup->links.first; tlink; tlink = tlink->next) {
+ /* only use active output node */
+ if (tlink->tonode->type == NODE_GROUP_OUTPUT && (tlink->tonode->flag & NODE_DO_OUTPUT)) {
+ if (STREQ(tlink->tosock->identifier, identifier)) {
+ nodeAddLink(ntree,
+ tlink->fromnode->new_node,
+ tlink->fromsock->new_sock,
+ link->tonode,
+ link->tosock);
+ ++num_internal_links;
+ }
+ }
+ }
+
+ /* if group output is not internally linked,
+ * convert the constant output value to ensure somewhat consistent behavior */
+ if (num_internal_links == 0) {
+ /* XXX TODO bNodeSocket *sock = node_group_find_output_socket(gnode, identifier);
+ BLI_assert(sock);*/
+
+ /* XXX TODO
+ * nodeSocketCopy(ntree, link->tosock, link->tonode, ntree, sock, gnode); */
+ }
+ }
+ }
+
+ while (nodes_delayed_free) {
+ node = BLI_linklist_pop(&nodes_delayed_free);
+ nodeRemoveNode(bmain, ntree, node, false);
+ }
+
+ /* delete the group instance */
+ nodeRemoveNode(bmain, ntree, gnode, false);
+
+ ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
+
+ return 1;
}
-
static int node_group_ungroup_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- const char *node_idname = group_node_idname(C);
- bNode *gnode;
-
- ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
-
- gnode = node_group_get_active(C, node_idname);
- if (!gnode) {
- return OPERATOR_CANCELLED;
- }
-
- if (gnode->id && node_group_ungroup(bmain, snode->edittree, gnode)) {
- ntreeUpdateTree(bmain, snode->nodetree);
- }
- else {
- BKE_report(op->reports, RPT_WARNING, "Cannot ungroup");
- return OPERATOR_CANCELLED;
- }
-
- snode_notify(C, snode);
- snode_dag_update(C, snode);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ const char *node_idname = group_node_idname(C);
+ bNode *gnode;
+
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
+
+ gnode = node_group_get_active(C, node_idname);
+ if (!gnode) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (gnode->id && node_group_ungroup(bmain, snode->edittree, gnode)) {
+ ntreeUpdateTree(bmain, snode->nodetree);
+ }
+ else {
+ BKE_report(op->reports, RPT_WARNING, "Cannot ungroup");
+ return OPERATOR_CANCELLED;
+ }
+
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
+
+ return OPERATOR_FINISHED;
}
void NODE_OT_group_ungroup(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Ungroup";
- ot->description = "Ungroup selected nodes";
- ot->idname = "NODE_OT_group_ungroup";
+ /* identifiers */
+ ot->name = "Ungroup";
+ ot->description = "Ungroup selected nodes";
+ ot->idname = "NODE_OT_group_ungroup";
- /* api callbacks */
- ot->exec = node_group_ungroup_exec;
- ot->poll = node_group_operator_editable;
+ /* api callbacks */
+ ot->exec = node_group_ungroup_exec;
+ ot->poll = node_group_operator_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Separate operator ********************** */
/* returns 1 if its OK */
static int node_group_separate_selected(
- Main *bmain, bNodeTree *ntree, bNodeTree *ngroup, float offx, float offy, int make_copy)
+ Main *bmain, bNodeTree *ntree, bNodeTree *ngroup, float offx, float offy, int make_copy)
{
- bNodeLink *link, *link_next;
- bNode *node, *node_next, *newnode;
- ListBase anim_basepaths = {NULL, NULL};
-
- /* deselect all nodes in the target tree */
- for (node = ntree->nodes.first; node; node = node->next) {
- nodeSetSelected(node, false);
- }
-
- /* clear new pointers, set in BKE_node_copy_ex(). */
- for (node = ngroup->nodes.first; node; node = node->next) {
- node->new_node = NULL;
- }
-
- /* add selected nodes into the ntree */
- for (node = ngroup->nodes.first; node; node = node_next) {
- node_next = node->next;
- if (!(node->flag & NODE_SELECT)) {
- continue;
- }
-
- /* ignore interface nodes */
- if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
- nodeSetSelected(node, false);
- continue;
- }
-
- if (make_copy) {
- /* make a copy */
- newnode = BKE_node_copy_ex(ngroup, node, LIB_ID_COPY_DEFAULT);
- }
- else {
- /* use the existing node */
- newnode = node;
- }
-
- /* keep track of this node's RNA "base" path (the part of the path identifying the node)
- * if the old nodetree has animation data which potentially covers this node
- */
- if (ngroup->adt) {
- PointerRNA ptr;
- char *path;
-
- RNA_pointer_create(&ngroup->id, &RNA_Node, newnode, &ptr);
- path = RNA_path_from_ID_to_struct(&ptr);
-
- if (path) {
- BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
- }
- }
-
- /* ensure valid parent pointers, detach if parent stays inside the group */
- if (newnode->parent && !(newnode->parent->flag & NODE_SELECT)) {
- nodeDetachNode(newnode);
- }
-
- /* migrate node */
- BLI_remlink(&ngroup->nodes, newnode);
- BLI_addtail(&ntree->nodes, newnode);
-
- /* ensure unique node name in the node tree */
- nodeUniqueName(ntree, newnode);
-
- if (!newnode->parent) {
- newnode->locx += offx;
- newnode->locy += offy;
- }
- }
-
- /* add internal links to the ntree */
- for (link = ngroup->links.first; link; link = link_next) {
- const bool fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT));
- const bool toselect = (link->tonode && (link->tonode->flag & NODE_SELECT));
- link_next = link->next;
-
- if (make_copy) {
- /* make a copy of internal links */
- if (fromselect && toselect) {
- nodeAddLink(ntree, link->fromnode->new_node, link->fromsock->new_sock, link->tonode->new_node, link->tosock->new_sock);
- }
- }
- else {
- /* move valid links over, delete broken links */
- if (fromselect && toselect) {
- BLI_remlink(&ngroup->links, link);
- BLI_addtail(&ntree->links, link);
- }
- else if (fromselect || toselect) {
- nodeRemLink(ngroup, link);
- }
- }
- }
-
- /* and copy across the animation,
- * note that the animation data's action can be NULL here */
- if (ngroup->adt) {
- LinkData *ld, *ldn = NULL;
-
- /* now perform the moving */
- BKE_animdata_separate_by_basepath(bmain, &ngroup->id, &ntree->id, &anim_basepaths);
-
- /* paths + their wrappers need to be freed */
- for (ld = anim_basepaths.first; ld; ld = ldn) {
- ldn = ld->next;
-
- MEM_freeN(ld->data);
- BLI_freelinkN(&anim_basepaths, ld);
- }
- }
-
- ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
- if (!make_copy) {
- ngroup->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
- }
-
- return 1;
+ bNodeLink *link, *link_next;
+ bNode *node, *node_next, *newnode;
+ ListBase anim_basepaths = {NULL, NULL};
+
+ /* deselect all nodes in the target tree */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ nodeSetSelected(node, false);
+ }
+
+ /* clear new pointers, set in BKE_node_copy_ex(). */
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ node->new_node = NULL;
+ }
+
+ /* add selected nodes into the ntree */
+ for (node = ngroup->nodes.first; node; node = node_next) {
+ node_next = node->next;
+ if (!(node->flag & NODE_SELECT)) {
+ continue;
+ }
+
+ /* ignore interface nodes */
+ if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
+ nodeSetSelected(node, false);
+ continue;
+ }
+
+ if (make_copy) {
+ /* make a copy */
+ newnode = BKE_node_copy_ex(ngroup, node, LIB_ID_COPY_DEFAULT);
+ }
+ else {
+ /* use the existing node */
+ newnode = node;
+ }
+
+ /* keep track of this node's RNA "base" path (the part of the path identifying the node)
+ * if the old nodetree has animation data which potentially covers this node
+ */
+ if (ngroup->adt) {
+ PointerRNA ptr;
+ char *path;
+
+ RNA_pointer_create(&ngroup->id, &RNA_Node, newnode, &ptr);
+ path = RNA_path_from_ID_to_struct(&ptr);
+
+ if (path) {
+ BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
+ }
+ }
+
+ /* ensure valid parent pointers, detach if parent stays inside the group */
+ if (newnode->parent && !(newnode->parent->flag & NODE_SELECT)) {
+ nodeDetachNode(newnode);
+ }
+
+ /* migrate node */
+ BLI_remlink(&ngroup->nodes, newnode);
+ BLI_addtail(&ntree->nodes, newnode);
+
+ /* ensure unique node name in the node tree */
+ nodeUniqueName(ntree, newnode);
+
+ if (!newnode->parent) {
+ newnode->locx += offx;
+ newnode->locy += offy;
+ }
+ }
+
+ /* add internal links to the ntree */
+ for (link = ngroup->links.first; link; link = link_next) {
+ const bool fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT));
+ const bool toselect = (link->tonode && (link->tonode->flag & NODE_SELECT));
+ link_next = link->next;
+
+ if (make_copy) {
+ /* make a copy of internal links */
+ if (fromselect && toselect) {
+ nodeAddLink(ntree,
+ link->fromnode->new_node,
+ link->fromsock->new_sock,
+ link->tonode->new_node,
+ link->tosock->new_sock);
+ }
+ }
+ else {
+ /* move valid links over, delete broken links */
+ if (fromselect && toselect) {
+ BLI_remlink(&ngroup->links, link);
+ BLI_addtail(&ntree->links, link);
+ }
+ else if (fromselect || toselect) {
+ nodeRemLink(ngroup, link);
+ }
+ }
+ }
+
+ /* and copy across the animation,
+ * note that the animation data's action can be NULL here */
+ if (ngroup->adt) {
+ LinkData *ld, *ldn = NULL;
+
+ /* now perform the moving */
+ BKE_animdata_separate_by_basepath(bmain, &ngroup->id, &ntree->id, &anim_basepaths);
+
+ /* paths + their wrappers need to be freed */
+ for (ld = anim_basepaths.first; ld; ld = ldn) {
+ ldn = ld->next;
+
+ MEM_freeN(ld->data);
+ BLI_freelinkN(&anim_basepaths, ld);
+ }
+ }
+
+ ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
+ if (!make_copy) {
+ ngroup->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
+ }
+
+ return 1;
}
typedef enum eNodeGroupSeparateType {
- NODE_GS_COPY,
- NODE_GS_MOVE,
+ NODE_GS_COPY,
+ NODE_GS_MOVE,
} eNodeGroupSeparateType;
/* Operator Property */
static const EnumPropertyItem node_group_separate_types[] = {
- {NODE_GS_COPY, "COPY", 0, "Copy", "Copy to parent node tree, keep group intact"},
- {NODE_GS_MOVE, "MOVE", 0, "Move", "Move to parent node tree, remove from group"},
- {0, NULL, 0, NULL, NULL},
+ {NODE_GS_COPY, "COPY", 0, "Copy", "Copy to parent node tree, keep group intact"},
+ {NODE_GS_MOVE, "MOVE", 0, "Move", "Move to parent node tree, remove from group"},
+ {0, NULL, 0, NULL, NULL},
};
static int node_group_separate_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ngroup, *nparent;
- int type = RNA_enum_get(op->ptr, "type");
- float offx, offy;
-
- ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
-
- /* are we inside of a group? */
- ngroup = snode->edittree;
- nparent = ED_node_tree_get(snode, 1);
- if (!nparent) {
- BKE_report(op->reports, RPT_WARNING, "Not inside node group");
- return OPERATOR_CANCELLED;
- }
- /* get node tree offset */
- snode_group_offset(snode, &offx, &offy);
-
- switch (type) {
- case NODE_GS_COPY:
- if (!node_group_separate_selected(bmain, nparent, ngroup, offx, offy, true)) {
- BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
- return OPERATOR_CANCELLED;
- }
- break;
- case NODE_GS_MOVE:
- if (!node_group_separate_selected(bmain, nparent, ngroup, offx, offy, false)) {
- BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
- return OPERATOR_CANCELLED;
- }
- break;
- }
-
- /* switch to parent tree */
- ED_node_tree_pop(snode);
-
- ntreeUpdateTree(CTX_data_main(C), snode->nodetree);
-
- snode_notify(C, snode);
- snode_dag_update(C, snode);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ngroup, *nparent;
+ int type = RNA_enum_get(op->ptr, "type");
+ float offx, offy;
+
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
+
+ /* are we inside of a group? */
+ ngroup = snode->edittree;
+ nparent = ED_node_tree_get(snode, 1);
+ if (!nparent) {
+ BKE_report(op->reports, RPT_WARNING, "Not inside node group");
+ return OPERATOR_CANCELLED;
+ }
+ /* get node tree offset */
+ snode_group_offset(snode, &offx, &offy);
+
+ switch (type) {
+ case NODE_GS_COPY:
+ if (!node_group_separate_selected(bmain, nparent, ngroup, offx, offy, true)) {
+ BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
+ return OPERATOR_CANCELLED;
+ }
+ break;
+ case NODE_GS_MOVE:
+ if (!node_group_separate_selected(bmain, nparent, ngroup, offx, offy, false)) {
+ BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
+ return OPERATOR_CANCELLED;
+ }
+ break;
+ }
+
+ /* switch to parent tree */
+ ED_node_tree_pop(snode);
+
+ ntreeUpdateTree(CTX_data_main(C), snode->nodetree);
+
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
+
+ return OPERATOR_FINISHED;
}
-static int node_group_separate_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
+static int node_group_separate_invoke(bContext *C,
+ wmOperator *UNUSED(op),
+ const wmEvent *UNUSED(event))
{
- uiPopupMenu *pup = UI_popup_menu_begin(C, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Separate"), ICON_NONE);
- uiLayout *layout = UI_popup_menu_layout(pup);
+ uiPopupMenu *pup = UI_popup_menu_begin(
+ C, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Separate"), ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
- uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
- uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_COPY);
- uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_MOVE);
+ uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
+ uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_COPY);
+ uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_MOVE);
- UI_popup_menu_end(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
void NODE_OT_group_separate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Separate";
- ot->description = "Separate selected nodes from the node group";
- ot->idname = "NODE_OT_group_separate";
+ /* identifiers */
+ ot->name = "Separate";
+ ot->description = "Separate selected nodes from the node group";
+ ot->idname = "NODE_OT_group_separate";
- /* api callbacks */
- ot->invoke = node_group_separate_invoke;
- ot->exec = node_group_separate_exec;
- ot->poll = node_group_operator_editable;
+ /* api callbacks */
+ ot->invoke = node_group_separate_invoke;
+ ot->exec = node_group_separate_exec;
+ ot->poll = node_group_operator_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_enum(ot->srna, "type", node_group_separate_types, NODE_GS_COPY, "Type", "");
+ RNA_def_enum(ot->srna, "type", node_group_separate_types, NODE_GS_COPY, "Type", "");
}
/* ****************** Make Group operator ******************* */
static bool node_group_make_use_node(bNode *node, bNode *gnode)
{
- return (node != gnode &&
- !ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT) &&
- (node->flag & NODE_SELECT));
+ return (node != gnode && !ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT) &&
+ (node->flag & NODE_SELECT));
}
-static bool node_group_make_test_selected(bNodeTree *ntree, bNode *gnode, const char *ntree_idname, struct ReportList *reports)
+static bool node_group_make_test_selected(bNodeTree *ntree,
+ bNode *gnode,
+ const char *ntree_idname,
+ struct ReportList *reports)
{
- bNodeTree *ngroup;
- bNode *node;
- bNodeLink *link;
- int ok = true;
-
- /* make a local pseudo node tree to pass to the node poll functions */
- ngroup = ntreeAddTree(NULL, "Pseudo Node Group", ntree_idname);
-
- /* check poll functions for selected nodes */
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node_group_make_use_node(node, gnode)) {
- if (node->typeinfo->poll_instance && !node->typeinfo->poll_instance(node, ngroup)) {
- BKE_reportf(reports, RPT_WARNING, "Can not add node '%s' in a group", node->name);
- ok = false;
- break;
- }
- }
-
- node->done = 0;
- }
-
- /* free local pseudo node tree again */
- ntreeFreeTree(ngroup);
- MEM_freeN(ngroup);
- if (!ok) {
- return false;
- }
-
- /* check if all connections are OK, no unselected node has both
- * inputs and outputs to a selection */
- for (link = ntree->links.first; link; link = link->next) {
- if (node_group_make_use_node(link->fromnode, gnode)) {
- link->tonode->done |= 1;
- }
- if (node_group_make_use_node(link->tonode, gnode)) {
- link->fromnode->done |= 2;
- }
- }
- for (node = ntree->nodes.first; node; node = node->next) {
- if (!(node->flag & NODE_SELECT) &&
- node != gnode &&
- node->done == 3)
- {
- return false;
- }
- }
- return true;
+ bNodeTree *ngroup;
+ bNode *node;
+ bNodeLink *link;
+ int ok = true;
+
+ /* make a local pseudo node tree to pass to the node poll functions */
+ ngroup = ntreeAddTree(NULL, "Pseudo Node Group", ntree_idname);
+
+ /* check poll functions for selected nodes */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node_group_make_use_node(node, gnode)) {
+ if (node->typeinfo->poll_instance && !node->typeinfo->poll_instance(node, ngroup)) {
+ BKE_reportf(reports, RPT_WARNING, "Can not add node '%s' in a group", node->name);
+ ok = false;
+ break;
+ }
+ }
+
+ node->done = 0;
+ }
+
+ /* free local pseudo node tree again */
+ ntreeFreeTree(ngroup);
+ MEM_freeN(ngroup);
+ if (!ok) {
+ return false;
+ }
+
+ /* check if all connections are OK, no unselected node has both
+ * inputs and outputs to a selection */
+ for (link = ntree->links.first; link; link = link->next) {
+ if (node_group_make_use_node(link->fromnode, gnode)) {
+ link->tonode->done |= 1;
+ }
+ if (node_group_make_use_node(link->tonode, gnode)) {
+ link->fromnode->done |= 2;
+ }
+ }
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (!(node->flag & NODE_SELECT) && node != gnode && node->done == 3) {
+ return false;
+ }
+ }
+ return true;
}
static int node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min, float *max)
{
- bNode *node;
- float loc[2];
- int totselect = 0;
-
- INIT_MINMAX2(min, max);
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node_group_make_use_node(node, gnode)) {
- nodeToView(node, 0.0f, 0.0f, &loc[0], &loc[1]);
- minmax_v2v2_v2(min, max, loc);
- ++totselect;
- }
- }
-
- /* sane min/max if no selected nodes */
- if (totselect == 0) {
- min[0] = min[1] = max[0] = max[1] = 0.0f;
- }
-
- return totselect;
+ bNode *node;
+ float loc[2];
+ int totselect = 0;
+
+ INIT_MINMAX2(min, max);
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node_group_make_use_node(node, gnode)) {
+ nodeToView(node, 0.0f, 0.0f, &loc[0], &loc[1]);
+ minmax_v2v2_v2(min, max, loc);
+ ++totselect;
+ }
+ }
+
+ /* sane min/max if no selected nodes */
+ if (totselect == 0) {
+ min[0] = min[1] = max[0] = max[1] = 0.0f;
+ }
+
+ return totselect;
}
static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, bNode *gnode)
{
- Main *bmain = CTX_data_main(C);
- bNodeTree *ngroup = (bNodeTree *)gnode->id;
- bNodeLink *link, *linkn;
- bNode *node, *nextn;
- bNodeSocket *sock;
- ListBase anim_basepaths = {NULL, NULL};
- float min[2], max[2], center[2];
- int totselect;
- bool expose_all = false;
- bNode *input_node, *output_node;
-
- /* XXX rough guess, not nice but we don't have access to UI constants here ... */
- static const float offsetx = 200;
- static const float offsety = 0.0f;
-
- /* deselect all nodes in the target tree */
- for (node = ngroup->nodes.first; node; node = node->next) {
- nodeSetSelected(node, false);
- }
-
- totselect = node_get_selected_minmax(ntree, gnode, min, max);
- add_v2_v2v2(center, min, max);
- mul_v2_fl(center, 0.5f);
-
- /* auto-add interface for "solo" nodes */
- if (totselect == 1) {
- expose_all = true;
- }
-
- /* move nodes over */
- for (node = ntree->nodes.first; node; node = nextn) {
- nextn = node->next;
- if (node_group_make_use_node(node, gnode)) {
- /* keep track of this node's RNA "base" path (the part of the pat identifying the node)
- * if the old nodetree has animation data which potentially covers this node
- */
- if (ntree->adt) {
- PointerRNA ptr;
- char *path;
-
- RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
- path = RNA_path_from_ID_to_struct(&ptr);
-
- if (path) {
- BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
- }
- }
-
- /* ensure valid parent pointers, detach if parent stays outside the group */
- if (node->parent && !(node->parent->flag & NODE_SELECT)) {
- nodeDetachNode(node);
- }
-
- /* change node-collection membership */
- BLI_remlink(&ntree->nodes, node);
- BLI_addtail(&ngroup->nodes, node);
-
- /* ensure unique node name in the ngroup */
- nodeUniqueName(ngroup, node);
- }
- }
-
- /* move animation data over */
- if (ntree->adt) {
- LinkData *ld, *ldn = NULL;
-
- BKE_animdata_separate_by_basepath(bmain, &ntree->id, &ngroup->id, &anim_basepaths);
-
- /* paths + their wrappers need to be freed */
- for (ld = anim_basepaths.first; ld; ld = ldn) {
- ldn = ld->next;
-
- MEM_freeN(ld->data);
- BLI_freelinkN(&anim_basepaths, ld);
- }
- }
-
- /* node groups don't use internal cached data */
- ntreeFreeCache(ngroup);
-
- /* create input node */
- input_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_INPUT);
- input_node->locx = min[0] - center[0] - offsetx;
- input_node->locy = -offsety;
-
- /* create output node */
- output_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_OUTPUT);
- output_node->locx = max[0] - center[0] + offsetx;
- output_node->locy = -offsety;
-
- /* relink external sockets */
- for (link = ntree->links.first; link; link = linkn) {
- int fromselect = node_group_make_use_node(link->fromnode, gnode);
- int toselect = node_group_make_use_node(link->tonode, gnode);
-
- linkn = link->next;
-
- if ((fromselect && link->tonode == gnode) || (toselect && link->fromnode == gnode)) {
- /* remove all links to/from the gnode.
- * this can remove link information, but there's no general way to preserve it.
- */
- nodeRemLink(ntree, link);
- }
- else if (fromselect && toselect) {
- BLI_remlink(&ntree->links, link);
- BLI_addtail(&ngroup->links, link);
- }
- else if (toselect) {
- bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, link->tonode, link->tosock);
- bNodeSocket *input_sock;
-
- /* update the group node and interface node sockets,
- * so the new interface socket can be linked.
- */
- node_group_verify(ntree, gnode, (ID *)ngroup);
- node_group_input_verify(ngroup, input_node, (ID *)ngroup);
-
- /* create new internal link */
- input_sock = node_group_input_find_socket(input_node, iosock->identifier);
- nodeAddLink(ngroup, input_node, input_sock, link->tonode, link->tosock);
-
- /* redirect external link */
- link->tonode = gnode;
- link->tosock = node_group_find_input_socket(gnode, iosock->identifier);
- }
- else if (fromselect) {
- /* First check whether the source of this link is already connected to an output.
- * If yes, reuse that output instead of duplicating it. */
- bool connected = false;
- bNodeLink *olink;
- for (olink = ngroup->links.first; olink; olink = olink->next) {
- if (olink->fromsock == link->fromsock && olink->tonode == output_node) {
- bNodeSocket *output_sock = node_group_find_output_socket(gnode, olink->tosock->identifier);
- link->fromnode = gnode;
- link->fromsock = output_sock;
- connected = true;
- }
- }
-
- if (!connected) {
- bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, link->fromnode, link->fromsock);
- bNodeSocket *output_sock;
-
- /* update the group node and interface node sockets,
- * so the new interface socket can be linked.
- */
- node_group_verify(ntree, gnode, (ID *)ngroup);
- node_group_output_verify(ngroup, output_node, (ID *)ngroup);
-
- /* create new internal link */
- output_sock = node_group_output_find_socket(output_node, iosock->identifier);
- nodeAddLink(ngroup, link->fromnode, link->fromsock, output_node, output_sock);
-
- /* redirect external link */
- link->fromnode = gnode;
- link->fromsock = node_group_find_output_socket(gnode, iosock->identifier);
- }
- }
- }
-
- /* move nodes in the group to the center */
- for (node = ngroup->nodes.first; node; node = node->next) {
- if (node_group_make_use_node(node, gnode) && !node->parent) {
- node->locx -= center[0];
- node->locy -= center[1];
- }
- }
-
- /* expose all unlinked sockets too */
- if (expose_all) {
- for (node = ngroup->nodes.first; node; node = node->next) {
- if (node_group_make_use_node(node, gnode)) {
- for (sock = node->inputs.first; sock; sock = sock->next) {
- bNodeSocket *iosock, *input_sock;
- bool skip = false;
- for (link = ngroup->links.first; link; link = link->next) {
- if (link->tosock == sock) {
- skip = true;
- break;
- }
- }
- if (skip) {
- continue;
- }
-
- iosock = ntreeAddSocketInterfaceFromSocket(ngroup, node, sock);
-
- node_group_input_verify(ngroup, input_node, (ID *)ngroup);
-
- /* create new internal link */
- input_sock = node_group_input_find_socket(input_node, iosock->identifier);
- nodeAddLink(ngroup, input_node, input_sock, node, sock);
- }
-
- for (sock = node->outputs.first; sock; sock = sock->next) {
- bNodeSocket *iosock, *output_sock;
- bool skip = false;
- for (link = ngroup->links.first; link; link = link->next) {
- if (link->fromsock == sock) {
- skip = true;
- }
- }
- if (skip) {
- continue;
- }
-
- iosock = ntreeAddSocketInterfaceFromSocket(ngroup, node, sock);
-
- node_group_output_verify(ngroup, output_node, (ID *)ngroup);
-
- /* create new internal link */
- output_sock = node_group_output_find_socket(output_node, iosock->identifier);
- nodeAddLink(ngroup, node, sock, output_node, output_sock);
- }
- }
- }
- }
-
- /* update of the group tree */
- ngroup->update |= NTREE_UPDATE | NTREE_UPDATE_LINKS;
- /* update of the tree containing the group instance node */
- ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
+ Main *bmain = CTX_data_main(C);
+ bNodeTree *ngroup = (bNodeTree *)gnode->id;
+ bNodeLink *link, *linkn;
+ bNode *node, *nextn;
+ bNodeSocket *sock;
+ ListBase anim_basepaths = {NULL, NULL};
+ float min[2], max[2], center[2];
+ int totselect;
+ bool expose_all = false;
+ bNode *input_node, *output_node;
+
+ /* XXX rough guess, not nice but we don't have access to UI constants here ... */
+ static const float offsetx = 200;
+ static const float offsety = 0.0f;
+
+ /* deselect all nodes in the target tree */
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ nodeSetSelected(node, false);
+ }
+
+ totselect = node_get_selected_minmax(ntree, gnode, min, max);
+ add_v2_v2v2(center, min, max);
+ mul_v2_fl(center, 0.5f);
+
+ /* auto-add interface for "solo" nodes */
+ if (totselect == 1) {
+ expose_all = true;
+ }
+
+ /* move nodes over */
+ for (node = ntree->nodes.first; node; node = nextn) {
+ nextn = node->next;
+ if (node_group_make_use_node(node, gnode)) {
+ /* keep track of this node's RNA "base" path (the part of the pat identifying the node)
+ * if the old nodetree has animation data which potentially covers this node
+ */
+ if (ntree->adt) {
+ PointerRNA ptr;
+ char *path;
+
+ RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
+ path = RNA_path_from_ID_to_struct(&ptr);
+
+ if (path) {
+ BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
+ }
+ }
+
+ /* ensure valid parent pointers, detach if parent stays outside the group */
+ if (node->parent && !(node->parent->flag & NODE_SELECT)) {
+ nodeDetachNode(node);
+ }
+
+ /* change node-collection membership */
+ BLI_remlink(&ntree->nodes, node);
+ BLI_addtail(&ngroup->nodes, node);
+
+ /* ensure unique node name in the ngroup */
+ nodeUniqueName(ngroup, node);
+ }
+ }
+
+ /* move animation data over */
+ if (ntree->adt) {
+ LinkData *ld, *ldn = NULL;
+
+ BKE_animdata_separate_by_basepath(bmain, &ntree->id, &ngroup->id, &anim_basepaths);
+
+ /* paths + their wrappers need to be freed */
+ for (ld = anim_basepaths.first; ld; ld = ldn) {
+ ldn = ld->next;
+
+ MEM_freeN(ld->data);
+ BLI_freelinkN(&anim_basepaths, ld);
+ }
+ }
+
+ /* node groups don't use internal cached data */
+ ntreeFreeCache(ngroup);
+
+ /* create input node */
+ input_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_INPUT);
+ input_node->locx = min[0] - center[0] - offsetx;
+ input_node->locy = -offsety;
+
+ /* create output node */
+ output_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_OUTPUT);
+ output_node->locx = max[0] - center[0] + offsetx;
+ output_node->locy = -offsety;
+
+ /* relink external sockets */
+ for (link = ntree->links.first; link; link = linkn) {
+ int fromselect = node_group_make_use_node(link->fromnode, gnode);
+ int toselect = node_group_make_use_node(link->tonode, gnode);
+
+ linkn = link->next;
+
+ if ((fromselect && link->tonode == gnode) || (toselect && link->fromnode == gnode)) {
+ /* remove all links to/from the gnode.
+ * this can remove link information, but there's no general way to preserve it.
+ */
+ nodeRemLink(ntree, link);
+ }
+ else if (fromselect && toselect) {
+ BLI_remlink(&ntree->links, link);
+ BLI_addtail(&ngroup->links, link);
+ }
+ else if (toselect) {
+ bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, link->tonode, link->tosock);
+ bNodeSocket *input_sock;
+
+ /* update the group node and interface node sockets,
+ * so the new interface socket can be linked.
+ */
+ node_group_verify(ntree, gnode, (ID *)ngroup);
+ node_group_input_verify(ngroup, input_node, (ID *)ngroup);
+
+ /* create new internal link */
+ input_sock = node_group_input_find_socket(input_node, iosock->identifier);
+ nodeAddLink(ngroup, input_node, input_sock, link->tonode, link->tosock);
+
+ /* redirect external link */
+ link->tonode = gnode;
+ link->tosock = node_group_find_input_socket(gnode, iosock->identifier);
+ }
+ else if (fromselect) {
+ /* First check whether the source of this link is already connected to an output.
+ * If yes, reuse that output instead of duplicating it. */
+ bool connected = false;
+ bNodeLink *olink;
+ for (olink = ngroup->links.first; olink; olink = olink->next) {
+ if (olink->fromsock == link->fromsock && olink->tonode == output_node) {
+ bNodeSocket *output_sock = node_group_find_output_socket(gnode,
+ olink->tosock->identifier);
+ link->fromnode = gnode;
+ link->fromsock = output_sock;
+ connected = true;
+ }
+ }
+
+ if (!connected) {
+ bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(
+ ngroup, link->fromnode, link->fromsock);
+ bNodeSocket *output_sock;
+
+ /* update the group node and interface node sockets,
+ * so the new interface socket can be linked.
+ */
+ node_group_verify(ntree, gnode, (ID *)ngroup);
+ node_group_output_verify(ngroup, output_node, (ID *)ngroup);
+
+ /* create new internal link */
+ output_sock = node_group_output_find_socket(output_node, iosock->identifier);
+ nodeAddLink(ngroup, link->fromnode, link->fromsock, output_node, output_sock);
+
+ /* redirect external link */
+ link->fromnode = gnode;
+ link->fromsock = node_group_find_output_socket(gnode, iosock->identifier);
+ }
+ }
+ }
+
+ /* move nodes in the group to the center */
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node_group_make_use_node(node, gnode) && !node->parent) {
+ node->locx -= center[0];
+ node->locy -= center[1];
+ }
+ }
+
+ /* expose all unlinked sockets too */
+ if (expose_all) {
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node_group_make_use_node(node, gnode)) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ bNodeSocket *iosock, *input_sock;
+ bool skip = false;
+ for (link = ngroup->links.first; link; link = link->next) {
+ if (link->tosock == sock) {
+ skip = true;
+ break;
+ }
+ }
+ if (skip) {
+ continue;
+ }
+
+ iosock = ntreeAddSocketInterfaceFromSocket(ngroup, node, sock);
+
+ node_group_input_verify(ngroup, input_node, (ID *)ngroup);
+
+ /* create new internal link */
+ input_sock = node_group_input_find_socket(input_node, iosock->identifier);
+ nodeAddLink(ngroup, input_node, input_sock, node, sock);
+ }
+
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ bNodeSocket *iosock, *output_sock;
+ bool skip = false;
+ for (link = ngroup->links.first; link; link = link->next) {
+ if (link->fromsock == sock) {
+ skip = true;
+ }
+ }
+ if (skip) {
+ continue;
+ }
+
+ iosock = ntreeAddSocketInterfaceFromSocket(ngroup, node, sock);
+
+ node_group_output_verify(ngroup, output_node, (ID *)ngroup);
+
+ /* create new internal link */
+ output_sock = node_group_output_find_socket(output_node, iosock->identifier);
+ nodeAddLink(ngroup, node, sock, output_node, output_sock);
+ }
+ }
+ }
+ }
+
+ /* update of the group tree */
+ ngroup->update |= NTREE_UPDATE | NTREE_UPDATE_LINKS;
+ /* update of the tree containing the group instance node */
+ ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
}
-static bNode *node_group_make_from_selected(const bContext *C, bNodeTree *ntree, const char *ntype, const char *ntreetype)
+static bNode *node_group_make_from_selected(const bContext *C,
+ bNodeTree *ntree,
+ const char *ntype,
+ const char *ntreetype)
{
- Main *bmain = CTX_data_main(C);
- bNode *gnode;
- bNodeTree *ngroup;
- float min[2], max[2];
- int totselect;
+ Main *bmain = CTX_data_main(C);
+ bNode *gnode;
+ bNodeTree *ngroup;
+ float min[2], max[2];
+ int totselect;
- totselect = node_get_selected_minmax(ntree, NULL, min, max);
- /* don't make empty group */
- if (totselect == 0) {
- return NULL;
- }
+ totselect = node_get_selected_minmax(ntree, NULL, min, max);
+ /* don't make empty group */
+ if (totselect == 0) {
+ return NULL;
+ }
- /* new nodetree */
- ngroup = ntreeAddTree(bmain, "NodeGroup", ntreetype);
+ /* new nodetree */
+ ngroup = ntreeAddTree(bmain, "NodeGroup", ntreetype);
- /* make group node */
- gnode = nodeAddNode(C, ntree, ntype);
- gnode->id = (ID *)ngroup;
+ /* make group node */
+ gnode = nodeAddNode(C, ntree, ntype);
+ gnode->id = (ID *)ngroup;
- gnode->locx = 0.5f * (min[0] + max[0]);
- gnode->locy = 0.5f * (min[1] + max[1]);
+ gnode->locx = 0.5f * (min[0] + max[0]);
+ gnode->locy = 0.5f * (min[1] + max[1]);
- node_group_make_insert_selected(C, ntree, gnode);
+ node_group_make_insert_selected(C, ntree, gnode);
- /* update of the tree containing the group instance node */
- ntree->update |= NTREE_UPDATE_NODES;
+ /* update of the tree containing the group instance node */
+ ntree->update |= NTREE_UPDATE_NODES;
- return gnode;
+ return gnode;
}
static int node_group_make_exec(bContext *C, wmOperator *op)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree = snode->edittree;
- const char *ntree_idname = group_ntree_idname(C);
- const char *node_idname = group_node_idname(C);
- bNodeTree *ngroup;
- bNode *gnode;
- Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ const char *ntree_idname = group_ntree_idname(C);
+ const char *node_idname = group_node_idname(C);
+ bNodeTree *ngroup;
+ bNode *gnode;
+ Main *bmain = CTX_data_main(C);
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
- if (!node_group_make_test_selected(ntree, NULL, ntree_idname, op->reports)) {
- return OPERATOR_CANCELLED;
- }
+ if (!node_group_make_test_selected(ntree, NULL, ntree_idname, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
- gnode = node_group_make_from_selected(C, ntree, node_idname, ntree_idname);
+ gnode = node_group_make_from_selected(C, ntree, node_idname, ntree_idname);
- if (gnode) {
- ngroup = (bNodeTree *)gnode->id;
+ if (gnode) {
+ ngroup = (bNodeTree *)gnode->id;
- nodeSetActive(ntree, gnode);
- if (ngroup) {
- ED_node_tree_push(snode, ngroup, gnode);
- ntreeUpdateTree(bmain, ngroup);
- }
- }
+ nodeSetActive(ntree, gnode);
+ if (ngroup) {
+ ED_node_tree_push(snode, ngroup, gnode);
+ ntreeUpdateTree(bmain, ngroup);
+ }
+ }
- ntreeUpdateTree(bmain, ntree);
+ ntreeUpdateTree(bmain, ntree);
- snode_notify(C, snode);
- snode_dag_update(C, snode);
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
- /* We broke relations in node tree, need to rebuild them in the grahes. */
- DEG_relations_tag_update(bmain);
+ /* We broke relations in node tree, need to rebuild them in the grahes. */
+ DEG_relations_tag_update(bmain);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_group_make(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Group";
- ot->description = "Make group from selected nodes";
- ot->idname = "NODE_OT_group_make";
+ /* identifiers */
+ ot->name = "Make Group";
+ ot->description = "Make group from selected nodes";
+ ot->idname = "NODE_OT_group_make";
- /* api callbacks */
- ot->exec = node_group_make_exec;
- ot->poll = node_group_operator_editable;
+ /* api callbacks */
+ ot->exec = node_group_make_exec;
+ ot->poll = node_group_operator_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** Group Insert operator ******************* */
static int node_group_insert_exec(bContext *C, wmOperator *op)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree = snode->edittree;
- bNodeTree *ngroup;
- const char *node_idname = group_node_idname(C);
- bNode *gnode;
- Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNodeTree *ngroup;
+ const char *node_idname = group_node_idname(C);
+ bNode *gnode;
+ Main *bmain = CTX_data_main(C);
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
- gnode = node_group_get_active(C, node_idname);
+ gnode = node_group_get_active(C, node_idname);
- if (!gnode || !gnode->id) {
- return OPERATOR_CANCELLED;
- }
+ if (!gnode || !gnode->id) {
+ return OPERATOR_CANCELLED;
+ }
- ngroup = (bNodeTree *)gnode->id;
- if (!node_group_make_test_selected(ntree, gnode, ngroup->idname, op->reports)) {
- return OPERATOR_CANCELLED;
- }
+ ngroup = (bNodeTree *)gnode->id;
+ if (!node_group_make_test_selected(ntree, gnode, ngroup->idname, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
- node_group_make_insert_selected(C, ntree, gnode);
+ node_group_make_insert_selected(C, ntree, gnode);
- nodeSetActive(ntree, gnode);
- ED_node_tree_push(snode, ngroup, gnode);
- ntreeUpdateTree(bmain, ngroup);
+ nodeSetActive(ntree, gnode);
+ ED_node_tree_push(snode, ngroup, gnode);
+ ntreeUpdateTree(bmain, ngroup);
- ntreeUpdateTree(bmain, ntree);
+ ntreeUpdateTree(bmain, ntree);
- snode_notify(C, snode);
- snode_dag_update(C, snode);
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_group_insert(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Group Insert";
- ot->description = "Insert selected nodes into a node group";
- ot->idname = "NODE_OT_group_insert";
+ /* identifiers */
+ ot->name = "Group Insert";
+ ot->description = "Insert selected nodes into a node group";
+ ot->idname = "NODE_OT_group_insert";
- /* api callbacks */
- ot->exec = node_group_insert_exec;
- ot->poll = node_group_operator_editable;
+ /* api callbacks */
+ ot->exec = node_group_insert_exec;
+ ot->poll = node_group_operator_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index dbd6ef163e3..7b4102ce324 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -43,14 +43,14 @@ struct wmWindow;
/* temp data to pass on to modal */
typedef struct bNodeLinkDrag {
- struct bNodeLinkDrag *next, *prev;
-
- /* List of links dragged by the operator.
- * Note: This is a list of LinkData structs on top of the actual bNodeLinks.
- * This way the links can be added to the node tree while being stored in this list.
- */
- ListBase links;
- int in_out;
+ struct bNodeLinkDrag *next, *prev;
+
+ /* List of links dragged by the operator.
+ * Note: This is a list of LinkData structs on top of the actual bNodeLinks.
+ * This way the links can be added to the node tree while being stored in this list.
+ */
+ ListBase links;
+ int in_out;
} bNodeLinkDrag;
/* space_node.c */
@@ -64,19 +64,31 @@ void snode_group_offset(struct SpaceNode *snode, float *x, float *y);
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 SpaceNode *snode,
- struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key);
-void node_draw_sockets(struct View2D *v2d, const struct bContext *C, struct bNodeTree *ntree, struct bNode *node, bool draw_outputs, bool select_all);
+void node_draw_default(const struct bContext *C,
+ struct ARegion *ar,
+ struct SpaceNode *snode,
+ struct bNodeTree *ntree,
+ struct bNode *node,
+ bNodeInstanceKey key);
+void node_draw_sockets(struct View2D *v2d,
+ const struct bContext *C,
+ struct bNodeTree *ntree,
+ struct bNode *node,
+ bool draw_outputs,
+ bool select_all);
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_update_nodetree(const struct bContext *C, struct bNodeTree *ntree);
-void node_draw_nodetree(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode,
- struct bNodeTree *ntree, bNodeInstanceKey parent_key);
+void node_draw_nodetree(const struct bContext *C,
+ struct ARegion *ar,
+ struct SpaceNode *snode,
+ struct bNodeTree *ntree,
+ bNodeInstanceKey parent_key);
void drawnodespace(const bContext *C, ARegion *ar);
void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode, float cursor[2]);
- /* DPI scaled coords */
+/* DPI scaled coords */
void node_to_view(struct bNode *node, float x, float y, float *rx, float *ry);
void node_to_updated_rect(struct bNode *node, rctf *r_rect);
void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry);
@@ -113,8 +125,11 @@ void NODE_OT_select_same_type_step(struct wmOperatorType *ot);
void NODE_OT_find_node(struct wmOperatorType *ot);
/* node_view.c */
-int space_node_view_flag(struct bContext *C, SpaceNode *snode, ARegion *ar,
- const int node_flag, const int smooth_viewtx);
+int space_node_view_flag(struct bContext *C,
+ SpaceNode *snode,
+ ARegion *ar,
+ const int node_flag,
+ const int smooth_viewtx);
void NODE_OT_view_all(struct wmOperatorType *ot);
void NODE_OT_view_selected(struct wmOperatorType *ot);
@@ -129,20 +144,31 @@ void nodelink_batch_start(struct SpaceNode *snode);
void nodelink_batch_end(struct SpaceNode *snode);
void node_draw_link(struct View2D *v2d, struct SpaceNode *snode, struct bNodeLink *link);
-void node_draw_link_bezier(struct View2D *v2d, struct SpaceNode *snode, struct bNodeLink *link, int th_col1, int th_col2, int th_col3);
-bool node_link_bezier_points(struct View2D *v2d, struct SpaceNode *snode, struct bNodeLink *link, float coord_array[][2], int resol);
+void node_draw_link_bezier(struct View2D *v2d,
+ struct SpaceNode *snode,
+ struct bNodeLink *link,
+ int th_col1,
+ int th_col2,
+ int th_col3);
+bool node_link_bezier_points(struct View2D *v2d,
+ struct SpaceNode *snode,
+ struct bNodeLink *link,
+ float coord_array[][2],
+ int resol);
// void node_draw_link_straight(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3 );
-void draw_nodespace_back_pix(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, bNodeInstanceKey parent_key);
-
+void draw_nodespace_back_pix(const struct bContext *C,
+ struct ARegion *ar,
+ struct SpaceNode *snode,
+ bNodeInstanceKey parent_key);
/* node_add.c */
-bNode *node_add_node(const struct bContext *C, const char *idname, int type, float locx, float locy);
+bNode *node_add_node(
+ const struct bContext *C, const char *idname, int type, float locx, float locy);
void NODE_OT_add_reroute(struct wmOperatorType *ot);
void NODE_OT_add_file(struct wmOperatorType *ot);
void NODE_OT_add_mask(struct wmOperatorType *ot);
void NODE_OT_new_node_tree(struct wmOperatorType *ot);
-
/* node_group.c */
void NODE_OT_group_make(struct wmOperatorType *ot);
void NODE_OT_group_insert(struct wmOperatorType *ot);
@@ -150,7 +176,6 @@ void NODE_OT_group_ungroup(struct wmOperatorType *ot);
void NODE_OT_group_separate(struct wmOperatorType *ot);
void NODE_OT_group_edit(struct wmOperatorType *ot);
-
/* node_relationships.c */
bool node_connected_to_output(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node);
@@ -180,7 +205,11 @@ 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_render_changed_exec(bContext *, struct wmOperator *);
-int node_find_indicated_socket(struct SpaceNode *snode, struct bNode **nodep, struct bNodeSocket **sockp, float cursor[2], int in_out);
+int node_find_indicated_socket(struct SpaceNode *snode,
+ struct bNode **nodep,
+ struct bNodeSocket **sockp,
+ float cursor[2],
+ int in_out);
void NODE_OT_duplicate(struct wmOperatorType *ot);
void NODE_OT_delete(struct wmOperatorType *ot);
@@ -201,7 +230,7 @@ void NODE_OT_output_file_add_socket(struct wmOperatorType *ot);
void NODE_OT_output_file_remove_active_socket(struct wmOperatorType *ot);
void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot);
-void NODE_OT_switch_view_update (struct wmOperatorType *ot);
+void NODE_OT_switch_view_update(struct wmOperatorType *ot);
/* Note: clipboard_cut is a simple macro of copy + delete */
void NODE_OT_clipboard_copy(struct wmOperatorType *ot);
@@ -230,36 +259,36 @@ extern const char *node_context_dir[];
// XXXXXX
// nodes draw without dpi - the view zoom is flexible
-#define HIDDEN_RAD (0.75f * U.widget_unit)
-#define BASIS_RAD (0.2f * U.widget_unit)
-#define NODE_DYS (U.widget_unit / 2)
-#define NODE_DY U.widget_unit
-#define NODE_SOCKDY (0.08f * U.widget_unit)
-#define NODE_WIDTH(node) (node->width * UI_DPI_FAC)
+#define HIDDEN_RAD (0.75f * U.widget_unit)
+#define BASIS_RAD (0.2f * U.widget_unit)
+#define NODE_DYS (U.widget_unit / 2)
+#define NODE_DY U.widget_unit
+#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_SOCKSIZE (0.25f * U.widget_unit)
+#define NODE_MARGIN_X (0.75f * 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
// XXX button events (butspace)
enum eNodeSpace_ButEvents {
- B_NOP = 0,
- B_REDR = 1,
- B_NODE_USEMAT,
- B_NODE_USESCENE,
- B_NODE_USETEX,
- B_TEXBROWSE,
- B_TEXALONE,
- B_TEXLOCAL,
- B_TEXDELETE,
- B_TEXPRV,
- B_AUTOTEXNAME,
- B_KEEPDATA,
- B_NODE_EXEC,
- B_MATPRV,
- B_NODE_LOADIMAGE,
- B_NODE_SETIMAGE,
+ B_NOP = 0,
+ B_REDR = 1,
+ B_NODE_USEMAT,
+ B_NODE_USESCENE,
+ B_NODE_USETEX,
+ B_TEXBROWSE,
+ B_TEXALONE,
+ B_TEXLOCAL,
+ B_TEXDELETE,
+ B_TEXPRV,
+ B_AUTOTEXNAME,
+ B_KEEPDATA,
+ B_NODE_EXEC,
+ B_MATPRV,
+ B_NODE_LOADIMAGE,
+ B_NODE_SETIMAGE,
};
#endif /* __NODE_INTERN_H__ */
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c
index 517e4df1dc1..ce6bf2820c6 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.c
@@ -21,14 +21,13 @@
* \ingroup spnode
*/
-
#include "DNA_node_types.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "ED_node.h" /* own include */
+#include "ED_node.h" /* own include */
#include "ED_screen.h"
#include "ED_select_utils.h"
#include "ED_transform.h"
@@ -38,170 +37,180 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "node_intern.h" /* own include */
+#include "node_intern.h" /* own include */
void node_operatortypes(void)
{
- WM_operatortype_append(NODE_OT_properties);
- WM_operatortype_append(NODE_OT_toolbar);
+ WM_operatortype_append(NODE_OT_properties);
+ WM_operatortype_append(NODE_OT_toolbar);
- WM_operatortype_append(NODE_OT_select);
- WM_operatortype_append(NODE_OT_select_all);
- WM_operatortype_append(NODE_OT_select_linked_to);
- WM_operatortype_append(NODE_OT_select_linked_from);
- WM_operatortype_append(NODE_OT_select_box);
- WM_operatortype_append(NODE_OT_select_circle);
- WM_operatortype_append(NODE_OT_select_lasso);
- WM_operatortype_append(NODE_OT_select_grouped);
- WM_operatortype_append(NODE_OT_select_same_type_step);
+ WM_operatortype_append(NODE_OT_select);
+ WM_operatortype_append(NODE_OT_select_all);
+ WM_operatortype_append(NODE_OT_select_linked_to);
+ WM_operatortype_append(NODE_OT_select_linked_from);
+ WM_operatortype_append(NODE_OT_select_box);
+ WM_operatortype_append(NODE_OT_select_circle);
+ WM_operatortype_append(NODE_OT_select_lasso);
+ WM_operatortype_append(NODE_OT_select_grouped);
+ WM_operatortype_append(NODE_OT_select_same_type_step);
- WM_operatortype_append(NODE_OT_find_node);
+ WM_operatortype_append(NODE_OT_find_node);
- WM_operatortype_append(NODE_OT_view_all);
- WM_operatortype_append(NODE_OT_view_selected);
+ WM_operatortype_append(NODE_OT_view_all);
+ WM_operatortype_append(NODE_OT_view_selected);
- WM_operatortype_append(NODE_OT_mute_toggle);
- WM_operatortype_append(NODE_OT_hide_toggle);
- WM_operatortype_append(NODE_OT_preview_toggle);
- WM_operatortype_append(NODE_OT_options_toggle);
- WM_operatortype_append(NODE_OT_hide_socket_toggle);
- WM_operatortype_append(NODE_OT_node_copy_color);
+ WM_operatortype_append(NODE_OT_mute_toggle);
+ WM_operatortype_append(NODE_OT_hide_toggle);
+ WM_operatortype_append(NODE_OT_preview_toggle);
+ WM_operatortype_append(NODE_OT_options_toggle);
+ WM_operatortype_append(NODE_OT_hide_socket_toggle);
+ WM_operatortype_append(NODE_OT_node_copy_color);
- WM_operatortype_append(NODE_OT_duplicate);
- WM_operatortype_append(NODE_OT_delete);
- WM_operatortype_append(NODE_OT_delete_reconnect);
- WM_operatortype_append(NODE_OT_resize);
+ WM_operatortype_append(NODE_OT_duplicate);
+ WM_operatortype_append(NODE_OT_delete);
+ WM_operatortype_append(NODE_OT_delete_reconnect);
+ WM_operatortype_append(NODE_OT_resize);
- WM_operatortype_append(NODE_OT_link);
- WM_operatortype_append(NODE_OT_link_make);
- WM_operatortype_append(NODE_OT_links_cut);
- WM_operatortype_append(NODE_OT_links_detach);
- WM_operatortype_append(NODE_OT_add_reroute);
+ WM_operatortype_append(NODE_OT_link);
+ WM_operatortype_append(NODE_OT_link_make);
+ WM_operatortype_append(NODE_OT_links_cut);
+ WM_operatortype_append(NODE_OT_links_detach);
+ WM_operatortype_append(NODE_OT_add_reroute);
- WM_operatortype_append(NODE_OT_group_make);
- WM_operatortype_append(NODE_OT_group_insert);
- WM_operatortype_append(NODE_OT_group_ungroup);
- WM_operatortype_append(NODE_OT_group_separate);
- WM_operatortype_append(NODE_OT_group_edit);
+ WM_operatortype_append(NODE_OT_group_make);
+ WM_operatortype_append(NODE_OT_group_insert);
+ WM_operatortype_append(NODE_OT_group_ungroup);
+ WM_operatortype_append(NODE_OT_group_separate);
+ WM_operatortype_append(NODE_OT_group_edit);
- WM_operatortype_append(NODE_OT_link_viewer);
+ WM_operatortype_append(NODE_OT_link_viewer);
- WM_operatortype_append(NODE_OT_insert_offset);
+ WM_operatortype_append(NODE_OT_insert_offset);
- WM_operatortype_append(NODE_OT_read_viewlayers);
- WM_operatortype_append(NODE_OT_render_changed);
+ WM_operatortype_append(NODE_OT_read_viewlayers);
+ WM_operatortype_append(NODE_OT_render_changed);
- WM_operatortype_append(NODE_OT_backimage_move);
- WM_operatortype_append(NODE_OT_backimage_zoom);
- WM_operatortype_append(NODE_OT_backimage_fit);
- WM_operatortype_append(NODE_OT_backimage_sample);
+ WM_operatortype_append(NODE_OT_backimage_move);
+ WM_operatortype_append(NODE_OT_backimage_zoom);
+ WM_operatortype_append(NODE_OT_backimage_fit);
+ WM_operatortype_append(NODE_OT_backimage_sample);
- WM_operatortype_append(NODE_OT_add_file);
- WM_operatortype_append(NODE_OT_add_mask);
+ WM_operatortype_append(NODE_OT_add_file);
+ WM_operatortype_append(NODE_OT_add_mask);
- WM_operatortype_append(NODE_OT_new_node_tree);
+ WM_operatortype_append(NODE_OT_new_node_tree);
- WM_operatortype_append(NODE_OT_output_file_add_socket);
- WM_operatortype_append(NODE_OT_output_file_remove_active_socket);
- WM_operatortype_append(NODE_OT_output_file_move_active_socket);
+ WM_operatortype_append(NODE_OT_output_file_add_socket);
+ WM_operatortype_append(NODE_OT_output_file_remove_active_socket);
+ WM_operatortype_append(NODE_OT_output_file_move_active_socket);
- WM_operatortype_append(NODE_OT_parent_set);
- WM_operatortype_append(NODE_OT_join);
- WM_operatortype_append(NODE_OT_attach);
- WM_operatortype_append(NODE_OT_detach);
+ WM_operatortype_append(NODE_OT_parent_set);
+ WM_operatortype_append(NODE_OT_join);
+ WM_operatortype_append(NODE_OT_attach);
+ WM_operatortype_append(NODE_OT_detach);
- WM_operatortype_append(NODE_OT_clipboard_copy);
- WM_operatortype_append(NODE_OT_clipboard_paste);
+ WM_operatortype_append(NODE_OT_clipboard_copy);
+ WM_operatortype_append(NODE_OT_clipboard_paste);
- WM_operatortype_append(NODE_OT_shader_script_update);
+ WM_operatortype_append(NODE_OT_shader_script_update);
- WM_operatortype_append(NODE_OT_viewer_border);
- WM_operatortype_append(NODE_OT_clear_viewer_border);
+ WM_operatortype_append(NODE_OT_viewer_border);
+ WM_operatortype_append(NODE_OT_clear_viewer_border);
- WM_operatortype_append(NODE_OT_switch_view_update);
+ WM_operatortype_append(NODE_OT_switch_view_update);
- WM_operatortype_append(NODE_OT_tree_socket_add);
- WM_operatortype_append(NODE_OT_tree_socket_remove);
- WM_operatortype_append(NODE_OT_tree_socket_move);
+ WM_operatortype_append(NODE_OT_tree_socket_add);
+ WM_operatortype_append(NODE_OT_tree_socket_remove);
+ WM_operatortype_append(NODE_OT_tree_socket_move);
- WM_operatortype_append(NODE_OT_cryptomatte_layer_add);
- WM_operatortype_append(NODE_OT_cryptomatte_layer_remove);
+ WM_operatortype_append(NODE_OT_cryptomatte_layer_add);
+ WM_operatortype_append(NODE_OT_cryptomatte_layer_remove);
}
void ED_operatormacros_node(void)
{
- wmOperatorType *ot;
- wmOperatorTypeMacro *mot;
-
- ot = WM_operatortype_append_macro("NODE_OT_select_link_viewer", "Link Viewer",
- "Select node and link it to a viewer node",
- OPTYPE_UNDO);
- mot = WM_operatortype_macro_define(ot, "NODE_OT_select");
- RNA_boolean_set(mot->ptr, "extend", false);
- RNA_boolean_set(mot->ptr, "socket_select", true);
- WM_operatortype_macro_define(ot, "NODE_OT_link_viewer");
-
- ot = WM_operatortype_append_macro("NODE_OT_translate_attach", "Move and Attach",
- "Move nodes and attach to frame",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- mot = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_boolean_set(mot->ptr, "release_confirm", true);
- WM_operatortype_macro_define(ot, "NODE_OT_attach");
- WM_operatortype_macro_define(ot, "NODE_OT_insert_offset");
-
- /* NODE_OT_translate_attach with remove_on_canel set to true */
- ot = WM_operatortype_append_macro("NODE_OT_translate_attach_remove_on_cancel", "Move and Attach",
- "Move nodes and attach to frame",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- mot = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_boolean_set(mot->ptr, "release_confirm", true);
- RNA_boolean_set(mot->ptr, "remove_on_cancel", true);
- WM_operatortype_macro_define(ot, "NODE_OT_attach");
- WM_operatortype_macro_define(ot, "NODE_OT_insert_offset");
-
- /* Note: Currently not in a default keymap or menu due to messy keymaps
- * and tricky invoke functionality.
- * Kept around in case users want to make own shortcuts.
- */
- ot = WM_operatortype_append_macro("NODE_OT_detach_translate_attach", "Detach and Move",
- "Detach nodes, move and attach to frame",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "NODE_OT_detach");
- mot = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_boolean_set(mot->ptr, "release_confirm", true);
- WM_operatortype_macro_define(ot, "NODE_OT_attach");
-
- ot = WM_operatortype_append_macro("NODE_OT_duplicate_move", "Duplicate",
- "Duplicate selected nodes and move them",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "NODE_OT_duplicate");
- WM_operatortype_macro_define(ot, "NODE_OT_translate_attach");
-
- /* modified operator call for duplicating with input links */
- ot = WM_operatortype_append_macro("NODE_OT_duplicate_move_keep_inputs", "Duplicate",
- "Duplicate selected nodes keeping input links and move them",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- mot = WM_operatortype_macro_define(ot, "NODE_OT_duplicate");
- RNA_boolean_set(mot->ptr, "keep_inputs", true);
- WM_operatortype_macro_define(ot, "NODE_OT_translate_attach");
-
- ot = WM_operatortype_append_macro("NODE_OT_move_detach_links", "Detach", "Move a node to detach links",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "NODE_OT_links_detach");
- WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- WM_operatortype_macro_define(ot, "NODE_OT_insert_offset");
-
- ot = WM_operatortype_append_macro("NODE_OT_move_detach_links_release", "Detach", "Move a node to detach links",
- OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "NODE_OT_links_detach");
- WM_operatortype_macro_define(ot, "NODE_OT_translate_attach");
+ wmOperatorType *ot;
+ wmOperatorTypeMacro *mot;
+
+ ot = WM_operatortype_append_macro("NODE_OT_select_link_viewer",
+ "Link Viewer",
+ "Select node and link it to a viewer node",
+ OPTYPE_UNDO);
+ mot = WM_operatortype_macro_define(ot, "NODE_OT_select");
+ RNA_boolean_set(mot->ptr, "extend", false);
+ RNA_boolean_set(mot->ptr, "socket_select", true);
+ WM_operatortype_macro_define(ot, "NODE_OT_link_viewer");
+
+ ot = WM_operatortype_append_macro("NODE_OT_translate_attach",
+ "Move and Attach",
+ "Move nodes and attach to frame",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ mot = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_boolean_set(mot->ptr, "release_confirm", true);
+ WM_operatortype_macro_define(ot, "NODE_OT_attach");
+ WM_operatortype_macro_define(ot, "NODE_OT_insert_offset");
+
+ /* NODE_OT_translate_attach with remove_on_canel set to true */
+ ot = WM_operatortype_append_macro("NODE_OT_translate_attach_remove_on_cancel",
+ "Move and Attach",
+ "Move nodes and attach to frame",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ mot = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_boolean_set(mot->ptr, "release_confirm", true);
+ RNA_boolean_set(mot->ptr, "remove_on_cancel", true);
+ WM_operatortype_macro_define(ot, "NODE_OT_attach");
+ WM_operatortype_macro_define(ot, "NODE_OT_insert_offset");
+
+ /* Note: Currently not in a default keymap or menu due to messy keymaps
+ * and tricky invoke functionality.
+ * Kept around in case users want to make own shortcuts.
+ */
+ ot = WM_operatortype_append_macro("NODE_OT_detach_translate_attach",
+ "Detach and Move",
+ "Detach nodes, move and attach to frame",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "NODE_OT_detach");
+ mot = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_boolean_set(mot->ptr, "release_confirm", true);
+ WM_operatortype_macro_define(ot, "NODE_OT_attach");
+
+ ot = WM_operatortype_append_macro("NODE_OT_duplicate_move",
+ "Duplicate",
+ "Duplicate selected nodes and move them",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "NODE_OT_duplicate");
+ WM_operatortype_macro_define(ot, "NODE_OT_translate_attach");
+
+ /* modified operator call for duplicating with input links */
+ ot = WM_operatortype_append_macro("NODE_OT_duplicate_move_keep_inputs",
+ "Duplicate",
+ "Duplicate selected nodes keeping input links and move them",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ mot = WM_operatortype_macro_define(ot, "NODE_OT_duplicate");
+ RNA_boolean_set(mot->ptr, "keep_inputs", true);
+ WM_operatortype_macro_define(ot, "NODE_OT_translate_attach");
+
+ ot = WM_operatortype_append_macro("NODE_OT_move_detach_links",
+ "Detach",
+ "Move a node to detach links",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "NODE_OT_links_detach");
+ WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ WM_operatortype_macro_define(ot, "NODE_OT_insert_offset");
+
+ ot = WM_operatortype_append_macro("NODE_OT_move_detach_links_release",
+ "Detach",
+ "Move a node to detach links",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "NODE_OT_links_detach");
+ WM_operatortype_macro_define(ot, "NODE_OT_translate_attach");
}
void node_keymap(struct wmKeyConfig *keyconf)
{
- /* Entire Editor only ----------------- */
- WM_keymap_ensure(keyconf, "Node Generic", SPACE_NODE, 0);
+ /* Entire Editor only ----------------- */
+ WM_keymap_ensure(keyconf, "Node Generic", SPACE_NODE, 0);
- /* Main Region only ----------------- */
- WM_keymap_ensure(keyconf, "Node Editor", SPACE_NODE, 0);
+ /* Main Region only ----------------- */
+ WM_keymap_ensure(keyconf, "Node Editor", SPACE_NODE, 0);
}
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index afb0c833aa8..14636dad8c6 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -36,7 +36,7 @@
#include "BKE_main.h"
#include "BKE_node.h"
-#include "ED_node.h" /* own include */
+#include "ED_node.h" /* own include */
#include "ED_screen.h"
#include "ED_render.h"
#include "ED_util.h"
@@ -52,913 +52,905 @@
#include "BLT_translation.h"
-#include "node_intern.h" /* own include */
+#include "node_intern.h" /* own include */
/* ****************** Relations helpers *********************** */
static bool ntree_has_drivers(bNodeTree *ntree)
{
- AnimData *adt = BKE_animdata_from_id(&ntree->id);
- if (adt == NULL) {
- return false;
- }
- return !BLI_listbase_is_empty(&adt->drivers);
+ AnimData *adt = BKE_animdata_from_id(&ntree->id);
+ if (adt == NULL) {
+ return false;
+ }
+ return !BLI_listbase_is_empty(&adt->drivers);
}
-static bool ntree_check_nodes_connected_dfs(bNodeTree *ntree,
- bNode *from,
- bNode *to)
+static bool ntree_check_nodes_connected_dfs(bNodeTree *ntree, bNode *from, bNode *to)
{
- if (from->flag & NODE_TEST) {
- return false;
- }
- from->flag |= NODE_TEST;
- for (bNodeLink *link = ntree->links.first; link != NULL; link = link->next) {
- if (link->fromnode == from) {
- if (link->tonode == to) {
- return true;
- }
- else {
- if (ntree_check_nodes_connected_dfs(ntree, link->tonode, to)) {
- return true;
- }
- }
- }
- }
- return false;
+ if (from->flag & NODE_TEST) {
+ return false;
+ }
+ from->flag |= NODE_TEST;
+ for (bNodeLink *link = ntree->links.first; link != NULL; link = link->next) {
+ if (link->fromnode == from) {
+ if (link->tonode == to) {
+ return true;
+ }
+ else {
+ if (ntree_check_nodes_connected_dfs(ntree, link->tonode, to)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
}
static bool ntree_check_nodes_connected(bNodeTree *ntree, bNode *from, bNode *to)
{
- if (from == to) {
- return true;
- }
- ntreeNodeFlagSet(ntree, NODE_TEST, false);
- return ntree_check_nodes_connected_dfs(ntree, from, to);
+ if (from == to) {
+ return true;
+ }
+ ntreeNodeFlagSet(ntree, NODE_TEST, false);
+ return ntree_check_nodes_connected_dfs(ntree, from, to);
}
static bool node_group_has_output_dfs(bNode *node)
{
- bNodeTree *ntree = (bNodeTree *)node->id;
- if (ntree->id.tag & LIB_TAG_DOIT) {
- return false;
- }
- ntree->id.tag |= LIB_TAG_DOIT;
- for (bNode *current_node = ntree->nodes.first;
- current_node != NULL;
- current_node = current_node->next)
- {
- if (current_node->type == NODE_GROUP) {
- if (current_node->id && node_group_has_output_dfs(current_node)) {
- return true;
- }
- }
- if (current_node->flag & NODE_DO_OUTPUT &&
- current_node->type != NODE_GROUP_OUTPUT)
- {
- return true;
- }
- }
- return false;
+ bNodeTree *ntree = (bNodeTree *)node->id;
+ if (ntree->id.tag & LIB_TAG_DOIT) {
+ return false;
+ }
+ ntree->id.tag |= LIB_TAG_DOIT;
+ for (bNode *current_node = ntree->nodes.first; current_node != NULL;
+ current_node = current_node->next) {
+ if (current_node->type == NODE_GROUP) {
+ if (current_node->id && node_group_has_output_dfs(current_node)) {
+ return true;
+ }
+ }
+ if (current_node->flag & NODE_DO_OUTPUT && current_node->type != NODE_GROUP_OUTPUT) {
+ return true;
+ }
+ }
+ return false;
}
static bool node_group_has_output(Main *bmain, bNode *node)
{
- BLI_assert(ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP));
- bNodeTree *ntree = (bNodeTree *)node->id;
- if (ntree == NULL) {
- return false;
- }
- BKE_main_id_tag_listbase(&bmain->nodetrees, LIB_TAG_DOIT, false);
- return node_group_has_output_dfs(node);
+ BLI_assert(ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP));
+ bNodeTree *ntree = (bNodeTree *)node->id;
+ if (ntree == NULL) {
+ return false;
+ }
+ BKE_main_id_tag_listbase(&bmain->nodetrees, LIB_TAG_DOIT, false);
+ return node_group_has_output_dfs(node);
}
bool node_connected_to_output(Main *bmain, bNodeTree *ntree, bNode *node)
{
- /* Special case for drivers: if node tree has any drivers we assume it is
- * always to be tagged for update when node changes. Otherwise we will be
- * doomed to do some deep and nasty deep search of indirect dependencies,
- * which will be too complicated without real benefit.
- */
- if (ntree_has_drivers(ntree)) {
- return true;
- }
- for (bNode *current_node = ntree->nodes.first;
- current_node != NULL;
- current_node = current_node->next)
- {
- /* Special case for group nodes -- if modified node connected to a group
- * with active output inside we consider refresh is needed.
- *
- * We could make check more grained here by taking which socket the node
- * is connected to and so eventually.
- */
- if (ELEM(current_node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
- if (current_node->id != NULL &&
- ntree_has_drivers((bNodeTree *)current_node->id))
- {
- return true;
- }
- if (ntree_check_nodes_connected(ntree, node, current_node) &&
- node_group_has_output(bmain, current_node))
- {
- return true;
- }
- }
- if (current_node->flag & NODE_DO_OUTPUT) {
- if (ntree_check_nodes_connected(ntree, node, current_node)) {
- return true;
- }
- }
- }
- return false;
+ /* Special case for drivers: if node tree has any drivers we assume it is
+ * always to be tagged for update when node changes. Otherwise we will be
+ * doomed to do some deep and nasty deep search of indirect dependencies,
+ * which will be too complicated without real benefit.
+ */
+ if (ntree_has_drivers(ntree)) {
+ return true;
+ }
+ for (bNode *current_node = ntree->nodes.first; current_node != NULL;
+ current_node = current_node->next) {
+ /* Special case for group nodes -- if modified node connected to a group
+ * with active output inside we consider refresh is needed.
+ *
+ * We could make check more grained here by taking which socket the node
+ * is connected to and so eventually.
+ */
+ if (ELEM(current_node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
+ if (current_node->id != NULL && ntree_has_drivers((bNodeTree *)current_node->id)) {
+ return true;
+ }
+ if (ntree_check_nodes_connected(ntree, node, current_node) &&
+ node_group_has_output(bmain, current_node)) {
+ return true;
+ }
+ }
+ if (current_node->flag & NODE_DO_OUTPUT) {
+ if (ntree_check_nodes_connected(ntree, node, current_node)) {
+ return true;
+ }
+ }
+ }
+ return false;
}
/* ****************** Add *********************** */
-
typedef struct bNodeListItem {
- struct bNodeListItem *next, *prev;
- struct bNode *node;
+ struct bNodeListItem *next, *prev;
+ struct bNode *node;
} bNodeListItem;
typedef struct NodeInsertOfsData {
- bNodeTree *ntree;
- bNode *insert; /* inserted node */
- bNode *prev, *next; /* prev/next node in the chain */
- bNode *insert_parent;
+ bNodeTree *ntree;
+ bNode *insert; /* inserted node */
+ bNode *prev, *next; /* prev/next node in the chain */
+ bNode *insert_parent;
- wmTimer *anim_timer;
+ wmTimer *anim_timer;
- float offset_x; /* offset to apply to node chain */
+ float offset_x; /* offset to apply to node chain */
} NodeInsertOfsData;
static int sort_nodes_locx(const void *a, const void *b)
{
- const bNodeListItem *nli1 = a;
- const bNodeListItem *nli2 = b;
- const bNode *node1 = nli1->node;
- const bNode *node2 = nli2->node;
-
- if (node1->locx > node2->locx) {
- return 1;
- }
- else {
- return 0;
- }
+ const bNodeListItem *nli1 = a;
+ const bNodeListItem *nli2 = b;
+ const bNode *node1 = nli1->node;
+ const bNode *node2 = nli2->node;
+
+ if (node1->locx > node2->locx) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
static bool socket_is_available(bNodeTree *UNUSED(ntree), bNodeSocket *sock, const bool allow_used)
{
- if (nodeSocketIsHidden(sock)) {
- return 0;
- }
+ if (nodeSocketIsHidden(sock)) {
+ return 0;
+ }
- if (!allow_used && (sock->flag & SOCK_IN_USE)) {
- return 0;
- }
+ if (!allow_used && (sock->flag & SOCK_IN_USE)) {
+ return 0;
+ }
- return 1;
+ return 1;
}
-static bNodeSocket *best_socket_output(bNodeTree *ntree, bNode *node, bNodeSocket *sock_target, const bool allow_multiple)
+static bNodeSocket *best_socket_output(bNodeTree *ntree,
+ bNode *node,
+ bNodeSocket *sock_target,
+ const bool allow_multiple)
{
- bNodeSocket *sock;
-
- /* first look for selected output */
- for (sock = node->outputs.first; sock; sock = sock->next) {
- if (!socket_is_available(ntree, sock, allow_multiple)) {
- continue;
- }
-
- if (sock->flag & SELECT) {
- return sock;
- }
- }
-
- /* try to find a socket with a matching name */
- for (sock = node->outputs.first; sock; sock = sock->next) {
- if (!socket_is_available(ntree, sock, allow_multiple)) {
- continue;
- }
-
- /* check for same types */
- if (sock->type == sock_target->type) {
- if (STREQ(sock->name, sock_target->name)) {
- return sock;
- }
- }
- }
-
- /* otherwise settle for the first available socket of the right type */
- for (sock = node->outputs.first; sock; sock = sock->next) {
-
- if (!socket_is_available(ntree, sock, allow_multiple)) {
- continue;
- }
-
- /* check for same types */
- if (sock->type == sock_target->type) {
- return sock;
- }
- }
-
- return NULL;
+ bNodeSocket *sock;
+
+ /* first look for selected output */
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ if (!socket_is_available(ntree, sock, allow_multiple)) {
+ continue;
+ }
+
+ if (sock->flag & SELECT) {
+ return sock;
+ }
+ }
+
+ /* try to find a socket with a matching name */
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ if (!socket_is_available(ntree, sock, allow_multiple)) {
+ continue;
+ }
+
+ /* check for same types */
+ if (sock->type == sock_target->type) {
+ if (STREQ(sock->name, sock_target->name)) {
+ return sock;
+ }
+ }
+ }
+
+ /* otherwise settle for the first available socket of the right type */
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+
+ if (!socket_is_available(ntree, sock, allow_multiple)) {
+ continue;
+ }
+
+ /* check for same types */
+ if (sock->type == sock_target->type) {
+ return sock;
+ }
+ }
+
+ return NULL;
}
/* this is a bit complicated, but designed to prioritize finding
* sockets of higher types, such as image, first */
static bNodeSocket *best_socket_input(bNodeTree *ntree, bNode *node, int num, int replace)
{
- bNodeSocket *sock;
- int socktype, maxtype = 0;
- int a = 0;
-
- for (sock = node->inputs.first; sock; sock = sock->next) {
- maxtype = max_ii(sock->type, maxtype);
- }
-
- /* find sockets of higher 'types' first (i.e. image) */
- for (socktype = maxtype; socktype >= 0; socktype--) {
- for (sock = node->inputs.first; sock; sock = sock->next) {
-
- if (!socket_is_available(ntree, sock, replace)) {
- a++;
- continue;
- }
-
- if (sock->type == socktype) {
- /* increment to make sure we don't keep finding
- * the same socket on every attempt running this function */
- a++;
- if (a > num) {
- return sock;
- }
- }
- }
- }
-
- return NULL;
+ bNodeSocket *sock;
+ int socktype, maxtype = 0;
+ int a = 0;
+
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ maxtype = max_ii(sock->type, maxtype);
+ }
+
+ /* find sockets of higher 'types' first (i.e. image) */
+ for (socktype = maxtype; socktype >= 0; socktype--) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+
+ if (!socket_is_available(ntree, sock, replace)) {
+ a++;
+ continue;
+ }
+
+ if (sock->type == socktype) {
+ /* increment to make sure we don't keep finding
+ * the same socket on every attempt running this function */
+ a++;
+ if (a > num) {
+ return sock;
+ }
+ }
+ }
+ }
+
+ return NULL;
}
-static bool snode_autoconnect_input(SpaceNode *snode, bNode *node_fr, bNodeSocket *sock_fr, bNode *node_to, bNodeSocket *sock_to, int replace)
+static bool snode_autoconnect_input(SpaceNode *snode,
+ bNode *node_fr,
+ bNodeSocket *sock_fr,
+ bNode *node_to,
+ bNodeSocket *sock_to,
+ int replace)
{
- bNodeTree *ntree = snode->edittree;
+ bNodeTree *ntree = snode->edittree;
- /* then we can connect */
- if (replace) {
- nodeRemSocketLinks(ntree, sock_to);
- }
+ /* then we can connect */
+ if (replace) {
+ nodeRemSocketLinks(ntree, sock_to);
+ }
- nodeAddLink(ntree, node_fr, sock_fr, node_to, sock_to);
- return true;
+ nodeAddLink(ntree, node_fr, sock_fr, node_to, sock_to);
+ return true;
}
-static void snode_autoconnect(Main *bmain, SpaceNode *snode, const bool allow_multiple, const bool replace)
+static void snode_autoconnect(Main *bmain,
+ SpaceNode *snode,
+ const bool allow_multiple,
+ const bool replace)
{
- bNodeTree *ntree = snode->edittree;
- ListBase *nodelist = MEM_callocN(sizeof(ListBase), "items_list");
- bNodeListItem *nli;
- bNode *node;
- int i, numlinks = 0;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_SELECT) {
- nli = MEM_mallocN(sizeof(bNodeListItem), "temporary node list item");
- nli->node = node;
- BLI_addtail(nodelist, nli);
- }
- }
-
- /* sort nodes left to right */
- BLI_listbase_sort(nodelist, sort_nodes_locx);
-
- for (nli = nodelist->first; nli; nli = nli->next) {
- bNode *node_fr, *node_to;
- bNodeSocket *sock_fr, *sock_to;
- bool has_selected_inputs = false;
-
- if (nli->next == NULL) {
- break;
- }
-
- node_fr = nli->node;
- node_to = nli->next->node;
- /* corner case: input/output node aligned the wrong way around (T47729) */
- if (BLI_listbase_is_empty(&node_to->inputs) || BLI_listbase_is_empty(&node_fr->outputs)) {
- SWAP(bNode *, node_fr, node_to);
- }
-
- /* if there are selected sockets, connect those */
- for (sock_to = node_to->inputs.first; sock_to; sock_to = sock_to->next) {
- if (sock_to->flag & SELECT) {
- has_selected_inputs = 1;
-
- if (!socket_is_available(ntree, sock_to, replace)) {
- continue;
- }
-
- /* check for an appropriate output socket to connect from */
- sock_fr = best_socket_output(ntree, node_fr, sock_to, allow_multiple);
- if (!sock_fr) {
- continue;
- }
-
- if (snode_autoconnect_input(snode, node_fr, sock_fr, node_to, sock_to, replace)) {
- numlinks++;
- }
- }
- }
-
- if (!has_selected_inputs) {
- /* no selected inputs, connect by finding suitable match */
- int num_inputs = BLI_listbase_count(&node_to->inputs);
-
- for (i = 0; i < num_inputs; i++) {
-
- /* find the best guess input socket */
- sock_to = best_socket_input(ntree, node_to, i, replace);
- if (!sock_to) {
- continue;
- }
-
- /* check for an appropriate output socket to connect from */
- sock_fr = best_socket_output(ntree, node_fr, sock_to, allow_multiple);
- if (!sock_fr) {
- continue;
- }
-
- if (snode_autoconnect_input(snode, node_fr, sock_fr, node_to, sock_to, replace)) {
- numlinks++;
- break;
- }
- }
- }
- }
-
- if (numlinks > 0) {
- ntreeUpdateTree(bmain, ntree);
- }
-
- BLI_freelistN(nodelist);
- MEM_freeN(nodelist);
+ bNodeTree *ntree = snode->edittree;
+ ListBase *nodelist = MEM_callocN(sizeof(ListBase), "items_list");
+ bNodeListItem *nli;
+ bNode *node;
+ int i, numlinks = 0;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->flag & NODE_SELECT) {
+ nli = MEM_mallocN(sizeof(bNodeListItem), "temporary node list item");
+ nli->node = node;
+ BLI_addtail(nodelist, nli);
+ }
+ }
+
+ /* sort nodes left to right */
+ BLI_listbase_sort(nodelist, sort_nodes_locx);
+
+ for (nli = nodelist->first; nli; nli = nli->next) {
+ bNode *node_fr, *node_to;
+ bNodeSocket *sock_fr, *sock_to;
+ bool has_selected_inputs = false;
+
+ if (nli->next == NULL) {
+ break;
+ }
+
+ node_fr = nli->node;
+ node_to = nli->next->node;
+ /* corner case: input/output node aligned the wrong way around (T47729) */
+ if (BLI_listbase_is_empty(&node_to->inputs) || BLI_listbase_is_empty(&node_fr->outputs)) {
+ SWAP(bNode *, node_fr, node_to);
+ }
+
+ /* if there are selected sockets, connect those */
+ for (sock_to = node_to->inputs.first; sock_to; sock_to = sock_to->next) {
+ if (sock_to->flag & SELECT) {
+ has_selected_inputs = 1;
+
+ if (!socket_is_available(ntree, sock_to, replace)) {
+ continue;
+ }
+
+ /* check for an appropriate output socket to connect from */
+ sock_fr = best_socket_output(ntree, node_fr, sock_to, allow_multiple);
+ if (!sock_fr) {
+ continue;
+ }
+
+ if (snode_autoconnect_input(snode, node_fr, sock_fr, node_to, sock_to, replace)) {
+ numlinks++;
+ }
+ }
+ }
+
+ if (!has_selected_inputs) {
+ /* no selected inputs, connect by finding suitable match */
+ int num_inputs = BLI_listbase_count(&node_to->inputs);
+
+ for (i = 0; i < num_inputs; i++) {
+
+ /* find the best guess input socket */
+ sock_to = best_socket_input(ntree, node_to, i, replace);
+ if (!sock_to) {
+ continue;
+ }
+
+ /* check for an appropriate output socket to connect from */
+ sock_fr = best_socket_output(ntree, node_fr, sock_to, allow_multiple);
+ if (!sock_fr) {
+ continue;
+ }
+
+ if (snode_autoconnect_input(snode, node_fr, sock_fr, node_to, sock_to, replace)) {
+ numlinks++;
+ break;
+ }
+ }
+ }
+ }
+
+ if (numlinks > 0) {
+ ntreeUpdateTree(bmain, ntree);
+ }
+
+ BLI_freelistN(nodelist);
+ MEM_freeN(nodelist);
}
/* *************************** link viewer op ******************** */
static int node_link_viewer(const bContext *C, bNode *tonode)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node;
- bNodeLink *link;
- bNodeSocket *sock;
-
- /* context check */
- if (tonode == NULL || BLI_listbase_is_empty(&tonode->outputs)) {
- return OPERATOR_CANCELLED;
- }
- if (ELEM(tonode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
- return OPERATOR_CANCELLED;
- }
-
- /* get viewer */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
- if (node->flag & NODE_DO_OUTPUT) {
- break;
- }
- }
- }
- /* no viewer, we make one active */
- if (node == NULL) {
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
- node->flag |= NODE_DO_OUTPUT;
- break;
- }
- }
- }
-
- sock = NULL;
-
- /* try to find an already connected socket to cycle to the next */
- if (node) {
- link = NULL;
- for (link = snode->edittree->links.first; link; link = link->next) {
- if (link->tonode == node && link->fromnode == tonode) {
- if (link->tosock == node->inputs.first) {
- break;
- }
- }
- }
- if (link) {
- /* unlink existing connection */
- sock = link->fromsock;
- nodeRemLink(snode->edittree, link);
-
- /* find a socket after the previously connected socket */
- for (sock = sock->next; sock; sock = sock->next) {
- if (!nodeSocketIsHidden(sock)) {
- break;
- }
- }
- }
- }
-
- if (tonode) {
- /* Find a selected socket that overrides the socket to connect to */
- for (bNodeSocket *sock2 = tonode->outputs.first; sock2; sock2 = sock2->next) {
- if (!nodeSocketIsHidden(sock2) && sock2->flag & SELECT) {
- sock = sock2;
- break;
- }
- }
- }
-
-
- /* find a socket starting from the first socket */
- if (!sock) {
- for (sock = tonode->outputs.first; sock; sock = sock->next) {
- if (!nodeSocketIsHidden(sock)) {
- break;
- }
- }
- }
-
- if (sock) {
- /* add a new viewer if none exists yet */
- if (!node) {
- /* XXX location is a quick hack, just place it next to the linked socket */
- node = node_add_node(C, NULL, CMP_NODE_VIEWER, sock->locx + 100, sock->locy);
- if (!node) {
- return OPERATOR_CANCELLED;
- }
-
- link = NULL;
- }
- else {
- /* get link to viewer */
- for (link = snode->edittree->links.first; link; link = link->next) {
- if (link->tonode == node && link->tosock == node->inputs.first) {
- break;
- }
- }
- }
-
- if (link == NULL) {
- nodeAddLink(snode->edittree, tonode, sock, node, node->inputs.first);
- }
- else {
- link->fromnode = tonode;
- link->fromsock = sock;
- /* make sure the dependency sorting is updated */
- snode->edittree->update |= NTREE_UPDATE_LINKS;
- }
- ntreeUpdateTree(CTX_data_main(C), snode->edittree);
- snode_update(snode, node);
- }
-
- return OPERATOR_FINISHED;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node;
+ bNodeLink *link;
+ bNodeSocket *sock;
+
+ /* context check */
+ if (tonode == NULL || BLI_listbase_is_empty(&tonode->outputs)) {
+ return OPERATOR_CANCELLED;
+ }
+ if (ELEM(tonode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get viewer */
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+ if (node->flag & NODE_DO_OUTPUT) {
+ break;
+ }
+ }
+ }
+ /* no viewer, we make one active */
+ if (node == NULL) {
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+ node->flag |= NODE_DO_OUTPUT;
+ break;
+ }
+ }
+ }
+
+ sock = NULL;
+
+ /* try to find an already connected socket to cycle to the next */
+ if (node) {
+ link = NULL;
+ for (link = snode->edittree->links.first; link; link = link->next) {
+ if (link->tonode == node && link->fromnode == tonode) {
+ if (link->tosock == node->inputs.first) {
+ break;
+ }
+ }
+ }
+ if (link) {
+ /* unlink existing connection */
+ sock = link->fromsock;
+ nodeRemLink(snode->edittree, link);
+
+ /* find a socket after the previously connected socket */
+ for (sock = sock->next; sock; sock = sock->next) {
+ if (!nodeSocketIsHidden(sock)) {
+ break;
+ }
+ }
+ }
+ }
+
+ if (tonode) {
+ /* Find a selected socket that overrides the socket to connect to */
+ for (bNodeSocket *sock2 = tonode->outputs.first; sock2; sock2 = sock2->next) {
+ if (!nodeSocketIsHidden(sock2) && sock2->flag & SELECT) {
+ sock = sock2;
+ break;
+ }
+ }
+ }
+
+ /* find a socket starting from the first socket */
+ if (!sock) {
+ for (sock = tonode->outputs.first; sock; sock = sock->next) {
+ if (!nodeSocketIsHidden(sock)) {
+ break;
+ }
+ }
+ }
+
+ if (sock) {
+ /* add a new viewer if none exists yet */
+ if (!node) {
+ /* XXX location is a quick hack, just place it next to the linked socket */
+ node = node_add_node(C, NULL, CMP_NODE_VIEWER, sock->locx + 100, sock->locy);
+ if (!node) {
+ return OPERATOR_CANCELLED;
+ }
+
+ link = NULL;
+ }
+ else {
+ /* get link to viewer */
+ for (link = snode->edittree->links.first; link; link = link->next) {
+ if (link->tonode == node && link->tosock == node->inputs.first) {
+ break;
+ }
+ }
+ }
+
+ if (link == NULL) {
+ nodeAddLink(snode->edittree, tonode, sock, node, node->inputs.first);
+ }
+ else {
+ link->fromnode = tonode;
+ link->fromsock = sock;
+ /* make sure the dependency sorting is updated */
+ snode->edittree->update |= NTREE_UPDATE_LINKS;
+ }
+ ntreeUpdateTree(CTX_data_main(C), snode->edittree);
+ snode_update(snode, node);
+ }
+
+ return OPERATOR_FINISHED;
}
-
static int node_active_link_viewer_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node;
- node = nodeGetActive(snode->edittree);
+ node = nodeGetActive(snode->edittree);
- if (!node) {
- return OPERATOR_CANCELLED;
- }
+ if (!node) {
+ return OPERATOR_CANCELLED;
+ }
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
- if (node_link_viewer(C, node) == OPERATOR_CANCELLED) {
- return OPERATOR_CANCELLED;
- }
+ if (node_link_viewer(C, node) == OPERATOR_CANCELLED) {
+ return OPERATOR_CANCELLED;
+ }
- snode_notify(C, snode);
+ snode_notify(C, snode);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
void NODE_OT_link_viewer(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Link to Viewer Node";
- ot->description = "Link to viewer node";
- ot->idname = "NODE_OT_link_viewer";
+ /* identifiers */
+ ot->name = "Link to Viewer Node";
+ ot->description = "Link to viewer node";
+ ot->idname = "NODE_OT_link_viewer";
- /* api callbacks */
- ot->exec = node_active_link_viewer_exec;
- ot->poll = composite_node_editable;
+ /* api callbacks */
+ ot->exec = node_active_link_viewer_exec;
+ ot->poll = composite_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/* *************************** add link op ******************** */
static void node_link_update_header(bContext *C, bNodeLinkDrag *UNUSED(nldrag))
{
- char header[UI_MAX_DRAW_STR];
+ char header[UI_MAX_DRAW_STR];
- BLI_strncpy(header, IFACE_("LMB: drag node link, RMB: cancel"), sizeof(header));
- ED_workspace_status_text(C, header);
+ BLI_strncpy(header, IFACE_("LMB: drag node link, RMB: cancel"), sizeof(header));
+ ED_workspace_status_text(C, header);
}
static int node_count_links(bNodeTree *ntree, bNodeSocket *sock)
{
- bNodeLink *link;
- int count = 0;
- for (link = ntree->links.first; link; link = link->next) {
- if (link->fromsock == sock) {
- ++count;
- }
- if (link->tosock == sock) {
- ++count;
- }
- }
- return count;
+ bNodeLink *link;
+ int count = 0;
+ for (link = ntree->links.first; link; link = link->next) {
+ if (link->fromsock == sock) {
+ ++count;
+ }
+ if (link->tosock == sock) {
+ ++count;
+ }
+ }
+ return count;
}
static void node_remove_extra_links(SpaceNode *snode, bNodeLink *link)
{
- bNodeTree *ntree = snode->edittree;
- bNodeSocket *from = link->fromsock, *to = link->tosock;
- bNodeLink *tlink, *tlink_next;
- int to_count = node_count_links(ntree, to);
- int from_count = node_count_links(ntree, from);
-
- for (tlink = ntree->links.first; tlink; tlink = tlink_next) {
- tlink_next = tlink->next;
- if (tlink == link) {
- continue;
- }
-
- if (tlink && tlink->fromsock == from) {
- if (from_count > from->limit) {
- nodeRemLink(ntree, tlink);
- tlink = NULL;
- --from_count;
- }
- }
-
- if (tlink && tlink->tosock == to) {
- if (to_count > to->limit) {
- nodeRemLink(ntree, tlink);
- tlink = NULL;
- --to_count;
- }
- }
- }
+ bNodeTree *ntree = snode->edittree;
+ bNodeSocket *from = link->fromsock, *to = link->tosock;
+ bNodeLink *tlink, *tlink_next;
+ int to_count = node_count_links(ntree, to);
+ int from_count = node_count_links(ntree, from);
+
+ for (tlink = ntree->links.first; tlink; tlink = tlink_next) {
+ tlink_next = tlink->next;
+ if (tlink == link) {
+ continue;
+ }
+
+ if (tlink && tlink->fromsock == from) {
+ if (from_count > from->limit) {
+ nodeRemLink(ntree, tlink);
+ tlink = NULL;
+ --from_count;
+ }
+ }
+
+ if (tlink && tlink->tosock == to) {
+ if (to_count > to->limit) {
+ nodeRemLink(ntree, tlink);
+ tlink = NULL;
+ --to_count;
+ }
+ }
+ }
}
static void node_link_exit(bContext *C, wmOperator *op, bool apply_links)
{
- Main *bmain = CTX_data_main(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree = snode->edittree;
- bNodeLinkDrag *nldrag = op->customdata;
- LinkData *linkdata;
- bool do_tag_update = false;
-
- /* avoid updates while applying links */
- ntree->is_updating = true;
- for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
- bNodeLink *link = linkdata->data;
-
- /* See note below, but basically TEST flag means that the link
- * was connected to output (or to a node which affects the
- * output).
- */
- do_tag_update |= (link->flag & NODE_LINK_TEST) != 0;
-
- if (apply_links && link->tosock && link->fromsock) {
- /* before actually adding the link,
- * let nodes perform special link insertion handling
- */
- if (link->fromnode->typeinfo->insert_link) {
- link->fromnode->typeinfo->insert_link(ntree, link->fromnode, link);
- }
- if (link->tonode->typeinfo->insert_link) {
- link->tonode->typeinfo->insert_link(ntree, link->tonode, link);
- }
-
- /* add link to the node tree */
- BLI_addtail(&ntree->links, link);
-
- ntree->update |= NTREE_UPDATE_LINKS;
-
- /* tag tonode for update */
- link->tonode->update |= NODE_UPDATE;
-
- /* we might need to remove a link */
- node_remove_extra_links(snode, link);
-
- if (link->tonode) {
- do_tag_update |= (do_tag_update || node_connected_to_output(bmain, ntree, link->tonode));
- }
- }
- else {
- nodeRemLink(ntree, link);
- }
- }
- ntree->is_updating = false;
-
- ntreeUpdateTree(bmain, ntree);
- snode_notify(C, snode);
- if (do_tag_update) {
- snode_dag_update(C, snode);
- }
-
- BLI_remlink(&snode->linkdrag, nldrag);
- /* links->data pointers are either held by the tree or freed already */
- BLI_freelistN(&nldrag->links);
- MEM_freeN(nldrag);
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNodeLinkDrag *nldrag = op->customdata;
+ LinkData *linkdata;
+ bool do_tag_update = false;
+
+ /* avoid updates while applying links */
+ ntree->is_updating = true;
+ for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
+ bNodeLink *link = linkdata->data;
+
+ /* See note below, but basically TEST flag means that the link
+ * was connected to output (or to a node which affects the
+ * output).
+ */
+ do_tag_update |= (link->flag & NODE_LINK_TEST) != 0;
+
+ if (apply_links && link->tosock && link->fromsock) {
+ /* before actually adding the link,
+ * let nodes perform special link insertion handling
+ */
+ if (link->fromnode->typeinfo->insert_link) {
+ link->fromnode->typeinfo->insert_link(ntree, link->fromnode, link);
+ }
+ if (link->tonode->typeinfo->insert_link) {
+ link->tonode->typeinfo->insert_link(ntree, link->tonode, link);
+ }
+
+ /* add link to the node tree */
+ BLI_addtail(&ntree->links, link);
+
+ ntree->update |= NTREE_UPDATE_LINKS;
+
+ /* tag tonode for update */
+ link->tonode->update |= NODE_UPDATE;
+
+ /* we might need to remove a link */
+ node_remove_extra_links(snode, link);
+
+ if (link->tonode) {
+ do_tag_update |= (do_tag_update || node_connected_to_output(bmain, ntree, link->tonode));
+ }
+ }
+ else {
+ nodeRemLink(ntree, link);
+ }
+ }
+ ntree->is_updating = false;
+
+ ntreeUpdateTree(bmain, ntree);
+ snode_notify(C, snode);
+ if (do_tag_update) {
+ snode_dag_update(C, snode);
+ }
+
+ BLI_remlink(&snode->linkdrag, nldrag);
+ /* links->data pointers are either held by the tree or freed already */
+ BLI_freelistN(&nldrag->links);
+ MEM_freeN(nldrag);
}
static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2])
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeLinkDrag *nldrag = op->customdata;
- bNode *tnode;
- bNodeSocket *tsock = NULL;
- LinkData *linkdata;
-
- if (nldrag->in_out == SOCK_OUT) {
- if (node_find_indicated_socket(snode, &tnode, &tsock, cursor, SOCK_IN)) {
- for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
- bNodeLink *link = linkdata->data;
-
- /* skip if this is already the target socket */
- if (link->tosock == tsock) {
- continue;
- }
- /* skip if socket is on the same node as the fromsock */
- if (tnode && link->fromnode == tnode) {
- continue;
- }
-
- /* attach links to the socket */
- link->tonode = tnode;
- link->tosock = tsock;
- }
- }
- else {
- for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
- bNodeLink *link = linkdata->data;
-
- link->tonode = NULL;
- link->tosock = NULL;
- }
- }
- }
- else {
- if (node_find_indicated_socket(snode, &tnode, &tsock, cursor, SOCK_OUT)) {
- for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
- bNodeLink *link = linkdata->data;
-
- /* skip if this is already the target socket */
- if (link->fromsock == tsock) {
- continue;
- }
- /* skip if socket is on the same node as the fromsock */
- if (tnode && link->tonode == tnode) {
- continue;
- }
-
- /* attach links to the socket */
- link->fromnode = tnode;
- link->fromsock = tsock;
- }
- }
- else {
- for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
- bNodeLink *link = linkdata->data;
-
- link->fromnode = NULL;
- link->fromsock = NULL;
- }
- }
- }
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeLinkDrag *nldrag = op->customdata;
+ bNode *tnode;
+ bNodeSocket *tsock = NULL;
+ LinkData *linkdata;
+
+ if (nldrag->in_out == SOCK_OUT) {
+ if (node_find_indicated_socket(snode, &tnode, &tsock, cursor, SOCK_IN)) {
+ for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
+ bNodeLink *link = linkdata->data;
+
+ /* skip if this is already the target socket */
+ if (link->tosock == tsock) {
+ continue;
+ }
+ /* skip if socket is on the same node as the fromsock */
+ if (tnode && link->fromnode == tnode) {
+ continue;
+ }
+
+ /* attach links to the socket */
+ link->tonode = tnode;
+ link->tosock = tsock;
+ }
+ }
+ else {
+ for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
+ bNodeLink *link = linkdata->data;
+
+ link->tonode = NULL;
+ link->tosock = NULL;
+ }
+ }
+ }
+ else {
+ if (node_find_indicated_socket(snode, &tnode, &tsock, cursor, SOCK_OUT)) {
+ for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
+ bNodeLink *link = linkdata->data;
+
+ /* skip if this is already the target socket */
+ if (link->fromsock == tsock) {
+ continue;
+ }
+ /* skip if socket is on the same node as the fromsock */
+ if (tnode && link->tonode == tnode) {
+ continue;
+ }
+
+ /* attach links to the socket */
+ link->fromnode = tnode;
+ link->fromsock = tsock;
+ }
+ }
+ else {
+ for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
+ bNodeLink *link = linkdata->data;
+
+ link->fromnode = NULL;
+ link->fromsock = NULL;
+ }
+ }
+ }
}
/* loop that adds a nodelink, called by function below */
/* in_out = starting socket */
static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- bNodeLinkDrag *nldrag = op->customdata;
- ARegion *ar = CTX_wm_region(C);
- float cursor[2];
-
- UI_view2d_region_to_view(&ar->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);
- break;
-
- case LEFTMOUSE:
- case RIGHTMOUSE:
- case MIDDLEMOUSE:
- {
- if (event->val == KM_RELEASE) {
- node_link_exit(C, op, true);
-
- ED_workspace_status_text(C, NULL);
- ED_region_tag_redraw(ar);
- return OPERATOR_FINISHED;
- }
- break;
- }
- }
-
- return OPERATOR_RUNNING_MODAL;
+ bNodeLinkDrag *nldrag = op->customdata;
+ ARegion *ar = CTX_wm_region(C);
+ float cursor[2];
+
+ UI_view2d_region_to_view(&ar->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);
+ break;
+
+ case LEFTMOUSE:
+ case RIGHTMOUSE:
+ case MIDDLEMOUSE: {
+ if (event->val == KM_RELEASE) {
+ node_link_exit(C, op, true);
+
+ ED_workspace_status_text(C, NULL);
+ ED_region_tag_redraw(ar);
+ return OPERATOR_FINISHED;
+ }
+ break;
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
/* return 1 when socket clicked */
static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor[2], bool detach)
{
- bNode *node;
- bNodeSocket *sock;
- bNodeLink *link, *link_next, *oplink;
- bNodeLinkDrag *nldrag = NULL;
- LinkData *linkdata;
- int num_links;
-
- /* output indicated? */
- if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) {
- nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
-
- num_links = nodeCountSocketLinks(snode->edittree, sock);
- if (num_links > 0 && (num_links >= sock->limit || detach)) {
- /* dragged links are fixed on input side */
- nldrag->in_out = SOCK_IN;
- /* detach current links and store them in the operator data */
- for (link = snode->edittree->links.first; link; link = link_next) {
- link_next = link->next;
- if (link->fromsock == sock) {
- linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
- linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
- *oplink = *link;
- oplink->next = oplink->prev = NULL;
- oplink->flag |= NODE_LINK_VALID;
-
- /* The link could be disconnected and in that case we
- * wouldn't be able to check whether tag update is
- * needed or not when releasing mouse button. So we
- * cache whether the link affects output or not here
- * using TEST flag.
- */
- oplink->flag &= ~NODE_LINK_TEST;
- if (node_connected_to_output(bmain, snode->edittree, link->tonode)) {
- oplink->flag |= NODE_LINK_TEST;
- }
-
- BLI_addtail(&nldrag->links, linkdata);
- nodeRemLink(snode->edittree, link);
- }
- }
- }
- else {
- /* dragged links are fixed on output side */
- nldrag->in_out = SOCK_OUT;
- /* create a new link */
- linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
- linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
- oplink->fromnode = node;
- oplink->fromsock = sock;
- oplink->flag |= NODE_LINK_VALID;
- oplink->flag &= ~NODE_LINK_TEST;
- if (node_connected_to_output(bmain, snode->edittree, node)) {
- oplink->flag |= NODE_LINK_TEST;
- }
-
- BLI_addtail(&nldrag->links, linkdata);
- }
- }
- /* or an input? */
- else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) {
- nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
-
- num_links = nodeCountSocketLinks(snode->edittree, sock);
- if (num_links > 0 && (num_links >= sock->limit || detach)) {
- /* dragged links are fixed on output side */
- nldrag->in_out = SOCK_OUT;
- /* detach current links and store them in the operator data */
- for (link = snode->edittree->links.first; link; link = link_next) {
- link_next = link->next;
- if (link->tosock == sock) {
- linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
- linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
- *oplink = *link;
- oplink->next = oplink->prev = NULL;
- oplink->flag |= NODE_LINK_VALID;
- oplink->flag &= ~NODE_LINK_TEST;
- if (node_connected_to_output(bmain, snode->edittree, link->tonode)) {
- oplink->flag |= NODE_LINK_TEST;
- }
-
- BLI_addtail(&nldrag->links, linkdata);
- nodeRemLink(snode->edittree, link);
-
- /* send changed event to original link->tonode */
- if (node) {
- snode_update(snode, node);
- }
- }
- }
- }
- else {
- /* dragged links are fixed on input side */
- nldrag->in_out = SOCK_IN;
- /* create a new link */
- linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
- linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
- oplink->tonode = node;
- oplink->tosock = sock;
- oplink->flag |= NODE_LINK_VALID;
- oplink->flag &= ~NODE_LINK_TEST;
- if (node_connected_to_output(bmain, snode->edittree, node)) {
- oplink->flag |= NODE_LINK_TEST;
- }
-
- BLI_addtail(&nldrag->links, linkdata);
- }
- }
-
- return nldrag;
+ bNode *node;
+ bNodeSocket *sock;
+ bNodeLink *link, *link_next, *oplink;
+ bNodeLinkDrag *nldrag = NULL;
+ LinkData *linkdata;
+ int num_links;
+
+ /* output indicated? */
+ if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) {
+ nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
+
+ num_links = nodeCountSocketLinks(snode->edittree, sock);
+ if (num_links > 0 && (num_links >= sock->limit || detach)) {
+ /* dragged links are fixed on input side */
+ nldrag->in_out = SOCK_IN;
+ /* detach current links and store them in the operator data */
+ for (link = snode->edittree->links.first; link; link = link_next) {
+ link_next = link->next;
+ if (link->fromsock == sock) {
+ linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
+ linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
+ *oplink = *link;
+ oplink->next = oplink->prev = NULL;
+ oplink->flag |= NODE_LINK_VALID;
+
+ /* The link could be disconnected and in that case we
+ * wouldn't be able to check whether tag update is
+ * needed or not when releasing mouse button. So we
+ * cache whether the link affects output or not here
+ * using TEST flag.
+ */
+ oplink->flag &= ~NODE_LINK_TEST;
+ if (node_connected_to_output(bmain, snode->edittree, link->tonode)) {
+ oplink->flag |= NODE_LINK_TEST;
+ }
+
+ BLI_addtail(&nldrag->links, linkdata);
+ nodeRemLink(snode->edittree, link);
+ }
+ }
+ }
+ else {
+ /* dragged links are fixed on output side */
+ nldrag->in_out = SOCK_OUT;
+ /* create a new link */
+ linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
+ linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
+ oplink->fromnode = node;
+ oplink->fromsock = sock;
+ oplink->flag |= NODE_LINK_VALID;
+ oplink->flag &= ~NODE_LINK_TEST;
+ if (node_connected_to_output(bmain, snode->edittree, node)) {
+ oplink->flag |= NODE_LINK_TEST;
+ }
+
+ BLI_addtail(&nldrag->links, linkdata);
+ }
+ }
+ /* or an input? */
+ else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) {
+ nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
+
+ num_links = nodeCountSocketLinks(snode->edittree, sock);
+ if (num_links > 0 && (num_links >= sock->limit || detach)) {
+ /* dragged links are fixed on output side */
+ nldrag->in_out = SOCK_OUT;
+ /* detach current links and store them in the operator data */
+ for (link = snode->edittree->links.first; link; link = link_next) {
+ link_next = link->next;
+ if (link->tosock == sock) {
+ linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
+ linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
+ *oplink = *link;
+ oplink->next = oplink->prev = NULL;
+ oplink->flag |= NODE_LINK_VALID;
+ oplink->flag &= ~NODE_LINK_TEST;
+ if (node_connected_to_output(bmain, snode->edittree, link->tonode)) {
+ oplink->flag |= NODE_LINK_TEST;
+ }
+
+ BLI_addtail(&nldrag->links, linkdata);
+ nodeRemLink(snode->edittree, link);
+
+ /* send changed event to original link->tonode */
+ if (node) {
+ snode_update(snode, node);
+ }
+ }
+ }
+ }
+ else {
+ /* dragged links are fixed on input side */
+ nldrag->in_out = SOCK_IN;
+ /* create a new link */
+ linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
+ linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
+ oplink->tonode = node;
+ oplink->tosock = sock;
+ oplink->flag |= NODE_LINK_VALID;
+ oplink->flag &= ~NODE_LINK_TEST;
+ if (node_connected_to_output(bmain, snode->edittree, node)) {
+ oplink->flag |= NODE_LINK_TEST;
+ }
+
+ BLI_addtail(&nldrag->links, linkdata);
+ }
+ }
+
+ return nldrag;
}
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);
- bNodeLinkDrag *nldrag;
- float cursor[2];
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
+ bNodeLinkDrag *nldrag;
+ float cursor[2];
- bool detach = RNA_boolean_get(op->ptr, "detach");
+ 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(&ar->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]);
- ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
- nldrag = node_link_init(bmain, snode, cursor, detach);
+ nldrag = node_link_init(bmain, snode, cursor, detach);
- if (nldrag) {
- op->customdata = nldrag;
- BLI_addtail(&snode->linkdrag, nldrag);
+ if (nldrag) {
+ op->customdata = nldrag;
+ BLI_addtail(&snode->linkdrag, nldrag);
- /* add modal handler */
- WM_event_add_modal_handler(C, op);
+ /* add modal handler */
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
- }
- else {
- return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
- }
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
+ }
}
static void node_link_cancel(bContext *C, wmOperator *op)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeLinkDrag *nldrag = op->customdata;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeLinkDrag *nldrag = op->customdata;
- BLI_remlink(&snode->linkdrag, nldrag);
+ BLI_remlink(&snode->linkdrag, nldrag);
- BLI_freelistN(&nldrag->links);
- MEM_freeN(nldrag);
+ BLI_freelistN(&nldrag->links);
+ MEM_freeN(nldrag);
}
void NODE_OT_link(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Link Nodes";
- ot->idname = "NODE_OT_link";
- ot->description = "Use the mouse to create a link between two nodes";
-
- /* api callbacks */
- ot->invoke = node_link_invoke;
- ot->modal = node_link_modal;
-// ot->exec = node_link_exec;
- ot->poll = ED_operator_node_editable;
- ot->cancel = node_link_cancel;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- RNA_def_boolean(ot->srna, "detach", false, "Detach", "Detach and redirect existing links");
+ /* identifiers */
+ ot->name = "Link Nodes";
+ ot->idname = "NODE_OT_link";
+ ot->description = "Use the mouse to create a link between two nodes";
+
+ /* api callbacks */
+ ot->invoke = node_link_invoke;
+ ot->modal = node_link_modal;
+ // ot->exec = node_link_exec;
+ ot->poll = ED_operator_node_editable;
+ ot->cancel = node_link_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ RNA_def_boolean(ot->srna, "detach", false, "Detach", "Detach and redirect existing links");
}
/* ********************** Make Link operator ***************** */
@@ -966,671 +958,668 @@ void NODE_OT_link(wmOperatorType *ot)
/* makes a link between selected output and input sockets */
static int node_make_link_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- const bool replace = RNA_boolean_get(op->ptr, "replace");
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ const bool replace = RNA_boolean_get(op->ptr, "replace");
- ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
- snode_autoconnect(bmain, snode, 1, replace);
+ snode_autoconnect(bmain, snode, 1, replace);
- /* deselect sockets after linking */
- node_deselect_all_input_sockets(snode, 0);
- node_deselect_all_output_sockets(snode, 0);
+ /* deselect sockets after linking */
+ node_deselect_all_input_sockets(snode, 0);
+ node_deselect_all_output_sockets(snode, 0);
- ntreeUpdateTree(CTX_data_main(C), snode->edittree);
- snode_notify(C, snode);
- snode_dag_update(C, snode);
+ ntreeUpdateTree(CTX_data_main(C), snode->edittree);
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_link_make(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Links";
- ot->description = "Makes a link between selected output in input sockets";
- ot->idname = "NODE_OT_link_make";
+ /* identifiers */
+ ot->name = "Make Links";
+ ot->description = "Makes a link between selected output in input sockets";
+ ot->idname = "NODE_OT_link_make";
- /* callbacks */
- ot->exec = node_make_link_exec;
- ot->poll = ED_operator_node_editable; // XXX we need a special poll which checks that there are selected input/output sockets
+ /* callbacks */
+ ot->exec = node_make_link_exec;
+ ot->poll =
+ ED_operator_node_editable; // XXX we need a special poll which checks that there are selected input/output sockets
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "replace", 0, "Replace", "Replace socket connections with the new links");
+ RNA_def_boolean(
+ ot->srna, "replace", 0, "Replace", "Replace socket connections with the new links");
}
/* ********************** Cut Link operator ***************** */
static bool cut_links_intersect(bNodeLink *link, float mcoords[][2], int tot)
{
- float coord_array[NODE_LINK_RESOL + 1][2];
- int i, b;
-
- if (node_link_bezier_points(NULL, NULL, link, coord_array, NODE_LINK_RESOL)) {
-
- for (i = 0; i < tot - 1; i++) {
- for (b = 0; b < NODE_LINK_RESOL; b++) {
- if (isect_seg_seg_v2(mcoords[i], mcoords[i + 1], coord_array[b], coord_array[b + 1]) > 0) {
- return 1;
- }
- }
- }
- }
- return 0;
+ float coord_array[NODE_LINK_RESOL + 1][2];
+ int i, b;
+
+ if (node_link_bezier_points(NULL, NULL, link, coord_array, NODE_LINK_RESOL)) {
+
+ for (i = 0; i < tot - 1; i++) {
+ for (b = 0; b < NODE_LINK_RESOL; b++) {
+ if (isect_seg_seg_v2(mcoords[i], mcoords[i + 1], coord_array[b], coord_array[b + 1]) > 0) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
}
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);
- float mcoords[256][2];
- int i = 0;
- bool do_tag_update = false;
-
- RNA_BEGIN (op->ptr, itemptr, "path")
- {
- 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]);
- i++;
- if (i >= 256) {
- break;
- }
- }
- RNA_END;
-
- if (i > 1) {
- bool found = false;
- bNodeLink *link, *next;
-
- ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
-
- for (link = snode->edittree->links.first; link; link = next) {
- next = link->next;
- if (nodeLinkIsHidden(link)) {
- continue;
- }
-
- if (cut_links_intersect(link, mcoords, i)) {
-
- if (found == false) {
- /* TODO(sergey): Why did we kill jobs twice? */
- ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
- found = true;
- }
-
- do_tag_update |= (do_tag_update || node_connected_to_output(bmain, snode->edittree, link->tonode));
-
- snode_update(snode, link->tonode);
- nodeRemLink(snode->edittree, link);
- }
- }
-
- if (found) {
- ntreeUpdateTree(CTX_data_main(C), snode->edittree);
- snode_notify(C, snode);
- if (do_tag_update) {
- snode_dag_update(C, snode);
- }
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
-
- }
-
- return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
+ float mcoords[256][2];
+ int i = 0;
+ bool do_tag_update = false;
+
+ RNA_BEGIN (op->ptr, itemptr, "path") {
+ 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]);
+ i++;
+ if (i >= 256) {
+ break;
+ }
+ }
+ RNA_END;
+
+ if (i > 1) {
+ bool found = false;
+ bNodeLink *link, *next;
+
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
+
+ for (link = snode->edittree->links.first; link; link = next) {
+ next = link->next;
+ if (nodeLinkIsHidden(link)) {
+ continue;
+ }
+
+ if (cut_links_intersect(link, mcoords, i)) {
+
+ if (found == false) {
+ /* TODO(sergey): Why did we kill jobs twice? */
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
+ found = true;
+ }
+
+ do_tag_update |= (do_tag_update ||
+ node_connected_to_output(bmain, snode->edittree, link->tonode));
+
+ snode_update(snode, link->tonode);
+ nodeRemLink(snode->edittree, link);
+ }
+ }
+
+ if (found) {
+ ntreeUpdateTree(CTX_data_main(C), snode->edittree);
+ snode_notify(C, snode);
+ if (do_tag_update) {
+ snode_dag_update(C, snode);
+ }
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
}
void NODE_OT_links_cut(wmOperatorType *ot)
{
- ot->name = "Cut Links";
- ot->idname = "NODE_OT_links_cut";
- ot->description = "Use the mouse to cut (remove) some links";
+ ot->name = "Cut Links";
+ ot->idname = "NODE_OT_links_cut";
+ ot->description = "Use the mouse to cut (remove) some links";
- ot->invoke = WM_gesture_lines_invoke;
- ot->modal = WM_gesture_lines_modal;
- ot->exec = cut_links_exec;
- ot->cancel = WM_gesture_lines_cancel;
+ ot->invoke = WM_gesture_lines_invoke;
+ ot->modal = WM_gesture_lines_modal;
+ ot->exec = cut_links_exec;
+ ot->cancel = WM_gesture_lines_cancel;
- ot->poll = ED_operator_node_editable;
+ ot->poll = ED_operator_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- PropertyRNA *prop;
- prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ /* properties */
+ PropertyRNA *prop;
+ prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- /* internal */
- RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
+ /* internal */
+ RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
}
/* ********************** Detach links operator ***************** */
static int detach_links_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree = snode->edittree;
- bNode *node;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNode *node;
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->flag & SELECT) {
- nodeInternalRelink(ntree, node);
- }
- }
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->flag & SELECT) {
+ nodeInternalRelink(ntree, node);
+ }
+ }
- ntreeUpdateTree(CTX_data_main(C), ntree);
+ ntreeUpdateTree(CTX_data_main(C), ntree);
- snode_notify(C, snode);
- snode_dag_update(C, snode);
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_links_detach(wmOperatorType *ot)
{
- ot->name = "Detach Links";
- ot->idname = "NODE_OT_links_detach";
- ot->description = "Remove all links to selected nodes, and try to connect neighbor nodes together";
+ ot->name = "Detach Links";
+ ot->idname = "NODE_OT_links_detach";
+ ot->description =
+ "Remove all links to selected nodes, and try to connect neighbor nodes together";
- ot->exec = detach_links_exec;
- ot->poll = ED_operator_node_editable;
+ ot->exec = detach_links_exec;
+ ot->poll = ED_operator_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/* ****************** Set Parent ******************* */
static int node_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree = snode->edittree;
- bNode *frame = nodeGetActive(ntree), *node;
- if (!frame || frame->type != NODE_FRAME) {
- return OPERATOR_CANCELLED;
- }
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node == frame) {
- continue;
- }
- if (node->flag & NODE_SELECT) {
- nodeDetachNode(node);
- nodeAttachNode(node, frame);
- }
- }
-
- ED_node_sort(ntree);
- WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
-
- return OPERATOR_FINISHED;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNode *frame = nodeGetActive(ntree), *node;
+ if (!frame || frame->type != NODE_FRAME) {
+ return OPERATOR_CANCELLED;
+ }
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node == frame) {
+ continue;
+ }
+ if (node->flag & NODE_SELECT) {
+ nodeDetachNode(node);
+ nodeAttachNode(node, frame);
+ }
+ }
+
+ ED_node_sort(ntree);
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+
+ return OPERATOR_FINISHED;
}
void NODE_OT_parent_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Parent";
- ot->description = "Attach selected nodes";
- ot->idname = "NODE_OT_parent_set";
+ /* identifiers */
+ ot->name = "Make Parent";
+ ot->description = "Attach selected nodes";
+ ot->idname = "NODE_OT_parent_set";
- /* api callbacks */
- ot->exec = node_parent_set_exec;
- ot->poll = ED_operator_node_editable;
+ /* api callbacks */
+ ot->exec = node_parent_set_exec;
+ ot->poll = ED_operator_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** Join Nodes ******************* */
/* tags for depth-first search */
-#define NODE_JOIN_DONE 1
+#define NODE_JOIN_DONE 1
#define NODE_JOIN_IS_DESCENDANT 2
static void node_join_attach_recursive(bNode *node, bNode *frame)
{
- node->done |= NODE_JOIN_DONE;
-
- if (node == frame) {
- node->done |= NODE_JOIN_IS_DESCENDANT;
- }
- else if (node->parent) {
- /* call recursively */
- if (!(node->parent->done & NODE_JOIN_DONE)) {
- node_join_attach_recursive(node->parent, frame);
- }
-
- /* in any case: if the parent is a descendant, so is the child */
- if (node->parent->done & NODE_JOIN_IS_DESCENDANT) {
- node->done |= NODE_JOIN_IS_DESCENDANT;
- }
- else if (node->flag & NODE_TEST) {
- /* if parent is not an descendant of the frame, reattach the node */
- nodeDetachNode(node);
- nodeAttachNode(node, frame);
- node->done |= NODE_JOIN_IS_DESCENDANT;
- }
- }
- else if (node->flag & NODE_TEST) {
- nodeAttachNode(node, frame);
- node->done |= NODE_JOIN_IS_DESCENDANT;
- }
+ node->done |= NODE_JOIN_DONE;
+
+ if (node == frame) {
+ node->done |= NODE_JOIN_IS_DESCENDANT;
+ }
+ else if (node->parent) {
+ /* call recursively */
+ if (!(node->parent->done & NODE_JOIN_DONE)) {
+ node_join_attach_recursive(node->parent, frame);
+ }
+
+ /* in any case: if the parent is a descendant, so is the child */
+ if (node->parent->done & NODE_JOIN_IS_DESCENDANT) {
+ node->done |= NODE_JOIN_IS_DESCENDANT;
+ }
+ else if (node->flag & NODE_TEST) {
+ /* if parent is not an descendant of the frame, reattach the node */
+ nodeDetachNode(node);
+ nodeAttachNode(node, frame);
+ node->done |= NODE_JOIN_IS_DESCENDANT;
+ }
+ }
+ else if (node->flag & NODE_TEST) {
+ nodeAttachNode(node, frame);
+ node->done |= NODE_JOIN_IS_DESCENDANT;
+ }
}
static int node_join_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree = snode->edittree;
- bNode *node, *frame;
-
- /* XXX save selection: node_add_node call below sets the new frame as single
- * active+selected node */
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_SELECT) {
- node->flag |= NODE_TEST;
- }
- else {
- node->flag &= ~NODE_TEST;
- }
- }
-
- frame = node_add_node(C, NULL, NODE_FRAME, 0.0f, 0.0f);
-
- /* reset tags */
- for (node = ntree->nodes.first; node; node = node->next) {
- node->done = 0;
- }
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (!(node->done & NODE_JOIN_DONE)) {
- node_join_attach_recursive(node, frame);
- }
- }
-
- /* restore selection */
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_TEST) {
- node->flag |= NODE_SELECT;
- }
- }
-
- ED_node_sort(ntree);
- WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
-
- return OPERATOR_FINISHED;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNode *node, *frame;
+
+ /* XXX save selection: node_add_node call below sets the new frame as single
+ * active+selected node */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->flag & NODE_SELECT) {
+ node->flag |= NODE_TEST;
+ }
+ else {
+ node->flag &= ~NODE_TEST;
+ }
+ }
+
+ frame = node_add_node(C, NULL, NODE_FRAME, 0.0f, 0.0f);
+
+ /* reset tags */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ node->done = 0;
+ }
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (!(node->done & NODE_JOIN_DONE)) {
+ node_join_attach_recursive(node, frame);
+ }
+ }
+
+ /* restore selection */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->flag & NODE_TEST) {
+ node->flag |= NODE_SELECT;
+ }
+ }
+
+ ED_node_sort(ntree);
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+
+ return OPERATOR_FINISHED;
}
void NODE_OT_join(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Join Nodes";
- ot->description = "Attach selected nodes to a new common frame";
- ot->idname = "NODE_OT_join";
+ /* identifiers */
+ ot->name = "Join Nodes";
+ ot->description = "Attach selected nodes to a new common frame";
+ ot->idname = "NODE_OT_join";
- /* api callbacks */
- ot->exec = node_join_exec;
- ot->poll = ED_operator_node_editable;
+ /* api callbacks */
+ ot->exec = node_join_exec;
+ ot->poll = ED_operator_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** Attach ******************* */
static bNode *node_find_frame_to_attach(ARegion *ar, 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]);
-
- /* check nodes front to back */
- for (frame = ntree->nodes.last; frame; frame = frame->prev) {
- /* skip selected, those are the nodes we want to attach */
- if ((frame->type != NODE_FRAME) || (frame->flag & NODE_SELECT)) {
- continue;
- }
- if (BLI_rctf_isect_pt_v(&frame->totr, cursor)) {
- return frame;
- }
- }
-
- return NULL;
+ 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]);
+
+ /* check nodes front to back */
+ for (frame = ntree->nodes.last; frame; frame = frame->prev) {
+ /* skip selected, those are the nodes we want to attach */
+ if ((frame->type != NODE_FRAME) || (frame->flag & NODE_SELECT)) {
+ continue;
+ }
+ if (BLI_rctf_isect_pt_v(&frame->totr, cursor)) {
+ return frame;
+ }
+ }
+
+ return NULL;
}
static int node_attach_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- ARegion *ar = 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);
-
- if (frame) {
- bNode *node, *parent;
- for (node = ntree->nodes.last; node; node = node->prev) {
- if (node->flag & NODE_SELECT) {
- if (node->parent == NULL) {
- /* disallow moving a parent into its child */
- if (nodeAttachNodeCheck(frame, node) == false) {
- /* attach all unparented nodes */
- nodeAttachNode(node, frame);
- }
- }
- else {
- /* attach nodes which share parent with the frame */
- for (parent = frame->parent; parent; parent = parent->parent) {
- if (parent == node->parent) {
- break;
- }
- }
-
- if (parent) {
- /* disallow moving a parent into its child */
- if (nodeAttachNodeCheck(frame, node) == false) {
- nodeDetachNode(node);
- nodeAttachNode(node, frame);
- }
- }
- }
- }
- }
- }
-
- ED_node_sort(ntree);
- WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
-
- return OPERATOR_FINISHED;
+ ARegion *ar = 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);
+
+ if (frame) {
+ bNode *node, *parent;
+ for (node = ntree->nodes.last; node; node = node->prev) {
+ if (node->flag & NODE_SELECT) {
+ if (node->parent == NULL) {
+ /* disallow moving a parent into its child */
+ if (nodeAttachNodeCheck(frame, node) == false) {
+ /* attach all unparented nodes */
+ nodeAttachNode(node, frame);
+ }
+ }
+ else {
+ /* attach nodes which share parent with the frame */
+ for (parent = frame->parent; parent; parent = parent->parent) {
+ if (parent == node->parent) {
+ break;
+ }
+ }
+
+ if (parent) {
+ /* disallow moving a parent into its child */
+ if (nodeAttachNodeCheck(frame, node) == false) {
+ nodeDetachNode(node);
+ nodeAttachNode(node, frame);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ ED_node_sort(ntree);
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+
+ return OPERATOR_FINISHED;
}
-
void NODE_OT_attach(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Attach Nodes";
- ot->description = "Attach active node to a frame";
- ot->idname = "NODE_OT_attach";
+ /* identifiers */
+ ot->name = "Attach Nodes";
+ ot->description = "Attach active node to a frame";
+ ot->idname = "NODE_OT_attach";
- /* api callbacks */
+ /* api callbacks */
- ot->invoke = node_attach_invoke;
- ot->poll = ED_operator_node_editable;
+ ot->invoke = node_attach_invoke;
+ ot->poll = ED_operator_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ****************** Detach ******************* */
/* tags for depth-first search */
-#define NODE_DETACH_DONE 1
-#define NODE_DETACH_IS_DESCENDANT 2
+#define NODE_DETACH_DONE 1
+#define NODE_DETACH_IS_DESCENDANT 2
static void node_detach_recursive(bNode *node)
{
- node->done |= NODE_DETACH_DONE;
-
- if (node->parent) {
- /* call recursively */
- if (!(node->parent->done & NODE_DETACH_DONE)) {
- node_detach_recursive(node->parent);
- }
-
- /* in any case: if the parent is a descendant, so is the child */
- if (node->parent->done & NODE_DETACH_IS_DESCENDANT) {
- node->done |= NODE_DETACH_IS_DESCENDANT;
- }
- else if (node->flag & NODE_SELECT) {
- /* if parent is not a descendant of a selected node, detach */
- nodeDetachNode(node);
- node->done |= NODE_DETACH_IS_DESCENDANT;
- }
- }
- else if (node->flag & NODE_SELECT) {
- node->done |= NODE_DETACH_IS_DESCENDANT;
- }
+ node->done |= NODE_DETACH_DONE;
+
+ if (node->parent) {
+ /* call recursively */
+ if (!(node->parent->done & NODE_DETACH_DONE)) {
+ node_detach_recursive(node->parent);
+ }
+
+ /* in any case: if the parent is a descendant, so is the child */
+ if (node->parent->done & NODE_DETACH_IS_DESCENDANT) {
+ node->done |= NODE_DETACH_IS_DESCENDANT;
+ }
+ else if (node->flag & NODE_SELECT) {
+ /* if parent is not a descendant of a selected node, detach */
+ nodeDetachNode(node);
+ node->done |= NODE_DETACH_IS_DESCENDANT;
+ }
+ }
+ else if (node->flag & NODE_SELECT) {
+ node->done |= NODE_DETACH_IS_DESCENDANT;
+ }
}
-
/* detach the root nodes in the current selection */
static int node_detach_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree = snode->edittree;
- bNode *node;
-
- /* reset tags */
- for (node = ntree->nodes.first; node; node = node->next) {
- node->done = 0;
- }
- /* detach nodes recursively
- * relative order is preserved here!
- */
- for (node = ntree->nodes.first; node; node = node->next) {
- if (!(node->done & NODE_DETACH_DONE)) {
- node_detach_recursive(node);
- }
- }
-
- ED_node_sort(ntree);
- WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
-
- return OPERATOR_FINISHED;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNode *node;
+
+ /* reset tags */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ node->done = 0;
+ }
+ /* detach nodes recursively
+ * relative order is preserved here!
+ */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (!(node->done & NODE_DETACH_DONE)) {
+ node_detach_recursive(node);
+ }
+ }
+
+ ED_node_sort(ntree);
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+
+ return OPERATOR_FINISHED;
}
void NODE_OT_detach(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Detach Nodes";
- ot->description = "Detach selected nodes from parents";
- ot->idname = "NODE_OT_detach";
+ /* identifiers */
+ ot->name = "Detach Nodes";
+ ot->description = "Detach selected nodes from parents";
+ ot->idname = "NODE_OT_detach";
- /* api callbacks */
- ot->exec = node_detach_exec;
- ot->poll = ED_operator_node_editable;
+ /* api callbacks */
+ ot->exec = node_detach_exec;
+ ot->poll = ED_operator_node_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************* 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)
{
- SpaceNode *snode = sa ? sa->spacedata.first : NULL;
- bNode *node, *select = NULL;
- bNodeLink *link;
-
- *r_snode = snode;
- *r_select = NULL;
-
- /* no unlucky accidents */
- if (sa == NULL || sa->spacetype != SPACE_NODE) {
- return false;
- }
-
- if (!test) {
- /* no need to look for a node */
- return true;
- }
-
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & SELECT) {
- if (select) {
- break;
- }
- else {
- select = node;
- }
- }
- }
- /* only one selected */
- if (node || select == NULL) {
- return false;
- }
-
- /* correct node */
- if (BLI_listbase_is_empty(&select->inputs) || BLI_listbase_is_empty(&select->outputs)) {
- return false;
- }
-
- /* test node for links */
- for (link = snode->edittree->links.first; link; link = link->next) {
- if (nodeLinkIsHidden(link)) {
- continue;
- }
-
- if (link->tonode == select || link->fromnode == select) {
- return false;
- }
- }
-
- *r_select = select;
- return true;
+ SpaceNode *snode = sa ? sa->spacedata.first : NULL;
+ bNode *node, *select = NULL;
+ bNodeLink *link;
+
+ *r_snode = snode;
+ *r_select = NULL;
+
+ /* no unlucky accidents */
+ if (sa == NULL || sa->spacetype != SPACE_NODE) {
+ return false;
+ }
+
+ if (!test) {
+ /* no need to look for a node */
+ return true;
+ }
+
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (node->flag & SELECT) {
+ if (select) {
+ break;
+ }
+ else {
+ select = node;
+ }
+ }
+ }
+ /* only one selected */
+ if (node || select == NULL) {
+ return false;
+ }
+
+ /* correct node */
+ if (BLI_listbase_is_empty(&select->inputs) || BLI_listbase_is_empty(&select->outputs)) {
+ return false;
+ }
+
+ /* test node for links */
+ for (link = snode->edittree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link)) {
+ continue;
+ }
+
+ if (link->tonode == select || link->fromnode == select) {
+ return false;
+ }
+ }
+
+ *r_select = select;
+ return true;
}
/* test == 0, clear all intersect flags */
void ED_node_link_intersect_test(ScrArea *sa, int test)
{
- bNode *select;
- SpaceNode *snode;
- bNodeLink *link, *selink = NULL;
- float dist_best = FLT_MAX;
-
- if (!ed_node_link_conditions(sa, test, &snode, &select)) {
- return;
- }
-
- /* clear flags */
- for (link = snode->edittree->links.first; link; link = link->next) {
- link->flag &= ~NODE_LINKFLAG_HILITE;
- }
-
- if (test == 0) {
- return;
- }
-
- /* find link to select/highlight */
- for (link = snode->edittree->links.first; link; link = link->next) {
- float coord_array[NODE_LINK_RESOL + 1][2];
-
- if (nodeLinkIsHidden(link)) {
- continue;
- }
-
- if (node_link_bezier_points(NULL, NULL, link, coord_array, NODE_LINK_RESOL)) {
- float dist = FLT_MAX;
- int i;
-
- /* loop over link coords to find shortest dist to
- * upper left node edge of a intersected line segment */
- for (i = 0; i < NODE_LINK_RESOL; i++) {
- /* check if the node rect intersetcts the line from this point to next one */
- if (BLI_rctf_isect_segment(&select->totr, coord_array[i], coord_array[i + 1])) {
- /* store the shortest distance to the upper left edge
- * of all intersections found so far */
- const float node_xy[] = {select->totr.xmin, select->totr.ymax};
-
- /* to be precise coord_array should be clipped by select->totr,
- * but not done since there's no real noticeable difference */
- dist = min_ff(dist_squared_to_line_segment_v2(node_xy, coord_array[i], coord_array[i + 1]),
- dist);
- }
- }
-
- /* we want the link with the shortest distance to node center */
- if (dist < dist_best) {
- dist_best = dist;
- selink = link;
- }
- }
- }
-
- if (selink) {
- selink->flag |= NODE_LINKFLAG_HILITE;
- }
+ bNode *select;
+ SpaceNode *snode;
+ bNodeLink *link, *selink = NULL;
+ float dist_best = FLT_MAX;
+
+ if (!ed_node_link_conditions(sa, test, &snode, &select)) {
+ return;
+ }
+
+ /* clear flags */
+ for (link = snode->edittree->links.first; link; link = link->next) {
+ link->flag &= ~NODE_LINKFLAG_HILITE;
+ }
+
+ if (test == 0) {
+ return;
+ }
+
+ /* find link to select/highlight */
+ for (link = snode->edittree->links.first; link; link = link->next) {
+ float coord_array[NODE_LINK_RESOL + 1][2];
+
+ if (nodeLinkIsHidden(link)) {
+ continue;
+ }
+
+ if (node_link_bezier_points(NULL, NULL, link, coord_array, NODE_LINK_RESOL)) {
+ float dist = FLT_MAX;
+ int i;
+
+ /* loop over link coords to find shortest dist to
+ * upper left node edge of a intersected line segment */
+ for (i = 0; i < NODE_LINK_RESOL; i++) {
+ /* check if the node rect intersetcts the line from this point to next one */
+ if (BLI_rctf_isect_segment(&select->totr, coord_array[i], coord_array[i + 1])) {
+ /* store the shortest distance to the upper left edge
+ * of all intersections found so far */
+ const float node_xy[] = {select->totr.xmin, select->totr.ymax};
+
+ /* to be precise coord_array should be clipped by select->totr,
+ * but not done since there's no real noticeable difference */
+ dist = min_ff(
+ dist_squared_to_line_segment_v2(node_xy, coord_array[i], coord_array[i + 1]), dist);
+ }
+ }
+
+ /* we want the link with the shortest distance to node center */
+ if (dist < dist_best) {
+ dist_best = dist;
+ selink = link;
+ }
+ }
+ }
+
+ if (selink) {
+ selink->flag |= NODE_LINKFLAG_HILITE;
+ }
}
/* assumes sockets in list */
static bNodeSocket *socket_best_match(ListBase *sockets)
{
- bNodeSocket *sock;
- int type, maxtype = 0;
-
- /* find type range */
- for (sock = sockets->first; sock; sock = sock->next) {
- maxtype = max_ii(sock->type, maxtype);
- }
-
- /* try all types, starting from 'highest' (i.e. colors, vectors, values) */
- for (type = maxtype; type >= 0; --type) {
- for (sock = sockets->first; sock; sock = sock->next) {
- if (!nodeSocketIsHidden(sock) && type == sock->type) {
- return sock;
- }
- }
- }
-
- /* no visible sockets, unhide first of highest type */
- for (type = maxtype; type >= 0; --type) {
- for (sock = sockets->first; sock; sock = sock->next) {
- if (type == sock->type) {
- sock->flag &= ~SOCK_HIDDEN;
- return sock;
- }
- }
- }
-
- return NULL;
+ bNodeSocket *sock;
+ int type, maxtype = 0;
+
+ /* find type range */
+ for (sock = sockets->first; sock; sock = sock->next) {
+ maxtype = max_ii(sock->type, maxtype);
+ }
+
+ /* try all types, starting from 'highest' (i.e. colors, vectors, values) */
+ for (type = maxtype; type >= 0; --type) {
+ for (sock = sockets->first; sock; sock = sock->next) {
+ if (!nodeSocketIsHidden(sock) && type == sock->type) {
+ return sock;
+ }
+ }
+ }
+
+ /* no visible sockets, unhide first of highest type */
+ for (type = maxtype; type >= 0; --type) {
+ for (sock = sockets->first; sock; sock = sock->next) {
+ if (type == sock->type) {
+ sock->flag &= ~SOCK_HIDDEN;
+ return sock;
+ }
+ }
+ }
+
+ return NULL;
}
static bool node_parents_offset_flag_enable_cb(bNode *parent, void *UNUSED(userdata))
{
- /* NODE_TEST is used to flag nodes that shouldn't be offset (again) */
- parent->flag |= NODE_TEST;
+ /* NODE_TEST is used to flag nodes that shouldn't be offset (again) */
+ parent->flag |= NODE_TEST;
- return true;
+ return true;
}
static void node_offset_apply(bNode *node, const float offset_x)
{
- /* NODE_TEST is used to flag nodes that shouldn't be offset (again) */
- if ((node->flag & NODE_TEST) == 0) {
- node->anim_init_locx = node->locx;
- node->anim_ofsx = (offset_x / UI_DPI_FAC);
- node->flag |= NODE_TEST;
- }
+ /* NODE_TEST is used to flag nodes that shouldn't be offset (again) */
+ if ((node->flag & NODE_TEST) == 0) {
+ node->anim_init_locx = node->locx;
+ node->anim_ofsx = (offset_x / UI_DPI_FAC);
+ node->flag |= NODE_TEST;
+ }
}
static void node_parent_offset_apply(NodeInsertOfsData *data, bNode *parent, const float offset_x)
{
- bNode *node;
-
- 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) */
- 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) */
- node->flag |= NODE_TEST;
- }
- }
+ bNode *node;
+
+ 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) */
+ 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) */
+ node->flag |= NODE_TEST;
+ }
+ }
}
#define NODE_INSOFS_ANIM_DURATION 0.25f
@@ -1639,193 +1628,190 @@ static void node_parent_offset_apply(NodeInsertOfsData *data, bNode *parent, con
* Callback that applies NodeInsertOfsData.offset_x to a node or its parent, similar
* to node_link_insert_offset_output_chain_cb below, but with slightly different logic
*/
-static bool node_link_insert_offset_frame_chain_cb(
- bNode *fromnode, bNode *tonode,
- void *userdata,
- const bool reversed)
+static bool node_link_insert_offset_frame_chain_cb(bNode *fromnode,
+ bNode *tonode,
+ void *userdata,
+ const bool reversed)
{
- NodeInsertOfsData *data = userdata;
- bNode *ofs_node = reversed ? fromnode : tonode;
+ NodeInsertOfsData *data = userdata;
+ bNode *ofs_node = reversed ? fromnode : tonode;
- if (ofs_node->parent && ofs_node->parent != data->insert_parent) {
- node_offset_apply(ofs_node->parent, data->offset_x);
- }
- else {
- node_offset_apply(ofs_node, data->offset_x);
- }
+ if (ofs_node->parent && ofs_node->parent != data->insert_parent) {
+ node_offset_apply(ofs_node->parent, data->offset_x);
+ }
+ else {
+ node_offset_apply(ofs_node, data->offset_x);
+ }
- return true;
+ return true;
}
/**
* Applies NodeInsertOfsData.offset_x to all childs of \a parent
*/
-static void node_link_insert_offset_frame_chains(
- const bNodeTree *ntree, const bNode *parent,
- NodeInsertOfsData *data,
- const bool reversed)
+static void node_link_insert_offset_frame_chains(const bNodeTree *ntree,
+ const bNode *parent,
+ NodeInsertOfsData *data,
+ const bool reversed)
{
- bNode *node;
+ bNode *node;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (nodeIsChildOf(parent, node)) {
- nodeChainIter(ntree, node, node_link_insert_offset_frame_chain_cb, data, reversed);
- }
- }
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (nodeIsChildOf(parent, node)) {
+ nodeChainIter(ntree, node, node_link_insert_offset_frame_chain_cb, data, reversed);
+ }
+ }
}
/**
* Callback that applies NodeInsertOfsData.offset_x to a node or its parent,
* considering the logic needed for offsetting nodes after link insert
*/
-static bool node_link_insert_offset_chain_cb(
- bNode *fromnode, bNode *tonode,
- void *userdata,
- const bool reversed)
+static bool node_link_insert_offset_chain_cb(bNode *fromnode,
+ bNode *tonode,
+ void *userdata,
+ const bool reversed)
{
- NodeInsertOfsData *data = userdata;
- bNode *ofs_node = reversed ? fromnode : tonode;
-
- if (data->insert_parent) {
- if (ofs_node->parent && (ofs_node->parent->flag & NODE_TEST) == 0) {
- node_parent_offset_apply(data, ofs_node->parent, data->offset_x);
- node_link_insert_offset_frame_chains(data->ntree, ofs_node->parent, data, reversed);
- }
- else {
- node_offset_apply(ofs_node, data->offset_x);
- }
-
- if (nodeIsChildOf(data->insert_parent, ofs_node) == false) {
- data->insert_parent = NULL;
- }
- }
- else if (ofs_node->parent) {
- bNode *node = nodeFindRootParent(ofs_node);
- node_offset_apply(node, data->offset_x);
- }
- else {
- node_offset_apply(ofs_node, data->offset_x);
- }
-
- return true;
+ NodeInsertOfsData *data = userdata;
+ bNode *ofs_node = reversed ? fromnode : tonode;
+
+ if (data->insert_parent) {
+ if (ofs_node->parent && (ofs_node->parent->flag & NODE_TEST) == 0) {
+ node_parent_offset_apply(data, ofs_node->parent, data->offset_x);
+ node_link_insert_offset_frame_chains(data->ntree, ofs_node->parent, data, reversed);
+ }
+ else {
+ node_offset_apply(ofs_node, data->offset_x);
+ }
+
+ if (nodeIsChildOf(data->insert_parent, ofs_node) == false) {
+ data->insert_parent = NULL;
+ }
+ }
+ else if (ofs_node->parent) {
+ bNode *node = nodeFindRootParent(ofs_node);
+ node_offset_apply(node, data->offset_x);
+ }
+ else {
+ node_offset_apply(ofs_node, data->offset_x);
+ }
+
+ return true;
}
-static void node_link_insert_offset_ntree(
- NodeInsertOfsData *iofsd, ARegion *ar,
- const int mouse_xy[2], const bool right_alignment)
+static void node_link_insert_offset_ntree(NodeInsertOfsData *iofsd,
+ ARegion *ar,
+ const int mouse_xy[2],
+ const bool right_alignment)
{
- bNodeTree *ntree = iofsd->ntree;
- bNode *insert = iofsd->insert;
- bNode *prev = iofsd->prev, *next = iofsd->next;
- bNode *init_parent = insert->parent; /* store old insert->parent for restoring later */
- rctf totr_insert;
-
- const float min_margin = U.node_margin * UI_DPI_FAC;
- const float width = NODE_WIDTH(insert);
- const bool needs_alignment = (next->totr.xmin - prev->totr.xmax) < (width + (min_margin * 2.0f));
-
- float margin = width;
- float dist, addval;
-
-
- /* NODE_TEST will be used later, so disable for all nodes */
- ntreeNodeFlagSet(ntree, NODE_TEST, false);
-
- /* insert->totr isn't updated yet,
- * so totr_insert is used to get the correct worldspace coords */
- node_to_updated_rect(insert, &totr_insert);
-
- /* 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);
-
- /* 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)
- * - logic here is similar to node_find_frame_to_attach */
- if (!insert->parent ||
- (prev->parent && (prev->parent == next->parent) && (prev->parent != insert->parent)))
- {
- bNode *frame;
- rctf totr_frame;
-
- /* check nodes front to back */
- for (frame = ntree->nodes.last; frame; frame = frame->prev) {
- /* skip selected, those are the nodes we want to attach */
- if ((frame->type != NODE_FRAME) || (frame->flag & NODE_SELECT)) {
- continue;
- }
-
- /* for some reason frame y coords aren't correct yet */
- node_to_updated_rect(frame, &totr_frame);
-
- if (BLI_rctf_isect_x(&totr_frame, totr_insert.xmin) &&
- BLI_rctf_isect_x(&totr_frame, totr_insert.xmax))
- {
- if (BLI_rctf_isect_y(&totr_frame, totr_insert.ymin) ||
- BLI_rctf_isect_y(&totr_frame, totr_insert.ymax))
- {
- /* frame isn't insert->parent actually, but this is needed to make offsetting
- * nodes work correctly for above checked cases (it is restored later) */
- insert->parent = frame;
- break;
- }
- }
- }
- }
-
-
- /* *** ensure offset at the left (or right for right_alignment case) of insert_node *** */
-
- dist = right_alignment ? totr_insert.xmin - prev->totr.xmax : next->totr.xmin - totr_insert.xmax;
- /* distance between insert_node and prev is smaller than min margin */
- if (dist < min_margin) {
- addval = (min_margin - dist) * (right_alignment ? 1.0f : -1.0f);
-
- node_offset_apply(insert, addval);
-
- totr_insert.xmin += addval;
- totr_insert.xmax += addval;
- margin += min_margin;
- }
-
- /* *** ensure offset at the right (or left for right_alignment case) of insert_node *** */
-
- dist = right_alignment ? next->totr.xmin - totr_insert.xmax : totr_insert.xmin - prev->totr.xmax;
- /* distance between insert_node and next is smaller than min margin */
- if (dist < min_margin) {
- addval = (min_margin - dist) * (right_alignment ? 1.0f : -1.0f);
- if (needs_alignment) {
- bNode *offs_node = right_alignment ? next : prev;
- if (!offs_node->parent ||
- offs_node->parent == insert->parent ||
- nodeIsChildOf(offs_node->parent, insert))
- {
- node_offset_apply(offs_node, addval);
- }
- else if (!insert->parent && offs_node->parent) {
- node_offset_apply(nodeFindRootParent(offs_node), addval);
- }
- margin = addval;
- }
- /* enough room is available, but we want to ensure the min margin at the right */
- else {
- /* offset inserted node so that min margin is kept at the right */
- node_offset_apply(insert, -addval);
- }
- }
-
-
- if (needs_alignment) {
- iofsd->insert_parent = insert->parent;
- iofsd->offset_x = margin;
-
- /* flag all parents of insert as offset to prevent them from being offset */
- nodeParentsIter(insert, node_parents_offset_flag_enable_cb, NULL);
- /* iterate over entire chain and apply offsets */
- nodeChainIter(ntree, right_alignment ? next : prev, node_link_insert_offset_chain_cb, iofsd, !right_alignment);
- }
-
- insert->parent = init_parent;
+ bNodeTree *ntree = iofsd->ntree;
+ bNode *insert = iofsd->insert;
+ bNode *prev = iofsd->prev, *next = iofsd->next;
+ bNode *init_parent = insert->parent; /* store old insert->parent for restoring later */
+ rctf totr_insert;
+
+ const float min_margin = U.node_margin * UI_DPI_FAC;
+ const float width = NODE_WIDTH(insert);
+ const bool needs_alignment = (next->totr.xmin - prev->totr.xmax) < (width + (min_margin * 2.0f));
+
+ float margin = width;
+ float dist, addval;
+
+ /* NODE_TEST will be used later, so disable for all nodes */
+ ntreeNodeFlagSet(ntree, NODE_TEST, false);
+
+ /* insert->totr isn't updated yet,
+ * so totr_insert is used to get the correct worldspace coords */
+ node_to_updated_rect(insert, &totr_insert);
+
+ /* 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);
+
+ /* 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)
+ * - logic here is similar to node_find_frame_to_attach */
+ if (!insert->parent ||
+ (prev->parent && (prev->parent == next->parent) && (prev->parent != insert->parent))) {
+ bNode *frame;
+ rctf totr_frame;
+
+ /* check nodes front to back */
+ for (frame = ntree->nodes.last; frame; frame = frame->prev) {
+ /* skip selected, those are the nodes we want to attach */
+ if ((frame->type != NODE_FRAME) || (frame->flag & NODE_SELECT)) {
+ continue;
+ }
+
+ /* for some reason frame y coords aren't correct yet */
+ node_to_updated_rect(frame, &totr_frame);
+
+ if (BLI_rctf_isect_x(&totr_frame, totr_insert.xmin) &&
+ BLI_rctf_isect_x(&totr_frame, totr_insert.xmax)) {
+ if (BLI_rctf_isect_y(&totr_frame, totr_insert.ymin) ||
+ BLI_rctf_isect_y(&totr_frame, totr_insert.ymax)) {
+ /* frame isn't insert->parent actually, but this is needed to make offsetting
+ * nodes work correctly for above checked cases (it is restored later) */
+ insert->parent = frame;
+ break;
+ }
+ }
+ }
+ }
+
+ /* *** ensure offset at the left (or right for right_alignment case) of insert_node *** */
+
+ dist = right_alignment ? totr_insert.xmin - prev->totr.xmax : next->totr.xmin - totr_insert.xmax;
+ /* distance between insert_node and prev is smaller than min margin */
+ if (dist < min_margin) {
+ addval = (min_margin - dist) * (right_alignment ? 1.0f : -1.0f);
+
+ node_offset_apply(insert, addval);
+
+ totr_insert.xmin += addval;
+ totr_insert.xmax += addval;
+ margin += min_margin;
+ }
+
+ /* *** ensure offset at the right (or left for right_alignment case) of insert_node *** */
+
+ dist = right_alignment ? next->totr.xmin - totr_insert.xmax : totr_insert.xmin - prev->totr.xmax;
+ /* distance between insert_node and next is smaller than min margin */
+ if (dist < min_margin) {
+ addval = (min_margin - dist) * (right_alignment ? 1.0f : -1.0f);
+ if (needs_alignment) {
+ bNode *offs_node = right_alignment ? next : prev;
+ if (!offs_node->parent || offs_node->parent == insert->parent ||
+ nodeIsChildOf(offs_node->parent, insert)) {
+ node_offset_apply(offs_node, addval);
+ }
+ else if (!insert->parent && offs_node->parent) {
+ node_offset_apply(nodeFindRootParent(offs_node), addval);
+ }
+ margin = addval;
+ }
+ /* enough room is available, but we want to ensure the min margin at the right */
+ else {
+ /* offset inserted node so that min margin is kept at the right */
+ node_offset_apply(insert, -addval);
+ }
+ }
+
+ if (needs_alignment) {
+ iofsd->insert_parent = insert->parent;
+ iofsd->offset_x = margin;
+
+ /* flag all parents of insert as offset to prevent them from being offset */
+ nodeParentsIter(insert, node_parents_offset_flag_enable_cb, NULL);
+ /* iterate over entire chain and apply offsets */
+ nodeChainIter(ntree,
+ right_alignment ? next : prev,
+ node_link_insert_offset_chain_cb,
+ iofsd,
+ !right_alignment);
+ }
+
+ insert->parent = init_parent;
}
/**
@@ -1833,147 +1819,146 @@ static void node_link_insert_offset_ntree(
*/
static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- NodeInsertOfsData *iofsd = snode->iofsd;
- bNode *node;
- float duration;
- bool redraw = false;
-
- if (!snode || event->type != TIMER || iofsd == NULL || iofsd->anim_timer != event->customdata) {
- return OPERATOR_PASS_THROUGH;
- }
-
- duration = (float)iofsd->anim_timer->duration;
-
- /* handle animation - do this before possibly aborting due to duration, since
- * main thread might be so busy that node hasn't reached final position yet */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (UNLIKELY(node->anim_ofsx)) {
- const float endval = node->anim_init_locx + node->anim_ofsx;
- if (IS_EQF(node->locx, endval) == false) {
- node->locx = BLI_easing_cubic_ease_in_out(duration, node->anim_init_locx, node->anim_ofsx,
- NODE_INSOFS_ANIM_DURATION);
- if (node->anim_ofsx < 0) {
- CLAMP_MIN(node->locx, endval);
- }
- else {
- CLAMP_MAX(node->locx, endval);
- }
- redraw = true;
- }
- }
- }
- if (redraw) {
- ED_region_tag_redraw(CTX_wm_region(C));
- }
-
- /* end timer + free insert offset data */
- if (duration > NODE_INSOFS_ANIM_DURATION) {
- WM_event_remove_timer(CTX_wm_manager(C), NULL, iofsd->anim_timer);
-
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- node->anim_init_locx = node->anim_ofsx = 0.0f;
- }
-
- snode->iofsd = NULL;
- MEM_freeN(iofsd);
-
- return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
- }
-
- return OPERATOR_RUNNING_MODAL;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ NodeInsertOfsData *iofsd = snode->iofsd;
+ bNode *node;
+ float duration;
+ bool redraw = false;
+
+ if (!snode || event->type != TIMER || iofsd == NULL || iofsd->anim_timer != event->customdata) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ duration = (float)iofsd->anim_timer->duration;
+
+ /* handle animation - do this before possibly aborting due to duration, since
+ * main thread might be so busy that node hasn't reached final position yet */
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (UNLIKELY(node->anim_ofsx)) {
+ const float endval = node->anim_init_locx + node->anim_ofsx;
+ if (IS_EQF(node->locx, endval) == false) {
+ node->locx = BLI_easing_cubic_ease_in_out(
+ duration, node->anim_init_locx, node->anim_ofsx, NODE_INSOFS_ANIM_DURATION);
+ if (node->anim_ofsx < 0) {
+ CLAMP_MIN(node->locx, endval);
+ }
+ else {
+ CLAMP_MAX(node->locx, endval);
+ }
+ redraw = true;
+ }
+ }
+ }
+ if (redraw) {
+ ED_region_tag_redraw(CTX_wm_region(C));
+ }
+
+ /* end timer + free insert offset data */
+ if (duration > NODE_INSOFS_ANIM_DURATION) {
+ WM_event_remove_timer(CTX_wm_manager(C), NULL, iofsd->anim_timer);
+
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ node->anim_init_locx = node->anim_ofsx = 0.0f;
+ }
+
+ snode->iofsd = NULL;
+ MEM_freeN(iofsd);
+
+ return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
#undef NODE_INSOFS_ANIM_DURATION
static int node_insert_offset_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- const SpaceNode *snode = CTX_wm_space_node(C);
- NodeInsertOfsData *iofsd = snode->iofsd;
+ const SpaceNode *snode = CTX_wm_space_node(C);
+ NodeInsertOfsData *iofsd = snode->iofsd;
- if (!iofsd || !iofsd->insert) {
- return OPERATOR_CANCELLED;
- }
+ if (!iofsd || !iofsd->insert) {
+ return OPERATOR_CANCELLED;
+ }
- BLI_assert((snode->flag & SNODE_SKIP_INSOFFSET) == 0);
+ BLI_assert((snode->flag & SNODE_SKIP_INSOFFSET) == 0);
- iofsd->ntree = snode->edittree;
- iofsd->anim_timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.02);
+ iofsd->ntree = snode->edittree;
+ iofsd->anim_timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.02);
- node_link_insert_offset_ntree(
- iofsd, CTX_wm_region(C),
- event->mval, (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT));
+ node_link_insert_offset_ntree(
+ iofsd, CTX_wm_region(C), event->mval, (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT));
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void NODE_OT_insert_offset(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Insert Offset";
- ot->description = "Automatically offset nodes on insertion";
- ot->idname = "NODE_OT_insert_offset";
-
- /* callbacks */
- ot->invoke = node_insert_offset_invoke;
- ot->modal = node_insert_offset_modal;
- ot->poll = ED_operator_node_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ /* identifiers */
+ ot->name = "Insert Offset";
+ ot->description = "Automatically offset nodes on insertion";
+ ot->idname = "NODE_OT_insert_offset";
+
+ /* callbacks */
+ ot->invoke = node_insert_offset_invoke;
+ ot->modal = node_insert_offset_modal;
+ ot->poll = ED_operator_node_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
}
/* assumes link with NODE_LINKFLAG_HILITE set */
void ED_node_link_insert(Main *bmain, ScrArea *sa)
{
- bNode *node, *select;
- SpaceNode *snode;
- bNodeLink *link;
- bNodeSocket *sockto;
-
- if (!ed_node_link_conditions(sa, true, &snode, &select)) {
- return;
- }
-
- /* get the link */
- for (link = snode->edittree->links.first; link; link = link->next) {
- if (link->flag & NODE_LINKFLAG_HILITE) {
- break;
- }
- }
-
- if (link) {
- bNodeSocket *best_input = socket_best_match(&select->inputs);
- bNodeSocket *best_output = socket_best_match(&select->outputs);
-
- if (best_input && best_output) {
- node = link->tonode;
- sockto = link->tosock;
-
- link->tonode = select;
- link->tosock = best_input;
- node_remove_extra_links(snode, link);
- link->flag &= ~NODE_LINKFLAG_HILITE;
-
- nodeAddLink(snode->edittree, select, best_output, node, sockto);
-
- /* set up insert offset data, it needs stuff from here */
- if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) {
- NodeInsertOfsData *iofsd = MEM_callocN(sizeof(NodeInsertOfsData), __func__);
-
- iofsd->insert = select;
- iofsd->prev = link->fromnode;
- iofsd->next = node;
-
- snode->iofsd = iofsd;
- }
-
- ntreeUpdateTree(bmain, snode->edittree); /* needed for pointers */
- snode_update(snode, select);
- ED_node_tag_update_id(snode->id);
- }
- }
+ bNode *node, *select;
+ SpaceNode *snode;
+ bNodeLink *link;
+ bNodeSocket *sockto;
+
+ if (!ed_node_link_conditions(sa, true, &snode, &select)) {
+ return;
+ }
+
+ /* get the link */
+ for (link = snode->edittree->links.first; link; link = link->next) {
+ if (link->flag & NODE_LINKFLAG_HILITE) {
+ break;
+ }
+ }
+
+ if (link) {
+ bNodeSocket *best_input = socket_best_match(&select->inputs);
+ bNodeSocket *best_output = socket_best_match(&select->outputs);
+
+ if (best_input && best_output) {
+ node = link->tonode;
+ sockto = link->tosock;
+
+ link->tonode = select;
+ link->tosock = best_input;
+ node_remove_extra_links(snode, link);
+ link->flag &= ~NODE_LINKFLAG_HILITE;
+
+ nodeAddLink(snode->edittree, select, best_output, node, sockto);
+
+ /* set up insert offset data, it needs stuff from here */
+ if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) {
+ NodeInsertOfsData *iofsd = MEM_callocN(sizeof(NodeInsertOfsData), __func__);
+
+ iofsd->insert = select;
+ iofsd->prev = link->fromnode;
+ iofsd->next = node;
+
+ snode->iofsd = iofsd;
+ }
+
+ ntreeUpdateTree(bmain, snode->edittree); /* needed for pointers */
+ snode_update(snode, select);
+ ED_node_tag_update_id(snode->id);
+ }
+ }
}
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index a027481ff27..58531ec32b1 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -36,7 +36,7 @@
#include "BKE_main.h"
#include "BKE_node.h"
-#include "ED_node.h" /* own include */
+#include "ED_node.h" /* own include */
#include "ED_screen.h"
#include "ED_select_utils.h"
@@ -52,7 +52,7 @@
#include "MEM_guardedalloc.h"
-#include "node_intern.h" /* own include */
+#include "node_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Public Node Selection API
@@ -60,182 +60,182 @@
static bNode *node_under_mouse_select(bNodeTree *ntree, int mx, int my)
{
- bNode *node;
-
- for (node = ntree->nodes.last; node; node = node->prev) {
- if (node->typeinfo->select_area_func) {
- if (node->typeinfo->select_area_func(node, mx, my)) {
- return node;
- }
- }
- }
- return NULL;
+ bNode *node;
+
+ for (node = ntree->nodes.last; node; node = node->prev) {
+ if (node->typeinfo->select_area_func) {
+ if (node->typeinfo->select_area_func(node, mx, my)) {
+ return node;
+ }
+ }
+ }
+ return NULL;
}
static bNode *node_under_mouse_tweak(bNodeTree *ntree, int mx, int my)
{
- bNode *node;
-
- for (node = ntree->nodes.last; node; node = node->prev) {
- if (node->typeinfo->tweak_area_func) {
- if (node->typeinfo->tweak_area_func(node, mx, my)) {
- return node;
- }
- }
- }
- return NULL;
+ bNode *node;
+
+ for (node = ntree->nodes.last; node; node = node->prev) {
+ if (node->typeinfo->tweak_area_func) {
+ if (node->typeinfo->tweak_area_func(node, mx, my)) {
+ return node;
+ }
+ }
+ }
+ return NULL;
}
static bool is_position_over_node_or_socket(SpaceNode *snode, float mouse[2])
{
- if (node_under_mouse_tweak(snode->edittree, mouse[0], mouse[1])) {
- return true;
- }
+ if (node_under_mouse_tweak(snode->edittree, mouse[0], mouse[1])) {
+ return true;
+ }
- bNode *node;
- bNodeSocket *sock;
- if (node_find_indicated_socket(snode, &node, &sock, mouse, SOCK_IN | SOCK_OUT)) {
- return true;
- }
+ bNode *node;
+ bNodeSocket *sock;
+ if (node_find_indicated_socket(snode, &node, &sock, mouse, SOCK_IN | SOCK_OUT)) {
+ return true;
+ }
- return false;
+ return false;
}
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);
- float mouse[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &mouse[0], &mouse[1]);
- return is_position_over_node_or_socket(snode, mouse);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
+ float mouse[2];
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &mouse[0], &mouse[1]);
+ return is_position_over_node_or_socket(snode, mouse);
}
static void node_toggle(bNode *node)
{
- nodeSetSelected(node, !(node->flag & SELECT));
+ nodeSetSelected(node, !(node->flag & SELECT));
}
void node_socket_select(bNode *node, bNodeSocket *sock)
{
- sock->flag |= SELECT;
+ sock->flag |= SELECT;
- /* select node too */
- if (node) {
- node->flag |= SELECT;
- }
+ /* select node too */
+ if (node) {
+ node->flag |= SELECT;
+ }
}
void node_socket_deselect(bNode *node, bNodeSocket *sock, const bool deselect_node)
{
- sock->flag &= ~SELECT;
-
- if (node && deselect_node) {
- bool sel = 0;
-
- /* if no selected sockets remain, also deselect the node */
- for (sock = node->inputs.first; sock; sock = sock->next) {
- if (sock->flag & SELECT) {
- sel = 1;
- break;
- }
- }
- for (sock = node->outputs.first; sock; sock = sock->next) {
- if (sock->flag & SELECT) {
- sel = 1;
- break;
- }
- }
-
- if (!sel) {
- node->flag &= ~SELECT;
- }
- }
+ sock->flag &= ~SELECT;
+
+ if (node && deselect_node) {
+ bool sel = 0;
+
+ /* if no selected sockets remain, also deselect the node */
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (sock->flag & SELECT) {
+ sel = 1;
+ break;
+ }
+ }
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ if (sock->flag & SELECT) {
+ sel = 1;
+ break;
+ }
+ }
+
+ if (!sel) {
+ node->flag &= ~SELECT;
+ }
+ }
}
static void node_socket_toggle(bNode *node, bNodeSocket *sock, int deselect_node)
{
- if (sock->flag & SELECT) {
- node_socket_deselect(node, sock, deselect_node);
- }
- else {
- node_socket_select(node, sock);
- }
+ if (sock->flag & SELECT) {
+ node_socket_deselect(node, sock, deselect_node);
+ }
+ else {
+ node_socket_select(node, sock);
+ }
}
/* no undo here! */
void node_deselect_all(SpaceNode *snode)
{
- bNode *node;
+ bNode *node;
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- nodeSetSelected(node, false);
- }
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ nodeSetSelected(node, false);
+ }
}
void node_deselect_all_input_sockets(SpaceNode *snode, const bool deselect_nodes)
{
- bNode *node;
- bNodeSocket *sock;
-
- /* XXX not calling node_socket_deselect here each time, because this does iteration
- * over all node sockets internally to check if the node stays selected.
- * We can do that more efficiently here.
- */
-
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- int sel = 0;
-
- for (sock = node->inputs.first; sock; sock = sock->next) {
- sock->flag &= ~SELECT;
- }
-
- /* if no selected sockets remain, also deselect the node */
- if (deselect_nodes) {
- for (sock = node->outputs.first; sock; sock = sock->next) {
- if (sock->flag & SELECT) {
- sel = 1;
- break;
- }
- }
-
- if (!sel) {
- node->flag &= ~SELECT;
- }
- }
- }
+ bNode *node;
+ bNodeSocket *sock;
+
+ /* XXX not calling node_socket_deselect here each time, because this does iteration
+ * over all node sockets internally to check if the node stays selected.
+ * We can do that more efficiently here.
+ */
+
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ int sel = 0;
+
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ sock->flag &= ~SELECT;
+ }
+
+ /* if no selected sockets remain, also deselect the node */
+ if (deselect_nodes) {
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ if (sock->flag & SELECT) {
+ sel = 1;
+ break;
+ }
+ }
+
+ if (!sel) {
+ node->flag &= ~SELECT;
+ }
+ }
+ }
}
void node_deselect_all_output_sockets(SpaceNode *snode, const bool deselect_nodes)
{
- bNode *node;
- bNodeSocket *sock;
-
- /* XXX not calling node_socket_deselect here each time, because this does iteration
- * over all node sockets internally to check if the node stays selected.
- * We can do that more efficiently here.
- */
-
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- bool sel = false;
-
- for (sock = node->outputs.first; sock; sock = sock->next) {
- sock->flag &= ~SELECT;
- }
-
- /* if no selected sockets remain, also deselect the node */
- if (deselect_nodes) {
- for (sock = node->inputs.first; sock; sock = sock->next) {
- if (sock->flag & SELECT) {
- sel = 1;
- break;
- }
- }
-
- if (!sel) {
- node->flag &= ~SELECT;
- }
- }
- }
+ bNode *node;
+ bNodeSocket *sock;
+
+ /* XXX not calling node_socket_deselect here each time, because this does iteration
+ * over all node sockets internally to check if the node stays selected.
+ * We can do that more efficiently here.
+ */
+
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ bool sel = false;
+
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ sock->flag &= ~SELECT;
+ }
+
+ /* if no selected sockets remain, also deselect the node */
+ if (deselect_nodes) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (sock->flag & SELECT) {
+ sel = 1;
+ break;
+ }
+ }
+
+ if (!sel) {
+ node->flag &= ~SELECT;
+ }
+ }
+ }
}
/** \} */
@@ -248,152 +248,158 @@ void node_deselect_all_output_sockets(SpaceNode *snode, const bool deselect_node
static bool node_select_grouped_type(SpaceNode *snode, bNode *node_act)
{
- bNode *node;
- bool changed = false;
-
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if ((node->flag & SELECT) == 0) {
- if (node->type == node_act->type) {
- nodeSetSelected(node, true);
- changed = true;
- }
- }
- }
-
- return changed;
+ bNode *node;
+ bool changed = false;
+
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if ((node->flag & SELECT) == 0) {
+ if (node->type == node_act->type) {
+ nodeSetSelected(node, true);
+ changed = true;
+ }
+ }
+ }
+
+ return changed;
}
static bool node_select_grouped_color(SpaceNode *snode, bNode *node_act)
{
- bNode *node;
- bool changed = false;
-
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if ((node->flag & SELECT) == 0) {
- if (compare_v3v3(node->color, node_act->color, 0.005f)) {
- nodeSetSelected(node, true);
- changed = true;
- }
- }
- }
-
- return changed;
+ bNode *node;
+ bool changed = false;
+
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if ((node->flag & SELECT) == 0) {
+ if (compare_v3v3(node->color, node_act->color, 0.005f)) {
+ nodeSetSelected(node, true);
+ changed = true;
+ }
+ }
+ }
+
+ return changed;
}
static bool node_select_grouped_name(SpaceNode *snode, bNode *node_act, const bool from_right)
{
- bNode *node;
- bool changed = false;
- const unsigned int delims[] = {'.', '-', '_', '\0'};
- size_t pref_len_act, pref_len_curr;
- const char *sep, *suf_act, *suf_curr;
-
- pref_len_act = BLI_str_partition_ex_utf8(node_act->name, NULL, delims, &sep, &suf_act, from_right);
-
- /* Note: in case we are searching for suffix, and found none, use whole name as suffix. */
- if (from_right && !(sep && suf_act)) {
- pref_len_act = 0;
- suf_act = node_act->name;
- }
-
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & SELECT) {
- continue;
- }
- pref_len_curr = BLI_str_partition_ex_utf8(node->name, NULL, delims, &sep, &suf_curr, from_right);
-
- /* Same as with active node name! */
- if (from_right && !(sep && suf_curr)) {
- pref_len_curr = 0;
- suf_curr = node->name;
- }
-
- if ((from_right && STREQ(suf_act, suf_curr)) ||
- (!from_right && (pref_len_act == pref_len_curr) && STREQLEN(node_act->name, node->name, pref_len_act)))
- {
- nodeSetSelected(node, true);
- changed = true;
- }
- }
-
- return changed;
+ bNode *node;
+ bool changed = false;
+ const unsigned int delims[] = {'.', '-', '_', '\0'};
+ size_t pref_len_act, pref_len_curr;
+ const char *sep, *suf_act, *suf_curr;
+
+ pref_len_act = BLI_str_partition_ex_utf8(
+ node_act->name, NULL, delims, &sep, &suf_act, from_right);
+
+ /* Note: in case we are searching for suffix, and found none, use whole name as suffix. */
+ if (from_right && !(sep && suf_act)) {
+ pref_len_act = 0;
+ suf_act = node_act->name;
+ }
+
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (node->flag & SELECT) {
+ continue;
+ }
+ pref_len_curr = BLI_str_partition_ex_utf8(
+ node->name, NULL, delims, &sep, &suf_curr, from_right);
+
+ /* Same as with active node name! */
+ if (from_right && !(sep && suf_curr)) {
+ pref_len_curr = 0;
+ suf_curr = node->name;
+ }
+
+ if ((from_right && STREQ(suf_act, suf_curr)) ||
+ (!from_right && (pref_len_act == pref_len_curr) &&
+ STREQLEN(node_act->name, node->name, pref_len_act))) {
+ nodeSetSelected(node, true);
+ changed = true;
+ }
+ }
+
+ return changed;
}
enum {
- NODE_SELECT_GROUPED_TYPE = 0,
- NODE_SELECT_GROUPED_COLOR = 1,
- NODE_SELECT_GROUPED_PREFIX = 2,
- NODE_SELECT_GROUPED_SUFIX = 3,
+ NODE_SELECT_GROUPED_TYPE = 0,
+ NODE_SELECT_GROUPED_COLOR = 1,
+ NODE_SELECT_GROUPED_PREFIX = 2,
+ NODE_SELECT_GROUPED_SUFIX = 3,
};
static int node_select_grouped_exec(bContext *C, wmOperator *op)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node_act = nodeGetActive(snode->edittree);
- bNode *node;
- bool changed = false;
- const bool extend = RNA_boolean_get(op->ptr, "extend");
- const int type = RNA_enum_get(op->ptr, "type");
-
- if (!extend) {
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- nodeSetSelected(node, false);
- }
- }
- nodeSetSelected(node_act, true);
-
- switch (type) {
- case NODE_SELECT_GROUPED_TYPE:
- changed = node_select_grouped_type(snode, node_act);
- break;
- case NODE_SELECT_GROUPED_COLOR:
- changed = node_select_grouped_color(snode, node_act);
- break;
- case NODE_SELECT_GROUPED_PREFIX:
- changed = node_select_grouped_name(snode, node_act, false);
- break;
- case NODE_SELECT_GROUPED_SUFIX:
- changed = node_select_grouped_name(snode, node_act, true);
- break;
- default:
- break;
- }
-
- if (changed) {
- ED_node_sort(snode->edittree);
- WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_CANCELLED;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node_act = nodeGetActive(snode->edittree);
+ bNode *node;
+ bool changed = false;
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const int type = RNA_enum_get(op->ptr, "type");
+
+ if (!extend) {
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ nodeSetSelected(node, false);
+ }
+ }
+ nodeSetSelected(node_act, true);
+
+ switch (type) {
+ case NODE_SELECT_GROUPED_TYPE:
+ changed = node_select_grouped_type(snode, node_act);
+ break;
+ case NODE_SELECT_GROUPED_COLOR:
+ changed = node_select_grouped_color(snode, node_act);
+ break;
+ case NODE_SELECT_GROUPED_PREFIX:
+ changed = node_select_grouped_name(snode, node_act, false);
+ break;
+ case NODE_SELECT_GROUPED_SUFIX:
+ changed = node_select_grouped_name(snode, node_act, true);
+ break;
+ default:
+ break;
+ }
+
+ if (changed) {
+ ED_node_sort(snode->edittree);
+ WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
}
void NODE_OT_select_grouped(wmOperatorType *ot)
{
- static const EnumPropertyItem prop_select_grouped_types[] = {
- {NODE_SELECT_GROUPED_TYPE, "TYPE", 0, "Type", ""},
- {NODE_SELECT_GROUPED_COLOR, "COLOR", 0, "Color", ""},
- {NODE_SELECT_GROUPED_PREFIX, "PREFIX", 0, "Prefix", ""},
- {NODE_SELECT_GROUPED_SUFIX, "SUFFIX", 0, "Suffix", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Select Grouped";
- ot->description = "Select nodes with similar properties";
- ot->idname = "NODE_OT_select_grouped";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = node_select_grouped_exec;
- ot->poll = ED_operator_node_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
- ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
+ static const EnumPropertyItem prop_select_grouped_types[] = {
+ {NODE_SELECT_GROUPED_TYPE, "TYPE", 0, "Type", ""},
+ {NODE_SELECT_GROUPED_COLOR, "COLOR", 0, "Color", ""},
+ {NODE_SELECT_GROUPED_PREFIX, "PREFIX", 0, "Prefix", ""},
+ {NODE_SELECT_GROUPED_SUFIX, "SUFFIX", 0, "Suffix", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Select Grouped";
+ ot->description = "Select nodes with similar properties";
+ ot->idname = "NODE_OT_select_grouped";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = node_select_grouped_exec;
+ ot->poll = ED_operator_node_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "extend",
+ false,
+ "Extend",
+ "Extend selection instead of deselecting everything first");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
}
/** \} */
@@ -404,175 +410,175 @@ void NODE_OT_select_grouped(wmOperatorType *ot)
void node_select_single(bContext *C, bNode *node)
{
- Main *bmain = CTX_data_main(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *tnode;
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *tnode;
- for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
- if (tnode != node) {
- nodeSetSelected(tnode, false);
- }
- }
- nodeSetSelected(node, true);
+ for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
+ if (tnode != node) {
+ nodeSetSelected(tnode, false);
+ }
+ }
+ nodeSetSelected(node, true);
- ED_node_set_active(bmain, snode->edittree, node);
- ED_node_set_active_viewer_key(snode);
+ ED_node_set_active(bmain, snode->edittree, node);
+ ED_node_set_active_viewer_key(snode);
- ED_node_sort(snode->edittree);
+ ED_node_sort(snode->edittree);
- WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
}
-static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const int mval[2], bool extend, bool socket_select)
+static int node_mouse_select(
+ Main *bmain, SpaceNode *snode, ARegion *ar, const int mval[2], bool extend, bool socket_select)
{
- bNode *node, *tnode;
- bNodeSocket *sock = NULL;
- bNodeSocket *tsock;
- float cursor[2];
- bool selected = false;
-
- /* get mouse coordinates in view2d space */
- UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &cursor[0], &cursor[1]);
-
- /* first do socket selection, these generally overlap with nodes. */
- if (socket_select) {
- if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) {
- node_socket_toggle(node, sock, 1);
- selected = true;
- }
- else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) {
- if (sock->flag & SELECT) {
- if (extend) {
- node_socket_deselect(node, sock, 1);
- }
- else {
- selected = true;
- }
- }
- else {
- /* only allow one selected output per node, for sensible linking.
- * allows selecting outputs from different nodes though. */
- if (node) {
- for (tsock = node->outputs.first; tsock; tsock = tsock->next) {
- node_socket_deselect(node, tsock, 1);
- }
- }
- if (extend) {
- /* only allow one selected output per node, for sensible linking.
- * allows selecting outputs from different nodes though. */
- for (tsock = node->outputs.first; tsock; tsock = tsock->next) {
- if (tsock != sock) {
- node_socket_deselect(node, tsock, 1);
- }
- }
- }
- node_socket_select(node, sock);
- selected = true;
- }
- }
- }
-
- if (!sock) {
- if (extend) {
- /* find the closest visible node */
- node = node_under_mouse_select(snode->edittree, cursor[0], cursor[1]);
-
- if (node) {
- if ((node->flag & SELECT) && (node->flag & NODE_ACTIVE) == 0) {
- /* if node is selected but not active make it active */
- ED_node_set_active(bmain, snode->edittree, node);
- }
- else {
- node_toggle(node);
- ED_node_set_active(bmain, snode->edittree, node);
- }
- selected = true;
- }
- }
- else {
- /* find the closest visible node */
- node = node_under_mouse_select(snode->edittree, cursor[0], cursor[1]);
-
- if (node) {
- for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
- nodeSetSelected(tnode, false);
- }
- nodeSetSelected(node, true);
- ED_node_set_active(bmain, snode->edittree, node);
- selected = true;
- }
- }
- }
-
- /* update node order */
- if (selected) {
- ED_node_set_active_viewer_key(snode);
- ED_node_sort(snode->edittree);
- }
-
- return selected;
+ bNode *node, *tnode;
+ bNodeSocket *sock = NULL;
+ bNodeSocket *tsock;
+ float cursor[2];
+ bool selected = false;
+
+ /* get mouse coordinates in view2d space */
+ UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &cursor[0], &cursor[1]);
+
+ /* first do socket selection, these generally overlap with nodes. */
+ if (socket_select) {
+ if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) {
+ node_socket_toggle(node, sock, 1);
+ selected = true;
+ }
+ else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) {
+ if (sock->flag & SELECT) {
+ if (extend) {
+ node_socket_deselect(node, sock, 1);
+ }
+ else {
+ selected = true;
+ }
+ }
+ else {
+ /* only allow one selected output per node, for sensible linking.
+ * allows selecting outputs from different nodes though. */
+ if (node) {
+ for (tsock = node->outputs.first; tsock; tsock = tsock->next) {
+ node_socket_deselect(node, tsock, 1);
+ }
+ }
+ if (extend) {
+ /* only allow one selected output per node, for sensible linking.
+ * allows selecting outputs from different nodes though. */
+ for (tsock = node->outputs.first; tsock; tsock = tsock->next) {
+ if (tsock != sock) {
+ node_socket_deselect(node, tsock, 1);
+ }
+ }
+ }
+ node_socket_select(node, sock);
+ selected = true;
+ }
+ }
+ }
+
+ if (!sock) {
+ if (extend) {
+ /* find the closest visible node */
+ node = node_under_mouse_select(snode->edittree, cursor[0], cursor[1]);
+
+ if (node) {
+ if ((node->flag & SELECT) && (node->flag & NODE_ACTIVE) == 0) {
+ /* if node is selected but not active make it active */
+ ED_node_set_active(bmain, snode->edittree, node);
+ }
+ else {
+ node_toggle(node);
+ ED_node_set_active(bmain, snode->edittree, node);
+ }
+ selected = true;
+ }
+ }
+ else {
+ /* find the closest visible node */
+ node = node_under_mouse_select(snode->edittree, cursor[0], cursor[1]);
+
+ if (node) {
+ for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
+ nodeSetSelected(tnode, false);
+ }
+ nodeSetSelected(node, true);
+ ED_node_set_active(bmain, snode->edittree, node);
+ selected = true;
+ }
+ }
+ }
+
+ /* update node order */
+ if (selected) {
+ ED_node_set_active_viewer_key(snode);
+ ED_node_sort(snode->edittree);
+ }
+
+ return selected;
}
static int node_select_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
- int mval[2];
- short extend;
- bool socket_select;
-
- /* get settings from RNA properties for operator */
- mval[0] = RNA_int_get(op->ptr, "mouse_x");
- mval[1] = RNA_int_get(op->ptr, "mouse_y");
-
- extend = RNA_boolean_get(op->ptr, "extend");
- /* always do socket_select when extending selection. */
- socket_select = extend || RNA_boolean_get(op->ptr, "socket_select");
-
- /* perform the select */
- if (node_mouse_select(bmain, snode, ar, mval, extend, socket_select)) {
- /* send notifiers */
- WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
-
- /* allow tweak event to work too */
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
- }
- else {
- /* allow tweak event to work too */
- return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
- }
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
+ int mval[2];
+ short extend;
+ bool socket_select;
+
+ /* get settings from RNA properties for operator */
+ mval[0] = RNA_int_get(op->ptr, "mouse_x");
+ mval[1] = RNA_int_get(op->ptr, "mouse_y");
+
+ extend = RNA_boolean_get(op->ptr, "extend");
+ /* always do socket_select when extending selection. */
+ socket_select = extend || RNA_boolean_get(op->ptr, "socket_select");
+
+ /* perform the select */
+ if (node_mouse_select(bmain, snode, ar, mval, extend, socket_select)) {
+ /* send notifiers */
+ WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
+
+ /* allow tweak event to work too */
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ }
+ else {
+ /* allow tweak event to work too */
+ return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
+ }
}
static int node_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- RNA_int_set(op->ptr, "mouse_x", event->mval[0]);
- RNA_int_set(op->ptr, "mouse_y", event->mval[1]);
+ RNA_int_set(op->ptr, "mouse_x", event->mval[0]);
+ RNA_int_set(op->ptr, "mouse_y", event->mval[1]);
- return node_select_exec(C, op);
+ return node_select_exec(C, op);
}
-
void NODE_OT_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select";
- ot->idname = "NODE_OT_select";
- ot->description = "Select the node under the cursor";
-
- /* api callbacks */
- ot->invoke = node_select_invoke;
- ot->exec = node_select_exec;
- ot->poll = ED_operator_node_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_int(ot->srna, "mouse_x", 0, INT_MIN, INT_MAX, "Mouse X", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "mouse_y", 0, INT_MIN, INT_MAX, "Mouse Y", "", INT_MIN, INT_MAX);
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "");
- RNA_def_boolean(ot->srna, "socket_select", false, "Socket Select", "");
+ /* identifiers */
+ ot->name = "Select";
+ ot->idname = "NODE_OT_select";
+ ot->description = "Select the node under the cursor";
+
+ /* api callbacks */
+ ot->invoke = node_select_invoke;
+ ot->exec = node_select_exec;
+ ot->poll = ED_operator_node_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "mouse_x", 0, INT_MIN, INT_MAX, "Mouse X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "mouse_y", 0, INT_MIN, INT_MAX, "Mouse Y", "", INT_MIN, INT_MAX);
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "");
+ RNA_def_boolean(ot->srna, "socket_select", false, "Socket Select", "");
}
/** \} */
@@ -583,74 +589,78 @@ 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);
- rctf rectf;
-
- 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);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- ED_node_select_all(&snode->edittree->nodes, SEL_DESELECT);
- }
-
- for (bNode *node = snode->edittree->nodes.first; node; node = node->next) {
- bool is_inside;
- if (node->type == NODE_FRAME) {
- is_inside = BLI_rctf_inside_rctf(&rectf, &node->totr);
- }
- else {
- is_inside = BLI_rctf_isect(&rectf, &node->totr, NULL);
- }
-
- if (is_inside) {
- nodeSetSelected(node, select);
- }
- }
-
- ED_node_sort(snode->edittree);
-
- WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
-
- return OPERATOR_FINISHED;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
+ rctf rectf;
+
+ 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);
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ ED_node_select_all(&snode->edittree->nodes, SEL_DESELECT);
+ }
+
+ for (bNode *node = snode->edittree->nodes.first; node; node = node->next) {
+ bool is_inside;
+ if (node->type == NODE_FRAME) {
+ is_inside = BLI_rctf_inside_rctf(&rectf, &node->totr);
+ }
+ else {
+ is_inside = BLI_rctf_isect(&rectf, &node->totr, NULL);
+ }
+
+ if (is_inside) {
+ nodeSetSelected(node, select);
+ }
+ }
+
+ ED_node_sort(snode->edittree);
+
+ WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
+
+ return OPERATOR_FINISHED;
}
static int node_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- const bool tweak = RNA_boolean_get(op->ptr, "tweak");
+ const bool tweak = RNA_boolean_get(op->ptr, "tweak");
- if (tweak && is_event_over_node_or_socket(C, event)) {
- return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
- }
+ if (tweak && is_event_over_node_or_socket(C, event)) {
+ return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
+ }
- return WM_gesture_box_invoke(C, op, event);
+ return WM_gesture_box_invoke(C, op, event);
}
void NODE_OT_select_box(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Box Select";
- ot->idname = "NODE_OT_select_box";
- ot->description = "Use box selection to select nodes";
-
- /* api callbacks */
- ot->invoke = node_box_select_invoke;
- ot->exec = node_box_select_exec;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
-
- ot->poll = ED_operator_node_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "tweak", 0, "Tweak", "Only activate when mouse is not over a node - useful for tweak gesture");
-
- WM_operator_properties_gesture_box(ot);
- WM_operator_properties_select_operation_simple(ot);
+ /* identifiers */
+ ot->name = "Box Select";
+ ot->idname = "NODE_OT_select_box";
+ ot->description = "Use box selection to select nodes";
+
+ /* api callbacks */
+ ot->invoke = node_box_select_invoke;
+ ot->exec = node_box_select_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
+
+ ot->poll = ED_operator_node_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "tweak",
+ 0,
+ "Tweak",
+ "Only activate when mouse is not over a node - useful for tweak gesture");
+
+ WM_operator_properties_gesture_box(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
/** \} */
@@ -661,60 +671,60 @@ 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);
- bNode *node;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
+ bNode *node;
- int x, y, radius;
- float offset[2];
+ 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(&ar->winrct)) / (float)(BLI_rctf_size_x(&ar->v2d.cur));
- 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);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- ED_node_select_all(&snode->edittree->nodes, SEL_DESELECT);
- }
+ 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);
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ ED_node_select_all(&snode->edittree->nodes, SEL_DESELECT);
+ }
- /* get operator properties */
- x = RNA_int_get(op->ptr, "x");
- y = RNA_int_get(op->ptr, "y");
- radius = RNA_int_get(op->ptr, "radius");
+ /* get operator properties */
+ x = RNA_int_get(op->ptr, "x");
+ 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(&ar->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)) {
- nodeSetSelected(node, select);
- }
- }
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (BLI_rctf_isect_circle(&node->totr, offset, radius / zoom)) {
+ nodeSetSelected(node, select);
+ }
+ }
- WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_select_circle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Circle Select";
- ot->idname = "NODE_OT_select_circle";
- ot->description = "Use circle selection to select nodes";
+ /* identifiers */
+ ot->name = "Circle Select";
+ ot->idname = "NODE_OT_select_circle";
+ ot->description = "Use circle selection to select nodes";
- /* api callbacks */
- ot->invoke = WM_gesture_circle_invoke;
- ot->exec = node_circleselect_exec;
- ot->modal = WM_gesture_circle_modal;
+ /* api callbacks */
+ ot->invoke = WM_gesture_circle_invoke;
+ ot->exec = node_circleselect_exec;
+ ot->modal = WM_gesture_circle_modal;
- ot->poll = ED_operator_node_active;
+ ot->poll = ED_operator_node_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_gesture_circle(ot);
- WM_operator_properties_select_operation_simple(ot);
+ /* properties */
+ WM_operator_properties_gesture_circle(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
/** \} */
@@ -725,101 +735,103 @@ void NODE_OT_select_circle(wmOperatorType *ot)
static int node_lasso_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- const bool tweak = RNA_boolean_get(op->ptr, "tweak");
+ const bool tweak = RNA_boolean_get(op->ptr, "tweak");
- if (tweak && is_event_over_node_or_socket(C, event)) {
- return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
- }
+ if (tweak && is_event_over_node_or_socket(C, event)) {
+ return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
+ }
- return WM_gesture_lasso_invoke(C, op, event);
+ 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)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node;
- ARegion *ar = CTX_wm_region(C);
+ ARegion *ar = CTX_wm_region(C);
- rcti rect;
- bool changed = false;
+ rcti rect;
+ bool changed = false;
- const bool select = (sel_op != SEL_OP_SUB);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- ED_node_select_all(&snode->edittree->nodes, SEL_DESELECT);
- changed = true;
- }
+ const bool select = (sel_op != SEL_OP_SUB);
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ ED_node_select_all(&snode->edittree->nodes, SEL_DESELECT);
+ changed = true;
+ }
- /* get rectangle from operator */
- BLI_lasso_boundbox(&rect, mcords, moves);
+ /* get rectangle from operator */
+ BLI_lasso_boundbox(&rect, mcords, moves);
- /* do actual selection */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
+ /* do actual selection */
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (select && (node->flag & NODE_SELECT)) {
- continue;
- }
+ if (select && (node->flag & NODE_SELECT)) {
+ continue;
+ }
- int screen_co[2];
- const float cent[2] = {BLI_rctf_cent_x(&node->totr),
- BLI_rctf_cent_y(&node->totr)};
+ int screen_co[2];
+ 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]) &&
- 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))
- {
- nodeSetSelected(node, select);
- changed = true;
- }
- }
+ /* marker in screen coords */
+ if (UI_view2d_view_to_region_clip(&ar->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)) {
+ nodeSetSelected(node, select);
+ changed = true;
+ }
+ }
- if (changed) {
- WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
- }
+ if (changed) {
+ WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
+ }
- return changed;
+ return changed;
}
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 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");
+ if (mcords) {
+ 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, mcords, mcords_tot, sel_op);
- MEM_freeN((void *)mcords);
+ MEM_freeN((void *)mcords);
- return OPERATOR_FINISHED;
- }
- return OPERATOR_PASS_THROUGH;
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_PASS_THROUGH;
}
void NODE_OT_select_lasso(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Lasso Select";
- ot->description = "Select nodes using lasso selection";
- ot->idname = "NODE_OT_select_lasso";
-
- /* api callbacks */
- ot->invoke = node_lasso_select_invoke;
- ot->modal = WM_gesture_lasso_modal;
- ot->exec = node_lasso_select_exec;
- ot->poll = ED_operator_node_active;
- ot->cancel = WM_gesture_lasso_cancel;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "tweak", 0, "Tweak", "Only activate when mouse is not over a node - useful for tweak gesture");
-
- WM_operator_properties_gesture_lasso(ot);
- WM_operator_properties_select_operation_simple(ot);
+ /* identifiers */
+ ot->name = "Lasso Select";
+ ot->description = "Select nodes using lasso selection";
+ ot->idname = "NODE_OT_select_lasso";
+
+ /* api callbacks */
+ ot->invoke = node_lasso_select_invoke;
+ ot->modal = WM_gesture_lasso_modal;
+ ot->exec = node_lasso_select_exec;
+ ot->poll = ED_operator_node_active;
+ ot->cancel = WM_gesture_lasso_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "tweak",
+ 0,
+ "Tweak",
+ "Only activate when mouse is not over a node - useful for tweak gesture");
+
+ WM_operator_properties_gesture_lasso(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
/** \} */
@@ -830,33 +842,33 @@ void NODE_OT_select_lasso(wmOperatorType *ot)
static int node_select_all_exec(bContext *C, wmOperator *op)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- ListBase *node_lb = &snode->edittree->nodes;
- int action = RNA_enum_get(op->ptr, "action");
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ListBase *node_lb = &snode->edittree->nodes;
+ int action = RNA_enum_get(op->ptr, "action");
- ED_node_select_all(node_lb, action);
+ ED_node_select_all(node_lb, action);
- ED_node_sort(snode->edittree);
+ ED_node_sort(snode->edittree);
- WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
+ return OPERATOR_FINISHED;
}
void NODE_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All";
- ot->description = "(De)select all nodes";
- ot->idname = "NODE_OT_select_all";
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->description = "(De)select all nodes";
+ ot->idname = "NODE_OT_select_all";
- /* api callbacks */
- ot->exec = node_select_all_exec;
- ot->poll = ED_operator_node_active;
+ /* api callbacks */
+ ot->exec = node_select_all_exec;
+ ot->poll = ED_operator_node_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_select_all(ot);
+ WM_operator_properties_select_all(ot);
}
/** \} */
@@ -867,48 +879,48 @@ void NODE_OT_select_all(wmOperatorType *ot)
static int node_select_linked_to_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeLink *link;
- bNode *node;
-
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- node->flag &= ~NODE_TEST;
- }
-
- for (link = snode->edittree->links.first; link; link = link->next) {
- if (nodeLinkIsHidden(link)) {
- continue;
- }
- if (link->fromnode && link->tonode && (link->fromnode->flag & NODE_SELECT)) {
- link->tonode->flag |= NODE_TEST;
- }
- }
-
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_TEST) {
- nodeSetSelected(node, true);
- }
- }
-
- ED_node_sort(snode->edittree);
-
- WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeLink *link;
+ bNode *node;
+
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ node->flag &= ~NODE_TEST;
+ }
+
+ for (link = snode->edittree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link)) {
+ continue;
+ }
+ if (link->fromnode && link->tonode && (link->fromnode->flag & NODE_SELECT)) {
+ link->tonode->flag |= NODE_TEST;
+ }
+ }
+
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (node->flag & NODE_TEST) {
+ nodeSetSelected(node, true);
+ }
+ }
+
+ ED_node_sort(snode->edittree);
+
+ WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
+ return OPERATOR_FINISHED;
}
void NODE_OT_select_linked_to(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Linked To";
- ot->description = "Select nodes linked to the selected ones";
- ot->idname = "NODE_OT_select_linked_to";
+ /* identifiers */
+ ot->name = "Select Linked To";
+ ot->description = "Select nodes linked to the selected ones";
+ ot->idname = "NODE_OT_select_linked_to";
- /* api callbacks */
- ot->exec = node_select_linked_to_exec;
- ot->poll = ED_operator_node_active;
+ /* api callbacks */
+ ot->exec = node_select_linked_to_exec;
+ ot->poll = ED_operator_node_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -919,48 +931,48 @@ void NODE_OT_select_linked_to(wmOperatorType *ot)
static int node_select_linked_from_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeLink *link;
- bNode *node;
-
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- node->flag &= ~NODE_TEST;
- }
-
- for (link = snode->edittree->links.first; link; link = link->next) {
- if (nodeLinkIsHidden(link)) {
- continue;
- }
- if (link->fromnode && link->tonode && (link->tonode->flag & NODE_SELECT)) {
- link->fromnode->flag |= NODE_TEST;
- }
- }
-
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_TEST) {
- nodeSetSelected(node, true);
- }
- }
-
- ED_node_sort(snode->edittree);
-
- WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeLink *link;
+ bNode *node;
+
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ node->flag &= ~NODE_TEST;
+ }
+
+ for (link = snode->edittree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link)) {
+ continue;
+ }
+ if (link->fromnode && link->tonode && (link->tonode->flag & NODE_SELECT)) {
+ link->fromnode->flag |= NODE_TEST;
+ }
+ }
+
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (node->flag & NODE_TEST) {
+ nodeSetSelected(node, true);
+ }
+ }
+
+ ED_node_sort(snode->edittree);
+
+ WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
+ return OPERATOR_FINISHED;
}
void NODE_OT_select_linked_from(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Linked From";
- ot->description = "Select nodes linked from the selected ones";
- ot->idname = "NODE_OT_select_linked_from";
+ /* identifiers */
+ ot->name = "Select Linked From";
+ ot->description = "Select nodes linked from the selected ones";
+ ot->idname = "NODE_OT_select_linked_from";
- /* api callbacks */
- ot->exec = node_select_linked_from_exec;
- ot->poll = ED_operator_node_active;
+ /* api callbacks */
+ ot->exec = node_select_linked_from_exec;
+ ot->poll = ED_operator_node_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -971,106 +983,104 @@ 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);
- bNode **node_array;
- bNode *active = nodeGetActive(snode->edittree);
- int totnodes;
- const bool revert = RNA_boolean_get(op->ptr, "prev");
- const bool same_type = 1;
-
- ntreeGetDependencyList(snode->edittree, &node_array, &totnodes);
-
- if (totnodes > 1) {
- int a;
-
- for (a = 0; a < totnodes; a++) {
- if (node_array[a] == active) {
- break;
- }
- }
-
- if (same_type) {
- bNode *node = NULL;
-
- while (node == NULL) {
- if (revert) {
- a--;
- }
- else {
- a++;
- }
-
- if (a < 0 || a >= totnodes) {
- break;
- }
-
- node = node_array[a];
-
- if (node->type == active->type) {
- break;
- }
- else {
- node = NULL;
- }
- }
- if (node) {
- active = node;
- }
- }
- else {
- if (revert) {
- if (a == 0) {
- active = node_array[totnodes - 1];
- }
- else {
- active = node_array[a - 1];
- }
- }
- else {
- if (a == totnodes - 1) {
- active = node_array[0];
- }
- else {
- active = node_array[a + 1];
- }
- }
- }
-
- 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)
- {
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- space_node_view_flag(C, snode, ar, NODE_SELECT, smooth_viewtx);
- }
- }
-
- if (node_array) {
- MEM_freeN(node_array);
- }
-
- return OPERATOR_FINISHED;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
+ bNode **node_array;
+ bNode *active = nodeGetActive(snode->edittree);
+ int totnodes;
+ const bool revert = RNA_boolean_get(op->ptr, "prev");
+ const bool same_type = 1;
+
+ ntreeGetDependencyList(snode->edittree, &node_array, &totnodes);
+
+ if (totnodes > 1) {
+ int a;
+
+ for (a = 0; a < totnodes; a++) {
+ if (node_array[a] == active) {
+ break;
+ }
+ }
+
+ if (same_type) {
+ bNode *node = NULL;
+
+ while (node == NULL) {
+ if (revert) {
+ a--;
+ }
+ else {
+ a++;
+ }
+
+ if (a < 0 || a >= totnodes) {
+ break;
+ }
+
+ node = node_array[a];
+
+ if (node->type == active->type) {
+ break;
+ }
+ else {
+ node = NULL;
+ }
+ }
+ if (node) {
+ active = node;
+ }
+ }
+ else {
+ if (revert) {
+ if (a == 0) {
+ active = node_array[totnodes - 1];
+ }
+ else {
+ active = node_array[a - 1];
+ }
+ }
+ else {
+ if (a == totnodes - 1) {
+ active = node_array[0];
+ }
+ else {
+ active = node_array[a + 1];
+ }
+ }
+ }
+
+ 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) {
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ space_node_view_flag(C, snode, ar, NODE_SELECT, smooth_viewtx);
+ }
+ }
+
+ if (node_array) {
+ MEM_freeN(node_array);
+ }
+
+ return OPERATOR_FINISHED;
}
void NODE_OT_select_same_type_step(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Activate Same Type Next/Prev";
- ot->description = "Activate and view same node type, step by step";
- ot->idname = "NODE_OT_select_same_type_step";
-
- /* api callbacks */
- ot->exec = node_select_same_type_step_exec;
- ot->poll = ED_operator_node_active;
+ /* identifiers */
+ ot->name = "Activate Same Type Next/Prev";
+ ot->description = "Activate and view same node type, step by step";
+ ot->idname = "NODE_OT_select_same_type_step";
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* api callbacks */
+ ot->exec = node_select_same_type_step_exec;
+ ot->poll = ED_operator_node_active;
- RNA_def_boolean(ot->srna, "prev", 0, "Previous", "");
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ RNA_def_boolean(ot->srna, "prev", 0, "Previous", "");
}
/** \} */
@@ -1080,96 +1090,108 @@ 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_cb(const struct bContext *C,
+ void *UNUSED(arg),
+ const char *str,
+ uiSearchItems *items)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *node;
-
- for (node = snode->edittree->nodes.first; node; node = node->next) {
-
- if (BLI_strcasestr(node->name, str) || BLI_strcasestr(node->label, str)) {
- char name[256];
-
- if (node->label[0]) {
- BLI_snprintf(name, 256, "%s (%s)", node->name, node->label);
- }
- else {
- BLI_strncpy(name, node->name, 256);
- }
- if (false == UI_search_item_add(items, name, node, 0)) {
- break;
- }
- }
- }
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node;
+
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+
+ if (BLI_strcasestr(node->name, str) || BLI_strcasestr(node->label, str)) {
+ char name[256];
+
+ if (node->label[0]) {
+ BLI_snprintf(name, 256, "%s (%s)", node->name, node->label);
+ }
+ else {
+ BLI_strncpy(name, node->name, 256);
+ }
+ if (false == UI_search_item_add(items, name, node, 0)) {
+ break;
+ }
+ }
+ }
}
static void node_find_call_cb(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);
- 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);
- }
-
- }
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *active = arg2;
+
+ if (active) {
+ ARegion *ar = 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);
+ }
+ }
}
static uiBlock *node_find_menu(bContext *C, ARegion *ar, 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);
- 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);
-
- but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, 9 * UI_UNIT_X, UI_UNIT_Y, 0, 0, "");
- UI_but_func_search_set(but, NULL, node_find_cb, op->type, false, node_find_call_cb, NULL);
- UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
-
- /* fake button, it holds space for search items */
- uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 10 - UI_searchbox_size_y(), UI_searchbox_size_x(), UI_searchbox_size_y(), NULL, 0, 0, 0, 0, NULL);
-
- /* Move it downwards, mouse over button. */
- UI_block_bounds_set_popup(block, 6, (const int[2]){0, -UI_UNIT_Y});
-
- return block;
+ static char search[256] = "";
+ uiBlock *block;
+ uiBut *but;
+ wmOperator *op = (wmOperator *)arg_op;
+
+ block = UI_block_begin(C, ar, "_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);
+
+ but = uiDefSearchBut(
+ block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, 9 * UI_UNIT_X, UI_UNIT_Y, 0, 0, "");
+ UI_but_func_search_set(but, NULL, node_find_cb, op->type, false, node_find_call_cb, NULL);
+ UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
+
+ /* fake button, it holds space for search items */
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ "",
+ 10,
+ 10 - UI_searchbox_size_y(),
+ UI_searchbox_size_x(),
+ UI_searchbox_size_y(),
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL);
+
+ /* Move it downwards, mouse over button. */
+ UI_block_bounds_set_popup(block, 6, (const int[2]){0, -UI_UNIT_Y});
+
+ return block;
}
-
static int node_find_node_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- UI_popup_block_invoke(C, node_find_menu, op);
- return OPERATOR_CANCELLED;
+ UI_popup_block_invoke(C, node_find_menu, op);
+ return OPERATOR_CANCELLED;
}
-
void NODE_OT_find_node(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Find Node";
- ot->description = "Search for named node and allow to select and activate it";
- ot->idname = "NODE_OT_find_node";
-
- /* api callbacks */
- ot->invoke = node_find_node_invoke;
- ot->poll = ED_operator_node_active;
+ /* identifiers */
+ ot->name = "Find Node";
+ ot->description = "Search for named node and allow to select and activate it";
+ ot->idname = "NODE_OT_find_node";
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* api callbacks */
+ ot->invoke = node_find_node_invoke;
+ ot->poll = ED_operator_node_active;
- RNA_def_boolean(ot->srna, "prev", 0, "Previous", "");
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ RNA_def_boolean(ot->srna, "prev", 0, "Previous", "");
}
/** \} */
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index aa6fb770c56..8cc57a82fe0 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -42,24 +42,23 @@
#include "NOD_socket.h"
#include "UI_interface.h"
-#include "../interface/interface_intern.h" /* XXX bad level */
+#include "../interface/interface_intern.h" /* XXX bad level */
-#include "ED_node.h" /* own include */
+#include "ED_node.h" /* own include */
#include "ED_undo.h"
-
/************************* Node Socket Manipulation **************************/
/* describes an instance of a node type and a specific socket to link */
typedef struct NodeLinkItem {
- int socket_index; /* index for linking */
- int socket_type; /* socket type for compatibility check */
- const char *socket_name; /* ui label of the socket */
- const char *node_name; /* ui label of the node */
+ int socket_index; /* index for linking */
+ int socket_type; /* socket type for compatibility check */
+ const char *socket_name; /* ui label of the socket */
+ const char *node_name; /* ui label of the node */
- /* extra settings */
- bNodeTree *ngroup; /* group node tree */
+ /* extra settings */
+ bNodeTree *ngroup; /* group node tree */
} NodeLinkItem;
/* Compare an existing node to a link item to see if it can be reused.
@@ -68,731 +67,799 @@ typedef struct NodeLinkItem {
*/
static bool node_link_item_compare(bNode *node, NodeLinkItem *item)
{
- if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
- return (node->id == (ID *)item->ngroup);
- }
- else {
- return true;
- }
+ if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
+ return (node->id == (ID *)item->ngroup);
+ }
+ else {
+ return true;
+ }
}
static void node_link_item_apply(Main *bmain, bNode *node, NodeLinkItem *item)
{
- if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
- node->id = (ID *)item->ngroup;
- ntreeUpdateTree(bmain, item->ngroup);
- }
- else {
- /* nothing to do for now */
- }
-
- if (node->id) {
- id_us_plus(node->id);
- }
+ if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
+ node->id = (ID *)item->ngroup;
+ ntreeUpdateTree(bmain, item->ngroup);
+ }
+ else {
+ /* nothing to do for now */
+ }
+
+ if (node->id) {
+ id_us_plus(node->id);
+ }
}
static void node_tag_recursive(bNode *node)
{
- bNodeSocket *input;
+ bNodeSocket *input;
- if (!node || (node->flag & NODE_TEST)) {
- return; /* in case of cycles */
- }
+ if (!node || (node->flag & NODE_TEST)) {
+ return; /* in case of cycles */
+ }
- node->flag |= NODE_TEST;
+ node->flag |= NODE_TEST;
- for (input = node->inputs.first; input; input = input->next) {
- if (input->link) {
- node_tag_recursive(input->link->fromnode);
- }
- }
+ for (input = node->inputs.first; input; input = input->next) {
+ if (input->link) {
+ node_tag_recursive(input->link->fromnode);
+ }
+ }
}
static void node_clear_recursive(bNode *node)
{
- bNodeSocket *input;
+ bNodeSocket *input;
- if (!node || !(node->flag & NODE_TEST)) {
- return; /* in case of cycles */
- }
+ if (!node || !(node->flag & NODE_TEST)) {
+ return; /* in case of cycles */
+ }
- node->flag &= ~NODE_TEST;
+ node->flag &= ~NODE_TEST;
- for (input = node->inputs.first; input; input = input->next) {
- if (input->link) {
- node_clear_recursive(input->link->fromnode);
- }
- }
+ for (input = node->inputs.first; input; input = input->next) {
+ if (input->link) {
+ node_clear_recursive(input->link->fromnode);
+ }
+ }
}
static void node_remove_linked(Main *bmain, bNodeTree *ntree, bNode *rem_node)
{
- bNode *node, *next;
- bNodeSocket *sock;
-
- if (!rem_node) {
- return;
- }
-
- /* tag linked nodes to be removed */
- for (node = ntree->nodes.first; node; node = node->next) {
- node->flag &= ~NODE_TEST;
- }
-
- node_tag_recursive(rem_node);
-
- /* clear tags on nodes that are still used by other nodes */
- for (node = ntree->nodes.first; node; node = node->next) {
- if (!(node->flag & NODE_TEST)) {
- for (sock = node->inputs.first; sock; sock = sock->next) {
- if (sock->link && sock->link->fromnode != rem_node) {
- node_clear_recursive(sock->link->fromnode);
- }
- }
- }
- }
-
- /* remove nodes */
- for (node = ntree->nodes.first; node; node = next) {
- next = node->next;
-
- if (node->flag & NODE_TEST) {
- nodeRemoveNode(bmain, ntree, node, true);
- }
- }
+ bNode *node, *next;
+ bNodeSocket *sock;
+
+ if (!rem_node) {
+ return;
+ }
+
+ /* tag linked nodes to be removed */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ node->flag &= ~NODE_TEST;
+ }
+
+ node_tag_recursive(rem_node);
+
+ /* clear tags on nodes that are still used by other nodes */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (!(node->flag & NODE_TEST)) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (sock->link && sock->link->fromnode != rem_node) {
+ node_clear_recursive(sock->link->fromnode);
+ }
+ }
+ }
+ }
+
+ /* remove nodes */
+ for (node = ntree->nodes.first; node; node = next) {
+ next = node->next;
+
+ if (node->flag & NODE_TEST) {
+ nodeRemoveNode(bmain, ntree, node, true);
+ }
+ }
}
/* disconnect socket from the node it is connected to */
-static void node_socket_disconnect(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to)
+static void node_socket_disconnect(Main *bmain,
+ bNodeTree *ntree,
+ bNode *node_to,
+ bNodeSocket *sock_to)
{
- if (!sock_to->link) {
- return;
- }
+ if (!sock_to->link) {
+ return;
+ }
- nodeRemLink(ntree, sock_to->link);
- sock_to->flag |= SOCK_COLLAPSED;
+ nodeRemLink(ntree, sock_to->link);
+ sock_to->flag |= SOCK_COLLAPSED;
- nodeUpdate(ntree, node_to);
- ntreeUpdateTree(bmain, ntree);
+ nodeUpdate(ntree, node_to);
+ ntreeUpdateTree(bmain, ntree);
- ED_node_tag_update_nodetree(bmain, ntree, node_to);
+ ED_node_tag_update_nodetree(bmain, ntree, node_to);
}
/* remove all nodes connected to this socket, if they aren't connected to other nodes */
static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to)
{
- if (!sock_to->link) {
- return;
- }
+ if (!sock_to->link) {
+ return;
+ }
- node_remove_linked(bmain, ntree, sock_to->link->fromnode);
- sock_to->flag |= SOCK_COLLAPSED;
+ node_remove_linked(bmain, ntree, sock_to->link->fromnode);
+ sock_to->flag |= SOCK_COLLAPSED;
- nodeUpdate(ntree, node_to);
- ntreeUpdateTree(bmain, ntree);
+ nodeUpdate(ntree, node_to);
+ ntreeUpdateTree(bmain, ntree);
- ED_node_tag_update_nodetree(bmain, ntree, node_to);
+ ED_node_tag_update_nodetree(bmain, ntree, node_to);
}
/* add new node connected to this socket, or replace an existing one */
-static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to,
- int type, NodeLinkItem *item)
+static void node_socket_add_replace(const bContext *C,
+ bNodeTree *ntree,
+ bNode *node_to,
+ bNodeSocket *sock_to,
+ int type,
+ NodeLinkItem *item)
{
- Main *bmain = CTX_data_main(C);
- bNode *node_from;
- bNodeSocket *sock_from_tmp;
- bNode *node_prev = NULL;
-
- /* unlink existing node */
- if (sock_to->link) {
- node_prev = sock_to->link->fromnode;
- nodeRemLink(ntree, sock_to->link);
- }
-
- /* find existing node that we can use */
- for (node_from = ntree->nodes.first; node_from; node_from = node_from->next) {
- if (node_from->type == type) {
- break;
- }
- }
-
- if (node_from) {
- if (node_from->inputs.first || node_from->typeinfo->draw_buttons || node_from->typeinfo->draw_buttons_ex) {
- node_from = NULL;
- }
- }
-
- if (node_prev && node_prev->type == type && node_link_item_compare(node_prev, item)) {
- /* keep the previous node if it's the same type */
- node_from = node_prev;
- }
- else if (!node_from) {
- node_from = nodeAddStaticNode(C, ntree, type);
- if (node_prev != NULL) {
- /* If we're replacing existing node, use its location. */
- node_from->locx = node_prev->locx;
- node_from->locy = node_prev->locy;
- node_from->offsetx = node_prev->offsetx;
- node_from->offsety = node_prev->offsety;
- }
- else {
- sock_from_tmp = BLI_findlink(&node_from->outputs, item->socket_index);
- nodePositionRelative(node_from, node_to, sock_from_tmp, sock_to);
- }
-
- node_link_item_apply(bmain, node_from, item);
- }
-
- nodeSetActive(ntree, node_from);
-
- /* add link */
- sock_from_tmp = BLI_findlink(&node_from->outputs, item->socket_index);
- nodeAddLink(ntree, node_from, sock_from_tmp, node_to, sock_to);
- sock_to->flag &= ~SOCK_COLLAPSED;
-
- /* copy input sockets from previous node */
- if (node_prev && node_from != node_prev) {
- bNodeSocket *sock_prev, *sock_from;
-
- 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) {
- continue;
- }
-
- if (STREQ(sock_prev->name, sock_from->name) && sock_prev->type == sock_from->type) {
- bNodeLink *link = sock_prev->link;
-
- if (link && link->fromnode) {
- nodeAddLink(ntree, link->fromnode, link->fromsock, node_from, sock_from);
- nodeRemLink(ntree, link);
- }
-
- node_socket_copy_default_value(sock_from, sock_prev);
- }
- }
- }
-
- /* also preserve mapping for texture nodes */
- if (node_from->typeinfo->nclass == NODE_CLASS_TEXTURE &&
- node_prev->typeinfo->nclass == NODE_CLASS_TEXTURE)
- {
- memcpy(node_from->storage, node_prev->storage, sizeof(NodeTexBase));
- }
-
- /* remove node */
- node_remove_linked(bmain, ntree, node_prev);
- }
-
- nodeUpdate(ntree, node_from);
- nodeUpdate(ntree, node_to);
- ntreeUpdateTree(CTX_data_main(C), ntree);
-
- ED_node_tag_update_nodetree(CTX_data_main(C), ntree, node_to);
+ Main *bmain = CTX_data_main(C);
+ bNode *node_from;
+ bNodeSocket *sock_from_tmp;
+ bNode *node_prev = NULL;
+
+ /* unlink existing node */
+ if (sock_to->link) {
+ node_prev = sock_to->link->fromnode;
+ nodeRemLink(ntree, sock_to->link);
+ }
+
+ /* find existing node that we can use */
+ for (node_from = ntree->nodes.first; node_from; node_from = node_from->next) {
+ if (node_from->type == type) {
+ break;
+ }
+ }
+
+ if (node_from) {
+ if (node_from->inputs.first || node_from->typeinfo->draw_buttons ||
+ node_from->typeinfo->draw_buttons_ex) {
+ node_from = NULL;
+ }
+ }
+
+ if (node_prev && node_prev->type == type && node_link_item_compare(node_prev, item)) {
+ /* keep the previous node if it's the same type */
+ node_from = node_prev;
+ }
+ else if (!node_from) {
+ node_from = nodeAddStaticNode(C, ntree, type);
+ if (node_prev != NULL) {
+ /* If we're replacing existing node, use its location. */
+ node_from->locx = node_prev->locx;
+ node_from->locy = node_prev->locy;
+ node_from->offsetx = node_prev->offsetx;
+ node_from->offsety = node_prev->offsety;
+ }
+ else {
+ sock_from_tmp = BLI_findlink(&node_from->outputs, item->socket_index);
+ nodePositionRelative(node_from, node_to, sock_from_tmp, sock_to);
+ }
+
+ node_link_item_apply(bmain, node_from, item);
+ }
+
+ nodeSetActive(ntree, node_from);
+
+ /* add link */
+ sock_from_tmp = BLI_findlink(&node_from->outputs, item->socket_index);
+ nodeAddLink(ntree, node_from, sock_from_tmp, node_to, sock_to);
+ sock_to->flag &= ~SOCK_COLLAPSED;
+
+ /* copy input sockets from previous node */
+ if (node_prev && node_from != node_prev) {
+ bNodeSocket *sock_prev, *sock_from;
+
+ 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) {
+ continue;
+ }
+
+ if (STREQ(sock_prev->name, sock_from->name) && sock_prev->type == sock_from->type) {
+ bNodeLink *link = sock_prev->link;
+
+ if (link && link->fromnode) {
+ nodeAddLink(ntree, link->fromnode, link->fromsock, node_from, sock_from);
+ nodeRemLink(ntree, link);
+ }
+
+ node_socket_copy_default_value(sock_from, sock_prev);
+ }
+ }
+ }
+
+ /* also preserve mapping for texture nodes */
+ if (node_from->typeinfo->nclass == NODE_CLASS_TEXTURE &&
+ node_prev->typeinfo->nclass == NODE_CLASS_TEXTURE) {
+ memcpy(node_from->storage, node_prev->storage, sizeof(NodeTexBase));
+ }
+
+ /* remove node */
+ node_remove_linked(bmain, ntree, node_prev);
+ }
+
+ nodeUpdate(ntree, node_from);
+ nodeUpdate(ntree, node_to);
+ ntreeUpdateTree(CTX_data_main(C), ntree);
+
+ ED_node_tag_update_nodetree(CTX_data_main(C), ntree, node_to);
}
/****************************** Node Link Menu *******************************/
// #define UI_NODE_LINK_ADD 0
#define UI_NODE_LINK_DISCONNECT -1
-#define UI_NODE_LINK_REMOVE -2
+#define UI_NODE_LINK_REMOVE -2
typedef struct NodeLinkArg {
- Main *bmain;
- Scene *scene;
- bNodeTree *ntree;
- bNode *node;
- bNodeSocket *sock;
+ Main *bmain;
+ Scene *scene;
+ bNodeTree *ntree;
+ bNode *node;
+ bNodeSocket *sock;
- bNodeType *node_type;
- NodeLinkItem item;
+ bNodeType *node_type;
+ NodeLinkItem item;
- uiLayout *layout;
+ uiLayout *layout;
} NodeLinkArg;
-static void ui_node_link_items(NodeLinkArg *arg, int in_out, NodeLinkItem **r_items, int *r_totitems)
+static void ui_node_link_items(NodeLinkArg *arg,
+ int in_out,
+ NodeLinkItem **r_items,
+ int *r_totitems)
{
- /* XXX this should become a callback for node types! */
- NodeLinkItem *items = NULL;
- int totitems = 0;
-
- if (arg->node_type->type == NODE_GROUP) {
- bNodeTree *ngroup;
- int i;
-
- for (ngroup = arg->bmain->nodetrees.first; ngroup; ngroup = ngroup->id.next) {
- ListBase *lb = ((in_out == SOCK_IN) ? &ngroup->inputs : &ngroup->outputs);
- totitems += BLI_listbase_count(lb);
- }
-
- if (totitems > 0) {
- items = MEM_callocN(sizeof(NodeLinkItem) * totitems, "ui node link items");
-
- i = 0;
- for (ngroup = arg->bmain->nodetrees.first; ngroup; ngroup = ngroup->id.next) {
- ListBase *lb = (in_out == SOCK_IN ? &ngroup->inputs : &ngroup->outputs);
- bNodeSocket *stemp;
- int index;
- for (stemp = lb->first, index = 0; stemp; stemp = stemp->next, ++index, ++i) {
- NodeLinkItem *item = &items[i];
-
- item->socket_index = index;
- /* note: int stemp->type is not fully reliable, not used for node group
- * interface sockets. use the typeinfo->type instead.
- */
- item->socket_type = stemp->typeinfo->type;
- item->socket_name = stemp->name;
- item->node_name = ngroup->id.name + 2;
- item->ngroup = ngroup;
- }
- }
- }
- }
- else {
- bNodeSocketTemplate *socket_templates = (in_out == SOCK_IN ? arg->node_type->inputs : arg->node_type->outputs);
- bNodeSocketTemplate *stemp;
- int i;
-
- for (stemp = socket_templates; stemp && stemp->type != -1; ++stemp) {
- ++totitems;
- }
-
- if (totitems > 0) {
- items = MEM_callocN(sizeof(NodeLinkItem) * totitems, "ui node link items");
-
- i = 0;
- for (stemp = socket_templates; stemp && stemp->type != -1; ++stemp, ++i) {
- NodeLinkItem *item = &items[i];
-
- item->socket_index = i;
- item->socket_type = stemp->type;
- item->socket_name = stemp->name;
- item->node_name = arg->node_type->ui_name;
- }
- }
- }
-
- *r_items = items;
- *r_totitems = totitems;
+ /* XXX this should become a callback for node types! */
+ NodeLinkItem *items = NULL;
+ int totitems = 0;
+
+ if (arg->node_type->type == NODE_GROUP) {
+ bNodeTree *ngroup;
+ int i;
+
+ for (ngroup = arg->bmain->nodetrees.first; ngroup; ngroup = ngroup->id.next) {
+ ListBase *lb = ((in_out == SOCK_IN) ? &ngroup->inputs : &ngroup->outputs);
+ totitems += BLI_listbase_count(lb);
+ }
+
+ if (totitems > 0) {
+ items = MEM_callocN(sizeof(NodeLinkItem) * totitems, "ui node link items");
+
+ i = 0;
+ for (ngroup = arg->bmain->nodetrees.first; ngroup; ngroup = ngroup->id.next) {
+ ListBase *lb = (in_out == SOCK_IN ? &ngroup->inputs : &ngroup->outputs);
+ bNodeSocket *stemp;
+ int index;
+ for (stemp = lb->first, index = 0; stemp; stemp = stemp->next, ++index, ++i) {
+ NodeLinkItem *item = &items[i];
+
+ item->socket_index = index;
+ /* note: int stemp->type is not fully reliable, not used for node group
+ * interface sockets. use the typeinfo->type instead.
+ */
+ item->socket_type = stemp->typeinfo->type;
+ item->socket_name = stemp->name;
+ item->node_name = ngroup->id.name + 2;
+ item->ngroup = ngroup;
+ }
+ }
+ }
+ }
+ else {
+ bNodeSocketTemplate *socket_templates = (in_out == SOCK_IN ? arg->node_type->inputs :
+ arg->node_type->outputs);
+ bNodeSocketTemplate *stemp;
+ int i;
+
+ for (stemp = socket_templates; stemp && stemp->type != -1; ++stemp) {
+ ++totitems;
+ }
+
+ if (totitems > 0) {
+ items = MEM_callocN(sizeof(NodeLinkItem) * totitems, "ui node link items");
+
+ i = 0;
+ for (stemp = socket_templates; stemp && stemp->type != -1; ++stemp, ++i) {
+ NodeLinkItem *item = &items[i];
+
+ item->socket_index = i;
+ item->socket_type = stemp->type;
+ item->socket_name = stemp->name;
+ item->node_name = arg->node_type->ui_name;
+ }
+ }
+ }
+
+ *r_items = items;
+ *r_totitems = totitems;
}
static void ui_node_link(bContext *C, void *arg_p, void *event_p)
{
- NodeLinkArg *arg = (NodeLinkArg *)arg_p;
- Main *bmain = arg->bmain;
- bNode *node_to = arg->node;
- bNodeSocket *sock_to = arg->sock;
- bNodeTree *ntree = arg->ntree;
- int event = POINTER_AS_INT(event_p);
-
- if (event == UI_NODE_LINK_DISCONNECT) {
- node_socket_disconnect(bmain, ntree, node_to, sock_to);
- }
- else if (event == UI_NODE_LINK_REMOVE) {
- node_socket_remove(bmain, ntree, node_to, sock_to);
- }
- else {
- node_socket_add_replace(C, ntree, node_to, sock_to, arg->node_type->type, &arg->item);
- }
-
- ED_undo_push(C, "Node input modify");
+ NodeLinkArg *arg = (NodeLinkArg *)arg_p;
+ Main *bmain = arg->bmain;
+ bNode *node_to = arg->node;
+ bNodeSocket *sock_to = arg->sock;
+ bNodeTree *ntree = arg->ntree;
+ int event = POINTER_AS_INT(event_p);
+
+ if (event == UI_NODE_LINK_DISCONNECT) {
+ node_socket_disconnect(bmain, ntree, node_to, sock_to);
+ }
+ else if (event == UI_NODE_LINK_REMOVE) {
+ node_socket_remove(bmain, ntree, node_to, sock_to);
+ }
+ else {
+ node_socket_add_replace(C, ntree, node_to, sock_to, arg->node_type->type, &arg->item);
+ }
+
+ ED_undo_push(C, "Node input modify");
}
static void ui_node_sock_name(bNodeTree *ntree, bNodeSocket *sock, char name[UI_MAX_NAME_STR])
{
- if (sock->link && sock->link->fromnode) {
- bNode *node = sock->link->fromnode;
- char node_name[UI_MAX_NAME_STR];
-
- nodeLabel(ntree, node, node_name, sizeof(node_name));
-
- if (BLI_listbase_is_empty(&node->inputs) &&
- node->outputs.first != node->outputs.last)
- {
- BLI_snprintf(name, UI_MAX_NAME_STR, "%s | %s", IFACE_(node_name), IFACE_(sock->link->fromsock->name));
- }
- else {
- BLI_strncpy(name, IFACE_(node_name), UI_MAX_NAME_STR);
- }
- }
- else if (sock->type == SOCK_SHADER) {
- BLI_strncpy(name, IFACE_("None"), UI_MAX_NAME_STR);
- }
- else {
- BLI_strncpy(name, IFACE_("Default"), UI_MAX_NAME_STR);
- }
+ if (sock->link && sock->link->fromnode) {
+ bNode *node = sock->link->fromnode;
+ char node_name[UI_MAX_NAME_STR];
+
+ nodeLabel(ntree, node, node_name, sizeof(node_name));
+
+ if (BLI_listbase_is_empty(&node->inputs) && node->outputs.first != node->outputs.last) {
+ BLI_snprintf(
+ name, UI_MAX_NAME_STR, "%s | %s", IFACE_(node_name), IFACE_(sock->link->fromsock->name));
+ }
+ else {
+ BLI_strncpy(name, IFACE_(node_name), UI_MAX_NAME_STR);
+ }
+ }
+ else if (sock->type == SOCK_SHADER) {
+ BLI_strncpy(name, IFACE_("None"), UI_MAX_NAME_STR);
+ }
+ else {
+ BLI_strncpy(name, IFACE_("Default"), UI_MAX_NAME_STR);
+ }
}
static int ui_compatible_sockets(int typeA, int typeB)
{
- return (typeA == typeB);
+ return (typeA == typeB);
}
static int ui_node_item_name_compare(const void *a, const void *b)
{
- const bNodeType *type_a = *(const bNodeType **)a;
- const bNodeType *type_b = *(const bNodeType **)b;
- return BLI_natstrcmp(type_a->ui_name, type_b->ui_name);
+ const bNodeType *type_a = *(const bNodeType **)a;
+ const bNodeType *type_b = *(const bNodeType **)b;
+ return BLI_natstrcmp(type_a->ui_name, type_b->ui_name);
}
-static bool ui_node_item_special_poll(const bNodeTree *UNUSED(ntree),
- const bNodeType *ntype)
+static bool ui_node_item_special_poll(const bNodeTree *UNUSED(ntree), const bNodeType *ntype)
{
- if (STREQ(ntype->idname, "ShaderNodeUVAlongStroke")) {
- /* TODO(sergey): Currently we don't have Freestyle nodes edited from
- * the buttons context, so can ignore it's nodes completely.
- *
- * However, we might want to do some extra checks here later.
- */
- return false;
- }
- return true;
+ if (STREQ(ntype->idname, "ShaderNodeUVAlongStroke")) {
+ /* TODO(sergey): Currently we don't have Freestyle nodes edited from
+ * the buttons context, so can ignore it's nodes completely.
+ *
+ * However, we might want to do some extra checks here later.
+ */
+ return false;
+ }
+ return true;
}
static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
{
- bNodeTree *ntree = arg->ntree;
- bNodeSocket *sock = arg->sock;
- uiLayout *layout = arg->layout;
- uiLayout *column = NULL;
- uiBlock *block = uiLayoutGetBlock(layout);
- uiBut *but;
- NodeLinkArg *argN;
- int first = 1;
-
- /* generate array of node types sorted by UI name */
- bNodeType **sorted_ntypes = NULL;
- BLI_array_declare(sorted_ntypes);
-
- NODE_TYPES_BEGIN(ntype) {
- if (!(ntype->poll && ntype->poll(ntype, ntree))) {
- continue;
- }
-
- if (ntype->nclass != nclass) {
- continue;
- }
-
- if (!ui_node_item_special_poll(ntree, ntype)) {
- continue;
- }
-
- BLI_array_append(sorted_ntypes, ntype);
- } NODE_TYPES_END;
-
- qsort(sorted_ntypes, BLI_array_len(sorted_ntypes), sizeof(bNodeType *), ui_node_item_name_compare);
-
- /* generate UI */
- for (int j = 0; j < BLI_array_len(sorted_ntypes); j++) {
- bNodeType *ntype = sorted_ntypes[j];
- NodeLinkItem *items;
- int totitems;
- char name[UI_MAX_NAME_STR];
- const char *cur_node_name = NULL;
- int i, num = 0;
- int icon = ICON_NONE;
-
- arg->node_type = ntype;
-
- ui_node_link_items(arg, SOCK_OUT, &items, &totitems);
-
- for (i = 0; i < totitems; ++i) {
- if (ui_compatible_sockets(items[i].socket_type, sock->type)) {
- num++;
- }
- }
-
- for (i = 0; i < totitems; ++i) {
- if (!ui_compatible_sockets(items[i].socket_type, sock->type)) {
- continue;
- }
-
- if (first) {
- column = uiLayoutColumn(layout, 0);
- UI_block_layout_set_current(block, column);
-
- uiItemL(column, IFACE_(cname), ICON_NODE);
- but = block->buttons.last;
-
- first = 0;
- }
-
- if (num > 1) {
- if (!cur_node_name || !STREQ(cur_node_name, items[i].node_name)) {
- cur_node_name = items[i].node_name;
- /* XXX Do not use uiItemL here,
- * it would add an empty icon as we are in a menu! */
- uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_(cur_node_name), 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, "");
- }
-
- BLI_snprintf(name, UI_MAX_NAME_STR, "%s", IFACE_(items[i].socket_name));
- icon = ICON_BLANK1;
- }
- else {
- BLI_strncpy(name, IFACE_(items[i].node_name), UI_MAX_NAME_STR);
- icon = ICON_NONE;
- }
-
- but = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, icon, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input"));
-
- argN = MEM_dupallocN(arg);
- argN->item = items[i];
- UI_but_funcN_set(but, ui_node_link, argN, NULL);
- }
-
- if (items) {
- MEM_freeN(items);
- }
- }
-
- BLI_array_free(sorted_ntypes);
+ bNodeTree *ntree = arg->ntree;
+ bNodeSocket *sock = arg->sock;
+ uiLayout *layout = arg->layout;
+ uiLayout *column = NULL;
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiBut *but;
+ NodeLinkArg *argN;
+ int first = 1;
+
+ /* generate array of node types sorted by UI name */
+ bNodeType **sorted_ntypes = NULL;
+ BLI_array_declare(sorted_ntypes);
+
+ NODE_TYPES_BEGIN (ntype) {
+ if (!(ntype->poll && ntype->poll(ntype, ntree))) {
+ continue;
+ }
+
+ if (ntype->nclass != nclass) {
+ continue;
+ }
+
+ if (!ui_node_item_special_poll(ntree, ntype)) {
+ continue;
+ }
+
+ BLI_array_append(sorted_ntypes, ntype);
+ }
+ NODE_TYPES_END;
+
+ qsort(
+ sorted_ntypes, BLI_array_len(sorted_ntypes), sizeof(bNodeType *), ui_node_item_name_compare);
+
+ /* generate UI */
+ for (int j = 0; j < BLI_array_len(sorted_ntypes); j++) {
+ bNodeType *ntype = sorted_ntypes[j];
+ NodeLinkItem *items;
+ int totitems;
+ char name[UI_MAX_NAME_STR];
+ const char *cur_node_name = NULL;
+ int i, num = 0;
+ int icon = ICON_NONE;
+
+ arg->node_type = ntype;
+
+ ui_node_link_items(arg, SOCK_OUT, &items, &totitems);
+
+ for (i = 0; i < totitems; ++i) {
+ if (ui_compatible_sockets(items[i].socket_type, sock->type)) {
+ num++;
+ }
+ }
+
+ for (i = 0; i < totitems; ++i) {
+ if (!ui_compatible_sockets(items[i].socket_type, sock->type)) {
+ continue;
+ }
+
+ if (first) {
+ column = uiLayoutColumn(layout, 0);
+ UI_block_layout_set_current(block, column);
+
+ uiItemL(column, IFACE_(cname), ICON_NODE);
+ but = block->buttons.last;
+
+ first = 0;
+ }
+
+ if (num > 1) {
+ if (!cur_node_name || !STREQ(cur_node_name, items[i].node_name)) {
+ cur_node_name = items[i].node_name;
+ /* XXX Do not use uiItemL here,
+ * it would add an empty icon as we are in a menu! */
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ IFACE_(cur_node_name),
+ 0,
+ 0,
+ UI_UNIT_X * 4,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ "");
+ }
+
+ BLI_snprintf(name, UI_MAX_NAME_STR, "%s", IFACE_(items[i].socket_name));
+ icon = ICON_BLANK1;
+ }
+ else {
+ BLI_strncpy(name, IFACE_(items[i].node_name), UI_MAX_NAME_STR);
+ icon = ICON_NONE;
+ }
+
+ but = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ icon,
+ name,
+ 0,
+ 0,
+ UI_UNIT_X * 4,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Add node to input"));
+
+ argN = MEM_dupallocN(arg);
+ argN->item = items[i];
+ UI_but_funcN_set(but, ui_node_link, argN, NULL);
+ }
+
+ if (items) {
+ MEM_freeN(items);
+ }
+ }
+
+ BLI_array_free(sorted_ntypes);
}
static void node_menu_column_foreach_cb(void *calldata, int nclass, const char *name)
{
- NodeLinkArg *arg = (NodeLinkArg *)calldata;
+ NodeLinkArg *arg = (NodeLinkArg *)calldata;
- if (!ELEM(nclass, NODE_CLASS_GROUP, NODE_CLASS_LAYOUT)) {
- ui_node_menu_column(arg, nclass, name);
- }
+ if (!ELEM(nclass, NODE_CLASS_GROUP, NODE_CLASS_LAYOUT)) {
+ ui_node_menu_column(arg, nclass, name);
+ }
}
static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_p)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- uiBlock *block = uiLayoutGetBlock(layout);
- uiBut *but = (uiBut *)but_p;
- uiLayout *split, *column;
- NodeLinkArg *arg = (NodeLinkArg *)but->func_argN;
- bNodeSocket *sock = arg->sock;
- bNodeTreeType *ntreetype = arg->ntree->typeinfo;
-
- UI_block_flag_enable(block, UI_BLOCK_NO_FLIP | UI_BLOCK_IS_FLIP);
- UI_block_layout_set_current(block, layout);
- split = uiLayoutSplit(layout, 0.0f, false);
-
- arg->bmain = bmain;
- arg->scene = scene;
- arg->layout = split;
-
- if (ntreetype && ntreetype->foreach_nodeclass) {
- ntreetype->foreach_nodeclass(scene, arg, node_menu_column_foreach_cb);
- }
-
- column = uiLayoutColumn(split, false);
- UI_block_layout_set_current(block, column);
-
- if (sock->link) {
- uiItemL(column, IFACE_("Link"), ICON_NONE);
- but = block->buttons.last;
- but->drawflag = UI_BUT_TEXT_LEFT;
-
- but = uiDefBut(block, UI_BTYPE_BUT, 0, IFACE_("Remove"), 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Remove nodes connected to the input"));
- UI_but_funcN_set(but, ui_node_link, MEM_dupallocN(arg), POINTER_FROM_INT(UI_NODE_LINK_REMOVE));
-
- but = uiDefBut(block, UI_BTYPE_BUT, 0, IFACE_("Disconnect"), 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Disconnect nodes connected to the input"));
- UI_but_funcN_set(but, ui_node_link, MEM_dupallocN(arg), POINTER_FROM_INT(UI_NODE_LINK_DISCONNECT));
- }
-
- ui_node_menu_column(arg, NODE_CLASS_GROUP, N_("Group"));
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiBut *but = (uiBut *)but_p;
+ uiLayout *split, *column;
+ NodeLinkArg *arg = (NodeLinkArg *)but->func_argN;
+ bNodeSocket *sock = arg->sock;
+ bNodeTreeType *ntreetype = arg->ntree->typeinfo;
+
+ UI_block_flag_enable(block, UI_BLOCK_NO_FLIP | UI_BLOCK_IS_FLIP);
+ UI_block_layout_set_current(block, layout);
+ split = uiLayoutSplit(layout, 0.0f, false);
+
+ arg->bmain = bmain;
+ arg->scene = scene;
+ arg->layout = split;
+
+ if (ntreetype && ntreetype->foreach_nodeclass) {
+ ntreetype->foreach_nodeclass(scene, arg, node_menu_column_foreach_cb);
+ }
+
+ column = uiLayoutColumn(split, false);
+ UI_block_layout_set_current(block, column);
+
+ if (sock->link) {
+ uiItemL(column, IFACE_("Link"), ICON_NONE);
+ but = block->buttons.last;
+ but->drawflag = UI_BUT_TEXT_LEFT;
+
+ but = uiDefBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ IFACE_("Remove"),
+ 0,
+ 0,
+ UI_UNIT_X * 4,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Remove nodes connected to the input"));
+ UI_but_funcN_set(but, ui_node_link, MEM_dupallocN(arg), POINTER_FROM_INT(UI_NODE_LINK_REMOVE));
+
+ but = uiDefBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ IFACE_("Disconnect"),
+ 0,
+ 0,
+ UI_UNIT_X * 4,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Disconnect nodes connected to the input"));
+ UI_but_funcN_set(
+ but, ui_node_link, MEM_dupallocN(arg), POINTER_FROM_INT(UI_NODE_LINK_DISCONNECT));
+ }
+
+ ui_node_menu_column(arg, NODE_CLASS_GROUP, N_("Group"));
}
void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSocket *sock)
{
- uiBlock *block = uiLayoutGetBlock(layout);
- NodeLinkArg *arg;
- uiBut *but;
-
- arg = MEM_callocN(sizeof(NodeLinkArg), "NodeLinkArg");
- arg->ntree = ntree;
- arg->node = node;
- arg->sock = sock;
-
- UI_block_layout_set_current(block, layout);
-
- if (sock->link || sock->type == SOCK_SHADER || (sock->flag & SOCK_HIDE_VALUE)) {
- char name[UI_MAX_NAME_STR];
- ui_node_sock_name(ntree, sock, name);
- but = uiDefMenuBut(block, ui_template_node_link_menu, NULL, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y, "");
- }
- else {
- but = uiDefIconMenuBut(block, ui_template_node_link_menu, NULL, ICON_NONE, 0, 0, UI_UNIT_X, UI_UNIT_Y, "");
- }
-
- UI_but_type_set_menu_from_pulldown(but);
-
- but->flag |= UI_BUT_NODE_LINK;
- but->poin = (char *)but;
- but->func_argN = arg;
-
- if (sock->link && sock->link->fromnode) {
- if (sock->link->fromnode->flag & NODE_ACTIVE_TEXTURE) {
- but->flag |= UI_BUT_NODE_ACTIVE;
- }
- }
+ uiBlock *block = uiLayoutGetBlock(layout);
+ NodeLinkArg *arg;
+ uiBut *but;
+
+ arg = MEM_callocN(sizeof(NodeLinkArg), "NodeLinkArg");
+ arg->ntree = ntree;
+ arg->node = node;
+ arg->sock = sock;
+
+ UI_block_layout_set_current(block, layout);
+
+ if (sock->link || sock->type == SOCK_SHADER || (sock->flag & SOCK_HIDE_VALUE)) {
+ char name[UI_MAX_NAME_STR];
+ ui_node_sock_name(ntree, sock, name);
+ but = uiDefMenuBut(
+ block, ui_template_node_link_menu, NULL, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y, "");
+ }
+ else {
+ but = uiDefIconMenuBut(
+ block, ui_template_node_link_menu, NULL, ICON_NONE, 0, 0, UI_UNIT_X, UI_UNIT_Y, "");
+ }
+
+ UI_but_type_set_menu_from_pulldown(but);
+
+ but->flag |= UI_BUT_NODE_LINK;
+ but->poin = (char *)but;
+ but->func_argN = arg;
+
+ if (sock->link && sock->link->fromnode) {
+ if (sock->link->fromnode->flag & NODE_ACTIVE_TEXTURE) {
+ but->flag |= UI_BUT_NODE_ACTIVE;
+ }
+ }
}
/**************************** Node Tree Layout *******************************/
-static void ui_node_draw_input(uiLayout *layout, bContext *C,
- bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth);
+static void ui_node_draw_input(
+ uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth);
-static void ui_node_draw_node(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, int depth)
+static void ui_node_draw_node(
+ uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, int depth)
{
- bNodeSocket *input;
- uiLayout *col, *split;
- PointerRNA nodeptr;
+ bNodeSocket *input;
+ uiLayout *col, *split;
+ PointerRNA nodeptr;
- RNA_pointer_create(&ntree->id, &RNA_Node, node, &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);
+ 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);
- }
- }
+ node->typeinfo->draw_buttons(col, C, &nodeptr);
+ }
+ }
- for (input = node->inputs.first; input; input = input->next) {
- ui_node_draw_input(layout, C, ntree, node, input, depth + 1);
- }
+ for (input = node->inputs.first; input; input = input->next) {
+ ui_node_draw_input(layout, C, ntree, node, input, depth + 1);
+ }
}
-static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth)
+static void ui_node_draw_input(
+ uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth)
{
- PointerRNA inputptr, nodeptr;
- uiBlock *block = uiLayoutGetBlock(layout);
- uiBut *bt;
- uiLayout *split, *row, *col;
- bNode *lnode;
- char label[UI_MAX_NAME_STR];
- int i, indent = (depth > 1) ? 2 * (depth - 1) : 0;
- int dependency_loop;
-
- if (input->flag & SOCK_UNAVAIL) {
- return;
- }
-
- /* to avoid eternal loops on cyclic dependencies */
- node->flag |= NODE_TEST;
- lnode = (input->link) ? input->link->fromnode : NULL;
-
- dependency_loop = (lnode && (lnode->flag & NODE_TEST));
- if (dependency_loop) {
- lnode = NULL;
- }
-
- /* socket RNA pointer */
- 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));
-
- /* split in label and value */
- split = uiLayoutSplit(layout, 0.5f, false);
-
- row = uiLayoutRow(split, true);
-
- 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);
- }
-
- bt = block->buttons.last;
- bt->rect.xmax = UI_UNIT_X / 2;
-
- UI_block_emboss_set(block, UI_EMBOSS);
- }
-
- 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);
- }
- else if (lnode) {
- /* input linked to a node */
- uiTemplateNodeLink(split, ntree, node, input);
-
- if (depth == 0 || !(input->flag & SOCK_COLLAPSED)) {
- if (depth == 0) {
- uiItemS(layout);
- }
-
- ui_node_draw_node(layout, C, ntree, lnode, depth);
- }
- }
- else {
- /* input not linked, show value */
- if (!(input->flag & SOCK_HIDE_VALUE)) {
- switch (input->type) {
- 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);
- break;
-
- default:
- row = uiLayoutRow(split, false);
- break;
- }
- }
- else {
- row = uiLayoutRow(split, false);
- }
-
- uiTemplateNodeLink(row, ntree, node, input);
- }
-
- /* clear */
- node->flag &= ~NODE_TEST;
+ PointerRNA inputptr, nodeptr;
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiBut *bt;
+ uiLayout *split, *row, *col;
+ bNode *lnode;
+ char label[UI_MAX_NAME_STR];
+ int i, indent = (depth > 1) ? 2 * (depth - 1) : 0;
+ int dependency_loop;
+
+ if (input->flag & SOCK_UNAVAIL) {
+ return;
+ }
+
+ /* to avoid eternal loops on cyclic dependencies */
+ node->flag |= NODE_TEST;
+ lnode = (input->link) ? input->link->fromnode : NULL;
+
+ dependency_loop = (lnode && (lnode->flag & NODE_TEST));
+ if (dependency_loop) {
+ lnode = NULL;
+ }
+
+ /* socket RNA pointer */
+ 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));
+
+ /* split in label and value */
+ split = uiLayoutSplit(layout, 0.5f, false);
+
+ row = uiLayoutRow(split, true);
+
+ 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);
+ }
+
+ bt = block->buttons.last;
+ bt->rect.xmax = UI_UNIT_X / 2;
+
+ UI_block_emboss_set(block, UI_EMBOSS);
+ }
+
+ 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);
+ }
+ else if (lnode) {
+ /* input linked to a node */
+ uiTemplateNodeLink(split, ntree, node, input);
+
+ if (depth == 0 || !(input->flag & SOCK_COLLAPSED)) {
+ if (depth == 0) {
+ uiItemS(layout);
+ }
+
+ ui_node_draw_node(layout, C, ntree, lnode, depth);
+ }
+ }
+ else {
+ /* input not linked, show value */
+ if (!(input->flag & SOCK_HIDE_VALUE)) {
+ switch (input->type) {
+ 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);
+ break;
+
+ default:
+ row = uiLayoutRow(split, false);
+ break;
+ }
+ }
+ else {
+ row = uiLayoutRow(split, false);
+ }
+
+ uiTemplateNodeLink(row, ntree, node, input);
+ }
+
+ /* clear */
+ node->flag &= ~NODE_TEST;
}
-void uiTemplateNodeView(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input)
+void uiTemplateNodeView(
+ uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input)
{
- bNode *tnode;
-
- if (!ntree) {
- return;
- }
-
- /* clear for cycle check */
- for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
- tnode->flag &= ~NODE_TEST;
- }
-
- if (input) {
- ui_node_draw_input(layout, C, ntree, node, input, 0);
- }
- else {
- ui_node_draw_node(layout, C, ntree, node, 0);
- }
+ bNode *tnode;
+
+ if (!ntree) {
+ return;
+ }
+
+ /* clear for cycle check */
+ for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
+ tnode->flag &= ~NODE_TEST;
+ }
+
+ if (input) {
+ ui_node_draw_input(layout, C, ntree, node, input, 0);
+ }
+ else {
+ ui_node_draw_node(layout, C, ntree, node, 0);
+ }
}
diff --git a/source/blender/editors/space_node/node_toolbar.c b/source/blender/editors/space_node/node_toolbar.c
index dae8024611a..bc7119fa4ab 100644
--- a/source/blender/editors/space_node/node_toolbar.c
+++ b/source/blender/editors/space_node/node_toolbar.c
@@ -33,8 +33,7 @@
#include "ED_screen.h"
-#include "node_intern.h" /* own include */
-
+#include "node_intern.h" /* own include */
/* ******************* node toolbar registration ************** */
@@ -46,32 +45,32 @@ void node_toolbar_register(ARegionType *UNUSED(art))
static int node_toolbar_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = node_has_tools_region(sa);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = node_has_tools_region(sa);
- if (ar) {
- ED_region_toggle_hidden(C, ar);
- }
+ if (ar) {
+ ED_region_toggle_hidden(C, ar);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* non-standard poll operator which doesn't care if there are any nodes */
static bool node_toolbar_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- return (sa && (sa->spacetype == SPACE_NODE));
+ ScrArea *sa = CTX_wm_area(C);
+ return (sa && (sa->spacetype == SPACE_NODE));
}
void NODE_OT_toolbar(wmOperatorType *ot)
{
- ot->name = "Tool Shelf";
- ot->description = "Toggles tool shelf display";
- ot->idname = "NODE_OT_toolbar";
+ ot->name = "Tool Shelf";
+ ot->description = "Toggles tool shelf display";
+ ot->idname = "NODE_OT_toolbar";
- ot->exec = node_toolbar_toggle_exec;
- ot->poll = node_toolbar_poll;
+ ot->exec = node_toolbar_toggle_exec;
+ ot->poll = node_toolbar_poll;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index 9d4b9d18c2a..15eb12ecf39 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -33,7 +33,7 @@
#include "BKE_node.h"
#include "BKE_screen.h"
-#include "ED_node.h" /* own include */
+#include "ED_node.h" /* own include */
#include "ED_screen.h"
#include "ED_space_api.h"
#include "ED_image.h"
@@ -52,587 +52,593 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
-#include "node_intern.h" /* own include */
+#include "node_intern.h" /* own include */
#include "NOD_composite.h"
-
/* **************** View All Operator ************** */
-int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar,
- const int node_flag, const int smooth_viewtx)
+int space_node_view_flag(
+ bContext *C, SpaceNode *snode, ARegion *ar, const int node_flag, const int smooth_viewtx)
{
- bNode *node;
- rctf cur_new;
- float oldwidth, oldheight, width, height;
- float oldasp, asp;
- int tot = 0;
- bool has_frame = false;
-
- oldwidth = BLI_rctf_size_x(&ar->v2d.cur);
- oldheight = BLI_rctf_size_y(&ar->v2d.cur);
-
- oldasp = oldwidth / oldheight;
-
- BLI_rctf_init_minmax(&cur_new);
-
- if (snode->edittree) {
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if ((node->flag & node_flag) == node_flag) {
- BLI_rctf_union(&cur_new, &node->totr);
- tot++;
-
- if (node->type == NODE_FRAME) {
- has_frame = true;
- }
- }
- }
- }
-
- if (tot) {
- width = BLI_rctf_size_x(&cur_new);
- height = BLI_rctf_size_y(&cur_new);
- asp = width / height;
-
- /* for single non-frame nodes, don't zoom in, just pan view,
- * but do allow zooming out, this allows for big nodes to be zoomed out */
- if ((tot == 1) &&
- (has_frame == false) &&
- ((oldwidth * oldheight) > (width * height)))
- {
- /* center, don't zoom */
- BLI_rctf_resize(&cur_new, oldwidth, oldheight);
- }
- else {
- if (oldasp < asp) {
- const float height_new = width / oldasp;
- cur_new.ymin = cur_new.ymin - height_new / 2.0f;
- cur_new.ymax = cur_new.ymax + height_new / 2.0f;
- }
- else {
- const float width_new = height * oldasp;
- cur_new.xmin = cur_new.xmin - width_new / 2.0f;
- cur_new.xmax = cur_new.xmax + width_new / 2.0f;
- }
-
- /* add some padding */
- BLI_rctf_scale(&cur_new, 1.1f);
- }
-
- UI_view2d_smooth_view(C, ar, &cur_new, smooth_viewtx);
- }
-
- return (tot != 0);
+ bNode *node;
+ rctf cur_new;
+ float oldwidth, oldheight, width, height;
+ float oldasp, asp;
+ int tot = 0;
+ bool has_frame = false;
+
+ oldwidth = BLI_rctf_size_x(&ar->v2d.cur);
+ oldheight = BLI_rctf_size_y(&ar->v2d.cur);
+
+ oldasp = oldwidth / oldheight;
+
+ BLI_rctf_init_minmax(&cur_new);
+
+ if (snode->edittree) {
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if ((node->flag & node_flag) == node_flag) {
+ BLI_rctf_union(&cur_new, &node->totr);
+ tot++;
+
+ if (node->type == NODE_FRAME) {
+ has_frame = true;
+ }
+ }
+ }
+ }
+
+ if (tot) {
+ width = BLI_rctf_size_x(&cur_new);
+ height = BLI_rctf_size_y(&cur_new);
+ asp = width / height;
+
+ /* for single non-frame nodes, don't zoom in, just pan view,
+ * but do allow zooming out, this allows for big nodes to be zoomed out */
+ if ((tot == 1) && (has_frame == false) && ((oldwidth * oldheight) > (width * height))) {
+ /* center, don't zoom */
+ BLI_rctf_resize(&cur_new, oldwidth, oldheight);
+ }
+ else {
+ if (oldasp < asp) {
+ const float height_new = width / oldasp;
+ cur_new.ymin = cur_new.ymin - height_new / 2.0f;
+ cur_new.ymax = cur_new.ymax + height_new / 2.0f;
+ }
+ else {
+ const float width_new = height * oldasp;
+ cur_new.xmin = cur_new.xmin - width_new / 2.0f;
+ cur_new.xmax = cur_new.xmax + width_new / 2.0f;
+ }
+
+ /* add some padding */
+ BLI_rctf_scale(&cur_new, 1.1f);
+ }
+
+ UI_view2d_smooth_view(C, ar, &cur_new, smooth_viewtx);
+ }
+
+ return (tot != 0);
}
static int node_view_all_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
-
- /* is this really needed? */
- snode->xof = 0;
- snode->yof = 0;
-
- if (space_node_view_flag(C, snode, ar, 0, smooth_viewtx)) {
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ ARegion *ar = CTX_wm_region(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+
+ /* is this really needed? */
+ snode->xof = 0;
+ snode->yof = 0;
+
+ if (space_node_view_flag(C, snode, ar, 0, smooth_viewtx)) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void NODE_OT_view_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View All";
- ot->idname = "NODE_OT_view_all";
- ot->description = "Resize view so you can see all nodes";
+ /* identifiers */
+ ot->name = "View All";
+ ot->idname = "NODE_OT_view_all";
+ ot->description = "Resize view so you can see all nodes";
- /* api callbacks */
- ot->exec = node_view_all_exec;
- ot->poll = ED_operator_node_active;
+ /* api callbacks */
+ ot->exec = node_view_all_exec;
+ ot->poll = ED_operator_node_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int node_view_selected_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = 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)) {
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ ARegion *ar = 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)) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void NODE_OT_view_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Selected";
- ot->idname = "NODE_OT_view_selected";
- ot->description = "Resize view so you can see selected nodes";
+ /* identifiers */
+ ot->name = "View Selected";
+ ot->idname = "NODE_OT_view_selected";
+ ot->description = "Resize view so you can see selected nodes";
- /* api callbacks */
- ot->exec = node_view_selected_exec;
- ot->poll = ED_operator_node_active;
+ /* api callbacks */
+ ot->exec = node_view_selected_exec;
+ ot->poll = ED_operator_node_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* **************** Background Image Operators ************** */
typedef struct NodeViewMove {
- int mvalo[2];
- int xmin, ymin, xmax, ymax;
+ int mvalo[2];
+ int xmin, ymin, xmax, ymax;
} 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);
- NodeViewMove *nvm = op->customdata;
-
- switch (event->type) {
- case MOUSEMOVE:
-
- snode->xof -= (nvm->mvalo[0] - event->mval[0]);
- snode->yof -= (nvm->mvalo[1] - event->mval[1]);
- nvm->mvalo[0] = event->mval[0];
- nvm->mvalo[1] = event->mval[1];
-
- /* prevent dragging image outside of the window and losing it! */
- CLAMP(snode->xof, nvm->xmin, nvm->xmax);
- CLAMP(snode->yof, nvm->ymin, nvm->ymax);
-
- ED_region_tag_redraw(ar);
- WM_main_add_notifier(NC_NODE | ND_DISPLAY, NULL);
-
- break;
-
- case LEFTMOUSE:
- case MIDDLEMOUSE:
- case RIGHTMOUSE:
- if (event->val == KM_RELEASE) {
- MEM_freeN(nvm);
- op->customdata = NULL;
- return OPERATOR_FINISHED;
- }
- break;
- }
-
- return OPERATOR_RUNNING_MODAL;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
+ NodeViewMove *nvm = op->customdata;
+
+ switch (event->type) {
+ case MOUSEMOVE:
+
+ snode->xof -= (nvm->mvalo[0] - event->mval[0]);
+ snode->yof -= (nvm->mvalo[1] - event->mval[1]);
+ nvm->mvalo[0] = event->mval[0];
+ nvm->mvalo[1] = event->mval[1];
+
+ /* prevent dragging image outside of the window and losing it! */
+ CLAMP(snode->xof, nvm->xmin, nvm->xmax);
+ CLAMP(snode->yof, nvm->ymin, nvm->ymax);
+
+ ED_region_tag_redraw(ar);
+ WM_main_add_notifier(NC_NODE | ND_DISPLAY, NULL);
+
+ break;
+
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ case RIGHTMOUSE:
+ if (event->val == KM_RELEASE) {
+ MEM_freeN(nvm);
+ op->customdata = NULL;
+ return OPERATOR_FINISHED;
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
static int snode_bg_viewmove_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);
- NodeViewMove *nvm;
- Image *ima;
- ImBuf *ibuf;
- const float pad = 32.0f; /* better be bigger then scrollbars */
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
+ NodeViewMove *nvm;
+ Image *ima;
+ ImBuf *ibuf;
+ const float pad = 32.0f; /* better be bigger then scrollbars */
- void *lock;
+ void *lock;
- ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
- ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+ ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
- if (ibuf == NULL) {
- BKE_image_release_ibuf(ima, ibuf, lock);
- return OPERATOR_CANCELLED;
- }
+ if (ibuf == NULL) {
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ return OPERATOR_CANCELLED;
+ }
- nvm = MEM_callocN(sizeof(NodeViewMove), "NodeViewMove struct");
- op->customdata = nvm;
- nvm->mvalo[0] = event->mval[0];
- nvm->mvalo[1] = event->mval[1];
+ nvm = MEM_callocN(sizeof(NodeViewMove), "NodeViewMove struct");
+ op->customdata = nvm;
+ 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 = -(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;
- BKE_image_release_ibuf(ima, ibuf, lock);
+ BKE_image_release_ibuf(ima, ibuf, lock);
- /* add modal handler */
- WM_event_add_modal_handler(C, op);
+ /* add modal handler */
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static void snode_bg_viewmove_cancel(bContext *UNUSED(C), wmOperator *op)
{
- MEM_freeN(op->customdata);
- op->customdata = NULL;
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
}
void NODE_OT_backimage_move(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Background Image Move";
- ot->description = "Move Node backdrop";
- ot->idname = "NODE_OT_backimage_move";
-
- /* api callbacks */
- ot->invoke = snode_bg_viewmove_invoke;
- ot->modal = snode_bg_viewmove_modal;
- ot->poll = composite_node_active;
- ot->cancel = snode_bg_viewmove_cancel;
-
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
+ /* identifiers */
+ ot->name = "Background Image Move";
+ ot->description = "Move Node backdrop";
+ ot->idname = "NODE_OT_backimage_move";
+
+ /* api callbacks */
+ ot->invoke = snode_bg_viewmove_invoke;
+ ot->modal = snode_bg_viewmove_modal;
+ ot->poll = composite_node_active;
+ ot->cancel = snode_bg_viewmove_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
}
static int backimage_zoom_exec(bContext *C, wmOperator *op)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
- float fac = RNA_float_get(op->ptr, "factor");
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
+ float fac = RNA_float_get(op->ptr, "factor");
- snode->zoom *= fac;
- ED_region_tag_redraw(ar);
- WM_main_add_notifier(NC_NODE | ND_DISPLAY, NULL);
+ snode->zoom *= fac;
+ ED_region_tag_redraw(ar);
+ WM_main_add_notifier(NC_NODE | ND_DISPLAY, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
void NODE_OT_backimage_zoom(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Background Image Zoom";
- ot->idname = "NODE_OT_backimage_zoom";
- ot->description = "Zoom in/out the background image";
+ /* identifiers */
+ ot->name = "Background Image Zoom";
+ ot->idname = "NODE_OT_backimage_zoom";
+ ot->description = "Zoom in/out the background image";
- /* api callbacks */
- ot->exec = backimage_zoom_exec;
- ot->poll = composite_node_active;
+ /* api callbacks */
+ ot->exec = backimage_zoom_exec;
+ ot->poll = composite_node_active;
- /* flags */
- ot->flag = OPTYPE_BLOCKING;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
- /* internal */
- RNA_def_float(ot->srna, "factor", 1.2f, 0.0f, 10.0f, "Factor", "", 0.0f, 10.0f);
+ /* internal */
+ RNA_def_float(ot->srna, "factor", 1.2f, 0.0f, 10.0f, "Factor", "", 0.0f, 10.0f);
}
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);
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
- Image *ima;
- ImBuf *ibuf;
+ Image *ima;
+ ImBuf *ibuf;
- const float pad = 32.0f;
+ const float pad = 32.0f;
- void *lock;
+ void *lock;
- float facx, facy;
+ float facx, facy;
- ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
- ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+ ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
- if ((ibuf == NULL) || (ibuf->x == 0) || (ibuf->y == 0)) {
- BKE_image_release_ibuf(ima, ibuf, lock);
- return OPERATOR_CANCELLED;
- }
+ if ((ibuf == NULL) || (ibuf->x == 0) || (ibuf->y == 0)) {
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ 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 * (ar->sizex - pad) / (ibuf->x * snode->zoom);
+ facy = 1.0f * (ar->sizey - pad) / (ibuf->y * snode->zoom);
- BKE_image_release_ibuf(ima, ibuf, lock);
+ BKE_image_release_ibuf(ima, ibuf, lock);
- snode->zoom *= min_ff(facx, facy);
+ snode->zoom *= min_ff(facx, facy);
- snode->xof = 0;
- snode->yof = 0;
+ snode->xof = 0;
+ snode->yof = 0;
- ED_region_tag_redraw(ar);
- WM_main_add_notifier(NC_NODE | ND_DISPLAY, NULL);
+ ED_region_tag_redraw(ar);
+ WM_main_add_notifier(NC_NODE | ND_DISPLAY, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void NODE_OT_backimage_fit(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Background Image Fit";
- ot->idname = "NODE_OT_backimage_fit";
- ot->description = "Fit the background image to the view";
-
- /* api callbacks */
- ot->exec = backimage_fit_exec;
- ot->poll = composite_node_active;
+ /* identifiers */
+ ot->name = "Background Image Fit";
+ ot->idname = "NODE_OT_backimage_fit";
+ ot->description = "Fit the background image to the view";
- /* flags */
- ot->flag = OPTYPE_BLOCKING;
+ /* api callbacks */
+ ot->exec = backimage_fit_exec;
+ ot->poll = composite_node_active;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
}
/******************** sample backdrop operator ********************/
typedef struct ImageSampleInfo {
- ARegionType *art;
- void *draw_handle;
- int x, y;
- int channels;
+ ARegionType *art;
+ void *draw_handle;
+ int x, y;
+ int channels;
- unsigned char col[4];
- float colf[4];
- float linearcol[4];
+ unsigned char col[4];
+ float colf[4];
+ float linearcol[4];
- int z;
- float zf;
+ int z;
+ float zf;
- int *zp;
- float *zfp;
+ int *zp;
+ float *zfp;
- int draw;
- int color_manage;
+ 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->col, info->colf, info->linearcol,
- info->zp, info->zfp);
- }
+ 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->col,
+ info->colf,
+ info->linearcol,
+ info->zp,
+ info->zfp);
+ }
}
/* Returns color in linear space, matching ED_space_image_color_sample().
* 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])
+bool ED_space_node_color_sample(
+ Main *bmain, SpaceNode *snode, ARegion *ar, int mval[2], float r_col[3])
{
- void *lock;
- Image *ima;
- ImBuf *ibuf;
- float fx, fy, bufx, bufy;
- bool ret = false;
-
- if (!ED_node_is_compositor(snode) || (snode->flag & SNODE_BACKDRAW) == 0) {
- /* use viewer image for color sampling only if we're in compositor tree
- * with backdrop enabled
- */
- return false;
- }
-
- ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
- ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
- if (!ibuf) {
- return false;
- }
-
- /* 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);
-
- if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
- const float *fp;
- unsigned char *cp;
- int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
-
- CLAMP(x, 0, ibuf->x - 1);
- CLAMP(y, 0, ibuf->y - 1);
-
- if (ibuf->rect_float) {
- fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
- /* IB_PROFILE_NONE is default but infact its linear */
- copy_v3_v3(r_col, fp);
- ret = true;
- }
- else if (ibuf->rect) {
- cp = (unsigned char *)(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;
- }
- }
-
- BKE_image_release_ibuf(ima, ibuf, lock);
-
- return ret;
+ void *lock;
+ Image *ima;
+ ImBuf *ibuf;
+ float fx, fy, bufx, bufy;
+ bool ret = false;
+
+ if (!ED_node_is_compositor(snode) || (snode->flag & SNODE_BACKDRAW) == 0) {
+ /* use viewer image for color sampling only if we're in compositor tree
+ * with backdrop enabled
+ */
+ return false;
+ }
+
+ ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+ if (!ibuf) {
+ return false;
+ }
+
+ /* 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);
+
+ if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
+ const float *fp;
+ unsigned char *cp;
+ int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
+
+ CLAMP(x, 0, ibuf->x - 1);
+ CLAMP(y, 0, ibuf->y - 1);
+
+ if (ibuf->rect_float) {
+ fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
+ /* IB_PROFILE_NONE is default but infact its linear */
+ copy_v3_v3(r_col, fp);
+ ret = true;
+ }
+ else if (ibuf->rect) {
+ cp = (unsigned char *)(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;
+ }
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
+
+ return ret;
}
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);
- 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");
- ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
- if (!ibuf) {
- info->draw = 0;
- return;
- }
-
- if (!ibuf->rect) {
- IMB_rect_from_float(ibuf);
- }
-
- /* 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);
-
- if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
- const float *fp;
- unsigned char *cp;
- int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
-
- CLAMP(x, 0, ibuf->x - 1);
- CLAMP(y, 0, ibuf->y - 1);
-
- info->x = x;
- info->y = y;
- info->draw = 1;
- info->channels = ibuf->channels;
-
- info->zp = NULL;
- info->zfp = 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->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;
-
- 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->color_manage = true;
- }
-
- if (ibuf->zbuf) {
- info->z = ibuf->zbuf[y * ibuf->x + x];
- info->zp = &info->z;
- }
- if (ibuf->zbuf_float) {
- info->zf = ibuf->zbuf_float[y * ibuf->x + x];
- info->zfp = &info->zf;
- }
-
- ED_node_sample_set(info->colf);
- }
- else {
- info->draw = 0;
- ED_node_sample_set(NULL);
- }
-
- BKE_image_release_ibuf(ima, ibuf, lock);
-
- ED_area_tag_redraw(CTX_wm_area(C));
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = 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");
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+ if (!ibuf) {
+ info->draw = 0;
+ return;
+ }
+
+ if (!ibuf->rect) {
+ IMB_rect_from_float(ibuf);
+ }
+
+ /* 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);
+
+ if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
+ const float *fp;
+ unsigned char *cp;
+ int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
+
+ CLAMP(x, 0, ibuf->x - 1);
+ CLAMP(y, 0, ibuf->y - 1);
+
+ info->x = x;
+ info->y = y;
+ info->draw = 1;
+ info->channels = ibuf->channels;
+
+ info->zp = NULL;
+ info->zfp = 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->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;
+
+ 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->color_manage = true;
+ }
+
+ if (ibuf->zbuf) {
+ info->z = ibuf->zbuf[y * ibuf->x + x];
+ info->zp = &info->z;
+ }
+ if (ibuf->zbuf_float) {
+ info->zf = ibuf->zbuf_float[y * ibuf->x + x];
+ info->zfp = &info->zf;
+ }
+
+ ED_node_sample_set(info->colf);
+ }
+ else {
+ info->draw = 0;
+ ED_node_sample_set(NULL);
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
}
static void sample_exit(bContext *C, wmOperator *op)
{
- ImageSampleInfo *info = op->customdata;
+ ImageSampleInfo *info = op->customdata;
- ED_node_sample_set(NULL);
- ED_region_draw_cb_exit(info->art, info->draw_handle);
- ED_area_tag_redraw(CTX_wm_area(C));
- MEM_freeN(info);
+ ED_node_sample_set(NULL);
+ 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)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
- ImageSampleInfo *info;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
+ ImageSampleInfo *info;
- if (!ED_node_is_compositor(snode) || !(snode->flag & SNODE_BACKDRAW)) {
- return OPERATOR_CANCELLED;
- }
+ if (!ED_node_is_compositor(snode) || !(snode->flag & SNODE_BACKDRAW)) {
+ 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;
+ 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);
+ sample_apply(C, op, event);
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ 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;
+ 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);
+ sample_exit(C, op);
}
void NODE_OT_backimage_sample(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Backimage Sample";
- ot->idname = "NODE_OT_backimage_sample";
- ot->description = "Use mouse to sample background image";
-
- /* api callbacks */
- ot->invoke = sample_invoke;
- ot->modal = sample_modal;
- ot->cancel = sample_cancel;
- ot->poll = ED_operator_node_active;
-
- /* flags */
- ot->flag = OPTYPE_BLOCKING;
+ /* identifiers */
+ ot->name = "Backimage Sample";
+ ot->idname = "NODE_OT_backimage_sample";
+ ot->description = "Use mouse to sample background image";
+
+ /* api callbacks */
+ ot->invoke = sample_invoke;
+ ot->modal = sample_modal;
+ ot->cancel = sample_cancel;
+ ot->poll = ED_operator_node_active;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
}
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index 22564061aed..52dab2a44a8 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -53,1030 +53,1032 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "node_intern.h" /* own include */
-
+#include "node_intern.h" /* own include */
/* ******************** tree path ********************* */
void ED_node_tree_start(SpaceNode *snode, bNodeTree *ntree, ID *id, ID *from)
{
- bNodeTreePath *path, *path_next;
- for (path = snode->treepath.first; path; path = path_next) {
- path_next = path->next;
- MEM_freeN(path);
- }
- BLI_listbase_clear(&snode->treepath);
+ bNodeTreePath *path, *path_next;
+ for (path = snode->treepath.first; path; path = path_next) {
+ path_next = path->next;
+ MEM_freeN(path);
+ }
+ BLI_listbase_clear(&snode->treepath);
- if (ntree) {
- path = MEM_callocN(sizeof(bNodeTreePath), "node tree path");
- path->nodetree = ntree;
- path->parent_key = NODE_INSTANCE_KEY_BASE;
+ if (ntree) {
+ path = MEM_callocN(sizeof(bNodeTreePath), "node tree path");
+ path->nodetree = ntree;
+ path->parent_key = NODE_INSTANCE_KEY_BASE;
- /* copy initial offset from bNodeTree */
- copy_v2_v2(path->view_center, ntree->view_center);
+ /* copy initial offset from bNodeTree */
+ copy_v2_v2(path->view_center, ntree->view_center);
- if (id) {
- BLI_strncpy(path->node_name, id->name + 2, sizeof(path->node_name));
- }
+ if (id) {
+ BLI_strncpy(path->node_name, id->name + 2, sizeof(path->node_name));
+ }
- BLI_addtail(&snode->treepath, path);
+ BLI_addtail(&snode->treepath, path);
- id_us_ensure_real(&ntree->id);
- }
+ id_us_ensure_real(&ntree->id);
+ }
- /* update current tree */
- snode->nodetree = snode->edittree = ntree;
- snode->id = id;
- snode->from = from;
+ /* update current tree */
+ snode->nodetree = snode->edittree = ntree;
+ snode->id = id;
+ snode->from = from;
- ED_node_set_active_viewer_key(snode);
+ ED_node_set_active_viewer_key(snode);
- WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
}
void ED_node_tree_push(SpaceNode *snode, bNodeTree *ntree, bNode *gnode)
{
- bNodeTreePath *path = MEM_callocN(sizeof(bNodeTreePath), "node tree path");
- bNodeTreePath *prev_path = snode->treepath.last;
- path->nodetree = ntree;
- if (gnode) {
- if (prev_path) {
- path->parent_key = BKE_node_instance_key(prev_path->parent_key, prev_path->nodetree, gnode);
- }
- else {
- path->parent_key = NODE_INSTANCE_KEY_BASE;
- }
+ bNodeTreePath *path = MEM_callocN(sizeof(bNodeTreePath), "node tree path");
+ bNodeTreePath *prev_path = snode->treepath.last;
+ path->nodetree = ntree;
+ if (gnode) {
+ if (prev_path) {
+ path->parent_key = BKE_node_instance_key(prev_path->parent_key, prev_path->nodetree, gnode);
+ }
+ else {
+ path->parent_key = NODE_INSTANCE_KEY_BASE;
+ }
- BLI_strncpy(path->node_name, gnode->name, sizeof(path->node_name));
- }
- else {
- path->parent_key = NODE_INSTANCE_KEY_BASE;
- }
+ BLI_strncpy(path->node_name, gnode->name, sizeof(path->node_name));
+ }
+ else {
+ path->parent_key = NODE_INSTANCE_KEY_BASE;
+ }
- /* copy initial offset from bNodeTree */
- copy_v2_v2(path->view_center, ntree->view_center);
+ /* copy initial offset from bNodeTree */
+ copy_v2_v2(path->view_center, ntree->view_center);
- BLI_addtail(&snode->treepath, path);
+ BLI_addtail(&snode->treepath, path);
- id_us_ensure_real(&ntree->id);
+ id_us_ensure_real(&ntree->id);
- /* update current tree */
- snode->edittree = ntree;
+ /* update current tree */
+ snode->edittree = ntree;
- ED_node_set_active_viewer_key(snode);
+ ED_node_set_active_viewer_key(snode);
- WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
}
void ED_node_tree_pop(SpaceNode *snode)
{
- bNodeTreePath *path = snode->treepath.last;
+ bNodeTreePath *path = snode->treepath.last;
- /* don't remove root */
- if (path == snode->treepath.first) {
- return;
- }
+ /* don't remove root */
+ if (path == snode->treepath.first) {
+ return;
+ }
- BLI_remlink(&snode->treepath, path);
- MEM_freeN(path);
+ BLI_remlink(&snode->treepath, path);
+ MEM_freeN(path);
- /* update current tree */
- path = snode->treepath.last;
- snode->edittree = path->nodetree;
+ /* update current tree */
+ path = snode->treepath.last;
+ snode->edittree = path->nodetree;
- ED_node_set_active_viewer_key(snode);
+ ED_node_set_active_viewer_key(snode);
- /* listener updates the View2D center from edittree */
- WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
+ /* listener updates the View2D center from edittree */
+ WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
}
int ED_node_tree_depth(SpaceNode *snode)
{
- return BLI_listbase_count(&snode->treepath);
+ return BLI_listbase_count(&snode->treepath);
}
bNodeTree *ED_node_tree_get(SpaceNode *snode, int level)
{
- bNodeTreePath *path;
- int i;
- for (path = snode->treepath.last, i = 0; path; path = path->prev, ++i) {
- if (i == level) {
- return path->nodetree;
- }
- }
- return NULL;
+ bNodeTreePath *path;
+ int i;
+ for (path = snode->treepath.last, i = 0; path; path = path->prev, ++i) {
+ if (i == level) {
+ return path->nodetree;
+ }
+ }
+ return NULL;
}
int ED_node_tree_path_length(SpaceNode *snode)
{
- bNodeTreePath *path;
- int length = 0;
- int i;
- for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
- length += strlen(path->node_name);
- if (i > 0) {
- length += 1; /* for separator char */
- }
- }
- return length;
+ bNodeTreePath *path;
+ int length = 0;
+ int i;
+ for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
+ length += strlen(path->node_name);
+ if (i > 0) {
+ length += 1; /* for separator char */
+ }
+ }
+ return length;
}
void ED_node_tree_path_get(SpaceNode *snode, char *value)
{
- bNodeTreePath *path;
- int i;
-
- value[0] = '\0';
- for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
- if (i == 0) {
- strcpy(value, path->node_name);
- value += strlen(path->node_name);
- }
- else {
- sprintf(value, "/%s", path->node_name);
- value += strlen(path->node_name) + 1;
- }
- }
+ bNodeTreePath *path;
+ int i;
+
+ value[0] = '\0';
+ for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
+ if (i == 0) {
+ strcpy(value, path->node_name);
+ value += strlen(path->node_name);
+ }
+ else {
+ sprintf(value, "/%s", path->node_name);
+ value += strlen(path->node_name) + 1;
+ }
+ }
}
void ED_node_tree_path_get_fixedbuf(SpaceNode *snode, char *value, int max_length)
{
- bNodeTreePath *path;
- int size, i;
-
- value[0] = '\0';
- for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
- if (i == 0) {
- size = BLI_strncpy_rlen(value, path->node_name, max_length);
- }
- else {
- size = BLI_snprintf_rlen(value, max_length, "/%s", path->node_name);
- }
- max_length -= size;
- if (max_length <= 0) {
- break;
- }
- value += size;
- }
+ bNodeTreePath *path;
+ int size, i;
+
+ value[0] = '\0';
+ for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
+ if (i == 0) {
+ size = BLI_strncpy_rlen(value, path->node_name, max_length);
+ }
+ else {
+ size = BLI_snprintf_rlen(value, max_length, "/%s", path->node_name);
+ }
+ max_length -= size;
+ if (max_length <= 0) {
+ break;
+ }
+ value += size;
+ }
}
void ED_node_set_active_viewer_key(SpaceNode *snode)
{
- bNodeTreePath *path = snode->treepath.last;
- if (snode->nodetree && path) {
- snode->nodetree->active_viewer_key = path->parent_key;
- }
+ bNodeTreePath *path = snode->treepath.last;
+ if (snode->nodetree && path) {
+ snode->nodetree->active_viewer_key = path->parent_key;
+ }
}
void snode_group_offset(SpaceNode *snode, float *x, float *y)
{
- bNodeTreePath *path = snode->treepath.last;
-
- if (path && path->prev) {
- float dcenter[2];
- sub_v2_v2v2(dcenter, path->view_center, path->prev->view_center);
- *x = dcenter[0];
- *y = dcenter[1];
- }
- else {
- *x = *y = 0.0f;
- }
+ bNodeTreePath *path = snode->treepath.last;
+
+ if (path && path->prev) {
+ float dcenter[2];
+ sub_v2_v2v2(dcenter, path->view_center, path->prev->view_center);
+ *x = dcenter[0];
+ *y = dcenter[1];
+ }
+ else {
+ *x = *y = 0.0f;
+ }
}
/* ******************** manage regions ********************* */
ARegion *node_has_buttons_region(ScrArea *sa)
{
- ARegion *ar, *arnew;
+ ARegion *ar, *arnew;
- ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
- if (ar) {
- return ar;
- }
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
+ if (ar) {
+ return ar;
+ }
- /* add subdiv level; after header */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+ /* add subdiv level; after header */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
- /* is error! */
- if (ar == NULL) {
- return NULL;
- }
+ /* is error! */
+ if (ar == NULL) {
+ return NULL;
+ }
- arnew = MEM_callocN(sizeof(ARegion), "buttons for node");
+ arnew = MEM_callocN(sizeof(ARegion), "buttons for node");
- BLI_insertlinkafter(&sa->regionbase, ar, arnew);
- arnew->regiontype = RGN_TYPE_UI;
- arnew->alignment = RGN_ALIGN_RIGHT;
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype = RGN_TYPE_UI;
+ arnew->alignment = RGN_ALIGN_RIGHT;
- arnew->flag = RGN_FLAG_HIDDEN;
+ arnew->flag = RGN_FLAG_HIDDEN;
- return arnew;
+ return arnew;
}
ARegion *node_has_tools_region(ScrArea *sa)
{
- ARegion *ar, *arnew;
+ ARegion *ar, *arnew;
- ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
- if (ar) {
- return ar;
- }
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
+ if (ar) {
+ return ar;
+ }
- /* add subdiv level; after header */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+ /* add subdiv level; after header */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
- /* is error! */
- if (ar == NULL) {
- return NULL;
- }
+ /* is error! */
+ if (ar == NULL) {
+ return NULL;
+ }
- arnew = MEM_callocN(sizeof(ARegion), "node tools");
+ arnew = MEM_callocN(sizeof(ARegion), "node tools");
- BLI_insertlinkafter(&sa->regionbase, ar, arnew);
- arnew->regiontype = RGN_TYPE_TOOLS;
- arnew->alignment = RGN_ALIGN_LEFT;
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype = RGN_TYPE_TOOLS;
+ arnew->alignment = RGN_ALIGN_LEFT;
- arnew->flag = RGN_FLAG_HIDDEN;
+ arnew->flag = RGN_FLAG_HIDDEN;
- return arnew;
+ return arnew;
}
/* ******************** default callbacks for node space ***************** */
static SpaceLink *node_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
- SpaceNode *snode;
+ ARegion *ar;
+ SpaceNode *snode;
- snode = MEM_callocN(sizeof(SpaceNode), "initnode");
- snode->spacetype = SPACE_NODE;
+ snode = MEM_callocN(sizeof(SpaceNode), "initnode");
+ snode->spacetype = SPACE_NODE;
- snode->flag = SNODE_SHOW_GPENCIL | SNODE_USE_ALPHA;
+ snode->flag = SNODE_SHOW_GPENCIL | SNODE_USE_ALPHA;
- /* backdrop */
- snode->zoom = 1.0f;
+ /* backdrop */
+ snode->zoom = 1.0f;
- /* select the first tree type for valid type */
- NODE_TREE_TYPES_BEGIN (treetype)
- {
- strcpy(snode->tree_idname, treetype->idname);
- break;
- }
- NODE_TREE_TYPES_END;
+ /* select the first tree type for valid type */
+ NODE_TREE_TYPES_BEGIN (treetype) {
+ strcpy(snode->tree_idname, treetype->idname);
+ break;
+ }
+ NODE_TREE_TYPES_END;
- /* header */
- ar = MEM_callocN(sizeof(ARegion), "header for node");
+ /* header */
+ ar = 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, 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 node");
+ /* buttons/list view */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_UI;
+ ar->alignment = RGN_ALIGN_RIGHT;
- /* toolbar */
- ar = MEM_callocN(sizeof(ARegion), "node tools");
+ /* toolbar */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_TOOLS;
+ ar->alignment = RGN_ALIGN_LEFT;
- ar->flag = RGN_FLAG_HIDDEN;
+ ar->flag = RGN_FLAG_HIDDEN;
- /* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for node");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for node");
- BLI_addtail(&snode->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&snode->regionbase, ar);
+ ar->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;
+ 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;
- ar->v2d.cur = ar->v2d.tot;
+ ar->v2d.cur = ar->v2d.tot;
- ar->v2d.min[0] = 1.0f;
- ar->v2d.min[1] = 1.0f;
+ ar->v2d.min[0] = 1.0f;
+ ar->v2d.min[1] = 1.0f;
- ar->v2d.max[0] = 32000.0f;
- ar->v2d.max[1] = 32000.0f;
+ ar->v2d.max[0] = 32000.0f;
+ ar->v2d.max[1] = 32000.0f;
- ar->v2d.minzoom = 0.09f;
- ar->v2d.maxzoom = 2.31f;
+ ar->v2d.minzoom = 0.09f;
+ ar->v2d.maxzoom = 2.31f;
- ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
- ar->v2d.keepzoom = V2D_LIMITZOOM | V2D_KEEPASPECT;
- ar->v2d.keeptot = 0;
+ ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
+ ar->v2d.keepzoom = V2D_LIMITZOOM | V2D_KEEPASPECT;
+ ar->v2d.keeptot = 0;
- return (SpaceLink *)snode;
+ return (SpaceLink *)snode;
}
static void node_free(SpaceLink *sl)
{
- SpaceNode *snode = (SpaceNode *)sl;
- bNodeTreePath *path, *path_next;
+ SpaceNode *snode = (SpaceNode *)sl;
+ bNodeTreePath *path, *path_next;
- for (path = snode->treepath.first; path; path = path_next) {
- path_next = path->next;
- MEM_freeN(path);
- }
+ for (path = snode->treepath.first; path; path = path_next) {
+ path_next = path->next;
+ MEM_freeN(path);
+ }
}
-
/* spacetype; init callback */
static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
{
-
}
-static void node_area_listener(wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene))
+static void node_area_listener(wmWindow *UNUSED(win),
+ ScrArea *sa,
+ wmNotifier *wmn,
+ Scene *UNUSED(scene))
{
- /* note, ED_area_tag_refresh will re-execute compositor */
- SpaceNode *snode = sa->spacedata.first;
- /* shaderfrom is only used for new shading nodes, otherwise all shaders are from objects */
- short shader_type = snode->shaderfrom;
-
- /* preview renders */
- switch (wmn->category) {
- case NC_SCENE:
- switch (wmn->data) {
- case ND_NODES:
- {
- ARegion *ar = BKE_area_find_region_type(sa, 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]);
- }
-
- ED_area_tag_refresh(sa);
- break;
- }
- case ND_FRAME:
- ED_area_tag_refresh(sa);
- break;
- case ND_COMPO_RESULT:
- ED_area_tag_redraw(sa);
- 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);
- }
- }
- break;
- case ND_LAYER_CONTENT:
- ED_area_tag_refresh(sa);
- break;
- }
- break;
-
- /* future: add ID checks? */
- case NC_MATERIAL:
- if (ED_node_is_shader(snode)) {
- if (wmn->data == ND_SHADING) {
- ED_area_tag_refresh(sa);
- }
- else if (wmn->data == ND_SHADING_DRAW) {
- ED_area_tag_refresh(sa);
- }
- else if (wmn->data == ND_SHADING_LINKS) {
- ED_area_tag_refresh(sa);
- }
- else if (wmn->action == NA_ADDED && snode->edittree) {
- nodeSetActiveID(snode->edittree, ID_MA, wmn->reference);
- }
-
- }
- break;
- case NC_TEXTURE:
- if (ED_node_is_shader(snode) || ED_node_is_texture(snode)) {
- if (wmn->data == ND_NODES) {
- ED_area_tag_refresh(sa);
- }
- }
- break;
- case NC_WORLD:
- if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_WORLD) {
- ED_area_tag_refresh(sa);
- }
- break;
- case NC_OBJECT:
- if (ED_node_is_shader(snode)) {
- if (wmn->data == ND_OB_SHADING) {
- ED_area_tag_refresh(sa);
- }
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_NODE) {
- ED_area_tag_refresh(sa);
- }
- else if (wmn->data == ND_SPACE_NODE_VIEW) {
- ED_area_tag_redraw(sa);
- }
- break;
- case NC_NODE:
- if (wmn->action == NA_EDITED) {
- ED_area_tag_refresh(sa);
- }
- else if (wmn->action == NA_SELECTED) {
- ED_area_tag_redraw(sa);
- }
- break;
- case NC_SCREEN:
- switch (wmn->data) {
- case ND_ANIMPLAY:
- ED_area_tag_refresh(sa);
- break;
- }
- break;
- case NC_MASK:
- if (wmn->action == NA_EDITED) {
- if (snode->nodetree && snode->nodetree->type == NTREE_COMPOSIT) {
- ED_area_tag_refresh(sa);
- }
- }
- break;
-
- case NC_IMAGE:
- if (wmn->action == NA_EDITED) {
- if (ED_node_is_compositor(snode)) {
- /* note that nodeUpdateID is already called by BKE_image_signal() on all
- * 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);
- }
- }
- }
- break;
-
- case NC_MOVIECLIP:
- if (wmn->action == NA_EDITED) {
- if (ED_node_is_compositor(snode)) {
- if (nodeUpdateID(snode->nodetree, wmn->reference)) {
- ED_area_tag_refresh(sa);
- }
- }
- }
- break;
-
- case NC_LINESTYLE:
- if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_LINESTYLE) {
- ED_area_tag_refresh(sa);
- }
- break;
- case NC_WM:
- if (wmn->data == ND_UNDO) {
- ED_area_tag_refresh(sa);
- }
- break;
- case NC_GPENCIL:
- if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_area_tag_redraw(sa);
- }
- break;
- }
+ /* note, ED_area_tag_refresh will re-execute compositor */
+ SpaceNode *snode = sa->spacedata.first;
+ /* shaderfrom is only used for new shading nodes, otherwise all shaders are from objects */
+ short shader_type = snode->shaderfrom;
+
+ /* preview renders */
+ switch (wmn->category) {
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_NODES: {
+ ARegion *ar = BKE_area_find_region_type(sa, 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]);
+ }
+
+ ED_area_tag_refresh(sa);
+ break;
+ }
+ case ND_FRAME:
+ ED_area_tag_refresh(sa);
+ break;
+ case ND_COMPO_RESULT:
+ ED_area_tag_redraw(sa);
+ 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);
+ }
+ }
+ break;
+ case ND_LAYER_CONTENT:
+ ED_area_tag_refresh(sa);
+ break;
+ }
+ break;
+
+ /* future: add ID checks? */
+ case NC_MATERIAL:
+ if (ED_node_is_shader(snode)) {
+ if (wmn->data == ND_SHADING) {
+ ED_area_tag_refresh(sa);
+ }
+ else if (wmn->data == ND_SHADING_DRAW) {
+ ED_area_tag_refresh(sa);
+ }
+ else if (wmn->data == ND_SHADING_LINKS) {
+ ED_area_tag_refresh(sa);
+ }
+ else if (wmn->action == NA_ADDED && snode->edittree) {
+ nodeSetActiveID(snode->edittree, ID_MA, wmn->reference);
+ }
+ }
+ break;
+ case NC_TEXTURE:
+ if (ED_node_is_shader(snode) || ED_node_is_texture(snode)) {
+ if (wmn->data == ND_NODES) {
+ ED_area_tag_refresh(sa);
+ }
+ }
+ break;
+ case NC_WORLD:
+ if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_WORLD) {
+ ED_area_tag_refresh(sa);
+ }
+ break;
+ case NC_OBJECT:
+ if (ED_node_is_shader(snode)) {
+ if (wmn->data == ND_OB_SHADING) {
+ ED_area_tag_refresh(sa);
+ }
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_NODE) {
+ ED_area_tag_refresh(sa);
+ }
+ else if (wmn->data == ND_SPACE_NODE_VIEW) {
+ ED_area_tag_redraw(sa);
+ }
+ break;
+ case NC_NODE:
+ if (wmn->action == NA_EDITED) {
+ ED_area_tag_refresh(sa);
+ }
+ else if (wmn->action == NA_SELECTED) {
+ ED_area_tag_redraw(sa);
+ }
+ break;
+ case NC_SCREEN:
+ switch (wmn->data) {
+ case ND_ANIMPLAY:
+ ED_area_tag_refresh(sa);
+ break;
+ }
+ break;
+ case NC_MASK:
+ if (wmn->action == NA_EDITED) {
+ if (snode->nodetree && snode->nodetree->type == NTREE_COMPOSIT) {
+ ED_area_tag_refresh(sa);
+ }
+ }
+ break;
+
+ case NC_IMAGE:
+ if (wmn->action == NA_EDITED) {
+ if (ED_node_is_compositor(snode)) {
+ /* note that nodeUpdateID is already called by BKE_image_signal() on all
+ * 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);
+ }
+ }
+ }
+ break;
+
+ case NC_MOVIECLIP:
+ if (wmn->action == NA_EDITED) {
+ if (ED_node_is_compositor(snode)) {
+ if (nodeUpdateID(snode->nodetree, wmn->reference)) {
+ ED_area_tag_refresh(sa);
+ }
+ }
+ }
+ break;
+
+ case NC_LINESTYLE:
+ if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_LINESTYLE) {
+ ED_area_tag_refresh(sa);
+ }
+ break;
+ case NC_WM:
+ if (wmn->data == ND_UNDO) {
+ ED_area_tag_refresh(sa);
+ }
+ break;
+ case NC_GPENCIL:
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
+ ED_area_tag_redraw(sa);
+ }
+ break;
+ }
}
static void node_area_refresh(const struct bContext *C, ScrArea *sa)
{
- /* default now: refresh node is starting preview */
- SpaceNode *snode = sa->spacedata.first;
-
- snode_set_context(C);
-
- if (snode->nodetree) {
- if (snode->nodetree->type == NTREE_SHADER) {
- 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);
- }
- }
- 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);
- }
- }
- 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);
- }
- }
- }
- else if (snode->nodetree->type == NTREE_COMPOSIT) {
- Scene *scene = (Scene *)snode->id;
- if (scene->use_nodes) {
- /* recalc is set on 3d view changes for auto compo */
- if (snode->recalc) {
- snode->recalc = 0;
- node_render_changed_exec((struct bContext *)C, NULL);
- }
- else {
- ED_node_composite_job(C, snode->nodetree, scene);
- }
- }
- }
- 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);
- }
- }
- }
+ /* default now: refresh node is starting preview */
+ SpaceNode *snode = sa->spacedata.first;
+
+ snode_set_context(C);
+
+ if (snode->nodetree) {
+ if (snode->nodetree->type == NTREE_SHADER) {
+ 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);
+ }
+ }
+ 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);
+ }
+ }
+ 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);
+ }
+ }
+ }
+ else if (snode->nodetree->type == NTREE_COMPOSIT) {
+ Scene *scene = (Scene *)snode->id;
+ if (scene->use_nodes) {
+ /* recalc is set on 3d view changes for auto compo */
+ if (snode->recalc) {
+ snode->recalc = 0;
+ node_render_changed_exec((struct bContext *)C, NULL);
+ }
+ else {
+ ED_node_composite_job(C, snode->nodetree, scene);
+ }
+ }
+ }
+ 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);
+ }
+ }
+ }
}
static SpaceLink *node_duplicate(SpaceLink *sl)
{
- SpaceNode *snode = (SpaceNode *)sl;
- SpaceNode *snoden = MEM_dupallocN(snode);
+ SpaceNode *snode = (SpaceNode *)sl;
+ SpaceNode *snoden = MEM_dupallocN(snode);
- BLI_duplicatelist(&snoden->treepath, &snode->treepath);
+ BLI_duplicatelist(&snoden->treepath, &snode->treepath);
- /* clear or remove stuff from old */
- BLI_listbase_clear(&snoden->linkdrag);
+ /* clear or remove stuff from old */
+ BLI_listbase_clear(&snoden->linkdrag);
- /* Note: no need to set node tree user counts,
- * the editor only keeps at least 1 (id_us_ensure_real),
- * which is already done by the original SpaceNode.
- */
+ /* Note: no need to set node tree user counts,
+ * the editor only keeps at least 1 (id_us_ensure_real),
+ * which is already done by the original SpaceNode.
+ */
- return (SpaceLink *)snoden;
+ return (SpaceLink *)snoden;
}
-
/* add handlers, stuff you only do once or on area/region changes */
static void node_buttons_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, ar);
- keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
}
static void node_buttons_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, ar);
}
/* add handlers, stuff you only do once or on area/region changes */
static void node_toolbar_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, ar);
- keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
}
static void node_toolbar_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, ar);
}
static void node_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
{
- SpaceNode *snode = sa->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,
- &snode->cursor[0], &snode->cursor[1]);
+ SpaceNode *snode = sa->spacedata.first;
- /* here snode->cursor is used to detect the node edge for sizing */
- node_set_cursor(win, snode, snode->cursor);
+ /* 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,
+ &snode->cursor[0],
+ &snode->cursor[1]);
- /* XXX snode->cursor is in placing new nodes space */
- snode->cursor[0] /= UI_DPI_FAC;
- snode->cursor[1] /= UI_DPI_FAC;
+ /* here snode->cursor is used to detect the node edge for sizing */
+ node_set_cursor(win, snode, snode->cursor);
+ /* XXX snode->cursor is in placing new nodes space */
+ snode->cursor[0] /= UI_DPI_FAC;
+ snode->cursor[1] /= UI_DPI_FAC;
}
/* Initialize main region, setting handlers. */
static void node_main_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
- ListBase *lb;
+ wmKeyMap *keymap;
+ ListBase *lb;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
- /* own keymaps */
- keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ /* own keymaps */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
- keymap = WM_keymap_ensure(wm->defaultconf, "Node Editor", SPACE_NODE, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Node Editor", SPACE_NODE, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- /* add drop boxes */
- lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW);
+ /* 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(&ar->handlers, lb);
}
static void node_main_region_draw(const bContext *C, ARegion *ar)
{
- drawnodespace(C, ar);
+ drawnodespace(C, ar);
}
-
/* ************* dropboxes ************* */
-static bool node_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
+static bool node_ima_drop_poll(bContext *UNUSED(C),
+ wmDrag *drag,
+ const wmEvent *UNUSED(event),
+ const char **UNUSED(tooltip))
{
- if (drag->type == WM_DRAG_PATH) {
- /* rule might not work? */
- return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE));
- }
- else {
- return WM_drag_ID(drag, ID_IM) != NULL;
- }
+ if (drag->type == WM_DRAG_PATH) {
+ /* rule might not work? */
+ return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE));
+ }
+ else {
+ return WM_drag_ID(drag, ID_IM) != NULL;
+ }
}
-static bool node_mask_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
+static bool node_mask_drop_poll(bContext *UNUSED(C),
+ wmDrag *drag,
+ const wmEvent *UNUSED(event),
+ const char **UNUSED(tooltip))
{
- return WM_drag_ID(drag, ID_MSK) != NULL;
+ return WM_drag_ID(drag, ID_MSK) != NULL;
}
static void node_id_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = WM_drag_ID(drag, 0);
+ ID *id = WM_drag_ID(drag, 0);
- RNA_string_set(drop->ptr, "name", id->name + 2);
+ RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = WM_drag_ID(drag, 0);
-
- if (id) {
- RNA_string_set(drop->ptr, "name", id->name + 2);
- RNA_struct_property_unset(drop->ptr, "filepath");
- }
- else if (drag->path[0]) {
- RNA_string_set(drop->ptr, "filepath", drag->path);
- RNA_struct_property_unset(drop->ptr, "name");
- }
+ ID *id = WM_drag_ID(drag, 0);
+
+ if (id) {
+ RNA_string_set(drop->ptr, "name", id->name + 2);
+ RNA_struct_property_unset(drop->ptr, "filepath");
+ }
+ else if (drag->path[0]) {
+ RNA_string_set(drop->ptr, "filepath", drag->path);
+ RNA_struct_property_unset(drop->ptr, "name");
+ }
}
/* this region dropbox definition */
static void node_dropboxes(void)
{
- ListBase *lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW);
-
- WM_dropbox_add(lb, "NODE_OT_add_file", node_ima_drop_poll, node_id_path_drop_copy);
- WM_dropbox_add(lb, "NODE_OT_add_mask", node_mask_drop_poll, node_id_drop_copy);
+ ListBase *lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW);
+ WM_dropbox_add(lb, "NODE_OT_add_file", node_ima_drop_poll, node_id_path_drop_copy);
+ WM_dropbox_add(lb, "NODE_OT_add_mask", node_mask_drop_poll, node_id_drop_copy);
}
/* ************* 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)
{
- ED_region_header_init(ar);
+ ED_region_header_init(ar);
}
static void node_header_region_draw(const bContext *C, ARegion *ar)
{
- /* find and set the context */
- snode_set_context(C);
+ /* find and set the context */
+ snode_set_context(C);
- ED_region_header(C, ar);
+ ED_region_header(C, ar);
}
/* used for header + main region */
-static void node_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void node_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- wmGizmoMap *gzmap = ar->gizmo_map;
-
- /* context changes */
- switch (wmn->category) {
- case NC_SPACE:
- switch (wmn->data) {
- case ND_SPACE_NODE:
- ED_region_tag_redraw(ar);
- break;
- case ND_SPACE_NODE_VIEW:
- WM_gizmomap_tag_refresh(gzmap);
- break;
- }
- break;
- case NC_SCREEN:
- if (wmn->data == ND_LAYOUTSET || wmn->action == NA_EDITED) {
- WM_gizmomap_tag_refresh(gzmap);
- }
- switch (wmn->data) {
- case ND_ANIMPLAY:
- case ND_LAYER:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_WM:
- if (wmn->data == ND_JOB) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SCENE:
- ED_region_tag_redraw(ar);
- if (wmn->data == ND_RENDER_RESULT) {
- WM_gizmomap_tag_refresh(gzmap);
- }
- break;
- case NC_NODE:
- ED_region_tag_redraw(ar);
- if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- WM_gizmomap_tag_refresh(gzmap);
- }
- break;
- case NC_MATERIAL:
- case NC_TEXTURE:
- case NC_WORLD:
- case NC_LINESTYLE:
- ED_region_tag_redraw(ar);
- break;
- case NC_OBJECT:
- if (wmn->data == ND_OB_SHADING) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_ID:
- if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_GPENCIL:
- if (wmn->action == NA_EDITED) {
- ED_region_tag_redraw(ar);
- }
- else if (wmn->data & ND_GPENCIL_EDITMODE) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
+ wmGizmoMap *gzmap = ar->gizmo_map;
+
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SPACE:
+ switch (wmn->data) {
+ case ND_SPACE_NODE:
+ ED_region_tag_redraw(ar);
+ break;
+ case ND_SPACE_NODE_VIEW:
+ WM_gizmomap_tag_refresh(gzmap);
+ break;
+ }
+ break;
+ case NC_SCREEN:
+ if (wmn->data == ND_LAYOUTSET || wmn->action == NA_EDITED) {
+ WM_gizmomap_tag_refresh(gzmap);
+ }
+ switch (wmn->data) {
+ case ND_ANIMPLAY:
+ case ND_LAYER:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_WM:
+ if (wmn->data == ND_JOB) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SCENE:
+ ED_region_tag_redraw(ar);
+ if (wmn->data == ND_RENDER_RESULT) {
+ WM_gizmomap_tag_refresh(gzmap);
+ }
+ break;
+ case NC_NODE:
+ ED_region_tag_redraw(ar);
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
+ WM_gizmomap_tag_refresh(gzmap);
+ }
+ break;
+ case NC_MATERIAL:
+ case NC_TEXTURE:
+ case NC_WORLD:
+ case NC_LINESTYLE:
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_OBJECT:
+ if (wmn->data == ND_OB_SHADING) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_ID:
+ if (wmn->action == NA_RENAME) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_GPENCIL:
+ if (wmn->action == NA_EDITED) {
+ ED_region_tag_redraw(ar);
+ }
+ else if (wmn->data & ND_GPENCIL_EDITMODE) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
}
const char *node_context_dir[] = {
- "selected_nodes", "active_node", "light", "material", "world", NULL
-};
+ "selected_nodes", "active_node", "light", "material", "world", NULL};
static int node_context(const bContext *C, const char *member, bContextDataResult *result)
{
- SpaceNode *snode = CTX_wm_space_node(C);
-
- if (CTX_data_dir(member)) {
- CTX_data_dir_set(result, node_context_dir);
- return 1;
- }
- else if (CTX_data_equals(member, "selected_nodes")) {
- bNode *node;
-
- if (snode->edittree) {
- for (node = snode->edittree->nodes.last; node; node = node->prev) {
- if (node->flag & NODE_SELECT) {
- CTX_data_list_add(result, &snode->edittree->id, &RNA_Node, node);
- }
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "active_node")) {
- if (snode->edittree) {
- bNode *node = nodeGetActive(snode->edittree);
- CTX_data_pointer_set(result, &snode->edittree->id, &RNA_Node, node);
- }
-
- CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
- return 1;
- }
- else if (CTX_data_equals(member, "node_previews")) {
- if (snode->nodetree) {
- CTX_data_pointer_set(result, &snode->nodetree->id, &RNA_NodeInstanceHash, snode->nodetree->previews);
- }
-
- CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
- return 1;
- }
- else if (CTX_data_equals(member, "material")) {
- if (snode->id && GS(snode->id->name) == ID_MA) {
- CTX_data_id_pointer_set(result, snode->id);
- }
- return 1;
- }
- else if (CTX_data_equals(member, "light")) {
- if (snode->id && GS(snode->id->name) == ID_LA) {
- CTX_data_id_pointer_set(result, snode->id);
- }
- return 1;
- }
- else if (CTX_data_equals(member, "world")) {
- if (snode->id && GS(snode->id->name) == ID_WO) {
- CTX_data_id_pointer_set(result, snode->id);
- }
- return 1;
- }
-
- return 0;
+ SpaceNode *snode = CTX_wm_space_node(C);
+
+ if (CTX_data_dir(member)) {
+ CTX_data_dir_set(result, node_context_dir);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "selected_nodes")) {
+ bNode *node;
+
+ if (snode->edittree) {
+ for (node = snode->edittree->nodes.last; node; node = node->prev) {
+ if (node->flag & NODE_SELECT) {
+ CTX_data_list_add(result, &snode->edittree->id, &RNA_Node, node);
+ }
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "active_node")) {
+ if (snode->edittree) {
+ bNode *node = nodeGetActive(snode->edittree);
+ CTX_data_pointer_set(result, &snode->edittree->id, &RNA_Node, node);
+ }
+
+ CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "node_previews")) {
+ if (snode->nodetree) {
+ CTX_data_pointer_set(
+ result, &snode->nodetree->id, &RNA_NodeInstanceHash, snode->nodetree->previews);
+ }
+
+ CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "material")) {
+ if (snode->id && GS(snode->id->name) == ID_MA) {
+ CTX_data_id_pointer_set(result, snode->id);
+ }
+ return 1;
+ }
+ else if (CTX_data_equals(member, "light")) {
+ if (snode->id && GS(snode->id->name) == ID_LA) {
+ CTX_data_id_pointer_set(result, snode->id);
+ }
+ return 1;
+ }
+ else if (CTX_data_equals(member, "world")) {
+ if (snode->id && GS(snode->id->name) == ID_WO) {
+ CTX_data_id_pointer_set(result, snode->id);
+ }
+ return 1;
+ }
+
+ return 0;
}
static void node_widgets(void)
{
- /* create the widgetmap for the area here */
- wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(
- &(const struct wmGizmoMapType_Params){SPACE_NODE, RGN_TYPE_WINDOW});
- WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_transform);
- WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_crop);
- WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_sun_beams);
- WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_corner_pin);
+ /* create the widgetmap for the area here */
+ wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(
+ &(const struct wmGizmoMapType_Params){SPACE_NODE, RGN_TYPE_WINDOW});
+ WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_transform);
+ WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_crop);
+ WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_sun_beams);
+ 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)
{
- 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;
- }
- }
- else if (GS(old_id->name) == ID_OB) {
- if (snode->from == old_id) {
- if (new_id == NULL) {
- snode->flag &= ~SNODE_PIN;
- }
- snode->from = new_id;
- }
- }
- else if (GS(old_id->name) == ID_GD) {
- if ((ID *)snode->gpd == old_id) {
- snode->gpd = (bGPdata *)new_id;
- id_us_min(old_id);
- id_us_plus(new_id);
- }
- }
- else if (GS(old_id->name) == ID_NT) {
- bNodeTreePath *path, *path_next;
-
- 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);
- }
- if (path == snode->treepath.first) {
- /* first nodetree in path is same as snode->nodetree */
- snode->nodetree = path->nodetree;
- }
- if (path->nodetree == NULL) {
- break;
- }
- }
-
- /* remaining path entries are invalid, remove */
- for (; path; path = path_next) {
- path_next = path->next;
-
- BLI_remlink(&snode->treepath, path);
- MEM_freeN(path);
- }
-
- /* edittree is just the last in the path,
- * set this directly since the path may have been shortened above */
- if (snode->treepath.last) {
- path = snode->treepath.last;
- snode->edittree = path->nodetree;
- }
- else {
- snode->edittree = NULL;
- }
- }
+ 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;
+ }
+ }
+ else if (GS(old_id->name) == ID_OB) {
+ if (snode->from == old_id) {
+ if (new_id == NULL) {
+ snode->flag &= ~SNODE_PIN;
+ }
+ snode->from = new_id;
+ }
+ }
+ else if (GS(old_id->name) == ID_GD) {
+ if ((ID *)snode->gpd == old_id) {
+ snode->gpd = (bGPdata *)new_id;
+ id_us_min(old_id);
+ id_us_plus(new_id);
+ }
+ }
+ else if (GS(old_id->name) == ID_NT) {
+ bNodeTreePath *path, *path_next;
+
+ 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);
+ }
+ if (path == snode->treepath.first) {
+ /* first nodetree in path is same as snode->nodetree */
+ snode->nodetree = path->nodetree;
+ }
+ if (path->nodetree == NULL) {
+ break;
+ }
+ }
+
+ /* remaining path entries are invalid, remove */
+ for (; path; path = path_next) {
+ path_next = path->next;
+
+ BLI_remlink(&snode->treepath, path);
+ MEM_freeN(path);
+ }
+
+ /* edittree is just the last in the path,
+ * set this directly since the path may have been shortened above */
+ if (snode->treepath.last) {
+ path = snode->treepath.last;
+ snode->edittree = path->nodetree;
+ }
+ else {
+ snode->edittree = NULL;
+ }
+ }
}
-
static int node_space_subtype_get(ScrArea *sa)
{
- SpaceNode *snode = sa->spacedata.first;
- return rna_node_tree_idname_to_enum(snode->tree_idname);
+ SpaceNode *snode = sa->spacedata.first;
+ return rna_node_tree_idname_to_enum(snode->tree_idname);
}
static void node_space_subtype_set(ScrArea *sa, int value)
{
- SpaceNode *snode = sa->spacedata.first;
- ED_node_set_tree_type(snode, rna_node_tree_type_from_enum(value));
+ SpaceNode *snode = sa->spacedata.first;
+ ED_node_set_tree_type(snode, rna_node_tree_type_from_enum(value));
}
-static void node_space_subtype_item_extend(
- bContext *C, EnumPropertyItem **item, int *totitem)
+static void node_space_subtype_item_extend(bContext *C, EnumPropertyItem **item, int *totitem)
{
- 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++) {
- RNA_enum_item_add(item, totitem, item_iter);
- }
- if (free) {
- MEM_freeN((void *)item_src);
- }
+ 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++) {
+ RNA_enum_item_add(item, totitem, item_iter);
+ }
+ if (free) {
+ MEM_freeN((void *)item_src);
+ }
}
/* only called once, from space/spacetypes.c */
void ED_spacetype_node(void)
{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype node");
- ARegionType *art;
-
- st->spaceid = SPACE_NODE;
- strncpy(st->name, "Node", BKE_ST_MAXNAME);
-
- st->new = node_new;
- st->free = node_free;
- st->init = node_init;
- st->duplicate = node_duplicate;
- st->operatortypes = node_operatortypes;
- st->keymap = node_keymap;
- st->listener = node_area_listener;
- st->refresh = node_area_refresh;
- st->context = node_context;
- st->dropboxes = node_dropboxes;
- st->gizmos = node_widgets;
- st->id_remap = node_id_remap;
- st->space_subtype_item_extend = node_space_subtype_item_extend;
- st->space_subtype_get = node_space_subtype_get;
- st->space_subtype_set = node_space_subtype_set;
-
- /* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
- art->regionid = RGN_TYPE_WINDOW;
- art->init = node_main_region_init;
- art->draw = node_main_region_draw;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_GIZMO | ED_KEYMAP_TOOL | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL;
- art->listener = node_region_listener;
- art->cursor = node_cursor;
- art->event_cursor = true;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
- art->listener = node_region_listener;
- art->init = node_header_region_init;
- art->draw = node_header_region_draw;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: listview/buttons */
- art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
- art->regionid = RGN_TYPE_UI;
- art->prefsizex = 180; // XXX
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
- art->listener = node_region_listener;
- art->init = node_buttons_region_init;
- art->draw = node_buttons_region_draw;
- BLI_addhead(&st->regiontypes, art);
-
- node_buttons_register(art);
-
- /* regions: toolbar */
- art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region");
- art->regionid = RGN_TYPE_TOOLS;
- art->prefsizex = 58; /* XXX */
- art->prefsizey = 50; /* XXX */
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
- art->listener = node_region_listener;
- art->message_subscribe = ED_region_generic_tools_region_message_subscribe;
- art->snap_size = ED_region_generic_tools_region_snap_size;
- art->init = node_toolbar_region_init;
- art->draw = node_toolbar_region_draw;
- BLI_addhead(&st->regiontypes, art);
-
- node_toolbar_register(art);
-
- BKE_spacetype_register(st);
+ SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype node");
+ ARegionType *art;
+
+ st->spaceid = SPACE_NODE;
+ strncpy(st->name, "Node", BKE_ST_MAXNAME);
+
+ st->new = node_new;
+ st->free = node_free;
+ st->init = node_init;
+ st->duplicate = node_duplicate;
+ st->operatortypes = node_operatortypes;
+ st->keymap = node_keymap;
+ st->listener = node_area_listener;
+ st->refresh = node_area_refresh;
+ st->context = node_context;
+ st->dropboxes = node_dropboxes;
+ st->gizmos = node_widgets;
+ st->id_remap = node_id_remap;
+ st->space_subtype_item_extend = node_space_subtype_item_extend;
+ st->space_subtype_get = node_space_subtype_get;
+ st->space_subtype_set = node_space_subtype_set;
+
+ /* regions: main window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init = node_main_region_init;
+ art->draw = node_main_region_draw;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_GIZMO | ED_KEYMAP_TOOL | ED_KEYMAP_VIEW2D |
+ ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL;
+ art->listener = node_region_listener;
+ art->cursor = node_cursor;
+ art->event_cursor = true;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = HEADERY;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
+ art->listener = node_region_listener;
+ art->init = node_header_region_init;
+ art->draw = node_header_region_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: listview/buttons */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
+ art->regionid = RGN_TYPE_UI;
+ art->prefsizex = 180; // XXX
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
+ art->listener = node_region_listener;
+ art->init = node_buttons_region_init;
+ art->draw = node_buttons_region_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ node_buttons_register(art);
+
+ /* regions: toolbar */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region");
+ art->regionid = RGN_TYPE_TOOLS;
+ art->prefsizex = 58; /* XXX */
+ art->prefsizey = 50; /* XXX */
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
+ art->listener = node_region_listener;
+ art->message_subscribe = ED_region_generic_tools_region_message_subscribe;
+ art->snap_size = ED_region_generic_tools_region_snap_size;
+ art->init = node_toolbar_region_init;
+ art->draw = node_toolbar_region_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ node_toolbar_register(art);
+
+ BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt
index 83832d62b9e..f08069c418b 100644
--- a/source/blender/editors/space_outliner/CMakeLists.txt
+++ b/source/blender/editors/space_outliner/CMakeLists.txt
@@ -16,47 +16,47 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../depsgraph
- ../../imbuf
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../depsgraph
+ ../../imbuf
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- outliner_collections.c
- outliner_dragdrop.c
- outliner_draw.c
- outliner_edit.c
- outliner_ops.c
- outliner_select.c
- outliner_tools.c
- outliner_tree.c
- outliner_utils.c
- space_outliner.c
+ outliner_collections.c
+ outliner_dragdrop.c
+ outliner_draw.c
+ outliner_edit.c
+ outliner_ops.c
+ outliner_select.c
+ outliner_tools.c
+ outliner_tree.c
+ outliner_utils.c
+ space_outliner.c
- outliner_intern.h
+ outliner_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
- bf_editor_undo
+ bf_blenkernel
+ bf_blenlib
+ bf_editor_undo
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 30eaefe6149..835c154786b 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -56,78 +56,81 @@
bool outliner_is_collection_tree_element(const TreeElement *te)
{
- TreeStoreElem *tselem = TREESTORE(te);
+ TreeStoreElem *tselem = TREESTORE(te);
- if (!tselem) {
- return false;
- }
+ if (!tselem) {
+ return false;
+ }
- if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
- return true;
- }
- else if (tselem->type == 0 && te->idcode == ID_GR) {
- return true;
- }
+ if (ELEM(tselem->type,
+ TSE_LAYER_COLLECTION,
+ TSE_SCENE_COLLECTION_BASE,
+ TSE_VIEW_COLLECTION_BASE)) {
+ return true;
+ }
+ else if (tselem->type == 0 && te->idcode == ID_GR) {
+ return true;
+ }
- return false;
+ return false;
}
Collection *outliner_collection_from_tree_element(const TreeElement *te)
{
- TreeStoreElem *tselem = TREESTORE(te);
+ TreeStoreElem *tselem = TREESTORE(te);
- if (!tselem) {
- return NULL;
- }
+ if (!tselem) {
+ return NULL;
+ }
- if (tselem->type == TSE_LAYER_COLLECTION) {
- LayerCollection *lc = te->directdata;
- return lc->collection;
- }
- else if (ELEM(tselem->type, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
- Scene *scene = (Scene *)tselem->id;
- return BKE_collection_master(scene);
- }
- else if (tselem->type == 0 && te->idcode == ID_GR) {
- return (Collection *)tselem->id;
- }
+ if (tselem->type == TSE_LAYER_COLLECTION) {
+ LayerCollection *lc = te->directdata;
+ return lc->collection;
+ }
+ else if (ELEM(tselem->type, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
+ Scene *scene = (Scene *)tselem->id;
+ return BKE_collection_master(scene);
+ }
+ else if (tselem->type == 0 && te->idcode == ID_GR) {
+ return (Collection *)tselem->id;
+ }
- return NULL;
+ return NULL;
}
TreeTraversalAction outliner_find_selected_collections(TreeElement *te, void *customdata)
{
- struct IDsSelectedData *data = customdata;
- TreeStoreElem *tselem = TREESTORE(te);
+ struct IDsSelectedData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
- if (outliner_is_collection_tree_element(te)) {
- BLI_addtail(&data->selected_array, BLI_genericNodeN(te));
- return TRAVERSE_CONTINUE;
- }
+ if (outliner_is_collection_tree_element(te)) {
+ BLI_addtail(&data->selected_array, BLI_genericNodeN(te));
+ return TRAVERSE_CONTINUE;
+ }
- if (tselem->type || (tselem->id && GS(tselem->id->name) != ID_GR)) {
- return TRAVERSE_SKIP_CHILDS;
- }
+ if (tselem->type || (tselem->id && GS(tselem->id->name) != ID_GR)) {
+ return TRAVERSE_SKIP_CHILDS;
+ }
- return TRAVERSE_CONTINUE;
+ return TRAVERSE_CONTINUE;
}
TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *customdata)
{
- struct IDsSelectedData *data = customdata;
- TreeStoreElem *tselem = TREESTORE(te);
+ struct IDsSelectedData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
- if (outliner_is_collection_tree_element(te)) {
- return TRAVERSE_CONTINUE;
- }
+ if (outliner_is_collection_tree_element(te)) {
+ return TRAVERSE_CONTINUE;
+ }
- if (tselem->type || (tselem->id == NULL) || (GS(tselem->id->name) != ID_OB)) {
- return TRAVERSE_SKIP_CHILDS;
- }
+ if (tselem->type || (tselem->id == NULL) || (GS(tselem->id->name) != ID_OB)) {
+ return TRAVERSE_SKIP_CHILDS;
+ }
- BLI_addtail(&data->selected_array, BLI_genericNodeN(te));
+ BLI_addtail(&data->selected_array, BLI_genericNodeN(te));
- return TRAVERSE_CONTINUE;
+ return TRAVERSE_CONTINUE;
}
/* -------------------------------------------------------------------- */
@@ -135,1247 +138,1302 @@ TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *custom
bool ED_outliner_collections_editor_poll(bContext *C)
{
- SpaceOutliner *so = CTX_wm_space_outliner(C);
- return (so != NULL) && ELEM(so->outlinevis, SO_VIEW_LAYER, SO_SCENES, SO_LIBRARIES);
+ SpaceOutliner *so = CTX_wm_space_outliner(C);
+ return (so != NULL) && ELEM(so->outlinevis, SO_VIEW_LAYER, SO_SCENES, SO_LIBRARIES);
}
static bool outliner_view_layer_collections_editor_poll(bContext *C)
{
- SpaceOutliner *so = CTX_wm_space_outliner(C);
- return (so != NULL) && (so->outlinevis == SO_VIEW_LAYER);
+ SpaceOutliner *so = CTX_wm_space_outliner(C);
+ return (so != NULL) && (so->outlinevis == SO_VIEW_LAYER);
}
/********************************* New Collection ****************************/
-struct CollectionNewData
-{
- bool error;
- Collection *collection;
+struct CollectionNewData {
+ bool error;
+ Collection *collection;
};
static TreeTraversalAction collection_find_selected_to_add(TreeElement *te, void *customdata)
{
- struct CollectionNewData *data = customdata;
- Collection *collection = outliner_collection_from_tree_element(te);
+ struct CollectionNewData *data = customdata;
+ Collection *collection = outliner_collection_from_tree_element(te);
- if (!collection) {
- return TRAVERSE_SKIP_CHILDS;
- }
+ if (!collection) {
+ return TRAVERSE_SKIP_CHILDS;
+ }
- if (data->collection != NULL) {
- data->error = true;
- return TRAVERSE_BREAK;
- }
+ if (data->collection != NULL) {
+ data->error = true;
+ return TRAVERSE_BREAK;
+ }
- data->collection = collection;
- return TRAVERSE_CONTINUE;
+ data->collection = collection;
+ return TRAVERSE_CONTINUE;
}
static int collection_new_exec(bContext *C, wmOperator *op)
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ ARegion *ar = CTX_wm_region(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
- struct CollectionNewData data = {
- .error = false,
- .collection = NULL,
- };
+ struct CollectionNewData data = {
+ .error = false,
+ .collection = NULL,
+ };
- if (RNA_boolean_get(op->ptr, "nested")) {
- outliner_build_tree(bmain, scene, view_layer, soops, ar);
+ if (RNA_boolean_get(op->ptr, "nested")) {
+ outliner_build_tree(bmain, scene, view_layer, soops, ar);
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_to_add, &data);
+ outliner_tree_traverse(
+ soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_to_add, &data);
- if (data.error) {
- BKE_report(op->reports, RPT_ERROR, "More than one collection is selected");
- return OPERATOR_CANCELLED;
- }
- }
+ if (data.error) {
+ BKE_report(op->reports, RPT_ERROR, "More than one collection is selected");
+ return OPERATOR_CANCELLED;
+ }
+ }
- if (data.collection == NULL || ID_IS_LINKED(data.collection)) {
- data.collection = BKE_collection_master(scene);
- }
+ if (data.collection == NULL || ID_IS_LINKED(data.collection)) {
+ data.collection = BKE_collection_master(scene);
+ }
- if (ID_IS_LINKED(scene)) {
- BKE_report(op->reports, RPT_ERROR, "Can't add a new collection to linked scene/collection");
- return OPERATOR_CANCELLED;
- }
+ if (ID_IS_LINKED(scene)) {
+ BKE_report(op->reports, RPT_ERROR, "Can't add a new collection to linked scene/collection");
+ return OPERATOR_CANCELLED;
+ }
- BKE_collection_add(
- bmain,
- data.collection,
- NULL);
+ BKE_collection_add(bmain, data.collection, NULL);
- DEG_id_tag_update(&data.collection->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&data.collection->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
- outliner_cleanup_tree(soops);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- return OPERATOR_FINISHED;
+ outliner_cleanup_tree(soops);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_collection_new(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "New Collection";
- ot->idname = "OUTLINER_OT_collection_new";
- ot->description = "Add a new collection inside selected collection";
+ /* identifiers */
+ ot->name = "New Collection";
+ ot->idname = "OUTLINER_OT_collection_new";
+ ot->description = "Add a new collection inside selected collection";
- /* api callbacks */
- ot->exec = collection_new_exec;
- ot->poll = ED_outliner_collections_editor_poll;
+ /* api callbacks */
+ ot->exec = collection_new_exec;
+ ot->poll = ED_outliner_collections_editor_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- PropertyRNA *prop = RNA_def_boolean(ot->srna, "nested", true, "Nested", "Add as child of selected collection");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ PropertyRNA *prop = RNA_def_boolean(
+ ot->srna, "nested", true, "Nested", "Add as child of selected collection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/**************************** Delete Collection ******************************/
struct CollectionEditData {
- Scene *scene;
- SpaceOutliner *soops;
- GSet *collections_to_edit;
+ Scene *scene;
+ SpaceOutliner *soops;
+ GSet *collections_to_edit;
};
static TreeTraversalAction collection_find_data_to_edit(TreeElement *te, void *customdata)
{
- struct CollectionEditData *data = customdata;
- Collection *collection = outliner_collection_from_tree_element(te);
+ struct CollectionEditData *data = customdata;
+ Collection *collection = outliner_collection_from_tree_element(te);
- if (!collection) {
- return TRAVERSE_SKIP_CHILDS;
- }
+ if (!collection) {
+ return TRAVERSE_SKIP_CHILDS;
+ }
- if (collection->flag & COLLECTION_IS_MASTER) {
- /* skip - showing warning/error message might be misleading
- * when deleting multiple collections, so just do nothing */
- }
- else {
- /* Delete, duplicate and link don't edit children, those will come along
- * with the parents. */
- BLI_gset_add(data->collections_to_edit, collection);
- return TRAVERSE_SKIP_CHILDS;
- }
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ /* skip - showing warning/error message might be misleading
+ * when deleting multiple collections, so just do nothing */
+ }
+ else {
+ /* Delete, duplicate and link don't edit children, those will come along
+ * with the parents. */
+ BLI_gset_add(data->collections_to_edit, collection);
+ return TRAVERSE_SKIP_CHILDS;
+ }
- return TRAVERSE_CONTINUE;
+ return TRAVERSE_CONTINUE;
}
static int collection_delete_exec(bContext *C, wmOperator *op)
{
- 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__);
-
- /* We first walk over and find the Collections we actually want to delete (ignoring duplicates). */
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_edit, &data);
-
- /* Effectively delete the collections. */
- GSetIterator collections_to_edit_iter;
- GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
- Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
-
- /* Test in case collection got deleted as part of another one. */
- if (BLI_findindex(&bmain->collections, collection) != -1) {
- /* We cannot allow to delete collections that are indirectly linked, or that are used by (linked to...)
- * other linked scene/collection. */
- bool skip = false;
- if (ID_IS_LINKED(collection)) {
- if (collection->id.tag & LIB_TAG_INDIRECT) {
- skip = true;
- }
- else {
- for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
- Collection *parent = cparent->collection;
- if (ID_IS_LINKED(parent)) {
- skip = true;
- break;
- }
- else if (parent->flag & COLLECTION_IS_MASTER) {
- Scene *parent_scene = BKE_collection_master_scene_search(bmain, parent);
- if (ID_IS_LINKED(parent_scene)) {
- skip = true;
- break;
- }
- }
- }
- }
- }
-
- if (!skip) {
- BKE_collection_delete(bmain, collection, hierarchy);
- }
- else {
- BKE_reportf(op->reports, RPT_WARNING,
- "Cannot delete linked collection '%s', it is used by other linked scenes/collections",
- collection->id.name + 2);
- }
- }
- }
-
- BLI_gset_free(data.collections_to_edit, NULL);
-
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
-
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
-
- if (basact_prev != BASACT(view_layer)) {
- WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active);
- }
-
- return OPERATOR_FINISHED;
+ 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__);
+
+ /* We first walk over and find the Collections we actually want to delete (ignoring duplicates). */
+ outliner_tree_traverse(
+ soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_edit, &data);
+
+ /* Effectively delete the collections. */
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER (collections_to_edit_iter, data.collections_to_edit) {
+ Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+
+ /* Test in case collection got deleted as part of another one. */
+ if (BLI_findindex(&bmain->collections, collection) != -1) {
+ /* We cannot allow to delete collections that are indirectly linked, or that are used by (linked to...)
+ * other linked scene/collection. */
+ bool skip = false;
+ if (ID_IS_LINKED(collection)) {
+ if (collection->id.tag & LIB_TAG_INDIRECT) {
+ skip = true;
+ }
+ else {
+ for (CollectionParent *cparent = collection->parents.first; cparent;
+ cparent = cparent->next) {
+ Collection *parent = cparent->collection;
+ if (ID_IS_LINKED(parent)) {
+ skip = true;
+ break;
+ }
+ else if (parent->flag & COLLECTION_IS_MASTER) {
+ Scene *parent_scene = BKE_collection_master_scene_search(bmain, parent);
+ if (ID_IS_LINKED(parent_scene)) {
+ skip = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (!skip) {
+ BKE_collection_delete(bmain, collection, hierarchy);
+ }
+ else {
+ BKE_reportf(
+ op->reports,
+ RPT_WARNING,
+ "Cannot delete linked collection '%s', it is used by other linked scenes/collections",
+ collection->id.name + 2);
+ }
+ }
+ }
+
+ BLI_gset_free(data.collections_to_edit, NULL);
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ if (basact_prev != BASACT(view_layer)) {
+ WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active);
+ }
+
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_collection_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Collection";
- ot->idname = "OUTLINER_OT_collection_delete";
- ot->description = "Delete selected collections";
+ /* identifiers */
+ ot->name = "Delete Collection";
+ ot->idname = "OUTLINER_OT_collection_delete";
+ ot->description = "Delete selected collections";
- /* api callbacks */
- ot->exec = collection_delete_exec;
- ot->poll = ED_outliner_collections_editor_poll;
+ /* api callbacks */
+ ot->exec = collection_delete_exec;
+ ot->poll = ED_outliner_collections_editor_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* 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);
+ /* 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 *******************************/
struct CollectionObjectsSelectData {
- bool error;
- LayerCollection *layer_collection;
+ bool error;
+ LayerCollection *layer_collection;
};
-static TreeTraversalAction outliner_find_first_selected_layer_collection(TreeElement *te, void *customdata)
+static TreeTraversalAction outliner_find_first_selected_layer_collection(TreeElement *te,
+ void *customdata)
{
- struct CollectionObjectsSelectData *data = customdata;
- TreeStoreElem *tselem = TREESTORE(te);
+ struct CollectionObjectsSelectData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
- switch (tselem->type) {
- case TSE_LAYER_COLLECTION:
- data->layer_collection = te->directdata;
- return TRAVERSE_BREAK;
- case TSE_R_LAYER:
- case TSE_SCENE_COLLECTION_BASE:
- case TSE_VIEW_COLLECTION_BASE:
- return TRAVERSE_CONTINUE;
- default:
- return TRAVERSE_SKIP_CHILDS;
- }
+ switch (tselem->type) {
+ case TSE_LAYER_COLLECTION:
+ data->layer_collection = te->directdata;
+ return TRAVERSE_BREAK;
+ case TSE_R_LAYER:
+ case TSE_SCENE_COLLECTION_BASE:
+ case TSE_VIEW_COLLECTION_BASE:
+ return TRAVERSE_CONTINUE;
+ default:
+ return TRAVERSE_SKIP_CHILDS;
+ }
}
static LayerCollection *outliner_active_layer_collection(bContext *C)
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
- struct CollectionObjectsSelectData data = {
- .layer_collection = NULL,
- };
+ struct CollectionObjectsSelectData data = {
+ .layer_collection = NULL,
+ };
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_first_selected_layer_collection, &data);
- return data.layer_collection;
+ outliner_tree_traverse(
+ soops, &soops->tree, 0, TSE_SELECTED, outliner_find_first_selected_layer_collection, &data);
+ return data.layer_collection;
}
static int collection_objects_select_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- LayerCollection *layer_collection = outliner_active_layer_collection(C);
- bool deselect = STREQ(op->idname, "OUTLINER_OT_collection_objects_deselect");
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *layer_collection = outliner_active_layer_collection(C);
+ bool deselect = STREQ(op->idname, "OUTLINER_OT_collection_objects_deselect");
- if (layer_collection == NULL) {
- return OPERATOR_CANCELLED;
- }
+ if (layer_collection == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- BKE_layer_collection_objects_select(view_layer, layer_collection, deselect);
+ BKE_layer_collection_objects_select(view_layer, layer_collection, deselect);
- 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);
+ 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);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_collection_objects_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Objects";
- ot->idname = "OUTLINER_OT_collection_objects_select";
- ot->description = "Select objects in collection";
+ /* identifiers */
+ ot->name = "Select Objects";
+ ot->idname = "OUTLINER_OT_collection_objects_select";
+ ot->description = "Select objects in collection";
- /* api callbacks */
- ot->exec = collection_objects_select_exec;
- ot->poll = ED_outliner_collections_editor_poll;
+ /* api callbacks */
+ ot->exec = collection_objects_select_exec;
+ ot->poll = ED_outliner_collections_editor_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void OUTLINER_OT_collection_objects_deselect(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Deselect Objects";
- ot->idname = "OUTLINER_OT_collection_objects_deselect";
- ot->description = "Deselect objects in collection";
+ /* identifiers */
+ ot->name = "Deselect Objects";
+ ot->idname = "OUTLINER_OT_collection_objects_deselect";
+ ot->description = "Deselect objects in collection";
- /* api callbacks */
- ot->exec = collection_objects_select_exec;
- ot->poll = ED_outliner_collections_editor_poll;
+ /* api callbacks */
+ ot->exec = collection_objects_select_exec;
+ ot->poll = ED_outliner_collections_editor_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************** Duplicate Collection *****************************/
struct CollectionDuplicateData {
- TreeElement *te;
+ TreeElement *te;
};
-static TreeTraversalAction outliner_find_first_selected_collection(TreeElement *te, void *customdata)
+static TreeTraversalAction outliner_find_first_selected_collection(TreeElement *te,
+ void *customdata)
{
- struct CollectionDuplicateData *data = customdata;
- TreeStoreElem *tselem = TREESTORE(te);
+ struct CollectionDuplicateData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
- switch (tselem->type) {
- case TSE_LAYER_COLLECTION:
- data->te = te;
- return TRAVERSE_BREAK;
- case TSE_R_LAYER:
- case TSE_SCENE_COLLECTION_BASE:
- case TSE_VIEW_COLLECTION_BASE:
- default:
- return TRAVERSE_CONTINUE;
- }
+ switch (tselem->type) {
+ case TSE_LAYER_COLLECTION:
+ data->te = te;
+ return TRAVERSE_BREAK;
+ case TSE_R_LAYER:
+ case TSE_SCENE_COLLECTION_BASE:
+ case TSE_VIEW_COLLECTION_BASE:
+ default:
+ return TRAVERSE_CONTINUE;
+ }
}
static TreeElement *outliner_active_collection(bContext *C)
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
- struct CollectionDuplicateData data = {
- .te = NULL,
- };
+ struct CollectionDuplicateData data = {
+ .te = NULL,
+ };
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_first_selected_collection, &data);
- return data.te;
+ outliner_tree_traverse(
+ soops, &soops->tree, 0, TSE_SELECTED, outliner_find_first_selected_collection, &data);
+ return data.te;
}
static int collection_duplicate_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- TreeElement *te = outliner_active_collection(C);
- const bool linked = strstr(op->idname, "linked") != NULL;
-
- /* Can happen when calling from a key binding. */
- if (te == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active collection");
- return OPERATOR_CANCELLED;
- }
-
- Collection *collection = outliner_collection_from_tree_element(te);
- Collection *parent = (te->parent) ? outliner_collection_from_tree_element(te->parent) : NULL;
-
- /* We are allowed to duplicated linked collections (they will become local IDs then),
- * but we should not allow its parent to be a linked ID, ever.
- * This can happen when a whole scene is linked e.g. */
- if (parent != NULL && ID_IS_LINKED(parent)) {
- Scene *scene = CTX_data_scene(C);
- parent = ID_IS_LINKED(scene) ? NULL : BKE_collection_master(scene);
- }
- else if (parent != NULL && (parent->flag & COLLECTION_IS_MASTER) != 0) {
- Scene *scene = BKE_collection_master_scene_search(bmain, parent);
- BLI_assert(scene != NULL);
- if (ID_IS_LINKED(scene)) {
- scene = CTX_data_scene(C);
- parent = ID_IS_LINKED(scene) ? NULL : BKE_collection_master(scene);
- }
- }
-
- if (collection->flag & COLLECTION_IS_MASTER) {
- BKE_report(op->reports, RPT_ERROR, "Can't duplicate the master collection");
- return OPERATOR_CANCELLED;
- }
-
- if (parent == NULL) {
- BKE_report(op->reports, RPT_WARNING,
- "Could not find a valid parent collection for the new duplicate, "
- "it won't be linked to any view layer");
- }
-
- BKE_collection_duplicate(bmain, parent, collection, true, true, !linked);
-
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, CTX_data_scene(C));
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ TreeElement *te = outliner_active_collection(C);
+ const bool linked = strstr(op->idname, "linked") != NULL;
+
+ /* Can happen when calling from a key binding. */
+ if (te == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active collection");
+ return OPERATOR_CANCELLED;
+ }
+
+ Collection *collection = outliner_collection_from_tree_element(te);
+ Collection *parent = (te->parent) ? outliner_collection_from_tree_element(te->parent) : NULL;
+
+ /* We are allowed to duplicated linked collections (they will become local IDs then),
+ * but we should not allow its parent to be a linked ID, ever.
+ * This can happen when a whole scene is linked e.g. */
+ if (parent != NULL && ID_IS_LINKED(parent)) {
+ Scene *scene = CTX_data_scene(C);
+ parent = ID_IS_LINKED(scene) ? NULL : BKE_collection_master(scene);
+ }
+ else if (parent != NULL && (parent->flag & COLLECTION_IS_MASTER) != 0) {
+ Scene *scene = BKE_collection_master_scene_search(bmain, parent);
+ BLI_assert(scene != NULL);
+ if (ID_IS_LINKED(scene)) {
+ scene = CTX_data_scene(C);
+ parent = ID_IS_LINKED(scene) ? NULL : BKE_collection_master(scene);
+ }
+ }
+
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ BKE_report(op->reports, RPT_ERROR, "Can't duplicate the master collection");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (parent == NULL) {
+ BKE_report(op->reports,
+ RPT_WARNING,
+ "Could not find a valid parent collection for the new duplicate, "
+ "it won't be linked to any view layer");
+ }
+
+ BKE_collection_duplicate(bmain, parent, collection, true, true, !linked);
+
+ DEG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, CTX_data_scene(C));
+
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_collection_duplicate_linked(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Duplicate Linked Collection";
- ot->idname = "OUTLINER_OT_collection_duplicate_linked";
- ot->description = "Recursively duplicate the collection, all its children and objects, with linked object data";
+ /* identifiers */
+ ot->name = "Duplicate Linked Collection";
+ ot->idname = "OUTLINER_OT_collection_duplicate_linked";
+ ot->description =
+ "Recursively duplicate the collection, all its children and objects, with linked object "
+ "data";
- /* api callbacks */
- ot->exec = collection_duplicate_exec;
- ot->poll = ED_outliner_collections_editor_poll;
+ /* api callbacks */
+ ot->exec = collection_duplicate_exec;
+ ot->poll = ED_outliner_collections_editor_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void OUTLINER_OT_collection_duplicate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Duplicate Collection";
- ot->idname = "OUTLINER_OT_collection_duplicate";
- ot->description = "Recursively duplicate the collection, all its children, objects and object data";
+ /* identifiers */
+ ot->name = "Duplicate Collection";
+ ot->idname = "OUTLINER_OT_collection_duplicate";
+ ot->description =
+ "Recursively duplicate the collection, all its children, objects and object data";
- /* api callbacks */
- ot->exec = collection_duplicate_exec;
- ot->poll = ED_outliner_collections_editor_poll;
+ /* api callbacks */
+ ot->exec = collection_duplicate_exec;
+ ot->poll = ED_outliner_collections_editor_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/**************************** Link Collection ******************************/
static int collection_link_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Collection *active_collection = CTX_data_layer_collection(C)->collection;
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- struct CollectionEditData data = {.scene = scene, .soops = soops,};
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Collection *active_collection = CTX_data_layer_collection(C)->collection;
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ struct CollectionEditData data = {
+ .scene = scene,
+ .soops = soops,
+ };
- if (ID_IS_LINKED(active_collection) ||
- ((active_collection->flag & COLLECTION_IS_MASTER) && ID_IS_LINKED(scene)))
- {
- BKE_report(op->reports, RPT_ERROR, "Cannot add a colection to a linked collection/scene");
- return OPERATOR_CANCELLED;
- }
+ if (ID_IS_LINKED(active_collection) ||
+ ((active_collection->flag & COLLECTION_IS_MASTER) && ID_IS_LINKED(scene))) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot add a colection to a linked collection/scene");
+ return OPERATOR_CANCELLED;
+ }
- data.collections_to_edit = BLI_gset_ptr_new(__func__);
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
- /* We first walk over and find the Collections we actually want to link (ignoring duplicates). */
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_edit, &data);
+ /* We first walk over and find the Collections we actually want to link (ignoring duplicates). */
+ outliner_tree_traverse(
+ soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_edit, &data);
- /* Effectively link the collections. */
- GSetIterator collections_to_edit_iter;
- GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
- Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
- BKE_collection_child_add(bmain, active_collection, collection);
- id_fake_user_clear(&collection->id);
- }
+ /* Effectively link the collections. */
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER (collections_to_edit_iter, data.collections_to_edit) {
+ Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+ BKE_collection_child_add(bmain, active_collection, collection);
+ id_fake_user_clear(&collection->id);
+ }
- BLI_gset_free(data.collections_to_edit, NULL);
+ BLI_gset_free(data.collections_to_edit, NULL);
- DEG_id_tag_update(&active_collection->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&active_collection->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_collection_link(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Link Collection";
- ot->idname = "OUTLINER_OT_collection_link";
- ot->description = "Link selected collections to active scene";
+ /* identifiers */
+ ot->name = "Link Collection";
+ ot->idname = "OUTLINER_OT_collection_link";
+ ot->description = "Link selected collections to active scene";
- /* api callbacks */
- ot->exec = collection_link_exec;
- ot->poll = ED_outliner_collections_editor_poll;
+ /* api callbacks */
+ ot->exec = collection_link_exec;
+ ot->poll = ED_outliner_collections_editor_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************** Instance Collection ******************************/
static int collection_instance_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- struct CollectionEditData data = {.scene = scene, .soops = soops,};
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ struct CollectionEditData data = {
+ .scene = scene,
+ .soops = soops,
+ };
- data.collections_to_edit = BLI_gset_ptr_new(__func__);
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
- /* We first walk over and find the Collections we actually want to instance (ignoring duplicates). */
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_edit, &data);
+ /* We first walk over and find the Collections we actually want to instance (ignoring duplicates). */
+ outliner_tree_traverse(
+ soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_edit, &data);
- /* Find an active collection to add to, that doesn't give dependency cycles. */
- LayerCollection *active_lc = BKE_layer_collection_get_active(view_layer);
+ /* Find an active collection to add to, that doesn't give dependency cycles. */
+ LayerCollection *active_lc = BKE_layer_collection_get_active(view_layer);
- GSetIterator collections_to_edit_iter;
- GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
- Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER (collections_to_edit_iter, data.collections_to_edit) {
+ Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
- while (BKE_collection_find_cycle(active_lc->collection, collection)) {
- active_lc = BKE_layer_collection_activate_parent(view_layer, active_lc);
- }
- }
+ while (BKE_collection_find_cycle(active_lc->collection, collection)) {
+ active_lc = BKE_layer_collection_activate_parent(view_layer, active_lc);
+ }
+ }
- /* Effectively instance the collections. */
- GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
- Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
- Object *ob = ED_object_add_type(C, OB_EMPTY, collection->id.name + 2, scene->cursor.location, NULL, false, 0);
- ob->instance_collection = collection;
- ob->transflag |= OB_DUPLICOLLECTION;
- id_lib_extern(&collection->id);
- }
+ /* Effectively instance the collections. */
+ GSET_ITER (collections_to_edit_iter, data.collections_to_edit) {
+ Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+ Object *ob = ED_object_add_type(
+ C, OB_EMPTY, collection->id.name + 2, scene->cursor.location, NULL, false, 0);
+ ob->instance_collection = collection;
+ ob->transflag |= OB_DUPLICOLLECTION;
+ id_lib_extern(&collection->id);
+ }
- BLI_gset_free(data.collections_to_edit, NULL);
+ BLI_gset_free(data.collections_to_edit, NULL);
- DEG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_collection_instance(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Instance Collection";
- ot->idname = "OUTLINER_OT_collection_instance";
- ot->description = "Instance selected collections to active scene";
+ /* identifiers */
+ ot->name = "Instance Collection";
+ ot->idname = "OUTLINER_OT_collection_instance";
+ ot->description = "Instance selected collections to active scene";
- /* api callbacks */
- ot->exec = collection_instance_exec;
- ot->poll = ED_outliner_collections_editor_poll;
+ /* api callbacks */
+ ot->exec = collection_instance_exec;
+ ot->poll = ED_outliner_collections_editor_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************** Exclude Collection ******************************/
static TreeTraversalAction layer_collection_find_data_to_edit(TreeElement *te, void *customdata)
{
- struct CollectionEditData *data = customdata;
- TreeStoreElem *tselem = TREESTORE(te);
+ struct CollectionEditData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
- if (!(tselem && tselem->type == TSE_LAYER_COLLECTION)) {
- return TRAVERSE_CONTINUE;
- }
+ if (!(tselem && tselem->type == TSE_LAYER_COLLECTION)) {
+ return TRAVERSE_CONTINUE;
+ }
- LayerCollection *lc = te->directdata;
+ LayerCollection *lc = te->directdata;
- if (lc->collection->flag & COLLECTION_IS_MASTER) {
- /* skip - showing warning/error message might be misleading
- * when deleting multiple collections, so just do nothing */
- }
- else {
- /* Delete, duplicate and link don't edit children, those will come along
- * with the parents. */
- BLI_gset_add(data->collections_to_edit, lc);
- }
+ if (lc->collection->flag & COLLECTION_IS_MASTER) {
+ /* skip - showing warning/error message might be misleading
+ * when deleting multiple collections, so just do nothing */
+ }
+ else {
+ /* Delete, duplicate and link don't edit children, those will come along
+ * with the parents. */
+ BLI_gset_add(data->collections_to_edit, lc);
+ }
- return TRAVERSE_CONTINUE;
+ return TRAVERSE_CONTINUE;
}
static bool collections_view_layer_poll(bContext *C, bool clear, int flag)
{
- /* Poll function so the right click menu show current state of selected collections. */
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- if (!(soops && soops->outlinevis == SO_VIEW_LAYER)) {
- return false;
- }
+ /* Poll function so the right click menu show current state of selected collections. */
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ if (!(soops && soops->outlinevis == SO_VIEW_LAYER)) {
+ return false;
+ }
- Scene *scene = CTX_data_scene(C);
- struct CollectionEditData data = {.scene = scene, .soops = soops,};
- data.collections_to_edit = BLI_gset_ptr_new(__func__);
- bool result = false;
+ Scene *scene = CTX_data_scene(C);
+ struct CollectionEditData data = {
+ .scene = scene,
+ .soops = soops,
+ };
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
+ bool result = false;
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
+ outliner_tree_traverse(
+ soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
- GSetIterator collections_to_edit_iter;
- GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
- LayerCollection *lc = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+ 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)) {
- result = true;
- }
- else if (!clear && !(lc->flag & flag)) {
- result = true;
- }
- }
+ if (clear && (lc->flag & flag)) {
+ result = true;
+ }
+ else if (!clear && !(lc->flag & flag)) {
+ result = true;
+ }
+ }
- BLI_gset_free(data.collections_to_edit, NULL);
- return result;
+ BLI_gset_free(data.collections_to_edit, NULL);
+ return result;
}
static bool collections_exclude_set_poll(bContext *C)
{
- return collections_view_layer_poll(C, false, LAYER_COLLECTION_EXCLUDE);
+ return collections_view_layer_poll(C, false, LAYER_COLLECTION_EXCLUDE);
}
static bool collections_exclude_clear_poll(bContext *C)
{
- return collections_view_layer_poll(C, true, LAYER_COLLECTION_EXCLUDE);
+ return collections_view_layer_poll(C, true, LAYER_COLLECTION_EXCLUDE);
}
static bool collections_holdout_set_poll(bContext *C)
{
- return collections_view_layer_poll(C, false, LAYER_COLLECTION_HOLDOUT);
+ return collections_view_layer_poll(C, false, LAYER_COLLECTION_HOLDOUT);
}
static bool collections_holdout_clear_poll(bContext *C)
{
- return collections_view_layer_poll(C, true, LAYER_COLLECTION_HOLDOUT);
+ return collections_view_layer_poll(C, true, LAYER_COLLECTION_HOLDOUT);
}
static bool collections_indirect_only_set_poll(bContext *C)
{
- return collections_view_layer_poll(C, false, LAYER_COLLECTION_INDIRECT_ONLY);
+ return collections_view_layer_poll(C, false, LAYER_COLLECTION_INDIRECT_ONLY);
}
static bool collections_indirect_only_clear_poll(bContext *C)
{
- return collections_view_layer_poll(C, true, LAYER_COLLECTION_INDIRECT_ONLY);
+ 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;
- }
+ 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);
- }
+ layer_collection_flag_recursive_set(nlc, flag);
+ }
}
static int collection_view_layer_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);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- struct CollectionEditData data = {.scene = scene, .soops = soops,};
- bool clear = strstr(op->idname, "clear") != NULL;
- int flag = strstr(op->idname, "holdout") ? LAYER_COLLECTION_HOLDOUT :
- strstr(op->idname, "indirect_only") ? LAYER_COLLECTION_INDIRECT_ONLY :
- LAYER_COLLECTION_EXCLUDE;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ struct CollectionEditData data = {
+ .scene = scene,
+ .soops = soops,
+ };
+ bool clear = strstr(op->idname, "clear") != NULL;
+ int flag = strstr(op->idname, "holdout") ?
+ LAYER_COLLECTION_HOLDOUT :
+ strstr(op->idname, "indirect_only") ? LAYER_COLLECTION_INDIRECT_ONLY :
+ LAYER_COLLECTION_EXCLUDE;
- data.collections_to_edit = BLI_gset_ptr_new(__func__);
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
+ outliner_tree_traverse(
+ soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
- GSetIterator collections_to_edit_iter;
- GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
- LayerCollection *lc = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+ 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;
- }
+ if (clear) {
+ lc->flag &= ~flag;
+ }
+ else {
+ lc->flag |= flag;
+ }
- layer_collection_flag_recursive_set(lc, flag);
- }
+ layer_collection_flag_recursive_set(lc, flag);
+ }
- BLI_gset_free(data.collections_to_edit, NULL);
+ BLI_gset_free(data.collections_to_edit, NULL);
- BKE_layer_collection_sync(scene, view_layer);
- DEG_relations_tag_update(bmain);
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_collection_exclude_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Exclude";
- ot->idname = "OUTLINER_OT_collection_exclude_set";
- ot->description = "Exclude collection from the active view layer";
+ /* identifiers */
+ ot->name = "Set Exclude";
+ ot->idname = "OUTLINER_OT_collection_exclude_set";
+ ot->description = "Exclude collection from the active view layer";
- /* api callbacks */
- ot->exec = collection_view_layer_exec;
- ot->poll = collections_exclude_set_poll;
+ /* api callbacks */
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_exclude_set_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void OUTLINER_OT_collection_exclude_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Exclude";
- ot->idname = "OUTLINER_OT_collection_exclude_clear";
- ot->description = "Include collection in the active view layer";
+ /* identifiers */
+ ot->name = "Clear Exclude";
+ ot->idname = "OUTLINER_OT_collection_exclude_clear";
+ ot->description = "Include collection in the active view layer";
- /* api callbacks */
- ot->exec = collection_view_layer_exec;
- ot->poll = collections_exclude_clear_poll;
+ /* api callbacks */
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_exclude_clear_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void OUTLINER_OT_collection_holdout_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Holdout";
- ot->idname = "OUTLINER_OT_collection_holdout_set";
- ot->description = "Mask collection in the active view layer";
+ /* identifiers */
+ ot->name = "Set Holdout";
+ ot->idname = "OUTLINER_OT_collection_holdout_set";
+ ot->description = "Mask collection in the active view layer";
- /* api callbacks */
- ot->exec = collection_view_layer_exec;
- ot->poll = collections_holdout_set_poll;
+ /* api callbacks */
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_holdout_set_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void OUTLINER_OT_collection_holdout_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Holdout";
- ot->idname = "OUTLINER_OT_collection_holdout_clear";
- ot->description = "Clear masking of collection in the active view layer";
+ /* identifiers */
+ ot->name = "Clear Holdout";
+ ot->idname = "OUTLINER_OT_collection_holdout_clear";
+ ot->description = "Clear masking of collection in the active view layer";
- /* api callbacks */
- ot->exec = collection_view_layer_exec;
- ot->poll = collections_holdout_clear_poll;
+ /* api callbacks */
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_holdout_clear_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void OUTLINER_OT_collection_indirect_only_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Indirect Only";
- ot->idname = "OUTLINER_OT_collection_indirect_only_set";
- ot->description = "Set collection to only contribute indirectly (through shadows and reflections) in the view layer";
+ /* identifiers */
+ ot->name = "Set Indirect Only";
+ ot->idname = "OUTLINER_OT_collection_indirect_only_set";
+ ot->description =
+ "Set collection to only contribute indirectly (through shadows and reflections) in the view "
+ "layer";
- /* api callbacks */
- ot->exec = collection_view_layer_exec;
- ot->poll = collections_indirect_only_set_poll;
+ /* api callbacks */
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_indirect_only_set_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void OUTLINER_OT_collection_indirect_only_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Indirect Only";
- ot->idname = "OUTLINER_OT_collection_indirect_only_clear";
- ot->description = "Clear collection contributing only indirectly in the view layer";
+ /* identifiers */
+ ot->name = "Clear Indirect Only";
+ ot->idname = "OUTLINER_OT_collection_indirect_only_clear";
+ ot->description = "Clear collection contributing only indirectly in the view layer";
- /* api callbacks */
- ot->exec = collection_view_layer_exec;
- ot->poll = collections_indirect_only_clear_poll;
+ /* api callbacks */
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_indirect_only_clear_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************** Visibility Operators ******************************/
static int collection_isolate_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- const bool extend = RNA_boolean_get(op->ptr, "extend");
- bool depsgraph_changed = false;
- struct CollectionEditData data = {.scene = scene, .soops = soops,};
- data.collections_to_edit = BLI_gset_ptr_new(__func__);
-
- /* Hide all collections before the isolate function - needed in order to support multiple selected collections. */
- if (!extend) {
- LayerCollection *lc_master = view_layer->layer_collections.first;
- for (LayerCollection *lc_iter = lc_master->layer_collections.first; lc_iter; lc_iter = lc_iter->next) {
- lc_iter->flag |= LAYER_COLLECTION_RESTRICT_VIEW;
- layer_collection_flag_recursive_set(lc_iter, LAYER_COLLECTION_RESTRICT_VIEW);
- }
- }
-
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
-
- GSetIterator collections_to_edit_iter;
- GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
- LayerCollection *layer_collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
- depsgraph_changed |= BKE_layer_collection_isolate(scene, view_layer, layer_collection, true);
- }
- BLI_gset_free(data.collections_to_edit, NULL);
-
- BKE_layer_collection_sync(scene, view_layer);
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
-
- if (depsgraph_changed) {
- DEG_relations_tag_update(CTX_data_main(C));
- }
-
- WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ bool depsgraph_changed = false;
+ struct CollectionEditData data = {
+ .scene = scene,
+ .soops = soops,
+ };
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
+
+ /* Hide all collections before the isolate function - needed in order to support multiple selected collections. */
+ if (!extend) {
+ LayerCollection *lc_master = view_layer->layer_collections.first;
+ for (LayerCollection *lc_iter = lc_master->layer_collections.first; lc_iter;
+ lc_iter = lc_iter->next) {
+ lc_iter->flag |= LAYER_COLLECTION_RESTRICT_VIEW;
+ layer_collection_flag_recursive_set(lc_iter, LAYER_COLLECTION_RESTRICT_VIEW);
+ }
+ }
+
+ outliner_tree_traverse(
+ soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
+
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER (collections_to_edit_iter, data.collections_to_edit) {
+ LayerCollection *layer_collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+ depsgraph_changed |= BKE_layer_collection_isolate(scene, view_layer, layer_collection, true);
+ }
+ BLI_gset_free(data.collections_to_edit, NULL);
+
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+
+ if (depsgraph_changed) {
+ DEG_relations_tag_update(CTX_data_main(C));
+ }
+
+ WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
+ return OPERATOR_FINISHED;
}
static int collection_isolate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, "extend");
- if (!RNA_property_is_set(op->ptr, prop) && (event->shift)) {
- RNA_property_boolean_set(op->ptr, prop, true);
- }
- return collection_isolate_exec(C, op);
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "extend");
+ if (!RNA_property_is_set(op->ptr, prop) && (event->shift)) {
+ RNA_property_boolean_set(op->ptr, prop, true);
+ }
+ return collection_isolate_exec(C, op);
}
void OUTLINER_OT_collection_isolate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Isolate Collection";
- ot->idname = "OUTLINER_OT_collection_isolate";
- ot->description = "Hide all but this collection and its parents";
+ /* identifiers */
+ ot->name = "Isolate Collection";
+ ot->idname = "OUTLINER_OT_collection_isolate";
+ ot->description = "Hide all but this collection and its parents";
- /* api callbacks */
- ot->exec = collection_isolate_exec;
- ot->invoke = collection_isolate_invoke;
- ot->poll = ED_outliner_collections_editor_poll;
+ /* api callbacks */
+ ot->exec = collection_isolate_exec;
+ ot->invoke = collection_isolate_invoke;
+ ot->poll = ED_outliner_collections_editor_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- PropertyRNA *prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend current visible collections");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ PropertyRNA *prop = RNA_def_boolean(
+ ot->srna, "extend", false, "Extend", "Extend current visible collections");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static bool collection_show_poll(bContext *C)
{
- return collections_view_layer_poll(C, true, LAYER_COLLECTION_RESTRICT_VIEW);
+ return collections_view_layer_poll(C, true, LAYER_COLLECTION_RESTRICT_VIEW);
}
static bool collection_hide_poll(bContext *C)
{
- return collections_view_layer_poll(C, false, LAYER_COLLECTION_RESTRICT_VIEW);
+ return collections_view_layer_poll(C, false, LAYER_COLLECTION_RESTRICT_VIEW);
}
static bool collection_inside_poll(bContext *C)
{
- if (!ED_outliner_collections_editor_poll(C)) {
- return false;
- }
- return outliner_active_layer_collection(C) != NULL;
+ if (!ED_outliner_collections_editor_poll(C)) {
+ return false;
+ }
+ return outliner_active_layer_collection(C) != NULL;
}
static int collection_visibility_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- const bool is_inside = strstr(op->idname, "inside") != NULL;
- const bool show = strstr(op->idname, "show") != NULL;
- bool depsgraph_changed = false;
- struct CollectionEditData data = {.scene = scene, .soops = soops,};
- data.collections_to_edit = BLI_gset_ptr_new(__func__);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ const bool is_inside = strstr(op->idname, "inside") != NULL;
+ const bool show = strstr(op->idname, "show") != NULL;
+ bool depsgraph_changed = false;
+ struct CollectionEditData data = {
+ .scene = scene,
+ .soops = soops,
+ };
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
+ outliner_tree_traverse(
+ soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
- GSetIterator collections_to_edit_iter;
- GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
- LayerCollection *layer_collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
- depsgraph_changed |= BKE_layer_collection_set_visible(view_layer, layer_collection, show, is_inside);
- }
- BLI_gset_free(data.collections_to_edit, NULL);
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER (collections_to_edit_iter, data.collections_to_edit) {
+ LayerCollection *layer_collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+ depsgraph_changed |= BKE_layer_collection_set_visible(
+ view_layer, layer_collection, show, is_inside);
+ }
+ BLI_gset_free(data.collections_to_edit, NULL);
- BKE_layer_collection_sync(scene, view_layer);
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
- if (depsgraph_changed) {
- DEG_relations_tag_update(CTX_data_main(C));
- }
+ if (depsgraph_changed) {
+ DEG_relations_tag_update(CTX_data_main(C));
+ }
- WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
- return OPERATOR_FINISHED;
+ WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_collection_show(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Show Collection";
- ot->idname = "OUTLINER_OT_collection_show";
- ot->description = "Show the collection in this view layer";
+ /* identifiers */
+ ot->name = "Show Collection";
+ ot->idname = "OUTLINER_OT_collection_show";
+ ot->description = "Show the collection in this view layer";
- /* api callbacks */
- ot->exec = collection_visibility_exec;
- ot->poll = collection_show_poll;
+ /* api callbacks */
+ ot->exec = collection_visibility_exec;
+ ot->poll = collection_show_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void OUTLINER_OT_collection_hide(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Collection";
- ot->idname = "OUTLINER_OT_collection_hide";
- ot->description = "Hide the collection in this view layer";
+ /* identifiers */
+ ot->name = "Hide Collection";
+ ot->idname = "OUTLINER_OT_collection_hide";
+ ot->description = "Hide the collection in this view layer";
- /* api callbacks */
- ot->exec = collection_visibility_exec;
- ot->poll = collection_hide_poll;
+ /* api callbacks */
+ ot->exec = collection_visibility_exec;
+ ot->poll = collection_hide_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void OUTLINER_OT_collection_show_inside(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Show Inside Collection";
- ot->idname = "OUTLINER_OT_collection_show_inside";
- ot->description = "Show all the objects and collections inside the collection";
+ /* identifiers */
+ ot->name = "Show Inside Collection";
+ ot->idname = "OUTLINER_OT_collection_show_inside";
+ ot->description = "Show all the objects and collections inside the collection";
- /* api callbacks */
- ot->exec = collection_visibility_exec;
- ot->poll = collection_inside_poll;
+ /* api callbacks */
+ ot->exec = collection_visibility_exec;
+ ot->poll = collection_inside_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void OUTLINER_OT_collection_hide_inside(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Inside Collection";
- ot->idname = "OUTLINER_OT_collection_hide_inside";
- ot->description = "Hide all the objects and collections inside the collection";
+ /* identifiers */
+ ot->name = "Hide Inside Collection";
+ ot->idname = "OUTLINER_OT_collection_hide_inside";
+ ot->description = "Hide all the objects and collections inside the collection";
- /* api callbacks */
- ot->exec = collection_visibility_exec;
- ot->poll = collection_inside_poll;
+ /* api callbacks */
+ ot->exec = collection_visibility_exec;
+ ot->poll = collection_inside_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static bool collection_flag_poll(bContext *C, bool clear, int flag)
{
- if (!ED_outliner_collections_editor_poll(C)) {
- return false;
- }
+ if (!ED_outliner_collections_editor_poll(C)) {
+ return false;
+ }
- TreeElement *te = outliner_active_collection(C);
- if (te == NULL) {
- return false;
- }
+ TreeElement *te = outliner_active_collection(C);
+ if (te == NULL) {
+ return false;
+ }
- Collection *collection = outliner_collection_from_tree_element(te);
- if (collection == NULL) {
- return false;
- }
+ Collection *collection = outliner_collection_from_tree_element(te);
+ if (collection == NULL) {
+ return false;
+ }
- if (clear && (collection->flag & flag)) {
- return true;
- }
- else if (!clear && !(collection->flag & flag)) {
- return true;
- }
+ if (clear && (collection->flag & flag)) {
+ return true;
+ }
+ else if (!clear && !(collection->flag & flag)) {
+ return true;
+ }
- return false;
+ return false;
}
static bool collection_enable_poll(bContext *C)
{
- return collection_flag_poll(C, true, COLLECTION_RESTRICT_VIEW);
+ return collection_flag_poll(C, true, COLLECTION_RESTRICT_VIEW);
}
static bool collection_disable_poll(bContext *C)
{
- return collection_flag_poll(C, false, COLLECTION_RESTRICT_VIEW);
+ return collection_flag_poll(C, false, COLLECTION_RESTRICT_VIEW);
}
static bool collection_enable_render_poll(bContext *C)
{
- return collection_flag_poll(C, true, COLLECTION_RESTRICT_RENDER);
+ return collection_flag_poll(C, true, COLLECTION_RESTRICT_RENDER);
}
static bool collection_disable_render_poll(bContext *C)
{
- return collection_flag_poll(C, false, COLLECTION_RESTRICT_RENDER);
+ return collection_flag_poll(C, false, COLLECTION_RESTRICT_RENDER);
}
static int collection_flag_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- const bool is_render = strstr(op->idname, "render");
- const bool clear = strstr(op->idname, "show") || strstr(op->idname, "enable");
- int flag = is_render ? COLLECTION_RESTRICT_RENDER : COLLECTION_RESTRICT_VIEW;
- struct CollectionEditData data = {.scene = scene, .soops = soops,};
- data.collections_to_edit = BLI_gset_ptr_new(__func__);
- const bool has_layer_collection = soops->outlinevis == SO_VIEW_LAYER;
-
- if (has_layer_collection) {
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
- GSetIterator collections_to_edit_iter;
- GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
- LayerCollection *layer_collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
- Collection *collection = layer_collection->collection;
- if (ID_IS_LINKED(collection)) {
- continue;
- }
- if (clear) {
- collection->flag &= ~flag;
- }
- else {
- collection->flag |= flag;
- }
-
- /* Make sure (at least for this view layer) the collection is visible. */
- if (clear && !is_render) {
- layer_collection->flag &= ~LAYER_COLLECTION_RESTRICT_VIEW;
- }
- }
- BLI_gset_free(data.collections_to_edit, NULL);
- }
- else {
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_edit, &data);
- GSetIterator collections_to_edit_iter;
- GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
- Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
-
- if (clear) {
- collection->flag &= ~flag;
- }
- else {
- collection->flag |= flag;
- }
- }
- BLI_gset_free(data.collections_to_edit, NULL);
- }
-
- BKE_layer_collection_sync(scene, view_layer);
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
-
- if (!is_render) {
- DEG_relations_tag_update(CTX_data_main(C));
- }
-
- WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ const bool is_render = strstr(op->idname, "render");
+ const bool clear = strstr(op->idname, "show") || strstr(op->idname, "enable");
+ int flag = is_render ? COLLECTION_RESTRICT_RENDER : COLLECTION_RESTRICT_VIEW;
+ struct CollectionEditData data = {
+ .scene = scene,
+ .soops = soops,
+ };
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
+ const bool has_layer_collection = soops->outlinevis == SO_VIEW_LAYER;
+
+ if (has_layer_collection) {
+ outliner_tree_traverse(
+ soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER (collections_to_edit_iter, data.collections_to_edit) {
+ LayerCollection *layer_collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+ Collection *collection = layer_collection->collection;
+ if (ID_IS_LINKED(collection)) {
+ continue;
+ }
+ if (clear) {
+ collection->flag &= ~flag;
+ }
+ else {
+ collection->flag |= flag;
+ }
+
+ /* Make sure (at least for this view layer) the collection is visible. */
+ if (clear && !is_render) {
+ layer_collection->flag &= ~LAYER_COLLECTION_RESTRICT_VIEW;
+ }
+ }
+ BLI_gset_free(data.collections_to_edit, NULL);
+ }
+ else {
+ outliner_tree_traverse(
+ soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_edit, &data);
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER (collections_to_edit_iter, data.collections_to_edit) {
+ Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+
+ if (clear) {
+ collection->flag &= ~flag;
+ }
+ else {
+ collection->flag |= flag;
+ }
+ }
+ BLI_gset_free(data.collections_to_edit, NULL);
+ }
+
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+
+ if (!is_render) {
+ DEG_relations_tag_update(CTX_data_main(C));
+ }
+
+ WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_collection_enable(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Enable Collection";
- ot->idname = "OUTLINER_OT_collection_enable";
- ot->description = "Enable viewport drawing in the view layers";
+ /* identifiers */
+ ot->name = "Enable Collection";
+ ot->idname = "OUTLINER_OT_collection_enable";
+ ot->description = "Enable viewport drawing in the view layers";
- /* api callbacks */
- ot->exec = collection_flag_exec;
- ot->poll = collection_enable_poll;
+ /* api callbacks */
+ ot->exec = collection_flag_exec;
+ ot->poll = collection_enable_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void OUTLINER_OT_collection_disable(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Disable Collection";
- ot->idname = "OUTLINER_OT_collection_disable";
- ot->description = "Disable viewport drawing in the view layers";
+ /* identifiers */
+ ot->name = "Disable Collection";
+ ot->idname = "OUTLINER_OT_collection_disable";
+ ot->description = "Disable viewport drawing in the view layers";
- /* api callbacks */
- ot->exec = collection_flag_exec;
- ot->poll = collection_disable_poll;
+ /* api callbacks */
+ ot->exec = collection_flag_exec;
+ ot->poll = collection_disable_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void OUTLINER_OT_collection_enable_render(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Enable Collection in Render";
- ot->idname = "OUTLINER_OT_collection_enable_render";
- ot->description = "Render the collection";
+ /* identifiers */
+ ot->name = "Enable Collection in Render";
+ ot->idname = "OUTLINER_OT_collection_enable_render";
+ ot->description = "Render the collection";
- /* api callbacks */
- ot->exec = collection_flag_exec;
- ot->poll = collection_enable_render_poll;
+ /* api callbacks */
+ ot->exec = collection_flag_exec;
+ ot->poll = collection_enable_render_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void OUTLINER_OT_collection_disable_render(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Disable Collection in Render";
- ot->idname = "OUTLINER_OT_collection_disable_render";
- ot->description = "Do not render this collection";
+ /* identifiers */
+ ot->name = "Disable Collection in Render";
+ ot->idname = "OUTLINER_OT_collection_disable_render";
+ ot->description = "Do not render this collection";
- /* api callbacks */
- ot->exec = collection_flag_exec;
- ot->poll = collection_disable_render_poll;
+ /* api callbacks */
+ ot->exec = collection_flag_exec;
+ ot->poll = collection_disable_render_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
struct OutlinerHideEditData {
- Scene *scene;
- ViewLayer *view_layer;
- SpaceOutliner *soops;
- GSet *collections_to_edit;
- GSet *bases_to_edit;
+ Scene *scene;
+ ViewLayer *view_layer;
+ SpaceOutliner *soops;
+ GSet *collections_to_edit;
+ GSet *bases_to_edit;
};
static TreeTraversalAction outliner_hide_find_data_to_edit(TreeElement *te, void *customdata)
{
- struct OutlinerHideEditData *data = customdata;
- TreeStoreElem *tselem = TREESTORE(te);
+ struct OutlinerHideEditData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
- if (tselem == NULL) {
- return TRAVERSE_CONTINUE;
- }
+ if (tselem == NULL) {
+ return TRAVERSE_CONTINUE;
+ }
- if (tselem->type == TSE_LAYER_COLLECTION) {
- LayerCollection *lc = te->directdata;
+ if (tselem->type == TSE_LAYER_COLLECTION) {
+ LayerCollection *lc = te->directdata;
- if (lc->collection->flag & COLLECTION_IS_MASTER) {
- /* Skip - showing warning/error message might be misleading
- * when deleting multiple collections, so just do nothing. */
- }
- else {
- /* Delete, duplicate and link don't edit children,
- * those will come along with the parents. */
- BLI_gset_add(data->collections_to_edit, lc);
- }
- }
- else if (tselem->type == 0 && te->idcode == ID_OB) {
- Object *ob = (Object *)tselem->id;
- Base *base = BKE_view_layer_base_find(data->view_layer, ob);
- BLI_gset_add(data->bases_to_edit, base);
- }
+ if (lc->collection->flag & COLLECTION_IS_MASTER) {
+ /* Skip - showing warning/error message might be misleading
+ * when deleting multiple collections, so just do nothing. */
+ }
+ else {
+ /* Delete, duplicate and link don't edit children,
+ * those will come along with the parents. */
+ BLI_gset_add(data->collections_to_edit, lc);
+ }
+ }
+ else if (tselem->type == 0 && te->idcode == ID_OB) {
+ Object *ob = (Object *)tselem->id;
+ Base *base = BKE_view_layer_base_find(data->view_layer, ob);
+ BLI_gset_add(data->bases_to_edit, base);
+ }
- return TRAVERSE_CONTINUE;
+ return TRAVERSE_CONTINUE;
}
static int outliner_hide_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- struct OutlinerHideEditData data = {.scene = scene, .view_layer = view_layer, .soops = soops,};
- data.collections_to_edit = BLI_gset_ptr_new("outliner_hide_exec__collections_to_edit");
- data.bases_to_edit = BLI_gset_ptr_new("outliner_hide_exec__bases_to_edit");
-
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_hide_find_data_to_edit, &data);
-
- GSetIterator collections_to_edit_iter;
- GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
- LayerCollection *layer_collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
- BKE_layer_collection_set_visible(view_layer, layer_collection, false, false);
- }
- BLI_gset_free(data.collections_to_edit, NULL);
-
- GSetIterator bases_to_edit_iter;
- GSET_ITER(bases_to_edit_iter, data.bases_to_edit) {
- Base *base = BLI_gsetIterator_getKey(&bases_to_edit_iter);
- base->flag |= BASE_HIDDEN;
- }
- BLI_gset_free(data.bases_to_edit, NULL);
-
- BKE_layer_collection_sync(scene, view_layer);
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
-
- WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ struct OutlinerHideEditData data = {
+ .scene = scene,
+ .view_layer = view_layer,
+ .soops = soops,
+ };
+ data.collections_to_edit = BLI_gset_ptr_new("outliner_hide_exec__collections_to_edit");
+ data.bases_to_edit = BLI_gset_ptr_new("outliner_hide_exec__bases_to_edit");
+
+ outliner_tree_traverse(
+ soops, &soops->tree, 0, TSE_SELECTED, outliner_hide_find_data_to_edit, &data);
+
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER (collections_to_edit_iter, data.collections_to_edit) {
+ LayerCollection *layer_collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+ BKE_layer_collection_set_visible(view_layer, layer_collection, false, false);
+ }
+ BLI_gset_free(data.collections_to_edit, NULL);
+
+ GSetIterator bases_to_edit_iter;
+ GSET_ITER (bases_to_edit_iter, data.bases_to_edit) {
+ Base *base = BLI_gsetIterator_getKey(&bases_to_edit_iter);
+ base->flag |= BASE_HIDDEN;
+ }
+ BLI_gset_free(data.bases_to_edit, NULL);
+
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+
+ WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_hide(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide";
- ot->idname = "OUTLINER_OT_hide";
- ot->description = "Hide selected objects and collections";
+ /* identifiers */
+ ot->name = "Hide";
+ ot->idname = "OUTLINER_OT_hide";
+ ot->description = "Hide selected objects and collections";
- /* api callbacks */
- ot->exec = outliner_hide_exec;
- ot->poll = outliner_view_layer_collections_editor_poll;
+ /* api callbacks */
+ ot->exec = outliner_hide_exec;
+ ot->poll = outliner_view_layer_collections_editor_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int outliner_unhide_all_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
- /* 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_RESTRICT_VIEW;
- layer_collection_flag_recursive_set(lc_iter, LAYER_COLLECTION_RESTRICT_VIEW);
- }
+ /* 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_RESTRICT_VIEW;
+ layer_collection_flag_recursive_set(lc_iter, LAYER_COLLECTION_RESTRICT_VIEW);
+ }
- /* Unhide all objects. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- base->flag &= ~BASE_HIDDEN;
- }
+ /* Unhide all objects. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ base->flag &= ~BASE_HIDDEN;
+ }
- BKE_layer_collection_sync(scene, view_layer);
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
- WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
- return OPERATOR_FINISHED;
+ WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_unhide_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unhide All";
- ot->idname = "OUTLINER_OT_unhide_all";
- ot->description = "Unhide all objects and collections";
+ /* identifiers */
+ ot->name = "Unhide All";
+ ot->idname = "OUTLINER_OT_unhide_all";
+ ot->description = "Unhide all objects and collections";
- /* api callbacks */
- ot->exec = outliner_unhide_all_exec;
- ot->poll = outliner_view_layer_collections_editor_poll;
+ /* api callbacks */
+ ot->exec = outliner_unhide_all_exec;
+ ot->poll = outliner_view_layer_collections_editor_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/**
@@ -1385,13 +1443,14 @@ void OUTLINER_OT_unhide_all(wmOperatorType *ot)
*/
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);
+ 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 647fdeccb40..cff262698fa 100644
--- a/source/blender/editors/space_outliner/outliner_dragdrop.c
+++ b/source/blender/editors/space_outliner/outliner_dragdrop.c
@@ -69,948 +69,981 @@
/* ******************** Drop Target Find *********************** */
-static TreeElement *outliner_dropzone_element(TreeElement *te, const float fmval[2], const bool children)
+static TreeElement *outliner_dropzone_element(TreeElement *te,
+ const float fmval[2],
+ const bool children)
{
- if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) {
- /* name and first icon */
- if ((fmval[0] > te->xs + UI_UNIT_X) && (fmval[0] < te->xend)) {
- return te;
- }
- }
- /* Not it. Let's look at its children. */
- if (children && (TREESTORE(te)->flag & TSE_CLOSED) == 0 && (te->subtree.first)) {
- for (te = te->subtree.first; te; te = te->next) {
- TreeElement *te_valid = outliner_dropzone_element(te, fmval, children);
- if (te_valid) {
- return te_valid;
- }
- }
- }
- return NULL;
+ if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) {
+ /* name and first icon */
+ if ((fmval[0] > te->xs + UI_UNIT_X) && (fmval[0] < te->xend)) {
+ return te;
+ }
+ }
+ /* Not it. Let's look at its children. */
+ if (children && (TREESTORE(te)->flag & TSE_CLOSED) == 0 && (te->subtree.first)) {
+ for (te = te->subtree.first; te; te = te->next) {
+ TreeElement *te_valid = outliner_dropzone_element(te, fmval, children);
+ if (te_valid) {
+ return te_valid;
+ }
+ }
+ }
+ return NULL;
}
/* Find tree element to drop into. */
-static TreeElement *outliner_dropzone_find(const SpaceOutliner *soops, const float fmval[2], const bool children)
+static TreeElement *outliner_dropzone_find(const SpaceOutliner *soops,
+ const float fmval[2],
+ const bool children)
{
- TreeElement *te;
-
- for (te = soops->tree.first; te; te = te->next) {
- TreeElement *te_valid = outliner_dropzone_element(te, fmval, children);
- if (te_valid) {
- return te_valid;
- }
- }
- return NULL;
+ TreeElement *te;
+
+ for (te = soops->tree.first; te; te = te->next) {
+ TreeElement *te_valid = outliner_dropzone_element(te, fmval, children);
+ if (te_valid) {
+ return te_valid;
+ }
+ }
+ return NULL;
}
static TreeElement *outliner_drop_find(bContext *C, const wmEvent *event)
{
- ARegion *ar = 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]);
+ ARegion *ar = 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]);
- return outliner_dropzone_find(soops, fmval, true);
+ return outliner_dropzone_find(soops, fmval, true);
}
static ID *outliner_ID_drop_find(bContext *C, const wmEvent *event, short idcode)
{
- TreeElement *te = outliner_drop_find(C, event);
- TreeStoreElem *tselem = (te) ? TREESTORE(te) : NULL;
-
- if (te && te->idcode == idcode && tselem->type == 0) {
- return tselem->id;
- }
- else {
- return NULL;
- }
+ TreeElement *te = outliner_drop_find(C, event);
+ TreeStoreElem *tselem = (te) ? TREESTORE(te) : NULL;
+
+ if (te && te->idcode == idcode && tselem->type == 0) {
+ return tselem->id;
+ }
+ else {
+ return NULL;
+ }
}
/* Find tree element to drop into, with additional before and after reorder support. */
-static TreeElement *outliner_drop_insert_find(
- bContext *C, const wmEvent *event,
- TreeElementInsertType *r_insert_type)
+static TreeElement *outliner_drop_insert_find(bContext *C,
+ const wmEvent *event,
+ TreeElementInsertType *r_insert_type)
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- ARegion *ar = 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]);
- te_hovered = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]);
-
- if (te_hovered) {
- /* mouse hovers an element (ignoring x-axis), now find out how to insert the dragged item exactly */
- const float margin = UI_UNIT_Y * (1.0f / 4);
-
- if (view_mval[1] < (te_hovered->ys + margin)) {
- if (TSELEM_OPEN(TREESTORE(te_hovered), soops)) {
- /* inserting after a open item means we insert into it, but as first child */
- if (BLI_listbase_is_empty(&te_hovered->subtree)) {
- *r_insert_type = TE_INSERT_INTO;
- return te_hovered;
- }
- else {
- *r_insert_type = TE_INSERT_BEFORE;
- return te_hovered->subtree.first;
- }
- }
- else {
- *r_insert_type = TE_INSERT_AFTER;
- return te_hovered;
- }
- }
- else if (view_mval[1] > (te_hovered->ys + (3 * margin))) {
- *r_insert_type = TE_INSERT_BEFORE;
- return te_hovered;
- }
- else {
- *r_insert_type = TE_INSERT_INTO;
- return te_hovered;
- }
- }
- else {
- /* mouse doesn't hover any item (ignoring x-axis), so it's either above list bounds or below. */
- TreeElement *first = soops->tree.first;
- TreeElement *last = soops->tree.last;
-
- if (view_mval[1] < last->ys) {
- *r_insert_type = TE_INSERT_AFTER;
- return last;
- }
- else if (view_mval[1] > (first->ys + UI_UNIT_Y)) {
- *r_insert_type = TE_INSERT_BEFORE;
- return first;
- }
- else {
- BLI_assert(0);
- return NULL;
- }
- }
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ ARegion *ar = 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]);
+ te_hovered = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]);
+
+ if (te_hovered) {
+ /* mouse hovers an element (ignoring x-axis), now find out how to insert the dragged item exactly */
+ const float margin = UI_UNIT_Y * (1.0f / 4);
+
+ if (view_mval[1] < (te_hovered->ys + margin)) {
+ if (TSELEM_OPEN(TREESTORE(te_hovered), soops)) {
+ /* inserting after a open item means we insert into it, but as first child */
+ if (BLI_listbase_is_empty(&te_hovered->subtree)) {
+ *r_insert_type = TE_INSERT_INTO;
+ return te_hovered;
+ }
+ else {
+ *r_insert_type = TE_INSERT_BEFORE;
+ return te_hovered->subtree.first;
+ }
+ }
+ else {
+ *r_insert_type = TE_INSERT_AFTER;
+ return te_hovered;
+ }
+ }
+ else if (view_mval[1] > (te_hovered->ys + (3 * margin))) {
+ *r_insert_type = TE_INSERT_BEFORE;
+ return te_hovered;
+ }
+ else {
+ *r_insert_type = TE_INSERT_INTO;
+ return te_hovered;
+ }
+ }
+ else {
+ /* mouse doesn't hover any item (ignoring x-axis), so it's either above list bounds or below. */
+ TreeElement *first = soops->tree.first;
+ TreeElement *last = soops->tree.last;
+
+ if (view_mval[1] < last->ys) {
+ *r_insert_type = TE_INSERT_AFTER;
+ return last;
+ }
+ else if (view_mval[1] > (first->ys + UI_UNIT_Y)) {
+ *r_insert_type = TE_INSERT_BEFORE;
+ return first;
+ }
+ else {
+ BLI_assert(0);
+ return NULL;
+ }
+ }
}
-static Collection *outliner_collection_from_tree_element_and_parents(TreeElement *te, TreeElement **r_te)
+static Collection *outliner_collection_from_tree_element_and_parents(TreeElement *te,
+ TreeElement **r_te)
{
- while (te != NULL) {
- Collection *collection = outliner_collection_from_tree_element(te);
- if (collection) {
- *r_te = te;
- return collection;
- }
- te = te->parent;
- }
- return NULL;
+ while (te != NULL) {
+ Collection *collection = outliner_collection_from_tree_element(te);
+ if (collection) {
+ *r_te = te;
+ return collection;
+ }
+ te = te->parent;
+ }
+ return NULL;
}
-static TreeElement *outliner_drop_insert_collection_find(
- bContext *C, const wmEvent *event,
- TreeElementInsertType *r_insert_type)
+static TreeElement *outliner_drop_insert_collection_find(bContext *C,
+ const wmEvent *event,
+ TreeElementInsertType *r_insert_type)
{
- TreeElement *te = outliner_drop_insert_find(C, event, r_insert_type);
- if (!te) {
- return NULL;
- }
-
- TreeElement *collection_te;
- Collection *collection = outliner_collection_from_tree_element_and_parents(te, &collection_te);
- if (!collection) {
- return NULL;
- }
-
- if (collection_te != te) {
- *r_insert_type = TE_INSERT_INTO;
- }
-
- /* We can't insert before/after master collection. */
- if (collection->flag & COLLECTION_IS_MASTER) {
- *r_insert_type = TE_INSERT_INTO;
- }
-
- return collection_te;
+ TreeElement *te = outliner_drop_insert_find(C, event, r_insert_type);
+ if (!te) {
+ return NULL;
+ }
+
+ TreeElement *collection_te;
+ Collection *collection = outliner_collection_from_tree_element_and_parents(te, &collection_te);
+ if (!collection) {
+ return NULL;
+ }
+
+ if (collection_te != te) {
+ *r_insert_type = TE_INSERT_INTO;
+ }
+
+ /* We can't insert before/after master collection. */
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ *r_insert_type = TE_INSERT_INTO;
+ }
+
+ return collection_te;
}
/* ******************** Parent Drop Operator *********************** */
static bool parent_drop_allowed(SpaceOutliner *soops, TreeElement *te, Object *potential_child)
{
- TreeStoreElem *tselem = TREESTORE(te);
- if (te->idcode != ID_OB || tselem->type != 0) {
- return false;
- }
-
- Object *potential_parent = (Object *)tselem->id;
-
- if (potential_parent == potential_child) {
- return false;
- }
- if (BKE_object_is_child_recursive(potential_child, potential_parent)) {
- return false;
- }
- if (potential_parent == potential_child->parent) {
- return false;
- }
-
- /* check that parent/child are both in the same scene */
- Scene *scene = (Scene *)outliner_search_back(soops, 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)
- {
- if (BKE_view_layer_base_find(view_layer, potential_child)) {
- return true;
- }
- }
- return false;
- }
- else {
- return true;
- }
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (te->idcode != ID_OB || tselem->type != 0) {
+ return false;
+ }
+
+ Object *potential_parent = (Object *)tselem->id;
+
+ if (potential_parent == potential_child) {
+ return false;
+ }
+ if (BKE_object_is_child_recursive(potential_child, potential_parent)) {
+ return false;
+ }
+ if (potential_parent == potential_child->parent) {
+ return false;
+ }
+
+ /* check that parent/child are both in the same scene */
+ Scene *scene = (Scene *)outliner_search_back(soops, 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) {
+ if (BKE_view_layer_base_find(view_layer, potential_child)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ else {
+ return true;
+ }
}
static bool allow_parenting_without_modifier_key(SpaceOutliner *soops)
{
- switch (soops->outlinevis) {
- case SO_VIEW_LAYER:
- return soops->filter & SO_FILTER_NO_COLLECTION;
- case SO_SCENES:
- return true;
- default:
- return false;
- }
+ switch (soops->outlinevis) {
+ case SO_VIEW_LAYER:
+ return soops->filter & SO_FILTER_NO_COLLECTION;
+ case SO_SCENES:
+ return true;
+ default:
+ return false;
+ }
}
-static bool parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **UNUSED(tooltip))
+static bool parent_drop_poll(bContext *C,
+ wmDrag *drag,
+ const wmEvent *event,
+ const char **UNUSED(tooltip))
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
-
- bool changed = outliner_flag_set(&soops->tree, TSE_DRAG_ANY, false);
- if (changed) {
- ED_region_tag_redraw_no_rebuild(CTX_wm_region(C));
- }
-
- Object *potential_child = (Object *)WM_drag_ID(drag, ID_OB);
- if (!potential_child) {
- return false;
- }
-
- if (!allow_parenting_without_modifier_key(soops)) {
- if (!event->shift) {
- return false;
- }
- }
-
- TreeElement *te = outliner_drop_find(C, event);
- if (!te) {
- return false;
- }
-
- if (parent_drop_allowed(soops, te, potential_child)) {
- TREESTORE(te)->flag |= TSE_DRAG_INTO;
- ED_region_tag_redraw_no_rebuild(CTX_wm_region(C));
- return true;
- }
-
- return false;
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+
+ bool changed = outliner_flag_set(&soops->tree, TSE_DRAG_ANY, false);
+ if (changed) {
+ ED_region_tag_redraw_no_rebuild(CTX_wm_region(C));
+ }
+
+ Object *potential_child = (Object *)WM_drag_ID(drag, ID_OB);
+ if (!potential_child) {
+ return false;
+ }
+
+ if (!allow_parenting_without_modifier_key(soops)) {
+ if (!event->shift) {
+ return false;
+ }
+ }
+
+ TreeElement *te = outliner_drop_find(C, event);
+ if (!te) {
+ return false;
+ }
+
+ if (parent_drop_allowed(soops, te, potential_child)) {
+ TREESTORE(te)->flag |= TSE_DRAG_INTO;
+ ED_region_tag_redraw_no_rebuild(CTX_wm_region(C));
+ return true;
+ }
+
+ return false;
}
static int parent_drop_exec(bContext *C, wmOperator *op)
{
- Object *par = NULL, *ob = NULL;
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- int partype = -1;
- char parname[MAX_NAME], childname[MAX_NAME];
-
- partype = RNA_enum_get(op->ptr, "type");
- RNA_string_get(op->ptr, "parent", parname);
- par = (Object *)BKE_libblock_find_name(bmain, ID_OB, parname);
- RNA_string_get(op->ptr, "child", childname);
- ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, childname);
-
- if (ID_IS_LINKED(ob)) {
- BKE_report(op->reports, RPT_INFO, "Can't edit library linked object");
- return OPERATOR_CANCELLED;
- }
-
- ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL);
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
-
- return OPERATOR_FINISHED;
+ Object *par = NULL, *ob = NULL;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ int partype = -1;
+ char parname[MAX_NAME], childname[MAX_NAME];
+
+ partype = RNA_enum_get(op->ptr, "type");
+ RNA_string_get(op->ptr, "parent", parname);
+ par = (Object *)BKE_libblock_find_name(bmain, ID_OB, parname);
+ RNA_string_get(op->ptr, "child", childname);
+ ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, childname);
+
+ if (ID_IS_LINKED(ob)) {
+ BKE_report(op->reports, RPT_INFO, "Can't edit library linked object");
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL);
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
+
+ return OPERATOR_FINISHED;
}
static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Main *bmain = CTX_data_main(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- TreeElement *te = outliner_drop_find(C, event);
- TreeStoreElem *tselem = te ? TREESTORE(te) : NULL;
-
- if (!(te && te->idcode == ID_OB && tselem->type == 0)) {
- return OPERATOR_CANCELLED;
- }
-
- Object *par = (Object *)tselem->id;
- Object *ob = (Object *)WM_drag_ID_from_event(event, ID_OB);
-
- if (ELEM(NULL, ob, par)) {
- return OPERATOR_CANCELLED;
- }
- if (ob == par) {
- return OPERATOR_CANCELLED;
- }
- if (ID_IS_LINKED(ob)) {
- BKE_report(op->reports, RPT_INFO, "Can't edit library linked object");
- return OPERATOR_CANCELLED;
- }
-
- char childname[MAX_NAME];
- char parname[MAX_NAME];
- STRNCPY(childname, ob->id.name + 2);
- STRNCPY(parname, par->id.name + 2);
- RNA_string_set(op->ptr, "child", childname);
- RNA_string_set(op->ptr, "parent", parname);
-
- Scene *scene = (Scene *)outliner_search_back(soops, te, ID_SCE);
-
- if (scene == NULL) {
- /* currently outlier 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)
- */
-
- scene = CTX_data_scene(C);
- }
-
- if ((par->type != OB_ARMATURE) && (par->type != OB_CURVE) && (par->type != OB_LATTICE)) {
- int partype = 0;
- if (ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL)) {
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
- }
- }
- else {
- /* Menu creation */
- wmOperatorType *ot = WM_operatortype_find("OUTLINER_OT_parent_drop", false);
- uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Set Parent To"), ICON_NONE);
- uiLayout *layout = UI_popup_menu_layout(pup);
- PointerRNA ptr;
-
- /* Cannot use uiItemEnumO()... have multiple properties to set. */
- uiItemFullO_ptr(layout, ot, IFACE_("Object"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- RNA_string_set(&ptr, "parent", parname);
- RNA_string_set(&ptr, "child", childname);
- RNA_enum_set(&ptr, "type", PAR_OBJECT);
-
- /* par becomes parent, make the associated menus */
- if (par->type == OB_ARMATURE) {
- uiItemFullO_ptr(layout, ot, IFACE_("Armature Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- RNA_string_set(&ptr, "parent", parname);
- RNA_string_set(&ptr, "child", childname);
- RNA_enum_set(&ptr, "type", PAR_ARMATURE);
-
- uiItemFullO_ptr(layout, ot, IFACE_(" With Empty Groups"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- RNA_string_set(&ptr, "parent", parname);
- RNA_string_set(&ptr, "child", childname);
- RNA_enum_set(&ptr, "type", PAR_ARMATURE_NAME);
-
- uiItemFullO_ptr(layout, ot, IFACE_(" With Envelope Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- RNA_string_set(&ptr, "parent", parname);
- RNA_string_set(&ptr, "child", childname);
- RNA_enum_set(&ptr, "type", PAR_ARMATURE_ENVELOPE);
-
- uiItemFullO_ptr(layout, ot, IFACE_(" With Automatic Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- RNA_string_set(&ptr, "parent", parname);
- RNA_string_set(&ptr, "child", childname);
- RNA_enum_set(&ptr, "type", PAR_ARMATURE_AUTO);
-
- uiItemFullO_ptr(layout, ot, IFACE_("Bone"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- RNA_string_set(&ptr, "parent", parname);
- RNA_string_set(&ptr, "child", childname);
- RNA_enum_set(&ptr, "type", PAR_BONE);
- }
- else if (par->type == OB_CURVE) {
- uiItemFullO_ptr(layout, ot, IFACE_("Curve Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- RNA_string_set(&ptr, "parent", parname);
- RNA_string_set(&ptr, "child", childname);
- RNA_enum_set(&ptr, "type", PAR_CURVE);
-
- uiItemFullO_ptr(layout, ot, IFACE_("Follow Path"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- RNA_string_set(&ptr, "parent", parname);
- RNA_string_set(&ptr, "child", childname);
- RNA_enum_set(&ptr, "type", PAR_FOLLOW);
-
- uiItemFullO_ptr(layout, ot, IFACE_("Path Constraint"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- RNA_string_set(&ptr, "parent", parname);
- RNA_string_set(&ptr, "child", childname);
- RNA_enum_set(&ptr, "type", PAR_PATH_CONST);
- }
- else if (par->type == OB_LATTICE) {
- uiItemFullO_ptr(layout, ot, IFACE_("Lattice Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- RNA_string_set(&ptr, "parent", parname);
- RNA_string_set(&ptr, "child", childname);
- RNA_enum_set(&ptr, "type", PAR_LATTICE);
- }
-
- UI_popup_menu_end(C, pup);
-
- return OPERATOR_INTERFACE;
- }
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ TreeElement *te = outliner_drop_find(C, event);
+ TreeStoreElem *tselem = te ? TREESTORE(te) : NULL;
+
+ if (!(te && te->idcode == ID_OB && tselem->type == 0)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ Object *par = (Object *)tselem->id;
+ Object *ob = (Object *)WM_drag_ID_from_event(event, ID_OB);
+
+ if (ELEM(NULL, ob, par)) {
+ return OPERATOR_CANCELLED;
+ }
+ if (ob == par) {
+ return OPERATOR_CANCELLED;
+ }
+ if (ID_IS_LINKED(ob)) {
+ BKE_report(op->reports, RPT_INFO, "Can't edit library linked object");
+ return OPERATOR_CANCELLED;
+ }
+
+ char childname[MAX_NAME];
+ char parname[MAX_NAME];
+ STRNCPY(childname, ob->id.name + 2);
+ STRNCPY(parname, par->id.name + 2);
+ RNA_string_set(op->ptr, "child", childname);
+ RNA_string_set(op->ptr, "parent", parname);
+
+ Scene *scene = (Scene *)outliner_search_back(soops, te, ID_SCE);
+
+ if (scene == NULL) {
+ /* currently outlier 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)
+ */
+
+ scene = CTX_data_scene(C);
+ }
+
+ if ((par->type != OB_ARMATURE) && (par->type != OB_CURVE) && (par->type != OB_LATTICE)) {
+ int partype = 0;
+ if (ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL)) {
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
+ }
+ }
+ else {
+ /* Menu creation */
+ wmOperatorType *ot = WM_operatortype_find("OUTLINER_OT_parent_drop", false);
+ uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Set Parent To"), ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+ PointerRNA ptr;
+
+ /* Cannot use uiItemEnumO()... have multiple properties to set. */
+ uiItemFullO_ptr(layout, ot, IFACE_("Object"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "parent", parname);
+ RNA_string_set(&ptr, "child", childname);
+ RNA_enum_set(&ptr, "type", PAR_OBJECT);
+
+ /* par becomes parent, make the associated menus */
+ if (par->type == OB_ARMATURE) {
+ uiItemFullO_ptr(layout, ot, IFACE_("Armature Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "parent", parname);
+ RNA_string_set(&ptr, "child", childname);
+ RNA_enum_set(&ptr, "type", PAR_ARMATURE);
+
+ uiItemFullO_ptr(
+ layout, ot, IFACE_(" With Empty Groups"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "parent", parname);
+ RNA_string_set(&ptr, "child", childname);
+ RNA_enum_set(&ptr, "type", PAR_ARMATURE_NAME);
+
+ uiItemFullO_ptr(
+ layout, ot, IFACE_(" With Envelope Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "parent", parname);
+ RNA_string_set(&ptr, "child", childname);
+ RNA_enum_set(&ptr, "type", PAR_ARMATURE_ENVELOPE);
+
+ uiItemFullO_ptr(
+ layout, ot, IFACE_(" With Automatic Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "parent", parname);
+ RNA_string_set(&ptr, "child", childname);
+ RNA_enum_set(&ptr, "type", PAR_ARMATURE_AUTO);
+
+ uiItemFullO_ptr(layout, ot, IFACE_("Bone"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "parent", parname);
+ RNA_string_set(&ptr, "child", childname);
+ RNA_enum_set(&ptr, "type", PAR_BONE);
+ }
+ else if (par->type == OB_CURVE) {
+ uiItemFullO_ptr(layout, ot, IFACE_("Curve Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "parent", parname);
+ RNA_string_set(&ptr, "child", childname);
+ RNA_enum_set(&ptr, "type", PAR_CURVE);
+
+ uiItemFullO_ptr(layout, ot, IFACE_("Follow Path"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "parent", parname);
+ RNA_string_set(&ptr, "child", childname);
+ RNA_enum_set(&ptr, "type", PAR_FOLLOW);
+
+ uiItemFullO_ptr(layout, ot, IFACE_("Path Constraint"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "parent", parname);
+ RNA_string_set(&ptr, "child", childname);
+ RNA_enum_set(&ptr, "type", PAR_PATH_CONST);
+ }
+ else if (par->type == OB_LATTICE) {
+ uiItemFullO_ptr(layout, ot, IFACE_("Lattice Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "parent", parname);
+ RNA_string_set(&ptr, "child", childname);
+ RNA_enum_set(&ptr, "type", PAR_LATTICE);
+ }
+
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
+ }
+
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_parent_drop(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Drop to Set Parent";
- ot->description = "Drag to parent in Outliner";
- ot->idname = "OUTLINER_OT_parent_drop";
+ /* identifiers */
+ ot->name = "Drop to Set Parent";
+ ot->description = "Drag to parent in Outliner";
+ ot->idname = "OUTLINER_OT_parent_drop";
- /* api callbacks */
- ot->invoke = parent_drop_invoke;
- ot->exec = parent_drop_exec;
+ /* api callbacks */
+ ot->invoke = parent_drop_invoke;
+ ot->exec = parent_drop_exec;
- ot->poll = ED_operator_outliner_active;
+ ot->poll = ED_operator_outliner_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- /* properties */
- RNA_def_string(ot->srna, "child", "Object", MAX_NAME, "Child", "Child Object");
- RNA_def_string(ot->srna, "parent", "Object", MAX_NAME, "Parent", "Parent Object");
- RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
+ /* properties */
+ RNA_def_string(ot->srna, "child", "Object", MAX_NAME, "Child", "Child Object");
+ RNA_def_string(ot->srna, "parent", "Object", MAX_NAME, "Parent", "Parent Object");
+ RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
}
/* ******************** Parent Clear Operator *********************** */
-static bool parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **UNUSED(tooltip))
+static bool parent_clear_poll(bContext *C,
+ wmDrag *drag,
+ const wmEvent *event,
+ const char **UNUSED(tooltip))
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
-
- if (!allow_parenting_without_modifier_key(soops)) {
- if (!event->shift) {
- return false;
- }
- }
-
- Object *ob = (Object *)WM_drag_ID(drag, ID_OB);
- if (!ob) {
- return false;
- }
- if (!ob->parent) {
- return false;
- }
-
- TreeElement *te = outliner_drop_find(C, event);
- if (te) {
- TreeStoreElem *tselem = TREESTORE(te);
- ID *id = tselem->id;
- if (!id) {
- return true;
- }
-
- switch (GS(id->name)) {
- case ID_OB:
- return ELEM(tselem->type, TSE_MODIFIER_BASE, TSE_CONSTRAINT_BASE);
- case ID_GR:
- return event->shift;
- default:
- return true;
- }
- }
- else {
- return true;
- }
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+
+ if (!allow_parenting_without_modifier_key(soops)) {
+ if (!event->shift) {
+ return false;
+ }
+ }
+
+ Object *ob = (Object *)WM_drag_ID(drag, ID_OB);
+ if (!ob) {
+ return false;
+ }
+ if (!ob->parent) {
+ return false;
+ }
+
+ TreeElement *te = outliner_drop_find(C, event);
+ if (te) {
+ TreeStoreElem *tselem = TREESTORE(te);
+ ID *id = tselem->id;
+ if (!id) {
+ return true;
+ }
+
+ switch (GS(id->name)) {
+ case ID_OB:
+ return ELEM(tselem->type, TSE_MODIFIER_BASE, TSE_CONSTRAINT_BASE);
+ case ID_GR:
+ return event->shift;
+ default:
+ return true;
+ }
+ }
+ else {
+ return true;
+ }
}
static int parent_clear_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = (Object *)WM_drag_ID_from_event(event, ID_OB);
+ Main *bmain = CTX_data_main(C);
+ Object *ob = (Object *)WM_drag_ID_from_event(event, ID_OB);
- if (ob == NULL) {
- return OPERATOR_CANCELLED;
- }
+ if (ob == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- ED_object_parent_clear(ob, 0);
+ ED_object_parent_clear(ob, 0);
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
- return OPERATOR_FINISHED;
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_parent_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Drop to Clear Parent";
- ot->description = "Drag to clear parent in Outliner";
- ot->idname = "OUTLINER_OT_parent_clear";
+ /* identifiers */
+ ot->name = "Drop to Clear Parent";
+ ot->description = "Drag to clear parent in Outliner";
+ ot->idname = "OUTLINER_OT_parent_clear";
- /* api callbacks */
- ot->invoke = parent_clear_invoke;
+ /* api callbacks */
+ ot->invoke = parent_clear_invoke;
- ot->poll = ED_operator_outliner_active;
+ ot->poll = ED_operator_outliner_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
/* ******************** Scene Drop Operator *********************** */
-static bool scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **UNUSED(tooltip))
+static bool scene_drop_poll(bContext *C,
+ wmDrag *drag,
+ const wmEvent *event,
+ const char **UNUSED(tooltip))
{
- /* Ensure item under cursor is valid drop target */
- Object *ob = (Object *)WM_drag_ID(drag, ID_OB);
- return (ob && (outliner_ID_drop_find(C, event, ID_SCE) != NULL));
+ /* Ensure item under cursor is valid drop target */
+ Object *ob = (Object *)WM_drag_ID(drag, ID_OB);
+ return (ob && (outliner_ID_drop_find(C, event, ID_SCE) != NULL));
}
static int scene_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = (Scene *)outliner_ID_drop_find(C, event, ID_SCE);
- Object *ob = (Object *)WM_drag_ID_from_event(event, ID_OB);
-
- if (ELEM(NULL, ob, scene) || ID_IS_LINKED(scene)) {
- return OPERATOR_CANCELLED;
- }
-
- if (BKE_scene_has_object(scene, ob)) {
- return OPERATOR_CANCELLED;
- }
-
- Collection *collection;
- if (scene != CTX_data_scene(C)) {
- /* when linking to an inactive scene link to the master collection */
- collection = BKE_collection_master(scene);
- }
- else {
- collection = CTX_data_collection(C);
- }
-
- BKE_collection_object_add(bmain, collection, ob);
-
- for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
- Base *base = BKE_view_layer_base_find(view_layer, ob);
- if (base) {
- ED_object_base_select(base, BA_SELECT);
- }
- }
-
- DEG_relations_tag_update(bmain);
-
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = (Scene *)outliner_ID_drop_find(C, event, ID_SCE);
+ Object *ob = (Object *)WM_drag_ID_from_event(event, ID_OB);
+
+ if (ELEM(NULL, ob, scene) || ID_IS_LINKED(scene)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (BKE_scene_has_object(scene, ob)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ Collection *collection;
+ if (scene != CTX_data_scene(C)) {
+ /* when linking to an inactive scene link to the master collection */
+ collection = BKE_collection_master(scene);
+ }
+ else {
+ collection = CTX_data_collection(C);
+ }
+
+ BKE_collection_object_add(bmain, collection, ob);
+
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer;
+ view_layer = view_layer->next) {
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+ if (base) {
+ ED_object_base_select(base, BA_SELECT);
+ }
+ }
+
+ DEG_relations_tag_update(bmain);
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_scene_drop(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Drop Object to Scene";
- ot->description = "Drag object to scene in Outliner";
- ot->idname = "OUTLINER_OT_scene_drop";
+ /* identifiers */
+ ot->name = "Drop Object to Scene";
+ ot->description = "Drag object to scene in Outliner";
+ ot->idname = "OUTLINER_OT_scene_drop";
- /* api callbacks */
- ot->invoke = scene_drop_invoke;
+ /* api callbacks */
+ ot->invoke = scene_drop_invoke;
- ot->poll = ED_operator_outliner_active;
+ ot->poll = ED_operator_outliner_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
/* ******************** Material Drop Operator *********************** */
-static bool material_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **UNUSED(tooltip))
+static bool material_drop_poll(bContext *C,
+ wmDrag *drag,
+ const wmEvent *event,
+ const char **UNUSED(tooltip))
{
- /* Ensure item under cursor is valid drop target */
- Material *ma = (Material *)WM_drag_ID(drag, ID_MA);
- return (ma && (outliner_ID_drop_find(C, event, ID_OB) != NULL));
+ /* Ensure item under cursor is valid drop target */
+ Material *ma = (Material *)WM_drag_ID(drag, ID_MA);
+ return (ma && (outliner_ID_drop_find(C, event, ID_OB) != NULL));
}
static int material_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = (Object *)outliner_ID_drop_find(C, event, ID_OB);
- Material *ma = (Material *)WM_drag_ID_from_event(event, ID_MA);
+ Main *bmain = CTX_data_main(C);
+ Object *ob = (Object *)outliner_ID_drop_find(C, event, ID_OB);
+ Material *ma = (Material *)WM_drag_ID_from_event(event, ID_MA);
- if (ELEM(NULL, ob, ma)) {
- return OPERATOR_CANCELLED;
- }
+ if (ELEM(NULL, ob, ma)) {
+ return OPERATOR_CANCELLED;
+ }
- /* only drop grease pencil material on grease pencil objects */
- if ((ma->gp_style != NULL) && (ob->type != OB_GPENCIL)) {
- return OPERATOR_CANCELLED;
- }
+ /* only drop grease pencil material on grease pencil objects */
+ if ((ma->gp_style != NULL) && (ob->type != OB_GPENCIL)) {
+ return OPERATOR_CANCELLED;
+ }
- assign_material(bmain, ob, ma, ob->totcol + 1, BKE_MAT_ASSIGN_USERPREF);
+ assign_material(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);
+ 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);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_material_drop(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Drop Material on Object";
- ot->description = "Drag material to object in Outliner";
- ot->idname = "OUTLINER_OT_material_drop";
+ /* identifiers */
+ ot->name = "Drop Material on Object";
+ ot->description = "Drag material to object in Outliner";
+ ot->idname = "OUTLINER_OT_material_drop";
- /* api callbacks */
- ot->invoke = material_drop_invoke;
+ /* api callbacks */
+ ot->invoke = material_drop_invoke;
- ot->poll = ED_operator_outliner_active;
+ ot->poll = ED_operator_outliner_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
/* ******************** Collection Drop Operator *********************** */
typedef struct CollectionDrop {
- Collection *from;
- Collection *to;
+ Collection *from;
+ Collection *to;
- TreeElement *te;
- TreeElementInsertType insert_type;
+ TreeElement *te;
+ TreeElementInsertType insert_type;
} CollectionDrop;
static Collection *collection_parent_from_ID(ID *id)
{
- /* Can't change linked parent collections. */
- if (!id || ID_IS_LINKED(id)) {
- return NULL;
- }
-
- /* Also support dropping into/from scene collection. */
- if (GS(id->name) == ID_SCE) {
- return ((Scene *)id)->master_collection;
- }
- else if (GS(id->name) == ID_GR) {
- return (Collection *)id;
- }
-
- return NULL;
+ /* Can't change linked parent collections. */
+ if (!id || ID_IS_LINKED(id)) {
+ return NULL;
+ }
+
+ /* Also support dropping into/from scene collection. */
+ if (GS(id->name) == ID_SCE) {
+ return ((Scene *)id)->master_collection;
+ }
+ else if (GS(id->name) == ID_GR) {
+ return (Collection *)id;
+ }
+
+ return NULL;
}
-static bool collection_drop_init(bContext *C, wmDrag *drag, const wmEvent *event, CollectionDrop *data)
+static bool collection_drop_init(bContext *C,
+ wmDrag *drag,
+ const wmEvent *event,
+ CollectionDrop *data)
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
-
- /* Get collection to drop into. */
- TreeElementInsertType insert_type;
- TreeElement *te = outliner_drop_insert_collection_find(C, event, &insert_type);
- if (!te) {
- return false;
- }
-
- Collection *to_collection = outliner_collection_from_tree_element(te);
- if (ID_IS_LINKED(to_collection)) {
- return false;
- }
-
- /* Get drag datablocks. */
- if (drag->type != WM_DRAG_ID) {
- return false;
- }
-
- wmDragID *drag_id = drag->ids.first;
- if (drag_id == NULL) {
- return false;
- }
-
- ID *id = drag_id->id;
- if (!(id && ELEM(GS(id->name), ID_GR, ID_OB))) {
- return false;
- }
-
- /* Get collection to drag out of. */
- ID *parent = drag_id->from_parent;
- Collection *from_collection = collection_parent_from_ID(parent);
- if (event->ctrl || soops->outlinevis == SO_SCENES) {
- from_collection = NULL;
- }
-
- /* Get collections. */
- if (GS(id->name) == ID_GR) {
- if (id == &to_collection->id) {
- return false;
- }
- }
- else {
- insert_type = TE_INSERT_INTO;
- }
-
- data->from = from_collection;
- data->to = to_collection;
- data->te = te;
- data->insert_type = insert_type;
-
- return true;
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+
+ /* Get collection to drop into. */
+ TreeElementInsertType insert_type;
+ TreeElement *te = outliner_drop_insert_collection_find(C, event, &insert_type);
+ if (!te) {
+ return false;
+ }
+
+ Collection *to_collection = outliner_collection_from_tree_element(te);
+ if (ID_IS_LINKED(to_collection)) {
+ return false;
+ }
+
+ /* Get drag datablocks. */
+ if (drag->type != WM_DRAG_ID) {
+ return false;
+ }
+
+ wmDragID *drag_id = drag->ids.first;
+ if (drag_id == NULL) {
+ return false;
+ }
+
+ ID *id = drag_id->id;
+ if (!(id && ELEM(GS(id->name), ID_GR, ID_OB))) {
+ return false;
+ }
+
+ /* Get collection to drag out of. */
+ ID *parent = drag_id->from_parent;
+ Collection *from_collection = collection_parent_from_ID(parent);
+ if (event->ctrl || soops->outlinevis == SO_SCENES) {
+ from_collection = NULL;
+ }
+
+ /* Get collections. */
+ if (GS(id->name) == ID_GR) {
+ if (id == &to_collection->id) {
+ return false;
+ }
+ }
+ else {
+ insert_type = TE_INSERT_INTO;
+ }
+
+ data->from = from_collection;
+ data->to = to_collection;
+ data->te = te;
+ data->insert_type = insert_type;
+
+ return true;
}
-static bool collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **tooltip)
+static bool collection_drop_poll(bContext *C,
+ wmDrag *drag,
+ const wmEvent *event,
+ const char **tooltip)
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
- bool changed = outliner_flag_set(&soops->tree, TSE_HIGHLIGHTED | TSE_DRAG_ANY, false);
-
- CollectionDrop data;
- if (!event->shift && collection_drop_init(C, drag, event, &data)) {
- TreeElement *te = data.te;
- TreeStoreElem *tselem = TREESTORE(te);
- if (!data.from || event->ctrl) {
- tselem->flag |= TSE_DRAG_INTO;
- changed = true;
- *tooltip = IFACE_("Link inside Collection");
- }
- else {
- switch (data.insert_type) {
- case TE_INSERT_BEFORE:
- tselem->flag |= TSE_DRAG_BEFORE;
- changed = true;
- if (te->prev && outliner_is_collection_tree_element(te->prev)) {
- *tooltip = TIP_("Move between collections");
- }
- else {
- *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");
- }
- else {
- *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)");
- break;
- }
- }
- if (changed) {
- ED_region_tag_redraw_no_rebuild(ar);
- }
- return true;
- }
- else {
- if (changed) {
- ED_region_tag_redraw_no_rebuild(ar);
- }
- return false;
- }
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ ARegion *ar = CTX_wm_region(C);
+ bool changed = outliner_flag_set(&soops->tree, TSE_HIGHLIGHTED | TSE_DRAG_ANY, false);
+
+ CollectionDrop data;
+ if (!event->shift && collection_drop_init(C, drag, event, &data)) {
+ TreeElement *te = data.te;
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (!data.from || event->ctrl) {
+ tselem->flag |= TSE_DRAG_INTO;
+ changed = true;
+ *tooltip = IFACE_("Link inside Collection");
+ }
+ else {
+ switch (data.insert_type) {
+ case TE_INSERT_BEFORE:
+ tselem->flag |= TSE_DRAG_BEFORE;
+ changed = true;
+ if (te->prev && outliner_is_collection_tree_element(te->prev)) {
+ *tooltip = TIP_("Move between collections");
+ }
+ else {
+ *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");
+ }
+ else {
+ *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)");
+ break;
+ }
+ }
+ if (changed) {
+ ED_region_tag_redraw_no_rebuild(ar);
+ }
+ return true;
+ }
+ else {
+ if (changed) {
+ ED_region_tag_redraw_no_rebuild(ar);
+ }
+ return false;
+ }
}
static int collection_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
-
- if (event->custom != EVT_DATA_DRAGDROP) {
- return OPERATOR_CANCELLED;
- }
-
- ListBase *lb = event->customdata;
- wmDrag *drag = lb->first;
-
- CollectionDrop data;
- if (!collection_drop_init(C, drag, event, &data)) {
- return OPERATOR_CANCELLED;
- }
-
- /* Before/after insert handling. */
- Collection *relative = NULL;
- bool relative_after = false;
-
- if (ELEM(data.insert_type, TE_INSERT_BEFORE, TE_INSERT_AFTER)) {
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
-
- relative = data.to;
- relative_after = (data.insert_type == TE_INSERT_AFTER);
-
- TreeElement *parent_te = outliner_find_parent_element(&soops->tree, NULL, data.te);
- data.to = (parent_te) ? outliner_collection_from_tree_element(parent_te) : NULL;
- }
-
- if (!data.to) {
- return OPERATOR_CANCELLED;
- }
-
- if (BKE_collection_is_empty(data.to)) {
- TREESTORE(data.te)->flag &= ~TSE_CLOSED;
- }
-
- for (wmDragID *drag_id = drag->ids.first; drag_id; drag_id = drag_id->next) {
- /* 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);
-
- if (GS(drag_id->id->name) == ID_OB) {
- /* Move/link object into collection. */
- Object *object = (Object *)drag_id->id;
-
- if (from) {
- BKE_collection_object_move(bmain, scene, data.to, from, object);
- }
- else {
- BKE_collection_object_add(bmain, data.to, object);
- }
- }
- else if (GS(drag_id->id->name) == ID_GR) {
- /* Move/link collection into collection. */
- Collection *collection = (Collection *)drag_id->id;
-
- if (collection != from) {
- BKE_collection_move(bmain, data.to, from, relative, relative_after, collection);
- }
- }
-
- if (from) {
- DEG_id_tag_update(&from->id, ID_RECALC_COPY_ON_WRITE);
- }
- }
-
- /* Update dependency graph. */
- DEG_id_tag_update(&data.to->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+
+ if (event->custom != EVT_DATA_DRAGDROP) {
+ return OPERATOR_CANCELLED;
+ }
+
+ ListBase *lb = event->customdata;
+ wmDrag *drag = lb->first;
+
+ CollectionDrop data;
+ if (!collection_drop_init(C, drag, event, &data)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Before/after insert handling. */
+ Collection *relative = NULL;
+ bool relative_after = false;
+
+ if (ELEM(data.insert_type, TE_INSERT_BEFORE, TE_INSERT_AFTER)) {
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+
+ relative = data.to;
+ relative_after = (data.insert_type == TE_INSERT_AFTER);
+
+ TreeElement *parent_te = outliner_find_parent_element(&soops->tree, NULL, data.te);
+ data.to = (parent_te) ? outliner_collection_from_tree_element(parent_te) : NULL;
+ }
+
+ if (!data.to) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (BKE_collection_is_empty(data.to)) {
+ TREESTORE(data.te)->flag &= ~TSE_CLOSED;
+ }
+
+ for (wmDragID *drag_id = drag->ids.first; drag_id; drag_id = drag_id->next) {
+ /* 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);
+
+ if (GS(drag_id->id->name) == ID_OB) {
+ /* Move/link object into collection. */
+ Object *object = (Object *)drag_id->id;
+
+ if (from) {
+ BKE_collection_object_move(bmain, scene, data.to, from, object);
+ }
+ else {
+ BKE_collection_object_add(bmain, data.to, object);
+ }
+ }
+ else if (GS(drag_id->id->name) == ID_GR) {
+ /* Move/link collection into collection. */
+ Collection *collection = (Collection *)drag_id->id;
+
+ if (collection != from) {
+ BKE_collection_move(bmain, data.to, from, relative, relative_after, collection);
+ }
+ }
+
+ if (from) {
+ DEG_id_tag_update(&from->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ }
+
+ /* Update dependency graph. */
+ DEG_id_tag_update(&data.to->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_collection_drop(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move to Collection";
- ot->description = "Drag to move to collection in Outliner";
- ot->idname = "OUTLINER_OT_collection_drop";
+ /* identifiers */
+ ot->name = "Move to Collection";
+ ot->description = "Drag to move to collection in Outliner";
+ ot->idname = "OUTLINER_OT_collection_drop";
- /* api callbacks */
- ot->invoke = collection_drop_invoke;
- ot->poll = ED_operator_outliner_active;
+ /* api callbacks */
+ ot->invoke = collection_drop_invoke;
+ ot->poll = ED_operator_outliner_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
/* ********************* Outliner Drag Operator ******************** */
-static TreeElement *outliner_item_drag_element_find(SpaceOutliner *soops, ARegion *ar, const wmEvent *event)
+static TreeElement *outliner_item_drag_element_find(SpaceOutliner *soops,
+ ARegion *ar,
+ 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]);
- return outliner_find_item_at_y(soops, &soops->tree, my);
+ /* 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]);
+ return outliner_find_item_at_y(soops, &soops->tree, my);
}
-static int outliner_item_drag_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+static int outliner_item_drag_drop_invoke(bContext *C,
+ wmOperator *UNUSED(op),
+ const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- TreeElement *te = outliner_item_drag_element_find(soops, ar, event);
-
- if (!te) {
- return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
- }
-
- TreeElementIcon data = tree_element_get_icon(TREESTORE(te), te);
- if (!data.drag_id) {
- return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
- }
-
- wmDrag *drag = WM_event_start_drag(C, data.icon, WM_DRAG_ID, NULL, 0.0, WM_DRAG_NOP);
-
- if (ELEM(GS(data.drag_id->name), ID_OB, ID_GR)) {
- /* For collections and objects we cheat and drag all selected. */
-
- /* Only drag element under mouse if it was not selected before. */
- if ((TREESTORE(te)->flag & TSE_SELECTED) == 0) {
- outliner_flag_set(&soops->tree, TSE_SELECTED, 0);
- TREESTORE(te)->flag |= TSE_SELECTED;
- }
-
- /* Gather all selected elements. */
- struct IDsSelectedData selected = {
- .selected_array = {NULL, NULL},
- };
-
- if (GS(data.drag_id->name) == ID_OB) {
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &selected);
- }
- else {
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_collections, &selected);
- }
-
- LISTBASE_FOREACH (LinkData *, link, &selected.selected_array) {
- TreeElement *te_selected = (TreeElement *)link->data;
- ID *id;
-
- if (GS(data.drag_id->name) == ID_OB) {
- id = TREESTORE(te_selected)->id;
- }
- else {
- /* Keep collection hierarchies intact when dragging. */
- bool parent_selected = false;
- for (TreeElement *te_parent = te_selected->parent; te_parent; te_parent = te_parent->parent) {
- if (outliner_is_collection_tree_element(te_parent)) {
- if (TREESTORE(te_parent)->flag & TSE_SELECTED) {
- parent_selected = true;
- break;
- }
- }
- }
-
- if (parent_selected) {
- continue;
- }
-
- id = &outliner_collection_from_tree_element(te_selected)->id;
- }
-
- /* Find parent collection. */
- Collection *parent = NULL;
-
- if (te_selected->parent) {
- for (TreeElement *te_parent = te_selected->parent; te_parent; te_parent = te_parent->parent) {
- if (outliner_is_collection_tree_element(te_parent)) {
- parent = outliner_collection_from_tree_element(te_parent);
- break;
- }
- }
- }
- else {
- Scene *scene = CTX_data_scene(C);
- parent = BKE_collection_master(scene);
- }
-
- WM_drag_add_ID(drag, id, &parent->id);
- }
-
- BLI_freelistN(&selected.selected_array);
- }
- else {
- /* Add single ID. */
- WM_drag_add_ID(drag, data.drag_id, data.drag_parent);
- }
-
- return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ TreeElement *te = outliner_item_drag_element_find(soops, ar, event);
+
+ if (!te) {
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+ TreeElementIcon data = tree_element_get_icon(TREESTORE(te), te);
+ if (!data.drag_id) {
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+ wmDrag *drag = WM_event_start_drag(C, data.icon, WM_DRAG_ID, NULL, 0.0, WM_DRAG_NOP);
+
+ if (ELEM(GS(data.drag_id->name), ID_OB, ID_GR)) {
+ /* For collections and objects we cheat and drag all selected. */
+
+ /* Only drag element under mouse if it was not selected before. */
+ if ((TREESTORE(te)->flag & TSE_SELECTED) == 0) {
+ outliner_flag_set(&soops->tree, TSE_SELECTED, 0);
+ TREESTORE(te)->flag |= TSE_SELECTED;
+ }
+
+ /* Gather all selected elements. */
+ struct IDsSelectedData selected = {
+ .selected_array = {NULL, NULL},
+ };
+
+ if (GS(data.drag_id->name) == ID_OB) {
+ outliner_tree_traverse(
+ soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &selected);
+ }
+ else {
+ outliner_tree_traverse(
+ soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_collections, &selected);
+ }
+
+ LISTBASE_FOREACH (LinkData *, link, &selected.selected_array) {
+ TreeElement *te_selected = (TreeElement *)link->data;
+ ID *id;
+
+ if (GS(data.drag_id->name) == ID_OB) {
+ id = TREESTORE(te_selected)->id;
+ }
+ else {
+ /* Keep collection hierarchies intact when dragging. */
+ bool parent_selected = false;
+ for (TreeElement *te_parent = te_selected->parent; te_parent;
+ te_parent = te_parent->parent) {
+ if (outliner_is_collection_tree_element(te_parent)) {
+ if (TREESTORE(te_parent)->flag & TSE_SELECTED) {
+ parent_selected = true;
+ break;
+ }
+ }
+ }
+
+ if (parent_selected) {
+ continue;
+ }
+
+ id = &outliner_collection_from_tree_element(te_selected)->id;
+ }
+
+ /* Find parent collection. */
+ Collection *parent = NULL;
+
+ if (te_selected->parent) {
+ for (TreeElement *te_parent = te_selected->parent; te_parent;
+ te_parent = te_parent->parent) {
+ if (outliner_is_collection_tree_element(te_parent)) {
+ parent = outliner_collection_from_tree_element(te_parent);
+ break;
+ }
+ }
+ }
+ else {
+ Scene *scene = CTX_data_scene(C);
+ parent = BKE_collection_master(scene);
+ }
+
+ WM_drag_add_ID(drag, id, &parent->id);
+ }
+
+ BLI_freelistN(&selected.selected_array);
+ }
+ else {
+ /* Add single ID. */
+ WM_drag_add_ID(drag, data.drag_id, data.drag_parent);
+ }
+
+ return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
}
/* Outliner drag and drop. This operator mostly exists to support dragging
@@ -1019,12 +1052,12 @@ static int outliner_item_drag_drop_invoke(bContext *C, wmOperator *UNUSED(op), c
void OUTLINER_OT_item_drag_drop(wmOperatorType *ot)
{
- ot->name = "Drag and Drop";
- ot->idname = "OUTLINER_OT_item_drag_drop";
- ot->description = "Drag and drop element to another place";
+ ot->name = "Drag and Drop";
+ ot->idname = "OUTLINER_OT_item_drag_drop";
+ ot->description = "Drag and drop element to another place";
- ot->invoke = outliner_item_drag_drop_invoke;
- ot->poll = ED_operator_outliner_active;
+ ot->invoke = outliner_item_drag_drop_invoke;
+ ot->poll = ED_operator_outliner_active;
}
/* *************************** Drop Boxes ************************** */
@@ -1032,11 +1065,11 @@ void OUTLINER_OT_item_drag_drop(wmOperatorType *ot)
/* region dropbox definition */
void outliner_dropboxes(void)
{
- ListBase *lb = WM_dropboxmap_find("Outliner", SPACE_OUTLINER, RGN_TYPE_WINDOW);
+ ListBase *lb = WM_dropboxmap_find("Outliner", SPACE_OUTLINER, RGN_TYPE_WINDOW);
- WM_dropbox_add(lb, "OUTLINER_OT_parent_drop", parent_drop_poll, NULL);
- WM_dropbox_add(lb, "OUTLINER_OT_parent_clear", parent_clear_poll, NULL);
- WM_dropbox_add(lb, "OUTLINER_OT_scene_drop", scene_drop_poll, NULL);
- WM_dropbox_add(lb, "OUTLINER_OT_material_drop", material_drop_poll, NULL);
- WM_dropbox_add(lb, "OUTLINER_OT_collection_drop", collection_drop_poll, NULL);
+ WM_dropbox_add(lb, "OUTLINER_OT_parent_drop", parent_drop_poll, NULL);
+ WM_dropbox_add(lb, "OUTLINER_OT_parent_clear", parent_clear_poll, NULL);
+ WM_dropbox_add(lb, "OUTLINER_OT_scene_drop", scene_drop_poll, NULL);
+ WM_dropbox_add(lb, "OUTLINER_OT_material_drop", material_drop_poll, NULL);
+ WM_dropbox_add(lb, "OUTLINER_OT_collection_drop", collection_drop_poll, NULL);
}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index ff0b9d8a55f..2d33c5db49d 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -84,56 +84,56 @@
static void outliner_height(SpaceOutliner *soops, ListBase *lb, int *h)
{
- TreeElement *te = lb->first;
- while (te) {
- TreeStoreElem *tselem = TREESTORE(te);
- if (TSELEM_OPEN(tselem, soops)) {
- outliner_height(soops, &te->subtree, h);
- }
- (*h) += UI_UNIT_Y;
- te = te->next;
- }
+ TreeElement *te = lb->first;
+ while (te) {
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (TSELEM_OPEN(tselem, soops)) {
+ outliner_height(soops, &te->subtree, h);
+ }
+ (*h) += UI_UNIT_Y;
+ te = te->next;
+ }
}
#if 0 // XXX this is currently disabled until te->xend is set correctly
static void outliner_width(SpaceOutliner *soops, ListBase *lb, int *w)
{
- TreeElement *te = lb->first;
- while (te) {
-// TreeStoreElem *tselem = TREESTORE(te);
-
- // XXX fixme... te->xend is not set yet
- if (!TSELEM_OPEN(tselem, soops)) {
- if (te->xend > *w)
- *w = te->xend;
- }
- outliner_width(soops, &te->subtree, w);
- te = te->next;
- }
+ TreeElement *te = lb->first;
+ while (te) {
+// TreeStoreElem *tselem = TREESTORE(te);
+
+ // XXX fixme... te->xend is not set yet
+ if (!TSELEM_OPEN(tselem, soops)) {
+ if (te->xend > *w)
+ *w = te->xend;
+ }
+ outliner_width(soops, &te->subtree, w);
+ te = te->next;
+ }
}
#endif
static void outliner_rna_width(SpaceOutliner *soops, ListBase *lb, int *w, int startx)
{
- TreeElement *te = lb->first;
- while (te) {
- TreeStoreElem *tselem = TREESTORE(te);
- // XXX fixme... (currently, we're using a fixed length of 100)!
+ TreeElement *te = lb->first;
+ while (te) {
+ TreeStoreElem *tselem = TREESTORE(te);
+ // XXX fixme... (currently, we're using a fixed length of 100)!
#if 0
- if (te->xend) {
- if (te->xend > *w)
- *w = te->xend;
- }
+ if (te->xend) {
+ if (te->xend > *w)
+ *w = te->xend;
+ }
#endif
- if (startx + 100 > *w) {
- *w = startx + 100;
- }
-
- if (TSELEM_OPEN(tselem, soops)) {
- outliner_rna_width(soops, &te->subtree, w, startx + UI_UNIT_X);
- }
- te = te->next;
- }
+ if (startx + 100 > *w) {
+ *w = startx + 100;
+ }
+
+ if (TSELEM_OPEN(tselem, soops)) {
+ outliner_rna_width(soops, &te->subtree, w, startx + UI_UNIT_X);
+ }
+ te = te->next;
+ }
}
/**
@@ -141,830 +141,1092 @@ static void outliner_rna_width(SpaceOutliner *soops, ListBase *lb, int *w, int s
*/
static bool is_object_data_in_editmode(const ID *id, const Object *obact)
{
- const short id_type = GS(id->name);
- return (
- (obact && (obact->mode & OB_MODE_EDIT)) &&
- (id && OB_DATA_SUPPORT_EDITMODE(id_type)) &&
- (GS(((ID *)obact->data)->name) == id_type) &&
- BKE_object_data_is_in_editmode(id)
- );
+ const short id_type = GS(id->name);
+ return ((obact && (obact->mode & OB_MODE_EDIT)) && (id && OB_DATA_SUPPORT_EDITMODE(id_type)) &&
+ (GS(((ID *)obact->data)->name) == id_type) && BKE_object_data_is_in_editmode(id));
}
/* ****************************************************** */
-static void restrictbutton_recursive_ebone(bContext *C, EditBone *ebone_parent, int flag, bool set_flag)
+static void restrictbutton_recursive_ebone(bContext *C,
+ EditBone *ebone_parent,
+ int flag,
+ bool set_flag)
{
- Object *obedit = CTX_data_edit_object(C);
- bArmature *arm = obedit->data;
- EditBone *ebone;
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (ED_armature_ebone_is_child_recursive(ebone_parent, ebone)) {
- if (set_flag) {
- ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
- ebone->flag |= flag;
- }
- else {
- ebone->flag &= ~flag;
- }
- }
- }
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm = obedit->data;
+ EditBone *ebone;
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ED_armature_ebone_is_child_recursive(ebone_parent, ebone)) {
+ if (set_flag) {
+ ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ ebone->flag |= flag;
+ }
+ else {
+ ebone->flag &= ~flag;
+ }
+ }
+ }
}
static void restrictbutton_recursive_bone(Bone *bone_parent, int flag, bool set_flag)
{
- Bone *bone;
- for (bone = bone_parent->childbase.first; bone; bone = bone->next) {
- if (set_flag) {
- bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
- bone->flag |= flag;
- }
- else {
- bone->flag &= ~flag;
- }
- restrictbutton_recursive_bone(bone, flag, set_flag);
- }
-
+ Bone *bone;
+ for (bone = bone_parent->childbase.first; bone; bone = bone->next) {
+ if (set_flag) {
+ bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ bone->flag |= flag;
+ }
+ else {
+ bone->flag &= ~flag;
+ }
+ restrictbutton_recursive_bone(bone, flag, set_flag);
+ }
}
static void restrictbutton_r_lay_cb(bContext *C, void *poin, void *UNUSED(poin2))
{
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, poin);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, poin);
}
static void restrictbutton_bone_visibility_cb(bContext *C, void *UNUSED(poin), void *poin2)
{
- Bone *bone = (Bone *)poin2;
- if (bone->flag & BONE_HIDDEN_P) {
- bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
+ Bone *bone = (Bone *)poin2;
+ if (bone->flag & BONE_HIDDEN_P) {
+ bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
- if (CTX_wm_window(C)->eventstate->ctrl) {
- restrictbutton_recursive_bone(bone, BONE_HIDDEN_P, (bone->flag & BONE_HIDDEN_P) != 0);
- }
+ if (CTX_wm_window(C)->eventstate->ctrl) {
+ restrictbutton_recursive_bone(bone, BONE_HIDDEN_P, (bone->flag & BONE_HIDDEN_P) != 0);
+ }
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
}
static void restrictbutton_bone_select_cb(bContext *C, void *UNUSED(poin), void *poin2)
{
- Bone *bone = (Bone *)poin2;
- if (bone->flag & BONE_UNSELECTABLE) {
- bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
+ Bone *bone = (Bone *)poin2;
+ if (bone->flag & BONE_UNSELECTABLE) {
+ bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
- if (CTX_wm_window(C)->eventstate->ctrl) {
- restrictbutton_recursive_bone(bone, BONE_UNSELECTABLE, (bone->flag & BONE_UNSELECTABLE) != 0);
- }
+ if (CTX_wm_window(C)->eventstate->ctrl) {
+ restrictbutton_recursive_bone(bone, BONE_UNSELECTABLE, (bone->flag & BONE_UNSELECTABLE) != 0);
+ }
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
}
static void restrictbutton_ebone_select_cb(bContext *C, void *UNUSED(poin), void *poin2)
{
- EditBone *ebone = (EditBone *)poin2;
+ EditBone *ebone = (EditBone *)poin2;
- if (ebone->flag & BONE_UNSELECTABLE) {
- ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
+ if (ebone->flag & BONE_UNSELECTABLE) {
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
- if (CTX_wm_window(C)->eventstate->ctrl) {
- restrictbutton_recursive_ebone(C, ebone, BONE_UNSELECTABLE, (ebone->flag & BONE_UNSELECTABLE) != 0);
- }
+ if (CTX_wm_window(C)->eventstate->ctrl) {
+ restrictbutton_recursive_ebone(
+ C, ebone, BONE_UNSELECTABLE, (ebone->flag & BONE_UNSELECTABLE) != 0);
+ }
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
}
static void restrictbutton_ebone_visibility_cb(bContext *C, void *UNUSED(poin), void *poin2)
{
- EditBone *ebone = (EditBone *)poin2;
- if (ebone->flag & BONE_HIDDEN_A) {
- ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
+ EditBone *ebone = (EditBone *)poin2;
+ if (ebone->flag & BONE_HIDDEN_A) {
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
- if (CTX_wm_window(C)->eventstate->ctrl) {
- restrictbutton_recursive_ebone(C, ebone, BONE_HIDDEN_A, (ebone->flag & BONE_HIDDEN_A) != 0);
- }
+ if (CTX_wm_window(C)->eventstate->ctrl) {
+ restrictbutton_recursive_ebone(C, ebone, BONE_HIDDEN_A, (ebone->flag & BONE_HIDDEN_A) != 0);
+ }
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
}
static void restrictbutton_gp_layer_flag_cb(bContext *C, void *poin, void *UNUSED(poin2))
{
- ID *id = (ID *)poin;
+ ID *id = (ID *)poin;
- DEG_id_tag_update(id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ DEG_id_tag_update(id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void *UNUSED(poin2))
{
- ID *id = (ID *)poin;
+ ID *id = (ID *)poin;
- BLI_assert(id != NULL);
+ BLI_assert(id != NULL);
- if (id->flag & LIB_FAKEUSER) {
- id_us_plus(id);
- }
- else {
- id_us_min(id);
- }
+ if (id->flag & LIB_FAKEUSER) {
+ id_us_plus(id);
+ }
+ else {
+ id_us_min(id);
+ }
}
static int base_pushed_state_cb(bContext *UNUSED(C), void *poin)
{
- Base *base = poin;
- Object *ob = base->object;
+ Base *base = poin;
+ Object *ob = base->object;
- const bool is_visible = ((base->flag & BASE_HIDDEN) == 0) &&
- ((ob->restrictflag & OB_RESTRICT_VIEW) == 0);
- return !is_visible;
+ const bool is_visible = ((base->flag & BASE_HIDDEN) == 0) &&
+ ((ob->restrictflag & OB_RESTRICT_VIEW) == 0);
+ return !is_visible;
}
static void hidebutton_base_flag_cb(bContext *C, void *poin, void *poin2)
{
- wmWindow *win = CTX_wm_window(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = poin;
- Base *base = poin2;
- Object *ob = base->object;
- bool do_disable = (CTX_wm_window(C)->eventstate->alt != 0);
- bool do_isolate = (win->eventstate->ctrl != 0) && !do_disable;
- bool extend = (win->eventstate->shift != 0);
- bool depsgraph_changed = false;
- const bool is_linked = ID_IS_LINKED(ob);
-
- if (do_disable) {
- if (!is_linked) {
- ob->restrictflag |= OB_RESTRICT_VIEW;
- depsgraph_changed = true;
- }
- }
- else if (do_isolate) {
- depsgraph_changed = (!is_linked) && ((ob->restrictflag & OB_RESTRICT_VIEW) != 0);
-
- if (!extend) {
- /* Make only one base visible. */
- for (Base *other = view_layer->object_bases.first; other; other = other->next) {
- other->flag |= BASE_HIDDEN;
- }
-
- base->flag &= ~BASE_HIDDEN;
- }
- else {
- /* Toggle visibility of one base. */
- base->flag ^= BASE_HIDDEN;
- }
-
- if (!is_linked) {
- ob->restrictflag &= ~OB_RESTRICT_VIEW;
- }
- }
- else if (ob->restrictflag & OB_RESTRICT_VIEW) {
- if (!is_linked) {
- ob->restrictflag &= ~OB_RESTRICT_VIEW;
- base->flag &= ~BASE_HIDDEN;
- }
- depsgraph_changed = true;
- }
- else {
- base->flag ^= BASE_HIDDEN;
- }
-
- if (depsgraph_changed) {
- BKE_main_collection_sync_remap(bmain);
- DEG_id_tag_update(&ob->id, LIB_TAG_COPIED_ON_WRITE);
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, &ob->id);
- }
-
- if (!do_disable) {
- BKE_layer_collection_sync(scene, view_layer);
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
+ wmWindow *win = CTX_wm_window(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = poin;
+ Base *base = poin2;
+ Object *ob = base->object;
+ bool do_disable = (CTX_wm_window(C)->eventstate->alt != 0);
+ bool do_isolate = (win->eventstate->ctrl != 0) && !do_disable;
+ bool extend = (win->eventstate->shift != 0);
+ bool depsgraph_changed = false;
+ const bool is_linked = ID_IS_LINKED(ob);
+
+ if (do_disable) {
+ if (!is_linked) {
+ ob->restrictflag |= OB_RESTRICT_VIEW;
+ depsgraph_changed = true;
+ }
+ }
+ else if (do_isolate) {
+ depsgraph_changed = (!is_linked) && ((ob->restrictflag & OB_RESTRICT_VIEW) != 0);
+
+ if (!extend) {
+ /* Make only one base visible. */
+ for (Base *other = view_layer->object_bases.first; other; other = other->next) {
+ other->flag |= BASE_HIDDEN;
+ }
+
+ base->flag &= ~BASE_HIDDEN;
+ }
+ else {
+ /* Toggle visibility of one base. */
+ base->flag ^= BASE_HIDDEN;
+ }
+
+ if (!is_linked) {
+ ob->restrictflag &= ~OB_RESTRICT_VIEW;
+ }
+ }
+ else if (ob->restrictflag & OB_RESTRICT_VIEW) {
+ if (!is_linked) {
+ ob->restrictflag &= ~OB_RESTRICT_VIEW;
+ base->flag &= ~BASE_HIDDEN;
+ }
+ depsgraph_changed = true;
+ }
+ else {
+ base->flag ^= BASE_HIDDEN;
+ }
+
+ if (depsgraph_changed) {
+ BKE_main_collection_sync_remap(bmain);
+ DEG_id_tag_update(&ob->id, LIB_TAG_COPIED_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, &ob->id);
+ }
+
+ if (!do_disable) {
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ }
}
static int layer_collection_pushed_state_cb(bContext *UNUSED(C), void *poin)
{
- LayerCollection *lc = poin;
- Collection *collection = lc->collection;
+ LayerCollection *lc = poin;
+ Collection *collection = lc->collection;
- const bool is_visible = ((lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) == 0) &&
- ((collection->flag & COLLECTION_RESTRICT_VIEW) == 0);
- return !is_visible;
+ const bool is_visible = ((lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) == 0) &&
+ ((collection->flag & COLLECTION_RESTRICT_VIEW) == 0);
+ return !is_visible;
}
static void hidebutton_layer_collection_flag_cb(bContext *C, void *poin, void *poin2)
{
- Main *bmain = CTX_data_main(C);
- wmWindow *win = CTX_wm_window(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = poin;
- LayerCollection *lc = poin2;
- Collection *collection = lc->collection;
- bool do_disable = (win->eventstate->alt != 0);
- bool do_isolate = (win->eventstate->ctrl != 0) && !do_disable;
- bool extend = (win->eventstate->shift != 0);
- bool depsgraph_changed = false;
-
- if (do_disable) {
- if (!ID_IS_LINKED(collection)) {
- collection->flag |= COLLECTION_RESTRICT_VIEW;
- depsgraph_changed = true;
- }
- }
- else if (do_isolate) {
- depsgraph_changed |= BKE_layer_collection_isolate(scene, view_layer, lc, extend);
- }
- else {
- bool make_visible = ((lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) != 0) ||
- ((collection->flag & COLLECTION_RESTRICT_VIEW) != 0);
- depsgraph_changed |= BKE_layer_collection_set_visible(view_layer, lc, make_visible, extend);
- }
-
- BKE_layer_collection_sync(scene, view_layer);
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
-
- if (depsgraph_changed) {
- BKE_main_collection_sync_remap(bmain);
- DEG_relations_tag_update(bmain);
- }
- WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
+ Main *bmain = CTX_data_main(C);
+ wmWindow *win = CTX_wm_window(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = poin;
+ LayerCollection *lc = poin2;
+ Collection *collection = lc->collection;
+ bool do_disable = (win->eventstate->alt != 0);
+ bool do_isolate = (win->eventstate->ctrl != 0) && !do_disable;
+ bool extend = (win->eventstate->shift != 0);
+ bool depsgraph_changed = false;
+
+ if (do_disable) {
+ if (!ID_IS_LINKED(collection)) {
+ collection->flag |= COLLECTION_RESTRICT_VIEW;
+ depsgraph_changed = true;
+ }
+ }
+ else if (do_isolate) {
+ depsgraph_changed |= BKE_layer_collection_isolate(scene, view_layer, lc, extend);
+ }
+ else {
+ bool make_visible = ((lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) != 0) ||
+ ((collection->flag & COLLECTION_RESTRICT_VIEW) != 0);
+ depsgraph_changed |= BKE_layer_collection_set_visible(view_layer, lc, make_visible, extend);
+ }
+
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+
+ if (depsgraph_changed) {
+ BKE_main_collection_sync_remap(bmain);
+ DEG_relations_tag_update(bmain);
+ }
+ WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
}
static void namebutton_cb(bContext *C, void *tsep, char *oldname)
{
- Main *bmain = CTX_data_main(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- Object *obedit = CTX_data_edit_object(C);
- BLI_mempool *ts = soops->treestore;
- TreeStoreElem *tselem = tsep;
-
- if (ts && tselem) {
- TreeElement *te = outliner_find_tree_element(&soops->tree, tselem);
-
- if (tselem->type == 0) {
- BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
-
- switch (GS(tselem->id->name)) {
- case ID_MA:
- WM_event_add_notifier(C, NC_MATERIAL, NULL); break;
- case ID_TE:
- WM_event_add_notifier(C, NC_TEXTURE, NULL); break;
- case ID_IM:
- WM_event_add_notifier(C, NC_IMAGE, NULL); break;
- case ID_SCE:
- WM_event_add_notifier(C, NC_SCENE, NULL); break;
- case ID_OB:
- {
- Object *ob = (Object *)tselem->id;
- if (ob->type == OB_MBALL) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL); break;
- }
- default:
- WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL); break;
- }
- /* Check the library target exists */
- if (te->idcode == ID_LI) {
- Library *lib = (Library *)tselem->id;
- char expanded[FILE_MAX];
-
- BKE_library_filepath_set(bmain, lib, lib->name);
-
- BLI_strncpy(expanded, lib->name, sizeof(expanded));
- BLI_path_abs(expanded, BKE_main_blendfile_path(bmain));
- if (!BLI_exists(expanded)) {
- BKE_reportf(CTX_wm_reports(C), RPT_ERROR,
- "Library path '%s' does not exist, correct this before saving", expanded);
- }
- else if (lib->id.tag & LIB_TAG_MISSING) {
- BKE_reportf(CTX_wm_reports(C), RPT_INFO,
- "Library path '%s' is now valid, please reload the library", expanded);
- lib->id.tag &= ~LIB_TAG_MISSING;
- }
- }
- }
- else {
- switch (tselem->type) {
- case TSE_DEFGROUP:
- defgroup_unique_name(te->directdata, (Object *)tselem->id); // id = object
- break;
- case TSE_NLA_ACTION:
- BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
- break;
- case TSE_EBONE:
- {
- bArmature *arm = (bArmature *)tselem->id;
- if (arm->edbo) {
- EditBone *ebone = te->directdata;
- char newname[sizeof(ebone->name)];
-
- /* restore bone name */
- BLI_strncpy(newname, ebone->name, sizeof(ebone->name));
- BLI_strncpy(ebone->name, oldname, sizeof(ebone->name));
- ED_armature_bone_rename(bmain, obedit->data, oldname, newname);
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
- }
- break;
- }
-
- case TSE_BONE:
- {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Scene *scene = CTX_data_scene(C);
- bArmature *arm = (bArmature *)tselem->id;
- Bone *bone = te->directdata;
- char newname[sizeof(bone->name)];
-
- /* always make current object active */
- tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NORMAL, true);
-
- /* restore bone name */
- BLI_strncpy(newname, bone->name, sizeof(bone->name));
- BLI_strncpy(bone->name, oldname, sizeof(bone->name));
- ED_armature_bone_rename(bmain, arm, oldname, newname);
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
- break;
- }
- case TSE_POSE_CHANNEL:
- {
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = (Object *)tselem->id;
- bPoseChannel *pchan = te->directdata;
- char newname[sizeof(pchan->name)];
-
- /* always make current pose-bone active */
- tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NORMAL, true);
-
- BLI_assert(ob->type == OB_ARMATURE);
-
- /* restore bone name */
- BLI_strncpy(newname, pchan->name, sizeof(pchan->name));
- BLI_strncpy(pchan->name, oldname, sizeof(pchan->name));
- ED_armature_bone_rename(bmain, ob->data, oldname, newname);
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
- break;
- }
- case TSE_POSEGRP:
- {
- Object *ob = (Object *)tselem->id; // id = object
- bActionGroup *grp = te->directdata;
-
- BLI_uniquename(&ob->pose->agroups, grp, CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "Group"), '.',
- offsetof(bActionGroup, name), sizeof(grp->name));
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
- break;
- }
- case TSE_GP_LAYER:
- {
- bGPdata *gpd = (bGPdata *)tselem->id; /* id = GP Datablock */
- bGPDlayer *gpl = te->directdata;
-
- /* always make layer active */
- BKE_gpencil_layer_setactive(gpd, gpl);
-
- // XXX: name needs translation stuff
- BLI_uniquename(&gpd->layers, gpl, "GP Layer", '.',
- offsetof(bGPDlayer, info), sizeof(gpl->info));
-
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, gpd);
- break;
- }
- case TSE_R_LAYER:
- {
- Scene *scene = (Scene *)tselem->id;
- ViewLayer *view_layer = te->directdata;
-
- /* Restore old name. */
- char newname[sizeof(view_layer->name)];
- BLI_strncpy(newname, view_layer->name, sizeof(view_layer->name));
- BLI_strncpy(view_layer->name, oldname, sizeof(view_layer->name));
-
- /* Rename, preserving animation and compositing data. */
- BKE_view_layer_rename(bmain, scene, view_layer, newname);
- WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL);
- break;
- }
- case TSE_LAYER_COLLECTION:
- {
- BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
- WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL);
- break;
- }
- }
- }
- tselem->flag &= ~TSE_TEXTBUT;
- }
+ Main *bmain = CTX_data_main(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ Object *obedit = CTX_data_edit_object(C);
+ BLI_mempool *ts = soops->treestore;
+ TreeStoreElem *tselem = tsep;
+
+ if (ts && tselem) {
+ TreeElement *te = outliner_find_tree_element(&soops->tree, tselem);
+
+ if (tselem->type == 0) {
+ BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
+
+ switch (GS(tselem->id->name)) {
+ case ID_MA:
+ WM_event_add_notifier(C, NC_MATERIAL, NULL);
+ break;
+ case ID_TE:
+ WM_event_add_notifier(C, NC_TEXTURE, NULL);
+ break;
+ case ID_IM:
+ WM_event_add_notifier(C, NC_IMAGE, NULL);
+ break;
+ case ID_SCE:
+ WM_event_add_notifier(C, NC_SCENE, NULL);
+ break;
+ case ID_OB: {
+ Object *ob = (Object *)tselem->id;
+ if (ob->type == OB_MBALL) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL);
+ break;
+ }
+ default:
+ WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL);
+ break;
+ }
+ /* Check the library target exists */
+ if (te->idcode == ID_LI) {
+ Library *lib = (Library *)tselem->id;
+ char expanded[FILE_MAX];
+
+ BKE_library_filepath_set(bmain, lib, lib->name);
+
+ BLI_strncpy(expanded, lib->name, sizeof(expanded));
+ BLI_path_abs(expanded, BKE_main_blendfile_path(bmain));
+ if (!BLI_exists(expanded)) {
+ BKE_reportf(CTX_wm_reports(C),
+ RPT_ERROR,
+ "Library path '%s' does not exist, correct this before saving",
+ expanded);
+ }
+ else if (lib->id.tag & LIB_TAG_MISSING) {
+ BKE_reportf(CTX_wm_reports(C),
+ RPT_INFO,
+ "Library path '%s' is now valid, please reload the library",
+ expanded);
+ lib->id.tag &= ~LIB_TAG_MISSING;
+ }
+ }
+ }
+ else {
+ switch (tselem->type) {
+ case TSE_DEFGROUP:
+ defgroup_unique_name(te->directdata, (Object *)tselem->id); // id = object
+ break;
+ case TSE_NLA_ACTION:
+ BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
+ break;
+ case TSE_EBONE: {
+ bArmature *arm = (bArmature *)tselem->id;
+ if (arm->edbo) {
+ EditBone *ebone = te->directdata;
+ char newname[sizeof(ebone->name)];
+
+ /* restore bone name */
+ BLI_strncpy(newname, ebone->name, sizeof(ebone->name));
+ BLI_strncpy(ebone->name, oldname, sizeof(ebone->name));
+ ED_armature_bone_rename(bmain, obedit->data, oldname, newname);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+ }
+ break;
+ }
+
+ case TSE_BONE: {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Scene *scene = CTX_data_scene(C);
+ bArmature *arm = (bArmature *)tselem->id;
+ Bone *bone = te->directdata;
+ char newname[sizeof(bone->name)];
+
+ /* always make current object active */
+ tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NORMAL, true);
+
+ /* restore bone name */
+ BLI_strncpy(newname, bone->name, sizeof(bone->name));
+ BLI_strncpy(bone->name, oldname, sizeof(bone->name));
+ ED_armature_bone_rename(bmain, arm, oldname, newname);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+ break;
+ }
+ case TSE_POSE_CHANNEL: {
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = (Object *)tselem->id;
+ bPoseChannel *pchan = te->directdata;
+ char newname[sizeof(pchan->name)];
+
+ /* always make current pose-bone active */
+ tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NORMAL, true);
+
+ BLI_assert(ob->type == OB_ARMATURE);
+
+ /* restore bone name */
+ BLI_strncpy(newname, pchan->name, sizeof(pchan->name));
+ BLI_strncpy(pchan->name, oldname, sizeof(pchan->name));
+ ED_armature_bone_rename(bmain, ob->data, oldname, newname);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+ break;
+ }
+ case TSE_POSEGRP: {
+ Object *ob = (Object *)tselem->id; // id = object
+ bActionGroup *grp = te->directdata;
+
+ BLI_uniquename(&ob->pose->agroups,
+ grp,
+ CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "Group"),
+ '.',
+ offsetof(bActionGroup, name),
+ sizeof(grp->name));
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ break;
+ }
+ case TSE_GP_LAYER: {
+ bGPdata *gpd = (bGPdata *)tselem->id; /* id = GP Datablock */
+ bGPDlayer *gpl = te->directdata;
+
+ /* always make layer active */
+ BKE_gpencil_layer_setactive(gpd, gpl);
+
+ // XXX: name needs translation stuff
+ BLI_uniquename(
+ &gpd->layers, gpl, "GP Layer", '.', offsetof(bGPDlayer, info), sizeof(gpl->info));
+
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, gpd);
+ break;
+ }
+ case TSE_R_LAYER: {
+ Scene *scene = (Scene *)tselem->id;
+ ViewLayer *view_layer = te->directdata;
+
+ /* Restore old name. */
+ char newname[sizeof(view_layer->name)];
+ BLI_strncpy(newname, view_layer->name, sizeof(view_layer->name));
+ BLI_strncpy(view_layer->name, oldname, sizeof(view_layer->name));
+
+ /* Rename, preserving animation and compositing data. */
+ BKE_view_layer_rename(bmain, scene, view_layer, newname);
+ WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL);
+ break;
+ }
+ case TSE_LAYER_COLLECTION: {
+ BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
+ WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL);
+ break;
+ }
+ }
+ }
+ tselem->flag &= ~TSE_TEXTBUT;
+ }
}
-static void outliner_draw_restrictbuts(
- uiBlock *block, Scene *scene, ViewLayer *view_layer, ARegion *ar, SpaceOutliner *soops, ListBase *lb)
+static void outliner_draw_restrictbuts(uiBlock *block,
+ Scene *scene,
+ ViewLayer *view_layer,
+ ARegion *ar,
+ SpaceOutliner *soops,
+ ListBase *lb)
{
- /* Get RNA properties (once for speed). */
- static struct RestrictProperties {
- bool initialized;
-
- PropertyRNA *object_hide_viewport, *object_hide_select, *object_hide_render;
- PropertyRNA *collection_hide_viewport, *collection_hide_select, *collection_hide_render;
- PropertyRNA *modifier_show_viewport, *modifier_show_render;
- } props = {false};
-
- if (!props.initialized) {
- props.object_hide_viewport = RNA_struct_type_find_property(&RNA_Object, "hide_viewport");
- props.object_hide_select = RNA_struct_type_find_property(&RNA_Object, "hide_select");
- props.object_hide_render = RNA_struct_type_find_property(&RNA_Object, "hide_render");
- props.collection_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select");
- props.collection_hide_viewport = RNA_struct_type_find_property(&RNA_Collection, "hide_viewport");
- props.collection_hide_render = RNA_struct_type_find_property(&RNA_Collection, "hide_render");
- props.modifier_show_viewport = RNA_struct_type_find_property(&RNA_Modifier, "show_viewport");
- props.modifier_show_render = RNA_struct_type_find_property(&RNA_Modifier, "show_render");
-
- props.initialized = true;
- }
-
- /* Create buttons. */
- uiBut *bt;
-
- for (TreeElement *te = lb->first; te; te = te->next) {
- TreeStoreElem *tselem = TREESTORE(te);
- if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
- if (tselem->type == TSE_R_LAYER && (soops->outlinevis == SO_SCENES)) {
- /* View layer render toggle. */
- ViewLayer *layer = te->directdata;
-
- bt = uiDefIconButBitS(
- block, UI_BTYPE_ICON_TOGGLE_N, VIEW_LAYER_RENDER, 0, ICON_RESTRICT_RENDER_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &layer->flag, 0, 0, 0, 0, TIP_("Use view layer for rendering"));
- UI_but_func_set(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
- }
- else if (tselem->type == 0 && te->idcode == ID_OB) {
- PointerRNA ptr;
- Object *ob = (Object *)tselem->id;
- RNA_pointer_create(&ob->id, &RNA_Object, ob, &ptr);
- Base *base = BKE_view_layer_base_find(view_layer, ob);
-
- if (base) {
- int icon = ICON_RESTRICT_VIEW_ON;
- if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0) {
- icon = (base->flag & BASE_HIDDEN) != 0 ?
- ICON_HIDE_ON :
- ICON_HIDE_OFF;
- }
- bt = uiDefIconBut(
- block, UI_BTYPE_ICON_TOGGLE, 0, icon,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0, 0, 0, 0,
- TIP_("Hide object in viewport\n"
- "* Alt to disable for all viewports\n"
- "* Ctrl to isolate visibility"));
- UI_but_func_set(bt, hidebutton_base_flag_cb, view_layer, base);
- UI_but_func_pushed_state_set(bt, base_pushed_state_cb, base);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- }
- else {
- bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- &ptr, props.object_hide_viewport, -1, 0, 0, -1, -1, NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- }
-
- bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- &ptr, props.object_hide_select, -1, 0, 0, -1, -1, NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-
- bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- &ptr, props.object_hide_render, -1, 0, 0, -1, -1, NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-
- }
- else if (tselem->type == TSE_MODIFIER) {
- ModifierData *md = (ModifierData *)te->directdata;
-
- PointerRNA ptr;
- RNA_pointer_create(tselem->id, &RNA_Modifier, md, &ptr);
-
- bt = uiDefIconButR_prop(
- block, UI_BTYPE_ICON_TOGGLE, 0, 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- &ptr, props.modifier_show_viewport, -1, 0, 0, -1, -1, NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-
- bt = uiDefIconButR_prop(
- block, UI_BTYPE_ICON_TOGGLE, 0, 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- &ptr, props.modifier_show_render, -1, 0, 0, -1, -1, NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- }
- else if (tselem->type == TSE_POSE_CHANNEL) {
- bPoseChannel *pchan = (bPoseChannel *)te->directdata;
- Bone *bone = pchan->bone;
- Object *ob = (Object *)tselem->id;
-
- bt = uiDefIconButBitI(
- block, UI_BTYPE_ICON_TOGGLE, BONE_HIDDEN_P, 0, ICON_HIDE_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0,
- TIP_("Restrict/Allow visibility in the 3D View"));
- UI_but_func_set(bt, restrictbutton_bone_visibility_cb, ob->data, bone);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
-
- bt = uiDefIconButBitI(
- block, UI_BTYPE_ICON_TOGGLE, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0,
- TIP_("Restrict/Allow selection in the 3D View"));
- UI_but_func_set(bt, restrictbutton_bone_select_cb, ob->data, bone);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
- }
- else if (tselem->type == TSE_EBONE) {
- EditBone *ebone = (EditBone *)te->directdata;
-
- bt = uiDefIconButBitI(
- block, UI_BTYPE_ICON_TOGGLE, BONE_HIDDEN_A, 0, ICON_RESTRICT_VIEW_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &(ebone->flag), 0, 0, 0, 0,
- TIP_("Restrict/Allow visibility in the 3D View"));
- UI_but_func_set(bt, restrictbutton_ebone_visibility_cb, NULL, ebone);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
-
- bt = uiDefIconButBitI(
- block, UI_BTYPE_ICON_TOGGLE, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &(ebone->flag), 0, 0, 0, 0,
- TIP_("Restrict/Allow selection in the 3D View"));
- UI_but_func_set(bt, restrictbutton_ebone_select_cb, NULL, ebone);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
- }
- else if (tselem->type == TSE_GP_LAYER) {
- ID *id = tselem->id;
- bGPDlayer *gpl = (bGPDlayer *)te->directdata;
-
- bt = uiDefIconButBitS(
- block, UI_BTYPE_ICON_TOGGLE, GP_LAYER_HIDE, 0, ICON_HIDE_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &gpl->flag, 0, 0, 0, 0,
- TIP_("Restrict/Allow visibility in the 3D View"));
- UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, id, gpl);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
-
- bt = uiDefIconButBitS(
- block, UI_BTYPE_ICON_TOGGLE, GP_LAYER_LOCKED, 0, ICON_UNLOCKED,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &gpl->flag, 0, 0, 0, 0,
- TIP_("Restrict/Allow editing of strokes and keyframes in this layer"));
- UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, id, gpl);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- }
- else if (outliner_is_collection_tree_element(te)) {
- LayerCollection *lc = (tselem->type == TSE_LAYER_COLLECTION) ? te->directdata : NULL;
- Collection *collection = outliner_collection_from_tree_element(te);
-
- if ((!lc || !(lc->flag & LAYER_COLLECTION_EXCLUDE)) &&
- !(collection->flag & COLLECTION_IS_MASTER))
- {
- PointerRNA collection_ptr;
- RNA_id_pointer_create(&collection->id, &collection_ptr);
-
- if (lc != NULL) {
- int icon = ICON_RESTRICT_VIEW_ON;
- if ((collection->flag & COLLECTION_RESTRICT_VIEW) == 0) {
- icon = (lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) != 0 ?
- ICON_HIDE_ON :
- ICON_HIDE_OFF;
- }
- bt = uiDefIconBut(
- block, UI_BTYPE_TOGGLE, 0, icon,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0, 0, 0, 0,
- TIP_("Hide collection in viewport\n"
- "* Alt to disable for all viewports\n"
- "* Ctrl to isolate visibility\n"
- "* Shift to hide inside objects and collections"));
- UI_but_func_set(bt, hidebutton_layer_collection_flag_cb, view_layer, lc);
- UI_but_func_pushed_state_set(bt, layer_collection_pushed_state_cb, lc);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- }
- else {
- bt = uiDefIconButR_prop(
- block, UI_BTYPE_ICON_TOGGLE, 0, 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &collection_ptr, props.collection_hide_viewport, -1, 0, 0, 0, 0, NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- }
-
- bt = uiDefIconButR_prop(
- block, UI_BTYPE_ICON_TOGGLE, 0, 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &collection_ptr, props.collection_hide_render, -1, 0, 0, 0, 0, NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-
- bt = uiDefIconButR_prop(
- block, UI_BTYPE_ICON_TOGGLE, 0, 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &collection_ptr, props.collection_hide_select, -1, 0, 0, 0, 0, NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- }
- }
- }
-
- if (TSELEM_OPEN(tselem, soops)) {
- outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &te->subtree);
- }
- }
+ /* Get RNA properties (once for speed). */
+ static struct RestrictProperties {
+ bool initialized;
+
+ PropertyRNA *object_hide_viewport, *object_hide_select, *object_hide_render;
+ PropertyRNA *collection_hide_viewport, *collection_hide_select, *collection_hide_render;
+ PropertyRNA *modifier_show_viewport, *modifier_show_render;
+ } props = {false};
+
+ if (!props.initialized) {
+ props.object_hide_viewport = RNA_struct_type_find_property(&RNA_Object, "hide_viewport");
+ props.object_hide_select = RNA_struct_type_find_property(&RNA_Object, "hide_select");
+ props.object_hide_render = RNA_struct_type_find_property(&RNA_Object, "hide_render");
+ props.collection_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select");
+ props.collection_hide_viewport = RNA_struct_type_find_property(&RNA_Collection,
+ "hide_viewport");
+ props.collection_hide_render = RNA_struct_type_find_property(&RNA_Collection, "hide_render");
+ props.modifier_show_viewport = RNA_struct_type_find_property(&RNA_Modifier, "show_viewport");
+ props.modifier_show_render = RNA_struct_type_find_property(&RNA_Modifier, "show_render");
+
+ props.initialized = true;
+ }
+
+ /* Create buttons. */
+ uiBut *bt;
+
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
+ if (tselem->type == TSE_R_LAYER && (soops->outlinevis == SO_SCENES)) {
+ /* View layer render toggle. */
+ ViewLayer *layer = te->directdata;
+
+ bt = uiDefIconButBitS(block,
+ UI_BTYPE_ICON_TOGGLE_N,
+ VIEW_LAYER_RENDER,
+ 0,
+ ICON_RESTRICT_RENDER_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &layer->flag,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Use view layer for rendering"));
+ UI_but_func_set(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ }
+ else if (tselem->type == 0 && te->idcode == ID_OB) {
+ PointerRNA ptr;
+ Object *ob = (Object *)tselem->id;
+ RNA_pointer_create(&ob->id, &RNA_Object, ob, &ptr);
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+
+ if (base) {
+ int icon = ICON_RESTRICT_VIEW_ON;
+ if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0) {
+ icon = (base->flag & BASE_HIDDEN) != 0 ? ICON_HIDE_ON : ICON_HIDE_OFF;
+ }
+ bt = uiDefIconBut(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ icon,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Hide object in viewport\n"
+ "* Alt to disable for all viewports\n"
+ "* Ctrl to isolate visibility"));
+ UI_but_func_set(bt, hidebutton_base_flag_cb, view_layer, base);
+ UI_but_func_pushed_state_set(bt, base_pushed_state_cb, base);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
+ else {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &ptr,
+ props.object_hide_viewport,
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
+
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &ptr,
+ props.object_hide_select,
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &ptr,
+ props.object_hide_render,
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
+ else if (tselem->type == TSE_MODIFIER) {
+ ModifierData *md = (ModifierData *)te->directdata;
+
+ PointerRNA ptr;
+ RNA_pointer_create(tselem->id, &RNA_Modifier, md, &ptr);
+
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &ptr,
+ props.modifier_show_viewport,
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &ptr,
+ props.modifier_show_render,
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
+ else if (tselem->type == TSE_POSE_CHANNEL) {
+ bPoseChannel *pchan = (bPoseChannel *)te->directdata;
+ Bone *bone = pchan->bone;
+ Object *ob = (Object *)tselem->id;
+
+ bt = uiDefIconButBitI(block,
+ UI_BTYPE_ICON_TOGGLE,
+ BONE_HIDDEN_P,
+ 0,
+ ICON_HIDE_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &(bone->flag),
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Restrict/Allow visibility in the 3D View"));
+ UI_but_func_set(bt, restrictbutton_bone_visibility_cb, ob->data, bone);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+
+ bt = uiDefIconButBitI(block,
+ UI_BTYPE_ICON_TOGGLE,
+ BONE_UNSELECTABLE,
+ 0,
+ ICON_RESTRICT_SELECT_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &(bone->flag),
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Restrict/Allow selection in the 3D View"));
+ UI_but_func_set(bt, restrictbutton_bone_select_cb, ob->data, bone);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ }
+ else if (tselem->type == TSE_EBONE) {
+ EditBone *ebone = (EditBone *)te->directdata;
+
+ bt = uiDefIconButBitI(block,
+ UI_BTYPE_ICON_TOGGLE,
+ BONE_HIDDEN_A,
+ 0,
+ ICON_RESTRICT_VIEW_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &(ebone->flag),
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Restrict/Allow visibility in the 3D View"));
+ UI_but_func_set(bt, restrictbutton_ebone_visibility_cb, NULL, ebone);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+
+ bt = uiDefIconButBitI(block,
+ UI_BTYPE_ICON_TOGGLE,
+ BONE_UNSELECTABLE,
+ 0,
+ ICON_RESTRICT_SELECT_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &(ebone->flag),
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Restrict/Allow selection in the 3D View"));
+ UI_but_func_set(bt, restrictbutton_ebone_select_cb, NULL, ebone);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ }
+ else if (tselem->type == TSE_GP_LAYER) {
+ ID *id = tselem->id;
+ bGPDlayer *gpl = (bGPDlayer *)te->directdata;
+
+ bt = uiDefIconButBitS(block,
+ UI_BTYPE_ICON_TOGGLE,
+ GP_LAYER_HIDE,
+ 0,
+ ICON_HIDE_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &gpl->flag,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Restrict/Allow visibility in the 3D View"));
+ UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, id, gpl);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+
+ bt = uiDefIconButBitS(
+ block,
+ UI_BTYPE_ICON_TOGGLE,
+ GP_LAYER_LOCKED,
+ 0,
+ ICON_UNLOCKED,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &gpl->flag,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Restrict/Allow editing of strokes and keyframes in this layer"));
+ UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, id, gpl);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
+ else if (outliner_is_collection_tree_element(te)) {
+ LayerCollection *lc = (tselem->type == TSE_LAYER_COLLECTION) ? te->directdata : NULL;
+ Collection *collection = outliner_collection_from_tree_element(te);
+
+ if ((!lc || !(lc->flag & LAYER_COLLECTION_EXCLUDE)) &&
+ !(collection->flag & COLLECTION_IS_MASTER)) {
+ PointerRNA collection_ptr;
+ RNA_id_pointer_create(&collection->id, &collection_ptr);
+
+ if (lc != NULL) {
+ int icon = ICON_RESTRICT_VIEW_ON;
+ if ((collection->flag & COLLECTION_RESTRICT_VIEW) == 0) {
+ icon = (lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) != 0 ? ICON_HIDE_ON :
+ ICON_HIDE_OFF;
+ }
+ bt = uiDefIconBut(block,
+ UI_BTYPE_TOGGLE,
+ 0,
+ icon,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Hide collection in viewport\n"
+ "* Alt to disable for all viewports\n"
+ "* Ctrl to isolate visibility\n"
+ "* Shift to hide inside objects and collections"));
+ UI_but_func_set(bt, hidebutton_layer_collection_flag_cb, view_layer, lc);
+ UI_but_func_pushed_state_set(bt, layer_collection_pushed_state_cb, lc);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
+ else {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &collection_ptr,
+ props.collection_hide_viewport,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
+
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &collection_ptr,
+ props.collection_hide_render,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &collection_ptr,
+ props.collection_hide_select,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
+ }
+ }
+
+ if (TSELEM_OPEN(tselem, soops)) {
+ outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &te->subtree);
+ }
+ }
}
static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOutliner *soops, ListBase *lb)
{
- for (TreeElement *te = lb->first; te; te = te->next) {
- TreeStoreElem *tselem = TREESTORE(te);
- if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
- if (tselem->type == 0) {
- uiBut *bt;
- ID *id = tselem->id;
- const char *tip = NULL;
- int icon = ICON_NONE;
- char buf[16] = "";
- int but_flag = UI_BUT_DRAG_LOCK;
-
- if (ID_IS_LINKED(id)) {
- but_flag |= UI_BUT_DISABLED;
- }
-
- if (id->flag & LIB_FAKEUSER) {
- icon = ICON_FILE_TICK;
- tip = TIP_("Data-block will be retained using a fake user");
- }
- else {
- icon = ICON_X;
- tip = TIP_("Data-block has no users and will be deleted");
- }
- bt = uiDefIconButBitS(
- block, UI_BTYPE_TOGGLE, LIB_FAKEUSER, 1, icon,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- &id->flag, 0, 0, 0, 0, tip);
- UI_but_func_set(bt, restrictbutton_id_user_toggle, id, NULL);
- UI_but_flag_enable(bt, but_flag);
-
-
- BLI_str_format_int_grouped(buf, id->us);
- bt = uiDefBut(
- block, UI_BTYPE_BUT, 1, buf,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys,
- UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0,
- TIP_("Number of users of this data-block"));
- UI_but_flag_enable(bt, but_flag);
-
-
- bt = uiDefButBitS(
- block, UI_BTYPE_TOGGLE, LIB_FAKEUSER, 1, (id->flag & LIB_FAKEUSER) ? "F" : " ",
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- &id->flag, 0, 0, 0, 0,
- TIP_("Data-block has a 'fake' user which will keep it in the file "
- "even if nothing else uses it"));
- UI_but_func_set(bt, restrictbutton_id_user_toggle, id, NULL);
- UI_but_flag_enable(bt, but_flag);
- }
- }
-
- if (TSELEM_OPEN(tselem, soops)) {
- outliner_draw_userbuts(block, ar, soops, &te->subtree);
- }
- }
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
+ if (tselem->type == 0) {
+ uiBut *bt;
+ ID *id = tselem->id;
+ const char *tip = NULL;
+ int icon = ICON_NONE;
+ char buf[16] = "";
+ int but_flag = UI_BUT_DRAG_LOCK;
+
+ if (ID_IS_LINKED(id)) {
+ but_flag |= UI_BUT_DISABLED;
+ }
+
+ if (id->flag & LIB_FAKEUSER) {
+ icon = ICON_FILE_TICK;
+ tip = TIP_("Data-block will be retained using a fake user");
+ }
+ else {
+ icon = ICON_X;
+ tip = TIP_("Data-block has no users and will be deleted");
+ }
+ bt = uiDefIconButBitS(block,
+ UI_BTYPE_TOGGLE,
+ LIB_FAKEUSER,
+ 1,
+ icon,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &id->flag,
+ 0,
+ 0,
+ 0,
+ 0,
+ tip);
+ UI_but_func_set(bt, restrictbutton_id_user_toggle, id, NULL);
+ UI_but_flag_enable(bt, but_flag);
+
+ BLI_str_format_int_grouped(buf, id->us);
+ bt = uiDefBut(block,
+ UI_BTYPE_BUT,
+ 1,
+ buf,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ TIP_("Number of users of this data-block"));
+ UI_but_flag_enable(bt, but_flag);
+
+ bt = uiDefButBitS(block,
+ UI_BTYPE_TOGGLE,
+ LIB_FAKEUSER,
+ 1,
+ (id->flag & LIB_FAKEUSER) ? "F" : " ",
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &id->flag,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Data-block has a 'fake' user which will keep it in the file "
+ "even if nothing else uses it"));
+ UI_but_func_set(bt, restrictbutton_id_user_toggle, id, NULL);
+ UI_but_flag_enable(bt, but_flag);
+ }
+ }
+
+ if (TSELEM_OPEN(tselem, soops)) {
+ outliner_draw_userbuts(block, ar, soops, &te->subtree);
+ }
+ }
}
static void outliner_draw_rnacols(ARegion *ar, int sizex)
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &ar->v2d;
- float miny = v2d->cur.ymin;
- if (miny < v2d->tot.ymin) {
- miny = v2d->tot.ymin;
- }
+ float miny = v2d->cur.ymin;
+ if (miny < v2d->tot.ymin) {
+ miny = v2d->tot.ymin;
+ }
- GPU_line_width(1.0f);
+ GPU_line_width(1.0f);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColorShadeAlpha(TH_BACK, -15, -200);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShadeAlpha(TH_BACK, -15, -200);
- immBegin(GPU_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, sizex, v2d->cur.ymax);
- immVertex2f(pos, sizex, miny);
+ immVertex2f(pos, sizex, v2d->cur.ymax);
+ immVertex2f(pos, sizex, miny);
- immVertex2f(pos, sizex + OL_RNA_COL_SIZEX, v2d->cur.ymax);
- immVertex2f(pos, sizex + OL_RNA_COL_SIZEX, miny);
+ immVertex2f(pos, sizex + OL_RNA_COL_SIZEX, v2d->cur.ymax);
+ immVertex2f(pos, sizex + OL_RNA_COL_SIZEX, miny);
- immEnd();
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
}
-static void outliner_draw_rnabuts(uiBlock *block, ARegion *ar, SpaceOutliner *soops, int sizex, ListBase *lb)
+static void outliner_draw_rnabuts(
+ uiBlock *block, ARegion *ar, SpaceOutliner *soops, int sizex, ListBase *lb)
{
- PointerRNA *ptr;
- PropertyRNA *prop;
-
- for (TreeElement *te = lb->first; te; te = te->next) {
- TreeStoreElem *tselem = TREESTORE(te);
- if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
- if (tselem->type == TSE_RNA_PROPERTY) {
- ptr = &te->rnaptr;
- prop = te->directdata;
-
- if (!TSELEM_OPEN(tselem, soops)) {
- if (RNA_property_type(prop) == PROP_POINTER) {
- uiBut *but = uiDefAutoButR(
- block, ptr, prop, -1, "", ICON_NONE, sizex, te->ys,
- OL_RNA_COL_SIZEX, UI_UNIT_Y - 1);
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- else if (RNA_property_type(prop) == PROP_ENUM) {
- uiDefAutoButR(
- block, ptr, prop, -1, NULL, ICON_NONE, sizex, te->ys, OL_RNA_COL_SIZEX,
- UI_UNIT_Y - 1);
- }
- else {
- uiDefAutoButR(
- block, ptr, prop, -1, "", ICON_NONE, sizex, te->ys, OL_RNA_COL_SIZEX,
- UI_UNIT_Y - 1);
- }
- }
- }
- else if (tselem->type == TSE_RNA_ARRAY_ELEM) {
- ptr = &te->rnaptr;
- prop = te->directdata;
-
- uiDefAutoButR(
- block, ptr, prop, te->index, "", ICON_NONE, sizex, te->ys, OL_RNA_COL_SIZEX,
- UI_UNIT_Y - 1);
- }
- }
-
- if (TSELEM_OPEN(tselem, soops)) {
- outliner_draw_rnabuts(block, ar, soops, sizex, &te->subtree);
- }
- }
+ PointerRNA *ptr;
+ PropertyRNA *prop;
+
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
+ if (tselem->type == TSE_RNA_PROPERTY) {
+ ptr = &te->rnaptr;
+ prop = te->directdata;
+
+ if (!TSELEM_OPEN(tselem, soops)) {
+ if (RNA_property_type(prop) == PROP_POINTER) {
+ uiBut *but = uiDefAutoButR(block,
+ ptr,
+ prop,
+ -1,
+ "",
+ ICON_NONE,
+ sizex,
+ te->ys,
+ OL_RNA_COL_SIZEX,
+ UI_UNIT_Y - 1);
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ else if (RNA_property_type(prop) == PROP_ENUM) {
+ uiDefAutoButR(block,
+ ptr,
+ prop,
+ -1,
+ NULL,
+ ICON_NONE,
+ sizex,
+ te->ys,
+ OL_RNA_COL_SIZEX,
+ UI_UNIT_Y - 1);
+ }
+ else {
+ uiDefAutoButR(block,
+ ptr,
+ prop,
+ -1,
+ "",
+ ICON_NONE,
+ sizex,
+ te->ys,
+ OL_RNA_COL_SIZEX,
+ UI_UNIT_Y - 1);
+ }
+ }
+ }
+ else if (tselem->type == TSE_RNA_ARRAY_ELEM) {
+ ptr = &te->rnaptr;
+ prop = te->directdata;
+
+ uiDefAutoButR(block,
+ ptr,
+ prop,
+ te->index,
+ "",
+ ICON_NONE,
+ sizex,
+ te->ys,
+ OL_RNA_COL_SIZEX,
+ UI_UNIT_Y - 1);
+ }
+ }
+
+ if (TSELEM_OPEN(tselem, soops)) {
+ outliner_draw_rnabuts(block, ar, soops, sizex, &te->subtree);
+ }
+ }
}
static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, TreeElement *te)
{
- uiBut *bt;
- TreeStoreElem *tselem;
- int spx, dx, len;
-
- tselem = TREESTORE(te);
-
- BLI_assert(tselem->flag & TSE_TEXTBUT);
- /* If we add support to rename Sequence.
- * need change this.
- */
-
- if (tselem->type == TSE_EBONE) {
- len = sizeof(((EditBone *) 0)->name);
- }
- else if (tselem->type == TSE_MODIFIER) {
- len = sizeof(((ModifierData *) 0)->name);
- }
- else if (tselem->id && GS(tselem->id->name) == ID_LI) {
- len = sizeof(((Library *) 0)->name);
- }
- else {
- len = MAX_ID_NAME - 2;
- }
-
- spx = te->xs + 1.8f * UI_UNIT_X;
- dx = ar->v2d.cur.xmax - (spx + 3.2f * UI_UNIT_X);
-
- bt = uiDefBut(
- block, UI_BTYPE_TEXT, OL_NAMEBUTTON, "", spx, te->ys, dx, UI_UNIT_Y - 1, (void *)te->name,
- 1.0, (float)len, 0, 0, "");
- 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)) {
- tselem->flag &= ~TSE_TEXTBUT;
-
- /* bad! (notifier within draw) without this, we don't get a refresh */
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
- }
+ uiBut *bt;
+ TreeStoreElem *tselem;
+ int spx, dx, len;
+
+ tselem = TREESTORE(te);
+
+ BLI_assert(tselem->flag & TSE_TEXTBUT);
+ /* If we add support to rename Sequence.
+ * need change this.
+ */
+
+ if (tselem->type == TSE_EBONE) {
+ len = sizeof(((EditBone *)0)->name);
+ }
+ else if (tselem->type == TSE_MODIFIER) {
+ len = sizeof(((ModifierData *)0)->name);
+ }
+ else if (tselem->id && GS(tselem->id->name) == ID_LI) {
+ len = sizeof(((Library *)0)->name);
+ }
+ else {
+ len = MAX_ID_NAME - 2;
+ }
+
+ spx = te->xs + 1.8f * UI_UNIT_X;
+ dx = ar->v2d.cur.xmax - (spx + 3.2f * UI_UNIT_X);
+
+ bt = uiDefBut(block,
+ UI_BTYPE_TEXT,
+ OL_NAMEBUTTON,
+ "",
+ spx,
+ te->ys,
+ dx,
+ UI_UNIT_Y - 1,
+ (void *)te->name,
+ 1.0,
+ (float)len,
+ 0,
+ 0,
+ "");
+ 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)) {
+ tselem->flag &= ~TSE_TEXTBUT;
+
+ /* bad! (notifier within draw) without this, we don't get a refresh */
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+ }
}
/* ****************************************************** */
@@ -972,615 +1234,674 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Tre
TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
{
- TreeElementIcon data = {0};
-
- if (tselem->type) {
- switch (tselem->type) {
- case TSE_ANIM_DATA:
- data.icon = ICON_ANIM_DATA; /* XXX */
- break;
- case TSE_NLA:
- data.icon = ICON_NLA;
- break;
- case TSE_NLA_TRACK:
- data.icon = ICON_NLA; /* XXX */
- break;
- case TSE_NLA_ACTION:
- data.icon = ICON_ACTION;
- break;
- case TSE_DRIVER_BASE:
- data.icon = ICON_DRIVER;
- break;
- case TSE_DEFGROUP_BASE:
- data.icon = ICON_GROUP_VERTEX;
- break;
- case TSE_BONE:
- case TSE_EBONE:
- data.icon = ICON_BONE_DATA;
- break;
- case TSE_CONSTRAINT_BASE:
- data.icon = ICON_CONSTRAINT;
- break;
- case TSE_MODIFIER_BASE:
- data.icon = ICON_MODIFIER_DATA;
- break;
- case TSE_LINKED_OB:
- data.icon = ICON_OBJECT_DATA;
- break;
- case TSE_LINKED_PSYS:
- data.icon = ICON_PARTICLES;
- break;
- case TSE_MODIFIER:
- {
- Object *ob = (Object *)tselem->id;
- if (ob->type != OB_GPENCIL) {
- ModifierData *md = BLI_findlink(&ob->modifiers, tselem->nr);
- switch ((ModifierType)md->type) {
- case eModifierType_Subsurf:
- data.icon = ICON_MOD_SUBSURF;
- break;
- case eModifierType_Armature:
- data.icon = ICON_MOD_ARMATURE;
- break;
- case eModifierType_Lattice:
- data.icon = ICON_MOD_LATTICE;
- break;
- case eModifierType_Curve:
- data.icon = ICON_MOD_CURVE;
- break;
- case eModifierType_Build:
- data.icon = ICON_MOD_BUILD;
- break;
- case eModifierType_Mirror:
- data.icon = ICON_MOD_MIRROR;
- break;
- case eModifierType_Decimate:
- data.icon = ICON_MOD_DECIM;
- break;
- case eModifierType_Wave:
- data.icon = ICON_MOD_WAVE;
- break;
- case eModifierType_Hook:
- data.icon = ICON_HOOK;
- break;
- case eModifierType_Softbody:
- data.icon = ICON_MOD_SOFT;
- break;
- case eModifierType_Boolean:
- data.icon = ICON_MOD_BOOLEAN;
- break;
- case eModifierType_ParticleSystem:
- data.icon = ICON_MOD_PARTICLES;
- break;
- case eModifierType_ParticleInstance:
- data.icon = ICON_MOD_PARTICLES;
- break;
- case eModifierType_EdgeSplit:
- data.icon = ICON_MOD_EDGESPLIT;
- break;
- case eModifierType_Array:
- data.icon = ICON_MOD_ARRAY;
- break;
- case eModifierType_UVProject:
- case eModifierType_UVWarp: /* TODO, get own icon */
- data.icon = ICON_MOD_UVPROJECT;
- break;
- case eModifierType_Displace:
- data.icon = ICON_MOD_DISPLACE;
- break;
- case eModifierType_Shrinkwrap:
- data.icon = ICON_MOD_SHRINKWRAP;
- break;
- case eModifierType_Cast:
- data.icon = ICON_MOD_CAST;
- break;
- case eModifierType_MeshDeform:
- case eModifierType_SurfaceDeform:
- data.icon = ICON_MOD_MESHDEFORM;
- break;
- case eModifierType_Bevel:
- data.icon = ICON_MOD_BEVEL;
- break;
- case eModifierType_Smooth:
- case eModifierType_LaplacianSmooth:
- case eModifierType_CorrectiveSmooth:
- data.icon = ICON_MOD_SMOOTH;
- break;
- case eModifierType_SimpleDeform:
- data.icon = ICON_MOD_SIMPLEDEFORM;
- break;
- case eModifierType_Mask:
- data.icon = ICON_MOD_MASK;
- break;
- case eModifierType_Cloth:
- data.icon = ICON_MOD_CLOTH;
- break;
- case eModifierType_Explode:
- data.icon = ICON_MOD_EXPLODE;
- break;
- case eModifierType_Collision:
- case eModifierType_Surface:
- data.icon = ICON_MOD_PHYSICS;
- break;
- case eModifierType_Fluidsim:
- data.icon = ICON_MOD_FLUIDSIM;
- break;
- case eModifierType_Multires:
- data.icon = ICON_MOD_MULTIRES;
- break;
- case eModifierType_Smoke:
- data.icon = ICON_MOD_SMOKE;
- break;
- case eModifierType_Solidify:
- data.icon = ICON_MOD_SOLIDIFY;
- break;
- case eModifierType_Screw:
- data.icon = ICON_MOD_SCREW;
- break;
- case eModifierType_Remesh:
- data.icon = ICON_MOD_REMESH;
- break;
- case eModifierType_WeightVGEdit:
- case eModifierType_WeightVGMix:
- case eModifierType_WeightVGProximity:
- data.icon = ICON_MOD_VERTEX_WEIGHT;
- break;
- case eModifierType_DynamicPaint:
- data.icon = ICON_MOD_DYNAMICPAINT;
- break;
- case eModifierType_Ocean:
- data.icon = ICON_MOD_OCEAN;
- break;
- case eModifierType_Warp:
- data.icon = ICON_MOD_WARP;
- break;
- case eModifierType_Skin:
- data.icon = ICON_MOD_SKIN;
- break;
- case eModifierType_Triangulate:
- data.icon = ICON_MOD_TRIANGULATE;
- break;
- case eModifierType_MeshCache:
- data.icon = ICON_MOD_MESHDEFORM; /* XXX, needs own icon */
- break;
- case eModifierType_MeshSequenceCache:
- data.icon = ICON_MOD_MESHDEFORM; /* XXX, needs own icon */
- break;
- case eModifierType_Wireframe:
- data.icon = ICON_MOD_WIREFRAME;
- break;
- case eModifierType_LaplacianDeform:
- data.icon = ICON_MOD_MESHDEFORM; /* XXX, needs own icon */
- break;
- case eModifierType_DataTransfer:
- data.icon = ICON_MOD_DATA_TRANSFER;
- break;
- case eModifierType_NormalEdit:
- case eModifierType_WeightedNormal:
- data.icon = ICON_MOD_NORMALEDIT;
- break;
- /* Default */
- case eModifierType_None:
- case eModifierType_ShapeKey:
-
- case NUM_MODIFIER_TYPES:
- data.icon = ICON_DOT;
- break;
- }
- }
- else {
- /* grease pencil modifiers */
- GpencilModifierData *md = BLI_findlink(&ob->greasepencil_modifiers, tselem->nr);
- switch ((GpencilModifierType)md->type) {
- case eGpencilModifierType_Noise:
- data.icon = ICON_RNDCURVE;
- break;
- case eGpencilModifierType_Subdiv:
- data.icon = ICON_MOD_SUBSURF;
- break;
- case eGpencilModifierType_Thick:
- data.icon = ICON_MOD_THICKNESS;
- break;
- case eGpencilModifierType_Tint:
- data.icon = ICON_MOD_TINT;
- break;
- case eGpencilModifierType_Array:
- data.icon = ICON_MOD_ARRAY;
- break;
- case eGpencilModifierType_Build:
- data.icon = ICON_MOD_BUILD;
- break;
- case eGpencilModifierType_Opacity:
- data.icon = ICON_MOD_MASK;
- break;
- case eGpencilModifierType_Color:
- data.icon = ICON_MOD_HUE_SATURATION;
- break;
- case eGpencilModifierType_Lattice:
- data.icon = ICON_MOD_LATTICE;
- break;
- case eGpencilModifierType_Mirror:
- data.icon = ICON_MOD_MIRROR;
- break;
- case eGpencilModifierType_Simplify:
- data.icon = ICON_MOD_SIMPLIFY;
- break;
- case eGpencilModifierType_Smooth:
- data.icon = ICON_MOD_SMOOTH;
- break;
- case eGpencilModifierType_Hook:
- data.icon = ICON_HOOK;
- break;
- case eGpencilModifierType_Offset:
- data.icon = ICON_MOD_OFFSET;
- break;
- case eGpencilModifierType_Armature:
- data.icon = ICON_MOD_ARMATURE;
- break;
-
- /* Default */
- default:
- data.icon = ICON_DOT;
- break;
- }
- }
- break;
- }
- case TSE_POSE_BASE:
- data.icon = ICON_ARMATURE_DATA;
- break;
- case TSE_POSE_CHANNEL:
- data.icon = ICON_BONE_DATA;
- break;
- case TSE_PROXY:
- data.icon = ICON_GHOST_ENABLED;
- break;
- case TSE_R_LAYER_BASE:
- data.icon = ICON_RENDERLAYERS;
- break;
- case TSE_SCENE_OBJECTS_BASE:
- data.icon = ICON_OUTLINER_OB_GROUP_INSTANCE;
- break;
- case TSE_R_LAYER:
- data.icon = ICON_RENDER_RESULT;
- break;
- case TSE_LINKED_LAMP:
- data.icon = ICON_LIGHT_DATA;
- break;
- case TSE_LINKED_MAT:
- data.icon = ICON_MATERIAL_DATA;
- break;
- case TSE_POSEGRP_BASE:
- data.icon = ICON_GROUP_BONE;
- break;
- case TSE_SEQUENCE:
- if (te->idcode == SEQ_TYPE_MOVIE) {
- data.icon = ICON_SEQUENCE;
- }
- else if (te->idcode == SEQ_TYPE_META) {
- data.icon = ICON_DOT;
- }
- else if (te->idcode == SEQ_TYPE_SCENE) {
- data.icon = ICON_SCENE;
- }
- else if (te->idcode == SEQ_TYPE_SOUND_RAM) {
- data.icon = ICON_SOUND;
- }
- else if (te->idcode == SEQ_TYPE_IMAGE) {
- data.icon = ICON_IMAGE;
- }
- else {
- data.icon = ICON_PARTICLES;
- }
- break;
- case TSE_SEQ_STRIP:
- data.icon = ICON_LIBRARY_DATA_DIRECT;
- break;
- case TSE_SEQUENCE_DUP:
- data.icon = ICON_OBJECT_DATA;
- break;
- case TSE_RNA_STRUCT:
- if (RNA_struct_is_ID(te->rnaptr.type)) {
- data.drag_id = (ID *)te->rnaptr.data;
- data.icon = RNA_struct_ui_icon(te->rnaptr.type);
- }
- else {
- data.icon = RNA_struct_ui_icon(te->rnaptr.type);
- }
- break;
- case TSE_LAYER_COLLECTION:
- case TSE_SCENE_COLLECTION_BASE:
- case TSE_VIEW_COLLECTION_BASE:
- {
- Collection *collection = outliner_collection_from_tree_element(te);
- if (collection && !(collection->flag & COLLECTION_IS_MASTER)) {
- data.drag_id = tselem->id;
- data.drag_parent = (data.drag_id && te->parent) ? TREESTORE(te->parent)->id : NULL;
- }
-
- data.icon = ICON_GROUP;
- break;
- }
- /* Removed the icons from outliner. Need a better structure with Layers, Palettes and Colors */
- case TSE_GP_LAYER:
- {
- /* indicate whether layer is active */
- bGPDlayer *gpl = te->directdata;
- if (gpl->flag & GP_LAYER_ACTIVE) {
- data.icon = ICON_GREASEPENCIL;
- }
- else {
- data.icon = ICON_DOT;
- }
- break;
- }
- default:
- data.icon = ICON_DOT;
- break;
- }
- }
- else if (tselem->id) {
- data.drag_id = tselem->id;
- data.drag_parent = (data.drag_id && te->parent) ? TREESTORE(te->parent)->id : NULL;
-
- if (GS(tselem->id->name) == ID_OB) {
- Object *ob = (Object *)tselem->id;
- switch (ob->type) {
- case OB_LAMP:
- data.icon = ICON_OUTLINER_OB_LIGHT; break;
- case OB_MESH:
- data.icon = ICON_OUTLINER_OB_MESH; break;
- case OB_CAMERA:
- data.icon = ICON_OUTLINER_OB_CAMERA; break;
- case OB_CURVE:
- data.icon = ICON_OUTLINER_OB_CURVE; break;
- case OB_MBALL:
- data.icon = ICON_OUTLINER_OB_META; break;
- case OB_LATTICE:
- data.icon = ICON_OUTLINER_OB_LATTICE; break;
- case OB_ARMATURE:
- data.icon = ICON_OUTLINER_OB_ARMATURE; break;
- case OB_FONT:
- data.icon = ICON_OUTLINER_OB_FONT; break;
- case OB_SURF:
- data.icon = ICON_OUTLINER_OB_SURFACE; break;
- case OB_SPEAKER:
- data.icon = ICON_OUTLINER_OB_SPEAKER; break;
- case OB_LIGHTPROBE:
- data.icon = ICON_OUTLINER_OB_LIGHTPROBE; break;
- case OB_EMPTY:
- if (ob->instance_collection) {
- data.icon = ICON_OUTLINER_OB_GROUP_INSTANCE;
- }
- else if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
- data.icon = ICON_OUTLINER_OB_IMAGE;
- }
- else {
- data.icon = ICON_OUTLINER_OB_EMPTY;
- }
- break;
- case OB_GPENCIL:
- data.icon = ICON_OUTLINER_OB_GREASEPENCIL; break;
- break;
- }
- }
- else {
- /* TODO(sergey): Casting to short here just to handle ID_NLA which is
- * NOT inside of IDType enum.
- */
- switch ((short)GS(tselem->id->name)) {
- case ID_SCE:
- data.icon = ICON_SCENE_DATA; break;
- case ID_ME:
- data.icon = ICON_OUTLINER_DATA_MESH; break;
- case ID_CU:
- data.icon = ICON_OUTLINER_DATA_CURVE; break;
- case ID_MB:
- data.icon = ICON_OUTLINER_DATA_META; break;
- case ID_LT:
- data.icon = ICON_OUTLINER_DATA_LATTICE; break;
- case ID_LA:
- {
- Light *la = (Light *)tselem->id;
- switch (la->type) {
- case LA_LOCAL:
- data.icon = ICON_LIGHT_POINT; break;
- case LA_SUN:
- data.icon = ICON_LIGHT_SUN; break;
- case LA_SPOT:
- data.icon = ICON_LIGHT_SPOT; break;
- case LA_AREA:
- data.icon = ICON_LIGHT_AREA; break;
- default:
- data.icon = ICON_OUTLINER_DATA_LIGHT; break;
- }
- break;
- }
- case ID_MA:
- data.icon = ICON_MATERIAL_DATA; break;
- case ID_TE:
- data.icon = ICON_TEXTURE_DATA; break;
- case ID_IM:
- data.icon = ICON_IMAGE_DATA; break;
- case ID_SPK:
- case ID_SO:
- data.icon = ICON_OUTLINER_DATA_SPEAKER; break;
- case ID_AR:
- data.icon = ICON_OUTLINER_DATA_ARMATURE; break;
- case ID_CA:
- data.icon = ICON_OUTLINER_DATA_CAMERA; break;
- case ID_KE:
- data.icon = ICON_SHAPEKEY_DATA; break;
- case ID_WO:
- data.icon = ICON_WORLD_DATA; break;
- case ID_AC:
- data.icon = ICON_ACTION; break;
- case ID_NLA:
- data.icon = ICON_NLA; break;
- case ID_TXT:
- data.icon = ICON_SCRIPT; break;
- case ID_GR:
- data.icon = ICON_GROUP; break;
- case ID_LI:
- if (tselem->id->tag & LIB_TAG_MISSING) {
- data.icon = ICON_LIBRARY_DATA_BROKEN;
- }
- else if (((Library *)tselem->id)->parent) {
- data.icon = ICON_LIBRARY_DATA_INDIRECT;
- }
- else {
- data.icon = ICON_LIBRARY_DATA_DIRECT;
- }
- break;
- case ID_LS:
- data.icon = ICON_LINE_DATA; break;
- case ID_GD:
- data.icon = ICON_OUTLINER_DATA_GREASEPENCIL; break;
- case ID_LP:
- {
- LightProbe *lp = (LightProbe *)tselem->id;
- switch (lp->type) {
- case LIGHTPROBE_TYPE_CUBE:
- data.icon = ICON_LIGHTPROBE_CUBEMAP; break;
- case LIGHTPROBE_TYPE_PLANAR:
- data.icon = ICON_LIGHTPROBE_PLANAR; break;
- case LIGHTPROBE_TYPE_GRID:
- data.icon = ICON_LIGHTPROBE_GRID; break;
- default:
- data.icon = ICON_LIGHTPROBE_CUBEMAP; break;
- }
- break;
- }
- case ID_BR:
- data.icon = ICON_BRUSH_DATA; break;
- case ID_SCR:
- case ID_WS:
- data.icon = ICON_WORKSPACE; break;
- case ID_MSK:
- data.icon = ICON_MOD_MASK; break;
- case ID_MC:
- data.icon = ICON_SEQUENCE; break;
- case ID_PC:
- data.icon = ICON_CURVE_BEZCURVE; break;
- default:
- break;
- }
- }
- }
-
- return data;
+ TreeElementIcon data = {0};
+
+ if (tselem->type) {
+ switch (tselem->type) {
+ case TSE_ANIM_DATA:
+ data.icon = ICON_ANIM_DATA; /* XXX */
+ break;
+ case TSE_NLA:
+ data.icon = ICON_NLA;
+ break;
+ case TSE_NLA_TRACK:
+ data.icon = ICON_NLA; /* XXX */
+ break;
+ case TSE_NLA_ACTION:
+ data.icon = ICON_ACTION;
+ break;
+ case TSE_DRIVER_BASE:
+ data.icon = ICON_DRIVER;
+ break;
+ case TSE_DEFGROUP_BASE:
+ data.icon = ICON_GROUP_VERTEX;
+ break;
+ case TSE_BONE:
+ case TSE_EBONE:
+ data.icon = ICON_BONE_DATA;
+ break;
+ case TSE_CONSTRAINT_BASE:
+ data.icon = ICON_CONSTRAINT;
+ break;
+ case TSE_MODIFIER_BASE:
+ data.icon = ICON_MODIFIER_DATA;
+ break;
+ case TSE_LINKED_OB:
+ data.icon = ICON_OBJECT_DATA;
+ break;
+ case TSE_LINKED_PSYS:
+ data.icon = ICON_PARTICLES;
+ break;
+ case TSE_MODIFIER: {
+ Object *ob = (Object *)tselem->id;
+ if (ob->type != OB_GPENCIL) {
+ ModifierData *md = BLI_findlink(&ob->modifiers, tselem->nr);
+ switch ((ModifierType)md->type) {
+ case eModifierType_Subsurf:
+ data.icon = ICON_MOD_SUBSURF;
+ break;
+ case eModifierType_Armature:
+ data.icon = ICON_MOD_ARMATURE;
+ break;
+ case eModifierType_Lattice:
+ data.icon = ICON_MOD_LATTICE;
+ break;
+ case eModifierType_Curve:
+ data.icon = ICON_MOD_CURVE;
+ break;
+ case eModifierType_Build:
+ data.icon = ICON_MOD_BUILD;
+ break;
+ case eModifierType_Mirror:
+ data.icon = ICON_MOD_MIRROR;
+ break;
+ case eModifierType_Decimate:
+ data.icon = ICON_MOD_DECIM;
+ break;
+ case eModifierType_Wave:
+ data.icon = ICON_MOD_WAVE;
+ break;
+ case eModifierType_Hook:
+ data.icon = ICON_HOOK;
+ break;
+ case eModifierType_Softbody:
+ data.icon = ICON_MOD_SOFT;
+ break;
+ case eModifierType_Boolean:
+ data.icon = ICON_MOD_BOOLEAN;
+ break;
+ case eModifierType_ParticleSystem:
+ data.icon = ICON_MOD_PARTICLES;
+ break;
+ case eModifierType_ParticleInstance:
+ data.icon = ICON_MOD_PARTICLES;
+ break;
+ case eModifierType_EdgeSplit:
+ data.icon = ICON_MOD_EDGESPLIT;
+ break;
+ case eModifierType_Array:
+ data.icon = ICON_MOD_ARRAY;
+ break;
+ case eModifierType_UVProject:
+ case eModifierType_UVWarp: /* TODO, get own icon */
+ data.icon = ICON_MOD_UVPROJECT;
+ break;
+ case eModifierType_Displace:
+ data.icon = ICON_MOD_DISPLACE;
+ break;
+ case eModifierType_Shrinkwrap:
+ data.icon = ICON_MOD_SHRINKWRAP;
+ break;
+ case eModifierType_Cast:
+ data.icon = ICON_MOD_CAST;
+ break;
+ case eModifierType_MeshDeform:
+ case eModifierType_SurfaceDeform:
+ data.icon = ICON_MOD_MESHDEFORM;
+ break;
+ case eModifierType_Bevel:
+ data.icon = ICON_MOD_BEVEL;
+ break;
+ case eModifierType_Smooth:
+ case eModifierType_LaplacianSmooth:
+ case eModifierType_CorrectiveSmooth:
+ data.icon = ICON_MOD_SMOOTH;
+ break;
+ case eModifierType_SimpleDeform:
+ data.icon = ICON_MOD_SIMPLEDEFORM;
+ break;
+ case eModifierType_Mask:
+ data.icon = ICON_MOD_MASK;
+ break;
+ case eModifierType_Cloth:
+ data.icon = ICON_MOD_CLOTH;
+ break;
+ case eModifierType_Explode:
+ data.icon = ICON_MOD_EXPLODE;
+ break;
+ case eModifierType_Collision:
+ case eModifierType_Surface:
+ data.icon = ICON_MOD_PHYSICS;
+ break;
+ case eModifierType_Fluidsim:
+ data.icon = ICON_MOD_FLUIDSIM;
+ break;
+ case eModifierType_Multires:
+ data.icon = ICON_MOD_MULTIRES;
+ break;
+ case eModifierType_Smoke:
+ data.icon = ICON_MOD_SMOKE;
+ break;
+ case eModifierType_Solidify:
+ data.icon = ICON_MOD_SOLIDIFY;
+ break;
+ case eModifierType_Screw:
+ data.icon = ICON_MOD_SCREW;
+ break;
+ case eModifierType_Remesh:
+ data.icon = ICON_MOD_REMESH;
+ break;
+ case eModifierType_WeightVGEdit:
+ case eModifierType_WeightVGMix:
+ case eModifierType_WeightVGProximity:
+ data.icon = ICON_MOD_VERTEX_WEIGHT;
+ break;
+ case eModifierType_DynamicPaint:
+ data.icon = ICON_MOD_DYNAMICPAINT;
+ break;
+ case eModifierType_Ocean:
+ data.icon = ICON_MOD_OCEAN;
+ break;
+ case eModifierType_Warp:
+ data.icon = ICON_MOD_WARP;
+ break;
+ case eModifierType_Skin:
+ data.icon = ICON_MOD_SKIN;
+ break;
+ case eModifierType_Triangulate:
+ data.icon = ICON_MOD_TRIANGULATE;
+ break;
+ case eModifierType_MeshCache:
+ data.icon = ICON_MOD_MESHDEFORM; /* XXX, needs own icon */
+ break;
+ case eModifierType_MeshSequenceCache:
+ data.icon = ICON_MOD_MESHDEFORM; /* XXX, needs own icon */
+ break;
+ case eModifierType_Wireframe:
+ data.icon = ICON_MOD_WIREFRAME;
+ break;
+ case eModifierType_LaplacianDeform:
+ data.icon = ICON_MOD_MESHDEFORM; /* XXX, needs own icon */
+ break;
+ case eModifierType_DataTransfer:
+ data.icon = ICON_MOD_DATA_TRANSFER;
+ break;
+ case eModifierType_NormalEdit:
+ case eModifierType_WeightedNormal:
+ data.icon = ICON_MOD_NORMALEDIT;
+ break;
+ /* Default */
+ case eModifierType_None:
+ case eModifierType_ShapeKey:
+
+ case NUM_MODIFIER_TYPES:
+ data.icon = ICON_DOT;
+ break;
+ }
+ }
+ else {
+ /* grease pencil modifiers */
+ GpencilModifierData *md = BLI_findlink(&ob->greasepencil_modifiers, tselem->nr);
+ switch ((GpencilModifierType)md->type) {
+ case eGpencilModifierType_Noise:
+ data.icon = ICON_RNDCURVE;
+ break;
+ case eGpencilModifierType_Subdiv:
+ data.icon = ICON_MOD_SUBSURF;
+ break;
+ case eGpencilModifierType_Thick:
+ data.icon = ICON_MOD_THICKNESS;
+ break;
+ case eGpencilModifierType_Tint:
+ data.icon = ICON_MOD_TINT;
+ break;
+ case eGpencilModifierType_Array:
+ data.icon = ICON_MOD_ARRAY;
+ break;
+ case eGpencilModifierType_Build:
+ data.icon = ICON_MOD_BUILD;
+ break;
+ case eGpencilModifierType_Opacity:
+ data.icon = ICON_MOD_MASK;
+ break;
+ case eGpencilModifierType_Color:
+ data.icon = ICON_MOD_HUE_SATURATION;
+ break;
+ case eGpencilModifierType_Lattice:
+ data.icon = ICON_MOD_LATTICE;
+ break;
+ case eGpencilModifierType_Mirror:
+ data.icon = ICON_MOD_MIRROR;
+ break;
+ case eGpencilModifierType_Simplify:
+ data.icon = ICON_MOD_SIMPLIFY;
+ break;
+ case eGpencilModifierType_Smooth:
+ data.icon = ICON_MOD_SMOOTH;
+ break;
+ case eGpencilModifierType_Hook:
+ data.icon = ICON_HOOK;
+ break;
+ case eGpencilModifierType_Offset:
+ data.icon = ICON_MOD_OFFSET;
+ break;
+ case eGpencilModifierType_Armature:
+ data.icon = ICON_MOD_ARMATURE;
+ break;
+
+ /* Default */
+ default:
+ data.icon = ICON_DOT;
+ break;
+ }
+ }
+ break;
+ }
+ case TSE_POSE_BASE:
+ data.icon = ICON_ARMATURE_DATA;
+ break;
+ case TSE_POSE_CHANNEL:
+ data.icon = ICON_BONE_DATA;
+ break;
+ case TSE_PROXY:
+ data.icon = ICON_GHOST_ENABLED;
+ break;
+ case TSE_R_LAYER_BASE:
+ data.icon = ICON_RENDERLAYERS;
+ break;
+ case TSE_SCENE_OBJECTS_BASE:
+ data.icon = ICON_OUTLINER_OB_GROUP_INSTANCE;
+ break;
+ case TSE_R_LAYER:
+ data.icon = ICON_RENDER_RESULT;
+ break;
+ case TSE_LINKED_LAMP:
+ data.icon = ICON_LIGHT_DATA;
+ break;
+ case TSE_LINKED_MAT:
+ data.icon = ICON_MATERIAL_DATA;
+ break;
+ case TSE_POSEGRP_BASE:
+ data.icon = ICON_GROUP_BONE;
+ break;
+ case TSE_SEQUENCE:
+ if (te->idcode == SEQ_TYPE_MOVIE) {
+ data.icon = ICON_SEQUENCE;
+ }
+ else if (te->idcode == SEQ_TYPE_META) {
+ data.icon = ICON_DOT;
+ }
+ else if (te->idcode == SEQ_TYPE_SCENE) {
+ data.icon = ICON_SCENE;
+ }
+ else if (te->idcode == SEQ_TYPE_SOUND_RAM) {
+ data.icon = ICON_SOUND;
+ }
+ else if (te->idcode == SEQ_TYPE_IMAGE) {
+ data.icon = ICON_IMAGE;
+ }
+ else {
+ data.icon = ICON_PARTICLES;
+ }
+ break;
+ case TSE_SEQ_STRIP:
+ data.icon = ICON_LIBRARY_DATA_DIRECT;
+ break;
+ case TSE_SEQUENCE_DUP:
+ data.icon = ICON_OBJECT_DATA;
+ break;
+ case TSE_RNA_STRUCT:
+ if (RNA_struct_is_ID(te->rnaptr.type)) {
+ data.drag_id = (ID *)te->rnaptr.data;
+ data.icon = RNA_struct_ui_icon(te->rnaptr.type);
+ }
+ else {
+ data.icon = RNA_struct_ui_icon(te->rnaptr.type);
+ }
+ break;
+ case TSE_LAYER_COLLECTION:
+ case TSE_SCENE_COLLECTION_BASE:
+ case TSE_VIEW_COLLECTION_BASE: {
+ Collection *collection = outliner_collection_from_tree_element(te);
+ if (collection && !(collection->flag & COLLECTION_IS_MASTER)) {
+ data.drag_id = tselem->id;
+ data.drag_parent = (data.drag_id && te->parent) ? TREESTORE(te->parent)->id : NULL;
+ }
+
+ data.icon = ICON_GROUP;
+ break;
+ }
+ /* Removed the icons from outliner. Need a better structure with Layers, Palettes and Colors */
+ case TSE_GP_LAYER: {
+ /* indicate whether layer is active */
+ bGPDlayer *gpl = te->directdata;
+ if (gpl->flag & GP_LAYER_ACTIVE) {
+ data.icon = ICON_GREASEPENCIL;
+ }
+ else {
+ data.icon = ICON_DOT;
+ }
+ break;
+ }
+ default:
+ data.icon = ICON_DOT;
+ break;
+ }
+ }
+ else if (tselem->id) {
+ data.drag_id = tselem->id;
+ data.drag_parent = (data.drag_id && te->parent) ? TREESTORE(te->parent)->id : NULL;
+
+ if (GS(tselem->id->name) == ID_OB) {
+ Object *ob = (Object *)tselem->id;
+ switch (ob->type) {
+ case OB_LAMP:
+ data.icon = ICON_OUTLINER_OB_LIGHT;
+ break;
+ case OB_MESH:
+ data.icon = ICON_OUTLINER_OB_MESH;
+ break;
+ case OB_CAMERA:
+ data.icon = ICON_OUTLINER_OB_CAMERA;
+ break;
+ case OB_CURVE:
+ data.icon = ICON_OUTLINER_OB_CURVE;
+ break;
+ case OB_MBALL:
+ data.icon = ICON_OUTLINER_OB_META;
+ break;
+ case OB_LATTICE:
+ data.icon = ICON_OUTLINER_OB_LATTICE;
+ break;
+ case OB_ARMATURE:
+ data.icon = ICON_OUTLINER_OB_ARMATURE;
+ break;
+ case OB_FONT:
+ data.icon = ICON_OUTLINER_OB_FONT;
+ break;
+ case OB_SURF:
+ data.icon = ICON_OUTLINER_OB_SURFACE;
+ break;
+ case OB_SPEAKER:
+ data.icon = ICON_OUTLINER_OB_SPEAKER;
+ break;
+ case OB_LIGHTPROBE:
+ data.icon = ICON_OUTLINER_OB_LIGHTPROBE;
+ break;
+ case OB_EMPTY:
+ if (ob->instance_collection) {
+ data.icon = ICON_OUTLINER_OB_GROUP_INSTANCE;
+ }
+ else if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
+ data.icon = ICON_OUTLINER_OB_IMAGE;
+ }
+ else {
+ data.icon = ICON_OUTLINER_OB_EMPTY;
+ }
+ break;
+ case OB_GPENCIL:
+ data.icon = ICON_OUTLINER_OB_GREASEPENCIL;
+ break;
+ break;
+ }
+ }
+ else {
+ /* TODO(sergey): Casting to short here just to handle ID_NLA which is
+ * NOT inside of IDType enum.
+ */
+ switch ((short)GS(tselem->id->name)) {
+ case ID_SCE:
+ data.icon = ICON_SCENE_DATA;
+ break;
+ case ID_ME:
+ data.icon = ICON_OUTLINER_DATA_MESH;
+ break;
+ case ID_CU:
+ data.icon = ICON_OUTLINER_DATA_CURVE;
+ break;
+ case ID_MB:
+ data.icon = ICON_OUTLINER_DATA_META;
+ break;
+ case ID_LT:
+ data.icon = ICON_OUTLINER_DATA_LATTICE;
+ break;
+ case ID_LA: {
+ Light *la = (Light *)tselem->id;
+ switch (la->type) {
+ case LA_LOCAL:
+ data.icon = ICON_LIGHT_POINT;
+ break;
+ case LA_SUN:
+ data.icon = ICON_LIGHT_SUN;
+ break;
+ case LA_SPOT:
+ data.icon = ICON_LIGHT_SPOT;
+ break;
+ case LA_AREA:
+ data.icon = ICON_LIGHT_AREA;
+ break;
+ default:
+ data.icon = ICON_OUTLINER_DATA_LIGHT;
+ break;
+ }
+ break;
+ }
+ case ID_MA:
+ data.icon = ICON_MATERIAL_DATA;
+ break;
+ case ID_TE:
+ data.icon = ICON_TEXTURE_DATA;
+ break;
+ case ID_IM:
+ data.icon = ICON_IMAGE_DATA;
+ break;
+ case ID_SPK:
+ case ID_SO:
+ data.icon = ICON_OUTLINER_DATA_SPEAKER;
+ break;
+ case ID_AR:
+ data.icon = ICON_OUTLINER_DATA_ARMATURE;
+ break;
+ case ID_CA:
+ data.icon = ICON_OUTLINER_DATA_CAMERA;
+ break;
+ case ID_KE:
+ data.icon = ICON_SHAPEKEY_DATA;
+ break;
+ case ID_WO:
+ data.icon = ICON_WORLD_DATA;
+ break;
+ case ID_AC:
+ data.icon = ICON_ACTION;
+ break;
+ case ID_NLA:
+ data.icon = ICON_NLA;
+ break;
+ case ID_TXT:
+ data.icon = ICON_SCRIPT;
+ break;
+ case ID_GR:
+ data.icon = ICON_GROUP;
+ break;
+ case ID_LI:
+ if (tselem->id->tag & LIB_TAG_MISSING) {
+ data.icon = ICON_LIBRARY_DATA_BROKEN;
+ }
+ else if (((Library *)tselem->id)->parent) {
+ data.icon = ICON_LIBRARY_DATA_INDIRECT;
+ }
+ else {
+ data.icon = ICON_LIBRARY_DATA_DIRECT;
+ }
+ break;
+ case ID_LS:
+ data.icon = ICON_LINE_DATA;
+ break;
+ case ID_GD:
+ data.icon = ICON_OUTLINER_DATA_GREASEPENCIL;
+ break;
+ case ID_LP: {
+ LightProbe *lp = (LightProbe *)tselem->id;
+ switch (lp->type) {
+ case LIGHTPROBE_TYPE_CUBE:
+ data.icon = ICON_LIGHTPROBE_CUBEMAP;
+ break;
+ case LIGHTPROBE_TYPE_PLANAR:
+ data.icon = ICON_LIGHTPROBE_PLANAR;
+ break;
+ case LIGHTPROBE_TYPE_GRID:
+ data.icon = ICON_LIGHTPROBE_GRID;
+ break;
+ default:
+ data.icon = ICON_LIGHTPROBE_CUBEMAP;
+ break;
+ }
+ break;
+ }
+ case ID_BR:
+ data.icon = ICON_BRUSH_DATA;
+ break;
+ case ID_SCR:
+ case ID_WS:
+ data.icon = ICON_WORKSPACE;
+ break;
+ case ID_MSK:
+ data.icon = ICON_MOD_MASK;
+ break;
+ case ID_MC:
+ data.icon = ICON_SEQUENCE;
+ break;
+ case ID_PC:
+ data.icon = ICON_CURVE_BEZCURVE;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ return data;
}
-static void tselem_draw_icon(
- uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te,
- float alpha, const bool is_clickable)
+static void tselem_draw_icon(uiBlock *block,
+ int xmax,
+ float x,
+ float y,
+ TreeStoreElem *tselem,
+ TreeElement *te,
+ float alpha,
+ const bool is_clickable)
{
- TreeElementIcon data = tree_element_get_icon(tselem, te);
-
- if (data.icon == 0) {
- return;
- }
-
- if (!is_clickable || x >= xmax) {
- /* placement of icons, copied from interface_widgets.c */
- float aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT;
- x += 2.0f * aspect;
- y += 2.0f * aspect;
-
- /* restrict column clip... it has been coded by simply overdrawing,
- * doesn't work for buttons */
- UI_icon_draw_alpha(x, y, data.icon, alpha);
- }
- else {
- uiDefIconBut(
- block, UI_BTYPE_LABEL, 0, data.icon, x, y, UI_UNIT_X, UI_UNIT_Y, NULL,
- 0.0, 0.0, 1.0, alpha,
- (data.drag_id && ID_IS_LINKED(data.drag_id)) ? data.drag_id->lib->name : "");
- }
+ TreeElementIcon data = tree_element_get_icon(tselem, te);
+
+ if (data.icon == 0) {
+ return;
+ }
+
+ if (!is_clickable || x >= xmax) {
+ /* placement of icons, copied from interface_widgets.c */
+ float aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT;
+ x += 2.0f * aspect;
+ y += 2.0f * aspect;
+
+ /* restrict column clip... it has been coded by simply overdrawing,
+ * doesn't work for buttons */
+ UI_icon_draw_alpha(x, y, data.icon, alpha);
+ }
+ else {
+ uiDefIconBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ data.icon,
+ x,
+ y,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 1.0,
+ alpha,
+ (data.drag_id && ID_IS_LINKED(data.drag_id)) ? data.drag_id->lib->name : "");
+ }
}
/**
* For icon-only children of a collapsed tree,
* Draw small number over the icon to show how many items of this type are displayed.
*/
-static void outliner_draw_iconrow_number(
- const uiFontStyle *fstyle,
- int offsx, int ys,
- const int num_elements)
+static void outliner_draw_iconrow_number(const uiFontStyle *fstyle,
+ int offsx,
+ int ys,
+ const int num_elements)
{
- float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
- float ufac = 0.25f * UI_UNIT_X;
- float offset_x = (float) offsx + UI_UNIT_X * 0.35f;
-
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_aa(true,
- offset_x + ufac,
- (float)ys - UI_UNIT_Y * 0.2f + ufac,
- offset_x + UI_UNIT_X - ufac,
- (float)ys - UI_UNIT_Y * 0.2f + UI_UNIT_Y - ufac,
- (float)UI_UNIT_Y / 2.0f - ufac,
- color);
-
- /* Now the numbers. */
- unsigned char text_col[4];
-
- UI_GetThemeColor4ubv(TH_TEXT_HI, text_col);
- text_col[3] = 255;
-
- uiFontStyle fstyle_small = *fstyle;
- fstyle_small.points *= 0.8f;
-
- /* We treat +99 as 4 digits to make sure the (eyeballed) alignment looks nice. */
- int num_digits = 4;
- char number_text[4] = "+99\0";
- if (num_elements < 100) {
- BLI_snprintf(number_text, sizeof(number_text), "%d", num_elements);
- num_digits = num_elements < 10 ? 1 : 2;
- }
- UI_fontstyle_draw_simple(&fstyle_small,
- (offset_x + ufac + UI_UNIT_X * (2 - num_digits) * 0.12f),
- (float)ys - UI_UNIT_Y * 0.095f + ufac,
- number_text, text_col);
- UI_fontstyle_set(fstyle);
- GPU_blend(true); /* Roundbox and text drawing disables. */
+ float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ float ufac = 0.25f * UI_UNIT_X;
+ float offset_x = (float)offsx + UI_UNIT_X * 0.35f;
+
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_aa(true,
+ offset_x + ufac,
+ (float)ys - UI_UNIT_Y * 0.2f + ufac,
+ offset_x + UI_UNIT_X - ufac,
+ (float)ys - UI_UNIT_Y * 0.2f + UI_UNIT_Y - ufac,
+ (float)UI_UNIT_Y / 2.0f - ufac,
+ color);
+
+ /* Now the numbers. */
+ unsigned char text_col[4];
+
+ UI_GetThemeColor4ubv(TH_TEXT_HI, text_col);
+ text_col[3] = 255;
+
+ uiFontStyle fstyle_small = *fstyle;
+ fstyle_small.points *= 0.8f;
+
+ /* We treat +99 as 4 digits to make sure the (eyeballed) alignment looks nice. */
+ int num_digits = 4;
+ char number_text[4] = "+99\0";
+ if (num_elements < 100) {
+ BLI_snprintf(number_text, sizeof(number_text), "%d", num_elements);
+ num_digits = num_elements < 10 ? 1 : 2;
+ }
+ UI_fontstyle_draw_simple(&fstyle_small,
+ (offset_x + ufac + UI_UNIT_X * (2 - num_digits) * 0.12f),
+ (float)ys - UI_UNIT_Y * 0.095f + ufac,
+ number_text,
+ text_col);
+ UI_fontstyle_set(fstyle);
+ GPU_blend(true); /* Roundbox and text drawing disables. */
}
-static void outliner_draw_iconrow_doit(
- uiBlock *block, TreeElement *te,
- const uiFontStyle *fstyle,
- int xmax, int *offsx, int ys, float alpha_fac,
- const eOLDrawState active,
- const int num_elements)
+static void outliner_draw_iconrow_doit(uiBlock *block,
+ TreeElement *te,
+ const uiFontStyle *fstyle,
+ int xmax,
+ int *offsx,
+ int ys,
+ float alpha_fac,
+ const eOLDrawState active,
+ const int num_elements)
{
- TreeStoreElem *tselem = TREESTORE(te);
-
- if (active != OL_DRAWSEL_NONE) {
- float ufac = UI_UNIT_X / 20.0f;
- float color[4] = {1.0f, 1.0f, 1.0f, 0.2f};
-
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- color[3] *= alpha_fac;
-
- UI_draw_roundbox_aa(true,
- (float) *offsx + 1.0f * ufac,
- (float)ys + 1.0f * ufac,
- (float)*offsx + UI_UNIT_X - 1.0f * ufac,
- (float)ys + UI_UNIT_Y - ufac,
- (float)UI_UNIT_Y / 2.0f - ufac,
- color);
- GPU_blend(true); /* Roundbox disables. */
- }
-
- /* No inlined icon should be clickable. */
- tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.8f * alpha_fac, false);
- te->xs = *offsx;
- te->ys = ys;
- te->xend = (short)*offsx + UI_UNIT_X;
-
- if (num_elements > 1) {
- outliner_draw_iconrow_number(fstyle, *offsx, ys, num_elements);
- }
- (*offsx) += UI_UNIT_X;
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (active != OL_DRAWSEL_NONE) {
+ float ufac = UI_UNIT_X / 20.0f;
+ float color[4] = {1.0f, 1.0f, 1.0f, 0.2f};
+
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ color[3] *= alpha_fac;
+
+ UI_draw_roundbox_aa(true,
+ (float)*offsx + 1.0f * ufac,
+ (float)ys + 1.0f * ufac,
+ (float)*offsx + UI_UNIT_X - 1.0f * ufac,
+ (float)ys + UI_UNIT_Y - ufac,
+ (float)UI_UNIT_Y / 2.0f - ufac,
+ color);
+ GPU_blend(true); /* Roundbox disables. */
+ }
+
+ /* No inlined icon should be clickable. */
+ tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.8f * alpha_fac, false);
+ te->xs = *offsx;
+ te->ys = ys;
+ te->xend = (short)*offsx + UI_UNIT_X;
+
+ if (num_elements > 1) {
+ outliner_draw_iconrow_number(fstyle, *offsx, ys, num_elements);
+ }
+ (*offsx) += UI_UNIT_X;
}
/**
@@ -1591,675 +1912,764 @@ static void outliner_draw_iconrow_doit(
*/
static 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;
- if (id_index < INDEX_ID_OB) {
- return id_index;
- }
- else if (id_index == INDEX_ID_OB) {
- const Object *ob = (Object *)tselem->id;
- return INDEX_ID_OB + ob->type;
- }
- else {
- return id_index + OB_TYPE_MAX;
- }
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ const int id_index = tselem->type == 0 ? BKE_idcode_to_index(te->idcode) : INDEX_ID_GR;
+ if (id_index < INDEX_ID_OB) {
+ return id_index;
+ }
+ else if (id_index == INDEX_ID_OB) {
+ const Object *ob = (Object *)tselem->id;
+ return INDEX_ID_OB + ob->type;
+ }
+ else {
+ return id_index + OB_TYPE_MAX;
+ }
}
typedef struct MergedIconRow {
- eOLDrawState active[INDEX_ID_MAX + OB_TYPE_MAX];
- int num_elements[INDEX_ID_MAX + OB_TYPE_MAX];
- TreeElement *tree_element[INDEX_ID_MAX + OB_TYPE_MAX];
+ eOLDrawState active[INDEX_ID_MAX + OB_TYPE_MAX];
+ int num_elements[INDEX_ID_MAX + OB_TYPE_MAX];
+ TreeElement *tree_element[INDEX_ID_MAX + OB_TYPE_MAX];
} MergedIconRow;
-static void outliner_draw_iconrow(
- bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, ViewLayer *view_layer, SpaceOutliner *soops,
- ListBase *lb, int level, int xmax, int *offsx, int ys, float alpha_fac, MergedIconRow *merged)
+static void outliner_draw_iconrow(bContext *C,
+ uiBlock *block,
+ const uiFontStyle *fstyle,
+ Scene *scene,
+ ViewLayer *view_layer,
+ SpaceOutliner *soops,
+ ListBase *lb,
+ int level,
+ int xmax,
+ int *offsx,
+ int ys,
+ float alpha_fac,
+ MergedIconRow *merged)
{
- eOLDrawState active;
- const Object *obact = OBACT(view_layer);
-
- for (TreeElement *te = lb->first; te; te = te->next) {
- /* exit drawing early */
- if ((*offsx) - UI_UNIT_X > xmax) {
- break;
- }
-
- TreeStoreElem *tselem = TREESTORE(te);
-
- /* object hierarchy always, further constrained on level */
- if (level < 1 || (tselem->type == 0 && te->idcode == ID_OB)) {
- /* active blocks get white circle */
- if (tselem->type == 0) {
- if (te->idcode == ID_OB) {
- active = (OBACT(view_layer) == (Object *)tselem->id) ? OL_DRAWSEL_NORMAL : OL_DRAWSEL_NONE;
- }
- else if (is_object_data_in_editmode(tselem->id, obact)) {
- active = OL_DRAWSEL_NORMAL;
- }
- else {
- active = tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NONE, false);
- }
- }
- else {
- active = tree_element_type_active(C, scene, view_layer, soops, te, tselem, OL_SETSEL_NONE, false);
- }
-
- if (!ELEM(tselem->type, 0, TSE_LAYER_COLLECTION, TSE_R_LAYER)) {
- outliner_draw_iconrow_doit(block, te, fstyle, xmax, offsx, ys, alpha_fac, active, 1);
- }
- else {
- const int index = tree_element_id_type_to_index(te);
- merged->num_elements[index]++;
- if ((merged->tree_element[index] == NULL) ||
- (active > merged->active[index]))
- {
- merged->tree_element[index] = te;
- }
- merged->active[index] = MAX2(active, merged->active[index]);
- }
- }
-
- /* this tree element always has same amount of branches, so don't draw */
- if (tselem->type != TSE_R_LAYER) {
- outliner_draw_iconrow(
- C, block, fstyle, scene, view_layer, soops,
- &te->subtree, level + 1, xmax, offsx, ys, alpha_fac, merged);
- }
- }
-
- if (level == 0) {
- for (int i = 0; i < INDEX_ID_MAX; i++) {
- const int num_subtypes = (i == INDEX_ID_OB) ? OB_TYPE_MAX : 1;
- /* See tree_element_id_type_to_index for the index logic. */
- int index_base = i;
- if (i > INDEX_ID_OB) {
- index_base += OB_TYPE_MAX;
- }
- for (int j = 0; j < num_subtypes; j++) {
- const int index = index_base + j;
- if (merged->num_elements[index] != 0) {
- outliner_draw_iconrow_doit(block,
- merged->tree_element[index],
- fstyle,
- xmax, offsx, ys, alpha_fac,
- merged->active[index],
- merged->num_elements[index]);
- }
- }
- }
- }
+ eOLDrawState active;
+ const Object *obact = OBACT(view_layer);
+
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ /* exit drawing early */
+ if ((*offsx) - UI_UNIT_X > xmax) {
+ break;
+ }
+
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ /* object hierarchy always, further constrained on level */
+ if (level < 1 || (tselem->type == 0 && te->idcode == ID_OB)) {
+ /* active blocks get white circle */
+ if (tselem->type == 0) {
+ if (te->idcode == ID_OB) {
+ active = (OBACT(view_layer) == (Object *)tselem->id) ? OL_DRAWSEL_NORMAL :
+ OL_DRAWSEL_NONE;
+ }
+ else if (is_object_data_in_editmode(tselem->id, obact)) {
+ active = OL_DRAWSEL_NORMAL;
+ }
+ else {
+ active = tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NONE, false);
+ }
+ }
+ else {
+ active = tree_element_type_active(
+ C, scene, view_layer, soops, te, tselem, OL_SETSEL_NONE, false);
+ }
+
+ if (!ELEM(tselem->type, 0, TSE_LAYER_COLLECTION, TSE_R_LAYER)) {
+ outliner_draw_iconrow_doit(block, te, fstyle, xmax, offsx, ys, alpha_fac, active, 1);
+ }
+ else {
+ const int index = tree_element_id_type_to_index(te);
+ merged->num_elements[index]++;
+ if ((merged->tree_element[index] == NULL) || (active > merged->active[index])) {
+ merged->tree_element[index] = te;
+ }
+ merged->active[index] = MAX2(active, merged->active[index]);
+ }
+ }
+
+ /* this tree element always has same amount of branches, so don't draw */
+ if (tselem->type != TSE_R_LAYER) {
+ outliner_draw_iconrow(C,
+ block,
+ fstyle,
+ scene,
+ view_layer,
+ soops,
+ &te->subtree,
+ level + 1,
+ xmax,
+ offsx,
+ ys,
+ alpha_fac,
+ merged);
+ }
+ }
+
+ if (level == 0) {
+ for (int i = 0; i < INDEX_ID_MAX; i++) {
+ const int num_subtypes = (i == INDEX_ID_OB) ? OB_TYPE_MAX : 1;
+ /* See tree_element_id_type_to_index for the index logic. */
+ int index_base = i;
+ if (i > INDEX_ID_OB) {
+ index_base += OB_TYPE_MAX;
+ }
+ for (int j = 0; j < num_subtypes; j++) {
+ const int index = index_base + j;
+ if (merged->num_elements[index] != 0) {
+ outliner_draw_iconrow_doit(block,
+ merged->tree_element[index],
+ fstyle,
+ xmax,
+ offsx,
+ ys,
+ alpha_fac,
+ merged->active[index],
+ merged->num_elements[index]);
+ }
+ }
+ }
+ }
}
/* closed tree element */
static void outliner_set_coord_tree_element(TreeElement *te, int startx, int starty)
{
- TreeElement *ten;
-
- /* closed items may be displayed in row of parent, don't change their coordinate! */
- if ((te->flag & TE_ICONROW) == 0) {
- /* store coord and continue, we need coordinates for elements outside view too */
- te->xs = startx;
- te->ys = starty;
- }
-
- for (ten = te->subtree.first; ten; ten = ten->next) {
- outliner_set_coord_tree_element(ten, startx + UI_UNIT_X, starty);
- }
+ TreeElement *ten;
+
+ /* closed items may be displayed in row of parent, don't change their coordinate! */
+ if ((te->flag & TE_ICONROW) == 0) {
+ /* store coord and continue, we need coordinates for elements outside view too */
+ te->xs = startx;
+ te->ys = starty;
+ }
+
+ for (ten = te->subtree.first; ten; ten = ten->next) {
+ outliner_set_coord_tree_element(ten, startx + UI_UNIT_X, starty);
+ }
}
-
-static void outliner_draw_tree_element(
- bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, ViewLayer *view_layer,
- ARegion *ar, SpaceOutliner *soops, TreeElement *te, bool draw_grayed_out,
- int startx, int *starty, TreeElement **te_edit)
+static void outliner_draw_tree_element(bContext *C,
+ uiBlock *block,
+ const uiFontStyle *fstyle,
+ Scene *scene,
+ ViewLayer *view_layer,
+ ARegion *ar,
+ SpaceOutliner *soops,
+ TreeElement *te,
+ bool draw_grayed_out,
+ int startx,
+ int *starty,
+ TreeElement **te_edit)
{
- TreeStoreElem *tselem;
- float ufac = UI_UNIT_X / 20.0f;
- int offsx = 0;
- eOLDrawState active = OL_DRAWSEL_NONE;
- float color[4];
- tselem = TREESTORE(te);
-
- if (*starty + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && *starty <= ar->v2d.cur.ymax) {
- const float alpha_fac = ((te->flag & TE_DISABLED) || draw_grayed_out) ? 0.5f : 1.0f;
- const float alpha = 0.5f * alpha_fac;
- int xmax = ar->v2d.cur.xmax;
-
- if ((tselem->flag & TSE_TEXTBUT) && (*te_edit == NULL)) {
- *te_edit = te;
- }
-
- /* icons can be ui buts, we don't want it to overlap with restrict */
- if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0) {
- xmax -= OL_TOGW + UI_UNIT_X;
- }
-
- GPU_blend(true);
-
- /* colors for active/selected data */
- if (tselem->type == 0) {
- const Object *obact = OBACT(view_layer);
- if (te->idcode == ID_SCE) {
- if (tselem->id == (ID *)scene) {
- rgba_float_args_set(color, 1.0f, 1.0f, 1.0f, alpha);
- active = OL_DRAWSEL_ACTIVE;
- }
- }
- else if (te->idcode == ID_OB) {
- Object *ob = (Object *)tselem->id;
- Base *base = BKE_view_layer_base_find(view_layer, ob);
- const bool is_selected = (base != NULL) && ((base->flag & BASE_SELECTED) != 0);
-
- if (ob == obact || is_selected) {
- uchar col[4] = {0, 0, 0, 0};
-
- /* outliner active ob: always white text, circle color now similar to view3d */
-
- active = OL_DRAWSEL_ACTIVE;
- if (ob == obact) {
- if (is_selected) {
- UI_GetThemeColorType4ubv(TH_ACTIVE, SPACE_VIEW3D, col);
- col[3] = alpha;
- }
-
- active = OL_DRAWSEL_NORMAL;
- }
- else if (is_selected) {
- UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col);
- col[3] = alpha;
- }
- rgba_float_args_set(color, (float)col[0] / 255, (float)col[1] / 255, (float)col[2] / 255, alpha);
- }
- }
- else if (is_object_data_in_editmode(tselem->id, obact)) {
- rgba_float_args_set(color, 1.0f, 1.0f, 1.0f, alpha);
- active = OL_DRAWSEL_ACTIVE;
- }
- else {
- if (tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NONE, false)) {
- rgba_float_args_set(color, 0.85f, 0.85f, 1.0f, alpha);
- active = OL_DRAWSEL_ACTIVE;
- }
- }
- }
- else {
- active = tree_element_type_active(C, scene, view_layer, soops, te, tselem, OL_SETSEL_NONE, false);
- rgba_float_args_set(color, 0.85f, 0.85f, 1.0f, alpha);
- }
-
- /* active circle */
- if (active != OL_DRAWSEL_NONE) {
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_aa(
- true,
- (float)startx + UI_UNIT_X + 1.0f * ufac,
- (float)*starty + 1.0f * ufac,
- (float)startx + 2.0f * UI_UNIT_X - 1.0f * ufac,
- (float)*starty + UI_UNIT_Y - 1.0f * ufac,
- UI_UNIT_Y / 2.0f - 1.0f * ufac, color);
- GPU_blend(true); /* roundbox disables it */
-
- te->flag |= TE_ACTIVE; // for lookup in display hierarchies
- }
-
- if (tselem->type == TSE_VIEW_COLLECTION_BASE) {
- /* Scene collection in view layer can't expand/collapse. */
- }
- else if (te->subtree.first || (tselem->type == 0 && te->idcode == ID_SCE) || (te->flag & TE_LAZY_CLOSED)) {
- /* open/close icon, only when sublevels, except for scene */
- int icon_x = startx;
-
- // icons a bit higher
- if (TSELEM_OPEN(tselem, soops)) {
- UI_icon_draw_alpha(
- (float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_DOWN,
- alpha_fac);
- }
- else {
- UI_icon_draw_alpha(
- (float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_RIGHT,
- alpha_fac);
- }
- }
- offsx += UI_UNIT_X;
-
- /* datatype icon */
-
- if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE))) {
- tselem_draw_icon(block, xmax, (float)startx + offsx, (float)*starty, tselem, te, alpha_fac, true);
- offsx += UI_UNIT_X + 4 * ufac;
- }
- else {
- offsx += 2 * ufac;
- }
-
- if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) && ID_IS_LINKED(tselem->id)) {
- if (tselem->id->tag & LIB_TAG_MISSING) {
- UI_icon_draw_alpha(
- (float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN,
- alpha_fac);
- }
- else if (tselem->id->tag & LIB_TAG_INDIRECT) {
- UI_icon_draw_alpha(
- (float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_INDIRECT,
- alpha_fac);
- }
- else {
- UI_icon_draw_alpha(
- (float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT,
- alpha_fac);
- }
- offsx += UI_UNIT_X + 4 * ufac;
- }
- else if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) && ID_IS_STATIC_OVERRIDE(tselem->id)) {
- UI_icon_draw_alpha(
- (float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_OVERRIDE,
- alpha_fac);
- offsx += UI_UNIT_X + 4 * ufac;
- }
- GPU_blend(false);
-
- /* name */
- if ((tselem->flag & TSE_TEXTBUT) == 0) {
- unsigned char text_col[4];
-
- if (active == OL_DRAWSEL_NORMAL) {
- UI_GetThemeColor4ubv(TH_TEXT_HI, text_col);
- }
- else if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
- UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.75f, text_col);
- text_col[3] = 255;
- }
- else {
- UI_GetThemeColor4ubv(TH_TEXT, text_col);
- }
- text_col[3] *= alpha_fac;
-
- UI_fontstyle_draw_simple(fstyle, startx + offsx, *starty + 5 * ufac, te->name, text_col);
- }
-
- offsx += (int)(UI_UNIT_X + UI_fontstyle_string_width(fstyle, te->name));
-
- /* closed item, we draw the icons, not when it's a scene, or master-server list though */
- if (!TSELEM_OPEN(tselem, soops)) {
- if (te->subtree.first) {
- if (tselem->type == 0 && te->idcode == ID_SCE) {
- /* pass */
- }
- /* this tree element always has same amount of branches, so don't draw */
- else if (tselem->type != TSE_R_LAYER) {
- int tempx = startx + offsx;
-
- GPU_blend(true);
-
- /* divider */
- {
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- unsigned char col[4];
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- UI_GetThemeColorShade4ubv(TH_BACK, -40, col);
- col[3] *= alpha_fac;
-
- immUniformColor4ubv(col);
- immRecti(pos, tempx - 10.0f * ufac,
- *starty + 4.0f * ufac,
- tempx - 8.0f * ufac,
- *starty + UI_UNIT_Y - 4.0f * ufac);
- immUnbindProgram();
- }
-
- MergedIconRow merged = {{0}};
- outliner_draw_iconrow(
- C, block, fstyle, scene, view_layer, soops, &te->subtree, 0, xmax, &tempx,
- *starty, alpha_fac, &merged);
-
- GPU_blend(false);
- }
- }
- }
- }
- /* store coord and continue, we need coordinates for elements outside view too */
- te->xs = startx;
- te->ys = *starty;
- te->xend = startx + offsx;
-
- if (TSELEM_OPEN(tselem, soops)) {
- *starty -= UI_UNIT_Y;
-
- for (TreeElement *ten = te->subtree.first; ten; ten = ten->next) {
- /* 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);
- outliner_draw_tree_element(
- C, block, fstyle, scene, view_layer,
- ar, soops, ten, draw_childs_grayed_out,
- startx + UI_UNIT_X, starty, te_edit);
- }
- }
- else {
- for (TreeElement *ten = te->subtree.first; ten; ten = ten->next) {
- outliner_set_coord_tree_element(ten, startx, *starty);
- }
-
- *starty -= UI_UNIT_Y;
- }
+ TreeStoreElem *tselem;
+ float ufac = UI_UNIT_X / 20.0f;
+ int offsx = 0;
+ eOLDrawState active = OL_DRAWSEL_NONE;
+ float color[4];
+ tselem = TREESTORE(te);
+
+ if (*starty + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && *starty <= ar->v2d.cur.ymax) {
+ const float alpha_fac = ((te->flag & TE_DISABLED) || draw_grayed_out) ? 0.5f : 1.0f;
+ const float alpha = 0.5f * alpha_fac;
+ int xmax = ar->v2d.cur.xmax;
+
+ if ((tselem->flag & TSE_TEXTBUT) && (*te_edit == NULL)) {
+ *te_edit = te;
+ }
+
+ /* icons can be ui buts, we don't want it to overlap with restrict */
+ if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0) {
+ xmax -= OL_TOGW + UI_UNIT_X;
+ }
+
+ GPU_blend(true);
+
+ /* colors for active/selected data */
+ if (tselem->type == 0) {
+ const Object *obact = OBACT(view_layer);
+ if (te->idcode == ID_SCE) {
+ if (tselem->id == (ID *)scene) {
+ rgba_float_args_set(color, 1.0f, 1.0f, 1.0f, alpha);
+ active = OL_DRAWSEL_ACTIVE;
+ }
+ }
+ else if (te->idcode == ID_OB) {
+ Object *ob = (Object *)tselem->id;
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+ const bool is_selected = (base != NULL) && ((base->flag & BASE_SELECTED) != 0);
+
+ if (ob == obact || is_selected) {
+ uchar col[4] = {0, 0, 0, 0};
+
+ /* outliner active ob: always white text, circle color now similar to view3d */
+
+ active = OL_DRAWSEL_ACTIVE;
+ if (ob == obact) {
+ if (is_selected) {
+ UI_GetThemeColorType4ubv(TH_ACTIVE, SPACE_VIEW3D, col);
+ col[3] = alpha;
+ }
+
+ active = OL_DRAWSEL_NORMAL;
+ }
+ else if (is_selected) {
+ UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col);
+ col[3] = alpha;
+ }
+ rgba_float_args_set(
+ color, (float)col[0] / 255, (float)col[1] / 255, (float)col[2] / 255, alpha);
+ }
+ }
+ else if (is_object_data_in_editmode(tselem->id, obact)) {
+ rgba_float_args_set(color, 1.0f, 1.0f, 1.0f, alpha);
+ active = OL_DRAWSEL_ACTIVE;
+ }
+ else {
+ if (tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NONE, false)) {
+ rgba_float_args_set(color, 0.85f, 0.85f, 1.0f, alpha);
+ active = OL_DRAWSEL_ACTIVE;
+ }
+ }
+ }
+ else {
+ active = tree_element_type_active(
+ C, scene, view_layer, soops, te, tselem, OL_SETSEL_NONE, false);
+ rgba_float_args_set(color, 0.85f, 0.85f, 1.0f, alpha);
+ }
+
+ /* active circle */
+ if (active != OL_DRAWSEL_NONE) {
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_aa(true,
+ (float)startx + UI_UNIT_X + 1.0f * ufac,
+ (float)*starty + 1.0f * ufac,
+ (float)startx + 2.0f * UI_UNIT_X - 1.0f * ufac,
+ (float)*starty + UI_UNIT_Y - 1.0f * ufac,
+ UI_UNIT_Y / 2.0f - 1.0f * ufac,
+ color);
+ GPU_blend(true); /* roundbox disables it */
+
+ te->flag |= TE_ACTIVE; // for lookup in display hierarchies
+ }
+
+ if (tselem->type == TSE_VIEW_COLLECTION_BASE) {
+ /* Scene collection in view layer can't expand/collapse. */
+ }
+ else if (te->subtree.first || (tselem->type == 0 && te->idcode == ID_SCE) ||
+ (te->flag & TE_LAZY_CLOSED)) {
+ /* open/close icon, only when sublevels, except for scene */
+ int icon_x = startx;
+
+ // icons a bit higher
+ if (TSELEM_OPEN(tselem, soops)) {
+ UI_icon_draw_alpha((float)icon_x + 2 * ufac,
+ (float)*starty + 1 * ufac,
+ ICON_DISCLOSURE_TRI_DOWN,
+ alpha_fac);
+ }
+ else {
+ UI_icon_draw_alpha((float)icon_x + 2 * ufac,
+ (float)*starty + 1 * ufac,
+ ICON_DISCLOSURE_TRI_RIGHT,
+ alpha_fac);
+ }
+ }
+ offsx += UI_UNIT_X;
+
+ /* datatype icon */
+
+ if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE))) {
+ tselem_draw_icon(
+ block, xmax, (float)startx + offsx, (float)*starty, tselem, te, alpha_fac, true);
+ offsx += UI_UNIT_X + 4 * ufac;
+ }
+ else {
+ offsx += 2 * ufac;
+ }
+
+ if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) && ID_IS_LINKED(tselem->id)) {
+ if (tselem->id->tag & LIB_TAG_MISSING) {
+ UI_icon_draw_alpha((float)startx + offsx + 2 * ufac,
+ (float)*starty + 2 * ufac,
+ ICON_LIBRARY_DATA_BROKEN,
+ alpha_fac);
+ }
+ else if (tselem->id->tag & LIB_TAG_INDIRECT) {
+ UI_icon_draw_alpha((float)startx + offsx + 2 * ufac,
+ (float)*starty + 2 * ufac,
+ ICON_LIBRARY_DATA_INDIRECT,
+ alpha_fac);
+ }
+ else {
+ UI_icon_draw_alpha((float)startx + offsx + 2 * ufac,
+ (float)*starty + 2 * ufac,
+ ICON_LIBRARY_DATA_DIRECT,
+ alpha_fac);
+ }
+ offsx += UI_UNIT_X + 4 * ufac;
+ }
+ else if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) && ID_IS_STATIC_OVERRIDE(tselem->id)) {
+ UI_icon_draw_alpha((float)startx + offsx + 2 * ufac,
+ (float)*starty + 2 * ufac,
+ ICON_LIBRARY_DATA_OVERRIDE,
+ alpha_fac);
+ offsx += UI_UNIT_X + 4 * ufac;
+ }
+ GPU_blend(false);
+
+ /* name */
+ if ((tselem->flag & TSE_TEXTBUT) == 0) {
+ unsigned char text_col[4];
+
+ if (active == OL_DRAWSEL_NORMAL) {
+ UI_GetThemeColor4ubv(TH_TEXT_HI, text_col);
+ }
+ else if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
+ UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.75f, text_col);
+ text_col[3] = 255;
+ }
+ else {
+ UI_GetThemeColor4ubv(TH_TEXT, text_col);
+ }
+ text_col[3] *= alpha_fac;
+
+ UI_fontstyle_draw_simple(fstyle, startx + offsx, *starty + 5 * ufac, te->name, text_col);
+ }
+
+ offsx += (int)(UI_UNIT_X + UI_fontstyle_string_width(fstyle, te->name));
+
+ /* closed item, we draw the icons, not when it's a scene, or master-server list though */
+ if (!TSELEM_OPEN(tselem, soops)) {
+ if (te->subtree.first) {
+ if (tselem->type == 0 && te->idcode == ID_SCE) {
+ /* pass */
+ }
+ /* this tree element always has same amount of branches, so don't draw */
+ else if (tselem->type != TSE_R_LAYER) {
+ int tempx = startx + offsx;
+
+ GPU_blend(true);
+
+ /* divider */
+ {
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(
+ format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ unsigned char col[4];
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ UI_GetThemeColorShade4ubv(TH_BACK, -40, col);
+ col[3] *= alpha_fac;
+
+ immUniformColor4ubv(col);
+ immRecti(pos,
+ tempx - 10.0f * ufac,
+ *starty + 4.0f * ufac,
+ tempx - 8.0f * ufac,
+ *starty + UI_UNIT_Y - 4.0f * ufac);
+ immUnbindProgram();
+ }
+
+ MergedIconRow merged = {{0}};
+ outliner_draw_iconrow(C,
+ block,
+ fstyle,
+ scene,
+ view_layer,
+ soops,
+ &te->subtree,
+ 0,
+ xmax,
+ &tempx,
+ *starty,
+ alpha_fac,
+ &merged);
+
+ GPU_blend(false);
+ }
+ }
+ }
+ }
+ /* store coord and continue, we need coordinates for elements outside view too */
+ te->xs = startx;
+ te->ys = *starty;
+ te->xend = startx + offsx;
+
+ if (TSELEM_OPEN(tselem, soops)) {
+ *starty -= UI_UNIT_Y;
+
+ for (TreeElement *ten = te->subtree.first; ten; ten = ten->next) {
+ /* 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);
+ outliner_draw_tree_element(C,
+ block,
+ fstyle,
+ scene,
+ view_layer,
+ ar,
+ soops,
+ ten,
+ draw_childs_grayed_out,
+ startx + UI_UNIT_X,
+ starty,
+ te_edit);
+ }
+ }
+ else {
+ for (TreeElement *ten = te->subtree.first; ten; ten = ten->next) {
+ outliner_set_coord_tree_element(ten, startx, *starty);
+ }
+
+ *starty -= UI_UNIT_Y;
+ }
}
-static void outliner_draw_hierarchy_lines_recursive(
- unsigned pos, SpaceOutliner *soops, ListBase *lb, int startx,
- const unsigned char col[4], bool draw_grayed_out,
- int *starty)
+static void outliner_draw_hierarchy_lines_recursive(unsigned pos,
+ SpaceOutliner *soops,
+ ListBase *lb,
+ int startx,
+ const unsigned char col[4],
+ bool draw_grayed_out,
+ int *starty)
{
- TreeElement *te, *te_vertical_line_last = NULL;
- int y1, y2;
-
- if (BLI_listbase_is_empty(lb)) {
- return;
- }
-
- const unsigned char grayed_alpha = col[3] / 2;
-
- /* For vertical lines between objects. */
- y1 = y2 = *starty;
- for (te = lb->first; te; te = te->next) {
- bool draw_childs_grayed_out = draw_grayed_out || (te->flag & TE_DRAGGING);
- TreeStoreElem *tselem = TREESTORE(te);
-
- if (draw_childs_grayed_out) {
- immUniformColor3ubvAlpha(col, grayed_alpha);
- }
- else {
- immUniformColor4ubv(col);
- }
-
- /* Horizontal Line? */
- if (tselem->type == 0 && (te->idcode == ID_OB || te->idcode == ID_SCE)) {
- immRecti(pos, startx, *starty, startx + UI_UNIT_X, *starty - 1);
-
- /* Vertical Line? */
- if (te->idcode == ID_OB) {
- te_vertical_line_last = te;
- y2 = *starty;
- }
- }
-
- *starty -= UI_UNIT_Y;
-
- if (TSELEM_OPEN(tselem, soops)) {
- outliner_draw_hierarchy_lines_recursive(
- pos, soops, &te->subtree, startx + UI_UNIT_X,
- col, draw_childs_grayed_out, starty);
- }
- }
-
- if (draw_grayed_out) {
- immUniformColor3ubvAlpha(col, grayed_alpha);
- }
- else {
- immUniformColor4ubv(col);
- }
-
- /* Vertical line. */
- te = te_vertical_line_last;
- if ((te != NULL) && (te->parent || lb->first != lb->last)) {
- immRecti(pos, startx, y1 + UI_UNIT_Y, startx + 1, y2);
- }
+ TreeElement *te, *te_vertical_line_last = NULL;
+ int y1, y2;
+
+ if (BLI_listbase_is_empty(lb)) {
+ return;
+ }
+
+ const unsigned char grayed_alpha = col[3] / 2;
+
+ /* For vertical lines between objects. */
+ y1 = y2 = *starty;
+ for (te = lb->first; te; te = te->next) {
+ bool draw_childs_grayed_out = draw_grayed_out || (te->flag & TE_DRAGGING);
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (draw_childs_grayed_out) {
+ immUniformColor3ubvAlpha(col, grayed_alpha);
+ }
+ else {
+ immUniformColor4ubv(col);
+ }
+
+ /* Horizontal Line? */
+ if (tselem->type == 0 && (te->idcode == ID_OB || te->idcode == ID_SCE)) {
+ immRecti(pos, startx, *starty, startx + UI_UNIT_X, *starty - 1);
+
+ /* Vertical Line? */
+ if (te->idcode == ID_OB) {
+ te_vertical_line_last = te;
+ y2 = *starty;
+ }
+ }
+
+ *starty -= UI_UNIT_Y;
+
+ if (TSELEM_OPEN(tselem, soops)) {
+ outliner_draw_hierarchy_lines_recursive(
+ pos, soops, &te->subtree, startx + UI_UNIT_X, col, draw_childs_grayed_out, starty);
+ }
+ }
+
+ if (draw_grayed_out) {
+ immUniformColor3ubvAlpha(col, grayed_alpha);
+ }
+ else {
+ immUniformColor4ubv(col);
+ }
+
+ /* Vertical line. */
+ te = te_vertical_line_last;
+ if ((te != NULL) && (te->parent || lb->first != lb->last)) {
+ immRecti(pos, startx, y1 + UI_UNIT_Y, startx + 1, y2);
+ }
}
-static void outliner_draw_hierarchy_lines(SpaceOutliner *soops, ListBase *lb, int startx, int *starty)
+static void outliner_draw_hierarchy_lines(SpaceOutliner *soops,
+ ListBase *lb,
+ int startx,
+ int *starty)
{
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- unsigned char col[4];
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ unsigned char col[4];
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.4f, col);
- col[3] = 255;
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.4f, col);
+ col[3] = 255;
- GPU_blend(true);
- outliner_draw_hierarchy_lines_recursive(pos, soops, lb, startx, col, false, starty);
- GPU_blend(false);
+ GPU_blend(true);
+ outliner_draw_hierarchy_lines_recursive(pos, soops, lb, startx, col, false, starty);
+ GPU_blend(false);
- immUnbindProgram();
+ immUnbindProgram();
}
-static void outliner_draw_struct_marks(ARegion *ar, SpaceOutliner *soops, ListBase *lb, int *starty)
+static void outliner_draw_struct_marks(ARegion *ar,
+ SpaceOutliner *soops,
+ ListBase *lb,
+ int *starty)
{
- for (TreeElement *te = lb->first; te; te = te->next) {
- TreeStoreElem *tselem = TREESTORE(te);
-
- /* selection status */
- if (TSELEM_OPEN(tselem, soops)) {
- if (tselem->type == TSE_RNA_STRUCT) {
- GPUVertFormat *format = immVertexFormat();
- 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);
- immUnbindProgram();
- }
- }
-
- *starty -= UI_UNIT_Y;
- if (TSELEM_OPEN(tselem, soops)) {
- outliner_draw_struct_marks(ar, 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);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immThemeColorShadeAlpha(TH_BACK, -15, -200);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, 0, (float)*starty + UI_UNIT_Y);
- immVertex2f(pos, ar->v2d.cur.xmax, (float)*starty + UI_UNIT_Y);
- immEnd();
-
- immUnbindProgram();
- }
- }
- }
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ /* selection status */
+ if (TSELEM_OPEN(tselem, soops)) {
+ if (tselem->type == TSE_RNA_STRUCT) {
+ GPUVertFormat *format = immVertexFormat();
+ 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);
+ immUnbindProgram();
+ }
+ }
+
+ *starty -= UI_UNIT_Y;
+ if (TSELEM_OPEN(tselem, soops)) {
+ outliner_draw_struct_marks(ar, 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);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immThemeColorShadeAlpha(TH_BACK, -15, -200);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, 0, (float)*starty + UI_UNIT_Y);
+ immVertex2f(pos, ar->v2d.cur.xmax, (float)*starty + UI_UNIT_Y);
+ immEnd();
+
+ immUnbindProgram();
+ }
+ }
+ }
}
-static void outliner_draw_highlights_recursive(
- unsigned pos, const ARegion *ar, const SpaceOutliner *soops, const ListBase *lb,
- const float col_selection[4], const float col_highlight[4], const float col_searchmatch[4],
- int start_x, int *io_start_y)
+static void outliner_draw_highlights_recursive(unsigned pos,
+ const ARegion *ar,
+ const SpaceOutliner *soops,
+ const ListBase *lb,
+ const float col_selection[4],
+ const float col_highlight[4],
+ const float col_searchmatch[4],
+ int start_x,
+ int *io_start_y)
{
- 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) {
- const TreeStoreElem *tselem = TREESTORE(te);
- const int start_y = *io_start_y;
-
- /* selection status */
- if (tselem->flag & TSE_SELECTED) {
- immUniformColor4fv(col_selection);
- immRecti(pos, 0, start_y + 1, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1);
- }
-
- /* highlights */
- if (tselem->flag & (TSE_DRAG_ANY | TSE_HIGHLIGHTED | TSE_SEARCHMATCH)) {
- const int end_x = (int)ar->v2d.cur.xmax;
-
- if (tselem->flag & TSE_DRAG_ANY) {
- /* drag and drop highlight */
- float col[4];
- UI_GetThemeColorShade4fv(TH_BACK, -40, col);
-
- if (tselem->flag & TSE_DRAG_BEFORE) {
- immUniformColor4fv(col);
- immRecti(pos, start_x, start_y + UI_UNIT_Y - 1, end_x, start_y + UI_UNIT_Y + 1);
- }
- else if (tselem->flag & TSE_DRAG_AFTER) {
- immUniformColor4fv(col);
- immRecti(pos, start_x, start_y - 1, end_x, start_y + 1);
- }
- else {
- immUniformColor3fvAlpha(col, col[3] * 0.5f);
- immRecti(pos, start_x, start_y + 1, end_x, start_y + UI_UNIT_Y - 1);
- }
- }
- else {
- if (is_searching && (tselem->flag & TSE_SEARCHMATCH)) {
- /* search match highlights
- * we don't expand items when searching in the datablocks but we
- * still want to highlight any filter matches. */
- immUniformColor4fv(col_searchmatch);
- immRecti(pos, start_x, start_y + 1, end_x, start_y + UI_UNIT_Y - 1);
- }
- else if (tselem->flag & TSE_HIGHLIGHTED) {
- /* mouse hover highlight */
- immUniformColor4fv(col_highlight);
- immRecti(pos, 0, start_y + 1, end_x, start_y + UI_UNIT_Y - 1);
- }
- }
- }
-
- *io_start_y -= UI_UNIT_Y;
- if (TSELEM_OPEN(tselem, soops)) {
- outliner_draw_highlights_recursive(
- pos, ar, soops, &te->subtree, col_selection, col_highlight, col_searchmatch,
- start_x + UI_UNIT_X, io_start_y);
- }
- }
+ 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) {
+ const TreeStoreElem *tselem = TREESTORE(te);
+ const int start_y = *io_start_y;
+
+ /* selection status */
+ if (tselem->flag & TSE_SELECTED) {
+ immUniformColor4fv(col_selection);
+ immRecti(pos, 0, start_y + 1, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1);
+ }
+
+ /* highlights */
+ if (tselem->flag & (TSE_DRAG_ANY | TSE_HIGHLIGHTED | TSE_SEARCHMATCH)) {
+ const int end_x = (int)ar->v2d.cur.xmax;
+
+ if (tselem->flag & TSE_DRAG_ANY) {
+ /* drag and drop highlight */
+ float col[4];
+ UI_GetThemeColorShade4fv(TH_BACK, -40, col);
+
+ if (tselem->flag & TSE_DRAG_BEFORE) {
+ immUniformColor4fv(col);
+ immRecti(pos, start_x, start_y + UI_UNIT_Y - 1, end_x, start_y + UI_UNIT_Y + 1);
+ }
+ else if (tselem->flag & TSE_DRAG_AFTER) {
+ immUniformColor4fv(col);
+ immRecti(pos, start_x, start_y - 1, end_x, start_y + 1);
+ }
+ else {
+ immUniformColor3fvAlpha(col, col[3] * 0.5f);
+ immRecti(pos, start_x, start_y + 1, end_x, start_y + UI_UNIT_Y - 1);
+ }
+ }
+ else {
+ if (is_searching && (tselem->flag & TSE_SEARCHMATCH)) {
+ /* search match highlights
+ * we don't expand items when searching in the datablocks but we
+ * still want to highlight any filter matches. */
+ immUniformColor4fv(col_searchmatch);
+ immRecti(pos, start_x, start_y + 1, end_x, start_y + UI_UNIT_Y - 1);
+ }
+ else if (tselem->flag & TSE_HIGHLIGHTED) {
+ /* mouse hover highlight */
+ immUniformColor4fv(col_highlight);
+ immRecti(pos, 0, start_y + 1, end_x, start_y + UI_UNIT_Y - 1);
+ }
+ }
+ }
+
+ *io_start_y -= UI_UNIT_Y;
+ if (TSELEM_OPEN(tselem, soops)) {
+ outliner_draw_highlights_recursive(pos,
+ ar,
+ soops,
+ &te->subtree,
+ col_selection,
+ col_highlight,
+ col_searchmatch,
+ start_x + UI_UNIT_X,
+ io_start_y);
+ }
+ }
}
static void outliner_draw_highlights(ARegion *ar, SpaceOutliner *soops, int startx, int *starty)
{
- const float col_highlight[4] = {1.0f, 1.0f, 1.0f, 0.13f};
- float col_selection[4], col_searchmatch[4];
-
- UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, col_selection);
- col_selection[3] = 1.0f; /* no alpha */
- UI_GetThemeColor4fv(TH_MATCH, col_searchmatch);
- col_searchmatch[3] = 0.5f;
-
- GPU_blend(true);
- GPUVertFormat *format = immVertexFormat();
- 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, soops, &soops->tree, col_selection, col_highlight, col_searchmatch,
- startx, starty);
- immUnbindProgram();
- GPU_blend(false);
+ const float col_highlight[4] = {1.0f, 1.0f, 1.0f, 0.13f};
+ float col_selection[4], col_searchmatch[4];
+
+ UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, col_selection);
+ col_selection[3] = 1.0f; /* no alpha */
+ UI_GetThemeColor4fv(TH_MATCH, col_searchmatch);
+ col_searchmatch[3] = 0.5f;
+
+ GPU_blend(true);
+ GPUVertFormat *format = immVertexFormat();
+ 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, soops, &soops->tree, col_selection, col_highlight, col_searchmatch, startx, starty);
+ immUnbindProgram();
+ GPU_blend(false);
}
-static void outliner_draw_tree(
- bContext *C, uiBlock *block, Scene *scene, ViewLayer *view_layer,
- ARegion *ar, SpaceOutliner *soops, const bool has_restrict_icons,
- TreeElement **te_edit)
+static void outliner_draw_tree(bContext *C,
+ uiBlock *block,
+ Scene *scene,
+ ViewLayer *view_layer,
+ ARegion *ar,
+ SpaceOutliner *soops,
+ const bool has_restrict_icons,
+ TreeElement **te_edit)
{
- const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- int starty, startx;
-
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); // only once
-
- 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);
- }
-
- /* draw highlights before hierarchy */
- starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
- startx = 0;
- outliner_draw_highlights(ar, soops, startx, &starty);
-
- /* set scissor so tree elements or lines can't overlap restriction icons */
- float scissor[4] = {0};
- if (has_restrict_icons) {
- int mask_x = BLI_rcti_size_x(&ar->v2d.mask) - (int)OL_TOGW + 1;
- CLAMP_MIN(mask_x, 0);
-
- GPU_scissor_get_f(scissor);
- GPU_scissor(0, 0, mask_x, ar->winy);
- }
-
- // gray hierarchy lines
-
- starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y / 2 - OL_Y_OFFSET;
- startx = UI_UNIT_X / 2 - 1.0f;
- outliner_draw_hierarchy_lines(soops, &soops->tree, startx, &starty);
-
- // items themselves
- starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
- startx = 0;
- for (TreeElement *te = soops->tree.first; te; te = te->next) {
- outliner_draw_tree_element(
- C, block, fstyle, scene, view_layer,
- ar, soops, te, (te->flag & TE_DRAGGING) != 0,
- startx, &starty, te_edit);
- }
-
- if (has_restrict_icons) {
- /* reset scissor */
- GPU_scissor(UNPACK4(scissor));
- }
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ int starty, startx;
+
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); // only once
+
+ 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);
+ }
+
+ /* draw highlights before hierarchy */
+ starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
+ startx = 0;
+ outliner_draw_highlights(ar, soops, startx, &starty);
+
+ /* set scissor so tree elements or lines can't overlap restriction icons */
+ float scissor[4] = {0};
+ if (has_restrict_icons) {
+ int mask_x = BLI_rcti_size_x(&ar->v2d.mask) - (int)OL_TOGW + 1;
+ CLAMP_MIN(mask_x, 0);
+
+ GPU_scissor_get_f(scissor);
+ GPU_scissor(0, 0, mask_x, ar->winy);
+ }
+
+ // gray hierarchy lines
+
+ starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y / 2 - OL_Y_OFFSET;
+ startx = UI_UNIT_X / 2 - 1.0f;
+ outliner_draw_hierarchy_lines(soops, &soops->tree, startx, &starty);
+
+ // items themselves
+ starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
+ startx = 0;
+ for (TreeElement *te = soops->tree.first; te; te = te->next) {
+ outliner_draw_tree_element(C,
+ block,
+ fstyle,
+ scene,
+ view_layer,
+ ar,
+ soops,
+ te,
+ (te->flag & TE_DRAGGING) != 0,
+ startx,
+ &starty,
+ te_edit);
+ }
+
+ if (has_restrict_icons) {
+ /* reset scissor */
+ GPU_scissor(UNPACK4(scissor));
+ }
}
-
static void outliner_back(ARegion *ar)
{
- int ystart;
-
- ystart = (int)ar->v2d.tot.ymax;
- ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET;
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColorShade(TH_BACK, 6);
-
- const float x1 = 0.0f, x2 = ar->v2d.cur.xmax;
- float y1 = ystart, y2;
- int tot = (int)floor(ystart - ar->v2d.cur.ymin + 2 * UI_UNIT_Y) / (2 * UI_UNIT_Y);
-
- if (tot > 0) {
- immBegin(GPU_PRIM_TRIS, 6 * tot);
- while (tot--) {
- y1 -= 2 * UI_UNIT_Y;
- y2 = y1 + UI_UNIT_Y;
- immVertex2f(pos, x1, y1);
- immVertex2f(pos, x2, y1);
- immVertex2f(pos, x2, y2);
-
- immVertex2f(pos, x1, y1);
- immVertex2f(pos, x2, y2);
- immVertex2f(pos, x1, y2);
- }
- immEnd();
- }
- immUnbindProgram();
+ int ystart;
+
+ ystart = (int)ar->v2d.tot.ymax;
+ ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET;
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShade(TH_BACK, 6);
+
+ const float x1 = 0.0f, x2 = ar->v2d.cur.xmax;
+ float y1 = ystart, y2;
+ int tot = (int)floor(ystart - ar->v2d.cur.ymin + 2 * UI_UNIT_Y) / (2 * UI_UNIT_Y);
+
+ if (tot > 0) {
+ immBegin(GPU_PRIM_TRIS, 6 * tot);
+ while (tot--) {
+ y1 -= 2 * UI_UNIT_Y;
+ y2 = y1 + UI_UNIT_Y;
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x2, y2);
+
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x1, y2);
+ }
+ immEnd();
+ }
+ immUnbindProgram();
}
static void outliner_draw_restrictcols(ARegion *ar)
{
- GPU_line_width(1.0f);
+ GPU_line_width(1.0f);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColorShadeAlpha(TH_BACK, -15, -200);
- immBegin(GPU_PRIM_LINES, 6);
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShadeAlpha(TH_BACK, -15, -200);
+ immBegin(GPU_PRIM_LINES, 6);
- immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)ar->v2d.cur.ymax);
- immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)ar->v2d.cur.ymin);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)ar->v2d.cur.ymax);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)ar->v2d.cur.ymin);
- immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)ar->v2d.cur.ymax);
- immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)ar->v2d.cur.ymin);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)ar->v2d.cur.ymax);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)ar->v2d.cur.ymin);
- immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)ar->v2d.cur.ymax);
- immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)ar->v2d.cur.ymin);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)ar->v2d.cur.ymax);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)ar->v2d.cur.ymin);
- immEnd();
- immUnbindProgram();
+ immEnd();
+ immUnbindProgram();
}
/* ****************************************************** */
@@ -2267,106 +2677,105 @@ static void outliner_draw_restrictcols(ARegion *ar)
void draw_outliner(const bContext *C)
{
- Main *mainvar = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = &ar->v2d;
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- uiBlock *block;
- int sizey = 0, sizex = 0, sizex_rna = 0;
- TreeElement *te_edit = NULL;
- bool has_restrict_icons;
-
- outliner_build_tree(mainvar, scene, view_layer, soops, ar); // always
-
- /* get extents of data */
- outliner_height(soops, &soops->tree, &sizey);
-
- /* extend size to allow for horizontal scrollbar */
- sizey += V2D_SCROLL_HEIGHT;
-
- if (soops->outlinevis == SO_DATA_API) {
- /* RNA has two columns:
- * - column 1 is (max_width + OL_RNA_COL_SPACEX) or
- * (OL_RNA_COL_X), whichever is wider...
- * - column 2 is fixed at OL_RNA_COL_SIZEX
- *
- * (*) XXX max width for now is a fixed factor of (UI_UNIT_X * (max_indention + 100))
- */
-
- /* get actual width of column 1 */
- outliner_rna_width(soops, &soops->tree, &sizex_rna, 0);
- sizex_rna = max_ii(OL_RNA_COLX, sizex_rna + OL_RNA_COL_SPACEX);
-
- /* get width of data (for setting 'tot' rect, this is column 1 + column 2 + a bit extra) */
- sizex = sizex_rna + OL_RNA_COL_SIZEX + 50;
- has_restrict_icons = false;
- }
- else {
- /* width must take into account restriction columns (if visible)
- * so that entries will still be visible */
- //outliner_width(soops, &soops->tree, &sizex);
- // XXX should use outliner_width instead when te->xend will be set correctly...
- outliner_rna_width(soops, &soops->tree, &sizex, 0);
-
- /* constant offset for restriction columns */
- // XXX this isn't that great yet...
- if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0) {
- sizex += OL_TOGW * 3;
- }
-
- has_restrict_icons = !(soops->flag & SO_HIDE_RESTRICTCOLS);
- }
-
- /* adds vertical offset */
- sizey += OL_Y_OFFSET;
-
- /* update size of tot-rect (extents of data/viewable area) */
- UI_view2d_totRect_set(v2d, sizex, sizey);
-
- /* force display to pixel coords */
- v2d->flag |= (V2D_PIXELOFS_X | V2D_PIXELOFS_Y);
- /* set matrix for 2d-view controls */
- UI_view2d_view_ortho(v2d);
-
- /* draw outliner stuff (background, hierarchy lines and names) */
- outliner_back(ar);
- block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
- outliner_draw_tree(
- (bContext *)C, block, scene, view_layer,
- ar, soops, has_restrict_icons, &te_edit);
-
- /* Default to no emboss for outliner UI. */
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
- if (soops->outlinevis == SO_DATA_API) {
- /* draw rna buttons */
- outliner_draw_rnacols(ar, sizex_rna);
-
- UI_block_emboss_set(block, UI_EMBOSS);
- outliner_draw_rnabuts(block, ar, soops, sizex_rna, &soops->tree);
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- }
- else if ((soops->outlinevis == SO_ID_ORPHANS) && has_restrict_icons) {
- /* draw user toggle columns */
- outliner_draw_restrictcols(ar);
- outliner_draw_userbuts(block, ar, soops, &soops->tree);
- }
- else if (has_restrict_icons) {
- /* draw restriction columns */
- outliner_draw_restrictcols(ar);
-
- outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &soops->tree);
- }
-
- UI_block_emboss_set(block, UI_EMBOSS);
-
- /* draw edit buttons if nessecery */
- if (te_edit) {
- outliner_buttons(C, block, ar, te_edit);
- }
-
- UI_block_end(C, block);
- UI_block_draw(C, block);
+ Main *mainvar = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ ARegion *ar = CTX_wm_region(C);
+ View2D *v2d = &ar->v2d;
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ uiBlock *block;
+ int sizey = 0, sizex = 0, sizex_rna = 0;
+ TreeElement *te_edit = NULL;
+ bool has_restrict_icons;
+
+ outliner_build_tree(mainvar, scene, view_layer, soops, ar); // always
+
+ /* get extents of data */
+ outliner_height(soops, &soops->tree, &sizey);
+
+ /* extend size to allow for horizontal scrollbar */
+ sizey += V2D_SCROLL_HEIGHT;
+
+ if (soops->outlinevis == SO_DATA_API) {
+ /* RNA has two columns:
+ * - column 1 is (max_width + OL_RNA_COL_SPACEX) or
+ * (OL_RNA_COL_X), whichever is wider...
+ * - column 2 is fixed at OL_RNA_COL_SIZEX
+ *
+ * (*) XXX max width for now is a fixed factor of (UI_UNIT_X * (max_indention + 100))
+ */
+
+ /* get actual width of column 1 */
+ outliner_rna_width(soops, &soops->tree, &sizex_rna, 0);
+ sizex_rna = max_ii(OL_RNA_COLX, sizex_rna + OL_RNA_COL_SPACEX);
+
+ /* get width of data (for setting 'tot' rect, this is column 1 + column 2 + a bit extra) */
+ sizex = sizex_rna + OL_RNA_COL_SIZEX + 50;
+ has_restrict_icons = false;
+ }
+ else {
+ /* width must take into account restriction columns (if visible)
+ * so that entries will still be visible */
+ //outliner_width(soops, &soops->tree, &sizex);
+ // XXX should use outliner_width instead when te->xend will be set correctly...
+ outliner_rna_width(soops, &soops->tree, &sizex, 0);
+
+ /* constant offset for restriction columns */
+ // XXX this isn't that great yet...
+ if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0) {
+ sizex += OL_TOGW * 3;
+ }
+
+ has_restrict_icons = !(soops->flag & SO_HIDE_RESTRICTCOLS);
+ }
+
+ /* adds vertical offset */
+ sizey += OL_Y_OFFSET;
+
+ /* update size of tot-rect (extents of data/viewable area) */
+ UI_view2d_totRect_set(v2d, sizex, sizey);
+
+ /* force display to pixel coords */
+ v2d->flag |= (V2D_PIXELOFS_X | V2D_PIXELOFS_Y);
+ /* set matrix for 2d-view controls */
+ UI_view2d_view_ortho(v2d);
+
+ /* draw outliner stuff (background, hierarchy lines and names) */
+ outliner_back(ar);
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ outliner_draw_tree(
+ (bContext *)C, block, scene, view_layer, ar, soops, has_restrict_icons, &te_edit);
+
+ /* Default to no emboss for outliner UI. */
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+
+ if (soops->outlinevis == SO_DATA_API) {
+ /* draw rna buttons */
+ outliner_draw_rnacols(ar, sizex_rna);
+
+ UI_block_emboss_set(block, UI_EMBOSS);
+ outliner_draw_rnabuts(block, ar, soops, sizex_rna, &soops->tree);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ }
+ else if ((soops->outlinevis == SO_ID_ORPHANS) && has_restrict_icons) {
+ /* draw user toggle columns */
+ outliner_draw_restrictcols(ar);
+ outliner_draw_userbuts(block, ar, soops, &soops->tree);
+ }
+ else if (has_restrict_icons) {
+ /* draw restriction columns */
+ outliner_draw_restrictcols(ar);
+
+ outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &soops->tree);
+ }
+
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ /* draw edit buttons if nessecery */
+ if (te_edit) {
+ outliner_buttons(C, block, ar, te_edit);
+ }
+
+ UI_block_end(C, block);
+ UI_block_draw(C, block);
}
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 8b8dff9dc27..11d01931945 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -88,773 +88,840 @@
static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- /* Drag and drop does own highlighting. */
- wmWindowManager *wm = CTX_wm_manager(C);
- if (wm->drags.first) {
- return OPERATOR_PASS_THROUGH;
- }
+ /* Drag and drop does own highlighting. */
+ wmWindowManager *wm = CTX_wm_manager(C);
+ if (wm->drags.first) {
+ return OPERATOR_PASS_THROUGH;
+ }
- ARegion *ar = CTX_wm_region(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- const float my = UI_view2d_region_to_view_y(&ar->v2d, event->mval[1]);
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ const float my = UI_view2d_region_to_view_y(&ar->v2d, event->mval[1]);
- TreeElement *hovered_te = outliner_find_item_at_y(soops, &soops->tree, my);
- bool changed = false;
+ TreeElement *hovered_te = outliner_find_item_at_y(soops, &soops->tree, my);
+ bool changed = false;
- if (!hovered_te || !(hovered_te->store_elem->flag & TSE_HIGHLIGHTED)) {
- changed = outliner_flag_set(&soops->tree, TSE_HIGHLIGHTED | TSE_DRAG_ANY, false);
- if (hovered_te) {
- hovered_te->store_elem->flag |= TSE_HIGHLIGHTED;
- changed = true;
- }
- }
+ if (!hovered_te || !(hovered_te->store_elem->flag & TSE_HIGHLIGHTED)) {
+ changed = outliner_flag_set(&soops->tree, TSE_HIGHLIGHTED | TSE_DRAG_ANY, false);
+ if (hovered_te) {
+ hovered_te->store_elem->flag |= TSE_HIGHLIGHTED;
+ changed = true;
+ }
+ }
- if (changed) {
- ED_region_tag_redraw_no_rebuild(ar);
- }
+ if (changed) {
+ ED_region_tag_redraw_no_rebuild(ar);
+ }
- return OPERATOR_PASS_THROUGH;
+ return OPERATOR_PASS_THROUGH;
}
void OUTLINER_OT_highlight_update(wmOperatorType *ot)
{
- ot->name = "Update Highlight";
- ot->idname = "OUTLINER_OT_highlight_update";
- ot->description = "Update the item highlight based on the current mouse position";
+ ot->name = "Update Highlight";
+ ot->idname = "OUTLINER_OT_highlight_update";
+ ot->description = "Update the item highlight based on the current mouse position";
- ot->invoke = outliner_highlight_update;
+ ot->invoke = outliner_highlight_update;
- ot->poll = ED_operator_outliner_active;
+ ot->poll = ED_operator_outliner_active;
}
/* Toggle Open/Closed ------------------------------------------- */
-static int do_outliner_item_openclose(bContext *C, SpaceOutliner *soops, TreeElement *te, const bool all, const float mval[2])
+static int do_outliner_item_openclose(
+ bContext *C, SpaceOutliner *soops, TreeElement *te, const bool all, const float mval[2])
{
- if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
- TreeStoreElem *tselem = TREESTORE(te);
+ if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
+ TreeStoreElem *tselem = TREESTORE(te);
- /* all below close/open? */
- if (all) {
- tselem->flag &= ~TSE_CLOSED;
- outliner_flag_set(&te->subtree, TSE_CLOSED, !outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1));
- }
- else {
- if (tselem->flag & TSE_CLOSED) {
- tselem->flag &= ~TSE_CLOSED;
- }
- else {
- tselem->flag |= TSE_CLOSED;
- }
- }
+ /* all below close/open? */
+ if (all) {
+ tselem->flag &= ~TSE_CLOSED;
+ outliner_flag_set(
+ &te->subtree, TSE_CLOSED, !outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1));
+ }
+ else {
+ if (tselem->flag & TSE_CLOSED) {
+ tselem->flag &= ~TSE_CLOSED;
+ }
+ else {
+ tselem->flag |= TSE_CLOSED;
+ }
+ }
- return 1;
- }
-
- for (te = te->subtree.first; te; te = te->next) {
- if (do_outliner_item_openclose(C, soops, te, all, mval)) {
- return 1;
- }
- }
- return 0;
+ return 1;
+ }
+ for (te = te->subtree.first; te; te = te->next) {
+ if (do_outliner_item_openclose(C, soops, te, all, mval)) {
+ return 1;
+ }
+ }
+ return 0;
}
/* event can enterkey, then it opens/closes */
static int outliner_item_openclose(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- TreeElement *te;
- float fmval[2];
- const bool all = RNA_boolean_get(op->ptr, "all");
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ TreeElement *te;
+ float fmval[2];
+ const bool all = RNA_boolean_get(op->ptr, "all");
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
- for (te = soops->tree.first; te; te = te->next) {
- if (do_outliner_item_openclose(C, soops, te, all, fmval)) {
- break;
- }
- }
+ for (te = soops->tree.first; te; te = te->next) {
+ if (do_outliner_item_openclose(C, soops, te, all, fmval)) {
+ break;
+ }
+ }
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_item_openclose(wmOperatorType *ot)
{
- ot->name = "Open/Close";
- ot->idname = "OUTLINER_OT_item_openclose";
- ot->description = "Toggle whether item under cursor is enabled or closed";
+ ot->name = "Open/Close";
+ ot->idname = "OUTLINER_OT_item_openclose";
+ ot->description = "Toggle whether item under cursor is enabled or closed";
- ot->invoke = outliner_item_openclose;
+ ot->invoke = outliner_item_openclose;
- ot->poll = ED_operator_outliner_active;
+ ot->poll = ED_operator_outliner_active;
- RNA_def_boolean(ot->srna, "all", 1, "All", "Close or open all items");
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Close or open all items");
}
/* -------------------------------------------------------------------- */
/** \name Object Mode Enter/Exit
* \{ */
-static void item_object_mode_enter_exit(
- bContext *C, ReportList *reports, Object *ob,
- bool enter)
+static void item_object_mode_enter_exit(bContext *C, ReportList *reports, Object *ob, bool enter)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *obact = OBACT(view_layer);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obact = OBACT(view_layer);
- if ((ob->type != obact->type) || ID_IS_LINKED(ob->data)) {
- return;
- }
- if (((ob->mode & obact->mode) != 0) == enter) {
- return;
- }
+ if ((ob->type != obact->type) || ID_IS_LINKED(ob->data)) {
+ return;
+ }
+ if (((ob->mode & obact->mode) != 0) == enter) {
+ return;
+ }
- if (ob == obact) {
- BKE_report(reports, RPT_WARNING, "Active object mode not changed");
- return;
- }
+ if (ob == obact) {
+ BKE_report(reports, RPT_WARNING, "Active object mode not changed");
+ return;
+ }
- Base *base = BKE_view_layer_base_find(view_layer, ob);
- if (base == NULL) {
- return;
- }
- Scene *scene = CTX_data_scene(C);
- outliner_object_mode_toggle(C, scene, view_layer, base);
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+ if (base == NULL) {
+ return;
+ }
+ Scene *scene = CTX_data_scene(C);
+ outliner_object_mode_toggle(C, scene, view_layer, base);
}
-void item_object_mode_enter_cb(
- bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
+void item_object_mode_enter_cb(bContext *C,
+ ReportList *reports,
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
{
- Object *ob = (Object *)tselem->id;
- item_object_mode_enter_exit(C, reports, ob, true);
+ Object *ob = (Object *)tselem->id;
+ item_object_mode_enter_exit(C, reports, ob, true);
}
-void item_object_mode_exit_cb(
- bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
+void item_object_mode_exit_cb(bContext *C,
+ ReportList *reports,
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
{
- Object *ob = (Object *)tselem->id;
- item_object_mode_enter_exit(C, reports, ob, false);
+ Object *ob = (Object *)tselem->id;
+ item_object_mode_enter_exit(C, reports, ob, false);
}
/** \} */
/* Rename --------------------------------------------------- */
-static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
+static void do_item_rename(ARegion *ar,
+ TreeElement *te,
+ TreeStoreElem *tselem,
ReportList *reports)
{
- bool add_textbut = false;
-
- /* can't rename rna datablocks entries or listbases */
- if (ELEM(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE, TSE_SCENE_OBJECTS_BASE)) {
- /* do nothing */
- }
- else if (ELEM(tselem->type, TSE_ANIM_DATA, TSE_NLA, TSE_DEFGROUP_BASE, TSE_CONSTRAINT_BASE, TSE_MODIFIER_BASE,
- TSE_DRIVER_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE, TSE_SCENE_COLLECTION_BASE,
- TSE_VIEW_COLLECTION_BASE))
- {
- BKE_report(reports, RPT_WARNING, "Cannot edit builtin name");
- }
- else if (ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
- BKE_report(reports, RPT_WARNING, "Cannot edit sequence name");
- }
- else if (outliner_is_collection_tree_element(te)) {
- Collection *collection = outliner_collection_from_tree_element(te);
-
- if (collection->flag & COLLECTION_IS_MASTER) {
- BKE_report(reports, RPT_WARNING, "Cannot edit name of master collection");
- }
- else {
- 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");
- }
- else {
- add_textbut = true;
- }
-
- if (add_textbut) {
- tselem->flag |= TSE_TEXTBUT;
- ED_region_tag_redraw(ar);
- }
-}
-
-void item_rename_cb(
- bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *te,
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- ARegion *ar = CTX_wm_region(C);
- do_item_rename(ar, te, tselem, reports);
-}
-
-static int do_outliner_item_rename(ReportList *reports, ARegion *ar, TreeElement *te,
+ bool add_textbut = false;
+
+ /* can't rename rna datablocks entries or listbases */
+ if (ELEM(tselem->type,
+ TSE_RNA_STRUCT,
+ TSE_RNA_PROPERTY,
+ TSE_RNA_ARRAY_ELEM,
+ TSE_ID_BASE,
+ TSE_SCENE_OBJECTS_BASE)) {
+ /* do nothing */
+ }
+ else if (ELEM(tselem->type,
+ TSE_ANIM_DATA,
+ TSE_NLA,
+ TSE_DEFGROUP_BASE,
+ TSE_CONSTRAINT_BASE,
+ TSE_MODIFIER_BASE,
+ TSE_DRIVER_BASE,
+ TSE_POSE_BASE,
+ TSE_POSEGRP_BASE,
+ TSE_R_LAYER_BASE,
+ TSE_SCENE_COLLECTION_BASE,
+ TSE_VIEW_COLLECTION_BASE)) {
+ BKE_report(reports, RPT_WARNING, "Cannot edit builtin name");
+ }
+ else if (ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
+ BKE_report(reports, RPT_WARNING, "Cannot edit sequence name");
+ }
+ else if (outliner_is_collection_tree_element(te)) {
+ Collection *collection = outliner_collection_from_tree_element(te);
+
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ BKE_report(reports, RPT_WARNING, "Cannot edit name of master collection");
+ }
+ else {
+ 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");
+ }
+ else {
+ add_textbut = true;
+ }
+
+ if (add_textbut) {
+ tselem->flag |= TSE_TEXTBUT;
+ ED_region_tag_redraw(ar);
+ }
+}
+
+void item_rename_cb(bContext *C,
+ ReportList *reports,
+ Scene *UNUSED(scene),
+ TreeElement *te,
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
+{
+ ARegion *ar = CTX_wm_region(C);
+ do_item_rename(ar, te, tselem, reports);
+}
+
+static int do_outliner_item_rename(ReportList *reports,
+ ARegion *ar,
+ TreeElement *te,
const float mval[2])
{
- if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
- TreeStoreElem *tselem = TREESTORE(te);
+ if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
+ TreeStoreElem *tselem = TREESTORE(te);
- /* click on name */
- if (mval[0] > te->xs + UI_UNIT_X * 2 && mval[0] < te->xend) {
- do_item_rename(ar, te, tselem, reports);
- return 1;
- }
- return 0;
- }
+ /* click on name */
+ if (mval[0] > te->xs + UI_UNIT_X * 2 && mval[0] < te->xend) {
+ do_item_rename(ar, te, tselem, reports);
+ return 1;
+ }
+ return 0;
+ }
- for (te = te->subtree.first; te; te = te->next) {
- if (do_outliner_item_rename(reports, ar, te, mval)) {
- return 1;
- }
- }
- return 0;
+ for (te = te->subtree.first; te; te = te->next) {
+ if (do_outliner_item_rename(reports, ar, te, mval)) {
+ return 1;
+ }
+ }
+ return 0;
}
static int outliner_item_rename(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- TreeElement *te;
- float fmval[2];
- bool changed = false;
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ TreeElement *te;
+ float fmval[2];
+ bool changed = false;
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
- for (te = soops->tree.first; te; te = te->next) {
- if (do_outliner_item_rename(op->reports, ar, te, fmval)) {
- changed = true;
- break;
- }
- }
+ for (te = soops->tree.first; te; te = te->next) {
+ if (do_outliner_item_rename(op->reports, ar, te, fmval)) {
+ changed = true;
+ break;
+ }
+ }
- return changed ? OPERATOR_FINISHED : OPERATOR_PASS_THROUGH;
+ return changed ? OPERATOR_FINISHED : OPERATOR_PASS_THROUGH;
}
-
void OUTLINER_OT_item_rename(wmOperatorType *ot)
{
- ot->name = "Rename";
- ot->idname = "OUTLINER_OT_item_rename";
- ot->description = "Rename item under cursor";
+ ot->name = "Rename";
+ ot->idname = "OUTLINER_OT_item_rename";
+ ot->description = "Rename item under cursor";
- ot->invoke = outliner_item_rename;
+ ot->invoke = outliner_item_rename;
- ot->poll = ED_operator_outliner_active;
+ ot->poll = ED_operator_outliner_active;
}
/* ID delete --------------------------------------------------- */
static void id_delete(bContext *C, ReportList *reports, TreeElement *te, TreeStoreElem *tselem)
{
- Main *bmain = CTX_data_main(C);
- ID *id = tselem->id;
-
- BLI_assert(te->idcode != 0 && id != NULL);
- UNUSED_VARS_NDEBUG(te);
-
- if (te->idcode == ID_LI && ((Library *)id)->parent != NULL) {
- BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked library '%s'", id->name);
- return;
- }
- if (id->tag & LIB_TAG_INDIRECT) {
- BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked id '%s'", id->name);
- return;
- }
- else if (BKE_library_ID_is_indirectly_used(bmain, id) && ID_REAL_USERS(id) <= 1) {
- BKE_reportf(reports, RPT_WARNING,
- "Cannot delete id '%s', indirectly used data-blocks need at least one user",
- id->name);
- return;
- }
-
-
- BKE_id_delete(bmain, id);
-
- WM_event_add_notifier(C, NC_WINDOW, NULL);
-}
-
-void id_delete_cb(
- bContext *C, ReportList *reports, Scene *UNUSED(scene),
- TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- id_delete(C, reports, te, tselem);
-}
-
-static int outliner_id_delete_invoke_do(bContext *C, ReportList *reports, TreeElement *te, const float mval[2])
-{
- if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
- TreeStoreElem *tselem = TREESTORE(te);
-
- if (te->idcode != 0 && tselem->id) {
- if (te->idcode == ID_LI && ((Library *)tselem->id)->parent) {
- BKE_reportf(reports, RPT_ERROR_INVALID_INPUT,
- "Cannot delete indirectly linked library '%s'", ((Library *)tselem->id)->filepath);
- return OPERATOR_CANCELLED;
- }
- id_delete(C, reports, te, tselem);
- return OPERATOR_FINISHED;
- }
- }
- else {
- for (te = te->subtree.first; te; te = te->next) {
- int ret;
- if ((ret = outliner_id_delete_invoke_do(C, reports, te, mval))) {
- return ret;
- }
- }
- }
-
- return 0;
+ Main *bmain = CTX_data_main(C);
+ ID *id = tselem->id;
+
+ BLI_assert(te->idcode != 0 && id != NULL);
+ UNUSED_VARS_NDEBUG(te);
+
+ if (te->idcode == ID_LI && ((Library *)id)->parent != NULL) {
+ BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked library '%s'", id->name);
+ return;
+ }
+ if (id->tag & LIB_TAG_INDIRECT) {
+ BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked id '%s'", id->name);
+ return;
+ }
+ else if (BKE_library_ID_is_indirectly_used(bmain, id) && ID_REAL_USERS(id) <= 1) {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Cannot delete id '%s', indirectly used data-blocks need at least one user",
+ id->name);
+ return;
+ }
+
+ BKE_id_delete(bmain, id);
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+}
+
+void id_delete_cb(bContext *C,
+ ReportList *reports,
+ Scene *UNUSED(scene),
+ TreeElement *te,
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
+{
+ id_delete(C, reports, te, tselem);
+}
+
+static int outliner_id_delete_invoke_do(bContext *C,
+ ReportList *reports,
+ TreeElement *te,
+ const float mval[2])
+{
+ if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (te->idcode != 0 && tselem->id) {
+ if (te->idcode == ID_LI && ((Library *)tselem->id)->parent) {
+ BKE_reportf(reports,
+ RPT_ERROR_INVALID_INPUT,
+ "Cannot delete indirectly linked library '%s'",
+ ((Library *)tselem->id)->filepath);
+ return OPERATOR_CANCELLED;
+ }
+ id_delete(C, reports, te, tselem);
+ return OPERATOR_FINISHED;
+ }
+ }
+ else {
+ for (te = te->subtree.first; te; te = te->next) {
+ int ret;
+ if ((ret = outliner_id_delete_invoke_do(C, reports, te, mval))) {
+ return ret;
+ }
+ }
+ }
+
+ return 0;
}
static int outliner_id_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- TreeElement *te;
- float fmval[2];
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ TreeElement *te;
+ float fmval[2];
- BLI_assert(ar && soops);
+ BLI_assert(ar && soops);
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
- for (te = soops->tree.first; te; te = te->next) {
- int ret;
+ for (te = soops->tree.first; te; te = te->next) {
+ int ret;
- if ((ret = outliner_id_delete_invoke_do(C, op->reports, te, fmval))) {
- return ret;
- }
- }
+ if ((ret = outliner_id_delete_invoke_do(C, op->reports, te, fmval))) {
+ return ret;
+ }
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
void OUTLINER_OT_id_delete(wmOperatorType *ot)
{
- ot->name = "Delete Data-Block";
- ot->idname = "OUTLINER_OT_id_delete";
- ot->description = "Delete the ID under cursor";
+ ot->name = "Delete Data-Block";
+ ot->idname = "OUTLINER_OT_id_delete";
+ ot->description = "Delete the ID under cursor";
- ot->invoke = outliner_id_delete_invoke;
- ot->poll = ED_operator_outliner_active;
+ ot->invoke = outliner_id_delete_invoke;
+ ot->poll = ED_operator_outliner_active;
}
/* ID remap --------------------------------------------------- */
static int outliner_id_remap_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ Main *bmain = CTX_data_main(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
- const short id_type = (short)RNA_enum_get(op->ptr, "id_type");
- ID *old_id = BLI_findlink(which_libbase(CTX_data_main(C), id_type), RNA_enum_get(op->ptr, "old_id"));
- ID *new_id = BLI_findlink(which_libbase(CTX_data_main(C), id_type), RNA_enum_get(op->ptr, "new_id"));
+ const short id_type = (short)RNA_enum_get(op->ptr, "id_type");
+ ID *old_id = BLI_findlink(which_libbase(CTX_data_main(C), id_type),
+ RNA_enum_get(op->ptr, "old_id"));
+ ID *new_id = BLI_findlink(which_libbase(CTX_data_main(C), id_type),
+ RNA_enum_get(op->ptr, "new_id"));
- /* check for invalid states */
- if (soops == NULL) {
- return OPERATOR_CANCELLED;
- }
+ /* check for invalid states */
+ if (soops == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- if (!(old_id && new_id && (old_id != new_id) && (GS(old_id->name) == GS(new_id->name)))) {
- BKE_reportf(op->reports, RPT_ERROR_INVALID_INPUT, "Invalid old/new ID pair ('%s' / '%s')",
- old_id ? old_id->name : "Invalid ID", new_id ? new_id->name : "Invalid ID");
- return OPERATOR_CANCELLED;
- }
+ if (!(old_id && new_id && (old_id != new_id) && (GS(old_id->name) == GS(new_id->name)))) {
+ BKE_reportf(op->reports,
+ RPT_ERROR_INVALID_INPUT,
+ "Invalid old/new ID pair ('%s' / '%s')",
+ old_id ? old_id->name : "Invalid ID",
+ new_id ? new_id->name : "Invalid ID");
+ return OPERATOR_CANCELLED;
+ }
- if (ID_IS_LINKED(old_id)) {
- BKE_reportf(op->reports, RPT_WARNING,
- "Old ID '%s' is linked from a library, indirect usages of this data-block will not be remapped",
- old_id->name);
- }
+ if (ID_IS_LINKED(old_id)) {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Old ID '%s' is linked from a library, indirect usages of this data-block will "
+ "not be remapped",
+ old_id->name);
+ }
- BKE_libblock_remap(bmain, old_id, new_id,
- ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE);
+ BKE_libblock_remap(
+ bmain, old_id, new_id, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE);
- BKE_main_lib_objects_recalc_all(bmain);
+ BKE_main_lib_objects_recalc_all(bmain);
- /* recreate dependency graph to include new objects */
- DEG_relations_tag_update(bmain);
+ /* recreate dependency graph to include new objects */
+ DEG_relations_tag_update(bmain);
- /* Free gpu materials, some materials depend on existing objects,
- * such as lights so freeing correctly refreshes. */
- GPU_materials_free(bmain);
+ /* Free gpu materials, some materials depend on existing objects,
+ * such as lights so freeing correctly refreshes. */
+ GPU_materials_free(bmain);
- WM_event_add_notifier(C, NC_WINDOW, NULL);
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static bool outliner_id_remap_find_tree_element(bContext *C, wmOperator *op, ListBase *tree, const float y)
+static bool outliner_id_remap_find_tree_element(bContext *C,
+ wmOperator *op,
+ ListBase *tree,
+ const float y)
{
- TreeElement *te;
+ TreeElement *te;
- for (te = tree->first; te; te = te->next) {
- if (y > te->ys && y < te->ys + UI_UNIT_Y) {
- TreeStoreElem *tselem = TREESTORE(te);
+ for (te = tree->first; te; te = te->next) {
+ if (y > te->ys && y < te->ys + UI_UNIT_Y) {
+ TreeStoreElem *tselem = TREESTORE(te);
- if (tselem->type == 0 && tselem->id) {
- printf("found id %s (%p)!\n", tselem->id->name, tselem->id);
+ if (tselem->type == 0 && tselem->id) {
+ printf("found id %s (%p)!\n", tselem->id->name, tselem->id);
- RNA_enum_set(op->ptr, "id_type", GS(tselem->id->name));
- RNA_enum_set_identifier(C, op->ptr, "new_id", tselem->id->name + 2);
- RNA_enum_set_identifier(C, op->ptr, "old_id", tselem->id->name + 2);
- return true;
- }
- }
- if (outliner_id_remap_find_tree_element(C, op, &te->subtree, y)) {
- return true;
- }
- }
- return false;
+ RNA_enum_set(op->ptr, "id_type", GS(tselem->id->name));
+ RNA_enum_set_identifier(C, op->ptr, "new_id", tselem->id->name + 2);
+ RNA_enum_set_identifier(C, op->ptr, "old_id", tselem->id->name + 2);
+ return true;
+ }
+ }
+ if (outliner_id_remap_find_tree_element(C, op, &te->subtree, y)) {
+ return true;
+ }
+ }
+ return false;
}
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);
- float fmval[2];
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ ARegion *ar = 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]);
+ 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]);
- outliner_id_remap_find_tree_element(C, op, &soops->tree, 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, 100);
}
-static const EnumPropertyItem *outliner_id_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *outliner_id_itemf(bContext *C,
+ PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- EnumPropertyItem item_tmp = {0}, *item = NULL;
- int totitem = 0;
- int i = 0;
+ EnumPropertyItem item_tmp = {0}, *item = NULL;
+ int totitem = 0;
+ int i = 0;
- short id_type = (short)RNA_enum_get(ptr, "id_type");
- ID *id = which_libbase(CTX_data_main(C), id_type)->first;
+ short id_type = (short)RNA_enum_get(ptr, "id_type");
+ ID *id = which_libbase(CTX_data_main(C), id_type)->first;
- for (; id; id = id->next) {
- item_tmp.identifier = item_tmp.name = id->name + 2;
- item_tmp.value = i++;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- }
+ for (; id; id = id->next) {
+ item_tmp.identifier = item_tmp.name = id->name + 2;
+ item_tmp.value = i++;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
- return item;
+ return item;
}
void OUTLINER_OT_id_remap(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Outliner ID data Remap";
- ot->idname = "OUTLINER_OT_id_remap";
+ /* identifiers */
+ ot->name = "Outliner ID data Remap";
+ ot->idname = "OUTLINER_OT_id_remap";
- /* callbacks */
- ot->invoke = outliner_id_remap_invoke;
- ot->exec = outliner_id_remap_exec;
- ot->poll = ED_operator_outliner_active;
+ /* callbacks */
+ ot->invoke = outliner_id_remap_invoke;
+ ot->exec = outliner_id_remap_exec;
+ ot->poll = ED_operator_outliner_active;
- ot->flag = 0;
+ ot->flag = 0;
- prop = RNA_def_enum(ot->srna, "id_type", rna_enum_id_type_items, ID_OB, "ID Type", "");
- RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
+ prop = RNA_def_enum(ot->srna, "id_type", rna_enum_id_type_items, ID_OB, "ID Type", "");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
- prop = RNA_def_enum(ot->srna, "old_id", DummyRNA_NULL_items, 0, "Old ID", "Old ID to replace");
- RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, outliner_id_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE | PROP_HIDDEN);
+ prop = RNA_def_enum(ot->srna, "old_id", DummyRNA_NULL_items, 0, "Old ID", "Old ID to replace");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, outliner_id_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE | PROP_HIDDEN);
- ot->prop = RNA_def_enum(ot->srna, "new_id", DummyRNA_NULL_items, 0,
- "New ID", "New ID to remap all selected IDs' users to");
- RNA_def_property_enum_funcs_runtime(ot->prop, NULL, NULL, outliner_id_itemf);
- RNA_def_property_flag(ot->prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = RNA_def_enum(ot->srna,
+ "new_id",
+ DummyRNA_NULL_items,
+ 0,
+ "New ID",
+ "New ID to remap all selected IDs' users to");
+ RNA_def_property_enum_funcs_runtime(ot->prop, NULL, NULL, outliner_id_itemf);
+ RNA_def_property_flag(ot->prop, PROP_ENUM_NO_TRANSLATE);
}
-void id_remap_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
+void id_remap_cb(bContext *C,
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
{
- wmOperatorType *ot = WM_operatortype_find("OUTLINER_OT_id_remap", false);
- PointerRNA op_props;
+ wmOperatorType *ot = WM_operatortype_find("OUTLINER_OT_id_remap", false);
+ PointerRNA op_props;
- BLI_assert(tselem->id != NULL);
+ BLI_assert(tselem->id != NULL);
- WM_operator_properties_create_ptr(&op_props, ot);
+ WM_operator_properties_create_ptr(&op_props, ot);
- RNA_enum_set(&op_props, "id_type", GS(tselem->id->name));
- RNA_enum_set_identifier(C, &op_props, "old_id", tselem->id->name + 2);
+ RNA_enum_set(&op_props, "id_type", GS(tselem->id->name));
+ RNA_enum_set_identifier(C, &op_props, "old_id", tselem->id->name + 2);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_props);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_props);
- WM_operator_properties_free(&op_props);
+ WM_operator_properties_free(&op_props);
}
/* ID copy/Paste ------------------------------------------------------------- */
static int outliner_id_copy_tag(SpaceOutliner *soops, ListBase *tree)
{
- TreeElement *te;
- TreeStoreElem *tselem;
- int num_ids = 0;
+ TreeElement *te;
+ TreeStoreElem *tselem;
+ int num_ids = 0;
- for (te = tree->first; te; te = te->next) {
- tselem = TREESTORE(te);
+ for (te = tree->first; te; te = te->next) {
+ tselem = TREESTORE(te);
- /* if item is selected and is an ID, tag it as needing to be copied. */
- if (tselem->flag & TSE_SELECTED && ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
- ID *id = tselem->id;
- if (!(id->tag & LIB_TAG_DOIT)) {
- BKE_copybuffer_tag_ID(tselem->id);
- num_ids++;
- }
- }
+ /* if item is selected and is an ID, tag it as needing to be copied. */
+ if (tselem->flag & TSE_SELECTED && ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
+ ID *id = tselem->id;
+ if (!(id->tag & LIB_TAG_DOIT)) {
+ BKE_copybuffer_tag_ID(tselem->id);
+ num_ids++;
+ }
+ }
- /* go over sub-tree */
- if (TSELEM_OPEN(tselem, soops)) {
- num_ids += outliner_id_copy_tag(soops, &te->subtree);
- }
- }
+ /* go over sub-tree */
+ if (TSELEM_OPEN(tselem, soops)) {
+ num_ids += outliner_id_copy_tag(soops, &te->subtree);
+ }
+ }
- return num_ids;
+ return num_ids;
}
static int outliner_id_copy_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- char str[FILE_MAX];
+ Main *bmain = CTX_data_main(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ char str[FILE_MAX];
- BKE_copybuffer_begin(bmain);
+ BKE_copybuffer_begin(bmain);
- const int num_ids = outliner_id_copy_tag(soops, &soops->tree);
- if (num_ids == 0) {
- BKE_report(op->reports, RPT_INFO, "No selected data-blocks to copy");
- return OPERATOR_CANCELLED;
- }
+ const int num_ids = outliner_id_copy_tag(soops, &soops->tree);
+ if (num_ids == 0) {
+ BKE_report(op->reports, RPT_INFO, "No selected data-blocks to copy");
+ return OPERATOR_CANCELLED;
+ }
- BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
- BKE_copybuffer_save(bmain, str, op->reports);
+ BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
+ BKE_copybuffer_save(bmain, str, op->reports);
- BKE_reportf(op->reports, RPT_INFO, "Copied %d selected data-blocks", num_ids);
+ BKE_reportf(op->reports, RPT_INFO, "Copied %d selected data-blocks", num_ids);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_id_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Outliner ID Data Copy";
- ot->idname = "OUTLINER_OT_id_copy";
- ot->description = "Selected data-blocks are copied to the clipboard";
+ /* identifiers */
+ ot->name = "Outliner ID Data Copy";
+ ot->idname = "OUTLINER_OT_id_copy";
+ ot->description = "Selected data-blocks are copied to the clipboard";
- /* callbacks */
- ot->exec = outliner_id_copy_exec;
- ot->poll = ED_operator_outliner_active;
+ /* callbacks */
+ ot->exec = outliner_id_copy_exec;
+ ot->poll = ED_operator_outliner_active;
- ot->flag = 0;
+ ot->flag = 0;
}
static int outliner_id_paste_exec(bContext *C, wmOperator *op)
{
- char str[FILE_MAX];
- const short flag = FILE_AUTOSELECT | FILE_ACTIVE_COLLECTION;
+ char str[FILE_MAX];
+ const short flag = FILE_AUTOSELECT | FILE_ACTIVE_COLLECTION;
- BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
+ BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
- const int num_pasted = BKE_copybuffer_paste(C, str, flag, op->reports, 0);
- if (num_pasted == 0) {
- BKE_report(op->reports, RPT_INFO, "No data to paste");
- return OPERATOR_CANCELLED;
- }
+ const int num_pasted = BKE_copybuffer_paste(C, str, flag, op->reports, 0);
+ if (num_pasted == 0) {
+ BKE_report(op->reports, RPT_INFO, "No data to paste");
+ return OPERATOR_CANCELLED;
+ }
- WM_event_add_notifier(C, NC_WINDOW, NULL);
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
- BKE_reportf(op->reports, RPT_INFO, "%d data-blocks pasted", num_pasted);
- return OPERATOR_FINISHED;
+ BKE_reportf(op->reports, RPT_INFO, "%d data-blocks pasted", num_pasted);
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_id_paste(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Outliner ID Data Paste";
- ot->idname = "OUTLINER_OT_id_paste";
- ot->description = "Data-blocks from the clipboard are pasted";
+ /* identifiers */
+ ot->name = "Outliner ID Data Paste";
+ ot->idname = "OUTLINER_OT_id_paste";
+ ot->description = "Data-blocks from the clipboard are pasted";
- /* callbacks */
- ot->exec = outliner_id_paste_exec;
- ot->poll = ED_operator_outliner_active;
+ /* callbacks */
+ ot->exec = outliner_id_paste_exec;
+ ot->poll = ED_operator_outliner_active;
- ot->flag = 0;
+ ot->flag = 0;
}
/* Library relocate/reload --------------------------------------------------- */
static int lib_relocate(
- bContext *C, TreeElement *te, TreeStoreElem *tselem, wmOperatorType *ot, const bool reload)
+ bContext *C, TreeElement *te, TreeStoreElem *tselem, wmOperatorType *ot, const bool reload)
{
- PointerRNA op_props;
- int ret = 0;
+ PointerRNA op_props;
+ int ret = 0;
- BLI_assert(te->idcode == ID_LI && tselem->id != NULL);
- UNUSED_VARS_NDEBUG(te);
+ BLI_assert(te->idcode == ID_LI && tselem->id != NULL);
+ UNUSED_VARS_NDEBUG(te);
- WM_operator_properties_create_ptr(&op_props, ot);
+ WM_operator_properties_create_ptr(&op_props, ot);
- RNA_string_set(&op_props, "library", tselem->id->name + 2);
+ RNA_string_set(&op_props, "library", tselem->id->name + 2);
- if (reload) {
- Library *lib = (Library *)tselem->id;
- char dir[FILE_MAXDIR], filename[FILE_MAX];
+ if (reload) {
+ Library *lib = (Library *)tselem->id;
+ char dir[FILE_MAXDIR], filename[FILE_MAX];
- BLI_split_dirfile(lib->filepath, dir, filename, sizeof(dir), sizeof(filename));
+ BLI_split_dirfile(lib->filepath, dir, filename, sizeof(dir), sizeof(filename));
- printf("%s, %s\n", tselem->id->name, lib->filepath);
+ printf("%s, %s\n", tselem->id->name, lib->filepath);
- /* We assume if both paths in lib are not the same then lib->name was relative... */
- RNA_boolean_set(&op_props, "relative_path", BLI_path_cmp(lib->filepath, lib->name) != 0);
+ /* We assume if both paths in lib are not the same then lib->name was relative... */
+ RNA_boolean_set(&op_props, "relative_path", BLI_path_cmp(lib->filepath, lib->name) != 0);
- RNA_string_set(&op_props, "directory", dir);
- RNA_string_set(&op_props, "filename", filename);
+ RNA_string_set(&op_props, "directory", dir);
+ RNA_string_set(&op_props, "filename", filename);
- ret = WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props);
- }
- else {
- ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_props);
- }
+ ret = WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props);
+ }
+ else {
+ ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_props);
+ }
- WM_operator_properties_free(&op_props);
+ WM_operator_properties_free(&op_props);
- return ret;
+ return ret;
}
static int outliner_lib_relocate_invoke_do(
- bContext *C, ReportList *reports, TreeElement *te, const float mval[2], const bool reload)
-{
- if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
- TreeStoreElem *tselem = TREESTORE(te);
-
- if (te->idcode == ID_LI && tselem->id) {
- if (((Library *)tselem->id)->parent && !reload) {
- BKE_reportf(reports, RPT_ERROR_INVALID_INPUT,
- "Cannot relocate indirectly linked library '%s'", ((Library *)tselem->id)->filepath);
- return OPERATOR_CANCELLED;
- }
- else {
- wmOperatorType *ot = WM_operatortype_find(reload ? "WM_OT_lib_reload" : "WM_OT_lib_relocate", false);
-
- return lib_relocate(C, te, tselem, ot, reload);
- }
- }
- }
- else {
- for (te = te->subtree.first; te; te = te->next) {
- int ret;
- if ((ret = outliner_lib_relocate_invoke_do(C, reports, te, mval, reload))) {
- return ret;
- }
- }
- }
-
- return 0;
+ bContext *C, ReportList *reports, TreeElement *te, const float mval[2], const bool reload)
+{
+ if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (te->idcode == ID_LI && tselem->id) {
+ if (((Library *)tselem->id)->parent && !reload) {
+ BKE_reportf(reports,
+ RPT_ERROR_INVALID_INPUT,
+ "Cannot relocate indirectly linked library '%s'",
+ ((Library *)tselem->id)->filepath);
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ wmOperatorType *ot = WM_operatortype_find(
+ reload ? "WM_OT_lib_reload" : "WM_OT_lib_relocate", false);
+
+ return lib_relocate(C, te, tselem, ot, reload);
+ }
+ }
+ }
+ else {
+ for (te = te->subtree.first; te; te = te->next) {
+ int ret;
+ if ((ret = outliner_lib_relocate_invoke_do(C, reports, te, mval, reload))) {
+ return ret;
+ }
+ }
+ }
+
+ return 0;
}
static int outliner_lib_relocate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- TreeElement *te;
- float fmval[2];
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ TreeElement *te;
+ float fmval[2];
- BLI_assert(ar && soops);
+ BLI_assert(ar && soops);
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
- for (te = soops->tree.first; te; te = te->next) {
- int ret;
+ for (te = soops->tree.first; te; te = te->next) {
+ int ret;
- if ((ret = outliner_lib_relocate_invoke_do(C, op->reports, te, fmval, false))) {
- return ret;
- }
- }
+ if ((ret = outliner_lib_relocate_invoke_do(C, op->reports, te, fmval, false))) {
+ return ret;
+ }
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
void OUTLINER_OT_lib_relocate(wmOperatorType *ot)
{
- ot->name = "Relocate Library";
- ot->idname = "OUTLINER_OT_lib_relocate";
- ot->description = "Relocate the library under cursor";
+ ot->name = "Relocate Library";
+ ot->idname = "OUTLINER_OT_lib_relocate";
+ ot->description = "Relocate the library under cursor";
- ot->invoke = outliner_lib_relocate_invoke;
- ot->poll = ED_operator_outliner_active;
+ ot->invoke = outliner_lib_relocate_invoke;
+ ot->poll = ED_operator_outliner_active;
}
/* XXX This does not work with several items
* (it is only called once in the end, due to the 'deferred'
* filebrowser invocation through event system...). */
-void lib_relocate_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *te,
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
+void lib_relocate_cb(bContext *C,
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *te,
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
{
- wmOperatorType *ot = WM_operatortype_find("WM_OT_lib_relocate", false);
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_lib_relocate", false);
- lib_relocate(C, te, tselem, ot, false);
+ lib_relocate(C, te, tselem, ot, false);
}
-
static int outliner_lib_reload_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- TreeElement *te;
- float fmval[2];
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ TreeElement *te;
+ float fmval[2];
- BLI_assert(ar && soops);
+ BLI_assert(ar && soops);
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
- for (te = soops->tree.first; te; te = te->next) {
- int ret;
+ for (te = soops->tree.first; te; te = te->next) {
+ int ret;
- if ((ret = outliner_lib_relocate_invoke_do(C, op->reports, te, fmval, true))) {
- return ret;
- }
- }
+ if ((ret = outliner_lib_relocate_invoke_do(C, op->reports, te, fmval, true))) {
+ return ret;
+ }
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
void OUTLINER_OT_lib_reload(wmOperatorType *ot)
{
- ot->name = "Reload Library";
- ot->idname = "OUTLINER_OT_lib_reload";
- ot->description = "Reload the library under cursor";
+ ot->name = "Reload Library";
+ ot->idname = "OUTLINER_OT_lib_reload";
+ ot->description = "Reload the library under cursor";
- ot->invoke = outliner_lib_reload_invoke;
- ot->poll = ED_operator_outliner_active;
+ ot->invoke = outliner_lib_reload_invoke;
+ ot->poll = ED_operator_outliner_active;
}
-void lib_reload_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *te,
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
+void lib_reload_cb(bContext *C,
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *te,
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
{
- wmOperatorType *ot = WM_operatortype_find("WM_OT_lib_reload", false);
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_lib_reload", false);
- lib_relocate(C, te, tselem, ot, true);
+ lib_relocate(C, te, tselem, ot, true);
}
/* ************************************************************** */
@@ -867,37 +934,37 @@ void lib_reload_cb(
static int outliner_count_levels(ListBase *lb, const int curlevel)
{
- TreeElement *te;
- int level = curlevel, lev;
+ TreeElement *te;
+ int level = curlevel, lev;
- for (te = lb->first; te; te = te->next) {
+ for (te = lb->first; te; te = te->next) {
- lev = outliner_count_levels(&te->subtree, curlevel + 1);
- if (lev > level) {
- level = lev;
- }
- }
- return level;
+ lev = outliner_count_levels(&te->subtree, curlevel + 1);
+ if (lev > level) {
+ level = lev;
+ }
+ }
+ return level;
}
int outliner_flag_is_any_test(ListBase *lb, short flag, const int curlevel)
{
- TreeElement *te;
- TreeStoreElem *tselem;
- int level;
+ TreeElement *te;
+ TreeStoreElem *tselem;
+ int level;
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
- if (tselem->flag & flag) {
- return curlevel;
- }
+ for (te = lb->first; te; te = te->next) {
+ tselem = TREESTORE(te);
+ if (tselem->flag & flag) {
+ return curlevel;
+ }
- level = outliner_flag_is_any_test(&te->subtree, flag, curlevel + 1);
- if (level) {
- return level;
- }
- }
- return 0;
+ level = outliner_flag_is_any_test(&te->subtree, flag, curlevel + 1);
+ if (level) {
+ return level;
+ }
+ }
+ return 0;
}
/**
@@ -906,43 +973,43 @@ int outliner_flag_is_any_test(ListBase *lb, short flag, const int curlevel)
*/
bool outliner_flag_set(ListBase *lb, short flag, short set)
{
- TreeElement *te;
- TreeStoreElem *tselem;
- bool changed = false;
- bool has_flag;
-
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
- has_flag = (tselem->flag & flag);
- if (set == 0) {
- if (has_flag) {
- tselem->flag &= ~flag;
- changed = true;
- }
- }
- else if (!has_flag) {
- tselem->flag |= flag;
- changed = true;
- }
- changed |= outliner_flag_set(&te->subtree, flag, set);
- }
-
- return changed;
+ TreeElement *te;
+ TreeStoreElem *tselem;
+ bool changed = false;
+ bool has_flag;
+
+ for (te = lb->first; te; te = te->next) {
+ tselem = TREESTORE(te);
+ has_flag = (tselem->flag & flag);
+ if (set == 0) {
+ if (has_flag) {
+ tselem->flag &= ~flag;
+ changed = true;
+ }
+ }
+ else if (!has_flag) {
+ tselem->flag |= flag;
+ changed = true;
+ }
+ changed |= outliner_flag_set(&te->subtree, flag, set);
+ }
+
+ return changed;
}
bool outliner_flag_flip(ListBase *lb, short flag)
{
- TreeElement *te;
- TreeStoreElem *tselem;
- bool changed = false;
+ TreeElement *te;
+ TreeStoreElem *tselem;
+ bool changed = false;
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
- tselem->flag ^= flag;
- changed |= outliner_flag_flip(&te->subtree, flag);
- }
+ for (te = lb->first; te; te = te->next) {
+ tselem = TREESTORE(te);
+ tselem->flag ^= flag;
+ changed |= outliner_flag_flip(&te->subtree, flag);
+ }
- return changed;
+ return changed;
}
/* Restriction Columns ------------------------------- */
@@ -952,23 +1019,23 @@ bool outliner_flag_flip(ListBase *lb, short flag)
* otherwise return 1 */
int common_restrict_check(bContext *C, Object *ob)
{
- /* Don't allow hide an object in edit mode,
- * check the bug #22153 and #21609, #23977
- */
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit == ob) {
- /* found object is hidden, reset */
- if (ob->restrictflag & OB_RESTRICT_VIEW) {
- ob->restrictflag &= ~OB_RESTRICT_VIEW;
- }
- /* found object is unselectable, reset */
- if (ob->restrictflag & OB_RESTRICT_SELECT) {
- ob->restrictflag &= ~OB_RESTRICT_SELECT;
- }
- return 0;
- }
-
- return 1;
+ /* Don't allow hide an object in edit mode,
+ * check the bug #22153 and #21609, #23977
+ */
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit == ob) {
+ /* found object is hidden, reset */
+ if (ob->restrictflag & OB_RESTRICT_VIEW) {
+ ob->restrictflag &= ~OB_RESTRICT_VIEW;
+ }
+ /* found object is unselectable, reset */
+ if (ob->restrictflag & OB_RESTRICT_SELECT) {
+ ob->restrictflag &= ~OB_RESTRICT_SELECT;
+ }
+ return 0;
+ }
+
+ return 1;
}
/* =============================================== */
@@ -978,81 +1045,81 @@ int common_restrict_check(bContext *C, Object *ob)
static int outliner_toggle_expanded_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ ARegion *ar = CTX_wm_region(C);
- if (outliner_flag_is_any_test(&soops->tree, TSE_CLOSED, 1)) {
- outliner_flag_set(&soops->tree, TSE_CLOSED, 0);
- }
- else {
- outliner_flag_set(&soops->tree, TSE_CLOSED, 1);
- }
+ if (outliner_flag_is_any_test(&soops->tree, TSE_CLOSED, 1)) {
+ outliner_flag_set(&soops->tree, TSE_CLOSED, 0);
+ }
+ else {
+ outliner_flag_set(&soops->tree, TSE_CLOSED, 1);
+ }
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_expanded_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Expand/Collapse All";
- ot->idname = "OUTLINER_OT_expanded_toggle";
- ot->description = "Expand/Collapse all items";
+ /* identifiers */
+ ot->name = "Expand/Collapse All";
+ ot->idname = "OUTLINER_OT_expanded_toggle";
+ ot->description = "Expand/Collapse all items";
- /* callbacks */
- ot->exec = outliner_toggle_expanded_exec;
- ot->poll = ED_operator_outliner_active;
+ /* callbacks */
+ ot->exec = outliner_toggle_expanded_exec;
+ ot->poll = ED_operator_outliner_active;
- /* no undo or registry, UI option */
+ /* no undo or registry, UI option */
}
/* Toggle Selected (Outliner) ---------------------------------------- */
static int outliner_select_all_exec(bContext *C, wmOperator *op)
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
- int action = RNA_enum_get(op->ptr, "action");
- if (action == SEL_TOGGLE) {
- action = outliner_flag_is_any_test(&soops->tree, TSE_SELECTED, 1) ? SEL_DESELECT : SEL_SELECT;
- }
-
- switch (action) {
- case SEL_SELECT:
- outliner_flag_set(&soops->tree, TSE_SELECTED, 1);
- break;
- case SEL_DESELECT:
- outliner_flag_set(&soops->tree, TSE_SELECTED, 0);
- break;
- case SEL_INVERT:
- outliner_flag_flip(&soops->tree, TSE_SELECTED);
- break;
- }
-
- 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);
-
- return OPERATOR_FINISHED;
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+ int action = RNA_enum_get(op->ptr, "action");
+ if (action == SEL_TOGGLE) {
+ action = outliner_flag_is_any_test(&soops->tree, TSE_SELECTED, 1) ? SEL_DESELECT : SEL_SELECT;
+ }
+
+ switch (action) {
+ case SEL_SELECT:
+ outliner_flag_set(&soops->tree, TSE_SELECTED, 1);
+ break;
+ case SEL_DESELECT:
+ outliner_flag_set(&soops->tree, TSE_SELECTED, 0);
+ break;
+ case SEL_INVERT:
+ outliner_flag_flip(&soops->tree, TSE_SELECTED);
+ break;
+ }
+
+ 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);
+
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Selected";
- ot->idname = "OUTLINER_OT_select_all";
- ot->description = "Toggle the Outliner selection of items";
+ /* identifiers */
+ ot->name = "Toggle Selected";
+ ot->idname = "OUTLINER_OT_select_all";
+ ot->description = "Toggle the Outliner selection of items";
- /* callbacks */
- ot->exec = outliner_select_all_exec;
- ot->poll = ED_operator_outliner_active;
+ /* callbacks */
+ ot->exec = outliner_select_all_exec;
+ ot->poll = ED_operator_outliner_active;
- /* no undo or registry */
+ /* no undo or registry */
- /* rna */
- WM_operator_properties_select_all(ot);
+ /* rna */
+ WM_operator_properties_select_all(ot);
}
/* ************************************************************** */
@@ -1060,165 +1127,167 @@ void OUTLINER_OT_select_all(wmOperatorType *ot)
/* Show Active --------------------------------------------------- */
-static void outliner_set_coordinates_element_recursive(SpaceOutliner *soops, TreeElement *te, int startx, int *starty)
+static void outliner_set_coordinates_element_recursive(SpaceOutliner *soops,
+ TreeElement *te,
+ int startx,
+ int *starty)
{
- TreeStoreElem *tselem = TREESTORE(te);
+ TreeStoreElem *tselem = TREESTORE(te);
- /* store coord and continue, we need coordinates for elements outside view too */
- te->xs = (float)startx;
- te->ys = (float)(*starty);
- *starty -= UI_UNIT_Y;
+ /* store coord and continue, we need coordinates for elements outside view too */
+ te->xs = (float)startx;
+ te->ys = (float)(*starty);
+ *starty -= UI_UNIT_Y;
- if (TSELEM_OPEN(tselem, soops)) {
- TreeElement *ten;
- for (ten = te->subtree.first; ten; ten = ten->next) {
- outliner_set_coordinates_element_recursive(soops, ten, startx + UI_UNIT_X, starty);
- }
- }
+ if (TSELEM_OPEN(tselem, soops)) {
+ TreeElement *ten;
+ for (ten = te->subtree.first; ten; ten = ten->next) {
+ outliner_set_coordinates_element_recursive(soops, ten, startx + UI_UNIT_X, starty);
+ }
+ }
}
/* to retrieve coordinates with redrawing the entire tree */
void outliner_set_coordinates(ARegion *ar, SpaceOutliner *soops)
{
- TreeElement *te;
- int starty = (int)(ar->v2d.tot.ymax) - UI_UNIT_Y;
+ TreeElement *te;
+ int starty = (int)(ar->v2d.tot.ymax) - UI_UNIT_Y;
- for (te = soops->tree.first; te; te = te->next) {
- outliner_set_coordinates_element_recursive(soops, te, 0, &starty);
- }
+ for (te = soops->tree.first; te; te = te->next) {
+ outliner_set_coordinates_element_recursive(soops, te, 0, &starty);
+ }
}
/* return 1 when levels were opened */
static int outliner_open_back(TreeElement *te)
{
- TreeStoreElem *tselem;
- int retval = 0;
+ TreeStoreElem *tselem;
+ int retval = 0;
- for (te = te->parent; te; te = te->parent) {
- tselem = TREESTORE(te);
- if (tselem->flag & TSE_CLOSED) {
- tselem->flag &= ~TSE_CLOSED;
- retval = 1;
- }
- }
- return retval;
+ for (te = te->parent; te; te = te->parent) {
+ tselem = TREESTORE(te);
+ if (tselem->flag & TSE_CLOSED) {
+ tselem->flag &= ~TSE_CLOSED;
+ retval = 1;
+ }
+ }
+ return retval;
}
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;
-
- TreeElement *te;
- int xdelta, ytop;
+ 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;
- Object *obact = OBACT(view_layer);
+ TreeElement *te;
+ int xdelta, ytop;
- if (!obact) {
- return OPERATOR_CANCELLED;
- }
+ Object *obact = OBACT(view_layer);
+ if (!obact) {
+ return OPERATOR_CANCELLED;
+ }
- te = outliner_find_id(so, &so->tree, &obact->id);
+ te = outliner_find_id(so, &so->tree, &obact->id);
- if (te != NULL && obact->type == OB_ARMATURE) {
- /* traverse down the bone hierarchy in case of armature */
- TreeElement *te_obact = te;
+ if (te != NULL && obact->type == OB_ARMATURE) {
+ /* traverse down the bone hierarchy in case of armature */
+ TreeElement *te_obact = te;
- if (obact->mode & OB_MODE_POSE) {
- bPoseChannel *pchan = CTX_data_active_pose_bone(C);
- if (pchan) {
- te = outliner_find_posechannel(&te_obact->subtree, pchan);
- }
- }
- else if (obact->mode & OB_MODE_EDIT) {
- EditBone *ebone = CTX_data_active_bone(C);
- if (ebone) {
- te = outliner_find_editbone(&te_obact->subtree, ebone);
- }
- }
- }
+ if (obact->mode & OB_MODE_POSE) {
+ bPoseChannel *pchan = CTX_data_active_pose_bone(C);
+ if (pchan) {
+ te = outliner_find_posechannel(&te_obact->subtree, pchan);
+ }
+ }
+ else if (obact->mode & OB_MODE_EDIT) {
+ EditBone *ebone = CTX_data_active_bone(C);
+ if (ebone) {
+ te = outliner_find_editbone(&te_obact->subtree, ebone);
+ }
+ }
+ }
- if (te) {
- /* open up tree to active object/bone */
- if (outliner_open_back(te)) {
- outliner_set_coordinates(ar, so);
- }
+ if (te) {
+ /* open up tree to active object/bone */
+ if (outliner_open_back(te)) {
+ outliner_set_coordinates(ar, so);
+ }
- /* make te->ys center of view */
- ytop = te->ys + BLI_rcti_size_y(&v2d->mask) / 2;
- if (ytop > 0) {
- ytop = 0;
- }
+ /* make te->ys center of view */
+ ytop = te->ys + BLI_rcti_size_y(&v2d->mask) / 2;
+ if (ytop > 0) {
+ ytop = 0;
+ }
- v2d->cur.ymax = (float)ytop;
- v2d->cur.ymin = (float)(ytop - BLI_rcti_size_y(&v2d->mask));
+ v2d->cur.ymax = (float)ytop;
+ v2d->cur.ymin = (float)(ytop - BLI_rcti_size_y(&v2d->mask));
- /* make te->xs ==> te->xend center of view */
- xdelta = (int)(te->xs - v2d->cur.xmin);
- v2d->cur.xmin += xdelta;
- v2d->cur.xmax += xdelta;
- }
+ /* make te->xs ==> te->xend center of view */
+ xdelta = (int)(te->xs - v2d->cur.xmin);
+ v2d->cur.xmin += xdelta;
+ v2d->cur.xmax += xdelta;
+ }
- ED_region_tag_redraw_no_rebuild(ar);
+ ED_region_tag_redraw_no_rebuild(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_show_active(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Show Active";
- ot->idname = "OUTLINER_OT_show_active";
- ot->description = "Open up the tree and adjust the view so that the active Object is shown centered";
+ /* identifiers */
+ ot->name = "Show Active";
+ ot->idname = "OUTLINER_OT_show_active";
+ ot->description =
+ "Open up the tree and adjust the view so that the active Object is shown centered";
- /* callbacks */
- ot->exec = outliner_show_active_exec;
- ot->poll = ED_operator_outliner_active;
+ /* callbacks */
+ ot->exec = outliner_show_active_exec;
+ ot->poll = ED_operator_outliner_active;
}
/* View Panning --------------------------------------------------- */
static int outliner_scroll_page_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
- int dy = BLI_rcti_size_y(&ar->v2d.mask);
- int up = 0;
+ ARegion *ar = CTX_wm_region(C);
+ int dy = BLI_rcti_size_y(&ar->v2d.mask);
+ int up = 0;
- if (RNA_boolean_get(op->ptr, "up")) {
- up = 1;
- }
+ if (RNA_boolean_get(op->ptr, "up")) {
+ up = 1;
+ }
- if (up == 0) {
- dy = -dy;
- }
- ar->v2d.cur.ymin += dy;
- ar->v2d.cur.ymax += dy;
+ if (up == 0) {
+ dy = -dy;
+ }
+ ar->v2d.cur.ymin += dy;
+ ar->v2d.cur.ymax += dy;
- ED_region_tag_redraw_no_rebuild(ar);
+ ED_region_tag_redraw_no_rebuild(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
void OUTLINER_OT_scroll_page(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Scroll Page";
- ot->idname = "OUTLINER_OT_scroll_page";
- ot->description = "Scroll page up or down";
+ /* identifiers */
+ ot->name = "Scroll Page";
+ ot->idname = "OUTLINER_OT_scroll_page";
+ ot->description = "Scroll page up or down";
- /* callbacks */
- ot->exec = outliner_scroll_page_exec;
- ot->poll = ED_operator_outliner_active;
+ /* callbacks */
+ ot->exec = outliner_scroll_page_exec;
+ ot->poll = ED_operator_outliner_active;
- /* properties */
- prop = RNA_def_boolean(ot->srna, "up", 0, "Up", "Scroll up one page");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "up", 0, "Up", "Scroll up one page");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* Search ------------------------------------------------------- */
@@ -1230,104 +1299,104 @@ void OUTLINER_OT_scroll_page(wmOperatorType *ot)
static TreeElement *outliner_find_name(SpaceOutliner *soops, ListBase *lb, char *name, int flags,
TreeElement *prev, int *prevFound)
{
- TreeElement *te, *tes;
+ TreeElement *te, *tes;
- for (te = lb->first; te; te = te->next) {
- int found = outliner_filter_has_name(te, name, flags);
+ for (te = lb->first; te; te = te->next) {
+ int found = outliner_filter_has_name(te, name, flags);
- if (found) {
- /* name is right, but is element the previous one? */
- if (prev) {
- if ((te != prev) && (*prevFound))
- return te;
- if (te == prev) {
- *prevFound = 1;
- }
- }
- else
- return te;
- }
+ if (found) {
+ /* name is right, but is element the previous one? */
+ if (prev) {
+ if ((te != prev) && (*prevFound))
+ return te;
+ if (te == prev) {
+ *prevFound = 1;
+ }
+ }
+ else
+ return te;
+ }
- tes = outliner_find_name(soops, &te->subtree, name, flags, prev, prevFound);
- if (tes) return tes;
- }
+ tes = outliner_find_name(soops, &te->subtree, name, flags, prev, prevFound);
+ if (tes) return tes;
+ }
- /* nothing valid found */
- return NULL;
+ /* nothing valid found */
+ return NULL;
}
static void outliner_find_panel(Scene *UNUSED(scene), ARegion *ar, SpaceOutliner *soops, int again, int flags)
{
- ReportList *reports = NULL; // CTX_wm_reports(C);
- TreeElement *te = NULL;
- TreeElement *last_find;
- TreeStoreElem *tselem;
- int ytop, xdelta, prevFound = 0;
- char name[sizeof(soops->search_string)];
-
- /* get last found tree-element based on stored search_tse */
- last_find = outliner_find_tse(soops, &soops->search_tse);
-
- /* determine which type of search to do */
- if (again && last_find) {
- /* no popup panel - previous + user wanted to search for next after previous */
- BLI_strncpy(name, soops->search_string, sizeof(name));
- flags = soops->search_flags;
-
- /* try to find matching element */
- te = outliner_find_name(soops, &soops->tree, name, flags, last_find, &prevFound);
- if (te == NULL) {
- /* no more matches after previous, start from beginning again */
- prevFound = 1;
- te = outliner_find_name(soops, &soops->tree, name, flags, last_find, &prevFound);
- }
- }
- else {
- /* pop up panel - no previous, or user didn't want search after previous */
- name[0] = '\0';
-// XXX if (sbutton(name, 0, sizeof(name) - 1, "Find: ") && name[0]) {
-// te = outliner_find_name(soops, &soops->tree, name, flags, NULL, &prevFound);
-// }
-// else return; /* XXX RETURN! XXX */
- }
-
- /* do selection and reveal */
- if (te) {
- tselem = TREESTORE(te);
- 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);
-
- /* deselect all visible, and select found element */
- outliner_flag_set(soops, &soops->tree, TSE_SELECTED, 0);
- tselem->flag |= TSE_SELECTED;
-
- /* make te->ys center of view */
- ytop = (int)(te->ys + BLI_rctf_size_y(&ar->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));
-
- /* 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;
-
- /* store selection */
- soops->search_tse = *tselem;
-
- BLI_strncpy(soops->search_string, name, sizeof(soops->search_string));
- soops->search_flags = flags;
-
- /* redraw */
- ED_region_tag_redraw_no_rebuild(ar);
- }
- }
- else {
- /* no tree-element found */
- BKE_reportf(reports, RPT_WARNING, "Not found: %s", name);
- }
+ ReportList *reports = NULL; // CTX_wm_reports(C);
+ TreeElement *te = NULL;
+ TreeElement *last_find;
+ TreeStoreElem *tselem;
+ int ytop, xdelta, prevFound = 0;
+ char name[sizeof(soops->search_string)];
+
+ /* get last found tree-element based on stored search_tse */
+ last_find = outliner_find_tse(soops, &soops->search_tse);
+
+ /* determine which type of search to do */
+ if (again && last_find) {
+ /* no popup panel - previous + user wanted to search for next after previous */
+ BLI_strncpy(name, soops->search_string, sizeof(name));
+ flags = soops->search_flags;
+
+ /* try to find matching element */
+ te = outliner_find_name(soops, &soops->tree, name, flags, last_find, &prevFound);
+ if (te == NULL) {
+ /* no more matches after previous, start from beginning again */
+ prevFound = 1;
+ te = outliner_find_name(soops, &soops->tree, name, flags, last_find, &prevFound);
+ }
+ }
+ else {
+ /* pop up panel - no previous, or user didn't want search after previous */
+ name[0] = '\0';
+// XXX if (sbutton(name, 0, sizeof(name) - 1, "Find: ") && name[0]) {
+// te = outliner_find_name(soops, &soops->tree, name, flags, NULL, &prevFound);
+// }
+// else return; /* XXX RETURN! XXX */
+ }
+
+ /* do selection and reveal */
+ if (te) {
+ tselem = TREESTORE(te);
+ 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);
+
+ /* deselect all visible, and select found element */
+ outliner_flag_set(soops, &soops->tree, TSE_SELECTED, 0);
+ tselem->flag |= TSE_SELECTED;
+
+ /* make te->ys center of view */
+ ytop = (int)(te->ys + BLI_rctf_size_y(&ar->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));
+
+ /* 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;
+
+ /* store selection */
+ soops->search_tse = *tselem;
+
+ BLI_strncpy(soops->search_string, name, sizeof(soops->search_string));
+ soops->search_flags = flags;
+
+ /* redraw */
+ ED_region_tag_redraw_no_rebuild(ar);
+ }
+ }
+ else {
+ /* no tree-element found */
+ BKE_reportf(reports, RPT_WARNING, "Not found: %s", name);
+ }
}
#endif
@@ -1336,72 +1405,72 @@ static void outliner_find_panel(Scene *UNUSED(scene), ARegion *ar, SpaceOutliner
/* helper function for Show/Hide one level operator */
static void outliner_openclose_level(ListBase *lb, int curlevel, int level, int open)
{
- TreeElement *te;
- TreeStoreElem *tselem;
+ TreeElement *te;
+ TreeStoreElem *tselem;
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
+ for (te = lb->first; te; te = te->next) {
+ tselem = TREESTORE(te);
- if (open) {
- if (curlevel <= level) {
- tselem->flag &= ~TSE_CLOSED;
- }
- }
- else {
- if (curlevel >= level) {
- tselem->flag |= TSE_CLOSED;
- }
- }
+ if (open) {
+ if (curlevel <= level) {
+ tselem->flag &= ~TSE_CLOSED;
+ }
+ }
+ else {
+ if (curlevel >= level) {
+ tselem->flag |= TSE_CLOSED;
+ }
+ }
- outliner_openclose_level(&te->subtree, curlevel + 1, level, open);
- }
+ outliner_openclose_level(&te->subtree, curlevel + 1, level, open);
+ }
}
static int outliner_one_level_exec(bContext *C, wmOperator *op)
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
- const bool add = RNA_boolean_get(op->ptr, "open");
- int level;
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ ARegion *ar = CTX_wm_region(C);
+ const bool add = RNA_boolean_get(op->ptr, "open");
+ int level;
- level = outliner_flag_is_any_test(&soops->tree, TSE_CLOSED, 1);
- if (add == 1) {
- if (level) {
- outliner_openclose_level(&soops->tree, 1, level, 1);
- }
- }
- else {
- if (level == 0) {
- level = outliner_count_levels(&soops->tree, 0);
- }
- if (level) {
- outliner_openclose_level(&soops->tree, 1, level - 1, 0);
- }
- }
+ level = outliner_flag_is_any_test(&soops->tree, TSE_CLOSED, 1);
+ if (add == 1) {
+ if (level) {
+ outliner_openclose_level(&soops->tree, 1, level, 1);
+ }
+ }
+ else {
+ if (level == 0) {
+ level = outliner_count_levels(&soops->tree, 0);
+ }
+ if (level) {
+ outliner_openclose_level(&soops->tree, 1, level - 1, 0);
+ }
+ }
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_show_one_level(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Show/Hide One Level";
- ot->idname = "OUTLINER_OT_show_one_level";
- ot->description = "Expand/collapse all entries by one level";
+ /* identifiers */
+ ot->name = "Show/Hide One Level";
+ ot->idname = "OUTLINER_OT_show_one_level";
+ ot->description = "Expand/collapse all entries by one level";
- /* callbacks */
- ot->exec = outliner_one_level_exec;
- ot->poll = ED_operator_outliner_active;
+ /* callbacks */
+ ot->exec = outliner_one_level_exec;
+ ot->poll = ED_operator_outliner_active;
- /* no undo or registry, UI option */
+ /* no undo or registry, UI option */
- /* properties */
- prop = RNA_def_boolean(ot->srna, "open", 1, "Open", "Expand all entries one level deep");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "open", 1, "Open", "Expand all entries one level deep");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* Show Hierarchy ----------------------------------------------- */
@@ -1409,86 +1478,86 @@ void OUTLINER_OT_show_one_level(wmOperatorType *ot)
/* helper function for tree_element_shwo_hierarchy() - recursively checks whether subtrees have any objects*/
static int subtree_has_objects(ListBase *lb)
{
- TreeElement *te;
- TreeStoreElem *tselem;
+ TreeElement *te;
+ TreeStoreElem *tselem;
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
- if (tselem->type == 0 && te->idcode == ID_OB) {
- return 1;
- }
- if (subtree_has_objects(&te->subtree)) {
- return 1;
- }
- }
- return 0;
+ for (te = lb->first; te; te = te->next) {
+ tselem = TREESTORE(te);
+ if (tselem->type == 0 && te->idcode == ID_OB) {
+ return 1;
+ }
+ if (subtree_has_objects(&te->subtree)) {
+ return 1;
+ }
+ }
+ return 0;
}
/* recursive helper function for Show Hierarchy operator */
static void tree_element_show_hierarchy(Scene *scene, SpaceOutliner *soops, ListBase *lb)
{
- TreeElement *te;
- TreeStoreElem *tselem;
-
- /* open all object elems, close others */
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
-
- if (tselem->type == 0) {
- if (te->idcode == ID_SCE) {
- if (tselem->id != (ID *)scene) {
- tselem->flag |= TSE_CLOSED;
- }
- else {
- tselem->flag &= ~TSE_CLOSED;
- }
- }
- else if (te->idcode == ID_OB) {
- if (subtree_has_objects(&te->subtree)) {
- tselem->flag &= ~TSE_CLOSED;
- }
- else {
- tselem->flag |= TSE_CLOSED;
- }
- }
- }
- else {
- tselem->flag |= TSE_CLOSED;
- }
-
- if (TSELEM_OPEN(tselem, soops)) {
- tree_element_show_hierarchy(scene, soops, &te->subtree);
- }
- }
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ /* open all object elems, close others */
+ for (te = lb->first; te; te = te->next) {
+ tselem = TREESTORE(te);
+
+ if (tselem->type == 0) {
+ if (te->idcode == ID_SCE) {
+ if (tselem->id != (ID *)scene) {
+ tselem->flag |= TSE_CLOSED;
+ }
+ else {
+ tselem->flag &= ~TSE_CLOSED;
+ }
+ }
+ else if (te->idcode == ID_OB) {
+ if (subtree_has_objects(&te->subtree)) {
+ tselem->flag &= ~TSE_CLOSED;
+ }
+ else {
+ tselem->flag |= TSE_CLOSED;
+ }
+ }
+ }
+ else {
+ tselem->flag |= TSE_CLOSED;
+ }
+
+ if (TSELEM_OPEN(tselem, soops)) {
+ tree_element_show_hierarchy(scene, soops, &te->subtree);
+ }
+ }
}
/* show entire object level hierarchy */
static int outliner_show_hierarchy_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
- /* recursively open/close levels */
- tree_element_show_hierarchy(scene, soops, &soops->tree);
+ /* recursively open/close levels */
+ tree_element_show_hierarchy(scene, soops, &soops->tree);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_show_hierarchy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Show Hierarchy";
- ot->idname = "OUTLINER_OT_show_hierarchy";
- ot->description = "Open all object entries and close all others";
+ /* identifiers */
+ ot->name = "Show Hierarchy";
+ ot->idname = "OUTLINER_OT_show_hierarchy";
+ ot->description = "Open all object entries and close all others";
- /* callbacks */
- ot->exec = outliner_show_hierarchy_exec;
- ot->poll = ED_operator_outliner_active; // TODO: shouldn't be allowed in RNA views...
+ /* callbacks */
+ ot->exec = outliner_show_hierarchy_exec;
+ ot->poll = ED_operator_outliner_active; // TODO: shouldn't be allowed in RNA views...
- /* no undo or registry, UI option */
+ /* no undo or registry, UI option */
}
/* ************************************************************** */
@@ -1498,157 +1567,161 @@ void OUTLINER_OT_show_hierarchy(wmOperatorType *ot)
/* specialized poll callback for these operators to work in Datablocks view only */
static bool ed_operator_outliner_datablocks_active(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- if ((sa) && (sa->spacetype == SPACE_OUTLINER)) {
- SpaceOutliner *so = CTX_wm_space_outliner(C);
- return (so->outlinevis == SO_DATA_API);
- }
- return 0;
+ ScrArea *sa = CTX_wm_area(C);
+ if ((sa) && (sa->spacetype == SPACE_OUTLINER)) {
+ SpaceOutliner *so = CTX_wm_space_outliner(C);
+ return (so->outlinevis == SO_DATA_API);
+ }
+ return 0;
}
-
/* Helper func to extract an RNA path from selected tree element
* NOTE: the caller must zero-out all values of the pointers that it passes here first, as
* this function does not do that yet
*/
-static void tree_element_to_path(TreeElement *te, TreeStoreElem *tselem,
- ID **id, char **path, int *array_index, short *flag, short *UNUSED(groupmode))
-{
- ListBase hierarchy = {NULL, NULL};
- LinkData *ld;
- TreeElement *tem, *temnext, *temsub;
- TreeStoreElem *tse /* , *tsenext */ /* UNUSED */;
- PointerRNA *ptr, *nextptr;
- PropertyRNA *prop;
- char *newpath = NULL;
-
- /* optimize tricks:
- * - Don't do anything if the selected item is a 'struct', but arrays are allowed
- */
- if (tselem->type == TSE_RNA_STRUCT) {
- return;
- }
-
- /* Overview of Algorithm:
- * 1. Go up the chain of parents until we find the 'root', taking note of the
- * levels encountered in reverse-order (i.e. items are added to the start of the list
- * for more convenient looping later)
- * 2. Walk down the chain, adding from the first ID encountered
- * (which will become the 'ID' for the KeyingSet Path), and build a
- * path as we step through the chain
- */
-
- /* step 1: flatten out hierarchy of parents into a flat chain */
- for (tem = te->parent; tem; tem = tem->parent) {
- ld = MEM_callocN(sizeof(LinkData), "LinkData for tree_element_to_path()");
- ld->data = tem;
- BLI_addhead(&hierarchy, ld);
- }
-
- /* step 2: step down hierarchy building the path
- * (NOTE: addhead in previous loop was needed so that we can loop like this) */
- for (ld = hierarchy.first; ld; ld = ld->next) {
- /* get data */
- tem = (TreeElement *)ld->data;
- tse = TREESTORE(tem);
- ptr = &tem->rnaptr;
- prop = tem->directdata;
-
- /* check if we're looking for first ID, or appending to path */
- if (*id) {
- /* just 'append' property to path
- * - to prevent memory leaks, we must write to newpath not path, then free old path + swap them
- */
- if (tse->type == TSE_RNA_PROPERTY) {
- if (RNA_property_type(prop) == PROP_POINTER) {
- /* for pointer we just append property name */
- newpath = RNA_path_append(*path, ptr, prop, 0, NULL);
- }
- else if (RNA_property_type(prop) == PROP_COLLECTION) {
- char buf[128], *name;
-
- temnext = (TreeElement *)(ld->next->data);
- /* tsenext = TREESTORE(temnext); */ /* UNUSED */
-
- nextptr = &temnext->rnaptr;
- name = RNA_struct_name_get_alloc(nextptr, buf, sizeof(buf), NULL);
-
- if (name) {
- /* if possible, use name as a key in the path */
- newpath = RNA_path_append(*path, NULL, prop, 0, name);
-
- if (name != buf) {
- MEM_freeN(name);
- }
- }
- else {
- /* otherwise use index */
- int index = 0;
-
- for (temsub = tem->subtree.first; temsub; temsub = temsub->next, index++) {
- if (temsub == temnext) {
- break;
- }
- }
- newpath = RNA_path_append(*path, NULL, prop, index, NULL);
- }
-
- ld = ld->next;
- }
- }
-
- if (newpath) {
- if (*path) {
- MEM_freeN(*path);
- }
- *path = newpath;
- newpath = NULL;
- }
- }
- else {
- /* no ID, so check if entry is RNA-struct, and if that RNA-struct is an ID datablock to extract info from */
- if (tse->type == TSE_RNA_STRUCT) {
- /* ptr->data not ptr->id.data 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;
-
- /* clear path */
- if (*path) {
- MEM_freeN(*path);
- path = NULL;
- }
- }
- }
- }
- }
-
- /* step 3: if we've got an ID, add the current item to the path */
- if (*id) {
- /* add the active property to the path */
- ptr = &te->rnaptr;
- prop = te->directdata;
-
- /* array checks */
- if (tselem->type == TSE_RNA_ARRAY_ELEM) {
- /* item is part of an array, so must set the array_index */
- *array_index = te->index;
- }
- else if (RNA_property_array_check(prop)) {
- /* entire array was selected, so keyframe all */
- *flag |= KSP_FLAG_WHOLE_ARRAY;
- }
-
- /* path */
- newpath = RNA_path_append(*path, NULL, prop, 0, NULL);
- if (*path) {
- MEM_freeN(*path);
- }
- *path = newpath;
- }
-
- /* free temp data */
- BLI_freelistN(&hierarchy);
+static void tree_element_to_path(TreeElement *te,
+ TreeStoreElem *tselem,
+ ID **id,
+ char **path,
+ int *array_index,
+ short *flag,
+ short *UNUSED(groupmode))
+{
+ ListBase hierarchy = {NULL, NULL};
+ LinkData *ld;
+ TreeElement *tem, *temnext, *temsub;
+ TreeStoreElem *tse /* , *tsenext */ /* UNUSED */;
+ PointerRNA *ptr, *nextptr;
+ PropertyRNA *prop;
+ char *newpath = NULL;
+
+ /* optimize tricks:
+ * - Don't do anything if the selected item is a 'struct', but arrays are allowed
+ */
+ if (tselem->type == TSE_RNA_STRUCT) {
+ return;
+ }
+
+ /* Overview of Algorithm:
+ * 1. Go up the chain of parents until we find the 'root', taking note of the
+ * levels encountered in reverse-order (i.e. items are added to the start of the list
+ * for more convenient looping later)
+ * 2. Walk down the chain, adding from the first ID encountered
+ * (which will become the 'ID' for the KeyingSet Path), and build a
+ * path as we step through the chain
+ */
+
+ /* step 1: flatten out hierarchy of parents into a flat chain */
+ for (tem = te->parent; tem; tem = tem->parent) {
+ ld = MEM_callocN(sizeof(LinkData), "LinkData for tree_element_to_path()");
+ ld->data = tem;
+ BLI_addhead(&hierarchy, ld);
+ }
+
+ /* step 2: step down hierarchy building the path
+ * (NOTE: addhead in previous loop was needed so that we can loop like this) */
+ for (ld = hierarchy.first; ld; ld = ld->next) {
+ /* get data */
+ tem = (TreeElement *)ld->data;
+ tse = TREESTORE(tem);
+ ptr = &tem->rnaptr;
+ prop = tem->directdata;
+
+ /* check if we're looking for first ID, or appending to path */
+ if (*id) {
+ /* just 'append' property to path
+ * - to prevent memory leaks, we must write to newpath not path, then free old path + swap them
+ */
+ if (tse->type == TSE_RNA_PROPERTY) {
+ if (RNA_property_type(prop) == PROP_POINTER) {
+ /* for pointer we just append property name */
+ newpath = RNA_path_append(*path, ptr, prop, 0, NULL);
+ }
+ else if (RNA_property_type(prop) == PROP_COLLECTION) {
+ char buf[128], *name;
+
+ temnext = (TreeElement *)(ld->next->data);
+ /* tsenext = TREESTORE(temnext); */ /* UNUSED */
+
+ nextptr = &temnext->rnaptr;
+ name = RNA_struct_name_get_alloc(nextptr, buf, sizeof(buf), NULL);
+
+ if (name) {
+ /* if possible, use name as a key in the path */
+ newpath = RNA_path_append(*path, NULL, prop, 0, name);
+
+ if (name != buf) {
+ MEM_freeN(name);
+ }
+ }
+ else {
+ /* otherwise use index */
+ int index = 0;
+
+ for (temsub = tem->subtree.first; temsub; temsub = temsub->next, index++) {
+ if (temsub == temnext) {
+ break;
+ }
+ }
+ newpath = RNA_path_append(*path, NULL, prop, index, NULL);
+ }
+
+ ld = ld->next;
+ }
+ }
+
+ if (newpath) {
+ if (*path) {
+ MEM_freeN(*path);
+ }
+ *path = newpath;
+ newpath = NULL;
+ }
+ }
+ else {
+ /* no ID, so check if entry is RNA-struct, and if that RNA-struct is an ID datablock to extract info from */
+ if (tse->type == TSE_RNA_STRUCT) {
+ /* ptr->data not ptr->id.data 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;
+
+ /* clear path */
+ if (*path) {
+ MEM_freeN(*path);
+ path = NULL;
+ }
+ }
+ }
+ }
+ }
+
+ /* step 3: if we've got an ID, add the current item to the path */
+ if (*id) {
+ /* add the active property to the path */
+ ptr = &te->rnaptr;
+ prop = te->directdata;
+
+ /* array checks */
+ if (tselem->type == TSE_RNA_ARRAY_ELEM) {
+ /* item is part of an array, so must set the array_index */
+ *array_index = te->index;
+ }
+ else if (RNA_property_array_check(prop)) {
+ /* entire array was selected, so keyframe all */
+ *flag |= KSP_FLAG_WHOLE_ARRAY;
+ }
+
+ /* path */
+ newpath = RNA_path_append(*path, NULL, prop, 0, NULL);
+ if (*path) {
+ MEM_freeN(*path);
+ }
+ *path = newpath;
+ }
+
+ /* free temp data */
+ BLI_freelistN(&hierarchy);
}
/* =============================================== */
@@ -1658,159 +1731,155 @@ static void tree_element_to_path(TreeElement *te, TreeStoreElem *tselem,
* they depend on having RNA paths and/or hierarchies available.
*/
enum {
- DRIVERS_EDITMODE_ADD = 0,
- DRIVERS_EDITMODE_REMOVE,
+ 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, ReportList *reports, short mode)
-{
- TreeElement *te;
- TreeStoreElem *tselem;
-
- for (te = tree->first; te; te = te->next) {
- tselem = TREESTORE(te);
-
- /* if item is selected, perform operation */
- if (tselem->flag & TSE_SELECTED) {
- ID *id = NULL;
- char *path = NULL;
- int array_index = 0;
- short flag = 0;
- short groupmode = KSP_GROUP_KSNAME;
-
- /* check if RNA-property described by this selected element is an animatable prop */
- if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM) &&
- RNA_property_animateable(&te->rnaptr, te->directdata))
- {
- /* get id + path + index info from the selected element */
- tree_element_to_path(te, tselem,
- &id, &path, &array_index, &flag, &groupmode);
- }
-
- /* only if ID and path were set, should we perform any actions */
- if (id && path) {
- short dflags = CREATEDRIVER_WITH_DEFAULT_DVAR;
- int arraylen = 1;
-
- /* array checks */
- if (flag & KSP_FLAG_WHOLE_ARRAY) {
- /* entire array was selected, so add drivers for all */
- arraylen = RNA_property_array_length(&te->rnaptr, te->directdata);
- }
- else {
- arraylen = array_index;
- }
-
- /* we should do at least one step */
- if (arraylen == array_index) {
- arraylen++;
- }
-
- /* for each array element we should affect, add driver */
- for (; array_index < arraylen; array_index++) {
- /* action depends on mode */
- switch (mode) {
- case DRIVERS_EDITMODE_ADD:
- {
- /* add a new driver with the information obtained (only if valid) */
- ANIM_add_driver(reports, id, path, array_index, dflags, DRIVER_TYPE_PYTHON);
- break;
- }
- case DRIVERS_EDITMODE_REMOVE:
- {
- /* remove driver matching the information obtained (only if valid) */
- ANIM_remove_driver(reports, id, path, array_index, dflags);
- break;
- }
- }
- }
-
- /* free path, since it had to be generated */
- MEM_freeN(path);
- }
-
-
- }
-
- /* go over sub-tree */
- if (TSELEM_OPEN(tselem, soops)) {
- do_outliner_drivers_editop(soops, &te->subtree, reports, mode);
- }
- }
+static void do_outliner_drivers_editop(SpaceOutliner *soops,
+ ListBase *tree,
+ ReportList *reports,
+ short mode)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for (te = tree->first; te; te = te->next) {
+ tselem = TREESTORE(te);
+
+ /* if item is selected, perform operation */
+ if (tselem->flag & TSE_SELECTED) {
+ ID *id = NULL;
+ char *path = NULL;
+ int array_index = 0;
+ short flag = 0;
+ short groupmode = KSP_GROUP_KSNAME;
+
+ /* check if RNA-property described by this selected element is an animatable prop */
+ if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM) &&
+ RNA_property_animateable(&te->rnaptr, te->directdata)) {
+ /* get id + path + index info from the selected element */
+ tree_element_to_path(te, tselem, &id, &path, &array_index, &flag, &groupmode);
+ }
+
+ /* only if ID and path were set, should we perform any actions */
+ if (id && path) {
+ short dflags = CREATEDRIVER_WITH_DEFAULT_DVAR;
+ int arraylen = 1;
+
+ /* array checks */
+ if (flag & KSP_FLAG_WHOLE_ARRAY) {
+ /* entire array was selected, so add drivers for all */
+ arraylen = RNA_property_array_length(&te->rnaptr, te->directdata);
+ }
+ else {
+ arraylen = array_index;
+ }
+
+ /* we should do at least one step */
+ if (arraylen == array_index) {
+ arraylen++;
+ }
+
+ /* for each array element we should affect, add driver */
+ for (; array_index < arraylen; array_index++) {
+ /* action depends on mode */
+ switch (mode) {
+ case DRIVERS_EDITMODE_ADD: {
+ /* add a new driver with the information obtained (only if valid) */
+ ANIM_add_driver(reports, id, path, array_index, dflags, DRIVER_TYPE_PYTHON);
+ break;
+ }
+ case DRIVERS_EDITMODE_REMOVE: {
+ /* remove driver matching the information obtained (only if valid) */
+ ANIM_remove_driver(reports, id, path, array_index, dflags);
+ break;
+ }
+ }
+ }
+
+ /* free path, since it had to be generated */
+ MEM_freeN(path);
+ }
+ }
+
+ /* go over sub-tree */
+ if (TSELEM_OPEN(tselem, soops)) {
+ do_outliner_drivers_editop(soops, &te->subtree, reports, mode);
+ }
+ }
}
/* Add Operator ---------------------------------- */
static int outliner_drivers_addsel_exec(bContext *C, wmOperator *op)
{
- SpaceOutliner *soutliner = CTX_wm_space_outliner(C);
+ SpaceOutliner *soutliner = CTX_wm_space_outliner(C);
- /* check for invalid states */
- if (soutliner == NULL) {
- return OPERATOR_CANCELLED;
- }
+ /* check for invalid states */
+ if (soutliner == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- /* recursively go into tree, adding selected items */
- do_outliner_drivers_editop(soutliner, &soutliner->tree, op->reports, DRIVERS_EDITMODE_ADD);
+ /* recursively go into tree, adding selected items */
+ do_outliner_drivers_editop(soutliner, &soutliner->tree, op->reports, DRIVERS_EDITMODE_ADD);
- /* send notifiers */
- WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX
+ /* send notifiers */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_drivers_add_selected(wmOperatorType *ot)
{
- /* api callbacks */
- ot->idname = "OUTLINER_OT_drivers_add_selected";
- ot->name = "Add Drivers for Selected";
- ot->description = "Add drivers to selected items";
+ /* api callbacks */
+ ot->idname = "OUTLINER_OT_drivers_add_selected";
+ ot->name = "Add Drivers for Selected";
+ ot->description = "Add drivers to selected items";
- /* api callbacks */
- ot->exec = outliner_drivers_addsel_exec;
- ot->poll = ed_operator_outliner_datablocks_active;
+ /* api callbacks */
+ ot->exec = outliner_drivers_addsel_exec;
+ ot->poll = ed_operator_outliner_datablocks_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/* Remove Operator ---------------------------------- */
static int outliner_drivers_deletesel_exec(bContext *C, wmOperator *op)
{
- SpaceOutliner *soutliner = CTX_wm_space_outliner(C);
+ SpaceOutliner *soutliner = CTX_wm_space_outliner(C);
- /* check for invalid states */
- if (soutliner == NULL) {
- return OPERATOR_CANCELLED;
- }
+ /* check for invalid states */
+ if (soutliner == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- /* recursively go into tree, adding selected items */
- do_outliner_drivers_editop(soutliner, &soutliner->tree, op->reports, DRIVERS_EDITMODE_REMOVE);
+ /* recursively go into tree, adding selected items */
+ do_outliner_drivers_editop(soutliner, &soutliner->tree, op->reports, DRIVERS_EDITMODE_REMOVE);
- /* send notifiers */
- WM_event_add_notifier(C, ND_KEYS, NULL); // XXX
+ /* send notifiers */
+ WM_event_add_notifier(C, ND_KEYS, NULL); // XXX
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_drivers_delete_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->idname = "OUTLINER_OT_drivers_delete_selected";
- ot->name = "Delete Drivers for Selected";
- ot->description = "Delete drivers assigned to selected items";
+ /* identifiers */
+ ot->idname = "OUTLINER_OT_drivers_delete_selected";
+ ot->name = "Delete Drivers for Selected";
+ ot->description = "Delete drivers assigned to selected items";
- /* api callbacks */
- ot->exec = outliner_drivers_deletesel_exec;
- ot->poll = ed_operator_outliner_datablocks_active;
+ /* api callbacks */
+ ot->exec = outliner_drivers_deletesel_exec;
+ ot->poll = ed_operator_outliner_datablocks_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* =============================================== */
@@ -1820,8 +1889,8 @@ void OUTLINER_OT_drivers_delete_selected(wmOperatorType *ot)
* they depend on having RNA paths and/or hierarchies available.
*/
enum {
- KEYINGSET_EDITMODE_ADD = 0,
- KEYINGSET_EDITMODE_REMOVE,
+ KEYINGSET_EDITMODE_ADD = 0,
+ KEYINGSET_EDITMODE_REMOVE,
} /*eKeyingSet_EditModes*/;
/* Utilities ---------------------------------- */
@@ -1830,300 +1899,298 @@ enum {
// TODO: should this be an API func?
static KeyingSet *verify_active_keyingset(Scene *scene, short add)
{
- KeyingSet *ks = NULL;
+ KeyingSet *ks = NULL;
- /* sanity check */
- if (scene == NULL) {
- return NULL;
- }
+ /* sanity check */
+ if (scene == NULL) {
+ return NULL;
+ }
- /* try to find one from scene */
- if (scene->active_keyingset > 0) {
- ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1);
- }
+ /* try to find one from scene */
+ if (scene->active_keyingset > 0) {
+ ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1);
+ }
- /* add if none found */
- // XXX the default settings have yet to evolve
- if ((add) && (ks == NULL)) {
- ks = BKE_keyingset_add(&scene->keyingsets, NULL, NULL, KEYINGSET_ABSOLUTE, 0);
- scene->active_keyingset = BLI_listbase_count(&scene->keyingsets);
- }
+ /* add if none found */
+ // XXX the default settings have yet to evolve
+ if ((add) && (ks == NULL)) {
+ ks = BKE_keyingset_add(&scene->keyingsets, NULL, NULL, KEYINGSET_ABSOLUTE, 0);
+ scene->active_keyingset = BLI_listbase_count(&scene->keyingsets);
+ }
- return ks;
+ return ks;
}
/* Recursively iterate over tree, finding and working on selected items */
-static void do_outliner_keyingset_editop(SpaceOutliner *soops, KeyingSet *ks, ListBase *tree, short mode)
-{
- TreeElement *te;
- TreeStoreElem *tselem;
-
- for (te = tree->first; te; te = te->next) {
- tselem = TREESTORE(te);
-
- /* if item is selected, perform operation */
- if (tselem->flag & TSE_SELECTED) {
- ID *id = NULL;
- char *path = NULL;
- int array_index = 0;
- short flag = 0;
- short groupmode = KSP_GROUP_KSNAME;
-
- /* check if RNA-property described by this selected element is an animatable prop */
- if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM) &&
- RNA_property_animateable(&te->rnaptr, te->directdata))
- {
- /* get id + path + index info from the selected element */
- tree_element_to_path(te, tselem,
- &id, &path, &array_index, &flag, &groupmode);
- }
-
- /* only if ID and path were set, should we perform any actions */
- if (id && path) {
- /* action depends on mode */
- switch (mode) {
- case KEYINGSET_EDITMODE_ADD:
- {
- /* add a new path with the information obtained (only if valid) */
- /* TODO: what do we do with group name?
- * for now, we don't supply one, and just let this use the KeyingSet name */
- BKE_keyingset_add_path(ks, id, NULL, path, array_index, flag, groupmode);
- ks->active_path = BLI_listbase_count(&ks->paths);
- break;
- }
- case KEYINGSET_EDITMODE_REMOVE:
- {
- /* find the relevant path, then remove it from the KeyingSet */
- KS_Path *ksp = BKE_keyingset_find_path(ks, id, NULL, path, array_index, groupmode);
-
- if (ksp) {
- /* free path's data */
- BKE_keyingset_free_path(ks, ksp);
-
- ks->active_path = 0;
- }
- break;
- }
- }
-
- /* free path, since it had to be generated */
- MEM_freeN(path);
- }
- }
-
- /* go over sub-tree */
- if (TSELEM_OPEN(tselem, soops)) {
- do_outliner_keyingset_editop(soops, ks, &te->subtree, mode);
- }
- }
+static void do_outliner_keyingset_editop(SpaceOutliner *soops,
+ KeyingSet *ks,
+ ListBase *tree,
+ short mode)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for (te = tree->first; te; te = te->next) {
+ tselem = TREESTORE(te);
+
+ /* if item is selected, perform operation */
+ if (tselem->flag & TSE_SELECTED) {
+ ID *id = NULL;
+ char *path = NULL;
+ int array_index = 0;
+ short flag = 0;
+ short groupmode = KSP_GROUP_KSNAME;
+
+ /* check if RNA-property described by this selected element is an animatable prop */
+ if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM) &&
+ RNA_property_animateable(&te->rnaptr, te->directdata)) {
+ /* get id + path + index info from the selected element */
+ tree_element_to_path(te, tselem, &id, &path, &array_index, &flag, &groupmode);
+ }
+
+ /* only if ID and path were set, should we perform any actions */
+ if (id && path) {
+ /* action depends on mode */
+ switch (mode) {
+ case KEYINGSET_EDITMODE_ADD: {
+ /* add a new path with the information obtained (only if valid) */
+ /* TODO: what do we do with group name?
+ * for now, we don't supply one, and just let this use the KeyingSet name */
+ BKE_keyingset_add_path(ks, id, NULL, path, array_index, flag, groupmode);
+ ks->active_path = BLI_listbase_count(&ks->paths);
+ break;
+ }
+ case KEYINGSET_EDITMODE_REMOVE: {
+ /* find the relevant path, then remove it from the KeyingSet */
+ KS_Path *ksp = BKE_keyingset_find_path(ks, id, NULL, path, array_index, groupmode);
+
+ if (ksp) {
+ /* free path's data */
+ BKE_keyingset_free_path(ks, ksp);
+
+ ks->active_path = 0;
+ }
+ break;
+ }
+ }
+
+ /* free path, since it had to be generated */
+ MEM_freeN(path);
+ }
+ }
+
+ /* go over sub-tree */
+ if (TSELEM_OPEN(tselem, soops)) {
+ do_outliner_keyingset_editop(soops, ks, &te->subtree, mode);
+ }
+ }
}
/* Add Operator ---------------------------------- */
static int outliner_keyingset_additems_exec(bContext *C, wmOperator *op)
{
- SpaceOutliner *soutliner = CTX_wm_space_outliner(C);
- Scene *scene = CTX_data_scene(C);
- KeyingSet *ks = verify_active_keyingset(scene, 1);
+ SpaceOutliner *soutliner = CTX_wm_space_outliner(C);
+ Scene *scene = CTX_data_scene(C);
+ KeyingSet *ks = verify_active_keyingset(scene, 1);
- /* check for invalid states */
- if (ks == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Operation requires an active keying set");
- return OPERATOR_CANCELLED;
- }
- if (soutliner == NULL) {
- return OPERATOR_CANCELLED;
- }
+ /* check for invalid states */
+ if (ks == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Operation requires an active keying set");
+ return OPERATOR_CANCELLED;
+ }
+ if (soutliner == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- /* recursively go into tree, adding selected items */
- do_outliner_keyingset_editop(soutliner, ks, &soutliner->tree, KEYINGSET_EDITMODE_ADD);
+ /* recursively go into tree, adding selected items */
+ do_outliner_keyingset_editop(soutliner, ks, &soutliner->tree, KEYINGSET_EDITMODE_ADD);
- /* send notifiers */
- WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
+ /* send notifiers */
+ WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_keyingset_add_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->idname = "OUTLINER_OT_keyingset_add_selected";
- ot->name = "Keying Set Add Selected";
- ot->description = "Add selected items (blue-gray rows) to active Keying Set";
+ /* identifiers */
+ ot->idname = "OUTLINER_OT_keyingset_add_selected";
+ ot->name = "Keying Set Add Selected";
+ ot->description = "Add selected items (blue-gray rows) to active Keying Set";
- /* api callbacks */
- ot->exec = outliner_keyingset_additems_exec;
- ot->poll = ed_operator_outliner_datablocks_active;
+ /* api callbacks */
+ ot->exec = outliner_keyingset_additems_exec;
+ ot->poll = ed_operator_outliner_datablocks_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/* Remove Operator ---------------------------------- */
static int outliner_keyingset_removeitems_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceOutliner *soutliner = CTX_wm_space_outliner(C);
- Scene *scene = CTX_data_scene(C);
- KeyingSet *ks = verify_active_keyingset(scene, 1);
+ SpaceOutliner *soutliner = CTX_wm_space_outliner(C);
+ Scene *scene = CTX_data_scene(C);
+ KeyingSet *ks = verify_active_keyingset(scene, 1);
- /* check for invalid states */
- if (soutliner == NULL) {
- return OPERATOR_CANCELLED;
- }
+ /* check for invalid states */
+ if (soutliner == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- /* recursively go into tree, adding selected items */
- do_outliner_keyingset_editop(soutliner, ks, &soutliner->tree, KEYINGSET_EDITMODE_REMOVE);
+ /* recursively go into tree, adding selected items */
+ do_outliner_keyingset_editop(soutliner, ks, &soutliner->tree, KEYINGSET_EDITMODE_REMOVE);
- /* send notifiers */
- WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
+ /* send notifiers */
+ WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_keyingset_remove_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->idname = "OUTLINER_OT_keyingset_remove_selected";
- ot->name = "Keying Set Remove Selected";
- ot->description = "Remove selected items (blue-gray rows) from active Keying Set";
+ /* identifiers */
+ ot->idname = "OUTLINER_OT_keyingset_remove_selected";
+ ot->name = "Keying Set Remove Selected";
+ ot->description = "Remove selected items (blue-gray rows) from active Keying Set";
- /* api callbacks */
- ot->exec = outliner_keyingset_removeitems_exec;
- ot->poll = ed_operator_outliner_datablocks_active;
+ /* api callbacks */
+ ot->exec = outliner_keyingset_removeitems_exec;
+ ot->poll = ed_operator_outliner_datablocks_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/* ************************************************************** */
/* ORPHANED DATABLOCKS */
static bool ed_operator_outliner_id_orphans_active(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- if ((sa) && (sa->spacetype == SPACE_OUTLINER)) {
- SpaceOutliner *so = CTX_wm_space_outliner(C);
- return (so->outlinevis == SO_ID_ORPHANS);
- }
- return 0;
+ ScrArea *sa = CTX_wm_area(C);
+ if ((sa) && (sa->spacetype == SPACE_OUTLINER)) {
+ SpaceOutliner *so = CTX_wm_space_outliner(C);
+ return (so->outlinevis == SO_ID_ORPHANS);
+ }
+ return 0;
}
/* 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))]++;
- }
- else {
- id->tag &= ~LIB_TAG_DOIT;
- }
+ if (id->us == 0) {
+ id->tag |= LIB_TAG_DOIT;
+ num_tagged[INDEX_ID_NULL]++;
+ num_tagged[BKE_idcode_to_index(GS(id->name))]++;
+ }
+ else {
+ id->tag &= ~LIB_TAG_DOIT;
+ }
}
static int outliner_orphans_purge_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(evt))
{
- Main *bmain = CTX_data_main(C);
- int num_tagged[INDEX_ID_MAX] = {0};
-
- /* Tag all IDs having zero users. */
- ID *id;
- FOREACH_MAIN_ID_BEGIN(bmain, id)
- {
- outliner_orphans_purge_tag(id, num_tagged);
- }
- FOREACH_MAIN_ID_END;
- 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");
- return OPERATOR_CANCELLED;
- }
-
- DynStr *dyn_str = BLI_dynstr_new();
- BLI_dynstr_append(dyn_str, "Purging unused data-blocks (");
- bool is_first = true;
- for (int i = 0; i < INDEX_ID_MAX - 2; i++) {
- if (num_tagged[i] != 0) {
- if (!is_first) {
- BLI_dynstr_append(dyn_str, ", ");
- }
- else {
- is_first = false;
- }
- BLI_dynstr_appendf(
- dyn_str, "%d %s",
- num_tagged[i], TIP_(BKE_idcode_to_name_plural(BKE_idcode_from_index(i))));
- }
- }
- BLI_dynstr_append(dyn_str, TIP_("). Click here to proceed..."));
-
- char *message = BLI_dynstr_get_cstring(dyn_str);
- int ret = WM_operator_confirm_message(C, op, message);
-
- MEM_freeN(message);
- BLI_dynstr_free(dyn_str);
- return ret;
+ Main *bmain = CTX_data_main(C);
+ int num_tagged[INDEX_ID_MAX] = {0};
+
+ /* Tag all IDs having zero users. */
+ ID *id;
+ FOREACH_MAIN_ID_BEGIN(bmain, id)
+ {
+ outliner_orphans_purge_tag(id, num_tagged);
+ }
+ FOREACH_MAIN_ID_END;
+ 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");
+ return OPERATOR_CANCELLED;
+ }
+
+ DynStr *dyn_str = BLI_dynstr_new();
+ BLI_dynstr_append(dyn_str, "Purging unused data-blocks (");
+ bool is_first = true;
+ for (int i = 0; i < INDEX_ID_MAX - 2; i++) {
+ if (num_tagged[i] != 0) {
+ if (!is_first) {
+ BLI_dynstr_append(dyn_str, ", ");
+ }
+ else {
+ is_first = false;
+ }
+ BLI_dynstr_appendf(dyn_str,
+ "%d %s",
+ num_tagged[i],
+ TIP_(BKE_idcode_to_name_plural(BKE_idcode_from_index(i))));
+ }
+ }
+ BLI_dynstr_append(dyn_str, TIP_("). Click here to proceed..."));
+
+ char *message = BLI_dynstr_get_cstring(dyn_str);
+ int ret = WM_operator_confirm_message(C, op, message);
+
+ MEM_freeN(message);
+ BLI_dynstr_free(dyn_str);
+ return ret;
}
static int outliner_orphans_purge_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- int num_tagged[INDEX_ID_MAX] = {0};
+ Main *bmain = CTX_data_main(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ int num_tagged[INDEX_ID_MAX] = {0};
- if ((num_tagged[INDEX_ID_NULL] = RNA_int_get(op->ptr, "num_deleted")) == 0) {
- /* Tag all IDs having zero users. */
- ID *id;
- FOREACH_MAIN_ID_BEGIN(bmain, id)
- {
- outliner_orphans_purge_tag(id, num_tagged);
- }
- FOREACH_MAIN_ID_END;
+ if ((num_tagged[INDEX_ID_NULL] = RNA_int_get(op->ptr, "num_deleted")) == 0) {
+ /* Tag all IDs having zero users. */
+ ID *id;
+ FOREACH_MAIN_ID_BEGIN(bmain, id)
+ {
+ outliner_orphans_purge_tag(id, num_tagged);
+ }
+ FOREACH_MAIN_ID_END;
- if (num_tagged[INDEX_ID_NULL] == 0) {
- BKE_report(op->reports, RPT_INFO, "No orphanned data-blocks to purge");
- return OPERATOR_CANCELLED;
- }
- }
+ if (num_tagged[INDEX_ID_NULL] == 0) {
+ BKE_report(op->reports, RPT_INFO, "No orphanned data-blocks to purge");
+ return OPERATOR_CANCELLED;
+ }
+ }
- BKE_id_multi_tagged_delete(bmain);
+ BKE_id_multi_tagged_delete(bmain);
- BKE_reportf(op->reports, RPT_INFO, "Deleted %d data-blocks", num_tagged[INDEX_ID_NULL]);
+ BKE_reportf(op->reports, RPT_INFO, "Deleted %d data-blocks", num_tagged[INDEX_ID_NULL]);
- /* 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);
+ /* 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);
- WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
- return OPERATOR_FINISHED;
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_orphans_purge(wmOperatorType *ot)
{
- /* identifiers */
- ot->idname = "OUTLINER_OT_orphans_purge";
- ot->name = "Purge All";
- ot->description = "Clear all orphaned data-blocks without any users from the file";
+ /* identifiers */
+ ot->idname = "OUTLINER_OT_orphans_purge";
+ ot->name = "Purge All";
+ ot->description = "Clear all orphaned data-blocks without any users from the file";
- /* callbacks */
- ot->invoke = outliner_orphans_purge_invoke;
- ot->exec = outliner_orphans_purge_exec;
- ot->poll = ed_operator_outliner_id_orphans_active;
+ /* callbacks */
+ ot->invoke = outliner_orphans_purge_invoke;
+ ot->exec = outliner_orphans_purge_exec;
+ ot->poll = ed_operator_outliner_id_orphans_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- 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);
+ /* properties */
+ 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 57fed22d36b..d382384076b 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -21,7 +21,6 @@
* \ingroup spoutliner
*/
-
#ifndef __OUTLINER_INTERN_H__
#define __OUTLINER_INTERN_H__
@@ -46,73 +45,106 @@ struct wmKeyConfig;
struct wmOperatorType;
typedef enum TreeElementInsertType {
- TE_INSERT_BEFORE,
- TE_INSERT_AFTER,
- TE_INSERT_INTO,
+ TE_INSERT_BEFORE,
+ TE_INSERT_AFTER,
+ TE_INSERT_INTO,
} TreeElementInsertType;
typedef enum TreeTraversalAction {
- /* Continue traversal regularly, don't skip children. */
- TRAVERSE_CONTINUE = 0,
- /* Stop traversal */
- TRAVERSE_BREAK,
- /* Continue traversal, but skip childs of traversed element */
- TRAVERSE_SKIP_CHILDS,
+ /* Continue traversal regularly, don't skip children. */
+ TRAVERSE_CONTINUE = 0,
+ /* Stop traversal */
+ TRAVERSE_BREAK,
+ /* Continue traversal, but skip childs of traversed element */
+ TRAVERSE_SKIP_CHILDS,
} TreeTraversalAction;
typedef TreeTraversalAction (*TreeTraversalFunc)(struct TreeElement *te, void *customdata);
-
typedef struct TreeElement {
- struct TreeElement *next, *prev, *parent;
- ListBase subtree;
- int xs, ys; // do selection
- TreeStoreElem *store_elem; // element in tree store
- short flag; // flag for non-saved stuff
- short index; // index for data arrays
- short idcode; // from TreeStore id
- short xend; // width of item display, for select
- const char *name;
- void *directdata; // Armature Bones, Base, Sequence, Strip...
- PointerRNA rnaptr; // RNA Pointer
+ struct TreeElement *next, *prev, *parent;
+ ListBase subtree;
+ int xs, ys; // do selection
+ TreeStoreElem *store_elem; // element in tree store
+ short flag; // flag for non-saved stuff
+ short index; // index for data arrays
+ short idcode; // from TreeStore id
+ short xend; // width of item display, for select
+ const char *name;
+ void *directdata; // Armature Bones, Base, Sequence, Strip...
+ PointerRNA rnaptr; // RNA Pointer
} TreeElement;
typedef struct TreeElementIcon {
- struct ID *drag_id, *drag_parent;
- int icon;
+ struct ID *drag_id, *drag_parent;
+ int icon;
} TreeElementIcon;
#define TREESTORE_ID_TYPE(_id) \
- (ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, ID_NT, ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \
- ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS, ID_LP) || \
- /* Only in 'blendfile' mode ... :/ */ \
- ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF, ID_SO, ID_CF, ID_PAL, ID_MC, ID_WS, ID_MSK, ID_PC))
+ (ELEM(GS((_id)->name), \
+ ID_SCE, \
+ ID_LI, \
+ ID_OB, \
+ ID_ME, \
+ ID_CU, \
+ ID_MB, \
+ ID_NT, \
+ ID_MA, \
+ ID_TE, \
+ ID_IM, \
+ ID_LT, \
+ ID_LA, \
+ ID_CA) || \
+ ELEM(GS((_id)->name), \
+ ID_KE, \
+ ID_WO, \
+ ID_SPK, \
+ ID_GR, \
+ ID_AR, \
+ ID_AC, \
+ ID_BR, \
+ ID_PA, \
+ ID_GD, \
+ ID_LS, \
+ ID_LP) || /* Only in 'blendfile' mode ... :/ */ \
+ ELEM(GS((_id)->name), \
+ ID_SCR, \
+ ID_WM, \
+ ID_TXT, \
+ ID_VF, \
+ ID_SO, \
+ ID_CF, \
+ ID_PAL, \
+ ID_MC, \
+ ID_WS, \
+ ID_MSK, \
+ ID_PC))
/* TreeElement->flag */
enum {
- TE_ACTIVE = (1 << 0),
- /* Closed items display their children as icon within the row. TE_ICONROW is for
- * these child-items that are visible but only within the row of the closed parent. */
- TE_ICONROW = (1 << 1),
- TE_LAZY_CLOSED = (1 << 2),
- TE_FREE_NAME = (1 << 3),
- TE_DISABLED = (1 << 4),
- TE_DRAGGING = (1 << 5),
+ TE_ACTIVE = (1 << 0),
+ /* Closed items display their children as icon within the row. TE_ICONROW is for
+ * these child-items that are visible but only within the row of the closed parent. */
+ TE_ICONROW = (1 << 1),
+ TE_LAZY_CLOSED = (1 << 2),
+ TE_FREE_NAME = (1 << 3),
+ TE_DISABLED = (1 << 4),
+ TE_DRAGGING = (1 << 5),
};
/* button events */
-#define OL_NAMEBUTTON 1
+#define OL_NAMEBUTTON 1
typedef enum {
- OL_DRAWSEL_NONE = 0, /* inactive (regular black text) */
- OL_DRAWSEL_NORMAL = 1, /* active object (draws white text) */
- OL_DRAWSEL_ACTIVE = 2, /* active obdata (draws a circle around the icon) */
+ OL_DRAWSEL_NONE = 0, /* inactive (regular black text) */
+ OL_DRAWSEL_NORMAL = 1, /* active object (draws white text) */
+ OL_DRAWSEL_ACTIVE = 2, /* active obdata (draws a circle around the icon) */
} eOLDrawState;
typedef enum {
- OL_SETSEL_NONE = 0, /* don't change the selection state */
- OL_SETSEL_NORMAL = 1, /* select the item */
- OL_SETSEL_EXTEND = 2, /* select the item and extend (also toggles selection) */
+ OL_SETSEL_NONE = 0, /* don't change the selection state */
+ OL_SETSEL_NORMAL = 1, /* select the item */
+ OL_SETSEL_EXTEND = 2, /* select the item and extend (also toggles selection) */
} eOLSetState;
/* get TreeStoreElem associated with a TreeElement
@@ -124,14 +156,14 @@ typedef enum {
#define OL_Y_OFFSET 2
#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 3.0f + V2D_SCROLL_WIDTH)
-#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 2.0f + V2D_SCROLL_WIDTH)
+#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 2.0f + V2D_SCROLL_WIDTH)
#define OL_TOG_RESTRICT_RENDERX (UI_UNIT_X + V2D_SCROLL_WIDTH)
#define OL_TOGW OL_TOG_RESTRICT_SELECTX
-#define OL_RNA_COLX (UI_UNIT_X * 15)
-#define OL_RNA_COL_SIZEX (UI_UNIT_X * 7.5f)
-#define OL_RNA_COL_SPACEX (UI_UNIT_X * 2.5f)
+#define OL_RNA_COLX (UI_UNIT_X * 15)
+#define OL_RNA_COL_SIZEX (UI_UNIT_X * 7.5f)
+#define OL_RNA_COL_SPACEX (UI_UNIT_X * 2.5f)
/* The outliner display modes that support the filter system.
* Note: keep it synced with space_outliner.py */
@@ -153,10 +185,11 @@ typedef enum {
* - not searching into RNA items helps but isn't the complete solution
*/
-#define SEARCHING_OUTLINER(sov) (sov->search_flags & SO_SEARCH_RECURSIVE)
+#define SEARCHING_OUTLINER(sov) (sov->search_flags & SO_SEARCH_RECURSIVE)
/* 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)) )
+#define TSELEM_OPEN(telm, sv) \
+ ((telm->flag & TSE_CLOSED) == 0 || (SEARCHING_OUTLINER(sv) && (telm->flag & TSE_CHILDSEARCH)))
/* outliner_tree.c ----------------------------------------------- */
@@ -164,13 +197,14 @@ void outliner_free_tree(ListBase *tree);
void outliner_cleanup_tree(struct SpaceOutliner *soops);
void outliner_free_tree_element(TreeElement *element, ListBase *parent_subtree);
-void outliner_build_tree(
- struct Main *mainvar,
- struct Scene *scene, struct ViewLayer *view_layer,
- struct SpaceOutliner *soops, struct ARegion *ar);
+void outliner_build_tree(struct Main *mainvar,
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ struct SpaceOutliner *soops,
+ struct ARegion *ar);
typedef struct IDsSelectedData {
- struct ListBase selected_array;
+ struct ListBase selected_array;
} IDsSelectedData;
TreeTraversalAction outliner_find_selected_collections(struct TreeElement *te, void *customdata);
@@ -183,38 +217,62 @@ void draw_outliner(const struct bContext *C);
TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te);
/* outliner_select.c -------------------------------------------- */
-eOLDrawState tree_element_type_active(
- struct bContext *C, struct Scene *scene, struct ViewLayer *view_layer, struct SpaceOutliner *soops,
- TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive);
-eOLDrawState tree_element_active(struct bContext *C, struct Scene *scene, struct ViewLayer *view_layer, SpaceOutliner *soops,
- TreeElement *te, const eOLSetState set, const bool handle_all_types);
+eOLDrawState tree_element_type_active(struct bContext *C,
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ struct SpaceOutliner *soops,
+ TreeElement *te,
+ TreeStoreElem *tselem,
+ const eOLSetState set,
+ bool recursive);
+eOLDrawState tree_element_active(struct bContext *C,
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ SpaceOutliner *soops,
+ TreeElement *te,
+ const eOLSetState set,
+ const bool handle_all_types);
void outliner_item_do_activate_from_tree_element(
- struct bContext *C, TreeElement *te, TreeStoreElem *tselem,
- bool extend, bool recursive);
-int outliner_item_do_activate_from_cursor(
- struct bContext *C, const int mval[2],
- bool extend, bool recursive);
-
-void outliner_item_select(
- struct SpaceOutliner *soops, const struct TreeElement *te,
- const bool extend, const bool toggle);
-
-void outliner_object_mode_toggle(
- struct bContext *C, Scene *scene, ViewLayer *view_layer,
- Base *base);
+ struct bContext *C, TreeElement *te, TreeStoreElem *tselem, bool extend, bool recursive);
+int outliner_item_do_activate_from_cursor(struct bContext *C,
+ const int mval[2],
+ bool extend,
+ bool recursive);
+
+void outliner_item_select(struct SpaceOutliner *soops,
+ const struct TreeElement *te,
+ const bool extend,
+ const bool toggle);
+
+void outliner_object_mode_toggle(struct bContext *C,
+ Scene *scene,
+ ViewLayer *view_layer,
+ Base *base);
/* outliner_edit.c ---------------------------------------------- */
-typedef void (*outliner_operation_cb)(
- struct bContext *C, struct ReportList *, struct Scene *scene,
- struct TreeElement *, struct TreeStoreElem *, TreeStoreElem *, void *);
-
-void outliner_do_object_operation_ex(
- struct bContext *C, struct ReportList *reports, struct Scene *scene, struct SpaceOutliner *soops,
- struct ListBase *lb, outliner_operation_cb operation_cb, void *user_data, bool recurse_selected);
-void outliner_do_object_operation(
- struct bContext *C, struct ReportList *reports, struct Scene *scene, struct SpaceOutliner *soops,
- struct ListBase *lb, outliner_operation_cb operation_cb);
+typedef void (*outliner_operation_cb)(struct bContext *C,
+ struct ReportList *,
+ struct Scene *scene,
+ struct TreeElement *,
+ struct TreeStoreElem *,
+ TreeStoreElem *,
+ void *);
+
+void outliner_do_object_operation_ex(struct bContext *C,
+ struct ReportList *reports,
+ struct Scene *scene,
+ struct SpaceOutliner *soops,
+ struct ListBase *lb,
+ outliner_operation_cb operation_cb,
+ void *user_data,
+ bool recurse_selected);
+void outliner_do_object_operation(struct bContext *C,
+ struct ReportList *reports,
+ struct Scene *scene,
+ struct SpaceOutliner *soops,
+ struct ListBase *lb,
+ outliner_operation_cb operation_cb);
int common_restrict_check(struct bContext *C, struct Object *ob);
@@ -222,29 +280,57 @@ int outliner_flag_is_any_test(ListBase *lb, short flag, const int curlevel);
bool outliner_flag_set(ListBase *lb, short flag, short set);
bool outliner_flag_flip(ListBase *lb, short flag);
-void item_rename_cb(
- struct bContext *C, struct ReportList *reports, struct Scene *scene,
- TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
-void lib_relocate_cb(
- struct bContext *C, struct ReportList *reports, struct Scene *scene, struct TreeElement *te,
- struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
-void lib_reload_cb(
- struct bContext *C, struct ReportList *reports, struct Scene *scene, struct TreeElement *te,
- struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
-
-void id_delete_cb(
- struct bContext *C, struct ReportList *reports, struct Scene *scene, struct TreeElement *te,
- struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
-void id_remap_cb(
- struct bContext *C, struct ReportList *reports, struct Scene *scene, struct TreeElement *te,
- struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
-
-void item_object_mode_enter_cb(
- struct bContext *C, struct ReportList *reports, struct Scene *scene,
- TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
-void item_object_mode_exit_cb(
- struct bContext *C, struct ReportList *reports, struct Scene *scene,
- TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
+void item_rename_cb(struct bContext *C,
+ struct ReportList *reports,
+ struct Scene *scene,
+ TreeElement *te,
+ struct TreeStoreElem *tsep,
+ struct TreeStoreElem *tselem,
+ void *user_data);
+void lib_relocate_cb(struct bContext *C,
+ struct ReportList *reports,
+ struct Scene *scene,
+ struct TreeElement *te,
+ struct TreeStoreElem *tsep,
+ struct TreeStoreElem *tselem,
+ void *user_data);
+void lib_reload_cb(struct bContext *C,
+ struct ReportList *reports,
+ struct Scene *scene,
+ struct TreeElement *te,
+ struct TreeStoreElem *tsep,
+ struct TreeStoreElem *tselem,
+ void *user_data);
+
+void id_delete_cb(struct bContext *C,
+ struct ReportList *reports,
+ struct Scene *scene,
+ struct TreeElement *te,
+ struct TreeStoreElem *tsep,
+ struct TreeStoreElem *tselem,
+ void *user_data);
+void id_remap_cb(struct bContext *C,
+ struct ReportList *reports,
+ struct Scene *scene,
+ struct TreeElement *te,
+ struct TreeStoreElem *tsep,
+ struct TreeStoreElem *tselem,
+ void *user_data);
+
+void item_object_mode_enter_cb(struct bContext *C,
+ struct ReportList *reports,
+ struct Scene *scene,
+ TreeElement *te,
+ struct TreeStoreElem *tsep,
+ struct TreeStoreElem *tselem,
+ void *user_data);
+void item_object_mode_exit_cb(struct bContext *C,
+ struct ReportList *reports,
+ struct Scene *scene,
+ TreeElement *te,
+ struct TreeStoreElem *tsep,
+ struct TreeStoreElem *tselem,
+ void *user_data);
void outliner_set_coordinates(struct ARegion *ar, struct SpaceOutliner *soops);
@@ -345,17 +431,26 @@ void OUTLINER_OT_unhide_all(struct wmOperatorType *ot);
/* outliner_utils.c ---------------------------------------------- */
-TreeElement *outliner_find_item_at_y(const SpaceOutliner *soops, const ListBase *tree, float view_co_y);
-TreeElement *outliner_find_item_at_x_in_row(const SpaceOutliner *soops, const TreeElement *parent_te, float view_co_x);
+TreeElement *outliner_find_item_at_y(const SpaceOutliner *soops,
+ const ListBase *tree,
+ float view_co_y);
+TreeElement *outliner_find_item_at_x_in_row(const SpaceOutliner *soops,
+ const TreeElement *parent_te,
+ float view_co_x);
TreeElement *outliner_find_tse(struct SpaceOutliner *soops, const TreeStoreElem *tse);
TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem);
-TreeElement *outliner_find_parent_element(ListBase *lb, TreeElement *parent_te, const TreeElement *child_te);
+TreeElement *outliner_find_parent_element(ListBase *lb,
+ TreeElement *parent_te,
+ const TreeElement *child_te);
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);
-bool outliner_tree_traverse(const SpaceOutliner *soops, ListBase *tree, int filter_te_flag, int filter_tselem_flag,
- TreeTraversalFunc func, void *customdata);
-
+bool outliner_tree_traverse(const SpaceOutliner *soops,
+ ListBase *tree,
+ int filter_te_flag,
+ int filter_tselem_flag,
+ TreeTraversalFunc func,
+ void *customdata);
#endif /* __OUTLINER_INTERN_H__ */
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index c14a5eace91..f155a2d5f89 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -23,12 +23,10 @@
#include "MEM_guardedalloc.h"
-
#include "DNA_collection_types.h"
#include "BLT_translation.h"
-
#include "GPU_immediate.h"
#include "GPU_state.h"
@@ -49,80 +47,80 @@
void outliner_operatortypes(void)
{
- WM_operatortype_append(OUTLINER_OT_highlight_update);
- WM_operatortype_append(OUTLINER_OT_item_activate);
- WM_operatortype_append(OUTLINER_OT_select_box);
- WM_operatortype_append(OUTLINER_OT_item_openclose);
- WM_operatortype_append(OUTLINER_OT_item_rename);
- WM_operatortype_append(OUTLINER_OT_item_drag_drop);
- WM_operatortype_append(OUTLINER_OT_operation);
- WM_operatortype_append(OUTLINER_OT_scene_operation);
- WM_operatortype_append(OUTLINER_OT_object_operation);
- WM_operatortype_append(OUTLINER_OT_lib_operation);
- WM_operatortype_append(OUTLINER_OT_lib_relocate);
- WM_operatortype_append(OUTLINER_OT_id_operation);
- WM_operatortype_append(OUTLINER_OT_id_delete);
- WM_operatortype_append(OUTLINER_OT_id_remap);
- WM_operatortype_append(OUTLINER_OT_id_copy);
- WM_operatortype_append(OUTLINER_OT_id_paste);
- WM_operatortype_append(OUTLINER_OT_data_operation);
- WM_operatortype_append(OUTLINER_OT_animdata_operation);
- 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_show_one_level);
- WM_operatortype_append(OUTLINER_OT_show_active);
- WM_operatortype_append(OUTLINER_OT_show_hierarchy);
- WM_operatortype_append(OUTLINER_OT_scroll_page);
-
- WM_operatortype_append(OUTLINER_OT_select_all);
- WM_operatortype_append(OUTLINER_OT_expanded_toggle);
-
- WM_operatortype_append(OUTLINER_OT_keyingset_add_selected);
- WM_operatortype_append(OUTLINER_OT_keyingset_remove_selected);
-
- WM_operatortype_append(OUTLINER_OT_drivers_add_selected);
- WM_operatortype_append(OUTLINER_OT_drivers_delete_selected);
-
- WM_operatortype_append(OUTLINER_OT_orphans_purge);
-
- WM_operatortype_append(OUTLINER_OT_parent_drop);
- WM_operatortype_append(OUTLINER_OT_parent_clear);
- WM_operatortype_append(OUTLINER_OT_scene_drop);
- WM_operatortype_append(OUTLINER_OT_material_drop);
- WM_operatortype_append(OUTLINER_OT_collection_drop);
-
- /* collections */
- 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_objects_select);
- WM_operatortype_append(OUTLINER_OT_collection_objects_deselect);
- WM_operatortype_append(OUTLINER_OT_collection_link);
- WM_operatortype_append(OUTLINER_OT_collection_instance);
- WM_operatortype_append(OUTLINER_OT_collection_exclude_set);
- WM_operatortype_append(OUTLINER_OT_collection_exclude_clear);
- WM_operatortype_append(OUTLINER_OT_collection_holdout_set);
- WM_operatortype_append(OUTLINER_OT_collection_holdout_clear);
- WM_operatortype_append(OUTLINER_OT_collection_indirect_only_set);
- WM_operatortype_append(OUTLINER_OT_collection_indirect_only_clear);
-
- WM_operatortype_append(OUTLINER_OT_collection_isolate);
- WM_operatortype_append(OUTLINER_OT_collection_disable);
- WM_operatortype_append(OUTLINER_OT_collection_enable);
- WM_operatortype_append(OUTLINER_OT_collection_hide);
- WM_operatortype_append(OUTLINER_OT_collection_show);
- WM_operatortype_append(OUTLINER_OT_collection_disable_render);
- WM_operatortype_append(OUTLINER_OT_collection_enable_render);
- WM_operatortype_append(OUTLINER_OT_collection_hide_inside);
- WM_operatortype_append(OUTLINER_OT_collection_show_inside);
- WM_operatortype_append(OUTLINER_OT_hide);
- WM_operatortype_append(OUTLINER_OT_unhide_all);
+ WM_operatortype_append(OUTLINER_OT_highlight_update);
+ WM_operatortype_append(OUTLINER_OT_item_activate);
+ WM_operatortype_append(OUTLINER_OT_select_box);
+ WM_operatortype_append(OUTLINER_OT_item_openclose);
+ WM_operatortype_append(OUTLINER_OT_item_rename);
+ WM_operatortype_append(OUTLINER_OT_item_drag_drop);
+ WM_operatortype_append(OUTLINER_OT_operation);
+ WM_operatortype_append(OUTLINER_OT_scene_operation);
+ WM_operatortype_append(OUTLINER_OT_object_operation);
+ WM_operatortype_append(OUTLINER_OT_lib_operation);
+ WM_operatortype_append(OUTLINER_OT_lib_relocate);
+ WM_operatortype_append(OUTLINER_OT_id_operation);
+ WM_operatortype_append(OUTLINER_OT_id_delete);
+ WM_operatortype_append(OUTLINER_OT_id_remap);
+ WM_operatortype_append(OUTLINER_OT_id_copy);
+ WM_operatortype_append(OUTLINER_OT_id_paste);
+ WM_operatortype_append(OUTLINER_OT_data_operation);
+ WM_operatortype_append(OUTLINER_OT_animdata_operation);
+ 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_show_one_level);
+ WM_operatortype_append(OUTLINER_OT_show_active);
+ WM_operatortype_append(OUTLINER_OT_show_hierarchy);
+ WM_operatortype_append(OUTLINER_OT_scroll_page);
+
+ WM_operatortype_append(OUTLINER_OT_select_all);
+ WM_operatortype_append(OUTLINER_OT_expanded_toggle);
+
+ WM_operatortype_append(OUTLINER_OT_keyingset_add_selected);
+ WM_operatortype_append(OUTLINER_OT_keyingset_remove_selected);
+
+ WM_operatortype_append(OUTLINER_OT_drivers_add_selected);
+ WM_operatortype_append(OUTLINER_OT_drivers_delete_selected);
+
+ WM_operatortype_append(OUTLINER_OT_orphans_purge);
+
+ WM_operatortype_append(OUTLINER_OT_parent_drop);
+ WM_operatortype_append(OUTLINER_OT_parent_clear);
+ WM_operatortype_append(OUTLINER_OT_scene_drop);
+ WM_operatortype_append(OUTLINER_OT_material_drop);
+ WM_operatortype_append(OUTLINER_OT_collection_drop);
+
+ /* collections */
+ 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_objects_select);
+ WM_operatortype_append(OUTLINER_OT_collection_objects_deselect);
+ WM_operatortype_append(OUTLINER_OT_collection_link);
+ WM_operatortype_append(OUTLINER_OT_collection_instance);
+ WM_operatortype_append(OUTLINER_OT_collection_exclude_set);
+ WM_operatortype_append(OUTLINER_OT_collection_exclude_clear);
+ WM_operatortype_append(OUTLINER_OT_collection_holdout_set);
+ WM_operatortype_append(OUTLINER_OT_collection_holdout_clear);
+ WM_operatortype_append(OUTLINER_OT_collection_indirect_only_set);
+ WM_operatortype_append(OUTLINER_OT_collection_indirect_only_clear);
+
+ WM_operatortype_append(OUTLINER_OT_collection_isolate);
+ WM_operatortype_append(OUTLINER_OT_collection_disable);
+ WM_operatortype_append(OUTLINER_OT_collection_enable);
+ WM_operatortype_append(OUTLINER_OT_collection_hide);
+ WM_operatortype_append(OUTLINER_OT_collection_show);
+ WM_operatortype_append(OUTLINER_OT_collection_disable_render);
+ WM_operatortype_append(OUTLINER_OT_collection_enable_render);
+ WM_operatortype_append(OUTLINER_OT_collection_hide_inside);
+ WM_operatortype_append(OUTLINER_OT_collection_show_inside);
+ WM_operatortype_append(OUTLINER_OT_hide);
+ WM_operatortype_append(OUTLINER_OT_unhide_all);
}
void outliner_keymap(wmKeyConfig *keyconf)
{
- WM_keymap_ensure(keyconf, "Outliner", SPACE_OUTLINER, 0);
+ WM_keymap_ensure(keyconf, "Outliner", SPACE_OUTLINER, 0);
}
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 9866b43a6a6..bab5ee02916 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -63,7 +63,6 @@
#include "WM_api.h"
#include "WM_types.h"
-
#include "UI_interface.h"
#include "UI_view2d.h"
@@ -72,38 +71,36 @@
#include "outliner_intern.h"
-static bool do_outliner_activate_common(
- bContext *C,
- Main *bmain,
- Depsgraph *depsgraph,
- Scene *scene,
- ViewLayer *view_layer,
- Base *base,
- const bool extend,
- const bool do_exit)
+static bool do_outliner_activate_common(bContext *C,
+ Main *bmain,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ ViewLayer *view_layer,
+ Base *base,
+ const bool extend,
+ const bool do_exit)
{
- bool use_all = false;
-
- if (do_exit) {
- FOREACH_OBJECT_BEGIN(view_layer, ob_iter)
- {
- ED_object_mode_generic_exit(bmain, depsgraph, scene, ob_iter);
- }
- FOREACH_OBJECT_END;
- }
-
- /* Just like clicking in the object changes the active object,
- * clicking on the object data should change it as well. */
- ED_object_base_activate(C, base);
-
- if (extend) {
- use_all = true;
- }
- else {
- ED_object_base_deselect_all(view_layer, NULL, SEL_DESELECT);
- }
-
- return use_all;
+ bool use_all = false;
+
+ if (do_exit) {
+ FOREACH_OBJECT_BEGIN (view_layer, ob_iter) {
+ ED_object_mode_generic_exit(bmain, depsgraph, scene, ob_iter);
+ }
+ FOREACH_OBJECT_END;
+ }
+
+ /* Just like clicking in the object changes the active object,
+ * clicking on the object data should change it as well. */
+ ED_object_base_activate(C, base);
+
+ if (extend) {
+ use_all = true;
+ }
+ else {
+ ED_object_base_deselect_all(view_layer, NULL, SEL_DESELECT);
+ }
+
+ return use_all;
}
/**
@@ -112,142 +109,145 @@ static bool do_outliner_activate_common(
* If extend is used, we try to have the other compatible selected objects in the new mode as well.
* Otherwise only the new object will be active, selected and in the edit mode.
*/
-static void do_outliner_activate_obdata(bContext *C, Scene *scene, ViewLayer *view_layer, Base *base, const bool extend)
+static void do_outliner_activate_obdata(
+ bContext *C, Scene *scene, ViewLayer *view_layer, Base *base, const bool extend)
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *obact = OBACT(view_layer);
- Object *ob = base->object;
- bool use_all = false;
-
- if (obact == NULL) {
- ED_object_base_activate(C, base);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- obact = ob;
- use_all = true;
- }
- else if (obact->data == ob->data) {
- use_all = true;
- }
- else if (obact->mode == OB_MODE_OBJECT) {
- use_all = do_outliner_activate_common(C, bmain, depsgraph, scene, view_layer, base, extend, false);
- }
- else if ((ob->type != obact->type) ||
- ((obact->mode & OB_MODE_EDIT) == 0) ||
- ((obact->mode & OB_MODE_POSE) && ELEM(OB_ARMATURE, ob->type, obact->type)) ||
- !extend)
- {
- use_all = do_outliner_activate_common(C, bmain, depsgraph, scene, view_layer, base, extend, true);
- }
-
- if (use_all) {
- WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
- }
- else {
- bool ok;
- if (BKE_object_is_in_editmode(ob)) {
- ok = ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
- }
- else {
- ok = ED_object_editmode_enter_ex(CTX_data_main(C), scene, ob, EM_NO_CONTEXT);
- }
- if (ok) {
- ED_object_base_select(base, (ob->mode & OB_MODE_EDIT) ? BA_SELECT : BA_DESELECT);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
- }
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *obact = OBACT(view_layer);
+ Object *ob = base->object;
+ bool use_all = false;
+
+ if (obact == NULL) {
+ ED_object_base_activate(C, base);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ obact = ob;
+ use_all = true;
+ }
+ else if (obact->data == ob->data) {
+ use_all = true;
+ }
+ else if (obact->mode == OB_MODE_OBJECT) {
+ use_all = do_outliner_activate_common(
+ C, bmain, depsgraph, scene, view_layer, base, extend, false);
+ }
+ else if ((ob->type != obact->type) || ((obact->mode & OB_MODE_EDIT) == 0) ||
+ ((obact->mode & OB_MODE_POSE) && ELEM(OB_ARMATURE, ob->type, obact->type)) || !extend) {
+ use_all = do_outliner_activate_common(
+ C, bmain, depsgraph, scene, view_layer, base, extend, true);
+ }
+
+ if (use_all) {
+ WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
+ }
+ else {
+ bool ok;
+ if (BKE_object_is_in_editmode(ob)) {
+ ok = ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
+ }
+ else {
+ ok = ED_object_editmode_enter_ex(CTX_data_main(C), scene, ob, EM_NO_CONTEXT);
+ }
+ if (ok) {
+ ED_object_base_select(base, (ob->mode & OB_MODE_EDIT) ? BA_SELECT : BA_DESELECT);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ }
+ }
}
-static void do_outliner_activate_pose(bContext *C, Scene *scene, ViewLayer *view_layer, Base *base, const bool extend)
+static void do_outliner_activate_pose(
+ bContext *C, Scene *scene, ViewLayer *view_layer, Base *base, const bool extend)
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *obact = OBACT(view_layer);
- Object *ob = base->object;
- bool use_all = false;
-
- if (obact == NULL) {
- ED_object_base_activate(C, base);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- obact = ob;
- use_all = true;
- }
- else if (obact->data == ob->data) {
- use_all = true;
- }
- else if (obact->mode == OB_MODE_OBJECT) {
- use_all = do_outliner_activate_common(C, bmain, depsgraph, scene, view_layer, base, extend, false);
- }
- else if ((!ELEM(ob->type, obact->type)) ||
- ((obact->mode & OB_MODE_EDIT) && ELEM(OB_ARMATURE, ob->type, obact->type)))
- {
- use_all = do_outliner_activate_common(C, bmain, depsgraph, scene, view_layer, base, extend, true);
- }
-
- if (use_all) {
- WM_operator_name_call(C, "OBJECT_OT_posemode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
- }
- else {
- bool ok = false;
- if (ob->mode & OB_MODE_POSE) {
- ok = ED_object_posemode_exit_ex(bmain, ob);
- }
- else {
- ok = ED_object_posemode_enter_ex(bmain, ob);
- }
- if (ok) {
- ED_object_base_select(base, (ob->mode & OB_MODE_POSE) ? BA_SELECT : BA_DESELECT);
-
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
- }
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *obact = OBACT(view_layer);
+ Object *ob = base->object;
+ bool use_all = false;
+
+ if (obact == NULL) {
+ ED_object_base_activate(C, base);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ obact = ob;
+ use_all = true;
+ }
+ else if (obact->data == ob->data) {
+ use_all = true;
+ }
+ else if (obact->mode == OB_MODE_OBJECT) {
+ use_all = do_outliner_activate_common(
+ C, bmain, depsgraph, scene, view_layer, base, extend, false);
+ }
+ else if ((!ELEM(ob->type, obact->type)) ||
+ ((obact->mode & OB_MODE_EDIT) && ELEM(OB_ARMATURE, ob->type, obact->type))) {
+ use_all = do_outliner_activate_common(
+ C, bmain, depsgraph, scene, view_layer, base, extend, true);
+ }
+
+ if (use_all) {
+ WM_operator_name_call(C, "OBJECT_OT_posemode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
+ }
+ else {
+ bool ok = false;
+ if (ob->mode & OB_MODE_POSE) {
+ ok = ED_object_posemode_exit_ex(bmain, ob);
+ }
+ else {
+ ok = ED_object_posemode_enter_ex(bmain, ob);
+ }
+ if (ok) {
+ ED_object_base_select(base, (ob->mode & OB_MODE_POSE) ? BA_SELECT : BA_DESELECT);
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ }
+ }
}
/* For draw callback to run mode switching */
-void outliner_object_mode_toggle(
- bContext *C, Scene *scene, ViewLayer *view_layer,
- Base *base)
+void outliner_object_mode_toggle(bContext *C, Scene *scene, ViewLayer *view_layer, Base *base)
{
- Object *obact = OBACT(view_layer);
- if (obact->mode & OB_MODE_EDIT) {
- do_outliner_activate_obdata(C, scene, view_layer, base, true);
- }
- else if (obact->mode & OB_MODE_POSE) {
- do_outliner_activate_pose(C, scene, view_layer, base, true);
- }
+ Object *obact = OBACT(view_layer);
+ if (obact->mode & OB_MODE_EDIT) {
+ do_outliner_activate_obdata(C, scene, view_layer, base, true);
+ }
+ else if (obact->mode & OB_MODE_POSE) {
+ do_outliner_activate_pose(C, scene, view_layer, base, true);
+ }
}
/* ****************************************************** */
/* Outliner Element Selection/Activation on Click */
-static eOLDrawState active_viewlayer(
- bContext *C, Scene *UNUSED(scene), ViewLayer *UNUSED(sl), TreeElement *te, const eOLSetState set)
+static eOLDrawState active_viewlayer(bContext *C,
+ Scene *UNUSED(scene),
+ ViewLayer *UNUSED(sl),
+ TreeElement *te,
+ const eOLSetState set)
{
- /* paranoia check */
- if (te->idcode != ID_SCE) {
- return OL_DRAWSEL_NONE;
- }
-
- ViewLayer *view_layer = te->directdata;
-
- if (set != OL_SETSEL_NONE) {
- wmWindow *win = CTX_wm_window(C);
- Scene *scene = WM_window_get_active_scene(win);
-
- if (BLI_findindex(&scene->view_layers, view_layer) != -1) {
- WM_window_set_active_view_layer(win, view_layer);
- WM_event_add_notifier(C, NC_SCREEN | ND_LAYER, NULL);
- }
- }
- else {
- return CTX_data_view_layer(C) == view_layer;
- }
- return OL_DRAWSEL_NONE;
+ /* paranoia check */
+ if (te->idcode != ID_SCE) {
+ return OL_DRAWSEL_NONE;
+ }
+
+ ViewLayer *view_layer = te->directdata;
+
+ if (set != OL_SETSEL_NONE) {
+ wmWindow *win = CTX_wm_window(C);
+ Scene *scene = WM_window_get_active_scene(win);
+
+ if (BLI_findindex(&scene->view_layers, view_layer) != -1) {
+ WM_window_set_active_view_layer(win, view_layer);
+ WM_event_add_notifier(C, NC_SCREEN | ND_LAYER, NULL);
+ }
+ }
+ else {
+ return CTX_data_view_layer(C) == view_layer;
+ }
+ return OL_DRAWSEL_NONE;
}
/**
@@ -255,772 +255,856 @@ static eOLDrawState active_viewlayer(
* CTRL+LMB: Select/Deselect object and all children.
* CTRL+SHIFT+LMB: Add/Remove object and all children.
*/
-static void do_outliner_object_select_recursive(ViewLayer *view_layer, Object *ob_parent, bool select)
+static void do_outliner_object_select_recursive(ViewLayer *view_layer,
+ Object *ob_parent,
+ bool select)
{
- Base *base;
-
- for (base = FIRSTBASE(view_layer); base; base = base->next) {
- Object *ob = base->object;
- if ((((base->flag & BASE_VISIBLE) != 0) && BKE_object_is_child_recursive(ob_parent, ob))) {
- ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
- }
- }
+ Base *base;
+
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
+ Object *ob = base->object;
+ if ((((base->flag & BASE_VISIBLE) != 0) && BKE_object_is_child_recursive(ob_parent, ob))) {
+ ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
+ }
+ }
}
static void do_outliner_bone_select_recursive(bArmature *arm, Bone *bone_parent, bool select)
{
- Bone *bone;
- for (bone = bone_parent->childbase.first; bone; bone = bone->next) {
- if (select && PBONE_SELECTABLE(arm, bone)) {
- bone->flag |= BONE_SELECTED;
- }
- else {
- bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
- }
- do_outliner_bone_select_recursive(arm, bone, select);
- }
+ Bone *bone;
+ for (bone = bone_parent->childbase.first; bone; bone = bone->next) {
+ if (select && PBONE_SELECTABLE(arm, bone)) {
+ bone->flag |= BONE_SELECTED;
+ }
+ else {
+ bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ }
+ do_outliner_bone_select_recursive(arm, bone, select);
+ }
}
static void do_outliner_ebone_select_recursive(bArmature *arm, EditBone *ebone_parent, bool select)
{
- EditBone *ebone;
- for (ebone = ebone_parent->next; ebone; ebone = ebone->next) {
- if (ED_armature_ebone_is_child_recursive(ebone_parent, ebone)) {
- if (select && EBONE_SELECTABLE(arm, ebone)) {
- ebone->flag |= BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL;
- }
- else {
- ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
- }
- }
- }
+ EditBone *ebone;
+ for (ebone = ebone_parent->next; ebone; ebone = ebone->next) {
+ if (ED_armature_ebone_is_child_recursive(ebone_parent, ebone)) {
+ if (select && EBONE_SELECTABLE(arm, ebone)) {
+ ebone->flag |= BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL;
+ }
+ else {
+ ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ }
+ }
+ }
}
-static eOLDrawState tree_element_set_active_object(
- bContext *C, Scene *scene, ViewLayer *view_layer, SpaceOutliner *soops,
- TreeElement *te, const eOLSetState set, bool recursive)
+static eOLDrawState tree_element_set_active_object(bContext *C,
+ Scene *scene,
+ ViewLayer *view_layer,
+ SpaceOutliner *soops,
+ TreeElement *te,
+ const eOLSetState set,
+ bool recursive)
{
- TreeStoreElem *tselem = TREESTORE(te);
- Scene *sce;
- Base *base;
- Object *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)) {
- return OL_DRAWSEL_NONE;
- }
- }
- if (ob == NULL) {
- return OL_DRAWSEL_NONE;
- }
-
- sce = (Scene *)outliner_search_back(soops, te, ID_SCE);
- if (sce && scene != sce) {
- WM_window_set_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce);
- scene = sce;
- }
-
- /* find associated base in current scene */
- base = BKE_view_layer_base_find(view_layer, ob);
-
- if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
- if (base != NULL) {
- Object *obact = OBACT(view_layer);
- const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT;
- if (base && !BKE_object_is_mode_compat(base->object, object_mode)) {
- if (object_mode == OB_MODE_OBJECT) {
- struct Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ED_object_mode_generic_exit(bmain, depsgraph, scene, base->object);
- }
- if (!BKE_object_is_mode_compat(base->object, object_mode)) {
- base = NULL;
- }
- }
- }
- }
-
- if (base) {
- if (set == OL_SETSEL_EXTEND) {
- /* swap select */
- if (base->flag & BASE_SELECTED) {
- ED_object_base_select(base, BA_DESELECT);
- }
- else {
- ED_object_base_select(base, BA_SELECT);
- }
- }
- else {
- /* deleselect all */
-
- /* Only in object mode so we can switch the active object,
- * keeping all objects in the current 'mode' selected, useful for multi-pose/edit mode.
- * This keeps the convention that all objects in the current mode are also selected.
- * see T55246. */
- if ((scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ? (ob->mode == OB_MODE_OBJECT) : true) {
- BKE_view_layer_base_deselect_all(view_layer);
- }
- ED_object_base_select(base, BA_SELECT);
- }
-
- if (recursive) {
- /* Recursive select/deselect for Object hierarchies */
- do_outliner_object_select_recursive(view_layer, ob, (base->flag & BASE_SELECTED) != 0);
- }
-
- if (set != OL_SETSEL_NONE) {
- ED_object_base_activate(C, base); /* adds notifier */
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
-
- if (ob != OBEDIT_FROM_VIEW_LAYER(view_layer)) {
- ED_object_editmode_exit(C, EM_FREEDATA);
- }
- }
- return OL_DRAWSEL_NORMAL;
+ TreeStoreElem *tselem = TREESTORE(te);
+ Scene *sce;
+ Base *base;
+ Object *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)) {
+ return OL_DRAWSEL_NONE;
+ }
+ }
+ if (ob == NULL) {
+ return OL_DRAWSEL_NONE;
+ }
+
+ sce = (Scene *)outliner_search_back(soops, te, ID_SCE);
+ if (sce && scene != sce) {
+ WM_window_set_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce);
+ scene = sce;
+ }
+
+ /* find associated base in current scene */
+ base = BKE_view_layer_base_find(view_layer, ob);
+
+ if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ if (base != NULL) {
+ Object *obact = OBACT(view_layer);
+ const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT;
+ if (base && !BKE_object_is_mode_compat(base->object, object_mode)) {
+ if (object_mode == OB_MODE_OBJECT) {
+ struct Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ED_object_mode_generic_exit(bmain, depsgraph, scene, base->object);
+ }
+ if (!BKE_object_is_mode_compat(base->object, object_mode)) {
+ base = NULL;
+ }
+ }
+ }
+ }
+
+ if (base) {
+ if (set == OL_SETSEL_EXTEND) {
+ /* swap select */
+ if (base->flag & BASE_SELECTED) {
+ ED_object_base_select(base, BA_DESELECT);
+ }
+ else {
+ ED_object_base_select(base, BA_SELECT);
+ }
+ }
+ else {
+ /* deleselect all */
+
+ /* Only in object mode so we can switch the active object,
+ * keeping all objects in the current 'mode' selected, useful for multi-pose/edit mode.
+ * This keeps the convention that all objects in the current mode are also selected.
+ * see T55246. */
+ if ((scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ?
+ (ob->mode == OB_MODE_OBJECT) :
+ true) {
+ BKE_view_layer_base_deselect_all(view_layer);
+ }
+ ED_object_base_select(base, BA_SELECT);
+ }
+
+ if (recursive) {
+ /* Recursive select/deselect for Object hierarchies */
+ do_outliner_object_select_recursive(view_layer, ob, (base->flag & BASE_SELECTED) != 0);
+ }
+
+ if (set != OL_SETSEL_NONE) {
+ ED_object_base_activate(C, base); /* adds notifier */
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ }
+
+ if (ob != OBEDIT_FROM_VIEW_LAYER(view_layer)) {
+ ED_object_editmode_exit(C, EM_FREEDATA);
+ }
+ }
+ return OL_DRAWSEL_NORMAL;
}
-static eOLDrawState tree_element_active_material(
- bContext *C, Scene *UNUSED(scene), ViewLayer *view_layer, SpaceOutliner *soops,
- TreeElement *te, const eOLSetState set)
+static eOLDrawState tree_element_active_material(bContext *C,
+ Scene *UNUSED(scene),
+ ViewLayer *view_layer,
+ SpaceOutliner *soops,
+ TreeElement *te,
+ const eOLSetState set)
{
- TreeElement *tes;
- Object *ob;
-
- /* we search for the object parent */
- ob = (Object *)outliner_search_back(soops, 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 */
- }
-
- /* searching in ob mat array? */
- tes = te->parent;
- if (tes->idcode == ID_OB) {
- if (set != OL_SETSEL_NONE) {
- ob->actcol = te->index + 1;
- ob->matbits[te->index] = 1; // make ob material active too
- }
- else {
- if (ob->actcol == te->index + 1) {
- if (ob->matbits[te->index]) {
- return OL_DRAWSEL_NORMAL;
- }
- }
- }
- }
- /* or we search for obdata material */
- else {
- if (set != OL_SETSEL_NONE) {
- ob->actcol = te->index + 1;
- ob->matbits[te->index] = 0; // make obdata material active too
- }
- else {
- if (ob->actcol == te->index + 1) {
- if (ob->matbits[te->index] == 0) {
- return OL_DRAWSEL_NORMAL;
- }
- }
- }
- }
- if (set != OL_SETSEL_NONE) {
- /* Tagging object for update seems a bit stupid here, but looks like we have to do it
- * for render views to update. See T42973.
- * Note that RNA material update does it too, see e.g. rna_MaterialSlot_update(). */
- DEG_id_tag_update((ID *)ob, ID_RECALC_TRANSFORM);
- WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL);
- }
- return OL_DRAWSEL_NONE;
+ TreeElement *tes;
+ Object *ob;
+
+ /* we search for the object parent */
+ ob = (Object *)outliner_search_back(soops, 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 */
+ }
+
+ /* searching in ob mat array? */
+ tes = te->parent;
+ if (tes->idcode == ID_OB) {
+ if (set != OL_SETSEL_NONE) {
+ ob->actcol = te->index + 1;
+ ob->matbits[te->index] = 1; // make ob material active too
+ }
+ else {
+ if (ob->actcol == te->index + 1) {
+ if (ob->matbits[te->index]) {
+ return OL_DRAWSEL_NORMAL;
+ }
+ }
+ }
+ }
+ /* or we search for obdata material */
+ else {
+ if (set != OL_SETSEL_NONE) {
+ ob->actcol = te->index + 1;
+ ob->matbits[te->index] = 0; // make obdata material active too
+ }
+ else {
+ if (ob->actcol == te->index + 1) {
+ if (ob->matbits[te->index] == 0) {
+ return OL_DRAWSEL_NORMAL;
+ }
+ }
+ }
+ }
+ if (set != OL_SETSEL_NONE) {
+ /* Tagging object for update seems a bit stupid here, but looks like we have to do it
+ * for render views to update. See T42973.
+ * Note that RNA material update does it too, see e.g. rna_MaterialSlot_update(). */
+ DEG_id_tag_update((ID *)ob, ID_RECALC_TRANSFORM);
+ WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL);
+ }
+ return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_light(
- bContext *UNUSED(C), Scene *UNUSED(scene), ViewLayer *view_layer, SpaceOutliner *soops,
- TreeElement *te, const eOLSetState set)
+static eOLDrawState tree_element_active_light(bContext *UNUSED(C),
+ Scene *UNUSED(scene),
+ ViewLayer *view_layer,
+ SpaceOutliner *soops,
+ TreeElement *te,
+ const eOLSetState set)
{
- Object *ob;
-
- /* we search for the object parent */
- ob = (Object *)outliner_search_back(soops, te, ID_OB);
- if (ob == NULL || ob != OBACT(view_layer)) {
- /* just paranoia */
- return OL_DRAWSEL_NONE;
- }
-
- if (set != OL_SETSEL_NONE) {
-// XXX extern_set_butspace(F5KEY, 0);
- }
- else {
- return OL_DRAWSEL_NORMAL;
- }
-
- return OL_DRAWSEL_NONE;
+ Object *ob;
+
+ /* we search for the object parent */
+ ob = (Object *)outliner_search_back(soops, te, ID_OB);
+ if (ob == NULL || ob != OBACT(view_layer)) {
+ /* just paranoia */
+ return OL_DRAWSEL_NONE;
+ }
+
+ if (set != OL_SETSEL_NONE) {
+ // XXX extern_set_butspace(F5KEY, 0);
+ }
+ else {
+ return OL_DRAWSEL_NORMAL;
+ }
+
+ return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_camera(
- bContext *UNUSED(C), Scene *scene, ViewLayer *UNUSED(sl), SpaceOutliner *soops,
- TreeElement *te, const eOLSetState set)
+static eOLDrawState tree_element_active_camera(bContext *UNUSED(C),
+ Scene *scene,
+ ViewLayer *UNUSED(sl),
+ SpaceOutliner *soops,
+ TreeElement *te,
+ const eOLSetState set)
{
- Object *ob = (Object *)outliner_search_back(soops, te, ID_OB);
+ Object *ob = (Object *)outliner_search_back(soops, te, ID_OB);
- if (set != OL_SETSEL_NONE) {
- return OL_DRAWSEL_NONE;
- }
+ if (set != OL_SETSEL_NONE) {
+ return OL_DRAWSEL_NONE;
+ }
- return scene->camera == ob;
+ return scene->camera == ob;
}
-static eOLDrawState tree_element_active_world(
- bContext *C, Scene *scene, ViewLayer *UNUSED(sl), SpaceOutliner *UNUSED(soops),
- TreeElement *te, const eOLSetState set)
+static eOLDrawState tree_element_active_world(bContext *C,
+ Scene *scene,
+ ViewLayer *UNUSED(sl),
+ SpaceOutliner *UNUSED(soops),
+ TreeElement *te,
+ const eOLSetState set)
{
- TreeElement *tep;
- TreeStoreElem *tselem = NULL;
- Scene *sce = NULL;
-
- tep = te->parent;
- if (tep) {
- tselem = TREESTORE(tep);
- if (tselem->type == 0) {
- sce = (Scene *)tselem->id;
- }
- }
-
- if (set != OL_SETSEL_NONE) {
- /* make new scene active */
- if (sce && scene != sce) {
- WM_window_set_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce);
- }
- }
-
- if (tep == NULL || tselem->id == (ID *)scene) {
- if (set != OL_SETSEL_NONE) {
-// XXX extern_set_butspace(F8KEY, 0);
- }
- else {
- return OL_DRAWSEL_NORMAL;
- }
- }
- return OL_DRAWSEL_NONE;
+ TreeElement *tep;
+ TreeStoreElem *tselem = NULL;
+ Scene *sce = NULL;
+
+ tep = te->parent;
+ if (tep) {
+ tselem = TREESTORE(tep);
+ if (tselem->type == 0) {
+ sce = (Scene *)tselem->id;
+ }
+ }
+
+ if (set != OL_SETSEL_NONE) {
+ /* make new scene active */
+ if (sce && scene != sce) {
+ WM_window_set_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce);
+ }
+ }
+
+ if (tep == NULL || tselem->id == (ID *)scene) {
+ if (set != OL_SETSEL_NONE) {
+ // XXX extern_set_butspace(F8KEY, 0);
+ }
+ else {
+ return OL_DRAWSEL_NORMAL;
+ }
+ }
+ return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_defgroup(
- bContext *C, ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
+static eOLDrawState tree_element_active_defgroup(bContext *C,
+ ViewLayer *view_layer,
+ TreeElement *te,
+ TreeStoreElem *tselem,
+ const eOLSetState set)
{
- Object *ob;
-
- /* id in tselem is object */
- ob = (Object *)tselem->id;
- if (set != OL_SETSEL_NONE) {
- BLI_assert(te->index + 1 >= 0);
- ob->actdef = te->index + 1;
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
- }
- else {
- if (ob == OBACT(view_layer))
- if (ob->actdef == te->index + 1) {
- return OL_DRAWSEL_NORMAL;
- }
- }
- return OL_DRAWSEL_NONE;
+ Object *ob;
+
+ /* id in tselem is object */
+ ob = (Object *)tselem->id;
+ if (set != OL_SETSEL_NONE) {
+ BLI_assert(te->index + 1 >= 0);
+ ob->actdef = te->index + 1;
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
+ }
+ else {
+ if (ob == OBACT(view_layer))
+ if (ob->actdef == te->index + 1) {
+ return OL_DRAWSEL_NORMAL;
+ }
+ }
+ return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_gplayer(
- bContext *C, Scene *UNUSED(scene), TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
+static eOLDrawState tree_element_active_gplayer(bContext *C,
+ Scene *UNUSED(scene),
+ TreeElement *te,
+ TreeStoreElem *tselem,
+ const eOLSetState set)
{
- bGPdata *gpd = (bGPdata *)tselem->id;
- bGPDlayer *gpl = te->directdata;
-
- /* We can only have a single "active" layer at a time
- * and there must always be an active layer...
- */
- if (set != OL_SETSEL_NONE) {
- if (gpl) {
- BKE_gpencil_layer_setactive(gpd, gpl);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, gpd);
- }
- }
- else {
- return OL_DRAWSEL_NORMAL;
- }
-
- return OL_DRAWSEL_NONE;
+ bGPdata *gpd = (bGPdata *)tselem->id;
+ bGPDlayer *gpl = te->directdata;
+
+ /* We can only have a single "active" layer at a time
+ * and there must always be an active layer...
+ */
+ if (set != OL_SETSEL_NONE) {
+ if (gpl) {
+ BKE_gpencil_layer_setactive(gpd, gpl);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, gpd);
+ }
+ }
+ else {
+ return OL_DRAWSEL_NORMAL;
+ }
+
+ return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_posegroup(
- bContext *C, Scene *UNUSED(scene), ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
+static eOLDrawState tree_element_active_posegroup(bContext *C,
+ Scene *UNUSED(scene),
+ ViewLayer *view_layer,
+ TreeElement *te,
+ TreeStoreElem *tselem,
+ const eOLSetState set)
{
- Object *ob = (Object *)tselem->id;
-
- if (set != OL_SETSEL_NONE) {
- if (ob->pose) {
- ob->pose->active_group = te->index + 1;
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- }
- }
- else {
- if (ob == OBACT(view_layer) && ob->pose) {
- if (ob->pose->active_group == te->index + 1) {
- return OL_DRAWSEL_NORMAL;
- }
- }
- }
- return OL_DRAWSEL_NONE;
+ Object *ob = (Object *)tselem->id;
+
+ if (set != OL_SETSEL_NONE) {
+ if (ob->pose) {
+ ob->pose->active_group = te->index + 1;
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ }
+ else {
+ if (ob == OBACT(view_layer) && ob->pose) {
+ if (ob->pose->active_group == te->index + 1) {
+ return OL_DRAWSEL_NORMAL;
+ }
+ }
+ }
+ return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_posechannel(
- bContext *C, Scene *UNUSED(scene), ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
+static eOLDrawState tree_element_active_posechannel(bContext *C,
+ Scene *UNUSED(scene),
+ ViewLayer *view_layer,
+ TreeElement *te,
+ TreeStoreElem *tselem,
+ const eOLSetState set,
+ bool recursive)
{
- Object *ob = (Object *)tselem->id;
- bArmature *arm = ob->data;
- bPoseChannel *pchan = te->directdata;
-
- if (set != OL_SETSEL_NONE) {
- if (!(pchan->bone->flag & BONE_HIDDEN_P)) {
-
- if (set != OL_SETSEL_EXTEND) {
- /* Single select forces all other bones to get unselected. */
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(view_layer, NULL, &objects_len, OB_MODE_POSE);
- for (uint object_index = 0; object_index < objects_len; object_index++) {
- Object *ob_iter = BKE_object_pose_armature_get(objects[object_index]);
-
- /* Sanity checks. */
- if (ELEM(NULL, ob_iter, ob_iter->pose, ob_iter->data)) {
- continue;
- }
-
- bPoseChannel *pchannel;
- for (pchannel = ob_iter->pose->chanbase.first; pchannel; pchannel = pchannel->next) {
- pchannel->bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
- }
-
- if (ob != ob_iter) {
- DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
- }
- }
- MEM_freeN(objects);
- }
-
- if ((set == OL_SETSEL_EXTEND) && (pchan->bone->flag & BONE_SELECTED)) {
- pchan->bone->flag &= ~BONE_SELECTED;
- }
- else {
- pchan->bone->flag |= BONE_SELECTED;
- arm->act_bone = pchan->bone;
- }
-
- if (recursive) {
- /* Recursive select/deselect */
- do_outliner_bone_select_recursive(arm, pchan->bone, (pchan->bone->flag & BONE_SELECTED) != 0);
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, ob);
- DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
- }
- }
- else {
- if (ob == OBACT(view_layer) && ob->pose) {
- if (pchan->bone->flag & BONE_SELECTED) {
- return OL_DRAWSEL_NORMAL;
- }
- }
- }
- return OL_DRAWSEL_NONE;
+ Object *ob = (Object *)tselem->id;
+ bArmature *arm = ob->data;
+ bPoseChannel *pchan = te->directdata;
+
+ if (set != OL_SETSEL_NONE) {
+ if (!(pchan->bone->flag & BONE_HIDDEN_P)) {
+
+ if (set != OL_SETSEL_EXTEND) {
+ /* Single select forces all other bones to get unselected. */
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(
+ view_layer, NULL, &objects_len, OB_MODE_POSE);
+ for (uint object_index = 0; object_index < objects_len; object_index++) {
+ Object *ob_iter = BKE_object_pose_armature_get(objects[object_index]);
+
+ /* Sanity checks. */
+ if (ELEM(NULL, ob_iter, ob_iter->pose, ob_iter->data)) {
+ continue;
+ }
+
+ bPoseChannel *pchannel;
+ for (pchannel = ob_iter->pose->chanbase.first; pchannel; pchannel = pchannel->next) {
+ pchannel->bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ }
+
+ if (ob != ob_iter) {
+ DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
+ }
+ }
+ MEM_freeN(objects);
+ }
+
+ if ((set == OL_SETSEL_EXTEND) && (pchan->bone->flag & BONE_SELECTED)) {
+ pchan->bone->flag &= ~BONE_SELECTED;
+ }
+ else {
+ pchan->bone->flag |= BONE_SELECTED;
+ arm->act_bone = pchan->bone;
+ }
+
+ if (recursive) {
+ /* Recursive select/deselect */
+ do_outliner_bone_select_recursive(
+ arm, pchan->bone, (pchan->bone->flag & BONE_SELECTED) != 0);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, ob);
+ DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
+ }
+ }
+ else {
+ if (ob == OBACT(view_layer) && ob->pose) {
+ if (pchan->bone->flag & BONE_SELECTED) {
+ return OL_DRAWSEL_NORMAL;
+ }
+ }
+ }
+ return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_bone(
- bContext *C, ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
+static eOLDrawState tree_element_active_bone(bContext *C,
+ ViewLayer *view_layer,
+ TreeElement *te,
+ TreeStoreElem *tselem,
+ const eOLSetState set,
+ bool recursive)
{
- bArmature *arm = (bArmature *)tselem->id;
- Bone *bone = te->directdata;
-
- if (set != OL_SETSEL_NONE) {
- if (!(bone->flag & BONE_HIDDEN_P)) {
- Object *ob = OBACT(view_layer);
- if (ob) {
- if (set != OL_SETSEL_EXTEND) {
- /* single select forces all other bones to get unselected */
- for (Bone *bone_iter = arm->bonebase.first; bone_iter != NULL; bone_iter = bone_iter->next) {
- bone_iter->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
- do_outliner_bone_select_recursive(arm, bone_iter, false);
- }
- }
- }
-
- if (set == OL_SETSEL_EXTEND && (bone->flag & BONE_SELECTED)) {
- bone->flag &= ~BONE_SELECTED;
- }
- else {
- bone->flag |= BONE_SELECTED;
- arm->act_bone = bone;
- }
-
- if (recursive) {
- /* Recursive select/deselect */
- do_outliner_bone_select_recursive(arm, bone, (bone->flag & BONE_SELECTED) != 0);
- }
-
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, ob);
- }
- }
- else {
- Object *ob = OBACT(view_layer);
-
- if (ob && ob->data == arm) {
- if (bone->flag & BONE_SELECTED) {
- return OL_DRAWSEL_NORMAL;
- }
- }
- }
- return OL_DRAWSEL_NONE;
+ bArmature *arm = (bArmature *)tselem->id;
+ Bone *bone = te->directdata;
+
+ if (set != OL_SETSEL_NONE) {
+ if (!(bone->flag & BONE_HIDDEN_P)) {
+ Object *ob = OBACT(view_layer);
+ if (ob) {
+ if (set != OL_SETSEL_EXTEND) {
+ /* single select forces all other bones to get unselected */
+ for (Bone *bone_iter = arm->bonebase.first; bone_iter != NULL;
+ bone_iter = bone_iter->next) {
+ bone_iter->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ do_outliner_bone_select_recursive(arm, bone_iter, false);
+ }
+ }
+ }
+
+ if (set == OL_SETSEL_EXTEND && (bone->flag & BONE_SELECTED)) {
+ bone->flag &= ~BONE_SELECTED;
+ }
+ else {
+ bone->flag |= BONE_SELECTED;
+ arm->act_bone = bone;
+ }
+
+ if (recursive) {
+ /* Recursive select/deselect */
+ do_outliner_bone_select_recursive(arm, bone, (bone->flag & BONE_SELECTED) != 0);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, ob);
+ }
+ }
+ else {
+ Object *ob = OBACT(view_layer);
+
+ if (ob && ob->data == arm) {
+ if (bone->flag & BONE_SELECTED) {
+ return OL_DRAWSEL_NORMAL;
+ }
+ }
+ }
+ return OL_DRAWSEL_NONE;
}
-
/* ebones only draw in editmode armature */
static void tree_element_active_ebone__sel(bContext *C, bArmature *arm, EditBone *ebone, short sel)
{
- if (sel) {
- ebone->flag |= BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL;
- arm->act_edbone = ebone;
- // flush to parent?
- if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
- ebone->parent->flag |= BONE_TIPSEL;
- }
- }
- else {
- ebone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
- // flush to parent?
- if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
- ebone->parent->flag &= ~BONE_TIPSEL;
- }
- }
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, CTX_data_edit_object(C));
+ if (sel) {
+ ebone->flag |= BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL;
+ arm->act_edbone = ebone;
+ // flush to parent?
+ if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+ ebone->parent->flag |= BONE_TIPSEL;
+ }
+ }
+ else {
+ ebone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
+ // flush to parent?
+ if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+ ebone->parent->flag &= ~BONE_TIPSEL;
+ }
+ }
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, CTX_data_edit_object(C));
}
-static eOLDrawState tree_element_active_ebone(
- bContext *C, ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
+static eOLDrawState tree_element_active_ebone(bContext *C,
+ ViewLayer *view_layer,
+ TreeElement *te,
+ TreeStoreElem *tselem,
+ const eOLSetState set,
+ bool recursive)
{
- bArmature *arm = (bArmature *)tselem->id;
- EditBone *ebone = te->directdata;
- eOLDrawState status = OL_DRAWSEL_NONE;
-
- if (set != OL_SETSEL_NONE) {
- if (set == OL_SETSEL_NORMAL) {
- if (!(ebone->flag & BONE_HIDDEN_A)) {
- uint bases_len = 0;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(view_layer, NULL, &bases_len);
- ED_armature_edit_deselect_all_multi_ex(bases, bases_len);
- MEM_freeN(bases);
-
- tree_element_active_ebone__sel(C, arm, ebone, true);
- status = OL_DRAWSEL_NORMAL;
- }
- }
- else if (set == OL_SETSEL_EXTEND) {
- if (!(ebone->flag & BONE_HIDDEN_A)) {
- if (!(ebone->flag & BONE_SELECTED)) {
- tree_element_active_ebone__sel(C, arm, ebone, true);
- status = OL_DRAWSEL_NORMAL;
- }
- else {
- /* entirely selected, so de-select */
- tree_element_active_ebone__sel(C, arm, ebone, false);
- status = OL_DRAWSEL_NONE;
- }
- }
- }
-
- if (recursive) {
- /* Recursive select/deselect */
- do_outliner_ebone_select_recursive(arm, ebone, (ebone->flag & BONE_SELECTED) != 0);
- }
- }
- else if (ebone->flag & BONE_SELECTED) {
- status = OL_DRAWSEL_NORMAL;
- }
-
- return status;
+ bArmature *arm = (bArmature *)tselem->id;
+ EditBone *ebone = te->directdata;
+ eOLDrawState status = OL_DRAWSEL_NONE;
+
+ if (set != OL_SETSEL_NONE) {
+ if (set == OL_SETSEL_NORMAL) {
+ if (!(ebone->flag & BONE_HIDDEN_A)) {
+ uint bases_len = 0;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
+ view_layer, NULL, &bases_len);
+ ED_armature_edit_deselect_all_multi_ex(bases, bases_len);
+ MEM_freeN(bases);
+
+ tree_element_active_ebone__sel(C, arm, ebone, true);
+ status = OL_DRAWSEL_NORMAL;
+ }
+ }
+ else if (set == OL_SETSEL_EXTEND) {
+ if (!(ebone->flag & BONE_HIDDEN_A)) {
+ if (!(ebone->flag & BONE_SELECTED)) {
+ tree_element_active_ebone__sel(C, arm, ebone, true);
+ status = OL_DRAWSEL_NORMAL;
+ }
+ else {
+ /* entirely selected, so de-select */
+ tree_element_active_ebone__sel(C, arm, ebone, false);
+ status = OL_DRAWSEL_NONE;
+ }
+ }
+ }
+
+ if (recursive) {
+ /* Recursive select/deselect */
+ do_outliner_ebone_select_recursive(arm, ebone, (ebone->flag & BONE_SELECTED) != 0);
+ }
+ }
+ else if (ebone->flag & BONE_SELECTED) {
+ status = OL_DRAWSEL_NORMAL;
+ }
+
+ return status;
}
-static eOLDrawState tree_element_active_modifier(
- bContext *C, Scene *UNUSED(scene), ViewLayer *UNUSED(sl), TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
+static eOLDrawState tree_element_active_modifier(bContext *C,
+ Scene *UNUSED(scene),
+ ViewLayer *UNUSED(sl),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *tselem,
+ const eOLSetState set)
{
- if (set != OL_SETSEL_NONE) {
- Object *ob = (Object *)tselem->id;
+ if (set != OL_SETSEL_NONE) {
+ Object *ob = (Object *)tselem->id;
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-// XXX extern_set_butspace(F9KEY, 0);
- }
+ // XXX extern_set_butspace(F9KEY, 0);
+ }
- return OL_DRAWSEL_NONE;
+ return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_psys(
- bContext *C, Scene *UNUSED(scene), TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
+static eOLDrawState tree_element_active_psys(bContext *C,
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *tselem,
+ const eOLSetState set)
{
- if (set != OL_SETSEL_NONE) {
- Object *ob = (Object *)tselem->id;
+ if (set != OL_SETSEL_NONE) {
+ Object *ob = (Object *)tselem->id;
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
-// XXX extern_set_butspace(F7KEY, 0);
- }
+ // XXX extern_set_butspace(F7KEY, 0);
+ }
- return OL_DRAWSEL_NONE;
+ return OL_DRAWSEL_NONE;
}
-static int tree_element_active_constraint(
- bContext *C, Scene *UNUSED(scene), ViewLayer *UNUSED(sl), TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
+static int tree_element_active_constraint(bContext *C,
+ Scene *UNUSED(scene),
+ ViewLayer *UNUSED(sl),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *tselem,
+ const eOLSetState set)
{
- if (set != OL_SETSEL_NONE) {
- Object *ob = (Object *)tselem->id;
+ if (set != OL_SETSEL_NONE) {
+ Object *ob = (Object *)tselem->id;
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
-// XXX extern_set_butspace(F7KEY, 0);
- }
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ // XXX extern_set_butspace(F7KEY, 0);
+ }
- return OL_DRAWSEL_NONE;
+ return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_text(
- bContext *UNUSED(C), Scene *UNUSED(scene), ViewLayer *UNUSED(sl), SpaceOutliner *UNUSED(soops),
- TreeElement *UNUSED(te), int UNUSED(set))
+static eOLDrawState tree_element_active_text(bContext *UNUSED(C),
+ Scene *UNUSED(scene),
+ ViewLayer *UNUSED(sl),
+ SpaceOutliner *UNUSED(soops),
+ TreeElement *UNUSED(te),
+ int UNUSED(set))
{
- // XXX removed
- return OL_DRAWSEL_NONE;
+ // XXX removed
+ return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_pose(
- bContext *C, Scene *scene, ViewLayer *view_layer, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
+static eOLDrawState tree_element_active_pose(bContext *C,
+ Scene *scene,
+ ViewLayer *view_layer,
+ TreeElement *UNUSED(te),
+ TreeStoreElem *tselem,
+ const eOLSetState set)
{
- Object *ob = (Object *)tselem->id;
- Base *base = BKE_view_layer_base_find(view_layer, ob);
-
- if (base == NULL) {
- /* Armature not instantiated in current scene (e.g. inside an appended group...). */
- return OL_DRAWSEL_NONE;
- }
-
- if (set != OL_SETSEL_NONE) {
- do_outliner_activate_pose(C, scene, view_layer, base, (set == OL_SETSEL_EXTEND));
- }
- else {
- if (ob->mode & OB_MODE_POSE) {
- return OL_DRAWSEL_NORMAL;
- }
- }
- return OL_DRAWSEL_NONE;
+ Object *ob = (Object *)tselem->id;
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+
+ if (base == NULL) {
+ /* Armature not instantiated in current scene (e.g. inside an appended group...). */
+ return OL_DRAWSEL_NONE;
+ }
+
+ if (set != OL_SETSEL_NONE) {
+ do_outliner_activate_pose(C, scene, view_layer, base, (set == OL_SETSEL_EXTEND));
+ }
+ else {
+ if (ob->mode & OB_MODE_POSE) {
+ return OL_DRAWSEL_NORMAL;
+ }
+ }
+ return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_sequence(
- bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set)
+static eOLDrawState tree_element_active_sequence(bContext *C,
+ Scene *scene,
+ TreeElement *te,
+ TreeStoreElem *UNUSED(tselem),
+ const eOLSetState set)
{
- Sequence *seq = (Sequence *) te->directdata;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
-
- if (set != OL_SETSEL_NONE) {
- /* only check on setting */
- if (BLI_findindex(ed->seqbasep, seq) != -1) {
- if (set == OL_SETSEL_EXTEND) {
- BKE_sequencer_active_set(scene, NULL);
- }
- ED_sequencer_deselect_all(scene);
-
- if ((set == OL_SETSEL_EXTEND) && seq->flag & SELECT) {
- seq->flag &= ~SELECT;
- }
- else {
- seq->flag |= SELECT;
- BKE_sequencer_active_set(scene, seq);
- }
- }
-
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
- }
- else {
- if (ed->act_seq == seq && seq->flag & SELECT) {
- return OL_DRAWSEL_NORMAL;
- }
- }
- return OL_DRAWSEL_NONE;
+ Sequence *seq = (Sequence *)te->directdata;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+
+ if (set != OL_SETSEL_NONE) {
+ /* only check on setting */
+ if (BLI_findindex(ed->seqbasep, seq) != -1) {
+ if (set == OL_SETSEL_EXTEND) {
+ BKE_sequencer_active_set(scene, NULL);
+ }
+ ED_sequencer_deselect_all(scene);
+
+ if ((set == OL_SETSEL_EXTEND) && seq->flag & SELECT) {
+ seq->flag &= ~SELECT;
+ }
+ else {
+ seq->flag |= SELECT;
+ BKE_sequencer_active_set(scene, seq);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
+ }
+ else {
+ if (ed->act_seq == seq && seq->flag & SELECT) {
+ return OL_DRAWSEL_NORMAL;
+ }
+ }
+ return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_sequence_dup(
- Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set)
+static eOLDrawState tree_element_active_sequence_dup(Scene *scene,
+ TreeElement *te,
+ TreeStoreElem *UNUSED(tselem),
+ const eOLSetState set)
{
- Sequence *seq, *p;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
-
- seq = (Sequence *)te->directdata;
- if (set == OL_SETSEL_NONE) {
- if (seq->flag & SELECT) {
- return OL_DRAWSEL_NORMAL;
- }
- return OL_DRAWSEL_NONE;
- }
-
-// XXX select_single_seq(seq, 1);
- p = ed->seqbasep->first;
- while (p) {
- if ((!p->strip) || (!p->strip->stripdata) || (p->strip->stripdata->name[0] == '\0')) {
- p = p->next;
- continue;
- }
-
-// if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name))
-// XXX select_single_seq(p, 0);
- p = p->next;
- }
- return OL_DRAWSEL_NONE;
+ Sequence *seq, *p;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+
+ seq = (Sequence *)te->directdata;
+ if (set == OL_SETSEL_NONE) {
+ if (seq->flag & SELECT) {
+ return OL_DRAWSEL_NORMAL;
+ }
+ return OL_DRAWSEL_NONE;
+ }
+
+ // XXX select_single_seq(seq, 1);
+ p = ed->seqbasep->first;
+ while (p) {
+ if ((!p->strip) || (!p->strip->stripdata) || (p->strip->stripdata->name[0] == '\0')) {
+ p = p->next;
+ continue;
+ }
+
+ // if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name))
+ // XXX select_single_seq(p, 0);
+ p = p->next;
+ }
+ return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_keymap_item(
- bContext *UNUSED(C), Scene *UNUSED(scene), ViewLayer *UNUSED(sl), TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set)
+static eOLDrawState tree_element_active_keymap_item(bContext *UNUSED(C),
+ Scene *UNUSED(scene),
+ ViewLayer *UNUSED(sl),
+ TreeElement *te,
+ TreeStoreElem *UNUSED(tselem),
+ const eOLSetState set)
{
- wmKeyMapItem *kmi = te->directdata;
-
- if (set == OL_SETSEL_NONE) {
- if (kmi->flag & KMI_INACTIVE) {
- return OL_DRAWSEL_NONE;
- }
- return OL_DRAWSEL_NORMAL;
- }
- else {
- kmi->flag ^= KMI_INACTIVE;
- }
- return OL_DRAWSEL_NONE;
+ wmKeyMapItem *kmi = te->directdata;
+
+ if (set == OL_SETSEL_NONE) {
+ if (kmi->flag & KMI_INACTIVE) {
+ return OL_DRAWSEL_NONE;
+ }
+ return OL_DRAWSEL_NORMAL;
+ }
+ else {
+ kmi->flag ^= KMI_INACTIVE;
+ }
+ return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_master_collection(
- bContext *C, TreeElement *UNUSED(te), const eOLSetState set)
+static eOLDrawState tree_element_active_master_collection(bContext *C,
+ TreeElement *UNUSED(te),
+ const eOLSetState set)
{
- if (set == OL_SETSEL_NONE) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- LayerCollection *active = CTX_data_layer_collection(C);
-
- if (active == view_layer->layer_collections.first) {
- return OL_DRAWSEL_NORMAL;
- }
- }
- else {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- LayerCollection *layer_collection = view_layer->layer_collections.first;
- BKE_layer_collection_activate(view_layer, layer_collection);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- }
-
- return OL_DRAWSEL_NONE;
+ if (set == OL_SETSEL_NONE) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *active = CTX_data_layer_collection(C);
+
+ if (active == view_layer->layer_collections.first) {
+ return OL_DRAWSEL_NORMAL;
+ }
+ }
+ else {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *layer_collection = view_layer->layer_collections.first;
+ BKE_layer_collection_activate(view_layer, layer_collection);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ }
+
+ return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_layer_collection(
- bContext *C, TreeElement *te, const eOLSetState set)
+static eOLDrawState tree_element_active_layer_collection(bContext *C,
+ TreeElement *te,
+ const eOLSetState set)
{
- if (set == OL_SETSEL_NONE) {
- LayerCollection *active = CTX_data_layer_collection(C);
-
- if (active == te->directdata) {
- return OL_DRAWSEL_NORMAL;
- }
- }
- else {
- Scene *scene = CTX_data_scene(C);
- LayerCollection *layer_collection = te->directdata;
- ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, layer_collection);
- BKE_layer_collection_activate(view_layer, layer_collection);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- }
-
- return OL_DRAWSEL_NONE;
+ if (set == OL_SETSEL_NONE) {
+ LayerCollection *active = CTX_data_layer_collection(C);
+
+ if (active == te->directdata) {
+ return OL_DRAWSEL_NORMAL;
+ }
+ }
+ else {
+ Scene *scene = CTX_data_scene(C);
+ LayerCollection *layer_collection = te->directdata;
+ ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, layer_collection);
+ BKE_layer_collection_activate(view_layer, layer_collection);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ }
+
+ return OL_DRAWSEL_NONE;
}
/* ---------------------------------------------- */
/* generic call for ID data check or make/check active in UI */
-eOLDrawState tree_element_active(bContext *C, Scene *scene, ViewLayer *view_layer, SpaceOutliner *soops, TreeElement *te,
- const eOLSetState set, const bool handle_all_types)
+eOLDrawState tree_element_active(bContext *C,
+ Scene *scene,
+ ViewLayer *view_layer,
+ SpaceOutliner *soops,
+ TreeElement *te,
+ const eOLSetState set,
+ const bool handle_all_types)
{
- switch (te->idcode) {
- /* Note: ID_OB only if handle_all_type is true, else objects are handled specially to allow multiple
- * selection. See do_outliner_item_activate. */
- case ID_OB:
- if (handle_all_types) {
- return tree_element_set_active_object(C, scene, view_layer, soops, te, set, false);
- }
- break;
- case ID_MA:
- return tree_element_active_material(C, scene, view_layer, soops, te, set);
- case ID_WO:
- return tree_element_active_world(C, scene, view_layer, soops, te, set);
- case ID_LA:
- return tree_element_active_light(C, scene, view_layer, soops, te, set);
- case ID_TXT:
- return tree_element_active_text(C, scene, view_layer, soops, te, set);
- case ID_CA:
- return tree_element_active_camera(C, scene, view_layer, soops, te, set);
- }
- return OL_DRAWSEL_NONE;
+ switch (te->idcode) {
+ /* Note: ID_OB only if handle_all_type is true, else objects are handled specially to allow multiple
+ * selection. See do_outliner_item_activate. */
+ case ID_OB:
+ if (handle_all_types) {
+ return tree_element_set_active_object(C, scene, view_layer, soops, te, set, false);
+ }
+ break;
+ case ID_MA:
+ return tree_element_active_material(C, scene, view_layer, soops, te, set);
+ case ID_WO:
+ return tree_element_active_world(C, scene, view_layer, soops, te, set);
+ case ID_LA:
+ return tree_element_active_light(C, scene, view_layer, soops, te, set);
+ case ID_TXT:
+ return tree_element_active_text(C, scene, view_layer, soops, te, set);
+ case ID_CA:
+ return tree_element_active_camera(C, scene, view_layer, soops, te, set);
+ }
+ return OL_DRAWSEL_NONE;
}
/**
* Generic call for non-id data to make/check active in UI
*/
-eOLDrawState tree_element_type_active(
- bContext *C, Scene *scene, ViewLayer *view_layer, SpaceOutliner *soops,
- TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
+eOLDrawState tree_element_type_active(bContext *C,
+ Scene *scene,
+ ViewLayer *view_layer,
+ SpaceOutliner *soops,
+ TreeElement *te,
+ TreeStoreElem *tselem,
+ const eOLSetState set,
+ bool recursive)
{
- switch (tselem->type) {
- case TSE_DEFGROUP:
- return tree_element_active_defgroup(C, view_layer, te, tselem, set);
- case TSE_BONE:
- return tree_element_active_bone(C, view_layer, te, tselem, set, recursive);
- case TSE_EBONE:
- return tree_element_active_ebone(C, view_layer, te, tselem, set, recursive);
- case TSE_MODIFIER:
- return tree_element_active_modifier(C, scene, view_layer, te, tselem, set);
- case TSE_LINKED_OB:
- if (set != OL_SETSEL_NONE) {
- tree_element_set_active_object(C, scene, view_layer, soops, te, set, false);
- }
- else if (tselem->id == (ID *)OBACT(view_layer)) {
- return OL_DRAWSEL_NORMAL;
- }
- break;
- case TSE_LINKED_PSYS:
- return tree_element_active_psys(C, scene, te, tselem, set);
- case TSE_POSE_BASE:
- return tree_element_active_pose(C, scene, view_layer, te, tselem, set);
- case TSE_POSE_CHANNEL:
- return tree_element_active_posechannel(C, scene, view_layer, te, tselem, set, recursive);
- case TSE_CONSTRAINT:
- return tree_element_active_constraint(C, scene, view_layer, te, tselem, set);
- case TSE_R_LAYER:
- return active_viewlayer(C, scene, view_layer, te, set);
- case TSE_POSEGRP:
- return tree_element_active_posegroup(C, scene, view_layer, te, tselem, set);
- case TSE_SEQUENCE:
- return tree_element_active_sequence(C, scene, te, tselem, set);
- case TSE_SEQUENCE_DUP:
- return tree_element_active_sequence_dup(scene, te, tselem, set);
- case TSE_KEYMAP_ITEM:
- return tree_element_active_keymap_item(C, scene, view_layer, te, tselem, set);
- case TSE_GP_LAYER:
- return tree_element_active_gplayer(C, scene, te, tselem, set);
- break;
- case TSE_VIEW_COLLECTION_BASE:
- return tree_element_active_master_collection(C, te, set);
- case TSE_LAYER_COLLECTION:
- return tree_element_active_layer_collection(C, te, set);
- }
- return OL_DRAWSEL_NONE;
+ switch (tselem->type) {
+ case TSE_DEFGROUP:
+ return tree_element_active_defgroup(C, view_layer, te, tselem, set);
+ case TSE_BONE:
+ return tree_element_active_bone(C, view_layer, te, tselem, set, recursive);
+ case TSE_EBONE:
+ return tree_element_active_ebone(C, view_layer, te, tselem, set, recursive);
+ case TSE_MODIFIER:
+ return tree_element_active_modifier(C, scene, view_layer, te, tselem, set);
+ case TSE_LINKED_OB:
+ if (set != OL_SETSEL_NONE) {
+ tree_element_set_active_object(C, scene, view_layer, soops, te, set, false);
+ }
+ else if (tselem->id == (ID *)OBACT(view_layer)) {
+ return OL_DRAWSEL_NORMAL;
+ }
+ break;
+ case TSE_LINKED_PSYS:
+ return tree_element_active_psys(C, scene, te, tselem, set);
+ case TSE_POSE_BASE:
+ return tree_element_active_pose(C, scene, view_layer, te, tselem, set);
+ case TSE_POSE_CHANNEL:
+ return tree_element_active_posechannel(C, scene, view_layer, te, tselem, set, recursive);
+ case TSE_CONSTRAINT:
+ return tree_element_active_constraint(C, scene, view_layer, te, tselem, set);
+ case TSE_R_LAYER:
+ return active_viewlayer(C, scene, view_layer, te, set);
+ case TSE_POSEGRP:
+ return tree_element_active_posegroup(C, scene, view_layer, te, tselem, set);
+ case TSE_SEQUENCE:
+ return tree_element_active_sequence(C, scene, te, tselem, set);
+ case TSE_SEQUENCE_DUP:
+ return tree_element_active_sequence_dup(scene, te, tselem, set);
+ case TSE_KEYMAP_ITEM:
+ return tree_element_active_keymap_item(C, scene, view_layer, te, tselem, set);
+ case TSE_GP_LAYER:
+ return tree_element_active_gplayer(C, scene, te, tselem, set);
+ break;
+ case TSE_VIEW_COLLECTION_BASE:
+ return tree_element_active_master_collection(C, te, set);
+ case TSE_LAYER_COLLECTION:
+ return tree_element_active_layer_collection(C, te, set);
+ }
+ return OL_DRAWSEL_NONE;
}
/* ================================================ */
@@ -1031,143 +1115,162 @@ eOLDrawState tree_element_type_active(
*
* Needed to run from operators accessed from a menu.
*/
-static void do_outliner_item_activate_tree_element(
- bContext *C, Scene *scene, ViewLayer *view_layer, SpaceOutliner *soops,
- TreeElement *te, TreeStoreElem *tselem,
- const bool extend, const bool recursive)
+static void do_outliner_item_activate_tree_element(bContext *C,
+ Scene *scene,
+ ViewLayer *view_layer,
+ SpaceOutliner *soops,
+ TreeElement *te,
+ TreeStoreElem *tselem,
+ const bool extend,
+ const bool recursive)
{
- /* Always makes active object, except for some specific types. */
- if (ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE, TSE_LAYER_COLLECTION)) {
- /* Note about TSE_EBONE: In case of a same ID_AR datablock shared among several objects, we do not want
- * to switch out of edit mode (see T48328 for details). */
- }
- else if (tselem->id && OB_DATA_SUPPORT_EDITMODE(te->idcode)) {
- /* Support edit-mode toggle, keeping the active object as is. */
- }
- else if (tselem->type == TSE_POSE_BASE) {
- /* Support pose mode toggle, keeping the active object as is. */
- }
- else {
- tree_element_set_active_object(
- C, scene, view_layer, soops, te,
- (extend && tselem->type == 0) ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
- recursive && tselem->type == 0);
- }
-
- if (tselem->type == 0) { // the lib blocks
- /* editmode? */
- if (te->idcode == ID_SCE) {
- if (scene != (Scene *)tselem->id) {
- WM_window_set_active_scene(CTX_data_main(C), C, CTX_wm_window(C), (Scene *)tselem->id);
- }
- }
- else if (te->idcode == ID_GR) {
- Collection *gr = (Collection *)tselem->id;
-
- if (extend) {
- int sel = BA_SELECT;
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(gr, object)
- {
- Base *base = BKE_view_layer_base_find(view_layer, object);
- if (base && (base->flag & BASE_SELECTED)) {
- sel = BA_DESELECT;
- break;
- }
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
-
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(gr, object)
- {
- Base *base = BKE_view_layer_base_find(view_layer, object);
- if (base) {
- ED_object_base_select(base, sel);
- }
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- }
- else {
- BKE_view_layer_base_deselect_all(view_layer);
-
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(gr, object)
- {
- Base *base = BKE_view_layer_base_find(view_layer, object);
- /* Object may not be in this scene */
- if (base != NULL) {
- if ((base->flag & BASE_SELECTED) == 0) {
- ED_object_base_select(base, BA_SELECT);
- }
- }
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- }
-
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
- else if (OB_DATA_SUPPORT_EDITMODE(te->idcode)) {
- Object *ob = (Object *)outliner_search_back(soops, te, ID_OB);
- if ((ob != NULL) && (ob->data == tselem->id)) {
- Base *base = BKE_view_layer_base_find(view_layer, ob);
- if ((base != NULL) && (base->flag & BASE_VISIBLE)) {
- do_outliner_activate_obdata(C, scene, view_layer, base, extend);
- }
- }
- }
- else if (ELEM(te->idcode, ID_GD)) {
- /* set grease pencil to object mode */
- WM_operator_name_call(C, "GPENCIL_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
- }
- else { // rest of types
- tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NORMAL, false);
- }
-
- }
- else {
- tree_element_type_active(C, scene, view_layer, soops, te, tselem,
- extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
- recursive);
- }
+ /* Always makes active object, except for some specific types. */
+ if (ELEM(tselem->type,
+ TSE_SEQUENCE,
+ TSE_SEQ_STRIP,
+ TSE_SEQUENCE_DUP,
+ TSE_EBONE,
+ TSE_LAYER_COLLECTION)) {
+ /* Note about TSE_EBONE: In case of a same ID_AR datablock shared among several objects, we do not want
+ * to switch out of edit mode (see T48328 for details). */
+ }
+ else if (tselem->id && OB_DATA_SUPPORT_EDITMODE(te->idcode)) {
+ /* Support edit-mode toggle, keeping the active object as is. */
+ }
+ else if (tselem->type == TSE_POSE_BASE) {
+ /* Support pose mode toggle, keeping the active object as is. */
+ }
+ else {
+ tree_element_set_active_object(C,
+ scene,
+ view_layer,
+ soops,
+ te,
+ (extend && tselem->type == 0) ? OL_SETSEL_EXTEND :
+ OL_SETSEL_NORMAL,
+ recursive && tselem->type == 0);
+ }
+
+ if (tselem->type == 0) { // the lib blocks
+ /* editmode? */
+ if (te->idcode == ID_SCE) {
+ if (scene != (Scene *)tselem->id) {
+ WM_window_set_active_scene(CTX_data_main(C), C, CTX_wm_window(C), (Scene *)tselem->id);
+ }
+ }
+ else if (te->idcode == ID_GR) {
+ Collection *gr = (Collection *)tselem->id;
+
+ if (extend) {
+ int sel = BA_SELECT;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (gr, object) {
+ Base *base = BKE_view_layer_base_find(view_layer, object);
+ if (base && (base->flag & BASE_SELECTED)) {
+ sel = BA_DESELECT;
+ break;
+ }
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (gr, object) {
+ Base *base = BKE_view_layer_base_find(view_layer, object);
+ if (base) {
+ ED_object_base_select(base, sel);
+ }
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ }
+ else {
+ BKE_view_layer_base_deselect_all(view_layer);
+
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (gr, object) {
+ Base *base = BKE_view_layer_base_find(view_layer, object);
+ /* Object may not be in this scene */
+ if (base != NULL) {
+ if ((base->flag & BASE_SELECTED) == 0) {
+ ED_object_base_select(base, BA_SELECT);
+ }
+ }
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ }
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ }
+ else if (OB_DATA_SUPPORT_EDITMODE(te->idcode)) {
+ Object *ob = (Object *)outliner_search_back(soops, te, ID_OB);
+ if ((ob != NULL) && (ob->data == tselem->id)) {
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+ if ((base != NULL) && (base->flag & BASE_VISIBLE)) {
+ do_outliner_activate_obdata(C, scene, view_layer, base, extend);
+ }
+ }
+ }
+ else if (ELEM(te->idcode, ID_GD)) {
+ /* set grease pencil to object mode */
+ WM_operator_name_call(C, "GPENCIL_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
+ }
+ else { // rest of types
+ tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NORMAL, false);
+ }
+ }
+ else {
+ tree_element_type_active(C,
+ scene,
+ view_layer,
+ soops,
+ te,
+ tselem,
+ extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
+ recursive);
+ }
}
/**
* \param extend: Don't deselect other items, only modify \a te.
* \param toggle: Select \a te when not selected, deselect when selected.
*/
-void outliner_item_select(SpaceOutliner *soops, const TreeElement *te, const bool extend, const bool toggle)
+void outliner_item_select(SpaceOutliner *soops,
+ const TreeElement *te,
+ const bool extend,
+ const bool toggle)
{
- TreeStoreElem *tselem = TREESTORE(te);
- const short new_flag = toggle ? (tselem->flag ^ TSE_SELECTED) : (tselem->flag | TSE_SELECTED);
+ TreeStoreElem *tselem = TREESTORE(te);
+ const short new_flag = toggle ? (tselem->flag ^ TSE_SELECTED) : (tselem->flag | TSE_SELECTED);
- if (extend == false) {
- outliner_flag_set(&soops->tree, TSE_SELECTED, false);
- }
- tselem->flag = new_flag;
+ if (extend == false) {
+ outliner_flag_set(&soops->tree, TSE_SELECTED, false);
+ }
+ tselem->flag = new_flag;
}
static void outliner_item_toggle_closed(TreeElement *te, const bool toggle_children)
{
- TreeStoreElem *tselem = TREESTORE(te);
- if (toggle_children) {
- tselem->flag &= ~TSE_CLOSED;
-
- const bool all_opened = !outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1);
- outliner_flag_set(&te->subtree, TSE_CLOSED, all_opened);
- }
- else {
- tselem->flag ^= TSE_CLOSED;
- }
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (toggle_children) {
+ tselem->flag &= ~TSE_CLOSED;
+
+ const bool all_opened = !outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1);
+ outliner_flag_set(&te->subtree, TSE_CLOSED, all_opened);
+ }
+ else {
+ tselem->flag ^= TSE_CLOSED;
+ }
}
static bool outliner_item_is_co_within_close_toggle(TreeElement *te, float view_co_x)
{
- return ((te->flag & TE_ICONROW) == 0) && (view_co_x > te->xs) && (view_co_x < te->xs + UI_UNIT_X);
+ return ((te->flag & TE_ICONROW) == 0) && (view_co_x > te->xs) &&
+ (view_co_x < te->xs + UI_UNIT_X);
}
-static bool outliner_is_co_within_restrict_columns(const SpaceOutliner *soops, const ARegion *ar, float view_co_x)
+static bool outliner_is_co_within_restrict_columns(const SpaceOutliner *soops,
+ const ARegion *ar,
+ float view_co_x)
{
- return ((soops->outlinevis != SO_DATA_API) &&
- !(soops->flag & SO_HIDE_RESTRICTCOLS) &&
- (view_co_x > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX));
+ return ((soops->outlinevis != SO_DATA_API) && !(soops->flag & SO_HIDE_RESTRICTCOLS) &&
+ (view_co_x > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX));
}
/**
@@ -1177,17 +1280,14 @@ static bool outliner_is_co_within_restrict_columns(const SpaceOutliner *soops, c
* This allows us to simulate clicking on an item without dealing with the mouse cursor.
*/
void outliner_item_do_activate_from_tree_element(
- bContext *C, TreeElement *te, TreeStoreElem *tselem,
- bool extend, bool recursive)
+ bContext *C, TreeElement *te, TreeStoreElem *tselem, bool extend, bool recursive)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
-
- do_outliner_item_activate_tree_element(
- C, scene, view_layer, soops,
- te, tselem,
- extend, recursive);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+
+ do_outliner_item_activate_tree_element(
+ C, scene, view_layer, soops, te, tselem, extend, recursive);
}
/**
@@ -1195,149 +1295,152 @@ void outliner_item_do_activate_from_tree_element(
*
* May expend/collapse branches or activate items.
* */
-int outliner_item_do_activate_from_cursor(
- bContext *C, const int mval[2],
- bool extend, bool recursive)
+int outliner_item_do_activate_from_cursor(bContext *C,
+ const int mval[2],
+ bool extend,
+ bool recursive)
{
- ARegion *ar = 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]);
-
- if (outliner_is_co_within_restrict_columns(soops, ar, view_mval[0])) {
- return OPERATOR_CANCELLED;
- }
-
- if (!(te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]))) {
- /* skip */
- }
- else if (outliner_item_is_co_within_close_toggle(te, view_mval[0])) {
- outliner_item_toggle_closed(te, extend);
- changed = true;
- rebuild_tree = true;
- }
- else {
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- /* the row may also contain children, if one is hovered we want this instead of current te */
- TreeElement *activate_te = outliner_find_item_at_x_in_row(soops, te, view_mval[0]);
- TreeStoreElem *activate_tselem = TREESTORE(activate_te);
-
- outliner_item_select(soops, activate_te, extend, extend);
- do_outliner_item_activate_tree_element(C, scene, view_layer, soops, activate_te, activate_tselem, extend, recursive);
- changed = true;
- }
-
- if (changed) {
- if (rebuild_tree) {
- ED_region_tag_redraw(ar);
- }
- else {
- ED_region_tag_redraw_no_rebuild(ar);
- }
- ED_undo_push(C, "Outliner selection change");
- }
-
- return OPERATOR_FINISHED;
+ ARegion *ar = 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]);
+
+ if (outliner_is_co_within_restrict_columns(soops, ar, view_mval[0])) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!(te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]))) {
+ /* skip */
+ }
+ else if (outliner_item_is_co_within_close_toggle(te, view_mval[0])) {
+ outliner_item_toggle_closed(te, extend);
+ changed = true;
+ rebuild_tree = true;
+ }
+ else {
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ /* the row may also contain children, if one is hovered we want this instead of current te */
+ TreeElement *activate_te = outliner_find_item_at_x_in_row(soops, te, view_mval[0]);
+ TreeStoreElem *activate_tselem = TREESTORE(activate_te);
+
+ outliner_item_select(soops, activate_te, extend, extend);
+ do_outliner_item_activate_tree_element(
+ C, scene, view_layer, soops, activate_te, activate_tselem, extend, recursive);
+ changed = true;
+ }
+
+ if (changed) {
+ if (rebuild_tree) {
+ ED_region_tag_redraw(ar);
+ }
+ else {
+ ED_region_tag_redraw_no_rebuild(ar);
+ }
+ ED_undo_push(C, "Outliner selection change");
+ }
+
+ return OPERATOR_FINISHED;
}
/* event can enterkey, then it opens/closes */
static int outliner_item_activate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bool extend = RNA_boolean_get(op->ptr, "extend");
- bool recursive = RNA_boolean_get(op->ptr, "recursive");
- return outliner_item_do_activate_from_cursor(C, event->mval, extend, recursive);
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+ bool recursive = RNA_boolean_get(op->ptr, "recursive");
+ return outliner_item_do_activate_from_cursor(C, event->mval, extend, recursive);
}
void OUTLINER_OT_item_activate(wmOperatorType *ot)
{
- ot->name = "Select";
- ot->idname = "OUTLINER_OT_item_activate";
- ot->description = "Handle mouse clicks to select and activate items";
+ ot->name = "Select";
+ ot->idname = "OUTLINER_OT_item_activate";
+ ot->description = "Handle mouse clicks to select and activate items";
- ot->invoke = outliner_item_activate_invoke;
+ ot->invoke = outliner_item_activate_invoke;
- ot->poll = ED_operator_outliner_active;
+ ot->poll = ED_operator_outliner_active;
- RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection for activation");
- RNA_def_boolean(ot->srna, "recursive", false, "Recursive", "Select Objects and their children");
+ RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection for activation");
+ RNA_def_boolean(ot->srna, "recursive", false, "Recursive", "Select Objects and their children");
}
/* ****************************************************** */
/* **************** Box Select Tool ****************** */
-static void outliner_item_box_select(SpaceOutliner *soops, Scene *scene, rctf *rectf, TreeElement *te, bool select)
+static void outliner_item_box_select(
+ SpaceOutliner *soops, Scene *scene, rctf *rectf, TreeElement *te, bool select)
{
- TreeStoreElem *tselem = TREESTORE(te);
-
- if (te->ys <= rectf->ymax && te->ys + UI_UNIT_Y >= rectf->ymin) {
- if (select) {
- tselem->flag |= TSE_SELECTED;
- }
- else {
- tselem->flag &= ~TSE_SELECTED;
- }
- }
-
- /* Look at its children. */
- if (TSELEM_OPEN(tselem, soops)) {
- for (te = te->subtree.first; te; te = te->next) {
- outliner_item_box_select(soops, scene, rectf, te, select);
- }
- }
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (te->ys <= rectf->ymax && te->ys + UI_UNIT_Y >= rectf->ymin) {
+ if (select) {
+ tselem->flag |= TSE_SELECTED;
+ }
+ else {
+ tselem->flag &= ~TSE_SELECTED;
+ }
+ }
+
+ /* Look at its children. */
+ if (TSELEM_OPEN(tselem, soops)) {
+ for (te = te->subtree.first; te; te = te->next) {
+ outliner_item_box_select(soops, scene, rectf, te, select);
+ }
+ }
}
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);
- rctf rectf;
+ Scene *scene = CTX_data_scene(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ ARegion *ar = CTX_wm_region(C);
+ rctf rectf;
- 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)) {
- outliner_flag_set(&soops->tree, TSE_SELECTED, 0);
- }
+ 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)) {
+ outliner_flag_set(&soops->tree, TSE_SELECTED, 0);
+ }
- WM_operator_properties_border_to_rctf(op, &rectf);
- UI_view2d_region_to_view_rctf(&ar->v2d, &rectf, &rectf);
+ WM_operator_properties_border_to_rctf(op, &rectf);
+ UI_view2d_region_to_view_rctf(&ar->v2d, &rectf, &rectf);
- for (TreeElement *te = soops->tree.first; te; te = te->next) {
- outliner_item_box_select(soops, scene, &rectf, te, select);
- }
+ for (TreeElement *te = soops->tree.first; te; te = te->next) {
+ 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);
+ 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);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_select_box(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Box Select";
- ot->idname = "OUTLINER_OT_select_box";
- ot->description = "Use box selection to select tree elements";
+ /* identifiers */
+ ot->name = "Box Select";
+ ot->idname = "OUTLINER_OT_select_box";
+ ot->description = "Use box selection to select tree elements";
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = outliner_box_select_exec;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = outliner_box_select_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
- ot->poll = ED_operator_outliner_active;
+ ot->poll = ED_operator_outliner_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_gesture_box(ot);
- WM_operator_properties_select_operation_simple(ot);
+ /* properties */
+ WM_operator_properties_gesture_box(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
/* ****************************************************** */
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 083ae3a048c..ad4661102bc 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -82,2041 +82,2222 @@
#include "outliner_intern.h"
-
/* ****************************************************** */
/* ************ SELECTION OPERATIONS ********* */
-static void set_operation_types(SpaceOutliner *soops, ListBase *lb,
+static void set_operation_types(SpaceOutliner *soops,
+ ListBase *lb,
int *scenelevel,
int *objectlevel,
int *idlevel,
int *datalevel)
{
- TreeElement *te;
- TreeStoreElem *tselem;
-
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
- if (tselem->flag & TSE_SELECTED) {
- /* Layer collection points to collection ID. */
- if (!ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
- if (*datalevel == 0) {
- *datalevel = tselem->type;
- }
- else if (*datalevel != tselem->type) {
- *datalevel = -1;
- }
- }
- else {
- int idcode = GS(tselem->id->name);
- switch (idcode) {
- case ID_SCE:
- *scenelevel = 1;
- break;
- case ID_OB:
- *objectlevel = 1;
- break;
-
- case ID_ME: case ID_CU: case ID_MB: case ID_LT:
- case ID_LA: case ID_AR: case ID_CA: case ID_SPK:
- case ID_MA: case ID_TE: case ID_IP: case ID_IM:
- case ID_SO: case ID_KE: case ID_WO: case ID_AC:
- case ID_NLA: case ID_TXT: case ID_GR: case ID_LS:
- case ID_LI:
- if (*idlevel == 0) {
- *idlevel = idcode;
- }
- else if (*idlevel != idcode) {
- *idlevel = -1;
- }
- if (ELEM(*datalevel, TSE_VIEW_COLLECTION_BASE, TSE_SCENE_COLLECTION_BASE)) {
- *datalevel = 0;
- }
- break;
- }
- }
- }
- if (TSELEM_OPEN(tselem, soops)) {
- set_operation_types(soops, &te->subtree,
- scenelevel, objectlevel, idlevel, datalevel);
- }
- }
-}
-
-static void unlink_action_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
- TreeStoreElem *tsep, TreeStoreElem *UNUSED(tselem), void *UNUSED(user_data))
-{
- /* just set action to NULL */
- BKE_animdata_set_action(CTX_wm_reports(C), tsep->id, NULL);
-}
-
-static void unlink_material_cb(
- bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *te,
- TreeStoreElem *tsep, TreeStoreElem *UNUSED(tselem), void *UNUSED(user_data))
-{
- Material **matar = NULL;
- int a, totcol = 0;
-
- if (GS(tsep->id->name) == ID_OB) {
- Object *ob = (Object *)tsep->id;
- totcol = ob->totcol;
- matar = ob->mat;
- }
- else if (GS(tsep->id->name) == ID_ME) {
- Mesh *me = (Mesh *)tsep->id;
- totcol = me->totcol;
- matar = me->mat;
- }
- else if (GS(tsep->id->name) == ID_CU) {
- Curve *cu = (Curve *)tsep->id;
- totcol = cu->totcol;
- matar = cu->mat;
- }
- else if (GS(tsep->id->name) == ID_MB) {
- MetaBall *mb = (MetaBall *)tsep->id;
- totcol = mb->totcol;
- matar = mb->mat;
- }
- else {
- BLI_assert(0);
- }
-
- if (LIKELY(matar != NULL)) {
- for (a = 0; a < totcol; a++) {
- if (a == te->index && matar[a]) {
- id_us_min(&matar[a]->id);
- matar[a] = NULL;
- }
- }
- }
-}
-
-static void unlink_texture_cb(
- bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *te,
- TreeStoreElem *tsep, TreeStoreElem *UNUSED(tselem), void *UNUSED(user_data))
-{
- MTex **mtex = NULL;
- int a;
-
- if (GS(tsep->id->name) == ID_LS) {
- FreestyleLineStyle *ls = (FreestyleLineStyle *)tsep->id;
- mtex = ls->mtex;
- }
- else {
- return;
- }
-
- for (a = 0; a < MAX_MTEX; a++) {
- if (a == te->index && mtex[a]) {
- if (mtex[a]->tex) {
- id_us_min(&mtex[a]->tex->id);
- mtex[a]->tex = NULL;
- }
- }
- }
-}
-
-static void unlink_collection_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
- TreeStoreElem *tsep, TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Main *bmain = CTX_data_main(C);
- Collection *collection = (Collection *)tselem->id;
-
- if (tsep) {
- if (GS(tsep->id->name) == ID_OB) {
- Object *ob = (Object *)tsep->id;
- ob->instance_collection = NULL;
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- DEG_relations_tag_update(bmain);
- }
- else if (GS(tsep->id->name) == ID_GR) {
- Collection *parent = (Collection *)tsep->id;
- id_fake_user_set(&collection->id);
- BKE_collection_child_remove(bmain, parent, collection);
- DEG_id_tag_update(&parent->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
- }
- else if (GS(tsep->id->name) == ID_SCE) {
- Scene *scene = (Scene *)tsep->id;
- Collection *parent = BKE_collection_master(scene);
- id_fake_user_set(&collection->id);
- BKE_collection_child_remove(bmain, parent, collection);
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
- }
- }
-}
-
-static void unlink_object_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
- TreeStoreElem *tsep, TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Main *bmain = CTX_data_main(C);
- Object *ob = (Object *)tselem->id;
-
- if (tsep) {
- if (GS(tsep->id->name) == ID_GR) {
- Collection *parent = (Collection *)tsep->id;
- BKE_collection_object_remove(bmain, parent, ob, true);
- DEG_id_tag_update(&parent->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
- }
- else if (GS(tsep->id->name) == ID_SCE) {
- Scene *scene = (Scene *)tsep->id;
- Collection *parent = BKE_collection_master(scene);
- BKE_collection_object_remove(bmain, parent, ob, true);
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
- }
- }
-}
-
-static void unlink_world_cb(
- bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
- TreeStoreElem *tsep, TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Scene *parscene = (Scene *)tsep->id;
- World *wo = (World *)tselem->id;
-
- /* need to use parent scene not just scene, otherwise may end up getting wrong one */
- id_us_min(&wo->id);
- parscene->world = NULL;
-}
-
-static void outliner_do_libdata_operation(
- bContext *C, ReportList *reports, Scene *scene, SpaceOutliner *soops, ListBase *lb,
- outliner_operation_cb operation_cb,
- void *user_data)
-{
- TreeElement *te;
- TreeStoreElem *tselem;
-
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
- if (tselem->flag & TSE_SELECTED) {
- if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
- TreeStoreElem *tsep = te->parent ? TREESTORE(te->parent) : NULL;
- operation_cb(C, reports, scene, te, tsep, tselem, user_data);
- }
- }
- if (TSELEM_OPEN(tselem, soops)) {
- outliner_do_libdata_operation(C, reports, scene, soops, &te->subtree, operation_cb, user_data);
- }
- }
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for (te = lb->first; te; te = te->next) {
+ tselem = TREESTORE(te);
+ if (tselem->flag & TSE_SELECTED) {
+ /* Layer collection points to collection ID. */
+ if (!ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
+ if (*datalevel == 0) {
+ *datalevel = tselem->type;
+ }
+ else if (*datalevel != tselem->type) {
+ *datalevel = -1;
+ }
+ }
+ else {
+ int idcode = GS(tselem->id->name);
+ switch (idcode) {
+ case ID_SCE:
+ *scenelevel = 1;
+ break;
+ case ID_OB:
+ *objectlevel = 1;
+ break;
+
+ case ID_ME:
+ case ID_CU:
+ case ID_MB:
+ case ID_LT:
+ case ID_LA:
+ case ID_AR:
+ case ID_CA:
+ case ID_SPK:
+ case ID_MA:
+ case ID_TE:
+ case ID_IP:
+ case ID_IM:
+ case ID_SO:
+ case ID_KE:
+ case ID_WO:
+ case ID_AC:
+ case ID_NLA:
+ case ID_TXT:
+ case ID_GR:
+ case ID_LS:
+ case ID_LI:
+ if (*idlevel == 0) {
+ *idlevel = idcode;
+ }
+ else if (*idlevel != idcode) {
+ *idlevel = -1;
+ }
+ if (ELEM(*datalevel, TSE_VIEW_COLLECTION_BASE, TSE_SCENE_COLLECTION_BASE)) {
+ *datalevel = 0;
+ }
+ break;
+ }
+ }
+ }
+ if (TSELEM_OPEN(tselem, soops)) {
+ set_operation_types(soops, &te->subtree, scenelevel, objectlevel, idlevel, datalevel);
+ }
+ }
+}
+
+static void unlink_action_cb(bContext *C,
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *tsep,
+ TreeStoreElem *UNUSED(tselem),
+ void *UNUSED(user_data))
+{
+ /* just set action to NULL */
+ BKE_animdata_set_action(CTX_wm_reports(C), tsep->id, NULL);
+}
+
+static void unlink_material_cb(bContext *UNUSED(C),
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *te,
+ TreeStoreElem *tsep,
+ TreeStoreElem *UNUSED(tselem),
+ void *UNUSED(user_data))
+{
+ Material **matar = NULL;
+ int a, totcol = 0;
+
+ if (GS(tsep->id->name) == ID_OB) {
+ Object *ob = (Object *)tsep->id;
+ totcol = ob->totcol;
+ matar = ob->mat;
+ }
+ else if (GS(tsep->id->name) == ID_ME) {
+ Mesh *me = (Mesh *)tsep->id;
+ totcol = me->totcol;
+ matar = me->mat;
+ }
+ else if (GS(tsep->id->name) == ID_CU) {
+ Curve *cu = (Curve *)tsep->id;
+ totcol = cu->totcol;
+ matar = cu->mat;
+ }
+ else if (GS(tsep->id->name) == ID_MB) {
+ MetaBall *mb = (MetaBall *)tsep->id;
+ totcol = mb->totcol;
+ matar = mb->mat;
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ if (LIKELY(matar != NULL)) {
+ for (a = 0; a < totcol; a++) {
+ if (a == te->index && matar[a]) {
+ id_us_min(&matar[a]->id);
+ matar[a] = NULL;
+ }
+ }
+ }
+}
+
+static void unlink_texture_cb(bContext *UNUSED(C),
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *te,
+ TreeStoreElem *tsep,
+ TreeStoreElem *UNUSED(tselem),
+ void *UNUSED(user_data))
+{
+ MTex **mtex = NULL;
+ int a;
+
+ if (GS(tsep->id->name) == ID_LS) {
+ FreestyleLineStyle *ls = (FreestyleLineStyle *)tsep->id;
+ mtex = ls->mtex;
+ }
+ else {
+ return;
+ }
+
+ for (a = 0; a < MAX_MTEX; a++) {
+ if (a == te->index && mtex[a]) {
+ if (mtex[a]->tex) {
+ id_us_min(&mtex[a]->tex->id);
+ mtex[a]->tex = NULL;
+ }
+ }
+ }
+}
+
+static void unlink_collection_cb(bContext *C,
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *tsep,
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
+{
+ Main *bmain = CTX_data_main(C);
+ Collection *collection = (Collection *)tselem->id;
+
+ if (tsep) {
+ if (GS(tsep->id->name) == ID_OB) {
+ Object *ob = (Object *)tsep->id;
+ ob->instance_collection = NULL;
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ DEG_relations_tag_update(bmain);
+ }
+ else if (GS(tsep->id->name) == ID_GR) {
+ Collection *parent = (Collection *)tsep->id;
+ id_fake_user_set(&collection->id);
+ BKE_collection_child_remove(bmain, parent, collection);
+ DEG_id_tag_update(&parent->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+ }
+ else if (GS(tsep->id->name) == ID_SCE) {
+ Scene *scene = (Scene *)tsep->id;
+ Collection *parent = BKE_collection_master(scene);
+ id_fake_user_set(&collection->id);
+ BKE_collection_child_remove(bmain, parent, collection);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+ }
+ }
+}
+
+static void unlink_object_cb(bContext *C,
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *tsep,
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = (Object *)tselem->id;
+
+ if (tsep) {
+ if (GS(tsep->id->name) == ID_GR) {
+ Collection *parent = (Collection *)tsep->id;
+ BKE_collection_object_remove(bmain, parent, ob, true);
+ DEG_id_tag_update(&parent->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+ }
+ else if (GS(tsep->id->name) == ID_SCE) {
+ Scene *scene = (Scene *)tsep->id;
+ Collection *parent = BKE_collection_master(scene);
+ BKE_collection_object_remove(bmain, parent, ob, true);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+ }
+ }
+}
+
+static void unlink_world_cb(bContext *UNUSED(C),
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *tsep,
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
+{
+ Scene *parscene = (Scene *)tsep->id;
+ World *wo = (World *)tselem->id;
+
+ /* need to use parent scene not just scene, otherwise may end up getting wrong one */
+ id_us_min(&wo->id);
+ parscene->world = NULL;
+}
+
+static void outliner_do_libdata_operation(bContext *C,
+ ReportList *reports,
+ Scene *scene,
+ SpaceOutliner *soops,
+ ListBase *lb,
+ outliner_operation_cb operation_cb,
+ void *user_data)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for (te = lb->first; te; te = te->next) {
+ tselem = TREESTORE(te);
+ if (tselem->flag & TSE_SELECTED) {
+ if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
+ TreeStoreElem *tsep = te->parent ? TREESTORE(te->parent) : NULL;
+ operation_cb(C, reports, scene, te, tsep, tselem, user_data);
+ }
+ }
+ if (TSELEM_OPEN(tselem, soops)) {
+ outliner_do_libdata_operation(
+ C, reports, scene, soops, &te->subtree, operation_cb, user_data);
+ }
+ }
}
/* ******************************************** */
typedef enum eOutliner_PropSceneOps {
- OL_SCENE_OP_DELETE = 1,
+ OL_SCENE_OP_DELETE = 1,
} eOutliner_PropSceneOps;
static const EnumPropertyItem prop_scene_op_types[] = {
- {OL_SCENE_OP_DELETE, "DELETE", ICON_X, "Delete", ""},
- {0, NULL, 0, NULL, NULL},
+ {OL_SCENE_OP_DELETE, "DELETE", ICON_X, "Delete", ""},
+ {0, NULL, 0, NULL, NULL},
};
static bool outliner_do_scene_operation(
- bContext *C, eOutliner_PropSceneOps event, ListBase *lb,
- bool (*operation_cb)(bContext *, eOutliner_PropSceneOps, TreeElement *, TreeStoreElem *))
+ bContext *C,
+ eOutliner_PropSceneOps event,
+ ListBase *lb,
+ bool (*operation_cb)(bContext *, eOutliner_PropSceneOps, TreeElement *, TreeStoreElem *))
{
- TreeElement *te;
- TreeStoreElem *tselem;
- bool success = false;
+ TreeElement *te;
+ TreeStoreElem *tselem;
+ bool success = false;
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
- if (tselem->flag & TSE_SELECTED) {
- if (operation_cb(C, event, te, tselem)) {
- success = true;
- }
- }
- }
+ for (te = lb->first; te; te = te->next) {
+ tselem = TREESTORE(te);
+ if (tselem->flag & TSE_SELECTED) {
+ if (operation_cb(C, event, te, tselem)) {
+ success = true;
+ }
+ }
+ }
- return success;
+ return success;
}
-static bool scene_cb(bContext *C, eOutliner_PropSceneOps event, TreeElement *UNUSED(te), TreeStoreElem *tselem)
+static bool scene_cb(bContext *C,
+ eOutliner_PropSceneOps event,
+ TreeElement *UNUSED(te),
+ TreeStoreElem *tselem)
{
- Scene *scene = (Scene *)tselem->id;
+ Scene *scene = (Scene *)tselem->id;
- if (event == OL_SCENE_OP_DELETE) {
- if (ED_scene_delete(C, CTX_data_main(C), CTX_wm_window(C), scene)) {
- WM_event_add_notifier(C, NC_SCENE | NA_REMOVED, scene);
- }
- else {
- return false;
- }
- }
+ if (event == OL_SCENE_OP_DELETE) {
+ if (ED_scene_delete(C, CTX_data_main(C), CTX_wm_window(C), scene)) {
+ WM_event_add_notifier(C, NC_SCENE | NA_REMOVED, scene);
+ }
+ else {
+ return false;
+ }
+ }
- return true;
+ return true;
}
static int outliner_scene_operation_exec(bContext *C, wmOperator *op)
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- const eOutliner_PropSceneOps event = RNA_enum_get(op->ptr, "type");
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ const eOutliner_PropSceneOps event = RNA_enum_get(op->ptr, "type");
- if (outliner_do_scene_operation(C, event, &soops->tree, scene_cb) == false) {
- return OPERATOR_CANCELLED;
- }
+ if (outliner_do_scene_operation(C, event, &soops->tree, scene_cb) == false) {
+ return OPERATOR_CANCELLED;
+ }
- if (event == OL_SCENE_OP_DELETE) {
- outliner_cleanup_tree(soops);
- ED_undo_push(C, "Delete Scene(s)");
- }
- else {
- BLI_assert(0);
- return OPERATOR_CANCELLED;
- }
+ if (event == OL_SCENE_OP_DELETE) {
+ outliner_cleanup_tree(soops);
+ ED_undo_push(C, "Delete Scene(s)");
+ }
+ else {
+ BLI_assert(0);
+ return OPERATOR_CANCELLED;
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_scene_operation(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Outliner Scene Operation";
- ot->idname = "OUTLINER_OT_scene_operation";
- ot->description = "Context menu for scene operations";
+ /* identifiers */
+ ot->name = "Outliner Scene Operation";
+ ot->idname = "OUTLINER_OT_scene_operation";
+ ot->description = "Context menu for scene operations";
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = outliner_scene_operation_exec;
- ot->poll = ED_operator_outliner_active;
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = outliner_scene_operation_exec;
+ ot->poll = ED_operator_outliner_active;
- ot->flag = 0;
+ ot->flag = 0;
- ot->prop = RNA_def_enum(ot->srna, "type", prop_scene_op_types, 0, "Scene Operation", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_scene_op_types, 0, "Scene Operation", "");
}
/* ******************************************** */
-static void object_select_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = (Object *)tselem->id;
- Base *base = BKE_view_layer_base_find(view_layer, ob);
-
- if (base && ((base->flag & BASE_VISIBLE) != 0)) {
- base->flag |= BASE_SELECTED;
- }
-}
-
-static void object_select_hierarchy_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *te,
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- /* Don't extend because this toggles, which is nice for Ctrl-Click but not for a menu item.
- * it's especially confusing when multiple items are selected since some toggle on/off. */
- outliner_item_do_activate_from_tree_element(C, te, tselem, false, true);
-}
-
-static void object_deselect_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = (Object *)tselem->id;
- Base *base = BKE_view_layer_base_find(view_layer, ob);
-
- if (base) {
- base->flag &= ~BASE_SELECTED;
- }
-}
-
-static void object_delete_cb(
- bContext *C, ReportList *reports, Scene *scene, TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Object *ob = (Object *)tselem->id;
- if (ob) {
- Main *bmain = CTX_data_main(C);
- if (ob->id.tag & LIB_TAG_INDIRECT) {
- BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", ob->id.name + 2);
- return;
- }
- else if (BKE_library_ID_is_indirectly_used(bmain, ob) &&
- ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0)
- {
- BKE_reportf(reports, RPT_WARNING,
- "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
- ob->id.name + 2, scene->id.name + 2);
- return;
- }
-
- // check also library later
- if (ob == CTX_data_edit_object(C)) {
- ED_object_editmode_exit(C, EM_FREEDATA);
- }
- ED_object_base_free_and_unlink(CTX_data_main(C), scene, ob);
- /* leave for ED_outliner_id_unref to handle */
+static void object_select_cb(bContext *C,
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = (Object *)tselem->id;
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+
+ if (base && ((base->flag & BASE_VISIBLE) != 0)) {
+ base->flag |= BASE_SELECTED;
+ }
+}
+
+static void object_select_hierarchy_cb(bContext *C,
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *te,
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
+{
+ /* Don't extend because this toggles, which is nice for Ctrl-Click but not for a menu item.
+ * it's especially confusing when multiple items are selected since some toggle on/off. */
+ outliner_item_do_activate_from_tree_element(C, te, tselem, false, true);
+}
+
+static void object_deselect_cb(bContext *C,
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = (Object *)tselem->id;
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+
+ if (base) {
+ base->flag &= ~BASE_SELECTED;
+ }
+}
+
+static void object_delete_cb(bContext *C,
+ ReportList *reports,
+ Scene *scene,
+ TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
+{
+ Object *ob = (Object *)tselem->id;
+ if (ob) {
+ Main *bmain = CTX_data_main(C);
+ if (ob->id.tag & LIB_TAG_INDIRECT) {
+ BKE_reportf(
+ reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", ob->id.name + 2);
+ return;
+ }
+ else if (BKE_library_ID_is_indirectly_used(bmain, ob) && ID_REAL_USERS(ob) <= 1 &&
+ ID_EXTRA_USERS(ob) == 0) {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Cannot delete object '%s' from scene '%s', indirectly used objects need at "
+ "least one user",
+ ob->id.name + 2,
+ scene->id.name + 2);
+ return;
+ }
+
+ // check also library later
+ if (ob == CTX_data_edit_object(C)) {
+ ED_object_editmode_exit(C, EM_FREEDATA);
+ }
+ ED_object_base_free_and_unlink(CTX_data_main(C), scene, ob);
+ /* leave for ED_outliner_id_unref to handle */
#if 0
- te->directdata = NULL;
- tselem->id = NULL;
+ te->directdata = NULL;
+ tselem->id = NULL;
#endif
- }
+ }
}
-static void id_local_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
+static void id_local_cb(bContext *C,
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
{
- if (ID_IS_LINKED(tselem->id) && (tselem->id->tag & LIB_TAG_EXTERN)) {
- 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);
- }
- else {
- BKE_main_id_clear_newpoins(bmain);
- }
- }
+ if (ID_IS_LINKED(tselem->id) && (tselem->id->tag & LIB_TAG_EXTERN)) {
+ 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);
+ }
+ else {
+ BKE_main_id_clear_newpoins(bmain);
+ }
+ }
}
-static void id_static_override_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
+static void id_static_override_cb(bContext *C,
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
{
- if (ID_IS_LINKED(tselem->id) && (tselem->id->tag & LIB_TAG_EXTERN)) {
- Main *bmain = CTX_data_main(C);
- ID *override_id = BKE_override_static_create_from_id(bmain, tselem->id);
- if (override_id != NULL) {
- BKE_main_id_clear_newpoins(bmain);
- }
- }
+ if (ID_IS_LINKED(tselem->id) && (tselem->id->tag & LIB_TAG_EXTERN)) {
+ Main *bmain = CTX_data_main(C);
+ ID *override_id = BKE_override_static_create_from_id(bmain, tselem->id);
+ if (override_id != NULL) {
+ BKE_main_id_clear_newpoins(bmain);
+ }
+ }
}
-static void id_fake_user_set_cb(
- bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
+static void id_fake_user_set_cb(bContext *UNUSED(C),
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
{
- ID *id = tselem->id;
+ ID *id = tselem->id;
- id_fake_user_set(id);
+ id_fake_user_set(id);
}
-static void id_fake_user_clear_cb(
- bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
+static void id_fake_user_clear_cb(bContext *UNUSED(C),
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
{
- ID *id = tselem->id;
+ ID *id = tselem->id;
- id_fake_user_clear(id);
+ id_fake_user_clear(id);
}
-static void id_select_linked_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
+static void id_select_linked_cb(bContext *C,
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
{
- ID *id = tselem->id;
+ ID *id = tselem->id;
- ED_object_select_linked_by_id(C, id);
+ ED_object_select_linked_by_id(C, id);
}
-static void singleuser_action_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
- TreeStoreElem *tsep, TreeStoreElem *tselem, void *UNUSED(user_data))
+static void singleuser_action_cb(bContext *C,
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *tsep,
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
{
- ID *id = tselem->id;
+ ID *id = tselem->id;
- if (id) {
- IdAdtTemplate *iat = (IdAdtTemplate *)tsep->id;
- PointerRNA ptr = {{NULL}};
- PropertyRNA *prop;
+ if (id) {
+ IdAdtTemplate *iat = (IdAdtTemplate *)tsep->id;
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop;
- RNA_pointer_create(&iat->id, &RNA_AnimData, iat->adt, &ptr);
- prop = RNA_struct_find_property(&ptr, "action");
+ RNA_pointer_create(&iat->id, &RNA_AnimData, iat->adt, &ptr);
+ prop = RNA_struct_find_property(&ptr, "action");
- id_single_user(C, id, &ptr, prop);
- }
+ id_single_user(C, id, &ptr, prop);
+ }
}
-static void singleuser_world_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
- TreeStoreElem *tsep, TreeStoreElem *tselem, void *UNUSED(user_data))
+static void singleuser_world_cb(bContext *C,
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *tsep,
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
{
- ID *id = tselem->id;
+ ID *id = tselem->id;
- /* need to use parent scene not just scene, otherwise may end up getting wrong one */
- if (id) {
- Scene *parscene = (Scene *)tsep->id;
- PointerRNA ptr = {{NULL}};
- PropertyRNA *prop;
+ /* need to use parent scene not just scene, otherwise may end up getting wrong one */
+ if (id) {
+ Scene *parscene = (Scene *)tsep->id;
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop;
- RNA_id_pointer_create(&parscene->id, &ptr);
- prop = RNA_struct_find_property(&ptr, "world");
+ RNA_id_pointer_create(&parscene->id, &ptr);
+ prop = RNA_struct_find_property(&ptr, "world");
- id_single_user(C, id, &ptr, prop);
- }
+ id_single_user(C, id, &ptr, prop);
+ }
}
/**
* \param select_recurse: Set to false for operations which are already recursively operating on their children.
*/
-void outliner_do_object_operation_ex(
- bContext *C, ReportList *reports, Scene *scene_act, SpaceOutliner *soops, ListBase *lb,
- outliner_operation_cb operation_cb, void *user_data, bool select_recurse)
-{
- TreeElement *te;
-
- for (te = lb->first; te; te = te->next) {
- TreeStoreElem *tselem = TREESTORE(te);
- bool select_handled = false;
- 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);
- if (scene_owner && scene_act != scene_owner) {
- WM_window_set_active_scene(CTX_data_main(C), C, CTX_wm_window(C), scene_owner);
- }
- /* important to use 'scene_owner' not scene_act else deleting objects can crash.
- * only use 'scene_act' when 'scene_owner' is NULL, which can happen when the
- * outliner isn't showing scenes: Visible Layer draw mode for eg. */
- operation_cb(C, reports, scene_owner ? scene_owner : scene_act, te, NULL, tselem, user_data);
- select_handled = true;
- }
- }
- if (TSELEM_OPEN(tselem, soops)) {
- if ((select_handled == false) || select_recurse) {
- outliner_do_object_operation_ex(
- C, reports, scene_act, soops, &te->subtree, operation_cb, NULL, select_recurse);
- }
- }
- }
-}
-
-void outliner_do_object_operation(
- bContext *C, ReportList *reports, Scene *scene_act, SpaceOutliner *soops, ListBase *lb,
- outliner_operation_cb operation_cb)
-{
- outliner_do_object_operation_ex(C, reports, scene_act, soops, lb, operation_cb, NULL, true);
+void outliner_do_object_operation_ex(bContext *C,
+ ReportList *reports,
+ Scene *scene_act,
+ SpaceOutliner *soops,
+ ListBase *lb,
+ outliner_operation_cb operation_cb,
+ void *user_data,
+ bool select_recurse)
+{
+ TreeElement *te;
+
+ for (te = lb->first; te; te = te->next) {
+ TreeStoreElem *tselem = TREESTORE(te);
+ bool select_handled = false;
+ 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);
+ if (scene_owner && scene_act != scene_owner) {
+ WM_window_set_active_scene(CTX_data_main(C), C, CTX_wm_window(C), scene_owner);
+ }
+ /* important to use 'scene_owner' not scene_act else deleting objects can crash.
+ * only use 'scene_act' when 'scene_owner' is NULL, which can happen when the
+ * outliner isn't showing scenes: Visible Layer draw mode for eg. */
+ operation_cb(
+ C, reports, scene_owner ? scene_owner : scene_act, te, NULL, tselem, user_data);
+ select_handled = true;
+ }
+ }
+ if (TSELEM_OPEN(tselem, soops)) {
+ if ((select_handled == false) || select_recurse) {
+ outliner_do_object_operation_ex(
+ C, reports, scene_act, soops, &te->subtree, operation_cb, NULL, select_recurse);
+ }
+ }
+ }
+}
+
+void outliner_do_object_operation(bContext *C,
+ ReportList *reports,
+ Scene *scene_act,
+ SpaceOutliner *soops,
+ ListBase *lb,
+ outliner_operation_cb operation_cb)
+{
+ outliner_do_object_operation_ex(C, reports, scene_act, soops, lb, operation_cb, NULL, true);
}
/* ******************************************** */
-static void clear_animdata_cb(int UNUSED(event), TreeElement *UNUSED(te),
- TreeStoreElem *tselem, void *UNUSED(arg))
+static void clear_animdata_cb(int UNUSED(event),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *tselem,
+ void *UNUSED(arg))
{
- BKE_animdata_free(tselem->id, true);
+ BKE_animdata_free(tselem->id, true);
}
-
-static void unlinkact_animdata_cb(int UNUSED(event), TreeElement *UNUSED(te),
- TreeStoreElem *tselem, void *UNUSED(arg))
+static void unlinkact_animdata_cb(int UNUSED(event),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *tselem,
+ void *UNUSED(arg))
{
- /* just set action to NULL */
- BKE_animdata_set_action(NULL, tselem->id, NULL);
+ /* just set action to NULL */
+ BKE_animdata_set_action(NULL, tselem->id, NULL);
}
-static void cleardrivers_animdata_cb(int UNUSED(event), TreeElement *UNUSED(te),
- TreeStoreElem *tselem, void *UNUSED(arg))
+static void cleardrivers_animdata_cb(int UNUSED(event),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *tselem,
+ void *UNUSED(arg))
{
- IdAdtTemplate *iat = (IdAdtTemplate *)tselem->id;
+ IdAdtTemplate *iat = (IdAdtTemplate *)tselem->id;
- /* just free drivers - stored as a list of F-Curves */
- free_fcurves(&iat->adt->drivers);
+ /* just free drivers - stored as a list of F-Curves */
+ free_fcurves(&iat->adt->drivers);
}
-static void refreshdrivers_animdata_cb(int UNUSED(event), TreeElement *UNUSED(te),
- TreeStoreElem *tselem, void *UNUSED(arg))
+static void refreshdrivers_animdata_cb(int UNUSED(event),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *tselem,
+ void *UNUSED(arg))
{
- IdAdtTemplate *iat = (IdAdtTemplate *)tselem->id;
- FCurve *fcu;
+ IdAdtTemplate *iat = (IdAdtTemplate *)tselem->id;
+ FCurve *fcu;
- /* loop over drivers, performing refresh (i.e. check graph_buttons.c and rna_fcurve.c for details) */
- for (fcu = iat->adt->drivers.first; fcu; fcu = fcu->next) {
- fcu->flag &= ~FCURVE_DISABLED;
+ /* loop over drivers, performing refresh (i.e. check graph_buttons.c and rna_fcurve.c for details) */
+ for (fcu = iat->adt->drivers.first; fcu; fcu = fcu->next) {
+ fcu->flag &= ~FCURVE_DISABLED;
- if (fcu->driver) {
- fcu->driver->flag &= ~DRIVER_FLAG_INVALID;
- }
- }
+ if (fcu->driver) {
+ fcu->driver->flag &= ~DRIVER_FLAG_INVALID;
+ }
+ }
}
/* --------------------------------- */
typedef enum eOutliner_PropDataOps {
- OL_DOP_SELECT = 1,
- OL_DOP_DESELECT,
- OL_DOP_HIDE,
- OL_DOP_UNHIDE,
- OL_DOP_SELECT_LINKED,
+ OL_DOP_SELECT = 1,
+ OL_DOP_DESELECT,
+ OL_DOP_HIDE,
+ OL_DOP_UNHIDE,
+ OL_DOP_SELECT_LINKED,
} eOutliner_PropDataOps;
typedef enum eOutliner_PropConstraintOps {
- OL_CONSTRAINTOP_ENABLE = 1,
- OL_CONSTRAINTOP_DISABLE,
- OL_CONSTRAINTOP_DELETE,
+ OL_CONSTRAINTOP_ENABLE = 1,
+ OL_CONSTRAINTOP_DISABLE,
+ OL_CONSTRAINTOP_DELETE,
} eOutliner_PropConstraintOps;
typedef enum eOutliner_PropModifierOps {
- OL_MODIFIER_OP_TOGVIS = 1,
- OL_MODIFIER_OP_TOGREN,
- OL_MODIFIER_OP_DELETE,
+ OL_MODIFIER_OP_TOGVIS = 1,
+ OL_MODIFIER_OP_TOGREN,
+ OL_MODIFIER_OP_DELETE,
} eOutliner_PropModifierOps;
static void pchan_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *UNUSED(arg))
{
- bPoseChannel *pchan = (bPoseChannel *)te->directdata;
+ bPoseChannel *pchan = (bPoseChannel *)te->directdata;
- if (event == OL_DOP_SELECT) {
- pchan->bone->flag |= BONE_SELECTED;
- }
- else if (event == OL_DOP_DESELECT) {
- pchan->bone->flag &= ~BONE_SELECTED;
- }
- else if (event == OL_DOP_HIDE) {
- pchan->bone->flag |= BONE_HIDDEN_P;
- pchan->bone->flag &= ~BONE_SELECTED;
- }
- else if (event == OL_DOP_UNHIDE) {
- pchan->bone->flag &= ~BONE_HIDDEN_P;
- }
+ if (event == OL_DOP_SELECT) {
+ pchan->bone->flag |= BONE_SELECTED;
+ }
+ else if (event == OL_DOP_DESELECT) {
+ pchan->bone->flag &= ~BONE_SELECTED;
+ }
+ else if (event == OL_DOP_HIDE) {
+ pchan->bone->flag |= BONE_HIDDEN_P;
+ pchan->bone->flag &= ~BONE_SELECTED;
+ }
+ else if (event == OL_DOP_UNHIDE) {
+ pchan->bone->flag &= ~BONE_HIDDEN_P;
+ }
}
static void bone_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *UNUSED(arg))
{
- Bone *bone = (Bone *)te->directdata;
+ Bone *bone = (Bone *)te->directdata;
- if (event == OL_DOP_SELECT) {
- bone->flag |= BONE_SELECTED;
- }
- else if (event == OL_DOP_DESELECT) {
- bone->flag &= ~BONE_SELECTED;
- }
- else if (event == OL_DOP_HIDE) {
- bone->flag |= BONE_HIDDEN_P;
- bone->flag &= ~BONE_SELECTED;
- }
- else if (event == OL_DOP_UNHIDE) {
- bone->flag &= ~BONE_HIDDEN_P;
- }
+ if (event == OL_DOP_SELECT) {
+ bone->flag |= BONE_SELECTED;
+ }
+ else if (event == OL_DOP_DESELECT) {
+ bone->flag &= ~BONE_SELECTED;
+ }
+ else if (event == OL_DOP_HIDE) {
+ bone->flag |= BONE_HIDDEN_P;
+ bone->flag &= ~BONE_SELECTED;
+ }
+ else if (event == OL_DOP_UNHIDE) {
+ bone->flag &= ~BONE_HIDDEN_P;
+ }
}
static void ebone_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *UNUSED(arg))
{
- EditBone *ebone = (EditBone *)te->directdata;
+ EditBone *ebone = (EditBone *)te->directdata;
- if (event == OL_DOP_SELECT) {
- ebone->flag |= BONE_SELECTED;
- }
- else if (event == OL_DOP_DESELECT) {
- ebone->flag &= ~BONE_SELECTED;
- }
- else if (event == OL_DOP_HIDE) {
- ebone->flag |= BONE_HIDDEN_A;
- ebone->flag &= ~BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL;
- }
- else if (event == OL_DOP_UNHIDE) {
- ebone->flag &= ~BONE_HIDDEN_A;
- }
+ if (event == OL_DOP_SELECT) {
+ ebone->flag |= BONE_SELECTED;
+ }
+ else if (event == OL_DOP_DESELECT) {
+ ebone->flag &= ~BONE_SELECTED;
+ }
+ else if (event == OL_DOP_HIDE) {
+ ebone->flag |= BONE_HIDDEN_A;
+ ebone->flag &= ~BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL;
+ }
+ else if (event == OL_DOP_UNHIDE) {
+ ebone->flag &= ~BONE_HIDDEN_A;
+ }
}
static void sequence_cb(int event, TreeElement *te, TreeStoreElem *tselem, void *scene_ptr)
{
- Sequence *seq = (Sequence *)te->directdata;
- if (event == OL_DOP_SELECT) {
- Scene *scene = (Scene *)scene_ptr;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- if (BLI_findindex(ed->seqbasep, seq) != -1) {
- ED_sequencer_select_sequence_single(scene, seq, true);
- }
- }
+ Sequence *seq = (Sequence *)te->directdata;
+ if (event == OL_DOP_SELECT) {
+ Scene *scene = (Scene *)scene_ptr;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ if (BLI_findindex(ed->seqbasep, seq) != -1) {
+ ED_sequencer_select_sequence_single(scene, seq, true);
+ }
+ }
- (void)tselem;
+ (void)tselem;
}
-static void gp_layer_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *UNUSED(arg))
+static void gp_layer_cb(int event,
+ TreeElement *te,
+ TreeStoreElem *UNUSED(tselem),
+ void *UNUSED(arg))
{
- bGPDlayer *gpl = (bGPDlayer *)te->directdata;
+ bGPDlayer *gpl = (bGPDlayer *)te->directdata;
- if (event == OL_DOP_SELECT) {
- gpl->flag |= GP_LAYER_SELECT;
- }
- else if (event == OL_DOP_DESELECT) {
- gpl->flag &= ~GP_LAYER_SELECT;
- }
- else if (event == OL_DOP_HIDE) {
- gpl->flag |= GP_LAYER_HIDE;
- }
- else if (event == OL_DOP_UNHIDE) {
- gpl->flag &= ~GP_LAYER_HIDE;
- }
+ if (event == OL_DOP_SELECT) {
+ gpl->flag |= GP_LAYER_SELECT;
+ }
+ else if (event == OL_DOP_DESELECT) {
+ gpl->flag &= ~GP_LAYER_SELECT;
+ }
+ else if (event == OL_DOP_HIDE) {
+ gpl->flag |= GP_LAYER_HIDE;
+ }
+ else if (event == OL_DOP_UNHIDE) {
+ gpl->flag &= ~GP_LAYER_HIDE;
+ }
}
-static void data_select_linked_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *C_v)
+static void data_select_linked_cb(int event,
+ TreeElement *te,
+ TreeStoreElem *UNUSED(tselem),
+ void *C_v)
{
- if (event == OL_DOP_SELECT_LINKED) {
- if (RNA_struct_is_ID(te->rnaptr.type)) {
- bContext *C = (bContext *) C_v;
- ID *id = te->rnaptr.data;
+ if (event == OL_DOP_SELECT_LINKED) {
+ if (RNA_struct_is_ID(te->rnaptr.type)) {
+ bContext *C = (bContext *)C_v;
+ ID *id = te->rnaptr.data;
- ED_object_select_linked_by_id(C, id);
- }
- }
+ ED_object_select_linked_by_id(C, id);
+ }
+ }
}
static void constraint_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *C_v)
{
- 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);
-
- if (event == OL_CONSTRAINTOP_ENABLE) {
- constraint->flag &= ~CONSTRAINT_OFF;
- ED_object_constraint_update(bmain, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
- }
- else if (event == OL_CONSTRAINTOP_DISABLE) {
- constraint->flag = CONSTRAINT_OFF;
- ED_object_constraint_update(bmain, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
- }
- else if (event == OL_CONSTRAINTOP_DELETE) {
- ListBase *lb = NULL;
-
- if (TREESTORE(te->parent->parent)->type == TSE_POSE_CHANNEL) {
- lb = &((bPoseChannel *)te->parent->parent->directdata)->constraints;
- }
- else {
- lb = &ob->constraints;
- }
-
- if (BKE_constraint_remove_ex(lb, ob, constraint, true)) {
- /* there's no active constraint now, so make sure this is the case */
- BKE_constraints_active_set(&ob->constraints, NULL);
-
- /* needed to set the flags on posebones correctly */
- ED_object_constraint_update(bmain, ob);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
- te->store_elem->flag &= ~TSE_SELECTED;
- }
- }
+ 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);
+
+ if (event == OL_CONSTRAINTOP_ENABLE) {
+ constraint->flag &= ~CONSTRAINT_OFF;
+ ED_object_constraint_update(bmain, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ }
+ else if (event == OL_CONSTRAINTOP_DISABLE) {
+ constraint->flag = CONSTRAINT_OFF;
+ ED_object_constraint_update(bmain, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ }
+ else if (event == OL_CONSTRAINTOP_DELETE) {
+ ListBase *lb = NULL;
+
+ if (TREESTORE(te->parent->parent)->type == TSE_POSE_CHANNEL) {
+ lb = &((bPoseChannel *)te->parent->parent->directdata)->constraints;
+ }
+ else {
+ lb = &ob->constraints;
+ }
+
+ if (BKE_constraint_remove_ex(lb, ob, constraint, true)) {
+ /* there's no active constraint now, so make sure this is the case */
+ BKE_constraints_active_set(&ob->constraints, NULL);
+
+ /* needed to set the flags on posebones correctly */
+ ED_object_constraint_update(bmain, ob);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
+ te->store_elem->flag &= ~TSE_SELECTED;
+ }
+ }
}
static void modifier_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *Carg)
{
- 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);
-
- if (event == OL_MODIFIER_OP_TOGVIS) {
- md->mode ^= eModifierMode_Realtime;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- }
- else if (event == OL_MODIFIER_OP_TOGREN) {
- md->mode ^= eModifierMode_Render;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- }
- else if (event == OL_MODIFIER_OP_DELETE) {
- ED_object_modifier_remove(NULL, bmain, ob, md);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER | NA_REMOVED, ob);
- te->store_elem->flag &= ~TSE_SELECTED;
- }
-}
-
-static void outliner_do_data_operation(SpaceOutliner *soops, int type, int event, ListBase *lb,
- void (*operation_cb)(int, TreeElement *, TreeStoreElem *, void *),
- void *arg)
-{
- TreeElement *te;
- TreeStoreElem *tselem;
-
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
- if (tselem->flag & TSE_SELECTED) {
- if (tselem->type == type) {
- operation_cb(event, te, tselem, arg);
- }
- }
- if (TSELEM_OPEN(tselem, soops)) {
- outliner_do_data_operation(soops, type, event, &te->subtree, operation_cb, arg);
- }
- }
+ 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);
+
+ if (event == OL_MODIFIER_OP_TOGVIS) {
+ md->mode ^= eModifierMode_Realtime;
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ }
+ else if (event == OL_MODIFIER_OP_TOGREN) {
+ md->mode ^= eModifierMode_Render;
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ }
+ else if (event == OL_MODIFIER_OP_DELETE) {
+ ED_object_modifier_remove(NULL, bmain, ob, md);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER | NA_REMOVED, ob);
+ te->store_elem->flag &= ~TSE_SELECTED;
+ }
+}
+
+static void outliner_do_data_operation(
+ SpaceOutliner *soops,
+ int type,
+ int event,
+ ListBase *lb,
+ void (*operation_cb)(int, TreeElement *, TreeStoreElem *, void *),
+ void *arg)
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for (te = lb->first; te; te = te->next) {
+ tselem = TREESTORE(te);
+ if (tselem->flag & TSE_SELECTED) {
+ if (tselem->type == type) {
+ operation_cb(event, te, tselem, arg);
+ }
+ }
+ if (TSELEM_OPEN(tselem, soops)) {
+ outliner_do_data_operation(soops, type, event, &te->subtree, operation_cb, arg);
+ }
+ }
}
static Base *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *scene, Base *base)
{
- Base *child_base, *base_next;
- Object *parent;
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- if (!base) {
- return NULL;
- }
-
- for (child_base = view_layer->object_bases.first; child_base; child_base = base_next) {
- base_next = child_base->next;
- for (parent = child_base->object->parent; parent && (parent != base->object); parent = parent->parent) {
- /* pass */
- }
- if (parent) {
- base_next = outline_delete_hierarchy(C, reports, scene, child_base);
- }
- }
-
- base_next = base->next;
-
- Main *bmain = CTX_data_main(C);
- if (base->object->id.tag & LIB_TAG_INDIRECT) {
- BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", base->object->id.name + 2);
- return base_next;
- }
- else if (BKE_library_ID_is_indirectly_used(bmain, base->object) &&
- ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0)
- {
- BKE_reportf(reports, RPT_WARNING,
- "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
- base->object->id.name + 2, scene->id.name + 2);
- return base_next;
- }
- ED_object_base_free_and_unlink(CTX_data_main(C), scene, base->object);
- return base_next;
-}
-
-static void object_delete_hierarchy_cb(
- bContext *C, ReportList *reports, Scene *scene,
- TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base = (Base *)te->directdata;
- Object *obedit = CTX_data_edit_object(C);
-
- if (!base) {
- base = BKE_view_layer_base_find(view_layer, (Object *)tselem->id);
- }
- if (base) {
- /* Check also library later. */
- for (; obedit && (obedit != base->object); obedit = obedit->parent) {
- /* pass */
- }
- if (obedit == base->object) {
- ED_object_editmode_exit(C, EM_FREEDATA);
- }
-
- outline_delete_hierarchy(C, reports, scene, base);
- /* leave for ED_outliner_id_unref to handle */
+ Base *child_base, *base_next;
+ Object *parent;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ if (!base) {
+ return NULL;
+ }
+
+ for (child_base = view_layer->object_bases.first; child_base; child_base = base_next) {
+ base_next = child_base->next;
+ for (parent = child_base->object->parent; parent && (parent != base->object);
+ parent = parent->parent) {
+ /* pass */
+ }
+ if (parent) {
+ base_next = outline_delete_hierarchy(C, reports, scene, child_base);
+ }
+ }
+
+ base_next = base->next;
+
+ Main *bmain = CTX_data_main(C);
+ if (base->object->id.tag & LIB_TAG_INDIRECT) {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Cannot delete indirectly linked object '%s'",
+ base->object->id.name + 2);
+ return base_next;
+ }
+ else if (BKE_library_ID_is_indirectly_used(bmain, base->object) &&
+ ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Cannot delete object '%s' from scene '%s', indirectly used objects need at least "
+ "one user",
+ base->object->id.name + 2,
+ scene->id.name + 2);
+ return base_next;
+ }
+ ED_object_base_free_and_unlink(CTX_data_main(C), scene, base->object);
+ return base_next;
+}
+
+static void object_delete_hierarchy_cb(bContext *C,
+ ReportList *reports,
+ Scene *scene,
+ TreeElement *te,
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base = (Base *)te->directdata;
+ Object *obedit = CTX_data_edit_object(C);
+
+ if (!base) {
+ base = BKE_view_layer_base_find(view_layer, (Object *)tselem->id);
+ }
+ if (base) {
+ /* Check also library later. */
+ for (; obedit && (obedit != base->object); obedit = obedit->parent) {
+ /* pass */
+ }
+ if (obedit == base->object) {
+ ED_object_editmode_exit(C, EM_FREEDATA);
+ }
+
+ outline_delete_hierarchy(C, reports, scene, base);
+ /* leave for ED_outliner_id_unref to handle */
#if 0
- te->directdata = NULL;
- tselem->id = NULL;
+ te->directdata = NULL;
+ tselem->id = NULL;
#endif
- }
+ }
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
}
static Base *outline_batch_delete_hierarchy(
- ReportList *reports, Main *bmain, ViewLayer *view_layer, Scene *scene, Base *base)
-{
- Base *child_base, *base_next;
- Object *object, *parent;
-
- if (!base) {
- return NULL;
- }
-
- object = base->object;
- for (child_base = view_layer->object_bases.first; child_base; child_base = base_next) {
- base_next = child_base->next;
- for (parent = child_base->object->parent; parent && (parent != object); parent = parent->parent) {
- /* pass */
- }
- if (parent) {
- base_next = outline_batch_delete_hierarchy(reports, bmain, view_layer, scene, child_base);
- }
- }
-
- base_next = base->next;
-
- if (object->id.tag & LIB_TAG_INDIRECT) {
- BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", base->object->id.name + 2);
- return base_next;
- }
- else if (BKE_library_ID_is_indirectly_used(bmain, object) &&
- ID_REAL_USERS(object) <= 1 && ID_EXTRA_USERS(object) == 0)
- {
- BKE_reportf(reports, RPT_WARNING,
- "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
- object->id.name + 2, scene->id.name + 2);
- return base_next;
- }
-
- DEG_id_tag_update_ex(bmain, &object->id, ID_RECALC_BASE_FLAGS);
- BKE_scene_collections_object_remove(bmain, scene, object, false);
-
- if (object->id.us == 0) {
- object->id.tag |= LIB_TAG_DOIT;
- }
-
- return base_next;
-}
-
-static void object_batch_delete_hierarchy_cb(
- bContext *C, ReportList *reports, Scene *scene,
- TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base = (Base *)te->directdata;
- Object *obedit = CTX_data_edit_object(C);
-
- if (!base) {
- base = BKE_view_layer_base_find(view_layer, (Object *)tselem->id);
- }
- if (base) {
- /* Check also library later. */
- for (; obedit && (obedit != base->object); obedit = obedit->parent) {
- /* pass */
- }
- if (obedit == base->object) {
- ED_object_editmode_exit(C, EM_FREEDATA);
- }
-
- outline_batch_delete_hierarchy(reports, CTX_data_main(C), view_layer, scene, base);
- /* leave for ED_outliner_id_unref to handle */
+ ReportList *reports, Main *bmain, ViewLayer *view_layer, Scene *scene, Base *base)
+{
+ Base *child_base, *base_next;
+ Object *object, *parent;
+
+ if (!base) {
+ return NULL;
+ }
+
+ object = base->object;
+ for (child_base = view_layer->object_bases.first; child_base; child_base = base_next) {
+ base_next = child_base->next;
+ for (parent = child_base->object->parent; parent && (parent != object);
+ parent = parent->parent) {
+ /* pass */
+ }
+ if (parent) {
+ base_next = outline_batch_delete_hierarchy(reports, bmain, view_layer, scene, child_base);
+ }
+ }
+
+ base_next = base->next;
+
+ if (object->id.tag & LIB_TAG_INDIRECT) {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Cannot delete indirectly linked object '%s'",
+ base->object->id.name + 2);
+ return base_next;
+ }
+ else if (BKE_library_ID_is_indirectly_used(bmain, object) && ID_REAL_USERS(object) <= 1 &&
+ ID_EXTRA_USERS(object) == 0) {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Cannot delete object '%s' from scene '%s', indirectly used objects need at least "
+ "one user",
+ object->id.name + 2,
+ scene->id.name + 2);
+ return base_next;
+ }
+
+ DEG_id_tag_update_ex(bmain, &object->id, ID_RECALC_BASE_FLAGS);
+ BKE_scene_collections_object_remove(bmain, scene, object, false);
+
+ if (object->id.us == 0) {
+ object->id.tag |= LIB_TAG_DOIT;
+ }
+
+ return base_next;
+}
+
+static void object_batch_delete_hierarchy_cb(bContext *C,
+ ReportList *reports,
+ Scene *scene,
+ TreeElement *te,
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base = (Base *)te->directdata;
+ Object *obedit = CTX_data_edit_object(C);
+
+ if (!base) {
+ base = BKE_view_layer_base_find(view_layer, (Object *)tselem->id);
+ }
+ if (base) {
+ /* Check also library later. */
+ for (; obedit && (obedit != base->object); obedit = obedit->parent) {
+ /* pass */
+ }
+ if (obedit == base->object) {
+ ED_object_editmode_exit(C, EM_FREEDATA);
+ }
+
+ outline_batch_delete_hierarchy(reports, CTX_data_main(C), view_layer, scene, base);
+ /* leave for ED_outliner_id_unref to handle */
#if 0
- te->directdata = NULL;
- tselem->id = NULL;
+ te->directdata = NULL;
+ tselem->id = NULL;
#endif
- }
+ }
}
/* **************************************** */
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 */
- OL_OP_TOGVIS,
- OL_OP_TOGSEL,
- OL_OP_TOGREN,
- OL_OP_RENAME,
- OL_OP_OBJECT_MODE_ENTER,
- OL_OP_OBJECT_MODE_EXIT,
+ 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 */
+ OL_OP_TOGVIS,
+ OL_OP_TOGSEL,
+ OL_OP_TOGREN,
+ OL_OP_RENAME,
+ OL_OP_OBJECT_MODE_ENTER,
+ OL_OP_OBJECT_MODE_EXIT,
};
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", 0, "Remap Users",
- "Make all users of selected data-blocks to use instead a new chosen one"},
- {OL_OP_RENAME, "RENAME", 0, "Rename", ""},
- {OL_OP_OBJECT_MODE_ENTER, "OBJECT_MODE_ENTER", 0, "Enter Mode", ""},
- {OL_OP_OBJECT_MODE_EXIT, "OBJECT_MODE_EXIT", 0, "Exit Mode", ""},
- {0, NULL, 0, NULL, NULL},
+ {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",
+ 0,
+ "Remap Users",
+ "Make all users of selected data-blocks to use instead a new chosen one"},
+ {OL_OP_RENAME, "RENAME", 0, "Rename", ""},
+ {OL_OP_OBJECT_MODE_ENTER, "OBJECT_MODE_ENTER", 0, "Enter Mode", ""},
+ {OL_OP_OBJECT_MODE_EXIT, "OBJECT_MODE_EXIT", 0, "Exit Mode", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int outliner_object_operation_exec(bContext *C, wmOperator *op)
{
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- wmWindow *win = CTX_wm_window(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- int event;
- const char *str = NULL;
-
- /* check for invalid states */
- if (soops == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- event = RNA_enum_get(op->ptr, "type");
-
- if (event == OL_OP_SELECT) {
- Scene *sce = scene; // to be able to delete, scenes are set...
- outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_select_cb);
- if (scene != sce) {
- WM_window_set_active_scene(bmain, C, win, sce);
- }
-
- str = "Select 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_SELECT_HIERARCHY) {
- Scene *sce = scene; // to be able to delete, scenes are set...
- outliner_do_object_operation_ex(
- C, op->reports, scene, soops, &soops->tree, object_select_hierarchy_cb, NULL, false);
- if (scene != sce) {
- 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);
- }
- 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);
- }
- }
- else if (event == OL_OP_DELETE_HIERARCHY) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const Base *basact_prev = BASACT(view_layer);
-
- /* Keeping old 'safe and slow' code for a bit (new one enabled on 28/01/2019). */
- if (G.debug_value == 666) {
- outliner_do_object_operation_ex(
- C, op->reports, scene, soops, &soops->tree, object_delete_hierarchy_cb, NULL, false);
- }
- else {
- BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
-
- outliner_do_object_operation_ex(
- C, op->reports, scene, soops, &soops->tree, object_batch_delete_hierarchy_cb, NULL, false);
-
- BKE_id_multi_tagged_delete(bmain);
- }
-
- /* XXX: See OL_OP_DELETE comment above. */
- outliner_cleanup_tree(soops);
-
- DEG_relations_tag_update(bmain);
- str = "Delete Object Hierarchy";
- 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);
- }
- }
- else if (event == OL_OP_REMAP) {
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL);
- str = "Remap ID";
- }
- else if (event == OL_OP_LOCALIZED) { /* disabled, see above enum (ton) */
- outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, id_local_cb);
- str = "Localized Objects";
- }
- else if (event == OL_OP_RENAME) {
- outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb);
- str = "Rename Object";
- }
- else if (event == OL_OP_OBJECT_MODE_ENTER) {
- outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_object_mode_enter_cb);
- str = "Enter Current Mode";
- }
- else if (event == OL_OP_OBJECT_MODE_EXIT) {
- outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_object_mode_exit_cb);
- str = "Exit Current Mode";
- }
- else {
- BLI_assert(0);
- return OPERATOR_CANCELLED;
- }
-
- ED_undo_push(C, str);
-
- return OPERATOR_FINISHED;
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ wmWindow *win = CTX_wm_window(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ int event;
+ const char *str = NULL;
+
+ /* check for invalid states */
+ if (soops == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ event = RNA_enum_get(op->ptr, "type");
+
+ if (event == OL_OP_SELECT) {
+ Scene *sce = scene; // to be able to delete, scenes are set...
+ outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_select_cb);
+ if (scene != sce) {
+ WM_window_set_active_scene(bmain, C, win, sce);
+ }
+
+ str = "Select 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_SELECT_HIERARCHY) {
+ Scene *sce = scene; // to be able to delete, scenes are set...
+ outliner_do_object_operation_ex(
+ C, op->reports, scene, soops, &soops->tree, object_select_hierarchy_cb, NULL, false);
+ if (scene != sce) {
+ 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);
+ }
+ 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);
+ }
+ }
+ else if (event == OL_OP_DELETE_HIERARCHY) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const Base *basact_prev = BASACT(view_layer);
+
+ /* Keeping old 'safe and slow' code for a bit (new one enabled on 28/01/2019). */
+ if (G.debug_value == 666) {
+ outliner_do_object_operation_ex(
+ C, op->reports, scene, soops, &soops->tree, object_delete_hierarchy_cb, NULL, false);
+ }
+ else {
+ BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+
+ outliner_do_object_operation_ex(C,
+ op->reports,
+ scene,
+ soops,
+ &soops->tree,
+ object_batch_delete_hierarchy_cb,
+ NULL,
+ false);
+
+ BKE_id_multi_tagged_delete(bmain);
+ }
+
+ /* XXX: See OL_OP_DELETE comment above. */
+ outliner_cleanup_tree(soops);
+
+ DEG_relations_tag_update(bmain);
+ str = "Delete Object Hierarchy";
+ 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);
+ }
+ }
+ else if (event == OL_OP_REMAP) {
+ outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL);
+ str = "Remap ID";
+ }
+ else if (event == OL_OP_LOCALIZED) { /* disabled, see above enum (ton) */
+ outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, id_local_cb);
+ str = "Localized Objects";
+ }
+ else if (event == OL_OP_RENAME) {
+ outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb);
+ str = "Rename Object";
+ }
+ else if (event == OL_OP_OBJECT_MODE_ENTER) {
+ outliner_do_object_operation(
+ C, op->reports, scene, soops, &soops->tree, item_object_mode_enter_cb);
+ str = "Enter Current Mode";
+ }
+ else if (event == OL_OP_OBJECT_MODE_EXIT) {
+ outliner_do_object_operation(
+ C, op->reports, scene, soops, &soops->tree, item_object_mode_exit_cb);
+ str = "Exit Current Mode";
+ }
+ else {
+ BLI_assert(0);
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_undo_push(C, str);
+
+ return OPERATOR_FINISHED;
}
-
void OUTLINER_OT_object_operation(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Outliner Object Operation";
- ot->idname = "OUTLINER_OT_object_operation";
+ /* identifiers */
+ ot->name = "Outliner Object Operation";
+ ot->idname = "OUTLINER_OT_object_operation";
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = outliner_object_operation_exec;
- ot->poll = ED_operator_outliner_active;
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = outliner_object_operation_exec;
+ ot->poll = ED_operator_outliner_active;
- ot->flag = 0;
+ ot->flag = 0;
- ot->prop = RNA_def_enum(ot->srna, "type", prop_object_op_types, 0, "Object Operation", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_object_op_types, 0, "Object Operation", "");
}
/* **************************************** */
typedef enum eOutlinerIdOpTypes {
- OUTLINER_IDOP_INVALID = 0,
+ OUTLINER_IDOP_INVALID = 0,
- OUTLINER_IDOP_UNLINK,
- OUTLINER_IDOP_LOCAL,
- OUTLINER_IDOP_STATIC_OVERRIDE,
- OUTLINER_IDOP_SINGLE,
- OUTLINER_IDOP_DELETE,
- OUTLINER_IDOP_REMAP,
+ OUTLINER_IDOP_UNLINK,
+ OUTLINER_IDOP_LOCAL,
+ OUTLINER_IDOP_STATIC_OVERRIDE,
+ OUTLINER_IDOP_SINGLE,
+ OUTLINER_IDOP_DELETE,
+ OUTLINER_IDOP_REMAP,
- OUTLINER_IDOP_COPY,
- OUTLINER_IDOP_PASTE,
+ OUTLINER_IDOP_COPY,
+ OUTLINER_IDOP_PASTE,
- OUTLINER_IDOP_FAKE_ADD,
- OUTLINER_IDOP_FAKE_CLEAR,
- OUTLINER_IDOP_RENAME,
+ OUTLINER_IDOP_FAKE_ADD,
+ OUTLINER_IDOP_FAKE_CLEAR,
+ OUTLINER_IDOP_RENAME,
- OUTLINER_IDOP_SELECT_LINKED,
+ OUTLINER_IDOP_SELECT_LINKED,
} eOutlinerIdOpTypes;
// TODO: implement support for changing the ID-block used
static const EnumPropertyItem prop_id_op_types[] = {
- {OUTLINER_IDOP_UNLINK, "UNLINK", 0, "Unlink", ""},
- {OUTLINER_IDOP_LOCAL, "LOCAL", 0, "Make Local", ""},
- {OUTLINER_IDOP_STATIC_OVERRIDE, "STATIC_OVERRIDE", 0, "Add Static Override",
- "Add a local static override of this data-block"},
- {OUTLINER_IDOP_SINGLE, "SINGLE", 0, "Make Single User", ""},
- {OUTLINER_IDOP_DELETE, "DELETE", ICON_X, "Delete", ""},
- {OUTLINER_IDOP_REMAP, "REMAP", 0, "Remap Users",
- "Make all users of selected data-blocks to use instead current (clicked) one"},
- {0, "", 0, NULL, NULL},
- {OUTLINER_IDOP_COPY, "COPY", ICON_COPYDOWN, "Copy", ""},
- {OUTLINER_IDOP_PASTE, "PASTE", ICON_PASTEDOWN, "Paste", ""},
- {0, "", 0, NULL, NULL},
- {OUTLINER_IDOP_FAKE_ADD, "ADD_FAKE", 0, "Add Fake User",
- "Ensure data-block gets saved even if it isn't in use (e.g. for motion and material libraries)"},
- {OUTLINER_IDOP_FAKE_CLEAR, "CLEAR_FAKE", 0, "Clear Fake User", ""},
- {OUTLINER_IDOP_RENAME, "RENAME", 0, "Rename", ""},
- {OUTLINER_IDOP_SELECT_LINKED, "SELECT_LINKED", 0, "Select Linked", ""},
- {0, NULL, 0, NULL, NULL},
+ {OUTLINER_IDOP_UNLINK, "UNLINK", 0, "Unlink", ""},
+ {OUTLINER_IDOP_LOCAL, "LOCAL", 0, "Make Local", ""},
+ {OUTLINER_IDOP_STATIC_OVERRIDE,
+ "STATIC_OVERRIDE",
+ 0,
+ "Add Static Override",
+ "Add a local static override of this data-block"},
+ {OUTLINER_IDOP_SINGLE, "SINGLE", 0, "Make Single User", ""},
+ {OUTLINER_IDOP_DELETE, "DELETE", ICON_X, "Delete", ""},
+ {OUTLINER_IDOP_REMAP,
+ "REMAP",
+ 0,
+ "Remap Users",
+ "Make all users of selected data-blocks to use instead current (clicked) one"},
+ {0, "", 0, NULL, NULL},
+ {OUTLINER_IDOP_COPY, "COPY", ICON_COPYDOWN, "Copy", ""},
+ {OUTLINER_IDOP_PASTE, "PASTE", ICON_PASTEDOWN, "Paste", ""},
+ {0, "", 0, NULL, NULL},
+ {OUTLINER_IDOP_FAKE_ADD,
+ "ADD_FAKE",
+ 0,
+ "Add Fake User",
+ "Ensure data-block gets saved even if it isn't in use (e.g. for motion and material "
+ "libraries)"},
+ {OUTLINER_IDOP_FAKE_CLEAR, "CLEAR_FAKE", 0, "Clear Fake User", ""},
+ {OUTLINER_IDOP_RENAME, "RENAME", 0, "Rename", ""},
+ {OUTLINER_IDOP_SELECT_LINKED, "SELECT_LINKED", 0, "Select Linked", ""},
+ {0, NULL, 0, NULL, NULL},
};
-static const EnumPropertyItem *outliner_id_operation_itemf(
- bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *outliner_id_operation_itemf(bContext *UNUSED(C),
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- if (BKE_override_static_is_enabled()) {
- *r_free = false;
- return prop_id_op_types;
- }
+ if (BKE_override_static_is_enabled()) {
+ *r_free = false;
+ return prop_id_op_types;
+ }
- EnumPropertyItem *items = NULL;
- int totitem = 0;
+ EnumPropertyItem *items = NULL;
+ int totitem = 0;
- for (const EnumPropertyItem *it = prop_id_op_types; it->identifier != NULL; it++) {
- if (it->value == OUTLINER_IDOP_STATIC_OVERRIDE) {
- continue;
- }
- RNA_enum_item_add(&items, &totitem, it);
- }
- RNA_enum_item_end(&items, &totitem);
- *r_free = true;
+ for (const EnumPropertyItem *it = prop_id_op_types; it->identifier != NULL; it++) {
+ if (it->value == OUTLINER_IDOP_STATIC_OVERRIDE) {
+ continue;
+ }
+ RNA_enum_item_add(&items, &totitem, it);
+ }
+ RNA_enum_item_end(&items, &totitem);
+ *r_free = true;
- return items;
+ return items;
}
static int outliner_id_operation_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
- eOutlinerIdOpTypes event;
-
- /* check for invalid states */
- if (soops == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
-
- event = RNA_enum_get(op->ptr, "type");
-
- switch (event) {
- case OUTLINER_IDOP_UNLINK:
- {
- /* unlink datablock from its parent */
- if (objectlevel) {
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, unlink_object_cb, NULL);
-
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, NULL);
- ED_undo_push(C, "Unlink Object");
- break;
- }
-
- switch (idlevel) {
- case ID_AC:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, unlink_action_cb, NULL);
-
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
- ED_undo_push(C, "Unlink action");
- break;
- case ID_MA:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, unlink_material_cb, NULL);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, NULL);
- ED_undo_push(C, "Unlink material");
- break;
- case ID_TE:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, unlink_texture_cb, NULL);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, NULL);
- ED_undo_push(C, "Unlink texture");
- break;
- case ID_WO:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, unlink_world_cb, NULL);
-
- WM_event_add_notifier(C, NC_SCENE | ND_WORLD, NULL);
- ED_undo_push(C, "Unlink world");
- break;
- case ID_GR:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, unlink_collection_cb, NULL);
-
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, NULL);
- ED_undo_push(C, "Unlink Collection");
- break;
- default:
- BKE_report(op->reports, RPT_WARNING, "Not yet implemented");
- break;
- }
- break;
- }
- case OUTLINER_IDOP_LOCAL:
- {
- /* make local */
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_local_cb, NULL);
- ED_undo_push(C, "Localized Data");
- break;
- }
- case OUTLINER_IDOP_STATIC_OVERRIDE:
- {
- if (BKE_override_static_is_enabled()) {
- /* make local */
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_static_override_cb, NULL);
- ED_undo_push(C, "Overridden Data");
- }
- break;
- }
- case OUTLINER_IDOP_SINGLE:
- {
- /* make single user */
- switch (idlevel) {
- case ID_AC:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, singleuser_action_cb, NULL);
-
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
- ED_undo_push(C, "Single-User Action");
- break;
-
- case ID_WO:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, singleuser_world_cb, NULL);
-
- WM_event_add_notifier(C, NC_SCENE | ND_WORLD, NULL);
- ED_undo_push(C, "Single-User World");
- break;
-
- default:
- BKE_report(op->reports, RPT_WARNING, "Not yet implemented");
- break;
- }
- break;
- }
- case OUTLINER_IDOP_DELETE:
- {
- if (idlevel > 0) {
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL);
- ED_undo_push(C, "Delete");
- }
- break;
- }
- case OUTLINER_IDOP_REMAP:
- {
- if (idlevel > 0) {
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL);
- ED_undo_push(C, "Remap");
- }
- break;
- }
- case OUTLINER_IDOP_COPY:
- {
- WM_operator_name_call(C, "OUTLINER_OT_id_copy", WM_OP_INVOKE_DEFAULT, NULL);
- break;
- }
- case OUTLINER_IDOP_PASTE:
- {
- WM_operator_name_call(C, "OUTLINER_OT_id_paste", WM_OP_INVOKE_DEFAULT, NULL);
- ED_undo_push(C, "Paste");
- break;
- }
- case OUTLINER_IDOP_FAKE_ADD:
- {
- /* set fake user */
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_fake_user_set_cb, NULL);
-
- WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
- ED_undo_push(C, "Add Fake User");
- break;
- }
- case OUTLINER_IDOP_FAKE_CLEAR:
- {
- /* clear fake user */
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_fake_user_clear_cb, NULL);
-
- WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
- ED_undo_push(C, "Clear Fake User");
- break;
- }
- case OUTLINER_IDOP_RENAME:
- {
- /* rename */
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb, NULL);
-
- WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
- ED_undo_push(C, "Rename");
- break;
- }
- case OUTLINER_IDOP_SELECT_LINKED:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_select_linked_cb, NULL);
- ED_undo_push(C, "Select");
- break;
-
- default:
- // invalid - unhandled
- break;
- }
-
- /* wrong notifier still... */
- WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
-
- // XXX: this is just so that outliner is always up to date
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
+ eOutlinerIdOpTypes event;
+
+ /* check for invalid states */
+ if (soops == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
+
+ event = RNA_enum_get(op->ptr, "type");
+
+ switch (event) {
+ case OUTLINER_IDOP_UNLINK: {
+ /* unlink datablock from its parent */
+ if (objectlevel) {
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, unlink_object_cb, NULL);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, NULL);
+ ED_undo_push(C, "Unlink Object");
+ break;
+ }
+
+ switch (idlevel) {
+ case ID_AC:
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, unlink_action_cb, NULL);
+
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
+ ED_undo_push(C, "Unlink action");
+ break;
+ case ID_MA:
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, unlink_material_cb, NULL);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, NULL);
+ ED_undo_push(C, "Unlink material");
+ break;
+ case ID_TE:
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, unlink_texture_cb, NULL);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, NULL);
+ ED_undo_push(C, "Unlink texture");
+ break;
+ case ID_WO:
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, unlink_world_cb, NULL);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_WORLD, NULL);
+ ED_undo_push(C, "Unlink world");
+ break;
+ case ID_GR:
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, unlink_collection_cb, NULL);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, NULL);
+ ED_undo_push(C, "Unlink Collection");
+ break;
+ default:
+ BKE_report(op->reports, RPT_WARNING, "Not yet implemented");
+ break;
+ }
+ break;
+ }
+ case OUTLINER_IDOP_LOCAL: {
+ /* make local */
+ outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_local_cb, NULL);
+ ED_undo_push(C, "Localized Data");
+ break;
+ }
+ case OUTLINER_IDOP_STATIC_OVERRIDE: {
+ if (BKE_override_static_is_enabled()) {
+ /* make local */
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, id_static_override_cb, NULL);
+ ED_undo_push(C, "Overridden Data");
+ }
+ break;
+ }
+ case OUTLINER_IDOP_SINGLE: {
+ /* make single user */
+ switch (idlevel) {
+ case ID_AC:
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, singleuser_action_cb, NULL);
+
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
+ ED_undo_push(C, "Single-User Action");
+ break;
+
+ case ID_WO:
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, singleuser_world_cb, NULL);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_WORLD, NULL);
+ ED_undo_push(C, "Single-User World");
+ break;
+
+ default:
+ BKE_report(op->reports, RPT_WARNING, "Not yet implemented");
+ break;
+ }
+ break;
+ }
+ case OUTLINER_IDOP_DELETE: {
+ if (idlevel > 0) {
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL);
+ ED_undo_push(C, "Delete");
+ }
+ break;
+ }
+ case OUTLINER_IDOP_REMAP: {
+ if (idlevel > 0) {
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL);
+ ED_undo_push(C, "Remap");
+ }
+ break;
+ }
+ case OUTLINER_IDOP_COPY: {
+ WM_operator_name_call(C, "OUTLINER_OT_id_copy", WM_OP_INVOKE_DEFAULT, NULL);
+ break;
+ }
+ case OUTLINER_IDOP_PASTE: {
+ WM_operator_name_call(C, "OUTLINER_OT_id_paste", WM_OP_INVOKE_DEFAULT, NULL);
+ ED_undo_push(C, "Paste");
+ break;
+ }
+ case OUTLINER_IDOP_FAKE_ADD: {
+ /* set fake user */
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, id_fake_user_set_cb, NULL);
+
+ WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
+ ED_undo_push(C, "Add Fake User");
+ break;
+ }
+ case OUTLINER_IDOP_FAKE_CLEAR: {
+ /* clear fake user */
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, id_fake_user_clear_cb, NULL);
+
+ WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
+ ED_undo_push(C, "Clear Fake User");
+ break;
+ }
+ case OUTLINER_IDOP_RENAME: {
+ /* rename */
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, item_rename_cb, NULL);
+
+ WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
+ ED_undo_push(C, "Rename");
+ break;
+ }
+ case OUTLINER_IDOP_SELECT_LINKED:
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, id_select_linked_cb, NULL);
+ ED_undo_push(C, "Select");
+ break;
+
+ default:
+ // invalid - unhandled
+ break;
+ }
+
+ /* wrong notifier still... */
+ WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
+
+ // XXX: this is just so that outliner is always up to date
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+
+ return OPERATOR_FINISHED;
}
-
void OUTLINER_OT_id_operation(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Outliner ID data Operation";
- ot->idname = "OUTLINER_OT_id_operation";
+ /* identifiers */
+ ot->name = "Outliner ID data Operation";
+ ot->idname = "OUTLINER_OT_id_operation";
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = outliner_id_operation_exec;
- ot->poll = ED_operator_outliner_active;
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = outliner_id_operation_exec;
+ ot->poll = ED_operator_outliner_active;
- ot->flag = 0;
+ ot->flag = 0;
- ot->prop = RNA_def_enum(ot->srna, "type", prop_id_op_types, 0, "ID data Operation", "");
- RNA_def_enum_funcs(ot->prop, outliner_id_operation_itemf);
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_id_op_types, 0, "ID data Operation", "");
+ RNA_def_enum_funcs(ot->prop, outliner_id_operation_itemf);
}
/* **************************************** */
typedef enum eOutlinerLibOpTypes {
- OL_LIB_INVALID = 0,
+ OL_LIB_INVALID = 0,
- OL_LIB_RENAME,
- OL_LIB_DELETE,
- OL_LIB_RELOCATE,
- OL_LIB_RELOAD,
+ OL_LIB_RENAME,
+ OL_LIB_DELETE,
+ OL_LIB_RELOCATE,
+ OL_LIB_RELOAD,
} eOutlinerLibOpTypes;
static const EnumPropertyItem outliner_lib_op_type_items[] = {
- {OL_LIB_RENAME, "RENAME", 0, "Rename", ""},
- {OL_LIB_DELETE, "DELETE", ICON_X, "Delete", "Delete this library and all its item from Blender - WARNING: no undo"},
- {OL_LIB_RELOCATE, "RELOCATE", 0, "Relocate", "Select a new path for this library, and reload all its data"},
- {OL_LIB_RELOAD, "RELOAD", ICON_FILE_REFRESH, "Reload", "Reload all data from this library"},
- {0, NULL, 0, NULL, NULL},
+ {OL_LIB_RENAME, "RENAME", 0, "Rename", ""},
+ {OL_LIB_DELETE,
+ "DELETE",
+ ICON_X,
+ "Delete",
+ "Delete this library and all its item from Blender - WARNING: no undo"},
+ {OL_LIB_RELOCATE,
+ "RELOCATE",
+ 0,
+ "Relocate",
+ "Select a new path for this library, and reload all its data"},
+ {OL_LIB_RELOAD, "RELOAD", ICON_FILE_REFRESH, "Reload", "Reload all data from this library"},
+ {0, NULL, 0, NULL, NULL},
};
static int outliner_lib_operation_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
- eOutlinerLibOpTypes event;
-
- /* check for invalid states */
- if (soops == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
-
- event = RNA_enum_get(op->ptr, "type");
-
- switch (event) {
- case OL_LIB_RENAME:
- {
- /* rename */
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb, NULL);
-
- WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
- ED_undo_push(C, "Rename Library");
- break;
- }
- case OL_LIB_DELETE:
- {
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL);
- ED_undo_push(C, "Delete Library");
- break;
- }
- case OL_LIB_RELOCATE:
- {
- /* rename */
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, lib_relocate_cb, NULL);
- ED_undo_push(C, "Relocate Library");
- break;
- }
- case OL_LIB_RELOAD:
- {
- /* rename */
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, lib_reload_cb, NULL);
- break;
- }
- default:
- /* invalid - unhandled */
- break;
- }
-
- /* wrong notifier still... */
- WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
-
- /* XXX: this is just so that outliner is always up to date */
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
+ eOutlinerLibOpTypes event;
+
+ /* check for invalid states */
+ if (soops == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
+
+ event = RNA_enum_get(op->ptr, "type");
+
+ switch (event) {
+ case OL_LIB_RENAME: {
+ /* rename */
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, item_rename_cb, NULL);
+
+ WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
+ ED_undo_push(C, "Rename Library");
+ break;
+ }
+ case OL_LIB_DELETE: {
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL);
+ ED_undo_push(C, "Delete Library");
+ break;
+ }
+ case OL_LIB_RELOCATE: {
+ /* rename */
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, lib_relocate_cb, NULL);
+ ED_undo_push(C, "Relocate Library");
+ break;
+ }
+ case OL_LIB_RELOAD: {
+ /* rename */
+ outliner_do_libdata_operation(
+ C, op->reports, scene, soops, &soops->tree, lib_reload_cb, NULL);
+ break;
+ }
+ default:
+ /* invalid - unhandled */
+ break;
+ }
+
+ /* wrong notifier still... */
+ WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
+
+ /* XXX: this is just so that outliner is always up to date */
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+
+ return OPERATOR_FINISHED;
}
-
void OUTLINER_OT_lib_operation(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Outliner Library Operation";
- ot->idname = "OUTLINER_OT_lib_operation";
+ /* identifiers */
+ ot->name = "Outliner Library Operation";
+ ot->idname = "OUTLINER_OT_lib_operation";
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = outliner_lib_operation_exec;
- ot->poll = ED_operator_outliner_active;
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = outliner_lib_operation_exec;
+ ot->poll = ED_operator_outliner_active;
- ot->prop = RNA_def_enum(ot->srna, "type", outliner_lib_op_type_items, 0, "Library Operation", "");
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", outliner_lib_op_type_items, 0, "Library Operation", "");
}
/* **************************************** */
-static void outliner_do_id_set_operation(SpaceOutliner *soops, int type, ListBase *lb, ID *newid,
- void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *, ID *))
-{
- TreeElement *te;
- TreeStoreElem *tselem;
-
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
- if (tselem->flag & TSE_SELECTED) {
- if (tselem->type == type) {
- TreeStoreElem *tsep = te->parent ? TREESTORE(te->parent) : NULL;
- operation_cb(te, tselem, tsep, newid);
- }
- }
- if (TSELEM_OPEN(tselem, soops)) {
- outliner_do_id_set_operation(soops, type, &te->subtree, newid, operation_cb);
- }
- }
+static void outliner_do_id_set_operation(
+ SpaceOutliner *soops,
+ int type,
+ ListBase *lb,
+ ID *newid,
+ void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *, ID *))
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for (te = lb->first; te; te = te->next) {
+ tselem = TREESTORE(te);
+ if (tselem->flag & TSE_SELECTED) {
+ if (tselem->type == type) {
+ TreeStoreElem *tsep = te->parent ? TREESTORE(te->parent) : NULL;
+ operation_cb(te, tselem, tsep, newid);
+ }
+ }
+ if (TSELEM_OPEN(tselem, soops)) {
+ outliner_do_id_set_operation(soops, type, &te->subtree, newid, operation_cb);
+ }
+ }
}
/* ------------------------------------------ */
-static void actionset_id_cb(TreeElement *UNUSED(te), TreeStoreElem *tselem, TreeStoreElem *tsep, ID *actId)
+static void actionset_id_cb(TreeElement *UNUSED(te),
+ TreeStoreElem *tselem,
+ TreeStoreElem *tsep,
+ ID *actId)
{
- bAction *act = (bAction *)actId;
+ bAction *act = (bAction *)actId;
- if (tselem->type == TSE_ANIM_DATA) {
- /* "animation" entries - action is child of this */
- BKE_animdata_set_action(NULL, tselem->id, act);
- }
- /* TODO: if any other "expander" channels which own actions need to support this menu,
- * add: tselem->type = ...
- */
- else if (tsep && (tsep->type == TSE_ANIM_DATA)) {
- /* "animation" entries case again */
- BKE_animdata_set_action(NULL, tsep->id, act);
- }
- // TODO: other cases not supported yet
+ if (tselem->type == TSE_ANIM_DATA) {
+ /* "animation" entries - action is child of this */
+ BKE_animdata_set_action(NULL, tselem->id, act);
+ }
+ /* TODO: if any other "expander" channels which own actions need to support this menu,
+ * add: tselem->type = ...
+ */
+ else if (tsep && (tsep->type == TSE_ANIM_DATA)) {
+ /* "animation" entries case again */
+ BKE_animdata_set_action(NULL, tsep->id, act);
+ }
+ // TODO: other cases not supported yet
}
static int outliner_action_set_exec(bContext *C, wmOperator *op)
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
-
- bAction *act;
-
- /* check for invalid states */
- if (soops == NULL) {
- return OPERATOR_CANCELLED;
- }
- 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"));
-
- if (act == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No valid action to add");
- return OPERATOR_CANCELLED;
- }
- else if (act->idroot == 0) {
- /* hopefully in this case (i.e. library of userless actions), the user knows what they're doing... */
- BKE_reportf(op->reports, RPT_WARNING,
- "Action '%s' does not specify what data-blocks it can be used on "
- "(try setting the 'ID Root Type' setting from the data-blocks editor "
- "for this action to avoid future problems)",
- act->id.name + 2);
- }
-
- /* perform action if valid channel */
- if (datalevel == TSE_ANIM_DATA) {
- outliner_do_id_set_operation(soops, datalevel, &soops->tree, (ID *)act, actionset_id_cb);
- }
- else if (idlevel == ID_AC) {
- outliner_do_id_set_operation(soops, idlevel, &soops->tree, (ID *)act, actionset_id_cb);
- }
- else {
- return OPERATOR_CANCELLED;
- }
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
- ED_undo_push(C, "Set action");
-
- /* done */
- return OPERATOR_FINISHED;
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
+
+ bAction *act;
+
+ /* check for invalid states */
+ if (soops == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ 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"));
+
+ if (act == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No valid action to add");
+ return OPERATOR_CANCELLED;
+ }
+ else if (act->idroot == 0) {
+ /* hopefully in this case (i.e. library of userless actions), the user knows what they're doing... */
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Action '%s' does not specify what data-blocks it can be used on "
+ "(try setting the 'ID Root Type' setting from the data-blocks editor "
+ "for this action to avoid future problems)",
+ act->id.name + 2);
+ }
+
+ /* perform action if valid channel */
+ if (datalevel == TSE_ANIM_DATA) {
+ outliner_do_id_set_operation(soops, datalevel, &soops->tree, (ID *)act, actionset_id_cb);
+ }
+ else if (idlevel == ID_AC) {
+ outliner_do_id_set_operation(soops, idlevel, &soops->tree, (ID *)act, actionset_id_cb);
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
+ ED_undo_push(C, "Set action");
+
+ /* done */
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_action_set(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Outliner Set Action";
- ot->idname = "OUTLINER_OT_action_set";
- ot->description = "Change the active action used";
+ /* identifiers */
+ ot->name = "Outliner Set Action";
+ ot->idname = "OUTLINER_OT_action_set";
+ ot->description = "Change the active action used";
- /* api callbacks */
- ot->invoke = WM_enum_search_invoke;
- ot->exec = outliner_action_set_exec;
- ot->poll = ED_operator_outliner_active;
+ /* api callbacks */
+ ot->invoke = WM_enum_search_invoke;
+ ot->exec = outliner_action_set_exec;
+ ot->poll = ED_operator_outliner_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
- /* props */
- // TODO: this would be nicer as an ID-pointer...
- prop = RNA_def_enum(ot->srna, "action", DummyRNA_NULL_items, 0, "Action", "");
- RNA_def_enum_funcs(prop, RNA_action_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ /* props */
+ // TODO: this would be nicer as an ID-pointer...
+ prop = RNA_def_enum(ot->srna, "action", DummyRNA_NULL_items, 0, "Action", "");
+ RNA_def_enum_funcs(prop, RNA_action_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
/* **************************************** */
typedef enum eOutliner_AnimDataOps {
- OUTLINER_ANIMOP_INVALID = 0,
+ OUTLINER_ANIMOP_INVALID = 0,
- OUTLINER_ANIMOP_CLEAR_ADT,
+ OUTLINER_ANIMOP_CLEAR_ADT,
- OUTLINER_ANIMOP_SET_ACT,
- OUTLINER_ANIMOP_CLEAR_ACT,
+ OUTLINER_ANIMOP_SET_ACT,
+ OUTLINER_ANIMOP_CLEAR_ACT,
- OUTLINER_ANIMOP_REFRESH_DRV,
- OUTLINER_ANIMOP_CLEAR_DRV
+ OUTLINER_ANIMOP_REFRESH_DRV,
+ OUTLINER_ANIMOP_CLEAR_DRV
- //OUTLINER_ANIMOP_COPY_DRIVERS,
- //OUTLINER_ANIMOP_PASTE_DRIVERS
+ //OUTLINER_ANIMOP_COPY_DRIVERS,
+ //OUTLINER_ANIMOP_PASTE_DRIVERS
} eOutliner_AnimDataOps;
static const EnumPropertyItem prop_animdata_op_types[] = {
- {OUTLINER_ANIMOP_CLEAR_ADT, "CLEAR_ANIMDATA", 0, "Clear Animation Data", "Remove this animation data container"},
- {OUTLINER_ANIMOP_SET_ACT, "SET_ACT", 0, "Set Action", ""},
- {OUTLINER_ANIMOP_CLEAR_ACT, "CLEAR_ACT", 0, "Unlink Action", ""},
- {OUTLINER_ANIMOP_REFRESH_DRV, "REFRESH_DRIVERS", 0, "Refresh Drivers", ""},
- //{OUTLINER_ANIMOP_COPY_DRIVERS, "COPY_DRIVERS", 0, "Copy Drivers", ""},
- //{OUTLINER_ANIMOP_PASTE_DRIVERS, "PASTE_DRIVERS", 0, "Paste Drivers", ""},
- {OUTLINER_ANIMOP_CLEAR_DRV, "CLEAR_DRIVERS", 0, "Clear Drivers", ""},
- {0, NULL, 0, NULL, NULL},
+ {OUTLINER_ANIMOP_CLEAR_ADT,
+ "CLEAR_ANIMDATA",
+ 0,
+ "Clear Animation Data",
+ "Remove this animation data container"},
+ {OUTLINER_ANIMOP_SET_ACT, "SET_ACT", 0, "Set Action", ""},
+ {OUTLINER_ANIMOP_CLEAR_ACT, "CLEAR_ACT", 0, "Unlink Action", ""},
+ {OUTLINER_ANIMOP_REFRESH_DRV, "REFRESH_DRIVERS", 0, "Refresh Drivers", ""},
+ //{OUTLINER_ANIMOP_COPY_DRIVERS, "COPY_DRIVERS", 0, "Copy Drivers", ""},
+ //{OUTLINER_ANIMOP_PASTE_DRIVERS, "PASTE_DRIVERS", 0, "Paste Drivers", ""},
+ {OUTLINER_ANIMOP_CLEAR_DRV, "CLEAR_DRIVERS", 0, "Clear Drivers", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int outliner_animdata_operation_exec(bContext *C, wmOperator *op)
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
- eOutliner_AnimDataOps event;
- short updateDeps = 0;
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
+ eOutliner_AnimDataOps event;
+ short updateDeps = 0;
- /* check for invalid states */
- if (soops == NULL) {
- return OPERATOR_CANCELLED;
- }
+ /* check for invalid states */
+ if (soops == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- event = RNA_enum_get(op->ptr, "type");
- set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
+ event = RNA_enum_get(op->ptr, "type");
+ set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
- if (datalevel != TSE_ANIM_DATA) {
- return OPERATOR_CANCELLED;
- }
+ if (datalevel != TSE_ANIM_DATA) {
+ return OPERATOR_CANCELLED;
+ }
- /* perform the core operation */
- switch (event) {
- case OUTLINER_ANIMOP_CLEAR_ADT:
- /* Remove Animation Data - this may remove the active action, in some cases... */
- outliner_do_data_operation(soops, datalevel, event, &soops->tree, clear_animdata_cb, NULL);
+ /* perform the core operation */
+ switch (event) {
+ case OUTLINER_ANIMOP_CLEAR_ADT:
+ /* Remove Animation Data - this may remove the active action, in some cases... */
+ outliner_do_data_operation(soops, datalevel, event, &soops->tree, clear_animdata_cb, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
- ED_undo_push(C, "Clear Animation Data");
- break;
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
+ ED_undo_push(C, "Clear Animation Data");
+ break;
- case OUTLINER_ANIMOP_SET_ACT:
- /* delegate once again... */
- WM_operator_name_call(C, "OUTLINER_OT_action_set", WM_OP_INVOKE_REGION_WIN, NULL);
- break;
+ case OUTLINER_ANIMOP_SET_ACT:
+ /* delegate once again... */
+ WM_operator_name_call(C, "OUTLINER_OT_action_set", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
- case OUTLINER_ANIMOP_CLEAR_ACT:
- /* clear active action - using standard rules */
- outliner_do_data_operation(soops, datalevel, event, &soops->tree, unlinkact_animdata_cb, NULL);
+ case OUTLINER_ANIMOP_CLEAR_ACT:
+ /* clear active action - using standard rules */
+ outliner_do_data_operation(
+ soops, datalevel, event, &soops->tree, unlinkact_animdata_cb, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
- ED_undo_push(C, "Unlink action");
- break;
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
+ ED_undo_push(C, "Unlink action");
+ break;
- case OUTLINER_ANIMOP_REFRESH_DRV:
- outliner_do_data_operation(soops, datalevel, event, &soops->tree, refreshdrivers_animdata_cb, NULL);
+ case OUTLINER_ANIMOP_REFRESH_DRV:
+ outliner_do_data_operation(
+ soops, datalevel, event, &soops->tree, refreshdrivers_animdata_cb, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, NULL);
- //ED_undo_push(C, "Refresh Drivers"); /* no undo needed - shouldn't have any impact? */
- updateDeps = 1;
- break;
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, NULL);
+ //ED_undo_push(C, "Refresh Drivers"); /* no undo needed - shouldn't have any impact? */
+ updateDeps = 1;
+ break;
- case OUTLINER_ANIMOP_CLEAR_DRV:
- outliner_do_data_operation(soops, datalevel, event, &soops->tree, cleardrivers_animdata_cb, NULL);
+ case OUTLINER_ANIMOP_CLEAR_DRV:
+ outliner_do_data_operation(
+ soops, datalevel, event, &soops->tree, cleardrivers_animdata_cb, NULL);
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, NULL);
- ED_undo_push(C, "Clear Drivers");
- updateDeps = 1;
- break;
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, NULL);
+ ED_undo_push(C, "Clear Drivers");
+ updateDeps = 1;
+ break;
- default: // invalid
- break;
- }
+ default: // invalid
+ break;
+ }
- /* update dependencies */
- if (updateDeps) {
- /* rebuild depsgraph for the new deps */
- DEG_relations_tag_update(CTX_data_main(C));
- }
+ /* update dependencies */
+ if (updateDeps) {
+ /* rebuild depsgraph for the new deps */
+ DEG_relations_tag_update(CTX_data_main(C));
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
void OUTLINER_OT_animdata_operation(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Outliner Animation Data Operation";
- ot->idname = "OUTLINER_OT_animdata_operation";
+ /* identifiers */
+ ot->name = "Outliner Animation Data Operation";
+ ot->idname = "OUTLINER_OT_animdata_operation";
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = outliner_animdata_operation_exec;
- ot->poll = ED_operator_outliner_active;
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = outliner_animdata_operation_exec;
+ ot->poll = ED_operator_outliner_active;
- ot->flag = 0;
+ ot->flag = 0;
- ot->prop = RNA_def_enum(ot->srna, "type", prop_animdata_op_types, 0, "Animation Operation", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_animdata_op_types, 0, "Animation Operation", "");
}
/* **************************************** */
static const EnumPropertyItem prop_constraint_op_types[] = {
- {OL_CONSTRAINTOP_ENABLE, "ENABLE", ICON_HIDE_OFF, "Enable", ""},
- {OL_CONSTRAINTOP_DISABLE, "DISABLE", ICON_HIDE_ON, "Disable", ""},
- {OL_CONSTRAINTOP_DELETE, "DELETE", ICON_X, "Delete", ""},
- {0, NULL, 0, NULL, NULL},
+ {OL_CONSTRAINTOP_ENABLE, "ENABLE", ICON_HIDE_OFF, "Enable", ""},
+ {OL_CONSTRAINTOP_DISABLE, "DISABLE", ICON_HIDE_ON, "Disable", ""},
+ {OL_CONSTRAINTOP_DELETE, "DELETE", ICON_X, "Delete", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int outliner_constraint_operation_exec(bContext *C, wmOperator *op)
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
- eOutliner_PropConstraintOps event;
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
+ eOutliner_PropConstraintOps event;
- event = RNA_enum_get(op->ptr, "type");
- set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
+ event = RNA_enum_get(op->ptr, "type");
+ set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
- outliner_do_data_operation(soops, datalevel, event, &soops->tree, constraint_cb, C);
+ outliner_do_data_operation(soops, datalevel, event, &soops->tree, constraint_cb, C);
- if (event == OL_CONSTRAINTOP_DELETE) {
- outliner_cleanup_tree(soops);
- }
+ if (event == OL_CONSTRAINTOP_DELETE) {
+ outliner_cleanup_tree(soops);
+ }
- ED_undo_push(C, "Constraint operation");
+ ED_undo_push(C, "Constraint operation");
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_constraint_operation(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Outliner Constraint Operation";
- ot->idname = "OUTLINER_OT_constraint_operation";
+ /* identifiers */
+ ot->name = "Outliner Constraint Operation";
+ ot->idname = "OUTLINER_OT_constraint_operation";
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = outliner_constraint_operation_exec;
- ot->poll = ED_operator_outliner_active;
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = outliner_constraint_operation_exec;
+ ot->poll = ED_operator_outliner_active;
- ot->flag = 0;
+ ot->flag = 0;
- ot->prop = RNA_def_enum(ot->srna, "type", prop_constraint_op_types, 0, "Constraint Operation", "");
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", prop_constraint_op_types, 0, "Constraint Operation", "");
}
/* ******************** */
static const EnumPropertyItem prop_modifier_op_types[] = {
- {OL_MODIFIER_OP_TOGVIS, "TOGVIS", ICON_RESTRICT_VIEW_OFF, "Toggle viewport use", ""},
- {OL_MODIFIER_OP_TOGREN, "TOGREN", ICON_RESTRICT_RENDER_OFF, "Toggle render use", ""},
- {OL_MODIFIER_OP_DELETE, "DELETE", ICON_X, "Delete", ""},
- {0, NULL, 0, NULL, NULL},
+ {OL_MODIFIER_OP_TOGVIS, "TOGVIS", ICON_RESTRICT_VIEW_OFF, "Toggle viewport use", ""},
+ {OL_MODIFIER_OP_TOGREN, "TOGREN", ICON_RESTRICT_RENDER_OFF, "Toggle render use", ""},
+ {OL_MODIFIER_OP_DELETE, "DELETE", ICON_X, "Delete", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int outliner_modifier_operation_exec(bContext *C, wmOperator *op)
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
- eOutliner_PropModifierOps event;
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
+ eOutliner_PropModifierOps event;
- event = RNA_enum_get(op->ptr, "type");
- set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
+ event = RNA_enum_get(op->ptr, "type");
+ set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
- outliner_do_data_operation(soops, datalevel, event, &soops->tree, modifier_cb, C);
+ outliner_do_data_operation(soops, datalevel, event, &soops->tree, modifier_cb, C);
- if (event == OL_MODIFIER_OP_DELETE) {
- outliner_cleanup_tree(soops);
- }
+ if (event == OL_MODIFIER_OP_DELETE) {
+ outliner_cleanup_tree(soops);
+ }
- ED_undo_push(C, "Modifier operation");
+ ED_undo_push(C, "Modifier operation");
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_modifier_operation(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Outliner Modifier Operation";
- ot->idname = "OUTLINER_OT_modifier_operation";
+ /* identifiers */
+ ot->name = "Outliner Modifier Operation";
+ ot->idname = "OUTLINER_OT_modifier_operation";
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = outliner_modifier_operation_exec;
- ot->poll = ED_operator_outliner_active;
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = outliner_modifier_operation_exec;
+ ot->poll = ED_operator_outliner_active;
- ot->flag = 0;
+ ot->flag = 0;
- ot->prop = RNA_def_enum(ot->srna, "type", prop_modifier_op_types, 0, "Modifier Operation", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_modifier_op_types, 0, "Modifier Operation", "");
}
/* ******************** */
// XXX: select linked is for RNA structs only
static const EnumPropertyItem prop_data_op_types[] = {
- {OL_DOP_SELECT, "SELECT", 0, "Select", ""},
- {OL_DOP_DESELECT, "DESELECT", 0, "Deselect", ""},
- {OL_DOP_HIDE, "HIDE", 0, "Hide", ""},
- {OL_DOP_UNHIDE, "UNHIDE", 0, "Unhide", ""},
- {OL_DOP_SELECT_LINKED, "SELECT_LINKED", 0, "Select Linked", ""},
- {0, NULL, 0, NULL, NULL},
+ {OL_DOP_SELECT, "SELECT", 0, "Select", ""},
+ {OL_DOP_DESELECT, "DESELECT", 0, "Deselect", ""},
+ {OL_DOP_HIDE, "HIDE", 0, "Hide", ""},
+ {OL_DOP_UNHIDE, "UNHIDE", 0, "Unhide", ""},
+ {OL_DOP_SELECT_LINKED, "SELECT_LINKED", 0, "Select Linked", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int outliner_data_operation_exec(bContext *C, wmOperator *op)
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
- eOutliner_PropDataOps event;
-
- /* check for invalid states */
- if (soops == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- event = RNA_enum_get(op->ptr, "type");
- set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
-
- switch (datalevel) {
- case TSE_POSE_CHANNEL:
- {
- outliner_do_data_operation(soops, datalevel, event, &soops->tree, pchan_cb, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
- ED_undo_push(C, "PoseChannel operation");
-
- break;
- }
- case TSE_BONE:
- {
- outliner_do_data_operation(soops, datalevel, event, &soops->tree, bone_cb, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
- ED_undo_push(C, "Bone operation");
-
- break;
- }
- case TSE_EBONE:
- {
- outliner_do_data_operation(soops, datalevel, event, &soops->tree, ebone_cb, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
- ED_undo_push(C, "EditBone operation");
-
- break;
- }
- case TSE_SEQUENCE:
- {
- Scene *scene = CTX_data_scene(C);
- outliner_do_data_operation(soops, datalevel, event, &soops->tree, sequence_cb, scene);
-
- break;
- }
- case TSE_GP_LAYER:
- {
- outliner_do_data_operation(soops, datalevel, event, &soops->tree, gp_layer_cb, NULL);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
- ED_undo_push(C, "Grease Pencil Layer operation");
-
- break;
- }
- case TSE_RNA_STRUCT:
- if (event == OL_DOP_SELECT_LINKED) {
- outliner_do_data_operation(soops, datalevel, event, &soops->tree, data_select_linked_cb, C);
- }
-
- break;
-
- default:
- BKE_report(op->reports, RPT_WARNING, "Not yet implemented");
- break;
- }
-
- return OPERATOR_FINISHED;
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
+ eOutliner_PropDataOps event;
+
+ /* check for invalid states */
+ if (soops == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ event = RNA_enum_get(op->ptr, "type");
+ set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
+
+ switch (datalevel) {
+ case TSE_POSE_CHANNEL: {
+ outliner_do_data_operation(soops, datalevel, event, &soops->tree, pchan_cb, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+ ED_undo_push(C, "PoseChannel operation");
+
+ break;
+ }
+ case TSE_BONE: {
+ outliner_do_data_operation(soops, datalevel, event, &soops->tree, bone_cb, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+ ED_undo_push(C, "Bone operation");
+
+ break;
+ }
+ case TSE_EBONE: {
+ outliner_do_data_operation(soops, datalevel, event, &soops->tree, ebone_cb, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+ ED_undo_push(C, "EditBone operation");
+
+ break;
+ }
+ case TSE_SEQUENCE: {
+ Scene *scene = CTX_data_scene(C);
+ outliner_do_data_operation(soops, datalevel, event, &soops->tree, sequence_cb, scene);
+
+ break;
+ }
+ case TSE_GP_LAYER: {
+ outliner_do_data_operation(soops, datalevel, event, &soops->tree, gp_layer_cb, NULL);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
+ ED_undo_push(C, "Grease Pencil Layer operation");
+
+ break;
+ }
+ case TSE_RNA_STRUCT:
+ if (event == OL_DOP_SELECT_LINKED) {
+ outliner_do_data_operation(
+ soops, datalevel, event, &soops->tree, data_select_linked_cb, C);
+ }
+
+ break;
+
+ default:
+ BKE_report(op->reports, RPT_WARNING, "Not yet implemented");
+ break;
+ }
+
+ return OPERATOR_FINISHED;
}
-
void OUTLINER_OT_data_operation(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Outliner Data Operation";
- ot->idname = "OUTLINER_OT_data_operation";
+ /* identifiers */
+ ot->name = "Outliner Data Operation";
+ ot->idname = "OUTLINER_OT_data_operation";
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = outliner_data_operation_exec;
- ot->poll = ED_operator_outliner_active;
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = outliner_data_operation_exec;
+ ot->poll = ED_operator_outliner_active;
- ot->flag = 0;
+ ot->flag = 0;
- ot->prop = RNA_def_enum(ot->srna, "type", prop_data_op_types, 0, "Data Operation", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_data_op_types, 0, "Data Operation", "");
}
-
/* ******************** */
static int outliner_operator_menu(bContext *C, const char *opname)
{
- wmOperatorType *ot = WM_operatortype_find(opname, false);
- uiPopupMenu *pup = UI_popup_menu_begin(C, RNA_struct_ui_name(ot->srna), ICON_NONE);
- uiLayout *layout = UI_popup_menu_layout(pup);
-
- /* set this so the default execution context is the same as submenus */
- 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);
- }
-
- UI_popup_menu_end(C, pup);
-
- return OPERATOR_INTERFACE;
-}
-
-static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOutliner *soops,
- TreeElement *te, const float mval[2])
-{
- ReportList *reports = CTX_wm_reports(C); // XXX...
-
- if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
- int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
- TreeStoreElem *tselem = TREESTORE(te);
-
- /* select object that's clicked on and popup context menu */
- if (!(tselem->flag & TSE_SELECTED)) {
-
- if (outliner_flag_is_any_test(&soops->tree, TSE_SELECTED, 1)) {
- outliner_flag_set(&soops->tree, TSE_SELECTED, 0);
- }
-
- tselem->flag |= TSE_SELECTED;
-
- /* Only redraw, don't rebuild here because TreeElement pointers will
- * become invalid and operations will crash. */
- ED_region_tag_redraw_no_rebuild(ar);
- }
-
- set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
-
- if (scenelevel) {
- if (objectlevel || datalevel || idlevel) {
- BKE_report(reports, RPT_WARNING, "Mixed selection");
- return OPERATOR_CANCELLED;
- }
- else {
- return outliner_operator_menu(C, "OUTLINER_OT_scene_operation");
- }
- }
- else if (objectlevel) {
- WM_menu_name_call(C, "OUTLINER_MT_object", WM_OP_INVOKE_REGION_WIN);
- return OPERATOR_FINISHED;
- }
- else if (idlevel) {
- if (idlevel == -1 || datalevel) {
- BKE_report(reports, RPT_WARNING, "Mixed selection");
- return OPERATOR_CANCELLED;
- }
- else {
- switch (idlevel) {
- case ID_GR:
- WM_menu_name_call(C, "OUTLINER_MT_collection", WM_OP_INVOKE_REGION_WIN);
- return OPERATOR_FINISHED;
- break;
- case ID_LI:
- return outliner_operator_menu(C, "OUTLINER_OT_lib_operation");
- break;
- default:
- return outliner_operator_menu(C, "OUTLINER_OT_id_operation");
- break;
- }
- }
- }
- else if (datalevel) {
- if (datalevel == -1) {
- BKE_report(reports, RPT_WARNING, "Mixed selection");
- return OPERATOR_CANCELLED;
- }
- else {
- if (datalevel == TSE_ANIM_DATA) {
- return outliner_operator_menu(C, "OUTLINER_OT_animdata_operation");
- }
- else if (datalevel == TSE_DRIVER_BASE) {
- /* do nothing... no special ops needed yet */
- return OPERATOR_CANCELLED;
- }
- else if (datalevel == TSE_LAYER_COLLECTION) {
- WM_menu_name_call(C, "OUTLINER_MT_collection", WM_OP_INVOKE_REGION_WIN);
- return OPERATOR_FINISHED;
- }
- else if (ELEM(datalevel, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
- WM_menu_name_call(C, "OUTLINER_MT_collection_new", WM_OP_INVOKE_REGION_WIN);
- return OPERATOR_FINISHED;
- }
- else if (datalevel == TSE_ID_BASE) {
- /* do nothing... there are no ops needed here yet */
- }
- else if (datalevel == TSE_CONSTRAINT) {
- return outliner_operator_menu(C, "OUTLINER_OT_constraint_operation");
- }
- else if (datalevel == TSE_MODIFIER) {
- return outliner_operator_menu(C, "OUTLINER_OT_modifier_operation");
- }
- else {
- return outliner_operator_menu(C, "OUTLINER_OT_data_operation");
- }
- }
- }
-
- return 0;
- }
-
- for (te = te->subtree.first; te; te = te->next) {
- int retval = do_outliner_operation_event(C, ar, soops, te, mval);
- if (retval) {
- return retval;
- }
- }
-
- return 0;
+ wmOperatorType *ot = WM_operatortype_find(opname, false);
+ uiPopupMenu *pup = UI_popup_menu_begin(C, RNA_struct_ui_name(ot->srna), ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+
+ /* set this so the default execution context is the same as submenus */
+ 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);
+ }
+
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
+}
+
+static int do_outliner_operation_event(
+ bContext *C, ARegion *ar, SpaceOutliner *soops, TreeElement *te, const float mval[2])
+{
+ ReportList *reports = CTX_wm_reports(C); // XXX...
+
+ if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
+ int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ /* select object that's clicked on and popup context menu */
+ if (!(tselem->flag & TSE_SELECTED)) {
+
+ if (outliner_flag_is_any_test(&soops->tree, TSE_SELECTED, 1)) {
+ outliner_flag_set(&soops->tree, TSE_SELECTED, 0);
+ }
+
+ tselem->flag |= TSE_SELECTED;
+
+ /* Only redraw, don't rebuild here because TreeElement pointers will
+ * become invalid and operations will crash. */
+ ED_region_tag_redraw_no_rebuild(ar);
+ }
+
+ set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
+
+ if (scenelevel) {
+ if (objectlevel || datalevel || idlevel) {
+ BKE_report(reports, RPT_WARNING, "Mixed selection");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ return outliner_operator_menu(C, "OUTLINER_OT_scene_operation");
+ }
+ }
+ else if (objectlevel) {
+ WM_menu_name_call(C, "OUTLINER_MT_object", WM_OP_INVOKE_REGION_WIN);
+ return OPERATOR_FINISHED;
+ }
+ else if (idlevel) {
+ if (idlevel == -1 || datalevel) {
+ BKE_report(reports, RPT_WARNING, "Mixed selection");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ switch (idlevel) {
+ case ID_GR:
+ WM_menu_name_call(C, "OUTLINER_MT_collection", WM_OP_INVOKE_REGION_WIN);
+ return OPERATOR_FINISHED;
+ break;
+ case ID_LI:
+ return outliner_operator_menu(C, "OUTLINER_OT_lib_operation");
+ break;
+ default:
+ return outliner_operator_menu(C, "OUTLINER_OT_id_operation");
+ break;
+ }
+ }
+ }
+ else if (datalevel) {
+ if (datalevel == -1) {
+ BKE_report(reports, RPT_WARNING, "Mixed selection");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ if (datalevel == TSE_ANIM_DATA) {
+ return outliner_operator_menu(C, "OUTLINER_OT_animdata_operation");
+ }
+ else if (datalevel == TSE_DRIVER_BASE) {
+ /* do nothing... no special ops needed yet */
+ return OPERATOR_CANCELLED;
+ }
+ else if (datalevel == TSE_LAYER_COLLECTION) {
+ WM_menu_name_call(C, "OUTLINER_MT_collection", WM_OP_INVOKE_REGION_WIN);
+ return OPERATOR_FINISHED;
+ }
+ else if (ELEM(datalevel, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
+ WM_menu_name_call(C, "OUTLINER_MT_collection_new", WM_OP_INVOKE_REGION_WIN);
+ return OPERATOR_FINISHED;
+ }
+ else if (datalevel == TSE_ID_BASE) {
+ /* do nothing... there are no ops needed here yet */
+ }
+ else if (datalevel == TSE_CONSTRAINT) {
+ return outliner_operator_menu(C, "OUTLINER_OT_constraint_operation");
+ }
+ else if (datalevel == TSE_MODIFIER) {
+ return outliner_operator_menu(C, "OUTLINER_OT_modifier_operation");
+ }
+ else {
+ return outliner_operator_menu(C, "OUTLINER_OT_data_operation");
+ }
+ }
+ }
+
+ return 0;
+ }
+
+ for (te = te->subtree.first; te; te = te->next) {
+ int retval = do_outliner_operation_event(C, ar, soops, te, mval);
+ if (retval) {
+ return retval;
+ }
+ }
+
+ return 0;
}
-
static int outliner_operation(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- uiBut *but = UI_context_active_but_get(C);
- TreeElement *te;
- float fmval[2];
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ uiBut *but = UI_context_active_but_get(C);
+ TreeElement *te;
+ float fmval[2];
- if (but) {
- UI_but_tooltip_timer_remove(C, but);
- }
+ if (but) {
+ 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(&ar->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);
- if (retval) {
- return retval;
- }
- }
+ for (te = soops->tree.first; te; te = te->next) {
+ int retval = do_outliner_operation_event(C, ar, 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;
- }
+ /* 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;
+ WM_menu_name_call(C, "OUTLINER_MT_context", WM_OP_INVOKE_REGION_WIN);
+ return OPERATOR_FINISHED;
}
/* Menu only! Calls other operators */
void OUTLINER_OT_operation(wmOperatorType *ot)
{
- ot->name = "Context Menu";
- ot->idname = "OUTLINER_OT_operation";
- ot->description = "Context menu for item operations";
+ ot->name = "Context Menu";
+ ot->idname = "OUTLINER_OT_operation";
+ ot->description = "Context menu for item operations";
- ot->invoke = outliner_operation;
+ ot->invoke = outliner_operation;
- ot->poll = ED_operator_outliner_active;
+ 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 a4e512d6846..a03d9b6fb6d 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -83,8 +83,9 @@
#endif
/* prototypes */
-static TreeElement *outliner_add_collection_recursive(
- SpaceOutliner *soops, Collection *collection, TreeElement *ten);
+static TreeElement *outliner_add_collection_recursive(SpaceOutliner *soops,
+ Collection *collection,
+ TreeElement *ten);
static void outliner_make_object_parent_hierarchy(ListBase *lb);
/* ********************************************************* */
@@ -92,98 +93,97 @@ static void outliner_make_object_parent_hierarchy(ListBase *lb);
static void outliner_storage_cleanup(SpaceOutliner *soops)
{
- BLI_mempool *ts = soops->treestore;
-
- if (ts) {
- TreeStoreElem *tselem;
- int unused = 0;
-
- /* each element used once, for ID blocks with more users to have each a treestore */
- BLI_mempool_iter iter;
-
- BLI_mempool_iternew(ts, &iter);
- while ((tselem = BLI_mempool_iterstep(&iter))) {
- tselem->used = 0;
- }
-
- /* cleanup only after reading file or undo step, and always for
- * RNA datablocks view in order to save memory */
- if (soops->storeflag & SO_TREESTORE_CLEANUP) {
- soops->storeflag &= ~SO_TREESTORE_CLEANUP;
-
- BLI_mempool_iternew(ts, &iter);
- while ((tselem = BLI_mempool_iterstep(&iter))) {
- if (tselem->id == NULL) {
- unused++;
- }
- }
-
- if (unused) {
- if (BLI_mempool_len(ts) == unused) {
- BLI_mempool_destroy(ts);
- soops->treestore = NULL;
- if (soops->treehash) {
- BKE_outliner_treehash_free(soops->treehash);
- soops->treehash = NULL;
- }
- }
- else {
- TreeStoreElem *tsenew;
- BLI_mempool *new_ts = BLI_mempool_create(sizeof(TreeStoreElem), BLI_mempool_len(ts) - unused,
- 512, BLI_MEMPOOL_ALLOW_ITER);
- BLI_mempool_iternew(ts, &iter);
- while ((tselem = BLI_mempool_iterstep(&iter))) {
- if (tselem->id) {
- tsenew = BLI_mempool_alloc(new_ts);
- *tsenew = *tselem;
- }
- }
- BLI_mempool_destroy(ts);
- soops->treestore = new_ts;
- if (soops->treehash) {
- /* update hash table to fix broken pointers */
- BKE_outliner_treehash_rebuild_from_treestore(soops->treehash, soops->treestore);
- }
- }
- }
- }
- else if (soops->treehash) {
- BKE_outliner_treehash_clear_used(soops->treehash);
- }
- }
+ BLI_mempool *ts = soops->treestore;
+
+ if (ts) {
+ TreeStoreElem *tselem;
+ int unused = 0;
+
+ /* each element used once, for ID blocks with more users to have each a treestore */
+ BLI_mempool_iter iter;
+
+ BLI_mempool_iternew(ts, &iter);
+ while ((tselem = BLI_mempool_iterstep(&iter))) {
+ tselem->used = 0;
+ }
+
+ /* cleanup only after reading file or undo step, and always for
+ * RNA datablocks view in order to save memory */
+ if (soops->storeflag & SO_TREESTORE_CLEANUP) {
+ soops->storeflag &= ~SO_TREESTORE_CLEANUP;
+
+ BLI_mempool_iternew(ts, &iter);
+ while ((tselem = BLI_mempool_iterstep(&iter))) {
+ if (tselem->id == NULL) {
+ unused++;
+ }
+ }
+
+ if (unused) {
+ if (BLI_mempool_len(ts) == unused) {
+ BLI_mempool_destroy(ts);
+ soops->treestore = NULL;
+ if (soops->treehash) {
+ BKE_outliner_treehash_free(soops->treehash);
+ soops->treehash = NULL;
+ }
+ }
+ else {
+ TreeStoreElem *tsenew;
+ BLI_mempool *new_ts = BLI_mempool_create(
+ sizeof(TreeStoreElem), BLI_mempool_len(ts) - unused, 512, BLI_MEMPOOL_ALLOW_ITER);
+ BLI_mempool_iternew(ts, &iter);
+ while ((tselem = BLI_mempool_iterstep(&iter))) {
+ if (tselem->id) {
+ tsenew = BLI_mempool_alloc(new_ts);
+ *tsenew = *tselem;
+ }
+ }
+ BLI_mempool_destroy(ts);
+ soops->treestore = new_ts;
+ if (soops->treehash) {
+ /* update hash table to fix broken pointers */
+ BKE_outliner_treehash_rebuild_from_treestore(soops->treehash, soops->treestore);
+ }
+ }
+ }
+ }
+ else if (soops->treehash) {
+ BKE_outliner_treehash_clear_used(soops->treehash);
+ }
+ }
}
static void check_persistent(SpaceOutliner *soops, TreeElement *te, ID *id, short type, short nr)
{
- TreeStoreElem *tselem;
-
- if (soops->treestore == NULL) {
- /* if treestore was not created in readfile.c, create it here */
- soops->treestore = BLI_mempool_create(sizeof(TreeStoreElem), 1, 512, BLI_MEMPOOL_ALLOW_ITER);
-
- }
- if (soops->treehash == NULL) {
- soops->treehash = BKE_outliner_treehash_create_from_treestore(soops->treestore);
- }
-
- /* find any unused tree element in treestore and mark it as used
- * (note that there may be multiple unused elements in case of linked objects) */
- tselem = BKE_outliner_treehash_lookup_unused(soops->treehash, type, nr, id);
- if (tselem) {
- te->store_elem = tselem;
- tselem->used = 1;
- return;
- }
-
- /* add 1 element to treestore */
- tselem = BLI_mempool_alloc(soops->treestore);
- tselem->type = type;
- tselem->nr = type ? nr : 0;
- tselem->id = id;
- tselem->used = 0;
- tselem->flag = TSE_CLOSED;
- te->store_elem = tselem;
- BKE_outliner_treehash_add_element(soops->treehash, tselem);
+ TreeStoreElem *tselem;
+
+ if (soops->treestore == NULL) {
+ /* if treestore was not created in readfile.c, create it here */
+ soops->treestore = BLI_mempool_create(sizeof(TreeStoreElem), 1, 512, BLI_MEMPOOL_ALLOW_ITER);
+ }
+ if (soops->treehash == NULL) {
+ soops->treehash = BKE_outliner_treehash_create_from_treestore(soops->treestore);
+ }
+
+ /* find any unused tree element in treestore and mark it as used
+ * (note that there may be multiple unused elements in case of linked objects) */
+ tselem = BKE_outliner_treehash_lookup_unused(soops->treehash, type, nr, id);
+ if (tselem) {
+ te->store_elem = tselem;
+ tselem->used = 1;
+ return;
+ }
+
+ /* add 1 element to treestore */
+ tselem = BLI_mempool_alloc(soops->treestore);
+ tselem->type = type;
+ tselem->nr = type ? nr : 0;
+ tselem->id = id;
+ tselem->used = 0;
+ tselem->flag = TSE_CLOSED;
+ te->store_elem = tselem;
+ BKE_outliner_treehash_add_element(soops->treehash, tselem);
}
/* ********************************************************* */
@@ -191,16 +191,16 @@ static void check_persistent(SpaceOutliner *soops, TreeElement *te, ID *id, shor
void outliner_free_tree(ListBase *tree)
{
- for (TreeElement *element = tree->first, *element_next; element; element = element_next) {
- element_next = element->next;
- outliner_free_tree_element(element, tree);
- }
+ for (TreeElement *element = tree->first, *element_next; element; element = element_next) {
+ element_next = element->next;
+ outliner_free_tree_element(element, tree);
+ }
}
void outliner_cleanup_tree(SpaceOutliner *soops)
{
- outliner_free_tree(&soops->tree);
- outliner_storage_cleanup(soops);
+ outliner_free_tree(&soops->tree);
+ outliner_storage_cleanup(soops);
}
/**
@@ -211,926 +211,924 @@ void outliner_cleanup_tree(SpaceOutliner *soops)
*/
void outliner_free_tree_element(TreeElement *element, ListBase *parent_subtree)
{
- BLI_assert(BLI_findindex(parent_subtree, element) > -1);
- BLI_remlink(parent_subtree, element);
+ BLI_assert(BLI_findindex(parent_subtree, element) > -1);
+ BLI_remlink(parent_subtree, element);
- outliner_free_tree(&element->subtree);
+ outliner_free_tree(&element->subtree);
- if (element->flag & TE_FREE_NAME) {
- MEM_freeN((void *)element->name);
- }
- MEM_freeN(element);
+ if (element->flag & TE_FREE_NAME) {
+ MEM_freeN((void *)element->name);
+ }
+ MEM_freeN(element);
}
-
/* ********************************************************* */
/* Prototype, see functions below */
-static TreeElement *outliner_add_element(SpaceOutliner *soops, ListBase *lb, void *idv,
- TreeElement *parent, short type, short index);
+static TreeElement *outliner_add_element(
+ SpaceOutliner *soops, ListBase *lb, void *idv, TreeElement *parent, short type, short index);
/* -------------------------------------------------------- */
/* special handling of hierarchical non-lib data */
-static void outliner_add_bone(SpaceOutliner *soops, ListBase *lb, ID *id, Bone *curBone,
- TreeElement *parent, int *a)
+static void outliner_add_bone(
+ SpaceOutliner *soops, ListBase *lb, ID *id, Bone *curBone, TreeElement *parent, int *a)
{
- TreeElement *te = outliner_add_element(soops, lb, id, parent, TSE_BONE, *a);
+ TreeElement *te = outliner_add_element(soops, lb, id, parent, TSE_BONE, *a);
- (*a)++;
- te->name = curBone->name;
- te->directdata = curBone;
+ (*a)++;
+ te->name = curBone->name;
+ te->directdata = curBone;
- for (curBone = curBone->childbase.first; curBone; curBone = curBone->next) {
- outliner_add_bone(soops, &te->subtree, id, curBone, te, a);
- }
+ for (curBone = curBone->childbase.first; curBone; curBone = curBone->next) {
+ outliner_add_bone(soops, &te->subtree, id, curBone, te, a);
+ }
}
static bool outliner_animdata_test(AnimData *adt)
{
- if (adt) {
- return (adt->action || adt->drivers.first || adt->nla_tracks.first);
- }
- return false;
+ if (adt) {
+ return (adt->action || adt->drivers.first || adt->nla_tracks.first);
+ }
+ return false;
}
#ifdef WITH_FREESTYLE
-static void outliner_add_line_styles(SpaceOutliner *soops, ListBase *lb, Scene *sce, TreeElement *te)
+static void outliner_add_line_styles(SpaceOutliner *soops,
+ ListBase *lb,
+ Scene *sce,
+ TreeElement *te)
{
- ViewLayer *view_layer;
- FreestyleLineSet *lineset;
-
- for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
- for (lineset = view_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
- FreestyleLineStyle *linestyle = lineset->linestyle;
- if (linestyle) {
- linestyle->id.tag |= LIB_TAG_DOIT;
- }
- }
- }
- for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
- for (lineset = view_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
- FreestyleLineStyle *linestyle = lineset->linestyle;
- if (linestyle) {
- if (!(linestyle->id.tag & LIB_TAG_DOIT)) {
- continue;
- }
- linestyle->id.tag &= ~LIB_TAG_DOIT;
- outliner_add_element(soops, lb, linestyle, te, 0, 0);
- }
- }
- }
+ ViewLayer *view_layer;
+ FreestyleLineSet *lineset;
+
+ for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (lineset = view_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
+ FreestyleLineStyle *linestyle = lineset->linestyle;
+ if (linestyle) {
+ linestyle->id.tag |= LIB_TAG_DOIT;
+ }
+ }
+ }
+ for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (lineset = view_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
+ FreestyleLineStyle *linestyle = lineset->linestyle;
+ if (linestyle) {
+ if (!(linestyle->id.tag & LIB_TAG_DOIT)) {
+ continue;
+ }
+ linestyle->id.tag &= ~LIB_TAG_DOIT;
+ outliner_add_element(soops, lb, linestyle, te, 0, 0);
+ }
+ }
+ }
}
#endif
-static void outliner_add_scene_contents(SpaceOutliner *soops, ListBase *lb, Scene *sce, TreeElement *te)
+static void outliner_add_scene_contents(SpaceOutliner *soops,
+ ListBase *lb,
+ Scene *sce,
+ TreeElement *te)
{
- /* View layers */
- TreeElement *ten = outliner_add_element(soops, lb, sce, te, TSE_R_LAYER_BASE, 0);
- ten->name = IFACE_("View Layers");
-
- ViewLayer *view_layer;
- for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
- TreeElement *tenlay = outliner_add_element(soops, &ten->subtree, sce, te, TSE_R_LAYER, 0);
- tenlay->name = view_layer->name;
- tenlay->directdata = view_layer;
- }
-
- /* Collections */
- ten = outliner_add_element(soops, lb, &sce->id, te, TSE_SCENE_COLLECTION_BASE, 0);
- ten->name = IFACE_("Scene Collection");
- outliner_add_collection_recursive(soops, sce->master_collection, ten);
-
- /* Objects */
- ten = outliner_add_element(soops, lb, sce, te, TSE_SCENE_OBJECTS_BASE, 0);
- ten->name = IFACE_("Objects");
- FOREACH_SCENE_OBJECT_BEGIN(sce, ob)
- {
- outliner_add_element(soops, &ten->subtree, ob, NULL, 0, 0);
- }
- FOREACH_SCENE_OBJECT_END;
- outliner_make_object_parent_hierarchy(&ten->subtree);
-
- /* Animation Data */
- if (outliner_animdata_test(sce->adt)) {
- outliner_add_element(soops, lb, sce, te, TSE_ANIM_DATA, 0);
- }
-
+ /* View layers */
+ TreeElement *ten = outliner_add_element(soops, lb, sce, te, TSE_R_LAYER_BASE, 0);
+ ten->name = IFACE_("View Layers");
+
+ ViewLayer *view_layer;
+ for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
+ TreeElement *tenlay = outliner_add_element(soops, &ten->subtree, sce, te, TSE_R_LAYER, 0);
+ tenlay->name = view_layer->name;
+ tenlay->directdata = view_layer;
+ }
+
+ /* Collections */
+ ten = outliner_add_element(soops, lb, &sce->id, te, TSE_SCENE_COLLECTION_BASE, 0);
+ ten->name = IFACE_("Scene Collection");
+ outliner_add_collection_recursive(soops, sce->master_collection, ten);
+
+ /* Objects */
+ ten = outliner_add_element(soops, lb, sce, te, TSE_SCENE_OBJECTS_BASE, 0);
+ ten->name = IFACE_("Objects");
+ FOREACH_SCENE_OBJECT_BEGIN (sce, ob) {
+ outliner_add_element(soops, &ten->subtree, ob, NULL, 0, 0);
+ }
+ FOREACH_SCENE_OBJECT_END;
+ outliner_make_object_parent_hierarchy(&ten->subtree);
+
+ /* Animation Data */
+ if (outliner_animdata_test(sce->adt)) {
+ outliner_add_element(soops, lb, sce, te, TSE_ANIM_DATA, 0);
+ }
}
// can be inlined if necessary
-static void outliner_add_object_contents(SpaceOutliner *soops, TreeElement *te, TreeStoreElem *tselem, Object *ob)
+static void outliner_add_object_contents(SpaceOutliner *soops,
+ TreeElement *te,
+ TreeStoreElem *tselem,
+ Object *ob)
{
- if (outliner_animdata_test(ob->adt)) {
- outliner_add_element(soops, &te->subtree, ob, te, TSE_ANIM_DATA, 0);
- }
-
- outliner_add_element(soops, &te->subtree, ob->poselib, te, 0, 0); // XXX FIXME.. add a special type for this
-
- if (ob->proxy && !ID_IS_LINKED(ob)) {
- outliner_add_element(soops, &te->subtree, ob->proxy, te, TSE_PROXY, 0);
- }
-
- outliner_add_element(soops, &te->subtree, ob->data, te, 0, 0);
-
- if (ob->pose) {
- bArmature *arm = ob->data;
- bPoseChannel *pchan;
- TreeElement *tenla = outliner_add_element(soops, &te->subtree, ob, te, TSE_POSE_BASE, 0);
-
- tenla->name = IFACE_("Pose");
-
- /* channels undefined in editmode, but we want the 'tenla' pose icon itself */
- if ((arm->edbo == NULL) && (ob->mode & OB_MODE_POSE)) {
- TreeElement *ten;
- int a = 0, const_index = 1000; /* ensure unique id for bone constraints */
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next, a++) {
- ten = outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_POSE_CHANNEL, a);
- ten->name = pchan->name;
- ten->directdata = pchan;
- pchan->temp = (void *)ten;
-
- if (pchan->constraints.first) {
- //Object *target;
- bConstraint *con;
- TreeElement *ten1;
- TreeElement *tenla1 = outliner_add_element(soops, &ten->subtree, ob, ten, TSE_CONSTRAINT_BASE, 0);
- //char *str;
-
- tenla1->name = IFACE_("Constraints");
- for (con = pchan->constraints.first; con; con = con->next, const_index++) {
- ten1 = outliner_add_element(soops, &tenla1->subtree, ob, tenla1, TSE_CONSTRAINT, const_index);
+ if (outliner_animdata_test(ob->adt)) {
+ outliner_add_element(soops, &te->subtree, ob, te, TSE_ANIM_DATA, 0);
+ }
+
+ outliner_add_element(
+ soops, &te->subtree, ob->poselib, te, 0, 0); // XXX FIXME.. add a special type for this
+
+ if (ob->proxy && !ID_IS_LINKED(ob)) {
+ outliner_add_element(soops, &te->subtree, ob->proxy, te, TSE_PROXY, 0);
+ }
+
+ outliner_add_element(soops, &te->subtree, ob->data, te, 0, 0);
+
+ if (ob->pose) {
+ bArmature *arm = ob->data;
+ bPoseChannel *pchan;
+ TreeElement *tenla = outliner_add_element(soops, &te->subtree, ob, te, TSE_POSE_BASE, 0);
+
+ tenla->name = IFACE_("Pose");
+
+ /* channels undefined in editmode, but we want the 'tenla' pose icon itself */
+ if ((arm->edbo == NULL) && (ob->mode & OB_MODE_POSE)) {
+ TreeElement *ten;
+ int a = 0, const_index = 1000; /* ensure unique id for bone constraints */
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next, a++) {
+ ten = outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_POSE_CHANNEL, a);
+ ten->name = pchan->name;
+ ten->directdata = pchan;
+ pchan->temp = (void *)ten;
+
+ if (pchan->constraints.first) {
+ //Object *target;
+ bConstraint *con;
+ TreeElement *ten1;
+ TreeElement *tenla1 = outliner_add_element(
+ soops, &ten->subtree, ob, ten, TSE_CONSTRAINT_BASE, 0);
+ //char *str;
+
+ tenla1->name = IFACE_("Constraints");
+ for (con = pchan->constraints.first; con; con = con->next, const_index++) {
+ ten1 = outliner_add_element(
+ soops, &tenla1->subtree, ob, tenla1, TSE_CONSTRAINT, const_index);
#if 0 /* disabled as it needs to be reworked for recoded constraints system */
- target = get_constraint_target(con, &str);
- if (str && str[0]) ten1->name = str;
- else if (target) ten1->name = target->id.name + 2;
- else ten1->name = con->name;
+ target = get_constraint_target(con, &str);
+ if (str && str[0]) ten1->name = str;
+ else if (target) ten1->name = target->id.name + 2;
+ else ten1->name = con->name;
#endif
- ten1->name = con->name;
- ten1->directdata = con;
- /* possible add all other types links? */
- }
- }
- }
- /* make hierarchy */
- ten = tenla->subtree.first;
- while (ten) {
- TreeElement *nten = ten->next, *par;
- tselem = TREESTORE(ten);
- if (tselem->type == TSE_POSE_CHANNEL) {
- pchan = (bPoseChannel *)ten->directdata;
- if (pchan->parent) {
- BLI_remlink(&tenla->subtree, ten);
- par = (TreeElement *)pchan->parent->temp;
- BLI_addtail(&par->subtree, ten);
- ten->parent = par;
- }
- }
- ten = nten;
- }
- }
-
- /* Pose Groups */
- if (ob->pose->agroups.first) {
- bActionGroup *agrp;
- TreeElement *ten_bonegrp = outliner_add_element(soops, &te->subtree, ob, te, TSE_POSEGRP_BASE, 0);
- int a = 0;
-
- ten_bonegrp->name = IFACE_("Bone Groups");
- for (agrp = ob->pose->agroups.first; agrp; agrp = agrp->next, a++) {
- TreeElement *ten;
- ten = outliner_add_element(soops, &ten_bonegrp->subtree, ob, ten_bonegrp, TSE_POSEGRP, a);
- ten->name = agrp->name;
- ten->directdata = agrp;
- }
- }
- }
-
- for (int a = 0; a < ob->totcol; a++) {
- outliner_add_element(soops, &te->subtree, ob->mat[a], te, 0, a);
- }
-
- if (ob->constraints.first) {
- //Object *target;
- bConstraint *con;
- TreeElement *ten;
- TreeElement *tenla = outliner_add_element(soops, &te->subtree, ob, te, TSE_CONSTRAINT_BASE, 0);
- //char *str;
- int a;
-
- tenla->name = IFACE_("Constraints");
- for (con = ob->constraints.first, a = 0; con; con = con->next, a++) {
- ten = outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_CONSTRAINT, a);
+ ten1->name = con->name;
+ ten1->directdata = con;
+ /* possible add all other types links? */
+ }
+ }
+ }
+ /* make hierarchy */
+ ten = tenla->subtree.first;
+ while (ten) {
+ TreeElement *nten = ten->next, *par;
+ tselem = TREESTORE(ten);
+ if (tselem->type == TSE_POSE_CHANNEL) {
+ pchan = (bPoseChannel *)ten->directdata;
+ if (pchan->parent) {
+ BLI_remlink(&tenla->subtree, ten);
+ par = (TreeElement *)pchan->parent->temp;
+ BLI_addtail(&par->subtree, ten);
+ ten->parent = par;
+ }
+ }
+ ten = nten;
+ }
+ }
+
+ /* Pose Groups */
+ if (ob->pose->agroups.first) {
+ bActionGroup *agrp;
+ TreeElement *ten_bonegrp = outliner_add_element(
+ soops, &te->subtree, ob, te, TSE_POSEGRP_BASE, 0);
+ int a = 0;
+
+ ten_bonegrp->name = IFACE_("Bone Groups");
+ for (agrp = ob->pose->agroups.first; agrp; agrp = agrp->next, a++) {
+ TreeElement *ten;
+ ten = outliner_add_element(soops, &ten_bonegrp->subtree, ob, ten_bonegrp, TSE_POSEGRP, a);
+ ten->name = agrp->name;
+ ten->directdata = agrp;
+ }
+ }
+ }
+
+ for (int a = 0; a < ob->totcol; a++) {
+ outliner_add_element(soops, &te->subtree, ob->mat[a], te, 0, a);
+ }
+
+ if (ob->constraints.first) {
+ //Object *target;
+ bConstraint *con;
+ TreeElement *ten;
+ TreeElement *tenla = outliner_add_element(soops, &te->subtree, ob, te, TSE_CONSTRAINT_BASE, 0);
+ //char *str;
+ int a;
+
+ tenla->name = IFACE_("Constraints");
+ for (con = ob->constraints.first, a = 0; con; con = con->next, a++) {
+ ten = outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_CONSTRAINT, a);
#if 0 /* disabled due to constraints system targets recode... code here needs review */
- target = get_constraint_target(con, &str);
- if (str && str[0]) ten->name = str;
- else if (target) ten->name = target->id.name + 2;
- else ten->name = con->name;
+ target = get_constraint_target(con, &str);
+ if (str && str[0]) ten->name = str;
+ else if (target) ten->name = target->id.name + 2;
+ else ten->name = con->name;
#endif
- ten->name = con->name;
- ten->directdata = con;
- /* possible add all other types links? */
- }
- }
-
- if (ob->modifiers.first) {
- ModifierData *md;
- TreeElement *ten_mod = outliner_add_element(soops, &te->subtree, ob, te, TSE_MODIFIER_BASE, 0);
- int index;
-
- ten_mod->name = IFACE_("Modifiers");
- for (index = 0, md = ob->modifiers.first; md; index++, md = md->next) {
- TreeElement *ten = outliner_add_element(soops, &ten_mod->subtree, ob, ten_mod, TSE_MODIFIER, index);
- ten->name = md->name;
- ten->directdata = md;
-
- if (md->type == eModifierType_Lattice) {
- outliner_add_element(soops, &ten->subtree, ((LatticeModifierData *) md)->object, ten, TSE_LINKED_OB, 0);
- }
- else if (md->type == eModifierType_Curve) {
- outliner_add_element(soops, &ten->subtree, ((CurveModifierData *) md)->object, ten, TSE_LINKED_OB, 0);
- }
- else if (md->type == eModifierType_Armature) {
- outliner_add_element(soops, &ten->subtree, ((ArmatureModifierData *) md)->object, ten, TSE_LINKED_OB, 0);
- }
- else if (md->type == eModifierType_Hook) {
- outliner_add_element(soops, &ten->subtree, ((HookModifierData *) md)->object, ten, TSE_LINKED_OB, 0);
- }
- else if (md->type == eModifierType_ParticleSystem) {
- ParticleSystem *psys = ((ParticleSystemModifierData *) md)->psys;
- TreeElement *ten_psys;
-
- ten_psys = outliner_add_element(soops, &ten->subtree, ob, te, TSE_LINKED_PSYS, 0);
- ten_psys->directdata = psys;
- ten_psys->name = psys->part->id.name + 2;
- }
- }
- }
-
- /* vertex groups */
- if (ob->defbase.first) {
- bDeformGroup *defgroup;
- TreeElement *ten;
- TreeElement *tenla = outliner_add_element(soops, &te->subtree, ob, te, TSE_DEFGROUP_BASE, 0);
- int a;
-
- tenla->name = IFACE_("Vertex Groups");
- for (defgroup = ob->defbase.first, a = 0; defgroup; defgroup = defgroup->next, a++) {
- ten = outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_DEFGROUP, a);
- ten->name = defgroup->name;
- ten->directdata = defgroup;
- }
- }
-
- /* duplicated group */
- if (ob->instance_collection) {
- outliner_add_element(soops, &te->subtree, ob->instance_collection, te, 0, 0);
- }
+ ten->name = con->name;
+ ten->directdata = con;
+ /* possible add all other types links? */
+ }
+ }
+
+ if (ob->modifiers.first) {
+ ModifierData *md;
+ TreeElement *ten_mod = outliner_add_element(soops, &te->subtree, ob, te, TSE_MODIFIER_BASE, 0);
+ int index;
+
+ ten_mod->name = IFACE_("Modifiers");
+ for (index = 0, md = ob->modifiers.first; md; index++, md = md->next) {
+ TreeElement *ten = outliner_add_element(
+ soops, &ten_mod->subtree, ob, ten_mod, TSE_MODIFIER, index);
+ ten->name = md->name;
+ ten->directdata = md;
+
+ if (md->type == eModifierType_Lattice) {
+ outliner_add_element(
+ soops, &ten->subtree, ((LatticeModifierData *)md)->object, ten, TSE_LINKED_OB, 0);
+ }
+ else if (md->type == eModifierType_Curve) {
+ outliner_add_element(
+ soops, &ten->subtree, ((CurveModifierData *)md)->object, ten, TSE_LINKED_OB, 0);
+ }
+ else if (md->type == eModifierType_Armature) {
+ outliner_add_element(
+ soops, &ten->subtree, ((ArmatureModifierData *)md)->object, ten, TSE_LINKED_OB, 0);
+ }
+ else if (md->type == eModifierType_Hook) {
+ outliner_add_element(
+ soops, &ten->subtree, ((HookModifierData *)md)->object, ten, TSE_LINKED_OB, 0);
+ }
+ else if (md->type == eModifierType_ParticleSystem) {
+ ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys;
+ TreeElement *ten_psys;
+
+ ten_psys = outliner_add_element(soops, &ten->subtree, ob, te, TSE_LINKED_PSYS, 0);
+ ten_psys->directdata = psys;
+ ten_psys->name = psys->part->id.name + 2;
+ }
+ }
+ }
+
+ /* vertex groups */
+ if (ob->defbase.first) {
+ bDeformGroup *defgroup;
+ TreeElement *ten;
+ TreeElement *tenla = outliner_add_element(soops, &te->subtree, ob, te, TSE_DEFGROUP_BASE, 0);
+ int a;
+
+ tenla->name = IFACE_("Vertex Groups");
+ for (defgroup = ob->defbase.first, a = 0; defgroup; defgroup = defgroup->next, a++) {
+ ten = outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_DEFGROUP, a);
+ ten->name = defgroup->name;
+ ten->directdata = defgroup;
+ }
+ }
+
+ /* duplicated group */
+ if (ob->instance_collection) {
+ outliner_add_element(soops, &te->subtree, ob->instance_collection, te, 0, 0);
+ }
}
-
// can be inlined if necessary
-static void outliner_add_id_contents(SpaceOutliner *soops, TreeElement *te, TreeStoreElem *tselem, ID *id)
+static void outliner_add_id_contents(SpaceOutliner *soops,
+ TreeElement *te,
+ TreeStoreElem *tselem,
+ ID *id)
{
- /* tuck pointer back in object, to construct hierarchy */
- if (GS(id->name) == ID_OB) {
- id->newid = (ID *)te;
- }
-
- /* expand specific data always */
- switch (GS(id->name)) {
- case ID_LI:
- {
- te->name = ((Library *)id)->name;
- break;
- }
- case ID_SCE:
- {
- outliner_add_scene_contents(soops, &te->subtree, (Scene *)id, te);
- break;
- }
- case ID_OB:
- {
- outliner_add_object_contents(soops, te, tselem, (Object *)id);
- break;
- }
- case ID_ME:
- {
- Mesh *me = (Mesh *)id;
- int a;
-
- if (outliner_animdata_test(me->adt)) {
- outliner_add_element(soops, &te->subtree, me, te, TSE_ANIM_DATA, 0);
- }
-
- outliner_add_element(soops, &te->subtree, me->key, te, 0, 0);
- for (a = 0; a < me->totcol; a++) {
- outliner_add_element(soops, &te->subtree, me->mat[a], te, 0, a);
- }
- /* could do tfaces with image links, but the images are not grouped nicely.
- * would require going over all tfaces, sort images in use. etc... */
- break;
- }
- case ID_CU:
- {
- Curve *cu = (Curve *)id;
- int a;
-
- if (outliner_animdata_test(cu->adt)) {
- outliner_add_element(soops, &te->subtree, cu, te, TSE_ANIM_DATA, 0);
- }
-
- for (a = 0; a < cu->totcol; a++) {
- outliner_add_element(soops, &te->subtree, cu->mat[a], te, 0, a);
- }
- break;
- }
- case ID_MB:
- {
- MetaBall *mb = (MetaBall *)id;
- int a;
-
- if (outliner_animdata_test(mb->adt)) {
- outliner_add_element(soops, &te->subtree, mb, te, TSE_ANIM_DATA, 0);
- }
-
- for (a = 0; a < mb->totcol; a++) {
- outliner_add_element(soops, &te->subtree, mb->mat[a], te, 0, a);
- }
- break;
- }
- case ID_MA:
- {
- Material *ma = (Material *)id;
-
- if (outliner_animdata_test(ma->adt)) {
- outliner_add_element(soops, &te->subtree, ma, te, TSE_ANIM_DATA, 0);
- }
- break;
- }
- case ID_TE:
- {
- Tex *tex = (Tex *)id;
-
- if (outliner_animdata_test(tex->adt)) {
- outliner_add_element(soops, &te->subtree, tex, te, TSE_ANIM_DATA, 0);
- }
- outliner_add_element(soops, &te->subtree, tex->ima, te, 0, 0);
- break;
- }
- case ID_CA:
- {
- Camera *ca = (Camera *)id;
-
- if (outliner_animdata_test(ca->adt)) {
- outliner_add_element(soops, &te->subtree, ca, te, TSE_ANIM_DATA, 0);
- }
- break;
- }
- case ID_CF:
- {
- CacheFile *cache_file = (CacheFile *)id;
-
- if (outliner_animdata_test(cache_file->adt)) {
- outliner_add_element(soops, &te->subtree, cache_file, te, TSE_ANIM_DATA, 0);
- }
-
- break;
- }
- case ID_LA:
- {
- Light *la = (Light *)id;
-
- if (outliner_animdata_test(la->adt)) {
- outliner_add_element(soops, &te->subtree, la, te, TSE_ANIM_DATA, 0);
- }
- break;
- }
- case ID_SPK:
- {
- Speaker *spk = (Speaker *)id;
-
- if (outliner_animdata_test(spk->adt)) {
- outliner_add_element(soops, &te->subtree, spk, te, TSE_ANIM_DATA, 0);
- }
- break;
- }
- case ID_LP:
- {
- LightProbe *prb = (LightProbe *)id;
-
- if (outliner_animdata_test(prb->adt)) {
- outliner_add_element(soops, &te->subtree, prb, te, TSE_ANIM_DATA, 0);
- }
- break;
- }
- case ID_WO:
- {
- World *wrld = (World *)id;
-
- if (outliner_animdata_test(wrld->adt)) {
- outliner_add_element(soops, &te->subtree, wrld, te, TSE_ANIM_DATA, 0);
- }
- break;
- }
- case ID_KE:
- {
- Key *key = (Key *)id;
-
- if (outliner_animdata_test(key->adt)) {
- outliner_add_element(soops, &te->subtree, key, te, TSE_ANIM_DATA, 0);
- }
- break;
- }
- case ID_AC:
- {
- // XXX do we want to be exposing the F-Curves here?
- //bAction *act = (bAction *)id;
- break;
- }
- case ID_AR:
- {
- bArmature *arm = (bArmature *)id;
- int a = 0;
-
- if (outliner_animdata_test(arm->adt)) {
- outliner_add_element(soops, &te->subtree, arm, te, TSE_ANIM_DATA, 0);
- }
-
- if (arm->edbo) {
- EditBone *ebone;
- TreeElement *ten;
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next, a++) {
- ten = outliner_add_element(soops, &te->subtree, id, te, TSE_EBONE, a);
- ten->directdata = ebone;
- ten->name = ebone->name;
- ebone->temp.p = ten;
- }
- /* make hierarchy */
- ten = arm->edbo->first ? ((EditBone *)arm->edbo->first)->temp.p : NULL;
- while (ten) {
- TreeElement *nten = ten->next, *par;
- ebone = (EditBone *)ten->directdata;
- if (ebone->parent) {
- BLI_remlink(&te->subtree, ten);
- par = ebone->parent->temp.p;
- BLI_addtail(&par->subtree, ten);
- ten->parent = par;
- }
- ten = nten;
- }
- }
- else {
- /* do not extend Armature when we have posemode */
- tselem = TREESTORE(te->parent);
- if (GS(tselem->id->name) == ID_OB && ((Object *)tselem->id)->mode & OB_MODE_POSE) {
- /* pass */
- }
- else {
- Bone *curBone;
- for (curBone = arm->bonebase.first; curBone; curBone = curBone->next) {
- outliner_add_bone(soops, &te->subtree, id, curBone, te, &a);
- }
- }
- }
- break;
- }
- case ID_LS:
- {
- FreestyleLineStyle *linestyle = (FreestyleLineStyle *)id;
- int a;
-
- if (outliner_animdata_test(linestyle->adt)) {
- outliner_add_element(soops, &te->subtree, linestyle, te, TSE_ANIM_DATA, 0);
- }
-
- for (a = 0; a < MAX_MTEX; a++) {
- if (linestyle->mtex[a]) {
- outliner_add_element(soops, &te->subtree, linestyle->mtex[a]->tex, te, 0, a);
- }
- }
- break;
- }
- case ID_GD:
- {
- bGPdata *gpd = (bGPdata *)id;
- bGPDlayer *gpl;
- int a = 0;
-
- if (outliner_animdata_test(gpd->adt)) {
- outliner_add_element(soops, &te->subtree, gpd, te, TSE_ANIM_DATA, 0);
- }
-
- // TODO: base element for layers?
- for (gpl = gpd->layers.last; gpl; gpl = gpl->prev) {
- outliner_add_element(soops, &te->subtree, gpl, te, TSE_GP_LAYER, a);
- a++;
- }
- break;
- }
- case ID_GR:
- {
- /* Don't expand for instances, creates too many elements. */
- if (!(te->parent && te->parent->idcode == ID_OB)) {
- Collection *collection = (Collection *)id;
- outliner_add_collection_recursive(soops, collection, te);
- }
- }
- default:
- break;
- }
+ /* tuck pointer back in object, to construct hierarchy */
+ if (GS(id->name) == ID_OB) {
+ id->newid = (ID *)te;
+ }
+
+ /* expand specific data always */
+ switch (GS(id->name)) {
+ case ID_LI: {
+ te->name = ((Library *)id)->name;
+ break;
+ }
+ case ID_SCE: {
+ outliner_add_scene_contents(soops, &te->subtree, (Scene *)id, te);
+ break;
+ }
+ case ID_OB: {
+ outliner_add_object_contents(soops, te, tselem, (Object *)id);
+ break;
+ }
+ case ID_ME: {
+ Mesh *me = (Mesh *)id;
+ int a;
+
+ if (outliner_animdata_test(me->adt)) {
+ outliner_add_element(soops, &te->subtree, me, te, TSE_ANIM_DATA, 0);
+ }
+
+ outliner_add_element(soops, &te->subtree, me->key, te, 0, 0);
+ for (a = 0; a < me->totcol; a++) {
+ outliner_add_element(soops, &te->subtree, me->mat[a], te, 0, a);
+ }
+ /* could do tfaces with image links, but the images are not grouped nicely.
+ * would require going over all tfaces, sort images in use. etc... */
+ break;
+ }
+ case ID_CU: {
+ Curve *cu = (Curve *)id;
+ int a;
+
+ if (outliner_animdata_test(cu->adt)) {
+ outliner_add_element(soops, &te->subtree, cu, te, TSE_ANIM_DATA, 0);
+ }
+
+ for (a = 0; a < cu->totcol; a++) {
+ outliner_add_element(soops, &te->subtree, cu->mat[a], te, 0, a);
+ }
+ break;
+ }
+ case ID_MB: {
+ MetaBall *mb = (MetaBall *)id;
+ int a;
+
+ if (outliner_animdata_test(mb->adt)) {
+ outliner_add_element(soops, &te->subtree, mb, te, TSE_ANIM_DATA, 0);
+ }
+
+ for (a = 0; a < mb->totcol; a++) {
+ outliner_add_element(soops, &te->subtree, mb->mat[a], te, 0, a);
+ }
+ break;
+ }
+ case ID_MA: {
+ Material *ma = (Material *)id;
+
+ if (outliner_animdata_test(ma->adt)) {
+ outliner_add_element(soops, &te->subtree, ma, te, TSE_ANIM_DATA, 0);
+ }
+ break;
+ }
+ case ID_TE: {
+ Tex *tex = (Tex *)id;
+
+ if (outliner_animdata_test(tex->adt)) {
+ outliner_add_element(soops, &te->subtree, tex, te, TSE_ANIM_DATA, 0);
+ }
+ outliner_add_element(soops, &te->subtree, tex->ima, te, 0, 0);
+ break;
+ }
+ case ID_CA: {
+ Camera *ca = (Camera *)id;
+
+ if (outliner_animdata_test(ca->adt)) {
+ outliner_add_element(soops, &te->subtree, ca, te, TSE_ANIM_DATA, 0);
+ }
+ break;
+ }
+ case ID_CF: {
+ CacheFile *cache_file = (CacheFile *)id;
+
+ if (outliner_animdata_test(cache_file->adt)) {
+ outliner_add_element(soops, &te->subtree, cache_file, te, TSE_ANIM_DATA, 0);
+ }
+
+ break;
+ }
+ case ID_LA: {
+ Light *la = (Light *)id;
+
+ if (outliner_animdata_test(la->adt)) {
+ outliner_add_element(soops, &te->subtree, la, te, TSE_ANIM_DATA, 0);
+ }
+ break;
+ }
+ case ID_SPK: {
+ Speaker *spk = (Speaker *)id;
+
+ if (outliner_animdata_test(spk->adt)) {
+ outliner_add_element(soops, &te->subtree, spk, te, TSE_ANIM_DATA, 0);
+ }
+ break;
+ }
+ case ID_LP: {
+ LightProbe *prb = (LightProbe *)id;
+
+ if (outliner_animdata_test(prb->adt)) {
+ outliner_add_element(soops, &te->subtree, prb, te, TSE_ANIM_DATA, 0);
+ }
+ break;
+ }
+ case ID_WO: {
+ World *wrld = (World *)id;
+
+ if (outliner_animdata_test(wrld->adt)) {
+ outliner_add_element(soops, &te->subtree, wrld, te, TSE_ANIM_DATA, 0);
+ }
+ break;
+ }
+ case ID_KE: {
+ Key *key = (Key *)id;
+
+ if (outliner_animdata_test(key->adt)) {
+ outliner_add_element(soops, &te->subtree, key, te, TSE_ANIM_DATA, 0);
+ }
+ break;
+ }
+ case ID_AC: {
+ // XXX do we want to be exposing the F-Curves here?
+ //bAction *act = (bAction *)id;
+ break;
+ }
+ case ID_AR: {
+ bArmature *arm = (bArmature *)id;
+ int a = 0;
+
+ if (outliner_animdata_test(arm->adt)) {
+ outliner_add_element(soops, &te->subtree, arm, te, TSE_ANIM_DATA, 0);
+ }
+
+ if (arm->edbo) {
+ EditBone *ebone;
+ TreeElement *ten;
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next, a++) {
+ ten = outliner_add_element(soops, &te->subtree, id, te, TSE_EBONE, a);
+ ten->directdata = ebone;
+ ten->name = ebone->name;
+ ebone->temp.p = ten;
+ }
+ /* make hierarchy */
+ ten = arm->edbo->first ? ((EditBone *)arm->edbo->first)->temp.p : NULL;
+ while (ten) {
+ TreeElement *nten = ten->next, *par;
+ ebone = (EditBone *)ten->directdata;
+ if (ebone->parent) {
+ BLI_remlink(&te->subtree, ten);
+ par = ebone->parent->temp.p;
+ BLI_addtail(&par->subtree, ten);
+ ten->parent = par;
+ }
+ ten = nten;
+ }
+ }
+ else {
+ /* do not extend Armature when we have posemode */
+ tselem = TREESTORE(te->parent);
+ if (GS(tselem->id->name) == ID_OB && ((Object *)tselem->id)->mode & OB_MODE_POSE) {
+ /* pass */
+ }
+ else {
+ Bone *curBone;
+ for (curBone = arm->bonebase.first; curBone; curBone = curBone->next) {
+ outliner_add_bone(soops, &te->subtree, id, curBone, te, &a);
+ }
+ }
+ }
+ break;
+ }
+ case ID_LS: {
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)id;
+ int a;
+
+ if (outliner_animdata_test(linestyle->adt)) {
+ outliner_add_element(soops, &te->subtree, linestyle, te, TSE_ANIM_DATA, 0);
+ }
+
+ for (a = 0; a < MAX_MTEX; a++) {
+ if (linestyle->mtex[a]) {
+ outliner_add_element(soops, &te->subtree, linestyle->mtex[a]->tex, te, 0, a);
+ }
+ }
+ break;
+ }
+ case ID_GD: {
+ bGPdata *gpd = (bGPdata *)id;
+ bGPDlayer *gpl;
+ int a = 0;
+
+ if (outliner_animdata_test(gpd->adt)) {
+ outliner_add_element(soops, &te->subtree, gpd, te, TSE_ANIM_DATA, 0);
+ }
+
+ // TODO: base element for layers?
+ for (gpl = gpd->layers.last; gpl; gpl = gpl->prev) {
+ outliner_add_element(soops, &te->subtree, gpl, te, TSE_GP_LAYER, a);
+ a++;
+ }
+ break;
+ }
+ case ID_GR: {
+ /* Don't expand for instances, creates too many elements. */
+ if (!(te->parent && te->parent->idcode == ID_OB)) {
+ Collection *collection = (Collection *)id;
+ outliner_add_collection_recursive(soops, collection, te);
+ }
+ }
+ default:
+ break;
+ }
}
// TODO: this function needs to be split up! It's getting a bit too large...
// Note: "ID" is not always a real ID
-static TreeElement *outliner_add_element(SpaceOutliner *soops, ListBase *lb, void *idv,
- TreeElement *parent, short type, short index)
+static TreeElement *outliner_add_element(
+ SpaceOutliner *soops, ListBase *lb, void *idv, TreeElement *parent, short type, short index)
{
- TreeElement *te;
- TreeStoreElem *tselem;
- ID *id = idv;
-
- if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
- id = ((PointerRNA *)idv)->id.data;
- if (!id) {
- id = ((PointerRNA *)idv)->data;
- }
- }
- else if (type == TSE_GP_LAYER) {
- /* idv is the layer its self */
- id = TREESTORE(parent)->id;
- }
-
- /* exceptions */
- if (type == TSE_ID_BASE) {
- /* pass */
- }
- else if (id == NULL) {
- return NULL;
- }
-
- if (type == 0) {
- /* Zero type means real ID, ensure we do not get non-outliner ID types here... */
- BLI_assert(TREESTORE_ID_TYPE(id));
- }
-
- te = MEM_callocN(sizeof(TreeElement), "tree elem");
- /* add to the visual tree */
- BLI_addtail(lb, te);
- /* add to the storage */
- check_persistent(soops, te, id, type, index);
- tselem = TREESTORE(te);
-
- /* if we are searching for something expand to see child elements */
- if (SEARCHING_OUTLINER(soops)) {
- tselem->flag |= TSE_CHILDSEARCH;
- }
-
- te->parent = parent;
- te->index = index; // for data arrays
- if (ELEM(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
- /* pass */
- }
- else if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
- /* pass */
- }
- else if (type == TSE_ANIM_DATA) {
- /* pass */
- }
- else if (type == TSE_GP_LAYER) {
- /* pass */
- }
- else if (ELEM(type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
- /* pass */
- }
- else if (type == TSE_ID_BASE) {
- /* pass */
- }
- else {
- /* do here too, for blend file viewer, own ID_LI then shows file name */
- if (GS(id->name) == ID_LI) {
- te->name = ((Library *)id)->name;
- }
- else {
- te->name = id->name + 2; // default, can be overridden by Library or non-ID data
- }
- te->idcode = GS(id->name);
- }
-
- if (type == 0) {
- TreeStoreElem *tsepar = parent ? TREESTORE(parent) : NULL;
-
- /* ID datablock */
- if (tsepar == NULL || tsepar->type != TSE_ID_BASE || soops->filter_id_type) {
- outliner_add_id_contents(soops, te, tselem, id);
- }
- }
- else if (type == TSE_ANIM_DATA) {
- IdAdtTemplate *iat = (IdAdtTemplate *)idv;
- AnimData *adt = (AnimData *)iat->adt;
-
- /* this element's info */
- te->name = IFACE_("Animation");
- te->directdata = adt;
-
- /* Action */
- outliner_add_element(soops, &te->subtree, adt->action, te, 0, 0);
-
- /* Drivers */
- if (adt->drivers.first) {
- TreeElement *ted = outliner_add_element(soops, &te->subtree, adt, te, TSE_DRIVER_BASE, 0);
- ID *lastadded = NULL;
- FCurve *fcu;
-
- ted->name = IFACE_("Drivers");
-
- for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
- if (fcu->driver && fcu->driver->variables.first) {
- ChannelDriver *driver = fcu->driver;
- DriverVar *dvar;
-
- for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
- /* loop over all targets used here */
- DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar)
- {
- if (lastadded != dtar->id) {
- // XXX this lastadded check is rather lame, and also fails quite badly...
- outliner_add_element(soops, &ted->subtree, dtar->id, ted, TSE_LINKED_OB, 0);
- lastadded = dtar->id;
- }
- }
- DRIVER_TARGETS_LOOPER_END;
- }
- }
- }
- }
-
- /* NLA Data */
- if (adt->nla_tracks.first) {
- TreeElement *tenla = outliner_add_element(soops, &te->subtree, adt, te, TSE_NLA, 0);
- NlaTrack *nlt;
- int a = 0;
-
- tenla->name = IFACE_("NLA Tracks");
-
- for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
- TreeElement *tenlt = outliner_add_element(soops, &tenla->subtree, nlt, tenla, TSE_NLA_TRACK, a);
- NlaStrip *strip;
- TreeElement *ten;
- int b = 0;
-
- tenlt->name = nlt->name;
-
- for (strip = nlt->strips.first; strip; strip = strip->next, b++) {
- ten = outliner_add_element(soops, &tenlt->subtree, strip->act, tenlt, TSE_NLA_ACTION, b);
- if (ten) {
- ten->directdata = strip;
- }
- }
- }
- }
- }
- else if (type == TSE_GP_LAYER) {
- bGPDlayer *gpl = (bGPDlayer *)idv;
-
- te->name = gpl->info;
- te->directdata = gpl;
- }
- else if (type == TSE_SEQUENCE) {
- Sequence *seq = (Sequence *) idv;
- Sequence *p;
-
- /*
- * The idcode is a little hack, but the outliner
- * only check te->idcode if te->type is equal to zero,
- * so this is "safe".
- */
- te->idcode = seq->type;
- te->directdata = seq;
- te->name = seq->name + 2;
-
- if (!(seq->type & SEQ_TYPE_EFFECT)) {
- /*
- * This work like the sequence.
- * If the sequence have a name (not default name)
- * show it, in other case put the filename.
- */
-
- if (seq->type == SEQ_TYPE_META) {
- p = seq->seqbase.first;
- while (p) {
- outliner_add_element(soops, &te->subtree, (void *)p, te, TSE_SEQUENCE, index);
- p = p->next;
- }
- }
- else {
- outliner_add_element(soops, &te->subtree, (void *)seq->strip, te, TSE_SEQ_STRIP, index);
- }
- }
- }
- else if (type == TSE_SEQ_STRIP) {
- Strip *strip = (Strip *)idv;
-
- if (strip->dir[0] != '\0') {
- te->name = strip->dir;
- }
- else {
- te->name = IFACE_("Strip None");
- }
- te->directdata = strip;
- }
- else if (type == TSE_SEQUENCE_DUP) {
- Sequence *seq = (Sequence *)idv;
-
- te->idcode = seq->type;
- te->directdata = seq;
- te->name = seq->strip->stripdata->name;
- }
- else if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
- PointerRNA pptr, propptr, *ptr = (PointerRNA *)idv;
- PropertyRNA *prop, *iterprop;
- PropertyType proptype;
-
- /* Don't display arrays larger, weak but index is stored as a short,
- * also the outliner isn't intended for editing such large data-sets. */
- BLI_STATIC_ASSERT(sizeof(te->index) == 2, "Index is no longer short!");
- const int tot_limit = SHRT_MAX;
-
- int a, tot;
-
- /* we do lazy build, for speed and to avoid infinite recursion */
-
- if (ptr->data == NULL) {
- te->name = IFACE_("(empty)");
- }
- else if (type == TSE_RNA_STRUCT) {
- /* struct */
- te->name = RNA_struct_name_get_alloc(ptr, NULL, 0, NULL);
-
- if (te->name) {
- te->flag |= TE_FREE_NAME;
- }
- else {
- te->name = RNA_struct_ui_name(ptr->type);
- }
-
- /* If searching don't expand RNA entries */
- if (SEARCHING_OUTLINER(soops) && BLI_strcasecmp("RNA", te->name) == 0) {
- tselem->flag &= ~TSE_CHILDSEARCH;
- }
-
- iterprop = RNA_struct_iterator_property(ptr->type);
- tot = RNA_property_collection_length(ptr, iterprop);
- CLAMP_MAX(tot, tot_limit);
-
- /* auto open these cases */
- if (!parent || (RNA_property_type(parent->directdata)) == PROP_POINTER) {
- if (!tselem->used) {
- tselem->flag &= ~TSE_CLOSED;
- }
- }
-
- if (TSELEM_OPEN(tselem, soops)) {
- for (a = 0; a < tot; a++) {
- RNA_property_collection_lookup_int(ptr, iterprop, a, &propptr);
- if (!(RNA_property_flag(propptr.data) & PROP_HIDDEN)) {
- outliner_add_element(soops, &te->subtree, (void *)ptr, te, TSE_RNA_PROPERTY, a);
- }
- }
- }
- else if (tot) {
- te->flag |= TE_LAZY_CLOSED;
- }
-
- te->rnaptr = *ptr;
- }
- else if (type == TSE_RNA_PROPERTY) {
- /* property */
- iterprop = RNA_struct_iterator_property(ptr->type);
- RNA_property_collection_lookup_int(ptr, iterprop, index, &propptr);
-
- prop = propptr.data;
- proptype = RNA_property_type(prop);
-
- te->name = RNA_property_ui_name(prop);
- te->directdata = prop;
- te->rnaptr = *ptr;
-
- /* If searching don't expand RNA entries */
- if (SEARCHING_OUTLINER(soops) && BLI_strcasecmp("RNA", te->name) == 0) {
- tselem->flag &= ~TSE_CHILDSEARCH;
- }
-
- if (proptype == PROP_POINTER) {
- pptr = RNA_property_pointer_get(ptr, prop);
-
- if (pptr.data) {
- if (TSELEM_OPEN(tselem, soops)) {
- outliner_add_element(soops, &te->subtree, (void *)&pptr, te, TSE_RNA_STRUCT, -1);
- }
- else {
- te->flag |= TE_LAZY_CLOSED;
- }
- }
- }
- else if (proptype == PROP_COLLECTION) {
- tot = RNA_property_collection_length(ptr, prop);
- CLAMP_MAX(tot, tot_limit);
-
- if (TSELEM_OPEN(tselem, soops)) {
- for (a = 0; a < tot; a++) {
- RNA_property_collection_lookup_int(ptr, prop, a, &pptr);
- outliner_add_element(soops, &te->subtree, (void *)&pptr, te, TSE_RNA_STRUCT, a);
- }
- }
- else if (tot) {
- te->flag |= TE_LAZY_CLOSED;
- }
- }
- else if (ELEM(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
- tot = RNA_property_array_length(ptr, prop);
- CLAMP_MAX(tot, tot_limit);
-
- if (TSELEM_OPEN(tselem, soops)) {
- for (a = 0; a < tot; a++) {
- outliner_add_element(soops, &te->subtree, (void *)ptr, te, TSE_RNA_ARRAY_ELEM, a);
- }
- }
- else if (tot) {
- te->flag |= TE_LAZY_CLOSED;
- }
- }
- }
- else if (type == TSE_RNA_ARRAY_ELEM) {
- char c;
-
- prop = parent->directdata;
-
- te->directdata = prop;
- te->rnaptr = *ptr;
- te->index = index;
-
- c = RNA_property_array_item_char(prop, index);
-
- te->name = MEM_callocN(sizeof(char) * 20, "OutlinerRNAArrayName");
- if (c) {
- sprintf((char *)te->name, " %c", c);
- }
- else {
- sprintf((char *)te->name, " %d", index + 1);
- }
- te->flag |= TE_FREE_NAME;
- }
- }
- else if (type == TSE_KEYMAP) {
- wmKeyMap *km = (wmKeyMap *)idv;
- wmKeyMapItem *kmi;
- char opname[OP_MAX_TYPENAME];
-
- te->directdata = idv;
- te->name = km->idname;
-
- if (TSELEM_OPEN(tselem, soops)) {
- int a = 0;
-
- for (kmi = km->items.first; kmi; kmi = kmi->next, a++) {
- const char *key = WM_key_event_string(kmi->type, false);
-
- if (key[0]) {
- wmOperatorType *ot = NULL;
-
- if (kmi->propvalue) {
- /* pass */
- }
- else {
- ot = WM_operatortype_find(kmi->idname, 0);
- }
-
- if (ot || kmi->propvalue) {
- TreeElement *ten = outliner_add_element(soops, &te->subtree, kmi, te, TSE_KEYMAP_ITEM, a);
-
- ten->directdata = kmi;
-
- if (kmi->propvalue) {
- ten->name = IFACE_("Modal map, not yet");
- }
- else {
- WM_operator_py_idname(opname, ot->idname);
- ten->name = BLI_strdup(opname);
- ten->flag |= TE_FREE_NAME;
- }
- }
- }
- }
- }
- else {
- te->flag |= TE_LAZY_CLOSED;
- }
- }
-
- return te;
+ TreeElement *te;
+ TreeStoreElem *tselem;
+ ID *id = idv;
+
+ if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
+ id = ((PointerRNA *)idv)->id.data;
+ if (!id) {
+ id = ((PointerRNA *)idv)->data;
+ }
+ }
+ else if (type == TSE_GP_LAYER) {
+ /* idv is the layer its self */
+ id = TREESTORE(parent)->id;
+ }
+
+ /* exceptions */
+ if (type == TSE_ID_BASE) {
+ /* pass */
+ }
+ else if (id == NULL) {
+ return NULL;
+ }
+
+ if (type == 0) {
+ /* Zero type means real ID, ensure we do not get non-outliner ID types here... */
+ BLI_assert(TREESTORE_ID_TYPE(id));
+ }
+
+ te = MEM_callocN(sizeof(TreeElement), "tree elem");
+ /* add to the visual tree */
+ BLI_addtail(lb, te);
+ /* add to the storage */
+ check_persistent(soops, te, id, type, index);
+ tselem = TREESTORE(te);
+
+ /* if we are searching for something expand to see child elements */
+ if (SEARCHING_OUTLINER(soops)) {
+ tselem->flag |= TSE_CHILDSEARCH;
+ }
+
+ te->parent = parent;
+ te->index = index; // for data arrays
+ if (ELEM(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
+ /* pass */
+ }
+ else if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
+ /* pass */
+ }
+ else if (type == TSE_ANIM_DATA) {
+ /* pass */
+ }
+ else if (type == TSE_GP_LAYER) {
+ /* pass */
+ }
+ else if (ELEM(type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
+ /* pass */
+ }
+ else if (type == TSE_ID_BASE) {
+ /* pass */
+ }
+ else {
+ /* do here too, for blend file viewer, own ID_LI then shows file name */
+ if (GS(id->name) == ID_LI) {
+ te->name = ((Library *)id)->name;
+ }
+ else {
+ te->name = id->name + 2; // default, can be overridden by Library or non-ID data
+ }
+ te->idcode = GS(id->name);
+ }
+
+ if (type == 0) {
+ TreeStoreElem *tsepar = parent ? TREESTORE(parent) : NULL;
+
+ /* ID datablock */
+ if (tsepar == NULL || tsepar->type != TSE_ID_BASE || soops->filter_id_type) {
+ outliner_add_id_contents(soops, te, tselem, id);
+ }
+ }
+ else if (type == TSE_ANIM_DATA) {
+ IdAdtTemplate *iat = (IdAdtTemplate *)idv;
+ AnimData *adt = (AnimData *)iat->adt;
+
+ /* this element's info */
+ te->name = IFACE_("Animation");
+ te->directdata = adt;
+
+ /* Action */
+ outliner_add_element(soops, &te->subtree, adt->action, te, 0, 0);
+
+ /* Drivers */
+ if (adt->drivers.first) {
+ TreeElement *ted = outliner_add_element(soops, &te->subtree, adt, te, TSE_DRIVER_BASE, 0);
+ ID *lastadded = NULL;
+ FCurve *fcu;
+
+ ted->name = IFACE_("Drivers");
+
+ for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
+ if (fcu->driver && fcu->driver->variables.first) {
+ ChannelDriver *driver = fcu->driver;
+ DriverVar *dvar;
+
+ for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
+ /* loop over all targets used here */
+ DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
+ if (lastadded != dtar->id) {
+ // XXX this lastadded check is rather lame, and also fails quite badly...
+ outliner_add_element(soops, &ted->subtree, dtar->id, ted, TSE_LINKED_OB, 0);
+ lastadded = dtar->id;
+ }
+ }
+ DRIVER_TARGETS_LOOPER_END;
+ }
+ }
+ }
+ }
+
+ /* NLA Data */
+ if (adt->nla_tracks.first) {
+ TreeElement *tenla = outliner_add_element(soops, &te->subtree, adt, te, TSE_NLA, 0);
+ NlaTrack *nlt;
+ int a = 0;
+
+ tenla->name = IFACE_("NLA Tracks");
+
+ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+ TreeElement *tenlt = outliner_add_element(
+ soops, &tenla->subtree, nlt, tenla, TSE_NLA_TRACK, a);
+ NlaStrip *strip;
+ TreeElement *ten;
+ int b = 0;
+
+ tenlt->name = nlt->name;
+
+ for (strip = nlt->strips.first; strip; strip = strip->next, b++) {
+ ten = outliner_add_element(soops, &tenlt->subtree, strip->act, tenlt, TSE_NLA_ACTION, b);
+ if (ten) {
+ ten->directdata = strip;
+ }
+ }
+ }
+ }
+ }
+ else if (type == TSE_GP_LAYER) {
+ bGPDlayer *gpl = (bGPDlayer *)idv;
+
+ te->name = gpl->info;
+ te->directdata = gpl;
+ }
+ else if (type == TSE_SEQUENCE) {
+ Sequence *seq = (Sequence *)idv;
+ Sequence *p;
+
+ /*
+ * The idcode is a little hack, but the outliner
+ * only check te->idcode if te->type is equal to zero,
+ * so this is "safe".
+ */
+ te->idcode = seq->type;
+ te->directdata = seq;
+ te->name = seq->name + 2;
+
+ if (!(seq->type & SEQ_TYPE_EFFECT)) {
+ /*
+ * This work like the sequence.
+ * If the sequence have a name (not default name)
+ * show it, in other case put the filename.
+ */
+
+ if (seq->type == SEQ_TYPE_META) {
+ p = seq->seqbase.first;
+ while (p) {
+ outliner_add_element(soops, &te->subtree, (void *)p, te, TSE_SEQUENCE, index);
+ p = p->next;
+ }
+ }
+ else {
+ outliner_add_element(soops, &te->subtree, (void *)seq->strip, te, TSE_SEQ_STRIP, index);
+ }
+ }
+ }
+ else if (type == TSE_SEQ_STRIP) {
+ Strip *strip = (Strip *)idv;
+
+ if (strip->dir[0] != '\0') {
+ te->name = strip->dir;
+ }
+ else {
+ te->name = IFACE_("Strip None");
+ }
+ te->directdata = strip;
+ }
+ else if (type == TSE_SEQUENCE_DUP) {
+ Sequence *seq = (Sequence *)idv;
+
+ te->idcode = seq->type;
+ te->directdata = seq;
+ te->name = seq->strip->stripdata->name;
+ }
+ else if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
+ PointerRNA pptr, propptr, *ptr = (PointerRNA *)idv;
+ PropertyRNA *prop, *iterprop;
+ PropertyType proptype;
+
+ /* Don't display arrays larger, weak but index is stored as a short,
+ * also the outliner isn't intended for editing such large data-sets. */
+ BLI_STATIC_ASSERT(sizeof(te->index) == 2, "Index is no longer short!");
+ const int tot_limit = SHRT_MAX;
+
+ int a, tot;
+
+ /* we do lazy build, for speed and to avoid infinite recursion */
+
+ if (ptr->data == NULL) {
+ te->name = IFACE_("(empty)");
+ }
+ else if (type == TSE_RNA_STRUCT) {
+ /* struct */
+ te->name = RNA_struct_name_get_alloc(ptr, NULL, 0, NULL);
+
+ if (te->name) {
+ te->flag |= TE_FREE_NAME;
+ }
+ else {
+ te->name = RNA_struct_ui_name(ptr->type);
+ }
+
+ /* If searching don't expand RNA entries */
+ if (SEARCHING_OUTLINER(soops) && BLI_strcasecmp("RNA", te->name) == 0) {
+ tselem->flag &= ~TSE_CHILDSEARCH;
+ }
+
+ iterprop = RNA_struct_iterator_property(ptr->type);
+ tot = RNA_property_collection_length(ptr, iterprop);
+ CLAMP_MAX(tot, tot_limit);
+
+ /* auto open these cases */
+ if (!parent || (RNA_property_type(parent->directdata)) == PROP_POINTER) {
+ if (!tselem->used) {
+ tselem->flag &= ~TSE_CLOSED;
+ }
+ }
+
+ if (TSELEM_OPEN(tselem, soops)) {
+ for (a = 0; a < tot; a++) {
+ RNA_property_collection_lookup_int(ptr, iterprop, a, &propptr);
+ if (!(RNA_property_flag(propptr.data) & PROP_HIDDEN)) {
+ outliner_add_element(soops, &te->subtree, (void *)ptr, te, TSE_RNA_PROPERTY, a);
+ }
+ }
+ }
+ else if (tot) {
+ te->flag |= TE_LAZY_CLOSED;
+ }
+
+ te->rnaptr = *ptr;
+ }
+ else if (type == TSE_RNA_PROPERTY) {
+ /* property */
+ iterprop = RNA_struct_iterator_property(ptr->type);
+ RNA_property_collection_lookup_int(ptr, iterprop, index, &propptr);
+
+ prop = propptr.data;
+ proptype = RNA_property_type(prop);
+
+ te->name = RNA_property_ui_name(prop);
+ te->directdata = prop;
+ te->rnaptr = *ptr;
+
+ /* If searching don't expand RNA entries */
+ if (SEARCHING_OUTLINER(soops) && BLI_strcasecmp("RNA", te->name) == 0) {
+ tselem->flag &= ~TSE_CHILDSEARCH;
+ }
+
+ if (proptype == PROP_POINTER) {
+ pptr = RNA_property_pointer_get(ptr, prop);
+
+ if (pptr.data) {
+ if (TSELEM_OPEN(tselem, soops)) {
+ outliner_add_element(soops, &te->subtree, (void *)&pptr, te, TSE_RNA_STRUCT, -1);
+ }
+ else {
+ te->flag |= TE_LAZY_CLOSED;
+ }
+ }
+ }
+ else if (proptype == PROP_COLLECTION) {
+ tot = RNA_property_collection_length(ptr, prop);
+ CLAMP_MAX(tot, tot_limit);
+
+ if (TSELEM_OPEN(tselem, soops)) {
+ for (a = 0; a < tot; a++) {
+ RNA_property_collection_lookup_int(ptr, prop, a, &pptr);
+ outliner_add_element(soops, &te->subtree, (void *)&pptr, te, TSE_RNA_STRUCT, a);
+ }
+ }
+ else if (tot) {
+ te->flag |= TE_LAZY_CLOSED;
+ }
+ }
+ else if (ELEM(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
+ tot = RNA_property_array_length(ptr, prop);
+ CLAMP_MAX(tot, tot_limit);
+
+ if (TSELEM_OPEN(tselem, soops)) {
+ for (a = 0; a < tot; a++) {
+ outliner_add_element(soops, &te->subtree, (void *)ptr, te, TSE_RNA_ARRAY_ELEM, a);
+ }
+ }
+ else if (tot) {
+ te->flag |= TE_LAZY_CLOSED;
+ }
+ }
+ }
+ else if (type == TSE_RNA_ARRAY_ELEM) {
+ char c;
+
+ prop = parent->directdata;
+
+ te->directdata = prop;
+ te->rnaptr = *ptr;
+ te->index = index;
+
+ c = RNA_property_array_item_char(prop, index);
+
+ te->name = MEM_callocN(sizeof(char) * 20, "OutlinerRNAArrayName");
+ if (c) {
+ sprintf((char *)te->name, " %c", c);
+ }
+ else {
+ sprintf((char *)te->name, " %d", index + 1);
+ }
+ te->flag |= TE_FREE_NAME;
+ }
+ }
+ else if (type == TSE_KEYMAP) {
+ wmKeyMap *km = (wmKeyMap *)idv;
+ wmKeyMapItem *kmi;
+ char opname[OP_MAX_TYPENAME];
+
+ te->directdata = idv;
+ te->name = km->idname;
+
+ if (TSELEM_OPEN(tselem, soops)) {
+ int a = 0;
+
+ for (kmi = km->items.first; kmi; kmi = kmi->next, a++) {
+ const char *key = WM_key_event_string(kmi->type, false);
+
+ if (key[0]) {
+ wmOperatorType *ot = NULL;
+
+ if (kmi->propvalue) {
+ /* pass */
+ }
+ else {
+ ot = WM_operatortype_find(kmi->idname, 0);
+ }
+
+ if (ot || kmi->propvalue) {
+ TreeElement *ten = outliner_add_element(
+ soops, &te->subtree, kmi, te, TSE_KEYMAP_ITEM, a);
+
+ ten->directdata = kmi;
+
+ if (kmi->propvalue) {
+ ten->name = IFACE_("Modal map, not yet");
+ }
+ else {
+ WM_operator_py_idname(opname, ot->idname);
+ ten->name = BLI_strdup(opname);
+ ten->flag |= TE_FREE_NAME;
+ }
+ }
+ }
+ }
+ }
+ else {
+ te->flag |= TE_LAZY_CLOSED;
+ }
+ }
+
+ return te;
}
/* ======================================================= */
@@ -1139,297 +1137,307 @@ static TreeElement *outliner_add_element(SpaceOutliner *soops, ListBase *lb, voi
/* Helped function to put duplicate sequence in the same tree. */
static int need_add_seq_dup(Sequence *seq)
{
- Sequence *p;
-
- if ((!seq->strip) || (!seq->strip->stripdata)) {
- return 1;
- }
-
- /*
- * First check backward, if we found a duplicate
- * sequence before this, don't need it, just return.
- */
- p = seq->prev;
- while (p) {
- if ((!p->strip) || (!p->strip->stripdata)) {
- p = p->prev;
- continue;
- }
-
- if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) {
- return 2;
- }
- p = p->prev;
- }
-
- p = seq->next;
- while (p) {
- if ((!p->strip) || (!p->strip->stripdata)) {
- p = p->next;
- continue;
- }
-
- if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) {
- return 0;
- }
- p = p->next;
- }
- return(1);
+ Sequence *p;
+
+ if ((!seq->strip) || (!seq->strip->stripdata)) {
+ return 1;
+ }
+
+ /*
+ * First check backward, if we found a duplicate
+ * sequence before this, don't need it, just return.
+ */
+ p = seq->prev;
+ while (p) {
+ if ((!p->strip) || (!p->strip->stripdata)) {
+ p = p->prev;
+ continue;
+ }
+
+ if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) {
+ return 2;
+ }
+ p = p->prev;
+ }
+
+ p = seq->next;
+ while (p) {
+ if ((!p->strip) || (!p->strip->stripdata)) {
+ p = p->next;
+ continue;
+ }
+
+ if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) {
+ return 0;
+ }
+ p = p->next;
+ }
+ return (1);
}
static void outliner_add_seq_dup(SpaceOutliner *soops, Sequence *seq, TreeElement *te, short index)
{
- /* TreeElement *ch; */ /* UNUSED */
- Sequence *p;
-
- p = seq;
- while (p) {
- if ((!p->strip) || (!p->strip->stripdata) || (p->strip->stripdata->name[0] == '\0')) {
- p = p->next;
- continue;
- }
-
- if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) {
- /* ch = */ /* UNUSED */ outliner_add_element(soops, &te->subtree, (void *)p, te, TSE_SEQUENCE, index);
- }
- p = p->next;
- }
+ /* TreeElement *ch; */ /* UNUSED */
+ Sequence *p;
+
+ p = seq;
+ while (p) {
+ if ((!p->strip) || (!p->strip->stripdata) || (p->strip->stripdata->name[0] == '\0')) {
+ p = p->next;
+ continue;
+ }
+
+ if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) {
+ /* ch = */ /* UNUSED */ outliner_add_element(
+ soops, &te->subtree, (void *)p, te, TSE_SEQUENCE, index);
+ }
+ p = p->next;
+ }
}
-
/* ----------------------------------------------- */
static const char *outliner_idcode_to_plural(short idcode)
{
- const char *propname = BKE_idcode_to_name_plural(idcode);
- PropertyRNA *prop = RNA_struct_type_find_property(&RNA_BlendData, propname);
- return (prop) ? RNA_property_ui_name(prop) : "UNKNOWN";
+ const char *propname = BKE_idcode_to_name_plural(idcode);
+ PropertyRNA *prop = RNA_struct_type_find_property(&RNA_BlendData, propname);
+ return (prop) ? RNA_property_ui_name(prop) : "UNKNOWN";
}
static bool outliner_library_id_show(Library *lib, ID *id, short filter_id_type)
{
- if (id->lib != lib) {
- return false;
- }
-
- if (filter_id_type == ID_GR) {
- /* Don't show child collections of non-scene master collection,
- * they are already shown as children. */
- Collection *collection = (Collection *)id;
- bool has_non_scene_parent = false;
-
- for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
- if (!(cparent->collection->flag & COLLECTION_IS_MASTER)) {
- has_non_scene_parent = true;
- }
- }
-
- if (has_non_scene_parent) {
- return false;
- }
- }
-
- return true;
+ if (id->lib != lib) {
+ return false;
+ }
+
+ if (filter_id_type == ID_GR) {
+ /* Don't show child collections of non-scene master collection,
+ * they are already shown as children. */
+ Collection *collection = (Collection *)id;
+ bool has_non_scene_parent = false;
+
+ for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
+ if (!(cparent->collection->flag & COLLECTION_IS_MASTER)) {
+ has_non_scene_parent = true;
+ }
+ }
+
+ if (has_non_scene_parent) {
+ return false;
+ }
+ }
+
+ return true;
}
-static TreeElement *outliner_add_library_contents(Main *mainvar, SpaceOutliner *soops, ListBase *lb, Library *lib)
+static TreeElement *outliner_add_library_contents(Main *mainvar,
+ SpaceOutliner *soops,
+ ListBase *lb,
+ Library *lib)
{
- TreeElement *ten, *tenlib = NULL;
- ListBase *lbarray[MAX_LIBARRAY];
- int a, tot;
- short filter_id_type = (soops->filter & SO_FILTER_ID_TYPE) ? soops->filter_id_type : 0;
-
- if (filter_id_type) {
- lbarray[0] = which_libbase(mainvar, soops->filter_id_type);
- tot = 1;
- }
- else {
- tot = set_listbasepointers(mainvar, lbarray);
- }
-
- for (a = 0; a < tot; a++) {
- if (lbarray[a] && lbarray[a]->first) {
- ID *id = lbarray[a]->first;
-
- /* check if there's data in current lib */
- for (; id; id = id->next) {
- if (id->lib == lib) {
- break;
- }
- }
-
- if (id) {
- if (!tenlib) {
- /* Create library tree element on demand, depending if there are any datablocks. */
- if (lib) {
- tenlib = outliner_add_element(soops, lb, lib, NULL, 0, 0);
- }
- else {
- tenlib = outliner_add_element(soops, lb, mainvar, NULL, TSE_ID_BASE, 0);
- tenlib->name = IFACE_("Current File");
- }
- }
-
- /* Create datablock list parent element on demand. */
- if (filter_id_type) {
- ten = tenlib;
- }
- else {
- ten = outliner_add_element(soops, &tenlib->subtree, lbarray[a], NULL, TSE_ID_BASE, 0);
- ten->directdata = lbarray[a];
- ten->name = outliner_idcode_to_plural(GS(id->name));
- }
-
- for (id = lbarray[a]->first; id; id = id->next) {
- if (outliner_library_id_show(lib, id, filter_id_type)) {
- outliner_add_element(soops, &ten->subtree, id, ten, 0, 0);
- }
- }
- }
- }
- }
-
- return tenlib;
+ TreeElement *ten, *tenlib = NULL;
+ ListBase *lbarray[MAX_LIBARRAY];
+ int a, tot;
+ short filter_id_type = (soops->filter & SO_FILTER_ID_TYPE) ? soops->filter_id_type : 0;
+
+ if (filter_id_type) {
+ lbarray[0] = which_libbase(mainvar, soops->filter_id_type);
+ tot = 1;
+ }
+ else {
+ tot = set_listbasepointers(mainvar, lbarray);
+ }
+
+ for (a = 0; a < tot; a++) {
+ if (lbarray[a] && lbarray[a]->first) {
+ ID *id = lbarray[a]->first;
+
+ /* check if there's data in current lib */
+ for (; id; id = id->next) {
+ if (id->lib == lib) {
+ break;
+ }
+ }
+
+ if (id) {
+ if (!tenlib) {
+ /* Create library tree element on demand, depending if there are any datablocks. */
+ if (lib) {
+ tenlib = outliner_add_element(soops, lb, lib, NULL, 0, 0);
+ }
+ else {
+ tenlib = outliner_add_element(soops, lb, mainvar, NULL, TSE_ID_BASE, 0);
+ tenlib->name = IFACE_("Current File");
+ }
+ }
+
+ /* Create datablock list parent element on demand. */
+ if (filter_id_type) {
+ ten = tenlib;
+ }
+ else {
+ ten = outliner_add_element(soops, &tenlib->subtree, lbarray[a], NULL, TSE_ID_BASE, 0);
+ ten->directdata = lbarray[a];
+ ten->name = outliner_idcode_to_plural(GS(id->name));
+ }
+
+ for (id = lbarray[a]->first; id; id = id->next) {
+ if (outliner_library_id_show(lib, id, filter_id_type)) {
+ outliner_add_element(soops, &ten->subtree, id, ten, 0, 0);
+ }
+ }
+ }
+ }
+ }
+
+ return tenlib;
}
static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOutliner *soops)
{
- TreeElement *ten;
- ListBase *lbarray[MAX_LIBARRAY];
- int a, tot;
- short filter_id_type = (soops->filter & SO_FILTER_ID_TYPE) ? soops->filter_id_type : 0;
-
- if (filter_id_type) {
- lbarray[0] = which_libbase(mainvar, soops->filter_id_type);
- tot = 1;
- }
- else {
- tot = set_listbasepointers(mainvar, lbarray);
- }
-
- for (a = 0; a < tot; a++) {
- if (lbarray[a] && lbarray[a]->first) {
- ID *id = lbarray[a]->first;
-
- /* check if there are any datablocks of this type which are orphans */
- for (; id; id = id->next) {
- if (ID_REAL_USERS(id) <= 0) {
- break;
- }
- }
-
- if (id) {
- /* header for this type of datablock */
- if (filter_id_type) {
- ten = NULL;
- }
- else {
- ten = outliner_add_element(soops, &soops->tree, lbarray[a], NULL, TSE_ID_BASE, 0);
- ten->directdata = lbarray[a];
- ten->name = outliner_idcode_to_plural(GS(id->name));
- }
-
- /* add the orphaned datablocks - these will not be added with any subtrees attached */
- for (id = lbarray[a]->first; id; id = id->next) {
- if (ID_REAL_USERS(id) <= 0) {
- outliner_add_element(soops, (ten) ? &ten->subtree : &soops->tree, id, ten, 0, 0);
- }
- }
- }
- }
- }
+ TreeElement *ten;
+ ListBase *lbarray[MAX_LIBARRAY];
+ int a, tot;
+ short filter_id_type = (soops->filter & SO_FILTER_ID_TYPE) ? soops->filter_id_type : 0;
+
+ if (filter_id_type) {
+ lbarray[0] = which_libbase(mainvar, soops->filter_id_type);
+ tot = 1;
+ }
+ else {
+ tot = set_listbasepointers(mainvar, lbarray);
+ }
+
+ for (a = 0; a < tot; a++) {
+ if (lbarray[a] && lbarray[a]->first) {
+ ID *id = lbarray[a]->first;
+
+ /* check if there are any datablocks of this type which are orphans */
+ for (; id; id = id->next) {
+ if (ID_REAL_USERS(id) <= 0) {
+ break;
+ }
+ }
+
+ if (id) {
+ /* header for this type of datablock */
+ if (filter_id_type) {
+ ten = NULL;
+ }
+ else {
+ ten = outliner_add_element(soops, &soops->tree, lbarray[a], NULL, TSE_ID_BASE, 0);
+ ten->directdata = lbarray[a];
+ ten->name = outliner_idcode_to_plural(GS(id->name));
+ }
+
+ /* add the orphaned datablocks - these will not be added with any subtrees attached */
+ for (id = lbarray[a]->first; id; id = id->next) {
+ if (ID_REAL_USERS(id) <= 0) {
+ outliner_add_element(soops, (ten) ? &ten->subtree : &soops->tree, id, ten, 0, 0);
+ }
+ }
+ }
+ }
+ }
}
static void outliner_add_layer_collection_objects(
- SpaceOutliner *soops, ListBase *tree, ViewLayer *layer,
- LayerCollection *lc, TreeElement *ten)
+ SpaceOutliner *soops, ListBase *tree, ViewLayer *layer, LayerCollection *lc, TreeElement *ten)
{
- for (CollectionObject *cob = lc->collection->gobject.first; cob; cob = cob->next) {
- 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;
-
- if (!(base->flag & BASE_VISIBLE)) {
- te_object->flag |= TE_DISABLED;
- }
- }
+ for (CollectionObject *cob = lc->collection->gobject.first; cob; cob = cob->next) {
+ 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;
+
+ if (!(base->flag & BASE_VISIBLE)) {
+ te_object->flag |= TE_DISABLED;
+ }
+ }
}
-static void outliner_add_layer_collections_recursive(
- SpaceOutliner *soops, ListBase *tree, ViewLayer *layer,
- ListBase *layer_collections, TreeElement *parent_ten,
- const bool show_objects)
+static void outliner_add_layer_collections_recursive(SpaceOutliner *soops,
+ ListBase *tree,
+ ViewLayer *layer,
+ ListBase *layer_collections,
+ TreeElement *parent_ten,
+ const bool show_objects)
{
- for (LayerCollection *lc = layer_collections->first; lc; lc = lc->next) {
- ID *id = &lc->collection->id;
- TreeElement *ten = outliner_add_element(soops, tree, id, parent_ten, TSE_LAYER_COLLECTION, 0);
-
- ten->name = id->name + 2;
- ten->directdata = lc;
-
- /* Open by default. */
- TreeStoreElem *tselem = TREESTORE(ten);
- if (!tselem->used) {
- tselem->flag &= ~TSE_CLOSED;
- }
-
- const bool exclude = (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0;
- if (exclude ||
- ((lc->runtime_flag & LAYER_COLLECTION_VISIBLE) == 0))
- {
- ten->flag |= TE_DISABLED;
- }
-
- outliner_add_layer_collections_recursive(soops, &ten->subtree, layer, &lc->layer_collections, ten, show_objects);
- if (!exclude && show_objects) {
- outliner_add_layer_collection_objects(soops, &ten->subtree, layer, lc, ten);
- }
- }
+ for (LayerCollection *lc = layer_collections->first; lc; lc = lc->next) {
+ ID *id = &lc->collection->id;
+ TreeElement *ten = outliner_add_element(soops, tree, id, parent_ten, TSE_LAYER_COLLECTION, 0);
+
+ ten->name = id->name + 2;
+ ten->directdata = lc;
+
+ /* Open by default. */
+ TreeStoreElem *tselem = TREESTORE(ten);
+ if (!tselem->used) {
+ tselem->flag &= ~TSE_CLOSED;
+ }
+
+ const bool exclude = (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0;
+ if (exclude || ((lc->runtime_flag & LAYER_COLLECTION_VISIBLE) == 0)) {
+ ten->flag |= TE_DISABLED;
+ }
+
+ outliner_add_layer_collections_recursive(
+ soops, &ten->subtree, layer, &lc->layer_collections, ten, show_objects);
+ if (!exclude && show_objects) {
+ outliner_add_layer_collection_objects(soops, &ten->subtree, layer, lc, ten);
+ }
+ }
}
-static void outliner_add_view_layer(SpaceOutliner *soops, ListBase *tree, TreeElement *parent,
- ViewLayer *layer, const bool show_objects)
+static void outliner_add_view_layer(SpaceOutliner *soops,
+ ListBase *tree,
+ TreeElement *parent,
+ ViewLayer *layer,
+ const bool show_objects)
{
- /* First layer collection is for master collection, don't show it. */
- LayerCollection *lc = layer->layer_collections.first;
- if (lc == NULL) {
- return;
- }
-
- outliner_add_layer_collections_recursive(soops, tree, layer, &lc->layer_collections, parent, show_objects);
- if (show_objects) {
- outliner_add_layer_collection_objects(soops, tree, layer, lc, parent);
- }
+ /* First layer collection is for master collection, don't show it. */
+ LayerCollection *lc = layer->layer_collections.first;
+ if (lc == NULL) {
+ return;
+ }
+
+ outliner_add_layer_collections_recursive(
+ soops, tree, layer, &lc->layer_collections, parent, show_objects);
+ if (show_objects) {
+ outliner_add_layer_collection_objects(soops, tree, layer, lc, parent);
+ }
}
BLI_INLINE void outliner_add_collection_init(TreeElement *te, Collection *collection)
{
- te->name = BKE_collection_ui_name_get(collection);
- te->directdata = collection;
+ te->name = BKE_collection_ui_name_get(collection);
+ te->directdata = collection;
}
-BLI_INLINE void outliner_add_collection_objects(
- SpaceOutliner *soops, ListBase *tree, Collection *collection, TreeElement *parent)
+BLI_INLINE void outliner_add_collection_objects(SpaceOutliner *soops,
+ ListBase *tree,
+ Collection *collection,
+ TreeElement *parent)
{
- for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
- outliner_add_element(soops, tree, cob->ob, parent, 0, 0);
- }
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ outliner_add_element(soops, tree, cob->ob, parent, 0, 0);
+ }
}
-static TreeElement *outliner_add_collection_recursive(
- SpaceOutliner *soops, Collection *collection, TreeElement *ten)
+static TreeElement *outliner_add_collection_recursive(SpaceOutliner *soops,
+ Collection *collection,
+ TreeElement *ten)
{
- outliner_add_collection_init(ten, collection);
+ outliner_add_collection_init(ten, collection);
- for (CollectionChild *child = collection->children.first; child; child = child->next) {
- outliner_add_element(soops, &ten->subtree, &child->collection->id, ten, 0, 0);
- }
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ outliner_add_element(soops, &ten->subtree, &child->collection->id, ten, 0, 0);
+ }
- if (soops->outlinevis != SO_SCENES) {
- outliner_add_collection_objects(soops, &ten->subtree, collection, ten);
- }
+ if (soops->outlinevis != SO_SCENES) {
+ outliner_add_collection_objects(soops, &ten->subtree, collection, ten);
+ }
- return ten;
+ return ten;
}
/* ======================================================= */
@@ -1440,267 +1448,270 @@ static TreeElement *outliner_add_collection_recursive(
/* make sure elements are correctly nested */
static void outliner_make_object_parent_hierarchy(ListBase *lb)
{
- TreeElement *te, *ten, *tep;
- TreeStoreElem *tselem;
-
- /* build hierarchy */
- // XXX also, set extents here...
- te = lb->first;
- while (te) {
- ten = te->next;
- tselem = TREESTORE(te);
-
- if (tselem->type == 0 && te->idcode == ID_OB) {
- Object *ob = (Object *)tselem->id;
- if (ob->parent && ob->parent->id.newid) {
- BLI_remlink(lb, te);
- tep = (TreeElement *)ob->parent->id.newid;
- BLI_addtail(&tep->subtree, te);
- // set correct parent pointers
- for (te = tep->subtree.first; te; te = te->next) {
- te->parent = tep;
- }
- }
- }
- te = ten;
- }
+ TreeElement *te, *ten, *tep;
+ TreeStoreElem *tselem;
+
+ /* build hierarchy */
+ // XXX also, set extents here...
+ te = lb->first;
+ while (te) {
+ ten = te->next;
+ tselem = TREESTORE(te);
+
+ if (tselem->type == 0 && te->idcode == ID_OB) {
+ Object *ob = (Object *)tselem->id;
+ if (ob->parent && ob->parent->id.newid) {
+ BLI_remlink(lb, te);
+ tep = (TreeElement *)ob->parent->id.newid;
+ BLI_addtail(&tep->subtree, te);
+ // set correct parent pointers
+ for (te = tep->subtree.first; te; te = te->next) {
+ te->parent = tep;
+ }
+ }
+ }
+ te = ten;
+ }
}
/* Sorting ------------------------------------------------------ */
typedef struct tTreeSort {
- TreeElement *te;
- ID *id;
- const char *name;
- short idcode;
+ TreeElement *te;
+ ID *id;
+ const char *name;
+ short idcode;
} tTreeSort;
/* alphabetical comparator, tryping to put objects first */
static int treesort_alpha_ob(const void *v1, const void *v2)
{
- const tTreeSort *x1 = v1, *x2 = v2;
- int comp;
-
- /* first put objects last (hierarchy) */
- comp = (x1->idcode == ID_OB);
- if (x2->idcode == ID_OB) {
- comp += 2;
- }
-
- if (comp == 1) {
- return 1;
- }
- else if (comp == 2) {
- return -1;
- }
- else if (comp == 3) {
- comp = strcmp(x1->name, x2->name);
-
- if (comp > 0) {
- return 1;
- }
- else if (comp < 0) {
- return -1;
- }
- return 0;
- }
- return 0;
+ const tTreeSort *x1 = v1, *x2 = v2;
+ int comp;
+
+ /* first put objects last (hierarchy) */
+ comp = (x1->idcode == ID_OB);
+ if (x2->idcode == ID_OB) {
+ comp += 2;
+ }
+
+ if (comp == 1) {
+ return 1;
+ }
+ else if (comp == 2) {
+ return -1;
+ }
+ else if (comp == 3) {
+ comp = strcmp(x1->name, x2->name);
+
+ if (comp > 0) {
+ return 1;
+ }
+ else if (comp < 0) {
+ return -1;
+ }
+ return 0;
+ }
+ return 0;
}
/* alphabetical comparator */
static int treesort_alpha(const void *v1, const void *v2)
{
- const tTreeSort *x1 = v1, *x2 = v2;
- int comp;
-
- comp = strcmp(x1->name, x2->name);
-
- if (comp > 0) {
- return 1;
- }
- else if (comp < 0) {
- return -1;
- }
- return 0;
+ const tTreeSort *x1 = v1, *x2 = v2;
+ int comp;
+
+ comp = strcmp(x1->name, x2->name);
+
+ if (comp > 0) {
+ return 1;
+ }
+ else if (comp < 0) {
+ return -1;
+ }
+ return 0;
}
-
/* this is nice option for later? doesn't look too useful... */
#if 0
static int treesort_obtype_alpha(const void *v1, const void *v2)
{
- const tTreeSort *x1 = v1, *x2 = v2;
-
- /* first put objects last (hierarchy) */
- if (x1->idcode == ID_OB && x2->idcode != ID_OB) {
- return 1;
- }
- else if (x2->idcode == ID_OB && x1->idcode != ID_OB) {
- return -1;
- }
- else {
- /* 2nd we check ob type */
- if (x1->idcode == ID_OB && x2->idcode == ID_OB) {
- if (((Object *)x1->id)->type > ((Object *)x2->id)->type) return 1;
- else if (((Object *)x1->id)->type > ((Object *)x2->id)->type) return -1;
- else return 0;
- }
- else {
- int comp = strcmp(x1->name, x2->name);
-
- if (comp > 0) return 1;
- else if (comp < 0) return -1;
- return 0;
- }
- }
+ const tTreeSort *x1 = v1, *x2 = v2;
+
+ /* first put objects last (hierarchy) */
+ if (x1->idcode == ID_OB && x2->idcode != ID_OB) {
+ return 1;
+ }
+ else if (x2->idcode == ID_OB && x1->idcode != ID_OB) {
+ return -1;
+ }
+ else {
+ /* 2nd we check ob type */
+ if (x1->idcode == ID_OB && x2->idcode == ID_OB) {
+ if (((Object *)x1->id)->type > ((Object *)x2->id)->type) return 1;
+ else if (((Object *)x1->id)->type > ((Object *)x2->id)->type) return -1;
+ else return 0;
+ }
+ else {
+ int comp = strcmp(x1->name, x2->name);
+
+ if (comp > 0) return 1;
+ else if (comp < 0) return -1;
+ return 0;
+ }
+ }
}
#endif
/* sort happens on each subtree individual */
static void outliner_sort(ListBase *lb)
{
- TreeElement *te;
- TreeStoreElem *tselem;
-
- te = lb->last;
- if (te == NULL) {
- return;
- }
- tselem = TREESTORE(te);
-
- /* sorting rules; only object lists, ID lists, or deformgroups */
- if (ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) || (tselem->type == 0 && te->idcode == ID_OB)) {
- int totelem = BLI_listbase_count(lb);
-
- if (totelem > 1) {
- tTreeSort *tear = MEM_mallocN(totelem * sizeof(tTreeSort), "tree sort array");
- tTreeSort *tp = tear;
- int skip = 0;
-
- for (te = lb->first; te; te = te->next, tp++) {
- tselem = TREESTORE(te);
- tp->te = te;
- tp->name = te->name;
- tp->idcode = te->idcode;
-
- if (tselem->type && tselem->type != TSE_DEFGROUP) {
- tp->idcode = 0; // don't sort this
- }
- if (tselem->type == TSE_ID_BASE) {
- tp->idcode = 1; // do sort this
- }
-
- tp->id = tselem->id;
- }
-
- /* just sort alphabetically */
- if (tear->idcode == 1) {
- qsort(tear, totelem, sizeof(tTreeSort), treesort_alpha);
- }
- else {
- /* keep beginning of list */
- for (tp = tear, skip = 0; skip < totelem; skip++, tp++) {
- if (tp->idcode) {
- break;
- }
- }
-
- if (skip < totelem) {
- qsort(tear + skip, totelem - skip, sizeof(tTreeSort), treesort_alpha_ob);
- }
- }
-
- BLI_listbase_clear(lb);
- tp = tear;
- while (totelem--) {
- BLI_addtail(lb, tp->te);
- tp++;
- }
- MEM_freeN(tear);
- }
- }
-
- for (te = lb->first; te; te = te->next) {
- outliner_sort(&te->subtree);
- }
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ te = lb->last;
+ if (te == NULL) {
+ return;
+ }
+ tselem = TREESTORE(te);
+
+ /* sorting rules; only object lists, ID lists, or deformgroups */
+ if (ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) ||
+ (tselem->type == 0 && te->idcode == ID_OB)) {
+ int totelem = BLI_listbase_count(lb);
+
+ if (totelem > 1) {
+ tTreeSort *tear = MEM_mallocN(totelem * sizeof(tTreeSort), "tree sort array");
+ tTreeSort *tp = tear;
+ int skip = 0;
+
+ for (te = lb->first; te; te = te->next, tp++) {
+ tselem = TREESTORE(te);
+ tp->te = te;
+ tp->name = te->name;
+ tp->idcode = te->idcode;
+
+ if (tselem->type && tselem->type != TSE_DEFGROUP) {
+ tp->idcode = 0; // don't sort this
+ }
+ if (tselem->type == TSE_ID_BASE) {
+ tp->idcode = 1; // do sort this
+ }
+
+ tp->id = tselem->id;
+ }
+
+ /* just sort alphabetically */
+ if (tear->idcode == 1) {
+ qsort(tear, totelem, sizeof(tTreeSort), treesort_alpha);
+ }
+ else {
+ /* keep beginning of list */
+ for (tp = tear, skip = 0; skip < totelem; skip++, tp++) {
+ if (tp->idcode) {
+ break;
+ }
+ }
+
+ if (skip < totelem) {
+ qsort(tear + skip, totelem - skip, sizeof(tTreeSort), treesort_alpha_ob);
+ }
+ }
+
+ BLI_listbase_clear(lb);
+ tp = tear;
+ while (totelem--) {
+ BLI_addtail(lb, tp->te);
+ tp++;
+ }
+ MEM_freeN(tear);
+ }
+ }
+
+ for (te = lb->first; te; te = te->next) {
+ outliner_sort(&te->subtree);
+ }
}
/* Filtering ----------------------------------------------- */
typedef struct OutlinerTreeElementFocus {
- TreeStoreElem *tselem;
- int ys;
+ TreeStoreElem *tselem;
+ int ys;
} OutlinerTreeElementFocus;
/**
* Bring the outliner scrolling back to where it was in relation to the original focus element
* Caller is expected to handle redrawing of ARegion.
*/
-static void outliner_restore_scrolling_position(SpaceOutliner *soops, ARegion *ar, OutlinerTreeElementFocus *focus)
+static void outliner_restore_scrolling_position(SpaceOutliner *soops,
+ ARegion *ar,
+ OutlinerTreeElementFocus *focus)
{
- View2D *v2d = &ar->v2d;
- int ytop;
+ View2D *v2d = &ar->v2d;
+ int ytop;
- if (focus->tselem != NULL) {
- outliner_set_coordinates(ar, soops);
+ if (focus->tselem != NULL) {
+ outliner_set_coordinates(ar, soops);
- TreeElement *te_new = outliner_find_tree_element(&soops->tree, focus->tselem);
+ TreeElement *te_new = outliner_find_tree_element(&soops->tree, focus->tselem);
- if (te_new != NULL) {
- int ys_new, ys_old;
+ if (te_new != NULL) {
+ int ys_new, ys_old;
- ys_new = te_new->ys;
- ys_old = focus->ys;
+ ys_new = te_new->ys;
+ ys_old = focus->ys;
- ytop = v2d->cur.ymax + (ys_new - ys_old) -1;
- if (ytop > 0) {
- ytop = 0;
- }
+ ytop = v2d->cur.ymax + (ys_new - ys_old) - 1;
+ if (ytop > 0) {
+ ytop = 0;
+ }
- v2d->cur.ymax = (float)ytop;
- v2d->cur.ymin = (float)(ytop - BLI_rcti_size_y(&v2d->mask));
- }
- else {
- return;
- }
- }
+ v2d->cur.ymax = (float)ytop;
+ v2d->cur.ymin = (float)(ytop - BLI_rcti_size_y(&v2d->mask));
+ }
+ else {
+ return;
+ }
+ }
}
static bool test_collection_callback(TreeElement *te)
{
- return outliner_is_collection_tree_element(te);
+ return outliner_is_collection_tree_element(te);
}
static bool test_object_callback(TreeElement *te)
{
- TreeStoreElem *tselem = TREESTORE(te);
- return ((tselem->type == 0) && (te->idcode == ID_OB));
+ TreeStoreElem *tselem = TREESTORE(te);
+ return ((tselem->type == 0) && (te->idcode == ID_OB));
}
/**
* See if TreeElement or any of its children pass the callback_test.
*/
static TreeElement *outliner_find_first_desired_element_at_y_recursive(
- const SpaceOutliner *soops,
- TreeElement *te,
- const float limit,
- bool (*callback_test)(TreeElement *))
+ const SpaceOutliner *soops,
+ TreeElement *te,
+ const float limit,
+ bool (*callback_test)(TreeElement *))
{
- if (callback_test(te)) {
- return te;
- }
-
- if (TSELEM_OPEN(te->store_elem, soops)) {
- TreeElement *te_iter, *te_sub;
- for (te_iter = te->subtree.first; te_iter; te_iter = te_iter->next) {
- te_sub = outliner_find_first_desired_element_at_y_recursive(soops, te_iter, limit, callback_test);
- if (te_sub != NULL) {
- return te_sub;
- }
- }
- }
-
- return NULL;
+ if (callback_test(te)) {
+ return te;
+ }
+
+ if (TSELEM_OPEN(te->store_elem, soops)) {
+ TreeElement *te_iter, *te_sub;
+ for (te_iter = te->subtree.first; te_iter; te_iter = te_iter->next) {
+ te_sub = outliner_find_first_desired_element_at_y_recursive(
+ soops, te_iter, limit, callback_test);
+ if (te_sub != NULL) {
+ return te_sub;
+ }
+ }
+ }
+
+ return NULL;
}
/**
@@ -1713,55 +1724,53 @@ static TreeElement *outliner_find_first_desired_element_at_y_recursive(
* what we are looking for. If we are past the visible range and we can't find a valid element
* we return NULL.
*/
-static TreeElement *outliner_find_first_desired_element_at_y(
- const SpaceOutliner *soops,
- const float view_co,
- const float view_co_limit)
+static TreeElement *outliner_find_first_desired_element_at_y(const SpaceOutliner *soops,
+ const float view_co,
+ const float view_co_limit)
{
- TreeElement *te, *te_sub;
- te = outliner_find_item_at_y(soops, &soops->tree, view_co);
-
- bool (*callback_test)(TreeElement *);
- if ((soops->outlinevis == SO_VIEW_LAYER) &&
- (soops->filter & SO_FILTER_NO_COLLECTION))
- {
- callback_test = test_object_callback;
- }
- else {
- callback_test = test_collection_callback;
- }
-
- while (te != NULL) {
- te_sub = outliner_find_first_desired_element_at_y_recursive(soops, te, view_co_limit, callback_test);
- if (te_sub != NULL) {
- /* Skip the element if it was not visible to start with. */
- if (te->ys + UI_UNIT_Y > view_co_limit) {
- return te_sub;
- }
- else {
- return NULL;
- }
- }
-
- if (te->next) {
- te = te->next;
- continue;
- }
-
- if (te->parent == NULL) {
- break;
- }
-
- while (te->parent) {
- if (te->parent->next) {
- te = te->parent->next;
- break;
- }
- te = te->parent;
- }
- }
-
- return NULL;
+ TreeElement *te, *te_sub;
+ te = outliner_find_item_at_y(soops, &soops->tree, view_co);
+
+ bool (*callback_test)(TreeElement *);
+ if ((soops->outlinevis == SO_VIEW_LAYER) && (soops->filter & SO_FILTER_NO_COLLECTION)) {
+ callback_test = test_object_callback;
+ }
+ else {
+ callback_test = test_collection_callback;
+ }
+
+ while (te != NULL) {
+ te_sub = outliner_find_first_desired_element_at_y_recursive(
+ soops, te, view_co_limit, callback_test);
+ if (te_sub != NULL) {
+ /* Skip the element if it was not visible to start with. */
+ if (te->ys + UI_UNIT_Y > view_co_limit) {
+ return te_sub;
+ }
+ else {
+ return NULL;
+ }
+ }
+
+ if (te->next) {
+ te = te->next;
+ continue;
+ }
+
+ if (te->parent == NULL) {
+ break;
+ }
+
+ while (te->parent) {
+ if (te->parent->next) {
+ te = te->parent->next;
+ break;
+ }
+ te = te->parent;
+ }
+ }
+
+ return NULL;
}
/**
@@ -1770,240 +1779,244 @@ static TreeElement *outliner_find_first_desired_element_at_y(
* Finds the top-most collection visible in the outliner and populates the OutlinerTreeElementFocus
* struct to retrieve this element later to make sure it is in the same original position as before filtering
*/
-static void outliner_store_scrolling_position(SpaceOutliner *soops, ARegion *ar, OutlinerTreeElementFocus *focus)
+static void outliner_store_scrolling_position(SpaceOutliner *soops,
+ ARegion *ar,
+ OutlinerTreeElementFocus *focus)
{
- TreeElement *te;
- float limit = ar->v2d.cur.ymin;
+ TreeElement *te;
+ float limit = ar->v2d.cur.ymin;
- outliner_set_coordinates(ar, soops);
+ outliner_set_coordinates(ar, soops);
- te = outliner_find_first_desired_element_at_y(soops, ar->v2d.cur.ymax, limit);
+ te = outliner_find_first_desired_element_at_y(soops, ar->v2d.cur.ymax, limit);
- if (te != NULL) {
- focus->tselem = TREESTORE(te);
- focus->ys = te->ys;
- }
- else {
- focus->tselem = NULL;
- }
+ if (te != NULL) {
+ focus->tselem = TREESTORE(te);
+ focus->ys = te->ys;
+ }
+ else {
+ focus->tselem = NULL;
+ }
}
static int outliner_exclude_filter_get(SpaceOutliner *soops)
{
- int exclude_filter = soops->filter & ~SO_FILTER_OB_STATE;
-
- if (soops->search_string[0] != 0) {
- exclude_filter |= SO_FILTER_SEARCH;
- }
- else {
- exclude_filter &= ~SO_FILTER_SEARCH;
- }
-
- /* Let's have this for the collection options at first. */
- if (!SUPPORT_FILTER_OUTLINER(soops)) {
- return (exclude_filter & SO_FILTER_SEARCH);
- }
-
- if (soops->filter & SO_FILTER_NO_OBJECT) {
- exclude_filter |= SO_FILTER_OB_TYPE;
- }
-
- switch (soops->filter_state) {
- case SO_FILTER_OB_VISIBLE:
- exclude_filter |= SO_FILTER_OB_STATE_VISIBLE;
- break;
- case SO_FILTER_OB_SELECTED:
- exclude_filter |= SO_FILTER_OB_STATE_SELECTED;
- break;
- case SO_FILTER_OB_ACTIVE:
- exclude_filter |= SO_FILTER_OB_STATE_ACTIVE;
- break;
- }
-
- return exclude_filter;
+ int exclude_filter = soops->filter & ~SO_FILTER_OB_STATE;
+
+ if (soops->search_string[0] != 0) {
+ exclude_filter |= SO_FILTER_SEARCH;
+ }
+ else {
+ exclude_filter &= ~SO_FILTER_SEARCH;
+ }
+
+ /* Let's have this for the collection options at first. */
+ if (!SUPPORT_FILTER_OUTLINER(soops)) {
+ return (exclude_filter & SO_FILTER_SEARCH);
+ }
+
+ if (soops->filter & SO_FILTER_NO_OBJECT) {
+ exclude_filter |= SO_FILTER_OB_TYPE;
+ }
+
+ switch (soops->filter_state) {
+ case SO_FILTER_OB_VISIBLE:
+ exclude_filter |= SO_FILTER_OB_STATE_VISIBLE;
+ break;
+ case SO_FILTER_OB_SELECTED:
+ exclude_filter |= SO_FILTER_OB_STATE_SELECTED;
+ break;
+ case SO_FILTER_OB_ACTIVE:
+ exclude_filter |= SO_FILTER_OB_STATE_ACTIVE;
+ break;
+ }
+
+ return exclude_filter;
}
-static bool outliner_element_visible_get(ViewLayer *view_layer, TreeElement *te, const int exclude_filter)
+static bool outliner_element_visible_get(ViewLayer *view_layer,
+ TreeElement *te,
+ const int exclude_filter)
{
- if ((exclude_filter & SO_FILTER_ANY) == 0) {
- return true;
- }
-
- TreeStoreElem *tselem = TREESTORE(te);
- if ((tselem->type == 0) && (te->idcode == ID_OB)) {
- if ((exclude_filter & SO_FILTER_OB_TYPE) == SO_FILTER_OB_TYPE) {
- return false;
- }
-
- Object *ob = (Object *)tselem->id;
- Base *base = (Base *)te->directdata;
- BLI_assert((base == NULL) || (base->object == ob));
-
- if (exclude_filter & SO_FILTER_OB_TYPE) {
- switch (ob->type) {
- case OB_MESH:
- if (exclude_filter & SO_FILTER_NO_OB_MESH) {
- return false;
- }
- break;
- case OB_ARMATURE:
- if (exclude_filter & SO_FILTER_NO_OB_ARMATURE) {
- return false;
- }
- break;
- case OB_EMPTY:
- if (exclude_filter & SO_FILTER_NO_OB_EMPTY) {
- return false;
- }
- break;
- case OB_LAMP:
- if (exclude_filter & SO_FILTER_NO_OB_LAMP) {
- return false;
- }
- break;
- case OB_CAMERA:
- if (exclude_filter & SO_FILTER_NO_OB_CAMERA) {
- return false;
- }
- break;
- default:
- if (exclude_filter & SO_FILTER_NO_OB_OTHERS) {
- return false;
- }
- break;
- }
- }
-
- if (exclude_filter & SO_FILTER_OB_STATE) {
- if (base == NULL) {
- base = BKE_view_layer_base_find(view_layer, ob);
-
- if (base == NULL) {
- return false;
- }
- }
-
- if (exclude_filter & SO_FILTER_OB_STATE_VISIBLE) {
- if ((base->flag & BASE_VISIBLE) == 0) {
- return false;
- }
- }
- else if (exclude_filter & SO_FILTER_OB_STATE_SELECTED) {
- if ((base->flag & BASE_SELECTED) == 0) {
- return false;
- }
- }
- else {
- BLI_assert(exclude_filter & SO_FILTER_OB_STATE_ACTIVE);
- if (base != BASACT(view_layer)) {
- return false;
- }
- }
- }
-
- if ((te->parent != NULL) &&
- (TREESTORE(te->parent)->type == 0) && (te->parent->idcode == ID_OB))
- {
- if (exclude_filter & SO_FILTER_NO_CHILDREN) {
- return false;
- }
- }
- }
- else if (te->parent != NULL &&
- TREESTORE(te->parent)->type == 0 && te->parent->idcode == ID_OB)
- {
- if (exclude_filter & SO_FILTER_NO_OB_CONTENT) {
- return false;
- }
- }
-
- return true;
+ if ((exclude_filter & SO_FILTER_ANY) == 0) {
+ return true;
+ }
+
+ TreeStoreElem *tselem = TREESTORE(te);
+ if ((tselem->type == 0) && (te->idcode == ID_OB)) {
+ if ((exclude_filter & SO_FILTER_OB_TYPE) == SO_FILTER_OB_TYPE) {
+ return false;
+ }
+
+ Object *ob = (Object *)tselem->id;
+ Base *base = (Base *)te->directdata;
+ BLI_assert((base == NULL) || (base->object == ob));
+
+ if (exclude_filter & SO_FILTER_OB_TYPE) {
+ switch (ob->type) {
+ case OB_MESH:
+ if (exclude_filter & SO_FILTER_NO_OB_MESH) {
+ return false;
+ }
+ break;
+ case OB_ARMATURE:
+ if (exclude_filter & SO_FILTER_NO_OB_ARMATURE) {
+ return false;
+ }
+ break;
+ case OB_EMPTY:
+ if (exclude_filter & SO_FILTER_NO_OB_EMPTY) {
+ return false;
+ }
+ break;
+ case OB_LAMP:
+ if (exclude_filter & SO_FILTER_NO_OB_LAMP) {
+ return false;
+ }
+ break;
+ case OB_CAMERA:
+ if (exclude_filter & SO_FILTER_NO_OB_CAMERA) {
+ return false;
+ }
+ break;
+ default:
+ if (exclude_filter & SO_FILTER_NO_OB_OTHERS) {
+ return false;
+ }
+ break;
+ }
+ }
+
+ if (exclude_filter & SO_FILTER_OB_STATE) {
+ if (base == NULL) {
+ base = BKE_view_layer_base_find(view_layer, ob);
+
+ if (base == NULL) {
+ return false;
+ }
+ }
+
+ if (exclude_filter & SO_FILTER_OB_STATE_VISIBLE) {
+ if ((base->flag & BASE_VISIBLE) == 0) {
+ return false;
+ }
+ }
+ else if (exclude_filter & SO_FILTER_OB_STATE_SELECTED) {
+ if ((base->flag & BASE_SELECTED) == 0) {
+ return false;
+ }
+ }
+ else {
+ BLI_assert(exclude_filter & SO_FILTER_OB_STATE_ACTIVE);
+ if (base != BASACT(view_layer)) {
+ return false;
+ }
+ }
+ }
+
+ if ((te->parent != NULL) && (TREESTORE(te->parent)->type == 0) &&
+ (te->parent->idcode == ID_OB)) {
+ if (exclude_filter & SO_FILTER_NO_CHILDREN) {
+ return false;
+ }
+ }
+ }
+ else if (te->parent != NULL && TREESTORE(te->parent)->type == 0 && te->parent->idcode == ID_OB) {
+ if (exclude_filter & SO_FILTER_NO_OB_CONTENT) {
+ return false;
+ }
+ }
+
+ return true;
}
static bool outliner_filter_has_name(TreeElement *te, const char *name, int flags)
{
- int fn_flag = 0;
+ int fn_flag = 0;
- if ((flags & SO_FIND_CASE_SENSITIVE) == 0) {
- fn_flag |= FNM_CASEFOLD;
- }
+ if ((flags & SO_FIND_CASE_SENSITIVE) == 0) {
+ fn_flag |= FNM_CASEFOLD;
+ }
- return fnmatch(name, te->name, fn_flag) == 0;
+ return fnmatch(name, te->name, fn_flag) == 0;
}
-static int outliner_filter_subtree(
- SpaceOutliner *soops, ViewLayer *view_layer, ListBase *lb, const char *search_string, const int exclude_filter)
+static int outliner_filter_subtree(SpaceOutliner *soops,
+ ViewLayer *view_layer,
+ ListBase *lb,
+ const char *search_string,
+ const int exclude_filter)
{
- TreeElement *te, *te_next;
- TreeStoreElem *tselem;
-
- for (te = lb->first; te; te = te_next) {
- te_next = te->next;
-
- if ((outliner_element_visible_get(view_layer, te, exclude_filter) == false)) {
- outliner_free_tree_element(te, lb);
- continue;
- }
- else if ((exclude_filter & SO_FILTER_SEARCH) == 0) {
- /* Filter subtree too. */
- outliner_filter_subtree(soops, view_layer, &te->subtree, search_string, exclude_filter);
- continue;
- }
-
- if (!outliner_filter_has_name(te, search_string, soops->search_flags)) {
- /* item isn't something we're looking for, but...
- * - if the subtree is expanded, check if there are any matches that can be easily found
- * so that searching for "cu" in the default scene will still match the Cube
- * - otherwise, we can't see within the subtree and the item doesn't match,
- * so these can be safely ignored (i.e. the subtree can get freed)
- */
- tselem = TREESTORE(te);
-
- /* flag as not a found item */
- tselem->flag &= ~TSE_SEARCHMATCH;
-
- if ((!TSELEM_OPEN(tselem, soops)) ||
- outliner_filter_subtree(soops, view_layer, &te->subtree, search_string, exclude_filter) == 0)
- {
- outliner_free_tree_element(te, lb);
- }
- }
- else {
- tselem = TREESTORE(te);
-
- /* flag as a found item - we can then highlight it */
- tselem->flag |= TSE_SEARCHMATCH;
-
- /* filter subtree too */
- outliner_filter_subtree(soops, view_layer, &te->subtree, search_string, exclude_filter);
- }
- }
-
- /* if there are still items in the list, that means that there were still some matches */
- return (BLI_listbase_is_empty(lb) == false);
+ TreeElement *te, *te_next;
+ TreeStoreElem *tselem;
+
+ for (te = lb->first; te; te = te_next) {
+ te_next = te->next;
+
+ if ((outliner_element_visible_get(view_layer, te, exclude_filter) == false)) {
+ outliner_free_tree_element(te, lb);
+ continue;
+ }
+ else if ((exclude_filter & SO_FILTER_SEARCH) == 0) {
+ /* Filter subtree too. */
+ outliner_filter_subtree(soops, view_layer, &te->subtree, search_string, exclude_filter);
+ continue;
+ }
+
+ if (!outliner_filter_has_name(te, search_string, soops->search_flags)) {
+ /* item isn't something we're looking for, but...
+ * - if the subtree is expanded, check if there are any matches that can be easily found
+ * so that searching for "cu" in the default scene will still match the Cube
+ * - otherwise, we can't see within the subtree and the item doesn't match,
+ * so these can be safely ignored (i.e. the subtree can get freed)
+ */
+ tselem = TREESTORE(te);
+
+ /* flag as not a found item */
+ tselem->flag &= ~TSE_SEARCHMATCH;
+
+ if ((!TSELEM_OPEN(tselem, soops)) ||
+ outliner_filter_subtree(
+ soops, view_layer, &te->subtree, search_string, exclude_filter) == 0) {
+ outliner_free_tree_element(te, lb);
+ }
+ }
+ else {
+ tselem = TREESTORE(te);
+
+ /* flag as a found item - we can then highlight it */
+ tselem->flag |= TSE_SEARCHMATCH;
+
+ /* filter subtree too */
+ outliner_filter_subtree(soops, view_layer, &te->subtree, search_string, exclude_filter);
+ }
+ }
+
+ /* if there are still items in the list, that means that there were still some matches */
+ return (BLI_listbase_is_empty(lb) == false);
}
static void outliner_filter_tree(SpaceOutliner *soops, ViewLayer *view_layer)
{
- char search_buff[sizeof(((struct SpaceOutliner *)NULL)->search_string) + 2];
- char *search_string;
+ char search_buff[sizeof(((struct SpaceOutliner *)NULL)->search_string) + 2];
+ char *search_string;
- const int exclude_filter = outliner_exclude_filter_get(soops);
+ const int exclude_filter = outliner_exclude_filter_get(soops);
- if (exclude_filter == 0) {
- return;
- }
+ if (exclude_filter == 0) {
+ return;
+ }
- if (soops->search_flags & SO_FIND_COMPLETE) {
- search_string = soops->search_string;
- }
- else {
- /* Implicitly add heading/trailing wildcards if needed. */
- BLI_strncpy_ensure_pad(search_buff, soops->search_string, '*', sizeof(search_buff));
- search_string = search_buff;
- }
+ if (soops->search_flags & SO_FIND_COMPLETE) {
+ search_string = soops->search_string;
+ }
+ else {
+ /* Implicitly add heading/trailing wildcards if needed. */
+ BLI_strncpy_ensure_pad(search_buff, soops->search_string, '*', sizeof(search_buff));
+ search_string = search_buff;
+ }
- outliner_filter_subtree(soops, view_layer, &soops->tree, search_string, exclude_filter);
+ outliner_filter_subtree(soops, view_layer, &soops->tree, search_string, exclude_filter);
}
/* ======================================================= */
@@ -2011,172 +2024,173 @@ 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)
+void outliner_build_tree(
+ Main *mainvar, Scene *scene, ViewLayer *view_layer, SpaceOutliner *soops, ARegion *ar)
{
- TreeElement *te = NULL, *ten;
- TreeStoreElem *tselem;
- /* on first view, we open scenes */
- int show_opened = !soops->treestore || !BLI_mempool_len(soops->treestore);
-
- /* Are we looking for something - we want to tag parents to filter child matches
- * - NOT in datablocks view - searching all datablocks takes way too long to be useful
- * - this variable is only set once per tree build */
- if (soops->search_string[0] != 0 && soops->outlinevis != SO_DATA_API) {
- soops->search_flags |= SO_SEARCH_RECURSIVE;
- }
- else {
- soops->search_flags &= ~SO_SEARCH_RECURSIVE;
- }
-
- if (soops->treehash && (soops->storeflag & SO_TREESTORE_REBUILD) && soops->treestore) {
- soops->storeflag &= ~SO_TREESTORE_REBUILD;
- BKE_outliner_treehash_rebuild_from_treestore(soops->treehash, soops->treestore);
- }
-
- if (ar->do_draw & RGN_DRAW_NO_REBUILD) {
- return;
- }
-
- OutlinerTreeElementFocus focus;
- outliner_store_scrolling_position(soops, ar, &focus);
-
- outliner_free_tree(&soops->tree);
- outliner_storage_cleanup(soops);
-
- /* options */
- if (soops->outlinevis == SO_LIBRARIES) {
- Library *lib;
-
- /* current file first - mainvar provides tselem with unique pointer - not used */
- ten = outliner_add_library_contents(mainvar, soops, &soops->tree, NULL);
- if (ten) {
- tselem = TREESTORE(ten);
- if (!tselem->used) {
- tselem->flag &= ~TSE_CLOSED;
- }
- }
-
- for (lib = mainvar->libraries.first; lib; lib = lib->id.next) {
- ten = outliner_add_library_contents(mainvar, soops, &soops->tree, lib);
- if (ten) {
- lib->id.newid = (ID *)ten;
- }
-
- }
- /* make hierarchy */
- ten = soops->tree.first;
- if (ten != NULL) {
- ten = ten->next; /* first one is main */
- while (ten) {
- TreeElement *nten = ten->next, *par;
- tselem = TREESTORE(ten);
- lib = (Library *)tselem->id;
- if (lib && lib->parent) {
- par = (TreeElement *)lib->parent->id.newid;
- if (tselem->id->tag & LIB_TAG_INDIRECT) {
- /* Only remove from 'first level' if lib is not also directly used. */
- BLI_remlink(&soops->tree, ten);
- BLI_addtail(&par->subtree, ten);
- ten->parent = par;
- }
- else {
- /* Else, make a new copy of the libtree for our parent. */
- TreeElement *dupten = outliner_add_library_contents(mainvar, soops, &par->subtree, lib);
- if (dupten) {
- dupten->parent = par;
- }
- }
- }
- ten = nten;
- }
- }
- /* restore newid pointers */
- for (lib = mainvar->libraries.first; lib; lib = lib->id.next) {
- lib->id.newid = NULL;
- }
-
- }
- else if (soops->outlinevis == SO_SCENES) {
- Scene *sce;
- for (sce = mainvar->scenes.first; sce; sce = sce->id.next) {
- te = outliner_add_element(soops, &soops->tree, sce, NULL, 0, 0);
- tselem = TREESTORE(te);
-
- if (sce == scene && show_opened) {
- tselem->flag &= ~TSE_CLOSED;
- }
-
- outliner_make_object_parent_hierarchy(&te->subtree);
- }
- }
- else if (soops->outlinevis == SO_SEQUENCE) {
- Sequence *seq;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- int op;
-
- if (ed == NULL) {
- return;
- }
-
- seq = ed->seqbasep->first;
- if (!seq) {
- return;
- }
-
- while (seq) {
- op = need_add_seq_dup(seq);
- if (op == 1) {
- /* ten = */ outliner_add_element(soops, &soops->tree, (void *)seq, NULL, TSE_SEQUENCE, 0);
- }
- else if (op == 0) {
- ten = outliner_add_element(soops, &soops->tree, (void *)seq, NULL, TSE_SEQUENCE_DUP, 0);
- outliner_add_seq_dup(soops, seq, ten, 0);
- }
- seq = seq->next;
- }
- }
- else if (soops->outlinevis == SO_DATA_API) {
- PointerRNA mainptr;
-
- RNA_main_pointer_create(mainvar, &mainptr);
-
- ten = outliner_add_element(soops, &soops->tree, (void *)&mainptr, NULL, TSE_RNA_STRUCT, -1);
-
- if (show_opened) {
- tselem = TREESTORE(ten);
- tselem->flag &= ~TSE_CLOSED;
- }
- }
- else if (soops->outlinevis == SO_ID_ORPHANS) {
- outliner_add_orphaned_datablocks(mainvar, soops);
- }
- 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) {
- TreeElement *te_object = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
- te_object->directdata = base;
- }
-
- outliner_make_object_parent_hierarchy(&soops->tree);
- }
- else {
- /* Show collections in the view layer. */
- ten = outliner_add_element(soops, &soops->tree, scene, NULL, TSE_VIEW_COLLECTION_BASE, 0);
- ten->name = IFACE_("Scene Collection");
- TREESTORE(ten)->flag &= ~TSE_CLOSED;
-
- bool show_objects = !(soops->filter & SO_FILTER_NO_OBJECT);
- outliner_add_view_layer(soops, &ten->subtree, ten, view_layer, show_objects);
- }
- }
-
- if ((soops->flag & SO_SKIP_SORT_ALPHA) == 0) {
- outliner_sort(&soops->tree);
- }
-
- outliner_filter_tree(soops, view_layer);
- outliner_restore_scrolling_position(soops, ar, &focus);
-
- BKE_main_id_clear_newpoins(mainvar);
+ TreeElement *te = NULL, *ten;
+ TreeStoreElem *tselem;
+ /* on first view, we open scenes */
+ int show_opened = !soops->treestore || !BLI_mempool_len(soops->treestore);
+
+ /* Are we looking for something - we want to tag parents to filter child matches
+ * - NOT in datablocks view - searching all datablocks takes way too long to be useful
+ * - this variable is only set once per tree build */
+ if (soops->search_string[0] != 0 && soops->outlinevis != SO_DATA_API) {
+ soops->search_flags |= SO_SEARCH_RECURSIVE;
+ }
+ else {
+ soops->search_flags &= ~SO_SEARCH_RECURSIVE;
+ }
+
+ if (soops->treehash && (soops->storeflag & SO_TREESTORE_REBUILD) && soops->treestore) {
+ soops->storeflag &= ~SO_TREESTORE_REBUILD;
+ BKE_outliner_treehash_rebuild_from_treestore(soops->treehash, soops->treestore);
+ }
+
+ if (ar->do_draw & RGN_DRAW_NO_REBUILD) {
+ return;
+ }
+
+ OutlinerTreeElementFocus focus;
+ outliner_store_scrolling_position(soops, ar, &focus);
+
+ outliner_free_tree(&soops->tree);
+ outliner_storage_cleanup(soops);
+
+ /* options */
+ if (soops->outlinevis == SO_LIBRARIES) {
+ Library *lib;
+
+ /* current file first - mainvar provides tselem with unique pointer - not used */
+ ten = outliner_add_library_contents(mainvar, soops, &soops->tree, NULL);
+ if (ten) {
+ tselem = TREESTORE(ten);
+ if (!tselem->used) {
+ tselem->flag &= ~TSE_CLOSED;
+ }
+ }
+
+ for (lib = mainvar->libraries.first; lib; lib = lib->id.next) {
+ ten = outliner_add_library_contents(mainvar, soops, &soops->tree, lib);
+ if (ten) {
+ lib->id.newid = (ID *)ten;
+ }
+ }
+ /* make hierarchy */
+ ten = soops->tree.first;
+ if (ten != NULL) {
+ ten = ten->next; /* first one is main */
+ while (ten) {
+ TreeElement *nten = ten->next, *par;
+ tselem = TREESTORE(ten);
+ lib = (Library *)tselem->id;
+ if (lib && lib->parent) {
+ par = (TreeElement *)lib->parent->id.newid;
+ if (tselem->id->tag & LIB_TAG_INDIRECT) {
+ /* Only remove from 'first level' if lib is not also directly used. */
+ BLI_remlink(&soops->tree, ten);
+ BLI_addtail(&par->subtree, ten);
+ ten->parent = par;
+ }
+ else {
+ /* Else, make a new copy of the libtree for our parent. */
+ TreeElement *dupten = outliner_add_library_contents(
+ mainvar, soops, &par->subtree, lib);
+ if (dupten) {
+ dupten->parent = par;
+ }
+ }
+ }
+ ten = nten;
+ }
+ }
+ /* restore newid pointers */
+ for (lib = mainvar->libraries.first; lib; lib = lib->id.next) {
+ lib->id.newid = NULL;
+ }
+ }
+ else if (soops->outlinevis == SO_SCENES) {
+ Scene *sce;
+ for (sce = mainvar->scenes.first; sce; sce = sce->id.next) {
+ te = outliner_add_element(soops, &soops->tree, sce, NULL, 0, 0);
+ tselem = TREESTORE(te);
+
+ if (sce == scene && show_opened) {
+ tselem->flag &= ~TSE_CLOSED;
+ }
+
+ outliner_make_object_parent_hierarchy(&te->subtree);
+ }
+ }
+ else if (soops->outlinevis == SO_SEQUENCE) {
+ Sequence *seq;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ int op;
+
+ if (ed == NULL) {
+ return;
+ }
+
+ seq = ed->seqbasep->first;
+ if (!seq) {
+ return;
+ }
+
+ while (seq) {
+ op = need_add_seq_dup(seq);
+ if (op == 1) {
+ /* ten = */ outliner_add_element(soops, &soops->tree, (void *)seq, NULL, TSE_SEQUENCE, 0);
+ }
+ else if (op == 0) {
+ ten = outliner_add_element(soops, &soops->tree, (void *)seq, NULL, TSE_SEQUENCE_DUP, 0);
+ outliner_add_seq_dup(soops, seq, ten, 0);
+ }
+ seq = seq->next;
+ }
+ }
+ else if (soops->outlinevis == SO_DATA_API) {
+ PointerRNA mainptr;
+
+ RNA_main_pointer_create(mainvar, &mainptr);
+
+ ten = outliner_add_element(soops, &soops->tree, (void *)&mainptr, NULL, TSE_RNA_STRUCT, -1);
+
+ if (show_opened) {
+ tselem = TREESTORE(ten);
+ tselem->flag &= ~TSE_CLOSED;
+ }
+ }
+ else if (soops->outlinevis == SO_ID_ORPHANS) {
+ outliner_add_orphaned_datablocks(mainvar, soops);
+ }
+ 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) {
+ TreeElement *te_object = outliner_add_element(
+ soops, &soops->tree, base->object, NULL, 0, 0);
+ te_object->directdata = base;
+ }
+
+ outliner_make_object_parent_hierarchy(&soops->tree);
+ }
+ else {
+ /* Show collections in the view layer. */
+ ten = outliner_add_element(soops, &soops->tree, scene, NULL, TSE_VIEW_COLLECTION_BASE, 0);
+ ten->name = IFACE_("Scene Collection");
+ TREESTORE(ten)->flag &= ~TSE_CLOSED;
+
+ bool show_objects = !(soops->filter & SO_FILTER_NO_OBJECT);
+ outliner_add_view_layer(soops, &ten->subtree, ten, view_layer, show_objects);
+ }
+ }
+
+ if ((soops->flag & SO_SKIP_SORT_ALPHA) == 0) {
+ outliner_sort(&soops->tree);
+ }
+
+ outliner_filter_tree(soops, view_layer);
+ outliner_restore_scrolling_position(soops, ar, &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 a44a6e605de..03d15088380 100644
--- a/source/blender/editors/space_outliner/outliner_utils.c
+++ b/source/blender/editors/space_outliner/outliner_utils.c
@@ -38,25 +38,27 @@
* Try to find an item under y-coordinate \a view_co_y (view-space).
* \note Recursive
*/
-TreeElement *outliner_find_item_at_y(const SpaceOutliner *soops, const ListBase *tree, float view_co_y)
+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) {
- if (view_co_y < (te_iter->ys + UI_UNIT_Y)) {
- if (view_co_y >= te_iter->ys) {
- /* co_y is inside this element */
- return te_iter;
- }
- else if (TSELEM_OPEN(te_iter->store_elem, soops)) {
- /* co_y is lower than current element, possibly inside children */
- TreeElement *te_sub = outliner_find_item_at_y(soops, &te_iter->subtree, view_co_y);
- if (te_sub) {
- return te_sub;
- }
- }
- }
- }
-
- return NULL;
+ for (TreeElement *te_iter = tree->first; te_iter; te_iter = te_iter->next) {
+ if (view_co_y < (te_iter->ys + UI_UNIT_Y)) {
+ if (view_co_y >= te_iter->ys) {
+ /* co_y is inside this element */
+ return te_iter;
+ }
+ else if (TSELEM_OPEN(te_iter->store_elem, soops)) {
+ /* co_y is lower than current element, possibly inside children */
+ TreeElement *te_sub = outliner_find_item_at_y(soops, &te_iter->subtree, view_co_y);
+ if (te_sub) {
+ return te_sub;
+ }
+ }
+ }
+ }
+
+ return NULL;
}
/**
@@ -65,146 +67,150 @@ TreeElement *outliner_find_item_at_y(const SpaceOutliner *soops, const ListBase
*
* \return a hovered child item or \a parent_te (if no hovered child found).
*/
-TreeElement *outliner_find_item_at_x_in_row(const SpaceOutliner *soops, const TreeElement *parent_te, float view_co_x)
+TreeElement *outliner_find_item_at_x_in_row(const SpaceOutliner *soops,
+ const TreeElement *parent_te,
+ float view_co_x)
{
- /* if parent_te is opened, it doesn't show childs in row */
- if (!TSELEM_OPEN(TREESTORE(parent_te), soops)) {
- /* no recursion, items can only display their direct children in the row */
- for (TreeElement *child_te = parent_te->subtree.first;
- /* don't look further if co_x is smaller than child position*/
- child_te && view_co_x >= child_te->xs;
-
- child_te = child_te->next)
- {
- if ((child_te->flag & TE_ICONROW) && (view_co_x > child_te->xs) && (view_co_x < child_te->xend)) {
- return child_te;
- }
- }
- }
-
- /* return parent if no child is hovered */
- return (TreeElement *)parent_te;
+ /* if parent_te is opened, it doesn't show childs in row */
+ if (!TSELEM_OPEN(TREESTORE(parent_te), soops)) {
+ /* no recursion, items can only display their direct children in the row */
+ for (TreeElement *child_te = parent_te->subtree.first;
+ /* don't look further if co_x is smaller than child position*/
+ child_te && view_co_x >= child_te->xs;
+
+ child_te = child_te->next) {
+ if ((child_te->flag & TE_ICONROW) && (view_co_x > child_te->xs) &&
+ (view_co_x < child_te->xend)) {
+ return child_te;
+ }
+ }
+ }
+
+ /* return parent if no child is hovered */
+ return (TreeElement *)parent_te;
}
/* Find specific item from the treestore */
TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem)
{
- TreeElement *te, *tes;
- for (te = lb->first; te; te = te->next) {
- if (te->store_elem == store_elem) {
- return te;
- }
- tes = outliner_find_tree_element(&te->subtree, store_elem);
- if (tes) {
- return tes;
- }
- }
- return NULL;
+ TreeElement *te, *tes;
+ for (te = lb->first; te; te = te->next) {
+ if (te->store_elem == store_elem) {
+ return te;
+ }
+ tes = outliner_find_tree_element(&te->subtree, store_elem);
+ if (tes) {
+ return tes;
+ }
+ }
+ return NULL;
}
/* Find parent element of te */
-TreeElement *outliner_find_parent_element(ListBase *lb, TreeElement *parent_te, const TreeElement *child_te)
+TreeElement *outliner_find_parent_element(ListBase *lb,
+ TreeElement *parent_te,
+ const TreeElement *child_te)
{
- TreeElement *te;
- for (te = lb->first; te; te = te->next) {
- if (te == child_te) {
- return parent_te;
- }
-
- TreeElement *find_te = outliner_find_parent_element(&te->subtree, te, child_te);
- if (find_te) {
- return find_te;
- }
- }
- return NULL;
+ TreeElement *te;
+ for (te = lb->first; te; te = te->next) {
+ if (te == child_te) {
+ return parent_te;
+ }
+
+ TreeElement *find_te = outliner_find_parent_element(&te->subtree, te, child_te);
+ if (find_te) {
+ return find_te;
+ }
+ }
+ return NULL;
}
/* tse is not in the treestore, we use its contents to find a match */
TreeElement *outliner_find_tse(SpaceOutliner *soops, const TreeStoreElem *tse)
{
- TreeStoreElem *tselem;
+ TreeStoreElem *tselem;
- if (tse->id == NULL) {
- return NULL;
- }
+ if (tse->id == NULL) {
+ return NULL;
+ }
- /* check if 'tse' is in treestore */
- tselem = BKE_outliner_treehash_lookup_any(soops->treehash, tse->type, tse->nr, tse->id);
- if (tselem) {
- return outliner_find_tree_element(&soops->tree, tselem);
- }
+ /* check if 'tse' is in treestore */
+ tselem = BKE_outliner_treehash_lookup_any(soops->treehash, tse->type, tse->nr, tse->id);
+ if (tselem) {
+ return outliner_find_tree_element(&soops->tree, tselem);
+ }
- return NULL;
+ return NULL;
}
/* 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) {
- TreeStoreElem *tselem = TREESTORE(te);
- if (tselem->type == 0) {
- if (tselem->id == id) {
- return te;
- }
- }
-
- TreeElement *tes = outliner_find_id(soops, &te->subtree, id);
- if (tes) {
- return tes;
- }
- }
- return NULL;
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (tselem->type == 0) {
+ if (tselem->id == id) {
+ return te;
+ }
+ }
+
+ TreeElement *tes = outliner_find_id(soops, &te->subtree, id);
+ if (tes) {
+ return tes;
+ }
+ }
+ return NULL;
}
TreeElement *outliner_find_posechannel(ListBase *lb, const bPoseChannel *pchan)
{
- for (TreeElement *te = lb->first; te; te = te->next) {
- if (te->directdata == pchan) {
- return te;
- }
-
- TreeStoreElem *tselem = TREESTORE(te);
- if (ELEM(tselem->type, TSE_POSE_BASE, TSE_POSE_CHANNEL)) {
- TreeElement *tes = outliner_find_posechannel(&te->subtree, pchan);
- if (tes) {
- return tes;
- }
- }
- }
- return NULL;
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ if (te->directdata == pchan) {
+ return te;
+ }
+
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (ELEM(tselem->type, TSE_POSE_BASE, TSE_POSE_CHANNEL)) {
+ TreeElement *tes = outliner_find_posechannel(&te->subtree, pchan);
+ if (tes) {
+ return tes;
+ }
+ }
+ }
+ return NULL;
}
TreeElement *outliner_find_editbone(ListBase *lb, const EditBone *ebone)
{
- for (TreeElement *te = lb->first; te; te = te->next) {
- if (te->directdata == ebone) {
- return te;
- }
-
- TreeStoreElem *tselem = TREESTORE(te);
- if (ELEM(tselem->type, 0, TSE_EBONE)) {
- TreeElement *tes = outliner_find_editbone(&te->subtree, ebone);
- if (tes) {
- return tes;
- }
- }
- }
- return NULL;
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ if (te->directdata == ebone) {
+ return te;
+ }
+
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (ELEM(tselem->type, 0, TSE_EBONE)) {
+ TreeElement *tes = outliner_find_editbone(&te->subtree, ebone);
+ if (tes) {
+ return tes;
+ }
+ }
+ }
+ return NULL;
}
ID *outliner_search_back(SpaceOutliner *UNUSED(soops), TreeElement *te, short idcode)
{
- TreeStoreElem *tselem;
- te = te->parent;
-
- while (te) {
- tselem = TREESTORE(te);
- if (tselem->type == 0 && te->idcode == idcode) {
- return tselem->id;
- }
- te = te->parent;
- }
- return NULL;
+ TreeStoreElem *tselem;
+ te = te->parent;
+
+ while (te) {
+ tselem = TREESTORE(te);
+ if (tselem->type == 0 && te->idcode == idcode) {
+ return tselem->id;
+ }
+ te = te->parent;
+ }
+ return NULL;
}
/**
@@ -215,38 +221,43 @@ ID *outliner_search_back(SpaceOutliner *UNUSED(soops), TreeElement *te, short id
* \param filter_tselem_flag: Same as \a filter_te_flag, but for the TreeStoreElem.
* \param func: Custom callback to execute for each visited item.
*/
-bool outliner_tree_traverse(const SpaceOutliner *soops, ListBase *tree, int filter_te_flag, int filter_tselem_flag,
- TreeTraversalFunc func, void *customdata)
+bool outliner_tree_traverse(const SpaceOutliner *soops,
+ ListBase *tree,
+ int filter_te_flag,
+ int filter_tselem_flag,
+ TreeTraversalFunc func,
+ void *customdata)
{
- for (TreeElement *te = tree->first, *te_next; te; te = te_next) {
- TreeTraversalAction func_retval = TRAVERSE_CONTINUE;
- /* in case te is freed in callback */
- TreeStoreElem *tselem = TREESTORE(te);
- ListBase subtree = te->subtree;
- te_next = te->next;
-
- if (filter_te_flag && (te->flag & filter_te_flag) == 0) {
- /* skip */
- }
- else if (filter_tselem_flag && (tselem->flag & filter_tselem_flag) == 0) {
- /* skip */
- }
- else {
- func_retval = func(te, customdata);
- }
- /* Don't access te or tselem from now on! Might've been freed... */
-
- if (func_retval == TRAVERSE_BREAK) {
- return false;
- }
-
- if (func_retval == TRAVERSE_SKIP_CHILDS) {
- /* skip */
- }
- else if (!outliner_tree_traverse(soops, &subtree, filter_te_flag, filter_tselem_flag, func, customdata)) {
- return false;
- }
- }
-
- return true;
+ for (TreeElement *te = tree->first, *te_next; te; te = te_next) {
+ TreeTraversalAction func_retval = TRAVERSE_CONTINUE;
+ /* in case te is freed in callback */
+ TreeStoreElem *tselem = TREESTORE(te);
+ ListBase subtree = te->subtree;
+ te_next = te->next;
+
+ if (filter_te_flag && (te->flag & filter_te_flag) == 0) {
+ /* skip */
+ }
+ else if (filter_tselem_flag && (tselem->flag & filter_tselem_flag) == 0) {
+ /* skip */
+ }
+ else {
+ func_retval = func(te, customdata);
+ }
+ /* Don't access te or tselem from now on! Might've been freed... */
+
+ if (func_retval == TRAVERSE_BREAK) {
+ return false;
+ }
+
+ if (func_retval == TRAVERSE_SKIP_CHILDS) {
+ /* skip */
+ }
+ else if (!outliner_tree_traverse(
+ soops, &subtree, filter_te_flag, filter_tselem_flag, func, customdata)) {
+ return false;
+ }
+ }
+
+ return true;
}
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index dc51d501b99..26b97a1cdd9 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -21,7 +21,6 @@
* \ingroup spoutliner
*/
-
#include <string.h>
#include <stdio.h>
@@ -52,380 +51,381 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-
#include "outliner_intern.h"
#include "GPU_framebuffer.h"
static void outliner_main_region_init(wmWindowManager *wm, ARegion *ar)
{
- 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;
-
- 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;
-
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
-
- /* own keymap */
- keymap = WM_keymap_ensure(wm->defaultconf, "Outliner", SPACE_OUTLINER, 0);
- /* don't pass on view2d mask, it's always set with scrollbar space, hide fails */
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, NULL, &ar->winrct);
-
- /* Add dropboxes */
- lb = WM_dropboxmap_find("Outliner", SPACE_OUTLINER, RGN_TYPE_WINDOW);
- WM_event_add_dropbox_handler(&ar->handlers, lb);
+ 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;
+
+ 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;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Outliner", SPACE_OUTLINER, 0);
+ /* don't pass on view2d mask, it's always set with scrollbar space, hide fails */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, NULL, &ar->winrct);
+
+ /* Add dropboxes */
+ lb = WM_dropboxmap_find("Outliner", SPACE_OUTLINER, RGN_TYPE_WINDOW);
+ WM_event_add_dropbox_handler(&ar->handlers, lb);
}
static void outliner_main_region_draw(const bContext *C, ARegion *ar)
{
- View2D *v2d = &ar->v2d;
- View2DScrollers *scrollers;
+ View2D *v2d = &ar->v2d;
+ View2DScrollers *scrollers;
- /* clear */
- UI_ThemeClearColor(TH_BACK);
- GPU_clear(GPU_COLOR_BIT);
+ /* clear */
+ UI_ThemeClearColor(TH_BACK);
+ GPU_clear(GPU_COLOR_BIT);
- draw_outliner(C);
+ draw_outliner(C);
- /* reset view matrix */
- UI_view2d_view_restore(C);
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
- /* scrollers */
- scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
+ /* scrollers */
+ scrollers = UI_view2d_scrollers_calc(
+ C, v2d, NULL, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
}
-
static void outliner_main_region_free(ARegion *UNUSED(ar))
{
-
}
-static void outliner_main_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void outliner_main_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_SCENE:
- switch (wmn->data) {
- case ND_OB_ACTIVE:
- case ND_OB_SELECT:
- case ND_OB_VISIBLE:
- case ND_OB_RENDER:
- case ND_MODE:
- case ND_KEYINGSET:
- case ND_FRAME:
- case ND_RENDER_OPTIONS:
- case ND_SEQUENCER:
- case ND_LAYER:
- case ND_LAYER_CONTENT:
- case ND_WORLD:
- case ND_SCENEBROWSE:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_OBJECT:
- switch (wmn->data) {
- case ND_TRANSFORM:
- /* transform doesn't change outliner data */
- break;
- case ND_BONE_ACTIVE:
- case ND_BONE_SELECT:
- case ND_DRAW:
- case ND_PARENT:
- case ND_OB_SHADING:
- ED_region_tag_redraw(ar);
- break;
- case ND_CONSTRAINT:
- switch (wmn->action) {
- case NA_ADDED:
- case NA_REMOVED:
- case NA_RENAME:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case ND_MODIFIER:
- /* all modifier actions now */
- ED_region_tag_redraw(ar);
- break;
- default:
- /* Trigger update for NC_OBJECT itself */
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_GROUP:
- /* all actions now, todo: check outliner view mode? */
- ED_region_tag_redraw(ar);
- break;
- case NC_LAMP:
- /* For updating light icons, when changing light type */
- if (wmn->data == ND_LIGHTING_DRAW) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_OUTLINER) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_ID:
- if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_MATERIAL:
- switch (wmn->data) {
- case ND_SHADING_LINKS:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_GEOM:
- switch (wmn->data) {
- case ND_VERTEX_GROUP:
- case ND_DATA:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_ANIMATION:
- switch (wmn->data) {
- case ND_NLA_ACTCHANGE:
- case ND_KEYFRAME:
- ED_region_tag_redraw(ar);
- break;
- case ND_ANIMCHAN:
- if (wmn->action == NA_SELECTED) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
- break;
- case NC_GPENCIL:
- if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SCREEN:
- if (ELEM(wmn->data, ND_LAYER)) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_MASK:
- if (ELEM(wmn->action, NA_ADDED)) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_PAINTCURVE:
- if (ELEM(wmn->action, NA_ADDED)) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
-
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_OB_ACTIVE:
+ case ND_OB_SELECT:
+ case ND_OB_VISIBLE:
+ case ND_OB_RENDER:
+ case ND_MODE:
+ case ND_KEYINGSET:
+ case ND_FRAME:
+ case ND_RENDER_OPTIONS:
+ case ND_SEQUENCER:
+ case ND_LAYER:
+ case ND_LAYER_CONTENT:
+ case ND_WORLD:
+ case ND_SCENEBROWSE:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch (wmn->data) {
+ case ND_TRANSFORM:
+ /* transform doesn't change outliner data */
+ break;
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_DRAW:
+ case ND_PARENT:
+ case ND_OB_SHADING:
+ ED_region_tag_redraw(ar);
+ break;
+ case ND_CONSTRAINT:
+ switch (wmn->action) {
+ case NA_ADDED:
+ case NA_REMOVED:
+ case NA_RENAME:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case ND_MODIFIER:
+ /* all modifier actions now */
+ ED_region_tag_redraw(ar);
+ break;
+ default:
+ /* Trigger update for NC_OBJECT itself */
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_GROUP:
+ /* all actions now, todo: check outliner view mode? */
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_LAMP:
+ /* For updating light icons, when changing light type */
+ if (wmn->data == ND_LIGHTING_DRAW) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_OUTLINER) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_ID:
+ if (wmn->action == NA_RENAME) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_MATERIAL:
+ switch (wmn->data) {
+ case ND_SHADING_LINKS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_GEOM:
+ switch (wmn->data) {
+ case ND_VERTEX_GROUP:
+ case ND_DATA:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_ANIMATION:
+ switch (wmn->data) {
+ case ND_NLA_ACTCHANGE:
+ case ND_KEYFRAME:
+ ED_region_tag_redraw(ar);
+ break;
+ case ND_ANIMCHAN:
+ if (wmn->action == NA_SELECTED) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
+ break;
+ case NC_GPENCIL:
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SCREEN:
+ if (ELEM(wmn->data, ND_LAYER)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_MASK:
+ if (ELEM(wmn->action, NA_ADDED)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_PAINTCURVE:
+ if (ELEM(wmn->action, NA_ADDED)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
}
-static void outliner_main_region_message_subscribe(
- const struct bContext *UNUSED(C),
- struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene),
- struct bScreen *UNUSED(screen), struct ScrArea *sa, struct ARegion *ar,
- struct wmMsgBus *mbus)
+static void outliner_main_region_message_subscribe(const struct bContext *UNUSED(C),
+ struct WorkSpace *UNUSED(workspace),
+ struct Scene *UNUSED(scene),
+ struct bScreen *UNUSED(screen),
+ struct ScrArea *sa,
+ struct ARegion *ar,
+ struct wmMsgBus *mbus)
{
- SpaceOutliner *soops = sa->spacedata.first;
- wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
- .notify = ED_region_do_msg_notify_tag_redraw,
- };
-
- if (ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_SCENES)) {
- WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
- }
+ SpaceOutliner *soops = sa->spacedata.first;
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ if (ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_SCENES)) {
+ WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
+ }
}
-
/* ************************ 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)
{
- ED_region_header_init(ar);
+ ED_region_header_init(ar);
}
static void outliner_header_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_header(C, ar);
+ ED_region_header(C, ar);
}
static void outliner_header_region_free(ARegion *UNUSED(ar))
{
}
-static void outliner_header_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void outliner_header_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_SCENE:
- if (wmn->data == ND_KEYINGSET) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_OUTLINER) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SCENE:
+ if (wmn->data == ND_KEYINGSET) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_OUTLINER) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
}
/* ******************** default callbacks for outliner space ***************** */
static SpaceLink *outliner_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
- SpaceOutliner *soutliner;
+ ARegion *ar;
+ SpaceOutliner *soutliner;
- soutliner = MEM_callocN(sizeof(SpaceOutliner), "initoutliner");
- soutliner->spacetype = SPACE_OUTLINER;
- soutliner->filter_id_type = ID_GR;
+ soutliner = MEM_callocN(sizeof(SpaceOutliner), "initoutliner");
+ soutliner->spacetype = SPACE_OUTLINER;
+ soutliner->filter_id_type = ID_GR;
- /* header */
- ar = MEM_callocN(sizeof(ARegion), "header for outliner");
+ /* header */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_HEADER;
+ ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
- /* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for outliner");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for outliner");
- BLI_addtail(&soutliner->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&soutliner->regionbase, ar);
+ ar->regiontype = RGN_TYPE_WINDOW;
- return (SpaceLink *)soutliner;
+ return (SpaceLink *)soutliner;
}
/* not spacelink itself */
static void outliner_free(SpaceLink *sl)
{
- SpaceOutliner *soutliner = (SpaceOutliner *)sl;
-
- outliner_free_tree(&soutliner->tree);
- if (soutliner->treestore) {
- BLI_mempool_destroy(soutliner->treestore);
- }
- if (soutliner->treehash) {
- BKE_outliner_treehash_free(soutliner->treehash);
- }
+ SpaceOutliner *soutliner = (SpaceOutliner *)sl;
+
+ outliner_free_tree(&soutliner->tree);
+ if (soutliner->treestore) {
+ BLI_mempool_destroy(soutliner->treestore);
+ }
+ if (soutliner->treehash) {
+ BKE_outliner_treehash_free(soutliner->treehash);
+ }
}
/* spacetype; init callback */
static void outliner_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
{
-
}
static SpaceLink *outliner_duplicate(SpaceLink *sl)
{
- SpaceOutliner *soutliner = (SpaceOutliner *)sl;
- SpaceOutliner *soutlinern = MEM_dupallocN(soutliner);
+ SpaceOutliner *soutliner = (SpaceOutliner *)sl;
+ SpaceOutliner *soutlinern = MEM_dupallocN(soutliner);
- BLI_listbase_clear(&soutlinern->tree);
- soutlinern->treestore = NULL;
- soutlinern->treehash = NULL;
+ BLI_listbase_clear(&soutlinern->tree);
+ soutlinern->treestore = NULL;
+ soutlinern->treehash = NULL;
- return (SpaceLink *)soutlinern;
+ return (SpaceLink *)soutlinern;
}
static void outliner_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
{
- SpaceOutliner *so = (SpaceOutliner *)slink;
-
- /* Some early out checks. */
- if (!TREESTORE_ID_TYPE(old_id)) {
- return; /* ID type is not used by outilner... */
- }
-
- if (so->search_tse.id == old_id) {
- so->search_tse.id = new_id;
- }
-
- if (so->treestore) {
- TreeStoreElem *tselem;
- BLI_mempool_iter iter;
- bool changed = false;
-
- BLI_mempool_iternew(so->treestore, &iter);
- while ((tselem = BLI_mempool_iterstep(&iter))) {
- if (tselem->id == old_id) {
- tselem->id = new_id;
- changed = true;
- }
- }
- if (so->treehash && changed) {
- /* rebuild hash table, because it depends on ids too */
- /* postpone a full rebuild because this can be called many times on-free */
- so->storeflag |= SO_TREESTORE_REBUILD;
- }
- }
+ SpaceOutliner *so = (SpaceOutliner *)slink;
+
+ /* Some early out checks. */
+ if (!TREESTORE_ID_TYPE(old_id)) {
+ return; /* ID type is not used by outilner... */
+ }
+
+ if (so->search_tse.id == old_id) {
+ so->search_tse.id = new_id;
+ }
+
+ if (so->treestore) {
+ TreeStoreElem *tselem;
+ BLI_mempool_iter iter;
+ bool changed = false;
+
+ BLI_mempool_iternew(so->treestore, &iter);
+ while ((tselem = BLI_mempool_iterstep(&iter))) {
+ if (tselem->id == old_id) {
+ tselem->id = new_id;
+ changed = true;
+ }
+ }
+ if (so->treehash && changed) {
+ /* rebuild hash table, because it depends on ids too */
+ /* postpone a full rebuild because this can be called many times on-free */
+ so->storeflag |= SO_TREESTORE_REBUILD;
+ }
+ }
}
/* only called once, from space_api/spacetypes.c */
void ED_spacetype_outliner(void)
{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype time");
- ARegionType *art;
-
- st->spaceid = SPACE_OUTLINER;
- strncpy(st->name, "Outliner", BKE_ST_MAXNAME);
-
- st->new = outliner_new;
- st->free = outliner_free;
- st->init = outliner_init;
- st->duplicate = outliner_duplicate;
- st->operatortypes = outliner_operatortypes;
- st->keymap = outliner_keymap;
- st->dropboxes = outliner_dropboxes;
- st->id_remap = outliner_id_remap;
-
- /* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype outliner region");
- art->regionid = RGN_TYPE_WINDOW;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES;
-
- art->init = outliner_main_region_init;
- art->draw = outliner_main_region_draw;
- art->free = outliner_main_region_free;
- art->listener = outliner_main_region_listener;
- art->message_subscribe = outliner_main_region_message_subscribe;
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype outliner header region");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
-
- art->init = outliner_header_region_init;
- art->draw = outliner_header_region_draw;
- art->free = outliner_header_region_free;
- art->listener = outliner_header_region_listener;
- BLI_addhead(&st->regiontypes, art);
-
- BKE_spacetype_register(st);
+ SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype time");
+ ARegionType *art;
+
+ st->spaceid = SPACE_OUTLINER;
+ strncpy(st->name, "Outliner", BKE_ST_MAXNAME);
+
+ st->new = outliner_new;
+ st->free = outliner_free;
+ st->init = outliner_init;
+ st->duplicate = outliner_duplicate;
+ st->operatortypes = outliner_operatortypes;
+ st->keymap = outliner_keymap;
+ st->dropboxes = outliner_dropboxes;
+ st->id_remap = outliner_id_remap;
+
+ /* regions: main window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype outliner region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES;
+
+ art->init = outliner_main_region_init;
+ art->draw = outliner_main_region_draw;
+ art->free = outliner_main_region_free;
+ art->listener = outliner_main_region_listener;
+ art->message_subscribe = outliner_main_region_message_subscribe;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype outliner header region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = HEADERY;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
+
+ art->init = outliner_header_region_init;
+ art->draw = outliner_header_region_draw;
+ art->free = outliner_header_region_free;
+ art->listener = outliner_header_region_listener;
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_script/CMakeLists.txt b/source/blender/editors/space_script/CMakeLists.txt
index 19b3e42b37a..1abc05d2270 100644
--- a/source/blender/editors/space_script/CMakeLists.txt
+++ b/source/blender/editors/space_script/CMakeLists.txt
@@ -16,37 +16,37 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- script_edit.c
- script_ops.c
- space_script.c
+ script_edit.c
+ script_ops.c
+ space_script.c
- script_intern.h
+ script_intern.h
)
set(LIB
)
if(WITH_PYTHON)
- list(APPEND INC
- ../../python
- )
- add_definitions(-DWITH_PYTHON)
+ list(APPEND INC
+ ../../python
+ )
+ add_definitions(-DWITH_PYTHON)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/space_script/script_edit.c b/source/blender/editors/space_script/script_edit.c
index 4b5cd6b7166..48248fe1dd2 100644
--- a/source/blender/editors/space_script/script_edit.c
+++ b/source/blender/editors/space_script/script_edit.c
@@ -21,7 +21,6 @@
* \ingroup spscript
*/
-
#include <string.h>
#include <stdio.h>
@@ -40,69 +39,68 @@
#include "ED_screen.h"
-
#include "script_intern.h" // own include
#ifdef WITH_PYTHON
-#include "BPY_extern.h" /* BPY_script_exec */
+# include "BPY_extern.h" /* BPY_script_exec */
#endif
static int run_pyfile_exec(bContext *C, wmOperator *op)
{
- char path[512];
- RNA_string_get(op->ptr, "filepath", path);
+ char path[512];
+ 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);
- return OPERATOR_FINISHED;
- }
+ if (BPY_execute_filepath(C, path, op->reports)) {
+ ARegion *ar = CTX_wm_region(C);
+ ED_region_tag_redraw(ar);
+ return OPERATOR_FINISHED;
+ }
#else
- (void)C; /* unused */
+ (void)C; /* unused */
#endif
- return OPERATOR_CANCELLED; /* FAIL */
+ return OPERATOR_CANCELLED; /* FAIL */
}
void SCRIPT_OT_python_file_run(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Run Python File";
- ot->description = "Run Python file";
- ot->idname = "SCRIPT_OT_python_file_run";
- ot->flag = OPTYPE_UNDO;
+ /* identifiers */
+ 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;
+ /* api callbacks */
+ ot->exec = run_pyfile_exec;
+ ot->poll = ED_operator_areaactive;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- RNA_def_string_file_path(ot->srna, "filepath", NULL, FILE_MAX, "Path", "");
+ RNA_def_string_file_path(ot->srna, "filepath", NULL, FILE_MAX, "Path", "");
}
#ifdef WITH_PYTHON
static bool script_test_modal_operators(bContext *C)
{
- wmWindowManager *wm;
- wmWindow *win;
-
- wm = CTX_wm_manager(C);
-
- for (win = wm->windows.first; win; win = win->next) {
- LISTBASE_FOREACH (wmEventHandler *, handler_base, &win->modalhandlers) {
- if (handler_base->type == WM_HANDLER_TYPE_OP) {
- wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base;
- if (handler->op != NULL) {
- wmOperatorType *ot = handler->op->type;
- if (ot->ext.srna) {
- return true;
- }
- }
- }
- }
- }
-
- return false;
+ wmWindowManager *wm;
+ wmWindow *win;
+
+ wm = CTX_wm_manager(C);
+
+ for (win = wm->windows.first; win; win = win->next) {
+ LISTBASE_FOREACH (wmEventHandler *, handler_base, &win->modalhandlers) {
+ if (handler_base->type == WM_HANDLER_TYPE_OP) {
+ wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base;
+ if (handler->op != NULL) {
+ wmOperatorType *ot = handler->op->type;
+ if (ot->ext.srna) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
}
#endif
@@ -110,32 +108,33 @@ static int script_reload_exec(bContext *C, wmOperator *op)
{
#ifdef WITH_PYTHON
- /* clear running operators */
- if (script_test_modal_operators(C)) {
- BKE_report(op->reports, RPT_ERROR, "Can't reload with running modal operators");
- return OPERATOR_CANCELLED;
- }
-
- /* TODO, this crashes on netrender and keying sets, need to look into why
- * disable for now unless running in debug mode */
- WM_cursor_wait(1);
- BPY_execute_string(C, (const char *[]){"bpy", NULL}, "bpy.utils.load_scripts(reload_scripts=True)");
- WM_cursor_wait(0);
- WM_event_add_notifier(C, NC_WINDOW, NULL);
- return OPERATOR_FINISHED;
+ /* clear running operators */
+ if (script_test_modal_operators(C)) {
+ BKE_report(op->reports, RPT_ERROR, "Can't reload with running modal operators");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* TODO, this crashes on netrender and keying sets, need to look into why
+ * disable for now unless running in debug mode */
+ WM_cursor_wait(1);
+ BPY_execute_string(
+ C, (const char *[]){"bpy", NULL}, "bpy.utils.load_scripts(reload_scripts=True)");
+ WM_cursor_wait(0);
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ return OPERATOR_FINISHED;
#else
- UNUSED_VARS(C, op);
- return OPERATOR_CANCELLED;
+ UNUSED_VARS(C, op);
+ return OPERATOR_CANCELLED;
#endif
}
void SCRIPT_OT_reload(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reload Scripts";
- ot->description = "Reload Scripts";
- ot->idname = "SCRIPT_OT_reload";
+ /* identifiers */
+ ot->name = "Reload Scripts";
+ ot->description = "Reload Scripts";
+ ot->idname = "SCRIPT_OT_reload";
- /* api callbacks */
- ot->exec = script_reload_exec;
+ /* api callbacks */
+ ot->exec = script_reload_exec;
}
diff --git a/source/blender/editors/space_script/script_ops.c b/source/blender/editors/space_script/script_ops.c
index 3f800117346..3101bf6a7a7 100644
--- a/source/blender/editors/space_script/script_ops.c
+++ b/source/blender/editors/space_script/script_ops.c
@@ -21,25 +21,22 @@
* \ingroup spscript
*/
-
#include <stdlib.h>
#include <math.h>
#include "WM_api.h"
-
#include "script_intern.h"
-
/* ************************** registration **********************************/
void script_operatortypes(void)
{
- WM_operatortype_append(SCRIPT_OT_python_file_run);
- WM_operatortype_append(SCRIPT_OT_reload);
+ WM_operatortype_append(SCRIPT_OT_python_file_run);
+ WM_operatortype_append(SCRIPT_OT_reload);
}
void script_keymap(wmKeyConfig *UNUSED(keyconf))
{
- /* Script space is deprecated, and doesn't need a keymap */
+ /* Script space is deprecated, and doesn't need a keymap */
}
diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c
index 45d6151e7b2..e26c0e3cec3 100644
--- a/source/blender/editors/space_script/space_script.c
+++ b/source/blender/editors/space_script/space_script.c
@@ -21,7 +21,6 @@
* \ingroup spscript
*/
-
#include <string.h>
#include <stdio.h>
@@ -36,7 +35,6 @@
#include "ED_space_api.h"
#include "ED_screen.h"
-
#include "WM_api.h"
#include "WM_types.h"
@@ -49,172 +47,167 @@
#include "script_intern.h" // own include
#include "GPU_framebuffer.h"
-
//static script_run_python(char *funcname, )
-
/* ******************** default callbacks for script space ***************** */
static SpaceLink *script_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
- SpaceScript *sscript;
-
- sscript = MEM_callocN(sizeof(SpaceScript), "initscript");
- sscript->spacetype = SPACE_SCRIPT;
+ ARegion *ar;
+ SpaceScript *sscript;
+ sscript = MEM_callocN(sizeof(SpaceScript), "initscript");
+ sscript->spacetype = SPACE_SCRIPT;
- /* header */
- ar = MEM_callocN(sizeof(ARegion), "header for script");
+ /* header */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_HEADER;
+ ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
- /* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for script");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for script");
- BLI_addtail(&sscript->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&sscript->regionbase, ar);
+ ar->regiontype = RGN_TYPE_WINDOW;
- /* channel list region XXX */
+ /* channel list region XXX */
-
- return (SpaceLink *)sscript;
+ return (SpaceLink *)sscript;
}
/* not spacelink itself */
static void script_free(SpaceLink *sl)
{
- SpaceScript *sscript = (SpaceScript *) sl;
+ SpaceScript *sscript = (SpaceScript *)sl;
#ifdef WITH_PYTHON
- /*free buttons references*/
- if (sscript->but_refs) {
-// XXX BPy_Set_DrawButtonsList(sscript->but_refs);
-// BPy_Free_DrawButtonsList();
- sscript->but_refs = NULL;
- }
+ /*free buttons references*/
+ if (sscript->but_refs) {
+ // XXX BPy_Set_DrawButtonsList(sscript->but_refs);
+ // BPy_Free_DrawButtonsList();
+ sscript->but_refs = NULL;
+ }
#endif
- sscript->script = NULL;
+ sscript->script = NULL;
}
-
/* spacetype; init callback */
static void script_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
{
-
}
static SpaceLink *script_duplicate(SpaceLink *sl)
{
- SpaceScript *sscriptn = MEM_dupallocN(sl);
+ SpaceScript *sscriptn = MEM_dupallocN(sl);
- /* clear or remove stuff from old */
+ /* clear or remove stuff from old */
- return (SpaceLink *)sscriptn;
+ return (SpaceLink *)sscriptn;
}
-
-
/* add handlers, stuff you only do once or on area/region changes */
static void script_main_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
- /* own keymap */
- keymap = WM_keymap_ensure(wm->defaultconf, "Script", SPACE_SCRIPT, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ /* own keymap */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Script", SPACE_SCRIPT, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
static void script_main_region_draw(const bContext *C, ARegion *ar)
{
- /* draw entirely, view changes should be handled here */
- SpaceScript *sscript = (SpaceScript *)CTX_wm_space_data(C);
- View2D *v2d = &ar->v2d;
+ /* draw entirely, view changes should be handled here */
+ SpaceScript *sscript = (SpaceScript *)CTX_wm_space_data(C);
+ View2D *v2d = &ar->v2d;
- /* clear and setup matrix */
- UI_ThemeClearColor(TH_BACK);
- GPU_clear(GPU_COLOR_BIT);
+ /* clear and setup matrix */
+ UI_ThemeClearColor(TH_BACK);
+ GPU_clear(GPU_COLOR_BIT);
- UI_view2d_view_ortho(v2d);
+ UI_view2d_view_ortho(v2d);
- /* data... */
- // BPY_script_exec(C, "/root/blender-svn/blender25/test.py", NULL);
+ /* data... */
+ // BPY_script_exec(C, "/root/blender-svn/blender25/test.py", NULL);
#ifdef WITH_PYTHON
- if (sscript->script) {
- // BPY_run_script_space_draw(C, sscript);
- }
+ if (sscript->script) {
+ // BPY_run_script_space_draw(C, sscript);
+ }
#else
- (void)sscript;
+ (void)sscript;
#endif
- /* reset view matrix */
- UI_view2d_view_restore(C);
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
- /* scrollers? */
+ /* scrollers? */
}
/* add handlers, stuff you only do once or on area/region changes */
static void script_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
- ED_region_header_init(ar);
+ ED_region_header_init(ar);
}
static void script_header_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_header(C, ar);
+ ED_region_header(C, ar);
}
-static void script_main_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *UNUSED(ar),
- wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene))
+static void script_main_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *UNUSED(ar),
+ wmNotifier *UNUSED(wmn),
+ const Scene *UNUSED(scene))
{
- /* context changes */
- // XXX - Todo, need the ScriptSpace accessible to get the python script to run.
- // BPY_run_script_space_listener()
+ /* context changes */
+ // XXX - Todo, need the ScriptSpace accessible to get the python script to run.
+ // BPY_run_script_space_listener()
}
/* only called once, from space/spacetypes.c */
void ED_spacetype_script(void)
{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype script");
- ARegionType *art;
-
- st->spaceid = SPACE_SCRIPT;
- strncpy(st->name, "Script", BKE_ST_MAXNAME);
-
- st->new = script_new;
- st->free = script_free;
- st->init = script_init;
- st->duplicate = script_duplicate;
- st->operatortypes = script_operatortypes;
- st->keymap = script_keymap;
-
- /* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype script region");
- art->regionid = RGN_TYPE_WINDOW;
- art->init = script_main_region_init;
- art->draw = script_main_region_draw;
- art->listener = script_main_region_listener;
- art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_UI | ED_KEYMAP_FRAMES; // XXX need to further test this ED_KEYMAP_UI is needed for button interaction
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype script region");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
-
- art->init = script_header_region_init;
- art->draw = script_header_region_draw;
-
- BLI_addhead(&st->regiontypes, art);
-
-
- BKE_spacetype_register(st);
+ SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype script");
+ ARegionType *art;
+
+ st->spaceid = SPACE_SCRIPT;
+ strncpy(st->name, "Script", BKE_ST_MAXNAME);
+
+ st->new = script_new;
+ st->free = script_free;
+ st->init = script_init;
+ st->duplicate = script_duplicate;
+ st->operatortypes = script_operatortypes;
+ st->keymap = script_keymap;
+
+ /* regions: main window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype script region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init = script_main_region_init;
+ art->draw = script_main_region_draw;
+ art->listener = script_main_region_listener;
+ art->keymapflag =
+ ED_KEYMAP_VIEW2D | ED_KEYMAP_UI |
+ ED_KEYMAP_FRAMES; // XXX need to further test this ED_KEYMAP_UI is needed for button interaction
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype script region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = HEADERY;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
+
+ art->init = script_header_region_init;
+ art->draw = script_header_region_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt
index 5724e811e77..8b97f7537f8 100644
--- a/source/blender/editors/space_sequencer/CMakeLists.txt
+++ b/source/blender/editors/space_sequencer/CMakeLists.txt
@@ -16,55 +16,55 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../imbuf
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/atomic
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../imbuf
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/atomic
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- sequencer_add.c
- sequencer_buttons.c
- sequencer_draw.c
- sequencer_edit.c
- sequencer_modifier.c
- sequencer_ops.c
- sequencer_preview.c
- sequencer_scopes.c
- sequencer_select.c
- sequencer_view.c
- space_sequencer.c
+ sequencer_add.c
+ sequencer_buttons.c
+ sequencer_draw.c
+ sequencer_edit.c
+ sequencer_modifier.c
+ sequencer_ops.c
+ sequencer_preview.c
+ sequencer_scopes.c
+ sequencer_select.c
+ sequencer_view.c
+ space_sequencer.c
- sequencer_intern.h
+ sequencer_intern.h
)
set(LIB
- bf_editor_interface
- bf_editor_util
+ bf_editor_interface
+ bf_editor_util
)
if(WITH_AUDASPACE)
- add_definitions(-DWITH_AUDASPACE)
+ add_definitions(-DWITH_AUDASPACE)
- list(APPEND INC_SYS
- ${AUDASPACE_C_INCLUDE_DIRS}
- )
+ list(APPEND INC_SYS
+ ${AUDASPACE_C_INCLUDE_DIRS}
+ )
endif()
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 5e36ad9e8bc..218804b0ab4 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -37,7 +37,6 @@
#include "DNA_scene_types.h"
#include "DNA_mask_types.h"
-
#include "BKE_context.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -69,201 +68,219 @@
#include "sequencer_intern.h"
typedef struct SequencerAddData {
- ImageFormatData im_format;
+ ImageFormatData im_format;
} SequencerAddData;
/* Generic functions, reused by add strip operators */
/* avoid passing multiple args and be more verbose */
-#define SEQPROP_STARTFRAME (1 << 0)
-#define SEQPROP_ENDFRAME (1 << 1)
-#define SEQPROP_NOPATHS (1 << 2)
-#define SEQPROP_NOCHAN (1 << 3)
+#define SEQPROP_STARTFRAME (1 << 0)
+#define SEQPROP_ENDFRAME (1 << 1)
+#define SEQPROP_NOPATHS (1 << 2)
+#define SEQPROP_NOCHAN (1 << 3)
#define SELECT 1
static void sequencer_generic_props__internal(wmOperatorType *ot, int flag)
{
- PropertyRNA *prop;
-
- if (flag & SEQPROP_STARTFRAME) {
- RNA_def_int(ot->srna, "frame_start", 0, INT_MIN, INT_MAX,
- "Start Frame", "Start frame of the sequence strip", INT_MIN, INT_MAX);
- }
-
- if (flag & SEQPROP_ENDFRAME) {
- /* not usual since most strips have a fixed length */
- RNA_def_int(ot->srna, "frame_end", 0, INT_MIN, INT_MAX,
- "End Frame", "End frame for the color strip", INT_MIN, INT_MAX);
- }
-
- RNA_def_int(ot->srna, "channel", 1, 1, MAXSEQ,
- "Channel", "Channel to place this strip into", 1, MAXSEQ);
-
- 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 */
- 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);
+ PropertyRNA *prop;
+
+ if (flag & SEQPROP_STARTFRAME) {
+ RNA_def_int(ot->srna,
+ "frame_start",
+ 0,
+ INT_MIN,
+ INT_MAX,
+ "Start Frame",
+ "Start frame of the sequence strip",
+ INT_MIN,
+ INT_MAX);
+ }
+
+ if (flag & SEQPROP_ENDFRAME) {
+ /* not usual since most strips have a fixed length */
+ RNA_def_int(ot->srna,
+ "frame_end",
+ 0,
+ INT_MIN,
+ INT_MAX,
+ "End Frame",
+ "End frame for the color strip",
+ INT_MIN,
+ INT_MAX);
+ }
+
+ RNA_def_int(
+ ot->srna, "channel", 1, 1, MAXSEQ, "Channel", "Channel to place this strip into", 1, MAXSEQ);
+
+ 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 */
+ 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);
}
-static void sequencer_generic_invoke_path__internal(bContext *C, wmOperator *op, const char *identifier)
+static void sequencer_generic_invoke_path__internal(bContext *C,
+ wmOperator *op,
+ const char *identifier)
{
- if (RNA_struct_find_property(op->ptr, identifier)) {
- Scene *scene = CTX_data_scene(C);
- Sequence *last_seq = BKE_sequencer_active_get(scene);
- if (last_seq && last_seq->strip && SEQ_HAS_PATH(last_seq)) {
- Main *bmain = CTX_data_main(C);
- char path[FILE_MAX];
- BLI_strncpy(path, last_seq->strip->dir, sizeof(path));
- BLI_path_abs(path, BKE_main_blendfile_path(bmain));
- RNA_string_set(op->ptr, identifier, path);
- }
- }
+ if (RNA_struct_find_property(op->ptr, identifier)) {
+ Scene *scene = CTX_data_scene(C);
+ Sequence *last_seq = BKE_sequencer_active_get(scene);
+ if (last_seq && last_seq->strip && SEQ_HAS_PATH(last_seq)) {
+ Main *bmain = CTX_data_main(C);
+ char path[FILE_MAX];
+ BLI_strncpy(path, last_seq->strip->dir, sizeof(path));
+ BLI_path_abs(path, BKE_main_blendfile_path(bmain));
+ RNA_string_set(op->ptr, identifier, path);
+ }
+ }
}
static int sequencer_generic_invoke_xy_guess_channel(bContext *C, int type)
{
- Sequence *tgt = NULL;
- Sequence *seq;
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, true);
- int cfra = (int) CFRA;
- int proximity = INT_MAX;
-
- if (!ed || !ed->seqbasep) {
- return 1;
- }
-
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if ((type == -1 || seq->type == type) &&
- (seq->enddisp < cfra) &&
- (cfra - seq->enddisp < proximity))
- {
- tgt = seq;
- proximity = cfra - seq->enddisp;
- }
- }
-
- if (tgt) {
- return tgt->machine;
- }
- return 1;
+ Sequence *tgt = NULL;
+ Sequence *seq;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, true);
+ int cfra = (int)CFRA;
+ int proximity = INT_MAX;
+
+ if (!ed || !ed->seqbasep) {
+ return 1;
+ }
+
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if ((type == -1 || seq->type == type) && (seq->enddisp < cfra) &&
+ (cfra - seq->enddisp < proximity)) {
+ tgt = seq;
+ proximity = cfra - seq->enddisp;
+ }
+ }
+
+ if (tgt) {
+ return tgt->machine;
+ }
+ return 1;
}
static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, int flag, int type)
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- int cfra = (int) CFRA;
+ int cfra = (int)CFRA;
- /* effect strips don't need a channel initialized from the mouse */
- if (!(flag & SEQPROP_NOCHAN)) {
- RNA_int_set(op->ptr, "channel", sequencer_generic_invoke_xy_guess_channel(C, type));
- }
+ /* effect strips don't need a channel initialized from the mouse */
+ if (!(flag & SEQPROP_NOCHAN)) {
+ RNA_int_set(op->ptr, "channel", sequencer_generic_invoke_xy_guess_channel(C, type));
+ }
- RNA_int_set(op->ptr, "frame_start", cfra);
+ RNA_int_set(op->ptr, "frame_start", cfra);
- if ((flag & SEQPROP_ENDFRAME) && RNA_struct_property_is_set(op->ptr, "frame_end") == 0) {
- RNA_int_set(op->ptr, "frame_end", cfra + 25); // XXX arbitrary but ok for now.
- }
+ if ((flag & SEQPROP_ENDFRAME) && RNA_struct_property_is_set(op->ptr, "frame_end") == 0) {
+ RNA_int_set(op->ptr, "frame_end", cfra + 25); // XXX arbitrary but ok for now.
+ }
- if (!(flag & SEQPROP_NOPATHS)) {
- sequencer_generic_invoke_path__internal(C, op, "filepath");
- sequencer_generic_invoke_path__internal(C, op, "directory");
- }
+ if (!(flag & SEQPROP_NOPATHS)) {
+ sequencer_generic_invoke_path__internal(C, op, "filepath");
+ sequencer_generic_invoke_path__internal(C, op, "directory");
+ }
}
static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
-
- PropertyRNA *prop;
- const bool relative = (prop = RNA_struct_find_property(op->ptr, "relative_path")) && RNA_property_boolean_get(op->ptr, prop);
- int is_file = -1;
- 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->channel = RNA_int_get(op->ptr, "channel");
- seq_load->len = 1; // images only, if endframe isn't set!
-
- if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) {
- /* 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 */
- RNA_property_string_get(op->ptr, prop, seq_load->path);
- is_file = 0;
- }
-
- if ((is_file != -1) && relative) {
- BLI_path_rel(seq_load->path, BKE_main_blendfile_path(bmain));
- }
-
-
- if ((prop = RNA_struct_find_property(op->ptr, "frame_end"))) {
- seq_load->end_frame = RNA_property_int_get(op->ptr, prop);
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "replace_sel")) && RNA_property_boolean_get(op->ptr, prop)) {
- seq_load->flag |= SEQ_LOAD_REPLACE_SEL;
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "cache")) && RNA_property_boolean_get(op->ptr, prop)) {
- seq_load->flag |= SEQ_LOAD_SOUND_CACHE;
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "mono")) && RNA_property_boolean_get(op->ptr, prop)) {
- seq_load->flag |= SEQ_LOAD_SOUND_MONO;
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "sound")) && RNA_property_boolean_get(op->ptr, prop)) {
- seq_load->flag |= SEQ_LOAD_MOVIE_SOUND;
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "use_framerate")) && RNA_property_boolean_get(op->ptr, prop)) {
- seq_load->flag |= SEQ_LOAD_SYNC_FPS;
- }
-
- /* always use this for ops */
- 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));
- MEM_freeN(name);
- break;
- }
- RNA_PROP_END;
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "use_multiview")) && RNA_property_boolean_get(op->ptr, prop)) {
- if (op->customdata) {
- SequencerAddData *sad = op->customdata;
- ImageFormatData *imf = &sad->im_format;
-
- 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;
- }
- }
+ Main *bmain = CTX_data_main(C);
+
+ PropertyRNA *prop;
+ const bool relative = (prop = RNA_struct_find_property(op->ptr, "relative_path")) &&
+ RNA_property_boolean_get(op->ptr, prop);
+ int is_file = -1;
+ 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->channel = RNA_int_get(op->ptr, "channel");
+ seq_load->len = 1; // images only, if endframe isn't set!
+
+ if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) {
+ /* 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 */
+ RNA_property_string_get(op->ptr, prop, seq_load->path);
+ is_file = 0;
+ }
+
+ if ((is_file != -1) && relative) {
+ BLI_path_rel(seq_load->path, BKE_main_blendfile_path(bmain));
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "frame_end"))) {
+ seq_load->end_frame = RNA_property_int_get(op->ptr, prop);
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "replace_sel")) &&
+ RNA_property_boolean_get(op->ptr, prop)) {
+ seq_load->flag |= SEQ_LOAD_REPLACE_SEL;
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "cache")) &&
+ RNA_property_boolean_get(op->ptr, prop)) {
+ seq_load->flag |= SEQ_LOAD_SOUND_CACHE;
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "mono")) &&
+ RNA_property_boolean_get(op->ptr, prop)) {
+ seq_load->flag |= SEQ_LOAD_SOUND_MONO;
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "sound")) &&
+ RNA_property_boolean_get(op->ptr, prop)) {
+ seq_load->flag |= SEQ_LOAD_MOVIE_SOUND;
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "use_framerate")) &&
+ RNA_property_boolean_get(op->ptr, prop)) {
+ seq_load->flag |= SEQ_LOAD_SYNC_FPS;
+ }
+
+ /* always use this for ops */
+ 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));
+ MEM_freeN(name);
+ break;
+ }
+ RNA_PROP_END;
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "use_multiview")) &&
+ RNA_property_boolean_get(op->ptr, prop)) {
+ if (op->customdata) {
+ SequencerAddData *sad = op->customdata;
+ ImageFormatData *imf = &sad->im_format;
+
+ 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;
+ }
+ }
}
/**
@@ -271,875 +288,909 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperato
*/
static void sequencer_add_apply_overlap(bContext *C, wmOperator *op, Sequence *seq)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
-
- if (RNA_boolean_get(op->ptr, "overlap") == false) {
- if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
- BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
- }
- }
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+
+ if (RNA_boolean_get(op->ptr, "overlap") == false) {
+ if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
+ BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
+ }
+ }
}
static void sequencer_add_apply_replace_sel(bContext *C, wmOperator *op, Sequence *seq)
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- if (RNA_boolean_get(op->ptr, "replace_sel")) {
- ED_sequencer_deselect_all(scene);
- BKE_sequencer_active_set(scene, seq);
- seq->flag |= SELECT;
- }
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ ED_sequencer_deselect_all(scene);
+ BKE_sequencer_active_set(scene, seq);
+ seq->flag |= SELECT;
+ }
}
/* add scene operator */
static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, true);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, true);
- Scene *sce_seq;
+ Scene *sce_seq;
- Sequence *seq; /* generic strip vars */
- Strip *strip;
+ Sequence *seq; /* generic strip vars */
+ Strip *strip;
- int start_frame, channel; /* operator props */
+ int start_frame, channel; /* operator props */
- start_frame = RNA_int_get(op->ptr, "frame_start");
- channel = RNA_int_get(op->ptr, "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(&CTX_data_main(C)->scenes, RNA_enum_get(op->ptr, "scene"));
- if (sce_seq == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Scene not found");
- return OPERATOR_CANCELLED;
- }
+ if (sce_seq == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Scene not found");
+ return OPERATOR_CANCELLED;
+ }
- seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel);
- seq->type = SEQ_TYPE_SCENE;
- seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
+ seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel);
+ seq->type = SEQ_TYPE_SCENE;
+ seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
- seq->scene = sce_seq;
+ seq->scene = sce_seq;
- /* basic defaults */
- seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
- seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1;
- strip->us = 1;
+ /* basic defaults */
+ seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
+ seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1;
+ strip->us = 1;
- BLI_strncpy(seq->name + 2, sce_seq->id.name + 2, sizeof(seq->name) - 2);
- BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
+ BLI_strncpy(seq->name + 2, sce_seq->id.name + 2, sizeof(seq->name) - 2);
+ BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
- seq->scene_sound = BKE_sound_scene_add_scene_sound(scene, seq, start_frame, start_frame + seq->len, 0);
+ seq->scene_sound = BKE_sound_scene_add_scene_sound(
+ scene, seq, start_frame, start_frame + seq->len, 0);
- BKE_sequence_calc_disp(scene, seq);
- BKE_sequencer_sort(scene);
+ BKE_sequence_calc_disp(scene, seq);
+ BKE_sequencer_sort(scene);
- sequencer_add_apply_replace_sel(C, op, seq);
- sequencer_add_apply_overlap(C, op, seq);
+ sequencer_add_apply_replace_sel(C, op, seq);
+ sequencer_add_apply_overlap(C, op, seq);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
static int sequencer_add_scene_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (!RNA_struct_property_is_set(op->ptr, "scene")) {
- return WM_enum_search_invoke(C, op, event);
- }
-
- 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);
+ if (!RNA_struct_property_is_set(op->ptr, "scene")) {
+ return WM_enum_search_invoke(C, op, event);
+ }
+
+ 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;
+ PropertyRNA *prop;
- /* 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";
+ /* 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 */
- ot->invoke = sequencer_add_scene_strip_invoke;
- ot->exec = sequencer_add_scene_strip_exec;
+ /* api callbacks */
+ ot->invoke = sequencer_add_scene_strip_invoke;
+ ot->exec = sequencer_add_scene_strip_exec;
- ot->poll = ED_operator_sequencer_active_editable;
+ ot->poll = ED_operator_sequencer_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
- prop = RNA_def_enum(ot->srna, "scene", DummyRNA_NULL_items, 0, "Scene", "");
- RNA_def_enum_funcs(prop, RNA_scene_without_active_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
+ prop = RNA_def_enum(ot->srna, "scene", DummyRNA_NULL_items, 0, "Scene", "");
+ RNA_def_enum_funcs(prop, RNA_scene_without_active_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
/* add movieclip operator */
static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, true);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, true);
- MovieClip *clip;
+ MovieClip *clip;
- Sequence *seq; /* generic strip vars */
- Strip *strip;
+ Sequence *seq; /* generic strip vars */
+ Strip *strip;
- int start_frame, channel; /* operator props */
+ int start_frame, channel; /* operator props */
- start_frame = RNA_int_get(op->ptr, "frame_start");
- channel = RNA_int_get(op->ptr, "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(&CTX_data_main(C)->movieclips, RNA_enum_get(op->ptr, "clip"));
- if (clip == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Movie clip not found");
- return OPERATOR_CANCELLED;
- }
+ if (clip == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Movie clip not found");
+ return OPERATOR_CANCELLED;
+ }
- seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel);
- seq->type = SEQ_TYPE_MOVIECLIP;
- seq->blend_mode = SEQ_TYPE_CROSS;
- seq->clip = clip;
+ seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel);
+ seq->type = SEQ_TYPE_MOVIECLIP;
+ seq->blend_mode = SEQ_TYPE_CROSS;
+ seq->clip = clip;
- id_us_ensure_real(&seq->clip->id);
+ id_us_ensure_real(&seq->clip->id);
- /* basic defaults */
- seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
- seq->len = BKE_movieclip_get_duration(clip);
- strip->us = 1;
+ /* basic defaults */
+ seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
+ seq->len = BKE_movieclip_get_duration(clip);
+ strip->us = 1;
- BLI_strncpy(seq->name + 2, clip->id.name + 2, sizeof(seq->name) - 2);
- BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
+ BLI_strncpy(seq->name + 2, clip->id.name + 2, sizeof(seq->name) - 2);
+ BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
- BKE_sequence_calc_disp(scene, seq);
- BKE_sequencer_sort(scene);
+ BKE_sequence_calc_disp(scene, seq);
+ BKE_sequencer_sort(scene);
- sequencer_add_apply_replace_sel(C, op, seq);
- sequencer_add_apply_overlap(C, op, seq);
+ sequencer_add_apply_replace_sel(C, op, seq);
+ sequencer_add_apply_overlap(C, op, seq);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int sequencer_add_movieclip_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (!RNA_struct_property_is_set(op->ptr, "clip")) {
- return WM_enum_search_invoke(C, op, event);
- }
-
- 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);
+ if (!RNA_struct_property_is_set(op->ptr, "clip")) {
+ return WM_enum_search_invoke(C, op, event);
+ }
+
+ 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;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Add MovieClip Strip";
- ot->idname = "SEQUENCER_OT_movieclip_strip_add";
- ot->description = "Add a movieclip strip to the sequencer";
+ /* identifiers */
+ ot->name = "Add MovieClip Strip";
+ ot->idname = "SEQUENCER_OT_movieclip_strip_add";
+ ot->description = "Add a movieclip strip to the sequencer";
- /* api callbacks */
- ot->invoke = sequencer_add_movieclip_strip_invoke;
- ot->exec = sequencer_add_movieclip_strip_exec;
+ /* api callbacks */
+ ot->invoke = sequencer_add_movieclip_strip_invoke;
+ ot->exec = sequencer_add_movieclip_strip_exec;
- ot->poll = ED_operator_sequencer_active_editable;
+ ot->poll = ED_operator_sequencer_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
- prop = RNA_def_enum(ot->srna, "clip", DummyRNA_NULL_items, 0, "Clip", "");
- RNA_def_enum_funcs(prop, RNA_movieclip_itemf);
- RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MOVIECLIP);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
+ prop = RNA_def_enum(ot->srna, "clip", DummyRNA_NULL_items, 0, "Clip", "");
+ RNA_def_enum_funcs(prop, RNA_movieclip_itemf);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MOVIECLIP);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, true);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, true);
- Mask *mask;
+ Mask *mask;
- Sequence *seq; /* generic strip vars */
- Strip *strip;
+ Sequence *seq; /* generic strip vars */
+ Strip *strip;
- int start_frame, channel; /* operator props */
+ int start_frame, channel; /* operator props */
- start_frame = RNA_int_get(op->ptr, "frame_start");
- channel = RNA_int_get(op->ptr, "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(&CTX_data_main(C)->masks, RNA_enum_get(op->ptr, "mask"));
- if (mask == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Mask not found");
- return OPERATOR_CANCELLED;
- }
+ if (mask == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Mask not found");
+ return OPERATOR_CANCELLED;
+ }
- seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel);
- seq->type = SEQ_TYPE_MASK;
- seq->blend_mode = SEQ_TYPE_CROSS;
- seq->mask = mask;
+ seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel);
+ seq->type = SEQ_TYPE_MASK;
+ seq->blend_mode = SEQ_TYPE_CROSS;
+ seq->mask = mask;
- id_us_ensure_real(&seq->mask->id);
+ id_us_ensure_real(&seq->mask->id);
- /* basic defaults */
- seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
- seq->len = BKE_mask_get_duration(mask);
- strip->us = 1;
+ /* basic defaults */
+ seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
+ seq->len = BKE_mask_get_duration(mask);
+ strip->us = 1;
- BLI_strncpy(seq->name + 2, mask->id.name + 2, sizeof(seq->name) - 2);
- BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
+ BLI_strncpy(seq->name + 2, mask->id.name + 2, sizeof(seq->name) - 2);
+ BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
- BKE_sequence_calc_disp(scene, seq);
- BKE_sequencer_sort(scene);
+ BKE_sequence_calc_disp(scene, seq);
+ BKE_sequencer_sort(scene);
- sequencer_add_apply_replace_sel(C, op, seq);
- sequencer_add_apply_overlap(C, op, seq);
+ sequencer_add_apply_replace_sel(C, op, seq);
+ sequencer_add_apply_overlap(C, op, seq);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int sequencer_add_mask_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (!RNA_struct_property_is_set(op->ptr, "mask")) {
- return WM_enum_search_invoke(C, op, event);
- }
-
- 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);
+ if (!RNA_struct_property_is_set(op->ptr, "mask")) {
+ return WM_enum_search_invoke(C, op, event);
+ }
+
+ 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;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Add Mask Strip";
- ot->idname = "SEQUENCER_OT_mask_strip_add";
- ot->description = "Add a mask strip to the sequencer";
+ /* identifiers */
+ ot->name = "Add Mask Strip";
+ ot->idname = "SEQUENCER_OT_mask_strip_add";
+ ot->description = "Add a mask strip to the sequencer";
- /* api callbacks */
- ot->invoke = sequencer_add_mask_strip_invoke;
- ot->exec = sequencer_add_mask_strip_exec;
+ /* api callbacks */
+ ot->invoke = sequencer_add_mask_strip_invoke;
+ ot->exec = sequencer_add_mask_strip_exec;
- ot->poll = ED_operator_sequencer_active_editable;
+ ot->poll = ED_operator_sequencer_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
- prop = RNA_def_enum(ot->srna, "mask", DummyRNA_NULL_items, 0, "Mask", "");
- RNA_def_enum_funcs(prop, RNA_mask_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
+ prop = RNA_def_enum(ot->srna, "mask", DummyRNA_NULL_items, 0, "Mask", "");
+ RNA_def_enum_funcs(prop, RNA_mask_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
-
static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoadFunc seq_load_func)
{
- Scene *scene = CTX_data_scene(C); /* only for sound */
- Editing *ed = BKE_sequencer_editing_get(scene, true);
- SeqLoadInfo seq_load;
- int tot_files;
-
- seq_load_operator_info(&seq_load, C, op);
-
- if (seq_load.flag & SEQ_LOAD_REPLACE_SEL) {
- ED_sequencer_deselect_all(scene);
- }
-
- if (RNA_struct_property_is_set(op->ptr, "files")) {
- tot_files = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
- }
- else {
- tot_files = 0;
- }
-
- if (tot_files) {
- /* multiple files */
- char dir_only[FILE_MAX];
- char file_only[FILE_MAX];
-
- BLI_split_dir_part(seq_load.path, dir_only, sizeof(dir_only));
-
- RNA_BEGIN (op->ptr, itemptr, "files")
- {
- Sequence *seq;
-
- 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! */
- BLI_strncpy(seq_load.name, file_only, sizeof(seq_load.name));
-
- seq = seq_load_func(C, ed->seqbasep, &seq_load);
- if (seq) {
- sequencer_add_apply_overlap(C, op, seq);
- if (seq_load.seq_sound) {
- sequencer_add_apply_overlap(C, op, seq_load.seq_sound);
- }
- }
- }
- RNA_END;
- }
- else {
- Sequence *seq;
-
- /* 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) {
- sequencer_add_apply_overlap(C, op, seq_load.seq_sound);
- }
- }
- }
-
- if (seq_load.tot_success == 0) {
- BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", seq_load.path);
- return OPERATOR_CANCELLED;
- }
-
- if (op->customdata) {
- MEM_freeN(op->customdata);
- }
-
- BKE_sequencer_sort(scene);
- BKE_sequencer_update_muting(ed);
-
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C); /* only for sound */
+ Editing *ed = BKE_sequencer_editing_get(scene, true);
+ SeqLoadInfo seq_load;
+ int tot_files;
+
+ seq_load_operator_info(&seq_load, C, op);
+
+ if (seq_load.flag & SEQ_LOAD_REPLACE_SEL) {
+ ED_sequencer_deselect_all(scene);
+ }
+
+ if (RNA_struct_property_is_set(op->ptr, "files")) {
+ tot_files = RNA_property_collection_length(op->ptr,
+ RNA_struct_find_property(op->ptr, "files"));
+ }
+ else {
+ tot_files = 0;
+ }
+
+ if (tot_files) {
+ /* multiple files */
+ char dir_only[FILE_MAX];
+ char file_only[FILE_MAX];
+
+ BLI_split_dir_part(seq_load.path, dir_only, sizeof(dir_only));
+
+ RNA_BEGIN (op->ptr, itemptr, "files") {
+ Sequence *seq;
+
+ 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! */
+ BLI_strncpy(seq_load.name, file_only, sizeof(seq_load.name));
+
+ seq = seq_load_func(C, ed->seqbasep, &seq_load);
+ if (seq) {
+ sequencer_add_apply_overlap(C, op, seq);
+ if (seq_load.seq_sound) {
+ sequencer_add_apply_overlap(C, op, seq_load.seq_sound);
+ }
+ }
+ }
+ RNA_END;
+ }
+ else {
+ Sequence *seq;
+
+ /* 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) {
+ sequencer_add_apply_overlap(C, op, seq_load.seq_sound);
+ }
+ }
+ }
+
+ if (seq_load.tot_success == 0) {
+ BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", seq_load.path);
+ return OPERATOR_CANCELLED;
+ }
+
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ }
+
+ BKE_sequencer_sort(scene);
+ BKE_sequencer_update_muting(ed);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
}
/* add sequencer operators */
static void sequencer_add_init(bContext *UNUSED(C), wmOperator *op)
{
- op->customdata = MEM_callocN(sizeof(SequencerAddData), __func__);
+ op->customdata = MEM_callocN(sizeof(SequencerAddData), __func__);
}
static void sequencer_add_cancel(bContext *UNUSED(C), wmOperator *op)
{
- if (op->customdata) {
- MEM_freeN(op->customdata);
- }
- op->customdata = NULL;
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ }
+ 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_prop(PointerRNA *UNUSED(ptr),
+ PropertyRNA *prop,
+ void *UNUSED(user_data))
{
- const char *prop_id = RNA_property_identifier(prop);
+ const char *prop_id = RNA_property_identifier(prop);
- return !(STREQ(prop_id, "filepath") ||
- STREQ(prop_id, "directory") ||
- STREQ(prop_id, "filename")
- );
+ return !(STREQ(prop_id, "filepath") || STREQ(prop_id, "directory") ||
+ 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);
+ return sequencer_add_generic_strip_exec(C, op, BKE_sequencer_add_movie_strip);
}
-static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int sequencer_add_movie_strip_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
{
- PropertyRNA *prop;
- 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
- */
- if (ed && ed->seqbasep && ed->seqbasep->first) {
- RNA_boolean_set(op->ptr, "use_framerate", false);
- }
-
- /* 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);
- return sequencer_add_movie_strip_exec(C, op);
- }
-
- 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 */
- 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);
+ PropertyRNA *prop;
+ 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
+ */
+ if (ed && ed->seqbasep && ed->seqbasep->first) {
+ RNA_boolean_set(op->ptr, "use_framerate", false);
+ }
+
+ /* 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);
+ return sequencer_add_movie_strip_exec(C, op);
+ }
+
+ 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 */
+ 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)
{
- uiLayout *layout = op->layout;
- SequencerAddData *sad = op->customdata;
- ImageFormatData *imf = &sad->im_format;
- PointerRNA imf_ptr, ptr;
-
- /* 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);
-
- /* image template */
- RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr);
-
- /* multiview template */
- if (RNA_boolean_get(op->ptr, "show_multiview")) {
- uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr);
- }
+ uiLayout *layout = op->layout;
+ SequencerAddData *sad = op->customdata;
+ ImageFormatData *imf = &sad->im_format;
+ PointerRNA imf_ptr, ptr;
+
+ /* 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);
+
+ /* image template */
+ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr);
+
+ /* multiview template */
+ if (RNA_boolean_get(op->ptr, "show_multiview")) {
+ uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr);
+ }
}
void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Movie Strip";
- ot->idname = "SEQUENCER_OT_movie_strip_add";
- ot->description = "Add a movie strip to the sequencer";
-
- /* 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 */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
- sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
- RNA_def_boolean(ot->srna, "sound", true, "Sound", "Load sound with the movie");
- RNA_def_boolean(ot->srna, "use_framerate", true, "Use Movie Framerate", "Use framerate from the movie to keep sound and video in sync");
+ /* identifiers */
+ ot->name = "Add Movie Strip";
+ ot->idname = "SEQUENCER_OT_movie_strip_add";
+ ot->description = "Add a movie strip to the sequencer";
+
+ /* 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 */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_MOVIE,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_FILES,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
+ RNA_def_boolean(ot->srna, "sound", true, "Sound", "Load sound with the movie");
+ RNA_def_boolean(ot->srna,
+ "use_framerate",
+ true,
+ "Use Movie Framerate",
+ "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);
+ return sequencer_add_generic_strip_exec(C, op, BKE_sequencer_add_sound_strip);
}
-static int sequencer_add_sound_strip_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int sequencer_add_sound_strip_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
{
- /* 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);
- return sequencer_add_sound_strip_exec(C, op);
- }
+ /* 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);
+ return sequencer_add_sound_strip_exec(C, op);
+ }
- sequencer_generic_invoke_xy__internal(C, op, 0, SEQ_TYPE_SOUND_RAM);
+ sequencer_generic_invoke_xy__internal(C, op, 0, SEQ_TYPE_SOUND_RAM);
- WM_event_add_fileselect(C, op);
- return OPERATOR_RUNNING_MODAL;
+ WM_event_add_fileselect(C, op);
+ return OPERATOR_RUNNING_MODAL;
- //return sequencer_add_sound_strip_exec(C, op);
+ //return sequencer_add_sound_strip_exec(C, op);
}
-
void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Sound Strip";
- ot->idname = "SEQUENCER_OT_sound_strip_add";
- ot->description = "Add a sound strip to the sequencer";
-
- /* api callbacks */
- ot->invoke = sequencer_add_sound_strip_invoke;
- ot->exec = sequencer_add_sound_strip_exec;
-
- ot->poll = ED_operator_sequencer_active_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_SOUND, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
- sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
- RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
- RNA_def_boolean(ot->srna, "mono", false, "Mono", "Merge all the sound's channels into one");
+ /* identifiers */
+ ot->name = "Add Sound Strip";
+ ot->idname = "SEQUENCER_OT_sound_strip_add";
+ ot->description = "Add a sound strip to the sequencer";
+
+ /* api callbacks */
+ ot->invoke = sequencer_add_sound_strip_invoke;
+ ot->exec = sequencer_add_sound_strip_exec;
+
+ ot->poll = ED_operator_sequencer_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_SOUND,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_FILES,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
+ RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
+ RNA_def_boolean(ot->srna, "mono", false, "Mono", "Merge all the sound's channels into one");
}
-int sequencer_image_seq_get_minmax_frame(wmOperator *op, int sfra, int *r_minframe, int *r_numdigits)
+int sequencer_image_seq_get_minmax_frame(wmOperator *op,
+ int sfra,
+ int *r_minframe,
+ int *r_numdigits)
{
- int minframe = INT32_MAX, maxframe = INT32_MIN;
- int numdigits = 0;
-
- 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) {
- if (BLI_path_frame_get(filename, &frame, &numdigits)) {
- minframe = min_ii(minframe, frame);
- maxframe = max_ii(maxframe, frame);
- }
-
- MEM_freeN(filename);
- }
- }
- RNA_END;
-
- if (minframe == INT32_MAX) {
- minframe = sfra;
- maxframe = minframe + 1;
- }
-
- *r_minframe = minframe;
- *r_numdigits = numdigits;
-
- return maxframe - minframe + 1;
+ int minframe = INT32_MAX, maxframe = INT32_MIN;
+ int numdigits = 0;
+
+ 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) {
+ if (BLI_path_frame_get(filename, &frame, &numdigits)) {
+ minframe = min_ii(minframe, frame);
+ maxframe = max_ii(maxframe, frame);
+ }
+
+ MEM_freeN(filename);
+ }
+ }
+ RNA_END;
+
+ if (minframe == INT32_MAX) {
+ minframe = sfra;
+ maxframe = minframe + 1;
+ }
+
+ *r_minframe = minframe;
+ *r_numdigits = numdigits;
+
+ return maxframe - minframe + 1;
}
-void sequencer_image_seq_reserve_frames(wmOperator *op, StripElem *se, int len, int minframe, int numdigits)
+void sequencer_image_seq_reserve_frames(
+ wmOperator *op, StripElem *se, int len, int minframe, int numdigits)
{
- 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;
- }
- RNA_END;
-
- if (filename) {
- char ext[PATH_MAX];
- char filename_stripped[PATH_MAX];
- /* strip the frame from filename and substitute with # */
- BLI_path_frame_strip(filename, ext);
-
- for (i = 0; i < len; i++, se++) {
- BLI_strncpy(filename_stripped, filename, sizeof(filename_stripped));
- BLI_path_frame(filename_stripped, minframe + i, numdigits);
- BLI_snprintf(se->name, sizeof(se->name), "%s%s", filename_stripped, ext);
- }
-
- MEM_freeN(filename);
- }
+ 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;
+ }
+ RNA_END;
+
+ if (filename) {
+ char ext[PATH_MAX];
+ char filename_stripped[PATH_MAX];
+ /* strip the frame from filename and substitute with # */
+ BLI_path_frame_strip(filename, ext);
+
+ for (i = 0; i < len; i++, se++) {
+ BLI_strncpy(filename_stripped, filename, sizeof(filename_stripped));
+ BLI_path_frame(filename_stripped, minframe + i, numdigits);
+ BLI_snprintf(se->name, sizeof(se->name), "%s%s", filename_stripped, ext);
+ }
+
+ MEM_freeN(filename);
+ }
}
-
/* 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 */
- 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 */
- if (use_placeholders) {
- seq_load.len = sequencer_image_seq_get_minmax_frame(op, seq_load.start_frame, &minframe, &numdigits);
- }
- else {
- seq_load.len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
- }
-
- if (seq_load.len == 0) {
- return OPERATOR_CANCELLED;
- }
-
- if (seq_load.flag & SEQ_LOAD_REPLACE_SEL) {
- ED_sequencer_deselect_all(scene);
- }
-
- /* 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) {
- sequencer_image_seq_reserve_frames(op, se, seq_load.len, minframe, numdigits);
- }
- else {
- RNA_BEGIN (op->ptr, itemptr, "files")
- {
- char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
- BLI_strncpy(se->name, filename, sizeof(se->name));
- MEM_freeN(filename);
- se++;
- }
- RNA_END;
- }
-
- if (seq_load.len == 1) {
- if (seq_load.start_frame < seq_load.end_frame) {
- seq->endstill = seq_load.end_frame - seq_load.start_frame;
- }
- }
-
- BKE_sequence_init_colorspace(seq);
-
- BKE_sequence_calc_disp(scene, seq);
-
- BKE_sequencer_sort(scene);
-
- /* 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);
- }
-
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
- return OPERATOR_FINISHED;
+ int minframe, numdigits;
+ /* cant use the generic function for this */
+ Scene *scene = CTX_data_scene(C); /* only for sound */
+ 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 */
+ if (use_placeholders) {
+ seq_load.len = sequencer_image_seq_get_minmax_frame(
+ op, seq_load.start_frame, &minframe, &numdigits);
+ }
+ else {
+ seq_load.len = RNA_property_collection_length(op->ptr,
+ RNA_struct_find_property(op->ptr, "files"));
+ }
+
+ if (seq_load.len == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (seq_load.flag & SEQ_LOAD_REPLACE_SEL) {
+ ED_sequencer_deselect_all(scene);
+ }
+
+ /* 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) {
+ sequencer_image_seq_reserve_frames(op, se, seq_load.len, minframe, numdigits);
+ }
+ else {
+ RNA_BEGIN (op->ptr, itemptr, "files") {
+ char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+ BLI_strncpy(se->name, filename, sizeof(se->name));
+ MEM_freeN(filename);
+ se++;
+ }
+ RNA_END;
+ }
+
+ if (seq_load.len == 1) {
+ if (seq_load.start_frame < seq_load.end_frame) {
+ seq->endstill = seq_load.end_frame - seq_load.start_frame;
+ }
+ }
+
+ BKE_sequence_init_colorspace(seq);
+
+ BKE_sequence_calc_disp(scene, seq);
+
+ BKE_sequencer_sort(scene);
+
+ /* 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);
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
}
-static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int sequencer_add_image_strip_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
{
- PropertyRNA *prop;
- Scene *scene = CTX_data_scene(C);
+ PropertyRNA *prop;
+ Scene *scene = CTX_data_scene(C);
- /* drag drop has set the names */
- 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);
- return sequencer_add_image_strip_exec(C, op);
- }
+ /* drag drop has set the names */
+ 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);
+ return sequencer_add_image_strip_exec(C, op);
+ }
- sequencer_generic_invoke_xy__internal(C, op, SEQPROP_ENDFRAME, SEQ_TYPE_IMAGE);
+ sequencer_generic_invoke_xy__internal(C, op, SEQPROP_ENDFRAME, SEQ_TYPE_IMAGE);
- sequencer_add_init(C, op);
+ sequencer_add_init(C, op);
- /* show multiview save options only if scene has multiviews */
- prop = RNA_struct_find_property(op->ptr, "show_multiview");
- RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0);
+ /* show multiview save options only if scene has multiviews */
+ 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;
+ WM_event_add_fileselect(C, op);
+ return OPERATOR_RUNNING_MODAL;
}
-
void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot)
{
- /* 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 */
- 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 */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
- sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME);
-
- RNA_def_boolean(ot->srna, "use_placeholders", false, "Use Placeholders", "Use placeholders for missing frames of the strip");
+ /* 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 */
+ 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 */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_IMAGE,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILES,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME);
+
+ RNA_def_boolean(ot->srna,
+ "use_placeholders",
+ false,
+ "Use Placeholders",
+ "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 */
- Strip *strip;
- struct SeqEffectHandle sh;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, true);
- int start_frame, end_frame, channel, type; /* operator props */
+ Sequence *seq; /* generic strip vars */
+ Strip *strip;
+ struct SeqEffectHandle sh;
- Sequence *seq1, *seq2, *seq3;
- const char *error_msg;
+ int start_frame, end_frame, channel, type; /* operator props */
- 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");
+ Sequence *seq1, *seq2, *seq3;
+ const char *error_msg;
- type = RNA_enum_get(op->ptr, "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");
- // 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;
- }
+ type = RNA_enum_get(op->ptr, "type");
- /* 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 */
- if (seq1 == NULL && end_frame <= start_frame) {
- BKE_report(op->reports, RPT_ERROR, "Start and end frame are not set");
- return OPERATOR_CANCELLED;
- }
+ // 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;
+ }
- seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel);
- seq->type = type;
+ /* 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 */
+ if (seq1 == NULL && end_frame <= start_frame) {
+ BKE_report(op->reports, RPT_ERROR, "Start and end frame are not set");
+ return OPERATOR_CANCELLED;
+ }
- BLI_strncpy(seq->name + 2, BKE_sequence_give_name(seq), sizeof(seq->name) - 2);
- BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
+ seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel);
+ seq->type = type;
- sh = BKE_sequence_get_effect(seq);
+ BLI_strncpy(seq->name + 2, BKE_sequence_give_name(seq), sizeof(seq->name) - 2);
+ BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
- seq->seq1 = seq1;
- seq->seq2 = seq2;
- seq->seq3 = seq3;
+ sh = BKE_sequence_get_effect(seq);
- sh.init(seq);
+ seq->seq1 = seq1;
+ seq->seq2 = seq2;
+ seq->seq3 = seq3;
- if (!seq1) { /* effect has no deps */
- seq->len = 1;
- BKE_sequence_tx_set_final_right(seq, end_frame);
- }
+ sh.init(seq);
- seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
+ if (!seq1) { /* effect has no deps */
+ seq->len = 1;
+ BKE_sequence_tx_set_final_right(seq, end_frame);
+ }
- BKE_sequence_calc(scene, seq);
+ seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
- /* basic defaults */
- seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
- strip->us = 1;
+ 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 */
+ /* basic defaults */
+ seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
+ strip->us = 1;
- }
- else if (seq->type == SEQ_TYPE_ADJUSTMENT) {
- seq->blend_mode = SEQ_TYPE_CROSS;
- }
- else if (seq->type == SEQ_TYPE_TEXT) {
- seq->blend_mode = SEQ_TYPE_ALPHAOVER;
- }
+ 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 */
+ }
+ else if (seq->type == SEQ_TYPE_ADJUSTMENT) {
+ seq->blend_mode = SEQ_TYPE_CROSS;
+ }
+ else if (seq->type == SEQ_TYPE_TEXT) {
+ seq->blend_mode = SEQ_TYPE_ALPHAOVER;
+ }
- /* an unset channel is a special case where we automatically go above
- * the other strips. */
- if (!RNA_struct_property_is_set(op->ptr, "channel")) {
- if (seq->seq1) {
- int chan = max_iii(seq->seq1 ? seq->seq1->machine : 0,
- seq->seq2 ? seq->seq2->machine : 0,
- seq->seq3 ? seq->seq3->machine : 0);
- if (chan < MAXSEQ) {
- seq->machine = chan;
- }
- }
- }
+ /* an unset channel is a special case where we automatically go above
+ * the other strips. */
+ if (!RNA_struct_property_is_set(op->ptr, "channel")) {
+ if (seq->seq1) {
+ int chan = max_iii(seq->seq1 ? seq->seq1->machine : 0,
+ seq->seq2 ? seq->seq2->machine : 0,
+ seq->seq3 ? seq->seq3->machine : 0);
+ if (chan < MAXSEQ) {
+ seq->machine = chan;
+ }
+ }
+ }
- sequencer_add_apply_replace_sel(C, op, seq);
- sequencer_add_apply_overlap(C, op, seq);
+ 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 */
+ 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_sort(scene);
- /* 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_sort(scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
/* add color */
-static int sequencer_add_effect_strip_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int sequencer_add_effect_strip_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
{
- bool is_type_set = RNA_struct_property_is_set(op->ptr, "type");
- int type = -1;
- int prop_flag = SEQPROP_ENDFRAME | SEQPROP_NOPATHS;
+ bool is_type_set = RNA_struct_property_is_set(op->ptr, "type");
+ int type = -1;
+ int prop_flag = SEQPROP_ENDFRAME | SEQPROP_NOPATHS;
- if (is_type_set) {
- type = RNA_enum_get(op->ptr, "type");
+ 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. */
- if (BKE_sequence_effect_get_num_inputs(type) != 0) {
- prop_flag |= SEQPROP_NOCHAN;
- }
- }
+ /* 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. */
+ if (BKE_sequence_effect_get_num_inputs(type) != 0) {
+ prop_flag |= SEQPROP_NOCHAN;
+ }
+ }
- sequencer_generic_invoke_xy__internal(C, op, prop_flag, type);
+ sequencer_generic_invoke_xy__internal(C, op, prop_flag, type);
- return sequencer_add_effect_strip_exec(C, op);
+ return sequencer_add_effect_strip_exec(C, op);
}
void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot)
{
- /* 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 */
- ot->invoke = sequencer_add_effect_strip_invoke;
- ot->exec = sequencer_add_effect_strip_exec;
-
- ot->poll = ED_operator_sequencer_active_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME);
- RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_TYPE_CROSS, "Type", "Sequencer effect type");
- RNA_def_float_vector(ot->srna, "color", 3, NULL, 0.0f, 1.0f, "Color",
- "Initialize the strip with this color (only used when type='COLOR')", 0.0f, 1.0f);
+ /* 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 */
+ ot->invoke = sequencer_add_effect_strip_invoke;
+ ot->exec = sequencer_add_effect_strip_exec;
+
+ ot->poll = ED_operator_sequencer_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME);
+ RNA_def_enum(ot->srna,
+ "type",
+ sequencer_prop_effect_types,
+ SEQ_TYPE_CROSS,
+ "Type",
+ "Sequencer effect type");
+ RNA_def_float_vector(ot->srna,
+ "color",
+ 3,
+ NULL,
+ 0.0f,
+ 1.0f,
+ "Color",
+ "Initialize the strip with this color (only used when type='COLOR')",
+ 0.0f,
+ 1.0f);
}
diff --git a/source/blender/editors/space_sequencer/sequencer_buttons.c b/source/blender/editors/space_sequencer/sequencer_buttons.c
index 7b7f6599404..8d9fea2cb98 100644
--- a/source/blender/editors/space_sequencer/sequencer_buttons.c
+++ b/source/blender/editors/space_sequencer/sequencer_buttons.c
@@ -24,7 +24,6 @@
#include <string.h>
#include <stdio.h>
-
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
@@ -53,101 +52,97 @@
#if 0
static bool sequencer_grease_pencil_panel_poll(const bContext *C, PanelType *UNUSED(pt))
{
- SpaceSeq *sseq = CTX_wm_space_seq(C);
+ SpaceSeq *sseq = CTX_wm_space_seq(C);
- /* don't show the gpencil if we are not showing the image */
- return ED_space_sequencer_check_show_imbuf(sseq);
+ /* don't show the gpencil if we are not showing the image */
+ return ED_space_sequencer_check_show_imbuf(sseq);
}
#endif
static bool metadata_panel_context_poll(const bContext *C, PanelType *UNUSED(pt))
{
- SpaceSeq *space_sequencer = CTX_wm_space_seq(C);
- if (space_sequencer == NULL) {
- return false;
- }
- return ED_space_sequencer_check_show_imbuf(space_sequencer);
+ SpaceSeq *space_sequencer = CTX_wm_space_seq(C);
+ if (space_sequencer == NULL) {
+ return false;
+ }
+ return ED_space_sequencer_check_show_imbuf(space_sequencer);
}
static void metadata_panel_context_draw(const bContext *C, Panel *panel)
{
- /* Image buffer can not be acquired during render, similar to
- * draw_image_seq(). */
- if (G.is_rendering) {
- return;
- }
- struct Main *bmain = CTX_data_main(C);
- struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
- struct Scene *scene = CTX_data_scene(C);
- SpaceSeq *space_sequencer = CTX_wm_space_seq(C);
- /* NOTE: We can only reliably show metadata for the original (current)
- * frame when split view is used. */
- const bool show_split = (
- scene->ed &&
- (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) &&
- (space_sequencer->mainb == SEQ_DRAW_IMG_IMBUF));
- if (show_split &&
- space_sequencer->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE)
- {
- return;
- }
- /* NOTE: We disable multiview for drawing, since we don't know what is the
- * from the panel (is kind of all the views?). */
- ImBuf *ibuf = sequencer_ibuf_get(bmain, depsgraph, scene, space_sequencer, scene->r.cfra, 0, "");
- if (ibuf != NULL) {
- ED_region_image_metadata_panel_draw(ibuf, panel->layout);
- IMB_freeImBuf(ibuf);
- }
+ /* Image buffer can not be acquired during render, similar to
+ * draw_image_seq(). */
+ if (G.is_rendering) {
+ return;
+ }
+ struct Main *bmain = CTX_data_main(C);
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ struct Scene *scene = CTX_data_scene(C);
+ SpaceSeq *space_sequencer = CTX_wm_space_seq(C);
+ /* NOTE: We can only reliably show metadata for the original (current)
+ * frame when split view is used. */
+ const bool show_split = (scene->ed && (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) &&
+ (space_sequencer->mainb == SEQ_DRAW_IMG_IMBUF));
+ if (show_split && space_sequencer->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) {
+ return;
+ }
+ /* NOTE: We disable multiview for drawing, since we don't know what is the
+ * from the panel (is kind of all the views?). */
+ ImBuf *ibuf = sequencer_ibuf_get(bmain, depsgraph, scene, space_sequencer, scene->r.cfra, 0, "");
+ if (ibuf != NULL) {
+ ED_region_image_metadata_panel_draw(ibuf, panel->layout);
+ IMB_freeImBuf(ibuf);
+ }
}
void sequencer_buttons_register(ARegionType *art)
{
- PanelType *pt;
+ PanelType *pt;
#if 0
- pt = MEM_callocN(sizeof(PanelType), "spacetype sequencer panel gpencil");
- strcpy(pt->idname, "SEQUENCER_PT_gpencil");
- strcpy(pt->label, N_("Grease Pencil"));
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw_header = ED_gpencil_panel_standard_header;
- pt->draw = ED_gpencil_panel_standard;
- pt->poll = sequencer_grease_pencil_panel_poll;
- BLI_addtail(&art->paneltypes, pt);
+ pt = MEM_callocN(sizeof(PanelType), "spacetype sequencer panel gpencil");
+ strcpy(pt->idname, "SEQUENCER_PT_gpencil");
+ strcpy(pt->label, N_("Grease Pencil"));
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw_header = ED_gpencil_panel_standard_header;
+ pt->draw = ED_gpencil_panel_standard;
+ pt->poll = sequencer_grease_pencil_panel_poll;
+ BLI_addtail(&art->paneltypes, pt);
#endif
- pt = MEM_callocN(sizeof(PanelType), "spacetype sequencer panel metadata");
- strcpy(pt->idname, "SEQUENCER_PT_metadata");
- strcpy(pt->label, N_("Metadata"));
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->poll = metadata_panel_context_poll;
- pt->draw = metadata_panel_context_draw;
- pt->flag |= PNL_DEFAULT_CLOSED;
- BLI_addtail(&art->paneltypes, pt);
+ pt = MEM_callocN(sizeof(PanelType), "spacetype sequencer panel metadata");
+ strcpy(pt->idname, "SEQUENCER_PT_metadata");
+ strcpy(pt->label, N_("Metadata"));
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->poll = metadata_panel_context_poll;
+ pt->draw = metadata_panel_context_draw;
+ pt->flag |= PNL_DEFAULT_CLOSED;
+ BLI_addtail(&art->paneltypes, pt);
}
/* **************** operator to open/close properties view ************* */
static int sequencer_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = sequencer_has_buttons_region(sa);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = sequencer_has_buttons_region(sa);
- if (ar) {
- ED_region_toggle_hidden(C, ar);
- }
+ if (ar) {
+ ED_region_toggle_hidden(C, ar);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_properties(wmOperatorType *ot)
{
- ot->name = "Properties";
- ot->idname = "SEQUENCER_OT_properties";
- ot->description = "Toggle the properties region visibility";
+ ot->name = "Properties";
+ ot->idname = "SEQUENCER_OT_properties";
+ ot->description = "Toggle the properties region visibility";
- ot->exec = sequencer_properties_toggle_exec;
- ot->poll = ED_operator_sequencer_active;
+ ot->exec = sequencer_properties_toggle_exec;
+ ot->poll = ED_operator_sequencer_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 7bd19287e29..e2140fba1f6 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -21,7 +21,6 @@
* \ingroup spseq
*/
-
#include <string.h>
#include <math.h>
@@ -49,7 +48,6 @@
#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
-
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
@@ -75,16 +73,14 @@
/* own include */
#include "sequencer_intern.h"
+#define SEQ_LEFTHANDLE 1
+#define SEQ_RIGHTHANDLE 2
-#define SEQ_LEFTHANDLE 1
-#define SEQ_RIGHTHANDLE 2
-
-#define SEQ_HANDLE_SIZE_MIN 7.0f
+#define SEQ_HANDLE_SIZE_MIN 7.0f
#define SEQ_HANDLE_SIZE_MAX 40.0f
#define SEQ_SCROLLER_TEXT_OFFSET 8
-
/* Note, Don't use SEQ_BEGIN/SEQ_END while drawing!
* it messes up transform, - Campbell */
#undef SEQ_BEGIN
@@ -95,1710 +91,1827 @@ static Sequence *special_seq_update = NULL;
void color3ubv_from_seq(Scene *curscene, Sequence *seq, unsigned char col[3])
{
- unsigned char blendcol[3];
- SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
-
- switch (seq->type) {
- case SEQ_TYPE_IMAGE:
- UI_GetThemeColor3ubv(TH_SEQ_IMAGE, col);
- break;
-
- case SEQ_TYPE_META:
- UI_GetThemeColor3ubv(TH_SEQ_META, col);
- break;
-
- case SEQ_TYPE_MOVIE:
- UI_GetThemeColor3ubv(TH_SEQ_MOVIE, col);
- break;
-
- case SEQ_TYPE_MOVIECLIP:
- UI_GetThemeColor3ubv(TH_SEQ_MOVIECLIP, col);
- break;
-
- case SEQ_TYPE_MASK:
- UI_GetThemeColor3ubv(TH_SEQ_MASK, col); /* TODO */
- break;
-
- case SEQ_TYPE_SCENE:
- UI_GetThemeColor3ubv(TH_SEQ_SCENE, col);
-
- if (seq->scene == curscene) {
- UI_GetColorPtrShade3ubv(col, col, 20);
- }
- break;
-
- /* transitions */
- 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); }
- break;
-
- /* effects */
- case SEQ_TYPE_TRANSFORM:
- case SEQ_TYPE_SPEED:
- case SEQ_TYPE_ADD:
- case SEQ_TYPE_SUB:
- case SEQ_TYPE_MUL:
- case SEQ_TYPE_ALPHAOVER:
- case SEQ_TYPE_ALPHAUNDER:
- case SEQ_TYPE_OVERDROP:
- case SEQ_TYPE_GLOW:
- case SEQ_TYPE_MULTICAM:
- case SEQ_TYPE_ADJUSTMENT:
- case SEQ_TYPE_GAUSSIAN_BLUR:
- case SEQ_TYPE_COLORMIX:
- UI_GetThemeColor3ubv(TH_SEQ_EFFECT, col);
-
- /* slightly offset hue to distinguish different effects */
- if (seq->type == SEQ_TYPE_ADD) { rgb_byte_set_hue_float_offset(col, 0.04); }
- else if (seq->type == SEQ_TYPE_SUB) { rgb_byte_set_hue_float_offset(col, 0.08); }
- else if (seq->type == SEQ_TYPE_MUL) { rgb_byte_set_hue_float_offset(col, 0.12); }
- 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); }
- else if (seq->type == SEQ_TYPE_OVERDROP) { rgb_byte_set_hue_float_offset(col, 0.24); }
- else if (seq->type == SEQ_TYPE_GLOW) { rgb_byte_set_hue_float_offset(col, 0.28); }
- else if (seq->type == SEQ_TYPE_TRANSFORM) { rgb_byte_set_hue_float_offset(col, 0.36); }
- else if (seq->type == SEQ_TYPE_MULTICAM) { rgb_byte_set_hue_float_offset(col, 0.32); }
- else if (seq->type == SEQ_TYPE_ADJUSTMENT) { rgb_byte_set_hue_float_offset(col, 0.40); }
- else if (seq->type == SEQ_TYPE_GAUSSIAN_BLUR) { rgb_byte_set_hue_float_offset(col, 0.42); }
- else if (seq->type == SEQ_TYPE_COLORMIX) { rgb_byte_set_hue_float_offset(col, 0.46); }
- break;
-
- case SEQ_TYPE_COLOR:
- rgb_float_to_uchar(col, colvars->col);
- break;
-
- case SEQ_TYPE_SOUND_RAM:
- UI_GetThemeColor3ubv(TH_SEQ_AUDIO, col);
- blendcol[0] = blendcol[1] = blendcol[2] = 128;
- if (seq->flag & SEQ_MUTE) {
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.5, 20);
- }
- break;
-
- case SEQ_TYPE_TEXT:
- UI_GetThemeColor3ubv(TH_SEQ_TEXT, col);
- break;
-
- default:
- col[0] = 10; col[1] = 255; col[2] = 40;
- break;
- }
+ unsigned char blendcol[3];
+ SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
+
+ switch (seq->type) {
+ case SEQ_TYPE_IMAGE:
+ UI_GetThemeColor3ubv(TH_SEQ_IMAGE, col);
+ break;
+
+ case SEQ_TYPE_META:
+ UI_GetThemeColor3ubv(TH_SEQ_META, col);
+ break;
+
+ case SEQ_TYPE_MOVIE:
+ UI_GetThemeColor3ubv(TH_SEQ_MOVIE, col);
+ break;
+
+ case SEQ_TYPE_MOVIECLIP:
+ UI_GetThemeColor3ubv(TH_SEQ_MOVIECLIP, col);
+ break;
+
+ case SEQ_TYPE_MASK:
+ UI_GetThemeColor3ubv(TH_SEQ_MASK, col); /* TODO */
+ break;
+
+ case SEQ_TYPE_SCENE:
+ UI_GetThemeColor3ubv(TH_SEQ_SCENE, col);
+
+ if (seq->scene == curscene) {
+ UI_GetColorPtrShade3ubv(col, col, 20);
+ }
+ break;
+
+ /* transitions */
+ 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);
+ }
+ break;
+
+ /* effects */
+ case SEQ_TYPE_TRANSFORM:
+ case SEQ_TYPE_SPEED:
+ case SEQ_TYPE_ADD:
+ case SEQ_TYPE_SUB:
+ case SEQ_TYPE_MUL:
+ case SEQ_TYPE_ALPHAOVER:
+ case SEQ_TYPE_ALPHAUNDER:
+ case SEQ_TYPE_OVERDROP:
+ case SEQ_TYPE_GLOW:
+ case SEQ_TYPE_MULTICAM:
+ case SEQ_TYPE_ADJUSTMENT:
+ case SEQ_TYPE_GAUSSIAN_BLUR:
+ case SEQ_TYPE_COLORMIX:
+ UI_GetThemeColor3ubv(TH_SEQ_EFFECT, col);
+
+ /* slightly offset hue to distinguish different effects */
+ if (seq->type == SEQ_TYPE_ADD) {
+ rgb_byte_set_hue_float_offset(col, 0.04);
+ }
+ else if (seq->type == SEQ_TYPE_SUB) {
+ rgb_byte_set_hue_float_offset(col, 0.08);
+ }
+ else if (seq->type == SEQ_TYPE_MUL) {
+ rgb_byte_set_hue_float_offset(col, 0.12);
+ }
+ 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);
+ }
+ else if (seq->type == SEQ_TYPE_OVERDROP) {
+ rgb_byte_set_hue_float_offset(col, 0.24);
+ }
+ else if (seq->type == SEQ_TYPE_GLOW) {
+ rgb_byte_set_hue_float_offset(col, 0.28);
+ }
+ else if (seq->type == SEQ_TYPE_TRANSFORM) {
+ rgb_byte_set_hue_float_offset(col, 0.36);
+ }
+ else if (seq->type == SEQ_TYPE_MULTICAM) {
+ rgb_byte_set_hue_float_offset(col, 0.32);
+ }
+ else if (seq->type == SEQ_TYPE_ADJUSTMENT) {
+ rgb_byte_set_hue_float_offset(col, 0.40);
+ }
+ else if (seq->type == SEQ_TYPE_GAUSSIAN_BLUR) {
+ rgb_byte_set_hue_float_offset(col, 0.42);
+ }
+ else if (seq->type == SEQ_TYPE_COLORMIX) {
+ rgb_byte_set_hue_float_offset(col, 0.46);
+ }
+ break;
+
+ case SEQ_TYPE_COLOR:
+ rgb_float_to_uchar(col, colvars->col);
+ break;
+
+ case SEQ_TYPE_SOUND_RAM:
+ UI_GetThemeColor3ubv(TH_SEQ_AUDIO, col);
+ blendcol[0] = blendcol[1] = blendcol[2] = 128;
+ if (seq->flag & SEQ_MUTE) {
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.5, 20);
+ }
+ break;
+
+ case SEQ_TYPE_TEXT:
+ UI_GetThemeColor3ubv(TH_SEQ_TEXT, col);
+ break;
+
+ default:
+ col[0] = 10;
+ col[1] = 255;
+ col[2] = 40;
+ break;
+ }
}
-static void drawseqwave(View2D *v2d, const bContext *C, SpaceSeq *sseq, Scene *scene, Sequence *seq,
- float x1, float y1, float x2, float y2, float stepsize)
+static void drawseqwave(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 */
- int x1_offset = max_ff(v2d->cur.xmin, x1);
- int x2_offset = min_ff(v2d->cur.xmax + 1.0f, x2);
-
- if (seq->sound && ((sseq->flag & SEQ_ALL_WAVEFORMS) || (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM))) {
- int i, j, p;
- int length = floor((x2_offset - x1_offset) / stepsize) + 1;
- float ymid = (y1 + y2) / 2.0f;
- float yscale = (y2 - y1) / 2.0f;
- float samplestep;
- float startsample, endsample;
- float value1, value2;
- bSound *sound = seq->sound;
-
- SoundWaveform *waveform;
-
- if (length < 2) {
- return;
- }
-
- if (!sound->spinlock) {
- sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock");
- BLI_spin_init(sound->spinlock);
- }
-
- BLI_spin_lock(sound->spinlock);
- if (!sound->waveform) {
- if (!(sound->tags & SOUND_TAGS_WAVEFORM_LOADING)) {
- /* prevent sounds from reloading */
- sound->tags |= SOUND_TAGS_WAVEFORM_LOADING;
- BLI_spin_unlock(sound->spinlock);
- sequencer_preview_add_sound(C, seq);
- }
- else {
- BLI_spin_unlock(sound->spinlock);
- }
- return; /* nothing to draw */
- }
- BLI_spin_unlock(sound->spinlock);
-
- waveform = sound->waveform;
-
- if (waveform->length == 0) {
- /* BKE_sound_read_waveform() set an empty SoundWaveform data in case it cannot generate a valid one...
- * See T45726. */
- return;
- }
-
- startsample = floor((seq->startofs + seq->anim_startofs) / FPS * SOUND_WAVE_SAMPLES_PER_SECOND);
- endsample = ceil((seq->startofs + seq->anim_startofs + seq->enddisp - seq->startdisp) / FPS * SOUND_WAVE_SAMPLES_PER_SECOND);
- samplestep = (endsample - startsample) * stepsize / (x2 - x1);
-
- length = min_ii(floor((waveform->length - startsample) / samplestep - (x1_offset - x1) / stepsize), length);
-
- if (length < 2) {
- return;
- }
-
- GPU_blend(true);
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- immBegin(GPU_PRIM_TRI_STRIP, length * 2);
-
- for (i = 0; i < length; i++) {
- float sampleoffset = startsample + ((x1_offset - x1) / stepsize + i) * samplestep;
- p = sampleoffset;
-
- value1 = waveform->data[p * 3];
- value2 = waveform->data[p * 3 + 1];
-
- if (samplestep > 1.0f) {
- for (j = p + 1; (j < waveform->length) && (j < p + samplestep); j++) {
- if (value1 > waveform->data[j * 3]) {
- value1 = waveform->data[j * 3];
- }
-
- if (value2 < waveform->data[j * 3 + 1]) {
- value2 = waveform->data[j * 3 + 1];
- }
- }
- }
- else if (p + 1 < waveform->length) {
- /* 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];
- }
-
- value1 *= seq->volume;
- value2 *= seq->volume;
-
- if (value2 > 1 || value1 < -1) {
- immAttr4f(col, 1.0f, 0.0f, 0.0f, 0.5f);
-
- CLAMP_MAX(value2, 1.0f);
- CLAMP_MIN(value1, -1.0f);
- }
- else {
- immAttr4f(col, 1.0f, 1.0f, 1.0f, 0.5f);
- }
-
- immVertex2f(pos, x1_offset + i * stepsize, ymid + value1 * yscale);
- immVertex2f(pos, x1_offset + i * stepsize, ymid + value2 * yscale);
- }
-
- immEnd();
- immUnbindProgram();
- GPU_blend(false);
- }
+ /*
+ * 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 */
+ int x1_offset = max_ff(v2d->cur.xmin, x1);
+ int x2_offset = min_ff(v2d->cur.xmax + 1.0f, x2);
+
+ if (seq->sound && ((sseq->flag & SEQ_ALL_WAVEFORMS) || (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM))) {
+ int i, j, p;
+ int length = floor((x2_offset - x1_offset) / stepsize) + 1;
+ float ymid = (y1 + y2) / 2.0f;
+ float yscale = (y2 - y1) / 2.0f;
+ float samplestep;
+ float startsample, endsample;
+ float value1, value2;
+ bSound *sound = seq->sound;
+
+ SoundWaveform *waveform;
+
+ if (length < 2) {
+ return;
+ }
+
+ if (!sound->spinlock) {
+ sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock");
+ BLI_spin_init(sound->spinlock);
+ }
+
+ BLI_spin_lock(sound->spinlock);
+ if (!sound->waveform) {
+ if (!(sound->tags & SOUND_TAGS_WAVEFORM_LOADING)) {
+ /* prevent sounds from reloading */
+ sound->tags |= SOUND_TAGS_WAVEFORM_LOADING;
+ BLI_spin_unlock(sound->spinlock);
+ sequencer_preview_add_sound(C, seq);
+ }
+ else {
+ BLI_spin_unlock(sound->spinlock);
+ }
+ return; /* nothing to draw */
+ }
+ BLI_spin_unlock(sound->spinlock);
+
+ waveform = sound->waveform;
+
+ if (waveform->length == 0) {
+ /* BKE_sound_read_waveform() set an empty SoundWaveform data in case it cannot generate a valid one...
+ * See T45726. */
+ return;
+ }
+
+ startsample = floor((seq->startofs + seq->anim_startofs) / FPS *
+ SOUND_WAVE_SAMPLES_PER_SECOND);
+ endsample = ceil((seq->startofs + seq->anim_startofs + seq->enddisp - seq->startdisp) / FPS *
+ SOUND_WAVE_SAMPLES_PER_SECOND);
+ samplestep = (endsample - startsample) * stepsize / (x2 - x1);
+
+ length = min_ii(
+ floor((waveform->length - startsample) / samplestep - (x1_offset - x1) / stepsize),
+ length);
+
+ if (length < 2) {
+ return;
+ }
+
+ GPU_blend(true);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GPU_PRIM_TRI_STRIP, length * 2);
+
+ for (i = 0; i < length; i++) {
+ float sampleoffset = startsample + ((x1_offset - x1) / stepsize + i) * samplestep;
+ p = sampleoffset;
+
+ value1 = waveform->data[p * 3];
+ value2 = waveform->data[p * 3 + 1];
+
+ if (samplestep > 1.0f) {
+ for (j = p + 1; (j < waveform->length) && (j < p + samplestep); j++) {
+ if (value1 > waveform->data[j * 3]) {
+ value1 = waveform->data[j * 3];
+ }
+
+ if (value2 < waveform->data[j * 3 + 1]) {
+ value2 = waveform->data[j * 3 + 1];
+ }
+ }
+ }
+ else if (p + 1 < waveform->length) {
+ /* 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];
+ }
+
+ value1 *= seq->volume;
+ value2 *= seq->volume;
+
+ if (value2 > 1 || value1 < -1) {
+ immAttr4f(col, 1.0f, 0.0f, 0.0f, 0.5f);
+
+ CLAMP_MAX(value2, 1.0f);
+ CLAMP_MIN(value1, -1.0f);
+ }
+ else {
+ immAttr4f(col, 1.0f, 1.0f, 1.0f, 0.5f);
+ }
+
+ immVertex2f(pos, x1_offset + i * stepsize, ymid + value1 * yscale);
+ immVertex2f(pos, x1_offset + i * stepsize, ymid + value2 * yscale);
+ }
+
+ immEnd();
+ immUnbindProgram();
+ 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 */
- Sequence *seq;
- unsigned char col[4];
-
- int chan_min = MAXSEQ;
- int chan_max = 0;
- int chan_range = 0;
- float draw_range = y2 - y1;
- float draw_height;
- ListBase *seqbase;
- int offset;
-
- seqbase = BKE_sequence_seqbase_get(seqm, &offset);
- if (!seqbase || BLI_listbase_is_empty(seqbase)) {
- return;
- }
-
- if (seqm->type == SEQ_TYPE_SCENE) {
- offset = seqm->start - offset;
- }
- else {
- offset = 0;
- }
-
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- for (seq = seqbase->first; seq; seq = seq->next) {
- chan_min = min_ii(chan_min, seq->machine);
- chan_max = max_ii(chan_max, seq->machine);
- }
-
- chan_range = (chan_max - chan_min) + 1;
- draw_height = draw_range / chan_range;
-
- 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);
-
- for (seq = seqbase->first; seq; seq = seq->next) {
- const int startdisp = seq->startdisp + offset;
- const int enddisp = seq->enddisp + offset;
-
- if ((startdisp > x2 || enddisp < x1) == 0) {
- float y_chan = (seq->machine - chan_min) / (float)(chan_range) * draw_range;
- float x1_chan = startdisp;
- float x2_chan = enddisp;
- float y1_chan, y2_chan;
-
- color3ubv_from_seq(scene, seq, col);
-
- if ((seqm->flag & SEQ_MUTE) || (seq->flag & SEQ_MUTE)) {
- col[3] = 64;
- }
- else {
- col[3] = 196;
- }
-
- immUniformColor4ubv(col);
-
- /* clamp within parent sequence strip bounds */
- if (x1_chan < x1) {
- x1_chan = x1;
- }
- if (x2_chan > x2) {
- x2_chan = x2;
- }
-
- y1_chan = y1 + y_chan + (draw_height * SEQ_STRIP_OFSBOTTOM);
- y2_chan = y1 + y_chan + (draw_height * SEQ_STRIP_OFSTOP);
-
- immRectf(pos, x1_chan, y1_chan, x2_chan, y2_chan);
- }
- }
-
- immUnbindProgram();
-
- GPU_blend(false);
+ /* 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 */
+ Sequence *seq;
+ unsigned char col[4];
+
+ int chan_min = MAXSEQ;
+ int chan_max = 0;
+ int chan_range = 0;
+ float draw_range = y2 - y1;
+ float draw_height;
+ ListBase *seqbase;
+ int offset;
+
+ seqbase = BKE_sequence_seqbase_get(seqm, &offset);
+ if (!seqbase || BLI_listbase_is_empty(seqbase)) {
+ return;
+ }
+
+ if (seqm->type == SEQ_TYPE_SCENE) {
+ offset = seqm->start - offset;
+ }
+ else {
+ offset = 0;
+ }
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ for (seq = seqbase->first; seq; seq = seq->next) {
+ chan_min = min_ii(chan_min, seq->machine);
+ chan_max = max_ii(chan_max, seq->machine);
+ }
+
+ chan_range = (chan_max - chan_min) + 1;
+ draw_height = draw_range / chan_range;
+
+ 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);
+
+ for (seq = seqbase->first; seq; seq = seq->next) {
+ const int startdisp = seq->startdisp + offset;
+ const int enddisp = seq->enddisp + offset;
+
+ if ((startdisp > x2 || enddisp < x1) == 0) {
+ float y_chan = (seq->machine - chan_min) / (float)(chan_range)*draw_range;
+ float x1_chan = startdisp;
+ float x2_chan = enddisp;
+ float y1_chan, y2_chan;
+
+ color3ubv_from_seq(scene, seq, col);
+
+ if ((seqm->flag & SEQ_MUTE) || (seq->flag & SEQ_MUTE)) {
+ col[3] = 64;
+ }
+ else {
+ col[3] = 196;
+ }
+
+ immUniformColor4ubv(col);
+
+ /* clamp within parent sequence strip bounds */
+ if (x1_chan < x1) {
+ x1_chan = x1;
+ }
+ if (x2_chan > x2) {
+ x2_chan = x2;
+ }
+
+ y1_chan = y1 + y_chan + (draw_height * SEQ_STRIP_OFSBOTTOM);
+ y2_chan = y1 + y_chan + (draw_height * SEQ_STRIP_OFSTOP);
+
+ immRectf(pos, x1_chan, y1_chan, x2_chan, y2_chan);
+ }
+ }
+
+ immUnbindProgram();
+
+ GPU_blend(false);
}
/* clamp handles to defined size in pixel space */
static float draw_seq_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 minhandle = pixelx * SEQ_HANDLE_SIZE_MIN;
+ const float maxhandle = pixelx * SEQ_HANDLE_SIZE_MAX;
+ float size = CLAMPIS(seq->handsize, minhandle, maxhandle);
- /* ensure we're not greater than half width */
- return min_ff(size, ((float)(seq->enddisp - seq->startdisp) / 2.0f) / pixelx);
+ /* ensure we're not greater than half width */
+ return min_ff(size, ((float)(seq->enddisp - seq->startdisp) / 2.0f) / pixelx);
}
/* draw a handle, for each end of a sequence strip */
-static void draw_seq_handle(
- View2D *v2d, Sequence *seq, const float handsize_clamped,
- const short direction, unsigned int pos)
+static void draw_seq_handle(View2D *v2d,
+ Sequence *seq,
+ const float handsize_clamped,
+ const short direction,
+ unsigned int pos)
{
- float v1[2], v2[2], v3[2], rx1 = 0, rx2 = 0; //for triangles and rect
- float x1, x2, y1, y2;
- unsigned int whichsel = 0;
-
- x1 = seq->startdisp;
- x2 = seq->enddisp;
-
- y1 = seq->machine + SEQ_STRIP_OFSBOTTOM;
- y2 = seq->machine + SEQ_STRIP_OFSTOP;
-
- /* set up co-ordinates/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;
-
- whichsel = SEQ_LEFTSEL;
- }
- else if (direction == SEQ_RIGHTHANDLE) {
- rx1 = x2 - handsize_clamped * 0.75f;
- 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);
-
- GPU_blend_set_func_separate(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);
- }
- else {
- immUniformColor4ub(0, 0, 0, 22);
- }
-
- immRectf(pos, rx1, y1, rx2, y2);
-
- if (seq->flag & whichsel) {
- immUniformColor4ub(255, 255, 255, 200);
- }
- else {
- immUniformColor4ub(0, 0, 0, 50);
- }
-
- immBegin(GPU_PRIM_TRIS, 3);
- immVertex2fv(pos, v1);
- immVertex2fv(pos, v2);
- immVertex2fv(pos, v3);
- immEnd();
-
- GPU_blend(false);
- }
-
- if ((G.moving & G_TRANSFORM_SEQ) || (seq->flag & whichsel)) {
- const char col[4] = {255, 255, 255, 255};
- char numstr[32];
- size_t numstr_len;
-
- if (direction == SEQ_LEFTHANDLE) {
- numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", seq->startdisp);
- x1 = rx1;
- y1 -= 0.45f;
- }
- else {
- numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", seq->enddisp - 1);
- x1 = x2 - handsize_clamped * 0.75f;
- y1 = y2 + 0.05f;
- }
- UI_view2d_text_cache_add(v2d, x1, y1, numstr, numstr_len, col);
- }
+ float v1[2], v2[2], v3[2], rx1 = 0, rx2 = 0; //for triangles and rect
+ float x1, x2, y1, y2;
+ unsigned int whichsel = 0;
+
+ x1 = seq->startdisp;
+ x2 = seq->enddisp;
+
+ y1 = seq->machine + SEQ_STRIP_OFSBOTTOM;
+ y2 = seq->machine + SEQ_STRIP_OFSTOP;
+
+ /* set up co-ordinates/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;
+
+ whichsel = SEQ_LEFTSEL;
+ }
+ else if (direction == SEQ_RIGHTHANDLE) {
+ rx1 = x2 - handsize_clamped * 0.75f;
+ 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);
+
+ GPU_blend_set_func_separate(
+ 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);
+ }
+ else {
+ immUniformColor4ub(0, 0, 0, 22);
+ }
+
+ immRectf(pos, rx1, y1, rx2, y2);
+
+ if (seq->flag & whichsel) {
+ immUniformColor4ub(255, 255, 255, 200);
+ }
+ else {
+ immUniformColor4ub(0, 0, 0, 50);
+ }
+
+ immBegin(GPU_PRIM_TRIS, 3);
+ immVertex2fv(pos, v1);
+ immVertex2fv(pos, v2);
+ immVertex2fv(pos, v3);
+ immEnd();
+
+ GPU_blend(false);
+ }
+
+ if ((G.moving & G_TRANSFORM_SEQ) || (seq->flag & whichsel)) {
+ const char col[4] = {255, 255, 255, 255};
+ char numstr[32];
+ size_t numstr_len;
+
+ if (direction == SEQ_LEFTHANDLE) {
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", seq->startdisp);
+ x1 = rx1;
+ y1 -= 0.45f;
+ }
+ else {
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", seq->enddisp - 1);
+ x1 = x2 - handsize_clamped * 0.75f;
+ y1 = y2 + 0.05f;
+ }
+ UI_view2d_text_cache_add(v2d, x1, y1, numstr, numstr_len, col);
+ }
}
/* draw info text on a sequence strip */
-static void draw_seq_text(
- View2D *v2d, SpaceSeq *sseq, Sequence *seq,
- float x1, float x2, float y1, float y2,
- const unsigned char background_col[3])
+static void draw_seq_text(View2D *v2d,
+ SpaceSeq *sseq,
+ Sequence *seq,
+ float x1,
+ float x2,
+ float y1,
+ float y2,
+ const unsigned char background_col[3])
{
- rctf rect;
- char str[32 + FILE_MAX];
- size_t str_len;
- const char *name = seq->name + 2;
- char col[4];
-
- /* note, all strings should include 'name' */
- if (name[0] == '\0') {
- name = BKE_sequence_give_name(seq);
- }
-
- if (seq->type == SEQ_TYPE_META || seq->type == SEQ_TYPE_ADJUSTMENT) {
- str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len);
- }
- else if (seq->type == SEQ_TYPE_SCENE) {
- if (seq->scene) {
- if (seq->scene_camera) {
- str_len = BLI_snprintf(str, sizeof(str), "%s: %s (%s) | %d",
- name, seq->scene->id.name + 2, ((ID *)seq->scene_camera)->name + 2, seq->len);
- }
- else {
- str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d",
- name, seq->scene->id.name + 2, seq->len);
- }
- }
- else {
- str_len = BLI_snprintf(str, sizeof(str), "%s | %d",
- name, seq->len);
- }
- }
- else if (seq->type == SEQ_TYPE_MOVIECLIP) {
- if (seq->clip && !STREQ(name, seq->clip->id.name + 2)) {
- str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d",
- name, seq->clip->id.name + 2, seq->len);
- }
- else {
- str_len = BLI_snprintf(str, sizeof(str), "%s | %d",
- name, seq->len);
- }
- }
- else if (seq->type == SEQ_TYPE_MASK) {
- if (seq->mask && !STREQ(name, seq->mask->id.name + 2)) {
- str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d",
- name, seq->mask->id.name + 2, seq->len);
- }
- else {
- str_len = BLI_snprintf(str, sizeof(str), "%s | %d",
- name, seq->len);
- }
- }
- else if (seq->type == SEQ_TYPE_MULTICAM) {
- str_len = BLI_snprintf(str, sizeof(str), "Cam %s: %d",
- name, seq->multicam_source);
- }
- else if (seq->type == SEQ_TYPE_IMAGE) {
- str_len = BLI_snprintf(str, sizeof(str), "%s: %s%s | %d",
- name, seq->strip->dir, seq->strip->stripdata->name, seq->len);
- }
- else if (seq->type == SEQ_TYPE_TEXT) {
- TextVars *textdata = seq->effectdata;
- str_len = BLI_snprintf(str, sizeof(str), "%s | %d",
- textdata->text, seq->startdisp);
- }
- else if (seq->type & SEQ_TYPE_EFFECT) {
- 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)) {
- str[0] = 0;
- str_len = 0;
- }
- else if (seq->sound) {
- str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d",
- name, seq->sound->name, seq->len);
- }
- else {
- str_len = BLI_snprintf(str, sizeof(str), "%s | %d",
- name, seq->len);
- }
- }
- else if (seq->type == SEQ_TYPE_MOVIE) {
- str_len = BLI_snprintf(str, sizeof(str), "%s: %s%s | %d",
- name, seq->strip->dir, seq->strip->stripdata->name, seq->len);
- }
- else {
- /* 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;
- }
- col[3] = 255;
-
- rect.xmin = x1;
- rect.ymin = y1;
- rect.xmax = x2;
- rect.ymax = y2;
-
- UI_view2d_text_cache_add_rectf(v2d, &rect, str, str_len, col);
+ rctf rect;
+ char str[32 + FILE_MAX];
+ size_t str_len;
+ const char *name = seq->name + 2;
+ char col[4];
+
+ /* note, all strings should include 'name' */
+ if (name[0] == '\0') {
+ name = BKE_sequence_give_name(seq);
+ }
+
+ if (seq->type == SEQ_TYPE_META || seq->type == SEQ_TYPE_ADJUSTMENT) {
+ str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len);
+ }
+ else if (seq->type == SEQ_TYPE_SCENE) {
+ if (seq->scene) {
+ if (seq->scene_camera) {
+ str_len = BLI_snprintf(str,
+ sizeof(str),
+ "%s: %s (%s) | %d",
+ name,
+ seq->scene->id.name + 2,
+ ((ID *)seq->scene_camera)->name + 2,
+ seq->len);
+ }
+ else {
+ str_len = BLI_snprintf(
+ str, sizeof(str), "%s: %s | %d", name, seq->scene->id.name + 2, seq->len);
+ }
+ }
+ else {
+ str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len);
+ }
+ }
+ else if (seq->type == SEQ_TYPE_MOVIECLIP) {
+ if (seq->clip && !STREQ(name, seq->clip->id.name + 2)) {
+ str_len = BLI_snprintf(
+ str, sizeof(str), "%s: %s | %d", name, seq->clip->id.name + 2, seq->len);
+ }
+ else {
+ str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len);
+ }
+ }
+ else if (seq->type == SEQ_TYPE_MASK) {
+ if (seq->mask && !STREQ(name, seq->mask->id.name + 2)) {
+ str_len = BLI_snprintf(
+ str, sizeof(str), "%s: %s | %d", name, seq->mask->id.name + 2, seq->len);
+ }
+ else {
+ str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len);
+ }
+ }
+ else if (seq->type == SEQ_TYPE_MULTICAM) {
+ str_len = BLI_snprintf(str, sizeof(str), "Cam %s: %d", name, seq->multicam_source);
+ }
+ else if (seq->type == SEQ_TYPE_IMAGE) {
+ str_len = BLI_snprintf(str,
+ sizeof(str),
+ "%s: %s%s | %d",
+ name,
+ seq->strip->dir,
+ seq->strip->stripdata->name,
+ seq->len);
+ }
+ else if (seq->type == SEQ_TYPE_TEXT) {
+ TextVars *textdata = seq->effectdata;
+ str_len = BLI_snprintf(str, sizeof(str), "%s | %d", textdata->text, seq->startdisp);
+ }
+ else if (seq->type & SEQ_TYPE_EFFECT) {
+ 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)) {
+ str[0] = 0;
+ str_len = 0;
+ }
+ else if (seq->sound) {
+ str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d", name, seq->sound->name, seq->len);
+ }
+ else {
+ str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len);
+ }
+ }
+ else if (seq->type == SEQ_TYPE_MOVIE) {
+ str_len = BLI_snprintf(str,
+ sizeof(str),
+ "%s: %s%s | %d",
+ name,
+ seq->strip->dir,
+ seq->strip->stripdata->name,
+ seq->len);
+ }
+ else {
+ /* 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;
+ }
+ col[3] = 255;
+
+ rect.xmin = x1;
+ rect.ymin = y1;
+ rect.xmax = x2;
+ rect.ymax = y2;
+
+ 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)
{
- float x1, x2, y1, y2, pixely;
- unsigned char col[4], blendcol[3];
- View2D *v2d = &ar->v2d;
-
- x1 = seq->startdisp;
- x2 = seq->enddisp;
-
- 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);
-
- if (pixely <= 0) {
- return; /* can happen when the view is split/resized */
- }
-
- blendcol[0] = blendcol[1] = blendcol[2] = 120;
-
- 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);
-
- color3ubv_from_seq(scene, seq, col);
-
- if (seq->flag & SELECT) {
- UI_GetColorPtrShade3ubv(col, col, -50);
- }
-
- if (seq->flag & SEQ_MUTE) {
- col[3] = 64;
- }
- else {
- if (seq->flag & SELECT) {
- col[3] = 170;
- }
- else {
- col[3] = 80;
- }
- }
- }
-
- if (seq->startofs) {
- immUniformColor4ubv(col);
- immRectf(pos, (float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1);
-
- immUniformColor3ubvAlpha(col, col[3] + 50);
-
- /* 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);
-
- immUniformColor3ubvAlpha(col, col[3] + 50);
-
- /* outline */
- imm_draw_box_wire_2d(pos, x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM);
- }
-
- if (seq->startofs || seq->endofs) {
- GPU_blend(false);
- }
-
- if (seq->startstill || seq->endstill) {
- 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);
-
- if (seq->flag & SEQ_MUTE) {
- col[3] = 96;
- }
- else {
- if (seq->flag & SELECT) {
- col[3] = 255;
- }
- else {
- col[3] = 170;
- }
- }
-
- 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);
- }
-
- if (seq->startstill || seq->endstill) {
- GPU_blend(false);
- }
+ float x1, x2, y1, y2, pixely;
+ unsigned char col[4], blendcol[3];
+ View2D *v2d = &ar->v2d;
+
+ x1 = seq->startdisp;
+ x2 = seq->enddisp;
+
+ 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);
+
+ if (pixely <= 0) {
+ return; /* can happen when the view is split/resized */
+ }
+
+ blendcol[0] = blendcol[1] = blendcol[2] = 120;
+
+ 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);
+
+ color3ubv_from_seq(scene, seq, col);
+
+ if (seq->flag & SELECT) {
+ UI_GetColorPtrShade3ubv(col, col, -50);
+ }
+
+ if (seq->flag & SEQ_MUTE) {
+ col[3] = 64;
+ }
+ else {
+ if (seq->flag & SELECT) {
+ col[3] = 170;
+ }
+ else {
+ col[3] = 80;
+ }
+ }
+ }
+
+ if (seq->startofs) {
+ immUniformColor4ubv(col);
+ immRectf(pos, (float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1);
+
+ immUniformColor3ubvAlpha(col, col[3] + 50);
+
+ /* 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);
+
+ immUniformColor3ubvAlpha(col, col[3] + 50);
+
+ /* outline */
+ imm_draw_box_wire_2d(pos, x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM);
+ }
+
+ if (seq->startofs || seq->endofs) {
+ GPU_blend(false);
+ }
+
+ if (seq->startstill || seq->endstill) {
+ 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);
+
+ if (seq->flag & SEQ_MUTE) {
+ col[3] = 96;
+ }
+ else {
+ if (seq->flag & SELECT) {
+ col[3] = 255;
+ }
+ else {
+ col[3] = 170;
+ }
+ }
+
+ 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);
+ }
+
+ if (seq->startstill || seq->endstill) {
+ 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_strip(const bContext *C,
+ SpaceSeq *sseq,
+ Scene *scene,
+ ARegion *ar,
+ Sequence *seq,
+ int outline_tint,
+ float pixelx)
{
- 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);
-
- /* we need to know if this is a single image/color or not for drawing */
- is_single_image = (char)BKE_sequence_single_check(seq);
-
- /* 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;
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* get the correct color per strip type*/
- //color3ubv_from_seq(scene, seq, col);
- color3ubv_from_seq(scene, seq, background_col);
-
- if (seq->flag & SEQ_MUTE) {
- background_col[3] = 128;
-
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- }
- else {
- background_col[3] = 255;
- }
-
- if (seq->flag & SELECT) {
- UI_GetColorPtrShade3ubv(background_col, background_col, -50);
- }
-
- immUniformColor4ubv(background_col);
-
- /* 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);
- }
- else { /* normal operation */
- immRectf(pos, x1, y1, x2, y2);
- }
-
- if (seq->flag & SEQ_MUTE) {
- GPU_blend(false);
- }
-
- if (!is_single_image) {
- if ((sseq->draw_flag & SEQ_DRAW_OFFSET_EXT) || (seq == special_seq_update)) {
- draw_sequence_extensions(scene, ar, seq, pos);
- }
- }
-
- draw_seq_handle(v2d, seq, handsize_clamped, SEQ_LEFTHANDLE, pos);
- draw_seq_handle(v2d, seq, handsize_clamped, SEQ_RIGHTHANDLE, pos);
+ 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);
+
+ /* we need to know if this is a single image/color or not for drawing */
+ is_single_image = (char)BKE_sequence_single_check(seq);
+
+ /* 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;
- x1 = seq->startdisp;
- x2 = seq->enddisp;
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immUnbindProgram();
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- /* 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);
- }
- }
-
- /* draw lock */
- if (seq->flag & SEQ_LOCK) {
- GPU_blend(true);
-
- pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES);
-
- 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);
-
- immRectf(pos, x1, y1, x2, y2);
-
- immUnbindProgram();
-
- GPU_blend(false);
- }
-
- if (!BKE_sequence_is_valid_check(seq)) {
- GPU_blend(true);
-
- pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES);
-
- 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);
-
- immRectf(pos, x1, y1, x2, y2);
-
- immUnbindProgram();
-
- GPU_blend(false);
- }
-
- color3ubv_from_seq(scene, seq, col);
-
- /* 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);
- }
- }
- else {
- UI_GetColorPtrShade3ubv(col, col, outline_tint);
- }
-
- 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 (seq->flag & SEQ_MUTE) {
- col[3] = 96;
-
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- immUniformColor4ubv(col);
- }
- else {
- immUniformColor3ubv(col);
- }
-
- imm_draw_box_wire_2d(pos, x1, y1, x2, y2); /* outline */
+ /* get the correct color per strip type*/
+ //color3ubv_from_seq(scene, seq, col);
+ color3ubv_from_seq(scene, seq, background_col);
- immUnbindProgram();
-
- /* calculate if seq is long enough to print a name */
- x1 = seq->startdisp + handsize_clamped;
- x2 = seq->enddisp - handsize_clamped;
+ if (seq->flag & SEQ_MUTE) {
+ background_col[3] = 128;
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ }
+ else {
+ background_col[3] = 255;
+ }
+
+ if (seq->flag & SELECT) {
+ UI_GetColorPtrShade3ubv(background_col, background_col, -50);
+ }
+
+ immUniformColor4ubv(background_col);
+
+ /* 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);
+ }
+ else { /* normal operation */
+ immRectf(pos, x1, y1, x2, y2);
+ }
+
+ if (seq->flag & SEQ_MUTE) {
+ GPU_blend(false);
+ }
+
+ if (!is_single_image) {
+ if ((sseq->draw_flag & SEQ_DRAW_OFFSET_EXT) || (seq == special_seq_update)) {
+ draw_sequence_extensions(scene, ar, seq, pos);
+ }
+ }
+
+ draw_seq_handle(v2d, seq, handsize_clamped, SEQ_LEFTHANDLE, pos);
+ draw_seq_handle(v2d, seq, handsize_clamped, SEQ_RIGHTHANDLE, pos);
- float scroller_vert_xoffs = (V2D_SCROLL_WIDTH_TEXT + SEQ_SCROLLER_TEXT_OFFSET) * pixelx;
+ x1 = seq->startdisp;
+ x2 = seq->enddisp;
- /* 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;
- }
+ immUnbindProgram();
+
+ /* 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);
+ }
+ }
+
+ /* draw lock */
+ if (seq->flag & SEQ_LOCK) {
+ GPU_blend(true);
+
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES);
+
+ 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);
+
+ immRectf(pos, x1, y1, x2, y2);
+
+ immUnbindProgram();
+
+ GPU_blend(false);
+ }
+
+ if (!BKE_sequence_is_valid_check(seq)) {
+ GPU_blend(true);
+
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES);
+
+ 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);
+
+ immRectf(pos, x1, y1, x2, y2);
+
+ immUnbindProgram();
+
+ GPU_blend(false);
+ }
+
+ color3ubv_from_seq(scene, seq, col);
+
+ /* 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);
+ }
+ }
+ else {
+ UI_GetColorPtrShade3ubv(col, col, outline_tint);
+ }
+
+ 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 (seq->flag & SEQ_MUTE) {
+ col[3] = 96;
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ immUniformColor4ubv(col);
+ }
+ else {
+ immUniformColor3ubv(col);
+ }
+
+ imm_draw_box_wire_2d(pos, x1, y1, x2, y2); /* outline */
+
+ immUnbindProgram();
+
+ /* calculate if seq is long enough to print a name */
+ x1 = seq->startdisp + handsize_clamped;
+ x2 = seq->enddisp - handsize_clamped;
+
+ float scroller_vert_xoffs = (V2D_SCROLL_WIDTH_TEXT + SEQ_SCROLLER_TEXT_OFFSET) * pixelx;
- /* 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);
- }
+ /* 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;
+ }
+
+ /* 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);
+ }
}
void sequencer_special_update_set(Sequence *seq)
{
- special_seq_update = seq;
+ special_seq_update = seq;
}
Sequence *ED_sequencer_special_preview_get(void)
{
- return special_seq_update;
+ return special_seq_update;
}
void ED_sequencer_special_preview_set(bContext *C, const int mval[2])
{
- Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
- int hand;
- Sequence *seq;
- seq = find_nearest_seq(scene, &ar->v2d, &hand, mval);
- sequencer_special_update_set(seq);
+ Scene *scene = CTX_data_scene(C);
+ ARegion *ar = CTX_wm_region(C);
+ int hand;
+ Sequence *seq;
+ seq = find_nearest_seq(scene, &ar->v2d, &hand, mval);
+ sequencer_special_update_set(seq);
}
void ED_sequencer_special_preview_clear(void)
{
- sequencer_special_update_set(NULL);
+ sequencer_special_update_set(NULL);
}
-ImBuf *sequencer_ibuf_get(
- struct Main *bmain, struct Depsgraph *depsgraph, Scene *scene,
- SpaceSeq *sseq, int cfra, int frame_ofs, const char *viewname)
+ImBuf *sequencer_ibuf_get(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ Scene *scene,
+ SpaceSeq *sseq,
+ int cfra,
+ int frame_ofs,
+ const char *viewname)
{
- SeqRenderData context = {0};
- ImBuf *ibuf;
- int rectx, recty;
- float render_size;
- float proxy_size = 100.0;
- short is_break = G.is_break;
-
- render_size = sseq->render_size;
- if (render_size == 0) {
- render_size = scene->r.size;
- }
- else {
- proxy_size = render_size;
- }
-
- if (render_size < 0) {
- return NULL;
- }
-
- rectx = (render_size * (float)scene->r.xsch) / 100.0f + 0.5f;
- recty = (render_size * (float)scene->r.ysch) / 100.0f + 0.5f;
-
- BKE_sequencer_new_render_data(
- bmain, depsgraph, scene,
- rectx, recty, proxy_size, false,
- &context);
- context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
-
- /* sequencer could start rendering, in this case we need to be sure it wouldn't be canceled
- * by Esc pressed somewhere in the past
- */
- G.is_break = false;
-
- /* Rendering can change OGL context. Save & Restore framebuffer. */
- GPUFrameBuffer *fb = GPU_framebuffer_active_get();
- GPU_framebuffer_restore();
-
- 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);
- }
-
- if (fb) {
- GPU_framebuffer_bind(fb);
- }
-
- /* restore state so real rendering would be canceled (if needed) */
- G.is_break = is_break;
-
- return ibuf;
+ SeqRenderData context = {0};
+ ImBuf *ibuf;
+ int rectx, recty;
+ float render_size;
+ float proxy_size = 100.0;
+ short is_break = G.is_break;
+
+ render_size = sseq->render_size;
+ if (render_size == 0) {
+ render_size = scene->r.size;
+ }
+ else {
+ proxy_size = render_size;
+ }
+
+ if (render_size < 0) {
+ return NULL;
+ }
+
+ rectx = (render_size * (float)scene->r.xsch) / 100.0f + 0.5f;
+ recty = (render_size * (float)scene->r.ysch) / 100.0f + 0.5f;
+
+ BKE_sequencer_new_render_data(
+ bmain, depsgraph, scene, rectx, recty, proxy_size, false, &context);
+ context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
+
+ /* sequencer could start rendering, in this case we need to be sure it wouldn't be canceled
+ * by Esc pressed somewhere in the past
+ */
+ G.is_break = false;
+
+ /* Rendering can change OGL context. Save & Restore framebuffer. */
+ GPUFrameBuffer *fb = GPU_framebuffer_active_get();
+ GPU_framebuffer_restore();
+
+ 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);
+ }
+
+ if (fb) {
+ GPU_framebuffer_bind(fb);
+ }
+
+ /* restore state so real rendering would be canceled (if needed) */
+ G.is_break = is_break;
+
+ return ibuf;
}
static void sequencer_check_scopes(SequencerScopes *scopes, ImBuf *ibuf)
{
- if (scopes->reference_ibuf != ibuf) {
- if (scopes->zebra_ibuf) {
- IMB_freeImBuf(scopes->zebra_ibuf);
- scopes->zebra_ibuf = NULL;
- }
-
- if (scopes->waveform_ibuf) {
- IMB_freeImBuf(scopes->waveform_ibuf);
- scopes->waveform_ibuf = NULL;
- }
-
- if (scopes->sep_waveform_ibuf) {
- IMB_freeImBuf(scopes->sep_waveform_ibuf);
- scopes->sep_waveform_ibuf = NULL;
- }
-
- if (scopes->vector_ibuf) {
- IMB_freeImBuf(scopes->vector_ibuf);
- scopes->vector_ibuf = NULL;
- }
-
- if (scopes->histogram_ibuf) {
- IMB_freeImBuf(scopes->histogram_ibuf);
- scopes->histogram_ibuf = NULL;
- }
- }
+ if (scopes->reference_ibuf != ibuf) {
+ if (scopes->zebra_ibuf) {
+ IMB_freeImBuf(scopes->zebra_ibuf);
+ scopes->zebra_ibuf = NULL;
+ }
+
+ if (scopes->waveform_ibuf) {
+ IMB_freeImBuf(scopes->waveform_ibuf);
+ scopes->waveform_ibuf = NULL;
+ }
+
+ if (scopes->sep_waveform_ibuf) {
+ IMB_freeImBuf(scopes->sep_waveform_ibuf);
+ scopes->sep_waveform_ibuf = NULL;
+ }
+
+ if (scopes->vector_ibuf) {
+ IMB_freeImBuf(scopes->vector_ibuf);
+ scopes->vector_ibuf = NULL;
+ }
+
+ if (scopes->histogram_ibuf) {
+ IMB_freeImBuf(scopes->histogram_ibuf);
+ scopes->histogram_ibuf = NULL;
+ }
+ }
}
-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_cb)(ImBuf *ibuf))
{
- ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
- ImBuf *scope;
+ ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
+ ImBuf *scope;
- IMB_colormanagement_imbuf_make_display_space(
- display_ibuf, &scene->view_settings,
- &scene->display_settings);
+ IMB_colormanagement_imbuf_make_display_space(
+ display_ibuf, &scene->view_settings, &scene->display_settings);
- scope = make_scope_cb(display_ibuf);
+ scope = make_scope_cb(display_ibuf);
- IMB_freeImBuf(display_ibuf);
+ IMB_freeImBuf(display_ibuf);
- return scope;
+ return scope;
}
static void sequencer_display_size(Scene *scene, float r_viewrect[2])
{
- r_viewrect[0] = (float)scene->r.xsch;
- r_viewrect[1] = (float)scene->r.ysch;
+ r_viewrect[0] = (float)scene->r.xsch;
+ r_viewrect[1] = (float)scene->r.ysch;
- /* Aspect ratio seems to have no effect on output image*/
- /* r_viewrect[0] *= scene->r.xasp / scene->r.yasp; */
+ /* Aspect ratio seems to have no effect on output image*/
+ /* r_viewrect[0] *= scene->r.xasp / scene->r.yasp; */
}
static void sequencer_draw_gpencil(const bContext *C)
{
- /* draw grease-pencil (image aligned) */
- ED_annotation_draw_2dimage(C);
+ /* draw grease-pencil (image aligned) */
+ ED_annotation_draw_2dimage(C);
- /* ortho at pixel level */
- UI_view2d_view_restore(C);
+ /* ortho at pixel level */
+ UI_view2d_view_restore(C);
- /* draw grease-pencil (screen aligned) */
- ED_annotation_draw_view2d(C, 0);
+ /* draw grease-pencil (screen aligned) */
+ ED_annotation_draw_view2d(C, 0);
}
/* draws content borders plus safety borders if needed */
static void sequencer_draw_borders(const SpaceSeq *sseq, const View2D *v2d, const Scene *scene)
{
- float x1 = v2d->tot.xmin;
- float y1 = v2d->tot.ymin;
- float x2 = v2d->tot.xmax;
- float y2 = v2d->tot.ymax;
+ float x1 = v2d->tot.xmin;
+ float y1 = v2d->tot.ymin;
+ float x2 = v2d->tot.xmax;
+ float y2 = v2d->tot.ymax;
- GPU_line_width(1.0f);
+ GPU_line_width(1.0f);
- /* border */
- const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ /* border */
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
- immUniformThemeColor(TH_BACK);
- immUniform1i("colors_len", 0); /* Simple dashes. */
- immUniform1f("dash_width", 6.0f);
- immUniform1f("dash_factor", 0.5f);
+ immUniformThemeColor(TH_BACK);
+ immUniform1i("colors_len", 0); /* Simple dashes. */
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
- imm_draw_box_wire_2d(shdr_pos, x1 - 0.5f, y1 - 0.5f, x2 + 0.5f, y2 + 0.5f);
+ imm_draw_box_wire_2d(shdr_pos, x1 - 0.5f, y1 - 0.5f, x2 + 0.5f, y2 + 0.5f);
- /* safety border */
- if (sseq->flag & SEQ_SHOW_SAFE_MARGINS) {
- immUniformThemeColorBlend(TH_VIEW_OVERLAY, TH_BACK, 0.25f);
+ /* safety border */
+ if (sseq->flag & SEQ_SHOW_SAFE_MARGINS) {
+ immUniformThemeColorBlend(TH_VIEW_OVERLAY, TH_BACK, 0.25f);
- UI_draw_safe_areas(
- shdr_pos, x1, x2, y1, y2,
- scene->safe_areas.title,
- scene->safe_areas.action);
+ UI_draw_safe_areas(
+ shdr_pos, x1, x2, y1, y2, scene->safe_areas.title, scene->safe_areas.action);
- if (sseq->flag & SEQ_SHOW_SAFE_CENTER) {
- UI_draw_safe_areas(
- shdr_pos, x1, x2, y1, y2,
- scene->safe_areas.title_center,
- scene->safe_areas.action_center);
- }
- }
+ if (sseq->flag & SEQ_SHOW_SAFE_CENTER) {
+ UI_draw_safe_areas(shdr_pos,
+ x1,
+ x2,
+ y1,
+ y2,
+ scene->safe_areas.title_center,
+ scene->safe_areas.action_center);
+ }
+ }
- immUnbindProgram();
+ immUnbindProgram();
}
#if 0
void sequencer_draw_maskedit(const bContext *C, Scene *scene, ARegion *ar, 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 */
-
- // if (sc->mode == SC_MODE_MASKEDIT)
- if (0 && sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
- Mask *mask = BKE_sequencer_mask_get(scene);
-
- if (mask) {
- int width, height;
- float aspx = 1.0f, aspy = 1.0f;
- // ED_mask_get_size(C, &width, &height);
-
- //Scene *scene = CTX_data_scene(C);
- width = (scene->r.size * scene->r.xsch) / 100;
- height = (scene->r.size * scene->r.ysch) / 100;
-
- ED_mask_draw_region(
- mask, ar,
- 0, 0, 0, /* TODO */
- width, height,
- aspx, aspy,
- false, true,
- NULL, C);
- }
- }
+ /* 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) {
+ Mask *mask = BKE_sequencer_mask_get(scene);
+
+ if (mask) {
+ int width, height;
+ float aspx = 1.0f, aspy = 1.0f;
+ // ED_mask_get_size(C, &width, &height);
+
+ //Scene *scene = CTX_data_scene(C);
+ width = (scene->r.size * scene->r.xsch) / 100;
+ height = (scene->r.size * scene->r.ysch) / 100;
+
+ ED_mask_draw_region(
+ mask, ar,
+ 0, 0, 0, /* TODO */
+ width, height,
+ aspx, aspy,
+ false, true,
+ NULL, C);
+ }
+ }
}
#endif
-static void *sequencer_OCIO_transform_ibuf(const bContext *C, ImBuf *ibuf, bool *glsl_used, int *format, int *type)
+static void *sequencer_OCIO_transform_ibuf(
+ const bContext *C, ImBuf *ibuf, bool *glsl_used, int *format, int *type)
{
- void *display_buffer;
- void *cache_handle = NULL;
- bool force_fallback = false;
- *glsl_used = false;
- force_fallback |= (U.image_draw_method != IMAGE_DRAW_METHOD_GLSL);
- force_fallback |= (ibuf->dither != 0.0f);
-
- if (force_fallback) {
- /* Fallback to CPU based color space conversion */
- *glsl_used = false;
- *format = GL_RGBA;
- *type = GL_UNSIGNED_BYTE;
- display_buffer = NULL;
- }
- else if (ibuf->rect_float) {
- display_buffer = ibuf->rect_float;
-
- if (ibuf->channels == 4) {
- *format = GL_RGBA;
- }
- else if (ibuf->channels == 3) {
- *format = GL_RGB;
- }
- else {
- BLI_assert(!"Incompatible number of channels for float buffer in sequencer");
- *format = GL_RGBA;
- display_buffer = NULL;
- }
-
- *type = GL_FLOAT;
-
- if (ibuf->float_colorspace) {
- *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);
- }
- }
- else if (ibuf->rect) {
- display_buffer = ibuf->rect;
- *format = GL_RGBA;
- *type = GL_UNSIGNED_BYTE;
-
- *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;
- 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) {
- display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
- *format = GL_RGBA;
- *type = GL_UNSIGNED_BYTE;
- }
- if (cache_handle) {
- IMB_display_buffer_release(cache_handle);
- }
-
- return display_buffer;
+ void *display_buffer;
+ void *cache_handle = NULL;
+ bool force_fallback = false;
+ *glsl_used = false;
+ force_fallback |= (U.image_draw_method != IMAGE_DRAW_METHOD_GLSL);
+ force_fallback |= (ibuf->dither != 0.0f);
+
+ if (force_fallback) {
+ /* Fallback to CPU based color space conversion */
+ *glsl_used = false;
+ *format = GL_RGBA;
+ *type = GL_UNSIGNED_BYTE;
+ display_buffer = NULL;
+ }
+ else if (ibuf->rect_float) {
+ display_buffer = ibuf->rect_float;
+
+ if (ibuf->channels == 4) {
+ *format = GL_RGBA;
+ }
+ else if (ibuf->channels == 3) {
+ *format = GL_RGB;
+ }
+ else {
+ BLI_assert(!"Incompatible number of channels for float buffer in sequencer");
+ *format = GL_RGBA;
+ display_buffer = NULL;
+ }
+
+ *type = GL_FLOAT;
+
+ if (ibuf->float_colorspace) {
+ *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);
+ }
+ }
+ else if (ibuf->rect) {
+ display_buffer = ibuf->rect;
+ *format = GL_RGBA;
+ *type = GL_UNSIGNED_BYTE;
+
+ *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;
+ 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) {
+ display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
+ *format = GL_RGBA;
+ *type = GL_UNSIGNED_BYTE;
+ }
+ if (cache_handle) {
+ IMB_display_buffer_release(cache_handle);
+ }
+
+ return display_buffer;
}
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
- */
- 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
- */
- WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_RENDER_PREVIEW);
- }
+ 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
+ */
+ 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
+ */
+ WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_RENDER_PREVIEW);
+ }
}
static void sequencer_preview_clear(void)
{
- float col[3];
+ float col[3];
- UI_GetThemeColor3fv(TH_SEQ_PREVIEW, col);
- GPU_clear_color(col[0], col[1], col[2], 0.0);
- GPU_clear(GPU_COLOR_BIT);
+ UI_GetThemeColor3fv(TH_SEQ_PREVIEW, col);
+ GPU_clear_color(col[0], col[1], col[2], 0.0);
+ GPU_clear(GPU_COLOR_BIT);
}
-static void sequencer_preview_get_rect(
- rctf *preview, Scene *scene, ARegion *ar, SpaceSeq *sseq,
- bool draw_overlay, bool draw_backdrop)
+static void sequencer_preview_get_rect(rctf *preview,
+ Scene *scene,
+ ARegion *ar,
+ SpaceSeq *sseq,
+ bool draw_overlay,
+ bool draw_backdrop)
{
- struct View2D *v2d = &ar->v2d;
- float viewrect[2];
-
- sequencer_display_size(scene, viewrect);
- BLI_rctf_init(preview, -1.0f, 1.0f, -1.0f, 1.0f);
-
- if (draw_overlay && sseq->overlay_type == SEQ_DRAW_OVERLAY_RECT) {
- preview->xmax = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmax);
- preview->xmin = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmin);
- preview->ymax = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymax);
- preview->ymin = v2d->tot.ymin + (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 image_aspect = viewrect[0] / viewrect[1];
-
- if (aspect >= image_aspect) {
- preview->xmax = image_aspect / aspect;
- preview->xmin = -preview->xmax;
- }
- else {
- preview->ymax = aspect / image_aspect;
- preview->ymin = -preview->ymax;
- }
- }
- else {
- *preview = v2d->tot;
- }
+ struct View2D *v2d = &ar->v2d;
+ float viewrect[2];
+
+ sequencer_display_size(scene, viewrect);
+ BLI_rctf_init(preview, -1.0f, 1.0f, -1.0f, 1.0f);
+
+ if (draw_overlay && sseq->overlay_type == SEQ_DRAW_OVERLAY_RECT) {
+ preview->xmax = v2d->tot.xmin +
+ (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmax);
+ preview->xmin = v2d->tot.xmin +
+ (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmin);
+ preview->ymax = v2d->tot.ymin +
+ (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymax);
+ preview->ymin = v2d->tot.ymin +
+ (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 image_aspect = viewrect[0] / viewrect[1];
+
+ if (aspect >= image_aspect) {
+ preview->xmax = image_aspect / aspect;
+ preview->xmin = -preview->xmax;
+ }
+ else {
+ preview->ymax = aspect / image_aspect;
+ preview->ymin = -preview->ymax;
+ }
+ }
+ else {
+ *preview = v2d->tot;
+ }
}
-static void sequencer_draw_display_buffer(
- const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, ImBuf *ibuf, ImBuf *scope,
- bool draw_overlay, bool draw_backdrop)
+static void sequencer_draw_display_buffer(const bContext *C,
+ Scene *scene,
+ ARegion *ar,
+ SpaceSeq *sseq,
+ ImBuf *ibuf,
+ ImBuf *scope,
+ bool draw_overlay,
+ bool draw_backdrop)
{
- void *display_buffer;
-
- if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- }
-
- /* Format needs to be created prior to any immBindProgram call.
- * Do it here because OCIO binds it's own shader.
- */
- int format, type;
- bool glsl_used = false;
- GLuint texid;
- GPUVertFormat *imm_format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(imm_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint texCoord = GPU_vertformat_attr_add(imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- if (scope) {
- ibuf = scope;
-
- if (ibuf->rect_float && ibuf->rect == NULL) {
- IMB_rect_from_float(ibuf);
- }
-
- display_buffer = (unsigned char *)ibuf->rect;
- format = GL_RGBA;
- type = GL_UNSIGNED_BYTE;
- }
- else {
- display_buffer = sequencer_OCIO_transform_ibuf(C, ibuf, &glsl_used, &format, &type);
- }
-
- if (draw_backdrop) {
- GPU_matrix_push();
- GPU_matrix_identity_set();
- GPU_matrix_push_projection();
- GPU_matrix_identity_projection_set();
- }
-
- glGenTextures(1, (GLuint *)&texid);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, texid);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
- if (type == GL_FLOAT) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, ibuf->x, ibuf->y, 0, format, type, display_buffer);
- }
- else {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, format, type, display_buffer);
- }
-
- if (!glsl_used) {
- immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
- immUniformColor3f(1.0f, 1.0f, 1.0f);
- immUniform1i("image", 0);
- }
-
- immBegin(GPU_PRIM_TRI_FAN, 4);
-
- rctf preview;
- rctf canvas;
- sequencer_preview_get_rect(&preview, scene, ar, sseq, draw_overlay, draw_backdrop);
-
- if (draw_overlay && sseq->overlay_type == SEQ_DRAW_OVERLAY_RECT) {
- canvas = scene->ed->over_border;
- }
- else {
- BLI_rctf_init(&canvas, 0.0f, 1.0f, 0.0f, 1.0f);
- }
-
- immAttr2f(texCoord, canvas.xmin, canvas.ymin);
- immVertex2f(pos, preview.xmin, preview.ymin);
-
- immAttr2f(texCoord, canvas.xmin, canvas.ymax);
- immVertex2f(pos, preview.xmin, preview.ymax);
-
- immAttr2f(texCoord, canvas.xmax, canvas.ymax);
- immVertex2f(pos, preview.xmax, preview.ymax);
-
- immAttr2f(texCoord, canvas.xmax, canvas.ymin);
- immVertex2f(pos, preview.xmax, preview.ymin);
-
- immEnd();
- glBindTexture(GL_TEXTURE_2D, 0);
- glDeleteTextures(1, &texid);
-
- if (!glsl_used) {
- immUnbindProgram();
- }
- else {
- IMB_colormanagement_finish_glsl_draw();
- }
-
- if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
- GPU_blend(false);
- }
-
- if (draw_backdrop) {
- GPU_matrix_pop();
- GPU_matrix_pop_projection();
- }
+ void *display_buffer;
+
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ }
+
+ /* Format needs to be created prior to any immBindProgram call.
+ * Do it here because OCIO binds it's own shader.
+ */
+ int format, type;
+ bool glsl_used = false;
+ GLuint texid;
+ GPUVertFormat *imm_format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(imm_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint texCoord = GPU_vertformat_attr_add(
+ imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ if (scope) {
+ ibuf = scope;
+
+ if (ibuf->rect_float && ibuf->rect == NULL) {
+ IMB_rect_from_float(ibuf);
+ }
+
+ display_buffer = (unsigned char *)ibuf->rect;
+ format = GL_RGBA;
+ type = GL_UNSIGNED_BYTE;
+ }
+ else {
+ display_buffer = sequencer_OCIO_transform_ibuf(C, ibuf, &glsl_used, &format, &type);
+ }
+
+ if (draw_backdrop) {
+ GPU_matrix_push();
+ GPU_matrix_identity_set();
+ GPU_matrix_push_projection();
+ GPU_matrix_identity_projection_set();
+ }
+
+ glGenTextures(1, (GLuint *)&texid);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, texid);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ if (type == GL_FLOAT) {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, ibuf->x, ibuf->y, 0, format, type, display_buffer);
+ }
+ else {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, format, type, display_buffer);
+ }
+
+ if (!glsl_used) {
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
+ immUniform1i("image", 0);
+ }
+
+ immBegin(GPU_PRIM_TRI_FAN, 4);
+
+ rctf preview;
+ rctf canvas;
+ sequencer_preview_get_rect(&preview, scene, ar, sseq, draw_overlay, draw_backdrop);
+
+ if (draw_overlay && sseq->overlay_type == SEQ_DRAW_OVERLAY_RECT) {
+ canvas = scene->ed->over_border;
+ }
+ else {
+ BLI_rctf_init(&canvas, 0.0f, 1.0f, 0.0f, 1.0f);
+ }
+
+ immAttr2f(texCoord, canvas.xmin, canvas.ymin);
+ immVertex2f(pos, preview.xmin, preview.ymin);
+
+ immAttr2f(texCoord, canvas.xmin, canvas.ymax);
+ immVertex2f(pos, preview.xmin, preview.ymax);
+
+ immAttr2f(texCoord, canvas.xmax, canvas.ymax);
+ immVertex2f(pos, preview.xmax, preview.ymax);
+
+ immAttr2f(texCoord, canvas.xmax, canvas.ymin);
+ immVertex2f(pos, preview.xmax, preview.ymin);
+
+ immEnd();
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDeleteTextures(1, &texid);
+
+ if (!glsl_used) {
+ immUnbindProgram();
+ }
+ else {
+ IMB_colormanagement_finish_glsl_draw();
+ }
+
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
+ GPU_blend(false);
+ }
+
+ if (draw_backdrop) {
+ GPU_matrix_pop();
+ GPU_matrix_pop_projection();
+ }
}
static ImBuf *sequencer_get_scope(Scene *scene, SpaceSeq *sseq, ImBuf *ibuf, bool draw_backdrop)
{
- struct ImBuf *scope = NULL;
- SequencerScopes *scopes = &sseq->scopes;
-
- if (!draw_backdrop && (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0)) {
- sequencer_check_scopes(scopes, ibuf);
-
-
- switch (sseq->mainb) {
- case SEQ_DRAW_IMG_IMBUF:
- if (!scopes->zebra_ibuf) {
- ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
-
- if (display_ibuf->rect_float) {
- IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings,
- &scene->display_settings);
- }
- scopes->zebra_ibuf = make_zebra_view_from_ibuf(display_ibuf, sseq->zebra);
- IMB_freeImBuf(display_ibuf);
- }
- scope = scopes->zebra_ibuf;
- break;
- case SEQ_DRAW_IMG_WAVEFORM:
- if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) {
- if (!scopes->sep_waveform_ibuf) {
- scopes->sep_waveform_ibuf = sequencer_make_scope(scene, ibuf, make_sep_waveform_view_from_ibuf);
- }
- scope = scopes->sep_waveform_ibuf;
- }
- else {
- if (!scopes->waveform_ibuf) {
- scopes->waveform_ibuf = sequencer_make_scope(scene, ibuf, make_waveform_view_from_ibuf);
- }
- scope = scopes->waveform_ibuf;
- }
- break;
- case SEQ_DRAW_IMG_VECTORSCOPE:
- if (!scopes->vector_ibuf) {
- scopes->vector_ibuf = sequencer_make_scope(scene, ibuf, make_vectorscope_view_from_ibuf);
- }
- scope = scopes->vector_ibuf;
- break;
- case SEQ_DRAW_IMG_HISTOGRAM:
- if (!scopes->histogram_ibuf) {
- scopes->histogram_ibuf = sequencer_make_scope(scene, ibuf, make_histogram_view_from_ibuf);
- }
- scope = scopes->histogram_ibuf;
- break;
- }
-
- /* future files may have new scopes we don't catch above */
- if (scope) {
- scopes->reference_ibuf = ibuf;
- }
- }
- return scope;
+ struct ImBuf *scope = NULL;
+ SequencerScopes *scopes = &sseq->scopes;
+
+ if (!draw_backdrop && (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0)) {
+ sequencer_check_scopes(scopes, ibuf);
+
+ switch (sseq->mainb) {
+ case SEQ_DRAW_IMG_IMBUF:
+ if (!scopes->zebra_ibuf) {
+ ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
+
+ if (display_ibuf->rect_float) {
+ IMB_colormanagement_imbuf_make_display_space(
+ display_ibuf, &scene->view_settings, &scene->display_settings);
+ }
+ scopes->zebra_ibuf = make_zebra_view_from_ibuf(display_ibuf, sseq->zebra);
+ IMB_freeImBuf(display_ibuf);
+ }
+ scope = scopes->zebra_ibuf;
+ break;
+ case SEQ_DRAW_IMG_WAVEFORM:
+ if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) {
+ if (!scopes->sep_waveform_ibuf) {
+ scopes->sep_waveform_ibuf = sequencer_make_scope(
+ scene, ibuf, make_sep_waveform_view_from_ibuf);
+ }
+ scope = scopes->sep_waveform_ibuf;
+ }
+ else {
+ if (!scopes->waveform_ibuf) {
+ scopes->waveform_ibuf = sequencer_make_scope(
+ scene, ibuf, make_waveform_view_from_ibuf);
+ }
+ scope = scopes->waveform_ibuf;
+ }
+ break;
+ case SEQ_DRAW_IMG_VECTORSCOPE:
+ if (!scopes->vector_ibuf) {
+ scopes->vector_ibuf = sequencer_make_scope(scene, ibuf, make_vectorscope_view_from_ibuf);
+ }
+ scope = scopes->vector_ibuf;
+ break;
+ case SEQ_DRAW_IMG_HISTOGRAM:
+ if (!scopes->histogram_ibuf) {
+ scopes->histogram_ibuf = sequencer_make_scope(
+ scene, ibuf, make_histogram_view_from_ibuf);
+ }
+ scope = scopes->histogram_ibuf;
+ break;
+ }
+
+ /* future files may have new scopes we don't catch above */
+ if (scope) {
+ scopes->reference_ibuf = ibuf;
+ }
+ }
+ return scope;
}
-void sequencer_draw_preview(
- const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq,
- int cfra, int frame_ofs,
- bool draw_overlay, bool draw_backdrop)
+void sequencer_draw_preview(const bContext *C,
+ Scene *scene,
+ ARegion *ar,
+ SpaceSeq *sseq,
+ int cfra,
+ int frame_ofs,
+ bool draw_overlay,
+ bool draw_backdrop)
{
- struct Main *bmain = CTX_data_main(C);
- struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
- struct View2D *v2d = &ar->v2d;
- struct ImBuf *ibuf = NULL;
- struct ImBuf *scope = NULL;
- float viewrect[2];
- const bool show_imbuf = ED_space_sequencer_check_show_imbuf(sseq);
- const bool draw_gpencil = ((sseq->flag & SEQ_SHOW_GPENCIL) && sseq->gpd);
- const char *names[2] = { STEREO_LEFT_NAME, STEREO_RIGHT_NAME };
-
- sequencer_stop_running_jobs(C, scene);
- if (G.is_rendering) {
- return;
- }
-
- if (sseq->render_size == SEQ_PROXY_RENDER_SIZE_NONE) {
- sequencer_preview_clear();
- return;
- }
-
- /* 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 */
- if (!draw_backdrop && (!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE)) {
- sequencer_preview_clear();
-
- if (sseq->flag & SEQ_USE_ALPHA) {
- imm_draw_box_checker_2d(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
- }
- }
- /* 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 over image */
- if (sseq->flag & SEQ_SHOW_METADATA) {
- ED_region_image_metadata_draw(0.0, 0.0, ibuf, &v2d->tot, 1.0, 1.0);
- }
- }
-
- if (show_imbuf) {
- sequencer_draw_borders(sseq, v2d, scene);
- }
-
- if (draw_gpencil && show_imbuf) {
- sequencer_draw_gpencil(C);
- }
-
- /* 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. */
- if (ibuf) {
- IMB_freeImBuf(ibuf);
- }
-
- UI_view2d_view_restore(C);
+ struct Main *bmain = CTX_data_main(C);
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ struct View2D *v2d = &ar->v2d;
+ struct ImBuf *ibuf = NULL;
+ struct ImBuf *scope = NULL;
+ float viewrect[2];
+ const bool show_imbuf = ED_space_sequencer_check_show_imbuf(sseq);
+ const bool draw_gpencil = ((sseq->flag & SEQ_SHOW_GPENCIL) && sseq->gpd);
+ const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
+
+ sequencer_stop_running_jobs(C, scene);
+ if (G.is_rendering) {
+ return;
+ }
+
+ if (sseq->render_size == SEQ_PROXY_RENDER_SIZE_NONE) {
+ sequencer_preview_clear();
+ return;
+ }
+
+ /* 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 */
+ if (!draw_backdrop && (!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE)) {
+ sequencer_preview_clear();
+
+ if (sseq->flag & SEQ_USE_ALPHA) {
+ imm_draw_box_checker_2d(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
+ }
+ }
+ /* 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 over image */
+ if (sseq->flag & SEQ_SHOW_METADATA) {
+ ED_region_image_metadata_draw(0.0, 0.0, ibuf, &v2d->tot, 1.0, 1.0);
+ }
+ }
+
+ if (show_imbuf) {
+ sequencer_draw_borders(sseq, v2d, scene);
+ }
+
+ if (draw_gpencil && show_imbuf) {
+ sequencer_draw_gpencil(C);
+ }
+
+ /* 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. */
+ if (ibuf) {
+ IMB_freeImBuf(ibuf);
+ }
+
+ UI_view2d_view_restore(C);
}
#if 0
void drawprefetchseqspace(Scene *scene, ARegion *UNUSED(ar), SpaceSeq *sseq)
{
- int rectx, recty;
- int render_size = sseq->render_size;
- int proxy_size = 100.0;
- if (render_size == 0) {
- render_size = scene->r.size;
- }
- else {
- proxy_size = render_size;
- }
- if (render_size < 0) {
- return;
- }
-
- rectx = (render_size * scene->r.xsch) / 100;
- recty = (render_size * scene->r.ysch) / 100;
-
- if (sseq->mainb != SEQ_DRAW_SEQUENCE) {
- give_ibuf_prefetch_request(
- rectx, recty, (scene->r.cfra), sseq->chanshown,
- proxy_size);
- }
+ int rectx, recty;
+ int render_size = sseq->render_size;
+ int proxy_size = 100.0;
+ if (render_size == 0) {
+ render_size = scene->r.size;
+ }
+ else {
+ proxy_size = render_size;
+ }
+ if (render_size < 0) {
+ return;
+ }
+
+ rectx = (render_size * scene->r.xsch) / 100;
+ recty = (render_size * scene->r.ysch) / 100;
+
+ if (sseq->mainb != SEQ_DRAW_SEQUENCE) {
+ give_ibuf_prefetch_request(
+ rectx, recty, (scene->r.cfra), sseq->chanshown,
+ proxy_size);
+ }
}
#endif
/* draw backdrop of the sequencer strips view */
static void draw_seq_backdrop(View2D *v2d)
{
- int i;
-
- 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 */
- immUniformThemeColorShade(TH_BACK, -20);
- immRectf(pos, v2d->cur.xmin, -1.0, v2d->cur.xmax, 1.0);
-
- /* Alternating horizontal stripes */
- i = max_ii(1, ((int)v2d->cur.ymin) - 1);
-
- while (i < v2d->cur.ymax) {
- if (i & 1) {
- immUniformThemeColorShade(TH_BACK, -15);
- }
- else {
- immUniformThemeColorShade(TH_BACK, -25);
- }
-
- immRectf(pos, v2d->cur.xmin, i, v2d->cur.xmax, i + 1);
-
- i++;
- }
-
- /* 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);
- immBegin(GPU_PRIM_LINES, line_len * 2);
- while (line_len--) {
- immVertex2f(pos, v2d->cur.xmax, i);
- immVertex2f(pos, v2d->cur.xmin, i);
- }
- immEnd();
-
- immUnbindProgram();
+ int i;
+
+ 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 */
+ immUniformThemeColorShade(TH_BACK, -20);
+ immRectf(pos, v2d->cur.xmin, -1.0, v2d->cur.xmax, 1.0);
+
+ /* Alternating horizontal stripes */
+ i = max_ii(1, ((int)v2d->cur.ymin) - 1);
+
+ while (i < v2d->cur.ymax) {
+ if (i & 1) {
+ immUniformThemeColorShade(TH_BACK, -15);
+ }
+ else {
+ immUniformThemeColorShade(TH_BACK, -25);
+ }
+
+ immRectf(pos, v2d->cur.xmin, i, v2d->cur.xmax, i + 1);
+
+ i++;
+ }
+
+ /* 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);
+ immBegin(GPU_PRIM_LINES, line_len * 2);
+ while (line_len--) {
+ immVertex2f(pos, v2d->cur.xmax, i);
+ immVertex2f(pos, v2d->cur.xmin, i);
+ }
+ immEnd();
+
+ immUnbindProgram();
}
/* draw the contents of the sequencer strips view */
static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
{
- Scene *scene = CTX_data_scene(C);
- View2D *v2d = &ar->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 */
- 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 */
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- /* boundbox and selection tests for NOT drawing the strip... */
- if ((seq->flag & SELECT) != sel) { continue; }
- else if (seq == last_seq) { continue; }
- else if (min_ii(seq->startdisp, seq->start) > v2d->cur.xmax) { continue; }
- else if (max_ii(seq->enddisp, seq->start + seq->len) < v2d->cur.xmin) { continue; }
- else if (seq->machine + 1.0f < v2d->cur.ymin) { continue; }
- else if (seq->machine > v2d->cur.ymax) { continue; }
-
- /* strip passed all tests unscathed... so draw it now */
- draw_seq_strip(C, sseq, scene, ar, seq, outline_tint, pixelx);
- }
-
- /* 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);
- }
-
- /* draw highlight when previewing a single strip */
- if (special_seq_update) {
- const Sequence *seq = special_seq_update;
- 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, seq->startdisp, seq->machine + SEQ_STRIP_OFSBOTTOM, seq->enddisp, seq->machine + SEQ_STRIP_OFSTOP);
-
- immUnbindProgram();
-
- GPU_blend(false);
- }
+ Scene *scene = CTX_data_scene(C);
+ View2D *v2d = &ar->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 */
+ 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 */
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ /* boundbox and selection tests for NOT drawing the strip... */
+ if ((seq->flag & SELECT) != sel) {
+ continue;
+ }
+ else if (seq == last_seq) {
+ continue;
+ }
+ else if (min_ii(seq->startdisp, seq->start) > v2d->cur.xmax) {
+ continue;
+ }
+ else if (max_ii(seq->enddisp, seq->start + seq->len) < v2d->cur.xmin) {
+ continue;
+ }
+ else if (seq->machine + 1.0f < v2d->cur.ymin) {
+ continue;
+ }
+ else if (seq->machine > v2d->cur.ymax) {
+ continue;
+ }
+
+ /* strip passed all tests unscathed... so draw it now */
+ draw_seq_strip(C, sseq, scene, ar, seq, outline_tint, pixelx);
+ }
+
+ /* 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);
+ }
+
+ /* draw highlight when previewing a single strip */
+ if (special_seq_update) {
+ const Sequence *seq = special_seq_update;
+ 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,
+ seq->startdisp,
+ seq->machine + SEQ_STRIP_OFSBOTTOM,
+ seq->enddisp,
+ seq->machine + SEQ_STRIP_OFSTOP);
+
+ immUnbindProgram();
+
+ GPU_blend(false);
+ }
}
static void seq_draw_sfra_efra(Scene *scene, View2D *v2d)
{
- const Editing *ed = BKE_sequencer_editing_get(scene, false);
- const int frame_sta = PSFRA;
- const int frame_end = PEFRA + 1;
+ const Editing *ed = BKE_sequencer_editing_get(scene, false);
+ const int frame_sta = PSFRA;
+ const int frame_end = PEFRA + 1;
- GPU_blend(true);
+ GPU_blend(true);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ 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 */
- immUniformThemeColorShadeAlpha(TH_BACK, -25, -100);
+ /* draw darkened area outside of active timeline
+ * frame range used is preview range or scene range */
+ immUniformThemeColorShadeAlpha(TH_BACK, -25, -100);
- if (frame_sta < frame_end) {
- immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)frame_sta, v2d->cur.ymax);
- immRectf(pos, (float)frame_end, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
- }
- else {
- immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
- }
+ if (frame_sta < frame_end) {
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)frame_sta, v2d->cur.ymax);
+ immRectf(pos, (float)frame_end, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ }
+ else {
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ }
- immUniformThemeColorShade(TH_BACK, -60);
+ immUniformThemeColorShade(TH_BACK, -60);
- /* thin lines where the actual frames are */
- immBegin(GPU_PRIM_LINES, 4);
+ /* thin lines where the actual frames are */
+ immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, frame_sta, v2d->cur.ymin);
- immVertex2f(pos, frame_sta, v2d->cur.ymax);
+ immVertex2f(pos, frame_sta, v2d->cur.ymin);
+ immVertex2f(pos, frame_sta, v2d->cur.ymax);
- immVertex2f(pos, frame_end, v2d->cur.ymin);
- immVertex2f(pos, frame_end, v2d->cur.ymax);
+ immVertex2f(pos, frame_end, v2d->cur.ymin);
+ immVertex2f(pos, frame_end, v2d->cur.ymax);
- immEnd();
+ immEnd();
- if (ed && !BLI_listbase_is_empty(&ed->metastack)) {
- MetaStack *ms = ed->metastack.last;
+ if (ed && !BLI_listbase_is_empty(&ed->metastack)) {
+ MetaStack *ms = ed->metastack.last;
- immUniformColor4ub(255, 255, 255, 8);
- immRectf(pos, ms->disp_range[0], v2d->cur.ymin, ms->disp_range[1], v2d->cur.ymax);
+ immUniformColor4ub(255, 255, 255, 8);
+ immRectf(pos, ms->disp_range[0], v2d->cur.ymin, ms->disp_range[1], v2d->cur.ymax);
- immUniformThemeColorShade(TH_BACK, -40);
+ immUniformThemeColorShade(TH_BACK, -40);
- immBegin(GPU_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, ms->disp_range[0], v2d->cur.ymin);
- immVertex2f(pos, ms->disp_range[0], v2d->cur.ymax);
+ immVertex2f(pos, ms->disp_range[0], v2d->cur.ymin);
+ immVertex2f(pos, ms->disp_range[0], v2d->cur.ymax);
- immVertex2f(pos, ms->disp_range[1], v2d->cur.ymin);
- immVertex2f(pos, ms->disp_range[1], v2d->cur.ymax);
+ immVertex2f(pos, ms->disp_range[1], v2d->cur.ymin);
+ immVertex2f(pos, ms->disp_range[1], v2d->cur.ymax);
- immEnd();
- }
+ immEnd();
+ }
- immUnbindProgram();
+ immUnbindProgram();
- GPU_blend(false);
+ GPU_blend(false);
}
/* Draw Timeline/Strip Editor Mode for Sequencer */
void draw_timeline_seq(const bContext *C, ARegion *ar)
{
- 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;
- View2DScrollers *scrollers;
- short unit = 0, cfra_flag = 0;
- float col[3];
-
- /* 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);
- }
- else {
- GPU_clear_color(col[0], col[1], col[2], 0.0f);
- }
- GPU_clear(GPU_COLOR_BIT);
-
- UI_view2d_view_ortho(v2d);
-
-
- /* calculate extents of sequencer strips/data
- * NOTE: needed for the scrollers later
- */
- 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. */
- 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);
- UI_view2d_view_ortho(v2d);
- }
-
- ED_region_draw_cb_draw(C, ar, 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);
- }
-
- /* 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_MARKER_LINES) {
- marker_draw_flag |= DRAW_MARKERS_LINES;
- }
- ED_markers_draw(C, marker_draw_flag);
-
- /* preview range */
- UI_view2d_view_ortho(v2d);
- ANIM_draw_previewrange(C, v2d, 1);
-
- /* 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 : scene->r.cfra + scene->ed->over_ofs;
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- immUniformColor3f(0.2f, 0.2f, 0.2f);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, cfra_over, v2d->cur.ymin);
- immVertex2f(pos, cfra_over, v2d->cur.ymax);
- immEnd();
-
- immUnbindProgram();
- }
-
- /* callback */
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
-
- /* reset view matrix */
- UI_view2d_view_restore(C);
-
- /* scrollers */
- unit = (sseq->flag & SEQ_DRAWFRAMES) ? V2D_UNIT_FRAMES : V2D_UNIT_SECONDS;
- scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, unit, V2D_GRID_CLAMP, V2D_UNIT_VALUES, V2D_GRID_CLAMP);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
-
- /* draw current frame number-indicator on top of scrollers */
- if ((sseq->flag & SEQ_NO_DRAW_CFRANUM) == 0) {
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- ANIM_draw_cfra_number(C, v2d, cfra_flag);
- }
+ 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;
+ View2DScrollers *scrollers;
+ short unit = 0, cfra_flag = 0;
+ float col[3];
+
+ /* 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);
+ }
+ else {
+ GPU_clear_color(col[0], col[1], col[2], 0.0f);
+ }
+ GPU_clear(GPU_COLOR_BIT);
+
+ UI_view2d_view_ortho(v2d);
+
+ /* calculate extents of sequencer strips/data
+ * NOTE: needed for the scrollers later
+ */
+ 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. */
+ 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);
+ UI_view2d_view_ortho(v2d);
+ }
+
+ ED_region_draw_cb_draw(C, ar, 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);
+ }
+
+ /* 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_MARKER_LINES) {
+ marker_draw_flag |= DRAW_MARKERS_LINES;
+ }
+ ED_markers_draw(C, marker_draw_flag);
+
+ /* preview range */
+ UI_view2d_view_ortho(v2d);
+ ANIM_draw_previewrange(C, v2d, 1);
+
+ /* 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 :
+ scene->r.cfra + scene->ed->over_ofs;
+
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3f(0.2f, 0.2f, 0.2f);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, cfra_over, v2d->cur.ymin);
+ immVertex2f(pos, cfra_over, v2d->cur.ymax);
+ immEnd();
+
+ immUnbindProgram();
+ }
+
+ /* callback */
+ ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ unit = (sseq->flag & SEQ_DRAWFRAMES) ? V2D_UNIT_FRAMES : V2D_UNIT_SECONDS;
+ scrollers = UI_view2d_scrollers_calc(
+ C, v2d, NULL, unit, V2D_GRID_CLAMP, V2D_UNIT_VALUES, V2D_GRID_CLAMP);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+
+ /* draw current frame number-indicator on top of scrollers */
+ if ((sseq->flag & SEQ_NO_DRAW_CFRANUM) == 0) {
+ UI_view2d_view_orthoSpecial(ar, v2d, 1);
+ ANIM_draw_cfra_number(C, v2d, cfra_flag);
+ }
}
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 9e5a2624226..cf07e252404 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -21,7 +21,6 @@
* \ingroup spseq
*/
-
#include <stdlib.h>
#include <math.h>
#include <string.h>
@@ -71,25 +70,25 @@
/* XXX */
/* 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"},
- {SEQ_TYPE_SUB, "SUBTRACT", 0, "Subtract", "Subtract effect strip type"},
- {SEQ_TYPE_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", "Alpha Over effect strip type"},
- {SEQ_TYPE_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", "Alpha Under effect strip type"},
- {SEQ_TYPE_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", "Gamma Cross effect strip type"},
- {SEQ_TYPE_MUL, "MULTIPLY", 0, "Multiply", "Multiply effect strip type"},
- {SEQ_TYPE_OVERDROP, "OVER_DROP", 0, "Alpha Over Drop", "Alpha Over Drop effect strip type"},
- {SEQ_TYPE_WIPE, "WIPE", 0, "Wipe", "Wipe effect strip type"},
- {SEQ_TYPE_GLOW, "GLOW", 0, "Glow", "Glow effect strip type"},
- {SEQ_TYPE_TRANSFORM, "TRANSFORM", 0, "Transform", "Transform effect strip type"},
- {SEQ_TYPE_COLOR, "COLOR", 0, "Color", "Color effect strip type"},
- {SEQ_TYPE_SPEED, "SPEED", 0, "Speed", "Color effect strip type"},
- {SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
- {SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
- {SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
- {SEQ_TYPE_TEXT, "TEXT", 0, "Text", ""},
- {SEQ_TYPE_COLORMIX, "COLORMIX", 0, "Color Mix", ""},
- {0, NULL, 0, NULL, NULL},
+ {SEQ_TYPE_CROSS, "CROSS", 0, "Crossfade", "Crossfade effect strip type"},
+ {SEQ_TYPE_ADD, "ADD", 0, "Add", "Add effect strip type"},
+ {SEQ_TYPE_SUB, "SUBTRACT", 0, "Subtract", "Subtract effect strip type"},
+ {SEQ_TYPE_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", "Alpha Over effect strip type"},
+ {SEQ_TYPE_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", "Alpha Under effect strip type"},
+ {SEQ_TYPE_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", "Gamma Cross effect strip type"},
+ {SEQ_TYPE_MUL, "MULTIPLY", 0, "Multiply", "Multiply effect strip type"},
+ {SEQ_TYPE_OVERDROP, "OVER_DROP", 0, "Alpha Over Drop", "Alpha Over Drop effect strip type"},
+ {SEQ_TYPE_WIPE, "WIPE", 0, "Wipe", "Wipe effect strip type"},
+ {SEQ_TYPE_GLOW, "GLOW", 0, "Glow", "Glow effect strip type"},
+ {SEQ_TYPE_TRANSFORM, "TRANSFORM", 0, "Transform", "Transform effect strip type"},
+ {SEQ_TYPE_COLOR, "COLOR", 0, "Color", "Color effect strip type"},
+ {SEQ_TYPE_SPEED, "SPEED", 0, "Speed", "Color effect strip type"},
+ {SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
+ {SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
+ {SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
+ {SEQ_TYPE_TEXT, "TEXT", 0, "Text", ""},
+ {SEQ_TYPE_COLORMIX, "COLORMIX", 0, "Color Mix", ""},
+ {0, NULL, 0, NULL, NULL},
};
/* mute operator */
@@ -97,27 +96,27 @@ EnumPropertyItem sequencer_prop_effect_types[] = {
#define SEQ_SIDE_MOUSE -1
EnumPropertyItem prop_side_types[] = {
- {SEQ_SIDE_MOUSE, "MOUSE", 0, "Mouse position", "" },
- {SEQ_SIDE_LEFT, "LEFT", 0, "Left", "" },
- {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
- {SEQ_SIDE_BOTH, "BOTH", 0, "Both", ""},
- {0, NULL, 0, NULL, NULL},
+ {SEQ_SIDE_MOUSE, "MOUSE", 0, "Mouse position", ""},
+ {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""},
+ {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
+ {SEQ_SIDE_BOTH, "BOTH", 0, "Both", ""},
+ {0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem prop_side_lr_types[] = {
- {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""},
- {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
- {0, NULL, 0, NULL, NULL},
+ {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""},
+ {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
+ {0, NULL, 0, NULL, NULL},
};
typedef struct TransSeq {
- int start, machine;
- int startstill, endstill;
- int startdisp, enddisp;
- int startofs, endofs;
- int anim_startofs, anim_endofs;
- /* int final_left, final_right; */ /* UNUSED */
- int len;
+ int start, machine;
+ int startstill, endstill;
+ int startdisp, enddisp;
+ int startofs, endofs;
+ int anim_startofs, anim_endofs;
+ /* int final_left, final_right; */ /* UNUSED */
+ int len;
} TransSeq;
/* ********************************************************************** */
@@ -125,828 +124,831 @@ typedef struct TransSeq {
/* ***************** proxy job manager ********************** */
typedef struct ProxyBuildJob {
- struct Main *main;
- struct Depsgraph *depsgraph;
- Scene *scene;
- ListBase queue;
- int stop;
+ struct Main *main;
+ struct Depsgraph *depsgraph;
+ Scene *scene;
+ ListBase queue;
+ int stop;
} ProxyJob;
static void proxy_freejob(void *pjv)
{
- ProxyJob *pj = pjv;
+ ProxyJob *pj = pjv;
- BLI_freelistN(&pj->queue);
+ BLI_freelistN(&pj->queue);
- MEM_freeN(pj);
+ MEM_freeN(pj);
}
/* only this runs inside thread */
static void proxy_startjob(void *pjv, short *stop, short *do_update, float *progress)
{
- ProxyJob *pj = pjv;
- LinkData *link;
+ ProxyJob *pj = pjv;
+ LinkData *link;
- for (link = pj->queue.first; link; link = link->next) {
- struct SeqIndexBuildContext *context = link->data;
+ for (link = pj->queue.first; link; link = link->next) {
+ struct SeqIndexBuildContext *context = link->data;
- BKE_sequencer_proxy_rebuild(context, stop, do_update, progress);
+ BKE_sequencer_proxy_rebuild(context, stop, do_update, progress);
- if (*stop) {
- pj->stop = 1;
- fprintf(stderr, "Canceling proxy rebuild on users request...\n");
- break;
- }
- }
+ if (*stop) {
+ pj->stop = 1;
+ fprintf(stderr, "Canceling proxy rebuild on users request...\n");
+ break;
+ }
+ }
}
static void proxy_endjob(void *pjv)
{
- ProxyJob *pj = pjv;
- Editing *ed = BKE_sequencer_editing_get(pj->scene, false);
- LinkData *link;
+ ProxyJob *pj = pjv;
+ Editing *ed = BKE_sequencer_editing_get(pj->scene, false);
+ LinkData *link;
- for (link = pj->queue.first; link; link = link->next) {
- BKE_sequencer_proxy_rebuild_finish(link->data, pj->stop);
- }
+ for (link = pj->queue.first; link; link = link->next) {
+ BKE_sequencer_proxy_rebuild_finish(link->data, pj->stop);
+ }
- BKE_sequencer_free_imbuf(pj->scene, &ed->seqbase, false);
+ BKE_sequencer_free_imbuf(pj->scene, &ed->seqbase, false);
- WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, pj->scene);
+ WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, pj->scene);
}
static void seq_proxy_build_job(const bContext *C)
{
- wmJob *wm_job;
- ProxyJob *pj;
- struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- ScrArea *sa = CTX_wm_area(C);
- Sequence *seq;
- GSet *file_list;
+ wmJob *wm_job;
+ ProxyJob *pj;
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ ScrArea *sa = CTX_wm_area(C);
+ Sequence *seq;
+ GSet *file_list;
- if (ed == NULL) {
- return;
- }
+ if (ed == NULL) {
+ return;
+ }
- wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Building Proxies",
- WM_JOB_PROGRESS, WM_JOB_TYPE_SEQ_BUILD_PROXY);
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ sa,
+ "Building Proxies",
+ WM_JOB_PROGRESS,
+ WM_JOB_TYPE_SEQ_BUILD_PROXY);
- pj = WM_jobs_customdata_get(wm_job);
+ pj = WM_jobs_customdata_get(wm_job);
- if (!pj) {
- pj = MEM_callocN(sizeof(ProxyJob), "proxy rebuild job");
+ if (!pj) {
+ pj = MEM_callocN(sizeof(ProxyJob), "proxy rebuild job");
- pj->depsgraph = depsgraph;
- pj->scene = scene;
- pj->main = CTX_data_main(C);
+ pj->depsgraph = depsgraph;
+ pj->scene = scene;
+ pj->main = CTX_data_main(C);
- WM_jobs_customdata_set(wm_job, pj, proxy_freejob);
- WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_SEQUENCER, NC_SCENE | ND_SEQUENCER);
- WM_jobs_callbacks(wm_job, proxy_startjob, NULL, NULL, proxy_endjob);
- }
+ WM_jobs_customdata_set(wm_job, pj, proxy_freejob);
+ WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_SEQUENCER, NC_SCENE | ND_SEQUENCER);
+ WM_jobs_callbacks(wm_job, proxy_startjob, NULL, NULL, proxy_endjob);
+ }
- file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list");
- SEQP_BEGIN (ed, seq)
- {
- if ((seq->flag & SELECT)) {
- BKE_sequencer_proxy_rebuild_context(pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue);
- }
- } SEQ_END;
+ file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list");
+ SEQP_BEGIN (ed, seq) {
+ if ((seq->flag & SELECT)) {
+ BKE_sequencer_proxy_rebuild_context(
+ pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue);
+ }
+ }
+ SEQ_END;
- BLI_gset_free(file_list, MEM_freeN);
+ BLI_gset_free(file_list, MEM_freeN);
- if (!WM_jobs_is_running(wm_job)) {
- G.is_break = false;
- WM_jobs_start(CTX_wm_manager(C), wm_job);
- }
+ if (!WM_jobs_is_running(wm_job)) {
+ G.is_break = false;
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+ }
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(sa);
}
/* ********************************************************************** */
void seq_rectf(Sequence *seq, rctf *rectf)
{
- if (seq->startstill) {
- rectf->xmin = seq->start;
- }
- else {
- rectf->xmin = seq->startdisp;
- }
+ if (seq->startstill) {
+ rectf->xmin = seq->start;
+ }
+ else {
+ rectf->xmin = seq->startdisp;
+ }
- rectf->ymin = seq->machine + SEQ_STRIP_OFSBOTTOM;
- if (seq->endstill) {
- rectf->xmax = seq->start + seq->len;
- }
- else {
- rectf->xmax = seq->enddisp;
- }
- rectf->ymax = seq->machine + SEQ_STRIP_OFSTOP;
+ rectf->ymin = seq->machine + SEQ_STRIP_OFSBOTTOM;
+ if (seq->endstill) {
+ rectf->xmax = seq->start + seq->len;
+ }
+ else {
+ rectf->xmax = seq->enddisp;
+ }
+ rectf->ymax = seq->machine + SEQ_STRIP_OFSTOP;
}
void boundbox_seq(Scene *scene, rctf *rect)
{
- Sequence *seq;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- float min[2], max[2];
-
-
- if (ed == NULL) {
- return;
- }
+ Sequence *seq;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ float min[2], max[2];
- min[0] = 0.0;
- max[0] = EFRA + 1;
- min[1] = 0.0;
- max[1] = 8.0;
+ if (ed == NULL) {
+ return;
+ }
- seq = ed->seqbasep->first;
- while (seq) {
+ min[0] = 0.0;
+ max[0] = EFRA + 1;
+ min[1] = 0.0;
+ max[1] = 8.0;
- if (min[0] > seq->startdisp - 1) {
- min[0] = seq->startdisp - 1;
- }
- if (max[0] < seq->enddisp + 1) {
- max[0] = seq->enddisp + 1;
- }
- if (max[1] < seq->machine + 2) {
- max[1] = seq->machine + 2;
- }
+ seq = ed->seqbasep->first;
+ while (seq) {
- seq = seq->next;
- }
+ if (min[0] > seq->startdisp - 1) {
+ min[0] = seq->startdisp - 1;
+ }
+ if (max[0] < seq->enddisp + 1) {
+ max[0] = seq->enddisp + 1;
+ }
+ if (max[1] < seq->machine + 2) {
+ max[1] = seq->machine + 2;
+ }
- rect->xmin = min[0];
- rect->xmax = max[0];
- rect->ymin = min[1];
- rect->ymax = max[1];
+ seq = seq->next;
+ }
+ rect->xmin = min[0];
+ rect->xmax = max[0];
+ rect->ymin = min[1];
+ rect->ymax = max[1];
}
static int mouse_frame_side(View2D *v2d, short mouse_x, int frame)
{
- int mval[2];
- float mouseloc[2];
+ int mval[2];
+ float mouseloc[2];
- mval[0] = mouse_x;
- mval[1] = 0;
+ mval[0] = mouse_x;
+ mval[1] = 0;
- /* 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]);
+ /* 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;
+ return mouseloc[0] > frame ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT;
}
-
Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int sel)
{
- /* sel - 0==unselected, 1==selected, -1==done care*/
- Sequence *seq;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
-
- if (ed == NULL) {
- return NULL;
- }
-
- if (sel > 0) {
- sel = SELECT;
- }
-
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if ((seq != test) &&
- (test->machine == seq->machine) &&
- ((sel == -1) || (sel && (seq->flag & SELECT)) || (sel == 0 && (seq->flag & SELECT) == 0)))
- {
- switch (lr) {
- case SEQ_SIDE_LEFT:
- if (test->startdisp == (seq->enddisp)) {
- return seq;
- }
- break;
- case SEQ_SIDE_RIGHT:
- if (test->enddisp == (seq->startdisp)) {
- return seq;
- }
- break;
- }
- }
- }
- return NULL;
+ /* sel - 0==unselected, 1==selected, -1==done care*/
+ Sequence *seq;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+
+ if (ed == NULL) {
+ return NULL;
+ }
+
+ if (sel > 0) {
+ sel = SELECT;
+ }
+
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if ((seq != test) && (test->machine == seq->machine) &&
+ ((sel == -1) || (sel && (seq->flag & SELECT)) ||
+ (sel == 0 && (seq->flag & SELECT) == 0))) {
+ switch (lr) {
+ case SEQ_SIDE_LEFT:
+ if (test->startdisp == (seq->enddisp)) {
+ return seq;
+ }
+ break;
+ case SEQ_SIDE_RIGHT:
+ if (test->enddisp == (seq->startdisp)) {
+ return seq;
+ }
+ break;
+ }
+ }
+ }
+ return NULL;
}
static Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, int sel)
{
- /* sel - 0==unselected, 1==selected, -1==done care*/
- Sequence *seq, *best_seq = NULL;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
-
- int dist, best_dist;
- best_dist = MAXFRAME * 2;
-
-
- if (ed == NULL) {
- return NULL;
- }
-
- seq = ed->seqbasep->first;
- while (seq) {
- if ((seq != test) &&
- (test->machine == seq->machine) &&
- (test->depth == seq->depth) &&
- ((sel == -1) || (sel == (seq->flag & SELECT))))
- {
- dist = MAXFRAME * 2;
-
- switch (lr) {
- case SEQ_SIDE_LEFT:
- if (seq->enddisp <= test->startdisp) {
- dist = test->enddisp - seq->startdisp;
- }
- break;
- case SEQ_SIDE_RIGHT:
- if (seq->startdisp >= test->enddisp) {
- dist = seq->startdisp - test->enddisp;
- }
- break;
- }
-
- if (dist == 0) {
- best_seq = seq;
- break;
- }
- else if (dist < best_dist) {
- best_dist = dist;
- best_seq = seq;
- }
- }
- seq = seq->next;
- }
- return best_seq; /* can be null */
+ /* sel - 0==unselected, 1==selected, -1==done care*/
+ Sequence *seq, *best_seq = NULL;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+
+ int dist, best_dist;
+ best_dist = MAXFRAME * 2;
+
+ if (ed == NULL) {
+ return NULL;
+ }
+
+ seq = ed->seqbasep->first;
+ while (seq) {
+ if ((seq != test) && (test->machine == seq->machine) && (test->depth == seq->depth) &&
+ ((sel == -1) || (sel == (seq->flag & SELECT)))) {
+ dist = MAXFRAME * 2;
+
+ switch (lr) {
+ case SEQ_SIDE_LEFT:
+ if (seq->enddisp <= test->startdisp) {
+ dist = test->enddisp - seq->startdisp;
+ }
+ break;
+ case SEQ_SIDE_RIGHT:
+ if (seq->startdisp >= test->enddisp) {
+ dist = seq->startdisp - test->enddisp;
+ }
+ break;
+ }
+
+ if (dist == 0) {
+ best_seq = seq;
+ break;
+ }
+ else if (dist < best_dist) {
+ best_dist = dist;
+ best_seq = seq;
+ }
+ }
+ seq = seq->next;
+ }
+ return best_seq; /* can be null */
}
-
Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[2])
{
- Sequence *seq;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- float x, y;
- float pixelx;
- float handsize;
- float displen;
- *hand = SEQ_SIDE_NONE;
-
-
- if (ed == NULL) {
- return NULL;
- }
-
- pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
-
- UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
-
- seq = ed->seqbasep->first;
-
- while (seq) {
- if (seq->machine == (int)y) {
- /* 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;
- displen = (float)abs(seq->startdisp - seq->enddisp);
-
- /* 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;
- }
- else {
- CLAMP(handsize, 7 * pixelx, 30 * pixelx);
- }
-
- if (handsize + seq->startdisp >= x) {
- *hand = SEQ_SIDE_LEFT;
- }
- else if (-handsize + seq->enddisp <= x) {
- *hand = SEQ_SIDE_RIGHT;
- }
- }
- }
- return seq;
- }
- }
- seq = seq->next;
- }
- return NULL;
+ Sequence *seq;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ float x, y;
+ float pixelx;
+ float handsize;
+ float displen;
+ *hand = SEQ_SIDE_NONE;
+
+ if (ed == NULL) {
+ return NULL;
+ }
+
+ pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
+
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
+
+ seq = ed->seqbasep->first;
+
+ while (seq) {
+ if (seq->machine == (int)y) {
+ /* 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;
+ displen = (float)abs(seq->startdisp - seq->enddisp);
+
+ /* 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;
+ }
+ else {
+ CLAMP(handsize, 7 * pixelx, 30 * pixelx);
+ }
+
+ if (handsize + seq->startdisp >= x) {
+ *hand = SEQ_SIDE_LEFT;
+ }
+ else if (-handsize + seq->enddisp <= x) {
+ *hand = SEQ_SIDE_RIGHT;
+ }
+ }
+ }
+ return seq;
+ }
+ }
+ seq = seq->next;
+ }
+ return NULL;
}
-
static bool seq_is_parent(Sequence *par, Sequence *seq)
{
- return ((par->seq1 == seq) || (par->seq2 == seq) || (par->seq3 == seq));
+ return ((par->seq1 == seq) || (par->seq2 == seq) || (par->seq3 == seq));
}
static bool seq_is_predecessor(Sequence *pred, Sequence *seq)
{
- if (!pred) { return 0; }
- if (pred == seq) { return 0; }
- else if (seq_is_parent(pred, seq)) { return 1; }
- else if (pred->seq1 && seq_is_predecessor(pred->seq1, seq)) { return 1; }
- else if (pred->seq2 && seq_is_predecessor(pred->seq2, seq)) { return 1; }
- else if (pred->seq3 && seq_is_predecessor(pred->seq3, seq)) { return 1; }
-
- return 0;
+ if (!pred) {
+ return 0;
+ }
+ if (pred == seq) {
+ return 0;
+ }
+ else if (seq_is_parent(pred, seq)) {
+ return 1;
+ }
+ else if (pred->seq1 && seq_is_predecessor(pred->seq1, seq)) {
+ return 1;
+ }
+ else if (pred->seq2 && seq_is_predecessor(pred->seq2, seq)) {
+ return 1;
+ }
+ else if (pred->seq3 && seq_is_predecessor(pred->seq3, seq)) {
+ return 1;
+ }
+
+ return 0;
}
void ED_sequencer_deselect_all(Scene *scene)
{
- Sequence *seq;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
-
-
- if (ed == NULL) {
- return;
- }
+ Sequence *seq;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
- SEQP_BEGIN (ed, seq)
- {
- seq->flag &= ~SEQ_ALLSEL;
- } SEQ_END;
+ if (ed == NULL) {
+ return;
+ }
+ SEQP_BEGIN (ed, seq) {
+ seq->flag &= ~SEQ_ALLSEL;
+ }
+ SEQ_END;
}
void recurs_sel_seq(Sequence *seqm)
{
- Sequence *seq;
+ Sequence *seq;
- seq = seqm->seqbase.first;
- while (seq) {
+ seq = seqm->seqbase.first;
+ while (seq) {
- if (seqm->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) {
- seq->flag &= ~SEQ_ALLSEL;
- }
- else if (seqm->flag & SELECT) {
- seq->flag |= SELECT;
- }
- else {
- seq->flag &= ~SEQ_ALLSEL;
- }
+ if (seqm->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) {
+ seq->flag &= ~SEQ_ALLSEL;
+ }
+ else if (seqm->flag & SELECT) {
+ seq->flag |= SELECT;
+ }
+ else {
+ seq->flag &= ~SEQ_ALLSEL;
+ }
- if (seq->seqbase.first) {
- recurs_sel_seq(seq);
- }
+ if (seq->seqbase.first) {
+ recurs_sel_seq(seq);
+ }
- seq = seq->next;
- }
+ seq = seq->next;
+ }
}
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);
+ /* in this case both funcs are the same, for clip editor not */
+ return ED_space_sequencer_maskedit_poll(C);
}
bool ED_space_sequencer_check_show_maskedit(SpaceSeq *sseq, Scene *scene)
{
- if (sseq && sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
- return (BKE_sequencer_mask_get(scene) != NULL);
- }
+ if (sseq && sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
+ return (BKE_sequencer_mask_get(scene) != NULL);
+ }
- return false;
+ return false;
}
bool ED_space_sequencer_maskedit_poll(bContext *C)
{
- SpaceSeq *sseq = CTX_wm_space_seq(C);
+ SpaceSeq *sseq = CTX_wm_space_seq(C);
- if (sseq) {
- Scene *scene = CTX_data_scene(C);
- return ED_space_sequencer_check_show_maskedit(sseq, scene);
- }
+ if (sseq) {
+ Scene *scene = CTX_data_scene(C);
+ return ED_space_sequencer_check_show_maskedit(sseq, scene);
+ }
- return false;
+ return false;
}
/* 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) &&
- ELEM(sseq->mainb, SEQ_DRAW_SEQUENCE, SEQ_DRAW_IMG_IMBUF));
+ return (ELEM(sseq->view, SEQ_VIEW_PREVIEW, SEQ_VIEW_SEQUENCE_PREVIEW) &&
+ ELEM(sseq->mainb, SEQ_DRAW_SEQUENCE, SEQ_DRAW_IMG_IMBUF));
}
bool ED_space_sequencer_check_show_strip(SpaceSeq *sseq)
{
- return (ELEM(sseq->view, SEQ_VIEW_SEQUENCE, SEQ_VIEW_SEQUENCE_PREVIEW) &&
- ELEM(sseq->mainb, SEQ_DRAW_SEQUENCE, SEQ_DRAW_IMG_IMBUF));
-}
-
-
-int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequence **selseq1, Sequence **selseq2, Sequence **selseq3, const char **error_str)
-{
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq1 = NULL, *seq2 = NULL, *seq3 = NULL, *seq;
-
- *error_str = NULL;
-
- if (!activeseq) {
- seq2 = BKE_sequencer_active_get(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");
- return 0;
- }
- if ((seq != activeseq) && (seq != seq2)) {
- if (seq2 == NULL) {
- seq2 = seq;
- }
- else if (seq1 == NULL) {
- seq1 = seq;
- }
- else if (seq3 == NULL) {
- seq3 = seq;
- }
- else {
- *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 */
- if (seq3 != NULL && seq2 != NULL) {
- Sequence *tmp = seq2;
- seq2 = seq3;
- seq3 = tmp;
- }
-
-
- switch (BKE_sequence_effect_get_num_inputs(type)) {
- case 0:
- *selseq1 = *selseq2 = *selseq3 = NULL;
- return 1; /* success */
- case 1:
- if (seq2 == NULL) {
- *error_str = N_("At least one selected sequence strip is needed");
- return 0;
- }
- if (seq1 == NULL) {
- seq1 = seq2;
- }
- if (seq3 == NULL) {
- seq3 = seq2;
- }
- ATTR_FALLTHROUGH;
- case 2:
- if (seq1 == NULL || seq2 == NULL) {
- *error_str = N_("2 selected sequence strips are needed");
- return 0;
- }
- if (seq3 == NULL) {
- seq3 = seq2;
- }
- break;
- }
-
- if (seq1 == NULL && seq2 == NULL && seq3 == NULL) {
- *error_str = N_("TODO: in what cases does this happen?");
- return 0;
- }
-
- *selseq1 = seq1;
- *selseq2 = seq2;
- *selseq3 = seq3;
-
- return 1;
+ return (ELEM(sseq->view, SEQ_VIEW_SEQUENCE, SEQ_VIEW_SEQUENCE_PREVIEW) &&
+ ELEM(sseq->mainb, SEQ_DRAW_SEQUENCE, SEQ_DRAW_IMG_IMBUF));
+}
+
+int seq_effect_find_selected(Scene *scene,
+ Sequence *activeseq,
+ int type,
+ Sequence **selseq1,
+ Sequence **selseq2,
+ Sequence **selseq3,
+ const char **error_str)
+{
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq1 = NULL, *seq2 = NULL, *seq3 = NULL, *seq;
+
+ *error_str = NULL;
+
+ if (!activeseq) {
+ seq2 = BKE_sequencer_active_get(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");
+ return 0;
+ }
+ if ((seq != activeseq) && (seq != seq2)) {
+ if (seq2 == NULL) {
+ seq2 = seq;
+ }
+ else if (seq1 == NULL) {
+ seq1 = seq;
+ }
+ else if (seq3 == NULL) {
+ seq3 = seq;
+ }
+ else {
+ *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 */
+ if (seq3 != NULL && seq2 != NULL) {
+ Sequence *tmp = seq2;
+ seq2 = seq3;
+ seq3 = tmp;
+ }
+
+ switch (BKE_sequence_effect_get_num_inputs(type)) {
+ case 0:
+ *selseq1 = *selseq2 = *selseq3 = NULL;
+ return 1; /* success */
+ case 1:
+ if (seq2 == NULL) {
+ *error_str = N_("At least one selected sequence strip is needed");
+ return 0;
+ }
+ if (seq1 == NULL) {
+ seq1 = seq2;
+ }
+ if (seq3 == NULL) {
+ seq3 = seq2;
+ }
+ ATTR_FALLTHROUGH;
+ case 2:
+ if (seq1 == NULL || seq2 == NULL) {
+ *error_str = N_("2 selected sequence strips are needed");
+ return 0;
+ }
+ if (seq3 == NULL) {
+ seq3 = seq2;
+ }
+ break;
+ }
+
+ if (seq1 == NULL && seq2 == NULL && seq3 == NULL) {
+ *error_str = N_("TODO: in what cases does this happen?");
+ return 0;
+ }
+
+ *selseq1 = seq1;
+ *selseq2 = seq2;
+ *selseq3 = seq3;
+
+ return 1;
}
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 */
-
- if (!seq) {
- return NULL;
- }
- else if (!(seq->type & SEQ_TYPE_EFFECT)) {
- return ((seq->flag & SELECT) ? NULL : seq);
- }
- else if (!(seq->flag & SELECT)) {
- /* 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 */
- }
- else if (seq1 || seq2 || seq3) {
- seq->seq1 = (seq1) ? seq1 : (seq2) ? seq2 : seq3;
- seq->seq2 = (seq2) ? seq2 : (seq1) ? seq1 : seq3;
- seq->seq3 = (seq3) ? seq3 : (seq1) ? seq1 : seq2;
-
- BKE_sequencer_update_changed_seq_and_deps(scene, seq, 1, 1);
- }
- else {
- seq->flag |= SELECT; /* mark for delete */
- }
- }
-
- if (seq->flag & SELECT) {
- if ((seq1 = del_seq_find_replace_recurs(scene, seq->seq1))) { return seq1; }
- if ((seq2 = del_seq_find_replace_recurs(scene, seq->seq2))) { return seq2; }
- if ((seq3 = del_seq_find_replace_recurs(scene, seq->seq3))) { return seq3; }
- else {
- return NULL;
- }
- }
- else {
- return seq;
- }
+ Sequence *seq1, *seq2, *seq3;
+
+ /* try to find a replacement input sequence, and flag for later deletion if
+ * no replacement can be found */
+
+ if (!seq) {
+ return NULL;
+ }
+ else if (!(seq->type & SEQ_TYPE_EFFECT)) {
+ return ((seq->flag & SELECT) ? NULL : seq);
+ }
+ else if (!(seq->flag & SELECT)) {
+ /* 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 */
+ }
+ else if (seq1 || seq2 || seq3) {
+ seq->seq1 = (seq1) ? seq1 : (seq2) ? seq2 : seq3;
+ seq->seq2 = (seq2) ? seq2 : (seq1) ? seq1 : seq3;
+ seq->seq3 = (seq3) ? seq3 : (seq1) ? seq1 : seq2;
+
+ BKE_sequencer_update_changed_seq_and_deps(scene, seq, 1, 1);
+ }
+ else {
+ seq->flag |= SELECT; /* mark for delete */
+ }
+ }
+
+ if (seq->flag & SELECT) {
+ if ((seq1 = del_seq_find_replace_recurs(scene, seq->seq1))) {
+ return seq1;
+ }
+ if ((seq2 = del_seq_find_replace_recurs(scene, seq->seq2))) {
+ return seq2;
+ }
+ if ((seq3 = del_seq_find_replace_recurs(scene, seq->seq3))) {
+ return seq3;
+ }
+ else {
+ return NULL;
+ }
+ }
+ else {
+ return seq;
+ }
}
static void del_seq_clear_modifiers_recurs(Scene *scene, Sequence *deleting_sequence)
{
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *current_sequence;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *current_sequence;
- SEQP_BEGIN(ed, current_sequence)
- {
- if (!(current_sequence->flag & SELECT) && current_sequence != deleting_sequence) {
- SequenceModifierData *smd;
+ SEQP_BEGIN (ed, current_sequence) {
+ if (!(current_sequence->flag & SELECT) && current_sequence != deleting_sequence) {
+ SequenceModifierData *smd;
- for (smd = current_sequence->modifiers.first; smd; smd = smd->next) {
- if (smd->mask_sequence == deleting_sequence) {
- smd->mask_sequence = NULL;
- }
- }
- }
- } SEQ_END;
+ for (smd = current_sequence->modifiers.first; smd; smd = smd->next) {
+ if (smd->mask_sequence == deleting_sequence) {
+ smd->mask_sequence = NULL;
+ }
+ }
+ }
+ }
+ SEQ_END;
}
static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short deleteall)
{
- Sequence *seq, *seqn;
- Sequence *last_seq = BKE_sequencer_active_get(scene);
-
- seq = lb->first;
- while (seq) {
- seqn = seq->next;
- if ((seq->flag & flag) || deleteall) {
- BLI_remlink(lb, seq);
- if (seq == last_seq) {
- BKE_sequencer_active_set(scene, NULL);
- }
- if (seq->type == SEQ_TYPE_META) {
- recurs_del_seq_flag(scene, &seq->seqbase, flag, 1);
- }
- BKE_sequence_free(scene, seq);
- }
- seq = seqn;
- }
+ Sequence *seq, *seqn;
+ Sequence *last_seq = BKE_sequencer_active_get(scene);
+
+ seq = lb->first;
+ while (seq) {
+ seqn = seq->next;
+ if ((seq->flag & flag) || deleteall) {
+ BLI_remlink(lb, seq);
+ if (seq == last_seq) {
+ BKE_sequencer_active_set(scene, NULL);
+ }
+ if (seq->type == SEQ_TYPE_META) {
+ recurs_del_seq_flag(scene, &seq->seqbase, flag, 1);
+ }
+ BKE_sequence_free(scene, seq);
+ }
+ seq = seqn;
+ }
}
-
static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, ListBase *new_seq_list, int cutframe)
{
- 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);
-
- /* backup values */
- ts.start = seq->start;
- ts.machine = seq->machine;
- ts.startstill = seq->startstill;
- ts.endstill = seq->endstill;
- ts.startdisp = seq->startdisp;
- ts.enddisp = seq->enddisp;
- ts.startofs = seq->startofs;
- ts.endofs = seq->endofs;
- ts.anim_startofs = seq->anim_startofs;
- 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) {
- BKE_sequence_reload_new_file(scene, seq, true);
- BKE_sequence_calc(scene, seq);
- }
-
- /* Important to offset the start when 'cutframe == 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->type == SEQ_TYPE_META) {
- skip_dup = true;
- seq->startstill = seq->start - cutframe;
- }
- else {
- seq->start = cutframe - 1;
- seq->startstill = cutframe - seq->startdisp - 1;
- seq->anim_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 = 0;
- seq->endstill = 0;
- seq->anim_endofs += (seq->start + seq->len) - cutframe;
- }
- /* 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 ... */
- if (seq->type == SEQ_TYPE_META) {
- skip_dup = true;
- }
- }
-
- BKE_sequence_reload_new_file(scene, seq, false);
- BKE_sequence_calc(scene, seq);
-
- if (!skip_dup) {
- /* Duplicate AFTER the first change */
- seqn = BKE_sequence_dupli_recursive(scene, scene, new_seq_list, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
- }
-
- if (seqn) {
- seqn->flag |= SELECT;
-
- /* Important not to re-assign this (unlike soft-cut) */
+ 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);
+
+ /* backup values */
+ ts.start = seq->start;
+ ts.machine = seq->machine;
+ ts.startstill = seq->startstill;
+ ts.endstill = seq->endstill;
+ ts.startdisp = seq->startdisp;
+ ts.enddisp = seq->enddisp;
+ ts.startofs = seq->startofs;
+ ts.endofs = seq->endofs;
+ ts.anim_startofs = seq->anim_startofs;
+ 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) {
+ BKE_sequence_reload_new_file(scene, seq, true);
+ BKE_sequence_calc(scene, seq);
+ }
+
+ /* Important to offset the start when 'cutframe == 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->type == SEQ_TYPE_META) {
+ skip_dup = true;
+ seq->startstill = seq->start - cutframe;
+ }
+ else {
+ seq->start = cutframe - 1;
+ seq->startstill = cutframe - seq->startdisp - 1;
+ seq->anim_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 = 0;
+ seq->endstill = 0;
+ seq->anim_endofs += (seq->start + seq->len) - cutframe;
+ }
+ /* 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 ... */
+ if (seq->type == SEQ_TYPE_META) {
+ skip_dup = true;
+ }
+ }
+
+ BKE_sequence_reload_new_file(scene, seq, false);
+ BKE_sequence_calc(scene, seq);
+
+ if (!skip_dup) {
+ /* Duplicate AFTER the first change */
+ seqn = BKE_sequence_dupli_recursive(
+ scene, scene, new_seq_list, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
+ }
+
+ 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) == cutframe);
#endif
- /* Second Strip! */
- /* strips with extended stillframes before */
- if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
- seqn->start = ts.start;
- seqn->startstill = ts.start - cutframe;
- seqn->anim_endofs = ts.anim_endofs;
- seqn->endstill = ts.endstill;
- }
-
- /* normal strip */
- else if ((is_end_exact == false) &&
- ((cutframe >= seqn->start) && (cutframe <= (seqn->start + seqn->len))))
- {
- seqn->start = cutframe;
- seqn->startstill = 0;
- seqn->startofs = 0;
- seqn->endofs = ts.endofs;
- seqn->anim_startofs += cutframe - ts.start;
- seqn->anim_endofs = ts.anim_endofs;
- seqn->endstill = ts.endstill;
- }
-
- /* strips with extended stillframes after */
- else if ((is_end_exact == true) ||
- (((seqn->start + seqn->len) < cutframe) && (seqn->endstill)))
- {
- seqn->start = cutframe;
- seqn->startofs = 0;
- seqn->anim_startofs += ts.len - 1;
- seqn->endstill = ts.enddisp - cutframe - 1;
- seqn->startstill = 0;
- }
-
- BKE_sequence_reload_new_file(scene, seqn, false);
- BKE_sequence_calc(scene, seqn);
- }
- return seqn;
+ /* Second Strip! */
+ /* strips with extended stillframes before */
+ if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
+ seqn->start = ts.start;
+ seqn->startstill = ts.start - cutframe;
+ seqn->anim_endofs = ts.anim_endofs;
+ seqn->endstill = ts.endstill;
+ }
+
+ /* normal strip */
+ else if ((is_end_exact == false) &&
+ ((cutframe >= seqn->start) && (cutframe <= (seqn->start + seqn->len)))) {
+ seqn->start = cutframe;
+ seqn->startstill = 0;
+ seqn->startofs = 0;
+ seqn->endofs = ts.endofs;
+ seqn->anim_startofs += cutframe - ts.start;
+ seqn->anim_endofs = ts.anim_endofs;
+ seqn->endstill = ts.endstill;
+ }
+
+ /* strips with extended stillframes after */
+ else if ((is_end_exact == true) ||
+ (((seqn->start + seqn->len) < cutframe) && (seqn->endstill))) {
+ seqn->start = cutframe;
+ seqn->startofs = 0;
+ seqn->anim_startofs += ts.len - 1;
+ seqn->endstill = ts.enddisp - cutframe - 1;
+ seqn->startstill = 0;
+ }
+
+ BKE_sequence_reload_new_file(scene, seqn, false);
+ BKE_sequence_calc(scene, seqn);
+ }
+ return seqn;
}
static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, ListBase *new_seq_list, int cutframe)
{
- TransSeq ts;
- Sequence *seqn = NULL;
- bool skip_dup = false;
-
- bool is_end_exact = ((seq->start + seq->len) == cutframe);
-
- /* backup values */
- ts.start = seq->start;
- ts.machine = seq->machine;
- ts.startstill = seq->startstill;
- ts.endstill = seq->endstill;
- ts.startdisp = seq->startdisp;
- ts.enddisp = seq->enddisp;
- ts.startofs = seq->startofs;
- ts.endofs = seq->endofs;
- ts.anim_startofs = seq->anim_startofs;
- 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'
- * 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->type == SEQ_TYPE_META) {
- skip_dup = true;
- seq->startstill = seq->start - cutframe;
- }
- else {
- seq->start = cutframe - 1;
- seq->startstill = cutframe - 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;
- }
- /* 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 ... */
- if (seq->type == SEQ_TYPE_META) {
- skip_dup = true;
- }
- }
-
- BKE_sequence_calc(scene, seq);
-
- if (!skip_dup) {
- /* Duplicate AFTER the first change */
- seqn = BKE_sequence_dupli_recursive(scene, scene, new_seq_list, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
- }
-
- if (seqn) {
- seqn->flag |= SELECT;
-
- is_end_exact = ((seqn->start + seqn->len) == cutframe);
-
- /* Second Strip! */
- /* strips with extended stillframes before */
- if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
- seqn->start = ts.start;
- seqn->startstill = ts.start - cutframe;
- seqn->endofs = ts.endofs;
- seqn->endstill = ts.endstill;
- }
-
- /* normal strip */
- else if ((is_end_exact == false) &&
- (cutframe >= seqn->start) && (cutframe <= (seqn->start + seqn->len)))
- {
- seqn->startstill = 0;
- seqn->startofs = cutframe - ts.start;
- seqn->endofs = ts.endofs;
- seqn->endstill = ts.endstill;
- }
-
- /* strips with extended stillframes after */
- else if ((is_end_exact == true) ||
- (((seqn->start + seqn->len) < cutframe) && (seqn->endstill)))
- {
- seqn->start = cutframe - ts.len + 1;
- seqn->startofs = ts.len - 1;
- seqn->endstill = ts.enddisp - cutframe - 1;
- seqn->startstill = 0;
- }
-
- BKE_sequence_calc(scene, seqn);
- }
- return seqn;
+ TransSeq ts;
+ Sequence *seqn = NULL;
+ bool skip_dup = false;
+
+ bool is_end_exact = ((seq->start + seq->len) == cutframe);
+
+ /* backup values */
+ ts.start = seq->start;
+ ts.machine = seq->machine;
+ ts.startstill = seq->startstill;
+ ts.endstill = seq->endstill;
+ ts.startdisp = seq->startdisp;
+ ts.enddisp = seq->enddisp;
+ ts.startofs = seq->startofs;
+ ts.endofs = seq->endofs;
+ ts.anim_startofs = seq->anim_startofs;
+ 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'
+ * 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->type == SEQ_TYPE_META) {
+ skip_dup = true;
+ seq->startstill = seq->start - cutframe;
+ }
+ else {
+ seq->start = cutframe - 1;
+ seq->startstill = cutframe - 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;
+ }
+ /* 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 ... */
+ if (seq->type == SEQ_TYPE_META) {
+ skip_dup = true;
+ }
+ }
+
+ BKE_sequence_calc(scene, seq);
+
+ if (!skip_dup) {
+ /* Duplicate AFTER the first change */
+ seqn = BKE_sequence_dupli_recursive(
+ scene, scene, new_seq_list, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
+ }
+
+ if (seqn) {
+ seqn->flag |= SELECT;
+
+ is_end_exact = ((seqn->start + seqn->len) == cutframe);
+
+ /* Second Strip! */
+ /* strips with extended stillframes before */
+ if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
+ seqn->start = ts.start;
+ seqn->startstill = ts.start - cutframe;
+ seqn->endofs = ts.endofs;
+ seqn->endstill = ts.endstill;
+ }
+
+ /* normal strip */
+ else if ((is_end_exact == false) && (cutframe >= seqn->start) &&
+ (cutframe <= (seqn->start + seqn->len))) {
+ seqn->startstill = 0;
+ seqn->startofs = cutframe - ts.start;
+ seqn->endofs = ts.endofs;
+ seqn->endstill = ts.endstill;
+ }
+
+ /* strips with extended stillframes after */
+ else if ((is_end_exact == true) ||
+ (((seqn->start + seqn->len) < cutframe) && (seqn->endstill))) {
+ seqn->start = cutframe - ts.len + 1;
+ seqn->startofs = ts.len - 1;
+ seqn->endstill = ts.enddisp - cutframe - 1;
+ seqn->startstill = 0;
+ }
+
+ BKE_sequence_calc(scene, seqn);
+ }
+ 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
@@ -955,1277 +957,1307 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, ListBase *new_seq_lis
* may generate strips with the same name (which will mess up animdata)
*/
-static bool cut_seq_list(Scene *scene, ListBase *slist, int cutframe,
- Sequence * (*cut_seq)(Scene *, Sequence *, ListBase *, int))
-{
- Sequence *seq, *seq_next_iter;
- Sequence *seq_first_new = NULL;
-
- seq = slist->first;
-
- while (seq && seq != seq_first_new) {
- seq_next_iter = seq->next; /* we need this because we may remove seq */
- seq->tmp = NULL;
- if (seq->flag & SELECT) {
- if (cutframe > seq->startdisp &&
- cutframe < seq->enddisp)
- {
- Sequence *seqn = cut_seq(scene, seq, slist, cutframe);
- if (seqn) {
- if (seq_first_new == NULL) {
- seq_first_new = seqn;
- }
- }
- }
- else if (seq->enddisp <= cutframe) {
- /* do nothing */
- }
- else if (seq->startdisp >= cutframe) {
- /* move to tail */
- BLI_remlink(slist, seq);
- BLI_addtail(slist, seq);
-
- if (seq_first_new == NULL) {
- seq_first_new = seq;
- }
- }
- }
- seq = seq_next_iter;
- }
-
- return (seq_first_new != NULL);
+static bool cut_seq_list(Scene *scene,
+ ListBase *slist,
+ int cutframe,
+ Sequence *(*cut_seq)(Scene *, Sequence *, ListBase *, int))
+{
+ Sequence *seq, *seq_next_iter;
+ Sequence *seq_first_new = NULL;
+
+ seq = slist->first;
+
+ while (seq && seq != seq_first_new) {
+ seq_next_iter = seq->next; /* we need this because we may remove seq */
+ seq->tmp = NULL;
+ if (seq->flag & SELECT) {
+ if (cutframe > seq->startdisp && cutframe < seq->enddisp) {
+ Sequence *seqn = cut_seq(scene, seq, slist, cutframe);
+ if (seqn) {
+ if (seq_first_new == NULL) {
+ seq_first_new = seqn;
+ }
+ }
+ }
+ else if (seq->enddisp <= cutframe) {
+ /* do nothing */
+ }
+ else if (seq->startdisp >= cutframe) {
+ /* move to tail */
+ BLI_remlink(slist, seq);
+ BLI_addtail(slist, seq);
+
+ if (seq_first_new == NULL) {
+ seq_first_new = seq;
+ }
+ }
+ }
+ seq = seq_next_iter;
+ }
+
+ return (seq_first_new != NULL);
}
static bool sequence_offset_after_frame(Scene *scene, const int delta, const int cfra)
{
- Sequence *seq;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- bool done = false;
- TimeMarker *marker;
+ Sequence *seq;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ bool done = false;
+ TimeMarker *marker;
- /* all strips >= cfra are shifted */
+ /* all strips >= cfra are shifted */
- if (ed == NULL) {
- return 0;
- }
+ if (ed == NULL) {
+ return 0;
+ }
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if (seq->startdisp >= cfra) {
- BKE_sequence_translate(scene, seq, delta);
- BKE_sequence_calc(scene, seq);
- done = true;
- }
- }
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (seq->startdisp >= cfra) {
+ BKE_sequence_translate(scene, seq, delta);
+ BKE_sequence_calc(scene, seq);
+ done = true;
+ }
+ }
- if (!scene->toolsettings->lock_markers) {
- for (marker = scene->markers.first; marker; marker = marker->next) {
- if (marker->frame >= cfra) {
- marker->frame += delta;
- }
- }
- }
+ if (!scene->toolsettings->lock_markers) {
+ for (marker = scene->markers.first; marker; marker = marker->next) {
+ if (marker->frame >= cfra) {
+ marker->frame += delta;
+ }
+ }
+ }
- return done;
+ return done;
}
#if 0
static void set_filter_seq(Scene *scene)
{
- Sequence *seq;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
- if (ed == NULL) return;
+ if (ed == NULL) return;
- if (okee("Set Deinterlace") == 0) return;
+ if (okee("Set Deinterlace") == 0) return;
- SEQP_BEGIN (ed, seq)
- {
- if (seq->flag & SELECT) {
- if (seq->type == SEQ_TYPE_MOVIE) {
- seq->flag |= SEQ_FILTERY;
- BKE_sequence_reload_new_file(scene, seq, false);
- BKE_sequence_calc(scene, seq);
- }
+ SEQP_BEGIN (ed, seq)
+ {
+ if (seq->flag & SELECT) {
+ if (seq->type == SEQ_TYPE_MOVIE) {
+ seq->flag |= SEQ_FILTERY;
+ BKE_sequence_reload_new_file(scene, seq, false);
+ BKE_sequence_calc(scene, seq);
+ }
- }
- } SEQ_END;
+ }
+ } SEQ_END;
}
#endif
-static void UNUSED_FUNCTION(seq_remap_paths) (Scene *scene)
+static void UNUSED_FUNCTION(seq_remap_paths)(Scene *scene)
{
- Sequence *seq, *last_seq = BKE_sequencer_active_get(scene);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- char from[FILE_MAX], to[FILE_MAX], stripped[FILE_MAX];
-
-
- if (last_seq == NULL) {
- return;
- }
+ Sequence *seq, *last_seq = BKE_sequencer_active_get(scene);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ char from[FILE_MAX], to[FILE_MAX], stripped[FILE_MAX];
- BLI_strncpy(from, last_seq->strip->dir, sizeof(from));
-// XXX if (0 == sbutton(from, 0, sizeof(from) - 1, "From: "))
-// return;
+ if (last_seq == NULL) {
+ return;
+ }
- BLI_strncpy(to, from, sizeof(to));
-// XXX if (0 == sbutton(to, 0, sizeof(to) - 1, "To: "))
-// return;
+ BLI_strncpy(from, last_seq->strip->dir, sizeof(from));
+ // XXX if (0 == sbutton(from, 0, sizeof(from) - 1, "From: "))
+ // return;
- if (STREQ(to, from)) {
- return;
- }
+ BLI_strncpy(to, from, sizeof(to));
+ // XXX if (0 == sbutton(to, 0, sizeof(to) - 1, "To: "))
+ // return;
- SEQP_BEGIN (ed, seq)
- {
- if (seq->flag & SELECT) {
- if (STREQLEN(seq->strip->dir, from, strlen(from))) {
- printf("found %s\n", seq->strip->dir);
+ if (STREQ(to, from)) {
+ return;
+ }
- /* strip off the beginning */
- stripped[0] = 0;
- BLI_strncpy(stripped, seq->strip->dir + strlen(from), FILE_MAX);
+ SEQP_BEGIN (ed, seq) {
+ if (seq->flag & SELECT) {
+ if (STREQLEN(seq->strip->dir, from, strlen(from))) {
+ printf("found %s\n", seq->strip->dir);
- /* new path */
- BLI_snprintf(seq->strip->dir, sizeof(seq->strip->dir), "%s%s", to, stripped);
- printf("new %s\n", seq->strip->dir);
- }
- }
- } SEQ_END;
+ /* strip off the beginning */
+ stripped[0] = 0;
+ BLI_strncpy(stripped, seq->strip->dir + strlen(from), FILE_MAX);
+ /* new path */
+ BLI_snprintf(seq->strip->dir, sizeof(seq->strip->dir), "%s%s", to, stripped);
+ printf("new %s\n", seq->strip->dir);
+ }
+ }
+ }
+ SEQ_END;
}
-
static int sequencer_gap_remove_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- rctf rectf;
- int cfra, efra, sfra;
- bool first = false, done;
- bool do_all = RNA_boolean_get(op->ptr, "all");
-
- /* 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 */
- for (cfra = CFRA; cfra >= sfra; cfra--) {
- if (BKE_sequencer_evaluate_frame(scene, cfra)) {
- first = true;
- break;
- }
- }
-
- for ( ; cfra < efra; cfra++) {
- /* first == 0 means there's still no strip to remove a gap for */
- if (first == false) {
- if (BKE_sequencer_evaluate_frame(scene, cfra) ) {
- first = true;
- }
- }
- else if (BKE_sequencer_evaluate_frame(scene, cfra) == 0) {
- done = true;
- while (BKE_sequencer_evaluate_frame(scene, cfra) == 0) {
- done = sequence_offset_after_frame(scene, -1, cfra);
- if (done == false) {
- break;
- }
- }
- if (done == false || do_all == false) {
- break;
- }
- }
- }
-
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
- return OPERATOR_FINISHED;
-
+ Scene *scene = CTX_data_scene(C);
+ rctf rectf;
+ int cfra, efra, sfra;
+ bool first = false, done;
+ bool do_all = RNA_boolean_get(op->ptr, "all");
+
+ /* 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 */
+ for (cfra = CFRA; cfra >= sfra; cfra--) {
+ if (BKE_sequencer_evaluate_frame(scene, cfra)) {
+ first = true;
+ break;
+ }
+ }
+
+ for (; cfra < efra; cfra++) {
+ /* first == 0 means there's still no strip to remove a gap for */
+ if (first == false) {
+ if (BKE_sequencer_evaluate_frame(scene, cfra)) {
+ first = true;
+ }
+ }
+ else if (BKE_sequencer_evaluate_frame(scene, cfra) == 0) {
+ done = true;
+ while (BKE_sequencer_evaluate_frame(scene, cfra) == 0) {
+ done = sequence_offset_after_frame(scene, -1, cfra);
+ if (done == false) {
+ break;
+ }
+ }
+ if (done == false || do_all == false) {
+ break;
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
}
-
void SEQUENCER_OT_gap_remove(struct wmOperatorType *ot)
{
- /* 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";
+ /* 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 */
-// ot->invoke = sequencer_snap_invoke;
- ot->exec = sequencer_gap_remove_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ // ot->invoke = sequencer_snap_invoke;
+ ot->exec = sequencer_gap_remove_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "all", 0, "All Gaps", "Do all gaps to right of current frame");
+ RNA_def_boolean(ot->srna, "all", 0, "All Gaps", "Do all gaps to right of current frame");
}
static int sequencer_gap_insert_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- int frames = RNA_int_get(op->ptr, "frames");
+ Scene *scene = CTX_data_scene(C);
+ int frames = RNA_int_get(op->ptr, "frames");
- sequence_offset_after_frame(scene, frames, CFRA);
+ sequence_offset_after_frame(scene, frames, CFRA);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
- return OPERATOR_FINISHED;
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_gap_insert(struct wmOperatorType *ot)
{
- /* 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";
+ /* 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 */
- // ot->invoke = sequencer_snap_invoke;
- ot->exec = sequencer_gap_insert_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ // ot->invoke = sequencer_snap_invoke;
+ ot->exec = sequencer_gap_insert_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_int(ot->srna, "frames", 10, 0, INT_MAX, "Frames", "Frames to insert after current strip", 0, 1000);
+ RNA_def_int(ot->srna,
+ "frames",
+ 10,
+ 0,
+ INT_MAX,
+ "Frames",
+ "Frames to insert after current strip",
+ 0,
+ 1000);
}
-
#if 0
static int seq_get_snaplimit(View2D *v2d)
{
- /* fake mouse coords to get the snap value
- * a bit lazy but its only done once pre transform */
- float xmouse, ymouse, x;
- int mval[2] = {24, 0}; /* 24 screen px snap */
+ /* fake mouse coords to get the snap value
+ * a bit lazy but its only done once pre transform */
+ float xmouse, ymouse, x;
+ int mval[2] = {24, 0}; /* 24 screen px snap */
- UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
- x = xmouse;
- mval[0] = 0;
- UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
- return (int)(x - xmouse);
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
+ x = xmouse;
+ mval[0] = 0;
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
+ return (int)(x - xmouse);
}
#endif
/* Operator functions */
bool sequencer_edit_poll(bContext *C)
{
- return (BKE_sequencer_editing_get(CTX_data_scene(C), false) != NULL);
+ return (BKE_sequencer_editing_get(CTX_data_scene(C), false) != NULL);
}
#if 0 /* UNUSED */
bool sequencer_strip_poll(bContext *C)
{
- Editing *ed;
- return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) && (ed->act_seq != NULL));
+ Editing *ed;
+ return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) && (ed->act_seq != NULL));
}
#endif
bool sequencer_strip_has_path_poll(bContext *C)
{
- Editing *ed;
- Sequence *seq;
- return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) && ((seq = ed->act_seq) != NULL) && (SEQ_HAS_PATH(seq)));
+ Editing *ed;
+ Sequence *seq;
+ return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) &&
+ ((seq = ed->act_seq) != NULL) && (SEQ_HAS_PATH(seq)));
}
bool sequencer_view_preview_poll(bContext *C)
{
- SpaceSeq *sseq = CTX_wm_space_seq(C);
- Editing *ed = BKE_sequencer_editing_get(CTX_data_scene(C), false);
- if (ed && sseq && (sseq->mainb == SEQ_DRAW_IMG_IMBUF)) {
- return 1;
- }
+ SpaceSeq *sseq = CTX_wm_space_seq(C);
+ Editing *ed = BKE_sequencer_editing_get(CTX_data_scene(C), false);
+ if (ed && sseq && (sseq->mainb == SEQ_DRAW_IMG_IMBUF)) {
+ return 1;
+ }
- return 0;
+ return 0;
}
bool sequencer_view_strips_poll(bContext *C)
{
- SpaceSeq *sseq = CTX_wm_space_seq(C);
- if (sseq && ED_space_sequencer_check_show_strip(sseq)) {
- return 1;
- }
+ SpaceSeq *sseq = CTX_wm_space_seq(C);
+ if (sseq && ED_space_sequencer_check_show_strip(sseq)) {
+ return 1;
+ }
- return 0;
+ return 0;
}
/* snap operator*/
static int sequencer_snap_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
-
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq;
- int snap_frame;
-
- snap_frame = RNA_int_get(op->ptr, "frame");
-
- /* also 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);
- }
- else {
- if (seq->flag & SEQ_LEFTSEL) {
- BKE_sequence_tx_set_final_left(seq, snap_frame);
- }
- else { /* SEQ_RIGHTSEL */
- BKE_sequence_tx_set_final_right(seq, snap_frame);
- }
- BKE_sequence_tx_handle_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL);
- BKE_sequence_single_fix(seq);
- }
- BKE_sequence_calc(scene, seq);
- }
- }
-
- /* 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;
- if (BKE_sequence_test_overlap(ed->seqbasep, seq) ) {
- BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
- }
- }
- else if (seq->type & SEQ_TYPE_EFFECT) {
- if (seq->seq1 && (seq->seq1->flag & SELECT)) {
- BKE_sequence_calc(scene, seq);
- }
- else if (seq->seq2 && (seq->seq2->flag & SELECT)) {
- BKE_sequence_calc(scene, seq);
- }
- else if (seq->seq3 && (seq->seq3->flag & SELECT)) {
- BKE_sequence_calc(scene, seq);
- }
- }
- }
-
- /* as last: */
- BKE_sequencer_sort(scene);
-
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+ int snap_frame;
+
+ snap_frame = RNA_int_get(op->ptr, "frame");
+
+ /* also 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);
+ }
+ else {
+ if (seq->flag & SEQ_LEFTSEL) {
+ BKE_sequence_tx_set_final_left(seq, snap_frame);
+ }
+ else { /* SEQ_RIGHTSEL */
+ BKE_sequence_tx_set_final_right(seq, snap_frame);
+ }
+ BKE_sequence_tx_handle_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL);
+ BKE_sequence_single_fix(seq);
+ }
+ BKE_sequence_calc(scene, seq);
+ }
+ }
+
+ /* 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;
+ if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
+ BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
+ }
+ }
+ else if (seq->type & SEQ_TYPE_EFFECT) {
+ if (seq->seq1 && (seq->seq1->flag & SELECT)) {
+ BKE_sequence_calc(scene, seq);
+ }
+ else if (seq->seq2 && (seq->seq2->flag & SELECT)) {
+ BKE_sequence_calc(scene, seq);
+ }
+ else if (seq->seq3 && (seq->seq3->flag & SELECT)) {
+ BKE_sequence_calc(scene, seq);
+ }
+ }
+ }
+
+ /* as last: */
+ BKE_sequencer_sort(scene);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
}
static int sequencer_snap_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- int snap_frame;
+ int snap_frame;
- snap_frame = CFRA;
+ snap_frame = CFRA;
- RNA_int_set(op->ptr, "frame", snap_frame);
- return sequencer_snap_exec(C, op);
+ RNA_int_set(op->ptr, "frame", snap_frame);
+ return sequencer_snap_exec(C, op);
}
void SEQUENCER_OT_snap(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Snap Strips to Frame";
- ot->idname = "SEQUENCER_OT_snap";
- ot->description = "Frame where selected strips will be snapped";
+ /* identifiers */
+ ot->name = "Snap Strips to Frame";
+ ot->idname = "SEQUENCER_OT_snap";
+ ot->description = "Frame where selected strips will be snapped";
- /* api callbacks */
- ot->invoke = sequencer_snap_invoke;
- ot->exec = sequencer_snap_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->invoke = sequencer_snap_invoke;
+ ot->exec = sequencer_snap_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be snapped", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna,
+ "frame",
+ 0,
+ INT_MIN,
+ INT_MAX,
+ "Frame",
+ "Frame where selected strips will be snapped",
+ INT_MIN,
+ INT_MAX);
}
typedef struct SlipData {
- int init_mouse[2];
- float init_mouseloc[2];
- TransSeq *ts;
- Sequence **seq_array;
- bool *trim;
- int num_seq;
- bool slow;
- int slow_offset; /* offset at the point where offset was turned on */
- NumInput num_input;
+ int init_mouse[2];
+ float init_mouseloc[2];
+ TransSeq *ts;
+ Sequence **seq_array;
+ bool *trim;
+ int num_seq;
+ bool slow;
+ int slow_offset; /* offset at the point where offset was turned on */
+ NumInput num_input;
} SlipData;
static void transseq_backup(TransSeq *ts, Sequence *seq)
{
- ts->start = seq->start;
- ts->machine = seq->machine;
- ts->startstill = seq->startstill;
- ts->endstill = seq->endstill;
- ts->startdisp = seq->startdisp;
- ts->enddisp = seq->enddisp;
- ts->startofs = seq->startofs;
- ts->endofs = seq->endofs;
- ts->anim_startofs = seq->anim_startofs;
- ts->anim_endofs = seq->anim_endofs;
- ts->len = seq->len;
+ ts->start = seq->start;
+ ts->machine = seq->machine;
+ ts->startstill = seq->startstill;
+ ts->endstill = seq->endstill;
+ ts->startdisp = seq->startdisp;
+ ts->enddisp = seq->enddisp;
+ ts->startofs = seq->startofs;
+ ts->endofs = seq->endofs;
+ ts->anim_startofs = seq->anim_startofs;
+ ts->anim_endofs = seq->anim_endofs;
+ ts->len = seq->len;
}
-
static void transseq_restore(TransSeq *ts, Sequence *seq)
{
- seq->start = ts->start;
- seq->machine = ts->machine;
- seq->startstill = ts->startstill;
- seq->endstill = ts->endstill;
- seq->startdisp = ts->startdisp;
- seq->enddisp = ts->enddisp;
- seq->startofs = ts->startofs;
- seq->endofs = ts->endofs;
- seq->anim_startofs = ts->anim_startofs;
- seq->anim_endofs = ts->anim_endofs;
- seq->len = ts->len;
-}
-
-static int slip_add_sequences_rec(ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool do_trim)
-{
- Sequence *seq;
- int num_items = 0;
-
- for (seq = seqbasep->first; seq; seq = seq->next) {
- if (!do_trim || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
- seq_array[offset + num_items] = seq;
- trim[offset + num_items] = do_trim;
- num_items++;
-
- if (seq->type == SEQ_TYPE_META) {
- /* trim the sub-sequences */
- num_items += slip_add_sequences_rec(&seq->seqbase, seq_array, trim, num_items + offset, false);
- }
- else if (seq->type & SEQ_TYPE_EFFECT) {
- trim[offset + num_items] = false;
- }
- }
- }
-
- return num_items;
+ seq->start = ts->start;
+ seq->machine = ts->machine;
+ seq->startstill = ts->startstill;
+ seq->endstill = ts->endstill;
+ seq->startdisp = ts->startdisp;
+ seq->enddisp = ts->enddisp;
+ seq->startofs = ts->startofs;
+ seq->endofs = ts->endofs;
+ seq->anim_startofs = ts->anim_startofs;
+ seq->anim_endofs = ts->anim_endofs;
+ seq->len = ts->len;
+}
+
+static int slip_add_sequences_rec(
+ ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool do_trim)
+{
+ Sequence *seq;
+ int num_items = 0;
+
+ for (seq = seqbasep->first; seq; seq = seq->next) {
+ if (!do_trim || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
+ seq_array[offset + num_items] = seq;
+ trim[offset + num_items] = do_trim;
+ num_items++;
+
+ if (seq->type == SEQ_TYPE_META) {
+ /* trim the sub-sequences */
+ num_items += slip_add_sequences_rec(
+ &seq->seqbase, seq_array, trim, num_items + offset, false);
+ }
+ else if (seq->type & SEQ_TYPE_EFFECT) {
+ trim[offset + num_items] = false;
+ }
+ }
+ }
+
+ return num_items;
}
static int slip_count_sequences_rec(ListBase *seqbasep, bool first_level)
{
- Sequence *seq;
- int trimmed_sequences = 0;
+ Sequence *seq;
+ int trimmed_sequences = 0;
- for (seq = seqbasep->first; seq; seq = seq->next) {
- if (!first_level || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
- trimmed_sequences++;
+ for (seq = seqbasep->first; seq; seq = seq->next) {
+ if (!first_level || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
+ trimmed_sequences++;
- if (seq->type == SEQ_TYPE_META) {
- /* trim the sub-sequences */
- trimmed_sequences += slip_count_sequences_rec(&seq->seqbase, false);
- }
- }
- }
+ if (seq->type == SEQ_TYPE_META) {
+ /* trim the sub-sequences */
+ trimmed_sequences += slip_count_sequences_rec(&seq->seqbase, false);
+ }
+ }
+ }
- return trimmed_sequences;
+ return trimmed_sequences;
}
static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- SlipData *data;
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- float mouseloc[2];
- int num_seq, i;
- View2D *v2d = UI_view2d_fromcontext(C);
+ SlipData *data;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ float mouseloc[2];
+ 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);
+ /* first recursively count the trimmed elements */
+ num_seq = slip_count_sequences_rec(ed->seqbasep, true);
- if (num_seq == 0) {
- return OPERATOR_CANCELLED;
- }
+ if (num_seq == 0) {
+ return OPERATOR_CANCELLED;
+ }
- data = op->customdata = MEM_mallocN(sizeof(SlipData), "trimdata");
- data->ts = MEM_mallocN(num_seq * sizeof(TransSeq), "trimdata_transform");
- data->seq_array = MEM_mallocN(num_seq * sizeof(Sequence *), "trimdata_sequences");
- data->trim = MEM_mallocN(num_seq * sizeof(bool), "trimdata_trim");
- data->num_seq = num_seq;
+ data = op->customdata = MEM_mallocN(sizeof(SlipData), "trimdata");
+ data->ts = MEM_mallocN(num_seq * sizeof(TransSeq), "trimdata_transform");
+ data->seq_array = MEM_mallocN(num_seq * sizeof(Sequence *), "trimdata_sequences");
+ data->trim = MEM_mallocN(num_seq * sizeof(bool), "trimdata_trim");
+ data->num_seq = num_seq;
- initNumInput(&data->num_input);
- data->num_input.idx_max = 0;
- data->num_input.val_flag[0] |= NUM_NO_FRACTION;
- data->num_input.unit_sys = USER_UNIT_NONE;
- data->num_input.unit_type[0] = 0;
+ initNumInput(&data->num_input);
+ data->num_input.idx_max = 0;
+ data->num_input.val_flag[0] |= NUM_NO_FRACTION;
+ 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_rec(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]);
+ }
- for (i = 0; i < num_seq; i++) {
- transseq_backup(data->ts + i, data->seq_array[i]);
- }
+ UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
- UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
+ copy_v2_v2_int(data->init_mouse, event->mval);
+ copy_v2_v2(data->init_mouseloc, mouseloc);
- copy_v2_v2_int(data->init_mouse, event->mval);
- copy_v2_v2(data->init_mouseloc, mouseloc);
+ data->slow = false;
- data->slow = false;
+ WM_event_add_modal_handler(C, op);
- WM_event_add_modal_handler(C, op);
+ /* notify so we draw extensions immediately */
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- /* notify so we draw extensions immediately */
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
{
- /* 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;
-
- if (data->trim[i]) {
- /* find the endframe */
- endframe = seq->start + seq->len;
-
- /* 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 (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;
- }
- }
- 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;
- }
-
- /* effects are only added if we they are in a metastrip. 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);
- }
- }
- BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
-
- return true;
- }
-
- return 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;
+
+ if (data->trim[i]) {
+ /* find the endframe */
+ endframe = seq->start + seq->len;
+
+ /* 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 (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;
+ }
+ }
+ 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;
+ }
+
+ /* effects are only added if we they are in a metastrip. 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);
+ }
+ }
+ BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+
+ return true;
+ }
+
+ return false;
}
static int sequencer_slip_exec(bContext *C, wmOperator *op)
{
- SlipData *data;
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- int num_seq, i;
- int offset = RNA_int_get(op->ptr, "offset");
- bool success = false;
+ SlipData *data;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ int num_seq, i;
+ 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);
+ /* first recursively count the trimmed elements */
+ num_seq = slip_count_sequences_rec(ed->seqbasep, true);
- if (num_seq == 0) {
- return OPERATOR_CANCELLED;
- }
+ if (num_seq == 0) {
+ return OPERATOR_CANCELLED;
+ }
- data = op->customdata = MEM_mallocN(sizeof(SlipData), "trimdata");
- data->ts = MEM_mallocN(num_seq * sizeof(TransSeq), "trimdata_transform");
- data->seq_array = MEM_mallocN(num_seq * sizeof(Sequence *), "trimdata_sequences");
- data->trim = MEM_mallocN(num_seq * sizeof(bool), "trimdata_trim");
- data->num_seq = num_seq;
+ data = op->customdata = MEM_mallocN(sizeof(SlipData), "trimdata");
+ data->ts = MEM_mallocN(num_seq * sizeof(TransSeq), "trimdata_transform");
+ data->seq_array = MEM_mallocN(num_seq * sizeof(Sequence *), "trimdata_sequences");
+ 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_rec(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]);
- }
+ for (i = 0; i < num_seq; i++) {
+ transseq_backup(data->ts + i, data->seq_array[i]);
+ }
- success = sequencer_slip_recursively(scene, data, offset);
+ success = sequencer_slip_recursively(scene, data, offset);
- MEM_freeN(data->seq_array);
- MEM_freeN(data->trim);
- MEM_freeN(data->ts);
- MEM_freeN(data);
+ MEM_freeN(data->seq_array);
+ MEM_freeN(data->trim);
+ MEM_freeN(data->ts);
+ MEM_freeN(data);
- if (success) {
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ if (success) {
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
-
static void sequencer_slip_update_header(Scene *scene, ScrArea *sa, SlipData *data, int offset)
{
- char msg[UI_MAX_DRAW_STR];
+ char msg[UI_MAX_DRAW_STR];
- if (sa) {
- if (hasNumInput(&data->num_input)) {
- char num_str[NUM_STR_REP_LEN];
- outputNumInput(&data->num_input, num_str, &scene->unit);
- BLI_snprintf(msg, sizeof(msg), IFACE_("Trim offset: %s"), num_str);
- }
- else {
- BLI_snprintf(msg, sizeof(msg), IFACE_("Trim offset: %d"), offset);
- }
- }
+ if (sa) {
+ if (hasNumInput(&data->num_input)) {
+ char num_str[NUM_STR_REP_LEN];
+ outputNumInput(&data->num_input, num_str, &scene->unit);
+ BLI_snprintf(msg, sizeof(msg), IFACE_("Trim offset: %s"), num_str);
+ }
+ else {
+ BLI_snprintf(msg, sizeof(msg), IFACE_("Trim offset: %d"), offset);
+ }
+ }
- ED_area_status_text(sa, msg);
+ ED_area_status_text(sa, msg);
}
static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- Scene *scene = CTX_data_scene(C);
- SlipData *data = (SlipData *)op->customdata;
- ScrArea *sa = CTX_wm_area(C);
- const bool has_numInput = hasNumInput(&data->num_input);
- bool handled = true;
-
- /* Modal numinput active, try to handle numeric inputs first... */
- if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &data->num_input, event)) {
- float offset;
- applyNumInput(&data->num_input, &offset);
-
- sequencer_slip_update_header(scene, sa, data, (int)offset);
-
- RNA_int_set(op->ptr, "offset", offset);
-
- if (sequencer_slip_recursively(scene, data, offset)) {
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- }
-
- return OPERATOR_RUNNING_MODAL;
- }
-
- switch (event->type) {
- case MOUSEMOVE:
- {
- if (!has_numInput) {
- float mouseloc[2];
- int offset;
- int mouse_x;
- View2D *v2d = UI_view2d_fromcontext(C);
-
- if (data->slow) {
- mouse_x = event->mval[0] - data->slow_offset;
- mouse_x *= 0.1f;
- mouse_x += data->slow_offset;
- }
- else {
- mouse_x = event->mval[0];
- }
-
-
- /* choose the side based on which side of the playhead the mouse is on */
- 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);
-
- RNA_int_set(op->ptr, "offset", offset);
-
- if (sequencer_slip_recursively(scene, data, offset)) {
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- }
- }
- break;
- }
-
- case LEFTMOUSE:
- case RETKEY:
- case 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);
- }
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
- }
-
- case ESCKEY:
- case RIGHTMOUSE:
- {
- int i;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
-
- for (i = 0; i < data->num_seq; i++) {
- transseq_restore(data->ts + i, data->seq_array[i]);
- }
-
- for (i = 0; i < data->num_seq; i++) {
- Sequence *seq = data->seq_array[i];
- BKE_sequence_reload_new_file(scene, seq, false);
- BKE_sequence_calc(scene, seq);
- }
-
- MEM_freeN(data->seq_array);
- MEM_freeN(data->ts);
- MEM_freeN(data->trim);
- MEM_freeN(data);
- op->customdata = NULL;
-
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
- BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
-
- if (sa) {
- ED_area_status_text(sa, NULL);
- }
-
- return OPERATOR_CANCELLED;
- }
-
- case RIGHTSHIFTKEY:
- case LEFTSHIFTKEY:
- if (!has_numInput) {
- if (event->val == KM_PRESS) {
- data->slow = true;
- data->slow_offset = event->mval[0];
- }
- else if (event->val == KM_RELEASE) {
- data->slow = false;
- }
- }
- break;
-
- default:
- handled = false;
- break;
- }
-
- /* Modal numinput inactive, try to handle numeric inputs last... */
- if (!handled && event->val == KM_PRESS && handleNumInput(C, &data->num_input, event)) {
- float offset;
- applyNumInput(&data->num_input, &offset);
-
- sequencer_slip_update_header(scene, sa, data, (int)offset);
-
- RNA_int_set(op->ptr, "offset", offset);
-
- if (sequencer_slip_recursively(scene, data, offset)) {
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- }
- }
-
- return OPERATOR_RUNNING_MODAL;
+ Scene *scene = CTX_data_scene(C);
+ SlipData *data = (SlipData *)op->customdata;
+ ScrArea *sa = CTX_wm_area(C);
+ const bool has_numInput = hasNumInput(&data->num_input);
+ bool handled = true;
+
+ /* Modal numinput active, try to handle numeric inputs first... */
+ if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &data->num_input, event)) {
+ float offset;
+ applyNumInput(&data->num_input, &offset);
+
+ sequencer_slip_update_header(scene, sa, data, (int)offset);
+
+ RNA_int_set(op->ptr, "offset", offset);
+
+ if (sequencer_slip_recursively(scene, data, offset)) {
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ switch (event->type) {
+ case MOUSEMOVE: {
+ if (!has_numInput) {
+ float mouseloc[2];
+ int offset;
+ int mouse_x;
+ View2D *v2d = UI_view2d_fromcontext(C);
+
+ if (data->slow) {
+ mouse_x = event->mval[0] - data->slow_offset;
+ mouse_x *= 0.1f;
+ mouse_x += data->slow_offset;
+ }
+ else {
+ mouse_x = event->mval[0];
+ }
+
+ /* choose the side based on which side of the playhead the mouse is on */
+ 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);
+
+ RNA_int_set(op->ptr, "offset", offset);
+
+ if (sequencer_slip_recursively(scene, data, offset)) {
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ }
+ }
+ break;
+ }
+
+ case LEFTMOUSE:
+ case RETKEY:
+ case 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);
+ }
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ return OPERATOR_FINISHED;
+ }
+
+ case ESCKEY:
+ case RIGHTMOUSE: {
+ int i;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+
+ for (i = 0; i < data->num_seq; i++) {
+ transseq_restore(data->ts + i, data->seq_array[i]);
+ }
+
+ for (i = 0; i < data->num_seq; i++) {
+ Sequence *seq = data->seq_array[i];
+ BKE_sequence_reload_new_file(scene, seq, false);
+ BKE_sequence_calc(scene, seq);
+ }
+
+ MEM_freeN(data->seq_array);
+ MEM_freeN(data->ts);
+ MEM_freeN(data->trim);
+ MEM_freeN(data);
+ op->customdata = NULL;
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+
+ if (sa) {
+ ED_area_status_text(sa, NULL);
+ }
+
+ return OPERATOR_CANCELLED;
+ }
+
+ case RIGHTSHIFTKEY:
+ case LEFTSHIFTKEY:
+ if (!has_numInput) {
+ if (event->val == KM_PRESS) {
+ data->slow = true;
+ data->slow_offset = event->mval[0];
+ }
+ else if (event->val == KM_RELEASE) {
+ data->slow = false;
+ }
+ }
+ break;
+
+ default:
+ handled = false;
+ break;
+ }
+
+ /* Modal numinput inactive, try to handle numeric inputs last... */
+ if (!handled && event->val == KM_PRESS && handleNumInput(C, &data->num_input, event)) {
+ float offset;
+ applyNumInput(&data->num_input, &offset);
+
+ sequencer_slip_update_header(scene, sa, data, (int)offset);
+
+ RNA_int_set(op->ptr, "offset", offset);
+
+ if (sequencer_slip_recursively(scene, data, offset)) {
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
void SEQUENCER_OT_slip(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Trim Strips";
- ot->idname = "SEQUENCER_OT_slip";
- ot->description = "Trim the contents of the active strip";
+ /* identifiers */
+ ot->name = "Trim Strips";
+ ot->idname = "SEQUENCER_OT_slip";
+ ot->description = "Trim the contents of the active strip";
- /* api callbacks */
- ot->invoke = sequencer_slip_invoke;
- ot->modal = sequencer_slip_modal;
- ot->exec = sequencer_slip_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->invoke = sequencer_slip_invoke;
+ ot->modal = sequencer_slip_modal;
+ ot->exec = sequencer_slip_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_int(ot->srna, "offset", 0, INT32_MIN, INT32_MAX, "Offset", "Offset to the data of the strip",
- INT32_MIN, INT32_MAX);
+ RNA_def_int(ot->srna,
+ "offset",
+ 0,
+ INT32_MIN,
+ INT32_MAX,
+ "Offset",
+ "Offset to the data of the strip",
+ INT32_MIN,
+ INT32_MAX);
}
/* mute operator */
static int sequencer_mute_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq;
- bool selected;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+ bool selected;
- selected = !RNA_boolean_get(op->ptr, "unselected");
+ selected = !RNA_boolean_get(op->ptr, "unselected");
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if ((seq->flag & SEQ_LOCK) == 0) {
- if (selected) { /* mute unselected */
- if (seq->flag & SELECT) {
- seq->flag |= SEQ_MUTE;
- BKE_sequence_invalidate_dependent(scene, seq);
- }
- }
- else {
- if ((seq->flag & SELECT) == 0) {
- seq->flag |= SEQ_MUTE;
- BKE_sequence_invalidate_dependent(scene, seq);
- }
- }
- }
- }
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if ((seq->flag & SEQ_LOCK) == 0) {
+ if (selected) { /* mute unselected */
+ if (seq->flag & SELECT) {
+ seq->flag |= SEQ_MUTE;
+ BKE_sequence_invalidate_dependent(scene, seq);
+ }
+ }
+ else {
+ if ((seq->flag & SELECT) == 0) {
+ seq->flag |= SEQ_MUTE;
+ BKE_sequence_invalidate_dependent(scene, seq);
+ }
+ }
+ }
+ }
- BKE_sequencer_update_muting(ed);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ BKE_sequencer_update_muting(ed);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_mute(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Mute Strips";
- ot->idname = "SEQUENCER_OT_mute";
- ot->description = "Mute (un)selected strips";
+ /* identifiers */
+ ot->name = "Mute Strips";
+ ot->idname = "SEQUENCER_OT_mute";
+ ot->description = "Mute (un)selected strips";
- /* api callbacks */
- ot->exec = sequencer_mute_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->exec = sequencer_mute_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Mute unselected rather than selected strips");
+ RNA_def_boolean(
+ ot->srna, "unselected", 0, "Unselected", "Mute unselected rather than selected strips");
}
-
/* unmute operator */
static int sequencer_unmute_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq;
- bool selected;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+ bool selected;
- selected = !RNA_boolean_get(op->ptr, "unselected");
+ selected = !RNA_boolean_get(op->ptr, "unselected");
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if ((seq->flag & SEQ_LOCK) == 0) {
- if (selected) { /* unmute unselected */
- if (seq->flag & SELECT) {
- seq->flag &= ~SEQ_MUTE;
- BKE_sequence_invalidate_dependent(scene, seq);
- }
- }
- else {
- if ((seq->flag & SELECT) == 0) {
- seq->flag &= ~SEQ_MUTE;
- BKE_sequence_invalidate_dependent(scene, seq);
- }
- }
- }
- }
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if ((seq->flag & SEQ_LOCK) == 0) {
+ if (selected) { /* unmute unselected */
+ if (seq->flag & SELECT) {
+ seq->flag &= ~SEQ_MUTE;
+ BKE_sequence_invalidate_dependent(scene, seq);
+ }
+ }
+ else {
+ if ((seq->flag & SELECT) == 0) {
+ seq->flag &= ~SEQ_MUTE;
+ BKE_sequence_invalidate_dependent(scene, seq);
+ }
+ }
+ }
+ }
- BKE_sequencer_update_muting(ed);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ BKE_sequencer_update_muting(ed);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_unmute(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unmute Strips";
- ot->idname = "SEQUENCER_OT_unmute";
- ot->description = "Unmute (un)selected strips";
+ /* identifiers */
+ ot->name = "Unmute Strips";
+ ot->idname = "SEQUENCER_OT_unmute";
+ ot->description = "Unmute (un)selected strips";
- /* api callbacks */
- ot->exec = sequencer_unmute_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->exec = sequencer_unmute_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Unmute unselected rather than selected strips");
+ RNA_def_boolean(
+ ot->srna, "unselected", 0, "Unselected", "Unmute unselected rather than selected strips");
}
-
/* lock operator */
static int sequencer_lock_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if (seq->flag & SELECT) {
- seq->flag |= SEQ_LOCK;
- }
- }
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (seq->flag & SELECT) {
+ seq->flag |= SEQ_LOCK;
+ }
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_lock(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Lock Strips";
- ot->idname = "SEQUENCER_OT_lock";
- ot->description = "Lock strips so they can't be transformed";
+ /* identifiers */
+ ot->name = "Lock Strips";
+ ot->idname = "SEQUENCER_OT_lock";
+ ot->description = "Lock strips so they can't be transformed";
- /* api callbacks */
- ot->exec = sequencer_lock_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->exec = sequencer_lock_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* unlock operator */
static int sequencer_unlock_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if (seq->flag & SELECT) {
- seq->flag &= ~SEQ_LOCK;
- }
- }
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (seq->flag & SELECT) {
+ seq->flag &= ~SEQ_LOCK;
+ }
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_unlock(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unlock Strips";
- ot->idname = "SEQUENCER_OT_unlock";
- ot->description = "Unlock strips so they can be transformed";
+ /* identifiers */
+ ot->name = "Unlock Strips";
+ ot->idname = "SEQUENCER_OT_unlock";
+ ot->description = "Unlock strips so they can be transformed";
- /* api callbacks */
- ot->exec = sequencer_unlock_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->exec = sequencer_unlock_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* reload operator */
static int sequencer_reload_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq;
- const bool adjust_length = RNA_boolean_get(op->ptr, "adjust_length");
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+ const bool adjust_length = RNA_boolean_get(op->ptr, "adjust_length");
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if (seq->flag & SELECT) {
- BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1);
- BKE_sequence_reload_new_file(scene, seq, !adjust_length);
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (seq->flag & SELECT) {
+ BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1);
+ BKE_sequence_reload_new_file(scene, seq, !adjust_length);
- if (adjust_length) {
- if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
- BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
- }
- }
- }
- }
+ if (adjust_length) {
+ if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
+ BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
+ }
+ }
+ }
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_reload(struct wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Reload Strips";
- ot->idname = "SEQUENCER_OT_reload";
- ot->description = "Reload strips in the sequencer";
+ /* identifiers */
+ ot->name = "Reload Strips";
+ ot->idname = "SEQUENCER_OT_reload";
+ ot->description = "Reload strips in the sequencer";
- /* api callbacks */
- ot->exec = sequencer_reload_exec;
- ot->poll = sequencer_edit_poll;
+ /* 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", 0, "Adjust Length",
- "Adjust length of strips to their data length");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna,
+ "adjust_length",
+ 0,
+ "Adjust Length",
+ "Adjust length of strips to their data length");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* reload operator */
static bool sequencer_refresh_all_poll(bContext *C)
{
- if (G.is_rendering) {
- return 0;
- }
- return sequencer_edit_poll(C);
+ if (G.is_rendering) {
+ return 0;
+ }
+ return sequencer_edit_poll(C);
}
static int sequencer_refresh_all_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
- BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+ BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_refresh_all(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Refresh Sequencer";
- ot->idname = "SEQUENCER_OT_refresh_all";
- ot->description = "Refresh the sequencer editor";
+ /* identifiers */
+ ot->name = "Refresh Sequencer";
+ ot->idname = "SEQUENCER_OT_refresh_all";
+ ot->description = "Refresh the sequencer editor";
- /* api callbacks */
- ot->exec = sequencer_refresh_all_exec;
- ot->poll = sequencer_refresh_all_poll;
+ /* api callbacks */
+ ot->exec = sequencer_refresh_all_exec;
+ ot->poll = sequencer_refresh_all_poll;
}
static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Sequence *seq1, *seq2, *seq3, *last_seq = BKE_sequencer_active_get(scene);
- const char *error_msg;
+ Scene *scene = CTX_data_scene(C);
+ Sequence *seq1, *seq2, *seq3, *last_seq = BKE_sequencer_active_get(scene);
+ const char *error_msg;
- if (!seq_effect_find_selected(scene, last_seq, last_seq->type, &seq1, &seq2, &seq3, &error_msg)) {
- BKE_report(op->reports, RPT_ERROR, error_msg);
- return OPERATOR_CANCELLED;
- }
- /* see reassigning would create a cycle */
- 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");
- return OPERATOR_CANCELLED;
- }
+ if (!seq_effect_find_selected(
+ scene, last_seq, last_seq->type, &seq1, &seq2, &seq3, &error_msg)) {
+ BKE_report(op->reports, RPT_ERROR, error_msg);
+ return OPERATOR_CANCELLED;
+ }
+ /* see reassigning would create a cycle */
+ 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");
+ return OPERATOR_CANCELLED;
+ }
- last_seq->seq1 = seq1;
- last_seq->seq2 = seq2;
- last_seq->seq3 = seq3;
+ last_seq->seq1 = seq1;
+ last_seq->seq2 = seq2;
+ last_seq->seq3 = seq3;
- BKE_sequencer_update_changed_seq_and_deps(scene, last_seq, 1, 1);
+ BKE_sequencer_update_changed_seq_and_deps(scene, last_seq, 1, 1);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static bool sequencer_effect_poll(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
- if (ed) {
- Sequence *last_seq = BKE_sequencer_active_get(scene);
- if (last_seq && (last_seq->type & SEQ_TYPE_EFFECT)) {
- return 1;
- }
- }
+ if (ed) {
+ Sequence *last_seq = BKE_sequencer_active_get(scene);
+ if (last_seq && (last_seq->type & SEQ_TYPE_EFFECT)) {
+ return 1;
+ }
+ }
- return 0;
+ return 0;
}
void SEQUENCER_OT_reassign_inputs(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reassign Inputs";
- ot->idname = "SEQUENCER_OT_reassign_inputs";
- ot->description = "Reassign the inputs for the effect strip";
+ /* identifiers */
+ ot->name = "Reassign Inputs";
+ ot->idname = "SEQUENCER_OT_reassign_inputs";
+ ot->description = "Reassign the inputs for the effect strip";
- /* api callbacks */
- ot->exec = sequencer_reassign_inputs_exec;
- ot->poll = sequencer_effect_poll;
+ /* api callbacks */
+ ot->exec = sequencer_reassign_inputs_exec;
+ ot->poll = sequencer_effect_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
static int sequencer_swap_inputs_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Sequence *seq, *last_seq = BKE_sequencer_active_get(scene);
+ Scene *scene = CTX_data_scene(C);
+ Sequence *seq, *last_seq = BKE_sequencer_active_get(scene);
- if (last_seq->seq1 == NULL || last_seq->seq2 == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No valid inputs to swap");
- return OPERATOR_CANCELLED;
- }
+ if (last_seq->seq1 == NULL || last_seq->seq2 == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No valid inputs to swap");
+ return OPERATOR_CANCELLED;
+ }
- seq = last_seq->seq1;
- last_seq->seq1 = last_seq->seq2;
- last_seq->seq2 = seq;
+ seq = last_seq->seq1;
+ last_seq->seq1 = last_seq->seq2;
+ last_seq->seq2 = seq;
- BKE_sequencer_update_changed_seq_and_deps(scene, last_seq, 1, 1);
+ BKE_sequencer_update_changed_seq_and_deps(scene, last_seq, 1, 1);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_swap_inputs(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Swap Inputs";
- ot->idname = "SEQUENCER_OT_swap_inputs";
- ot->description = "Swap the first two inputs for the effect strip";
+ /* identifiers */
+ ot->name = "Swap Inputs";
+ ot->idname = "SEQUENCER_OT_swap_inputs";
+ ot->description = "Swap the first two inputs for the effect strip";
- /* api callbacks */
- ot->exec = sequencer_swap_inputs_exec;
- ot->poll = sequencer_effect_poll;
+ /* api callbacks */
+ ot->exec = sequencer_swap_inputs_exec;
+ ot->poll = sequencer_effect_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* 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", ""},
- {0, NULL, 0, NULL, NULL},
+ {SEQ_CUT_SOFT, "SOFT", 0, "Soft", ""},
+ {SEQ_CUT_HARD, "HARD", 0, "Hard", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int sequencer_cut_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- int cut_side, cut_hard, cut_frame;
-
- bool changed;
-
- cut_frame = RNA_int_get(op->ptr, "frame");
- cut_hard = RNA_enum_get(op->ptr, "type");
- cut_side = RNA_enum_get(op->ptr, "side");
-
- if (cut_hard == SEQ_CUT_HARD) {
- changed = cut_seq_list(scene, ed->seqbasep, cut_frame, cut_seq_hard);
- }
- else {
- changed = cut_seq_list(scene, ed->seqbasep, cut_frame, cut_seq_soft);
- }
-
- if (changed) { /* got new strips ? */
- Sequence *seq;
-
- if (cut_side != SEQ_SIDE_BOTH) {
- SEQP_BEGIN (ed, seq)
- {
- if (cut_side == SEQ_SIDE_LEFT) {
- if (seq->startdisp >= cut_frame) {
- seq->flag &= ~SEQ_ALLSEL;
- }
- }
- else {
- if (seq->enddisp <= cut_frame) {
- seq->flag &= ~SEQ_ALLSEL;
- }
- }
- }
- SEQ_END;
- }
-
- SEQP_BEGIN (ed, seq)
- {
- if (seq->seq1 || seq->seq2 || seq->seq3) {
- BKE_sequence_calc(scene, seq);
- }
- }
- SEQ_END;
-
- /* as last: */
- BKE_sequencer_sort(scene);
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ int cut_side, cut_hard, cut_frame;
+
+ bool changed;
+
+ cut_frame = RNA_int_get(op->ptr, "frame");
+ cut_hard = RNA_enum_get(op->ptr, "type");
+ cut_side = RNA_enum_get(op->ptr, "side");
+
+ if (cut_hard == SEQ_CUT_HARD) {
+ changed = cut_seq_list(scene, ed->seqbasep, cut_frame, cut_seq_hard);
+ }
+ else {
+ changed = cut_seq_list(scene, ed->seqbasep, cut_frame, cut_seq_soft);
+ }
+
+ if (changed) { /* got new strips ? */
+ Sequence *seq;
+
+ if (cut_side != SEQ_SIDE_BOTH) {
+ SEQP_BEGIN (ed, seq) {
+ if (cut_side == SEQ_SIDE_LEFT) {
+ if (seq->startdisp >= cut_frame) {
+ seq->flag &= ~SEQ_ALLSEL;
+ }
+ }
+ else {
+ if (seq->enddisp <= cut_frame) {
+ seq->flag &= ~SEQ_ALLSEL;
+ }
+ }
+ }
+ SEQ_END;
+ }
+
+ SEQP_BEGIN (ed, seq) {
+ if (seq->seq1 || seq->seq2 || seq->seq3) {
+ BKE_sequence_calc(scene, seq);
+ }
+ }
+ SEQ_END;
+
+ /* as last: */
+ BKE_sequencer_sort(scene);
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
-
static int sequencer_cut_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Scene *scene = CTX_data_scene(C);
- View2D *v2d = UI_view2d_fromcontext(C);
+ 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 cut_side = RNA_enum_get(op->ptr, "side");
+ int cut_frame = CFRA;
- if (cut_side == SEQ_SIDE_MOUSE) {
- if (ED_operator_sequencer_active(C) && v2d) {
- cut_side = mouse_frame_side(v2d, event->mval[0], cut_frame);
- }
- else {
- cut_side = SEQ_SIDE_BOTH;
- }
- }
- RNA_int_set(op->ptr, "frame", cut_frame);
- 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);
+ if (cut_side == SEQ_SIDE_MOUSE) {
+ if (ED_operator_sequencer_active(C) && v2d) {
+ cut_side = mouse_frame_side(v2d, event->mval[0], cut_frame);
+ }
+ else {
+ cut_side = SEQ_SIDE_BOTH;
+ }
+ }
+ RNA_int_set(op->ptr, "frame", cut_frame);
+ 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);
}
-
void SEQUENCER_OT_cut(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Cut Strips";
- ot->idname = "SEQUENCER_OT_cut";
- ot->description = "Cut the selected strips";
-
- /* api callbacks */
- ot->invoke = sequencer_cut_invoke;
- ot->exec = sequencer_cut_exec;
- ot->poll = sequencer_edit_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- PropertyRNA *prop;
- RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be cut", INT_MIN, INT_MAX);
- RNA_def_enum(ot->srna, "type", prop_cut_types, SEQ_CUT_SOFT, "Type", "The type of cut operation to perform on strips");
- prop = RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_MOUSE, "Side", "The side that remains selected after cutting");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* identifiers */
+ ot->name = "Cut Strips";
+ ot->idname = "SEQUENCER_OT_cut";
+ ot->description = "Cut the selected strips";
+
+ /* api callbacks */
+ ot->invoke = sequencer_cut_invoke;
+ ot->exec = sequencer_cut_exec;
+ ot->poll = sequencer_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ PropertyRNA *prop;
+ RNA_def_int(ot->srna,
+ "frame",
+ 0,
+ INT_MIN,
+ INT_MAX,
+ "Frame",
+ "Frame where selected strips will be cut",
+ INT_MIN,
+ INT_MAX);
+ RNA_def_enum(ot->srna,
+ "type",
+ prop_cut_types,
+ SEQ_CUT_SOFT,
+ "Type",
+ "The type of cut operation to perform on strips");
+ prop = RNA_def_enum(ot->srna,
+ "side",
+ prop_side_types,
+ SEQ_SIDE_MOUSE,
+ "Side",
+ "The side that remains selected after cutting");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
#undef SEQ_SIDE_MOUSE
@@ -2233,1873 +2265,1908 @@ void SEQUENCER_OT_cut(struct wmOperatorType *ot)
/* duplicate operator */
static int apply_unique_name_cb(Sequence *seq, void *arg_pt)
{
- Scene *scene = (Scene *)arg_pt;
- char name[sizeof(seq->name) - 2];
-
- BLI_strncpy_utf8(name, seq->name + 2, sizeof(name));
- BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
- BKE_sequencer_dupe_animdata(scene, name, seq->name + 2);
- return 1;
+ Scene *scene = (Scene *)arg_pt;
+ char name[sizeof(seq->name) - 2];
+ BLI_strncpy_utf8(name, seq->name + 2, sizeof(name));
+ BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
+ BKE_sequencer_dupe_animdata(scene, name, seq->name + 2);
+ return 1;
}
static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
- ListBase nseqbase = {NULL, NULL};
+ ListBase nseqbase = {NULL, NULL};
- if (ed == NULL) {
- return OPERATOR_CANCELLED;
- }
+ if (ed == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- BKE_sequence_base_dupli_recursive(scene, scene, &nseqbase, ed->seqbasep, SEQ_DUPE_CONTEXT, 0);
+ BKE_sequence_base_dupli_recursive(scene, scene, &nseqbase, ed->seqbasep, SEQ_DUPE_CONTEXT, 0);
- if (nseqbase.first) {
- Sequence *seq = nseqbase.first;
- /* rely on the nseqbase list being added at the end */
- BLI_movelisttolist(ed->seqbasep, &nseqbase);
+ if (nseqbase.first) {
+ Sequence *seq = nseqbase.first;
+ /* 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);
- }
+ for (; seq; seq = seq->next) {
+ BKE_sequencer_recursive_apply(seq, apply_unique_name_cb, scene);
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
- }
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
void SEQUENCER_OT_duplicate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Duplicate Strips";
- ot->idname = "SEQUENCER_OT_duplicate";
- ot->description = "Duplicate the selected strips";
+ /* identifiers */
+ ot->name = "Duplicate Strips";
+ ot->idname = "SEQUENCER_OT_duplicate";
+ ot->description = "Duplicate the selected strips";
- /* api callbacks */
- ot->exec = sequencer_add_duplicate_exec;
- ot->poll = ED_operator_sequencer_active;
+ /* api callbacks */
+ ot->exec = sequencer_add_duplicate_exec;
+ ot->poll = ED_operator_sequencer_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* to give to transform */
- RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
+ /* to give to transform */
+ RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
}
/* delete operator */
static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq;
- MetaStack *ms;
- 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 */
- nothing_selected = false;
- }
- else {
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if (seq->flag & SELECT) {
- nothing_selected = false;
- break;
- }
- }
- }
-
- if (nothing_selected) {
- return OPERATOR_FINISHED;
- }
-
- /* 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)) {
- del_seq_find_replace_recurs(scene, seq);
- }
- }
- else {
- del_seq_clear_modifiers_recurs(scene, seq);
- }
- }
-
- /* delete all selected strips */
- recurs_del_seq_flag(scene, ed->seqbasep, SELECT, 0);
-
- /* updates lengths etc */
- seq = ed->seqbasep->first;
- while (seq) {
- BKE_sequence_calc(scene, seq);
- seq = seq->next;
- }
-
- /* free parent metas */
- ms = ed->metastack.last;
- while (ms) {
- BKE_sequence_calc(scene, ms->parseq);
- ms = ms->prev;
- }
-
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+ MetaStack *ms;
+ 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 */
+ nothing_selected = false;
+ }
+ else {
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (seq->flag & SELECT) {
+ nothing_selected = false;
+ break;
+ }
+ }
+ }
+
+ if (nothing_selected) {
+ return OPERATOR_FINISHED;
+ }
+
+ /* 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)) {
+ del_seq_find_replace_recurs(scene, seq);
+ }
+ }
+ else {
+ del_seq_clear_modifiers_recurs(scene, seq);
+ }
+ }
+
+ /* delete all selected strips */
+ recurs_del_seq_flag(scene, ed->seqbasep, SELECT, 0);
+
+ /* updates lengths etc */
+ seq = ed->seqbasep->first;
+ while (seq) {
+ BKE_sequence_calc(scene, seq);
+ seq = seq->next;
+ }
+
+ /* free parent metas */
+ ms = ed->metastack.last;
+ while (ms) {
+ BKE_sequence_calc(scene, ms->parseq);
+ ms = ms->prev;
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
}
static int sequencer_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *ar = 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 (event->mval[1] <= 30) {
- return OPERATOR_PASS_THROUGH;
- }
- }
+ if (ar->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;
+ }
+ }
- return WM_operator_confirm(C, op, event);
+ return WM_operator_confirm(C, op, event);
}
void SEQUENCER_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Erase Strips";
- ot->idname = "SEQUENCER_OT_delete";
- ot->description = "Erase selected strips from the sequencer";
+ /* identifiers */
+ ot->name = "Erase Strips";
+ ot->idname = "SEQUENCER_OT_delete";
+ ot->description = "Erase selected strips from the sequencer";
- /* api callbacks */
- ot->invoke = sequencer_delete_invoke;
- ot->exec = sequencer_delete_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->invoke = sequencer_delete_invoke;
+ ot->exec = sequencer_delete_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/* 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;
+ 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 (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;
- }
- }
+ /* 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 */
- seq = ed->seqbasep->first;
- while (seq) {
- BKE_sequence_calc(scene, seq);
- seq = seq->next;
- }
+ /* updates lengths etc */
+ seq = ed->seqbasep->first;
+ while (seq) {
+ BKE_sequence_calc(scene, seq);
+ seq = seq->next;
+ }
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if ((seq->type & SEQ_TYPE_EFFECT) == 0 && (seq->flag & SELECT)) {
- if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
- BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
- }
- }
- }
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if ((seq->type & SEQ_TYPE_EFFECT) == 0 && (seq->flag & SELECT)) {
+ if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
+ BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
+ }
+ }
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
void SEQUENCER_OT_offset_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Strip Offset";
- ot->idname = "SEQUENCER_OT_offset_clear";
- ot->description = "Clear strip offsets from the start and end frames";
+ /* 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 */
- ot->exec = sequencer_offset_clear_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->exec = sequencer_offset_clear_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/* separate_images operator */
static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq, *seq_new;
- Strip *strip_new;
- StripElem *se, *se_new;
- int start_ofs, cfra, frame_end;
- int step = RNA_int_get(op->ptr, "length");
+ Sequence *seq, *seq_new;
+ Strip *strip_new;
+ StripElem *se, *se_new;
+ 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;
+ 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,
- * see seq_free_sequence below for the real freeing. */
- BLI_remlink(ed->seqbasep, seq);
- /* if (seq->ipo) id_us_min(&seq->ipo->id); */
- /* XXX, remove fcurve and assign to split image strips */
+ /* 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); */
+ /* XXX, remove fcurve and assign to split image strips */
- start_ofs = cfra = BKE_sequence_tx_get_final_left(seq, false);
- frame_end = BKE_sequence_tx_get_final_right(seq, false);
+ start_ofs = cfra = BKE_sequence_tx_get_final_left(seq, false);
+ frame_end = BKE_sequence_tx_get_final_right(seq, false);
- while (cfra < frame_end) {
- /* new seq */
- se = BKE_sequencer_give_stripelem(seq, cfra);
+ while (cfra < frame_end) {
+ /* new seq */
+ se = BKE_sequencer_give_stripelem(seq, cfra);
- seq_new = BKE_sequence_dupli_recursive(scene, scene, ed->seqbasep, seq, SEQ_DUPE_UNIQUE_NAME);
+ seq_new = BKE_sequence_dupli_recursive(
+ scene, scene, ed->seqbasep, seq, SEQ_DUPE_UNIQUE_NAME);
- seq_new->start = start_ofs;
- seq_new->type = SEQ_TYPE_IMAGE;
- seq_new->len = 1;
- seq_new->endstill = step - 1;
+ seq_new->start = start_ofs;
+ seq_new->type = SEQ_TYPE_IMAGE;
+ seq_new->len = 1;
+ seq_new->endstill = step - 1;
- /* new strip */
- strip_new = seq_new->strip;
- strip_new->us = 1;
+ /* new strip */
+ strip_new = seq_new->strip;
+ strip_new->us = 1;
- /* 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));
- BLI_strncpy(se_new->name, se->name, sizeof(se_new->name));
- strip_new->stripdata = se_new;
+ /* 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));
+ BLI_strncpy(se_new->name, se->name, sizeof(se_new->name));
+ strip_new->stripdata = se_new;
- BKE_sequence_calc(scene, seq_new);
+ BKE_sequence_calc(scene, seq_new);
- if (step > 1) {
- seq_new->flag &= ~SEQ_OVERLAP;
- if (BKE_sequence_test_overlap(ed->seqbasep, seq_new)) {
- BKE_sequence_base_shuffle(ed->seqbasep, seq_new, scene);
- }
- }
+ if (step > 1) {
+ seq_new->flag &= ~SEQ_OVERLAP;
+ if (BKE_sequence_test_overlap(ed->seqbasep, seq_new)) {
+ BKE_sequence_base_shuffle(ed->seqbasep, seq_new, scene);
+ }
+ }
- /* XXX, COPY FCURVES */
+ /* XXX, COPY FCURVES */
- cfra++;
- start_ofs += step;
- }
+ cfra++;
+ start_ofs += step;
+ }
- seq_next = seq->next;
- BKE_sequence_free(scene, seq);
- seq = seq_next;
- }
- else {
- seq = seq->next;
- }
- }
+ seq_next = seq->next;
+ BKE_sequence_free(scene, seq);
+ seq = seq_next;
+ }
+ else {
+ seq = seq->next;
+ }
+ }
- /* as last: */
- BKE_sequencer_sort(scene);
+ /* as last: */
+ BKE_sequencer_sort(scene);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-
void SEQUENCER_OT_images_separate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Separate Images";
- ot->idname = "SEQUENCER_OT_images_separate";
- ot->description = "On image sequence strips, it returns a strip for each image";
+ /* 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 */
- ot->exec = sequencer_separate_images_exec;
- ot->invoke = WM_operator_props_popup_confirm;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->exec = sequencer_separate_images_exec;
+ ot->invoke = WM_operator_props_popup_confirm;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_int(ot->srna, "length", 1, 1, INT_MAX, "Length", "Length of each frame", 1, 1000);
+ RNA_def_int(ot->srna, "length", 1, 1, INT_MAX, "Length", "Length of each frame", 1, 1000);
}
-
/* META Operators */
/* separate_meta_toggle operator */
static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *last_seq = BKE_sequencer_active_get(scene);
- MetaStack *ms;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *last_seq = BKE_sequencer_active_get(scene);
+ MetaStack *ms;
- if (last_seq && last_seq->type == SEQ_TYPE_META && last_seq->flag & SELECT) {
- /* Enter Metastrip */
- ms = MEM_mallocN(sizeof(MetaStack), "metastack");
- BLI_addtail(&ed->metastack, ms);
- ms->parseq = last_seq;
- ms->oldbasep = ed->seqbasep;
- copy_v2_v2_int(ms->disp_range, &ms->parseq->startdisp);
+ if (last_seq && last_seq->type == SEQ_TYPE_META && last_seq->flag & SELECT) {
+ /* Enter Metastrip */
+ ms = MEM_mallocN(sizeof(MetaStack), "metastack");
+ BLI_addtail(&ed->metastack, ms);
+ ms->parseq = last_seq;
+ ms->oldbasep = ed->seqbasep;
+ copy_v2_v2_int(ms->disp_range, &ms->parseq->startdisp);
- ed->seqbasep = &last_seq->seqbase;
+ ed->seqbasep = &last_seq->seqbase;
- BKE_sequencer_active_set(scene, NULL);
+ BKE_sequencer_active_set(scene, NULL);
+ }
+ else {
+ /* Exit Metastrip (if possible) */
- }
- else {
- /* Exit Metastrip (if possible) */
+ Sequence *seq;
- Sequence *seq;
+ if (BLI_listbase_is_empty(&ed->metastack)) {
+ return OPERATOR_CANCELLED;
+ }
- if (BLI_listbase_is_empty(&ed->metastack)) {
- return OPERATOR_CANCELLED;
- }
+ ms = ed->metastack.last;
+ BLI_remlink(&ed->metastack, ms);
- ms = ed->metastack.last;
- BLI_remlink(&ed->metastack, ms);
+ ed->seqbasep = ms->oldbasep;
- ed->seqbasep = ms->oldbasep;
+ /* 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);
+ }
- /* 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 */
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ BKE_sequence_calc(scene, seq);
+ }
- /* 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. */
+ /* 2.73+, keeping endpoints is important!
+ * 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]);
- BKE_sequence_single_fix(ms->parseq);
- BKE_sequence_calc(scene, ms->parseq);
+ BKE_sequence_tx_set_final_left(ms->parseq, ms->disp_range[0]);
+ BKE_sequence_tx_set_final_right(ms->parseq, ms->disp_range[1]);
+ BKE_sequence_single_fix(ms->parseq);
+ BKE_sequence_calc(scene, ms->parseq);
#else
- if (BKE_sequence_test_overlap(ed->seqbasep, ms->parseq)) {
- BKE_sequence_base_shuffle(ed->seqbasep, ms->parseq, scene);
- }
+ if (BKE_sequence_test_overlap(ed->seqbasep, ms->parseq)) {
+ BKE_sequence_base_shuffle(ed->seqbasep, ms->parseq, scene);
+ }
#endif
- BKE_sequencer_active_set(scene, ms->parseq);
-
- ms->parseq->flag |= SELECT;
- recurs_sel_seq(ms->parseq);
+ BKE_sequencer_active_set(scene, ms->parseq);
- MEM_freeN(ms);
+ ms->parseq->flag |= SELECT;
+ recurs_sel_seq(ms->parseq);
- }
+ MEM_freeN(ms);
+ }
- BKE_sequencer_update_muting(ed);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ BKE_sequencer_update_muting(ed);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_meta_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Meta Strip";
- ot->idname = "SEQUENCER_OT_meta_toggle";
- ot->description = "Toggle a metastrip (to edit enclosed strips)";
+ /* identifiers */
+ ot->name = "Toggle Meta Strip";
+ ot->idname = "SEQUENCER_OT_meta_toggle";
+ ot->description = "Toggle a metastrip (to edit enclosed strips)";
- /* api callbacks */
- ot->exec = sequencer_meta_toggle_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->exec = sequencer_meta_toggle_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/* separate_meta_make operator */
static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq, *seqm, *next, *last_seq = BKE_sequencer_active_get(scene);
- int channel_max = 1;
+ Sequence *seq, *seqm, *next, *last_seq = BKE_sequencer_active_get(scene);
+ int channel_max = 1;
- if (BKE_sequence_base_isolated_sel_check(ed->seqbasep) == false) {
- BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
- return OPERATOR_CANCELLED;
- }
+ if (BKE_sequence_base_isolated_sel_check(ed->seqbasep) == false) {
+ BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
+ 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); /* channel number set later */
- strcpy(seqm->name + 2, "MetaStrip");
- seqm->type = SEQ_TYPE_META;
- seqm->flag = SELECT;
+ seqm = BKE_sequence_alloc(ed->seqbasep, 1, 1); /* channel number set later */
+ strcpy(seqm->name + 2, "MetaStrip");
+ seqm->type = SEQ_TYPE_META;
+ seqm->flag = SELECT;
- seq = ed->seqbasep->first;
- while (seq) {
- next = seq->next;
- if (seq != seqm && (seq->flag & SELECT)) {
- BKE_sequence_invalidate_cache(scene, seq);
- channel_max = max_ii(seq->machine, channel_max);
- BLI_remlink(ed->seqbasep, seq);
- BLI_addtail(&seqm->seqbase, seq);
- }
- seq = next;
- }
- seqm->machine = last_seq ? last_seq->machine : channel_max;
- BKE_sequence_calc(scene, seqm);
+ seq = ed->seqbasep->first;
+ while (seq) {
+ next = seq->next;
+ if (seq != seqm && (seq->flag & SELECT)) {
+ BKE_sequence_invalidate_cache(scene, seq);
+ channel_max = max_ii(seq->machine, channel_max);
+ BLI_remlink(ed->seqbasep, seq);
+ BLI_addtail(&seqm->seqbase, seq);
+ }
+ seq = next;
+ }
+ seqm->machine = last_seq ? last_seq->machine : channel_max;
+ BKE_sequence_calc(scene, seqm);
- seqm->strip = MEM_callocN(sizeof(Strip), "metastrip");
- seqm->strip->us = 1;
+ seqm->strip = MEM_callocN(sizeof(Strip), "metastrip");
+ seqm->strip->us = 1;
- BKE_sequencer_active_set(scene, seqm);
+ BKE_sequencer_active_set(scene, seqm);
- if (BKE_sequence_test_overlap(ed->seqbasep, seqm)) {
- BKE_sequence_base_shuffle(ed->seqbasep, seqm, scene);
- }
+ if (BKE_sequence_test_overlap(ed->seqbasep, seqm)) {
+ BKE_sequence_base_shuffle(ed->seqbasep, seqm, scene);
+ }
- BKE_sequencer_update_muting(ed);
+ BKE_sequencer_update_muting(ed);
- BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seqm);
+ BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seqm);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_meta_make(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Meta Strip";
- ot->idname = "SEQUENCER_OT_meta_make";
- ot->description = "Group selected strips into a metastrip";
+ /* identifiers */
+ ot->name = "Make Meta Strip";
+ ot->idname = "SEQUENCER_OT_meta_make";
+ ot->description = "Group selected strips into a metastrip";
- /* api callbacks */
- ot->exec = sequencer_meta_make_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->exec = sequencer_meta_make_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
static int seq_depends_on_meta(Sequence *seq, Sequence *seqm)
{
- if (seq == seqm) {
- return 1;
- }
- else if (seq->seq1 && seq_depends_on_meta(seq->seq1, seqm)) {
- return 1;
- }
- else if (seq->seq2 && seq_depends_on_meta(seq->seq2, seqm)) {
- return 1;
- }
- else if (seq->seq3 && seq_depends_on_meta(seq->seq3, seqm)) {
- return 1;
- }
- else {
- return 0;
- }
+ if (seq == seqm) {
+ return 1;
+ }
+ else if (seq->seq1 && seq_depends_on_meta(seq->seq1, seqm)) {
+ return 1;
+ }
+ else if (seq->seq2 && seq_depends_on_meta(seq->seq2, seqm)) {
+ return 1;
+ }
+ else if (seq->seq3 && seq_depends_on_meta(seq->seq3, seqm)) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
/* separate_meta_make operator */
static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq, *last_seq = BKE_sequencer_active_get(scene); /* last_seq checks (ed == NULL) */
+ Sequence *seq, *last_seq = BKE_sequencer_active_get(scene); /* last_seq checks (ed == NULL) */
- if (last_seq == NULL || last_seq->type != SEQ_TYPE_META) {
- return OPERATOR_CANCELLED;
- }
+ if (last_seq == NULL || last_seq->type != SEQ_TYPE_META) {
+ return OPERATOR_CANCELLED;
+ }
- for (seq = last_seq->seqbase.first; seq != NULL; seq = seq->next) {
- BKE_sequence_invalidate_cache(scene, seq);
- }
+ for (seq = last_seq->seqbase.first; seq != NULL; seq = seq->next) {
+ BKE_sequence_invalidate_cache(scene, seq);
+ }
- BLI_movelisttolist(ed->seqbasep, &last_seq->seqbase);
+ BLI_movelisttolist(ed->seqbasep, &last_seq->seqbase);
- BLI_listbase_clear(&last_seq->seqbase);
+ BLI_listbase_clear(&last_seq->seqbase);
- BLI_remlink(ed->seqbasep, last_seq);
- BKE_sequence_free(scene, last_seq);
+ BLI_remlink(ed->seqbasep, last_seq);
+ BKE_sequence_free(scene, last_seq);
- /* 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;
- }
- }
+ /* 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;
+ }
+ }
- recurs_del_seq_flag(scene, ed->seqbasep, SEQ_FLAG_DELETE, 0);
+ 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 */
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if (seq->flag & SELECT) {
- seq->flag &= ~SEQ_OVERLAP;
- if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
- BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
- }
- }
- }
+ /* 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;
+ if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
+ BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
+ }
+ }
+ }
- BKE_sequencer_sort(scene);
- BKE_sequencer_update_muting(ed);
+ BKE_sequencer_sort(scene);
+ BKE_sequencer_update_muting(ed);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_meta_separate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "UnMeta Strip";
- ot->idname = "SEQUENCER_OT_meta_separate";
- ot->description = "Put the contents of a metastrip back in the sequencer";
+ /* 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 */
- ot->exec = sequencer_meta_separate_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->exec = sequencer_meta_separate_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* view_all operator */
static int sequencer_view_all_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = UI_view2d_fromcontext(C);
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ ARegion *ar = CTX_wm_region(C);
+ View2D *v2d = UI_view2d_fromcontext(C);
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- UI_view2d_smooth_view(C, ar, &v2d->tot, smooth_viewtx);
- return OPERATOR_FINISHED;
+ UI_view2d_smooth_view(C, ar, &v2d->tot, smooth_viewtx);
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_view_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View All";
- ot->idname = "SEQUENCER_OT_view_all";
- ot->description = "View all the strips in the sequencer";
+ /* identifiers */
+ ot->name = "View All";
+ ot->idname = "SEQUENCER_OT_view_all";
+ ot->description = "View all the strips in the sequencer";
- /* api callbacks */
- ot->exec = sequencer_view_all_exec;
- ot->poll = ED_operator_sequencer_active;
+ /* api callbacks */
+ ot->exec = sequencer_view_all_exec;
+ ot->poll = ED_operator_sequencer_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
}
static int sequencer_view_frame_exec(bContext *C, wmOperator *op)
{
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- ANIM_center_frame(C, smooth_viewtx);
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ ANIM_center_frame(C, smooth_viewtx);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_view_frame(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Frame";
- ot->idname = "SEQUENCER_OT_view_frame";
- ot->description = "Reset viewable area to show range around current frame";
+ /* identifiers */
+ ot->name = "View Frame";
+ ot->idname = "SEQUENCER_OT_view_frame";
+ ot->description = "Reset viewable area to show range around current frame";
- /* api callbacks */
- ot->exec = sequencer_view_frame_exec;
- ot->poll = ED_operator_sequencer_active;
+ /* api callbacks */
+ ot->exec = sequencer_view_frame_exec;
+ ot->poll = ED_operator_sequencer_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* view_all operator */
static int sequencer_view_all_preview_exec(bContext *C, wmOperator *UNUSED(op))
{
- bScreen *sc = CTX_wm_screen(C);
- ScrArea *area = CTX_wm_area(C);
+ bScreen *sc = CTX_wm_screen(C);
+ ScrArea *area = CTX_wm_area(C);
#if 0
- ARegion *ar = CTX_wm_region(C);
- SpaceSeq *sseq = area->spacedata.first;
- Scene *scene = CTX_data_scene(C);
+ ARegion *ar = CTX_wm_region(C);
+ SpaceSeq *sseq = area->spacedata.first;
+ Scene *scene = CTX_data_scene(C);
#endif
- View2D *v2d = UI_view2d_fromcontext(C);
+ View2D *v2d = UI_view2d_fromcontext(C);
- v2d->cur = v2d->tot;
- UI_view2d_curRect_validate(v2d);
- UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
+ v2d->cur = v2d->tot;
+ UI_view2d_curRect_validate(v2d);
+ UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
#if 0
- /* Like zooming on an image view */
- float zoomX, zoomY;
- int width, height, imgwidth, imgheight;
-
- width = ar->winx;
- height = ar->winy;
-
- seq_reset_imageofs(sseq);
-
- imgwidth = (scene->r.size * scene->r.xsch) / 100;
- imgheight = (scene->r.size * scene->r.ysch) / 100;
-
- /* Apply aspect, dosnt 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 */
- zoomX = ((float)width) / ((float)imgwidth);
- zoomY = ((float)height) / ((float)imgheight);
- sseq->zoom = (zoomX < zoomY) ? zoomX : zoomY;
-
- sseq->zoom = 1.0f / power_of_2(1 / min_ff(zoomX, zoomY));
- }
- else {
- sseq->zoom = 1.0f;
- }
+ /* Like zooming on an image view */
+ float zoomX, zoomY;
+ int width, height, imgwidth, imgheight;
+
+ width = ar->winx;
+ height = ar->winy;
+
+ seq_reset_imageofs(sseq);
+
+ imgwidth = (scene->r.size * scene->r.xsch) / 100;
+ imgheight = (scene->r.size * scene->r.ysch) / 100;
+
+ /* Apply aspect, dosnt 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 */
+ zoomX = ((float)width) / ((float)imgwidth);
+ zoomY = ((float)height) / ((float)imgheight);
+ sseq->zoom = (zoomX < zoomY) ? zoomX : zoomY;
+
+ sseq->zoom = 1.0f / power_of_2(1 / min_ff(zoomX, zoomY));
+ }
+ else {
+ sseq->zoom = 1.0f;
+ }
#endif
- ED_area_tag_redraw(CTX_wm_area(C));
- return OPERATOR_FINISHED;
+ ED_area_tag_redraw(CTX_wm_area(C));
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_view_all_preview(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View All";
- ot->idname = "SEQUENCER_OT_view_all_preview";
- ot->description = "Zoom preview to fit in the area";
+ /* identifiers */
+ ot->name = "View All";
+ ot->idname = "SEQUENCER_OT_view_all_preview";
+ ot->description = "Zoom preview to fit in the area";
- /* api callbacks */
- ot->exec = sequencer_view_all_preview_exec;
- ot->poll = ED_operator_sequencer_active;
+ /* api callbacks */
+ ot->exec = sequencer_view_all_preview_exec;
+ ot->poll = ED_operator_sequencer_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
}
-
static int sequencer_view_zoom_ratio_exec(bContext *C, wmOperator *op)
{
- RenderData *rd = &CTX_data_scene(C)->r;
- View2D *v2d = UI_view2d_fromcontext(C);
+ RenderData *rd = &CTX_data_scene(C)->r;
+ View2D *v2d = UI_view2d_fromcontext(C);
- float ratio = RNA_float_get(op->ptr, "ratio");
+ float ratio = RNA_float_get(op->ptr, "ratio");
- float winx = (int)(rd->size * rd->xsch) / 100;
- float winy = (int)(rd->size * rd->ysch) / 100;
+ float winx = (int)(rd->size * rd->xsch) / 100;
+ float winy = (int)(rd->size * rd->ysch) / 100;
- float facx = BLI_rcti_size_x(&v2d->mask) / winx;
- float facy = BLI_rcti_size_y(&v2d->mask) / winy;
+ float facx = BLI_rcti_size_x(&v2d->mask) / winx;
+ float facy = BLI_rcti_size_y(&v2d->mask) / winy;
- BLI_rctf_resize(&v2d->cur, ceilf(winx * facx / ratio + 0.5f), ceilf(winy * facy / ratio + 0.5f));
+ BLI_rctf_resize(&v2d->cur, ceilf(winx * facx / ratio + 0.5f), ceilf(winy * facy / ratio + 0.5f));
- ED_region_tag_redraw(CTX_wm_region(C));
+ ED_region_tag_redraw(CTX_wm_region(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_view_zoom_ratio(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Sequencer View Zoom Ratio";
- ot->idname = "SEQUENCER_OT_view_zoom_ratio";
- ot->description = "Change zoom ratio of sequencer preview";
+ /* identifiers */
+ ot->name = "Sequencer View Zoom Ratio";
+ ot->idname = "SEQUENCER_OT_view_zoom_ratio";
+ ot->description = "Change zoom ratio of sequencer preview";
- /* api callbacks */
- ot->exec = sequencer_view_zoom_ratio_exec;
- ot->poll = ED_operator_sequencer_active;
+ /* api callbacks */
+ ot->exec = sequencer_view_zoom_ratio_exec;
+ ot->poll = ED_operator_sequencer_active;
- /* properties */
- RNA_def_float(ot->srna, "ratio", 1.0f, -FLT_MAX, FLT_MAX,
- "Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out", -FLT_MAX, FLT_MAX);
+ /* properties */
+ RNA_def_float(ot->srna,
+ "ratio",
+ 1.0f,
+ -FLT_MAX,
+ FLT_MAX,
+ "Ratio",
+ "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out",
+ -FLT_MAX,
+ FLT_MAX);
}
-
#if 0
static const EnumPropertyItem view_type_items[] = {
- {SEQ_VIEW_SEQUENCE, "SEQUENCER", ICON_SEQ_SEQUENCER, "Sequencer", ""},
- {SEQ_VIEW_PREVIEW, "PREVIEW", ICON_SEQ_PREVIEW, "Image Preview", ""},
- {SEQ_VIEW_SEQUENCE_PREVIEW, "SEQUENCER_PREVIEW", ICON_SEQ_SEQUENCER, "Sequencer and Image Preview", ""},
- {0, NULL, 0, NULL, NULL},
+ {SEQ_VIEW_SEQUENCE, "SEQUENCER", ICON_SEQ_SEQUENCER, "Sequencer", ""},
+ {SEQ_VIEW_PREVIEW, "PREVIEW", ICON_SEQ_PREVIEW, "Image Preview", ""},
+ {SEQ_VIEW_SEQUENCE_PREVIEW, "SEQUENCER_PREVIEW", ICON_SEQ_SEQUENCER, "Sequencer and Image Preview", ""},
+ {0, NULL, 0, NULL, NULL},
};
#endif
/* view_all operator */
static int sequencer_view_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceSeq *sseq = (SpaceSeq *)CTX_wm_space_data(C);
+ SpaceSeq *sseq = (SpaceSeq *)CTX_wm_space_data(C);
- sseq->view++;
- if (sseq->view > SEQ_VIEW_SEQUENCE_PREVIEW) {
- sseq->view = SEQ_VIEW_SEQUENCE;
- }
+ sseq->view++;
+ if (sseq->view > SEQ_VIEW_SEQUENCE_PREVIEW) {
+ sseq->view = SEQ_VIEW_SEQUENCE;
+ }
- ED_area_tag_refresh(CTX_wm_area(C));
+ ED_area_tag_refresh(CTX_wm_area(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_view_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Toggle";
- ot->idname = "SEQUENCER_OT_view_toggle";
- ot->description = "Toggle between sequencer views (sequence, preview, both)";
+ /* identifiers */
+ ot->name = "View Toggle";
+ ot->idname = "SEQUENCER_OT_view_toggle";
+ ot->description = "Toggle between sequencer views (sequence, preview, both)";
- /* api callbacks */
- ot->exec = sequencer_view_toggle_exec;
- ot->poll = ED_operator_sequencer_active;
+ /* api callbacks */
+ ot->exec = sequencer_view_toggle_exec;
+ ot->poll = ED_operator_sequencer_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
}
-
/* 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);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *last_seq = BKE_sequencer_active_get(scene);
- Sequence *seq;
- rctf cur_new = v2d->cur;
-
- int xmin = MAXFRAME * 2;
- int xmax = -MAXFRAME * 2;
- int ymin = MAXSEQ + 1;
- int ymax = 0;
- int orig_height;
- int ymid;
- int ymargin = 1;
- int xmargin = FPS;
+ Scene *scene = CTX_data_scene(C);
+ View2D *v2d = UI_view2d_fromcontext(C);
+ ARegion *ar = CTX_wm_region(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *last_seq = BKE_sequencer_active_get(scene);
+ Sequence *seq;
+ rctf cur_new = v2d->cur;
- if (ed == NULL) {
- return OPERATOR_CANCELLED;
- }
+ int xmin = MAXFRAME * 2;
+ int xmax = -MAXFRAME * 2;
+ int ymin = MAXSEQ + 1;
+ int ymax = 0;
+ int orig_height;
+ int ymid;
+ int ymargin = 1;
+ int xmargin = FPS;
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if ((seq->flag & SELECT) || (seq == last_seq)) {
- xmin = min_ii(xmin, seq->startdisp);
- xmax = max_ii(xmax, seq->enddisp);
+ if (ed == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- ymin = min_ii(ymin, seq->machine);
- ymax = max_ii(ymax, seq->machine);
- }
- }
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if ((seq->flag & SELECT) || (seq == last_seq)) {
+ xmin = min_ii(xmin, seq->startdisp);
+ xmax = max_ii(xmax, seq->enddisp);
- if (ymax != 0) {
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ ymin = min_ii(ymin, seq->machine);
+ ymax = max_ii(ymax, seq->machine);
+ }
+ }
- xmax += xmargin;
- xmin -= xmargin;
- ymax += ymargin;
- ymin -= ymargin;
+ if (ymax != 0) {
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- orig_height = BLI_rctf_size_y(&cur_new);
+ xmax += xmargin;
+ xmin -= xmargin;
+ ymax += ymargin;
+ ymin -= ymargin;
- cur_new.xmin = xmin;
- cur_new.xmax = xmax;
+ orig_height = BLI_rctf_size_y(&cur_new);
- cur_new.ymin = ymin;
- cur_new.ymax = ymax;
+ cur_new.xmin = xmin;
+ cur_new.xmax = xmax;
- /* only zoom out vertically */
- if (orig_height > BLI_rctf_size_y(&cur_new)) {
- ymid = BLI_rctf_cent_y(&cur_new);
+ cur_new.ymin = ymin;
+ cur_new.ymax = ymax;
- cur_new.ymin = ymid - (orig_height / 2);
- cur_new.ymax = ymid + (orig_height / 2);
- }
+ /* only zoom out vertically */
+ if (orig_height > BLI_rctf_size_y(&cur_new)) {
+ ymid = BLI_rctf_cent_y(&cur_new);
- UI_view2d_smooth_view(C, ar, &cur_new, smooth_viewtx);
+ cur_new.ymin = ymid - (orig_height / 2);
+ cur_new.ymax = ymid + (orig_height / 2);
+ }
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ UI_view2d_smooth_view(C, ar, &cur_new, smooth_viewtx);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void SEQUENCER_OT_view_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Selected";
- ot->idname = "SEQUENCER_OT_view_selected";
- ot->description = "Zoom the sequencer on the selected strips";
+ /* identifiers */
+ ot->name = "View Selected";
+ ot->idname = "SEQUENCER_OT_view_selected";
+ ot->description = "Zoom the sequencer on the selected strips";
- /* api callbacks */
- ot->exec = sequencer_view_selected_exec;
- ot->poll = ED_operator_sequencer_active;
+ /* api callbacks */
+ ot->exec = sequencer_view_selected_exec;
+ ot->poll = ED_operator_sequencer_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
}
static bool strip_jump_internal(Scene *scene,
const short side,
- const bool do_skip_mute, const bool do_center)
+ const bool do_skip_mute,
+ const bool do_center)
{
- bool changed = false;
- int cfra = CFRA;
- int nfra = BKE_sequencer_find_next_prev_edit(scene, cfra, side, do_skip_mute, do_center, false);
+ bool changed = false;
+ int cfra = CFRA;
+ int nfra = BKE_sequencer_find_next_prev_edit(scene, cfra, side, do_skip_mute, do_center, false);
- if (nfra != cfra) {
- CFRA = nfra;
- changed = true;
- }
+ if (nfra != cfra) {
+ CFRA = nfra;
+ changed = true;
+ }
- return changed;
+ return changed;
}
static bool sequencer_strip_jump_poll(bContext *C)
{
- /* prevent changes during render */
- if (G.is_rendering) {
- return 0;
- }
+ /* prevent changes during render */
+ if (G.is_rendering) {
+ return 0;
+ }
- return sequencer_edit_poll(C);
+ return sequencer_edit_poll(C);
}
/* jump frame to edit point operator */
static int sequencer_strip_jump_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- const bool next = RNA_boolean_get(op->ptr, "next");
- const bool center = RNA_boolean_get(op->ptr, "center");
+ 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 */
- if (!strip_jump_internal(scene, next ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT, true, center)) {
- return OPERATOR_CANCELLED;
- }
+ /* currently do_skip_mute is always true */
+ if (!strip_jump_internal(scene, next ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT, true, center)) {
+ return OPERATOR_CANCELLED;
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_strip_jump(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Jump to Strip";
- ot->idname = "SEQUENCER_OT_strip_jump";
- ot->description = "Move frame to previous edit point";
+ /* identifiers */
+ ot->name = "Jump to Strip";
+ ot->idname = "SEQUENCER_OT_strip_jump";
+ ot->description = "Move frame to previous edit point";
- /* api callbacks */
- ot->exec = sequencer_strip_jump_exec;
- ot->poll = sequencer_strip_jump_poll;
+ /* api callbacks */
+ ot->exec = sequencer_strip_jump_exec;
+ ot->poll = sequencer_strip_jump_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "next", true, "Next Strip", "");
- RNA_def_boolean(ot->srna, "center", true, "Use strip center", "");
+ /* properties */
+ RNA_def_boolean(ot->srna, "next", true, "Next Strip", "");
+ RNA_def_boolean(ot->srna, "center", true, "Use strip center", "");
}
static void swap_sequence(Scene *scene, Sequence *seqa, Sequence *seqb)
{
- int gap = seqb->startdisp - seqa->enddisp;
- int seq_a_start;
- int seq_b_start;
+ int gap = seqb->startdisp - seqa->enddisp;
+ int seq_a_start;
+ int seq_b_start;
- seq_b_start = (seqb->start - seqb->startdisp) + seqa->startdisp;
- BKE_sequence_translate(scene, seqb, seq_b_start - seqb->start);
- BKE_sequence_calc(scene, seqb);
+ seq_b_start = (seqb->start - seqb->startdisp) + seqa->startdisp;
+ BKE_sequence_translate(scene, seqb, seq_b_start - seqb->start);
+ BKE_sequence_calc(scene, seqb);
- seq_a_start = (seqa->start - seqa->startdisp) + seqb->enddisp + gap;
- BKE_sequence_translate(scene, seqa, seq_a_start - seqa->start);
- BKE_sequence_calc(scene, seqa);
+ seq_a_start = (seqa->start - seqa->startdisp) + seqb->enddisp + gap;
+ BKE_sequence_translate(scene, seqa, seq_a_start - seqa->start);
+ BKE_sequence_calc(scene, seqa);
}
#if 0
static Sequence *sequence_find_parent(Scene *scene, Sequence *child)
{
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *parent = NULL;
- Sequence *seq;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *parent = NULL;
+ Sequence *seq;
- if (ed == NULL) return NULL;
+ if (ed == NULL) return NULL;
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if ((seq != child) && seq_is_parent(seq, child)) {
- parent = seq;
- break;
- }
- }
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if ((seq != child) && seq_is_parent(seq, child)) {
+ parent = seq;
+ break;
+ }
+ }
- return parent;
+ return parent;
}
#endif
static int sequencer_swap_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *active_seq = BKE_sequencer_active_get(scene);
- Sequence *seq, *iseq;
- int side = RNA_enum_get(op->ptr, "side");
-
- if (active_seq == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- seq = find_next_prev_sequence(scene, active_seq, side, -1);
-
- if (seq) {
-
- /* disallow effect strips */
- if (BKE_sequence_effect_get_num_inputs(seq->type) >= 1 && (seq->effectdata || seq->seq1 || seq->seq2 || seq->seq3)) {
- return OPERATOR_CANCELLED;
- }
- if ((BKE_sequence_effect_get_num_inputs(active_seq->type) >= 1) && (active_seq->effectdata || active_seq->seq1 || active_seq->seq2 || active_seq->seq3)) {
- return OPERATOR_CANCELLED;
- }
-
- switch (side) {
- case SEQ_SIDE_LEFT:
- swap_sequence(scene, seq, active_seq);
- break;
- case SEQ_SIDE_RIGHT:
- swap_sequence(scene, active_seq, seq);
- break;
- }
-
- // 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))) {
- BKE_sequence_calc(scene, iseq);
- }
- }
-
- /* 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 */
- if (BKE_sequence_test_overlap(ed->seqbasep, iseq) ) {
- BKE_sequence_base_shuffle(ed->seqbasep, iseq, scene);
- }
- }
- }
-
-
-
- BKE_sequencer_sort(scene);
-
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *active_seq = BKE_sequencer_active_get(scene);
+ Sequence *seq, *iseq;
+ int side = RNA_enum_get(op->ptr, "side");
+
+ if (active_seq == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ seq = find_next_prev_sequence(scene, active_seq, side, -1);
+
+ if (seq) {
+
+ /* disallow effect strips */
+ if (BKE_sequence_effect_get_num_inputs(seq->type) >= 1 &&
+ (seq->effectdata || seq->seq1 || seq->seq2 || seq->seq3)) {
+ return OPERATOR_CANCELLED;
+ }
+ if ((BKE_sequence_effect_get_num_inputs(active_seq->type) >= 1) &&
+ (active_seq->effectdata || active_seq->seq1 || active_seq->seq2 || active_seq->seq3)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (side) {
+ case SEQ_SIDE_LEFT:
+ swap_sequence(scene, seq, active_seq);
+ break;
+ case SEQ_SIDE_RIGHT:
+ swap_sequence(scene, active_seq, seq);
+ break;
+ }
+
+ // 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))) {
+ BKE_sequence_calc(scene, iseq);
+ }
+ }
+
+ /* 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 */
+ if (BKE_sequence_test_overlap(ed->seqbasep, iseq)) {
+ BKE_sequence_base_shuffle(ed->seqbasep, iseq, scene);
+ }
+ }
+ }
+
+ BKE_sequencer_sort(scene);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
}
void SEQUENCER_OT_swap(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Swap Strip";
- ot->idname = "SEQUENCER_OT_swap";
- ot->description = "Swap active strip with strip to the right or left";
+ /* identifiers */
+ ot->name = "Swap Strip";
+ ot->idname = "SEQUENCER_OT_swap";
+ ot->description = "Swap active strip with strip to the right or left";
- /* api callbacks */
- ot->exec = sequencer_swap_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->exec = sequencer_swap_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_enum(ot->srna, "side", prop_side_lr_types, SEQ_SIDE_RIGHT, "Side", "Side of the strip to swap");
+ /* properties */
+ RNA_def_enum(
+ ot->srna, "side", prop_side_lr_types, SEQ_SIDE_RIGHT, "Side", "Side of the strip to swap");
}
static int sequencer_rendersize_exec(bContext *C, wmOperator *UNUSED(op))
{
- int retval = OPERATOR_CANCELLED;
- Scene *scene = CTX_data_scene(C);
- Sequence *active_seq = BKE_sequencer_active_get(scene);
- StripElem *se = NULL;
-
- if (active_seq == NULL) {
- return OPERATOR_CANCELLED;
- }
-
-
- if (active_seq->strip) {
- switch (active_seq->type) {
- case SEQ_TYPE_IMAGE:
- se = BKE_sequencer_give_stripelem(active_seq, scene->r.cfra);
- break;
- case SEQ_TYPE_MOVIE:
- se = active_seq->strip->stripdata;
- break;
- case SEQ_TYPE_SCENE:
- case SEQ_TYPE_META:
- case SEQ_TYPE_SOUND_RAM:
- case SEQ_TYPE_SOUND_HD:
- default:
- break;
- }
- }
-
- if (se) {
- // 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;
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
- retval = OPERATOR_FINISHED;
- }
- }
-
- return retval;
+ int retval = OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ Sequence *active_seq = BKE_sequencer_active_get(scene);
+ StripElem *se = NULL;
+
+ if (active_seq == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (active_seq->strip) {
+ switch (active_seq->type) {
+ case SEQ_TYPE_IMAGE:
+ se = BKE_sequencer_give_stripelem(active_seq, scene->r.cfra);
+ break;
+ case SEQ_TYPE_MOVIE:
+ se = active_seq->strip->stripdata;
+ break;
+ case SEQ_TYPE_SCENE:
+ case SEQ_TYPE_META:
+ case SEQ_TYPE_SOUND_RAM:
+ case SEQ_TYPE_SOUND_HD:
+ default:
+ break;
+ }
+ }
+
+ if (se) {
+ // 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;
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+ retval = OPERATOR_FINISHED;
+ }
+ }
+
+ return retval;
}
void SEQUENCER_OT_rendersize(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Render Size";
- ot->idname = "SEQUENCER_OT_rendersize";
- ot->description = "Set render size and aspect from active sequence";
+ /* identifiers */
+ ot->name = "Set Render Size";
+ ot->idname = "SEQUENCER_OT_rendersize";
+ ot->description = "Set render size and aspect from active sequence";
- /* api callbacks */
- ot->exec = sequencer_rendersize_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->exec = sequencer_rendersize_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
+ /* properties */
}
static void seq_copy_del_sound(Scene *scene, Sequence *seq)
{
- if (seq->type == SEQ_TYPE_META) {
- Sequence *iseq;
- for (iseq = seq->seqbase.first; iseq; iseq = iseq->next) {
- seq_copy_del_sound(scene, iseq);
- }
- }
- else if (seq->scene_sound) {
- BKE_sound_remove_scene_sound(scene, seq->scene_sound);
- seq->scene_sound = NULL;
- }
+ if (seq->type == SEQ_TYPE_META) {
+ Sequence *iseq;
+ for (iseq = seq->seqbase.first; iseq; iseq = iseq->next) {
+ seq_copy_del_sound(scene, iseq);
+ }
+ }
+ else if (seq->scene_sound) {
+ BKE_sound_remove_scene_sound(scene, seq->scene_sound);
+ seq->scene_sound = NULL;
+ }
}
static int sequencer_copy_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);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
- ListBase nseqbase = {NULL, NULL};
+ ListBase nseqbase = {NULL, NULL};
- BKE_sequencer_free_clipboard();
+ BKE_sequencer_free_clipboard();
- if (BKE_sequence_base_isolated_sel_check(ed->seqbasep) == false) {
- BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
- return OPERATOR_CANCELLED;
- }
+ if (BKE_sequence_base_isolated_sel_check(ed->seqbasep) == false) {
+ BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
+ return OPERATOR_CANCELLED;
+ }
- BKE_sequence_base_dupli_recursive(scene, scene, &nseqbase, ed->seqbasep, SEQ_DUPE_UNIQUE_NAME, LIB_ID_CREATE_NO_USER_REFCOUNT);
+ 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);
+ /* 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);
- }
+ 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;
+ 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;
- }
- }
+ if (first_seq->prev) {
+ first_seq->prev->next = NULL;
+ ed->seqbasep->last = first_seq->prev;
+ first_seq->prev = NULL;
+ }
+ }
- seqbase_clipboard_frame = scene->r.cfra;
+ 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) {
- seq_copy_del_sound(scene, seq);
- }
+ /* Need to remove anything that references the current scene */
+ for (Sequence *seq = seqbase_clipboard.first; seq; seq = seq->next) {
+ seq_copy_del_sound(scene, seq);
+ }
- /* Replace datablock pointers with copies, to keep things working in case
- * datablocks get deleted or another .blend file is opened. */
- BKE_sequencer_base_clipboard_pointers_store(bmain, &seqbase_clipboard);
+ /* Replace datablock pointers with copies, to keep things working in case
+ * datablocks get deleted or another .blend file is opened. */
+ BKE_sequencer_base_clipboard_pointers_store(bmain, &seqbase_clipboard);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy";
- ot->idname = "SEQUENCER_OT_copy";
+ /* identifiers */
+ ot->name = "Copy";
+ ot->idname = "SEQUENCER_OT_copy";
- /* api callbacks */
- ot->exec = sequencer_copy_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->exec = sequencer_copy_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
- /* properties */
+ /* 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 */
- ListBase nseqbase = {NULL, NULL};
- int ofs;
- Sequence *iseq, *iseq_first;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, true); /* create if needed */
+ ListBase nseqbase = {NULL, NULL};
+ int ofs;
+ Sequence *iseq, *iseq_first;
- ED_sequencer_deselect_all(scene);
- ofs = scene->r.cfra - seqbase_clipboard_frame;
+ ED_sequencer_deselect_all(scene);
+ ofs = scene->r.cfra - seqbase_clipboard_frame;
- /* Copy strips, temporarily restoring pointers to actual datablocks. This
- * must happen on the clipboard itself, so that copying does user counting
- * on the actual datablocks. */
- 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);
+ /* Copy strips, temporarily restoring pointers to actual datablocks. This
+ * must happen on the clipboard itself, so that copying does user counting
+ * on the actual datablocks. */
+ 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);
- }
- }
+ /* transform pasted strips before adding */
+ if (ofs) {
+ for (iseq = nseqbase.first; iseq; iseq = iseq->next) {
+ BKE_sequence_translate(scene, iseq, ofs);
+ }
+ }
- for (iseq = nseqbase.first; iseq; iseq = iseq->next) {
- BKE_sequence_sound_init(scene, iseq);
- }
+ for (iseq = nseqbase.first; iseq; iseq = iseq->next) {
+ BKE_sequence_sound_init(scene, iseq);
+ }
- iseq_first = nseqbase.first;
+ iseq_first = nseqbase.first;
- BLI_movelisttolist(ed->seqbasep, &nseqbase);
+ 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);
- }
+ /* 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) {
- if (BKE_sequence_test_overlap(ed->seqbasep, iseq)) {
- BKE_sequence_base_shuffle(ed->seqbasep, iseq, scene);
- }
- }
+ /* ensure pasted strips don't overlap */
+ for (iseq = iseq_first; iseq; iseq = iseq->next) {
+ if (BKE_sequence_test_overlap(ed->seqbasep, iseq)) {
+ BKE_sequence_base_shuffle(ed->seqbasep, iseq, scene);
+ }
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_paste(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Paste";
- ot->idname = "SEQUENCER_OT_paste";
+ /* identifiers */
+ ot->name = "Paste";
+ ot->idname = "SEQUENCER_OT_paste";
- /* api callbacks */
- ot->exec = sequencer_paste_exec;
- ot->poll = ED_operator_sequencer_active;
+ /* api callbacks */
+ ot->exec = sequencer_paste_exec;
+ ot->poll = ED_operator_sequencer_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
+ /* properties */
}
static int sequencer_swap_data_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Sequence *seq_act;
- Sequence *seq_other;
- const char *error_msg;
+ Scene *scene = CTX_data_scene(C);
+ Sequence *seq_act;
+ Sequence *seq_other;
+ const char *error_msg;
- if (BKE_sequencer_active_get_pair(scene, &seq_act, &seq_other) == 0) {
- BKE_report(op->reports, RPT_ERROR, "Please select two strips");
- return OPERATOR_CANCELLED;
- }
+ if (BKE_sequencer_active_get_pair(scene, &seq_act, &seq_other) == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Please select two strips");
+ return OPERATOR_CANCELLED;
+ }
- if (BKE_sequence_swap(seq_act, seq_other, &error_msg) == 0) {
- BKE_report(op->reports, RPT_ERROR, error_msg);
- return OPERATOR_CANCELLED;
- }
+ if (BKE_sequence_swap(seq_act, seq_other, &error_msg) == 0) {
+ BKE_report(op->reports, RPT_ERROR, error_msg);
+ return OPERATOR_CANCELLED;
+ }
- if (seq_act->scene_sound) {
- BKE_sound_remove_scene_sound(scene, seq_act->scene_sound);
- }
+ if (seq_act->scene_sound) {
+ BKE_sound_remove_scene_sound(scene, seq_act->scene_sound);
+ }
- if (seq_other->scene_sound) {
- BKE_sound_remove_scene_sound(scene, seq_other->scene_sound);
- }
+ if (seq_other->scene_sound) {
+ BKE_sound_remove_scene_sound(scene, seq_other->scene_sound);
+ }
- seq_act->scene_sound = NULL;
- seq_other->scene_sound = NULL;
+ seq_act->scene_sound = NULL;
+ seq_other->scene_sound = NULL;
- BKE_sequence_calc(scene, seq_act);
- BKE_sequence_calc(scene, seq_other);
+ BKE_sequence_calc(scene, seq_act);
+ BKE_sequence_calc(scene, seq_other);
- if (seq_act->sound) {
- BKE_sound_add_scene_sound_defaults(scene, seq_act);
- }
- if (seq_other->sound) {
- BKE_sound_add_scene_sound_defaults(scene, seq_other);
- }
+ if (seq_act->sound) {
+ BKE_sound_add_scene_sound_defaults(scene, seq_act);
+ }
+ if (seq_other->sound) {
+ BKE_sound_add_scene_sound_defaults(scene, seq_other);
+ }
- BKE_sequence_invalidate_cache(scene, seq_act);
- BKE_sequence_invalidate_cache(scene, seq_other);
+ BKE_sequence_invalidate_cache(scene, seq_act);
+ BKE_sequence_invalidate_cache(scene, seq_other);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_swap_data(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Sequencer Swap Data";
- ot->idname = "SEQUENCER_OT_swap_data";
- ot->description = "Swap 2 sequencer strips";
+ /* identifiers */
+ ot->name = "Sequencer Swap Data";
+ ot->idname = "SEQUENCER_OT_swap_data";
+ ot->description = "Swap 2 sequencer strips";
- /* api callbacks */
- ot->exec = sequencer_swap_data_exec;
- ot->poll = ED_operator_sequencer_active;
+ /* api callbacks */
+ ot->exec = sequencer_swap_data_exec;
+ ot->poll = ED_operator_sequencer_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
+ /* properties */
}
/* box select operator */
static int view_ghost_border_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- View2D *v2d = UI_view2d_fromcontext(C);
+ Scene *scene = CTX_data_scene(C);
+ View2D *v2d = UI_view2d_fromcontext(C);
- rctf rect;
+ rctf rect;
- /* 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);
+ /* 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);
- rect.xmin /= fabsf(BLI_rctf_size_x(&v2d->tot));
- rect.ymin /= fabsf(BLI_rctf_size_y(&v2d->tot));
+ rect.xmin /= fabsf(BLI_rctf_size_x(&v2d->tot));
+ rect.ymin /= fabsf(BLI_rctf_size_y(&v2d->tot));
- rect.xmax /= fabsf(BLI_rctf_size_x(&v2d->tot));
- rect.ymax /= fabsf(BLI_rctf_size_y(&v2d->tot));
+ rect.xmax /= fabsf(BLI_rctf_size_x(&v2d->tot));
+ rect.ymax /= fabsf(BLI_rctf_size_y(&v2d->tot));
- rect.xmin += 0.5f;
- rect.xmax += 0.5f;
- rect.ymin += 0.5f;
- rect.ymax += 0.5f;
+ rect.xmin += 0.5f;
+ rect.xmax += 0.5f;
+ rect.ymin += 0.5f;
+ rect.ymax += 0.5f;
- CLAMP(rect.xmin, 0.0f, 1.0f);
- CLAMP(rect.ymin, 0.0f, 1.0f);
- CLAMP(rect.xmax, 0.0f, 1.0f);
- CLAMP(rect.ymax, 0.0f, 1.0f);
+ CLAMP(rect.xmin, 0.0f, 1.0f);
+ CLAMP(rect.ymin, 0.0f, 1.0f);
+ CLAMP(rect.xmax, 0.0f, 1.0f);
+ CLAMP(rect.ymax, 0.0f, 1.0f);
- scene->ed->over_border = rect;
+ scene->ed->over_border = rect;
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* ****** Box Select ****** */
void SEQUENCER_OT_view_ghost_border(wmOperatorType *ot)
{
- /* 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";
+ /* 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 */
- 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;
+ /* 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 */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
- /* rna */
- WM_operator_properties_gesture_box(ot);
+ /* rna */
+ WM_operator_properties_gesture_box(ot);
}
/* rebuild_proxy operator */
-static int sequencer_rebuild_proxy_invoke(bContext *C, wmOperator *UNUSED(op),
+static int sequencer_rebuild_proxy_invoke(bContext *C,
+ wmOperator *UNUSED(op),
const wmEvent *UNUSED(event))
{
- seq_proxy_build_job(C);
+ seq_proxy_build_job(C);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq;
- GSet *file_list;
+ Main *bmain = CTX_data_main(C);
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+ GSet *file_list;
- if (ed == NULL) {
- return OPERATOR_CANCELLED;
- }
+ if (ed == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list");
+ file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list");
- SEQP_BEGIN(ed, seq)
- {
- if ((seq->flag & SELECT)) {
- ListBase queue = {NULL, NULL};
- LinkData *link;
- short stop = 0, do_update;
- float progress;
+ SEQP_BEGIN (ed, seq) {
+ if ((seq->flag & SELECT)) {
+ ListBase queue = {NULL, NULL};
+ LinkData *link;
+ short stop = 0, do_update;
+ float progress;
- BKE_sequencer_proxy_rebuild_context(bmain, depsgraph, scene, seq, file_list, &queue);
+ BKE_sequencer_proxy_rebuild_context(bmain, depsgraph, scene, seq, file_list, &queue);
- for (link = queue.first; link; link = link->next) {
- struct SeqIndexBuildContext *context = link->data;
- BKE_sequencer_proxy_rebuild(context, &stop, &do_update, &progress);
- BKE_sequencer_proxy_rebuild_finish(context, 0);
- }
- BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
- }
- } SEQ_END;
+ for (link = queue.first; link; link = link->next) {
+ struct SeqIndexBuildContext *context = link->data;
+ BKE_sequencer_proxy_rebuild(context, &stop, &do_update, &progress);
+ BKE_sequencer_proxy_rebuild_finish(context, 0);
+ }
+ BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+ }
+ }
+ SEQ_END;
- BLI_gset_free(file_list, MEM_freeN);
+ BLI_gset_free(file_list, MEM_freeN);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_rebuild_proxy(wmOperatorType *ot)
{
- /* 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";
+ /* 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 */
- ot->invoke = sequencer_rebuild_proxy_invoke;
- ot->exec = sequencer_rebuild_proxy_exec;
+ /* api callbacks */
+ ot->invoke = sequencer_rebuild_proxy_invoke;
+ ot->exec = sequencer_rebuild_proxy_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
}
-static int sequencer_enable_proxies_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+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, 100);
}
static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq;
- bool proxy_25 = RNA_boolean_get(op->ptr, "proxy_25");
- bool proxy_50 = RNA_boolean_get(op->ptr, "proxy_50");
- bool proxy_75 = RNA_boolean_get(op->ptr, "proxy_75");
- bool proxy_100 = RNA_boolean_get(op->ptr, "proxy_100");
- bool overwrite = RNA_boolean_get(op->ptr, "overwrite");
- bool turnon = true;
-
- if (ed == NULL || !(proxy_25 || proxy_50 || proxy_75 || proxy_100)) {
- turnon = false;
- }
-
- SEQP_BEGIN(ed, seq)
- {
- if ((seq->flag & SELECT)) {
- if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_META, SEQ_TYPE_SCENE, SEQ_TYPE_MULTICAM)) {
- BKE_sequencer_proxy_set(seq, turnon);
- if (seq->strip->proxy == NULL) {
- continue;
- }
-
- if (proxy_25) {
- seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_25;
- }
- else {
- seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_25;
- }
-
- if (proxy_50) {
- seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_50;
- }
- else {
- seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_50;
- }
-
- if (proxy_75) {
- seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_75;
- }
- else {
- seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_75;
- }
-
- if (proxy_100) {
- seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_100;
- }
- else {
- seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_100;
- }
-
- if (!overwrite) {
- seq->strip->proxy->build_flags |= SEQ_PROXY_SKIP_EXISTING;
- }
- else {
- seq->strip->proxy->build_flags &= ~SEQ_PROXY_SKIP_EXISTING;
- }
- }
- }
- } SEQ_END;
-
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+ bool proxy_25 = RNA_boolean_get(op->ptr, "proxy_25");
+ bool proxy_50 = RNA_boolean_get(op->ptr, "proxy_50");
+ bool proxy_75 = RNA_boolean_get(op->ptr, "proxy_75");
+ bool proxy_100 = RNA_boolean_get(op->ptr, "proxy_100");
+ bool overwrite = RNA_boolean_get(op->ptr, "overwrite");
+ bool turnon = true;
+
+ if (ed == NULL || !(proxy_25 || proxy_50 || proxy_75 || proxy_100)) {
+ turnon = false;
+ }
+
+ SEQP_BEGIN (ed, seq) {
+ if ((seq->flag & SELECT)) {
+ if (ELEM(seq->type,
+ SEQ_TYPE_MOVIE,
+ SEQ_TYPE_IMAGE,
+ SEQ_TYPE_META,
+ SEQ_TYPE_SCENE,
+ SEQ_TYPE_MULTICAM)) {
+ BKE_sequencer_proxy_set(seq, turnon);
+ if (seq->strip->proxy == NULL) {
+ continue;
+ }
+
+ if (proxy_25) {
+ seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_25;
+ }
+ else {
+ seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_25;
+ }
+
+ if (proxy_50) {
+ seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_50;
+ }
+ else {
+ seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_50;
+ }
+
+ if (proxy_75) {
+ seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_75;
+ }
+ else {
+ seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_75;
+ }
+
+ if (proxy_100) {
+ seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_100;
+ }
+ else {
+ seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_100;
+ }
+
+ if (!overwrite) {
+ seq->strip->proxy->build_flags |= SEQ_PROXY_SKIP_EXISTING;
+ }
+ else {
+ seq->strip->proxy->build_flags &= ~SEQ_PROXY_SKIP_EXISTING;
+ }
+ }
+ }
+ }
+ SEQ_END;
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_enable_proxies(wmOperatorType *ot)
{
- /* 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";
+ /* 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 */
- ot->invoke = sequencer_enable_proxies_invoke;
- ot->exec = sequencer_enable_proxies_exec;
+ /* api callbacks */
+ ot->invoke = sequencer_enable_proxies_invoke;
+ ot->exec = sequencer_enable_proxies_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
- RNA_def_boolean(ot->srna, "proxy_25", false, "25%", "");
- RNA_def_boolean(ot->srna, "proxy_50", false, "50%", "");
- RNA_def_boolean(ot->srna, "proxy_75", false, "75%", "");
- RNA_def_boolean(ot->srna, "proxy_100", false, "100%", "");
- RNA_def_boolean(ot->srna, "overwrite", false, "Overwrite", "");
+ RNA_def_boolean(ot->srna, "proxy_25", false, "25%", "");
+ RNA_def_boolean(ot->srna, "proxy_50", false, "50%", "");
+ RNA_def_boolean(ot->srna, "proxy_75", false, "75%", "");
+ RNA_def_boolean(ot->srna, "proxy_100", false, "100%", "");
+ RNA_def_boolean(ot->srna, "overwrite", false, "Overwrite", "");
}
/* change ops */
static const EnumPropertyItem prop_change_effect_input_types[] = {
- {0, "A_B", 0, "A -> B", ""},
- {1, "B_C", 0, "B -> C", ""},
- {2, "A_C", 0, "A -> C", ""},
- {0, NULL, 0, NULL, NULL},
+ {0, "A_B", 0, "A -> B", ""},
+ {1, "B_C", 0, "B -> C", ""},
+ {2, "A_C", 0, "A -> C", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int sequencer_change_effect_input_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq = BKE_sequencer_active_get(scene);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq = BKE_sequencer_active_get(scene);
- Sequence **seq_1, **seq_2;
+ Sequence **seq_1, **seq_2;
- switch (RNA_enum_get(op->ptr, "swap")) {
- case 0:
- seq_1 = &seq->seq1;
- seq_2 = &seq->seq2;
- break;
- case 1:
- seq_1 = &seq->seq2;
- seq_2 = &seq->seq3;
- break;
- default: /* 2 */
- seq_1 = &seq->seq1;
- seq_2 = &seq->seq3;
- break;
- }
+ switch (RNA_enum_get(op->ptr, "swap")) {
+ case 0:
+ seq_1 = &seq->seq1;
+ seq_2 = &seq->seq2;
+ break;
+ case 1:
+ seq_1 = &seq->seq2;
+ seq_2 = &seq->seq3;
+ break;
+ default: /* 2 */
+ seq_1 = &seq->seq1;
+ seq_2 = &seq->seq3;
+ break;
+ }
- if (*seq_1 == NULL || *seq_2 == NULL) {
- BKE_report(op->reports, RPT_ERROR, "One of the effect inputs is unset, cannot swap");
- return OPERATOR_CANCELLED;
- }
- else {
- SWAP(Sequence *, *seq_1, *seq_2);
- }
+ if (*seq_1 == NULL || *seq_2 == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "One of the effect inputs is unset, cannot swap");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ SWAP(Sequence *, *seq_1, *seq_2);
+ }
- BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1);
+ BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1);
- /* important else we don't get the imbuf cache flushed */
- BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+ /* important else we don't get the imbuf cache flushed */
+ BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_change_effect_input(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Change Effect Input";
- ot->idname = "SEQUENCER_OT_change_effect_input";
+ /* identifiers */
+ ot->name = "Change Effect Input";
+ ot->idname = "SEQUENCER_OT_change_effect_input";
- /* api callbacks */
- ot->exec = sequencer_change_effect_input_exec;
- ot->poll = sequencer_effect_poll;
+ /* api callbacks */
+ ot->exec = sequencer_change_effect_input_exec;
+ ot->poll = sequencer_effect_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* 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");
+ ot->prop = RNA_def_enum(
+ ot->srna, "swap", prop_change_effect_input_types, 0, "Swap", "The effect inputs to swap");
}
static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq = BKE_sequencer_active_get(scene);
- const int new_type = RNA_enum_get(op->ptr, "type");
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq = BKE_sequencer_active_get(scene);
+ const int new_type = RNA_enum_get(op->ptr, "type");
- /* free previous effect and init new effect */
- struct SeqEffectHandle sh;
+ /* free previous effect and init new effect */
+ struct SeqEffectHandle sh;
- if ((seq->type & SEQ_TYPE_EFFECT) == 0) {
- return OPERATOR_CANCELLED;
- }
+ if ((seq->type & SEQ_TYPE_EFFECT) == 0) {
+ return OPERATOR_CANCELLED;
+ }
- /* 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))
- {
- BKE_report(op->reports, RPT_ERROR, "New effect needs more input strips");
- return OPERATOR_CANCELLED;
- }
- else {
- sh = BKE_sequence_get_effect(seq);
- sh.free(seq, true);
+ /* 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)) {
+ BKE_report(op->reports, RPT_ERROR, "New effect needs more input strips");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ sh = BKE_sequence_get_effect(seq);
+ sh.free(seq, true);
- seq->type = new_type;
+ seq->type = new_type;
- sh = BKE_sequence_get_effect(seq);
- sh.init(seq);
- }
+ sh = BKE_sequence_get_effect(seq);
+ sh.init(seq);
+ }
- /* update */
- BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1);
+ /* update */
+ BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1);
- /* important else we don't get the imbuf cache flushed */
- BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+ /* important else we don't get the imbuf cache flushed */
+ BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_change_effect_type(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Change Effect Type";
- ot->idname = "SEQUENCER_OT_change_effect_type";
+ /* identifiers */
+ ot->name = "Change Effect Type";
+ ot->idname = "SEQUENCER_OT_change_effect_type";
- /* api callbacks */
- ot->exec = sequencer_change_effect_type_exec;
- ot->poll = sequencer_effect_poll;
+ /* api callbacks */
+ ot->exec = sequencer_change_effect_type_exec;
+ ot->poll = sequencer_effect_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_TYPE_CROSS, "Type", "Sequencer effect type");
+ ot->prop = RNA_def_enum(ot->srna,
+ "type",
+ sequencer_prop_effect_types,
+ SEQ_TYPE_CROSS,
+ "Type",
+ "Sequencer effect type");
}
static int sequencer_change_path_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);
- Sequence *seq = BKE_sequencer_active_get(scene);
- const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
- const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
- int minframe, numdigits;
-
- if (seq->type == SEQ_TYPE_IMAGE) {
- char directory[FILE_MAX];
- int len;
- StripElem *se;
-
- /* need to find min/max frame for placeholders */
- if (use_placeholders) {
- len = sequencer_image_seq_get_minmax_frame(op, seq->sfra, &minframe, &numdigits);
- }
- else {
- len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
- }
- if (len == 0) {
- return OPERATOR_CANCELLED;
- }
-
- RNA_string_get(op->ptr, "directory", directory);
- if (is_relative_path) {
- /* TODO, shouldn't this already be relative from the filesel?
- * (as the 'filepath' is) for now just make relative here,
- * but look into changing after 2.60 - campbell */
- BLI_path_rel(directory, BKE_main_blendfile_path(bmain));
- }
- BLI_strncpy(seq->strip->dir, directory, sizeof(seq->strip->dir));
-
- if (seq->strip->stripdata) {
- MEM_freeN(seq->strip->stripdata);
- }
- seq->strip->stripdata = se = MEM_callocN(len * sizeof(StripElem), "stripelem");
-
- if (use_placeholders) {
- sequencer_image_seq_reserve_frames(op, se, len, minframe, numdigits);
- }
- else {
- RNA_BEGIN (op->ptr, itemptr, "files")
- {
- char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
- BLI_strncpy(se->name, filename, sizeof(se->name));
- MEM_freeN(filename);
- se++;
- }
- RNA_END;
- }
-
- /* 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 */
- BKE_sequence_reload_new_file(scene, seq, true);
-
- BKE_sequence_calc(scene, seq);
-
- /* important else we don't get the imbuf cache flushed */
- BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
- }
- else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) {
- bSound *sound = seq->sound;
- if (sound == NULL) {
- return OPERATOR_CANCELLED;
- }
- char filepath[FILE_MAX];
- RNA_string_get(op->ptr, "filepath", filepath);
- BLI_strncpy(sound->name, filepath, sizeof(sound->name));
- BKE_sound_load(bmain, sound);
- }
- else {
- /* lame, set rna filepath */
- PointerRNA seq_ptr;
- PropertyRNA *prop;
- char filepath[FILE_MAX];
-
- RNA_pointer_create(&scene->id, &RNA_Sequence, seq, &seq_ptr);
-
- RNA_string_get(op->ptr, "filepath", filepath);
- prop = RNA_struct_find_property(&seq_ptr, "filepath");
- RNA_property_string_set(&seq_ptr, prop, filepath);
- RNA_property_update(C, &seq_ptr, prop);
- }
-
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq = BKE_sequencer_active_get(scene);
+ const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
+ const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
+ int minframe, numdigits;
+
+ if (seq->type == SEQ_TYPE_IMAGE) {
+ char directory[FILE_MAX];
+ int len;
+ StripElem *se;
+
+ /* need to find min/max frame for placeholders */
+ if (use_placeholders) {
+ len = sequencer_image_seq_get_minmax_frame(op, seq->sfra, &minframe, &numdigits);
+ }
+ else {
+ len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
+ }
+ if (len == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ RNA_string_get(op->ptr, "directory", directory);
+ if (is_relative_path) {
+ /* TODO, shouldn't this already be relative from the filesel?
+ * (as the 'filepath' is) for now just make relative here,
+ * but look into changing after 2.60 - campbell */
+ BLI_path_rel(directory, BKE_main_blendfile_path(bmain));
+ }
+ BLI_strncpy(seq->strip->dir, directory, sizeof(seq->strip->dir));
+
+ if (seq->strip->stripdata) {
+ MEM_freeN(seq->strip->stripdata);
+ }
+ seq->strip->stripdata = se = MEM_callocN(len * sizeof(StripElem), "stripelem");
+
+ if (use_placeholders) {
+ sequencer_image_seq_reserve_frames(op, se, len, minframe, numdigits);
+ }
+ else {
+ RNA_BEGIN (op->ptr, itemptr, "files") {
+ char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+ BLI_strncpy(se->name, filename, sizeof(se->name));
+ MEM_freeN(filename);
+ se++;
+ }
+ RNA_END;
+ }
+
+ /* 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 */
+ BKE_sequence_reload_new_file(scene, seq, true);
+
+ BKE_sequence_calc(scene, seq);
+
+ /* important else we don't get the imbuf cache flushed */
+ BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+ }
+ else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) {
+ bSound *sound = seq->sound;
+ if (sound == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ char filepath[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filepath);
+ BLI_strncpy(sound->name, filepath, sizeof(sound->name));
+ BKE_sound_load(bmain, sound);
+ }
+ else {
+ /* lame, set rna filepath */
+ PointerRNA seq_ptr;
+ PropertyRNA *prop;
+ char filepath[FILE_MAX];
+
+ RNA_pointer_create(&scene->id, &RNA_Sequence, seq, &seq_ptr);
+
+ RNA_string_get(op->ptr, "filepath", filepath);
+ prop = RNA_struct_find_property(&seq_ptr, "filepath");
+ RNA_property_string_set(&seq_ptr, prop, filepath);
+ RNA_property_update(C, &seq_ptr, prop);
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
}
static int sequencer_change_path_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Scene *scene = CTX_data_scene(C);
- Sequence *seq = BKE_sequencer_active_get(scene);
- char filepath[FILE_MAX];
+ Scene *scene = CTX_data_scene(C);
+ Sequence *seq = BKE_sequencer_active_get(scene);
+ char filepath[FILE_MAX];
- BLI_join_dirfile(filepath, sizeof(filepath), seq->strip->dir, seq->strip->stripdata->name);
+ BLI_join_dirfile(filepath, sizeof(filepath), seq->strip->dir, seq->strip->stripdata->name);
- RNA_string_set(op->ptr, "directory", seq->strip->dir);
- RNA_string_set(op->ptr, "filepath", filepath);
+ RNA_string_set(op->ptr, "directory", seq->strip->dir);
+ RNA_string_set(op->ptr, "filepath", filepath);
- /* set default display depending on seq type */
- if (seq->type == SEQ_TYPE_IMAGE) {
- RNA_boolean_set(op->ptr, "filter_movie", false);
- }
- else {
- RNA_boolean_set(op->ptr, "filter_image", false);
- }
+ /* set default display depending on seq type */
+ if (seq->type == SEQ_TYPE_IMAGE) {
+ RNA_boolean_set(op->ptr, "filter_movie", false);
+ }
+ else {
+ RNA_boolean_set(op->ptr, "filter_image", false);
+ }
- WM_event_add_fileselect(C, op);
+ WM_event_add_fileselect(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void SEQUENCER_OT_change_path(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Change Data/Files";
- ot->idname = "SEQUENCER_OT_change_path";
+ /* identifiers */
+ ot->name = "Change Data/Files";
+ ot->idname = "SEQUENCER_OT_change_path";
- /* api callbacks */
- ot->exec = sequencer_change_path_exec;
- ot->invoke = sequencer_change_path_invoke;
- ot->poll = sequencer_strip_has_path_poll;
+ /* api callbacks */
+ ot->exec = sequencer_change_path_exec;
+ ot->invoke = sequencer_change_path_invoke;
+ ot->poll = sequencer_strip_has_path_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILEPATH | WM_FILESEL_FILES,
- FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
- RNA_def_boolean(ot->srna, "use_placeholders", false, "Use Placeholders", "Use placeholders for missing frames of the strip");
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILEPATH |
+ WM_FILESEL_FILES,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
+ RNA_def_boolean(ot->srna,
+ "use_placeholders",
+ false,
+ "Use Placeholders",
+ "Use placeholders for missing frames of the strip");
}
-static int sequencer_export_subtitles_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int sequencer_export_subtitles_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
{
- Main *bmain = CTX_data_main(C);
- if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
- char filepath[FILE_MAX];
+ Main *bmain = CTX_data_main(C);
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ char filepath[FILE_MAX];
- if (BKE_main_blendfile_path(bmain)[0] == '\0') {
- BLI_strncpy(filepath, "untitled", sizeof(filepath));
- }
- else {
- BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath));
- }
+ if (BKE_main_blendfile_path(bmain)[0] == '\0') {
+ BLI_strncpy(filepath, "untitled", sizeof(filepath));
+ }
+ else {
+ BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath));
+ }
- BLI_path_extension_replace(filepath, sizeof(filepath), ".srt");
- RNA_string_set(op->ptr, "filepath", filepath);
- }
+ BLI_path_extension_replace(filepath, sizeof(filepath), ".srt");
+ RNA_string_set(op->ptr, "filepath", filepath);
+ }
- WM_event_add_fileselect(C, op);
+ WM_event_add_fileselect(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Sequence *seq, *seq_next;
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- ListBase text_seq = {0};
- int iter = 0;
- FILE *file;
- char filepath[FILE_MAX];
-
- if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
- BKE_report(op->reports, RPT_ERROR, "No filename given");
- return OPERATOR_CANCELLED;
- }
-
- RNA_string_get(op->ptr, "filepath", filepath);
- BLI_path_extension_ensure(filepath, sizeof(filepath), ".srt");
-
- /* Avoid File write exceptions */
- if (!BLI_exists(filepath)) {
- BLI_make_existing_file(filepath);
- if (!BLI_file_touch(filepath)) {
- BKE_report(op->reports, RPT_ERROR, "Can't create subtitle file");
- return OPERATOR_CANCELLED;
- }
- }
- else if (!BLI_file_is_writable(filepath)) {
- BKE_report(op->reports, RPT_ERROR, "Can't overwrite export file");
- return OPERATOR_CANCELLED;
- }
-
- SEQ_BEGIN(ed, seq)
- {
- if (seq->type == SEQ_TYPE_TEXT) {
- BLI_addtail(&text_seq, MEM_dupallocN(seq));
- }
- } SEQ_END;
-
- if (BLI_listbase_is_empty(&text_seq)) {
- BKE_report(op->reports, RPT_ERROR, "No subtitles (text strips) to export");
- return OPERATOR_CANCELLED;
- }
-
- BLI_listbase_sort(&text_seq, BKE_sequencer_cmp_time_startdisp);
-
- /* time to open and write! */
- file = BLI_fopen(filepath, "w");
-
- for (seq = text_seq.first; seq; seq = seq_next) {
- TextVars *data = seq->effectdata;
- char timecode_str_start[32];
- char timecode_str_end[32];
-
- BLI_timecode_string_from_time(timecode_str_start, sizeof(timecode_str_start),
- -2, FRA2TIME(seq->startdisp), FPS, USER_TIMECODE_SUBRIP);
- BLI_timecode_string_from_time(timecode_str_end, sizeof(timecode_str_end),
- -2, FRA2TIME(seq->enddisp), FPS, USER_TIMECODE_SUBRIP);
-
- fprintf(file, "%d\n%s --> %s\n%s\n\n", iter++, timecode_str_start, timecode_str_end, data->text);
-
- seq_next = seq->next;
- MEM_freeN(seq);
- }
-
- fclose(file);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Sequence *seq, *seq_next;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ ListBase text_seq = {0};
+ int iter = 0;
+ FILE *file;
+ char filepath[FILE_MAX];
+
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ BKE_report(op->reports, RPT_ERROR, "No filename given");
+ return OPERATOR_CANCELLED;
+ }
+
+ RNA_string_get(op->ptr, "filepath", filepath);
+ BLI_path_extension_ensure(filepath, sizeof(filepath), ".srt");
+
+ /* Avoid File write exceptions */
+ if (!BLI_exists(filepath)) {
+ BLI_make_existing_file(filepath);
+ if (!BLI_file_touch(filepath)) {
+ BKE_report(op->reports, RPT_ERROR, "Can't create subtitle file");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else if (!BLI_file_is_writable(filepath)) {
+ BKE_report(op->reports, RPT_ERROR, "Can't overwrite export file");
+ return OPERATOR_CANCELLED;
+ }
+
+ SEQ_BEGIN (ed, seq) {
+ if (seq->type == SEQ_TYPE_TEXT) {
+ BLI_addtail(&text_seq, MEM_dupallocN(seq));
+ }
+ }
+ SEQ_END;
+
+ if (BLI_listbase_is_empty(&text_seq)) {
+ BKE_report(op->reports, RPT_ERROR, "No subtitles (text strips) to export");
+ return OPERATOR_CANCELLED;
+ }
+
+ BLI_listbase_sort(&text_seq, BKE_sequencer_cmp_time_startdisp);
+
+ /* time to open and write! */
+ file = BLI_fopen(filepath, "w");
+
+ for (seq = text_seq.first; seq; seq = seq_next) {
+ TextVars *data = seq->effectdata;
+ char timecode_str_start[32];
+ char timecode_str_end[32];
+
+ BLI_timecode_string_from_time(timecode_str_start,
+ sizeof(timecode_str_start),
+ -2,
+ FRA2TIME(seq->startdisp),
+ FPS,
+ USER_TIMECODE_SUBRIP);
+ BLI_timecode_string_from_time(timecode_str_end,
+ sizeof(timecode_str_end),
+ -2,
+ FRA2TIME(seq->enddisp),
+ FPS,
+ USER_TIMECODE_SUBRIP);
+
+ fprintf(
+ file, "%d\n%s --> %s\n%s\n\n", iter++, timecode_str_start, timecode_str_end, data->text);
+
+ seq_next = seq->next;
+ MEM_freeN(seq);
+ }
+
+ fclose(file);
+
+ return OPERATOR_FINISHED;
}
static bool sequencer_strip_is_text_poll(bContext *C)
{
- Editing *ed;
- Sequence *seq;
- return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) && ((seq = ed->act_seq) != NULL) && (seq->type == SEQ_TYPE_TEXT));
+ Editing *ed;
+ Sequence *seq;
+ return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) &&
+ ((seq = ed->act_seq) != NULL) && (seq->type == SEQ_TYPE_TEXT));
}
void SEQUENCER_OT_export_subtitles(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Export Subtitles";
- ot->idname = "SEQUENCER_OT_export_subtitles";
- ot->description = "Export .srt file containing text strips";
-
- /* api callbacks */
- ot->exec = sequencer_export_subtitles_exec;
- ot->invoke = sequencer_export_subtitles_invoke;
- ot->poll = sequencer_strip_is_text_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER, FILE_BLENDER, FILE_SAVE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+ /* identifiers */
+ ot->name = "Export Subtitles";
+ ot->idname = "SEQUENCER_OT_export_subtitles";
+ ot->description = "Export .srt file containing text strips";
+
+ /* api callbacks */
+ ot->exec = sequencer_export_subtitles_exec;
+ ot->invoke = sequencer_export_subtitles_invoke;
+ ot->poll = sequencer_strip_is_text_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER,
+ FILE_BLENDER,
+ FILE_SAVE,
+ WM_FILESEL_FILEPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
}
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index ad3ac79171c..a051071ab61 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -45,10 +45,16 @@ struct wmOperator;
/* space_sequencer.c */
struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa);
-
/* sequencer_draw.c */
void draw_timeline_seq(const struct bContext *C, struct ARegion *ar);
-void sequencer_draw_preview(const struct bContext *C, struct Scene *scene, struct ARegion *ar, struct SpaceSeq *sseq, int cfra, int offset, bool draw_overlay, bool draw_backdrop);
+void sequencer_draw_preview(const struct bContext *C,
+ struct Scene *scene,
+ struct ARegion *ar,
+ struct SpaceSeq *sseq,
+ int cfra,
+ int offset,
+ bool draw_overlay,
+ bool draw_backdrop);
void color3ubv_from_seq(struct Scene *curscene, struct Sequence *seq, unsigned char col[3]);
void sequencer_special_update_set(Sequence *seq);
@@ -56,16 +62,34 @@ void sequencer_special_update_set(Sequence *seq);
/* UNUSED */
// void seq_reset_imageofs(struct SpaceSeq *sseq);
-struct ImBuf *sequencer_ibuf_get(struct Main *bmain, struct Depsgraph *depsgraph, struct Scene *scene, struct SpaceSeq *sseq, int cfra, int frame_ofs, const char *viewname);
+struct ImBuf *sequencer_ibuf_get(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct SpaceSeq *sseq,
+ int cfra,
+ int frame_ofs,
+ const char *viewname);
/* sequencer_edit.c */
struct View2D;
void seq_rectf(struct Sequence *seq, struct rctf *rectf);
void boundbox_seq(struct Scene *scene, struct rctf *rect);
-struct Sequence *find_nearest_seq(struct Scene *scene, struct View2D *v2d, int *hand, const int mval[2]);
-struct Sequence *find_neighboring_sequence(struct Scene *scene, struct Sequence *test, int lr, int sel);
+struct Sequence *find_nearest_seq(struct Scene *scene,
+ struct View2D *v2d,
+ int *hand,
+ const int mval[2]);
+struct Sequence *find_neighboring_sequence(struct Scene *scene,
+ struct Sequence *test,
+ int lr,
+ int sel);
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);
+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);
/* operator helpers */
bool sequencer_edit_poll(struct bContext *C);
@@ -155,23 +179,23 @@ 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_CUT_SOFT,
+ SEQ_CUT_HARD,
};
enum {
- SEQ_SELECTED,
- SEQ_UNSELECTED,
+ SEQ_SELECTED,
+ SEQ_UNSELECTED,
};
enum {
- SEQ_SELECT_LR_NONE = 0,
- SEQ_SELECT_LR_MOUSE,
- SEQ_SELECT_LR_LEFT,
- SEQ_SELECT_LR_RIGHT,
+ SEQ_SELECT_LR_NONE = 0,
+ SEQ_SELECT_LR_MOUSE,
+ SEQ_SELECT_LR_LEFT,
+ SEQ_SELECT_LR_RIGHT,
};
/* defines used internally */
-#define SCE_MARKERS 0 // XXX - dummy
+#define SCE_MARKERS 0 // XXX - dummy
/* sequencer_ops.c */
void sequencer_operatortypes(void);
@@ -201,7 +225,11 @@ void SEQUENCER_OT_sample(struct wmOperatorType *ot);
void sequencer_preview_add_sound(const struct bContext *C, struct Sequence *seq);
/* sequencer_add */
-int sequencer_image_seq_get_minmax_frame(struct wmOperator *op, int sfra, int *r_minframe, int *r_numdigits);
-void sequencer_image_seq_reserve_frames(struct wmOperator *op, struct StripElem *se, int len, int minframe, int numdigits);
+int sequencer_image_seq_get_minmax_frame(struct wmOperator *op,
+ int sfra,
+ int *r_minframe,
+ int *r_numdigits);
+void sequencer_image_seq_reserve_frames(
+ struct wmOperator *op, struct StripElem *se, int len, int minframe, int numdigits);
#endif /* __SEQUENCER_INTERN_H__ */
diff --git a/source/blender/editors/space_sequencer/sequencer_modifier.c b/source/blender/editors/space_sequencer/sequencer_modifier.c
index 41ca52e0431..e00d33853a3 100644
--- a/source/blender/editors/space_sequencer/sequencer_modifier.c
+++ b/source/blender/editors/space_sequencer/sequencer_modifier.c
@@ -17,12 +17,10 @@
* All rights reserved.
*/
-
/** \file
* \ingroup spseq
*/
-
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -37,7 +35,6 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
-
/* own include */
#include "sequencer_intern.h"
@@ -45,237 +42,244 @@
static bool strip_modifier_active_poll(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
- if (ed) {
- Sequence *seq = BKE_sequencer_active_get(scene);
+ if (ed) {
+ Sequence *seq = BKE_sequencer_active_get(scene);
- if (seq) {
- return BKE_sequence_supports_modifiers(seq);
- }
- }
+ if (seq) {
+ return BKE_sequence_supports_modifiers(seq);
+ }
+ }
- return false;
+ return false;
}
static int strip_modifier_add_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Sequence *seq = BKE_sequencer_active_get(scene);
- int type = RNA_enum_get(op->ptr, "type");
+ Scene *scene = CTX_data_scene(C);
+ Sequence *seq = BKE_sequencer_active_get(scene);
+ int type = RNA_enum_get(op->ptr, "type");
- BKE_sequence_modifier_new(seq, NULL, type);
+ BKE_sequence_modifier_new(seq, NULL, type);
- BKE_sequence_invalidate_cache(scene, seq);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ BKE_sequence_invalidate_cache(scene, seq);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_strip_modifier_add(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Add Strip Modifier";
- ot->idname = "SEQUENCER_OT_strip_modifier_add";
- ot->description = "Add a modifier to the strip";
-
- /* api callbacks */
- ot->exec = strip_modifier_add_exec;
- ot->poll = strip_modifier_active_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "type", rna_enum_sequence_modifier_type_items, seqModifierType_ColorBalance, "Type", "");
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Add Strip Modifier";
+ ot->idname = "SEQUENCER_OT_strip_modifier_add";
+ ot->description = "Add a modifier to the strip";
+
+ /* api callbacks */
+ ot->exec = strip_modifier_add_exec;
+ ot->poll = strip_modifier_active_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna,
+ "type",
+ rna_enum_sequence_modifier_type_items,
+ seqModifierType_ColorBalance,
+ "Type",
+ "");
+ ot->prop = prop;
}
/*********************** Remove modifier operator *************************/
static int strip_modifier_remove_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Sequence *seq = BKE_sequencer_active_get(scene);
- char name[MAX_NAME];
- SequenceModifierData *smd;
+ Scene *scene = CTX_data_scene(C);
+ Sequence *seq = BKE_sequencer_active_get(scene);
+ char name[MAX_NAME];
+ SequenceModifierData *smd;
- RNA_string_get(op->ptr, "name", name);
+ RNA_string_get(op->ptr, "name", name);
- smd = BKE_sequence_modifier_find_by_name(seq, name);
- if (!smd) {
- return OPERATOR_CANCELLED;
- }
+ smd = BKE_sequence_modifier_find_by_name(seq, name);
+ if (!smd) {
+ return OPERATOR_CANCELLED;
+ }
- BLI_remlink(&seq->modifiers, smd);
- BKE_sequence_modifier_free(smd);
+ BLI_remlink(&seq->modifiers, smd);
+ BKE_sequence_modifier_free(smd);
- BKE_sequence_invalidate_cache(scene, seq);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ BKE_sequence_invalidate_cache(scene, seq);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_strip_modifier_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Strip Modifier";
- ot->idname = "SEQUENCER_OT_strip_modifier_remove";
- ot->description = "Remove a modifier from the strip";
+ /* identifiers */
+ ot->name = "Remove Strip Modifier";
+ ot->idname = "SEQUENCER_OT_strip_modifier_remove";
+ ot->description = "Remove a modifier from the strip";
- /* api callbacks */
- ot->exec = strip_modifier_remove_exec;
- ot->poll = strip_modifier_active_poll;
+ /* api callbacks */
+ ot->exec = strip_modifier_remove_exec;
+ ot->poll = strip_modifier_active_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_string(ot->srna, "name", "Name", MAX_NAME, "Name", "Name of modifier to remove");
+ /* properties */
+ RNA_def_string(ot->srna, "name", "Name", MAX_NAME, "Name", "Name of modifier to remove");
}
/*********************** Move operator *************************/
enum {
- SEQ_MODIFIER_MOVE_UP = 0,
- SEQ_MODIFIER_MOVE_DOWN,
+ SEQ_MODIFIER_MOVE_UP = 0,
+ SEQ_MODIFIER_MOVE_DOWN,
};
static int strip_modifier_move_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Sequence *seq = BKE_sequencer_active_get(scene);
- char name[MAX_NAME];
- int direction;
- SequenceModifierData *smd;
-
- RNA_string_get(op->ptr, "name", name);
- direction = RNA_enum_get(op->ptr, "direction");
-
- smd = BKE_sequence_modifier_find_by_name(seq, name);
- if (!smd) {
- return OPERATOR_CANCELLED;
- }
-
- if (direction == SEQ_MODIFIER_MOVE_UP) {
- if (smd->prev) {
- BLI_remlink(&seq->modifiers, smd);
- BLI_insertlinkbefore(&seq->modifiers, smd->prev, smd);
- }
- }
- else if (direction == SEQ_MODIFIER_MOVE_DOWN) {
- if (smd->next) {
- BLI_remlink(&seq->modifiers, smd);
- BLI_insertlinkafter(&seq->modifiers, smd->next, smd);
- }
- }
-
- BKE_sequence_invalidate_cache(scene, seq);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Sequence *seq = BKE_sequencer_active_get(scene);
+ char name[MAX_NAME];
+ int direction;
+ SequenceModifierData *smd;
+
+ RNA_string_get(op->ptr, "name", name);
+ direction = RNA_enum_get(op->ptr, "direction");
+
+ smd = BKE_sequence_modifier_find_by_name(seq, name);
+ if (!smd) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (direction == SEQ_MODIFIER_MOVE_UP) {
+ if (smd->prev) {
+ BLI_remlink(&seq->modifiers, smd);
+ BLI_insertlinkbefore(&seq->modifiers, smd->prev, smd);
+ }
+ }
+ else if (direction == SEQ_MODIFIER_MOVE_DOWN) {
+ if (smd->next) {
+ BLI_remlink(&seq->modifiers, smd);
+ BLI_insertlinkafter(&seq->modifiers, smd->next, smd);
+ }
+ }
+
+ BKE_sequence_invalidate_cache(scene, seq);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_strip_modifier_move(wmOperatorType *ot)
{
- static const EnumPropertyItem direction_items[] = {
- {SEQ_MODIFIER_MOVE_UP, "UP", 0, "Up", "Move modifier up in the stack"},
- {SEQ_MODIFIER_MOVE_DOWN, "DOWN", 0, "Down", "Move modifier down in the stack"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Move Strip Modifier";
- ot->idname = "SEQUENCER_OT_strip_modifier_move";
- ot->description = "Move modifier up and down in the stack";
-
- /* api callbacks */
- ot->exec = strip_modifier_move_exec;
- ot->poll = strip_modifier_active_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_string(ot->srna, "name", "Name", MAX_NAME, "Name", "Name of modifier to remove");
- RNA_def_enum(ot->srna, "direction", direction_items, SEQ_MODIFIER_MOVE_UP, "Type", "");
+ static const EnumPropertyItem direction_items[] = {
+ {SEQ_MODIFIER_MOVE_UP, "UP", 0, "Up", "Move modifier up in the stack"},
+ {SEQ_MODIFIER_MOVE_DOWN, "DOWN", 0, "Down", "Move modifier down in the stack"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Move Strip Modifier";
+ ot->idname = "SEQUENCER_OT_strip_modifier_move";
+ ot->description = "Move modifier up and down in the stack";
+
+ /* api callbacks */
+ ot->exec = strip_modifier_move_exec;
+ ot->poll = strip_modifier_active_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_string(ot->srna, "name", "Name", MAX_NAME, "Name", "Name of modifier to remove");
+ RNA_def_enum(ot->srna, "direction", direction_items, SEQ_MODIFIER_MOVE_UP, "Type", "");
}
/*********************** Copy to selected operator *************************/
enum {
- SEQ_MODIFIER_COPY_REPLACE = 0,
- SEQ_MODIFIER_COPY_APPEND = 1,
+ SEQ_MODIFIER_COPY_REPLACE = 0,
+ SEQ_MODIFIER_COPY_APPEND = 1,
};
static int strip_modifier_copy_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = scene->ed;
- Sequence *seq = BKE_sequencer_active_get(scene);
- Sequence *seq_iter;
- const int type = RNA_enum_get(op->ptr, "type");
-
- if (!seq || !seq->modifiers.first) {
- return OPERATOR_CANCELLED;
- }
-
- SEQP_BEGIN(ed, seq_iter)
- {
- if (seq_iter->flag & SELECT) {
- if (seq_iter == seq) {
- continue;
- }
-
- if (type == SEQ_MODIFIER_COPY_REPLACE) {
- if (seq_iter->modifiers.first) {
- SequenceModifierData *smd_tmp, *smd = seq_iter->modifiers.first;
- while (smd) {
- smd_tmp = smd->next;
- BLI_remlink(&seq_iter->modifiers, smd);
- BKE_sequence_modifier_free(smd);
- smd = smd_tmp;
- }
- BLI_listbase_clear(&seq_iter->modifiers);
- }
- }
-
- BKE_sequence_modifier_list_copy(seq_iter, seq);
- }
- } SEQ_END;
-
- BKE_sequence_invalidate_cache(scene, seq);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = scene->ed;
+ Sequence *seq = BKE_sequencer_active_get(scene);
+ Sequence *seq_iter;
+ const int type = RNA_enum_get(op->ptr, "type");
+
+ if (!seq || !seq->modifiers.first) {
+ return OPERATOR_CANCELLED;
+ }
+
+ SEQP_BEGIN (ed, seq_iter) {
+ if (seq_iter->flag & SELECT) {
+ if (seq_iter == seq) {
+ continue;
+ }
+
+ if (type == SEQ_MODIFIER_COPY_REPLACE) {
+ if (seq_iter->modifiers.first) {
+ SequenceModifierData *smd_tmp, *smd = seq_iter->modifiers.first;
+ while (smd) {
+ smd_tmp = smd->next;
+ BLI_remlink(&seq_iter->modifiers, smd);
+ BKE_sequence_modifier_free(smd);
+ smd = smd_tmp;
+ }
+ BLI_listbase_clear(&seq_iter->modifiers);
+ }
+ }
+
+ BKE_sequence_modifier_list_copy(seq_iter, seq);
+ }
+ }
+ SEQ_END;
+
+ BKE_sequence_invalidate_cache(scene, seq);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_strip_modifier_copy(wmOperatorType *ot)
{
- static const EnumPropertyItem type_items[] = {
- {SEQ_MODIFIER_COPY_REPLACE, "REPLACE", 0, "Replace",
- "Replace modifiers in destination"},
- {SEQ_MODIFIER_COPY_APPEND, "APPEND", 0, "Append",
- "Append active modifiers to selected strips"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Copy to Selected Strips";
- ot->idname = "SEQUENCER_OT_strip_modifier_copy";
- ot->description = "Copy modifiers of the active strip to all selected strips";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = strip_modifier_copy_exec;
- ot->poll = strip_modifier_active_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", type_items, SEQ_MODIFIER_COPY_REPLACE, "Type", "");
+ static const EnumPropertyItem type_items[] = {
+ {SEQ_MODIFIER_COPY_REPLACE, "REPLACE", 0, "Replace", "Replace modifiers in destination"},
+ {SEQ_MODIFIER_COPY_APPEND,
+ "APPEND",
+ 0,
+ "Append",
+ "Append active modifiers to selected strips"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Copy to Selected Strips";
+ ot->idname = "SEQUENCER_OT_strip_modifier_copy";
+ ot->description = "Copy modifiers of the active strip to all selected strips";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = strip_modifier_copy_exec;
+ ot->poll = strip_modifier_active_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", type_items, SEQ_MODIFIER_COPY_REPLACE, "Type", "");
}
diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c
index 9a619dd0d9b..6adca28a3fa 100644
--- a/source/blender/editors/space_sequencer/sequencer_ops.c
+++ b/source/blender/editors/space_sequencer/sequencer_ops.c
@@ -38,112 +38,111 @@
#include "sequencer_intern.h"
-
/* ************************** registration **********************************/
-
void sequencer_operatortypes(void)
{
- /* sequencer_edit.c */
- WM_operatortype_append(SEQUENCER_OT_cut);
- WM_operatortype_append(SEQUENCER_OT_slip);
- WM_operatortype_append(SEQUENCER_OT_mute);
- WM_operatortype_append(SEQUENCER_OT_unmute);
- WM_operatortype_append(SEQUENCER_OT_lock);
- WM_operatortype_append(SEQUENCER_OT_unlock);
- WM_operatortype_append(SEQUENCER_OT_reload);
- WM_operatortype_append(SEQUENCER_OT_refresh_all);
- WM_operatortype_append(SEQUENCER_OT_reassign_inputs);
- WM_operatortype_append(SEQUENCER_OT_swap_inputs);
- WM_operatortype_append(SEQUENCER_OT_duplicate);
- WM_operatortype_append(SEQUENCER_OT_delete);
- WM_operatortype_append(SEQUENCER_OT_offset_clear);
- WM_operatortype_append(SEQUENCER_OT_images_separate);
- WM_operatortype_append(SEQUENCER_OT_meta_toggle);
- WM_operatortype_append(SEQUENCER_OT_meta_make);
- WM_operatortype_append(SEQUENCER_OT_meta_separate);
-
- WM_operatortype_append(SEQUENCER_OT_gap_remove);
- WM_operatortype_append(SEQUENCER_OT_gap_insert);
- WM_operatortype_append(SEQUENCER_OT_snap);
- WM_operatortype_append(SEQUENCER_OT_strip_jump);
- WM_operatortype_append(SEQUENCER_OT_swap);
- WM_operatortype_append(SEQUENCER_OT_swap_data);
- WM_operatortype_append(SEQUENCER_OT_rendersize);
-
- WM_operatortype_append(SEQUENCER_OT_export_subtitles);
-
- WM_operatortype_append(SEQUENCER_OT_copy);
- WM_operatortype_append(SEQUENCER_OT_paste);
-
- WM_operatortype_append(SEQUENCER_OT_view_all);
- WM_operatortype_append(SEQUENCER_OT_view_selected);
- WM_operatortype_append(SEQUENCER_OT_view_frame);
- WM_operatortype_append(SEQUENCER_OT_view_all_preview);
- WM_operatortype_append(SEQUENCER_OT_view_toggle);
- WM_operatortype_append(SEQUENCER_OT_view_zoom_ratio);
- WM_operatortype_append(SEQUENCER_OT_view_ghost_border);
-
- WM_operatortype_append(SEQUENCER_OT_rebuild_proxy);
- WM_operatortype_append(SEQUENCER_OT_enable_proxies);
- WM_operatortype_append(SEQUENCER_OT_change_effect_input);
- WM_operatortype_append(SEQUENCER_OT_change_effect_type);
- WM_operatortype_append(SEQUENCER_OT_change_path);
-
- /* sequencer_select.c */
- WM_operatortype_append(SEQUENCER_OT_select_all);
- WM_operatortype_append(SEQUENCER_OT_select);
- WM_operatortype_append(SEQUENCER_OT_select_more);
- WM_operatortype_append(SEQUENCER_OT_select_less);
- WM_operatortype_append(SEQUENCER_OT_select_linked_pick);
- WM_operatortype_append(SEQUENCER_OT_select_linked);
- WM_operatortype_append(SEQUENCER_OT_select_handles);
- WM_operatortype_append(SEQUENCER_OT_select_active_side);
- WM_operatortype_append(SEQUENCER_OT_select_box);
- WM_operatortype_append(SEQUENCER_OT_select_grouped);
-
- /* sequencer_add.c */
- WM_operatortype_append(SEQUENCER_OT_scene_strip_add);
- WM_operatortype_append(SEQUENCER_OT_movieclip_strip_add);
- WM_operatortype_append(SEQUENCER_OT_mask_strip_add);
- WM_operatortype_append(SEQUENCER_OT_movie_strip_add);
- WM_operatortype_append(SEQUENCER_OT_sound_strip_add);
- WM_operatortype_append(SEQUENCER_OT_image_strip_add);
- WM_operatortype_append(SEQUENCER_OT_effect_strip_add);
-
- /* sequencer_buttons.c */
- WM_operatortype_append(SEQUENCER_OT_properties);
-
- /* sequencer_modifiers.c */
- WM_operatortype_append(SEQUENCER_OT_strip_modifier_add);
- WM_operatortype_append(SEQUENCER_OT_strip_modifier_remove);
- WM_operatortype_append(SEQUENCER_OT_strip_modifier_move);
- WM_operatortype_append(SEQUENCER_OT_strip_modifier_copy);
-
- /* sequencer_view.h */
- WM_operatortype_append(SEQUENCER_OT_sample);
+ /* sequencer_edit.c */
+ WM_operatortype_append(SEQUENCER_OT_cut);
+ WM_operatortype_append(SEQUENCER_OT_slip);
+ WM_operatortype_append(SEQUENCER_OT_mute);
+ WM_operatortype_append(SEQUENCER_OT_unmute);
+ WM_operatortype_append(SEQUENCER_OT_lock);
+ WM_operatortype_append(SEQUENCER_OT_unlock);
+ WM_operatortype_append(SEQUENCER_OT_reload);
+ WM_operatortype_append(SEQUENCER_OT_refresh_all);
+ WM_operatortype_append(SEQUENCER_OT_reassign_inputs);
+ WM_operatortype_append(SEQUENCER_OT_swap_inputs);
+ WM_operatortype_append(SEQUENCER_OT_duplicate);
+ WM_operatortype_append(SEQUENCER_OT_delete);
+ WM_operatortype_append(SEQUENCER_OT_offset_clear);
+ WM_operatortype_append(SEQUENCER_OT_images_separate);
+ WM_operatortype_append(SEQUENCER_OT_meta_toggle);
+ WM_operatortype_append(SEQUENCER_OT_meta_make);
+ WM_operatortype_append(SEQUENCER_OT_meta_separate);
+
+ WM_operatortype_append(SEQUENCER_OT_gap_remove);
+ WM_operatortype_append(SEQUENCER_OT_gap_insert);
+ WM_operatortype_append(SEQUENCER_OT_snap);
+ WM_operatortype_append(SEQUENCER_OT_strip_jump);
+ WM_operatortype_append(SEQUENCER_OT_swap);
+ WM_operatortype_append(SEQUENCER_OT_swap_data);
+ WM_operatortype_append(SEQUENCER_OT_rendersize);
+
+ WM_operatortype_append(SEQUENCER_OT_export_subtitles);
+
+ WM_operatortype_append(SEQUENCER_OT_copy);
+ WM_operatortype_append(SEQUENCER_OT_paste);
+
+ WM_operatortype_append(SEQUENCER_OT_view_all);
+ WM_operatortype_append(SEQUENCER_OT_view_selected);
+ WM_operatortype_append(SEQUENCER_OT_view_frame);
+ WM_operatortype_append(SEQUENCER_OT_view_all_preview);
+ WM_operatortype_append(SEQUENCER_OT_view_toggle);
+ WM_operatortype_append(SEQUENCER_OT_view_zoom_ratio);
+ WM_operatortype_append(SEQUENCER_OT_view_ghost_border);
+
+ WM_operatortype_append(SEQUENCER_OT_rebuild_proxy);
+ WM_operatortype_append(SEQUENCER_OT_enable_proxies);
+ WM_operatortype_append(SEQUENCER_OT_change_effect_input);
+ WM_operatortype_append(SEQUENCER_OT_change_effect_type);
+ WM_operatortype_append(SEQUENCER_OT_change_path);
+
+ /* sequencer_select.c */
+ WM_operatortype_append(SEQUENCER_OT_select_all);
+ WM_operatortype_append(SEQUENCER_OT_select);
+ WM_operatortype_append(SEQUENCER_OT_select_more);
+ WM_operatortype_append(SEQUENCER_OT_select_less);
+ WM_operatortype_append(SEQUENCER_OT_select_linked_pick);
+ WM_operatortype_append(SEQUENCER_OT_select_linked);
+ WM_operatortype_append(SEQUENCER_OT_select_handles);
+ WM_operatortype_append(SEQUENCER_OT_select_active_side);
+ WM_operatortype_append(SEQUENCER_OT_select_box);
+ WM_operatortype_append(SEQUENCER_OT_select_grouped);
+
+ /* sequencer_add.c */
+ WM_operatortype_append(SEQUENCER_OT_scene_strip_add);
+ WM_operatortype_append(SEQUENCER_OT_movieclip_strip_add);
+ WM_operatortype_append(SEQUENCER_OT_mask_strip_add);
+ WM_operatortype_append(SEQUENCER_OT_movie_strip_add);
+ WM_operatortype_append(SEQUENCER_OT_sound_strip_add);
+ WM_operatortype_append(SEQUENCER_OT_image_strip_add);
+ WM_operatortype_append(SEQUENCER_OT_effect_strip_add);
+
+ /* sequencer_buttons.c */
+ WM_operatortype_append(SEQUENCER_OT_properties);
+
+ /* sequencer_modifiers.c */
+ WM_operatortype_append(SEQUENCER_OT_strip_modifier_add);
+ WM_operatortype_append(SEQUENCER_OT_strip_modifier_remove);
+ WM_operatortype_append(SEQUENCER_OT_strip_modifier_move);
+ WM_operatortype_append(SEQUENCER_OT_strip_modifier_copy);
+
+ /* sequencer_view.h */
+ WM_operatortype_append(SEQUENCER_OT_sample);
}
-
void sequencer_keymap(wmKeyConfig *keyconf)
{
- /* Common items ------------------------------------------------------------------ */
- WM_keymap_ensure(keyconf, "SequencerCommon", SPACE_SEQ, 0);
+ /* Common items ------------------------------------------------------------------ */
+ WM_keymap_ensure(keyconf, "SequencerCommon", SPACE_SEQ, 0);
- /* Strips Region --------------------------------------------------------------- */
- WM_keymap_ensure(keyconf, "Sequencer", SPACE_SEQ, 0);
+ /* Strips Region --------------------------------------------------------------- */
+ WM_keymap_ensure(keyconf, "Sequencer", SPACE_SEQ, 0);
- /* Preview Region ----------------------------------------------------------- */
- WM_keymap_ensure(keyconf, "SequencerPreview", SPACE_SEQ, 0);
+ /* Preview Region ----------------------------------------------------------- */
+ WM_keymap_ensure(keyconf, "SequencerPreview", SPACE_SEQ, 0);
}
void ED_operatormacros_sequencer(void)
{
- wmOperatorType *ot;
+ wmOperatorType *ot;
- ot = WM_operatortype_append_macro("SEQUENCER_OT_duplicate_move", "Duplicate Strips",
- "Duplicate selected strips and move them", OPTYPE_UNDO | OPTYPE_REGISTER);
+ ot = WM_operatortype_append_macro("SEQUENCER_OT_duplicate_move",
+ "Duplicate Strips",
+ "Duplicate selected strips and move them",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
- WM_operatortype_macro_define(ot, "SEQUENCER_OT_duplicate");
- WM_operatortype_macro_define(ot, "TRANSFORM_OT_seq_slide");
+ WM_operatortype_macro_define(ot, "SEQUENCER_OT_duplicate");
+ WM_operatortype_macro_define(ot, "TRANSFORM_OT_seq_slide");
}
diff --git a/source/blender/editors/space_sequencer/sequencer_preview.c b/source/blender/editors/space_sequencer/sequencer_preview.c
index 640d61a503b..546c2a8a9f0 100644
--- a/source/blender/editors/space_sequencer/sequencer_preview.c
+++ b/source/blender/editors/space_sequencer/sequencer_preview.c
@@ -41,126 +41,129 @@
#include "sequencer_intern.h"
typedef struct PreviewJob {
- ListBase previews;
- ThreadMutex *mutex;
- Scene *scene;
- int total;
- int processed;
+ ListBase previews;
+ ThreadMutex *mutex;
+ Scene *scene;
+ int total;
+ int processed;
} PreviewJob;
typedef struct PreviewJobAudio {
- struct PreviewJobAudio *next, *prev;
- bSound *sound;
- int lr; /* sample left or right */
- int startframe;
- bool waveform; /* reload sound or waveform */
+ struct PreviewJobAudio *next, *prev;
+ bSound *sound;
+ int lr; /* sample left or right */
+ int startframe;
+ bool waveform; /* reload sound or waveform */
} PreviewJobAudio;
static void free_preview_job(void *data)
{
- PreviewJob *pj = (PreviewJob *)data;
+ PreviewJob *pj = (PreviewJob *)data;
- BLI_mutex_free(pj->mutex);
- BLI_freelistN(&pj->previews);
- MEM_freeN(pj);
+ BLI_mutex_free(pj->mutex);
+ BLI_freelistN(&pj->previews);
+ MEM_freeN(pj);
}
/* only this runs inside thread */
static void preview_startjob(void *data, short *stop, short *do_update, float *progress)
{
- PreviewJob *pj = data;
- PreviewJobAudio *previewjb;
-
- BLI_mutex_lock(pj->mutex);
- previewjb = pj->previews.first;
- BLI_mutex_unlock(pj->mutex);
-
- while (previewjb) {
- PreviewJobAudio *preview_next;
- bSound *sound = previewjb->sound;
-
- BKE_sound_read_waveform(sound, stop);
-
- if (*stop || G.is_break) {
- BLI_mutex_lock(pj->mutex);
- previewjb = previewjb->next;
- BLI_mutex_unlock(pj->mutex);
- while (previewjb) {
- sound = previewjb->sound;
-
- /* make sure we cleanup the loading flag! */
- BLI_spin_lock(sound->spinlock);
- sound->tags &= ~SOUND_TAGS_WAVEFORM_LOADING;
- BLI_spin_unlock(sound->spinlock);
-
- BLI_mutex_lock(pj->mutex);
- previewjb = previewjb->next;
- BLI_mutex_unlock(pj->mutex);
- }
-
- BLI_mutex_lock(pj->mutex);
- BLI_freelistN(&pj->previews);
- pj->total = 0;
- pj->processed = 0;
- BLI_mutex_unlock(pj->mutex);
- break;
- }
-
- BLI_mutex_lock(pj->mutex);
- preview_next = previewjb->next;
- BLI_freelinkN(&pj->previews, previewjb);
- previewjb = preview_next;
- pj->processed++;
- *progress = (pj->total > 0) ? (float)pj->processed / (float)pj->total : 1.0f;
- *do_update = true;
- BLI_mutex_unlock(pj->mutex);
- }
+ PreviewJob *pj = data;
+ PreviewJobAudio *previewjb;
+
+ BLI_mutex_lock(pj->mutex);
+ previewjb = pj->previews.first;
+ BLI_mutex_unlock(pj->mutex);
+
+ while (previewjb) {
+ PreviewJobAudio *preview_next;
+ bSound *sound = previewjb->sound;
+
+ BKE_sound_read_waveform(sound, stop);
+
+ if (*stop || G.is_break) {
+ BLI_mutex_lock(pj->mutex);
+ previewjb = previewjb->next;
+ BLI_mutex_unlock(pj->mutex);
+ while (previewjb) {
+ sound = previewjb->sound;
+
+ /* make sure we cleanup the loading flag! */
+ BLI_spin_lock(sound->spinlock);
+ sound->tags &= ~SOUND_TAGS_WAVEFORM_LOADING;
+ BLI_spin_unlock(sound->spinlock);
+
+ BLI_mutex_lock(pj->mutex);
+ previewjb = previewjb->next;
+ BLI_mutex_unlock(pj->mutex);
+ }
+
+ BLI_mutex_lock(pj->mutex);
+ BLI_freelistN(&pj->previews);
+ pj->total = 0;
+ pj->processed = 0;
+ BLI_mutex_unlock(pj->mutex);
+ break;
+ }
+
+ BLI_mutex_lock(pj->mutex);
+ preview_next = previewjb->next;
+ BLI_freelinkN(&pj->previews, previewjb);
+ previewjb = preview_next;
+ pj->processed++;
+ *progress = (pj->total > 0) ? (float)pj->processed / (float)pj->total : 1.0f;
+ *do_update = true;
+ BLI_mutex_unlock(pj->mutex);
+ }
}
static void preview_endjob(void *data)
{
- PreviewJob *pj = data;
+ PreviewJob *pj = data;
- WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, pj->scene);
+ WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, pj->scene);
}
-
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);
- PreviewJobAudio *audiojob = MEM_callocN(sizeof(PreviewJobAudio), "preview_audio");
- wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Strip Previews",
- WM_JOB_PROGRESS, WM_JOB_TYPE_SEQ_BUILD_PREVIEW);
-
- pj = WM_jobs_customdata_get(wm_job);
-
- if (!pj) {
- pj = MEM_callocN(sizeof(PreviewJob), "preview rebuild job");
-
- pj->mutex = BLI_mutex_alloc();
- pj->scene = CTX_data_scene(C);
-
- WM_jobs_customdata_set(wm_job, pj, free_preview_job);
- WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_SEQUENCER, NC_SCENE | ND_SEQUENCER);
- WM_jobs_callbacks(wm_job, preview_startjob, NULL, NULL, preview_endjob);
- }
-
- /* attempt to lock mutex of job here */
-
- audiojob->sound = seq->sound;
-
- BLI_mutex_lock(pj->mutex);
- BLI_addtail(&pj->previews, audiojob);
- pj->total++;
- BLI_mutex_unlock(pj->mutex);
-
- if (!WM_jobs_is_running(wm_job)) {
- G.is_break = false;
- WM_jobs_start(CTX_wm_manager(C), wm_job);
- }
-
- ED_area_tag_redraw(sa);
+ /* first, get the preview job, if it exists */
+ wmJob *wm_job;
+ PreviewJob *pj;
+ ScrArea *sa = 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),
+ sa,
+ "Strip Previews",
+ WM_JOB_PROGRESS,
+ WM_JOB_TYPE_SEQ_BUILD_PREVIEW);
+
+ pj = WM_jobs_customdata_get(wm_job);
+
+ if (!pj) {
+ pj = MEM_callocN(sizeof(PreviewJob), "preview rebuild job");
+
+ pj->mutex = BLI_mutex_alloc();
+ pj->scene = CTX_data_scene(C);
+
+ WM_jobs_customdata_set(wm_job, pj, free_preview_job);
+ WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_SEQUENCER, NC_SCENE | ND_SEQUENCER);
+ WM_jobs_callbacks(wm_job, preview_startjob, NULL, NULL, preview_endjob);
+ }
+
+ /* attempt to lock mutex of job here */
+
+ audiojob->sound = seq->sound;
+
+ BLI_mutex_lock(pj->mutex);
+ BLI_addtail(&pj->previews, audiojob);
+ pj->total++;
+ BLI_mutex_unlock(pj->mutex);
+
+ if (!WM_jobs_is_running(wm_job)) {
+ G.is_break = false;
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+ }
+
+ ED_area_tag_redraw(sa);
}
diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c
index 5ccd9e86e12..2aebc6c97fb 100644
--- a/source/blender/editors/space_sequencer/sequencer_scopes.c
+++ b/source/blender/editors/space_sequencer/sequencer_scopes.c
@@ -20,7 +20,6 @@
* \ingroup spseq
*/
-
#include <math.h>
#include <string.h>
@@ -39,738 +38,733 @@
* only difference is it does some normalize after, need to double check on this - campbell */
static void rgb_to_yuv_normalized(const float rgb[3], float yuv[3])
{
- yuv[0] = 0.299f * rgb[0] + 0.587f * rgb[1] + 0.114f * rgb[2];
- yuv[1] = 0.492f * (rgb[2] - yuv[0]);
- yuv[2] = 0.877f * (rgb[0] - yuv[0]);
+ yuv[0] = 0.299f * rgb[0] + 0.587f * rgb[1] + 0.114f * rgb[2];
+ yuv[1] = 0.492f * (rgb[2] - yuv[0]);
+ yuv[2] = 0.877f * (rgb[0] - yuv[0]);
- /* Normalize */
- yuv[1] *= 255.0f / (122 * 2.0f);
- yuv[1] += 0.5f;
+ /* Normalize */
+ yuv[1] *= 255.0f / (122 * 2.0f);
+ yuv[1] += 0.5f;
- yuv[2] *= 255.0f / (157 * 2.0f);
- yuv[2] += 0.5f;
+ yuv[2] *= 255.0f / (157 * 2.0f);
+ yuv[2] += 0.5f;
}
static void scope_put_pixel(unsigned char *table, unsigned char *pos)
{
- unsigned char newval = table[*pos];
- pos[0] = pos[1] = pos[2] = newval;
- pos[3] = 255;
+ unsigned char 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)
{
- char newval = table[pos[col]];
- pos[col] = newval;
- pos[3] = 255;
+ 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)
{
- if (last_pos > new_pos) {
- unsigned char *temp = new_pos;
- new_pos = last_pos;
- last_pos = temp;
- }
-
- while (last_pos < new_pos) {
- if (last_pos[0] == 0) {
- last_pos[0] = last_pos[1] = last_pos[2] = 32;
- last_pos[3] = 255;
- }
- last_pos += 4 * w;
- }
+ if (last_pos > new_pos) {
+ unsigned char *temp = new_pos;
+ new_pos = last_pos;
+ last_pos = temp;
+ }
+
+ while (last_pos < new_pos) {
+ if (last_pos[0] == 0) {
+ last_pos[0] = last_pos[1] = last_pos[2] = 32;
+ last_pos[3] = 255;
+ }
+ last_pos += 4 * w;
+ }
}
static void wform_put_line_single(int w, unsigned char *last_pos, unsigned char *new_pos, int col)
{
- if (last_pos > new_pos) {
- unsigned char *temp = new_pos;
- new_pos = last_pos;
- last_pos = temp;
- }
-
- while (last_pos < new_pos) {
- if (last_pos[col] == 0) {
- last_pos[col] = 32;
- last_pos[3] = 255;
- }
- last_pos += 4 * w;
- }
+ if (last_pos > new_pos) {
+ unsigned char *temp = new_pos;
+ new_pos = last_pos;
+ last_pos = temp;
+ }
+
+ while (last_pos < new_pos) {
+ if (last_pos[col] == 0) {
+ last_pos[col] = 32;
+ last_pos[3] = 255;
+ }
+ last_pos += 4 * w;
+ }
}
static void wform_put_border(unsigned char *tgt, int w, int h)
{
- int x, y;
-
- for (x = 0; x < w; x++) {
- unsigned char *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);
- p[1] = p[3] = 155;
- p[-4 * w + 1] = p[-4 * w + 3] = 155;
- }
-
- for (y = 0; y < h; y++) {
- unsigned char *p = tgt + 4 * w * y;
- p[1] = p[3] = 155;
- p[4 + 1] = p[4 + 3] = 155;
- p = tgt + 4 * (w * y + w - 1);
- p[1] = p[3] = 155;
- p[-4 + 1] = p[-4 + 3] = 155;
- }
+ int x, y;
+
+ for (x = 0; x < w; x++) {
+ unsigned char *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);
+ p[1] = p[3] = 155;
+ p[-4 * w + 1] = p[-4 * w + 3] = 155;
+ }
+
+ for (y = 0; y < h; y++) {
+ unsigned char *p = tgt + 4 * w * y;
+ p[1] = p[3] = 155;
+ p[4 + 1] = p[4 + 3] = 155;
+ p = tgt + 4 * (w * y + w - 1);
+ p[1] = p[3] = 155;
+ p[-4 + 1] = p[-4 + 3] = 155;
+ }
}
static void wform_put_gridrow(unsigned char *tgt, float perc, int w, int h)
{
- int i;
+ int i;
- tgt += (int) (perc / 100.0f * h) * w * 4;
+ tgt += (int)(perc / 100.0f * h) * w * 4;
- for (i = 0; i < w * 2; i++) {
- tgt[0] = 255;
+ for (i = 0; i < w * 2; i++) {
+ tgt[0] = 255;
- tgt += 4;
- }
+ tgt += 4;
+ }
}
static void wform_put_grid(unsigned char *tgt, int w, int h)
{
- wform_put_gridrow(tgt, 90.0, w, h);
- wform_put_gridrow(tgt, 70.0, w, h);
- wform_put_gridrow(tgt, 10.0, w, h);
+ wform_put_gridrow(tgt, 90.0, w, h);
+ wform_put_gridrow(tgt, 70.0, w, h);
+ wform_put_gridrow(tgt, 10.0, w, h);
}
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;
- int w = ibuf->x + 3;
- int h = 515;
- float waveform_gamma = 0.2;
- unsigned char 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);
- }
-
- for (y = 0; y < ibuf->y; y++) {
- unsigned char *last_p = NULL;
-
- for (x = 0; x < ibuf->x; x++) {
- const unsigned char *rgb = src + 4 * (ibuf->x * y + x);
- float v = (float)IMB_colormanagement_get_luminance_byte(rgb) / 255.0f;
- unsigned char *p = tgt;
- p += 4 * (w * ((int) (v * (h - 3)) + 1) + x + 1);
-
- scope_put_pixel(wtable, p);
- p += 4 * w;
- scope_put_pixel(wtable, p);
-
- if (last_p != NULL) {
- wform_put_line(w, last_p, p);
- }
- last_p = p;
- }
- }
-
- return rval;
+ 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;
+ int w = ibuf->x + 3;
+ int h = 515;
+ float waveform_gamma = 0.2;
+ unsigned char 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);
+ }
+
+ for (y = 0; y < ibuf->y; y++) {
+ unsigned char *last_p = NULL;
+
+ for (x = 0; x < ibuf->x; x++) {
+ const unsigned char *rgb = src + 4 * (ibuf->x * y + x);
+ float v = (float)IMB_colormanagement_get_luminance_byte(rgb) / 255.0f;
+ unsigned char *p = tgt;
+ p += 4 * (w * ((int)(v * (h - 3)) + 1) + x + 1);
+
+ scope_put_pixel(wtable, p);
+ p += 4 * w;
+ scope_put_pixel(wtable, p);
+
+ if (last_p != NULL) {
+ wform_put_line(w, last_p, p);
+ }
+ last_p = p;
+ }
+ }
+
+ return rval;
}
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;
- int w = ibuf->x + 3;
- int h = 515;
- float waveform_gamma = 0.2;
- unsigned char wtable[256];
+ 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;
+ int w = ibuf->x + 3;
+ int h = 515;
+ float waveform_gamma = 0.2;
+ unsigned char wtable[256];
- wform_put_grid(tgt, w, h);
+ wform_put_grid(tgt, w, h);
- for (x = 0; x < 256; x++) {
- wtable[x] = (unsigned char) (pow(((float) x + 1) / 256, waveform_gamma) * 255);
- }
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char)(pow(((float)x + 1) / 256, waveform_gamma) * 255);
+ }
- for (y = 0; y < ibuf->y; y++) {
- unsigned char *last_p = NULL;
+ for (y = 0; y < ibuf->y; y++) {
+ unsigned char *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;
+ 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;
- CLAMP(v, 0.0f, 1.0f);
+ CLAMP(v, 0.0f, 1.0f);
- p += 4 * (w * ((int) (v * (h - 3)) + 1) + x + 1);
+ p += 4 * (w * ((int)(v * (h - 3)) + 1) + x + 1);
- scope_put_pixel(wtable, p);
- p += 4 * w;
- scope_put_pixel(wtable, p);
+ scope_put_pixel(wtable, p);
+ p += 4 * w;
+ scope_put_pixel(wtable, p);
- if (last_p != NULL) {
- wform_put_line(w, last_p, p);
- }
- last_p = p;
- }
- }
+ if (last_p != NULL) {
+ wform_put_line(w, last_p, p);
+ }
+ last_p = p;
+ }
+ }
- wform_put_border(tgt, w, h);
+ wform_put_border(tgt, w, h);
- return rval;
+ return rval;
}
ImBuf *make_waveform_view_from_ibuf(ImBuf *ibuf)
{
- if (ibuf->rect_float) {
- return make_waveform_view_from_ibuf_float(ibuf);
- }
- else {
- return make_waveform_view_from_ibuf_byte(ibuf);
- }
+ if (ibuf->rect_float) {
+ return make_waveform_view_from_ibuf_float(ibuf);
+ }
+ else {
+ return make_waveform_view_from_ibuf_byte(ibuf);
+ }
}
-
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;
- int w = ibuf->x + 3;
- int sw = ibuf->x / 3;
- int h = 515;
- float waveform_gamma = 0.2;
- unsigned char 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);
- }
-
- for (y = 0; y < ibuf->y; y++) {
- unsigned char *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);
- for (c = 0; c < 3; c++) {
- unsigned char *p = tgt;
- p += 4 * (w * ((rgb[c] * (h - 3)) / 255 + 1) + c * sw + x / 3 + 1);
-
- scope_put_pixel_single(wtable, p, c);
- p += 4 * w;
- scope_put_pixel_single(wtable, p, c);
-
- if (last_p[c] != NULL) {
- wform_put_line_single(w, last_p[c], p, c);
- }
- last_p[c] = p;
- }
- }
- }
-
- wform_put_border(tgt, w, h);
-
- return rval;
+ 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;
+ int w = ibuf->x + 3;
+ int sw = ibuf->x / 3;
+ int h = 515;
+ float waveform_gamma = 0.2;
+ unsigned char 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);
+ }
+
+ for (y = 0; y < ibuf->y; y++) {
+ unsigned char *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);
+ for (c = 0; c < 3; c++) {
+ unsigned char *p = tgt;
+ p += 4 * (w * ((rgb[c] * (h - 3)) / 255 + 1) + c * sw + x / 3 + 1);
+
+ scope_put_pixel_single(wtable, p, c);
+ p += 4 * w;
+ scope_put_pixel_single(wtable, p, c);
+
+ if (last_p[c] != NULL) {
+ wform_put_line_single(w, last_p[c], p, c);
+ }
+ last_p[c] = p;
+ }
+ }
+ }
+
+ wform_put_border(tgt, w, h);
+
+ return rval;
}
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;
- int w = ibuf->x + 3;
- int sw = ibuf->x / 3;
- int h = 515;
- float waveform_gamma = 0.2;
- unsigned char 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);
- }
-
- for (y = 0; y < ibuf->y; y++) {
- unsigned char *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;
- float v = rgb[c];
-
- CLAMP(v, 0.0f, 1.0f);
-
- p += 4 * (w * ((int) (v * (h - 3)) + 1) + c * sw + x / 3 + 1);
-
- scope_put_pixel_single(wtable, p, c);
- p += 4 * w;
- scope_put_pixel_single(wtable, p, c);
-
- if (last_p[c] != NULL) {
- wform_put_line_single(w, last_p[c], p, c);
- }
- last_p[c] = p;
- }
- }
- }
-
- wform_put_border(tgt, w, h);
-
- return rval;
+ 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;
+ int w = ibuf->x + 3;
+ int sw = ibuf->x / 3;
+ int h = 515;
+ float waveform_gamma = 0.2;
+ unsigned char 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);
+ }
+
+ for (y = 0; y < ibuf->y; y++) {
+ unsigned char *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;
+ float v = rgb[c];
+
+ CLAMP(v, 0.0f, 1.0f);
+
+ p += 4 * (w * ((int)(v * (h - 3)) + 1) + c * sw + x / 3 + 1);
+
+ scope_put_pixel_single(wtable, p, c);
+ p += 4 * w;
+ scope_put_pixel_single(wtable, p, c);
+
+ if (last_p[c] != NULL) {
+ wform_put_line_single(w, last_p[c], p, c);
+ }
+ last_p[c] = p;
+ }
+ }
+ }
+
+ wform_put_border(tgt, w, h);
+
+ return rval;
}
ImBuf *make_sep_waveform_view_from_ibuf(ImBuf *ibuf)
{
- if (ibuf->rect_float) {
- return make_sep_waveform_view_from_ibuf_float(ibuf);
- }
- else {
- return make_sep_waveform_view_from_ibuf_byte(ibuf);
- }
+ if (ibuf->rect_float) {
+ return make_sep_waveform_view_from_ibuf_float(ibuf);
+ }
+ else {
+ return make_sep_waveform_view_from_ibuf_byte(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;
- 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++;
-
- if (r >= limit || g >= limit || b >= limit) {
- if (((x + y) & 0x08) != 0) {
- r = 255 - r;
- g = 255 - g;
- b = 255 - b;
- }
- }
- *o++ = r;
- *o++ = g;
- *o++ = b;
- *o++ = a;
- }
- }
+ unsigned int limit = 255.0f * perc / 100.0f;
+ unsigned char *p = (unsigned char *)src->rect;
+ unsigned char *o = (unsigned char *)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++;
+
+ if (r >= limit || g >= limit || b >= limit) {
+ if (((x + y) & 0x08) != 0) {
+ r = 255 - r;
+ g = 255 - g;
+ b = 255 - b;
+ }
+ }
+ *o++ = r;
+ *o++ = g;
+ *o++ = b;
+ *o++ = a;
+ }
+ }
}
-
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;
- int x;
- int y;
-
- for (y = 0; y < ibuf->y; y++) {
- for (x = 0; x < ibuf->x; x++) {
- float r = *p++;
- float g = *p++;
- float b = *p++;
- float a = *p++;
-
- if (r >= limit || g >= limit || b >= limit) {
- if (((x + y) & 0x08) != 0) {
- r = -r;
- g = -g;
- b = -b;
- }
- }
-
- *o++ = unit_float_to_uchar_clamp(r);
- *o++ = unit_float_to_uchar_clamp(g);
- *o++ = unit_float_to_uchar_clamp(b);
- *o++ = unit_float_to_uchar_clamp(a);
- }
- }
+ float limit = perc / 100.0f;
+ const float *p = src->rect_float;
+ unsigned char *o = (unsigned char *)ibuf->rect;
+ int x;
+ int y;
+
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ float r = *p++;
+ float g = *p++;
+ float b = *p++;
+ float a = *p++;
+
+ if (r >= limit || g >= limit || b >= limit) {
+ if (((x + y) & 0x08) != 0) {
+ r = -r;
+ g = -g;
+ b = -b;
+ }
+ }
+
+ *o++ = unit_float_to_uchar_clamp(r);
+ *o++ = unit_float_to_uchar_clamp(g);
+ *o++ = unit_float_to_uchar_clamp(b);
+ *o++ = unit_float_to_uchar_clamp(a);
+ }
+ }
}
ImBuf *make_zebra_view_from_ibuf(ImBuf *src, float perc)
{
- ImBuf *ibuf = IMB_allocImBuf(src->x, src->y, 32, IB_rect);
-
- if (src->rect_float) {
- draw_zebra_float(src, ibuf, perc);
- }
- else {
- draw_zebra_byte(src, ibuf, perc);
- }
- return ibuf;
+ ImBuf *ibuf = IMB_allocImBuf(src->x, src->y, 32, IB_rect);
+
+ if (src->rect_float) {
+ draw_zebra_float(src, ibuf, perc);
+ }
+ else {
+ draw_zebra_byte(src, ibuf, perc);
+ }
+ return ibuf;
}
static void draw_histogram_marker(ImBuf *ibuf, int x)
{
- unsigned char *p = (unsigned char *) ibuf->rect;
- int barh = ibuf->y * 0.1;
- int i;
+ unsigned char *p = (unsigned char *)ibuf->rect;
+ int barh = ibuf->y * 0.1;
+ int i;
- p += 4 * (x + ibuf->x * (ibuf->y - barh + 1));
+ p += 4 * (x + ibuf->x * (ibuf->y - barh + 1));
- for (i = 0; i < barh - 1; i++) {
- p[0] = p[1] = p[2] = 255;
- p += ibuf->x * 4;
- }
+ for (i = 0; i < barh - 1; i++) {
+ p[0] = p[1] = p[2] = 255;
+ p += ibuf->x * 4;
+ }
}
static void draw_histogram_bar(ImBuf *ibuf, int x, float val, int col)
{
- unsigned char *p = (unsigned char *) ibuf->rect;
- int barh = ibuf->y * val * 0.9f;
- int i;
+ unsigned char *p = (unsigned char *)ibuf->rect;
+ int barh = ibuf->y * val * 0.9f;
+ int i;
- p += 4 * (x + ibuf->x);
+ p += 4 * (x + ibuf->x);
- for (i = 0; i < barh; i++) {
- p[col] = 255;
- p += ibuf->x * 4;
- }
+ for (i = 0; i < barh; i++) {
+ p[col] = 255;
+ p += ibuf->x * 4;
+ }
}
#define HIS_STEPS 512
typedef struct MakeHistogramViewData {
- const ImBuf *ibuf;
- uint32_t (*bins)[HIS_STEPS];
+ 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 ParallelRangeTLS *__restrict tls)
+static void make_histogram_view_from_ibuf_byte_cb_ex(void *__restrict userdata,
+ const int y,
+ const ParallelRangeTLS *__restrict tls)
{
- MakeHistogramViewData *data = userdata;
- const ImBuf *ibuf = data->ibuf;
- const unsigned char *src = (unsigned char *)ibuf->rect;
+ MakeHistogramViewData *data = userdata;
+ const ImBuf *ibuf = data->ibuf;
+ const unsigned char *src = (unsigned char *)ibuf->rect;
- uint32_t (*cur_bins)[HIS_STEPS] = tls->userdata_chunk;
+ 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;
+ for (int x = 0; x < ibuf->x; x++) {
+ const unsigned char *pixel = src + (y * ibuf->x + x) * 4;
- for (int j = 3; j--;) {
- cur_bins[j][pixel[j]]++;
- }
- }
+ for (int j = 3; j--;) {
+ cur_bins[j][pixel[j]]++;
+ }
+ }
}
static void make_histogram_view_from_ibuf_finalize(void *__restrict userdata,
void *__restrict userdata_chunk)
{
- MakeHistogramViewData *data = userdata;
- uint32_t (*bins)[HIS_STEPS] = data->bins;
+ MakeHistogramViewData *data = userdata;
+ uint32_t(*bins)[HIS_STEPS] = data->bins;
- uint32_t (*cur_bins)[HIS_STEPS] = userdata_chunk;
+ uint32_t(*cur_bins)[HIS_STEPS] = userdata_chunk;
- for (int j = 3; j--;) {
- for (int i = 0; i < HIS_STEPS; i++) {
- bins[j][i] += cur_bins[j][i];
- }
- }
+ for (int j = 3; j--;) {
+ for (int i = 0; i < HIS_STEPS; i++) {
+ bins[j][i] += cur_bins[j][i];
+ }
+ }
}
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;
-
- unsigned int bins[3][HIS_STEPS];
-
- memset(bins, 0, sizeof(bins));
-
- MakeHistogramViewData data = { .ibuf = ibuf, .bins = bins, };
- ParallelRangeSettings 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);
-
- nr = nb = ng = 0;
- for (x = 0; x < HIS_STEPS; x++) {
- if (bins[0][x] > nr) {
- nr = bins[0][x];
- }
- if (bins[1][x] > ng) {
- ng = bins[1][x];
- }
- if (bins[2][x] > nb) {
- nb = bins[2][x];
- }
- }
-
- for (x = 0; x < HIS_STEPS; x++) {
- if (nr) {
- draw_histogram_bar(rval, x * 2 + 1, ((float) bins[0][x]) / nr, 0);
- draw_histogram_bar(rval, x * 2 + 2, ((float) bins[0][x]) / nr, 0);
- }
- if (ng) {
- draw_histogram_bar(rval, x * 2 + 1, ((float) bins[1][x]) / ng, 1);
- draw_histogram_bar(rval, x * 2 + 2, ((float) bins[1][x]) / ng, 1);
- }
- if (nb) {
- draw_histogram_bar(rval, x * 2 + 1, ((float) bins[2][x]) / nb, 2);
- draw_histogram_bar(rval, x * 2 + 2, ((float) bins[2][x]) / nb, 2);
- }
- }
-
- wform_put_border((unsigned char *) rval->rect, rval->x, rval->y);
-
- return rval;
+ ImBuf *rval = IMB_allocImBuf(515, 128, 32, IB_rect);
+ int x;
+ unsigned int nr, ng, nb;
+
+ unsigned int bins[3][HIS_STEPS];
+
+ memset(bins, 0, sizeof(bins));
+
+ MakeHistogramViewData data = {
+ .ibuf = ibuf,
+ .bins = bins,
+ };
+ ParallelRangeSettings 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);
+
+ nr = nb = ng = 0;
+ for (x = 0; x < HIS_STEPS; x++) {
+ if (bins[0][x] > nr) {
+ nr = bins[0][x];
+ }
+ if (bins[1][x] > ng) {
+ ng = bins[1][x];
+ }
+ if (bins[2][x] > nb) {
+ nb = bins[2][x];
+ }
+ }
+
+ for (x = 0; x < HIS_STEPS; x++) {
+ if (nr) {
+ draw_histogram_bar(rval, x * 2 + 1, ((float)bins[0][x]) / nr, 0);
+ draw_histogram_bar(rval, x * 2 + 2, ((float)bins[0][x]) / nr, 0);
+ }
+ if (ng) {
+ draw_histogram_bar(rval, x * 2 + 1, ((float)bins[1][x]) / ng, 1);
+ draw_histogram_bar(rval, x * 2 + 2, ((float)bins[1][x]) / ng, 1);
+ }
+ if (nb) {
+ draw_histogram_bar(rval, x * 2 + 1, ((float)bins[2][x]) / nb, 2);
+ draw_histogram_bar(rval, x * 2 + 2, ((float)bins[2][x]) / nb, 2);
+ }
+ }
+
+ wform_put_border((unsigned char *)rval->rect, rval->x, rval->y);
+
+ return rval;
}
BLI_INLINE int get_bin_float(float f)
{
- if (f < -0.25f) {
- return 0;
- }
- else if (f >= 1.25f) {
- return 511;
- }
-
- return (int) (((f + 0.25f) / 1.5f) * 512);
+ if (f < -0.25f) {
+ return 0;
+ }
+ else if (f >= 1.25f) {
+ return 511;
+ }
+
+ 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 ParallelRangeTLS *__restrict tls)
+static void make_histogram_view_from_ibuf_float_cb_ex(void *__restrict userdata,
+ const int y,
+ const ParallelRangeTLS *__restrict tls)
{
- const MakeHistogramViewData *data = userdata;
- const ImBuf *ibuf = data->ibuf;
- const float *src = ibuf->rect_float;
+ const MakeHistogramViewData *data = userdata;
+ const ImBuf *ibuf = data->ibuf;
+ const float *src = ibuf->rect_float;
- uint32_t (*cur_bins)[HIS_STEPS] = tls->userdata_chunk;
+ uint32_t(*cur_bins)[HIS_STEPS] = tls->userdata_chunk;
- for (int x = 0; x < ibuf->x; x++) {
- const float *pixel = src + (y * ibuf->x + x) * 4;
+ for (int x = 0; x < ibuf->x; x++) {
+ const float *pixel = src + (y * ibuf->x + x) * 4;
- for (int j = 3; j--;) {
- cur_bins[j][get_bin_float(pixel[j])]++;
- }
- }
+ for (int j = 3; j--;) {
+ cur_bins[j][get_bin_float(pixel[j])]++;
+ }
+ }
}
static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf)
{
- ImBuf *rval = IMB_allocImBuf(515, 128, 32, IB_rect);
- int nr, ng, nb;
- int x;
-
- unsigned int bins[3][HIS_STEPS];
-
- memset(bins, 0, sizeof(bins));
-
- MakeHistogramViewData data = { .ibuf = ibuf, .bins = bins, };
- ParallelRangeSettings 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);
-
- nr = nb = ng = 0;
- for (x = 0; x < HIS_STEPS; x++) {
- if (bins[0][x] > nr) {
- nr = bins[0][x];
- }
- if (bins[1][x] > ng) {
- ng = bins[1][x];
- }
- if (bins[2][x] > nb) {
- nb = bins[2][x];
- }
- }
-
- for (x = 0; x < HIS_STEPS; x++) {
- if (nr) {
- draw_histogram_bar(rval, x + 1, ((float) bins[0][x]) / nr, 0);
- }
- if (ng) {
- draw_histogram_bar(rval, x + 1, ((float) bins[1][x]) / ng, 1);
- }
- if (nb) {
- draw_histogram_bar(rval, x + 1, ((float) bins[2][x]) / nb, 2);
- }
- }
-
- 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);
-
- return rval;
+ ImBuf *rval = IMB_allocImBuf(515, 128, 32, IB_rect);
+ int nr, ng, nb;
+ int x;
+
+ unsigned int bins[3][HIS_STEPS];
+
+ memset(bins, 0, sizeof(bins));
+
+ MakeHistogramViewData data = {
+ .ibuf = ibuf,
+ .bins = bins,
+ };
+ ParallelRangeSettings 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);
+
+ nr = nb = ng = 0;
+ for (x = 0; x < HIS_STEPS; x++) {
+ if (bins[0][x] > nr) {
+ nr = bins[0][x];
+ }
+ if (bins[1][x] > ng) {
+ ng = bins[1][x];
+ }
+ if (bins[2][x] > nb) {
+ nb = bins[2][x];
+ }
+ }
+
+ for (x = 0; x < HIS_STEPS; x++) {
+ if (nr) {
+ draw_histogram_bar(rval, x + 1, ((float)bins[0][x]) / nr, 0);
+ }
+ if (ng) {
+ draw_histogram_bar(rval, x + 1, ((float)bins[1][x]) / ng, 1);
+ }
+ if (nb) {
+ draw_histogram_bar(rval, x + 1, ((float)bins[2][x]) / nb, 2);
+ }
+ }
+
+ 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);
+
+ return rval;
}
#undef HIS_STEPS
ImBuf *make_histogram_view_from_ibuf(ImBuf *ibuf)
{
- if (ibuf->rect_float) {
- return make_histogram_view_from_ibuf_float(ibuf);
- }
- else {
- return make_histogram_view_from_ibuf_byte(ibuf);
- }
+ if (ibuf->rect_float) {
+ return make_histogram_view_from_ibuf_float(ibuf);
+ }
+ else {
+ return make_histogram_view_from_ibuf_byte(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(
+ unsigned char r, unsigned char g, unsigned char b, char *tgt, int w, int h, int size)
{
- float rgb[3], yuv[3];
- char *p;
- int x = 0;
- int y = 0;
-
- rgb[0] = (float)r / 255.0f;
- rgb[1] = (float)g / 255.0f;
- rgb[2] = (float)b / 255.0f;
- rgb_to_yuv_normalized(rgb, yuv);
-
- p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1)) +
- (int) ((yuv[1] * (w - 3) + 1)));
-
- if (r == 0 && g == 0 && b == 0) {
- r = 255;
- }
-
- for (y = -size; y <= size; y++) {
- for (x = -size; x <= size; x++) {
- char *q = p + 4 * (y * w + x);
- q[0] = r; q[1] = g; q[2] = b; q[3] = 255;
- }
- }
+ float rgb[3], yuv[3];
+ char *p;
+ int x = 0;
+ int y = 0;
+
+ rgb[0] = (float)r / 255.0f;
+ rgb[1] = (float)g / 255.0f;
+ rgb[2] = (float)b / 255.0f;
+ rgb_to_yuv_normalized(rgb, yuv);
+
+ p = tgt + 4 * (w * (int)((yuv[2] * (h - 3) + 1)) + (int)((yuv[1] * (w - 3) + 1)));
+
+ if (r == 0 && g == 0 && b == 0) {
+ r = 255;
+ }
+
+ for (y = -size; y <= size; y++) {
+ for (x = -size; x <= size; x++) {
+ char *q = p + 4 * (y * w + x);
+ q[0] = r;
+ q[1] = g;
+ q[2] = b;
+ q[3] = 255;
+ }
+ }
}
static ImBuf *make_vectorscope_view_from_ibuf_byte(ImBuf *ibuf)
{
- ImBuf *rval = IMB_allocImBuf(515, 515, 32, IB_rect);
- int x, y;
- const char *src = (const char *) ibuf->rect;
- char *tgt = (char *) rval->rect;
- float rgb[3], yuv[3];
- int w = 515;
- int h = 515;
- float scope_gamma = 0.2;
- unsigned char wtable[256];
-
- for (x = 0; x < 256; x++) {
- wtable[x] = (unsigned char) (pow(((float) x + 1) / 256, scope_gamma) * 255);
- }
-
- for (x = 0; x < 256; x++) {
- vectorscope_put_cross(255, 0, 255 - x, tgt, w, h, 1);
- vectorscope_put_cross(255, x, 0, tgt, w, h, 1);
- vectorscope_put_cross(255 - x, 255, 0, tgt, w, h, 1);
- vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
- vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
- vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
- }
-
- for (y = 0; y < ibuf->y; y++) {
- for (x = 0; x < ibuf->x; x++) {
- const char *src1 = src + 4 * (ibuf->x * y + x);
- char *p;
-
- rgb[0] = (float)src1[0] / 255.0f;
- rgb[1] = (float)src1[1] / 255.0f;
- rgb[2] = (float)src1[2] / 255.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);
- }
- }
-
- vectorscope_put_cross(0, 0, 0, tgt, w, h, 3);
-
- return rval;
+ ImBuf *rval = IMB_allocImBuf(515, 515, 32, IB_rect);
+ int x, y;
+ const char *src = (const char *)ibuf->rect;
+ char *tgt = (char *)rval->rect;
+ float rgb[3], yuv[3];
+ int w = 515;
+ int h = 515;
+ float scope_gamma = 0.2;
+ unsigned char wtable[256];
+
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char)(pow(((float)x + 1) / 256, scope_gamma) * 255);
+ }
+
+ for (x = 0; x < 256; x++) {
+ vectorscope_put_cross(255, 0, 255 - x, tgt, w, h, 1);
+ vectorscope_put_cross(255, x, 0, tgt, w, h, 1);
+ vectorscope_put_cross(255 - x, 255, 0, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
+ vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
+ }
+
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ const char *src1 = src + 4 * (ibuf->x * y + x);
+ char *p;
+
+ rgb[0] = (float)src1[0] / 255.0f;
+ rgb[1] = (float)src1[1] / 255.0f;
+ rgb[2] = (float)src1[2] / 255.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);
+ }
+ }
+
+ vectorscope_put_cross(0, 0, 0, tgt, w, h, 3);
+
+ return rval;
}
static ImBuf *make_vectorscope_view_from_ibuf_float(ImBuf *ibuf)
{
- ImBuf *rval = IMB_allocImBuf(515, 515, 32, IB_rect);
- int x, y;
- const float *src = ibuf->rect_float;
- char *tgt = (char *) rval->rect;
- float rgb[3], yuv[3];
- int w = 515;
- int h = 515;
- float scope_gamma = 0.2;
- unsigned char wtable[256];
-
- for (x = 0; x < 256; x++) {
- wtable[x] = (unsigned char) (pow(((float) x + 1) / 256, scope_gamma) * 255);
- }
-
- for (x = 0; x <= 255; x++) {
- vectorscope_put_cross(255, 0, 255 - x, tgt, w, h, 1);
- vectorscope_put_cross(255, x, 0, tgt, w, h, 1);
- vectorscope_put_cross(255 - x, 255, 0, tgt, w, h, 1);
- vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
- vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
- vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
- }
-
- for (y = 0; y < ibuf->y; y++) {
- for (x = 0; x < ibuf->x; x++) {
- const float *src1 = src + 4 * (ibuf->x * y + x);
- const char *p;
-
- 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);
-
- 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);
- }
- }
-
- vectorscope_put_cross(0, 0, 0, tgt, w, h, 3);
-
- return rval;
+ ImBuf *rval = IMB_allocImBuf(515, 515, 32, IB_rect);
+ int x, y;
+ const float *src = ibuf->rect_float;
+ char *tgt = (char *)rval->rect;
+ float rgb[3], yuv[3];
+ int w = 515;
+ int h = 515;
+ float scope_gamma = 0.2;
+ unsigned char wtable[256];
+
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char)(pow(((float)x + 1) / 256, scope_gamma) * 255);
+ }
+
+ for (x = 0; x <= 255; x++) {
+ vectorscope_put_cross(255, 0, 255 - x, tgt, w, h, 1);
+ vectorscope_put_cross(255, x, 0, tgt, w, h, 1);
+ vectorscope_put_cross(255 - x, 255, 0, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
+ vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
+ }
+
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ const float *src1 = src + 4 * (ibuf->x * y + x);
+ const char *p;
+
+ 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);
+
+ 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);
+ }
+ }
+
+ vectorscope_put_cross(0, 0, 0, tgt, w, h, 3);
+
+ return rval;
}
ImBuf *make_vectorscope_view_from_ibuf(ImBuf *ibuf)
{
- if (ibuf->rect_float) {
- return make_vectorscope_view_from_ibuf_float(ibuf);
- }
- else {
- return make_vectorscope_view_from_ibuf_byte(ibuf);
- }
+ if (ibuf->rect_float) {
+ return make_vectorscope_view_from_ibuf_float(ibuf);
+ }
+ else {
+ return make_vectorscope_view_from_ibuf_byte(ibuf);
+ }
}
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index 6de20e3c4af..a59a3b830e3 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -21,7 +21,6 @@
* \ingroup spseq
*/
-
#include <stdlib.h>
#include <math.h>
#include <string.h>
@@ -52,1183 +51,1191 @@
#include "sequencer_intern.h"
static void *find_nearest_marker(int UNUSED(d1), int UNUSED(d2))
{
- return NULL;
+ return NULL;
}
static void select_surrounding_handles(Scene *scene, Sequence *test) /* XXX BRING BACK */
{
- Sequence *neighbor;
-
- neighbor = find_neighboring_sequence(scene, test, SEQ_SIDE_LEFT, -1);
- if (neighbor) {
- /* Only select neighbor handle if matching handle from test seq is also selected, or if neighbor
- * was not selected at all up till now.
- * Otherwise, we get odd mismatch when shift-alt-rmb selecting neighbor strips... */
- if (!(neighbor->flag & SELECT) || (test->flag & SEQ_LEFTSEL)) {
- neighbor->flag |= SEQ_RIGHTSEL;
- }
- neighbor->flag |= SELECT;
- recurs_sel_seq(neighbor);
- }
- neighbor = find_neighboring_sequence(scene, test, SEQ_SIDE_RIGHT, -1);
- if (neighbor) {
- if (!(neighbor->flag & SELECT) || (test->flag & SEQ_RIGHTSEL)) { /* See comment above. */
- neighbor->flag |= SEQ_LEFTSEL;
- }
- neighbor->flag |= SELECT;
- recurs_sel_seq(neighbor);
- }
+ Sequence *neighbor;
+
+ neighbor = find_neighboring_sequence(scene, test, SEQ_SIDE_LEFT, -1);
+ if (neighbor) {
+ /* Only select neighbor handle if matching handle from test seq is also selected, or if neighbor
+ * was not selected at all up till now.
+ * Otherwise, we get odd mismatch when shift-alt-rmb selecting neighbor strips... */
+ if (!(neighbor->flag & SELECT) || (test->flag & SEQ_LEFTSEL)) {
+ neighbor->flag |= SEQ_RIGHTSEL;
+ }
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ }
+ neighbor = find_neighboring_sequence(scene, test, SEQ_SIDE_RIGHT, -1);
+ if (neighbor) {
+ if (!(neighbor->flag & SELECT) || (test->flag & SEQ_RIGHTSEL)) { /* See comment above. */
+ neighbor->flag |= SEQ_LEFTSEL;
+ }
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ }
}
/* used for mouse selection and for SEQUENCER_OT_select_active_side() */
static void select_active_side(ListBase *seqbase, int sel_side, int channel, int frame)
{
- Sequence *seq;
-
- for (seq = seqbase->first; seq; seq = seq->next) {
- if (channel == seq->machine) {
- switch (sel_side) {
- case SEQ_SIDE_LEFT:
- if (frame > (seq->startdisp)) {
- seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL);
- seq->flag |= SELECT;
- }
- break;
- case SEQ_SIDE_RIGHT:
- if (frame < (seq->startdisp)) {
- seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL);
- seq->flag |= SELECT;
- }
- break;
- case SEQ_SIDE_BOTH:
- seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL);
- seq->flag |= SELECT;
- break;
- }
- }
- }
+ Sequence *seq;
+
+ for (seq = seqbase->first; seq; seq = seq->next) {
+ if (channel == seq->machine) {
+ switch (sel_side) {
+ case SEQ_SIDE_LEFT:
+ if (frame > (seq->startdisp)) {
+ seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL);
+ seq->flag |= SELECT;
+ }
+ break;
+ case SEQ_SIDE_RIGHT:
+ if (frame < (seq->startdisp)) {
+ seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL);
+ seq->flag |= SELECT;
+ }
+ break;
+ case SEQ_SIDE_BOTH:
+ seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL);
+ seq->flag |= SELECT;
+ break;
+ }
+ }
+ }
}
/* used for mouse selection and for SEQUENCER_OT_select_active_side() */
static void select_linked_time(ListBase *seqbase, Sequence *seq_link)
{
- Sequence *seq;
+ Sequence *seq;
- for (seq = seqbase->first; seq; seq = seq->next) {
- if (seq_link->machine != seq->machine) {
- int left_match = (seq->startdisp == seq_link->startdisp) ? 1 : 0;
- int right_match = (seq->enddisp == seq_link->enddisp) ? 1 : 0;
+ for (seq = seqbase->first; seq; seq = seq->next) {
+ if (seq_link->machine != seq->machine) {
+ int left_match = (seq->startdisp == seq_link->startdisp) ? 1 : 0;
+ int right_match = (seq->enddisp == seq_link->enddisp) ? 1 : 0;
- if (left_match && right_match) {
- /* a direct match, copy the selection settinhs */
- seq->flag &= ~(SELECT | SEQ_LEFTSEL | SEQ_RIGHTSEL);
- seq->flag |= seq_link->flag & (SELECT | SEQ_LEFTSEL | SEQ_RIGHTSEL);
+ if (left_match && right_match) {
+ /* a direct match, copy the selection settinhs */
+ seq->flag &= ~(SELECT | SEQ_LEFTSEL | SEQ_RIGHTSEL);
+ seq->flag |= seq_link->flag & (SELECT | SEQ_LEFTSEL | SEQ_RIGHTSEL);
- recurs_sel_seq(seq);
- }
- else if (seq_link->flag & SELECT && (left_match || right_match)) {
+ recurs_sel_seq(seq);
+ }
+ else if (seq_link->flag & SELECT && (left_match || right_match)) {
- /* clear for reselection */
- seq->flag &= ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
+ /* clear for reselection */
+ seq->flag &= ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
- if (left_match && seq_link->flag & SEQ_LEFTSEL) {
- seq->flag |= SELECT | SEQ_LEFTSEL;
- }
+ if (left_match && seq_link->flag & SEQ_LEFTSEL) {
+ seq->flag |= SELECT | SEQ_LEFTSEL;
+ }
- if (right_match && seq_link->flag & SEQ_RIGHTSEL) {
- seq->flag |= SELECT | SEQ_RIGHTSEL;
- }
+ if (right_match && seq_link->flag & SEQ_RIGHTSEL) {
+ seq->flag |= SELECT | SEQ_RIGHTSEL;
+ }
- recurs_sel_seq(seq);
- }
- }
- }
+ recurs_sel_seq(seq);
+ }
+ }
+ }
}
-#if 0 // BRING BACK
+#if 0 // BRING BACK
void select_surround_from_last(Scene *scene)
{
- Sequence *seq = get_last_seq(scene);
+ Sequence *seq = get_last_seq(scene);
- if (seq == NULL)
- return;
+ if (seq == NULL)
+ return;
- select_surrounding_handles(scene, seq);
+ select_surrounding_handles(scene, seq);
}
#endif
void ED_sequencer_select_sequence_single(Scene *scene, Sequence *seq, bool deselect_all)
{
- Editing *ed = BKE_sequencer_editing_get(scene, false);
-
- if (deselect_all) {
- ED_sequencer_deselect_all(scene);
- }
-
- BKE_sequencer_active_set(scene, seq);
-
- if ((seq->type == SEQ_TYPE_IMAGE) || (seq->type == SEQ_TYPE_MOVIE)) {
- if (seq->strip) {
- BLI_strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR);
- }
- }
- else if (seq->type == SEQ_TYPE_SOUND_RAM) {
- if (seq->strip) {
- BLI_strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR);
- }
- }
- seq->flag |= SELECT;
- recurs_sel_seq(seq);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+
+ if (deselect_all) {
+ ED_sequencer_deselect_all(scene);
+ }
+
+ BKE_sequencer_active_set(scene, seq);
+
+ if ((seq->type == SEQ_TYPE_IMAGE) || (seq->type == SEQ_TYPE_MOVIE)) {
+ if (seq->strip) {
+ BLI_strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR);
+ }
+ }
+ else if (seq->type == SEQ_TYPE_SOUND_RAM) {
+ if (seq->strip) {
+ BLI_strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR);
+ }
+ }
+ seq->flag |= SELECT;
+ recurs_sel_seq(seq);
}
#if 0
static void select_neighbor_from_last(Scene *scene, int lr)
{
- Sequence *seq = BKE_sequencer_active_get(scene);
- Sequence *neighbor;
- bool changed = false;
- if (seq) {
- neighbor = find_neighboring_sequence(scene, seq, lr, -1);
- if (neighbor) {
- switch (lr) {
- case SEQ_SIDE_LEFT:
- neighbor->flag |= SELECT;
- recurs_sel_seq(neighbor);
- neighbor->flag |= SEQ_RIGHTSEL;
- seq->flag |= SEQ_LEFTSEL;
- break;
- case SEQ_SIDE_RIGHT:
- neighbor->flag |= SELECT;
- recurs_sel_seq(neighbor);
- neighbor->flag |= SEQ_LEFTSEL;
- seq->flag |= SEQ_RIGHTSEL;
- break;
- }
- seq->flag |= SELECT;
- changed = true;
- }
- }
- if (changed) {
- /* pass */
- }
+ Sequence *seq = BKE_sequencer_active_get(scene);
+ Sequence *neighbor;
+ bool changed = false;
+ if (seq) {
+ neighbor = find_neighboring_sequence(scene, seq, lr, -1);
+ if (neighbor) {
+ switch (lr) {
+ case SEQ_SIDE_LEFT:
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ neighbor->flag |= SEQ_RIGHTSEL;
+ seq->flag |= SEQ_LEFTSEL;
+ break;
+ case SEQ_SIDE_RIGHT:
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ neighbor->flag |= SEQ_LEFTSEL;
+ seq->flag |= SEQ_RIGHTSEL;
+ break;
+ }
+ seq->flag |= SELECT;
+ changed = true;
+ }
+ }
+ if (changed) {
+ /* pass */
+ }
}
#endif
/* (de)select operator */
static int sequencer_de_select_all_exec(bContext *C, wmOperator *op)
{
- int action = RNA_enum_get(op->ptr, "action");
-
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq;
-
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if (seq->flag & SEQ_ALLSEL) {
- action = SEL_DESELECT;
- break;
- }
- }
- }
-
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- switch (action) {
- case SEL_SELECT:
- seq->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL);
- seq->flag |= SELECT;
- break;
- case SEL_DESELECT:
- seq->flag &= ~SEQ_ALLSEL;
- break;
- case SEL_INVERT:
- if (seq->flag & SEQ_ALLSEL) {
- seq->flag &= ~SEQ_ALLSEL;
- }
- else {
- seq->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL);
- seq->flag |= SELECT;
- }
- break;
- }
- }
-
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
-
- return OPERATOR_FINISHED;
+ int action = RNA_enum_get(op->ptr, "action");
+
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (seq->flag & SEQ_ALLSEL) {
+ action = SEL_DESELECT;
+ break;
+ }
+ }
+ }
+
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ switch (action) {
+ case SEL_SELECT:
+ seq->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL);
+ seq->flag |= SELECT;
+ break;
+ case SEL_DESELECT:
+ seq->flag &= ~SEQ_ALLSEL;
+ break;
+ case SEL_INVERT:
+ if (seq->flag & SEQ_ALLSEL) {
+ seq->flag &= ~SEQ_ALLSEL;
+ }
+ else {
+ seq->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL);
+ seq->flag |= SELECT;
+ }
+ break;
+ }
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
+
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_select_all(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All";
- ot->idname = "SEQUENCER_OT_select_all";
- ot->description = "Select or deselect all strips";
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->idname = "SEQUENCER_OT_select_all";
+ ot->description = "Select or deselect all strips";
- /* api callbacks */
- ot->exec = sequencer_de_select_all_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->exec = sequencer_de_select_all_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_select_all(ot);
+ 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);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq;
-
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if (seq->flag & SELECT) {
- seq->flag &= ~SEQ_ALLSEL;
- }
- else {
- seq->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL);
- seq->flag |= SELECT;
- }
- }
-
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (seq->flag & SELECT) {
+ seq->flag &= ~SEQ_ALLSEL;
+ }
+ else {
+ seq->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL);
+ seq->flag |= SELECT;
+ }
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
+
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_select_inverse(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Inverse";
- ot->idname = "SEQUENCER_OT_select_inverse";
- ot->description = "Select unselected strips";
+ /* identifiers */
+ ot->name = "Select Inverse";
+ ot->idname = "SEQUENCER_OT_select_inverse";
+ ot->description = "Select unselected strips";
- /* api callbacks */
- ot->exec = sequencer_select_inverse_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->exec = sequencer_select_inverse_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- View2D *v2d = UI_view2d_fromcontext(C);
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- const bool extend = RNA_boolean_get(op->ptr, "extend");
- const bool linked_handle = RNA_boolean_get(op->ptr, "linked_handle");
- const bool linked_time = RNA_boolean_get(op->ptr, "linked_time");
- int left_right = RNA_enum_get(op->ptr, "left_right");
-
- Sequence *seq, *neighbor, *act_orig;
- int hand, sel_side;
- TimeMarker *marker;
-
- if (ed == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- marker = find_nearest_marker(SCE_MARKERS, 1); //XXX - dummy function for now
-
- seq = find_nearest_seq(scene, v2d, &hand, event->mval);
-
- // XXX - not nice, Ctrl+RMB needs to do left_right only when not over a strip
- if (seq && linked_time && (left_right == SEQ_SELECT_LR_MOUSE)) {
- left_right = SEQ_SELECT_LR_NONE;
- }
-
-
- if (marker) {
- int oldflag;
- /* select timeline marker */
- if (extend) {
- oldflag = marker->flag;
- if (oldflag & SELECT) {
- marker->flag &= ~SELECT;
- }
- else {
- marker->flag |= SELECT;
- }
- }
- else {
- /* XXX, in 2.4x, seq selection used to deselect all, need to re-thnik this for 2.5 */
- /* deselect_markers(0, 0); */
- marker->flag |= SELECT;
- }
-
- }
- else if (left_right != SEQ_SELECT_LR_NONE) {
- /* use different logic for this */
- float x;
- ED_sequencer_deselect_all(scene);
-
- switch (left_right) {
- case SEQ_SELECT_LR_MOUSE:
- x = UI_view2d_region_to_view_x(v2d, event->mval[0]);
- break;
- case SEQ_SELECT_LR_LEFT:
- x = CFRA - 1.0f;
- break;
- case SEQ_SELECT_LR_RIGHT:
- default:
- x = CFRA;
- break;
- }
-
- SEQP_BEGIN (ed, seq)
- {
- if (((x < CFRA) && (seq->enddisp <= CFRA)) ||
- ((x >= CFRA) && (seq->startdisp >= CFRA)))
- {
- seq->flag |= SELECT;
- recurs_sel_seq(seq);
- }
- } SEQ_END;
-
- {
- SpaceSeq *sseq = CTX_wm_space_seq(C);
- if (sseq && sseq->flag & SEQ_MARKER_TRANS) {
- TimeMarker *tmarker;
-
- for (tmarker = scene->markers.first; tmarker; tmarker = tmarker->next) {
- if (((x < CFRA) && (tmarker->frame <= CFRA)) ||
- ((x >= CFRA) && (tmarker->frame >= CFRA)))
- {
- tmarker->flag |= SELECT;
- }
- else {
- tmarker->flag &= ~SELECT;
- }
- }
- }
- }
- }
- else {
- // seq = find_nearest_seq(scene, v2d, &hand, mval);
-
- act_orig = ed->act_seq;
-
- if (extend == 0 && linked_handle == 0) {
- ED_sequencer_deselect_all(scene);
- }
-
- if (seq) {
- BKE_sequencer_active_set(scene, seq);
-
- if ((seq->type == SEQ_TYPE_IMAGE) || (seq->type == SEQ_TYPE_MOVIE)) {
- if (seq->strip) {
- BLI_strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR);
- }
- }
- else if (seq->type == SEQ_TYPE_SOUND_RAM) {
- if (seq->strip) {
- BLI_strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR);
- }
- }
-
- /* 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).
- * Second click selects the strip, both of its handles and its adjacent handles (if valid).
- */
- const bool is_striponly_selected = ((seq->flag & SEQ_ALLSEL) == SELECT);
-
- if (!extend) {
- ED_sequencer_deselect_all(scene);
- }
- seq->flag &= ~SEQ_ALLSEL;
- seq->flag |= is_striponly_selected ? SEQ_ALLSEL : SELECT;
- select_surrounding_handles(scene, seq);
- }
- else {
- /* always select the strip under the cursor */
- seq->flag |= SELECT;
-
- /* First click selects adjacent handles on that side.
- * Second click selects all strips in that direction.
- * If there are no adjacent strips, it just selects all in that direction.
- */
- sel_side = hand;
- neighbor = find_neighboring_sequence(scene, seq, sel_side, -1);
- if (neighbor) {
- switch (sel_side) {
- case SEQ_SIDE_LEFT:
- if ((seq->flag & SEQ_LEFTSEL) && (neighbor->flag & SEQ_RIGHTSEL)) {
- if (extend == 0) {
- ED_sequencer_deselect_all(scene);
- }
- seq->flag |= SELECT;
-
- select_active_side(ed->seqbasep, SEQ_SIDE_LEFT, seq->machine, seq->startdisp);
- }
- else {
- if (extend == 0) {
- ED_sequencer_deselect_all(scene);
- }
- seq->flag |= SELECT;
-
- neighbor->flag |= SELECT;
- recurs_sel_seq(neighbor);
- neighbor->flag |= SEQ_RIGHTSEL;
- seq->flag |= SEQ_LEFTSEL;
- }
- break;
- case SEQ_SIDE_RIGHT:
- if ((seq->flag & SEQ_RIGHTSEL) && (neighbor->flag & SEQ_LEFTSEL)) {
- if (extend == 0) {
- ED_sequencer_deselect_all(scene);
- }
- seq->flag |= SELECT;
-
- select_active_side(ed->seqbasep, SEQ_SIDE_RIGHT, seq->machine, seq->startdisp);
- }
- else {
- if (extend == 0) {
- ED_sequencer_deselect_all(scene);
- }
- seq->flag |= SELECT;
-
- neighbor->flag |= SELECT;
- recurs_sel_seq(neighbor);
- neighbor->flag |= SEQ_LEFTSEL;
- seq->flag |= SEQ_RIGHTSEL;
- }
- break;
- }
- }
- else {
- if (extend == 0) {
- ED_sequencer_deselect_all(scene);
- }
- select_active_side(ed->seqbasep, sel_side, seq->machine, seq->startdisp);
- }
- }
- }
- else {
- if (extend && (seq->flag & SELECT) && ed->act_seq == act_orig) {
- switch (hand) {
- case SEQ_SIDE_NONE:
- if (linked_handle == 0) {
- seq->flag &= ~SEQ_ALLSEL;
- }
- break;
- case SEQ_SIDE_LEFT:
- seq->flag ^= SEQ_LEFTSEL;
- break;
- case SEQ_SIDE_RIGHT:
- seq->flag ^= SEQ_RIGHTSEL;
- break;
- }
- }
- else {
- seq->flag |= SELECT;
- if (hand == SEQ_SIDE_LEFT) {
- seq->flag |= SEQ_LEFTSEL;
- }
- if (hand == SEQ_SIDE_RIGHT) {
- seq->flag |= SEQ_RIGHTSEL;
- }
- }
- }
-
- recurs_sel_seq(seq);
-
- if (linked_time) {
- select_linked_time(ed->seqbasep, seq);
- }
- }
- }
-
- /* marker transform */
-#if 0 // XXX probably need to redo this differently for 2.5
- if (marker) {
- int mval[2], xo, yo;
-// getmouseco_areawin(mval);
- xo = mval[0];
- yo = mval[1];
-
- while (get_mbut()) {
-// getmouseco_areawin(mval);
- if (abs(mval[0] - xo) + abs(mval[1] - yo) > 4) {
- transform_markers('g', 0);
- return;
- }
- }
- }
+ View2D *v2d = UI_view2d_fromcontext(C);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool linked_handle = RNA_boolean_get(op->ptr, "linked_handle");
+ const bool linked_time = RNA_boolean_get(op->ptr, "linked_time");
+ int left_right = RNA_enum_get(op->ptr, "left_right");
+
+ Sequence *seq, *neighbor, *act_orig;
+ int hand, sel_side;
+ TimeMarker *marker;
+
+ if (ed == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ marker = find_nearest_marker(SCE_MARKERS, 1); //XXX - dummy function for now
+
+ seq = find_nearest_seq(scene, v2d, &hand, event->mval);
+
+ // XXX - not nice, Ctrl+RMB needs to do left_right only when not over a strip
+ if (seq && linked_time && (left_right == SEQ_SELECT_LR_MOUSE)) {
+ left_right = SEQ_SELECT_LR_NONE;
+ }
+
+ if (marker) {
+ int oldflag;
+ /* select timeline marker */
+ if (extend) {
+ oldflag = marker->flag;
+ if (oldflag & SELECT) {
+ marker->flag &= ~SELECT;
+ }
+ else {
+ marker->flag |= SELECT;
+ }
+ }
+ else {
+ /* XXX, in 2.4x, seq selection used to deselect all, need to re-thnik this for 2.5 */
+ /* deselect_markers(0, 0); */
+ marker->flag |= SELECT;
+ }
+ }
+ else if (left_right != SEQ_SELECT_LR_NONE) {
+ /* use different logic for this */
+ float x;
+ ED_sequencer_deselect_all(scene);
+
+ switch (left_right) {
+ case SEQ_SELECT_LR_MOUSE:
+ x = UI_view2d_region_to_view_x(v2d, event->mval[0]);
+ break;
+ case SEQ_SELECT_LR_LEFT:
+ x = CFRA - 1.0f;
+ break;
+ case SEQ_SELECT_LR_RIGHT:
+ default:
+ x = CFRA;
+ break;
+ }
+
+ SEQP_BEGIN (ed, seq) {
+ if (((x < CFRA) && (seq->enddisp <= CFRA)) || ((x >= CFRA) && (seq->startdisp >= CFRA))) {
+ seq->flag |= SELECT;
+ recurs_sel_seq(seq);
+ }
+ }
+ SEQ_END;
+
+ {
+ SpaceSeq *sseq = CTX_wm_space_seq(C);
+ if (sseq && sseq->flag & SEQ_MARKER_TRANS) {
+ TimeMarker *tmarker;
+
+ for (tmarker = scene->markers.first; tmarker; tmarker = tmarker->next) {
+ if (((x < CFRA) && (tmarker->frame <= CFRA)) ||
+ ((x >= CFRA) && (tmarker->frame >= CFRA))) {
+ tmarker->flag |= SELECT;
+ }
+ else {
+ tmarker->flag &= ~SELECT;
+ }
+ }
+ }
+ }
+ }
+ else {
+ // seq = find_nearest_seq(scene, v2d, &hand, mval);
+
+ act_orig = ed->act_seq;
+
+ if (extend == 0 && linked_handle == 0) {
+ ED_sequencer_deselect_all(scene);
+ }
+
+ if (seq) {
+ BKE_sequencer_active_set(scene, seq);
+
+ if ((seq->type == SEQ_TYPE_IMAGE) || (seq->type == SEQ_TYPE_MOVIE)) {
+ if (seq->strip) {
+ BLI_strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR);
+ }
+ }
+ else if (seq->type == SEQ_TYPE_SOUND_RAM) {
+ if (seq->strip) {
+ BLI_strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR);
+ }
+ }
+
+ /* 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).
+ * Second click selects the strip, both of its handles and its adjacent handles (if valid).
+ */
+ const bool is_striponly_selected = ((seq->flag & SEQ_ALLSEL) == SELECT);
+
+ if (!extend) {
+ ED_sequencer_deselect_all(scene);
+ }
+ seq->flag &= ~SEQ_ALLSEL;
+ seq->flag |= is_striponly_selected ? SEQ_ALLSEL : SELECT;
+ select_surrounding_handles(scene, seq);
+ }
+ else {
+ /* always select the strip under the cursor */
+ seq->flag |= SELECT;
+
+ /* First click selects adjacent handles on that side.
+ * Second click selects all strips in that direction.
+ * If there are no adjacent strips, it just selects all in that direction.
+ */
+ sel_side = hand;
+ neighbor = find_neighboring_sequence(scene, seq, sel_side, -1);
+ if (neighbor) {
+ switch (sel_side) {
+ case SEQ_SIDE_LEFT:
+ if ((seq->flag & SEQ_LEFTSEL) && (neighbor->flag & SEQ_RIGHTSEL)) {
+ if (extend == 0) {
+ ED_sequencer_deselect_all(scene);
+ }
+ seq->flag |= SELECT;
+
+ select_active_side(ed->seqbasep, SEQ_SIDE_LEFT, seq->machine, seq->startdisp);
+ }
+ else {
+ if (extend == 0) {
+ ED_sequencer_deselect_all(scene);
+ }
+ seq->flag |= SELECT;
+
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ neighbor->flag |= SEQ_RIGHTSEL;
+ seq->flag |= SEQ_LEFTSEL;
+ }
+ break;
+ case SEQ_SIDE_RIGHT:
+ if ((seq->flag & SEQ_RIGHTSEL) && (neighbor->flag & SEQ_LEFTSEL)) {
+ if (extend == 0) {
+ ED_sequencer_deselect_all(scene);
+ }
+ seq->flag |= SELECT;
+
+ select_active_side(ed->seqbasep, SEQ_SIDE_RIGHT, seq->machine, seq->startdisp);
+ }
+ else {
+ if (extend == 0) {
+ ED_sequencer_deselect_all(scene);
+ }
+ seq->flag |= SELECT;
+
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ neighbor->flag |= SEQ_LEFTSEL;
+ seq->flag |= SEQ_RIGHTSEL;
+ }
+ break;
+ }
+ }
+ else {
+ if (extend == 0) {
+ ED_sequencer_deselect_all(scene);
+ }
+ select_active_side(ed->seqbasep, sel_side, seq->machine, seq->startdisp);
+ }
+ }
+ }
+ else {
+ if (extend && (seq->flag & SELECT) && ed->act_seq == act_orig) {
+ switch (hand) {
+ case SEQ_SIDE_NONE:
+ if (linked_handle == 0) {
+ seq->flag &= ~SEQ_ALLSEL;
+ }
+ break;
+ case SEQ_SIDE_LEFT:
+ seq->flag ^= SEQ_LEFTSEL;
+ break;
+ case SEQ_SIDE_RIGHT:
+ seq->flag ^= SEQ_RIGHTSEL;
+ break;
+ }
+ }
+ else {
+ seq->flag |= SELECT;
+ if (hand == SEQ_SIDE_LEFT) {
+ seq->flag |= SEQ_LEFTSEL;
+ }
+ if (hand == SEQ_SIDE_RIGHT) {
+ seq->flag |= SEQ_RIGHTSEL;
+ }
+ }
+ }
+
+ recurs_sel_seq(seq);
+
+ if (linked_time) {
+ select_linked_time(ed->seqbasep, seq);
+ }
+ }
+ }
+
+ /* marker transform */
+#if 0 // XXX probably need to redo this differently for 2.5
+ if (marker) {
+ int mval[2], xo, yo;
+// getmouseco_areawin(mval);
+ xo = mval[0];
+ yo = mval[1];
+
+ while (get_mbut()) {
+// getmouseco_areawin(mval);
+ if (abs(mval[0] - xo) + abs(mval[1] - yo) > 4) {
+ transform_markers('g', 0);
+ return;
+ }
+ }
+ }
#endif
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
- /* allowing tweaks */
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ /* allowing tweaks */
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
}
void SEQUENCER_OT_select(wmOperatorType *ot)
{
- static const EnumPropertyItem sequencer_select_left_right_types[] = {
- {SEQ_SELECT_LR_NONE, "NONE", 0, "None", "Don't do left-right selection"},
- {SEQ_SELECT_LR_MOUSE, "MOUSE", 0, "Mouse", "Use mouse position for selection"},
- {SEQ_SELECT_LR_LEFT, "LEFT", 0, "Left", "Select left"},
- {SEQ_SELECT_LR_RIGHT, "RIGHT", 0, "Right", "Select right"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Select";
- ot->idname = "SEQUENCER_OT_select";
- ot->description = "Select a strip (last selected becomes the \"active strip\")";
-
- /* api callbacks */
- ot->invoke = sequencer_select_invoke;
- ot->poll = ED_operator_sequencer_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
- 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 */
- RNA_def_enum(ot->srna, "left_right", sequencer_select_left_right_types, 0, "Left/Right", "Select based on the current frame side the cursor is on");
- RNA_def_boolean(ot->srna, "linked_time", 0, "Linked Time", "Select other strips at the same time");
+ static const EnumPropertyItem sequencer_select_left_right_types[] = {
+ {SEQ_SELECT_LR_NONE, "NONE", 0, "None", "Don't do left-right selection"},
+ {SEQ_SELECT_LR_MOUSE, "MOUSE", 0, "Mouse", "Use mouse position for selection"},
+ {SEQ_SELECT_LR_LEFT, "LEFT", 0, "Left", "Select left"},
+ {SEQ_SELECT_LR_RIGHT, "RIGHT", 0, "Right", "Select right"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Select";
+ ot->idname = "SEQUENCER_OT_select";
+ ot->description = "Select a strip (last selected becomes the \"active strip\")";
+
+ /* api callbacks */
+ ot->invoke = sequencer_select_invoke;
+ ot->poll = ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
+ 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 */
+ RNA_def_enum(ot->srna,
+ "left_right",
+ sequencer_select_left_right_types,
+ 0,
+ "Left/Right",
+ "Select based on the current frame side the cursor is on");
+ RNA_def_boolean(
+ ot->srna, "linked_time", 0, "Linked Time", "Select other strips at the same time");
}
-
/* 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);
- Sequence *seq, *neighbor;
- bool changed = false;
- int isel;
-
- if (ed == NULL) {
- return changed;
- }
-
- if (sel) {
- sel = SELECT;
- isel = 0;
- }
- else {
- sel = 0;
- isel = SELECT;
- }
-
- if (!linked) {
- /* if not linked we only want to touch each seq once, newseq */
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- seq->tmp = NULL;
- }
- }
-
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if ((seq->flag & SELECT) == sel) {
- if (linked || (seq->tmp == NULL)) {
- /* only get unselected neighbors */
- neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_LEFT, isel);
- if (neighbor) {
- if (sel) {
- neighbor->flag |= SELECT;
- recurs_sel_seq(neighbor);
- }
- else {
- neighbor->flag &= ~SELECT;
- }
- if (!linked) {
- neighbor->tmp = (Sequence *)1;
- }
- changed = true;
- }
- neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, isel);
- if (neighbor) {
- if (sel) {
- neighbor->flag |= SELECT;
- recurs_sel_seq(neighbor);
- }
- else {
- neighbor->flag &= ~SELECT;
- }
- if (!linked) {
- neighbor->tmp = (Sequence *)1;
- }
- changed = true;
- }
- }
- }
- }
-
- return changed;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq, *neighbor;
+ bool changed = false;
+ int isel;
+
+ if (ed == NULL) {
+ return changed;
+ }
+
+ if (sel) {
+ sel = SELECT;
+ isel = 0;
+ }
+ else {
+ sel = 0;
+ isel = SELECT;
+ }
+
+ if (!linked) {
+ /* if not linked we only want to touch each seq once, newseq */
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ seq->tmp = NULL;
+ }
+ }
+
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if ((seq->flag & SELECT) == sel) {
+ if (linked || (seq->tmp == NULL)) {
+ /* only get unselected neighbors */
+ neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_LEFT, isel);
+ if (neighbor) {
+ if (sel) {
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ }
+ else {
+ neighbor->flag &= ~SELECT;
+ }
+ if (!linked) {
+ neighbor->tmp = (Sequence *)1;
+ }
+ changed = true;
+ }
+ neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, isel);
+ if (neighbor) {
+ if (sel) {
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ }
+ else {
+ neighbor->flag &= ~SELECT;
+ }
+ if (!linked) {
+ neighbor->tmp = (Sequence *)1;
+ }
+ changed = true;
+ }
+ }
+ }
+ }
+
+ return changed;
}
-
-
/* select more operator */
static int sequencer_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- if (!select_more_less_seq__internal(scene, true, false)) {
- return OPERATOR_CANCELLED;
- }
+ if (!select_more_less_seq__internal(scene, true, false)) {
+ return OPERATOR_CANCELLED;
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_select_more(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select More";
- ot->idname = "SEQUENCER_OT_select_more";
- ot->description = "Select more strips adjacent to the current selection";
+ /* identifiers */
+ ot->name = "Select More";
+ ot->idname = "SEQUENCER_OT_select_more";
+ ot->description = "Select more strips adjacent to the current selection";
- /* api callbacks */
- ot->exec = sequencer_select_more_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->exec = sequencer_select_more_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
+ /* properties */
}
-
/* select less operator */
static int sequencer_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- if (!select_more_less_seq__internal(scene, false, false)) {
- return OPERATOR_CANCELLED;
- }
+ if (!select_more_less_seq__internal(scene, false, false)) {
+ return OPERATOR_CANCELLED;
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_select_less(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Less";
- ot->idname = "SEQUENCER_OT_select_less";
- ot->description = "Shrink the current selection of adjacent selected strips";
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->idname = "SEQUENCER_OT_select_less";
+ ot->description = "Shrink the current selection of adjacent selected strips";
- /* api callbacks */
- ot->exec = sequencer_select_less_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->exec = sequencer_select_less_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
+ /* 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);
- View2D *v2d = UI_view2d_fromcontext(C);
+ Scene *scene = CTX_data_scene(C);
+ View2D *v2d = UI_view2d_fromcontext(C);
- bool extend = RNA_boolean_get(op->ptr, "extend");
+ bool extend = RNA_boolean_get(op->ptr, "extend");
- Sequence *mouse_seq;
- int selected, hand;
+ Sequence *mouse_seq;
+ int selected, hand;
- /* 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?? */
- }
+ /* 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?? */
+ }
- if (extend == 0) {
- ED_sequencer_deselect_all(scene);
- }
+ if (extend == 0) {
+ ED_sequencer_deselect_all(scene);
+ }
- mouse_seq->flag |= SELECT;
- recurs_sel_seq(mouse_seq);
+ mouse_seq->flag |= SELECT;
+ recurs_sel_seq(mouse_seq);
- selected = 1;
- while (selected) {
- selected = select_more_less_seq__internal(scene, 1, 1);
- }
+ selected = 1;
+ while (selected) {
+ selected = select_more_less_seq__internal(scene, 1, 1);
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_select_linked_pick(wmOperatorType *ot)
{
- /* 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";
+ /* 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 */
- ot->invoke = sequencer_select_linked_pick_invoke;
- ot->poll = ED_operator_sequencer_active;
+ /* api callbacks */
+ ot->invoke = sequencer_select_linked_pick_invoke;
+ ot->poll = ED_operator_sequencer_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
+ /* 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);
- bool selected;
+ Scene *scene = CTX_data_scene(C);
+ bool selected;
- selected = true;
- while (selected) {
- selected = select_more_less_seq__internal(scene, true, true);
- }
+ selected = true;
+ while (selected) {
+ selected = select_more_less_seq__internal(scene, true, true);
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_select_linked(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Linked";
- ot->idname = "SEQUENCER_OT_select_linked";
- ot->description = "Select all strips adjacent to the current selection";
+ /* identifiers */
+ ot->name = "Select Linked";
+ ot->idname = "SEQUENCER_OT_select_linked";
+ ot->description = "Select all strips adjacent to the current selection";
- /* api callbacks */
- ot->exec = sequencer_select_linked_exec;
- ot->poll = sequencer_edit_poll;
+ /* api callbacks */
+ ot->exec = sequencer_select_linked_exec;
+ ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
+ /* properties */
}
-
/* select handles operator */
static int sequencer_select_handles_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq;
- int sel_side = RNA_enum_get(op->ptr, "side");
-
-
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if (seq->flag & SELECT) {
- switch (sel_side) {
- case SEQ_SIDE_LEFT:
- seq->flag &= ~SEQ_RIGHTSEL;
- seq->flag |= SEQ_LEFTSEL;
- break;
- case SEQ_SIDE_RIGHT:
- seq->flag &= ~SEQ_LEFTSEL;
- seq->flag |= SEQ_RIGHTSEL;
- break;
- case SEQ_SIDE_BOTH:
- seq->flag |= SEQ_LEFTSEL | SEQ_RIGHTSEL;
- break;
- }
- }
- }
-
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+ int sel_side = RNA_enum_get(op->ptr, "side");
+
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (seq->flag & SELECT) {
+ switch (sel_side) {
+ case SEQ_SIDE_LEFT:
+ seq->flag &= ~SEQ_RIGHTSEL;
+ seq->flag |= SEQ_LEFTSEL;
+ break;
+ case SEQ_SIDE_RIGHT:
+ seq->flag &= ~SEQ_LEFTSEL;
+ seq->flag |= SEQ_RIGHTSEL;
+ break;
+ case SEQ_SIDE_BOTH:
+ seq->flag |= SEQ_LEFTSEL | SEQ_RIGHTSEL;
+ break;
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
+
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_select_handles(wmOperatorType *ot)
{
- /* 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 */
- ot->exec = sequencer_select_handles_exec;
- ot->poll = sequencer_edit_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side of the handle that is selected");
+ /* 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 */
+ ot->exec = sequencer_select_handles_exec;
+ ot->poll = sequencer_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna,
+ "side",
+ prop_side_types,
+ SEQ_SIDE_BOTH,
+ "Side",
+ "The side of the handle that is selected");
}
/* select side operator */
static int sequencer_select_active_side_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq_act = BKE_sequencer_active_get(scene);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq_act = BKE_sequencer_active_get(scene);
- if (ed == NULL || seq_act == NULL) {
- return OPERATOR_CANCELLED;
- }
+ if (ed == NULL || seq_act == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- seq_act->flag |= SELECT;
+ seq_act->flag |= SELECT;
- select_active_side(ed->seqbasep, RNA_enum_get(op->ptr, "side"), seq_act->machine, seq_act->startdisp);
+ select_active_side(
+ ed->seqbasep, RNA_enum_get(op->ptr, "side"), seq_act->machine, seq_act->startdisp);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_select_active_side(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Active Side";
- ot->idname = "SEQUENCER_OT_select_active_side";
- ot->description = "Select strips on the nominated side of the active strip";
-
- /* api callbacks */
- ot->exec = sequencer_select_active_side_exec;
- ot->poll = sequencer_edit_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side of the handle that is selected");
+ /* identifiers */
+ ot->name = "Select Active Side";
+ ot->idname = "SEQUENCER_OT_select_active_side";
+ ot->description = "Select strips on the nominated side of the active strip";
+
+ /* api callbacks */
+ ot->exec = sequencer_select_active_side_exec;
+ ot->poll = sequencer_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna,
+ "side",
+ prop_side_types,
+ SEQ_SIDE_BOTH,
+ "Side",
+ "The side of the handle that is selected");
}
-
/* box_select operator */
static int sequencer_box_select_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(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 select = (sel_op != SEL_OP_SUB);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- ED_sequencer_deselect_all(scene);
- }
-
- rctf rectf;
- 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) {
- 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);
- }
- }
-
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(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 select = (sel_op != SEL_OP_SUB);
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ ED_sequencer_deselect_all(scene);
+ }
+
+ rctf rectf;
+ 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) {
+ 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);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
+
+ return OPERATOR_FINISHED;
}
-
/* ****** Box Select ****** */
void SEQUENCER_OT_select_box(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Box Select";
- ot->idname = "SEQUENCER_OT_select_box";
- ot->description = "Select strips using box selection";
+ /* identifiers */
+ ot->name = "Box Select";
+ ot->idname = "SEQUENCER_OT_select_box";
+ ot->description = "Select strips using box selection";
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = sequencer_box_select_exec;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = sequencer_box_select_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
- ot->poll = ED_operator_sequencer_active;
+ ot->poll = ED_operator_sequencer_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_gesture_box(ot);
- WM_operator_properties_select_operation_simple(ot);
+ /* properties */
+ WM_operator_properties_gesture_box(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
/* ****** Selected Grouped ****** */
enum {
- SEQ_SELECT_GROUP_TYPE,
- SEQ_SELECT_GROUP_TYPE_BASIC,
- SEQ_SELECT_GROUP_TYPE_EFFECT,
- SEQ_SELECT_GROUP_DATA,
- SEQ_SELECT_GROUP_EFFECT,
- SEQ_SELECT_GROUP_EFFECT_LINK,
- SEQ_SELECT_GROUP_OVERLAP,
+ SEQ_SELECT_GROUP_TYPE,
+ SEQ_SELECT_GROUP_TYPE_BASIC,
+ SEQ_SELECT_GROUP_TYPE_EFFECT,
+ SEQ_SELECT_GROUP_DATA,
+ SEQ_SELECT_GROUP_EFFECT,
+ SEQ_SELECT_GROUP_EFFECT_LINK,
+ SEQ_SELECT_GROUP_OVERLAP,
};
static const EnumPropertyItem sequencer_prop_select_grouped_types[] = {
- {SEQ_SELECT_GROUP_TYPE, "TYPE", 0, "Type", "Shared strip type"},
- {SEQ_SELECT_GROUP_TYPE_BASIC, "TYPE_BASIC", 0, "Global Type", "All strips of same basic type (Graphical or Sound)"},
- {SEQ_SELECT_GROUP_TYPE_EFFECT, "TYPE_EFFECT", 0, "Effect Type",
- "Shared strip effect type (if active strip is not an effect one, select all non-effect strips)"},
- {SEQ_SELECT_GROUP_DATA, "DATA", 0, "Data", "Shared data (scene, image, sound, etc.)"},
- {SEQ_SELECT_GROUP_EFFECT, "EFFECT", 0, "Effect", "Shared effects"},
- {SEQ_SELECT_GROUP_EFFECT_LINK, "EFFECT_LINK", 0, "Effect/Linked",
- "Other strips affected by the active one (sharing some time, and below or effect-assigned)"},
- {SEQ_SELECT_GROUP_OVERLAP, "OVERLAP", 0, "Overlap", "Overlapping time"},
- {0, NULL, 0, NULL, NULL},
+ {SEQ_SELECT_GROUP_TYPE, "TYPE", 0, "Type", "Shared strip type"},
+ {SEQ_SELECT_GROUP_TYPE_BASIC,
+ "TYPE_BASIC",
+ 0,
+ "Global Type",
+ "All strips of same basic type (Graphical or Sound)"},
+ {SEQ_SELECT_GROUP_TYPE_EFFECT,
+ "TYPE_EFFECT",
+ 0,
+ "Effect Type",
+ "Shared strip effect type (if active strip is not an effect one, select all non-effect "
+ "strips)"},
+ {SEQ_SELECT_GROUP_DATA, "DATA", 0, "Data", "Shared data (scene, image, sound, etc.)"},
+ {SEQ_SELECT_GROUP_EFFECT, "EFFECT", 0, "Effect", "Shared effects"},
+ {SEQ_SELECT_GROUP_EFFECT_LINK,
+ "EFFECT_LINK",
+ 0,
+ "Effect/Linked",
+ "Other strips affected by the active one (sharing some time, and below or effect-assigned)"},
+ {SEQ_SELECT_GROUP_OVERLAP, "OVERLAP", 0, "Overlap", "Overlapping time"},
+ {0, NULL, 0, NULL, NULL},
};
#define SEQ_IS_SOUND(_seq) ((_seq->type & SEQ_TYPE_SOUND_RAM) && !(_seq->type & SEQ_TYPE_EFFECT))
#define SEQ_IS_EFFECT(_seq) ((_seq->type & SEQ_TYPE_EFFECT) != 0)
-#define SEQ_USE_DATA(_seq) (ELEM(_seq->type, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK) || SEQ_HAS_PATH(_seq))
+#define SEQ_USE_DATA(_seq) \
+ (ELEM(_seq->type, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK) || SEQ_HAS_PATH(_seq))
#define SEQ_CHANNEL_CHECK(_seq, _chan) (ELEM((_chan), 0, (_seq)->machine))
static bool select_grouped_type(Editing *ed, Sequence *actseq, const int channel)
{
- Sequence *seq;
- bool changed = false;
-
- SEQP_BEGIN (ed, seq)
- {
- if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == actseq->type) {
- seq->flag |= SELECT;
- changed = true;
- }
- }
- SEQ_END;
-
- return changed;
+ Sequence *seq;
+ bool changed = false;
+
+ SEQP_BEGIN (ed, seq) {
+ if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == actseq->type) {
+ seq->flag |= SELECT;
+ changed = true;
+ }
+ }
+ SEQ_END;
+
+ return changed;
}
static bool select_grouped_type_basic(Editing *ed, Sequence *actseq, const int channel)
{
- Sequence *seq;
- bool changed = false;
- const bool is_sound = SEQ_IS_SOUND(actseq);
-
- SEQP_BEGIN (ed, seq)
- {
- if (SEQ_CHANNEL_CHECK(seq, channel) && (is_sound ? SEQ_IS_SOUND(seq) : !SEQ_IS_SOUND(seq))) {
- seq->flag |= SELECT;
- changed = true;
- }
- }
- SEQ_END;
-
- return changed;
+ Sequence *seq;
+ bool changed = false;
+ const bool is_sound = SEQ_IS_SOUND(actseq);
+
+ SEQP_BEGIN (ed, seq) {
+ if (SEQ_CHANNEL_CHECK(seq, channel) && (is_sound ? SEQ_IS_SOUND(seq) : !SEQ_IS_SOUND(seq))) {
+ seq->flag |= SELECT;
+ changed = true;
+ }
+ }
+ SEQ_END;
+
+ return changed;
}
static bool select_grouped_type_effect(Editing *ed, Sequence *actseq, const int channel)
{
- Sequence *seq;
- bool changed = false;
- const bool is_effect = SEQ_IS_EFFECT(actseq);
-
- SEQP_BEGIN (ed, seq)
- {
- if (SEQ_CHANNEL_CHECK(seq, channel) && (is_effect ? SEQ_IS_EFFECT(seq) : !SEQ_IS_EFFECT(seq))) {
- seq->flag |= SELECT;
- changed = true;
- }
- }
- SEQ_END;
-
- return changed;
+ Sequence *seq;
+ bool changed = false;
+ const bool is_effect = SEQ_IS_EFFECT(actseq);
+
+ SEQP_BEGIN (ed, seq) {
+ if (SEQ_CHANNEL_CHECK(seq, channel) &&
+ (is_effect ? SEQ_IS_EFFECT(seq) : !SEQ_IS_EFFECT(seq))) {
+ seq->flag |= SELECT;
+ changed = true;
+ }
+ }
+ SEQ_END;
+
+ return changed;
}
static bool select_grouped_data(Editing *ed, Sequence *actseq, const int channel)
{
- Sequence *seq;
- bool changed = false;
- const char *dir = actseq->strip ? actseq->strip->dir : NULL;
-
- if (!SEQ_USE_DATA(actseq)) {
- return changed;
- }
-
- if (SEQ_HAS_PATH(actseq) && dir) {
- SEQP_BEGIN (ed, seq)
- {
- if (SEQ_CHANNEL_CHECK(seq, channel) && SEQ_HAS_PATH(seq) && seq->strip && STREQ(seq->strip->dir, dir)) {
- seq->flag |= SELECT;
- changed = true;
- }
- }
- SEQ_END;
- }
- else if (actseq->type == SEQ_TYPE_SCENE) {
- Scene *sce = actseq->scene;
- SEQP_BEGIN (ed, seq)
- {
- if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == SEQ_TYPE_SCENE && seq->scene == sce) {
- seq->flag |= SELECT;
- changed = true;
- }
- }
- SEQ_END;
- }
- else if (actseq->type == SEQ_TYPE_MOVIECLIP) {
- MovieClip *clip = actseq->clip;
- SEQP_BEGIN (ed, seq)
- {
- if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == SEQ_TYPE_MOVIECLIP && seq->clip == clip) {
- seq->flag |= SELECT;
- changed = true;
- }
- }
- SEQ_END;
- }
- else if (actseq->type == SEQ_TYPE_MASK) {
- struct Mask *mask = actseq->mask;
- SEQP_BEGIN (ed, seq)
- {
- if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == SEQ_TYPE_MASK && seq->mask == mask) {
- seq->flag |= SELECT;
- changed = true;
- }
- }
- SEQ_END;
- }
-
- return changed;
+ Sequence *seq;
+ bool changed = false;
+ const char *dir = actseq->strip ? actseq->strip->dir : NULL;
+
+ if (!SEQ_USE_DATA(actseq)) {
+ return changed;
+ }
+
+ if (SEQ_HAS_PATH(actseq) && dir) {
+ SEQP_BEGIN (ed, seq) {
+ if (SEQ_CHANNEL_CHECK(seq, channel) && SEQ_HAS_PATH(seq) && seq->strip &&
+ STREQ(seq->strip->dir, dir)) {
+ seq->flag |= SELECT;
+ changed = true;
+ }
+ }
+ SEQ_END;
+ }
+ else if (actseq->type == SEQ_TYPE_SCENE) {
+ Scene *sce = actseq->scene;
+ SEQP_BEGIN (ed, seq) {
+ if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == SEQ_TYPE_SCENE && seq->scene == sce) {
+ seq->flag |= SELECT;
+ changed = true;
+ }
+ }
+ SEQ_END;
+ }
+ else if (actseq->type == SEQ_TYPE_MOVIECLIP) {
+ MovieClip *clip = actseq->clip;
+ SEQP_BEGIN (ed, seq) {
+ if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == SEQ_TYPE_MOVIECLIP &&
+ seq->clip == clip) {
+ seq->flag |= SELECT;
+ changed = true;
+ }
+ }
+ SEQ_END;
+ }
+ else if (actseq->type == SEQ_TYPE_MASK) {
+ struct Mask *mask = actseq->mask;
+ SEQP_BEGIN (ed, seq) {
+ if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == SEQ_TYPE_MASK && seq->mask == mask) {
+ seq->flag |= SELECT;
+ changed = true;
+ }
+ }
+ SEQ_END;
+ }
+
+ return changed;
}
static bool select_grouped_effect(Editing *ed, Sequence *actseq, const int channel)
{
- Sequence *seq;
- bool changed = false;
- bool effects[SEQ_TYPE_MAX + 1];
- int i;
-
- for (i = 0; i <= SEQ_TYPE_MAX; i++) {
- effects[i] = false;
- }
-
- SEQP_BEGIN (ed, seq)
- {
- if (SEQ_CHANNEL_CHECK(seq, channel) && (seq->type & SEQ_TYPE_EFFECT) &&
- ELEM(actseq, seq->seq1, seq->seq2, seq->seq3))
- {
- effects[seq->type] = true;
- }
- }
- SEQ_END;
-
- SEQP_BEGIN (ed, seq)
- {
- if (SEQ_CHANNEL_CHECK(seq, channel) && effects[seq->type]) {
- if (seq->seq1) { seq->seq1->flag |= SELECT; }
- if (seq->seq2) { seq->seq2->flag |= SELECT; }
- if (seq->seq3) { seq->seq3->flag |= SELECT; }
- changed = true;
- }
- }
- SEQ_END;
-
- return changed;
+ Sequence *seq;
+ bool changed = false;
+ bool effects[SEQ_TYPE_MAX + 1];
+ int i;
+
+ for (i = 0; i <= SEQ_TYPE_MAX; i++) {
+ effects[i] = false;
+ }
+
+ SEQP_BEGIN (ed, seq) {
+ if (SEQ_CHANNEL_CHECK(seq, channel) && (seq->type & SEQ_TYPE_EFFECT) &&
+ ELEM(actseq, seq->seq1, seq->seq2, seq->seq3)) {
+ effects[seq->type] = true;
+ }
+ }
+ SEQ_END;
+
+ SEQP_BEGIN (ed, seq) {
+ if (SEQ_CHANNEL_CHECK(seq, channel) && effects[seq->type]) {
+ if (seq->seq1) {
+ seq->seq1->flag |= SELECT;
+ }
+ if (seq->seq2) {
+ seq->seq2->flag |= SELECT;
+ }
+ if (seq->seq3) {
+ seq->seq3->flag |= SELECT;
+ }
+ changed = true;
+ }
+ }
+ SEQ_END;
+
+ return changed;
}
static bool select_grouped_time_overlap(Editing *ed, Sequence *actseq)
{
- Sequence *seq;
- bool changed = false;
-
- SEQP_BEGIN (ed, seq)
- {
- if (!((seq->startdisp >= actseq->enddisp) || (seq->enddisp < actseq->startdisp))) {
- seq->flag |= SELECT;
- changed = true;
- }
- }
- SEQ_END;
-
- return changed;
+ Sequence *seq;
+ bool changed = false;
+
+ SEQP_BEGIN (ed, seq) {
+ if (!((seq->startdisp >= actseq->enddisp) || (seq->enddisp < actseq->startdisp))) {
+ seq->flag |= SELECT;
+ changed = true;
+ }
+ }
+ SEQ_END;
+
+ return changed;
}
static bool select_grouped_effect_link(Editing *ed, Sequence *actseq, const int channel)
{
- Sequence *seq = NULL;
- bool changed = false;
- const bool is_audio = ((actseq->type == SEQ_TYPE_META) || SEQ_IS_SOUND(actseq));
- int startdisp = actseq->startdisp;
- int enddisp = actseq->enddisp;
- int machine = actseq->machine;
- SeqIterator iter;
-
- SEQP_BEGIN (ed, seq)
- {
- seq->tmp = NULL;
- }
- SEQ_END;
-
- actseq->tmp = POINTER_FROM_INT(true);
-
- for (BKE_sequence_iterator_begin(ed, &iter, true); iter.valid; BKE_sequence_iterator_next(&iter)) {
- seq = iter.seq;
-
- /* 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) || (seq->enddisp < startdisp) ||
- (!is_audio && SEQ_IS_SOUND(seq)) ||
- (is_audio && !((seq->type == SEQ_TYPE_META) || SEQ_IS_SOUND(seq))))
- {
- continue;
- }
-
- /* 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) {
- startdisp = seq->startdisp;
- }
- if (enddisp < seq->enddisp) {
- enddisp = seq->enddisp;
- }
- if (machine < seq->machine) {
- machine = seq->machine;
- }
-
- seq->tmp = POINTER_FROM_INT(true);
-
- seq->flag |= SELECT;
- changed = true;
-
- /* Unfortunately, we must restart checks from the beginning. */
- BKE_sequence_iterator_end(&iter);
- BKE_sequence_iterator_begin(ed, &iter, true);
- }
-
- /* Video strips below active one, or any strip for audio (order do no matters here!). */
- else if (seq->machine < machine || is_audio) {
- seq->flag |= SELECT;
- changed = true;
- }
- }
- BKE_sequence_iterator_end(&iter);
-
- return changed;
+ Sequence *seq = NULL;
+ bool changed = false;
+ const bool is_audio = ((actseq->type == SEQ_TYPE_META) || SEQ_IS_SOUND(actseq));
+ int startdisp = actseq->startdisp;
+ int enddisp = actseq->enddisp;
+ int machine = actseq->machine;
+ SeqIterator iter;
+
+ SEQP_BEGIN (ed, seq) {
+ seq->tmp = NULL;
+ }
+ SEQ_END;
+
+ actseq->tmp = POINTER_FROM_INT(true);
+
+ for (BKE_sequence_iterator_begin(ed, &iter, true); iter.valid;
+ BKE_sequence_iterator_next(&iter)) {
+ seq = iter.seq;
+
+ /* 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) ||
+ (seq->enddisp < startdisp) || (!is_audio && SEQ_IS_SOUND(seq)) ||
+ (is_audio && !((seq->type == SEQ_TYPE_META) || SEQ_IS_SOUND(seq)))) {
+ continue;
+ }
+
+ /* 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) {
+ startdisp = seq->startdisp;
+ }
+ if (enddisp < seq->enddisp) {
+ enddisp = seq->enddisp;
+ }
+ if (machine < seq->machine) {
+ machine = seq->machine;
+ }
+
+ seq->tmp = POINTER_FROM_INT(true);
+
+ seq->flag |= SELECT;
+ changed = true;
+
+ /* Unfortunately, we must restart checks from the beginning. */
+ BKE_sequence_iterator_end(&iter);
+ BKE_sequence_iterator_begin(ed, &iter, true);
+ }
+
+ /* Video strips below active one, or any strip for audio (order do no matters here!). */
+ else if (seq->machine < machine || is_audio) {
+ seq->flag |= SELECT;
+ changed = true;
+ }
+ }
+ BKE_sequence_iterator_end(&iter);
+
+ return changed;
}
#undef SEQ_IS_SOUND
@@ -1237,83 +1244,89 @@ static bool select_grouped_effect_link(Editing *ed, Sequence *actseq, const int
static int sequencer_select_grouped_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq, *actseq = BKE_sequencer_active_get(scene);
-
- 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;
- changed = true;
- }
- SEQ_END;
- }
-
- switch (type) {
- case SEQ_SELECT_GROUP_TYPE:
- changed |= select_grouped_type(ed, actseq, channel);
- break;
- case SEQ_SELECT_GROUP_TYPE_BASIC:
- changed |= select_grouped_type_basic(ed, actseq, channel);
- break;
- case SEQ_SELECT_GROUP_TYPE_EFFECT:
- changed |= select_grouped_type_effect(ed, actseq, channel);
- break;
- case SEQ_SELECT_GROUP_DATA:
- changed |= select_grouped_data(ed, actseq, channel);
- break;
- case SEQ_SELECT_GROUP_EFFECT:
- changed |= select_grouped_effect(ed, actseq, channel);
- break;
- case SEQ_SELECT_GROUP_EFFECT_LINK:
- changed |= select_grouped_effect_link(ed, actseq, channel);
- break;
- case SEQ_SELECT_GROUP_OVERLAP:
- changed |= select_grouped_time_overlap(ed, actseq);
- break;
- default:
- BLI_assert(0);
- break;
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq, *actseq = BKE_sequencer_active_get(scene);
+
+ 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;
+ changed = true;
+ }
+ SEQ_END;
+ }
+
+ switch (type) {
+ case SEQ_SELECT_GROUP_TYPE:
+ changed |= select_grouped_type(ed, actseq, channel);
+ break;
+ case SEQ_SELECT_GROUP_TYPE_BASIC:
+ changed |= select_grouped_type_basic(ed, actseq, channel);
+ break;
+ case SEQ_SELECT_GROUP_TYPE_EFFECT:
+ changed |= select_grouped_type_effect(ed, actseq, channel);
+ break;
+ case SEQ_SELECT_GROUP_DATA:
+ changed |= select_grouped_data(ed, actseq, channel);
+ break;
+ case SEQ_SELECT_GROUP_EFFECT:
+ changed |= select_grouped_effect(ed, actseq, channel);
+ break;
+ case SEQ_SELECT_GROUP_EFFECT_LINK:
+ changed |= select_grouped_effect_link(ed, actseq, channel);
+ break;
+ case SEQ_SELECT_GROUP_OVERLAP:
+ changed |= select_grouped_time_overlap(ed, actseq);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
}
void SEQUENCER_OT_select_grouped(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Grouped";
- ot->description = "Select all strips grouped by various properties";
- ot->idname = "SEQUENCER_OT_select_grouped";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = sequencer_select_grouped_exec;
- ot->poll = sequencer_edit_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", sequencer_prop_select_grouped_types, 0, "Type", "");
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
- RNA_def_boolean(ot->srna, "use_active_channel", false, "Same Channel",
- "Only consider strips on the same channel as the active one");
+ /* identifiers */
+ ot->name = "Select Grouped";
+ ot->description = "Select all strips grouped by various properties";
+ ot->idname = "SEQUENCER_OT_select_grouped";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = sequencer_select_grouped_exec;
+ ot->poll = sequencer_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", sequencer_prop_select_grouped_types, 0, "Type", "");
+ RNA_def_boolean(ot->srna,
+ "extend",
+ false,
+ "Extend",
+ "Extend selection instead of deselecting everything first");
+ RNA_def_boolean(ot->srna,
+ "use_active_channel",
+ false,
+ "Same Channel",
+ "Only consider strips on the same channel as the active one");
}
diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c
index 30f526c0675..e16029395bd 100644
--- a/source/blender/editors/space_sequencer/sequencer_view.c
+++ b/source/blender/editors/space_sequencer/sequencer_view.c
@@ -17,7 +17,6 @@
* All rights reserved.
*/
-
/** \file
* \ingroup spseq
*/
@@ -53,188 +52,199 @@
/******************** sample backdrop operator ********************/
typedef struct ImageSampleInfo {
- ARegionType *art;
- void *draw_handle;
- int x, y;
- int channels;
+ ARegionType *art;
+ void *draw_handle;
+ int x, y;
+ int channels;
- unsigned char col[4];
- float colf[4];
- float linearcol[4];
+ unsigned char col[4];
+ float colf[4];
+ float linearcol[4];
- unsigned char *colp;
- const float *colfp;
+ unsigned char *colp;
+ const float *colfp;
- int draw;
-int color_manage;
+ 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);
- }
+ 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_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 += (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));
+ Main *bmain = CTX_data_main(C);
+ struct Depsgraph *depsgraph = CTX_data_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 += (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;
+ 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);
+ 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;
+ 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;
- }
+ 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;
+ 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);
+ sample_apply(C, op, event);
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ 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;
+ 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);
+ 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;
+ 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 */
- 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;
-
- /* flags */
- ot->flag = OPTYPE_BLOCKING;
+ /* 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;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
}
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 561d603ab08..35c031e8bc8 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -21,7 +21,6 @@
* \ingroup spseq
*/
-
#include <string.h>
#include <stdio.h>
@@ -56,684 +55,698 @@
#include "IMB_imbuf.h"
-#include "sequencer_intern.h" // own include
+#include "sequencer_intern.h" // own include
/**************************** common state *****************************/
static void sequencer_scopes_tag_refresh(ScrArea *sa)
{
- SpaceSeq *sseq = (SpaceSeq *)sa->spacedata.first;
+ SpaceSeq *sseq = (SpaceSeq *)sa->spacedata.first;
- sseq->scopes.reference_ibuf = NULL;
+ sseq->scopes.reference_ibuf = NULL;
}
/* ******************** manage regions ********************* */
ARegion *sequencer_has_buttons_region(ScrArea *sa)
{
- ARegion *ar, *arnew;
+ ARegion *ar, *arnew;
- ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
- if (ar) {
- return ar;
- }
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
+ if (ar) {
+ return ar;
+ }
- /* add subdiv level; after header */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+ /* add subdiv level; after header */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
- /* is error! */
- if (ar == NULL) {
- return NULL;
- }
+ /* is error! */
+ if (ar == NULL) {
+ return NULL;
+ }
- arnew = MEM_callocN(sizeof(ARegion), "buttons for sequencer");
+ arnew = MEM_callocN(sizeof(ARegion), "buttons for sequencer");
- BLI_insertlinkafter(&sa->regionbase, ar, arnew);
- arnew->regiontype = RGN_TYPE_UI;
- arnew->alignment = RGN_ALIGN_RIGHT;
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype = RGN_TYPE_UI;
+ arnew->alignment = RGN_ALIGN_RIGHT;
- arnew->flag = RGN_FLAG_HIDDEN;
+ arnew->flag = RGN_FLAG_HIDDEN;
- return arnew;
+ return arnew;
}
static ARegion *sequencer_find_region(ScrArea *sa, short type)
{
- ARegion *ar = NULL;
+ ARegion *ar = NULL;
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == type) {
- return ar;
- }
- }
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == type) {
+ return ar;
+ }
+ }
- return ar;
+ return ar;
}
/* ******************** default callbacks for sequencer space ***************** */
static SpaceLink *sequencer_new(const ScrArea *UNUSED(sa), const Scene *scene)
{
- ARegion *ar;
- SpaceSeq *sseq;
-
- sseq = MEM_callocN(sizeof(SpaceSeq), "initsequencer");
- sseq->spacetype = SPACE_SEQ;
- sseq->chanshown = 0;
- sseq->view = SEQ_VIEW_SEQUENCE;
- sseq->mainb = SEQ_DRAW_IMG_IMBUF;
- sseq->flag = SEQ_SHOW_GPENCIL | SEQ_USE_ALPHA | SEQ_SHOW_MARKER_LINES;
-
- /* 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;
-
- /* 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_SCALE_HORIZONTAL);
- ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL);
- ar->v2d.keepzoom = 0;
- ar->v2d.keeptot = 0;
- ar->v2d.align = V2D_ALIGN_NO_NEG_Y;
-
- return (SpaceLink *)sseq;
+ ARegion *ar;
+ SpaceSeq *sseq;
+
+ sseq = MEM_callocN(sizeof(SpaceSeq), "initsequencer");
+ sseq->spacetype = SPACE_SEQ;
+ sseq->chanshown = 0;
+ sseq->view = SEQ_VIEW_SEQUENCE;
+ sseq->mainb = SEQ_DRAW_IMG_IMBUF;
+ sseq->flag = SEQ_SHOW_GPENCIL | SEQ_USE_ALPHA | SEQ_SHOW_MARKER_LINES;
+
+ /* 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;
+
+ /* 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_SCALE_HORIZONTAL);
+ ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL);
+ ar->v2d.keepzoom = 0;
+ ar->v2d.keeptot = 0;
+ ar->v2d.align = V2D_ALIGN_NO_NEG_Y;
+
+ return (SpaceLink *)sseq;
}
/* not spacelink itself */
static void sequencer_free(SpaceLink *sl)
{
- SpaceSeq *sseq = (SpaceSeq *) sl;
- SequencerScopes *scopes = &sseq->scopes;
+ 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);
- }
+ if (scopes->zebra_ibuf) {
+ IMB_freeImBuf(scopes->zebra_ibuf);
+ }
- if (scopes->waveform_ibuf) {
- IMB_freeImBuf(scopes->waveform_ibuf);
- }
+ if (scopes->waveform_ibuf) {
+ IMB_freeImBuf(scopes->waveform_ibuf);
+ }
- if (scopes->sep_waveform_ibuf) {
- IMB_freeImBuf(scopes->sep_waveform_ibuf);
- }
+ if (scopes->sep_waveform_ibuf) {
+ IMB_freeImBuf(scopes->sep_waveform_ibuf);
+ }
- if (scopes->vector_ibuf) {
- IMB_freeImBuf(scopes->vector_ibuf);
- }
+ if (scopes->vector_ibuf) {
+ IMB_freeImBuf(scopes->vector_ibuf);
+ }
- if (scopes->histogram_ibuf) {
- IMB_freeImBuf(scopes->histogram_ibuf);
- }
+ if (scopes->histogram_ibuf) {
+ IMB_freeImBuf(scopes->histogram_ibuf);
+ }
}
-
/* spacetype; init callback */
static void sequencer_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
{
-
}
static void sequencer_refresh(const bContext *C, ScrArea *sa)
{
- 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);
- 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;
- 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);
- view_changed = true;
- }
- if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
- ar_main->alignment = RGN_ALIGN_NONE;
- view_changed = true;
- }
- if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
- ar_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);
- 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;
- view_changed = true;
- }
- if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
- ar_main->alignment = RGN_ALIGN_NONE;
- view_changed = true;
- }
- if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
- ar_preview->alignment = RGN_ALIGN_NONE;
- view_changed = true;
- }
- break;
- case SEQ_VIEW_SEQUENCE_PREVIEW:
- if (ar_main && ar_preview) {
- /* Get available height (without DPI correction). */
- const float height = (sa->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);
- 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);
- view_changed = true;
- }
- if (ar_main->alignment != RGN_ALIGN_NONE) {
- ar_main->alignment = RGN_ALIGN_NONE;
- view_changed = true;
- }
- if (ar_preview->alignment != RGN_ALIGN_TOP) {
- ar_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);
- view_changed = true;
- }
- }
- break;
- }
-
- if (view_changed) {
- ED_area_initialize(wm, window, sa);
- ED_area_tag_redraw(sa);
- }
+ 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);
+ 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;
+ 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);
+ view_changed = true;
+ }
+ if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
+ ar_main->alignment = RGN_ALIGN_NONE;
+ view_changed = true;
+ }
+ if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
+ ar_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);
+ 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;
+ view_changed = true;
+ }
+ if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
+ ar_main->alignment = RGN_ALIGN_NONE;
+ view_changed = true;
+ }
+ if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
+ ar_preview->alignment = RGN_ALIGN_NONE;
+ view_changed = true;
+ }
+ break;
+ case SEQ_VIEW_SEQUENCE_PREVIEW:
+ if (ar_main && ar_preview) {
+ /* Get available height (without DPI correction). */
+ const float height = (sa->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);
+ 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);
+ view_changed = true;
+ }
+ if (ar_main->alignment != RGN_ALIGN_NONE) {
+ ar_main->alignment = RGN_ALIGN_NONE;
+ view_changed = true;
+ }
+ if (ar_preview->alignment != RGN_ALIGN_TOP) {
+ ar_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);
+ view_changed = true;
+ }
+ }
+ break;
+ }
+
+ if (view_changed) {
+ ED_area_initialize(wm, window, sa);
+ ED_area_tag_redraw(sa);
+ }
}
static SpaceLink *sequencer_duplicate(SpaceLink *sl)
{
- SpaceSeq *sseqn = MEM_dupallocN(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));
+ memset(&sseqn->scopes, 0, sizeof(sseqn->scopes));
- return (SpaceLink *)sseqn;
+ return (SpaceLink *)sseqn;
}
-static void sequencer_listener(
- wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene))
+static void sequencer_listener(wmWindow *UNUSED(win),
+ ScrArea *sa,
+ wmNotifier *wmn,
+ Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_SCENE:
- switch (wmn->data) {
- case ND_FRAME:
- case ND_SEQUENCER:
- sequencer_scopes_tag_refresh(sa);
- break;
- }
- break;
- case NC_WINDOW:
- case NC_SPACE:
- if (wmn->data == ND_SPACE_SEQUENCER) {
- sequencer_scopes_tag_refresh(sa);
- }
- break;
- case NC_GPENCIL:
- if (wmn->data & ND_GPENCIL_EDITMODE) {
- ED_area_tag_redraw(sa);
- }
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_FRAME:
+ case ND_SEQUENCER:
+ sequencer_scopes_tag_refresh(sa);
+ break;
+ }
+ break;
+ case NC_WINDOW:
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_SEQUENCER) {
+ sequencer_scopes_tag_refresh(sa);
+ }
+ break;
+ case NC_GPENCIL:
+ if (wmn->data & ND_GPENCIL_EDITMODE) {
+ ED_area_tag_redraw(sa);
+ }
+ break;
+ }
}
/* ************* dropboxes ************* */
-static bool image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **UNUSED(tooltip))
+static bool image_drop_poll(bContext *C,
+ wmDrag *drag,
+ const wmEvent *event,
+ const char **UNUSED(tooltip))
{
- ARegion *ar = 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) {
- return 1;
- }
- }
- }
-
- return 0;
+ ARegion *ar = 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) {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
}
-static bool movie_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **UNUSED(tooltip))
+static bool movie_drop_poll(bContext *C,
+ wmDrag *drag,
+ const wmEvent *event,
+ const char **UNUSED(tooltip))
{
- ARegion *ar = 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) {
- return 1;
- }
- }
- }
- return 0;
+ ARegion *ar = 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) {
+ return 1;
+ }
+ }
+ }
+ return 0;
}
-static bool sound_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **UNUSED(tooltip))
+static bool sound_drop_poll(bContext *C,
+ wmDrag *drag,
+ const wmEvent *event,
+ const char **UNUSED(tooltip))
{
- ARegion *ar = 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) {
- return 1;
- }
- }
- }
- return 0;
+ ARegion *ar = 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) {
+ return 1;
+ }
+ }
+ }
+ return 0;
}
static void sequencer_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- /* copy drag path to properties */
- if (RNA_struct_find_property(drop->ptr, "filepath")) {
- RNA_string_set(drop->ptr, "filepath", drag->path);
- }
+ /* copy drag path to properties */
+ if (RNA_struct_find_property(drop->ptr, "filepath")) {
+ RNA_string_set(drop->ptr, "filepath", drag->path);
+ }
- if (RNA_struct_find_property(drop->ptr, "directory")) {
- PointerRNA itemptr;
- char dir[FILE_MAX], file[FILE_MAX];
+ if (RNA_struct_find_property(drop->ptr, "directory")) {
+ PointerRNA itemptr;
+ char dir[FILE_MAX], file[FILE_MAX];
- BLI_split_dirfile(drag->path, dir, file, sizeof(dir), sizeof(file));
+ BLI_split_dirfile(drag->path, dir, file, sizeof(dir), sizeof(file));
- RNA_string_set(drop->ptr, "directory", dir);
+ RNA_string_set(drop->ptr, "directory", dir);
- RNA_collection_clear(drop->ptr, "files");
- RNA_collection_add(drop->ptr, "files", &itemptr);
- RNA_string_set(&itemptr, "name", file);
- }
+ RNA_collection_clear(drop->ptr, "files");
+ RNA_collection_add(drop->ptr, "files", &itemptr);
+ RNA_string_set(&itemptr, "name", file);
+ }
}
/* this region dropbox definition */
static void sequencer_dropboxes(void)
{
- ListBase *lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
+ ListBase *lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
- WM_dropbox_add(lb, "SEQUENCER_OT_image_strip_add", image_drop_poll, sequencer_drop_copy);
- WM_dropbox_add(lb, "SEQUENCER_OT_movie_strip_add", movie_drop_poll, sequencer_drop_copy);
- WM_dropbox_add(lb, "SEQUENCER_OT_sound_strip_add", sound_drop_poll, sequencer_drop_copy);
+ WM_dropbox_add(lb, "SEQUENCER_OT_image_strip_add", image_drop_poll, sequencer_drop_copy);
+ WM_dropbox_add(lb, "SEQUENCER_OT_movie_strip_add", movie_drop_poll, sequencer_drop_copy);
+ WM_dropbox_add(lb, "SEQUENCER_OT_sound_strip_add", sound_drop_poll, sequencer_drop_copy);
}
/* ************* 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)
{
- Scene *scene = CTX_data_scene(C);
-
- if (CTX_data_dir(member)) {
- CTX_data_dir_set(result, sequencer_context_dir);
-
- return true;
- }
- else if (CTX_data_equals(member, "edit_mask")) {
- Mask *mask = BKE_sequencer_mask_get(scene);
- if (mask) {
- CTX_data_id_pointer_set(result, &mask->id);
- }
- return true;
- }
-
- return false;
+ Scene *scene = CTX_data_scene(C);
+
+ if (CTX_data_dir(member)) {
+ CTX_data_dir_set(result, sequencer_context_dir);
+
+ return true;
+ }
+ else if (CTX_data_equals(member, "edit_mask")) {
+ Mask *mask = BKE_sequencer_mask_get(scene);
+ if (mask) {
+ CTX_data_id_pointer_set(result, &mask->id);
+ }
+ return true;
+ }
+
+ return false;
}
/* *********************** 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)
{
- wmKeyMap *keymap;
- ListBase *lb;
+ wmKeyMap *keymap;
+ ListBase *lb;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
#if 0
- keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", 0, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", 0, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
#endif
- keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- /* own keymap */
- keymap = WM_keymap_ensure(wm->defaultconf, "Sequencer", SPACE_SEQ, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ /* own keymap */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Sequencer", SPACE_SEQ, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- /* add drop boxes */
- lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
+ /* 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(&ar->handlers, lb);
}
static void sequencer_main_region_draw(const bContext *C, ARegion *ar)
{
- /* NLE - strip editing timeline interface */
- draw_timeline_seq(C, ar);
+ /* NLE - strip editing timeline interface */
+ draw_timeline_seq(C, ar);
}
-static void sequencer_main_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void sequencer_main_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* 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_SEQUENCER:
- case ND_RENDER_RESULT:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_ANIMATION:
- switch (wmn->data) {
- case ND_KEYFRAME:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_SEQUENCER) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_ID:
- if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SCREEN:
- if (ELEM(wmn->data, ND_ANIMPLAY)) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
+ /* 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_SEQUENCER:
+ case ND_RENDER_RESULT:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_ANIMATION:
+ switch (wmn->data) {
+ case ND_KEYFRAME:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_SEQUENCER) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_ID:
+ if (wmn->action == NA_RENAME) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SCREEN:
+ if (ELEM(wmn->data, ND_ANIMPLAY)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
}
-static void sequencer_main_region_message_subscribe(
- const struct bContext *UNUSED(C),
- struct WorkSpace *UNUSED(workspace), struct Scene *scene,
- struct bScreen *UNUSED(screen), struct ScrArea *UNUSED(sa), struct ARegion *ar,
- struct wmMsgBus *mbus)
+static void sequencer_main_region_message_subscribe(const struct bContext *UNUSED(C),
+ struct WorkSpace *UNUSED(workspace),
+ struct Scene *scene,
+ struct bScreen *UNUSED(screen),
+ struct ScrArea *UNUSED(sa),
+ struct ARegion *ar,
+ struct wmMsgBus *mbus)
{
- wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
- .notify = ED_region_do_msg_notify_tag_redraw,
- };
-
- /* Timeline depends on scene properties. */
- {
- bool use_preview = (scene->r.flag & SCER_PRV_RANGE);
- extern PropertyRNA rna_Scene_frame_start;
- extern PropertyRNA rna_Scene_frame_end;
- extern PropertyRNA rna_Scene_frame_preview_start;
- extern PropertyRNA rna_Scene_frame_preview_end;
- extern PropertyRNA rna_Scene_use_preview_range;
- extern PropertyRNA rna_Scene_frame_current;
- const PropertyRNA *props[] = {
- use_preview ? &rna_Scene_frame_preview_start : &rna_Scene_frame_start,
- use_preview ? &rna_Scene_frame_preview_end : &rna_Scene_frame_end,
- &rna_Scene_use_preview_range,
- &rna_Scene_frame_current,
- };
-
- PointerRNA idptr;
- RNA_id_pointer_create(&scene->id, &idptr);
-
- for (int i = 0; i < ARRAY_SIZE(props); i++) {
- WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__);
- }
- }
-
- {
- StructRNA *type_array[] = {
- &RNA_SequenceEditor,
-
- &RNA_Sequence,
- /* Members of 'Sequence'. */
- &RNA_SequenceCrop,
- &RNA_SequenceTransform,
- &RNA_SequenceModifier,
- &RNA_SequenceColorBalanceData,
- };
- wmMsgParams_RNA msg_key_params = {{{0}}};
- for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
- msg_key_params.ptr.type = type_array[i];
- WM_msg_subscribe_rna_params(mbus, &msg_key_params, &msg_sub_value_region_tag_redraw, __func__);
- }
- }
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ /* Timeline depends on scene properties. */
+ {
+ bool use_preview = (scene->r.flag & SCER_PRV_RANGE);
+ extern PropertyRNA rna_Scene_frame_start;
+ extern PropertyRNA rna_Scene_frame_end;
+ extern PropertyRNA rna_Scene_frame_preview_start;
+ extern PropertyRNA rna_Scene_frame_preview_end;
+ extern PropertyRNA rna_Scene_use_preview_range;
+ extern PropertyRNA rna_Scene_frame_current;
+ const PropertyRNA *props[] = {
+ use_preview ? &rna_Scene_frame_preview_start : &rna_Scene_frame_start,
+ use_preview ? &rna_Scene_frame_preview_end : &rna_Scene_frame_end,
+ &rna_Scene_use_preview_range,
+ &rna_Scene_frame_current,
+ };
+
+ PointerRNA idptr;
+ RNA_id_pointer_create(&scene->id, &idptr);
+
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__);
+ }
+ }
+
+ {
+ StructRNA *type_array[] = {
+ &RNA_SequenceEditor,
+
+ &RNA_Sequence,
+ /* Members of 'Sequence'. */
+ &RNA_SequenceCrop,
+ &RNA_SequenceTransform,
+ &RNA_SequenceModifier,
+ &RNA_SequenceColorBalanceData,
+ };
+ wmMsgParams_RNA msg_key_params = {{{0}}};
+ for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
+ msg_key_params.ptr.type = type_array[i];
+ WM_msg_subscribe_rna_params(
+ mbus, &msg_key_params, &msg_sub_value_region_tag_redraw, __func__);
+ }
+ }
}
/* *********************** 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)
{
- ED_region_header_init(ar);
+ ED_region_header_init(ar);
}
static void sequencer_header_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_header(C, ar);
+ ED_region_header(C, ar);
}
/* *********************** preview region ************************ */
static void sequencer_preview_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
#if 0
- keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", 0, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", 0, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
#endif
- keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- /* own keymap */
- keymap = WM_keymap_ensure(wm->defaultconf, "SequencerPreview", SPACE_SEQ, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ /* own keymap */
+ keymap = WM_keymap_ensure(wm->defaultconf, "SequencerPreview", SPACE_SEQ, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
static void sequencer_preview_region_draw(const bContext *C, ARegion *ar)
{
- ScrArea *sa = CTX_wm_area(C);
- SpaceSeq *sseq = sa->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));
-
- /* 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 (show_split && sseq->overlay_type != SEQ_DRAW_OVERLAY_CURRENT) {
- int over_cfra;
-
- if (scene->ed->over_flag & SEQ_EDIT_OVERLAY_ABS) {
- over_cfra = scene->ed->over_cfra;
- }
- else {
- over_cfra = scene->r.cfra + scene->ed->over_ofs;
- }
-
- 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);
- }
- }
-
- if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
- rcti rect;
- ED_region_visible_rect(ar, &rect);
- int xoffset = rect.xmin + U.widget_unit;
- int yoffset = rect.ymax;
- ED_scene_draw_fps(scene, xoffset, &yoffset);
- }
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceSeq *sseq = sa->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));
+
+ /* 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 (show_split && sseq->overlay_type != SEQ_DRAW_OVERLAY_CURRENT) {
+ int over_cfra;
+
+ if (scene->ed->over_flag & SEQ_EDIT_OVERLAY_ABS) {
+ over_cfra = scene->ed->over_cfra;
+ }
+ else {
+ over_cfra = scene->r.cfra + scene->ed->over_ofs;
+ }
+
+ 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);
+ }
+ }
+
+ if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
+ rcti rect;
+ ED_region_visible_rect(ar, &rect);
+ int xoffset = rect.xmin + U.widget_unit;
+ int yoffset = rect.ymax;
+ ED_scene_draw_fps(scene, xoffset, &yoffset);
+ }
}
-static void sequencer_preview_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void sequencer_preview_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_GPENCIL:
- if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SCENE:
- switch (wmn->data) {
- case ND_FRAME:
- case ND_MARKERS:
- case ND_SEQUENCER:
- case ND_RENDER_OPTIONS:
- case ND_DRAW_RENDER_VIEWPORT:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_ANIMATION:
- switch (wmn->data) {
- case ND_KEYFRAME:
- /* Otherwise, often prevents seeing immediately effects of keyframe editing... */
- BKE_sequencer_cache_cleanup();
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_SEQUENCER) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_ID:
- switch (wmn->data) {
- case NA_RENAME:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_MASK:
- if (wmn->action == NA_EDITED) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_GPENCIL:
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_FRAME:
+ case ND_MARKERS:
+ case ND_SEQUENCER:
+ case ND_RENDER_OPTIONS:
+ case ND_DRAW_RENDER_VIEWPORT:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_ANIMATION:
+ switch (wmn->data) {
+ case ND_KEYFRAME:
+ /* Otherwise, often prevents seeing immediately effects of keyframe editing... */
+ BKE_sequencer_cache_cleanup();
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_SEQUENCER) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_ID:
+ switch (wmn->data) {
+ case NA_RENAME:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_MASK:
+ if (wmn->action == NA_EDITED) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
}
/* *********************** buttons region ************************ */
@@ -741,64 +754,66 @@ static void sequencer_preview_region_listener(
/* add handlers, stuff you only do once or on area/region changes */
static void sequencer_buttons_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, ar);
}
static void sequencer_buttons_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, ar);
}
-static void sequencer_buttons_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void sequencer_buttons_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_GPENCIL:
- if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SCENE:
- switch (wmn->data) {
- case ND_FRAME:
- case ND_SEQUENCER:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_SEQUENCER) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_ID:
- if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_GPENCIL:
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_FRAME:
+ case ND_SEQUENCER:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_SEQUENCER) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_ID:
+ if (wmn->action == NA_RENAME) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
}
static void sequencer_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
{
- SpaceSeq *sseq = (SpaceSeq *)slink;
+ SpaceSeq *sseq = (SpaceSeq *)slink;
- if (!ELEM(GS(old_id->name), ID_GD)) {
- return;
- }
+ if (!ELEM(GS(old_id->name), ID_GD)) {
+ return;
+ }
- if ((ID *)sseq->gpd == old_id) {
- sseq->gpd = (bGPdata *)new_id;
- id_us_min(old_id);
- id_us_plus(new_id);
- }
+ if ((ID *)sseq->gpd == old_id) {
+ sseq->gpd = (bGPdata *)new_id;
+ id_us_min(old_id);
+ id_us_plus(new_id);
+ }
}
/* ************************************* */
@@ -806,72 +821,72 @@ static void sequencer_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id
/* only called once, from space/spacetypes.c */
void ED_spacetype_sequencer(void)
{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype sequencer");
- ARegionType *art;
-
- st->spaceid = SPACE_SEQ;
- strncpy(st->name, "Sequencer", BKE_ST_MAXNAME);
-
- st->new = sequencer_new;
- st->free = sequencer_free;
- st->init = sequencer_init;
- st->duplicate = sequencer_duplicate;
- st->operatortypes = sequencer_operatortypes;
- st->keymap = sequencer_keymap;
- st->context = sequencer_context;
- st->dropboxes = sequencer_dropboxes;
- st->refresh = sequencer_refresh;
- st->listener = sequencer_listener;
- st->id_remap = sequencer_id_remap;
-
- /* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
- art->regionid = RGN_TYPE_WINDOW;
- art->init = sequencer_main_region_init;
- art->draw = sequencer_main_region_draw;
- art->listener = sequencer_main_region_listener;
- art->message_subscribe = sequencer_main_region_message_subscribe;
- art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_FRAMES | ED_KEYMAP_ANIMATION;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* preview */
- art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
- art->regionid = RGN_TYPE_PREVIEW;
- art->init = sequencer_preview_region_init;
- art->draw = sequencer_preview_region_draw;
- art->listener = sequencer_preview_region_listener;
- art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL;
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: listview/buttons */
- art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
- art->regionid = RGN_TYPE_UI;
- art->prefsizex = 220; // XXX
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
- art->listener = sequencer_buttons_region_listener;
- art->init = sequencer_buttons_region_init;
- art->draw = sequencer_buttons_region_draw;
- BLI_addhead(&st->regiontypes, art);
-
- sequencer_buttons_register(art);
-
- /* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
-
- art->init = sequencer_header_region_init;
- art->draw = sequencer_header_region_draw;
- art->listener = sequencer_main_region_listener;
-
- BLI_addhead(&st->regiontypes, art);
-
- BKE_spacetype_register(st);
-
- /* set the sequencer callback when not in background mode */
- if (G.background == 0) {
- sequencer_view3d_cb = ED_view3d_draw_offscreen_imbuf_simple;
- }
+ SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype sequencer");
+ ARegionType *art;
+
+ st->spaceid = SPACE_SEQ;
+ strncpy(st->name, "Sequencer", BKE_ST_MAXNAME);
+
+ st->new = sequencer_new;
+ st->free = sequencer_free;
+ st->init = sequencer_init;
+ st->duplicate = sequencer_duplicate;
+ st->operatortypes = sequencer_operatortypes;
+ st->keymap = sequencer_keymap;
+ st->context = sequencer_context;
+ st->dropboxes = sequencer_dropboxes;
+ st->refresh = sequencer_refresh;
+ st->listener = sequencer_listener;
+ st->id_remap = sequencer_id_remap;
+
+ /* regions: main window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init = sequencer_main_region_init;
+ art->draw = sequencer_main_region_draw;
+ art->listener = sequencer_main_region_listener;
+ art->message_subscribe = sequencer_main_region_message_subscribe;
+ art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_FRAMES | ED_KEYMAP_ANIMATION;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* preview */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
+ art->regionid = RGN_TYPE_PREVIEW;
+ art->init = sequencer_preview_region_init;
+ art->draw = sequencer_preview_region_draw;
+ art->listener = sequencer_preview_region_listener;
+ art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: listview/buttons */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
+ art->regionid = RGN_TYPE_UI;
+ art->prefsizex = 220; // XXX
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
+ art->listener = sequencer_buttons_region_listener;
+ art->init = sequencer_buttons_region_init;
+ art->draw = sequencer_buttons_region_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ sequencer_buttons_register(art);
+
+ /* regions: header */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = HEADERY;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
+
+ art->init = sequencer_header_region_init;
+ art->draw = sequencer_header_region_draw;
+ art->listener = sequencer_main_region_listener;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
+
+ /* set the sequencer callback when not in background mode */
+ if (G.background == 0) {
+ sequencer_view3d_cb = ED_view3d_draw_offscreen_imbuf_simple;
+ }
}
diff --git a/source/blender/editors/space_statusbar/CMakeLists.txt b/source/blender/editors/space_statusbar/CMakeLists.txt
index 63562621d34..39957c6792c 100644
--- a/source/blender/editors/space_statusbar/CMakeLists.txt
+++ b/source/blender/editors/space_statusbar/CMakeLists.txt
@@ -16,30 +16,30 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blenloader
- ../../blentranslation
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blenloader
+ ../../blentranslation
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- space_statusbar.c
+ space_statusbar.c
)
set(LIB
- bf_blenkernel
- bf_blenlib
+ bf_blenkernel
+ bf_blenlib
)
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/space_statusbar/space_statusbar.c b/source/blender/editors/space_statusbar/space_statusbar.c
index 3c5ccb7e59b..63f27b4d74a 100644
--- a/source/blender/editors/space_statusbar/space_statusbar.c
+++ b/source/blender/editors/space_statusbar/space_statusbar.c
@@ -18,7 +18,6 @@
* \ingroup spstatusbar
*/
-
#include <string.h>
#include <stdio.h>
@@ -41,147 +40,143 @@
#include "WM_types.h"
#include "WM_message.h"
-
/* ******************** default callbacks for statusbar space ******************** */
static SpaceLink *statusbar_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
- SpaceStatusBar *sstatusbar;
+ ARegion *ar;
+ SpaceStatusBar *sstatusbar;
- sstatusbar = MEM_callocN(sizeof(*sstatusbar), "init statusbar");
- sstatusbar->spacetype = SPACE_STATUSBAR;
+ 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;
+ /* 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;
- return (SpaceLink *)sstatusbar;
+ return (SpaceLink *)sstatusbar;
}
/* not spacelink itself */
static void statusbar_free(SpaceLink *UNUSED(sl))
{
-
}
-
/* spacetype; init callback */
static void statusbar_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
{
-
}
static SpaceLink *statusbar_duplicate(SpaceLink *sl)
{
- SpaceStatusBar *sstatusbarn = MEM_dupallocN(sl);
+ SpaceStatusBar *sstatusbarn = MEM_dupallocN(sl);
- /* clear or remove stuff from old */
+ /* clear or remove stuff from old */
- return (SpaceLink *)sstatusbarn;
+ return (SpaceLink *)sstatusbarn;
}
-
-
/* add handlers, stuff you only do once or on area/region changes */
static void statusbar_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
{
- if (ELEM(region->alignment, RGN_ALIGN_RIGHT)) {
- region->flag |= RGN_FLAG_DYNAMIC_SIZE;
- }
- ED_region_header_init(region);
+ if (ELEM(region->alignment, RGN_ALIGN_RIGHT)) {
+ region->flag |= RGN_FLAG_DYNAMIC_SIZE;
+ }
+ ED_region_header_init(region);
}
static void statusbar_operatortypes(void)
{
-
}
static void statusbar_keymap(struct wmKeyConfig *UNUSED(keyconf))
{
-
}
-static void statusbar_header_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void statusbar_header_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_SCREEN:
- if (ELEM(wmn->data, ND_LAYER, ND_ANIMPLAY)) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_WM:
- if (wmn->data == ND_JOB) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SCENE:
- if (wmn->data == ND_RENDER_RESULT) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_INFO) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_ID:
- if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SCREEN:
+ if (ELEM(wmn->data, ND_LAYER, ND_ANIMPLAY)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_WM:
+ if (wmn->data == ND_JOB) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SCENE:
+ if (wmn->data == ND_RENDER_RESULT) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_INFO) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_ID:
+ if (wmn->action == NA_RENAME) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
}
-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,
- struct wmMsgBus *mbus)
+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,
+ struct wmMsgBus *mbus)
{
- wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
- .notify = ED_region_do_msg_notify_tag_redraw,
- };
-
- WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
- WM_msg_subscribe_rna_anon_prop(mbus, ViewLayer, name, &msg_sub_value_region_tag_redraw);
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(mbus, ViewLayer, name, &msg_sub_value_region_tag_redraw);
}
/* only called once, from space/spacetypes.c */
void ED_spacetype_statusbar(void)
{
- SpaceType *st = MEM_callocN(sizeof(*st), "spacetype statusbar");
- ARegionType *art;
-
- st->spaceid = SPACE_STATUSBAR;
- strncpy(st->name, "Status Bar", BKE_ST_MAXNAME);
-
- st->new = statusbar_new;
- st->free = statusbar_free;
- st->init = statusbar_init;
- st->duplicate = statusbar_duplicate;
- st->operatortypes = statusbar_operatortypes;
- st->keymap = statusbar_keymap;
-
- /* regions: header window */
- art = MEM_callocN(sizeof(*art), "spacetype statusbar header region");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = 0.8f * HEADERY;
- art->prefsizex = UI_UNIT_X * 5; /* Mainly to avoid glitches */
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
- art->init = statusbar_header_region_init;
- art->layout = ED_region_header_layout;
- art->draw = ED_region_header_draw;
- art->listener = statusbar_header_region_listener;
- art->message_subscribe = statusbar_header_region_message_subscribe;
- BLI_addhead(&st->regiontypes, art);
-
- BKE_spacetype_register(st);
+ SpaceType *st = MEM_callocN(sizeof(*st), "spacetype statusbar");
+ ARegionType *art;
+
+ st->spaceid = SPACE_STATUSBAR;
+ strncpy(st->name, "Status Bar", BKE_ST_MAXNAME);
+
+ st->new = statusbar_new;
+ st->free = statusbar_free;
+ st->init = statusbar_init;
+ st->duplicate = statusbar_duplicate;
+ st->operatortypes = statusbar_operatortypes;
+ st->keymap = statusbar_keymap;
+
+ /* regions: header window */
+ art = MEM_callocN(sizeof(*art), "spacetype statusbar header region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = 0.8f * HEADERY;
+ art->prefsizex = UI_UNIT_X * 5; /* Mainly to avoid glitches */
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
+ art->init = statusbar_header_region_init;
+ art->layout = ED_region_header_layout;
+ art->draw = ED_region_header_draw;
+ art->listener = statusbar_header_region_listener;
+ art->message_subscribe = statusbar_header_region_message_subscribe;
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_text/CMakeLists.txt b/source/blender/editors/space_text/CMakeLists.txt
index f4054a0dd0e..f5db86ac4c2 100644
--- a/source/blender/editors/space_text/CMakeLists.txt
+++ b/source/blender/editors/space_text/CMakeLists.txt
@@ -16,57 +16,57 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenfont
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenfont
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- space_text.c
- text_autocomplete.c
- text_draw.c
- text_format.c
- text_format_lua.c
- text_format_osl.c
- text_format_pov.c
- text_format_pov_ini.c
- text_format_py.c
- text_header.c
- text_ops.c
- text_undo.c
+ space_text.c
+ text_autocomplete.c
+ text_draw.c
+ text_format.c
+ text_format_lua.c
+ text_format_osl.c
+ text_format_pov.c
+ text_format_pov_ini.c
+ text_format_py.c
+ text_header.c
+ text_ops.c
+ text_undo.c
- text_format.h
- text_intern.h
+ text_format.h
+ text_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
+ bf_blenkernel
+ bf_blenlib
)
add_definitions(${GL_DEFINITIONS})
if(WITH_PYTHON)
- list(APPEND INC
- ../../python
- )
- add_definitions(-DWITH_PYTHON)
+ list(APPEND INC
+ ../../python
+ )
+ add_definitions(-DWITH_PYTHON)
endif()
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
blender_add_lib(bf_editor_space_text "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index 55165e4840f..9232d0322ab 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -21,7 +21,6 @@
* \ingroup sptext
*/
-
#include <string.h>
#include "DNA_text_types.h"
@@ -38,7 +37,6 @@
#include "ED_space_api.h"
#include "ED_screen.h"
-
#include "WM_api.h"
#include "WM_types.h"
@@ -48,217 +46,217 @@
#include "RNA_access.h"
-
#include "text_format.h"
-#include "text_intern.h" /* own include */
+#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;
- SpaceText *stext;
+ ARegion *ar;
+ SpaceText *stext;
- stext = MEM_callocN(sizeof(SpaceText), "inittext");
- stext->spacetype = SPACE_TEXT;
+ stext = MEM_callocN(sizeof(SpaceText), "inittext");
+ stext->spacetype = SPACE_TEXT;
- stext->lheight = 12;
- stext->tabnumber = 4;
- stext->margin_column = 80;
+ stext->lheight = 12;
+ stext->tabnumber = 4;
+ stext->margin_column = 80;
- /* header */
- ar = MEM_callocN(sizeof(ARegion), "header for text");
+ /* header */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_HEADER;
+ ar->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;
+ /* 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;
- /* properties region */
- ar = MEM_callocN(sizeof(ARegion), "properties region for text");
+ /* properties region */
+ ar = MEM_callocN(sizeof(ARegion), "properties region for text");
- BLI_addtail(&stext->regionbase, ar);
- ar->regiontype = RGN_TYPE_UI;
- ar->alignment = RGN_ALIGN_LEFT;
- ar->flag = RGN_FLAG_HIDDEN;
+ BLI_addtail(&stext->regionbase, ar);
+ ar->regiontype = RGN_TYPE_UI;
+ ar->alignment = RGN_ALIGN_LEFT;
+ ar->flag = RGN_FLAG_HIDDEN;
- /* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for text");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for text");
- BLI_addtail(&stext->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&stext->regionbase, ar);
+ ar->regiontype = RGN_TYPE_WINDOW;
- return (SpaceLink *)stext;
+ return (SpaceLink *)stext;
}
/* not spacelink itself */
static void text_free(SpaceLink *sl)
{
- SpaceText *stext = (SpaceText *) sl;
+ SpaceText *stext = (SpaceText *)sl;
- stext->text = NULL;
- text_free_caches(stext);
+ stext->text = NULL;
+ text_free_caches(stext);
}
-
/* spacetype; init callback */
static void text_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
{
-
}
static SpaceLink *text_duplicate(SpaceLink *sl)
{
- SpaceText *stextn = MEM_dupallocN(sl);
+ SpaceText *stextn = MEM_dupallocN(sl);
- /* clear or remove stuff from old */
+ /* clear or remove stuff from old */
- stextn->drawcache = NULL; /* space need it's own cache */
+ stextn->drawcache = NULL; /* space need it's own cache */
- return (SpaceLink *)stextn;
+ return (SpaceLink *)stextn;
}
-static void text_listener(wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene))
+static void text_listener(wmWindow *UNUSED(win),
+ ScrArea *sa,
+ wmNotifier *wmn,
+ Scene *UNUSED(scene))
{
- SpaceText *st = sa->spacedata.first;
-
- /* context changes */
- switch (wmn->category) {
- case NC_TEXT:
- /* check if active text was changed, no need to redraw if text isn't active
- * (reference == NULL) means text was unlinked, should update anyway for this
- * case -- no way to know was text active before unlinking or not */
- if (wmn->reference && wmn->reference != st->text)
- break;
-
- switch (wmn->data) {
- case ND_DISPLAY:
- ED_area_tag_redraw(sa);
- break;
- case ND_CURSOR:
- if (st->text && st->text == wmn->reference)
- text_scroll_to_cursor__area(st, sa, true);
-
- ED_area_tag_redraw(sa);
- break;
- }
-
- switch (wmn->action) {
- case NA_EDITED:
- if (st->text) {
- text_drawcache_tag_update(st, 1);
- text_update_edited(st->text);
- }
-
- ED_area_tag_redraw(sa);
- ATTR_FALLTHROUGH; /* fall down to tag redraw */
- case NA_ADDED:
- case NA_REMOVED:
- ED_area_tag_redraw(sa);
- break;
- case NA_SELECTED:
- if (st->text && st->text == wmn->reference)
- text_scroll_to_cursor__area(st, sa, true);
-
- break;
- }
-
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_TEXT)
- ED_area_tag_redraw(sa);
- break;
- }
+ SpaceText *st = sa->spacedata.first;
+
+ /* context changes */
+ switch (wmn->category) {
+ case NC_TEXT:
+ /* check if active text was changed, no need to redraw if text isn't active
+ * (reference == NULL) means text was unlinked, should update anyway for this
+ * case -- no way to know was text active before unlinking or not */
+ if (wmn->reference && wmn->reference != st->text)
+ break;
+
+ switch (wmn->data) {
+ case ND_DISPLAY:
+ ED_area_tag_redraw(sa);
+ break;
+ case ND_CURSOR:
+ if (st->text && st->text == wmn->reference)
+ text_scroll_to_cursor__area(st, sa, true);
+
+ ED_area_tag_redraw(sa);
+ break;
+ }
+
+ switch (wmn->action) {
+ case NA_EDITED:
+ if (st->text) {
+ text_drawcache_tag_update(st, 1);
+ text_update_edited(st->text);
+ }
+
+ ED_area_tag_redraw(sa);
+ ATTR_FALLTHROUGH; /* fall down to tag redraw */
+ case NA_ADDED:
+ case NA_REMOVED:
+ ED_area_tag_redraw(sa);
+ break;
+ case NA_SELECTED:
+ if (st->text && st->text == wmn->reference)
+ text_scroll_to_cursor__area(st, sa, true);
+
+ break;
+ }
+
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_TEXT)
+ ED_area_tag_redraw(sa);
+ break;
+ }
}
static void text_operatortypes(void)
{
- WM_operatortype_append(TEXT_OT_new);
- WM_operatortype_append(TEXT_OT_open);
- WM_operatortype_append(TEXT_OT_reload);
- WM_operatortype_append(TEXT_OT_unlink);
- WM_operatortype_append(TEXT_OT_save);
- WM_operatortype_append(TEXT_OT_save_as);
- WM_operatortype_append(TEXT_OT_make_internal);
- WM_operatortype_append(TEXT_OT_run_script);
- WM_operatortype_append(TEXT_OT_refresh_pyconstraints);
-
- WM_operatortype_append(TEXT_OT_paste);
- WM_operatortype_append(TEXT_OT_copy);
- WM_operatortype_append(TEXT_OT_cut);
- WM_operatortype_append(TEXT_OT_duplicate_line);
-
- WM_operatortype_append(TEXT_OT_convert_whitespace);
- WM_operatortype_append(TEXT_OT_uncomment);
- WM_operatortype_append(TEXT_OT_comment);
- WM_operatortype_append(TEXT_OT_unindent);
- WM_operatortype_append(TEXT_OT_indent);
-
- WM_operatortype_append(TEXT_OT_select_line);
- WM_operatortype_append(TEXT_OT_select_all);
- WM_operatortype_append(TEXT_OT_select_word);
-
- WM_operatortype_append(TEXT_OT_move_lines);
-
- WM_operatortype_append(TEXT_OT_jump);
- WM_operatortype_append(TEXT_OT_move);
- WM_operatortype_append(TEXT_OT_move_select);
- WM_operatortype_append(TEXT_OT_delete);
- WM_operatortype_append(TEXT_OT_overwrite_toggle);
-
- WM_operatortype_append(TEXT_OT_selection_set);
- WM_operatortype_append(TEXT_OT_cursor_set);
- WM_operatortype_append(TEXT_OT_scroll);
- WM_operatortype_append(TEXT_OT_scroll_bar);
- WM_operatortype_append(TEXT_OT_line_number);
-
- WM_operatortype_append(TEXT_OT_line_break);
- WM_operatortype_append(TEXT_OT_insert);
-
- WM_operatortype_append(TEXT_OT_properties);
-
- WM_operatortype_append(TEXT_OT_find);
- WM_operatortype_append(TEXT_OT_find_set_selected);
- WM_operatortype_append(TEXT_OT_replace);
- WM_operatortype_append(TEXT_OT_replace_set_selected);
-
- WM_operatortype_append(TEXT_OT_start_find);
-
- WM_operatortype_append(TEXT_OT_to_3d_object);
-
- WM_operatortype_append(TEXT_OT_resolve_conflict);
-
- WM_operatortype_append(TEXT_OT_autocomplete);
+ WM_operatortype_append(TEXT_OT_new);
+ WM_operatortype_append(TEXT_OT_open);
+ WM_operatortype_append(TEXT_OT_reload);
+ WM_operatortype_append(TEXT_OT_unlink);
+ WM_operatortype_append(TEXT_OT_save);
+ WM_operatortype_append(TEXT_OT_save_as);
+ WM_operatortype_append(TEXT_OT_make_internal);
+ WM_operatortype_append(TEXT_OT_run_script);
+ WM_operatortype_append(TEXT_OT_refresh_pyconstraints);
+
+ WM_operatortype_append(TEXT_OT_paste);
+ WM_operatortype_append(TEXT_OT_copy);
+ WM_operatortype_append(TEXT_OT_cut);
+ WM_operatortype_append(TEXT_OT_duplicate_line);
+
+ WM_operatortype_append(TEXT_OT_convert_whitespace);
+ WM_operatortype_append(TEXT_OT_uncomment);
+ WM_operatortype_append(TEXT_OT_comment);
+ WM_operatortype_append(TEXT_OT_unindent);
+ WM_operatortype_append(TEXT_OT_indent);
+
+ WM_operatortype_append(TEXT_OT_select_line);
+ WM_operatortype_append(TEXT_OT_select_all);
+ WM_operatortype_append(TEXT_OT_select_word);
+
+ WM_operatortype_append(TEXT_OT_move_lines);
+
+ WM_operatortype_append(TEXT_OT_jump);
+ WM_operatortype_append(TEXT_OT_move);
+ WM_operatortype_append(TEXT_OT_move_select);
+ WM_operatortype_append(TEXT_OT_delete);
+ WM_operatortype_append(TEXT_OT_overwrite_toggle);
+
+ WM_operatortype_append(TEXT_OT_selection_set);
+ WM_operatortype_append(TEXT_OT_cursor_set);
+ WM_operatortype_append(TEXT_OT_scroll);
+ WM_operatortype_append(TEXT_OT_scroll_bar);
+ WM_operatortype_append(TEXT_OT_line_number);
+
+ WM_operatortype_append(TEXT_OT_line_break);
+ WM_operatortype_append(TEXT_OT_insert);
+
+ WM_operatortype_append(TEXT_OT_properties);
+
+ WM_operatortype_append(TEXT_OT_find);
+ WM_operatortype_append(TEXT_OT_find_set_selected);
+ WM_operatortype_append(TEXT_OT_replace);
+ WM_operatortype_append(TEXT_OT_replace_set_selected);
+
+ WM_operatortype_append(TEXT_OT_start_find);
+
+ WM_operatortype_append(TEXT_OT_to_3d_object);
+
+ WM_operatortype_append(TEXT_OT_resolve_conflict);
+
+ WM_operatortype_append(TEXT_OT_autocomplete);
}
static void text_keymap(struct wmKeyConfig *keyconf)
{
- WM_keymap_ensure(keyconf, "Text Generic", SPACE_TEXT, 0);
- WM_keymap_ensure(keyconf, "Text", SPACE_TEXT, 0);
+ WM_keymap_ensure(keyconf, "Text Generic", SPACE_TEXT, 0);
+ WM_keymap_ensure(keyconf, "Text", SPACE_TEXT, 0);
}
const char *text_context_dir[] = {"edit_text", NULL};
static int text_context(const bContext *C, const char *member, bContextDataResult *result)
{
- SpaceText *st = CTX_wm_space_text(C);
-
- if (CTX_data_dir(member)) {
- CTX_data_dir_set(result, text_context_dir);
- return 1;
- }
- else if (CTX_data_equals(member, "edit_text")) {
- CTX_data_id_pointer_set(result, &st->text->id);
- return 1;
- }
-
- return 0;
+ SpaceText *st = CTX_wm_space_text(C);
+
+ if (CTX_data_dir(member)) {
+ CTX_data_dir_set(result, text_context_dir);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "edit_text")) {
+ CTX_data_id_pointer_set(result, &st->text->id);
+ return 1;
+ }
+
+ return 0;
}
/********************* main region ********************/
@@ -266,116 +264,120 @@ static int text_context(const bContext *C, const char *member, bContextDataResul
/* add handlers, stuff you only do once or on area/region changes */
static void text_main_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
- ListBase *lb;
+ wmKeyMap *keymap;
+ ListBase *lb;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
- /* own keymap */
- keymap = WM_keymap_ensure(wm->defaultconf, "Text Generic", SPACE_TEXT, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- keymap = WM_keymap_ensure(wm->defaultconf, "Text", SPACE_TEXT, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ /* own keymap */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Text Generic", SPACE_TEXT, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Text", SPACE_TEXT, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
- /* add drop boxes */
- lb = WM_dropboxmap_find("Text", SPACE_TEXT, RGN_TYPE_WINDOW);
+ /* 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(&ar->handlers, lb);
}
static void text_main_region_draw(const bContext *C, ARegion *ar)
{
- /* draw entirely, view changes should be handled here */
- SpaceText *st = CTX_wm_space_text(C);
- //View2D *v2d = &ar->v2d;
+ /* draw entirely, view changes should be handled here */
+ SpaceText *st = CTX_wm_space_text(C);
+ //View2D *v2d = &ar->v2d;
- /* clear and setup matrix */
- UI_ThemeClearColor(TH_BACK);
- GPU_clear(GPU_COLOR_BIT);
+ /* clear and setup matrix */
+ UI_ThemeClearColor(TH_BACK);
+ GPU_clear(GPU_COLOR_BIT);
- // UI_view2d_view_ortho(v2d);
+ // UI_view2d_view_ortho(v2d);
- /* data... */
- draw_text_main(st, ar);
+ /* data... */
+ draw_text_main(st, ar);
- /* reset view matrix */
- // UI_view2d_view_restore(C);
+ /* reset view matrix */
+ // UI_view2d_view_restore(C);
- /* scrollers? */
+ /* scrollers? */
}
static void text_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
{
- SpaceText *st = sa->spacedata.first;
- int wmcursor = BC_TEXTEDITCURSOR;
+ SpaceText *st = sa->spacedata.first;
+ int wmcursor = BC_TEXTEDITCURSOR;
- if (st->text && BLI_rcti_isect_pt(&st->txtbar, win->eventstate->x - ar->winrct.xmin, st->txtbar.ymin)) {
- wmcursor = CURSOR_STD;
- }
+ if (st->text &&
+ BLI_rcti_isect_pt(&st->txtbar, win->eventstate->x - ar->winrct.xmin, st->txtbar.ymin)) {
+ wmcursor = CURSOR_STD;
+ }
- WM_cursor_set(win, wmcursor);
+ WM_cursor_set(win, wmcursor);
}
-
-
/* ************* dropboxes ************* */
-static bool text_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
+static bool text_drop_poll(bContext *UNUSED(C),
+ wmDrag *drag,
+ const wmEvent *UNUSED(event),
+ const char **UNUSED(tooltip))
{
- if (drag->type == WM_DRAG_PATH) {
- /* rule might not work? */
- if (ELEM(drag->icon, ICON_FILE_SCRIPT, ICON_FILE_TEXT, ICON_FILE_BLANK)) {
- return true;
- }
- }
- return false;
+ if (drag->type == WM_DRAG_PATH) {
+ /* rule might not work? */
+ if (ELEM(drag->icon, ICON_FILE_SCRIPT, ICON_FILE_TEXT, ICON_FILE_BLANK)) {
+ return true;
+ }
+ }
+ return false;
}
static void text_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- /* copy drag path to properties */
- RNA_string_set(drop->ptr, "filepath", drag->path);
+ /* copy drag path to properties */
+ RNA_string_set(drop->ptr, "filepath", drag->path);
}
-static bool text_drop_paste_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
+static bool text_drop_paste_poll(bContext *UNUSED(C),
+ wmDrag *drag,
+ const wmEvent *UNUSED(event),
+ const char **UNUSED(tooltip))
{
- return (drag->type == WM_DRAG_ID);
+ return (drag->type == WM_DRAG_ID);
}
static void text_drop_paste(wmDrag *drag, wmDropBox *drop)
{
- char *text;
- ID *id = WM_drag_ID(drag, 0);
+ char *text;
+ ID *id = WM_drag_ID(drag, 0);
- /* copy drag path to properties */
- text = RNA_path_full_ID_py(id);
- RNA_string_set(drop->ptr, "text", text);
- MEM_freeN(text);
+ /* copy drag path to properties */
+ text = RNA_path_full_ID_py(id);
+ RNA_string_set(drop->ptr, "text", text);
+ MEM_freeN(text);
}
/* this region dropbox definition */
static void text_dropboxes(void)
{
- ListBase *lb = WM_dropboxmap_find("Text", SPACE_TEXT, RGN_TYPE_WINDOW);
+ ListBase *lb = WM_dropboxmap_find("Text", SPACE_TEXT, RGN_TYPE_WINDOW);
- WM_dropbox_add(lb, "TEXT_OT_open", text_drop_poll, text_drop_copy);
- WM_dropbox_add(lb, "TEXT_OT_insert", text_drop_paste_poll, text_drop_paste);
+ WM_dropbox_add(lb, "TEXT_OT_open", text_drop_poll, text_drop_copy);
+ WM_dropbox_add(lb, "TEXT_OT_insert", text_drop_paste_poll, text_drop_paste);
}
/* ************* end drop *********** */
-
/****************** 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)
{
- ED_region_header_init(ar);
+ ED_region_header_init(ar);
}
static void text_header_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_header(C, ar);
+ ED_region_header(C, ar);
}
/****************** properties region ******************/
@@ -383,46 +385,45 @@ static void text_header_region_draw(const bContext *C, ARegion *ar)
/* add handlers, stuff you only do once or on area/region changes */
static void text_properties_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
-
- ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
- ED_region_panels_init(wm, ar);
+ wmKeyMap *keymap;
- /* own keymaps */
- keymap = WM_keymap_ensure(wm->defaultconf, "Text Generic", SPACE_TEXT, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
+ ED_region_panels_init(wm, ar);
+ /* own keymaps */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Text Generic", SPACE_TEXT, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
static void text_properties_region_draw(const bContext *C, ARegion *ar)
{
- SpaceText *st = CTX_wm_space_text(C);
-
- ED_region_panels(C, ar);
-
- /* 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 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);
- }
- st->flags &= ~ST_FIND_ACTIVATE;
- }
+ SpaceText *st = CTX_wm_space_text(C);
+
+ ED_region_panels(C, ar);
+
+ /* 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 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);
+ }
+ st->flags &= ~ST_FIND_ACTIVATE;
+ }
}
static void text_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
{
- SpaceText *stext = (SpaceText *)slink;
+ SpaceText *stext = (SpaceText *)slink;
- if (!ELEM(GS(old_id->name), ID_TXT)) {
- return;
- }
+ if (!ELEM(GS(old_id->name), ID_TXT)) {
+ return;
+ }
- if ((ID *)stext->text == old_id) {
- stext->text = (Text *)new_id;
- id_us_ensure_real(new_id);
- }
+ if ((ID *)stext->text == old_id) {
+ stext->text = (Text *)new_id;
+ id_us_ensure_real(new_id);
+ }
}
/********************* registration ********************/
@@ -430,68 +431,68 @@ static void text_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID
/* only called once, from space/spacetypes.c */
void ED_spacetype_text(void)
{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype text");
- ARegionType *art;
-
- st->spaceid = SPACE_TEXT;
- strncpy(st->name, "Text", BKE_ST_MAXNAME);
-
- st->new = text_new;
- st->free = text_free;
- st->init = text_init;
- st->duplicate = text_duplicate;
- st->operatortypes = text_operatortypes;
- st->keymap = text_keymap;
- st->listener = text_listener;
- st->context = text_context;
- st->dropboxes = text_dropboxes;
- st->id_remap = text_id_remap;
-
- /* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype text region");
- art->regionid = RGN_TYPE_WINDOW;
- art->init = text_main_region_init;
- art->draw = text_main_region_draw;
- art->cursor = text_cursor;
- art->event_cursor = true;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: properties */
- art = MEM_callocN(sizeof(ARegionType), "spacetype text region");
- art->regionid = RGN_TYPE_UI;
- art->prefsizex = UI_COMPACT_PANEL_WIDTH;
- art->keymapflag = ED_KEYMAP_UI;
-
- art->init = text_properties_region_init;
- art->draw = text_properties_region_draw;
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype text region");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
-
- art->init = text_header_region_init;
- art->draw = text_header_region_draw;
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: footer */
- art = MEM_callocN(sizeof(ARegionType), "spacetype text region");
- art->regionid = RGN_TYPE_FOOTER;
- art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FOOTER;
- art->init = text_header_region_init;
- art->draw = text_header_region_draw;
- BLI_addhead(&st->regiontypes, art);
-
- BKE_spacetype_register(st);
-
- /* register formatters */
- ED_text_format_register_py();
- ED_text_format_register_osl();
- ED_text_format_register_lua();
- ED_text_format_register_pov();
- ED_text_format_register_pov_ini();
+ SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype text");
+ ARegionType *art;
+
+ st->spaceid = SPACE_TEXT;
+ strncpy(st->name, "Text", BKE_ST_MAXNAME);
+
+ st->new = text_new;
+ st->free = text_free;
+ st->init = text_init;
+ st->duplicate = text_duplicate;
+ st->operatortypes = text_operatortypes;
+ st->keymap = text_keymap;
+ st->listener = text_listener;
+ st->context = text_context;
+ st->dropboxes = text_dropboxes;
+ st->id_remap = text_id_remap;
+
+ /* regions: main window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype text region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init = text_main_region_init;
+ art->draw = text_main_region_draw;
+ art->cursor = text_cursor;
+ art->event_cursor = true;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: properties */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype text region");
+ art->regionid = RGN_TYPE_UI;
+ art->prefsizex = UI_COMPACT_PANEL_WIDTH;
+ art->keymapflag = ED_KEYMAP_UI;
+
+ art->init = text_properties_region_init;
+ art->draw = text_properties_region_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype text region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = HEADERY;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
+
+ art->init = text_header_region_init;
+ art->draw = text_header_region_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: footer */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype text region");
+ art->regionid = RGN_TYPE_FOOTER;
+ art->prefsizey = HEADERY;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FOOTER;
+ art->init = text_header_region_init;
+ art->draw = text_header_region_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
+
+ /* register formatters */
+ ED_text_format_register_py();
+ ED_text_format_register_osl();
+ ED_text_format_register_lua();
+ ED_text_format_register_pov();
+ ED_text_format_register_pov_ini();
}
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
index 65fb91893f3..10303aeba7c 100644
--- a/source/blender/editors/space_text/text_autocomplete.c
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -43,85 +43,90 @@
#include "UI_interface.h"
#include "text_format.h"
-#include "text_intern.h" /* own include */
-
+#include "text_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/* Public API */
int text_do_suggest_select(SpaceText *st, ARegion *ar)
{
- SuggItem *item, *first, *last /* , *sel */ /* UNUSED */;
- TextLine *tmp;
- int l, x, y, w, h, i;
- int tgti, *top;
- int mval[2] = {0, 0};
-
- if (!st || !st->text) return 0;
- if (!texttool_text_is_active(st->text)) return 0;
-
- first = texttool_suggest_first();
- last = texttool_suggest_last();
- /* sel = texttool_suggest_selected(); */ /* UNUSED */
- top = texttool_suggest_top();
-
- if (!last || !first)
- return 0;
-
- /* Count the visible lines to the cursor */
- for (tmp = st->text->curl, l = -st->top; tmp; tmp = tmp->prev, l++) ;
- if (l < 0) return 0;
-
- text_update_character_width(st);
-
- if (st->showlinenrs) {
- x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET + TEXTXLOC - 4;
- }
- else {
- x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET - 4;
- }
- y = ar->winy - st->lheight_dpi * l - 2;
-
- w = SUGG_LIST_WIDTH * st->cwidth + U.widget_unit;
- h = SUGG_LIST_SIZE * st->lheight_dpi + 0.4f * U.widget_unit;
-
- // XXX getmouseco_areawin(mval);
-
- if (mval[0] < x || x + w < mval[0] || mval[1] < y - h || y < mval[1])
- return 0;
-
- /* Work out which of the items is at the top of the visible list */
- for (i = 0, item = first; i < *top && item->next; i++, item = item->next) ;
-
- /* Work out the target item index in the visible list */
- tgti = (y - mval[1] - 4) / st->lheight_dpi;
- if (tgti < 0 || tgti > SUGG_LIST_SIZE)
- return 1;
-
- for (i = tgti; i > 0 && item->next; i--, item = item->next) ;
- if (item)
- texttool_suggest_select(item);
- return 1;
+ SuggItem *item, *first, *last /* , *sel */ /* UNUSED */;
+ TextLine *tmp;
+ int l, x, y, w, h, i;
+ int tgti, *top;
+ int mval[2] = {0, 0};
+
+ if (!st || !st->text)
+ return 0;
+ if (!texttool_text_is_active(st->text))
+ return 0;
+
+ first = texttool_suggest_first();
+ last = texttool_suggest_last();
+ /* sel = texttool_suggest_selected(); */ /* UNUSED */
+ top = texttool_suggest_top();
+
+ if (!last || !first)
+ return 0;
+
+ /* Count the visible lines to the cursor */
+ for (tmp = st->text->curl, l = -st->top; tmp; tmp = tmp->prev, l++)
+ ;
+ if (l < 0)
+ return 0;
+
+ text_update_character_width(st);
+
+ if (st->showlinenrs) {
+ x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET + TEXTXLOC - 4;
+ }
+ else {
+ x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET - 4;
+ }
+ y = ar->winy - st->lheight_dpi * l - 2;
+
+ w = SUGG_LIST_WIDTH * st->cwidth + U.widget_unit;
+ h = SUGG_LIST_SIZE * st->lheight_dpi + 0.4f * U.widget_unit;
+
+ // XXX getmouseco_areawin(mval);
+
+ if (mval[0] < x || x + w < mval[0] || mval[1] < y - h || y < mval[1])
+ return 0;
+
+ /* Work out which of the items is at the top of the visible list */
+ for (i = 0, item = first; i < *top && item->next; i++, item = item->next)
+ ;
+
+ /* Work out the target item index in the visible list */
+ tgti = (y - mval[1] - 4) / st->lheight_dpi;
+ if (tgti < 0 || tgti > SUGG_LIST_SIZE)
+ return 1;
+
+ for (i = tgti; i > 0 && item->next; i--, item = item->next)
+ ;
+ if (item)
+ texttool_suggest_select(item);
+ return 1;
}
void text_pop_suggest_list(void)
{
- SuggItem *item, *sel;
- int *top, i;
-
- item = texttool_suggest_first();
- sel = texttool_suggest_selected();
- top = texttool_suggest_top();
-
- i = 0;
- while (item && item != sel) {
- item = item->next;
- i++;
- }
- if (i > *top + SUGG_LIST_SIZE - 1)
- *top = i - SUGG_LIST_SIZE + 1;
- else if (i < *top)
- *top = i;
+ SuggItem *item, *sel;
+ int *top, i;
+
+ item = texttool_suggest_first();
+ sel = texttool_suggest_selected();
+ top = texttool_suggest_top();
+
+ i = 0;
+ while (item && item != sel) {
+ item = item->next;
+ i++;
+ }
+ if (i > *top + SUGG_LIST_SIZE - 1)
+ *top = i - SUGG_LIST_SIZE + 1;
+ else if (i < *top)
+ *top = i;
}
/* -------------------------------------------------------------------- */
@@ -131,469 +136,475 @@ static void text_autocomplete_free(bContext *C, wmOperator *op);
static GHash *text_autocomplete_build(Text *text)
{
- GHash *gh;
- int seek_len = 0;
- const char *seek;
- texttool_text_clear();
-
- texttool_text_set_active(text);
-
- /* first get the word we're at */
- {
- const int i = text_find_identifier_start(text->curl->line, text->curc);
- seek_len = text->curc - i;
- seek = text->curl->line + i;
-
- // BLI_strncpy(seek, seek_ptr, seek_len);
- }
-
- /* now walk over entire doc and suggest words */
- {
- TextLine *linep;
-
- gh = BLI_ghash_str_new(__func__);
-
- for (linep = text->lines.first; linep; linep = linep->next) {
- size_t i_start = 0;
- size_t i_end = 0;
- size_t i_pos = 0;
-
- while (i_start < linep->len) {
- /* seek identifier beginning */
- i_pos = i_start;
- while ((i_start < linep->len) &&
- (!text_check_identifier_nodigit_unicode(BLI_str_utf8_as_unicode_and_size_safe(&linep->line[i_start], &i_pos))))
- {
- i_start = i_pos;
- }
- i_pos = i_end = i_start;
- while ((i_end < linep->len) &&
- (text_check_identifier_unicode(BLI_str_utf8_as_unicode_and_size_safe(&linep->line[i_end], &i_pos))))
- {
- i_end = i_pos;
- }
-
- if ((i_start != i_end) &&
- /* check we're at the beginning of a line or that the previous char is not an identifier
- * this prevents digits from being added */
- ((i_start < 1) || !text_check_identifier_unicode(BLI_str_utf8_as_unicode(&linep->line[i_start - 1]))))
- {
- char *str_sub = &linep->line[i_start];
- const int choice_len = i_end - i_start;
-
- if ((choice_len > seek_len) &&
- (seek_len == 0 || STREQLEN(seek, str_sub, seek_len)) &&
- (seek != str_sub))
- {
- // printf("Adding: %s\n", s);
- char str_sub_last = str_sub[choice_len];
- str_sub[choice_len] = '\0';
- if (!BLI_ghash_lookup(gh, str_sub)) {
- char *str_dup = BLI_strdupn(str_sub, choice_len);
- /* A 'set' would make more sense here */
- BLI_ghash_insert(gh, str_dup, str_dup);
- }
- str_sub[choice_len] = str_sub_last;
- }
- }
- if (i_end != i_start) {
- i_start = i_end;
- }
- else {
- /* highly unlikely, but prevent eternal loop */
- i_start++;
- }
- }
- }
-
- {
- GHashIterator gh_iter;
-
- /* get the formatter for highlighting */
- TextFormatType *tft;
- tft = ED_text_format_get(text);
-
- GHASH_ITER (gh_iter, gh) {
- const char *s = BLI_ghashIterator_getValue(&gh_iter);
- texttool_suggest_add(s, tft->format_identifier(s));
- }
- }
- }
-
- texttool_suggest_prefix(seek, seek_len);
-
- return gh;
+ GHash *gh;
+ int seek_len = 0;
+ const char *seek;
+ texttool_text_clear();
+
+ texttool_text_set_active(text);
+
+ /* first get the word we're at */
+ {
+ const int i = text_find_identifier_start(text->curl->line, text->curc);
+ seek_len = text->curc - i;
+ seek = text->curl->line + i;
+
+ // BLI_strncpy(seek, seek_ptr, seek_len);
+ }
+
+ /* now walk over entire doc and suggest words */
+ {
+ TextLine *linep;
+
+ gh = BLI_ghash_str_new(__func__);
+
+ for (linep = text->lines.first; linep; linep = linep->next) {
+ size_t i_start = 0;
+ size_t i_end = 0;
+ size_t i_pos = 0;
+
+ while (i_start < linep->len) {
+ /* seek identifier beginning */
+ i_pos = i_start;
+ while ((i_start < linep->len) &&
+ (!text_check_identifier_nodigit_unicode(
+ BLI_str_utf8_as_unicode_and_size_safe(&linep->line[i_start], &i_pos)))) {
+ i_start = i_pos;
+ }
+ i_pos = i_end = i_start;
+ while ((i_end < linep->len) &&
+ (text_check_identifier_unicode(
+ BLI_str_utf8_as_unicode_and_size_safe(&linep->line[i_end], &i_pos)))) {
+ i_end = i_pos;
+ }
+
+ if ((i_start != i_end) &&
+ /* check we're at the beginning of a line or that the previous char is not an identifier
+ * this prevents digits from being added */
+ ((i_start < 1) ||
+ !text_check_identifier_unicode(BLI_str_utf8_as_unicode(&linep->line[i_start - 1])))) {
+ char *str_sub = &linep->line[i_start];
+ const int choice_len = i_end - i_start;
+
+ if ((choice_len > seek_len) && (seek_len == 0 || STREQLEN(seek, str_sub, seek_len)) &&
+ (seek != str_sub)) {
+ // printf("Adding: %s\n", s);
+ char str_sub_last = str_sub[choice_len];
+ str_sub[choice_len] = '\0';
+ if (!BLI_ghash_lookup(gh, str_sub)) {
+ char *str_dup = BLI_strdupn(str_sub, choice_len);
+ /* A 'set' would make more sense here */
+ BLI_ghash_insert(gh, str_dup, str_dup);
+ }
+ str_sub[choice_len] = str_sub_last;
+ }
+ }
+ if (i_end != i_start) {
+ i_start = i_end;
+ }
+ else {
+ /* highly unlikely, but prevent eternal loop */
+ i_start++;
+ }
+ }
+ }
+
+ {
+ GHashIterator gh_iter;
+
+ /* get the formatter for highlighting */
+ TextFormatType *tft;
+ tft = ED_text_format_get(text);
+
+ GHASH_ITER (gh_iter, gh) {
+ const char *s = BLI_ghashIterator_getValue(&gh_iter);
+ texttool_suggest_add(s, tft->format_identifier(s));
+ }
+ }
+ }
+
+ texttool_suggest_prefix(seek, seek_len);
+
+ return gh;
}
/* -- */
static void get_suggest_prefix(Text *text, int offset)
{
- int i, len;
- const char *line;
-
- if (!text) return;
- if (!texttool_text_is_active(text)) return;
-
- line = text->curl->line;
- i = text_find_identifier_start(line, text->curc + offset);
- len = text->curc - i + offset;
- texttool_suggest_prefix(line + i, len);
+ int i, len;
+ const char *line;
+
+ if (!text)
+ return;
+ if (!texttool_text_is_active(text))
+ return;
+
+ line = text->curl->line;
+ i = text_find_identifier_start(line, text->curc + offset);
+ len = text->curc - i + offset;
+ texttool_suggest_prefix(line + i, len);
}
static void confirm_suggestion(Text *text, TextUndoBuf *utxt)
{
- SuggItem *sel;
- int i, over = 0;
- const char *line;
+ SuggItem *sel;
+ int i, over = 0;
+ const char *line;
- if (!text) return;
- if (!texttool_text_is_active(text)) return;
+ if (!text)
+ return;
+ if (!texttool_text_is_active(text))
+ return;
- sel = texttool_suggest_selected();
- if (!sel) return;
+ sel = texttool_suggest_selected();
+ if (!sel)
+ return;
- line = text->curl->line;
- i = text_find_identifier_start(line, text->curc /* - skipleft */);
- over = text->curc - i;
+ line = text->curl->line;
+ i = text_find_identifier_start(line, text->curc /* - skipleft */);
+ over = text->curc - i;
-// for (i = 0; i < skipleft; i++)
-// txt_move_left(text, 0);
- BLI_assert(memcmp(sel->name, &line[i], over) == 0);
- txt_insert_buf(text, utxt, sel->name + over);
+ // for (i = 0; i < skipleft; i++)
+ // txt_move_left(text, 0);
+ BLI_assert(memcmp(sel->name, &line[i], over) == 0);
+ txt_insert_buf(text, utxt, sel->name + over);
-// for (i = 0; i < skipleft; i++)
-// txt_move_right(text, 0);
+ // for (i = 0; i < skipleft; i++)
+ // txt_move_right(text, 0);
- texttool_text_clear();
+ texttool_text_clear();
}
/* -- */
-
static int text_autocomplete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- SpaceText *st = CTX_wm_space_text(C);
- Text *text = CTX_data_edit_text(C);
-
- st->doplugins = true;
- op->customdata = text_autocomplete_build(text);
-
- if (texttool_suggest_first()) {
-
- ED_area_tag_redraw(CTX_wm_area(C));
-
- if (texttool_suggest_first() == texttool_suggest_last()) {
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- confirm_suggestion(st->text, utxt);
- text_update_line_edited(st->text->curl);
- text_autocomplete_free(C, op);
- ED_undo_push(C, op->type->name);
- return OPERATOR_FINISHED;
- }
- else {
- WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
- }
- }
- else {
- text_autocomplete_free(C, op);
- return OPERATOR_CANCELLED;
- }
+ SpaceText *st = CTX_wm_space_text(C);
+ Text *text = CTX_data_edit_text(C);
+
+ st->doplugins = true;
+ op->customdata = text_autocomplete_build(text);
+
+ if (texttool_suggest_first()) {
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ if (texttool_suggest_first() == texttool_suggest_last()) {
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ confirm_suggestion(st->text, utxt);
+ text_update_line_edited(st->text->curl);
+ text_autocomplete_free(C, op);
+ ED_undo_push(C, op->type->name);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+ else {
+ text_autocomplete_free(C, op);
+ return OPERATOR_CANCELLED;
+ }
}
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);
-
- int draw = 0, tools = 0, swallow = 0, scroll = 1;
- Text *text = CTX_data_edit_text(C);
- int retval = OPERATOR_RUNNING_MODAL;
-
- (void)text;
-
- if (st->doplugins && texttool_text_is_active(st->text)) {
- if (texttool_suggest_first()) tools |= TOOL_SUGG_LIST;
- if (texttool_docs_get()) tools |= TOOL_DOCUMENT;
- }
-
- switch (event->type) {
- case LEFTMOUSE:
- if (event->val == KM_PRESS) {
- if (text_do_suggest_select(st, ar))
- swallow = 1;
- else {
- if (tools & TOOL_SUGG_LIST) {
- texttool_suggest_clear();
- }
- if (tools & TOOL_DOCUMENT) {
- texttool_docs_clear();
- doc_scroll = 0;
- }
- retval = OPERATOR_FINISHED;
- }
- draw = 1;
- }
- break;
- case MIDDLEMOUSE:
- if (event->val == KM_PRESS) {
- if (text_do_suggest_select(st, ar)) {
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- confirm_suggestion(st->text, utxt);
- text_update_line_edited(st->text->curl);
- ED_undo_push(C, op->type->name);
- swallow = 1;
- }
- else {
- if (tools & TOOL_SUGG_LIST) {
- texttool_suggest_clear();
- }
- if (tools & TOOL_DOCUMENT) {
- texttool_docs_clear();
- doc_scroll = 0;
- }
- retval = OPERATOR_FINISHED;
- }
- draw = 1;
- }
- break;
- case ESCKEY:
- if (event->val == KM_PRESS) {
- draw = swallow = 1;
- if (tools & TOOL_SUGG_LIST) {
- texttool_suggest_clear();
- }
- else if (tools & TOOL_DOCUMENT) {
- texttool_docs_clear();
- doc_scroll = 0;
- }
- else draw = swallow = 0;
- retval = OPERATOR_CANCELLED;
- }
- break;
- case RETKEY:
- case PADENTER:
- if (event->val == KM_PRESS) {
- if (tools & TOOL_SUGG_LIST) {
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- confirm_suggestion(st->text, utxt);
- text_update_line_edited(st->text->curl);
- ED_undo_push(C, op->type->name);
- swallow = 1;
- draw = 1;
- }
- if (tools & TOOL_DOCUMENT) {
- texttool_docs_clear();
- doc_scroll = 0;
- draw = 1;
- }
- retval = OPERATOR_FINISHED;
- }
- break;
- case LEFTARROWKEY:
- case BACKSPACEKEY:
- if (event->val == KM_PRESS) {
- if (tools & TOOL_SUGG_LIST) {
- if (event->ctrl) {
- texttool_suggest_clear();
- retval = OPERATOR_CANCELLED;
- }
- else {
- /* Work out which char we are about to delete/pass */
- if (st->text->curl && st->text->curc > 0) {
- char ch = st->text->curl->line[st->text->curc - 1];
- if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
- get_suggest_prefix(st->text, -1);
- text_pop_suggest_list();
- }
- else {
- texttool_suggest_clear();
- retval = OPERATOR_CANCELLED;
- }
- }
- else {
- texttool_suggest_clear();
- retval = OPERATOR_CANCELLED;
- }
- }
- }
- if (tools & TOOL_DOCUMENT) {
- texttool_docs_clear();
- doc_scroll = 0;
- }
- }
- break;
- case RIGHTARROWKEY:
- if (event->val == KM_PRESS) {
- if (tools & TOOL_SUGG_LIST) {
- if (event->ctrl) {
- texttool_suggest_clear();
- retval = OPERATOR_CANCELLED;
- }
- else {
- /* Work out which char we are about to pass */
- if (st->text->curl && st->text->curc < st->text->curl->len) {
- char ch = st->text->curl->line[st->text->curc + 1];
- if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
- get_suggest_prefix(st->text, 1);
- text_pop_suggest_list();
- }
- else {
- texttool_suggest_clear();
- retval = OPERATOR_CANCELLED;
- }
- }
- else {
- texttool_suggest_clear();
- retval = OPERATOR_CANCELLED;
- }
- }
- }
- if (tools & TOOL_DOCUMENT) {
- texttool_docs_clear();
- doc_scroll = 0;
- }
- }
- break;
- case PAGEDOWNKEY:
- scroll = SUGG_LIST_SIZE - 1;
- ATTR_FALLTHROUGH;
- case WHEELDOWNMOUSE:
- case DOWNARROWKEY:
- if (event->val == KM_PRESS) {
- if (tools & TOOL_DOCUMENT) {
- doc_scroll++;
- swallow = 1;
- draw = 1;
- }
- else if (tools & TOOL_SUGG_LIST) {
- SuggItem *sel = texttool_suggest_selected();
- if (!sel) {
- texttool_suggest_select(texttool_suggest_first());
- }
- else {
- while (sel && scroll--) {
- if (sel != texttool_suggest_last() && sel->next) {
- texttool_suggest_select(sel->next);
- sel = sel->next;
- }
- else {
- texttool_suggest_select(texttool_suggest_first());
- sel = texttool_suggest_first();
- }
- }
- }
- text_pop_suggest_list();
- swallow = 1;
- draw = 1;
- }
- }
- break;
- case PAGEUPKEY:
- scroll = SUGG_LIST_SIZE - 1;
- ATTR_FALLTHROUGH;
- case WHEELUPMOUSE:
- case UPARROWKEY:
- if (event->val == KM_PRESS) {
- if (tools & TOOL_DOCUMENT) {
- if (doc_scroll > 0) doc_scroll--;
- swallow = 1;
- draw = 1;
- }
- else if (tools & TOOL_SUGG_LIST) {
- SuggItem *sel = texttool_suggest_selected();
- while (sel && scroll--) {
- if (sel != texttool_suggest_first() && sel->prev) {
- texttool_suggest_select(sel->prev);
- sel = sel->prev;
- }
- else {
- texttool_suggest_select(texttool_suggest_last());
- sel = texttool_suggest_last();
- }
- }
- text_pop_suggest_list();
- swallow = 1;
- draw = 1;
- }
- }
- break;
- case RIGHTSHIFTKEY:
- case LEFTSHIFTKEY:
- break;
+ SpaceText *st = CTX_wm_space_text(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+
+ int draw = 0, tools = 0, swallow = 0, scroll = 1;
+ Text *text = CTX_data_edit_text(C);
+ int retval = OPERATOR_RUNNING_MODAL;
+
+ (void)text;
+
+ if (st->doplugins && texttool_text_is_active(st->text)) {
+ if (texttool_suggest_first())
+ tools |= TOOL_SUGG_LIST;
+ if (texttool_docs_get())
+ tools |= TOOL_DOCUMENT;
+ }
+
+ switch (event->type) {
+ case LEFTMOUSE:
+ if (event->val == KM_PRESS) {
+ if (text_do_suggest_select(st, ar))
+ swallow = 1;
+ else {
+ if (tools & TOOL_SUGG_LIST) {
+ texttool_suggest_clear();
+ }
+ if (tools & TOOL_DOCUMENT) {
+ texttool_docs_clear();
+ doc_scroll = 0;
+ }
+ retval = OPERATOR_FINISHED;
+ }
+ draw = 1;
+ }
+ break;
+ case MIDDLEMOUSE:
+ if (event->val == KM_PRESS) {
+ if (text_do_suggest_select(st, ar)) {
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ confirm_suggestion(st->text, utxt);
+ text_update_line_edited(st->text->curl);
+ ED_undo_push(C, op->type->name);
+ swallow = 1;
+ }
+ else {
+ if (tools & TOOL_SUGG_LIST) {
+ texttool_suggest_clear();
+ }
+ if (tools & TOOL_DOCUMENT) {
+ texttool_docs_clear();
+ doc_scroll = 0;
+ }
+ retval = OPERATOR_FINISHED;
+ }
+ draw = 1;
+ }
+ break;
+ case ESCKEY:
+ if (event->val == KM_PRESS) {
+ draw = swallow = 1;
+ if (tools & TOOL_SUGG_LIST) {
+ texttool_suggest_clear();
+ }
+ else if (tools & TOOL_DOCUMENT) {
+ texttool_docs_clear();
+ doc_scroll = 0;
+ }
+ else
+ draw = swallow = 0;
+ retval = OPERATOR_CANCELLED;
+ }
+ break;
+ case RETKEY:
+ case PADENTER:
+ if (event->val == KM_PRESS) {
+ if (tools & TOOL_SUGG_LIST) {
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ confirm_suggestion(st->text, utxt);
+ text_update_line_edited(st->text->curl);
+ ED_undo_push(C, op->type->name);
+ swallow = 1;
+ draw = 1;
+ }
+ if (tools & TOOL_DOCUMENT) {
+ texttool_docs_clear();
+ doc_scroll = 0;
+ draw = 1;
+ }
+ retval = OPERATOR_FINISHED;
+ }
+ break;
+ case LEFTARROWKEY:
+ case BACKSPACEKEY:
+ if (event->val == KM_PRESS) {
+ if (tools & TOOL_SUGG_LIST) {
+ if (event->ctrl) {
+ texttool_suggest_clear();
+ retval = OPERATOR_CANCELLED;
+ }
+ else {
+ /* Work out which char we are about to delete/pass */
+ if (st->text->curl && st->text->curc > 0) {
+ char ch = st->text->curl->line[st->text->curc - 1];
+ if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
+ get_suggest_prefix(st->text, -1);
+ text_pop_suggest_list();
+ }
+ else {
+ texttool_suggest_clear();
+ retval = OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ texttool_suggest_clear();
+ retval = OPERATOR_CANCELLED;
+ }
+ }
+ }
+ if (tools & TOOL_DOCUMENT) {
+ texttool_docs_clear();
+ doc_scroll = 0;
+ }
+ }
+ break;
+ case RIGHTARROWKEY:
+ if (event->val == KM_PRESS) {
+ if (tools & TOOL_SUGG_LIST) {
+ if (event->ctrl) {
+ texttool_suggest_clear();
+ retval = OPERATOR_CANCELLED;
+ }
+ else {
+ /* Work out which char we are about to pass */
+ if (st->text->curl && st->text->curc < st->text->curl->len) {
+ char ch = st->text->curl->line[st->text->curc + 1];
+ if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
+ get_suggest_prefix(st->text, 1);
+ text_pop_suggest_list();
+ }
+ else {
+ texttool_suggest_clear();
+ retval = OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ texttool_suggest_clear();
+ retval = OPERATOR_CANCELLED;
+ }
+ }
+ }
+ if (tools & TOOL_DOCUMENT) {
+ texttool_docs_clear();
+ doc_scroll = 0;
+ }
+ }
+ break;
+ case PAGEDOWNKEY:
+ scroll = SUGG_LIST_SIZE - 1;
+ ATTR_FALLTHROUGH;
+ case WHEELDOWNMOUSE:
+ case DOWNARROWKEY:
+ if (event->val == KM_PRESS) {
+ if (tools & TOOL_DOCUMENT) {
+ doc_scroll++;
+ swallow = 1;
+ draw = 1;
+ }
+ else if (tools & TOOL_SUGG_LIST) {
+ SuggItem *sel = texttool_suggest_selected();
+ if (!sel) {
+ texttool_suggest_select(texttool_suggest_first());
+ }
+ else {
+ while (sel && scroll--) {
+ if (sel != texttool_suggest_last() && sel->next) {
+ texttool_suggest_select(sel->next);
+ sel = sel->next;
+ }
+ else {
+ texttool_suggest_select(texttool_suggest_first());
+ sel = texttool_suggest_first();
+ }
+ }
+ }
+ text_pop_suggest_list();
+ swallow = 1;
+ draw = 1;
+ }
+ }
+ break;
+ case PAGEUPKEY:
+ scroll = SUGG_LIST_SIZE - 1;
+ ATTR_FALLTHROUGH;
+ case WHEELUPMOUSE:
+ case UPARROWKEY:
+ if (event->val == KM_PRESS) {
+ if (tools & TOOL_DOCUMENT) {
+ if (doc_scroll > 0)
+ doc_scroll--;
+ swallow = 1;
+ draw = 1;
+ }
+ else if (tools & TOOL_SUGG_LIST) {
+ SuggItem *sel = texttool_suggest_selected();
+ while (sel && scroll--) {
+ if (sel != texttool_suggest_first() && sel->prev) {
+ texttool_suggest_select(sel->prev);
+ sel = sel->prev;
+ }
+ else {
+ texttool_suggest_select(texttool_suggest_last());
+ sel = texttool_suggest_last();
+ }
+ }
+ text_pop_suggest_list();
+ swallow = 1;
+ draw = 1;
+ }
+ }
+ break;
+ case RIGHTSHIFTKEY:
+ case LEFTSHIFTKEY:
+ break;
#if 0
- default:
- if (tools & TOOL_SUGG_LIST) {
- texttool_suggest_clear();
- draw = 1;
- }
- if (tools & TOOL_DOCUMENT) {
- texttool_docs_clear();
- doc_scroll = 0;
- draw = 1;
- }
+ default:
+ if (tools & TOOL_SUGG_LIST) {
+ texttool_suggest_clear();
+ draw = 1;
+ }
+ if (tools & TOOL_DOCUMENT) {
+ texttool_docs_clear();
+ doc_scroll = 0;
+ draw = 1;
+ }
#endif
- }
-
- if (draw) {
- ED_area_tag_redraw(sa);
- }
-
-// if (swallow) {
-// retval = OPERATOR_RUNNING_MODAL;
-// }
-
- if (texttool_suggest_first()) {
- if (retval != OPERATOR_RUNNING_MODAL) {
- text_autocomplete_free(C, op);
- }
- return retval;
- }
- else {
- text_autocomplete_free(C, op);
- return OPERATOR_FINISHED;
- }
+ }
+
+ if (draw) {
+ ED_area_tag_redraw(sa);
+ }
+
+ // if (swallow) {
+ // retval = OPERATOR_RUNNING_MODAL;
+ // }
+
+ if (texttool_suggest_first()) {
+ if (retval != OPERATOR_RUNNING_MODAL) {
+ text_autocomplete_free(C, op);
+ }
+ return retval;
+ }
+ else {
+ text_autocomplete_free(C, op);
+ return OPERATOR_FINISHED;
+ }
}
static void text_autocomplete_free(bContext *C, wmOperator *op)
{
- GHash *gh = op->customdata;
- if (gh) {
- BLI_ghash_free(gh, NULL, MEM_freeN);
- op->customdata = NULL;
- }
-
- /* other stuff */
- {
- SpaceText *st = CTX_wm_space_text(C);
- st->doplugins = false;
- texttool_text_clear();
- }
+ GHash *gh = op->customdata;
+ if (gh) {
+ BLI_ghash_free(gh, NULL, MEM_freeN);
+ op->customdata = NULL;
+ }
+
+ /* other stuff */
+ {
+ SpaceText *st = CTX_wm_space_text(C);
+ st->doplugins = false;
+ texttool_text_clear();
+ }
}
static void text_autocomplete_cancel(bContext *C, wmOperator *op)
{
- text_autocomplete_free(C, op);
+ text_autocomplete_free(C, op);
}
void TEXT_OT_autocomplete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Text Auto Complete";
- ot->description = "Show a list of used text in the open document";
- ot->idname = "TEXT_OT_autocomplete";
-
- /* api callbacks */
- ot->invoke = text_autocomplete_invoke;
- ot->cancel = text_autocomplete_cancel;
- ot->modal = text_autocomplete_modal;
- ot->poll = text_space_edit_poll;
-
- /* flags */
- /* Undo is handled conditionally by this operator. */
- ot->flag = OPTYPE_BLOCKING;
+ /* identifiers */
+ ot->name = "Text Auto Complete";
+ ot->description = "Show a list of used text in the open document";
+ ot->idname = "TEXT_OT_autocomplete";
+
+ /* api callbacks */
+ ot->invoke = text_autocomplete_invoke;
+ ot->cancel = text_autocomplete_cancel;
+ ot->modal = text_autocomplete_modal;
+ ot->poll = text_space_edit_poll;
+
+ /* flags */
+ /* Undo is handled conditionally by this operator. */
+ ot->flag = OPTYPE_BLOCKING;
}
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 1b49e637350..dadb86f439b 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -38,7 +38,6 @@
#include "ED_text.h"
-
#include "GPU_immediate.h"
#include "GPU_state.h"
@@ -52,21 +51,21 @@
/******************** text font drawing ******************/
typedef struct TextDrawContext {
- int font_id;
- int cwidth;
- int lheight_dpi;
+ int font_id;
+ int cwidth;
+ int lheight_dpi;
} TextDrawContext;
static void text_draw_context_init(const SpaceText *st, TextDrawContext *tdc)
{
- tdc->font_id = blf_mono_font;
- tdc->cwidth = 0;
- tdc->lheight_dpi = st->lheight_dpi;
+ tdc->font_id = blf_mono_font;
+ tdc->cwidth = 0;
+ tdc->lheight_dpi = st->lheight_dpi;
}
static void text_font_begin(const TextDrawContext *tdc)
{
- BLF_size(tdc->font_id, tdc->lheight_dpi, 72);
+ BLF_size(tdc->font_id, tdc->lheight_dpi, 72);
}
static void text_font_end(const TextDrawContext *UNUSED(tdc))
@@ -75,81 +74,81 @@ static void text_font_end(const TextDrawContext *UNUSED(tdc))
static int text_font_draw(const TextDrawContext *tdc, int x, int y, const char *str)
{
- int columns;
+ int columns;
- BLF_position(tdc->font_id, x, y, 0);
- columns = BLF_draw_mono(tdc->font_id, str, BLF_DRAW_STR_DUMMY_MAX, tdc->cwidth);
+ BLF_position(tdc->font_id, x, y, 0);
+ columns = BLF_draw_mono(tdc->font_id, str, BLF_DRAW_STR_DUMMY_MAX, tdc->cwidth);
- return tdc->cwidth * columns;
+ return tdc->cwidth * columns;
}
static int text_font_draw_character(const TextDrawContext *tdc, int x, int y, char c)
{
- BLF_position(tdc->font_id, x, y, 0);
- BLF_draw(tdc->font_id, &c, 1);
+ BLF_position(tdc->font_id, x, y, 0);
+ BLF_draw(tdc->font_id, &c, 1);
- return tdc->cwidth;
+ return tdc->cwidth;
}
static int text_font_draw_character_utf8(const TextDrawContext *tdc, int x, int y, const char *c)
{
- int columns;
+ int columns;
- const size_t len = BLI_str_utf8_size_safe(c);
- BLF_position(tdc->font_id, x, y, 0);
- columns = BLF_draw_mono(tdc->font_id, c, len, tdc->cwidth);
+ const size_t len = BLI_str_utf8_size_safe(c);
+ BLF_position(tdc->font_id, x, y, 0);
+ columns = BLF_draw_mono(tdc->font_id, c, len, tdc->cwidth);
- return tdc->cwidth * columns;
+ return tdc->cwidth * columns;
}
#if 0
/* Formats every line of the current text */
static void txt_format_text(SpaceText *st)
{
- TextLine *linep;
+ TextLine *linep;
- if (!st->text) return;
+ if (!st->text) return;
- for (linep = st->text->lines.first; linep; linep = linep->next)
- txt_format_line(st, linep, 0);
+ for (linep = st->text->lines.first; linep; linep = linep->next)
+ txt_format_line(st, linep, 0);
}
#endif
/* Sets the current drawing color based on the format character specified */
static void format_draw_color(const TextDrawContext *tdc, char formatchar)
{
- switch (formatchar) {
- case FMT_TYPE_WHITESPACE:
- break;
- case FMT_TYPE_SYMBOL:
- UI_FontThemeColor(tdc->font_id, TH_SYNTAX_S);
- break;
- case FMT_TYPE_COMMENT:
- UI_FontThemeColor(tdc->font_id, TH_SYNTAX_C);
- break;
- case FMT_TYPE_NUMERAL:
- UI_FontThemeColor(tdc->font_id, TH_SYNTAX_N);
- break;
- case FMT_TYPE_STRING:
- UI_FontThemeColor(tdc->font_id, TH_SYNTAX_L);
- break;
- case FMT_TYPE_DIRECTIVE:
- UI_FontThemeColor(tdc->font_id, TH_SYNTAX_D);
- break;
- case FMT_TYPE_SPECIAL:
- UI_FontThemeColor(tdc->font_id, TH_SYNTAX_V);
- break;
- case FMT_TYPE_RESERVED:
- UI_FontThemeColor(tdc->font_id, TH_SYNTAX_R);
- break;
- case FMT_TYPE_KEYWORD:
- UI_FontThemeColor(tdc->font_id, TH_SYNTAX_B);
- break;
- case FMT_TYPE_DEFAULT:
- default:
- UI_FontThemeColor(tdc->font_id, TH_TEXT);
- break;
- }
+ switch (formatchar) {
+ case FMT_TYPE_WHITESPACE:
+ break;
+ case FMT_TYPE_SYMBOL:
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_S);
+ break;
+ case FMT_TYPE_COMMENT:
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_C);
+ break;
+ case FMT_TYPE_NUMERAL:
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_N);
+ break;
+ case FMT_TYPE_STRING:
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_L);
+ break;
+ case FMT_TYPE_DIRECTIVE:
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_D);
+ break;
+ case FMT_TYPE_SPECIAL:
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_V);
+ break;
+ case FMT_TYPE_RESERVED:
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_R);
+ break;
+ case FMT_TYPE_KEYWORD:
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_B);
+ break;
+ case FMT_TYPE_DEFAULT:
+ default:
+ UI_FontThemeColor(tdc->font_id, TH_TEXT);
+ break;
+ }
}
/************************** draw text *****************************/
@@ -185,533 +184,566 @@ static void format_draw_color(const TextDrawContext *tdc, char formatchar)
int wrap_width(const SpaceText *st, ARegion *ar)
{
- int winx = ar->winx - TXT_SCROLL_WIDTH;
- int x, max;
+ int winx = ar->winx - TXT_SCROLL_WIDTH;
+ int x, max;
- x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
- max = st->cwidth ? (winx - x) / st->cwidth : 0;
- return max > 8 ? max : 8;
+ x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
+ max = st->cwidth ? (winx - x) / st->cwidth : 0;
+ return max > 8 ? max : 8;
}
/* 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)
+void wrap_offset(
+ const SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *offl, int *offc)
{
- Text *text;
- TextLine *linep;
- int i, j, start, end, max, chop;
- char ch;
-
- *offl = *offc = 0;
-
- if (!st->text) return;
- if (!st->wordwrap) return;
-
- text = st->text;
-
- /* Move pointer to first visible line (top) */
- linep = text->lines.first;
- i = st->top;
- while (i > 0 && linep) {
- int lines = text_get_visible_lines(st, ar, linep->line);
-
- /* Line before top */
- if (linep == linein) {
- if (lines <= i)
- /* no visible part of line */
- return;
- }
-
- if (i - lines < 0) {
- break;
- }
- else {
- linep = linep->next;
- (*offl) += lines - 1;
- i -= lines;
- }
- }
-
- max = wrap_width(st, ar);
- cursin = txt_utf8_offset_to_column(linein->line, cursin);
-
- while (linep) {
- start = 0;
- end = max;
- chop = 1;
- *offc = 0;
- for (i = 0, j = 0; linep->line[j]; j += BLI_str_utf8_size_safe(linep->line + j)) {
- int chars;
- int columns = BLI_str_utf8_char_width_safe(linep->line + j); /* = 1 for tab */
-
- /* Mimic replacement of tabs */
- ch = linep->line[j];
- if (ch == '\t') {
- chars = st->tabnumber - i % st->tabnumber;
- if (linep == linein && i < cursin) cursin += chars - 1;
- ch = ' ';
- }
- else {
- chars = 1;
- }
-
- while (chars--) {
- if (i + columns - start > max) {
- end = MIN2(end, i);
-
- if (chop && linep == linein && i >= cursin) {
- if (i == cursin) {
- (*offl)++;
- *offc -= end - start;
- }
-
- return;
- }
-
- (*offl)++;
- *offc -= end - start;
-
- start = end;
- end += max;
- chop = 1;
- }
- else if (ch == ' ' || ch == '-') {
- end = i + 1;
- chop = 0;
- if (linep == linein && i >= cursin)
- return;
- }
- i += columns;
- }
- }
- if (linep == linein) break;
- linep = linep->next;
- }
+ Text *text;
+ TextLine *linep;
+ int i, j, start, end, max, chop;
+ char ch;
+
+ *offl = *offc = 0;
+
+ if (!st->text)
+ return;
+ if (!st->wordwrap)
+ return;
+
+ text = st->text;
+
+ /* Move pointer to first visible line (top) */
+ linep = text->lines.first;
+ i = st->top;
+ while (i > 0 && linep) {
+ int lines = text_get_visible_lines(st, ar, linep->line);
+
+ /* Line before top */
+ if (linep == linein) {
+ if (lines <= i)
+ /* no visible part of line */
+ return;
+ }
+
+ if (i - lines < 0) {
+ break;
+ }
+ else {
+ linep = linep->next;
+ (*offl) += lines - 1;
+ i -= lines;
+ }
+ }
+
+ max = wrap_width(st, ar);
+ cursin = txt_utf8_offset_to_column(linein->line, cursin);
+
+ while (linep) {
+ start = 0;
+ end = max;
+ chop = 1;
+ *offc = 0;
+ for (i = 0, j = 0; linep->line[j]; j += BLI_str_utf8_size_safe(linep->line + j)) {
+ int chars;
+ int columns = BLI_str_utf8_char_width_safe(linep->line + j); /* = 1 for tab */
+
+ /* Mimic replacement of tabs */
+ ch = linep->line[j];
+ if (ch == '\t') {
+ chars = st->tabnumber - i % st->tabnumber;
+ if (linep == linein && i < cursin)
+ cursin += chars - 1;
+ ch = ' ';
+ }
+ else {
+ chars = 1;
+ }
+
+ while (chars--) {
+ if (i + columns - start > max) {
+ end = MIN2(end, i);
+
+ if (chop && linep == linein && i >= cursin) {
+ if (i == cursin) {
+ (*offl)++;
+ *offc -= end - start;
+ }
+
+ return;
+ }
+
+ (*offl)++;
+ *offc -= end - start;
+
+ start = end;
+ end += max;
+ chop = 1;
+ }
+ else if (ch == ' ' || ch == '-') {
+ end = i + 1;
+ chop = 0;
+ if (linep == linein && i >= cursin)
+ return;
+ }
+ i += columns;
+ }
+ }
+ if (linep == linein)
+ break;
+ linep = linep->next;
+ }
}
/* cursin - mem, offc - view */
-void wrap_offset_in_line(const SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *offl, int *offc)
+void wrap_offset_in_line(
+ const SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *offl, int *offc)
{
- int i, j, start, end, chars, max, chop;
- char ch;
-
- *offl = *offc = 0;
-
- if (!st->text) return;
- if (!st->wordwrap) return;
-
- max = wrap_width(st, ar);
-
- start = 0;
- end = max;
- chop = 1;
- *offc = 0;
- cursin = txt_utf8_offset_to_column(linein->line, cursin);
-
- for (i = 0, j = 0; linein->line[j]; j += BLI_str_utf8_size_safe(linein->line + j)) {
- int columns = BLI_str_utf8_char_width_safe(linein->line + j); /* = 1 for tab */
-
- /* Mimic replacement of tabs */
- ch = linein->line[j];
- if (ch == '\t') {
- chars = st->tabnumber - i % st->tabnumber;
- if (i < cursin) cursin += chars - 1;
- ch = ' ';
- }
- else
- chars = 1;
-
- while (chars--) {
- if (i + columns - start > max) {
- end = MIN2(end, i);
-
- if (chop && i >= cursin) {
- if (i == cursin) {
- (*offl)++;
- *offc -= end - start;
- }
-
- return;
- }
-
- (*offl)++;
- *offc -= end - start;
-
- start = end;
- end += max;
- chop = 1;
- }
- else if (ch == ' ' || ch == '-') {
- end = i + 1;
- chop = 0;
- if (i >= cursin)
- return;
- }
- i += columns;
- }
- }
+ int i, j, start, end, chars, max, chop;
+ char ch;
+
+ *offl = *offc = 0;
+
+ if (!st->text)
+ return;
+ if (!st->wordwrap)
+ return;
+
+ max = wrap_width(st, ar);
+
+ start = 0;
+ end = max;
+ chop = 1;
+ *offc = 0;
+ cursin = txt_utf8_offset_to_column(linein->line, cursin);
+
+ for (i = 0, j = 0; linein->line[j]; j += BLI_str_utf8_size_safe(linein->line + j)) {
+ int columns = BLI_str_utf8_char_width_safe(linein->line + j); /* = 1 for tab */
+
+ /* Mimic replacement of tabs */
+ ch = linein->line[j];
+ if (ch == '\t') {
+ chars = st->tabnumber - i % st->tabnumber;
+ if (i < cursin)
+ cursin += chars - 1;
+ ch = ' ';
+ }
+ else
+ chars = 1;
+
+ while (chars--) {
+ if (i + columns - start > max) {
+ end = MIN2(end, i);
+
+ if (chop && i >= cursin) {
+ if (i == cursin) {
+ (*offl)++;
+ *offc -= end - start;
+ }
+
+ return;
+ }
+
+ (*offl)++;
+ *offc -= end - start;
+
+ start = end;
+ end += max;
+ chop = 1;
+ }
+ else if (ch == ' ' || ch == '-') {
+ end = i + 1;
+ chop = 0;
+ if (i >= cursin)
+ return;
+ }
+ i += columns;
+ }
+ }
}
int text_get_char_pos(const SpaceText *st, const char *line, int cur)
{
- int a = 0, i;
-
- for (i = 0; i < cur && line[i]; i += BLI_str_utf8_size_safe(line + i)) {
- if (line[i] == '\t')
- a += st->tabnumber - a % st->tabnumber;
- else
- a += BLI_str_utf8_char_width_safe(line + i);
- }
- return a;
+ int a = 0, i;
+
+ for (i = 0; i < cur && line[i]; i += BLI_str_utf8_size_safe(line + i)) {
+ if (line[i] == '\t')
+ a += st->tabnumber - a % st->tabnumber;
+ else
+ a += BLI_str_utf8_char_width_safe(line + i);
+ }
+ return a;
}
static const char *txt_utf8_forward_columns(const char *str, int columns, int *padding)
{
- int col;
- const char *p = str;
- while (*p) {
- col = BLI_str_utf8_char_width(p);
- if (columns - col < 0)
- break;
- columns -= col;
- p += BLI_str_utf8_size_safe(p);
- if (columns == 0)
- break;
- }
- if (padding)
- *padding = *p ? columns : 0;
- return p;
+ int col;
+ const char *p = str;
+ while (*p) {
+ col = BLI_str_utf8_char_width(p);
+ if (columns - col < 0)
+ break;
+ columns -= col;
+ p += BLI_str_utf8_size_safe(p);
+ if (columns == 0)
+ break;
+ }
+ if (padding)
+ *padding = *p ? columns : 0;
+ return p;
}
-static int text_draw_wrapped(
- const SpaceText *st, const TextDrawContext *tdc,
- const char *str, int x, int y, int w, const char *format, int skip)
+static int text_draw_wrapped(const SpaceText *st,
+ const TextDrawContext *tdc,
+ const char *str,
+ int x,
+ int y,
+ int w,
+ const char *format,
+ int skip)
{
- const bool use_syntax = (st->showsyntax && format);
- FlattenString fs;
- int basex, lines;
- int i, wrap, end, max, columns, padding; /* column */
- /* warning, only valid when 'use_syntax' is set */
- int a, fstart, fpos; /* utf8 chars */
- int mi, ma, mstart, mend; /* mem */
- char fmt_prev = 0xff;
- /* don't draw lines below this */
- const int clip_min_y = -(int)(st->lheight_dpi - 1);
-
- flatten_string(st, &fs, str);
- str = fs.buf;
- max = w / st->cwidth;
- if (max < 8) max = 8;
- basex = x;
- lines = 1;
-
- fpos = fstart = 0; mstart = 0;
- mend = txt_utf8_forward_columns(str, max, &padding) - str;
- end = wrap = max - padding;
-
- for (i = 0, mi = 0; str[mi]; i += columns, mi += BLI_str_utf8_size_safe(str + mi)) {
- columns = BLI_str_utf8_char_width_safe(str + mi);
- if (i + columns > end) {
- /* skip hidden part of line */
- if (skip) {
- skip--;
- if (use_syntax) {
- /* currently fpos only used when formatting */
- fpos += BLI_strnlen_utf8(str + mstart, mend - mstart);
- }
- fstart = fpos; mstart = mend;
- mend = txt_utf8_forward_columns(str + mend, max, &padding) - str;
- end = (wrap += max - padding);
- continue;
- }
-
- /* Draw the visible portion of text on the overshot line */
- for (a = fstart, ma = mstart; ma < mend; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
- if (use_syntax) {
- if (fmt_prev != format[a]) format_draw_color(tdc, fmt_prev = format[a]);
- }
- x += text_font_draw_character_utf8(tdc, x, y, str + ma);
- fpos++;
- }
- y -= st->lheight_dpi + TXT_LINE_SPACING;
- x = basex;
- lines++;
- fstart = fpos; mstart = mend;
- mend = txt_utf8_forward_columns(str + mend, max, &padding) - str;
- end = (wrap += max - padding);
-
- if (y <= clip_min_y)
- break;
- }
- else if (str[mi] == ' ' || str[mi] == '-') {
- wrap = i + 1; mend = mi + 1;
- }
- }
-
- /* Draw the remaining text */
- for (a = fstart, ma = mstart; str[ma] && y > clip_min_y; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
- if (use_syntax) {
- if (fmt_prev != format[a]) format_draw_color(tdc, fmt_prev = format[a]);
- }
-
- x += text_font_draw_character_utf8(tdc, x, y, str + ma);
- }
-
- flatten_string_free(&fs);
-
- return lines;
+ const bool use_syntax = (st->showsyntax && format);
+ FlattenString fs;
+ int basex, lines;
+ int i, wrap, end, max, columns, padding; /* column */
+ /* warning, only valid when 'use_syntax' is set */
+ int a, fstart, fpos; /* utf8 chars */
+ int mi, ma, mstart, mend; /* mem */
+ char fmt_prev = 0xff;
+ /* don't draw lines below this */
+ const int clip_min_y = -(int)(st->lheight_dpi - 1);
+
+ flatten_string(st, &fs, str);
+ str = fs.buf;
+ max = w / st->cwidth;
+ if (max < 8)
+ max = 8;
+ basex = x;
+ lines = 1;
+
+ fpos = fstart = 0;
+ mstart = 0;
+ mend = txt_utf8_forward_columns(str, max, &padding) - str;
+ end = wrap = max - padding;
+
+ for (i = 0, mi = 0; str[mi]; i += columns, mi += BLI_str_utf8_size_safe(str + mi)) {
+ columns = BLI_str_utf8_char_width_safe(str + mi);
+ if (i + columns > end) {
+ /* skip hidden part of line */
+ if (skip) {
+ skip--;
+ if (use_syntax) {
+ /* currently fpos only used when formatting */
+ fpos += BLI_strnlen_utf8(str + mstart, mend - mstart);
+ }
+ fstart = fpos;
+ mstart = mend;
+ mend = txt_utf8_forward_columns(str + mend, max, &padding) - str;
+ end = (wrap += max - padding);
+ continue;
+ }
+
+ /* Draw the visible portion of text on the overshot line */
+ for (a = fstart, ma = mstart; ma < mend; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
+ if (use_syntax) {
+ if (fmt_prev != format[a])
+ format_draw_color(tdc, fmt_prev = format[a]);
+ }
+ x += text_font_draw_character_utf8(tdc, x, y, str + ma);
+ fpos++;
+ }
+ y -= st->lheight_dpi + TXT_LINE_SPACING;
+ x = basex;
+ lines++;
+ fstart = fpos;
+ mstart = mend;
+ mend = txt_utf8_forward_columns(str + mend, max, &padding) - str;
+ end = (wrap += max - padding);
+
+ if (y <= clip_min_y)
+ break;
+ }
+ else if (str[mi] == ' ' || str[mi] == '-') {
+ wrap = i + 1;
+ mend = mi + 1;
+ }
+ }
+
+ /* Draw the remaining text */
+ for (a = fstart, ma = mstart; str[ma] && y > clip_min_y;
+ a++, ma += BLI_str_utf8_size_safe(str + ma)) {
+ if (use_syntax) {
+ if (fmt_prev != format[a])
+ format_draw_color(tdc, fmt_prev = format[a]);
+ }
+
+ x += text_font_draw_character_utf8(tdc, x, y, str + ma);
+ }
+
+ flatten_string_free(&fs);
+
+ return lines;
}
-static void text_draw(
- const SpaceText *st, const TextDrawContext *tdc,
- char *str, int cshift, int maxwidth, int x, int y, const char *format)
+static void text_draw(const SpaceText *st,
+ const TextDrawContext *tdc,
+ char *str,
+ int cshift,
+ int maxwidth,
+ int x,
+ int y,
+ const char *format)
{
- const bool use_syntax = (st->showsyntax && format);
- FlattenString fs;
- int columns, size, n, w = 0, padding, amount = 0;
- const char *in = NULL;
-
- for (n = flatten_string(st, &fs, str), str = fs.buf; n > 0; n--) {
- columns = BLI_str_utf8_char_width_safe(str);
- size = BLI_str_utf8_size_safe(str);
-
- if (!in) {
- if (w >= cshift) {
- padding = w - cshift;
- in = str;
- }
- else if (format)
- format++;
- }
- if (in) {
- if (maxwidth && w + columns > cshift + maxwidth)
- break;
- amount++;
- }
-
- w += columns;
- str += size;
- }
- if (!in) {
- flatten_string_free(&fs);
- return; /* String is shorter than shift or ends with a padding */
- }
-
- x += tdc->cwidth * padding;
-
- if (use_syntax) {
- int a, str_shift = 0;
- char fmt_prev = 0xff;
-
- for (a = 0; a < amount; a++) {
- if (format[a] != fmt_prev) format_draw_color(tdc, fmt_prev = format[a]);
- x += text_font_draw_character_utf8(tdc, x, y, in + str_shift);
- str_shift += BLI_str_utf8_size_safe(in + str_shift);
- }
- }
- else {
- text_font_draw(tdc, x, y, in);
- }
-
- flatten_string_free(&fs);
+ const bool use_syntax = (st->showsyntax && format);
+ FlattenString fs;
+ int columns, size, n, w = 0, padding, amount = 0;
+ const char *in = NULL;
+
+ for (n = flatten_string(st, &fs, str), str = fs.buf; n > 0; n--) {
+ columns = BLI_str_utf8_char_width_safe(str);
+ size = BLI_str_utf8_size_safe(str);
+
+ if (!in) {
+ if (w >= cshift) {
+ padding = w - cshift;
+ in = str;
+ }
+ else if (format)
+ format++;
+ }
+ if (in) {
+ if (maxwidth && w + columns > cshift + maxwidth)
+ break;
+ amount++;
+ }
+
+ w += columns;
+ str += size;
+ }
+ if (!in) {
+ flatten_string_free(&fs);
+ return; /* String is shorter than shift or ends with a padding */
+ }
+
+ x += tdc->cwidth * padding;
+
+ if (use_syntax) {
+ int a, str_shift = 0;
+ char fmt_prev = 0xff;
+
+ for (a = 0; a < amount; a++) {
+ if (format[a] != fmt_prev)
+ format_draw_color(tdc, fmt_prev = format[a]);
+ x += text_font_draw_character_utf8(tdc, x, y, in + str_shift);
+ str_shift += BLI_str_utf8_size_safe(in + str_shift);
+ }
+ }
+ else {
+ text_font_draw(tdc, x, y, in);
+ }
+
+ flatten_string_free(&fs);
}
/************************ cache utilities *****************************/
typedef struct DrawCache {
- int *line_height;
- int total_lines, nlines;
-
- /* this is needed to check cache relevance */
- int winx, wordwrap, showlinenrs, tabnumber;
- short lheight;
- char cwidth;
- char text_id[MAX_ID_NAME];
-
- /* for partial lines recalculation */
- short update_flag;
- int valid_head, valid_tail; /* amount of unchanged lines */
+ int *line_height;
+ int total_lines, nlines;
+
+ /* this is needed to check cache relevance */
+ int winx, wordwrap, showlinenrs, tabnumber;
+ short lheight;
+ char cwidth;
+ char text_id[MAX_ID_NAME];
+
+ /* for partial lines recalculation */
+ short update_flag;
+ int valid_head, valid_tail; /* amount of unchanged lines */
} DrawCache;
static void text_drawcache_init(SpaceText *st)
{
- DrawCache *drawcache = MEM_callocN(sizeof(DrawCache), "text draw cache");
+ DrawCache *drawcache = MEM_callocN(sizeof(DrawCache), "text draw cache");
- drawcache->winx = -1;
- drawcache->nlines = BLI_listbase_count(&st->text->lines);
- drawcache->text_id[0] = '\0';
+ drawcache->winx = -1;
+ drawcache->nlines = BLI_listbase_count(&st->text->lines);
+ drawcache->text_id[0] = '\0';
- st->drawcache = drawcache;
+ st->drawcache = drawcache;
}
static void text_update_drawcache(SpaceText *st, ARegion *ar)
{
- DrawCache *drawcache;
- int full_update = 0, nlines = 0;
- Text *txt = st->text;
-
- if (!st->drawcache) text_drawcache_init(st);
-
- text_update_character_width(st);
-
- drawcache = (DrawCache *)st->drawcache;
- nlines = drawcache->nlines;
-
- /* check if full cache update is needed */
-
- /* area was resized */
- full_update |= drawcache->winx != ar->winx;
- /* word-wrapping option was toggled */
- full_update |= drawcache->wordwrap != st->wordwrap;
- /* word-wrapping option was toggled */
- full_update |= drawcache->showlinenrs != st->showlinenrs;
- /* word-wrapping option was toggled */
- full_update |= drawcache->tabnumber != st->tabnumber;
- /* word-wrapping option was toggled */
- full_update |= drawcache->lheight != st->lheight_dpi;
- /* word-wrapping option was toggled */
- full_update |= drawcache->cwidth != st->cwidth;
- /* text datablock was changed */
- full_update |= !STREQLEN(drawcache->text_id, txt->id.name, MAX_ID_NAME);
-
- if (st->wordwrap) {
- /* update line heights */
- if (full_update || !drawcache->line_height) {
- drawcache->valid_head = 0;
- drawcache->valid_tail = 0;
- drawcache->update_flag = 1;
- }
-
- if (drawcache->update_flag) {
- TextLine *line = st->text->lines.first;
- int lineno = 0, size, lines_count;
- int *fp = drawcache->line_height, *new_tail, *old_tail;
-
- nlines = BLI_listbase_count(&txt->lines);
- size = sizeof(int) * nlines;
-
- if (fp) fp = MEM_reallocN(fp, size);
- else fp = MEM_callocN(size, "text drawcache line_height");
-
- drawcache->valid_tail = drawcache->valid_head = 0;
- old_tail = fp + drawcache->nlines - drawcache->valid_tail;
- new_tail = fp + nlines - drawcache->valid_tail;
- memmove(new_tail, old_tail, drawcache->valid_tail);
-
- drawcache->total_lines = 0;
-
- if (st->showlinenrs)
- st->linenrs_tot = integer_digits_i(nlines);
-
- while (line) {
- if (drawcache->valid_head) { /* we're inside valid head lines */
- lines_count = fp[lineno];
- drawcache->valid_head--;
- }
- else if (lineno > new_tail - fp) { /* we-re inside valid tail lines */
- lines_count = fp[lineno];
- }
- else {
- lines_count = text_get_visible_lines(st, ar, line->line);
- }
-
- fp[lineno] = lines_count;
-
- line = line->next;
- lineno++;
- drawcache->total_lines += lines_count;
- }
-
- drawcache->line_height = fp;
- }
- }
- else {
- if (drawcache->line_height) {
- MEM_freeN(drawcache->line_height);
- drawcache->line_height = NULL;
- }
-
- if (full_update || drawcache->update_flag) {
- nlines = BLI_listbase_count(&txt->lines);
-
- if (st->showlinenrs)
- st->linenrs_tot = integer_digits_i(nlines);
- }
-
- drawcache->total_lines = nlines;
- }
-
- drawcache->nlines = nlines;
-
- /* store settings */
- drawcache->winx = ar->winx;
- drawcache->wordwrap = st->wordwrap;
- drawcache->lheight = st->lheight_dpi;
- drawcache->cwidth = st->cwidth;
- drawcache->showlinenrs = st->showlinenrs;
- drawcache->tabnumber = st->tabnumber;
-
- strncpy(drawcache->text_id, txt->id.name, MAX_ID_NAME);
-
- /* clear update flag */
- drawcache->update_flag = 0;
- drawcache->valid_head = 0;
- drawcache->valid_tail = 0;
+ DrawCache *drawcache;
+ int full_update = 0, nlines = 0;
+ Text *txt = st->text;
+
+ if (!st->drawcache)
+ text_drawcache_init(st);
+
+ text_update_character_width(st);
+
+ drawcache = (DrawCache *)st->drawcache;
+ nlines = drawcache->nlines;
+
+ /* check if full cache update is needed */
+
+ /* area was resized */
+ full_update |= drawcache->winx != ar->winx;
+ /* word-wrapping option was toggled */
+ full_update |= drawcache->wordwrap != st->wordwrap;
+ /* word-wrapping option was toggled */
+ full_update |= drawcache->showlinenrs != st->showlinenrs;
+ /* word-wrapping option was toggled */
+ full_update |= drawcache->tabnumber != st->tabnumber;
+ /* word-wrapping option was toggled */
+ full_update |= drawcache->lheight != st->lheight_dpi;
+ /* word-wrapping option was toggled */
+ full_update |= drawcache->cwidth != st->cwidth;
+ /* text datablock was changed */
+ full_update |= !STREQLEN(drawcache->text_id, txt->id.name, MAX_ID_NAME);
+
+ if (st->wordwrap) {
+ /* update line heights */
+ if (full_update || !drawcache->line_height) {
+ drawcache->valid_head = 0;
+ drawcache->valid_tail = 0;
+ drawcache->update_flag = 1;
+ }
+
+ if (drawcache->update_flag) {
+ TextLine *line = st->text->lines.first;
+ int lineno = 0, size, lines_count;
+ int *fp = drawcache->line_height, *new_tail, *old_tail;
+
+ nlines = BLI_listbase_count(&txt->lines);
+ size = sizeof(int) * nlines;
+
+ if (fp)
+ fp = MEM_reallocN(fp, size);
+ else
+ fp = MEM_callocN(size, "text drawcache line_height");
+
+ drawcache->valid_tail = drawcache->valid_head = 0;
+ old_tail = fp + drawcache->nlines - drawcache->valid_tail;
+ new_tail = fp + nlines - drawcache->valid_tail;
+ memmove(new_tail, old_tail, drawcache->valid_tail);
+
+ drawcache->total_lines = 0;
+
+ if (st->showlinenrs)
+ st->linenrs_tot = integer_digits_i(nlines);
+
+ while (line) {
+ if (drawcache->valid_head) { /* we're inside valid head lines */
+ lines_count = fp[lineno];
+ drawcache->valid_head--;
+ }
+ else if (lineno > new_tail - fp) { /* we-re inside valid tail lines */
+ lines_count = fp[lineno];
+ }
+ else {
+ lines_count = text_get_visible_lines(st, ar, line->line);
+ }
+
+ fp[lineno] = lines_count;
+
+ line = line->next;
+ lineno++;
+ drawcache->total_lines += lines_count;
+ }
+
+ drawcache->line_height = fp;
+ }
+ }
+ else {
+ if (drawcache->line_height) {
+ MEM_freeN(drawcache->line_height);
+ drawcache->line_height = NULL;
+ }
+
+ if (full_update || drawcache->update_flag) {
+ nlines = BLI_listbase_count(&txt->lines);
+
+ if (st->showlinenrs)
+ st->linenrs_tot = integer_digits_i(nlines);
+ }
+
+ drawcache->total_lines = nlines;
+ }
+
+ drawcache->nlines = nlines;
+
+ /* store settings */
+ drawcache->winx = ar->winx;
+ drawcache->wordwrap = st->wordwrap;
+ drawcache->lheight = st->lheight_dpi;
+ drawcache->cwidth = st->cwidth;
+ drawcache->showlinenrs = st->showlinenrs;
+ drawcache->tabnumber = st->tabnumber;
+
+ strncpy(drawcache->text_id, txt->id.name, MAX_ID_NAME);
+
+ /* clear update flag */
+ drawcache->update_flag = 0;
+ drawcache->valid_head = 0;
+ drawcache->valid_tail = 0;
}
void text_drawcache_tag_update(SpaceText *st, int full)
{
- /* this happens if text editor ops are caled from python */
- if (st == NULL)
- return;
-
- if (st->drawcache) {
- DrawCache *drawcache = (DrawCache *)st->drawcache;
- Text *txt = st->text;
-
- if (drawcache->update_flag) {
- /* happens when tagging update from space listener */
- /* should do nothing to prevent locally tagged cache be fully recalculated */
- return;
- }
-
- if (!full) {
- int sellno = BLI_findindex(&txt->lines, txt->sell);
- int curlno = BLI_findindex(&txt->lines, txt->curl);
-
- if (curlno < sellno) {
- drawcache->valid_head = curlno;
- drawcache->valid_tail = drawcache->nlines - sellno - 1;
- }
- else {
- drawcache->valid_head = sellno;
- drawcache->valid_tail = drawcache->nlines - curlno - 1;
- }
-
- /* quick cache recalculation is also used in delete operator,
- * which could merge lines which are adjacent to current selection lines
- * expand recalculate area to this lines */
- if (drawcache->valid_head > 0) drawcache->valid_head--;
- if (drawcache->valid_tail > 0) drawcache->valid_tail--;
- }
- else {
- drawcache->valid_head = 0;
- drawcache->valid_tail = 0;
- }
-
- drawcache->update_flag = 1;
- }
+ /* this happens if text editor ops are caled from python */
+ if (st == NULL)
+ return;
+
+ if (st->drawcache) {
+ DrawCache *drawcache = (DrawCache *)st->drawcache;
+ Text *txt = st->text;
+
+ if (drawcache->update_flag) {
+ /* happens when tagging update from space listener */
+ /* should do nothing to prevent locally tagged cache be fully recalculated */
+ return;
+ }
+
+ if (!full) {
+ int sellno = BLI_findindex(&txt->lines, txt->sell);
+ int curlno = BLI_findindex(&txt->lines, txt->curl);
+
+ if (curlno < sellno) {
+ drawcache->valid_head = curlno;
+ drawcache->valid_tail = drawcache->nlines - sellno - 1;
+ }
+ else {
+ drawcache->valid_head = sellno;
+ drawcache->valid_tail = drawcache->nlines - curlno - 1;
+ }
+
+ /* quick cache recalculation is also used in delete operator,
+ * which could merge lines which are adjacent to current selection lines
+ * expand recalculate area to this lines */
+ if (drawcache->valid_head > 0)
+ drawcache->valid_head--;
+ if (drawcache->valid_tail > 0)
+ drawcache->valid_tail--;
+ }
+ else {
+ drawcache->valid_head = 0;
+ drawcache->valid_tail = 0;
+ }
+
+ drawcache->update_flag = 1;
+ }
}
void text_free_caches(SpaceText *st)
{
- DrawCache *drawcache = (DrawCache *)st->drawcache;
+ DrawCache *drawcache = (DrawCache *)st->drawcache;
- if (drawcache) {
- if (drawcache->line_height)
- MEM_freeN(drawcache->line_height);
+ if (drawcache) {
+ if (drawcache->line_height)
+ MEM_freeN(drawcache->line_height);
- MEM_freeN(drawcache);
- }
+ MEM_freeN(drawcache);
+ }
}
/************************ word-wrap utilities *****************************/
@@ -719,217 +751,231 @@ void text_free_caches(SpaceText *st)
/* cache should be updated in caller */
static int text_get_visible_lines_no(const SpaceText *st, int lineno)
{
- const DrawCache *drawcache = st->drawcache;
+ const DrawCache *drawcache = st->drawcache;
- return drawcache->line_height[lineno];
+ return drawcache->line_height[lineno];
}
int text_get_visible_lines(const SpaceText *st, ARegion *ar, const char *str)
{
- int i, j, start, end, max, lines, chars;
- char ch;
-
- max = wrap_width(st, ar);
- lines = 1;
- start = 0;
- end = max;
- for (i = 0, j = 0; str[j]; j += BLI_str_utf8_size_safe(str + j)) {
- int columns = BLI_str_utf8_char_width_safe(str + j); /* = 1 for tab */
-
- /* Mimic replacement of tabs */
- ch = str[j];
- if (ch == '\t') {
- chars = st->tabnumber - i % st->tabnumber;
- ch = ' ';
- }
- else {
- chars = 1;
- }
-
- while (chars--) {
- if (i + columns - start > max) {
- lines++;
- start = MIN2(end, i);
- end += max;
- }
- else if (ch == ' ' || ch == '-') {
- end = i + 1;
- }
-
- i += columns;
- }
- }
-
- return lines;
+ int i, j, start, end, max, lines, chars;
+ char ch;
+
+ max = wrap_width(st, ar);
+ lines = 1;
+ start = 0;
+ end = max;
+ for (i = 0, j = 0; str[j]; j += BLI_str_utf8_size_safe(str + j)) {
+ int columns = BLI_str_utf8_char_width_safe(str + j); /* = 1 for tab */
+
+ /* Mimic replacement of tabs */
+ ch = str[j];
+ if (ch == '\t') {
+ chars = st->tabnumber - i % st->tabnumber;
+ ch = ' ';
+ }
+ else {
+ chars = 1;
+ }
+
+ while (chars--) {
+ if (i + columns - start > max) {
+ lines++;
+ start = MIN2(end, i);
+ end += max;
+ }
+ else if (ch == ' ' || ch == '-') {
+ end = i + 1;
+ }
+
+ i += columns;
+ }
+ }
+
+ return lines;
}
int text_get_span_wrap(const SpaceText *st, ARegion *ar, TextLine *from, TextLine *to)
{
- if (st->wordwrap) {
- int ret = 0;
- TextLine *tmp = from;
-
- /* Look forwards */
- while (tmp) {
- if (tmp == to) return ret;
- ret += text_get_visible_lines(st, ar, tmp->line);
- tmp = tmp->next;
- }
-
- return ret;
- }
- else {
- return txt_get_span(from, to);
- }
+ if (st->wordwrap) {
+ int ret = 0;
+ TextLine *tmp = from;
+
+ /* Look forwards */
+ while (tmp) {
+ if (tmp == to)
+ return ret;
+ ret += text_get_visible_lines(st, ar, tmp->line);
+ tmp = tmp->next;
+ }
+
+ return ret;
+ }
+ else {
+ return txt_get_span(from, to);
+ }
}
int text_get_total_lines(SpaceText *st, ARegion *ar)
{
- DrawCache *drawcache;
+ DrawCache *drawcache;
- text_update_drawcache(st, ar);
- drawcache = st->drawcache;
+ text_update_drawcache(st, ar);
+ drawcache = st->drawcache;
- return drawcache->total_lines;
+ return drawcache->total_lines;
}
/************************ draw scrollbar *****************************/
static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll, rcti *back)
{
- int lhlstart, lhlend, ltexth, sell_off, curl_off;
- short barheight, barstart, hlstart, hlend, blank_lines;
- short pix_available, pix_top_margin, pix_bottom_margin, pix_bardiff;
-
- 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);
- blank_lines = st->viewlines / 2;
-
- /* nicer code: use scroll rect for entire bar */
- back->xmin = ar->winx - (0.6 * U.widget_unit);
- back->xmax = ar->winx;
- back->ymin = 0;
- back->ymax = ar->winy;
-
- scroll->xmax = ar->winx - (0.2 * U.widget_unit);
- scroll->xmin = scroll->xmax - (0.4 * U.widget_unit);
- scroll->ymin = pix_top_margin;
- scroll->ymax = pix_available;
-
- /* when re-sizing a view-port with the bar at the bottom to a greater height
- * more blank lines will be added */
- if (ltexth + blank_lines < st->top + st->viewlines) {
- blank_lines = st->top + st->viewlines - ltexth;
- }
-
- ltexth += blank_lines;
-
- barheight = (ltexth > 0) ? (st->viewlines * pix_available) / ltexth : 0;
- pix_bardiff = 0;
- if (barheight < 20) {
- pix_bardiff = 20 - barheight; /* take into account the now non-linear sizing of the bar */
- barheight = 20;
- }
- barstart = (ltexth > 0) ? ((pix_available - pix_bardiff) * st->top) / ltexth : 0;
-
- st->txtbar = *scroll;
- st->txtbar.ymax -= barstart;
- st->txtbar.ymin = st->txtbar.ymax - barheight;
-
- CLAMP(st->txtbar.ymin, pix_bottom_margin, ar->winy - pix_top_margin);
- CLAMP(st->txtbar.ymax, pix_bottom_margin, ar->winy - pix_top_margin);
-
- st->pix_per_line = (pix_available > 0) ? (float) ltexth / pix_available : 0;
- if (st->pix_per_line < 0.1f) st->pix_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);
- lhlstart = MIN2(curl_off, sell_off);
- lhlend = MAX2(curl_off, sell_off);
-
- if (ltexth > 0) {
- hlstart = (lhlstart * pix_available) / ltexth;
- hlend = (lhlend * pix_available) / ltexth;
-
- /* the scrollbar is non-linear sized */
- if (pix_bardiff > 0) {
- /* the start of the highlight is in the current viewport */
- if (st->viewlines && lhlstart >= st->top && lhlstart <= st->top + st->viewlines) {
- /* speed the progresion of the start of the highlight through the scrollbar */
- hlstart = ( ( (pix_available - pix_bardiff) * lhlstart) / ltexth) + (pix_bardiff * (lhlstart - st->top) / st->viewlines);
- }
- else if (lhlstart > st->top + st->viewlines && hlstart < barstart + barheight && hlstart > barstart) {
- /* push hl start down */
- hlstart = barstart + barheight;
- }
- else if (lhlend > st->top && lhlstart < st->top && hlstart > barstart) {
- /*fill out start */
- hlstart = barstart;
- }
-
- if (hlend <= hlstart) {
- hlend = hlstart + 2;
- }
-
- /* the end of the highlight is in the current viewport */
- if (st->viewlines && lhlend >= st->top && lhlend <= st->top + st->viewlines) {
- /* speed the progresion of the end of the highlight through the scrollbar */
- hlend = (((pix_available - pix_bardiff) * lhlend) / ltexth) + (pix_bardiff * (lhlend - st->top) / st->viewlines);
- }
- else if (lhlend < st->top && hlend >= barstart - 2 && hlend < barstart + barheight) {
- /* push hl end up */
- hlend = barstart;
- }
- else if (lhlend > st->top + st->viewlines && lhlstart < st->top + st->viewlines && hlend < barstart + barheight) {
- /* fill out end */
- hlend = barstart + barheight;
- }
-
- if (hlend <= hlstart) {
- hlstart = hlend - 2;
- }
- }
- }
- else {
- hlstart = 0;
- hlend = 0;
- }
-
- if (hlend - hlstart < 2) {
- hlend = hlstart + 2;
- }
-
- st->txtscroll = *scroll;
- st->txtscroll.ymax = ar->winy - pix_top_margin - hlstart;
- st->txtscroll.ymin = ar->winy - pix_top_margin - hlend;
-
- CLAMP(st->txtscroll.ymin, pix_bottom_margin, ar->winy - pix_top_margin);
- CLAMP(st->txtscroll.ymax, pix_bottom_margin, ar->winy - pix_top_margin);
+ int lhlstart, lhlend, ltexth, sell_off, curl_off;
+ short barheight, barstart, hlstart, hlend, blank_lines;
+ short pix_available, pix_top_margin, pix_bottom_margin, pix_bardiff;
+
+ 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);
+ blank_lines = st->viewlines / 2;
+
+ /* nicer code: use scroll rect for entire bar */
+ back->xmin = ar->winx - (0.6 * U.widget_unit);
+ back->xmax = ar->winx;
+ back->ymin = 0;
+ back->ymax = ar->winy;
+
+ scroll->xmax = ar->winx - (0.2 * U.widget_unit);
+ scroll->xmin = scroll->xmax - (0.4 * U.widget_unit);
+ scroll->ymin = pix_top_margin;
+ scroll->ymax = pix_available;
+
+ /* when re-sizing a view-port with the bar at the bottom to a greater height
+ * more blank lines will be added */
+ if (ltexth + blank_lines < st->top + st->viewlines) {
+ blank_lines = st->top + st->viewlines - ltexth;
+ }
+
+ ltexth += blank_lines;
+
+ barheight = (ltexth > 0) ? (st->viewlines * pix_available) / ltexth : 0;
+ pix_bardiff = 0;
+ if (barheight < 20) {
+ pix_bardiff = 20 - barheight; /* take into account the now non-linear sizing of the bar */
+ barheight = 20;
+ }
+ barstart = (ltexth > 0) ? ((pix_available - pix_bardiff) * st->top) / ltexth : 0;
+
+ st->txtbar = *scroll;
+ st->txtbar.ymax -= barstart;
+ st->txtbar.ymin = st->txtbar.ymax - barheight;
+
+ CLAMP(st->txtbar.ymin, pix_bottom_margin, ar->winy - pix_top_margin);
+ CLAMP(st->txtbar.ymax, pix_bottom_margin, ar->winy - pix_top_margin);
+
+ st->pix_per_line = (pix_available > 0) ? (float)ltexth / pix_available : 0;
+ if (st->pix_per_line < 0.1f)
+ st->pix_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);
+ lhlstart = MIN2(curl_off, sell_off);
+ lhlend = MAX2(curl_off, sell_off);
+
+ if (ltexth > 0) {
+ hlstart = (lhlstart * pix_available) / ltexth;
+ hlend = (lhlend * pix_available) / ltexth;
+
+ /* the scrollbar is non-linear sized */
+ if (pix_bardiff > 0) {
+ /* the start of the highlight is in the current viewport */
+ if (st->viewlines && lhlstart >= st->top && lhlstart <= st->top + st->viewlines) {
+ /* speed the progresion of the start of the highlight through the scrollbar */
+ hlstart = (((pix_available - pix_bardiff) * lhlstart) / ltexth) +
+ (pix_bardiff * (lhlstart - st->top) / st->viewlines);
+ }
+ else if (lhlstart > st->top + st->viewlines && hlstart < barstart + barheight &&
+ hlstart > barstart) {
+ /* push hl start down */
+ hlstart = barstart + barheight;
+ }
+ else if (lhlend > st->top && lhlstart < st->top && hlstart > barstart) {
+ /*fill out start */
+ hlstart = barstart;
+ }
+
+ if (hlend <= hlstart) {
+ hlend = hlstart + 2;
+ }
+
+ /* the end of the highlight is in the current viewport */
+ if (st->viewlines && lhlend >= st->top && lhlend <= st->top + st->viewlines) {
+ /* speed the progresion of the end of the highlight through the scrollbar */
+ hlend = (((pix_available - pix_bardiff) * lhlend) / ltexth) +
+ (pix_bardiff * (lhlend - st->top) / st->viewlines);
+ }
+ else if (lhlend < st->top && hlend >= barstart - 2 && hlend < barstart + barheight) {
+ /* push hl end up */
+ hlend = barstart;
+ }
+ else if (lhlend > st->top + st->viewlines && lhlstart < st->top + st->viewlines &&
+ hlend < barstart + barheight) {
+ /* fill out end */
+ hlend = barstart + barheight;
+ }
+
+ if (hlend <= hlstart) {
+ hlstart = hlend - 2;
+ }
+ }
+ }
+ else {
+ hlstart = 0;
+ hlend = 0;
+ }
+
+ if (hlend - hlstart < 2) {
+ hlend = hlstart + 2;
+ }
+
+ st->txtscroll = *scroll;
+ st->txtscroll.ymax = ar->winy - pix_top_margin - hlstart;
+ st->txtscroll.ymin = ar->winy - pix_top_margin - hlend;
+
+ CLAMP(st->txtscroll.ymin, pix_bottom_margin, ar->winy - pix_top_margin);
+ CLAMP(st->txtscroll.ymax, pix_bottom_margin, ar->winy - pix_top_margin);
}
static void draw_textscroll(const SpaceText *st, rcti *scroll, rcti *back)
{
- bTheme *btheme = UI_GetTheme();
- uiWidgetColors wcol = btheme->tui.wcol_scroll;
- float col[4];
- float rad;
-
- /* background so highlights don't go behind the scrollbar */
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor(TH_BACK);
- immRecti(pos, back->xmin, back->ymin, back->xmax, back->ymax);
- immUnbindProgram();
-
- UI_draw_widget_scroll(&wcol, scroll, &st->txtbar, (st->flags & ST_SCROLL_SELECT) ? UI_SCROLL_PRESSED : 0);
-
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- rad = 0.4f * min_ii(BLI_rcti_size_x(&st->txtscroll), BLI_rcti_size_y(&st->txtscroll));
- UI_GetThemeColor3fv(TH_HILITE, col);
- col[3] = 0.18f;
- UI_draw_roundbox_aa(true, st->txtscroll.xmin + 1, st->txtscroll.ymin, st->txtscroll.xmax - 1, st->txtscroll.ymax, rad, col);
+ bTheme *btheme = UI_GetTheme();
+ uiWidgetColors wcol = btheme->tui.wcol_scroll;
+ float col[4];
+ float rad;
+
+ /* background so highlights don't go behind the scrollbar */
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_BACK);
+ immRecti(pos, back->xmin, back->ymin, back->xmax, back->ymax);
+ immUnbindProgram();
+
+ UI_draw_widget_scroll(
+ &wcol, scroll, &st->txtbar, (st->flags & ST_SCROLL_SELECT) ? UI_SCROLL_PRESSED : 0);
+
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ rad = 0.4f * min_ii(BLI_rcti_size_x(&st->txtscroll), BLI_rcti_size_y(&st->txtscroll));
+ UI_GetThemeColor3fv(TH_HILITE, col);
+ col[3] = 0.18f;
+ UI_draw_roundbox_aa(true,
+ st->txtscroll.xmin + 1,
+ st->txtscroll.ymin,
+ st->txtscroll.xmax - 1,
+ st->txtscroll.ymax,
+ rad,
+ col);
}
/*********************** draw documentation *******************************/
@@ -937,92 +983,92 @@ static void draw_textscroll(const SpaceText *st, rcti *scroll, rcti *back)
#if 0
static void draw_documentation(const SpaceText *st, ARegion *ar)
{
- TextDrawContext tdc = {0};
- TextLine *tmp;
- char *docs, buf[DOC_WIDTH + 1], *p;
- int i, br, lines;
- int boxw, boxh, l, x, y /* , top */ /* UNUSED */;
-
- if (!st || !st->text) return;
- if (!texttool_text_is_active(st->text)) return;
-
- docs = texttool_docs_get();
-
- if (!docs) return;
-
- text_draw_context_init(st, &tdc);
-
- /* Count the visible lines to the cursor */
- for (tmp = st->text->curl, l = -st->top; tmp; tmp = tmp->prev, l++) ;
- if (l < 0) return;
-
- if (st->showlinenrs) {
- x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET + TEXTXLOC - 4;
- }
- else {
- x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET - 4;
- }
- if (texttool_suggest_first()) {
- x += SUGG_LIST_WIDTH * st->cwidth + 50;
- }
-
- /* top = */ /* UNUSED */ y = ar->winy - st->lheight_dpi * l - 2;
- boxw = DOC_WIDTH * st->cwidth + 20;
- boxh = (DOC_HEIGHT + 1) * (st->lheight_dpi + TXT_LINE_SPACING);
-
- /* Draw panel */
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- immUniformThemeColor(TH_BACK);
- immRecti(pos, x, y, x + boxw, y - boxh);
- immUniformThemeColor(TH_SHADE1);
- immBegin(GPU_PRIM_LINE_LOOP, 4);
- immVertex2i(pos, x, y);
- immVertex2i(pos, x + boxw, y);
- immVertex2i(pos, x + boxw, y - boxh);
- immVertex2i(pos, x, y - boxh);
- immEnd();
- immBegin(GPU_PRIM_LINE_LOOP, 3);
- immVertex2i(pos, x + boxw - 10, y - 7);
- immVertex2i(pos, x + boxw - 4, y - 7);
- immVertex2i(pos, x + boxw - 7, y - 2);
- immEnd();
- immBegin(GPU_PRIM_LINE_LOOP, 3);
- immVertex2i(pos, x + boxw - 10, y - boxh + 7);
- immVertex2i(pos, x + boxw - 4, y - boxh + 7);
- immVertex2i(pos, x + boxw - 7, y - boxh + 2);
- immEnd();
-
- immUnbindProgram();
-
- UI_FontThemeColor(tdc.font_id, TH_TEXT);
-
- i = 0; br = DOC_WIDTH; lines = 0; // XXX -doc_scroll;
- for (p = docs; *p; p++) {
- if (*p == '\r' && *(++p) != '\n') *(--p) = '\n'; /* Fix line endings */
- if (*p == ' ' || *p == '\t')
- br = i;
- else if (*p == '\n') {
- buf[i] = '\0';
- if (lines >= 0) {
- y -= st->lheight_dpi;
- text_draw(st, &tdc, buf, 0, 0, x + 4, y - 3, NULL);
- }
- i = 0; br = DOC_WIDTH; lines++;
- }
- buf[i++] = *p;
- if (i == DOC_WIDTH) { /* Reached the width, go to last break and wrap there */
- buf[br] = '\0';
- if (lines >= 0) {
- y -= st->lheight_dpi;
- text_draw(st, &tdc, buf, 0, 0, x + 4, y - 3, NULL);
- }
- p -= i - br - 1; /* Rewind pointer to last break */
- i = 0; br = DOC_WIDTH; lines++;
- }
- if (lines >= DOC_HEIGHT) break;
- }
+ TextDrawContext tdc = {0};
+ TextLine *tmp;
+ char *docs, buf[DOC_WIDTH + 1], *p;
+ int i, br, lines;
+ int boxw, boxh, l, x, y /* , top */ /* UNUSED */;
+
+ if (!st || !st->text) return;
+ if (!texttool_text_is_active(st->text)) return;
+
+ docs = texttool_docs_get();
+
+ if (!docs) return;
+
+ text_draw_context_init(st, &tdc);
+
+ /* Count the visible lines to the cursor */
+ for (tmp = st->text->curl, l = -st->top; tmp; tmp = tmp->prev, l++) ;
+ if (l < 0) return;
+
+ if (st->showlinenrs) {
+ x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET + TEXTXLOC - 4;
+ }
+ else {
+ x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET - 4;
+ }
+ if (texttool_suggest_first()) {
+ x += SUGG_LIST_WIDTH * st->cwidth + 50;
+ }
+
+ /* top = */ /* UNUSED */ y = ar->winy - st->lheight_dpi * l - 2;
+ boxw = DOC_WIDTH * st->cwidth + 20;
+ boxh = (DOC_HEIGHT + 1) * (st->lheight_dpi + TXT_LINE_SPACING);
+
+ /* Draw panel */
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformThemeColor(TH_BACK);
+ immRecti(pos, x, y, x + boxw, y - boxh);
+ immUniformThemeColor(TH_SHADE1);
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
+ immVertex2i(pos, x, y);
+ immVertex2i(pos, x + boxw, y);
+ immVertex2i(pos, x + boxw, y - boxh);
+ immVertex2i(pos, x, y - boxh);
+ immEnd();
+ immBegin(GPU_PRIM_LINE_LOOP, 3);
+ immVertex2i(pos, x + boxw - 10, y - 7);
+ immVertex2i(pos, x + boxw - 4, y - 7);
+ immVertex2i(pos, x + boxw - 7, y - 2);
+ immEnd();
+ immBegin(GPU_PRIM_LINE_LOOP, 3);
+ immVertex2i(pos, x + boxw - 10, y - boxh + 7);
+ immVertex2i(pos, x + boxw - 4, y - boxh + 7);
+ immVertex2i(pos, x + boxw - 7, y - boxh + 2);
+ immEnd();
+
+ immUnbindProgram();
+
+ UI_FontThemeColor(tdc.font_id, TH_TEXT);
+
+ i = 0; br = DOC_WIDTH; lines = 0; // XXX -doc_scroll;
+ for (p = docs; *p; p++) {
+ if (*p == '\r' && *(++p) != '\n') *(--p) = '\n'; /* Fix line endings */
+ if (*p == ' ' || *p == '\t')
+ br = i;
+ else if (*p == '\n') {
+ buf[i] = '\0';
+ if (lines >= 0) {
+ y -= st->lheight_dpi;
+ text_draw(st, &tdc, buf, 0, 0, x + 4, y - 3, NULL);
+ }
+ i = 0; br = DOC_WIDTH; lines++;
+ }
+ buf[i++] = *p;
+ if (i == DOC_WIDTH) { /* Reached the width, go to last break and wrap there */
+ buf[br] = '\0';
+ if (lines >= 0) {
+ y -= st->lheight_dpi;
+ text_draw(st, &tdc, buf, 0, 0, x + 4, y - 3, NULL);
+ }
+ p -= i - br - 1; /* Rewind pointer to last break */
+ i = 0; br = DOC_WIDTH; lines++;
+ }
+ if (lines >= DOC_HEIGHT) break;
+ }
}
#endif
@@ -1030,641 +1076,683 @@ static void draw_documentation(const SpaceText *st, ARegion *ar)
static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc, ARegion *ar)
{
- SuggItem *item, *first, *last, *sel;
- char str[SUGG_LIST_WIDTH * BLI_UTF8_MAX + 1];
- int offl, offc, vcurl, vcurc;
- int w, boxw = 0, boxh, i, x, y, *top;
- const int lheight = st->lheight_dpi + TXT_LINE_SPACING;
- const int margin_x = 2;
+ SuggItem *item, *first, *last, *sel;
+ char str[SUGG_LIST_WIDTH * BLI_UTF8_MAX + 1];
+ int offl, offc, vcurl, vcurc;
+ int w, boxw = 0, boxh, i, x, y, *top;
+ const int lheight = st->lheight_dpi + TXT_LINE_SPACING;
+ const int margin_x = 2;
- if (!st->text) return;
- if (!texttool_text_is_active(st->text)) return;
+ if (!st->text)
+ return;
+ if (!texttool_text_is_active(st->text))
+ return;
- first = texttool_suggest_first();
- last = texttool_suggest_last();
+ first = texttool_suggest_first();
+ last = texttool_suggest_last();
- if (!first || !last) return;
+ if (!first || !last)
+ return;
- text_pop_suggest_list();
- sel = texttool_suggest_selected();
- top = texttool_suggest_top();
+ text_pop_suggest_list();
+ sel = texttool_suggest_selected();
+ top = texttool_suggest_top();
- wrap_offset(st, ar, 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;
+ wrap_offset(st, ar, 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 = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
- x += vcurc * st->cwidth - 4;
- y = ar->winy - (vcurl + 1) * lheight - 2;
+ x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
+ x += vcurc * st->cwidth - 4;
+ y = ar->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 */
- x -= st->cwidth * (st->text->curc - text_find_identifier_start(st->text->curl->line, st->text->curc));
+ /* offset back so the start of the text lines up with the suggestions,
+ * not essential but makes suggestions easier to follow */
+ x -= st->cwidth *
+ (st->text->curc - text_find_identifier_start(st->text->curl->line, st->text->curc));
- boxw = SUGG_LIST_WIDTH * st->cwidth + 20;
- boxh = SUGG_LIST_SIZE * lheight + 8;
+ boxw = SUGG_LIST_WIDTH * st->cwidth + 20;
+ boxh = SUGG_LIST_SIZE * lheight + 8;
- if (x + boxw > ar->winx)
- x = MAX2(0, ar->winx - boxw);
+ if (x + boxw > ar->winx)
+ x = MAX2(0, ar->winx - boxw);
- /* not needed but stands out nicer */
- UI_draw_box_shadow(220, x, y - boxh, x + boxw, y);
+ /* not needed but stands out nicer */
+ UI_draw_box_shadow(220, x, y - boxh, x + boxw, y);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor(TH_SHADE1);
- immRecti(pos, x - 1, y + 1, x + boxw + 1, y - boxh - 1);
- immUniformThemeColorShade(TH_BACK, 16);
- immRecti(pos, x, y, x + boxw, y - boxh);
+ immUniformThemeColor(TH_SHADE1);
+ immRecti(pos, x - 1, y + 1, x + boxw + 1, y - boxh - 1);
+ immUniformThemeColorShade(TH_BACK, 16);
+ immRecti(pos, x, y, x + boxw, y - boxh);
- immUnbindProgram();
+ immUnbindProgram();
- /* Set the top 'item' of the visible list */
- for (i = 0, item = first; i < *top && item->next; i++, item = item->next) ;
+ /* Set the top 'item' of the visible list */
+ for (i = 0, item = first; i < *top && item->next; i++, item = item->next)
+ ;
- for (i = 0; i < SUGG_LIST_SIZE && item; i++, item = item->next) {
- int len = txt_utf8_forward_columns(item->name, SUGG_LIST_WIDTH, NULL) - item->name;
+ for (i = 0; i < SUGG_LIST_SIZE && item; i++, item = item->next) {
+ int len = txt_utf8_forward_columns(item->name, SUGG_LIST_WIDTH, NULL) - item->name;
- y -= lheight;
+ y -= lheight;
- BLI_strncpy(str, item->name, len + 1);
+ BLI_strncpy(str, item->name, len + 1);
- w = st->cwidth * text_get_char_pos(st, str, len);
+ w = st->cwidth * text_get_char_pos(st, str, len);
- if (item == sel) {
- uint posi = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ if (item == sel) {
+ uint posi = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor(TH_SHADE2);
- immRecti(posi, x + margin_x, y - 3, x + margin_x + w, y + lheight - 3);
+ immUniformThemeColor(TH_SHADE2);
+ immRecti(posi, x + margin_x, y - 3, x + margin_x + w, y + lheight - 3);
- immUnbindProgram();
- }
+ immUnbindProgram();
+ }
- format_draw_color(tdc, item->type);
- text_draw(st, tdc, str, 0, 0, x + margin_x, y - 1, NULL);
+ format_draw_color(tdc, item->type);
+ text_draw(st, tdc, str, 0, 0, x + margin_x, y - 1, NULL);
- if (item == last) break;
- }
+ if (item == last)
+ break;
+ }
}
/*********************** draw cursor ************************/
static void draw_text_decoration(SpaceText *st, ARegion *ar)
{
- Text *text = st->text;
- int vcurl, vcurc, vsell, vselc, hidden = 0;
- int x, y, w, i;
- int offl, offc;
- const int lheight = st->lheight_dpi + TXT_LINE_SPACING;
-
- /* Convert to view space character coordinates to determine if cursor is hidden */
- wrap_offset(st, ar, 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;
-
- if (vselc < 0) {
- vselc = 0;
- hidden = 1;
- }
-
- if (text->curl == text->sell && text->curc == text->selc && !st->line_hlight && hidden) {
- /* Nothing to draw here */
- return;
- }
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* 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);
- 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;
-
- if (vcurc < 0) {
- vcurc = 0;
- }
-
- immUniformThemeColor(TH_SHADE2);
-
- x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
- y = ar->winy;
-
- if (vcurl == vsell) {
- y -= vcurl * lheight;
-
- if (vcurc < vselc) {
- immRecti(pos, x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - lheight);
- }
- else {
- immRecti(pos, x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - lheight);
- }
- }
- else {
- int froml, fromc, tol, toc;
-
- if (vcurl < vsell) {
- froml = vcurl; tol = vsell;
- fromc = vcurc; toc = vselc;
- }
- else {
- froml = vsell; tol = vcurl;
- fromc = vselc; toc = vcurc;
- }
-
- y -= froml * lheight;
-
- immRecti(pos, x + fromc * st->cwidth - 1, y, ar->winx, y - lheight);
- y -= lheight;
-
- for (i = froml + 1; i < tol; i++) {
- immRecti(pos, x - 4, y, ar->winx, y - lheight);
- y -= lheight;
- }
-
- immRecti(pos, x - 4, y, x + toc * st->cwidth, y - lheight);
- y -= lheight;
- }
- }
-
- if (st->line_hlight) {
- int x1, x2, y1, y2;
-
- if (st->wordwrap) {
- int visible_lines = text_get_visible_lines(st, ar, text->sell->line);
-
- wrap_offset_in_line(st, ar, text->sell, text->selc, &offl, &offc);
-
- y1 = ar->winy - (vsell - offl) * lheight;
- y2 = y1 - (lheight * visible_lines);
- }
- else {
- y1 = ar->winy - vsell * lheight;
- y2 = y1 - (lheight);
- }
-
- if (!(y1 < 0 || y2 > ar->winy)) { /* check we need to draw */
- x1 = 0; // st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
- x2 = x1 + ar->winx;
-
- immUniformColor4ub(255, 255, 255, 32);
-
- 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, x1 - 4, y1, x2, y2);
- GPU_blend(false);
- }
- }
-
- if (!hidden) {
- /* Draw the cursor itself (we draw the sel. cursor as this is the leading edge) */
- x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
- x += vselc * st->cwidth;
- y = ar->winy - vsell * lheight;
-
- immUniformThemeColor(TH_HILITE);
-
- if (st->overwrite) {
- char ch = text->sell->line[text->selc];
-
- y += TXT_LINE_SPACING;
- w = st->cwidth;
- if (ch == '\t') w *= st->tabnumber - (vselc + st->left) % st->tabnumber;
-
- immRecti(pos, x, y - lheight - 1, x + w, y - lheight + 1);
- }
- else {
- immRecti(pos, x - 1, y, x + 1, y - lheight);
- }
- }
-
- immUnbindProgram();
+ Text *text = st->text;
+ int vcurl, vcurc, vsell, vselc, hidden = 0;
+ int x, y, w, i;
+ int offl, offc;
+ const int lheight = st->lheight_dpi + TXT_LINE_SPACING;
+
+ /* Convert to view space character coordinates to determine if cursor is hidden */
+ wrap_offset(st, ar, 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;
+
+ if (vselc < 0) {
+ vselc = 0;
+ hidden = 1;
+ }
+
+ if (text->curl == text->sell && text->curc == text->selc && !st->line_hlight && hidden) {
+ /* Nothing to draw here */
+ return;
+ }
+
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* 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);
+ 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;
+
+ if (vcurc < 0) {
+ vcurc = 0;
+ }
+
+ immUniformThemeColor(TH_SHADE2);
+
+ x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
+ y = ar->winy;
+
+ if (vcurl == vsell) {
+ y -= vcurl * lheight;
+
+ if (vcurc < vselc) {
+ immRecti(pos, x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - lheight);
+ }
+ else {
+ immRecti(pos, x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - lheight);
+ }
+ }
+ else {
+ int froml, fromc, tol, toc;
+
+ if (vcurl < vsell) {
+ froml = vcurl;
+ tol = vsell;
+ fromc = vcurc;
+ toc = vselc;
+ }
+ else {
+ froml = vsell;
+ tol = vcurl;
+ fromc = vselc;
+ toc = vcurc;
+ }
+
+ y -= froml * lheight;
+
+ immRecti(pos, x + fromc * st->cwidth - 1, y, ar->winx, y - lheight);
+ y -= lheight;
+
+ for (i = froml + 1; i < tol; i++) {
+ immRecti(pos, x - 4, y, ar->winx, y - lheight);
+ y -= lheight;
+ }
+
+ immRecti(pos, x - 4, y, x + toc * st->cwidth, y - lheight);
+ y -= lheight;
+ }
+ }
+
+ if (st->line_hlight) {
+ int x1, x2, y1, y2;
+
+ if (st->wordwrap) {
+ int visible_lines = text_get_visible_lines(st, ar, text->sell->line);
+
+ wrap_offset_in_line(st, ar, text->sell, text->selc, &offl, &offc);
+
+ y1 = ar->winy - (vsell - offl) * lheight;
+ y2 = y1 - (lheight * visible_lines);
+ }
+ else {
+ y1 = ar->winy - vsell * lheight;
+ y2 = y1 - (lheight);
+ }
+
+ if (!(y1 < 0 || y2 > ar->winy)) { /* check we need to draw */
+ x1 = 0; // st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
+ x2 = x1 + ar->winx;
+
+ immUniformColor4ub(255, 255, 255, 32);
+
+ 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, x1 - 4, y1, x2, y2);
+ GPU_blend(false);
+ }
+ }
+
+ if (!hidden) {
+ /* Draw the cursor itself (we draw the sel. cursor as this is the leading edge) */
+ x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
+ x += vselc * st->cwidth;
+ y = ar->winy - vsell * lheight;
+
+ immUniformThemeColor(TH_HILITE);
+
+ if (st->overwrite) {
+ char ch = text->sell->line[text->selc];
+
+ y += TXT_LINE_SPACING;
+ w = st->cwidth;
+ if (ch == '\t')
+ w *= st->tabnumber - (vselc + st->left) % st->tabnumber;
+
+ immRecti(pos, x, y - lheight - 1, x + w, y - lheight + 1);
+ }
+ else {
+ immRecti(pos, x - 1, y, x + 1, y - lheight);
+ }
+ }
+
+ immUnbindProgram();
}
/******************* draw matching brackets *********************/
static void draw_brackets(const SpaceText *st, const TextDrawContext *tdc, ARegion *ar)
{
- TextLine *startl, *endl, *linep;
- Text *text = st->text;
- int b, fc, find, stack, viewc, viewl, offl, offc, x, y;
- int startc, endc, c;
-
- char ch;
-
- // showsyntax must be on or else the format string will be null
- if (!text->curl || !st->showsyntax) return;
-
- startl = text->curl;
- startc = text->curc;
- b = text_check_bracket(startl->line[startc]);
- if (b == 0 && startc > 0) b = text_check_bracket(startl->line[--startc]);
- if (b == 0) return;
-
- linep = startl;
- c = startc;
- fc = txt_utf8_offset_to_index(linep->line, startc);
- endl = NULL;
- endc = -1;
- find = -b;
- stack = 0;
-
- /* Don't highlight backets if syntax HL is off or bracket in string or comment. */
- if (!linep->format || linep->format[fc] == FMT_TYPE_STRING || linep->format[fc] == FMT_TYPE_COMMENT)
- return;
-
- if (b > 0) {
- /* opening bracket, search forward for close */
- fc++;
- c += BLI_str_utf8_size_safe(linep->line + c);
- while (linep) {
- while (c < linep->len) {
- if (linep->format && linep->format[fc] != FMT_TYPE_STRING && linep->format[fc] != FMT_TYPE_COMMENT) {
- b = text_check_bracket(linep->line[c]);
- if (b == find) {
- if (stack == 0) {
- endl = linep;
- endc = c;
- break;
- }
- stack--;
- }
- else if (b == -find) {
- stack++;
- }
- }
- fc++;
- c += BLI_str_utf8_size_safe(linep->line + c);
- }
- if (endl) break;
- linep = linep->next;
- c = 0;
- fc = 0;
- }
- }
- else {
- /* closing bracket, search backward for open */
- fc--;
- if (c > 0) c -= linep->line + c - BLI_str_prev_char_utf8(linep->line + c);
- while (linep) {
- while (fc >= 0) {
- if (linep->format && linep->format[fc] != FMT_TYPE_STRING && linep->format[fc] != FMT_TYPE_COMMENT) {
- b = text_check_bracket(linep->line[c]);
- if (b == find) {
- if (stack == 0) {
- endl = linep;
- endc = c;
- break;
- }
- stack--;
- }
- else if (b == -find) {
- stack++;
- }
- }
- fc--;
- if (c > 0) c -= linep->line + c - BLI_str_prev_char_utf8(linep->line + c);
- }
- if (endl) break;
- linep = linep->prev;
- if (linep) {
- if (linep->format) fc = strlen(linep->format) - 1;
- else fc = -1;
- if (linep->len) c = BLI_str_prev_char_utf8(linep->line + linep->len) - linep->line;
- else fc = -1;
- }
- }
- }
-
- if (!endl || endc == -1)
- return;
-
- UI_FontThemeColor(tdc->font_id, TH_HILITE);
- x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
- y = ar->winy - st->lheight_dpi;
-
- /* draw opening bracket */
- ch = startl->line[startc];
- wrap_offset(st, ar, startl, startc, &offl, &offc);
- viewc = text_get_char_pos(st, startl->line, startc) - st->left + offc;
-
- if (viewc >= 0) {
- viewl = txt_get_span(text->lines.first, startl) - st->top + offl;
-
- text_font_draw_character(tdc, x + viewc * st->cwidth, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
- text_font_draw_character(tdc, x + viewc * st->cwidth + 1, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
- }
-
- /* draw closing bracket */
- ch = endl->line[endc];
- wrap_offset(st, ar, endl, endc, &offl, &offc);
- viewc = text_get_char_pos(st, endl->line, endc) - st->left + offc;
-
- if (viewc >= 0) {
- viewl = txt_get_span(text->lines.first, endl) - st->top + offl;
-
- text_font_draw_character(tdc, x + viewc * st->cwidth, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
- text_font_draw_character(tdc, x + viewc * st->cwidth + 1, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
- }
+ TextLine *startl, *endl, *linep;
+ Text *text = st->text;
+ int b, fc, find, stack, viewc, viewl, offl, offc, x, y;
+ int startc, endc, c;
+
+ char ch;
+
+ // showsyntax must be on or else the format string will be null
+ if (!text->curl || !st->showsyntax)
+ return;
+
+ startl = text->curl;
+ startc = text->curc;
+ b = text_check_bracket(startl->line[startc]);
+ if (b == 0 && startc > 0)
+ b = text_check_bracket(startl->line[--startc]);
+ if (b == 0)
+ return;
+
+ linep = startl;
+ c = startc;
+ fc = txt_utf8_offset_to_index(linep->line, startc);
+ endl = NULL;
+ endc = -1;
+ find = -b;
+ stack = 0;
+
+ /* Don't highlight backets if syntax HL is off or bracket in string or comment. */
+ if (!linep->format || linep->format[fc] == FMT_TYPE_STRING ||
+ linep->format[fc] == FMT_TYPE_COMMENT)
+ return;
+
+ if (b > 0) {
+ /* opening bracket, search forward for close */
+ fc++;
+ c += BLI_str_utf8_size_safe(linep->line + c);
+ while (linep) {
+ while (c < linep->len) {
+ if (linep->format && linep->format[fc] != FMT_TYPE_STRING &&
+ linep->format[fc] != FMT_TYPE_COMMENT) {
+ b = text_check_bracket(linep->line[c]);
+ if (b == find) {
+ if (stack == 0) {
+ endl = linep;
+ endc = c;
+ break;
+ }
+ stack--;
+ }
+ else if (b == -find) {
+ stack++;
+ }
+ }
+ fc++;
+ c += BLI_str_utf8_size_safe(linep->line + c);
+ }
+ if (endl)
+ break;
+ linep = linep->next;
+ c = 0;
+ fc = 0;
+ }
+ }
+ else {
+ /* closing bracket, search backward for open */
+ fc--;
+ if (c > 0)
+ c -= linep->line + c - BLI_str_prev_char_utf8(linep->line + c);
+ while (linep) {
+ while (fc >= 0) {
+ if (linep->format && linep->format[fc] != FMT_TYPE_STRING &&
+ linep->format[fc] != FMT_TYPE_COMMENT) {
+ b = text_check_bracket(linep->line[c]);
+ if (b == find) {
+ if (stack == 0) {
+ endl = linep;
+ endc = c;
+ break;
+ }
+ stack--;
+ }
+ else if (b == -find) {
+ stack++;
+ }
+ }
+ fc--;
+ if (c > 0)
+ c -= linep->line + c - BLI_str_prev_char_utf8(linep->line + c);
+ }
+ if (endl)
+ break;
+ linep = linep->prev;
+ if (linep) {
+ if (linep->format)
+ fc = strlen(linep->format) - 1;
+ else
+ fc = -1;
+ if (linep->len)
+ c = BLI_str_prev_char_utf8(linep->line + linep->len) - linep->line;
+ else
+ fc = -1;
+ }
+ }
+ }
+
+ if (!endl || endc == -1)
+ return;
+
+ UI_FontThemeColor(tdc->font_id, TH_HILITE);
+ x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
+ y = ar->winy - st->lheight_dpi;
+
+ /* draw opening bracket */
+ ch = startl->line[startc];
+ wrap_offset(st, ar, startl, startc, &offl, &offc);
+ viewc = text_get_char_pos(st, startl->line, startc) - st->left + offc;
+
+ if (viewc >= 0) {
+ viewl = txt_get_span(text->lines.first, startl) - st->top + offl;
+
+ text_font_draw_character(
+ tdc, x + viewc * st->cwidth, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
+ text_font_draw_character(
+ tdc, x + viewc * st->cwidth + 1, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
+ }
+
+ /* draw closing bracket */
+ ch = endl->line[endc];
+ wrap_offset(st, ar, endl, endc, &offl, &offc);
+ viewc = text_get_char_pos(st, endl->line, endc) - st->left + offc;
+
+ if (viewc >= 0) {
+ viewl = txt_get_span(text->lines.first, endl) - st->top + offl;
+
+ text_font_draw_character(
+ tdc, x + viewc * st->cwidth, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
+ text_font_draw_character(
+ tdc, x + viewc * st->cwidth + 1, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
+ }
}
/*********************** main region drawing *************************/
void draw_text_main(SpaceText *st, ARegion *ar)
{
- TextDrawContext tdc = {0};
- Text *text = st->text;
- TextFormatType *tft;
- TextLine *tmp;
- rcti scroll, back;
- char linenr[12];
- int i, x, y, winx, linecount = 0, lineno = 0;
- int wraplinecount = 0, wrap_skip = 0;
- int margin_column_x;
-
- /* if no text, nothing to do */
- if (!text)
- return;
-
- /* dpi controlled line height and font size */
- st->lheight_dpi = (U.widget_unit * st->lheight) / 20;
-
- /* don't draw lines below this */
- const int clip_min_y = -(int)(st->lheight_dpi - 1);
-
- st->viewlines = (st->lheight_dpi) ? (int)(ar->winy - clip_min_y) / (st->lheight_dpi + TXT_LINE_SPACING) : 0;
-
- text_draw_context_init(st, &tdc);
-
- text_update_drawcache(st, ar);
-
- /* make sure all the positional pointers exist */
- if (!text->curl || !text->sell || !text->lines.first || !text->lines.last)
- txt_clean_text(text);
-
- /* update rects for scroll */
- calc_text_rcts(st, ar, &scroll, &back); /* scroll will hold the entire bar size */
-
- /* update syntax formatting if needed */
- tft = ED_text_format_get(text);
- tmp = text->lines.first;
- lineno = 0;
- for (i = 0; i < st->top && tmp; i++) {
- if (st->showsyntax && !tmp->format)
- tft->format_line(st, tmp, false);
-
- if (st->wordwrap) {
- int lines = text_get_visible_lines_no(st, lineno);
-
- if (wraplinecount + lines > st->top) {
- wrap_skip = st->top - wraplinecount;
- break;
- }
- else {
- wraplinecount += lines;
- tmp = tmp->next;
- linecount++;
- }
- }
- else {
- tmp = tmp->next;
- linecount++;
- }
-
- lineno++;
- }
-
-
- text_font_begin(&tdc);
-
- tdc.cwidth = max_ii((int)BLF_fixed_width(tdc.font_id), 1);
- st->cwidth = tdc.cwidth;
-
- /* draw line numbers background */
- if (st->showlinenrs) {
- x = TXT_OFFSET + TEXTXLOC;
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor(TH_GRID);
- immRecti(pos, (TXT_OFFSET - 12), 0, (TXT_OFFSET - 5) + TEXTXLOC, ar->winy - 2);
- immUnbindProgram();
- }
- else {
- st->linenrs_tot = 0; /* not used */
- x = TXT_OFFSET;
- }
- y = ar->winy - st->lheight_dpi;
- winx = ar->winx - TXT_SCROLL_WIDTH;
-
- /* draw cursor, margin, selection and highlight */
- draw_text_decoration(st, ar);
-
- /* draw the text */
- UI_FontThemeColor(tdc.font_id, TH_TEXT);
-
- for (i = 0; y > clip_min_y && i < st->viewlines && tmp; i++, tmp = tmp->next) {
- if (st->showsyntax && !tmp->format)
- tft->format_line(st, tmp, false);
-
- if (st->showlinenrs && !wrap_skip) {
- /* draw line number */
- if (tmp == text->curl) {
- UI_FontThemeColor(tdc.font_id, TH_HILITE);
- }
- else {
- UI_FontThemeColor(tdc.font_id, TH_TEXT);
- }
-
- BLI_snprintf(linenr, sizeof(linenr), "%*d", st->linenrs_tot, i + linecount + 1);
- /* itoa(i + linecount + 1, linenr, 10); */ /* not ansi-c :/ */
- text_font_draw(&tdc, TXT_OFFSET - 7, y, linenr);
-
- if (tmp == text->curl) {
- UI_FontThemeColor(tdc.font_id, TH_TEXT);
- }
- }
-
- if (st->wordwrap) {
- /* draw word wrapped text */
- int lines = text_draw_wrapped(st, &tdc, tmp->line, x, y, winx - x, tmp->format, wrap_skip);
- y -= lines * (st->lheight_dpi + TXT_LINE_SPACING);
- }
- else {
- /* draw unwrapped text */
- text_draw(st, &tdc, tmp->line, st->left, ar->winx / st->cwidth, x, y, tmp->format);
- y -= st->lheight_dpi + TXT_LINE_SPACING;
- }
-
- wrap_skip = 0;
- }
-
- if (st->flags & ST_SHOW_MARGIN) {
- margin_column_x = x + st->cwidth * (st->margin_column - st->left);
-
- if (margin_column_x >= x) {
- const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
-
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
-
- immUniform1i("colors_len", 0); /* "simple" mode */
- immUniformThemeColor(TH_GRID); /* same color as line number background */
- immUniform1f("dash_width", 2.0f);
- immUniform1f("dash_factor", 0.5f);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2i(shdr_pos, margin_column_x, 0);
- immVertex2i(shdr_pos, margin_column_x, ar->winy - 2);
- immEnd();
- immUnbindProgram();
- }
- }
-
- /* draw other stuff */
- draw_brackets(st, &tdc, ar);
- draw_textscroll(st, &scroll, &back);
- /* draw_documentation(st, ar); - No longer supported */
- draw_suggestion_list(st, &tdc, ar);
-
- text_font_end(&tdc);
+ TextDrawContext tdc = {0};
+ Text *text = st->text;
+ TextFormatType *tft;
+ TextLine *tmp;
+ rcti scroll, back;
+ char linenr[12];
+ int i, x, y, winx, linecount = 0, lineno = 0;
+ int wraplinecount = 0, wrap_skip = 0;
+ int margin_column_x;
+
+ /* if no text, nothing to do */
+ if (!text)
+ return;
+
+ /* dpi controlled line height and font size */
+ st->lheight_dpi = (U.widget_unit * st->lheight) / 20;
+
+ /* don't draw lines below this */
+ const int clip_min_y = -(int)(st->lheight_dpi - 1);
+
+ st->viewlines = (st->lheight_dpi) ?
+ (int)(ar->winy - clip_min_y) / (st->lheight_dpi + TXT_LINE_SPACING) :
+ 0;
+
+ text_draw_context_init(st, &tdc);
+
+ text_update_drawcache(st, ar);
+
+ /* make sure all the positional pointers exist */
+ if (!text->curl || !text->sell || !text->lines.first || !text->lines.last)
+ txt_clean_text(text);
+
+ /* update rects for scroll */
+ calc_text_rcts(st, ar, &scroll, &back); /* scroll will hold the entire bar size */
+
+ /* update syntax formatting if needed */
+ tft = ED_text_format_get(text);
+ tmp = text->lines.first;
+ lineno = 0;
+ for (i = 0; i < st->top && tmp; i++) {
+ if (st->showsyntax && !tmp->format)
+ tft->format_line(st, tmp, false);
+
+ if (st->wordwrap) {
+ int lines = text_get_visible_lines_no(st, lineno);
+
+ if (wraplinecount + lines > st->top) {
+ wrap_skip = st->top - wraplinecount;
+ break;
+ }
+ else {
+ wraplinecount += lines;
+ tmp = tmp->next;
+ linecount++;
+ }
+ }
+ else {
+ tmp = tmp->next;
+ linecount++;
+ }
+
+ lineno++;
+ }
+
+ text_font_begin(&tdc);
+
+ tdc.cwidth = max_ii((int)BLF_fixed_width(tdc.font_id), 1);
+ st->cwidth = tdc.cwidth;
+
+ /* draw line numbers background */
+ if (st->showlinenrs) {
+ x = TXT_OFFSET + TEXTXLOC;
+
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_GRID);
+ immRecti(pos, (TXT_OFFSET - 12), 0, (TXT_OFFSET - 5) + TEXTXLOC, ar->winy - 2);
+ immUnbindProgram();
+ }
+ else {
+ st->linenrs_tot = 0; /* not used */
+ x = TXT_OFFSET;
+ }
+ y = ar->winy - st->lheight_dpi;
+ winx = ar->winx - TXT_SCROLL_WIDTH;
+
+ /* draw cursor, margin, selection and highlight */
+ draw_text_decoration(st, ar);
+
+ /* draw the text */
+ UI_FontThemeColor(tdc.font_id, TH_TEXT);
+
+ for (i = 0; y > clip_min_y && i < st->viewlines && tmp; i++, tmp = tmp->next) {
+ if (st->showsyntax && !tmp->format)
+ tft->format_line(st, tmp, false);
+
+ if (st->showlinenrs && !wrap_skip) {
+ /* draw line number */
+ if (tmp == text->curl) {
+ UI_FontThemeColor(tdc.font_id, TH_HILITE);
+ }
+ else {
+ UI_FontThemeColor(tdc.font_id, TH_TEXT);
+ }
+
+ BLI_snprintf(linenr, sizeof(linenr), "%*d", st->linenrs_tot, i + linecount + 1);
+ /* itoa(i + linecount + 1, linenr, 10); */ /* not ansi-c :/ */
+ text_font_draw(&tdc, TXT_OFFSET - 7, y, linenr);
+
+ if (tmp == text->curl) {
+ UI_FontThemeColor(tdc.font_id, TH_TEXT);
+ }
+ }
+
+ if (st->wordwrap) {
+ /* draw word wrapped text */
+ int lines = text_draw_wrapped(st, &tdc, tmp->line, x, y, winx - x, tmp->format, wrap_skip);
+ y -= lines * (st->lheight_dpi + TXT_LINE_SPACING);
+ }
+ else {
+ /* draw unwrapped text */
+ text_draw(st, &tdc, tmp->line, st->left, ar->winx / st->cwidth, x, y, tmp->format);
+ y -= st->lheight_dpi + TXT_LINE_SPACING;
+ }
+
+ wrap_skip = 0;
+ }
+
+ if (st->flags & ST_SHOW_MARGIN) {
+ margin_column_x = x + st->cwidth * (st->margin_column - st->left);
+
+ if (margin_column_x >= x) {
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniformThemeColor(TH_GRID); /* same color as line number background */
+ immUniform1f("dash_width", 2.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2i(shdr_pos, margin_column_x, 0);
+ immVertex2i(shdr_pos, margin_column_x, ar->winy - 2);
+ immEnd();
+ immUnbindProgram();
+ }
+ }
+
+ /* draw other stuff */
+ draw_brackets(st, &tdc, ar);
+ draw_textscroll(st, &scroll, &back);
+ /* draw_documentation(st, ar); - No longer supported */
+ draw_suggestion_list(st, &tdc, ar);
+
+ text_font_end(&tdc);
}
/************************** update ***************************/
void text_update_character_width(SpaceText *st)
{
- TextDrawContext tdc = {0};
+ TextDrawContext tdc = {0};
- text_draw_context_init(st, &tdc);
+ text_draw_context_init(st, &tdc);
- text_font_begin(&tdc);
- st->cwidth = BLF_fixed_width(tdc.font_id);
- st->cwidth = MAX2(st->cwidth, (char)1);
- text_font_end(&tdc);
+ text_font_begin(&tdc);
+ st->cwidth = BLF_fixed_width(tdc.font_id);
+ st->cwidth = MAX2(st->cwidth, (char)1);
+ text_font_end(&tdc);
}
/* 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)
{
- Text *text;
- int i, x, winx = ar->winx;
-
- if (ELEM(NULL, st, st->text, st->text->curl)) return;
-
- text = st->text;
-
- text_update_character_width(st);
-
- 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);
- i += offl;
- }
-
- if (center) {
- if (st->top + st->viewlines <= i || st->top > i) {
- st->top = i - st->viewlines / 2;
- }
- }
- else {
- if (st->top + st->viewlines <= i) {
- st->top = i - (st->viewlines - 1);
- }
- else if (st->top > i) {
- st->top = i;
- }
- }
-
- if (st->wordwrap) {
- st->left = 0;
- }
- else {
- x = st->cwidth * (text_get_char_pos(st, text->sell->line, text->selc) - st->left);
- winx -= TXT_OFFSET + (st->showlinenrs ? TEXTXLOC : 0) + TXT_SCROLL_WIDTH;
-
- if (center) {
- if (x <= 0 || x > winx) {
- st->left += (x - winx / 2) / st->cwidth;
- }
- }
- else {
- if (x <= 0) {
- st->left += ((x + 1) / st->cwidth) - 1;
- }
- else if (x > winx) {
- st->left += ((x - (winx + 1)) / st->cwidth) + 1;
- }
- }
- }
-
- if (st->top < 0) st->top = 0;
- if (st->left < 0) st->left = 0;
-
- st->scroll_accum[0] = 0.0f;
- st->scroll_accum[1] = 0.0f;
+ Text *text;
+ int i, x, winx = ar->winx;
+
+ if (ELEM(NULL, st, st->text, st->text->curl))
+ return;
+
+ text = st->text;
+
+ text_update_character_width(st);
+
+ 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);
+ i += offl;
+ }
+
+ if (center) {
+ if (st->top + st->viewlines <= i || st->top > i) {
+ st->top = i - st->viewlines / 2;
+ }
+ }
+ else {
+ if (st->top + st->viewlines <= i) {
+ st->top = i - (st->viewlines - 1);
+ }
+ else if (st->top > i) {
+ st->top = i;
+ }
+ }
+
+ if (st->wordwrap) {
+ st->left = 0;
+ }
+ else {
+ x = st->cwidth * (text_get_char_pos(st, text->sell->line, text->selc) - st->left);
+ winx -= TXT_OFFSET + (st->showlinenrs ? TEXTXLOC : 0) + TXT_SCROLL_WIDTH;
+
+ if (center) {
+ if (x <= 0 || x > winx) {
+ st->left += (x - winx / 2) / st->cwidth;
+ }
+ }
+ else {
+ if (x <= 0) {
+ st->left += ((x + 1) / st->cwidth) - 1;
+ }
+ else if (x > winx) {
+ st->left += ((x - (winx + 1)) / st->cwidth) + 1;
+ }
+ }
+ }
+
+ if (st->top < 0)
+ st->top = 0;
+ if (st->left < 0)
+ st->left = 0;
+
+ st->scroll_accum[0] = 0.0f;
+ st->scroll_accum[1] = 0.0f;
}
/* takes an area instead of a region, use for listeners */
void text_scroll_to_cursor__area(SpaceText *st, ScrArea *sa, const bool center)
{
- ARegion *ar;
+ ARegion *ar;
- if (ELEM(NULL, st, st->text, st->text->curl)) return;
+ if (ELEM(NULL, st, st->text, st->text->curl))
+ return;
- ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar) {
- text_scroll_to_cursor(st, ar, center);
- }
+ if (ar) {
+ text_scroll_to_cursor(st, ar, center);
+ }
}
void text_update_cursor_moved(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- SpaceText *st = CTX_wm_space_text(C);
+ ScrArea *sa = 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, sa, true);
}
/**
* Takes a cursor (row, character) and returns x,y pixel coords.
*/
-bool ED_text_region_location_from_cursor(SpaceText *st, ARegion *ar, const int cursor_co[2], int r_pixel_co[2])
+bool ED_text_region_location_from_cursor(SpaceText *st,
+ ARegion *ar,
+ const int cursor_co[2],
+ int r_pixel_co[2])
{
- TextLine *line = NULL;
-
- if (!st->text) {
- goto error;
- }
-
- line = BLI_findlink(&st->text->lines, cursor_co[0]);
- if (!line || (cursor_co[1] < 0) || (cursor_co[1] > line->len)) {
- goto error;
- }
- else {
- int offl, offc;
- int linenr_offset = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
- /* 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);
- r_pixel_co[0] = (char_pos + offc - st->left) * st->cwidth + linenr_offset;
- r_pixel_co[1] = (cursor_co[0] + offl - st->top) * (st->lheight_dpi + TXT_LINE_SPACING);
- r_pixel_co[1] = (ar->winy - (r_pixel_co[1] + TXT_OFFSET)) - st->lheight_dpi;
- }
- return true;
-
+ TextLine *line = NULL;
+
+ if (!st->text) {
+ goto error;
+ }
+
+ line = BLI_findlink(&st->text->lines, cursor_co[0]);
+ if (!line || (cursor_co[1] < 0) || (cursor_co[1] > line->len)) {
+ goto error;
+ }
+ else {
+ int offl, offc;
+ int linenr_offset = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
+ /* 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);
+ r_pixel_co[0] = (char_pos + offc - st->left) * st->cwidth + linenr_offset;
+ r_pixel_co[1] = (cursor_co[0] + offl - st->top) * (st->lheight_dpi + TXT_LINE_SPACING);
+ r_pixel_co[1] = (ar->winy - (r_pixel_co[1] + TXT_OFFSET)) - st->lheight_dpi;
+ }
+ return true;
error:
- r_pixel_co[0] = r_pixel_co[1] = -1;
- return false;
+ r_pixel_co[0] = r_pixel_co[1] = -1;
+ return false;
}
diff --git a/source/blender/editors/space_text/text_format.c b/source/blender/editors/space_text/text_format.c
index 0f5dfed080c..0a885fc5875 100644
--- a/source/blender/editors/space_text/text_format.c
+++ b/source/blender/editors/space_text/text_format.c
@@ -31,105 +31,107 @@
#include "text_format.h"
-
/****************** flatten string **********************/
static void flatten_string_append(FlattenString *fs, const char *c, int accum, int len)
{
- int i;
+ int i;
- if (fs->pos + len > fs->len) {
- char *nbuf; int *naccum;
- fs->len *= 2;
+ if (fs->pos + len > fs->len) {
+ char *nbuf;
+ int *naccum;
+ fs->len *= 2;
- nbuf = MEM_callocN(sizeof(*fs->buf) * fs->len, "fs->buf");
- naccum = MEM_callocN(sizeof(*fs->accum) * fs->len, "fs->accum");
+ nbuf = MEM_callocN(sizeof(*fs->buf) * fs->len, "fs->buf");
+ naccum = MEM_callocN(sizeof(*fs->accum) * fs->len, "fs->accum");
- memcpy(nbuf, fs->buf, fs->pos * sizeof(*fs->buf));
- memcpy(naccum, fs->accum, fs->pos * sizeof(*fs->accum));
+ memcpy(nbuf, fs->buf, fs->pos * sizeof(*fs->buf));
+ memcpy(naccum, fs->accum, fs->pos * sizeof(*fs->accum));
- if (fs->buf != fs->fixedbuf) {
- MEM_freeN(fs->buf);
- MEM_freeN(fs->accum);
- }
+ if (fs->buf != fs->fixedbuf) {
+ MEM_freeN(fs->buf);
+ MEM_freeN(fs->accum);
+ }
- fs->buf = nbuf;
- fs->accum = naccum;
- }
+ fs->buf = nbuf;
+ fs->accum = naccum;
+ }
- for (i = 0; i < len; i++) {
- fs->buf[fs->pos + i] = c[i];
- fs->accum[fs->pos + i] = accum;
- }
+ for (i = 0; i < len; i++) {
+ fs->buf[fs->pos + i] = c[i];
+ fs->accum[fs->pos + i] = accum;
+ }
- fs->pos += len;
+ fs->pos += len;
}
int flatten_string(const SpaceText *st, FlattenString *fs, const char *in)
{
- int r, i, total = 0;
-
- memset(fs, 0, sizeof(FlattenString));
- fs->buf = fs->fixedbuf;
- fs->accum = fs->fixedaccum;
- fs->len = sizeof(fs->fixedbuf);
-
- for (r = 0, i = 0; *in; r++) {
- if (*in == '\t') {
- i = st->tabnumber - (total % st->tabnumber);
- total += i;
-
- while (i--)
- flatten_string_append(fs, " ", r, 1);
-
- in++;
- }
- else {
- size_t len = BLI_str_utf8_size_safe(in);
- flatten_string_append(fs, in, r, len);
- in += len;
- total++;
- }
- }
-
- flatten_string_append(fs, "\0", r, 1);
-
- return total;
+ int r, i, total = 0;
+
+ memset(fs, 0, sizeof(FlattenString));
+ fs->buf = fs->fixedbuf;
+ fs->accum = fs->fixedaccum;
+ fs->len = sizeof(fs->fixedbuf);
+
+ for (r = 0, i = 0; *in; r++) {
+ if (*in == '\t') {
+ i = st->tabnumber - (total % st->tabnumber);
+ total += i;
+
+ while (i--)
+ flatten_string_append(fs, " ", r, 1);
+
+ in++;
+ }
+ else {
+ size_t len = BLI_str_utf8_size_safe(in);
+ flatten_string_append(fs, in, r, len);
+ in += len;
+ total++;
+ }
+ }
+
+ flatten_string_append(fs, "\0", r, 1);
+
+ return total;
}
void flatten_string_free(FlattenString *fs)
{
- if (fs->buf != fs->fixedbuf)
- MEM_freeN(fs->buf);
- if (fs->accum != fs->fixedaccum)
- MEM_freeN(fs->accum);
+ if (fs->buf != fs->fixedbuf)
+ MEM_freeN(fs->buf);
+ if (fs->accum != fs->fixedaccum)
+ MEM_freeN(fs->accum);
}
/* takes a string within fs->buf and returns its length */
int flatten_string_strlen(FlattenString *fs, const char *str)
{
- const int len = (fs->pos - (int)(str - fs->buf)) - 1;
- BLI_assert(strlen(str) == len);
- return len;
+ const int len = (fs->pos - (int)(str - fs->buf)) - 1;
+ BLI_assert(strlen(str) == len);
+ return len;
}
/* 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)
{
- if (line->format) {
- if (strlen(line->format) < len) {
- MEM_freeN(line->format);
- line->format = MEM_mallocN(len + 2, "SyntaxFormat");
- if (!line->format) return 0;
- }
- }
- else {
- line->format = MEM_mallocN(len + 2, "SyntaxFormat");
- if (!line->format) return 0;
- }
-
- return 1;
+ if (line->format) {
+ if (strlen(line->format) < len) {
+ MEM_freeN(line->format);
+ line->format = MEM_mallocN(len + 2, "SyntaxFormat");
+ if (!line->format)
+ return 0;
+ }
+ }
+ else {
+ line->format = MEM_mallocN(len + 2, "SyntaxFormat");
+ if (!line->format)
+ return 0;
+ }
+
+ return 1;
}
/**
@@ -140,25 +142,25 @@ int text_check_format_len(TextLine *line, unsigned int len)
*/
void text_format_fill(const char **str_p, char **fmt_p, const char type, const int len)
{
- const char *str = *str_p;
- char *fmt = *fmt_p;
- int i = 0;
+ const char *str = *str_p;
+ char *fmt = *fmt_p;
+ int i = 0;
- while (i < len) {
- const int size = BLI_str_utf8_size_safe(str);
- *fmt++ = type;
+ while (i < len) {
+ const int size = BLI_str_utf8_size_safe(str);
+ *fmt++ = type;
- str += size;
- i += 1;
- }
+ str += size;
+ i += 1;
+ }
- str--;
- fmt--;
+ str--;
+ fmt--;
- BLI_assert(*str != '\0');
+ BLI_assert(*str != '\0');
- *str_p = str;
- *fmt_p = fmt;
+ *str_p = str;
+ *fmt_p = fmt;
}
/**
* ascii version of #text_format_fill,
@@ -166,54 +168,54 @@ void text_format_fill(const char **str_p, char **fmt_p, const char type, const i
*/
void text_format_fill_ascii(const char **str_p, char **fmt_p, const char type, const int len)
{
- const char *str = *str_p;
- char *fmt = *fmt_p;
+ const char *str = *str_p;
+ char *fmt = *fmt_p;
- memset(fmt, type, len);
+ memset(fmt, type, len);
- str += len - 1;
- fmt += len - 1;
+ str += len - 1;
+ fmt += len - 1;
- BLI_assert(*str != '\0');
+ BLI_assert(*str != '\0');
- *str_p = str;
- *fmt_p = fmt;
+ *str_p = str;
+ *fmt_p = fmt;
}
/* *** Registration *** */
static ListBase tft_lb = {NULL, NULL};
void ED_text_format_register(TextFormatType *tft)
{
- BLI_addtail(&tft_lb, tft);
+ BLI_addtail(&tft_lb, tft);
}
TextFormatType *ED_text_format_get(Text *text)
{
- TextFormatType *tft;
-
- if (text) {
- const char *text_ext = strchr(text->id.name + 2, '.');
- if (text_ext) {
- text_ext++; /* skip the '.' */
- /* Check all text formats in the static list */
- for (tft = tft_lb.first; tft; tft = tft->next) {
- /* All formats should have an ext, but just in case */
- const char **ext;
- for (ext = tft->ext; *ext; ext++) {
- /* If extension matches text name, return the matching tft */
- if (BLI_strcasecmp(text_ext, *ext) == 0) {
- return tft;
- }
- }
- }
- }
-
- /* If we make it here we never found an extension that worked - return
- * the "default" text format */
- return tft_lb.first;
- }
- else {
- /* Return the "default" text format */
- return tft_lb.first;
- }
+ TextFormatType *tft;
+
+ if (text) {
+ const char *text_ext = strchr(text->id.name + 2, '.');
+ if (text_ext) {
+ text_ext++; /* skip the '.' */
+ /* Check all text formats in the static list */
+ for (tft = tft_lb.first; tft; tft = tft->next) {
+ /* All formats should have an ext, but just in case */
+ const char **ext;
+ for (ext = tft->ext; *ext; ext++) {
+ /* If extension matches text name, return the matching tft */
+ if (BLI_strcasecmp(text_ext, *ext) == 0) {
+ return tft;
+ }
+ }
+ }
+ }
+
+ /* If we make it here we never found an extension that worked - return
+ * the "default" text format */
+ return tft_lb.first;
+ }
+ else {
+ /* Return the "default" text format */
+ return tft_lb.first;
+ }
}
diff --git a/source/blender/editors/space_text/text_format.h b/source/blender/editors/space_text/text_format.h
index 9fac0a34d77..07635e4227a 100644
--- a/source/blender/editors/space_text/text_format.h
+++ b/source/blender/editors/space_text/text_format.h
@@ -26,80 +26,80 @@
/* *** Flatten String *** */
typedef struct FlattenString {
- char fixedbuf[256];
- int fixedaccum[256];
+ char fixedbuf[256];
+ int fixedaccum[256];
- char *buf;
- int *accum;
- int pos, len;
+ char *buf;
+ int *accum;
+ int pos, len;
} FlattenString;
/* format continuation flags (stored just after the NULL terminator) */
enum {
- FMT_CONT_NOP = 0, /* no continuation */
- FMT_CONT_QUOTESINGLE = (1 << 0), /* single quotes */
- FMT_CONT_QUOTEDOUBLE = (1 << 1), /* double quotes */
- FMT_CONT_TRIPLE = (1 << 2), /* triplets of quotes: """ or ''' */
- FMT_CONT_QUOTESINGLE_TRIPLE = (FMT_CONT_TRIPLE | FMT_CONT_QUOTESINGLE),
- FMT_CONT_QUOTEDOUBLE_TRIPLE = (FMT_CONT_TRIPLE | FMT_CONT_QUOTEDOUBLE),
- FMT_CONT_COMMENT_C = (1 << 3) /* multi-line comments, OSL only (C style) */
+ FMT_CONT_NOP = 0, /* no continuation */
+ FMT_CONT_QUOTESINGLE = (1 << 0), /* single quotes */
+ FMT_CONT_QUOTEDOUBLE = (1 << 1), /* double quotes */
+ FMT_CONT_TRIPLE = (1 << 2), /* triplets of quotes: """ or ''' */
+ FMT_CONT_QUOTESINGLE_TRIPLE = (FMT_CONT_TRIPLE | FMT_CONT_QUOTESINGLE),
+ FMT_CONT_QUOTEDOUBLE_TRIPLE = (FMT_CONT_TRIPLE | FMT_CONT_QUOTEDOUBLE),
+ FMT_CONT_COMMENT_C = (1 << 3) /* multi-line comments, OSL only (C style) */
};
#define FMT_CONT_ALL \
- (FMT_CONT_QUOTESINGLE | FMT_CONT_QUOTEDOUBLE | FMT_CONT_TRIPLE | FMT_CONT_COMMENT_C)
+ (FMT_CONT_QUOTESINGLE | FMT_CONT_QUOTEDOUBLE | FMT_CONT_TRIPLE | FMT_CONT_COMMENT_C)
-int flatten_string(const struct SpaceText *st, FlattenString *fs, const char *in);
+int flatten_string(const struct SpaceText *st, FlattenString *fs, const char *in);
void flatten_string_free(FlattenString *fs);
-int flatten_string_strlen(FlattenString *fs, const char *str);
+int flatten_string_strlen(FlattenString *fs, const char *str);
-int text_check_format_len(TextLine *line, unsigned int len);
+int text_check_format_len(TextLine *line, unsigned int len);
void text_format_fill(const char **str_p, char **fmt_p, const char type, const int len);
void text_format_fill_ascii(const char **str_p, char **fmt_p, const char type, const int len);
/* *** Generalize Formatting *** */
typedef struct TextFormatType {
- struct TextFormatType *next, *prev;
-
- char (*format_identifier)(const char *string);
-
- /* Formats the specified line. If do_next is set, the process will move on to
- * the succeeding line if it is affected (eg. multiline strings). Format strings
- * may contain any of the following characters:
- *
- * It is terminated with a null-terminator '\0' followed by a continuation
- * flag indicating whether the line is part of a multi-line string.
- *
- * See: FMT_TYPE_ enums below
- */
- void (*format_line)(SpaceText *st, TextLine *line, const bool do_next);
-
- const char **ext; /* NULL terminated extensions */
+ struct TextFormatType *next, *prev;
+
+ char (*format_identifier)(const char *string);
+
+ /* Formats the specified line. If do_next is set, the process will move on to
+ * the succeeding line if it is affected (eg. multiline strings). Format strings
+ * may contain any of the following characters:
+ *
+ * It is terminated with a null-terminator '\0' followed by a continuation
+ * flag indicating whether the line is part of a multi-line string.
+ *
+ * See: FMT_TYPE_ enums below
+ */
+ void (*format_line)(SpaceText *st, TextLine *line, const bool do_next);
+
+ const char **ext; /* NULL terminated extensions */
} TextFormatType;
enum {
- /** Whitespace */
- FMT_TYPE_WHITESPACE = '_',
- /** Comment text */
- FMT_TYPE_COMMENT = '#',
- /** Punctuation and other symbols */
- FMT_TYPE_SYMBOL = '!',
- /** Numerals */
- FMT_TYPE_NUMERAL = 'n',
- /** String letters */
- FMT_TYPE_STRING = 'l',
- /** Decorator / Preprocessor directive */
- FMT_TYPE_DIRECTIVE = 'd',
- /** Special variables (class, def) */
- FMT_TYPE_SPECIAL = 'v',
- /** Reserved keywords currently not in use, but still prohibited (OSL -> switch e.g.) */
- FMT_TYPE_RESERVED = 'r',
- /** Built-in names (return, for, etc.) */
- FMT_TYPE_KEYWORD = 'b',
- /** Regular text (identifiers, etc.) */
- FMT_TYPE_DEFAULT = 'q',
+ /** Whitespace */
+ FMT_TYPE_WHITESPACE = '_',
+ /** Comment text */
+ FMT_TYPE_COMMENT = '#',
+ /** Punctuation and other symbols */
+ FMT_TYPE_SYMBOL = '!',
+ /** Numerals */
+ FMT_TYPE_NUMERAL = 'n',
+ /** String letters */
+ FMT_TYPE_STRING = 'l',
+ /** Decorator / Preprocessor directive */
+ FMT_TYPE_DIRECTIVE = 'd',
+ /** Special variables (class, def) */
+ FMT_TYPE_SPECIAL = 'v',
+ /** Reserved keywords currently not in use, but still prohibited (OSL -> switch e.g.) */
+ FMT_TYPE_RESERVED = 'r',
+ /** Built-in names (return, for, etc.) */
+ FMT_TYPE_KEYWORD = 'b',
+ /** Regular text (identifiers, etc.) */
+ FMT_TYPE_DEFAULT = 'q',
};
TextFormatType *ED_text_format_get(Text *text);
-void ED_text_format_register(TextFormatType *tft);
+void ED_text_format_register(TextFormatType *tft);
/* formatters */
void ED_text_format_register_py(void);
@@ -109,6 +109,6 @@ void ED_text_format_register_pov(void);
void ED_text_format_register_pov_ini(void);
#define STR_LITERAL_STARTSWITH(str, str_literal, len_var) \
- (strncmp(str, str_literal, len_var = (sizeof(str_literal) - 1)) == 0)
+ (strncmp(str, str_literal, len_var = (sizeof(str_literal) - 1)) == 0)
-#endif /* __TEXT_FORMAT_H__ */
+#endif /* __TEXT_FORMAT_H__ */
diff --git a/source/blender/editors/space_text/text_format_lua.c b/source/blender/editors/space_text/text_format_lua.c
index 30080d2395b..b82e8aec122 100644
--- a/source/blender/editors/space_text/text_format_lua.c
+++ b/source/blender/editors/space_text/text_format_lua.c
@@ -43,37 +43,37 @@
*/
static int txtfmt_lua_find_keyword(const char *string)
{
- int i, len;
-
- /* Keep aligned args for readability. */
- /* clang-format off */
-
- if (STR_LITERAL_STARTSWITH(string, "and", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "do", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "elseif", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "end", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "function", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "in", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "local", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "not", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "or", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "repeat", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "return", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "then", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "until", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
- else i = 0;
-
- /* clang-format on */
-
- /* If next source char is an identifier (eg. 'i' in "definite") no match */
- if (i == 0 || text_check_identifier(string[i]))
- return -1;
- return i;
+ int i, len;
+
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ if (STR_LITERAL_STARTSWITH(string, "and", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "do", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "elseif", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "end", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "function", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "in", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "local", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "not", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "or", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "repeat", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "then", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "until", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
+ else i = 0;
+
+ /* clang-format on */
+
+ /* If next source char is an identifier (eg. 'i' in "definite") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
}
/**
@@ -89,243 +89,261 @@ static int txtfmt_lua_find_keyword(const char *string)
*/
static int txtfmt_lua_find_specialvar(const char *string)
{
- int i, len;
-
- /* Keep aligned args for readability. */
- /* clang-format off */
-
- if (STR_LITERAL_STARTSWITH(string, "assert", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "collectgarbage", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "dofile", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "error", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "_G", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "getfenv", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "getmetatable", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "__index", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ipairs", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "load", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "loadfile", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "loadstring", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "next", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pairs", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pcall", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "print", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "rawequal", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "rawget", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "rawset", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "select", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "setfenv", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "setmetatable", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tonumber", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tostring", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "type", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "unpack", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "_VERSION", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "xpcall", len)) i = len;
- else i = 0;
-
- /* clang-format on */
-
- /* If next source char is an identifier (eg. 'i' in "definite") no match */
- if (i == 0 || text_check_identifier(string[i]))
- return -1;
- return i;
+ int i, len;
+
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ if (STR_LITERAL_STARTSWITH(string, "assert", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "collectgarbage", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "dofile", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "error", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "_G", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "getfenv", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "getmetatable", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "__index", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ipairs", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "load", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "loadfile", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "loadstring", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "next", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pairs", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pcall", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "print", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rawequal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rawget", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rawset", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "select", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "setfenv", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "setmetatable", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tonumber", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tostring", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "type", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "unpack", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "_VERSION", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "xpcall", len)) i = len;
+ else i = 0;
+
+ /* clang-format on */
+
+ /* If next source char is an identifier (eg. 'i' in "definite") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
}
static int txtfmt_lua_find_bool(const char *string)
{
- int i, len;
-
- if (STR_LITERAL_STARTSWITH(string, "nil", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len;
- else i = 0;
-
- /* clang-format on */
-
- /* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
- if (i == 0 || text_check_identifier(string[i]))
- return -1;
- return i;
+ int i, len;
+
+ if (STR_LITERAL_STARTSWITH(string, "nil", len))
+ i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "true", len))
+ i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "false", len))
+ i = len;
+ else
+ i = 0;
+
+ /* clang-format on */
+
+ /* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
}
static char txtfmt_lua_format_identifier(const char *str)
{
- char fmt;
+ char fmt;
- /* Keep aligned args for readability. */
- /* clang-format off */
+ /* Keep aligned args for readability. */
+ /* clang-format off */
- if ((txtfmt_lua_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL;
- else if ((txtfmt_lua_find_keyword(str)) != -1) fmt = FMT_TYPE_KEYWORD;
- else fmt = FMT_TYPE_DEFAULT;
+ if ((txtfmt_lua_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL;
+ else if ((txtfmt_lua_find_keyword(str)) != -1) fmt = FMT_TYPE_KEYWORD;
+ else fmt = FMT_TYPE_DEFAULT;
- /* clang-format on */
+ /* clang-format on */
- return fmt;
+ return fmt;
}
static void txtfmt_lua_format_line(SpaceText *st, TextLine *line, const bool do_next)
{
- FlattenString fs;
- const char *str;
- char *fmt;
- char cont_orig, cont, find, prev = ' ';
- int len, i;
-
- /* Get continuation from previous line */
- if (line->prev && line->prev->format != NULL) {
- fmt = line->prev->format;
- cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
- BLI_assert((FMT_CONT_ALL & cont) == cont);
- }
- else {
- cont = FMT_CONT_NOP;
- }
-
- /* Get original continuation from this line */
- if (line->format != NULL) {
- fmt = line->format;
- cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
- BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
- }
- else {
- cont_orig = 0xFF;
- }
-
- len = flatten_string(st, &fs, line->line);
- str = fs.buf;
- if (!text_check_format_len(line, len)) {
- flatten_string_free(&fs);
- return;
- }
- fmt = line->format;
-
- while (*str) {
- /* Handle escape sequences by skipping both \ and next char */
- if (*str == '\\') {
- *fmt = prev; fmt++; str++;
- if (*str == '\0') break;
- *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str);
- continue;
- }
- /* Handle continuations */
- else if (cont) {
- /* Multi-line comments */
- if (cont & FMT_CONT_COMMENT_C) {
- if (*str == ']' && *(str + 1) == ']') {
- *fmt = FMT_TYPE_COMMENT; fmt++; str++;
- *fmt = FMT_TYPE_COMMENT;
- cont = FMT_CONT_NOP;
- }
- else {
- *fmt = FMT_TYPE_COMMENT;
- }
- /* Handle other comments */
- }
- else {
- find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
- if (*str == find) cont = 0;
- *fmt = FMT_TYPE_STRING;
- }
-
- str += BLI_str_utf8_size_safe(str) - 1;
- }
- /* Not in a string... */
- else {
- /* Multi-line comments */
- if (*str == '-' && *(str + 1) == '-' &&
- *(str + 2) == '[' && *(str + 3) == '[')
- {
- cont = FMT_CONT_COMMENT_C;
- *fmt = FMT_TYPE_COMMENT; fmt++; str++;
- *fmt = FMT_TYPE_COMMENT; fmt++; str++;
- *fmt = FMT_TYPE_COMMENT; fmt++; str++;
- *fmt = FMT_TYPE_COMMENT;
- }
- /* Single line comment */
- else if (*str == '-' && *(str + 1) == '-') {
- text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format));
- }
- else if (*str == '"' || *str == '\'') {
- /* Strings */
- find = *str;
- cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
- *fmt = FMT_TYPE_STRING;
- }
- /* Whitespace (all ws. has been converted to spaces) */
- else if (*str == ' ') {
- *fmt = FMT_TYPE_WHITESPACE;
- }
- /* Numbers (digits not part of an identifier and periods followed by digits) */
- else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
- (*str == '.' && text_check_digit(*(str + 1))))
- {
- *fmt = FMT_TYPE_NUMERAL;
- }
- /* Booleans */
- else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_lua_find_bool(str)) != -1) {
- if (i > 0) {
- text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i);
- }
- else {
- str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = FMT_TYPE_DEFAULT;
- }
- }
- /* Punctuation */
- else if ((*str != '#') && text_check_delim(*str)) {
- *fmt = FMT_TYPE_SYMBOL;
- }
- /* Identifiers and other text (no previous ws. or delims. so text continues) */
- else if (prev == FMT_TYPE_DEFAULT) {
- str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = FMT_TYPE_DEFAULT;
- }
- /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
- else {
- /* Keep aligned args for readability. */
- /* clang-format off */
-
- /* Special vars(v) or built-in keywords(b) */
- /* keep in sync with 'txtfmt_osl_format_identifier()' */
- if ((i = txtfmt_lua_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL;
- else if ((i = txtfmt_lua_find_keyword(str)) != -1) prev = FMT_TYPE_KEYWORD;
-
- /* clang-format on */
-
- if (i > 0) {
- text_format_fill_ascii(&str, &fmt, prev, i);
- }
- else {
- str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = FMT_TYPE_DEFAULT;
- }
- }
- }
- prev = *fmt; fmt++; str++;
- }
-
- /* Terminate and add continuation char */
- *fmt = '\0'; fmt++;
- *fmt = cont;
-
- /* If continuation has changed and we're allowed, process the next line */
- if (cont != cont_orig && do_next && line->next) {
- txtfmt_lua_format_line(st, line->next, do_next);
- }
-
- flatten_string_free(&fs);
+ FlattenString fs;
+ const char *str;
+ char *fmt;
+ char cont_orig, cont, find, prev = ' ';
+ int len, i;
+
+ /* Get continuation from previous line */
+ if (line->prev && line->prev->format != NULL) {
+ fmt = line->prev->format;
+ cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont) == cont);
+ }
+ else {
+ cont = FMT_CONT_NOP;
+ }
+
+ /* Get original continuation from this line */
+ if (line->format != NULL) {
+ fmt = line->format;
+ cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
+ }
+ else {
+ cont_orig = 0xFF;
+ }
+
+ len = flatten_string(st, &fs, line->line);
+ str = fs.buf;
+ if (!text_check_format_len(line, len)) {
+ flatten_string_free(&fs);
+ return;
+ }
+ fmt = line->format;
+
+ while (*str) {
+ /* Handle escape sequences by skipping both \ and next char */
+ if (*str == '\\') {
+ *fmt = prev;
+ fmt++;
+ str++;
+ if (*str == '\0')
+ break;
+ *fmt = prev;
+ fmt++;
+ str += BLI_str_utf8_size_safe(str);
+ continue;
+ }
+ /* Handle continuations */
+ else if (cont) {
+ /* Multi-line comments */
+ if (cont & FMT_CONT_COMMENT_C) {
+ if (*str == ']' && *(str + 1) == ']') {
+ *fmt = FMT_TYPE_COMMENT;
+ fmt++;
+ str++;
+ *fmt = FMT_TYPE_COMMENT;
+ cont = FMT_CONT_NOP;
+ }
+ else {
+ *fmt = FMT_TYPE_COMMENT;
+ }
+ /* Handle other comments */
+ }
+ else {
+ find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
+ if (*str == find)
+ cont = 0;
+ *fmt = FMT_TYPE_STRING;
+ }
+
+ str += BLI_str_utf8_size_safe(str) - 1;
+ }
+ /* Not in a string... */
+ else {
+ /* Multi-line comments */
+ if (*str == '-' && *(str + 1) == '-' && *(str + 2) == '[' && *(str + 3) == '[') {
+ cont = FMT_CONT_COMMENT_C;
+ *fmt = FMT_TYPE_COMMENT;
+ fmt++;
+ str++;
+ *fmt = FMT_TYPE_COMMENT;
+ fmt++;
+ str++;
+ *fmt = FMT_TYPE_COMMENT;
+ fmt++;
+ str++;
+ *fmt = FMT_TYPE_COMMENT;
+ }
+ /* Single line comment */
+ else if (*str == '-' && *(str + 1) == '-') {
+ text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format));
+ }
+ else if (*str == '"' || *str == '\'') {
+ /* Strings */
+ find = *str;
+ cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
+ *fmt = FMT_TYPE_STRING;
+ }
+ /* Whitespace (all ws. has been converted to spaces) */
+ else if (*str == ' ') {
+ *fmt = FMT_TYPE_WHITESPACE;
+ }
+ /* Numbers (digits not part of an identifier and periods followed by digits) */
+ else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
+ (*str == '.' && text_check_digit(*(str + 1)))) {
+ *fmt = FMT_TYPE_NUMERAL;
+ }
+ /* Booleans */
+ else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_lua_find_bool(str)) != -1) {
+ if (i > 0) {
+ text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i);
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ /* Punctuation */
+ else if ((*str != '#') && text_check_delim(*str)) {
+ *fmt = FMT_TYPE_SYMBOL;
+ }
+ /* Identifiers and other text (no previous ws. or delims. so text continues) */
+ else if (prev == FMT_TYPE_DEFAULT) {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
+ else {
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ /* Special vars(v) or built-in keywords(b) */
+ /* keep in sync with 'txtfmt_osl_format_identifier()' */
+ if ((i = txtfmt_lua_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL;
+ else if ((i = txtfmt_lua_find_keyword(str)) != -1) prev = FMT_TYPE_KEYWORD;
+
+ /* clang-format on */
+
+ if (i > 0) {
+ text_format_fill_ascii(&str, &fmt, prev, i);
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ }
+ prev = *fmt;
+ fmt++;
+ str++;
+ }
+
+ /* Terminate and add continuation char */
+ *fmt = '\0';
+ fmt++;
+ *fmt = cont;
+
+ /* If continuation has changed and we're allowed, process the next line */
+ if (cont != cont_orig && do_next && line->next) {
+ txtfmt_lua_format_line(st, line->next, do_next);
+ }
+
+ flatten_string_free(&fs);
}
void ED_text_format_register_lua(void)
{
- static TextFormatType tft = {NULL};
- static const char *ext[] = {"lua", NULL};
+ static TextFormatType tft = {NULL};
+ static const char *ext[] = {"lua", NULL};
- tft.format_identifier = txtfmt_lua_format_identifier;
- tft.format_line = txtfmt_lua_format_line;
- tft.ext = ext;
+ tft.format_identifier = txtfmt_lua_format_identifier;
+ tft.format_line = txtfmt_lua_format_line;
+ tft.ext = ext;
- ED_text_format_register(&tft);
+ ED_text_format_register(&tft);
}
diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c
index 66980b30c4d..8473b3f80ce 100644
--- a/source/blender/editors/space_text/text_format_osl.c
+++ b/source/blender/editors/space_text/text_format_osl.c
@@ -32,102 +32,102 @@
static int txtfmt_osl_find_builtinfunc(const char *string)
{
- int i, len;
-
- /* Keep aligned args for readability. */
- /* clang-format off */
-
- /* list is from
- * https://github.com/imageworks/OpenShadingLanguage/raw/master/src/doc/osl-languagespec.pdf
- */
- if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "closure", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "color", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "continue", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "do", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "emit", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "float", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "illuminance", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "illuminate", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "int", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "matrix", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "normal", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "output", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "point", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "public", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "return", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "string", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "struct", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "vector", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "void", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
- else i = 0;
-
- /* clang-format on */
-
- /* If next source char is an identifier (eg. 'i' in "definite") no match */
- if (i == 0 || text_check_identifier(string[i]))
- return -1;
- return i;
+ int i, len;
+
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ /* list is from
+ * https://github.com/imageworks/OpenShadingLanguage/raw/master/src/doc/osl-languagespec.pdf
+ */
+ if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "closure", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "color", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "continue", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "do", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "emit", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "float", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "illuminance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "illuminate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "int", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "matrix", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "normal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "output", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "point", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "public", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "string", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "struct", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vector", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "void", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
+ else i = 0;
+
+ /* clang-format on */
+
+ /* If next source char is an identifier (eg. 'i' in "definite") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
}
static int txtfmt_osl_find_reserved(const char *string)
{
- int i, len;
-
- /* Keep aligned args for readability. */
- /* clang-format off */
-
- /* list is from...
- * https://github.com/imageworks/OpenShadingLanguage/raw/master/src/doc/osl-languagespec.pdf
- */
- if (STR_LITERAL_STARTSWITH(string, "bool", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "case", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "catch", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "char", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "const", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "delete", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "default", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "double", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "enum", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "extern", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "friend", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "goto", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "inline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "long", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "new", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "operator", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "private", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "protected", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "short", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "signed", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sizeof", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "static", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "switch", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "template", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "this", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "throw", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "try", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "typedef", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "uniform", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "union", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "unsigned", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "varying", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "virtual", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "volatile", len)) i = len;
- else i = 0;
-
- /* clang-format on */
-
- /* If next source char is an identifier (eg. 'i' in "definite") no match */
- if (i == 0 || text_check_identifier(string[i]))
- return -1;
- return i;
+ int i, len;
+
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ /* list is from...
+ * https://github.com/imageworks/OpenShadingLanguage/raw/master/src/doc/osl-languagespec.pdf
+ */
+ if (STR_LITERAL_STARTSWITH(string, "bool", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "case", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "catch", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "char", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "const", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "delete", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "default", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "double", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "enum", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "extern", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "friend", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "goto", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "inline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "long", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "new", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "operator", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "private", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "protected", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "short", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "signed", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sizeof", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "static", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "switch", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "template", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "this", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "throw", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "try", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "typedef", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uniform", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "union", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "unsigned", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "varying", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "virtual", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "volatile", len)) i = len;
+ else i = 0;
+
+ /* clang-format on */
+
+ /* If next source char is an identifier (eg. 'i' in "definite") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
}
/* Checks the specified source string for a OSL special name. This name must
@@ -139,216 +139,228 @@ static int txtfmt_osl_find_reserved(const char *string)
static int txtfmt_osl_find_specialvar(const char *string)
{
- int i, len;
+ int i, len;
- /* Keep aligned args for readability. */
- /* clang-format off */
+ /* Keep aligned args for readability. */
+ /* clang-format off */
- /* OSL shader types */
- if (STR_LITERAL_STARTSWITH(string, "shader", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "surface", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "volume", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "displacement", len)) i = len;
- else i = 0;
+ /* OSL shader types */
+ if (STR_LITERAL_STARTSWITH(string, "shader", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "surface", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "volume", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "displacement", len)) i = len;
+ else i = 0;
- /* clang-format on */
+ /* clang-format on */
- /* If next source char is an identifier (eg. 'i' in "definite") no match */
- if (i == 0 || text_check_identifier(string[i]))
- return -1;
- return i;
+ /* If next source char is an identifier (eg. 'i' in "definite") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
}
/* matches py 'txtfmt_osl_find_decorator' */
static int txtfmt_osl_find_preprocessor(const char *string)
{
- if (string[0] == '#') {
- int i = 1;
- /* Whitespace is ok '# foo' */
- while (text_check_whitespace(string[i])) {
- i++;
- }
- while (text_check_identifier(string[i])) {
- i++;
- }
- return i;
- }
- return -1;
+ if (string[0] == '#') {
+ int i = 1;
+ /* Whitespace is ok '# foo' */
+ while (text_check_whitespace(string[i])) {
+ i++;
+ }
+ while (text_check_identifier(string[i])) {
+ i++;
+ }
+ return i;
+ }
+ return -1;
}
static char txtfmt_osl_format_identifier(const char *str)
{
- char fmt;
+ char fmt;
- /* Keep aligned args for readability. */
- /* clang-format off */
+ /* Keep aligned args for readability. */
+ /* clang-format off */
- if ((txtfmt_osl_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL;
- else if ((txtfmt_osl_find_builtinfunc(str)) != -1) fmt = FMT_TYPE_KEYWORD;
- else if ((txtfmt_osl_find_reserved(str)) != -1) fmt = FMT_TYPE_RESERVED;
- else if ((txtfmt_osl_find_preprocessor(str)) != -1) fmt = FMT_TYPE_DIRECTIVE;
- else fmt = FMT_TYPE_DEFAULT;
+ if ((txtfmt_osl_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL;
+ else if ((txtfmt_osl_find_builtinfunc(str)) != -1) fmt = FMT_TYPE_KEYWORD;
+ else if ((txtfmt_osl_find_reserved(str)) != -1) fmt = FMT_TYPE_RESERVED;
+ else if ((txtfmt_osl_find_preprocessor(str)) != -1) fmt = FMT_TYPE_DIRECTIVE;
+ else fmt = FMT_TYPE_DEFAULT;
- /* clang-format on */
+ /* clang-format on */
- return fmt;
+ return fmt;
}
static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const bool do_next)
{
- FlattenString fs;
- const char *str;
- char *fmt;
- char cont_orig, cont, find, prev = ' ';
- int len, i;
-
- /* Get continuation from previous line */
- if (line->prev && line->prev->format != NULL) {
- fmt = line->prev->format;
- cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
- BLI_assert((FMT_CONT_ALL & cont) == cont);
- }
- else {
- cont = FMT_CONT_NOP;
- }
-
- /* Get original continuation from this line */
- if (line->format != NULL) {
- fmt = line->format;
- cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
- BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
- }
- else {
- cont_orig = 0xFF;
- }
-
- len = flatten_string(st, &fs, line->line);
- str = fs.buf;
- if (!text_check_format_len(line, len)) {
- flatten_string_free(&fs);
- return;
- }
- fmt = line->format;
-
- while (*str) {
- /* Handle escape sequences by skipping both \ and next char */
- if (*str == '\\') {
- *fmt = prev; fmt++; str++;
- if (*str == '\0') break;
- *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str);
- continue;
- }
- /* Handle continuations */
- else if (cont) {
- /* C-Style comments */
- if (cont & FMT_CONT_COMMENT_C) {
- if (*str == '*' && *(str + 1) == '/') {
- *fmt = FMT_TYPE_COMMENT; fmt++; str++;
- *fmt = FMT_TYPE_COMMENT;
- cont = FMT_CONT_NOP;
- }
- else {
- *fmt = FMT_TYPE_COMMENT;
- }
- /* Handle other comments */
- }
- else {
- find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
- if (*str == find) cont = 0;
- *fmt = FMT_TYPE_STRING;
- }
-
- str += BLI_str_utf8_size_safe(str) - 1;
- }
- /* Not in a string... */
- else {
- /* Deal with comments first */
- if (*str == '/' && *(str + 1) == '/') {
- /* fill the remaining line */
- text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format));
- }
- /* C-Style (multi-line) comments */
- else if (*str == '/' && *(str + 1) == '*') {
- cont = FMT_CONT_COMMENT_C;
- *fmt = FMT_TYPE_COMMENT; fmt++; str++;
- *fmt = FMT_TYPE_COMMENT;
- }
- else if (*str == '"' || *str == '\'') {
- /* Strings */
- find = *str;
- cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
- *fmt = FMT_TYPE_STRING;
- }
- /* Whitespace (all ws. has been converted to spaces) */
- else if (*str == ' ') {
- *fmt = FMT_TYPE_WHITESPACE;
- }
- /* Numbers (digits not part of an identifier and periods followed by digits) */
- else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
- (*str == '.' && text_check_digit(*(str + 1))))
- {
- *fmt = FMT_TYPE_NUMERAL;
- }
- /* Punctuation */
- else if ((*str != '#') && text_check_delim(*str)) {
- *fmt = FMT_TYPE_SYMBOL;
- }
- /* Identifiers and other text (no previous ws. or delims. so text continues) */
- else if (prev == FMT_TYPE_DEFAULT) {
- str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = FMT_TYPE_DEFAULT;
- }
- /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
- else {
- /* Keep aligned args for readability. */
- /* clang-format off */
-
- /* Special vars(v) or built-in keywords(b) */
- /* keep in sync with 'txtfmt_osl_format_identifier()' */
- if ((i = txtfmt_osl_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL;
- else if ((i = txtfmt_osl_find_builtinfunc(str)) != -1) prev = FMT_TYPE_KEYWORD;
- else if ((i = txtfmt_osl_find_reserved(str)) != -1) prev = FMT_TYPE_RESERVED;
- else if ((i = txtfmt_osl_find_preprocessor(str)) != -1) prev = FMT_TYPE_DIRECTIVE;
-
- /* clang-format on */
-
- if (i > 0) {
- if (prev == FMT_TYPE_DIRECTIVE) { /* can contain utf8 */
- text_format_fill(&str, &fmt, prev, i);
- }
- else {
- text_format_fill_ascii(&str, &fmt, prev, i);
- }
- }
- else {
- str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = FMT_TYPE_DEFAULT;
- }
- }
- }
- prev = *fmt; fmt++; str++;
- }
-
- /* Terminate and add continuation char */
- *fmt = '\0'; fmt++;
- *fmt = cont;
-
- /* If continuation has changed and we're allowed, process the next line */
- if (cont != cont_orig && do_next && line->next) {
- txtfmt_osl_format_line(st, line->next, do_next);
- }
-
- flatten_string_free(&fs);
+ FlattenString fs;
+ const char *str;
+ char *fmt;
+ char cont_orig, cont, find, prev = ' ';
+ int len, i;
+
+ /* Get continuation from previous line */
+ if (line->prev && line->prev->format != NULL) {
+ fmt = line->prev->format;
+ cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont) == cont);
+ }
+ else {
+ cont = FMT_CONT_NOP;
+ }
+
+ /* Get original continuation from this line */
+ if (line->format != NULL) {
+ fmt = line->format;
+ cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
+ }
+ else {
+ cont_orig = 0xFF;
+ }
+
+ len = flatten_string(st, &fs, line->line);
+ str = fs.buf;
+ if (!text_check_format_len(line, len)) {
+ flatten_string_free(&fs);
+ return;
+ }
+ fmt = line->format;
+
+ while (*str) {
+ /* Handle escape sequences by skipping both \ and next char */
+ if (*str == '\\') {
+ *fmt = prev;
+ fmt++;
+ str++;
+ if (*str == '\0')
+ break;
+ *fmt = prev;
+ fmt++;
+ str += BLI_str_utf8_size_safe(str);
+ continue;
+ }
+ /* Handle continuations */
+ else if (cont) {
+ /* C-Style comments */
+ if (cont & FMT_CONT_COMMENT_C) {
+ if (*str == '*' && *(str + 1) == '/') {
+ *fmt = FMT_TYPE_COMMENT;
+ fmt++;
+ str++;
+ *fmt = FMT_TYPE_COMMENT;
+ cont = FMT_CONT_NOP;
+ }
+ else {
+ *fmt = FMT_TYPE_COMMENT;
+ }
+ /* Handle other comments */
+ }
+ else {
+ find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
+ if (*str == find)
+ cont = 0;
+ *fmt = FMT_TYPE_STRING;
+ }
+
+ str += BLI_str_utf8_size_safe(str) - 1;
+ }
+ /* Not in a string... */
+ else {
+ /* Deal with comments first */
+ if (*str == '/' && *(str + 1) == '/') {
+ /* fill the remaining line */
+ text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format));
+ }
+ /* C-Style (multi-line) comments */
+ else if (*str == '/' && *(str + 1) == '*') {
+ cont = FMT_CONT_COMMENT_C;
+ *fmt = FMT_TYPE_COMMENT;
+ fmt++;
+ str++;
+ *fmt = FMT_TYPE_COMMENT;
+ }
+ else if (*str == '"' || *str == '\'') {
+ /* Strings */
+ find = *str;
+ cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
+ *fmt = FMT_TYPE_STRING;
+ }
+ /* Whitespace (all ws. has been converted to spaces) */
+ else if (*str == ' ') {
+ *fmt = FMT_TYPE_WHITESPACE;
+ }
+ /* Numbers (digits not part of an identifier and periods followed by digits) */
+ else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
+ (*str == '.' && text_check_digit(*(str + 1)))) {
+ *fmt = FMT_TYPE_NUMERAL;
+ }
+ /* Punctuation */
+ else if ((*str != '#') && text_check_delim(*str)) {
+ *fmt = FMT_TYPE_SYMBOL;
+ }
+ /* Identifiers and other text (no previous ws. or delims. so text continues) */
+ else if (prev == FMT_TYPE_DEFAULT) {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
+ else {
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ /* Special vars(v) or built-in keywords(b) */
+ /* keep in sync with 'txtfmt_osl_format_identifier()' */
+ if ((i = txtfmt_osl_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL;
+ else if ((i = txtfmt_osl_find_builtinfunc(str)) != -1) prev = FMT_TYPE_KEYWORD;
+ else if ((i = txtfmt_osl_find_reserved(str)) != -1) prev = FMT_TYPE_RESERVED;
+ else if ((i = txtfmt_osl_find_preprocessor(str)) != -1) prev = FMT_TYPE_DIRECTIVE;
+
+ /* clang-format on */
+
+ if (i > 0) {
+ if (prev == FMT_TYPE_DIRECTIVE) { /* can contain utf8 */
+ text_format_fill(&str, &fmt, prev, i);
+ }
+ else {
+ text_format_fill_ascii(&str, &fmt, prev, i);
+ }
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ }
+ prev = *fmt;
+ fmt++;
+ str++;
+ }
+
+ /* Terminate and add continuation char */
+ *fmt = '\0';
+ fmt++;
+ *fmt = cont;
+
+ /* If continuation has changed and we're allowed, process the next line */
+ if (cont != cont_orig && do_next && line->next) {
+ txtfmt_osl_format_line(st, line->next, do_next);
+ }
+
+ flatten_string_free(&fs);
}
void ED_text_format_register_osl(void)
{
- static TextFormatType tft = {NULL};
- static const char *ext[] = {"osl", NULL};
+ static TextFormatType tft = {NULL};
+ static const char *ext[] = {"osl", NULL};
- tft.format_identifier = txtfmt_osl_format_identifier;
- tft.format_line = txtfmt_osl_format_line;
- tft.ext = ext;
+ tft.format_identifier = txtfmt_osl_format_identifier;
+ tft.format_line = txtfmt_osl_format_line;
+ tft.ext = ext;
- ED_text_format_register(&tft);
+ ED_text_format_register(&tft);
}
diff --git a/source/blender/editors/space_text/text_format_pov.c b/source/blender/editors/space_text/text_format_pov.c
index c0f4507aa5d..8064f4e69e2 100644
--- a/source/blender/editors/space_text/text_format_pov.c
+++ b/source/blender/editors/space_text/text_format_pov.c
@@ -43,443 +43,442 @@
*/
static int txtfmt_pov_find_keyword(const char *string)
{
- /* Keep aligned args for readability. */
- /* clang-format off */
-
- int i, len;
- /* Language Directives */
- if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "persistent", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "statistics", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "version", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "warning", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "declare", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "default", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "include", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "append", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "elseif", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "debug", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "error", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fclose", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fopen", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ifndef", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ifdef", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "patch", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "local", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "macro", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "range", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "read", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "render", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "switch", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "undef", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "write", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "case", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "end", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
- else i = 0;
-
- /* clang-format on */
-
- /* If next source char is an identifier (eg. 'i' in "definite") no match */
- return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ int i, len;
+ /* Language Directives */
+ if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "persistent", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "statistics", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "version", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "warning", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "declare", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "default", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "include", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "append", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "elseif", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "debug", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "error", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fclose", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fopen", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ifndef", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ifdef", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "patch", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "local", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "macro", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "range", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "read", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "render", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "switch", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "undef", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "write", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "case", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "end", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
+ else i = 0;
+
+ /* clang-format on */
+
+ /* If next source char is an identifier (eg. 'i' in "definite") no match */
+ return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
}
static int txtfmt_pov_find_reserved_keywords(const char *string)
{
- int i, len;
- /* POV-Ray Built-in Variables
- * list is from...
- * http://www.povray.org/documentation/view/3.7.0/212/
- */
-
- /* Keep aligned args for readability. */
- /* clang-format off */
-
- /* Float Functions */
- if (STR_LITERAL_STARTSWITH(string, "conserve_energy", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max_intersections", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "dimension_size", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bitwise_and", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bitwise_or", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bitwise_xor", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "file_exists", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "precompute", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "dimensions", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "clipped_by", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "shadowless", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "turb_depth", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "reciprocal", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "quaternion", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "phong_size", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tesselate", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "save_file", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "load_file", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max_trace", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "transform", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "translate", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "direction", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "roughness", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "metallic", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "gts_load", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "gts_save", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "location", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "altitude", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "function", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "evaluate", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "inverse", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "collect", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "target", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "albedo", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "rotate", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "matrix", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "look_at", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "jitter", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "angle", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "right", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "scale", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "child", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "crand", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "blink", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "defined", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "degrees", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "inside", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "radians", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "vlength", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "select", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "floor", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "strcmp", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "strlen", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tessel", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sturm", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "abs", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "acosh", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "prod", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "with", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "acos", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "asc", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "asinh", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "asin", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "atan2", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "atand", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "atanh", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "atan", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ceil", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "warp", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cosh", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "log", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "min", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "mod", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pow", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "rand", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "seed", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "form", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sinh", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sqrt", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tanh", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "vdot", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sin", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sqr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sum", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pwr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tan", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "val", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cos", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "div", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "exp", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "int", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sky", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "up", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ln", len)) i = len;
- /* Color Identifiers */
- else if (STR_LITERAL_STARTSWITH(string, "transmit", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "filter", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "srgbft", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "srgbf", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "srgbt", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "rgbft", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "gamma", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "green", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "blue", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "gray", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "srgb", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sRGB", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "SRGB", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "rgbf", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "rgbt", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "rgb", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "red", len)) i = len;
- /* Color Spaces */
- else if (STR_LITERAL_STARTSWITH(string, "pov", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "hsl", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "hsv", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "xyl", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "xyv", len)) i = len;
- /* Vector Functions */
- else if (STR_LITERAL_STARTSWITH(string, "vaxis_rotate", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "vturbulence", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "min_extent", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "vnormalize", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max_extent", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "vrotate", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "vcross", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "trace", len)) i = len;
- /* String Functions */
- else if (STR_LITERAL_STARTSWITH(string, "file_time", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "datetime", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "concat", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "strlwr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "strupr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "substr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "vstr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "chr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "str", len)) i = len;
- else i = 0;
-
- /* clang-format on */
-
- /* If next source char is an identifier (eg. 'i' in "definite") no match */
- return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
+ int i, len;
+ /* POV-Ray Built-in Variables
+ * list is from...
+ * http://www.povray.org/documentation/view/3.7.0/212/
+ */
+
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ /* Float Functions */
+ if (STR_LITERAL_STARTSWITH(string, "conserve_energy", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_intersections", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "dimension_size", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bitwise_and", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bitwise_or", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bitwise_xor", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "file_exists", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "precompute", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "dimensions", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clipped_by", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "shadowless", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "turb_depth", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "reciprocal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "quaternion", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "phong_size", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tesselate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "save_file", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "load_file", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_trace", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "transform", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "translate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "direction", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "roughness", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "metallic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gts_load", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gts_save", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "location", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "altitude", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "function", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "evaluate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "inverse", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "collect", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "target", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "albedo", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rotate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "matrix", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "look_at", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "jitter", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "angle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "right", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "scale", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "child", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "crand", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "blink", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "defined", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "degrees", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "inside", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "radians", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vlength", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "select", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "floor", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "strcmp", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "strlen", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tessel", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sturm", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "abs", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "acosh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "prod", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "with", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "acos", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "asc", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "asinh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "asin", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "atan2", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "atand", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "atanh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "atan", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ceil", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "warp", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cosh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "log", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "min", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mod", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pow", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rand", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "seed", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "form", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sinh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sqrt", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tanh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vdot", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sin", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sqr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sum", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pwr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tan", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "val", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cos", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "div", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "exp", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "int", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sky", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "up", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ln", len)) i = len;
+ /* Color Identifiers */
+ else if (STR_LITERAL_STARTSWITH(string, "transmit", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "filter", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "srgbft", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "srgbf", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "srgbt", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rgbft", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gamma", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "green", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "blue", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gray", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "srgb", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sRGB", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "SRGB", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rgbf", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rgbt", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rgb", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "red", len)) i = len;
+ /* Color Spaces */
+ else if (STR_LITERAL_STARTSWITH(string, "pov", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hsl", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hsv", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "xyl", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "xyv", len)) i = len;
+ /* Vector Functions */
+ else if (STR_LITERAL_STARTSWITH(string, "vaxis_rotate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vturbulence", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "min_extent", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vnormalize", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_extent", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vrotate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vcross", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "trace", len)) i = len;
+ /* String Functions */
+ else if (STR_LITERAL_STARTSWITH(string, "file_time", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "datetime", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "concat", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "strlwr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "strupr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "substr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vstr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "chr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "str", len)) i = len;
+ else i = 0;
+
+ /* clang-format on */
+
+ /* If next source char is an identifier (eg. 'i' in "definite") no match */
+ return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
}
-
static int txtfmt_pov_find_reserved_builtins(const char *string)
{
- int i, len;
-
- /* POV-Ray Built-in Variables
- * list is from...
- * http://www.povray.org/documentation/view/3.7.0/212/
- */
-
- /* Keep aligned args for readability. */
- /* clang-format off */
-
- /* Language Keywords */
- if (STR_LITERAL_STARTSWITH(string, "reflection_exponent", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "area_illumination", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "all_intersections", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cutaway_textures", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "smooth_triangle", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "lommel_seeliger", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "falloff_angle", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "aa_threshold", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "hypercomplex", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "major_radius", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max_distance", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max_iteration", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "colour_space", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "color_space", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "iridescence", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "subsurface", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "scattering", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "absorption", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "water_level", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "reflection", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max_extent", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "oren_nayar", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "refraction", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "hierarchy", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "radiosity", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tolerance", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "interior", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "toroidal", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "emission", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "material", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "internal", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "photons", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "arc_angle", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "minnaert", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "texture", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "array", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "black_hole", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "component", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "composite", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "coords", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cube", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "dist_exp", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "exterior", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "file_gamma", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "flatness", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "planet", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "screw", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "keep", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "flip", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "move", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "roll", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "look_at", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "metric", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "offset", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "orientation", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pattern", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "precision", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "width", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "repeat", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bend", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "size", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "alpha", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "slice", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "smooth", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "solid", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "all", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "now", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pot", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "type", len)) i = len;
- /* Animation Options */
- else if (STR_LITERAL_STARTSWITH(string, "global_settings", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "input_file_name", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "initial_clock", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "initial_frame", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "frame_number", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "image_height", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "image_width", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "final_clock", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "final_frame", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "clock_delta", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "clock_on", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "clock", len)) i = len;
- /* Spline Identifiers */
- else if (STR_LITERAL_STARTSWITH(string, "extended_x_spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "general_x_spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "quadratic_spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "basic_x_spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "natural_spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "linear_spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bezier_spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "akima_spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cubic_spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sor_spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tcb_spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "linear_sweep", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "conic_sweep", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "b_spline", len)) i = len;
- /* Patterns */
- else if (STR_LITERAL_STARTSWITH(string, "pigment_pattern", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "image_pattern", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "density_file", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cylindrical", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "proportion", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "triangular", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "image_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "proximity", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "spherical", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bump_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "wrinkles", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "average", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "voronoi", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "masonry", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "binary", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "boxed", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bozo", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "brick", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bumps", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cells", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "checker", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "crackle", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cubic", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "dents", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "facets", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "gradient", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "granite", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "hexagon", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "julia", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "leopard", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "magnet", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "mandel", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "marble", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "onion", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pavement", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "planar", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "quilted", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "radial", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ripples", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "slope", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "spiral1", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "spiral2", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "spotted", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "square", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tile2", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tiling", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tiles", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "waves", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "wood", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "agate", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "aoi", len)) i = len;
- /* Objects */
- else if (STR_LITERAL_STARTSWITH(string, "superellipsoid", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bicubic_patch", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "julia_fractal", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "height_field", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cubic_spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sphere_sweep", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "light_group", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "light_source", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "intersection", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "isosurface", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "background", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sky_sphere", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cylinder", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "difference", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "brilliance", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "parametric", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "interunion", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "intermerge", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "polynomial", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "displace", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "specular", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ambient", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "diffuse", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "polygon", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "quadric", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "quartic", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "rainbow", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sphere", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "spline", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "prism", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "camera", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "galley", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cubic", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "phong", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cone", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "blob", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "box", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "disc", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fog", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "lathe", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "merge", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "mesh2", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "mesh", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "object", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ovus", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "lemon", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "plane", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "poly", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "irid", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sor", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "text", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "torus", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "triangle", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "union", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "colour", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "color", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "media", len)) i = len;
- /* Built-in Vectors */
- else if (STR_LITERAL_STARTSWITH(string, "t", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "u", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "v", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "x", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "y", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "z", len)) i = len;
- else i = 0;
-
- /* clang-format off */
-
- /* If next source char is an identifier (eg. 'i' in "definite") no match */
- return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
+ int i, len;
+
+ /* POV-Ray Built-in Variables
+ * list is from...
+ * http://www.povray.org/documentation/view/3.7.0/212/
+ */
+
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ /* Language Keywords */
+ if (STR_LITERAL_STARTSWITH(string, "reflection_exponent", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "area_illumination", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "all_intersections", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cutaway_textures", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "smooth_triangle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lommel_seeliger", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "falloff_angle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "aa_threshold", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hypercomplex", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "major_radius", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_distance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_iteration", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "colour_space", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "color_space", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "iridescence", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "subsurface", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "scattering", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "absorption", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "water_level", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "reflection", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_extent", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "oren_nayar", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "refraction", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hierarchy", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "radiosity", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tolerance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "interior", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "toroidal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "emission", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "material", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "internal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "photons", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "arc_angle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "minnaert", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "texture", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "array", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "black_hole", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "component", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "composite", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "coords", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cube", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "dist_exp", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "exterior", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "file_gamma", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "flatness", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "planet", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "screw", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "keep", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "flip", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "move", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "roll", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "look_at", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "metric", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "offset", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "orientation", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pattern", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "precision", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "repeat", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bend", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "size", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "alpha", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "slice", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "smooth", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "solid", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "all", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "now", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pot", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "type", len)) i = len;
+ /* Animation Options */
+ else if (STR_LITERAL_STARTSWITH(string, "global_settings", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "input_file_name", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "initial_clock", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "initial_frame", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "frame_number", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "image_height", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "image_width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "final_clock", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "final_frame", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clock_delta", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clock_on", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clock", len)) i = len;
+ /* Spline Identifiers */
+ else if (STR_LITERAL_STARTSWITH(string, "extended_x_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "general_x_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "quadratic_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "basic_x_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "natural_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "linear_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bezier_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "akima_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cubic_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sor_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tcb_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "linear_sweep", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "conic_sweep", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "b_spline", len)) i = len;
+ /* Patterns */
+ else if (STR_LITERAL_STARTSWITH(string, "pigment_pattern", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "image_pattern", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "density_file", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cylindrical", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "proportion", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "triangular", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "image_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "proximity", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "spherical", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bump_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "wrinkles", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "average", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "voronoi", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "masonry", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "binary", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "boxed", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bozo", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "brick", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bumps", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cells", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "checker", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "crackle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cubic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "dents", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "facets", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gradient", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "granite", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hexagon", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "julia", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "leopard", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "magnet", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mandel", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "marble", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "onion", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pavement", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "planar", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "quilted", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "radial", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ripples", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "slope", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "spiral1", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "spiral2", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "spotted", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "square", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tile2", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tiling", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tiles", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "waves", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "wood", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "agate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "aoi", len)) i = len;
+ /* Objects */
+ else if (STR_LITERAL_STARTSWITH(string, "superellipsoid", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bicubic_patch", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "julia_fractal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "height_field", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cubic_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sphere_sweep", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "light_group", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "light_source", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "intersection", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "isosurface", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "background", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sky_sphere", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cylinder", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "difference", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "brilliance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "parametric", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "interunion", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "intermerge", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "polynomial", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "displace", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "specular", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ambient", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "diffuse", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "polygon", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "quadric", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "quartic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rainbow", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sphere", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "prism", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "camera", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "galley", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cubic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "phong", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cone", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "blob", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "box", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "disc", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fog", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lathe", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "merge", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mesh2", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mesh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "object", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ovus", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lemon", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "plane", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "poly", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "irid", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sor", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "text", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "torus", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "triangle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "union", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "colour", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "color", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "media", len)) i = len;
+ /* Built-in Vectors */
+ else if (STR_LITERAL_STARTSWITH(string, "t", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "u", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "v", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "x", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "y", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "z", len)) i = len;
+ else i = 0;
+
+ /* clang-format off */
+
+ /* If next source char is an identifier (eg. 'i' in "definite") no match */
+ return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
}
@@ -496,438 +495,450 @@ static int txtfmt_pov_find_reserved_builtins(const char *string)
*/
static int txtfmt_pov_find_specialvar(const char *string)
{
- int i, len;
- /* Modifiers */
- if (STR_LITERAL_STARTSWITH(string, "dispersion_samples", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "projected_through", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "double_illuminate", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "expand_thresholds", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "media_interaction", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "media_attenuation", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "low_error_factor", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "recursion_limit", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "interior_texture", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max_trace_level", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "gray_threshold", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pretrace_start", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "normal_indices", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "normal_vectors", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "vertex_vectors", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "noise_generator", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "irid_wavelength", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "number_of_waves", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ambient_light", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "inside_vector", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "face_indices", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "texture_list", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max_gradient", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "uv_indices", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "uv_vectors", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fade_distance", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "global_lights", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "no_bump_scale", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pretrace_end", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "no_radiosity", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "no_reflection", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "assumed_gamma", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "scallop_wave", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "triangle_wave", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "nearest_count", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "maximum_reuse", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "minimum_reuse", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "always_sample", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "translucency", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "eccentricity", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "contained_by", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "inside_point", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "adc_bailout", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "density_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "split_union", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "mm_per_unit", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "agate_turb", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bounded_by", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "brick_size", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "hf_gray_16", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "dispersion", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "extinction", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "thickness", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "color_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "colour_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cubic_wave", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fade_colour", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fade_power", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fade_color", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "normal_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pigment_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "quick_color", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "quick_colour", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "material_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pass_through", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "interpolate", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "texture_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "error_bound", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "brightness", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "use_color", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "use_alpha", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "use_colour", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "use_index", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "uv_mapping", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "importance", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "max_sample", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "intervals", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sine_wave", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "slope_map", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "poly_wave", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "no_shadow", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ramp_wave", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "precision", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "original", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "accuracy", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "map_type", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "no_image", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "distance", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "autostop", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "caustics", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "octaves", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "aa_level", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "frequency", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fog_offset", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "modulation", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "outbound", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "no_cache", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pigment", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "charset", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "inbound", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "outside", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "inner", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "turbulence", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "threshold", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "accuracy", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "polarity", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bump_size", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "circular", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "control0", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "control1", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "maximal", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "minimal", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fog_type", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fog_alt", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "samples", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "origin", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "amount", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "adaptive", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "exponent", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "strength", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "density", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fresnel", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "albinos", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "finish", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "method", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "omega", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fixed", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "spacing", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "u_steps", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "v_steps", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "offset", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "hollow", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "gather", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "lambda", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "mortar", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "cubic", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "count", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "once", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "orient", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "normal", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "phase", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ratio", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "open", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ior", len)) i = len;
- /* Light Types and options*/
- else if (STR_LITERAL_STARTSWITH(string, "area_light", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "looks_like", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fade_power", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tightness", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "spotlight", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "parallel", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "point_at", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "falloff", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "radius", len)) i = len;
- /* Camera Types and options*/
- else if (STR_LITERAL_STARTSWITH(string, "omni_directional_stereo", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "lambert_cylindrical", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "miller_cylindrical", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "lambert_azimuthal", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ultra_wide_angle", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "camera_direction", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "camera_location ", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "van_der_grinten", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "aitoff_hammer", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "smyth_craster", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "orthographic", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "camera_right", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "blur_samples", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "plate_carree", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "camera_type", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "perspective", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "mesh_camera", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "focal_point", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "balthasart", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "confidence", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "parallaxe", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "hobo_dyer", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "camera_up", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "panoramic", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "eckert_vi", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "eckert_iv", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "mollweide", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "aperture", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "behrmann", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "variance", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "stereo", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "icosa", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tetra", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "octa", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "mercator", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "omnimax", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fisheye", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "edwards", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "peters", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "gall", len)) i = len;
- else i = 0;
-
- /* If next source char is an identifier (eg. 'i' in "definite") no match */
- return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
+ int i, len;
+ /* Modifiers */
+ if (STR_LITERAL_STARTSWITH(string, "dispersion_samples", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "projected_through", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "double_illuminate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "expand_thresholds", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "media_interaction", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "media_attenuation", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "low_error_factor", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "recursion_limit", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "interior_texture", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_trace_level", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gray_threshold", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pretrace_start", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "normal_indices", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "normal_vectors", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vertex_vectors", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "noise_generator", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "irid_wavelength", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "number_of_waves", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ambient_light", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "inside_vector", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "face_indices", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "texture_list", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_gradient", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uv_indices", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uv_vectors", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fade_distance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "global_lights", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no_bump_scale", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pretrace_end", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no_radiosity", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no_reflection", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "assumed_gamma", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "scallop_wave", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "triangle_wave", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "nearest_count", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "maximum_reuse", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "minimum_reuse", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "always_sample", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "translucency", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "eccentricity", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "contained_by", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "inside_point", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "adc_bailout", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "density_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "split_union", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mm_per_unit", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "agate_turb", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bounded_by", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "brick_size", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hf_gray_16", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "dispersion", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "extinction", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "thickness", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "color_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "colour_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cubic_wave", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fade_colour", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fade_power", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fade_color", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "normal_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pigment_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "quick_color", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "quick_colour", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "material_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pass_through", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "interpolate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "texture_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "error_bound", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "brightness", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "use_color", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "use_alpha", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "use_colour", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "use_index", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uv_mapping", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "importance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_sample", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "intervals", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sine_wave", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "slope_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "poly_wave", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no_shadow", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ramp_wave", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "precision", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "original", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "accuracy", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "map_type", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no_image", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "distance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "autostop", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "caustics", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "octaves", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "aa_level", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "frequency", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fog_offset", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "modulation", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "outbound", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no_cache", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pigment", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "charset", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "inbound", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "outside", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "inner", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "turbulence", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "threshold", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "accuracy", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "polarity", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bump_size", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "circular", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "control0", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "control1", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "maximal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "minimal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fog_type", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fog_alt", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "samples", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "origin", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "amount", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "adaptive", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "exponent", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "strength", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "density", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fresnel", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "albinos", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "finish", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "method", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "omega", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fixed", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "spacing", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "u_steps", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "v_steps", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "offset", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hollow", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gather", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lambda", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mortar", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cubic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "count", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "once", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "orient", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "normal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "phase", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ratio", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "open", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ior", len)) i = len;
+ /* Light Types and options*/
+ else if (STR_LITERAL_STARTSWITH(string, "area_light", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "looks_like", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fade_power", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tightness", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "spotlight", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "parallel", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "point_at", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "falloff", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "radius", len)) i = len;
+ /* Camera Types and options*/
+ else if (STR_LITERAL_STARTSWITH(string, "omni_directional_stereo", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lambert_cylindrical", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "miller_cylindrical", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lambert_azimuthal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ultra_wide_angle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "camera_direction", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "camera_location ", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "van_der_grinten", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "aitoff_hammer", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "smyth_craster", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "orthographic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "camera_right", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "blur_samples", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "plate_carree", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "camera_type", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "perspective", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mesh_camera", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "focal_point", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "balthasart", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "confidence", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "parallaxe", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hobo_dyer", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "camera_up", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "panoramic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "eckert_vi", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "eckert_iv", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mollweide", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "aperture", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "behrmann", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "variance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "stereo", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "icosa", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tetra", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "octa", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mercator", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "omnimax", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fisheye", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "edwards", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "peters", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gall", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definite") no match */
+ return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
}
static int txtfmt_pov_find_bool(const char *string)
{
- int i, len;
-
- /* Keep aligned args for readability. */
- /* clang-format off */
-
- /* Built-in Constants */
- if (STR_LITERAL_STARTSWITH(string, "unofficial", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "no", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "off", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "yes", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "on", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pi", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tau", len)) i = len;
- /* Encodings */
- else if (STR_LITERAL_STARTSWITH(string, "sint16be", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sint16le", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sint32be", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sint32le", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "uint16be", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "uint16le", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bt2020", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "bt709", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sint8", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "uint8", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ascii", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "utf8", len)) i = len;
- /* Filetypes */
- else if (STR_LITERAL_STARTSWITH(string, "tiff", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "df3", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "exr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "gif", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "hdr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "iff", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "jpeg", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pgm", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "png", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ppm", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sys", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tga", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ttf", len)) i = len;
- else i = 0;
-
- /* clang-format on */
-
- /* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
- return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
+ int i, len;
+
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ /* Built-in Constants */
+ if (STR_LITERAL_STARTSWITH(string, "unofficial", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "off", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "yes", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "on", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pi", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tau", len)) i = len;
+ /* Encodings */
+ else if (STR_LITERAL_STARTSWITH(string, "sint16be", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint16le", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint32be", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint32le", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uint16be", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uint16le", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bt2020", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bt709", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint8", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uint8", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ascii", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "utf8", len)) i = len;
+ /* Filetypes */
+ else if (STR_LITERAL_STARTSWITH(string, "tiff", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "df3", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "exr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gif", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hdr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "iff", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "jpeg", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pgm", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "png", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ppm", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sys", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tga", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ttf", len)) i = len;
+ else i = 0;
+
+ /* clang-format on */
+
+ /* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
+ return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
}
static char txtfmt_pov_format_identifier(const char *str)
{
- char fmt;
+ char fmt;
- /* Keep aligned args for readability. */
- /* clang-format off */
+ /* Keep aligned args for readability. */
+ /* clang-format off */
- if ((txtfmt_pov_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL;
- else if ((txtfmt_pov_find_keyword(str)) != -1) fmt = FMT_TYPE_KEYWORD;
- else if ((txtfmt_pov_find_reserved_keywords(str)) != -1) fmt = FMT_TYPE_RESERVED;
- else if ((txtfmt_pov_find_reserved_builtins(str)) != -1) fmt = FMT_TYPE_DIRECTIVE;
- else fmt = FMT_TYPE_DEFAULT;
+ if ((txtfmt_pov_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL;
+ else if ((txtfmt_pov_find_keyword(str)) != -1) fmt = FMT_TYPE_KEYWORD;
+ else if ((txtfmt_pov_find_reserved_keywords(str)) != -1) fmt = FMT_TYPE_RESERVED;
+ else if ((txtfmt_pov_find_reserved_builtins(str)) != -1) fmt = FMT_TYPE_DIRECTIVE;
+ else fmt = FMT_TYPE_DEFAULT;
- /* clang-format on */
+ /* clang-format on */
- return fmt;
+ return fmt;
}
static void txtfmt_pov_format_line(SpaceText *st, TextLine *line, const bool do_next)
{
- FlattenString fs;
- const char *str;
- char *fmt;
- char cont_orig, cont, find, prev = ' ';
- int len, i;
-
- /* Get continuation from previous line */
- if (line->prev && line->prev->format != NULL) {
- fmt = line->prev->format;
- cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
- BLI_assert((FMT_CONT_ALL & cont) == cont);
- }
- else {
- cont = FMT_CONT_NOP;
- }
-
- /* Get original continuation from this line */
- if (line->format != NULL) {
- fmt = line->format;
- cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
- BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
- }
- else {
- cont_orig = 0xFF;
- }
-
- len = flatten_string(st, &fs, line->line);
- str = fs.buf;
- if (!text_check_format_len(line, len)) {
- flatten_string_free(&fs);
- return;
- }
- fmt = line->format;
-
- while (*str) {
- /* Handle escape sequences by skipping both \ and next char */
- if (*str == '\\') {
- *fmt = prev; fmt++; str++;
- if (*str == '\0') break;
- *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str);
- continue;
- }
- /* Handle continuations */
- else if (cont) {
- /* C-Style comments */
- if (cont & FMT_CONT_COMMENT_C) {
- if (*str == '*' && *(str + 1) == '/') {
- *fmt = FMT_TYPE_COMMENT; fmt++; str++;
- *fmt = FMT_TYPE_COMMENT;
- cont = FMT_CONT_NOP;
- }
- else {
- *fmt = FMT_TYPE_COMMENT;
- }
- /* Handle other comments */
- }
- else {
- find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
- if (*str == find) cont = 0;
- *fmt = FMT_TYPE_STRING;
- }
-
- str += BLI_str_utf8_size_safe(str) - 1;
- }
- /* Not in a string... */
- else {
- /* C-Style (multi-line) comments */
- if (*str == '/' && *(str + 1) == '*') {
- cont = FMT_CONT_COMMENT_C;
- *fmt = FMT_TYPE_COMMENT; fmt++; str++;
- *fmt = FMT_TYPE_COMMENT;
- }
- /* Single line comment */
- else if (*str == '/' && *(str + 1) == '/') {
- text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format));
- }
- else if (*str == '"' || *str == '\'') {
- /* Strings */
- find = *str;
- cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
- *fmt = FMT_TYPE_STRING;
- }
- /* Whitespace (all ws. has been converted to spaces) */
- else if (*str == ' ') {
- *fmt = FMT_TYPE_WHITESPACE;
- }
- /* Numbers (digits not part of an identifier and periods followed by digits) */
- else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
- (*str == '.' && text_check_digit(*(str + 1))))
- {
- *fmt = FMT_TYPE_NUMERAL;
- }
- /* Booleans */
- else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_pov_find_bool(str)) != -1) {
- if (i > 0) {
- text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i);
- }
- else {
- str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = FMT_TYPE_DEFAULT;
- }
- }
- /* Punctuation */
- else if (text_check_delim(*str)) {
- *fmt = FMT_TYPE_SYMBOL;
- }
- /* Identifiers and other text (no previous ws. or delims. so text continues) */
- else if (prev == FMT_TYPE_DEFAULT) {
- str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = FMT_TYPE_DEFAULT;
- }
- /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
- else {
- /* Keep aligned args for readability. */
- /* clang-format off */
-
- /* Special vars(v) or built-in keywords(b) */
- /* keep in sync with 'txtfmt_pov_format_identifier()' */
- if ((i = txtfmt_pov_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL;
- else if ((i = txtfmt_pov_find_keyword(str)) != -1) prev = FMT_TYPE_KEYWORD;
- else if ((i = txtfmt_pov_find_reserved_keywords(str)) != -1) prev = FMT_TYPE_RESERVED;
- else if ((i = txtfmt_pov_find_reserved_builtins(str)) != -1) prev = FMT_TYPE_DIRECTIVE;
-
- /* clang-format on */
-
- if (i > 0) {
- text_format_fill_ascii(&str, &fmt, prev, i);
- }
- else {
- str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = FMT_TYPE_DEFAULT;
- }
- }
- }
- prev = *fmt; fmt++; str++;
- }
-
- /* Terminate and add continuation char */
- *fmt = '\0'; fmt++;
- *fmt = cont;
-
- /* If continuation has changed and we're allowed, process the next line */
- if (cont != cont_orig && do_next && line->next) {
- txtfmt_pov_format_line(st, line->next, do_next);
- }
-
- flatten_string_free(&fs);
+ FlattenString fs;
+ const char *str;
+ char *fmt;
+ char cont_orig, cont, find, prev = ' ';
+ int len, i;
+
+ /* Get continuation from previous line */
+ if (line->prev && line->prev->format != NULL) {
+ fmt = line->prev->format;
+ cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont) == cont);
+ }
+ else {
+ cont = FMT_CONT_NOP;
+ }
+
+ /* Get original continuation from this line */
+ if (line->format != NULL) {
+ fmt = line->format;
+ cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
+ }
+ else {
+ cont_orig = 0xFF;
+ }
+
+ len = flatten_string(st, &fs, line->line);
+ str = fs.buf;
+ if (!text_check_format_len(line, len)) {
+ flatten_string_free(&fs);
+ return;
+ }
+ fmt = line->format;
+
+ while (*str) {
+ /* Handle escape sequences by skipping both \ and next char */
+ if (*str == '\\') {
+ *fmt = prev;
+ fmt++;
+ str++;
+ if (*str == '\0')
+ break;
+ *fmt = prev;
+ fmt++;
+ str += BLI_str_utf8_size_safe(str);
+ continue;
+ }
+ /* Handle continuations */
+ else if (cont) {
+ /* C-Style comments */
+ if (cont & FMT_CONT_COMMENT_C) {
+ if (*str == '*' && *(str + 1) == '/') {
+ *fmt = FMT_TYPE_COMMENT;
+ fmt++;
+ str++;
+ *fmt = FMT_TYPE_COMMENT;
+ cont = FMT_CONT_NOP;
+ }
+ else {
+ *fmt = FMT_TYPE_COMMENT;
+ }
+ /* Handle other comments */
+ }
+ else {
+ find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
+ if (*str == find)
+ cont = 0;
+ *fmt = FMT_TYPE_STRING;
+ }
+
+ str += BLI_str_utf8_size_safe(str) - 1;
+ }
+ /* Not in a string... */
+ else {
+ /* C-Style (multi-line) comments */
+ if (*str == '/' && *(str + 1) == '*') {
+ cont = FMT_CONT_COMMENT_C;
+ *fmt = FMT_TYPE_COMMENT;
+ fmt++;
+ str++;
+ *fmt = FMT_TYPE_COMMENT;
+ }
+ /* Single line comment */
+ else if (*str == '/' && *(str + 1) == '/') {
+ text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format));
+ }
+ else if (*str == '"' || *str == '\'') {
+ /* Strings */
+ find = *str;
+ cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
+ *fmt = FMT_TYPE_STRING;
+ }
+ /* Whitespace (all ws. has been converted to spaces) */
+ else if (*str == ' ') {
+ *fmt = FMT_TYPE_WHITESPACE;
+ }
+ /* Numbers (digits not part of an identifier and periods followed by digits) */
+ else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
+ (*str == '.' && text_check_digit(*(str + 1)))) {
+ *fmt = FMT_TYPE_NUMERAL;
+ }
+ /* Booleans */
+ else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_pov_find_bool(str)) != -1) {
+ if (i > 0) {
+ text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i);
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ /* Punctuation */
+ else if (text_check_delim(*str)) {
+ *fmt = FMT_TYPE_SYMBOL;
+ }
+ /* Identifiers and other text (no previous ws. or delims. so text continues) */
+ else if (prev == FMT_TYPE_DEFAULT) {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
+ else {
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ /* Special vars(v) or built-in keywords(b) */
+ /* keep in sync with 'txtfmt_pov_format_identifier()' */
+ if ((i = txtfmt_pov_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL;
+ else if ((i = txtfmt_pov_find_keyword(str)) != -1) prev = FMT_TYPE_KEYWORD;
+ else if ((i = txtfmt_pov_find_reserved_keywords(str)) != -1) prev = FMT_TYPE_RESERVED;
+ else if ((i = txtfmt_pov_find_reserved_builtins(str)) != -1) prev = FMT_TYPE_DIRECTIVE;
+
+ /* clang-format on */
+
+ if (i > 0) {
+ text_format_fill_ascii(&str, &fmt, prev, i);
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ }
+ prev = *fmt;
+ fmt++;
+ str++;
+ }
+
+ /* Terminate and add continuation char */
+ *fmt = '\0';
+ fmt++;
+ *fmt = cont;
+
+ /* If continuation has changed and we're allowed, process the next line */
+ if (cont != cont_orig && do_next && line->next) {
+ txtfmt_pov_format_line(st, line->next, do_next);
+ }
+
+ flatten_string_free(&fs);
}
void ED_text_format_register_pov(void)
{
- static TextFormatType tft = {NULL};
- static const char *ext[] = {"pov", "inc", "mcr", "mac", NULL};
+ static TextFormatType tft = {NULL};
+ static const char *ext[] = {"pov", "inc", "mcr", "mac", NULL};
- tft.format_identifier = txtfmt_pov_format_identifier;
- tft.format_line = txtfmt_pov_format_line;
- tft.ext = ext;
+ tft.format_identifier = txtfmt_pov_format_identifier;
+ tft.format_line = txtfmt_pov_format_line;
+ tft.ext = ext;
- ED_text_format_register(&tft);
+ ED_text_format_register(&tft);
}
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 5ef5746bffb..0dbf2b1bdd3 100644
--- a/source/blender/editors/space_text/text_format_pov_ini.c
+++ b/source/blender/editors/space_text/text_format_pov_ini.c
@@ -43,468 +43,478 @@
*/
static int txtfmt_ini_find_keyword(const char *string)
{
- int i, len;
-
- /* Keep aligned args for readability. */
- /* clang-format off */
-
- /* Language Directives */
- if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "statistics", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "declare", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "default", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "version", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "warning", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "include", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fclose", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ifndef", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "append", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "elseif", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "debug", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "error", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "fopen", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ifdef", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "local", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "macro", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "range", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "render", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "switch", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "undef", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "write", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "case", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "read", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "end", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
-
- else if (STR_LITERAL_STARTSWITH(string, "I", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "S", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "A", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Q", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "U", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "F", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "C", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "N", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "P", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "T", len)) i = len;
-
- else i = 0;
-
- /* clang-format on */
-
- /* If next source char is an identifier (eg. 'i' in "definite") no match */
- return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
+ int i, len;
+
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ /* Language Directives */
+ if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "statistics", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "declare", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "default", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "version", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "warning", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "include", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fclose", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ifndef", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "append", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "elseif", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "debug", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "error", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fopen", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ifdef", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "local", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "macro", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "range", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "render", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "switch", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "undef", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "write", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "case", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "read", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "end", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
+
+ else if (STR_LITERAL_STARTSWITH(string, "I", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "S", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "A", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Q", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "U", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "F", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "C", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "N", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "P", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "T", len)) i = len;
+
+ else i = 0;
+
+ /* clang-format on */
+
+ /* If next source char is an identifier (eg. 'i' in "definite") no match */
+ return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
}
static int txtfmt_ini_find_reserved(const char *string)
{
- int i, len;
-
- /* Keep aligned args for readability. */
- /* clang-format off */
-
- /* POV-Ray Built-in INI Variables
- * list is from...
- * http://www.povray.org/documentation/view/3.7.0/212/
- */
- if (STR_LITERAL_STARTSWITH(string, "RenderCompleteSoundEnabled", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Create_Continue_Trace_Log", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ParseErrorSoundEnabled", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "RenderErrorSoundEnabled", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "HideWhenMainMinimized", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Antialias_Confidence", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "RenderCompleteSound", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ParseErrorSound", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "RenderErrorSound", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "UseExtensions", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ReadWriteSourceDir", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "NormalPositionLeft", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "NormalPositionTop", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "NormalPositionRight", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "NormalPositionBottom", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Pre_Scene_Command", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Pre_Frame_Command", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Post_Scene_Command", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Post_Frame_Command", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "User_Abort_Command", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Fatal_Error_Command", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "NormalPositionX", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "NormalPositionY", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Pre_Scene_Return", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Pre_Frame_Return", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Post_Scene_Return", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Post_Frame_Return", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "User_Abort_Return", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Fatal_Error_Return", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Antialias_Threshold", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Antialias_Gamma", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Antialias_Depth", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "input_file_name", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Subset_Start_Frame", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Subset_End_Frame", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "UseToolbar", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "UseTooltips", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Frame_Step", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Cyclic_Animation", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Field_Render", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Odd_Field", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "final_clock", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "final_frame", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "frame_number", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "initial_clock", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "initial_frame", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "image_height", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "image_width", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Start_Column", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Start_Row", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "End_Column", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "End_Row", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Test_Abort_Count", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Test_Abort", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Continue_Trace", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Bounding_Method", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Create_Ini", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Display_Gamma", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Display", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Version", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Pause_When_Done", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Verbose", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Preview_Start_Size", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Preview_End_Size", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Output_to_File", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Input_File_Name", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Output_File_Name", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Output_File_Type", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Output_Alpha", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Bits_Per_Color", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Compression", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Dither_Method", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Include_Header", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Library_Path", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Debug_Console", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Fatal_Console", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Render_Console", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Statistic_Console", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Warning_Console", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Warning_Level", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "All_Console", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Debug_File", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Fatal_File", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Render_File", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Statistic_File", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Warning_File", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "All_File", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Quality", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Bounding_Threshold", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Bounding", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Light_Buffer", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Vista_Buffer", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Remove_Bounds", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Split_Unions", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Antialias", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Glare_Desaturation", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Sampling_Method", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Stochastic_Seed", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Jitter_Amount", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Jitter", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Antialias_Depth", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "CheckNewVersion", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "RunCount", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "CommandLine", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "TextColour", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "WarningColour", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ErrorColour", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "BackgroundColour", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "DropToEditor", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "LastRenderName", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "LastRenderPath", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "LastQueuePath", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "SecondaryINISection", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "BetaVersionNo64", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "LastBitmapName", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "LastBitmapPath", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "LastINIPath", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "SecondaryINIFile", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "BackgroundFile", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "SaveSettingsOnExit", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "TileBackground", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "HideNewUserHelp", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "SendSystemInfo", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ItsAboutTime", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "LastPath", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Band0Width", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Band1Width", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Band2Width", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Band3Width", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Band4Width", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ShowCmd", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Transparency", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Use8BitMode", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "MakeActive", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "KeepAboveMain", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "AutoClose", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "PreserveBitmap", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "FontSize", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "FontWeight", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "KeepMessages", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "AlertSound", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Completion", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Priority", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "DutyCycle", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "AlertOnCompletion", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "AutoRender", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "PreventSleep", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "NoShelloutWait", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "SystemNoActive", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "NoShellOuts", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "VideoSource", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "SceneFile", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "OutputFile", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "IniOutputFile", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "CurrentDirectory", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "SourceFile", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Rendering", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "RenderwinClose", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Append_File", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Warning Level", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "clock_delta", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "clock_on", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "clock", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Height", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Width", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Dither", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Flags", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "Font", len)) i = len;
- /* Filetypes */
- else if (STR_LITERAL_STARTSWITH(string, "df3", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "exr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "gif", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "hdr", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "iff", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "jpeg", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pgm", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "png", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "ppm", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sys", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tga", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tiff", len)) i = len;
- /* Encodings */
- else if (STR_LITERAL_STARTSWITH(string, "ascii", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "utf8", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "uint8", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "uint16be", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "uint16le", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sint8", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sint16be", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sint16le", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sint32be", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "sint32le", len)) i = len;
-
- else i = 0;
-
- /* clang-format on */
-
- /* If next source char is an identifier (eg. 'i' in "definite") no match */
- return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
+ int i, len;
+
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ /* POV-Ray Built-in INI Variables
+ * list is from...
+ * http://www.povray.org/documentation/view/3.7.0/212/
+ */
+ if (STR_LITERAL_STARTSWITH(string, "RenderCompleteSoundEnabled", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Create_Continue_Trace_Log", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ParseErrorSoundEnabled", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "RenderErrorSoundEnabled", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "HideWhenMainMinimized", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Antialias_Confidence", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "RenderCompleteSound", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ParseErrorSound", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "RenderErrorSound", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "UseExtensions", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ReadWriteSourceDir", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NormalPositionLeft", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NormalPositionTop", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NormalPositionRight", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NormalPositionBottom", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Pre_Scene_Command", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Pre_Frame_Command", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Post_Scene_Command", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Post_Frame_Command", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "User_Abort_Command", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Fatal_Error_Command", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NormalPositionX", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NormalPositionY", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Pre_Scene_Return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Pre_Frame_Return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Post_Scene_Return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Post_Frame_Return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "User_Abort_Return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Fatal_Error_Return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Antialias_Threshold", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Antialias_Gamma", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Antialias_Depth", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "input_file_name", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Subset_Start_Frame", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Subset_End_Frame", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "UseToolbar", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "UseTooltips", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Frame_Step", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Cyclic_Animation", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Field_Render", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Odd_Field", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "final_clock", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "final_frame", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "frame_number", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "initial_clock", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "initial_frame", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "image_height", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "image_width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Start_Column", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Start_Row", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "End_Column", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "End_Row", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Test_Abort_Count", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Test_Abort", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Continue_Trace", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Bounding_Method", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Create_Ini", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Display_Gamma", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Display", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Version", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Pause_When_Done", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Verbose", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Preview_Start_Size", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Preview_End_Size", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Output_to_File", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Input_File_Name", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Output_File_Name", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Output_File_Type", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Output_Alpha", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Bits_Per_Color", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Compression", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Dither_Method", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Include_Header", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Library_Path", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Debug_Console", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Fatal_Console", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Render_Console", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Statistic_Console", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Warning_Console", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Warning_Level", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "All_Console", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Debug_File", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Fatal_File", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Render_File", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Statistic_File", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Warning_File", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "All_File", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Quality", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Bounding_Threshold", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Bounding", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Light_Buffer", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Vista_Buffer", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Remove_Bounds", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Split_Unions", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Antialias", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Glare_Desaturation", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Sampling_Method", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Stochastic_Seed", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Jitter_Amount", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Jitter", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Antialias_Depth", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "CheckNewVersion", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "RunCount", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "CommandLine", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "TextColour", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "WarningColour", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ErrorColour", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "BackgroundColour", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "DropToEditor", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "LastRenderName", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "LastRenderPath", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "LastQueuePath", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "SecondaryINISection", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "BetaVersionNo64", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "LastBitmapName", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "LastBitmapPath", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "LastINIPath", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "SecondaryINIFile", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "BackgroundFile", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "SaveSettingsOnExit", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "TileBackground", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "HideNewUserHelp", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "SendSystemInfo", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ItsAboutTime", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "LastPath", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Band0Width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Band1Width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Band2Width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Band3Width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Band4Width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ShowCmd", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Transparency", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Use8BitMode", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "MakeActive", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "KeepAboveMain", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "AutoClose", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "PreserveBitmap", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "FontSize", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "FontWeight", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "KeepMessages", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "AlertSound", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Completion", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Priority", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "DutyCycle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "AlertOnCompletion", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "AutoRender", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "PreventSleep", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NoShelloutWait", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "SystemNoActive", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NoShellOuts", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "VideoSource", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "SceneFile", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "OutputFile", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "IniOutputFile", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "CurrentDirectory", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "SourceFile", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Rendering", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "RenderwinClose", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Append_File", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Warning Level", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clock_delta", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clock_on", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clock", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Height", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Dither", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Flags", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Font", len)) i = len;
+ /* Filetypes */
+ else if (STR_LITERAL_STARTSWITH(string, "df3", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "exr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gif", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hdr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "iff", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "jpeg", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pgm", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "png", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ppm", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sys", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tga", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tiff", len)) i = len;
+ /* Encodings */
+ else if (STR_LITERAL_STARTSWITH(string, "ascii", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "utf8", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uint8", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uint16be", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uint16le", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint8", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint16be", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint16le", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint32be", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint32le", len)) i = len;
+
+ else i = 0;
+
+ /* clang-format on */
+
+ /* If next source char is an identifier (eg. 'i' in "definite") no match */
+ return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
}
-
-
-
static int txtfmt_ini_find_bool(const char *string)
{
- int i, len;
-
- /* Keep aligned args for readability. */
- /* clang-format off */
-
- /* Built-in Constants */
- if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "no", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "off", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "yes", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "on", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pi", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "tau", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "%o", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "%s", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "%n", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "%k", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "%h", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "%w", len)) i = len;
- else i = 0;
-
- /* clang-format on */
-
- /* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
- return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
+ int i, len;
+
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ /* Built-in Constants */
+ if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "off", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "yes", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "on", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pi", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tau", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "%o", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "%s", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "%n", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "%k", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "%h", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "%w", len)) i = len;
+ else i = 0;
+
+ /* clang-format on */
+
+ /* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
+ return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
}
static char txtfmt_pov_ini_format_identifier(const char *str)
{
- char fmt;
- if ((txtfmt_ini_find_keyword(str)) != -1) fmt = FMT_TYPE_KEYWORD;
- else if ((txtfmt_ini_find_reserved(str)) != -1) fmt = FMT_TYPE_RESERVED;
- else fmt = FMT_TYPE_DEFAULT;
- return fmt;
+ char fmt;
+ if ((txtfmt_ini_find_keyword(str)) != -1)
+ fmt = FMT_TYPE_KEYWORD;
+ else if ((txtfmt_ini_find_reserved(str)) != -1)
+ fmt = FMT_TYPE_RESERVED;
+ else
+ fmt = FMT_TYPE_DEFAULT;
+ return fmt;
}
static void txtfmt_pov_ini_format_line(SpaceText *st, TextLine *line, const bool do_next)
{
- FlattenString fs;
- const char *str;
- char *fmt;
- char cont_orig, cont, find, prev = ' ';
- int len, i;
-
- /* Get continuation from previous line */
- if (line->prev && line->prev->format != NULL) {
- fmt = line->prev->format;
- cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
- BLI_assert((FMT_CONT_ALL & cont) == cont);
- }
- else {
- cont = FMT_CONT_NOP;
- }
-
- /* Get original continuation from this line */
- if (line->format != NULL) {
- fmt = line->format;
- cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
- BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
- }
- else {
- cont_orig = 0xFF;
- }
-
- len = flatten_string(st, &fs, line->line);
- str = fs.buf;
- if (!text_check_format_len(line, len)) {
- flatten_string_free(&fs);
- return;
- }
- fmt = line->format;
-
- while (*str) {
- /* Handle escape sequences by skipping both \ and next char */
- if (*str == '\\') {
- *fmt = prev; fmt++; str++;
- if (*str == '\0') break;
- *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str);
- continue;
- }
- /* Handle continuations */
- else if (cont) {
- /* Multi-line comments */
- if (cont & FMT_CONT_COMMENT_C) {
- if (*str == ']' && *(str + 1) == ']') {
- *fmt = FMT_TYPE_COMMENT; fmt++; str++;
- *fmt = FMT_TYPE_COMMENT;
- cont = FMT_CONT_NOP;
- }
- else {
- *fmt = FMT_TYPE_COMMENT;
- }
- /* Handle other comments */
- }
- else {
- find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
- if (*str == find) cont = 0;
- *fmt = FMT_TYPE_STRING;
- }
-
- str += BLI_str_utf8_size_safe(str) - 1;
- }
- /* Not in a string... */
- else {
- /* Multi-line comments not supported */
- /* Single line comment */
- if (*str == ';') {
- text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format));
- }
- else if (*str == '"' || *str == '\'') {
- /* Strings */
- find = *str;
- cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
- *fmt = FMT_TYPE_STRING;
- }
- /* Whitespace (all ws. has been converted to spaces) */
- else if (*str == ' ') {
- *fmt = FMT_TYPE_WHITESPACE;
- }
- /* Numbers (digits not part of an identifier and periods followed by digits) */
- else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
- (*str == '.' && text_check_digit(*(str + 1))))
- {
- *fmt = FMT_TYPE_NUMERAL;
- }
- /* Booleans */
- else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_ini_find_bool(str)) != -1) {
- if (i > 0) {
- text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i);
- }
- else {
- str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = FMT_TYPE_DEFAULT;
- }
- }
- /* Punctuation */
- else if ((*str != '#') && text_check_delim(*str)) {
- *fmt = FMT_TYPE_SYMBOL;
- }
- /* Identifiers and other text (no previous ws. or delims. so text continues) */
- else if (prev == FMT_TYPE_DEFAULT) {
- str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = FMT_TYPE_DEFAULT;
- }
- /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
- else {
- /* Keep aligned args for readability. */
- /* clang-format off */
-
- /* Special vars(v) or built-in keywords(b) */
- /* keep in sync with 'txtfmt_ini_format_identifier()' */
- if ((i = txtfmt_ini_find_keyword(str)) != -1) prev = FMT_TYPE_KEYWORD;
- else if ((i = txtfmt_ini_find_reserved(str)) != -1) prev = FMT_TYPE_RESERVED;
-
- /* clang-format on */
-
- if (i > 0) {
- text_format_fill_ascii(&str, &fmt, prev, i);
- }
- else {
- str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = FMT_TYPE_DEFAULT;
- }
- }
- }
- prev = *fmt; fmt++; str++;
- }
-
- /* Terminate and add continuation char */
- *fmt = '\0'; fmt++;
- *fmt = cont;
-
- /* If continuation has changed and we're allowed, process the next line */
- if (cont != cont_orig && do_next && line->next) {
- txtfmt_pov_ini_format_line(st, line->next, do_next);
- }
-
- flatten_string_free(&fs);
+ FlattenString fs;
+ const char *str;
+ char *fmt;
+ char cont_orig, cont, find, prev = ' ';
+ int len, i;
+
+ /* Get continuation from previous line */
+ if (line->prev && line->prev->format != NULL) {
+ fmt = line->prev->format;
+ cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont) == cont);
+ }
+ else {
+ cont = FMT_CONT_NOP;
+ }
+
+ /* Get original continuation from this line */
+ if (line->format != NULL) {
+ fmt = line->format;
+ cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
+ }
+ else {
+ cont_orig = 0xFF;
+ }
+
+ len = flatten_string(st, &fs, line->line);
+ str = fs.buf;
+ if (!text_check_format_len(line, len)) {
+ flatten_string_free(&fs);
+ return;
+ }
+ fmt = line->format;
+
+ while (*str) {
+ /* Handle escape sequences by skipping both \ and next char */
+ if (*str == '\\') {
+ *fmt = prev;
+ fmt++;
+ str++;
+ if (*str == '\0')
+ break;
+ *fmt = prev;
+ fmt++;
+ str += BLI_str_utf8_size_safe(str);
+ continue;
+ }
+ /* Handle continuations */
+ else if (cont) {
+ /* Multi-line comments */
+ if (cont & FMT_CONT_COMMENT_C) {
+ if (*str == ']' && *(str + 1) == ']') {
+ *fmt = FMT_TYPE_COMMENT;
+ fmt++;
+ str++;
+ *fmt = FMT_TYPE_COMMENT;
+ cont = FMT_CONT_NOP;
+ }
+ else {
+ *fmt = FMT_TYPE_COMMENT;
+ }
+ /* Handle other comments */
+ }
+ else {
+ find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
+ if (*str == find)
+ cont = 0;
+ *fmt = FMT_TYPE_STRING;
+ }
+
+ str += BLI_str_utf8_size_safe(str) - 1;
+ }
+ /* Not in a string... */
+ else {
+ /* Multi-line comments not supported */
+ /* Single line comment */
+ if (*str == ';') {
+ text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format));
+ }
+ else if (*str == '"' || *str == '\'') {
+ /* Strings */
+ find = *str;
+ cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
+ *fmt = FMT_TYPE_STRING;
+ }
+ /* Whitespace (all ws. has been converted to spaces) */
+ else if (*str == ' ') {
+ *fmt = FMT_TYPE_WHITESPACE;
+ }
+ /* Numbers (digits not part of an identifier and periods followed by digits) */
+ else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
+ (*str == '.' && text_check_digit(*(str + 1)))) {
+ *fmt = FMT_TYPE_NUMERAL;
+ }
+ /* Booleans */
+ else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_ini_find_bool(str)) != -1) {
+ if (i > 0) {
+ text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i);
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ /* Punctuation */
+ else if ((*str != '#') && text_check_delim(*str)) {
+ *fmt = FMT_TYPE_SYMBOL;
+ }
+ /* Identifiers and other text (no previous ws. or delims. so text continues) */
+ else if (prev == FMT_TYPE_DEFAULT) {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
+ else {
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ /* Special vars(v) or built-in keywords(b) */
+ /* keep in sync with 'txtfmt_ini_format_identifier()' */
+ if ((i = txtfmt_ini_find_keyword(str)) != -1) prev = FMT_TYPE_KEYWORD;
+ else if ((i = txtfmt_ini_find_reserved(str)) != -1) prev = FMT_TYPE_RESERVED;
+
+ /* clang-format on */
+
+ if (i > 0) {
+ text_format_fill_ascii(&str, &fmt, prev, i);
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ }
+ prev = *fmt;
+ fmt++;
+ str++;
+ }
+
+ /* Terminate and add continuation char */
+ *fmt = '\0';
+ fmt++;
+ *fmt = cont;
+
+ /* If continuation has changed and we're allowed, process the next line */
+ if (cont != cont_orig && do_next && line->next) {
+ txtfmt_pov_ini_format_line(st, line->next, do_next);
+ }
+
+ flatten_string_free(&fs);
}
void ED_text_format_register_pov_ini(void)
{
- static TextFormatType tft = {NULL};
- static const char *ext[] = {"ini", NULL};
+ static TextFormatType tft = {NULL};
+ static const char *ext[] = {"ini", NULL};
- tft.format_identifier = txtfmt_pov_ini_format_identifier;
- tft.format_line = txtfmt_pov_ini_format_line;
- tft.ext = ext;
+ tft.format_identifier = txtfmt_pov_ini_format_identifier;
+ tft.format_line = txtfmt_pov_ini_format_line;
+ tft.ext = ext;
- ED_text_format_register(&tft);
+ ED_text_format_register(&tft);
}
diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c
index bb0b639f508..68e42335546 100644
--- a/source/blender/editors/space_text/text_format_py.c
+++ b/source/blender/editors/space_text/text_format_py.c
@@ -43,59 +43,59 @@
*/
static int txtfmt_py_find_builtinfunc(const char *string)
{
- int i, len;
- /* list is from...
- * ", ".join(['"%s"' % kw
- * for kw in __import__("keyword").kwlist
- * if kw not in {"False", "None", "True", "def", "class"}])
- *
- * ... and for this code:
- * print("\n".join(['else if (STR_LITERAL_STARTSWITH(string, "%s", len)) i = len;' % kw
- * for kw in __import__("keyword").kwlist
- * if kw not in {"False", "None", "True", "def", "class"}]))
- */
-
- /* Keep aligned args for readability. */
- /* clang-format off */
-
- if (STR_LITERAL_STARTSWITH(string, "and", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "as", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "assert", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "async", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "await", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "continue", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "del", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "elif", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "except", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "finally", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "from", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "global", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "import", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "in", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "is", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "lambda", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "nonlocal", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "not", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "or", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "pass", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "raise", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "return", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "try", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "with", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "yield", len)) i = len;
- else i = 0;
-
- /* clang-format on */
-
- /* If next source char is an identifier (eg. 'i' in "definite") no match */
- if (i == 0 || text_check_identifier(string[i]))
- return -1;
- return i;
+ int i, len;
+ /* list is from...
+ * ", ".join(['"%s"' % kw
+ * for kw in __import__("keyword").kwlist
+ * if kw not in {"False", "None", "True", "def", "class"}])
+ *
+ * ... and for this code:
+ * print("\n".join(['else if (STR_LITERAL_STARTSWITH(string, "%s", len)) i = len;' % kw
+ * for kw in __import__("keyword").kwlist
+ * if kw not in {"False", "None", "True", "def", "class"}]))
+ */
+
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ if (STR_LITERAL_STARTSWITH(string, "and", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "as", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "assert", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "async", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "await", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "continue", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "del", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "elif", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "except", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "finally", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "from", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "global", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "import", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "in", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "is", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lambda", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "nonlocal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "not", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "or", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pass", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "raise", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "try", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "with", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "yield", len)) i = len;
+ else i = 0;
+
+ /* clang-format on */
+
+ /* If next source char is an identifier (eg. 'i' in "definite") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
}
/* Checks the specified source string for a Python special name. This name must
@@ -107,240 +107,256 @@ static int txtfmt_py_find_builtinfunc(const char *string)
static int txtfmt_py_find_specialvar(const char *string)
{
- int i, len;
+ int i, len;
- /* Keep aligned args for readability. */
- /* clang-format off */
+ /* Keep aligned args for readability. */
+ /* clang-format off */
- if (STR_LITERAL_STARTSWITH(string, "def", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "class", len)) i = len;
- else i = 0;
+ if (STR_LITERAL_STARTSWITH(string, "def", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "class", len)) i = len;
+ else i = 0;
- /* clang-format on */
+ /* clang-format on */
- /* If next source char is an identifier (eg. 'i' in "definite") no match */
- if (i == 0 || text_check_identifier(string[i]))
- return -1;
- return i;
+ /* If next source char is an identifier (eg. 'i' in "definite") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
}
static int txtfmt_py_find_decorator(const char *string)
{
- if (string[0] != '@') {
- return -1;
- }
- if (!text_check_identifier(string[1])) {
- return -1;
- }
- /* Interpret as matrix multiplication when followed by whitespace. */
- if (text_check_whitespace(string[1])) {
- return -1;
- }
-
- int i = 1;
- while (text_check_identifier(string[i])) {
- i++;
- }
- return i;
+ if (string[0] != '@') {
+ return -1;
+ }
+ if (!text_check_identifier(string[1])) {
+ return -1;
+ }
+ /* Interpret as matrix multiplication when followed by whitespace. */
+ if (text_check_whitespace(string[1])) {
+ return -1;
+ }
+
+ int i = 1;
+ while (text_check_identifier(string[i])) {
+ i++;
+ }
+ return i;
}
static int txtfmt_py_find_bool(const char *string)
{
- int i, len;
+ int i, len;
- /* Keep aligned args for readability. */
- /* clang-format off */
+ /* Keep aligned args for readability. */
+ /* clang-format off */
- if (STR_LITERAL_STARTSWITH(string, "None", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "True", len)) i = len;
- else if (STR_LITERAL_STARTSWITH(string, "False", len)) i = len;
- else i = 0;
+ if (STR_LITERAL_STARTSWITH(string, "None", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "True", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "False", len)) i = len;
+ else i = 0;
- /* clang-format on */
+ /* clang-format on */
- /* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
- if (i == 0 || text_check_identifier(string[i]))
- return -1;
- return i;
+ /* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
}
static char txtfmt_py_format_identifier(const char *str)
{
- char fmt;
+ char fmt;
- /* Keep aligned args for readability. */
- /* clang-format off */
+ /* Keep aligned args for readability. */
+ /* clang-format off */
- if ((txtfmt_py_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL;
- else if ((txtfmt_py_find_builtinfunc(str)) != -1) fmt = FMT_TYPE_KEYWORD;
- else if ((txtfmt_py_find_decorator(str)) != -1) fmt = FMT_TYPE_RESERVED;
- else fmt = FMT_TYPE_DEFAULT;
+ if ((txtfmt_py_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL;
+ else if ((txtfmt_py_find_builtinfunc(str)) != -1) fmt = FMT_TYPE_KEYWORD;
+ else if ((txtfmt_py_find_decorator(str)) != -1) fmt = FMT_TYPE_RESERVED;
+ else fmt = FMT_TYPE_DEFAULT;
- /* clang-format on */
- return fmt;
+ /* clang-format on */
+ return fmt;
}
static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const bool do_next)
{
- FlattenString fs;
- const char *str;
- char *fmt;
- char cont_orig, cont, find, prev = ' ';
- int len, i;
-
- /* Get continuation from previous line */
- if (line->prev && line->prev->format != NULL) {
- fmt = line->prev->format;
- cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
- BLI_assert((FMT_CONT_ALL & cont) == cont);
- }
- else {
- cont = FMT_CONT_NOP;
- }
-
- /* Get original continuation from this line */
- if (line->format != NULL) {
- fmt = line->format;
- cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
- BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
- }
- else {
- cont_orig = 0xFF;
- }
-
- len = flatten_string(st, &fs, line->line);
- str = fs.buf;
- if (!text_check_format_len(line, len)) {
- flatten_string_free(&fs);
- return;
- }
- fmt = line->format;
-
- while (*str) {
- /* Handle escape sequences by skipping both \ and next char */
- if (*str == '\\') {
- *fmt = prev; fmt++; str++;
- if (*str == '\0') break;
- *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str);
- continue;
- }
- /* Handle continuations */
- else if (cont) {
- /* Triple strings ("""...""" or '''...''') */
- if (cont & FMT_CONT_TRIPLE) {
- find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
- if (*str == find && *(str + 1) == find && *(str + 2) == find) {
- *fmt = FMT_TYPE_STRING; fmt++; str++;
- *fmt = FMT_TYPE_STRING; fmt++; str++;
- cont = FMT_CONT_NOP;
- }
- /* Handle other strings */
- }
- else {
- find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
- if (*str == find) cont = FMT_CONT_NOP;
- }
-
- *fmt = FMT_TYPE_STRING;
- str += BLI_str_utf8_size_safe(str) - 1;
- }
- /* Not in a string... */
- else {
- /* Deal with comments first */
- if (*str == '#') {
- /* fill the remaining line */
- text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format));
- }
- else if (*str == '"' || *str == '\'') {
- /* Strings */
- find = *str;
- cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
- if (*(str + 1) == find && *(str + 2) == find) {
- *fmt = FMT_TYPE_STRING; fmt++; str++;
- *fmt = FMT_TYPE_STRING; fmt++; str++;
- cont |= FMT_CONT_TRIPLE;
- }
- *fmt = FMT_TYPE_STRING;
- }
- /* Whitespace (all ws. has been converted to spaces) */
- else if (*str == ' ') {
- *fmt = FMT_TYPE_WHITESPACE;
- }
- /* Numbers (digits not part of an identifier and periods followed by digits) */
- else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
- (*str == '.' && text_check_digit(*(str + 1))))
- {
- *fmt = FMT_TYPE_NUMERAL;
- }
- /* Booleans */
- else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_py_find_bool(str)) != -1) {
- if (i > 0) {
- text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i);
- }
- else {
- str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = FMT_TYPE_DEFAULT;
- }
- }
- /* Punctuation */
- else if ((*str != '@') && text_check_delim(*str)) {
- *fmt = FMT_TYPE_SYMBOL;
- }
- /* Identifiers and other text (no previous ws. or delims. so text continues) */
- else if (prev == FMT_TYPE_DEFAULT) {
- str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = FMT_TYPE_DEFAULT;
- }
- /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
- else {
- /* Keep aligned args for readability. */
- /* clang-format off */
-
- /* Special vars(v) or built-in keywords(b) */
- /* keep in sync with 'txtfmt_py_format_identifier()' */
- if ((i = txtfmt_py_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL;
- else if ((i = txtfmt_py_find_builtinfunc(str)) != -1) prev = FMT_TYPE_KEYWORD;
- else if ((i = txtfmt_py_find_decorator(str)) != -1) prev = FMT_TYPE_DIRECTIVE;
-
- /* clang-format on */
-
- if (i > 0) {
- if (prev == FMT_TYPE_DIRECTIVE) { /* can contain utf8 */
- text_format_fill(&str, &fmt, prev, i);
- }
- else {
- text_format_fill_ascii(&str, &fmt, prev, i);
- }
- }
- else {
- str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = FMT_TYPE_DEFAULT;
- }
- }
- }
- prev = *fmt; fmt++; str++;
- }
-
- /* Terminate and add continuation char */
- *fmt = '\0'; fmt++;
- *fmt = cont;
-
- /* If continuation has changed and we're allowed, process the next line */
- if (cont != cont_orig && do_next && line->next) {
- txtfmt_py_format_line(st, line->next, do_next);
- }
-
- flatten_string_free(&fs);
+ FlattenString fs;
+ const char *str;
+ char *fmt;
+ char cont_orig, cont, find, prev = ' ';
+ int len, i;
+
+ /* Get continuation from previous line */
+ if (line->prev && line->prev->format != NULL) {
+ fmt = line->prev->format;
+ cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont) == cont);
+ }
+ else {
+ cont = FMT_CONT_NOP;
+ }
+
+ /* Get original continuation from this line */
+ if (line->format != NULL) {
+ fmt = line->format;
+ cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
+ }
+ else {
+ cont_orig = 0xFF;
+ }
+
+ len = flatten_string(st, &fs, line->line);
+ str = fs.buf;
+ if (!text_check_format_len(line, len)) {
+ flatten_string_free(&fs);
+ return;
+ }
+ fmt = line->format;
+
+ while (*str) {
+ /* Handle escape sequences by skipping both \ and next char */
+ if (*str == '\\') {
+ *fmt = prev;
+ fmt++;
+ str++;
+ if (*str == '\0')
+ break;
+ *fmt = prev;
+ fmt++;
+ str += BLI_str_utf8_size_safe(str);
+ continue;
+ }
+ /* Handle continuations */
+ else if (cont) {
+ /* Triple strings ("""...""" or '''...''') */
+ if (cont & FMT_CONT_TRIPLE) {
+ find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
+ if (*str == find && *(str + 1) == find && *(str + 2) == find) {
+ *fmt = FMT_TYPE_STRING;
+ fmt++;
+ str++;
+ *fmt = FMT_TYPE_STRING;
+ fmt++;
+ str++;
+ cont = FMT_CONT_NOP;
+ }
+ /* Handle other strings */
+ }
+ else {
+ find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
+ if (*str == find)
+ cont = FMT_CONT_NOP;
+ }
+
+ *fmt = FMT_TYPE_STRING;
+ str += BLI_str_utf8_size_safe(str) - 1;
+ }
+ /* Not in a string... */
+ else {
+ /* Deal with comments first */
+ if (*str == '#') {
+ /* fill the remaining line */
+ text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format));
+ }
+ else if (*str == '"' || *str == '\'') {
+ /* Strings */
+ find = *str;
+ cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
+ if (*(str + 1) == find && *(str + 2) == find) {
+ *fmt = FMT_TYPE_STRING;
+ fmt++;
+ str++;
+ *fmt = FMT_TYPE_STRING;
+ fmt++;
+ str++;
+ cont |= FMT_CONT_TRIPLE;
+ }
+ *fmt = FMT_TYPE_STRING;
+ }
+ /* Whitespace (all ws. has been converted to spaces) */
+ else if (*str == ' ') {
+ *fmt = FMT_TYPE_WHITESPACE;
+ }
+ /* Numbers (digits not part of an identifier and periods followed by digits) */
+ else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
+ (*str == '.' && text_check_digit(*(str + 1)))) {
+ *fmt = FMT_TYPE_NUMERAL;
+ }
+ /* Booleans */
+ else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_py_find_bool(str)) != -1) {
+ if (i > 0) {
+ text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i);
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ /* Punctuation */
+ else if ((*str != '@') && text_check_delim(*str)) {
+ *fmt = FMT_TYPE_SYMBOL;
+ }
+ /* Identifiers and other text (no previous ws. or delims. so text continues) */
+ else if (prev == FMT_TYPE_DEFAULT) {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
+ else {
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ /* Special vars(v) or built-in keywords(b) */
+ /* keep in sync with 'txtfmt_py_format_identifier()' */
+ if ((i = txtfmt_py_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL;
+ else if ((i = txtfmt_py_find_builtinfunc(str)) != -1) prev = FMT_TYPE_KEYWORD;
+ else if ((i = txtfmt_py_find_decorator(str)) != -1) prev = FMT_TYPE_DIRECTIVE;
+
+ /* clang-format on */
+
+ if (i > 0) {
+ if (prev == FMT_TYPE_DIRECTIVE) { /* can contain utf8 */
+ text_format_fill(&str, &fmt, prev, i);
+ }
+ else {
+ text_format_fill_ascii(&str, &fmt, prev, i);
+ }
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ }
+ prev = *fmt;
+ fmt++;
+ str++;
+ }
+
+ /* Terminate and add continuation char */
+ *fmt = '\0';
+ fmt++;
+ *fmt = cont;
+
+ /* If continuation has changed and we're allowed, process the next line */
+ if (cont != cont_orig && do_next && line->next) {
+ txtfmt_py_format_line(st, line->next, do_next);
+ }
+
+ flatten_string_free(&fs);
}
void ED_text_format_register_py(void)
{
- static TextFormatType tft = {NULL};
- static const char *ext[] = {"py", NULL};
+ static TextFormatType tft = {NULL};
+ static const char *ext[] = {"py", NULL};
- tft.format_identifier = txtfmt_py_format_identifier;
- tft.format_line = txtfmt_py_format_line;
- tft.ext = ext;
+ tft.format_identifier = txtfmt_py_format_identifier;
+ tft.format_line = txtfmt_py_format_line;
+ tft.ext = ext;
- ED_text_format_register(&tft);
+ ED_text_format_register(&tft);
}
diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c
index e76fab28327..435a6fd67de 100644
--- a/source/blender/editors/space_text/text_header.c
+++ b/source/blender/editors/space_text/text_header.c
@@ -27,7 +27,6 @@
#include "BLI_blenlib.h"
-
#include "BKE_context.h"
#include "BKE_screen.h"
@@ -43,165 +42,166 @@
static ARegion *text_has_properties_region(ScrArea *sa)
{
- ARegion *ar, *arnew;
+ ARegion *ar, *arnew;
- ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
- if (ar) return ar;
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
+ if (ar)
+ return ar;
- /* add subdiv level; after header */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+ /* add subdiv level; after header */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
- /* is error! */
- if (ar == NULL) return NULL;
+ /* is error! */
+ if (ar == NULL)
+ return NULL;
- arnew = MEM_callocN(sizeof(ARegion), "properties region");
+ arnew = MEM_callocN(sizeof(ARegion), "properties region");
- BLI_insertlinkafter(&sa->regionbase, ar, arnew);
- arnew->regiontype = RGN_TYPE_UI;
- arnew->alignment = RGN_ALIGN_LEFT;
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype = RGN_TYPE_UI;
+ arnew->alignment = RGN_ALIGN_LEFT;
- arnew->flag = RGN_FLAG_HIDDEN;
+ arnew->flag = RGN_FLAG_HIDDEN;
- return arnew;
+ return arnew;
}
static bool text_properties_poll(bContext *C)
{
- return (CTX_wm_space_text(C) != NULL);
+ return (CTX_wm_space_text(C) != NULL);
}
static int text_properties_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = text_has_properties_region(sa);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = text_has_properties_region(sa);
- if (ar)
- ED_region_toggle_hidden(C, ar);
+ if (ar)
+ ED_region_toggle_hidden(C, ar);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_properties(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Sidebar";
- ot->description = "Toggle the properties region visibility";
- ot->idname = "TEXT_OT_properties";
-
- /* api callbacks */
- ot->exec = text_properties_exec;
- ot->poll = text_properties_poll;
+ /* identifiers */
+ ot->name = "Toggle Sidebar";
+ ot->description = "Toggle the properties region visibility";
+ ot->idname = "TEXT_OT_properties";
+
+ /* api callbacks */
+ ot->exec = text_properties_exec;
+ ot->poll = text_properties_poll;
}
static int text_text_search_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = text_has_properties_region(sa);
- SpaceText *st = CTX_wm_space_text(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = text_has_properties_region(sa);
+ SpaceText *st = CTX_wm_space_text(C);
- if (ar) {
- if (ar->flag & RGN_FLAG_HIDDEN)
- ED_region_toggle_hidden(C, ar);
+ if (ar) {
+ if (ar->flag & RGN_FLAG_HIDDEN)
+ ED_region_toggle_hidden(C, ar);
- /* 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;
+ /* 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);
- }
- return OPERATOR_FINISHED;
+ ED_region_tag_redraw(ar);
+ }
+ return OPERATOR_FINISHED;
}
-
void TEXT_OT_start_find(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Find";
- ot->description = "Start searching text";
- ot->idname = "TEXT_OT_start_find";
-
- /* api callbacks */
- ot->exec = text_text_search_exec;
- ot->poll = text_properties_poll;
+ /* identifiers */
+ ot->name = "Find";
+ ot->description = "Start searching text";
+ ot->idname = "TEXT_OT_start_find";
+
+ /* api callbacks */
+ ot->exec = text_text_search_exec;
+ ot->poll = text_properties_poll;
}
/******************** XXX popup menus *******************/
#if 0
{
- // RMB
-
- uiPopupMenu *pup;
-
- if (text) {
- pup = UI_popup_menu_begin(C, IFACE_("Text"), ICON_NONE);
- if (txt_has_sel(text)) {
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_cut");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_copy");
- }
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_paste");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save_as");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_run_script");
- UI_popup_menu_end(C, pup);
- }
- else {
- pup = UI_popup_menu_begin(C, IFACE_("File"), ICON_NONE);
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open");
- UI_popup_menu_end(C, pup);
- }
+ // RMB
+
+ uiPopupMenu *pup;
+
+ if (text) {
+ pup = UI_popup_menu_begin(C, IFACE_("Text"), ICON_NONE);
+ if (txt_has_sel(text)) {
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_cut");
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_copy");
+ }
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_paste");
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new");
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open");
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save");
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save_as");
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_run_script");
+ UI_popup_menu_end(C, pup);
+ }
+ else {
+ pup = UI_popup_menu_begin(C, IFACE_("File"), ICON_NONE);
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new");
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open");
+ UI_popup_menu_end(C, pup);
+ }
}
{
- // Alt+Shift+E
+ // Alt+Shift+E
- uiPopupMenu *pup;
+ uiPopupMenu *pup;
- pup = UI_popup_menu_begin(C, IFACE_("Edit"), ICON_NONE);
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_cut");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_copy");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_paste");
- UI_popup_menu_end(C, pup);
+ pup = UI_popup_menu_begin(C, IFACE_("Edit"), ICON_NONE);
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_cut");
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_copy");
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_paste");
+ UI_popup_menu_end(C, pup);
}
{
- // Alt+Shift+F
-
- uiPopupMenu *pup;
-
- if (text) {
- pup = UI_popup_menu_begin(C, IFACE_("Text"), ICON_NONE);
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save_as");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_run_script");
- UI_popup_menu_end(C, pup);
- }
- else {
- pup = UI_popup_menu_begin(C, IFACE_("File"), ICON_NONE);
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new");
- uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open");
- UI_popup_menu_end(C, pup);
- }
+ // Alt+Shift+F
+
+ uiPopupMenu *pup;
+
+ if (text) {
+ pup = UI_popup_menu_begin(C, IFACE_("Text"), ICON_NONE);
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new");
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open");
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save");
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save_as");
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_run_script");
+ UI_popup_menu_end(C, pup);
+ }
+ else {
+ pup = UI_popup_menu_begin(C, IFACE_("File"), ICON_NONE);
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new");
+ uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open");
+ UI_popup_menu_end(C, pup);
+ }
}
{
- // Alt+Shift+V
-
- uiPopupMenu *pup;
-
- pup = UI_popup_menu_begin(C, IFACE_("Text"), ICON_NONE);
- uiItemEnumO(layout, "TEXT_OT_move", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Top of File"),
- 0, "type", FILE_TOP);
- uiItemEnumO(layout, "TEXT_OT_move", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Bottom of File"),
- 0, "type", FILE_BOTTOM);
- uiItemEnumO(layout, "TEXT_OT_move", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Page Up"), 0, "type", PREV_PAGE);
- uiItemEnumO(layout, "TEXT_OT_move", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Page Down"),
- 0, "type", NEXT_PAGE);
- UI_popup_menu_end(C, pup);
+ // Alt+Shift+V
+
+ uiPopupMenu *pup;
+
+ pup = UI_popup_menu_begin(C, IFACE_("Text"), ICON_NONE);
+ uiItemEnumO(layout, "TEXT_OT_move", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Top of File"),
+ 0, "type", FILE_TOP);
+ uiItemEnumO(layout, "TEXT_OT_move", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Bottom of File"),
+ 0, "type", FILE_BOTTOM);
+ uiItemEnumO(layout, "TEXT_OT_move", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Page Up"), 0, "type", PREV_PAGE);
+ uiItemEnumO(layout, "TEXT_OT_move", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Page Down"),
+ 0, "type", NEXT_PAGE);
+ UI_popup_menu_end(C, pup);
}
#endif
diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h
index bf31469c322..cf28f3d317c 100644
--- a/source/blender/editors/space_text/text_intern.h
+++ b/source/blender/editors/space_text/text_intern.h
@@ -44,23 +44,33 @@ void text_scroll_to_cursor(struct SpaceText *st, struct ARegion *ar, const bool
void text_scroll_to_cursor__area(struct SpaceText *st, struct ScrArea *sa, const bool center);
void text_update_cursor_moved(struct bContext *C);
-#define TXT_OFFSET ((int)(0.5f * U.widget_unit))
-#define TXT_SCROLL_WIDTH U.widget_unit
-#define TXT_SCROLL_SPACE ((int)(0.1f * U.widget_unit))
-#define TXT_LINE_SPACING ((int)(0.3f * st->lheight_dpi)) /* space between lines */
-#define TEXTXLOC (st->cwidth * st->linenrs_tot)
+#define TXT_OFFSET ((int)(0.5f * U.widget_unit))
+#define TXT_SCROLL_WIDTH U.widget_unit
+#define TXT_SCROLL_SPACE ((int)(0.1f * U.widget_unit))
+#define TXT_LINE_SPACING ((int)(0.3f * st->lheight_dpi)) /* space between lines */
+#define TEXTXLOC (st->cwidth * st->linenrs_tot)
-#define SUGG_LIST_SIZE 7
-#define SUGG_LIST_WIDTH 20
-#define DOC_WIDTH 40
-#define DOC_HEIGHT 10
+#define SUGG_LIST_SIZE 7
+#define SUGG_LIST_WIDTH 20
+#define DOC_WIDTH 40
+#define DOC_HEIGHT 10
-#define TOOL_SUGG_LIST 0x01
-#define TOOL_DOCUMENT 0x02
+#define TOOL_SUGG_LIST 0x01
+#define TOOL_DOCUMENT 0x02
int wrap_width(const struct SpaceText *st, struct ARegion *ar);
-void wrap_offset(const struct SpaceText *st, struct ARegion *ar, struct TextLine *linein, int cursin, int *offl, int *offc);
-void wrap_offset_in_line(const struct SpaceText *st, struct ARegion *ar, struct TextLine *linep, int cursin, int *offl, int *offc);
+void wrap_offset(const struct SpaceText *st,
+ struct ARegion *ar,
+ struct TextLine *linein,
+ int cursin,
+ int *offl,
+ int *offc);
+void wrap_offset_in_line(const struct SpaceText *st,
+ struct ARegion *ar,
+ struct TextLine *linep,
+ int cursin,
+ int *offl,
+ int *offc);
int text_get_char_pos(const struct SpaceText *st, const char *line, int cur);
void text_drawcache_tag_update(struct SpaceText *st, int full);
@@ -70,12 +80,27 @@ int text_do_suggest_select(struct SpaceText *st, struct ARegion *ar);
void text_pop_suggest_list(void);
int text_get_visible_lines(const struct SpaceText *st, struct ARegion *ar, const char *str);
-int text_get_span_wrap(const struct SpaceText *st, struct ARegion *ar, struct TextLine *from, struct TextLine *to);
+int text_get_span_wrap(const struct SpaceText *st,
+ struct ARegion *ar,
+ struct TextLine *from,
+ struct TextLine *to);
int text_get_total_lines(struct SpaceText *st, struct ARegion *ar);
/* text_ops.c */
-enum { LINE_BEGIN, LINE_END, FILE_TOP, FILE_BOTTOM, PREV_CHAR, NEXT_CHAR,
- PREV_WORD, NEXT_WORD, PREV_LINE, NEXT_LINE, PREV_PAGE, NEXT_PAGE };
+enum {
+ LINE_BEGIN,
+ LINE_END,
+ FILE_TOP,
+ FILE_BOTTOM,
+ PREV_CHAR,
+ NEXT_CHAR,
+ PREV_WORD,
+ NEXT_WORD,
+ PREV_LINE,
+ NEXT_LINE,
+ PREV_PAGE,
+ NEXT_PAGE
+};
enum { DEL_NEXT_CHAR, DEL_PREV_CHAR, DEL_NEXT_WORD, DEL_PREV_WORD };
void TEXT_OT_new(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 2bf1dff63c1..c069fc600e8 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -21,7 +21,6 @@
* \ingroup sptext
*/
-
#include <string.h>
#include <errno.h>
@@ -54,7 +53,7 @@
#include "RNA_define.h"
#ifdef WITH_PYTHON
-#include "BPY_extern.h"
+# include "BPY_extern.h"
#endif
#include "text_intern.h"
@@ -64,593 +63,610 @@ static void txt_screen_clamp(SpaceText *st, ARegion *ar);
/************************ poll ***************************/
-
BLI_INLINE int text_pixel_x_to_column(SpaceText *st, const int x)
{
- /* add half the char width so mouse cursor selection is inbetween letters */
- return (x + (st->cwidth / 2)) / st->cwidth;
+ /* add half the char width so mouse cursor selection is inbetween letters */
+ return (x + (st->cwidth / 2)) / st->cwidth;
}
static bool text_new_poll(bContext *UNUSED(C))
{
- return 1;
+ return 1;
}
static bool text_edit_poll(bContext *C)
{
- Text *text = CTX_data_edit_text(C);
+ Text *text = CTX_data_edit_text(C);
- if (!text)
- return 0;
+ if (!text)
+ return 0;
- if (ID_IS_LINKED(text)) {
- // BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
- return 0;
- }
+ if (ID_IS_LINKED(text)) {
+ // BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
+ return 0;
+ }
- return 1;
+ return 1;
}
bool text_space_edit_poll(bContext *C)
{
- SpaceText *st = CTX_wm_space_text(C);
- Text *text = CTX_data_edit_text(C);
+ SpaceText *st = CTX_wm_space_text(C);
+ Text *text = CTX_data_edit_text(C);
- if (!st || !text)
- return 0;
+ if (!st || !text)
+ return 0;
- if (ID_IS_LINKED(text)) {
- // BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
- return 0;
- }
+ if (ID_IS_LINKED(text)) {
+ // BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
+ return 0;
+ }
- return 1;
+ return 1;
}
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);
+ SpaceText *st = CTX_wm_space_text(C);
+ Text *text = CTX_data_edit_text(C);
+ ARegion *ar = CTX_wm_region(C);
- if (!st || !text)
- return 0;
+ if (!st || !text)
+ return 0;
- if (!ar || ar->regiontype != RGN_TYPE_WINDOW)
- return 0;
+ if (!ar || ar->regiontype != RGN_TYPE_WINDOW)
+ return 0;
- if (ID_IS_LINKED(text)) {
- // BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
- return 0;
- }
+ if (ID_IS_LINKED(text)) {
+ // BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
+ return 0;
+ }
- return 1;
+ return 1;
}
/********************** updates *********************/
void text_update_line_edited(TextLine *line)
{
- if (!line)
- return;
+ if (!line)
+ return;
- /* we just free format here, and let it rebuild during draw */
- if (line->format) {
- MEM_freeN(line->format);
- line->format = NULL;
- }
+ /* we just free format here, and let it rebuild during draw */
+ if (line->format) {
+ MEM_freeN(line->format);
+ line->format = NULL;
+ }
}
void text_update_edited(Text *text)
{
- TextLine *line;
+ TextLine *line;
- for (line = text->lines.first; line; line = line->next)
- text_update_line_edited(line);
+ for (line = text->lines.first; line; line = line->next)
+ text_update_line_edited(line);
}
/******************* new operator *********************/
static int text_new_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceText *st = CTX_wm_space_text(C);
- Main *bmain = CTX_data_main(C);
- Text *text;
- PointerRNA ptr, idptr;
- PropertyRNA *prop;
+ SpaceText *st = CTX_wm_space_text(C);
+ Main *bmain = CTX_data_main(C);
+ Text *text;
+ PointerRNA ptr, idptr;
+ PropertyRNA *prop;
- text = BKE_text_add(bmain, "Text");
+ text = BKE_text_add(bmain, "Text");
- /* hook into UI */
- UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
+ /* hook into UI */
+ UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
- if (prop) {
- RNA_id_pointer_create(&text->id, &idptr);
- RNA_property_pointer_set(&ptr, prop, idptr);
- RNA_property_update(C, &ptr, prop);
- }
- else if (st) {
- st->text = text;
- st->left = 0;
- st->top = 0;
- st->scroll_accum[0] = 0.0f;
- st->scroll_accum[1] = 0.0f;
- text_drawcache_tag_update(st, 1);
- }
+ if (prop) {
+ RNA_id_pointer_create(&text->id, &idptr);
+ RNA_property_pointer_set(&ptr, prop, idptr);
+ RNA_property_update(C, &ptr, prop);
+ }
+ else if (st) {
+ st->text = text;
+ st->left = 0;
+ st->top = 0;
+ st->scroll_accum[0] = 0.0f;
+ st->scroll_accum[1] = 0.0f;
+ text_drawcache_tag_update(st, 1);
+ }
- WM_event_add_notifier(C, NC_TEXT | NA_ADDED, text);
+ WM_event_add_notifier(C, NC_TEXT | NA_ADDED, text);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_new(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "New Text";
- ot->idname = "TEXT_OT_new";
- ot->description = "Create a new text data-block";
+ /* identifiers */
+ ot->name = "New Text";
+ ot->idname = "TEXT_OT_new";
+ ot->description = "Create a new text data-block";
- /* api callbacks */
- ot->exec = text_new_exec;
- ot->poll = text_new_poll;
+ /* api callbacks */
+ ot->exec = text_new_exec;
+ ot->poll = text_new_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* open operator *********************/
static void text_open_init(bContext *C, wmOperator *op)
{
- PropertyPointerRNA *pprop;
+ PropertyPointerRNA *pprop;
- op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
- UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
+ op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
+ UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
}
static void text_open_cancel(bContext *UNUSED(C), wmOperator *op)
{
- MEM_freeN(op->customdata);
+ MEM_freeN(op->customdata);
}
static int text_open_exec(bContext *C, wmOperator *op)
{
- SpaceText *st = CTX_wm_space_text(C);
- Main *bmain = CTX_data_main(C);
- Text *text;
- PropertyPointerRNA *pprop;
- PointerRNA idptr;
- char str[FILE_MAX];
- const bool internal = RNA_boolean_get(op->ptr, "internal");
+ SpaceText *st = CTX_wm_space_text(C);
+ Main *bmain = CTX_data_main(C);
+ Text *text;
+ PropertyPointerRNA *pprop;
+ PointerRNA idptr;
+ char str[FILE_MAX];
+ const bool internal = RNA_boolean_get(op->ptr, "internal");
- RNA_string_get(op->ptr, "filepath", str);
+ RNA_string_get(op->ptr, "filepath", str);
- text = BKE_text_load_ex(bmain, str, BKE_main_blendfile_path(bmain), internal);
+ text = BKE_text_load_ex(bmain, str, BKE_main_blendfile_path(bmain), internal);
- if (!text) {
- if (op->customdata) MEM_freeN(op->customdata);
- return OPERATOR_CANCELLED;
- }
+ if (!text) {
+ if (op->customdata)
+ MEM_freeN(op->customdata);
+ return OPERATOR_CANCELLED;
+ }
- if (!op->customdata)
- text_open_init(C, op);
+ if (!op->customdata)
+ text_open_init(C, op);
- /* hook into UI */
- pprop = op->customdata;
+ /* hook into UI */
+ pprop = op->customdata;
- id_us_ensure_real(&text->id);
+ id_us_ensure_real(&text->id);
- if (pprop->prop) {
- RNA_id_pointer_create(&text->id, &idptr);
- RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
- RNA_property_update(C, &pprop->ptr, pprop->prop);
- }
- else if (st) {
- st->text = text;
- st->left = 0;
- st->top = 0;
- st->scroll_accum[0] = 0.0f;
- st->scroll_accum[1] = 0.0f;
- }
+ if (pprop->prop) {
+ RNA_id_pointer_create(&text->id, &idptr);
+ RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
+ RNA_property_update(C, &pprop->ptr, pprop->prop);
+ }
+ else if (st) {
+ st->text = text;
+ st->left = 0;
+ st->top = 0;
+ st->scroll_accum[0] = 0.0f;
+ st->scroll_accum[1] = 0.0f;
+ }
- text_drawcache_tag_update(st, 1);
- WM_event_add_notifier(C, NC_TEXT | NA_ADDED, text);
+ text_drawcache_tag_update(st, 1);
+ WM_event_add_notifier(C, NC_TEXT | NA_ADDED, text);
- MEM_freeN(op->customdata);
+ MEM_freeN(op->customdata);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int text_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Main *bmain = CTX_data_main(C);
- Text *text = CTX_data_edit_text(C);
- const char *path = (text && text->name) ? text->name : BKE_main_blendfile_path(bmain);
+ Main *bmain = CTX_data_main(C);
+ Text *text = CTX_data_edit_text(C);
+ const char *path = (text && text->name) ? text->name : BKE_main_blendfile_path(bmain);
- if (RNA_struct_property_is_set(op->ptr, "filepath"))
- return text_open_exec(C, op);
+ if (RNA_struct_property_is_set(op->ptr, "filepath"))
+ return text_open_exec(C, op);
- text_open_init(C, op);
- RNA_string_set(op->ptr, "filepath", path);
- WM_event_add_fileselect(C, op);
+ text_open_init(C, op);
+ RNA_string_set(op->ptr, "filepath", path);
+ WM_event_add_fileselect(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void TEXT_OT_open(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Open Text";
- ot->idname = "TEXT_OT_open";
- ot->description = "Open a new text data-block";
+ /* identifiers */
+ ot->name = "Open Text";
+ ot->idname = "TEXT_OT_open";
+ ot->description = "Open a new text data-block";
- /* api callbacks */
- ot->exec = text_open_exec;
- ot->invoke = text_open_invoke;
- ot->cancel = text_open_cancel;
- ot->poll = text_new_poll;
+ /* api callbacks */
+ ot->exec = text_open_exec;
+ ot->invoke = text_open_invoke;
+ ot->cancel = text_open_cancel;
+ ot->poll = text_new_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_TEXT | FILE_TYPE_PYSCRIPT, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); //XXX TODO, relative_path
- RNA_def_boolean(ot->srna, "internal", 0, "Make internal", "Make text file internal after loading");
+ /* properties */
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_TEXT | FILE_TYPE_PYSCRIPT,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_FILEPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA); //XXX TODO, relative_path
+ RNA_def_boolean(
+ ot->srna, "internal", 0, "Make internal", "Make text file internal after loading");
}
/******************* reload operator *********************/
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);
+ SpaceText *st = CTX_wm_space_text(C);
+ Text *text = CTX_data_edit_text(C);
+ ARegion *ar = CTX_wm_region(C);
- /* store view & cursor state */
- const int orig_top = st->top;
- const int orig_curl = BLI_findindex(&text->lines, text->curl);
- const int orig_curc = text->curc;
+ /* store view & cursor state */
+ const int orig_top = st->top;
+ const int orig_curl = BLI_findindex(&text->lines, text->curl);
+ const int orig_curc = text->curc;
- if (!BKE_text_reload(text)) {
- BKE_report(op->reports, RPT_ERROR, "Could not reopen file");
- return OPERATOR_CANCELLED;
- }
+ if (!BKE_text_reload(text)) {
+ BKE_report(op->reports, RPT_ERROR, "Could not reopen file");
+ return OPERATOR_CANCELLED;
+ }
#ifdef WITH_PYTHON
- if (text->compiled)
- BPY_text_free_code(text);
+ if (text->compiled)
+ BPY_text_free_code(text);
#endif
- text_update_edited(text);
- text_update_cursor_moved(C);
- text_drawcache_tag_update(CTX_wm_space_text(C), 1);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ text_update_edited(text);
+ text_update_cursor_moved(C);
+ text_drawcache_tag_update(CTX_wm_space_text(C), 1);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- /* return to scroll position */
- st->top = orig_top;
- txt_screen_clamp(st, ar);
- /* return cursor */
- txt_move_to(text, orig_curl, orig_curc, false);
+ /* return to scroll position */
+ st->top = orig_top;
+ txt_screen_clamp(st, ar);
+ /* return cursor */
+ txt_move_to(text, orig_curl, orig_curc, false);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_reload(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reload";
- ot->idname = "TEXT_OT_reload";
- ot->description = "Reload active text data-block from its file";
+ /* identifiers */
+ ot->name = "Reload";
+ ot->idname = "TEXT_OT_reload";
+ ot->description = "Reload active text data-block from its file";
- /* api callbacks */
- ot->exec = text_reload_exec;
- ot->invoke = WM_operator_confirm;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_reload_exec;
+ ot->invoke = WM_operator_confirm;
+ ot->poll = text_edit_poll;
}
/******************* delete operator *********************/
static bool text_unlink_poll(bContext *C)
{
- /* it should be possible to unlink texts if they're lib-linked in... */
- return CTX_data_edit_text(C) != NULL;
+ /* it should be possible to unlink texts if they're lib-linked in... */
+ return CTX_data_edit_text(C) != NULL;
}
static int text_unlink_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- SpaceText *st = CTX_wm_space_text(C);
- Text *text = CTX_data_edit_text(C);
+ Main *bmain = CTX_data_main(C);
+ SpaceText *st = CTX_wm_space_text(C);
+ Text *text = CTX_data_edit_text(C);
- /* make the previous text active, if its not there make the next text active */
- if (st) {
- if (text->id.prev) {
- st->text = text->id.prev;
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
- }
- else if (text->id.next) {
- st->text = text->id.next;
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
- }
- }
+ /* make the previous text active, if its not there make the next text active */
+ if (st) {
+ if (text->id.prev) {
+ st->text = text->id.prev;
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
+ }
+ else if (text->id.next) {
+ st->text = text->id.next;
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
+ }
+ }
- BKE_id_delete(bmain, text);
+ BKE_id_delete(bmain, text);
- text_drawcache_tag_update(st, 1);
- WM_event_add_notifier(C, NC_TEXT | NA_REMOVED, NULL);
+ text_drawcache_tag_update(st, 1);
+ WM_event_add_notifier(C, NC_TEXT | NA_REMOVED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_unlink(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unlink";
- ot->idname = "TEXT_OT_unlink";
- ot->description = "Unlink active text data-block";
+ /* identifiers */
+ ot->name = "Unlink";
+ ot->idname = "TEXT_OT_unlink";
+ ot->description = "Unlink active text data-block";
- /* api callbacks */
- ot->exec = text_unlink_exec;
- ot->invoke = WM_operator_confirm;
- ot->poll = text_unlink_poll;
+ /* api callbacks */
+ ot->exec = text_unlink_exec;
+ ot->invoke = WM_operator_confirm;
+ ot->poll = text_unlink_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* make internal operator *********************/
static int text_make_internal_exec(bContext *C, wmOperator *UNUSED(op))
{
- Text *text = CTX_data_edit_text(C);
+ Text *text = CTX_data_edit_text(C);
- text->flags |= TXT_ISMEM | TXT_ISDIRTY;
+ text->flags |= TXT_ISMEM | TXT_ISDIRTY;
- if (text->name) {
- MEM_freeN(text->name);
- text->name = NULL;
- }
+ if (text->name) {
+ MEM_freeN(text->name);
+ text->name = NULL;
+ }
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_make_internal(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Internal";
- ot->idname = "TEXT_OT_make_internal";
- ot->description = "Make active text file internal";
+ /* identifiers */
+ ot->name = "Make Internal";
+ ot->idname = "TEXT_OT_make_internal";
+ ot->description = "Make active text file internal";
- /* api callbacks */
- ot->exec = text_make_internal_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_make_internal_exec;
+ ot->poll = text_edit_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* save operator *********************/
static bool text_save_poll(bContext *C)
{
- Text *text = CTX_data_edit_text(C);
+ Text *text = CTX_data_edit_text(C);
- if (!text_edit_poll(C))
- return 0;
+ if (!text_edit_poll(C))
+ return 0;
- return (text->name != NULL && !(text->flags & TXT_ISMEM));
+ return (text->name != NULL && !(text->flags & TXT_ISMEM));
}
static void txt_write_file(Main *bmain, Text *text, ReportList *reports)
{
- FILE *fp;
- TextLine *tmp;
- BLI_stat_t st;
- char filepath[FILE_MAX];
-
- BLI_strncpy(filepath, text->name, FILE_MAX);
- BLI_path_abs(filepath, BKE_main_blendfile_path(bmain));
-
- fp = BLI_fopen(filepath, "w");
- if (fp == NULL) {
- BKE_reportf(reports, RPT_ERROR, "Unable to save '%s': %s",
- filepath, errno ? strerror(errno) : TIP_("unknown error writing file"));
- return;
- }
-
- for (tmp = text->lines.first; tmp; tmp = tmp->next) {
- fputs(tmp->line, fp);
- if (tmp->next) {
- fputc('\n', fp);
- }
- }
-
- fclose(fp);
-
- if (BLI_stat(filepath, &st) == 0) {
- text->mtime = st.st_mtime;
-
- /* report since this can be called from key-shortcuts */
- BKE_reportf(reports, RPT_INFO, "Saved Text '%s'", filepath);
- }
- else {
- text->mtime = 0;
- BKE_reportf(reports, RPT_WARNING, "Unable to stat '%s': %s",
- filepath, errno ? strerror(errno) : TIP_("unknown error stating file"));
- }
-
- text->flags &= ~TXT_ISDIRTY;
+ FILE *fp;
+ TextLine *tmp;
+ BLI_stat_t st;
+ char filepath[FILE_MAX];
+
+ BLI_strncpy(filepath, text->name, FILE_MAX);
+ BLI_path_abs(filepath, BKE_main_blendfile_path(bmain));
+
+ fp = BLI_fopen(filepath, "w");
+ if (fp == NULL) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Unable to save '%s': %s",
+ filepath,
+ errno ? strerror(errno) : TIP_("unknown error writing file"));
+ return;
+ }
+
+ for (tmp = text->lines.first; tmp; tmp = tmp->next) {
+ fputs(tmp->line, fp);
+ if (tmp->next) {
+ fputc('\n', fp);
+ }
+ }
+
+ fclose(fp);
+
+ if (BLI_stat(filepath, &st) == 0) {
+ text->mtime = st.st_mtime;
+
+ /* report since this can be called from key-shortcuts */
+ BKE_reportf(reports, RPT_INFO, "Saved Text '%s'", filepath);
+ }
+ else {
+ text->mtime = 0;
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Unable to stat '%s': %s",
+ filepath,
+ errno ? strerror(errno) : TIP_("unknown error stating file"));
+ }
+
+ text->flags &= ~TXT_ISDIRTY;
}
static int text_save_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Text *text = CTX_data_edit_text(C);
+ Main *bmain = CTX_data_main(C);
+ Text *text = CTX_data_edit_text(C);
- txt_write_file(bmain, text, op->reports);
+ txt_write_file(bmain, text, op->reports);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_save(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Save";
- ot->idname = "TEXT_OT_save";
- ot->description = "Save active text data-block";
+ /* identifiers */
+ ot->name = "Save";
+ ot->idname = "TEXT_OT_save";
+ ot->description = "Save active text data-block";
- /* api callbacks */
- ot->exec = text_save_exec;
- ot->poll = text_save_poll;
+ /* api callbacks */
+ ot->exec = text_save_exec;
+ ot->poll = text_save_poll;
}
/******************* save as operator *********************/
static int text_save_as_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Text *text = CTX_data_edit_text(C);
- char str[FILE_MAX];
+ Main *bmain = CTX_data_main(C);
+ Text *text = CTX_data_edit_text(C);
+ char str[FILE_MAX];
- if (!text)
- return OPERATOR_CANCELLED;
+ if (!text)
+ return OPERATOR_CANCELLED;
- RNA_string_get(op->ptr, "filepath", str);
+ RNA_string_get(op->ptr, "filepath", str);
- if (text->name) MEM_freeN(text->name);
- text->name = BLI_strdup(str);
- text->flags &= ~TXT_ISMEM;
+ if (text->name)
+ MEM_freeN(text->name);
+ text->name = BLI_strdup(str);
+ text->flags &= ~TXT_ISMEM;
- txt_write_file(bmain, text, op->reports);
+ txt_write_file(bmain, text, op->reports);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int text_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Main *bmain = CTX_data_main(C);
- Text *text = CTX_data_edit_text(C);
- const char *str;
+ Main *bmain = CTX_data_main(C);
+ Text *text = CTX_data_edit_text(C);
+ const char *str;
- if (RNA_struct_property_is_set(op->ptr, "filepath"))
- return text_save_as_exec(C, op);
+ if (RNA_struct_property_is_set(op->ptr, "filepath"))
+ return text_save_as_exec(C, op);
- if (text->name)
- str = text->name;
- else if (text->flags & TXT_ISMEM)
- str = text->id.name + 2;
- else
- str = BKE_main_blendfile_path(bmain);
+ if (text->name)
+ str = text->name;
+ else if (text->flags & TXT_ISMEM)
+ str = text->id.name + 2;
+ else
+ str = BKE_main_blendfile_path(bmain);
- RNA_string_set(op->ptr, "filepath", str);
- WM_event_add_fileselect(C, op);
+ RNA_string_set(op->ptr, "filepath", str);
+ WM_event_add_fileselect(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void TEXT_OT_save_as(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Save As";
- ot->idname = "TEXT_OT_save_as";
- ot->description = "Save active text file with options";
+ /* identifiers */
+ ot->name = "Save As";
+ ot->idname = "TEXT_OT_save_as";
+ ot->description = "Save active text file with options";
- /* api callbacks */
- ot->exec = text_save_as_exec;
- ot->invoke = text_save_as_invoke;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_save_as_exec;
+ ot->invoke = text_save_as_invoke;
+ ot->poll = text_edit_poll;
- /* properties */
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_TEXT | FILE_TYPE_PYSCRIPT, FILE_SPECIAL, FILE_SAVE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); //XXX TODO, relative_path
+ /* properties */
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_TEXT | FILE_TYPE_PYSCRIPT,
+ FILE_SPECIAL,
+ FILE_SAVE,
+ WM_FILESEL_FILEPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA); //XXX TODO, relative_path
}
/******************* run script operator *********************/
static bool text_run_script_poll(bContext *C)
{
- return (CTX_data_edit_text(C) != NULL);
+ return (CTX_data_edit_text(C) != NULL);
}
static int text_run_script(bContext *C, ReportList *reports)
{
#ifdef WITH_PYTHON
- Text *text = CTX_data_edit_text(C);
- const bool is_live = (reports == NULL);
-
- /* only for comparison */
- void *curl_prev = text->curl;
- int curc_prev = text->curc;
-
- if (BPY_execute_text(C, text, reports, !is_live)) {
- if (is_live) {
- /* for nice live updates */
- WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL);
- }
- return OPERATOR_FINISHED;
- }
-
- /* Don't report error messages while live editing */
- if (!is_live) {
- /* text may have freed its self */
- if (CTX_data_edit_text(C) == text) {
- if (text->curl != curl_prev || curc_prev != text->curc) {
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- }
- }
-
- BKE_report(reports, RPT_ERROR, "Python script failed, check the message in the system console");
-
- return OPERATOR_FINISHED;
- }
+ Text *text = CTX_data_edit_text(C);
+ const bool is_live = (reports == NULL);
+
+ /* only for comparison */
+ void *curl_prev = text->curl;
+ int curc_prev = text->curc;
+
+ if (BPY_execute_text(C, text, reports, !is_live)) {
+ if (is_live) {
+ /* for nice live updates */
+ WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL);
+ }
+ return OPERATOR_FINISHED;
+ }
+
+ /* Don't report error messages while live editing */
+ if (!is_live) {
+ /* text may have freed its self */
+ if (CTX_data_edit_text(C) == text) {
+ if (text->curl != curl_prev || curc_prev != text->curc) {
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ }
+ }
+
+ BKE_report(
+ reports, RPT_ERROR, "Python script failed, check the message in the system console");
+
+ return OPERATOR_FINISHED;
+ }
#else
- (void)C;
- (void)reports;
+ (void)C;
+ (void)reports;
#endif /* !WITH_PYTHON */
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
static int text_run_script_exec(bContext *C, wmOperator *op)
{
#ifndef WITH_PYTHON
- (void)C; /* unused */
+ (void)C; /* unused */
- BKE_report(op->reports, RPT_ERROR, "Python disabled in this build");
+ BKE_report(op->reports, RPT_ERROR, "Python disabled in this build");
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
#else
- return text_run_script(C, op->reports);
+ return text_run_script(C, op->reports);
#endif
}
void TEXT_OT_run_script(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Run Script";
- ot->idname = "TEXT_OT_run_script";
- ot->description = "Run active script";
+ /* identifiers */
+ ot->name = "Run Script";
+ ot->idname = "TEXT_OT_run_script";
+ ot->description = "Run active script";
- /* api callbacks */
- ot->poll = text_run_script_poll;
- ot->exec = text_run_script_exec;
+ /* api callbacks */
+ ot->poll = text_run_script_poll;
+ ot->exec = text_run_script_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************* refresh pyconstraints operator *********************/
@@ -658,1087 +674,1136 @@ void TEXT_OT_run_script(wmOperatorType *ot)
static int text_refresh_pyconstraints_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
{
#ifdef WITH_PYTHON
-#if 0
- 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) {
- update = 0;
- if (ob->type == OB_ARMATURE && ob->pose) {
- bPoseChannel *pchan;
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- for (con = pchan->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_PYTHON) {
- bPythonConstraint *data = con->data;
- if (data->text == text) BPY_pyconstraint_update(ob, con);
- update = 1;
-
- }
- }
- }
- }
- for (con = ob->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_PYTHON) {
- bPythonConstraint *data = con->data;
- if (data->text == text) BPY_pyconstraint_update(ob, con);
- update = 1;
- }
- }
-
- if (update) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- }
-#endif
+# if 0
+ 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) {
+ update = 0;
+ if (ob->type == OB_ARMATURE && ob->pose) {
+ bPoseChannel *pchan;
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ for (con = pchan->constraints.first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_PYTHON) {
+ bPythonConstraint *data = con->data;
+ if (data->text == text) BPY_pyconstraint_update(ob, con);
+ update = 1;
+
+ }
+ }
+ }
+ }
+ for (con = ob->constraints.first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_PYTHON) {
+ bPythonConstraint *data = con->data;
+ if (data->text == text) BPY_pyconstraint_update(ob, con);
+ update = 1;
+ }
+ }
+
+ if (update) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ }
+# endif
#endif
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_refresh_pyconstraints(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Refresh PyConstraints";
- ot->idname = "TEXT_OT_refresh_pyconstraints";
- ot->description = "Refresh all pyconstraints";
+ /* identifiers */
+ ot->name = "Refresh PyConstraints";
+ ot->idname = "TEXT_OT_refresh_pyconstraints";
+ ot->description = "Refresh all pyconstraints";
- /* api callbacks */
- ot->exec = text_refresh_pyconstraints_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_refresh_pyconstraints_exec;
+ ot->poll = text_edit_poll;
}
/******************* paste operator *********************/
static int text_paste_exec(bContext *C, wmOperator *op)
{
- const bool selection = RNA_boolean_get(op->ptr, "selection");
- Text *text = CTX_data_edit_text(C);
- char *buf;
- int buf_len;
+ const bool selection = RNA_boolean_get(op->ptr, "selection");
+ Text *text = CTX_data_edit_text(C);
+ char *buf;
+ int buf_len;
- buf = WM_clipboard_text_get(selection, &buf_len);
+ buf = WM_clipboard_text_get(selection, &buf_len);
- if (!buf)
- return OPERATOR_CANCELLED;
+ if (!buf)
+ return OPERATOR_CANCELLED;
- text_drawcache_tag_update(CTX_wm_space_text(C), 0);
+ text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- txt_insert_buf(text, utxt, buf);
- text_update_edited(text);
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ txt_insert_buf(text, utxt, buf);
+ text_update_edited(text);
- MEM_freeN(buf);
+ MEM_freeN(buf);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- /* run the script while editing, evil but useful */
- if (CTX_wm_space_text(C)->live_edit)
- text_run_script(C, NULL);
+ /* run the script while editing, evil but useful */
+ if (CTX_wm_space_text(C)->live_edit)
+ text_run_script(C, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_paste(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Paste";
- ot->idname = "TEXT_OT_paste";
- ot->description = "Paste text from clipboard";
+ /* identifiers */
+ ot->name = "Paste";
+ ot->idname = "TEXT_OT_paste";
+ ot->description = "Paste text from clipboard";
- /* api callbacks */
- ot->exec = text_paste_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_paste_exec;
+ ot->poll = text_edit_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "selection", 0, "Selection", "Paste text selected elsewhere rather than copied (X11 only)");
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "selection",
+ 0,
+ "Selection",
+ "Paste text selected elsewhere rather than copied (X11 only)");
}
/**************** duplicate operator *******************/
static int text_duplicate_line_exec(bContext *C, wmOperator *UNUSED(op))
{
- Text *text = CTX_data_edit_text(C);
+ Text *text = CTX_data_edit_text(C);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
- txt_duplicate_line(text, utxt);
+ txt_duplicate_line(text, utxt);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- /* run the script while editing, evil but useful */
- if (CTX_wm_space_text(C)->live_edit) {
- text_run_script(C, NULL);
- }
+ /* run the script while editing, evil but useful */
+ if (CTX_wm_space_text(C)->live_edit) {
+ text_run_script(C, NULL);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_duplicate_line(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Duplicate Line";
- ot->idname = "TEXT_OT_duplicate_line";
- ot->description = "Duplicate the current line";
+ /* identifiers */
+ ot->name = "Duplicate Line";
+ ot->idname = "TEXT_OT_duplicate_line";
+ ot->description = "Duplicate the current line";
- /* api callbacks */
- ot->exec = text_duplicate_line_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_duplicate_line_exec;
+ ot->poll = text_edit_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* copy operator *********************/
static void txt_copy_clipboard(Text *text)
{
- char *buf;
+ char *buf;
- if (!txt_has_sel(text))
- return;
+ if (!txt_has_sel(text))
+ return;
- buf = txt_sel_to_buf(text);
+ buf = txt_sel_to_buf(text);
- if (buf) {
- WM_clipboard_text_set(buf, 0);
- MEM_freeN(buf);
- }
+ if (buf) {
+ WM_clipboard_text_set(buf, 0);
+ MEM_freeN(buf);
+ }
}
static int text_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
- Text *text = CTX_data_edit_text(C);
+ Text *text = CTX_data_edit_text(C);
- txt_copy_clipboard(text);
+ txt_copy_clipboard(text);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy";
- ot->idname = "TEXT_OT_copy";
- ot->description = "Copy selected text to clipboard";
+ /* identifiers */
+ ot->name = "Copy";
+ ot->idname = "TEXT_OT_copy";
+ ot->description = "Copy selected text to clipboard";
- /* api callbacks */
- ot->exec = text_copy_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_copy_exec;
+ ot->poll = text_edit_poll;
}
/******************* cut operator *********************/
static int text_cut_exec(bContext *C, wmOperator *UNUSED(op))
{
- Text *text = CTX_data_edit_text(C);
+ Text *text = CTX_data_edit_text(C);
- text_drawcache_tag_update(CTX_wm_space_text(C), 0);
+ text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- txt_copy_clipboard(text);
+ txt_copy_clipboard(text);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- txt_delete_selected(text, utxt);
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ txt_delete_selected(text, utxt);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- /* run the script while editing, evil but useful */
- if (CTX_wm_space_text(C)->live_edit)
- text_run_script(C, NULL);
+ /* run the script while editing, evil but useful */
+ if (CTX_wm_space_text(C)->live_edit)
+ text_run_script(C, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_cut(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Cut";
- ot->idname = "TEXT_OT_cut";
- ot->description = "Cut selected text to clipboard";
+ /* identifiers */
+ ot->name = "Cut";
+ ot->idname = "TEXT_OT_cut";
+ ot->description = "Cut selected text to clipboard";
- /* api callbacks */
- ot->exec = text_cut_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_cut_exec;
+ ot->poll = text_edit_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* indent operator *********************/
static int text_indent_exec(bContext *C, wmOperator *UNUSED(op))
{
- Text *text = CTX_data_edit_text(C);
+ Text *text = CTX_data_edit_text(C);
- text_drawcache_tag_update(CTX_wm_space_text(C), 0);
+ text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
- if (txt_has_sel(text)) {
- txt_order_cursors(text, false);
- txt_indent(text, utxt);
- }
- else {
- txt_add_char(text, utxt, '\t');
- }
+ if (txt_has_sel(text)) {
+ txt_order_cursors(text, false);
+ txt_indent(text, utxt);
+ }
+ else {
+ txt_add_char(text, utxt, '\t');
+ }
- text_update_edited(text);
+ text_update_edited(text);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_indent(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Indent";
- ot->idname = "TEXT_OT_indent";
- ot->description = "Indent selected text";
+ /* identifiers */
+ ot->name = "Indent";
+ ot->idname = "TEXT_OT_indent";
+ ot->description = "Indent selected text";
- /* api callbacks */
- ot->exec = text_indent_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_indent_exec;
+ ot->poll = text_edit_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* unindent operator *********************/
static int text_unindent_exec(bContext *C, wmOperator *UNUSED(op))
{
- Text *text = CTX_data_edit_text(C);
+ Text *text = CTX_data_edit_text(C);
- text_drawcache_tag_update(CTX_wm_space_text(C), 0);
+ text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
- txt_order_cursors(text, false);
- txt_unindent(text, utxt);
+ txt_order_cursors(text, false);
+ txt_unindent(text, utxt);
- text_update_edited(text);
+ text_update_edited(text);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_unindent(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unindent";
- ot->idname = "TEXT_OT_unindent";
- ot->description = "Unindent selected text";
+ /* identifiers */
+ ot->name = "Unindent";
+ ot->idname = "TEXT_OT_unindent";
+ ot->description = "Unindent selected text";
- /* api callbacks */
- ot->exec = text_unindent_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_unindent_exec;
+ ot->poll = text_edit_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* line break operator *********************/
static int text_line_break_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceText *st = CTX_wm_space_text(C);
- Text *text = CTX_data_edit_text(C);
- int a, curts;
- int space = (text->flags & TXT_TABSTOSPACES) ? st->tabnumber : 1;
+ SpaceText *st = CTX_wm_space_text(C);
+ Text *text = CTX_data_edit_text(C);
+ int a, curts;
+ int space = (text->flags & TXT_TABSTOSPACES) ? st->tabnumber : 1;
- text_drawcache_tag_update(st, 0);
+ text_drawcache_tag_update(st, 0);
- // double check tabs/spaces before splitting the line
- curts = txt_setcurr_tab_spaces(text, space);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- txt_split_curline(text, utxt);
+ // double check tabs/spaces before splitting the line
+ curts = txt_setcurr_tab_spaces(text, space);
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ txt_split_curline(text, utxt);
- for (a = 0; a < curts; a++) {
- if (text->flags & TXT_TABSTOSPACES) {
- txt_add_char(text, utxt, ' ');
- }
- else {
- txt_add_char(text, utxt, '\t');
- }
- }
+ for (a = 0; a < curts; a++) {
+ if (text->flags & TXT_TABSTOSPACES) {
+ txt_add_char(text, utxt, ' ');
+ }
+ else {
+ txt_add_char(text, utxt, '\t');
+ }
+ }
- if (text->curl) {
- if (text->curl->prev)
- text_update_line_edited(text->curl->prev);
- text_update_line_edited(text->curl);
- }
+ if (text->curl) {
+ if (text->curl->prev)
+ text_update_line_edited(text->curl->prev);
+ text_update_line_edited(text->curl);
+ }
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_line_break(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Line Break";
- ot->idname = "TEXT_OT_line_break";
- ot->description = "Insert line break at cursor position";
+ /* identifiers */
+ ot->name = "Line Break";
+ ot->idname = "TEXT_OT_line_break";
+ ot->description = "Insert line break at cursor position";
- /* api callbacks */
- ot->exec = text_line_break_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_line_break_exec;
+ ot->poll = text_edit_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* comment operator *********************/
static int text_comment_exec(bContext *C, wmOperator *UNUSED(op))
{
- Text *text = CTX_data_edit_text(C);
+ Text *text = CTX_data_edit_text(C);
- if (txt_has_sel(text)) {
- text_drawcache_tag_update(CTX_wm_space_text(C), 0);
+ if (txt_has_sel(text)) {
+ text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
- txt_order_cursors(text, false);
- txt_comment(text, utxt);
- text_update_edited(text);
+ txt_order_cursors(text, false);
+ txt_comment(text, utxt);
+ text_update_edited(text);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
- }
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
void TEXT_OT_comment(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Comment";
- ot->idname = "TEXT_OT_comment";
- ot->description = "Convert selected text to comment";
+ /* identifiers */
+ ot->name = "Comment";
+ ot->idname = "TEXT_OT_comment";
+ ot->description = "Convert selected text to comment";
- /* api callbacks */
- ot->exec = text_comment_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_comment_exec;
+ ot->poll = text_edit_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* uncomment operator *********************/
static int text_uncomment_exec(bContext *C, wmOperator *UNUSED(op))
{
- Text *text = CTX_data_edit_text(C);
+ Text *text = CTX_data_edit_text(C);
- if (txt_has_sel(text)) {
- text_drawcache_tag_update(CTX_wm_space_text(C), 0);
+ if (txt_has_sel(text)) {
+ text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
- txt_order_cursors(text, false);
- txt_uncomment(text, utxt);
- text_update_edited(text);
+ txt_order_cursors(text, false);
+ txt_uncomment(text, utxt);
+ text_update_edited(text);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
void TEXT_OT_uncomment(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Uncomment";
- ot->idname = "TEXT_OT_uncomment";
- ot->description = "Convert selected comment to text";
+ /* identifiers */
+ ot->name = "Uncomment";
+ ot->idname = "TEXT_OT_uncomment";
+ ot->description = "Convert selected comment to text";
- /* api callbacks */
- ot->exec = text_uncomment_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_uncomment_exec;
+ ot->poll = text_edit_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* convert whitespace operator *********************/
enum { TO_SPACES, TO_TABS };
static const EnumPropertyItem whitespace_type_items[] = {
- {TO_SPACES, "SPACES", 0, "To Spaces", NULL},
- {TO_TABS, "TABS", 0, "To Tabs", NULL},
- {0, NULL, 0, NULL, NULL},
+ {TO_SPACES, "SPACES", 0, "To Spaces", NULL},
+ {TO_TABS, "TABS", 0, "To Tabs", NULL},
+ {0, NULL, 0, NULL, NULL},
};
static int text_convert_whitespace_exec(bContext *C, wmOperator *op)
{
- SpaceText *st = CTX_wm_space_text(C);
- Text *text = CTX_data_edit_text(C);
- TextLine *tmp;
- FlattenString fs;
- size_t a, j, max_len = 0;
- int type = RNA_enum_get(op->ptr, "type");
-
- /* first convert to all space, this make it a lot easier to convert to tabs
- * because there is no mixtures of ' ' && '\t' */
- for (tmp = text->lines.first; tmp; tmp = tmp->next) {
- char *new_line;
-
- BLI_assert(tmp->line);
-
- flatten_string(st, &fs, tmp->line);
- new_line = BLI_strdup(fs.buf);
- flatten_string_free(&fs);
-
- MEM_freeN(tmp->line);
- if (tmp->format)
- MEM_freeN(tmp->format);
-
- /* Put new_line in the tmp->line spot still need to try and set the curc correctly. */
- tmp->line = new_line;
- tmp->len = strlen(new_line);
- tmp->format = NULL;
- if (tmp->len > max_len) {
- max_len = tmp->len;
- }
- }
-
- if (type == TO_TABS) {
- char *tmp_line = MEM_mallocN(sizeof(*tmp_line) * (max_len + 1), __func__);
-
- for (tmp = text->lines.first; tmp; tmp = tmp->next) {
- const char *text_check_line = tmp->line;
- const int text_check_line_len = tmp->len;
- char *tmp_line_cur = tmp_line;
- const size_t tab_len = st->tabnumber;
-
- BLI_assert(text_check_line);
-
- for (a = 0; a < text_check_line_len;) {
- /* A tab can only start at a position multiple of tab_len... */
- if (!(a % tab_len) && (text_check_line[a] == ' ')) {
- /* a + 0 we already know to be ' ' char... */
- for (j = 1; (j < tab_len) && (a + j < text_check_line_len) && (text_check_line[a + j] == ' '); j++);
-
- if (j == tab_len) {
- /* We found a set of spaces that can be replaced by a tab... */
- if ((tmp_line_cur == tmp_line) && a != 0) {
- /* Copy all 'valid' string already 'parsed'... */
- memcpy(tmp_line_cur, text_check_line, a);
- tmp_line_cur += a;
- }
- *tmp_line_cur = '\t';
- tmp_line_cur++;
- a += j;
- }
- else {
- if (tmp_line_cur != tmp_line) {
- memcpy(tmp_line_cur, &text_check_line[a], j);
- tmp_line_cur += j;
- }
- a += j;
- }
- }
- else {
- size_t len = BLI_str_utf8_size_safe(&text_check_line[a]);
- if (tmp_line_cur != tmp_line) {
- memcpy(tmp_line_cur, &text_check_line[a], len);
- tmp_line_cur += len;
- }
- a += len;
- }
- }
-
- if (tmp_line_cur != tmp_line) {
- *tmp_line_cur = '\0';
+ SpaceText *st = CTX_wm_space_text(C);
+ Text *text = CTX_data_edit_text(C);
+ TextLine *tmp;
+ FlattenString fs;
+ size_t a, j, max_len = 0;
+ int type = RNA_enum_get(op->ptr, "type");
+
+ /* first convert to all space, this make it a lot easier to convert to tabs
+ * because there is no mixtures of ' ' && '\t' */
+ for (tmp = text->lines.first; tmp; tmp = tmp->next) {
+ char *new_line;
+
+ BLI_assert(tmp->line);
+
+ flatten_string(st, &fs, tmp->line);
+ new_line = BLI_strdup(fs.buf);
+ flatten_string_free(&fs);
+
+ MEM_freeN(tmp->line);
+ if (tmp->format)
+ MEM_freeN(tmp->format);
+
+ /* Put new_line in the tmp->line spot still need to try and set the curc correctly. */
+ tmp->line = new_line;
+ tmp->len = strlen(new_line);
+ tmp->format = NULL;
+ if (tmp->len > max_len) {
+ max_len = tmp->len;
+ }
+ }
+
+ if (type == TO_TABS) {
+ char *tmp_line = MEM_mallocN(sizeof(*tmp_line) * (max_len + 1), __func__);
+
+ for (tmp = text->lines.first; tmp; tmp = tmp->next) {
+ const char *text_check_line = tmp->line;
+ const int text_check_line_len = tmp->len;
+ char *tmp_line_cur = tmp_line;
+ const size_t tab_len = st->tabnumber;
+
+ BLI_assert(text_check_line);
+
+ for (a = 0; a < text_check_line_len;) {
+ /* A tab can only start at a position multiple of tab_len... */
+ if (!(a % tab_len) && (text_check_line[a] == ' ')) {
+ /* a + 0 we already know to be ' ' char... */
+ for (j = 1;
+ (j < tab_len) && (a + j < text_check_line_len) && (text_check_line[a + j] == ' ');
+ j++)
+ ;
+
+ if (j == tab_len) {
+ /* We found a set of spaces that can be replaced by a tab... */
+ if ((tmp_line_cur == tmp_line) && a != 0) {
+ /* Copy all 'valid' string already 'parsed'... */
+ memcpy(tmp_line_cur, text_check_line, a);
+ tmp_line_cur += a;
+ }
+ *tmp_line_cur = '\t';
+ tmp_line_cur++;
+ a += j;
+ }
+ else {
+ if (tmp_line_cur != tmp_line) {
+ memcpy(tmp_line_cur, &text_check_line[a], j);
+ tmp_line_cur += j;
+ }
+ a += j;
+ }
+ }
+ else {
+ size_t len = BLI_str_utf8_size_safe(&text_check_line[a]);
+ if (tmp_line_cur != tmp_line) {
+ memcpy(tmp_line_cur, &text_check_line[a], len);
+ tmp_line_cur += len;
+ }
+ a += len;
+ }
+ }
+
+ if (tmp_line_cur != tmp_line) {
+ *tmp_line_cur = '\0';
#ifndef NDEBUG
- BLI_assert(tmp_line_cur - tmp_line <= max_len);
+ BLI_assert(tmp_line_cur - tmp_line <= max_len);
- flatten_string(st, &fs, tmp_line);
- BLI_assert(STREQ(fs.buf, tmp->line));
- flatten_string_free(&fs);
+ flatten_string(st, &fs, tmp_line);
+ BLI_assert(STREQ(fs.buf, tmp->line));
+ flatten_string_free(&fs);
#endif
- MEM_freeN(tmp->line);
- if (tmp->format)
- MEM_freeN(tmp->format);
+ MEM_freeN(tmp->line);
+ if (tmp->format)
+ MEM_freeN(tmp->format);
- /* Put new_line in the tmp->line spot
- * still need to try and set the curc correctly. */
- tmp->line = BLI_strdup(tmp_line);
- tmp->len = strlen(tmp_line);
- tmp->format = NULL;
- }
- }
+ /* Put new_line in the tmp->line spot
+ * still need to try and set the curc correctly. */
+ tmp->line = BLI_strdup(tmp_line);
+ tmp->len = strlen(tmp_line);
+ tmp->format = NULL;
+ }
+ }
- MEM_freeN(tmp_line);
- }
+ MEM_freeN(tmp_line);
+ }
- text_update_edited(text);
- text_update_cursor_moved(C);
- text_drawcache_tag_update(st, 1);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ text_update_edited(text);
+ text_update_cursor_moved(C);
+ text_drawcache_tag_update(st, 1);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_convert_whitespace(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Convert Whitespace";
- ot->idname = "TEXT_OT_convert_whitespace";
- ot->description = "Convert whitespaces by type";
+ /* identifiers */
+ ot->name = "Convert Whitespace";
+ ot->idname = "TEXT_OT_convert_whitespace";
+ ot->description = "Convert whitespaces by type";
- /* api callbacks */
- ot->exec = text_convert_whitespace_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_convert_whitespace_exec;
+ ot->poll = text_edit_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- /* properties */
- RNA_def_enum(ot->srna, "type", whitespace_type_items, TO_SPACES, "Type", "Type of whitespace to convert to");
+ /* properties */
+ RNA_def_enum(ot->srna,
+ "type",
+ whitespace_type_items,
+ TO_SPACES,
+ "Type",
+ "Type of whitespace to convert to");
}
/******************* select all operator *********************/
static int text_select_all_exec(bContext *C, wmOperator *UNUSED(op))
{
- Text *text = CTX_data_edit_text(C);
+ Text *text = CTX_data_edit_text(C);
- txt_sel_all(text);
+ txt_sel_all(text);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select All";
- ot->idname = "TEXT_OT_select_all";
- ot->description = "Select all text";
+ /* identifiers */
+ ot->name = "Select All";
+ ot->idname = "TEXT_OT_select_all";
+ ot->description = "Select all text";
- /* api callbacks */
- ot->exec = text_select_all_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_select_all_exec;
+ ot->poll = text_edit_poll;
}
/******************* select line operator *********************/
static int text_select_line_exec(bContext *C, wmOperator *UNUSED(op))
{
- Text *text = CTX_data_edit_text(C);
+ Text *text = CTX_data_edit_text(C);
- txt_sel_line(text);
+ txt_sel_line(text);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_select_line(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Line";
- ot->idname = "TEXT_OT_select_line";
- ot->description = "Select text by line";
+ /* identifiers */
+ ot->name = "Select Line";
+ ot->idname = "TEXT_OT_select_line";
+ ot->description = "Select text by line";
- /* api callbacks */
- ot->exec = text_select_line_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_select_line_exec;
+ ot->poll = text_edit_poll;
}
/******************* select word operator *********************/
static int text_select_word_exec(bContext *C, wmOperator *UNUSED(op))
{
- Text *text = CTX_data_edit_text(C);
- /* don't advance cursor before stepping */
- const bool use_init_step = false;
+ Text *text = CTX_data_edit_text(C);
+ /* don't advance cursor before stepping */
+ const bool use_init_step = false;
- txt_jump_left(text, false, use_init_step);
- txt_jump_right(text, true, use_init_step);
+ txt_jump_left(text, false, use_init_step);
+ txt_jump_right(text, true, use_init_step);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_select_word(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Word";
- ot->idname = "TEXT_OT_select_word";
- ot->description = "Select word under cursor";
+ /* identifiers */
+ ot->name = "Select Word";
+ ot->idname = "TEXT_OT_select_word";
+ ot->description = "Select word under cursor";
- /* api callbacks */
- ot->exec = text_select_word_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_select_word_exec;
+ ot->poll = text_edit_poll;
}
/********************* move lines operators ***********************/
static int move_lines_exec(bContext *C, wmOperator *op)
{
- Text *text = CTX_data_edit_text(C);
- const int direction = RNA_enum_get(op->ptr, "direction");
+ Text *text = CTX_data_edit_text(C);
+ const int direction = RNA_enum_get(op->ptr, "direction");
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
- txt_move_lines(text, utxt, direction);
+ txt_move_lines(text, utxt, direction);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- /* run the script while editing, evil but useful */
- if (CTX_wm_space_text(C)->live_edit)
- text_run_script(C, NULL);
+ /* run the script while editing, evil but useful */
+ if (CTX_wm_space_text(C)->live_edit)
+ text_run_script(C, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_move_lines(wmOperatorType *ot)
{
- static const EnumPropertyItem direction_items[] = {
- {TXT_MOVE_LINE_UP, "UP", 0, "Up", ""},
- {TXT_MOVE_LINE_DOWN, "DOWN", 0, "Down", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem direction_items[] = {
+ {TXT_MOVE_LINE_UP, "UP", 0, "Up", ""},
+ {TXT_MOVE_LINE_DOWN, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Move Lines";
- ot->idname = "TEXT_OT_move_lines";
- ot->description = "Move the currently selected line(s) up/down";
+ /* identifiers */
+ ot->name = "Move Lines";
+ ot->idname = "TEXT_OT_move_lines";
+ ot->description = "Move the currently selected line(s) up/down";
- /* api callbacks */
- ot->exec = move_lines_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = move_lines_exec;
+ ot->poll = text_edit_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- /* properties */
- RNA_def_enum(ot->srna, "direction", direction_items, 1, "Direction", "");
+ /* properties */
+ RNA_def_enum(ot->srna, "direction", direction_items, 1, "Direction", "");
}
/************************ move operator ************************/
static const EnumPropertyItem move_type_items[] = {
- {LINE_BEGIN, "LINE_BEGIN", 0, "Line Begin", ""},
- {LINE_END, "LINE_END", 0, "Line End", ""},
- {FILE_TOP, "FILE_TOP", 0, "File Top", ""},
- {FILE_BOTTOM, "FILE_BOTTOM", 0, "File Bottom", ""},
- {PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
- {NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
- {PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
- {NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
- {PREV_LINE, "PREVIOUS_LINE", 0, "Previous Line", ""},
- {NEXT_LINE, "NEXT_LINE", 0, "Next Line", ""},
- {PREV_PAGE, "PREVIOUS_PAGE", 0, "Previous Page", ""},
- {NEXT_PAGE, "NEXT_PAGE", 0, "Next Page", ""},
- {0, NULL, 0, NULL, NULL},
+ {LINE_BEGIN, "LINE_BEGIN", 0, "Line Begin", ""},
+ {LINE_END, "LINE_END", 0, "Line End", ""},
+ {FILE_TOP, "FILE_TOP", 0, "File Top", ""},
+ {FILE_BOTTOM, "FILE_BOTTOM", 0, "File Bottom", ""},
+ {PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
+ {NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
+ {PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
+ {NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
+ {PREV_LINE, "PREVIOUS_LINE", 0, "Previous Line", ""},
+ {NEXT_LINE, "NEXT_LINE", 0, "Next Line", ""},
+ {PREV_PAGE, "PREVIOUS_PAGE", 0, "Previous Page", ""},
+ {NEXT_PAGE, "NEXT_PAGE", 0, "Next Page", ""},
+ {0, NULL, 0, NULL, NULL},
};
/* 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)
{
- int i, j, start, end, max, chop, curs, loop, endj, found, selc;
- char ch;
-
- max = wrap_width(st, ar);
-
- selc = start = endj = curs = found = 0;
- end = max;
- chop = loop = 1;
-
- for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe(linein->line + j)) {
- int chars;
- int columns = BLI_str_utf8_char_width_safe(linein->line + j); /* = 1 for tab */
-
- /* Mimic replacement of tabs */
- ch = linein->line[j];
- if (ch == '\t') {
- chars = st->tabnumber - i % st->tabnumber;
- ch = ' ';
- }
- else {
- chars = 1;
- }
-
- while (chars--) {
- if (rell == 0 && i - start <= relc && i + columns - start > relc) {
- /* current position could be wrapped to next line */
- /* this should be checked when end of current line would be reached */
- selc = j;
- found = 1;
- }
- else if (i - end <= relc && i + columns - end > relc) {
- curs = j;
- }
- if (i + columns - start > max) {
- end = MIN2(end, i);
-
- if (found) {
- /* exact cursor position was found, check if it's */
- /* still on needed line (hasn't been wrapped) */
- if (selc > endj && !chop) selc = endj;
- loop = 0;
- break;
- }
-
- if (chop) endj = j;
-
- start = end;
- end += max;
- chop = 1;
- rell--;
-
- if (rell == 0 && i + columns - start > relc) {
- selc = curs;
- loop = 0;
- break;
- }
- }
- else if (ch == '\0') {
- if (!found) selc = linein->len;
- loop = 0;
- break;
- }
- else if (ch == ' ' || ch == '-') {
- if (found) {
- loop = 0;
- break;
- }
-
- if (rell == 0 && i + columns - start > relc) {
- selc = curs;
- loop = 0;
- break;
- }
- end = i + 1;
- endj = j;
- chop = 0;
- }
- i += columns;
- }
- }
-
- return selc;
-}
-
-static int cursor_skip_find_line(SpaceText *st, ARegion *ar,
- 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);
- *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);
-
- if (*rell - visible_lines + offl >= 0) {
- if (!(*linep)->next) {
- if (offl < visible_lines - 1) {
- *rell = visible_lines - 1;
- return 1;
- }
-
- *charp = (*linep)->len;
- return 0;
- }
-
- *rell -= visible_lines - offl;
- *linep = (*linep)->next;
- }
- else {
- *rell += offl;
- return 1;
- }
- }
- else {
- if (*rell + offl <= 0) {
- if (!(*linep)->prev) {
- if (offl) {
- *rell = 0;
- return 1;
- }
-
- *charp = 0;
- return 0;
- }
-
- *rell += offl;
- *linep = (*linep)->prev;
- }
- else {
- *rell += offl;
- return 1;
- }
- }
-
- /* skip lines and find destination line and offsets */
- while (*linep) {
- visible_lines = text_get_visible_lines(st, ar, (*linep)->line);
-
- if (lines < 0) { /* moving top */
- if (*rell + visible_lines >= 0) {
- *rell += visible_lines;
- break;
- }
-
- if (!(*linep)->prev) {
- *rell = 0;
- break;
- }
-
- *rell += visible_lines;
- *linep = (*linep)->prev;
- }
- else { /* moving bottom */
- if (*rell - visible_lines < 0) break;
-
- if (!(*linep)->next) {
- *rell = visible_lines - 1;
- break;
- }
-
- *rell -= visible_lines;
- *linep = (*linep)->next;
- }
- }
-
- return 1;
+ int i, j, start, end, max, chop, curs, loop, endj, found, selc;
+ char ch;
+
+ max = wrap_width(st, ar);
+
+ selc = start = endj = curs = found = 0;
+ end = max;
+ chop = loop = 1;
+
+ for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe(linein->line + j)) {
+ int chars;
+ int columns = BLI_str_utf8_char_width_safe(linein->line + j); /* = 1 for tab */
+
+ /* Mimic replacement of tabs */
+ ch = linein->line[j];
+ if (ch == '\t') {
+ chars = st->tabnumber - i % st->tabnumber;
+ ch = ' ';
+ }
+ else {
+ chars = 1;
+ }
+
+ while (chars--) {
+ if (rell == 0 && i - start <= relc && i + columns - start > relc) {
+ /* current position could be wrapped to next line */
+ /* this should be checked when end of current line would be reached */
+ selc = j;
+ found = 1;
+ }
+ else if (i - end <= relc && i + columns - end > relc) {
+ curs = j;
+ }
+ if (i + columns - start > max) {
+ end = MIN2(end, i);
+
+ if (found) {
+ /* exact cursor position was found, check if it's */
+ /* still on needed line (hasn't been wrapped) */
+ if (selc > endj && !chop)
+ selc = endj;
+ loop = 0;
+ break;
+ }
+
+ if (chop)
+ endj = j;
+
+ start = end;
+ end += max;
+ chop = 1;
+ rell--;
+
+ if (rell == 0 && i + columns - start > relc) {
+ selc = curs;
+ loop = 0;
+ break;
+ }
+ }
+ else if (ch == '\0') {
+ if (!found)
+ selc = linein->len;
+ loop = 0;
+ break;
+ }
+ else if (ch == ' ' || ch == '-') {
+ if (found) {
+ loop = 0;
+ break;
+ }
+
+ if (rell == 0 && i + columns - start > relc) {
+ selc = curs;
+ loop = 0;
+ break;
+ }
+ end = i + 1;
+ endj = j;
+ chop = 0;
+ }
+ i += columns;
+ }
+ }
+
+ return selc;
+}
+
+static int cursor_skip_find_line(
+ SpaceText *st, ARegion *ar, 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);
+ *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);
+
+ if (*rell - visible_lines + offl >= 0) {
+ if (!(*linep)->next) {
+ if (offl < visible_lines - 1) {
+ *rell = visible_lines - 1;
+ return 1;
+ }
+
+ *charp = (*linep)->len;
+ return 0;
+ }
+
+ *rell -= visible_lines - offl;
+ *linep = (*linep)->next;
+ }
+ else {
+ *rell += offl;
+ return 1;
+ }
+ }
+ else {
+ if (*rell + offl <= 0) {
+ if (!(*linep)->prev) {
+ if (offl) {
+ *rell = 0;
+ return 1;
+ }
+
+ *charp = 0;
+ return 0;
+ }
+
+ *rell += offl;
+ *linep = (*linep)->prev;
+ }
+ else {
+ *rell += offl;
+ return 1;
+ }
+ }
+
+ /* skip lines and find destination line and offsets */
+ while (*linep) {
+ visible_lines = text_get_visible_lines(st, ar, (*linep)->line);
+
+ if (lines < 0) { /* moving top */
+ if (*rell + visible_lines >= 0) {
+ *rell += visible_lines;
+ break;
+ }
+
+ if (!(*linep)->prev) {
+ *rell = 0;
+ break;
+ }
+
+ *rell += visible_lines;
+ *linep = (*linep)->prev;
+ }
+ else { /* moving bottom */
+ if (*rell - visible_lines < 0)
+ break;
+
+ if (!(*linep)->next) {
+ *rell = visible_lines - 1;
+ break;
+ }
+
+ *rell -= visible_lines;
+ *linep = (*linep)->next;
+ }
+ }
+
+ return 1;
}
static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, const bool sel)
{
- Text *text = st->text;
- TextLine **linep;
- int *charp;
- int oldc, i, j, max, start, end, endj, chop, loop;
- char ch;
-
- text_update_character_width(st);
-
- if (sel) { linep = &text->sell; charp = &text->selc; }
- else { linep = &text->curl; charp = &text->curc; }
-
- oldc = *charp;
-
- max = wrap_width(st, ar);
-
- start = endj = 0;
- end = max;
- chop = loop = 1;
- *charp = 0;
-
- for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) {
- int chars;
- int columns = BLI_str_utf8_char_width_safe((*linep)->line + j); /* = 1 for tab */
-
- /* Mimic replacement of tabs */
- ch = (*linep)->line[j];
- if (ch == '\t') {
- chars = st->tabnumber - i % st->tabnumber;
- ch = ' ';
- }
- else {
- chars = 1;
- }
-
- while (chars--) {
- if (i + columns - start > max) {
- end = MIN2(end, i);
-
- *charp = endj;
-
- if (j >= oldc) {
- if (ch == '\0') *charp = txt_utf8_column_to_offset((*linep)->line, start);
- loop = 0;
- break;
- }
-
- if (chop) endj = j;
-
- start = end;
- end += max;
- chop = 1;
- }
- else if (ch == ' ' || ch == '-' || ch == '\0') {
- if (j >= oldc) {
- *charp = txt_utf8_column_to_offset((*linep)->line, start);
- loop = 0;
- break;
- }
-
- end = i + 1;
- endj = j + 1;
- chop = 0;
- }
- i += columns;
- }
- }
-
- if (!sel) txt_pop_sel(text);
+ Text *text = st->text;
+ TextLine **linep;
+ int *charp;
+ int oldc, i, j, max, start, end, endj, chop, loop;
+ char ch;
+
+ text_update_character_width(st);
+
+ if (sel) {
+ linep = &text->sell;
+ charp = &text->selc;
+ }
+ else {
+ linep = &text->curl;
+ charp = &text->curc;
+ }
+
+ oldc = *charp;
+
+ max = wrap_width(st, ar);
+
+ start = endj = 0;
+ end = max;
+ chop = loop = 1;
+ *charp = 0;
+
+ for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) {
+ int chars;
+ int columns = BLI_str_utf8_char_width_safe((*linep)->line + j); /* = 1 for tab */
+
+ /* Mimic replacement of tabs */
+ ch = (*linep)->line[j];
+ if (ch == '\t') {
+ chars = st->tabnumber - i % st->tabnumber;
+ ch = ' ';
+ }
+ else {
+ chars = 1;
+ }
+
+ while (chars--) {
+ if (i + columns - start > max) {
+ end = MIN2(end, i);
+
+ *charp = endj;
+
+ if (j >= oldc) {
+ if (ch == '\0')
+ *charp = txt_utf8_column_to_offset((*linep)->line, start);
+ loop = 0;
+ break;
+ }
+
+ if (chop)
+ endj = j;
+
+ start = end;
+ end += max;
+ chop = 1;
+ }
+ else if (ch == ' ' || ch == '-' || ch == '\0') {
+ if (j >= oldc) {
+ *charp = txt_utf8_column_to_offset((*linep)->line, start);
+ loop = 0;
+ break;
+ }
+
+ end = i + 1;
+ endj = j + 1;
+ chop = 0;
+ }
+ i += columns;
+ }
+ }
+
+ if (!sel)
+ txt_pop_sel(text);
}
static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, const bool sel)
{
- Text *text = st->text;
- TextLine **linep;
- int *charp;
- int oldc, i, j, max, start, end, endj, chop, loop;
- char ch;
-
- text_update_character_width(st);
-
- if (sel) { linep = &text->sell; charp = &text->selc; }
- else { linep = &text->curl; charp = &text->curc; }
-
- oldc = *charp;
-
- max = wrap_width(st, ar);
-
- start = endj = 0;
- end = max;
- chop = loop = 1;
- *charp = 0;
-
- for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) {
- int chars;
- int columns = BLI_str_utf8_char_width_safe((*linep)->line + j); /* = 1 for tab */
-
- /* Mimic replacement of tabs */
- ch = (*linep)->line[j];
- if (ch == '\t') {
- chars = st->tabnumber - i % st->tabnumber;
- ch = ' ';
- }
- else {
- chars = 1;
- }
-
- while (chars--) {
- if (i + columns - start > max) {
- end = MIN2(end, i);
-
- if (chop) endj = BLI_str_prev_char_utf8((*linep)->line + j) - (*linep)->line;
-
- if (endj >= oldc) {
- if (ch == '\0') *charp = (*linep)->len;
- else *charp = endj;
- loop = 0;
- break;
- }
-
- start = end;
- end += max;
- chop = 1;
- }
- else if (ch == '\0') {
- *charp = (*linep)->len;
- loop = 0;
- break;
- }
- else if (ch == ' ' || ch == '-') {
- end = i + 1;
- endj = j;
- chop = 0;
- }
- i += columns;
- }
- }
-
- if (!sel) txt_pop_sel(text);
+ Text *text = st->text;
+ TextLine **linep;
+ int *charp;
+ int oldc, i, j, max, start, end, endj, chop, loop;
+ char ch;
+
+ text_update_character_width(st);
+
+ if (sel) {
+ linep = &text->sell;
+ charp = &text->selc;
+ }
+ else {
+ linep = &text->curl;
+ charp = &text->curc;
+ }
+
+ oldc = *charp;
+
+ max = wrap_width(st, ar);
+
+ start = endj = 0;
+ end = max;
+ chop = loop = 1;
+ *charp = 0;
+
+ for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) {
+ int chars;
+ int columns = BLI_str_utf8_char_width_safe((*linep)->line + j); /* = 1 for tab */
+
+ /* Mimic replacement of tabs */
+ ch = (*linep)->line[j];
+ if (ch == '\t') {
+ chars = st->tabnumber - i % st->tabnumber;
+ ch = ' ';
+ }
+ else {
+ chars = 1;
+ }
+
+ while (chars--) {
+ if (i + columns - start > max) {
+ end = MIN2(end, i);
+
+ if (chop)
+ endj = BLI_str_prev_char_utf8((*linep)->line + j) - (*linep)->line;
+
+ if (endj >= oldc) {
+ if (ch == '\0')
+ *charp = (*linep)->len;
+ else
+ *charp = endj;
+ loop = 0;
+ break;
+ }
+
+ start = end;
+ end += max;
+ chop = 1;
+ }
+ else if (ch == '\0') {
+ *charp = (*linep)->len;
+ loop = 0;
+ break;
+ }
+ else if (ch == ' ' || ch == '-') {
+ end = i + 1;
+ endj = j;
+ chop = 0;
+ }
+ i += columns;
+ }
+ }
+
+ if (!sel)
+ txt_pop_sel(text);
}
static void txt_wrap_move_up(SpaceText *st, ARegion *ar, const bool sel)
{
- Text *text = st->text;
- TextLine **linep;
- int *charp;
- int offl, offc, col;
-
- text_update_character_width(st);
-
- if (sel) { linep = &text->sell; charp = &text->selc; }
- else { linep = &text->curl; charp = &text->curc; }
-
- wrap_offset_in_line(st, ar, *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);
- }
- 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);
- }
- else {
- *charp = 0;
- }
- }
-
- if (!sel) txt_pop_sel(text);
+ Text *text = st->text;
+ TextLine **linep;
+ int *charp;
+ int offl, offc, col;
+
+ text_update_character_width(st);
+
+ if (sel) {
+ linep = &text->sell;
+ charp = &text->selc;
+ }
+ else {
+ linep = &text->curl;
+ charp = &text->curc;
+ }
+
+ wrap_offset_in_line(st, ar, *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);
+ }
+ 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);
+ }
+ else {
+ *charp = 0;
+ }
+ }
+
+ if (!sel)
+ txt_pop_sel(text);
}
static void txt_wrap_move_down(SpaceText *st, ARegion *ar, const bool sel)
{
- Text *text = st->text;
- TextLine **linep;
- int *charp;
- int offl, offc, col, visible_lines;
-
- text_update_character_width(st);
-
- if (sel) { linep = &text->sell; charp = &text->selc; }
- else { linep = &text->curl; charp = &text->curc; }
-
- wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc);
- col = text_get_char_pos(st, (*linep)->line, *charp) + offc;
- visible_lines = text_get_visible_lines(st, ar, (*linep)->line);
- if (offl < visible_lines - 1) {
- *charp = text_get_cursor_rel(st, ar, *linep, offl + 1, col);
- }
- else {
- if ((*linep)->next) {
- *linep = (*linep)->next;
- *charp = text_get_cursor_rel(st, ar, *linep, 0, col);
- }
- else {
- *charp = (*linep)->len;
- }
- }
-
- if (!sel) txt_pop_sel(text);
+ Text *text = st->text;
+ TextLine **linep;
+ int *charp;
+ int offl, offc, col, visible_lines;
+
+ text_update_character_width(st);
+
+ if (sel) {
+ linep = &text->sell;
+ charp = &text->selc;
+ }
+ else {
+ linep = &text->curl;
+ charp = &text->curc;
+ }
+
+ wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc);
+ col = text_get_char_pos(st, (*linep)->line, *charp) + offc;
+ visible_lines = text_get_visible_lines(st, ar, (*linep)->line);
+ if (offl < visible_lines - 1) {
+ *charp = text_get_cursor_rel(st, ar, *linep, offl + 1, col);
+ }
+ else {
+ if ((*linep)->next) {
+ *linep = (*linep)->next;
+ *charp = text_get_cursor_rel(st, ar, *linep, 0, col);
+ }
+ else {
+ *charp = (*linep)->len;
+ }
+ }
+
+ if (!sel)
+ txt_pop_sel(text);
}
/* Moves the cursor vertically by the specified number of lines.
@@ -1749,1524 +1814,1602 @@ static void txt_wrap_move_down(SpaceText *st, ARegion *ar, const bool sel)
*/
static void cursor_skip(SpaceText *st, ARegion *ar, Text *text, int lines, const bool sel)
{
- TextLine **linep;
- int *charp;
-
- if (sel) { linep = &text->sell; charp = &text->selc; }
- else { linep = &text->curl; charp = &text->curc; }
-
- if (st && ar && 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);
- }
- else {
- while (lines > 0 && (*linep)->next) {
- *linep = (*linep)->next;
- lines--;
- }
- while (lines < 0 && (*linep)->prev) {
- *linep = (*linep)->prev;
- lines++;
- }
- }
-
- if (*charp > (*linep)->len) *charp = (*linep)->len;
-
- if (!sel) txt_pop_sel(text);
+ TextLine **linep;
+ int *charp;
+
+ if (sel) {
+ linep = &text->sell;
+ charp = &text->selc;
+ }
+ else {
+ linep = &text->curl;
+ charp = &text->curc;
+ }
+
+ if (st && ar && 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);
+ }
+ else {
+ while (lines > 0 && (*linep)->next) {
+ *linep = (*linep)->next;
+ lines--;
+ }
+ while (lines < 0 && (*linep)->prev) {
+ *linep = (*linep)->prev;
+ lines++;
+ }
+ }
+
+ if (*charp > (*linep)->len)
+ *charp = (*linep)->len;
+
+ if (!sel)
+ txt_pop_sel(text);
}
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);
-
- /* ensure we have the right region, it's optional */
- if (ar && ar->regiontype != RGN_TYPE_WINDOW)
- ar = NULL;
-
- switch (type) {
- case LINE_BEGIN:
- if (!select) {
- txt_sel_clear(text);
- }
- if (st && st->wordwrap && ar) txt_wrap_move_bol(st, ar, select);
- else txt_move_bol(text, select);
- break;
-
- case LINE_END:
- if (!select) {
- txt_sel_clear(text);
- }
- if (st && st->wordwrap && ar) txt_wrap_move_eol(st, ar, select);
- else txt_move_eol(text, select);
- break;
-
- case FILE_TOP:
- txt_move_bof(text, select);
- break;
-
- case FILE_BOTTOM:
- txt_move_eof(text, select);
- break;
-
- case PREV_WORD:
- if (txt_cursor_is_line_start(text)) {
- txt_move_left(text, select);
- }
- txt_jump_left(text, select, true);
- break;
-
- case NEXT_WORD:
- if (txt_cursor_is_line_end(text)) {
- txt_move_right(text, select);
- }
- txt_jump_right(text, select, true);
- break;
-
- case PREV_CHAR:
- if (txt_has_sel(text) && !select) {
- txt_order_cursors(text, false);
- txt_pop_sel(text);
- }
- else {
- txt_move_left(text, select);
- }
- break;
-
- case NEXT_CHAR:
- if (txt_has_sel(text) && !select) {
- txt_order_cursors(text, true);
- txt_pop_sel(text);
- }
- else {
- txt_move_right(text, select);
- }
- break;
-
- case PREV_LINE:
- if (st && st->wordwrap && ar) txt_wrap_move_up(st, ar, select);
- else txt_move_up(text, select);
- break;
-
- case NEXT_LINE:
- if (st && st->wordwrap && ar) txt_wrap_move_down(st, ar, select);
- else txt_move_down(text, select);
- break;
-
- case PREV_PAGE:
- if (st) cursor_skip(st, ar, st->text, -st->viewlines, select);
- else cursor_skip(NULL, NULL, text, -10, select);
- break;
-
- case NEXT_PAGE:
- if (st) cursor_skip(st, ar, st->text, st->viewlines, select);
- else cursor_skip(NULL, NULL, text, 10, select);
- break;
- }
-
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
-
- return OPERATOR_FINISHED;
+ SpaceText *st = CTX_wm_space_text(C);
+ Text *text = CTX_data_edit_text(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ /* ensure we have the right region, it's optional */
+ if (ar && ar->regiontype != RGN_TYPE_WINDOW)
+ ar = NULL;
+
+ switch (type) {
+ case LINE_BEGIN:
+ if (!select) {
+ txt_sel_clear(text);
+ }
+ if (st && st->wordwrap && ar)
+ txt_wrap_move_bol(st, ar, select);
+ else
+ txt_move_bol(text, select);
+ break;
+
+ case LINE_END:
+ if (!select) {
+ txt_sel_clear(text);
+ }
+ if (st && st->wordwrap && ar)
+ txt_wrap_move_eol(st, ar, select);
+ else
+ txt_move_eol(text, select);
+ break;
+
+ case FILE_TOP:
+ txt_move_bof(text, select);
+ break;
+
+ case FILE_BOTTOM:
+ txt_move_eof(text, select);
+ break;
+
+ case PREV_WORD:
+ if (txt_cursor_is_line_start(text)) {
+ txt_move_left(text, select);
+ }
+ txt_jump_left(text, select, true);
+ break;
+
+ case NEXT_WORD:
+ if (txt_cursor_is_line_end(text)) {
+ txt_move_right(text, select);
+ }
+ txt_jump_right(text, select, true);
+ break;
+
+ case PREV_CHAR:
+ if (txt_has_sel(text) && !select) {
+ txt_order_cursors(text, false);
+ txt_pop_sel(text);
+ }
+ else {
+ txt_move_left(text, select);
+ }
+ break;
+
+ case NEXT_CHAR:
+ if (txt_has_sel(text) && !select) {
+ txt_order_cursors(text, true);
+ txt_pop_sel(text);
+ }
+ else {
+ txt_move_right(text, select);
+ }
+ break;
+
+ case PREV_LINE:
+ if (st && st->wordwrap && ar)
+ txt_wrap_move_up(st, ar, select);
+ else
+ txt_move_up(text, select);
+ break;
+
+ case NEXT_LINE:
+ if (st && st->wordwrap && ar)
+ txt_wrap_move_down(st, ar, select);
+ else
+ txt_move_down(text, select);
+ break;
+
+ case PREV_PAGE:
+ if (st)
+ cursor_skip(st, ar, st->text, -st->viewlines, select);
+ else
+ cursor_skip(NULL, NULL, text, -10, select);
+ break;
+
+ case NEXT_PAGE:
+ if (st)
+ cursor_skip(st, ar, st->text, st->viewlines, select);
+ else
+ cursor_skip(NULL, NULL, text, 10, select);
+ break;
+ }
+
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
+
+ return OPERATOR_FINISHED;
}
static int text_move_exec(bContext *C, wmOperator *op)
{
- int type = RNA_enum_get(op->ptr, "type");
+ int type = RNA_enum_get(op->ptr, "type");
- return text_move_cursor(C, type, 0);
+ return text_move_cursor(C, type, 0);
}
void TEXT_OT_move(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move Cursor";
- ot->idname = "TEXT_OT_move";
- ot->description = "Move cursor to position type";
+ /* identifiers */
+ ot->name = "Move Cursor";
+ ot->idname = "TEXT_OT_move";
+ ot->description = "Move cursor to position type";
- /* api callbacks */
- ot->exec = text_move_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_move_exec;
+ ot->poll = text_edit_poll;
- /* properties */
- RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to");
+ /* properties */
+ RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to");
}
/******************* move select operator ********************/
static int text_move_select_exec(bContext *C, wmOperator *op)
{
- int type = RNA_enum_get(op->ptr, "type");
+ int type = RNA_enum_get(op->ptr, "type");
- return text_move_cursor(C, type, 1);
+ return text_move_cursor(C, type, 1);
}
void TEXT_OT_move_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move Select";
- ot->idname = "TEXT_OT_move_select";
- ot->description = "Move the cursor while selecting";
+ /* identifiers */
+ ot->name = "Move Select";
+ ot->idname = "TEXT_OT_move_select";
+ ot->description = "Move the cursor while selecting";
- /* api callbacks */
- ot->exec = text_move_select_exec;
- ot->poll = text_space_edit_poll;
+ /* api callbacks */
+ ot->exec = text_move_select_exec;
+ ot->poll = text_space_edit_poll;
- /* properties */
- RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to, to make a selection");
+ /* properties */
+ RNA_def_enum(ot->srna,
+ "type",
+ move_type_items,
+ LINE_BEGIN,
+ "Type",
+ "Where to move cursor to, to make a selection");
}
/******************* jump operator *********************/
static int text_jump_exec(bContext *C, wmOperator *op)
{
- Text *text = CTX_data_edit_text(C);
- int line = RNA_int_get(op->ptr, "line");
- short nlines = txt_get_span(text->lines.first, text->lines.last) + 1;
+ Text *text = CTX_data_edit_text(C);
+ int line = RNA_int_get(op->ptr, "line");
+ short nlines = txt_get_span(text->lines.first, text->lines.last) + 1;
- if (line < 1)
- txt_move_toline(text, 1, 0);
- else if (line > nlines)
- txt_move_toline(text, nlines - 1, 0);
- else
- txt_move_toline(text, line - 1, 0);
+ if (line < 1)
+ txt_move_toline(text, 1, 0);
+ else if (line > nlines)
+ txt_move_toline(text, nlines - 1, 0);
+ else
+ txt_move_toline(text, line - 1, 0);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
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, 100);
}
void TEXT_OT_jump(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Jump";
- ot->idname = "TEXT_OT_jump";
- ot->description = "Jump cursor to line";
+ /* identifiers */
+ ot->name = "Jump";
+ ot->idname = "TEXT_OT_jump";
+ ot->description = "Jump cursor to line";
- /* api callbacks */
- ot->invoke = text_jump_invoke;
- ot->exec = text_jump_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->invoke = text_jump_invoke;
+ ot->exec = text_jump_exec;
+ ot->poll = text_edit_poll;
- /* properties */
- prop = RNA_def_int(ot->srna, "line", 1, 1, INT_MAX, "Line", "Line number to jump to", 1, 10000);
- RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_TEXT);
+ /* properties */
+ prop = RNA_def_int(ot->srna, "line", 1, 1, INT_MAX, "Line", "Line number to jump to", 1, 10000);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_TEXT);
}
/******************* delete operator **********************/
static const EnumPropertyItem delete_type_items[] = {
- {DEL_NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
- {DEL_PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
- {DEL_NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
- {DEL_PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
- {0, NULL, 0, NULL, NULL},
+ {DEL_NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
+ {DEL_PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
+ {DEL_NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
+ {DEL_PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int text_delete_exec(bContext *C, wmOperator *op)
{
- SpaceText *st = CTX_wm_space_text(C);
- Text *text = CTX_data_edit_text(C);
- int type = RNA_enum_get(op->ptr, "type");
-
-
- text_drawcache_tag_update(st, 0);
-
- /* behavior could be changed here,
- * but for now just don't jump words when we have a selection */
- if (txt_has_sel(text)) {
- if (type == DEL_PREV_WORD) type = DEL_PREV_CHAR;
- else if (type == DEL_NEXT_WORD) type = DEL_NEXT_CHAR;
- }
-
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
-
- if (type == DEL_PREV_WORD) {
- if (txt_cursor_is_line_start(text)) {
- txt_backspace_char(text, utxt);
- }
- txt_backspace_word(text, utxt);
- }
- else if (type == DEL_PREV_CHAR) {
-
- if (text->flags & TXT_TABSTOSPACES) {
- if (!txt_has_sel(text) && !txt_cursor_is_line_start(text)) {
- int tabsize = 0;
- tabsize = txt_calc_tab_left(text->curl, text->curc);
- if (tabsize) {
- text->sell = text->curl;
- text->selc = text->curc - tabsize;
- txt_order_cursors(text, false);
- }
- }
- }
-
- txt_backspace_char(text, utxt);
- }
- else if (type == DEL_NEXT_WORD) {
- if (txt_cursor_is_line_end(text)) {
- txt_delete_char(text, utxt);
- }
- txt_delete_word(text, utxt);
- }
- else if (type == DEL_NEXT_CHAR) {
-
- if (text->flags & TXT_TABSTOSPACES) {
- if (!txt_has_sel(text) && !txt_cursor_is_line_end(text)) {
- int tabsize = 0;
- tabsize = txt_calc_tab_right(text->curl, text->curc);
- if (tabsize) {
- text->sell = text->curl;
- text->selc = text->curc + tabsize;
- txt_order_cursors(text, true);
- }
- }
- }
-
- txt_delete_char(text, utxt);
- }
-
- text_update_line_edited(text->curl);
-
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
-
- /* run the script while editing, evil but useful */
- if (st->live_edit)
- text_run_script(C, NULL);
-
- return OPERATOR_FINISHED;
+ SpaceText *st = CTX_wm_space_text(C);
+ Text *text = CTX_data_edit_text(C);
+ int type = RNA_enum_get(op->ptr, "type");
+
+ text_drawcache_tag_update(st, 0);
+
+ /* behavior could be changed here,
+ * but for now just don't jump words when we have a selection */
+ if (txt_has_sel(text)) {
+ if (type == DEL_PREV_WORD)
+ type = DEL_PREV_CHAR;
+ else if (type == DEL_NEXT_WORD)
+ type = DEL_NEXT_CHAR;
+ }
+
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+
+ if (type == DEL_PREV_WORD) {
+ if (txt_cursor_is_line_start(text)) {
+ txt_backspace_char(text, utxt);
+ }
+ txt_backspace_word(text, utxt);
+ }
+ else if (type == DEL_PREV_CHAR) {
+
+ if (text->flags & TXT_TABSTOSPACES) {
+ if (!txt_has_sel(text) && !txt_cursor_is_line_start(text)) {
+ int tabsize = 0;
+ tabsize = txt_calc_tab_left(text->curl, text->curc);
+ if (tabsize) {
+ text->sell = text->curl;
+ text->selc = text->curc - tabsize;
+ txt_order_cursors(text, false);
+ }
+ }
+ }
+
+ txt_backspace_char(text, utxt);
+ }
+ else if (type == DEL_NEXT_WORD) {
+ if (txt_cursor_is_line_end(text)) {
+ txt_delete_char(text, utxt);
+ }
+ txt_delete_word(text, utxt);
+ }
+ else if (type == DEL_NEXT_CHAR) {
+
+ if (text->flags & TXT_TABSTOSPACES) {
+ if (!txt_has_sel(text) && !txt_cursor_is_line_end(text)) {
+ int tabsize = 0;
+ tabsize = txt_calc_tab_right(text->curl, text->curc);
+ if (tabsize) {
+ text->sell = text->curl;
+ text->selc = text->curc + tabsize;
+ txt_order_cursors(text, true);
+ }
+ }
+ }
+
+ txt_delete_char(text, utxt);
+ }
+
+ text_update_line_edited(text->curl);
+
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+
+ /* run the script while editing, evil but useful */
+ if (st->live_edit)
+ text_run_script(C, NULL);
+
+ return OPERATOR_FINISHED;
}
void TEXT_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete";
- ot->idname = "TEXT_OT_delete";
- ot->description = "Delete text by cursor position";
+ /* identifiers */
+ ot->name = "Delete";
+ ot->idname = "TEXT_OT_delete";
+ ot->description = "Delete text by cursor position";
- /* api callbacks */
- ot->exec = text_delete_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_delete_exec;
+ ot->poll = text_edit_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- /* properties */
- PropertyRNA *prop;
- prop = RNA_def_enum(ot->srna, "type", delete_type_items, DEL_NEXT_CHAR, "Type", "Which part of the text to delete");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ /* properties */
+ PropertyRNA *prop;
+ prop = RNA_def_enum(ot->srna,
+ "type",
+ delete_type_items,
+ DEL_NEXT_CHAR,
+ "Type",
+ "Which part of the text to delete");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/******************* toggle overwrite operator **********************/
static int text_toggle_overwrite_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceText *st = CTX_wm_space_text(C);
+ SpaceText *st = CTX_wm_space_text(C);
- st->overwrite = !st->overwrite;
+ st->overwrite = !st->overwrite;
- WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
+ WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_overwrite_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Overwrite";
- ot->idname = "TEXT_OT_overwrite_toggle";
- ot->description = "Toggle overwrite while typing";
+ /* identifiers */
+ ot->name = "Toggle Overwrite";
+ ot->idname = "TEXT_OT_overwrite_toggle";
+ ot->description = "Toggle overwrite while typing";
- /* api callbacks */
- ot->exec = text_toggle_overwrite_exec;
- ot->poll = text_space_edit_poll;
+ /* api callbacks */
+ ot->exec = text_toggle_overwrite_exec;
+ ot->poll = text_space_edit_poll;
}
/******************* scroll operator **********************/
static void txt_screen_clamp(SpaceText *st, ARegion *ar)
{
- if (st->top <= 0) {
- st->top = 0;
- }
- else {
- int last;
- last = text_get_total_lines(st, ar);
- last = last - (st->viewlines / 2);
- if (last > 0 && st->top > last) {
- st->top = last;
- }
- }
+ if (st->top <= 0) {
+ st->top = 0;
+ }
+ else {
+ int last;
+ last = text_get_total_lines(st, ar);
+ last = last - (st->viewlines / 2);
+ if (last > 0 && st->top > last) {
+ st->top = last;
+ }
+ }
}
/* Moves the view vertically by the specified number of lines */
static void txt_screen_skip(SpaceText *st, ARegion *ar, int lines)
{
- st->top += lines;
- txt_screen_clamp(st, ar);
+ st->top += lines;
+ txt_screen_clamp(st, ar);
}
/* quick enum for tsc->zone (scroller handles) */
enum {
- SCROLLHANDLE_BAR,
- SCROLLHANDLE_MIN_OUTSIDE,
- SCROLLHANDLE_MAX_OUTSIDE,
+ SCROLLHANDLE_BAR,
+ SCROLLHANDLE_MIN_OUTSIDE,
+ SCROLLHANDLE_MAX_OUTSIDE,
};
typedef struct TextScroll {
- int old[2];
- int delta[2];
+ int old[2];
+ int delta[2];
- int first;
- int scrollbar;
+ int first;
+ int scrollbar;
- int zone;
+ int zone;
} TextScroll;
static bool text_scroll_poll(bContext *C)
{
- /* it should be possible to still scroll linked texts to read them,
- * even if they can't be edited... */
- return CTX_data_edit_text(C) != NULL;
+ /* it should be possible to still scroll linked texts to read them,
+ * even if they can't be edited... */
+ return CTX_data_edit_text(C) != NULL;
}
static int text_scroll_exec(bContext *C, wmOperator *op)
{
- SpaceText *st = CTX_wm_space_text(C);
- ARegion *ar = CTX_wm_region(C);
+ SpaceText *st = CTX_wm_space_text(C);
+ ARegion *ar = CTX_wm_region(C);
- int lines = RNA_int_get(op->ptr, "lines");
+ int lines = RNA_int_get(op->ptr, "lines");
- if (lines == 0)
- return OPERATOR_CANCELLED;
+ if (lines == 0)
+ return OPERATOR_CANCELLED;
- txt_screen_skip(st, ar, lines * U.wheellinescroll);
+ txt_screen_skip(st, ar, lines * U.wheellinescroll);
- ED_area_tag_redraw(CTX_wm_area(C));
+ ED_area_tag_redraw(CTX_wm_area(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void text_scroll_apply(bContext *C, wmOperator *op, const wmEvent *event)
{
- SpaceText *st = CTX_wm_space_text(C);
- ARegion *ar = CTX_wm_region(C);
- TextScroll *tsc = op->customdata;
- int mval[2] = {event->x, event->y};
- int scroll_steps[2] = {0, 0};
-
- text_update_character_width(st);
-
- /* compute mouse move distance */
- if (tsc->first) {
- tsc->old[0] = mval[0];
- tsc->old[1] = mval[1];
- tsc->first = 0;
- }
-
- if (event->type != MOUSEPAN) {
- tsc->delta[0] = mval[0] - tsc->old[0];
- tsc->delta[1] = mval[1] - tsc->old[1];
- }
-
- /* accumulate scroll, in float values for events that give less than one
- * line offset but taken together should still scroll */
- if (!tsc->scrollbar) {
- st->scroll_accum[0] += -tsc->delta[0] / (float)st->cwidth;
- st->scroll_accum[1] += tsc->delta[1] / (float)(st->lheight_dpi + TXT_LINE_SPACING);
- }
- else {
- st->scroll_accum[1] += -tsc->delta[1] * st->pix_per_line;
- }
-
- /* round to number of lines to scroll */
- scroll_steps[0] = (int)st->scroll_accum[0];
- scroll_steps[1] = (int)st->scroll_accum[1];
-
- st->scroll_accum[0] -= scroll_steps[0];
- st->scroll_accum[1] -= scroll_steps[1];
-
- /* perform vertical and/or horizontal scroll */
- if (scroll_steps[0] || scroll_steps[1]) {
- txt_screen_skip(st, ar, scroll_steps[1]);
-
- if (st->wordwrap) {
- st->left = 0;
- }
- else {
- st->left += scroll_steps[0];
- if (st->left < 0) st->left = 0;
- }
-
- ED_area_tag_redraw(CTX_wm_area(C));
- }
-
- tsc->old[0] = mval[0];
- tsc->old[1] = mval[1];
+ SpaceText *st = CTX_wm_space_text(C);
+ ARegion *ar = CTX_wm_region(C);
+ TextScroll *tsc = op->customdata;
+ int mval[2] = {event->x, event->y};
+ int scroll_steps[2] = {0, 0};
+
+ text_update_character_width(st);
+
+ /* compute mouse move distance */
+ if (tsc->first) {
+ tsc->old[0] = mval[0];
+ tsc->old[1] = mval[1];
+ tsc->first = 0;
+ }
+
+ if (event->type != MOUSEPAN) {
+ tsc->delta[0] = mval[0] - tsc->old[0];
+ tsc->delta[1] = mval[1] - tsc->old[1];
+ }
+
+ /* accumulate scroll, in float values for events that give less than one
+ * line offset but taken together should still scroll */
+ if (!tsc->scrollbar) {
+ st->scroll_accum[0] += -tsc->delta[0] / (float)st->cwidth;
+ st->scroll_accum[1] += tsc->delta[1] / (float)(st->lheight_dpi + TXT_LINE_SPACING);
+ }
+ else {
+ st->scroll_accum[1] += -tsc->delta[1] * st->pix_per_line;
+ }
+
+ /* round to number of lines to scroll */
+ scroll_steps[0] = (int)st->scroll_accum[0];
+ scroll_steps[1] = (int)st->scroll_accum[1];
+
+ st->scroll_accum[0] -= scroll_steps[0];
+ st->scroll_accum[1] -= scroll_steps[1];
+
+ /* perform vertical and/or horizontal scroll */
+ if (scroll_steps[0] || scroll_steps[1]) {
+ txt_screen_skip(st, ar, scroll_steps[1]);
+
+ if (st->wordwrap) {
+ st->left = 0;
+ }
+ else {
+ st->left += scroll_steps[0];
+ if (st->left < 0)
+ st->left = 0;
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+ tsc->old[0] = mval[0];
+ tsc->old[1] = mval[1];
}
static void scroll_exit(bContext *C, wmOperator *op)
{
- SpaceText *st = CTX_wm_space_text(C);
+ SpaceText *st = CTX_wm_space_text(C);
- st->flags &= ~ST_SCROLL_SELECT;
- MEM_freeN(op->customdata);
+ st->flags &= ~ST_SCROLL_SELECT;
+ MEM_freeN(op->customdata);
}
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);
-
- switch (event->type) {
- case MOUSEMOVE:
- if (tsc->zone == SCROLLHANDLE_BAR)
- text_scroll_apply(C, op, event);
- break;
- case LEFTMOUSE:
- case RIGHTMOUSE:
- case MIDDLEMOUSE:
- if (event->val == KM_RELEASE) {
- if (ELEM(tsc->zone, SCROLLHANDLE_MIN_OUTSIDE, SCROLLHANDLE_MAX_OUTSIDE)) {
- txt_screen_skip(st, ar, st->viewlines * (tsc->zone == SCROLLHANDLE_MIN_OUTSIDE ? 1 : -1));
-
- ED_area_tag_redraw(CTX_wm_area(C));
- }
- scroll_exit(C, op);
- return OPERATOR_FINISHED;
- }
- }
-
- return OPERATOR_RUNNING_MODAL;
+ TextScroll *tsc = op->customdata;
+ SpaceText *st = CTX_wm_space_text(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ switch (event->type) {
+ case MOUSEMOVE:
+ if (tsc->zone == SCROLLHANDLE_BAR)
+ text_scroll_apply(C, op, event);
+ break;
+ case LEFTMOUSE:
+ case RIGHTMOUSE:
+ case MIDDLEMOUSE:
+ if (event->val == KM_RELEASE) {
+ if (ELEM(tsc->zone, SCROLLHANDLE_MIN_OUTSIDE, SCROLLHANDLE_MAX_OUTSIDE)) {
+ txt_screen_skip(
+ st, ar, st->viewlines * (tsc->zone == SCROLLHANDLE_MIN_OUTSIDE ? 1 : -1));
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+ scroll_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
static void text_scroll_cancel(bContext *C, wmOperator *op)
{
- scroll_exit(C, op);
+ scroll_exit(C, op);
}
static int text_scroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- SpaceText *st = CTX_wm_space_text(C);
- TextScroll *tsc;
+ SpaceText *st = CTX_wm_space_text(C);
+ TextScroll *tsc;
- if (RNA_struct_property_is_set(op->ptr, "lines"))
- return text_scroll_exec(C, op);
+ if (RNA_struct_property_is_set(op->ptr, "lines"))
+ return text_scroll_exec(C, op);
- tsc = MEM_callocN(sizeof(TextScroll), "TextScroll");
- tsc->first = 1;
- tsc->zone = SCROLLHANDLE_BAR;
- op->customdata = tsc;
+ tsc = MEM_callocN(sizeof(TextScroll), "TextScroll");
+ tsc->first = 1;
+ tsc->zone = SCROLLHANDLE_BAR;
+ op->customdata = tsc;
- st->flags |= ST_SCROLL_SELECT;
+ st->flags |= ST_SCROLL_SELECT;
- if (event->type == MOUSEPAN) {
- text_update_character_width(st);
+ if (event->type == MOUSEPAN) {
+ text_update_character_width(st);
- tsc->old[0] = event->x;
- tsc->old[1] = event->y;
- /* Sensitivity of scroll set to 4pix per line/char */
- tsc->delta[0] = (event->x - event->prevx) * st->cwidth / 4;
- tsc->delta[1] = (event->y - event->prevy) * st->lheight_dpi / 4;
- tsc->first = 0;
- tsc->scrollbar = 0;
- text_scroll_apply(C, op, event);
- scroll_exit(C, op);
- return OPERATOR_FINISHED;
- }
+ tsc->old[0] = event->x;
+ tsc->old[1] = event->y;
+ /* Sensitivity of scroll set to 4pix per line/char */
+ tsc->delta[0] = (event->x - event->prevx) * st->cwidth / 4;
+ tsc->delta[1] = (event->y - event->prevy) * st->lheight_dpi / 4;
+ tsc->first = 0;
+ tsc->scrollbar = 0;
+ text_scroll_apply(C, op, event);
+ scroll_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void TEXT_OT_scroll(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Scroll";
- /* don't really see the difference between this and
- * scroll_bar. Both do basically the same thing (aside
- * from keymaps).*/
- ot->idname = "TEXT_OT_scroll";
+ /* identifiers */
+ ot->name = "Scroll";
+ /* don't really see the difference between this and
+ * scroll_bar. Both do basically the same thing (aside
+ * from keymaps).*/
+ ot->idname = "TEXT_OT_scroll";
- /* api callbacks */
- ot->exec = text_scroll_exec;
- ot->invoke = text_scroll_invoke;
- ot->modal = text_scroll_modal;
- ot->cancel = text_scroll_cancel;
- ot->poll = text_scroll_poll;
+ /* api callbacks */
+ ot->exec = text_scroll_exec;
+ ot->invoke = text_scroll_invoke;
+ ot->modal = text_scroll_modal;
+ ot->cancel = text_scroll_cancel;
+ ot->poll = text_scroll_poll;
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_INTERNAL;
- /* properties */
- RNA_def_int(ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100);
+ /* properties */
+ RNA_def_int(
+ ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100);
}
/******************** scroll bar operator *******************/
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);
+ /* 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);
- if (!st || !text)
- return 0;
+ if (!st || !text)
+ return 0;
- if (!ar || ar->regiontype != RGN_TYPE_WINDOW)
- return 0;
+ if (!ar || ar->regiontype != RGN_TYPE_WINDOW)
+ return 0;
- return 1;
+ return 1;
}
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);
- TextScroll *tsc;
- const int *mval = event->mval;
- int zone = -1;
-
- if (RNA_struct_property_is_set(op->ptr, "lines"))
- return text_scroll_exec(C, op);
-
- /* verify we are in the right zone */
- if (mval[0] > st->txtbar.xmin && mval[0] < st->txtbar.xmax) {
- if (mval[1] >= st->txtbar.ymin && mval[1] <= st->txtbar.ymax) {
- /* mouse inside scroll handle */
- zone = SCROLLHANDLE_BAR;
- }
- else if (mval[1] > TXT_SCROLL_SPACE && mval[1] < ar->winy - TXT_SCROLL_SPACE) {
- if (mval[1] < st->txtbar.ymin) zone = SCROLLHANDLE_MIN_OUTSIDE;
- else zone = SCROLLHANDLE_MAX_OUTSIDE;
- }
- }
-
- if (zone == -1) {
- /* we are outside slider - nothing to do */
- return OPERATOR_PASS_THROUGH;
- }
-
- tsc = MEM_callocN(sizeof(TextScroll), "TextScroll");
- tsc->first = 1;
- tsc->scrollbar = 1;
- tsc->zone = zone;
- op->customdata = tsc;
- st->flags |= ST_SCROLL_SELECT;
-
- /* jump scroll, works in v2d but needs to be added here too :S */
- if (event->type == MIDDLEMOUSE) {
- tsc->old[0] = ar->winrct.xmin + BLI_rcti_cent_x(&st->txtbar);
- tsc->old[1] = ar->winrct.ymin + BLI_rcti_cent_y(&st->txtbar);
-
- tsc->first = 0;
- tsc->zone = SCROLLHANDLE_BAR;
- text_scroll_apply(C, op, event);
- }
-
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
+ SpaceText *st = CTX_wm_space_text(C);
+ ARegion *ar = CTX_wm_region(C);
+ TextScroll *tsc;
+ const int *mval = event->mval;
+ int zone = -1;
+
+ if (RNA_struct_property_is_set(op->ptr, "lines"))
+ return text_scroll_exec(C, op);
+
+ /* verify we are in the right zone */
+ if (mval[0] > st->txtbar.xmin && mval[0] < st->txtbar.xmax) {
+ if (mval[1] >= st->txtbar.ymin && mval[1] <= st->txtbar.ymax) {
+ /* mouse inside scroll handle */
+ zone = SCROLLHANDLE_BAR;
+ }
+ else if (mval[1] > TXT_SCROLL_SPACE && mval[1] < ar->winy - TXT_SCROLL_SPACE) {
+ if (mval[1] < st->txtbar.ymin)
+ zone = SCROLLHANDLE_MIN_OUTSIDE;
+ else
+ zone = SCROLLHANDLE_MAX_OUTSIDE;
+ }
+ }
+
+ if (zone == -1) {
+ /* we are outside slider - nothing to do */
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ tsc = MEM_callocN(sizeof(TextScroll), "TextScroll");
+ tsc->first = 1;
+ tsc->scrollbar = 1;
+ tsc->zone = zone;
+ op->customdata = tsc;
+ st->flags |= ST_SCROLL_SELECT;
+
+ /* jump scroll, works in v2d but needs to be added here too :S */
+ if (event->type == MIDDLEMOUSE) {
+ tsc->old[0] = ar->winrct.xmin + BLI_rcti_cent_x(&st->txtbar);
+ tsc->old[1] = ar->winrct.ymin + BLI_rcti_cent_y(&st->txtbar);
+
+ tsc->first = 0;
+ tsc->zone = SCROLLHANDLE_BAR;
+ text_scroll_apply(C, op, event);
+ }
+
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
}
void TEXT_OT_scroll_bar(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Scrollbar";
- /* don't really see the difference between this and
- * scroll. Both do basically the same thing (aside
- * from keymaps).*/
- ot->idname = "TEXT_OT_scroll_bar";
+ /* identifiers */
+ ot->name = "Scrollbar";
+ /* don't really see the difference between this and
+ * scroll. Both do basically the same thing (aside
+ * from keymaps).*/
+ ot->idname = "TEXT_OT_scroll_bar";
- /* api callbacks */
- ot->invoke = text_scroll_bar_invoke;
- ot->modal = text_scroll_modal;
- ot->cancel = text_scroll_cancel;
- ot->poll = text_region_scroll_poll;
+ /* api callbacks */
+ ot->invoke = text_scroll_bar_invoke;
+ ot->modal = text_scroll_modal;
+ ot->cancel = text_scroll_cancel;
+ ot->poll = text_region_scroll_poll;
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
- /* properties */
- RNA_def_int(ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100);
+ /* properties */
+ RNA_def_int(
+ ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100);
}
/******************* set selection operator **********************/
typedef struct SetSelection {
- int selecting;
- int selc, sell;
- short old[2];
- wmTimer *timer; /* needed for scrolling when mouse at region bounds */
+ int selecting;
+ int selc, sell;
+ short old[2];
+ wmTimer *timer; /* needed for scrolling when mouse at region bounds */
} SetSelection;
static int flatten_width(SpaceText *st, const char *str)
{
- int i, total = 0;
+ int i, total = 0;
- for (i = 0; str[i]; i += BLI_str_utf8_size_safe(str + i)) {
- if (str[i] == '\t') {
- total += st->tabnumber - total % st->tabnumber;
- }
- else {
- total += BLI_str_utf8_char_width_safe(str + i);
- }
- }
+ for (i = 0; str[i]; i += BLI_str_utf8_size_safe(str + i)) {
+ if (str[i] == '\t') {
+ total += st->tabnumber - total % st->tabnumber;
+ }
+ else {
+ total += BLI_str_utf8_char_width_safe(str + i);
+ }
+ }
- return total;
+ return total;
}
static int flatten_column_to_offset(SpaceText *st, const char *str, int index)
{
- int i = 0, j = 0, col;
+ int i = 0, j = 0, col;
- while (*(str + j)) {
- if (str[j] == '\t')
- col = st->tabnumber - i % st->tabnumber;
- else
- col = BLI_str_utf8_char_width_safe(str + j);
+ while (*(str + j)) {
+ if (str[j] == '\t')
+ col = st->tabnumber - i % st->tabnumber;
+ else
+ col = BLI_str_utf8_char_width_safe(str + j);
- if (i + col > index)
- break;
+ if (i + col > index)
+ break;
- i += col;
- j += BLI_str_utf8_size_safe(str + j);
- }
+ i += col;
+ j += BLI_str_utf8_size_safe(str + j);
+ }
- return j;
+ return j;
}
static TextLine *get_line_pos_wrapped(SpaceText *st, ARegion *ar, int *y)
{
- TextLine *linep = st->text->lines.first;
- int i, lines;
-
- if (*y < -st->top) {
- return NULL; /* We are beyond the first line... */
- }
-
- for (i = -st->top; i <= *y && linep; linep = linep->next, i += lines) {
- lines = text_get_visible_lines(st, ar, linep->line);
-
- if (i + lines > *y) {
- /* We found the line matching given vertical 'coordinate',
- * now set y relative to this line's start. */
- *y -= i;
- break;
- }
- }
- return linep;
-}
-
-static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, 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 */
-
- /* Point to line matching given y position, if any. */
- TextLine *linep = get_line_pos_wrapped(st, ar, &y);
-
- if (linep) {
- int i = 0, start = 0, end = max; /* column */
- int j, curs = 0, endj = 0; /* mem */
- bool chop = true; /* flags */
- char ch;
-
- for (j = 0 ; !found && ((ch = linep->line[j]) != '\0'); j += BLI_str_utf8_size_safe(linep->line + j)) {
- int chars;
- int columns = BLI_str_utf8_char_width_safe(linep->line + j); /* = 1 for tab */
-
- /* Mimic replacement of tabs */
- if (ch == '\t') {
- chars = st->tabnumber - i % st->tabnumber;
- ch = ' ';
- }
- else {
- chars = 1;
- }
-
- while (chars--) {
- /* Gone too far, go back to last wrap point */
- if (y < 0) {
- charp = endj;
- y = 0;
- found = true;
- break;
- /* Exactly at the cursor */
- }
- else if (y == 0 && i - start <= x && i + columns - start > x) {
- /* current position could be wrapped to next line */
- /* this should be checked when end of current line would be reached */
- charp = curs = j;
- found = true;
- /* Prepare curs for next wrap */
- }
- else if (i - end <= x && i + columns - end > x) {
- curs = j;
- }
- if (i + columns - start > max) {
- end = MIN2(end, i);
-
- if (found) {
- /* exact cursor position was found, check if it's still on needed line
- * (hasn't been wrapped) */
- if (charp > endj && !chop && ch != '\0')
- charp = endj;
- break;
- }
-
- if (chop)
- endj = j;
- start = end;
- end += max;
-
- if (j < linep->len)
- y--;
-
- chop = true;
- if (y == 0 && i + columns - start > x) {
- charp = curs;
- found = true;
- break;
- }
- }
- else if (ch == ' ' || ch == '-' || ch == '\0') {
- if (found) {
- break;
- }
-
- if (y == 0 && i + columns - start > x) {
- charp = curs;
- found = true;
- break;
- }
- end = i + 1;
- endj = j;
- chop = false;
- }
- i += columns;
- }
- }
-
- BLI_assert(y == 0);
-
- if (!found) {
- /* On correct line but didn't meet cursor, must be at end */
- charp = linep->len;
- }
- }
- else if (y < 0) { /* Before start of text. */
- linep = st->text->lines.first;
- charp = 0;
- }
- else { /* Beyond end of text */
- linep = st->text->lines.last;
- charp = linep->len;
- }
-
- BLI_assert(linep && charp != -1);
-
- if (sel) {
- text->sell = linep;
- text->selc = charp;
- }
- else {
- text->curl = linep;
- text->curc = charp;
- }
+ TextLine *linep = st->text->lines.first;
+ int i, lines;
+
+ if (*y < -st->top) {
+ return NULL; /* We are beyond the first line... */
+ }
+
+ for (i = -st->top; i <= *y && linep; linep = linep->next, i += lines) {
+ lines = text_get_visible_lines(st, ar, linep->line);
+
+ if (i + lines > *y) {
+ /* We found the line matching given vertical 'coordinate',
+ * now set y relative to this line's start. */
+ *y -= i;
+ break;
+ }
+ }
+ return linep;
+}
+
+static void text_cursor_set_to_pos_wrapped(
+ SpaceText *st, ARegion *ar, 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 */
+
+ /* Point to line matching given y position, if any. */
+ TextLine *linep = get_line_pos_wrapped(st, ar, &y);
+
+ if (linep) {
+ int i = 0, start = 0, end = max; /* column */
+ int j, curs = 0, endj = 0; /* mem */
+ bool chop = true; /* flags */
+ char ch;
+
+ for (j = 0; !found && ((ch = linep->line[j]) != '\0');
+ j += BLI_str_utf8_size_safe(linep->line + j)) {
+ int chars;
+ int columns = BLI_str_utf8_char_width_safe(linep->line + j); /* = 1 for tab */
+
+ /* Mimic replacement of tabs */
+ if (ch == '\t') {
+ chars = st->tabnumber - i % st->tabnumber;
+ ch = ' ';
+ }
+ else {
+ chars = 1;
+ }
+
+ while (chars--) {
+ /* Gone too far, go back to last wrap point */
+ if (y < 0) {
+ charp = endj;
+ y = 0;
+ found = true;
+ break;
+ /* Exactly at the cursor */
+ }
+ else if (y == 0 && i - start <= x && i + columns - start > x) {
+ /* current position could be wrapped to next line */
+ /* this should be checked when end of current line would be reached */
+ charp = curs = j;
+ found = true;
+ /* Prepare curs for next wrap */
+ }
+ else if (i - end <= x && i + columns - end > x) {
+ curs = j;
+ }
+ if (i + columns - start > max) {
+ end = MIN2(end, i);
+
+ if (found) {
+ /* exact cursor position was found, check if it's still on needed line
+ * (hasn't been wrapped) */
+ if (charp > endj && !chop && ch != '\0')
+ charp = endj;
+ break;
+ }
+
+ if (chop)
+ endj = j;
+ start = end;
+ end += max;
+
+ if (j < linep->len)
+ y--;
+
+ chop = true;
+ if (y == 0 && i + columns - start > x) {
+ charp = curs;
+ found = true;
+ break;
+ }
+ }
+ else if (ch == ' ' || ch == '-' || ch == '\0') {
+ if (found) {
+ break;
+ }
+
+ if (y == 0 && i + columns - start > x) {
+ charp = curs;
+ found = true;
+ break;
+ }
+ end = i + 1;
+ endj = j;
+ chop = false;
+ }
+ i += columns;
+ }
+ }
+
+ BLI_assert(y == 0);
+
+ if (!found) {
+ /* On correct line but didn't meet cursor, must be at end */
+ charp = linep->len;
+ }
+ }
+ else if (y < 0) { /* Before start of text. */
+ linep = st->text->lines.first;
+ charp = 0;
+ }
+ else { /* Beyond end of text */
+ linep = st->text->lines.last;
+ charp = linep->len;
+ }
+
+ BLI_assert(linep && charp != -1);
+
+ if (sel) {
+ text->sell = linep;
+ text->selc = charp;
+ }
+ else {
+ text->curl = linep;
+ text->curc = charp;
+ }
}
static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, const bool sel)
{
- Text *text = st->text;
- text_update_character_width(st);
- y = (ar->winy - 2 - y) / (st->lheight_dpi + TXT_LINE_SPACING);
-
- if (st->showlinenrs) x -= TXT_OFFSET + TEXTXLOC;
- else x -= TXT_OFFSET;
-
- if (x < 0) x = 0;
- x = text_pixel_x_to_column(st, x) + st->left;
-
- if (st->wordwrap) {
- text_cursor_set_to_pos_wrapped(st, ar, x, y, sel);
- }
- else {
- TextLine **linep;
- int *charp;
- int w;
-
- if (sel) { linep = &text->sell; charp = &text->selc; }
- else { linep = &text->curl; charp = &text->curc; }
-
- y -= txt_get_span(text->lines.first, *linep) - st->top;
-
- if (y > 0) {
- while (y-- != 0) {
- if ((*linep)->next) *linep = (*linep)->next;
- }
- }
- else if (y < 0) {
- while (y++ != 0) {
- if ((*linep)->prev) *linep = (*linep)->prev;
- }
- }
-
-
- w = flatten_width(st, (*linep)->line);
- if (x < w) *charp = flatten_column_to_offset(st, (*linep)->line, x);
- else *charp = (*linep)->len;
- }
- if (!sel) txt_pop_sel(text);
+ Text *text = st->text;
+ text_update_character_width(st);
+ y = (ar->winy - 2 - y) / (st->lheight_dpi + TXT_LINE_SPACING);
+
+ if (st->showlinenrs)
+ x -= TXT_OFFSET + TEXTXLOC;
+ else
+ x -= TXT_OFFSET;
+
+ if (x < 0)
+ x = 0;
+ x = text_pixel_x_to_column(st, x) + st->left;
+
+ if (st->wordwrap) {
+ text_cursor_set_to_pos_wrapped(st, ar, x, y, sel);
+ }
+ else {
+ TextLine **linep;
+ int *charp;
+ int w;
+
+ if (sel) {
+ linep = &text->sell;
+ charp = &text->selc;
+ }
+ else {
+ linep = &text->curl;
+ charp = &text->curc;
+ }
+
+ y -= txt_get_span(text->lines.first, *linep) - st->top;
+
+ if (y > 0) {
+ while (y-- != 0) {
+ if ((*linep)->next)
+ *linep = (*linep)->next;
+ }
+ }
+ else if (y < 0) {
+ while (y++ != 0) {
+ if ((*linep)->prev)
+ *linep = (*linep)->prev;
+ }
+ }
+
+ w = flatten_width(st, (*linep)->line);
+ if (x < w)
+ *charp = flatten_column_to_offset(st, (*linep)->line, x);
+ else
+ *charp = (*linep)->len;
+ }
+ if (!sel)
+ txt_pop_sel(text);
}
static void text_cursor_timer_ensure(bContext *C, SetSelection *ssel)
{
- if (ssel->timer == NULL) {
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
+ if (ssel->timer == NULL) {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
- ssel->timer = WM_event_add_timer(wm, win, TIMER, 0.02f);
- }
+ ssel->timer = WM_event_add_timer(wm, win, TIMER, 0.02f);
+ }
}
static void text_cursor_timer_remove(bContext *C, SetSelection *ssel)
{
- if (ssel->timer) {
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
+ if (ssel->timer) {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
- WM_event_remove_timer(wm, win, ssel->timer);
- }
- ssel->timer = NULL;
+ WM_event_remove_timer(wm, win, ssel->timer);
+ }
+ ssel->timer = NULL;
}
-
-
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);
- SetSelection *ssel = op->customdata;
-
- if (event->mval[1] < 0 || event->mval[1] > ar->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);
- WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
- }
- }
- else if (!st->wordwrap && (event->mval[0] < 0 || event->mval[0] > ar->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);
- WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
- }
- }
- else {
- 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);
- WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
-
- ssel->old[0] = event->mval[0];
- ssel->old[1] = event->mval[1];
- }
- }
+ SpaceText *st = CTX_wm_space_text(C);
+ ARegion *ar = CTX_wm_region(C);
+ SetSelection *ssel = op->customdata;
+
+ if (event->mval[1] < 0 || event->mval[1] > ar->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);
+ WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
+ }
+ }
+ else if (!st->wordwrap && (event->mval[0] < 0 || event->mval[0] > ar->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);
+ WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
+ }
+ }
+ else {
+ 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);
+ WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
+
+ ssel->old[0] = event->mval[0];
+ ssel->old[1] = event->mval[1];
+ }
+ }
}
static void text_cursor_set_exit(bContext *C, wmOperator *op)
{
- SpaceText *st = CTX_wm_space_text(C);
- Text *text = st->text;
- SetSelection *ssel = op->customdata;
- char *buffer;
+ SpaceText *st = CTX_wm_space_text(C);
+ Text *text = st->text;
+ SetSelection *ssel = op->customdata;
+ char *buffer;
- if (txt_has_sel(text)) {
- buffer = txt_sel_to_buf(text);
- WM_clipboard_text_set(buffer, 1);
- MEM_freeN(buffer);
- }
+ if (txt_has_sel(text)) {
+ buffer = txt_sel_to_buf(text);
+ WM_clipboard_text_set(buffer, 1);
+ MEM_freeN(buffer);
+ }
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
- text_cursor_timer_remove(C, ssel);
- MEM_freeN(ssel);
+ text_cursor_timer_remove(C, ssel);
+ MEM_freeN(ssel);
}
static int text_set_selection_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- SpaceText *st = CTX_wm_space_text(C);
- SetSelection *ssel;
+ SpaceText *st = CTX_wm_space_text(C);
+ SetSelection *ssel;
- if (event->mval[0] >= st->txtbar.xmin)
- return OPERATOR_PASS_THROUGH;
+ if (event->mval[0] >= st->txtbar.xmin)
+ return OPERATOR_PASS_THROUGH;
- op->customdata = MEM_callocN(sizeof(SetSelection), "SetCursor");
- ssel = op->customdata;
- ssel->selecting = RNA_boolean_get(op->ptr, "select");
+ op->customdata = MEM_callocN(sizeof(SetSelection), "SetCursor");
+ ssel = op->customdata;
+ ssel->selecting = RNA_boolean_get(op->ptr, "select");
- ssel->old[0] = event->mval[0];
- ssel->old[1] = event->mval[1];
+ ssel->old[0] = event->mval[0];
+ ssel->old[1] = event->mval[1];
- ssel->sell = txt_get_span(st->text->lines.first, st->text->sell);
- ssel->selc = st->text->selc;
+ ssel->sell = txt_get_span(st->text->lines.first, st->text->sell);
+ ssel->selc = st->text->selc;
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
- text_cursor_set_apply(C, op, event);
+ text_cursor_set_apply(C, op, event);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static int text_set_selection_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- switch (event->type) {
- case LEFTMOUSE:
- case MIDDLEMOUSE:
- case RIGHTMOUSE:
- text_cursor_set_exit(C, op);
- return OPERATOR_FINISHED;
- case TIMER:
- case MOUSEMOVE:
- text_cursor_set_apply(C, op, event);
- break;
- }
+ switch (event->type) {
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ case RIGHTMOUSE:
+ text_cursor_set_exit(C, op);
+ return OPERATOR_FINISHED;
+ case TIMER:
+ case MOUSEMOVE:
+ text_cursor_set_apply(C, op, event);
+ break;
+ }
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static void text_set_selection_cancel(bContext *C, wmOperator *op)
{
- text_cursor_set_exit(C, op);
+ text_cursor_set_exit(C, op);
}
void TEXT_OT_selection_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Selection";
- ot->idname = "TEXT_OT_selection_set";
- ot->description = "Set cursor selection";
+ /* identifiers */
+ ot->name = "Set Selection";
+ ot->idname = "TEXT_OT_selection_set";
+ ot->description = "Set cursor selection";
- /* api callbacks */
- ot->invoke = text_set_selection_invoke;
- ot->modal = text_set_selection_modal;
- ot->cancel = text_set_selection_cancel;
- ot->poll = text_region_edit_poll;
+ /* api callbacks */
+ ot->invoke = text_set_selection_invoke;
+ ot->modal = text_set_selection_modal;
+ ot->cancel = text_set_selection_cancel;
+ ot->poll = text_region_edit_poll;
- /* properties */
- RNA_def_boolean(ot->srna, "select", 0, "Select", "Set selection end rather than cursor");
+ /* properties */
+ RNA_def_boolean(ot->srna, "select", 0, "Select", "Set selection end rather than cursor");
}
/******************* set cursor operator **********************/
static int text_cursor_set_exec(bContext *C, wmOperator *op)
{
- SpaceText *st = CTX_wm_space_text(C);
- ARegion *ar = CTX_wm_region(C);
- int x = RNA_int_get(op->ptr, "x");
- int y = RNA_int_get(op->ptr, "y");
+ SpaceText *st = CTX_wm_space_text(C);
+ ARegion *ar = 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, ar, x, y, 0);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
- return OPERATOR_PASS_THROUGH;
+ return OPERATOR_PASS_THROUGH;
}
static int text_cursor_set_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- SpaceText *st = CTX_wm_space_text(C);
+ SpaceText *st = CTX_wm_space_text(C);
- if (event->mval[0] >= st->txtbar.xmin)
- return OPERATOR_PASS_THROUGH;
+ if (event->mval[0] >= st->txtbar.xmin)
+ return OPERATOR_PASS_THROUGH;
- RNA_int_set(op->ptr, "x", event->mval[0]);
- RNA_int_set(op->ptr, "y", event->mval[1]);
+ RNA_int_set(op->ptr, "x", event->mval[0]);
+ RNA_int_set(op->ptr, "y", event->mval[1]);
- return text_cursor_set_exec(C, op);
+ return text_cursor_set_exec(C, op);
}
void TEXT_OT_cursor_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Cursor";
- ot->idname = "TEXT_OT_cursor_set";
- ot->description = "Set cursor position";
+ /* identifiers */
+ ot->name = "Set Cursor";
+ ot->idname = "TEXT_OT_cursor_set";
+ ot->description = "Set cursor position";
- /* api callbacks */
- ot->invoke = text_cursor_set_invoke;
- ot->exec = text_cursor_set_exec;
- ot->poll = text_region_edit_poll;
+ /* api callbacks */
+ ot->invoke = text_cursor_set_invoke;
+ ot->exec = text_cursor_set_exec;
+ ot->poll = text_region_edit_poll;
- /* properties */
- RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
+ /* properties */
+ RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
}
/******************* line number operator **********************/
static int text_line_number_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- SpaceText *st = CTX_wm_space_text(C);
- Text *text = CTX_data_edit_text(C);
- ARegion *ar = CTX_wm_region(C);
- const int *mval = event->mval;
- double time;
- static int jump_to = 0;
- static double last_jump = 0;
+ SpaceText *st = CTX_wm_space_text(C);
+ Text *text = CTX_data_edit_text(C);
+ ARegion *ar = CTX_wm_region(C);
+ const int *mval = event->mval;
+ double time;
+ static int jump_to = 0;
+ static double last_jump = 0;
- text_update_character_width(st);
+ text_update_character_width(st);
- if (!st->showlinenrs)
- return OPERATOR_PASS_THROUGH;
+ if (!st->showlinenrs)
+ return OPERATOR_PASS_THROUGH;
- if (!(mval[0] > 2 && mval[0] < (TXT_OFFSET + TEXTXLOC) && mval[1] > 2 && mval[1] < ar->winy - 2))
- return OPERATOR_PASS_THROUGH;
+ if (!(mval[0] > 2 && mval[0] < (TXT_OFFSET + TEXTXLOC) && mval[1] > 2 && mval[1] < ar->winy - 2))
+ return OPERATOR_PASS_THROUGH;
- if (!(event->ascii >= '0' && event->ascii <= '9'))
- return OPERATOR_PASS_THROUGH;
+ if (!(event->ascii >= '0' && event->ascii <= '9'))
+ return OPERATOR_PASS_THROUGH;
- time = PIL_check_seconds_timer();
- if (last_jump < time - 1)
- jump_to = 0;
+ time = PIL_check_seconds_timer();
+ if (last_jump < time - 1)
+ jump_to = 0;
- jump_to *= 10;
- jump_to += (int)(event->ascii - '0');
+ jump_to *= 10;
+ jump_to += (int)(event->ascii - '0');
- txt_move_toline(text, jump_to - 1, 0);
- last_jump = time;
+ txt_move_toline(text, jump_to - 1, 0);
+ last_jump = time;
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_line_number(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Line Number";
- ot->idname = "TEXT_OT_line_number";
- ot->description = "The current line number";
+ /* identifiers */
+ ot->name = "Line Number";
+ ot->idname = "TEXT_OT_line_number";
+ ot->description = "The current line number";
- /* api callbacks */
- ot->invoke = text_line_number_invoke;
- ot->poll = text_region_edit_poll;
+ /* api callbacks */
+ ot->invoke = text_line_number_invoke;
+ ot->poll = text_region_edit_poll;
}
/******************* insert operator **********************/
static int text_insert_exec(bContext *C, wmOperator *op)
{
- SpaceText *st = CTX_wm_space_text(C);
- Text *text = CTX_data_edit_text(C);
- char *str;
- bool done = false;
- size_t i = 0;
- unsigned int code;
+ SpaceText *st = CTX_wm_space_text(C);
+ Text *text = CTX_data_edit_text(C);
+ char *str;
+ bool done = false;
+ size_t i = 0;
+ unsigned int code;
- text_drawcache_tag_update(st, 0);
+ text_drawcache_tag_update(st, 0);
- str = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
+ str = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
- if (st && st->overwrite) {
- while (str[i]) {
- code = BLI_str_utf8_as_unicode_step(str, &i);
- done |= txt_replace_char(text, utxt, code);
- }
- }
- else {
- while (str[i]) {
- code = BLI_str_utf8_as_unicode_step(str, &i);
- done |= txt_add_char(text, utxt, code);
- }
- }
+ if (st && st->overwrite) {
+ while (str[i]) {
+ code = BLI_str_utf8_as_unicode_step(str, &i);
+ done |= txt_replace_char(text, utxt, code);
+ }
+ }
+ else {
+ while (str[i]) {
+ code = BLI_str_utf8_as_unicode_step(str, &i);
+ done |= txt_add_char(text, utxt, code);
+ }
+ }
- MEM_freeN(str);
+ MEM_freeN(str);
- if (!done)
- return OPERATOR_CANCELLED;
+ if (!done)
+ return OPERATOR_CANCELLED;
- text_update_line_edited(text->curl);
+ text_update_line_edited(text->curl);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int text_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- int ret;
-
- // if (!RNA_struct_property_is_set(op->ptr, "text")) { /* always set from keymap XXX */
- if (!RNA_string_length(op->ptr, "text")) {
- /* if alt/ctrl/super are pressed pass through except for utf8 character event
- * (when input method are used for utf8 inputs, the user may assign key event
- * including alt/ctrl/super like ctrl+m to commit utf8 string. in such case,
- * the modifiers in the utf8 character event make no sense.) */
- if ((event->ctrl || event->oskey) && !event->utf8_buf[0]) {
- return OPERATOR_PASS_THROUGH;
- }
- else {
- char str[BLI_UTF8_MAX + 1];
- size_t len;
-
- if (event->utf8_buf[0]) {
- len = BLI_str_utf8_size_safe(event->utf8_buf);
- memcpy(str, event->utf8_buf, len);
- }
- else {
- /* in theory, ghost can set value to extended ascii here */
- len = BLI_str_utf8_from_unicode(event->ascii, str);
- }
- str[len] = '\0';
- RNA_string_set(op->ptr, "text", str);
- }
- }
-
- ret = text_insert_exec(C, op);
-
- /* run the script while editing, evil but useful */
- if (ret == OPERATOR_FINISHED && CTX_wm_space_text(C)->live_edit)
- text_run_script(C, NULL);
-
- return ret;
+ int ret;
+
+ // if (!RNA_struct_property_is_set(op->ptr, "text")) { /* always set from keymap XXX */
+ if (!RNA_string_length(op->ptr, "text")) {
+ /* if alt/ctrl/super are pressed pass through except for utf8 character event
+ * (when input method are used for utf8 inputs, the user may assign key event
+ * including alt/ctrl/super like ctrl+m to commit utf8 string. in such case,
+ * the modifiers in the utf8 character event make no sense.) */
+ if ((event->ctrl || event->oskey) && !event->utf8_buf[0]) {
+ return OPERATOR_PASS_THROUGH;
+ }
+ else {
+ char str[BLI_UTF8_MAX + 1];
+ size_t len;
+
+ if (event->utf8_buf[0]) {
+ len = BLI_str_utf8_size_safe(event->utf8_buf);
+ memcpy(str, event->utf8_buf, len);
+ }
+ else {
+ /* in theory, ghost can set value to extended ascii here */
+ len = BLI_str_utf8_from_unicode(event->ascii, str);
+ }
+ str[len] = '\0';
+ RNA_string_set(op->ptr, "text", str);
+ }
+ }
+
+ ret = text_insert_exec(C, op);
+
+ /* run the script while editing, evil but useful */
+ if (ret == OPERATOR_FINISHED && CTX_wm_space_text(C)->live_edit)
+ text_run_script(C, NULL);
+
+ return ret;
}
void TEXT_OT_insert(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Insert";
- ot->idname = "TEXT_OT_insert";
- ot->description = "Insert text at cursor position";
+ /* identifiers */
+ ot->name = "Insert";
+ ot->idname = "TEXT_OT_insert";
+ ot->description = "Insert text at cursor position";
- /* api callbacks */
- ot->exec = text_insert_exec;
- ot->invoke = text_insert_invoke;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_insert_exec;
+ ot->invoke = text_insert_invoke;
+ ot->poll = text_edit_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- /* properties */
- prop = RNA_def_string(ot->srna, "text", NULL, 0, "Text", "Text to insert at the cursor position");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ prop = RNA_def_string(
+ ot->srna, "text", NULL, 0, "Text", "Text to insert at the cursor position");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/******************* find operator *********************/
/* mode */
-#define TEXT_FIND 0
-#define TEXT_REPLACE 1
+#define TEXT_FIND 0
+#define TEXT_REPLACE 1
static int text_find_and_replace(bContext *C, wmOperator *op, short mode)
{
- Main *bmain = CTX_data_main(C);
- SpaceText *st = CTX_wm_space_text(C);
- Text *text = st->text;
- int flags;
- int found = 0;
- char *tmp;
-
- if (!st->findstr[0])
- return OPERATOR_CANCELLED;
-
- flags = st->flags;
- if (flags & ST_FIND_ALL)
- flags &= ~ST_FIND_WRAP;
-
- /* Replace current */
- if (mode != TEXT_FIND && txt_has_sel(text)) {
- tmp = txt_sel_to_buf(text);
-
- if (flags & ST_MATCH_CASE) found = STREQ(st->findstr, tmp);
- else found = BLI_strcasecmp(st->findstr, tmp) == 0;
-
- if (found) {
- if (mode == TEXT_REPLACE) {
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- txt_insert_buf(text, utxt, st->replacestr);
- if (text->curl && text->curl->format) {
- MEM_freeN(text->curl->format);
- text->curl->format = NULL;
- }
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- text_drawcache_tag_update(CTX_wm_space_text(C), 1);
- }
- }
- MEM_freeN(tmp);
- tmp = NULL;
- }
-
- /* Find next */
- if (txt_find_string(text, st->findstr, flags & ST_FIND_WRAP, flags & ST_MATCH_CASE)) {
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
- }
- else if (flags & ST_FIND_ALL) {
- if (text->id.next)
- text = st->text = text->id.next;
- else
- text = st->text = bmain->texts.first;
- txt_move_toline(text, 0, 0);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
- }
- else {
- if (!found) BKE_reportf(op->reports, RPT_ERROR, "Text not found: %s", st->findstr);
- }
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ SpaceText *st = CTX_wm_space_text(C);
+ Text *text = st->text;
+ int flags;
+ int found = 0;
+ char *tmp;
+
+ if (!st->findstr[0])
+ return OPERATOR_CANCELLED;
+
+ flags = st->flags;
+ if (flags & ST_FIND_ALL)
+ flags &= ~ST_FIND_WRAP;
+
+ /* Replace current */
+ if (mode != TEXT_FIND && txt_has_sel(text)) {
+ tmp = txt_sel_to_buf(text);
+
+ if (flags & ST_MATCH_CASE)
+ found = STREQ(st->findstr, tmp);
+ else
+ found = BLI_strcasecmp(st->findstr, tmp) == 0;
+
+ if (found) {
+ if (mode == TEXT_REPLACE) {
+ TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ txt_insert_buf(text, utxt, st->replacestr);
+ if (text->curl && text->curl->format) {
+ MEM_freeN(text->curl->format);
+ text->curl->format = NULL;
+ }
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ text_drawcache_tag_update(CTX_wm_space_text(C), 1);
+ }
+ }
+ MEM_freeN(tmp);
+ tmp = NULL;
+ }
+
+ /* Find next */
+ if (txt_find_string(text, st->findstr, flags & ST_FIND_WRAP, flags & ST_MATCH_CASE)) {
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
+ }
+ else if (flags & ST_FIND_ALL) {
+ if (text->id.next)
+ text = st->text = text->id.next;
+ else
+ text = st->text = bmain->texts.first;
+ txt_move_toline(text, 0, 0);
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
+ }
+ else {
+ if (!found)
+ BKE_reportf(op->reports, RPT_ERROR, "Text not found: %s", st->findstr);
+ }
+
+ return OPERATOR_FINISHED;
}
static int text_find_exec(bContext *C, wmOperator *op)
{
- return text_find_and_replace(C, op, TEXT_FIND);
+ return text_find_and_replace(C, op, TEXT_FIND);
}
void TEXT_OT_find(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Find Next";
- ot->idname = "TEXT_OT_find";
- ot->description = "Find specified text";
+ /* identifiers */
+ ot->name = "Find Next";
+ ot->idname = "TEXT_OT_find";
+ ot->description = "Find specified text";
- /* api callbacks */
- ot->exec = text_find_exec;
- ot->poll = text_space_edit_poll;
+ /* api callbacks */
+ ot->exec = text_find_exec;
+ ot->poll = text_space_edit_poll;
}
/******************* replace operator *********************/
static int text_replace_exec(bContext *C, wmOperator *op)
{
- return text_find_and_replace(C, op, TEXT_REPLACE);
+ return text_find_and_replace(C, op, TEXT_REPLACE);
}
void TEXT_OT_replace(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Replace";
- ot->idname = "TEXT_OT_replace";
- ot->description = "Replace text with the specified text";
+ /* identifiers */
+ ot->name = "Replace";
+ ot->idname = "TEXT_OT_replace";
+ ot->description = "Replace text with the specified text";
- /* api callbacks */
- ot->exec = text_replace_exec;
- ot->poll = text_space_edit_poll;
+ /* api callbacks */
+ ot->exec = text_replace_exec;
+ ot->poll = text_space_edit_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/******************* find set selected *********************/
static int text_find_set_selected_exec(bContext *C, wmOperator *op)
{
- SpaceText *st = CTX_wm_space_text(C);
- Text *text = CTX_data_edit_text(C);
- char *tmp;
+ SpaceText *st = CTX_wm_space_text(C);
+ Text *text = CTX_data_edit_text(C);
+ char *tmp;
- tmp = txt_sel_to_buf(text);
- BLI_strncpy(st->findstr, tmp, ST_MAX_FIND_STR);
- MEM_freeN(tmp);
+ tmp = txt_sel_to_buf(text);
+ BLI_strncpy(st->findstr, tmp, ST_MAX_FIND_STR);
+ MEM_freeN(tmp);
- if (!st->findstr[0])
- return OPERATOR_FINISHED;
+ if (!st->findstr[0])
+ return OPERATOR_FINISHED;
- return text_find_and_replace(C, op, TEXT_FIND);
+ return text_find_and_replace(C, op, TEXT_FIND);
}
void TEXT_OT_find_set_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Find Set Selected";
- ot->idname = "TEXT_OT_find_set_selected";
- ot->description = "Find specified text and set as selected";
+ /* identifiers */
+ ot->name = "Find Set Selected";
+ ot->idname = "TEXT_OT_find_set_selected";
+ ot->description = "Find specified text and set as selected";
- /* api callbacks */
- ot->exec = text_find_set_selected_exec;
- ot->poll = text_space_edit_poll;
+ /* api callbacks */
+ ot->exec = text_find_set_selected_exec;
+ ot->poll = text_space_edit_poll;
}
/******************* replace set selected *********************/
static int text_replace_set_selected_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceText *st = CTX_wm_space_text(C);
- Text *text = CTX_data_edit_text(C);
- char *tmp;
+ SpaceText *st = CTX_wm_space_text(C);
+ Text *text = CTX_data_edit_text(C);
+ char *tmp;
- tmp = txt_sel_to_buf(text);
- BLI_strncpy(st->replacestr, tmp, ST_MAX_FIND_STR);
- MEM_freeN(tmp);
+ tmp = txt_sel_to_buf(text);
+ BLI_strncpy(st->replacestr, tmp, ST_MAX_FIND_STR);
+ MEM_freeN(tmp);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_replace_set_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Replace Set Selected";
- ot->idname = "TEXT_OT_replace_set_selected";
- ot->description = "Replace text with specified text and set as selected";
+ /* identifiers */
+ ot->name = "Replace Set Selected";
+ ot->idname = "TEXT_OT_replace_set_selected";
+ ot->description = "Replace text with specified text and set as selected";
- /* api callbacks */
- ot->exec = text_replace_set_selected_exec;
- ot->poll = text_space_edit_poll;
+ /* api callbacks */
+ ot->exec = text_replace_set_selected_exec;
+ ot->poll = text_space_edit_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
}
/****************** resolve conflict operator ******************/
enum { RESOLVE_IGNORE, RESOLVE_RELOAD, RESOLVE_SAVE, RESOLVE_MAKE_INTERNAL };
static const EnumPropertyItem resolution_items[] = {
- {RESOLVE_IGNORE, "IGNORE", 0, "Ignore", ""},
- {RESOLVE_RELOAD, "RELOAD", 0, "Reload", ""},
- {RESOLVE_SAVE, "SAVE", 0, "Save", ""},
- {RESOLVE_MAKE_INTERNAL, "MAKE_INTERNAL", 0, "Make Internal", ""},
- {0, NULL, 0, NULL, NULL},
+ {RESOLVE_IGNORE, "IGNORE", 0, "Ignore", ""},
+ {RESOLVE_RELOAD, "RELOAD", 0, "Reload", ""},
+ {RESOLVE_SAVE, "SAVE", 0, "Save", ""},
+ {RESOLVE_MAKE_INTERNAL, "MAKE_INTERNAL", 0, "Make Internal", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int text_resolve_conflict_exec(bContext *C, wmOperator *op)
{
- Text *text = CTX_data_edit_text(C);
- int resolution = RNA_enum_get(op->ptr, "resolution");
+ Text *text = CTX_data_edit_text(C);
+ int resolution = RNA_enum_get(op->ptr, "resolution");
- switch (resolution) {
- case RESOLVE_RELOAD:
- return text_reload_exec(C, op);
- case RESOLVE_SAVE:
- return text_save_exec(C, op);
- case RESOLVE_MAKE_INTERNAL:
- return text_make_internal_exec(C, op);
- case RESOLVE_IGNORE:
- BKE_text_file_modified_ignore(text);
- return OPERATOR_FINISHED;
- }
+ switch (resolution) {
+ case RESOLVE_RELOAD:
+ return text_reload_exec(C, op);
+ case RESOLVE_SAVE:
+ return text_save_exec(C, op);
+ case RESOLVE_MAKE_INTERNAL:
+ return text_make_internal_exec(C, op);
+ case RESOLVE_IGNORE:
+ BKE_text_file_modified_ignore(text);
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
static int text_resolve_conflict_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Text *text = CTX_data_edit_text(C);
- uiPopupMenu *pup;
- uiLayout *layout;
-
- switch (BKE_text_file_modified_check(text)) {
- case 1:
- if (text->flags & TXT_ISDIRTY) {
- /* modified locally and externally, ahhh. offer more possibilities. */
- pup = UI_popup_menu_begin(C, IFACE_("File Modified Outside and Inside Blender"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
- uiItemEnumO_ptr(layout, op->type, IFACE_("Reload from disk (ignore local changes)"),
- 0, "resolution", RESOLVE_RELOAD);
- uiItemEnumO_ptr(layout, op->type, IFACE_("Save to disk (ignore outside changes)"),
- 0, "resolution", RESOLVE_SAVE);
- uiItemEnumO_ptr(layout, op->type, IFACE_("Make text internal (separate copy)"),
- 0, "resolution", RESOLVE_MAKE_INTERNAL);
- UI_popup_menu_end(C, pup);
- }
- else {
- pup = UI_popup_menu_begin(C, IFACE_("File Modified Outside Blender"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
- uiItemEnumO_ptr(layout, op->type, IFACE_("Reload from disk"), 0, "resolution", RESOLVE_RELOAD);
- uiItemEnumO_ptr(layout, op->type, IFACE_("Make text internal (separate copy)"),
- 0, "resolution", RESOLVE_MAKE_INTERNAL);
- uiItemEnumO_ptr(layout, op->type, IFACE_("Ignore"), 0, "resolution", RESOLVE_IGNORE);
- UI_popup_menu_end(C, pup);
- }
- break;
- case 2:
- pup = UI_popup_menu_begin(C, IFACE_("File Deleted Outside Blender"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
- uiItemEnumO_ptr(layout, op->type, IFACE_("Make text internal"), 0, "resolution", RESOLVE_MAKE_INTERNAL);
- uiItemEnumO_ptr(layout, op->type, IFACE_("Recreate file"), 0, "resolution", RESOLVE_SAVE);
- UI_popup_menu_end(C, pup);
- break;
- }
-
- return OPERATOR_INTERFACE;
+ Text *text = CTX_data_edit_text(C);
+ uiPopupMenu *pup;
+ uiLayout *layout;
+
+ switch (BKE_text_file_modified_check(text)) {
+ case 1:
+ if (text->flags & TXT_ISDIRTY) {
+ /* modified locally and externally, ahhh. offer more possibilities. */
+ pup = UI_popup_menu_begin(
+ C, IFACE_("File Modified Outside and Inside Blender"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ uiItemEnumO_ptr(layout,
+ op->type,
+ IFACE_("Reload from disk (ignore local changes)"),
+ 0,
+ "resolution",
+ RESOLVE_RELOAD);
+ uiItemEnumO_ptr(layout,
+ op->type,
+ IFACE_("Save to disk (ignore outside changes)"),
+ 0,
+ "resolution",
+ RESOLVE_SAVE);
+ uiItemEnumO_ptr(layout,
+ op->type,
+ IFACE_("Make text internal (separate copy)"),
+ 0,
+ "resolution",
+ RESOLVE_MAKE_INTERNAL);
+ UI_popup_menu_end(C, pup);
+ }
+ else {
+ pup = UI_popup_menu_begin(C, IFACE_("File Modified Outside Blender"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ uiItemEnumO_ptr(
+ layout, op->type, IFACE_("Reload from disk"), 0, "resolution", RESOLVE_RELOAD);
+ uiItemEnumO_ptr(layout,
+ op->type,
+ IFACE_("Make text internal (separate copy)"),
+ 0,
+ "resolution",
+ RESOLVE_MAKE_INTERNAL);
+ uiItemEnumO_ptr(layout, op->type, IFACE_("Ignore"), 0, "resolution", RESOLVE_IGNORE);
+ UI_popup_menu_end(C, pup);
+ }
+ break;
+ case 2:
+ pup = UI_popup_menu_begin(C, IFACE_("File Deleted Outside Blender"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ uiItemEnumO_ptr(
+ layout, op->type, IFACE_("Make text internal"), 0, "resolution", RESOLVE_MAKE_INTERNAL);
+ uiItemEnumO_ptr(layout, op->type, IFACE_("Recreate file"), 0, "resolution", RESOLVE_SAVE);
+ UI_popup_menu_end(C, pup);
+ break;
+ }
+
+ return OPERATOR_INTERFACE;
}
void TEXT_OT_resolve_conflict(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Resolve Conflict";
- ot->idname = "TEXT_OT_resolve_conflict";
- ot->description = "When external text is out of sync, resolve the conflict";
+ /* identifiers */
+ ot->name = "Resolve Conflict";
+ ot->idname = "TEXT_OT_resolve_conflict";
+ ot->description = "When external text is out of sync, resolve the conflict";
- /* api callbacks */
- ot->exec = text_resolve_conflict_exec;
- ot->invoke = text_resolve_conflict_invoke;
- ot->poll = text_save_poll;
+ /* api callbacks */
+ ot->exec = text_resolve_conflict_exec;
+ ot->invoke = text_resolve_conflict_invoke;
+ ot->poll = text_save_poll;
- /* properties */
- RNA_def_enum(ot->srna, "resolution", resolution_items, RESOLVE_IGNORE, "Resolution", "How to solve conflict due to differences in internal and external text");
+ /* properties */
+ RNA_def_enum(ot->srna,
+ "resolution",
+ resolution_items,
+ RESOLVE_IGNORE,
+ "Resolution",
+ "How to solve conflict due to differences in internal and external text");
}
/********************** to 3d object operator *****************/
static int text_to_3d_object_exec(bContext *C, wmOperator *op)
{
- Text *text = CTX_data_edit_text(C);
- const bool split_lines = RNA_boolean_get(op->ptr, "split_lines");
+ Text *text = CTX_data_edit_text(C);
+ const bool split_lines = RNA_boolean_get(op->ptr, "split_lines");
- ED_text_to_object(C, text, split_lines);
+ ED_text_to_object(C, text, split_lines);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void TEXT_OT_to_3d_object(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "To 3D Object";
- ot->idname = "TEXT_OT_to_3d_object";
- ot->description = "Create 3D text object from active text data-block";
+ /* identifiers */
+ ot->name = "To 3D Object";
+ ot->idname = "TEXT_OT_to_3d_object";
+ ot->description = "Create 3D text object from active text data-block";
- /* api callbacks */
- ot->exec = text_to_3d_object_exec;
- ot->poll = text_edit_poll;
+ /* api callbacks */
+ ot->exec = text_to_3d_object_exec;
+ ot->poll = text_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "split_lines", 0, "Split Lines", "Create one object per line in the text");
+ /* properties */
+ RNA_def_boolean(
+ ot->srna, "split_lines", 0, "Split Lines", "Create one object per line in the text");
}
diff --git a/source/blender/editors/space_text/text_undo.c b/source/blender/editors/space_text/text_undo.c
index 76da0531225..7db97f15a68 100644
--- a/source/blender/editors/space_text/text_undo.c
+++ b/source/blender/editors/space_text/text_undo.c
@@ -60,160 +60,165 @@
* \{ */
typedef struct TextUndoStep {
- UndoStep step;
- UndoRefID_Text text_ref;
- TextUndoBuf data;
+ UndoStep step;
+ UndoRefID_Text text_ref;
+ TextUndoBuf data;
} TextUndoStep;
static bool text_undosys_poll(bContext *UNUSED(C))
{
- /* Only use when operators initialized. */
- UndoStack *ustack = ED_undo_stack_get();
- return (ustack->step_init && (ustack->step_init->type == BKE_UNDOSYS_TYPE_TEXT));
+ /* Only use when operators initialized. */
+ UndoStack *ustack = ED_undo_stack_get();
+ return (ustack->step_init && (ustack->step_init->type == BKE_UNDOSYS_TYPE_TEXT));
}
static void text_undosys_step_encode_init(struct bContext *C, UndoStep *us_p)
{
- TextUndoStep *us = (TextUndoStep *)us_p;
- BLI_assert(BLI_array_is_zeroed(&us->data, 1));
+ TextUndoStep *us = (TextUndoStep *)us_p;
+ BLI_assert(BLI_array_is_zeroed(&us->data, 1));
- UNUSED_VARS(C);
- /* XXX, use to set the undo type only. */
+ UNUSED_VARS(C);
+ /* XXX, use to set the undo type only. */
- us->data.buf = NULL;
- us->data.len = 0;
- us->data.pos = -1;
+ us->data.buf = NULL;
+ us->data.len = 0;
+ us->data.pos = -1;
}
-static bool text_undosys_step_encode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p)
+static bool text_undosys_step_encode(struct bContext *C,
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p)
{
- TextUndoStep *us = (TextUndoStep *)us_p;
+ TextUndoStep *us = (TextUndoStep *)us_p;
- Text *text = CTX_data_edit_text(C);
+ Text *text = CTX_data_edit_text(C);
- /* No undo data was generated. Hint, use global undo here. */
- if ((us->data.pos == -1) || (us->data.buf == NULL)) {
- return false;
- }
+ /* No undo data was generated. Hint, use global undo here. */
+ if ((us->data.pos == -1) || (us->data.buf == NULL)) {
+ return false;
+ }
- us_p->is_applied = true;
+ us_p->is_applied = true;
- us->text_ref.ptr = text;
+ us->text_ref.ptr = text;
- us->step.data_size = us->data.len;
+ us->step.data_size = us->data.len;
- return true;
+ return true;
}
-
static void text_undosys_step_decode_undo_impl(Text *text, TextUndoStep *us)
{
- BLI_assert(us->step.is_applied == true);
- TextUndoBuf data = us->data;
- while (data.pos > -1) {
- txt_do_undo(text, &data);
- }
- BLI_assert(data.pos == -1);
- us->step.is_applied = false;
+ BLI_assert(us->step.is_applied == true);
+ TextUndoBuf data = us->data;
+ while (data.pos > -1) {
+ txt_do_undo(text, &data);
+ }
+ BLI_assert(data.pos == -1);
+ us->step.is_applied = false;
}
static void text_undosys_step_decode_redo_impl(Text *text, TextUndoStep *us)
{
- BLI_assert(us->step.is_applied == false);
- TextUndoBuf data = us->data;
- data.pos = -1;
- while (data.pos < us->data.pos) {
- txt_do_redo(text, &data);
- }
- BLI_assert(data.pos == us->data.pos);
- us->step.is_applied = true;
+ BLI_assert(us->step.is_applied == false);
+ TextUndoBuf data = us->data;
+ data.pos = -1;
+ while (data.pos < us->data.pos) {
+ txt_do_redo(text, &data);
+ }
+ BLI_assert(data.pos == us->data.pos);
+ us->step.is_applied = true;
}
static void text_undosys_step_decode_undo(Text *text, TextUndoStep *us)
{
- TextUndoStep *us_iter = us;
- while (us_iter->step.next && (us_iter->step.next->type == us_iter->step.type)) {
- if (us_iter->step.next->is_applied == false) {
- break;
- }
- us_iter = (TextUndoStep *)us_iter->step.next;
- }
- while (us_iter != us) {
- text_undosys_step_decode_undo_impl(text, us_iter);
- us_iter = (TextUndoStep *)us_iter->step.prev;
- }
+ TextUndoStep *us_iter = us;
+ while (us_iter->step.next && (us_iter->step.next->type == us_iter->step.type)) {
+ if (us_iter->step.next->is_applied == false) {
+ break;
+ }
+ us_iter = (TextUndoStep *)us_iter->step.next;
+ }
+ while (us_iter != us) {
+ text_undosys_step_decode_undo_impl(text, us_iter);
+ us_iter = (TextUndoStep *)us_iter->step.prev;
+ }
}
static void text_undosys_step_decode_redo(Text *text, TextUndoStep *us)
{
- TextUndoStep *us_iter = us;
- while (us_iter->step.prev && (us_iter->step.prev->type == us_iter->step.type)) {
- if (us_iter->step.prev->is_applied == true) {
- break;
- }
- us_iter = (TextUndoStep *)us_iter->step.prev;
- }
- while (us_iter && (us_iter->step.is_applied == false)) {
- text_undosys_step_decode_redo_impl(text, us_iter);
- if (us_iter == us) {
- break;
- }
- us_iter = (TextUndoStep *)us_iter->step.next;
- }
+ TextUndoStep *us_iter = us;
+ while (us_iter->step.prev && (us_iter->step.prev->type == us_iter->step.type)) {
+ if (us_iter->step.prev->is_applied == true) {
+ break;
+ }
+ us_iter = (TextUndoStep *)us_iter->step.prev;
+ }
+ while (us_iter && (us_iter->step.is_applied == false)) {
+ text_undosys_step_decode_redo_impl(text, us_iter);
+ if (us_iter == us) {
+ break;
+ }
+ us_iter = (TextUndoStep *)us_iter->step.next;
+ }
}
-static void text_undosys_step_decode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p, int dir)
+static void text_undosys_step_decode(struct bContext *C,
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p,
+ int dir)
{
- TextUndoStep *us = (TextUndoStep *)us_p;
- Text *text = us->text_ref.ptr;
-
- if (dir < 0) {
- text_undosys_step_decode_undo(text, us);
- }
- else {
- text_undosys_step_decode_redo(text, us);
- }
-
- SpaceText *st = CTX_wm_space_text(C);
- if (st) {
- /* Not essential, always show text being undo where possible. */
- st->text = text;
- }
- text_update_edited(text);
- text_update_cursor_moved(C);
- text_drawcache_tag_update(st, 1);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ TextUndoStep *us = (TextUndoStep *)us_p;
+ Text *text = us->text_ref.ptr;
+
+ if (dir < 0) {
+ text_undosys_step_decode_undo(text, us);
+ }
+ else {
+ text_undosys_step_decode_redo(text, us);
+ }
+
+ SpaceText *st = CTX_wm_space_text(C);
+ if (st) {
+ /* Not essential, always show text being undo where possible. */
+ st->text = text;
+ }
+ text_update_edited(text);
+ text_update_cursor_moved(C);
+ text_drawcache_tag_update(st, 1);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
}
static void text_undosys_step_free(UndoStep *us_p)
{
- TextUndoStep *us = (TextUndoStep *)us_p;
- MEM_SAFE_FREE(us->data.buf);
+ TextUndoStep *us = (TextUndoStep *)us_p;
+ MEM_SAFE_FREE(us->data.buf);
}
-static void text_undosys_foreach_ID_ref(
- UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+static void text_undosys_foreach_ID_ref(UndoStep *us_p,
+ UndoTypeForEachIDRefFn foreach_ID_ref_fn,
+ void *user_data)
{
- TextUndoStep *us = (TextUndoStep *)us_p;
- foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->text_ref));
+ TextUndoStep *us = (TextUndoStep *)us_p;
+ foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->text_ref));
}
/* Export for ED_undo_sys. */
void ED_text_undosys_type(UndoType *ut)
{
- ut->name = "Text";
- ut->poll = text_undosys_poll;
- ut->step_encode_init = text_undosys_step_encode_init;
- ut->step_encode = text_undosys_step_encode;
- ut->step_decode = text_undosys_step_decode;
- ut->step_free = text_undosys_step_free;
+ ut->name = "Text";
+ ut->poll = text_undosys_poll;
+ ut->step_encode_init = text_undosys_step_encode_init;
+ ut->step_encode = text_undosys_step_encode;
+ ut->step_decode = text_undosys_step_decode;
+ ut->step_free = text_undosys_step_free;
- ut->step_foreach_ID_ref = text_undosys_foreach_ID_ref;
+ ut->step_foreach_ID_ref = text_undosys_foreach_ID_ref;
- ut->use_context = false;
+ ut->use_context = false;
- ut->step_size = sizeof(TextUndoStep);
+ ut->step_size = sizeof(TextUndoStep);
}
/** \} */
@@ -225,10 +230,10 @@ void ED_text_undosys_type(UndoType *ut)
/* Use operator system to finish the undo step. */
TextUndoBuf *ED_text_undo_push_init(bContext *C)
{
- UndoStack *ustack = ED_undo_stack_get();
- UndoStep *us_p = BKE_undosys_step_push_init_with_type(ustack, C, NULL, BKE_UNDOSYS_TYPE_TEXT);
- TextUndoStep *us = (TextUndoStep *)us_p;
- return &us->data;
+ UndoStack *ustack = ED_undo_stack_get();
+ UndoStep *us_p = BKE_undosys_step_push_init_with_type(ustack, C, NULL, BKE_UNDOSYS_TYPE_TEXT);
+ TextUndoStep *us = (TextUndoStep *)us_p;
+ return &us->data;
}
/** \} */
diff --git a/source/blender/editors/space_topbar/CMakeLists.txt b/source/blender/editors/space_topbar/CMakeLists.txt
index 15352044d4a..71e61a07ff7 100644
--- a/source/blender/editors/space_topbar/CMakeLists.txt
+++ b/source/blender/editors/space_topbar/CMakeLists.txt
@@ -16,25 +16,25 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blenloader
- ../../blentranslation
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blenloader
+ ../../blentranslation
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- space_topbar.c
+ space_topbar.c
)
set(LIB
diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c
index a65ced8987f..46a86bcbc86 100644
--- a/source/blender/editors/space_topbar/space_topbar.c
+++ b/source/blender/editors/space_topbar/space_topbar.c
@@ -21,7 +21,6 @@
* \ingroup sptopbar
*/
-
#include <string.h>
#include <stdio.h>
@@ -55,238 +54,237 @@
static SpaceLink *topbar_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
- 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;
-
- /* main regions */
- ar = MEM_callocN(sizeof(ARegion), "right aligned main region for topbar");
- BLI_addtail(&stopbar->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
- ar->alignment = RGN_ALIGN_RIGHT;
- ar = MEM_callocN(sizeof(ARegion), "main region of topbar");
- BLI_addtail(&stopbar->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
-
- return (SpaceLink *)stopbar;
+ ARegion *ar;
+ 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;
+
+ /* main regions */
+ ar = MEM_callocN(sizeof(ARegion), "right aligned main region for topbar");
+ BLI_addtail(&stopbar->regionbase, ar);
+ ar->regiontype = RGN_TYPE_WINDOW;
+ ar->alignment = RGN_ALIGN_RIGHT;
+ ar = MEM_callocN(sizeof(ARegion), "main region of topbar");
+ BLI_addtail(&stopbar->regionbase, ar);
+ ar->regiontype = RGN_TYPE_WINDOW;
+
+ return (SpaceLink *)stopbar;
}
/* not spacelink itself */
static void topbar_free(SpaceLink *UNUSED(sl))
{
-
}
-
/* spacetype; init callback */
static void topbar_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
{
-
}
static SpaceLink *topbar_duplicate(SpaceLink *sl)
{
- SpaceTopBar *stopbarn = MEM_dupallocN(sl);
+ SpaceTopBar *stopbarn = MEM_dupallocN(sl);
- /* clear or remove stuff from old */
+ /* clear or remove stuff from old */
- return (SpaceLink *)stopbarn;
+ return (SpaceLink *)stopbarn;
}
-
-
/* add handlers, stuff you only do once or on area/region changes */
static void topbar_main_region_init(wmWindowManager *wm, ARegion *region)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- /* force delayed UI_view2d_region_reinit call */
- if (ELEM(region->alignment, RGN_ALIGN_RIGHT)) {
- region->flag |= RGN_FLAG_DYNAMIC_SIZE;
- }
- UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_HEADER, region->winx, region->winy);
+ /* force delayed UI_view2d_region_reinit call */
+ if (ELEM(region->alignment, RGN_ALIGN_RIGHT)) {
+ region->flag |= RGN_FLAG_DYNAMIC_SIZE;
+ }
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_HEADER, region->winx, region->winy);
- keymap = WM_keymap_ensure(wm->defaultconf, "View2D Buttons List", 0, 0);
- WM_event_add_keymap_handler(&region->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "View2D Buttons List", 0, 0);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
static void topbar_operatortypes(void)
{
-
}
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)
{
- if ((ar->alignment & ~RGN_SPLIT_PREV) == RGN_ALIGN_RIGHT) {
- ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
- }
- ED_region_header_init(ar);
+ if ((ar->alignment & ~RGN_SPLIT_PREV) == RGN_ALIGN_RIGHT) {
+ ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
+ }
+ ED_region_header_init(ar);
}
-static void topbar_main_region_listener(wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void topbar_main_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_WM:
- if (wmn->data == ND_HISTORY) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SCENE:
- if (wmn->data == ND_MODE) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_VIEW3D) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_GPENCIL:
- if (wmn->data == ND_DATA) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_WM:
+ if (wmn->data == ND_HISTORY) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SCENE:
+ if (wmn->data == ND_MODE) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_VIEW3D) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_GPENCIL:
+ if (wmn->data == ND_DATA) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
}
-static void topbar_header_listener(wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void topbar_header_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_WM:
- if (wmn->data == ND_JOB) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_INFO) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SCREEN:
- if (wmn->data == ND_LAYER) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SCENE:
- if (wmn->data == ND_SCENEBROWSE) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_WM:
+ if (wmn->data == ND_JOB) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_INFO) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SCREEN:
+ if (wmn->data == ND_LAYER) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SCENE:
+ if (wmn->data == ND_SCENEBROWSE) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
}
-static void topbar_header_region_message_subscribe(
- const struct bContext *UNUSED(C),
- struct WorkSpace *workspace, struct Scene *UNUSED(scene),
- struct bScreen *UNUSED(screen), struct ScrArea *UNUSED(sa), struct ARegion *ar,
- struct wmMsgBus *mbus)
+static void topbar_header_region_message_subscribe(const struct bContext *UNUSED(C),
+ struct WorkSpace *workspace,
+ struct Scene *UNUSED(scene),
+ struct bScreen *UNUSED(screen),
+ struct ScrArea *UNUSED(sa),
+ struct ARegion *ar,
+ struct wmMsgBus *mbus)
{
- wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
- .notify = ED_region_do_msg_notify_tag_redraw,
- };
-
- WM_msg_subscribe_rna_prop(
- mbus, &workspace->id, workspace,
- WorkSpace, tools, &msg_sub_value_region_tag_redraw);
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ WM_msg_subscribe_rna_prop(
+ mbus, &workspace->id, workspace, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
}
static void recent_files_menu_draw(const bContext *UNUSED(C), Menu *menu)
{
- struct RecentFile *recent;
- uiLayout *layout = menu->layout;
- uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
- if (!BLI_listbase_is_empty(&G.recent_files)) {
- for (recent = G.recent_files.first; (recent); recent = recent->next) {
- const char *file = BLI_path_basename(recent->filepath);
- const int icon = BLO_has_bfile_extension(file) ? ICON_FILE_BLEND : ICON_FILE_BACKUP;
- uiItemStringO(layout, file, icon, "WM_OT_open_mainfile", "filepath", recent->filepath);
- }
- }
- else {
- uiItemL(layout, IFACE_("No Recent Files"), ICON_NONE);
- }
+ struct RecentFile *recent;
+ uiLayout *layout = menu->layout;
+ uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
+ if (!BLI_listbase_is_empty(&G.recent_files)) {
+ for (recent = G.recent_files.first; (recent); recent = recent->next) {
+ const char *file = BLI_path_basename(recent->filepath);
+ const int icon = BLO_has_bfile_extension(file) ? ICON_FILE_BLEND : ICON_FILE_BACKUP;
+ uiItemStringO(layout, file, icon, "WM_OT_open_mainfile", "filepath", recent->filepath);
+ }
+ }
+ else {
+ uiItemL(layout, IFACE_("No Recent Files"), ICON_NONE);
+ }
}
static void recent_files_menu_register(void)
{
- MenuType *mt;
-
- mt = MEM_callocN(sizeof(MenuType), "spacetype info menu recent files");
- strcpy(mt->idname, "TOPBAR_MT_file_open_recent");
- strcpy(mt->label, N_("Open Recent"));
- strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- mt->draw = recent_files_menu_draw;
- WM_menutype_add(mt);
+ MenuType *mt;
+
+ mt = MEM_callocN(sizeof(MenuType), "spacetype info menu recent files");
+ strcpy(mt->idname, "TOPBAR_MT_file_open_recent");
+ strcpy(mt->label, N_("Open Recent"));
+ strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ mt->draw = recent_files_menu_draw;
+ WM_menutype_add(mt);
}
-
/* only called once, from space/spacetypes.c */
void ED_spacetype_topbar(void)
{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype topbar");
- ARegionType *art;
-
- st->spaceid = SPACE_TOPBAR;
- strncpy(st->name, "Top Bar", BKE_ST_MAXNAME);
-
- st->new = topbar_new;
- st->free = topbar_free;
- st->init = topbar_init;
- st->duplicate = topbar_duplicate;
- st->operatortypes = topbar_operatortypes;
- st->keymap = topbar_keymap;
-
- /* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype topbar main region");
- art->regionid = RGN_TYPE_WINDOW;
- art->init = topbar_main_region_init;
- art->layout = ED_region_header_layout;
- art->draw = ED_region_header_draw;
- art->listener = topbar_main_region_listener;
- art->prefsizex = UI_UNIT_X * 5; /* Mainly to avoid glitches */
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype topbar header region");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = HEADERY;
- art->prefsizex = UI_UNIT_X * 5; /* Mainly to avoid glitches */
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
- art->listener = topbar_header_listener;
- art->message_subscribe = topbar_header_region_message_subscribe;
- art->init = topbar_header_region_init;
- art->layout = ED_region_header_layout;
- art->draw = ED_region_header_draw;
-
- BLI_addhead(&st->regiontypes, art);
-
- recent_files_menu_register();
-
- BKE_spacetype_register(st);
+ SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype topbar");
+ ARegionType *art;
+
+ st->spaceid = SPACE_TOPBAR;
+ strncpy(st->name, "Top Bar", BKE_ST_MAXNAME);
+
+ st->new = topbar_new;
+ st->free = topbar_free;
+ st->init = topbar_init;
+ st->duplicate = topbar_duplicate;
+ st->operatortypes = topbar_operatortypes;
+ st->keymap = topbar_keymap;
+
+ /* regions: main window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype topbar main region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init = topbar_main_region_init;
+ art->layout = ED_region_header_layout;
+ art->draw = ED_region_header_draw;
+ art->listener = topbar_main_region_listener;
+ art->prefsizex = UI_UNIT_X * 5; /* Mainly to avoid glitches */
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype topbar header region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = HEADERY;
+ art->prefsizex = UI_UNIT_X * 5; /* Mainly to avoid glitches */
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
+ art->listener = topbar_header_listener;
+ art->message_subscribe = topbar_header_region_message_subscribe;
+ art->init = topbar_header_region_init;
+ art->layout = ED_region_header_layout;
+ art->draw = ED_region_header_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ recent_files_menu_register();
+
+ BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_userpref/CMakeLists.txt b/source/blender/editors/space_userpref/CMakeLists.txt
index d26766358ca..61fe2bff63f 100644
--- a/source/blender/editors/space_userpref/CMakeLists.txt
+++ b/source/blender/editors/space_userpref/CMakeLists.txt
@@ -16,13 +16,13 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
)
set(INC_SYS
@@ -30,10 +30,10 @@ set(INC_SYS
)
set(SRC
- space_userpref.c
- userpref_ops.c
+ space_userpref.c
+ userpref_ops.c
- userpref_intern.h
+ userpref_intern.h
)
set(LIB
diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c
index 2857c5c8d81..2237e8b02bc 100644
--- a/source/blender/editors/space_userpref/space_userpref.c
+++ b/source/blender/editors/space_userpref/space_userpref.c
@@ -21,11 +21,9 @@
* \ingroup spuserpref
*/
-
#include <string.h>
#include <stdio.h>
-
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
@@ -42,95 +40,88 @@
#include "UI_interface.h"
-
-
/* ******************** default callbacks for userpref space ***************** */
static SpaceLink *userpref_new(const ScrArea *area, const Scene *UNUSED(scene))
{
- ARegion *ar;
- SpaceUserPref *spref;
+ ARegion *ar;
+ SpaceUserPref *spref;
- spref = MEM_callocN(sizeof(SpaceUserPref), "inituserpref");
- spref->spacetype = SPACE_USERPREF;
+ spref = MEM_callocN(sizeof(SpaceUserPref), "inituserpref");
+ spref->spacetype = SPACE_USERPREF;
- /* header */
- ar = MEM_callocN(sizeof(ARegion), "header for userpref");
+ /* header */
+ ar = MEM_callocN(sizeof(ARegion), "header for userpref");
- BLI_addtail(&spref->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- /* Ignore user preference "USER_HEADER_BOTTOM" here (always show bottom for new types). */
- ar->alignment = RGN_ALIGN_BOTTOM;
+ BLI_addtail(&spref->regionbase, ar);
+ ar->regiontype = RGN_TYPE_HEADER;
+ /* Ignore user preference "USER_HEADER_BOTTOM" here (always show bottom for new types). */
+ ar->alignment = RGN_ALIGN_BOTTOM;
- /* navigation region */
- ar = MEM_callocN(sizeof(ARegion), "navigation region for userpref");
+ /* navigation region */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_NAV_BAR;
+ ar->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;
- }
+ /* 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;
+ }
- /* execution region */
- ar = MEM_callocN(sizeof(ARegion), "execution region for userpref");
+ /* execution region */
+ ar = 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, ar);
+ ar->regiontype = RGN_TYPE_EXECUTE;
+ ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
+ ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
- /* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for userpref");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for userpref");
- BLI_addtail(&spref->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&spref->regionbase, ar);
+ ar->regiontype = RGN_TYPE_WINDOW;
- return (SpaceLink *)spref;
+ return (SpaceLink *)spref;
}
/* not spacelink itself */
static void userpref_free(SpaceLink *UNUSED(sl))
{
-// SpaceUserPref *spref = (SpaceUserPref *)sl;
-
+ // SpaceUserPref *spref = (SpaceUserPref *)sl;
}
-
/* spacetype; init callback */
static void userpref_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
{
-
}
static SpaceLink *userpref_duplicate(SpaceLink *sl)
{
- SpaceUserPref *sprefn = MEM_dupallocN(sl);
+ SpaceUserPref *sprefn = MEM_dupallocN(sl);
- /* clear or remove stuff from old */
+ /* clear or remove stuff from old */
- return (SpaceLink *)sprefn;
+ return (SpaceLink *)sprefn;
}
-
-
/* add handlers, stuff you only do once or on area/region changes */
static void userpref_main_region_init(wmWindowManager *wm, ARegion *ar)
{
- /* do not use here, the properties changed in userprefs do a system-wide refresh,
- * then scroller jumps back */
- /* ar->v2d.flag &= ~V2D_IS_INITIALISED; */
+ /* do not use here, the properties changed in userprefs do a system-wide refresh,
+ * then scroller jumps back */
+ /* ar->v2d.flag &= ~V2D_IS_INITIALISED; */
- ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
+ ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, ar);
}
static void userpref_main_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels_ex(C, ar, NULL, U.userpref, true);
+ ED_region_panels_ex(C, ar, NULL, U.userpref, true);
}
static void userpref_operatortypes(void)
@@ -139,133 +130,139 @@ static void userpref_operatortypes(void)
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)
{
- ED_region_header_init(ar);
+ ED_region_header_init(ar);
}
static void userpref_header_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_header(C, ar);
+ ED_region_header(C, ar);
}
/* add handlers, stuff you only do once or on area/region changes */
static void userpref_navigation_region_init(wmWindowManager *wm, ARegion *ar)
{
- ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
+ ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, ar);
}
static void userpref_navigation_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, ar);
}
/* add handlers, stuff you only do once or on area/region changes */
static void userpref_execute_region_init(wmWindowManager *wm, ARegion *ar)
{
- ED_region_panels_init(wm, ar);
- ar->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y;
+ ED_region_panels_init(wm, ar);
+ ar->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y;
}
-static void userpref_main_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *UNUSED(ar),
- wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene))
+static void userpref_main_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *UNUSED(ar),
+ wmNotifier *UNUSED(wmn),
+ const Scene *UNUSED(scene))
{
- /* context changes */
+ /* context changes */
}
-static void userpref_header_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *UNUSED(ar),
- wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene))
+static void userpref_header_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *UNUSED(ar),
+ wmNotifier *UNUSED(wmn),
+ const Scene *UNUSED(scene))
{
- /* context changes */
+ /* context changes */
#if 0
- switch (wmn->category) {
- default:
- break;
- }
+ switch (wmn->category) {
+ default:
+ break;
+ }
#endif
}
-static void userpref_navigation_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *UNUSED(ar),
- wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene))
+static void userpref_navigation_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *UNUSED(ar),
+ wmNotifier *UNUSED(wmn),
+ const Scene *UNUSED(scene))
{
- /* context changes */
+ /* context changes */
}
-static void userpref_execute_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *UNUSED(ar),
- wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene))
+static void userpref_execute_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *UNUSED(ar),
+ wmNotifier *UNUSED(wmn),
+ const Scene *UNUSED(scene))
{
- /* context changes */
+ /* context changes */
}
/* only called once, from space/spacetypes.c */
void ED_spacetype_userpref(void)
{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype userpref");
- ARegionType *art;
-
- st->spaceid = SPACE_USERPREF;
- strncpy(st->name, "Userpref", BKE_ST_MAXNAME);
-
- st->new = userpref_new;
- st->free = userpref_free;
- st->init = userpref_init;
- st->duplicate = userpref_duplicate;
- st->operatortypes = userpref_operatortypes;
- st->keymap = userpref_keymap;
-
- /* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype userpref region");
- art->regionid = RGN_TYPE_WINDOW;
- art->init = userpref_main_region_init;
- art->draw = userpref_main_region_draw;
- art->listener = userpref_main_region_listener;
- art->keymapflag = ED_KEYMAP_UI;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype userpref region");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
- art->listener = userpref_header_listener;
- art->init = userpref_header_region_init;
- art->draw = userpref_header_region_draw;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: navigation window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype userpref region");
- art->regionid = RGN_TYPE_NAV_BAR;
- art->prefsizex = UI_NAVIGATION_REGION_WIDTH;
- art->init = userpref_navigation_region_init;
- art->draw = userpref_navigation_region_draw;
- art->listener = userpref_navigation_region_listener;
- art->keymapflag = ED_KEYMAP_UI;
-
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: execution window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype userpref region");
- art->regionid = RGN_TYPE_EXECUTE;
- art->init = userpref_execute_region_init;
- art->layout = ED_region_panels_layout;
- art->draw = ED_region_panels_draw;
- art->listener = userpref_execute_region_listener;
- art->keymapflag = ED_KEYMAP_UI;
-
- BLI_addhead(&st->regiontypes, art);
-
-
- BKE_spacetype_register(st);
+ SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype userpref");
+ ARegionType *art;
+
+ st->spaceid = SPACE_USERPREF;
+ strncpy(st->name, "Userpref", BKE_ST_MAXNAME);
+
+ st->new = userpref_new;
+ st->free = userpref_free;
+ st->init = userpref_init;
+ st->duplicate = userpref_duplicate;
+ st->operatortypes = userpref_operatortypes;
+ st->keymap = userpref_keymap;
+
+ /* regions: main window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype userpref region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init = userpref_main_region_init;
+ art->draw = userpref_main_region_draw;
+ art->listener = userpref_main_region_listener;
+ art->keymapflag = ED_KEYMAP_UI;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype userpref region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = HEADERY;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
+ art->listener = userpref_header_listener;
+ art->init = userpref_header_region_init;
+ art->draw = userpref_header_region_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: navigation window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype userpref region");
+ art->regionid = RGN_TYPE_NAV_BAR;
+ art->prefsizex = UI_NAVIGATION_REGION_WIDTH;
+ art->init = userpref_navigation_region_init;
+ art->draw = userpref_navigation_region_draw;
+ art->listener = userpref_navigation_region_listener;
+ art->keymapflag = ED_KEYMAP_UI;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: execution window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype userpref region");
+ art->regionid = RGN_TYPE_EXECUTE;
+ art->init = userpref_execute_region_init;
+ art->layout = ED_region_panels_layout;
+ art->draw = ED_region_panels_draw;
+ art->listener = userpref_execute_region_listener;
+ art->keymapflag = ED_KEYMAP_UI;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c
index f6aaf01747c..a67e6c27acb 100644
--- a/source/blender/editors/space_userpref/userpref_ops.c
+++ b/source/blender/editors/space_userpref/userpref_ops.c
@@ -45,30 +45,30 @@
static int reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op))
{
- UI_theme_init_default();
- UI_style_init_default();
- WM_event_add_notifier(C, NC_WINDOW, NULL);
+ UI_theme_init_default();
+ UI_style_init_default();
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void PREFERENCES_OT_reset_default_theme(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reset to Default Theme";
- ot->idname = "PREFERENCES_OT_reset_default_theme";
- ot->description = "Reset to the default theme colors";
+ /* identifiers */
+ ot->name = "Reset to Default Theme";
+ ot->idname = "PREFERENCES_OT_reset_default_theme";
+ ot->description = "Reset to the default theme colors";
- /* callbacks */
- ot->exec = reset_default_theme_exec;
+ /* callbacks */
+ ot->exec = reset_default_theme_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
}
/** \} */
void ED_operatortypes_userpref(void)
{
- WM_operatortype_append(PREFERENCES_OT_reset_default_theme);
+ WM_operatortype_append(PREFERENCES_OT_reset_default_theme);
}
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index 837671d6f94..279c6913064 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -16,84 +16,84 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenfont
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../bmesh
- ../../draw
- ../../gpu
- ../../imbuf
- ../../makesdna
- ../../makesrna
- ../../render/extern/include
- ../../windowmanager
- ../../depsgraph
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
- ../../../../intern/smoke/extern
+ ../include
+ ../../blenfont
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../bmesh
+ ../../draw
+ ../../gpu
+ ../../imbuf
+ ../../makesdna
+ ../../makesrna
+ ../../render/extern/include
+ ../../windowmanager
+ ../../depsgraph
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
+ ../../../../intern/smoke/extern
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- drawobject.c
- space_view3d.c
- view3d_buttons.c
- view3d_camera_control.c
- view3d_draw.c
- view3d_draw_legacy.c
- view3d_edit.c
- view3d_fly.c
- view3d_gizmo_armature.c
- view3d_gizmo_camera.c
- view3d_gizmo_empty.c
- view3d_gizmo_forcefield.c
- view3d_gizmo_light.c
- view3d_gizmo_navigate.c
- view3d_gizmo_navigate_type.c
- view3d_gizmo_preselect.c
- view3d_gizmo_preselect_type.c
- view3d_gizmo_ruler.c
- view3d_header.c
- view3d_iterators.c
- view3d_ops.c
- view3d_project.c
- view3d_select.c
- view3d_snap.c
- view3d_toolbar.c
- view3d_utils.c
- view3d_view.c
- view3d_walk.c
+ drawobject.c
+ space_view3d.c
+ view3d_buttons.c
+ view3d_camera_control.c
+ view3d_draw.c
+ view3d_draw_legacy.c
+ view3d_edit.c
+ view3d_fly.c
+ view3d_gizmo_armature.c
+ view3d_gizmo_camera.c
+ view3d_gizmo_empty.c
+ view3d_gizmo_forcefield.c
+ view3d_gizmo_light.c
+ view3d_gizmo_navigate.c
+ view3d_gizmo_navigate_type.c
+ view3d_gizmo_preselect.c
+ view3d_gizmo_preselect_type.c
+ view3d_gizmo_ruler.c
+ view3d_header.c
+ view3d_iterators.c
+ view3d_ops.c
+ view3d_project.c
+ view3d_select.c
+ view3d_snap.c
+ view3d_toolbar.c
+ view3d_utils.c
+ view3d_view.c
+ view3d_walk.c
- view3d_intern.h
+ view3d_intern.h
)
set(LIB
- bf_editor_lattice
- bf_editor_mesh
+ bf_editor_lattice
+ bf_editor_mesh
)
if(WITH_PYTHON)
- blender_include_dirs(../../python)
- add_definitions(-DWITH_PYTHON)
+ blender_include_dirs(../../python)
+ add_definitions(-DWITH_PYTHON)
endif()
add_definitions(${GL_DEFINITIONS})
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
if(WITH_FREESTYLE)
- add_definitions(-DWITH_FREESTYLE)
+ add_definitions(-DWITH_FREESTYLE)
endif()
if(WITH_MOD_SMOKE)
- add_definitions(-DWITH_SMOKE)
+ add_definitions(-DWITH_SMOKE)
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 d4745247ae3..c304642c4c3 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -49,34 +49,34 @@
#include "DRW_engine.h"
-#include "view3d_intern.h" /* bad level include */
+#include "view3d_intern.h" /* bad level include */
-#include "../../draw/intern/draw_cache_impl.h" /* bad level include (temporary) */
+#include "../../draw/intern/draw_cache_impl.h" /* bad level include (temporary) */
int view3d_effective_drawtype(const struct View3D *v3d)
{
- if (v3d->shading.type == OB_RENDER) {
- return v3d->shading.prev_type;
- }
- return v3d->shading.type;
+ if (v3d->shading.type == OB_RENDER) {
+ return v3d->shading.prev_type;
+ }
+ return v3d->shading.type;
}
static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
{
- if ((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0) {
- return false;
- }
+ if ((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0) {
+ return false;
+ }
- if (G.f & G_FLAG_BACKBUFSEL) {
- return false;
- }
+ if (G.f & G_FLAG_BACKBUFSEL) {
+ return false;
+ }
- /* if its drawing textures with zbuf sel, then don't draw dots */
- if (dt == OB_TEXTURE && vd->shading.type == OB_TEXTURE) {
- return false;
- }
+ /* if its drawing textures with zbuf sel, then don't draw dots */
+ if (dt == OB_TEXTURE && vd->shading.type == OB_TEXTURE) {
+ return false;
+ }
- return true;
+ return true;
}
/* OpenGL Circle Drawing - Tables for Optimized Drawing Speed */
@@ -84,102 +84,51 @@ static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
#define CIRCLE_RESOL 32
static const float sinval[CIRCLE_RESOL] = {
- 0.00000000,
- 0.20129852,
- 0.39435585,
- 0.57126821,
- 0.72479278,
- 0.84864425,
- 0.93775213,
- 0.98846832,
- 0.99871650,
- 0.96807711,
- 0.89780453,
- 0.79077573,
- 0.65137248,
- 0.48530196,
- 0.29936312,
- 0.10116832,
- -0.10116832,
- -0.29936312,
- -0.48530196,
- -0.65137248,
- -0.79077573,
- -0.89780453,
- -0.96807711,
- -0.99871650,
- -0.98846832,
- -0.93775213,
- -0.84864425,
- -0.72479278,
- -0.57126821,
- -0.39435585,
- -0.20129852,
- 0.00000000,
+ 0.00000000, 0.20129852, 0.39435585, 0.57126821, 0.72479278, 0.84864425, 0.93775213,
+ 0.98846832, 0.99871650, 0.96807711, 0.89780453, 0.79077573, 0.65137248, 0.48530196,
+ 0.29936312, 0.10116832, -0.10116832, -0.29936312, -0.48530196, -0.65137248, -0.79077573,
+ -0.89780453, -0.96807711, -0.99871650, -0.98846832, -0.93775213, -0.84864425, -0.72479278,
+ -0.57126821, -0.39435585, -0.20129852, 0.00000000,
};
/* 32 values of cos function (still same result!) */
static const float cosval[CIRCLE_RESOL] = {
- 1.00000000,
- 0.97952994,
- 0.91895781,
- 0.82076344,
- 0.68896691,
- 0.52896401,
- 0.34730525,
- 0.15142777,
- -0.05064916,
- -0.25065253,
- -0.44039415,
- -0.61210598,
- -0.75875812,
- -0.87434661,
- -0.95413925,
- -0.99486932,
- -0.99486932,
- -0.95413925,
- -0.87434661,
- -0.75875812,
- -0.61210598,
- -0.44039415,
- -0.25065253,
- -0.05064916,
- 0.15142777,
- 0.34730525,
- 0.52896401,
- 0.68896691,
- 0.82076344,
- 0.91895781,
- 0.97952994,
- 1.00000000,
+ 1.00000000, 0.97952994, 0.91895781, 0.82076344, 0.68896691, 0.52896401, 0.34730525,
+ 0.15142777, -0.05064916, -0.25065253, -0.44039415, -0.61210598, -0.75875812, -0.87434661,
+ -0.95413925, -0.99486932, -0.99486932, -0.95413925, -0.87434661, -0.75875812, -0.61210598,
+ -0.44039415, -0.25065253, -0.05064916, 0.15142777, 0.34730525, 0.52896401, 0.68896691,
+ 0.82076344, 0.91895781, 0.97952994, 1.00000000,
};
-static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, const float tmat[4][4])
+static void circball_array_fill(float verts[CIRCLE_RESOL][3],
+ const float cent[3],
+ float rad,
+ const float tmat[4][4])
{
- float vx[3], vy[3];
- float *viter = (float *)verts;
+ float vx[3], vy[3];
+ float *viter = (float *)verts;
- mul_v3_v3fl(vx, tmat[0], rad);
- mul_v3_v3fl(vy, tmat[1], rad);
+ mul_v3_v3fl(vx, tmat[0], rad);
+ mul_v3_v3fl(vy, tmat[1], rad);
- for (uint a = 0; a < CIRCLE_RESOL; a++, viter += 3) {
- viter[0] = cent[0] + sinval[a] * vx[0] + cosval[a] * vy[0];
- viter[1] = cent[1] + sinval[a] * vx[1] + cosval[a] * vy[1];
- viter[2] = cent[2] + sinval[a] * vx[2] + cosval[a] * vy[2];
- }
+ for (uint a = 0; a < CIRCLE_RESOL; a++, viter += 3) {
+ viter[0] = cent[0] + sinval[a] * vx[0] + cosval[a] * vy[0];
+ viter[1] = cent[1] + sinval[a] * vx[1] + cosval[a] * vy[1];
+ viter[2] = cent[2] + sinval[a] * vx[2] + cosval[a] * vy[2];
+ }
}
void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos)
{
- float verts[CIRCLE_RESOL][3];
+ float verts[CIRCLE_RESOL][3];
- circball_array_fill(verts, cent, rad, tmat);
+ circball_array_fill(verts, cent, rad, tmat);
- immBegin(GPU_PRIM_LINE_LOOP, CIRCLE_RESOL);
- for (int i = 0; i < CIRCLE_RESOL; ++i) {
- immVertex3fv(pos, verts[i]);
- }
- immEnd();
+ immBegin(GPU_PRIM_LINE_LOOP, CIRCLE_RESOL);
+ for (int i = 0; i < CIRCLE_RESOL; ++i) {
+ immVertex3fv(pos, verts[i]);
+ }
+ immEnd();
}
#ifdef VIEW3D_CAMERA_BORDER_HACK
@@ -192,344 +141,359 @@ bool view3d_camera_border_hack_test = false;
/** See #DRW_shgroup_world_clip_planes_from_rv3d, same function for draw manager. */
static void bbs_world_clip_planes_from_rv3d(GPUBatch *batch, const float world_clip_planes[6][4])
{
- GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]);
+ GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]);
}
static void bbs_mesh_verts(GPUBatch *batch, int offset, const float world_clip_planes[6][4])
{
- GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE));
-
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", offset);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
+ GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE));
+
+ const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
+ GPU_SHADER_CFG_DEFAULT;
+ GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
+ GPU_batch_uniform_1ui(batch, "offset", offset);
+ if (world_clip_planes != NULL) {
+ bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
+ }
+ GPU_batch_draw(batch);
}
static void bbs_mesh_wire(GPUBatch *batch, int offset, const float world_clip_planes[6][4])
{
- GPU_line_width(1.0f);
- glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
-
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", offset);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
-
- glProvokingVertex(GL_LAST_VERTEX_CONVENTION);
+ GPU_line_width(1.0f);
+ glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
+
+ const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
+ GPU_SHADER_CFG_DEFAULT;
+ GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
+ GPU_batch_uniform_1ui(batch, "offset", offset);
+ if (world_clip_planes != NULL) {
+ bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
+ }
+ GPU_batch_draw(batch);
+
+ glProvokingVertex(GL_LAST_VERTEX_CONVENTION);
}
/* two options, facecolors or black */
-static void bbs_mesh_face(GPUBatch *batch, const bool use_select, const float world_clip_planes[6][4])
+static void bbs_mesh_face(GPUBatch *batch,
+ const bool use_select,
+ const float world_clip_planes[6][4])
{
- if (use_select) {
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", 1);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
- }
- else {
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_UNIFORM_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "id", 0);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
- }
+ if (use_select) {
+ const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
+ GPU_SHADER_CFG_DEFAULT;
+ GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
+ GPU_batch_uniform_1ui(batch, "offset", 1);
+ if (world_clip_planes != NULL) {
+ bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
+ }
+ GPU_batch_draw(batch);
+ }
+ else {
+ const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
+ GPU_SHADER_CFG_DEFAULT;
+ GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_UNIFORM_SELECT_ID, sh_cfg);
+ GPU_batch_uniform_1ui(batch, "id", 0);
+ if (world_clip_planes != NULL) {
+ bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
+ }
+ GPU_batch_draw(batch);
+ }
}
static void bbs_mesh_face_dot(GPUBatch *batch, const float world_clip_planes[6][4])
{
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", 1);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
+ const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
+ GPU_SHADER_CFG_DEFAULT;
+ GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
+ GPU_batch_uniform_1ui(batch, "offset", 1);
+ if (world_clip_planes != NULL) {
+ bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
+ }
+ GPU_batch_draw(batch);
}
-static void bbs_mesh_solid_verts(
- Depsgraph *UNUSED(depsgraph), Scene *UNUSED(scene), Object *ob, const float world_clip_planes[6][4])
+static void bbs_mesh_solid_verts(Depsgraph *UNUSED(depsgraph),
+ Scene *UNUSED(scene),
+ Object *ob,
+ const float world_clip_planes[6][4])
{
- Mesh *me = ob->data;
+ Mesh *me = ob->data;
- GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
- GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me);
- DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true);
+ GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
+ GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me);
+ DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true);
- /* Only draw faces to mask out verts, we don't want their selection ID's. */
- bbs_mesh_face(geom_faces, false, world_clip_planes);
- bbs_mesh_verts(geom_verts, 1, world_clip_planes);
+ /* Only draw faces to mask out verts, we don't want their selection ID's. */
+ bbs_mesh_face(geom_faces, false, world_clip_planes);
+ bbs_mesh_verts(geom_verts, 1, world_clip_planes);
- bm_vertoffs = me->totvert + 1;
+ bm_vertoffs = me->totvert + 1;
}
-static void bbs_mesh_solid_faces(Scene *UNUSED(scene), Object *ob, const float world_clip_planes[6][4])
+static void bbs_mesh_solid_faces(Scene *UNUSED(scene),
+ Object *ob,
+ const float world_clip_planes[6][4])
{
- Mesh *me = ob->data;
- Mesh *me_orig = DEG_get_original_object(ob)->data;
+ Mesh *me = ob->data;
+ Mesh *me_orig = DEG_get_original_object(ob)->data;
- const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL);
- GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
- DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, use_hide);
+ const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL);
+ GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
+ DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, use_hide);
- bbs_mesh_face(geom_faces, true, world_clip_planes);
+ bbs_mesh_face(geom_faces, true, world_clip_planes);
}
-void draw_object_select_id(
- Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob,
- short select_mode)
+void draw_object_select_id(Depsgraph *depsgraph,
+ Scene *scene,
+ View3D *v3d,
+ RegionView3D *rv3d,
+ Object *ob,
+ short select_mode)
{
- ToolSettings *ts = scene->toolsettings;
- if (select_mode == -1) {
- select_mode = ts->selectmode;
- }
-
- GPU_matrix_mul(ob->obmat);
- GPU_depth_test(true);
-
- const float (*world_clip_planes)[4] = NULL;
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_local(rv3d, ob->obmat);
- world_clip_planes = rv3d->clip_local;
- }
-
- switch (ob->type) {
- case OB_MESH:
- if (ob->mode & OB_MODE_EDIT) {
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- const bool draw_facedot = check_ob_drawface_dot(scene, v3d, ob->dt);
- const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0;
-
- BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
-
- GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots;
- geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
- if (select_mode & SCE_SELECT_EDGE) {
- geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me);
- }
- if (select_mode & SCE_SELECT_VERTEX) {
- geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me);
- }
- if (draw_facedot) {
- geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me);
- }
- DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true);
-
- bbs_mesh_face(geom_faces, use_faceselect, world_clip_planes);
-
- if (use_faceselect && draw_facedot) {
- bbs_mesh_face_dot(geom_facedots, world_clip_planes);
- }
-
- if (select_mode & SCE_SELECT_FACE) {
- bm_solidoffs = 1 + em->bm->totface;
- }
- else {
- bm_solidoffs = 1;
- }
-
- ED_view3d_polygon_offset(rv3d, 1.0);
-
- /* we draw edges if edge select mode */
- if (select_mode & SCE_SELECT_EDGE) {
- bbs_mesh_wire(geom_edges, bm_solidoffs, world_clip_planes);
- bm_wireoffs = bm_solidoffs + em->bm->totedge;
- }
- else {
- /* `bm_vertoffs` is calculated from `bm_wireoffs`. (otherwise see T53512) */
- bm_wireoffs = bm_solidoffs;
- }
-
- ED_view3d_polygon_offset(rv3d, 1.1);
-
- /* we draw verts if vert select mode. */
- if (select_mode & SCE_SELECT_VERTEX) {
- bbs_mesh_verts(geom_verts, bm_wireoffs, world_clip_planes);
- bm_vertoffs = bm_wireoffs + em->bm->totvert;
- }
- else {
- bm_vertoffs = bm_wireoffs;
- }
-
- ED_view3d_polygon_offset(rv3d, 0.0);
- }
- else {
- Mesh *me = DEG_get_original_object(ob)->data;
- if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) &&
- /* currently vertex select supports weight paint and vertex paint*/
- ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT)))
- {
- bbs_mesh_solid_verts(depsgraph, scene, ob, world_clip_planes);
- }
- else {
- bbs_mesh_solid_faces(scene, ob, world_clip_planes);
- }
- }
- break;
- case OB_CURVE:
- case OB_SURF:
- break;
- }
-
- GPU_matrix_set(rv3d->viewmat);
+ ToolSettings *ts = scene->toolsettings;
+ if (select_mode == -1) {
+ select_mode = ts->selectmode;
+ }
+
+ GPU_matrix_mul(ob->obmat);
+ GPU_depth_test(true);
+
+ const float(*world_clip_planes)[4] = NULL;
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ ED_view3d_clipping_local(rv3d, ob->obmat);
+ world_clip_planes = rv3d->clip_local;
+ }
+
+ switch (ob->type) {
+ case OB_MESH:
+ if (ob->mode & OB_MODE_EDIT) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ const bool draw_facedot = check_ob_drawface_dot(scene, v3d, ob->dt);
+ const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0;
+
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
+
+ GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots;
+ geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
+ if (select_mode & SCE_SELECT_EDGE) {
+ geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me);
+ }
+ if (select_mode & SCE_SELECT_VERTEX) {
+ geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me);
+ }
+ if (draw_facedot) {
+ geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me);
+ }
+ DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true);
+
+ bbs_mesh_face(geom_faces, use_faceselect, world_clip_planes);
+
+ if (use_faceselect && draw_facedot) {
+ bbs_mesh_face_dot(geom_facedots, world_clip_planes);
+ }
+
+ if (select_mode & SCE_SELECT_FACE) {
+ bm_solidoffs = 1 + em->bm->totface;
+ }
+ else {
+ bm_solidoffs = 1;
+ }
+
+ ED_view3d_polygon_offset(rv3d, 1.0);
+
+ /* we draw edges if edge select mode */
+ if (select_mode & SCE_SELECT_EDGE) {
+ bbs_mesh_wire(geom_edges, bm_solidoffs, world_clip_planes);
+ bm_wireoffs = bm_solidoffs + em->bm->totedge;
+ }
+ else {
+ /* `bm_vertoffs` is calculated from `bm_wireoffs`. (otherwise see T53512) */
+ bm_wireoffs = bm_solidoffs;
+ }
+
+ ED_view3d_polygon_offset(rv3d, 1.1);
+
+ /* we draw verts if vert select mode. */
+ if (select_mode & SCE_SELECT_VERTEX) {
+ bbs_mesh_verts(geom_verts, bm_wireoffs, world_clip_planes);
+ bm_vertoffs = bm_wireoffs + em->bm->totvert;
+ }
+ else {
+ bm_vertoffs = bm_wireoffs;
+ }
+
+ ED_view3d_polygon_offset(rv3d, 0.0);
+ }
+ else {
+ Mesh *me = DEG_get_original_object(ob)->data;
+ if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) &&
+ /* currently vertex select supports weight paint and vertex paint*/
+ ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) {
+ bbs_mesh_solid_verts(depsgraph, scene, ob, world_clip_planes);
+ }
+ else {
+ bbs_mesh_solid_faces(scene, ob, world_clip_planes);
+ }
+ }
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ break;
+ }
+
+ GPU_matrix_set(rv3d->viewmat);
}
void draw_object_depth(RegionView3D *rv3d, Object *ob)
{
- GPU_matrix_mul(ob->obmat);
- GPU_depth_test(true);
-
- const float (*world_clip_planes)[4] = NULL;
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_local(rv3d, ob->obmat);
- world_clip_planes = rv3d->clip_local;
- }
-
- switch (ob->type) {
- case OB_MESH:
- {
- GPUBatch *batch;
-
- Mesh *me = ob->data;
-
- if (ob->mode & OB_MODE_EDIT) {
- batch = DRW_mesh_batch_cache_get_edit_triangles(me);
- }
- else {
- batch = DRW_mesh_batch_cache_get_surface(me);
- }
-
- DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true);
-
- DRW_opengl_context_enable();
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_DEPTH_ONLY, sh_cfg);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
-
- GPU_batch_draw(batch);
- DRW_opengl_context_disable();
- }
- break;
- case OB_CURVE:
- case OB_SURF:
- break;
- }
-
- GPU_matrix_set(rv3d->viewmat);
+ GPU_matrix_mul(ob->obmat);
+ GPU_depth_test(true);
+
+ const float(*world_clip_planes)[4] = NULL;
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ ED_view3d_clipping_local(rv3d, ob->obmat);
+ world_clip_planes = rv3d->clip_local;
+ }
+
+ switch (ob->type) {
+ case OB_MESH: {
+ GPUBatch *batch;
+
+ Mesh *me = ob->data;
+
+ if (ob->mode & OB_MODE_EDIT) {
+ batch = DRW_mesh_batch_cache_get_edit_triangles(me);
+ }
+ else {
+ batch = DRW_mesh_batch_cache_get_surface(me);
+ }
+
+ DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true);
+
+ DRW_opengl_context_enable();
+ const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
+ GPU_SHADER_CFG_DEFAULT;
+ GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_DEPTH_ONLY, sh_cfg);
+ if (world_clip_planes != NULL) {
+ bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
+ }
+
+ GPU_batch_draw(batch);
+ DRW_opengl_context_disable();
+ } break;
+ case OB_CURVE:
+ case OB_SURF:
+ break;
+ }
+
+ GPU_matrix_set(rv3d->viewmat);
}
-
-void ED_draw_object_facemap(
- Depsgraph *depsgraph, Object *ob, const float col[4], const int facemap)
+void ED_draw_object_facemap(Depsgraph *depsgraph,
+ Object *ob,
+ const float col[4],
+ const int facemap)
{
- /* happens on undo */
- if (ob->type != OB_MESH || !ob->data) {
- return;
- }
-
- 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;
- }
- }
-
- glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
-
- /* Just to create the data to pass to immediate mode, grr! */
- const int *facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP);
- if (facemap_data) {
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
-
- const MVert *mvert = me->mvert;
- const MPoly *mpoly = me->mpoly;
- const MLoop *mloop = me->mloop;
-
- int mpoly_len = me->totpoly;
- int mloop_len = me->totloop;
-
- facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP);
-
- /* use gawain immediate mode fore now */
- const int looptris_len = poly_to_tri_count(mpoly_len, mloop_len);
- const int vbo_len_capacity = looptris_len * 3;
- int vbo_len_used = 0;
-
- GPUVertFormat format_pos = { 0 };
- const uint pos_id = GPU_vertformat_attr_add(&format_pos, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-
- GPUVertBuf *vbo_pos = GPU_vertbuf_create_with_format(&format_pos);
- GPU_vertbuf_data_alloc(vbo_pos, vbo_len_capacity);
-
- GPUVertBufRaw pos_step;
- GPU_vertbuf_attr_get_raw_data(vbo_pos, pos_id, &pos_step);
-
- const MPoly *mp;
- int i;
- if (me->runtime.looptris.array) {
- MLoopTri *mlt = me->runtime.looptris.array;
- for (mp = mpoly, i = 0; i < mpoly_len; i++, mp++) {
- if (facemap_data[i] == facemap) {
- for (int j = 2; j < mp->totloop; j++) {
- copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[mloop[mlt->tri[0]].v].co);
- copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[mloop[mlt->tri[1]].v].co);
- copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[mloop[mlt->tri[2]].v].co);
- vbo_len_used += 3;
- mlt++;
- }
- }
- else {
- mlt += mp->totloop - 2;
- }
- }
- }
- else {
- /* No tessellation data, fan-fill. */
- for (mp = mpoly, i = 0; i < mpoly_len; i++, mp++) {
- if (facemap_data[i] == facemap) {
- const MLoop *ml_start = &mloop[mp->loopstart];
- const MLoop *ml_a = ml_start + 1;
- const MLoop *ml_b = ml_start + 2;
- for (int j = 2; j < mp->totloop; j++) {
- copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[ml_start->v].co);
- copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[ml_a->v].co);
- copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[ml_b->v].co);
- vbo_len_used += 3;
-
- ml_a++;
- ml_b++;
- }
- }
- }
- }
-
- if (vbo_len_capacity != vbo_len_used) {
- GPU_vertbuf_data_resize(vbo_pos, vbo_len_used);
- }
-
- GPUBatch *draw_batch = GPU_batch_create(GPU_PRIM_TRIS, vbo_pos, NULL);
- GPU_batch_program_set_builtin(draw_batch, GPU_SHADER_3D_UNIFORM_COLOR);
- GPU_batch_uniform_4fv(draw_batch, "color", col);
- GPU_batch_draw(draw_batch);
- GPU_batch_discard(draw_batch);
- GPU_vertbuf_discard(vbo_pos);
-
- GPU_blend(false);
- }
+ /* happens on undo */
+ if (ob->type != OB_MESH || !ob->data) {
+ return;
+ }
+
+ 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;
+ }
+ }
+
+ glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
+
+ /* Just to create the data to pass to immediate mode, grr! */
+ const int *facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP);
+ if (facemap_data) {
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
+
+ const MVert *mvert = me->mvert;
+ const MPoly *mpoly = me->mpoly;
+ const MLoop *mloop = me->mloop;
+
+ int mpoly_len = me->totpoly;
+ int mloop_len = me->totloop;
+
+ facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP);
+
+ /* use gawain immediate mode fore now */
+ const int looptris_len = poly_to_tri_count(mpoly_len, mloop_len);
+ const int vbo_len_capacity = looptris_len * 3;
+ int vbo_len_used = 0;
+
+ GPUVertFormat format_pos = {0};
+ const uint pos_id = GPU_vertformat_attr_add(
+ &format_pos, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ GPUVertBuf *vbo_pos = GPU_vertbuf_create_with_format(&format_pos);
+ GPU_vertbuf_data_alloc(vbo_pos, vbo_len_capacity);
+
+ GPUVertBufRaw pos_step;
+ GPU_vertbuf_attr_get_raw_data(vbo_pos, pos_id, &pos_step);
+
+ const MPoly *mp;
+ int i;
+ if (me->runtime.looptris.array) {
+ MLoopTri *mlt = me->runtime.looptris.array;
+ for (mp = mpoly, i = 0; i < mpoly_len; i++, mp++) {
+ if (facemap_data[i] == facemap) {
+ for (int j = 2; j < mp->totloop; j++) {
+ copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[mloop[mlt->tri[0]].v].co);
+ copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[mloop[mlt->tri[1]].v].co);
+ copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[mloop[mlt->tri[2]].v].co);
+ vbo_len_used += 3;
+ mlt++;
+ }
+ }
+ else {
+ mlt += mp->totloop - 2;
+ }
+ }
+ }
+ else {
+ /* No tessellation data, fan-fill. */
+ for (mp = mpoly, i = 0; i < mpoly_len; i++, mp++) {
+ if (facemap_data[i] == facemap) {
+ const MLoop *ml_start = &mloop[mp->loopstart];
+ const MLoop *ml_a = ml_start + 1;
+ const MLoop *ml_b = ml_start + 2;
+ for (int j = 2; j < mp->totloop; j++) {
+ copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[ml_start->v].co);
+ copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[ml_a->v].co);
+ copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[ml_b->v].co);
+ vbo_len_used += 3;
+
+ ml_a++;
+ ml_b++;
+ }
+ }
+ }
+ }
+
+ if (vbo_len_capacity != vbo_len_used) {
+ GPU_vertbuf_data_resize(vbo_pos, vbo_len_used);
+ }
+
+ GPUBatch *draw_batch = GPU_batch_create(GPU_PRIM_TRIS, vbo_pos, NULL);
+ GPU_batch_program_set_builtin(draw_batch, GPU_SHADER_3D_UNIFORM_COLOR);
+ GPU_batch_uniform_4fv(draw_batch, "color", col);
+ GPU_batch_draw(draw_batch);
+ GPU_batch_discard(draw_batch);
+ GPU_vertbuf_discard(vbo_pos);
+
+ GPU_blend(false);
+ }
}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 42860b62ae5..434f379c6fe 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -21,7 +21,6 @@
* \ingroup spview3d
*/
-
#include <string.h>
#include <stdio.h>
@@ -79,75 +78,75 @@
#include "DEG_depsgraph.h"
-#include "view3d_intern.h" /* own include */
+#include "view3d_intern.h" /* own include */
/* ******************** manage regions ********************* */
ARegion *view3d_has_buttons_region(ScrArea *sa)
{
- ARegion *ar, *arnew;
+ ARegion *ar, *arnew;
- ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
- if (ar) {
- return ar;
- }
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
+ if (ar) {
+ return ar;
+ }
- /* add subdiv level; after header */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+ /* add subdiv level; after header */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
- /* is error! */
- if (ar == NULL) {
- return NULL;
- }
+ /* is error! */
+ if (ar == NULL) {
+ return NULL;
+ }
- arnew = MEM_callocN(sizeof(ARegion), "buttons for view3d");
+ arnew = MEM_callocN(sizeof(ARegion), "buttons for view3d");
- BLI_insertlinkafter(&sa->regionbase, ar, arnew);
- arnew->regiontype = RGN_TYPE_UI;
- arnew->alignment = RGN_ALIGN_RIGHT;
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype = RGN_TYPE_UI;
+ arnew->alignment = RGN_ALIGN_RIGHT;
- arnew->flag = RGN_FLAG_HIDDEN;
+ arnew->flag = RGN_FLAG_HIDDEN;
- return arnew;
+ return arnew;
}
ARegion *view3d_has_tools_region(ScrArea *sa)
{
- ARegion *ar, *artool = NULL, *arhead;
-
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_TOOLS) {
- artool = ar;
- }
- }
-
- /* tool region hide/unhide also hides props */
- if (artool) {
- return artool;
- }
-
- if (artool == NULL) {
- /* add subdiv level; after header */
- for (arhead = sa->regionbase.first; arhead; arhead = arhead->next) {
- if (arhead->regiontype == RGN_TYPE_HEADER) {
- break;
- }
- }
-
- /* is error! */
- if (arhead == NULL) {
- return NULL;
- }
-
- artool = MEM_callocN(sizeof(ARegion), "tools for view3d");
-
- BLI_insertlinkafter(&sa->regionbase, arhead, artool);
- artool->regiontype = RGN_TYPE_TOOLS;
- artool->alignment = RGN_ALIGN_LEFT;
- artool->flag = RGN_FLAG_HIDDEN;
- }
-
- return artool;
+ ARegion *ar, *artool = NULL, *arhead;
+
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_TOOLS) {
+ artool = ar;
+ }
+ }
+
+ /* tool region hide/unhide also hides props */
+ if (artool) {
+ return artool;
+ }
+
+ if (artool == NULL) {
+ /* add subdiv level; after header */
+ for (arhead = sa->regionbase.first; arhead; arhead = arhead->next) {
+ if (arhead->regiontype == RGN_TYPE_HEADER) {
+ break;
+ }
+ }
+
+ /* is error! */
+ if (arhead == NULL) {
+ return NULL;
+ }
+
+ artool = MEM_callocN(sizeof(ARegion), "tools for view3d");
+
+ BLI_insertlinkafter(&sa->regionbase, arhead, artool);
+ artool->regiontype = RGN_TYPE_TOOLS;
+ artool->alignment = RGN_ALIGN_LEFT;
+ artool->flag = RGN_FLAG_HIDDEN;
+ }
+
+ return artool;
}
/* ****************************************************** */
@@ -155,74 +154,75 @@ ARegion *view3d_has_tools_region(ScrArea *sa)
/* function to always find a regionview3d context inside 3D window */
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;
- }
- }
- }
- return rv3d;
+ 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;
+ }
+ }
+ }
+ return rv3d;
}
/* 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)
{
- ScrArea *sa = CTX_wm_area(C);
-
- *r_v3d = NULL;
- *r_ar = NULL;
-
- if (sa && sa->spacetype == SPACE_VIEW3D) {
- ARegion *ar = CTX_wm_region(C);
- View3D *v3d = (View3D *)sa->spacedata.first;
-
- if (ar) {
- RegionView3D *rv3d;
- if ((ar->regiontype == RGN_TYPE_WINDOW) && (rv3d = ar->regiondata) && (rv3d->viewlock & RV3D_LOCKED) == 0) {
- *r_v3d = v3d;
- *r_ar = ar;
- 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) {
- *r_v3d = v3d;
- *r_ar = ar_unlock_user;
- return true;
- }
-
- if (ar_unlock) {
- *r_v3d = v3d;
- *r_ar = ar_unlock;
- return true;
- }
- }
- }
- }
-
- return false;
+ ScrArea *sa = CTX_wm_area(C);
+
+ *r_v3d = NULL;
+ *r_ar = NULL;
+
+ if (sa && sa->spacetype == SPACE_VIEW3D) {
+ ARegion *ar = CTX_wm_region(C);
+ View3D *v3d = (View3D *)sa->spacedata.first;
+
+ if (ar) {
+ RegionView3D *rv3d;
+ if ((ar->regiontype == RGN_TYPE_WINDOW) && (rv3d = ar->regiondata) &&
+ (rv3d->viewlock & RV3D_LOCKED) == 0) {
+ *r_v3d = v3d;
+ *r_ar = ar;
+ 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) {
+ *r_v3d = v3d;
+ *r_ar = ar_unlock_user;
+ return true;
+ }
+
+ if (ar_unlock) {
+ *r_v3d = v3d;
+ *r_ar = ar_unlock;
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
}
/* Most of the time this isn't needed since you could assume the view matrix was
@@ -238,1325 +238,1340 @@ bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_ar)
*/
void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d)
{
- /* local viewmat and persmat, to calculate projections */
- mul_m4_m4m4(rv3d->viewmatob, rv3d->viewmat, ob->obmat);
- mul_m4_m4m4(rv3d->persmatob, rv3d->persmat, ob->obmat);
+ /* local viewmat and persmat, to calculate projections */
+ mul_m4_m4m4(rv3d->viewmatob, rv3d->viewmat, ob->obmat);
+ mul_m4_m4m4(rv3d->persmatob, rv3d->persmat, ob->obmat);
- /* initializes object space clipping, speeds up clip tests */
- ED_view3d_clipping_local(rv3d, ob->obmat);
+ /* initializes object space clipping, speeds up clip tests */
+ ED_view3d_clipping_local(rv3d, ob->obmat);
}
void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d)
{
- ED_view3d_init_mats_rv3d(ob, rv3d);
+ ED_view3d_init_mats_rv3d(ob, rv3d);
- /* we have to multiply instead of loading viewmatob to make
- * it work with duplis using displists, otherwise it will
- * override the dupli-matrix */
- GPU_matrix_mul(ob->obmat);
+ /* we have to multiply instead of loading viewmatob to make
+ * it work with duplis using displists, otherwise it will
+ * override the dupli-matrix */
+ GPU_matrix_mul(ob->obmat);
}
#ifdef DEBUG
/* ensure we correctly initialize */
void ED_view3d_clear_mats_rv3d(struct RegionView3D *rv3d)
{
- zero_m4(rv3d->viewmatob);
- zero_m4(rv3d->persmatob);
+ zero_m4(rv3d->viewmatob);
+ zero_m4(rv3d->persmatob);
}
void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d)
{
- BLI_ASSERT_ZERO_M4(rv3d->viewmatob);
- BLI_ASSERT_ZERO_M4(rv3d->persmatob);
+ BLI_ASSERT_ZERO_M4(rv3d->viewmatob);
+ BLI_ASSERT_ZERO_M4(rv3d->persmatob);
}
#endif
void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = ar->regiondata;
- if (rv3d->render_engine) {
+ if (rv3d->render_engine) {
#ifdef WITH_PYTHON
- BPy_BEGIN_ALLOW_THREADS;
+ BPy_BEGIN_ALLOW_THREADS;
#endif
- WM_jobs_kill_type(wm, ar, WM_JOB_TYPE_RENDER_PREVIEW);
+ WM_jobs_kill_type(wm, ar, WM_JOB_TYPE_RENDER_PREVIEW);
#ifdef WITH_PYTHON
- BPy_END_ALLOW_THREADS;
+ BPy_END_ALLOW_THREADS;
#endif
- RE_engine_free(rv3d->render_engine);
- rv3d->render_engine = NULL;
- }
+ RE_engine_free(rv3d->render_engine);
+ rv3d->render_engine = NULL;
+ }
}
void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
{
- wmWindowManager *wm = bmain->wm.first;
-
- if (v3d->shading.type != OB_RENDER) {
- ARegion *ar;
-
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if ((ar->regiontype == RGN_TYPE_WINDOW) && ar->regiondata) {
- ED_view3d_stop_render_preview(wm, ar);
- break;
- }
- }
- }
+ wmWindowManager *wm = bmain->wm.first;
+
+ if (v3d->shading.type != OB_RENDER) {
+ ARegion *ar;
+
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if ((ar->regiontype == RGN_TYPE_WINDOW) && ar->regiondata) {
+ ED_view3d_stop_render_preview(wm, ar);
+ break;
+ }
+ }
+ }
}
/* ******************** default callbacks for view3d space ***************** */
static SpaceLink *view3d_new(const ScrArea *UNUSED(sa), const Scene *scene)
{
- ARegion *ar;
- View3D *v3d;
- RegionView3D *rv3d;
-
- v3d = MEM_callocN(sizeof(View3D), "initview3d");
- v3d->spacetype = SPACE_VIEW3D;
- if (scene) {
- v3d->camera = scene->camera;
- }
- v3d->scenelock = true;
- v3d->grid = 1.0f;
- v3d->gridlines = 16;
- v3d->gridsubdiv = 10;
- BKE_screen_view3d_shading_init(&v3d->shading);
-
- v3d->overlay.wireframe_threshold = 1.0f;
- v3d->overlay.xray_alpha_bone = 0.5f;
- v3d->overlay.texture_paint_mode_opacity = 1.0f;
- v3d->overlay.weight_paint_mode_opacity = 1.0f;
- v3d->overlay.vertex_paint_mode_opacity = 1.0f;
- v3d->overlay.edit_flag = V3D_OVERLAY_EDIT_FACES |
- V3D_OVERLAY_EDIT_SEAMS |
- V3D_OVERLAY_EDIT_SHARP |
- V3D_OVERLAY_EDIT_FREESTYLE_EDGE |
- V3D_OVERLAY_EDIT_FREESTYLE_FACE |
- V3D_OVERLAY_EDIT_EDGES |
- V3D_OVERLAY_EDIT_CREASES |
- V3D_OVERLAY_EDIT_BWEIGHTS |
- V3D_OVERLAY_EDIT_CU_HANDLES |
- V3D_OVERLAY_EDIT_CU_NORMALS;
-
- v3d->gridflag = V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_FLOOR;
-
- v3d->flag = V3D_SELECT_OUTLINE;
- v3d->flag2 = V3D_SHOW_RECONSTRUCTION | V3D_SHOW_ANNOTATION;
-
- v3d->lens = 50.0f;
- v3d->clip_start = 0.01f;
- v3d->clip_end = 1000.0f;
-
- v3d->overlay.gpencil_paper_opacity = 0.5f;
- v3d->overlay.gpencil_grid_opacity = 0.9f;
-
- v3d->bundle_size = 0.2f;
- v3d->bundle_drawtype = OB_PLAINAXES;
-
- /* stereo */
- v3d->stereo3d_camera = STEREO_3D_ID;
- v3d->stereo3d_flag |= V3D_S3D_DISPPLANE;
- v3d->stereo3d_convergence_alpha = 0.15f;
- v3d->stereo3d_volume_alpha = 0.05f;
-
- /* grease pencil settings */
- v3d->vertex_opacity = 1.0f;
- v3d->gp_flag |= V3D_GP_SHOW_EDIT_LINES;
-
- /* header */
- ar = 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;
-
- /* tool shelf */
- ar = 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;
-
- /* buttons/list view */
- ar = 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;
-
- /* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for view3d");
-
- BLI_addtail(&v3d->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
-
- ar->regiondata = MEM_callocN(sizeof(RegionView3D), "region view3d");
- rv3d = ar->regiondata;
- rv3d->viewquat[0] = 1.0f;
- rv3d->persp = RV3D_PERSP;
- rv3d->view = RV3D_VIEW_USER;
- rv3d->dist = 10.0;
-
- return (SpaceLink *)v3d;
+ ARegion *ar;
+ View3D *v3d;
+ RegionView3D *rv3d;
+
+ v3d = MEM_callocN(sizeof(View3D), "initview3d");
+ v3d->spacetype = SPACE_VIEW3D;
+ if (scene) {
+ v3d->camera = scene->camera;
+ }
+ v3d->scenelock = true;
+ v3d->grid = 1.0f;
+ v3d->gridlines = 16;
+ v3d->gridsubdiv = 10;
+ BKE_screen_view3d_shading_init(&v3d->shading);
+
+ v3d->overlay.wireframe_threshold = 1.0f;
+ v3d->overlay.xray_alpha_bone = 0.5f;
+ v3d->overlay.texture_paint_mode_opacity = 1.0f;
+ v3d->overlay.weight_paint_mode_opacity = 1.0f;
+ v3d->overlay.vertex_paint_mode_opacity = 1.0f;
+ v3d->overlay.edit_flag = V3D_OVERLAY_EDIT_FACES | V3D_OVERLAY_EDIT_SEAMS |
+ V3D_OVERLAY_EDIT_SHARP | V3D_OVERLAY_EDIT_FREESTYLE_EDGE |
+ V3D_OVERLAY_EDIT_FREESTYLE_FACE | V3D_OVERLAY_EDIT_EDGES |
+ V3D_OVERLAY_EDIT_CREASES | V3D_OVERLAY_EDIT_BWEIGHTS |
+ V3D_OVERLAY_EDIT_CU_HANDLES | V3D_OVERLAY_EDIT_CU_NORMALS;
+
+ v3d->gridflag = V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_FLOOR;
+
+ v3d->flag = V3D_SELECT_OUTLINE;
+ v3d->flag2 = V3D_SHOW_RECONSTRUCTION | V3D_SHOW_ANNOTATION;
+
+ v3d->lens = 50.0f;
+ v3d->clip_start = 0.01f;
+ v3d->clip_end = 1000.0f;
+
+ v3d->overlay.gpencil_paper_opacity = 0.5f;
+ v3d->overlay.gpencil_grid_opacity = 0.9f;
+
+ v3d->bundle_size = 0.2f;
+ v3d->bundle_drawtype = OB_PLAINAXES;
+
+ /* stereo */
+ v3d->stereo3d_camera = STEREO_3D_ID;
+ v3d->stereo3d_flag |= V3D_S3D_DISPPLANE;
+ v3d->stereo3d_convergence_alpha = 0.15f;
+ v3d->stereo3d_volume_alpha = 0.05f;
+
+ /* grease pencil settings */
+ v3d->vertex_opacity = 1.0f;
+ v3d->gp_flag |= V3D_GP_SHOW_EDIT_LINES;
+
+ /* header */
+ ar = 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;
+
+ /* tool shelf */
+ ar = 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;
+
+ /* buttons/list view */
+ ar = 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;
+
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for view3d");
+
+ BLI_addtail(&v3d->regionbase, ar);
+ ar->regiontype = RGN_TYPE_WINDOW;
+
+ ar->regiondata = MEM_callocN(sizeof(RegionView3D), "region view3d");
+ rv3d = ar->regiondata;
+ rv3d->viewquat[0] = 1.0f;
+ rv3d->persp = RV3D_PERSP;
+ rv3d->view = RV3D_VIEW_USER;
+ rv3d->dist = 10.0;
+
+ return (SpaceLink *)v3d;
}
/* not spacelink itself */
static void view3d_free(SpaceLink *sl)
{
- View3D *vd = (View3D *) sl;
-
- if (vd->localvd) {
- MEM_freeN(vd->localvd);
- }
-
- if (vd->runtime.properties_storage) {
- MEM_freeN(vd->runtime.properties_storage);
- }
-
- if (vd->fx_settings.ssao) {
- MEM_freeN(vd->fx_settings.ssao);
- }
- if (vd->fx_settings.dof) {
- MEM_freeN(vd->fx_settings.dof);
- }
+ View3D *vd = (View3D *)sl;
+
+ if (vd->localvd) {
+ MEM_freeN(vd->localvd);
+ }
+
+ if (vd->runtime.properties_storage) {
+ MEM_freeN(vd->runtime.properties_storage);
+ }
+
+ if (vd->fx_settings.ssao) {
+ MEM_freeN(vd->fx_settings.ssao);
+ }
+ if (vd->fx_settings.dof) {
+ MEM_freeN(vd->fx_settings.dof);
+ }
}
-
/* spacetype; init callback */
static void view3d_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
{
-
}
static SpaceLink *view3d_duplicate(SpaceLink *sl)
{
- View3D *v3do = (View3D *)sl;
- View3D *v3dn = MEM_dupallocN(sl);
+ View3D *v3do = (View3D *)sl;
+ View3D *v3dn = MEM_dupallocN(sl);
- /* clear or remove stuff from old */
+ /* clear or remove stuff from old */
- if (v3dn->localvd) {
- v3dn->localvd = NULL;
- v3dn->runtime.properties_storage = NULL;
- }
+ if (v3dn->localvd) {
+ v3dn->localvd = NULL;
+ v3dn->runtime.properties_storage = NULL;
+ }
- if (v3dn->shading.type == OB_RENDER) {
- v3dn->shading.type = OB_SOLID;
- }
+ if (v3dn->shading.type == OB_RENDER) {
+ v3dn->shading.type = OB_SOLID;
+ }
- /* copy or clear inside new stuff */
+ /* copy or clear inside new stuff */
- v3dn->runtime.properties_storage = NULL;
- if (v3dn->fx_settings.dof) {
- v3dn->fx_settings.dof = MEM_dupallocN(v3do->fx_settings.dof);
- }
- if (v3dn->fx_settings.ssao) {
- v3dn->fx_settings.ssao = MEM_dupallocN(v3do->fx_settings.ssao);
- }
+ v3dn->runtime.properties_storage = NULL;
+ if (v3dn->fx_settings.dof) {
+ v3dn->fx_settings.dof = MEM_dupallocN(v3do->fx_settings.dof);
+ }
+ if (v3dn->fx_settings.ssao) {
+ v3dn->fx_settings.ssao = MEM_dupallocN(v3do->fx_settings.ssao);
+ }
- return (SpaceLink *)v3dn;
+ return (SpaceLink *)v3dn;
}
/* add handlers, stuff you only do once or on area/region changes */
static void view3d_main_region_init(wmWindowManager *wm, ARegion *ar)
{
- ListBase *lb;
- wmKeyMap *keymap;
-
- /* object ops. */
+ ListBase *lb;
+ wmKeyMap *keymap;
- /* 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);
+ /* 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, "Weight Paint Vertex Selection", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Weight Paint Vertex Selection", 0, 0);
+ WM_event_add_keymap_handler(&ar->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);
+ /* 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);
- keymap = WM_keymap_ensure(wm->defaultconf, "Object Mode", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Object Mode", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
- keymap = WM_keymap_ensure(wm->defaultconf, "Paint Curve", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Paint Curve", 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);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Curve", 0, 0);
+ WM_event_add_keymap_handler(&ar->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, "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, "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);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Weight Paint", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
- keymap = WM_keymap_ensure(wm->defaultconf, "Sculpt", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Sculpt", 0, 0);
+ WM_event_add_keymap_handler(&ar->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, "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);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Curve", 0, 0);
+ WM_event_add_keymap_handler(&ar->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, "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);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Pose", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
- keymap = WM_keymap_ensure(wm->defaultconf, "Metaball", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Metaball", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
- keymap = WM_keymap_ensure(wm->defaultconf, "Lattice", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Lattice", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
- keymap = WM_keymap_ensure(wm->defaultconf, "Particle", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Particle", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
- /* editfont keymap swallows all... */
- keymap = WM_keymap_ensure(wm->defaultconf, "Font", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ /* editfont keymap swallows all... */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Font", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
- keymap = WM_keymap_ensure(wm->defaultconf, "Object Non-modal", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Object Non-modal", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
- keymap = WM_keymap_ensure(wm->defaultconf, "Frames", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Frames", 0, 0);
+ WM_event_add_keymap_handler(&ar->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);
+ /* 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);
- keymap = WM_keymap_ensure(wm->defaultconf, "3D View", SPACE_VIEW3D, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "3D View", SPACE_VIEW3D, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
- /* add drop boxes */
- lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
-
- WM_event_add_dropbox_handler(&ar->handlers, lb);
+ /* add drop boxes */
+ lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
+ WM_event_add_dropbox_handler(&ar->handlers, lb);
}
static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar)
{
- ED_view3d_stop_render_preview(wm, ar);
+ ED_view3d_stop_render_preview(wm, ar);
}
-static bool view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
+static bool view3d_ob_drop_poll(bContext *UNUSED(C),
+ wmDrag *drag,
+ const wmEvent *UNUSED(event),
+ const char **UNUSED(tooltip))
{
- return WM_drag_ID(drag, ID_OB) != NULL;
+ return WM_drag_ID(drag, ID_OB) != NULL;
}
-static bool view3d_collection_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
+static bool view3d_collection_drop_poll(bContext *UNUSED(C),
+ wmDrag *drag,
+ const wmEvent *UNUSED(event),
+ const char **UNUSED(tooltip))
{
- return WM_drag_ID(drag, ID_GR) != NULL;
+ return WM_drag_ID(drag, ID_GR) != NULL;
}
-static bool view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
+static bool view3d_mat_drop_poll(bContext *UNUSED(C),
+ wmDrag *drag,
+ const wmEvent *UNUSED(event),
+ const char **UNUSED(tooltip))
{
- return WM_drag_ID(drag, ID_MA) != NULL;
+ return WM_drag_ID(drag, ID_MA) != NULL;
}
-static bool view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
+static bool view3d_ima_drop_poll(bContext *UNUSED(C),
+ wmDrag *drag,
+ const wmEvent *UNUSED(event),
+ const char **UNUSED(tooltip))
{
- if (drag->type == WM_DRAG_PATH) {
- /* rule might not work? */
- return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE));
- }
- else {
- return WM_drag_ID(drag, ID_IM) != NULL;
- }
+ if (drag->type == WM_DRAG_PATH) {
+ /* rule might not work? */
+ return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE));
+ }
+ else {
+ return WM_drag_ID(drag, ID_IM) != NULL;
+ }
}
static bool view3d_ima_bg_is_camera_view(bContext *C)
{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- if ((rv3d && (rv3d->persp == RV3D_CAMOB))) {
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d && v3d->camera && v3d->camera->type == OB_CAMERA) {
- return true;
- }
- }
- return false;
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if ((rv3d && (rv3d->persp == RV3D_CAMOB))) {
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d && v3d->camera && v3d->camera->type == OB_CAMERA) {
+ return true;
+ }
+ }
+ return false;
}
-static bool view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **tooltip)
+static bool view3d_ima_bg_drop_poll(bContext *C,
+ wmDrag *drag,
+ const wmEvent *event,
+ const char **tooltip)
{
- if (!view3d_ima_drop_poll(C, drag, event, tooltip)) {
- return false;
- }
+ if (!view3d_ima_drop_poll(C, drag, event, tooltip)) {
+ return false;
+ }
- if (ED_view3d_is_object_under_cursor(C, event->mval)) {
- return false;
- }
+ if (ED_view3d_is_object_under_cursor(C, event->mval)) {
+ return false;
+ }
- return view3d_ima_bg_is_camera_view(C);
+ return view3d_ima_bg_is_camera_view(C);
}
-static bool view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **tooltip)
+static bool view3d_ima_empty_drop_poll(bContext *C,
+ wmDrag *drag,
+ const wmEvent *event,
+ const char **tooltip)
{
- if (!view3d_ima_drop_poll(C, drag, event, tooltip)) {
- return false;
- }
+ if (!view3d_ima_drop_poll(C, drag, event, tooltip)) {
+ return false;
+ }
- Object *ob = ED_view3d_give_object_under_cursor(C, event->mval);
+ Object *ob = ED_view3d_give_object_under_cursor(C, event->mval);
- if (ob == NULL) {
- return true;
- }
+ if (ob == NULL) {
+ return true;
+ }
- if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) {
- return true;
- }
+ if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) {
+ return true;
+ }
- return false;
+ return false;
}
static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = WM_drag_ID(drag, ID_OB);
+ ID *id = WM_drag_ID(drag, ID_OB);
- RNA_string_set(drop->ptr, "name", id->name + 2);
+ RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = WM_drag_ID(drag, ID_GR);
+ ID *id = WM_drag_ID(drag, ID_GR);
- drop->opcontext = WM_OP_EXEC_DEFAULT;
- RNA_string_set(drop->ptr, "name", id->name + 2);
+ drop->opcontext = WM_OP_EXEC_DEFAULT;
+ RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = WM_drag_ID(drag, 0);
+ ID *id = WM_drag_ID(drag, 0);
- RNA_string_set(drop->ptr, "name", id->name + 2);
+ RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = WM_drag_ID(drag, 0);
-
- if (id) {
- RNA_string_set(drop->ptr, "name", id->name + 2);
- RNA_struct_property_unset(drop->ptr, "filepath");
- }
- else if (drag->path[0]) {
- RNA_string_set(drop->ptr, "filepath", drag->path);
- RNA_struct_property_unset(drop->ptr, "image");
- }
+ ID *id = WM_drag_ID(drag, 0);
+
+ if (id) {
+ RNA_string_set(drop->ptr, "name", id->name + 2);
+ RNA_struct_property_unset(drop->ptr, "filepath");
+ }
+ else if (drag->path[0]) {
+ RNA_string_set(drop->ptr, "filepath", drag->path);
+ RNA_struct_property_unset(drop->ptr, "image");
+ }
}
static void view3d_lightcache_update(bContext *C)
{
- PointerRNA op_ptr;
+ PointerRNA op_ptr;
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- if (strcmp(scene->r.engine, RE_engine_id_BLENDER_EEVEE) != 0) {
- /* Only do auto bake if eevee is the active engine */
- return;
- }
+ if (strcmp(scene->r.engine, RE_engine_id_BLENDER_EEVEE) != 0) {
+ /* Only do auto bake if eevee is the active engine */
+ return;
+ }
- WM_operator_properties_create(&op_ptr, "SCENE_OT_light_cache_bake");
- RNA_int_set(&op_ptr, "delay", 200);
- RNA_enum_set_identifier(C, &op_ptr, "subset", "DIRTY");
+ WM_operator_properties_create(&op_ptr, "SCENE_OT_light_cache_bake");
+ RNA_int_set(&op_ptr, "delay", 200);
+ RNA_enum_set_identifier(C, &op_ptr, "subset", "DIRTY");
- WM_operator_name_call(C, "SCENE_OT_light_cache_bake", WM_OP_INVOKE_DEFAULT, &op_ptr);
+ WM_operator_name_call(C, "SCENE_OT_light_cache_bake", WM_OP_INVOKE_DEFAULT, &op_ptr);
- WM_operator_properties_free(&op_ptr);
+ WM_operator_properties_free(&op_ptr);
}
/* region dropbox definition */
static void view3d_dropboxes(void)
{
- ListBase *lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
-
- WM_dropbox_add(lb, "OBJECT_OT_add_named", view3d_ob_drop_poll, view3d_ob_drop_copy);
- WM_dropbox_add(lb, "OBJECT_OT_drop_named_material", view3d_mat_drop_poll, view3d_id_drop_copy);
- WM_dropbox_add(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_collection_instance_add", view3d_collection_drop_poll, view3d_collection_drop_copy);
+ ListBase *lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
+
+ WM_dropbox_add(lb, "OBJECT_OT_add_named", view3d_ob_drop_poll, view3d_ob_drop_copy);
+ WM_dropbox_add(lb, "OBJECT_OT_drop_named_material", view3d_mat_drop_poll, view3d_id_drop_copy);
+ WM_dropbox_add(
+ 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_collection_instance_add",
+ view3d_collection_drop_poll,
+ view3d_collection_drop_copy);
}
static void view3d_widgets(void)
{
- wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(
- &(const struct wmGizmoMapType_Params){SPACE_VIEW3D, RGN_TYPE_WINDOW});
-
- WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_xform_gizmo_context);
- WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_spot);
- WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_area);
- WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_target);
- WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_force_field);
- WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_camera);
- WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_camera_view);
- WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_empty_image);
- WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_armature_spline);
-
- WM_gizmogrouptype_append(VIEW3D_GGT_xform_gizmo);
- WM_gizmogrouptype_append(VIEW3D_GGT_xform_cage);
- WM_gizmogrouptype_append(VIEW3D_GGT_xform_shear);
- WM_gizmogrouptype_append(VIEW3D_GGT_xform_extrude);
- WM_gizmogrouptype_append(VIEW3D_GGT_mesh_preselect_elem);
- WM_gizmogrouptype_append(VIEW3D_GGT_mesh_preselect_edgering);
-
- WM_gizmogrouptype_append(VIEW3D_GGT_ruler);
- WM_gizmotype_append(VIEW3D_GT_ruler_item);
-
- WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_navigate);
- WM_gizmotype_append(VIEW3D_GT_navigate_rotate);
+ wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(
+ &(const struct wmGizmoMapType_Params){SPACE_VIEW3D, RGN_TYPE_WINDOW});
+
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_xform_gizmo_context);
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_spot);
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_area);
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_target);
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_force_field);
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_camera);
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_camera_view);
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_empty_image);
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_armature_spline);
+
+ WM_gizmogrouptype_append(VIEW3D_GGT_xform_gizmo);
+ WM_gizmogrouptype_append(VIEW3D_GGT_xform_cage);
+ WM_gizmogrouptype_append(VIEW3D_GGT_xform_shear);
+ WM_gizmogrouptype_append(VIEW3D_GGT_xform_extrude);
+ WM_gizmogrouptype_append(VIEW3D_GGT_mesh_preselect_elem);
+ WM_gizmogrouptype_append(VIEW3D_GGT_mesh_preselect_edgering);
+
+ WM_gizmogrouptype_append(VIEW3D_GGT_ruler);
+ WM_gizmotype_append(VIEW3D_GT_ruler_item);
+
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_navigate);
+ WM_gizmotype_append(VIEW3D_GT_navigate_rotate);
}
-
/* type callback, not region itself */
static void view3d_main_region_free(ARegion *ar)
{
- RegionView3D *rv3d = ar->regiondata;
-
- if (rv3d) {
- if (rv3d->localvd) {
- MEM_freeN(rv3d->localvd);
- }
- if (rv3d->clipbb) {
- MEM_freeN(rv3d->clipbb);
- }
-
- if (rv3d->render_engine) {
- RE_engine_free(rv3d->render_engine);
- }
-
- if (rv3d->depths) {
- if (rv3d->depths->depths) {
- MEM_freeN(rv3d->depths->depths);
- }
- MEM_freeN(rv3d->depths);
- }
- if (rv3d->sms) {
- MEM_freeN(rv3d->sms);
- }
-
- MEM_freeN(rv3d);
- ar->regiondata = NULL;
- }
+ RegionView3D *rv3d = ar->regiondata;
+
+ if (rv3d) {
+ if (rv3d->localvd) {
+ MEM_freeN(rv3d->localvd);
+ }
+ if (rv3d->clipbb) {
+ MEM_freeN(rv3d->clipbb);
+ }
+
+ if (rv3d->render_engine) {
+ RE_engine_free(rv3d->render_engine);
+ }
+
+ if (rv3d->depths) {
+ if (rv3d->depths->depths) {
+ MEM_freeN(rv3d->depths->depths);
+ }
+ MEM_freeN(rv3d->depths);
+ }
+ if (rv3d->sms) {
+ MEM_freeN(rv3d->sms);
+ }
+
+ MEM_freeN(rv3d);
+ ar->regiondata = NULL;
+ }
}
/* copy regiondata */
static void *view3d_main_region_duplicate(void *poin)
{
- if (poin) {
- RegionView3D *rv3d = poin, *new;
-
- new = MEM_dupallocN(rv3d);
- if (rv3d->localvd) {
- new->localvd = MEM_dupallocN(rv3d->localvd);
- }
- if (rv3d->clipbb) {
- new->clipbb = MEM_dupallocN(rv3d->clipbb);
- }
-
- new->depths = NULL;
- new->render_engine = NULL;
- new->sms = NULL;
- new->smooth_timer = NULL;
-
- return new;
- }
- return NULL;
+ if (poin) {
+ RegionView3D *rv3d = poin, *new;
+
+ new = MEM_dupallocN(rv3d);
+ if (rv3d->localvd) {
+ new->localvd = MEM_dupallocN(rv3d->localvd);
+ }
+ if (rv3d->clipbb) {
+ new->clipbb = MEM_dupallocN(rv3d->clipbb);
+ }
+
+ new->depths = NULL;
+ new->render_engine = NULL;
+ new->sms = NULL;
+ new->smooth_timer = NULL;
+
+ return new;
+ }
+ return NULL;
}
static void view3d_main_region_listener(
- wmWindow *UNUSED(win), ScrArea *sa, ARegion *ar,
- wmNotifier *wmn, const Scene *scene)
+ wmWindow *UNUSED(win), ScrArea *sa, ARegion *ar, wmNotifier *wmn, const Scene *scene)
{
- View3D *v3d = sa->spacedata.first;
- RegionView3D *rv3d = ar->regiondata;
- wmGizmoMap *gzmap = ar->gizmo_map;
-
- /* context changes */
- switch (wmn->category) {
- case NC_WM:
- if (ELEM(wmn->data, ND_UNDO)) {
- WM_gizmomap_tag_refresh(gzmap);
- }
- break;
- case NC_ANIMATION:
- switch (wmn->data) {
- case ND_KEYFRAME_PROP:
- case ND_NLA_ACTCHANGE:
- ED_region_tag_redraw(ar);
- break;
- case ND_NLA:
- case ND_KEYFRAME:
- if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED)) {
- ED_region_tag_redraw(ar);
- }
- break;
- case ND_ANIMCHAN:
- if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
- break;
- case NC_SCENE:
- switch (wmn->data) {
- case ND_SCENEBROWSE:
- case ND_LAYER_CONTENT:
- ED_region_tag_redraw(ar);
- WM_gizmomap_tag_refresh(gzmap);
- break;
- case ND_LAYER:
- if (wmn->reference) {
- BKE_screen_view3d_sync(v3d, wmn->reference);
- }
- ED_region_tag_redraw(ar);
- WM_gizmomap_tag_refresh(gzmap);
- break;
- case ND_OB_ACTIVE:
- case ND_OB_SELECT:
- ATTR_FALLTHROUGH;
- case ND_FRAME:
- case ND_TRANSFORM:
- case ND_OB_VISIBLE:
- case ND_RENDER_OPTIONS:
- case ND_MARKERS:
- case ND_MODE:
- ED_region_tag_redraw(ar);
- WM_gizmomap_tag_refresh(gzmap);
- break;
- case ND_WORLD:
- /* handled by space_view3d_listener() for v3d access */
- break;
- case ND_DRAW_RENDER_VIEWPORT:
- {
- if (v3d->camera && (scene == wmn->reference)) {
- if (rv3d->persp == RV3D_CAMOB) {
- ED_region_tag_redraw(ar);
- }
- }
- break;
- }
- }
- if (wmn->action == NA_EDITED) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_OBJECT:
- switch (wmn->data) {
- case ND_BONE_ACTIVE:
- case ND_BONE_SELECT:
- case ND_TRANSFORM:
- case ND_POSE:
- case ND_DRAW:
- case ND_MODIFIER:
- case ND_CONSTRAINT:
- case ND_KEYS:
- case ND_PARTICLE:
- case ND_POINTCACHE:
- case ND_LOD:
- ED_region_tag_redraw(ar);
- WM_gizmomap_tag_refresh(gzmap);
- break;
- }
- switch (wmn->action) {
- case NA_ADDED:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_GEOM:
- switch (wmn->data) {
- case ND_SELECT:
- {
- WM_gizmomap_tag_refresh(gzmap);
- ATTR_FALLTHROUGH;
- }
- case ND_DATA:
- case ND_VERTEX_GROUP:
- ED_region_tag_redraw(ar);
- break;
- }
- switch (wmn->action) {
- case NA_EDITED:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_CAMERA:
- switch (wmn->data) {
- case ND_DRAW_RENDER_VIEWPORT:
- {
- if (v3d->camera && (v3d->camera->data == wmn->reference)) {
- if (rv3d->persp == RV3D_CAMOB) {
- ED_region_tag_redraw(ar);
- }
- }
- break;
- }
- }
- break;
- case NC_GROUP:
- /* all group ops for now */
- ED_region_tag_redraw(ar);
- break;
- case NC_BRUSH:
- switch (wmn->action) {
- case NA_EDITED:
- ED_region_tag_redraw_overlay(ar);
- 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);
- break;
- }
- break;
- case NC_MATERIAL:
- switch (wmn->data) {
- case ND_SHADING:
- case ND_NODES:
- /* TODO(sergey) This is a bit too much updates, but needed to
- * have proper material drivers update in the viewport.
- *
- * How to solve?
- */
- ED_region_tag_redraw(ar);
- break;
- case ND_SHADING_DRAW:
- case ND_SHADING_LINKS:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_WORLD:
- switch (wmn->data) {
- case ND_WORLD_DRAW:
- /* handled by space_view3d_listener() for v3d access */
- break;
- case ND_WORLD:
- /* Needed for updating world materials */
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_LAMP:
- switch (wmn->data) {
- case ND_LIGHTING:
- /* TODO(sergey): This is a bit too much, but needed to
- * handle updates from new depsgraph.
- */
- ED_region_tag_redraw(ar);
- break;
- case ND_LIGHTING_DRAW:
- ED_region_tag_redraw(ar);
- WM_gizmomap_tag_refresh(gzmap);
- break;
- }
- break;
- case NC_LIGHTPROBE:
- ED_area_tag_refresh(sa);
- 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);
- break;
- case NC_TEXTURE:
- /* same as above */
- ED_region_tag_redraw(ar);
- break;
- case NC_MOVIECLIP:
- if (wmn->data == ND_DISPLAY || wmn->action == NA_EDITED) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_VIEW3D) {
- if (wmn->subtype == NS_VIEW3D_GPU) {
- rv3d->rflag |= RV3D_GPULIGHT_UPDATE;
- }
- ED_region_tag_redraw(ar);
- WM_gizmomap_tag_refresh(gzmap);
- }
- break;
- case NC_ID:
- if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SCREEN:
- switch (wmn->data) {
- case ND_ANIMPLAY:
- case ND_SKETCH:
- ED_region_tag_redraw(ar);
- break;
- case ND_LAYOUTBROWSE:
- case ND_LAYOUTDELETE:
- case ND_LAYOUTSET:
- WM_gizmomap_tag_refresh(gzmap);
- ED_region_tag_redraw(ar);
- break;
- case ND_LAYER:
- ED_region_tag_redraw(ar);
- break;
- }
-
- break;
- case NC_GPENCIL:
- if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
+ View3D *v3d = sa->spacedata.first;
+ RegionView3D *rv3d = ar->regiondata;
+ wmGizmoMap *gzmap = ar->gizmo_map;
+
+ /* context changes */
+ switch (wmn->category) {
+ case NC_WM:
+ if (ELEM(wmn->data, ND_UNDO)) {
+ WM_gizmomap_tag_refresh(gzmap);
+ }
+ break;
+ case NC_ANIMATION:
+ switch (wmn->data) {
+ case ND_KEYFRAME_PROP:
+ case ND_NLA_ACTCHANGE:
+ ED_region_tag_redraw(ar);
+ break;
+ case ND_NLA:
+ case ND_KEYFRAME:
+ if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case ND_ANIMCHAN:
+ if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED, NA_SELECTED)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
+ break;
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_SCENEBROWSE:
+ case ND_LAYER_CONTENT:
+ ED_region_tag_redraw(ar);
+ WM_gizmomap_tag_refresh(gzmap);
+ break;
+ case ND_LAYER:
+ if (wmn->reference) {
+ BKE_screen_view3d_sync(v3d, wmn->reference);
+ }
+ ED_region_tag_redraw(ar);
+ WM_gizmomap_tag_refresh(gzmap);
+ break;
+ case ND_OB_ACTIVE:
+ case ND_OB_SELECT:
+ ATTR_FALLTHROUGH;
+ case ND_FRAME:
+ case ND_TRANSFORM:
+ case ND_OB_VISIBLE:
+ case ND_RENDER_OPTIONS:
+ case ND_MARKERS:
+ case ND_MODE:
+ ED_region_tag_redraw(ar);
+ WM_gizmomap_tag_refresh(gzmap);
+ break;
+ case ND_WORLD:
+ /* handled by space_view3d_listener() for v3d access */
+ break;
+ case ND_DRAW_RENDER_VIEWPORT: {
+ if (v3d->camera && (scene == wmn->reference)) {
+ if (rv3d->persp == RV3D_CAMOB) {
+ ED_region_tag_redraw(ar);
+ }
+ }
+ break;
+ }
+ }
+ if (wmn->action == NA_EDITED) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_OBJECT:
+ switch (wmn->data) {
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_TRANSFORM:
+ case ND_POSE:
+ case ND_DRAW:
+ case ND_MODIFIER:
+ case ND_CONSTRAINT:
+ case ND_KEYS:
+ case ND_PARTICLE:
+ case ND_POINTCACHE:
+ case ND_LOD:
+ ED_region_tag_redraw(ar);
+ WM_gizmomap_tag_refresh(gzmap);
+ break;
+ }
+ switch (wmn->action) {
+ case NA_ADDED:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_GEOM:
+ switch (wmn->data) {
+ case ND_SELECT: {
+ WM_gizmomap_tag_refresh(gzmap);
+ ATTR_FALLTHROUGH;
+ }
+ case ND_DATA:
+ case ND_VERTEX_GROUP:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ switch (wmn->action) {
+ case NA_EDITED:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_CAMERA:
+ switch (wmn->data) {
+ case ND_DRAW_RENDER_VIEWPORT: {
+ if (v3d->camera && (v3d->camera->data == wmn->reference)) {
+ if (rv3d->persp == RV3D_CAMOB) {
+ ED_region_tag_redraw(ar);
+ }
+ }
+ break;
+ }
+ }
+ break;
+ case NC_GROUP:
+ /* all group ops for now */
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_BRUSH:
+ switch (wmn->action) {
+ case NA_EDITED:
+ ED_region_tag_redraw_overlay(ar);
+ 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);
+ break;
+ }
+ break;
+ case NC_MATERIAL:
+ switch (wmn->data) {
+ case ND_SHADING:
+ case ND_NODES:
+ /* TODO(sergey) This is a bit too much updates, but needed to
+ * have proper material drivers update in the viewport.
+ *
+ * How to solve?
+ */
+ ED_region_tag_redraw(ar);
+ break;
+ case ND_SHADING_DRAW:
+ case ND_SHADING_LINKS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_WORLD:
+ switch (wmn->data) {
+ case ND_WORLD_DRAW:
+ /* handled by space_view3d_listener() for v3d access */
+ break;
+ case ND_WORLD:
+ /* Needed for updating world materials */
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_LAMP:
+ switch (wmn->data) {
+ case ND_LIGHTING:
+ /* TODO(sergey): This is a bit too much, but needed to
+ * handle updates from new depsgraph.
+ */
+ ED_region_tag_redraw(ar);
+ break;
+ case ND_LIGHTING_DRAW:
+ ED_region_tag_redraw(ar);
+ WM_gizmomap_tag_refresh(gzmap);
+ break;
+ }
+ break;
+ case NC_LIGHTPROBE:
+ ED_area_tag_refresh(sa);
+ 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);
+ break;
+ case NC_TEXTURE:
+ /* same as above */
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_MOVIECLIP:
+ if (wmn->data == ND_DISPLAY || wmn->action == NA_EDITED) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_VIEW3D) {
+ if (wmn->subtype == NS_VIEW3D_GPU) {
+ rv3d->rflag |= RV3D_GPULIGHT_UPDATE;
+ }
+ ED_region_tag_redraw(ar);
+ WM_gizmomap_tag_refresh(gzmap);
+ }
+ break;
+ case NC_ID:
+ if (wmn->action == NA_RENAME) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SCREEN:
+ switch (wmn->data) {
+ case ND_ANIMPLAY:
+ case ND_SKETCH:
+ ED_region_tag_redraw(ar);
+ break;
+ case ND_LAYOUTBROWSE:
+ case ND_LAYOUTDELETE:
+ case ND_LAYOUTSET:
+ WM_gizmomap_tag_refresh(gzmap);
+ ED_region_tag_redraw(ar);
+ break;
+ case ND_LAYER:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+
+ break;
+ case NC_GPENCIL:
+ if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
}
-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 wmMsgBus *mbus)
+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 wmMsgBus *mbus)
{
- /* Developer note: there are many properties that impact 3D view drawing,
- * so instead of subscribing to individual properties, just subscribe to types
- * accepting some redundant redraws.
- *
- * For other space types we might try avoid this, keep the 3D view as an exceptional case! */
- wmMsgParams_RNA msg_key_params = {{{0}}};
-
- /* Only subscribe to types. */
- StructRNA *type_array[] = {
- &RNA_Window,
-
- /* These object have properties that impact drawing. */
- &RNA_AreaLight,
- &RNA_Camera,
- &RNA_Light,
- &RNA_Speaker,
- &RNA_SunLight,
-
- /* General types the 3D view depends on. */
- &RNA_Object,
- &RNA_UnitSettings, /* grid-floor */
-
- &RNA_View3DOverlay,
- &RNA_View3DShading,
- &RNA_World,
- };
-
- wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
- .notify = ED_region_do_msg_notify_tag_redraw,
- };
-
- for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
- msg_key_params.ptr.type = type_array[i];
- WM_msg_subscribe_rna_params(
- mbus,
- &msg_key_params,
- &msg_sub_value_region_tag_redraw,
- __func__);
- }
-
- /* Subscribe to a handful of other properties. */
- RegionView3D *rv3d = ar->regiondata;
-
- WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, engine, &msg_sub_value_region_tag_redraw);
- WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_x, &msg_sub_value_region_tag_redraw);
- WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_y, &msg_sub_value_region_tag_redraw);
- WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_region_tag_redraw);
- WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_region_tag_redraw);
- if (rv3d->persp == RV3D_CAMOB) {
- WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, use_border, &msg_sub_value_region_tag_redraw);
- }
-
- WM_msg_subscribe_rna_anon_type(mbus, SceneEEVEE, &msg_sub_value_region_tag_redraw);
- WM_msg_subscribe_rna_anon_type(mbus, SceneDisplay, &msg_sub_value_region_tag_redraw);
- WM_msg_subscribe_rna_anon_type(mbus, ObjectDisplay, &msg_sub_value_region_tag_redraw);
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *obact = OBACT(view_layer);
- if (obact != NULL) {
- switch (obact->mode) {
- case OB_MODE_PARTICLE_EDIT:
- WM_msg_subscribe_rna_anon_type(mbus, ParticleEdit, &msg_sub_value_region_tag_redraw);
- break;
- default:
- break;
- }
- }
-
- {
- wmMsgSubscribeValue msg_sub_value_region_tag_refresh = {
- .owner = ar,
- .user_data = sa,
- .notify = WM_toolsystem_do_msg_notify_tag_refresh,
- };
- WM_msg_subscribe_rna_anon_prop(
- mbus, Object, mode,
- &msg_sub_value_region_tag_refresh);
- WM_msg_subscribe_rna_anon_prop(
- mbus, LayerObjects, active,
- &msg_sub_value_region_tag_refresh);
- }
+ /* Developer note: there are many properties that impact 3D view drawing,
+ * so instead of subscribing to individual properties, just subscribe to types
+ * accepting some redundant redraws.
+ *
+ * For other space types we might try avoid this, keep the 3D view as an exceptional case! */
+ wmMsgParams_RNA msg_key_params = {{{0}}};
+
+ /* Only subscribe to types. */
+ StructRNA *type_array[] = {
+ &RNA_Window,
+
+ /* These object have properties that impact drawing. */
+ &RNA_AreaLight,
+ &RNA_Camera,
+ &RNA_Light,
+ &RNA_Speaker,
+ &RNA_SunLight,
+
+ /* General types the 3D view depends on. */
+ &RNA_Object,
+ &RNA_UnitSettings, /* grid-floor */
+
+ &RNA_View3DOverlay,
+ &RNA_View3DShading,
+ &RNA_World,
+ };
+
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
+ msg_key_params.ptr.type = type_array[i];
+ WM_msg_subscribe_rna_params(mbus, &msg_key_params, &msg_sub_value_region_tag_redraw, __func__);
+ }
+
+ /* Subscribe to a handful of other properties. */
+ RegionView3D *rv3d = ar->regiondata;
+
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, engine, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(
+ mbus, RenderSettings, resolution_x, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(
+ mbus, RenderSettings, resolution_y, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(
+ mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(
+ mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_region_tag_redraw);
+ if (rv3d->persp == RV3D_CAMOB) {
+ WM_msg_subscribe_rna_anon_prop(
+ mbus, RenderSettings, use_border, &msg_sub_value_region_tag_redraw);
+ }
+
+ WM_msg_subscribe_rna_anon_type(mbus, SceneEEVEE, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_type(mbus, SceneDisplay, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_type(mbus, ObjectDisplay, &msg_sub_value_region_tag_redraw);
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obact = OBACT(view_layer);
+ if (obact != NULL) {
+ switch (obact->mode) {
+ case OB_MODE_PARTICLE_EDIT:
+ WM_msg_subscribe_rna_anon_type(mbus, ParticleEdit, &msg_sub_value_region_tag_redraw);
+ break;
+ default:
+ break;
+ }
+ }
+
+ {
+ wmMsgSubscribeValue msg_sub_value_region_tag_refresh = {
+ .owner = ar,
+ .user_data = sa,
+ .notify = WM_toolsystem_do_msg_notify_tag_refresh,
+ };
+ WM_msg_subscribe_rna_anon_prop(mbus, Object, mode, &msg_sub_value_region_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(mbus, LayerObjects, active, &msg_sub_value_region_tag_refresh);
+ }
}
/* concept is to retrieve cursor type context-less */
static void view3d_main_region_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
{
- if (WM_cursor_set_from_tool(win, sa, ar)) {
- return;
- }
-
- ViewLayer *view_layer = WM_window_get_active_view_layer(win);
- Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
- if (obedit) {
- WM_cursor_set(win, CURSOR_EDIT);
- }
- else {
- WM_cursor_set(win, CURSOR_STD);
- }
+ if (WM_cursor_set_from_tool(win, sa, ar)) {
+ return;
+ }
+
+ ViewLayer *view_layer = WM_window_get_active_view_layer(win);
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
+ if (obedit) {
+ WM_cursor_set(win, CURSOR_EDIT);
+ }
+ else {
+ WM_cursor_set(win, CURSOR_STD);
+ }
}
/* add handlers, stuff you only do once or on area/region changes */
static void view3d_header_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
+ 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(&ar->handlers, keymap);
- ED_region_header_init(ar);
+ ED_region_header_init(ar);
}
static void view3d_header_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_header(C, ar);
+ ED_region_header(C, ar);
}
-static void view3d_header_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void view3d_header_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_SCENE:
- switch (wmn->data) {
- case ND_FRAME:
- case ND_OB_ACTIVE:
- case ND_OB_SELECT:
- case ND_OB_VISIBLE:
- case ND_MODE:
- case ND_LAYER:
- case ND_TOOLSETTINGS:
- case ND_LAYER_CONTENT:
- case ND_RENDER_OPTIONS:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_VIEW3D) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_GPENCIL:
- if (wmn->data & ND_GPENCIL_EDITMODE) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_FRAME:
+ case ND_OB_ACTIVE:
+ case ND_OB_SELECT:
+ case ND_OB_VISIBLE:
+ case ND_MODE:
+ case ND_LAYER:
+ case ND_TOOLSETTINGS:
+ case ND_LAYER_CONTENT:
+ case ND_RENDER_OPTIONS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_VIEW3D) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_GPENCIL:
+ if (wmn->data & ND_GPENCIL_EDITMODE) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
}
-static void view3d_header_region_message_subscribe(
- const struct bContext *UNUSED(C),
- struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene),
- struct bScreen *UNUSED(screen), struct ScrArea *UNUSED(sa), struct ARegion *ar,
- struct wmMsgBus *mbus)
+static void view3d_header_region_message_subscribe(const struct bContext *UNUSED(C),
+ struct WorkSpace *UNUSED(workspace),
+ struct Scene *UNUSED(scene),
+ struct bScreen *UNUSED(screen),
+ struct ScrArea *UNUSED(sa),
+ struct ARegion *ar,
+ struct wmMsgBus *mbus)
{
- wmMsgParams_RNA msg_key_params = {{{0}}};
-
- /* Only subscribe to types. */
- StructRNA *type_array[] = {
- &RNA_View3DShading,
- };
-
- wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
- .notify = ED_region_do_msg_notify_tag_redraw,
- };
-
- for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
- msg_key_params.ptr.type = type_array[i];
- WM_msg_subscribe_rna_params(
- mbus,
- &msg_key_params,
- &msg_sub_value_region_tag_redraw,
- __func__);
- }
+ wmMsgParams_RNA msg_key_params = {{{0}}};
+
+ /* Only subscribe to types. */
+ StructRNA *type_array[] = {
+ &RNA_View3DShading,
+ };
+
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
+ msg_key_params.ptr.type = type_array[i];
+ WM_msg_subscribe_rna_params(mbus, &msg_key_params, &msg_sub_value_region_tag_redraw, __func__);
+ }
}
-
/* add handlers, stuff you only do once or on area/region changes */
static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, ar);
- keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
}
static void view3d_buttons_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels_ex(C, ar, (const char * []){CTX_data_mode_string(C), NULL}, -1, true);
+ ED_region_panels_ex(C, ar, (const char *[]){CTX_data_mode_string(C), NULL}, -1, true);
}
-static void view3d_buttons_region_listener(
- wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
- wmNotifier *wmn, const Scene *UNUSED(scene))
+static void view3d_buttons_region_listener(wmWindow *UNUSED(win),
+ ScrArea *UNUSED(sa),
+ ARegion *ar,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- /* context changes */
- switch (wmn->category) {
- case NC_ANIMATION:
- switch (wmn->data) {
- case ND_KEYFRAME_PROP:
- case ND_NLA_ACTCHANGE:
- ED_region_tag_redraw(ar);
- break;
- case ND_NLA:
- case ND_KEYFRAME:
- if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED)) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
- break;
- case NC_SCENE:
- switch (wmn->data) {
- case ND_FRAME:
- case ND_OB_ACTIVE:
- case ND_OB_SELECT:
- case ND_OB_VISIBLE:
- case ND_MODE:
- case ND_LAYER:
- case ND_LAYER_CONTENT:
- case ND_TOOLSETTINGS:
- ED_region_tag_redraw(ar);
- break;
- }
- switch (wmn->action) {
- case NA_EDITED:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_OBJECT:
- switch (wmn->data) {
- case ND_BONE_ACTIVE:
- case ND_BONE_SELECT:
- case ND_TRANSFORM:
- case ND_POSE:
- case ND_DRAW:
- case ND_KEYS:
- case ND_MODIFIER:
- ED_region_tag_redraw(ar);
- break;
- }
- break;
- case NC_GEOM:
- switch (wmn->data) {
- case ND_DATA:
- case ND_VERTEX_GROUP:
- case ND_SELECT:
- ED_region_tag_redraw(ar);
- break;
- }
- if (wmn->action == NA_EDITED) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_TEXTURE:
- case NC_MATERIAL:
- /* for brush textures */
- ED_region_tag_redraw(ar);
- break;
- case NC_BRUSH:
- /* NA_SELECTED is used on brush changes */
- if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_VIEW3D) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_ID:
- if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_GPENCIL:
- if ((wmn->data & (ND_DATA | ND_GPENCIL_EDITMODE)) || (wmn->action == NA_EDITED)) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_IMAGE:
- /* Update for the image layers in texture paint. */
- if (wmn->action == NA_EDITED) {
- ED_region_tag_redraw(ar);
- }
- break;
- }
+ /* context changes */
+ switch (wmn->category) {
+ case NC_ANIMATION:
+ switch (wmn->data) {
+ case ND_KEYFRAME_PROP:
+ case ND_NLA_ACTCHANGE:
+ ED_region_tag_redraw(ar);
+ break;
+ case ND_NLA:
+ case ND_KEYFRAME:
+ if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
+ break;
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_FRAME:
+ case ND_OB_ACTIVE:
+ case ND_OB_SELECT:
+ case ND_OB_VISIBLE:
+ case ND_MODE:
+ case ND_LAYER:
+ case ND_LAYER_CONTENT:
+ case ND_TOOLSETTINGS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ switch (wmn->action) {
+ case NA_EDITED:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch (wmn->data) {
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_TRANSFORM:
+ case ND_POSE:
+ case ND_DRAW:
+ case ND_KEYS:
+ case ND_MODIFIER:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_GEOM:
+ switch (wmn->data) {
+ case ND_DATA:
+ case ND_VERTEX_GROUP:
+ case ND_SELECT:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ if (wmn->action == NA_EDITED) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_TEXTURE:
+ case NC_MATERIAL:
+ /* for brush textures */
+ ED_region_tag_redraw(ar);
+ break;
+ case NC_BRUSH:
+ /* NA_SELECTED is used on brush changes */
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_VIEW3D) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_ID:
+ if (wmn->action == NA_RENAME) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_GPENCIL:
+ if ((wmn->data & (ND_DATA | ND_GPENCIL_EDITMODE)) || (wmn->action == NA_EDITED)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_IMAGE:
+ /* Update for the image layers in texture paint. */
+ if (wmn->action == NA_EDITED) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
}
/* add handlers, stuff you only do once or on area/region changes */
static void view3d_tools_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, ar);
- keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
}
static void view3d_tools_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels_ex(C, ar, (const char * []){CTX_data_mode_string(C), NULL}, -1, true);
+ ED_region_panels_ex(C, ar, (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, struct wmNotifier *wmn, Scene *UNUSED(scene))
+static void space_view3d_listener(wmWindow *UNUSED(win),
+ ScrArea *sa,
+ struct wmNotifier *wmn,
+ Scene *UNUSED(scene))
{
- View3D *v3d = sa->spacedata.first;
-
- /* context changes */
- switch (wmn->category) {
- case NC_SCENE:
- switch (wmn->data) {
- case ND_WORLD:
- if (v3d->flag2 & V3D_HIDE_OVERLAYS) {
- ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
- }
- break;
- }
- break;
- case NC_WORLD:
- switch (wmn->data) {
- 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);
- }
- break;
- }
- break;
- case NC_MATERIAL:
- switch (wmn->data) {
- case ND_NODES:
- if (v3d->shading.type == OB_TEXTURE) {
- ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
- }
- break;
- }
- break;
- }
+ View3D *v3d = sa->spacedata.first;
+
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_WORLD:
+ if (v3d->flag2 & V3D_HIDE_OVERLAYS) {
+ ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
+ }
+ break;
+ }
+ break;
+ case NC_WORLD:
+ switch (wmn->data) {
+ 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);
+ }
+ break;
+ }
+ break;
+ case NC_MATERIAL:
+ switch (wmn->data) {
+ case ND_NODES:
+ if (v3d->shading.type == OB_TEXTURE) {
+ ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
+ }
+ break;
+ }
+ break;
+ }
}
static void space_view3d_refresh(const bContext *C, ScrArea *UNUSED(sa))
{
- Scene *scene = CTX_data_scene(C);
- LightCache *lcache = scene->eevee.light_cache;
+ Scene *scene = CTX_data_scene(C);
+ LightCache *lcache = scene->eevee.light_cache;
- if (lcache && (lcache->flag & LIGHTCACHE_UPDATE_AUTO) != 0) {
- lcache->flag &= ~LIGHTCACHE_UPDATE_AUTO;
- view3d_lightcache_update((bContext *)C);
- }
+ if (lcache && (lcache->flag & LIGHTCACHE_UPDATE_AUTO) != 0) {
+ lcache->flag &= ~LIGHTCACHE_UPDATE_AUTO;
+ view3d_lightcache_update((bContext *)C);
+ }
}
const char *view3d_context_dir[] = {
- "active_base", "active_object", NULL,
+ "active_base",
+ "active_object",
+ NULL,
};
static int view3d_context(const bContext *C, const char *member, bContextDataResult *result)
{
- /* fallback to the scene layer,
- * allows duplicate and other object operators to run outside the 3d view */
-
- if (CTX_data_dir(member)) {
- CTX_data_dir_set(result, view3d_context_dir);
- }
- else if (CTX_data_equals(member, "active_base")) {
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- if (view_layer->basact) {
- Object *ob = view_layer->basact->object;
- /* if hidden but in edit mode, we still display, can happen with animation */
- if ((view_layer->basact->flag & BASE_VISIBLE) != 0 || (ob->mode & OB_MODE_EDIT)) {
- CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->basact);
- }
- }
-
- return 1;
- }
- else if (CTX_data_equals(member, "active_object")) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- if (view_layer->basact) {
- Object *ob = view_layer->basact->object;
- /* if hidden but in edit mode, we still display, can happen with animation */
- if ((view_layer->basact->flag & BASE_VISIBLE) != 0 || (ob->mode & OB_MODE_EDIT) != 0) {
- CTX_data_id_pointer_set(result, &ob->id);
- }
- }
-
- return 1;
- }
- else {
- return 0; /* not found */
- }
-
- return -1; /* found but not available */
+ /* fallback to the scene layer,
+ * allows duplicate and other object operators to run outside the 3d view */
+
+ if (CTX_data_dir(member)) {
+ CTX_data_dir_set(result, view3d_context_dir);
+ }
+ else if (CTX_data_equals(member, "active_base")) {
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ if (view_layer->basact) {
+ Object *ob = view_layer->basact->object;
+ /* if hidden but in edit mode, we still display, can happen with animation */
+ if ((view_layer->basact->flag & BASE_VISIBLE) != 0 || (ob->mode & OB_MODE_EDIT)) {
+ CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->basact);
+ }
+ }
+
+ return 1;
+ }
+ else if (CTX_data_equals(member, "active_object")) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ if (view_layer->basact) {
+ Object *ob = view_layer->basact->object;
+ /* if hidden but in edit mode, we still display, can happen with animation */
+ if ((view_layer->basact->flag & BASE_VISIBLE) != 0 || (ob->mode & OB_MODE_EDIT) != 0) {
+ CTX_data_id_pointer_set(result, &ob->id);
+ }
+ }
+
+ return 1;
+ }
+ else {
+ return 0; /* not found */
+ }
+
+ return -1; /* found but not available */
}
static void view3d_id_remap(ScrArea *sa, SpaceLink *slink, ID *old_id, ID *new_id)
{
- View3D *v3d;
- ARegion *ar;
- bool is_local = false;
-
- if (!ELEM(GS(old_id->name), ID_OB, ID_MA, ID_IM, ID_MC)) {
- return;
- }
-
- for (v3d = (View3D *)slink; v3d; v3d = v3d->localvd, is_local = true) {
- if ((ID *)v3d->camera == old_id) {
- 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;
- if (rv3d && (rv3d->persp == RV3D_CAMOB)) {
- rv3d->persp = RV3D_PERSP;
- }
- }
- }
- }
- }
-
- /* 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;
- /* Otherwise, bonename may remain valid...
- * We could be smart and check this, too? */
- if (new_id == NULL) {
- v3d->ob_centre_bone[0] = '\0';
- }
- }
- }
-
- if (is_local) {
- break;
- }
- }
+ View3D *v3d;
+ ARegion *ar;
+ bool is_local = false;
+
+ if (!ELEM(GS(old_id->name), ID_OB, ID_MA, ID_IM, ID_MC)) {
+ return;
+ }
+
+ for (v3d = (View3D *)slink; v3d; v3d = v3d->localvd, is_local = true) {
+ if ((ID *)v3d->camera == old_id) {
+ 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;
+ if (rv3d && (rv3d->persp == RV3D_CAMOB)) {
+ rv3d->persp = RV3D_PERSP;
+ }
+ }
+ }
+ }
+ }
+
+ /* 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;
+ /* Otherwise, bonename may remain valid...
+ * We could be smart and check this, too? */
+ if (new_id == NULL) {
+ v3d->ob_centre_bone[0] = '\0';
+ }
+ }
+ }
+
+ if (is_local) {
+ break;
+ }
+ }
}
/* only called once, from space/spacetypes.c */
void ED_spacetype_view3d(void)
{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype view3d");
- ARegionType *art;
-
- st->spaceid = SPACE_VIEW3D;
- strncpy(st->name, "View3D", BKE_ST_MAXNAME);
-
- st->new = view3d_new;
- st->free = view3d_free;
- st->init = view3d_init;
- st->listener = space_view3d_listener;
- st->refresh = space_view3d_refresh;
- st->duplicate = view3d_duplicate;
- st->operatortypes = view3d_operatortypes;
- st->keymap = view3d_keymap;
- st->dropboxes = view3d_dropboxes;
- st->gizmos = view3d_widgets;
- st->context = view3d_context;
- st->id_remap = view3d_id_remap;
-
- /* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype view3d main region");
- art->regionid = RGN_TYPE_WINDOW;
- art->keymapflag = ED_KEYMAP_GIZMO | ED_KEYMAP_TOOL | ED_KEYMAP_GPENCIL;
- art->draw = view3d_main_region_draw;
- art->init = view3d_main_region_init;
- art->exit = view3d_main_region_exit;
- art->free = view3d_main_region_free;
- art->duplicate = view3d_main_region_duplicate;
- art->listener = view3d_main_region_listener;
- art->message_subscribe = view3d_main_region_message_subscribe;
- art->cursor = view3d_main_region_cursor;
- art->lock = 1; /* can become flag, see BKE_spacedata_draw_locks */
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: listview/buttons */
- art = MEM_callocN(sizeof(ARegionType), "spacetype view3d buttons region");
- art->regionid = RGN_TYPE_UI;
- art->prefsizex = 180; /* XXX */
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
- art->listener = view3d_buttons_region_listener;
- art->init = view3d_buttons_region_init;
- art->draw = view3d_buttons_region_draw;
- BLI_addhead(&st->regiontypes, art);
-
- view3d_buttons_register(art);
-
- /* regions: tool(bar) */
- art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region");
- art->regionid = RGN_TYPE_TOOLS;
- art->prefsizex = 58; /* XXX */
- art->prefsizey = 50; /* XXX */
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
- art->listener = view3d_buttons_region_listener;
- art->message_subscribe = ED_region_generic_tools_region_message_subscribe;
- art->snap_size = ED_region_generic_tools_region_snap_size;
- art->init = view3d_tools_region_init;
- art->draw = view3d_tools_region_draw;
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype view3d header region");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
- art->listener = view3d_header_region_listener;
- art->init = view3d_header_region_init;
- art->draw = view3d_header_region_draw;
- art->message_subscribe = view3d_header_region_message_subscribe;
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: hud */
- art = ED_area_type_hud(st->spaceid);
- BLI_addhead(&st->regiontypes, art);
-
- BKE_spacetype_register(st);
+ SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype view3d");
+ ARegionType *art;
+
+ st->spaceid = SPACE_VIEW3D;
+ strncpy(st->name, "View3D", BKE_ST_MAXNAME);
+
+ st->new = view3d_new;
+ st->free = view3d_free;
+ st->init = view3d_init;
+ st->listener = space_view3d_listener;
+ st->refresh = space_view3d_refresh;
+ st->duplicate = view3d_duplicate;
+ st->operatortypes = view3d_operatortypes;
+ st->keymap = view3d_keymap;
+ st->dropboxes = view3d_dropboxes;
+ st->gizmos = view3d_widgets;
+ st->context = view3d_context;
+ st->id_remap = view3d_id_remap;
+
+ /* regions: main window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype view3d main region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->keymapflag = ED_KEYMAP_GIZMO | ED_KEYMAP_TOOL | ED_KEYMAP_GPENCIL;
+ art->draw = view3d_main_region_draw;
+ art->init = view3d_main_region_init;
+ art->exit = view3d_main_region_exit;
+ art->free = view3d_main_region_free;
+ art->duplicate = view3d_main_region_duplicate;
+ art->listener = view3d_main_region_listener;
+ art->message_subscribe = view3d_main_region_message_subscribe;
+ art->cursor = view3d_main_region_cursor;
+ art->lock = 1; /* can become flag, see BKE_spacedata_draw_locks */
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: listview/buttons */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype view3d buttons region");
+ art->regionid = RGN_TYPE_UI;
+ art->prefsizex = 180; /* XXX */
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
+ art->listener = view3d_buttons_region_listener;
+ art->init = view3d_buttons_region_init;
+ art->draw = view3d_buttons_region_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ view3d_buttons_register(art);
+
+ /* regions: tool(bar) */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region");
+ art->regionid = RGN_TYPE_TOOLS;
+ art->prefsizex = 58; /* XXX */
+ art->prefsizey = 50; /* XXX */
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
+ art->listener = view3d_buttons_region_listener;
+ art->message_subscribe = ED_region_generic_tools_region_message_subscribe;
+ art->snap_size = ED_region_generic_tools_region_snap_size;
+ art->init = view3d_tools_region_init;
+ art->draw = view3d_tools_region_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype view3d header region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = HEADERY;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
+ art->listener = view3d_header_region_listener;
+ art->init = view3d_header_region_init;
+ art->draw = view3d_header_region_draw;
+ art->message_subscribe = view3d_header_region_message_subscribe;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: hud */
+ art = ED_area_type_hud(st->spaceid);
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index ca30e3d3b01..abe36b1d563 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -21,7 +21,6 @@
* \ingroup spview3d
*/
-
#include <string.h>
#include <stdio.h>
#include <math.h>
@@ -70,49 +69,47 @@
#include "UI_interface.h"
#include "UI_resources.h"
-#include "view3d_intern.h" /* own include */
-
+#include "view3d_intern.h" /* own include */
/* ******************* view3d space & buttons ************** */
enum {
- B_REDR = 2,
- B_TRANSFORM_PANEL_MEDIAN = 1008,
- B_TRANSFORM_PANEL_DIMS = 1009,
+ B_REDR = 2,
+ B_TRANSFORM_PANEL_MEDIAN = 1008,
+ B_TRANSFORM_PANEL_DIMS = 1009,
};
/* All must start w/ location */
typedef struct {
- float location[3];
+ float location[3];
} TransformMedian_Generic;
typedef struct {
- float location[3], bv_weight, be_weight, skin[2], crease;
+ float location[3], bv_weight, be_weight, skin[2], crease;
} TransformMedian_Mesh;
typedef struct {
- float location[3], weight, b_weight, radius, tilt;
+ float location[3], weight, b_weight, radius, tilt;
} TransformMedian_Curve;
typedef struct {
- float location[3], weight;
+ float location[3], weight;
} TransformMedian_Lattice;
-
typedef union {
- TransformMedian_Generic generic;
- TransformMedian_Mesh mesh;
- TransformMedian_Curve curve;
- TransformMedian_Lattice lattice;
+ TransformMedian_Generic generic;
+ TransformMedian_Mesh mesh;
+ TransformMedian_Curve curve;
+ TransformMedian_Lattice lattice;
} TransformMedian;
/* temporary struct for storing transform properties */
typedef struct {
- float ob_dims_orig[3];
- float ob_dims[3];
- /* Floats only (treated as an array). */
- TransformMedian ve_median, median;
+ float ob_dims_orig[3];
+ float ob_dims[3];
+ /* Floats only (treated as an array). */
+ TransformMedian ve_median, median;
} TransformProperties;
#define TRANSFORM_MEDIAN_ARRAY_LEN (sizeof(TransformMedian) / sizeof(float))
@@ -124,30 +121,30 @@ typedef struct {
*/
static float compute_scale_factor(const float ve_median, const float median)
{
- if (ve_median <= 0.0f) {
- return 0.0f;
- }
- else if (ve_median >= 1.0f) {
- return 1.0f;
- }
- else {
- /* Scale value to target median. */
- float median_new = ve_median;
- float median_orig = ve_median - median; /* Previous median value. */
-
- /* In case of floating point error. */
- CLAMP(median_orig, 0.0f, 1.0f);
- CLAMP(median_new, 0.0f, 1.0f);
-
- if (median_new <= median_orig) {
- /* Scale down. */
- return median_new / median_orig;
- }
- else {
- /* Scale up, negative to indicate it... */
- return -(1.0f - median_new) / (1.0f - median_orig);
- }
- }
+ if (ve_median <= 0.0f) {
+ return 0.0f;
+ }
+ else if (ve_median >= 1.0f) {
+ return 1.0f;
+ }
+ else {
+ /* Scale value to target median. */
+ float median_new = ve_median;
+ float median_orig = ve_median - median; /* Previous median value. */
+
+ /* In case of floating point error. */
+ CLAMP(median_orig, 0.0f, 1.0f);
+ CLAMP(median_new, 0.0f, 1.0f);
+
+ if (median_new <= median_orig) {
+ /* Scale down. */
+ return median_new / median_orig;
+ }
+ else {
+ /* Scale up, negative to indicate it... */
+ return -(1.0f - median_new) / (1.0f - median_orig);
+ }
+ }
}
/* Apply helpers.
@@ -156,1167 +153,1531 @@ static float compute_scale_factor(const float ve_median, const float median)
*/
static void apply_raw_diff(float *val, const int tot, const float ve_median, const float median)
{
- *val = (tot == 1) ? ve_median : (*val + median);
+ *val = (tot == 1) ? ve_median : (*val + median);
}
-static void apply_raw_diff_v3(float val[3], const int tot, const float ve_median[3], const float median[3])
+static void apply_raw_diff_v3(float val[3],
+ const int tot,
+ const float ve_median[3],
+ const float median[3])
{
- if (tot == 1) {
- copy_v3_v3(val, ve_median);
- }
- else {
- add_v3_v3(val, median);
- }
+ if (tot == 1) {
+ copy_v3_v3(val, ve_median);
+ }
+ else {
+ add_v3_v3(val, median);
+ }
}
-static void apply_scale_factor(float *val, const int tot, const float ve_median, const float median, const float sca)
+static void apply_scale_factor(
+ float *val, const int tot, const float ve_median, const float median, const float sca)
{
- if (tot == 1 || ve_median == median) {
- *val = ve_median;
- }
- else {
- *val *= sca;
- }
+ if (tot == 1 || ve_median == median) {
+ *val = ve_median;
+ }
+ else {
+ *val *= sca;
+ }
}
-static void apply_scale_factor_clamp(float *val, const int tot, const float ve_median, const float sca)
+static void apply_scale_factor_clamp(float *val,
+ const int tot,
+ const float ve_median,
+ const float sca)
{
- if (tot == 1) {
- *val = ve_median;
- CLAMP(*val, 0.0f, 1.0f);
- }
- else if (ELEM(sca, 0.0f, 1.0f)) {
- *val = sca;
- }
- else {
- *val = (sca > 0.0f) ? (*val * sca) : (1.0f + ((1.0f - *val) * sca));
- CLAMP(*val, 0.0f, 1.0f);
- }
+ if (tot == 1) {
+ *val = ve_median;
+ CLAMP(*val, 0.0f, 1.0f);
+ }
+ else if (ELEM(sca, 0.0f, 1.0f)) {
+ *val = sca;
+ }
+ else {
+ *val = (sca > 0.0f) ? (*val * sca) : (1.0f + ((1.0f - *val) * sca));
+ CLAMP(*val, 0.0f, 1.0f);
+ }
}
static TransformProperties *v3d_transform_props_ensure(View3D *v3d)
{
- if (v3d->runtime.properties_storage == NULL) {
- v3d->runtime.properties_storage = MEM_callocN(sizeof(TransformProperties), "TransformProperties");
- }
- return v3d->runtime.properties_storage;
+ if (v3d->runtime.properties_storage == NULL) {
+ v3d->runtime.properties_storage = MEM_callocN(sizeof(TransformProperties),
+ "TransformProperties");
+ }
+ return v3d->runtime.properties_storage;
}
/* is used for both read and write... */
static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float lim)
{
- uiBlock *block = (layout) ? uiLayoutAbsoluteBlock(layout) : NULL;
- TransformProperties *tfp = v3d_transform_props_ensure(v3d);
- TransformMedian median_basis, ve_median_basis;
- int tot, totedgedata, totcurvedata, totlattdata, totcurvebweight;
- bool has_meshdata = false;
- bool has_skinradius = false;
- PointerRNA data_ptr;
-
- copy_vn_fl((float *)&median_basis, TRANSFORM_MEDIAN_ARRAY_LEN, 0.0f);
- tot = totedgedata = totcurvedata = totlattdata = totcurvebweight = 0;
-
- if (ob->type == OB_MESH) {
- TransformMedian_Mesh *median = &median_basis.mesh;
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- BMesh *bm = em->bm;
- BMVert *eve;
- BMEdge *eed;
- BMIter iter;
-
- const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
- const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
- const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
- const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
-
- has_skinradius = (cd_vert_skin_offset != -1);
-
- if (bm->totvertsel) {
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- tot++;
- add_v3_v3(median->location, eve->co);
-
- if (cd_vert_bweight_offset != -1) {
- median->bv_weight += BM_ELEM_CD_GET_FLOAT(eve, cd_vert_bweight_offset);
- }
-
- if (has_skinradius) {
- MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset);
- add_v2_v2(median->skin, vs->radius); /* Third val not used currently. */
- }
- }
- }
- }
-
- if ((cd_edge_bweight_offset != -1) || (cd_edge_crease_offset != -1)) {
- if (bm->totedgesel) {
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- if (cd_edge_bweight_offset != -1) {
- median->be_weight += BM_ELEM_CD_GET_FLOAT(eed, cd_edge_bweight_offset);
- }
-
- if (cd_edge_crease_offset != -1) {
- median->crease += BM_ELEM_CD_GET_FLOAT(eed, cd_edge_crease_offset);
- }
-
- totedgedata++;
- }
- }
- }
- }
- else {
- totedgedata = bm->totedgesel;
- }
-
- has_meshdata = (tot || totedgedata);
- }
- else if (ob->type == OB_CURVE || ob->type == OB_SURF) {
- TransformMedian_Curve *median = &median_basis.curve;
- Curve *cu = ob->data;
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- int a;
- ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- StructRNA *seltype = NULL;
- void *selp = NULL;
-
- nu = nurbs->first;
- while (nu) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (bezt->f2 & SELECT) {
- add_v3_v3(median->location, bezt->vec[1]);
- tot++;
- median->weight += bezt->weight;
- median->radius += bezt->radius;
- median->tilt += bezt->tilt;
- if (!totcurvedata) { /* I.e. first time... */
- selp = bezt;
- seltype = &RNA_BezierSplinePoint;
- }
- totcurvedata++;
- }
- else {
- if (bezt->f1 & SELECT) {
- add_v3_v3(median->location, bezt->vec[0]);
- tot++;
- }
- if (bezt->f3 & SELECT) {
- add_v3_v3(median->location, bezt->vec[2]);
- tot++;
- }
- }
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (bp->f1 & SELECT) {
- add_v3_v3(median->location, bp->vec);
- median->b_weight += bp->vec[3];
- totcurvebweight++;
- tot++;
- median->weight += bp->weight;
- median->radius += bp->radius;
- median->tilt += bp->tilt;
- if (!totcurvedata) { /* I.e. first time... */
- selp = bp;
- seltype = &RNA_SplinePoint;
- }
- totcurvedata++;
- }
- bp++;
- }
- }
- nu = nu->next;
- }
-
- if (totcurvedata == 1) {
- RNA_pointer_create(&cu->id, seltype, selp, &data_ptr);
- }
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = ob->data;
- TransformMedian_Lattice *median = &median_basis.lattice;
- BPoint *bp;
- int a;
- StructRNA *seltype = NULL;
- void *selp = NULL;
-
- a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
- bp = lt->editlatt->latt->def;
- while (a--) {
- if (bp->f1 & SELECT) {
- add_v3_v3(median->location, bp->vec);
- tot++;
- median->weight += bp->weight;
- if (!totlattdata) { /* I.e. first time... */
- selp = bp;
- seltype = &RNA_LatticePoint;
- }
- totlattdata++;
- }
- bp++;
- }
-
- if (totlattdata == 1) {
- RNA_pointer_create(&lt->id, seltype, selp, &data_ptr);
- }
- }
-
- if (tot == 0) {
- uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Nothing selected"), 0, 130, 200, 20, NULL, 0, 0, 0, 0, "");
- return;
- }
-
- /* Location, X/Y/Z */
- mul_v3_fl(median_basis.generic.location, 1.0f / (float)tot);
- if (v3d->flag & V3D_GLOBAL_STATS) {
- mul_m4_v3(ob->obmat, median_basis.generic.location);
- }
-
- if (has_meshdata) {
- TransformMedian_Mesh *median = &median_basis.mesh;
- if (totedgedata) {
- median->crease /= (float)totedgedata;
- median->be_weight /= (float)totedgedata;
- }
- if (tot) {
- median->bv_weight /= (float)tot;
- if (has_skinradius) {
- median->skin[0] /= (float)tot;
- median->skin[1] /= (float)tot;
- }
- }
- }
- else if (totcurvedata) {
- TransformMedian_Curve *median = &median_basis.curve;
- if (totcurvebweight) {
- median->b_weight /= (float)totcurvebweight;
- }
- median->weight /= (float)totcurvedata;
- median->radius /= (float)totcurvedata;
- median->tilt /= (float)totcurvedata;
- }
- else if (totlattdata) {
- TransformMedian_Lattice *median = &median_basis.lattice;
- median->weight /= (float)totlattdata;
- }
-
- if (block) { /* buttons */
- uiBut *but;
- int yi = 200;
- const float tilt_limit = DEG2RADF(21600.0f);
- const int butw = 200;
- const int buth = 20 * UI_DPI_FAC;
- const int but_margin = 2;
- const char *c;
-
- memcpy(&tfp->ve_median, &median_basis, sizeof(tfp->ve_median));
-
- UI_block_align_begin(block);
- if (tot == 1) {
- if (totcurvedata) {
- /* Curve */
- c = IFACE_("Control Point:");
- }
- else {
- /* Mesh or lattice */
- c = IFACE_("Vertex:");
- }
- }
- else {
- c = IFACE_("Median:");
- }
- uiDefBut(block, UI_BTYPE_LABEL, 0, c, 0, yi -= buth, butw, buth, NULL, 0, 0, 0, 0, "");
-
- UI_block_align_begin(block);
-
- /* Should be no need to translate these. */
- but = uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, IFACE_("X:"), 0, yi -= buth, butw, buth,
- &tfp->ve_median.generic.location[0], -lim, lim, 10, RNA_TRANSLATION_PREC_DEFAULT, "");
- UI_but_unit_type_set(but, PROP_UNIT_LENGTH);
- but = uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, IFACE_("Y:"), 0, yi -= buth, butw, buth,
- &tfp->ve_median.generic.location[1], -lim, lim, 10, RNA_TRANSLATION_PREC_DEFAULT, "");
- UI_but_unit_type_set(but, PROP_UNIT_LENGTH);
- but = uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, IFACE_("Z:"), 0, yi -= buth, butw, buth,
- &tfp->ve_median.generic.location[2], -lim, lim, 10, RNA_TRANSLATION_PREC_DEFAULT, "");
- UI_but_unit_type_set(but, PROP_UNIT_LENGTH);
-
- if (totcurvebweight == tot) {
- uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, IFACE_("W:"), 0, yi -= buth, butw, buth,
- &(tfp->ve_median.curve.b_weight), 0.01, 100.0, 1, 3, "");
- }
-
- UI_block_align_begin(block);
- uiDefButBitS(block, UI_BTYPE_TOGGLE, V3D_GLOBAL_STATS, B_REDR, IFACE_("Global"),
- 0, yi -= buth + but_margin, 100, buth,
- &v3d->flag, 0, 0, 0, 0, TIP_("Displays global values"));
- uiDefButBitS(block, UI_BTYPE_TOGGLE_N, V3D_GLOBAL_STATS, B_REDR, IFACE_("Local"),
- 100, yi, 100, buth,
- &v3d->flag, 0, 0, 0, 0, TIP_("Displays local values"));
- UI_block_align_end(block);
-
- /* Meshes... */
- if (has_meshdata) {
- TransformMedian_Mesh *ve_median = &tfp->ve_median.mesh;
- if (tot) {
- uiDefBut(block, UI_BTYPE_LABEL, 0, tot == 1 ? IFACE_("Vertex Data:") : IFACE_("Vertices Data:"),
- 0, yi -= buth + but_margin, butw, buth, NULL, 0.0, 0.0, 0, 0, "");
- /* customdata layer added on demand */
- uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN,
- tot == 1 ? IFACE_("Bevel Weight:") : IFACE_("Mean Bevel Weight:"),
- 0, yi -= buth + but_margin, butw, buth,
- &ve_median->bv_weight, 0.0, 1.0, 1, 2, TIP_("Vertex weight used by Bevel modifier"));
- }
- if (has_skinradius) {
- UI_block_align_begin(block);
- uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN,
- tot == 1 ? IFACE_("Radius X:") : IFACE_("Mean Radius X:"),
- 0, yi -= buth + but_margin, butw, buth,
- &ve_median->skin[0], 0.0, 100.0, 1, 3, TIP_("X radius used by Skin modifier"));
- uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN,
- tot == 1 ? IFACE_("Radius Y:") : IFACE_("Mean Radius Y:"),
- 0, yi -= buth + but_margin, butw, buth,
- &ve_median->skin[1], 0.0, 100.0, 1, 3, TIP_("Y radius used by Skin modifier"));
- UI_block_align_end(block);
- }
- if (totedgedata) {
- uiDefBut(block, UI_BTYPE_LABEL, 0, totedgedata == 1 ? IFACE_("Edge Data:") : IFACE_("Edges Data:"),
- 0, yi -= buth + but_margin, butw, buth, NULL, 0.0, 0.0, 0, 0, "");
- /* customdata layer added on demand */
- uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN,
- totedgedata == 1 ? IFACE_("Bevel Weight:") : IFACE_("Mean Bevel Weight:"),
- 0, yi -= buth + but_margin, butw, buth,
- &ve_median->be_weight, 0.0, 1.0, 1, 2, TIP_("Edge weight used by Bevel modifier"));
- /* customdata layer added on demand */
- uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN,
- totedgedata == 1 ? IFACE_("Crease:") : IFACE_("Mean Crease:"),
- 0, yi -= buth + but_margin, butw, buth,
- &ve_median->crease, 0.0, 1.0, 1, 2, TIP_("Weight used by the Subdivision Surface modifier"));
- }
- }
- /* Curve... */
- else if (totcurvedata) {
- TransformMedian_Curve *ve_median = &tfp->ve_median.curve;
- if (totcurvedata == 1) {
- uiDefButR(block, UI_BTYPE_NUM, 0, IFACE_("Weight:"), 0, yi -= buth + but_margin, butw, buth,
- &data_ptr, "weight_softbody", 0, 0.0, 1.0, 1, 3, NULL);
- uiDefButR(block, UI_BTYPE_NUM, 0, IFACE_("Radius:"), 0, yi -= buth + but_margin, butw, buth,
- &data_ptr, "radius", 0, 0.0, 100.0, 1, 3, NULL);
- uiDefButR(block, UI_BTYPE_NUM, 0, IFACE_("Tilt:"), 0, yi -= buth + but_margin, butw, buth,
- &data_ptr, "tilt", 0, -tilt_limit, tilt_limit, 1, 3, NULL);
- }
- else if (totcurvedata > 1) {
- uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, IFACE_("Mean Weight:"),
- 0, yi -= buth + but_margin, butw, buth,
- &ve_median->weight, 0.0, 1.0, 1, 3, TIP_("Weight used for Soft Body Goal"));
- uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, IFACE_("Mean Radius:"),
- 0, yi -= buth + but_margin, butw, buth,
- &ve_median->radius, 0.0, 100.0, 1, 3, TIP_("Radius of curve control points"));
- but = uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, IFACE_("Mean Tilt:"),
- 0, yi -= buth + but_margin, butw, buth,
- &ve_median->tilt, -tilt_limit, tilt_limit, 1, 3,
- TIP_("Tilt of curve control points"));
- UI_but_unit_type_set(but, PROP_UNIT_ROTATION);
- }
- }
- /* Lattice... */
- else if (totlattdata) {
- TransformMedian_Lattice *ve_median = &tfp->ve_median.lattice;
- if (totlattdata == 1) {
- uiDefButR(block, UI_BTYPE_NUM, 0, IFACE_("Weight:"), 0, yi -= buth + but_margin, butw, buth,
- &data_ptr, "weight_softbody", 0, 0.0, 1.0, 1, 3, NULL);
- }
- else if (totlattdata > 1) {
- uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, IFACE_("Mean Weight:"),
- 0, yi -= buth + but_margin, butw, buth,
- &ve_median->weight, 0.0, 1.0, 1, 3, TIP_("Weight used for Soft Body Goal"));
- }
- }
-
- UI_block_align_end(block);
- }
- else { /* apply */
- memcpy(&ve_median_basis, &tfp->ve_median, sizeof(tfp->ve_median));
-
- if (v3d->flag & V3D_GLOBAL_STATS) {
- invert_m4_m4(ob->imat, ob->obmat);
- mul_m4_v3(ob->imat, median_basis.generic.location);
- mul_m4_v3(ob->imat, ve_median_basis.generic.location);
- }
- sub_vn_vnvn(
- (float *)&median_basis,
- (float *)&ve_median_basis,
- (float *)&median_basis,
- TRANSFORM_MEDIAN_ARRAY_LEN);
-
- /* Note with a single element selected, we always do. */
- const bool apply_vcos = (tot == 1) || (len_squared_v3(median_basis.generic.location) != 0.0f);
-
- if ((ob->type == OB_MESH) &&
- (apply_vcos || median_basis.mesh.bv_weight || median_basis.mesh.skin[0] || median_basis.mesh.skin[1] ||
- median_basis.mesh.be_weight || median_basis.mesh.crease))
- {
- const TransformMedian_Mesh *median = &median_basis.mesh, *ve_median = &ve_median_basis.mesh;
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- BMesh *bm = em->bm;
- BMIter iter;
- BMVert *eve;
- BMEdge *eed;
-
- int cd_vert_bweight_offset = -1;
- int cd_vert_skin_offset = -1;
- int cd_edge_bweight_offset = -1;
- int cd_edge_crease_offset = -1;
-
- float scale_bv_weight = 1.0f;
- float scale_skin[2] = {1.0f, 1.0f};
- float scale_be_weight = 1.0f;
- float scale_crease = 1.0f;
-
- /* Vertices */
-
- if (apply_vcos || median->bv_weight || median->skin[0] || median->skin[1]) {
- if (median->bv_weight) {
- BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_VERT_BWEIGHT);
- cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
- BLI_assert(cd_vert_bweight_offset != -1);
-
- scale_bv_weight = compute_scale_factor(ve_median->bv_weight, median->bv_weight);
- }
-
- for (int i = 0; i < 2; i++) {
- if (median->skin[i]) {
- cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
- BLI_assert(cd_vert_skin_offset != -1);
-
- if (ve_median->skin[i] != median->skin[i]) {
- scale_skin[i] = ve_median->skin[i] / (ve_median->skin[i] - median->skin[i]);
- }
- }
- }
-
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- if (apply_vcos) {
- apply_raw_diff_v3(eve->co, tot, ve_median->location, median->location);
- }
-
- if (cd_vert_bweight_offset != -1) {
- float *b_weight = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset);
- apply_scale_factor_clamp(b_weight, tot, ve_median->bv_weight, scale_bv_weight);
- }
-
- if (cd_vert_skin_offset != -1) {
- MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset);
-
- /* That one is not clamped to [0.0, 1.0]. */
- for (int i = 0; i < 2; i++) {
- if (median->skin[i] != 0.0f) {
- apply_scale_factor(
- &vs->radius[i], tot, ve_median->skin[i], median->skin[i],
- scale_skin[i]);
- }
- }
- }
- }
- }
- }
-
- if (apply_vcos) {
- EDBM_mesh_normals_update(em);
- }
-
- /* Edges */
-
- if (median->be_weight || median->crease) {
- if (median->be_weight) {
- BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_BWEIGHT);
- cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
- BLI_assert(cd_edge_bweight_offset != -1);
-
- scale_be_weight = compute_scale_factor(ve_median->be_weight, median->be_weight);
- }
-
- if (median->crease) {
- BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_CREASE);
- cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
- BLI_assert(cd_edge_crease_offset != -1);
-
- scale_crease = compute_scale_factor(ve_median->crease, median->crease);
- }
-
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- if (median->be_weight != 0.0f) {
- float *b_weight = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_bweight_offset);
- apply_scale_factor_clamp(b_weight, tot, ve_median->be_weight, scale_be_weight);
- }
-
- if (median->crease != 0.0f) {
- float *crease = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_crease_offset);
- apply_scale_factor_clamp(crease, tot, ve_median->crease, scale_crease);
- }
- }
- }
- }
- }
- else if (ELEM(ob->type, OB_CURVE, OB_SURF) &&
- (apply_vcos ||
- median_basis.curve.b_weight ||
- median_basis.curve.weight ||
- median_basis.curve.radius ||
- median_basis.curve.tilt))
- {
- const TransformMedian_Curve *median = &median_basis.curve, *ve_median = &ve_median_basis.curve;
- Curve *cu = ob->data;
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- int a;
- ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- const float scale_w = compute_scale_factor(ve_median->weight, median->weight);
-
- nu = nurbs->first;
- while (nu) {
- if (nu->type == CU_BEZIER) {
- for (a = nu->pntsu, bezt = nu->bezt; a--; bezt++) {
- if (bezt->f2 & SELECT) {
- if (apply_vcos) {
- /* Here we always have to use the diff... :/
- * Cannot avoid some glitches when going e.g. from 3 to 0.0001 (see T37327),
- * unless we use doubles.
- */
- add_v3_v3(bezt->vec[0], median->location);
- add_v3_v3(bezt->vec[1], median->location);
- add_v3_v3(bezt->vec[2], median->location);
- }
- if (median->weight) {
- apply_scale_factor_clamp(&bezt->weight, tot, ve_median->weight, scale_w);
- }
- if (median->radius) {
- apply_raw_diff(&bezt->radius, tot, ve_median->radius, median->radius);
- }
- if (median->tilt) {
- apply_raw_diff(&bezt->tilt, tot, ve_median->tilt, median->tilt);
- }
- }
- else if (apply_vcos) {
- /* Handles can only have their coordinates changed here. */
- if (bezt->f1 & SELECT) {
- apply_raw_diff_v3(bezt->vec[0], tot, ve_median->location, median->location);
- }
- if (bezt->f3 & SELECT) {
- apply_raw_diff_v3(bezt->vec[2], tot, ve_median->location, median->location);
- }
- }
- }
- }
- else {
- for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a--; bp++) {
- if (bp->f1 & SELECT) {
- if (apply_vcos) {
- apply_raw_diff_v3(bp->vec, tot, ve_median->location, median->location);
- }
- if (median->b_weight) {
- apply_raw_diff(&bp->vec[3], tot, ve_median->b_weight, median->b_weight);
- }
- if (median->weight) {
- apply_scale_factor_clamp(&bp->weight, tot, ve_median->weight, scale_w);
- }
- if (median->radius) {
- apply_raw_diff(&bp->radius, tot, ve_median->radius, median->radius);
- }
- if (median->tilt) {
- apply_raw_diff(&bp->tilt, tot, ve_median->tilt, median->tilt);
- }
- }
- }
- }
- BKE_nurb_test_2d(nu);
- BKE_nurb_handles_test(nu, true); /* test for bezier too */
-
- nu = nu->next;
- }
- }
- else if ((ob->type == OB_LATTICE) &&
- (apply_vcos || median_basis.lattice.weight))
- {
- const TransformMedian_Lattice *median = &median_basis.lattice, *ve_median = &ve_median_basis.lattice;
- Lattice *lt = ob->data;
- BPoint *bp;
- int a;
- const float scale_w = compute_scale_factor(ve_median->weight, median->weight);
-
- a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
- bp = lt->editlatt->latt->def;
- while (a--) {
- if (bp->f1 & SELECT) {
- if (apply_vcos) {
- apply_raw_diff_v3(bp->vec, tot, ve_median->location, median->location);
- }
- if (median->weight) {
- apply_scale_factor_clamp(&bp->weight, tot, ve_median->weight, scale_w);
- }
- }
- bp++;
- }
- }
-
-/* ED_undo_push(C, "Transform properties"); */
- }
+ uiBlock *block = (layout) ? uiLayoutAbsoluteBlock(layout) : NULL;
+ TransformProperties *tfp = v3d_transform_props_ensure(v3d);
+ TransformMedian median_basis, ve_median_basis;
+ int tot, totedgedata, totcurvedata, totlattdata, totcurvebweight;
+ bool has_meshdata = false;
+ bool has_skinradius = false;
+ PointerRNA data_ptr;
+
+ copy_vn_fl((float *)&median_basis, TRANSFORM_MEDIAN_ARRAY_LEN, 0.0f);
+ tot = totedgedata = totcurvedata = totlattdata = totcurvebweight = 0;
+
+ if (ob->type == OB_MESH) {
+ TransformMedian_Mesh *median = &median_basis.mesh;
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ BMesh *bm = em->bm;
+ BMVert *eve;
+ BMEdge *eed;
+ BMIter iter;
+
+ const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
+ const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
+ const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
+ const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
+
+ has_skinradius = (cd_vert_skin_offset != -1);
+
+ if (bm->totvertsel) {
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ tot++;
+ add_v3_v3(median->location, eve->co);
+
+ if (cd_vert_bweight_offset != -1) {
+ median->bv_weight += BM_ELEM_CD_GET_FLOAT(eve, cd_vert_bweight_offset);
+ }
+
+ if (has_skinradius) {
+ MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset);
+ add_v2_v2(median->skin, vs->radius); /* Third val not used currently. */
+ }
+ }
+ }
+ }
+
+ if ((cd_edge_bweight_offset != -1) || (cd_edge_crease_offset != -1)) {
+ if (bm->totedgesel) {
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ if (cd_edge_bweight_offset != -1) {
+ median->be_weight += BM_ELEM_CD_GET_FLOAT(eed, cd_edge_bweight_offset);
+ }
+
+ if (cd_edge_crease_offset != -1) {
+ median->crease += BM_ELEM_CD_GET_FLOAT(eed, cd_edge_crease_offset);
+ }
+
+ totedgedata++;
+ }
+ }
+ }
+ }
+ else {
+ totedgedata = bm->totedgesel;
+ }
+
+ has_meshdata = (tot || totedgedata);
+ }
+ else if (ob->type == OB_CURVE || ob->type == OB_SURF) {
+ TransformMedian_Curve *median = &median_basis.curve;
+ Curve *cu = ob->data;
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+ StructRNA *seltype = NULL;
+ void *selp = NULL;
+
+ nu = nurbs->first;
+ while (nu) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ if (bezt->f2 & SELECT) {
+ add_v3_v3(median->location, bezt->vec[1]);
+ tot++;
+ median->weight += bezt->weight;
+ median->radius += bezt->radius;
+ median->tilt += bezt->tilt;
+ if (!totcurvedata) { /* I.e. first time... */
+ selp = bezt;
+ seltype = &RNA_BezierSplinePoint;
+ }
+ totcurvedata++;
+ }
+ else {
+ if (bezt->f1 & SELECT) {
+ add_v3_v3(median->location, bezt->vec[0]);
+ tot++;
+ }
+ if (bezt->f3 & SELECT) {
+ add_v3_v3(median->location, bezt->vec[2]);
+ tot++;
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ add_v3_v3(median->location, bp->vec);
+ median->b_weight += bp->vec[3];
+ totcurvebweight++;
+ tot++;
+ median->weight += bp->weight;
+ median->radius += bp->radius;
+ median->tilt += bp->tilt;
+ if (!totcurvedata) { /* I.e. first time... */
+ selp = bp;
+ seltype = &RNA_SplinePoint;
+ }
+ totcurvedata++;
+ }
+ bp++;
+ }
+ }
+ nu = nu->next;
+ }
+
+ if (totcurvedata == 1) {
+ RNA_pointer_create(&cu->id, seltype, selp, &data_ptr);
+ }
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = ob->data;
+ TransformMedian_Lattice *median = &median_basis.lattice;
+ BPoint *bp;
+ int a;
+ StructRNA *seltype = NULL;
+ void *selp = NULL;
+
+ a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
+ bp = lt->editlatt->latt->def;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ add_v3_v3(median->location, bp->vec);
+ tot++;
+ median->weight += bp->weight;
+ if (!totlattdata) { /* I.e. first time... */
+ selp = bp;
+ seltype = &RNA_LatticePoint;
+ }
+ totlattdata++;
+ }
+ bp++;
+ }
+
+ if (totlattdata == 1) {
+ RNA_pointer_create(&lt->id, seltype, selp, &data_ptr);
+ }
+ }
+
+ if (tot == 0) {
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ IFACE_("Nothing selected"),
+ 0,
+ 130,
+ 200,
+ 20,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ return;
+ }
+
+ /* Location, X/Y/Z */
+ mul_v3_fl(median_basis.generic.location, 1.0f / (float)tot);
+ if (v3d->flag & V3D_GLOBAL_STATS) {
+ mul_m4_v3(ob->obmat, median_basis.generic.location);
+ }
+
+ if (has_meshdata) {
+ TransformMedian_Mesh *median = &median_basis.mesh;
+ if (totedgedata) {
+ median->crease /= (float)totedgedata;
+ median->be_weight /= (float)totedgedata;
+ }
+ if (tot) {
+ median->bv_weight /= (float)tot;
+ if (has_skinradius) {
+ median->skin[0] /= (float)tot;
+ median->skin[1] /= (float)tot;
+ }
+ }
+ }
+ else if (totcurvedata) {
+ TransformMedian_Curve *median = &median_basis.curve;
+ if (totcurvebweight) {
+ median->b_weight /= (float)totcurvebweight;
+ }
+ median->weight /= (float)totcurvedata;
+ median->radius /= (float)totcurvedata;
+ median->tilt /= (float)totcurvedata;
+ }
+ else if (totlattdata) {
+ TransformMedian_Lattice *median = &median_basis.lattice;
+ median->weight /= (float)totlattdata;
+ }
+
+ if (block) { /* buttons */
+ uiBut *but;
+ int yi = 200;
+ const float tilt_limit = DEG2RADF(21600.0f);
+ const int butw = 200;
+ const int buth = 20 * UI_DPI_FAC;
+ const int but_margin = 2;
+ const char *c;
+
+ memcpy(&tfp->ve_median, &median_basis, sizeof(tfp->ve_median));
+
+ UI_block_align_begin(block);
+ if (tot == 1) {
+ if (totcurvedata) {
+ /* Curve */
+ c = IFACE_("Control Point:");
+ }
+ else {
+ /* Mesh or lattice */
+ c = IFACE_("Vertex:");
+ }
+ }
+ else {
+ c = IFACE_("Median:");
+ }
+ uiDefBut(block, UI_BTYPE_LABEL, 0, c, 0, yi -= buth, butw, buth, NULL, 0, 0, 0, 0, "");
+
+ UI_block_align_begin(block);
+
+ /* Should be no need to translate these. */
+ but = uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_TRANSFORM_PANEL_MEDIAN,
+ IFACE_("X:"),
+ 0,
+ yi -= buth,
+ butw,
+ buth,
+ &tfp->ve_median.generic.location[0],
+ -lim,
+ lim,
+ 10,
+ RNA_TRANSLATION_PREC_DEFAULT,
+ "");
+ UI_but_unit_type_set(but, PROP_UNIT_LENGTH);
+ but = uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_TRANSFORM_PANEL_MEDIAN,
+ IFACE_("Y:"),
+ 0,
+ yi -= buth,
+ butw,
+ buth,
+ &tfp->ve_median.generic.location[1],
+ -lim,
+ lim,
+ 10,
+ RNA_TRANSLATION_PREC_DEFAULT,
+ "");
+ UI_but_unit_type_set(but, PROP_UNIT_LENGTH);
+ but = uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_TRANSFORM_PANEL_MEDIAN,
+ IFACE_("Z:"),
+ 0,
+ yi -= buth,
+ butw,
+ buth,
+ &tfp->ve_median.generic.location[2],
+ -lim,
+ lim,
+ 10,
+ RNA_TRANSLATION_PREC_DEFAULT,
+ "");
+ UI_but_unit_type_set(but, PROP_UNIT_LENGTH);
+
+ if (totcurvebweight == tot) {
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_TRANSFORM_PANEL_MEDIAN,
+ IFACE_("W:"),
+ 0,
+ yi -= buth,
+ butw,
+ buth,
+ &(tfp->ve_median.curve.b_weight),
+ 0.01,
+ 100.0,
+ 1,
+ 3,
+ "");
+ }
+
+ UI_block_align_begin(block);
+ uiDefButBitS(block,
+ UI_BTYPE_TOGGLE,
+ V3D_GLOBAL_STATS,
+ B_REDR,
+ IFACE_("Global"),
+ 0,
+ yi -= buth + but_margin,
+ 100,
+ buth,
+ &v3d->flag,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Displays global values"));
+ uiDefButBitS(block,
+ UI_BTYPE_TOGGLE_N,
+ V3D_GLOBAL_STATS,
+ B_REDR,
+ IFACE_("Local"),
+ 100,
+ yi,
+ 100,
+ buth,
+ &v3d->flag,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Displays local values"));
+ UI_block_align_end(block);
+
+ /* Meshes... */
+ if (has_meshdata) {
+ TransformMedian_Mesh *ve_median = &tfp->ve_median.mesh;
+ if (tot) {
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ tot == 1 ? IFACE_("Vertex Data:") : IFACE_("Vertices Data:"),
+ 0,
+ yi -= buth + but_margin,
+ butw,
+ buth,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ /* customdata layer added on demand */
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_TRANSFORM_PANEL_MEDIAN,
+ tot == 1 ? IFACE_("Bevel Weight:") : IFACE_("Mean Bevel Weight:"),
+ 0,
+ yi -= buth + but_margin,
+ butw,
+ buth,
+ &ve_median->bv_weight,
+ 0.0,
+ 1.0,
+ 1,
+ 2,
+ TIP_("Vertex weight used by Bevel modifier"));
+ }
+ if (has_skinradius) {
+ UI_block_align_begin(block);
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_TRANSFORM_PANEL_MEDIAN,
+ tot == 1 ? IFACE_("Radius X:") : IFACE_("Mean Radius X:"),
+ 0,
+ yi -= buth + but_margin,
+ butw,
+ buth,
+ &ve_median->skin[0],
+ 0.0,
+ 100.0,
+ 1,
+ 3,
+ TIP_("X radius used by Skin modifier"));
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_TRANSFORM_PANEL_MEDIAN,
+ tot == 1 ? IFACE_("Radius Y:") : IFACE_("Mean Radius Y:"),
+ 0,
+ yi -= buth + but_margin,
+ butw,
+ buth,
+ &ve_median->skin[1],
+ 0.0,
+ 100.0,
+ 1,
+ 3,
+ TIP_("Y radius used by Skin modifier"));
+ UI_block_align_end(block);
+ }
+ if (totedgedata) {
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ totedgedata == 1 ? IFACE_("Edge Data:") : IFACE_("Edges Data:"),
+ 0,
+ yi -= buth + but_margin,
+ butw,
+ buth,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ /* customdata layer added on demand */
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_TRANSFORM_PANEL_MEDIAN,
+ totedgedata == 1 ? IFACE_("Bevel Weight:") : IFACE_("Mean Bevel Weight:"),
+ 0,
+ yi -= buth + but_margin,
+ butw,
+ buth,
+ &ve_median->be_weight,
+ 0.0,
+ 1.0,
+ 1,
+ 2,
+ TIP_("Edge weight used by Bevel modifier"));
+ /* customdata layer added on demand */
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_TRANSFORM_PANEL_MEDIAN,
+ totedgedata == 1 ? IFACE_("Crease:") : IFACE_("Mean Crease:"),
+ 0,
+ yi -= buth + but_margin,
+ butw,
+ buth,
+ &ve_median->crease,
+ 0.0,
+ 1.0,
+ 1,
+ 2,
+ TIP_("Weight used by the Subdivision Surface modifier"));
+ }
+ }
+ /* Curve... */
+ else if (totcurvedata) {
+ TransformMedian_Curve *ve_median = &tfp->ve_median.curve;
+ if (totcurvedata == 1) {
+ uiDefButR(block,
+ UI_BTYPE_NUM,
+ 0,
+ IFACE_("Weight:"),
+ 0,
+ yi -= buth + but_margin,
+ butw,
+ buth,
+ &data_ptr,
+ "weight_softbody",
+ 0,
+ 0.0,
+ 1.0,
+ 1,
+ 3,
+ NULL);
+ uiDefButR(block,
+ UI_BTYPE_NUM,
+ 0,
+ IFACE_("Radius:"),
+ 0,
+ yi -= buth + but_margin,
+ butw,
+ buth,
+ &data_ptr,
+ "radius",
+ 0,
+ 0.0,
+ 100.0,
+ 1,
+ 3,
+ NULL);
+ uiDefButR(block,
+ UI_BTYPE_NUM,
+ 0,
+ IFACE_("Tilt:"),
+ 0,
+ yi -= buth + but_margin,
+ butw,
+ buth,
+ &data_ptr,
+ "tilt",
+ 0,
+ -tilt_limit,
+ tilt_limit,
+ 1,
+ 3,
+ NULL);
+ }
+ else if (totcurvedata > 1) {
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_TRANSFORM_PANEL_MEDIAN,
+ IFACE_("Mean Weight:"),
+ 0,
+ yi -= buth + but_margin,
+ butw,
+ buth,
+ &ve_median->weight,
+ 0.0,
+ 1.0,
+ 1,
+ 3,
+ TIP_("Weight used for Soft Body Goal"));
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_TRANSFORM_PANEL_MEDIAN,
+ IFACE_("Mean Radius:"),
+ 0,
+ yi -= buth + but_margin,
+ butw,
+ buth,
+ &ve_median->radius,
+ 0.0,
+ 100.0,
+ 1,
+ 3,
+ TIP_("Radius of curve control points"));
+ but = uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_TRANSFORM_PANEL_MEDIAN,
+ IFACE_("Mean Tilt:"),
+ 0,
+ yi -= buth + but_margin,
+ butw,
+ buth,
+ &ve_median->tilt,
+ -tilt_limit,
+ tilt_limit,
+ 1,
+ 3,
+ TIP_("Tilt of curve control points"));
+ UI_but_unit_type_set(but, PROP_UNIT_ROTATION);
+ }
+ }
+ /* Lattice... */
+ else if (totlattdata) {
+ TransformMedian_Lattice *ve_median = &tfp->ve_median.lattice;
+ if (totlattdata == 1) {
+ uiDefButR(block,
+ UI_BTYPE_NUM,
+ 0,
+ IFACE_("Weight:"),
+ 0,
+ yi -= buth + but_margin,
+ butw,
+ buth,
+ &data_ptr,
+ "weight_softbody",
+ 0,
+ 0.0,
+ 1.0,
+ 1,
+ 3,
+ NULL);
+ }
+ else if (totlattdata > 1) {
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_TRANSFORM_PANEL_MEDIAN,
+ IFACE_("Mean Weight:"),
+ 0,
+ yi -= buth + but_margin,
+ butw,
+ buth,
+ &ve_median->weight,
+ 0.0,
+ 1.0,
+ 1,
+ 3,
+ TIP_("Weight used for Soft Body Goal"));
+ }
+ }
+
+ UI_block_align_end(block);
+ }
+ else { /* apply */
+ memcpy(&ve_median_basis, &tfp->ve_median, sizeof(tfp->ve_median));
+
+ if (v3d->flag & V3D_GLOBAL_STATS) {
+ invert_m4_m4(ob->imat, ob->obmat);
+ mul_m4_v3(ob->imat, median_basis.generic.location);
+ mul_m4_v3(ob->imat, ve_median_basis.generic.location);
+ }
+ sub_vn_vnvn((float *)&median_basis,
+ (float *)&ve_median_basis,
+ (float *)&median_basis,
+ TRANSFORM_MEDIAN_ARRAY_LEN);
+
+ /* Note with a single element selected, we always do. */
+ const bool apply_vcos = (tot == 1) || (len_squared_v3(median_basis.generic.location) != 0.0f);
+
+ if ((ob->type == OB_MESH) &&
+ (apply_vcos || median_basis.mesh.bv_weight || median_basis.mesh.skin[0] ||
+ median_basis.mesh.skin[1] || median_basis.mesh.be_weight || median_basis.mesh.crease)) {
+ const TransformMedian_Mesh *median = &median_basis.mesh, *ve_median = &ve_median_basis.mesh;
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMVert *eve;
+ BMEdge *eed;
+
+ int cd_vert_bweight_offset = -1;
+ int cd_vert_skin_offset = -1;
+ int cd_edge_bweight_offset = -1;
+ int cd_edge_crease_offset = -1;
+
+ float scale_bv_weight = 1.0f;
+ float scale_skin[2] = {1.0f, 1.0f};
+ float scale_be_weight = 1.0f;
+ float scale_crease = 1.0f;
+
+ /* Vertices */
+
+ if (apply_vcos || median->bv_weight || median->skin[0] || median->skin[1]) {
+ if (median->bv_weight) {
+ BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_VERT_BWEIGHT);
+ cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
+ BLI_assert(cd_vert_bweight_offset != -1);
+
+ scale_bv_weight = compute_scale_factor(ve_median->bv_weight, median->bv_weight);
+ }
+
+ for (int i = 0; i < 2; i++) {
+ if (median->skin[i]) {
+ cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
+ BLI_assert(cd_vert_skin_offset != -1);
+
+ if (ve_median->skin[i] != median->skin[i]) {
+ scale_skin[i] = ve_median->skin[i] / (ve_median->skin[i] - median->skin[i]);
+ }
+ }
+ }
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ if (apply_vcos) {
+ apply_raw_diff_v3(eve->co, tot, ve_median->location, median->location);
+ }
+
+ if (cd_vert_bweight_offset != -1) {
+ float *b_weight = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset);
+ apply_scale_factor_clamp(b_weight, tot, ve_median->bv_weight, scale_bv_weight);
+ }
+
+ if (cd_vert_skin_offset != -1) {
+ MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset);
+
+ /* That one is not clamped to [0.0, 1.0]. */
+ for (int i = 0; i < 2; i++) {
+ if (median->skin[i] != 0.0f) {
+ apply_scale_factor(
+ &vs->radius[i], tot, ve_median->skin[i], median->skin[i], scale_skin[i]);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (apply_vcos) {
+ EDBM_mesh_normals_update(em);
+ }
+
+ /* Edges */
+
+ if (median->be_weight || median->crease) {
+ if (median->be_weight) {
+ BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_BWEIGHT);
+ cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
+ BLI_assert(cd_edge_bweight_offset != -1);
+
+ scale_be_weight = compute_scale_factor(ve_median->be_weight, median->be_weight);
+ }
+
+ if (median->crease) {
+ BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_CREASE);
+ cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
+ BLI_assert(cd_edge_crease_offset != -1);
+
+ scale_crease = compute_scale_factor(ve_median->crease, median->crease);
+ }
+
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ if (median->be_weight != 0.0f) {
+ float *b_weight = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_bweight_offset);
+ apply_scale_factor_clamp(b_weight, tot, ve_median->be_weight, scale_be_weight);
+ }
+
+ if (median->crease != 0.0f) {
+ float *crease = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_crease_offset);
+ apply_scale_factor_clamp(crease, tot, ve_median->crease, scale_crease);
+ }
+ }
+ }
+ }
+ }
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF) &&
+ (apply_vcos || median_basis.curve.b_weight || median_basis.curve.weight ||
+ median_basis.curve.radius || median_basis.curve.tilt)) {
+ const TransformMedian_Curve *median = &median_basis.curve,
+ *ve_median = &ve_median_basis.curve;
+ Curve *cu = ob->data;
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+ const float scale_w = compute_scale_factor(ve_median->weight, median->weight);
+
+ nu = nurbs->first;
+ while (nu) {
+ if (nu->type == CU_BEZIER) {
+ for (a = nu->pntsu, bezt = nu->bezt; a--; bezt++) {
+ if (bezt->f2 & SELECT) {
+ if (apply_vcos) {
+ /* Here we always have to use the diff... :/
+ * Cannot avoid some glitches when going e.g. from 3 to 0.0001 (see T37327),
+ * unless we use doubles.
+ */
+ add_v3_v3(bezt->vec[0], median->location);
+ add_v3_v3(bezt->vec[1], median->location);
+ add_v3_v3(bezt->vec[2], median->location);
+ }
+ if (median->weight) {
+ apply_scale_factor_clamp(&bezt->weight, tot, ve_median->weight, scale_w);
+ }
+ if (median->radius) {
+ apply_raw_diff(&bezt->radius, tot, ve_median->radius, median->radius);
+ }
+ if (median->tilt) {
+ apply_raw_diff(&bezt->tilt, tot, ve_median->tilt, median->tilt);
+ }
+ }
+ else if (apply_vcos) {
+ /* Handles can only have their coordinates changed here. */
+ if (bezt->f1 & SELECT) {
+ apply_raw_diff_v3(bezt->vec[0], tot, ve_median->location, median->location);
+ }
+ if (bezt->f3 & SELECT) {
+ apply_raw_diff_v3(bezt->vec[2], tot, ve_median->location, median->location);
+ }
+ }
+ }
+ }
+ else {
+ for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a--; bp++) {
+ if (bp->f1 & SELECT) {
+ if (apply_vcos) {
+ apply_raw_diff_v3(bp->vec, tot, ve_median->location, median->location);
+ }
+ if (median->b_weight) {
+ apply_raw_diff(&bp->vec[3], tot, ve_median->b_weight, median->b_weight);
+ }
+ if (median->weight) {
+ apply_scale_factor_clamp(&bp->weight, tot, ve_median->weight, scale_w);
+ }
+ if (median->radius) {
+ apply_raw_diff(&bp->radius, tot, ve_median->radius, median->radius);
+ }
+ if (median->tilt) {
+ apply_raw_diff(&bp->tilt, tot, ve_median->tilt, median->tilt);
+ }
+ }
+ }
+ }
+ BKE_nurb_test_2d(nu);
+ BKE_nurb_handles_test(nu, true); /* test for bezier too */
+
+ nu = nu->next;
+ }
+ }
+ else if ((ob->type == OB_LATTICE) && (apply_vcos || median_basis.lattice.weight)) {
+ const TransformMedian_Lattice *median = &median_basis.lattice,
+ *ve_median = &ve_median_basis.lattice;
+ Lattice *lt = ob->data;
+ BPoint *bp;
+ int a;
+ const float scale_w = compute_scale_factor(ve_median->weight, median->weight);
+
+ a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
+ bp = lt->editlatt->latt->def;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ if (apply_vcos) {
+ apply_raw_diff_v3(bp->vec, tot, ve_median->location, median->location);
+ }
+ if (median->weight) {
+ apply_scale_factor_clamp(&bp->weight, tot, ve_median->weight, scale_w);
+ }
+ }
+ bp++;
+ }
+ }
+
+ /* ED_undo_push(C, "Transform properties"); */
+ }
}
#undef TRANSFORM_MEDIAN_ARRAY_LEN
static void v3d_object_dimension_buts(bContext *C, uiLayout *layout, View3D *v3d, Object *ob)
{
- uiBlock *block = (layout) ? uiLayoutAbsoluteBlock(layout) : NULL;
- TransformProperties *tfp = v3d_transform_props_ensure(v3d);
-
- if (block) {
- BLI_assert(C == NULL);
- int yi = 200;
- const int butw = 200;
- const int buth = 20 * UI_DPI_FAC;
-
- BKE_object_dimensions_get(ob, tfp->ob_dims);
- copy_v3_v3(tfp->ob_dims_orig, tfp->ob_dims);
-
- uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Dimensions:"), 0, yi -= buth, butw, buth, NULL, 0, 0, 0, 0, "");
- UI_block_align_begin(block);
- const float lim = 10000;
- for (int i = 0; i < 3; i++) {
- uiBut *but;
- char text[3] = {'X' + i, ':', '\0'};
- but = uiDefButF(
- block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_DIMS, text, 0, yi -= buth, butw, buth,
- &(tfp->ob_dims[i]), 0.0f, lim, 10, 3, "");
- UI_but_unit_type_set(but, PROP_UNIT_LENGTH);
- }
- UI_block_align_end(block);
- }
- else { /* apply */
- int axis_mask = 0;
- for (int i = 0; i < 3; i++) {
- if (tfp->ob_dims[i] == tfp->ob_dims_orig[i]) {
- axis_mask |= (1 << i);
- }
- }
- BKE_object_dimensions_set(ob, tfp->ob_dims, axis_mask);
-
- PointerRNA obptr;
- RNA_id_pointer_create(&ob->id, &obptr);
- PropertyRNA *prop = RNA_struct_find_property(&obptr, "scale");
- RNA_property_update(C, &obptr, prop);
- }
+ uiBlock *block = (layout) ? uiLayoutAbsoluteBlock(layout) : NULL;
+ TransformProperties *tfp = v3d_transform_props_ensure(v3d);
+
+ if (block) {
+ BLI_assert(C == NULL);
+ int yi = 200;
+ const int butw = 200;
+ const int buth = 20 * UI_DPI_FAC;
+
+ BKE_object_dimensions_get(ob, tfp->ob_dims);
+ copy_v3_v3(tfp->ob_dims_orig, tfp->ob_dims);
+
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ IFACE_("Dimensions:"),
+ 0,
+ yi -= buth,
+ butw,
+ buth,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ UI_block_align_begin(block);
+ const float lim = 10000;
+ for (int i = 0; i < 3; i++) {
+ uiBut *but;
+ char text[3] = {'X' + i, ':', '\0'};
+ but = uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_TRANSFORM_PANEL_DIMS,
+ text,
+ 0,
+ yi -= buth,
+ butw,
+ buth,
+ &(tfp->ob_dims[i]),
+ 0.0f,
+ lim,
+ 10,
+ 3,
+ "");
+ UI_but_unit_type_set(but, PROP_UNIT_LENGTH);
+ }
+ UI_block_align_end(block);
+ }
+ else { /* apply */
+ int axis_mask = 0;
+ for (int i = 0; i < 3; i++) {
+ if (tfp->ob_dims[i] == tfp->ob_dims_orig[i]) {
+ axis_mask |= (1 << i);
+ }
+ }
+ BKE_object_dimensions_set(ob, tfp->ob_dims, axis_mask);
+
+ PointerRNA obptr;
+ RNA_id_pointer_create(&ob->id, &obptr);
+ PropertyRNA *prop = RNA_struct_find_property(&obptr, "scale");
+ RNA_property_update(C, &obptr, prop);
+ }
}
-#define B_VGRP_PNL_EDIT_SINGLE 8 /* or greater */
+#define B_VGRP_PNL_EDIT_SINGLE 8 /* or greater */
static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event)
{
- if (event < B_VGRP_PNL_EDIT_SINGLE) {
- /* not for me */
- return;
- }
- else {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = view_layer->basact->object;
- ED_vgroup_vert_active_mirror(ob, event - B_VGRP_PNL_EDIT_SINGLE);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- }
+ if (event < B_VGRP_PNL_EDIT_SINGLE) {
+ /* not for me */
+ return;
+ }
+ else {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = view_layer->basact->object;
+ ED_vgroup_vert_active_mirror(ob, event - B_VGRP_PNL_EDIT_SINGLE);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ }
}
static bool view3d_panel_vgroup_poll(const bContext *C, PanelType *UNUSED(pt))
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- if (ob && (BKE_object_is_in_editmode_vgroup(ob) ||
- BKE_object_is_in_wpaint_select_vert(ob)))
- {
- MDeformVert *dvert_act = ED_mesh_active_dvert_get_only(ob);
- if (dvert_act) {
- return (dvert_act->totweight != 0);
- }
- }
-
- return false;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ if (ob && (BKE_object_is_in_editmode_vgroup(ob) || BKE_object_is_in_wpaint_select_vert(ob))) {
+ MDeformVert *dvert_act = ED_mesh_active_dvert_get_only(ob);
+ if (dvert_act) {
+ return (dvert_act->totweight != 0);
+ }
+ }
+
+ return false;
}
-
static void view3d_panel_vgroup(const bContext *C, Panel *pa)
{
- uiBlock *block = uiLayoutAbsoluteBlock(pa->layout);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = view_layer->basact->object;
-
- MDeformVert *dv;
-
- dv = ED_mesh_active_dvert_get_only(ob);
-
- if (dv && dv->totweight) {
- ToolSettings *ts = scene->toolsettings;
-
- wmOperatorType *ot;
- PointerRNA op_ptr, tools_ptr;
- PointerRNA *but_ptr;
-
- uiLayout *col, *bcol;
- uiLayout *row;
- uiBut *but;
- bDeformGroup *dg;
- uint i;
- int subset_count, vgroup_tot;
- const bool *vgroup_validmap;
- eVGroupSelect subset_type = ts->vgroupsubset;
- int yco = 0;
- int lock_count = 0;
-
- UI_block_func_handle_set(block, do_view3d_vgroup_buttons, NULL);
-
- bcol = uiLayoutColumn(pa->layout, true);
- row = uiLayoutRow(bcol, true); /* The filter button row */
-
- RNA_pointer_create(NULL, &RNA_ToolSettings, ts, &tools_ptr);
- uiItemR(row, &tools_ptr, "vertex_group_subset", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
-
- col = uiLayoutColumn(bcol, true);
-
- vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
- 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);
- if (dw) {
- int x, xco = 0;
- int icon;
- uiLayout *split = uiLayoutSplit(col, 0.45, true);
- row = uiLayoutRow(split, true);
-
- /* The Weight Group Name */
-
- ot = WM_operatortype_find("OBJECT_OT_vertex_weight_set_active", true);
- but = uiDefButO_ptr(block, UI_BTYPE_BUT, ot, WM_OP_EXEC_DEFAULT, dg->name,
- xco, yco, (x = UI_UNIT_X * 5), UI_UNIT_Y, "");
- but_ptr = UI_but_operator_ptr_get(but);
- RNA_int_set(but_ptr, "weight_group", i);
- UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT);
- if (ob->actdef != i + 1) {
- UI_but_flag_enable(but, UI_BUT_INACTIVE);
- }
- xco += x;
-
- row = uiLayoutRow(split, true);
- uiLayoutSetEnabled(row, !locked);
-
- /* The weight group value */
- /* To be reworked still */
- but = uiDefButF(block, UI_BTYPE_NUM, B_VGRP_PNL_EDIT_SINGLE + i, "",
- xco, yco, (x = UI_UNIT_X * 4), UI_UNIT_Y,
- &dw->weight, 0.0, 1.0, 1, 3, "");
- UI_but_drawflag_enable(but, UI_BUT_TEXT_LEFT);
- if (locked) {
- lock_count++;
- }
- xco += x;
-
- /* The weight group paste function */
- icon = (locked) ? ICON_BLANK1 : ICON_PASTEDOWN;
- uiItemFullO(row, "OBJECT_OT_vertex_weight_paste", "", icon, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
- RNA_int_set(&op_ptr, "weight_group", i);
-
- /* The weight entry delete function */
- icon = (locked) ? ICON_LOCKED : ICON_X;
- uiItemFullO(row, "OBJECT_OT_vertex_weight_delete", "", icon, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
- RNA_int_set(&op_ptr, "weight_group", i);
-
- yco -= UI_UNIT_Y;
- }
- }
- }
- MEM_freeN((void *)vgroup_validmap);
-
- yco -= 2;
-
- col = uiLayoutColumn(pa->layout, true);
- row = uiLayoutRow(col, true);
-
- ot = WM_operatortype_find("OBJECT_OT_vertex_weight_normalize_active_vertex", 1);
- but = uiDefButO_ptr(block, UI_BTYPE_BUT, ot, WM_OP_EXEC_DEFAULT, "Normalize",
- 0, yco, UI_UNIT_X * 5, UI_UNIT_Y,
- TIP_("Normalize weights of active vertex (if affected groups are unlocked)"));
- if (lock_count) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
-
- ot = WM_operatortype_find("OBJECT_OT_vertex_weight_copy", 1);
- but = uiDefButO_ptr(block, UI_BTYPE_BUT, ot, WM_OP_EXEC_DEFAULT, "Copy",
- UI_UNIT_X * 5, yco, UI_UNIT_X * 5, UI_UNIT_Y,
- TIP_("Copy active vertex to other selected vertices (if affected groups are unlocked)"));
- if (lock_count) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
-
- }
+ uiBlock *block = uiLayoutAbsoluteBlock(pa->layout);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = view_layer->basact->object;
+
+ MDeformVert *dv;
+
+ dv = ED_mesh_active_dvert_get_only(ob);
+
+ if (dv && dv->totweight) {
+ ToolSettings *ts = scene->toolsettings;
+
+ wmOperatorType *ot;
+ PointerRNA op_ptr, tools_ptr;
+ PointerRNA *but_ptr;
+
+ uiLayout *col, *bcol;
+ uiLayout *row;
+ uiBut *but;
+ bDeformGroup *dg;
+ uint i;
+ int subset_count, vgroup_tot;
+ const bool *vgroup_validmap;
+ eVGroupSelect subset_type = ts->vgroupsubset;
+ int yco = 0;
+ int lock_count = 0;
+
+ UI_block_func_handle_set(block, do_view3d_vgroup_buttons, NULL);
+
+ bcol = uiLayoutColumn(pa->layout, true);
+ row = uiLayoutRow(bcol, true); /* The filter button row */
+
+ RNA_pointer_create(NULL, &RNA_ToolSettings, ts, &tools_ptr);
+ uiItemR(row, &tools_ptr, "vertex_group_subset", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+
+ col = uiLayoutColumn(bcol, true);
+
+ vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
+ ob, subset_type, &vgroup_tot, &subset_count);
+ 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);
+ if (dw) {
+ int x, xco = 0;
+ int icon;
+ uiLayout *split = uiLayoutSplit(col, 0.45, true);
+ row = uiLayoutRow(split, true);
+
+ /* The Weight Group Name */
+
+ ot = WM_operatortype_find("OBJECT_OT_vertex_weight_set_active", true);
+ but = uiDefButO_ptr(block,
+ UI_BTYPE_BUT,
+ ot,
+ WM_OP_EXEC_DEFAULT,
+ dg->name,
+ xco,
+ yco,
+ (x = UI_UNIT_X * 5),
+ UI_UNIT_Y,
+ "");
+ but_ptr = UI_but_operator_ptr_get(but);
+ RNA_int_set(but_ptr, "weight_group", i);
+ UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT);
+ if (ob->actdef != i + 1) {
+ UI_but_flag_enable(but, UI_BUT_INACTIVE);
+ }
+ xco += x;
+
+ row = uiLayoutRow(split, true);
+ uiLayoutSetEnabled(row, !locked);
+
+ /* The weight group value */
+ /* To be reworked still */
+ but = uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_VGRP_PNL_EDIT_SINGLE + i,
+ "",
+ xco,
+ yco,
+ (x = UI_UNIT_X * 4),
+ UI_UNIT_Y,
+ &dw->weight,
+ 0.0,
+ 1.0,
+ 1,
+ 3,
+ "");
+ UI_but_drawflag_enable(but, UI_BUT_TEXT_LEFT);
+ if (locked) {
+ lock_count++;
+ }
+ xco += x;
+
+ /* The weight group paste function */
+ icon = (locked) ? ICON_BLANK1 : ICON_PASTEDOWN;
+ uiItemFullO(row,
+ "OBJECT_OT_vertex_weight_paste",
+ "",
+ icon,
+ NULL,
+ WM_OP_INVOKE_DEFAULT,
+ 0,
+ &op_ptr);
+ RNA_int_set(&op_ptr, "weight_group", i);
+
+ /* The weight entry delete function */
+ icon = (locked) ? ICON_LOCKED : ICON_X;
+ uiItemFullO(row,
+ "OBJECT_OT_vertex_weight_delete",
+ "",
+ icon,
+ NULL,
+ WM_OP_INVOKE_DEFAULT,
+ 0,
+ &op_ptr);
+ RNA_int_set(&op_ptr, "weight_group", i);
+
+ yco -= UI_UNIT_Y;
+ }
+ }
+ }
+ MEM_freeN((void *)vgroup_validmap);
+
+ yco -= 2;
+
+ col = uiLayoutColumn(pa->layout, true);
+ row = uiLayoutRow(col, true);
+
+ ot = WM_operatortype_find("OBJECT_OT_vertex_weight_normalize_active_vertex", 1);
+ but = uiDefButO_ptr(
+ block,
+ UI_BTYPE_BUT,
+ ot,
+ WM_OP_EXEC_DEFAULT,
+ "Normalize",
+ 0,
+ yco,
+ UI_UNIT_X * 5,
+ UI_UNIT_Y,
+ TIP_("Normalize weights of active vertex (if affected groups are unlocked)"));
+ if (lock_count) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+
+ ot = WM_operatortype_find("OBJECT_OT_vertex_weight_copy", 1);
+ but = uiDefButO_ptr(
+ block,
+ UI_BTYPE_BUT,
+ ot,
+ WM_OP_EXEC_DEFAULT,
+ "Copy",
+ UI_UNIT_X * 5,
+ yco,
+ UI_UNIT_X * 5,
+ UI_UNIT_Y,
+ TIP_("Copy active vertex to other selected vertices (if affected groups are unlocked)"));
+ if (lock_count) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ }
}
static void v3d_transform_butsR(uiLayout *layout, PointerRNA *ptr)
{
- uiLayout *split, *colsub;
-
- split = uiLayoutSplit(layout, 0.8f, false);
-
- if (ptr->type == &RNA_PoseBone) {
- PointerRNA boneptr;
- Bone *bone;
-
- boneptr = RNA_pointer_get(ptr, "bone");
- bone = boneptr.data;
- uiLayoutSetActive(split, !(bone->parent && bone->flag & BONE_CONNECTED));
- }
- colsub = uiLayoutColumn(split, true);
- uiItemR(colsub, ptr, "location", 0, NULL, ICON_NONE);
- colsub = uiLayoutColumn(split, true);
- uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE);
- uiItemL(colsub, "", ICON_NONE);
- uiItemR(colsub, ptr, "lock_location", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", ICON_DECORATE_UNLOCKED);
-
- split = uiLayoutSplit(layout, 0.8f, false);
-
- switch (RNA_enum_get(ptr, "rotation_mode")) {
- case ROT_MODE_QUAT: /* quaternion */
- colsub = uiLayoutColumn(split, true);
- uiItemR(colsub, ptr, "rotation_quaternion", 0, IFACE_("Rotation"), ICON_NONE);
- colsub = uiLayoutColumn(split, true);
- uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE);
- uiItemR(colsub, ptr, "lock_rotations_4d", UI_ITEM_R_TOGGLE, IFACE_("4L"), ICON_NONE);
- if (RNA_boolean_get(ptr, "lock_rotations_4d")) {
- uiItemR(colsub, ptr, "lock_rotation_w", UI_ITEM_R_TOGGLE + UI_ITEM_R_ICON_ONLY, "", ICON_DECORATE_UNLOCKED);
- }
- else {
- uiItemL(colsub, "", ICON_NONE);
- }
- uiItemR(colsub, ptr, "lock_rotation", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", ICON_DECORATE_UNLOCKED);
- break;
- case ROT_MODE_AXISANGLE: /* axis angle */
- colsub = uiLayoutColumn(split, true);
- uiItemR(colsub, ptr, "rotation_axis_angle", 0, IFACE_("Rotation"), ICON_NONE);
- colsub = uiLayoutColumn(split, true);
- uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE);
- uiItemR(colsub, ptr, "lock_rotations_4d", UI_ITEM_R_TOGGLE, IFACE_("4L"), ICON_NONE);
- if (RNA_boolean_get(ptr, "lock_rotations_4d")) {
- uiItemR(colsub, ptr, "lock_rotation_w", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", ICON_DECORATE_UNLOCKED);
- }
- else {
- uiItemL(colsub, "", ICON_NONE);
- }
- uiItemR(colsub, ptr, "lock_rotation", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", ICON_DECORATE_UNLOCKED);
- break;
- default: /* euler rotations */
- colsub = uiLayoutColumn(split, true);
- uiItemR(colsub, ptr, "rotation_euler", 0, IFACE_("Rotation"), ICON_NONE);
- colsub = uiLayoutColumn(split, true);
- uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE);
- uiItemL(colsub, "", ICON_NONE);
- uiItemR(colsub, ptr, "lock_rotation", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", ICON_DECORATE_UNLOCKED);
- break;
- }
- uiItemR(layout, ptr, "rotation_mode", 0, "", ICON_NONE);
-
- split = uiLayoutSplit(layout, 0.8f, false);
- colsub = uiLayoutColumn(split, true);
- uiItemR(colsub, ptr, "scale", 0, NULL, ICON_NONE);
- colsub = uiLayoutColumn(split, true);
- uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE);
- uiItemL(colsub, "", ICON_NONE);
- uiItemR(colsub, ptr, "lock_scale", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", ICON_DECORATE_UNLOCKED);
+ uiLayout *split, *colsub;
+
+ split = uiLayoutSplit(layout, 0.8f, false);
+
+ if (ptr->type == &RNA_PoseBone) {
+ PointerRNA boneptr;
+ Bone *bone;
+
+ boneptr = RNA_pointer_get(ptr, "bone");
+ bone = boneptr.data;
+ uiLayoutSetActive(split, !(bone->parent && bone->flag & BONE_CONNECTED));
+ }
+ colsub = uiLayoutColumn(split, true);
+ uiItemR(colsub, ptr, "location", 0, NULL, ICON_NONE);
+ colsub = uiLayoutColumn(split, true);
+ uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE);
+ uiItemL(colsub, "", ICON_NONE);
+ uiItemR(colsub,
+ ptr,
+ "lock_location",
+ UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY,
+ "",
+ ICON_DECORATE_UNLOCKED);
+
+ split = uiLayoutSplit(layout, 0.8f, false);
+
+ switch (RNA_enum_get(ptr, "rotation_mode")) {
+ case ROT_MODE_QUAT: /* quaternion */
+ colsub = uiLayoutColumn(split, true);
+ uiItemR(colsub, ptr, "rotation_quaternion", 0, IFACE_("Rotation"), ICON_NONE);
+ colsub = uiLayoutColumn(split, true);
+ uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE);
+ uiItemR(colsub, ptr, "lock_rotations_4d", UI_ITEM_R_TOGGLE, IFACE_("4L"), ICON_NONE);
+ if (RNA_boolean_get(ptr, "lock_rotations_4d")) {
+ uiItemR(colsub,
+ ptr,
+ "lock_rotation_w",
+ UI_ITEM_R_TOGGLE + UI_ITEM_R_ICON_ONLY,
+ "",
+ ICON_DECORATE_UNLOCKED);
+ }
+ else {
+ uiItemL(colsub, "", ICON_NONE);
+ }
+ uiItemR(colsub,
+ ptr,
+ "lock_rotation",
+ UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY,
+ "",
+ ICON_DECORATE_UNLOCKED);
+ break;
+ case ROT_MODE_AXISANGLE: /* axis angle */
+ colsub = uiLayoutColumn(split, true);
+ uiItemR(colsub, ptr, "rotation_axis_angle", 0, IFACE_("Rotation"), ICON_NONE);
+ colsub = uiLayoutColumn(split, true);
+ uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE);
+ uiItemR(colsub, ptr, "lock_rotations_4d", UI_ITEM_R_TOGGLE, IFACE_("4L"), ICON_NONE);
+ if (RNA_boolean_get(ptr, "lock_rotations_4d")) {
+ uiItemR(colsub,
+ ptr,
+ "lock_rotation_w",
+ UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY,
+ "",
+ ICON_DECORATE_UNLOCKED);
+ }
+ else {
+ uiItemL(colsub, "", ICON_NONE);
+ }
+ uiItemR(colsub,
+ ptr,
+ "lock_rotation",
+ UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY,
+ "",
+ ICON_DECORATE_UNLOCKED);
+ break;
+ default: /* euler rotations */
+ colsub = uiLayoutColumn(split, true);
+ uiItemR(colsub, ptr, "rotation_euler", 0, IFACE_("Rotation"), ICON_NONE);
+ colsub = uiLayoutColumn(split, true);
+ uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE);
+ uiItemL(colsub, "", ICON_NONE);
+ uiItemR(colsub,
+ ptr,
+ "lock_rotation",
+ UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY,
+ "",
+ ICON_DECORATE_UNLOCKED);
+ break;
+ }
+ uiItemR(layout, ptr, "rotation_mode", 0, "", ICON_NONE);
+
+ split = uiLayoutSplit(layout, 0.8f, false);
+ colsub = uiLayoutColumn(split, true);
+ uiItemR(colsub, ptr, "scale", 0, NULL, ICON_NONE);
+ colsub = uiLayoutColumn(split, true);
+ uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE);
+ uiItemL(colsub, "", ICON_NONE);
+ uiItemR(colsub,
+ ptr,
+ "lock_scale",
+ UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY,
+ "",
+ ICON_DECORATE_UNLOCKED);
}
static void v3d_posearmature_buts(uiLayout *layout, Object *ob)
{
- bPoseChannel *pchan;
- PointerRNA pchanptr;
- uiLayout *col;
+ bPoseChannel *pchan;
+ PointerRNA pchanptr;
+ uiLayout *col;
- pchan = BKE_pose_channel_active(ob);
+ pchan = BKE_pose_channel_active(ob);
- if (!pchan) {
- uiItemL(layout, IFACE_("No Bone Active"), ICON_NONE);
- return;
- }
+ if (!pchan) {
+ uiItemL(layout, IFACE_("No Bone Active"), ICON_NONE);
+ return;
+ }
- RNA_pointer_create(&ob->id, &RNA_PoseBone, pchan, &pchanptr);
+ RNA_pointer_create(&ob->id, &RNA_PoseBone, pchan, &pchanptr);
- col = uiLayoutColumn(layout, false);
+ col = uiLayoutColumn(layout, false);
- /* XXX: RNA buts show data in native types (i.e. quats, 4-component axis/angle, etc.)
- * but old-school UI shows in eulers always. Do we want to be able to still display in Eulers?
- * Maybe needs RNA/ui options to display rotations as different types... */
- v3d_transform_butsR(col, &pchanptr);
+ /* XXX: RNA buts show data in native types (i.e. quats, 4-component axis/angle, etc.)
+ * but old-school UI shows in eulers always. Do we want to be able to still display in Eulers?
+ * Maybe needs RNA/ui options to display rotations as different types... */
+ v3d_transform_butsR(col, &pchanptr);
}
static void v3d_editarmature_buts(uiLayout *layout, Object *ob)
{
- bArmature *arm = ob->data;
- EditBone *ebone;
- uiLayout *col;
- PointerRNA eboneptr;
-
- ebone = arm->act_edbone;
-
- if (!ebone || (ebone->layer & arm->layer) == 0) {
- uiItemL(layout, IFACE_("Nothing selected"), ICON_NONE);
- return;
- }
-
- RNA_pointer_create(&arm->id, &RNA_EditBone, ebone, &eboneptr);
-
- col = uiLayoutColumn(layout, false);
- uiItemR(col, &eboneptr, "head", 0, NULL, ICON_NONE);
- if (ebone->parent && ebone->flag & BONE_CONNECTED) {
- PointerRNA parptr = RNA_pointer_get(&eboneptr, "parent");
- uiItemR(col, &parptr, "tail_radius", 0, IFACE_("Radius (Parent)"), ICON_NONE);
- }
- else {
- uiItemR(col, &eboneptr, "head_radius", 0, IFACE_("Radius"), ICON_NONE);
- }
-
- uiItemR(col, &eboneptr, "tail", 0, NULL, ICON_NONE);
- uiItemR(col, &eboneptr, "tail_radius", 0, IFACE_("Radius"), ICON_NONE);
-
- uiItemR(col, &eboneptr, "roll", 0, NULL, ICON_NONE);
- uiItemR(col, &eboneptr, "envelope_distance", 0, IFACE_("Envelope"), ICON_NONE);
+ bArmature *arm = ob->data;
+ EditBone *ebone;
+ uiLayout *col;
+ PointerRNA eboneptr;
+
+ ebone = arm->act_edbone;
+
+ if (!ebone || (ebone->layer & arm->layer) == 0) {
+ uiItemL(layout, IFACE_("Nothing selected"), ICON_NONE);
+ return;
+ }
+
+ RNA_pointer_create(&arm->id, &RNA_EditBone, ebone, &eboneptr);
+
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, &eboneptr, "head", 0, NULL, ICON_NONE);
+ if (ebone->parent && ebone->flag & BONE_CONNECTED) {
+ PointerRNA parptr = RNA_pointer_get(&eboneptr, "parent");
+ uiItemR(col, &parptr, "tail_radius", 0, IFACE_("Radius (Parent)"), ICON_NONE);
+ }
+ else {
+ uiItemR(col, &eboneptr, "head_radius", 0, IFACE_("Radius"), ICON_NONE);
+ }
+
+ uiItemR(col, &eboneptr, "tail", 0, NULL, ICON_NONE);
+ uiItemR(col, &eboneptr, "tail_radius", 0, IFACE_("Radius"), ICON_NONE);
+
+ uiItemR(col, &eboneptr, "roll", 0, NULL, ICON_NONE);
+ uiItemR(col, &eboneptr, "envelope_distance", 0, IFACE_("Envelope"), ICON_NONE);
}
static void v3d_editmetaball_buts(uiLayout *layout, Object *ob)
{
- PointerRNA mbptr, ptr;
- MetaBall *mball = ob->data;
- uiLayout *col;
-
- if (!mball || !(mball->lastelem)) {
- return;
- }
-
- RNA_pointer_create(&mball->id, &RNA_MetaBall, mball, &mbptr);
-
- RNA_pointer_create(&mball->id, &RNA_MetaElement, mball->lastelem, &ptr);
-
- col = uiLayoutColumn(layout, false);
- uiItemR(col, &ptr, "co", 0, NULL, ICON_NONE);
-
- uiItemR(col, &ptr, "radius", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "stiffness", 0, NULL, ICON_NONE);
-
- uiItemR(col, &ptr, "type", 0, NULL, ICON_NONE);
-
- col = uiLayoutColumn(layout, true);
- switch (RNA_enum_get(&ptr, "type")) {
- case MB_BALL:
- break;
- case MB_CUBE:
- uiItemL(col, IFACE_("Size:"), ICON_NONE);
- uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE);
- uiItemR(col, &ptr, "size_y", 0, "Y", ICON_NONE);
- uiItemR(col, &ptr, "size_z", 0, "Z", ICON_NONE);
- break;
- case MB_TUBE:
- uiItemL(col, IFACE_("Size:"), ICON_NONE);
- uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE);
- break;
- case MB_PLANE:
- uiItemL(col, IFACE_("Size:"), ICON_NONE);
- uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE);
- uiItemR(col, &ptr, "size_y", 0, "Y", ICON_NONE);
- break;
- case MB_ELIPSOID:
- uiItemL(col, IFACE_("Size:"), ICON_NONE);
- uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE);
- uiItemR(col, &ptr, "size_y", 0, "Y", ICON_NONE);
- uiItemR(col, &ptr, "size_z", 0, "Z", ICON_NONE);
- break;
- }
+ PointerRNA mbptr, ptr;
+ MetaBall *mball = ob->data;
+ uiLayout *col;
+
+ if (!mball || !(mball->lastelem)) {
+ return;
+ }
+
+ RNA_pointer_create(&mball->id, &RNA_MetaBall, mball, &mbptr);
+
+ RNA_pointer_create(&mball->id, &RNA_MetaElement, mball->lastelem, &ptr);
+
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, &ptr, "co", 0, NULL, ICON_NONE);
+
+ uiItemR(col, &ptr, "radius", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "stiffness", 0, NULL, ICON_NONE);
+
+ uiItemR(col, &ptr, "type", 0, NULL, ICON_NONE);
+
+ col = uiLayoutColumn(layout, true);
+ switch (RNA_enum_get(&ptr, "type")) {
+ case MB_BALL:
+ break;
+ case MB_CUBE:
+ uiItemL(col, IFACE_("Size:"), ICON_NONE);
+ uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE);
+ uiItemR(col, &ptr, "size_y", 0, "Y", ICON_NONE);
+ uiItemR(col, &ptr, "size_z", 0, "Z", ICON_NONE);
+ break;
+ case MB_TUBE:
+ uiItemL(col, IFACE_("Size:"), ICON_NONE);
+ uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE);
+ break;
+ case MB_PLANE:
+ uiItemL(col, IFACE_("Size:"), ICON_NONE);
+ uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE);
+ uiItemR(col, &ptr, "size_y", 0, "Y", ICON_NONE);
+ break;
+ case MB_ELIPSOID:
+ uiItemL(col, IFACE_("Size:"), ICON_NONE);
+ uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE);
+ uiItemR(col, &ptr, "size_y", 0, "Y", ICON_NONE);
+ uiItemR(col, &ptr, "size_z", 0, "Z", ICON_NONE);
+ break;
+ }
}
static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- Object *ob = OBACT(view_layer);
-
- switch (event) {
-
- case B_REDR:
- ED_area_tag_redraw(CTX_wm_area(C));
- return; /* no notifier! */
-
- case B_TRANSFORM_PANEL_MEDIAN:
- if (ob) {
- v3d_editvertex_buts(NULL, v3d, ob, 1.0);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- break;
- case B_TRANSFORM_PANEL_DIMS:
- if (ob) {
- v3d_object_dimension_buts(C, NULL, v3d, ob);
- }
- break;
- }
-
- /* default for now */
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Object *ob = OBACT(view_layer);
+
+ switch (event) {
+
+ case B_REDR:
+ ED_area_tag_redraw(CTX_wm_area(C));
+ return; /* no notifier! */
+
+ case B_TRANSFORM_PANEL_MEDIAN:
+ if (ob) {
+ v3d_editvertex_buts(NULL, v3d, ob, 1.0);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ break;
+ case B_TRANSFORM_PANEL_DIMS:
+ if (ob) {
+ v3d_object_dimension_buts(C, NULL, v3d, ob);
+ }
+ break;
+ }
+
+ /* default for now */
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
}
static bool view3d_panel_transform_poll(const bContext *C, PanelType *UNUSED(pt))
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- return (view_layer->basact != NULL);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ return (view_layer->basact != NULL);
}
static void view3d_panel_transform(const bContext *C, Panel *pa)
{
- uiBlock *block;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = view_layer->basact->object;
- Object *obedit = OBEDIT_FROM_OBACT(ob);
- uiLayout *col;
-
- block = uiLayoutGetBlock(pa->layout);
- UI_block_func_handle_set(block, do_view3d_region_buttons, NULL);
-
- col = uiLayoutColumn(pa->layout, false);
-
- if (ob == obedit) {
- if (ob->type == OB_ARMATURE) {
- v3d_editarmature_buts(col, ob);
- }
- else if (ob->type == OB_MBALL) {
- v3d_editmetaball_buts(col, ob);
- }
- else {
- View3D *v3d = CTX_wm_view3d(C);
- Scene *scene = CTX_data_scene(C);
- const float lim = 10000.0f * max_ff(1.0f, ED_view3d_grid_scale(scene, v3d, NULL));
- v3d_editvertex_buts(col, v3d, ob, lim);
- }
- }
- else if (ob->mode & OB_MODE_POSE) {
- v3d_posearmature_buts(col, ob);
- }
- else {
- PointerRNA obptr;
-
- 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)) {
- View3D *v3d = CTX_wm_view3d(C);
- v3d_object_dimension_buts(NULL, col, v3d, ob);
- }
- }
+ uiBlock *block;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = view_layer->basact->object;
+ Object *obedit = OBEDIT_FROM_OBACT(ob);
+ uiLayout *col;
+
+ block = uiLayoutGetBlock(pa->layout);
+ UI_block_func_handle_set(block, do_view3d_region_buttons, NULL);
+
+ col = uiLayoutColumn(pa->layout, false);
+
+ if (ob == obedit) {
+ if (ob->type == OB_ARMATURE) {
+ v3d_editarmature_buts(col, ob);
+ }
+ else if (ob->type == OB_MBALL) {
+ v3d_editmetaball_buts(col, ob);
+ }
+ else {
+ View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ const float lim = 10000.0f * max_ff(1.0f, ED_view3d_grid_scale(scene, v3d, NULL));
+ v3d_editvertex_buts(col, v3d, ob, lim);
+ }
+ }
+ else if (ob->mode & OB_MODE_POSE) {
+ v3d_posearmature_buts(col, ob);
+ }
+ else {
+ PointerRNA obptr;
+
+ 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)) {
+ View3D *v3d = CTX_wm_view3d(C);
+ v3d_object_dimension_buts(NULL, col, v3d, ob);
+ }
+ }
}
static void hide_collections_menu_draw(const bContext *C, Menu *menu)
{
- ED_collection_hide_menu_draw(C, menu->layout);
+ ED_collection_hide_menu_draw(C, menu->layout);
}
void view3d_buttons_register(ARegionType *art)
{
- PanelType *pt;
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel object");
- strcpy(pt->idname, "VIEW3D_PT_transform");
- strcpy(pt->label, N_("Transform")); /* XXX C panels unavailable through RNA bpy.types! */
- strcpy(pt->category, "View");
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = view3d_panel_transform;
- pt->poll = view3d_panel_transform_poll;
- BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel vgroup");
- strcpy(pt->idname, "VIEW3D_PT_vgroup");
- strcpy(pt->label, N_("Vertex Weights")); /* XXX C panels unavailable through RNA bpy.types! */
- strcpy(pt->category, "View");
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = view3d_panel_vgroup;
- pt->poll = view3d_panel_vgroup_poll;
- BLI_addtail(&art->paneltypes, pt);
-
- MenuType *mt;
-
- mt = MEM_callocN(sizeof(MenuType), "spacetype view3d menu collections");
- strcpy(mt->idname, "VIEW3D_MT_collection");
- strcpy(mt->label, N_("Collection"));
- strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- mt->draw = hide_collections_menu_draw;
- WM_menutype_add(mt);
+ PanelType *pt;
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel object");
+ strcpy(pt->idname, "VIEW3D_PT_transform");
+ strcpy(pt->label, N_("Transform")); /* XXX C panels unavailable through RNA bpy.types! */
+ strcpy(pt->category, "View");
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = view3d_panel_transform;
+ pt->poll = view3d_panel_transform_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel vgroup");
+ strcpy(pt->idname, "VIEW3D_PT_vgroup");
+ strcpy(pt->label, N_("Vertex Weights")); /* XXX C panels unavailable through RNA bpy.types! */
+ strcpy(pt->category, "View");
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw = view3d_panel_vgroup;
+ pt->poll = view3d_panel_vgroup_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
+ MenuType *mt;
+
+ mt = MEM_callocN(sizeof(MenuType), "spacetype view3d menu collections");
+ strcpy(mt->idname, "VIEW3D_MT_collection");
+ strcpy(mt->label, N_("Collection"));
+ strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ mt->draw = hide_collections_menu_draw;
+ WM_menutype_add(mt);
}
static int view3d_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = view3d_has_buttons_region(sa);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = view3d_has_buttons_region(sa);
- if (ar) {
- ED_region_toggle_hidden(C, ar);
- }
+ if (ar) {
+ ED_region_toggle_hidden(C, ar);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_properties(wmOperatorType *ot)
{
- ot->name = "Toggle Sidebar";
- ot->description = "Toggle the properties region visibility";
- ot->idname = "VIEW3D_OT_properties";
+ ot->name = "Toggle Sidebar";
+ ot->description = "Toggle the properties region visibility";
+ ot->idname = "VIEW3D_OT_properties";
- ot->exec = view3d_properties_toggle_exec;
- ot->poll = ED_operator_view3d_active;
+ ot->exec = view3d_properties_toggle_exec;
+ ot->poll = ED_operator_view3d_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
static int view3d_object_mode_menu(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
- if (ob == NULL) {
- BKE_report(op->reports, RPT_WARNING, "No active object found");
- return OPERATOR_CANCELLED;
- }
- else if (((ob->mode & OB_MODE_EDIT) == 0) && (ELEM(ob->type, OB_ARMATURE))) {
- ED_object_mode_toggle(C, OB_MODE_POSE);
- return OPERATOR_CANCELLED;
- }
- else {
- UI_pie_menu_invoke(C, "VIEW3D_MT_object_mode_pie", CTX_wm_window(C)->eventstate);
- return OPERATOR_CANCELLED;
- }
+ Object *ob = CTX_data_active_object(C);
+ if (ob == NULL) {
+ BKE_report(op->reports, RPT_WARNING, "No active object found");
+ return OPERATOR_CANCELLED;
+ }
+ else if (((ob->mode & OB_MODE_EDIT) == 0) && (ELEM(ob->type, OB_ARMATURE))) {
+ ED_object_mode_toggle(C, OB_MODE_POSE);
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ UI_pie_menu_invoke(C, "VIEW3D_MT_object_mode_pie", CTX_wm_window(C)->eventstate);
+ return OPERATOR_CANCELLED;
+ }
}
void VIEW3D_OT_object_mode_pie_or_toggle(wmOperatorType *ot)
{
- ot->name = "Object Mode Menu";
- ot->idname = "VIEW3D_OT_object_mode_pie_or_toggle";
+ ot->name = "Object Mode Menu";
+ ot->idname = "VIEW3D_OT_object_mode_pie_or_toggle";
- ot->exec = view3d_object_mode_menu;
- ot->poll = ED_operator_view3d_active;
+ ot->exec = view3d_object_mode_menu;
+ ot->poll = ED_operator_view3d_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c
index 3f7356de465..c8059c25e15 100644
--- a/source/blender/editors/space_view3d/view3d_camera_control.c
+++ b/source/blender/editors/space_view3d/view3d_camera_control.c
@@ -51,287 +51,277 @@
#include "ED_screen.h"
-#include "view3d_intern.h" /* own include */
+#include "view3d_intern.h" /* own include */
#include "BLI_strict_flags.h"
-
typedef struct View3DCameraControl {
- /* -------------------------------------------------------------------- */
- /* Context (assign these to vars before use) */
- Scene *ctx_scene;
- View3D *ctx_v3d;
- RegionView3D *ctx_rv3d;
-
-
- /* -------------------------------------------------------------------- */
- /* internal vars */
+ /* -------------------------------------------------------------------- */
+ /* Context (assign these to vars before use) */
+ Scene *ctx_scene;
+ View3D *ctx_v3d;
+ RegionView3D *ctx_rv3d;
- /* for parenting calculation */
- float view_mat_prev[4][4];
+ /* -------------------------------------------------------------------- */
+ /* internal vars */
+ /* for parenting calculation */
+ float view_mat_prev[4][4];
- /* -------------------------------------------------------------------- */
- /* optional capabilities */
+ /* -------------------------------------------------------------------- */
+ /* optional capabilities */
- bool use_parent_root;
+ bool use_parent_root;
+ /* -------------------------------------------------------------------- */
+ /* initial values */
- /* -------------------------------------------------------------------- */
- /* initial values */
+ /* root most parent */
+ Object *root_parent;
- /* root most parent */
- Object *root_parent;
+ /* backup values */
+ float dist_backup;
+ /* backup the views distance since we use a zero dist for fly mode */
+ float ofs_backup[3];
+ /* backup the views offset in case the user cancels flying in non camera mode */
- /* backup values */
- float dist_backup;
- /* backup the views distance since we use a zero dist for fly mode */
- float ofs_backup[3];
- /* backup the views offset in case the user cancels flying in non camera mode */
+ /* backup the views quat in case the user cancels flying in non camera mode.
+ * (quat for view, eul for camera) */
+ float rot_backup[4];
+ /* remember if were ortho or not, only used for restoring the view if it was a ortho view */
+ char persp_backup;
- /* backup the views quat in case the user cancels flying in non camera mode.
- * (quat for view, eul for camera) */
- float rot_backup[4];
- /* remember if were 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,
+ * which was originally in ortho view?
+ * could probably figure it out but better be explicit */
+ bool is_ortho_cam;
- /* are we flying an ortho camera in perspective view,
- * which was originally in ortho view?
- * could probably figure it out but better be explicit */
- bool is_ortho_cam;
-
- /* backup the objects transform */
- void *obtfm;
+ /* backup the objects transform */
+ void *obtfm;
} View3DCameraControl;
-
BLI_INLINE Object *view3d_cameracontrol_object(View3DCameraControl *vctrl)
{
- return vctrl->root_parent ? vctrl->root_parent : vctrl->ctx_v3d->camera;
+ return vctrl->root_parent ? vctrl->root_parent : vctrl->ctx_v3d->camera;
}
-
/**
* Returns the object which is being manipulated or NULL.
*/
Object *ED_view3d_cameracontrol_object_get(View3DCameraControl *vctrl)
{
- RegionView3D *rv3d = vctrl->ctx_rv3d;
-
- if (rv3d->persp == RV3D_CAMOB) {
- return view3d_cameracontrol_object(vctrl);
- }
- else {
- return NULL;
- }
+ RegionView3D *rv3d = vctrl->ctx_rv3d;
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ return view3d_cameracontrol_object(vctrl);
+ }
+ else {
+ return NULL;
+ }
}
-
/**
* Creates a #View3DCameraControl handle and sets up
* the view for first-person style navigation.
*/
-struct View3DCameraControl *ED_view3d_cameracontrol_acquire(
- Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d,
- const bool use_parent_root)
+struct View3DCameraControl *ED_view3d_cameracontrol_acquire(Depsgraph *depsgraph,
+ Scene *scene,
+ View3D *v3d,
+ RegionView3D *rv3d,
+ const bool use_parent_root)
{
- View3DCameraControl *vctrl;
-
- vctrl = MEM_callocN(sizeof(View3DCameraControl), __func__);
-
- /* Store context */
- vctrl->ctx_scene = scene;
- vctrl->ctx_v3d = v3d;
- vctrl->ctx_rv3d = rv3d;
-
- vctrl->use_parent_root = use_parent_root;
-
- vctrl->persp_backup = rv3d->persp;
- vctrl->dist_backup = rv3d->dist;
-
- /* check for flying ortho camera - which we cant support well
- * we _could_ also check for an ortho camera but this is easier */
- if ((rv3d->persp == RV3D_CAMOB) &&
- (rv3d->is_persp == false))
- {
- ((Camera *)v3d->camera->data)->type = CAM_PERSP;
- vctrl->is_ortho_cam = true;
- }
-
- if (rv3d->persp == RV3D_CAMOB) {
- Object *ob_back;
- if (use_parent_root && (vctrl->root_parent = v3d->camera->parent)) {
- while (vctrl->root_parent->parent) {
- vctrl->root_parent = vctrl->root_parent->parent;
- }
- ob_back = vctrl->root_parent;
- }
- else {
- ob_back = v3d->camera;
- }
-
- /* store the original camera loc and rot */
- vctrl->obtfm = BKE_object_tfm_backup(ob_back);
-
- BKE_object_where_is_calc(depsgraph, scene, v3d->camera);
- negate_v3_v3(rv3d->ofs, v3d->camera->obmat[3]);
-
- rv3d->dist = 0.0;
- }
- else {
- /* perspective or ortho */
- if (rv3d->persp == RV3D_ORTHO) {
- /* if ortho projection, make perspective */
- rv3d->persp = RV3D_PERSP;
- }
-
- copy_qt_qt(vctrl->rot_backup, rv3d->viewquat);
- copy_v3_v3(vctrl->ofs_backup, rv3d->ofs);
-
- /* the dist defines a vector that is infront of the offset
- * to rotate the view about.
- * this is no good for fly mode because we
- * want to rotate about the viewers center.
- * but to correct the dist removal we must
- * alter offset so the view doesn't jump. */
-
- ED_view3d_distance_set(rv3d, 0.0f);
- /* Done with correcting for the dist */
- }
-
- ED_view3d_to_m4(vctrl->view_mat_prev, rv3d->ofs, rv3d->viewquat, rv3d->dist);
-
- return vctrl;
+ View3DCameraControl *vctrl;
+
+ vctrl = MEM_callocN(sizeof(View3DCameraControl), __func__);
+
+ /* Store context */
+ vctrl->ctx_scene = scene;
+ vctrl->ctx_v3d = v3d;
+ vctrl->ctx_rv3d = rv3d;
+
+ vctrl->use_parent_root = use_parent_root;
+
+ vctrl->persp_backup = rv3d->persp;
+ vctrl->dist_backup = rv3d->dist;
+
+ /* check for flying ortho camera - which we cant support well
+ * we _could_ also check for an ortho camera but this is easier */
+ if ((rv3d->persp == RV3D_CAMOB) && (rv3d->is_persp == false)) {
+ ((Camera *)v3d->camera->data)->type = CAM_PERSP;
+ vctrl->is_ortho_cam = true;
+ }
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ Object *ob_back;
+ if (use_parent_root && (vctrl->root_parent = v3d->camera->parent)) {
+ while (vctrl->root_parent->parent) {
+ vctrl->root_parent = vctrl->root_parent->parent;
+ }
+ ob_back = vctrl->root_parent;
+ }
+ else {
+ ob_back = v3d->camera;
+ }
+
+ /* store the original camera loc and rot */
+ vctrl->obtfm = BKE_object_tfm_backup(ob_back);
+
+ BKE_object_where_is_calc(depsgraph, scene, v3d->camera);
+ negate_v3_v3(rv3d->ofs, v3d->camera->obmat[3]);
+
+ rv3d->dist = 0.0;
+ }
+ else {
+ /* perspective or ortho */
+ if (rv3d->persp == RV3D_ORTHO) {
+ /* if ortho projection, make perspective */
+ rv3d->persp = RV3D_PERSP;
+ }
+
+ copy_qt_qt(vctrl->rot_backup, rv3d->viewquat);
+ copy_v3_v3(vctrl->ofs_backup, rv3d->ofs);
+
+ /* the dist defines a vector that is infront of the offset
+ * to rotate the view about.
+ * this is no good for fly mode because we
+ * want to rotate about the viewers center.
+ * but to correct the dist removal we must
+ * alter offset so the view doesn't jump. */
+
+ ED_view3d_distance_set(rv3d, 0.0f);
+ /* Done with correcting for the dist */
+ }
+
+ ED_view3d_to_m4(vctrl->view_mat_prev, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+
+ return vctrl;
}
-
/**
* Updates cameras from the ``rv3d`` values, optionally auto-keyframing.
*/
-void ED_view3d_cameracontrol_update(
- View3DCameraControl *vctrl,
- /* args for keyframing */
- const bool use_autokey,
- struct bContext *C, const bool do_rotate, const bool do_translate)
+void ED_view3d_cameracontrol_update(View3DCameraControl *vctrl,
+ /* args for keyframing */
+ const bool use_autokey,
+ struct bContext *C,
+ const bool do_rotate,
+ const bool do_translate)
{
- /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera
- * to the view */
+ /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera
+ * to the view */
- Scene *scene = vctrl->ctx_scene;
- View3D *v3d = vctrl->ctx_v3d;
- RegionView3D *rv3d = vctrl->ctx_rv3d;
+ Scene *scene = vctrl->ctx_scene;
+ View3D *v3d = vctrl->ctx_v3d;
+ RegionView3D *rv3d = vctrl->ctx_rv3d;
- ID *id_key;
+ ID *id_key;
- /* transform the parent or the camera? */
- if (vctrl->root_parent) {
- Object *ob_update;
+ /* transform the parent or the camera? */
+ if (vctrl->root_parent) {
+ Object *ob_update;
- float view_mat[4][4];
- float prev_view_imat[4][4];
- float diff_mat[4][4];
- float parent_mat[4][4];
+ float view_mat[4][4];
+ float prev_view_imat[4][4];
+ float diff_mat[4][4];
+ float parent_mat[4][4];
- invert_m4_m4(prev_view_imat, vctrl->view_mat_prev);
- ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
- mul_m4_m4m4(diff_mat, view_mat, prev_view_imat);
- mul_m4_m4m4(parent_mat, diff_mat, vctrl->root_parent->obmat);
+ invert_m4_m4(prev_view_imat, vctrl->view_mat_prev);
+ ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+ mul_m4_m4m4(diff_mat, view_mat, prev_view_imat);
+ mul_m4_m4m4(parent_mat, diff_mat, vctrl->root_parent->obmat);
- BKE_object_apply_mat4(vctrl->root_parent, parent_mat, true, false);
+ BKE_object_apply_mat4(vctrl->root_parent, parent_mat, true, false);
- ob_update = v3d->camera->parent;
- while (ob_update) {
- DEG_id_tag_update(&ob_update->id, ID_RECALC_TRANSFORM);
- ob_update = ob_update->parent;
- }
+ ob_update = v3d->camera->parent;
+ while (ob_update) {
+ DEG_id_tag_update(&ob_update->id, ID_RECALC_TRANSFORM);
+ ob_update = ob_update->parent;
+ }
- copy_m4_m4(vctrl->view_mat_prev, view_mat);
+ copy_m4_m4(vctrl->view_mat_prev, view_mat);
- id_key = &vctrl->root_parent->id;
- }
- else {
- float view_mat[4][4];
- float scale_mat[4][4];
- float scale_back[3];
+ id_key = &vctrl->root_parent->id;
+ }
+ else {
+ float view_mat[4][4];
+ float scale_mat[4][4];
+ float scale_back[3];
- /* even though we handle the scale matrix, this still changes over time */
- copy_v3_v3(scale_back, v3d->camera->scale);
+ /* even though we handle the scale matrix, this still changes over time */
+ copy_v3_v3(scale_back, v3d->camera->scale);
- ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
- size_to_mat4(scale_mat, v3d->camera->scale);
- mul_m4_m4m4(view_mat, view_mat, scale_mat);
+ ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+ size_to_mat4(scale_mat, v3d->camera->scale);
+ mul_m4_m4m4(view_mat, view_mat, scale_mat);
- BKE_object_apply_mat4(v3d->camera, view_mat, true, true);
+ BKE_object_apply_mat4(v3d->camera, view_mat, true, true);
- DEG_id_tag_update(&v3d->camera->id, ID_RECALC_TRANSFORM);
+ DEG_id_tag_update(&v3d->camera->id, ID_RECALC_TRANSFORM);
- copy_v3_v3(v3d->camera->scale, scale_back);
+ copy_v3_v3(v3d->camera->scale, scale_back);
- id_key = &v3d->camera->id;
- }
+ id_key = &v3d->camera->id;
+ }
- /* record the motion */
- if (use_autokey) {
- ED_view3d_camera_autokey(scene, id_key, C, do_rotate, do_translate);
- }
+ /* record the motion */
+ if (use_autokey) {
+ ED_view3d_camera_autokey(scene, id_key, C, do_rotate, do_translate);
+ }
}
-
/**
* Release view control.
*
* \param restore: Sets the view state to the values that were set
* before #ED_view3d_control_acquire was called.
*/
-void ED_view3d_cameracontrol_release(
- View3DCameraControl *vctrl,
- const bool restore)
+void ED_view3d_cameracontrol_release(View3DCameraControl *vctrl, const bool restore)
{
- View3D *v3d = vctrl->ctx_v3d;
- RegionView3D *rv3d = vctrl->ctx_rv3d;
-
- if (restore) {
- /* Revert to original view? */
- if (vctrl->persp_backup == RV3D_CAMOB) { /* a camera view */
- Object *ob_back = view3d_cameracontrol_object(vctrl);
-
- /* store the original camera loc and rot */
- BKE_object_tfm_restore(ob_back, vctrl->obtfm);
-
- DEG_id_tag_update(&ob_back->id, ID_RECALC_TRANSFORM);
- }
- else {
- /* Non Camera we need to reset the view back
- * to the original location because the user canceled. */
- copy_qt_qt(rv3d->viewquat, vctrl->rot_backup);
- rv3d->persp = vctrl->persp_backup;
- }
- /* always, is set to zero otherwise */
- copy_v3_v3(rv3d->ofs, vctrl->ofs_backup);
- rv3d->dist = vctrl->dist_backup;
- }
- else if (vctrl->persp_backup == RV3D_CAMOB) { /* camera */
- DEG_id_tag_update((ID *)view3d_cameracontrol_object(vctrl), ID_RECALC_TRANSFORM);
-
- /* always, is set to zero otherwise */
- copy_v3_v3(rv3d->ofs, vctrl->ofs_backup);
- rv3d->dist = vctrl->dist_backup;
- }
- else { /* not camera */
- /* Apply the fly mode view */
- /* restore the dist */
- ED_view3d_distance_set(rv3d, vctrl->dist_backup);
- /* Done with correcting for the dist */
- }
-
- if (vctrl->is_ortho_cam) {
- ((Camera *)v3d->camera->data)->type = CAM_ORTHO;
- }
-
- if (vctrl->obtfm) {
- MEM_freeN(vctrl->obtfm);
- }
-
- MEM_freeN(vctrl);
+ View3D *v3d = vctrl->ctx_v3d;
+ RegionView3D *rv3d = vctrl->ctx_rv3d;
+
+ if (restore) {
+ /* Revert to original view? */
+ if (vctrl->persp_backup == RV3D_CAMOB) { /* a camera view */
+ Object *ob_back = view3d_cameracontrol_object(vctrl);
+
+ /* store the original camera loc and rot */
+ BKE_object_tfm_restore(ob_back, vctrl->obtfm);
+
+ DEG_id_tag_update(&ob_back->id, ID_RECALC_TRANSFORM);
+ }
+ else {
+ /* Non Camera we need to reset the view back
+ * to the original location because the user canceled. */
+ copy_qt_qt(rv3d->viewquat, vctrl->rot_backup);
+ rv3d->persp = vctrl->persp_backup;
+ }
+ /* always, is set to zero otherwise */
+ copy_v3_v3(rv3d->ofs, vctrl->ofs_backup);
+ rv3d->dist = vctrl->dist_backup;
+ }
+ else if (vctrl->persp_backup == RV3D_CAMOB) { /* camera */
+ DEG_id_tag_update((ID *)view3d_cameracontrol_object(vctrl), ID_RECALC_TRANSFORM);
+
+ /* always, is set to zero otherwise */
+ copy_v3_v3(rv3d->ofs, vctrl->ofs_backup);
+ rv3d->dist = vctrl->dist_backup;
+ }
+ else { /* not camera */
+ /* Apply the fly mode view */
+ /* restore the dist */
+ ED_view3d_distance_set(rv3d, vctrl->dist_backup);
+ /* Done with correcting for the dist */
+ }
+
+ if (vctrl->is_ortho_cam) {
+ ((Camera *)v3d->camera->data)->type = CAM_ORTHO;
+ }
+
+ if (vctrl->obtfm) {
+ MEM_freeN(vctrl->obtfm);
+ }
+
+ MEM_freeN(vctrl);
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 3399bda1cfa..4610111aafa 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -30,7 +30,6 @@
#include "BLI_threads.h"
#include "BLI_jitter_2d.h"
-
#include "BKE_camera.h"
#include "BKE_collection.h"
#include "BKE_context.h"
@@ -91,7 +90,7 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
-#include "view3d_intern.h" /* own include */
+#include "view3d_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name General Functions
@@ -100,125 +99,131 @@
/**
* \note keep this synced with #ED_view3d_mats_rv3d_backup/#ED_view3d_mats_rv3d_restore
*/
-void ED_view3d_update_viewmat(
- Depsgraph *depsgraph, Scene *scene, View3D *v3d, ARegion *ar,
- float viewmat[4][4], float winmat[4][4], const rcti *rect)
+void ED_view3d_update_viewmat(Depsgraph *depsgraph,
+ Scene *scene,
+ View3D *v3d,
+ ARegion *ar,
+ float viewmat[4][4],
+ float winmat[4][4],
+ const rcti *rect)
{
- RegionView3D *rv3d = ar->regiondata;
-
- /* setup window matrices */
- if (winmat) {
- copy_m4_m4(rv3d->winmat, winmat);
- }
- else {
- view3d_winmatrix_set(depsgraph, ar, v3d, rect);
- }
-
- /* setup view matrix */
- if (viewmat) {
- copy_m4_m4(rv3d->viewmat, viewmat);
- }
- 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;
- }
- /* note: calls BKE_object_where_is_calc for camera... */
- view3d_viewmatrix_set(depsgraph, scene, v3d, rv3d, rect ? rect_scale : NULL);
- }
- /* update utility matrices */
- mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
- invert_m4_m4(rv3d->persinv, rv3d->persmat);
- invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
-
- /* calculate GLSL view dependent values */
-
- /* store window coordinates scaling/offset */
- if (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);
-
- rv3d->viewcamtexcofac[2] = -rv3d->viewcamtexcofac[0] * cameraborder.xmin / (float)ar->winx;
- rv3d->viewcamtexcofac[3] = -rv3d->viewcamtexcofac[1] * cameraborder.ymin / (float)ar->winy;
- }
- else {
- rv3d->viewcamtexcofac[0] = rv3d->viewcamtexcofac[1] = 1.0f;
- rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f;
- }
-
- /* calculate pixelsize factor once, is used for lights and obcenters */
- {
- /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])'
- * because of float point precision problems at large values [#23908] */
- float v1[3], v2[3];
- float len_px, len_sc;
-
- v1[0] = rv3d->persmat[0][0];
- v1[1] = rv3d->persmat[1][0];
- v1[2] = rv3d->persmat[2][0];
-
- v2[0] = rv3d->persmat[0][1];
- v2[1] = rv3d->persmat[1][1];
- v2[2] = rv3d->persmat[2][1];
-
- len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2)));
- len_sc = (float)MAX2(ar->winx, ar->winy);
-
- rv3d->pixsize = len_px / len_sc;
- }
+ RegionView3D *rv3d = ar->regiondata;
+
+ /* setup window matrices */
+ if (winmat) {
+ copy_m4_m4(rv3d->winmat, winmat);
+ }
+ else {
+ view3d_winmatrix_set(depsgraph, ar, v3d, rect);
+ }
+
+ /* setup view matrix */
+ if (viewmat) {
+ copy_m4_m4(rv3d->viewmat, viewmat);
+ }
+ 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;
+ }
+ /* note: calls BKE_object_where_is_calc for camera... */
+ view3d_viewmatrix_set(depsgraph, scene, v3d, rv3d, rect ? rect_scale : NULL);
+ }
+ /* update utility matrices */
+ mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
+ invert_m4_m4(rv3d->persinv, rv3d->persmat);
+ invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
+
+ /* calculate GLSL view dependent values */
+
+ /* store window coordinates scaling/offset */
+ if (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);
+
+ rv3d->viewcamtexcofac[2] = -rv3d->viewcamtexcofac[0] * cameraborder.xmin / (float)ar->winx;
+ rv3d->viewcamtexcofac[3] = -rv3d->viewcamtexcofac[1] * cameraborder.ymin / (float)ar->winy;
+ }
+ else {
+ rv3d->viewcamtexcofac[0] = rv3d->viewcamtexcofac[1] = 1.0f;
+ rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f;
+ }
+
+ /* calculate pixelsize factor once, is used for lights and obcenters */
+ {
+ /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])'
+ * because of float point precision problems at large values [#23908] */
+ float v1[3], v2[3];
+ float len_px, len_sc;
+
+ v1[0] = rv3d->persmat[0][0];
+ v1[1] = rv3d->persmat[1][0];
+ v1[2] = rv3d->persmat[2][0];
+
+ v2[0] = rv3d->persmat[0][1];
+ v2[1] = rv3d->persmat[1][1];
+ v2[2] = rv3d->persmat[2][1];
+
+ len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2)));
+ len_sc = (float)MAX2(ar->winx, ar->winy);
+
+ rv3d->pixsize = len_px / len_sc;
+ }
}
-static void view3d_main_region_setup_view(
- Depsgraph *depsgraph, Scene *scene,
- View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4], const rcti *rect)
+static void view3d_main_region_setup_view(Depsgraph *depsgraph,
+ Scene *scene,
+ View3D *v3d,
+ ARegion *ar,
+ float viewmat[4][4],
+ float winmat[4][4],
+ const rcti *rect)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = ar->regiondata;
- ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, rect);
+ ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, rect);
- /* set for opengl */
- GPU_matrix_projection_set(rv3d->winmat);
- GPU_matrix_set(rv3d->viewmat);
+ /* 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)
{
- if ((scene->r.scemode & R_MULTIVIEW) == 0) {
- return false;
- }
-
- if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB) {
- return false;
- }
-
- switch (v3d->stereo3d_camera) {
- case STEREO_MONO_ID:
- return false;
- break;
- case STEREO_3D_ID:
- /* win will be NULL when calling this from the selection or draw loop. */
- if ((win == NULL) || (WM_stereo3d_enabled(win, true) == false)) {
- return false;
- }
- if (((scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) != 0) &&
- !BKE_scene_multiview_is_stereo3d(&scene->r))
- {
- return false;
- }
- break;
- /* We always need the stereo calculation for left and right cameras. */
- case STEREO_LEFT_ID:
- case STEREO_RIGHT_ID:
- default:
- break;
- }
- return true;
+ if ((scene->r.scemode & R_MULTIVIEW) == 0) {
+ return false;
+ }
+
+ if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB) {
+ return false;
+ }
+
+ switch (v3d->stereo3d_camera) {
+ case STEREO_MONO_ID:
+ return false;
+ break;
+ case STEREO_3D_ID:
+ /* win will be NULL when calling this from the selection or draw loop. */
+ if ((win == NULL) || (WM_stereo3d_enabled(win, true) == false)) {
+ return false;
+ }
+ if (((scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) != 0) &&
+ !BKE_scene_multiview_is_stereo3d(&scene->r)) {
+ return false;
+ }
+ break;
+ /* We always need the stereo calculation for left and right cameras. */
+ case STEREO_LEFT_ID:
+ case STEREO_RIGHT_ID:
+ default:
+ break;
+ }
+ return true;
}
-
/* setup the view and win matrices for the multiview cameras
*
* unlike view3d_stereo3d_setup_offscreen, when view3d_stereo3d_setup is called
@@ -228,72 +233,77 @@ 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 *ar, const rcti *rect)
{
- bool is_left;
- const char *names[2] = { STEREO_LEFT_NAME, STEREO_RIGHT_NAME };
- const char *viewname;
+ bool is_left;
+ const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
+ const char *viewname;
- /* show only left or right camera */
- if (v3d->stereo3d_camera != STEREO_3D_ID) {
- v3d->multiview_eye = v3d->stereo3d_camera;
- }
+ /* show only left or right camera */
+ if (v3d->stereo3d_camera != STEREO_3D_ID) {
+ v3d->multiview_eye = v3d->stereo3d_camera;
+ }
- is_left = v3d->multiview_eye == STEREO_LEFT_ID;
- viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID];
+ is_left = v3d->multiview_eye == STEREO_LEFT_ID;
+ viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID];
- /* update the viewport matrices with the new camera */
- if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
- Camera *data, *data_eval;
- float viewmat[4][4];
- float shiftx;
+ /* update the viewport matrices with the new camera */
+ if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
+ Camera *data, *data_eval;
+ float viewmat[4][4];
+ float shiftx;
- data = (Camera *)v3d->camera->data;
- data_eval = (Camera *)DEG_get_evaluated_id(depsgraph, &data->id);
+ data = (Camera *)v3d->camera->data;
+ data_eval = (Camera *)DEG_get_evaluated_id(depsgraph, &data->id);
- shiftx = data_eval->shiftx;
+ shiftx = data_eval->shiftx;
- BLI_thread_lock(LOCK_VIEW3D);
- data_eval->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname);
+ BLI_thread_lock(LOCK_VIEW3D);
+ 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);
+ BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
+ view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, NULL, rect);
- data_eval->shiftx = shiftx;
- BLI_thread_unlock(LOCK_VIEW3D);
- }
- else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
- float viewmat[4][4];
- Object *view_ob = v3d->camera;
- Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
+ data_eval->shiftx = shiftx;
+ BLI_thread_unlock(LOCK_VIEW3D);
+ }
+ else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
+ float viewmat[4][4];
+ Object *view_ob = v3d->camera;
+ Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
- BLI_thread_lock(LOCK_VIEW3D);
- v3d->camera = camera;
+ BLI_thread_lock(LOCK_VIEW3D);
+ 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);
+ BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
+ view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, NULL, rect);
- v3d->camera = view_ob;
- BLI_thread_unlock(LOCK_VIEW3D);
- }
+ v3d->camera = view_ob;
+ BLI_thread_unlock(LOCK_VIEW3D);
+ }
}
/**
* Set the correct matrices
*/
-void ED_view3d_draw_setup_view(
- wmWindow *win, Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d,
- float viewmat[4][4], float winmat[4][4], const rcti *rect)
+void ED_view3d_draw_setup_view(wmWindow *win,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ ARegion *ar,
+ View3D *v3d,
+ float viewmat[4][4],
+ float winmat[4][4],
+ const rcti *rect)
{
- RegionView3D *rv3d = ar->regiondata;
-
- /* Setup the view matrix. */
- if (view3d_stereo3d_active(win, scene, v3d, rv3d)) {
- view3d_stereo3d_setup(depsgraph, scene, v3d, ar, rect);
- }
- else {
- view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, rect);
- }
+ RegionView3D *rv3d = ar->regiondata;
+
+ /* Setup the view matrix. */
+ if (view3d_stereo3d_active(win, scene, v3d, rv3d)) {
+ view3d_stereo3d_setup(depsgraph, scene, v3d, ar, rect);
+ }
+ else {
+ view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, rect);
+ }
}
/** \} */
@@ -302,471 +312,493 @@ void ED_view3d_draw_setup_view(
/** \name Draw View Border
* \{ */
-static void view3d_camera_border(
- const Scene *scene, struct Depsgraph *depsgraph,
- const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
- rctf *r_viewborder, const bool no_shift, const bool no_zoom)
+static void view3d_camera_border(const Scene *scene,
+ struct Depsgraph *depsgraph,
+ const ARegion *ar,
+ const View3D *v3d,
+ const RegionView3D *rv3d,
+ rctf *r_viewborder,
+ const bool no_shift,
+ const bool no_zoom)
{
- CameraParams params;
- rctf rect_view, rect_camera;
- Object *camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
-
- /* get viewport viewplane */
- BKE_camera_params_init(&params);
- BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
- if (no_zoom) {
- params.zoom = 1.0f;
- }
- BKE_camera_params_compute_viewplane(&params, ar->winx, ar->winy, 1.0f, 1.0f);
- rect_view = params.viewplane;
-
- /* get camera viewplane */
- BKE_camera_params_init(&params);
- /* fallback for non camera objects */
- params.clip_start = v3d->clip_start;
- params.clip_end = v3d->clip_end;
- BKE_camera_params_from_object(&params, camera_eval);
- if (no_shift) {
- params.shiftx = 0.0f;
- params.shifty = 0.0f;
- }
- BKE_camera_params_compute_viewplane(&params, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp);
- rect_camera = params.viewplane;
-
- /* get camera border within viewport */
- r_viewborder->xmin = ((rect_camera.xmin - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx;
- r_viewborder->xmax = ((rect_camera.xmax - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx;
- r_viewborder->ymin = ((rect_camera.ymin - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy;
- r_viewborder->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy;
+ CameraParams params;
+ rctf rect_view, rect_camera;
+ Object *camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
+
+ /* get viewport viewplane */
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
+ if (no_zoom) {
+ params.zoom = 1.0f;
+ }
+ BKE_camera_params_compute_viewplane(&params, ar->winx, ar->winy, 1.0f, 1.0f);
+ rect_view = params.viewplane;
+
+ /* get camera viewplane */
+ BKE_camera_params_init(&params);
+ /* fallback for non camera objects */
+ params.clip_start = v3d->clip_start;
+ params.clip_end = v3d->clip_end;
+ BKE_camera_params_from_object(&params, camera_eval);
+ if (no_shift) {
+ params.shiftx = 0.0f;
+ params.shifty = 0.0f;
+ }
+ BKE_camera_params_compute_viewplane(
+ &params, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp);
+ rect_camera = params.viewplane;
+
+ /* get camera border within viewport */
+ r_viewborder->xmin = ((rect_camera.xmin - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) *
+ ar->winx;
+ r_viewborder->xmax = ((rect_camera.xmax - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) *
+ ar->winx;
+ r_viewborder->ymin = ((rect_camera.ymin - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) *
+ ar->winy;
+ r_viewborder->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) *
+ ar->winy;
}
-void ED_view3d_calc_camera_border_size(
- const Scene *scene, Depsgraph *depsgraph,
- const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
- float r_size[2])
+void ED_view3d_calc_camera_border_size(const Scene *scene,
+ Depsgraph *depsgraph,
+ const ARegion *ar,
+ const View3D *v3d,
+ const RegionView3D *rv3d,
+ float r_size[2])
{
- rctf viewborder;
+ rctf viewborder;
- view3d_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, true, true);
- r_size[0] = BLI_rctf_size_x(&viewborder);
- r_size[1] = BLI_rctf_size_y(&viewborder);
+ view3d_camera_border(scene, depsgraph, ar, 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 View3D *v3d, const RegionView3D *rv3d,
- rctf *r_viewborder, const bool no_shift)
+void ED_view3d_calc_camera_border(const Scene *scene,
+ Depsgraph *depsgraph,
+ const ARegion *ar,
+ 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, ar, v3d, rv3d, r_viewborder, no_shift, false);
}
static void drawviewborder_grid3(uint shdr_pos, float x1, float x2, float y1, float y2, float fac)
{
- float x3, y3, x4, y4;
+ float x3, y3, x4, y4;
- x3 = x1 + fac * (x2 - x1);
- y3 = y1 + fac * (y2 - y1);
- x4 = x1 + (1.0f - fac) * (x2 - x1);
- y4 = y1 + (1.0f - fac) * (y2 - y1);
+ x3 = x1 + fac * (x2 - x1);
+ y3 = y1 + fac * (y2 - y1);
+ x4 = x1 + (1.0f - fac) * (x2 - x1);
+ y4 = y1 + (1.0f - fac) * (y2 - y1);
- immBegin(GPU_PRIM_LINES, 8);
+ immBegin(GPU_PRIM_LINES, 8);
- immVertex2f(shdr_pos, x1, y3);
- immVertex2f(shdr_pos, x2, y3);
+ immVertex2f(shdr_pos, x1, y3);
+ immVertex2f(shdr_pos, x2, y3);
- immVertex2f(shdr_pos, x1, y4);
- immVertex2f(shdr_pos, x2, y4);
+ immVertex2f(shdr_pos, x1, y4);
+ immVertex2f(shdr_pos, x2, y4);
- immVertex2f(shdr_pos, x3, y1);
- immVertex2f(shdr_pos, x3, y2);
+ immVertex2f(shdr_pos, x3, y1);
+ immVertex2f(shdr_pos, x3, y2);
- immVertex2f(shdr_pos, x4, y1);
- immVertex2f(shdr_pos, x4, y2);
+ immVertex2f(shdr_pos, x4, y1);
+ immVertex2f(shdr_pos, x4, y2);
- immEnd();
+ immEnd();
}
/* harmonious triangle */
static void drawviewborder_triangle(
- uint shdr_pos, float x1, float x2, float y1, float y2, const char golden, const char dir)
+ uint shdr_pos, float x1, float x2, float y1, float y2, const char golden, const char dir)
{
- float ofs;
- float w = x2 - x1;
- float h = y2 - y1;
-
- immBegin(GPU_PRIM_LINES, 6);
-
- if (w > h) {
- if (golden) {
- ofs = w * (1.0f - (1.0f / 1.61803399f));
- }
- else {
- ofs = h * (h / w);
- }
- if (dir == 'B') {
- SWAP(float, y1, y2);
- }
-
- immVertex2f(shdr_pos, x1, y1);
- immVertex2f(shdr_pos, x2, y2);
-
- immVertex2f(shdr_pos, x2, y1);
- immVertex2f(shdr_pos, x1 + (w - ofs), y2);
-
- immVertex2f(shdr_pos, x1, y2);
- immVertex2f(shdr_pos, x1 + ofs, y1);
- }
- else {
- if (golden) {
- ofs = h * (1.0f - (1.0f / 1.61803399f));
- }
- else {
- ofs = w * (w / h);
- }
- if (dir == 'B') {
- SWAP(float, x1, x2);
- }
-
- immVertex2f(shdr_pos, x1, y1);
- immVertex2f(shdr_pos, x2, y2);
-
- immVertex2f(shdr_pos, x2, y1);
- immVertex2f(shdr_pos, x1, y1 + ofs);
-
- immVertex2f(shdr_pos, x1, y2);
- immVertex2f(shdr_pos, x2, y1 + (h - ofs));
- }
-
- immEnd();
+ float ofs;
+ float w = x2 - x1;
+ float h = y2 - y1;
+
+ immBegin(GPU_PRIM_LINES, 6);
+
+ if (w > h) {
+ if (golden) {
+ ofs = w * (1.0f - (1.0f / 1.61803399f));
+ }
+ else {
+ ofs = h * (h / w);
+ }
+ if (dir == 'B') {
+ SWAP(float, y1, y2);
+ }
+
+ immVertex2f(shdr_pos, x1, y1);
+ immVertex2f(shdr_pos, x2, y2);
+
+ immVertex2f(shdr_pos, x2, y1);
+ immVertex2f(shdr_pos, x1 + (w - ofs), y2);
+
+ immVertex2f(shdr_pos, x1, y2);
+ immVertex2f(shdr_pos, x1 + ofs, y1);
+ }
+ else {
+ if (golden) {
+ ofs = h * (1.0f - (1.0f / 1.61803399f));
+ }
+ else {
+ ofs = w * (w / h);
+ }
+ if (dir == 'B') {
+ SWAP(float, x1, x2);
+ }
+
+ immVertex2f(shdr_pos, x1, y1);
+ immVertex2f(shdr_pos, x2, y2);
+
+ immVertex2f(shdr_pos, x2, y1);
+ immVertex2f(shdr_pos, x1, y1 + ofs);
+
+ immVertex2f(shdr_pos, x1, y2);
+ immVertex2f(shdr_pos, x2, y1 + (h - ofs));
+ }
+
+ immEnd();
}
static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View3D *v3d)
{
- float x1, x2, y1, y2;
- float x1i, x2i, y1i, y2i;
-
- rctf viewborder;
- Camera *ca = NULL;
- RegionView3D *rv3d = ar->regiondata;
-
- if (v3d->camera == NULL) {
- return;
- }
- if (v3d->camera->type == OB_CAMERA) {
- ca = v3d->camera->data;
- }
-
- ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, false);
- /* the offsets */
- x1 = viewborder.xmin;
- y1 = viewborder.ymin;
- x2 = viewborder.xmax;
- y2 = viewborder.ymax;
-
- GPU_line_width(1.0f);
-
- /* apply offsets so the real 3D camera shows through */
-
- /* note: quite un-scientific but without this bit extra
- * 0.0001 on the lower left the 2D border sometimes
- * obscures the 3D camera border */
- /* note: with VIEW3D_CAMERA_BORDER_HACK defined this error isn't noticeable
- * but keep it here in case we need to remove the workaround */
- x1i = (int)(x1 - 1.0001f);
- y1i = (int)(y1 - 1.0001f);
- x2i = (int)(x2 + (1.0f - 0.0001f));
- y2i = (int)(y2 + (1.0f - 0.0001f));
-
- uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- /* First, solid lines. */
- {
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- /* 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);
-
- float alpha = 1.0f;
-
- if (ca->passepartalpha != 1.0f) {
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
- alpha = ca->passepartalpha;
- }
-
- immUniformColor4f(0.0f, 0.0f, 0.0f, alpha);
-
- if (x1i > 0.0f) {
- immRectf(shdr_pos, 0.0f, winy, x1i, 0.0f);
- }
- if (x2i < winx) {
- immRectf(shdr_pos, x2i, winy, winx, 0.0f);
- }
- if (y2i < winy) {
- immRectf(shdr_pos, x1i, winy, x2i, y2i);
- }
- if (y2i > 0.0f) {
- immRectf(shdr_pos, x1i, y1i, x2i, 0.0f);
- }
-
- GPU_blend(false);
- }
-
- immUniformThemeColor(TH_BACK);
- imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i);
+ float x1, x2, y1, y2;
+ float x1i, x2i, y1i, y2i;
+
+ rctf viewborder;
+ Camera *ca = NULL;
+ RegionView3D *rv3d = ar->regiondata;
+
+ if (v3d->camera == NULL) {
+ return;
+ }
+ if (v3d->camera->type == OB_CAMERA) {
+ ca = v3d->camera->data;
+ }
+
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, false);
+ /* the offsets */
+ x1 = viewborder.xmin;
+ y1 = viewborder.ymin;
+ x2 = viewborder.xmax;
+ y2 = viewborder.ymax;
+
+ GPU_line_width(1.0f);
+
+ /* apply offsets so the real 3D camera shows through */
+
+ /* note: quite un-scientific but without this bit extra
+ * 0.0001 on the lower left the 2D border sometimes
+ * obscures the 3D camera border */
+ /* note: with VIEW3D_CAMERA_BORDER_HACK defined this error isn't noticeable
+ * but keep it here in case we need to remove the workaround */
+ x1i = (int)(x1 - 1.0001f);
+ y1i = (int)(y1 - 1.0001f);
+ x2i = (int)(x2 + (1.0f - 0.0001f));
+ y2i = (int)(y2 + (1.0f - 0.0001f));
+
+ uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ /* First, solid lines. */
+ {
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* 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);
+
+ float alpha = 1.0f;
+
+ if (ca->passepartalpha != 1.0f) {
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
+ alpha = ca->passepartalpha;
+ }
+
+ immUniformColor4f(0.0f, 0.0f, 0.0f, alpha);
+
+ if (x1i > 0.0f) {
+ immRectf(shdr_pos, 0.0f, winy, x1i, 0.0f);
+ }
+ if (x2i < winx) {
+ immRectf(shdr_pos, x2i, winy, winx, 0.0f);
+ }
+ if (y2i < winy) {
+ immRectf(shdr_pos, x1i, winy, x2i, y2i);
+ }
+ if (y2i > 0.0f) {
+ immRectf(shdr_pos, x1i, y1i, x2i, 0.0f);
+ }
+
+ GPU_blend(false);
+ }
+
+ immUniformThemeColor(TH_BACK);
+ imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i);
#ifdef VIEW3D_CAMERA_BORDER_HACK
- if (view3d_camera_border_hack_test == true) {
- immUniformColor3ubv(view3d_camera_border_hack_col);
- imm_draw_box_wire_2d(shdr_pos, x1i + 1, y1i + 1, x2i - 1, y2i - 1);
- view3d_camera_border_hack_test = false;
- }
+ if (view3d_camera_border_hack_test == true) {
+ immUniformColor3ubv(view3d_camera_border_hack_col);
+ imm_draw_box_wire_2d(shdr_pos, x1i + 1, y1i + 1, x2i - 1, y2i - 1);
+ view3d_camera_border_hack_test = false;
+ }
#endif
- immUnbindProgram();
- }
+ immUnbindProgram();
+ }
- /* When overlays are disabled, only show camera outline & passepartout. */
- if (v3d->flag2 & V3D_HIDE_OVERLAYS) {
- return;
- }
+ /* When overlays are disabled, only show camera outline & passepartout. */
+ if (v3d->flag2 & V3D_HIDE_OVERLAYS) {
+ return;
+ }
- /* And now, the dashed lines! */
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ /* And now, the dashed lines! */
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- {
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+ {
+ 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 */
- immUniform1f("dash_width", 6.0f);
- immUniform1f("dash_factor", 0.5f);
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
- /* outer line not to confuse with object selection */
- if (v3d->flag2 & V3D_LOCK_CAMERA) {
- immUniformThemeColor(TH_REDALERT);
- imm_draw_box_wire_2d(shdr_pos, x1i - 1, y1i - 1, x2i + 1, y2i + 1);
- }
+ /* outer line not to confuse with object selection */
+ if (v3d->flag2 & V3D_LOCK_CAMERA) {
+ immUniformThemeColor(TH_REDALERT);
+ imm_draw_box_wire_2d(shdr_pos, x1i - 1, y1i - 1, x2i + 1, y2i + 1);
+ }
- immUniformThemeColor(TH_VIEW_OVERLAY);
- imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i);
- }
+ immUniformThemeColor(TH_VIEW_OVERLAY);
+ imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i);
+ }
- /* Render Border. */
- if (scene->r.mode & R_BORDER) {
- float x3, y3, x4, y4;
+ /* Render Border. */
+ if (scene->r.mode & R_BORDER) {
+ float x3, y3, x4, y4;
- x3 = floorf(x1 + (scene->r.border.xmin * (x2 - x1))) - 1;
- y3 = floorf(y1 + (scene->r.border.ymin * (y2 - y1))) - 1;
- x4 = floorf(x1 + (scene->r.border.xmax * (x2 - x1))) + (U.pixelsize - 1);
- y4 = floorf(y1 + (scene->r.border.ymax * (y2 - y1))) + (U.pixelsize - 1);
-
- immUniformColor3f(1.0f, 0.25f, 0.25f);
- imm_draw_box_wire_2d(shdr_pos, x3, y3, x4, y4);
- }
-
- /* safety border */
- if (ca) {
- immUniformThemeColorBlend(TH_VIEW_OVERLAY, TH_BACK, 0.25f);
-
- if (ca->dtx & CAM_DTX_CENTER) {
- float x3, y3;
-
- x3 = x1 + 0.5f * (x2 - x1);
- y3 = y1 + 0.5f * (y2 - y1);
-
- immBegin(GPU_PRIM_LINES, 4);
-
- immVertex2f(shdr_pos, x1, y3);
- immVertex2f(shdr_pos, x2, y3);
-
- immVertex2f(shdr_pos, x3, y1);
- immVertex2f(shdr_pos, x3, y2);
-
- immEnd();
- }
-
- if (ca->dtx & CAM_DTX_CENTER_DIAG) {
- immBegin(GPU_PRIM_LINES, 4);
-
- immVertex2f(shdr_pos, x1, y1);
- immVertex2f(shdr_pos, x2, y2);
-
- immVertex2f(shdr_pos, x1, y2);
- immVertex2f(shdr_pos, x2, y1);
-
- immEnd();
- }
-
- if (ca->dtx & CAM_DTX_THIRDS) {
- drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f / 3.0f);
- }
-
- if (ca->dtx & CAM_DTX_GOLDEN) {
- drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f - (1.0f / 1.61803399f));
- }
-
- if (ca->dtx & CAM_DTX_GOLDEN_TRI_A) {
- drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 0, 'A');
- }
-
- if (ca->dtx & CAM_DTX_GOLDEN_TRI_B) {
- drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 0, 'B');
- }
-
- if (ca->dtx & CAM_DTX_HARMONY_TRI_A) {
- drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 1, 'A');
- }
-
- if (ca->dtx & CAM_DTX_HARMONY_TRI_B) {
- drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 1, 'B');
- }
-
- if (ca->flag & CAM_SHOW_SAFE_MARGINS) {
- UI_draw_safe_areas(
- shdr_pos, x1, x2, y1, y2,
- scene->safe_areas.title, scene->safe_areas.action);
-
- if (ca->flag & CAM_SHOW_SAFE_CENTER) {
- UI_draw_safe_areas(
- shdr_pos, x1, x2, y1, y2,
- scene->safe_areas.title_center, scene->safe_areas.action_center);
- }
- }
-
- if (ca->flag & CAM_SHOWSENSOR) {
- /* determine sensor fit, and get sensor x/y, for auto fit we
- * assume and square sensor and only use sensor_x */
- float sizex = scene->r.xsch * scene->r.xasp;
- float sizey = scene->r.ysch * scene->r.yasp;
- int sensor_fit = BKE_camera_sensor_fit(ca->sensor_fit, sizex, sizey);
- float sensor_x = ca->sensor_x;
- float sensor_y = (ca->sensor_fit == CAMERA_SENSOR_FIT_AUTO) ? ca->sensor_x : ca->sensor_y;
-
- /* determine sensor plane */
- rctf rect;
-
- if (sensor_fit == CAMERA_SENSOR_FIT_HOR) {
- float sensor_scale = (x2i - x1i) / sensor_x;
- float sensor_height = sensor_scale * sensor_y;
-
- rect.xmin = x1i;
- rect.xmax = x2i;
- rect.ymin = (y1i + y2i) * 0.5f - sensor_height * 0.5f;
- rect.ymax = rect.ymin + sensor_height;
- }
- else {
- float sensor_scale = (y2i - y1i) / sensor_y;
- float sensor_width = sensor_scale * sensor_x;
-
- rect.xmin = (x1i + x2i) * 0.5f - sensor_width * 0.5f;
- rect.xmax = rect.xmin + sensor_width;
- rect.ymin = y1i;
- rect.ymax = y2i;
- }
-
- /* draw */
- immUniformThemeColorShade(TH_VIEW_OVERLAY, 100);
-
- /* TODO Was using UI_draw_roundbox_4fv(false, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f, color).
- * We'll probably need a new imm_draw_line_roundbox_dashed dor that - though in practice the
- * 2.0f round corner effect was nearly not visible anyway... */
- imm_draw_box_wire_2d(shdr_pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- }
- }
-
- immUnbindProgram();
- /* end dashed lines */
-
- /* camera name - draw in highlighted text color */
- if (ca && ((v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) && (ca->flag & CAM_SHOWNAME)) {
- UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
- BLF_draw_default(
- x1i, y1i - (0.7f * U.widget_unit), 0.0f,
- v3d->camera->id.name + 2, sizeof(v3d->camera->id.name) - 2);
- }
+ x3 = floorf(x1 + (scene->r.border.xmin * (x2 - x1))) - 1;
+ y3 = floorf(y1 + (scene->r.border.ymin * (y2 - y1))) - 1;
+ x4 = floorf(x1 + (scene->r.border.xmax * (x2 - x1))) + (U.pixelsize - 1);
+ y4 = floorf(y1 + (scene->r.border.ymax * (y2 - y1))) + (U.pixelsize - 1);
+
+ immUniformColor3f(1.0f, 0.25f, 0.25f);
+ imm_draw_box_wire_2d(shdr_pos, x3, y3, x4, y4);
+ }
+
+ /* safety border */
+ if (ca) {
+ immUniformThemeColorBlend(TH_VIEW_OVERLAY, TH_BACK, 0.25f);
+
+ if (ca->dtx & CAM_DTX_CENTER) {
+ float x3, y3;
+
+ x3 = x1 + 0.5f * (x2 - x1);
+ y3 = y1 + 0.5f * (y2 - y1);
+
+ immBegin(GPU_PRIM_LINES, 4);
+
+ immVertex2f(shdr_pos, x1, y3);
+ immVertex2f(shdr_pos, x2, y3);
+
+ immVertex2f(shdr_pos, x3, y1);
+ immVertex2f(shdr_pos, x3, y2);
+
+ immEnd();
+ }
+
+ if (ca->dtx & CAM_DTX_CENTER_DIAG) {
+ immBegin(GPU_PRIM_LINES, 4);
+
+ immVertex2f(shdr_pos, x1, y1);
+ immVertex2f(shdr_pos, x2, y2);
+
+ immVertex2f(shdr_pos, x1, y2);
+ immVertex2f(shdr_pos, x2, y1);
+
+ immEnd();
+ }
+
+ if (ca->dtx & CAM_DTX_THIRDS) {
+ drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f / 3.0f);
+ }
+
+ if (ca->dtx & CAM_DTX_GOLDEN) {
+ drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f - (1.0f / 1.61803399f));
+ }
+
+ if (ca->dtx & CAM_DTX_GOLDEN_TRI_A) {
+ drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 0, 'A');
+ }
+
+ if (ca->dtx & CAM_DTX_GOLDEN_TRI_B) {
+ drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 0, 'B');
+ }
+
+ if (ca->dtx & CAM_DTX_HARMONY_TRI_A) {
+ drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 1, 'A');
+ }
+
+ if (ca->dtx & CAM_DTX_HARMONY_TRI_B) {
+ drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 1, 'B');
+ }
+
+ if (ca->flag & CAM_SHOW_SAFE_MARGINS) {
+ UI_draw_safe_areas(
+ shdr_pos, x1, x2, y1, y2, scene->safe_areas.title, scene->safe_areas.action);
+
+ if (ca->flag & CAM_SHOW_SAFE_CENTER) {
+ UI_draw_safe_areas(shdr_pos,
+ x1,
+ x2,
+ y1,
+ y2,
+ scene->safe_areas.title_center,
+ scene->safe_areas.action_center);
+ }
+ }
+
+ if (ca->flag & CAM_SHOWSENSOR) {
+ /* determine sensor fit, and get sensor x/y, for auto fit we
+ * assume and square sensor and only use sensor_x */
+ float sizex = scene->r.xsch * scene->r.xasp;
+ float sizey = scene->r.ysch * scene->r.yasp;
+ int sensor_fit = BKE_camera_sensor_fit(ca->sensor_fit, sizex, sizey);
+ float sensor_x = ca->sensor_x;
+ float sensor_y = (ca->sensor_fit == CAMERA_SENSOR_FIT_AUTO) ? ca->sensor_x : ca->sensor_y;
+
+ /* determine sensor plane */
+ rctf rect;
+
+ if (sensor_fit == CAMERA_SENSOR_FIT_HOR) {
+ float sensor_scale = (x2i - x1i) / sensor_x;
+ float sensor_height = sensor_scale * sensor_y;
+
+ rect.xmin = x1i;
+ rect.xmax = x2i;
+ rect.ymin = (y1i + y2i) * 0.5f - sensor_height * 0.5f;
+ rect.ymax = rect.ymin + sensor_height;
+ }
+ else {
+ float sensor_scale = (y2i - y1i) / sensor_y;
+ float sensor_width = sensor_scale * sensor_x;
+
+ rect.xmin = (x1i + x2i) * 0.5f - sensor_width * 0.5f;
+ rect.xmax = rect.xmin + sensor_width;
+ rect.ymin = y1i;
+ rect.ymax = y2i;
+ }
+
+ /* draw */
+ immUniformThemeColorShade(TH_VIEW_OVERLAY, 100);
+
+ /* TODO Was using UI_draw_roundbox_4fv(false, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f, color).
+ * We'll probably need a new imm_draw_line_roundbox_dashed dor that - though in practice the
+ * 2.0f round corner effect was nearly not visible anyway... */
+ imm_draw_box_wire_2d(shdr_pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ }
+ }
+
+ immUnbindProgram();
+ /* end dashed lines */
+
+ /* camera name - draw in highlighted text color */
+ if (ca && ((v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) && (ca->flag & CAM_SHOWNAME)) {
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
+ BLF_draw_default(x1i,
+ y1i - (0.7f * U.widget_unit),
+ 0.0f,
+ v3d->camera->id.name + 2,
+ sizeof(v3d->camera->id.name) - 2);
+ }
}
static void drawrenderborder(ARegion *ar, View3D *v3d)
{
- /* use the same program for everything */
- uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ /* use the same program for everything */
+ uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- GPU_line_width(1.0f);
+ GPU_line_width(1.0f);
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+ 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 */
- immUniform4f("color", 1.0f, 0.25f, 0.25f, 1.0f);
- immUniform1f("dash_width", 6.0f);
- immUniform1f("dash_factor", 0.5f);
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniform4f("color", 1.0f, 0.25f, 0.25f, 1.0f);
+ immUniform1f("dash_width", 6.0f);
+ 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);
+ 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);
- immUnbindProgram();
+ immUnbindProgram();
}
-void ED_view3d_draw_depth(
- Depsgraph *depsgraph,
- ARegion *ar, View3D *v3d, bool alphaoverride)
+void ED_view3d_draw_depth(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, bool alphaoverride)
{
- struct bThemeState theme_state;
- Scene *scene = DEG_get_evaluated_scene(depsgraph);
- RegionView3D *rv3d = ar->regiondata;
+ struct bThemeState theme_state;
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ RegionView3D *rv3d = ar->regiondata;
- short flag = v3d->flag;
- float glalphaclip = U.glalphaclip;
- int obcenter_dia = U.obcenter_dia;
- /* temp set drawtype to solid */
- /* Setting these temporarily is not nice */
- v3d->flag &= ~V3D_SELECT_OUTLINE;
+ short flag = v3d->flag;
+ float glalphaclip = U.glalphaclip;
+ int obcenter_dia = U.obcenter_dia;
+ /* temp set drawtype to solid */
+ /* Setting these temporarily is not nice */
+ v3d->flag &= ~V3D_SELECT_OUTLINE;
- /* not that nice but means we wont zoom into billboards */
- U.glalphaclip = alphaoverride ? 0.5f : glalphaclip;
+ /* not that nice but means we wont zoom into billboards */
+ U.glalphaclip = alphaoverride ? 0.5f : glalphaclip;
- U.obcenter_dia = 0;
+ U.obcenter_dia = 0;
- /* Tools may request depth outside of regular drawing code. */
- UI_Theme_Store(&theme_state);
- UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
+ /* Tools may request depth outside of regular drawing code. */
+ 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(NULL, depsgraph, scene, ar, v3d, NULL, NULL, NULL);
- GPU_clear(GPU_DEPTH_BIT);
+ GPU_clear(GPU_DEPTH_BIT);
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_set(rv3d);
- }
- /* get surface depth without bias */
- rv3d->rflag |= RV3D_ZOFFSET_DISABLED;
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ ED_view3d_clipping_set(rv3d);
+ }
+ /* get surface depth without bias */
+ rv3d->rflag |= RV3D_ZOFFSET_DISABLED;
- GPU_depth_test(true);
+ GPU_depth_test(true);
- GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
- DRW_draw_depth_loop(depsgraph, ar, v3d, viewport);
+ GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
+ DRW_draw_depth_loop(depsgraph, ar, v3d, viewport);
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_disable();
- }
- rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED;
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ ED_view3d_clipping_disable();
+ }
+ rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED;
- /* Reset default for UI */
- GPU_depth_test(false);
+ /* Reset default for UI */
+ GPU_depth_test(false);
- U.glalphaclip = glalphaclip;
- v3d->flag = flag;
- U.obcenter_dia = obcenter_dia;
+ U.glalphaclip = glalphaclip;
+ v3d->flag = flag;
+ U.obcenter_dia = obcenter_dia;
- UI_Theme_Restore(&theme_state);
+ UI_Theme_Restore(&theme_state);
}
/* ******************** other elements ***************** */
@@ -774,241 +806,244 @@ void ED_view3d_draw_depth(
/** could move this elsewhere, but tied into #ED_view3d_grid_scale */
float ED_scene_grid_scale(Scene *scene, const char **grid_unit)
{
- /* apply units */
- if (scene->unit.system) {
- const void *usys;
- int len;
-
- bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len);
-
- if (usys) {
- int i = bUnit_GetBaseUnit(usys);
- if (grid_unit) {
- *grid_unit = bUnit_GetNameDisplay(usys, i);
- }
- return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length;
- }
- }
-
- return 1.0f;
+ /* apply units */
+ if (scene->unit.system) {
+ const void *usys;
+ int len;
+
+ bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len);
+
+ if (usys) {
+ int i = bUnit_GetBaseUnit(usys);
+ if (grid_unit) {
+ *grid_unit = bUnit_GetNameDisplay(usys, i);
+ }
+ return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length;
+ }
+ }
+
+ return 1.0f;
}
float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit)
{
- return v3d->grid * ED_scene_grid_scale(scene, grid_unit);
+ return v3d->grid * ED_scene_grid_scale(scene, grid_unit);
}
/* Simulates the grid scale that is actually viewed.
* The actual code is seen in `object_grid_frag.glsl` (see `grid_res`).
* Currently the simulation is only done when RV3D_VIEW_IS_AXIS. */
-float ED_view3d_grid_view_scale(
- Scene *scene, View3D *v3d, RegionView3D *rv3d, const char **grid_unit)
+float ED_view3d_grid_view_scale(Scene *scene,
+ View3D *v3d,
+ RegionView3D *rv3d,
+ const char **grid_unit)
{
- float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
- if (!rv3d->is_persp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
- /* Decrease the distance between grid snap points depending on zoom. */
- float grid_subdiv = v3d->gridsubdiv;
- if (grid_subdiv > 1) {
- /* Allow 3 more subdivisions (see OBJECT_engine_init). */
- grid_scale /= powf(grid_subdiv, 3);
-
- /* `3.0` was a value obtained by trial and error in order to get
- * a nice snap distance.*/
- float grid_res = 3.0 * (rv3d->dist / v3d->lens);
- float lvl = (logf(grid_res / grid_scale) / logf(grid_subdiv));
-
- CLAMP_MIN(lvl, 0.0f);
-
- grid_scale *= pow(grid_subdiv, (int)lvl);
- }
- }
-
- return grid_scale;
+ float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
+ if (!rv3d->is_persp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
+ /* Decrease the distance between grid snap points depending on zoom. */
+ float grid_subdiv = v3d->gridsubdiv;
+ if (grid_subdiv > 1) {
+ /* Allow 3 more subdivisions (see OBJECT_engine_init). */
+ grid_scale /= powf(grid_subdiv, 3);
+
+ /* `3.0` was a value obtained by trial and error in order to get
+ * a nice snap distance.*/
+ float grid_res = 3.0 * (rv3d->dist / v3d->lens);
+ float lvl = (logf(grid_res / grid_scale) / logf(grid_subdiv));
+
+ CLAMP_MIN(lvl, 0.0f);
+
+ grid_scale *= pow(grid_subdiv, (int)lvl);
+ }
+ }
+
+ return grid_scale;
}
static void draw_view_axis(RegionView3D *rv3d, const rcti *rect)
{
- const float k = U.rvisize * U.pixelsize; /* axis size */
- /* axis alpha offset (rvibright has range 0-10) */
- const int bright = - 20 * (10 - U.rvibright);
-
- /* Axis center in screen coordinates.
- *
- * - Unit size offset so small text doesn't draw outside the screen
- * - Extra X offset because of the panel expander.
- */
- const float startx = rect->xmax - (k + UI_UNIT_X * 1.5);
- const float starty = rect->ymax - (k + UI_UNIT_Y);
-
- float axis_pos[3][2];
- uchar axis_col[3][4];
-
- int axis_order[3] = {0, 1, 2};
- axis_sort_v3(rv3d->viewinv[2], axis_order);
-
- for (int axis_i = 0; axis_i < 3; axis_i++) {
- int i = axis_order[axis_i];
-
- /* get position of each axis tip on screen */
- float vec[3] = { 0.0f };
- vec[i] = 1.0f;
- mul_qt_v3(rv3d->viewquat, vec);
- axis_pos[i][0] = startx + vec[0] * k;
- axis_pos[i][1] = starty + vec[1] * k;
-
- /* get color of each axis */
- UI_GetThemeColorShade3ubv(TH_AXIS_X + i, bright, axis_col[i]); /* rgb */
- axis_col[i][3] = 255 * hypotf(vec[0], vec[1]); /* alpha */
- }
-
- /* draw axis lines */
- GPU_line_width(2.0f);
- GPU_line_smooth(true);
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint col = 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_LINES, 6);
-
- for (int axis_i = 0; axis_i < 3; axis_i++) {
- int i = axis_order[axis_i];
-
- immAttr4ubv(col, axis_col[i]);
- immVertex2f(pos, startx, starty);
- immAttr4ubv(col, axis_col[i]);
- immVertex2fv(pos, axis_pos[i]);
- }
-
- immEnd();
- immUnbindProgram();
- GPU_line_smooth(false);
-
- /* draw axis names */
- for (int axis_i = 0; axis_i < 3; axis_i++) {
- int i = axis_order[axis_i];
-
- const char axis_text[2] = {'x' + i, '\0'};
- BLF_color4ubv(BLF_default(), axis_col[i]);
- BLF_draw_default_ascii(axis_pos[i][0] + 2, axis_pos[i][1] + 2, 0.0f, axis_text, 1);
- }
+ const float k = U.rvisize * U.pixelsize; /* axis size */
+ /* axis alpha offset (rvibright has range 0-10) */
+ const int bright = -20 * (10 - U.rvibright);
+
+ /* Axis center in screen coordinates.
+ *
+ * - Unit size offset so small text doesn't draw outside the screen
+ * - Extra X offset because of the panel expander.
+ */
+ const float startx = rect->xmax - (k + UI_UNIT_X * 1.5);
+ const float starty = rect->ymax - (k + UI_UNIT_Y);
+
+ float axis_pos[3][2];
+ uchar axis_col[3][4];
+
+ int axis_order[3] = {0, 1, 2};
+ axis_sort_v3(rv3d->viewinv[2], axis_order);
+
+ for (int axis_i = 0; axis_i < 3; axis_i++) {
+ int i = axis_order[axis_i];
+
+ /* get position of each axis tip on screen */
+ float vec[3] = {0.0f};
+ vec[i] = 1.0f;
+ mul_qt_v3(rv3d->viewquat, vec);
+ axis_pos[i][0] = startx + vec[0] * k;
+ axis_pos[i][1] = starty + vec[1] * k;
+
+ /* get color of each axis */
+ UI_GetThemeColorShade3ubv(TH_AXIS_X + i, bright, axis_col[i]); /* rgb */
+ axis_col[i][3] = 255 * hypotf(vec[0], vec[1]); /* alpha */
+ }
+
+ /* draw axis lines */
+ GPU_line_width(2.0f);
+ GPU_line_smooth(true);
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col = 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_LINES, 6);
+
+ for (int axis_i = 0; axis_i < 3; axis_i++) {
+ int i = axis_order[axis_i];
+
+ immAttr4ubv(col, axis_col[i]);
+ immVertex2f(pos, startx, starty);
+ immAttr4ubv(col, axis_col[i]);
+ immVertex2fv(pos, axis_pos[i]);
+ }
+
+ immEnd();
+ immUnbindProgram();
+ GPU_line_smooth(false);
+
+ /* draw axis names */
+ for (int axis_i = 0; axis_i < 3; axis_i++) {
+ int i = axis_order[axis_i];
+
+ const char axis_text[2] = {'x' + i, '\0'};
+ BLF_color4ubv(BLF_default(), axis_col[i]);
+ BLF_draw_default_ascii(axis_pos[i][0] + 2, axis_pos[i][1] + 2, 0.0f, axis_text, 1);
+ }
}
#ifdef WITH_INPUT_NDOF
/* draw center and axis of rotation for ongoing 3D mouse navigation */
static void draw_rotation_guide(const RegionView3D *rv3d)
{
- float o[3]; /* center of rotation */
- float end[3]; /* endpoints for drawing */
-
- GLubyte color[4] = {0, 108, 255, 255}; /* bright blue so it matches device LEDs */
-
- negate_v3_v3(o, rv3d->ofs);
-
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- glDepthMask(GL_FALSE); /* don't overwrite zbuf */
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
-
- if (rv3d->rot_angle != 0.0f) {
- /* -- draw rotation axis -- */
- float scaled_axis[3];
- const float scale = rv3d->dist;
- mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale);
-
-
- immBegin(GPU_PRIM_LINE_STRIP, 3);
- color[3] = 0; /* more transparent toward the ends */
- immAttr4ubv(col, color);
- add_v3_v3v3(end, o, scaled_axis);
- immVertex3fv(pos, end);
-
-#if 0
- color[3] = 0.2f + fabsf(rv3d->rot_angle); /* modulate opacity with angle */
- /* ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 */
-#endif
-
- color[3] = 127; /* more opaque toward the center */
- immAttr4ubv(col, color);
- immVertex3fv(pos, o);
-
- color[3] = 0;
- immAttr4ubv(col, color);
- sub_v3_v3v3(end, o, scaled_axis);
- immVertex3fv(pos, end);
- immEnd();
-
- /* -- draw ring around rotation center -- */
- {
-#define ROT_AXIS_DETAIL 13
-
- const float s = 0.05f * scale;
- const float step = 2.0f * (float)(M_PI / ROT_AXIS_DETAIL);
-
- float q[4]; /* rotate ring so it's perpendicular to axis */
- const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f;
- if (!upright) {
- const float up[3] = {0.0f, 0.0f, 1.0f};
- float vis_angle, vis_axis[3];
-
- cross_v3_v3v3(vis_axis, up, rv3d->rot_axis);
- vis_angle = acosf(dot_v3v3(up, rv3d->rot_axis));
- axis_angle_to_quat(q, vis_axis, vis_angle);
- }
-
- immBegin(GPU_PRIM_LINE_LOOP, ROT_AXIS_DETAIL);
- color[3] = 63; /* somewhat faint */
- immAttr4ubv(col, color);
- float angle = 0.0f;
- for (int i = 0; i < ROT_AXIS_DETAIL; ++i, angle += step) {
- float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f};
-
- if (!upright) {
- mul_qt_v3(q, p);
- }
-
- add_v3_v3(p, o);
- immVertex3fv(pos, p);
- }
- immEnd();
-
-#undef ROT_AXIS_DETAIL
- }
-
- color[3] = 255; /* solid dot */
- }
- else {
- color[3] = 127; /* see-through dot */
- }
-
- immUnbindProgram();
-
- /* -- draw rotation center -- */
- immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR);
- GPU_point_size(5.0f);
- immBegin(GPU_PRIM_POINTS, 1);
- immAttr4ubv(col, color);
- immVertex3fv(pos, o);
- immEnd();
- immUnbindProgram();
-
-#if 0
- /* find screen coordinates for rotation center, then draw pretty icon */
- mul_m4_v3(rv3d->persinv, rot_center);
- UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN);
- /* ^^ just playing around, does not work */
-#endif
-
- GPU_blend(false);
- glDepthMask(GL_TRUE);
+ float o[3]; /* center of rotation */
+ float end[3]; /* endpoints for drawing */
+
+ GLubyte color[4] = {0, 108, 255, 255}; /* bright blue so it matches device LEDs */
+
+ negate_v3_v3(o, rv3d->ofs);
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ glDepthMask(GL_FALSE); /* don't overwrite zbuf */
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
+
+ if (rv3d->rot_angle != 0.0f) {
+ /* -- draw rotation axis -- */
+ float scaled_axis[3];
+ const float scale = rv3d->dist;
+ mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale);
+
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
+ color[3] = 0; /* more transparent toward the ends */
+ immAttr4ubv(col, color);
+ add_v3_v3v3(end, o, scaled_axis);
+ immVertex3fv(pos, end);
+
+# if 0
+ color[3] = 0.2f + fabsf(rv3d->rot_angle); /* modulate opacity with angle */
+ /* ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 */
+# endif
+
+ color[3] = 127; /* more opaque toward the center */
+ immAttr4ubv(col, color);
+ immVertex3fv(pos, o);
+
+ color[3] = 0;
+ immAttr4ubv(col, color);
+ sub_v3_v3v3(end, o, scaled_axis);
+ immVertex3fv(pos, end);
+ immEnd();
+
+ /* -- draw ring around rotation center -- */
+ {
+# define ROT_AXIS_DETAIL 13
+
+ const float s = 0.05f * scale;
+ const float step = 2.0f * (float)(M_PI / ROT_AXIS_DETAIL);
+
+ float q[4]; /* rotate ring so it's perpendicular to axis */
+ const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f;
+ if (!upright) {
+ const float up[3] = {0.0f, 0.0f, 1.0f};
+ float vis_angle, vis_axis[3];
+
+ cross_v3_v3v3(vis_axis, up, rv3d->rot_axis);
+ vis_angle = acosf(dot_v3v3(up, rv3d->rot_axis));
+ axis_angle_to_quat(q, vis_axis, vis_angle);
+ }
+
+ immBegin(GPU_PRIM_LINE_LOOP, ROT_AXIS_DETAIL);
+ color[3] = 63; /* somewhat faint */
+ immAttr4ubv(col, color);
+ float angle = 0.0f;
+ for (int i = 0; i < ROT_AXIS_DETAIL; ++i, angle += step) {
+ float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f};
+
+ if (!upright) {
+ mul_qt_v3(q, p);
+ }
+
+ add_v3_v3(p, o);
+ immVertex3fv(pos, p);
+ }
+ immEnd();
+
+# undef ROT_AXIS_DETAIL
+ }
+
+ color[3] = 255; /* solid dot */
+ }
+ else {
+ color[3] = 127; /* see-through dot */
+ }
+
+ immUnbindProgram();
+
+ /* -- draw rotation center -- */
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR);
+ GPU_point_size(5.0f);
+ immBegin(GPU_PRIM_POINTS, 1);
+ immAttr4ubv(col, color);
+ immVertex3fv(pos, o);
+ immEnd();
+ immUnbindProgram();
+
+# if 0
+ /* find screen coordinates for rotation center, then draw pretty icon */
+ mul_m4_v3(rv3d->persinv, rot_center);
+ UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN);
+ /* ^^ just playing around, does not work */
+# endif
+
+ GPU_blend(false);
+ glDepthMask(GL_TRUE);
}
#endif /* WITH_INPUT_NDOF */
@@ -1017,17 +1052,17 @@ static void draw_rotation_guide(const RegionView3D *rv3d)
*/
static void view3d_draw_border(const bContext *C, ARegion *ar)
{
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- RegionView3D *rv3d = ar->regiondata;
- View3D *v3d = CTX_wm_view3d(C);
-
- if (rv3d->persp == RV3D_CAMOB) {
- drawviewborder(scene, depsgraph, ar, v3d);
- }
- else if (v3d->flag2 & V3D_RENDER_BORDER) {
- drawrenderborder(ar, v3d);
- }
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ RegionView3D *rv3d = ar->regiondata;
+ View3D *v3d = CTX_wm_view3d(C);
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ drawviewborder(scene, depsgraph, ar, v3d);
+ }
+ else if (v3d->flag2 & V3D_RENDER_BORDER) {
+ drawrenderborder(ar, v3d);
+ }
}
/** \} */
@@ -1041,7 +1076,7 @@ static void view3d_draw_border(const bContext *C, ARegion *ar)
*/
static void view3d_draw_grease_pencil(const bContext *UNUSED(C))
{
- /* TODO viewport */
+ /* TODO viewport */
}
/**
@@ -1049,119 +1084,120 @@ static void view3d_draw_grease_pencil(const bContext *UNUSED(C))
*/
static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
{
- const char *name = NULL;
-
- switch (rv3d->view) {
- case RV3D_VIEW_FRONT:
- if (rv3d->persp == RV3D_ORTHO) {
- name = IFACE_("Front Orthographic");
- }
- else {
- name = IFACE_("Front Perspective");
- }
- break;
- case RV3D_VIEW_BACK:
- if (rv3d->persp == RV3D_ORTHO) {
- name = IFACE_("Back Orthographic");
- }
- else {
- name = IFACE_("Back Perspective");
- }
- break;
- case RV3D_VIEW_TOP:
- if (rv3d->persp == RV3D_ORTHO) {
- name = IFACE_("Top Orthographic");
- }
- else {
- name = IFACE_("Top Perspective");
- }
- break;
- case RV3D_VIEW_BOTTOM:
- if (rv3d->persp == RV3D_ORTHO) {
- name = IFACE_("Bottom Orthographic");
- }
- else {
- name = IFACE_("Bottom Perspective");
- }
- break;
- case RV3D_VIEW_RIGHT:
- if (rv3d->persp == RV3D_ORTHO) {
- name = IFACE_("Right Orthographic");
- }
- else {
- name = IFACE_("Right Perspective");
- }
- break;
- case RV3D_VIEW_LEFT:
- if (rv3d->persp == RV3D_ORTHO) {
- name = IFACE_("Left Orthographic");
- }
- else {
- name = IFACE_("Left Perspective");
- }
- break;
-
- default:
- if (rv3d->persp == RV3D_CAMOB) {
- if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
- Camera *cam;
- cam = v3d->camera->data;
- if (cam->type == CAM_PERSP) {
- name = IFACE_("Camera Perspective");
- }
- else if (cam->type == CAM_ORTHO) {
- name = IFACE_("Camera Orthographic");
- }
- else {
- BLI_assert(cam->type == CAM_PANO);
- name = IFACE_("Camera Panoramic");
- }
- }
- else {
- name = IFACE_("Object as Camera");
- }
- }
- else {
- name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Orthographic") : IFACE_("User Perspective");
- }
- }
-
- return name;
+ const char *name = NULL;
+
+ switch (rv3d->view) {
+ case RV3D_VIEW_FRONT:
+ if (rv3d->persp == RV3D_ORTHO) {
+ name = IFACE_("Front Orthographic");
+ }
+ else {
+ name = IFACE_("Front Perspective");
+ }
+ break;
+ case RV3D_VIEW_BACK:
+ if (rv3d->persp == RV3D_ORTHO) {
+ name = IFACE_("Back Orthographic");
+ }
+ else {
+ name = IFACE_("Back Perspective");
+ }
+ break;
+ case RV3D_VIEW_TOP:
+ if (rv3d->persp == RV3D_ORTHO) {
+ name = IFACE_("Top Orthographic");
+ }
+ else {
+ name = IFACE_("Top Perspective");
+ }
+ break;
+ case RV3D_VIEW_BOTTOM:
+ if (rv3d->persp == RV3D_ORTHO) {
+ name = IFACE_("Bottom Orthographic");
+ }
+ else {
+ name = IFACE_("Bottom Perspective");
+ }
+ break;
+ case RV3D_VIEW_RIGHT:
+ if (rv3d->persp == RV3D_ORTHO) {
+ name = IFACE_("Right Orthographic");
+ }
+ else {
+ name = IFACE_("Right Perspective");
+ }
+ break;
+ case RV3D_VIEW_LEFT:
+ if (rv3d->persp == RV3D_ORTHO) {
+ name = IFACE_("Left Orthographic");
+ }
+ else {
+ name = IFACE_("Left Perspective");
+ }
+ break;
+
+ default:
+ if (rv3d->persp == RV3D_CAMOB) {
+ if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
+ Camera *cam;
+ cam = v3d->camera->data;
+ if (cam->type == CAM_PERSP) {
+ name = IFACE_("Camera Perspective");
+ }
+ else if (cam->type == CAM_ORTHO) {
+ name = IFACE_("Camera Orthographic");
+ }
+ else {
+ BLI_assert(cam->type == CAM_PANO);
+ name = IFACE_("Camera Panoramic");
+ }
+ }
+ else {
+ name = IFACE_("Object as Camera");
+ }
+ }
+ else {
+ name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Orthographic") :
+ IFACE_("User Perspective");
+ }
+ }
+
+ return name;
}
static void draw_viewport_name(ARegion *ar, View3D *v3d, int xoffset, int *yoffset)
{
- RegionView3D *rv3d = ar->regiondata;
- const char *name = view3d_get_name(v3d, rv3d);
- const int font_id = BLF_default();
+ RegionView3D *rv3d = ar->regiondata;
+ const char *name = view3d_get_name(v3d, rv3d);
+ const int font_id = BLF_default();
- /* increase size for unicode languages (Chinese in utf-8...) */
+ /* increase size for unicode languages (Chinese in utf-8...) */
#ifdef WITH_INTERNATIONAL
- char tmpstr[96];
+ char tmpstr[96];
#else
- char tmpstr[32];
+ char tmpstr[32];
#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);
+ 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 (v3d->localvd) {
- BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name);
- name = tmpstr;
- }
+ if (v3d->localvd) {
+ BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name);
+ name = tmpstr;
+ }
- UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
- *yoffset -= U.widget_unit;
+ *yoffset -= U.widget_unit;
#ifdef WITH_INTERNATIONAL
- BLF_draw_default(xoffset, *yoffset, 0.0f, name, sizeof(tmpstr));
+ BLF_draw_default(xoffset, *yoffset, 0.0f, name, sizeof(tmpstr));
#else
- BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, name, sizeof(tmpstr));
+ BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, name, sizeof(tmpstr));
#endif
- BLF_disable(font_id, BLF_SHADOW);
+ BLF_disable(font_id, BLF_SHADOW);
}
/**
@@ -1169,125 +1205,130 @@ static void draw_viewport_name(ARegion *ar, View3D *v3d, int xoffset, int *yoffs
* framenum, collection, object name, bone name (if available), marker name (if available)
*/
-static void draw_selected_name(Scene *scene, ViewLayer *view_layer, Object *ob, int xoffset, int *yoffset)
+static void draw_selected_name(
+ Scene *scene, ViewLayer *view_layer, Object *ob, int xoffset, int *yoffset)
{
- const int cfra = CFRA;
- const char *msg_pin = " (Pinned)";
- const char *msg_sep = " : ";
-
- const int font_id = BLF_default();
-
- char info[300];
- char *s = info;
-
- s += sprintf(s, "(%d)", cfra);
-
- if ((ob == NULL) || (ob->mode == OB_MODE_OBJECT)) {
- LayerCollection *layer_collection = view_layer->active_collection;
- s += sprintf(s, " %s%s", BKE_collection_ui_name_get(layer_collection->collection), (ob == NULL) ? "" : " |");
- }
-
- /*
- * info can contain:
- * - a frame (7 + 2)
- * - a collection name (MAX_NAME + 3)
- * - 3 object names (MAX_NAME)
- * - 2 BREAD_CRUMB_SEPARATORs (6)
- * - a SHAPE_KEY_PINNED marker and a trailing '\0' (9+1) - translated, so give some room!
- * - a marker name (MAX_NAME + 3)
- */
-
- /* get name of marker on current frame (if available) */
- const char *markern = BKE_scene_find_marker_name(scene, cfra);
-
- /* check if there is an object */
- if (ob) {
- *s++ = ' ';
- s += BLI_strcpy_rlen(s, ob->id.name + 2);
-
- /* name(s) to display depends on type of object */
- if (ob->type == OB_ARMATURE) {
- bArmature *arm = ob->data;
-
- /* show name of active bone too (if possible) */
- if (arm->edbo) {
- if (arm->act_edbone) {
- s += BLI_strcpy_rlen(s, msg_sep);
- s += BLI_strcpy_rlen(s, arm->act_edbone->name);
- }
- }
- else if (ob->mode & OB_MODE_POSE) {
- if (arm->act_bone) {
-
- if (arm->act_bone->layer & arm->layer) {
- s += BLI_strcpy_rlen(s, msg_sep);
- s += BLI_strcpy_rlen(s, arm->act_bone->name);
- }
- }
- }
- }
- else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
- /* try to display active bone and active shapekey too (if they exist) */
-
- if (ob->type == OB_MESH && ob->mode & OB_MODE_WEIGHT_PAINT) {
- Object *armobj = BKE_object_pose_armature_get(ob);
- if (armobj && armobj->mode & OB_MODE_POSE) {
- bArmature *arm = armobj->data;
- if (arm->act_bone) {
- if (arm->act_bone->layer & arm->layer) {
- s += BLI_strcpy_rlen(s, msg_sep);
- s += BLI_strcpy_rlen(s, arm->act_bone->name);
- }
- }
- }
- }
-
- Key *key = BKE_key_from_object(ob);
- if (key) {
- KeyBlock *kb = BLI_findlink(&key->block, ob->shapenr - 1);
- if (kb) {
- s += BLI_strcpy_rlen(s, msg_sep);
- s += BLI_strcpy_rlen(s, kb->name);
- if (ob->shapeflag & OB_SHAPE_LOCK) {
- s += BLI_strcpy_rlen(s, IFACE_(msg_pin));
- }
- }
- }
- }
-
- /* color depends on whether there is a keyframe */
- if (id_frame_has_keyframe((ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) {
- UI_FontThemeColor(font_id, TH_TIME_KEYFRAME);
- }
- else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra)) {
- UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME);
- }
- else {
- UI_FontThemeColor(font_id, TH_TEXT_HI);
- }
- }
- else {
- /* no object */
- if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra)) {
- UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME);
- }
- else {
- UI_FontThemeColor(font_id, TH_TEXT_HI);
- }
- }
-
- if (markern) {
- s += sprintf(s, " <%s>", markern);
- }
-
- 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;
- BLF_draw_default(xoffset, *yoffset, 0.0f, info, sizeof(info));
-
- BLF_disable(font_id, BLF_SHADOW);
+ const int cfra = CFRA;
+ const char *msg_pin = " (Pinned)";
+ const char *msg_sep = " : ";
+
+ const int font_id = BLF_default();
+
+ char info[300];
+ char *s = info;
+
+ s += sprintf(s, "(%d)", cfra);
+
+ if ((ob == NULL) || (ob->mode == OB_MODE_OBJECT)) {
+ LayerCollection *layer_collection = view_layer->active_collection;
+ s += sprintf(s,
+ " %s%s",
+ BKE_collection_ui_name_get(layer_collection->collection),
+ (ob == NULL) ? "" : " |");
+ }
+
+ /*
+ * info can contain:
+ * - a frame (7 + 2)
+ * - a collection name (MAX_NAME + 3)
+ * - 3 object names (MAX_NAME)
+ * - 2 BREAD_CRUMB_SEPARATORs (6)
+ * - a SHAPE_KEY_PINNED marker and a trailing '\0' (9+1) - translated, so give some room!
+ * - a marker name (MAX_NAME + 3)
+ */
+
+ /* get name of marker on current frame (if available) */
+ const char *markern = BKE_scene_find_marker_name(scene, cfra);
+
+ /* check if there is an object */
+ if (ob) {
+ *s++ = ' ';
+ s += BLI_strcpy_rlen(s, ob->id.name + 2);
+
+ /* name(s) to display depends on type of object */
+ if (ob->type == OB_ARMATURE) {
+ bArmature *arm = ob->data;
+
+ /* show name of active bone too (if possible) */
+ if (arm->edbo) {
+ if (arm->act_edbone) {
+ s += BLI_strcpy_rlen(s, msg_sep);
+ s += BLI_strcpy_rlen(s, arm->act_edbone->name);
+ }
+ }
+ else if (ob->mode & OB_MODE_POSE) {
+ if (arm->act_bone) {
+
+ if (arm->act_bone->layer & arm->layer) {
+ s += BLI_strcpy_rlen(s, msg_sep);
+ s += BLI_strcpy_rlen(s, arm->act_bone->name);
+ }
+ }
+ }
+ }
+ else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
+ /* try to display active bone and active shapekey too (if they exist) */
+
+ if (ob->type == OB_MESH && ob->mode & OB_MODE_WEIGHT_PAINT) {
+ Object *armobj = BKE_object_pose_armature_get(ob);
+ if (armobj && armobj->mode & OB_MODE_POSE) {
+ bArmature *arm = armobj->data;
+ if (arm->act_bone) {
+ if (arm->act_bone->layer & arm->layer) {
+ s += BLI_strcpy_rlen(s, msg_sep);
+ s += BLI_strcpy_rlen(s, arm->act_bone->name);
+ }
+ }
+ }
+ }
+
+ Key *key = BKE_key_from_object(ob);
+ if (key) {
+ KeyBlock *kb = BLI_findlink(&key->block, ob->shapenr - 1);
+ if (kb) {
+ s += BLI_strcpy_rlen(s, msg_sep);
+ s += BLI_strcpy_rlen(s, kb->name);
+ if (ob->shapeflag & OB_SHAPE_LOCK) {
+ s += BLI_strcpy_rlen(s, IFACE_(msg_pin));
+ }
+ }
+ }
+ }
+
+ /* color depends on whether there is a keyframe */
+ if (id_frame_has_keyframe(
+ (ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) {
+ UI_FontThemeColor(font_id, TH_TIME_KEYFRAME);
+ }
+ else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra)) {
+ UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME);
+ }
+ else {
+ UI_FontThemeColor(font_id, TH_TEXT_HI);
+ }
+ }
+ else {
+ /* no object */
+ if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra)) {
+ UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME);
+ }
+ else {
+ UI_FontThemeColor(font_id, TH_TEXT_HI);
+ }
+ }
+
+ if (markern) {
+ s += sprintf(s, " <%s>", markern);
+ }
+
+ 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;
+ BLF_draw_default(xoffset, *yoffset, 0.0f, info, sizeof(info));
+
+ BLF_disable(font_id, BLF_SHADOW);
}
/**
@@ -1295,83 +1336,77 @@ static void draw_selected_name(Scene *scene, ViewLayer *view_layer, Object *ob,
*/
void view3d_draw_region_info(const bContext *C, ARegion *ar)
{
- RegionView3D *rv3d = ar->regiondata;
- View3D *v3d = CTX_wm_view3d(C);
- Scene *scene = CTX_data_scene(C);
- wmWindowManager *wm = CTX_wm_manager(C);
+ RegionView3D *rv3d = ar->regiondata;
+ View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
#ifdef WITH_INPUT_NDOF
- if ((U.ndof_flag & NDOF_SHOW_GUIDE) &&
- ((rv3d->viewlock & RV3D_LOCKED) == 0) &&
- (rv3d->persp != RV3D_CAMOB))
- {
- /* TODO: draw something else (but not this) during fly mode */
- draw_rotation_guide(rv3d);
- }
+ if ((U.ndof_flag & NDOF_SHOW_GUIDE) && ((rv3d->viewlock & RV3D_LOCKED) == 0) &&
+ (rv3d->persp != RV3D_CAMOB)) {
+ /* TODO: draw something else (but not this) during fly mode */
+ draw_rotation_guide(rv3d);
+ }
#endif
- /* correct projection matrix */
- ED_region_pixelspace(ar);
+ /* correct projection matrix */
+ ED_region_pixelspace(ar);
- /* local coordinate visible rect inside region, to accommodate overlapping ui */
- rcti rect;
- ED_region_visible_rect(ar, &rect);
+ /* local coordinate visible rect inside region, to accommodate overlapping ui */
+ rcti rect;
+ ED_region_visible_rect(ar, &rect);
+ view3d_draw_border(C, ar);
+ view3d_draw_grease_pencil(C);
- view3d_draw_border(C, ar);
- view3d_draw_grease_pencil(C);
+ BLF_batch_draw_begin();
- BLF_batch_draw_begin();
+ if ((U.uiflag & USER_SHOW_GIZMO_AXIS) ||
+ /* No need to display gizmo and this info. */
+ (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_NAVIGATE))) {
+ /* pass */
+ }
+ else {
+ draw_view_axis(rv3d, &rect);
+ }
- if ((U.uiflag & USER_SHOW_GIZMO_AXIS) ||
- /* No need to display gizmo and this info. */
- (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_NAVIGATE)))
- {
- /* pass */
- }
- else {
- draw_view_axis(rv3d, &rect);
- }
+ int xoffset = rect.xmin + U.widget_unit;
+ int yoffset = rect.ymax;
- int xoffset = rect.xmin + U.widget_unit;
- int yoffset = rect.ymax;
+ 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);
+ }
- 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);
- }
-
- 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);
- }
+ 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);
+ }
#if 0 /* TODO */
- if (grid_unit) { /* draw below the viewport name */
- char numstr[32] = "";
+ if (grid_unit) { /* draw below the viewport name */
+ char numstr[32] = "";
- UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
- if (v3d->grid != 1.0f) {
- BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
- }
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
+ if (v3d->grid != 1.0f) {
+ BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
+ }
- *yoffset -= U.widget_unit;
- BLF_draw_default_ascii(xoffset, *yoffset, numstr[0] ? numstr : grid_unit, sizeof(numstr));
- }
+ *yoffset -= U.widget_unit;
+ BLF_draw_default_ascii(xoffset, *yoffset, numstr[0] ? numstr : grid_unit, sizeof(numstr));
+ }
#endif
- }
+ }
- if ((v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) {
- DRW_draw_region_engine_info(xoffset, yoffset);
- }
+ if ((v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) {
+ DRW_draw_region_engine_info(xoffset, yoffset);
+ }
- BLF_batch_draw_end();
+ BLF_batch_draw_end();
}
/** \} */
@@ -1382,43 +1417,50 @@ void view3d_draw_region_info(const bContext *C, ARegion *ar)
static void view3d_draw_view(const bContext *C, ARegion *ar)
{
- ED_view3d_draw_setup_view(CTX_wm_window(C), CTX_data_depsgraph(C), CTX_data_scene(C), ar, CTX_wm_view3d(C), NULL, NULL, NULL);
-
- /* Only 100% compliant on new spec goes below */
- DRW_draw_view(C);
+ ED_view3d_draw_setup_view(CTX_wm_window(C),
+ CTX_data_depsgraph(C),
+ CTX_data_scene(C),
+ ar,
+ CTX_wm_view3d(C),
+ NULL,
+ NULL,
+ NULL);
+
+ /* Only 100% compliant on new spec goes below */
+ DRW_draw_view(C);
}
RenderEngineType *ED_view3d_engine_type(Scene *scene, int drawtype)
{
- /*
- * Temporary viewport draw modes until we have a proper system.
- * all modes are done in the draw manager, except
- * cycles material as it is an external render engine.
- */
- if (strcmp(scene->r.engine, RE_engine_id_CYCLES) == 0 && drawtype == OB_MATERIAL) {
- return RE_engines_find(RE_engine_id_BLENDER_EEVEE);
- }
- return RE_engines_find(scene->r.engine);
+ /*
+ * Temporary viewport draw modes until we have a proper system.
+ * all modes are done in the draw manager, except
+ * cycles material as it is an external render engine.
+ */
+ if (strcmp(scene->r.engine, RE_engine_id_CYCLES) == 0 && drawtype == OB_MATERIAL) {
+ return RE_engines_find(RE_engine_id_BLENDER_EEVEE);
+ }
+ return RE_engines_find(scene->r.engine);
}
void view3d_main_region_draw(const bContext *C, ARegion *ar)
{
- Main *bmain = CTX_data_main(C);
- View3D *v3d = CTX_wm_view3d(C);
+ Main *bmain = CTX_data_main(C);
+ View3D *v3d = CTX_wm_view3d(C);
- view3d_draw_view(C, ar);
+ view3d_draw_view(C, ar);
- GPU_free_images_old(bmain);
- GPU_pass_cache_garbage_collect();
+ GPU_free_images_old(bmain);
+ GPU_pass_cache_garbage_collect();
- /* XXX This is in order to draw UI batches with the DRW
- * olg context since we now use it for drawing the entire area */
- gpu_batch_presets_reset();
+ /* XXX This is in order to draw UI batches with the DRW
+ * olg context since we now use it for drawing the entire area */
+ gpu_batch_presets_reset();
- /* No depth test for drawing action zones afterwards. */
- GPU_depth_test(false);
+ /* No depth test for drawing action zones afterwards. */
+ GPU_depth_test(false);
- v3d->flag |= V3D_INVALID_BACKBUF;
+ v3d->flag |= V3D_INVALID_BACKBUF;
}
/** \} */
@@ -1427,92 +1469,103 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar)
/** \name Offscreen Drawing
* \{ */
-static void view3d_stereo3d_setup_offscreen(
- Depsgraph *depsgraph, Scene *scene, View3D *v3d, ARegion *ar,
- float winmat[4][4], const char *viewname)
+static void view3d_stereo3d_setup_offscreen(Depsgraph *depsgraph,
+ Scene *scene,
+ View3D *v3d,
+ ARegion *ar,
+ float winmat[4][4],
+ const char *viewname)
{
- /* update the viewport matrices with the new camera */
- if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
- float viewmat[4][4];
- const bool is_left = STREQ(viewname, STEREO_LEFT_NAME);
-
- BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
- view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL);
- }
- else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
- float viewmat[4][4];
- Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
-
- BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
- view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL);
- }
+ /* update the viewport matrices with the new camera */
+ if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
+ float viewmat[4][4];
+ const bool is_left = STREQ(viewname, STEREO_LEFT_NAME);
+
+ BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
+ view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL);
+ }
+ else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
+ float viewmat[4][4];
+ Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
+
+ BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
+ view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL);
+ }
}
-void ED_view3d_draw_offscreen(
- Depsgraph *depsgraph, Scene *scene,
- int drawtype,
- View3D *v3d, ARegion *ar, int winx, int winy,
- float viewmat[4][4], float winmat[4][4],
- bool do_sky, bool UNUSED(is_persp), const char *viewname,
- GPUFXSettings *UNUSED(fx_settings), const bool do_color_management,
- GPUOffScreen *ofs, GPUViewport *viewport)
+void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
+ Scene *scene,
+ int drawtype,
+ View3D *v3d,
+ ARegion *ar,
+ int winx,
+ int winy,
+ float viewmat[4][4],
+ float winmat[4][4],
+ bool do_sky,
+ bool UNUSED(is_persp),
+ const char *viewname,
+ GPUFXSettings *UNUSED(fx_settings),
+ const bool do_color_management,
+ GPUOffScreen *ofs,
+ GPUViewport *viewport)
{
- RegionView3D *rv3d = ar->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;
-
- ar->winx = winx;
- ar->winy = winy;
- ar->winrct.xmin = 0;
- ar->winrct.ymin = 0;
- ar->winrct.xmax = winx;
- ar->winrct.ymax = winy;
-
- struct bThemeState theme_state;
- UI_Theme_Store(&theme_state);
- UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
-
- /* set flags */
- G.f |= G_FLAG_RENDER_VIEWPORT;
-
- {
- /* free images which can have changed on frame-change
- * warning! can be slow so only free animated images - campbell */
- GPU_free_images_anim(G.main); /* XXX :((( */
- }
-
- GPU_matrix_push_projection();
- GPU_matrix_identity_set();
- GPU_matrix_push();
- GPU_matrix_identity_set();
-
- if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera) {
- view3d_stereo3d_setup_offscreen(depsgraph, scene, v3d, ar, winmat, viewname);
- }
- else {
- view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL);
- }
-
- /* main drawing call */
- DRW_draw_render_loop_offscreen(
- depsgraph, engine_type, ar, v3d,
- do_sky, do_color_management, ofs, viewport);
-
- /* restore size */
- ar->winx = bwinx;
- ar->winy = bwiny;
- ar->winrct = brect;
-
- GPU_matrix_pop_projection();
- GPU_matrix_pop();
-
- UI_Theme_Restore(&theme_state);
-
- G.f &= ~G_FLAG_RENDER_VIEWPORT;
+ RegionView3D *rv3d = ar->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;
+
+ ar->winx = winx;
+ ar->winy = winy;
+ ar->winrct.xmin = 0;
+ ar->winrct.ymin = 0;
+ ar->winrct.xmax = winx;
+ ar->winrct.ymax = winy;
+
+ struct bThemeState theme_state;
+ UI_Theme_Store(&theme_state);
+ UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
+
+ /* set flags */
+ G.f |= G_FLAG_RENDER_VIEWPORT;
+
+ {
+ /* free images which can have changed on frame-change
+ * warning! can be slow so only free animated images - campbell */
+ GPU_free_images_anim(G.main); /* XXX :((( */
+ }
+
+ GPU_matrix_push_projection();
+ GPU_matrix_identity_set();
+ GPU_matrix_push();
+ GPU_matrix_identity_set();
+
+ if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) &&
+ rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ view3d_stereo3d_setup_offscreen(depsgraph, scene, v3d, ar, winmat, viewname);
+ }
+ else {
+ view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL);
+ }
+
+ /* main drawing call */
+ DRW_draw_render_loop_offscreen(
+ depsgraph, engine_type, ar, v3d, do_sky, do_color_management, ofs, viewport);
+
+ /* restore size */
+ ar->winx = bwinx;
+ ar->winy = bwiny;
+ ar->winrct = brect;
+
+ GPU_matrix_pop_projection();
+ GPU_matrix_pop();
+
+ UI_Theme_Restore(&theme_state);
+
+ G.f &= ~G_FLAG_RENDER_VIEWPORT;
}
/**
@@ -1521,189 +1574,242 @@ void ED_view3d_draw_offscreen(
* \param ofs: Optional off-screen buffer, can be NULL.
* (avoids re-creating when doing multiple GL renders).
*/
-ImBuf *ED_view3d_draw_offscreen_imbuf(
- Depsgraph *depsgraph, Scene *scene,
- int drawtype,
- View3D *v3d, ARegion *ar, int sizex, int sizey,
- uint flag, uint draw_flags,
- int alpha_mode, int samples, const char *viewname,
- /* output vars */
- GPUOffScreen *ofs, char err_out[256])
+ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
+ Scene *scene,
+ int drawtype,
+ View3D *v3d,
+ ARegion *ar,
+ int sizex,
+ int sizey,
+ uint flag,
+ uint draw_flags,
+ int alpha_mode,
+ int samples,
+ const char *viewname,
+ /* output vars */
+ GPUOffScreen *ofs,
+ char err_out[256])
{
- RegionView3D *rv3d = ar->regiondata;
- const bool draw_sky = (alpha_mode == R_ADDSKY);
- const bool use_full_sample = (draw_flags & V3D_OFSDRAW_USE_FULL_SAMPLE);
-
- /* view state */
- GPUFXSettings fx_settings = v3d->fx_settings;
- bool is_ortho = false;
- float winmat[4][4];
-
- if (ofs && ((GPU_offscreen_width(ofs) != sizex) || (GPU_offscreen_height(ofs) != sizey))) {
- /* sizes differ, can't reuse */
- ofs = NULL;
- }
-
- GPUFrameBuffer *old_fb = GPU_framebuffer_active_get();
-
- if (old_fb) {
- GPU_framebuffer_restore();
- }
-
- const bool own_ofs = (ofs == NULL);
- DRW_opengl_context_enable();
-
- if (own_ofs) {
- /* bind */
- ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, true, false, err_out);
- if (ofs == NULL) {
- DRW_opengl_context_disable();
- return NULL;
- }
- }
-
- GPU_offscreen_bind(ofs, true);
-
- /* read in pixels & stamp */
- ImBuf *ibuf = IMB_allocImBuf(sizex, sizey, 32, flag);
-
- /* render 3d view */
- if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
- CameraParams params;
- Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
- const Object *camera_eval = DEG_get_evaluated_object(
- depsgraph,
- camera);
-
- BKE_camera_params_init(&params);
- /* fallback for non camera objects */
- params.clip_start = v3d->clip_start;
- params.clip_end = v3d->clip_end;
- BKE_camera_params_from_object(&params, camera_eval);
- BKE_camera_multiview_params(&scene->r, &params, camera_eval, viewname);
- BKE_camera_params_compute_viewplane(&params, sizex, sizey, scene->r.xasp, scene->r.yasp);
- BKE_camera_params_compute_matrix(&params);
-
- BKE_camera_to_gpu_dof(camera, &fx_settings);
-
- is_ortho = params.is_ortho;
- copy_m4_m4(winmat, params.winmat);
- }
- else {
- rctf viewplane;
- float clip_start, clipend;
-
- is_ortho = ED_view3d_viewplane_get(depsgraph, v3d, rv3d, sizex, sizey, &viewplane, &clip_start, &clipend, NULL);
- if (is_ortho) {
- orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend);
- }
- else {
- perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clip_start, clipend);
- }
- }
-
- if ((samples && use_full_sample) == 0) {
- const bool do_color_management = (ibuf->rect_float == NULL);
- /* Single-pass render, common case */
- ED_view3d_draw_offscreen(
- depsgraph, scene, drawtype,
- v3d, ar, sizex, sizey, NULL, winmat,
- draw_sky, !is_ortho, viewname,
- &fx_settings, do_color_management, ofs, NULL);
-
- if (ibuf->rect_float) {
- GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float);
- }
- else if (ibuf->rect) {
- GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect);
- }
- }
- else {
- /* Multi-pass render, use accumulation buffer & jitter for 'full' oversampling.
- * Use because OpenGL may use a lower quality MSAA, and only over-sample edges. */
- static float jit_ofs[32][2];
- float winmat_jitter[4][4];
- float *rect_temp = (ibuf->rect_float) ? ibuf->rect_float : MEM_mallocN(sizex * sizey * sizeof(float[4]), "rect_temp");
- float *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(float[4]), "accum_buffer");
- GPUViewport *viewport = GPU_viewport_create_from_offscreen(ofs);
-
- BLI_jitter_init(jit_ofs, samples);
-
- /* first sample buffer, also initializes 'rv3d->persmat' */
- ED_view3d_draw_offscreen(
- depsgraph, scene, drawtype,
- v3d, ar, sizex, sizey, NULL, winmat,
- draw_sky, !is_ortho, viewname,
- &fx_settings, false, ofs, viewport);
- GPU_offscreen_read_pixels(ofs, GL_FLOAT, accum_buffer);
-
- /* skip the first sample */
- for (int j = 1; j < samples; j++) {
- copy_m4_m4(winmat_jitter, winmat);
- window_translate_m4(
- winmat_jitter, rv3d->persmat,
- (jit_ofs[j][0] * 2.0f) / sizex,
- (jit_ofs[j][1] * 2.0f) / sizey);
-
- ED_view3d_draw_offscreen(
- depsgraph, scene, drawtype,
- v3d, ar, sizex, sizey, NULL, winmat_jitter,
- draw_sky, !is_ortho, viewname,
- &fx_settings, false, ofs, viewport);
- GPU_offscreen_read_pixels(ofs, GL_FLOAT, rect_temp);
-
- uint i = sizex * sizey * 4;
- while (i--) {
- accum_buffer[i] += rect_temp[i];
- }
- }
-
- {
- /* don't free data owned by 'ofs' */
- GPU_viewport_clear_from_offscreen(viewport);
- GPU_viewport_free(viewport);
- }
-
- if (ibuf->rect_float == NULL) {
- MEM_freeN(rect_temp);
- }
-
- if (ibuf->rect_float) {
- float *rect_float = ibuf->rect_float;
- uint i = sizex * sizey * 4;
- while (i--) {
- rect_float[i] = accum_buffer[i] / samples;
- }
- }
- else {
- uchar *rect_ub = (uchar *)ibuf->rect;
- uint i = sizex * sizey * 4;
- while (i--) {
- rect_ub[i] = (uchar)(255.0f * accum_buffer[i] / samples);
- }
- }
-
- MEM_freeN(accum_buffer);
- }
-
- /* unbind */
- GPU_offscreen_unbind(ofs, true);
-
- if (own_ofs) {
- GPU_offscreen_free(ofs);
- }
-
- DRW_opengl_context_disable();
-
- if (old_fb) {
- GPU_framebuffer_bind(old_fb);
- }
-
- if (ibuf->rect_float && ibuf->rect) {
- IMB_rect_from_float(ibuf);
- }
-
- return ibuf;
+ RegionView3D *rv3d = ar->regiondata;
+ const bool draw_sky = (alpha_mode == R_ADDSKY);
+ const bool use_full_sample = (draw_flags & V3D_OFSDRAW_USE_FULL_SAMPLE);
+
+ /* view state */
+ GPUFXSettings fx_settings = v3d->fx_settings;
+ bool is_ortho = false;
+ float winmat[4][4];
+
+ if (ofs && ((GPU_offscreen_width(ofs) != sizex) || (GPU_offscreen_height(ofs) != sizey))) {
+ /* sizes differ, can't reuse */
+ ofs = NULL;
+ }
+
+ GPUFrameBuffer *old_fb = GPU_framebuffer_active_get();
+
+ if (old_fb) {
+ GPU_framebuffer_restore();
+ }
+
+ const bool own_ofs = (ofs == NULL);
+ DRW_opengl_context_enable();
+
+ if (own_ofs) {
+ /* bind */
+ ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, true, false, err_out);
+ if (ofs == NULL) {
+ DRW_opengl_context_disable();
+ return NULL;
+ }
+ }
+
+ GPU_offscreen_bind(ofs, true);
+
+ /* read in pixels & stamp */
+ ImBuf *ibuf = IMB_allocImBuf(sizex, sizey, 32, flag);
+
+ /* render 3d view */
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ CameraParams params;
+ Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
+ const Object *camera_eval = DEG_get_evaluated_object(depsgraph, camera);
+
+ BKE_camera_params_init(&params);
+ /* fallback for non camera objects */
+ params.clip_start = v3d->clip_start;
+ params.clip_end = v3d->clip_end;
+ BKE_camera_params_from_object(&params, camera_eval);
+ BKE_camera_multiview_params(&scene->r, &params, camera_eval, viewname);
+ BKE_camera_params_compute_viewplane(&params, sizex, sizey, scene->r.xasp, scene->r.yasp);
+ BKE_camera_params_compute_matrix(&params);
+
+ BKE_camera_to_gpu_dof(camera, &fx_settings);
+
+ is_ortho = params.is_ortho;
+ copy_m4_m4(winmat, params.winmat);
+ }
+ else {
+ rctf viewplane;
+ float clip_start, clipend;
+
+ is_ortho = ED_view3d_viewplane_get(
+ depsgraph, v3d, rv3d, sizex, sizey, &viewplane, &clip_start, &clipend, NULL);
+ if (is_ortho) {
+ orthographic_m4(winmat,
+ viewplane.xmin,
+ viewplane.xmax,
+ viewplane.ymin,
+ viewplane.ymax,
+ -clipend,
+ clipend);
+ }
+ else {
+ perspective_m4(winmat,
+ viewplane.xmin,
+ viewplane.xmax,
+ viewplane.ymin,
+ viewplane.ymax,
+ clip_start,
+ clipend);
+ }
+ }
+
+ if ((samples && use_full_sample) == 0) {
+ const bool do_color_management = (ibuf->rect_float == NULL);
+ /* Single-pass render, common case */
+ ED_view3d_draw_offscreen(depsgraph,
+ scene,
+ drawtype,
+ v3d,
+ ar,
+ sizex,
+ sizey,
+ NULL,
+ winmat,
+ draw_sky,
+ !is_ortho,
+ viewname,
+ &fx_settings,
+ do_color_management,
+ ofs,
+ NULL);
+
+ if (ibuf->rect_float) {
+ GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float);
+ }
+ else if (ibuf->rect) {
+ GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect);
+ }
+ }
+ else {
+ /* Multi-pass render, use accumulation buffer & jitter for 'full' oversampling.
+ * Use because OpenGL may use a lower quality MSAA, and only over-sample edges. */
+ static float jit_ofs[32][2];
+ float winmat_jitter[4][4];
+ float *rect_temp = (ibuf->rect_float) ?
+ ibuf->rect_float :
+ MEM_mallocN(sizex * sizey * sizeof(float[4]), "rect_temp");
+ float *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(float[4]), "accum_buffer");
+ GPUViewport *viewport = GPU_viewport_create_from_offscreen(ofs);
+
+ BLI_jitter_init(jit_ofs, samples);
+
+ /* first sample buffer, also initializes 'rv3d->persmat' */
+ ED_view3d_draw_offscreen(depsgraph,
+ scene,
+ drawtype,
+ v3d,
+ ar,
+ sizex,
+ sizey,
+ NULL,
+ winmat,
+ draw_sky,
+ !is_ortho,
+ viewname,
+ &fx_settings,
+ false,
+ ofs,
+ viewport);
+ GPU_offscreen_read_pixels(ofs, GL_FLOAT, accum_buffer);
+
+ /* skip the first sample */
+ for (int j = 1; j < samples; j++) {
+ copy_m4_m4(winmat_jitter, winmat);
+ window_translate_m4(winmat_jitter,
+ rv3d->persmat,
+ (jit_ofs[j][0] * 2.0f) / sizex,
+ (jit_ofs[j][1] * 2.0f) / sizey);
+
+ ED_view3d_draw_offscreen(depsgraph,
+ scene,
+ drawtype,
+ v3d,
+ ar,
+ sizex,
+ sizey,
+ NULL,
+ winmat_jitter,
+ draw_sky,
+ !is_ortho,
+ viewname,
+ &fx_settings,
+ false,
+ ofs,
+ viewport);
+ GPU_offscreen_read_pixels(ofs, GL_FLOAT, rect_temp);
+
+ uint i = sizex * sizey * 4;
+ while (i--) {
+ accum_buffer[i] += rect_temp[i];
+ }
+ }
+
+ {
+ /* don't free data owned by 'ofs' */
+ GPU_viewport_clear_from_offscreen(viewport);
+ GPU_viewport_free(viewport);
+ }
+
+ if (ibuf->rect_float == NULL) {
+ MEM_freeN(rect_temp);
+ }
+
+ if (ibuf->rect_float) {
+ float *rect_float = ibuf->rect_float;
+ uint i = sizex * sizey * 4;
+ while (i--) {
+ rect_float[i] = accum_buffer[i] / samples;
+ }
+ }
+ else {
+ uchar *rect_ub = (uchar *)ibuf->rect;
+ uint i = sizex * sizey * 4;
+ while (i--) {
+ rect_ub[i] = (uchar)(255.0f * accum_buffer[i] / samples);
+ }
+ }
+
+ MEM_freeN(accum_buffer);
+ }
+
+ /* unbind */
+ GPU_offscreen_unbind(ofs, true);
+
+ if (own_ofs) {
+ GPU_offscreen_free(ofs);
+ }
+
+ DRW_opengl_context_disable();
+
+ if (old_fb) {
+ GPU_framebuffer_bind(old_fb);
+ }
+
+ if (ibuf->rect_float && ibuf->rect) {
+ IMB_rect_from_float(ibuf);
+ }
+
+ return ibuf;
}
/**
@@ -1714,71 +1820,86 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
*
* \note used by the sequencer
*/
-ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
- Depsgraph *depsgraph, Scene *scene,
- int drawtype,
- Object *camera, int width, int height,
- uint flag, uint draw_flags,
- int alpha_mode, int samples, const char *viewname,
- GPUOffScreen *ofs, char err_out[256])
+ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph,
+ Scene *scene,
+ int drawtype,
+ Object *camera,
+ int width,
+ int height,
+ uint flag,
+ uint draw_flags,
+ int alpha_mode,
+ int samples,
+ const char *viewname,
+ GPUOffScreen *ofs,
+ char err_out[256])
{
- View3D v3d = {NULL};
- ARegion ar = {NULL};
- RegionView3D rv3d = {{{0}}};
-
- /* connect data */
- v3d.regionbase.first = v3d.regionbase.last = &ar;
- ar.regiondata = &rv3d;
- ar.regiontype = RGN_TYPE_WINDOW;
-
- v3d.camera = camera;
- v3d.shading.type = drawtype;
- v3d.flag2 = V3D_HIDE_OVERLAYS;
-
- if (draw_flags & V3D_OFSDRAW_USE_GPENCIL) {
- v3d.flag2 |= V3D_SHOW_ANNOTATION;
- }
-
- v3d.shading.background_type = V3D_SHADING_BACKGROUND_WORLD;
-
- if (draw_flags & V3D_OFSDRAW_USE_CAMERA_DOF) {
- if (camera->type == OB_CAMERA) {
- v3d.fx_settings.dof = &((Camera *)camera->data)->gpu_dof;
- v3d.fx_settings.fx_flag |= GPU_FX_FLAG_DOF;
- }
- }
-
- rv3d.persp = RV3D_CAMOB;
-
- copy_m4_m4(rv3d.viewinv, v3d.camera->obmat);
- normalize_m4(rv3d.viewinv);
- invert_m4_m4(rv3d.viewmat, rv3d.viewinv);
-
- {
- CameraParams params;
- const Object *view_camera_eval = DEG_get_evaluated_object(
- depsgraph,
- BKE_camera_multiview_render(scene, v3d.camera, viewname));
-
- BKE_camera_params_init(&params);
- BKE_camera_params_from_object(&params, view_camera_eval);
- BKE_camera_multiview_params(&scene->r, &params, view_camera_eval, viewname);
- BKE_camera_params_compute_viewplane(&params, width, height, scene->r.xasp, scene->r.yasp);
- BKE_camera_params_compute_matrix(&params);
-
- copy_m4_m4(rv3d.winmat, params.winmat);
- v3d.clip_start = params.clip_start;
- v3d.clip_end = params.clip_end;
- v3d.lens = params.lens;
- }
-
- mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
- invert_m4_m4(rv3d.persinv, rv3d.viewinv);
-
- return ED_view3d_draw_offscreen_imbuf(
- depsgraph, scene, drawtype,
- &v3d, &ar, width, height, flag,
- draw_flags, alpha_mode, samples, viewname, ofs, err_out);
+ View3D v3d = {NULL};
+ ARegion ar = {NULL};
+ RegionView3D rv3d = {{{0}}};
+
+ /* connect data */
+ v3d.regionbase.first = v3d.regionbase.last = &ar;
+ ar.regiondata = &rv3d;
+ ar.regiontype = RGN_TYPE_WINDOW;
+
+ v3d.camera = camera;
+ v3d.shading.type = drawtype;
+ v3d.flag2 = V3D_HIDE_OVERLAYS;
+
+ if (draw_flags & V3D_OFSDRAW_USE_GPENCIL) {
+ v3d.flag2 |= V3D_SHOW_ANNOTATION;
+ }
+
+ v3d.shading.background_type = V3D_SHADING_BACKGROUND_WORLD;
+
+ if (draw_flags & V3D_OFSDRAW_USE_CAMERA_DOF) {
+ if (camera->type == OB_CAMERA) {
+ v3d.fx_settings.dof = &((Camera *)camera->data)->gpu_dof;
+ v3d.fx_settings.fx_flag |= GPU_FX_FLAG_DOF;
+ }
+ }
+
+ rv3d.persp = RV3D_CAMOB;
+
+ copy_m4_m4(rv3d.viewinv, v3d.camera->obmat);
+ normalize_m4(rv3d.viewinv);
+ invert_m4_m4(rv3d.viewmat, rv3d.viewinv);
+
+ {
+ CameraParams params;
+ const Object *view_camera_eval = DEG_get_evaluated_object(
+ depsgraph, BKE_camera_multiview_render(scene, v3d.camera, viewname));
+
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_object(&params, view_camera_eval);
+ BKE_camera_multiview_params(&scene->r, &params, view_camera_eval, viewname);
+ BKE_camera_params_compute_viewplane(&params, width, height, scene->r.xasp, scene->r.yasp);
+ BKE_camera_params_compute_matrix(&params);
+
+ copy_m4_m4(rv3d.winmat, params.winmat);
+ v3d.clip_start = params.clip_start;
+ v3d.clip_end = params.clip_end;
+ v3d.lens = params.lens;
+ }
+
+ mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
+ invert_m4_m4(rv3d.persinv, rv3d.viewinv);
+
+ return ED_view3d_draw_offscreen_imbuf(depsgraph,
+ scene,
+ drawtype,
+ &v3d,
+ &ar,
+ width,
+ height,
+ flag,
+ draw_flags,
+ alpha_mode,
+ samples,
+ viewname,
+ ofs,
+ err_out);
}
/** \} */
@@ -1789,24 +1910,24 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
static bool view3d_clipping_test(const float co[3], const float clip[6][4])
{
- if (plane_point_side_v3(clip[0], co) > 0.0f) {
- if (plane_point_side_v3(clip[1], co) > 0.0f) {
- if (plane_point_side_v3(clip[2], co) > 0.0f) {
- if (plane_point_side_v3(clip[3], co) > 0.0f) {
- return false;
- }
- }
- }
- }
-
- return true;
+ if (plane_point_side_v3(clip[0], co) > 0.0f) {
+ if (plane_point_side_v3(clip[1], co) > 0.0f) {
+ if (plane_point_side_v3(clip[2], co) > 0.0f) {
+ if (plane_point_side_v3(clip[3], co) > 0.0f) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
}
/* 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);
+ return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip);
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
index f7fcd5cb11f..85bc0fba36b 100644
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -102,7 +102,7 @@
#include "DRW_engine.h"
-#include "view3d_intern.h" /* own include */
+#include "view3d_intern.h" /* own include */
/* ********* custom clipping *********** */
@@ -113,206 +113,207 @@
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);
- }
+ 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);
- }
+ 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++) {
+ for (unsigned a = 0; a < 6; a++) {
#ifdef USE_CLIP_PLANES
- glDisable(GL_CLIP_PLANE0 + a);
+ glDisable(GL_CLIP_PLANE0 + a);
#endif
- glDisable(GL_CLIP_DISTANCE0 + a);
- }
+ glDisable(GL_CLIP_DISTANCE0 + a);
+ }
}
void ED_view3d_clipping_enable(void)
{
- for (unsigned a = 0; a < 6; a++) {
+ for (unsigned a = 0; a < 6; a++) {
#ifdef USE_CLIP_PLANES
- glEnable(GL_CLIP_PLANE0 + a);
+ glEnable(GL_CLIP_PLANE0 + a);
#endif
- glEnable(GL_CLIP_DISTANCE0 + a);
- }
+ glEnable(GL_CLIP_DISTANCE0 + a);
+ }
}
/* *********************** backdraw for selection *************** */
-static void validate_object_select_id(
- struct Depsgraph *depsgraph, Scene *scene,
- ARegion *ar, View3D *v3d,
- Object *obact, Object *obedit,
- short select_mode)
+static void validate_object_select_id(struct Depsgraph *depsgraph,
+ Scene *scene,
+ ARegion *ar,
+ View3D *v3d,
+ Object *obact,
+ Object *obedit,
+ short select_mode)
{
- RegionView3D *rv3d = ar->regiondata;
- Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id);
- Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact);
-
- BLI_assert(ar->regiontype == RGN_TYPE_WINDOW);
-
- 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 if ((obedit && (obedit->mode & OB_MODE_EDIT)) &&
- !XRAY_FLAG_ENABLED(v3d))
- {
- /* do nothing */
- }
- else {
- v3d->flag &= ~V3D_INVALID_BACKBUF;
- return;
- }
-
- if (!(v3d->flag & V3D_INVALID_BACKBUF)) {
- return;
- }
+ RegionView3D *rv3d = ar->regiondata;
+ Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id);
+ Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact);
+
+ BLI_assert(ar->regiontype == RGN_TYPE_WINDOW);
+
+ 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 if ((obedit && (obedit->mode & OB_MODE_EDIT)) && !XRAY_FLAG_ENABLED(v3d)) {
+ /* do nothing */
+ }
+ else {
+ v3d->flag &= ~V3D_INVALID_BACKBUF;
+ return;
+ }
+
+ if (!(v3d->flag & V3D_INVALID_BACKBUF)) {
+ return;
+ }
#if 0
- if (test) {
- if (qtest()) {
- addafterqueue(ar->win, BACKBUFDRAW, 1);
- return;
- }
- }
+ if (test) {
+ if (qtest()) {
+ addafterqueue(ar->win, BACKBUFDRAW, 1);
+ return;
+ }
+ }
#endif
#if 0 /* v3d->zbuf deprecated */
- if (v3d->shading.type > OB_WIRE) {
- v3d->zbuf = true;
- }
+ if (v3d->shading.type > OB_WIRE) {
+ v3d->zbuf = true;
+ }
#endif
- G.f |= G_FLAG_BACKBUFSEL;
+ G.f |= G_FLAG_BACKBUFSEL;
- if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) {
- DRW_framebuffer_select_id_setup(ar, true);
- draw_object_select_id(depsgraph, scene_eval, v3d, rv3d, obact_eval, select_mode);
- DRW_framebuffer_select_id_release(ar);
- }
+ if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) {
+ DRW_framebuffer_select_id_setup(ar, true);
+ draw_object_select_id(depsgraph, scene_eval, v3d, rv3d, obact_eval, select_mode);
+ DRW_framebuffer_select_id_release(ar);
+ }
- /* TODO: Create a flag in `DRW_manager` because the drawing is no longer
- * made on the backbuffer in this case. */
- v3d->flag &= ~V3D_INVALID_BACKBUF;
+ /* TODO: Create a flag in `DRW_manager` because the drawing is no longer
+ * made on the backbuffer in this case. */
+ v3d->flag &= ~V3D_INVALID_BACKBUF;
- G.f &= ~G_FLAG_BACKBUFSEL;
+ G.f &= ~G_FLAG_BACKBUFSEL;
}
-void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data)
+void view3d_opengl_read_pixels(
+ ARegion *ar, int x, int y, int w, int h, int format, int type, void *data)
{
- glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
+ glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
}
/* 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);
+ 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);
- glDisable(GL_SCISSOR_TEST);
+ GPUFrameBuffer *tmp_fb = GPU_framebuffer_create();
+ GPU_framebuffer_texture_attach(tmp_fb, dtxl->depth, 0, 0);
+ GPU_framebuffer_bind(tmp_fb);
+ glDisable(GL_SCISSOR_TEST);
- glReadPixels(rect->xmin, rect->ymin,
- BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
- GL_DEPTH_COMPONENT, GL_FLOAT, data);
+ glReadPixels(rect->xmin,
+ rect->ymin,
+ BLI_rcti_size_x(rect),
+ BLI_rcti_size_y(rect),
+ GL_DEPTH_COMPONENT,
+ GL_FLOAT,
+ data);
- glEnable(GL_SCISSOR_TEST);
- GPU_framebuffer_restore();
+ glEnable(GL_SCISSOR_TEST);
+ GPU_framebuffer_restore();
- GPU_framebuffer_free(tmp_fb);
+ GPU_framebuffer_free(tmp_fb);
}
void ED_view3d_select_id_validate_with_select_mode(ViewContext *vc, short select_mode)
{
- /* TODO: Create a flag in `DRW_manager` because the drawing is no longer
- * made on the backbuffer in this case. */
- if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
- validate_object_select_id(
- vc->depsgraph, vc->scene, vc->ar, vc->v3d,
- vc->obact, vc->obedit, select_mode);
- }
+ /* TODO: Create a flag in `DRW_manager` because the drawing is no longer
+ * made on the backbuffer in this case. */
+ if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
+ validate_object_select_id(
+ vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact, vc->obedit, select_mode);
+ }
}
void ED_view3d_select_id_validate(ViewContext *vc)
{
- ED_view3d_select_id_validate_with_select_mode(vc, -1);
+ ED_view3d_select_id_validate_with_select_mode(vc, -1);
}
void ED_view3d_backbuf_depth_validate(ViewContext *vc)
{
- if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
- ARegion *ar = vc->ar;
- RegionView3D *rv3d = ar->regiondata;
- Object *obact_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact);
+ if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
+ ARegion *ar = vc->ar;
+ RegionView3D *rv3d = ar->regiondata;
+ Object *obact_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact);
- if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) {
- GPU_scissor(ar->winrct.xmin, ar->winrct.ymin,
- BLI_rcti_size_x(&ar->winrct),
- BLI_rcti_size_y(&ar->winrct));
+ if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) {
+ GPU_scissor(ar->winrct.xmin,
+ ar->winrct.ymin,
+ BLI_rcti_size_x(&ar->winrct),
+ BLI_rcti_size_y(&ar->winrct));
- GPU_depth_test(true);
- GPU_clear(GPU_DEPTH_BIT);
+ GPU_depth_test(true);
+ GPU_clear(GPU_DEPTH_BIT);
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_set(rv3d);
- }
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ ED_view3d_clipping_set(rv3d);
+ }
- draw_object_depth(rv3d, obact_eval);
+ draw_object_depth(rv3d, obact_eval);
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_disable();
- }
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ ED_view3d_clipping_disable();
+ }
- GPU_depth_test(false);
- }
+ GPU_depth_test(false);
+ }
- vc->v3d->flag &= ~V3D_INVALID_BACKBUF;
- }
+ vc->v3d->flag &= ~V3D_INVALID_BACKBUF;
+ }
}
uint *ED_view3d_select_id_read_rect(ViewContext *vc, const rcti *clip, uint *r_buf_len)
{
- ED_view3d_select_id_validate(vc);
+ ED_view3d_select_id_validate(vc);
- uint width = BLI_rcti_size_x(clip);
- uint height = BLI_rcti_size_y(clip);
- uint buf_len = width * height;
- uint *buf = MEM_mallocN(buf_len * sizeof(*buf), __func__);
+ uint width = BLI_rcti_size_x(clip);
+ uint height = BLI_rcti_size_y(clip);
+ uint buf_len = width * height;
+ uint *buf = MEM_mallocN(buf_len * sizeof(*buf), __func__);
- DRW_framebuffer_select_id_read(clip, buf);
+ DRW_framebuffer_select_id_read(clip, buf);
- if (r_buf_len) {
- *r_buf_len = buf_len;
- }
+ if (r_buf_len) {
+ *r_buf_len = buf_len;
+ }
- return buf;
+ return buf;
}
/**
@@ -321,611 +322,623 @@ uint *ED_view3d_select_id_read_rect(ViewContext *vc, const rcti *clip, uint *r_b
*/
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));
+ return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx));
}
/* samples a single pixel (copied from vpaint) */
-uint ED_view3d_select_id_sample(
- ViewContext *vc, int x, int y)
+uint ED_view3d_select_id_sample(ViewContext *vc, int x, int y)
{
- if (x >= vc->ar->winx || y >= vc->ar->winy) {
- return 0;
- }
+ if (x >= vc->ar->winx || y >= vc->ar->winy) {
+ return 0;
+ }
- uint buf_len;
- uint *buf = ED_view3d_select_id_read(vc, x, y, x, y, &buf_len);
- BLI_assert(0 != buf_len);
- uint ret = buf[0];
- MEM_freeN(buf);
+ uint buf_len;
+ uint *buf = ED_view3d_select_id_read(vc, x, y, x, y, &buf_len);
+ BLI_assert(0 != buf_len);
+ uint ret = buf[0];
+ MEM_freeN(buf);
- return ret;
+ return ret;
}
/* reads full rect, converts indices */
uint *ED_view3d_select_id_read(
- ViewContext *vc, int xmin, int ymin, int xmax, int ymax, uint *r_buf_len)
+ ViewContext *vc, int xmin, int ymin, int xmax, int ymax, uint *r_buf_len)
{
- if (UNLIKELY((xmin > xmax) || (ymin > ymax))) {
- return NULL;
- }
+ if (UNLIKELY((xmin > xmax) || (ymin > ymax))) {
+ return NULL;
+ }
- const rcti rect = {
- .xmin = xmin, .xmax = xmax + 1,
- .ymin = ymin, .ymax = ymax + 1,
- };
+ const rcti rect = {
+ .xmin = xmin,
+ .xmax = xmax + 1,
+ .ymin = ymin,
+ .ymax = ymax + 1,
+ };
- uint buf_len;
- uint *buf = ED_view3d_select_id_read_rect(vc, &rect, &buf_len);
+ uint buf_len;
+ uint *buf = ED_view3d_select_id_read_rect(vc, &rect, &buf_len);
- if (r_buf_len) {
- *r_buf_len = buf_len;
- }
+ if (r_buf_len) {
+ *r_buf_len = buf_len;
+ }
- return buf;
+ return buf;
}
/* smart function to sample a rect spiralling outside, nice for backbuf selection */
-uint ED_view3d_select_id_read_nearest(
- struct ViewContext *UNUSED(vc), const int mval[2],
- const uint id_min, const uint id_max, uint *r_dist)
+uint ED_view3d_select_id_read_nearest(struct ViewContext *UNUSED(vc),
+ const int mval[2],
+ const uint id_min,
+ const uint id_max,
+ uint *r_dist)
{
- /* Create region around mouse cursor. This must be square and have an odd
- * width, the spiralling algorithm does not work with arbitrary rectangles. */
- rcti rect;
- BLI_rcti_init_pt_radius(&rect, mval, *r_dist);
- rect.xmax += 1;
- rect.ymax += 1;
-
- int width = BLI_rcti_size_x(&rect);
- int height = width;
- BLI_assert(width == height);
-
- /* Read from selection framebuffer. */
- uint *buf = MEM_mallocN(width * height * sizeof(*buf), __func__);
- DRW_framebuffer_select_id_read(&rect, buf);
-
- /* Spiral, starting from center of buffer. */
- int spiral_offset = height * (int)(width / 2) + (height / 2);
- int spiral_direction = 0;
-
- uint index = 0;
-
- for (int nr = 1; nr <= height; nr++) {
- for (int a = 0; a < 2; a++) {
- for (int b = 0; b < nr; b++) {
- /* Find hit within the specified range. */
- uint hit_id = buf[spiral_offset];
-
- if (hit_id && hit_id >= id_min && hit_id < id_max) {
- /* Get x/y from spiral offset. */
- int hit_x = spiral_offset % width;
- int hit_y = spiral_offset / width;
-
- int center_x = width / 2;
- int center_y = height / 2;
-
- /* Manhatten distance in keeping with other screen-based selection. */
- *r_dist = (uint)(abs(hit_x - center_x) + abs(hit_y - center_y));
-
- /* Indices start at 1 here. */
- index = (hit_id - id_min) + 1;
- goto exit;
- }
-
- /* Next spiral step. */
- if (spiral_direction == 0) {
- spiral_offset += 1; /* right */
- }
- else if (spiral_direction == 1) {
- spiral_offset -= width; /* down */
- }
- else if (spiral_direction == 2) {
- spiral_offset -= 1; /* left */
- }
- else {
- spiral_offset += width; /* up */
- }
-
- /* Stop if we are outside the buffer. */
- if (spiral_offset < 0 || spiral_offset >= width * height) {
- goto exit;
- }
- }
-
- spiral_direction = (spiral_direction + 1) % 4;
- }
- }
+ /* Create region around mouse cursor. This must be square and have an odd
+ * width, the spiralling algorithm does not work with arbitrary rectangles. */
+ rcti rect;
+ BLI_rcti_init_pt_radius(&rect, mval, *r_dist);
+ rect.xmax += 1;
+ rect.ymax += 1;
+
+ int width = BLI_rcti_size_x(&rect);
+ int height = width;
+ BLI_assert(width == height);
+
+ /* Read from selection framebuffer. */
+ uint *buf = MEM_mallocN(width * height * sizeof(*buf), __func__);
+ DRW_framebuffer_select_id_read(&rect, buf);
+
+ /* Spiral, starting from center of buffer. */
+ int spiral_offset = height * (int)(width / 2) + (height / 2);
+ int spiral_direction = 0;
+
+ uint index = 0;
+
+ for (int nr = 1; nr <= height; nr++) {
+ for (int a = 0; a < 2; a++) {
+ for (int b = 0; b < nr; b++) {
+ /* Find hit within the specified range. */
+ uint hit_id = buf[spiral_offset];
+
+ if (hit_id && hit_id >= id_min && hit_id < id_max) {
+ /* Get x/y from spiral offset. */
+ int hit_x = spiral_offset % width;
+ int hit_y = spiral_offset / width;
+
+ int center_x = width / 2;
+ int center_y = height / 2;
+
+ /* Manhatten distance in keeping with other screen-based selection. */
+ *r_dist = (uint)(abs(hit_x - center_x) + abs(hit_y - center_y));
+
+ /* Indices start at 1 here. */
+ index = (hit_id - id_min) + 1;
+ goto exit;
+ }
+
+ /* Next spiral step. */
+ if (spiral_direction == 0) {
+ spiral_offset += 1; /* right */
+ }
+ else if (spiral_direction == 1) {
+ spiral_offset -= width; /* down */
+ }
+ else if (spiral_direction == 2) {
+ spiral_offset -= 1; /* left */
+ }
+ else {
+ spiral_offset += width; /* up */
+ }
+
+ /* Stop if we are outside the buffer. */
+ if (spiral_offset < 0 || spiral_offset >= width * height) {
+ goto exit;
+ }
+ }
+
+ spiral_direction = (spiral_direction + 1) % 4;
+ }
+ }
exit:
- MEM_freeN(buf);
- return index;
+ MEM_freeN(buf);
+ return index;
}
-
/* ************************************************************* */
static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser)
{
- if (BKE_image_is_stereo(ima)) {
- iuser->flag |= IMA_SHOW_STEREO;
-
- if ((scene->r.scemode & R_MULTIVIEW) == 0) {
- iuser->multiview_eye = STEREO_LEFT_ID;
- }
- else if (v3d->stereo3d_camera != STEREO_3D_ID) {
- /* show only left or right camera */
- iuser->multiview_eye = v3d->stereo3d_camera;
- }
-
- BKE_image_multiview_index(ima, iuser);
- }
- else {
- iuser->flag &= ~IMA_SHOW_STEREO;
- }
+ if (BKE_image_is_stereo(ima)) {
+ iuser->flag |= IMA_SHOW_STEREO;
+
+ if ((scene->r.scemode & R_MULTIVIEW) == 0) {
+ iuser->multiview_eye = STEREO_LEFT_ID;
+ }
+ else if (v3d->stereo3d_camera != STEREO_3D_ID) {
+ /* show only left or right camera */
+ iuser->multiview_eye = v3d->stereo3d_camera;
+ }
+
+ BKE_image_multiview_index(ima, iuser);
+ }
+ else {
+ iuser->flag &= ~IMA_SHOW_STEREO;
+ }
}
-static void view3d_draw_bgpic(Scene *scene, Depsgraph *depsgraph,
- ARegion *ar, View3D *v3d,
- const bool do_foreground, const bool do_camera_frame)
+static void view3d_draw_bgpic(Scene *scene,
+ Depsgraph *depsgraph,
+ ARegion *ar,
+ View3D *v3d,
+ const bool do_foreground,
+ const bool do_camera_frame)
{
- RegionView3D *rv3d = ar->regiondata;
- int fg_flag = do_foreground ? CAM_BGIMG_FLAG_FOREGROUND : 0;
- if (v3d->camera == NULL || v3d->camera->type != OB_CAMERA) {
- return;
- }
- Camera *cam = v3d->camera->data;
-
- for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) {
- if ((bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) != fg_flag) {
- continue;
- }
-
- {
- float image_aspect[2];
- float x1, y1, x2, y2, centx, centy;
-
- void *lock;
-
- Image *ima = NULL;
-
- /* disable individual images */
- if ((bgpic->flag & CAM_BGIMG_FLAG_DISABLED)) {
- continue;
- }
-
- ImBuf *ibuf = NULL;
- ImBuf *freeibuf = NULL;
- ImBuf *releaseibuf = NULL;
- if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) {
- ima = bgpic->ima;
- if (ima == NULL) {
- continue;
- }
-
- ImageUser iuser = bgpic->iuser;
- iuser.scene = scene; /* Needed for render results. */
- BKE_image_user_frame_calc(&iuser, (int)DEG_get_ctime(depsgraph));
- if (ima->source == IMA_SRC_SEQUENCE && !(iuser.flag & IMA_USER_FRAME_IN_RANGE)) {
- ibuf = NULL; /* frame is out of range, dont show */
- }
- else {
- view3d_stereo_bgpic_setup(scene, v3d, ima, &iuser);
- ibuf = BKE_image_acquire_ibuf(ima, &iuser, &lock);
- releaseibuf = ibuf;
- }
-
- image_aspect[0] = ima->aspx;
- image_aspect[1] = ima->aspy;
- }
- else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) {
- /* TODO: skip drawing when out of frame range (as image sequences do above) */
- MovieClip *clip = NULL;
-
- if (bgpic->flag & CAM_BGIMG_FLAG_CAMERACLIP) {
- if (scene->camera) {
- clip = BKE_object_movieclip_get(scene, scene->camera, true);
- }
- }
- else {
- clip = bgpic->clip;
- }
-
- if (clip == NULL) {
- continue;
- }
-
- BKE_movieclip_user_set_frame(&bgpic->cuser, (int)DEG_get_ctime(depsgraph));
- ibuf = BKE_movieclip_get_ibuf(clip, &bgpic->cuser);
-
- image_aspect[0] = clip->aspx;
- image_aspect[1] = clip->aspy;
-
- /* working with ibuf from image and clip has got different workflow now.
- * ibuf acquired from clip is referenced by cache system and should
- * be dereferenced after usage. */
- freeibuf = ibuf;
- }
- else {
- /* perhaps when loading future files... */
- BLI_assert(0);
- copy_v2_fl(image_aspect, 1.0f);
- }
-
- if (ibuf == NULL) {
- continue;
- }
-
- if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) {
- /* invalid image format */
- if (freeibuf) {
- IMB_freeImBuf(freeibuf);
- }
- if (releaseibuf) {
- BKE_image_release_ibuf(ima, releaseibuf, lock);
- }
-
- continue;
- }
-
- if (ibuf->rect == NULL) {
- IMB_rect_from_float(ibuf);
- }
-
- BLI_assert(rv3d->persp == RV3D_CAMOB);
- {
- if (do_camera_frame) {
- rctf vb;
- ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &vb, false);
- x1 = vb.xmin;
- y1 = vb.ymin;
- x2 = vb.xmax;
- y2 = vb.ymax;
- }
- else {
- x1 = ar->winrct.xmin;
- y1 = ar->winrct.ymin;
- x2 = ar->winrct.xmax;
- y2 = ar->winrct.ymax;
- }
-
- /* apply offset last - camera offset is different to offset in blender units */
- /* so this has some sane way of working - this matches camera's shift _exactly_ */
- {
- const float max_dim = max_ff(x2 - x1, y2 - y1);
- const float xof_scale = bgpic->offset[0] * max_dim;
- const float yof_scale = bgpic->offset[1] * max_dim;
-
- x1 += xof_scale;
- y1 += yof_scale;
- x2 += xof_scale;
- y2 += yof_scale;
- }
-
- centx = (x1 + x2) * 0.5f;
- centy = (y1 + y2) * 0.5f;
-
- /* aspect correction */
- if (bgpic->flag & CAM_BGIMG_FLAG_CAMERA_ASPECT) {
- /* apply aspect from clip */
- const float w_src = ibuf->x * image_aspect[0];
- const float h_src = ibuf->y * image_aspect[1];
-
- /* destination aspect is already applied from the camera frame */
- const float w_dst = x1 - x2;
- const float h_dst = y1 - y2;
-
- const float asp_src = w_src / h_src;
- const float asp_dst = w_dst / h_dst;
-
- if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) {
- if ((asp_src > asp_dst) == ((bgpic->flag & CAM_BGIMG_FLAG_CAMERA_CROP) != 0)) {
- /* fit X */
- const float div = asp_src / asp_dst;
- x1 = ((x1 - centx) * div) + centx;
- x2 = ((x2 - centx) * div) + centx;
- }
- else {
- /* fit Y */
- const float div = asp_dst / asp_src;
- y1 = ((y1 - centy) * div) + centy;
- y2 = ((y2 - centy) * div) + centy;
- }
- }
- }
- }
-
- /* complete clip? */
- rctf clip_rect;
- BLI_rctf_init(&clip_rect, x1, x2, y1, y2);
- if (bgpic->rotation) {
- BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation);
- }
-
- if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx || clip_rect.ymin > ar->winy) {
- if (freeibuf) {
- IMB_freeImBuf(freeibuf);
- }
- if (releaseibuf) {
- BKE_image_release_ibuf(ima, releaseibuf, lock);
- }
-
- continue;
- }
-
- float zoomx = (x2 - x1) / ibuf->x;
- float zoomy = (y2 - y1) / ibuf->y;
-
- /* For some reason; zoom-levels down refuses to use GL_ALPHA_SCALE. */
- if (zoomx < 1.0f || zoomy < 1.0f) {
- float tzoom = min_ff(zoomx, zoomy);
- int mip = 0;
-
- if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) {
- IMB_remakemipmap(ibuf, 0);
- ibuf->userflags &= ~IB_MIPMAP_INVALID;
- }
- else if (ibuf->mipmap[0] == NULL) {
- IMB_makemipmap(ibuf, 0);
- }
-
- while (tzoom < 1.0f && mip < 8 && ibuf->mipmap[mip]) {
- tzoom *= 2.0f;
- zoomx *= 2.0f;
- zoomy *= 2.0f;
- mip++;
- }
- if (mip > 0) {
- ibuf = ibuf->mipmap[mip - 1];
- }
- }
-
- GPU_depth_test(!do_foreground);
- glDepthMask(GL_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_projection();
- GPU_matrix_push();
- ED_region_pixelspace(ar);
-
- GPU_matrix_translate_2f(centx, centy);
- GPU_matrix_scale_1f(bgpic->scale);
- GPU_matrix_rotate_2d(RAD2DEGF(-bgpic->rotation));
-
- if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_X) {
- zoomx *= -1.0f;
- x1 = x2;
- }
- if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_Y) {
- zoomy *= -1.0f;
- y1 = y2;
- }
-
- float col[4] = {1.0f, 1.0f, 1.0f, bgpic->alpha};
- IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
- immDrawPixelsTex(&state, x1 - centx, y1 - centy, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect,
- zoomx, zoomy, col);
-
- GPU_matrix_pop_projection();
- GPU_matrix_pop();
-
- GPU_blend(false);
-
- glDepthMask(GL_TRUE);
- GPU_depth_test(true);
-
- if (freeibuf) {
- IMB_freeImBuf(freeibuf);
- }
- if (releaseibuf) {
- BKE_image_release_ibuf(ima, releaseibuf, lock);
- }
- }
- }
+ RegionView3D *rv3d = ar->regiondata;
+ int fg_flag = do_foreground ? CAM_BGIMG_FLAG_FOREGROUND : 0;
+ if (v3d->camera == NULL || v3d->camera->type != OB_CAMERA) {
+ return;
+ }
+ Camera *cam = v3d->camera->data;
+
+ for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) {
+ if ((bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) != fg_flag) {
+ continue;
+ }
+
+ {
+ float image_aspect[2];
+ float x1, y1, x2, y2, centx, centy;
+
+ void *lock;
+
+ Image *ima = NULL;
+
+ /* disable individual images */
+ if ((bgpic->flag & CAM_BGIMG_FLAG_DISABLED)) {
+ continue;
+ }
+
+ ImBuf *ibuf = NULL;
+ ImBuf *freeibuf = NULL;
+ ImBuf *releaseibuf = NULL;
+ if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) {
+ ima = bgpic->ima;
+ if (ima == NULL) {
+ continue;
+ }
+
+ ImageUser iuser = bgpic->iuser;
+ iuser.scene = scene; /* Needed for render results. */
+ BKE_image_user_frame_calc(&iuser, (int)DEG_get_ctime(depsgraph));
+ if (ima->source == IMA_SRC_SEQUENCE && !(iuser.flag & IMA_USER_FRAME_IN_RANGE)) {
+ ibuf = NULL; /* frame is out of range, dont show */
+ }
+ else {
+ view3d_stereo_bgpic_setup(scene, v3d, ima, &iuser);
+ ibuf = BKE_image_acquire_ibuf(ima, &iuser, &lock);
+ releaseibuf = ibuf;
+ }
+
+ image_aspect[0] = ima->aspx;
+ image_aspect[1] = ima->aspy;
+ }
+ else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) {
+ /* TODO: skip drawing when out of frame range (as image sequences do above) */
+ MovieClip *clip = NULL;
+
+ if (bgpic->flag & CAM_BGIMG_FLAG_CAMERACLIP) {
+ if (scene->camera) {
+ clip = BKE_object_movieclip_get(scene, scene->camera, true);
+ }
+ }
+ else {
+ clip = bgpic->clip;
+ }
+
+ if (clip == NULL) {
+ continue;
+ }
+
+ BKE_movieclip_user_set_frame(&bgpic->cuser, (int)DEG_get_ctime(depsgraph));
+ ibuf = BKE_movieclip_get_ibuf(clip, &bgpic->cuser);
+
+ image_aspect[0] = clip->aspx;
+ image_aspect[1] = clip->aspy;
+
+ /* working with ibuf from image and clip has got different workflow now.
+ * ibuf acquired from clip is referenced by cache system and should
+ * be dereferenced after usage. */
+ freeibuf = ibuf;
+ }
+ else {
+ /* perhaps when loading future files... */
+ BLI_assert(0);
+ copy_v2_fl(image_aspect, 1.0f);
+ }
+
+ if (ibuf == NULL) {
+ continue;
+ }
+
+ if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) {
+ /* invalid image format */
+ if (freeibuf) {
+ IMB_freeImBuf(freeibuf);
+ }
+ if (releaseibuf) {
+ BKE_image_release_ibuf(ima, releaseibuf, lock);
+ }
+
+ continue;
+ }
+
+ if (ibuf->rect == NULL) {
+ IMB_rect_from_float(ibuf);
+ }
+
+ BLI_assert(rv3d->persp == RV3D_CAMOB);
+ {
+ if (do_camera_frame) {
+ rctf vb;
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &vb, false);
+ x1 = vb.xmin;
+ y1 = vb.ymin;
+ x2 = vb.xmax;
+ y2 = vb.ymax;
+ }
+ else {
+ x1 = ar->winrct.xmin;
+ y1 = ar->winrct.ymin;
+ x2 = ar->winrct.xmax;
+ y2 = ar->winrct.ymax;
+ }
+
+ /* apply offset last - camera offset is different to offset in blender units */
+ /* so this has some sane way of working - this matches camera's shift _exactly_ */
+ {
+ const float max_dim = max_ff(x2 - x1, y2 - y1);
+ const float xof_scale = bgpic->offset[0] * max_dim;
+ const float yof_scale = bgpic->offset[1] * max_dim;
+
+ x1 += xof_scale;
+ y1 += yof_scale;
+ x2 += xof_scale;
+ y2 += yof_scale;
+ }
+
+ centx = (x1 + x2) * 0.5f;
+ centy = (y1 + y2) * 0.5f;
+
+ /* aspect correction */
+ if (bgpic->flag & CAM_BGIMG_FLAG_CAMERA_ASPECT) {
+ /* apply aspect from clip */
+ const float w_src = ibuf->x * image_aspect[0];
+ const float h_src = ibuf->y * image_aspect[1];
+
+ /* destination aspect is already applied from the camera frame */
+ const float w_dst = x1 - x2;
+ const float h_dst = y1 - y2;
+
+ const float asp_src = w_src / h_src;
+ const float asp_dst = w_dst / h_dst;
+
+ if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) {
+ if ((asp_src > asp_dst) == ((bgpic->flag & CAM_BGIMG_FLAG_CAMERA_CROP) != 0)) {
+ /* fit X */
+ const float div = asp_src / asp_dst;
+ x1 = ((x1 - centx) * div) + centx;
+ x2 = ((x2 - centx) * div) + centx;
+ }
+ else {
+ /* fit Y */
+ const float div = asp_dst / asp_src;
+ y1 = ((y1 - centy) * div) + centy;
+ y2 = ((y2 - centy) * div) + centy;
+ }
+ }
+ }
+ }
+
+ /* complete clip? */
+ rctf clip_rect;
+ BLI_rctf_init(&clip_rect, x1, x2, y1, y2);
+ if (bgpic->rotation) {
+ BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation);
+ }
+
+ if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx ||
+ clip_rect.ymin > ar->winy) {
+ if (freeibuf) {
+ IMB_freeImBuf(freeibuf);
+ }
+ if (releaseibuf) {
+ BKE_image_release_ibuf(ima, releaseibuf, lock);
+ }
+
+ continue;
+ }
+
+ float zoomx = (x2 - x1) / ibuf->x;
+ float zoomy = (y2 - y1) / ibuf->y;
+
+ /* For some reason; zoom-levels down refuses to use GL_ALPHA_SCALE. */
+ if (zoomx < 1.0f || zoomy < 1.0f) {
+ float tzoom = min_ff(zoomx, zoomy);
+ int mip = 0;
+
+ if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) {
+ IMB_remakemipmap(ibuf, 0);
+ ibuf->userflags &= ~IB_MIPMAP_INVALID;
+ }
+ else if (ibuf->mipmap[0] == NULL) {
+ IMB_makemipmap(ibuf, 0);
+ }
+
+ while (tzoom < 1.0f && mip < 8 && ibuf->mipmap[mip]) {
+ tzoom *= 2.0f;
+ zoomx *= 2.0f;
+ zoomy *= 2.0f;
+ mip++;
+ }
+ if (mip > 0) {
+ ibuf = ibuf->mipmap[mip - 1];
+ }
+ }
+
+ GPU_depth_test(!do_foreground);
+ glDepthMask(GL_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_projection();
+ GPU_matrix_push();
+ ED_region_pixelspace(ar);
+
+ GPU_matrix_translate_2f(centx, centy);
+ GPU_matrix_scale_1f(bgpic->scale);
+ GPU_matrix_rotate_2d(RAD2DEGF(-bgpic->rotation));
+
+ if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_X) {
+ zoomx *= -1.0f;
+ x1 = x2;
+ }
+ if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_Y) {
+ zoomy *= -1.0f;
+ y1 = y2;
+ }
+
+ float col[4] = {1.0f, 1.0f, 1.0f, bgpic->alpha};
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(&state,
+ x1 - centx,
+ y1 - centy,
+ ibuf->x,
+ ibuf->y,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ GL_LINEAR,
+ ibuf->rect,
+ zoomx,
+ zoomy,
+ col);
+
+ GPU_matrix_pop_projection();
+ GPU_matrix_pop();
+
+ GPU_blend(false);
+
+ glDepthMask(GL_TRUE);
+ GPU_depth_test(true);
+
+ if (freeibuf) {
+ IMB_freeImBuf(freeibuf);
+ }
+ if (releaseibuf) {
+ BKE_image_release_ibuf(ima, releaseibuf, lock);
+ }
+ }
+ }
}
-void ED_view3d_draw_bgpic_test(
- Scene *scene, Depsgraph *depsgraph,
- ARegion *ar, View3D *v3d,
- const bool do_foreground, const bool do_camera_frame)
+void ED_view3d_draw_bgpic_test(Scene *scene,
+ Depsgraph *depsgraph,
+ ARegion *ar,
+ View3D *v3d,
+ const bool do_foreground,
+ const bool do_camera_frame)
{
- RegionView3D *rv3d = ar->regiondata;
-
- if ((rv3d->persp == RV3D_CAMOB) && v3d->camera && (v3d->camera->type == OB_CAMERA)) {
- Camera *cam = v3d->camera->data;
- if ((cam->flag & CAM_SHOW_BG_IMAGE) == 0) {
- return;
- }
- }
- else {
- return;
- }
-
- /* disabled - mango request, since footage /w only render is quite useful
- * and this option is easy to disable all background images at once */
+ RegionView3D *rv3d = ar->regiondata;
+
+ if ((rv3d->persp == RV3D_CAMOB) && v3d->camera && (v3d->camera->type == OB_CAMERA)) {
+ Camera *cam = v3d->camera->data;
+ if ((cam->flag & CAM_SHOW_BG_IMAGE) == 0) {
+ return;
+ }
+ }
+ else {
+ return;
+ }
+
+ /* disabled - mango request, since footage /w only render is quite useful
+ * and this option is easy to disable all background images at once */
#if 0
- if (v3d->flag2 & V3D_HIDE_OVERLAYS) {
- return;
- }
+ if (v3d->flag2 & V3D_HIDE_OVERLAYS) {
+ return;
+ }
#endif
- if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) {
- if (rv3d->persp == RV3D_CAMOB) {
- view3d_draw_bgpic(scene, depsgraph, ar, v3d, do_foreground, do_camera_frame);
- }
- }
- else {
- view3d_draw_bgpic(scene, depsgraph, ar, v3d, do_foreground, do_camera_frame);
- }
+ if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) {
+ if (rv3d->persp == RV3D_CAMOB) {
+ view3d_draw_bgpic(scene, depsgraph, ar, v3d, do_foreground, do_camera_frame);
+ }
+ }
+ else {
+ view3d_draw_bgpic(scene, depsgraph, ar, v3d, do_foreground, do_camera_frame);
+ }
}
/* *********************** */
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;
- }
+ /* 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) {
- view3d_opengl_read_pixels(ar, 0, 0, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
- glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
-
- d->damaged = false;
- }
- }
+ 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) {
+ view3d_opengl_read_pixels(ar, 0, 0, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, 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;
+ /* 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)
+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);
+ /* Setup view matrix. */
+ ED_view3d_draw_setup_view(NULL, depsgraph, scene, ar, v3d, NULL, NULL, NULL);
- GPU_clear(GPU_DEPTH_BIT);
+ GPU_clear(GPU_DEPTH_BIT);
- GPU_depth_test(true);
+ GPU_depth_test(true);
- GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
- DRW_draw_depth_loop_gpencil(depsgraph, ar, v3d, viewport);
+ GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
+ DRW_draw_depth_loop_gpencil(depsgraph, ar, v3d, viewport);
- GPU_depth_test(false);
+ GPU_depth_test(false);
}
/* *********************** customdata **************** */
-void ED_view3d_datamask(
- const bContext *C, const Scene *UNUSED(scene), const View3D *v3d, CustomData_MeshMasks *r_cddata_masks)
+void ED_view3d_datamask(const bContext *C,
+ const Scene *UNUSED(scene),
+ const View3D *v3d,
+ CustomData_MeshMasks *r_cddata_masks)
{
- const int drawtype = view3d_effective_drawtype(v3d);
+ const int drawtype = view3d_effective_drawtype(v3d);
- if (ELEM(drawtype, OB_TEXTURE, OB_MATERIAL)) {
- r_cddata_masks->lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL;
+ if (ELEM(drawtype, OB_TEXTURE, OB_MATERIAL)) {
+ r_cddata_masks->lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL;
- if (drawtype == OB_MATERIAL) {
- r_cddata_masks->vmask |= CD_MASK_ORCO;
- }
- }
+ if (drawtype == OB_MATERIAL) {
+ r_cddata_masks->vmask |= CD_MASK_ORCO;
+ }
+ }
- 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;
- }
+ 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)
+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);
- }
- }
+ 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);
+ }
+ }
}
/**
@@ -935,38 +948,38 @@ void ED_view3d_screen_datamask(
* 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;
+ 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;
+ 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;
+ 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;
}
/**
@@ -975,115 +988,117 @@ void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixSto
*/
void ED_scene_draw_fps(Scene *scene, int xoffset, int *yoffset)
{
- ScreenFrameRateInfo *fpsi = scene->fps_info;
- char printable[16];
+ ScreenFrameRateInfo *fpsi = scene->fps_info;
+ char printable[16];
- if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime) {
- return;
- }
+ if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime) {
+ return;
+ }
- printable[0] = '\0';
+ printable[0] = '\0';
#if 0
- /* this is too simple, better do an average */
- fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime))
+ /* 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;
- }
+ 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();
+ 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));
- }
+ /* 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);
+ 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;
+ *yoffset -= U.widget_unit;
#ifdef WITH_INTERNATIONAL
- BLF_draw_default(xoffset, *yoffset, 0.0f, printable, sizeof(printable));
+ BLF_draw_default(xoffset, *yoffset, 0.0f, printable, sizeof(printable));
#else
- BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, printable, sizeof(printable));
+ BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, printable, sizeof(printable));
#endif
- BLF_disable(font_id, BLF_SHADOW);
+ 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);
+ 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)
+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;
+ 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 e74703baf2d..1d2d361d868 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -78,12 +78,11 @@
#include "PIL_time.h"
-#include "view3d_intern.h" /* own include */
-
+#include "view3d_intern.h" /* own include */
enum {
- HAS_TRANSLATE = (1 << 0),
- HAS_ROTATE = (1 << 0),
+ HAS_TRANSLATE = (1 << 0),
+ HAS_ROTATE = (1 << 0),
};
/* -------------------------------------------------------------------- */
@@ -91,35 +90,37 @@ enum {
* \{ */
enum eV3D_OpPropFlag {
- V3D_OP_PROP_MOUSE_CO = (1 << 0),
- V3D_OP_PROP_DELTA = (1 << 1),
- V3D_OP_PROP_USE_ALL_REGIONS = (1 << 2),
- V3D_OP_PROP_USE_MOUSE_INIT = (1 << 3),
+ V3D_OP_PROP_MOUSE_CO = (1 << 0),
+ V3D_OP_PROP_DELTA = (1 << 1),
+ V3D_OP_PROP_USE_ALL_REGIONS = (1 << 2),
+ V3D_OP_PROP_USE_MOUSE_INIT = (1 << 3),
};
static void view3d_operator_properties_common(wmOperatorType *ot, const enum eV3D_OpPropFlag flag)
{
- if (flag & V3D_OP_PROP_MOUSE_CO) {
- PropertyRNA *prop;
- prop = RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Region Position X", "", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
- prop = RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Region Position Y", "", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
- }
- if (flag & V3D_OP_PROP_DELTA) {
- RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
- }
- if (flag & V3D_OP_PROP_USE_ALL_REGIONS) {
- PropertyRNA *prop;
- prop = RNA_def_boolean(ot->srna, "use_all_regions", 0, "All Regions", "View selected for all regions");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- }
- if (flag & V3D_OP_PROP_USE_MOUSE_INIT) {
- /* Disable when view operators are initialized from buttons. */
- PropertyRNA *prop;
- prop = RNA_def_boolean(ot->srna, "use_mouse_init", true, "Mouse Init", "Use initial mouse position");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
- }
+ if (flag & V3D_OP_PROP_MOUSE_CO) {
+ PropertyRNA *prop;
+ prop = RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Region Position X", "", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Region Position Y", "", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ }
+ if (flag & V3D_OP_PROP_DELTA) {
+ RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
+ }
+ if (flag & V3D_OP_PROP_USE_ALL_REGIONS) {
+ PropertyRNA *prop;
+ prop = RNA_def_boolean(
+ ot->srna, "use_all_regions", 0, "All Regions", "View selected for all regions");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ }
+ if (flag & V3D_OP_PROP_USE_MOUSE_INIT) {
+ /* Disable when view operators are initialized from buttons. */
+ PropertyRNA *prop;
+ prop = RNA_def_boolean(
+ ot->srna, "use_mouse_init", true, "Mouse Init", "Use initial mouse position");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ }
}
/** \} */
@@ -129,87 +130,87 @@ static void view3d_operator_properties_common(wmOperatorType *ot, const enum eV3
* \{ */
typedef struct ViewOpsData {
- /** Context pointers (assigned by #viewops_data_alloc). */
- Main *bmain;
- Scene *scene;
- ScrArea *sa;
- ARegion *ar;
- View3D *v3d;
- RegionView3D *rv3d;
- Depsgraph *depsgraph;
-
- /** Needed for continuous zoom. */
- wmTimer *timer;
-
- /** Viewport state on initialization, don't change afterwards. */
- struct {
- float dist;
- float camzoom;
- float quat[4];
- /** #wmEvent.x, y. */
- int event_xy[2];
- /** Offset to use when #VIEWOPS_FLAG_USE_MOUSE_INIT is not set.
- * so we can simulate pressing in the middle of the screen. */
- int event_xy_offset[2];
- /** #wmEvent.type that triggered the operator. */
- int event_type;
- float ofs[3];
- /** Initial distance to 'ofs'. */
- float zfac;
-
- /** Trackball rotation only. */
- float trackvec[3];
- /** Dolly only. */
- float mousevec[3];
- } init;
-
- /** Previous state (previous modal event handled). */
- struct {
- int event_xy[2];
- /** For operators that use time-steps (continuous zoom). */
- double time;
- } prev;
-
- /** Current state. */
- struct {
- /** Working copy of #RegionView3D.viewquat, needed for rotation calculation
- * so we can apply snap to the view-port while keeping the unsnapped rotation
- * here to use when snap is disabled and for continued calculation. */
- float viewquat[4];
- } curr;
-
- float reverse;
- bool axis_snap; /* view rotate only */
-
- /** Use for orbit selection and auto-dist. */
- float dyn_ofs[3];
- bool use_dyn_ofs;
+ /** Context pointers (assigned by #viewops_data_alloc). */
+ Main *bmain;
+ Scene *scene;
+ ScrArea *sa;
+ ARegion *ar;
+ View3D *v3d;
+ RegionView3D *rv3d;
+ Depsgraph *depsgraph;
+
+ /** Needed for continuous zoom. */
+ wmTimer *timer;
+
+ /** Viewport state on initialization, don't change afterwards. */
+ struct {
+ float dist;
+ float camzoom;
+ float quat[4];
+ /** #wmEvent.x, y. */
+ int event_xy[2];
+ /** Offset to use when #VIEWOPS_FLAG_USE_MOUSE_INIT is not set.
+ * so we can simulate pressing in the middle of the screen. */
+ int event_xy_offset[2];
+ /** #wmEvent.type that triggered the operator. */
+ int event_type;
+ float ofs[3];
+ /** Initial distance to 'ofs'. */
+ float zfac;
+
+ /** Trackball rotation only. */
+ float trackvec[3];
+ /** Dolly only. */
+ float mousevec[3];
+ } init;
+
+ /** Previous state (previous modal event handled). */
+ struct {
+ int event_xy[2];
+ /** For operators that use time-steps (continuous zoom). */
+ double time;
+ } prev;
+
+ /** Current state. */
+ struct {
+ /** Working copy of #RegionView3D.viewquat, needed for rotation calculation
+ * so we can apply snap to the view-port while keeping the unsnapped rotation
+ * here to use when snap is disabled and for continued calculation. */
+ float viewquat[4];
+ } curr;
+
+ float reverse;
+ bool axis_snap; /* view rotate only */
+
+ /** Use for orbit selection and auto-dist. */
+ float dyn_ofs[3];
+ bool use_dyn_ofs;
} ViewOpsData;
-#define TRACKBALLSIZE (1.1f)
+#define TRACKBALLSIZE (1.1f)
static void calctrackballvec(const rcti *rect, const int event_xy[2], float vec[3])
{
- const float radius = TRACKBALLSIZE;
- const float t = radius / (float)M_SQRT2;
- float x, y, z, d;
+ const float radius = TRACKBALLSIZE;
+ const float t = radius / (float)M_SQRT2;
+ float x, y, z, d;
- /* normalize x and y */
- x = BLI_rcti_cent_x(rect) - event_xy[0];
- x /= (float)(BLI_rcti_size_x(rect) / 4);
- y = BLI_rcti_cent_y(rect) - event_xy[1];
- y /= (float)(BLI_rcti_size_y(rect) / 2);
- d = sqrtf(x * x + y * y);
- if (d < t) { /* Inside sphere */
- z = sqrtf(radius * radius - d * d);
- }
- else { /* On hyperbola */
- z = t * t / d;
- }
+ /* normalize x and y */
+ x = BLI_rcti_cent_x(rect) - event_xy[0];
+ x /= (float)(BLI_rcti_size_x(rect) / 4);
+ y = BLI_rcti_cent_y(rect) - event_xy[1];
+ y /= (float)(BLI_rcti_size_y(rect) / 2);
+ d = sqrtf(x * x + y * y);
+ if (d < t) { /* Inside sphere */
+ z = sqrtf(radius * radius - d * d);
+ }
+ else { /* On hyperbola */
+ z = t * t / d;
+ }
- vec[0] = x;
- vec[1] = y;
- vec[2] = -z; /* yah yah! */
+ vec[0] = x;
+ vec[1] = y;
+ vec[2] = -z; /* yah yah! */
}
/**
@@ -217,331 +218,330 @@ static void calctrackballvec(const rcti *rect, const int event_xy[2], float vec[
*/
static void viewops_data_alloc(bContext *C, wmOperator *op)
{
- ViewOpsData *vod = MEM_callocN(sizeof(ViewOpsData), "viewops data");
+ ViewOpsData *vod = MEM_callocN(sizeof(ViewOpsData), "viewops data");
- /* store data */
- op->customdata = vod;
- vod->bmain = CTX_data_main(C);
- vod->depsgraph = CTX_data_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;
+ /* store data */
+ op->customdata = vod;
+ vod->bmain = CTX_data_main(C);
+ vod->depsgraph = CTX_data_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;
}
-void view3d_orbit_apply_dyn_ofs(
- float r_ofs[3], const float ofs_init[3], const float viewquat_old[4],
- const float viewquat_new[4], const float dyn_ofs[3])
+void view3d_orbit_apply_dyn_ofs(float r_ofs[3],
+ const float ofs_init[3],
+ const float viewquat_old[4],
+ const float viewquat_new[4],
+ const float dyn_ofs[3])
{
- float q[4];
- invert_qt_qt_normalized(q, viewquat_old);
- mul_qt_qtqt(q, q, viewquat_new);
+ float q[4];
+ invert_qt_qt_normalized(q, viewquat_old);
+ mul_qt_qtqt(q, q, viewquat_new);
- invert_qt_normalized(q);
+ invert_qt_normalized(q);
- sub_v3_v3v3(r_ofs, ofs_init, dyn_ofs);
- mul_qt_v3(q, r_ofs);
- add_v3_v3(r_ofs, dyn_ofs);
+ sub_v3_v3v3(r_ofs, ofs_init, dyn_ofs);
+ mul_qt_v3(q, r_ofs);
+ add_v3_v3(r_ofs, dyn_ofs);
}
static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
{
- static float lastofs[3] = {0, 0, 0};
- bool is_set = false;
-
- const Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
- View3D *v3d = CTX_wm_view3d(C);
- Object *ob_act_eval = OBACT(view_layer_eval);
- Object *ob_act = DEG_get_original_object(ob_act_eval);
-
- if (ob_act && (ob_act->mode & OB_MODE_ALL_PAINT) &&
- /* with weight-paint + pose-mode, fall through to using calculateTransformCenter */
- ((ob_act->mode & OB_MODE_WEIGHT_PAINT) && BKE_object_pose_armature_get(ob_act)) == 0)
- {
- /* in case of sculpting use last average stroke position as a rotation
- * center, in other cases it's not clear what rotation center shall be
- * so just rotate around object origin
- */
- if (ob_act->mode & (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
- float stroke[3];
- BKE_paint_stroke_get_average(scene, ob_act_eval, stroke);
- copy_v3_v3(lastofs, stroke);
- }
- else {
- copy_v3_v3(lastofs, ob_act_eval->obmat[3]);
- }
- is_set = true;
- }
- else if (ob_act && (ob_act->mode & OB_MODE_EDIT) && (ob_act->type == OB_FONT)) {
- Curve *cu = ob_act_eval->data;
- EditFont *ef = cu->editfont;
- int i;
-
- zero_v3(lastofs);
- for (i = 0; i < 4; i++) {
- add_v2_v2(lastofs, ef->textcurs[i]);
- }
- mul_v2_fl(lastofs, 1.0f / 4.0f);
-
- mul_m4_v3(ob_act_eval->obmat, lastofs);
-
- is_set = true;
- }
- else if (ob_act == NULL || ob_act->mode == OB_MODE_OBJECT) {
- /* object mode use boundbox centers */
- Base *base_eval;
- uint tot = 0;
- float select_center[3];
-
- zero_v3(select_center);
- for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) {
- if (BASE_SELECTED(v3d, base_eval)) {
- /* use the boundbox if we can */
- Object *ob_eval = base_eval->object;
-
- if (ob_eval->runtime.bb && !(ob_eval->runtime.bb->flag & BOUNDBOX_DIRTY)) {
- float cent[3];
-
- BKE_boundbox_calc_center_aabb(ob_eval->runtime.bb, cent);
-
- mul_m4_v3(ob_eval->obmat, cent);
- add_v3_v3(select_center, cent);
- }
- else {
- add_v3_v3(select_center, ob_eval->obmat[3]);
- }
- tot++;
- }
- }
- if (tot) {
- mul_v3_fl(select_center, 1.0f / (float)tot);
- copy_v3_v3(lastofs, select_center);
- is_set = true;
- }
- }
- else {
- /* If there's no selection, lastofs is unmodified and last value since static */
- is_set = calculateTransformCenter(C, V3D_AROUND_CENTER_MEDIAN, lastofs, NULL);
- }
-
- copy_v3_v3(r_dyn_ofs, lastofs);
-
- return is_set;
+ static float lastofs[3] = {0, 0, 0};
+ bool is_set = false;
+
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
+ View3D *v3d = CTX_wm_view3d(C);
+ Object *ob_act_eval = OBACT(view_layer_eval);
+ Object *ob_act = DEG_get_original_object(ob_act_eval);
+
+ if (ob_act && (ob_act->mode & OB_MODE_ALL_PAINT) &&
+ /* with weight-paint + pose-mode, fall through to using calculateTransformCenter */
+ ((ob_act->mode & OB_MODE_WEIGHT_PAINT) && BKE_object_pose_armature_get(ob_act)) == 0) {
+ /* in case of sculpting use last average stroke position as a rotation
+ * center, in other cases it's not clear what rotation center shall be
+ * so just rotate around object origin
+ */
+ if (ob_act->mode &
+ (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
+ float stroke[3];
+ BKE_paint_stroke_get_average(scene, ob_act_eval, stroke);
+ copy_v3_v3(lastofs, stroke);
+ }
+ else {
+ copy_v3_v3(lastofs, ob_act_eval->obmat[3]);
+ }
+ is_set = true;
+ }
+ else if (ob_act && (ob_act->mode & OB_MODE_EDIT) && (ob_act->type == OB_FONT)) {
+ Curve *cu = ob_act_eval->data;
+ EditFont *ef = cu->editfont;
+ int i;
+
+ zero_v3(lastofs);
+ for (i = 0; i < 4; i++) {
+ add_v2_v2(lastofs, ef->textcurs[i]);
+ }
+ mul_v2_fl(lastofs, 1.0f / 4.0f);
+
+ mul_m4_v3(ob_act_eval->obmat, lastofs);
+
+ is_set = true;
+ }
+ else if (ob_act == NULL || ob_act->mode == OB_MODE_OBJECT) {
+ /* object mode use boundbox centers */
+ Base *base_eval;
+ uint tot = 0;
+ float select_center[3];
+
+ zero_v3(select_center);
+ for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) {
+ if (BASE_SELECTED(v3d, base_eval)) {
+ /* use the boundbox if we can */
+ Object *ob_eval = base_eval->object;
+
+ if (ob_eval->runtime.bb && !(ob_eval->runtime.bb->flag & BOUNDBOX_DIRTY)) {
+ float cent[3];
+
+ BKE_boundbox_calc_center_aabb(ob_eval->runtime.bb, cent);
+
+ mul_m4_v3(ob_eval->obmat, cent);
+ add_v3_v3(select_center, cent);
+ }
+ else {
+ add_v3_v3(select_center, ob_eval->obmat[3]);
+ }
+ tot++;
+ }
+ }
+ if (tot) {
+ mul_v3_fl(select_center, 1.0f / (float)tot);
+ copy_v3_v3(lastofs, select_center);
+ is_set = true;
+ }
+ }
+ else {
+ /* If there's no selection, lastofs is unmodified and last value since static */
+ is_set = calculateTransformCenter(C, V3D_AROUND_CENTER_MEDIAN, lastofs, NULL);
+ }
+
+ copy_v3_v3(r_dyn_ofs, lastofs);
+
+ return is_set;
}
enum eViewOpsFlag {
- /** When enabled, rotate around the selection. */
- VIEWOPS_FLAG_ORBIT_SELECT = (1 << 0),
- /** When enabled, use the depth under the cursor for navigation. */
- VIEWOPS_FLAG_DEPTH_NAVIGATE = (1 << 1),
- /**
- * When enabled run #ED_view3d_persp_ensure this may switch out of
- * camera view when orbiting or switch from ortho to perspective when auto-persp is enabled.
- * Some operations don't require this (view zoom/pan or ndof where subtle rotation is common
- * so we don't want it to trigger auto-perspective). */
- VIEWOPS_FLAG_PERSP_ENSURE = (1 << 2),
- /** When set, ignore any options that depend on initial cursor location. */
- VIEWOPS_FLAG_USE_MOUSE_INIT = (1 << 3),
+ /** When enabled, rotate around the selection. */
+ VIEWOPS_FLAG_ORBIT_SELECT = (1 << 0),
+ /** When enabled, use the depth under the cursor for navigation. */
+ VIEWOPS_FLAG_DEPTH_NAVIGATE = (1 << 1),
+ /**
+ * When enabled run #ED_view3d_persp_ensure this may switch out of
+ * camera view when orbiting or switch from ortho to perspective when auto-persp is enabled.
+ * Some operations don't require this (view zoom/pan or ndof where subtle rotation is common
+ * so we don't want it to trigger auto-perspective). */
+ VIEWOPS_FLAG_PERSP_ENSURE = (1 << 2),
+ /** When set, ignore any options that depend on initial cursor location. */
+ VIEWOPS_FLAG_USE_MOUSE_INIT = (1 << 3),
};
static enum eViewOpsFlag viewops_flag_from_args(bool use_select, bool use_depth)
{
- enum eViewOpsFlag flag = 0;
- if (use_select) {
- flag |= VIEWOPS_FLAG_ORBIT_SELECT;
- }
- if (use_depth) {
- flag |= VIEWOPS_FLAG_DEPTH_NAVIGATE;
- }
+ enum eViewOpsFlag flag = 0;
+ if (use_select) {
+ flag |= VIEWOPS_FLAG_ORBIT_SELECT;
+ }
+ if (use_depth) {
+ flag |= VIEWOPS_FLAG_DEPTH_NAVIGATE;
+ }
- return flag;
+ return flag;
}
static enum eViewOpsFlag viewops_flag_from_prefs(void)
{
- return viewops_flag_from_args(
- (U.uiflag & USER_ORBIT_SELECTION) != 0,
- (U.uiflag & USER_DEPTH_NAVIGATE) != 0);
+ return viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0,
+ (U.uiflag & USER_DEPTH_NAVIGATE) != 0);
}
/**
* Calculate the values for #ViewOpsData
*/
-static void viewops_data_create(
- bContext *C, wmOperator *op, const wmEvent *event,
- enum eViewOpsFlag viewops_flag)
-{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ViewOpsData *vod = op->customdata;
- RegionView3D *rv3d = vod->rv3d;
-
- /* Could do this more nicely. */
- if ((viewops_flag & VIEWOPS_FLAG_USE_MOUSE_INIT) == 0) {
- viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE;
- }
-
- /* we need the depth info before changing any viewport options */
- if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) {
- float fallback_depth_pt[3];
-
- view3d_operator_needs_opengl(C); /* needed for zbuf drawing */
-
- 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);
- }
- else {
- vod->use_dyn_ofs = false;
- }
-
- if (viewops_flag & VIEWOPS_FLAG_PERSP_ENSURE) {
- if (ED_view3d_persp_ensure(depsgraph, vod->v3d, vod->ar)) {
- /* If we're switching from camera view to the perspective one,
- * need to tag viewport update, so camera vuew and borders
- * are properly updated.
- */
- ED_region_tag_redraw(vod->ar);
- }
- }
-
- /* set the view from the camera, if view locking is enabled.
- * we may want to make this optional but for now its needed always */
- ED_view3d_camera_lock_init(depsgraph, vod->v3d, vod->rv3d);
-
- vod->init.dist = rv3d->dist;
- vod->init.camzoom = rv3d->camzoom;
- copy_qt_qt(vod->init.quat, rv3d->viewquat);
- vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x;
- vod->init.event_xy[1] = vod->prev.event_xy[1] = event->y;
-
- if (viewops_flag & VIEWOPS_FLAG_USE_MOUSE_INIT) {
- vod->init.event_xy_offset[0] = 0;
- vod->init.event_xy_offset[1] = 0;
- }
- 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_type = event->type;
- copy_v3_v3(vod->init.ofs, rv3d->ofs);
-
- copy_qt_qt(vod->curr.viewquat, rv3d->viewquat);
-
- if (viewops_flag & VIEWOPS_FLAG_ORBIT_SELECT) {
- float ofs[3];
- if (view3d_orbit_calc_center(C, ofs) || (vod->use_dyn_ofs == false)) {
- vod->use_dyn_ofs = true;
- negate_v3_v3(vod->dyn_ofs, ofs);
- viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE;
- }
- }
-
- if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) {
- if (vod->use_dyn_ofs) {
- if (rv3d->is_persp) {
- float my_origin[3]; /* original G.vd->ofs */
- float my_pivot[3]; /* view */
- float dvec[3];
-
- /* locals for dist correction */
- float mat[3][3];
- float upvec[3];
-
- negate_v3_v3(my_origin, rv3d->ofs); /* ofs is flipped */
-
- /* Set the dist value to be the distance from this 3d point this means youll
- * always be able to zoom into it and panning wont go bad when dist was zero */
-
- /* remove dist value */
- upvec[0] = upvec[1] = 0;
- upvec[2] = rv3d->dist;
- copy_m3_m4(mat, rv3d->viewinv);
-
- mul_m3_v3(mat, upvec);
- sub_v3_v3v3(my_pivot, rv3d->ofs, upvec);
- negate_v3(my_pivot); /* ofs is flipped */
-
- /* find a new ofs value that is along the view axis
- * (rather than the mouse location) */
- closest_to_line_v3(dvec, vod->dyn_ofs, my_pivot, my_origin);
- vod->init.dist = rv3d->dist = len_v3v3(my_pivot, dvec);
-
- 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};
-
- ED_view3d_win_to_3d(vod->v3d, vod->ar, vod->dyn_ofs, mval_ar_mid, rv3d->ofs);
- negate_v3(rv3d->ofs);
- }
- negate_v3(vod->dyn_ofs);
- copy_v3_v3(vod->init.ofs, rv3d->ofs);
- }
- }
-
- /* For dolly */
- ED_view3d_win_to_vector(vod->ar, (const float[2]){UNPACK2(event->mval)}, vod->init.mousevec);
-
- {
- const int event_xy_offset[2] = {
- event->x + vod->init.event_xy_offset[0],
- event->y + vod->init.event_xy_offset[1],
- };
- /* For rotation with trackball rotation. */
- calctrackballvec(&vod->ar->winrct, event_xy_offset, vod->init.trackvec);
- }
-
- {
- float tvec[3];
- negate_v3_v3(tvec, rv3d->ofs);
- vod->init.zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL);
- }
-
- vod->reverse = 1.0f;
- if (rv3d->persmat[2][1] < 0.0f) {
- vod->reverse = -1.0f;
- }
-
- rv3d->rflag |= RV3D_NAVIGATING;
+static void viewops_data_create(bContext *C,
+ wmOperator *op,
+ const wmEvent *event,
+ enum eViewOpsFlag viewops_flag)
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ViewOpsData *vod = op->customdata;
+ RegionView3D *rv3d = vod->rv3d;
+
+ /* Could do this more nicely. */
+ if ((viewops_flag & VIEWOPS_FLAG_USE_MOUSE_INIT) == 0) {
+ viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE;
+ }
+
+ /* we need the depth info before changing any viewport options */
+ if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) {
+ float fallback_depth_pt[3];
+
+ view3d_operator_needs_opengl(C); /* needed for zbuf drawing */
+
+ 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);
+ }
+ else {
+ vod->use_dyn_ofs = false;
+ }
+
+ if (viewops_flag & VIEWOPS_FLAG_PERSP_ENSURE) {
+ if (ED_view3d_persp_ensure(depsgraph, vod->v3d, vod->ar)) {
+ /* If we're switching from camera view to the perspective one,
+ * need to tag viewport update, so camera vuew and borders
+ * are properly updated.
+ */
+ ED_region_tag_redraw(vod->ar);
+ }
+ }
+
+ /* set the view from the camera, if view locking is enabled.
+ * we may want to make this optional but for now its needed always */
+ ED_view3d_camera_lock_init(depsgraph, vod->v3d, vod->rv3d);
+
+ vod->init.dist = rv3d->dist;
+ vod->init.camzoom = rv3d->camzoom;
+ copy_qt_qt(vod->init.quat, rv3d->viewquat);
+ vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x;
+ vod->init.event_xy[1] = vod->prev.event_xy[1] = event->y;
+
+ if (viewops_flag & VIEWOPS_FLAG_USE_MOUSE_INIT) {
+ vod->init.event_xy_offset[0] = 0;
+ vod->init.event_xy_offset[1] = 0;
+ }
+ 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_type = event->type;
+ copy_v3_v3(vod->init.ofs, rv3d->ofs);
+
+ copy_qt_qt(vod->curr.viewquat, rv3d->viewquat);
+
+ if (viewops_flag & VIEWOPS_FLAG_ORBIT_SELECT) {
+ float ofs[3];
+ if (view3d_orbit_calc_center(C, ofs) || (vod->use_dyn_ofs == false)) {
+ vod->use_dyn_ofs = true;
+ negate_v3_v3(vod->dyn_ofs, ofs);
+ viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE;
+ }
+ }
+
+ if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) {
+ if (vod->use_dyn_ofs) {
+ if (rv3d->is_persp) {
+ float my_origin[3]; /* original G.vd->ofs */
+ float my_pivot[3]; /* view */
+ float dvec[3];
+
+ /* locals for dist correction */
+ float mat[3][3];
+ float upvec[3];
+
+ negate_v3_v3(my_origin, rv3d->ofs); /* ofs is flipped */
+
+ /* Set the dist value to be the distance from this 3d point this means youll
+ * always be able to zoom into it and panning wont go bad when dist was zero */
+
+ /* remove dist value */
+ upvec[0] = upvec[1] = 0;
+ upvec[2] = rv3d->dist;
+ copy_m3_m4(mat, rv3d->viewinv);
+
+ mul_m3_v3(mat, upvec);
+ sub_v3_v3v3(my_pivot, rv3d->ofs, upvec);
+ negate_v3(my_pivot); /* ofs is flipped */
+
+ /* find a new ofs value that is along the view axis
+ * (rather than the mouse location) */
+ closest_to_line_v3(dvec, vod->dyn_ofs, my_pivot, my_origin);
+ vod->init.dist = rv3d->dist = len_v3v3(my_pivot, dvec);
+
+ 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};
+
+ ED_view3d_win_to_3d(vod->v3d, vod->ar, vod->dyn_ofs, mval_ar_mid, rv3d->ofs);
+ negate_v3(rv3d->ofs);
+ }
+ negate_v3(vod->dyn_ofs);
+ copy_v3_v3(vod->init.ofs, rv3d->ofs);
+ }
+ }
+
+ /* For dolly */
+ ED_view3d_win_to_vector(vod->ar, (const float[2]){UNPACK2(event->mval)}, vod->init.mousevec);
+
+ {
+ const int event_xy_offset[2] = {
+ event->x + vod->init.event_xy_offset[0],
+ event->y + vod->init.event_xy_offset[1],
+ };
+ /* For rotation with trackball rotation. */
+ calctrackballvec(&vod->ar->winrct, event_xy_offset, vod->init.trackvec);
+ }
+
+ {
+ float tvec[3];
+ negate_v3_v3(tvec, rv3d->ofs);
+ vod->init.zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL);
+ }
+
+ vod->reverse = 1.0f;
+ if (rv3d->persmat[2][1] < 0.0f) {
+ vod->reverse = -1.0f;
+ }
+
+ rv3d->rflag |= RV3D_NAVIGATING;
}
static void viewops_data_free(bContext *C, wmOperator *op)
{
- ARegion *ar;
+ ARegion *ar;
#if 0
- Paint *p = BKE_paint_get_active_from_context(C);
+ Paint *p = BKE_paint_get_active_from_context(C);
#endif
- if (op->customdata) {
- ViewOpsData *vod = op->customdata;
- ar = vod->ar;
- vod->rv3d->rflag &= ~RV3D_NAVIGATING;
-
- if (vod->timer) {
- WM_event_remove_timer(CTX_wm_manager(C), vod->timer->win, vod->timer);
- }
-
- MEM_freeN(vod);
- op->customdata = NULL;
- }
- else {
- ar = CTX_wm_region(C);
- }
+ if (op->customdata) {
+ ViewOpsData *vod = op->customdata;
+ ar = vod->ar;
+ vod->rv3d->rflag &= ~RV3D_NAVIGATING;
+
+ if (vod->timer) {
+ WM_event_remove_timer(CTX_wm_manager(C), vod->timer->win, vod->timer);
+ }
+
+ MEM_freeN(vod);
+ op->customdata = NULL;
+ }
+ else {
+ ar = CTX_wm_region(C);
+ }
#if 0
- if (p && (p->flags & PAINT_FAST_NAVIGATE))
+ if (p && (p->flags & PAINT_FAST_NAVIGATE))
#endif
- {
- ED_region_tag_redraw(ar);
- }
+ {
+ ED_region_tag_redraw(ar);
+ }
}
/** \} */
@@ -551,444 +551,445 @@ static void viewops_data_free(bContext *C, wmOperator *op)
* \{ */
enum {
- VIEW_PASS = 0,
- VIEW_APPLY,
- VIEW_CONFIRM,
+ VIEW_PASS = 0,
+ VIEW_APPLY,
+ VIEW_CONFIRM,
};
/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
enum {
- VIEW_MODAL_CONFIRM = 1, /* used for all view operations */
- VIEWROT_MODAL_AXIS_SNAP_ENABLE = 2,
- VIEWROT_MODAL_AXIS_SNAP_DISABLE = 3,
- VIEWROT_MODAL_SWITCH_ZOOM = 4,
- VIEWROT_MODAL_SWITCH_MOVE = 5,
- VIEWROT_MODAL_SWITCH_ROTATE = 6,
+ VIEW_MODAL_CONFIRM = 1, /* used for all view operations */
+ VIEWROT_MODAL_AXIS_SNAP_ENABLE = 2,
+ VIEWROT_MODAL_AXIS_SNAP_DISABLE = 3,
+ VIEWROT_MODAL_SWITCH_ZOOM = 4,
+ VIEWROT_MODAL_SWITCH_MOVE = 5,
+ VIEWROT_MODAL_SWITCH_ROTATE = 6,
};
/* called in transform_ops.c, on each regeneration of keymaps */
void viewrotate_modal_keymap(wmKeyConfig *keyconf)
{
- static const EnumPropertyItem modal_items[] = {
- {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+ static const EnumPropertyItem modal_items[] = {
+ {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
- {VIEWROT_MODAL_AXIS_SNAP_ENABLE, "AXIS_SNAP_ENABLE", 0, "Axis Snap", ""},
- {VIEWROT_MODAL_AXIS_SNAP_DISABLE, "AXIS_SNAP_DISABLE", 0, "Axis Snap (Off)", ""},
+ {VIEWROT_MODAL_AXIS_SNAP_ENABLE, "AXIS_SNAP_ENABLE", 0, "Axis Snap", ""},
+ {VIEWROT_MODAL_AXIS_SNAP_DISABLE, "AXIS_SNAP_DISABLE", 0, "Axis Snap (Off)", ""},
- {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"},
- {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
+ {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"},
+ {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
- {0, NULL, 0, NULL, NULL},
- };
+ {0, NULL, 0, NULL, NULL},
+ };
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Rotate Modal");
+ wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Rotate Modal");
- /* this function is called for each spacetype, only needs to add map once */
- if (keymap && keymap->modal_items) {
- return;
- }
+ /* 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_add(keyconf, "View3D Rotate Modal", modal_items);
- /* disabled mode switching for now, can re-implement better, later on */
+ /* disabled mode switching for now, can re-implement better, later on */
#if 0
- WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
- WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
- WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
+ WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
+ WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
#endif
- /* assign map to operators */
- WM_modalkeymap_assign(keymap, "VIEW3D_OT_rotate");
+ /* assign map to operators */
+ WM_modalkeymap_assign(keymap, "VIEW3D_OT_rotate");
}
static void viewrotate_apply_dyn_ofs(ViewOpsData *vod, const float viewquat_new[4])
{
- if (vod->use_dyn_ofs) {
- RegionView3D *rv3d = vod->rv3d;
- view3d_orbit_apply_dyn_ofs(rv3d->ofs, vod->init.ofs, vod->init.quat, viewquat_new, vod->dyn_ofs);
- }
+ if (vod->use_dyn_ofs) {
+ RegionView3D *rv3d = vod->rv3d;
+ view3d_orbit_apply_dyn_ofs(
+ rv3d->ofs, vod->init.ofs, vod->init.quat, viewquat_new, vod->dyn_ofs);
+ }
}
static void viewrotate_apply_snap(ViewOpsData *vod)
{
- const float axis_limit = DEG2RADF(45 / 3);
-
- RegionView3D *rv3d = vod->rv3d;
-
- float viewquat_inv[4];
- float zaxis[3] = {0, 0, 1};
- float zaxis_best[3];
- int x, y, z;
- bool found = false;
-
- invert_qt_qt_normalized(viewquat_inv, vod->curr.viewquat);
-
- mul_qt_v3(viewquat_inv, zaxis);
- normalize_v3(zaxis);
-
-
- for (x = -1; x < 2; x++) {
- for (y = -1; y < 2; y++) {
- for (z = -1; z < 2; z++) {
- if (x || y || z) {
- float zaxis_test[3] = {x, y, z};
-
- normalize_v3(zaxis_test);
-
- if (angle_normalized_v3v3(zaxis_test, zaxis) < axis_limit) {
- copy_v3_v3(zaxis_best, zaxis_test);
- found = true;
- }
- }
- }
- }
- }
-
- if (found) {
-
- /* find the best roll */
- float quat_roll[4], quat_final[4], quat_best[4], quat_snap[4];
- float viewquat_align[4]; /* viewquat aligned to zaxis_best */
- float viewquat_align_inv[4]; /* viewquat aligned to zaxis_best */
- float best_angle = axis_limit;
- int j;
-
- /* viewquat_align is the original viewquat aligned to the snapped axis
- * for testing roll */
- rotation_between_vecs_to_quat(viewquat_align, zaxis_best, zaxis);
- normalize_qt(viewquat_align);
- mul_qt_qtqt(viewquat_align, vod->curr.viewquat, viewquat_align);
- normalize_qt(viewquat_align);
- invert_qt_qt_normalized(viewquat_align_inv, viewquat_align);
-
- vec_to_quat(quat_snap, zaxis_best, OB_NEGZ, OB_POSY);
- normalize_qt(quat_snap);
- invert_qt_normalized(quat_snap);
-
- /* check if we can find the roll */
- found = false;
-
- /* find best roll */
- for (j = 0; j < 8; j++) {
- float angle;
- float xaxis1[3] = {1, 0, 0};
- float xaxis2[3] = {1, 0, 0};
- float quat_final_inv[4];
-
- axis_angle_to_quat(quat_roll, zaxis_best, (float)j * DEG2RADF(45.0f));
- normalize_qt(quat_roll);
-
- mul_qt_qtqt(quat_final, quat_snap, quat_roll);
- normalize_qt(quat_final);
-
- /* compare 2 vector angles to find the least roll */
- invert_qt_qt_normalized(quat_final_inv, quat_final);
- mul_qt_v3(viewquat_align_inv, xaxis1);
- mul_qt_v3(quat_final_inv, xaxis2);
- angle = angle_v3v3(xaxis1, xaxis2);
-
- if (angle <= best_angle) {
- found = true;
- best_angle = angle;
- copy_qt_qt(quat_best, quat_final);
- }
- }
-
- if (found) {
- /* lock 'quat_best' to an axis view if we can */
- rv3d->view = ED_view3d_quat_to_axis_view(quat_best, 0.01f);
- if (rv3d->view != RV3D_VIEW_USER) {
- ED_view3d_quat_from_axis_view(rv3d->view, quat_best);
- }
- }
- else {
- copy_qt_qt(quat_best, viewquat_align);
- }
-
- copy_qt_qt(rv3d->viewquat, quat_best);
-
- viewrotate_apply_dyn_ofs(vod, rv3d->viewquat);
- }
+ const float axis_limit = DEG2RADF(45 / 3);
+
+ RegionView3D *rv3d = vod->rv3d;
+
+ float viewquat_inv[4];
+ float zaxis[3] = {0, 0, 1};
+ float zaxis_best[3];
+ int x, y, z;
+ bool found = false;
+
+ invert_qt_qt_normalized(viewquat_inv, vod->curr.viewquat);
+
+ mul_qt_v3(viewquat_inv, zaxis);
+ normalize_v3(zaxis);
+
+ for (x = -1; x < 2; x++) {
+ for (y = -1; y < 2; y++) {
+ for (z = -1; z < 2; z++) {
+ if (x || y || z) {
+ float zaxis_test[3] = {x, y, z};
+
+ normalize_v3(zaxis_test);
+
+ if (angle_normalized_v3v3(zaxis_test, zaxis) < axis_limit) {
+ copy_v3_v3(zaxis_best, zaxis_test);
+ found = true;
+ }
+ }
+ }
+ }
+ }
+
+ if (found) {
+
+ /* find the best roll */
+ float quat_roll[4], quat_final[4], quat_best[4], quat_snap[4];
+ float viewquat_align[4]; /* viewquat aligned to zaxis_best */
+ float viewquat_align_inv[4]; /* viewquat aligned to zaxis_best */
+ float best_angle = axis_limit;
+ int j;
+
+ /* viewquat_align is the original viewquat aligned to the snapped axis
+ * for testing roll */
+ rotation_between_vecs_to_quat(viewquat_align, zaxis_best, zaxis);
+ normalize_qt(viewquat_align);
+ mul_qt_qtqt(viewquat_align, vod->curr.viewquat, viewquat_align);
+ normalize_qt(viewquat_align);
+ invert_qt_qt_normalized(viewquat_align_inv, viewquat_align);
+
+ vec_to_quat(quat_snap, zaxis_best, OB_NEGZ, OB_POSY);
+ normalize_qt(quat_snap);
+ invert_qt_normalized(quat_snap);
+
+ /* check if we can find the roll */
+ found = false;
+
+ /* find best roll */
+ for (j = 0; j < 8; j++) {
+ float angle;
+ float xaxis1[3] = {1, 0, 0};
+ float xaxis2[3] = {1, 0, 0};
+ float quat_final_inv[4];
+
+ axis_angle_to_quat(quat_roll, zaxis_best, (float)j * DEG2RADF(45.0f));
+ normalize_qt(quat_roll);
+
+ mul_qt_qtqt(quat_final, quat_snap, quat_roll);
+ normalize_qt(quat_final);
+
+ /* compare 2 vector angles to find the least roll */
+ invert_qt_qt_normalized(quat_final_inv, quat_final);
+ mul_qt_v3(viewquat_align_inv, xaxis1);
+ mul_qt_v3(quat_final_inv, xaxis2);
+ angle = angle_v3v3(xaxis1, xaxis2);
+
+ if (angle <= best_angle) {
+ found = true;
+ best_angle = angle;
+ copy_qt_qt(quat_best, quat_final);
+ }
+ }
+
+ if (found) {
+ /* lock 'quat_best' to an axis view if we can */
+ rv3d->view = ED_view3d_quat_to_axis_view(quat_best, 0.01f);
+ if (rv3d->view != RV3D_VIEW_USER) {
+ ED_view3d_quat_from_axis_view(rv3d->view, quat_best);
+ }
+ }
+ else {
+ copy_qt_qt(quat_best, viewquat_align);
+ }
+
+ copy_qt_qt(rv3d->viewquat, quat_best);
+
+ viewrotate_apply_dyn_ofs(vod, rv3d->viewquat);
+ }
}
static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2])
{
- RegionView3D *rv3d = vod->rv3d;
+ RegionView3D *rv3d = vod->rv3d;
- rv3d->view = RV3D_VIEW_USER; /* need to reset every time because of view snapping */
+ rv3d->view = RV3D_VIEW_USER; /* need to reset every time because of view snapping */
- if (U.flag & USER_TRACKBALL) {
- float axis[3], q1[4], dvec[3], newvec[3];
- float angle;
+ if (U.flag & USER_TRACKBALL) {
+ float axis[3], q1[4], dvec[3], newvec[3];
+ float angle;
- {
- const int event_xy_offset[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);
- }
+ {
+ const int event_xy_offset[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);
+ }
- sub_v3_v3v3(dvec, newvec, vod->init.trackvec);
+ sub_v3_v3v3(dvec, newvec, vod->init.trackvec);
- angle = (len_v3(dvec) / (2.0f * TRACKBALLSIZE)) * (float)M_PI;
+ angle = (len_v3(dvec) / (2.0f * TRACKBALLSIZE)) * (float)M_PI;
- /* Allow for rotation beyond the interval [-pi, pi] */
- angle = angle_wrap_rad(angle);
+ /* Allow for rotation beyond the interval [-pi, pi] */
+ angle = angle_wrap_rad(angle);
- /* This relation is used instead of the actual angle between vectors
- * so that the angle of rotation is linearly proportional to
- * the distance that the mouse is dragged. */
+ /* This relation is used instead of the actual angle between vectors
+ * so that the angle of rotation is linearly proportional to
+ * the distance that the mouse is dragged. */
- cross_v3_v3v3(axis, vod->init.trackvec, newvec);
- axis_angle_to_quat(q1, axis, angle);
+ cross_v3_v3v3(axis, vod->init.trackvec, newvec);
+ axis_angle_to_quat(q1, axis, angle);
- mul_qt_qtqt(vod->curr.viewquat, q1, vod->init.quat);
+ mul_qt_qtqt(vod->curr.viewquat, q1, vod->init.quat);
- viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat);
- }
- else {
- /* New turntable view code by John Aughey */
- float quat_local_x[4], quat_global_z[4];
- float m[3][3];
- float m_inv[3][3];
- const float zvec_global[3] = {0.0f, 0.0f, 1.0f};
- float xaxis[3];
+ viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat);
+ }
+ else {
+ /* New turntable view code by John Aughey */
+ float quat_local_x[4], quat_global_z[4];
+ float m[3][3];
+ float m_inv[3][3];
+ const float zvec_global[3] = {0.0f, 0.0f, 1.0f};
+ float xaxis[3];
- /* Sensitivity will control how fast the viewport rotates. 0.007 was
- * obtained experimentally by looking at viewport rotation sensitivities
- * on other modeling programs. */
- /* Perhaps this should be a configurable user parameter. */
- const float sensitivity = 0.007f;
+ /* Sensitivity will control how fast the viewport rotates. 0.007 was
+ * obtained experimentally by looking at viewport rotation sensitivities
+ * on other modeling programs. */
+ /* Perhaps this should be a configurable user parameter. */
+ const float sensitivity = 0.007f;
- /* Get the 3x3 matrix and its inverse from the quaternion */
- quat_to_mat3(m, vod->curr.viewquat);
- invert_m3_m3(m_inv, m);
+ /* Get the 3x3 matrix and its inverse from the quaternion */
+ quat_to_mat3(m, vod->curr.viewquat);
+ invert_m3_m3(m_inv, m);
- /* avoid gimble lock */
+ /* avoid gimble lock */
#if 1
- if (len_squared_v3v3(zvec_global, m_inv[2]) > 0.001f) {
- float fac;
- cross_v3_v3v3(xaxis, zvec_global, m_inv[2]);
- if (dot_v3v3(xaxis, m_inv[0]) < 0) {
- negate_v3(xaxis);
- }
- fac = angle_normalized_v3v3(zvec_global, m_inv[2]) / (float)M_PI;
- fac = fabsf(fac - 0.5f) * 2;
- fac = fac * fac;
- interp_v3_v3v3(xaxis, xaxis, m_inv[0], fac);
- }
- else {
- copy_v3_v3(xaxis, m_inv[0]);
- }
+ if (len_squared_v3v3(zvec_global, m_inv[2]) > 0.001f) {
+ float fac;
+ cross_v3_v3v3(xaxis, zvec_global, m_inv[2]);
+ if (dot_v3v3(xaxis, m_inv[0]) < 0) {
+ negate_v3(xaxis);
+ }
+ fac = angle_normalized_v3v3(zvec_global, m_inv[2]) / (float)M_PI;
+ fac = fabsf(fac - 0.5f) * 2;
+ fac = fac * fac;
+ interp_v3_v3v3(xaxis, xaxis, m_inv[0], fac);
+ }
+ else {
+ copy_v3_v3(xaxis, m_inv[0]);
+ }
#else
- copy_v3_v3(xaxis, m_inv[0]);
+ copy_v3_v3(xaxis, m_inv[0]);
#endif
- /* Determine the direction of the x vector (for rotating up and down) */
- /* This can likely be computed directly from the quaternion. */
+ /* Determine the direction of the x vector (for rotating up and down) */
+ /* This can likely be computed directly from the quaternion. */
- /* Perform the up/down rotation */
- axis_angle_to_quat(quat_local_x, xaxis, sensitivity * -(event_xy[1] - vod->prev.event_xy[1]));
- mul_qt_qtqt(quat_local_x, vod->curr.viewquat, quat_local_x);
+ /* Perform the up/down rotation */
+ axis_angle_to_quat(quat_local_x, xaxis, sensitivity * -(event_xy[1] - vod->prev.event_xy[1]));
+ mul_qt_qtqt(quat_local_x, vod->curr.viewquat, quat_local_x);
- /* Perform the orbital rotation */
- axis_angle_to_quat_single(quat_global_z, 'Z', sensitivity * vod->reverse * (event_xy[0] - vod->prev.event_xy[0]));
- mul_qt_qtqt(vod->curr.viewquat, quat_local_x, quat_global_z);
+ /* Perform the orbital rotation */
+ axis_angle_to_quat_single(
+ quat_global_z, 'Z', sensitivity * vod->reverse * (event_xy[0] - vod->prev.event_xy[0]));
+ mul_qt_qtqt(vod->curr.viewquat, quat_local_x, quat_global_z);
- viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat);
- }
+ viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat);
+ }
- /* avoid precision loss over time */
- normalize_qt(vod->curr.viewquat);
+ /* avoid precision loss over time */
+ normalize_qt(vod->curr.viewquat);
- /* use a working copy so view rotation locking doesn't overwrite the locked
- * rotation back into the view we calculate with */
- copy_qt_qt(rv3d->viewquat, vod->curr.viewquat);
+ /* use a working copy so view rotation locking doesn't overwrite the locked
+ * rotation back into the view we calculate with */
+ copy_qt_qt(rv3d->viewquat, vod->curr.viewquat);
- /* check for view snap,
- * note: don't apply snap to vod->viewquat so the view wont jam up */
- if (vod->axis_snap) {
- viewrotate_apply_snap(vod);
- }
- vod->prev.event_xy[0] = event_xy[0];
- vod->prev.event_xy[1] = event_xy[1];
+ /* check for view snap,
+ * note: don't apply snap to vod->viewquat so the view wont jam up */
+ if (vod->axis_snap) {
+ viewrotate_apply_snap(vod);
+ }
+ vod->prev.event_xy[0] = event_xy[0];
+ vod->prev.event_xy[1] = event_xy[1];
- ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, rv3d);
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, rv3d);
- ED_region_tag_redraw(vod->ar);
+ ED_region_tag_redraw(vod->ar);
}
static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewOpsData *vod = op->customdata;
- short event_code = VIEW_PASS;
- bool use_autokey = false;
- int ret = OPERATOR_RUNNING_MODAL;
-
- /* execute the events */
- if (event->type == MOUSEMOVE) {
- event_code = VIEW_APPLY;
- }
- else if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case VIEW_MODAL_CONFIRM:
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_AXIS_SNAP_ENABLE:
- vod->axis_snap = true;
- event_code = VIEW_APPLY;
- break;
- case VIEWROT_MODAL_AXIS_SNAP_DISABLE:
- vod->axis_snap = false;
- event_code = VIEW_APPLY;
- break;
- case VIEWROT_MODAL_SWITCH_ZOOM:
- WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_SWITCH_MOVE:
- WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- }
- }
- else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
- event_code = VIEW_CONFIRM;
- }
-
- if (event_code == VIEW_APPLY) {
- viewrotate_apply(vod, &event->x);
- if (ED_screen_animation_playing(CTX_wm_manager(C))) {
- use_autokey = true;
- }
- }
- else if (event_code == VIEW_CONFIRM) {
- ED_view3d_depth_tag_update(vod->rv3d);
- use_autokey = true;
- ret = OPERATOR_FINISHED;
- }
-
- if (use_autokey) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, true);
- }
-
- if (ret & OPERATOR_FINISHED) {
- viewops_data_free(C, op);
- }
-
- return ret;
+ ViewOpsData *vod = op->customdata;
+ short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
+
+ /* execute the events */
+ if (event->type == MOUSEMOVE) {
+ event_code = VIEW_APPLY;
+ }
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case VIEW_MODAL_CONFIRM:
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_AXIS_SNAP_ENABLE:
+ vod->axis_snap = true;
+ event_code = VIEW_APPLY;
+ break;
+ case VIEWROT_MODAL_AXIS_SNAP_DISABLE:
+ vod->axis_snap = false;
+ event_code = VIEW_APPLY;
+ break;
+ case VIEWROT_MODAL_SWITCH_ZOOM:
+ WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_MOVE:
+ WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ }
+ }
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
+ event_code = VIEW_CONFIRM;
+ }
+
+ if (event_code == VIEW_APPLY) {
+ viewrotate_apply(vod, &event->x);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
+ }
+ else if (event_code == VIEW_CONFIRM) {
+ ED_view3d_depth_tag_update(vod->rv3d);
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
+
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, true);
+ }
+
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op);
+ }
+
+ return ret;
}
static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewOpsData *vod;
+ ViewOpsData *vod;
- const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
- /* makes op->customdata */
- viewops_data_alloc(C, op);
- vod = op->customdata;
+ /* makes op->customdata */
+ viewops_data_alloc(C, op);
+ vod = op->customdata;
- /* poll should check but in some cases fails, see poll func for details */
- if (vod->rv3d->viewlock & RV3D_LOCKED) {
- viewops_data_free(C, op);
- return OPERATOR_PASS_THROUGH;
- }
+ /* poll should check but in some cases fails, see poll func for details */
+ if (vod->rv3d->viewlock & RV3D_LOCKED) {
+ 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->ar);
- viewops_data_create(
- C, op, event,
- viewops_flag_from_prefs() |
- VIEWOPS_FLAG_PERSP_ENSURE |
- (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
+ viewops_data_create(C,
+ op,
+ event,
+ viewops_flag_from_prefs() | VIEWOPS_FLAG_PERSP_ENSURE |
+ (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
- if (ELEM(event->type, MOUSEPAN, MOUSEROTATE)) {
- /* Rotate direction we keep always same */
- int event_xy[2];
+ if (ELEM(event->type, MOUSEPAN, MOUSEROTATE)) {
+ /* Rotate direction we keep always same */
+ int event_xy[2];
- if (event->type == MOUSEPAN) {
- if (U.uiflag2 & USER_TRACKPAD_NATURAL) {
- event_xy[0] = 2 * event->x - event->prevx;
- event_xy[1] = 2 * event->y - event->prevy;
- }
- else {
- event_xy[0] = event->prevx;
- event_xy[1] = event->prevy;
- }
- }
- else {
- /* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */
- event_xy[0] = event->prevx;
- event_xy[1] = event->y;
- }
+ if (event->type == MOUSEPAN) {
+ if (U.uiflag2 & USER_TRACKPAD_NATURAL) {
+ event_xy[0] = 2 * event->x - event->prevx;
+ event_xy[1] = 2 * event->y - event->prevy;
+ }
+ else {
+ event_xy[0] = event->prevx;
+ event_xy[1] = event->prevy;
+ }
+ }
+ else {
+ /* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */
+ event_xy[0] = event->prevx;
+ event_xy[1] = event->y;
+ }
- viewrotate_apply(vod, event_xy);
- ED_view3d_depth_tag_update(vod->rv3d);
+ viewrotate_apply(vod, event_xy);
+ ED_view3d_depth_tag_update(vod->rv3d);
- viewops_data_free(C, op);
+ viewops_data_free(C, op);
- return OPERATOR_FINISHED;
- }
- else {
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
- }
+ return OPERATOR_RUNNING_MODAL;
+ }
}
/* test for unlocked camera view in quad view */
static bool view3d_camera_user_poll(bContext *C)
{
- View3D *v3d;
- ARegion *ar;
+ View3D *v3d;
+ ARegion *ar;
- if (ED_view3d_context_user_region(C, &v3d, &ar)) {
- RegionView3D *rv3d = ar->regiondata;
- if (rv3d->persp == RV3D_CAMOB) {
- return 1;
- }
- }
+ if (ED_view3d_context_user_region(C, &v3d, &ar)) {
+ RegionView3D *rv3d = ar->regiondata;
+ if (rv3d->persp == RV3D_CAMOB) {
+ return 1;
+ }
+ }
- return 0;
+ 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;
+ 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);
+ viewops_data_free(C, op);
}
void VIEW3D_OT_rotate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Rotate View";
- ot->description = "Rotate the view";
- ot->idname = "VIEW3D_OT_rotate";
+ /* identifiers */
+ ot->name = "Rotate View";
+ ot->description = "Rotate the view";
+ ot->idname = "VIEW3D_OT_rotate";
- /* api callbacks */
- ot->invoke = viewrotate_invoke;
- ot->modal = viewrotate_modal;
- ot->poll = ED_operator_region_view3d_active;
- ot->cancel = viewrotate_cancel;
+ /* api callbacks */
+ ot->invoke = viewrotate_invoke;
+ ot->modal = viewrotate_modal;
+ ot->poll = ED_operator_region_view3d_active;
+ ot->cancel = viewrotate_cancel;
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
- view3d_operator_properties_common(ot, V3D_OP_PROP_USE_MOUSE_INIT);
+ view3d_operator_properties_common(ot, V3D_OP_PROP_USE_MOUSE_INIT);
}
/** \} */
@@ -998,48 +999,48 @@ void VIEW3D_OT_rotate(wmOperatorType *ot)
* \{ */
#ifdef WITH_INPUT_NDOF
-#define NDOF_HAS_TRANSLATE ((!ED_view3d_offset_lock_check(v3d, rv3d)) && !is_zero_v3(ndof->tvec))
-#define NDOF_HAS_ROTATE (((rv3d->viewlock & RV3D_LOCKED) == 0) && !is_zero_v3(ndof->rvec))
+# define NDOF_HAS_TRANSLATE ((!ED_view3d_offset_lock_check(v3d, rv3d)) && !is_zero_v3(ndof->tvec))
+# define NDOF_HAS_ROTATE (((rv3d->viewlock & RV3D_LOCKED) == 0) && !is_zero_v3(ndof->rvec))
/**
* \param depth_pt: A point to calculate the depth (in perspective mode)
*/
static float view3d_ndof_pan_speed_calc_ex(RegionView3D *rv3d, const float depth_pt[3])
{
- float speed = rv3d->pixsize * NDOF_PIXELS_PER_SECOND;
+ float speed = rv3d->pixsize * NDOF_PIXELS_PER_SECOND;
- if (rv3d->is_persp) {
- speed *= ED_view3d_calc_zfac(rv3d, depth_pt, NULL);
- }
+ if (rv3d->is_persp) {
+ speed *= ED_view3d_calc_zfac(rv3d, depth_pt, NULL);
+ }
- return speed;
+ return speed;
}
static float view3d_ndof_pan_speed_calc_from_dist(RegionView3D *rv3d, const float dist)
{
- float viewinv[4];
- float tvec[3];
+ float viewinv[4];
+ float tvec[3];
- BLI_assert(dist >= 0.0f);
+ BLI_assert(dist >= 0.0f);
- copy_v3_fl3(tvec, 0.0f, 0.0f, dist);
- /* rv3d->viewinv isn't always valid */
-#if 0
- mul_mat3_m4_v3(rv3d->viewinv, tvec);
-#else
- invert_qt_qt_normalized(viewinv, rv3d->viewquat);
- mul_qt_v3(viewinv, tvec);
-#endif
+ copy_v3_fl3(tvec, 0.0f, 0.0f, dist);
+ /* rv3d->viewinv isn't always valid */
+# if 0
+ mul_mat3_m4_v3(rv3d->viewinv, tvec);
+# else
+ invert_qt_qt_normalized(viewinv, rv3d->viewquat);
+ mul_qt_v3(viewinv, tvec);
+# endif
- return view3d_ndof_pan_speed_calc_ex(rv3d, tvec);
+ return view3d_ndof_pan_speed_calc_ex(rv3d, tvec);
}
static float view3d_ndof_pan_speed_calc(RegionView3D *rv3d)
{
- float tvec[3];
- negate_v3_v3(tvec, rv3d->ofs);
+ float tvec[3];
+ negate_v3_v3(tvec, rv3d->ofs);
- return view3d_ndof_pan_speed_calc_ex(rv3d, tvec);
+ return view3d_ndof_pan_speed_calc_ex(rv3d, tvec);
}
/**
@@ -1047,261 +1048,265 @@ static float view3d_ndof_pan_speed_calc(RegionView3D *rv3d)
*
* \param has_zoom: zoom, otherwise dolly, 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,
- const bool has_translate, const bool has_zoom)
+static void view3d_ndof_pan_zoom(const struct wmNDOFMotionData *ndof,
+ ScrArea *sa,
+ ARegion *ar,
+ const bool has_translate,
+ const bool has_zoom)
{
- RegionView3D *rv3d = ar->regiondata;
- float view_inv[4];
- float pan_vec[3];
+ RegionView3D *rv3d = ar->regiondata;
+ float view_inv[4];
+ float pan_vec[3];
- if (has_translate == false && has_zoom == false) {
- return;
- }
+ if (has_translate == false && has_zoom == false) {
+ return;
+ }
- WM_event_ndof_pan_get(ndof, pan_vec, false);
+ WM_event_ndof_pan_get(ndof, pan_vec, false);
- if (has_zoom) {
- /* zoom with Z */
+ if (has_zoom) {
+ /* zoom with Z */
- /* Zoom!
- * velocity should be proportional to the linear velocity attained by rotational motion of same strength
- * [got that?]
- * proportional to arclength = radius * angle
- */
+ /* Zoom!
+ * velocity should be proportional to the linear velocity attained by rotational motion of same strength
+ * [got that?]
+ * proportional to arclength = radius * angle
+ */
- pan_vec[2] = 0.0f;
+ pan_vec[2] = 0.0f;
- /* "zoom in" or "translate"? depends on zoom mode in user settings? */
- if (ndof->tvec[2]) {
- float zoom_distance = rv3d->dist * ndof->dt * ndof->tvec[2];
+ /* "zoom in" or "translate"? depends on zoom mode in user settings? */
+ if (ndof->tvec[2]) {
+ float zoom_distance = rv3d->dist * ndof->dt * ndof->tvec[2];
- if (U.ndof_flag & NDOF_ZOOM_INVERT) {
- zoom_distance = -zoom_distance;
- }
+ if (U.ndof_flag & NDOF_ZOOM_INVERT) {
+ zoom_distance = -zoom_distance;
+ }
- rv3d->dist += zoom_distance;
- }
- }
- else {
- /* dolly with Z */
+ rv3d->dist += zoom_distance;
+ }
+ }
+ else {
+ /* dolly with Z */
- /* all callers must check */
- if (has_translate) {
- BLI_assert(ED_view3d_offset_lock_check((View3D *)sa->spacedata.first, rv3d) == false);
- }
- }
+ /* all callers must check */
+ if (has_translate) {
+ BLI_assert(ED_view3d_offset_lock_check((View3D *)sa->spacedata.first, rv3d) == false);
+ }
+ }
- if (has_translate) {
- const float speed = view3d_ndof_pan_speed_calc(rv3d);
+ if (has_translate) {
+ const float speed = view3d_ndof_pan_speed_calc(rv3d);
- mul_v3_fl(pan_vec, speed * ndof->dt);
+ mul_v3_fl(pan_vec, speed * ndof->dt);
- /* transform motion from view to world coordinates */
- invert_qt_qt_normalized(view_inv, rv3d->viewquat);
- mul_qt_v3(view_inv, pan_vec);
+ /* transform motion from view to world coordinates */
+ invert_qt_qt_normalized(view_inv, rv3d->viewquat);
+ mul_qt_v3(view_inv, pan_vec);
- /* move center of view opposite of hand motion (this is camera mode, not object mode) */
- sub_v3_v3(rv3d->ofs, pan_vec);
+ /* 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->viewlock & RV3D_BOXVIEW) {
+ view3d_boxview_sync(sa, ar);
+ }
+ }
}
-
-static void view3d_ndof_orbit(
- const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar,
- ViewOpsData *vod, const bool apply_dyn_ofs)
+static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof,
+ ScrArea *sa,
+ ARegion *ar,
+ ViewOpsData *vod,
+ const bool apply_dyn_ofs)
{
- View3D *v3d = sa->spacedata.first;
- RegionView3D *rv3d = ar->regiondata;
+ View3D *v3d = sa->spacedata.first;
+ RegionView3D *rv3d = ar->regiondata;
- float view_inv[4];
+ float view_inv[4];
- BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
+ BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
- ED_view3d_persp_ensure(vod->depsgraph, v3d, ar);
+ ED_view3d_persp_ensure(vod->depsgraph, v3d, ar);
- rv3d->view = RV3D_VIEW_USER;
+ rv3d->view = RV3D_VIEW_USER;
- invert_qt_qt_normalized(view_inv, rv3d->viewquat);
+ invert_qt_qt_normalized(view_inv, rv3d->viewquat);
- if (U.ndof_flag & NDOF_TURNTABLE) {
- float rot[3];
+ if (U.ndof_flag & NDOF_TURNTABLE) {
+ float rot[3];
- /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */
- float angle, quat[4];
- float xvec[3] = {1, 0, 0};
+ /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */
+ float angle, quat[4];
+ float xvec[3] = {1, 0, 0};
- /* only use XY, ignore Z */
- WM_event_ndof_rotate_get(ndof, rot);
+ /* only use XY, ignore Z */
+ WM_event_ndof_rotate_get(ndof, rot);
- /* Determine the direction of the x vector (for rotating up and down) */
- mul_qt_v3(view_inv, xvec);
+ /* Determine the direction of the x vector (for rotating up and down) */
+ mul_qt_v3(view_inv, xvec);
- /* Perform the up/down rotation */
- angle = ndof->dt * rot[0];
- axis_angle_to_quat(quat, xvec, angle);
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
+ /* Perform the up/down rotation */
+ angle = ndof->dt * rot[0];
+ axis_angle_to_quat(quat, xvec, angle);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
- /* Perform the orbital rotation */
- angle = ndof->dt * rot[1];
+ /* Perform the orbital rotation */
+ angle = ndof->dt * rot[1];
- /* update the onscreen doo-dad */
- rv3d->rot_angle = angle;
- rv3d->rot_axis[0] = 0;
- rv3d->rot_axis[1] = 0;
- rv3d->rot_axis[2] = 1;
+ /* update the onscreen doo-dad */
+ rv3d->rot_angle = angle;
+ rv3d->rot_axis[0] = 0;
+ rv3d->rot_axis[1] = 0;
+ rv3d->rot_axis[2] = 1;
- axis_angle_to_quat_single(quat, 'Z', angle);
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
- }
- else {
- float quat[4];
- float axis[3];
- float angle = WM_event_ndof_to_axis_angle(ndof, axis);
+ axis_angle_to_quat_single(quat, 'Z', angle);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
+ }
+ else {
+ float quat[4];
+ float axis[3];
+ float angle = WM_event_ndof_to_axis_angle(ndof, axis);
- /* transform rotation axis from view to world coordinates */
- mul_qt_v3(view_inv, axis);
+ /* transform rotation axis from view to world coordinates */
+ mul_qt_v3(view_inv, axis);
- /* update the onscreen doo-dad */
- rv3d->rot_angle = angle;
- copy_v3_v3(rv3d->rot_axis, axis);
+ /* update the onscreen doo-dad */
+ rv3d->rot_angle = angle;
+ copy_v3_v3(rv3d->rot_axis, axis);
- axis_angle_to_quat(quat, axis, angle);
+ axis_angle_to_quat(quat, axis, angle);
- /* apply rotation */
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
- }
+ /* apply rotation */
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
+ }
- if (apply_dyn_ofs) {
- viewrotate_apply_dyn_ofs(vod, rv3d->viewquat);
- }
+ if (apply_dyn_ofs) {
+ viewrotate_apply_dyn_ofs(vod, rv3d->viewquat);
+ }
}
/**
* Called from both fly mode and walk mode,
*/
-void view3d_ndof_fly(
- const wmNDOFMotionData *ndof,
- View3D *v3d, RegionView3D *rv3d,
- const bool use_precision, const short protectflag,
- bool *r_has_translate, bool *r_has_rotate)
-{
- bool has_translate = NDOF_HAS_TRANSLATE;
- bool has_rotate = NDOF_HAS_ROTATE;
-
- float view_inv[4];
- invert_qt_qt_normalized(view_inv, rv3d->viewquat);
-
- rv3d->rot_angle = 0.0f; /* disable onscreen rotation doo-dad */
-
- if (has_translate) {
- /* ignore real 'dist' since fly has its own speed settings,
- * also its overwritten at this point. */
- float speed = view3d_ndof_pan_speed_calc_from_dist(rv3d, 1.0f);
- float trans[3], trans_orig_y;
-
- if (use_precision) {
- speed *= 0.2f;
- }
-
- WM_event_ndof_pan_get(ndof, trans, false);
- mul_v3_fl(trans, speed * ndof->dt);
- trans_orig_y = trans[1];
-
- if (U.ndof_flag & NDOF_FLY_HELICOPTER) {
- trans[1] = 0.0f;
- }
-
- /* transform motion from view to world coordinates */
- mul_qt_v3(view_inv, trans);
-
- if (U.ndof_flag & NDOF_FLY_HELICOPTER) {
- /* replace world z component with device y (yes it makes sense) */
- trans[2] = trans_orig_y;
- }
-
- if (rv3d->persp == RV3D_CAMOB) {
- /* respect camera position locks */
- if (protectflag & OB_LOCK_LOCX) {
- trans[0] = 0.0f;
- }
- if (protectflag & OB_LOCK_LOCY) {
- trans[1] = 0.0f;
- }
- if (protectflag & OB_LOCK_LOCZ) {
- trans[2] = 0.0f;
- }
- }
-
- if (!is_zero_v3(trans)) {
- /* move center of view opposite of hand motion
- * (this is camera mode, not object mode) */
- sub_v3_v3(rv3d->ofs, trans);
- has_translate = true;
- }
- else {
- has_translate = false;
- }
- }
-
- if (has_rotate) {
- const float turn_sensitivity = 1.0f;
-
- float rotation[4];
- float axis[3];
- float angle = turn_sensitivity * WM_event_ndof_to_axis_angle(ndof, axis);
-
- if (fabsf(angle) > 0.0001f) {
- has_rotate = true;
-
- if (use_precision) {
- angle *= 0.2f;
- }
-
- /* transform rotation axis from view to world coordinates */
- mul_qt_v3(view_inv, axis);
-
- /* apply rotation to view */
- axis_angle_to_quat(rotation, axis, angle);
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
-
- if (U.ndof_flag & NDOF_LOCK_HORIZON) {
- /* force an upright viewpoint
- * TODO: make this less... sudden */
- float view_horizon[3] = {1.0f, 0.0f, 0.0f}; /* view +x */
- float view_direction[3] = {0.0f, 0.0f, -1.0f}; /* view -z (into screen) */
-
- /* find new inverse since viewquat has changed */
- invert_qt_qt_normalized(view_inv, rv3d->viewquat);
- /* could apply reverse rotation to existing view_inv to save a few cycles */
-
- /* transform view vectors to world coordinates */
- mul_qt_v3(view_inv, view_horizon);
- mul_qt_v3(view_inv, view_direction);
-
-
- /* find difference between view & world horizons
- * true horizon lives in world xy plane, so look only at difference in z */
- angle = -asinf(view_horizon[2]);
-
- /* rotate view so view horizon = world horizon */
- axis_angle_to_quat(rotation, view_direction, angle);
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
- }
-
- rv3d->view = RV3D_VIEW_USER;
- }
- else {
- has_rotate = false;
- }
- }
-
- *r_has_translate = has_translate;
- *r_has_rotate = has_rotate;
+void view3d_ndof_fly(const wmNDOFMotionData *ndof,
+ View3D *v3d,
+ RegionView3D *rv3d,
+ const bool use_precision,
+ const short protectflag,
+ bool *r_has_translate,
+ bool *r_has_rotate)
+{
+ bool has_translate = NDOF_HAS_TRANSLATE;
+ bool has_rotate = NDOF_HAS_ROTATE;
+
+ float view_inv[4];
+ invert_qt_qt_normalized(view_inv, rv3d->viewquat);
+
+ rv3d->rot_angle = 0.0f; /* disable onscreen rotation doo-dad */
+
+ if (has_translate) {
+ /* ignore real 'dist' since fly has its own speed settings,
+ * also its overwritten at this point. */
+ float speed = view3d_ndof_pan_speed_calc_from_dist(rv3d, 1.0f);
+ float trans[3], trans_orig_y;
+
+ if (use_precision) {
+ speed *= 0.2f;
+ }
+
+ WM_event_ndof_pan_get(ndof, trans, false);
+ mul_v3_fl(trans, speed * ndof->dt);
+ trans_orig_y = trans[1];
+
+ if (U.ndof_flag & NDOF_FLY_HELICOPTER) {
+ trans[1] = 0.0f;
+ }
+
+ /* transform motion from view to world coordinates */
+ mul_qt_v3(view_inv, trans);
+
+ if (U.ndof_flag & NDOF_FLY_HELICOPTER) {
+ /* replace world z component with device y (yes it makes sense) */
+ trans[2] = trans_orig_y;
+ }
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ /* respect camera position locks */
+ if (protectflag & OB_LOCK_LOCX) {
+ trans[0] = 0.0f;
+ }
+ if (protectflag & OB_LOCK_LOCY) {
+ trans[1] = 0.0f;
+ }
+ if (protectflag & OB_LOCK_LOCZ) {
+ trans[2] = 0.0f;
+ }
+ }
+
+ if (!is_zero_v3(trans)) {
+ /* move center of view opposite of hand motion
+ * (this is camera mode, not object mode) */
+ sub_v3_v3(rv3d->ofs, trans);
+ has_translate = true;
+ }
+ else {
+ has_translate = false;
+ }
+ }
+
+ if (has_rotate) {
+ const float turn_sensitivity = 1.0f;
+
+ float rotation[4];
+ float axis[3];
+ float angle = turn_sensitivity * WM_event_ndof_to_axis_angle(ndof, axis);
+
+ if (fabsf(angle) > 0.0001f) {
+ has_rotate = true;
+
+ if (use_precision) {
+ angle *= 0.2f;
+ }
+
+ /* transform rotation axis from view to world coordinates */
+ mul_qt_v3(view_inv, axis);
+
+ /* apply rotation to view */
+ axis_angle_to_quat(rotation, axis, angle);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
+
+ if (U.ndof_flag & NDOF_LOCK_HORIZON) {
+ /* force an upright viewpoint
+ * TODO: make this less... sudden */
+ float view_horizon[3] = {1.0f, 0.0f, 0.0f}; /* view +x */
+ float view_direction[3] = {0.0f, 0.0f, -1.0f}; /* view -z (into screen) */
+
+ /* find new inverse since viewquat has changed */
+ invert_qt_qt_normalized(view_inv, rv3d->viewquat);
+ /* could apply reverse rotation to existing view_inv to save a few cycles */
+
+ /* transform view vectors to world coordinates */
+ mul_qt_v3(view_inv, view_horizon);
+ mul_qt_v3(view_inv, view_direction);
+
+ /* find difference between view & world horizons
+ * true horizon lives in world xy plane, so look only at difference in z */
+ angle = -asinf(view_horizon[2]);
+
+ /* rotate view so view horizon = world horizon */
+ axis_angle_to_quat(rotation, view_direction, angle);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
+ }
+
+ rv3d->view = RV3D_VIEW_USER;
+ }
+ else {
+ has_rotate = false;
+ }
+ }
+
+ *r_has_translate = has_translate;
+ *r_has_rotate = has_rotate;
}
/** \} */
@@ -1312,76 +1317,76 @@ void view3d_ndof_fly(
static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (event->type != NDOF_MOTION) {
- return OPERATOR_CANCELLED;
- }
+ if (event->type != NDOF_MOTION) {
+ return OPERATOR_CANCELLED;
+ }
- const Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ViewOpsData *vod;
- View3D *v3d;
- RegionView3D *rv3d;
- char xform_flag = 0;
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ViewOpsData *vod;
+ View3D *v3d;
+ RegionView3D *rv3d;
+ char xform_flag = 0;
- const wmNDOFMotionData *ndof = event->customdata;
+ const wmNDOFMotionData *ndof = event->customdata;
- viewops_data_alloc(C, op);
- viewops_data_create(
- C, op, event,
- viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0, false));
- vod = op->customdata;
+ viewops_data_alloc(C, op);
+ viewops_data_create(
+ 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->ar);
- v3d = vod->v3d;
- rv3d = vod->rv3d;
+ v3d = vod->v3d;
+ rv3d = vod->rv3d;
- /* off by default, until changed later this function */
- rv3d->rot_angle = 0.0f;
+ /* off by default, until changed later this function */
+ rv3d->rot_angle = 0.0f;
- ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
+ ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
- if (ndof->progress != P_FINISHING) {
- const bool has_rotation = NDOF_HAS_ROTATE;
- /* if we can't rotate, fallback to translate (locked axis views) */
- const bool has_translate = NDOF_HAS_TRANSLATE && (rv3d->viewlock & RV3D_LOCKED);
- const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp;
+ if (ndof->progress != P_FINISHING) {
+ const bool has_rotation = NDOF_HAS_ROTATE;
+ /* if we can't rotate, fallback to translate (locked axis views) */
+ const bool has_translate = NDOF_HAS_TRANSLATE && (rv3d->viewlock & RV3D_LOCKED);
+ 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);
- xform_flag |= HAS_TRANSLATE;
- }
+ if (has_translate || has_zoom) {
+ view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, has_translate, has_zoom);
+ xform_flag |= HAS_TRANSLATE;
+ }
- if (has_rotation) {
- view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true);
- xform_flag |= HAS_ROTATE;
- }
- }
+ if (has_rotation) {
+ view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true);
+ xform_flag |= HAS_ROTATE;
+ }
+ }
- ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
- if (xform_flag) {
- ED_view3d_camera_lock_autokey(v3d, rv3d, C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE);
- }
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
+ if (xform_flag) {
+ ED_view3d_camera_lock_autokey(
+ v3d, rv3d, C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE);
+ }
- ED_region_tag_redraw(vod->ar);
+ ED_region_tag_redraw(vod->ar);
- viewops_data_free(C, op);
+ viewops_data_free(C, op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "NDOF Orbit View";
- ot->description = "Orbit the view using the 3D mouse";
- ot->idname = "VIEW3D_OT_ndof_orbit";
+ /* identifiers */
+ ot->name = "NDOF Orbit View";
+ ot->description = "Orbit the view using the 3D mouse";
+ ot->idname = "VIEW3D_OT_ndof_orbit";
- /* api callbacks */
- ot->invoke = ndof_orbit_invoke;
- ot->poll = ED_operator_view3d_active;
+ /* api callbacks */
+ ot->invoke = ndof_orbit_invoke;
+ ot->poll = ED_operator_view3d_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
/** \} */
@@ -1392,112 +1397,110 @@ void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot)
static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (event->type != NDOF_MOTION) {
- return OPERATOR_CANCELLED;
- }
+ if (event->type != NDOF_MOTION) {
+ return OPERATOR_CANCELLED;
+ }
- const Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ViewOpsData *vod;
- View3D *v3d;
- RegionView3D *rv3d;
- char xform_flag = 0;
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ViewOpsData *vod;
+ View3D *v3d;
+ RegionView3D *rv3d;
+ char xform_flag = 0;
- const wmNDOFMotionData *ndof = event->customdata;
+ const wmNDOFMotionData *ndof = event->customdata;
- viewops_data_alloc(C, op);
- viewops_data_create(
- C, op, event,
- viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0, false));
+ viewops_data_alloc(C, op);
+ viewops_data_create(
+ C, op, event, viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0, false));
- vod = op->customdata;
+ vod = op->customdata;
- ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
+ ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
- v3d = vod->v3d;
- rv3d = vod->rv3d;
+ v3d = vod->v3d;
+ rv3d = vod->rv3d;
- /* off by default, until changed later this function */
- rv3d->rot_angle = 0.0f;
+ /* off by default, until changed later this function */
+ rv3d->rot_angle = 0.0f;
- ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
+ ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
- if (ndof->progress == P_FINISHING) {
- /* pass */
- }
- else if ((rv3d->persp == RV3D_ORTHO) && RV3D_VIEW_IS_AXIS(rv3d->view)) {
- /* if we can't rotate, fallback to translate (locked axis views) */
- const bool has_translate = NDOF_HAS_TRANSLATE;
- const bool has_zoom = (ndof->tvec[2] != 0.0f) && ED_view3d_offset_lock_check(v3d, rv3d);
+ if (ndof->progress == P_FINISHING) {
+ /* pass */
+ }
+ else if ((rv3d->persp == RV3D_ORTHO) && RV3D_VIEW_IS_AXIS(rv3d->view)) {
+ /* if we can't rotate, fallback to translate (locked axis views) */
+ const bool has_translate = NDOF_HAS_TRANSLATE;
+ 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);
- xform_flag |= HAS_TRANSLATE;
- }
- }
- else if ((U.ndof_flag & NDOF_MODE_ORBIT) ||
- ED_view3d_offset_lock_check(v3d, rv3d))
- {
- const bool has_rotation = NDOF_HAS_ROTATE;
- const bool has_zoom = (ndof->tvec[2] != 0.0f);
+ if (has_translate || has_zoom) {
+ view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, has_translate, true);
+ xform_flag |= HAS_TRANSLATE;
+ }
+ }
+ else if ((U.ndof_flag & NDOF_MODE_ORBIT) || ED_view3d_offset_lock_check(v3d, rv3d)) {
+ const bool has_rotation = NDOF_HAS_ROTATE;
+ const bool has_zoom = (ndof->tvec[2] != 0.0f);
- if (has_zoom) {
- view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, false, has_zoom);
- xform_flag |= HAS_TRANSLATE;
- }
+ if (has_zoom) {
+ view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, false, has_zoom);
+ xform_flag |= HAS_TRANSLATE;
+ }
- if (has_rotation) {
- view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true);
- xform_flag |= HAS_ROTATE;
- }
- }
- else { /* free/explore (like fly mode) */
- const bool has_rotation = NDOF_HAS_ROTATE;
- const bool has_translate = NDOF_HAS_TRANSLATE;
- const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp;
+ if (has_rotation) {
+ view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true);
+ xform_flag |= HAS_ROTATE;
+ }
+ }
+ else { /* free/explore (like fly mode) */
+ const bool has_rotation = NDOF_HAS_ROTATE;
+ const bool has_translate = NDOF_HAS_TRANSLATE;
+ const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp;
- float dist_backup;
+ float dist_backup;
- if (has_translate || has_zoom) {
- view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, has_translate, has_zoom);
- xform_flag |= HAS_TRANSLATE;
- }
+ if (has_translate || has_zoom) {
+ view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, has_translate, has_zoom);
+ xform_flag |= HAS_TRANSLATE;
+ }
- dist_backup = rv3d->dist;
- ED_view3d_distance_set(rv3d, 0.0f);
+ dist_backup = rv3d->dist;
+ ED_view3d_distance_set(rv3d, 0.0f);
- if (has_rotation) {
- view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, false);
- xform_flag |= HAS_ROTATE;
- }
+ if (has_rotation) {
+ view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, false);
+ xform_flag |= HAS_ROTATE;
+ }
- ED_view3d_distance_set(rv3d, dist_backup);
- }
+ ED_view3d_distance_set(rv3d, dist_backup);
+ }
- ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
- if (xform_flag) {
- ED_view3d_camera_lock_autokey(v3d, rv3d, C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE);
- }
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
+ if (xform_flag) {
+ ED_view3d_camera_lock_autokey(
+ v3d, rv3d, C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE);
+ }
- ED_region_tag_redraw(vod->ar);
+ ED_region_tag_redraw(vod->ar);
- viewops_data_free(C, op);
+ viewops_data_free(C, op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "NDOF Orbit View with Zoom";
- ot->description = "Orbit and zoom the view using the 3D mouse";
- ot->idname = "VIEW3D_OT_ndof_orbit_zoom";
+ /* identifiers */
+ ot->name = "NDOF Orbit View with Zoom";
+ ot->description = "Orbit and zoom the view using the 3D mouse";
+ ot->idname = "VIEW3D_OT_ndof_orbit_zoom";
- /* api callbacks */
- ot->invoke = ndof_orbit_zoom_invoke;
- ot->poll = ED_operator_view3d_active;
+ /* api callbacks */
+ ot->invoke = ndof_orbit_zoom_invoke;
+ ot->poll = ED_operator_view3d_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
/** \} */
@@ -1508,61 +1511,61 @@ void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot)
static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- if (event->type != NDOF_MOTION) {
- return OPERATOR_CANCELLED;
- }
+ if (event->type != NDOF_MOTION) {
+ return OPERATOR_CANCELLED;
+ }
- const Depsgraph *depsgraph = CTX_data_depsgraph(C);
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- const wmNDOFMotionData *ndof = event->customdata;
- char xform_flag = 0;
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ const wmNDOFMotionData *ndof = event->customdata;
+ char xform_flag = 0;
- const bool has_translate = NDOF_HAS_TRANSLATE;
- const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp;
+ const bool has_translate = NDOF_HAS_TRANSLATE;
+ const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp;
- /* we're panning here! so erase any leftover rotation from other operators */
- rv3d->rot_angle = 0.0f;
+ /* we're panning here! so erase any leftover rotation from other operators */
+ rv3d->rot_angle = 0.0f;
- if (!(has_translate || has_zoom)) {
- return OPERATOR_CANCELLED;
- }
+ if (!(has_translate || has_zoom)) {
+ return OPERATOR_CANCELLED;
+ }
- ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
+ 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);
+ if (ndof->progress != P_FINISHING) {
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
- if (has_translate || has_zoom) {
- view3d_ndof_pan_zoom(ndof, sa, ar, has_translate, has_zoom);
- xform_flag |= HAS_TRANSLATE;
- }
- }
+ if (has_translate || has_zoom) {
+ view3d_ndof_pan_zoom(ndof, sa, ar, has_translate, has_zoom);
+ xform_flag |= HAS_TRANSLATE;
+ }
+ }
- ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
- if (xform_flag) {
- ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, xform_flag & HAS_TRANSLATE);
- }
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
+ if (xform_flag) {
+ ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, xform_flag & HAS_TRANSLATE);
+ }
- ED_region_tag_redraw(CTX_wm_region(C));
+ ED_region_tag_redraw(CTX_wm_region(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "NDOF Pan View";
- ot->description = "Pan the view with the 3D mouse";
- ot->idname = "VIEW3D_OT_ndof_pan";
+ /* identifiers */
+ ot->name = "NDOF Pan View";
+ ot->description = "Pan the view with the 3D mouse";
+ ot->idname = "VIEW3D_OT_ndof_pan";
- /* api callbacks */
- ot->invoke = ndof_pan_invoke;
- ot->poll = ED_operator_view3d_active;
+ /* api callbacks */
+ ot->invoke = ndof_pan_invoke;
+ ot->poll = ED_operator_view3d_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
/** \} */
@@ -1576,32 +1579,32 @@ void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot)
*/
static int ndof_all_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- /* weak!, but it works */
- const int ndof_flag = U.ndof_flag;
- int ret;
+ /* weak!, but it works */
+ const int ndof_flag = U.ndof_flag;
+ int ret;
- U.ndof_flag &= ~NDOF_MODE_ORBIT;
+ U.ndof_flag &= ~NDOF_MODE_ORBIT;
- ret = ndof_orbit_zoom_invoke(C, op, event);
+ ret = ndof_orbit_zoom_invoke(C, op, event);
- U.ndof_flag = ndof_flag;
+ U.ndof_flag = ndof_flag;
- return ret;
+ return ret;
}
void VIEW3D_OT_ndof_all(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "NDOF Transform View";
- ot->description = "Pan and rotate the view with the 3D mouse";
- ot->idname = "VIEW3D_OT_ndof_all";
+ /* identifiers */
+ ot->name = "NDOF Transform View";
+ ot->description = "Pan and rotate the view with the 3D mouse";
+ ot->idname = "VIEW3D_OT_ndof_all";
- /* api callbacks */
- ot->invoke = ndof_all_invoke;
- ot->poll = ED_operator_view3d_active;
+ /* api callbacks */
+ ot->invoke = ndof_all_invoke;
+ ot->poll = ED_operator_view3d_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
#endif /* WITH_INPUT_NDOF */
@@ -1617,188 +1620,187 @@ void VIEW3D_OT_ndof_all(struct wmOperatorType *ot)
/* called in transform_ops.c, on each regeneration of keymaps */
void viewmove_modal_keymap(wmKeyConfig *keyconf)
{
- static const EnumPropertyItem modal_items[] = {
- {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+ static const EnumPropertyItem modal_items[] = {
+ {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
- {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"},
- {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
+ {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"},
+ {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
- {0, NULL, 0, NULL, NULL},
- };
+ {0, NULL, 0, NULL, NULL},
+ };
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Move Modal");
+ wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Move Modal");
- /* this function is called for each spacetype, only needs to add map once */
- if (keymap && keymap->modal_items) {
- return;
- }
+ /* 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_add(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);
+ /* 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);
- /* disabled mode switching for now, can re-implement better, later on */
+ /* disabled mode switching for now, can re-implement better, later on */
#if 0
- WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
- WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
- WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
+ WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
+ WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
#endif
- /* assign map to operators */
- WM_modalkeymap_assign(keymap, "VIEW3D_OT_move");
+ /* assign map to operators */
+ WM_modalkeymap_assign(keymap, "VIEW3D_OT_move");
}
-
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;
- }
- 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);
- CLAMP(vod->rv3d->camdx, -1.0f, 1.0f);
- CLAMP(vod->rv3d->camdy, -1.0f, 1.0f);
- }
- else {
- float dvec[3];
- float mval_f[2];
+ 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;
+ }
+ 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);
+ CLAMP(vod->rv3d->camdx, -1.0f, 1.0f);
+ CLAMP(vod->rv3d->camdy, -1.0f, 1.0f);
+ }
+ else {
+ float dvec[3];
+ float mval_f[2];
- 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);
+ 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);
- add_v3_v3(vod->rv3d->ofs, dvec);
+ add_v3_v3(vod->rv3d->ofs, dvec);
- if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_sync(vod->sa, vod->ar);
- }
- }
+ if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
+ view3d_boxview_sync(vod->sa, vod->ar);
+ }
+ }
- vod->prev.event_xy[0] = x;
- vod->prev.event_xy[1] = y;
+ vod->prev.event_xy[0] = x;
+ vod->prev.event_xy[1] = y;
- ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
- ED_region_tag_redraw(vod->ar);
+ ED_region_tag_redraw(vod->ar);
}
-
static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewOpsData *vod = op->customdata;
- short event_code = VIEW_PASS;
- bool use_autokey = false;
- int ret = OPERATOR_RUNNING_MODAL;
-
- /* execute the events */
- if (event->type == MOUSEMOVE) {
- event_code = VIEW_APPLY;
- }
- else if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case VIEW_MODAL_CONFIRM:
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_SWITCH_ZOOM:
- WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_SWITCH_ROTATE:
- WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- }
- }
- else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
- event_code = VIEW_CONFIRM;
- }
-
- if (event_code == VIEW_APPLY) {
- viewmove_apply(vod, event->x, event->y);
- if (ED_screen_animation_playing(CTX_wm_manager(C))) {
- use_autokey = true;
- }
- }
- else if (event_code == VIEW_CONFIRM) {
- ED_view3d_depth_tag_update(vod->rv3d);
- use_autokey = true;
- ret = OPERATOR_FINISHED;
- }
-
- if (use_autokey) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
- }
-
- if (ret & OPERATOR_FINISHED) {
- viewops_data_free(C, op);
- }
-
- return ret;
+ ViewOpsData *vod = op->customdata;
+ short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
+
+ /* execute the events */
+ if (event->type == MOUSEMOVE) {
+ event_code = VIEW_APPLY;
+ }
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case VIEW_MODAL_CONFIRM:
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_ZOOM:
+ WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_ROTATE:
+ WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ }
+ }
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
+ event_code = VIEW_CONFIRM;
+ }
+
+ if (event_code == VIEW_APPLY) {
+ viewmove_apply(vod, event->x, event->y);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
+ }
+ else if (event_code == VIEW_CONFIRM) {
+ ED_view3d_depth_tag_update(vod->rv3d);
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
+
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
+ }
+
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op);
+ }
+
+ return ret;
}
static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewOpsData *vod;
+ ViewOpsData *vod;
- const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
- /* makes op->customdata */
- viewops_data_alloc(C, op);
- viewops_data_create(
- C, op, event,
- (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
- (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
- vod = op->customdata;
+ /* makes op->customdata */
+ viewops_data_alloc(C, op);
+ viewops_data_create(C,
+ op,
+ event,
+ (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
+ (use_mouse_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->ar);
- if (event->type == MOUSEPAN) {
- /* invert it, trackpad scroll follows same principle as 2d windows this way */
- viewmove_apply(vod, 2 * event->x - event->prevx, 2 * event->y - event->prevy);
- ED_view3d_depth_tag_update(vod->rv3d);
+ if (event->type == MOUSEPAN) {
+ /* invert it, trackpad scroll follows same principle as 2d windows this way */
+ viewmove_apply(vod, 2 * event->x - event->prevx, 2 * event->y - event->prevy);
+ ED_view3d_depth_tag_update(vod->rv3d);
- viewops_data_free(C, op);
+ viewops_data_free(C, op);
- return OPERATOR_FINISHED;
- }
- else {
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
- }
+ return OPERATOR_RUNNING_MODAL;
+ }
}
static void viewmove_cancel(bContext *C, wmOperator *op)
{
- viewops_data_free(C, op);
+ viewops_data_free(C, op);
}
void VIEW3D_OT_move(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Pan View";
- ot->description = "Move the view";
- ot->idname = "VIEW3D_OT_move";
+ /* identifiers */
+ ot->name = "Pan View";
+ ot->description = "Move the view";
+ ot->idname = "VIEW3D_OT_move";
- /* api callbacks */
- ot->invoke = viewmove_invoke;
- ot->modal = viewmove_modal;
- ot->poll = ED_operator_view3d_active;
- ot->cancel = viewmove_cancel;
+ /* api callbacks */
+ ot->invoke = viewmove_invoke;
+ ot->modal = viewmove_modal;
+ ot->poll = ED_operator_view3d_active;
+ ot->cancel = viewmove_cancel;
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
- /* properties */
- view3d_operator_properties_common(ot, V3D_OP_PROP_USE_MOUSE_INIT);
+ /* properties */
+ view3d_operator_properties_common(ot, V3D_OP_PROP_USE_MOUSE_INIT);
}
/** \} */
@@ -1811,82 +1813,81 @@ void VIEW3D_OT_move(wmOperatorType *ot)
/* called in transform_ops.c, on each regeneration of keymaps */
void viewzoom_modal_keymap(wmKeyConfig *keyconf)
{
- static const EnumPropertyItem modal_items[] = {
- {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+ static const EnumPropertyItem modal_items[] = {
+ {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
- {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
- {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
+ {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
+ {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
- {0, NULL, 0, NULL, NULL},
- };
+ {0, NULL, 0, NULL, NULL},
+ };
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Zoom Modal");
+ wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Zoom Modal");
- /* this function is called for each spacetype, only needs to add map once */
- if (keymap && keymap->modal_items) {
- return;
- }
+ /* 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_add(keyconf, "View3D Zoom Modal", modal_items);
- /* disabled mode switching for now, can re-implement better, later on */
+ /* disabled mode switching for now, can re-implement better, later on */
#if 0
- WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
- WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
- WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+ WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+ WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
#endif
- /* assign map to operators */
- WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom");
+ /* assign map to operators */
+ WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom");
}
/**
* \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])
+ Scene *scene, Depsgraph *depsgraph, View3D *v3d, ARegion *ar, float dfac, const int zoom_xy[2])
{
- RegionView3D *rv3d = ar->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);
- const float camzoom_new = BKE_screen_view3d_zoom_from_fac(zoomfac_new);
-
+ RegionView3D *rv3d = ar->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);
+ const float camzoom_new = BKE_screen_view3d_zoom_from_fac(zoomfac_new);
- if (zoom_xy != NULL) {
- float zoomfac_px;
- rctf camera_frame_old;
- rctf camera_frame_new;
+ if (zoom_xy != NULL) {
+ float zoomfac_px;
+ rctf camera_frame_old;
+ rctf camera_frame_new;
- const float pt_src[2] = {zoom_xy[0], zoom_xy[1]};
- float pt_dst[2];
- float delta_px[2];
+ const float pt_src[2] = {zoom_xy[0], zoom_xy[1]};
+ 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, ar, v3d, rv3d, &camera_frame_old, false);
+ BLI_rctf_translate(&camera_frame_old, ar->winrct.xmin, ar->winrct.ymin);
- rv3d->camzoom = camzoom_new;
- CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
+ 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, ar, v3d, rv3d, &camera_frame_new, false);
+ BLI_rctf_translate(&camera_frame_new, ar->winrct.xmin, ar->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);
+ BLI_rctf_transform_pt_v(&camera_frame_new, &camera_frame_old, pt_dst, pt_src);
+ sub_v2_v2v2(delta_px, pt_dst, pt_src);
- /* translate the camera offset using pixel space delta
- * mapped back to the camera (same logic as panning in camera view) */
- zoomfac_px = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 2.0f;
+ /* translate the camera offset using pixel space delta
+ * 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);
- CLAMP(rv3d->camdx, -1.0f, 1.0f);
- CLAMP(rv3d->camdy, -1.0f, 1.0f);
- }
- else {
- rv3d->camzoom = camzoom_new;
- CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
- }
+ rv3d->camdx += delta_px[0] / (ar->winx * zoomfac_px);
+ rv3d->camdy += delta_px[1] / (ar->winy * zoomfac_px);
+ CLAMP(rv3d->camdx, -1.0f, 1.0f);
+ CLAMP(rv3d->camdy, -1.0f, 1.0f);
+ }
+ else {
+ rv3d->camzoom = camzoom_new;
+ CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
+ }
}
/**
@@ -1894,441 +1895,472 @@ static void view_zoom_to_window_xy_camera(
*/
static void view_zoom_to_window_xy_3d(ARegion *ar, float dfac, const int zoom_xy[2])
{
- RegionView3D *rv3d = ar->regiondata;
- const float dist_new = rv3d->dist * dfac;
-
- if (zoom_xy != NULL) {
- float dvec[3];
- float tvec[3];
- float tpos[3];
- float mval_f[2];
-
- float zfac;
-
- 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;
-
- /* Project cursor position into 3D space */
- zfac = ED_view3d_calc_zfac(rv3d, tpos, NULL);
- ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
-
- /* Calculate view target position for dolly */
- add_v3_v3v3(tvec, tpos, dvec);
- negate_v3(tvec);
-
- /* Offset to target position and dolly */
- copy_v3_v3(rv3d->ofs, tvec);
- rv3d->dist = dist_new;
-
- /* Calculate final offset */
- madd_v3_v3v3fl(rv3d->ofs, tvec, dvec, dfac);
- }
- else {
- rv3d->dist = dist_new;
- }
-}
-
-static float viewzoom_scale_value(
- const rcti *winrct,
- const short viewzoom,
- const bool zoom_invert, const bool zoom_invert_force,
- const int xy_curr[2], const int xy_init[2],
- const float val, const float val_orig,
- double *r_timer_lastdraw)
-{
- float zfac;
-
- if (viewzoom == USER_ZOOM_CONT) {
- double time = PIL_check_seconds_timer();
- float time_step = (float)(time - *r_timer_lastdraw);
- float fac;
-
- if (U.uiflag & USER_ZOOM_HORIZ) {
- fac = (float)(xy_init[0] - xy_curr[0]);
- }
- else {
- fac = (float)(xy_init[1] - xy_curr[1]);
- }
-
- if (zoom_invert != zoom_invert_force) {
- fac = -fac;
- }
-
- /* oldstyle zoom */
- zfac = 1.0f + ((fac / 20.0f) * time_step);
- *r_timer_lastdraw = time;
- }
- else if (viewzoom == USER_ZOOM_SCALE) {
- /* method which zooms based on how far you move the mouse */
-
- const int ctr[2] = {
- BLI_rcti_cent_x(winrct),
- BLI_rcti_cent_y(winrct),
- };
- float len_new = 5 + len_v2v2_int(ctr, xy_curr);
- float len_old = 5 + len_v2v2_int(ctr, xy_init);
-
- /* intentionally ignore 'zoom_invert' for scale */
- if (zoom_invert_force) {
- SWAP(float, len_new, len_old);
- }
-
- zfac = val_orig * (len_old / max_ff(len_new, 1.0f)) / val;
- }
- else { /* USER_ZOOM_DOLLY */
- float len_new = 5;
- float len_old = 5;
-
- if (U.uiflag & USER_ZOOM_HORIZ) {
- len_new += (winrct->xmax - (xy_curr[0]));
- len_old += (winrct->xmax - (xy_init[0]));
- }
- else {
- len_new += (winrct->ymax - (xy_curr[1]));
- len_old += (winrct->ymax - (xy_init[1]));
- }
-
- if (zoom_invert != zoom_invert_force) {
- SWAP(float, len_new, len_old);
- }
-
- zfac = val_orig * (2.0f * ((len_new / max_ff(len_old, 1.0f)) - 1.0f) + 1.0f) / val;
- }
-
-
- return zfac;
-}
-
-static float viewzoom_scale_value_offset(
- const rcti *winrct,
- const short viewzoom,
- const bool zoom_invert, const bool zoom_invert_force,
- const int xy_curr[2], const int xy_init[2], const int xy_offset[2],
- const float val, const float val_orig,
- double *r_timer_lastdraw)
-{
- const int xy_curr_offset[2] = {
- xy_curr[0] + xy_offset[0],
- xy_curr[1] + xy_offset[1],
- };
- const int xy_init_offset[2] = {
- xy_init[0] + xy_offset[0],
- xy_init[1] + xy_offset[1],
- };
- return viewzoom_scale_value(
- winrct, viewzoom, zoom_invert, zoom_invert_force,
- xy_curr_offset, xy_init_offset,
- val, val_orig, r_timer_lastdraw);
-}
-
-static void viewzoom_apply_camera(
- ViewOpsData *vod, const int xy[2],
- const short viewzoom, const bool zoom_invert, const bool zoom_to_pos)
-{
- float zfac;
- 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, viewzoom, zoom_invert, true,
- xy, vod->init.event_xy, vod->init.event_xy_offset,
- zoomfac, zoomfac_prev,
- &vod->prev.time);
-
- if (zfac != 1.0f && zfac != 0.0f) {
- /* calculate inverted, then invert again (needed because of camera zoom scaling) */
- zfac = 1.0f / zfac;
- view_zoom_to_window_xy_camera(
- vod->scene, vod->depsgraph, vod->v3d,
- vod->ar, zfac, zoom_to_pos ? vod->prev.event_xy : NULL);
- }
-
- ED_region_tag_redraw(vod->ar);
-}
-
-static void viewzoom_apply_3d(
- ViewOpsData *vod, const int xy[2],
- const short viewzoom, const bool zoom_invert, const bool zoom_to_pos)
-{
- float zfac;
- float dist_range[2];
-
- ED_view3d_dist_range_get(vod->v3d, dist_range);
-
- zfac = viewzoom_scale_value_offset(
- &vod->ar->winrct, viewzoom, zoom_invert, false,
- xy, vod->init.event_xy, vod->init.event_xy_offset,
- vod->rv3d->dist, vod->init.dist,
- &vod->prev.time);
-
- if (zfac != 1.0f) {
- const float zfac_min = dist_range[0] / vod->rv3d->dist;
- 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);
- }
-
- /* 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);
- }
-
- ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
-
- ED_region_tag_redraw(vod->ar);
-}
-
-static void viewzoom_apply(
- ViewOpsData *vod, const int xy[2],
- const short viewzoom, const bool zoom_invert, const bool zoom_to_pos)
-{
- if ((vod->rv3d->persp == RV3D_CAMOB) &&
- (vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) == 0)
- {
- viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert, zoom_to_pos);
- }
- else {
- viewzoom_apply_3d(vod, xy, viewzoom, zoom_invert, zoom_to_pos);
- }
+ RegionView3D *rv3d = ar->regiondata;
+ const float dist_new = rv3d->dist * dfac;
+
+ if (zoom_xy != NULL) {
+ float dvec[3];
+ float tvec[3];
+ float tpos[3];
+ float mval_f[2];
+
+ float zfac;
+
+ 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;
+
+ /* Project cursor position into 3D space */
+ zfac = ED_view3d_calc_zfac(rv3d, tpos, NULL);
+ ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
+
+ /* Calculate view target position for dolly */
+ add_v3_v3v3(tvec, tpos, dvec);
+ negate_v3(tvec);
+
+ /* Offset to target position and dolly */
+ copy_v3_v3(rv3d->ofs, tvec);
+ rv3d->dist = dist_new;
+
+ /* Calculate final offset */
+ madd_v3_v3v3fl(rv3d->ofs, tvec, dvec, dfac);
+ }
+ else {
+ rv3d->dist = dist_new;
+ }
+}
+
+static float viewzoom_scale_value(const rcti *winrct,
+ const short viewzoom,
+ const bool zoom_invert,
+ const bool zoom_invert_force,
+ const int xy_curr[2],
+ const int xy_init[2],
+ const float val,
+ const float val_orig,
+ double *r_timer_lastdraw)
+{
+ float zfac;
+
+ if (viewzoom == USER_ZOOM_CONT) {
+ double time = PIL_check_seconds_timer();
+ float time_step = (float)(time - *r_timer_lastdraw);
+ float fac;
+
+ if (U.uiflag & USER_ZOOM_HORIZ) {
+ fac = (float)(xy_init[0] - xy_curr[0]);
+ }
+ else {
+ fac = (float)(xy_init[1] - xy_curr[1]);
+ }
+
+ if (zoom_invert != zoom_invert_force) {
+ fac = -fac;
+ }
+
+ /* oldstyle zoom */
+ zfac = 1.0f + ((fac / 20.0f) * time_step);
+ *r_timer_lastdraw = time;
+ }
+ else if (viewzoom == USER_ZOOM_SCALE) {
+ /* method which zooms based on how far you move the mouse */
+
+ const int ctr[2] = {
+ BLI_rcti_cent_x(winrct),
+ BLI_rcti_cent_y(winrct),
+ };
+ float len_new = 5 + len_v2v2_int(ctr, xy_curr);
+ float len_old = 5 + len_v2v2_int(ctr, xy_init);
+
+ /* intentionally ignore 'zoom_invert' for scale */
+ if (zoom_invert_force) {
+ SWAP(float, len_new, len_old);
+ }
+
+ zfac = val_orig * (len_old / max_ff(len_new, 1.0f)) / val;
+ }
+ else { /* USER_ZOOM_DOLLY */
+ float len_new = 5;
+ float len_old = 5;
+
+ if (U.uiflag & USER_ZOOM_HORIZ) {
+ len_new += (winrct->xmax - (xy_curr[0]));
+ len_old += (winrct->xmax - (xy_init[0]));
+ }
+ else {
+ len_new += (winrct->ymax - (xy_curr[1]));
+ len_old += (winrct->ymax - (xy_init[1]));
+ }
+
+ if (zoom_invert != zoom_invert_force) {
+ SWAP(float, len_new, len_old);
+ }
+
+ zfac = val_orig * (2.0f * ((len_new / max_ff(len_old, 1.0f)) - 1.0f) + 1.0f) / val;
+ }
+
+ return zfac;
+}
+
+static float viewzoom_scale_value_offset(const rcti *winrct,
+ const short viewzoom,
+ const bool zoom_invert,
+ const bool zoom_invert_force,
+ const int xy_curr[2],
+ const int xy_init[2],
+ const int xy_offset[2],
+ const float val,
+ const float val_orig,
+ double *r_timer_lastdraw)
+{
+ const int xy_curr_offset[2] = {
+ xy_curr[0] + xy_offset[0],
+ xy_curr[1] + xy_offset[1],
+ };
+ const int xy_init_offset[2] = {
+ xy_init[0] + xy_offset[0],
+ xy_init[1] + xy_offset[1],
+ };
+ return viewzoom_scale_value(winrct,
+ viewzoom,
+ zoom_invert,
+ zoom_invert_force,
+ xy_curr_offset,
+ xy_init_offset,
+ val,
+ val_orig,
+ r_timer_lastdraw);
+}
+
+static void viewzoom_apply_camera(ViewOpsData *vod,
+ const int xy[2],
+ const short viewzoom,
+ const bool zoom_invert,
+ const bool zoom_to_pos)
+{
+ float zfac;
+ 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,
+ viewzoom,
+ zoom_invert,
+ true,
+ xy,
+ vod->init.event_xy,
+ vod->init.event_xy_offset,
+ zoomfac,
+ zoomfac_prev,
+ &vod->prev.time);
+
+ if (zfac != 1.0f && zfac != 0.0f) {
+ /* calculate inverted, then invert again (needed because of camera zoom scaling) */
+ zfac = 1.0f / zfac;
+ view_zoom_to_window_xy_camera(vod->scene,
+ vod->depsgraph,
+ vod->v3d,
+ vod->ar,
+ zfac,
+ zoom_to_pos ? vod->prev.event_xy : NULL);
+ }
+
+ ED_region_tag_redraw(vod->ar);
+}
+
+static void viewzoom_apply_3d(ViewOpsData *vod,
+ const int xy[2],
+ const short viewzoom,
+ const bool zoom_invert,
+ const bool zoom_to_pos)
+{
+ float zfac;
+ float dist_range[2];
+
+ ED_view3d_dist_range_get(vod->v3d, dist_range);
+
+ zfac = viewzoom_scale_value_offset(&vod->ar->winrct,
+ viewzoom,
+ zoom_invert,
+ false,
+ xy,
+ vod->init.event_xy,
+ vod->init.event_xy_offset,
+ vod->rv3d->dist,
+ vod->init.dist,
+ &vod->prev.time);
+
+ if (zfac != 1.0f) {
+ const float zfac_min = dist_range[0] / vod->rv3d->dist;
+ 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);
+ }
+
+ /* 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);
+ }
+
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
+
+ ED_region_tag_redraw(vod->ar);
+}
+
+static void viewzoom_apply(ViewOpsData *vod,
+ const int xy[2],
+ const short viewzoom,
+ const bool zoom_invert,
+ const bool zoom_to_pos)
+{
+ if ((vod->rv3d->persp == RV3D_CAMOB) &&
+ (vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) == 0) {
+ viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert, zoom_to_pos);
+ }
+ else {
+ viewzoom_apply_3d(vod, xy, viewzoom, zoom_invert, zoom_to_pos);
+ }
}
static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewOpsData *vod = op->customdata;
- short event_code = VIEW_PASS;
- bool use_autokey = false;
- int ret = OPERATOR_RUNNING_MODAL;
-
- /* execute the events */
- if (event->type == TIMER && event->customdata == vod->timer) {
- /* continuous zoom */
- event_code = VIEW_APPLY;
- }
- else if (event->type == MOUSEMOVE) {
- event_code = VIEW_APPLY;
- }
- else if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case VIEW_MODAL_CONFIRM:
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_SWITCH_MOVE:
- WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_SWITCH_ROTATE:
- WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- }
- }
- else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
- event_code = VIEW_CONFIRM;
- }
-
- if (event_code == VIEW_APPLY) {
- const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
- viewzoom_apply(
- vod, &event->x, U.viewzoom,
- (U.uiflag & USER_ZOOM_INVERT) != 0,
- (use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
- if (ED_screen_animation_playing(CTX_wm_manager(C))) {
- use_autokey = true;
- }
- }
- else if (event_code == VIEW_CONFIRM) {
- ED_view3d_depth_tag_update(vod->rv3d);
- use_autokey = true;
- ret = OPERATOR_FINISHED;
- }
-
- if (use_autokey) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
- }
-
- if (ret & OPERATOR_FINISHED) {
- viewops_data_free(C, op);
- }
-
- return ret;
+ ViewOpsData *vod = op->customdata;
+ short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
+
+ /* execute the events */
+ if (event->type == TIMER && event->customdata == vod->timer) {
+ /* continuous zoom */
+ event_code = VIEW_APPLY;
+ }
+ else if (event->type == MOUSEMOVE) {
+ event_code = VIEW_APPLY;
+ }
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case VIEW_MODAL_CONFIRM:
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_MOVE:
+ WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_ROTATE:
+ WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ }
+ }
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
+ event_code = VIEW_CONFIRM;
+ }
+
+ if (event_code == VIEW_APPLY) {
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+ viewzoom_apply(vod,
+ &event->x,
+ U.viewzoom,
+ (U.uiflag & USER_ZOOM_INVERT) != 0,
+ (use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
+ }
+ else if (event_code == VIEW_CONFIRM) {
+ ED_view3d_depth_tag_update(vod->rv3d);
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
+
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
+ }
+
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op);
+ }
+
+ return ret;
}
static int viewzoom_exec(bContext *C, wmOperator *op)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- View3D *v3d;
- RegionView3D *rv3d;
- ScrArea *sa;
- ARegion *ar;
- bool use_cam_zoom;
- float dist_range[2];
-
- const int delta = RNA_int_get(op->ptr, "delta");
- const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
-
- if (op->customdata) {
- ViewOpsData *vod = op->customdata;
-
- sa = vod->sa;
- ar = vod->ar;
- }
- else {
- sa = CTX_wm_area(C);
- ar = CTX_wm_region(C);
- }
-
- v3d = sa->spacedata.first;
- rv3d = ar->regiondata;
-
-
- use_cam_zoom = (rv3d->persp == RV3D_CAMOB) && !(rv3d->is_persp && ED_view3d_camera_lock_check(v3d, rv3d));
-
- int zoom_xy_buf[2];
- const int *zoom_xy = NULL;
- if (use_mouse_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;
- zoom_xy_buf[1] = RNA_struct_property_is_set(op->ptr, "my") ? RNA_int_get(op->ptr, "my") : ar->winy / 2;
- zoom_xy = zoom_xy_buf;
- }
-
- ED_view3d_dist_range_get(v3d, dist_range);
-
- if (delta < 0) {
- 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);
- }
- else {
- if (rv3d->dist < dist_range[1]) {
- view_zoom_to_window_xy_3d(ar, 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);
- }
- else {
- if (rv3d->dist > dist_range[0]) {
- view_zoom_to_window_xy_3d(ar, step, zoom_xy);
- }
- }
- }
-
- if (rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_sync(sa, ar);
- }
-
- ED_view3d_depth_tag_update(rv3d);
-
- ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
- ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true);
-
- ED_region_tag_redraw(ar);
-
- viewops_data_free(C, op);
-
- return OPERATOR_FINISHED;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d;
+ RegionView3D *rv3d;
+ ScrArea *sa;
+ ARegion *ar;
+ bool use_cam_zoom;
+ float dist_range[2];
+
+ const int delta = RNA_int_get(op->ptr, "delta");
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+
+ if (op->customdata) {
+ ViewOpsData *vod = op->customdata;
+
+ sa = vod->sa;
+ ar = vod->ar;
+ }
+ else {
+ sa = CTX_wm_area(C);
+ ar = CTX_wm_region(C);
+ }
+
+ v3d = sa->spacedata.first;
+ rv3d = ar->regiondata;
+
+ use_cam_zoom = (rv3d->persp == RV3D_CAMOB) &&
+ !(rv3d->is_persp && ED_view3d_camera_lock_check(v3d, rv3d));
+
+ int zoom_xy_buf[2];
+ const int *zoom_xy = NULL;
+ if (use_mouse_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;
+ zoom_xy_buf[1] = RNA_struct_property_is_set(op->ptr, "my") ? RNA_int_get(op->ptr, "my") :
+ ar->winy / 2;
+ zoom_xy = zoom_xy_buf;
+ }
+
+ ED_view3d_dist_range_get(v3d, dist_range);
+
+ if (delta < 0) {
+ 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);
+ }
+ else {
+ if (rv3d->dist < dist_range[1]) {
+ view_zoom_to_window_xy_3d(ar, 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);
+ }
+ else {
+ if (rv3d->dist > dist_range[0]) {
+ view_zoom_to_window_xy_3d(ar, step, zoom_xy);
+ }
+ }
+ }
+
+ if (rv3d->viewlock & RV3D_BOXVIEW) {
+ view3d_boxview_sync(sa, ar);
+ }
+
+ ED_view3d_depth_tag_update(rv3d);
+
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
+ ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true);
+
+ ED_region_tag_redraw(ar);
+
+ viewops_data_free(C, op);
+
+ return OPERATOR_FINISHED;
}
/* viewdolly_invoke() copied this function, changes here may apply there */
static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewOpsData *vod;
-
- const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
-
- /* makes op->customdata */
- viewops_data_alloc(C, op);
- viewops_data_create(
- C, op, event,
- (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
- (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
- vod = op->customdata;
-
- ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
-
- /* 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")) {
- RNA_int_set(op->ptr, "mx", event->x);
- RNA_int_set(op->ptr, "my", event->y);
- }
-
- if (RNA_struct_property_is_set(op->ptr, "delta")) {
- viewzoom_exec(C, op);
- }
- else {
- if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
-
- if (U.uiflag & USER_ZOOM_HORIZ) {
- vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x;
- }
- else {
- /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
- vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->x - event->prevx;
- }
- viewzoom_apply(
- vod, &event->prevx, USER_ZOOM_DOLLY,
- (U.uiflag & USER_ZOOM_INVERT) != 0,
- (use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
-
- ED_view3d_depth_tag_update(vod->rv3d);
-
- viewops_data_free(C, op);
- return OPERATOR_FINISHED;
- }
- else {
- if (U.viewzoom == USER_ZOOM_CONT) {
- /* needs a timer to continue redrawing */
- vod->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
- vod->prev.time = PIL_check_seconds_timer();
- }
-
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
- }
- }
- return OPERATOR_FINISHED;
+ ViewOpsData *vod;
+
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+
+ /* makes op->customdata */
+ viewops_data_alloc(C, op);
+ viewops_data_create(C,
+ op,
+ event,
+ (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
+ (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
+ vod = op->customdata;
+
+ ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
+
+ /* 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")) {
+ RNA_int_set(op->ptr, "mx", event->x);
+ RNA_int_set(op->ptr, "my", event->y);
+ }
+
+ if (RNA_struct_property_is_set(op->ptr, "delta")) {
+ viewzoom_exec(C, op);
+ }
+ else {
+ if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
+
+ if (U.uiflag & USER_ZOOM_HORIZ) {
+ vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x;
+ }
+ else {
+ /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
+ vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->x -
+ event->prevx;
+ }
+ viewzoom_apply(vod,
+ &event->prevx,
+ USER_ZOOM_DOLLY,
+ (U.uiflag & USER_ZOOM_INVERT) != 0,
+ (use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
+
+ ED_view3d_depth_tag_update(vod->rv3d);
+
+ viewops_data_free(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ if (U.viewzoom == USER_ZOOM_CONT) {
+ /* needs a timer to continue redrawing */
+ vod->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
+ vod->prev.time = PIL_check_seconds_timer();
+ }
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+ return OPERATOR_FINISHED;
}
static void viewzoom_cancel(bContext *C, wmOperator *op)
{
- viewops_data_free(C, op);
+ viewops_data_free(C, op);
}
void VIEW3D_OT_zoom(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Zoom View";
- ot->description = "Zoom in/out in the view";
- ot->idname = "VIEW3D_OT_zoom";
+ /* identifiers */
+ ot->name = "Zoom View";
+ ot->description = "Zoom in/out in the view";
+ ot->idname = "VIEW3D_OT_zoom";
- /* api callbacks */
- ot->invoke = viewzoom_invoke;
- ot->exec = viewzoom_exec;
- ot->modal = viewzoom_modal;
- ot->poll = ED_operator_region_view3d_active;
- ot->cancel = viewzoom_cancel;
+ /* api callbacks */
+ ot->invoke = viewzoom_invoke;
+ ot->exec = viewzoom_exec;
+ ot->modal = viewzoom_modal;
+ ot->poll = ED_operator_region_view3d_active;
+ ot->cancel = viewzoom_cancel;
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
- /* properties */
- view3d_operator_properties_common(
- ot,
- V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT);
+ /* properties */
+ view3d_operator_properties_common(
+ ot, V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT);
}
/** \} */
@@ -2344,304 +2376,304 @@ void VIEW3D_OT_zoom(wmOperatorType *ot)
/* called in transform_ops.c, on each regeneration of keymaps */
void viewdolly_modal_keymap(wmKeyConfig *keyconf)
{
- static const EnumPropertyItem modal_items[] = {
- {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+ static const EnumPropertyItem modal_items[] = {
+ {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
- {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
- {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
+ {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
+ {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
- {0, NULL, 0, NULL, NULL},
- };
+ {0, NULL, 0, NULL, NULL},
+ };
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Dolly Modal");
+ wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Dolly Modal");
- /* this function is called for each spacetype, only needs to add map once */
- if (keymap && keymap->modal_items) {
- return;
- }
+ /* 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_add(keyconf, "View3D Dolly Modal", modal_items);
- /* disabled mode switching for now, can re-implement better, later on */
+ /* disabled mode switching for now, can re-implement better, later on */
#if 0
- WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
- WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
- WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+ WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+ WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
#endif
- /* assign map to operators */
- WM_modalkeymap_assign(keymap, "VIEW3D_OT_dolly");
+ /* assign map to operators */
+ WM_modalkeymap_assign(keymap, "VIEW3D_OT_dolly");
}
static bool viewdolly_offset_lock_check(bContext *C, wmOperator *op)
{
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- if (ED_view3d_offset_lock_check(v3d, rv3d)) {
- BKE_report(op->reports, RPT_WARNING, "Cannot dolly when the view offset is locked");
- return true;
- }
- else {
- return false;
- }
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if (ED_view3d_offset_lock_check(v3d, rv3d)) {
+ BKE_report(op->reports, RPT_WARNING, "Cannot dolly when the view offset is locked");
+ return true;
+ }
+ else {
+ return false;
+ }
}
static void view_dolly_to_vector_3d(ARegion *ar, float orig_ofs[3], float dvec[3], float dfac)
{
- RegionView3D *rv3d = ar->regiondata;
- madd_v3_v3v3fl(rv3d->ofs, orig_ofs, dvec, -(1.0f - dfac));
+ RegionView3D *rv3d = ar->regiondata;
+ madd_v3_v3v3fl(rv3d->ofs, orig_ofs, dvec, -(1.0f - dfac));
}
static void viewdolly_apply(ViewOpsData *vod, const int xy[2], const short zoom_invert)
{
- float zfac = 1.0;
+ float zfac = 1.0;
- {
- float len1, len2;
+ {
+ 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;
- }
- else {
- len1 = (vod->ar->winrct.ymax - xy[1]) + 5;
- len2 = (vod->ar->winrct.ymax - vod->init.event_xy[1]) + 5;
- }
- if (zoom_invert) {
- SWAP(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;
+ }
+ else {
+ len1 = (vod->ar->winrct.ymax - xy[1]) + 5;
+ len2 = (vod->ar->winrct.ymax - vod->init.event_xy[1]) + 5;
+ }
+ if (zoom_invert) {
+ SWAP(float, len1, len2);
+ }
- zfac = 1.0f + ((len1 - len2) * 0.01f * vod->rv3d->dist);
- }
+ zfac = 1.0f + ((len1 - len2) * 0.01f * vod->rv3d->dist);
+ }
- if (zfac != 1.0f) {
- view_dolly_to_vector_3d(vod->ar, vod->init.ofs, vod->init.mousevec, zfac);
- }
+ if (zfac != 1.0f) {
+ view_dolly_to_vector_3d(vod->ar, vod->init.ofs, vod->init.mousevec, zfac);
+ }
- if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_sync(vod->sa, vod->ar);
- }
+ if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
+ view3d_boxview_sync(vod->sa, vod->ar);
+ }
- ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
- ED_region_tag_redraw(vod->ar);
+ ED_region_tag_redraw(vod->ar);
}
-
static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewOpsData *vod = op->customdata;
- short event_code = VIEW_PASS;
- bool use_autokey = false;
- int ret = OPERATOR_RUNNING_MODAL;
-
- /* execute the events */
- if (event->type == MOUSEMOVE) {
- event_code = VIEW_APPLY;
- }
- else if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case VIEW_MODAL_CONFIRM:
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_SWITCH_MOVE:
- WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_SWITCH_ROTATE:
- WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- }
- }
- else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
- event_code = VIEW_CONFIRM;
- }
-
- if (event_code == VIEW_APPLY) {
- viewdolly_apply(vod, &event->x, (U.uiflag & USER_ZOOM_INVERT) != 0);
- if (ED_screen_animation_playing(CTX_wm_manager(C))) {
- use_autokey = true;
- }
- }
- else if (event_code == VIEW_CONFIRM) {
- ED_view3d_depth_tag_update(vod->rv3d);
- use_autokey = true;
- ret = OPERATOR_FINISHED;
- }
-
- if (use_autokey) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
- }
-
- if (ret & OPERATOR_FINISHED) {
- viewops_data_free(C, op);
- }
-
- return ret;
+ ViewOpsData *vod = op->customdata;
+ short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
+
+ /* execute the events */
+ if (event->type == MOUSEMOVE) {
+ event_code = VIEW_APPLY;
+ }
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case VIEW_MODAL_CONFIRM:
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_MOVE:
+ WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_ROTATE:
+ WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ }
+ }
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
+ event_code = VIEW_CONFIRM;
+ }
+
+ if (event_code == VIEW_APPLY) {
+ viewdolly_apply(vod, &event->x, (U.uiflag & USER_ZOOM_INVERT) != 0);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
+ }
+ else if (event_code == VIEW_CONFIRM) {
+ ED_view3d_depth_tag_update(vod->rv3d);
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
+
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
+ }
+
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op);
+ }
+
+ return ret;
}
static int viewdolly_exec(bContext *C, wmOperator *op)
{
- View3D *v3d;
- RegionView3D *rv3d;
- ScrArea *sa;
- ARegion *ar;
- float mousevec[3];
+ View3D *v3d;
+ RegionView3D *rv3d;
+ ScrArea *sa;
+ ARegion *ar;
+ float mousevec[3];
- const int delta = RNA_int_get(op->ptr, "delta");
+ const int delta = RNA_int_get(op->ptr, "delta");
- if (op->customdata) {
- ViewOpsData *vod = op->customdata;
+ if (op->customdata) {
+ ViewOpsData *vod = op->customdata;
- sa = vod->sa;
- ar = vod->ar;
- 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]);
- normalize_v3(mousevec);
- }
+ sa = vod->sa;
+ ar = vod->ar;
+ 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]);
+ normalize_v3(mousevec);
+ }
- v3d = sa->spacedata.first;
- rv3d = ar->regiondata;
+ v3d = sa->spacedata.first;
+ rv3d = ar->regiondata;
- const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
- /* overwrite the mouse vector with the view direction (zoom into the center) */
- if ((use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) {
- normalize_v3_v3(mousevec, rv3d->viewinv[2]);
- }
+ /* overwrite the mouse vector with the view direction (zoom into the center) */
+ if ((use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) {
+ 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(ar, rv3d->ofs, mousevec, delta < 0 ? 0.2f : 1.8f);
- if (rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_sync(sa, ar);
- }
+ if (rv3d->viewlock & RV3D_BOXVIEW) {
+ view3d_boxview_sync(sa, ar);
+ }
- ED_view3d_depth_tag_update(rv3d);
+ ED_view3d_depth_tag_update(rv3d);
- ED_view3d_camera_lock_sync(CTX_data_depsgraph(C), v3d, rv3d);
+ ED_view3d_camera_lock_sync(CTX_data_depsgraph(C), v3d, rv3d);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- viewops_data_free(C, op);
+ viewops_data_free(C, op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* copied from viewzoom_invoke(), changes here may apply there */
static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewOpsData *vod;
-
- if (viewdolly_offset_lock_check(C, op)) {
- return OPERATOR_CANCELLED;
- }
-
- /* makes op->customdata */
- viewops_data_alloc(C, op);
- vod = op->customdata;
-
- /* poll should check but in some cases fails, see poll func for details */
- if (vod->rv3d->viewlock & RV3D_LOCKED) {
- viewops_data_free(C, op);
- return OPERATOR_PASS_THROUGH;
- }
-
- ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
-
- /* needs to run before 'viewops_data_create' so the backup 'rv3d->ofs' is correct */
- /* switch from camera view when: */
- if (vod->rv3d->persp != RV3D_PERSP) {
- if (vod->rv3d->persp == RV3D_CAMOB) {
- /* ignore rv3d->lpersp because dolly only makes sense in perspective mode */
- const Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ED_view3d_persp_switch_from_camera(depsgraph, vod->v3d, vod->rv3d, RV3D_PERSP);
- }
- else {
- vod->rv3d->persp = RV3D_PERSP;
- }
- ED_region_tag_redraw(vod->ar);
- }
-
- const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
-
- viewops_data_create(
- C, op, event,
- (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
- (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
-
-
- /* 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")) {
- RNA_int_set(op->ptr, "mx", event->x);
- RNA_int_set(op->ptr, "my", event->y);
- }
-
- if (RNA_struct_property_is_set(op->ptr, "delta")) {
- viewdolly_exec(C, op);
- }
- else {
- /* overwrite the mouse vector with the view direction (zoom into the center) */
- if ((use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) {
- negate_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]);
- normalize_v3(vod->init.mousevec);
- }
-
- if (event->type == MOUSEZOOM) {
- /* Bypass Zoom invert flag for track pads (pass false always) */
-
- if (U.uiflag & USER_ZOOM_HORIZ) {
- vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x;
- }
- else {
- /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
- vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->x - event->prevx;
- }
- viewdolly_apply(vod, &event->prevx, (U.uiflag & USER_ZOOM_INVERT) == 0);
- ED_view3d_depth_tag_update(vod->rv3d);
-
- viewops_data_free(C, op);
- return OPERATOR_FINISHED;
- }
- else {
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
- }
- }
- return OPERATOR_FINISHED;
+ ViewOpsData *vod;
+
+ if (viewdolly_offset_lock_check(C, op)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* makes op->customdata */
+ viewops_data_alloc(C, op);
+ vod = op->customdata;
+
+ /* poll should check but in some cases fails, see poll func for details */
+ if (vod->rv3d->viewlock & RV3D_LOCKED) {
+ viewops_data_free(C, op);
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
+
+ /* needs to run before 'viewops_data_create' so the backup 'rv3d->ofs' is correct */
+ /* switch from camera view when: */
+ if (vod->rv3d->persp != RV3D_PERSP) {
+ if (vod->rv3d->persp == RV3D_CAMOB) {
+ /* ignore rv3d->lpersp because dolly only makes sense in perspective mode */
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ED_view3d_persp_switch_from_camera(depsgraph, vod->v3d, vod->rv3d, RV3D_PERSP);
+ }
+ else {
+ vod->rv3d->persp = RV3D_PERSP;
+ }
+ ED_region_tag_redraw(vod->ar);
+ }
+
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+
+ viewops_data_create(C,
+ op,
+ event,
+ (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
+ (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
+
+ /* 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")) {
+ RNA_int_set(op->ptr, "mx", event->x);
+ RNA_int_set(op->ptr, "my", event->y);
+ }
+
+ if (RNA_struct_property_is_set(op->ptr, "delta")) {
+ viewdolly_exec(C, op);
+ }
+ else {
+ /* overwrite the mouse vector with the view direction (zoom into the center) */
+ if ((use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) {
+ negate_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]);
+ normalize_v3(vod->init.mousevec);
+ }
+
+ if (event->type == MOUSEZOOM) {
+ /* Bypass Zoom invert flag for track pads (pass false always) */
+
+ if (U.uiflag & USER_ZOOM_HORIZ) {
+ vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x;
+ }
+ else {
+ /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
+ vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->x -
+ event->prevx;
+ }
+ viewdolly_apply(vod, &event->prevx, (U.uiflag & USER_ZOOM_INVERT) == 0);
+ ED_view3d_depth_tag_update(vod->rv3d);
+
+ viewops_data_free(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+ return OPERATOR_FINISHED;
}
static void viewdolly_cancel(bContext *C, wmOperator *op)
{
- viewops_data_free(C, op);
+ viewops_data_free(C, op);
}
void VIEW3D_OT_dolly(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Dolly View";
- ot->description = "Dolly in/out in the view";
- ot->idname = "VIEW3D_OT_dolly";
+ /* identifiers */
+ ot->name = "Dolly View";
+ ot->description = "Dolly in/out in the view";
+ ot->idname = "VIEW3D_OT_dolly";
- /* api callbacks */
- ot->invoke = viewdolly_invoke;
- ot->exec = viewdolly_exec;
- ot->modal = viewdolly_modal;
- ot->poll = ED_operator_region_view3d_active;
- ot->cancel = viewdolly_cancel;
+ /* api callbacks */
+ ot->invoke = viewdolly_invoke;
+ ot->exec = viewdolly_exec;
+ ot->modal = viewdolly_modal;
+ ot->poll = ED_operator_region_view3d_active;
+ ot->cancel = viewdolly_cancel;
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
- /* properties */
- view3d_operator_properties_common(
- ot, V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT);
+ /* properties */
+ view3d_operator_properties_common(
+ ot, V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT);
}
/** \} */
@@ -2652,215 +2684,228 @@ void VIEW3D_OT_dolly(wmOperatorType *ot)
* Move & Zoom the view to fit all of it's contents.
* \{ */
-static bool view3d_object_skip_minmax(
- const View3D *v3d, const RegionView3D *rv3d, const Object *ob, const bool skip_camera,
- bool *r_only_center)
-{
- BLI_assert(ob->id.orig_id == NULL);
- *r_only_center = false;
-
- if (skip_camera && (ob == v3d->camera)) {
- return true;
- }
-
- if ((ob->type == OB_EMPTY) &&
- (ob->empty_drawtype == OB_EMPTY_IMAGE) &&
- !BKE_object_empty_image_frame_is_visible_in_view3d(ob, rv3d))
- {
- *r_only_center = true;
- return false;
- }
-
- return false;
-}
-
-static void view3d_from_minmax(
- bContext *C, View3D *v3d, ARegion *ar,
- const float min[3], const float max[3],
- bool ok_dist, const int smooth_viewtx)
-{
- RegionView3D *rv3d = ar->regiondata;
- float afm[3];
- float size;
-
- ED_view3d_smooth_view_force_finish(C, v3d, ar);
-
- /* SMOOTHVIEW */
- float new_ofs[3];
- float new_dist;
-
- sub_v3_v3v3(afm, max, min);
- size = max_fff(afm[0], afm[1], afm[2]);
-
- if (ok_dist) {
- char persp;
-
- if (rv3d->is_persp) {
- if (rv3d->persp == RV3D_CAMOB && ED_view3d_camera_lock_check(v3d, rv3d)) {
- persp = RV3D_CAMOB;
- }
- else {
- persp = RV3D_PERSP;
- }
- }
- else { /* ortho */
- if (size < 0.0001f) {
- /* bounding box was a single point so do not zoom */
- ok_dist = false;
- }
- else {
- /* adjust zoom so it looks nicer */
- persp = RV3D_ORTHO;
- }
- }
-
- if (ok_dist) {
- new_dist = ED_view3d_radius_to_dist(v3d, ar, CTX_data_depsgraph(C), 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);
- }
- }
- }
-
- mid_v3_v3v3(new_ofs, min, max);
- negate_v3(new_ofs);
-
- if (rv3d->persp == RV3D_CAMOB && !ED_view3d_camera_lock_check(v3d, rv3d)) {
- rv3d->persp = RV3D_PERSP;
- ED_view3d_smooth_view(
- C, v3d, ar, smooth_viewtx,
- &(const V3D_SmoothParams) {
- .camera_old = v3d->camera, .ofs = new_ofs,
- .dist = ok_dist ? &new_dist : NULL,
- });
- }
- else {
- ED_view3d_smooth_view(
- C, v3d, ar, smooth_viewtx,
- &(const V3D_SmoothParams) { .ofs = new_ofs, .dist = ok_dist ? &new_dist : NULL, });
- }
-
- /* smooth view does viewlock RV3D_BOXVIEW copy */
+static bool view3d_object_skip_minmax(const View3D *v3d,
+ const RegionView3D *rv3d,
+ const Object *ob,
+ const bool skip_camera,
+ bool *r_only_center)
+{
+ BLI_assert(ob->id.orig_id == NULL);
+ *r_only_center = false;
+
+ if (skip_camera && (ob == v3d->camera)) {
+ return true;
+ }
+
+ if ((ob->type == OB_EMPTY) && (ob->empty_drawtype == OB_EMPTY_IMAGE) &&
+ !BKE_object_empty_image_frame_is_visible_in_view3d(ob, rv3d)) {
+ *r_only_center = true;
+ return false;
+ }
+
+ return false;
+}
+
+static void view3d_from_minmax(bContext *C,
+ View3D *v3d,
+ ARegion *ar,
+ const float min[3],
+ const float max[3],
+ bool ok_dist,
+ const int smooth_viewtx)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ float afm[3];
+ float size;
+
+ ED_view3d_smooth_view_force_finish(C, v3d, ar);
+
+ /* SMOOTHVIEW */
+ float new_ofs[3];
+ float new_dist;
+
+ sub_v3_v3v3(afm, max, min);
+ size = max_fff(afm[0], afm[1], afm[2]);
+
+ if (ok_dist) {
+ char persp;
+
+ if (rv3d->is_persp) {
+ if (rv3d->persp == RV3D_CAMOB && ED_view3d_camera_lock_check(v3d, rv3d)) {
+ persp = RV3D_CAMOB;
+ }
+ else {
+ persp = RV3D_PERSP;
+ }
+ }
+ else { /* ortho */
+ if (size < 0.0001f) {
+ /* bounding box was a single point so do not zoom */
+ ok_dist = false;
+ }
+ else {
+ /* adjust zoom so it looks nicer */
+ persp = RV3D_ORTHO;
+ }
+ }
+
+ if (ok_dist) {
+ new_dist = ED_view3d_radius_to_dist(
+ v3d, ar, CTX_data_depsgraph(C), 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);
+ }
+ }
+ }
+
+ mid_v3_v3v3(new_ofs, min, max);
+ negate_v3(new_ofs);
+
+ if (rv3d->persp == RV3D_CAMOB && !ED_view3d_camera_lock_check(v3d, rv3d)) {
+ rv3d->persp = RV3D_PERSP;
+ ED_view3d_smooth_view(C,
+ v3d,
+ ar,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .camera_old = v3d->camera,
+ .ofs = new_ofs,
+ .dist = ok_dist ? &new_dist : NULL,
+ });
+ }
+ else {
+ ED_view3d_smooth_view(C,
+ v3d,
+ ar,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .ofs = new_ofs,
+ .dist = ok_dist ? &new_dist : NULL,
+ });
+ }
+
+ /* smooth view does viewlock RV3D_BOXVIEW copy */
}
/**
* Same as #view3d_from_minmax but for all regions (except cameras).
*/
-static void view3d_from_minmax_multi(
- bContext *C, View3D *v3d,
- const float min[3], const float max[3],
- 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;
- /* 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);
- }
- }
- }
+static void view3d_from_minmax_multi(bContext *C,
+ View3D *v3d,
+ const float min[3],
+ const float max[3],
+ 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;
+ /* 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);
+ }
+ }
+ }
}
static int view3d_all_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- Scene *scene = CTX_data_scene(C);
- const Depsgraph *depsgraph = CTX_data_depsgraph(C);
- 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) ||
- /* 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");
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
-
- float min[3], max[3];
- bool changed = false;
-
- if (center) {
- /* in 2.4x this also move the cursor to (0, 0, 0) (with shift+c). */
- View3DCursor *cursor = &scene->cursor;
- zero_v3(min);
- zero_v3(max);
- zero_v3(cursor->location);
- float mat3[3][3];
- unit_m3(mat3);
- BKE_scene_cursor_mat3_to_rot(cursor, mat3, false);
- }
- else {
- INIT_MINMAX(min, max);
- }
-
- for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) {
- if (BASE_VISIBLE(v3d, base_eval)) {
- bool only_center = false;
- Object *ob = DEG_get_original_object(base_eval->object);
- if (view3d_object_skip_minmax(v3d, rv3d, ob, skip_camera, &only_center)) {
- continue;
- }
-
- if (only_center) {
- minmax_v3v3_v3(min, max, base_eval->object->obmat[3]);
- }
- else {
- BKE_object_minmax(base_eval->object, min, max, false);
- }
- changed = true;
- }
- }
-
- if (center) {
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- }
-
- if (!changed) {
- ED_region_tag_redraw(ar);
- /* 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,
- * only the cursor so I choice a ED_region_tag like
- * view3d_smooth_view do for the center_cursor.
- * See bug #22640
- */
- return OPERATOR_FINISHED;
- }
-
- if (use_all_regions) {
- view3d_from_minmax_multi(C, v3d, min, max, true, smooth_viewtx);
- }
- else {
- view3d_from_minmax(C, v3d, ar, min, max, true, smooth_viewtx);
- }
-
- return OPERATOR_FINISHED;
+ ARegion *ar = CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ 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) ||
+ /* 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");
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+
+ float min[3], max[3];
+ bool changed = false;
+
+ if (center) {
+ /* in 2.4x this also move the cursor to (0, 0, 0) (with shift+c). */
+ View3DCursor *cursor = &scene->cursor;
+ zero_v3(min);
+ zero_v3(max);
+ zero_v3(cursor->location);
+ float mat3[3][3];
+ unit_m3(mat3);
+ BKE_scene_cursor_mat3_to_rot(cursor, mat3, false);
+ }
+ else {
+ INIT_MINMAX(min, max);
+ }
+
+ for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) {
+ if (BASE_VISIBLE(v3d, base_eval)) {
+ bool only_center = false;
+ Object *ob = DEG_get_original_object(base_eval->object);
+ if (view3d_object_skip_minmax(v3d, rv3d, ob, skip_camera, &only_center)) {
+ continue;
+ }
+
+ if (only_center) {
+ minmax_v3v3_v3(min, max, base_eval->object->obmat[3]);
+ }
+ else {
+ BKE_object_minmax(base_eval->object, min, max, false);
+ }
+ changed = true;
+ }
+ }
+
+ if (center) {
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ }
+
+ if (!changed) {
+ ED_region_tag_redraw(ar);
+ /* 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,
+ * only the cursor so I choice a ED_region_tag like
+ * view3d_smooth_view do for the center_cursor.
+ * See bug #22640
+ */
+ return OPERATOR_FINISHED;
+ }
+
+ if (use_all_regions) {
+ view3d_from_minmax_multi(C, v3d, min, max, true, smooth_viewtx);
+ }
+ else {
+ view3d_from_minmax(C, v3d, ar, min, max, true, smooth_viewtx);
+ }
+
+ return OPERATOR_FINISHED;
}
-
void VIEW3D_OT_view_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View All";
- ot->description = "View all objects in scene";
- ot->idname = "VIEW3D_OT_view_all";
+ /* identifiers */
+ ot->name = "View All";
+ ot->description = "View all objects in scene";
+ ot->idname = "VIEW3D_OT_view_all";
- /* api callbacks */
- ot->exec = view3d_all_exec;
- ot->poll = ED_operator_region_view3d_active;
+ /* api callbacks */
+ ot->exec = view3d_all_exec;
+ ot->poll = ED_operator_region_view3d_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
- /* properties */
- view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS);
- RNA_def_boolean(ot->srna, "center", 0, "Center", "");
+ /* properties */
+ view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS);
+ RNA_def_boolean(ot->srna, "center", 0, "Center", "");
}
/** \} */
@@ -2874,151 +2919,150 @@ 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);
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
- bGPdata *gpd = CTX_data_gpencil_data(C);
- const bool is_gp_edit = GPENCIL_ANY_MODE(gpd);
- const bool is_face_map = ((is_gp_edit == false) && ar->gizmo_map &&
- WM_gizmomap_is_any_selected(ar->gizmo_map));
- Object *ob_eval = OBACT(view_layer_eval);
- Object *obedit = CTX_data_edit_object(C);
- 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) ||
- /* 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);
-
- INIT_MINMAX(min, max);
- if (is_face_map) {
- ob_eval = NULL;
- }
-
- if (ob_eval && (ob_eval->mode & OB_MODE_WEIGHT_PAINT)) {
- /* hard-coded exception, we look for the one selected armature */
- /* this is weak code this way, we should make a generic
- * active/selection callback interface once... */
- Base *base_eval;
- for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) {
- if (BASE_SELECTED_EDITABLE(v3d, base_eval)) {
- if (base_eval->object->type == OB_ARMATURE) {
- if (base_eval->object->mode & OB_MODE_POSE) {
- break;
- }
- }
- }
- }
- if (base_eval) {
- ob_eval = base_eval->object;
- }
- }
-
- if (is_gp_edit) {
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
- {
- /* we're only interested in selected points here... */
- if ((gps->flag & GP_STROKE_SELECT) && (gps->flag & GP_STROKE_3DSPACE)) {
- ok |= BKE_gpencil_stroke_minmax(gps, true, min, max);
- }
- }
- CTX_DATA_END;
-
- if ((ob_eval) && (ok)) {
- mul_m4_v3(ob_eval->obmat, min);
- mul_m4_v3(ob_eval->obmat, max);
- }
- }
- else if (is_face_map) {
- ok = WM_gizmomap_minmax(ar->gizmo_map, true, true, min, max);
- }
- else if (obedit) {
- /* only selected */
- FOREACH_OBJECT_IN_MODE_BEGIN (view_layer_eval, v3d, obedit->type, obedit->mode, ob_eval_iter) {
- ok |= ED_view3d_minmax_verts(ob_eval_iter, min, max);
- }
- FOREACH_OBJECT_IN_MODE_END;
- }
- else if (ob_eval && (ob_eval->mode & OB_MODE_POSE)) {
- FOREACH_OBJECT_IN_MODE_BEGIN (view_layer_eval, v3d, ob_eval->type, ob_eval->mode, ob_eval_iter) {
- ok |= BKE_pose_minmax(ob_eval_iter, min, max, true, true);
- }
- FOREACH_OBJECT_IN_MODE_END;
- }
- else if (BKE_paint_select_face_test(ob_eval)) {
- ok = paintface_minmax(ob_eval, min, max);
- }
- else if (ob_eval && (ob_eval->mode & OB_MODE_PARTICLE_EDIT)) {
- ok = PE_minmax(scene, view_layer_eval, min, max);
- }
- else if (ob_eval &&
- (ob_eval->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)))
- {
- BKE_paint_stroke_get_average(scene, ob_eval, min);
- copy_v3_v3(max, min);
- ok = true;
- ok_dist = 0; /* don't zoom */
- }
- else {
- Base *base_eval;
- for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) {
- if (BASE_SELECTED(v3d, base_eval)) {
- bool only_center = false;
- Object *ob = DEG_get_original_object(base_eval->object);
- if (view3d_object_skip_minmax(v3d, rv3d, ob, skip_camera, &only_center)) {
- continue;
- }
-
- /* account for duplis */
- if (BKE_object_minmax_dupli(depsgraph, scene, base_eval->object, min, max, false) == 0) {
- /* use if duplis not found */
- if (only_center) {
- minmax_v3v3_v3(min, max, base_eval->object->obmat[3]);
- }
- else {
- BKE_object_minmax(base_eval->object, min, max, false);
- }
- }
-
- ok = 1;
- }
- }
- }
-
- if (ok == 0) {
- return OPERATOR_FINISHED;
- }
-
- if (use_all_regions) {
- 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);
- }
-
- return OPERATOR_FINISHED;
+ ARegion *ar = CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ const bool is_gp_edit = GPENCIL_ANY_MODE(gpd);
+ const bool is_face_map = ((is_gp_edit == false) && ar->gizmo_map &&
+ WM_gizmomap_is_any_selected(ar->gizmo_map));
+ Object *ob_eval = OBACT(view_layer_eval);
+ Object *obedit = CTX_data_edit_object(C);
+ 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) ||
+ /* 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);
+
+ INIT_MINMAX(min, max);
+ if (is_face_map) {
+ ob_eval = NULL;
+ }
+
+ if (ob_eval && (ob_eval->mode & OB_MODE_WEIGHT_PAINT)) {
+ /* hard-coded exception, we look for the one selected armature */
+ /* this is weak code this way, we should make a generic
+ * active/selection callback interface once... */
+ Base *base_eval;
+ for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) {
+ if (BASE_SELECTED_EDITABLE(v3d, base_eval)) {
+ if (base_eval->object->type == OB_ARMATURE) {
+ if (base_eval->object->mode & OB_MODE_POSE) {
+ break;
+ }
+ }
+ }
+ }
+ if (base_eval) {
+ ob_eval = base_eval->object;
+ }
+ }
+
+ if (is_gp_edit) {
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ /* we're only interested in selected points here... */
+ if ((gps->flag & GP_STROKE_SELECT) && (gps->flag & GP_STROKE_3DSPACE)) {
+ ok |= BKE_gpencil_stroke_minmax(gps, true, min, max);
+ }
+ }
+ CTX_DATA_END;
+
+ if ((ob_eval) && (ok)) {
+ mul_m4_v3(ob_eval->obmat, min);
+ mul_m4_v3(ob_eval->obmat, max);
+ }
+ }
+ else if (is_face_map) {
+ ok = WM_gizmomap_minmax(ar->gizmo_map, true, true, min, max);
+ }
+ else if (obedit) {
+ /* only selected */
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer_eval, v3d, obedit->type, obedit->mode, ob_eval_iter) {
+ ok |= ED_view3d_minmax_verts(ob_eval_iter, min, max);
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+ }
+ else if (ob_eval && (ob_eval->mode & OB_MODE_POSE)) {
+ FOREACH_OBJECT_IN_MODE_BEGIN (
+ view_layer_eval, v3d, ob_eval->type, ob_eval->mode, ob_eval_iter) {
+ ok |= BKE_pose_minmax(ob_eval_iter, min, max, true, true);
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+ }
+ else if (BKE_paint_select_face_test(ob_eval)) {
+ ok = paintface_minmax(ob_eval, min, max);
+ }
+ else if (ob_eval && (ob_eval->mode & OB_MODE_PARTICLE_EDIT)) {
+ ok = PE_minmax(scene, view_layer_eval, min, max);
+ }
+ else if (ob_eval && (ob_eval->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT |
+ OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) {
+ BKE_paint_stroke_get_average(scene, ob_eval, min);
+ copy_v3_v3(max, min);
+ ok = true;
+ ok_dist = 0; /* don't zoom */
+ }
+ else {
+ Base *base_eval;
+ for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) {
+ if (BASE_SELECTED(v3d, base_eval)) {
+ bool only_center = false;
+ Object *ob = DEG_get_original_object(base_eval->object);
+ if (view3d_object_skip_minmax(v3d, rv3d, ob, skip_camera, &only_center)) {
+ continue;
+ }
+
+ /* account for duplis */
+ if (BKE_object_minmax_dupli(depsgraph, scene, base_eval->object, min, max, false) == 0) {
+ /* use if duplis not found */
+ if (only_center) {
+ minmax_v3v3_v3(min, max, base_eval->object->obmat[3]);
+ }
+ else {
+ BKE_object_minmax(base_eval->object, min, max, false);
+ }
+ }
+
+ ok = 1;
+ }
+ }
+ }
+
+ if (ok == 0) {
+ return OPERATOR_FINISHED;
+ }
+
+ if (use_all_regions) {
+ 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);
+ }
+
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_view_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Selected";
- ot->description = "Move the view to the selection center";
- ot->idname = "VIEW3D_OT_view_selected";
+ /* identifiers */
+ ot->name = "View 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;
+ /* api callbacks */
+ ot->exec = viewselected_exec;
+ ot->poll = ED_operator_region_view3d_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
- /* properties */
- view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS);
+ /* properties */
+ view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS);
}
/** \} */
@@ -3029,34 +3073,34 @@ void VIEW3D_OT_view_selected(wmOperatorType *ot)
static int view_lock_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- View3D *v3d = CTX_wm_view3d(C);
+ View3D *v3d = CTX_wm_view3d(C);
- if (v3d) {
- ED_view3d_lock_clear(v3d);
+ if (v3d) {
+ ED_view3d_lock_clear(v3d);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void VIEW3D_OT_view_lock_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Lock Clear";
- ot->description = "Clear all view locking";
- ot->idname = "VIEW3D_OT_view_lock_clear";
+ /* identifiers */
+ ot->name = "View Lock Clear";
+ ot->description = "Clear all view locking";
+ ot->idname = "VIEW3D_OT_view_lock_clear";
- /* api callbacks */
- ot->exec = view_lock_clear_exec;
- ot->poll = ED_operator_region_view3d_active;
+ /* api callbacks */
+ ot->exec = view_lock_clear_exec;
+ ot->poll = ED_operator_region_view3d_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
/** \} */
@@ -3067,53 +3111,53 @@ void VIEW3D_OT_view_lock_clear(wmOperatorType *ot)
static int view_lock_to_active_exec(bContext *C, wmOperator *UNUSED(op))
{
- View3D *v3d = CTX_wm_view3d(C);
- Object *obact = CTX_data_active_object(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Object *obact = CTX_data_active_object(C);
- if (v3d) {
- ED_view3d_lock_clear(v3d);
+ if (v3d) {
+ ED_view3d_lock_clear(v3d);
- v3d->ob_centre = obact; /* can be NULL */
+ v3d->ob_centre = obact; /* can be NULL */
- if (obact && obact->type == OB_ARMATURE) {
- if (obact->mode & OB_MODE_POSE) {
- Object *obact_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), 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));
- }
- }
- 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));
- }
- }
- }
+ if (obact && obact->type == OB_ARMATURE) {
+ if (obact->mode & OB_MODE_POSE) {
+ Object *obact_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), 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));
+ }
+ }
+ 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));
+ }
+ }
+ }
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void VIEW3D_OT_view_lock_to_active(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Lock to Active";
- ot->description = "Lock the view to the active object/bone";
- ot->idname = "VIEW3D_OT_view_lock_to_active";
+ /* identifiers */
+ ot->name = "View Lock to Active";
+ ot->description = "Lock the view to the active object/bone";
+ ot->idname = "VIEW3D_OT_view_lock_to_active";
- /* api callbacks */
- ot->exec = view_lock_to_active_exec;
- ot->poll = ED_operator_region_view3d_active;
+ /* api callbacks */
+ ot->exec = view_lock_to_active_exec;
+ ot->poll = ED_operator_region_view3d_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
/** \} */
@@ -3124,42 +3168,40 @@ void VIEW3D_OT_view_lock_to_active(wmOperatorType *ot)
static int viewcenter_cursor_exec(bContext *C, wmOperator *op)
{
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ Scene *scene = CTX_data_scene(C);
- if (rv3d) {
- ARegion *ar = CTX_wm_region(C);
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ if (rv3d) {
+ ARegion *ar = 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, ar);
- /* 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});
+ /* 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});
- /* smooth view does viewlock RV3D_BOXVIEW copy */
- }
+ /* smooth view does viewlock RV3D_BOXVIEW copy */
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_view_center_cursor(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Center View to Cursor";
- ot->description = "Center the view so that the cursor is in the middle of the view";
- ot->idname = "VIEW3D_OT_view_center_cursor";
+ /* identifiers */
+ ot->name = "Center View to Cursor";
+ ot->description = "Center the view so that the cursor is in the middle of the view";
+ ot->idname = "VIEW3D_OT_view_center_cursor";
- /* api callbacks */
- ot->exec = viewcenter_cursor_exec;
- ot->poll = ED_operator_view3d_active;
+ /* api callbacks */
+ ot->exec = viewcenter_cursor_exec;
+ ot->poll = ED_operator_view3d_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
/** \} */
@@ -3170,49 +3212,47 @@ void VIEW3D_OT_view_center_cursor(wmOperatorType *ot)
static int viewcenter_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- ARegion *ar = CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
- if (rv3d) {
- struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
- float new_ofs[3];
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ if (rv3d) {
+ struct Depsgraph *depsgraph = CTX_data_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, ar);
- view3d_operator_needs_opengl(C);
+ view3d_operator_needs_opengl(C);
- if (ED_view3d_autodist(depsgraph, ar, 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);
- }
- negate_v3(new_ofs);
- ED_view3d_smooth_view(
- C, v3d, ar, smooth_viewtx,
- &(const V3D_SmoothParams) {.ofs = new_ofs});
- }
+ if (ED_view3d_autodist(depsgraph, ar, 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);
+ }
+ negate_v3(new_ofs);
+ ED_view3d_smooth_view(C, v3d, ar, smooth_viewtx, &(const V3D_SmoothParams){.ofs = new_ofs});
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_view_center_pick(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Center View to Mouse";
- ot->description = "Center the view to the Z-depth position under the mouse cursor";
- ot->idname = "VIEW3D_OT_view_center_pick";
+ /* identifiers */
+ ot->name = "Center View to Mouse";
+ ot->description = "Center the view to the Z-depth position under the mouse cursor";
+ ot->idname = "VIEW3D_OT_view_center_pick";
- /* api callbacks */
- ot->invoke = viewcenter_pick_invoke;
- ot->poll = ED_operator_view3d_active;
+ /* api callbacks */
+ ot->invoke = viewcenter_pick_invoke;
+ ot->poll = ED_operator_view3d_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
/** \} */
@@ -3223,48 +3263,48 @@ void VIEW3D_OT_view_center_pick(wmOperatorType *ot)
static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op))
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- float xfac, yfac;
- float size[2];
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ float xfac, yfac;
+ float size[2];
- View3D *v3d;
- ARegion *ar;
- RegionView3D *rv3d;
+ View3D *v3d;
+ ARegion *ar;
+ RegionView3D *rv3d;
- /* no NULL check is needed, poll checks */
- ED_view3d_context_user_region(C, &v3d, &ar);
- rv3d = ar->regiondata;
+ /* no NULL check is needed, poll checks */
+ ED_view3d_context_user_region(C, &v3d, &ar);
+ rv3d = ar->regiondata;
- rv3d->camdx = rv3d->camdy = 0.0f;
+ 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, ar, 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);
+ /* 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);
- rv3d->camzoom = BKE_screen_view3d_zoom_from_fac(min_ff(xfac, yfac));
- CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
+ rv3d->camzoom = BKE_screen_view3d_zoom_from_fac(min_ff(xfac, yfac));
+ CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_view_center_camera(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Camera Center";
- ot->description = "Center the camera view";
- ot->idname = "VIEW3D_OT_view_center_camera";
+ /* identifiers */
+ ot->name = "View Camera Center";
+ ot->description = "Center the camera view";
+ ot->idname = "VIEW3D_OT_view_center_camera";
- /* api callbacks */
- ot->exec = view3d_center_camera_exec;
- ot->poll = view3d_camera_user_poll;
+ /* api callbacks */
+ ot->exec = view3d_center_camera_exec;
+ ot->poll = view3d_camera_user_poll;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
/** \} */
@@ -3275,28 +3315,28 @@ void VIEW3D_OT_view_center_camera(wmOperatorType *ot)
static int view3d_center_lock_exec(bContext *C, wmOperator *UNUSED(op))
{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
- zero_v2(rv3d->ofs_lock);
+ zero_v2(rv3d->ofs_lock);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_view_center_lock(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Lock Center";
- ot->description = "Center the view lock offset";
- ot->idname = "VIEW3D_OT_view_center_lock";
+ /* identifiers */
+ ot->name = "View Lock Center";
+ ot->description = "Center the view lock offset";
+ ot->idname = "VIEW3D_OT_view_center_lock";
- /* api callbacks */
- ot->exec = view3d_center_lock_exec;
- ot->poll = view3d_lock_poll;
+ /* api callbacks */
+ ot->exec = view3d_center_lock_exec;
+ ot->poll = view3d_lock_poll;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
/** \} */
@@ -3307,97 +3347,97 @@ 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);
- RegionView3D *rv3d = ED_view3d_context_rv3d(C);
-
- Scene *scene = CTX_data_scene(C);
-
- rcti rect;
- rctf vb, border;
-
- /* get box select values using rna */
- WM_operator_properties_border_to_rcti(op, &rect);
-
- /* calculate range */
-
- if (rv3d->persp == RV3D_CAMOB) {
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &vb, false);
- }
- else {
- vb.xmin = 0;
- vb.ymin = 0;
- vb.xmax = ar->winx;
- vb.ymax = ar->winy;
- }
-
- border.xmin = ((float)rect.xmin - vb.xmin) / BLI_rctf_size_x(&vb);
- border.ymin = ((float)rect.ymin - vb.ymin) / BLI_rctf_size_y(&vb);
- border.xmax = ((float)rect.xmax - vb.xmin) / BLI_rctf_size_x(&vb);
- border.ymax = ((float)rect.ymax - vb.ymin) / BLI_rctf_size_y(&vb);
-
- /* actually set border */
- CLAMP(border.xmin, 0.0f, 1.0f);
- CLAMP(border.ymin, 0.0f, 1.0f);
- CLAMP(border.xmax, 0.0f, 1.0f);
- CLAMP(border.ymax, 0.0f, 1.0f);
-
- if (rv3d->persp == RV3D_CAMOB) {
- scene->r.border = border;
-
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL);
- }
- else {
- v3d->render_border = border;
-
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- }
-
- /* drawing a border outside the camera view switches off border rendering */
- if ((border.xmin == border.xmax || border.ymin == border.ymax)) {
- if (rv3d->persp == RV3D_CAMOB) {
- scene->r.mode &= ~R_BORDER;
- }
- else {
- v3d->flag2 &= ~V3D_RENDER_BORDER;
- }
- }
- else {
- if (rv3d->persp == RV3D_CAMOB) {
- scene->r.mode |= R_BORDER;
- }
- else {
- v3d->flag2 |= V3D_RENDER_BORDER;
- }
- }
-
- if (rv3d->persp == RV3D_CAMOB) {
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- }
- return OPERATOR_FINISHED;
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ED_view3d_context_rv3d(C);
+
+ Scene *scene = CTX_data_scene(C);
+
+ rcti rect;
+ rctf vb, border;
+
+ /* get box select values using rna */
+ WM_operator_properties_border_to_rcti(op, &rect);
+
+ /* calculate range */
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &vb, false);
+ }
+ else {
+ vb.xmin = 0;
+ vb.ymin = 0;
+ vb.xmax = ar->winx;
+ vb.ymax = ar->winy;
+ }
+
+ border.xmin = ((float)rect.xmin - vb.xmin) / BLI_rctf_size_x(&vb);
+ border.ymin = ((float)rect.ymin - vb.ymin) / BLI_rctf_size_y(&vb);
+ border.xmax = ((float)rect.xmax - vb.xmin) / BLI_rctf_size_x(&vb);
+ border.ymax = ((float)rect.ymax - vb.ymin) / BLI_rctf_size_y(&vb);
+
+ /* actually set border */
+ CLAMP(border.xmin, 0.0f, 1.0f);
+ CLAMP(border.ymin, 0.0f, 1.0f);
+ CLAMP(border.xmax, 0.0f, 1.0f);
+ CLAMP(border.ymax, 0.0f, 1.0f);
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ scene->r.border = border;
+
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ }
+ else {
+ v3d->render_border = border;
+
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ }
+
+ /* drawing a border outside the camera view switches off border rendering */
+ if ((border.xmin == border.xmax || border.ymin == border.ymax)) {
+ if (rv3d->persp == RV3D_CAMOB) {
+ scene->r.mode &= ~R_BORDER;
+ }
+ else {
+ v3d->flag2 &= ~V3D_RENDER_BORDER;
+ }
+ }
+ else {
+ if (rv3d->persp == RV3D_CAMOB) {
+ scene->r.mode |= R_BORDER;
+ }
+ else {
+ v3d->flag2 |= V3D_RENDER_BORDER;
+ }
+ }
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_render_border(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Render Region";
- ot->description = "Set the boundaries of the border render and enable border render";
- ot->idname = "VIEW3D_OT_render_border";
+ /* identifiers */
+ ot->name = "Set Render Region";
+ ot->description = "Set the boundaries of the border render and enable border render";
+ ot->idname = "VIEW3D_OT_render_border";
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = render_border_exec;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = render_border_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
- ot->poll = ED_operator_view3d_active;
+ ot->poll = ED_operator_view3d_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_border(ot);
+ /* properties */
+ WM_operator_properties_border(ot);
}
/** \} */
@@ -3408,49 +3448,49 @@ void VIEW3D_OT_render_border(wmOperatorType *ot)
static int clear_render_border_exec(bContext *C, wmOperator *UNUSED(op))
{
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = ED_view3d_context_rv3d(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = ED_view3d_context_rv3d(C);
- Scene *scene = CTX_data_scene(C);
- rctf *border = NULL;
+ Scene *scene = CTX_data_scene(C);
+ rctf *border = NULL;
- if (rv3d->persp == RV3D_CAMOB) {
- scene->r.mode &= ~R_BORDER;
- border = &scene->r.border;
+ if (rv3d->persp == RV3D_CAMOB) {
+ scene->r.mode &= ~R_BORDER;
+ border = &scene->r.border;
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL);
- }
- else {
- v3d->flag2 &= ~V3D_RENDER_BORDER;
- border = &v3d->render_border;
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ }
+ else {
+ v3d->flag2 &= ~V3D_RENDER_BORDER;
+ border = &v3d->render_border;
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- }
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ }
- border->xmin = 0.0f;
- border->ymin = 0.0f;
- border->xmax = 1.0f;
- border->ymax = 1.0f;
+ border->xmin = 0.0f;
+ border->ymin = 0.0f;
+ border->xmax = 1.0f;
+ border->ymax = 1.0f;
- if (rv3d->persp == RV3D_CAMOB) {
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- }
- return OPERATOR_FINISHED;
+ if (rv3d->persp == RV3D_CAMOB) {
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_clear_render_border(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Render Region";
- ot->description = "Clear the boundaries of the border render and disable border render";
- ot->idname = "VIEW3D_OT_clear_render_border";
+ /* identifiers */
+ ot->name = "Clear Render Region";
+ ot->description = "Clear the boundaries of the border render and disable border render";
+ ot->idname = "VIEW3D_OT_clear_render_border";
- /* api callbacks */
- ot->exec = clear_render_border_exec;
- ot->poll = ED_operator_view3d_active;
+ /* api callbacks */
+ ot->exec = clear_render_border_exec;
+ ot->poll = ED_operator_view3d_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -3461,161 +3501,165 @@ void VIEW3D_OT_clear_render_border(wmOperatorType *ot)
static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = 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);
-
- /* Zooms in on a border drawn by the user */
- rcti rect;
- float dvec[3], vb[2], xscale, yscale;
- float dist_range[2];
-
- /* SMOOTHVIEW */
- float new_dist;
- float new_ofs[3];
-
- /* ZBuffer depth vars */
- float depth_close = FLT_MAX;
- float cent[2], p[3];
-
- /* note; otherwise opengl won't work */
- view3d_operator_needs_opengl(C);
-
- /* get box select values using rna */
- WM_operator_properties_border_to_rcti(op, &rect);
-
- /* check if zooming in/out view */
- const bool zoom_in = !RNA_boolean_get(op->ptr, "zoom_out");
-
- ED_view3d_dist_range_get(v3d, dist_range);
-
- /* Get Z Depths, needed for perspective, nice for ortho */
- ED_view3d_draw_depth(CTX_data_depsgraph(C), ar, 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);
-
- /* find the closest Z pixel */
- depth_close = view3d_depth_near(&depth_temp);
-
- MEM_SAFE_FREE(depth_temp.depths);
- }
-
- cent[0] = (((float)rect.xmin) + ((float)rect.xmax)) / 2;
- cent[1] = (((float)rect.ymin) + ((float)rect.ymax)) / 2;
-
- if (rv3d->is_persp) {
- float p_corner[3];
-
- /* no depths to use, we cant do anything! */
- if (depth_close == FLT_MAX) {
- BKE_report(op->reports, RPT_ERROR, "Depth too large");
- 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)))
- {
- return OPERATOR_CANCELLED;
- }
-
- sub_v3_v3v3(dvec, p, p_corner);
- negate_v3_v3(new_ofs, p);
-
- new_dist = len_v3(dvec);
-
- /* ignore dist_range min */
- dist_range[0] = v3d->clip_start * 1.5f;
- }
- else { /* othographic */
- /* find the current window width and height */
- vb[0] = ar->winx;
- vb[1] = ar->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)) {
- negate_v3_v3(new_ofs, p);
- }
- else {
- float mval_f[2];
- float zfac;
-
- /* We cant use the depth, fallback to the old way that dosnt set the center depth */
- copy_v3_v3(new_ofs, rv3d->ofs);
-
- {
- float tvec[3];
- negate_v3_v3(tvec, new_ofs);
- zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL);
- }
-
- 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);
- /* center the view to the center of the rectangle */
- sub_v3_v3(new_ofs, dvec);
- }
-
- /* work out the ratios, so that everything selected fits when we zoom */
- xscale = (BLI_rcti_size_x(&rect) / vb[0]);
- yscale = (BLI_rcti_size_y(&rect) / vb[1]);
- new_dist *= max_ff(xscale, yscale);
- }
-
- if (!zoom_in) {
- sub_v3_v3v3(dvec, new_ofs, rv3d->ofs);
- new_dist = rv3d->dist * (rv3d->dist / new_dist);
- add_v3_v3v3(new_ofs, rv3d->ofs, dvec);
- }
-
- /* clamp after because we may have been zooming out */
- CLAMP(new_dist, dist_range[0], dist_range[1]);
-
- /* TODO(campbell): 'is_camera_lock' not currently working well. */
- const bool is_camera_lock = ED_view3d_camera_lock_check(v3d, rv3d);
- if ((rv3d->persp == RV3D_CAMOB) && (is_camera_lock == false)) {
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ED_view3d_persp_switch_from_camera(depsgraph, v3d, rv3d, RV3D_PERSP);
- }
-
- ED_view3d_smooth_view(
- C, v3d, ar, smooth_viewtx,
- &(const V3D_SmoothParams) { .ofs = new_ofs, .dist = &new_dist, });
-
- if (rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_sync(CTX_wm_area(C), ar);
- }
-
- return OPERATOR_FINISHED;
+ ARegion *ar = 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);
+
+ /* Zooms in on a border drawn by the user */
+ rcti rect;
+ float dvec[3], vb[2], xscale, yscale;
+ float dist_range[2];
+
+ /* SMOOTHVIEW */
+ float new_dist;
+ float new_ofs[3];
+
+ /* ZBuffer depth vars */
+ float depth_close = FLT_MAX;
+ float cent[2], p[3];
+
+ /* note; otherwise opengl won't work */
+ view3d_operator_needs_opengl(C);
+
+ /* get box select values using rna */
+ WM_operator_properties_border_to_rcti(op, &rect);
+
+ /* check if zooming in/out view */
+ const bool zoom_in = !RNA_boolean_get(op->ptr, "zoom_out");
+
+ ED_view3d_dist_range_get(v3d, dist_range);
+
+ /* Get Z Depths, needed for perspective, nice for ortho */
+ ED_view3d_draw_depth(CTX_data_depsgraph(C), ar, 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);
+
+ /* find the closest Z pixel */
+ depth_close = view3d_depth_near(&depth_temp);
+
+ MEM_SAFE_FREE(depth_temp.depths);
+ }
+
+ cent[0] = (((float)rect.xmin) + ((float)rect.xmax)) / 2;
+ cent[1] = (((float)rect.ymin) + ((float)rect.ymax)) / 2;
+
+ if (rv3d->is_persp) {
+ float p_corner[3];
+
+ /* no depths to use, we cant do anything! */
+ if (depth_close == FLT_MAX) {
+ BKE_report(op->reports, RPT_ERROR, "Depth too large");
+ 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))) {
+ return OPERATOR_CANCELLED;
+ }
+
+ sub_v3_v3v3(dvec, p, p_corner);
+ negate_v3_v3(new_ofs, p);
+
+ new_dist = len_v3(dvec);
+
+ /* ignore dist_range min */
+ dist_range[0] = v3d->clip_start * 1.5f;
+ }
+ else { /* othographic */
+ /* find the current window width and height */
+ vb[0] = ar->winx;
+ vb[1] = ar->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)) {
+ negate_v3_v3(new_ofs, p);
+ }
+ else {
+ float mval_f[2];
+ float zfac;
+
+ /* We cant use the depth, fallback to the old way that dosnt set the center depth */
+ copy_v3_v3(new_ofs, rv3d->ofs);
+
+ {
+ float tvec[3];
+ negate_v3_v3(tvec, new_ofs);
+ zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL);
+ }
+
+ 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);
+ /* center the view to the center of the rectangle */
+ sub_v3_v3(new_ofs, dvec);
+ }
+
+ /* work out the ratios, so that everything selected fits when we zoom */
+ xscale = (BLI_rcti_size_x(&rect) / vb[0]);
+ yscale = (BLI_rcti_size_y(&rect) / vb[1]);
+ new_dist *= max_ff(xscale, yscale);
+ }
+
+ if (!zoom_in) {
+ sub_v3_v3v3(dvec, new_ofs, rv3d->ofs);
+ new_dist = rv3d->dist * (rv3d->dist / new_dist);
+ add_v3_v3v3(new_ofs, rv3d->ofs, dvec);
+ }
+
+ /* clamp after because we may have been zooming out */
+ CLAMP(new_dist, dist_range[0], dist_range[1]);
+
+ /* TODO(campbell): 'is_camera_lock' not currently working well. */
+ const bool is_camera_lock = ED_view3d_camera_lock_check(v3d, rv3d);
+ if ((rv3d->persp == RV3D_CAMOB) && (is_camera_lock == false)) {
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ED_view3d_persp_switch_from_camera(depsgraph, v3d, rv3d, RV3D_PERSP);
+ }
+
+ ED_view3d_smooth_view(C,
+ v3d,
+ ar,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .ofs = new_ofs,
+ .dist = &new_dist,
+ });
+
+ if (rv3d->viewlock & RV3D_BOXVIEW) {
+ view3d_boxview_sync(CTX_wm_area(C), ar);
+ }
+
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_zoom_border(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Zoom to Border";
- ot->description = "Zoom in the view to the nearest object contained in the border";
- ot->idname = "VIEW3D_OT_zoom_border";
+ /* identifiers */
+ ot->name = "Zoom to Border";
+ ot->description = "Zoom in the view to the nearest object contained in the border";
+ ot->idname = "VIEW3D_OT_zoom_border";
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = view3d_zoom_border_exec;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = view3d_zoom_border_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
- ot->poll = ED_operator_region_view3d_active;
+ ot->poll = ED_operator_region_view3d_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
- /* properties */
- WM_operator_properties_gesture_box_zoom(ot);
+ /* properties */
+ WM_operator_properties_gesture_box_zoom(ot);
}
/** \} */
@@ -3626,49 +3670,52 @@ void VIEW3D_OT_zoom_border(wmOperatorType *ot)
* Sets the view to 1:1 camera/render-pixel.
* \{ */
-static void view3d_set_1_to_1_viewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View3D *v3d)
+static void view3d_set_1_to_1_viewborder(Scene *scene,
+ Depsgraph *depsgraph,
+ ARegion *ar,
+ View3D *v3d)
{
- RegionView3D *rv3d = ar->regiondata;
- float size[2];
- int im_width = (scene->r.size * scene->r.xsch) / 100;
+ RegionView3D *rv3d = ar->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, ar, 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);
+ rv3d->camzoom = BKE_screen_view3d_zoom_from_fac((float)im_width / size[0]);
+ CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
}
static int view3d_zoom_1_to_1_camera_exec(bContext *C, wmOperator *UNUSED(op))
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
- View3D *v3d;
- ARegion *ar;
+ View3D *v3d;
+ ARegion *ar;
- /* no NULL check is needed, poll checks */
- ED_view3d_context_user_region(C, &v3d, &ar);
+ /* no NULL check is needed, poll checks */
+ ED_view3d_context_user_region(C, &v3d, &ar);
- view3d_set_1_to_1_viewborder(scene, depsgraph, ar, v3d);
+ view3d_set_1_to_1_viewborder(scene, depsgraph, ar, v3d);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_zoom_camera_1_to_1(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Zoom Camera 1:1";
- ot->description = "Match the camera to 1:1 to the render output";
- ot->idname = "VIEW3D_OT_zoom_camera_1_to_1";
+ /* identifiers */
+ ot->name = "Zoom Camera 1:1";
+ ot->description = "Match the camera to 1:1 to the render output";
+ ot->idname = "VIEW3D_OT_zoom_camera_1_to_1";
- /* api callbacks */
- ot->exec = view3d_zoom_1_to_1_camera_exec;
- ot->poll = view3d_camera_user_poll;
+ /* api callbacks */
+ ot->exec = view3d_zoom_1_to_1_camera_exec;
+ ot->poll = view3d_camera_user_poll;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
/** \} */
@@ -3678,211 +3725,229 @@ void VIEW3D_OT_zoom_camera_1_to_1(wmOperatorType *ot)
* \{ */
static const EnumPropertyItem prop_view_items[] = {
- {RV3D_VIEW_LEFT, "LEFT", ICON_TRIA_LEFT, "Left", "View From the Left"},
- {RV3D_VIEW_RIGHT, "RIGHT", ICON_TRIA_RIGHT, "Right", "View From the Right"},
- {RV3D_VIEW_BOTTOM, "BOTTOM", ICON_TRIA_DOWN, "Bottom", "View From the Bottom"},
- {RV3D_VIEW_TOP, "TOP", ICON_TRIA_UP, "Top", "View From the Top"},
- {RV3D_VIEW_FRONT, "FRONT", 0, "Front", "View From the Front"},
- {RV3D_VIEW_BACK, "BACK", 0, "Back", "View From the Back"},
- {0, NULL, 0, NULL, NULL},
+ {RV3D_VIEW_LEFT, "LEFT", ICON_TRIA_LEFT, "Left", "View From the Left"},
+ {RV3D_VIEW_RIGHT, "RIGHT", ICON_TRIA_RIGHT, "Right", "View From the Right"},
+ {RV3D_VIEW_BOTTOM, "BOTTOM", ICON_TRIA_DOWN, "Bottom", "View From the Bottom"},
+ {RV3D_VIEW_TOP, "TOP", ICON_TRIA_UP, "Top", "View From the Top"},
+ {RV3D_VIEW_FRONT, "FRONT", 0, "Front", "View From the Front"},
+ {RV3D_VIEW_BACK, "BACK", 0, "Back", "View From the Back"},
+ {0, NULL, 0, NULL, NULL},
};
-
/* would like to make this a generic function - outside of transform */
/**
* \param align_to_quat: When not NULL, set the axis relative to this rotation.
*/
-static void axis_set_view(
- bContext *C, View3D *v3d, ARegion *ar,
- const float quat_[4],
- short view, int perspo,
- const float *align_to_quat,
- const int smooth_viewtx)
-{
- RegionView3D *rv3d = ar->regiondata; /* no NULL check is needed, poll checks */
- float quat[4];
- const short orig_persp = rv3d->persp;
-
-
- normalize_qt_qt(quat, quat_);
-
- if (align_to_quat) {
- mul_qt_qtqt(quat, quat, align_to_quat);
- rv3d->view = view = RV3D_VIEW_USER;
- }
-
- if (align_to_quat == NULL) {
- rv3d->view = view;
- }
-
- if (rv3d->viewlock & RV3D_LOCKED) {
- ED_region_tag_redraw(ar);
- return;
- }
-
- if (U.uiflag & USER_AUTOPERSP) {
- rv3d->persp = RV3D_VIEW_IS_AXIS(view) ? RV3D_ORTHO : perspo;
- }
- else if (rv3d->persp == RV3D_CAMOB) {
- rv3d->persp = perspo;
- }
-
- if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
- /* to camera */
- ED_view3d_smooth_view(
- C, v3d, ar, smooth_viewtx,
- &(const V3D_SmoothParams) { .camera_old = v3d->camera, .ofs = rv3d->ofs, .quat = quat, });
- }
- else if (orig_persp == RV3D_CAMOB && v3d->camera) {
- /* from camera */
- float ofs[3], dist;
-
- copy_v3_v3(ofs, rv3d->ofs);
- dist = rv3d->dist;
-
- /* so we animate _from_ the camera location */
- Object *camera_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), v3d->camera);
- ED_view3d_from_object(camera_eval, rv3d->ofs, NULL, &rv3d->dist, NULL);
-
- ED_view3d_smooth_view(
- C, v3d, ar, smooth_viewtx,
- &(const V3D_SmoothParams) { .ofs = ofs, .quat = quat, .dist = &dist, });
- }
- else {
- /* rotate around selection */
- const float *dyn_ofs_pt = NULL;
- float dyn_ofs[3];
-
- if (U.uiflag & USER_ORBIT_SELECTION) {
- if (view3d_orbit_calc_center(C, dyn_ofs)) {
- negate_v3(dyn_ofs);
- dyn_ofs_pt = dyn_ofs;
- }
- }
-
- /* no camera involved */
- ED_view3d_smooth_view(
- C, v3d, ar, smooth_viewtx,
- &(const V3D_SmoothParams) { .quat = quat, .dyn_ofs = dyn_ofs_pt, });
- }
+static void axis_set_view(bContext *C,
+ View3D *v3d,
+ ARegion *ar,
+ const float quat_[4],
+ short view,
+ int perspo,
+ const float *align_to_quat,
+ const int smooth_viewtx)
+{
+ RegionView3D *rv3d = ar->regiondata; /* no NULL check is needed, poll checks */
+ float quat[4];
+ const short orig_persp = rv3d->persp;
+
+ normalize_qt_qt(quat, quat_);
+
+ if (align_to_quat) {
+ mul_qt_qtqt(quat, quat, align_to_quat);
+ rv3d->view = view = RV3D_VIEW_USER;
+ }
+
+ if (align_to_quat == NULL) {
+ rv3d->view = view;
+ }
+
+ if (rv3d->viewlock & RV3D_LOCKED) {
+ ED_region_tag_redraw(ar);
+ return;
+ }
+
+ if (U.uiflag & USER_AUTOPERSP) {
+ rv3d->persp = RV3D_VIEW_IS_AXIS(view) ? RV3D_ORTHO : perspo;
+ }
+ else if (rv3d->persp == RV3D_CAMOB) {
+ rv3d->persp = perspo;
+ }
+
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ /* to camera */
+ ED_view3d_smooth_view(C,
+ v3d,
+ ar,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .camera_old = v3d->camera,
+ .ofs = rv3d->ofs,
+ .quat = quat,
+ });
+ }
+ else if (orig_persp == RV3D_CAMOB && v3d->camera) {
+ /* from camera */
+ float ofs[3], dist;
+
+ copy_v3_v3(ofs, rv3d->ofs);
+ dist = rv3d->dist;
+
+ /* so we animate _from_ the camera location */
+ Object *camera_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), v3d->camera);
+ ED_view3d_from_object(camera_eval, rv3d->ofs, NULL, &rv3d->dist, NULL);
+
+ ED_view3d_smooth_view(C,
+ v3d,
+ ar,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .ofs = ofs,
+ .quat = quat,
+ .dist = &dist,
+ });
+ }
+ else {
+ /* rotate around selection */
+ const float *dyn_ofs_pt = NULL;
+ float dyn_ofs[3];
+
+ if (U.uiflag & USER_ORBIT_SELECTION) {
+ if (view3d_orbit_calc_center(C, dyn_ofs)) {
+ negate_v3(dyn_ofs);
+ dyn_ofs_pt = dyn_ofs;
+ }
+ }
+
+ /* no camera involved */
+ ED_view3d_smooth_view(C,
+ v3d,
+ ar,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .quat = quat,
+ .dyn_ofs = dyn_ofs_pt,
+ });
+ }
}
static int view_axis_exec(bContext *C, wmOperator *op)
{
- View3D *v3d;
- ARegion *ar;
- RegionView3D *rv3d;
- static int perspo = RV3D_PERSP;
- int viewnum;
- 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_smooth_view_force_finish(C, v3d, ar);
-
- viewnum = RNA_enum_get(op->ptr, "type");
-
- float align_quat_buf[4];
- float *align_quat = NULL;
-
- if (RNA_boolean_get(op->ptr, "align_active")) {
- /* align to active object */
- Object *obact = CTX_data_active_object(C);
- if (obact != NULL) {
- float twmat[3][3];
- /* same as transform gizmo when normal is set */
- ED_getTransformOrientationMatrix(C, twmat, V3D_AROUND_ACTIVE);
- align_quat = align_quat_buf;
- mat3_to_quat(align_quat, twmat);
- invert_qt_normalized(align_quat);
- }
- }
-
- if (RNA_boolean_get(op->ptr, "relative")) {
- float z_rel[3];
-
- if (viewnum == RV3D_VIEW_RIGHT) {
- negate_v3_v3(z_rel, rv3d->viewinv[0]);
- }
- else if (viewnum == RV3D_VIEW_LEFT) {
- copy_v3_v3(z_rel, rv3d->viewinv[0]);
- }
- else if (viewnum == RV3D_VIEW_TOP) {
- negate_v3_v3(z_rel, rv3d->viewinv[1]);
- }
- else if (viewnum == RV3D_VIEW_BOTTOM) {
- copy_v3_v3(z_rel, rv3d->viewinv[1]);
- }
- else if (viewnum == RV3D_VIEW_FRONT) {
- negate_v3_v3(z_rel, rv3d->viewinv[2]);
- }
- else if (viewnum == RV3D_VIEW_BACK) {
- copy_v3_v3(z_rel, rv3d->viewinv[2]);
- }
- else {
- BLI_assert(0);
- }
-
- float angle_max = FLT_MAX;
- int view_closest = -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;
- }
- }
- if (view_closest == -1) {
- view_closest = RV3D_VIEW_FRONT;
- }
- viewnum = view_closest;
- }
-
- /* 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);
-
- perspo = rv3d->persp;
-
- return OPERATOR_FINISHED;
+ View3D *v3d;
+ ARegion *ar;
+ RegionView3D *rv3d;
+ static int perspo = RV3D_PERSP;
+ int viewnum;
+ 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_smooth_view_force_finish(C, v3d, ar);
+
+ viewnum = RNA_enum_get(op->ptr, "type");
+
+ float align_quat_buf[4];
+ float *align_quat = NULL;
+
+ if (RNA_boolean_get(op->ptr, "align_active")) {
+ /* align to active object */
+ Object *obact = CTX_data_active_object(C);
+ if (obact != NULL) {
+ float twmat[3][3];
+ /* same as transform gizmo when normal is set */
+ ED_getTransformOrientationMatrix(C, twmat, V3D_AROUND_ACTIVE);
+ align_quat = align_quat_buf;
+ mat3_to_quat(align_quat, twmat);
+ invert_qt_normalized(align_quat);
+ }
+ }
+
+ if (RNA_boolean_get(op->ptr, "relative")) {
+ float z_rel[3];
+
+ if (viewnum == RV3D_VIEW_RIGHT) {
+ negate_v3_v3(z_rel, rv3d->viewinv[0]);
+ }
+ else if (viewnum == RV3D_VIEW_LEFT) {
+ copy_v3_v3(z_rel, rv3d->viewinv[0]);
+ }
+ else if (viewnum == RV3D_VIEW_TOP) {
+ negate_v3_v3(z_rel, rv3d->viewinv[1]);
+ }
+ else if (viewnum == RV3D_VIEW_BOTTOM) {
+ copy_v3_v3(z_rel, rv3d->viewinv[1]);
+ }
+ else if (viewnum == RV3D_VIEW_FRONT) {
+ negate_v3_v3(z_rel, rv3d->viewinv[2]);
+ }
+ else if (viewnum == RV3D_VIEW_BACK) {
+ copy_v3_v3(z_rel, rv3d->viewinv[2]);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ float angle_max = FLT_MAX;
+ int view_closest = -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;
+ }
+ }
+ if (view_closest == -1) {
+ view_closest = RV3D_VIEW_FRONT;
+ }
+ viewnum = view_closest;
+ }
+
+ /* 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);
+
+ perspo = rv3d->persp;
+
+ return OPERATOR_FINISHED;
}
-
void VIEW3D_OT_view_axis(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "View Axis";
- ot->description = "Use a preset viewpoint";
- ot->idname = "VIEW3D_OT_view_axis";
+ /* identifiers */
+ ot->name = "View Axis";
+ ot->description = "Use a preset viewpoint";
+ ot->idname = "VIEW3D_OT_view_axis";
- /* api callbacks */
- ot->exec = view_axis_exec;
- ot->poll = ED_operator_rv3d_user_region_poll;
+ /* api callbacks */
+ ot->exec = view_axis_exec;
+ ot->poll = ED_operator_rv3d_user_region_poll;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
- ot->prop = RNA_def_enum(ot->srna, "type", prop_view_items, 0, "View", "Preset viewpoint to use");
- RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "align_active", 0, "Align Active", "Align to the active object's axis");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "relative", 0, "Relative", "Rotate relative to the current orientation");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_view_items, 0, "View", "Preset viewpoint to use");
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(
+ ot->srna, "align_active", 0, "Align Active", "Align to the active object's axis");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(
+ ot->srna, "relative", 0, "Relative", "Rotate relative to the current orientation");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/** \} */
@@ -3893,106 +3958,111 @@ void VIEW3D_OT_view_axis(wmOperatorType *ot)
static int view_camera_exec(bContext *C, wmOperator *op)
{
- View3D *v3d;
- ARegion *ar;
- RegionView3D *rv3d;
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ View3D *v3d;
+ ARegion *ar;
+ 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;
+ /* no NULL check is needed, poll checks */
+ ED_view3d_context_user_region(C, &v3d, &ar);
+ rv3d = ar->regiondata;
- ED_view3d_smooth_view_force_finish(C, v3d, ar);
+ ED_view3d_smooth_view_force_finish(C, v3d, ar);
- if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
- /* lastview - */
+ if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
+ /* lastview - */
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Scene *scene = CTX_data_scene(C);
- if (rv3d->persp != RV3D_CAMOB) {
- Object *ob = OBACT(view_layer);
+ if (rv3d->persp != RV3D_CAMOB) {
+ Object *ob = OBACT(view_layer);
- if (!rv3d->smooth_timer) {
- /* store settings of current view before allowing overwriting with camera view
- * only if we're not currently in a view transition */
+ if (!rv3d->smooth_timer) {
+ /* store settings of current view before allowing overwriting with camera view
+ * only if we're not currently in a view transition */
- ED_view3d_lastview_store(rv3d);
- }
+ ED_view3d_lastview_store(rv3d);
+ }
#if 0
- if (G.qual == LR_ALTKEY) {
- if (oldcamera && is_an_active_object(oldcamera)) {
- v3d->camera = oldcamera;
- }
- handle_view3d_lock();
- }
+ if (G.qual == LR_ALTKEY) {
+ if (oldcamera && is_an_active_object(oldcamera)) {
+ v3d->camera = oldcamera;
+ }
+ handle_view3d_lock();
+ }
#endif
- /* first get the default camera for the view lock type */
- if (v3d->scenelock) {
- /* sets the camera view if available */
- v3d->camera = scene->camera;
- }
- else {
- /* use scene camera if one is not set (even though we're unlocked) */
- if (v3d->camera == NULL) {
- v3d->camera = scene->camera;
- }
- }
-
- /* if the camera isn't found, check a number of options */
- if (v3d->camera == NULL && ob && ob->type == OB_CAMERA) {
- v3d->camera = ob;
- }
-
- if (v3d->camera == NULL) {
- v3d->camera = BKE_view_layer_camera_find(view_layer);
- }
-
- /* couldn't find any useful camera, bail out */
- if (v3d->camera == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- /* important these don't get out of sync for locked scenes */
- if (v3d->scenelock && scene->camera != v3d->camera) {
- scene->camera = v3d->camera;
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- }
-
- /* finally do snazzy view zooming */
- rv3d->persp = RV3D_CAMOB;
- ED_view3d_smooth_view(
- C, v3d, ar, smooth_viewtx,
- &(const V3D_SmoothParams) {
- .camera = v3d->camera, .ofs = rv3d->ofs, .quat = rv3d->viewquat,
- .dist = &rv3d->dist, .lens = &v3d->lens,
- });
- }
- 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);
- }
- }
-
- return OPERATOR_FINISHED;
+ /* first get the default camera for the view lock type */
+ if (v3d->scenelock) {
+ /* sets the camera view if available */
+ v3d->camera = scene->camera;
+ }
+ else {
+ /* use scene camera if one is not set (even though we're unlocked) */
+ if (v3d->camera == NULL) {
+ v3d->camera = scene->camera;
+ }
+ }
+
+ /* if the camera isn't found, check a number of options */
+ if (v3d->camera == NULL && ob && ob->type == OB_CAMERA) {
+ v3d->camera = ob;
+ }
+
+ if (v3d->camera == NULL) {
+ v3d->camera = BKE_view_layer_camera_find(view_layer);
+ }
+
+ /* couldn't find any useful camera, bail out */
+ if (v3d->camera == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* important these don't get out of sync for locked scenes */
+ if (v3d->scenelock && scene->camera != v3d->camera) {
+ scene->camera = v3d->camera;
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ }
+
+ /* finally do snazzy view zooming */
+ rv3d->persp = RV3D_CAMOB;
+ ED_view3d_smooth_view(C,
+ v3d,
+ ar,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .camera = v3d->camera,
+ .ofs = rv3d->ofs,
+ .quat = rv3d->viewquat,
+ .dist = &rv3d->dist,
+ .lens = &v3d->lens,
+ });
+ }
+ 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);
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_view_camera(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Camera";
- ot->description = "Toggle the camera view";
- ot->idname = "VIEW3D_OT_view_camera";
+ /* identifiers */
+ ot->name = "View Camera";
+ ot->description = "Toggle the camera view";
+ ot->idname = "VIEW3D_OT_view_camera";
- /* api callbacks */
- ot->exec = view_camera_exec;
- ot->poll = ED_operator_rv3d_user_region_poll;
+ /* api callbacks */
+ ot->exec = view_camera_exec;
+ ot->poll = ED_operator_rv3d_user_region_poll;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
/** \} */
@@ -4004,133 +4074,140 @@ void VIEW3D_OT_view_camera(wmOperatorType *ot)
* \{ */
enum {
- V3D_VIEW_STEPLEFT = 1,
- V3D_VIEW_STEPRIGHT,
- V3D_VIEW_STEPDOWN,
- V3D_VIEW_STEPUP,
+ V3D_VIEW_STEPLEFT = 1,
+ V3D_VIEW_STEPRIGHT,
+ V3D_VIEW_STEPDOWN,
+ V3D_VIEW_STEPUP,
};
static const EnumPropertyItem prop_view_orbit_items[] = {
- {V3D_VIEW_STEPLEFT, "ORBITLEFT", 0, "Orbit Left", "Orbit the view around to the Left"},
- {V3D_VIEW_STEPRIGHT, "ORBITRIGHT", 0, "Orbit Right", "Orbit the view around to the Right"},
- {V3D_VIEW_STEPUP, "ORBITUP", 0, "Orbit Up", "Orbit the view Up"},
- {V3D_VIEW_STEPDOWN, "ORBITDOWN", 0, "Orbit Down", "Orbit the view Down"},
- {0, NULL, 0, NULL, NULL},
+ {V3D_VIEW_STEPLEFT, "ORBITLEFT", 0, "Orbit Left", "Orbit the view around to the Left"},
+ {V3D_VIEW_STEPRIGHT, "ORBITRIGHT", 0, "Orbit Right", "Orbit the view around to the Right"},
+ {V3D_VIEW_STEPUP, "ORBITUP", 0, "Orbit Up", "Orbit the view Up"},
+ {V3D_VIEW_STEPDOWN, "ORBITDOWN", 0, "Orbit Down", "Orbit the view Down"},
+ {0, NULL, 0, NULL, NULL},
};
static int vieworbit_exec(bContext *C, wmOperator *op)
{
- View3D *v3d;
- ARegion *ar;
- RegionView3D *rv3d;
- int orbitdir;
- char view_opposite;
- PropertyRNA *prop_angle = RNA_struct_find_property(op->ptr, "angle");
- float angle = RNA_property_is_set(op->ptr, prop_angle) ?
- RNA_property_float_get(op->ptr, prop_angle) : DEG2RADF(U.pad_rot_angle);
-
- /* no NULL check is needed, poll checks */
- v3d = CTX_wm_view3d(C);
- ar = CTX_wm_region(C);
- rv3d = ar->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)) {
- /* no NULL check is needed, poll checks */
- ED_view3d_context_user_region(C, &v3d, &ar);
- rv3d = ar->regiondata;
- }
-
- ED_view3d_smooth_view_force_finish(C, v3d, ar);
-
- if ((rv3d->viewlock & RV3D_LOCKED) == 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];
- float quat_new[4];
-
- if (view_opposite == RV3D_VIEW_USER) {
- const Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ED_view3d_persp_ensure(depsgraph, v3d, ar);
- }
-
- if (ELEM(orbitdir, V3D_VIEW_STEPLEFT, V3D_VIEW_STEPRIGHT)) {
- if (orbitdir == V3D_VIEW_STEPRIGHT) {
- angle = -angle;
- }
-
- /* z-axis */
- axis_angle_to_quat_single(quat_mul, 'Z', angle);
- }
- else {
-
- if (orbitdir == V3D_VIEW_STEPDOWN) {
- angle = -angle;
- }
-
- /* horizontal axis */
- axis_angle_to_quat(quat_mul, rv3d->viewinv[0], angle);
- }
-
- mul_qt_qtqt(quat_new, rv3d->viewquat, quat_mul);
-
- /* avoid precision loss over time */
- normalize_qt(quat_new);
-
- 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);
- }
- else {
- rv3d->view = RV3D_VIEW_USER;
- }
-
-
- float dyn_ofs[3], *dyn_ofs_pt = NULL;
-
- if (U.uiflag & USER_ORBIT_SELECTION) {
- if (view3d_orbit_calc_center(C, dyn_ofs)) {
- negate_v3(dyn_ofs);
- dyn_ofs_pt = dyn_ofs;
- }
- }
-
- ED_view3d_smooth_view(
- C, v3d, ar, smooth_viewtx,
- &(const V3D_SmoothParams) { .quat = quat_new, .dyn_ofs = dyn_ofs_pt, });
-
- return OPERATOR_FINISHED;
- }
- }
-
- return OPERATOR_CANCELLED;
+ View3D *v3d;
+ ARegion *ar;
+ RegionView3D *rv3d;
+ int orbitdir;
+ char view_opposite;
+ PropertyRNA *prop_angle = RNA_struct_find_property(op->ptr, "angle");
+ float angle = RNA_property_is_set(op->ptr, prop_angle) ?
+ RNA_property_float_get(op->ptr, prop_angle) :
+ DEG2RADF(U.pad_rot_angle);
+
+ /* no NULL check is needed, poll checks */
+ v3d = CTX_wm_view3d(C);
+ ar = CTX_wm_region(C);
+ rv3d = ar->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)) {
+ /* no NULL check is needed, poll checks */
+ ED_view3d_context_user_region(C, &v3d, &ar);
+ rv3d = ar->regiondata;
+ }
+
+ ED_view3d_smooth_view_force_finish(C, v3d, ar);
+
+ if ((rv3d->viewlock & RV3D_LOCKED) == 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];
+ float quat_new[4];
+
+ if (view_opposite == RV3D_VIEW_USER) {
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ED_view3d_persp_ensure(depsgraph, v3d, ar);
+ }
+
+ if (ELEM(orbitdir, V3D_VIEW_STEPLEFT, V3D_VIEW_STEPRIGHT)) {
+ if (orbitdir == V3D_VIEW_STEPRIGHT) {
+ angle = -angle;
+ }
+
+ /* z-axis */
+ axis_angle_to_quat_single(quat_mul, 'Z', angle);
+ }
+ else {
+
+ if (orbitdir == V3D_VIEW_STEPDOWN) {
+ angle = -angle;
+ }
+
+ /* horizontal axis */
+ axis_angle_to_quat(quat_mul, rv3d->viewinv[0], angle);
+ }
+
+ mul_qt_qtqt(quat_new, rv3d->viewquat, quat_mul);
+
+ /* avoid precision loss over time */
+ normalize_qt(quat_new);
+
+ 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);
+ }
+ else {
+ rv3d->view = RV3D_VIEW_USER;
+ }
+
+ float dyn_ofs[3], *dyn_ofs_pt = NULL;
+
+ if (U.uiflag & USER_ORBIT_SELECTION) {
+ if (view3d_orbit_calc_center(C, dyn_ofs)) {
+ negate_v3(dyn_ofs);
+ dyn_ofs_pt = dyn_ofs;
+ }
+ }
+
+ ED_view3d_smooth_view(C,
+ v3d,
+ ar,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .quat = quat_new,
+ .dyn_ofs = dyn_ofs_pt,
+ });
+
+ return OPERATOR_FINISHED;
+ }
+ }
+
+ return OPERATOR_CANCELLED;
}
void VIEW3D_OT_view_orbit(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "View Orbit";
- ot->description = "Orbit the view";
- ot->idname = "VIEW3D_OT_view_orbit";
+ /* identifiers */
+ ot->name = "View Orbit";
+ ot->description = "Orbit the view";
+ ot->idname = "VIEW3D_OT_view_orbit";
- /* api callbacks */
- ot->exec = vieworbit_exec;
- ot->poll = ED_operator_rv3d_user_region_poll;
+ /* api callbacks */
+ ot->exec = vieworbit_exec;
+ ot->poll = ED_operator_rv3d_user_region_poll;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
- /* properties */
- prop = RNA_def_float(ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ prop = RNA_def_float(ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- ot->prop = RNA_def_enum(ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit");
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit");
}
/** \} */
@@ -4139,253 +4216,265 @@ void VIEW3D_OT_view_orbit(wmOperatorType *ot)
/** \name View Roll Operator
* \{ */
-static void view_roll_angle(ARegion *ar, float quat[4], const float orig_quat[4], const float dvec[3], float angle)
+static void view_roll_angle(
+ ARegion *ar, float quat[4], const float orig_quat[4], const float dvec[3], float angle)
{
- RegionView3D *rv3d = ar->regiondata;
- float quat_mul[4];
+ RegionView3D *rv3d = ar->regiondata;
+ float quat_mul[4];
- /* camera axis */
- axis_angle_normalized_to_quat(quat_mul, dvec, angle);
+ /* camera axis */
+ axis_angle_normalized_to_quat(quat_mul, dvec, angle);
- mul_qt_qtqt(quat, orig_quat, quat_mul);
+ mul_qt_qtqt(quat, orig_quat, quat_mul);
- /* avoid precision loss over time */
- normalize_qt(quat);
+ /* avoid precision loss over time */
+ normalize_qt(quat);
- rv3d->view = RV3D_VIEW_USER;
+ rv3d->view = RV3D_VIEW_USER;
}
static void viewroll_apply(ViewOpsData *vod, int x, int UNUSED(y))
{
- float angle = 0.0;
+ float angle = 0.0;
- {
- float len1, len2, tot;
+ {
+ 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;
- angle = (len1 - len2) * (float)M_PI * 4.0f;
- }
+ 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;
+ 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);
- }
+ if (angle != 0.0f) {
+ view_roll_angle(vod->ar, vod->rv3d->viewquat, vod->init.quat, vod->init.mousevec, angle);
+ }
- if (vod->use_dyn_ofs) {
- view3d_orbit_apply_dyn_ofs(vod->rv3d->ofs, vod->init.ofs, vod->init.quat, vod->rv3d->viewquat, vod->dyn_ofs);
- }
+ if (vod->use_dyn_ofs) {
+ view3d_orbit_apply_dyn_ofs(
+ 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 (vod->rv3d->viewlock & RV3D_BOXVIEW) {
+ view3d_boxview_sync(vod->sa, vod->ar);
+ }
- ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
- ED_region_tag_redraw(vod->ar);
+ ED_region_tag_redraw(vod->ar);
}
static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewOpsData *vod = op->customdata;
- short event_code = VIEW_PASS;
- bool use_autokey = false;
- int ret = OPERATOR_RUNNING_MODAL;
-
- /* execute the events */
- if (event->type == MOUSEMOVE) {
- event_code = VIEW_APPLY;
- }
- else if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case VIEW_MODAL_CONFIRM:
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_SWITCH_MOVE:
- WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_SWITCH_ROTATE:
- WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- }
- }
- else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
- event_code = VIEW_CONFIRM;
- }
-
- if (event_code == VIEW_APPLY) {
- viewroll_apply(vod, event->x, event->y);
- if (ED_screen_animation_playing(CTX_wm_manager(C))) {
- use_autokey = true;
- }
- }
- else if (event_code == VIEW_CONFIRM) {
- ED_view3d_depth_tag_update(vod->rv3d);
- use_autokey = true;
- ret = OPERATOR_FINISHED;
- }
-
- if (use_autokey) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, false);
- }
-
- if (ret & OPERATOR_FINISHED) {
- viewops_data_free(C, op);
- }
-
- return ret;
+ ViewOpsData *vod = op->customdata;
+ short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
+
+ /* execute the events */
+ if (event->type == MOUSEMOVE) {
+ event_code = VIEW_APPLY;
+ }
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case VIEW_MODAL_CONFIRM:
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_MOVE:
+ WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_ROTATE:
+ WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ }
+ }
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
+ event_code = VIEW_CONFIRM;
+ }
+
+ if (event_code == VIEW_APPLY) {
+ viewroll_apply(vod, event->x, event->y);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
+ }
+ else if (event_code == VIEW_CONFIRM) {
+ ED_view3d_depth_tag_update(vod->rv3d);
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
+
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, false);
+ }
+
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op);
+ }
+
+ return ret;
}
static const EnumPropertyItem prop_view_roll_items[] = {
- {0, "ANGLE", 0, "Roll Angle", "Roll the view using an angle value"},
- {V3D_VIEW_STEPLEFT, "LEFT", 0, "Roll Left", "Roll the view around to the Left"},
- {V3D_VIEW_STEPRIGHT, "RIGHT", 0, "Roll Right", "Roll the view around to the Right"},
- {0, NULL, 0, NULL, NULL},
+ {0, "ANGLE", 0, "Roll Angle", "Roll the view using an angle value"},
+ {V3D_VIEW_STEPLEFT, "LEFT", 0, "Roll Left", "Roll the view around to the Left"},
+ {V3D_VIEW_STEPRIGHT, "RIGHT", 0, "Roll Right", "Roll the view around to the Right"},
+ {0, NULL, 0, NULL, NULL},
};
-
static int viewroll_exec(bContext *C, wmOperator *op)
{
- View3D *v3d;
- RegionView3D *rv3d;
- ARegion *ar;
-
- if (op->customdata) {
- ViewOpsData *vod = op->customdata;
- ar = vod->ar;
- v3d = vod->v3d;
- }
- else {
- ED_view3d_context_user_region(C, &v3d, &ar);
- }
-
- rv3d = ar->regiondata;
- if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
-
- ED_view3d_smooth_view_force_finish(C, v3d, ar);
-
- int type = RNA_enum_get(op->ptr, "type");
- float angle = (type == 0) ? RNA_float_get(op->ptr, "angle") : DEG2RADF(U.pad_rot_angle);
- float mousevec[3];
- float quat_new[4];
-
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
-
- if (type == V3D_VIEW_STEPLEFT) {
- angle = -angle;
- }
-
- normalize_v3_v3(mousevec, rv3d->viewinv[2]);
- negate_v3(mousevec);
- view_roll_angle(ar, quat_new, rv3d->viewquat, mousevec, angle);
-
- const float *dyn_ofs_pt = NULL;
- float dyn_ofs[3];
- if (U.uiflag & USER_ORBIT_SELECTION) {
- if (view3d_orbit_calc_center(C, dyn_ofs)) {
- negate_v3(dyn_ofs);
- dyn_ofs_pt = dyn_ofs;
- }
- }
-
- ED_view3d_smooth_view(
- C, v3d, ar, smooth_viewtx,
- &(const V3D_SmoothParams) { .quat = quat_new, .dyn_ofs = dyn_ofs_pt, });
-
- viewops_data_free(C, op);
- return OPERATOR_FINISHED;
- }
- else {
- viewops_data_free(C, op);
- return OPERATOR_CANCELLED;
- }
+ View3D *v3d;
+ RegionView3D *rv3d;
+ ARegion *ar;
+
+ if (op->customdata) {
+ ViewOpsData *vod = op->customdata;
+ ar = vod->ar;
+ v3d = vod->v3d;
+ }
+ else {
+ ED_view3d_context_user_region(C, &v3d, &ar);
+ }
+
+ rv3d = ar->regiondata;
+ if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
+
+ ED_view3d_smooth_view_force_finish(C, v3d, ar);
+
+ int type = RNA_enum_get(op->ptr, "type");
+ float angle = (type == 0) ? RNA_float_get(op->ptr, "angle") : DEG2RADF(U.pad_rot_angle);
+ float mousevec[3];
+ float quat_new[4];
+
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+
+ if (type == V3D_VIEW_STEPLEFT) {
+ angle = -angle;
+ }
+
+ normalize_v3_v3(mousevec, rv3d->viewinv[2]);
+ negate_v3(mousevec);
+ view_roll_angle(ar, quat_new, rv3d->viewquat, mousevec, angle);
+
+ const float *dyn_ofs_pt = NULL;
+ float dyn_ofs[3];
+ if (U.uiflag & USER_ORBIT_SELECTION) {
+ if (view3d_orbit_calc_center(C, dyn_ofs)) {
+ negate_v3(dyn_ofs);
+ dyn_ofs_pt = dyn_ofs;
+ }
+ }
+
+ ED_view3d_smooth_view(C,
+ v3d,
+ ar,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .quat = quat_new,
+ .dyn_ofs = dyn_ofs_pt,
+ });
+
+ viewops_data_free(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ viewops_data_free(C, op);
+ return OPERATOR_CANCELLED;
+ }
}
static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewOpsData *vod;
+ ViewOpsData *vod;
- bool use_angle = RNA_enum_get(op->ptr, "type") != 0;
+ bool use_angle = RNA_enum_get(op->ptr, "type") != 0;
- if (use_angle || RNA_struct_property_is_set(op->ptr, "angle")) {
- viewroll_exec(C, op);
- }
- else {
- /* makes op->customdata */
- viewops_data_alloc(C, op);
- viewops_data_create(C, op, event, viewops_flag_from_prefs());
- vod = op->customdata;
+ if (use_angle || RNA_struct_property_is_set(op->ptr, "angle")) {
+ viewroll_exec(C, op);
+ }
+ else {
+ /* makes op->customdata */
+ viewops_data_alloc(C, op);
+ 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->ar);
- /* overwrite the mouse vector with the view direction */
- normalize_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]);
- negate_v3(vod->init.mousevec);
+ /* overwrite the mouse vector with the view direction */
+ normalize_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]);
+ negate_v3(vod->init.mousevec);
- if (event->type == MOUSEROTATE) {
- vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x;
- viewroll_apply(vod, event->prevx, event->prevy);
- ED_view3d_depth_tag_update(vod->rv3d);
+ if (event->type == MOUSEROTATE) {
+ vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x;
+ viewroll_apply(vod, event->prevx, event->prevy);
+ ED_view3d_depth_tag_update(vod->rv3d);
- viewops_data_free(C, op);
- return OPERATOR_FINISHED;
- }
- else {
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
+ viewops_data_free(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
- }
- }
- return OPERATOR_FINISHED;
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+ return OPERATOR_FINISHED;
}
static void viewroll_cancel(bContext *C, wmOperator *op)
{
- viewops_data_free(C, op);
+ viewops_data_free(C, op);
}
void VIEW3D_OT_view_roll(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "View Roll";
- ot->description = "Roll the view";
- ot->idname = "VIEW3D_OT_view_roll";
+ /* identifiers */
+ ot->name = "View Roll";
+ ot->description = "Roll the view";
+ ot->idname = "VIEW3D_OT_view_roll";
- /* api callbacks */
- ot->invoke = viewroll_invoke;
- ot->exec = viewroll_exec;
- ot->modal = viewroll_modal;
- ot->poll = ED_operator_rv3d_user_region_poll;
- ot->cancel = viewroll_cancel;
+ /* api callbacks */
+ ot->invoke = viewroll_invoke;
+ ot->exec = viewroll_exec;
+ ot->modal = viewroll_modal;
+ ot->poll = ED_operator_rv3d_user_region_poll;
+ ot->cancel = viewroll_cancel;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
- /* properties */
- ot->prop = prop = RNA_def_float(ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_enum(ot->srna, "type", prop_view_roll_items, 0, "Roll Angle Source", "How roll angle is calculated");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ ot->prop = prop = RNA_def_float(
+ ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_enum(ot->srna,
+ "type",
+ prop_view_roll_items,
+ 0,
+ "Roll Angle Source",
+ "How roll angle is calculated");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
enum {
- V3D_VIEW_PANLEFT = 1,
- V3D_VIEW_PANRIGHT,
- V3D_VIEW_PANDOWN,
- V3D_VIEW_PANUP,
+ V3D_VIEW_PANLEFT = 1,
+ V3D_VIEW_PANRIGHT,
+ V3D_VIEW_PANDOWN,
+ V3D_VIEW_PANUP,
};
static const EnumPropertyItem prop_view_pan_items[] = {
- {V3D_VIEW_PANLEFT, "PANLEFT", 0, "Pan Left", "Pan the view to the Left"},
- {V3D_VIEW_PANRIGHT, "PANRIGHT", 0, "Pan Right", "Pan the view to the Right"},
- {V3D_VIEW_PANUP, "PANUP", 0, "Pan Up", "Pan the view Up"},
- {V3D_VIEW_PANDOWN, "PANDOWN", 0, "Pan Down", "Pan the view Down"},
- {0, NULL, 0, NULL, NULL},
+ {V3D_VIEW_PANLEFT, "PANLEFT", 0, "Pan Left", "Pan the view to the Left"},
+ {V3D_VIEW_PANRIGHT, "PANRIGHT", 0, "Pan Right", "Pan the view to the Right"},
+ {V3D_VIEW_PANUP, "PANUP", 0, "Pan Up", "Pan the view Up"},
+ {V3D_VIEW_PANDOWN, "PANDOWN", 0, "Pan Down", "Pan the view Down"},
+ {0, NULL, 0, NULL, NULL},
};
/** \} */
@@ -4398,42 +4487,51 @@ static const EnumPropertyItem prop_view_pan_items[] = {
static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- int x = 0, y = 0;
- int pandir = RNA_enum_get(op->ptr, "type");
+ int x = 0, y = 0;
+ int pandir = RNA_enum_get(op->ptr, "type");
- if (pandir == V3D_VIEW_PANRIGHT) { x = -32; }
- else if (pandir == V3D_VIEW_PANLEFT) { x = 32; }
- else if (pandir == V3D_VIEW_PANUP) { y = -25; }
- else if (pandir == V3D_VIEW_PANDOWN) { y = 25; }
+ if (pandir == V3D_VIEW_PANRIGHT) {
+ x = -32;
+ }
+ else if (pandir == V3D_VIEW_PANLEFT) {
+ x = 32;
+ }
+ else if (pandir == V3D_VIEW_PANUP) {
+ y = -25;
+ }
+ else if (pandir == V3D_VIEW_PANDOWN) {
+ y = 25;
+ }
- viewops_data_alloc(C, op);
- viewops_data_create(C, op, event, (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT));
- ViewOpsData *vod = op->customdata;
+ viewops_data_alloc(C, op);
+ viewops_data_create(C, op, event, (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT));
+ ViewOpsData *vod = op->customdata;
- viewmove_apply(vod, vod->prev.event_xy[0] + x, vod->prev.event_xy[1] + y);
+ viewmove_apply(vod, vod->prev.event_xy[0] + x, vod->prev.event_xy[1] + y);
- ED_view3d_depth_tag_update(vod->rv3d);
- viewops_data_free(C, op);
+ ED_view3d_depth_tag_update(vod->rv3d);
+ viewops_data_free(C, op);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_view_pan(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Pan View Direction";
- ot->description = "Pan the view in a given direction";
- ot->idname = "VIEW3D_OT_view_pan";
+ /* identifiers */
+ ot->name = "Pan View Direction";
+ ot->description = "Pan the view in a given direction";
+ ot->idname = "VIEW3D_OT_view_pan";
- /* api callbacks */
- ot->invoke = viewpan_invoke;
- ot->poll = ED_operator_region_view3d_active;
+ /* api callbacks */
+ ot->invoke = viewpan_invoke;
+ ot->poll = ED_operator_region_view3d_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
- /* Properties */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_view_pan_items, 0, "Pan", "Direction of View Pan");
+ /* Properties */
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", prop_view_pan_items, 0, "Pan", "Direction of View Pan");
}
/** \} */
@@ -4444,40 +4542,40 @@ void VIEW3D_OT_view_pan(wmOperatorType *ot)
static int viewpersportho_exec(bContext *C, wmOperator *UNUSED(op))
{
- View3D *v3d_dummy;
- ARegion *ar;
- RegionView3D *rv3d;
+ View3D *v3d_dummy;
+ ARegion *ar;
+ RegionView3D *rv3d;
- /* no NULL check is needed, poll checks */
- ED_view3d_context_user_region(C, &v3d_dummy, &ar);
- rv3d = ar->regiondata;
+ /* no NULL check is needed, poll checks */
+ ED_view3d_context_user_region(C, &v3d_dummy, &ar);
+ rv3d = ar->regiondata;
- if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
- if (rv3d->persp != RV3D_ORTHO) {
- rv3d->persp = RV3D_ORTHO;
- }
- else {
- rv3d->persp = RV3D_PERSP;
- }
- ED_region_tag_redraw(ar);
- }
+ if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
+ if (rv3d->persp != RV3D_ORTHO) {
+ rv3d->persp = RV3D_ORTHO;
+ }
+ else {
+ rv3d->persp = RV3D_PERSP;
+ }
+ ED_region_tag_redraw(ar);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_view_persportho(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Persp/Ortho";
- ot->description = "Switch the current view from perspective/orthographic projection";
- ot->idname = "VIEW3D_OT_view_persportho";
+ /* identifiers */
+ ot->name = "View Persp/Ortho";
+ ot->description = "Switch the current view from perspective/orthographic projection";
+ ot->idname = "VIEW3D_OT_view_persportho";
- /* api callbacks */
- ot->exec = viewpersportho_exec;
- ot->poll = ED_operator_rv3d_user_region_poll;
+ /* api callbacks */
+ ot->exec = viewpersportho_exec;
+ ot->poll = ED_operator_rv3d_user_region_poll;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
/** \} */
@@ -4488,33 +4586,36 @@ void VIEW3D_OT_view_persportho(wmOperatorType *ot)
* Wraps walk/fly modes.
* \{ */
-static int view3d_navigate_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
+static int view3d_navigate_invoke(bContext *C,
+ wmOperator *UNUSED(op),
+ const wmEvent *UNUSED(event))
{
- eViewNavigation_Method mode = U.navigation_mode;
+ eViewNavigation_Method mode = U.navigation_mode;
- switch (mode) {
- case VIEW_NAVIGATION_FLY:
- WM_operator_name_call(C, "VIEW3D_OT_fly", WM_OP_INVOKE_DEFAULT, NULL);
- break;
- case VIEW_NAVIGATION_WALK:
- default:
- WM_operator_name_call(C, "VIEW3D_OT_walk", WM_OP_INVOKE_DEFAULT, NULL);
- break;
- }
+ switch (mode) {
+ case VIEW_NAVIGATION_FLY:
+ WM_operator_name_call(C, "VIEW3D_OT_fly", WM_OP_INVOKE_DEFAULT, NULL);
+ break;
+ case VIEW_NAVIGATION_WALK:
+ default:
+ WM_operator_name_call(C, "VIEW3D_OT_walk", WM_OP_INVOKE_DEFAULT, NULL);
+ break;
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_navigate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Navigation";
- ot->description = "Interactively navigate around the scene (uses the mode (walk/fly) preference)";
- ot->idname = "VIEW3D_OT_navigate";
+ /* identifiers */
+ ot->name = "View Navigation";
+ ot->description =
+ "Interactively navigate around the scene (uses the mode (walk/fly) preference)";
+ ot->idname = "VIEW3D_OT_navigate";
- /* api callbacks */
- ot->invoke = view3d_navigate_invoke;
- ot->poll = ED_operator_view3d_active;
+ /* api callbacks */
+ ot->invoke = view3d_navigate_invoke;
+ ot->poll = ED_operator_view3d_active;
}
/** \} */
@@ -4523,76 +4624,79 @@ void VIEW3D_OT_navigate(wmOperatorType *ot)
/** \name Background Image Add Operator
* \{ */
-
static Camera *background_image_camera_from_context(bContext *C)
{
- /* Needed to support drag-and-drop & camera buttons context. */
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d != NULL) {
- if (v3d->camera && v3d->camera->data && v3d->camera->type == OB_CAMERA) {
- return v3d->camera->data;
- }
- return NULL;
- }
- else {
- return CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
- }
+ /* Needed to support drag-and-drop & camera buttons context. */
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d != NULL) {
+ if (v3d->camera && v3d->camera->data && v3d->camera->type == OB_CAMERA) {
+ return v3d->camera->data;
+ }
+ return NULL;
+ }
+ else {
+ return CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
+ }
}
static int background_image_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Camera *cam = background_image_camera_from_context(C);
- BKE_camera_background_image_new(cam);
+ Camera *cam = background_image_camera_from_context(C);
+ BKE_camera_background_image_new(cam);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Camera *cam = background_image_camera_from_context(C);
- Image *ima;
- CameraBGImage *bgpic;
+ Camera *cam = background_image_camera_from_context(C);
+ Image *ima;
+ CameraBGImage *bgpic;
- ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
- /* may be NULL, continue anyway */
+ ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
+ /* may be NULL, continue anyway */
- bgpic = BKE_camera_background_image_new(cam);
- bgpic->ima = ima;
+ bgpic = BKE_camera_background_image_new(cam);
+ bgpic->ima = ima;
- cam->flag |= CAM_SHOW_BG_IMAGE;
+ cam->flag |= CAM_SHOW_BG_IMAGE;
- WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
+ WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static bool background_image_add_poll(bContext *C)
{
- return background_image_camera_from_context(C) != NULL;
+ return background_image_camera_from_context(C) != NULL;
}
void VIEW3D_OT_background_image_add(wmOperatorType *ot)
{
- /* identifiers */
- /* note: having key shortcut here is bad practice,
- * but for now keep because this displays when dragging an image over the 3D viewport */
- ot->name = "Add Background Image";
- ot->description = "Add a new background image";
- ot->idname = "VIEW3D_OT_background_image_add";
+ /* identifiers */
+ /* note: having key shortcut here is bad practice,
+ * but for now keep because this displays when dragging an image over the 3D viewport */
+ ot->name = "Add Background Image";
+ ot->description = "Add a new background image";
+ ot->idname = "VIEW3D_OT_background_image_add";
- /* api callbacks */
- ot->invoke = background_image_add_invoke;
- ot->exec = background_image_add_exec;
- ot->poll = background_image_add_poll;
+ /* api callbacks */
+ ot->invoke = background_image_add_invoke;
+ ot->exec = background_image_add_exec;
+ ot->poll = background_image_add_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- /* properties */
- RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Image name to assign");
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+ /* properties */
+ RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Image name to assign");
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
}
/** \} */
@@ -4603,44 +4707,45 @@ void VIEW3D_OT_background_image_add(wmOperatorType *ot)
static int background_image_remove_exec(bContext *C, wmOperator *op)
{
- Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
- const int index = RNA_int_get(op->ptr, "index");
- CameraBGImage *bgpic_rem = BLI_findlink(&cam->bg_images, index);
+ Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
+ const int index = RNA_int_get(op->ptr, "index");
+ CameraBGImage *bgpic_rem = BLI_findlink(&cam->bg_images, index);
- if (bgpic_rem) {
- if (bgpic_rem->source == CAM_BGIMG_SOURCE_IMAGE) {
- id_us_min((ID *)bgpic_rem->ima);
- }
- else if (bgpic_rem->source == CAM_BGIMG_SOURCE_MOVIE) {
- id_us_min((ID *)bgpic_rem->clip);
- }
+ if (bgpic_rem) {
+ if (bgpic_rem->source == CAM_BGIMG_SOURCE_IMAGE) {
+ id_us_min((ID *)bgpic_rem->ima);
+ }
+ else if (bgpic_rem->source == CAM_BGIMG_SOURCE_MOVIE) {
+ id_us_min((ID *)bgpic_rem->clip);
+ }
- BKE_camera_background_image_remove(cam, bgpic_rem);
+ BKE_camera_background_image_remove(cam, bgpic_rem);
- WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void VIEW3D_OT_background_image_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Background Image";
- ot->description = "Remove a background image from the 3D view";
- ot->idname = "VIEW3D_OT_background_image_remove";
+ /* identifiers */
+ ot->name = "Remove Background Image";
+ ot->description = "Remove a background image from the 3D view";
+ ot->idname = "VIEW3D_OT_background_image_remove";
- /* api callbacks */
- ot->exec = background_image_remove_exec;
- ot->poll = ED_operator_camera;
+ /* api callbacks */
+ ot->exec = background_image_remove_exec;
+ ot->poll = ED_operator_camera;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
- /* properties */
- RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Background image index to remove", 0, INT_MAX);
+ /* properties */
+ RNA_def_int(
+ ot->srna, "index", 0, 0, INT_MAX, "Index", "Background image index to remove", 0, INT_MAX);
}
/** \} */
@@ -4653,83 +4758,83 @@ void VIEW3D_OT_background_image_remove(wmOperatorType *ot)
static void calc_local_clipping(float clip_local[6][4], BoundBox *clipbb, float mat[4][4])
{
- BoundBox clipbb_local;
- float imat[4][4];
- int i;
+ BoundBox clipbb_local;
+ float imat[4][4];
+ int i;
- invert_m4_m4(imat, mat);
+ invert_m4_m4(imat, mat);
- for (i = 0; i < 8; i++) {
- mul_v3_m4v3(clipbb_local.vec[i], imat, clipbb->vec[i]);
- }
+ for (i = 0; i < 8; i++) {
+ mul_v3_m4v3(clipbb_local.vec[i], imat, clipbb->vec[i]);
+ }
- ED_view3d_clipping_calc_from_boundbox(clip_local, &clipbb_local, is_negative_m4(mat));
+ ED_view3d_clipping_calc_from_boundbox(clip_local, &clipbb_local, is_negative_m4(mat));
}
void ED_view3d_clipping_local(RegionView3D *rv3d, float mat[4][4])
{
- if (rv3d->rflag & RV3D_CLIPPING) {
- calc_local_clipping(rv3d->clip_local, rv3d->clipbb, mat);
- }
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ calc_local_clipping(rv3d->clip_local, rv3d->clipbb, mat);
+ }
}
static int view3d_clipping_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- rcti rect;
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ rcti rect;
- WM_operator_properties_border_to_rcti(op, &rect);
+ WM_operator_properties_border_to_rcti(op, &rect);
- rv3d->rflag |= RV3D_CLIPPING;
- rv3d->clipbb = MEM_callocN(sizeof(BoundBox), "clipbb");
+ rv3d->rflag |= RV3D_CLIPPING;
+ 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);
+ /* NULL object because we don't want it in object space */
+ ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, ar, NULL, &rect);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
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);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
- if (rv3d->rflag & RV3D_CLIPPING) {
- rv3d->rflag &= ~RV3D_CLIPPING;
- ED_region_tag_redraw(ar);
- if (rv3d->clipbb) {
- MEM_freeN(rv3d->clipbb);
- }
- rv3d->clipbb = NULL;
- return OPERATOR_FINISHED;
- }
- else {
- return WM_gesture_box_invoke(C, op, event);
- }
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ rv3d->rflag &= ~RV3D_CLIPPING;
+ ED_region_tag_redraw(ar);
+ if (rv3d->clipbb) {
+ MEM_freeN(rv3d->clipbb);
+ }
+ rv3d->clipbb = NULL;
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return WM_gesture_box_invoke(C, op, event);
+ }
}
void VIEW3D_OT_clip_border(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clipping Region";
- ot->description = "Set the view clipping region";
- ot->idname = "VIEW3D_OT_clip_border";
+ /* identifiers */
+ ot->name = "Clipping Region";
+ ot->description = "Set the view clipping region";
+ ot->idname = "VIEW3D_OT_clip_border";
- /* api callbacks */
- ot->invoke = view3d_clipping_invoke;
- ot->exec = view3d_clipping_exec;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
+ /* api callbacks */
+ ot->invoke = view3d_clipping_invoke;
+ ot->exec = view3d_clipping_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
- ot->poll = ED_operator_region_view3d_active;
+ ot->poll = ED_operator_region_view3d_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
- /* properties */
- WM_operator_properties_border(ot);
+ /* properties */
+ WM_operator_properties_border(ot);
}
/** \} */
@@ -4740,263 +4845,273 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot)
/* cursor position in vec, result in vec, mval in region coords */
/* note: cannot use event->mval here (called by object_add() */
-void ED_view3d_cursor3d_position(bContext *C, const int mval[2], const bool use_depth, float cursor_co[3])
-{
- ARegion *ar = CTX_wm_region(C);
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = ar->regiondata;
- bool flip;
- bool depth_used = false;
-
- /* normally the caller should ensure this,
- * but this is called from areas that aren't already dealing with the viewport */
- if (rv3d == NULL) {
- return;
- }
-
- ED_view3d_calc_zfac(rv3d, cursor_co, &flip);
-
- /* reset the depth based on the view offset (we _know_ the offset is infront of us) */
- if (flip) {
- negate_v3_v3(cursor_co, rv3d->ofs);
- /* re initialize, no need to check flip again */
- ED_view3d_calc_zfac(rv3d, cursor_co, NULL /* &flip */ );
- }
-
- if (use_depth) { /* maybe this should be accessed some other way */
- struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
-
- view3d_operator_needs_opengl(C);
- if (ED_view3d_autodist(depsgraph, ar, v3d, mval, cursor_co, true, NULL)) {
- depth_used = true;
- }
- }
-
- 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);
- }
-}
-
-void ED_view3d_cursor3d_position_rotation(
- bContext *C, const int mval[2],
- const bool use_depth, enum eV3DCursorOrient orientation,
- float cursor_co[3], float cursor_quat[4])
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
-
- /* XXX, caller should check. */
- if (rv3d == NULL) {
- return;
- }
-
- ED_view3d_cursor3d_position(C, mval, use_depth, cursor_co);
-
- if (orientation == V3D_CURSOR_ORIENT_NONE) {
- /* pass */
- }
- else if (orientation == V3D_CURSOR_ORIENT_VIEW) {
- copy_qt_qt(cursor_quat, rv3d->viewquat);
- cursor_quat[0] *= -1.0f;
- }
- else if (orientation == V3D_CURSOR_ORIENT_XFORM) {
- float mat[3][3];
- ED_transform_calc_orientation_from_type(C, mat);
- mat3_to_quat(cursor_quat, mat);
- }
- else if (orientation == V3D_CURSOR_ORIENT_GEOM) {
- copy_qt_qt(cursor_quat, rv3d->viewquat);
- cursor_quat[0] *= -1.0f;
-
- const float mval_fl[2] = {UNPACK2(mval)};
- float ray_no[3];
- float ray_co[3];
-
- struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- bmain, scene, CTX_data_depsgraph(C), 0, ar, v3d);
-
- float obmat[4][4];
- Object *ob_dummy = NULL;
- float dist_px = 0;
- if (ED_transform_snap_object_project_view3d_ex(
- snap_context,
- SCE_SNAP_MODE_FACE,
- &(const struct SnapObjectParams){
- .snap_select = SNAP_ALL,
- .use_object_edit_cage = false,
- },
- mval_fl, &dist_px,
- ray_co, ray_no, NULL,
- &ob_dummy, obmat))
- {
- if (use_depth) {
- copy_v3_v3(cursor_co, ray_co);
- }
-
- float tquat[4];
-
- /* Math normal (Z). */
- {
- float z_src[3] = {0, 0, 1};
- mul_qt_v3(cursor_quat, z_src);
- rotation_between_vecs_to_quat(tquat, z_src, ray_no);
- mul_qt_qtqt(cursor_quat, tquat, cursor_quat);
- }
-
- /* Match object matrix (X). */
- {
- const float ortho_axis_dot[3] = {
- dot_v3v3(ray_no, obmat[0]),
- dot_v3v3(ray_no, obmat[1]),
- dot_v3v3(ray_no, obmat[2]),
- };
- const int ortho_axis = axis_dominant_v3_ortho_single(ortho_axis_dot);
- float x_src[3] = {1, 0, 0};
- float x_dst[3];
- mul_qt_v3(cursor_quat, x_src);
- project_plane_v3_v3v3(x_dst, obmat[ortho_axis], ray_no);
- normalize_v3(x_dst);
- rotation_between_vecs_to_quat(tquat, x_src, x_dst);
- mul_qt_qtqt(cursor_quat, tquat, cursor_quat);
- }
- }
- ED_transform_snap_object_context_destroy(snap_context);
- }
-}
-
-void ED_view3d_cursor3d_update(
- bContext *C, const int mval[2],
- const bool use_depth, enum eV3DCursorOrient orientation)
-{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
-
- View3DCursor *cursor_curr = &scene->cursor;
- View3DCursor cursor_prev = *cursor_curr;
-
- {
- float quat[4], quat_prev[4];
- BKE_scene_cursor_rot_to_quat(cursor_curr, quat);
- copy_qt_qt(quat_prev, quat);
- ED_view3d_cursor3d_position_rotation(
- C, mval,
- use_depth, orientation,
- cursor_curr->location, quat);
-
- if (!equals_v4v4(quat_prev, quat)) {
- if ((cursor_curr->rotation_mode == ROT_MODE_AXISANGLE) &&
- RV3D_VIEW_IS_AXIS(rv3d->view))
- {
- float tmat[3][3], cmat[3][3];
- quat_to_mat3(tmat, quat);
- negate_v3_v3(cursor_curr->rotation_axis, tmat[2]);
- axis_angle_to_mat3(cmat, cursor_curr->rotation_axis, 0.0f);
- cursor_curr->rotation_angle = angle_signed_on_axis_v3v3_v3(cmat[0], tmat[0], cursor_curr->rotation_axis);
- }
- else {
- BKE_scene_cursor_quat_to_rot(cursor_curr, quat, true);
- }
- }
- }
-
- /* offset the cursor lock to avoid jumping to new offset */
- if (v3d->ob_centre_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) &&
- (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);
- }
- }
- else {
- /* Cursor may be outside of the view,
- * prevent it getting 'lost', see: T40353 & T45301 */
- zero_v2(rv3d->ofs_lock);
- }
- }
-
- if (v3d->localvd) {
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
- }
- else {
- WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
- }
-
- {
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- wmMsgParams_RNA msg_key_params = {{{0}}};
- RNA_pointer_create(&scene->id, &RNA_View3DCursor, &scene->cursor, &msg_key_params.ptr);
- WM_msg_publish_rna_params(mbus, &msg_key_params);
- }
-
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+void ED_view3d_cursor3d_position(bContext *C,
+ const int mval[2],
+ const bool use_depth,
+ float cursor_co[3])
+{
+ ARegion *ar = CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = ar->regiondata;
+ bool flip;
+ bool depth_used = false;
+
+ /* normally the caller should ensure this,
+ * but this is called from areas that aren't already dealing with the viewport */
+ if (rv3d == NULL) {
+ return;
+ }
+
+ ED_view3d_calc_zfac(rv3d, cursor_co, &flip);
+
+ /* reset the depth based on the view offset (we _know_ the offset is infront of us) */
+ if (flip) {
+ negate_v3_v3(cursor_co, rv3d->ofs);
+ /* re initialize, no need to check flip again */
+ ED_view3d_calc_zfac(rv3d, cursor_co, NULL /* &flip */);
+ }
+
+ if (use_depth) { /* maybe this should be accessed some other way */
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
+ view3d_operator_needs_opengl(C);
+ if (ED_view3d_autodist(depsgraph, ar, v3d, mval, cursor_co, true, NULL)) {
+ depth_used = true;
+ }
+ }
+
+ 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);
+ }
+}
+
+void ED_view3d_cursor3d_position_rotation(bContext *C,
+ const int mval[2],
+ const bool use_depth,
+ enum eV3DCursorOrient orientation,
+ float cursor_co[3],
+ float cursor_quat[4])
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ /* XXX, caller should check. */
+ if (rv3d == NULL) {
+ return;
+ }
+
+ ED_view3d_cursor3d_position(C, mval, use_depth, cursor_co);
+
+ if (orientation == V3D_CURSOR_ORIENT_NONE) {
+ /* pass */
+ }
+ else if (orientation == V3D_CURSOR_ORIENT_VIEW) {
+ copy_qt_qt(cursor_quat, rv3d->viewquat);
+ cursor_quat[0] *= -1.0f;
+ }
+ else if (orientation == V3D_CURSOR_ORIENT_XFORM) {
+ float mat[3][3];
+ ED_transform_calc_orientation_from_type(C, mat);
+ mat3_to_quat(cursor_quat, mat);
+ }
+ else if (orientation == V3D_CURSOR_ORIENT_GEOM) {
+ copy_qt_qt(cursor_quat, rv3d->viewquat);
+ cursor_quat[0] *= -1.0f;
+
+ const float mval_fl[2] = {UNPACK2(mval)};
+ float ray_no[3];
+ float ray_co[3];
+
+ struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
+ bmain, scene, CTX_data_depsgraph(C), 0, ar, v3d);
+
+ float obmat[4][4];
+ Object *ob_dummy = NULL;
+ float dist_px = 0;
+ if (ED_transform_snap_object_project_view3d_ex(snap_context,
+ SCE_SNAP_MODE_FACE,
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ .use_object_edit_cage = false,
+ },
+ mval_fl,
+ &dist_px,
+ ray_co,
+ ray_no,
+ NULL,
+ &ob_dummy,
+ obmat)) {
+ if (use_depth) {
+ copy_v3_v3(cursor_co, ray_co);
+ }
+
+ float tquat[4];
+
+ /* Math normal (Z). */
+ {
+ float z_src[3] = {0, 0, 1};
+ mul_qt_v3(cursor_quat, z_src);
+ rotation_between_vecs_to_quat(tquat, z_src, ray_no);
+ mul_qt_qtqt(cursor_quat, tquat, cursor_quat);
+ }
+
+ /* Match object matrix (X). */
+ {
+ const float ortho_axis_dot[3] = {
+ dot_v3v3(ray_no, obmat[0]),
+ dot_v3v3(ray_no, obmat[1]),
+ dot_v3v3(ray_no, obmat[2]),
+ };
+ const int ortho_axis = axis_dominant_v3_ortho_single(ortho_axis_dot);
+ float x_src[3] = {1, 0, 0};
+ float x_dst[3];
+ mul_qt_v3(cursor_quat, x_src);
+ project_plane_v3_v3v3(x_dst, obmat[ortho_axis], ray_no);
+ normalize_v3(x_dst);
+ rotation_between_vecs_to_quat(tquat, x_src, x_dst);
+ mul_qt_qtqt(cursor_quat, tquat, cursor_quat);
+ }
+ }
+ ED_transform_snap_object_context_destroy(snap_context);
+ }
+}
+
+void ED_view3d_cursor3d_update(bContext *C,
+ const int mval[2],
+ const bool use_depth,
+ enum eV3DCursorOrient orientation)
+{
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ View3DCursor *cursor_curr = &scene->cursor;
+ View3DCursor cursor_prev = *cursor_curr;
+
+ {
+ float quat[4], quat_prev[4];
+ BKE_scene_cursor_rot_to_quat(cursor_curr, quat);
+ copy_qt_qt(quat_prev, quat);
+ ED_view3d_cursor3d_position_rotation(
+ C, mval, use_depth, orientation, cursor_curr->location, quat);
+
+ if (!equals_v4v4(quat_prev, quat)) {
+ if ((cursor_curr->rotation_mode == ROT_MODE_AXISANGLE) && RV3D_VIEW_IS_AXIS(rv3d->view)) {
+ float tmat[3][3], cmat[3][3];
+ quat_to_mat3(tmat, quat);
+ negate_v3_v3(cursor_curr->rotation_axis, tmat[2]);
+ axis_angle_to_mat3(cmat, cursor_curr->rotation_axis, 0.0f);
+ cursor_curr->rotation_angle = angle_signed_on_axis_v3v3_v3(
+ cmat[0], tmat[0], cursor_curr->rotation_axis);
+ }
+ else {
+ BKE_scene_cursor_quat_to_rot(cursor_curr, quat, true);
+ }
+ }
+ }
+
+ /* offset the cursor lock to avoid jumping to new offset */
+ if (v3d->ob_centre_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) &&
+ (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);
+ }
+ }
+ else {
+ /* Cursor may be outside of the view,
+ * prevent it getting 'lost', see: T40353 & T45301 */
+ zero_v2(rv3d->ofs_lock);
+ }
+ }
+
+ if (v3d->localvd) {
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ }
+ else {
+ WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
+ }
+
+ {
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ wmMsgParams_RNA msg_key_params = {{{0}}};
+ RNA_pointer_create(&scene->id, &RNA_View3DCursor, &scene->cursor, &msg_key_params.ptr);
+ WM_msg_publish_rna_params(mbus, &msg_key_params);
+ }
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
}
static int view3d_cursor3d_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bool use_depth = (U.uiflag & USER_DEPTH_CURSOR);
- {
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_depth");
- if (RNA_property_is_set(op->ptr, prop)) {
- use_depth = RNA_property_boolean_get(op->ptr, prop);
- }
- else {
- RNA_property_boolean_set(op->ptr, prop, use_depth);
- }
- }
- const enum eV3DCursorOrient orientation = RNA_enum_get(op->ptr, "orientation");
- ED_view3d_cursor3d_update(C, event->mval, use_depth, orientation);
+ bool use_depth = (U.uiflag & USER_DEPTH_CURSOR);
+ {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_depth");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ use_depth = RNA_property_boolean_get(op->ptr, prop);
+ }
+ else {
+ RNA_property_boolean_set(op->ptr, prop, use_depth);
+ }
+ }
+ const enum eV3DCursorOrient orientation = RNA_enum_get(op->ptr, "orientation");
+ ED_view3d_cursor3d_update(C, event->mval, use_depth, orientation);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_cursor3d(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set 3D Cursor";
- ot->description = "Set the location of the 3D cursor";
- ot->idname = "VIEW3D_OT_cursor3d";
+ /* identifiers */
+ ot->name = "Set 3D Cursor";
+ ot->description = "Set the location of the 3D cursor";
+ ot->idname = "VIEW3D_OT_cursor3d";
- /* api callbacks */
- ot->invoke = view3d_cursor3d_invoke;
+ /* api callbacks */
+ ot->invoke = view3d_cursor3d_invoke;
- ot->poll = ED_operator_region_view3d_active;
+ ot->poll = ED_operator_region_view3d_active;
- /* flags */
-// ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+ /* flags */
+ // ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
- PropertyRNA *prop;
- static const EnumPropertyItem orientation_items[] = {
- {V3D_CURSOR_ORIENT_NONE, "NONE", 0, "None", "Leave orientation unchanged"},
- {V3D_CURSOR_ORIENT_VIEW, "VIEW", 0, "View", "Orient to the viewport"},
- {V3D_CURSOR_ORIENT_XFORM, "XFORM", 0, "Transform", "Orient to the current transform setting"},
- {V3D_CURSOR_ORIENT_GEOM, "GEOM", 0, "Geometry", "Match the surface normal"},
- {0, NULL, 0, NULL, NULL},
- };
+ PropertyRNA *prop;
+ static const EnumPropertyItem orientation_items[] = {
+ {V3D_CURSOR_ORIENT_NONE, "NONE", 0, "None", "Leave orientation unchanged"},
+ {V3D_CURSOR_ORIENT_VIEW, "VIEW", 0, "View", "Orient to the viewport"},
+ {V3D_CURSOR_ORIENT_XFORM,
+ "XFORM",
+ 0,
+ "Transform",
+ "Orient to the current transform setting"},
+ {V3D_CURSOR_ORIENT_GEOM, "GEOM", 0, "Geometry", "Match the surface normal"},
+ {0, NULL, 0, NULL, NULL},
+ };
- prop = RNA_def_boolean(
- ot->srna, "use_depth", true, "Surface Project",
- "Project onto the surface");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(
+ ot->srna, "use_depth", true, "Surface Project", "Project onto the surface");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_enum(
- ot->srna, "orientation", orientation_items, V3D_CURSOR_ORIENT_VIEW,
- "Orientation", "Preset viewpoint to use");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_enum(ot->srna,
+ "orientation",
+ orientation_items,
+ V3D_CURSOR_ORIENT_VIEW,
+ "Orientation",
+ "Preset viewpoint to use");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/** \} */
@@ -5006,120 +5121,114 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot)
* \{ */
static const EnumPropertyItem prop_shading_type_items[] = {
- {OB_WIRE, "WIREFRAME", 0, "Wireframe", "Toggle wireframe shading"},
- {OB_SOLID, "SOLID", 0, "Solid", "Toggle solid shading"},
- {OB_MATERIAL, "MATERIAL", 0, "LookDev", "Toggle lookdev shading"},
- {OB_RENDER, "RENDERED", 0, "Rendered", "Toggle rendered shading"},
- {0, NULL, 0, NULL, NULL},
+ {OB_WIRE, "WIREFRAME", 0, "Wireframe", "Toggle wireframe shading"},
+ {OB_SOLID, "SOLID", 0, "Solid", "Toggle solid shading"},
+ {OB_MATERIAL, "MATERIAL", 0, "LookDev", "Toggle lookdev shading"},
+ {OB_RENDER, "RENDERED", 0, "Rendered", "Toggle rendered shading"},
+ {0, NULL, 0, NULL, NULL},
};
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);
- int type = RNA_enum_get(op->ptr, "type");
-
- if (type == OB_SOLID) {
- if (v3d->shading.type != type) {
- v3d->shading.type = type;
- }
- else if (v3d->shading.type == OB_WIRE) {
- v3d->shading.type = OB_SOLID;
- }
- else {
- v3d->shading.type = OB_WIRE;
- }
- }
- else {
- char *prev_type = (
- (type == OB_WIRE) ?
- &v3d->shading.prev_type_wire :
- &v3d->shading.prev_type);
- if (v3d->shading.type == type) {
- if (*prev_type == type || !ELEM(*prev_type, OB_WIRE, OB_SOLID, OB_MATERIAL, OB_RENDER)) {
- *prev_type = OB_SOLID;
- }
- v3d->shading.type = *prev_type;
- }
- else {
- *prev_type = v3d->shading.type;
- v3d->shading.type = type;
- }
- }
-
- ED_view3d_shade_update(bmain, v3d, sa);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ ScrArea *sa = CTX_wm_area(C);
+ int type = RNA_enum_get(op->ptr, "type");
+
+ if (type == OB_SOLID) {
+ if (v3d->shading.type != type) {
+ v3d->shading.type = type;
+ }
+ else if (v3d->shading.type == OB_WIRE) {
+ v3d->shading.type = OB_SOLID;
+ }
+ else {
+ v3d->shading.type = OB_WIRE;
+ }
+ }
+ else {
+ char *prev_type = ((type == OB_WIRE) ? &v3d->shading.prev_type_wire : &v3d->shading.prev_type);
+ if (v3d->shading.type == type) {
+ if (*prev_type == type || !ELEM(*prev_type, OB_WIRE, OB_SOLID, OB_MATERIAL, OB_RENDER)) {
+ *prev_type = OB_SOLID;
+ }
+ v3d->shading.type = *prev_type;
+ }
+ else {
+ *prev_type = v3d->shading.type;
+ v3d->shading.type = type;
+ }
+ }
+
+ ED_view3d_shade_update(bmain, v3d, sa);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_toggle_shading(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Toggle Shading Type";
- ot->description = "Toggle shading type in 3D viewport";
- ot->idname = "VIEW3D_OT_toggle_shading";
+ /* identifiers */
+ ot->name = "Toggle Shading Type";
+ ot->description = "Toggle shading type in 3D viewport";
+ ot->idname = "VIEW3D_OT_toggle_shading";
- /* api callbacks */
- ot->exec = toggle_shading_exec;
- ot->poll = ED_operator_view3d_active;
+ /* api callbacks */
+ ot->exec = toggle_shading_exec;
+ ot->poll = ED_operator_view3d_active;
- prop = RNA_def_enum(ot->srna, "type", prop_shading_type_items, 0, "Type", "Shading type to toggle");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_enum(
+ ot->srna, "type", prop_shading_type_items, 0, "Type", "Shading type to toggle");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Toggle XRay
* \{ */
static int toggle_xray_exec(bContext *C, wmOperator *op)
{
- View3D *v3d = CTX_wm_view3d(C);
- ScrArea *sa = CTX_wm_area(C);
- Object *obact = CTX_data_active_object(C);
-
- if (obact &&
- ((obact->mode & OB_MODE_POSE) ||
- ((obact->mode & OB_MODE_WEIGHT_PAINT) && BKE_object_pose_armature_get(obact))))
- {
- v3d->overlay.flag ^= V3D_OVERLAY_BONE_SELECT;
- }
- else {
- const bool xray_active = (
- (obact && (obact->mode & OB_MODE_EDIT)) ||
- ELEM(v3d->shading.type, OB_WIRE, OB_SOLID));
-
- if (v3d->shading.type == OB_WIRE) {
- v3d->shading.flag ^= V3D_SHADING_XRAY_BONE;
- }
- else {
- v3d->shading.flag ^= V3D_SHADING_XRAY;
- }
- if (!xray_active) {
- BKE_report(op->reports, RPT_INFO, "X-Ray not available in current mode");
- }
- }
-
- ED_area_tag_redraw(sa);
-
- return OPERATOR_FINISHED;
+ View3D *v3d = CTX_wm_view3d(C);
+ ScrArea *sa = CTX_wm_area(C);
+ Object *obact = CTX_data_active_object(C);
+
+ if (obact && ((obact->mode & OB_MODE_POSE) ||
+ ((obact->mode & OB_MODE_WEIGHT_PAINT) && BKE_object_pose_armature_get(obact)))) {
+ v3d->overlay.flag ^= V3D_OVERLAY_BONE_SELECT;
+ }
+ else {
+ const bool xray_active = ((obact && (obact->mode & OB_MODE_EDIT)) ||
+ ELEM(v3d->shading.type, OB_WIRE, OB_SOLID));
+
+ if (v3d->shading.type == OB_WIRE) {
+ v3d->shading.flag ^= V3D_SHADING_XRAY_BONE;
+ }
+ else {
+ v3d->shading.flag ^= V3D_SHADING_XRAY;
+ }
+ if (!xray_active) {
+ BKE_report(op->reports, RPT_INFO, "X-Ray not available in current mode");
+ }
+ }
+
+ ED_area_tag_redraw(sa);
+
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_toggle_xray(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle X-Ray";
- ot->idname = "VIEW3D_OT_toggle_xray";
+ /* identifiers */
+ ot->name = "Toggle X-Ray";
+ ot->idname = "VIEW3D_OT_toggle_xray";
- /* api callbacks */
- ot->exec = toggle_xray_exec;
- ot->poll = ED_operator_view3d_active;
+ /* api callbacks */
+ ot->exec = toggle_xray_exec;
+ ot->poll = ED_operator_view3d_active;
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index b80ce2c49b0..8dc3abe6af5 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -38,7 +38,6 @@
#include "BLT_translation.h"
-
#include "WM_api.h"
#include "WM_types.h"
@@ -54,1068 +53,1085 @@
#include "DEG_depsgraph.h"
-#include "view3d_intern.h" /* own include */
+#include "view3d_intern.h" /* own include */
/* NOTE: these defines are saved in keymap files,
* do not change values but just add new ones */
enum {
- FLY_MODAL_CANCEL = 1,
- FLY_MODAL_CONFIRM,
- FLY_MODAL_ACCELERATE,
- FLY_MODAL_DECELERATE,
- FLY_MODAL_PAN_ENABLE,
- FLY_MODAL_PAN_DISABLE,
- FLY_MODAL_DIR_FORWARD,
- FLY_MODAL_DIR_BACKWARD,
- FLY_MODAL_DIR_LEFT,
- FLY_MODAL_DIR_RIGHT,
- FLY_MODAL_DIR_UP,
- FLY_MODAL_DIR_DOWN,
- FLY_MODAL_AXIS_LOCK_X,
- FLY_MODAL_AXIS_LOCK_Z,
- FLY_MODAL_PRECISION_ENABLE,
- FLY_MODAL_PRECISION_DISABLE,
- FLY_MODAL_FREELOOK_ENABLE,
- FLY_MODAL_FREELOOK_DISABLE,
- FLY_MODAL_SPEED, /* mousepan typically */
+ FLY_MODAL_CANCEL = 1,
+ FLY_MODAL_CONFIRM,
+ FLY_MODAL_ACCELERATE,
+ FLY_MODAL_DECELERATE,
+ FLY_MODAL_PAN_ENABLE,
+ FLY_MODAL_PAN_DISABLE,
+ FLY_MODAL_DIR_FORWARD,
+ FLY_MODAL_DIR_BACKWARD,
+ FLY_MODAL_DIR_LEFT,
+ FLY_MODAL_DIR_RIGHT,
+ FLY_MODAL_DIR_UP,
+ FLY_MODAL_DIR_DOWN,
+ FLY_MODAL_AXIS_LOCK_X,
+ FLY_MODAL_AXIS_LOCK_Z,
+ FLY_MODAL_PRECISION_ENABLE,
+ FLY_MODAL_PRECISION_DISABLE,
+ FLY_MODAL_FREELOOK_ENABLE,
+ FLY_MODAL_FREELOOK_DISABLE,
+ FLY_MODAL_SPEED, /* mousepan typically */
};
/* relative view axis locking - xlock, zlock */
typedef enum eFlyPanState {
- /* disabled */
- FLY_AXISLOCK_STATE_OFF = 0,
+ /* disabled */
+ FLY_AXISLOCK_STATE_OFF = 0,
- /* enabled but not checking because mouse hasn't moved outside the margin since locking was
- * checked an not needed when the mouse moves, locking is set to 2 so checks are done. */
- FLY_AXISLOCK_STATE_IDLE = 1,
+ /* enabled but not checking because mouse hasn't moved outside the margin since locking was
+ * checked an not needed when the mouse moves, locking is set to 2 so checks are done. */
+ FLY_AXISLOCK_STATE_IDLE = 1,
- /* mouse moved and checking needed,
- * if no view altering is done its changed back to #FLY_AXISLOCK_STATE_IDLE */
- FLY_AXISLOCK_STATE_ACTIVE = 2,
+ /* mouse moved and checking needed,
+ * if no view altering is done its changed back to #FLY_AXISLOCK_STATE_IDLE */
+ FLY_AXISLOCK_STATE_ACTIVE = 2,
} eFlyPanState;
/* called in transform_ops.c, on each regeneration of keymaps */
void fly_modal_keymap(wmKeyConfig *keyconf)
{
- static const EnumPropertyItem modal_items[] = {
- {FLY_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
- {FLY_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
+ static const EnumPropertyItem modal_items[] = {
+ {FLY_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+ {FLY_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
- {FLY_MODAL_DIR_FORWARD, "FORWARD", 0, "Forward", ""},
- {FLY_MODAL_DIR_BACKWARD, "BACKWARD", 0, "Backward", ""},
- {FLY_MODAL_DIR_LEFT, "LEFT", 0, "Left", ""},
- {FLY_MODAL_DIR_RIGHT, "RIGHT", 0, "Right", ""},
- {FLY_MODAL_DIR_UP, "UP", 0, "Up", ""},
- {FLY_MODAL_DIR_DOWN, "DOWN", 0, "Down", ""},
+ {FLY_MODAL_DIR_FORWARD, "FORWARD", 0, "Forward", ""},
+ {FLY_MODAL_DIR_BACKWARD, "BACKWARD", 0, "Backward", ""},
+ {FLY_MODAL_DIR_LEFT, "LEFT", 0, "Left", ""},
+ {FLY_MODAL_DIR_RIGHT, "RIGHT", 0, "Right", ""},
+ {FLY_MODAL_DIR_UP, "UP", 0, "Up", ""},
+ {FLY_MODAL_DIR_DOWN, "DOWN", 0, "Down", ""},
- {FLY_MODAL_PAN_ENABLE, "PAN_ENABLE", 0, "Pan", ""},
- {FLY_MODAL_PAN_DISABLE, "PAN_DISABLE", 0, "Pan (Off)", ""},
+ {FLY_MODAL_PAN_ENABLE, "PAN_ENABLE", 0, "Pan", ""},
+ {FLY_MODAL_PAN_DISABLE, "PAN_DISABLE", 0, "Pan (Off)", ""},
- {FLY_MODAL_ACCELERATE, "ACCELERATE", 0, "Accelerate", ""},
- {FLY_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""},
+ {FLY_MODAL_ACCELERATE, "ACCELERATE", 0, "Accelerate", ""},
+ {FLY_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""},
- {FLY_MODAL_AXIS_LOCK_X, "AXIS_LOCK_X", 0, "X Axis Correction", "X axis correction (toggle)"},
- {FLY_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "X Axis Correction", "Z axis correction (toggle)"},
+ {FLY_MODAL_AXIS_LOCK_X, "AXIS_LOCK_X", 0, "X Axis Correction", "X axis correction (toggle)"},
+ {FLY_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "X Axis Correction", "Z axis correction (toggle)"},
- {FLY_MODAL_PRECISION_ENABLE, "PRECISION_ENABLE", 0, "Precision", ""},
- {FLY_MODAL_PRECISION_DISABLE, "PRECISION_DISABLE", 0, "Precision (Off)", ""},
+ {FLY_MODAL_PRECISION_ENABLE, "PRECISION_ENABLE", 0, "Precision", ""},
+ {FLY_MODAL_PRECISION_DISABLE, "PRECISION_DISABLE", 0, "Precision (Off)", ""},
- {FLY_MODAL_FREELOOK_ENABLE, "FREELOOK_ENABLE", 0, "Rotation", ""},
- {FLY_MODAL_FREELOOK_DISABLE, "FREELOOK_DISABLE", 0, "Rotation (Off)", ""},
+ {FLY_MODAL_FREELOOK_ENABLE, "FREELOOK_ENABLE", 0, "Rotation", ""},
+ {FLY_MODAL_FREELOOK_DISABLE, "FREELOOK_DISABLE", 0, "Rotation (Off)", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ {0, NULL, 0, NULL, NULL},
+ };
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Fly Modal");
+ wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Fly Modal");
- /* this function is called for each spacetype, only needs to add map once */
- if (keymap && keymap->modal_items) {
- return;
- }
+ /* 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_add(keyconf, "View3D Fly Modal", modal_items);
- /* assign map to operators */
- WM_modalkeymap_assign(keymap, "VIEW3D_OT_fly");
+ /* assign map to operators */
+ WM_modalkeymap_assign(keymap, "VIEW3D_OT_fly");
}
typedef struct FlyInfo {
- /* context stuff */
- RegionView3D *rv3d;
- View3D *v3d;
- ARegion *ar;
- struct Depsgraph *depsgraph;
- Scene *scene;
-
- wmTimer *timer; /* needed for redraws */
-
- short state;
- bool redraw;
- bool use_precision;
- /* if the user presses shift they can look about
- * without moving the direction there looking */
- bool use_freelook;
-
- int mval[2]; /* latest 2D mouse values */
- int center_mval[2]; /* center mouse values */
- float width, height; /* camera viewport dimensions */
+ /* context stuff */
+ RegionView3D *rv3d;
+ View3D *v3d;
+ ARegion *ar;
+ struct Depsgraph *depsgraph;
+ Scene *scene;
+
+ wmTimer *timer; /* needed for redraws */
+
+ short state;
+ bool redraw;
+ bool use_precision;
+ /* if the user presses shift they can look about
+ * without moving the direction there looking */
+ bool use_freelook;
+
+ int mval[2]; /* latest 2D mouse values */
+ int center_mval[2]; /* center mouse values */
+ float width, height; /* camera viewport dimensions */
#ifdef WITH_INPUT_NDOF
- wmNDOFMotionData *ndof; /* latest 3D mouse values */
+ wmNDOFMotionData *ndof; /* latest 3D mouse values */
#endif
- /* fly state state */
- float speed; /* the speed the view is moving per redraw */
- short axis; /* Axis index to move along by default Z to move along the view */
- bool pan_view; /* when true, pan the view instead of rotating */
+ /* fly state state */
+ float speed; /* the speed the view is moving per redraw */
+ short axis; /* Axis index to move along by default Z to move along the view */
+ bool pan_view; /* when true, pan the view instead of rotating */
- eFlyPanState xlock, zlock;
- float xlock_momentum, zlock_momentum; /* nicer dynamics */
- float grid; /* world scale 1.0 default */
+ eFlyPanState xlock, zlock;
+ float xlock_momentum, zlock_momentum; /* nicer dynamics */
+ float grid; /* world scale 1.0 default */
- /* compare between last state */
- double time_lastwheel; /* used to accelerate when using the mousewheel a lot */
- double time_lastdraw; /* time between draws */
+ /* compare between last state */
+ double time_lastwheel; /* used to accelerate when using the mousewheel a lot */
+ double time_lastdraw; /* time between draws */
- void *draw_handle_pixel;
+ void *draw_handle_pixel;
- /* use for some lag */
- float dvec_prev[3]; /* old for some lag */
+ /* use for some lag */
+ float dvec_prev[3]; /* old for some lag */
- struct View3DCameraControl *v3d_camera_control;
+ struct View3DCameraControl *v3d_camera_control;
} FlyInfo;
static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
{
- FlyInfo *fly = arg;
- rctf viewborder;
- int xoff, yoff;
- float x1, x2, y1, y2;
+ FlyInfo *fly = arg;
+ rctf viewborder;
+ int xoff, yoff;
+ float x1, x2, y1, y2;
- 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);
- xoff = viewborder.xmin;
- yoff = viewborder.ymin;
- }
- else {
- xoff = 0;
- yoff = 0;
- }
+ 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);
+ xoff = viewborder.xmin;
+ yoff = viewborder.ymin;
+ }
+ else {
+ xoff = 0;
+ yoff = 0;
+ }
- /* draws 4 edge brackets that frame the safe area where the
- * mouse can move during fly mode without spinning the view */
+ /* draws 4 edge brackets that frame the safe area where the
+ * mouse can move during fly mode without spinning the view */
- x1 = xoff + 0.45f * fly->width;
- y1 = yoff + 0.45f * fly->height;
- x2 = xoff + 0.55f * fly->width;
- y2 = yoff + 0.55f * fly->height;
+ x1 = xoff + 0.45f * fly->width;
+ y1 = yoff + 0.45f * fly->height;
+ x2 = xoff + 0.55f * fly->width;
+ y2 = yoff + 0.55f * fly->height;
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor(TH_VIEW_OVERLAY);
+ immUniformThemeColor(TH_VIEW_OVERLAY);
- immBegin(GPU_PRIM_LINES, 16);
+ immBegin(GPU_PRIM_LINES, 16);
- /* bottom left */
- immVertex2f(pos, x1, y1);
- immVertex2f(pos, x1, y1 + 5);
+ /* bottom left */
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x1, y1 + 5);
- immVertex2f(pos, x1, y1);
- immVertex2f(pos, x1 + 5, y1);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x1 + 5, y1);
- /* top right */
- immVertex2f(pos, x2, y2);
- immVertex2f(pos, x2, y2 - 5);
+ /* top right */
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x2, y2 - 5);
- immVertex2f(pos, x2, y2);
- immVertex2f(pos, x2 - 5, y2);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x2 - 5, y2);
- /* top left */
- immVertex2f(pos, x1, y2);
- immVertex2f(pos, x1, y2 - 5);
+ /* top left */
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x1, y2 - 5);
- immVertex2f(pos, x1, y2);
- immVertex2f(pos, x1 + 5, y2);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x1 + 5, y2);
- /* bottom right */
- immVertex2f(pos, x2, y1);
- immVertex2f(pos, x2, y1 + 5);
+ /* bottom right */
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x2, y1 + 5);
- immVertex2f(pos, x2, y1);
- immVertex2f(pos, x2 - 5, y1);
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x2 - 5, y1);
- immEnd();
- immUnbindProgram();
+ immEnd();
+ immUnbindProgram();
}
static void fly_update_header(bContext *C, wmOperator *op, FlyInfo *fly)
{
- char header[UI_MAX_DRAW_STR];
- char buf[UI_MAX_DRAW_STR];
+ char header[UI_MAX_DRAW_STR];
+ char buf[UI_MAX_DRAW_STR];
- char *p = buf;
- int available_len = sizeof(buf);
+ char *p = buf;
+ int available_len = sizeof(buf);
#define WM_MODALKEY(_id) \
- WM_modalkeymap_operator_items_to_string_buf(op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p)
-
- BLI_snprintf(header, sizeof(header), IFACE_("%s: confirm, %s: cancel, "
- "%s: pan enable, "
- "%s|%s|%s|%s|%s|%s: direction, "
- "%s: slow, %s: free look, "
- "%s: Upright x axis (%s), "
- "%s: Upright z axis (%s), "
- "%s: increase speed, %s: decrease speed"),
- WM_MODALKEY(FLY_MODAL_CONFIRM), WM_MODALKEY(FLY_MODAL_CANCEL),
- WM_MODALKEY(FLY_MODAL_PAN_ENABLE),
- WM_MODALKEY(FLY_MODAL_DIR_FORWARD), WM_MODALKEY(FLY_MODAL_DIR_LEFT),
- WM_MODALKEY(FLY_MODAL_DIR_BACKWARD), WM_MODALKEY(FLY_MODAL_DIR_RIGHT),
- WM_MODALKEY(FLY_MODAL_DIR_UP), WM_MODALKEY(FLY_MODAL_DIR_DOWN),
- WM_MODALKEY(FLY_MODAL_PRECISION_ENABLE), WM_MODALKEY(FLY_MODAL_FREELOOK_ENABLE),
- WM_MODALKEY(FLY_MODAL_AXIS_LOCK_X), WM_bool_as_string(fly->xlock != FLY_AXISLOCK_STATE_OFF),
- WM_MODALKEY(FLY_MODAL_AXIS_LOCK_Z), WM_bool_as_string(fly->zlock != FLY_AXISLOCK_STATE_OFF),
- WM_MODALKEY(FLY_MODAL_ACCELERATE), WM_MODALKEY(FLY_MODAL_DECELERATE));
+ WM_modalkeymap_operator_items_to_string_buf( \
+ op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p)
+
+ BLI_snprintf(header,
+ sizeof(header),
+ IFACE_("%s: confirm, %s: cancel, "
+ "%s: pan enable, "
+ "%s|%s|%s|%s|%s|%s: direction, "
+ "%s: slow, %s: free look, "
+ "%s: Upright x axis (%s), "
+ "%s: Upright z axis (%s), "
+ "%s: increase speed, %s: decrease speed"),
+ WM_MODALKEY(FLY_MODAL_CONFIRM),
+ WM_MODALKEY(FLY_MODAL_CANCEL),
+ WM_MODALKEY(FLY_MODAL_PAN_ENABLE),
+ WM_MODALKEY(FLY_MODAL_DIR_FORWARD),
+ WM_MODALKEY(FLY_MODAL_DIR_LEFT),
+ WM_MODALKEY(FLY_MODAL_DIR_BACKWARD),
+ WM_MODALKEY(FLY_MODAL_DIR_RIGHT),
+ WM_MODALKEY(FLY_MODAL_DIR_UP),
+ WM_MODALKEY(FLY_MODAL_DIR_DOWN),
+ WM_MODALKEY(FLY_MODAL_PRECISION_ENABLE),
+ WM_MODALKEY(FLY_MODAL_FREELOOK_ENABLE),
+ WM_MODALKEY(FLY_MODAL_AXIS_LOCK_X),
+ WM_bool_as_string(fly->xlock != FLY_AXISLOCK_STATE_OFF),
+ WM_MODALKEY(FLY_MODAL_AXIS_LOCK_Z),
+ WM_bool_as_string(fly->zlock != FLY_AXISLOCK_STATE_OFF),
+ WM_MODALKEY(FLY_MODAL_ACCELERATE),
+ WM_MODALKEY(FLY_MODAL_DECELERATE));
#undef WM_MODALKEY
- ED_workspace_status_text(C, header);
+ ED_workspace_status_text(C, header);
}
/* FlyInfo->state */
enum {
- FLY_RUNNING = 0,
- FLY_CANCEL = 1,
- FLY_CONFIRM = 2,
+ FLY_RUNNING = 0,
+ FLY_CANCEL = 1,
+ FLY_CONFIRM = 2,
};
static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent *event)
{
- wmWindow *win = CTX_wm_window(C);
- rctf viewborder;
+ wmWindow *win = CTX_wm_window(C);
+ rctf viewborder;
- float upvec[3]; /* tmp */
- float mat[3][3];
+ float upvec[3]; /* tmp */
+ float mat[3][3];
- fly->rv3d = CTX_wm_region_view3d(C);
- fly->v3d = CTX_wm_view3d(C);
- fly->ar = CTX_wm_region(C);
- fly->depsgraph = CTX_data_depsgraph(C);
- fly->scene = CTX_data_scene(C);
+ fly->rv3d = CTX_wm_region_view3d(C);
+ fly->v3d = CTX_wm_view3d(C);
+ fly->ar = CTX_wm_region(C);
+ fly->depsgraph = CTX_data_depsgraph(C);
+ fly->scene = CTX_data_scene(C);
#ifdef NDOF_FLY_DEBUG
- puts("\n-- fly begin --");
+ puts("\n-- fly begin --");
#endif
- /* sanity check: for rare but possible case (if lib-linking the camera fails) */
- if ((fly->rv3d->persp == RV3D_CAMOB) && (fly->v3d->camera == NULL)) {
- fly->rv3d->persp = RV3D_PERSP;
- }
-
- if (fly->rv3d->persp == RV3D_CAMOB && ID_IS_LINKED(fly->v3d->camera)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library");
- return false;
- }
-
- if (ED_view3d_offset_lock_check(fly->v3d, fly->rv3d)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot fly when the view offset is locked");
- return false;
- }
-
- if (fly->rv3d->persp == RV3D_CAMOB && fly->v3d->camera->constraints.first) {
- BKE_report(op->reports, RPT_ERROR, "Cannot fly an object with constraints");
- return false;
- }
-
- fly->state = FLY_RUNNING;
- fly->speed = 0.0f;
- fly->axis = 2;
- fly->pan_view = false;
- fly->xlock = FLY_AXISLOCK_STATE_OFF;
- fly->zlock = FLY_AXISLOCK_STATE_OFF;
- fly->xlock_momentum = 0.0f;
- fly->zlock_momentum = 0.0f;
- fly->grid = 1.0f;
- fly->use_precision = false;
- fly->use_freelook = false;
+ /* sanity check: for rare but possible case (if lib-linking the camera fails) */
+ if ((fly->rv3d->persp == RV3D_CAMOB) && (fly->v3d->camera == NULL)) {
+ fly->rv3d->persp = RV3D_PERSP;
+ }
+
+ if (fly->rv3d->persp == RV3D_CAMOB && ID_IS_LINKED(fly->v3d->camera)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library");
+ return false;
+ }
+
+ if (ED_view3d_offset_lock_check(fly->v3d, fly->rv3d)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot fly when the view offset is locked");
+ return false;
+ }
+
+ if (fly->rv3d->persp == RV3D_CAMOB && fly->v3d->camera->constraints.first) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot fly an object with constraints");
+ return false;
+ }
+
+ fly->state = FLY_RUNNING;
+ fly->speed = 0.0f;
+ fly->axis = 2;
+ fly->pan_view = false;
+ fly->xlock = FLY_AXISLOCK_STATE_OFF;
+ fly->zlock = FLY_AXISLOCK_STATE_OFF;
+ fly->xlock_momentum = 0.0f;
+ fly->zlock_momentum = 0.0f;
+ fly->grid = 1.0f;
+ fly->use_precision = false;
+ fly->use_freelook = false;
#ifdef NDOF_FLY_DRAW_TOOMUCH
- fly->redraw = 1;
+ fly->redraw = 1;
#endif
- zero_v3(fly->dvec_prev);
+ zero_v3(fly->dvec_prev);
- fly->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f);
+ fly->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f);
- copy_v2_v2_int(fly->mval, event->mval);
+ copy_v2_v2_int(fly->mval, event->mval);
#ifdef WITH_INPUT_NDOF
- fly->ndof = NULL;
+ fly->ndof = NULL;
#endif
- 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->rv3d->rflag |= RV3D_NAVIGATING;
-
- /* detect whether to start with Z locking */
- copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
- copy_m3_m4(mat, fly->rv3d->viewinv);
- mul_m3_v3(mat, upvec);
- if (fabsf(upvec[2]) < 0.1f) {
- fly->zlock = FLY_AXISLOCK_STATE_IDLE;
- }
-
- fly->v3d_camera_control = ED_view3d_cameracontrol_acquire(
- CTX_data_depsgraph(C), fly->scene, fly->v3d, fly->rv3d,
- (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0);
-
- /* 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->width = BLI_rctf_size_x(&viewborder);
- fly->height = BLI_rctf_size_y(&viewborder);
-
- fly->center_mval[0] = viewborder.xmin + fly->width / 2;
- fly->center_mval[1] = viewborder.ymin + fly->height / 2;
- }
- else {
- fly->width = fly->ar->winx;
- fly->height = fly->ar->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]);
-
- fly_update_header(C, op, fly);
- return 1;
+ 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->rv3d->rflag |= RV3D_NAVIGATING;
+
+ /* detect whether to start with Z locking */
+ copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
+ copy_m3_m4(mat, fly->rv3d->viewinv);
+ mul_m3_v3(mat, upvec);
+ if (fabsf(upvec[2]) < 0.1f) {
+ fly->zlock = FLY_AXISLOCK_STATE_IDLE;
+ }
+
+ fly->v3d_camera_control = ED_view3d_cameracontrol_acquire(CTX_data_depsgraph(C),
+ fly->scene,
+ fly->v3d,
+ fly->rv3d,
+ (U.uiflag & USER_CAM_LOCK_NO_PARENT) ==
+ 0);
+
+ /* 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->width = BLI_rctf_size_x(&viewborder);
+ fly->height = BLI_rctf_size_y(&viewborder);
+
+ fly->center_mval[0] = viewborder.xmin + fly->width / 2;
+ fly->center_mval[1] = viewborder.ymin + fly->height / 2;
+ }
+ else {
+ fly->width = fly->ar->winx;
+ fly->height = fly->ar->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]);
+
+ fly_update_header(C, op, fly);
+ return 1;
}
static int flyEnd(bContext *C, FlyInfo *fly)
{
- wmWindow *win;
- RegionView3D *rv3d;
+ wmWindow *win;
+ RegionView3D *rv3d;
- if (fly->state == FLY_RUNNING) {
- return OPERATOR_RUNNING_MODAL;
- }
+ if (fly->state == FLY_RUNNING) {
+ return OPERATOR_RUNNING_MODAL;
+ }
#ifdef NDOF_FLY_DEBUG
- puts("\n-- fly end --");
+ puts("\n-- fly end --");
#endif
- win = CTX_wm_window(C);
- rv3d = fly->rv3d;
+ win = CTX_wm_window(C);
+ rv3d = fly->rv3d;
- WM_event_remove_timer(CTX_wm_manager(C), win, fly->timer);
+ 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->ar->type, fly->draw_handle_pixel);
- ED_view3d_cameracontrol_release(fly->v3d_camera_control, fly->state == FLY_CANCEL);
+ ED_view3d_cameracontrol_release(fly->v3d_camera_control, fly->state == FLY_CANCEL);
- rv3d->rflag &= ~RV3D_NAVIGATING;
+ rv3d->rflag &= ~RV3D_NAVIGATING;
#ifdef WITH_INPUT_NDOF
- if (fly->ndof) {
- MEM_freeN(fly->ndof);
- }
+ if (fly->ndof) {
+ MEM_freeN(fly->ndof);
+ }
#endif
- if (fly->state == FLY_CONFIRM) {
- MEM_freeN(fly);
- return OPERATOR_FINISHED;
- }
+ if (fly->state == FLY_CONFIRM) {
+ MEM_freeN(fly);
+ return OPERATOR_FINISHED;
+ }
- MEM_freeN(fly);
- return OPERATOR_CANCELLED;
+ MEM_freeN(fly);
+ return OPERATOR_CANCELLED;
}
static void flyEvent(bContext *C, wmOperator *op, FlyInfo *fly, const wmEvent *event)
{
- if (event->type == TIMER && event->customdata == fly->timer) {
- fly->redraw = 1;
- }
- else if (event->type == MOUSEMOVE) {
- copy_v2_v2_int(fly->mval, event->mval);
- }
+ if (event->type == TIMER && event->customdata == fly->timer) {
+ fly->redraw = 1;
+ }
+ else if (event->type == MOUSEMOVE) {
+ copy_v2_v2_int(fly->mval, event->mval);
+ }
#ifdef WITH_INPUT_NDOF
- else if (event->type == NDOF_MOTION) {
- /* do these automagically get delivered? yes. */
- // puts("ndof motion detected in fly mode!");
- // static const char *tag_name = "3D mouse position";
-
- const wmNDOFMotionData *incoming_ndof = event->customdata;
- switch (incoming_ndof->progress) {
- case P_STARTING:
- /* start keeping track of 3D mouse position */
+ else if (event->type == NDOF_MOTION) {
+ /* do these automagically get delivered? yes. */
+ // puts("ndof motion detected in fly mode!");
+ // static const char *tag_name = "3D mouse position";
+
+ const wmNDOFMotionData *incoming_ndof = event->customdata;
+ switch (incoming_ndof->progress) {
+ case P_STARTING:
+ /* start keeping track of 3D mouse position */
# ifdef NDOF_FLY_DEBUG
- puts("start keeping track of 3D mouse position");
+ puts("start keeping track of 3D mouse position");
# endif
- /* fall-through */
- case P_IN_PROGRESS:
- /* update 3D mouse position */
+ /* fall-through */
+ case P_IN_PROGRESS:
+ /* update 3D mouse position */
# ifdef NDOF_FLY_DEBUG
- putchar('.'); fflush(stdout);
+ putchar('.');
+ fflush(stdout);
# endif
- if (fly->ndof == NULL) {
- // fly->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name);
- fly->ndof = MEM_dupallocN(incoming_ndof);
- // fly->ndof = malloc(sizeof(wmNDOFMotionData));
- }
- else {
- memcpy(fly->ndof, incoming_ndof, sizeof(wmNDOFMotionData));
- }
- break;
- case P_FINISHING:
- /* stop keeping track of 3D mouse position */
+ if (fly->ndof == NULL) {
+ // fly->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name);
+ fly->ndof = MEM_dupallocN(incoming_ndof);
+ // fly->ndof = malloc(sizeof(wmNDOFMotionData));
+ }
+ else {
+ memcpy(fly->ndof, incoming_ndof, sizeof(wmNDOFMotionData));
+ }
+ break;
+ case P_FINISHING:
+ /* stop keeping track of 3D mouse position */
# ifdef NDOF_FLY_DEBUG
- puts("stop keeping track of 3D mouse position");
+ puts("stop keeping track of 3D mouse position");
# endif
- if (fly->ndof) {
- MEM_freeN(fly->ndof);
- // free(fly->ndof);
- fly->ndof = NULL;
- }
- /* update the time else the view will jump when 2D mouse/timer resume */
- fly->time_lastdraw = PIL_check_seconds_timer();
- break;
- default:
- break; /* should always be one of the above 3 */
- }
- }
+ if (fly->ndof) {
+ MEM_freeN(fly->ndof);
+ // free(fly->ndof);
+ fly->ndof = NULL;
+ }
+ /* update the time else the view will jump when 2D mouse/timer resume */
+ fly->time_lastdraw = PIL_check_seconds_timer();
+ break;
+ default:
+ break; /* should always be one of the above 3 */
+ }
+ }
#endif /* WITH_INPUT_NDOF */
- /* handle modal keymap first */
- else if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case FLY_MODAL_CANCEL:
- fly->state = FLY_CANCEL;
- break;
- case FLY_MODAL_CONFIRM:
- fly->state = FLY_CONFIRM;
- break;
-
- /* speed adjusting with mousepan (trackpad) */
- case FLY_MODAL_SPEED:
- {
- float fac = 0.02f * (event->prevy - event->y);
-
- /* allowing to brake immediate */
- if (fac > 0.0f && fly->speed < 0.0f) {
- fly->speed = 0.0f;
- }
- else if (fac < 0.0f && fly->speed > 0.0f) {
- fly->speed = 0.0f;
- }
- else {
- fly->speed += fly->grid * fac;
- }
-
- break;
- }
- case FLY_MODAL_ACCELERATE:
- {
- double time_currwheel;
- float time_wheel;
-
- /* not quite correct but avoids confusion WASD/arrow keys 'locking up' */
- if (fly->axis == -1) {
- fly->axis = 2;
- fly->speed = fabsf(fly->speed);
- }
-
- time_currwheel = PIL_check_seconds_timer();
- time_wheel = (float)(time_currwheel - fly->time_lastwheel);
- fly->time_lastwheel = time_currwheel;
- /* Mouse wheel delays range from (0.5 == slow) to (0.01 == fast) */
- /* 0-0.5 -> 0-5.0 */
- time_wheel = 1.0f + (10.0f - (20.0f * min_ff(time_wheel, 0.5f)));
-
- if (fly->speed < 0.0f) {
- fly->speed = 0.0f;
- }
- else {
- fly->speed += fly->grid * time_wheel * (fly->use_precision ? 0.1f : 1.0f);
- }
- break;
- }
- case FLY_MODAL_DECELERATE:
- {
- double time_currwheel;
- float time_wheel;
-
- /* not quite correct but avoids confusion WASD/arrow keys 'locking up' */
- if (fly->axis == -1) {
- fly->axis = 2;
- fly->speed = -fabsf(fly->speed);
- }
-
- time_currwheel = PIL_check_seconds_timer();
- time_wheel = (float)(time_currwheel - fly->time_lastwheel);
- fly->time_lastwheel = time_currwheel;
- /* 0-0.5 -> 0-5.0 */
- time_wheel = 1.0f + (10.0f - (20.0f * min_ff(time_wheel, 0.5f)));
-
- if (fly->speed > 0.0f) {
- fly->speed = 0;
- }
- else {
- fly->speed -= fly->grid * time_wheel * (fly->use_precision ? 0.1f : 1.0f);
- }
- break;
- }
- case FLY_MODAL_PAN_ENABLE:
- fly->pan_view = true;
- break;
- case FLY_MODAL_PAN_DISABLE:
- fly->pan_view = false;
- break;
-
- /* implement WASD keys,
- * comments only for 'forward '*/
- case FLY_MODAL_DIR_FORWARD:
- if (fly->axis == 2 && fly->speed < 0.0f) {
- /* reverse direction stops, tap again to continue */
- fly->axis = -1;
- }
- else {
- /* flip speed rather than stopping, game like motion,
- * else increase like mousewheel if were already moving in that direction */
- if (fly->speed < 0.0f) {
- fly->speed = -fly->speed;
- }
- else if (fly->axis == 2) {
- fly->speed += fly->grid;
- }
- fly->axis = 2;
- }
- break;
- case FLY_MODAL_DIR_BACKWARD:
- if (fly->axis == 2 && fly->speed > 0.0f) {
- fly->axis = -1;
- }
- else {
- if (fly->speed > 0.0f) {
- fly->speed = -fly->speed;
- }
- else if (fly->axis == 2) {
- fly->speed -= fly->grid;
- }
-
- fly->axis = 2;
- }
- break;
- case FLY_MODAL_DIR_LEFT:
- if (fly->axis == 0 && fly->speed < 0.0f) {
- fly->axis = -1;
- }
- else {
- if (fly->speed < 0.0f) {
- fly->speed = -fly->speed;
- }
- else if (fly->axis == 0) {
- fly->speed += fly->grid;
- }
-
- fly->axis = 0;
- }
- break;
- case FLY_MODAL_DIR_RIGHT:
- if (fly->axis == 0 && fly->speed > 0.0f) {
- fly->axis = -1;
- }
- else {
- if (fly->speed > 0.0f) {
- fly->speed = -fly->speed;
- }
- else if (fly->axis == 0) {
- fly->speed -= fly->grid;
- }
-
- fly->axis = 0;
- }
- break;
- case FLY_MODAL_DIR_DOWN:
- if (fly->axis == 1 && fly->speed < 0.0f) {
- fly->axis = -1;
- }
- else {
- if (fly->speed < 0.0f) {
- fly->speed = -fly->speed;
- }
- else if (fly->axis == 1) {
- fly->speed += fly->grid;
- }
- fly->axis = 1;
- }
- break;
- case FLY_MODAL_DIR_UP:
- if (fly->axis == 1 && fly->speed > 0.0f) {
- fly->axis = -1;
- }
- else {
- if (fly->speed > 0.0f) {
- fly->speed = -fly->speed;
- }
- else if (fly->axis == 1) {
- fly->speed -= fly->grid;
- }
- fly->axis = 1;
- }
- break;
-
- case FLY_MODAL_AXIS_LOCK_X:
- if (fly->xlock != FLY_AXISLOCK_STATE_OFF) {
- fly->xlock = FLY_AXISLOCK_STATE_OFF;
- }
- else {
- fly->xlock = FLY_AXISLOCK_STATE_ACTIVE;
- fly->xlock_momentum = 0.0;
- }
- fly_update_header(C, op, fly);
- break;
- case FLY_MODAL_AXIS_LOCK_Z:
- if (fly->zlock != FLY_AXISLOCK_STATE_OFF) {
- fly->zlock = FLY_AXISLOCK_STATE_OFF;
- }
- else {
- fly->zlock = FLY_AXISLOCK_STATE_ACTIVE;
- fly->zlock_momentum = 0.0;
- }
- fly_update_header(C, op, fly);
- break;
-
- case FLY_MODAL_PRECISION_ENABLE:
- fly->use_precision = true;
- break;
- case FLY_MODAL_PRECISION_DISABLE:
- fly->use_precision = false;
- break;
-
- case FLY_MODAL_FREELOOK_ENABLE:
- fly->use_freelook = true;
- break;
- case FLY_MODAL_FREELOOK_DISABLE:
- fly->use_freelook = false;
- break;
- }
- }
+ /* handle modal keymap first */
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case FLY_MODAL_CANCEL:
+ fly->state = FLY_CANCEL;
+ break;
+ case FLY_MODAL_CONFIRM:
+ fly->state = FLY_CONFIRM;
+ break;
+
+ /* speed adjusting with mousepan (trackpad) */
+ case FLY_MODAL_SPEED: {
+ float fac = 0.02f * (event->prevy - event->y);
+
+ /* allowing to brake immediate */
+ if (fac > 0.0f && fly->speed < 0.0f) {
+ fly->speed = 0.0f;
+ }
+ else if (fac < 0.0f && fly->speed > 0.0f) {
+ fly->speed = 0.0f;
+ }
+ else {
+ fly->speed += fly->grid * fac;
+ }
+
+ break;
+ }
+ case FLY_MODAL_ACCELERATE: {
+ double time_currwheel;
+ float time_wheel;
+
+ /* not quite correct but avoids confusion WASD/arrow keys 'locking up' */
+ if (fly->axis == -1) {
+ fly->axis = 2;
+ fly->speed = fabsf(fly->speed);
+ }
+
+ time_currwheel = PIL_check_seconds_timer();
+ time_wheel = (float)(time_currwheel - fly->time_lastwheel);
+ fly->time_lastwheel = time_currwheel;
+ /* Mouse wheel delays range from (0.5 == slow) to (0.01 == fast) */
+ /* 0-0.5 -> 0-5.0 */
+ time_wheel = 1.0f + (10.0f - (20.0f * min_ff(time_wheel, 0.5f)));
+
+ if (fly->speed < 0.0f) {
+ fly->speed = 0.0f;
+ }
+ else {
+ fly->speed += fly->grid * time_wheel * (fly->use_precision ? 0.1f : 1.0f);
+ }
+ break;
+ }
+ case FLY_MODAL_DECELERATE: {
+ double time_currwheel;
+ float time_wheel;
+
+ /* not quite correct but avoids confusion WASD/arrow keys 'locking up' */
+ if (fly->axis == -1) {
+ fly->axis = 2;
+ fly->speed = -fabsf(fly->speed);
+ }
+
+ time_currwheel = PIL_check_seconds_timer();
+ time_wheel = (float)(time_currwheel - fly->time_lastwheel);
+ fly->time_lastwheel = time_currwheel;
+ /* 0-0.5 -> 0-5.0 */
+ time_wheel = 1.0f + (10.0f - (20.0f * min_ff(time_wheel, 0.5f)));
+
+ if (fly->speed > 0.0f) {
+ fly->speed = 0;
+ }
+ else {
+ fly->speed -= fly->grid * time_wheel * (fly->use_precision ? 0.1f : 1.0f);
+ }
+ break;
+ }
+ case FLY_MODAL_PAN_ENABLE:
+ fly->pan_view = true;
+ break;
+ case FLY_MODAL_PAN_DISABLE:
+ fly->pan_view = false;
+ break;
+
+ /* implement WASD keys,
+ * comments only for 'forward '*/
+ case FLY_MODAL_DIR_FORWARD:
+ if (fly->axis == 2 && fly->speed < 0.0f) {
+ /* reverse direction stops, tap again to continue */
+ fly->axis = -1;
+ }
+ else {
+ /* flip speed rather than stopping, game like motion,
+ * else increase like mousewheel if were already moving in that direction */
+ if (fly->speed < 0.0f) {
+ fly->speed = -fly->speed;
+ }
+ else if (fly->axis == 2) {
+ fly->speed += fly->grid;
+ }
+ fly->axis = 2;
+ }
+ break;
+ case FLY_MODAL_DIR_BACKWARD:
+ if (fly->axis == 2 && fly->speed > 0.0f) {
+ fly->axis = -1;
+ }
+ else {
+ if (fly->speed > 0.0f) {
+ fly->speed = -fly->speed;
+ }
+ else if (fly->axis == 2) {
+ fly->speed -= fly->grid;
+ }
+
+ fly->axis = 2;
+ }
+ break;
+ case FLY_MODAL_DIR_LEFT:
+ if (fly->axis == 0 && fly->speed < 0.0f) {
+ fly->axis = -1;
+ }
+ else {
+ if (fly->speed < 0.0f) {
+ fly->speed = -fly->speed;
+ }
+ else if (fly->axis == 0) {
+ fly->speed += fly->grid;
+ }
+
+ fly->axis = 0;
+ }
+ break;
+ case FLY_MODAL_DIR_RIGHT:
+ if (fly->axis == 0 && fly->speed > 0.0f) {
+ fly->axis = -1;
+ }
+ else {
+ if (fly->speed > 0.0f) {
+ fly->speed = -fly->speed;
+ }
+ else if (fly->axis == 0) {
+ fly->speed -= fly->grid;
+ }
+
+ fly->axis = 0;
+ }
+ break;
+ case FLY_MODAL_DIR_DOWN:
+ if (fly->axis == 1 && fly->speed < 0.0f) {
+ fly->axis = -1;
+ }
+ else {
+ if (fly->speed < 0.0f) {
+ fly->speed = -fly->speed;
+ }
+ else if (fly->axis == 1) {
+ fly->speed += fly->grid;
+ }
+ fly->axis = 1;
+ }
+ break;
+ case FLY_MODAL_DIR_UP:
+ if (fly->axis == 1 && fly->speed > 0.0f) {
+ fly->axis = -1;
+ }
+ else {
+ if (fly->speed > 0.0f) {
+ fly->speed = -fly->speed;
+ }
+ else if (fly->axis == 1) {
+ fly->speed -= fly->grid;
+ }
+ fly->axis = 1;
+ }
+ break;
+
+ case FLY_MODAL_AXIS_LOCK_X:
+ if (fly->xlock != FLY_AXISLOCK_STATE_OFF) {
+ fly->xlock = FLY_AXISLOCK_STATE_OFF;
+ }
+ else {
+ fly->xlock = FLY_AXISLOCK_STATE_ACTIVE;
+ fly->xlock_momentum = 0.0;
+ }
+ fly_update_header(C, op, fly);
+ break;
+ case FLY_MODAL_AXIS_LOCK_Z:
+ if (fly->zlock != FLY_AXISLOCK_STATE_OFF) {
+ fly->zlock = FLY_AXISLOCK_STATE_OFF;
+ }
+ else {
+ fly->zlock = FLY_AXISLOCK_STATE_ACTIVE;
+ fly->zlock_momentum = 0.0;
+ }
+ fly_update_header(C, op, fly);
+ break;
+
+ case FLY_MODAL_PRECISION_ENABLE:
+ fly->use_precision = true;
+ break;
+ case FLY_MODAL_PRECISION_DISABLE:
+ fly->use_precision = false;
+ break;
+
+ case FLY_MODAL_FREELOOK_ENABLE:
+ fly->use_freelook = true;
+ break;
+ case FLY_MODAL_FREELOOK_DISABLE:
+ fly->use_freelook = false;
+ break;
+ }
+ }
}
-static void flyMoveCamera(bContext *C, FlyInfo *fly,
- const bool do_rotate, const bool do_translate)
+static void flyMoveCamera(bContext *C, FlyInfo *fly, const bool do_rotate, const bool do_translate)
{
- ED_view3d_cameracontrol_update(fly->v3d_camera_control, true, C, do_rotate, do_translate);
+ ED_view3d_cameracontrol_update(fly->v3d_camera_control, true, C, do_rotate, do_translate);
}
static int flyApply(bContext *C, FlyInfo *fly)
{
-#define FLY_ROTATE_FAC 10.0f /* more is faster */
-#define FLY_ZUP_CORRECT_FAC 0.1f /* amount to correct per step */
+#define FLY_ROTATE_FAC 10.0f /* more is faster */
+#define FLY_ZUP_CORRECT_FAC 0.1f /* amount to correct per step */
#define FLY_ZUP_CORRECT_ACCEL 0.05f /* increase upright momentum each step */
-#define FLY_SMOOTH_FAC 20.0f /* higher value less lag */
+#define FLY_SMOOTH_FAC 20.0f /* higher value less lag */
- /* fly mode - Shift+F
- * a fly loop where the user can move move the view as if they are flying
- */
- RegionView3D *rv3d = fly->rv3d;
+ /* fly mode - Shift+F
+ * a fly loop where the user can move move the view as if they are flying
+ */
+ RegionView3D *rv3d = fly->rv3d;
- /* 3x3 copy of the view matrix so we can move along the view axis */
- float mat[3][3];
- /* this is the direction that's added to the view offset per redraw */
- float dvec[3] = {0, 0, 0};
+ /* 3x3 copy of the view matrix so we can move along the view axis */
+ float mat[3][3];
+ /* this is the direction that's added to the view offset per redraw */
+ float dvec[3] = {0, 0, 0};
- /* Camera Uprighting variables */
- float moffset[2]; /* mouse offset from the views center */
- float tmp_quat[4]; /* used for rotating the view */
+ /* Camera Uprighting variables */
+ float moffset[2]; /* mouse offset from the views center */
+ float tmp_quat[4]; /* used for rotating the view */
- /* x and y margin are define the safe area where the mouses movement wont rotate the view */
- int xmargin, ymargin;
+ /* x and y margin are define the safe area where the mouses movement wont rotate the view */
+ int xmargin, ymargin;
#ifdef NDOF_FLY_DEBUG
- {
- static uint iteration = 1;
- printf("fly timer %d\n", iteration++);
- }
+ {
+ static uint iteration = 1;
+ printf("fly timer %d\n", iteration++);
+ }
#endif
- xmargin = fly->width / 20.0f;
- ymargin = fly->height / 20.0f;
-
- {
-
- /* mouse offset from the center */
- moffset[0] = fly->mval[0] - fly->center_mval[0];
- moffset[1] = fly->mval[1] - fly->center_mval[1];
-
- /* enforce a view margin */
- if (moffset[0] > xmargin) {
- moffset[0] -= xmargin;
- }
- else if (moffset[0] < -xmargin) {
- moffset[0] += xmargin;
- }
- else {
- moffset[0] = 0;
- }
-
- if (moffset[1] > ymargin) {
- moffset[1] -= ymargin;
- }
- else if (moffset[1] < -ymargin) {
- moffset[1] += ymargin;
- }
- else {
- moffset[1] = 0;
- }
-
-
- /* 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)
- *
- * the mouse moves isn't linear */
-
- if (moffset[0]) {
- moffset[0] /= fly->width - (xmargin * 2);
- moffset[0] *= fabsf(moffset[0]);
- }
-
- if (moffset[1]) {
- moffset[1] /= fly->height - (ymargin * 2);
- moffset[1] *= fabsf(moffset[1]);
- }
-
- /* Should we redraw? */
- if ((fly->speed != 0.0f) ||
- moffset[0] || moffset[1] ||
- (fly->zlock != FLY_AXISLOCK_STATE_OFF) ||
- (fly->xlock != FLY_AXISLOCK_STATE_OFF) ||
- dvec[0] || dvec[1] || dvec[2])
- {
- float dvec_tmp[3];
-
- /* time how fast it takes for us to redraw,
- * this is so simple scenes don't fly too fast */
- double time_current;
- float time_redraw;
- float time_redraw_clamped;
+ xmargin = fly->width / 20.0f;
+ ymargin = fly->height / 20.0f;
+
+ {
+
+ /* mouse offset from the center */
+ moffset[0] = fly->mval[0] - fly->center_mval[0];
+ moffset[1] = fly->mval[1] - fly->center_mval[1];
+
+ /* enforce a view margin */
+ if (moffset[0] > xmargin) {
+ moffset[0] -= xmargin;
+ }
+ else if (moffset[0] < -xmargin) {
+ moffset[0] += xmargin;
+ }
+ else {
+ moffset[0] = 0;
+ }
+
+ if (moffset[1] > ymargin) {
+ moffset[1] -= ymargin;
+ }
+ else if (moffset[1] < -ymargin) {
+ moffset[1] += ymargin;
+ }
+ else {
+ moffset[1] = 0;
+ }
+
+ /* 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)
+ *
+ * the mouse moves isn't linear */
+
+ if (moffset[0]) {
+ moffset[0] /= fly->width - (xmargin * 2);
+ moffset[0] *= fabsf(moffset[0]);
+ }
+
+ if (moffset[1]) {
+ moffset[1] /= fly->height - (ymargin * 2);
+ moffset[1] *= fabsf(moffset[1]);
+ }
+
+ /* Should we redraw? */
+ if ((fly->speed != 0.0f) || moffset[0] || moffset[1] ||
+ (fly->zlock != FLY_AXISLOCK_STATE_OFF) || (fly->xlock != FLY_AXISLOCK_STATE_OFF) ||
+ dvec[0] || dvec[1] || dvec[2]) {
+ float dvec_tmp[3];
+
+ /* time how fast it takes for us to redraw,
+ * this is so simple scenes don't fly too fast */
+ double time_current;
+ float time_redraw;
+ float time_redraw_clamped;
#ifdef NDOF_FLY_DRAW_TOOMUCH
- fly->redraw = 1;
+ fly->redraw = 1;
#endif
- time_current = PIL_check_seconds_timer();
- time_redraw = (float)(time_current - fly->time_lastdraw);
-
- /* clamp redraw time to avoid jitter in roll correction */
- time_redraw_clamped = min_ff(0.05f, time_redraw);
-
- fly->time_lastdraw = time_current;
-
- /* Scale the time to use shift to scale the speed down- just like
- * shift slows many other areas of blender down */
- if (fly->use_precision) {
- fly->speed = fly->speed * (1.0f - time_redraw_clamped);
- }
-
- copy_m3_m4(mat, rv3d->viewinv);
-
- if (fly->pan_view == true) {
- /* pan only */
- copy_v3_fl3(dvec_tmp, -moffset[0], -moffset[1], 0.0f);
-
- if (fly->use_precision) {
- dvec_tmp[0] *= 0.1f;
- dvec_tmp[1] *= 0.1f;
- }
-
- mul_m3_v3(mat, dvec_tmp);
- mul_v3_fl(dvec_tmp, time_redraw * 200.0f * fly->grid);
- }
- else {
- float roll; /* similar to the angle between the camera's up and the Z-up,
- * but its very rough so just roll */
-
- /* rotate about the X axis- look up/down */
- if (moffset[1]) {
- float upvec[3];
- copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
- mul_m3_v3(mat, upvec);
- /* Rotate about the relative up vec */
- axis_angle_to_quat(tmp_quat, upvec, moffset[1] * time_redraw * -FLY_ROTATE_FAC);
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
-
- if (fly->xlock != FLY_AXISLOCK_STATE_OFF) {
- fly->xlock = FLY_AXISLOCK_STATE_ACTIVE; /* check for rotation */
- }
- if (fly->zlock != FLY_AXISLOCK_STATE_OFF) {
- fly->zlock = FLY_AXISLOCK_STATE_ACTIVE;
- }
- fly->xlock_momentum = 0.0f;
- }
-
- /* rotate about the Y axis- look left/right */
- if (moffset[0]) {
- float upvec[3];
- /* if we're upside down invert the moffset */
- copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f);
- mul_m3_v3(mat, upvec);
-
- if (upvec[2] < 0.0f) {
- moffset[0] = -moffset[0];
- }
-
- /* make the lock vectors */
- if (fly->zlock) {
- copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
- }
- else {
- copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f);
- mul_m3_v3(mat, upvec);
- }
-
- /* Rotate about the relative up vec */
- axis_angle_to_quat(tmp_quat, upvec, moffset[0] * time_redraw * FLY_ROTATE_FAC);
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
-
- if (fly->xlock != FLY_AXISLOCK_STATE_OFF) {
- fly->xlock = FLY_AXISLOCK_STATE_ACTIVE; /* check for rotation */
- }
- if (fly->zlock != FLY_AXISLOCK_STATE_OFF) {
- fly->zlock = FLY_AXISLOCK_STATE_ACTIVE;
- }
- }
-
- if (fly->zlock == FLY_AXISLOCK_STATE_ACTIVE) {
- float upvec[3];
- copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
- mul_m3_v3(mat, upvec);
-
- /* make sure we have some z rolling */
- if (fabsf(upvec[2]) > 0.00001f) {
- roll = upvec[2] * 5.0f;
- /* rotate the view about this axis */
- copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
- mul_m3_v3(mat, upvec);
- /* Rotate about the relative up vec */
- axis_angle_to_quat(tmp_quat, upvec,
- roll * time_redraw_clamped * fly->zlock_momentum * FLY_ZUP_CORRECT_FAC);
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
-
- fly->zlock_momentum += FLY_ZUP_CORRECT_ACCEL;
- }
- else {
- /* don't check until the view rotates again */
- fly->zlock = FLY_AXISLOCK_STATE_IDLE;
- fly->zlock_momentum = 0.0f;
- }
- }
-
- /* only apply xcorrect when mouse isn't applying x rot */
- if (fly->xlock == FLY_AXISLOCK_STATE_ACTIVE && moffset[1] == 0) {
- float upvec[3];
- copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
- mul_m3_v3(mat, upvec);
- /* make sure we have some z rolling */
- if (fabsf(upvec[2]) > 0.00001f) {
- roll = upvec[2] * -5.0f;
- /* rotate the view about this axis */
- copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
- mul_m3_v3(mat, upvec);
-
- /* Rotate about the relative up vec */
- axis_angle_to_quat(tmp_quat, upvec, roll * time_redraw_clamped * fly->xlock_momentum * 0.1f);
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
-
- fly->xlock_momentum += 0.05f;
- }
- else {
- fly->xlock = FLY_AXISLOCK_STATE_IDLE; /* see above */
- fly->xlock_momentum = 0.0f;
- }
- }
-
- if (fly->axis == -1) {
- /* pause */
- zero_v3(dvec_tmp);
- }
- else if (!fly->use_freelook) {
- /* Normal operation */
- /* define dvec, view direction vector */
- zero_v3(dvec_tmp);
- /* move along the current axis */
- dvec_tmp[fly->axis] = 1.0f;
-
- mul_m3_v3(mat, dvec_tmp);
- }
- else {
- normalize_v3_v3(dvec_tmp, fly->dvec_prev);
- if (fly->speed < 0.0f) {
- negate_v3(dvec_tmp);
- }
- }
-
- mul_v3_fl(dvec_tmp, fly->speed * time_redraw * 0.25f);
- }
-
- /* impose a directional lag */
- interp_v3_v3v3(dvec, dvec_tmp, fly->dvec_prev, (1.0f / (1.0f + (time_redraw * FLY_SMOOTH_FAC))));
-
- if (rv3d->persp == RV3D_CAMOB) {
- Object *lock_ob = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control);
- if (lock_ob->protectflag & OB_LOCK_LOCX) {
- dvec[0] = 0.0;
- }
- if (lock_ob->protectflag & OB_LOCK_LOCY) {
- dvec[1] = 0.0;
- }
- if (lock_ob->protectflag & OB_LOCK_LOCZ) {
- dvec[2] = 0.0;
- }
- }
-
- add_v3_v3(rv3d->ofs, dvec);
-
- if (rv3d->persp == RV3D_CAMOB) {
- const bool do_rotate = ((fly->xlock != FLY_AXISLOCK_STATE_OFF) ||
- (fly->zlock != FLY_AXISLOCK_STATE_OFF) ||
- ((moffset[0] || moffset[1]) && !fly->pan_view));
- const bool do_translate = (fly->speed != 0.0f || fly->pan_view);
- flyMoveCamera(C, fly, do_rotate, do_translate);
- }
-
- }
- else {
- /* we're not redrawing but we need to update the time else the view will jump */
- fly->time_lastdraw = PIL_check_seconds_timer();
- }
- /* end drawing */
- copy_v3_v3(fly->dvec_prev, dvec);
- }
-
- return OPERATOR_FINISHED;
+ time_current = PIL_check_seconds_timer();
+ time_redraw = (float)(time_current - fly->time_lastdraw);
+
+ /* clamp redraw time to avoid jitter in roll correction */
+ time_redraw_clamped = min_ff(0.05f, time_redraw);
+
+ fly->time_lastdraw = time_current;
+
+ /* Scale the time to use shift to scale the speed down- just like
+ * shift slows many other areas of blender down */
+ if (fly->use_precision) {
+ fly->speed = fly->speed * (1.0f - time_redraw_clamped);
+ }
+
+ copy_m3_m4(mat, rv3d->viewinv);
+
+ if (fly->pan_view == true) {
+ /* pan only */
+ copy_v3_fl3(dvec_tmp, -moffset[0], -moffset[1], 0.0f);
+
+ if (fly->use_precision) {
+ dvec_tmp[0] *= 0.1f;
+ dvec_tmp[1] *= 0.1f;
+ }
+
+ mul_m3_v3(mat, dvec_tmp);
+ mul_v3_fl(dvec_tmp, time_redraw * 200.0f * fly->grid);
+ }
+ else {
+ float roll; /* similar to the angle between the camera's up and the Z-up,
+ * but its very rough so just roll */
+
+ /* rotate about the X axis- look up/down */
+ if (moffset[1]) {
+ float upvec[3];
+ copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
+ mul_m3_v3(mat, upvec);
+ /* Rotate about the relative up vec */
+ axis_angle_to_quat(tmp_quat, upvec, moffset[1] * time_redraw * -FLY_ROTATE_FAC);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
+
+ if (fly->xlock != FLY_AXISLOCK_STATE_OFF) {
+ fly->xlock = FLY_AXISLOCK_STATE_ACTIVE; /* check for rotation */
+ }
+ if (fly->zlock != FLY_AXISLOCK_STATE_OFF) {
+ fly->zlock = FLY_AXISLOCK_STATE_ACTIVE;
+ }
+ fly->xlock_momentum = 0.0f;
+ }
+
+ /* rotate about the Y axis- look left/right */
+ if (moffset[0]) {
+ float upvec[3];
+ /* if we're upside down invert the moffset */
+ copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f);
+ mul_m3_v3(mat, upvec);
+
+ if (upvec[2] < 0.0f) {
+ moffset[0] = -moffset[0];
+ }
+
+ /* make the lock vectors */
+ if (fly->zlock) {
+ copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
+ }
+ else {
+ copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f);
+ mul_m3_v3(mat, upvec);
+ }
+
+ /* Rotate about the relative up vec */
+ axis_angle_to_quat(tmp_quat, upvec, moffset[0] * time_redraw * FLY_ROTATE_FAC);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
+
+ if (fly->xlock != FLY_AXISLOCK_STATE_OFF) {
+ fly->xlock = FLY_AXISLOCK_STATE_ACTIVE; /* check for rotation */
+ }
+ if (fly->zlock != FLY_AXISLOCK_STATE_OFF) {
+ fly->zlock = FLY_AXISLOCK_STATE_ACTIVE;
+ }
+ }
+
+ if (fly->zlock == FLY_AXISLOCK_STATE_ACTIVE) {
+ float upvec[3];
+ copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
+ mul_m3_v3(mat, upvec);
+
+ /* make sure we have some z rolling */
+ if (fabsf(upvec[2]) > 0.00001f) {
+ roll = upvec[2] * 5.0f;
+ /* rotate the view about this axis */
+ copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
+ mul_m3_v3(mat, upvec);
+ /* Rotate about the relative up vec */
+ axis_angle_to_quat(tmp_quat,
+ upvec,
+ roll * time_redraw_clamped * fly->zlock_momentum *
+ FLY_ZUP_CORRECT_FAC);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
+
+ fly->zlock_momentum += FLY_ZUP_CORRECT_ACCEL;
+ }
+ else {
+ /* don't check until the view rotates again */
+ fly->zlock = FLY_AXISLOCK_STATE_IDLE;
+ fly->zlock_momentum = 0.0f;
+ }
+ }
+
+ /* only apply xcorrect when mouse isn't applying x rot */
+ if (fly->xlock == FLY_AXISLOCK_STATE_ACTIVE && moffset[1] == 0) {
+ float upvec[3];
+ copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
+ mul_m3_v3(mat, upvec);
+ /* make sure we have some z rolling */
+ if (fabsf(upvec[2]) > 0.00001f) {
+ roll = upvec[2] * -5.0f;
+ /* rotate the view about this axis */
+ copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
+ mul_m3_v3(mat, upvec);
+
+ /* Rotate about the relative up vec */
+ axis_angle_to_quat(
+ tmp_quat, upvec, roll * time_redraw_clamped * fly->xlock_momentum * 0.1f);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
+
+ fly->xlock_momentum += 0.05f;
+ }
+ else {
+ fly->xlock = FLY_AXISLOCK_STATE_IDLE; /* see above */
+ fly->xlock_momentum = 0.0f;
+ }
+ }
+
+ if (fly->axis == -1) {
+ /* pause */
+ zero_v3(dvec_tmp);
+ }
+ else if (!fly->use_freelook) {
+ /* Normal operation */
+ /* define dvec, view direction vector */
+ zero_v3(dvec_tmp);
+ /* move along the current axis */
+ dvec_tmp[fly->axis] = 1.0f;
+
+ mul_m3_v3(mat, dvec_tmp);
+ }
+ else {
+ normalize_v3_v3(dvec_tmp, fly->dvec_prev);
+ if (fly->speed < 0.0f) {
+ negate_v3(dvec_tmp);
+ }
+ }
+
+ mul_v3_fl(dvec_tmp, fly->speed * time_redraw * 0.25f);
+ }
+
+ /* impose a directional lag */
+ interp_v3_v3v3(
+ dvec, dvec_tmp, fly->dvec_prev, (1.0f / (1.0f + (time_redraw * FLY_SMOOTH_FAC))));
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ Object *lock_ob = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control);
+ if (lock_ob->protectflag & OB_LOCK_LOCX) {
+ dvec[0] = 0.0;
+ }
+ if (lock_ob->protectflag & OB_LOCK_LOCY) {
+ dvec[1] = 0.0;
+ }
+ if (lock_ob->protectflag & OB_LOCK_LOCZ) {
+ dvec[2] = 0.0;
+ }
+ }
+
+ add_v3_v3(rv3d->ofs, dvec);
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ const bool do_rotate = ((fly->xlock != FLY_AXISLOCK_STATE_OFF) ||
+ (fly->zlock != FLY_AXISLOCK_STATE_OFF) ||
+ ((moffset[0] || moffset[1]) && !fly->pan_view));
+ const bool do_translate = (fly->speed != 0.0f || fly->pan_view);
+ flyMoveCamera(C, fly, do_rotate, do_translate);
+ }
+ }
+ else {
+ /* we're not redrawing but we need to update the time else the view will jump */
+ fly->time_lastdraw = PIL_check_seconds_timer();
+ }
+ /* end drawing */
+ copy_v3_v3(fly->dvec_prev, dvec);
+ }
+
+ return OPERATOR_FINISHED;
}
#ifdef WITH_INPUT_NDOF
static void flyApply_ndof(bContext *C, FlyInfo *fly)
{
- Object *lock_ob = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control);
- bool has_translate, has_rotate;
-
- view3d_ndof_fly(fly->ndof,
- fly->v3d, fly->rv3d,
- fly->use_precision, lock_ob ? lock_ob->protectflag : 0,
- &has_translate, &has_rotate);
-
- if (has_translate || has_rotate) {
- fly->redraw = true;
-
- if (fly->rv3d->persp == RV3D_CAMOB) {
- flyMoveCamera(C, fly, has_rotate, has_translate);
- }
- }
+ Object *lock_ob = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control);
+ bool has_translate, has_rotate;
+
+ view3d_ndof_fly(fly->ndof,
+ fly->v3d,
+ fly->rv3d,
+ fly->use_precision,
+ lock_ob ? lock_ob->protectflag : 0,
+ &has_translate,
+ &has_rotate);
+
+ if (has_translate || has_rotate) {
+ fly->redraw = true;
+
+ if (fly->rv3d->persp == RV3D_CAMOB) {
+ flyMoveCamera(C, fly, has_rotate, has_translate);
+ }
+ }
}
#endif /* WITH_INPUT_NDOF */
static int fly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- FlyInfo *fly;
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ FlyInfo *fly;
- if (rv3d->viewlock & RV3D_LOCKED) {
- return OPERATOR_CANCELLED;
- }
+ if (rv3d->viewlock & RV3D_LOCKED) {
+ return OPERATOR_CANCELLED;
+ }
- fly = MEM_callocN(sizeof(FlyInfo), "FlyOperation");
+ fly = MEM_callocN(sizeof(FlyInfo), "FlyOperation");
- op->customdata = fly;
+ op->customdata = fly;
- if (initFlyInfo(C, fly, op, event) == false) {
- MEM_freeN(op->customdata);
- return OPERATOR_CANCELLED;
- }
+ if (initFlyInfo(C, fly, op, event) == false) {
+ MEM_freeN(op->customdata);
+ return OPERATOR_CANCELLED;
+ }
- flyEvent(C, op, fly, event);
+ flyEvent(C, op, fly, event);
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static void fly_cancel(bContext *C, wmOperator *op)
{
- FlyInfo *fly = op->customdata;
+ FlyInfo *fly = op->customdata;
- fly->state = FLY_CANCEL;
- flyEnd(C, fly);
- op->customdata = NULL;
+ fly->state = FLY_CANCEL;
+ flyEnd(C, fly);
+ op->customdata = NULL;
}
static int fly_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- int exit_code;
- bool do_draw = false;
- FlyInfo *fly = op->customdata;
- RegionView3D *rv3d = fly->rv3d;
- Object *fly_object = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control);
+ int exit_code;
+ bool do_draw = false;
+ FlyInfo *fly = op->customdata;
+ RegionView3D *rv3d = fly->rv3d;
+ Object *fly_object = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control);
- fly->redraw = 0;
+ fly->redraw = 0;
- flyEvent(C, op, fly, event);
+ flyEvent(C, op, fly, event);
#ifdef WITH_INPUT_NDOF
- if (fly->ndof) { /* 3D mouse overrules [2D mouse + timer] */
- if (event->type == NDOF_MOTION) {
- flyApply_ndof(C, fly);
- }
- }
- else
+ if (fly->ndof) { /* 3D mouse overrules [2D mouse + timer] */
+ if (event->type == NDOF_MOTION) {
+ flyApply_ndof(C, fly);
+ }
+ }
+ else
#endif /* WITH_INPUT_NDOF */
- if (event->type == TIMER && event->customdata == fly->timer) {
- flyApply(C, fly);
- }
+ if (event->type == TIMER && event->customdata == fly->timer) {
+ flyApply(C, fly);
+ }
- do_draw |= fly->redraw;
+ do_draw |= fly->redraw;
- exit_code = flyEnd(C, fly);
+ exit_code = flyEnd(C, fly);
- if (exit_code != OPERATOR_RUNNING_MODAL) {
- do_draw = true;
- }
+ if (exit_code != OPERATOR_RUNNING_MODAL) {
+ do_draw = true;
+ }
- if (do_draw) {
- if (rv3d->persp == RV3D_CAMOB) {
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, fly_object);
- }
+ if (do_draw) {
+ if (rv3d->persp == RV3D_CAMOB) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, fly_object);
+ }
- // puts("redraw!"); // too frequent, commented with NDOF_FLY_DRAW_TOOMUCH for now
- ED_region_tag_redraw(CTX_wm_region(C));
- }
+ // puts("redraw!"); // too frequent, commented with NDOF_FLY_DRAW_TOOMUCH for now
+ ED_region_tag_redraw(CTX_wm_region(C));
+ }
- if (ELEM(exit_code, OPERATOR_FINISHED, OPERATOR_CANCELLED)) {
- ED_workspace_status_text(C, NULL);
- }
+ if (ELEM(exit_code, OPERATOR_FINISHED, OPERATOR_CANCELLED)) {
+ ED_workspace_status_text(C, NULL);
+ }
- return exit_code;
+ return exit_code;
}
void VIEW3D_OT_fly(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Fly Navigation";
- ot->description = "Interactively fly around the scene";
- ot->idname = "VIEW3D_OT_fly";
-
- /* api callbacks */
- ot->invoke = fly_invoke;
- ot->cancel = fly_cancel;
- ot->modal = fly_modal;
- ot->poll = ED_operator_region_view3d_active;
-
- /* flags */
- ot->flag = OPTYPE_BLOCKING;
+ /* identifiers */
+ ot->name = "Fly Navigation";
+ ot->description = "Interactively fly around the scene";
+ ot->idname = "VIEW3D_OT_fly";
+
+ /* api callbacks */
+ ot->invoke = fly_invoke;
+ ot->cancel = fly_cancel;
+ ot->modal = fly_modal;
+ ot->poll = ED_operator_region_view3d_active;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
}
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_armature.c b/source/blender/editors/space_view3d/view3d_gizmo_armature.c
index 64617b03c5e..ae186505456 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_armature.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_armature.c
@@ -43,8 +43,7 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "view3d_intern.h" /* own include */
-
+#include "view3d_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Armature Spline Gizmo
@@ -63,166 +62,165 @@
#define BBONE_SCALE_Y 3.0f
struct BoneSplineHandle {
- wmGizmo *gizmo;
- bPoseChannel *pchan;
- /* We could remove, keep since at the moment for checking the conversion. */
- float co[3];
- int index;
+ wmGizmo *gizmo;
+ bPoseChannel *pchan;
+ /* We could remove, keep since at the moment for checking the conversion. */
+ float co[3];
+ int index;
};
struct BoneSplineWidgetGroup {
- struct BoneSplineHandle handles[2];
+ struct BoneSplineHandle handles[2];
};
-static void gizmo_bbone_offset_get(
- const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
- void *value_p)
+static void gizmo_bbone_offset_get(const wmGizmo *UNUSED(gz),
+ wmGizmoProperty *gz_prop,
+ void *value_p)
{
- struct BoneSplineHandle *bh = gz_prop->custom_func.user_data;
- bPoseChannel *pchan = bh->pchan;
-
- float *value = value_p;
- BLI_assert(gz_prop->type->array_length == 3);
-
- if (bh->index == 0) {
- bh->co[1] = pchan->bone->ease1 / BBONE_SCALE_Y;
- bh->co[0] = pchan->curveInX;
- bh->co[2] = pchan->curveInY;
- }
- else {
- bh->co[1] = -pchan->bone->ease2 / BBONE_SCALE_Y;
- bh->co[0] = pchan->curveOutX;
- bh->co[2] = pchan->curveOutY;
- }
- copy_v3_v3(value, bh->co);
+ struct BoneSplineHandle *bh = gz_prop->custom_func.user_data;
+ bPoseChannel *pchan = bh->pchan;
+
+ float *value = value_p;
+ BLI_assert(gz_prop->type->array_length == 3);
+
+ if (bh->index == 0) {
+ bh->co[1] = pchan->bone->ease1 / BBONE_SCALE_Y;
+ bh->co[0] = pchan->curveInX;
+ bh->co[2] = pchan->curveInY;
+ }
+ else {
+ bh->co[1] = -pchan->bone->ease2 / BBONE_SCALE_Y;
+ bh->co[0] = pchan->curveOutX;
+ bh->co[2] = pchan->curveOutY;
+ }
+ copy_v3_v3(value, bh->co);
}
-static void gizmo_bbone_offset_set(
- const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
- const void *value_p)
+static void gizmo_bbone_offset_set(const wmGizmo *UNUSED(gz),
+ wmGizmoProperty *gz_prop,
+ const void *value_p)
{
- struct BoneSplineHandle *bh = gz_prop->custom_func.user_data;
- bPoseChannel *pchan = bh->pchan;
-
- const float *value = value_p;
-
- BLI_assert(gz_prop->type->array_length == 3);
- copy_v3_v3(bh->co, value);
-
- if (bh->index == 0) {
- pchan->bone->ease1 = max_ff(0.0f, bh->co[1] * BBONE_SCALE_Y);
- pchan->curveInX = bh->co[0];
- pchan->curveInY = bh->co[2];
- }
- else {
- pchan->bone->ease2 = max_ff(0.0f, -bh->co[1] * BBONE_SCALE_Y);
- pchan->curveOutX = bh->co[0];
- pchan->curveOutY = bh->co[2];
- }
-
+ struct BoneSplineHandle *bh = gz_prop->custom_func.user_data;
+ bPoseChannel *pchan = bh->pchan;
+
+ const float *value = value_p;
+
+ BLI_assert(gz_prop->type->array_length == 3);
+ copy_v3_v3(bh->co, value);
+
+ if (bh->index == 0) {
+ pchan->bone->ease1 = max_ff(0.0f, bh->co[1] * BBONE_SCALE_Y);
+ pchan->curveInX = bh->co[0];
+ pchan->curveInY = bh->co[2];
+ }
+ else {
+ pchan->bone->ease2 = max_ff(0.0f, -bh->co[1] * BBONE_SCALE_Y);
+ pchan->curveOutX = bh->co[0];
+ pchan->curveOutY = bh->co[2];
+ }
}
static bool WIDGETGROUP_armature_spline_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) {
- return false;
- }
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base = BASACT(view_layer);
- if (base && BASE_SELECTABLE(v3d, base)) {
- Object *ob = BKE_object_pose_armature_get(base->object);
- if (ob) {
- const bArmature *arm = ob->data;
- if (arm->drawtype == ARM_B_BONE) {
- bPoseChannel *pchan = BKE_pose_channel_active(ob);
- if (pchan && pchan->bone->segments > 1) {
- return true;
- }
- }
- }
- }
- return false;
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) {
+ return false;
+ }
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base = BASACT(view_layer);
+ if (base && BASE_SELECTABLE(v3d, base)) {
+ Object *ob = BKE_object_pose_armature_get(base->object);
+ if (ob) {
+ const bArmature *arm = ob->data;
+ if (arm->drawtype == ARM_B_BONE) {
+ bPoseChannel *pchan = BKE_pose_channel_active(ob);
+ if (pchan && pchan->bone->segments > 1) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
}
-
static void WIDGETGROUP_armature_spline_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = BKE_object_pose_armature_get(OBACT(view_layer));
- bPoseChannel *pchan = BKE_pose_channel_active(ob);
-
- const wmGizmoType *gzt_move = WM_gizmotype_find("GIZMO_GT_move_3d", true);
-
- struct BoneSplineWidgetGroup *bspline_group = MEM_callocN(sizeof(struct BoneSplineWidgetGroup), __func__);
- gzgroup->customdata = bspline_group;
-
- /* Handles */
- for (int i = 0; i < ARRAY_SIZE(bspline_group->handles); i++) {
- wmGizmo *gz;
- gz = bspline_group->handles[i].gizmo = WM_gizmo_new_ptr(gzt_move, gzgroup, NULL);
- RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_RING_2D);
- RNA_enum_set(gz->ptr, "draw_options",
- ED_GIZMO_MOVE_DRAW_FLAG_FILL | ED_GIZMO_MOVE_DRAW_FLAG_ALIGN_VIEW);
- WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_VALUE, true);
-
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
-
- gz->scale_basis = 0.06f;
-
- if (i == 0) {
- copy_v3_v3(gz->matrix_basis[3], pchan->loc);
- }
- }
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = BKE_object_pose_armature_get(OBACT(view_layer));
+ bPoseChannel *pchan = BKE_pose_channel_active(ob);
+
+ const wmGizmoType *gzt_move = WM_gizmotype_find("GIZMO_GT_move_3d", true);
+
+ struct BoneSplineWidgetGroup *bspline_group = MEM_callocN(sizeof(struct BoneSplineWidgetGroup),
+ __func__);
+ gzgroup->customdata = bspline_group;
+
+ /* Handles */
+ for (int i = 0; i < ARRAY_SIZE(bspline_group->handles); i++) {
+ wmGizmo *gz;
+ gz = bspline_group->handles[i].gizmo = WM_gizmo_new_ptr(gzt_move, gzgroup, NULL);
+ RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_RING_2D);
+ RNA_enum_set(gz->ptr,
+ "draw_options",
+ ED_GIZMO_MOVE_DRAW_FLAG_FILL | ED_GIZMO_MOVE_DRAW_FLAG_ALIGN_VIEW);
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_VALUE, true);
+
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
+
+ gz->scale_basis = 0.06f;
+
+ if (i == 0) {
+ copy_v3_v3(gz->matrix_basis[3], pchan->loc);
+ }
+ }
}
static void WIDGETGROUP_armature_spline_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = BKE_object_pose_armature_get(OBACT(view_layer));
-
- if (!gzgroup->customdata) {
- return;
- }
-
- struct BoneSplineWidgetGroup *bspline_group = gzgroup->customdata;
- bPoseChannel *pchan = BKE_pose_channel_active(ob);
-
- /* Handles */
- for (int i = 0; i < ARRAY_SIZE(bspline_group->handles); i++) {
- wmGizmo *gz = bspline_group->handles[i].gizmo;
- bspline_group->handles[i].pchan = pchan;
- bspline_group->handles[i].index = i;
-
- float mat[4][4];
- mul_m4_m4m4(mat, ob->obmat, (i == 0) ? pchan->disp_mat : pchan->disp_tail_mat);
- copy_m4_m4(gz->matrix_space, mat);
-
- /* need to set property here for undo. TODO would prefer to do this in _init */
- WM_gizmo_target_property_def_func(
- gz, "offset",
- &(const struct wmGizmoPropertyFnParams) {
- .value_get_fn = gizmo_bbone_offset_get,
- .value_set_fn = gizmo_bbone_offset_set,
- .range_get_fn = NULL,
- .user_data = &bspline_group->handles[i],
- });
- }
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = BKE_object_pose_armature_get(OBACT(view_layer));
+
+ if (!gzgroup->customdata) {
+ return;
+ }
+
+ struct BoneSplineWidgetGroup *bspline_group = gzgroup->customdata;
+ bPoseChannel *pchan = BKE_pose_channel_active(ob);
+
+ /* Handles */
+ for (int i = 0; i < ARRAY_SIZE(bspline_group->handles); i++) {
+ wmGizmo *gz = bspline_group->handles[i].gizmo;
+ bspline_group->handles[i].pchan = pchan;
+ bspline_group->handles[i].index = i;
+
+ float mat[4][4];
+ mul_m4_m4m4(mat, ob->obmat, (i == 0) ? pchan->disp_mat : pchan->disp_tail_mat);
+ copy_m4_m4(gz->matrix_space, mat);
+
+ /* need to set property here for undo. TODO would prefer to do this in _init */
+ WM_gizmo_target_property_def_func(gz,
+ "offset",
+ &(const struct wmGizmoPropertyFnParams){
+ .value_get_fn = gizmo_bbone_offset_get,
+ .value_set_fn = gizmo_bbone_offset_set,
+ .range_get_fn = NULL,
+ .user_data = &bspline_group->handles[i],
+ });
+ }
}
void VIEW3D_GGT_armature_spline(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Armature Spline Widgets";
- gzgt->idname = "VIEW3D_GGT_armature_spline";
+ gzgt->name = "Armature Spline Widgets";
+ gzgt->idname = "VIEW3D_GGT_armature_spline";
- gzgt->flag = (WM_GIZMOGROUPTYPE_PERSISTENT |
- WM_GIZMOGROUPTYPE_3D);
+ gzgt->flag = (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_3D);
- gzgt->poll = WIDGETGROUP_armature_spline_poll;
- gzgt->setup = WIDGETGROUP_armature_spline_setup;
- gzgt->refresh = WIDGETGROUP_armature_spline_refresh;
+ gzgt->poll = WIDGETGROUP_armature_spline_poll;
+ gzgt->setup = WIDGETGROUP_armature_spline_setup;
+ gzgt->refresh = WIDGETGROUP_armature_spline_refresh;
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_camera.c b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
index 590597145a0..0b8c3b8cd28 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_camera.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
@@ -18,7 +18,6 @@
* \ingroup spview3d
*/
-
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -45,276 +44,279 @@
#include "DEG_depsgraph.h"
-#include "view3d_intern.h" /* own include */
-
+#include "view3d_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Camera Gizmos
* \{ */
struct CameraWidgetGroup {
- wmGizmo *dop_dist;
- wmGizmo *focal_len;
- wmGizmo *ortho_scale;
+ wmGizmo *dop_dist;
+ wmGizmo *focal_len;
+ wmGizmo *ortho_scale;
};
static bool WIDGETGROUP_camera_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) {
- return false;
- }
- if ((v3d->gizmo_show_camera & V3D_GIZMO_SHOW_CAMERA_LENS) == 0 &&
- (v3d->gizmo_show_camera & V3D_GIZMO_SHOW_CAMERA_DOF_DIST) == 0)
- {
- return false;
- }
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base = BASACT(view_layer);
- if (base && BASE_SELECTABLE(v3d, base)) {
- Object *ob = base->object;
- if (ob->type == OB_CAMERA) {
- Camera *camera = ob->data;
- /* TODO: support overrides. */
- if (camera->id.lib == NULL) {
- return true;
- }
- }
- }
- return false;
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) {
+ return false;
+ }
+ if ((v3d->gizmo_show_camera & V3D_GIZMO_SHOW_CAMERA_LENS) == 0 &&
+ (v3d->gizmo_show_camera & V3D_GIZMO_SHOW_CAMERA_DOF_DIST) == 0) {
+ return false;
+ }
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base = BASACT(view_layer);
+ if (base && BASE_SELECTABLE(v3d, base)) {
+ Object *ob = base->object;
+ if (ob->type == OB_CAMERA) {
+ Camera *camera = ob->data;
+ /* TODO: support overrides. */
+ if (camera->id.lib == NULL) {
+ return true;
+ }
+ }
+ }
+ return false;
}
static void WIDGETGROUP_camera_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- float dir[3];
-
- const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
-
- struct CameraWidgetGroup *cagzgroup = MEM_callocN(sizeof(struct CameraWidgetGroup), __func__);
- gzgroup->customdata = cagzgroup;
-
- negate_v3_v3(dir, ob->obmat[2]);
-
- /* dof distance */
- {
- wmGizmo *gz;
- gz = cagzgroup->dop_dist = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
- RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CROSS);
- WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true);
-
- UI_GetThemeColor3fv(TH_GIZMO_A, gz->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
- }
-
- /* focal length
- * - logic/calculations are similar to BKE_camera_view_frame_ex, better keep in sync */
- {
- wmGizmo *gz;
- gz = cagzgroup->focal_len = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
- gz->flag |= WM_GIZMO_DRAW_NO_SCALE;
- RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CONE);
- RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED);
-
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
-
- gz = cagzgroup->ortho_scale = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
- gz->flag |= WM_GIZMO_DRAW_NO_SCALE;
- RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CONE);
- RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED);
-
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
- }
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ float dir[3];
+
+ const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
+
+ struct CameraWidgetGroup *cagzgroup = MEM_callocN(sizeof(struct CameraWidgetGroup), __func__);
+ gzgroup->customdata = cagzgroup;
+
+ negate_v3_v3(dir, ob->obmat[2]);
+
+ /* dof distance */
+ {
+ wmGizmo *gz;
+ gz = cagzgroup->dop_dist = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CROSS);
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true);
+
+ UI_GetThemeColor3fv(TH_GIZMO_A, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
+ }
+
+ /* focal length
+ * - logic/calculations are similar to BKE_camera_view_frame_ex, better keep in sync */
+ {
+ wmGizmo *gz;
+ gz = cagzgroup->focal_len = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ gz->flag |= WM_GIZMO_DRAW_NO_SCALE;
+ RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CONE);
+ RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED);
+
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
+
+ gz = cagzgroup->ortho_scale = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ gz->flag |= WM_GIZMO_DRAW_NO_SCALE;
+ RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CONE);
+ RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED);
+
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
+ }
}
static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- if (!gzgroup->customdata) {
- return;
- }
-
- struct CameraWidgetGroup *cagzgroup = gzgroup->customdata;
- View3D *v3d = CTX_wm_view3d(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- Camera *ca = ob->data;
- PointerRNA camera_ptr;
- float dir[3];
-
- RNA_pointer_create(&ca->id, &RNA_Camera, ca, &camera_ptr);
-
- negate_v3_v3(dir, ob->obmat[2]);
-
- if ((ca->flag & CAM_SHOWLIMITS) &&
- (v3d->gizmo_show_camera & V3D_GIZMO_SHOW_CAMERA_DOF_DIST))
- {
- WM_gizmo_set_matrix_location(cagzgroup->dop_dist, ob->obmat[3]);
- WM_gizmo_set_matrix_rotation_from_yz_axis(cagzgroup->dop_dist, ob->obmat[1], dir);
- WM_gizmo_set_scale(cagzgroup->dop_dist, ca->drawsize);
- WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, false);
-
- /* need to set property here for undo. TODO would prefer to do this in _init */
- WM_gizmo_target_property_def_rna(cagzgroup->dop_dist, "offset", &camera_ptr, "dof_distance", -1);
- }
- else {
- WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, true);
- }
-
- /* TODO - make focal length/ortho ob_scale_inv widget optional */
- const Scene *scene = CTX_data_scene(C);
- const float aspx = (float)scene->r.xsch * scene->r.xasp;
- const float aspy = (float)scene->r.ysch * scene->r.yasp;
- const bool is_ortho = (ca->type == CAM_ORTHO);
- const int sensor_fit = BKE_camera_sensor_fit(ca->sensor_fit, aspx, aspy);
- /* Important to use camera value, not calculated fit since 'AUTO' uses width always. */
- const float sensor_size = BKE_camera_sensor_size(ca->sensor_fit, ca->sensor_x, ca->sensor_y);
- wmGizmo *widget = is_ortho ? cagzgroup->ortho_scale : cagzgroup->focal_len;
- float scale_matrix;
- if (true) {
- float offset[3];
- float aspect[2];
-
- WM_gizmo_set_flag(widget, WM_GIZMO_HIDDEN, false);
- WM_gizmo_set_flag(is_ortho ? cagzgroup->focal_len : cagzgroup->ortho_scale, WM_GIZMO_HIDDEN, true);
-
-
- /* account for lens shifting */
- offset[0] = ((ob->scale[0] > 0.0f) ? -2.0f : 2.0f) * ca->shiftx;
- offset[1] = 2.0f * ca->shifty;
- offset[2] = 0.0f;
-
- /* get aspect */
- aspect[0] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? 1.0f : aspx / aspy;
- aspect[1] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? aspy / aspx : 1.0f;
-
- unit_m4(widget->matrix_basis);
- WM_gizmo_set_matrix_location(widget, ob->obmat[3]);
- WM_gizmo_set_matrix_rotation_from_yz_axis(widget, ob->obmat[1], dir);
-
- if (is_ortho) {
- scale_matrix = ca->ortho_scale * 0.5f;
- }
- else {
- const float ob_scale_inv[3] = {
- 1.0f / len_v3(ob->obmat[0]),
- 1.0f / len_v3(ob->obmat[1]),
- 1.0f / len_v3(ob->obmat[2]),
- };
- const float ob_scale_uniform_inv = (ob_scale_inv[0] + ob_scale_inv[1] + ob_scale_inv[2]) / 3.0f;
- scale_matrix = (ca->drawsize * 0.5f) / ob_scale_uniform_inv;
- }
- mul_v3_fl(widget->matrix_basis[0], scale_matrix);
- mul_v3_fl(widget->matrix_basis[1], scale_matrix);
-
- RNA_float_set_array(widget->ptr, "aspect", aspect);
-
- WM_gizmo_set_matrix_offset_location(widget, offset);
- }
-
- /* define & update properties */
- {
- const char *propname = is_ortho ? "ortho_scale" : "lens";
- PropertyRNA *prop = RNA_struct_find_property(&camera_ptr, propname);
- const wmGizmoPropertyType *gz_prop_type = WM_gizmotype_target_property_find(widget->type, "offset");
-
- WM_gizmo_target_property_clear_rna_ptr(widget, gz_prop_type);
-
- float min, max, range;
- float step, precision;
-
- /* get property range */
- RNA_property_float_ui_range(&camera_ptr, prop, &min, &max, &step, &precision);
- range = max - min;
-
- ED_gizmo_arrow3d_set_range_fac(
- widget, is_ortho ?
- ((range / ca->ortho_scale) * ca->drawsize) :
- (scale_matrix * range /
- /* Half sensor, intentionally use sensor from camera and not calculated above. */
- (0.5f * sensor_size)));
-
- WM_gizmo_target_property_def_rna_ptr(widget, gz_prop_type, &camera_ptr, prop, -1);
- }
-
- /* This could be handled more elegently (split into two gizmo groups). */
- if ((v3d->gizmo_show_camera & V3D_GIZMO_SHOW_CAMERA_LENS) == 0) {
- WM_gizmo_set_flag(cagzgroup->focal_len, WM_GIZMO_HIDDEN, true);
- WM_gizmo_set_flag(cagzgroup->ortho_scale, WM_GIZMO_HIDDEN, true);
- }
+ if (!gzgroup->customdata) {
+ return;
+ }
+
+ struct CameraWidgetGroup *cagzgroup = gzgroup->customdata;
+ View3D *v3d = CTX_wm_view3d(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ Camera *ca = ob->data;
+ PointerRNA camera_ptr;
+ float dir[3];
+
+ RNA_pointer_create(&ca->id, &RNA_Camera, ca, &camera_ptr);
+
+ negate_v3_v3(dir, ob->obmat[2]);
+
+ if ((ca->flag & CAM_SHOWLIMITS) && (v3d->gizmo_show_camera & V3D_GIZMO_SHOW_CAMERA_DOF_DIST)) {
+ WM_gizmo_set_matrix_location(cagzgroup->dop_dist, ob->obmat[3]);
+ WM_gizmo_set_matrix_rotation_from_yz_axis(cagzgroup->dop_dist, ob->obmat[1], dir);
+ WM_gizmo_set_scale(cagzgroup->dop_dist, ca->drawsize);
+ WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, false);
+
+ /* need to set property here for undo. TODO would prefer to do this in _init */
+ WM_gizmo_target_property_def_rna(
+ cagzgroup->dop_dist, "offset", &camera_ptr, "dof_distance", -1);
+ }
+ else {
+ WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, true);
+ }
+
+ /* TODO - make focal length/ortho ob_scale_inv widget optional */
+ const Scene *scene = CTX_data_scene(C);
+ const float aspx = (float)scene->r.xsch * scene->r.xasp;
+ const float aspy = (float)scene->r.ysch * scene->r.yasp;
+ const bool is_ortho = (ca->type == CAM_ORTHO);
+ const int sensor_fit = BKE_camera_sensor_fit(ca->sensor_fit, aspx, aspy);
+ /* Important to use camera value, not calculated fit since 'AUTO' uses width always. */
+ const float sensor_size = BKE_camera_sensor_size(ca->sensor_fit, ca->sensor_x, ca->sensor_y);
+ wmGizmo *widget = is_ortho ? cagzgroup->ortho_scale : cagzgroup->focal_len;
+ float scale_matrix;
+ if (true) {
+ float offset[3];
+ float aspect[2];
+
+ WM_gizmo_set_flag(widget, WM_GIZMO_HIDDEN, false);
+ WM_gizmo_set_flag(
+ is_ortho ? cagzgroup->focal_len : cagzgroup->ortho_scale, WM_GIZMO_HIDDEN, true);
+
+ /* account for lens shifting */
+ offset[0] = ((ob->scale[0] > 0.0f) ? -2.0f : 2.0f) * ca->shiftx;
+ offset[1] = 2.0f * ca->shifty;
+ offset[2] = 0.0f;
+
+ /* get aspect */
+ aspect[0] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? 1.0f : aspx / aspy;
+ aspect[1] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? aspy / aspx : 1.0f;
+
+ unit_m4(widget->matrix_basis);
+ WM_gizmo_set_matrix_location(widget, ob->obmat[3]);
+ WM_gizmo_set_matrix_rotation_from_yz_axis(widget, ob->obmat[1], dir);
+
+ if (is_ortho) {
+ scale_matrix = ca->ortho_scale * 0.5f;
+ }
+ else {
+ const float ob_scale_inv[3] = {
+ 1.0f / len_v3(ob->obmat[0]),
+ 1.0f / len_v3(ob->obmat[1]),
+ 1.0f / len_v3(ob->obmat[2]),
+ };
+ const float ob_scale_uniform_inv = (ob_scale_inv[0] + ob_scale_inv[1] + ob_scale_inv[2]) /
+ 3.0f;
+ scale_matrix = (ca->drawsize * 0.5f) / ob_scale_uniform_inv;
+ }
+ mul_v3_fl(widget->matrix_basis[0], scale_matrix);
+ mul_v3_fl(widget->matrix_basis[1], scale_matrix);
+
+ RNA_float_set_array(widget->ptr, "aspect", aspect);
+
+ WM_gizmo_set_matrix_offset_location(widget, offset);
+ }
+
+ /* define & update properties */
+ {
+ const char *propname = is_ortho ? "ortho_scale" : "lens";
+ PropertyRNA *prop = RNA_struct_find_property(&camera_ptr, propname);
+ const wmGizmoPropertyType *gz_prop_type = WM_gizmotype_target_property_find(widget->type,
+ "offset");
+
+ WM_gizmo_target_property_clear_rna_ptr(widget, gz_prop_type);
+
+ float min, max, range;
+ float step, precision;
+
+ /* get property range */
+ RNA_property_float_ui_range(&camera_ptr, prop, &min, &max, &step, &precision);
+ range = max - min;
+
+ ED_gizmo_arrow3d_set_range_fac(
+ widget,
+ is_ortho ?
+ ((range / ca->ortho_scale) * ca->drawsize) :
+ (scale_matrix * range /
+ /* Half sensor, intentionally use sensor from camera and not calculated above. */
+ (0.5f * sensor_size)));
+
+ WM_gizmo_target_property_def_rna_ptr(widget, gz_prop_type, &camera_ptr, prop, -1);
+ }
+
+ /* This could be handled more elegently (split into two gizmo groups). */
+ if ((v3d->gizmo_show_camera & V3D_GIZMO_SHOW_CAMERA_LENS) == 0) {
+ WM_gizmo_set_flag(cagzgroup->focal_len, WM_GIZMO_HIDDEN, true);
+ WM_gizmo_set_flag(cagzgroup->ortho_scale, WM_GIZMO_HIDDEN, true);
+ }
}
-static void WIDGETGROUP_camera_message_subscribe(
- const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus)
+static void WIDGETGROUP_camera_message_subscribe(const bContext *C,
+ wmGizmoGroup *gzgroup,
+ struct wmMsgBus *mbus)
{
- ARegion *ar = 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,
- .user_data = gzgroup->parent_gzmap,
- .notify = WM_gizmo_do_msg_notify_tag_refresh,
- };
-
- {
- extern PropertyRNA rna_Camera_dof_distance;
- extern PropertyRNA rna_Camera_display_size;
- extern PropertyRNA rna_Camera_ortho_scale;
- extern PropertyRNA rna_Camera_sensor_fit;
- extern PropertyRNA rna_Camera_sensor_width;
- extern PropertyRNA rna_Camera_sensor_height;
- extern PropertyRNA rna_Camera_shift_x;
- extern PropertyRNA rna_Camera_shift_y;
- extern PropertyRNA rna_Camera_type;
- extern PropertyRNA rna_Camera_lens;
- const PropertyRNA *props[] = {
- &rna_Camera_dof_distance,
- &rna_Camera_display_size,
- &rna_Camera_ortho_scale,
- &rna_Camera_sensor_fit,
- &rna_Camera_sensor_width,
- &rna_Camera_sensor_height,
- &rna_Camera_shift_x,
- &rna_Camera_shift_y,
- &rna_Camera_type,
- &rna_Camera_lens,
- };
-
- PointerRNA idptr;
- RNA_id_pointer_create(&ca->id, &idptr);
-
- for (int i = 0; i < ARRAY_SIZE(props); i++) {
- WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
- }
- }
-
- /* Subscribe to render settings */
- {
- WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_x, &msg_sub_value_gz_tag_refresh);
- WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_y, &msg_sub_value_gz_tag_refresh);
- WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_gz_tag_refresh);
- WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_gz_tag_refresh);
- }
+ ARegion *ar = 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,
+ .user_data = gzgroup->parent_gzmap,
+ .notify = WM_gizmo_do_msg_notify_tag_refresh,
+ };
+
+ {
+ extern PropertyRNA rna_Camera_dof_distance;
+ extern PropertyRNA rna_Camera_display_size;
+ extern PropertyRNA rna_Camera_ortho_scale;
+ extern PropertyRNA rna_Camera_sensor_fit;
+ extern PropertyRNA rna_Camera_sensor_width;
+ extern PropertyRNA rna_Camera_sensor_height;
+ extern PropertyRNA rna_Camera_shift_x;
+ extern PropertyRNA rna_Camera_shift_y;
+ extern PropertyRNA rna_Camera_type;
+ extern PropertyRNA rna_Camera_lens;
+ const PropertyRNA *props[] = {
+ &rna_Camera_dof_distance,
+ &rna_Camera_display_size,
+ &rna_Camera_ortho_scale,
+ &rna_Camera_sensor_fit,
+ &rna_Camera_sensor_width,
+ &rna_Camera_sensor_height,
+ &rna_Camera_shift_x,
+ &rna_Camera_shift_y,
+ &rna_Camera_type,
+ &rna_Camera_lens,
+ };
+
+ PointerRNA idptr;
+ RNA_id_pointer_create(&ca->id, &idptr);
+
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
+ }
+ }
+
+ /* Subscribe to render settings */
+ {
+ WM_msg_subscribe_rna_anon_prop(
+ mbus, RenderSettings, resolution_x, &msg_sub_value_gz_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(
+ mbus, RenderSettings, resolution_y, &msg_sub_value_gz_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(
+ mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_gz_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(
+ mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_gz_tag_refresh);
+ }
}
void VIEW3D_GGT_camera(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Camera Widgets";
- gzgt->idname = "VIEW3D_GGT_camera";
+ gzgt->name = "Camera Widgets";
+ gzgt->idname = "VIEW3D_GGT_camera";
- gzgt->flag = (WM_GIZMOGROUPTYPE_PERSISTENT |
- WM_GIZMOGROUPTYPE_3D |
- WM_GIZMOGROUPTYPE_DEPTH_3D);
+ gzgt->flag = (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_DEPTH_3D);
- gzgt->poll = WIDGETGROUP_camera_poll;
- gzgt->setup = WIDGETGROUP_camera_setup;
- gzgt->refresh = WIDGETGROUP_camera_refresh;
- gzgt->message_subscribe = WIDGETGROUP_camera_message_subscribe;
+ gzgt->poll = WIDGETGROUP_camera_poll;
+ gzgt->setup = WIDGETGROUP_camera_setup;
+ gzgt->refresh = WIDGETGROUP_camera_refresh;
+ gzgt->message_subscribe = WIDGETGROUP_camera_message_subscribe;
}
/** \} */
@@ -324,177 +326,191 @@ void VIEW3D_GGT_camera(wmGizmoGroupType *gzgt)
* \{ */
struct CameraViewWidgetGroup {
- Scene *scene;
- bool is_camera;
+ Scene *scene;
+ bool is_camera;
- wmGizmo *border;
+ wmGizmo *border;
- struct {
- rctf *edit_border;
- rctf view_border;
- } state;
+ struct {
+ rctf *edit_border;
+ rctf view_border;
+ } state;
};
/* scale callbacks */
-static void gizmo_render_border_prop_matrix_get(
- const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
- void *value_p)
+static void gizmo_render_border_prop_matrix_get(const wmGizmo *UNUSED(gz),
+ wmGizmoProperty *gz_prop,
+ void *value_p)
{
- float (*matrix)[4] = value_p;
- BLI_assert(gz_prop->type->array_length == 16);
- struct CameraViewWidgetGroup *viewgroup = gz_prop->custom_func.user_data;
- const rctf *border = viewgroup->state.edit_border;
-
- unit_m4(matrix);
- matrix[0][0] = BLI_rctf_size_x(border);
- matrix[1][1] = BLI_rctf_size_y(border);
- matrix[3][0] = BLI_rctf_cent_x(border);
- matrix[3][1] = BLI_rctf_cent_y(border);
+ float(*matrix)[4] = value_p;
+ BLI_assert(gz_prop->type->array_length == 16);
+ struct CameraViewWidgetGroup *viewgroup = gz_prop->custom_func.user_data;
+ const rctf *border = viewgroup->state.edit_border;
+
+ unit_m4(matrix);
+ matrix[0][0] = BLI_rctf_size_x(border);
+ matrix[1][1] = BLI_rctf_size_y(border);
+ matrix[3][0] = BLI_rctf_cent_x(border);
+ matrix[3][1] = BLI_rctf_cent_y(border);
}
-static void gizmo_render_border_prop_matrix_set(
- const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
- const void *value_p)
+static void gizmo_render_border_prop_matrix_set(const wmGizmo *UNUSED(gz),
+ wmGizmoProperty *gz_prop,
+ const void *value_p)
{
- const float (*matrix)[4] = value_p;
- struct CameraViewWidgetGroup *viewgroup = gz_prop->custom_func.user_data;
- rctf *border = viewgroup->state.edit_border;
- BLI_assert(gz_prop->type->array_length == 16);
-
- BLI_rctf_resize(border, len_v3(matrix[0]), len_v3(matrix[1]));
- BLI_rctf_recenter(border, matrix[3][0], matrix[3][1]);
- BLI_rctf_isect(&(rctf){ .xmin = 0, .ymin = 0, .xmax = 1, .ymax = 1, }, border, border);
-
- if (viewgroup->is_camera) {
- DEG_id_tag_update(&viewgroup->scene->id, ID_RECALC_COPY_ON_WRITE);
- }
+ const float(*matrix)[4] = value_p;
+ struct CameraViewWidgetGroup *viewgroup = gz_prop->custom_func.user_data;
+ rctf *border = viewgroup->state.edit_border;
+ BLI_assert(gz_prop->type->array_length == 16);
+
+ BLI_rctf_resize(border, len_v3(matrix[0]), len_v3(matrix[1]));
+ BLI_rctf_recenter(border, matrix[3][0], matrix[3][1]);
+ BLI_rctf_isect(
+ &(rctf){
+ .xmin = 0,
+ .ymin = 0,
+ .xmax = 1,
+ .ymax = 1,
+ },
+ border,
+ border);
+
+ if (viewgroup->is_camera) {
+ DEG_id_tag_update(&viewgroup->scene->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
static bool WIDGETGROUP_camera_view_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
- Scene *scene = CTX_data_scene(C);
-
- /* This is just so the border isn't always in the way,
- * stealing mouse clicks from regular usage.
- * We could change the rules for when to show. */
- {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- if (scene->camera != OBACT(view_layer)) {
- return false;
- }
- }
-
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) {
- return false;
- }
-
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
- if (rv3d->persp == RV3D_CAMOB) {
- if (scene->r.mode & R_BORDER) {
- /* TODO: support overrides. */
- if (scene->id.lib == NULL) {
- return true;
- }
- }
- }
- else if (v3d->flag2 & V3D_RENDER_BORDER) {
- return true;
- }
- return false;
+ Scene *scene = CTX_data_scene(C);
+
+ /* This is just so the border isn't always in the way,
+ * stealing mouse clicks from regular usage.
+ * We could change the rules for when to show. */
+ {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ if (scene->camera != OBACT(view_layer)) {
+ return false;
+ }
+ }
+
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) {
+ return false;
+ }
+
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ if (rv3d->persp == RV3D_CAMOB) {
+ if (scene->r.mode & R_BORDER) {
+ /* TODO: support overrides. */
+ if (scene->id.lib == NULL) {
+ return true;
+ }
+ }
+ }
+ else if (v3d->flag2 & V3D_RENDER_BORDER) {
+ return true;
+ }
+ return false;
}
static void WIDGETGROUP_camera_view_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- struct CameraViewWidgetGroup *viewgroup = MEM_mallocN(sizeof(struct CameraViewWidgetGroup), __func__);
+ struct CameraViewWidgetGroup *viewgroup = MEM_mallocN(sizeof(struct CameraViewWidgetGroup),
+ __func__);
- viewgroup->border = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
+ viewgroup->border = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
- RNA_enum_set(viewgroup->border->ptr, "transform",
- ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
- /* Box style is more subtle in this case. */
- RNA_enum_set(viewgroup->border->ptr, "draw_style", ED_GIZMO_CAGE2D_STYLE_BOX);
+ RNA_enum_set(viewgroup->border->ptr,
+ "transform",
+ ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
+ /* Box style is more subtle in this case. */
+ RNA_enum_set(viewgroup->border->ptr, "draw_style", ED_GIZMO_CAGE2D_STYLE_BOX);
-
- gzgroup->customdata = viewgroup;
+ gzgroup->customdata = viewgroup;
}
static void WIDGETGROUP_camera_view_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct CameraViewWidgetGroup *viewgroup = gzgroup->customdata;
-
- ARegion *ar = CTX_wm_region(C);
- struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
- RegionView3D *rv3d = ar->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);
- }
- else {
- viewgroup->state.view_border = (rctf){ .xmin = 0, .ymin = 0, .xmax = ar->winx, .ymax = ar->winy, };
- }
-
- wmGizmo *gz = viewgroup->border;
- unit_m4(gz->matrix_space);
- mul_v3_fl(gz->matrix_space[0], BLI_rctf_size_x(&viewgroup->state.view_border));
- mul_v3_fl(gz->matrix_space[1], BLI_rctf_size_y(&viewgroup->state.view_border));
- gz->matrix_space[3][0] = viewgroup->state.view_border.xmin;
- gz->matrix_space[3][1] = viewgroup->state.view_border.ymin;
+ struct CameraViewWidgetGroup *viewgroup = gzgroup->customdata;
+
+ ARegion *ar = CTX_wm_region(C);
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ RegionView3D *rv3d = ar->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);
+ }
+ else {
+ viewgroup->state.view_border = (rctf){
+ .xmin = 0,
+ .ymin = 0,
+ .xmax = ar->winx,
+ .ymax = ar->winy,
+ };
+ }
+
+ wmGizmo *gz = viewgroup->border;
+ unit_m4(gz->matrix_space);
+ mul_v3_fl(gz->matrix_space[0], BLI_rctf_size_x(&viewgroup->state.view_border));
+ mul_v3_fl(gz->matrix_space[1], BLI_rctf_size_y(&viewgroup->state.view_border));
+ gz->matrix_space[3][0] = viewgroup->state.view_border.xmin;
+ gz->matrix_space[3][1] = viewgroup->state.view_border.ymin;
}
static void WIDGETGROUP_camera_view_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct CameraViewWidgetGroup *viewgroup = gzgroup->customdata;
-
- View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
- Scene *scene = CTX_data_scene(C);
-
- viewgroup->scene = scene;
-
- {
- wmGizmo *gz = viewgroup->border;
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
-
- RNA_enum_set(viewgroup->border->ptr, "transform",
- ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
-
- if (rv3d->persp == RV3D_CAMOB) {
- viewgroup->state.edit_border = &scene->r.border;
- viewgroup->is_camera = true;
- }
- else {
- viewgroup->state.edit_border = &v3d->render_border;
- viewgroup->is_camera = false;
- }
-
- WM_gizmo_target_property_def_func(
- gz, "matrix",
- &(const struct wmGizmoPropertyFnParams) {
- .value_get_fn = gizmo_render_border_prop_matrix_get,
- .value_set_fn = gizmo_render_border_prop_matrix_set,
- .range_get_fn = NULL,
- .user_data = viewgroup,
- });
- }
-
+ struct CameraViewWidgetGroup *viewgroup = gzgroup->customdata;
+
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ Scene *scene = CTX_data_scene(C);
+
+ viewgroup->scene = scene;
+
+ {
+ wmGizmo *gz = viewgroup->border;
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
+
+ RNA_enum_set(viewgroup->border->ptr,
+ "transform",
+ ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ viewgroup->state.edit_border = &scene->r.border;
+ viewgroup->is_camera = true;
+ }
+ else {
+ viewgroup->state.edit_border = &v3d->render_border;
+ viewgroup->is_camera = false;
+ }
+
+ WM_gizmo_target_property_def_func(gz,
+ "matrix",
+ &(const struct wmGizmoPropertyFnParams){
+ .value_get_fn = gizmo_render_border_prop_matrix_get,
+ .value_set_fn = gizmo_render_border_prop_matrix_set,
+ .range_get_fn = NULL,
+ .user_data = viewgroup,
+ });
+ }
}
void VIEW3D_GGT_camera_view(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Camera View Widgets";
- gzgt->idname = "VIEW3D_GGT_camera_view";
+ gzgt->name = "Camera View Widgets";
+ gzgt->idname = "VIEW3D_GGT_camera_view";
- gzgt->flag = (WM_GIZMOGROUPTYPE_PERSISTENT |
- WM_GIZMOGROUPTYPE_SCALE);
+ gzgt->flag = (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_SCALE);
- gzgt->poll = WIDGETGROUP_camera_view_poll;
- gzgt->setup = WIDGETGROUP_camera_view_setup;
- gzgt->draw_prepare = WIDGETGROUP_camera_view_draw_prepare;
- gzgt->refresh = WIDGETGROUP_camera_view_refresh;
+ gzgt->poll = WIDGETGROUP_camera_view_poll;
+ gzgt->setup = WIDGETGROUP_camera_view_setup;
+ gzgt->draw_prepare = WIDGETGROUP_camera_view_draw_prepare;
+ gzgt->refresh = WIDGETGROUP_camera_view_refresh;
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_empty.c b/source/blender/editors/space_view3d/view3d_gizmo_empty.c
index 8e78fe8a18e..6a3979ae458 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_empty.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_empty.c
@@ -18,7 +18,6 @@
* \ingroup spview3d
*/
-
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -43,167 +42,165 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "view3d_intern.h" /* own include */
+#include "view3d_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Empty Image Gizmos
* \{ */
struct EmptyImageWidgetGroup {
- wmGizmo *gizmo;
- struct {
- Object *ob;
- float dims[2];
- } state;
+ wmGizmo *gizmo;
+ struct {
+ Object *ob;
+ float dims[2];
+ } state;
};
/* translate callbacks */
-static void gizmo_empty_image_prop_matrix_get(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- void *value_p)
+static void gizmo_empty_image_prop_matrix_get(const wmGizmo *gz,
+ wmGizmoProperty *gz_prop,
+ void *value_p)
{
- float (*matrix)[4] = value_p;
- BLI_assert(gz_prop->type->array_length == 16);
- struct EmptyImageWidgetGroup *igzgroup = gz_prop->custom_func.user_data;
- const Object *ob = igzgroup->state.ob;
-
- unit_m4(matrix);
- matrix[0][0] = ob->empty_drawsize;
- matrix[1][1] = ob->empty_drawsize;
-
- float dims[2] = {0.0f, 0.0f};
- RNA_float_get_array(gz->ptr, "dimensions", dims);
- dims[0] *= ob->empty_drawsize;
- dims[1] *= ob->empty_drawsize;
-
- matrix[3][0] = (ob->ima_ofs[0] * dims[0]) + (0.5f * dims[0]);
- matrix[3][1] = (ob->ima_ofs[1] * dims[1]) + (0.5f * dims[1]);
+ float(*matrix)[4] = value_p;
+ BLI_assert(gz_prop->type->array_length == 16);
+ struct EmptyImageWidgetGroup *igzgroup = gz_prop->custom_func.user_data;
+ const Object *ob = igzgroup->state.ob;
+
+ unit_m4(matrix);
+ matrix[0][0] = ob->empty_drawsize;
+ matrix[1][1] = ob->empty_drawsize;
+
+ float dims[2] = {0.0f, 0.0f};
+ RNA_float_get_array(gz->ptr, "dimensions", dims);
+ dims[0] *= ob->empty_drawsize;
+ dims[1] *= ob->empty_drawsize;
+
+ matrix[3][0] = (ob->ima_ofs[0] * dims[0]) + (0.5f * dims[0]);
+ matrix[3][1] = (ob->ima_ofs[1] * dims[1]) + (0.5f * dims[1]);
}
-static void gizmo_empty_image_prop_matrix_set(
- const wmGizmo *gz, wmGizmoProperty *gz_prop,
- const void *value_p)
+static void gizmo_empty_image_prop_matrix_set(const wmGizmo *gz,
+ wmGizmoProperty *gz_prop,
+ const void *value_p)
{
- const float (*matrix)[4] = value_p;
- BLI_assert(gz_prop->type->array_length == 16);
- struct EmptyImageWidgetGroup *igzgroup = gz_prop->custom_func.user_data;
- Object *ob = igzgroup->state.ob;
+ const float(*matrix)[4] = value_p;
+ BLI_assert(gz_prop->type->array_length == 16);
+ struct EmptyImageWidgetGroup *igzgroup = gz_prop->custom_func.user_data;
+ Object *ob = igzgroup->state.ob;
- ob->empty_drawsize = matrix[0][0];
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ ob->empty_drawsize = matrix[0][0];
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- float dims[2];
- RNA_float_get_array(gz->ptr, "dimensions", dims);
- dims[0] *= ob->empty_drawsize;
- dims[1] *= ob->empty_drawsize;
+ float dims[2];
+ RNA_float_get_array(gz->ptr, "dimensions", dims);
+ dims[0] *= ob->empty_drawsize;
+ dims[1] *= ob->empty_drawsize;
- ob->ima_ofs[0] = (matrix[3][0] - (0.5f * dims[0])) / dims[0];
- ob->ima_ofs[1] = (matrix[3][1] - (0.5f * dims[1])) / dims[1];
+ ob->ima_ofs[0] = (matrix[3][0] - (0.5f * dims[0])) / dims[0];
+ ob->ima_ofs[1] = (matrix[3][1] - (0.5f * dims[1])) / dims[1];
}
static bool WIDGETGROUP_empty_image_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
-
- if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) {
- return false;
- }
- if ((v3d->gizmo_show_empty & V3D_GIZMO_SHOW_EMPTY_IMAGE) == 0) {
- return false;
- }
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base = BASACT(view_layer);
- if (base && BASE_SELECTABLE(v3d, base)) {
- Object *ob = base->object;
- if (ob->type == OB_EMPTY) {
- if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
- return BKE_object_empty_image_frame_is_visible_in_view3d(ob, rv3d);
- }
- }
- }
- return false;
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+
+ if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) {
+ return false;
+ }
+ if ((v3d->gizmo_show_empty & V3D_GIZMO_SHOW_EMPTY_IMAGE) == 0) {
+ return false;
+ }
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base = BASACT(view_layer);
+ if (base && BASE_SELECTABLE(v3d, base)) {
+ Object *ob = base->object;
+ if (ob->type == OB_EMPTY) {
+ if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
+ return BKE_object_empty_image_frame_is_visible_in_view3d(ob, rv3d);
+ }
+ }
+ }
+ return false;
}
static void WIDGETGROUP_empty_image_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- struct EmptyImageWidgetGroup *igzgroup = MEM_mallocN(sizeof(struct EmptyImageWidgetGroup), __func__);
- igzgroup->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
- wmGizmo *gz = igzgroup->gizmo;
- RNA_enum_set(gz->ptr, "transform",
- ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
+ struct EmptyImageWidgetGroup *igzgroup = MEM_mallocN(sizeof(struct EmptyImageWidgetGroup),
+ __func__);
+ igzgroup->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
+ wmGizmo *gz = igzgroup->gizmo;
+ RNA_enum_set(gz->ptr, "transform", ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
- gzgroup->customdata = igzgroup;
+ gzgroup->customdata = igzgroup;
- WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true);
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true);
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
}
static void WIDGETGROUP_empty_image_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct EmptyImageWidgetGroup *igzgroup = gzgroup->customdata;
- wmGizmo *gz = igzgroup->gizmo;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
-
- copy_m4_m4(gz->matrix_basis, ob->obmat);
-
- RNA_enum_set(gz->ptr, "transform",
- ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE |
- ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE |
- ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM);
-
- igzgroup->state.ob = ob;
-
- /* Use dimensions for aspect. */
- if (ob->data != NULL) {
- const Image *image = ob->data;
- ImageUser iuser = *ob->iuser;
- float size[2];
- BKE_image_get_size_fl(ob->data, &iuser, size);
-
- /* Get the image aspect even if the buffer is invalid */
- if (image->aspx > image->aspy) {
- size[1] *= image->aspy / image->aspx;
- }
- else if (image->aspx < image->aspy) {
- size[0] *= image->aspx / image->aspy;
- }
-
- const float dims_max = max_ff(size[0], size[1]);
- igzgroup->state.dims[0] = size[0] / dims_max;
- igzgroup->state.dims[1] = size[1] / dims_max;
- }
- else {
- copy_v2_fl(igzgroup->state.dims, 1.0f);
- }
- RNA_float_set_array(gz->ptr, "dimensions", igzgroup->state.dims);
-
- WM_gizmo_target_property_def_func(
- gz, "matrix",
- &(const struct wmGizmoPropertyFnParams) {
- .value_get_fn = gizmo_empty_image_prop_matrix_get,
- .value_set_fn = gizmo_empty_image_prop_matrix_set,
- .range_get_fn = NULL,
- .user_data = igzgroup,
- });
+ struct EmptyImageWidgetGroup *igzgroup = gzgroup->customdata;
+ wmGizmo *gz = igzgroup->gizmo;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+
+ copy_m4_m4(gz->matrix_basis, ob->obmat);
+
+ RNA_enum_set(gz->ptr,
+ "transform",
+ ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE |
+ ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM);
+
+ igzgroup->state.ob = ob;
+
+ /* Use dimensions for aspect. */
+ if (ob->data != NULL) {
+ const Image *image = ob->data;
+ ImageUser iuser = *ob->iuser;
+ float size[2];
+ BKE_image_get_size_fl(ob->data, &iuser, size);
+
+ /* Get the image aspect even if the buffer is invalid */
+ if (image->aspx > image->aspy) {
+ size[1] *= image->aspy / image->aspx;
+ }
+ else if (image->aspx < image->aspy) {
+ size[0] *= image->aspx / image->aspy;
+ }
+
+ const float dims_max = max_ff(size[0], size[1]);
+ igzgroup->state.dims[0] = size[0] / dims_max;
+ igzgroup->state.dims[1] = size[1] / dims_max;
+ }
+ else {
+ copy_v2_fl(igzgroup->state.dims, 1.0f);
+ }
+ RNA_float_set_array(gz->ptr, "dimensions", igzgroup->state.dims);
+
+ WM_gizmo_target_property_def_func(gz,
+ "matrix",
+ &(const struct wmGizmoPropertyFnParams){
+ .value_get_fn = gizmo_empty_image_prop_matrix_get,
+ .value_set_fn = gizmo_empty_image_prop_matrix_set,
+ .range_get_fn = NULL,
+ .user_data = igzgroup,
+ });
}
void VIEW3D_GGT_empty_image(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Area Light Widgets";
- gzgt->idname = "VIEW3D_GGT_empty_image";
+ gzgt->name = "Area Light Widgets";
+ gzgt->idname = "VIEW3D_GGT_empty_image";
- gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT |
- WM_GIZMOGROUPTYPE_3D |
- WM_GIZMOGROUPTYPE_DEPTH_3D);
+ gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_DEPTH_3D);
- gzgt->poll = WIDGETGROUP_empty_image_poll;
- gzgt->setup = WIDGETGROUP_empty_image_setup;
- gzgt->refresh = WIDGETGROUP_empty_image_refresh;
+ gzgt->poll = WIDGETGROUP_empty_image_poll;
+ gzgt->setup = WIDGETGROUP_empty_image_setup;
+ gzgt->refresh = WIDGETGROUP_empty_image_refresh;
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c
index 34cf38b3466..7d3e22b4d70 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c
@@ -18,7 +18,6 @@
* \ingroup spview3d
*/
-
#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -39,7 +38,7 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "view3d_intern.h" /* own include */
+#include "view3d_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Force Field Gizmos
@@ -47,80 +46,78 @@
static bool WIDGETGROUP_forcefield_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
- View3D *v3d = CTX_wm_view3d(C);
-
- if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) {
- return false;
- }
- if ((v3d->gizmo_show_empty & V3D_GIZMO_SHOW_EMPTY_FORCE_FIELD) == 0) {
- return false;
- }
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base = BASACT(view_layer);
- if (base && BASE_SELECTABLE(v3d, base)) {
- Object *ob = base->object;
- if (ob->pd && ob->pd->forcefield) {
- return true;
- }
- }
- return false;
+ View3D *v3d = CTX_wm_view3d(C);
+
+ if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) {
+ return false;
+ }
+ if ((v3d->gizmo_show_empty & V3D_GIZMO_SHOW_EMPTY_FORCE_FIELD) == 0) {
+ return false;
+ }
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base = BASACT(view_layer);
+ if (base && BASE_SELECTABLE(v3d, base)) {
+ Object *ob = base->object;
+ if (ob->pd && ob->pd->forcefield) {
+ return true;
+ }
+ }
+ return false;
}
static void WIDGETGROUP_forcefield_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- /* only wind effector for now */
- wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
- gzgroup->customdata = wwrapper;
-
- wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_arrow_3d", gzgroup, NULL);
- wmGizmo *gz = wwrapper->gizmo;
- RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED);
- ED_gizmo_arrow3d_set_ui_range(gz, -200.0f, 200.0f);
- ED_gizmo_arrow3d_set_range_fac(gz, 6.0f);
-
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
+ /* only wind effector for now */
+ wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
+ gzgroup->customdata = wwrapper;
+
+ wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_arrow_3d", gzgroup, NULL);
+ wmGizmo *gz = wwrapper->gizmo;
+ RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED);
+ ED_gizmo_arrow3d_set_ui_range(gz, -200.0f, 200.0f);
+ ED_gizmo_arrow3d_set_range_fac(gz, 6.0f);
+
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
}
static void WIDGETGROUP_forcefield_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- wmGizmoWrapper *wwrapper = gzgroup->customdata;
- wmGizmo *gz = wwrapper->gizmo;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- PartDeflect *pd = ob->pd;
-
- if (pd->forcefield == PFIELD_WIND) {
- const float size = (ob->type == OB_EMPTY) ? ob->empty_drawsize : 1.0f;
- const float ofs[3] = {0.0f, -size, 0.0f};
- PointerRNA field_ptr;
-
- RNA_pointer_create(&ob->id, &RNA_FieldSettings, pd, &field_ptr);
- WM_gizmo_set_matrix_location(gz, ob->obmat[3]);
- WM_gizmo_set_matrix_rotation_from_z_axis(gz, ob->obmat[2]);
- WM_gizmo_set_matrix_offset_location(gz, ofs);
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
- WM_gizmo_target_property_def_rna(gz, "offset", &field_ptr, "strength", -1);
- }
- else {
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
- }
+ wmGizmoWrapper *wwrapper = gzgroup->customdata;
+ wmGizmo *gz = wwrapper->gizmo;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ PartDeflect *pd = ob->pd;
+
+ if (pd->forcefield == PFIELD_WIND) {
+ const float size = (ob->type == OB_EMPTY) ? ob->empty_drawsize : 1.0f;
+ const float ofs[3] = {0.0f, -size, 0.0f};
+ PointerRNA field_ptr;
+
+ RNA_pointer_create(&ob->id, &RNA_FieldSettings, pd, &field_ptr);
+ WM_gizmo_set_matrix_location(gz, ob->obmat[3]);
+ WM_gizmo_set_matrix_rotation_from_z_axis(gz, ob->obmat[2]);
+ WM_gizmo_set_matrix_offset_location(gz, ofs);
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
+ WM_gizmo_target_property_def_rna(gz, "offset", &field_ptr, "strength", -1);
+ }
+ else {
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
+ }
}
void VIEW3D_GGT_force_field(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Force Field Widgets";
- gzgt->idname = "VIEW3D_GGT_force_field";
+ gzgt->name = "Force Field Widgets";
+ gzgt->idname = "VIEW3D_GGT_force_field";
- gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT |
- WM_GIZMOGROUPTYPE_3D |
- WM_GIZMOGROUPTYPE_SCALE |
- WM_GIZMOGROUPTYPE_DEPTH_3D);
+ gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_SCALE |
+ WM_GIZMOGROUPTYPE_DEPTH_3D);
- gzgt->poll = WIDGETGROUP_forcefield_poll;
- gzgt->setup = WIDGETGROUP_forcefield_setup;
- gzgt->refresh = WIDGETGROUP_forcefield_refresh;
+ gzgt->poll = WIDGETGROUP_forcefield_poll;
+ gzgt->setup = WIDGETGROUP_forcefield_setup;
+ gzgt->refresh = WIDGETGROUP_forcefield_refresh;
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_light.c b/source/blender/editors/space_view3d/view3d_gizmo_light.c
index 5fd5336f4ca..8c6f783de61 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_light.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_light.c
@@ -18,7 +18,6 @@
* \ingroup spview3d
*/
-
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -42,7 +41,7 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "view3d_intern.h" /* own include */
+#include "view3d_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Spot Light Gizmos
@@ -50,74 +49,72 @@
static bool WIDGETGROUP_light_spot_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) {
- return false;
- }
- if ((v3d->gizmo_show_light & V3D_GIZMO_SHOW_LIGHT_SIZE) == 0) {
- return false;
- }
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base = BASACT(view_layer);
- if (base && BASE_SELECTABLE(v3d, base)) {
- Object *ob = base->object;
- if (ob->type == OB_LAMP) {
- Light *la = ob->data;
- return (la->type == LA_SPOT);
- }
- }
- return false;
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) {
+ return false;
+ }
+ if ((v3d->gizmo_show_light & V3D_GIZMO_SHOW_LIGHT_SIZE) == 0) {
+ return false;
+ }
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base = BASACT(view_layer);
+ if (base && BASE_SELECTABLE(v3d, base)) {
+ Object *ob = base->object;
+ if (ob->type == OB_LAMP) {
+ Light *la = ob->data;
+ return (la->type == LA_SPOT);
+ }
+ }
+ return false;
}
static void WIDGETGROUP_light_spot_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
+ wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
- wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_arrow_3d", gzgroup, NULL);
- wmGizmo *gz = wwrapper->gizmo;
- RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_INVERTED);
+ wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_arrow_3d", gzgroup, NULL);
+ wmGizmo *gz = wwrapper->gizmo;
+ RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_INVERTED);
- gzgroup->customdata = wwrapper;
+ gzgroup->customdata = wwrapper;
- ED_gizmo_arrow3d_set_range_fac(gz, 4.0f);
+ ED_gizmo_arrow3d_set_range_fac(gz, 4.0f);
- UI_GetThemeColor3fv(TH_GIZMO_SECONDARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_SECONDARY, gz->color);
}
static void WIDGETGROUP_light_spot_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- wmGizmoWrapper *wwrapper = gzgroup->customdata;
- wmGizmo *gz = wwrapper->gizmo;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- Light *la = ob->data;
- float dir[3];
-
- negate_v3_v3(dir, ob->obmat[2]);
-
- WM_gizmo_set_matrix_rotation_from_z_axis(gz, dir);
- WM_gizmo_set_matrix_location(gz, ob->obmat[3]);
-
- /* need to set property here for undo. TODO would prefer to do this in _init */
- PointerRNA lamp_ptr;
- const char *propname = "spot_size";
- RNA_pointer_create(&la->id, &RNA_Light, la, &lamp_ptr);
- WM_gizmo_target_property_def_rna(gz, "offset", &lamp_ptr, propname, -1);
+ wmGizmoWrapper *wwrapper = gzgroup->customdata;
+ wmGizmo *gz = wwrapper->gizmo;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ Light *la = ob->data;
+ float dir[3];
+
+ negate_v3_v3(dir, ob->obmat[2]);
+
+ WM_gizmo_set_matrix_rotation_from_z_axis(gz, dir);
+ WM_gizmo_set_matrix_location(gz, ob->obmat[3]);
+
+ /* need to set property here for undo. TODO would prefer to do this in _init */
+ PointerRNA lamp_ptr;
+ const char *propname = "spot_size";
+ RNA_pointer_create(&la->id, &RNA_Light, la, &lamp_ptr);
+ WM_gizmo_target_property_def_rna(gz, "offset", &lamp_ptr, propname, -1);
}
void VIEW3D_GGT_light_spot(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Spot Light Widgets";
- gzgt->idname = "VIEW3D_GGT_light_spot";
+ gzgt->name = "Spot Light Widgets";
+ gzgt->idname = "VIEW3D_GGT_light_spot";
- gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT |
- WM_GIZMOGROUPTYPE_3D |
- WM_GIZMOGROUPTYPE_DEPTH_3D);
+ gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_DEPTH_3D);
- gzgt->poll = WIDGETGROUP_light_spot_poll;
- gzgt->setup = WIDGETGROUP_light_spot_setup;
- gzgt->refresh = WIDGETGROUP_light_spot_refresh;
+ gzgt->poll = WIDGETGROUP_light_spot_poll;
+ gzgt->setup = WIDGETGROUP_light_spot_setup;
+ gzgt->refresh = WIDGETGROUP_light_spot_refresh;
}
/** \} */
@@ -127,204 +124,200 @@ void VIEW3D_GGT_light_spot(wmGizmoGroupType *gzgt)
* \{ */
/* scale callbacks */
-static void gizmo_area_light_prop_matrix_get(
- const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
- void *value_p)
+static void gizmo_area_light_prop_matrix_get(const wmGizmo *UNUSED(gz),
+ wmGizmoProperty *gz_prop,
+ void *value_p)
{
- BLI_assert(gz_prop->type->array_length == 16);
- float (*matrix)[4] = value_p;
- const Light *la = gz_prop->custom_func.user_data;
+ BLI_assert(gz_prop->type->array_length == 16);
+ float(*matrix)[4] = value_p;
+ const Light *la = gz_prop->custom_func.user_data;
- matrix[0][0] = la->area_size;
- matrix[1][1] = ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE) ? la->area_sizey : la->area_size;
+ matrix[0][0] = la->area_size;
+ matrix[1][1] = ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE) ? la->area_sizey :
+ la->area_size;
}
-static void gizmo_area_light_prop_matrix_set(
- const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
- const void *value_p)
+static void gizmo_area_light_prop_matrix_set(const wmGizmo *UNUSED(gz),
+ wmGizmoProperty *gz_prop,
+ const void *value_p)
{
- const float (*matrix)[4] = value_p;
- BLI_assert(gz_prop->type->array_length == 16);
- Light *la = gz_prop->custom_func.user_data;
-
- if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE)) {
- la->area_size = len_v3(matrix[0]);
- la->area_sizey = len_v3(matrix[1]);
- }
- else {
- la->area_size = len_v3(matrix[0]);
- }
-
- DEG_id_tag_update(&la->id, ID_RECALC_COPY_ON_WRITE);
- WM_main_add_notifier(NC_LAMP | ND_LIGHTING_DRAW, la);
+ const float(*matrix)[4] = value_p;
+ BLI_assert(gz_prop->type->array_length == 16);
+ Light *la = gz_prop->custom_func.user_data;
+
+ if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE)) {
+ la->area_size = len_v3(matrix[0]);
+ la->area_sizey = len_v3(matrix[1]);
+ }
+ else {
+ la->area_size = len_v3(matrix[0]);
+ }
+
+ DEG_id_tag_update(&la->id, ID_RECALC_COPY_ON_WRITE);
+ WM_main_add_notifier(NC_LAMP | ND_LIGHTING_DRAW, la);
}
static bool WIDGETGROUP_light_area_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) {
- return false;
- }
- if ((v3d->gizmo_show_light & V3D_GIZMO_SHOW_LIGHT_SIZE) == 0) {
- return false;
- }
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base = BASACT(view_layer);
- if (base && BASE_SELECTABLE(v3d, base)) {
- Object *ob = base->object;
- if (ob->type == OB_LAMP) {
- Light *la = ob->data;
- return (la->type == LA_AREA);
- }
- }
- return false;
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) {
+ return false;
+ }
+ if ((v3d->gizmo_show_light & V3D_GIZMO_SHOW_LIGHT_SIZE) == 0) {
+ return false;
+ }
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base = BASACT(view_layer);
+ if (base && BASE_SELECTABLE(v3d, base)) {
+ Object *ob = base->object;
+ if (ob->type == OB_LAMP) {
+ Light *la = ob->data;
+ return (la->type == LA_AREA);
+ }
+ }
+ return false;
}
static void WIDGETGROUP_light_area_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
- wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
- wmGizmo *gz = wwrapper->gizmo;
- RNA_enum_set(gz->ptr, "transform",
- ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
+ wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
+ wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
+ wmGizmo *gz = wwrapper->gizmo;
+ RNA_enum_set(gz->ptr, "transform", ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
- gzgroup->customdata = wwrapper;
+ gzgroup->customdata = wwrapper;
- WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true);
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true);
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
}
static void WIDGETGROUP_light_area_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- wmGizmoWrapper *wwrapper = gzgroup->customdata;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- Light *la = ob->data;
- wmGizmo *gz = wwrapper->gizmo;
-
- copy_m4_m4(gz->matrix_basis, ob->obmat);
-
- int flag = ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE;
- if (ELEM(la->area_shape, LA_AREA_SQUARE, LA_AREA_DISK)) {
- flag |= ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM;
- }
- RNA_enum_set(gz->ptr, "transform", flag);
-
- /* need to set property here for undo. TODO would prefer to do this in _init */
- WM_gizmo_target_property_def_func(
- gz, "matrix",
- &(const struct wmGizmoPropertyFnParams) {
- .value_get_fn = gizmo_area_light_prop_matrix_get,
- .value_set_fn = gizmo_area_light_prop_matrix_set,
- .range_get_fn = NULL,
- .user_data = la,
- });
+ wmGizmoWrapper *wwrapper = gzgroup->customdata;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ Light *la = ob->data;
+ wmGizmo *gz = wwrapper->gizmo;
+
+ copy_m4_m4(gz->matrix_basis, ob->obmat);
+
+ int flag = ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE;
+ if (ELEM(la->area_shape, LA_AREA_SQUARE, LA_AREA_DISK)) {
+ flag |= ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM;
+ }
+ RNA_enum_set(gz->ptr, "transform", flag);
+
+ /* need to set property here for undo. TODO would prefer to do this in _init */
+ WM_gizmo_target_property_def_func(gz,
+ "matrix",
+ &(const struct wmGizmoPropertyFnParams){
+ .value_get_fn = gizmo_area_light_prop_matrix_get,
+ .value_set_fn = gizmo_area_light_prop_matrix_set,
+ .range_get_fn = NULL,
+ .user_data = la,
+ });
}
void VIEW3D_GGT_light_area(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Area Light Widgets";
- gzgt->idname = "VIEW3D_GGT_light_area";
+ gzgt->name = "Area Light Widgets";
+ gzgt->idname = "VIEW3D_GGT_light_area";
- gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT |
- WM_GIZMOGROUPTYPE_3D |
- WM_GIZMOGROUPTYPE_DEPTH_3D);
+ gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_DEPTH_3D);
- gzgt->poll = WIDGETGROUP_light_area_poll;
- gzgt->setup = WIDGETGROUP_light_area_setup;
- gzgt->refresh = WIDGETGROUP_light_area_refresh;
+ gzgt->poll = WIDGETGROUP_light_area_poll;
+ gzgt->setup = WIDGETGROUP_light_area_setup;
+ gzgt->refresh = WIDGETGROUP_light_area_refresh;
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Light Target Gizmo
* \{ */
static bool WIDGETGROUP_light_target_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) {
- return false;
- }
- if ((v3d->gizmo_show_light & V3D_GIZMO_SHOW_LIGHT_LOOK_AT) == 0) {
- return false;
- }
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base = BASACT(view_layer);
- if (base && BASE_SELECTABLE(v3d, base)) {
- Object *ob = base->object;
- if (ob->type == OB_LAMP) {
- Light *la = ob->data;
- return (ELEM(la->type, LA_SUN, LA_SPOT, LA_AREA));
- }
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) {
+ return false;
+ }
+ if ((v3d->gizmo_show_light & V3D_GIZMO_SHOW_LIGHT_LOOK_AT) == 0) {
+ return false;
+ }
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base = BASACT(view_layer);
+ if (base && BASE_SELECTABLE(v3d, base)) {
+ Object *ob = base->object;
+ if (ob->type == OB_LAMP) {
+ Light *la = ob->data;
+ return (ELEM(la->type, LA_SUN, LA_SPOT, LA_AREA));
+ }
#if 0
- else if (ob->type == OB_CAMERA) {
- return true;
- }
+ else if (ob->type == OB_CAMERA) {
+ return true;
+ }
#endif
- }
- return false;
+ }
+ return false;
}
static void WIDGETGROUP_light_target_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
- wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_move_3d", gzgroup, NULL);
- wmGizmo *gz = wwrapper->gizmo;
+ wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
+ wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_move_3d", gzgroup, NULL);
+ wmGizmo *gz = wwrapper->gizmo;
- gzgroup->customdata = wwrapper;
+ gzgroup->customdata = wwrapper;
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
- gz->scale_basis = 0.06f;
+ gz->scale_basis = 0.06f;
- wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_transform_axis_target", true);
+ wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_transform_axis_target", true);
- RNA_enum_set(gz->ptr, "draw_options",
- ED_GIZMO_MOVE_DRAW_FLAG_FILL | ED_GIZMO_MOVE_DRAW_FLAG_ALIGN_VIEW);
+ RNA_enum_set(
+ gz->ptr, "draw_options", ED_GIZMO_MOVE_DRAW_FLAG_FILL | ED_GIZMO_MOVE_DRAW_FLAG_ALIGN_VIEW);
- WM_gizmo_operator_set(gz, 0, ot, NULL);
+ WM_gizmo_operator_set(gz, 0, ot, NULL);
}
static void WIDGETGROUP_light_target_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- wmGizmoWrapper *wwrapper = gzgroup->customdata;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- wmGizmo *gz = wwrapper->gizmo;
-
- normalize_m4_m4(gz->matrix_basis, ob->obmat);
- unit_m4(gz->matrix_offset);
-
- if (ob->type == OB_LAMP) {
- Light *la = ob->data;
- if (la->type == LA_SPOT) {
- /* Draw just past the light size angle gizmo. */
- madd_v3_v3fl(gz->matrix_basis[3], gz->matrix_basis[2], -la->spotsize);
- }
- }
- gz->matrix_offset[3][2] -= 23.0;
- WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_OFFSET_SCALE, true);
+ wmGizmoWrapper *wwrapper = gzgroup->customdata;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ wmGizmo *gz = wwrapper->gizmo;
+
+ normalize_m4_m4(gz->matrix_basis, ob->obmat);
+ unit_m4(gz->matrix_offset);
+
+ if (ob->type == OB_LAMP) {
+ Light *la = ob->data;
+ if (la->type == LA_SPOT) {
+ /* Draw just past the light size angle gizmo. */
+ madd_v3_v3fl(gz->matrix_basis[3], gz->matrix_basis[2], -la->spotsize);
+ }
+ }
+ gz->matrix_offset[3][2] -= 23.0;
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_OFFSET_SCALE, true);
}
void VIEW3D_GGT_light_target(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Target Light Widgets";
- gzgt->idname = "VIEW3D_GGT_light_target";
+ gzgt->name = "Target Light Widgets";
+ gzgt->idname = "VIEW3D_GGT_light_target";
- gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT |
- WM_GIZMOGROUPTYPE_3D);
+ gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_3D);
- gzgt->poll = WIDGETGROUP_light_target_poll;
- gzgt->setup = WIDGETGROUP_light_target_setup;
- gzgt->draw_prepare = WIDGETGROUP_light_target_draw_prepare;
+ gzgt->poll = WIDGETGROUP_light_target_poll;
+ gzgt->setup = WIDGETGROUP_light_target_setup;
+ gzgt->draw_prepare = WIDGETGROUP_light_target_draw_prepare;
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
index a6fd195b04d..f98a87e84a8 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
@@ -39,7 +39,7 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "view3d_intern.h" /* own include */
+#include "view3d_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name View3D Navigation Gizmo Group
@@ -54,278 +54,280 @@
/* How much mini buttons offset from the primary. */
#define GIZMO_MINI_OFFSET_FAC 0.38f
-
enum {
- GZ_INDEX_MOVE = 0,
- GZ_INDEX_ROTATE = 1,
- GZ_INDEX_ZOOM = 2,
+ GZ_INDEX_MOVE = 0,
+ GZ_INDEX_ROTATE = 1,
+ GZ_INDEX_ZOOM = 2,
- /* just buttons */
- /* overlaps GZ_INDEX_ORTHO (switch between) */
- GZ_INDEX_PERSP = 3,
- GZ_INDEX_ORTHO = 4,
- GZ_INDEX_CAMERA = 5,
+ /* just buttons */
+ /* overlaps GZ_INDEX_ORTHO (switch between) */
+ GZ_INDEX_PERSP = 3,
+ GZ_INDEX_ORTHO = 4,
+ GZ_INDEX_CAMERA = 5,
- GZ_INDEX_TOTAL = 6,
+ GZ_INDEX_TOTAL = 6,
};
struct NavigateGizmoInfo {
- const char *opname;
- const char *gizmo;
- uint icon;
+ const char *opname;
+ const char *gizmo;
+ uint icon;
};
static struct NavigateGizmoInfo g_navigate_params[GZ_INDEX_TOTAL] = {
- {
- .opname = "VIEW3D_OT_move",
- .gizmo = "GIZMO_GT_button_2d",
- ICON_VIEW_PAN,
- }, {
- .opname = "VIEW3D_OT_rotate",
- .gizmo = "VIEW3D_GT_navigate_rotate",
- 0,
- }, {
- .opname = "VIEW3D_OT_zoom",
- .gizmo = "GIZMO_GT_button_2d",
- ICON_VIEW_ZOOM,
- }, {
- .opname = "VIEW3D_OT_view_persportho",
- .gizmo = "GIZMO_GT_button_2d",
- ICON_VIEW_PERSPECTIVE,
- }, {
- .opname = "VIEW3D_OT_view_persportho",
- .gizmo = "GIZMO_GT_button_2d",
- ICON_VIEW_ORTHO,
- }, {
- .opname = "VIEW3D_OT_view_camera",
- .gizmo = "GIZMO_GT_button_2d",
- ICON_VIEW_CAMERA,
- },
+ {
+ .opname = "VIEW3D_OT_move",
+ .gizmo = "GIZMO_GT_button_2d",
+ ICON_VIEW_PAN,
+ },
+ {
+ .opname = "VIEW3D_OT_rotate",
+ .gizmo = "VIEW3D_GT_navigate_rotate",
+ 0,
+ },
+ {
+ .opname = "VIEW3D_OT_zoom",
+ .gizmo = "GIZMO_GT_button_2d",
+ ICON_VIEW_ZOOM,
+ },
+ {
+ .opname = "VIEW3D_OT_view_persportho",
+ .gizmo = "GIZMO_GT_button_2d",
+ ICON_VIEW_PERSPECTIVE,
+ },
+ {
+ .opname = "VIEW3D_OT_view_persportho",
+ .gizmo = "GIZMO_GT_button_2d",
+ ICON_VIEW_ORTHO,
+ },
+ {
+ .opname = "VIEW3D_OT_view_camera",
+ .gizmo = "GIZMO_GT_button_2d",
+ ICON_VIEW_CAMERA,
+ },
};
struct NavigateWidgetGroup {
- wmGizmo *gz_array[GZ_INDEX_TOTAL];
- /* Store the view state to check for changes. */
- struct {
- rcti rect_visible;
- struct {
- char is_persp;
- char is_camera;
- char viewlock;
- } rv3d;
- } state;
- int region_size[2];
+ wmGizmo *gz_array[GZ_INDEX_TOTAL];
+ /* Store the view state to check for changes. */
+ struct {
+ rcti rect_visible;
+ struct {
+ char is_persp;
+ char is_camera;
+ char viewlock;
+ } rv3d;
+ } state;
+ int region_size[2];
};
static bool WIDGETGROUP_navigate_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
- View3D *v3d = CTX_wm_view3d(C);
- if (((U.uiflag & USER_SHOW_GIZMO_AXIS) == 0) ||
- (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_NAVIGATE)))
- {
- return false;
- }
- return true;
+ View3D *v3d = CTX_wm_view3d(C);
+ if (((U.uiflag & USER_SHOW_GIZMO_AXIS) == 0) ||
+ (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_NAVIGATE))) {
+ return false;
+ }
+ return true;
}
static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- struct NavigateWidgetGroup *navgroup = MEM_callocN(sizeof(struct NavigateWidgetGroup), __func__);
-
- navgroup->region_size[0] = -1;
- navgroup->region_size[1] = -1;
-
- wmOperatorType *ot_view_axis = WM_operatortype_find("VIEW3D_OT_view_axis", true);
- wmOperatorType *ot_view_camera = WM_operatortype_find("VIEW3D_OT_view_camera", true);
-
- for (int i = 0; i < GZ_INDEX_TOTAL; i++) {
- const struct NavigateGizmoInfo *info = &g_navigate_params[i];
- navgroup->gz_array[i] = WM_gizmo_new(info->gizmo, gzgroup, NULL);
- wmGizmo *gz = navgroup->gz_array[i];
- gz->flag |= WM_GIZMO_MOVE_CURSOR | WM_GIZMO_DRAW_MODAL;
-
- if (i == GZ_INDEX_ROTATE) {
- gz->color[3] = 0.0f;
- copy_v3_fl(gz->color_hi, 0.5f);
- gz->color_hi[3] = 0.5f;
- }
- else {
- uchar icon_color[3];
- UI_GetThemeColor3ubv(TH_TEXT, icon_color);
- int color_tint, color_tint_hi;
- if (icon_color[0] > 128) {
- color_tint = -40;
- color_tint_hi = 60;
- gz->color[3] = 0.5f;
- gz->color_hi[3] = 0.5f;
- }
- else {
- color_tint = 60;
- color_tint_hi = 60;
- gz->color[3] = 0.5f;
- gz->color_hi[3] = 0.75f;
- }
- UI_GetThemeColorShade3fv(TH_HEADER, color_tint, gz->color);
- UI_GetThemeColorShade3fv(TH_HEADER, color_tint_hi, gz->color_hi);
- }
-
- /* may be overwritten later */
- gz->scale_basis = (GIZMO_SIZE * GIZMO_MINI_FAC) / 2;
- if (info->icon != 0) {
- PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon");
- RNA_property_enum_set(gz->ptr, prop, info->icon);
- RNA_enum_set(gz->ptr, "draw_options", ED_GIZMO_BUTTON_SHOW_OUTLINE | ED_GIZMO_BUTTON_SHOW_BACKDROP);
- }
-
- wmOperatorType *ot = WM_operatortype_find(info->opname, true);
- WM_gizmo_operator_set(gz, 0, ot, NULL);
- }
-
- {
- wmGizmo *gz = navgroup->gz_array[GZ_INDEX_CAMERA];
- WM_gizmo_operator_set(gz, 0, ot_view_camera, NULL);
- }
-
- /* Click only buttons (not modal). */
- {
- int gz_ids[] = {GZ_INDEX_PERSP, GZ_INDEX_ORTHO, GZ_INDEX_CAMERA};
- for (int i = 0; i < ARRAY_SIZE(gz_ids); i++) {
- wmGizmo *gz = navgroup->gz_array[gz_ids[i]];
- RNA_boolean_set(gz->ptr, "show_drag", false);
- }
- }
-
- /* Modal operators, don't use initial mouse location since we're clicking on a button. */
- {
- int gz_ids[] = {GZ_INDEX_MOVE, GZ_INDEX_ROTATE, GZ_INDEX_ZOOM};
- for (int i = 0; i < ARRAY_SIZE(gz_ids); i++) {
- wmGizmo *gz = navgroup->gz_array[gz_ids[i]];
- wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
- RNA_boolean_set(&gzop->ptr, "use_mouse_init", false);
- }
- }
-
- {
- wmGizmo *gz = navgroup->gz_array[GZ_INDEX_ROTATE];
- gz->scale_basis = GIZMO_SIZE / 2;
- char mapping[6] = {
- RV3D_VIEW_LEFT,
- RV3D_VIEW_RIGHT,
- RV3D_VIEW_FRONT,
- RV3D_VIEW_BACK,
- RV3D_VIEW_BOTTOM,
- RV3D_VIEW_TOP,
- };
-
- for (int part_index = 0; part_index < 6; part_index += 1) {
- PointerRNA *ptr = WM_gizmo_operator_set(gz, part_index + 1, ot_view_axis, NULL);
- RNA_enum_set(ptr, "type", mapping[part_index]);
- }
-
- /* When dragging an axis, use this instead. */
- gz->drag_part = 0;
- }
-
- gzgroup->customdata = navgroup;
+ struct NavigateWidgetGroup *navgroup = MEM_callocN(sizeof(struct NavigateWidgetGroup), __func__);
+
+ navgroup->region_size[0] = -1;
+ navgroup->region_size[1] = -1;
+
+ wmOperatorType *ot_view_axis = WM_operatortype_find("VIEW3D_OT_view_axis", true);
+ wmOperatorType *ot_view_camera = WM_operatortype_find("VIEW3D_OT_view_camera", true);
+
+ for (int i = 0; i < GZ_INDEX_TOTAL; i++) {
+ const struct NavigateGizmoInfo *info = &g_navigate_params[i];
+ navgroup->gz_array[i] = WM_gizmo_new(info->gizmo, gzgroup, NULL);
+ wmGizmo *gz = navgroup->gz_array[i];
+ gz->flag |= WM_GIZMO_MOVE_CURSOR | WM_GIZMO_DRAW_MODAL;
+
+ if (i == GZ_INDEX_ROTATE) {
+ gz->color[3] = 0.0f;
+ copy_v3_fl(gz->color_hi, 0.5f);
+ gz->color_hi[3] = 0.5f;
+ }
+ else {
+ uchar icon_color[3];
+ UI_GetThemeColor3ubv(TH_TEXT, icon_color);
+ int color_tint, color_tint_hi;
+ if (icon_color[0] > 128) {
+ color_tint = -40;
+ color_tint_hi = 60;
+ gz->color[3] = 0.5f;
+ gz->color_hi[3] = 0.5f;
+ }
+ else {
+ color_tint = 60;
+ color_tint_hi = 60;
+ gz->color[3] = 0.5f;
+ gz->color_hi[3] = 0.75f;
+ }
+ UI_GetThemeColorShade3fv(TH_HEADER, color_tint, gz->color);
+ UI_GetThemeColorShade3fv(TH_HEADER, color_tint_hi, gz->color_hi);
+ }
+
+ /* may be overwritten later */
+ gz->scale_basis = (GIZMO_SIZE * GIZMO_MINI_FAC) / 2;
+ if (info->icon != 0) {
+ PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon");
+ RNA_property_enum_set(gz->ptr, prop, info->icon);
+ RNA_enum_set(
+ gz->ptr, "draw_options", ED_GIZMO_BUTTON_SHOW_OUTLINE | ED_GIZMO_BUTTON_SHOW_BACKDROP);
+ }
+
+ wmOperatorType *ot = WM_operatortype_find(info->opname, true);
+ WM_gizmo_operator_set(gz, 0, ot, NULL);
+ }
+
+ {
+ wmGizmo *gz = navgroup->gz_array[GZ_INDEX_CAMERA];
+ WM_gizmo_operator_set(gz, 0, ot_view_camera, NULL);
+ }
+
+ /* Click only buttons (not modal). */
+ {
+ int gz_ids[] = {GZ_INDEX_PERSP, GZ_INDEX_ORTHO, GZ_INDEX_CAMERA};
+ for (int i = 0; i < ARRAY_SIZE(gz_ids); i++) {
+ wmGizmo *gz = navgroup->gz_array[gz_ids[i]];
+ RNA_boolean_set(gz->ptr, "show_drag", false);
+ }
+ }
+
+ /* Modal operators, don't use initial mouse location since we're clicking on a button. */
+ {
+ int gz_ids[] = {GZ_INDEX_MOVE, GZ_INDEX_ROTATE, GZ_INDEX_ZOOM};
+ for (int i = 0; i < ARRAY_SIZE(gz_ids); i++) {
+ wmGizmo *gz = navgroup->gz_array[gz_ids[i]];
+ wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
+ RNA_boolean_set(&gzop->ptr, "use_mouse_init", false);
+ }
+ }
+
+ {
+ wmGizmo *gz = navgroup->gz_array[GZ_INDEX_ROTATE];
+ gz->scale_basis = GIZMO_SIZE / 2;
+ char mapping[6] = {
+ RV3D_VIEW_LEFT,
+ RV3D_VIEW_RIGHT,
+ RV3D_VIEW_FRONT,
+ RV3D_VIEW_BACK,
+ RV3D_VIEW_BOTTOM,
+ RV3D_VIEW_TOP,
+ };
+
+ for (int part_index = 0; part_index < 6; part_index += 1) {
+ PointerRNA *ptr = WM_gizmo_operator_set(gz, part_index + 1, ot_view_axis, NULL);
+ RNA_enum_set(ptr, "type", mapping[part_index]);
+ }
+
+ /* When dragging an axis, use this instead. */
+ gz->drag_part = 0;
+ }
+
+ gzgroup->customdata = navgroup;
}
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;
-
- for (int i = 0; i < 3; i++) {
- copy_v3_v3(navgroup->gz_array[GZ_INDEX_ROTATE]->matrix_offset[i], rv3d->viewmat[i]);
- }
-
- rcti rect_visible;
- ED_region_visible_rect(ar, &rect_visible);
-
- 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))
- {
- 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;
-
- const bool show_rotate = (
- ((rv3d->viewlock & RV3D_LOCKED) == 0) &&
- (navgroup->state.rv3d.is_camera == false));
- const bool show_fixed_offset = navgroup->state.rv3d.is_camera;
- const float icon_size = GIZMO_SIZE;
- const float icon_offset = (icon_size * 0.52f) * GIZMO_OFFSET_FAC * UI_DPI_FAC;
- const float icon_offset_mini = icon_size * GIZMO_MINI_OFFSET_FAC * UI_DPI_FAC;
- const float co_rotate[2] = {
- rect_visible.xmax - icon_offset,
- rect_visible.ymax - icon_offset,
- };
- const float co[2] = {
- rect_visible.xmax - ((show_rotate || show_fixed_offset) ? (icon_offset * 2.0f) : (icon_offset_mini * 0.75f)),
- rect_visible.ymax - icon_offset_mini * 0.75f,
- };
-
- wmGizmo *gz;
-
- for (uint i = 0; i < ARRAY_SIZE(navgroup->gz_array); i++) {
- gz = navgroup->gz_array[i];
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
- }
-
- /* RV3D_LOCKED or Camera: only show supported buttons. */
- if (show_rotate) {
- gz = navgroup->gz_array[GZ_INDEX_ROTATE];
- gz->matrix_basis[3][0] = co_rotate[0];
- gz->matrix_basis[3][1] = co_rotate[1];
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
- }
-
- int icon_mini_slot = 0;
-
- gz = navgroup->gz_array[GZ_INDEX_ZOOM];
- gz->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
- gz->matrix_basis[3][1] = co[1];
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
-
- gz = navgroup->gz_array[GZ_INDEX_MOVE];
- gz->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
- gz->matrix_basis[3][1] = co[1];
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
-
- if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
- gz = navgroup->gz_array[GZ_INDEX_CAMERA];
- gz->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
- gz->matrix_basis[3][1] = co[1];
- 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] - (icon_offset_mini * icon_mini_slot++);
- gz->matrix_basis[3][1] = co[1];
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
- }
- }
+ struct NavigateWidgetGroup *navgroup = gzgroup->customdata;
+ ARegion *ar = CTX_wm_region(C);
+ const RegionView3D *rv3d = ar->regiondata;
+
+ for (int i = 0; i < 3; i++) {
+ copy_v3_v3(navgroup->gz_array[GZ_INDEX_ROTATE]->matrix_offset[i], rv3d->viewmat[i]);
+ }
+
+ rcti rect_visible;
+ ED_region_visible_rect(ar, &rect_visible);
+
+ 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)) {
+ 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;
+
+ const bool show_rotate = (((rv3d->viewlock & RV3D_LOCKED) == 0) &&
+ (navgroup->state.rv3d.is_camera == false));
+ const bool show_fixed_offset = navgroup->state.rv3d.is_camera;
+ const float icon_size = GIZMO_SIZE;
+ const float icon_offset = (icon_size * 0.52f) * GIZMO_OFFSET_FAC * UI_DPI_FAC;
+ const float icon_offset_mini = icon_size * GIZMO_MINI_OFFSET_FAC * UI_DPI_FAC;
+ const float co_rotate[2] = {
+ rect_visible.xmax - icon_offset,
+ rect_visible.ymax - icon_offset,
+ };
+ const float co[2] = {
+ rect_visible.xmax -
+ ((show_rotate || show_fixed_offset) ? (icon_offset * 2.0f) : (icon_offset_mini * 0.75f)),
+ rect_visible.ymax - icon_offset_mini * 0.75f,
+ };
+
+ wmGizmo *gz;
+
+ for (uint i = 0; i < ARRAY_SIZE(navgroup->gz_array); i++) {
+ gz = navgroup->gz_array[i];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
+ }
+
+ /* RV3D_LOCKED or Camera: only show supported buttons. */
+ if (show_rotate) {
+ gz = navgroup->gz_array[GZ_INDEX_ROTATE];
+ gz->matrix_basis[3][0] = co_rotate[0];
+ gz->matrix_basis[3][1] = co_rotate[1];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
+ }
+
+ int icon_mini_slot = 0;
+
+ gz = navgroup->gz_array[GZ_INDEX_ZOOM];
+ gz->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ gz->matrix_basis[3][1] = co[1];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
+
+ gz = navgroup->gz_array[GZ_INDEX_MOVE];
+ gz->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ gz->matrix_basis[3][1] = co[1];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
+
+ if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
+ gz = navgroup->gz_array[GZ_INDEX_CAMERA];
+ gz->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ gz->matrix_basis[3][1] = co[1];
+ 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] - (icon_offset_mini * icon_mini_slot++);
+ gz->matrix_basis[3][1] = co[1];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
+ }
+ }
}
void VIEW3D_GGT_navigate(wmGizmoGroupType *gzgt)
{
- gzgt->name = "View3D Navigate";
- gzgt->idname = "VIEW3D_GGT_navigate";
+ gzgt->name = "View3D Navigate";
+ gzgt->idname = "VIEW3D_GGT_navigate";
- gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT |
- WM_GIZMOGROUPTYPE_SCALE |
- WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL);
+ gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_SCALE |
+ WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL);
- gzgt->poll = WIDGETGROUP_navigate_poll;
- gzgt->setup = WIDGETGROUP_navigate_setup;
- gzgt->draw_prepare = WIDGETGROUP_navigate_draw_prepare;
+ gzgt->poll = WIDGETGROUP_navigate_poll;
+ gzgt->setup = WIDGETGROUP_navigate_setup;
+ gzgt->draw_prepare = WIDGETGROUP_navigate_draw_prepare;
}
/** \} */
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 f9b67a430e6..539b5d93bdf 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c
@@ -33,7 +33,6 @@
#include "BKE_context.h"
-
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
@@ -71,12 +70,12 @@
#define AXIS_HANDLE_OFFSET (1.0f - AXIS_HANDLE_SIZE_FG)
struct AxisDrawInfo {
- /* Matrix is needed for screen-aligned font drawing. */
+ /* Matrix is needed for screen-aligned font drawing. */
#ifdef USE_AXIS_FONT
- float matrix_final[4][4];
+ float matrix_final[4][4];
#endif
#ifdef USE_FADE_BACKGROUND
- float color_bg[3];
+ float color_bg[3];
#endif
};
@@ -86,451 +85,453 @@ struct AxisDrawInfo {
* copied into a 3x3 matrix and normalized.
*/
static void draw_xyz_wire(
- uint pos_id, const float viewmat_local_unit[3][3], const float c[3], float size, int axis)
+ uint pos_id, const float viewmat_local_unit[3][3], const float c[3], float size, int axis)
{
- int line_type;
- float buffer[4][3];
- int n = 0;
+ int line_type;
+ float buffer[4][3];
+ int n = 0;
- float v1[3] = {0.0f, 0.0f, 0.0f}, v2[3] = {0.0f, 0.0f, 0.0f};
- float dim = size * 0.1f;
- float dx[3], dy[3];
+ float v1[3] = {0.0f, 0.0f, 0.0f}, v2[3] = {0.0f, 0.0f, 0.0f};
+ float dim = size * 0.1f;
+ float dx[3], dy[3];
- dx[0] = dim; dx[1] = 0.0f; dx[2] = 0.0f;
- dy[0] = 0.0f; dy[1] = dim; dy[2] = 0.0f;
+ dx[0] = dim;
+ dx[1] = 0.0f;
+ dx[2] = 0.0f;
+ dy[0] = 0.0f;
+ dy[1] = dim;
+ dy[2] = 0.0f;
- switch (axis) {
- case 0: /* x axis */
- line_type = GPU_PRIM_LINES;
+ switch (axis) {
+ case 0: /* x axis */
+ line_type = GPU_PRIM_LINES;
- /* bottom left to top right */
- negate_v3_v3(v1, dx);
- sub_v3_v3(v1, dy);
- copy_v3_v3(v2, dx);
- add_v3_v3(v2, dy);
+ /* bottom left to top right */
+ negate_v3_v3(v1, dx);
+ sub_v3_v3(v1, dy);
+ copy_v3_v3(v2, dx);
+ add_v3_v3(v2, dy);
- copy_v3_v3(buffer[n++], v1);
- copy_v3_v3(buffer[n++], v2);
+ copy_v3_v3(buffer[n++], v1);
+ copy_v3_v3(buffer[n++], v2);
- /* top left to bottom right */
- mul_v3_fl(dy, 2.0f);
- add_v3_v3(v1, dy);
- sub_v3_v3(v2, dy);
+ /* top left to bottom right */
+ mul_v3_fl(dy, 2.0f);
+ add_v3_v3(v1, dy);
+ sub_v3_v3(v2, dy);
- copy_v3_v3(buffer[n++], v1);
- copy_v3_v3(buffer[n++], v2);
+ copy_v3_v3(buffer[n++], v1);
+ copy_v3_v3(buffer[n++], v2);
- break;
- case 1: /* y axis */
- line_type = GPU_PRIM_LINES;
+ break;
+ case 1: /* y axis */
+ line_type = GPU_PRIM_LINES;
- /* bottom left to top right */
- mul_v3_fl(dx, 0.75f);
- negate_v3_v3(v1, dx);
- sub_v3_v3(v1, dy);
- copy_v3_v3(v2, dx);
- add_v3_v3(v2, dy);
+ /* bottom left to top right */
+ mul_v3_fl(dx, 0.75f);
+ negate_v3_v3(v1, dx);
+ sub_v3_v3(v1, dy);
+ copy_v3_v3(v2, dx);
+ add_v3_v3(v2, dy);
- copy_v3_v3(buffer[n++], v1);
- copy_v3_v3(buffer[n++], v2);
+ copy_v3_v3(buffer[n++], v1);
+ copy_v3_v3(buffer[n++], v2);
- /* top left to center */
- mul_v3_fl(dy, 2.0f);
- add_v3_v3(v1, dy);
- zero_v3(v2);
+ /* top left to center */
+ mul_v3_fl(dy, 2.0f);
+ add_v3_v3(v1, dy);
+ zero_v3(v2);
- copy_v3_v3(buffer[n++], v1);
- copy_v3_v3(buffer[n++], v2);
+ copy_v3_v3(buffer[n++], v1);
+ copy_v3_v3(buffer[n++], v2);
- break;
- case 2: /* z axis */
- line_type = GPU_PRIM_LINE_STRIP;
+ break;
+ case 2: /* z axis */
+ line_type = GPU_PRIM_LINE_STRIP;
- /* start at top left */
- negate_v3_v3(v1, dx);
- add_v3_v3(v1, dy);
+ /* start at top left */
+ negate_v3_v3(v1, dx);
+ add_v3_v3(v1, dy);
- copy_v3_v3(buffer[n++], v1);
+ copy_v3_v3(buffer[n++], v1);
- mul_v3_fl(dx, 2.0f);
- add_v3_v3(v1, dx);
+ mul_v3_fl(dx, 2.0f);
+ add_v3_v3(v1, dx);
- copy_v3_v3(buffer[n++], v1);
+ copy_v3_v3(buffer[n++], v1);
- mul_v3_fl(dy, 2.0f);
- sub_v3_v3(v1, dx);
- sub_v3_v3(v1, dy);
+ mul_v3_fl(dy, 2.0f);
+ sub_v3_v3(v1, dx);
+ sub_v3_v3(v1, dy);
- copy_v3_v3(buffer[n++], v1);
+ copy_v3_v3(buffer[n++], v1);
- add_v3_v3(v1, dx);
+ add_v3_v3(v1, dx);
- copy_v3_v3(buffer[n++], v1);
+ copy_v3_v3(buffer[n++], v1);
- break;
- default:
- BLI_assert(0);
- return;
- }
+ break;
+ default:
+ BLI_assert(0);
+ return;
+ }
- for (int i = 0; i < n; i++) {
- mul_transposed_m3_v3((float (*)[3])viewmat_local_unit, buffer[i]);
- add_v3_v3(buffer[i], c);
- }
+ for (int i = 0; i < n; i++) {
+ mul_transposed_m3_v3((float(*)[3])viewmat_local_unit, buffer[i]);
+ add_v3_v3(buffer[i], c);
+ }
- immBegin(line_type, n);
- for (int i = 0; i < n; i++) {
- immVertex3fv(pos_id, buffer[i]);
- }
- immEnd();
+ immBegin(line_type, n);
+ for (int i = 0; i < n; i++) {
+ immVertex3fv(pos_id, buffer[i]);
+ }
+ immEnd();
}
-#endif /* !USE_AXIS_FONT */
+#endif /* !USE_AXIS_FONT */
/**
* \param draw_info: Extra data needed for drawing.
*/
-static void axis_geom_draw(
- const wmGizmo *gz, const float color[4], const bool select,
- const struct AxisDrawInfo *draw_info)
+static void axis_geom_draw(const wmGizmo *gz,
+ const float color[4],
+ const bool select,
+ const struct AxisDrawInfo *draw_info)
{
- GPU_line_width(gz->line_width);
-
- GPUVertFormat *format = immVertexFormat();
- const uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
-
- struct {
- float depth;
- char index;
- char axis;
- bool is_pos;
- } axis_order[6] = {
- {-gz->matrix_offset[0][2], 0, 0, false},
- {+gz->matrix_offset[0][2], 1, 0, true},
- {-gz->matrix_offset[1][2], 2, 1, false},
- {+gz->matrix_offset[1][2], 3, 1, true},
- {-gz->matrix_offset[2][2], 4, 2, false},
- {+gz->matrix_offset[2][2], 5, 2, true},
- };
-
- int axis_align = -1;
- for (int axis = 0; axis < 3; axis++) {
- if (len_squared_v2(gz->matrix_offset[axis]) < 1e-6f) {
- axis_align = axis;
- break;
- }
- }
-
- /* Show backwards pointing highlight on-top (else we can't see it at all). */
- if ((select == false) && (gz->highlight_part > 0) && (axis_align != -1)) {
- if (axis_order[gz->highlight_part - 1].is_pos == false) {
- axis_order[gz->highlight_part - 1].depth = FLT_MAX;
- }
- }
-
- qsort(&axis_order, ARRAY_SIZE(axis_order), sizeof(axis_order[0]), BLI_sortutil_cmp_float);
-
- static const float axis_highlight[4] = {1, 1, 1, 1};
- static const float axis_black[4] = {0, 0, 0, 1};
- static float axis_color[3][4];
-
- const float axis_depth_bias = 0.01f;
+ GPU_line_width(gz->line_width);
+
+ GPUVertFormat *format = immVertexFormat();
+ const uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ struct {
+ float depth;
+ char index;
+ char axis;
+ bool is_pos;
+ } axis_order[6] = {
+ {-gz->matrix_offset[0][2], 0, 0, false},
+ {+gz->matrix_offset[0][2], 1, 0, true},
+ {-gz->matrix_offset[1][2], 2, 1, false},
+ {+gz->matrix_offset[1][2], 3, 1, true},
+ {-gz->matrix_offset[2][2], 4, 2, false},
+ {+gz->matrix_offset[2][2], 5, 2, true},
+ };
+
+ int axis_align = -1;
+ for (int axis = 0; axis < 3; axis++) {
+ if (len_squared_v2(gz->matrix_offset[axis]) < 1e-6f) {
+ axis_align = axis;
+ break;
+ }
+ }
+
+ /* Show backwards pointing highlight on-top (else we can't see it at all). */
+ if ((select == false) && (gz->highlight_part > 0) && (axis_align != -1)) {
+ if (axis_order[gz->highlight_part - 1].is_pos == false) {
+ axis_order[gz->highlight_part - 1].depth = FLT_MAX;
+ }
+ }
+
+ qsort(&axis_order, ARRAY_SIZE(axis_order), sizeof(axis_order[0]), BLI_sortutil_cmp_float);
+
+ static const float axis_highlight[4] = {1, 1, 1, 1};
+ static const float axis_black[4] = {0, 0, 0, 1};
+ static float axis_color[3][4];
+
+ const float axis_depth_bias = 0.01f;
#ifdef USE_AXIS_FONT
- struct {
- float matrix[4][4];
- int id;
- } font;
-
- if (select == false) {
- font.id = blf_mono_font;
- BLF_disable(font.id, BLF_ROTATION | BLF_SHADOW | BLF_MATRIX | BLF_ASPECT | BLF_WORD_WRAP);
- BLF_color4fv(font.id, axis_black);
- BLF_size(font.id, 11 * U.dpi_fac, 72);
-
- /* Calculate the inverse of the (matrix_final * matrix_offset).
- * This allows us to use the final location, while reversing the rotation so fonts
- * show without any rotation. */
- float m3[3][3];
- float m3_offset[3][3];
- copy_m3_m4(m3, draw_info->matrix_final);
- copy_m3_m4(m3_offset, gz->matrix_offset);
- mul_m3_m3m3(m3, m3, m3_offset);
- invert_m3(m3);
- copy_m4_m3(font.matrix, m3);
- }
+ struct {
+ float matrix[4][4];
+ int id;
+ } font;
+
+ if (select == false) {
+ font.id = blf_mono_font;
+ BLF_disable(font.id, BLF_ROTATION | BLF_SHADOW | BLF_MATRIX | BLF_ASPECT | BLF_WORD_WRAP);
+ BLF_color4fv(font.id, axis_black);
+ BLF_size(font.id, 11 * U.dpi_fac, 72);
+
+ /* Calculate the inverse of the (matrix_final * matrix_offset).
+ * This allows us to use the final location, while reversing the rotation so fonts
+ * show without any rotation. */
+ float m3[3][3];
+ float m3_offset[3][3];
+ copy_m3_m4(m3, draw_info->matrix_final);
+ copy_m3_m4(m3_offset, gz->matrix_offset);
+ mul_m3_m3m3(m3, m3, m3_offset);
+ invert_m3(m3);
+ copy_m4_m3(font.matrix, m3);
+ }
#endif
- /* When the cursor is over any of the gizmos (show circle backdrop). */
- const bool is_active = (color[3] != 0.0f);
-
- /* Circle defining active area. */
- if (is_active) {
- immUniformColor4fv(color);
- imm_draw_circle_fill_3d(pos_id, 0, 0, 1.0f, DIAL_RESOLUTION);
- }
-
- GPU_matrix_push();
- GPU_matrix_mul(gz->matrix_offset);
-
- for (int axis_index = 0; axis_index < ARRAY_SIZE(axis_order); axis_index++) {
- const int index = axis_order[axis_index].index;
- const int axis = axis_order[axis_index].axis;
- const bool is_pos = axis_order[axis_index].is_pos;
- const bool is_highlight = index + 1 == gz->highlight_part;
-
- UI_GetThemeColor3fv(TH_AXIS_X + axis, axis_color[axis]);
- axis_color[axis][3] = 1.0f;
-
- const int index_z = axis;
- const int index_y = (axis + 1) % 3;
- const int index_x = (axis + 2) % 3;
-
- bool ok = true;
-
- /* Skip view align axis when selecting (allows to switch to opposite side). */
- if (select && ((axis_align == axis) && (gz->matrix_offset[axis][2] > 0.0f) == is_pos)) {
- ok = false;
- }
- if (ok) {
- /* Check aligned, since the front axis won't display in this case,
- * and we want to make sure all 3 axes have a character at all times. */
- const bool show_axis_char = (is_pos || (axis == axis_align));
- const float v[3] = {0, 0, AXIS_HANDLE_OFFSET * (is_pos ? 1 : -1)};
- const float v_final[3] = {v[index_x], v[index_y], v[index_z]};
- const float *color_current = is_highlight ? axis_highlight : axis_color[axis];
- float color_current_fade[4];
-
- /* Flip the faded state when axis aligned, since we're hiding the front-mode axis
- * otherwise we see the color for the back-most axis, which is useful for
- * click-to-rotate 180d but not useful to visualize.
- *
- * Use depth bias so axis-aligned views show the positive axis as being in-front.
- * This is a detail so primary axes show as dominant.
- */
- const bool is_pos_color = (
- axis_order[axis_index].depth > (axis_depth_bias * (is_pos ? -1 : 1)));
-
-
- if (select == false) {
+ /* When the cursor is over any of the gizmos (show circle backdrop). */
+ const bool is_active = (color[3] != 0.0f);
+
+ /* Circle defining active area. */
+ if (is_active) {
+ immUniformColor4fv(color);
+ imm_draw_circle_fill_3d(pos_id, 0, 0, 1.0f, DIAL_RESOLUTION);
+ }
+
+ GPU_matrix_push();
+ GPU_matrix_mul(gz->matrix_offset);
+
+ for (int axis_index = 0; axis_index < ARRAY_SIZE(axis_order); axis_index++) {
+ const int index = axis_order[axis_index].index;
+ const int axis = axis_order[axis_index].axis;
+ const bool is_pos = axis_order[axis_index].is_pos;
+ const bool is_highlight = index + 1 == gz->highlight_part;
+
+ UI_GetThemeColor3fv(TH_AXIS_X + axis, axis_color[axis]);
+ axis_color[axis][3] = 1.0f;
+
+ const int index_z = axis;
+ const int index_y = (axis + 1) % 3;
+ const int index_x = (axis + 2) % 3;
+
+ bool ok = true;
+
+ /* Skip view align axis when selecting (allows to switch to opposite side). */
+ if (select && ((axis_align == axis) && (gz->matrix_offset[axis][2] > 0.0f) == is_pos)) {
+ ok = false;
+ }
+ if (ok) {
+ /* Check aligned, since the front axis won't display in this case,
+ * and we want to make sure all 3 axes have a character at all times. */
+ const bool show_axis_char = (is_pos || (axis == axis_align));
+ const float v[3] = {0, 0, AXIS_HANDLE_OFFSET * (is_pos ? 1 : -1)};
+ const float v_final[3] = {v[index_x], v[index_y], v[index_z]};
+ const float *color_current = is_highlight ? axis_highlight : axis_color[axis];
+ float color_current_fade[4];
+
+ /* Flip the faded state when axis aligned, since we're hiding the front-mode axis
+ * otherwise we see the color for the back-most axis, which is useful for
+ * click-to-rotate 180d but not useful to visualize.
+ *
+ * Use depth bias so axis-aligned views show the positive axis as being in-front.
+ * This is a detail so primary axes show as dominant.
+ */
+ const bool is_pos_color = (axis_order[axis_index].depth >
+ (axis_depth_bias * (is_pos ? -1 : 1)));
+
+ if (select == false) {
#ifdef USE_FADE_BACKGROUND
- interp_v3_v3v3(color_current_fade, draw_info->color_bg, color_current, is_highlight ? 1.0 : 0.5f);
- color_current_fade[3] = color_current[3];
+ interp_v3_v3v3(
+ color_current_fade, draw_info->color_bg, color_current, is_highlight ? 1.0 : 0.5f);
+ color_current_fade[3] = color_current[3];
#else
- copy_v4_v4(color_current_fade, color_current);
- color_current_fade[3] *= 0.2;
+ copy_v4_v4(color_current_fade, color_current);
+ color_current_fade[3] *= 0.2;
#endif
- }
- else {
- copy_v4_fl(color_current_fade, 1.0f);
- }
-
- /* Axis Line. */
- if (is_pos) {
- float v_start[3];
- GPU_line_width(2.0f);
- immUniformColor4fv(is_pos_color ? color_current : color_current_fade);
- immBegin(GPU_PRIM_LINES, 2);
- if (axis_align == -1) {
- zero_v3(v_start);
- }
- else {
- /* When axis aligned we don't draw the front most axis
- * (allowing us to switch to the opposite side).
- * In this case don't draw lines over axis pointing away from us
- * because it obscures character and looks noisy.
- */
- mul_v3_v3fl(v_start, v_final, 0.3f);
- }
- immVertex3fv(pos_id, v_start);
- immVertex3fv(pos_id, v_final);
- immEnd();
- }
-
- /* Axis Ball. */
- {
- GPU_matrix_push();
- GPU_matrix_translate_3fv(v_final);
- GPU_matrix_scale_1f(is_pos ? AXIS_HANDLE_SIZE_FG : AXIS_HANDLE_SIZE_BG);
-
- GPUBatch *sphere = GPU_batch_preset_sphere(0);
- GPU_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR);
-
- /* Black outlines for negative axis balls, otherwise they can be hard to see since
- * 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_batch_uniform_4fv(sphere, "color", axis_black_faded);
- GPU_batch_draw(sphere);
- GPU_matrix_scale_1f(1.0 / scale);
- }
-
- GPU_batch_uniform_4fv(sphere, "color", is_pos_color ? color_current : color_current_fade);
- GPU_batch_draw(sphere);
- GPU_matrix_pop();
- }
-
- /* Axis XYZ Character. */
- if (show_axis_char && (select == false)) {
+ }
+ else {
+ copy_v4_fl(color_current_fade, 1.0f);
+ }
+
+ /* Axis Line. */
+ if (is_pos) {
+ float v_start[3];
+ GPU_line_width(2.0f);
+ immUniformColor4fv(is_pos_color ? color_current : color_current_fade);
+ immBegin(GPU_PRIM_LINES, 2);
+ if (axis_align == -1) {
+ zero_v3(v_start);
+ }
+ else {
+ /* When axis aligned we don't draw the front most axis
+ * (allowing us to switch to the opposite side).
+ * In this case don't draw lines over axis pointing away from us
+ * because it obscures character and looks noisy.
+ */
+ mul_v3_v3fl(v_start, v_final, 0.3f);
+ }
+ immVertex3fv(pos_id, v_start);
+ immVertex3fv(pos_id, v_final);
+ immEnd();
+ }
+
+ /* Axis Ball. */
+ {
+ GPU_matrix_push();
+ GPU_matrix_translate_3fv(v_final);
+ GPU_matrix_scale_1f(is_pos ? AXIS_HANDLE_SIZE_FG : AXIS_HANDLE_SIZE_BG);
+
+ GPUBatch *sphere = GPU_batch_preset_sphere(0);
+ GPU_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR);
+
+ /* Black outlines for negative axis balls, otherwise they can be hard to see since
+ * 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_batch_uniform_4fv(sphere, "color", axis_black_faded);
+ GPU_batch_draw(sphere);
+ GPU_matrix_scale_1f(1.0 / scale);
+ }
+
+ GPU_batch_uniform_4fv(sphere, "color", is_pos_color ? color_current : color_current_fade);
+ GPU_batch_draw(sphere);
+ GPU_matrix_pop();
+ }
+
+ /* Axis XYZ Character. */
+ if (show_axis_char && (select == false)) {
#ifdef USE_AXIS_FONT
- immUnbindProgram();
+ immUnbindProgram();
- GPU_matrix_push();
- GPU_matrix_translate_3fv(v_final);
- GPU_matrix_mul(font.matrix);
+ GPU_matrix_push();
+ GPU_matrix_translate_3fv(v_final);
+ GPU_matrix_mul(font.matrix);
- const char axis_str[2] = {'X' + axis, 0};
- float offset[2] = {0};
- BLF_width_and_height(font.id, axis_str, 2, &offset[0], &offset[1]);
- BLF_position(font.id, roundf(offset[0] * -0.5f), roundf(offset[1] * -0.5f), 0);
- BLF_draw_ascii(font.id, axis_str, 2);
- GPU_blend(true); /* XXX, blf disables */
- GPU_matrix_pop();
+ const char axis_str[2] = {'X' + axis, 0};
+ float offset[2] = {0};
+ BLF_width_and_height(font.id, axis_str, 2, &offset[0], &offset[1]);
+ BLF_position(font.id, roundf(offset[0] * -0.5f), roundf(offset[1] * -0.5f), 0);
+ BLF_draw_ascii(font.id, axis_str, 2);
+ GPU_blend(true); /* XXX, blf disables */
+ GPU_matrix_pop();
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
#else
- GPU_line_width(1.0f);
- float m3[3][3];
- copy_m3_m4(m3, gz->matrix_offset);
- immUniformColor4fv(axis_black);
- draw_xyz_wire(pos_id, m3, v_final, 1.0, axis);
+ GPU_line_width(1.0f);
+ float m3[3][3];
+ copy_m3_m4(m3, gz->matrix_offset);
+ immUniformColor4fv(axis_black);
+ draw_xyz_wire(pos_id, m3, v_final, 1.0, axis);
#endif
- }
- }
- }
+ }
+ }
+ }
- GPU_matrix_pop();
- immUnbindProgram();
+ GPU_matrix_pop();
+ immUnbindProgram();
}
-static void axis3d_draw_intern(
- const bContext *C, wmGizmo *gz,
- const bool select, const bool highlight)
+static void axis3d_draw_intern(const bContext *C,
+ wmGizmo *gz,
+ const bool select,
+ const bool highlight)
{
- const float *color = highlight ? gz->color_hi : gz->color;
- float matrix_final[4][4];
- float matrix_unit[4][4];
-
- unit_m4(matrix_unit);
+ const float *color = highlight ? gz->color_hi : gz->color;
+ float matrix_final[4][4];
+ float matrix_unit[4][4];
- WM_gizmo_calc_matrix_final_params(
- gz,
- &((struct WM_GizmoMatrixParams) {
- .matrix_offset = matrix_unit,
- }), matrix_final);
+ unit_m4(matrix_unit);
- GPU_matrix_push();
- GPU_matrix_mul(matrix_final);
+ WM_gizmo_calc_matrix_final_params(gz,
+ &((struct WM_GizmoMatrixParams){
+ .matrix_offset = matrix_unit,
+ }),
+ matrix_final);
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix_final);
- struct AxisDrawInfo draw_info;
+ struct AxisDrawInfo draw_info;
#ifdef USE_AXIS_FONT
- if (select == false) {
- copy_m4_m4(draw_info.matrix_final, matrix_final);
- }
+ if (select == false) {
+ copy_m4_m4(draw_info.matrix_final, matrix_final);
+ }
#endif
#ifdef USE_FADE_BACKGROUND
- if (select == false) {
- ED_view3d_background_color_get(CTX_data_scene(C), CTX_wm_view3d(C), draw_info.color_bg);
- }
+ if (select == false) {
+ ED_view3d_background_color_get(CTX_data_scene(C), CTX_wm_view3d(C), draw_info.color_bg);
+ }
#else
- UNUSED_VARS(C);
+ UNUSED_VARS(C);
#endif
- GPU_blend(true);
- axis_geom_draw(
- gz, color, select,
- &draw_info);
- GPU_blend(false);
- GPU_matrix_pop();
+ GPU_blend(true);
+ axis_geom_draw(gz, color, select, &draw_info);
+ GPU_blend(false);
+ GPU_matrix_pop();
}
static void gizmo_axis_draw(const bContext *C, wmGizmo *gz)
{
- const bool is_modal = gz->state & WM_GIZMO_STATE_MODAL;
- const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
+ const bool is_modal = gz->state & WM_GIZMO_STATE_MODAL;
+ const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
- (void)is_modal;
+ (void)is_modal;
- GPU_blend(true);
- axis3d_draw_intern(C, gz, false, is_highlight);
- GPU_blend(false);
+ GPU_blend(true);
+ axis3d_draw_intern(C, gz, false, is_highlight);
+ GPU_blend(false);
}
-static int gizmo_axis_test_select(
- bContext *UNUSED(C), wmGizmo *gz, const int mval[2])
+static int gizmo_axis_test_select(bContext *UNUSED(C), wmGizmo *gz, const int mval[2])
{
- float point_local[2] = {UNPACK2(mval)};
- sub_v2_v2(point_local, gz->matrix_basis[3]);
- mul_v2_fl(point_local, 1.0f / (gz->scale_basis * UI_DPI_FAC));
-
- const float len_sq = len_squared_v2(point_local);
- if (len_sq > 1.0) {
- return -1;
- }
-
- int part_best = -1;
- int part_index = 1;
- /* Use 'SQUARE(HANDLE_SIZE)' if we want to be able to _not_ focus on one of the axis. */
- float i_best_len_sq = FLT_MAX;
- for (int i = 0; i < 3; i++) {
- for (int is_pos = 0; is_pos < 2; is_pos++) {
- float co[2] = {
- gz->matrix_offset[i][0] * (is_pos ? 1 : -1),
- gz->matrix_offset[i][1] * (is_pos ? 1 : -1),
- };
-
- bool ok = true;
-
- /* Check if we're viewing on an axis,
- * there is no point to clicking on the current axis so show the reverse. */
- if (len_squared_v2(co) < 1e-6f && (gz->matrix_offset[i][2] > 0.0f) == is_pos) {
- ok = false;
- }
-
- if (ok) {
- const float len_axis_sq = len_squared_v2v2(co, point_local);
- if (len_axis_sq < i_best_len_sq) {
- part_best = part_index;
- i_best_len_sq = len_axis_sq;
- }
- }
- part_index += 1;
- }
- }
-
- if (part_best != -1) {
- return part_best;
- }
-
- /* The 'gz->scale_final' is already applied when projecting. */
- if (len_sq < 1.0f) {
- return 0;
- }
-
- return -1;
+ float point_local[2] = {UNPACK2(mval)};
+ sub_v2_v2(point_local, gz->matrix_basis[3]);
+ mul_v2_fl(point_local, 1.0f / (gz->scale_basis * UI_DPI_FAC));
+
+ const float len_sq = len_squared_v2(point_local);
+ if (len_sq > 1.0) {
+ return -1;
+ }
+
+ int part_best = -1;
+ int part_index = 1;
+ /* Use 'SQUARE(HANDLE_SIZE)' if we want to be able to _not_ focus on one of the axis. */
+ float i_best_len_sq = FLT_MAX;
+ for (int i = 0; i < 3; i++) {
+ for (int is_pos = 0; is_pos < 2; is_pos++) {
+ float co[2] = {
+ gz->matrix_offset[i][0] * (is_pos ? 1 : -1),
+ gz->matrix_offset[i][1] * (is_pos ? 1 : -1),
+ };
+
+ bool ok = true;
+
+ /* Check if we're viewing on an axis,
+ * there is no point to clicking on the current axis so show the reverse. */
+ if (len_squared_v2(co) < 1e-6f && (gz->matrix_offset[i][2] > 0.0f) == is_pos) {
+ ok = false;
+ }
+
+ if (ok) {
+ const float len_axis_sq = len_squared_v2v2(co, point_local);
+ if (len_axis_sq < i_best_len_sq) {
+ part_best = part_index;
+ i_best_len_sq = len_axis_sq;
+ }
+ }
+ part_index += 1;
+ }
+ }
+
+ if (part_best != -1) {
+ return part_best;
+ }
+
+ /* The 'gz->scale_final' is already applied when projecting. */
+ if (len_sq < 1.0f) {
+ return 0;
+ }
+
+ return -1;
}
static int gizmo_axis_cursor_get(wmGizmo *gz)
{
- if (gz->highlight_part > 0) {
- return CURSOR_EDIT;
- }
- return BC_NSEW_SCROLLCURSOR;
+ if (gz->highlight_part > 0) {
+ return CURSOR_EDIT;
+ }
+ return BC_NSEW_SCROLLCURSOR;
}
void VIEW3D_GT_navigate_rotate(wmGizmoType *gzt)
{
- /* identifiers */
- gzt->idname = "VIEW3D_GT_navigate_rotate";
+ /* identifiers */
+ gzt->idname = "VIEW3D_GT_navigate_rotate";
- /* api callbacks */
- gzt->draw = gizmo_axis_draw;
- gzt->test_select = gizmo_axis_test_select;
- gzt->cursor_get = gizmo_axis_cursor_get;
+ /* api callbacks */
+ gzt->draw = gizmo_axis_draw;
+ gzt->test_select = gizmo_axis_test_select;
+ gzt->cursor_get = gizmo_axis_cursor_get;
- gzt->struct_size = sizeof(wmGizmo);
+ gzt->struct_size = sizeof(wmGizmo);
}
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect.c
index b71c03684d6..b9dc287b9cb 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_preselect.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect.c
@@ -33,7 +33,7 @@
#include "WM_types.h"
#include "WM_toolsystem.h"
-#include "view3d_intern.h" /* own include */
+#include "view3d_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Mesh Pre-Select Element Gizmo
@@ -41,32 +41,32 @@
* \{ */
struct GizmoGroupPreSelElem {
- wmGizmo *gizmo;
+ wmGizmo *gizmo;
};
static void WIDGETGROUP_mesh_preselect_elem_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- const wmGizmoType *gzt_presel = WM_gizmotype_find("GIZMO_GT_mesh_preselect_elem_3d", true);
- struct GizmoGroupPreSelElem *ggd = MEM_callocN(sizeof(struct GizmoGroupPreSelElem), __func__);
- gzgroup->customdata = ggd;
+ const wmGizmoType *gzt_presel = WM_gizmotype_find("GIZMO_GT_mesh_preselect_elem_3d", true);
+ struct GizmoGroupPreSelElem *ggd = MEM_callocN(sizeof(struct GizmoGroupPreSelElem), __func__);
+ gzgroup->customdata = ggd;
- wmGizmo *gz = ggd->gizmo = WM_gizmo_new_ptr(gzt_presel, gzgroup, NULL);
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
+ wmGizmo *gz = ggd->gizmo = WM_gizmo_new_ptr(gzt_presel, gzgroup, NULL);
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
}
void VIEW3D_GGT_mesh_preselect_elem(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Mesh Preselect Element";
- gzgt->idname = "VIEW3D_GGT_mesh_preselect_elem";
+ gzgt->name = "Mesh Preselect Element";
+ gzgt->idname = "VIEW3D_GGT_mesh_preselect_elem";
- gzgt->flag = WM_GIZMOGROUPTYPE_3D;
+ gzgt->flag = WM_GIZMOGROUPTYPE_3D;
- gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
- gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool;
- gzgt->setup = WIDGETGROUP_mesh_preselect_elem_setup;
+ gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool;
+ gzgt->setup = WIDGETGROUP_mesh_preselect_elem_setup;
}
/** \} */
@@ -77,32 +77,34 @@ void VIEW3D_GGT_mesh_preselect_elem(wmGizmoGroupType *gzgt)
* \{ */
struct GizmoGroupPreSelEdgeRing {
- wmGizmo *gizmo;
+ wmGizmo *gizmo;
};
-static void WIDGETGROUP_mesh_preselect_edgering_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
+static void WIDGETGROUP_mesh_preselect_edgering_setup(const bContext *UNUSED(C),
+ wmGizmoGroup *gzgroup)
{
- const wmGizmoType *gzt_presel = WM_gizmotype_find("GIZMO_GT_mesh_preselect_edgering_3d", true);
- struct GizmoGroupPreSelEdgeRing *ggd = MEM_callocN(sizeof(struct GizmoGroupPreSelEdgeRing), __func__);
- gzgroup->customdata = ggd;
-
- wmGizmo *gz = ggd->gizmo = WM_gizmo_new_ptr(gzt_presel, gzgroup, NULL);
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
+ const wmGizmoType *gzt_presel = WM_gizmotype_find("GIZMO_GT_mesh_preselect_edgering_3d", true);
+ struct GizmoGroupPreSelEdgeRing *ggd = MEM_callocN(sizeof(struct GizmoGroupPreSelEdgeRing),
+ __func__);
+ gzgroup->customdata = ggd;
+
+ wmGizmo *gz = ggd->gizmo = WM_gizmo_new_ptr(gzt_presel, gzgroup, NULL);
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
}
void VIEW3D_GGT_mesh_preselect_edgering(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Mesh Preselect Edge Ring";
- gzgt->idname = "VIEW3D_GGT_mesh_preselect_edgering";
+ gzgt->name = "Mesh Preselect Edge Ring";
+ gzgt->idname = "VIEW3D_GGT_mesh_preselect_edgering";
- gzgt->flag = WM_GIZMOGROUPTYPE_3D;
+ gzgt->flag = WM_GIZMOGROUPTYPE_3D;
- gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
- gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool;
- gzgt->setup = WIDGETGROUP_mesh_preselect_edgering_setup;
+ gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool;
+ gzgt->setup = WIDGETGROUP_mesh_preselect_edgering_setup;
}
/** \} */
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 418a9e76678..6f35c0aa748 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
@@ -55,196 +55,194 @@
*
* \{ */
-
typedef struct MeshElemGizmo3D {
- wmGizmo gizmo;
- Base **bases;
- uint bases_len;
- int base_index;
- int vert_index;
- int edge_index;
- int face_index;
- struct EditMesh_PreSelElem *psel;
+ wmGizmo gizmo;
+ Base **bases;
+ uint bases_len;
+ int base_index;
+ int vert_index;
+ int edge_index;
+ int face_index;
+ struct EditMesh_PreSelElem *psel;
} MeshElemGizmo3D;
static void gizmo_preselect_elem_draw(const bContext *UNUSED(C), wmGizmo *gz)
{
- MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz;
- if (gz_ele->base_index != -1) {
- Object *ob = gz_ele->bases[gz_ele->base_index]->object;
- EDBM_preselect_elem_draw(gz_ele->psel, ob->obmat);
- }
+ MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz;
+ if (gz_ele->base_index != -1) {
+ Object *ob = gz_ele->bases[gz_ele->base_index]->object;
+ EDBM_preselect_elem_draw(gz_ele->psel, ob->obmat);
+ }
}
-static int gizmo_preselect_elem_test_select(
- bContext *C, wmGizmo *gz, const int mval[2])
+static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int mval[2])
{
- MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz;
- struct {
- Object *ob;
- BMElem *ele;
- float dist;
- int base_index;
- } best = {
- .dist = ED_view3d_select_dist_px(),
- };
-
- struct {
- int base_index;
- int vert_index;
- int edge_index;
- int face_index;
- } prev = {
- .base_index = gz_ele->base_index,
- .vert_index = gz_ele->vert_index,
- .edge_index = gz_ele->edge_index,
- .face_index = gz_ele->face_index,
- };
-
- {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- if (((gz_ele->bases)) == NULL ||
- (gz_ele->bases[0] != view_layer->basact))
- {
- MEM_SAFE_FREE(gz_ele->bases);
- gz_ele->bases = BKE_view_layer_array_from_bases_in_edit_mode(
- view_layer, v3d, &gz_ele->bases_len);
- }
- }
-
- ViewContext vc;
- em_setup_viewcontext(C, &vc);
- copy_v2_v2_int(vc.mval, mval);
-
- {
- /* TODO: support faces. */
- int base_index = -1;
- BMVert *eve_test;
- BMEdge *eed_test;
-
- if (EDBM_unified_findnearest_from_raycast(
- &vc, gz_ele->bases, gz_ele->bases_len,
- true, &base_index, &eve_test, &eed_test, NULL))
- {
- Base *base = gz_ele->bases[base_index];
- best.ob = base->object;
- if (eve_test) {
- best.ele = (BMElem *)eve_test;
- }
- else if (eed_test) {
- best.ele = (BMElem *)eed_test;
- }
- else {
- BLI_assert(0);
- }
- best.base_index = base_index;
- /* Check above should never fail, if it does it's an internal error. */
- BLI_assert(best.base_index != -1);
- }
- }
-
- BMesh *bm = NULL;
-
- gz_ele->base_index = -1;
- gz_ele->vert_index = -1;
- gz_ele->edge_index = -1;
- gz_ele->face_index = -1;
-
- if (best.ele) {
- gz_ele->base_index = best.base_index;
- bm = BKE_editmesh_from_object(gz_ele->bases[gz_ele->base_index]->object)->bm;
- BM_mesh_elem_index_ensure(bm, best.ele->head.htype);
-
- if (best.ele->head.htype == BM_VERT) {
- gz_ele->vert_index = BM_elem_index_get(best.ele);
- }
- else if (best.ele->head.htype == BM_EDGE) {
- gz_ele->edge_index = BM_elem_index_get(best.ele);
- }
- else if (best.ele->head.htype == BM_FACE) {
- gz_ele->face_index = BM_elem_index_get(best.ele);
- }
- }
-
- if ((prev.base_index == gz_ele->base_index) &&
- (prev.vert_index == gz_ele->vert_index) &&
- (prev.edge_index == gz_ele->edge_index) &&
- (prev.face_index == gz_ele->face_index))
- {
- /* pass (only recalculate on change) */
- }
- else {
- if (best.ele) {
- const float (*coords)[3] = NULL;
- {
- Object *ob = gz_ele->bases[gz_ele->base_index]->object;
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data);
- if (me_eval->runtime.edit_data) {
- coords = me_eval->runtime.edit_data->vertexCos;
- }
- }
- EDBM_preselect_elem_update_from_single(gz_ele->psel, bm, best.ele, coords);
- }
- else {
- EDBM_preselect_elem_clear(gz_ele->psel);
- }
-
- RNA_int_set(gz->ptr, "object_index", gz_ele->base_index);
- RNA_int_set(gz->ptr, "vert_index", gz_ele->vert_index);
- RNA_int_set(gz->ptr, "edge_index", gz_ele->edge_index);
- RNA_int_set(gz->ptr, "face_index", gz_ele->face_index);
-
- ARegion *ar = CTX_wm_region(C);
- ED_region_tag_redraw(ar);
- }
-
- // return best.eed ? 0 : -1;
- return -1;
+ MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz;
+ struct {
+ Object *ob;
+ BMElem *ele;
+ float dist;
+ int base_index;
+ } best = {
+ .dist = ED_view3d_select_dist_px(),
+ };
+
+ struct {
+ int base_index;
+ int vert_index;
+ int edge_index;
+ int face_index;
+ } prev = {
+ .base_index = gz_ele->base_index,
+ .vert_index = gz_ele->vert_index,
+ .edge_index = gz_ele->edge_index,
+ .face_index = gz_ele->face_index,
+ };
+
+ {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ if (((gz_ele->bases)) == NULL || (gz_ele->bases[0] != view_layer->basact)) {
+ MEM_SAFE_FREE(gz_ele->bases);
+ gz_ele->bases = BKE_view_layer_array_from_bases_in_edit_mode(
+ view_layer, v3d, &gz_ele->bases_len);
+ }
+ }
+
+ ViewContext vc;
+ em_setup_viewcontext(C, &vc);
+ copy_v2_v2_int(vc.mval, mval);
+
+ {
+ /* TODO: support faces. */
+ int base_index = -1;
+ BMVert *eve_test;
+ BMEdge *eed_test;
+
+ if (EDBM_unified_findnearest_from_raycast(&vc,
+ gz_ele->bases,
+ gz_ele->bases_len,
+ true,
+ &base_index,
+ &eve_test,
+ &eed_test,
+ NULL)) {
+ Base *base = gz_ele->bases[base_index];
+ best.ob = base->object;
+ if (eve_test) {
+ best.ele = (BMElem *)eve_test;
+ }
+ else if (eed_test) {
+ best.ele = (BMElem *)eed_test;
+ }
+ else {
+ BLI_assert(0);
+ }
+ best.base_index = base_index;
+ /* Check above should never fail, if it does it's an internal error. */
+ BLI_assert(best.base_index != -1);
+ }
+ }
+
+ BMesh *bm = NULL;
+
+ gz_ele->base_index = -1;
+ gz_ele->vert_index = -1;
+ gz_ele->edge_index = -1;
+ gz_ele->face_index = -1;
+
+ if (best.ele) {
+ gz_ele->base_index = best.base_index;
+ bm = BKE_editmesh_from_object(gz_ele->bases[gz_ele->base_index]->object)->bm;
+ BM_mesh_elem_index_ensure(bm, best.ele->head.htype);
+
+ if (best.ele->head.htype == BM_VERT) {
+ gz_ele->vert_index = BM_elem_index_get(best.ele);
+ }
+ else if (best.ele->head.htype == BM_EDGE) {
+ gz_ele->edge_index = BM_elem_index_get(best.ele);
+ }
+ else if (best.ele->head.htype == BM_FACE) {
+ gz_ele->face_index = BM_elem_index_get(best.ele);
+ }
+ }
+
+ if ((prev.base_index == gz_ele->base_index) && (prev.vert_index == gz_ele->vert_index) &&
+ (prev.edge_index == gz_ele->edge_index) && (prev.face_index == gz_ele->face_index)) {
+ /* pass (only recalculate on change) */
+ }
+ else {
+ if (best.ele) {
+ const float(*coords)[3] = NULL;
+ {
+ Object *ob = gz_ele->bases[gz_ele->base_index]->object;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data);
+ if (me_eval->runtime.edit_data) {
+ coords = me_eval->runtime.edit_data->vertexCos;
+ }
+ }
+ EDBM_preselect_elem_update_from_single(gz_ele->psel, bm, best.ele, coords);
+ }
+ else {
+ EDBM_preselect_elem_clear(gz_ele->psel);
+ }
+
+ RNA_int_set(gz->ptr, "object_index", gz_ele->base_index);
+ RNA_int_set(gz->ptr, "vert_index", gz_ele->vert_index);
+ RNA_int_set(gz->ptr, "edge_index", gz_ele->edge_index);
+ RNA_int_set(gz->ptr, "face_index", gz_ele->face_index);
+
+ ARegion *ar = CTX_wm_region(C);
+ ED_region_tag_redraw(ar);
+ }
+
+ // return best.eed ? 0 : -1;
+ return -1;
}
static void gizmo_preselect_elem_setup(wmGizmo *gz)
{
- MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz;
- if (gz_ele->psel == NULL) {
- gz_ele->psel = EDBM_preselect_elem_create();
- }
- gz_ele->base_index = -1;
+ MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz;
+ if (gz_ele->psel == NULL) {
+ gz_ele->psel = EDBM_preselect_elem_create();
+ }
+ gz_ele->base_index = -1;
}
static void gizmo_preselect_elem_free(wmGizmo *gz)
{
- MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz;
- EDBM_preselect_elem_destroy(gz_ele->psel);
- gz_ele->psel = NULL;
- MEM_SAFE_FREE(gz_ele->bases);
+ MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz;
+ EDBM_preselect_elem_destroy(gz_ele->psel);
+ gz_ele->psel = NULL;
+ MEM_SAFE_FREE(gz_ele->bases);
}
-static int gizmo_preselect_elem_invoke(
- bContext *UNUSED(C), wmGizmo *UNUSED(gz), const wmEvent *UNUSED(event))
+static int gizmo_preselect_elem_invoke(bContext *UNUSED(C),
+ wmGizmo *UNUSED(gz),
+ const wmEvent *UNUSED(event))
{
- return OPERATOR_PASS_THROUGH;
+ return OPERATOR_PASS_THROUGH;
}
static void GIZMO_GT_mesh_preselect_elem_3d(wmGizmoType *gzt)
{
- /* identifiers */
- gzt->idname = "GIZMO_GT_mesh_preselect_elem_3d";
-
- /* api callbacks */
- gzt->invoke = gizmo_preselect_elem_invoke;
- gzt->draw = gizmo_preselect_elem_draw;
- gzt->test_select = gizmo_preselect_elem_test_select;
- gzt->setup = gizmo_preselect_elem_setup;
- gzt->free = gizmo_preselect_elem_free;
-
- gzt->struct_size = sizeof(MeshElemGizmo3D);
-
- RNA_def_int(gzt->srna, "object_index", -1, -1, INT_MAX, "Object Index", "", -1, INT_MAX);
- RNA_def_int(gzt->srna, "vert_index", -1, -1, INT_MAX, "Vert Index", "", -1, INT_MAX);
- RNA_def_int(gzt->srna, "edge_index", -1, -1, INT_MAX, "Edge Index", "", -1, INT_MAX);
- RNA_def_int(gzt->srna, "face_index", -1, -1, INT_MAX, "Face Index", "", -1, INT_MAX);
+ /* identifiers */
+ gzt->idname = "GIZMO_GT_mesh_preselect_elem_3d";
+
+ /* api callbacks */
+ gzt->invoke = gizmo_preselect_elem_invoke;
+ gzt->draw = gizmo_preselect_elem_draw;
+ gzt->test_select = gizmo_preselect_elem_test_select;
+ gzt->setup = gizmo_preselect_elem_setup;
+ gzt->free = gizmo_preselect_elem_free;
+
+ gzt->struct_size = sizeof(MeshElemGizmo3D);
+
+ RNA_def_int(gzt->srna, "object_index", -1, -1, INT_MAX, "Object Index", "", -1, INT_MAX);
+ RNA_def_int(gzt->srna, "vert_index", -1, -1, INT_MAX, "Vert Index", "", -1, INT_MAX);
+ RNA_def_int(gzt->srna, "edge_index", -1, -1, INT_MAX, "Edge Index", "", -1, INT_MAX);
+ RNA_def_int(gzt->srna, "face_index", -1, -1, INT_MAX, "Face Index", "", -1, INT_MAX);
}
/** \} */
@@ -255,162 +253,155 @@ static void GIZMO_GT_mesh_preselect_elem_3d(wmGizmoType *gzt)
* \{ */
typedef struct MeshEdgeRingGizmo3D {
- wmGizmo gizmo;
- Base **bases;
- uint bases_len;
- int base_index;
- int edge_index;
- struct EditMesh_PreSelEdgeRing *psel;
+ wmGizmo gizmo;
+ Base **bases;
+ uint bases_len;
+ int base_index;
+ int edge_index;
+ struct EditMesh_PreSelEdgeRing *psel;
} MeshEdgeRingGizmo3D;
static void gizmo_preselect_edgering_draw(const bContext *UNUSED(C), wmGizmo *gz)
{
- MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz;
- if (gz_ring->base_index != -1) {
- Object *ob = gz_ring->bases[gz_ring->base_index]->object;
- EDBM_preselect_edgering_draw(gz_ring->psel, ob->obmat);
- }
+ MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz;
+ if (gz_ring->base_index != -1) {
+ Object *ob = gz_ring->bases[gz_ring->base_index]->object;
+ EDBM_preselect_edgering_draw(gz_ring->psel, ob->obmat);
+ }
}
-static int gizmo_preselect_edgering_test_select(
- bContext *C, wmGizmo *gz, const int mval[2])
+static int gizmo_preselect_edgering_test_select(bContext *C, wmGizmo *gz, const int mval[2])
{
- MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz;
- struct {
- Object *ob;
- BMEdge *eed;
- float dist;
- int base_index;
- } best = {
- .dist = ED_view3d_select_dist_px(),
- };
-
- struct {
- int base_index;
- int edge_index;
- } prev = {
- .base_index = gz_ring->base_index,
- .edge_index = gz_ring->edge_index,
- };
-
- {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- if (((gz_ring->bases)) == NULL ||
- (gz_ring->bases[0] != view_layer->basact))
- {
- MEM_SAFE_FREE(gz_ring->bases);
- gz_ring->bases = BKE_view_layer_array_from_bases_in_edit_mode(
- view_layer, v3d, &gz_ring->bases_len);
- }
- }
-
- ViewContext vc;
- em_setup_viewcontext(C, &vc);
- copy_v2_v2_int(vc.mval, mval);
-
- for (uint base_index = 0; base_index < gz_ring->bases_len; base_index++) {
- Object *ob_iter = gz_ring->bases[base_index]->object;
- ED_view3d_viewcontext_init_object(&vc, ob_iter);
- BMEdge *eed_test = EDBM_edge_find_nearest_ex(&vc, &best.dist, NULL, false, false, NULL);
- if (eed_test) {
- best.ob = ob_iter;
- best.eed = eed_test;
- best.base_index = base_index;
- }
- }
-
- BMesh *bm = NULL;
- if (best.eed) {
- gz_ring->base_index = best.base_index;
- bm = BKE_editmesh_from_object(gz_ring->bases[gz_ring->base_index]->object)->bm;
- BM_mesh_elem_index_ensure(bm, BM_EDGE);
- gz_ring->edge_index = BM_elem_index_get(best.eed);
- }
- else {
- gz_ring->base_index = -1;
- gz_ring->edge_index = -1;
- }
-
-
- if ((prev.base_index == gz_ring->base_index) &&
- (prev.edge_index == gz_ring->edge_index))
- {
- /* pass (only recalculate on change) */
- }
- else {
- if (best.eed) {
- const float (*coords)[3] = NULL;
- {
- Object *ob = gz_ring->bases[gz_ring->base_index]->object;
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data);
- if (me_eval->runtime.edit_data) {
- coords = me_eval->runtime.edit_data->vertexCos;
- }
- }
- EDBM_preselect_edgering_update_from_edge(gz_ring->psel, bm, best.eed, 1, coords);
- }
- else {
- EDBM_preselect_edgering_clear(gz_ring->psel);
- }
-
- 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);
- }
-
- // return best.eed ? 0 : -1;
- return -1;
+ MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz;
+ struct {
+ Object *ob;
+ BMEdge *eed;
+ float dist;
+ int base_index;
+ } best = {
+ .dist = ED_view3d_select_dist_px(),
+ };
+
+ struct {
+ int base_index;
+ int edge_index;
+ } prev = {
+ .base_index = gz_ring->base_index,
+ .edge_index = gz_ring->edge_index,
+ };
+
+ {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ if (((gz_ring->bases)) == NULL || (gz_ring->bases[0] != view_layer->basact)) {
+ MEM_SAFE_FREE(gz_ring->bases);
+ gz_ring->bases = BKE_view_layer_array_from_bases_in_edit_mode(
+ view_layer, v3d, &gz_ring->bases_len);
+ }
+ }
+
+ ViewContext vc;
+ em_setup_viewcontext(C, &vc);
+ copy_v2_v2_int(vc.mval, mval);
+
+ for (uint base_index = 0; base_index < gz_ring->bases_len; base_index++) {
+ Object *ob_iter = gz_ring->bases[base_index]->object;
+ ED_view3d_viewcontext_init_object(&vc, ob_iter);
+ BMEdge *eed_test = EDBM_edge_find_nearest_ex(&vc, &best.dist, NULL, false, false, NULL);
+ if (eed_test) {
+ best.ob = ob_iter;
+ best.eed = eed_test;
+ best.base_index = base_index;
+ }
+ }
+
+ BMesh *bm = NULL;
+ if (best.eed) {
+ gz_ring->base_index = best.base_index;
+ bm = BKE_editmesh_from_object(gz_ring->bases[gz_ring->base_index]->object)->bm;
+ BM_mesh_elem_index_ensure(bm, BM_EDGE);
+ gz_ring->edge_index = BM_elem_index_get(best.eed);
+ }
+ else {
+ gz_ring->base_index = -1;
+ gz_ring->edge_index = -1;
+ }
+
+ if ((prev.base_index == gz_ring->base_index) && (prev.edge_index == gz_ring->edge_index)) {
+ /* pass (only recalculate on change) */
+ }
+ else {
+ if (best.eed) {
+ const float(*coords)[3] = NULL;
+ {
+ Object *ob = gz_ring->bases[gz_ring->base_index]->object;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data);
+ if (me_eval->runtime.edit_data) {
+ coords = me_eval->runtime.edit_data->vertexCos;
+ }
+ }
+ EDBM_preselect_edgering_update_from_edge(gz_ring->psel, bm, best.eed, 1, coords);
+ }
+ else {
+ EDBM_preselect_edgering_clear(gz_ring->psel);
+ }
+
+ 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);
+ }
+
+ // return best.eed ? 0 : -1;
+ return -1;
}
static void gizmo_preselect_edgering_setup(wmGizmo *gz)
{
- MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz;
- if (gz_ring->psel == NULL) {
- gz_ring->psel = EDBM_preselect_edgering_create();
- }
- gz_ring->base_index = -1;
+ MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz;
+ if (gz_ring->psel == NULL) {
+ gz_ring->psel = EDBM_preselect_edgering_create();
+ }
+ gz_ring->base_index = -1;
}
static void gizmo_preselect_edgering_free(wmGizmo *gz)
{
- MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz;
- EDBM_preselect_edgering_destroy(gz_ring->psel);
- gz_ring->psel = NULL;
- MEM_SAFE_FREE(gz_ring->bases);
+ MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz;
+ EDBM_preselect_edgering_destroy(gz_ring->psel);
+ gz_ring->psel = NULL;
+ MEM_SAFE_FREE(gz_ring->bases);
}
-static int gizmo_preselect_edgering_invoke(
- bContext *UNUSED(C), wmGizmo *UNUSED(gz), const wmEvent *UNUSED(event))
+static int gizmo_preselect_edgering_invoke(bContext *UNUSED(C),
+ wmGizmo *UNUSED(gz),
+ const wmEvent *UNUSED(event))
{
- return OPERATOR_PASS_THROUGH;
+ return OPERATOR_PASS_THROUGH;
}
-
static void GIZMO_GT_mesh_preselect_edgering_3d(wmGizmoType *gzt)
{
- /* identifiers */
- gzt->idname = "GIZMO_GT_mesh_preselect_edgering_3d";
+ /* identifiers */
+ gzt->idname = "GIZMO_GT_mesh_preselect_edgering_3d";
- /* api callbacks */
- gzt->invoke = gizmo_preselect_edgering_invoke;
- gzt->draw = gizmo_preselect_edgering_draw;
- gzt->test_select = gizmo_preselect_edgering_test_select;
- gzt->setup = gizmo_preselect_edgering_setup;
- gzt->free = gizmo_preselect_edgering_free;
+ /* api callbacks */
+ gzt->invoke = gizmo_preselect_edgering_invoke;
+ gzt->draw = gizmo_preselect_edgering_draw;
+ gzt->test_select = gizmo_preselect_edgering_test_select;
+ gzt->setup = gizmo_preselect_edgering_setup;
+ gzt->free = gizmo_preselect_edgering_free;
- gzt->struct_size = sizeof(MeshEdgeRingGizmo3D);
+ gzt->struct_size = sizeof(MeshEdgeRingGizmo3D);
- RNA_def_int(gzt->srna, "object_index", -1, -1, INT_MAX, "Object Index", "", -1, INT_MAX);
- RNA_def_int(gzt->srna, "edge_index", -1, -1, INT_MAX, "Edge Index", "", -1, INT_MAX);
+ RNA_def_int(gzt->srna, "object_index", -1, -1, INT_MAX, "Object Index", "", -1, INT_MAX);
+ RNA_def_int(gzt->srna, "edge_index", -1, -1, INT_MAX, "Edge Index", "", -1, INT_MAX);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Gizmo API
*
@@ -418,13 +409,12 @@ static void GIZMO_GT_mesh_preselect_edgering_3d(wmGizmoType *gzt)
void ED_gizmotypes_preselect_3d(void)
{
- WM_gizmotype_append(GIZMO_GT_mesh_preselect_elem_3d);
- WM_gizmotype_append(GIZMO_GT_mesh_preselect_edgering_3d);
+ WM_gizmotype_append(GIZMO_GT_mesh_preselect_elem_3d);
+ WM_gizmotype_append(GIZMO_GT_mesh_preselect_edgering_3d);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Gizmo Accessors
*
@@ -432,53 +422,55 @@ void ED_gizmotypes_preselect_3d(void)
* the information from this gizmo.
* \{ */
-void ED_view3d_gizmo_mesh_preselect_get_active(
- bContext *C, wmGizmo *gz,
- Base **r_base, BMElem **r_ele)
+void ED_view3d_gizmo_mesh_preselect_get_active(bContext *C,
+ wmGizmo *gz,
+ Base **r_base,
+ BMElem **r_ele)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- const int object_index = RNA_int_get(gz->ptr, "object_index");
-
- /* weak, allocate an array just to access the index. */
- Base *base = NULL;
- Object *obedit = NULL;
- {
- uint bases_len;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(view_layer, CTX_wm_view3d(C), &bases_len);
- if (object_index < bases_len) {
- base = bases[object_index];
- obedit = base->object;
- }
- MEM_freeN(bases);
- }
-
- *r_base = base;
- *r_ele = NULL;
-
- if (obedit) {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- PropertyRNA *prop;
-
- /* Ring select only defines edge, check properties exist first. */
- prop = RNA_struct_find_property(gz->ptr, "vert_index");
- const int vert_index = prop ? RNA_property_int_get(gz->ptr, prop) : -1;
- prop = RNA_struct_find_property(gz->ptr, "edge_index");
- const int edge_index = prop ? RNA_property_int_get(gz->ptr, prop) : -1;
- prop = RNA_struct_find_property(gz->ptr, "face_index");
- const int face_index = prop ? RNA_property_int_get(gz->ptr, prop) : -1;
-
- if (vert_index != -1) {
- *r_ele = (BMElem *)BM_vert_at_index_find(bm, vert_index);
- }
- else if (edge_index != -1) {
- *r_ele = (BMElem *)BM_edge_at_index_find(bm, edge_index);
- }
- else if (face_index != -1) {
- *r_ele = (BMElem *)BM_face_at_index_find(bm, face_index);
- }
- }
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ const int object_index = RNA_int_get(gz->ptr, "object_index");
+
+ /* weak, allocate an array just to access the index. */
+ Base *base = NULL;
+ Object *obedit = NULL;
+ {
+ uint bases_len;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(
+ view_layer, CTX_wm_view3d(C), &bases_len);
+ if (object_index < bases_len) {
+ base = bases[object_index];
+ obedit = base->object;
+ }
+ MEM_freeN(bases);
+ }
+
+ *r_base = base;
+ *r_ele = NULL;
+
+ if (obedit) {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ PropertyRNA *prop;
+
+ /* Ring select only defines edge, check properties exist first. */
+ prop = RNA_struct_find_property(gz->ptr, "vert_index");
+ const int vert_index = prop ? RNA_property_int_get(gz->ptr, prop) : -1;
+ prop = RNA_struct_find_property(gz->ptr, "edge_index");
+ const int edge_index = prop ? RNA_property_int_get(gz->ptr, prop) : -1;
+ prop = RNA_struct_find_property(gz->ptr, "face_index");
+ const int face_index = prop ? RNA_property_int_get(gz->ptr, prop) : -1;
+
+ if (vert_index != -1) {
+ *r_ele = (BMElem *)BM_vert_at_index_find(bm, vert_index);
+ }
+ else if (edge_index != -1) {
+ *r_ele = (BMElem *)BM_edge_at_index_find(bm, edge_index);
+ }
+ else if (face_index != -1) {
+ *r_ele = (BMElem *)BM_face_at_index_find(bm, face_index);
+ }
+ }
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index 253e02ca639..566a15cc7b7 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -57,7 +57,7 @@
#include "WM_types.h"
#include "WM_toolsystem.h"
-#include "view3d_intern.h" /* own include */
+#include "view3d_intern.h" /* own include */
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
@@ -68,20 +68,18 @@
static const char *view3d_gzgt_ruler_id = "VIEW3D_GGT_ruler";
-
#define MVAL_MAX_PX_DIST 12.0f
/* -------------------------------------------------------------------- */
/* Ruler Item (we can have many) */
enum {
- /** Use protractor. */
- RULERITEM_USE_ANGLE = (1 << 0),
- /** Protractor vertex is selected (deleting removes it). */
- RULERITEM_USE_ANGLE_ACTIVE = (1 << 1),
+ /** Use protractor. */
+ RULERITEM_USE_ANGLE = (1 << 0),
+ /** Protractor vertex is selected (deleting removes it). */
+ RULERITEM_USE_ANGLE_ACTIVE = (1 << 1),
};
-
/* keep smaller then selection, since we may want click elsewhere without selecting a ruler */
#define RULER_PICK_DIST 12.0f
#define RULER_PICK_DIST_SQ (RULER_PICK_DIST * RULER_PICK_DIST)
@@ -93,47 +91,47 @@ enum {
/* Ruler Info (wmGizmoGroup customdata) */
enum {
- RULER_STATE_NORMAL = 0,
- RULER_STATE_DRAG,
+ RULER_STATE_NORMAL = 0,
+ RULER_STATE_DRAG,
};
enum {
- RULER_SNAP_OK = (1 << 0),
+ RULER_SNAP_OK = (1 << 0),
};
struct RulerItem;
typedef struct RulerInfo {
- struct RulerItem *item_active;
- int flag;
- int snap_flag;
- int state;
+ struct RulerItem *item_active;
+ int flag;
+ int snap_flag;
+ int state;
- struct SnapObjectContext *snap_context;
+ struct SnapObjectContext *snap_context;
- /* wm state */
- wmWindow *win;
- ScrArea *sa;
- ARegion *ar; /* re-assigned every modal update */
+ /* wm state */
+ wmWindow *win;
+ ScrArea *sa;
+ ARegion *ar; /* re-assigned every modal update */
} RulerInfo;
/* -------------------------------------------------------------------- */
/* Ruler Item (two or three points) */
typedef struct RulerItem {
- wmGizmo gz;
+ wmGizmo gz;
- /* worldspace coords, middle being optional */
- float co[3][3];
+ /* worldspace coords, middle being optional */
+ float co[3][3];
- int flag;
- int raycast_dir; /* RULER_DIRECTION_* */
+ int flag;
+ int raycast_dir; /* RULER_DIRECTION_* */
} RulerItem;
typedef struct RulerInteraction {
- /* selected coord */
- char co_index; /* 0 -> 2 */
- float drag_start_co[3];
+ /* selected coord */
+ char co_index; /* 0 -> 2 */
+ float drag_start_co[3];
} RulerInteraction;
/* -------------------------------------------------------------------- */
@@ -142,121 +140,123 @@ typedef struct RulerInteraction {
static RulerItem *ruler_item_add(wmGizmoGroup *gzgroup)
{
- /* could pass this as an arg */
- const wmGizmoType *gzt_ruler = WM_gizmotype_find("VIEW3D_GT_ruler_item", true);
- RulerItem *ruler_item = (RulerItem *)WM_gizmo_new_ptr(gzt_ruler, gzgroup, NULL);
- WM_gizmo_set_flag(&ruler_item->gz, WM_GIZMO_DRAW_MODAL, true);
- return ruler_item;
+ /* could pass this as an arg */
+ const wmGizmoType *gzt_ruler = WM_gizmotype_find("VIEW3D_GT_ruler_item", true);
+ RulerItem *ruler_item = (RulerItem *)WM_gizmo_new_ptr(gzt_ruler, gzgroup, NULL);
+ WM_gizmo_set_flag(&ruler_item->gz, WM_GIZMO_DRAW_MODAL, true);
+ return ruler_item;
}
static void ruler_item_remove(bContext *C, wmGizmoGroup *gzgroup, RulerItem *ruler_item)
{
- RulerInfo *ruler_info = gzgroup->customdata;
- if (ruler_info->item_active == ruler_item) {
- ruler_info->item_active = NULL;
- }
- WM_gizmo_unlink(&gzgroup->gizmos, gzgroup->parent_gzmap, &ruler_item->gz, C);
+ RulerInfo *ruler_info = gzgroup->customdata;
+ if (ruler_info->item_active == ruler_item) {
+ ruler_info->item_active = NULL;
+ }
+ WM_gizmo_unlink(&gzgroup->gizmos, gzgroup->parent_gzmap, &ruler_item->gz, C);
}
-static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit,
- char *numstr, size_t numstr_size, int prec)
+static void ruler_item_as_string(
+ RulerItem *ruler_item, UnitSettings *unit, char *numstr, size_t numstr_size, int prec)
{
- if (ruler_item->flag & RULERITEM_USE_ANGLE) {
- const float ruler_angle = angle_v3v3v3(ruler_item->co[0],
- ruler_item->co[1],
- ruler_item->co[2]);
-
- if (unit->system == USER_UNIT_NONE) {
- BLI_snprintf(numstr, numstr_size, "%.*f°", prec, RAD2DEGF(ruler_angle));
- }
- else {
- bUnit_AsString2(
- numstr, numstr_size, (double)ruler_angle,
- prec, B_UNIT_ROTATION, unit, false);
- }
- }
- else {
- const float ruler_len = len_v3v3(ruler_item->co[0],
- ruler_item->co[2]);
-
- if (unit->system == USER_UNIT_NONE) {
- BLI_snprintf(numstr, numstr_size, "%.*f", prec, ruler_len);
- }
- else {
- bUnit_AsString2(
- numstr, numstr_size, (double)(ruler_len * unit->scale_length),
- prec, B_UNIT_LENGTH, unit, false);
- }
- }
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ const float ruler_angle = angle_v3v3v3(
+ ruler_item->co[0], ruler_item->co[1], ruler_item->co[2]);
+
+ if (unit->system == USER_UNIT_NONE) {
+ BLI_snprintf(numstr, numstr_size, "%.*f°", prec, RAD2DEGF(ruler_angle));
+ }
+ else {
+ bUnit_AsString2(
+ numstr, numstr_size, (double)ruler_angle, prec, B_UNIT_ROTATION, unit, false);
+ }
+ }
+ else {
+ const float ruler_len = len_v3v3(ruler_item->co[0], ruler_item->co[2]);
+
+ if (unit->system == USER_UNIT_NONE) {
+ BLI_snprintf(numstr, numstr_size, "%.*f", prec, ruler_len);
+ }
+ else {
+ bUnit_AsString2(numstr,
+ numstr_size,
+ (double)(ruler_len * unit->scale_length),
+ prec,
+ B_UNIT_LENGTH,
+ unit,
+ false);
+ }
+ }
}
-static bool view3d_ruler_pick(
- wmGizmoGroup *gzgroup, RulerItem *ruler_item, const float mval[2],
- int *r_co_index)
+static bool view3d_ruler_pick(wmGizmoGroup *gzgroup,
+ RulerItem *ruler_item,
+ const float mval[2],
+ int *r_co_index)
{
- RulerInfo *ruler_info = gzgroup->customdata;
- ARegion *ar = ruler_info->ar;
- bool found = false;
-
- float dist_best = RULER_PICK_DIST_SQ;
- int co_index_best = -1;
-
- {
- float co_ss[3][2];
- float dist;
- int j;
-
- /* 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);
- }
-
- if (ruler_item->flag & RULERITEM_USE_ANGLE) {
- dist = min_ff(dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[1]),
- dist_squared_to_line_segment_v2(mval, co_ss[1], co_ss[2]));
- if (dist < dist_best) {
- dist_best = dist;
- found = true;
-
- {
- const float dist_points[3] = {
- len_squared_v2v2(co_ss[0], mval),
- len_squared_v2v2(co_ss[1], mval),
- len_squared_v2v2(co_ss[2], mval),
- };
- if (min_fff(UNPACK3(dist_points)) < RULER_PICK_DIST_SQ) {
- co_index_best = min_axis_v3(dist_points);
- }
- else {
- co_index_best = -1;
- }
- }
- }
- }
- else {
- dist = dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[2]);
- if (dist < dist_best) {
- dist_best = dist;
- found = true;
-
- {
- const float dist_points[2] = {
- len_squared_v2v2(co_ss[0], mval),
- len_squared_v2v2(co_ss[2], mval),
- };
- if (min_ff(UNPACK2(dist_points)) < RULER_PICK_DIST_SQ) {
- co_index_best = (dist_points[0] < dist_points[1]) ? 0 : 2;
- }
- else {
- co_index_best = -1;
- }
- }
- }
- }
- }
-
- *r_co_index = co_index_best;
- return found;
+ RulerInfo *ruler_info = gzgroup->customdata;
+ ARegion *ar = ruler_info->ar;
+ bool found = false;
+
+ float dist_best = RULER_PICK_DIST_SQ;
+ int co_index_best = -1;
+
+ {
+ float co_ss[3][2];
+ float dist;
+ int j;
+
+ /* 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);
+ }
+
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ dist = min_ff(dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[1]),
+ dist_squared_to_line_segment_v2(mval, co_ss[1], co_ss[2]));
+ if (dist < dist_best) {
+ dist_best = dist;
+ found = true;
+
+ {
+ const float dist_points[3] = {
+ len_squared_v2v2(co_ss[0], mval),
+ len_squared_v2v2(co_ss[1], mval),
+ len_squared_v2v2(co_ss[2], mval),
+ };
+ if (min_fff(UNPACK3(dist_points)) < RULER_PICK_DIST_SQ) {
+ co_index_best = min_axis_v3(dist_points);
+ }
+ else {
+ co_index_best = -1;
+ }
+ }
+ }
+ }
+ else {
+ dist = dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[2]);
+ if (dist < dist_best) {
+ dist_best = dist;
+ found = true;
+
+ {
+ const float dist_points[2] = {
+ len_squared_v2v2(co_ss[0], mval),
+ len_squared_v2v2(co_ss[2], mval),
+ };
+ if (min_ff(UNPACK2(dist_points)) < RULER_PICK_DIST_SQ) {
+ co_index_best = (dist_points[0] < dist_points[1]) ? 0 : 2;
+ }
+ else {
+ co_index_best = -1;
+ }
+ }
+ }
+ }
+ }
+
+ *r_co_index = co_index_best;
+ return found;
}
/**
@@ -265,113 +265,114 @@ static bool view3d_ruler_pick(
*/
static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
{
- Main *bmain = CTX_data_main(C);
- if (state == ruler_info->state) {
- return;
- }
-
- /* always remove */
- if (ruler_info->snap_context) {
- ED_transform_snap_object_context_destroy(ruler_info->snap_context);
- ruler_info->snap_context = NULL;
- }
-
- if (state == RULER_STATE_NORMAL) {
- /* pass */
- }
- else if (state == RULER_STATE_DRAG) {
- ruler_info->snap_context = ED_transform_snap_object_context_create_view3d(
- bmain, CTX_data_scene(C), CTX_data_depsgraph(C), 0,
- ruler_info->ar, CTX_wm_view3d(C));
- }
- else {
- BLI_assert(0);
- }
-
- ruler_info->state = state;
+ Main *bmain = CTX_data_main(C);
+ if (state == ruler_info->state) {
+ return;
+ }
+
+ /* always remove */
+ if (ruler_info->snap_context) {
+ ED_transform_snap_object_context_destroy(ruler_info->snap_context);
+ ruler_info->snap_context = NULL;
+ }
+
+ if (state == RULER_STATE_NORMAL) {
+ /* pass */
+ }
+ else if (state == RULER_STATE_DRAG) {
+ ruler_info->snap_context = ED_transform_snap_object_context_create_view3d(
+ bmain, CTX_data_scene(C), CTX_data_depsgraph(C), 0, ruler_info->ar, CTX_wm_view3d(C));
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ ruler_info->state = state;
}
-static void view3d_ruler_item_project(
- RulerInfo *ruler_info, float r_co[3],
- const int xy[2])
+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->sa->spacedata.first, ruler_info->ar, r_co, xy, r_co);
}
/* use for mousemove events */
-static bool view3d_ruler_item_mousemove(
- RulerInfo *ruler_info, RulerItem *ruler_item, const int mval[2],
- const bool do_thickness, const bool do_snap)
+static bool view3d_ruler_item_mousemove(RulerInfo *ruler_info,
+ RulerItem *ruler_item,
+ const int mval[2],
+ const bool do_thickness,
+ const bool do_snap)
{
- const float eps_bias = 0.0002f;
- float dist_px = MVAL_MAX_PX_DIST * U.pixelsize; /* snap dist */
-
- ruler_info->snap_flag &= ~RULER_SNAP_OK;
-
- if (ruler_item) {
- RulerInteraction *inter = ruler_item->gz.interaction_data;
- float *co = ruler_item->co[inter->co_index];
- /* restore the initial depth */
- copy_v3_v3(co, inter->drag_start_co);
- view3d_ruler_item_project(ruler_info, co, mval);
- if (do_thickness && inter->co_index != 1) {
- // Scene *scene = CTX_data_scene(C);
- // View3D *v3d = ruler_info->sa->spacedata.first;
- const float mval_fl[2] = {UNPACK2(mval)};
- float ray_normal[3];
- float ray_start[3];
- float *co_other;
-
- co_other = ruler_item->co[inter->co_index == 0 ? 2 : 0];
-
- if (ED_transform_snap_object_project_view3d(
- ruler_info->snap_context,
- SCE_SNAP_MODE_FACE,
- &(const struct SnapObjectParams){
- .snap_select = SNAP_ALL,
- .use_object_edit_cage = true,
- },
- mval_fl, &dist_px,
- co, ray_normal))
- {
- negate_v3(ray_normal);
- /* add some bias */
- madd_v3_v3v3fl(ray_start, co, ray_normal, eps_bias);
- ED_transform_snap_object_project_ray(
- ruler_info->snap_context,
- &(const struct SnapObjectParams){
- .snap_select = SNAP_ALL,
- .use_object_edit_cage = true,
- },
- ray_start, ray_normal, NULL,
- co_other, NULL);
- }
- }
- else if (do_snap) {
- const float mval_fl[2] = {UNPACK2(mval)};
-
- if (ED_transform_snap_object_project_view3d(
- ruler_info->snap_context,
- (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE),
- &(const struct SnapObjectParams){
- .snap_select = SNAP_ALL,
- .use_object_edit_cage = true,
- .use_occlusion_test = true,
- },
- mval_fl, &dist_px,
- co, NULL))
- {
- ruler_info->snap_flag |= RULER_SNAP_OK;
- }
- }
- return true;
- }
- else {
- return false;
- }
+ const float eps_bias = 0.0002f;
+ float dist_px = MVAL_MAX_PX_DIST * U.pixelsize; /* snap dist */
+
+ ruler_info->snap_flag &= ~RULER_SNAP_OK;
+
+ if (ruler_item) {
+ RulerInteraction *inter = ruler_item->gz.interaction_data;
+ float *co = ruler_item->co[inter->co_index];
+ /* restore the initial depth */
+ copy_v3_v3(co, inter->drag_start_co);
+ view3d_ruler_item_project(ruler_info, co, mval);
+ if (do_thickness && inter->co_index != 1) {
+ // Scene *scene = CTX_data_scene(C);
+ // View3D *v3d = ruler_info->sa->spacedata.first;
+ const float mval_fl[2] = {UNPACK2(mval)};
+ float ray_normal[3];
+ float ray_start[3];
+ float *co_other;
+
+ co_other = ruler_item->co[inter->co_index == 0 ? 2 : 0];
+
+ if (ED_transform_snap_object_project_view3d(ruler_info->snap_context,
+ SCE_SNAP_MODE_FACE,
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ .use_object_edit_cage = true,
+ },
+ mval_fl,
+ &dist_px,
+ co,
+ ray_normal)) {
+ negate_v3(ray_normal);
+ /* add some bias */
+ madd_v3_v3v3fl(ray_start, co, ray_normal, eps_bias);
+ ED_transform_snap_object_project_ray(ruler_info->snap_context,
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ .use_object_edit_cage = true,
+ },
+ ray_start,
+ ray_normal,
+ NULL,
+ co_other,
+ NULL);
+ }
+ }
+ else if (do_snap) {
+ const float mval_fl[2] = {UNPACK2(mval)};
+
+ if (ED_transform_snap_object_project_view3d(
+ ruler_info->snap_context,
+ (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE),
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ .use_object_edit_cage = true,
+ .use_occlusion_test = true,
+ },
+ mval_fl,
+ &dist_px,
+ co,
+ NULL)) {
+ ruler_info->snap_flag |= RULER_SNAP_OK;
+ }
+ }
+ return true;
+ }
+ else {
+ return false;
+ }
}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -381,114 +382,115 @@ static bool view3d_ruler_item_mousemove(
#define RULER_ID "RulerData3D"
static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *gzgroup)
{
- // RulerInfo *ruler_info = gzgroup->customdata;
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
-
- bGPdata *gpd;
- bGPDlayer *gpl;
- bGPDframe *gpf;
- bGPDstroke *gps;
- RulerItem *ruler_item;
- const char *ruler_name = RULER_ID;
- bool changed = false;
-
- if (scene->gpd == NULL) {
- scene->gpd = BKE_gpencil_data_addnew(bmain, "Annotations");
- }
- gpd = scene->gpd;
-
- gpl = BLI_findstring(&gpd->layers, ruler_name, offsetof(bGPDlayer, info));
- if (gpl == NULL) {
- gpl = BKE_gpencil_layer_addnew(gpd, ruler_name, false);
- copy_v4_v4(gpl->color, U.gpencil_new_layer_col);
- gpl->thickness = 1;
- gpl->flag |= GP_LAYER_HIDE;
- }
-
- gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_NEW);
- BKE_gpencil_free_strokes(gpf);
-
- for (ruler_item = gzgroup->gizmos.first; ruler_item; ruler_item = (RulerItem *)ruler_item->gz.next) {
- bGPDspoint *pt;
- int j;
-
- /* allocate memory for a new stroke */
- gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
- if (ruler_item->flag & RULERITEM_USE_ANGLE) {
- gps->totpoints = 3;
- pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
- for (j = 0; j < 3; j++) {
- copy_v3_v3(&pt->x, ruler_item->co[j]);
- pt->pressure = 1.0f;
- pt->strength = 1.0f;
- pt++;
- }
- }
- else {
- gps->totpoints = 2;
- pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
- for (j = 0; j < 3; j += 2) {
- copy_v3_v3(&pt->x, ruler_item->co[j]);
- pt->pressure = 1.0f;
- pt->strength = 1.0f;
- pt++;
- }
- }
- 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;
-
- BLI_addtail(&gpf->strokes, gps);
- changed = true;
- }
-
- return changed;
+ // RulerInfo *ruler_info = gzgroup->customdata;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+
+ bGPdata *gpd;
+ bGPDlayer *gpl;
+ bGPDframe *gpf;
+ bGPDstroke *gps;
+ RulerItem *ruler_item;
+ const char *ruler_name = RULER_ID;
+ bool changed = false;
+
+ if (scene->gpd == NULL) {
+ scene->gpd = BKE_gpencil_data_addnew(bmain, "Annotations");
+ }
+ gpd = scene->gpd;
+
+ gpl = BLI_findstring(&gpd->layers, ruler_name, offsetof(bGPDlayer, info));
+ if (gpl == NULL) {
+ gpl = BKE_gpencil_layer_addnew(gpd, ruler_name, false);
+ copy_v4_v4(gpl->color, U.gpencil_new_layer_col);
+ gpl->thickness = 1;
+ gpl->flag |= GP_LAYER_HIDE;
+ }
+
+ gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_NEW);
+ BKE_gpencil_free_strokes(gpf);
+
+ for (ruler_item = gzgroup->gizmos.first; ruler_item;
+ ruler_item = (RulerItem *)ruler_item->gz.next) {
+ bGPDspoint *pt;
+ int j;
+
+ /* allocate memory for a new stroke */
+ gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ gps->totpoints = 3;
+ pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ for (j = 0; j < 3; j++) {
+ copy_v3_v3(&pt->x, ruler_item->co[j]);
+ pt->pressure = 1.0f;
+ pt->strength = 1.0f;
+ pt++;
+ }
+ }
+ else {
+ gps->totpoints = 2;
+ pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ for (j = 0; j < 3; j += 2) {
+ copy_v3_v3(&pt->x, ruler_item->co[j]);
+ pt->pressure = 1.0f;
+ pt->strength = 1.0f;
+ pt++;
+ }
+ }
+ 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;
+
+ BLI_addtail(&gpf->strokes, gps);
+ changed = true;
+ }
+
+ return changed;
}
static bool view3d_ruler_from_gpencil(const bContext *C, wmGizmoGroup *gzgroup)
{
- Scene *scene = CTX_data_scene(C);
- bool changed = false;
-
- if (scene->gpd) {
- bGPDlayer *gpl;
- const char *ruler_name = RULER_ID;
- gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
- if (gpl) {
- bGPDframe *gpf;
- gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV);
- if (gpf) {
- bGPDstroke *gps;
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- bGPDspoint *pt = gps->points;
- int j;
- RulerItem *ruler_item = NULL;
- if (gps->totpoints == 3) {
- ruler_item = ruler_item_add(gzgroup);
- for (j = 0; j < 3; j++) {
- copy_v3_v3(ruler_item->co[j], &pt->x);
- pt++;
- }
- ruler_item->flag |= RULERITEM_USE_ANGLE;
- changed = true;
- }
- else if (gps->totpoints == 2) {
- ruler_item = ruler_item_add(gzgroup);
- for (j = 0; j < 3; j += 2) {
- copy_v3_v3(ruler_item->co[j], &pt->x);
- pt++;
- }
- changed = true;
- }
- }
- }
- }
- }
-
- return changed;
+ Scene *scene = CTX_data_scene(C);
+ bool changed = false;
+
+ if (scene->gpd) {
+ bGPDlayer *gpl;
+ const char *ruler_name = RULER_ID;
+ gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
+ if (gpl) {
+ bGPDframe *gpf;
+ gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV);
+ if (gpf) {
+ bGPDstroke *gps;
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ bGPDspoint *pt = gps->points;
+ int j;
+ RulerItem *ruler_item = NULL;
+ if (gps->totpoints == 3) {
+ ruler_item = ruler_item_add(gzgroup);
+ for (j = 0; j < 3; j++) {
+ copy_v3_v3(ruler_item->co[j], &pt->x);
+ pt++;
+ }
+ ruler_item->flag |= RULERITEM_USE_ANGLE;
+ changed = true;
+ }
+ else if (gps->totpoints == 2) {
+ ruler_item = ruler_item_add(gzgroup);
+ for (j = 0; j < 3; j += 2) {
+ copy_v3_v3(ruler_item->co[j], &pt->x);
+ pt++;
+ }
+ changed = true;
+ }
+ }
+ }
+ }
+ }
+
+ return changed;
}
/** \} */
@@ -499,488 +501,492 @@ static bool view3d_ruler_from_gpencil(const bContext *C, wmGizmoGroup *gzgroup)
static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
{
- Scene *scene = CTX_data_scene(C);
- 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;
- const float cap_size = 4.0f;
- const float bg_margin = 4.0f * U.pixelsize;
- const float arc_size = 64.0f * U.pixelsize;
+ Scene *scene = CTX_data_scene(C);
+ 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;
+ const float cap_size = 4.0f;
+ const float bg_margin = 4.0f * U.pixelsize;
+ const float arc_size = 64.0f * U.pixelsize;
#define ARC_STEPS 24
- const int arc_steps = ARC_STEPS;
- const float color_act[4] = {1.0f, 1.0f, 1.0f, 1.0f};
- const float color_base[4] = {0.0f, 0.0f, 0.0f, 1.0f};
- uchar color_text[3];
- uchar color_wire[3];
- float color_back[4] = {1.0f, 1.0f, 1.0f, 0.5f};
-
- /* anti-aliased lines for more consistent appearance */
- GPU_line_smooth(true);
- GPU_line_width(1.0f);
-
- BLF_enable(blf_mono_font, BLF_ROTATION);
- BLF_size(blf_mono_font, 14 * U.pixelsize, U.dpi);
- BLF_rotation(blf_mono_font, 0.0f);
-
- UI_GetThemeColor3ubv(TH_TEXT, color_text);
- UI_GetThemeColor3ubv(TH_WIRE, color_wire);
-
- /* Avoid white on white text. (TODO Fix by using theme) */
- if ((int)color_text[0] + (int)color_text[1] + (int)color_text[2] > 127 * 3 * 0.6f) {
- copy_v3_fl(color_back, 0.0f);
- }
-
- const bool is_act = (ruler_info->item_active == ruler_item);
- float dir_ruler[2];
- float co_ss[3][2];
- int j;
-
- /* 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);
- }
-
- GPU_blend(true);
-
- const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- if (ruler_item->flag & RULERITEM_USE_ANGLE) {
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
-
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
-
- immUniform1i("colors_len", 2); /* "advanced" mode */
- const float *col = is_act ? color_act : color_base;
- immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2);
- immUniform1f("dash_width", 6.0f);
-
- immBegin(GPU_PRIM_LINE_STRIP, 3);
-
- immVertex2fv(shdr_pos, co_ss[0]);
- immVertex2fv(shdr_pos, co_ss[1]);
- immVertex2fv(shdr_pos, co_ss[2]);
-
- immEnd();
-
- immUnbindProgram();
+ const int arc_steps = ARC_STEPS;
+ const float color_act[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ const float color_base[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ uchar color_text[3];
+ uchar color_wire[3];
+ float color_back[4] = {1.0f, 1.0f, 1.0f, 0.5f};
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ /* anti-aliased lines for more consistent appearance */
+ GPU_line_smooth(true);
+ GPU_line_width(1.0f);
- /* arc */
- {
- float dir_tmp[3];
- float co_tmp[3];
- float arc_ss_coord[2];
+ BLF_enable(blf_mono_font, BLF_ROTATION);
+ BLF_size(blf_mono_font, 14 * U.pixelsize, U.dpi);
+ BLF_rotation(blf_mono_font, 0.0f);
- float dir_a[3];
- float dir_b[3];
- float quat[4];
- float axis[3];
- float angle;
- const float px_scale = (ED_view3d_pixel_size_no_ui_scale(rv3d, ruler_item->co[1]) *
- min_fff(arc_size,
- len_v2v2(co_ss[0], co_ss[1]) / 2.0f,
- len_v2v2(co_ss[2], co_ss[1]) / 2.0f));
+ UI_GetThemeColor3ubv(TH_TEXT, color_text);
+ UI_GetThemeColor3ubv(TH_WIRE, color_wire);
- sub_v3_v3v3(dir_a, ruler_item->co[0], ruler_item->co[1]);
- sub_v3_v3v3(dir_b, ruler_item->co[2], ruler_item->co[1]);
- normalize_v3(dir_a);
- normalize_v3(dir_b);
+ /* Avoid white on white text. (TODO Fix by using theme) */
+ if ((int)color_text[0] + (int)color_text[1] + (int)color_text[2] > 127 * 3 * 0.6f) {
+ copy_v3_fl(color_back, 0.0f);
+ }
- cross_v3_v3v3(axis, dir_a, dir_b);
- angle = angle_normalized_v3v3(dir_a, dir_b);
+ const bool is_act = (ruler_info->item_active == ruler_item);
+ float dir_ruler[2];
+ float co_ss[3][2];
+ int j;
- axis_angle_to_quat(quat, axis, angle / arc_steps);
+ /* 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);
+ }
+
+ GPU_blend(true);
+
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
- copy_v3_v3(dir_tmp, dir_a);
+ immUniform1i("colors_len", 2); /* "advanced" mode */
+ const float *col = is_act ? color_act : color_base;
+ immUniformArray4fv(
+ "colors",
+ (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}},
+ 2);
+ immUniform1f("dash_width", 6.0f);
+
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
- immUniformColor3ubv(color_wire);
+ immVertex2fv(shdr_pos, co_ss[0]);
+ immVertex2fv(shdr_pos, co_ss[1]);
+ immVertex2fv(shdr_pos, co_ss[2]);
+
+ immEnd();
+
+ immUnbindProgram();
- immBegin(GPU_PRIM_LINE_STRIP, arc_steps + 1);
-
- for (j = 0; j <= arc_steps; j++) {
- madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale);
- ED_view3d_project_float_global(ar, co_tmp, arc_ss_coord, V3D_PROJ_TEST_NOP);
- mul_qt_v3(quat, dir_tmp);
-
- immVertex2fv(shdr_pos, arc_ss_coord);
- }
-
- immEnd();
- }
-
- /* capping */
- {
- float rot_90_vec_a[2];
- float rot_90_vec_b[2];
- float cap[2];
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[1]);
- rot_90_vec_a[0] = -dir_ruler[1];
- rot_90_vec_a[1] = dir_ruler[0];
- normalize_v2(rot_90_vec_a);
+ /* arc */
+ {
+ float dir_tmp[3];
+ float co_tmp[3];
+ float arc_ss_coord[2];
- sub_v2_v2v2(dir_ruler, co_ss[1], co_ss[2]);
- rot_90_vec_b[0] = -dir_ruler[1];
- rot_90_vec_b[1] = dir_ruler[0];
- normalize_v2(rot_90_vec_b);
+ float dir_a[3];
+ float dir_b[3];
+ float quat[4];
+ float axis[3];
+ float angle;
+ const float px_scale = (ED_view3d_pixel_size_no_ui_scale(rv3d, ruler_item->co[1]) *
+ min_fff(arc_size,
+ len_v2v2(co_ss[0], co_ss[1]) / 2.0f,
+ len_v2v2(co_ss[2], co_ss[1]) / 2.0f));
- GPU_blend(true);
+ sub_v3_v3v3(dir_a, ruler_item->co[0], ruler_item->co[1]);
+ sub_v3_v3v3(dir_b, ruler_item->co[2], ruler_item->co[1]);
+ normalize_v3(dir_a);
+ normalize_v3(dir_b);
+
+ cross_v3_v3v3(axis, dir_a, dir_b);
+ angle = angle_normalized_v3v3(dir_a, dir_b);
+
+ axis_angle_to_quat(quat, axis, angle / arc_steps);
+
+ copy_v3_v3(dir_tmp, dir_a);
+
+ immUniformColor3ubv(color_wire);
+
+ immBegin(GPU_PRIM_LINE_STRIP, arc_steps + 1);
+
+ for (j = 0; j <= arc_steps; j++) {
+ madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale);
+ ED_view3d_project_float_global(ar, co_tmp, arc_ss_coord, V3D_PROJ_TEST_NOP);
+ mul_qt_v3(quat, dir_tmp);
+
+ immVertex2fv(shdr_pos, arc_ss_coord);
+ }
+
+ immEnd();
+ }
+
+ /* capping */
+ {
+ float rot_90_vec_a[2];
+ float rot_90_vec_b[2];
+ float cap[2];
+
+ sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[1]);
+ rot_90_vec_a[0] = -dir_ruler[1];
+ rot_90_vec_a[1] = dir_ruler[0];
+ normalize_v2(rot_90_vec_a);
+
+ sub_v2_v2v2(dir_ruler, co_ss[1], co_ss[2]);
+ rot_90_vec_b[0] = -dir_ruler[1];
+ rot_90_vec_b[1] = dir_ruler[0];
+ normalize_v2(rot_90_vec_b);
+
+ GPU_blend(true);
- if (is_act && (ruler_item->flag & RULERITEM_USE_ANGLE_ACTIVE)) {
- GPU_line_width(3.0f);
- immUniformColor3fv(color_act);
- immBegin(GPU_PRIM_LINES, 4);
- /* angle vertex */
- immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
- immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
- immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
- immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
+ if (is_act && (ruler_item->flag & RULERITEM_USE_ANGLE_ACTIVE)) {
+ GPU_line_width(3.0f);
+ immUniformColor3fv(color_act);
+ immBegin(GPU_PRIM_LINES, 4);
+ /* angle vertex */
+ immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
+ immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
+ immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
+ immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
- immEnd();
- GPU_line_width(1.0f);
- }
+ immEnd();
+ GPU_line_width(1.0f);
+ }
- immUniformColor3ubv(color_wire);
+ immUniformColor3ubv(color_wire);
- immBegin(GPU_PRIM_LINES, 8);
+ immBegin(GPU_PRIM_LINES, 8);
- madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size);
- immVertex2fv(shdr_pos, cap);
- madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size);
- immVertex2fv(shdr_pos, cap);
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size);
+ immVertex2fv(shdr_pos, cap);
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size);
+ immVertex2fv(shdr_pos, cap);
- madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size);
- immVertex2fv(shdr_pos, cap);
- madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size);
- immVertex2fv(shdr_pos, cap);
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size);
+ immVertex2fv(shdr_pos, cap);
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size);
+ immVertex2fv(shdr_pos, cap);
- /* angle vertex */
- immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
- immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
- immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
- immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
+ /* angle vertex */
+ immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
+ immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
+ immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
+ immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
- immEnd();
+ immEnd();
- GPU_blend(false);
- }
+ GPU_blend(false);
+ }
- /* text */
- char numstr[256];
- float numstr_size[2];
- float posit[2];
- const int prec = 2; /* XXX, todo, make optional */
+ /* text */
+ char numstr[256];
+ float numstr_size[2];
+ float posit[2];
+ const int prec = 2; /* XXX, todo, make optional */
- ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
+ ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
- BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]);
+ BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]);
- posit[0] = co_ss[1][0] + (cap_size * 2.0f);
- posit[1] = co_ss[1][1] - (numstr_size[1] / 2.0f);
+ posit[0] = co_ss[1][0] + (cap_size * 2.0f);
+ posit[1] = co_ss[1][1] - (numstr_size[1] / 2.0f);
- /* draw text (bg) */
- {
- immUniformColor4fv(color_back);
- GPU_blend(true);
- immRectf(shdr_pos,
- posit[0] - bg_margin, posit[1] - bg_margin,
- posit[0] + bg_margin + numstr_size[0], posit[1] + bg_margin + numstr_size[1]);
- GPU_blend(false);
- }
+ /* draw text (bg) */
+ {
+ immUniformColor4fv(color_back);
+ GPU_blend(true);
+ immRectf(shdr_pos,
+ posit[0] - bg_margin,
+ posit[1] - bg_margin,
+ posit[0] + bg_margin + numstr_size[0],
+ posit[1] + bg_margin + numstr_size[1]);
+ GPU_blend(false);
+ }
- immUnbindProgram();
+ immUnbindProgram();
- /* draw text */
- {
- BLF_color3ubv(blf_mono_font, color_text);
- BLF_position(blf_mono_font, posit[0], posit[1], 0.0f);
- BLF_rotation(blf_mono_font, 0.0f);
- BLF_draw(blf_mono_font, numstr, sizeof(numstr));
- }
- }
- else {
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ /* draw text */
+ {
+ BLF_color3ubv(blf_mono_font, color_text);
+ BLF_position(blf_mono_font, posit[0], posit[1], 0.0f);
+ BLF_rotation(blf_mono_font, 0.0f);
+ BLF_draw(blf_mono_font, numstr, sizeof(numstr));
+ }
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
- immUniform1i("colors_len", 2); /* "advanced" mode */
- const float *col = is_act ? color_act : color_base;
- immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2);
- immUniform1f("dash_width", 6.0f);
+ immUniform1i("colors_len", 2); /* "advanced" mode */
+ const float *col = is_act ? color_act : color_base;
+ immUniformArray4fv(
+ "colors",
+ (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}},
+ 2);
+ immUniform1f("dash_width", 6.0f);
- immBegin(GPU_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
- immVertex2fv(shdr_pos, co_ss[0]);
- immVertex2fv(shdr_pos, co_ss[2]);
+ immVertex2fv(shdr_pos, co_ss[0]);
+ immVertex2fv(shdr_pos, co_ss[2]);
- immEnd();
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]);
+ sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]);
- /* capping */
- {
- float rot_90_vec[2] = {-dir_ruler[1], dir_ruler[0]};
- float cap[2];
+ /* capping */
+ {
+ float rot_90_vec[2] = {-dir_ruler[1], dir_ruler[0]};
+ float cap[2];
- normalize_v2(rot_90_vec);
+ normalize_v2(rot_90_vec);
- GPU_blend(true);
+ GPU_blend(true);
- immUniformColor3ubv(color_wire);
+ immUniformColor3ubv(color_wire);
- immBegin(GPU_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
- madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size);
- immVertex2fv(shdr_pos, cap);
- madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size);
- immVertex2fv(shdr_pos, cap);
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size);
+ immVertex2fv(shdr_pos, cap);
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size);
+ immVertex2fv(shdr_pos, cap);
- madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size);
- immVertex2fv(shdr_pos, cap);
- madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size);
- immVertex2fv(shdr_pos, cap);
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size);
+ immVertex2fv(shdr_pos, cap);
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size);
+ immVertex2fv(shdr_pos, cap);
- immEnd();
+ immEnd();
- GPU_blend(false);
- }
+ GPU_blend(false);
+ }
- /* text */
- char numstr[256];
- float numstr_size[2];
- const int prec = 6; /* XXX, todo, make optional */
- float posit[2];
+ /* text */
+ char numstr[256];
+ float numstr_size[2];
+ const int prec = 6; /* XXX, todo, make optional */
+ float posit[2];
- ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
+ ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
- BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]);
+ BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]);
- mid_v2_v2v2(posit, co_ss[0], co_ss[2]);
+ mid_v2_v2v2(posit, co_ss[0], co_ss[2]);
- /* center text */
- posit[0] -= numstr_size[0] / 2.0f;
- posit[1] -= numstr_size[1] / 2.0f;
+ /* center text */
+ posit[0] -= numstr_size[0] / 2.0f;
+ posit[1] -= numstr_size[1] / 2.0f;
- /* draw text (bg) */
- {
- immUniformColor4fv(color_back);
- GPU_blend(true);
- immRectf(shdr_pos,
- posit[0] - bg_margin, posit[1] - bg_margin,
- posit[0] + bg_margin + numstr_size[0], posit[1] + bg_margin + numstr_size[1]);
- GPU_blend(false);
- }
+ /* draw text (bg) */
+ {
+ immUniformColor4fv(color_back);
+ GPU_blend(true);
+ immRectf(shdr_pos,
+ posit[0] - bg_margin,
+ posit[1] - bg_margin,
+ posit[0] + bg_margin + numstr_size[0],
+ posit[1] + bg_margin + numstr_size[1]);
+ GPU_blend(false);
+ }
- immUnbindProgram();
+ immUnbindProgram();
- /* draw text */
- {
- BLF_color3ubv(blf_mono_font, color_text);
- BLF_position(blf_mono_font, posit[0], posit[1], 0.0f);
- BLF_draw(blf_mono_font, numstr, sizeof(numstr));
- }
- }
+ /* draw text */
+ {
+ BLF_color3ubv(blf_mono_font, color_text);
+ BLF_position(blf_mono_font, posit[0], posit[1], 0.0f);
+ BLF_draw(blf_mono_font, numstr, sizeof(numstr));
+ }
+ }
- GPU_line_smooth(false);
+ GPU_line_smooth(false);
- BLF_disable(blf_mono_font, BLF_ROTATION);
+ BLF_disable(blf_mono_font, BLF_ROTATION);
#undef ARC_STEPS
- /* draw snap */
- if ((ruler_info->snap_flag & RULER_SNAP_OK) &&
- (ruler_info->state == RULER_STATE_DRAG) &&
- (ruler_item->gz.interaction_data != NULL))
- {
- RulerInteraction *inter = ruler_item->gz.interaction_data;
- /* size from drawSnapping */
- const float size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
- float co_ss_snap[3];
- ED_view3d_project_float_global(ar, ruler_item->co[inter->co_index], co_ss_snap, V3D_PROJ_TEST_NOP);
+ /* draw snap */
+ if ((ruler_info->snap_flag & RULER_SNAP_OK) && (ruler_info->state == RULER_STATE_DRAG) &&
+ (ruler_item->gz.interaction_data != NULL)) {
+ RulerInteraction *inter = ruler_item->gz.interaction_data;
+ /* size from drawSnapping */
+ const float size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
+ float co_ss_snap[3];
+ ED_view3d_project_float_global(
+ ar, 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);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4fv(color_act);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(color_act);
- imm_draw_circle_wire_2d(pos, co_ss_snap[0], co_ss_snap[1], size * U.pixelsize, 32);
+ imm_draw_circle_wire_2d(pos, co_ss_snap[0], co_ss_snap[1], size * U.pixelsize, 32);
- immUnbindProgram();
- }
+ immUnbindProgram();
+ }
}
-static int gizmo_ruler_test_select(
- bContext *UNUSED(C), wmGizmo *gz, const int mval[2])
+static int gizmo_ruler_test_select(bContext *UNUSED(C), wmGizmo *gz, const int mval[2])
{
- RulerItem *ruler_item_pick = (RulerItem *)gz;
- float mval_fl[2] = {UNPACK2(mval)};
- int co_index;
-
- /* select and drag */
- if (view3d_ruler_pick(gz->parent_gzgroup, ruler_item_pick, mval_fl, &co_index)) {
- if (co_index == -1) {
- if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) {
- return PART_LINE;
- }
- }
- else {
- return co_index;
- }
- }
- return -1;
+ RulerItem *ruler_item_pick = (RulerItem *)gz;
+ float mval_fl[2] = {UNPACK2(mval)};
+ int co_index;
+
+ /* select and drag */
+ if (view3d_ruler_pick(gz->parent_gzgroup, ruler_item_pick, mval_fl, &co_index)) {
+ if (co_index == -1) {
+ if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) {
+ return PART_LINE;
+ }
+ }
+ else {
+ return co_index;
+ }
+ }
+ return -1;
}
-static int gizmo_ruler_modal(
- bContext *C, wmGizmo *gz, const wmEvent *event,
- eWM_GizmoFlagTweak UNUSED(tweak_flag))
+static int gizmo_ruler_modal(bContext *C,
+ wmGizmo *gz,
+ const wmEvent *event,
+ eWM_GizmoFlagTweak UNUSED(tweak_flag))
{
- bool do_draw = false;
- int exit_code = OPERATOR_RUNNING_MODAL;
- RulerInfo *ruler_info = gz->parent_gzgroup->customdata;
- RulerItem *ruler_item = (RulerItem *)gz;
- ARegion *ar = CTX_wm_region(C);
-
- ruler_info->ar = ar;
-
- switch (event->type) {
- case MOUSEMOVE:
- {
- if (ruler_info->state == RULER_STATE_DRAG) {
- if (view3d_ruler_item_mousemove(
- ruler_info, ruler_item, event->mval,
- event->shift != 0, event->ctrl != 0))
- {
- do_draw = true;
- }
- }
- break;
- }
- }
- if (do_draw) {
- ED_region_tag_redraw(ar);
- }
- return exit_code;
+ bool do_draw = false;
+ int exit_code = OPERATOR_RUNNING_MODAL;
+ RulerInfo *ruler_info = gz->parent_gzgroup->customdata;
+ RulerItem *ruler_item = (RulerItem *)gz;
+ ARegion *ar = CTX_wm_region(C);
+
+ ruler_info->ar = ar;
+
+ switch (event->type) {
+ case MOUSEMOVE: {
+ if (ruler_info->state == RULER_STATE_DRAG) {
+ if (view3d_ruler_item_mousemove(
+ ruler_info, ruler_item, event->mval, event->shift != 0, event->ctrl != 0)) {
+ do_draw = true;
+ }
+ }
+ break;
+ }
+ }
+ if (do_draw) {
+ ED_region_tag_redraw(ar);
+ }
+ return exit_code;
}
-static int gizmo_ruler_invoke(
- bContext *C, wmGizmo *gz, const wmEvent *event)
+static int gizmo_ruler_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
{
- wmGizmoGroup *gzgroup = gz->parent_gzgroup;
- RulerInfo *ruler_info = gzgroup->customdata;
- RulerItem *ruler_item_pick = (RulerItem *)gz;
- RulerInteraction *inter = MEM_callocN(sizeof(RulerInteraction), __func__);
- gz->interaction_data = inter;
-
- ARegion *ar = ruler_info->ar;
-
- const float mval_fl[2] = {UNPACK2(event->mval)};
-
- /* select and drag */
- if (gz->highlight_part == PART_LINE) {
- if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) {
- /* Add Center Point */
- ruler_item_pick->flag |= RULERITEM_USE_ANGLE;
- inter->co_index = 1;
- ruler_state_set(C, ruler_info, RULER_STATE_DRAG);
-
- /* find the factor */
- {
- 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);
-
- fac = line_point_factor_v2(mval_fl, co_ss[0], co_ss[1]);
- CLAMP(fac, 0.0f, 1.0f);
-
- interp_v3_v3v3(ruler_item_pick->co[1],
- ruler_item_pick->co[0],
- ruler_item_pick->co[2], fac);
- }
-
- /* update the new location */
- view3d_ruler_item_mousemove(
- ruler_info, ruler_item_pick, event->mval,
- event->shift != 0, event->ctrl != 0);
- }
- }
- else {
- inter->co_index = gz->highlight_part;
- ruler_state_set(C, ruler_info, RULER_STATE_DRAG);
-
- /* store the initial depth */
- copy_v3_v3(inter->drag_start_co, ruler_item_pick->co[inter->co_index]);
- }
-
- if (inter->co_index == 1) {
- ruler_item_pick->flag |= RULERITEM_USE_ANGLE_ACTIVE;
- }
- else {
- ruler_item_pick->flag &= ~RULERITEM_USE_ANGLE_ACTIVE;
- }
-
- ruler_info->item_active = ruler_item_pick;
-
- return OPERATOR_RUNNING_MODAL;
+ wmGizmoGroup *gzgroup = gz->parent_gzgroup;
+ RulerInfo *ruler_info = gzgroup->customdata;
+ RulerItem *ruler_item_pick = (RulerItem *)gz;
+ RulerInteraction *inter = MEM_callocN(sizeof(RulerInteraction), __func__);
+ gz->interaction_data = inter;
+
+ ARegion *ar = ruler_info->ar;
+
+ const float mval_fl[2] = {UNPACK2(event->mval)};
+
+ /* select and drag */
+ if (gz->highlight_part == PART_LINE) {
+ if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) {
+ /* Add Center Point */
+ ruler_item_pick->flag |= RULERITEM_USE_ANGLE;
+ inter->co_index = 1;
+ ruler_state_set(C, ruler_info, RULER_STATE_DRAG);
+
+ /* find the factor */
+ {
+ 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);
+
+ fac = line_point_factor_v2(mval_fl, co_ss[0], co_ss[1]);
+ CLAMP(fac, 0.0f, 1.0f);
+
+ interp_v3_v3v3(
+ ruler_item_pick->co[1], ruler_item_pick->co[0], ruler_item_pick->co[2], fac);
+ }
+
+ /* update the new location */
+ view3d_ruler_item_mousemove(
+ ruler_info, ruler_item_pick, event->mval, event->shift != 0, event->ctrl != 0);
+ }
+ }
+ else {
+ inter->co_index = gz->highlight_part;
+ ruler_state_set(C, ruler_info, RULER_STATE_DRAG);
+
+ /* store the initial depth */
+ copy_v3_v3(inter->drag_start_co, ruler_item_pick->co[inter->co_index]);
+ }
+
+ if (inter->co_index == 1) {
+ ruler_item_pick->flag |= RULERITEM_USE_ANGLE_ACTIVE;
+ }
+ else {
+ ruler_item_pick->flag &= ~RULERITEM_USE_ANGLE_ACTIVE;
+ }
+
+ ruler_info->item_active = ruler_item_pick;
+
+ return OPERATOR_RUNNING_MODAL;
}
static void gizmo_ruler_exit(bContext *C, wmGizmo *gz, const bool cancel)
{
- wmGizmoGroup *gzgroup = gz->parent_gzgroup;
- RulerInfo *ruler_info = gzgroup->customdata;
-
- if (!cancel) {
- if (ruler_info->state == RULER_STATE_DRAG) {
- if (ruler_info->snap_flag & RULER_SNAP_OK) {
- ruler_info->snap_flag &= ~RULER_SNAP_OK;
- }
- ruler_state_set(C, ruler_info, RULER_STATE_NORMAL);
- }
- /* We could convert only the current gizmo, for now just re-generate. */
- view3d_ruler_to_gpencil(C, gzgroup);
- }
-
- if (gz) {
- MEM_SAFE_FREE(gz->interaction_data);
- }
-
- ruler_state_set(C, ruler_info, RULER_STATE_NORMAL);
+ wmGizmoGroup *gzgroup = gz->parent_gzgroup;
+ RulerInfo *ruler_info = gzgroup->customdata;
+
+ if (!cancel) {
+ if (ruler_info->state == RULER_STATE_DRAG) {
+ if (ruler_info->snap_flag & RULER_SNAP_OK) {
+ ruler_info->snap_flag &= ~RULER_SNAP_OK;
+ }
+ ruler_state_set(C, ruler_info, RULER_STATE_NORMAL);
+ }
+ /* We could convert only the current gizmo, for now just re-generate. */
+ view3d_ruler_to_gpencil(C, gzgroup);
+ }
+
+ if (gz) {
+ MEM_SAFE_FREE(gz->interaction_data);
+ }
+
+ ruler_state_set(C, ruler_info, RULER_STATE_NORMAL);
}
static int gizmo_ruler_cursor_get(wmGizmo *gz)
{
- if (gz->highlight_part == PART_LINE) {
- return BC_CROSSCURSOR;
- }
- return BC_NSEW_SCROLLCURSOR;
+ if (gz->highlight_part == PART_LINE) {
+ return BC_CROSSCURSOR;
+ }
+ return BC_NSEW_SCROLLCURSOR;
}
void VIEW3D_GT_ruler_item(wmGizmoType *gzt)
{
- /* identifiers */
- gzt->idname = "VIEW3D_GT_ruler_item";
-
- /* api callbacks */
- gzt->draw = gizmo_ruler_draw;
- gzt->test_select = gizmo_ruler_test_select;
- gzt->modal = gizmo_ruler_modal;
- gzt->invoke = gizmo_ruler_invoke;
- gzt->exit = gizmo_ruler_exit;
- gzt->cursor_get = gizmo_ruler_cursor_get;
-
- gzt->struct_size = sizeof(RulerItem);
+ /* identifiers */
+ gzt->idname = "VIEW3D_GT_ruler_item";
+
+ /* api callbacks */
+ gzt->draw = gizmo_ruler_draw;
+ gzt->test_select = gizmo_ruler_test_select;
+ gzt->modal = gizmo_ruler_modal;
+ gzt->invoke = gizmo_ruler_invoke;
+ gzt->exit = gizmo_ruler_exit;
+ gzt->cursor_get = gizmo_ruler_cursor_get;
+
+ gzt->struct_size = sizeof(RulerItem);
}
/** \} */
@@ -991,34 +997,34 @@ void VIEW3D_GT_ruler_item(wmGizmoType *gzt)
static void WIDGETGROUP_ruler_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
- RulerInfo *ruler_info = MEM_callocN(sizeof(RulerInfo), __func__);
+ RulerInfo *ruler_info = MEM_callocN(sizeof(RulerInfo), __func__);
- if (view3d_ruler_from_gpencil(C, gzgroup)) {
- /* nop */
- }
+ if (view3d_ruler_from_gpencil(C, gzgroup)) {
+ /* nop */
+ }
- wmWindow *win = CTX_wm_window(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- ruler_info->win = win;
- ruler_info->sa = sa;
- ruler_info->ar = ar;
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ ruler_info->win = win;
+ ruler_info->sa = sa;
+ ruler_info->ar = ar;
- gzgroup->customdata = ruler_info;
+ gzgroup->customdata = ruler_info;
}
void VIEW3D_GGT_ruler(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Ruler Widgets";
- gzgt->idname = view3d_gzgt_ruler_id;
+ gzgt->name = "Ruler Widgets";
+ gzgt->idname = view3d_gzgt_ruler_id;
- gzgt->flag |= WM_GIZMOGROUPTYPE_SCALE | WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_SCALE | WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL;
- gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
- gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool;
- gzgt->setup = WIDGETGROUP_ruler_setup;
+ gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool;
+ gzgt->setup = WIDGETGROUP_ruler_setup;
}
/** \} */
@@ -1029,72 +1035,68 @@ void VIEW3D_GGT_ruler(wmGizmoGroupType *gzgt)
static bool view3d_ruler_poll(bContext *C)
{
- bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
- if ((tref_rt == NULL) ||
- !STREQ(view3d_gzgt_ruler_id, tref_rt->gizmo_group) ||
- CTX_wm_region_view3d(C) == NULL)
- {
- return false;
- }
- return true;
+ bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
+ if ((tref_rt == NULL) || !STREQ(view3d_gzgt_ruler_id, tref_rt->gizmo_group) ||
+ CTX_wm_region_view3d(C) == NULL) {
+ return false;
+ }
+ return true;
}
static int view3d_ruler_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = ar->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;
- wmGizmoGroup *gzgroup = WM_gizmomap_group_find(gzmap, view3d_gzgt_ruler_id);
- const bool use_depth = (v3d->shading.type >= OB_SOLID);
-
- /* Create new line */
- RulerItem *ruler_item;
- ruler_item = ruler_item_add(gzgroup);
-
- /* This is a little weak, but there is no real good way to tweak directly. */
- WM_gizmo_highlight_set(gzmap, &ruler_item->gz);
- if (WM_operator_name_call(
- C, "GIZMOGROUP_OT_gizmo_tweak",
- WM_OP_INVOKE_REGION_WIN, NULL) == OPERATOR_RUNNING_MODAL)
- {
- RulerInfo *ruler_info = gzgroup->customdata;
- RulerInteraction *inter = ruler_item->gz.interaction_data;
- if (use_depth) {
- /* 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);
- copy_v3_v3(inter->drag_start_co, ruler_item->co[inter->co_index]);
- }
- else {
- negate_v3_v3(inter->drag_start_co, rv3d->ofs);
- copy_v3_v3(ruler_item->co[0], inter->drag_start_co);
- view3d_ruler_item_project(ruler_info, ruler_item->co[0], event->mval);
- }
-
- copy_v3_v3(ruler_item->co[2], ruler_item->co[0]);
- ruler_item->gz.highlight_part = inter->co_index = 2;
- }
- return OPERATOR_FINISHED;
+ ARegion *ar = CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = ar->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;
+ wmGizmoGroup *gzgroup = WM_gizmomap_group_find(gzmap, view3d_gzgt_ruler_id);
+ const bool use_depth = (v3d->shading.type >= OB_SOLID);
+
+ /* Create new line */
+ RulerItem *ruler_item;
+ ruler_item = ruler_item_add(gzgroup);
+
+ /* This is a little weak, but there is no real good way to tweak directly. */
+ WM_gizmo_highlight_set(gzmap, &ruler_item->gz);
+ if (WM_operator_name_call(C, "GIZMOGROUP_OT_gizmo_tweak", WM_OP_INVOKE_REGION_WIN, NULL) ==
+ OPERATOR_RUNNING_MODAL) {
+ RulerInfo *ruler_info = gzgroup->customdata;
+ RulerInteraction *inter = ruler_item->gz.interaction_data;
+ if (use_depth) {
+ /* 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);
+ copy_v3_v3(inter->drag_start_co, ruler_item->co[inter->co_index]);
+ }
+ else {
+ negate_v3_v3(inter->drag_start_co, rv3d->ofs);
+ copy_v3_v3(ruler_item->co[0], inter->drag_start_co);
+ view3d_ruler_item_project(ruler_info, ruler_item->co[0], event->mval);
+ }
+
+ copy_v3_v3(ruler_item->co[2], ruler_item->co[0]);
+ ruler_item->gz.highlight_part = inter->co_index = 2;
+ }
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_ruler_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Ruler Add";
- ot->idname = "VIEW3D_OT_ruler_add";
+ /* identifiers */
+ ot->name = "Ruler Add";
+ ot->idname = "VIEW3D_OT_ruler_add";
- ot->invoke = view3d_ruler_add_invoke;
- ot->poll = view3d_ruler_poll;
+ ot->invoke = view3d_ruler_add_invoke;
+ ot->poll = view3d_ruler_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
}
/** \} */
@@ -1105,46 +1107,45 @@ 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);
- View3D *v3d = CTX_wm_view3d(C);
-
- 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;
- wmGizmoGroup *gzgroup = WM_gizmomap_group_find(gzmap, view3d_gzgt_ruler_id);
- if (gzgroup) {
- RulerInfo *ruler_info = gzgroup->customdata;
- if (ruler_info->item_active) {
- RulerItem *ruler_item = ruler_info->item_active;
- if ((ruler_item->flag & RULERITEM_USE_ANGLE) &&
- (ruler_item->flag & RULERITEM_USE_ANGLE_ACTIVE))
- {
- ruler_item->flag &= ~(RULERITEM_USE_ANGLE | RULERITEM_USE_ANGLE_ACTIVE);
- }
- else {
- ruler_item_remove(C, gzgroup, ruler_item);
- }
- ED_region_tag_redraw(ar);
- return OPERATOR_FINISHED;
- }
- }
- return OPERATOR_PASS_THROUGH;
+ ARegion *ar = CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ 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;
+ wmGizmoGroup *gzgroup = WM_gizmomap_group_find(gzmap, view3d_gzgt_ruler_id);
+ if (gzgroup) {
+ RulerInfo *ruler_info = gzgroup->customdata;
+ if (ruler_info->item_active) {
+ RulerItem *ruler_item = ruler_info->item_active;
+ if ((ruler_item->flag & RULERITEM_USE_ANGLE) &&
+ (ruler_item->flag & RULERITEM_USE_ANGLE_ACTIVE)) {
+ ruler_item->flag &= ~(RULERITEM_USE_ANGLE | RULERITEM_USE_ANGLE_ACTIVE);
+ }
+ else {
+ ruler_item_remove(C, gzgroup, ruler_item);
+ }
+ ED_region_tag_redraw(ar);
+ return OPERATOR_FINISHED;
+ }
+ }
+ return OPERATOR_PASS_THROUGH;
}
void VIEW3D_OT_ruler_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Ruler Remove";
- ot->idname = "VIEW3D_OT_ruler_remove";
+ /* identifiers */
+ ot->name = "Ruler Remove";
+ ot->idname = "VIEW3D_OT_ruler_remove";
- ot->invoke = view3d_ruler_remove_invoke;
- ot->poll = view3d_ruler_poll;
+ ot->invoke = view3d_ruler_remove_invoke;
+ ot->poll = view3d_ruler_poll;
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index de3f0392ff0..6984562337c 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -57,9 +57,9 @@
static void do_view3d_header_buttons(bContext *C, void *arg, int event);
-#define B_SEL_VERT 110
-#define B_SEL_EDGE 111
-#define B_SEL_FACE 112
+#define B_SEL_VERT 110
+#define B_SEL_EDGE 111
+#define B_SEL_FACE 112
/* -------------------------------------------------------------------- */
/** \name Toggle Matcap Flip Operator
@@ -67,31 +67,31 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event);
static int toggle_matcap_flip(bContext *C, wmOperator *UNUSED(op))
{
- View3D *v3d = CTX_wm_view3d(C);
-
- if (v3d) {
- v3d->shading.flag ^= V3D_SHADING_MATCAP_FLIP_X;
- ED_view3d_shade_update(CTX_data_main(C), v3d, CTX_wm_area(C));
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
- }
- 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);
- }
-
- return OPERATOR_FINISHED;
+ View3D *v3d = CTX_wm_view3d(C);
+
+ if (v3d) {
+ v3d->shading.flag ^= V3D_SHADING_MATCAP_FLIP_X;
+ ED_view3d_shade_update(CTX_data_main(C), v3d, CTX_wm_area(C));
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ }
+ 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);
+ }
+
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_toggle_matcap_flip(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Flip MatCap";
- ot->description = "Flip MatCap";
- ot->idname = "VIEW3D_OT_toggle_matcap_flip";
+ /* identifiers */
+ ot->name = "Flip MatCap";
+ ot->description = "Flip MatCap";
+ ot->idname = "VIEW3D_OT_toggle_matcap_flip";
- /* api callbacks */
- ot->exec = toggle_matcap_flip;
+ /* api callbacks */
+ ot->exec = toggle_matcap_flip;
}
/** \} */
@@ -102,95 +102,136 @@ void VIEW3D_OT_toggle_matcap_flip(wmOperatorType *ot)
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 */
-
- switch (event) {
- case B_SEL_VERT:
- if (EDBM_selectmode_toggle(C, SCE_SELECT_VERTEX, -1, shift, ctrl)) {
- ED_undo_push(C, "Selectmode Set: Vertex");
- }
- break;
- case B_SEL_EDGE:
- if (EDBM_selectmode_toggle(C, SCE_SELECT_EDGE, -1, shift, ctrl)) {
- ED_undo_push(C, "Selectmode Set: Edge");
- }
- break;
- case B_SEL_FACE:
- if (EDBM_selectmode_toggle(C, SCE_SELECT_FACE, -1, shift, ctrl)) {
- ED_undo_push(C, "Selectmode Set: Face");
- }
- break;
- default:
- break;
- }
+ 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 */
+
+ switch (event) {
+ case B_SEL_VERT:
+ if (EDBM_selectmode_toggle(C, SCE_SELECT_VERTEX, -1, shift, ctrl)) {
+ ED_undo_push(C, "Selectmode Set: Vertex");
+ }
+ break;
+ case B_SEL_EDGE:
+ if (EDBM_selectmode_toggle(C, SCE_SELECT_EDGE, -1, shift, ctrl)) {
+ ED_undo_push(C, "Selectmode Set: Edge");
+ }
+ break;
+ case B_SEL_FACE:
+ if (EDBM_selectmode_toggle(C, SCE_SELECT_FACE, -1, shift, ctrl)) {
+ ED_undo_push(C, "Selectmode Set: Face");
+ }
+ break;
+ default:
+ break;
+ }
}
void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- uiBlock *block = uiLayoutGetBlock(layout);
-
- UI_block_func_handle_set(block, do_view3d_header_buttons, NULL);
-
- if (obedit && (obedit->type == OB_MESH)) {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- uiLayout *row;
-
- row = uiLayoutRow(layout, true);
- block = uiLayoutGetBlock(row);
- uiDefIconButBitS(block, UI_BTYPE_TOGGLE, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL,
- 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 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(block, UI_BTYPE_TOGGLE, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL,
- 0, 0, ceilf(UI_UNIT_X - U.pixelsize), UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0,
- TIP_("Face select - Shift-Click for multiple modes, Ctrl-Click expands selection"));
- }
+ Object *obedit = CTX_data_edit_object(C);
+ uiBlock *block = uiLayoutGetBlock(layout);
+
+ UI_block_func_handle_set(block, do_view3d_header_buttons, NULL);
+
+ if (obedit && (obedit->type == OB_MESH)) {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ uiLayout *row;
+
+ row = uiLayoutRow(layout, true);
+ block = uiLayoutGetBlock(row);
+ uiDefIconButBitS(
+ block,
+ UI_BTYPE_TOGGLE,
+ SCE_SELECT_VERTEX,
+ B_SEL_VERT,
+ ICON_VERTEXSEL,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &em->selectmode,
+ 1.0,
+ 0.0,
+ 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(
+ block,
+ UI_BTYPE_TOGGLE,
+ SCE_SELECT_FACE,
+ B_SEL_FACE,
+ ICON_FACESEL,
+ 0,
+ 0,
+ ceilf(UI_UNIT_X - U.pixelsize),
+ UI_UNIT_Y,
+ &em->selectmode,
+ 1.0,
+ 0.0,
+ 0,
+ 0,
+ TIP_("Face select - Shift-Click for multiple modes, Ctrl-Click expands selection"));
+ }
}
static void uiTemplatePaintModeSelection(uiLayout *layout, struct bContext *C)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
-
- /* Gizmos aren't used in paint modes */
- if (!ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_PARTICLE_EDIT)) {
- /* masks aren't used for sculpt and particle painting */
- PointerRNA meshptr;
-
- RNA_pointer_create(ob->data, &RNA_Mesh, ob->data, &meshptr);
- if (ob->mode & (OB_MODE_TEXTURE_PAINT)) {
- uiItemR(layout, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
- }
- else {
- uiLayout *row = uiLayoutRow(layout, true);
- uiItemR(row, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
- uiItemR(row, &meshptr, "use_paint_mask_vertex", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
- }
- }
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+
+ /* Gizmos aren't used in paint modes */
+ if (!ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_PARTICLE_EDIT)) {
+ /* masks aren't used for sculpt and particle painting */
+ PointerRNA meshptr;
+
+ RNA_pointer_create(ob->data, &RNA_Mesh, ob->data, &meshptr);
+ if (ob->mode & (OB_MODE_TEXTURE_PAINT)) {
+ uiItemR(layout, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ }
+ else {
+ uiLayout *row = uiLayoutRow(layout, true);
+ uiItemR(row, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ uiItemR(row, &meshptr, "use_paint_mask_vertex", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ }
+ }
}
void uiTemplateHeader3D_mode(uiLayout *layout, struct bContext *C)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- Object *obedit = CTX_data_edit_object(C);
- bGPdata *gpd = CTX_data_gpencil_data(C);
-
- bool is_paint = (
- ob && !(gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE)) &&
- ELEM(ob->mode,
- OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT));
-
- uiTemplateEditModeSelection(layout, C);
- if ((obedit == NULL) && is_paint) {
- uiTemplatePaintModeSelection(layout, C);
- }
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ Object *obedit = CTX_data_edit_object(C);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+
+ bool is_paint = (ob && !(gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE)) &&
+ ELEM(ob->mode,
+ OB_MODE_SCULPT,
+ OB_MODE_VERTEX_PAINT,
+ OB_MODE_WEIGHT_PAINT,
+ OB_MODE_TEXTURE_PAINT));
+
+ uiTemplateEditModeSelection(layout, C);
+ if ((obedit == NULL) && is_paint) {
+ uiTemplatePaintModeSelection(layout, C);
+ }
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index e85558765b6..fd306619577 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -50,9 +50,9 @@ struct wmWindowManager;
/* drawing flags: */
enum {
- DRAW_PICKING = (1 << 0),
- DRAW_CONSTCOLOR = (1 << 1),
- DRAW_SCENESET = (1 << 2),
+ DRAW_PICKING = (1 << 0),
+ DRAW_CONSTCOLOR = (1 << 1),
+ DRAW_SCENESET = (1 << 2),
};
/* view3d_header.c */
@@ -101,18 +101,22 @@ 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_orbit_apply_dyn_ofs(
- float r_ofs[3], const float ofs_old[3], const float viewquat_old[4],
- const float viewquat_new[4], const float dyn_ofs[3]);
+void view3d_orbit_apply_dyn_ofs(float r_ofs[3],
+ const float ofs_old[3],
+ const float viewquat_old[4],
+ const float viewquat_new[4],
+ const float dyn_ofs[3]);
#ifdef WITH_INPUT_NDOF
struct wmNDOFMotionData;
-void view3d_ndof_fly(
- const struct wmNDOFMotionData *ndof,
- struct View3D *v3d, struct RegionView3D *rv3d,
- const bool use_precision, const short protectflag,
- bool *r_has_translate, bool *r_has_rotate);
+void view3d_ndof_fly(const struct wmNDOFMotionData *ndof,
+ struct View3D *v3d,
+ struct RegionView3D *rv3d,
+ const bool use_precision,
+ const short protectflag,
+ bool *r_has_translate,
+ bool *r_has_rotate);
#endif /* WITH_INPUT_NDOF */
/* view3d_fly.c */
@@ -123,10 +127,12 @@ void VIEW3D_OT_fly(struct wmOperatorType *ot);
void VIEW3D_OT_walk(struct wmOperatorType *ot);
/* drawobject.c */
-void draw_object_select_id(
- struct Depsgraph *depsgraph, Scene *scene,
- View3D *v3d, RegionView3D *rv3d, struct Object *ob,
- short select_mode);
+void draw_object_select_id(struct Depsgraph *depsgraph,
+ Scene *scene,
+ View3D *v3d,
+ RegionView3D *rv3d,
+ struct Object *ob,
+ short select_mode);
void draw_object_depth(RegionView3D *rv3d, struct Object *ob);
@@ -136,19 +142,30 @@ int view3d_effective_drawtype(const struct View3D *v3d);
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 ED_view3d_draw_depth(
- struct Depsgraph *depsgraph,
- struct ARegion *ar, View3D *v3d, bool alphaoverride);
+void ED_view3d_draw_depth(struct Depsgraph *depsgraph,
+ struct ARegion *ar,
+ View3D *v3d,
+ bool alphaoverride);
/* view3d_draw_legacy.c */
-void ED_view3d_draw_depth_gpencil(struct Depsgraph *depsgraph, Scene *scene, struct ARegion *ar, View3D *v3d);
-
-void ED_view3d_draw_select_loop(
- struct Depsgraph *depsgraph, ViewContext *vc, Scene *scene, struct ViewLayer *view_layer, View3D *v3d, struct ARegion *ar,
- bool use_obedit_skip, bool use_nearest);
-
-void ED_view3d_draw_depth_loop(
- struct Depsgraph *depsgraph, Scene *scene, struct ARegion *ar, View3D *v3d);
+void ED_view3d_draw_depth_gpencil(struct Depsgraph *depsgraph,
+ Scene *scene,
+ struct ARegion *ar,
+ View3D *v3d);
+
+void ED_view3d_draw_select_loop(struct Depsgraph *depsgraph,
+ ViewContext *vc,
+ Scene *scene,
+ struct ViewLayer *view_layer,
+ View3D *v3d,
+ struct ARegion *ar,
+ bool use_obedit_skip,
+ bool use_nearest);
+
+void ED_view3d_draw_depth_loop(struct Depsgraph *depsgraph,
+ Scene *scene,
+ struct ARegion *ar,
+ View3D *v3d);
void view3d_update_depths_rect(struct ARegion *ar, struct ViewDepths *d, struct rcti *rect);
float view3d_depth_near(struct ViewDepths *d);
@@ -168,37 +185,46 @@ void VIEW3D_OT_object_as_camera(struct wmOperatorType *ot);
void VIEW3D_OT_localview(struct wmOperatorType *ot);
void VIEW3D_OT_localview_remove_from(struct wmOperatorType *ot);
-bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const struct BoundBox *bb, float obmat[4][4]);
+bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d,
+ const struct BoundBox *bb,
+ float obmat[4][4]);
bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const struct BoundBox *bb);
typedef struct V3D_SmoothParams {
- struct Object *camera_old, *camera;
- const float *ofs, *quat, *dist, *lens;
- /* alternate rotation center (ofs = must be NULL) */
- const float *dyn_ofs;
+ struct Object *camera_old, *camera;
+ const float *ofs, *quat, *dist, *lens;
+ /* alternate rotation center (ofs = must be NULL) */
+ const float *dyn_ofs;
} V3D_SmoothParams;
-void ED_view3d_smooth_view_ex(
- const struct Depsgraph *depsgraph,
- struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *sa,
- struct View3D *v3d, struct ARegion *ar, const int smooth_viewtx,
- const V3D_SmoothParams *sview);
-
-void ED_view3d_smooth_view(
- struct bContext *C,
- struct View3D *v3d, struct ARegion *ar, const int smooth_viewtx,
- const V3D_SmoothParams *sview);
-
-void ED_view3d_smooth_view_force_finish(
- struct bContext *C,
- struct View3D *v3d, struct ARegion *ar);
-
-void view3d_winmatrix_set(
- struct Depsgraph *depsgraph,
- struct ARegion *ar, const View3D *v3d, const rcti *rect);
-void view3d_viewmatrix_set(
- struct Depsgraph *depsgraph, Scene *scene,
- const View3D *v3d, RegionView3D *rv3d, const float rect_scale[2]);
+void ED_view3d_smooth_view_ex(const struct Depsgraph *depsgraph,
+ struct wmWindowManager *wm,
+ struct wmWindow *win,
+ struct ScrArea *sa,
+ struct View3D *v3d,
+ struct ARegion *ar,
+ const int smooth_viewtx,
+ const V3D_SmoothParams *sview);
+
+void ED_view3d_smooth_view(struct bContext *C,
+ struct View3D *v3d,
+ struct ARegion *ar,
+ const int smooth_viewtx,
+ const V3D_SmoothParams *sview);
+
+void ED_view3d_smooth_view_force_finish(struct bContext *C,
+ struct View3D *v3d,
+ struct ARegion *ar);
+
+void view3d_winmatrix_set(struct Depsgraph *depsgraph,
+ struct ARegion *ar,
+ const View3D *v3d,
+ const rcti *rect);
+void view3d_viewmatrix_set(struct Depsgraph *depsgraph,
+ Scene *scene,
+ const View3D *v3d,
+ RegionView3D *rv3d,
+ const float rect_scale[2]);
void fly_modal_keymap(struct wmKeyConfig *keyconf);
void walk_modal_keymap(struct wmKeyConfig *keyconf);
@@ -213,18 +239,18 @@ void VIEW3D_OT_object_mode_pie_or_toggle(struct wmOperatorType *ot);
void view3d_buttons_register(struct ARegionType *art);
/* view3d_camera_control.c */
-struct View3DCameraControl *ED_view3d_cameracontrol_acquire(
- struct Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d,
- const bool use_parent_root);
-void ED_view3d_cameracontrol_update(
- struct View3DCameraControl *vctrl,
- const bool use_autokey,
- struct bContext *C, const bool do_rotate, const bool do_translate);
-void ED_view3d_cameracontrol_release(
- struct View3DCameraControl *vctrl,
- const bool restore);
-struct Object *ED_view3d_cameracontrol_object_get(
- struct View3DCameraControl *vctrl);
+struct View3DCameraControl *ED_view3d_cameracontrol_acquire(struct Depsgraph *depsgraph,
+ Scene *scene,
+ View3D *v3d,
+ RegionView3D *rv3d,
+ const bool use_parent_root);
+void ED_view3d_cameracontrol_update(struct View3DCameraControl *vctrl,
+ const bool use_autokey,
+ struct bContext *C,
+ const bool do_rotate,
+ const bool do_translate);
+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);
diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c
index daa1cd38164..b6efc0ff136 100644
--- a/source/blender/editors/space_view3d/view3d_iterators.c
+++ b/source/blender/editors/space_view3d/view3d_iterators.c
@@ -49,36 +49,39 @@
#include "ED_view3d.h"
typedef struct foreachScreenObjectVert_userData {
- void (*func)(void *userData, MVert *mv, const float screen_co_b[2], int index);
- void *userData;
- ViewContext vc;
- eV3DProjTest clip_flag;
+ void (*func)(void *userData, MVert *mv, const float screen_co_b[2], int index);
+ void *userData;
+ ViewContext vc;
+ eV3DProjTest clip_flag;
} foreachScreenObjectVert_userData;
typedef struct foreachScreenVert_userData {
- void (*func)(void *userData, BMVert *eve, const float screen_co_b[2], int index);
- void *userData;
- ViewContext vc;
- eV3DProjTest clip_flag;
+ void (*func)(void *userData, BMVert *eve, const float screen_co_b[2], int index);
+ void *userData;
+ ViewContext vc;
+ eV3DProjTest clip_flag;
} foreachScreenVert_userData;
/* user data structures for derived mesh callbacks */
typedef struct foreachScreenEdge_userData {
- void (*func)(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], 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 */
- eV3DProjTest clip_flag;
+ void (*func)(void *userData,
+ BMEdge *eed,
+ const float screen_co_a[2],
+ const float screen_co_b[2],
+ 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 */
+ eV3DProjTest clip_flag;
} foreachScreenEdge_userData;
typedef struct foreachScreenFace_userData {
- void (*func)(void *userData, BMFace *efa, const float screen_co_b[2], int index);
- void *userData;
- ViewContext vc;
- eV3DProjTest clip_flag;
+ void (*func)(void *userData, BMFace *efa, const float screen_co_b[2], int index);
+ void *userData;
+ ViewContext vc;
+ eV3DProjTest clip_flag;
} foreachScreenFace_userData;
-
/**
* \note foreach funcs should be called while drawing or directly after
* if not, #ED_view3d_init_mats_rv3d() can be used for selection tools
@@ -88,392 +91,447 @@ typedef struct foreachScreenFace_userData {
/* ------------------------------------------------------------------------ */
-
-static void meshobject_foreachScreenVert__mapFunc(void *userData, int index, const float co[3],
- const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+static void meshobject_foreachScreenVert__mapFunc(void *userData,
+ int index,
+ const float co[3],
+ const float UNUSED(no_f[3]),
+ const short UNUSED(no_s[3]))
{
- foreachScreenObjectVert_userData *data = userData;
- struct MVert *mv = &((Mesh *)(data->vc.obact->data))->mvert[index];
+ foreachScreenObjectVert_userData *data = userData;
+ struct MVert *mv = &((Mesh *)(data->vc.obact->data))->mvert[index];
- if (!(mv->flag & ME_HIDE)) {
- float screen_co[2];
+ if (!(mv->flag & ME_HIDE)) {
+ float screen_co[2];
- if (ED_view3d_project_float_object(data->vc.ar, co, screen_co, data->clip_flag) != V3D_PROJ_RET_OK) {
- return;
- }
+ if (ED_view3d_project_float_object(data->vc.ar, co, screen_co, data->clip_flag) !=
+ V3D_PROJ_RET_OK) {
+ return;
+ }
- data->func(data->userData, mv, screen_co, index);
- }
+ data->func(data->userData, mv, screen_co, index);
+ }
}
void meshobject_foreachScreenVert(
- ViewContext *vc,
- void (*func)(void *userData, MVert *eve, const float screen_co[2], int index),
- void *userData, eV3DProjTest clip_flag)
+ ViewContext *vc,
+ void (*func)(void *userData, MVert *eve, const float screen_co[2], int index),
+ void *userData,
+ eV3DProjTest clip_flag)
{
- foreachScreenObjectVert_userData data;
- Mesh *me;
+ foreachScreenObjectVert_userData data;
+ Mesh *me;
- Scene *scene_eval = DEG_get_evaluated_scene(vc->depsgraph);
- Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact);
+ Scene *scene_eval = DEG_get_evaluated_scene(vc->depsgraph);
+ Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact);
- me = mesh_get_eval_deform(vc->depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
+ me = mesh_get_eval_deform(vc->depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
- ED_view3d_check_mats_rv3d(vc->rv3d);
+ ED_view3d_check_mats_rv3d(vc->rv3d);
- data.vc = *vc;
- data.func = func;
- data.userData = userData;
- data.clip_flag = clip_flag;
+ data.vc = *vc;
+ data.func = func;
+ data.userData = userData;
+ data.clip_flag = clip_flag;
- if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
- ED_view3d_clipping_local(vc->rv3d, vc->obact->obmat);
- }
+ if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
+ ED_view3d_clipping_local(vc->rv3d, vc->obact->obmat);
+ }
- BKE_mesh_foreach_mapped_vert(me, meshobject_foreachScreenVert__mapFunc, &data, MESH_FOREACH_NOP);
+ BKE_mesh_foreach_mapped_vert(me, meshobject_foreachScreenVert__mapFunc, &data, MESH_FOREACH_NOP);
}
-static void mesh_foreachScreenVert__mapFunc(void *userData, int index, const float co[3],
- const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+static void mesh_foreachScreenVert__mapFunc(void *userData,
+ int index,
+ const float co[3],
+ const float UNUSED(no_f[3]),
+ const short UNUSED(no_s[3]))
{
- foreachScreenVert_userData *data = userData;
- BMVert *eve = BM_vert_at_index(data->vc.em->bm, index);
+ foreachScreenVert_userData *data = userData;
+ BMVert *eve = BM_vert_at_index(data->vc.em->bm, index);
- if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- float screen_co[2];
+ 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) != V3D_PROJ_RET_OK) {
- return;
- }
+ if (ED_view3d_project_float_object(data->vc.ar, co, screen_co, data->clip_flag) !=
+ V3D_PROJ_RET_OK) {
+ return;
+ }
- data->func(data->userData, eve, screen_co, index);
- }
+ data->func(data->userData, eve, screen_co, index);
+ }
}
void mesh_foreachScreenVert(
- ViewContext *vc,
- void (*func)(void *userData, BMVert *eve, const float screen_co[2], int index),
- void *userData, eV3DProjTest clip_flag)
+ ViewContext *vc,
+ void (*func)(void *userData, BMVert *eve, const float screen_co[2], int index),
+ void *userData,
+ eV3DProjTest clip_flag)
{
- foreachScreenVert_userData data;
+ foreachScreenVert_userData data;
- Mesh *me = editbmesh_get_eval_cage_from_orig(vc->depsgraph, vc->scene, vc->obedit, vc->em, &CD_MASK_BAREMESH);
+ Mesh *me = editbmesh_get_eval_cage_from_orig(
+ vc->depsgraph, vc->scene, vc->obedit, vc->em, &CD_MASK_BAREMESH);
- ED_view3d_check_mats_rv3d(vc->rv3d);
+ ED_view3d_check_mats_rv3d(vc->rv3d);
- data.vc = *vc;
- data.func = func;
- data.userData = userData;
- data.clip_flag = clip_flag;
+ data.vc = *vc;
+ data.func = func;
+ data.userData = userData;
+ data.clip_flag = clip_flag;
- if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
- ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
- }
+ if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
+ ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
+ }
- BM_mesh_elem_table_ensure(vc->em->bm, BM_VERT);
- BKE_mesh_foreach_mapped_vert(me, mesh_foreachScreenVert__mapFunc, &data, MESH_FOREACH_NOP);
+ BM_mesh_elem_table_ensure(vc->em->bm, BM_VERT);
+ BKE_mesh_foreach_mapped_vert(me, mesh_foreachScreenVert__mapFunc, &data, MESH_FOREACH_NOP);
}
/* ------------------------------------------------------------------------ */
-static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, const float v0co[3], const float v1co[3])
+static void mesh_foreachScreenEdge__mapFunc(void *userData,
+ int index,
+ const float v0co[3],
+ const float v1co[3])
{
- foreachScreenEdge_userData *data = userData;
- BMEdge *eed = BM_edge_at_index(data->vc.em->bm, index);
-
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- float screen_co_a[2];
- 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) != V3D_PROJ_RET_OK) {
- return;
- }
- if (ED_view3d_project_float_object(data->vc.ar, v1co, screen_co_b, clip_flag_nowin) != V3D_PROJ_RET_OK) {
- return;
- }
-
- if (data->clip_flag & V3D_PROJ_TEST_CLIP_WIN) {
- if (!BLI_rctf_isect_segment(&data->win_rect, screen_co_a, screen_co_b)) {
- return;
- }
- }
-
- data->func(data->userData, eed, screen_co_a, screen_co_b, index);
- }
+ foreachScreenEdge_userData *data = userData;
+ BMEdge *eed = BM_edge_at_index(data->vc.em->bm, index);
+
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+ float screen_co_a[2];
+ 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) !=
+ V3D_PROJ_RET_OK) {
+ return;
+ }
+ if (ED_view3d_project_float_object(data->vc.ar, v1co, screen_co_b, clip_flag_nowin) !=
+ V3D_PROJ_RET_OK) {
+ return;
+ }
+
+ if (data->clip_flag & V3D_PROJ_TEST_CLIP_WIN) {
+ if (!BLI_rctf_isect_segment(&data->win_rect, screen_co_a, screen_co_b)) {
+ return;
+ }
+ }
+
+ data->func(data->userData, eed, screen_co_a, screen_co_b, index);
+ }
}
-void mesh_foreachScreenEdge(
- ViewContext *vc,
- void (*func)(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index),
- void *userData, eV3DProjTest clip_flag)
+void mesh_foreachScreenEdge(ViewContext *vc,
+ void (*func)(void *userData,
+ BMEdge *eed,
+ const float screen_co_a[2],
+ const float screen_co_b[2],
+ int index),
+ void *userData,
+ eV3DProjTest clip_flag)
{
- foreachScreenEdge_userData data;
+ foreachScreenEdge_userData data;
- Mesh *me = editbmesh_get_eval_cage_from_orig(vc->depsgraph, vc->scene, vc->obedit, vc->em, &CD_MASK_BAREMESH);
+ Mesh *me = editbmesh_get_eval_cage_from_orig(
+ vc->depsgraph, vc->scene, vc->obedit, vc->em, &CD_MASK_BAREMESH);
- ED_view3d_check_mats_rv3d(vc->rv3d);
+ ED_view3d_check_mats_rv3d(vc->rv3d);
- data.vc = *vc;
+ data.vc = *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.xmin = 0;
+ data.win_rect.ymin = 0;
+ data.win_rect.xmax = vc->ar->winx;
+ data.win_rect.ymax = vc->ar->winy;
- data.func = func;
- data.userData = userData;
- data.clip_flag = clip_flag;
+ data.func = func;
+ data.userData = userData;
+ data.clip_flag = clip_flag;
- if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
- ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
- }
+ if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
+ ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
+ }
- BM_mesh_elem_table_ensure(vc->em->bm, BM_EDGE);
- BKE_mesh_foreach_mapped_edge(me, mesh_foreachScreenEdge__mapFunc, &data);
+ BM_mesh_elem_table_ensure(vc->em->bm, BM_EDGE);
+ BKE_mesh_foreach_mapped_edge(me, mesh_foreachScreenEdge__mapFunc, &data);
}
/* ------------------------------------------------------------------------ */
-static void mesh_foreachScreenFace__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
+static void mesh_foreachScreenFace__mapFunc(void *userData,
+ int index,
+ const float cent[3],
+ const float UNUSED(no[3]))
{
- foreachScreenFace_userData *data = userData;
- BMFace *efa = BM_face_at_index(data->vc.em->bm, index);
-
- 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) == V3D_PROJ_RET_OK) {
- data->func(data->userData, efa, screen_co, index);
- }
- }
+ foreachScreenFace_userData *data = userData;
+ BMFace *efa = BM_face_at_index(data->vc.em->bm, index);
+
+ 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) ==
+ V3D_PROJ_RET_OK) {
+ data->func(data->userData, efa, screen_co, index);
+ }
+ }
}
void mesh_foreachScreenFace(
- ViewContext *vc,
- void (*func)(void *userData, BMFace *efa, const float screen_co_b[2], int index),
- void *userData, const eV3DProjTest clip_flag)
+ ViewContext *vc,
+ void (*func)(void *userData, BMFace *efa, const float screen_co_b[2], int index),
+ void *userData,
+ const eV3DProjTest clip_flag)
{
- foreachScreenFace_userData data;
+ foreachScreenFace_userData data;
- Mesh *me = editbmesh_get_eval_cage_from_orig(vc->depsgraph, vc->scene, vc->obedit, vc->em, &CD_MASK_BAREMESH);
- ED_view3d_check_mats_rv3d(vc->rv3d);
+ Mesh *me = editbmesh_get_eval_cage_from_orig(
+ vc->depsgraph, vc->scene, vc->obedit, vc->em, &CD_MASK_BAREMESH);
+ ED_view3d_check_mats_rv3d(vc->rv3d);
- data.vc = *vc;
- data.func = func;
- data.userData = userData;
- data.clip_flag = clip_flag;
+ data.vc = *vc;
+ data.func = func;
+ data.userData = userData;
+ data.clip_flag = clip_flag;
- BM_mesh_elem_table_ensure(vc->em->bm, BM_FACE);
- BKE_mesh_foreach_mapped_face_center(me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP);
+ BM_mesh_elem_table_ensure(vc->em->bm, BM_FACE);
+ BKE_mesh_foreach_mapped_face_center(
+ me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP);
}
/* ------------------------------------------------------------------------ */
-void nurbs_foreachScreenVert(
- ViewContext *vc,
- void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co_b[2]),
- void *userData, const eV3DProjTest clip_flag)
+void nurbs_foreachScreenVert(ViewContext *vc,
+ void (*func)(void *userData,
+ Nurb *nu,
+ BPoint *bp,
+ BezTriple *bezt,
+ int beztindex,
+ const float screen_co_b[2]),
+ void *userData,
+ const eV3DProjTest clip_flag)
{
- Curve *cu = vc->obedit->data;
- Nurb *nu;
- int i;
- ListBase *nurbs = BKE_curve_editNurbs_get(cu);
-
- ED_view3d_check_mats_rv3d(vc->rv3d);
-
- if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
- ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
- }
-
- for (nu = nurbs->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- for (i = 0; i < nu->pntsu; i++) {
- BezTriple *bezt = &nu->bezt[i];
-
- if (bezt->hide == 0) {
- float screen_co[2];
-
- if ((vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
- if (ED_view3d_project_float_object(vc->ar, 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);
- }
- }
- else {
- if (ED_view3d_project_float_object(vc->ar, 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, 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, bezt->vec[2], screen_co,
- V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_OK)
- {
- func(userData, nu, NULL, bezt, 2, screen_co);
- }
- }
- }
- }
- }
- else {
- for (i = 0; i < nu->pntsu * nu->pntsv; i++) {
- BPoint *bp = &nu->bp[i];
-
- 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) == V3D_PROJ_RET_OK)
- {
- func(userData, nu, bp, NULL, -1, screen_co);
- }
- }
- }
- }
- }
+ Curve *cu = vc->obedit->data;
+ Nurb *nu;
+ int i;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+
+ ED_view3d_check_mats_rv3d(vc->rv3d);
+
+ if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
+ ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
+ }
+
+ for (nu = nurbs->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ for (i = 0; i < nu->pntsu; i++) {
+ BezTriple *bezt = &nu->bezt[i];
+
+ if (bezt->hide == 0) {
+ float screen_co[2];
+
+ if ((vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
+ if (ED_view3d_project_float_object(vc->ar,
+ 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);
+ }
+ }
+ else {
+ if (ED_view3d_project_float_object(vc->ar,
+ 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,
+ 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,
+ bezt->vec[2],
+ screen_co,
+ V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
+ V3D_PROJ_RET_OK) {
+ func(userData, nu, NULL, bezt, 2, screen_co);
+ }
+ }
+ }
+ }
+ }
+ else {
+ for (i = 0; i < nu->pntsu * nu->pntsv; i++) {
+ BPoint *bp = &nu->bp[i];
+
+ 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) ==
+ V3D_PROJ_RET_OK) {
+ func(userData, nu, bp, NULL, -1, screen_co);
+ }
+ }
+ }
+ }
+ }
}
/* ------------------------------------------------------------------------ */
/* ED_view3d_init_mats_rv3d must be called first */
-void mball_foreachScreenElem(
- struct ViewContext *vc,
- void (*func)(void *userData, struct MetaElem *ml, const float screen_co_b[2]),
- void *userData, const eV3DProjTest clip_flag)
+void mball_foreachScreenElem(struct ViewContext *vc,
+ void (*func)(void *userData,
+ struct MetaElem *ml,
+ const float screen_co_b[2]),
+ void *userData,
+ const eV3DProjTest clip_flag)
{
- MetaBall *mb = (MetaBall *)vc->obedit->data;
- MetaElem *ml;
+ MetaBall *mb = (MetaBall *)vc->obedit->data;
+ MetaElem *ml;
- ED_view3d_check_mats_rv3d(vc->rv3d);
+ ED_view3d_check_mats_rv3d(vc->rv3d);
- 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) {
- func(userData, ml, screen_co);
- }
- }
+ 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) {
+ func(userData, ml, screen_co);
+ }
+ }
}
/* ------------------------------------------------------------------------ */
-void lattice_foreachScreenVert(
- ViewContext *vc,
- void (*func)(void *userData, BPoint *bp, const float screen_co[2]),
- void *userData, const eV3DProjTest clip_flag)
+void lattice_foreachScreenVert(ViewContext *vc,
+ void (*func)(void *userData, BPoint *bp, const float screen_co[2]),
+ void *userData,
+ const eV3DProjTest clip_flag)
{
- Object *obedit = vc->obedit;
- Lattice *lt = obedit->data;
- BPoint *bp = lt->editlatt->latt->def;
- DispList *dl = obedit->runtime.curve_cache ? BKE_displist_find(&obedit->runtime.curve_cache->disp, DL_VERTS) : NULL;
- const float *co = dl ? dl->verts : NULL;
- int i, N = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
-
- ED_view3d_check_mats_rv3d(vc->rv3d);
-
- if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
- ED_view3d_clipping_local(vc->rv3d, obedit->obmat); /* for local clipping lookups */
- }
-
- 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) == V3D_PROJ_RET_OK) {
- func(userData, bp, screen_co);
- }
- }
- }
+ Object *obedit = vc->obedit;
+ Lattice *lt = obedit->data;
+ BPoint *bp = lt->editlatt->latt->def;
+ DispList *dl = obedit->runtime.curve_cache ?
+ BKE_displist_find(&obedit->runtime.curve_cache->disp, DL_VERTS) :
+ NULL;
+ const float *co = dl ? dl->verts : NULL;
+ int i, N = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
+
+ ED_view3d_check_mats_rv3d(vc->rv3d);
+
+ if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
+ ED_view3d_clipping_local(vc->rv3d, obedit->obmat); /* for local clipping lookups */
+ }
+
+ 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) ==
+ V3D_PROJ_RET_OK) {
+ func(userData, bp, screen_co);
+ }
+ }
+ }
}
/* ------------------------------------------------------------------------ */
/* ED_view3d_init_mats_rv3d must be called first */
-void armature_foreachScreenBone(
- struct ViewContext *vc,
- void (*func)(void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2]),
- void *userData, const eV3DProjTest clip_flag)
+void armature_foreachScreenBone(struct ViewContext *vc,
+ void (*func)(void *userData,
+ struct EditBone *ebone,
+ const float screen_co_a[2],
+ const float screen_co_b[2]),
+ void *userData,
+ const eV3DProjTest clip_flag)
{
- bArmature *arm = vc->obedit->data;
- EditBone *ebone;
-
- ED_view3d_check_mats_rv3d(vc->rv3d);
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone)) {
- float screen_co_a[2], screen_co_b[2];
- 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) == V3D_PROJ_RET_OK) {
- points_proj_tot++;
- }
- else {
- screen_co_a[0] = IS_CLIPPED; /* weak */
- /* screen_co_a[1]: intentionally dont set this so we get errors on misuse */
- }
-
- /* project tail location to screenspace */
- if (ED_view3d_project_float_object(vc->ar, ebone->tail, screen_co_b, clip_flag) == V3D_PROJ_RET_OK) {
- points_proj_tot++;
- }
- else {
- screen_co_b[0] = IS_CLIPPED; /* weak */
- /* screen_co_b[1]: intentionally dont set this so we get errors on misuse */
- }
-
- if (points_proj_tot) { /* at least one point's projection worked */
- func(userData, ebone, screen_co_a, screen_co_b);
- }
- }
- }
+ bArmature *arm = vc->obedit->data;
+ EditBone *ebone;
+
+ ED_view3d_check_mats_rv3d(vc->rv3d);
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ float screen_co_a[2], screen_co_b[2];
+ 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) ==
+ V3D_PROJ_RET_OK) {
+ points_proj_tot++;
+ }
+ else {
+ screen_co_a[0] = IS_CLIPPED; /* weak */
+ /* screen_co_a[1]: intentionally dont set this so we get errors on misuse */
+ }
+
+ /* project tail location to screenspace */
+ if (ED_view3d_project_float_object(vc->ar, ebone->tail, screen_co_b, clip_flag) ==
+ V3D_PROJ_RET_OK) {
+ points_proj_tot++;
+ }
+ else {
+ screen_co_b[0] = IS_CLIPPED; /* weak */
+ /* screen_co_b[1]: intentionally dont set this so we get errors on misuse */
+ }
+
+ if (points_proj_tot) { /* at least one point's projection worked */
+ func(userData, ebone, screen_co_a, screen_co_b);
+ }
+ }
+ }
}
/* ------------------------------------------------------------------------ */
/* ED_view3d_init_mats_rv3d must be called first */
/* almost _exact_ copy of #armature_foreachScreenBone */
-void pose_foreachScreenBone(
- struct ViewContext *vc,
- void (*func)(void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2]),
- void *userData, const eV3DProjTest clip_flag)
+void pose_foreachScreenBone(struct ViewContext *vc,
+ void (*func)(void *userData,
+ struct bPoseChannel *pchan,
+ const float screen_co_a[2],
+ const float screen_co_b[2]),
+ void *userData,
+ const eV3DProjTest clip_flag)
{
- const Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact);
- const bArmature *arm_eval = ob_eval->data;
- bPose *pose = vc->obact->pose;
- bPoseChannel *pchan;
-
- ED_view3d_check_mats_rv3d(vc->rv3d);
-
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- if (PBONE_VISIBLE(arm_eval, pchan->bone)) {
- bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
- float screen_co_a[2], screen_co_b[2];
- 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) {
- points_proj_tot++;
- }
- else {
- screen_co_a[0] = IS_CLIPPED; /* weak */
- /* screen_co_a[1]: intentionally dont set this so we get errors on misuse */
- }
-
- /* 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) {
- points_proj_tot++;
- }
- else {
- screen_co_b[0] = IS_CLIPPED; /* weak */
- /* screen_co_b[1]: intentionally dont set this so we get errors on misuse */
- }
-
- if (points_proj_tot) { /* at least one point's projection worked */
- func(userData, pchan, screen_co_a, screen_co_b);
- }
- }
- }
+ const Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact);
+ const bArmature *arm_eval = ob_eval->data;
+ bPose *pose = vc->obact->pose;
+ bPoseChannel *pchan;
+
+ ED_view3d_check_mats_rv3d(vc->rv3d);
+
+ for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (PBONE_VISIBLE(arm_eval, pchan->bone)) {
+ bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
+ float screen_co_a[2], screen_co_b[2];
+ 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) {
+ points_proj_tot++;
+ }
+ else {
+ screen_co_a[0] = IS_CLIPPED; /* weak */
+ /* screen_co_a[1]: intentionally dont set this so we get errors on misuse */
+ }
+
+ /* 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) {
+ points_proj_tot++;
+ }
+ else {
+ screen_co_b[0] = IS_CLIPPED; /* weak */
+ /* screen_co_b[1]: intentionally dont set this so we get errors on misuse */
+ }
+
+ if (points_proj_tot) { /* at least one point's projection worked */
+ func(userData, pchan, screen_co_a, screen_co_b);
+ }
+ }
+ }
}
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 3efd0e32440..4e33005ebc0 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -21,11 +21,9 @@
* \ingroup spview3d
*/
-
#include <stdlib.h>
#include <math.h>
-
#include "DNA_collection_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -63,175 +61,177 @@
static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- char str[FILE_MAX];
- int num_copied = 0;
+ Main *bmain = CTX_data_main(C);
+ char str[FILE_MAX];
+ int num_copied = 0;
- BKE_copybuffer_begin(bmain);
+ BKE_copybuffer_begin(bmain);
- /* context, selection, could be generalized */
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
- BKE_copybuffer_tag_ID(&ob->id);
- num_copied++;
- }
- }
- CTX_DATA_END;
+ /* context, selection, could be generalized */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
+ BKE_copybuffer_tag_ID(&ob->id);
+ num_copied++;
+ }
+ }
+ CTX_DATA_END;
- BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
- BKE_copybuffer_save(bmain, str, op->reports);
+ BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
+ BKE_copybuffer_save(bmain, str, op->reports);
- BKE_reportf(op->reports, RPT_INFO, "Copied %d selected objects", num_copied);
+ BKE_reportf(op->reports, RPT_INFO, "Copied %d selected objects", num_copied);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void VIEW3D_OT_copybuffer(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Objects";
- ot->idname = "VIEW3D_OT_copybuffer";
- ot->description = "Selected objects are copied to the clipboard";
-
- /* api callbacks */
- ot->exec = view3d_copybuffer_exec;
- ot->poll = ED_operator_scene;
+ /* identifiers */
+ ot->name = "Copy Objects";
+ ot->idname = "VIEW3D_OT_copybuffer";
+ ot->description = "Selected objects are copied to the clipboard";
+
+ /* api callbacks */
+ ot->exec = view3d_copybuffer_exec;
+ ot->poll = ED_operator_scene;
}
static int view3d_pastebuffer_exec(bContext *C, wmOperator *op)
{
- char str[FILE_MAX];
- short flag = 0;
+ char str[FILE_MAX];
+ short flag = 0;
- if (RNA_boolean_get(op->ptr, "autoselect")) {
- flag |= FILE_AUTOSELECT;
- }
- if (RNA_boolean_get(op->ptr, "active_collection")) {
- flag |= FILE_ACTIVE_COLLECTION;
- }
+ if (RNA_boolean_get(op->ptr, "autoselect")) {
+ flag |= FILE_AUTOSELECT;
+ }
+ if (RNA_boolean_get(op->ptr, "active_collection")) {
+ flag |= FILE_ACTIVE_COLLECTION;
+ }
- BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
+ BLI_make_file_string("/", 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) {
- BKE_report(op->reports, RPT_INFO, "No objects to paste");
- return OPERATOR_CANCELLED;
- }
+ const int num_pasted = BKE_copybuffer_paste(C, str, flag, op->reports, FILTER_ID_OB);
+ if (num_pasted == 0) {
+ BKE_report(op->reports, RPT_INFO, "No objects to paste");
+ return OPERATOR_CANCELLED;
+ }
- WM_event_add_notifier(C, NC_WINDOW, NULL);
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
- BKE_reportf(op->reports, RPT_INFO, "%d objects pasted", num_pasted);
+ BKE_reportf(op->reports, RPT_INFO, "%d objects pasted", num_pasted);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void VIEW3D_OT_pastebuffer(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Paste Objects";
- ot->idname = "VIEW3D_OT_pastebuffer";
- ot->description = "Objects from the clipboard are pasted";
+ /* identifiers */
+ ot->name = "Paste Objects";
+ ot->idname = "VIEW3D_OT_pastebuffer";
+ ot->description = "Objects from the clipboard are pasted";
- /* api callbacks */
- ot->exec = view3d_pastebuffer_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = view3d_pastebuffer_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "autoselect", true, "Select", "Select pasted objects");
- RNA_def_boolean(ot->srna, "active_collection", true,
- "Active Collection", "Put pasted objects in the active collection");
+ RNA_def_boolean(ot->srna, "autoselect", true, "Select", "Select pasted objects");
+ RNA_def_boolean(ot->srna,
+ "active_collection",
+ true,
+ "Active Collection",
+ "Put pasted objects in the active collection");
}
/* ************************** registration **********************************/
void view3d_operatortypes(void)
{
- WM_operatortype_append(VIEW3D_OT_rotate);
- WM_operatortype_append(VIEW3D_OT_move);
- WM_operatortype_append(VIEW3D_OT_zoom);
- WM_operatortype_append(VIEW3D_OT_zoom_camera_1_to_1);
- WM_operatortype_append(VIEW3D_OT_dolly);
+ WM_operatortype_append(VIEW3D_OT_rotate);
+ WM_operatortype_append(VIEW3D_OT_move);
+ WM_operatortype_append(VIEW3D_OT_zoom);
+ WM_operatortype_append(VIEW3D_OT_zoom_camera_1_to_1);
+ WM_operatortype_append(VIEW3D_OT_dolly);
#ifdef WITH_INPUT_NDOF
- WM_operatortype_append(VIEW3D_OT_ndof_orbit_zoom);
- WM_operatortype_append(VIEW3D_OT_ndof_orbit);
- WM_operatortype_append(VIEW3D_OT_ndof_pan);
- WM_operatortype_append(VIEW3D_OT_ndof_all);
+ WM_operatortype_append(VIEW3D_OT_ndof_orbit_zoom);
+ WM_operatortype_append(VIEW3D_OT_ndof_orbit);
+ WM_operatortype_append(VIEW3D_OT_ndof_pan);
+ WM_operatortype_append(VIEW3D_OT_ndof_all);
#endif /* WITH_INPUT_NDOF */
- WM_operatortype_append(VIEW3D_OT_view_all);
- WM_operatortype_append(VIEW3D_OT_view_axis);
- WM_operatortype_append(VIEW3D_OT_view_camera);
- WM_operatortype_append(VIEW3D_OT_view_orbit);
- WM_operatortype_append(VIEW3D_OT_view_roll);
- WM_operatortype_append(VIEW3D_OT_view_pan);
- WM_operatortype_append(VIEW3D_OT_view_persportho);
- WM_operatortype_append(VIEW3D_OT_background_image_add);
- WM_operatortype_append(VIEW3D_OT_background_image_remove);
- WM_operatortype_append(VIEW3D_OT_view_selected);
- WM_operatortype_append(VIEW3D_OT_view_lock_clear);
- WM_operatortype_append(VIEW3D_OT_view_lock_to_active);
- WM_operatortype_append(VIEW3D_OT_view_center_cursor);
- WM_operatortype_append(VIEW3D_OT_view_center_pick);
- WM_operatortype_append(VIEW3D_OT_view_center_camera);
- WM_operatortype_append(VIEW3D_OT_view_center_lock);
- WM_operatortype_append(VIEW3D_OT_select);
- WM_operatortype_append(VIEW3D_OT_select_box);
- WM_operatortype_append(VIEW3D_OT_clip_border);
- WM_operatortype_append(VIEW3D_OT_select_circle);
- WM_operatortype_append(VIEW3D_OT_smoothview);
- WM_operatortype_append(VIEW3D_OT_render_border);
- WM_operatortype_append(VIEW3D_OT_clear_render_border);
- WM_operatortype_append(VIEW3D_OT_zoom_border);
- WM_operatortype_append(VIEW3D_OT_cursor3d);
- WM_operatortype_append(VIEW3D_OT_select_lasso);
- WM_operatortype_append(VIEW3D_OT_select_menu);
- WM_operatortype_append(VIEW3D_OT_camera_to_view);
- WM_operatortype_append(VIEW3D_OT_camera_to_view_selected);
- WM_operatortype_append(VIEW3D_OT_object_as_camera);
- WM_operatortype_append(VIEW3D_OT_localview);
- WM_operatortype_append(VIEW3D_OT_localview_remove_from);
- WM_operatortype_append(VIEW3D_OT_fly);
- WM_operatortype_append(VIEW3D_OT_walk);
- WM_operatortype_append(VIEW3D_OT_navigate);
- WM_operatortype_append(VIEW3D_OT_copybuffer);
- WM_operatortype_append(VIEW3D_OT_pastebuffer);
-
- WM_operatortype_append(VIEW3D_OT_properties);
- WM_operatortype_append(VIEW3D_OT_object_mode_pie_or_toggle);
- WM_operatortype_append(VIEW3D_OT_toolshelf);
-
- WM_operatortype_append(VIEW3D_OT_snap_selected_to_grid);
- WM_operatortype_append(VIEW3D_OT_snap_selected_to_cursor);
- WM_operatortype_append(VIEW3D_OT_snap_selected_to_active);
- WM_operatortype_append(VIEW3D_OT_snap_cursor_to_grid);
- WM_operatortype_append(VIEW3D_OT_snap_cursor_to_center);
- WM_operatortype_append(VIEW3D_OT_snap_cursor_to_selected);
- WM_operatortype_append(VIEW3D_OT_snap_cursor_to_active);
-
- WM_operatortype_append(VIEW3D_OT_toggle_shading);
- WM_operatortype_append(VIEW3D_OT_toggle_xray);
- WM_operatortype_append(VIEW3D_OT_toggle_matcap_flip);
-
- WM_operatortype_append(VIEW3D_OT_ruler_add);
- WM_operatortype_append(VIEW3D_OT_ruler_remove);
-
- transform_operatortypes();
+ WM_operatortype_append(VIEW3D_OT_view_all);
+ WM_operatortype_append(VIEW3D_OT_view_axis);
+ WM_operatortype_append(VIEW3D_OT_view_camera);
+ WM_operatortype_append(VIEW3D_OT_view_orbit);
+ WM_operatortype_append(VIEW3D_OT_view_roll);
+ WM_operatortype_append(VIEW3D_OT_view_pan);
+ WM_operatortype_append(VIEW3D_OT_view_persportho);
+ WM_operatortype_append(VIEW3D_OT_background_image_add);
+ WM_operatortype_append(VIEW3D_OT_background_image_remove);
+ WM_operatortype_append(VIEW3D_OT_view_selected);
+ WM_operatortype_append(VIEW3D_OT_view_lock_clear);
+ WM_operatortype_append(VIEW3D_OT_view_lock_to_active);
+ WM_operatortype_append(VIEW3D_OT_view_center_cursor);
+ WM_operatortype_append(VIEW3D_OT_view_center_pick);
+ WM_operatortype_append(VIEW3D_OT_view_center_camera);
+ WM_operatortype_append(VIEW3D_OT_view_center_lock);
+ WM_operatortype_append(VIEW3D_OT_select);
+ WM_operatortype_append(VIEW3D_OT_select_box);
+ WM_operatortype_append(VIEW3D_OT_clip_border);
+ WM_operatortype_append(VIEW3D_OT_select_circle);
+ WM_operatortype_append(VIEW3D_OT_smoothview);
+ WM_operatortype_append(VIEW3D_OT_render_border);
+ WM_operatortype_append(VIEW3D_OT_clear_render_border);
+ WM_operatortype_append(VIEW3D_OT_zoom_border);
+ WM_operatortype_append(VIEW3D_OT_cursor3d);
+ WM_operatortype_append(VIEW3D_OT_select_lasso);
+ WM_operatortype_append(VIEW3D_OT_select_menu);
+ WM_operatortype_append(VIEW3D_OT_camera_to_view);
+ WM_operatortype_append(VIEW3D_OT_camera_to_view_selected);
+ WM_operatortype_append(VIEW3D_OT_object_as_camera);
+ WM_operatortype_append(VIEW3D_OT_localview);
+ WM_operatortype_append(VIEW3D_OT_localview_remove_from);
+ WM_operatortype_append(VIEW3D_OT_fly);
+ WM_operatortype_append(VIEW3D_OT_walk);
+ WM_operatortype_append(VIEW3D_OT_navigate);
+ WM_operatortype_append(VIEW3D_OT_copybuffer);
+ WM_operatortype_append(VIEW3D_OT_pastebuffer);
+
+ WM_operatortype_append(VIEW3D_OT_properties);
+ WM_operatortype_append(VIEW3D_OT_object_mode_pie_or_toggle);
+ WM_operatortype_append(VIEW3D_OT_toolshelf);
+
+ WM_operatortype_append(VIEW3D_OT_snap_selected_to_grid);
+ WM_operatortype_append(VIEW3D_OT_snap_selected_to_cursor);
+ WM_operatortype_append(VIEW3D_OT_snap_selected_to_active);
+ WM_operatortype_append(VIEW3D_OT_snap_cursor_to_grid);
+ WM_operatortype_append(VIEW3D_OT_snap_cursor_to_center);
+ WM_operatortype_append(VIEW3D_OT_snap_cursor_to_selected);
+ WM_operatortype_append(VIEW3D_OT_snap_cursor_to_active);
+
+ WM_operatortype_append(VIEW3D_OT_toggle_shading);
+ WM_operatortype_append(VIEW3D_OT_toggle_xray);
+ WM_operatortype_append(VIEW3D_OT_toggle_matcap_flip);
+
+ WM_operatortype_append(VIEW3D_OT_ruler_add);
+ WM_operatortype_append(VIEW3D_OT_ruler_remove);
+
+ transform_operatortypes();
}
void view3d_keymap(wmKeyConfig *keyconf)
{
- WM_keymap_ensure(keyconf, "3D View Generic", SPACE_VIEW3D, 0);
+ WM_keymap_ensure(keyconf, "3D View Generic", SPACE_VIEW3D, 0);
- /* only for region 3D window */
- WM_keymap_ensure(keyconf, "3D View", SPACE_VIEW3D, 0);
+ /* only for region 3D window */
+ WM_keymap_ensure(keyconf, "3D View", SPACE_VIEW3D, 0);
- fly_modal_keymap(keyconf);
- walk_modal_keymap(keyconf);
- viewrotate_modal_keymap(keyconf);
- viewmove_modal_keymap(keyconf);
- viewzoom_modal_keymap(keyconf);
- viewdolly_modal_keymap(keyconf);
+ fly_modal_keymap(keyconf);
+ walk_modal_keymap(keyconf);
+ viewrotate_modal_keymap(keyconf);
+ viewmove_modal_keymap(keyconf);
+ viewzoom_modal_keymap(keyconf);
+ viewdolly_modal_keymap(keyconf);
}
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index e5f8ac147de..6932e94e78d 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -27,7 +27,7 @@
#include "DNA_scene_types.h"
#include "DNA_view3d_types.h"
-#include "BLI_sys_types.h" /* int64_t */
+#include "BLI_sys_types.h" /* int64_t */
#include "BLI_math_vector.h"
@@ -36,7 +36,7 @@
#include "GPU_matrix.h"
-#include "ED_view3d.h" /* own include */
+#include "ED_view3d.h" /* own include */
#define BL_NEAR_CLIP 0.001
#define BL_ZERO_CLIP 0.001
@@ -47,238 +47,268 @@
/**
* \note use #ED_view3d_ob_project_mat_get to get the projection matrix
*/
-void ED_view3d_project_float_v2_m4(const ARegion *ar, const float co[3], float r_co[2], float mat[4][4])
+void ED_view3d_project_float_v2_m4(const ARegion *ar,
+ const float co[3],
+ float r_co[2],
+ float mat[4][4])
{
- float vec4[4];
+ float vec4[4];
- copy_v3_v3(vec4, co);
- vec4[3] = 1.0;
- /* r_co[0] = IS_CLIPPED; */ /* always overwritten */
+ copy_v3_v3(vec4, co);
+ vec4[3] = 1.0;
+ /* r_co[0] = IS_CLIPPED; */ /* always overwritten */
- mul_m4_v4(mat, vec4);
+ 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];
- }
- else {
- zero_v2(r_co);
- }
+ 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];
+ }
+ else {
+ zero_v2(r_co);
+ }
}
/**
* \note use #ED_view3d_ob_project_mat_get to get projecting mat
*/
-void ED_view3d_project_float_v3_m4(const ARegion *ar, const float vec[3], float r_co[3], float mat[4][4])
+void ED_view3d_project_float_v3_m4(const ARegion *ar,
+ const float vec[3],
+ float r_co[3],
+ float mat[4][4])
{
- float vec4[4];
+ float vec4[4];
- copy_v3_v3(vec4, vec);
- vec4[3] = 1.0;
- /* r_co[0] = IS_CLIPPED; */ /* always overwritten */
+ copy_v3_v3(vec4, vec);
+ vec4[3] = 1.0;
+ /* r_co[0] = IS_CLIPPED; */ /* always overwritten */
- mul_m4_v4(mat, vec4);
+ 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[2] = vec4[2] / vec4[3];
- }
- else {
- zero_v3(r_co);
- }
+ 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[2] = vec4[2] / vec4[3];
+ }
+ else {
+ zero_v3(r_co);
+ }
}
-
/* Clipping Projection Functions
* ***************************** */
eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct Base *base)
{
- eV3DProjStatus ret = ED_view3d_project_short_global(ar, base->object->obmat[3], &base->sx, V3D_PROJ_TEST_CLIP_DEFAULT);
+ eV3DProjStatus ret = ED_view3d_project_short_global(
+ ar, base->object->obmat[3], &base->sx, V3D_PROJ_TEST_CLIP_DEFAULT);
- if (ret != V3D_PROJ_RET_OK) {
- base->sx = IS_CLIPPED;
- base->sy = 0;
- }
+ if (ret != V3D_PROJ_RET_OK) {
+ base->sx = IS_CLIPPED;
+ base->sy = 0;
+ }
- return ret;
+ return ret;
}
/* perspmat is typically...
* - 'rv3d->perspmat', is_local == false
* - 'rv3d->persmatob', is_local == true
*/
-static eV3DProjStatus ed_view3d_project__internal(
- const ARegion *ar,
- float perspmat[4][4], const bool is_local, /* normally hidden */
- const float co[3], float r_co[2], const eV3DProjTest flag)
-{
- float vec4[4];
-
- /* check for bad flags */
- BLI_assert((flag & V3D_PROJ_TEST_ALL) == flag);
-
- if (flag & V3D_PROJ_TEST_CLIP_BB) {
- RegionView3D *rv3d = ar->regiondata;
- if (rv3d->rflag & RV3D_CLIPPING) {
- if (ED_view3d_clipping_test(rv3d, co, is_local)) {
- return V3D_PROJ_RET_CLIP_BB;
- }
- }
- }
-
- copy_v3_v3(vec4, co);
- vec4[3] = 1.0;
- mul_m4_v4(perspmat, vec4);
-
-
-
- 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)) {
- r_co[0] = fx;
- r_co[1] = fy;
-
- /* check if the point is behind the view, we need to flip in this case */
- if (UNLIKELY((flag & V3D_PROJ_TEST_CLIP_NEAR) == 0) && (vec4[3] < 0.0f)) {
- negate_v2(r_co);
- }
- }
- else {
- return V3D_PROJ_RET_CLIP_WIN;
- }
- }
- else {
- return V3D_PROJ_RET_CLIP_WIN;
- }
- }
- else {
- return V3D_PROJ_RET_CLIP_NEAR;
- }
- }
- else {
- return V3D_PROJ_RET_CLIP_ZERO;
- }
-
- return V3D_PROJ_RET_OK;
-}
-
-eV3DProjStatus ED_view3d_project_short_ex(const ARegion *ar, float perspmat[4][4], const bool is_local,
- const float co[3], short r_co[2], const eV3DProjTest flag)
-{
- float tvec[2];
- eV3DProjStatus ret = ed_view3d_project__internal(ar, 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))
- {
- r_co[0] = (short)floorf(tvec[0]);
- r_co[1] = (short)floorf(tvec[1]);
- }
- else {
- ret = V3D_PROJ_RET_OVERFLOW;
- }
- }
- return ret;
-}
-
-eV3DProjStatus ED_view3d_project_int_ex(const ARegion *ar, float perspmat[4][4], const bool is_local,
- const float co[3], int r_co[2], const eV3DProjTest flag)
-{
- float tvec[2];
- eV3DProjStatus ret = ed_view3d_project__internal(ar, 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))
- {
- r_co[0] = (int)floorf(tvec[0]);
- r_co[1] = (int)floorf(tvec[1]);
- }
- else {
- ret = V3D_PROJ_RET_OVERFLOW;
- }
- }
- return ret;
-}
-
-eV3DProjStatus ED_view3d_project_float_ex(const ARegion *ar, float perspmat[4][4], const bool is_local,
- const float co[3], float r_co[2], const eV3DProjTest flag)
-{
- float tvec[2];
- eV3DProjStatus ret = ed_view3d_project__internal(ar, 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);
- }
- else {
- ret = V3D_PROJ_RET_OVERFLOW;
- }
- }
- return ret;
+static eV3DProjStatus ed_view3d_project__internal(const ARegion *ar,
+ float perspmat[4][4],
+ const bool is_local, /* normally hidden */
+ const float co[3],
+ float r_co[2],
+ const eV3DProjTest flag)
+{
+ float vec4[4];
+
+ /* check for bad flags */
+ BLI_assert((flag & V3D_PROJ_TEST_ALL) == flag);
+
+ if (flag & V3D_PROJ_TEST_CLIP_BB) {
+ RegionView3D *rv3d = ar->regiondata;
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ if (ED_view3d_clipping_test(rv3d, co, is_local)) {
+ return V3D_PROJ_RET_CLIP_BB;
+ }
+ }
+ }
+
+ copy_v3_v3(vec4, co);
+ vec4[3] = 1.0;
+ mul_m4_v4(perspmat, vec4);
+
+ 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)) {
+ r_co[0] = fx;
+ r_co[1] = fy;
+
+ /* check if the point is behind the view, we need to flip in this case */
+ if (UNLIKELY((flag & V3D_PROJ_TEST_CLIP_NEAR) == 0) && (vec4[3] < 0.0f)) {
+ negate_v2(r_co);
+ }
+ }
+ else {
+ return V3D_PROJ_RET_CLIP_WIN;
+ }
+ }
+ else {
+ return V3D_PROJ_RET_CLIP_WIN;
+ }
+ }
+ else {
+ return V3D_PROJ_RET_CLIP_NEAR;
+ }
+ }
+ else {
+ return V3D_PROJ_RET_CLIP_ZERO;
+ }
+
+ return V3D_PROJ_RET_OK;
+}
+
+eV3DProjStatus ED_view3d_project_short_ex(const ARegion *ar,
+ float perspmat[4][4],
+ const bool is_local,
+ const float co[3],
+ short r_co[2],
+ const eV3DProjTest flag)
+{
+ float tvec[2];
+ eV3DProjStatus ret = ed_view3d_project__internal(ar, 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)) {
+ r_co[0] = (short)floorf(tvec[0]);
+ r_co[1] = (short)floorf(tvec[1]);
+ }
+ else {
+ ret = V3D_PROJ_RET_OVERFLOW;
+ }
+ }
+ return ret;
+}
+
+eV3DProjStatus ED_view3d_project_int_ex(const ARegion *ar,
+ float perspmat[4][4],
+ const bool is_local,
+ const float co[3],
+ int r_co[2],
+ const eV3DProjTest flag)
+{
+ float tvec[2];
+ eV3DProjStatus ret = ed_view3d_project__internal(ar, 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)) {
+ r_co[0] = (int)floorf(tvec[0]);
+ r_co[1] = (int)floorf(tvec[1]);
+ }
+ else {
+ ret = V3D_PROJ_RET_OVERFLOW;
+ }
+ }
+ return ret;
+}
+
+eV3DProjStatus ED_view3d_project_float_ex(const ARegion *ar,
+ float perspmat[4][4],
+ const bool is_local,
+ const float co[3],
+ float r_co[2],
+ const eV3DProjTest flag)
+{
+ float tvec[2];
+ eV3DProjStatus ret = ed_view3d_project__internal(ar, 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);
+ }
+ else {
+ ret = V3D_PROJ_RET_OVERFLOW;
+ }
+ }
+ return ret;
}
/* --- short --- */
-eV3DProjStatus ED_view3d_project_short_global(const ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag)
+eV3DProjStatus ED_view3d_project_short_global(const ARegion *ar,
+ 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 = ar->regiondata;
+ return ED_view3d_project_short_ex(ar, 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, const float co[3], short r_co[2], const eV3DProjTest flag)
+eV3DProjStatus ED_view3d_project_short_object(const ARegion *ar,
+ const float co[3],
+ short r_co[2],
+ const eV3DProjTest flag)
{
- RegionView3D *rv3d = ar->regiondata;
- ED_view3d_check_mats_rv3d(rv3d);
- return ED_view3d_project_short_ex(ar, rv3d->persmatob, true, co, r_co, flag);
+ RegionView3D *rv3d = ar->regiondata;
+ ED_view3d_check_mats_rv3d(rv3d);
+ return ED_view3d_project_short_ex(ar, rv3d->persmatob, true, co, r_co, flag);
}
/* --- int --- */
-eV3DProjStatus ED_view3d_project_int_global(const ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag)
+eV3DProjStatus ED_view3d_project_int_global(const ARegion *ar,
+ 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 = ar->regiondata;
+ return ED_view3d_project_int_ex(ar, 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, const float co[3], int r_co[2], const eV3DProjTest flag)
+eV3DProjStatus ED_view3d_project_int_object(const ARegion *ar,
+ const float co[3],
+ int r_co[2],
+ const eV3DProjTest flag)
{
- RegionView3D *rv3d = ar->regiondata;
- ED_view3d_check_mats_rv3d(rv3d);
- return ED_view3d_project_int_ex(ar, rv3d->persmatob, true, co, r_co, flag);
+ RegionView3D *rv3d = ar->regiondata;
+ ED_view3d_check_mats_rv3d(rv3d);
+ return ED_view3d_project_int_ex(ar, rv3d->persmatob, true, co, r_co, flag);
}
/* --- float --- */
-eV3DProjStatus ED_view3d_project_float_global(const ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag)
+eV3DProjStatus ED_view3d_project_float_global(const ARegion *ar,
+ 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 = ar->regiondata;
+ return ED_view3d_project_float_ex(ar, 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, const float co[3], float r_co[2], const eV3DProjTest flag)
+eV3DProjStatus ED_view3d_project_float_object(const ARegion *ar,
+ const float co[3],
+ float r_co[2],
+ const eV3DProjTest flag)
{
- RegionView3D *rv3d = ar->regiondata;
- ED_view3d_check_mats_rv3d(rv3d);
- return ED_view3d_project_float_ex(ar, rv3d->persmatob, true, co, r_co, flag);
+ RegionView3D *rv3d = ar->regiondata;
+ ED_view3d_check_mats_rv3d(rv3d);
+ return ED_view3d_project_float_ex(ar, rv3d->persmatob, true, co, r_co, flag);
}
-
-
/* More Generic Window/Ray/Vector projection functions
* *************************************************** */
float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3])
{
- return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize * U.pixelsize;
+ return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize * U.pixelsize;
}
float ED_view3d_pixel_size_no_ui_scale(const RegionView3D *rv3d, const float co[3])
{
- return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize;
+ return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize;
}
/**
@@ -286,70 +316,72 @@ float ED_view3d_pixel_size_no_ui_scale(const RegionView3D *rv3d, const float co[
*/
float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3], bool *r_flip)
{
- float zfac = mul_project_m4_v3_zfac((float (*)[4])rv3d->persmat, co);
-
- if (r_flip) {
- *r_flip = (zfac < 0.0f);
- }
-
- /* if x,y,z is exactly the viewport offset, zfac is 0 and we don't want that
- * (accounting for near zero values) */
- if (zfac < 1.e-6f && zfac > -1.e-6f) {
- zfac = 1.0f;
- }
-
- /* Negative zfac means x, y, z was behind the camera (in perspective).
- * This gives flipped directions, so revert back to ok default case. */
- if (zfac < 0.0f) {
- zfac = -zfac;
- }
-
- return zfac;
-}
-
-static void view3d_win_to_ray_segment(
- struct Depsgraph *depsgraph,
- const ARegion *ar, const View3D *v3d, const float mval[2],
- float r_ray_co[3], float r_ray_dir[3], float r_ray_start[3], float r_ray_end[3])
-{
- RegionView3D *rv3d = ar->regiondata;
- float _ray_co[3], _ray_dir[3], start_offset, end_offset;
-
- if (!r_ray_co) {
- r_ray_co = _ray_co;
- }
- if (!r_ray_dir) {
- 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);
-
- if ((rv3d->is_persp == false) && (rv3d->persp != RV3D_CAMOB)) {
- end_offset = v3d->clip_end / 2.0f;
- start_offset = -end_offset;
- }
- else {
- ED_view3d_clip_range_get(depsgraph, v3d, rv3d, &start_offset, &end_offset, false);
- }
-
- if (r_ray_start) {
- madd_v3_v3v3fl(r_ray_start, r_ray_co, r_ray_dir, start_offset);
- }
- if (r_ray_end) {
- madd_v3_v3v3fl(r_ray_end, r_ray_co, r_ray_dir, end_offset);
- }
+ float zfac = mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co);
+
+ if (r_flip) {
+ *r_flip = (zfac < 0.0f);
+ }
+
+ /* if x,y,z is exactly the viewport offset, zfac is 0 and we don't want that
+ * (accounting for near zero values) */
+ if (zfac < 1.e-6f && zfac > -1.e-6f) {
+ zfac = 1.0f;
+ }
+
+ /* Negative zfac means x, y, z was behind the camera (in perspective).
+ * This gives flipped directions, so revert back to ok default case. */
+ if (zfac < 0.0f) {
+ zfac = -zfac;
+ }
+
+ return zfac;
+}
+
+static void view3d_win_to_ray_segment(struct Depsgraph *depsgraph,
+ const ARegion *ar,
+ const View3D *v3d,
+ const float mval[2],
+ float r_ray_co[3],
+ float r_ray_dir[3],
+ float r_ray_start[3],
+ float r_ray_end[3])
+{
+ RegionView3D *rv3d = ar->regiondata;
+ float _ray_co[3], _ray_dir[3], start_offset, end_offset;
+
+ if (!r_ray_co) {
+ r_ray_co = _ray_co;
+ }
+ if (!r_ray_dir) {
+ 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);
+
+ if ((rv3d->is_persp == false) && (rv3d->persp != RV3D_CAMOB)) {
+ end_offset = v3d->clip_end / 2.0f;
+ start_offset = -end_offset;
+ }
+ else {
+ ED_view3d_clip_range_get(depsgraph, v3d, rv3d, &start_offset, &end_offset, false);
+ }
+
+ if (r_ray_start) {
+ madd_v3_v3v3fl(r_ray_start, r_ray_co, r_ray_dir, start_offset);
+ }
+ if (r_ray_end) {
+ madd_v3_v3v3fl(r_ray_end, r_ray_co, r_ray_dir, end_offset);
+ }
}
bool ED_view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float ray_end[3])
{
- if ((rv3d->rflag & RV3D_CLIPPING) &&
- (clip_segment_v3_plane_n(ray_start, ray_end, rv3d->clip, 6,
- ray_start, ray_end) == false))
- {
- return false;
- }
- return true;
+ if ((rv3d->rflag & RV3D_CLIPPING) &&
+ (clip_segment_v3_plane_n(ray_start, ray_end, rv3d->clip, 6, ray_start, ray_end) == false)) {
+ return false;
+ }
+ return true;
}
/**
@@ -368,21 +400,26 @@ bool ED_view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float
* \param do_clip_planes: Optionally clip the start of the ray by the view clipping planes.
* \return success, false if the ray is totally clipped.
*/
-bool ED_view3d_win_to_ray_clipped_ex(
- struct Depsgraph *depsgraph,
- const ARegion *ar, const View3D *v3d, const float mval[2],
- float r_ray_co[3], float r_ray_normal[3], float r_ray_start[3], bool do_clip_planes)
+bool ED_view3d_win_to_ray_clipped_ex(struct Depsgraph *depsgraph,
+ const ARegion *ar,
+ const View3D *v3d,
+ const float mval[2],
+ float r_ray_co[3],
+ float r_ray_normal[3],
+ float r_ray_start[3],
+ bool do_clip_planes)
{
- float ray_end[3];
+ float ray_end[3];
- view3d_win_to_ray_segment(depsgraph, ar, v3d, mval, r_ray_co, r_ray_normal, r_ray_start, ray_end);
+ view3d_win_to_ray_segment(
+ depsgraph, ar, 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);
- }
+ /* bounds clipping */
+ if (do_clip_planes) {
+ return ED_view3d_clip_segment(ar->regiondata, r_ray_start, ray_end);
+ }
- return true;
+ return true;
}
/**
@@ -398,12 +435,16 @@ bool ED_view3d_win_to_ray_clipped_ex(
* \param do_clip_planes: Optionally clip the start of the ray by the view clipping planes.
* \return success, false if the ray is totally clipped.
*/
-bool ED_view3d_win_to_ray_clipped(
- struct Depsgraph *depsgraph,
- const ARegion *ar, const View3D *v3d, const float mval[2],
- float r_ray_start[3], float r_ray_normal[3], const bool do_clip_planes)
+bool ED_view3d_win_to_ray_clipped(struct Depsgraph *depsgraph,
+ const ARegion *ar,
+ const View3D *v3d,
+ const float mval[2],
+ float r_ray_start[3],
+ float r_ray_normal[3],
+ 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);
+ return ED_view3d_win_to_ray_clipped_ex(
+ depsgraph, ar, v3d, mval, NULL, r_ray_normal, r_ray_start, do_clip_planes);
}
/**
@@ -416,12 +457,13 @@ bool ED_view3d_win_to_ray_clipped(
*
* \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, const float mval[2],
- float r_ray_start[3], float r_ray_normal[3])
+void ED_view3d_win_to_ray(const ARegion *ar,
+ 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(ar, mval, r_ray_start);
+ ED_view3d_win_to_vector(ar, mval, r_ray_normal);
}
/**
@@ -433,57 +475,57 @@ void ED_view3d_win_to_ray(
*/
void ED_view3d_global_to_vector(const RegionView3D *rv3d, const float coord[3], float vec[3])
{
- if (rv3d->is_persp) {
- float p1[4], p2[4];
+ if (rv3d->is_persp) {
+ float p1[4], p2[4];
- copy_v3_v3(p1, coord);
- p1[3] = 1.0f;
- copy_v3_v3(p2, p1);
- p2[3] = 1.0f;
- mul_m4_v4((float (*)[4])rv3d->viewmat, p2);
+ copy_v3_v3(p1, coord);
+ p1[3] = 1.0f;
+ copy_v3_v3(p2, p1);
+ p2[3] = 1.0f;
+ mul_m4_v4((float(*)[4])rv3d->viewmat, p2);
- mul_v3_fl(p2, 2.0f);
+ mul_v3_fl(p2, 2.0f);
- mul_m4_v4((float (*)[4])rv3d->viewinv, p2);
+ mul_m4_v4((float(*)[4])rv3d->viewinv, p2);
- sub_v3_v3v3(vec, p1, p2);
- }
- else {
- copy_v3_v3(vec, rv3d->viewinv[2]);
- }
- normalize_v3(vec);
+ sub_v3_v3v3(vec, p1, p2);
+ }
+ else {
+ copy_v3_v3(vec, rv3d->viewinv[2]);
+ }
+ normalize_v3(vec);
}
/* very similar to ED_view3d_win_to_3d() but has no advantage, de-duplicating */
#if 0
bool view3d_get_view_aligned_coordinate(ARegion *ar, float fp[3], const int mval[2], const bool do_fallback)
{
- RegionView3D *rv3d = ar->regiondata;
- float dvec[3];
- int mval_cpy[2];
- eV3DProjStatus ret;
-
- ret = ED_view3d_project_int_global(ar, 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);
- sub_v3_v3(fp, dvec);
-
- return true;
- }
- else {
- /* fallback to the view center */
- if (do_fallback) {
- negate_v3_v3(fp, rv3d->ofs);
- return view3d_get_view_aligned_coordinate(ar, fp, mval, false);
- }
- else {
- return false;
- }
- }
+ RegionView3D *rv3d = ar->regiondata;
+ float dvec[3];
+ int mval_cpy[2];
+ eV3DProjStatus ret;
+
+ ret = ED_view3d_project_int_global(ar, 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);
+ sub_v3_v3(fp, dvec);
+
+ return true;
+ }
+ else {
+ /* fallback to the view center */
+ if (do_fallback) {
+ negate_v3_v3(fp, rv3d->ofs);
+ return view3d_get_view_aligned_coordinate(ar, fp, mval, false);
+ }
+ else {
+ return false;
+ }
+ }
}
#endif
@@ -494,90 +536,93 @@ bool view3d_get_view_aligned_coordinate(ARegion *ar, float fp[3], const int mval
* \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 float depth_pt[3], const float mval[2],
- float r_out[3])
-{
- RegionView3D *rv3d = ar->regiondata;
-
- float ray_origin[3];
- float ray_direction[3];
- float lambda;
-
- if (rv3d->is_persp) {
- float plane[4];
-
- copy_v3_v3(ray_origin, rv3d->viewinv[3]);
- ED_view3d_win_to_vector(ar, 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, so apply the unsigned factor instead */
- plane_from_point_normal_v3(plane, depth_pt, rv3d->viewinv[2]);
-
- isect_ray_plane_v3(ray_origin, ray_direction, plane, &lambda, false);
- 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;
-
- 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 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 shiftx = cam->shiftx * 0.5f * (sensor_fit == CAMERA_SENSOR_FIT_HOR ? 1.0f : aspy);
- const float shifty = cam->shifty * 0.5f * (sensor_fit == CAMERA_SENSOR_FIT_HOR ? aspx : 1.0f);
-
- dx += (rv3d->camdx + shiftx) * zoomfac;
- dy += (rv3d->camdy + shifty) * zoomfac;
- }
- ray_origin[0] = (rv3d->persinv[0][0] * dx) + (rv3d->persinv[1][0] * dy) + rv3d->viewinv[3][0];
- ray_origin[1] = (rv3d->persinv[0][1] * dx) + (rv3d->persinv[1][1] * dy) + rv3d->viewinv[3][1];
- ray_origin[2] = (rv3d->persinv[0][2] * dx) + (rv3d->persinv[1][2] * dy) + rv3d->viewinv[3][2];
-
- copy_v3_v3(ray_direction, rv3d->viewinv[2]);
- lambda = ray_point_factor_v3(depth_pt, ray_origin, ray_direction);
- }
-
- madd_v3_v3v3fl(r_out, ray_origin, ray_direction, lambda);
-}
-
-void ED_view3d_win_to_3d_int(
- const View3D *v3d, const ARegion *ar,
- 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);
-}
-
-bool ED_view3d_win_to_3d_on_plane(
- const ARegion *ar,
- 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);
- 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);
- return true;
- }
- return false;
+void ED_view3d_win_to_3d(const View3D *v3d,
+ const ARegion *ar,
+ const float depth_pt[3],
+ const float mval[2],
+ float r_out[3])
+{
+ RegionView3D *rv3d = ar->regiondata;
+
+ float ray_origin[3];
+ float ray_direction[3];
+ float lambda;
+
+ if (rv3d->is_persp) {
+ float plane[4];
+
+ copy_v3_v3(ray_origin, rv3d->viewinv[3]);
+ ED_view3d_win_to_vector(ar, 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, so apply the unsigned factor instead */
+ plane_from_point_normal_v3(plane, depth_pt, rv3d->viewinv[2]);
+
+ isect_ray_plane_v3(ray_origin, ray_direction, plane, &lambda, false);
+ 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;
+
+ 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 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 shiftx = cam->shiftx * 0.5f *
+ (sensor_fit == CAMERA_SENSOR_FIT_HOR ? 1.0f : aspy);
+ const float shifty = cam->shifty * 0.5f *
+ (sensor_fit == CAMERA_SENSOR_FIT_HOR ? aspx : 1.0f);
+
+ dx += (rv3d->camdx + shiftx) * zoomfac;
+ dy += (rv3d->camdy + shifty) * zoomfac;
+ }
+ ray_origin[0] = (rv3d->persinv[0][0] * dx) + (rv3d->persinv[1][0] * dy) + rv3d->viewinv[3][0];
+ ray_origin[1] = (rv3d->persinv[0][1] * dx) + (rv3d->persinv[1][1] * dy) + rv3d->viewinv[3][1];
+ ray_origin[2] = (rv3d->persinv[0][2] * dx) + (rv3d->persinv[1][2] * dy) + rv3d->viewinv[3][2];
+
+ copy_v3_v3(ray_direction, rv3d->viewinv[2]);
+ lambda = ray_point_factor_v3(depth_pt, ray_origin, ray_direction);
+ }
+
+ madd_v3_v3v3fl(r_out, ray_origin, ray_direction, lambda);
+}
+
+void ED_view3d_win_to_3d_int(const View3D *v3d,
+ const ARegion *ar,
+ 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);
+}
+
+bool ED_view3d_win_to_3d_on_plane(const ARegion *ar,
+ 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);
+ 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);
+ return true;
+ }
+ 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])
+ const ARegion *ar, 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);
+ 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);
}
/**
@@ -590,15 +635,15 @@ bool ED_view3d_win_to_3d_on_plane_int(
*/
void ED_view3d_win_to_delta(const ARegion *ar, const float mval[2], float out[3], const float zfac)
{
- RegionView3D *rv3d = ar->regiondata;
- float dx, dy;
+ RegionView3D *rv3d = ar->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 / ar->winx;
+ dy = 2.0f * mval[1] * zfac / ar->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);
- out[2] = (rv3d->persinv[0][2] * dx + rv3d->persinv[1][2] * dy);
+ out[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy);
+ out[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy);
+ out[2] = (rv3d->persinv[0][2] * dx + rv3d->persinv[1][2] * dy);
}
/**
@@ -613,23 +658,23 @@ void ED_view3d_win_to_delta(const ARegion *ar, const float mval[2], float out[3]
*/
void ED_view3d_win_to_origin(const ARegion *ar, const float mval[2], float out[3])
{
- RegionView3D *rv3d = ar->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;
+ RegionView3D *rv3d = ar->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;
- if (rv3d->persp == RV3D_CAMOB) {
- out[2] = -1.0f;
- }
- else {
- out[2] = 0.0f;
- }
+ if (rv3d->persp == RV3D_CAMOB) {
+ out[2] = -1.0f;
+ }
+ else {
+ out[2] = 0.0f;
+ }
- mul_project_m4_v3(rv3d->persinv, out);
- }
+ mul_project_m4_v3(rv3d->persinv, out);
+ }
}
/**
@@ -647,19 +692,19 @@ void ED_view3d_win_to_origin(const ARegion *ar, const float mval[2], float out[3
*/
void ED_view3d_win_to_vector(const ARegion *ar, const float mval[2], float out[3])
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = ar->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[2] = -0.5f;
- mul_project_m4_v3(rv3d->persinv, out);
- sub_v3_v3(out, rv3d->viewinv[3]);
- }
- else {
- negate_v3_v3(out, rv3d->viewinv[2]);
- }
- normalize_v3(out);
+ 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[2] = -0.5f;
+ mul_project_m4_v3(rv3d->persinv, out);
+ sub_v3_v3(out, rv3d->viewinv[3]);
+ }
+ else {
+ negate_v3_v3(out, rv3d->viewinv[2]);
+ }
+ normalize_v3(out);
}
/**
@@ -676,19 +721,22 @@ void ED_view3d_win_to_vector(const ARegion *ar, const float mval[2], float out[3
* \param do_clip_planes: Optionally clip the ray by the view clipping planes.
* \return success, false if the segment is totally clipped.
*/
-bool ED_view3d_win_to_segment_clipped(
- struct Depsgraph *depsgraph,
- const ARegion *ar, View3D *v3d, const float mval[2],
- float r_ray_start[3], float r_ray_end[3], const bool do_clip_planes)
+bool ED_view3d_win_to_segment_clipped(struct Depsgraph *depsgraph,
+ const ARegion *ar,
+ 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, ar, 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);
- }
+ /* bounds clipping */
+ if (do_clip_planes) {
+ return ED_view3d_clip_segment((RegionView3D *)ar->regiondata, r_ray_start, r_ray_end);
+ }
- return true;
+ return true;
}
/* Utility functions for projection
@@ -696,18 +744,20 @@ bool ED_view3d_win_to_segment_clipped(
void ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, Object *ob, float pmat[4][4])
{
- float vmat[4][4];
+ float vmat[4][4];
- mul_m4_m4m4(vmat, (float (*)[4])rv3d->viewmat, ob->obmat);
- mul_m4_m4m4(pmat, (float (*)[4])rv3d->winmat, vmat);
+ mul_m4_m4m4(vmat, (float(*)[4])rv3d->viewmat, ob->obmat);
+ mul_m4_m4m4(pmat, (float(*)[4])rv3d->winmat, vmat);
}
-void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d, float obmat[4][4], float pmat[4][4])
+void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d,
+ float obmat[4][4],
+ float pmat[4][4])
{
- float vmat[4][4];
+ float vmat[4][4];
- mul_m4_m4m4(vmat, (float (*)[4])rv3d->viewmat, obmat);
- mul_m4_m4m4(pmat, (float (*)[4])rv3d->winmat, vmat);
+ mul_m4_m4m4(vmat, (float(*)[4])rv3d->viewmat, obmat);
+ mul_m4_m4m4(pmat, (float(*)[4])rv3d->winmat, vmat);
}
/**
@@ -715,18 +765,19 @@ void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d, float obm
* a point in world space. */
void ED_view3d_project(const struct ARegion *ar, const float world[3], float region[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};
+ // 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};
- GPU_matrix_project(world, rv3d->viewmat, rv3d->winmat, viewport, region);
+ GPU_matrix_project(world, rv3d->viewmat, rv3d->winmat, viewport, region);
}
-bool ED_view3d_unproject(const struct ARegion *ar, float regionx, float regiony, float regionz, float world[3])
+bool ED_view3d_unproject(
+ const struct ARegion *ar, 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 = ar->regiondata;
+ int viewport[4] = {0, 0, ar->winx, ar->winy};
+ float region[3] = {regionx, regiony, regionz};
- return GPU_matrix_unproject(region, rv3d->viewmat, rv3d->winmat, viewport, world);
+ return GPU_matrix_unproject(region, 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 f57b31b2ed2..c0f2e563365 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -21,7 +21,6 @@
* \ingroup spview3d
*/
-
#include <string.h>
#include <stdio.h>
#include <math.h>
@@ -99,50 +98,49 @@
#include "GPU_glew.h"
#include "GPU_matrix.h"
-#include "view3d_intern.h" /* own include */
+#include "view3d_intern.h" /* own include */
// #include "PIL_time_utildefines.h"
-
/* -------------------------------------------------------------------- */
/** \name Public Utilities
* \{ */
float ED_view3d_select_dist_px(void)
{
- return 75.0f * U.pixelsize;
+ return 75.0f * U.pixelsize;
}
/* TODO: should return whether there is valid context to continue */
void ED_view3d_viewcontext_init(bContext *C, ViewContext *vc)
{
- memset(vc, 0, sizeof(ViewContext));
- vc->C = C;
- vc->ar = CTX_wm_region(C);
- vc->bmain = CTX_data_main(C);
- vc->depsgraph = CTX_data_depsgraph(C);
- vc->scene = CTX_data_scene(C);
- vc->view_layer = CTX_data_view_layer(C);
- vc->v3d = CTX_wm_view3d(C);
- vc->win = CTX_wm_window(C);
- vc->rv3d = CTX_wm_region_view3d(C);
- vc->obact = CTX_data_active_object(C);
- vc->obedit = CTX_data_edit_object(C);
+ memset(vc, 0, sizeof(ViewContext));
+ vc->C = C;
+ vc->ar = CTX_wm_region(C);
+ vc->bmain = CTX_data_main(C);
+ vc->depsgraph = CTX_data_depsgraph(C);
+ vc->scene = CTX_data_scene(C);
+ vc->view_layer = CTX_data_view_layer(C);
+ vc->v3d = CTX_wm_view3d(C);
+ vc->win = CTX_wm_window(C);
+ vc->rv3d = CTX_wm_region_view3d(C);
+ vc->obact = CTX_data_active_object(C);
+ vc->obedit = CTX_data_edit_object(C);
}
void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact)
{
- vc->obact = obact;
- if (vc->obedit) {
- BLI_assert(BKE_object_is_in_editmode(obact));
- vc->obedit = obact;
- /* previous selections are now invalid. */
- vc->v3d->flag |= V3D_INVALID_BACKBUF;
+ vc->obact = obact;
+ if (vc->obedit) {
+ BLI_assert(BKE_object_is_in_editmode(obact));
+ vc->obedit = obact;
+ /* previous selections are now invalid. */
+ vc->v3d->flag |= V3D_INVALID_BACKBUF;
- if (vc->em) {
- vc->em = BKE_editmesh_from_object(vc->obedit);
- }
- }
+ if (vc->em) {
+ vc->em = BKE_editmesh_from_object(vc->obedit);
+ }
+ }
}
/** \} */
@@ -153,31 +151,31 @@ 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) {
- if (base->flag & BASE_SELECTED) {
- if (BASE_SELECTABLE(v3d, base)) {
- ED_object_base_select(base, BA_DESELECT);
- changed = true;
- }
- }
- }
- return changed;
+ bool changed = false;
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->flag & BASE_SELECTED) {
+ if (BASE_SELECTABLE(v3d, base)) {
+ ED_object_base_select(base, BA_DESELECT);
+ changed = true;
+ }
+ }
+ }
+ return changed;
}
/* deselect all except b */
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) {
- if (base->flag & BASE_SELECTED) {
- if (b != base) {
- ED_object_base_select(base, BA_DESELECT);
- changed = true;
- }
- }
- }
- return changed;
+ bool changed = false;
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->flag & BASE_SELECTED) {
+ if (b != base) {
+ ED_object_base_select(base, BA_DESELECT);
+ changed = true;
+ }
+ }
+ }
+ return changed;
}
/** \} */
@@ -188,114 +186,114 @@ static bool object_deselect_all_except(ViewLayer *view_layer, Base *b)
static bool edbm_backbuf_check_and_select_verts(BMEditMesh *em, const eSelectOp sel_op)
{
- BMVert *eve;
- BMIter iter;
- uint index = bm_wireoffs;
- bool changed = false;
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT);
- const bool is_inside = EDBM_backbuf_check(index);
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- BM_vert_select_set(em->bm, eve, sel_op_result);
- changed = true;
- }
- }
- index++;
- }
- return changed;
+ BMVert *eve;
+ BMIter iter;
+ uint index = bm_wireoffs;
+ bool changed = false;
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+ const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT);
+ const bool is_inside = EDBM_backbuf_check(index);
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ BM_vert_select_set(em->bm, eve, sel_op_result);
+ changed = true;
+ }
+ }
+ index++;
+ }
+ return changed;
}
static bool edbm_backbuf_check_and_select_edges(BMEditMesh *em, const eSelectOp sel_op)
{
- BMEdge *eed;
- BMIter iter;
- uint index = bm_solidoffs;
- bool changed = false;
-
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
- const bool is_inside = EDBM_backbuf_check(index);
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- BM_edge_select_set(em->bm, eed, sel_op_result);
- changed = true;
- }
- }
- index++;
- }
- return changed;
+ BMEdge *eed;
+ BMIter iter;
+ uint index = bm_solidoffs;
+ bool changed = false;
+
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+ const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
+ const bool is_inside = EDBM_backbuf_check(index);
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ BM_edge_select_set(em->bm, eed, sel_op_result);
+ changed = true;
+ }
+ }
+ index++;
+ }
+ return changed;
}
static bool edbm_backbuf_check_and_select_faces(BMEditMesh *em, const eSelectOp sel_op)
{
- BMFace *efa;
- BMIter iter;
- uint index = 1;
- bool changed = false;
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT);
- const bool is_inside = EDBM_backbuf_check(index);
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- BM_face_select_set(em->bm, efa, sel_op_result);
- changed = true;
- }
- }
- index++;
- }
- return changed;
+ BMFace *efa;
+ BMIter iter;
+ uint index = 1;
+ bool changed = false;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT);
+ const bool is_inside = EDBM_backbuf_check(index);
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ BM_face_select_set(em->bm, efa, sel_op_result);
+ changed = true;
+ }
+ }
+ index++;
+ }
+ return changed;
}
/* object mode, edbm_ prefix is confusing here, rename? */
static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me, const eSelectOp sel_op)
{
- MVert *mv = me->mvert;
- uint index;
- bool changed = false;
-
- if (mv) {
- for (index = 1; index <= me->totvert; index++, mv++) {
- if (!(mv->flag & ME_HIDE)) {
- const bool is_select = mv->flag & SELECT;
- const bool is_inside = EDBM_backbuf_check(index);
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT);
- changed = true;
- }
- }
- }
- }
- return changed;
+ MVert *mv = me->mvert;
+ uint index;
+ bool changed = false;
+
+ if (mv) {
+ for (index = 1; index <= me->totvert; index++, mv++) {
+ if (!(mv->flag & ME_HIDE)) {
+ const bool is_select = mv->flag & SELECT;
+ const bool is_inside = EDBM_backbuf_check(index);
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT);
+ changed = true;
+ }
+ }
+ }
+ }
+ return changed;
}
/* object mode, edbm_ prefix is confusing here, rename? */
static bool edbm_backbuf_check_and_select_tfaces(Mesh *me, const eSelectOp sel_op)
{
- MPoly *mpoly = me->mpoly;
- uint index;
- bool changed = false;
-
- if (mpoly) {
- for (index = 1; index <= me->totpoly; index++, mpoly++) {
- if (!(mpoly->flag & ME_HIDE)) {
- const bool is_select = mpoly->flag & ME_FACE_SEL;
- const bool is_inside = EDBM_backbuf_check(index);
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(mpoly->flag, sel_op_result, ME_FACE_SEL);
- changed = true;
- }
- }
- }
- }
- return changed;
+ MPoly *mpoly = me->mpoly;
+ uint index;
+ bool changed = false;
+
+ if (mpoly) {
+ for (index = 1; index <= me->totpoly; index++, mpoly++) {
+ if (!(mpoly->flag & ME_HIDE)) {
+ const bool is_select = mpoly->flag & ME_FACE_SEL;
+ const bool is_inside = EDBM_backbuf_check(index);
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ SET_FLAG_FROM_TEST(mpoly->flag, sel_op_result, ME_FACE_SEL);
+ changed = true;
+ }
+ }
+ }
+ }
+ return changed;
}
/** \} */
@@ -305,871 +303,911 @@ static bool edbm_backbuf_check_and_select_tfaces(Mesh *me, const eSelectOp sel_o
* \{ */
typedef struct LassoSelectUserData {
- ViewContext *vc;
- const rcti *rect;
- const rctf *rect_fl;
- rctf _rect_fl;
- const int (*mcords)[2];
- int moves;
- eSelectOp sel_op;
-
- /* runtime */
- int pass;
- bool is_done;
- bool is_changed;
+ ViewContext *vc;
+ const rcti *rect;
+ const rctf *rect_fl;
+ rctf _rect_fl;
+ const int (*mcords)[2];
+ int moves;
+ eSelectOp sel_op;
+
+ /* runtime */
+ int pass;
+ bool is_done;
+ bool is_changed;
} LassoSelectUserData;
-static void view3d_userdata_lassoselect_init(
- LassoSelectUserData *r_data,
- ViewContext *vc, const rcti *rect, const int (*mcords)[2],
- const int moves, const eSelectOp sel_op)
+static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data,
+ ViewContext *vc,
+ const rcti *rect,
+ const int (*mcords)[2],
+ const int moves,
+ const eSelectOp sel_op)
{
- r_data->vc = vc;
+ r_data->vc = vc;
- r_data->rect = rect;
- r_data->rect_fl = &r_data->_rect_fl;
- BLI_rctf_rcti_copy(&r_data->_rect_fl, rect);
+ r_data->rect = rect;
+ 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->sel_op = sel_op;
+ r_data->mcords = mcords;
+ r_data->moves = moves;
+ r_data->sel_op = sel_op;
- /* runtime */
- r_data->pass = 0;
- r_data->is_done = false;
- r_data->is_changed = false;
+ /* runtime */
+ r_data->pass = 0;
+ r_data->is_done = false;
+ r_data->is_changed = false;
}
static bool view3d_selectable_data(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if (!ED_operator_region_view3d_active(C)) {
- return 0;
- }
+ if (!ED_operator_region_view3d_active(C)) {
+ return 0;
+ }
- if (ob) {
- if (ob->mode & OB_MODE_EDIT) {
- if (ob->type == OB_FONT) {
- return 0;
- }
- }
- else {
- if ((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) &&
- !BKE_paint_select_elem_test(ob))
- {
- return 0;
- }
- }
- }
+ if (ob) {
+ if (ob->mode & OB_MODE_EDIT) {
+ if (ob->type == OB_FONT) {
+ return 0;
+ }
+ }
+ else {
+ if ((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) &&
+ !BKE_paint_select_elem_test(ob)) {
+ return 0;
+ }
+ }
+ }
- return 1;
+ return 1;
}
-
/* helper also for box_select */
static bool edge_fully_inside_rect(const rctf *rect, const float v1[2], const float v2[2])
{
- return BLI_rctf_isect_pt_v(rect, v1) && BLI_rctf_isect_pt_v(rect, v2);
+ return BLI_rctf_isect_pt_v(rect, v1) && BLI_rctf_isect_pt_v(rect, v2);
}
static bool edge_inside_rect(const rctf *rect, const float v1[2], const float v2[2])
{
- int d1, d2, d3, d4;
-
- /* check points in rect */
- if (edge_fully_inside_rect(rect, v1, v2)) {
- return 1;
- }
-
- /* check points completely out rect */
- if (v1[0] < rect->xmin && v2[0] < rect->xmin) {
- return 0;
- }
- if (v1[0] > rect->xmax && v2[0] > rect->xmax) {
- return 0;
- }
- if (v1[1] < rect->ymin && v2[1] < rect->ymin) {
- return 0;
- }
- if (v1[1] > rect->ymax && v2[1] > rect->ymax) {
- return 0;
- }
-
- /* simple check lines intersecting. */
- d1 = (v1[1] - v2[1]) * (v1[0] - rect->xmin) + (v2[0] - v1[0]) * (v1[1] - rect->ymin);
- d2 = (v1[1] - v2[1]) * (v1[0] - rect->xmin) + (v2[0] - v1[0]) * (v1[1] - rect->ymax);
- d3 = (v1[1] - v2[1]) * (v1[0] - rect->xmax) + (v2[0] - v1[0]) * (v1[1] - rect->ymax);
- d4 = (v1[1] - v2[1]) * (v1[0] - rect->xmax) + (v2[0] - v1[0]) * (v1[1] - rect->ymin);
-
- if (d1 < 0 && d2 < 0 && d3 < 0 && d4 < 0) {
- return 0;
- }
- if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0) {
- return 0;
- }
-
- return 1;
-}
-
-static void do_lasso_select_pose__do_tag(
- void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2])
-{
- LassoSelectUserData *data = userData;
- bArmature *arm = data->vc->obact->data;
-
- if (PBONE_SELECTABLE(arm, pchan->bone)) {
- bool is_point_done = false;
- int points_proj_tot = 0;
-
- /* project head location to screenspace */
- 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))
- {
- is_point_done = true;
- }
- }
-
- /* project tail location to screenspace */
- 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))
- {
- 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)))
- {
- pchan->bone->flag |= BONE_DONE;
- }
- data->is_changed |= is_point_done;
- }
+ int d1, d2, d3, d4;
+
+ /* check points in rect */
+ if (edge_fully_inside_rect(rect, v1, v2)) {
+ return 1;
+ }
+
+ /* check points completely out rect */
+ if (v1[0] < rect->xmin && v2[0] < rect->xmin) {
+ return 0;
+ }
+ if (v1[0] > rect->xmax && v2[0] > rect->xmax) {
+ return 0;
+ }
+ if (v1[1] < rect->ymin && v2[1] < rect->ymin) {
+ return 0;
+ }
+ if (v1[1] > rect->ymax && v2[1] > rect->ymax) {
+ return 0;
+ }
+
+ /* simple check lines intersecting. */
+ d1 = (v1[1] - v2[1]) * (v1[0] - rect->xmin) + (v2[0] - v1[0]) * (v1[1] - rect->ymin);
+ d2 = (v1[1] - v2[1]) * (v1[0] - rect->xmin) + (v2[0] - v1[0]) * (v1[1] - rect->ymax);
+ d3 = (v1[1] - v2[1]) * (v1[0] - rect->xmax) + (v2[0] - v1[0]) * (v1[1] - rect->ymax);
+ d4 = (v1[1] - v2[1]) * (v1[0] - rect->xmax) + (v2[0] - v1[0]) * (v1[1] - rect->ymin);
+
+ if (d1 < 0 && d2 < 0 && d3 < 0 && d4 < 0) {
+ return 0;
+ }
+ if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static void do_lasso_select_pose__do_tag(void *userData,
+ struct bPoseChannel *pchan,
+ const float screen_co_a[2],
+ const float screen_co_b[2])
+{
+ LassoSelectUserData *data = userData;
+ bArmature *arm = data->vc->obact->data;
+
+ if (PBONE_SELECTABLE(arm, pchan->bone)) {
+ bool is_point_done = false;
+ int points_proj_tot = 0;
+
+ /* project head location to screenspace */
+ 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)) {
+ is_point_done = true;
+ }
+ }
+
+ /* project tail location to screenspace */
+ 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)) {
+ 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))) {
+ 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)
{
- ViewContext vc_tmp;
- LassoSelectUserData data;
- rcti rect;
+ ViewContext vc_tmp;
+ LassoSelectUserData data;
+ rcti rect;
- if ((ob->type != OB_ARMATURE) || (ob->pose == NULL)) {
- return;
- }
+ if ((ob->type != OB_ARMATURE) || (ob->pose == NULL)) {
+ return;
+ }
- vc_tmp = *vc;
- vc_tmp.obact = ob;
+ vc_tmp = *vc;
+ vc_tmp.obact = ob;
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcords, moves);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, 0);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, 0);
- ED_view3d_init_mats_rv3d(vc_tmp.obact, vc->rv3d);
+ ED_view3d_init_mats_rv3d(vc_tmp.obact, vc->rv3d);
- pose_foreachScreenBone(&vc_tmp, do_lasso_select_pose__do_tag, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ pose_foreachScreenBone(&vc_tmp, do_lasso_select_pose__do_tag, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
-static bool do_lasso_select_objects(
- ViewContext *vc, const int mcords[][2], const short moves,
- const eSelectOp sel_op)
+static bool do_lasso_select_objects(ViewContext *vc,
+ const int mcords[][2],
+ const short moves,
+ const eSelectOp sel_op)
{
- View3D *v3d = vc->v3d;
- Base *base;
+ View3D *v3d = vc->v3d;
+ Base *base;
- bool changed = false;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- changed |= object_deselect_all_visible(vc->view_layer, vc->v3d);
- }
+ bool changed = false;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ changed |= object_deselect_all_visible(vc->view_layer, vc->v3d);
+ }
- 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) &&
- BLI_lasso_is_point_inside(mcords, moves, 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);
- changed = true;
- }
- }
- }
+ 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) &&
+ BLI_lasso_is_point_inside(
+ mcords, moves, 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);
+ changed = true;
+ }
+ }
+ }
- if (changed) {
- DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
- WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, vc->scene);
- }
- return changed;
+ if (changed) {
+ DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
+ WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, vc->scene);
+ }
+ return changed;
}
-
/**
* Use for lasso & box select.
*/
static Base **do_pose_tag_select_op_prepare(ViewContext *vc, uint *r_bases_len)
{
- Base **bases = NULL;
- BLI_array_declare(bases);
- 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) {
- Bone *bone = pchan->bone;
- bone->flag &= ~BONE_DONE;
- }
- arm->id.tag |= LIB_TAG_DOIT;
- ob_iter->id.tag &= ~LIB_TAG_DOIT;
- BLI_array_append(bases, base_iter);
- }
- FOREACH_BASE_IN_MODE_END;
- *r_bases_len = BLI_array_len(bases);
- return bases;
+ Base **bases = NULL;
+ BLI_array_declare(bases);
+ 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) {
+ Bone *bone = pchan->bone;
+ bone->flag &= ~BONE_DONE;
+ }
+ arm->id.tag |= LIB_TAG_DOIT;
+ ob_iter->id.tag &= ~LIB_TAG_DOIT;
+ BLI_array_append(bases, base_iter);
+ }
+ FOREACH_BASE_IN_MODE_END;
+ *r_bases_len = BLI_array_len(bases);
+ return bases;
}
static bool do_pose_tag_select_op_exec(Base **bases, const uint bases_len, const eSelectOp sel_op)
{
- bool changed_multi = false;
-
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- for (int i = 0; i < bases_len; i++) {
- Base *base_iter = bases[i];
- Object *ob_iter = base_iter->object;
- if (ED_pose_deselect_all(ob_iter, SEL_DESELECT, false)) {
- ED_pose_bone_select_tag_update(ob_iter);
- changed_multi = true;
- }
- }
- }
-
- for (int i = 0; i < bases_len; i++) {
- Base *base_iter = bases[i];
- Object *ob_iter = base_iter->object;
- bArmature *arm = ob_iter->data;
-
- /* Don't handle twice. */
- if (arm->id.tag & LIB_TAG_DOIT) {
- arm->id.tag &= ~LIB_TAG_DOIT;
- }
- else {
- continue;
- }
-
- bool changed = true;
- for (bPoseChannel *pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) {
- Bone *bone = pchan->bone;
- if ((bone->flag & BONE_UNSELECTABLE) == 0) {
- const bool is_select = bone->flag & BONE_SELECTED;
- const bool is_inside = bone->flag & BONE_DONE;
- 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(bone->flag, sel_op_result, BONE_SELECTED);
- if (sel_op_result == 0) {
- if (arm->act_bone == bone) {
- arm->act_bone = NULL;
- }
- }
- changed = true;
- }
- }
- }
- if (changed) {
- ED_pose_bone_select_tag_update(ob_iter);
- changed_multi = true;
- }
- }
- return changed_multi;
-}
-
-static bool do_lasso_select_pose(
- ViewContext *vc, const int mcords[][2], const short moves,
- const eSelectOp sel_op)
-{
- uint bases_len;
- Base **bases = do_pose_tag_select_op_prepare(vc, &bases_len);
-
- 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);
- }
-
- const bool changed_multi = do_pose_tag_select_op_exec(bases, bases_len, sel_op);
- if (changed_multi) {
- DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
- WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, vc->scene);
- }
-
- MEM_freeN(bases);
- return changed_multi;
-}
-
-static void do_lasso_select_mesh__doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index))
-{
- 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 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);
- data->is_changed = true;
- }
+ bool changed_multi = false;
+
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ for (int i = 0; i < bases_len; i++) {
+ Base *base_iter = bases[i];
+ Object *ob_iter = base_iter->object;
+ if (ED_pose_deselect_all(ob_iter, SEL_DESELECT, false)) {
+ ED_pose_bone_select_tag_update(ob_iter);
+ changed_multi = true;
+ }
+ }
+ }
+
+ for (int i = 0; i < bases_len; i++) {
+ Base *base_iter = bases[i];
+ Object *ob_iter = base_iter->object;
+ bArmature *arm = ob_iter->data;
+
+ /* Don't handle twice. */
+ if (arm->id.tag & LIB_TAG_DOIT) {
+ arm->id.tag &= ~LIB_TAG_DOIT;
+ }
+ else {
+ continue;
+ }
+
+ bool changed = true;
+ for (bPoseChannel *pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) {
+ Bone *bone = pchan->bone;
+ if ((bone->flag & BONE_UNSELECTABLE) == 0) {
+ const bool is_select = bone->flag & BONE_SELECTED;
+ const bool is_inside = bone->flag & BONE_DONE;
+ 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(bone->flag, sel_op_result, BONE_SELECTED);
+ if (sel_op_result == 0) {
+ if (arm->act_bone == bone) {
+ arm->act_bone = NULL;
+ }
+ }
+ changed = true;
+ }
+ }
+ }
+ if (changed) {
+ ED_pose_bone_select_tag_update(ob_iter);
+ changed_multi = true;
+ }
+ }
+ return changed_multi;
+}
+
+static bool do_lasso_select_pose(ViewContext *vc,
+ const int mcords[][2],
+ const short moves,
+ const eSelectOp sel_op)
+{
+ uint bases_len;
+ Base **bases = do_pose_tag_select_op_prepare(vc, &bases_len);
+
+ 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);
+ }
+
+ const bool changed_multi = do_pose_tag_select_op_exec(bases, bases_len, sel_op);
+ if (changed_multi) {
+ DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
+ WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, vc->scene);
+ }
+
+ MEM_freeN(bases);
+ return changed_multi;
+}
+
+static void do_lasso_select_mesh__doSelectVert(void *userData,
+ BMVert *eve,
+ const float screen_co[2],
+ int UNUSED(index))
+{
+ 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 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);
+ data->is_changed = true;
+ }
}
static void do_lasso_select_mesh__doSelectEdge_pass0(
- void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
-{
- LassoSelectUserData *data = userData;
- const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
- const bool is_inside = (
- EDBM_backbuf_check(bm_solidoffs + index) &&
- edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), IS_CLIPPED) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), IS_CLIPPED));
- const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- BM_edge_select_set(data->vc->em->bm, eed, sel_op_result);
- data->is_done = true;
- data->is_changed = true;
- }
+ void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
+{
+ LassoSelectUserData *data = userData;
+ const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
+ const bool is_inside =
+ (EDBM_backbuf_check(bm_solidoffs + index) &&
+ edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) &&
+ BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), IS_CLIPPED) &&
+ BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), IS_CLIPPED));
+ const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ BM_edge_select_set(data->vc->em->bm, eed, sel_op_result);
+ data->is_done = true;
+ data->is_changed = true;
+ }
}
static void do_lasso_select_mesh__doSelectEdge_pass1(
- void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
-{
- LassoSelectUserData *data = userData;
- const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
- const bool is_inside = (
- EDBM_backbuf_check(bm_solidoffs + index) &&
- BLI_lasso_is_edge_inside(
- data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), IS_CLIPPED));
- const 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);
- data->is_changed = true;
- }
-}
-
-static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
-{
- 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 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);
- data->is_changed = true;
- }
-}
-
-static bool do_lasso_select_mesh(
- ViewContext *vc,
- const int mcords[][2], short moves, const eSelectOp sel_op)
-{
- LassoSelectUserData data;
- ToolSettings *ts = vc->scene->toolsettings;
- rcti rect;
- int bbsel;
-
- /* set editmesh */
- vc->em = BKE_editmesh_from_object(vc->obedit);
-
- BLI_lasso_boundbox(&rect, mcords, moves);
-
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
-
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- if (vc->em->bm->totvertsel) {
- EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT);
- data.is_changed = true;
- }
- }
-
- /* for non zbuf projections, don't change the GL state */
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
-
- GPU_matrix_set(vc->rv3d->viewmat);
- bbsel = EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
-
- if (ts->selectmode & SCE_SELECT_VERTEX) {
- if (bbsel) {
- data.is_changed |= edbm_backbuf_check_and_select_verts(vc->em, sel_op);
- }
- else {
- mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- }
- }
- if (ts->selectmode & SCE_SELECT_EDGE) {
- /* Does both bbsel and non-bbsel versions (need screen cos for both) */
- mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR);
- if (data.is_done == false) {
- mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR);
- }
- }
-
- if (ts->selectmode & SCE_SELECT_FACE) {
- if (bbsel) {
- data.is_changed |= edbm_backbuf_check_and_select_faces(vc->em, sel_op);
- }
- else {
- mesh_foreachScreenFace(vc, do_lasso_select_mesh__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- }
- }
-
- EDBM_backbuf_free();
-
- if (data.is_changed) {
- EDBM_selectmode_flush(vc->em);
- }
- return data.is_changed;
-}
-
-static void do_lasso_select_curve__doSelect(
- void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
-{
- LassoSelectUserData *data = userData;
-
- const bool is_inside = BLI_lasso_is_point_inside(data->mcords, data->moves, 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);
- if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT);
- data->is_changed = true;
- }
- }
- else {
- if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
- /* can only be (beztindex == 0) here since handles are hidden */
- const bool is_select = bezt->f2 & SELECT;
- const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, SELECT);
- }
- bezt->f1 = bezt->f3 = bezt->f2;
- data->is_changed = true;
- }
- else {
- char *flag_p = (&bezt->f1) + beztindex;
- const bool is_select = *flag_p & SELECT;
- const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(*flag_p, sel_op_result, SELECT);
- data->is_changed = true;
- }
- }
- }
-}
-
-static bool do_lasso_select_curve(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
-{
- LassoSelectUserData data;
- rcti rect;
-
- BLI_lasso_boundbox(&rect, mcords, moves);
-
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
-
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- Curve *curve = (Curve *) vc->obedit->data;
- data.is_changed |= ED_curve_deselect_all(curve->editnurb);
- }
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
- nurbs_foreachScreenVert(vc, do_lasso_select_curve__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- if (data.is_changed) {
- BKE_curve_nurb_vert_active_validate(vc->obedit->data);
- }
- return data.is_changed;
+ void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
+{
+ LassoSelectUserData *data = userData;
+ const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
+ const bool is_inside =
+ (EDBM_backbuf_check(bm_solidoffs + index) &&
+ BLI_lasso_is_edge_inside(
+ data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), IS_CLIPPED));
+ const 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);
+ data->is_changed = true;
+ }
+}
+
+static void do_lasso_select_mesh__doSelectFace(void *userData,
+ BMFace *efa,
+ const float screen_co[2],
+ int UNUSED(index))
+{
+ 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 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);
+ data->is_changed = true;
+ }
+}
+
+static bool do_lasso_select_mesh(ViewContext *vc,
+ const int mcords[][2],
+ short moves,
+ const eSelectOp sel_op)
+{
+ LassoSelectUserData data;
+ ToolSettings *ts = vc->scene->toolsettings;
+ rcti rect;
+ int bbsel;
+
+ /* set editmesh */
+ vc->em = BKE_editmesh_from_object(vc->obedit);
+
+ BLI_lasso_boundbox(&rect, mcords, moves);
+
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
+
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ if (vc->em->bm->totvertsel) {
+ EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT);
+ data.is_changed = true;
+ }
+ }
+
+ /* for non zbuf projections, don't change the GL state */
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+
+ GPU_matrix_set(vc->rv3d->viewmat);
+ bbsel = EDBM_backbuf_border_mask_init(
+ vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+
+ if (ts->selectmode & SCE_SELECT_VERTEX) {
+ if (bbsel) {
+ data.is_changed |= edbm_backbuf_check_and_select_verts(vc->em, sel_op);
+ }
+ else {
+ mesh_foreachScreenVert(
+ vc, do_lasso_select_mesh__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ }
+ }
+ if (ts->selectmode & SCE_SELECT_EDGE) {
+ /* Does both bbsel and non-bbsel versions (need screen cos for both) */
+ mesh_foreachScreenEdge(
+ vc, do_lasso_select_mesh__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ if (data.is_done == false) {
+ mesh_foreachScreenEdge(
+ vc, do_lasso_select_mesh__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ }
+ }
+
+ if (ts->selectmode & SCE_SELECT_FACE) {
+ if (bbsel) {
+ data.is_changed |= edbm_backbuf_check_and_select_faces(vc->em, sel_op);
+ }
+ else {
+ mesh_foreachScreenFace(
+ vc, do_lasso_select_mesh__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ }
+ }
+
+ EDBM_backbuf_free();
+
+ if (data.is_changed) {
+ EDBM_selectmode_flush(vc->em);
+ }
+ return data.is_changed;
+}
+
+static void do_lasso_select_curve__doSelect(void *userData,
+ Nurb *UNUSED(nu),
+ BPoint *bp,
+ BezTriple *bezt,
+ int beztindex,
+ const float screen_co[2])
+{
+ LassoSelectUserData *data = userData;
+
+ const bool is_inside = BLI_lasso_is_point_inside(
+ data->mcords, data->moves, 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);
+ if (sel_op_result != -1) {
+ SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT);
+ data->is_changed = true;
+ }
+ }
+ else {
+ if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
+ /* can only be (beztindex == 0) here since handles are hidden */
+ const bool is_select = bezt->f2 & SELECT;
+ const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, SELECT);
+ }
+ bezt->f1 = bezt->f3 = bezt->f2;
+ data->is_changed = true;
+ }
+ else {
+ char *flag_p = (&bezt->f1) + beztindex;
+ const bool is_select = *flag_p & SELECT;
+ const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ SET_FLAG_FROM_TEST(*flag_p, sel_op_result, SELECT);
+ data->is_changed = true;
+ }
+ }
+ }
+}
+
+static bool do_lasso_select_curve(ViewContext *vc,
+ const int mcords[][2],
+ short moves,
+ const eSelectOp sel_op)
+{
+ LassoSelectUserData data;
+ rcti rect;
+
+ BLI_lasso_boundbox(&rect, mcords, moves);
+
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
+
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ Curve *curve = (Curve *)vc->obedit->data;
+ data.is_changed |= ED_curve_deselect_all(curve->editnurb);
+ }
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
+ nurbs_foreachScreenVert(vc, do_lasso_select_curve__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ if (data.is_changed) {
+ BKE_curve_nurb_vert_active_validate(vc->obedit->data);
+ }
+ return data.is_changed;
}
static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const float screen_co[2])
{
- 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 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);
- data->is_changed = true;
- }
+ 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 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);
+ data->is_changed = true;
+ }
}
-static bool do_lasso_select_lattice(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
+static bool do_lasso_select_lattice(ViewContext *vc,
+ const int mcords[][2],
+ short moves,
+ const eSelectOp sel_op)
{
- LassoSelectUserData data;
- rcti rect;
-
- BLI_lasso_boundbox(&rect, mcords, moves);
-
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
-
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- data.is_changed |= ED_lattice_flags_set(vc->obedit, 0);
- }
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
- lattice_foreachScreenVert(vc, do_lasso_select_lattice__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- return data.is_changed;
+ LassoSelectUserData data;
+ rcti rect;
+
+ BLI_lasso_boundbox(&rect, mcords, moves);
+
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
+
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ data.is_changed |= ED_lattice_flags_set(vc->obedit, 0);
+ }
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
+ lattice_foreachScreenVert(
+ vc, do_lasso_select_lattice__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ return data.is_changed;
}
-static void do_lasso_select_armature__doSelectBone(
- void *userData, EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2])
+static void do_lasso_select_armature__doSelectBone(void *userData,
+ EditBone *ebone,
+ const float screen_co_a[2],
+ const float screen_co_b[2])
{
- LassoSelectUserData *data = userData;
- bArmature *arm = data->vc->obedit->data;
- if (EBONE_VISIBLE(arm, ebone)) {
- int is_ignore_flag = 0;
- int is_inside_flag = 0;
-
- 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))
- {
- is_inside_flag |= BONESEL_ROOT;
- }
- }
- else {
- is_ignore_flag |= BONESEL_ROOT;
- }
+ LassoSelectUserData *data = userData;
+ bArmature *arm = data->vc->obedit->data;
+ if (EBONE_VISIBLE(arm, ebone)) {
+ int is_ignore_flag = 0;
+ int is_inside_flag = 0;
- 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))
- {
- is_inside_flag |= BONESEL_TIP;
- }
- }
- else {
- is_ignore_flag |= BONESEL_TIP;
- }
+ 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)) {
+ is_inside_flag |= BONESEL_ROOT;
+ }
+ }
+ else {
+ is_ignore_flag |= BONESEL_ROOT;
+ }
- 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))
- {
- is_inside_flag |= BONESEL_BONE;
- }
+ 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)) {
+ is_inside_flag |= BONESEL_TIP;
+ }
+ }
+ else {
+ is_ignore_flag |= BONESEL_TIP;
+ }
+ 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)) {
+ is_inside_flag |= BONESEL_BONE;
+ }
- ebone->temp.i = is_inside_flag | (is_ignore_flag >> 16);
- }
+ ebone->temp.i = is_inside_flag | (is_ignore_flag >> 16);
+ }
}
-static bool do_lasso_select_armature(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
+static bool do_lasso_select_armature(ViewContext *vc,
+ const int mcords[][2],
+ short moves,
+ const eSelectOp sel_op)
{
- LassoSelectUserData data;
- rcti rect;
+ LassoSelectUserData data;
+ rcti rect;
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcords, moves);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit);
- }
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit);
+ }
- bArmature *arm = vc->obedit->data;
+ bArmature *arm = vc->obedit->data;
- ED_armature_ebone_listbase_temp_clear(arm->edbo);
+ ED_armature_ebone_listbase_temp_clear(arm->edbo);
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- armature_foreachScreenBone(vc, do_lasso_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ armature_foreachScreenBone(
+ vc, do_lasso_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- data.is_changed |= ED_armature_edit_select_op_from_tagged(vc->obedit->data, sel_op);
+ data.is_changed |= ED_armature_edit_select_op_from_tagged(vc->obedit->data, sel_op);
- if (data.is_changed) {
- WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit);
- }
- return data.is_changed;
+ if (data.is_changed) {
+ WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit);
+ }
+ return data.is_changed;
}
-static void do_lasso_select_mball__doSelectElem(void *userData, struct MetaElem *ml, const float screen_co[2])
+static void do_lasso_select_mball__doSelectElem(void *userData,
+ struct MetaElem *ml,
+ const float screen_co[2])
{
- 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 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);
- data->is_changed = true;
- }
+ 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 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);
+ data->is_changed = true;
+ }
}
-static bool do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
+static bool do_lasso_select_meta(ViewContext *vc,
+ const int mcords[][2],
+ short moves,
+ const eSelectOp sel_op)
{
- LassoSelectUserData data;
- rcti rect;
+ LassoSelectUserData data;
+ rcti rect;
- MetaBall *mb = (MetaBall *)vc->obedit->data;
+ MetaBall *mb = (MetaBall *)vc->obedit->data;
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcords, moves);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- data.is_changed |= BKE_mball_deselect_all(mb);
- }
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ data.is_changed |= BKE_mball_deselect_all(mb);
+ }
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mball_foreachScreenElem(vc, do_lasso_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ mball_foreachScreenElem(
+ vc, do_lasso_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- return data.is_changed;
+ return data.is_changed;
}
-static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
+static void do_lasso_select_meshobject__doSelectVert(void *userData,
+ MVert *mv,
+ const float screen_co[2],
+ int UNUSED(index))
{
- 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 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);
- data->is_changed = true;
- }
+ 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 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);
+ data->is_changed = true;
+ }
}
-static bool do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
+static bool do_lasso_select_paintvert(ViewContext *vc,
+ const int mcords[][2],
+ short moves,
+ const eSelectOp sel_op)
{
- const bool use_zbuf = !XRAY_ENABLED(vc->v3d);
- Object *ob = vc->obact;
- Mesh *me = ob->data;
- rcti rect;
+ const bool use_zbuf = !XRAY_ENABLED(vc->v3d);
+ Object *ob = vc->obact;
+ Mesh *me = ob->data;
+ rcti rect;
- if (me == NULL || me->totvert == 0) {
- return false;
- }
+ if (me == NULL || me->totvert == 0) {
+ return false;
+ }
- bool changed = false;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- /* flush selection at the end */
- changed |= paintvert_deselect_all_visible(ob, SEL_DESELECT, false);
- }
+ bool changed = false;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ /* flush selection at the end */
+ changed |= paintvert_deselect_all_visible(ob, SEL_DESELECT, false);
+ }
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcords, moves);
- if (use_zbuf) {
- bm_vertoffs = me->totvert + 1; /* max index array */
+ if (use_zbuf) {
+ bm_vertoffs = me->totvert + 1; /* max index array */
- EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- changed |= edbm_backbuf_check_and_select_verts_obmode(me, sel_op);
+ changed |= edbm_backbuf_check_and_select_verts_obmode(me, sel_op);
- EDBM_backbuf_free();
- }
- else {
- LassoSelectUserData data;
+ EDBM_backbuf_free();
+ }
+ else {
+ LassoSelectUserData data;
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
- ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
+ ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
- meshobject_foreachScreenVert(vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ meshobject_foreachScreenVert(
+ vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- changed |= data.is_changed;
- }
+ changed |= data.is_changed;
+ }
- if (changed) {
- if (SEL_OP_CAN_DESELECT(sel_op)) {
- BKE_mesh_mselect_validate(me);
- }
- paintvert_flush_flags(ob);
- paintvert_tag_select_update(vc->C, ob);
- }
- return changed;
+ if (changed) {
+ if (SEL_OP_CAN_DESELECT(sel_op)) {
+ BKE_mesh_mselect_validate(me);
+ }
+ paintvert_flush_flags(ob);
+ paintvert_tag_select_update(vc->C, ob);
+ }
+ return changed;
}
-static bool do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
+static bool do_lasso_select_paintface(ViewContext *vc,
+ const int mcords[][2],
+ short moves,
+ const eSelectOp sel_op)
{
- Object *ob = vc->obact;
- Mesh *me = ob->data;
- rcti rect;
+ Object *ob = vc->obact;
+ Mesh *me = ob->data;
+ rcti rect;
- if (me == NULL || me->totpoly == 0) {
- return false;
- }
+ if (me == NULL || me->totpoly == 0) {
+ return false;
+ }
- bm_vertoffs = me->totpoly + 1; /* max index array */
+ bm_vertoffs = me->totpoly + 1; /* max index array */
- BLI_lasso_boundbox(&rect, mcords, moves);
- EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ BLI_lasso_boundbox(&rect, mcords, moves);
+ EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- bool changed = false;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- /* flush selection at the end */
- changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false);
- }
- changed |= edbm_backbuf_check_and_select_tfaces(me, sel_op);
+ bool changed = false;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ /* flush selection at the end */
+ changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false);
+ }
+ changed |= edbm_backbuf_check_and_select_tfaces(me, sel_op);
- EDBM_backbuf_free();
+ EDBM_backbuf_free();
- if (changed) {
- paintface_flush_flags(vc->C, ob, SELECT);
- }
- return changed;
+ if (changed) {
+ paintface_flush_flags(vc->C, ob, SELECT);
+ }
+ return changed;
}
#if 0
static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp sel_op)
{
- SpaceNode *snode = sa->spacedata.first;
-
- bNode *node;
- rcti rect;
- int node_cent[2];
- float node_centf[2];
- bool changed = false;
-
- BLI_lasso_boundbox(&rect, mcords, moves);
-
- /* store selection in temp test flag */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- node_centf[0] = BLI_RCT_CENTER_X(&node->totr);
- node_centf[1] = BLI_RCT_CENTER_Y(&node->totr);
-
- 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]));
- 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);
- changed = true;
- }
- }
- if (changed) {
- BIF_undo_push("Lasso select nodes");
- }
+ SpaceNode *snode = sa->spacedata.first;
+
+ bNode *node;
+ rcti rect;
+ int node_cent[2];
+ float node_centf[2];
+ bool changed = false;
+
+ BLI_lasso_boundbox(&rect, mcords, moves);
+
+ /* store selection in temp test flag */
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ node_centf[0] = BLI_RCT_CENTER_X(&node->totr);
+ node_centf[1] = BLI_RCT_CENTER_Y(&node->totr);
+
+ 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]));
+ 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);
+ changed = true;
+ }
+ }
+ if (changed) {
+ BIF_undo_push("Lasso select nodes");
+ }
}
#endif
static bool view3d_lasso_select(
- bContext *C, ViewContext *vc,
- const int mcords[][2], short moves,
- const eSelectOp sel_op)
-{
- Object *ob = CTX_data_active_object(C);
- bool changed_multi = false;
-
- if (vc->obedit == NULL) { /* Object Mode */
- if (BKE_paint_select_face_test(ob)) {
- changed_multi |= do_lasso_select_paintface(vc, mcords, moves, sel_op);
- }
- else if (BKE_paint_select_vert_test(ob)) {
- changed_multi |= do_lasso_select_paintvert(vc, mcords, moves, 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);
- }
- else if (ob && (ob->mode & OB_MODE_POSE)) {
- changed_multi |= do_lasso_select_pose(vc, mcords, moves, sel_op);
- }
- else {
- changed_multi |= do_lasso_select_objects(vc, mcords, moves, sel_op);
- }
- }
- else { /* Edit Mode */
-
- FOREACH_OBJECT_IN_MODE_BEGIN (vc->view_layer, vc->v3d, ob->type, ob->mode, ob_iter) {
- ED_view3d_viewcontext_init_object(vc, ob_iter);
- bool changed = false;
-
- switch (vc->obedit->type) {
- case OB_MESH:
- changed = do_lasso_select_mesh(vc, mcords, moves, sel_op);
- break;
- case OB_CURVE:
- case OB_SURF:
- changed = do_lasso_select_curve(vc, mcords, moves, sel_op);
- break;
- case OB_LATTICE:
- changed = do_lasso_select_lattice(vc, mcords, moves, sel_op);
- break;
- case OB_ARMATURE:
- changed = do_lasso_select_armature(vc, mcords, moves, sel_op);
- break;
- case OB_MBALL:
- changed = do_lasso_select_meta(vc, mcords, moves, sel_op);
- break;
- default:
- assert(!"lasso select on incorrect object type");
- break;
- }
-
- if (changed) {
- DEG_id_tag_update(vc->obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data);
- changed_multi = true;
- }
- }
- FOREACH_OBJECT_IN_MODE_END;
- }
- return changed_multi;
+ bContext *C, ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
+{
+ Object *ob = CTX_data_active_object(C);
+ bool changed_multi = false;
+
+ if (vc->obedit == NULL) { /* Object Mode */
+ if (BKE_paint_select_face_test(ob)) {
+ changed_multi |= do_lasso_select_paintface(vc, mcords, moves, sel_op);
+ }
+ else if (BKE_paint_select_vert_test(ob)) {
+ changed_multi |= do_lasso_select_paintvert(vc, mcords, moves, 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);
+ }
+ else if (ob && (ob->mode & OB_MODE_POSE)) {
+ changed_multi |= do_lasso_select_pose(vc, mcords, moves, sel_op);
+ }
+ else {
+ changed_multi |= do_lasso_select_objects(vc, mcords, moves, sel_op);
+ }
+ }
+ else { /* Edit Mode */
+
+ FOREACH_OBJECT_IN_MODE_BEGIN (vc->view_layer, vc->v3d, ob->type, ob->mode, ob_iter) {
+ ED_view3d_viewcontext_init_object(vc, ob_iter);
+ bool changed = false;
+
+ switch (vc->obedit->type) {
+ case OB_MESH:
+ changed = do_lasso_select_mesh(vc, mcords, moves, sel_op);
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ changed = do_lasso_select_curve(vc, mcords, moves, sel_op);
+ break;
+ case OB_LATTICE:
+ changed = do_lasso_select_lattice(vc, mcords, moves, sel_op);
+ break;
+ case OB_ARMATURE:
+ changed = do_lasso_select_armature(vc, mcords, moves, sel_op);
+ break;
+ case OB_MBALL:
+ changed = do_lasso_select_meta(vc, mcords, moves, sel_op);
+ break;
+ default:
+ assert(!"lasso select on incorrect object type");
+ break;
+ }
+
+ if (changed) {
+ DEG_id_tag_update(vc->obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data);
+ changed_multi = true;
+ }
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+ }
+ return changed_multi;
}
-
/* lasso operator gives properties, but since old code works
* with short array we convert */
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);
+ ViewContext vc;
+ int mcords_tot;
+ const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
- if (mcords) {
- view3d_operator_needs_opengl(C);
+ if (mcords) {
+ view3d_operator_needs_opengl(C);
- /* setup view context for argument to callbacks */
- ED_view3d_viewcontext_init(C, &vc);
+ /* setup view context for argument to callbacks */
+ ED_view3d_viewcontext_init(C, &vc);
- eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
- bool changed_multi = view3d_lasso_select(C, &vc, mcords, mcords_tot, sel_op);
+ eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
+ bool changed_multi = view3d_lasso_select(C, &vc, mcords, mcords_tot, sel_op);
- MEM_freeN((void *)mcords);
+ MEM_freeN((void *)mcords);
- if (changed_multi) {
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
- }
- return OPERATOR_PASS_THROUGH;
+ if (changed_multi) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+ }
+ return OPERATOR_PASS_THROUGH;
}
void VIEW3D_OT_select_lasso(wmOperatorType *ot)
{
- ot->name = "Lasso Select";
- ot->description = "Select items using lasso selection";
- ot->idname = "VIEW3D_OT_select_lasso";
+ ot->name = "Lasso Select";
+ ot->description = "Select items using lasso selection";
+ ot->idname = "VIEW3D_OT_select_lasso";
- ot->invoke = WM_gesture_lasso_invoke;
- ot->modal = WM_gesture_lasso_modal;
- ot->exec = view3d_lasso_select_exec;
- ot->poll = view3d_selectable_data;
- ot->cancel = WM_gesture_lasso_cancel;
+ ot->invoke = WM_gesture_lasso_invoke;
+ ot->modal = WM_gesture_lasso_modal;
+ ot->exec = view3d_lasso_select_exec;
+ ot->poll = view3d_selectable_data;
+ ot->cancel = WM_gesture_lasso_cancel;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_gesture_lasso(ot);
- WM_operator_properties_select_operation(ot);
+ /* properties */
+ WM_operator_properties_gesture_lasso(ot);
+ WM_operator_properties_select_operation(ot);
}
/** \} */
@@ -1180,1015 +1218,1068 @@ void VIEW3D_OT_select_lasso(wmOperatorType *ot)
/* The max number of menu items in an object select menu */
typedef struct SelMenuItemF {
- char idname[MAX_ID_NAME - 2];
- int icon;
+ char idname[MAX_ID_NAME - 2];
+ int icon;
} SelMenuItemF;
-#define SEL_MENU_SIZE 22
+#define SEL_MENU_SIZE 22
static SelMenuItemF object_mouse_select_menu_data[SEL_MENU_SIZE];
/* special (crappy) operator only for menu select */
-static const EnumPropertyItem *object_select_menu_enum_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *object_select_menu_enum_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- EnumPropertyItem *item = NULL, item_tmp = {0};
- int totitem = 0;
- int i = 0;
+ EnumPropertyItem *item = NULL, item_tmp = {0};
+ int totitem = 0;
+ int i = 0;
- /* don't need context but avoid docgen using this */
- if (C == NULL || object_mouse_select_menu_data[i].idname[0] == '\0') {
- return DummyRNA_NULL_items;
- }
+ /* don't need context but avoid docgen using this */
+ if (C == NULL || object_mouse_select_menu_data[i].idname[0] == '\0') {
+ return DummyRNA_NULL_items;
+ }
- for (; i < SEL_MENU_SIZE && object_mouse_select_menu_data[i].idname[0] != '\0'; i++) {
- item_tmp.name = object_mouse_select_menu_data[i].idname;
- item_tmp.identifier = object_mouse_select_menu_data[i].idname;
- item_tmp.value = i;
- item_tmp.icon = object_mouse_select_menu_data[i].icon;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- }
+ for (; i < SEL_MENU_SIZE && object_mouse_select_menu_data[i].idname[0] != '\0'; i++) {
+ item_tmp.name = object_mouse_select_menu_data[i].idname;
+ item_tmp.identifier = object_mouse_select_menu_data[i].idname;
+ item_tmp.value = i;
+ item_tmp.icon = object_mouse_select_menu_data[i].icon;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
- return item;
+ return item;
}
static int object_select_menu_exec(bContext *C, wmOperator *op)
{
- const int name_index = RNA_enum_get(op->ptr, "name");
- const bool toggle = RNA_boolean_get(op->ptr, "toggle");
- bool changed = false;
- const char *name = object_mouse_select_menu_data[name_index].idname;
-
- if (!toggle) {
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- if ((base->flag & BASE_SELECTED) != 0) {
- ED_object_base_select(base, BA_DESELECT);
- changed = true;
- }
- }
- CTX_DATA_END;
- }
-
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- /* This is a bit dodgy, there should only be ONE object with this name,
- * but library objects can mess this up. */
- if (STREQ(name, base->object->id.name + 2)) {
- ED_object_base_activate(C, base);
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- CTX_DATA_END;
-
- /* weak but ensures we activate menu again before using the enum */
- memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data));
-
- /* undo? */
- if (changed) {
- Scene *scene = CTX_data_scene(C);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ const int name_index = RNA_enum_get(op->ptr, "name");
+ const bool toggle = RNA_boolean_get(op->ptr, "toggle");
+ bool changed = false;
+ const char *name = object_mouse_select_menu_data[name_index].idname;
+
+ if (!toggle) {
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ if ((base->flag & BASE_SELECTED) != 0) {
+ ED_object_base_select(base, BA_DESELECT);
+ changed = true;
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ /* This is a bit dodgy, there should only be ONE object with this name,
+ * but library objects can mess this up. */
+ if (STREQ(name, base->object->id.name + 2)) {
+ ED_object_base_activate(C, base);
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ CTX_DATA_END;
+
+ /* weak but ensures we activate menu again before using the enum */
+ memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data));
+
+ /* undo? */
+ if (changed) {
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void VIEW3D_OT_select_menu(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Select Menu";
- ot->description = "Menu object selection";
- ot->idname = "VIEW3D_OT_select_menu";
+ /* identifiers */
+ ot->name = "Select Menu";
+ ot->description = "Menu object selection";
+ ot->idname = "VIEW3D_OT_select_menu";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_select_menu_exec;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_select_menu_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* keyingset to use (dynamic enum) */
- prop = RNA_def_enum(ot->srna, "name", DummyRNA_NULL_items, 0, "Object Name", "");
- RNA_def_enum_funcs(prop, object_select_menu_enum_itemf);
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ /* keyingset to use (dynamic enum) */
+ prop = RNA_def_enum(ot->srna, "name", DummyRNA_NULL_items, 0, "Object Name", "");
+ RNA_def_enum_funcs(prop, object_select_menu_enum_itemf);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
- RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first");
+ RNA_def_boolean(
+ ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first");
}
static Base *object_mouse_select_menu(
- bContext *C, ViewContext *vc, uint *buffer, int hits,
- const int mval[2], bool toggle)
-{
- short baseCount = 0;
- bool ok;
- LinkNode *linklist = NULL;
-
- /* handle base->object->select_id */
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- ok = false;
-
- /* two selection methods, the CTRL select uses max dist of 15 */
- if (buffer) {
- for (int a = 0; a < hits; a++) {
- /* index was converted */
- if (base->object->select_id == (buffer[(4 * a) + 3] & ~0xFFFF0000)) {
- ok = true;
- break;
- }
- }
- }
- else {
- const int dist = 15 * U.pixelsize;
- if (ED_view3d_project_base(vc->ar, 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;
- }
- }
- }
-
- if (ok) {
- baseCount++;
- BLI_linklist_prepend(&linklist, base);
-
- if (baseCount == SEL_MENU_SIZE) {
- break;
- }
- }
- }
- CTX_DATA_END;
-
- if (baseCount == 0) {
- return NULL;
- }
- if (baseCount == 1) {
- Base *base = (Base *)linklist->link;
- BLI_linklist_free(linklist, NULL);
- return base;
- }
- else {
- /* UI, full in static array values that we later use in an enum function */
- LinkNode *node;
- int i;
-
- memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data));
-
- for (node = linklist, i = 0; node; node = node->next, i++) {
- Base *base = node->link;
- Object *ob = base->object;
- const char *name = ob->id.name + 2;
-
- BLI_strncpy(object_mouse_select_menu_data[i].idname, name, MAX_ID_NAME - 2);
- object_mouse_select_menu_data[i].icon = UI_icon_from_id(&ob->id);
- }
-
- {
- wmOperatorType *ot = WM_operatortype_find("VIEW3D_OT_select_menu", false);
- PointerRNA ptr;
-
- WM_operator_properties_create_ptr(&ptr, ot);
- RNA_boolean_set(&ptr, "toggle", toggle);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
- WM_operator_properties_free(&ptr);
- }
-
- BLI_linklist_free(linklist, NULL);
- return NULL;
- }
+ bContext *C, ViewContext *vc, uint *buffer, int hits, const int mval[2], bool toggle)
+{
+ short baseCount = 0;
+ bool ok;
+ LinkNode *linklist = NULL;
+
+ /* handle base->object->select_id */
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ ok = false;
+
+ /* two selection methods, the CTRL select uses max dist of 15 */
+ if (buffer) {
+ for (int a = 0; a < hits; a++) {
+ /* index was converted */
+ if (base->object->select_id == (buffer[(4 * a) + 3] & ~0xFFFF0000)) {
+ ok = true;
+ break;
+ }
+ }
+ }
+ else {
+ const int dist = 15 * U.pixelsize;
+ if (ED_view3d_project_base(vc->ar, 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;
+ }
+ }
+ }
+
+ if (ok) {
+ baseCount++;
+ BLI_linklist_prepend(&linklist, base);
+
+ if (baseCount == SEL_MENU_SIZE) {
+ break;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ if (baseCount == 0) {
+ return NULL;
+ }
+ if (baseCount == 1) {
+ Base *base = (Base *)linklist->link;
+ BLI_linklist_free(linklist, NULL);
+ return base;
+ }
+ else {
+ /* UI, full in static array values that we later use in an enum function */
+ LinkNode *node;
+ int i;
+
+ memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data));
+
+ for (node = linklist, i = 0; node; node = node->next, i++) {
+ Base *base = node->link;
+ Object *ob = base->object;
+ const char *name = ob->id.name + 2;
+
+ BLI_strncpy(object_mouse_select_menu_data[i].idname, name, MAX_ID_NAME - 2);
+ object_mouse_select_menu_data[i].icon = UI_icon_from_id(&ob->id);
+ }
+
+ {
+ wmOperatorType *ot = WM_operatortype_find("VIEW3D_OT_select_menu", false);
+ PointerRNA ptr;
+
+ WM_operator_properties_create_ptr(&ptr, ot);
+ RNA_boolean_set(&ptr, "toggle", toggle);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
+ WM_operator_properties_free(&ptr);
+ }
+
+ BLI_linklist_free(linklist, NULL);
+ return NULL;
+ }
}
static bool selectbuffer_has_bones(const uint *buffer, const uint hits)
{
- uint i;
- for (i = 0; i < hits; i++) {
- if (buffer[(4 * i) + 3] & 0xFFFF0000) {
- return true;
- }
- }
- return false;
+ uint i;
+ for (i = 0; i < hits; i++) {
+ if (buffer[(4 * i) + 3] & 0xFFFF0000) {
+ return true;
+ }
+ }
+ return false;
}
/* utility function for mixed_bones_object_selectbuffer */
static int selectbuffer_ret_hits_15(uint *UNUSED(buffer), const int hits15)
{
- return hits15;
+ return hits15;
}
static int selectbuffer_ret_hits_9(uint *buffer, const int hits15, const int hits9)
{
- const int offs = 4 * hits15;
- memcpy(buffer, buffer + offs, 4 * hits9 * sizeof(uint));
- return hits9;
+ const int offs = 4 * hits15;
+ memcpy(buffer, buffer + offs, 4 * hits9 * sizeof(uint));
+ return hits9;
}
-static int selectbuffer_ret_hits_5(uint *buffer, const int hits15, const int hits9, const int hits5)
+static int selectbuffer_ret_hits_5(uint *buffer,
+ const int hits15,
+ const int hits9,
+ const int hits5)
{
- const int offs = 4 * hits15 + 4 * hits9;
- memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(uint));
- return hits5;
+ const int offs = 4 * hits15 + 4 * hits9;
+ memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(uint));
+ return hits5;
}
/**
* Populate a select buffer with objects and bones, if there are any.
* Checks three selection levels and compare.
*/
-static int mixed_bones_object_selectbuffer(
- ViewContext *vc, uint *buffer, const int mval[2], eV3DSelectObjectFilter select_filter,
- bool do_nearest)
-{
- 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 hits = 0;
-
- /* we _must_ end cache before return, use 'goto finally' */
- view3d_opengl_select_cache_begin();
-
- BLI_rcti_init_pt_radius(&rect, mval, 14);
- hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter);
- if (hits15 == 1) {
- hits = selectbuffer_ret_hits_15(buffer, hits15);
- goto finally;
- }
- else if (hits15 > 0) {
- int offs;
- has_bones15 = selectbuffer_has_bones(buffer, hits15);
-
- offs = 4 * hits15;
- BLI_rcti_init_pt_radius(&rect, mval, 9);
- hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter);
- if (hits9 == 1) {
- hits = selectbuffer_ret_hits_9(buffer, hits15, hits9);
- goto finally;
- }
- else if (hits9 > 0) {
- has_bones9 = selectbuffer_has_bones(buffer + offs, hits9);
-
- offs += 4 * hits9;
- BLI_rcti_init_pt_radius(&rect, mval, 5);
- hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter);
- if (hits5 == 1) {
- hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
- goto finally;
- }
- else if (hits5 > 0) {
- has_bones5 = selectbuffer_has_bones(buffer + offs, hits5);
- }
- }
-
- if (has_bones5) { hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); goto finally; }
- else if (has_bones9) { hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); goto finally; }
- else if (has_bones15) { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; }
-
- if (hits5 > 0) { hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); goto finally; }
- else if (hits9 > 0) { hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); goto finally; }
- else { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; }
- }
+static int mixed_bones_object_selectbuffer(ViewContext *vc,
+ uint *buffer,
+ const int mval[2],
+ eV3DSelectObjectFilter select_filter,
+ bool do_nearest)
+{
+ 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 hits = 0;
+
+ /* we _must_ end cache before return, use 'goto finally' */
+ view3d_opengl_select_cache_begin();
+
+ BLI_rcti_init_pt_radius(&rect, mval, 14);
+ hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter);
+ if (hits15 == 1) {
+ hits = selectbuffer_ret_hits_15(buffer, hits15);
+ goto finally;
+ }
+ else if (hits15 > 0) {
+ int offs;
+ has_bones15 = selectbuffer_has_bones(buffer, hits15);
+
+ offs = 4 * hits15;
+ BLI_rcti_init_pt_radius(&rect, mval, 9);
+ hits9 = view3d_opengl_select(
+ vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter);
+ if (hits9 == 1) {
+ hits = selectbuffer_ret_hits_9(buffer, hits15, hits9);
+ goto finally;
+ }
+ else if (hits9 > 0) {
+ has_bones9 = selectbuffer_has_bones(buffer + offs, hits9);
+
+ offs += 4 * hits9;
+ BLI_rcti_init_pt_radius(&rect, mval, 5);
+ hits5 = view3d_opengl_select(
+ vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter);
+ if (hits5 == 1) {
+ hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
+ goto finally;
+ }
+ else if (hits5 > 0) {
+ has_bones5 = selectbuffer_has_bones(buffer + offs, hits5);
+ }
+ }
+
+ if (has_bones5) {
+ hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
+ goto finally;
+ }
+ else if (has_bones9) {
+ hits = selectbuffer_ret_hits_9(buffer, hits15, hits9);
+ goto finally;
+ }
+ else if (has_bones15) {
+ hits = selectbuffer_ret_hits_15(buffer, hits15);
+ goto finally;
+ }
+
+ if (hits5 > 0) {
+ hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
+ goto finally;
+ }
+ else if (hits9 > 0) {
+ hits = selectbuffer_ret_hits_9(buffer, hits15, hits9);
+ goto finally;
+ }
+ else {
+ hits = selectbuffer_ret_hits_15(buffer, hits15);
+ goto finally;
+ }
+ }
finally:
- view3d_opengl_select_cache_end();
- return hits;
-}
-
-static int mixed_bones_object_selectbuffer_extended(
- ViewContext *vc, uint *buffer, const int mval[2], eV3DSelectObjectFilter select_filter,
- bool use_cycle, bool enumerate, bool *r_do_nearest)
-{
- static int last_mval[2] = {-100, -100};
- bool do_nearest = false;
- View3D *v3d = vc->v3d;
-
- /* define if we use solid nearest select or not */
- if (use_cycle) {
- if (!XRAY_ACTIVE(v3d)) {
- do_nearest = true;
- if (len_manhattan_v2v2_int(mval, last_mval) <= WM_EVENT_CURSOR_MOTION_THRESHOLD) {
- do_nearest = false;
- }
- }
- copy_v2_v2_int(last_mval, mval);
- }
- else {
- if (!XRAY_ACTIVE(v3d)) {
- do_nearest = true;
- }
- }
-
- if (r_do_nearest) {
- *r_do_nearest = do_nearest;
- }
-
- do_nearest = do_nearest && !enumerate;
-
- int hits = mixed_bones_object_selectbuffer(vc, buffer, mval, select_filter, do_nearest);
-
- if (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
- const bool is_pose_mode = (
- (vc->obact && vc->obact->mode & OB_MODE_POSE) ||
- (select_filter == VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK));
- struct {
- uint data[4];
- } *buffer4 = (void *)buffer;
- uint j = 0;
- for (uint i = 0; i < hits; i++) {
- if (((buffer4[i].data[3] & 0xFFFF0000) != 0) == is_pose_mode) {
- if (i != j) {
- buffer4[j] = buffer4[i];
- }
- j++;
- }
- }
- hits = j;
- }
-
- return hits;
+ view3d_opengl_select_cache_end();
+ return hits;
+}
+
+static int mixed_bones_object_selectbuffer_extended(ViewContext *vc,
+ uint *buffer,
+ const int mval[2],
+ eV3DSelectObjectFilter select_filter,
+ bool use_cycle,
+ bool enumerate,
+ bool *r_do_nearest)
+{
+ static int last_mval[2] = {-100, -100};
+ bool do_nearest = false;
+ View3D *v3d = vc->v3d;
+
+ /* define if we use solid nearest select or not */
+ if (use_cycle) {
+ if (!XRAY_ACTIVE(v3d)) {
+ do_nearest = true;
+ if (len_manhattan_v2v2_int(mval, last_mval) <= WM_EVENT_CURSOR_MOTION_THRESHOLD) {
+ do_nearest = false;
+ }
+ }
+ copy_v2_v2_int(last_mval, mval);
+ }
+ else {
+ if (!XRAY_ACTIVE(v3d)) {
+ do_nearest = true;
+ }
+ }
+
+ if (r_do_nearest) {
+ *r_do_nearest = do_nearest;
+ }
+
+ do_nearest = do_nearest && !enumerate;
+
+ int hits = mixed_bones_object_selectbuffer(vc, buffer, mval, select_filter, do_nearest);
+
+ if (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ const bool is_pose_mode = ((vc->obact && vc->obact->mode & OB_MODE_POSE) ||
+ (select_filter == VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK));
+ struct {
+ uint data[4];
+ } *buffer4 = (void *)buffer;
+ uint j = 0;
+ for (uint i = 0; i < hits; i++) {
+ if (((buffer4[i].data[3] & 0xFFFF0000) != 0) == is_pose_mode) {
+ if (i != j) {
+ buffer4[j] = buffer4[i];
+ }
+ j++;
+ }
+ }
+ hits = j;
+ }
+
+ return hits;
}
/* returns basact */
-static Base *mouse_select_eval_buffer(
- ViewContext *vc, const uint *buffer, int hits,
- Base *startbase, bool has_bones, bool do_nearest)
-{
- ViewLayer *view_layer = vc->view_layer;
- View3D *v3d = vc->v3d;
- Base *base, *basact = NULL;
- int a;
-
- if (do_nearest) {
- uint min = 0xFFFFFFFF;
- int selcol = 0, notcol = 0;
-
-
- if (has_bones) {
- /* we skip non-bone hits */
- for (a = 0; a < hits; a++) {
- if (min > buffer[4 * a + 1] && (buffer[4 * a + 3] & 0xFFFF0000) ) {
- min = buffer[4 * a + 1];
- selcol = buffer[4 * a + 3] & 0xFFFF;
- }
- }
- }
- else {
- /* only exclude active object when it is selected... */
- if (BASACT(view_layer) && (BASACT(view_layer)->flag & BASE_SELECTED) && hits > 1) {
- notcol = BASACT(view_layer)->object->select_id;
- }
-
- for (a = 0; a < hits; a++) {
- if (min > buffer[4 * a + 1] && notcol != (buffer[4 * a + 3] & 0xFFFF)) {
- min = buffer[4 * a + 1];
- selcol = buffer[4 * a + 3] & 0xFFFF;
- }
- }
- }
-
- base = FIRSTBASE(view_layer);
- while (base) {
- if (BASE_SELECTABLE(v3d, base)) {
- if (base->object->select_id == selcol) {
- break;
- }
- }
- base = base->next;
- }
- if (base) {
- basact = base;
- }
- }
- else {
-
- base = startbase;
- while (base) {
- /* skip objects with select restriction, to prevent prematurely ending this loop
- * with an un-selectable choice */
- if ((base->flag & BASE_SELECTABLE) == 0) {
- base = base->next;
- if (base == NULL) {
- base = FIRSTBASE(view_layer);
- }
- if (base == startbase) {
- break;
- }
- }
-
- if (BASE_SELECTABLE(v3d, base)) {
- for (a = 0; a < hits; a++) {
- if (has_bones) {
- /* skip non-bone objects */
- if ((buffer[4 * a + 3] & 0xFFFF0000)) {
- if (base->object->select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
- basact = base;
- }
- }
- }
- else {
- if (base->object->select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
- basact = base;
- }
- }
- }
- }
-
- if (basact) {
- break;
- }
-
- base = base->next;
- if (base == NULL) {
- base = FIRSTBASE(view_layer);
- }
- if (base == startbase) {
- break;
- }
- }
- }
-
- return basact;
+static Base *mouse_select_eval_buffer(ViewContext *vc,
+ const uint *buffer,
+ int hits,
+ Base *startbase,
+ bool has_bones,
+ bool do_nearest)
+{
+ ViewLayer *view_layer = vc->view_layer;
+ View3D *v3d = vc->v3d;
+ Base *base, *basact = NULL;
+ int a;
+
+ if (do_nearest) {
+ uint min = 0xFFFFFFFF;
+ int selcol = 0, notcol = 0;
+
+ if (has_bones) {
+ /* we skip non-bone hits */
+ for (a = 0; a < hits; a++) {
+ if (min > buffer[4 * a + 1] && (buffer[4 * a + 3] & 0xFFFF0000)) {
+ min = buffer[4 * a + 1];
+ selcol = buffer[4 * a + 3] & 0xFFFF;
+ }
+ }
+ }
+ else {
+ /* only exclude active object when it is selected... */
+ if (BASACT(view_layer) && (BASACT(view_layer)->flag & BASE_SELECTED) && hits > 1) {
+ notcol = BASACT(view_layer)->object->select_id;
+ }
+
+ for (a = 0; a < hits; a++) {
+ if (min > buffer[4 * a + 1] && notcol != (buffer[4 * a + 3] & 0xFFFF)) {
+ min = buffer[4 * a + 1];
+ selcol = buffer[4 * a + 3] & 0xFFFF;
+ }
+ }
+ }
+
+ base = FIRSTBASE(view_layer);
+ while (base) {
+ if (BASE_SELECTABLE(v3d, base)) {
+ if (base->object->select_id == selcol) {
+ break;
+ }
+ }
+ base = base->next;
+ }
+ if (base) {
+ basact = base;
+ }
+ }
+ else {
+
+ base = startbase;
+ while (base) {
+ /* skip objects with select restriction, to prevent prematurely ending this loop
+ * with an un-selectable choice */
+ if ((base->flag & BASE_SELECTABLE) == 0) {
+ base = base->next;
+ if (base == NULL) {
+ base = FIRSTBASE(view_layer);
+ }
+ if (base == startbase) {
+ break;
+ }
+ }
+
+ if (BASE_SELECTABLE(v3d, base)) {
+ for (a = 0; a < hits; a++) {
+ if (has_bones) {
+ /* skip non-bone objects */
+ if ((buffer[4 * a + 3] & 0xFFFF0000)) {
+ if (base->object->select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
+ basact = base;
+ }
+ }
+ }
+ else {
+ if (base->object->select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
+ basact = base;
+ }
+ }
+ }
+ }
+
+ if (basact) {
+ break;
+ }
+
+ base = base->next;
+ if (base == NULL) {
+ base = FIRSTBASE(view_layer);
+ }
+ if (base == startbase) {
+ break;
+ }
+ }
+ }
+
+ return basact;
}
/* mval comes from event->mval, only use within region handlers */
Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
{
- ViewContext vc;
- Base *basact = NULL;
- uint buffer[MAXPICKBUF];
+ ViewContext vc;
+ Base *basact = NULL;
+ uint buffer[MAXPICKBUF];
- /* setup view context for argument to callbacks */
- view3d_operator_needs_opengl(C);
+ /* setup view context for argument to callbacks */
+ view3d_operator_needs_opengl(C);
- ED_view3d_viewcontext_init(C, &vc);
+ ED_view3d_viewcontext_init(C, &vc);
- const bool do_nearest = !XRAY_ACTIVE(vc.v3d);
- const int hits = mixed_bones_object_selectbuffer(
- &vc, buffer, mval, VIEW3D_SELECT_FILTER_NOP, do_nearest);
+ const bool do_nearest = !XRAY_ACTIVE(vc.v3d);
+ const int hits = mixed_bones_object_selectbuffer(
+ &vc, buffer, mval, VIEW3D_SELECT_FILTER_NOP, do_nearest);
- if (hits > 0) {
- const bool has_bones = selectbuffer_has_bones(buffer, hits);
- basact = mouse_select_eval_buffer(&vc, buffer, hits, vc.view_layer->object_bases.first, has_bones, do_nearest);
- }
+ if (hits > 0) {
+ const bool has_bones = selectbuffer_has_bones(buffer, hits);
+ basact = mouse_select_eval_buffer(
+ &vc, buffer, hits, vc.view_layer->object_bases.first, has_bones, do_nearest);
+ }
- return basact;
+ return basact;
}
Object *ED_view3d_give_object_under_cursor(bContext *C, const int mval[2])
{
- Base *base = ED_view3d_give_base_under_cursor(C, mval);
- if (base) {
- return base->object;
- }
- return NULL;
+ Base *base = ED_view3d_give_base_under_cursor(C, mval);
+ if (base) {
+ return base->object;
+ }
+ return NULL;
}
bool ED_view3d_is_object_under_cursor(bContext *C, const int mval[2])
{
- return ED_view3d_give_object_under_cursor(C, mval) != NULL;
+ return ED_view3d_give_object_under_cursor(C, mval) != NULL;
}
static void deselect_all_tracks(MovieTracking *tracking)
{
- MovieTrackingObject *object;
+ MovieTrackingObject *object;
- object = tracking->objects.first;
- while (object) {
- ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
- MovieTrackingTrack *track = tracksbase->first;
+ object = tracking->objects.first;
+ while (object) {
+ ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
+ MovieTrackingTrack *track = tracksbase->first;
- while (track) {
- BKE_tracking_track_deselect(track, TRACK_AREA_ALL);
+ while (track) {
+ BKE_tracking_track_deselect(track, TRACK_AREA_ALL);
- track = track->next;
- }
+ track = track->next;
+ }
- object = object->next;
- }
+ object = object->next;
+ }
}
/* mval is region coords */
-static bool ed_object_select_pick(
- bContext *C, const int mval[2],
- bool extend, bool deselect, bool toggle, bool obcenter, bool enumerate, bool object)
-{
- ViewContext vc;
- /* setup view context for argument to callbacks */
- ED_view3d_viewcontext_init(C, &vc);
-
- ARegion *ar = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- /* Don't set when the context has no active object (hidden), see: T60807. */
- const Base *oldbasact = vc.obact ? BASACT(view_layer) : NULL;
- Base *base, *startbase = NULL, *basact = NULL;
- const eObjectMode object_mode = oldbasact ? oldbasact->object->mode : OB_MODE_OBJECT;
- bool is_obedit;
- float dist = ED_view3d_select_dist_px() * 1.3333f;
- bool retval = false;
- int hits;
- const float mval_fl[2] = {(float)mval[0], (float)mval[1]};
-
-
- is_obedit = (vc.obedit != NULL);
- if (object) {
- /* signal for view3d_opengl_select to skip editmode objects */
- vc.obedit = NULL;
- }
-
- /* In pose mode we don't want to mess with object selection. */
- const bool is_pose_mode = (vc.obact && vc.obact->mode & OB_MODE_POSE);
-
- /* always start list from basact in wire mode */
- startbase = FIRSTBASE(view_layer);
- if (oldbasact && oldbasact->next) {
- startbase = oldbasact->next;
- }
-
- /* This block uses the control key to make the object selected
- * by its center point rather than its contents */
-
- /* in editmode do not activate */
- if (obcenter) {
-
- /* note; shift+alt goes to group-flush-selecting */
- if (enumerate) {
- basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, toggle);
- }
- else {
- base = startbase;
- while (base) {
- if (BASE_SELECTABLE(v3d, base)) {
- float screen_co[2];
- if (ED_view3d_project_float_global(
- ar, base->object->obmat[3], screen_co,
- V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
- {
- float dist_temp = len_manhattan_v2v2(mval_fl, screen_co);
- if (base == oldbasact) {
- dist_temp += 10.0f;
- }
- if (dist_temp < dist) {
- dist = dist_temp;
- basact = base;
- }
- }
- }
- base = base->next;
-
- if (base == NULL) {
- base = FIRSTBASE(view_layer);
- }
- if (base == startbase) {
- break;
- }
- }
- }
- if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
- if (is_obedit == false) {
- if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) {
- if (object_mode == OB_MODE_OBJECT) {
- struct Main *bmain = CTX_data_main(C);
- ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object);
- }
- if (!BKE_object_is_mode_compat(basact->object, object_mode)) {
- basact = NULL;
- }
- }
- }
- }
- }
- else {
- uint buffer[MAXPICKBUF];
- bool do_nearest;
-
- // TIMEIT_START(select_time);
-
- /* if objects have posemode set, the bones are in the same selection buffer */
- const eV3DSelectObjectFilter select_filter = (
- (object == false) ? ED_view3d_select_filter_from_mode(scene, vc.obact) : VIEW3D_SELECT_FILTER_NOP);
- hits = mixed_bones_object_selectbuffer_extended(
- &vc, buffer, mval, select_filter,
- true, enumerate,
- &do_nearest);
-
- // TIMEIT_END(select_time);
-
- if (hits > 0) {
- /* note: bundles are handling in the same way as bones */
- const bool has_bones = selectbuffer_has_bones(buffer, hits);
-
- /* note; shift+alt goes to group-flush-selecting */
- if (enumerate) {
- basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, toggle);
- }
- else {
- basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, has_bones, do_nearest);
- }
-
- if (has_bones && basact) {
- if (basact->object->type == OB_CAMERA) {
- if (oldbasact == basact) {
- int i, hitresult;
- bool changed = false;
-
- for (i = 0; i < hits; i++) {
- hitresult = buffer[3 + (i * 4)];
-
- /* if there's bundles in buffer select bundles first,
- * so non-camera elements should be ignored in buffer */
- if (basact->object->select_id != (hitresult & 0xFFFF)) {
- continue;
- }
-
- /* index of bundle is 1<<16-based. if there's no "bone" index
- * in height word, this buffer value belongs to camera. not to bundle
- */
- if (buffer[4 * i + 3] & 0xFFFF0000) {
- MovieClip *clip = BKE_object_movieclip_get(scene, basact->object, false);
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase;
- MovieTrackingTrack *track;
-
- track = BKE_tracking_track_get_indexed(&clip->tracking, hitresult >> 16, &tracksbase);
-
- if (TRACK_SELECTED(track) && extend) {
- changed = false;
- BKE_tracking_track_deselect(track, TRACK_AREA_ALL);
- }
- else {
- int oldsel = TRACK_SELECTED(track) ? 1 : 0;
- if (!extend) {
- deselect_all_tracks(tracking);
- }
-
- BKE_tracking_track_select(tracksbase, track, TRACK_AREA_ALL, extend);
-
- if (oldsel != (TRACK_SELECTED(track) ? 1 : 0)) {
- changed = true;
- }
- }
-
- basact->flag |= BASE_SELECTED;
- BKE_scene_object_base_flag_sync_from_base(basact);
-
- retval = true;
-
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, track);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-
- break;
- }
- }
-
- if (!changed) {
- /* fallback to regular object selection if no new bundles were selected,
- * allows to select object parented to reconstruction object */
- basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, 0, do_nearest);
- }
- }
- }
- else if (ED_armature_pose_select_pick_with_buffer(
- view_layer, v3d, basact, buffer, hits, extend, deselect, toggle, do_nearest))
- {
- /* then bone is found */
-
- /* we make the armature selected:
- * not-selected active object in posemode won't work well for tools */
- basact->flag |= BASE_SELECTED;
- BKE_scene_object_base_flag_sync_from_base(basact);
-
- retval = true;
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object);
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, basact->object);
-
- /* in weightpaint, we use selected bone to select vertexgroup,
- * so no switch to new active object */
- if (oldbasact && (oldbasact->object->mode & OB_MODE_WEIGHT_PAINT)) {
- /* prevent activating */
- basact = NULL;
- }
-
- }
- /* prevent bone selecting to pass on to object selecting */
- if (basact == oldbasact) {
- basact = NULL;
- }
- }
-
- if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
- if (is_obedit == false) {
- if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) {
- if (object_mode == OB_MODE_OBJECT) {
- struct Main *bmain = CTX_data_main(C);
- ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object);
- }
- if (!BKE_object_is_mode_compat(basact->object, object_mode)) {
- basact = NULL;
- }
- }
- }
- }
- }
- }
-
- if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
- /* Disallow switching modes,
- * special exception for edit-mode - vertex-parent operator. */
- if (is_obedit == false) {
- if (oldbasact && basact) {
- if ((oldbasact->object->mode != basact->object->mode) &&
- (oldbasact->object->mode & basact->object->mode) == 0)
- {
- basact = NULL;
- }
- }
- }
- }
-
- /* Ensure code above doesn't change the active base. */
- BLI_assert(oldbasact == (vc.obact ? BASACT(view_layer) : NULL));
-
- /* so, do we have something selected? */
- if (basact) {
- retval = true;
-
- if (vc.obedit) {
- /* only do select */
- object_deselect_all_except(view_layer, basact);
- ED_object_base_select(basact, BA_SELECT);
- }
- /* also prevent making it active on mouse selection */
- else if (BASE_SELECTABLE(v3d, basact)) {
- if (extend) {
- ED_object_base_select(basact, BA_SELECT);
- }
- else if (deselect) {
- ED_object_base_select(basact, BA_DESELECT);
- }
- else if (toggle) {
- if (basact->flag & BASE_SELECTED) {
- if (basact == oldbasact) {
- ED_object_base_select(basact, BA_DESELECT);
- }
- }
- else {
- ED_object_base_select(basact, BA_SELECT);
- }
- }
- else {
- /* When enabled, this puts other objects out of multi pose-mode. */
- if (is_pose_mode == false) {
- object_deselect_all_except(view_layer, basact);
- ED_object_base_select(basact, BA_SELECT);
- }
- }
-
- if ((oldbasact != basact) && (is_obedit == false)) {
- ED_object_base_activate(C, basact); /* adds notifier */
- }
-
- /* Set special modes for grease pencil
- The grease pencil modes are not real modes, but a hack to make the interface
- consistent, so need some tricks to keep UI synchronized */
- // XXX: This stuff needs reviewing (Aligorith)
- if (false &&
- (((oldbasact) && oldbasact->object->type == OB_GPENCIL) ||
- (basact->object->type == OB_GPENCIL)))
- {
- /* set cursor */
- if (ELEM(basact->object->mode,
- OB_MODE_PAINT_GPENCIL,
- OB_MODE_SCULPT_GPENCIL,
- OB_MODE_WEIGHT_GPENCIL))
- {
- ED_gpencil_toggle_brush_cursor(C, true, NULL);
- }
- else {
- /* TODO: maybe is better use restore */
- ED_gpencil_toggle_brush_cursor(C, false, NULL);
- }
- }
- }
-
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
-
- return retval;
+static bool ed_object_select_pick(bContext *C,
+ const int mval[2],
+ bool extend,
+ bool deselect,
+ bool toggle,
+ bool obcenter,
+ bool enumerate,
+ bool object)
+{
+ ViewContext vc;
+ /* setup view context for argument to callbacks */
+ ED_view3d_viewcontext_init(C, &vc);
+
+ ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ /* Don't set when the context has no active object (hidden), see: T60807. */
+ const Base *oldbasact = vc.obact ? BASACT(view_layer) : NULL;
+ Base *base, *startbase = NULL, *basact = NULL;
+ const eObjectMode object_mode = oldbasact ? oldbasact->object->mode : OB_MODE_OBJECT;
+ bool is_obedit;
+ float dist = ED_view3d_select_dist_px() * 1.3333f;
+ bool retval = false;
+ int hits;
+ const float mval_fl[2] = {(float)mval[0], (float)mval[1]};
+
+ is_obedit = (vc.obedit != NULL);
+ if (object) {
+ /* signal for view3d_opengl_select to skip editmode objects */
+ vc.obedit = NULL;
+ }
+
+ /* In pose mode we don't want to mess with object selection. */
+ const bool is_pose_mode = (vc.obact && vc.obact->mode & OB_MODE_POSE);
+
+ /* always start list from basact in wire mode */
+ startbase = FIRSTBASE(view_layer);
+ if (oldbasact && oldbasact->next) {
+ startbase = oldbasact->next;
+ }
+
+ /* This block uses the control key to make the object selected
+ * by its center point rather than its contents */
+
+ /* in editmode do not activate */
+ if (obcenter) {
+
+ /* note; shift+alt goes to group-flush-selecting */
+ if (enumerate) {
+ basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, toggle);
+ }
+ else {
+ base = startbase;
+ while (base) {
+ if (BASE_SELECTABLE(v3d, base)) {
+ float screen_co[2];
+ if (ED_view3d_project_float_global(ar,
+ base->object->obmat[3],
+ screen_co,
+ V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN |
+ V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) {
+ float dist_temp = len_manhattan_v2v2(mval_fl, screen_co);
+ if (base == oldbasact) {
+ dist_temp += 10.0f;
+ }
+ if (dist_temp < dist) {
+ dist = dist_temp;
+ basact = base;
+ }
+ }
+ }
+ base = base->next;
+
+ if (base == NULL) {
+ base = FIRSTBASE(view_layer);
+ }
+ if (base == startbase) {
+ break;
+ }
+ }
+ }
+ if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ if (is_obedit == false) {
+ if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) {
+ if (object_mode == OB_MODE_OBJECT) {
+ struct Main *bmain = CTX_data_main(C);
+ ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object);
+ }
+ if (!BKE_object_is_mode_compat(basact->object, object_mode)) {
+ basact = NULL;
+ }
+ }
+ }
+ }
+ }
+ else {
+ uint buffer[MAXPICKBUF];
+ bool do_nearest;
+
+ // TIMEIT_START(select_time);
+
+ /* if objects have posemode set, the bones are in the same selection buffer */
+ const eV3DSelectObjectFilter select_filter = ((object == false) ?
+ ED_view3d_select_filter_from_mode(scene,
+ vc.obact) :
+ VIEW3D_SELECT_FILTER_NOP);
+ hits = mixed_bones_object_selectbuffer_extended(
+ &vc, buffer, mval, select_filter, true, enumerate, &do_nearest);
+
+ // TIMEIT_END(select_time);
+
+ if (hits > 0) {
+ /* note: bundles are handling in the same way as bones */
+ const bool has_bones = selectbuffer_has_bones(buffer, hits);
+
+ /* note; shift+alt goes to group-flush-selecting */
+ if (enumerate) {
+ basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, toggle);
+ }
+ else {
+ basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, has_bones, do_nearest);
+ }
+
+ if (has_bones && basact) {
+ if (basact->object->type == OB_CAMERA) {
+ if (oldbasact == basact) {
+ int i, hitresult;
+ bool changed = false;
+
+ for (i = 0; i < hits; i++) {
+ hitresult = buffer[3 + (i * 4)];
+
+ /* if there's bundles in buffer select bundles first,
+ * so non-camera elements should be ignored in buffer */
+ if (basact->object->select_id != (hitresult & 0xFFFF)) {
+ continue;
+ }
+
+ /* index of bundle is 1<<16-based. if there's no "bone" index
+ * in height word, this buffer value belongs to camera. not to bundle
+ */
+ if (buffer[4 * i + 3] & 0xFFFF0000) {
+ MovieClip *clip = BKE_object_movieclip_get(scene, basact->object, false);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracksbase;
+ MovieTrackingTrack *track;
+
+ track = BKE_tracking_track_get_indexed(
+ &clip->tracking, hitresult >> 16, &tracksbase);
+
+ if (TRACK_SELECTED(track) && extend) {
+ changed = false;
+ BKE_tracking_track_deselect(track, TRACK_AREA_ALL);
+ }
+ else {
+ int oldsel = TRACK_SELECTED(track) ? 1 : 0;
+ if (!extend) {
+ deselect_all_tracks(tracking);
+ }
+
+ BKE_tracking_track_select(tracksbase, track, TRACK_AREA_ALL, extend);
+
+ if (oldsel != (TRACK_SELECTED(track) ? 1 : 0)) {
+ changed = true;
+ }
+ }
+
+ basact->flag |= BASE_SELECTED;
+ BKE_scene_object_base_flag_sync_from_base(basact);
+
+ retval = true;
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, track);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+ break;
+ }
+ }
+
+ if (!changed) {
+ /* fallback to regular object selection if no new bundles were selected,
+ * allows to select object parented to reconstruction object */
+ basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, 0, do_nearest);
+ }
+ }
+ }
+ else if (ED_armature_pose_select_pick_with_buffer(view_layer,
+ v3d,
+ basact,
+ buffer,
+ hits,
+ extend,
+ deselect,
+ toggle,
+ do_nearest)) {
+ /* then bone is found */
+
+ /* we make the armature selected:
+ * not-selected active object in posemode won't work well for tools */
+ basact->flag |= BASE_SELECTED;
+ BKE_scene_object_base_flag_sync_from_base(basact);
+
+ retval = true;
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, basact->object);
+
+ /* in weightpaint, we use selected bone to select vertexgroup,
+ * so no switch to new active object */
+ if (oldbasact && (oldbasact->object->mode & OB_MODE_WEIGHT_PAINT)) {
+ /* prevent activating */
+ basact = NULL;
+ }
+ }
+ /* prevent bone selecting to pass on to object selecting */
+ if (basact == oldbasact) {
+ basact = NULL;
+ }
+ }
+
+ if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ if (is_obedit == false) {
+ if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) {
+ if (object_mode == OB_MODE_OBJECT) {
+ struct Main *bmain = CTX_data_main(C);
+ ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object);
+ }
+ if (!BKE_object_is_mode_compat(basact->object, object_mode)) {
+ basact = NULL;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ /* Disallow switching modes,
+ * special exception for edit-mode - vertex-parent operator. */
+ if (is_obedit == false) {
+ if (oldbasact && basact) {
+ if ((oldbasact->object->mode != basact->object->mode) &&
+ (oldbasact->object->mode & basact->object->mode) == 0) {
+ basact = NULL;
+ }
+ }
+ }
+ }
+
+ /* Ensure code above doesn't change the active base. */
+ BLI_assert(oldbasact == (vc.obact ? BASACT(view_layer) : NULL));
+
+ /* so, do we have something selected? */
+ if (basact) {
+ retval = true;
+
+ if (vc.obedit) {
+ /* only do select */
+ object_deselect_all_except(view_layer, basact);
+ ED_object_base_select(basact, BA_SELECT);
+ }
+ /* also prevent making it active on mouse selection */
+ else if (BASE_SELECTABLE(v3d, basact)) {
+ if (extend) {
+ ED_object_base_select(basact, BA_SELECT);
+ }
+ else if (deselect) {
+ ED_object_base_select(basact, BA_DESELECT);
+ }
+ else if (toggle) {
+ if (basact->flag & BASE_SELECTED) {
+ if (basact == oldbasact) {
+ ED_object_base_select(basact, BA_DESELECT);
+ }
+ }
+ else {
+ ED_object_base_select(basact, BA_SELECT);
+ }
+ }
+ else {
+ /* When enabled, this puts other objects out of multi pose-mode. */
+ if (is_pose_mode == false) {
+ object_deselect_all_except(view_layer, basact);
+ ED_object_base_select(basact, BA_SELECT);
+ }
+ }
+
+ if ((oldbasact != basact) && (is_obedit == false)) {
+ ED_object_base_activate(C, basact); /* adds notifier */
+ }
+
+ /* Set special modes for grease pencil
+ The grease pencil modes are not real modes, but a hack to make the interface
+ consistent, so need some tricks to keep UI synchronized */
+ // XXX: This stuff needs reviewing (Aligorith)
+ if (false && (((oldbasact) && oldbasact->object->type == OB_GPENCIL) ||
+ (basact->object->type == OB_GPENCIL))) {
+ /* set cursor */
+ if (ELEM(basact->object->mode,
+ OB_MODE_PAINT_GPENCIL,
+ OB_MODE_SCULPT_GPENCIL,
+ OB_MODE_WEIGHT_GPENCIL)) {
+ ED_gpencil_toggle_brush_cursor(C, true, NULL);
+ }
+ else {
+ /* TODO: maybe is better use restore */
+ ED_gpencil_toggle_brush_cursor(C, false, NULL);
+ }
+ }
+ }
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ }
+
+ return retval;
}
/* mouse selection in weight paint */
/* gets called via generic mouse select operator */
static bool ed_wpaint_vertex_select_pick(
- bContext *C, const int mval[2],
- bool extend, bool deselect, bool toggle, Object *obact)
-{
- View3D *v3d = CTX_wm_view3d(C);
- const bool use_zbuf = !XRAY_ENABLED(v3d);
-
- Mesh *me = obact->data; /* already checked for NULL */
- uint index = 0;
- MVert *mv;
-
- if (ED_mesh_pick_vert(C, obact, mval, ED_MESH_PICK_DEFAULT_VERT_DIST, use_zbuf, &index)) {
- mv = &me->mvert[index];
- if (extend) {
- mv->flag |= SELECT;
- }
- else if (deselect) {
- mv->flag &= ~SELECT;
- }
- else if (toggle) {
- mv->flag ^= SELECT;
- }
- else {
- paintvert_deselect_all_visible(obact, SEL_DESELECT, false);
- mv->flag |= SELECT;
- }
-
- /* update mselect */
- if (mv->flag & SELECT) {
- BKE_mesh_mselect_active_set(me, index, ME_VSEL);
- }
- else {
- BKE_mesh_mselect_validate(me);
- }
-
- paintvert_flush_flags(obact);
- paintvert_tag_select_update(C, obact);
- return true;
- }
- return false;
+ bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, Object *obact)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ const bool use_zbuf = !XRAY_ENABLED(v3d);
+
+ Mesh *me = obact->data; /* already checked for NULL */
+ uint index = 0;
+ MVert *mv;
+
+ if (ED_mesh_pick_vert(C, obact, mval, ED_MESH_PICK_DEFAULT_VERT_DIST, use_zbuf, &index)) {
+ mv = &me->mvert[index];
+ if (extend) {
+ mv->flag |= SELECT;
+ }
+ else if (deselect) {
+ mv->flag &= ~SELECT;
+ }
+ else if (toggle) {
+ mv->flag ^= SELECT;
+ }
+ else {
+ paintvert_deselect_all_visible(obact, SEL_DESELECT, false);
+ mv->flag |= SELECT;
+ }
+
+ /* update mselect */
+ if (mv->flag & SELECT) {
+ BKE_mesh_mselect_active_set(me, index, ME_VSEL);
+ }
+ else {
+ BKE_mesh_mselect_validate(me);
+ }
+
+ paintvert_flush_flags(obact);
+ paintvert_tag_select_update(C, obact);
+ return true;
+ }
+ return false;
}
static int view3d_select_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- Object *obact = CTX_data_active_object(C);
- bool extend = RNA_boolean_get(op->ptr, "extend");
- bool deselect = RNA_boolean_get(op->ptr, "deselect");
- bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
- 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 */
- 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) */
- (obact && (obact->mode & OB_MODE_WEIGHT_PAINT) && BKE_object_pose_armature_get(obact))));
-
- bool retval = false;
- int location[2];
-
- RNA_int_get_array(op->ptr, "location", location);
-
- view3d_operator_needs_opengl(C);
-
- if (object) {
- obedit = NULL;
- 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 */
- center = false;
- }
-
- if (obedit && object == false) {
- if (obedit->type == OB_MESH) {
- retval = EDBM_select_pick(C, location, extend, deselect, toggle);
- if (!retval && deselect_all) {
- retval = EDBM_mesh_deselect_all_multi(C);
- }
- }
- else if (obedit->type == OB_ARMATURE) {
- retval = ED_armature_edit_select_pick(C, location, extend, deselect, toggle);
- if (!retval && deselect_all) {
- retval = ED_armature_edit_deselect_all_visible_multi(C);
- }
- }
- else if (obedit->type == OB_LATTICE) {
- retval = ED_lattice_select_pick(C, location, extend, deselect, toggle);
- if (!retval && deselect_all) {
- retval = ED_lattice_deselect_all_multi(C);
- }
- }
- else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
- retval = ED_curve_editnurb_select_pick(C, location, extend, deselect, toggle);
- if (!retval && deselect_all) {
- retval = ED_curve_deselect_all_multi(C);
- }
- }
- else if (obedit->type == OB_MBALL) {
- retval = ED_mball_select_pick(C, location, extend, deselect, toggle);
- if (!retval && deselect_all) {
- retval = ED_mball_deselect_all_multi(C);
- }
- }
- else if (obedit->type == OB_FONT) {
- retval = ED_curve_editfont_select_pick(C, location, extend, deselect, toggle);
- if (!retval && deselect_all) {
- /* pass */
- }
- }
-
- }
- else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
- retval = PE_mouse_particles(C, location, extend, deselect, toggle);
- if (!retval && deselect_all) {
- retval = PE_deselect_all_visible(C);
- }
- }
- else if (obact && BKE_paint_select_face_test(obact)) {
- retval = paintface_mouse_select(C, obact, location, extend, deselect, toggle);
- if (!retval && deselect_all) {
- retval = paintface_deselect_all_visible(C, CTX_data_active_object(C), SEL_DESELECT, false);
- }
- }
- else if (BKE_paint_select_vert_test(obact)) {
- retval = ed_wpaint_vertex_select_pick(C, location, extend, deselect, toggle, obact);
- if (!retval && deselect_all) {
- retval = paintvert_deselect_all_visible(obact, SEL_DESELECT, false);
- }
- }
- else {
- retval = ed_object_select_pick(C, location, extend, deselect, toggle, center, enumerate, object);
- if (!retval && deselect_all) {
- if (ED_pose_object_from_context(C)) {
- retval = ED_pose_deselect_all_multi(C, SEL_DESELECT, false);
- }
- else {
- retval = ED_object_base_deselect_all(CTX_data_view_layer(C), CTX_wm_view3d(C), SEL_DESELECT);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- }
- }
- }
-
- /* passthrough allows tweaks
- * FINISHED to signal one operator worked
- * */
- if (retval) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_PASS_THROUGH; /* nothing selected, just passthrough */
- }
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ Object *obact = CTX_data_active_object(C);
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+ bool deselect = RNA_boolean_get(op->ptr, "deselect");
+ bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
+ 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 */
+ 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) */
+ (obact && (obact->mode & OB_MODE_WEIGHT_PAINT) &&
+ BKE_object_pose_armature_get(obact))));
+
+ bool retval = false;
+ int location[2];
+
+ RNA_int_get_array(op->ptr, "location", location);
+
+ view3d_operator_needs_opengl(C);
+
+ if (object) {
+ obedit = NULL;
+ 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 */
+ center = false;
+ }
+
+ if (obedit && object == false) {
+ if (obedit->type == OB_MESH) {
+ retval = EDBM_select_pick(C, location, extend, deselect, toggle);
+ if (!retval && deselect_all) {
+ retval = EDBM_mesh_deselect_all_multi(C);
+ }
+ }
+ else if (obedit->type == OB_ARMATURE) {
+ retval = ED_armature_edit_select_pick(C, location, extend, deselect, toggle);
+ if (!retval && deselect_all) {
+ retval = ED_armature_edit_deselect_all_visible_multi(C);
+ }
+ }
+ else if (obedit->type == OB_LATTICE) {
+ retval = ED_lattice_select_pick(C, location, extend, deselect, toggle);
+ if (!retval && deselect_all) {
+ retval = ED_lattice_deselect_all_multi(C);
+ }
+ }
+ else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ retval = ED_curve_editnurb_select_pick(C, location, extend, deselect, toggle);
+ if (!retval && deselect_all) {
+ retval = ED_curve_deselect_all_multi(C);
+ }
+ }
+ else if (obedit->type == OB_MBALL) {
+ retval = ED_mball_select_pick(C, location, extend, deselect, toggle);
+ if (!retval && deselect_all) {
+ retval = ED_mball_deselect_all_multi(C);
+ }
+ }
+ else if (obedit->type == OB_FONT) {
+ retval = ED_curve_editfont_select_pick(C, location, extend, deselect, toggle);
+ if (!retval && deselect_all) {
+ /* pass */
+ }
+ }
+ }
+ else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
+ retval = PE_mouse_particles(C, location, extend, deselect, toggle);
+ if (!retval && deselect_all) {
+ retval = PE_deselect_all_visible(C);
+ }
+ }
+ else if (obact && BKE_paint_select_face_test(obact)) {
+ retval = paintface_mouse_select(C, obact, location, extend, deselect, toggle);
+ if (!retval && deselect_all) {
+ retval = paintface_deselect_all_visible(C, CTX_data_active_object(C), SEL_DESELECT, false);
+ }
+ }
+ else if (BKE_paint_select_vert_test(obact)) {
+ retval = ed_wpaint_vertex_select_pick(C, location, extend, deselect, toggle, obact);
+ if (!retval && deselect_all) {
+ retval = paintvert_deselect_all_visible(obact, SEL_DESELECT, false);
+ }
+ }
+ else {
+ retval = ed_object_select_pick(
+ C, location, extend, deselect, toggle, center, enumerate, object);
+ if (!retval && deselect_all) {
+ if (ED_pose_object_from_context(C)) {
+ retval = ED_pose_deselect_all_multi(C, SEL_DESELECT, false);
+ }
+ else {
+ retval = ED_object_base_deselect_all(
+ CTX_data_view_layer(C), CTX_wm_view3d(C), SEL_DESELECT);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ }
+ }
+ }
+
+ /* passthrough allows tweaks
+ * FINISHED to signal one operator worked
+ * */
+ if (retval) {
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_PASS_THROUGH; /* nothing selected, just passthrough */
+ }
}
static int view3d_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- RNA_int_set_array(op->ptr, "location", event->mval);
+ RNA_int_set_array(op->ptr, "location", event->mval);
- return view3d_select_exec(C, op);
+ return view3d_select_exec(C, op);
}
void VIEW3D_OT_select(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Select";
- ot->description = "Select and activate item(s)";
- ot->idname = "VIEW3D_OT_select";
-
- /* api callbacks */
- ot->invoke = view3d_select_invoke;
- ot->exec = view3d_select_exec;
- ot->poll = ED_operator_view3d_active;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_mouse_select(ot);
- prop = RNA_def_boolean(ot->srna, "deselect_all", 0, "Deselect", "Deselect all when nothing under the cursor");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- prop = RNA_def_boolean(ot->srna, "center", 0, "Center", "Use the object center when selecting, in editmode 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)");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- prop = RNA_def_int_vector(ot->srna, "location", 2, NULL, INT_MIN, INT_MAX, "Location", "Mouse location", INT_MIN, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select";
+ ot->description = "Select and activate item(s)";
+ ot->idname = "VIEW3D_OT_select";
+
+ /* api callbacks */
+ ot->invoke = view3d_select_invoke;
+ ot->exec = view3d_select_exec;
+ ot->poll = ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_mouse_select(ot);
+ prop = RNA_def_boolean(
+ ot->srna, "deselect_all", 0, "Deselect", "Deselect all when nothing under the cursor");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(
+ ot->srna,
+ "center",
+ 0,
+ "Center",
+ "Use the object center when selecting, in editmode 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)");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_int_vector(ot->srna,
+ "location",
+ 2,
+ NULL,
+ INT_MIN,
+ INT_MAX,
+ "Location",
+ "Mouse location",
+ INT_MIN,
+ INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/** \} */
@@ -2198,453 +2289,468 @@ void VIEW3D_OT_select(wmOperatorType *ot)
* \{ */
typedef struct BoxSelectUserData {
- ViewContext *vc;
- const rcti *rect;
- const rctf *rect_fl;
- rctf _rect_fl;
- eSelectOp sel_op;
-
- /* runtime */
- bool is_done;
- bool is_changed;
+ ViewContext *vc;
+ const rcti *rect;
+ const rctf *rect_fl;
+ rctf _rect_fl;
+ eSelectOp sel_op;
+
+ /* runtime */
+ bool is_done;
+ bool is_changed;
} BoxSelectUserData;
-static void view3d_userdata_boxselect_init(
- BoxSelectUserData *r_data,
- ViewContext *vc, const rcti *rect, const eSelectOp sel_op)
-{
- r_data->vc = vc;
-
- r_data->rect = rect;
- r_data->rect_fl = &r_data->_rect_fl;
- BLI_rctf_rcti_copy(&r_data->_rect_fl, rect);
-
- r_data->sel_op = sel_op;
-
- /* runtime */
- r_data->is_done = false;
- r_data->is_changed = false;
-}
-
-bool edge_inside_circle(const float cent[2], float radius, const float screen_co_a[2], const float screen_co_b[2])
-{
- const float radius_squared = radius * radius;
- return (dist_squared_to_line_segment_v2(cent, screen_co_a, screen_co_b) < radius_squared);
-}
-
-static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
-{
- BoxSelectUserData *data = userData;
- const bool is_select = mv->flag & SELECT;
- const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co);
- 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);
- data->is_changed = true;
- }
-}
-static bool do_paintvert_box_select(
- ViewContext *vc, const rcti *rect, const eSelectOp sel_op)
-{
- const bool use_zbuf = !XRAY_ENABLED(vc->v3d);
- Mesh *me;
-
- me = vc->obact->data;
- if ((me == NULL) || (me->totvert == 0)) {
- return OPERATOR_CANCELLED;
- }
-
- bool changed = false;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- changed |= paintvert_deselect_all_visible(vc->obact, SEL_DESELECT, false);
- }
-
- if (BLI_rcti_is_empty(rect)) {
- /* pass */
- }
- else if (use_zbuf) {
- MVert *mvert;
- unsigned int *rt;
- int a, index;
- char *selar;
-
- selar = MEM_callocN(me->totvert + 1, "selar");
-
- uint buf_len;
- uint *buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len);
-
- rt = buf;
-
- a = buf_len;
- while (a--) {
- if (*rt) {
- index = *rt;
- if (index <= me->totvert) {
- selar[index] = 1;
- }
- }
- rt++;
- }
-
- mvert = me->mvert;
- for (a = 1; a <= me->totvert; a++, mvert++) {
- if ((mvert->flag & ME_HIDE) == 0) {
- const bool is_select = mvert->flag & SELECT;
- const bool is_inside = (selar[a] != 0);
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(mvert->flag, sel_op_result, SELECT);
- changed = true;
- }
- }
- }
-
- MEM_freeN(buf);
- MEM_freeN(selar);
+static void view3d_userdata_boxselect_init(BoxSelectUserData *r_data,
+ ViewContext *vc,
+ const rcti *rect,
+ const eSelectOp sel_op)
+{
+ r_data->vc = vc;
+
+ r_data->rect = rect;
+ r_data->rect_fl = &r_data->_rect_fl;
+ BLI_rctf_rcti_copy(&r_data->_rect_fl, rect);
+
+ r_data->sel_op = sel_op;
+
+ /* runtime */
+ r_data->is_done = false;
+ r_data->is_changed = false;
+}
+
+bool edge_inside_circle(const float cent[2],
+ float radius,
+ const float screen_co_a[2],
+ const float screen_co_b[2])
+{
+ const float radius_squared = radius * radius;
+ return (dist_squared_to_line_segment_v2(cent, screen_co_a, screen_co_b) < radius_squared);
+}
+
+static void do_paintvert_box_select__doSelectVert(void *userData,
+ MVert *mv,
+ const float screen_co[2],
+ int UNUSED(index))
+{
+ BoxSelectUserData *data = userData;
+ const bool is_select = mv->flag & SELECT;
+ const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co);
+ 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);
+ data->is_changed = true;
+ }
+}
+static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSelectOp sel_op)
+{
+ const bool use_zbuf = !XRAY_ENABLED(vc->v3d);
+ Mesh *me;
+
+ me = vc->obact->data;
+ if ((me == NULL) || (me->totvert == 0)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ bool changed = false;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ changed |= paintvert_deselect_all_visible(vc->obact, SEL_DESELECT, false);
+ }
+
+ if (BLI_rcti_is_empty(rect)) {
+ /* pass */
+ }
+ else if (use_zbuf) {
+ MVert *mvert;
+ unsigned int *rt;
+ int a, index;
+ char *selar;
+
+ selar = MEM_callocN(me->totvert + 1, "selar");
+
+ uint buf_len;
+ uint *buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len);
+
+ rt = buf;
+
+ a = buf_len;
+ while (a--) {
+ if (*rt) {
+ index = *rt;
+ if (index <= me->totvert) {
+ selar[index] = 1;
+ }
+ }
+ rt++;
+ }
+
+ mvert = me->mvert;
+ for (a = 1; a <= me->totvert; a++, mvert++) {
+ if ((mvert->flag & ME_HIDE) == 0) {
+ const bool is_select = mvert->flag & SELECT;
+ const bool is_inside = (selar[a] != 0);
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ SET_FLAG_FROM_TEST(mvert->flag, sel_op_result, SELECT);
+ changed = true;
+ }
+ }
+ }
+
+ MEM_freeN(buf);
+ MEM_freeN(selar);
#ifdef __APPLE__
- glReadBuffer(GL_BACK);
+ glReadBuffer(GL_BACK);
#endif
- }
- else {
- BoxSelectUserData data;
-
- view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
-
- ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
-
- meshobject_foreachScreenVert(vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- changed |= data.is_changed;
- }
-
- if (changed) {
- if (SEL_OP_CAN_DESELECT(sel_op)) {
- BKE_mesh_mselect_validate(me);
- }
- paintvert_flush_flags(vc->obact);
- paintvert_tag_select_update(vc->C, vc->obact);
- }
- return changed;
-}
-
-static void do_nurbs_box_select__doSelect(
- void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
-{
- BoxSelectUserData *data = userData;
-
- const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co);
- 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);
- if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT);
- data->is_changed = true;
- }
- }
- else {
- if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
- /* can only be (beztindex == 0) here since handles are hidden */
- const bool is_select = bezt->f2 & SELECT;
- const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, SELECT);
- data->is_changed = true;
- }
- bezt->f1 = bezt->f3 = bezt->f2;
- }
- else {
- char *flag_p = (&bezt->f1) + beztindex;
- const bool is_select = *flag_p & SELECT;
- const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(*flag_p, sel_op_result, SELECT);
- data->is_changed = true;
- }
- }
- }
+ }
+ else {
+ BoxSelectUserData data;
+
+ view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
+
+ ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
+
+ meshobject_foreachScreenVert(
+ vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ changed |= data.is_changed;
+ }
+
+ if (changed) {
+ if (SEL_OP_CAN_DESELECT(sel_op)) {
+ BKE_mesh_mselect_validate(me);
+ }
+ paintvert_flush_flags(vc->obact);
+ paintvert_tag_select_update(vc->C, vc->obact);
+ }
+ return changed;
+}
+
+static void do_nurbs_box_select__doSelect(void *userData,
+ Nurb *UNUSED(nu),
+ BPoint *bp,
+ BezTriple *bezt,
+ int beztindex,
+ const float screen_co[2])
+{
+ BoxSelectUserData *data = userData;
+
+ const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co);
+ 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);
+ if (sel_op_result != -1) {
+ SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT);
+ data->is_changed = true;
+ }
+ }
+ else {
+ if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
+ /* can only be (beztindex == 0) here since handles are hidden */
+ const bool is_select = bezt->f2 & SELECT;
+ const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, SELECT);
+ data->is_changed = true;
+ }
+ bezt->f1 = bezt->f3 = bezt->f2;
+ }
+ else {
+ char *flag_p = (&bezt->f1) + beztindex;
+ const bool is_select = *flag_p & SELECT;
+ const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ SET_FLAG_FROM_TEST(*flag_p, sel_op_result, SELECT);
+ data->is_changed = true;
+ }
+ }
+ }
}
static bool do_nurbs_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op)
{
- BoxSelectUserData data;
+ BoxSelectUserData data;
- view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
+ view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- Curve *curve = (Curve *) vc->obedit->data;
- data.is_changed |= ED_curve_deselect_all(curve->editnurb);
- }
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ Curve *curve = (Curve *)vc->obedit->data;
+ data.is_changed |= ED_curve_deselect_all(curve->editnurb);
+ }
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
- nurbs_foreachScreenVert(vc, do_nurbs_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- BKE_curve_nurb_vert_active_validate(vc->obedit->data);
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
+ nurbs_foreachScreenVert(vc, do_nurbs_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ BKE_curve_nurb_vert_active_validate(vc->obedit->data);
- return data.is_changed;
+ return data.is_changed;
}
static void do_lattice_box_select__doSelect(void *userData, BPoint *bp, const float screen_co[2])
{
- BoxSelectUserData *data = userData;
- const bool is_select = bp->f1 & SELECT;
- const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co);
- 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);
- data->is_changed = true;
- }
+ BoxSelectUserData *data = userData;
+ const bool is_select = bp->f1 & SELECT;
+ const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co);
+ 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);
+ data->is_changed = true;
+ }
}
static bool do_lattice_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op)
{
- BoxSelectUserData data;
+ BoxSelectUserData data;
- view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
+ view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- data.is_changed |= ED_lattice_flags_set(vc->obedit, 0);
- }
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ data.is_changed |= ED_lattice_flags_set(vc->obedit, 0);
+ }
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
- lattice_foreachScreenVert(vc, do_lattice_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
+ lattice_foreachScreenVert(
+ vc, do_lattice_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- return data.is_changed;
+ return data.is_changed;
}
-static void do_mesh_box_select__doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index))
+static void do_mesh_box_select__doSelectVert(void *userData,
+ BMVert *eve,
+ const float screen_co[2],
+ int UNUSED(index))
{
- BoxSelectUserData *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);
- 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);
- data->is_changed = true;
- }
+ BoxSelectUserData *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);
+ 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);
+ data->is_changed = true;
+ }
}
static void do_mesh_box_select__doSelectEdge_pass0(
- void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
-{
- BoxSelectUserData *data = userData;
- const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
- const bool is_inside = (
- EDBM_backbuf_check(bm_solidoffs + index) &&
- edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b));
- 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);
- data->is_done = true;
- data->is_changed = true;
- }
+ void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
+{
+ BoxSelectUserData *data = userData;
+ const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
+ const bool is_inside = (EDBM_backbuf_check(bm_solidoffs + index) &&
+ edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b));
+ 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);
+ data->is_done = true;
+ data->is_changed = true;
+ }
}
static void do_mesh_box_select__doSelectEdge_pass1(
- void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
-{
- BoxSelectUserData *data = userData;
- const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
- const bool is_inside = (
- EDBM_backbuf_check(bm_solidoffs + index) &&
- edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b));
- const 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);
- data->is_changed = true;
- }
-}
-static void do_mesh_box_select__doSelectFace(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
-{
- BoxSelectUserData *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);
- 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);
- data->is_changed = true;
- }
-}
-static bool do_mesh_box_select(
- ViewContext *vc, rcti *rect, const eSelectOp sel_op)
-{
- BoxSelectUserData data;
- ToolSettings *ts = vc->scene->toolsettings;
- int bbsel;
-
- view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
-
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- if (vc->em->bm->totvertsel) {
- EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT);
- data.is_changed = true;
- }
- }
-
- /* for non zbuf projections, don't change the GL state */
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
-
- GPU_matrix_set(vc->rv3d->viewmat);
- bbsel = EDBM_backbuf_border_init(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
-
- if (ts->selectmode & SCE_SELECT_VERTEX) {
- if (bbsel) {
- data.is_changed |= edbm_backbuf_check_and_select_verts(vc->em, sel_op);
- }
- else {
- mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- }
- }
- if (ts->selectmode & SCE_SELECT_EDGE) {
- /* Does both bbsel and non-bbsel versions (need screen cos for both) */
- mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR);
- if (data.is_done == false) {
- mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR);
- }
- }
-
- if (ts->selectmode & SCE_SELECT_FACE) {
- if (bbsel) {
- data.is_changed |= edbm_backbuf_check_and_select_faces(vc->em, sel_op);
- }
- else {
- mesh_foreachScreenFace(vc, do_mesh_box_select__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- }
- }
-
- EDBM_backbuf_free();
-
- if (data.is_changed) {
- EDBM_selectmode_flush(vc->em);
- }
- return data.is_changed;
-}
-
-static bool do_meta_box_select(
- ViewContext *vc,
- const rcti *rect, const eSelectOp sel_op)
-{
- Object *ob = vc->obedit;
- MetaBall *mb = (MetaBall *)ob->data;
- MetaElem *ml;
- int a;
- bool changed = false;
-
- uint buffer[MAXPICKBUF];
- int hits;
-
- hits = view3d_opengl_select(
- vc, buffer, MAXPICKBUF, rect,
- VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
-
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- changed |= BKE_mball_deselect_all(mb);
- }
-
- int metaelem_id = 0;
- for (ml = mb->editelems->first; ml; ml = ml->next, metaelem_id += 0x10000) {
- bool is_inside_radius = false;
- bool is_inside_stiff = false;
-
- for (a = 0; a < hits; a++) {
- int hitresult = buffer[(4 * a) + 3];
-
- if (hitresult == -1) {
- continue;
- }
- else if (hitresult & MBALL_NOSEL) {
- continue;
- }
-
- const uint hit_object = hitresult & 0xFFFF;
- if (vc->obedit->select_id != hit_object) {
- continue;
- }
-
- if (metaelem_id != (hitresult & 0xFFFF0000 & ~(MBALLSEL_ANY))) {
- continue;
- }
-
- if (hitresult & MBALLSEL_RADIUS) {
- is_inside_radius = true;
- break;
- }
-
- if (hitresult & MBALLSEL_STIFF) {
- is_inside_stiff = true;
- break;
- }
- }
- const int flag_prev = ml->flag;
- if (is_inside_radius) {
- ml->flag |= MB_SCALE_RAD;
- }
- if (is_inside_stiff) {
- ml->flag &= ~MB_SCALE_RAD;
- }
-
- const bool is_select = (ml->flag & SELECT);
- const bool is_inside = is_inside_radius || is_inside_stiff;
-
- 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(ml->flag, sel_op_result, SELECT);
- }
- changed |= (flag_prev != ml->flag);
- }
-
- return changed;
-}
-
-static bool do_armature_box_select(
- ViewContext *vc,
- const rcti *rect, const eSelectOp sel_op)
-{
- bool changed = false;
- int a;
-
- uint buffer[MAXPICKBUF];
- int hits;
-
- hits = view3d_opengl_select(
- vc, buffer, MAXPICKBUF, rect,
- VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
-
- uint bases_len = 0;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc->view_layer, vc->v3d, &bases_len);
-
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- changed |= ED_armature_edit_deselect_all_visible_multi_ex(bases, bases_len);
- }
-
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Object *obedit = bases[base_index]->object;
- obedit->id.tag &= ~LIB_TAG_DOIT;
-
- bArmature *arm = obedit->data;
- ED_armature_ebone_listbase_temp_clear(arm->edbo);
- }
-
- /* first we only check points inside the border */
- for (a = 0; a < hits; a++) {
- int select_id = buffer[(4 * a) + 3];
- if (select_id != -1) {
- if ((select_id & 0xFFFF0000) == 0) {
- continue;
- }
-
- EditBone *ebone;
- Base *base_edit = ED_armature_base_and_ebone_from_select_buffer(bases, bases_len, select_id, &ebone);
- ebone->temp.i |= select_id & BONESEL_ANY;
- base_edit->object->id.tag |= LIB_TAG_DOIT;
- }
- }
-
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Object *obedit = bases[base_index]->object;
- if (obedit->id.tag & LIB_TAG_DOIT) {
- obedit->id.tag &= ~LIB_TAG_DOIT;
- changed |= ED_armature_edit_select_op_from_tagged(obedit->data, sel_op);
- }
- }
-
- MEM_freeN(bases);
-
- return changed;
+ void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
+{
+ BoxSelectUserData *data = userData;
+ const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
+ const bool is_inside = (EDBM_backbuf_check(bm_solidoffs + index) &&
+ edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b));
+ const 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);
+ data->is_changed = true;
+ }
+}
+static void do_mesh_box_select__doSelectFace(void *userData,
+ BMFace *efa,
+ const float screen_co[2],
+ int UNUSED(index))
+{
+ BoxSelectUserData *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);
+ 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);
+ data->is_changed = true;
+ }
+}
+static bool do_mesh_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op)
+{
+ BoxSelectUserData data;
+ ToolSettings *ts = vc->scene->toolsettings;
+ int bbsel;
+
+ view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
+
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ if (vc->em->bm->totvertsel) {
+ EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT);
+ data.is_changed = true;
+ }
+ }
+
+ /* for non zbuf projections, don't change the GL state */
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+
+ GPU_matrix_set(vc->rv3d->viewmat);
+ bbsel = EDBM_backbuf_border_init(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+
+ if (ts->selectmode & SCE_SELECT_VERTEX) {
+ if (bbsel) {
+ data.is_changed |= edbm_backbuf_check_and_select_verts(vc->em, sel_op);
+ }
+ else {
+ mesh_foreachScreenVert(
+ vc, do_mesh_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ }
+ }
+ if (ts->selectmode & SCE_SELECT_EDGE) {
+ /* Does both bbsel and non-bbsel versions (need screen cos for both) */
+ mesh_foreachScreenEdge(
+ vc, do_mesh_box_select__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ if (data.is_done == false) {
+ mesh_foreachScreenEdge(
+ vc, do_mesh_box_select__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ }
+ }
+
+ if (ts->selectmode & SCE_SELECT_FACE) {
+ if (bbsel) {
+ data.is_changed |= edbm_backbuf_check_and_select_faces(vc->em, sel_op);
+ }
+ else {
+ mesh_foreachScreenFace(
+ vc, do_mesh_box_select__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ }
+ }
+
+ EDBM_backbuf_free();
+
+ if (data.is_changed) {
+ EDBM_selectmode_flush(vc->em);
+ }
+ return data.is_changed;
+}
+
+static bool do_meta_box_select(ViewContext *vc, const rcti *rect, const eSelectOp sel_op)
+{
+ Object *ob = vc->obedit;
+ MetaBall *mb = (MetaBall *)ob->data;
+ MetaElem *ml;
+ int a;
+ bool changed = false;
+
+ uint buffer[MAXPICKBUF];
+ int hits;
+
+ hits = view3d_opengl_select(
+ vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
+
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ changed |= BKE_mball_deselect_all(mb);
+ }
+
+ int metaelem_id = 0;
+ for (ml = mb->editelems->first; ml; ml = ml->next, metaelem_id += 0x10000) {
+ bool is_inside_radius = false;
+ bool is_inside_stiff = false;
+
+ for (a = 0; a < hits; a++) {
+ int hitresult = buffer[(4 * a) + 3];
+
+ if (hitresult == -1) {
+ continue;
+ }
+ else if (hitresult & MBALL_NOSEL) {
+ continue;
+ }
+
+ const uint hit_object = hitresult & 0xFFFF;
+ if (vc->obedit->select_id != hit_object) {
+ continue;
+ }
+
+ if (metaelem_id != (hitresult & 0xFFFF0000 & ~(MBALLSEL_ANY))) {
+ continue;
+ }
+
+ if (hitresult & MBALLSEL_RADIUS) {
+ is_inside_radius = true;
+ break;
+ }
+
+ if (hitresult & MBALLSEL_STIFF) {
+ is_inside_stiff = true;
+ break;
+ }
+ }
+ const int flag_prev = ml->flag;
+ if (is_inside_radius) {
+ ml->flag |= MB_SCALE_RAD;
+ }
+ if (is_inside_stiff) {
+ ml->flag &= ~MB_SCALE_RAD;
+ }
+
+ const bool is_select = (ml->flag & SELECT);
+ const bool is_inside = is_inside_radius || is_inside_stiff;
+
+ 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(ml->flag, sel_op_result, SELECT);
+ }
+ changed |= (flag_prev != ml->flag);
+ }
+
+ return changed;
+}
+
+static bool do_armature_box_select(ViewContext *vc, const rcti *rect, const eSelectOp sel_op)
+{
+ bool changed = false;
+ int a;
+
+ uint buffer[MAXPICKBUF];
+ int hits;
+
+ hits = view3d_opengl_select(
+ vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
+
+ uint bases_len = 0;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
+ vc->view_layer, vc->v3d, &bases_len);
+
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ changed |= ED_armature_edit_deselect_all_visible_multi_ex(bases, bases_len);
+ }
+
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Object *obedit = bases[base_index]->object;
+ obedit->id.tag &= ~LIB_TAG_DOIT;
+
+ bArmature *arm = obedit->data;
+ ED_armature_ebone_listbase_temp_clear(arm->edbo);
+ }
+
+ /* first we only check points inside the border */
+ for (a = 0; a < hits; a++) {
+ int select_id = buffer[(4 * a) + 3];
+ if (select_id != -1) {
+ if ((select_id & 0xFFFF0000) == 0) {
+ continue;
+ }
+
+ EditBone *ebone;
+ Base *base_edit = ED_armature_base_and_ebone_from_select_buffer(
+ bases, bases_len, select_id, &ebone);
+ ebone->temp.i |= select_id & BONESEL_ANY;
+ base_edit->object->id.tag |= LIB_TAG_DOIT;
+ }
+ }
+
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Object *obedit = bases[base_index]->object;
+ if (obedit->id.tag & LIB_TAG_DOIT) {
+ obedit->id.tag &= ~LIB_TAG_DOIT;
+ changed |= ED_armature_edit_select_op_from_tagged(obedit->data, sel_op);
+ }
+ }
+
+ MEM_freeN(bases);
+
+ return changed;
}
/**
@@ -2653,291 +2759,294 @@ static bool do_armature_box_select(
*/
static int opengl_bone_select_buffer_cmp(const void *sel_a_p, const void *sel_b_p)
{
- /* 4th element is select id */
- uint sel_a = ((uint *)sel_a_p)[3];
- uint sel_b = ((uint *)sel_b_p)[3];
+ /* 4th element is select id */
+ uint sel_a = ((uint *)sel_a_p)[3];
+ uint sel_b = ((uint *)sel_b_p)[3];
#ifdef __BIG_ENDIAN__
- BLI_endian_switch_uint32(&sel_a);
- BLI_endian_switch_uint32(&sel_b);
+ BLI_endian_switch_uint32(&sel_a);
+ BLI_endian_switch_uint32(&sel_b);
#endif
- if (sel_a < sel_b) {
- return -1;
- }
- else if (sel_a > sel_b) {
- return 1;
- }
- else {
- return 0;
- }
+ if (sel_a < sel_b) {
+ return -1;
+ }
+ else if (sel_a > sel_b) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const eSelectOp sel_op)
{
- View3D *v3d = vc->v3d;
- int totobj = MAXPICKBUF; /* XXX solve later */
-
- /* selection buffer now has bones potentially too, so we add MAXPICKBUF */
- uint *vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(uint[4]), "selection buffer");
- const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene, vc->obact);
- 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) {
- base->object->id.tag &= ~LIB_TAG_DOIT;
- }
-
- Base **bases = NULL;
- BLI_array_declare(bases);
-
- bool changed = false;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- changed |= object_deselect_all_visible(vc->view_layer, vc->v3d);
- }
-
- if ((hits == -1) && !SEL_OP_USE_OUTSIDE(sel_op)) {
- goto finally;
- }
-
- for (Base *base = vc->view_layer->object_bases.first; base; base = base->next) {
- if (BASE_SELECTABLE(v3d, base)) {
- if ((base->object->select_id & 0x0000FFFF) != 0) {
- BLI_array_append(bases, base);
- }
- }
- }
-
- /* The draw order doesn't always match the order we populate the engine, see: T51695. */
- 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);
- if (base != NULL) {
- base->object->id.tag |= LIB_TAG_DOIT;
- }
- }
-
- for (Base *base = vc->view_layer->object_bases.first; base && hits; base = base->next) {
- if (BASE_SELECTABLE(v3d, base)) {
- const bool is_select = base->flag & BASE_SELECTED;
- const bool is_inside = base->object->id.tag & LIB_TAG_DOIT;
- 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);
- changed = true;
- }
- }
- }
+ View3D *v3d = vc->v3d;
+ int totobj = MAXPICKBUF; /* XXX solve later */
+
+ /* selection buffer now has bones potentially too, so we add MAXPICKBUF */
+ uint *vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(uint[4]), "selection buffer");
+ const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene,
+ vc->obact);
+ 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) {
+ base->object->id.tag &= ~LIB_TAG_DOIT;
+ }
+
+ Base **bases = NULL;
+ BLI_array_declare(bases);
+
+ bool changed = false;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ changed |= object_deselect_all_visible(vc->view_layer, vc->v3d);
+ }
+
+ if ((hits == -1) && !SEL_OP_USE_OUTSIDE(sel_op)) {
+ goto finally;
+ }
+
+ for (Base *base = vc->view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTABLE(v3d, base)) {
+ if ((base->object->select_id & 0x0000FFFF) != 0) {
+ BLI_array_append(bases, base);
+ }
+ }
+ }
+
+ /* The draw order doesn't always match the order we populate the engine, see: T51695. */
+ 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);
+ if (base != NULL) {
+ base->object->id.tag |= LIB_TAG_DOIT;
+ }
+ }
+
+ for (Base *base = vc->view_layer->object_bases.first; base && hits; base = base->next) {
+ if (BASE_SELECTABLE(v3d, base)) {
+ const bool is_select = base->flag & BASE_SELECTED;
+ const bool is_inside = base->object->id.tag & LIB_TAG_DOIT;
+ 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);
+ changed = true;
+ }
+ }
+ }
finally:
- if (bases != NULL) {
- MEM_freeN(bases);
- }
+ if (bases != NULL) {
+ MEM_freeN(bases);
+ }
- MEM_freeN(vbuffer);
+ MEM_freeN(vbuffer);
- if (changed) {
- DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
- }
- return changed;
+ if (changed) {
+ DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
+ }
+ return changed;
}
static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const eSelectOp sel_op)
{
- uint bases_len;
- Base **bases = do_pose_tag_select_op_prepare(vc, &bases_len);
-
- int totobj = MAXPICKBUF; /* XXX solve later */
-
- /* selection buffer now has bones potentially too, so we add MAXPICKBUF */
- uint *vbuffer = MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(uint[4]), "selection buffer");
- const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene, vc->obact);
- const int hits = view3d_opengl_select(
- vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect,
- VIEW3D_SELECT_ALL, select_filter);
- /*
- * LOGIC NOTES (theeth):
- * The buffer and ListBase have the same relative order, which makes the selection
- * very simple. Loop through both data sets at the same time, if the color
- * is the same as the object, we have a hit and can move to the next color
- * and object pair, if not, just move to the next object,
- * keeping the same color until we have a hit.
- */
-
- if (hits > 0) {
- /* no need to loop if there's no hit */
-
- /* The draw order doesn't always match the order we populate the engine, see: T51695. */
- 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, bases_len, *col, &bone);
-
- if (base == NULL) {
- continue;
- }
-
- /* Loop over contiguous bone hits for 'base'. */
- for (; col != col_end; col += 4) {
- /* should never fail */
- if (bone != NULL) {
- base->object->id.tag |= LIB_TAG_DOIT;
- bone->flag |= BONE_DONE;
- }
-
- /* Select the next bone if we're not switching bases. */
- if (col + 4 != col_end) {
- if ((base->object->select_id & 0x0000FFFF) != (col[4] & 0x0000FFFF)) {
- break;
- }
- if (base->object->pose != NULL) {
- const uint hit_bone = (col[4] & ~BONESEL_ANY) >> 16;
- bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
- bone = pchan ? pchan->bone : NULL;
- }
- else {
- bone = NULL;
- }
- }
- }
- }
- }
-
- const bool changed_multi = do_pose_tag_select_op_exec(bases, bases_len, sel_op);
- if (changed_multi) {
- DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
- }
-
- if (bases != NULL) {
- MEM_freeN(bases);
- }
- MEM_freeN(vbuffer);
-
- return changed_multi;
+ uint bases_len;
+ Base **bases = do_pose_tag_select_op_prepare(vc, &bases_len);
+
+ int totobj = MAXPICKBUF; /* XXX solve later */
+
+ /* selection buffer now has bones potentially too, so we add MAXPICKBUF */
+ uint *vbuffer = MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(uint[4]), "selection buffer");
+ const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene,
+ vc->obact);
+ const int hits = view3d_opengl_select(
+ vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
+ /*
+ * LOGIC NOTES (theeth):
+ * The buffer and ListBase have the same relative order, which makes the selection
+ * very simple. Loop through both data sets at the same time, if the color
+ * is the same as the object, we have a hit and can move to the next color
+ * and object pair, if not, just move to the next object,
+ * keeping the same color until we have a hit.
+ */
+
+ if (hits > 0) {
+ /* no need to loop if there's no hit */
+
+ /* The draw order doesn't always match the order we populate the engine, see: T51695. */
+ 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, bases_len, *col, &bone);
+
+ if (base == NULL) {
+ continue;
+ }
+
+ /* Loop over contiguous bone hits for 'base'. */
+ for (; col != col_end; col += 4) {
+ /* should never fail */
+ if (bone != NULL) {
+ base->object->id.tag |= LIB_TAG_DOIT;
+ bone->flag |= BONE_DONE;
+ }
+
+ /* Select the next bone if we're not switching bases. */
+ if (col + 4 != col_end) {
+ if ((base->object->select_id & 0x0000FFFF) != (col[4] & 0x0000FFFF)) {
+ break;
+ }
+ if (base->object->pose != NULL) {
+ const uint hit_bone = (col[4] & ~BONESEL_ANY) >> 16;
+ bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
+ bone = pchan ? pchan->bone : NULL;
+ }
+ else {
+ bone = NULL;
+ }
+ }
+ }
+ }
+ }
+
+ const bool changed_multi = do_pose_tag_select_op_exec(bases, bases_len, sel_op);
+ if (changed_multi) {
+ DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
+ }
+
+ if (bases != NULL) {
+ MEM_freeN(bases);
+ }
+ MEM_freeN(vbuffer);
+
+ return changed_multi;
}
static int view3d_box_select_exec(bContext *C, wmOperator *op)
{
- ViewContext vc;
- rcti rect;
- bool changed_multi = false;
-
- view3d_operator_needs_opengl(C);
-
- /* setup view context for argument to callbacks */
- ED_view3d_viewcontext_init(C, &vc);
-
- eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
- WM_operator_properties_border_to_rcti(op, &rect);
-
- if (vc.obedit) {
-
- FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, vc.v3d, vc.obedit->type, vc.obedit->mode, ob_iter) {
- ED_view3d_viewcontext_init_object(&vc, ob_iter);
- bool changed = false;
-
- switch (vc.obedit->type) {
- case OB_MESH:
- vc.em = BKE_editmesh_from_object(vc.obedit);
- changed = do_mesh_box_select(&vc, &rect, sel_op);
- if (changed) {
- DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
- }
- break;
- case OB_CURVE:
- case OB_SURF:
- changed = do_nurbs_box_select(&vc, &rect, sel_op);
- if (changed) {
- DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
- }
- break;
- case OB_MBALL:
- changed = do_meta_box_select(&vc, &rect, sel_op);
- if (changed) {
- DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
- }
- break;
- case OB_ARMATURE:
- changed = do_armature_box_select(&vc, &rect, sel_op);
- if (changed) {
- DEG_id_tag_update(&vc.obedit->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit);
- }
- break;
- case OB_LATTICE:
- changed = do_lattice_box_select(&vc, &rect, sel_op);
- if (changed) {
- DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
- }
- break;
- default:
- assert(!"box select on incorrect object type");
- break;
- }
- changed_multi |= changed;
- }
- FOREACH_OBJECT_IN_MODE_END;
- }
- else { /* no editmode, 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(C, &vc, &rect, sel_op == SEL_OP_ADD ? true : false);
- }
- else if (vc.obact && BKE_paint_select_face_test(vc.obact)) {
- changed_multi = do_paintface_box_select(&vc, &rect, sel_op);
- }
- else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) {
- changed_multi = do_paintvert_box_select(&vc, &rect, sel_op);
- }
- else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) {
- changed_multi = PE_box_select(C, &rect, sel_op);
- }
- else if (vc.obact && vc.obact->mode & OB_MODE_POSE) {
- changed_multi = do_pose_box_select(C, &vc, &rect, sel_op);
- }
- else { /* object mode with none active */
- changed_multi = do_object_box_select(C, &vc, &rect, sel_op);
- }
- }
-
- if (changed_multi) {
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ ViewContext vc;
+ rcti rect;
+ bool changed_multi = false;
+
+ view3d_operator_needs_opengl(C);
+
+ /* setup view context for argument to callbacks */
+ ED_view3d_viewcontext_init(C, &vc);
+
+ eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
+ WM_operator_properties_border_to_rcti(op, &rect);
+
+ if (vc.obedit) {
+
+ FOREACH_OBJECT_IN_MODE_BEGIN (
+ vc.view_layer, vc.v3d, vc.obedit->type, vc.obedit->mode, ob_iter) {
+ ED_view3d_viewcontext_init_object(&vc, ob_iter);
+ bool changed = false;
+
+ switch (vc.obedit->type) {
+ case OB_MESH:
+ vc.em = BKE_editmesh_from_object(vc.obedit);
+ changed = do_mesh_box_select(&vc, &rect, sel_op);
+ if (changed) {
+ DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
+ }
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ changed = do_nurbs_box_select(&vc, &rect, sel_op);
+ if (changed) {
+ DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
+ }
+ break;
+ case OB_MBALL:
+ changed = do_meta_box_select(&vc, &rect, sel_op);
+ if (changed) {
+ DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
+ }
+ break;
+ case OB_ARMATURE:
+ changed = do_armature_box_select(&vc, &rect, sel_op);
+ if (changed) {
+ DEG_id_tag_update(&vc.obedit->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit);
+ }
+ break;
+ case OB_LATTICE:
+ changed = do_lattice_box_select(&vc, &rect, sel_op);
+ if (changed) {
+ DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
+ }
+ break;
+ default:
+ assert(!"box select on incorrect object type");
+ break;
+ }
+ changed_multi |= changed;
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+ }
+ else { /* no editmode, 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(
+ C, &vc, &rect, sel_op == SEL_OP_ADD ? true : false);
+ }
+ else if (vc.obact && BKE_paint_select_face_test(vc.obact)) {
+ changed_multi = do_paintface_box_select(&vc, &rect, sel_op);
+ }
+ else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) {
+ changed_multi = do_paintvert_box_select(&vc, &rect, sel_op);
+ }
+ else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) {
+ changed_multi = PE_box_select(C, &rect, sel_op);
+ }
+ else if (vc.obact && vc.obact->mode & OB_MODE_POSE) {
+ changed_multi = do_pose_box_select(C, &vc, &rect, sel_op);
+ }
+ else { /* object mode with none active */
+ changed_multi = do_object_box_select(C, &vc, &rect, sel_op);
+ }
+ }
+
+ if (changed_multi) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void VIEW3D_OT_select_box(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Box Select";
- ot->description = "Select items using box selection";
- ot->idname = "VIEW3D_OT_select_box";
+ /* identifiers */
+ ot->name = "Box Select";
+ ot->description = "Select items using box selection";
+ ot->idname = "VIEW3D_OT_select_box";
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = view3d_box_select_exec;
- ot->modal = WM_gesture_box_modal;
- ot->poll = view3d_selectable_data;
- ot->cancel = WM_gesture_box_cancel;
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = view3d_box_select_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->poll = view3d_selectable_data;
+ ot->cancel = WM_gesture_box_cancel;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- /* rna */
- WM_operator_properties_gesture_box(ot);
- WM_operator_properties_select_operation(ot);
+ /* rna */
+ WM_operator_properties_gesture_box(ot);
+ WM_operator_properties_select_operation(ot);
}
/** \} */
@@ -2947,638 +3056,691 @@ void VIEW3D_OT_select_box(wmOperatorType *ot)
* \{ */
typedef struct CircleSelectUserData {
- ViewContext *vc;
- bool select;
- int mval[2];
- float mval_fl[2];
- float radius;
- float radius_squared;
-
- /* runtime */
- bool is_changed;
+ ViewContext *vc;
+ bool select;
+ int mval[2];
+ float mval_fl[2];
+ float radius;
+ float radius_squared;
+
+ /* runtime */
+ bool is_changed;
} CircleSelectUserData;
-static void view3d_userdata_circleselect_init(
- CircleSelectUserData *r_data,
- ViewContext *vc, const bool select, const int mval[2], const float rad)
+static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data,
+ ViewContext *vc,
+ const bool select,
+ const int mval[2],
+ const float rad)
{
- r_data->vc = vc;
- r_data->select = select;
- copy_v2_v2_int(r_data->mval, mval);
- r_data->mval_fl[0] = mval[0];
- r_data->mval_fl[1] = mval[1];
+ r_data->vc = vc;
+ r_data->select = select;
+ copy_v2_v2_int(r_data->mval, mval);
+ r_data->mval_fl[0] = mval[0];
+ r_data->mval_fl[1] = mval[1];
- r_data->radius = rad;
- r_data->radius_squared = rad * rad;
+ r_data->radius = rad;
+ r_data->radius_squared = rad * rad;
- /* runtime */
- r_data->is_changed = false;
+ /* runtime */
+ r_data->is_changed = false;
}
-static void mesh_circle_doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index))
+static void mesh_circle_doSelectVert(void *userData,
+ BMVert *eve,
+ const float screen_co[2],
+ int UNUSED(index))
{
- CircleSelectUserData *data = userData;
+ CircleSelectUserData *data = userData;
- if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
- BM_vert_select_set(data->vc->em->bm, eve, data->select);
- data->is_changed = true;
- }
+ if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
+ BM_vert_select_set(data->vc->em->bm, eve, data->select);
+ data->is_changed = true;
+ }
}
-static void mesh_circle_doSelectEdge(
- void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index))
+static void mesh_circle_doSelectEdge(void *userData,
+ BMEdge *eed,
+ const float screen_co_a[2],
+ const float screen_co_b[2],
+ int UNUSED(index))
{
- CircleSelectUserData *data = userData;
+ CircleSelectUserData *data = userData;
- if (edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) {
- BM_edge_select_set(data->vc->em->bm, eed, data->select);
- data->is_changed = true;
- }
+ if (edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) {
+ BM_edge_select_set(data->vc->em->bm, eed, data->select);
+ data->is_changed = true;
+ }
}
-static void mesh_circle_doSelectFace(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
+static void mesh_circle_doSelectFace(void *userData,
+ BMFace *efa,
+ const float screen_co[2],
+ int UNUSED(index))
{
- CircleSelectUserData *data = userData;
+ CircleSelectUserData *data = userData;
- if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
- BM_face_select_set(data->vc->em->bm, efa, data->select);
- data->is_changed = true;
- }
+ if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
+ BM_face_select_set(data->vc->em->bm, efa, data->select);
+ data->is_changed = true;
+ }
}
static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval[2], float rad)
{
- ToolSettings *ts = vc->scene->toolsettings;
- int bbsel;
- CircleSelectUserData data;
- vc->em = BKE_editmesh_from_object(vc->obedit);
-
- bool changed = false;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- if (vc->em->bm->totvertsel) {
- EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT);
- changed = true;
- }
- }
- const bool select = (sel_op != SEL_OP_SUB);
-
- bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
-
- view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
-
- if (ts->selectmode & SCE_SELECT_VERTEX) {
- if (bbsel) {
- changed |= edbm_backbuf_check_and_select_verts(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
- }
- else {
- mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- }
- }
-
- if (ts->selectmode & SCE_SELECT_EDGE) {
- if (bbsel) {
- changed |= edbm_backbuf_check_and_select_edges(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
- }
- else {
- mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
- }
- }
-
- if (ts->selectmode & SCE_SELECT_FACE) {
- if (bbsel) {
- changed |= edbm_backbuf_check_and_select_faces(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
- }
- else {
- mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- }
- }
-
- changed |= data.is_changed;
-
- EDBM_backbuf_free();
-
- if (changed) {
- EDBM_selectmode_flush(vc->em);
- }
- return changed;
-}
-
-static bool paint_facesel_circle_select(ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad)
-{
- BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB));
- Object *ob = vc->obact;
- Mesh *me = ob->data;
- bool bbsel;
-
- bool changed = false;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- /* flush selection at the end */
- changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false);
- }
-
- bm_vertoffs = me->totpoly + 1; /* max index array */
-
- bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
- if (bbsel) {
- changed |= edbm_backbuf_check_and_select_tfaces(me, sel_op);
- EDBM_backbuf_free();
- }
- if (changed) {
- paintface_flush_flags(vc->C, ob, SELECT);
- }
- return changed;
-}
-
-static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
-{
- CircleSelectUserData *data = userData;
-
- if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
- SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT);
- data->is_changed = true;
- }
-}
-static bool paint_vertsel_circle_select(ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad)
-{
- BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB));
- const bool use_zbuf = !XRAY_ENABLED(vc->v3d);
- Object *ob = vc->obact;
- Mesh *me = ob->data;
- bool bbsel;
- /* CircleSelectUserData data = {NULL}; */ /* UNUSED */
-
- bool changed = false;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- changed |= paintvert_deselect_all_visible(ob, SEL_DESELECT, false); /* flush selection at the end */
- }
-
- const bool select = (sel_op != SEL_OP_SUB);
-
- if (use_zbuf) {
- bm_vertoffs = me->totvert + 1; /* max index array */
-
- bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
- if (bbsel) {
- changed |= edbm_backbuf_check_and_select_verts_obmode(me, sel_op);
- EDBM_backbuf_free();
- }
- }
- else {
- CircleSelectUserData data;
-
- ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */
-
- view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
- meshobject_foreachScreenVert(vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- changed |= data.is_changed;
- }
-
- if (changed) {
- if (sel_op == SEL_OP_SUB) {
- BKE_mesh_mselect_validate(me);
- }
- paintvert_flush_flags(ob);
- paintvert_tag_select_update(vc->C, ob);
- }
- return changed;
-}
-
-
-static void nurbscurve_circle_doSelect(
- void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
-{
- CircleSelectUserData *data = userData;
-
- if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
- if (bp) {
- bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
- }
- else {
- if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
- /* can only be (beztindex == 0) here since handles are hidden */
- bezt->f1 = bezt->f2 = bezt->f3 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
- }
- else {
- if (beztindex == 0) {
- bezt->f1 = data->select ? (bezt->f1 | SELECT) : (bezt->f1 & ~SELECT);
- }
- else if (beztindex == 1) {
- bezt->f2 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
- }
- else {
- bezt->f3 = data->select ? (bezt->f3 | SELECT) : (bezt->f3 & ~SELECT);
- }
- }
- }
- data->is_changed = true;
- }
-}
-static bool nurbscurve_circle_select(ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad)
-{
- CircleSelectUserData data;
- bool changed = false;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- Curve *curve = vc->obedit->data;
- changed |= ED_curve_deselect_all(curve->editnurb);
- }
- const bool select = (sel_op != SEL_OP_SUB);
-
- view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
- nurbs_foreachScreenVert(vc, nurbscurve_circle_doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- BKE_curve_nurb_vert_active_validate(vc->obedit->data);
-
- return changed || data.is_changed;
+ ToolSettings *ts = vc->scene->toolsettings;
+ int bbsel;
+ CircleSelectUserData data;
+ vc->em = BKE_editmesh_from_object(vc->obedit);
+
+ bool changed = false;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ if (vc->em->bm->totvertsel) {
+ EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT);
+ changed = true;
+ }
+ }
+ const bool select = (sel_op != SEL_OP_SUB);
+
+ bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
+
+ view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
+
+ if (ts->selectmode & SCE_SELECT_VERTEX) {
+ if (bbsel) {
+ changed |= edbm_backbuf_check_and_select_verts(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
+ }
+ else {
+ mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ }
+ }
+
+ if (ts->selectmode & SCE_SELECT_EDGE) {
+ if (bbsel) {
+ changed |= edbm_backbuf_check_and_select_edges(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
+ }
+ else {
+ mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ }
+ }
+
+ if (ts->selectmode & SCE_SELECT_FACE) {
+ if (bbsel) {
+ changed |= edbm_backbuf_check_and_select_faces(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
+ }
+ else {
+ mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ }
+ }
+
+ changed |= data.is_changed;
+
+ EDBM_backbuf_free();
+
+ if (changed) {
+ EDBM_selectmode_flush(vc->em);
+ }
+ return changed;
+}
+
+static bool paint_facesel_circle_select(ViewContext *vc,
+ const eSelectOp sel_op,
+ const int mval[2],
+ float rad)
+{
+ BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB));
+ Object *ob = vc->obact;
+ Mesh *me = ob->data;
+ bool bbsel;
+
+ bool changed = false;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ /* flush selection at the end */
+ changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false);
+ }
+
+ bm_vertoffs = me->totpoly + 1; /* max index array */
+
+ bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
+ if (bbsel) {
+ changed |= edbm_backbuf_check_and_select_tfaces(me, sel_op);
+ EDBM_backbuf_free();
+ }
+ if (changed) {
+ paintface_flush_flags(vc->C, ob, SELECT);
+ }
+ return changed;
+}
+
+static void paint_vertsel_circle_select_doSelectVert(void *userData,
+ MVert *mv,
+ const float screen_co[2],
+ int UNUSED(index))
+{
+ CircleSelectUserData *data = userData;
+
+ if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
+ SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT);
+ data->is_changed = true;
+ }
+}
+static bool paint_vertsel_circle_select(ViewContext *vc,
+ const eSelectOp sel_op,
+ const int mval[2],
+ float rad)
+{
+ BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB));
+ const bool use_zbuf = !XRAY_ENABLED(vc->v3d);
+ Object *ob = vc->obact;
+ Mesh *me = ob->data;
+ bool bbsel;
+ /* CircleSelectUserData data = {NULL}; */ /* UNUSED */
+
+ bool changed = false;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ changed |= paintvert_deselect_all_visible(
+ ob, SEL_DESELECT, false); /* flush selection at the end */
+ }
+
+ const bool select = (sel_op != SEL_OP_SUB);
+
+ if (use_zbuf) {
+ bm_vertoffs = me->totvert + 1; /* max index array */
+
+ bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
+ if (bbsel) {
+ changed |= edbm_backbuf_check_and_select_verts_obmode(me, sel_op);
+ EDBM_backbuf_free();
+ }
+ }
+ else {
+ CircleSelectUserData data;
+
+ ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */
+
+ view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
+ meshobject_foreachScreenVert(
+ vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ changed |= data.is_changed;
+ }
+
+ if (changed) {
+ if (sel_op == SEL_OP_SUB) {
+ BKE_mesh_mselect_validate(me);
+ }
+ paintvert_flush_flags(ob);
+ paintvert_tag_select_update(vc->C, ob);
+ }
+ return changed;
+}
+
+static void nurbscurve_circle_doSelect(void *userData,
+ Nurb *UNUSED(nu),
+ BPoint *bp,
+ BezTriple *bezt,
+ int beztindex,
+ const float screen_co[2])
+{
+ CircleSelectUserData *data = userData;
+
+ if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
+ if (bp) {
+ bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
+ }
+ else {
+ if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
+ /* can only be (beztindex == 0) here since handles are hidden */
+ bezt->f1 = bezt->f2 = bezt->f3 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
+ }
+ else {
+ if (beztindex == 0) {
+ bezt->f1 = data->select ? (bezt->f1 | SELECT) : (bezt->f1 & ~SELECT);
+ }
+ else if (beztindex == 1) {
+ bezt->f2 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
+ }
+ else {
+ bezt->f3 = data->select ? (bezt->f3 | SELECT) : (bezt->f3 & ~SELECT);
+ }
+ }
+ }
+ data->is_changed = true;
+ }
+}
+static bool nurbscurve_circle_select(ViewContext *vc,
+ const eSelectOp sel_op,
+ const int mval[2],
+ float rad)
+{
+ CircleSelectUserData data;
+ bool changed = false;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ Curve *curve = vc->obedit->data;
+ changed |= ED_curve_deselect_all(curve->editnurb);
+ }
+ const bool select = (sel_op != SEL_OP_SUB);
+
+ view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
+ nurbs_foreachScreenVert(vc, nurbscurve_circle_doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ BKE_curve_nurb_vert_active_validate(vc->obedit->data);
+
+ return changed || data.is_changed;
}
-
static void latticecurve_circle_doSelect(void *userData, BPoint *bp, const float screen_co[2])
{
- CircleSelectUserData *data = userData;
+ CircleSelectUserData *data = userData;
- if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
- bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
- data->is_changed = true;
- }
+ if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
+ bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
+ data->is_changed = true;
+ }
}
-static bool lattice_circle_select(ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad)
+static bool lattice_circle_select(ViewContext *vc,
+ const eSelectOp sel_op,
+ const int mval[2],
+ float rad)
{
- CircleSelectUserData data;
- const bool select = (sel_op != SEL_OP_SUB);
+ CircleSelectUserData data;
+ const bool select = (sel_op != SEL_OP_SUB);
- view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
+ view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- data.is_changed |= ED_lattice_flags_set(vc->obedit, 0);
- }
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ data.is_changed |= ED_lattice_flags_set(vc->obedit, 0);
+ }
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
- lattice_foreachScreenVert(vc, latticecurve_circle_doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ lattice_foreachScreenVert(vc, latticecurve_circle_doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- return data.is_changed;
+ return data.is_changed;
}
-
/* NOTE: pose-bone case is copied from editbone case... */
-static bool pchan_circle_doSelectJoint(void *userData, bPoseChannel *pchan, const float screen_co[2])
-{
- CircleSelectUserData *data = userData;
-
- if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
- if (data->select) {
- pchan->bone->flag |= BONE_SELECTED;
- }
- else {
- pchan->bone->flag &= ~BONE_SELECTED;
- }
- return 1;
- }
- return 0;
-}
-static void do_circle_select_pose__doSelectBone(
- void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2])
-{
- CircleSelectUserData *data = userData;
- bArmature *arm = data->vc->obact->data;
-
- if (PBONE_SELECTABLE(arm, pchan->bone)) {
- bool is_point_done = false;
- int points_proj_tot = 0;
-
- /* project head location to screenspace */
- if (screen_co_a[0] != IS_CLIPPED) {
- points_proj_tot++;
- if (pchan_circle_doSelectJoint(data, pchan, screen_co_a)) {
- is_point_done = true;
- }
- }
-
- /* project tail location to screenspace */
- if (screen_co_b[0] != IS_CLIPPED) {
- points_proj_tot++;
- if (pchan_circle_doSelectJoint(data, pchan, screen_co_b)) {
- is_point_done = true;
- }
- }
-
- /* check if the head and/or tail is in the circle
- * - the call to check also does the selection already
- */
-
- /* only if the endpoints didn't get selected, deal with the middle of the bone too
- * It works nicer to only do this if the head or tail are not in the circle,
- * otherwise there is no way to circle select joints alone */
- if ((is_point_done == false) && (points_proj_tot == 2) &&
- edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b))
- {
- if (data->select) {
- pchan->bone->flag |= BONE_SELECTED;
- }
- else {
- pchan->bone->flag &= ~BONE_SELECTED;
- }
- data->is_changed = true;
- }
-
- data->is_changed |= is_point_done;
- }
-}
-static bool pose_circle_select(ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad)
-{
- BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB));
- CircleSelectUserData data;
- const bool select = (sel_op != SEL_OP_SUB);
-
- view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
-
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- data.is_changed |= ED_pose_deselect_all(vc->obact, SEL_DESELECT, false);
- }
-
- ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */
-
- pose_foreachScreenBone(vc, do_circle_select_pose__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
-
- if (data.is_changed) {
- ED_pose_bone_select_tag_update(vc->obact);
- }
- return data.is_changed;
-}
-
-static bool armature_circle_doSelectJoint(void *userData, EditBone *ebone, const float screen_co[2], bool head)
-{
- CircleSelectUserData *data = userData;
-
- if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
- if (head) {
- if (data->select) {
- ebone->flag |= BONE_ROOTSEL;
- }
- else {
- ebone->flag &= ~BONE_ROOTSEL;
- }
- }
- else {
- if (data->select) {
- ebone->flag |= BONE_TIPSEL;
- }
- else {
- ebone->flag &= ~BONE_TIPSEL;
- }
- }
- return 1;
- }
- return 0;
-}
-static void do_circle_select_armature__doSelectBone(
- void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2])
-{
- CircleSelectUserData *data = userData;
- bArmature *arm = data->vc->obedit->data;
-
- if (data->select ? EBONE_SELECTABLE(arm, ebone) : EBONE_VISIBLE(arm, ebone)) {
- bool is_point_done = false;
- int points_proj_tot = 0;
-
- /* project head location to screenspace */
- if (screen_co_a[0] != IS_CLIPPED) {
- points_proj_tot++;
- if (armature_circle_doSelectJoint(data, ebone, screen_co_a, true)) {
- is_point_done = true;
- }
- }
-
- /* project tail location to screenspace */
- if (screen_co_b[0] != IS_CLIPPED) {
- points_proj_tot++;
- if (armature_circle_doSelectJoint(data, ebone, screen_co_b, false)) {
- is_point_done = true;
- }
- }
-
- /* check if the head and/or tail is in the circle
- * - the call to check also does the selection already
- */
-
- /* only if the endpoints didn't get selected, deal with the middle of the bone too
- * It works nicer to only do this if the head or tail are not in the circle,
- * otherwise there is no way to circle select joints alone */
- if ((is_point_done == false) && (points_proj_tot == 2) &&
- edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b))
- {
- if (data->select) {
- ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else {
- ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- data->is_changed = true;
- }
-
- data->is_changed |= is_point_done;
- }
-}
-static bool armature_circle_select(ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad)
+static bool pchan_circle_doSelectJoint(void *userData,
+ bPoseChannel *pchan,
+ const float screen_co[2])
+{
+ CircleSelectUserData *data = userData;
+
+ if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
+ if (data->select) {
+ pchan->bone->flag |= BONE_SELECTED;
+ }
+ else {
+ pchan->bone->flag &= ~BONE_SELECTED;
+ }
+ return 1;
+ }
+ return 0;
+}
+static void do_circle_select_pose__doSelectBone(void *userData,
+ struct bPoseChannel *pchan,
+ const float screen_co_a[2],
+ const float screen_co_b[2])
+{
+ CircleSelectUserData *data = userData;
+ bArmature *arm = data->vc->obact->data;
+
+ if (PBONE_SELECTABLE(arm, pchan->bone)) {
+ bool is_point_done = false;
+ int points_proj_tot = 0;
+
+ /* project head location to screenspace */
+ if (screen_co_a[0] != IS_CLIPPED) {
+ points_proj_tot++;
+ if (pchan_circle_doSelectJoint(data, pchan, screen_co_a)) {
+ is_point_done = true;
+ }
+ }
+
+ /* project tail location to screenspace */
+ if (screen_co_b[0] != IS_CLIPPED) {
+ points_proj_tot++;
+ if (pchan_circle_doSelectJoint(data, pchan, screen_co_b)) {
+ is_point_done = true;
+ }
+ }
+
+ /* check if the head and/or tail is in the circle
+ * - the call to check also does the selection already
+ */
+
+ /* only if the endpoints didn't get selected, deal with the middle of the bone too
+ * It works nicer to only do this if the head or tail are not in the circle,
+ * otherwise there is no way to circle select joints alone */
+ if ((is_point_done == false) && (points_proj_tot == 2) &&
+ edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) {
+ if (data->select) {
+ pchan->bone->flag |= BONE_SELECTED;
+ }
+ else {
+ pchan->bone->flag &= ~BONE_SELECTED;
+ }
+ data->is_changed = true;
+ }
+
+ data->is_changed |= is_point_done;
+ }
+}
+static bool pose_circle_select(ViewContext *vc,
+ const eSelectOp sel_op,
+ const int mval[2],
+ float rad)
+{
+ BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB));
+ CircleSelectUserData data;
+ const bool select = (sel_op != SEL_OP_SUB);
+
+ view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
+
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ data.is_changed |= ED_pose_deselect_all(vc->obact, SEL_DESELECT, false);
+ }
+
+ ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */
+
+ pose_foreachScreenBone(
+ vc, do_circle_select_pose__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ if (data.is_changed) {
+ ED_pose_bone_select_tag_update(vc->obact);
+ }
+ return data.is_changed;
+}
+
+static bool armature_circle_doSelectJoint(void *userData,
+ EditBone *ebone,
+ const float screen_co[2],
+ bool head)
+{
+ CircleSelectUserData *data = userData;
+
+ if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
+ if (head) {
+ if (data->select) {
+ ebone->flag |= BONE_ROOTSEL;
+ }
+ else {
+ ebone->flag &= ~BONE_ROOTSEL;
+ }
+ }
+ else {
+ if (data->select) {
+ ebone->flag |= BONE_TIPSEL;
+ }
+ else {
+ ebone->flag &= ~BONE_TIPSEL;
+ }
+ }
+ return 1;
+ }
+ return 0;
+}
+static void do_circle_select_armature__doSelectBone(void *userData,
+ struct EditBone *ebone,
+ const float screen_co_a[2],
+ const float screen_co_b[2])
+{
+ CircleSelectUserData *data = userData;
+ bArmature *arm = data->vc->obedit->data;
+
+ if (data->select ? EBONE_SELECTABLE(arm, ebone) : EBONE_VISIBLE(arm, ebone)) {
+ bool is_point_done = false;
+ int points_proj_tot = 0;
+
+ /* project head location to screenspace */
+ if (screen_co_a[0] != IS_CLIPPED) {
+ points_proj_tot++;
+ if (armature_circle_doSelectJoint(data, ebone, screen_co_a, true)) {
+ is_point_done = true;
+ }
+ }
+
+ /* project tail location to screenspace */
+ if (screen_co_b[0] != IS_CLIPPED) {
+ points_proj_tot++;
+ if (armature_circle_doSelectJoint(data, ebone, screen_co_b, false)) {
+ is_point_done = true;
+ }
+ }
+
+ /* check if the head and/or tail is in the circle
+ * - the call to check also does the selection already
+ */
+
+ /* only if the endpoints didn't get selected, deal with the middle of the bone too
+ * It works nicer to only do this if the head or tail are not in the circle,
+ * otherwise there is no way to circle select joints alone */
+ if ((is_point_done == false) && (points_proj_tot == 2) &&
+ edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) {
+ if (data->select) {
+ ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else {
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ data->is_changed = true;
+ }
+
+ data->is_changed |= is_point_done;
+ }
+}
+static bool armature_circle_select(ViewContext *vc,
+ const eSelectOp sel_op,
+ const int mval[2],
+ float rad)
+{
+ CircleSelectUserData data;
+ bArmature *arm = vc->obedit->data;
+
+ const bool select = (sel_op != SEL_OP_SUB);
+
+ view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
+
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit);
+ }
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+
+ armature_foreachScreenBone(
+ vc, do_circle_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ if (data.is_changed) {
+ ED_armature_edit_sync_selection(arm->edbo);
+ ED_armature_edit_validate_active(arm);
+ WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit);
+ }
+ return data.is_changed;
+}
+
+static void do_circle_select_mball__doSelectElem(void *userData,
+ struct MetaElem *ml,
+ const float screen_co[2])
+{
+ CircleSelectUserData *data = userData;
+
+ if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
+ if (data->select) {
+ ml->flag |= SELECT;
+ }
+ else {
+ ml->flag &= ~SELECT;
+ }
+ data->is_changed = true;
+ }
+}
+static bool mball_circle_select(ViewContext *vc,
+ const eSelectOp sel_op,
+ const int mval[2],
+ float rad)
{
- CircleSelectUserData data;
- bArmature *arm = vc->obedit->data;
-
- const bool select = (sel_op != SEL_OP_SUB);
-
- view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
-
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit);
- }
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
-
- armature_foreachScreenBone(vc, do_circle_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
-
- if (data.is_changed) {
- ED_armature_edit_sync_selection(arm->edbo);
- ED_armature_edit_validate_active(arm);
- WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit);
- }
- return data.is_changed;
-}
-
-static void do_circle_select_mball__doSelectElem(void *userData, struct MetaElem *ml, const float screen_co[2])
-{
- CircleSelectUserData *data = userData;
-
- if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
- if (data->select) {
- ml->flag |= SELECT;
- }
- else {
- ml->flag &= ~SELECT;
- }
- data->is_changed = true;
- }
-}
-static bool mball_circle_select(ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad)
-{
- CircleSelectUserData data;
-
- const bool select = (sel_op != SEL_OP_SUB);
-
- view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
+ CircleSelectUserData data;
+
+ const bool select = (sel_op != SEL_OP_SUB);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- data.is_changed |= BKE_mball_deselect_all(vc->obedit->data);
- }
+ view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ data.is_changed |= BKE_mball_deselect_all(vc->obedit->data);
+ }
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mball_foreachScreenElem(vc, do_circle_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- return data.is_changed;
+ mball_foreachScreenElem(
+ vc, do_circle_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ return data.is_changed;
}
/** Callbacks for circle selection in Editmode */
-static bool obedit_circle_select(
- ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad)
-{
- BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB));
- switch (vc->obedit->type) {
- case OB_MESH:
- return mesh_circle_select(vc, sel_op, mval, rad);
- case OB_CURVE:
- case OB_SURF:
- return nurbscurve_circle_select(vc, sel_op, mval, rad);
- case OB_LATTICE:
- return lattice_circle_select(vc, sel_op, mval, rad);
- case OB_ARMATURE:
- return armature_circle_select(vc, sel_op, mval, rad);
- case OB_MBALL:
- return mball_circle_select(vc, sel_op, mval, rad);
- default:
- BLI_assert(0);
- return false;
- }
-}
-
-static bool object_circle_select(ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad)
-{
- BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB));
- ViewLayer *view_layer = vc->view_layer;
- View3D *v3d = vc->v3d;
-
- const float radius_squared = rad * rad;
- const float mval_fl[2] = {mval[0], mval[1]};
-
- bool changed = false;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- changed |= object_deselect_all_visible(vc->view_layer, vc->v3d);
- }
- const bool select = (sel_op != SEL_OP_SUB);
- const int select_flag = select ? BASE_SELECTED : 0;
-
- Base *base;
- 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, base->object->obmat[3], screen_co,
- V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
- {
- if (len_squared_v2v2(mval_fl, screen_co) <= radius_squared) {
- ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
- changed = true;
- }
- }
- }
- }
-
- return changed;
+static bool obedit_circle_select(ViewContext *vc,
+ const eSelectOp sel_op,
+ const int mval[2],
+ float rad)
+{
+ BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB));
+ switch (vc->obedit->type) {
+ case OB_MESH:
+ return mesh_circle_select(vc, sel_op, mval, rad);
+ case OB_CURVE:
+ case OB_SURF:
+ return nurbscurve_circle_select(vc, sel_op, mval, rad);
+ case OB_LATTICE:
+ return lattice_circle_select(vc, sel_op, mval, rad);
+ case OB_ARMATURE:
+ return armature_circle_select(vc, sel_op, mval, rad);
+ case OB_MBALL:
+ return mball_circle_select(vc, sel_op, mval, rad);
+ default:
+ BLI_assert(0);
+ return false;
+ }
+}
+
+static bool object_circle_select(ViewContext *vc,
+ const eSelectOp sel_op,
+ const int mval[2],
+ float rad)
+{
+ BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB));
+ ViewLayer *view_layer = vc->view_layer;
+ View3D *v3d = vc->v3d;
+
+ const float radius_squared = rad * rad;
+ const float mval_fl[2] = {mval[0], mval[1]};
+
+ bool changed = false;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ changed |= object_deselect_all_visible(vc->view_layer, vc->v3d);
+ }
+ const bool select = (sel_op != SEL_OP_SUB);
+ const int select_flag = select ? BASE_SELECTED : 0;
+
+ Base *base;
+ 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,
+ base->object->obmat[3],
+ screen_co,
+ V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN |
+ V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) {
+ if (len_squared_v2v2(mval_fl, screen_co) <= radius_squared) {
+ ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
+ changed = true;
+ }
+ }
+ }
+ }
+
+ return changed;
}
/* not a real operator, only for circle test */
static int view3d_circle_select_exec(bContext *C, wmOperator *op)
{
- ViewContext vc;
- const int radius = RNA_int_get(op->ptr, "radius");
- const int mval[2] = {RNA_int_get(op->ptr, "x"),
- RNA_int_get(op->ptr, "y")};
-
- const eSelectOp sel_op = ED_select_op_modal(
- RNA_enum_get(op->ptr, "mode"), WM_gesture_is_modal_first(op->customdata));
-
- ED_view3d_viewcontext_init(C, &vc);
-
- Object *obact = vc.obact;
- Object *obedit = vc.obedit;
-
- if (obedit || BKE_paint_select_elem_test(obact) ||
- (obact && (obact->mode & OB_MODE_POSE)))
- {
- view3d_operator_needs_opengl(C);
-
- FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, vc.v3d, obact->type, obact->mode, ob_iter) {
- ED_view3d_viewcontext_init_object(&vc, ob_iter);
-
- obact = vc.obact;
- obedit = vc.obedit;
-
- if (obedit) {
- if (obedit_circle_select(&vc, sel_op, mval, (float)radius)) {
- DEG_id_tag_update(obact->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
- }
- }
- else if (BKE_paint_select_face_test(obact)) {
- paint_facesel_circle_select(&vc, sel_op, mval, (float)radius);
- }
- else if (BKE_paint_select_vert_test(obact)) {
- paint_vertsel_circle_select(&vc, sel_op, mval, (float)radius);
- }
- else if (obact->mode & OB_MODE_POSE) {
- pose_circle_select(&vc, sel_op, mval, (float)radius);
- }
- else {
- BLI_assert(0);
- }
- }
- FOREACH_OBJECT_IN_MODE_END;
- }
- else if (obact && (obact->mode & OB_MODE_PARTICLE_EDIT)) {
- if (PE_circle_select(C, sel_op, mval, (float)radius)) {
- return OPERATOR_FINISHED;
- }
- return OPERATOR_CANCELLED;
- }
- else if (obact && obact->mode & OB_MODE_SCULPT) {
- return OPERATOR_CANCELLED;
- }
- else {
- if (object_circle_select(&vc, sel_op, mval, (float)radius)) {
- DEG_id_tag_update(&vc.scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc.scene);
- }
- }
-
- return OPERATOR_FINISHED;
+ ViewContext vc;
+ const int radius = RNA_int_get(op->ptr, "radius");
+ const int mval[2] = {RNA_int_get(op->ptr, "x"), RNA_int_get(op->ptr, "y")};
+
+ const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"),
+ WM_gesture_is_modal_first(op->customdata));
+
+ ED_view3d_viewcontext_init(C, &vc);
+
+ Object *obact = vc.obact;
+ Object *obedit = vc.obedit;
+
+ if (obedit || BKE_paint_select_elem_test(obact) || (obact && (obact->mode & OB_MODE_POSE))) {
+ view3d_operator_needs_opengl(C);
+
+ FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, vc.v3d, obact->type, obact->mode, ob_iter) {
+ ED_view3d_viewcontext_init_object(&vc, ob_iter);
+
+ obact = vc.obact;
+ obedit = vc.obedit;
+
+ if (obedit) {
+ if (obedit_circle_select(&vc, sel_op, mval, (float)radius)) {
+ DEG_id_tag_update(obact->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
+ }
+ }
+ else if (BKE_paint_select_face_test(obact)) {
+ paint_facesel_circle_select(&vc, sel_op, mval, (float)radius);
+ }
+ else if (BKE_paint_select_vert_test(obact)) {
+ paint_vertsel_circle_select(&vc, sel_op, mval, (float)radius);
+ }
+ else if (obact->mode & OB_MODE_POSE) {
+ pose_circle_select(&vc, sel_op, mval, (float)radius);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+ }
+ else if (obact && (obact->mode & OB_MODE_PARTICLE_EDIT)) {
+ if (PE_circle_select(C, sel_op, mval, (float)radius)) {
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_CANCELLED;
+ }
+ else if (obact && obact->mode & OB_MODE_SCULPT) {
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ if (object_circle_select(&vc, sel_op, mval, (float)radius)) {
+ DEG_id_tag_update(&vc.scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc.scene);
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_select_circle(wmOperatorType *ot)
{
- ot->name = "Circle Select";
- ot->description = "Select items using circle selection";
- ot->idname = "VIEW3D_OT_select_circle";
+ ot->name = "Circle Select";
+ ot->description = "Select items using circle selection";
+ ot->idname = "VIEW3D_OT_select_circle";
- ot->invoke = WM_gesture_circle_invoke;
- ot->modal = WM_gesture_circle_modal;
- ot->exec = view3d_circle_select_exec;
- ot->poll = view3d_selectable_data;
- ot->cancel = WM_gesture_circle_cancel;
+ ot->invoke = WM_gesture_circle_invoke;
+ ot->modal = WM_gesture_circle_modal;
+ ot->exec = view3d_circle_select_exec;
+ ot->poll = view3d_selectable_data;
+ ot->cancel = WM_gesture_circle_cancel;
- /* flags */
- ot->flag = OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_gesture_circle(ot);
- WM_operator_properties_select_operation_simple(ot);
+ /* properties */
+ WM_operator_properties_gesture_circle(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index 711e084f2ac..5aa19cc8a51 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -21,7 +21,6 @@
* \ingroup spview3d
*/
-
#include "MEM_guardedalloc.h"
#include "DNA_armature_types.h"
@@ -62,172 +61,172 @@
static bool snap_curs_to_sel_ex(bContext *C, float cursor[3]);
static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3]);
-
/* *********************** operators ******************** */
/** Snaps every individual object center to its nearest point on the grid. */
static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
- Object *obedit = CTX_data_edit_object(C);
- Scene *scene = CTX_data_scene(C);
- RegionView3D *rv3d = CTX_wm_region_data(C);
- View3D *v3d = CTX_wm_view3d(C);
- TransVertStore tvs = {NULL};
- TransVert *tv;
- float gridf, imat[3][3], bmat[3][3], vec[3];
- int a;
-
- gridf = ED_view3d_grid_view_scale(scene, v3d, rv3d, NULL);
-
- if (obedit) {
- 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++) {
- obedit = objects[ob_index];
-
- if (obedit->type == OB_MESH) {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totvertsel == 0) {
- continue;
- }
- }
-
- if (ED_transverts_check_obedit(obedit)) {
- ED_transverts_create_from_obedit(&tvs, obedit, 0);
- }
-
- if (tvs.transverts_tot != 0) {
- copy_m3_m4(bmat, obedit->obmat);
- invert_m3_m3(imat, bmat);
-
- tv = tvs.transverts;
- for (a = 0; a < tvs.transverts_tot; a++, tv++) {
- copy_v3_v3(vec, tv->loc);
- mul_m3_v3(bmat, vec);
- add_v3_v3(vec, obedit->obmat[3]);
- vec[0] = gridf * floorf(0.5f + vec[0] / gridf);
- vec[1] = gridf * floorf(0.5f + vec[1] / gridf);
- vec[2] = gridf * floorf(0.5f + vec[2] / gridf);
- sub_v3_v3(vec, obedit->obmat[3]);
-
- mul_m3_v3(imat, vec);
- copy_v3_v3(tv->loc, vec);
- }
- ED_transverts_update_obedit(&tvs, obedit);
- }
- ED_transverts_free(&tvs);
- }
- MEM_freeN(objects);
- }
- else {
- struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
-
- FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN(view_layer_eval, v3d, ob_eval)
- {
- Object *ob = DEG_get_original_object(ob_eval);
- if (ob->mode & OB_MODE_POSE) {
- bPoseChannel *pchan_eval;
- bArmature *arm_eval = ob_eval->data;
-
- invert_m4_m4(ob_eval->imat, ob_eval->obmat);
-
- for (pchan_eval = ob_eval->pose->chanbase.first; pchan_eval; pchan_eval = pchan_eval->next) {
- if (pchan_eval->bone->flag & BONE_SELECTED) {
- if (pchan_eval->bone->layer & arm_eval->layer) {
- if ((pchan_eval->bone->flag & BONE_CONNECTED) == 0) {
- float nLoc[3];
-
- /* get nearest grid point to snap to */
- copy_v3_v3(nLoc, pchan_eval->pose_mat[3]);
- /* We must operate in world space! */
- mul_m4_v3(ob_eval->obmat, nLoc);
- vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf);
- vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf);
- vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf);
- /* Back in object space... */
- mul_m4_v3(ob_eval->imat, vec);
-
- /* Get location of grid point in pose space. */
- BKE_armature_loc_pose_to_bone(pchan_eval, vec, vec);
-
- /* adjust location on the original pchan*/
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, pchan_eval->name);
- if ((pchan->protectflag & OB_LOCK_LOCX) == 0) {
- pchan->loc[0] = vec[0];
- }
- if ((pchan->protectflag & OB_LOCK_LOCY) == 0) {
- pchan->loc[1] = vec[1];
- }
- if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) {
- pchan->loc[2] = vec[2];
- }
-
- /* auto-keyframing */
- ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
- }
- /* if the bone has a parent and is connected to the parent,
- * don't do anything - will break chain unless we do auto-ik.
- */
- }
- }
- }
- ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- else {
- 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);
- vec[2] = -ob_eval->obmat[3][2] + gridf * floorf(0.5f + ob_eval->obmat[3][2] / gridf);
-
- if (ob->parent) {
- float originmat[3][3];
- BKE_object_where_is_calc_ex(depsgraph, scene, NULL, ob, originmat);
-
- invert_m3_m3(imat, originmat);
- mul_m3_v3(imat, vec);
- }
- if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
- ob->loc[0] = ob_eval->loc[0] + vec[0];
- }
- if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
- ob->loc[1] = ob_eval->loc[1] + vec[1];
- }
- if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
- ob->loc[2] = ob_eval->loc[2] + vec[2];
- }
-
- /* auto-keyframing */
- ED_autokeyframe_object(C, scene, ob, ks);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
- }
- FOREACH_SELECTED_EDITABLE_OBJECT_END;
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- return OPERATOR_FINISHED;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ RegionView3D *rv3d = CTX_wm_region_data(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ TransVertStore tvs = {NULL};
+ TransVert *tv;
+ float gridf, imat[3][3], bmat[3][3], vec[3];
+ int a;
+
+ gridf = ED_view3d_grid_view_scale(scene, v3d, rv3d, NULL);
+
+ if (obedit) {
+ 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++) {
+ obedit = objects[ob_index];
+
+ if (obedit->type == OB_MESH) {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
+ }
+
+ if (ED_transverts_check_obedit(obedit)) {
+ ED_transverts_create_from_obedit(&tvs, obedit, 0);
+ }
+
+ if (tvs.transverts_tot != 0) {
+ copy_m3_m4(bmat, obedit->obmat);
+ invert_m3_m3(imat, bmat);
+
+ tv = tvs.transverts;
+ for (a = 0; a < tvs.transverts_tot; a++, tv++) {
+ copy_v3_v3(vec, tv->loc);
+ mul_m3_v3(bmat, vec);
+ add_v3_v3(vec, obedit->obmat[3]);
+ vec[0] = gridf * floorf(0.5f + vec[0] / gridf);
+ vec[1] = gridf * floorf(0.5f + vec[1] / gridf);
+ vec[2] = gridf * floorf(0.5f + vec[2] / gridf);
+ sub_v3_v3(vec, obedit->obmat[3]);
+
+ mul_m3_v3(imat, vec);
+ copy_v3_v3(tv->loc, vec);
+ }
+ ED_transverts_update_obedit(&tvs, obedit);
+ }
+ ED_transverts_free(&tvs);
+ }
+ MEM_freeN(objects);
+ }
+ else {
+ struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
+
+ FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN (view_layer_eval, v3d, ob_eval) {
+ Object *ob = DEG_get_original_object(ob_eval);
+ if (ob->mode & OB_MODE_POSE) {
+ bPoseChannel *pchan_eval;
+ bArmature *arm_eval = ob_eval->data;
+
+ invert_m4_m4(ob_eval->imat, ob_eval->obmat);
+
+ for (pchan_eval = ob_eval->pose->chanbase.first; pchan_eval;
+ pchan_eval = pchan_eval->next) {
+ if (pchan_eval->bone->flag & BONE_SELECTED) {
+ if (pchan_eval->bone->layer & arm_eval->layer) {
+ if ((pchan_eval->bone->flag & BONE_CONNECTED) == 0) {
+ float nLoc[3];
+
+ /* get nearest grid point to snap to */
+ copy_v3_v3(nLoc, pchan_eval->pose_mat[3]);
+ /* We must operate in world space! */
+ mul_m4_v3(ob_eval->obmat, nLoc);
+ vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf);
+ vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf);
+ vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf);
+ /* Back in object space... */
+ mul_m4_v3(ob_eval->imat, vec);
+
+ /* Get location of grid point in pose space. */
+ BKE_armature_loc_pose_to_bone(pchan_eval, vec, vec);
+
+ /* adjust location on the original pchan*/
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, pchan_eval->name);
+ if ((pchan->protectflag & OB_LOCK_LOCX) == 0) {
+ pchan->loc[0] = vec[0];
+ }
+ if ((pchan->protectflag & OB_LOCK_LOCY) == 0) {
+ pchan->loc[1] = vec[1];
+ }
+ if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) {
+ pchan->loc[2] = vec[2];
+ }
+
+ /* auto-keyframing */
+ ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
+ }
+ /* if the bone has a parent and is connected to the parent,
+ * don't do anything - will break chain unless we do auto-ik.
+ */
+ }
+ }
+ }
+ ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ else {
+ 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);
+ vec[2] = -ob_eval->obmat[3][2] + gridf * floorf(0.5f + ob_eval->obmat[3][2] / gridf);
+
+ if (ob->parent) {
+ float originmat[3][3];
+ BKE_object_where_is_calc_ex(depsgraph, scene, NULL, ob, originmat);
+
+ invert_m3_m3(imat, originmat);
+ mul_m3_v3(imat, vec);
+ }
+ if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
+ ob->loc[0] = ob_eval->loc[0] + vec[0];
+ }
+ if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
+ ob->loc[1] = ob_eval->loc[1] + vec[1];
+ }
+ if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
+ ob->loc[2] = ob_eval->loc[2] + vec[2];
+ }
+
+ /* auto-keyframing */
+ ED_autokeyframe_object(C, scene, ob, ks);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+ }
+ FOREACH_SELECTED_EDITABLE_OBJECT_END;
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Snap Selection to Grid";
- ot->description = "Snap selected item(s) to their nearest grid division";
- ot->idname = "VIEW3D_OT_snap_selected_to_grid";
+ /* identifiers */
+ ot->name = "Snap Selection to Grid";
+ ot->description = "Snap selected item(s) to their nearest grid division";
+ ot->idname = "VIEW3D_OT_snap_selected_to_grid";
- /* api callbacks */
- ot->exec = snap_sel_to_grid_exec;
- ot->poll = ED_operator_region_view3d_active;
+ /* api callbacks */
+ ot->exec = snap_sel_to_grid_exec;
+ ot->poll = ED_operator_region_view3d_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
}
/* *************************************************** */
@@ -238,256 +237,257 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
* \param use_offset: if the selected objects should maintain their relative offsets and be snapped by the selection
* pivot point (median, active), or if every object origin should be snapped to the given location.
*/
-static int snap_selected_to_location(bContext *C, const float snap_target_global[3], const bool use_offset)
+static int snap_selected_to_location(bContext *C,
+ const float snap_target_global[3],
+ const bool use_offset)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- Object *obact = CTX_data_active_object(C);
- View3D *v3d = CTX_wm_view3d(C);
- TransVertStore tvs = {NULL};
- TransVert *tv;
- float imat[3][3], bmat[3][3];
- float center_global[3];
- float offset_global[3];
- int a;
-
- if (use_offset) {
- if ((v3d && scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) &&
- snap_calc_active_center(C, true, center_global))
- {
- /* pass */
- }
- else {
- snap_curs_to_sel_ex(C, center_global);
- }
- sub_v3_v3v3(offset_global, snap_target_global, center_global);
- }
-
- if (obedit) {
- float snap_target_local[3];
- 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++) {
- obedit = objects[ob_index];
-
- if (obedit->type == OB_MESH) {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totvertsel == 0) {
- continue;
- }
- }
-
- if (ED_transverts_check_obedit(obedit)) {
- ED_transverts_create_from_obedit(&tvs, obedit, 0);
- }
-
- if (tvs.transverts_tot != 0) {
- copy_m3_m4(bmat, obedit->obmat);
- invert_m3_m3(imat, bmat);
-
- /* get the cursor in object space */
- sub_v3_v3v3(snap_target_local, snap_target_global, obedit->obmat[3]);
- mul_m3_v3(imat, snap_target_local);
-
- if (use_offset) {
- float offset_local[3];
-
- mul_v3_m3v3(offset_local, imat, offset_global);
-
- tv = tvs.transverts;
- for (a = 0; a < tvs.transverts_tot; a++, tv++) {
- add_v3_v3(tv->loc, offset_local);
- }
- }
- else {
- tv = tvs.transverts;
- for (a = 0; a < tvs.transverts_tot; a++, tv++) {
- copy_v3_v3(tv->loc, snap_target_local);
- }
- }
- ED_transverts_update_obedit(&tvs, obedit);
- }
- ED_transverts_free(&tvs);
- }
- MEM_freeN(objects);
- }
- else if (obact && (obact->mode & OB_MODE_POSE)) {
- struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(view_layer, CTX_wm_view3d(C),
- &objects_len, OB_MODE_POSE);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- bPoseChannel *pchan;
- bArmature *arm = ob->data;
- float snap_target_local[3];
-
- invert_m4_m4(ob->imat, ob->obmat);
- mul_v3_m4v3(snap_target_local, ob->imat, snap_target_global);
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if ((pchan->bone->flag & BONE_SELECTED) &&
- (PBONE_VISIBLE(arm, pchan->bone)) &&
- /* if the bone has a parent and is connected to the parent,
- * don't do anything - will break chain unless we do auto-ik.
- */
- (pchan->bone->flag & BONE_CONNECTED) == 0)
- {
- pchan->bone->flag |= BONE_TRANSFORM;
- }
- else {
- pchan->bone->flag &= ~BONE_TRANSFORM;
- }
- }
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if ((pchan->bone->flag & BONE_TRANSFORM) &&
- /* check that our parents not transformed (if we have one) */
- ((pchan->bone->parent &&
- BKE_armature_bone_flag_test_recursive(pchan->bone->parent, BONE_TRANSFORM)) == 0))
- {
- /* Get position in pchan (pose) space. */
- float cursor_pose[3];
-
- if (use_offset) {
- mul_v3_m4v3(cursor_pose, ob->obmat, pchan->pose_mat[3]);
- add_v3_v3(cursor_pose, offset_global);
-
- mul_m4_v3(ob->imat, cursor_pose);
- BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose);
- }
- else {
- BKE_armature_loc_pose_to_bone(pchan, snap_target_local, cursor_pose);
- }
-
- /* copy new position */
- if ((pchan->protectflag & OB_LOCK_LOCX) == 0) {
- pchan->loc[0] = cursor_pose[0];
- }
- if ((pchan->protectflag & OB_LOCK_LOCY) == 0) {
- pchan->loc[1] = cursor_pose[1];
- }
- if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) {
- pchan->loc[2] = cursor_pose[2];
- }
-
- /* auto-keyframing */
- ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
- }
- }
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- pchan->bone->flag &= ~BONE_TRANSFORM;
- }
-
- ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- MEM_freeN(objects);
- }
- else {
- struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
- Main *bmain = CTX_data_main(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) {
- 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;
- }
-
- for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
- ob = ctx_ob->ptr.data;
-
- if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) {
-
- float cursor_parent[3]; /* parent-relative */
-
- if (use_offset) {
- add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global);
- }
- else {
- copy_v3_v3(cursor_parent, snap_target_global);
- }
-
- sub_v3_v3(cursor_parent, ob->obmat[3]);
-
- if (ob->parent) {
- float originmat[3][3];
- BKE_object_where_is_calc_ex(depsgraph, scene, NULL, ob, originmat);
-
- invert_m3_m3(imat, originmat);
- mul_m3_v3(imat, cursor_parent);
- }
- if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
- ob->loc[0] += cursor_parent[0];
- }
- if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
- ob->loc[1] += cursor_parent[1];
- }
- if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
- ob->loc[2] += cursor_parent[2];
- }
-
- /* auto-keyframing */
- ED_autokeyframe_object(C, scene, ob, ks);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
- }
-
- BLI_freelistN(&ctx_data_list);
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- return OPERATOR_FINISHED;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ Object *obact = CTX_data_active_object(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ TransVertStore tvs = {NULL};
+ TransVert *tv;
+ float imat[3][3], bmat[3][3];
+ float center_global[3];
+ float offset_global[3];
+ int a;
+
+ if (use_offset) {
+ if ((v3d && scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) &&
+ snap_calc_active_center(C, true, center_global)) {
+ /* pass */
+ }
+ else {
+ snap_curs_to_sel_ex(C, center_global);
+ }
+ sub_v3_v3v3(offset_global, snap_target_global, center_global);
+ }
+
+ if (obedit) {
+ float snap_target_local[3];
+ 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++) {
+ obedit = objects[ob_index];
+
+ if (obedit->type == OB_MESH) {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
+ }
+
+ if (ED_transverts_check_obedit(obedit)) {
+ ED_transverts_create_from_obedit(&tvs, obedit, 0);
+ }
+
+ if (tvs.transverts_tot != 0) {
+ copy_m3_m4(bmat, obedit->obmat);
+ invert_m3_m3(imat, bmat);
+
+ /* get the cursor in object space */
+ sub_v3_v3v3(snap_target_local, snap_target_global, obedit->obmat[3]);
+ mul_m3_v3(imat, snap_target_local);
+
+ if (use_offset) {
+ float offset_local[3];
+
+ mul_v3_m3v3(offset_local, imat, offset_global);
+
+ tv = tvs.transverts;
+ for (a = 0; a < tvs.transverts_tot; a++, tv++) {
+ add_v3_v3(tv->loc, offset_local);
+ }
+ }
+ else {
+ tv = tvs.transverts;
+ for (a = 0; a < tvs.transverts_tot; a++, tv++) {
+ copy_v3_v3(tv->loc, snap_target_local);
+ }
+ }
+ ED_transverts_update_obedit(&tvs, obedit);
+ }
+ ED_transverts_free(&tvs);
+ }
+ MEM_freeN(objects);
+ }
+ else if (obact && (obact->mode & OB_MODE_POSE)) {
+ struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len, OB_MODE_POSE);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ bPoseChannel *pchan;
+ bArmature *arm = ob->data;
+ float snap_target_local[3];
+
+ invert_m4_m4(ob->imat, ob->obmat);
+ mul_v3_m4v3(snap_target_local, ob->imat, snap_target_global);
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if ((pchan->bone->flag & BONE_SELECTED) && (PBONE_VISIBLE(arm, pchan->bone)) &&
+ /* if the bone has a parent and is connected to the parent,
+ * don't do anything - will break chain unless we do auto-ik.
+ */
+ (pchan->bone->flag & BONE_CONNECTED) == 0) {
+ pchan->bone->flag |= BONE_TRANSFORM;
+ }
+ else {
+ pchan->bone->flag &= ~BONE_TRANSFORM;
+ }
+ }
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if ((pchan->bone->flag & BONE_TRANSFORM) &&
+ /* check that our parents not transformed (if we have one) */
+ ((pchan->bone->parent &&
+ BKE_armature_bone_flag_test_recursive(pchan->bone->parent, BONE_TRANSFORM)) == 0)) {
+ /* Get position in pchan (pose) space. */
+ float cursor_pose[3];
+
+ if (use_offset) {
+ mul_v3_m4v3(cursor_pose, ob->obmat, pchan->pose_mat[3]);
+ add_v3_v3(cursor_pose, offset_global);
+
+ mul_m4_v3(ob->imat, cursor_pose);
+ BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose);
+ }
+ else {
+ BKE_armature_loc_pose_to_bone(pchan, snap_target_local, cursor_pose);
+ }
+
+ /* copy new position */
+ if ((pchan->protectflag & OB_LOCK_LOCX) == 0) {
+ pchan->loc[0] = cursor_pose[0];
+ }
+ if ((pchan->protectflag & OB_LOCK_LOCY) == 0) {
+ pchan->loc[1] = cursor_pose[1];
+ }
+ if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) {
+ pchan->loc[2] = cursor_pose[2];
+ }
+
+ /* auto-keyframing */
+ ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
+ }
+ }
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ pchan->bone->flag &= ~BONE_TRANSFORM;
+ }
+
+ ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ MEM_freeN(objects);
+ }
+ else {
+ struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
+ Main *bmain = CTX_data_main(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) {
+ 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;
+ }
+
+ for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
+ ob = ctx_ob->ptr.data;
+
+ if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) {
+
+ float cursor_parent[3]; /* parent-relative */
+
+ if (use_offset) {
+ add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global);
+ }
+ else {
+ copy_v3_v3(cursor_parent, snap_target_global);
+ }
+
+ sub_v3_v3(cursor_parent, ob->obmat[3]);
+
+ if (ob->parent) {
+ float originmat[3][3];
+ BKE_object_where_is_calc_ex(depsgraph, scene, NULL, ob, originmat);
+
+ invert_m3_m3(imat, originmat);
+ mul_m3_v3(imat, cursor_parent);
+ }
+ if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
+ ob->loc[0] += cursor_parent[0];
+ }
+ if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
+ ob->loc[1] += cursor_parent[1];
+ }
+ if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
+ ob->loc[2] += cursor_parent[2];
+ }
+
+ /* auto-keyframing */
+ ED_autokeyframe_object(C, scene, ob, ks);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+ }
+
+ BLI_freelistN(&ctx_data_list);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
}
static int snap_selected_to_cursor_exec(bContext *C, wmOperator *op)
{
- const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");
+ const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- const float *snap_target_global = scene->cursor.location;
+ const float *snap_target_global = scene->cursor.location;
- return snap_selected_to_location(C, snap_target_global, use_offset);
+ return snap_selected_to_location(C, snap_target_global, use_offset);
}
void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Snap Selection to Cursor";
- ot->description = "Snap selected item(s) to the 3D cursor";
- ot->idname = "VIEW3D_OT_snap_selected_to_cursor";
-
- /* api callbacks */
- ot->exec = snap_selected_to_cursor_exec;
- ot->poll = ED_operator_view3d_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
-
- /* rna */
- RNA_def_boolean(
- ot->srna, "use_offset", 1, "Offset",
- "If the selection should be snapped as a whole or by each object center");
+ /* identifiers */
+ ot->name = "Snap Selection to Cursor";
+ ot->description = "Snap selected item(s) to the 3D cursor";
+ ot->idname = "VIEW3D_OT_snap_selected_to_cursor";
+
+ /* api callbacks */
+ ot->exec = snap_selected_to_cursor_exec;
+ ot->poll = ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+
+ /* rna */
+ RNA_def_boolean(ot->srna,
+ "use_offset",
+ 1,
+ "Offset",
+ "If the selection should be snapped as a whole or by each object center");
}
/* *************************************************** */
@@ -495,68 +495,67 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
/** Snaps each selected object to the location of the active selected object. */
static int snap_selected_to_active_exec(bContext *C, wmOperator *op)
{
- float snap_target_global[3];
+ float snap_target_global[3];
- if (snap_calc_active_center(C, false, snap_target_global) == false) {
- BKE_report(op->reports, RPT_ERROR, "No active element found!");
- return OPERATOR_CANCELLED;
- }
+ if (snap_calc_active_center(C, false, snap_target_global) == false) {
+ BKE_report(op->reports, RPT_ERROR, "No active element found!");
+ return OPERATOR_CANCELLED;
+ }
- return snap_selected_to_location(C, snap_target_global, false);
+ return snap_selected_to_location(C, snap_target_global, false);
}
void VIEW3D_OT_snap_selected_to_active(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Snap Selection to Active";
- ot->description = "Snap selected item(s) to the active item";
- ot->idname = "VIEW3D_OT_snap_selected_to_active";
+ /* identifiers */
+ ot->name = "Snap Selection to Active";
+ ot->description = "Snap selected item(s) to the active item";
+ ot->idname = "VIEW3D_OT_snap_selected_to_active";
- /* api callbacks */
- ot->exec = snap_selected_to_active_exec;
- ot->poll = ED_operator_view3d_active;
+ /* api callbacks */
+ ot->exec = snap_selected_to_active_exec;
+ ot->poll = ED_operator_view3d_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
}
-
/* *************************************************** */
/** Snaps the 3D cursor location to its nearest point on the grid. */
static int snap_curs_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- RegionView3D *rv3d = CTX_wm_region_data(C);
- View3D *v3d = CTX_wm_view3d(C);
- float gridf, *curs;
+ Scene *scene = CTX_data_scene(C);
+ RegionView3D *rv3d = CTX_wm_region_data(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ float gridf, *curs;
- gridf = ED_view3d_grid_view_scale(scene, v3d, rv3d, NULL);
- curs = scene->cursor.location;
+ gridf = ED_view3d_grid_view_scale(scene, v3d, rv3d, NULL);
+ curs = scene->cursor.location;
- curs[0] = gridf * floorf(0.5f + curs[0] / gridf);
- curs[1] = gridf * floorf(0.5f + curs[1] / gridf);
- curs[2] = gridf * floorf(0.5f + curs[2] / gridf);
+ curs[0] = gridf * floorf(0.5f + curs[0] / gridf);
+ curs[1] = gridf * floorf(0.5f + curs[1] / gridf);
+ curs[2] = gridf * floorf(0.5f + curs[2] / gridf);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); /* hrm */
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); /* hrm */
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Snap Cursor to Grid";
- ot->description = "Snap 3D cursor to the nearest grid division";
- ot->idname = "VIEW3D_OT_snap_cursor_to_grid";
+ /* identifiers */
+ ot->name = "Snap Cursor to Grid";
+ ot->description = "Snap 3D cursor to the nearest grid division";
+ ot->idname = "VIEW3D_OT_snap_cursor_to_grid";
- /* api callbacks */
- ot->exec = snap_curs_to_grid_exec;
- ot->poll = ED_operator_region_view3d_active;
+ /* api callbacks */
+ ot->exec = snap_curs_to_grid_exec;
+ ot->poll = ED_operator_region_view3d_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* **************************************************** */
@@ -567,202 +566,202 @@ void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot)
*/
static void bundle_midpoint(Scene *scene, Object *ob, float r_vec[3])
{
- MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
- MovieTracking *tracking;
- MovieTrackingObject *object;
- bool ok = false;
- float min[3], max[3], mat[4][4], pos[3], cammat[4][4];
+ MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
+ MovieTracking *tracking;
+ MovieTrackingObject *object;
+ bool ok = false;
+ float min[3], max[3], mat[4][4], pos[3], cammat[4][4];
- if (!clip) {
- return;
- }
+ if (!clip) {
+ return;
+ }
- tracking = &clip->tracking;
+ tracking = &clip->tracking;
- copy_m4_m4(cammat, ob->obmat);
+ copy_m4_m4(cammat, ob->obmat);
- BKE_tracking_get_camera_object_matrix(scene, ob, mat);
+ BKE_tracking_get_camera_object_matrix(scene, ob, mat);
- INIT_MINMAX(min, max);
+ INIT_MINMAX(min, max);
- for (object = tracking->objects.first; object; object = object->next) {
- ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
- MovieTrackingTrack *track = tracksbase->first;
- float obmat[4][4];
+ for (object = tracking->objects.first; object; object = object->next) {
+ ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
+ MovieTrackingTrack *track = tracksbase->first;
+ float obmat[4][4];
- if (object->flag & TRACKING_OBJECT_CAMERA) {
- copy_m4_m4(obmat, mat);
- }
- else {
- float imat[4][4];
+ if (object->flag & TRACKING_OBJECT_CAMERA) {
+ copy_m4_m4(obmat, mat);
+ }
+ else {
+ float imat[4][4];
- BKE_tracking_camera_get_reconstructed_interpolate(tracking, object, scene->r.cfra, imat);
- invert_m4(imat);
+ BKE_tracking_camera_get_reconstructed_interpolate(tracking, object, scene->r.cfra, imat);
+ invert_m4(imat);
- mul_m4_m4m4(obmat, cammat, imat);
- }
+ mul_m4_m4m4(obmat, cammat, imat);
+ }
- while (track) {
- if ((track->flag & TRACK_HAS_BUNDLE) && TRACK_SELECTED(track)) {
- ok = 1;
- mul_v3_m4v3(pos, obmat, track->bundle_pos);
- minmax_v3v3_v3(min, max, pos);
- }
+ while (track) {
+ if ((track->flag & TRACK_HAS_BUNDLE) && TRACK_SELECTED(track)) {
+ ok = 1;
+ mul_v3_m4v3(pos, obmat, track->bundle_pos);
+ minmax_v3v3_v3(min, max, pos);
+ }
- track = track->next;
- }
- }
+ track = track->next;
+ }
+ }
- if (ok) {
- mid_v3_v3v3(r_vec, min, max);
- }
+ if (ok) {
+ mid_v3_v3v3(r_vec, min, max);
+ }
}
/** Snaps the 3D cursor location to the median point of the selection. */
static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
- Object *obedit = CTX_data_edit_object(C);
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- TransVertStore tvs = {NULL};
- TransVert *tv;
- float bmat[3][3], vec[3], min[3], max[3], centroid[3];
- int count, a;
-
- count = 0;
- INIT_MINMAX(min, max);
- zero_v3(centroid);
-
- if (obedit) {
- int global_transverts_tot = 0;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- obedit = objects[ob_index];
-
- /* We can do that quick check for meshes only... */
- if (obedit->type == OB_MESH) {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totvertsel == 0) {
- continue;
- }
- }
-
- if (ED_transverts_check_obedit(obedit)) {
- ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES);
- }
-
- global_transverts_tot += tvs.transverts_tot;
- if (tvs.transverts_tot != 0) {
- Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit);
- copy_m3_m4(bmat, obedit_eval->obmat);
-
- tv = tvs.transverts;
- for (a = 0; a < tvs.transverts_tot; a++, tv++) {
- copy_v3_v3(vec, tv->loc);
- mul_m3_v3(bmat, vec);
- add_v3_v3(vec, obedit_eval->obmat[3]);
- add_v3_v3(centroid, vec);
- minmax_v3v3_v3(min, max, vec);
- }
- }
- ED_transverts_free(&tvs);
- }
- MEM_freeN(objects);
-
- if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEDIAN) {
- mul_v3_fl(centroid, 1.0f / (float)global_transverts_tot);
- copy_v3_v3(cursor, centroid);
- }
- else {
- mid_v3_v3v3(cursor, min, max);
- }
- }
- else {
- Object *obact = CTX_data_active_object(C);
-
- if (obact && (obact->mode & OB_MODE_POSE)) {
- Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact);
- bArmature *arm = obact_eval->data;
- bPoseChannel *pchan;
- for (pchan = obact_eval->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (arm->layer & pchan->bone->layer) {
- if (pchan->bone->flag & BONE_SELECTED) {
- copy_v3_v3(vec, pchan->pose_head);
- mul_m4_v3(obact_eval->obmat, vec);
- add_v3_v3(centroid, vec);
- minmax_v3v3_v3(min, max, vec);
- count++;
- }
- }
- }
- }
- else {
- FOREACH_SELECTED_OBJECT_BEGIN(view_layer_eval, v3d, ob_eval)
- {
- copy_v3_v3(vec, ob_eval->obmat[3]);
-
- /* special case for camera -- snap to bundles */
- if (ob_eval->type == OB_CAMERA) {
- /* snap to bundles should happen only when bundles are visible */
- if (v3d->flag2 & V3D_SHOW_RECONSTRUCTION) {
- bundle_midpoint(scene, DEG_get_original_object(ob_eval), vec);
- }
- }
-
- add_v3_v3(centroid, vec);
- minmax_v3v3_v3(min, max, vec);
- count++;
- }
- FOREACH_SELECTED_OBJECT_END;
- }
-
- if (count == 0) {
- return false;
- }
-
- if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEDIAN) {
- mul_v3_fl(centroid, 1.0f / (float)count);
- copy_v3_v3(cursor, centroid);
- }
- else {
- mid_v3_v3v3(cursor, min, max);
- }
- }
- return true;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ TransVertStore tvs = {NULL};
+ TransVert *tv;
+ float bmat[3][3], vec[3], min[3], max[3], centroid[3];
+ int count, a;
+
+ count = 0;
+ INIT_MINMAX(min, max);
+ zero_v3(centroid);
+
+ if (obedit) {
+ int global_transverts_tot = 0;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ obedit = objects[ob_index];
+
+ /* We can do that quick check for meshes only... */
+ if (obedit->type == OB_MESH) {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
+ }
+
+ if (ED_transverts_check_obedit(obedit)) {
+ ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES);
+ }
+
+ global_transverts_tot += tvs.transverts_tot;
+ if (tvs.transverts_tot != 0) {
+ Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit);
+ copy_m3_m4(bmat, obedit_eval->obmat);
+
+ tv = tvs.transverts;
+ for (a = 0; a < tvs.transverts_tot; a++, tv++) {
+ copy_v3_v3(vec, tv->loc);
+ mul_m3_v3(bmat, vec);
+ add_v3_v3(vec, obedit_eval->obmat[3]);
+ add_v3_v3(centroid, vec);
+ minmax_v3v3_v3(min, max, vec);
+ }
+ }
+ ED_transverts_free(&tvs);
+ }
+ MEM_freeN(objects);
+
+ if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEDIAN) {
+ mul_v3_fl(centroid, 1.0f / (float)global_transverts_tot);
+ copy_v3_v3(cursor, centroid);
+ }
+ else {
+ mid_v3_v3v3(cursor, min, max);
+ }
+ }
+ else {
+ Object *obact = CTX_data_active_object(C);
+
+ if (obact && (obact->mode & OB_MODE_POSE)) {
+ Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact);
+ bArmature *arm = obact_eval->data;
+ bPoseChannel *pchan;
+ for (pchan = obact_eval->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (arm->layer & pchan->bone->layer) {
+ if (pchan->bone->flag & BONE_SELECTED) {
+ copy_v3_v3(vec, pchan->pose_head);
+ mul_m4_v3(obact_eval->obmat, vec);
+ add_v3_v3(centroid, vec);
+ minmax_v3v3_v3(min, max, vec);
+ count++;
+ }
+ }
+ }
+ }
+ else {
+ FOREACH_SELECTED_OBJECT_BEGIN (view_layer_eval, v3d, ob_eval) {
+ copy_v3_v3(vec, ob_eval->obmat[3]);
+
+ /* special case for camera -- snap to bundles */
+ if (ob_eval->type == OB_CAMERA) {
+ /* snap to bundles should happen only when bundles are visible */
+ if (v3d->flag2 & V3D_SHOW_RECONSTRUCTION) {
+ bundle_midpoint(scene, DEG_get_original_object(ob_eval), vec);
+ }
+ }
+
+ add_v3_v3(centroid, vec);
+ minmax_v3v3_v3(min, max, vec);
+ count++;
+ }
+ FOREACH_SELECTED_OBJECT_END;
+ }
+
+ if (count == 0) {
+ return false;
+ }
+
+ if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEDIAN) {
+ mul_v3_fl(centroid, 1.0f / (float)count);
+ copy_v3_v3(cursor, centroid);
+ }
+ else {
+ mid_v3_v3v3(cursor, min, max);
+ }
+ }
+ return true;
}
static int snap_curs_to_sel_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- if (snap_curs_to_sel_ex(C, scene->cursor.location)) {
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Scene *scene = CTX_data_scene(C);
+ if (snap_curs_to_sel_ex(C, scene->cursor.location)) {
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Snap Cursor to Selected";
- ot->description = "Snap 3D cursor to the middle of the selected item(s)";
- ot->idname = "VIEW3D_OT_snap_cursor_to_selected";
+ /* identifiers */
+ ot->name = "Snap Cursor to Selected";
+ ot->description = "Snap 3D cursor to the middle of the selected item(s)";
+ ot->idname = "VIEW3D_OT_snap_cursor_to_selected";
- /* api callbacks */
- ot->exec = snap_curs_to_sel_exec;
- ot->poll = ED_operator_view3d_active;
+ /* api callbacks */
+ ot->exec = snap_curs_to_sel_exec;
+ ot->poll = ED_operator_view3d_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
}
/* ********************************************** */
@@ -774,42 +773,42 @@ void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot)
*/
static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3])
{
- Object *ob = CTX_data_active_object(C);
- if (ob == NULL) {
- return false;
- }
- return ED_object_calc_active_center(ob, select_only, r_center);
+ Object *ob = CTX_data_active_object(C);
+ if (ob == NULL) {
+ return false;
+ }
+ return ED_object_calc_active_center(ob, select_only, r_center);
}
static int snap_curs_to_active_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
-
- if (snap_calc_active_center(C, false, scene->cursor.location)) {
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ if (snap_calc_active_center(C, false, scene->cursor.location)) {
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Snap Cursor to Active";
- ot->description = "Snap 3D cursor to the active item";
- ot->idname = "VIEW3D_OT_snap_cursor_to_active";
+ /* identifiers */
+ ot->name = "Snap Cursor to Active";
+ ot->description = "Snap 3D cursor to the active item";
+ ot->idname = "VIEW3D_OT_snap_cursor_to_active";
- /* api callbacks */
- ot->exec = snap_curs_to_active_exec;
- ot->poll = ED_operator_view3d_active;
+ /* api callbacks */
+ ot->exec = snap_curs_to_active_exec;
+ ot->poll = ED_operator_view3d_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
}
/* **************************************************** */
@@ -817,32 +816,32 @@ void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot)
/** Snaps the 3D cursor location to the origin and clears cursor rotation. */
static int snap_curs_to_center_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- float mat3[3][3];
- unit_m3(mat3);
+ Scene *scene = CTX_data_scene(C);
+ float mat3[3][3];
+ unit_m3(mat3);
- zero_v3(scene->cursor.location);
- BKE_scene_cursor_mat3_to_rot(&scene->cursor, mat3, false);
+ zero_v3(scene->cursor.location);
+ BKE_scene_cursor_mat3_to_rot(&scene->cursor, mat3, false);
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- return OPERATOR_FINISHED;
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Snap Cursor to World Origin";
- ot->description = "Snap 3D cursor to the world origin";
- ot->idname = "VIEW3D_OT_snap_cursor_to_center";
+ /* identifiers */
+ ot->name = "Snap Cursor to World Origin";
+ ot->description = "Snap 3D cursor to the world origin";
+ ot->idname = "VIEW3D_OT_snap_cursor_to_center";
- /* api callbacks */
- ot->exec = snap_curs_to_center_exec;
- ot->poll = ED_operator_view3d_active;
+ /* api callbacks */
+ ot->exec = snap_curs_to_center_exec;
+ ot->poll = ED_operator_view3d_active;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* **************************************************** */
@@ -853,43 +852,43 @@ void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot)
*/
bool ED_view3d_minmax_verts(Object *obedit, float r_min[3], float r_max[3])
{
- TransVertStore tvs = {NULL};
- TransVert *tv;
- float centroid[3], vec[3], bmat[3][3];
-
- /* Metaballs are an exception. */
- if (obedit->type == OB_MBALL) {
- float ob_min[3], ob_max[3];
- bool changed;
-
- changed = BKE_mball_minmax_ex(obedit->data, ob_min, ob_max, obedit->obmat, SELECT);
- if (changed) {
- minmax_v3v3_v3(r_min, r_max, ob_min);
- minmax_v3v3_v3(r_min, r_max, ob_max);
- }
- return changed;
- }
-
- if (ED_transverts_check_obedit(obedit)) {
- ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS);
- }
-
- if (tvs.transverts_tot == 0) {
- return false;
- }
-
- copy_m3_m4(bmat, obedit->obmat);
-
- tv = tvs.transverts;
- for (int a = 0; a < tvs.transverts_tot; a++, tv++) {
- copy_v3_v3(vec, (tv->flag & TX_VERT_USE_MAPLOC) ? tv->maploc : tv->loc);
- mul_m3_v3(bmat, vec);
- add_v3_v3(vec, obedit->obmat[3]);
- add_v3_v3(centroid, vec);
- minmax_v3v3_v3(r_min, r_max, vec);
- }
-
- ED_transverts_free(&tvs);
-
- return true;
+ TransVertStore tvs = {NULL};
+ TransVert *tv;
+ float centroid[3], vec[3], bmat[3][3];
+
+ /* Metaballs are an exception. */
+ if (obedit->type == OB_MBALL) {
+ float ob_min[3], ob_max[3];
+ bool changed;
+
+ changed = BKE_mball_minmax_ex(obedit->data, ob_min, ob_max, obedit->obmat, SELECT);
+ if (changed) {
+ minmax_v3v3_v3(r_min, r_max, ob_min);
+ minmax_v3v3_v3(r_min, r_max, ob_max);
+ }
+ return changed;
+ }
+
+ if (ED_transverts_check_obedit(obedit)) {
+ ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS);
+ }
+
+ if (tvs.transverts_tot == 0) {
+ return false;
+ }
+
+ copy_m3_m4(bmat, obedit->obmat);
+
+ tv = tvs.transverts;
+ for (int a = 0; a < tvs.transverts_tot; a++, tv++) {
+ copy_v3_v3(vec, (tv->flag & TX_VERT_USE_MAPLOC) ? tv->maploc : tv->loc);
+ mul_m3_v3(bmat, vec);
+ add_v3_v3(vec, obedit->obmat[3]);
+ add_v3_v3(centroid, vec);
+ minmax_v3v3_v3(r_min, r_max, vec);
+ }
+
+ ED_transverts_free(&tvs);
+
+ return true;
}
diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c
index c96e524ec2b..9357d3e05ee 100644
--- a/source/blender/editors/space_view3d/view3d_toolbar.c
+++ b/source/blender/editors/space_view3d/view3d_toolbar.c
@@ -37,31 +37,31 @@
#include "ED_screen.h"
-#include "view3d_intern.h" /* own include */
+#include "view3d_intern.h" /* own include */
/* ********** operator to open/close toolshelf region */
static int view3d_toolshelf_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = view3d_has_tools_region(sa);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = view3d_has_tools_region(sa);
- if (ar) {
- ED_region_toggle_hidden(C, ar);
- }
+ if (ar) {
+ ED_region_toggle_hidden(C, ar);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_toolshelf(wmOperatorType *ot)
{
- ot->name = "Toggle Toolbar";
- ot->description = "Toggles tool shelf display";
- ot->idname = "VIEW3D_OT_toolshelf";
+ ot->name = "Toggle Toolbar";
+ ot->description = "Toggles tool shelf display";
+ ot->idname = "VIEW3D_OT_toolshelf";
- ot->exec = view3d_toolshelf_toggle_exec;
- ot->poll = ED_operator_view3d_active;
+ ot->exec = view3d_toolshelf_toggle_exec;
+ ot->poll = ED_operator_view3d_active;
- /* flags */
- ot->flag = 0;
+ /* flags */
+ ot->flag = 0;
}
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index 0639bdaa71c..3f078e35046 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -63,7 +63,7 @@
#include "UI_resources.h"
-#include "view3d_intern.h" /* own include */
+#include "view3d_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name View Data Access Utilities
@@ -72,115 +72,118 @@
void ED_view3d_background_color_get(const Scene *scene, const View3D *v3d, float r_color[3])
{
- if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_WORLD) {
- if (scene->world) {
- copy_v3_v3(r_color, &scene->world->horr);
- return;
- }
- }
- else if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_VIEWPORT) {
- copy_v3_v3(r_color, v3d->shading.background_color);
- return;
- }
-
- UI_GetThemeColor3fv(TH_BACK, r_color);
+ if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_WORLD) {
+ if (scene->world) {
+ copy_v3_v3(r_color, &scene->world->horr);
+ return;
+ }
+ }
+ else if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_VIEWPORT) {
+ copy_v3_v3(r_color, v3d->shading.background_color);
+ return;
+ }
+
+ UI_GetThemeColor3fv(TH_BACK, r_color);
}
void ED_view3d_cursor3d_calc_mat3(const Scene *scene, float mat[3][3])
{
- const View3DCursor *cursor = &scene->cursor;
- BKE_scene_cursor_rot_to_mat3(cursor, mat);
+ const View3DCursor *cursor = &scene->cursor;
+ BKE_scene_cursor_rot_to_mat3(cursor, mat);
}
void ED_view3d_cursor3d_calc_mat4(const Scene *scene, float mat[4][4])
{
- const View3DCursor *cursor = &scene->cursor;
- float mat3[3][3];
- BKE_scene_cursor_rot_to_mat3(cursor, mat3);
- copy_m4_m3(mat, mat3);
- copy_v3_v3(mat[3], cursor->location);
+ const View3DCursor *cursor = &scene->cursor;
+ float mat3[3][3];
+ BKE_scene_cursor_rot_to_mat3(cursor, mat3);
+ copy_m4_m3(mat, mat3);
+ copy_v3_v3(mat[3], cursor->location);
}
Camera *ED_view3d_camera_data_get(View3D *v3d, RegionView3D *rv3d)
{
- /* establish the camera object,
- * so we can default to view mapping if anything is wrong with it */
- if ((rv3d->persp == RV3D_CAMOB) && v3d->camera && (v3d->camera->type == OB_CAMERA)) {
- return v3d->camera->data;
- }
- else {
- return NULL;
- }
+ /* establish the camera object,
+ * so we can default to view mapping if anything is wrong with it */
+ if ((rv3d->persp == RV3D_CAMOB) && v3d->camera && (v3d->camera->type == OB_CAMERA)) {
+ return v3d->camera->data;
+ }
+ else {
+ return NULL;
+ }
}
-void ED_view3d_dist_range_get(
- const View3D *v3d,
- float r_dist_range[2])
+void ED_view3d_dist_range_get(const View3D *v3d, float r_dist_range[2])
{
- r_dist_range[0] = v3d->grid * 0.001f;
- r_dist_range[1] = v3d->clip_end * 10.0f;
+ r_dist_range[0] = v3d->grid * 0.001f;
+ r_dist_range[1] = v3d->clip_end * 10.0f;
}
/**
* \note copies logic of #ED_view3d_viewplane_get(), keep in sync.
*/
-bool ED_view3d_clip_range_get(
- Depsgraph *depsgraph,
- const View3D *v3d, const RegionView3D *rv3d,
- float *r_clipsta, float *r_clipend,
- const bool use_ortho_factor)
+bool ED_view3d_clip_range_get(Depsgraph *depsgraph,
+ const View3D *v3d,
+ const RegionView3D *rv3d,
+ float *r_clipsta,
+ float *r_clipend,
+ const bool use_ortho_factor)
{
- CameraParams params;
+ CameraParams params;
- BKE_camera_params_init(&params);
- BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
- if (use_ortho_factor && params.is_ortho) {
- const float fac = 2.0f / (params.clip_end - params.clip_start);
- params.clip_start *= fac;
- params.clip_end *= fac;
- }
+ if (use_ortho_factor && params.is_ortho) {
+ const float fac = 2.0f / (params.clip_end - params.clip_start);
+ params.clip_start *= fac;
+ params.clip_end *= fac;
+ }
- if (r_clipsta) {
- *r_clipsta = params.clip_start;
- }
- if (r_clipend) {
- *r_clipend = params.clip_end;
- }
+ if (r_clipsta) {
+ *r_clipsta = params.clip_start;
+ }
+ if (r_clipend) {
+ *r_clipend = params.clip_end;
+ }
- return params.is_ortho;
+ return params.is_ortho;
}
-bool ED_view3d_viewplane_get(
- Depsgraph *depsgraph,
- const View3D *v3d, const RegionView3D *rv3d, int winx, int winy,
- rctf *r_viewplane, float *r_clip_start, float *r_clip_end, float *r_pixsize)
+bool ED_view3d_viewplane_get(Depsgraph *depsgraph,
+ const View3D *v3d,
+ const RegionView3D *rv3d,
+ int winx,
+ int winy,
+ rctf *r_viewplane,
+ float *r_clip_start,
+ float *r_clip_end,
+ float *r_pixsize)
{
- CameraParams params;
-
- BKE_camera_params_init(&params);
- BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
- BKE_camera_params_compute_viewplane(&params, winx, winy, 1.0f, 1.0f);
-
- if (r_viewplane) {
- *r_viewplane = params.viewplane;
- }
- if (r_clip_start) {
- *r_clip_start = params.clip_start;
- }
- if (r_clip_end) {
- *r_clip_end = params.clip_end;
- }
- if (r_pixsize) {
- *r_pixsize = params.viewdx;
- }
-
- return params.is_ortho;
+ CameraParams params;
+
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
+ BKE_camera_params_compute_viewplane(&params, winx, winy, 1.0f, 1.0f);
+
+ if (r_viewplane) {
+ *r_viewplane = params.viewplane;
+ }
+ if (r_clip_start) {
+ *r_clip_start = params.clip_start;
+ }
+ if (r_clip_end) {
+ *r_clip_end = params.clip_end;
+ }
+ if (r_pixsize) {
+ *r_pixsize = params.viewdx;
+ }
+
+ return params.is_ortho;
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name View State/Context Utilities
*
@@ -192,25 +195,25 @@ bool ED_view3d_viewplane_get(
*/
void view3d_operator_needs_opengl(const bContext *C)
{
- wmWindow *win = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
+ wmWindow *win = CTX_wm_window(C);
+ ARegion *ar = CTX_wm_region(C);
- view3d_region_operator_needs_opengl(win, ar);
+ view3d_region_operator_needs_opengl(win, ar);
}
void view3d_region_operator_needs_opengl(wmWindow *UNUSED(win), ARegion *ar)
{
- /* for debugging purpose, context should always be OK */
- if ((ar == NULL) || (ar->regiontype != RGN_TYPE_WINDOW)) {
- printf("view3d_region_operator_needs_opengl error, wrong region\n");
- }
- else {
- RegionView3D *rv3d = ar->regiondata;
-
- wmViewport(&ar->winrct); // TODO: bad
- GPU_matrix_projection_set(rv3d->winmat);
- GPU_matrix_set(rv3d->viewmat);
- }
+ /* for debugging purpose, context should always be OK */
+ if ((ar == NULL) || (ar->regiontype != RGN_TYPE_WINDOW)) {
+ printf("view3d_region_operator_needs_opengl error, wrong region\n");
+ }
+ else {
+ RegionView3D *rv3d = ar->regiondata;
+
+ wmViewport(&ar->winrct); // TODO: bad
+ GPU_matrix_projection_set(rv3d->winmat);
+ GPU_matrix_set(rv3d->viewmat);
+ }
}
/**
@@ -218,51 +221,51 @@ void view3d_region_operator_needs_opengl(wmWindow *UNUSED(win), ARegion *ar)
*/
void ED_view3d_polygon_offset(const RegionView3D *rv3d, const float dist)
{
- float viewdist;
+ float viewdist;
- if (rv3d->rflag & RV3D_ZOFFSET_DISABLED) {
- return;
- }
+ if (rv3d->rflag & RV3D_ZOFFSET_DISABLED) {
+ return;
+ }
- viewdist = rv3d->dist;
+ viewdist = rv3d->dist;
- /* special exception for ortho camera (viewdist isnt used for perspective cameras) */
- if (dist != 0.0f) {
- if (rv3d->persp == RV3D_CAMOB) {
- if (rv3d->is_persp == false) {
- viewdist = 1.0f / max_ff(fabsf(rv3d->winmat[0][0]), fabsf(rv3d->winmat[1][1]));
- }
- }
- }
+ /* special exception for ortho camera (viewdist isnt used for perspective cameras) */
+ if (dist != 0.0f) {
+ if (rv3d->persp == RV3D_CAMOB) {
+ if (rv3d->is_persp == false) {
+ viewdist = 1.0f / max_ff(fabsf(rv3d->winmat[0][0]), fabsf(rv3d->winmat[1][1]));
+ }
+ }
+ }
- bglPolygonOffset(viewdist, dist);
+ bglPolygonOffset(viewdist, dist);
}
bool ED_view3d_context_activate(bContext *C)
{
- bScreen *sc = CTX_wm_screen(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar;
+ bScreen *sc = CTX_wm_screen(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar;
- /* 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);
- }
+ /* 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);
+ }
- if (sa == NULL) {
- return false;
- }
+ if (sa == NULL) {
+ return false;
+ }
- ar = BKE_area_find_region_active_win(sa);
- if (ar == NULL) {
- return false;
- }
+ ar = BKE_area_find_region_active_win(sa);
+ if (ar == NULL) {
+ return false;
+ }
- /* bad context switch .. */
- CTX_wm_area_set(C, sa);
- CTX_wm_region_set(C, ar);
+ /* bad context switch .. */
+ CTX_wm_area_set(C, sa);
+ CTX_wm_region_set(C, ar);
- return true;
+ return true;
}
/** \} */
@@ -272,51 +275,54 @@ bool ED_view3d_context_activate(bContext *C)
*
* \{ */
-void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb, const bool is_flip)
+void ED_view3d_clipping_calc_from_boundbox(float clip[4][4],
+ const BoundBox *bb,
+ const bool is_flip)
{
- int val;
+ int val;
- for (val = 0; val < 4; val++) {
- normal_tri_v3(clip[val], bb->vec[val], bb->vec[val == 3 ? 0 : val + 1], bb->vec[val + 4]);
- if (UNLIKELY(is_flip)) {
- negate_v3(clip[val]);
- }
+ for (val = 0; val < 4; val++) {
+ normal_tri_v3(clip[val], bb->vec[val], bb->vec[val == 3 ? 0 : val + 1], bb->vec[val + 4]);
+ if (UNLIKELY(is_flip)) {
+ negate_v3(clip[val]);
+ }
- clip[val][3] = -dot_v3v3(clip[val], bb->vec[val]);
- }
+ clip[val][3] = -dot_v3v3(clip[val], bb->vec[val]);
+ }
}
-void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], const ARegion *ar, const Object *ob, const rcti *rect)
+void ED_view3d_clipping_calc(
+ BoundBox *bb, float planes[4][4], const ARegion *ar, const Object *ob, const rcti *rect)
{
- /* init in case unproject fails */
- memset(bb->vec, 0, sizeof(bb->vec));
-
- /* four clipping planes and bounding volume */
- /* first do the bounding volume */
- for (int val = 0; val < 4; val++) {
- 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]);
- }
-
- /* optionally transform to object space */
- if (ob) {
- float imat[4][4];
- invert_m4_m4(imat, ob->obmat);
-
- for (int val = 0; val < 8; val++) {
- mul_m4_v3(imat, bb->vec[val]);
- }
- }
-
- /* verify if we have negative scale. doing the transform before cross
- * product flips the sign of the vector compared to doing cross product
- * before transform then, so we correct for that. */
- int flip_sign = (ob) ? is_negative_m4(ob->obmat) : false;
-
- ED_view3d_clipping_calc_from_boundbox(planes, bb, flip_sign);
+ /* init in case unproject fails */
+ memset(bb->vec, 0, sizeof(bb->vec));
+
+ /* four clipping planes and bounding volume */
+ /* first do the bounding volume */
+ for (int val = 0; val < 4; val++) {
+ 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]);
+ }
+
+ /* optionally transform to object space */
+ if (ob) {
+ float imat[4][4];
+ invert_m4_m4(imat, ob->obmat);
+
+ for (int val = 0; val < 8; val++) {
+ mul_m4_v3(imat, bb->vec[val]);
+ }
+ }
+
+ /* verify if we have negative scale. doing the transform before cross
+ * product flips the sign of the vector compared to doing cross product
+ * before transform then, so we correct for that. */
+ int flip_sign = (ob) ? is_negative_m4(ob->obmat) : false;
+
+ ED_view3d_clipping_calc_from_boundbox(planes, bb, flip_sign);
}
/** \} */
@@ -328,73 +334,73 @@ void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], const ARegion *ar
static bool view3d_boundbox_clip_m4(const BoundBox *bb, float persmatob[4][4])
{
- int a, flag = -1, fl;
-
- for (a = 0; a < 8; a++) {
- float vec[4], min, max;
- copy_v3_v3(vec, bb->vec[a]);
- vec[3] = 1.0;
- mul_m4_v4(persmatob, vec);
- max = vec[3];
- min = -vec[3];
-
- fl = 0;
- if (vec[0] < min) {
- fl += 1;
- }
- if (vec[0] > max) {
- fl += 2;
- }
- if (vec[1] < min) {
- fl += 4;
- }
- if (vec[1] > max) {
- fl += 8;
- }
- if (vec[2] < min) {
- fl += 16;
- }
- if (vec[2] > max) {
- fl += 32;
- }
-
- flag &= fl;
- if (flag == 0) {
- return true;
- }
- }
-
- return false;
+ int a, flag = -1, fl;
+
+ for (a = 0; a < 8; a++) {
+ float vec[4], min, max;
+ copy_v3_v3(vec, bb->vec[a]);
+ vec[3] = 1.0;
+ mul_m4_v4(persmatob, vec);
+ max = vec[3];
+ min = -vec[3];
+
+ fl = 0;
+ if (vec[0] < min) {
+ fl += 1;
+ }
+ if (vec[0] > max) {
+ fl += 2;
+ }
+ if (vec[1] < min) {
+ fl += 4;
+ }
+ if (vec[1] > max) {
+ fl += 8;
+ }
+ if (vec[2] < min) {
+ fl += 16;
+ }
+ if (vec[2] > max) {
+ fl += 32;
+ }
+
+ flag &= fl;
+ if (flag == 0) {
+ return true;
+ }
+ }
+
+ return false;
}
bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const BoundBox *bb, float obmat[4][4])
{
- /* return 1: draw */
+ /* return 1: draw */
- float persmatob[4][4];
+ float persmatob[4][4];
- if (bb == NULL) {
- return true;
- }
- if (bb->flag & BOUNDBOX_DISABLED) {
- return true;
- }
+ if (bb == NULL) {
+ return true;
+ }
+ if (bb->flag & BOUNDBOX_DISABLED) {
+ return true;
+ }
- mul_m4_m4m4(persmatob, (float(*)[4])rv3d->persmat, obmat);
+ mul_m4_m4m4(persmatob, (float(*)[4])rv3d->persmat, obmat);
- return view3d_boundbox_clip_m4(bb, persmatob);
+ return view3d_boundbox_clip_m4(bb, persmatob);
}
bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const BoundBox *bb)
{
- if (bb == NULL) {
- return true;
- }
- if (bb->flag & BOUNDBOX_DISABLED) {
- return true;
- }
-
- return view3d_boundbox_clip_m4(bb, rv3d->persmatob);
+ if (bb == NULL) {
+ return true;
+ }
+ if (bb->flag & BOUNDBOX_DISABLED) {
+ return true;
+ }
+
+ return view3d_boundbox_clip_m4(bb, rv3d->persmatob);
}
/** \} */
@@ -405,9 +411,9 @@ bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const BoundBox *bb)
* Misc view utility functions.
* \{ */
-bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d)
+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_centre_cursor || v3d->ob_centre);
}
/**
@@ -415,19 +421,19 @@ bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d)
*/
void ED_view3d_lastview_store(RegionView3D *rv3d)
{
- copy_qt_qt(rv3d->lviewquat, rv3d->viewquat);
- rv3d->lview = rv3d->view;
- if (rv3d->persp != RV3D_CAMOB) {
- rv3d->lpersp = rv3d->persp;
- }
+ copy_qt_qt(rv3d->lviewquat, rv3d->viewquat);
+ rv3d->lview = rv3d->view;
+ if (rv3d->persp != RV3D_CAMOB) {
+ rv3d->lpersp = rv3d->persp;
+ }
}
void ED_view3d_lock_clear(View3D *v3d)
{
- v3d->ob_centre = NULL;
- v3d->ob_centre_bone[0] = '\0';
- v3d->ob_centre_cursor = false;
- v3d->flag2 &= ~V3D_LOCK_CAMERA;
+ v3d->ob_centre = NULL;
+ v3d->ob_centre_bone[0] = '\0';
+ v3d->ob_centre_cursor = false;
+ v3d->flag2 &= ~V3D_LOCK_CAMERA;
}
/**
@@ -437,20 +443,23 @@ void ED_view3d_lock_clear(View3D *v3d)
* sets the ``ofs`` and ``dist`` values of the viewport so it matches the camera,
* otherwise switching out of camera view may jump to a different part of the scene.
*/
-void ED_view3d_persp_switch_from_camera(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d, const char persp)
+void ED_view3d_persp_switch_from_camera(const Depsgraph *depsgraph,
+ View3D *v3d,
+ RegionView3D *rv3d,
+ const char persp)
{
- BLI_assert(rv3d->persp == RV3D_CAMOB);
- BLI_assert(persp != RV3D_CAMOB);
-
- if (v3d->camera) {
- Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
- rv3d->dist = ED_view3d_offset_distance(ob_camera_eval->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
- ED_view3d_from_object(ob_camera_eval, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
- }
-
- if (!ED_view3d_camera_lock_check(v3d, rv3d)) {
- rv3d->persp = persp;
- }
+ BLI_assert(rv3d->persp == RV3D_CAMOB);
+ BLI_assert(persp != RV3D_CAMOB);
+
+ if (v3d->camera) {
+ Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
+ rv3d->dist = ED_view3d_offset_distance(ob_camera_eval->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
+ ED_view3d_from_object(ob_camera_eval, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
+ }
+
+ if (!ED_view3d_camera_lock_check(v3d, rv3d)) {
+ rv3d->persp = persp;
+ }
}
/**
* Action to take when rotating the view,
@@ -460,29 +469,29 @@ void ED_view3d_persp_switch_from_camera(const Depsgraph *depsgraph, View3D *v3d,
*/
bool ED_view3d_persp_ensure(const Depsgraph *depsgraph, View3D *v3d, ARegion *ar)
{
- RegionView3D *rv3d = ar->regiondata;
- const bool autopersp = (U.uiflag & USER_AUTOPERSP) != 0;
-
- BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
-
- if (ED_view3d_camera_lock_check(v3d, rv3d)) {
- return false;
- }
-
- if (rv3d->persp != RV3D_PERSP) {
- if (rv3d->persp == RV3D_CAMOB) {
- /* If autopersp and previous view was an axis one,
- * switch back to PERSP mode, else reuse previous mode. */
- char persp = (autopersp && RV3D_VIEW_IS_AXIS(rv3d->lview)) ? RV3D_PERSP : rv3d->lpersp;
- ED_view3d_persp_switch_from_camera(depsgraph, v3d, rv3d, persp);
- }
- else if (autopersp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
- rv3d->persp = RV3D_PERSP;
- }
- return true;
- }
-
- return false;
+ RegionView3D *rv3d = ar->regiondata;
+ const bool autopersp = (U.uiflag & USER_AUTOPERSP) != 0;
+
+ BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
+
+ if (ED_view3d_camera_lock_check(v3d, rv3d)) {
+ return false;
+ }
+
+ if (rv3d->persp != RV3D_PERSP) {
+ if (rv3d->persp == RV3D_CAMOB) {
+ /* If autopersp and previous view was an axis one,
+ * switch back to PERSP mode, else reuse previous mode. */
+ char persp = (autopersp && RV3D_VIEW_IS_AXIS(rv3d->lview)) ? RV3D_PERSP : rv3d->lpersp;
+ ED_view3d_persp_switch_from_camera(depsgraph, v3d, rv3d, persp);
+ }
+ else if (autopersp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
+ rv3d->persp = RV3D_PERSP;
+ }
+ return true;
+ }
+
+ return false;
}
/** \} */
@@ -498,31 +507,33 @@ bool ED_view3d_persp_ensure(const Depsgraph *depsgraph, View3D *v3d, ARegion *ar
*/
bool ED_view3d_camera_lock_check(const View3D *v3d, const RegionView3D *rv3d)
{
- return ((v3d->camera) &&
- (!ID_IS_LINKED(v3d->camera)) &&
- (v3d->flag2 & V3D_LOCK_CAMERA) &&
- (rv3d->persp == RV3D_CAMOB));
+ return ((v3d->camera) && (!ID_IS_LINKED(v3d->camera)) && (v3d->flag2 & V3D_LOCK_CAMERA) &&
+ (rv3d->persp == RV3D_CAMOB));
}
/**
* Apply the camera object transformation to the view-port.
* (needed so we can use regular view-port manipulation operators, that sync back to the camera).
*/
-void ED_view3d_camera_lock_init_ex(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d, const bool calc_dist)
+void ED_view3d_camera_lock_init_ex(const Depsgraph *depsgraph,
+ View3D *v3d,
+ RegionView3D *rv3d,
+ const bool calc_dist)
{
- if (ED_view3d_camera_lock_check(v3d, rv3d)) {
- Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
- if (calc_dist) {
- /* using a fallback dist is OK here since ED_view3d_from_object() compensates for it */
- rv3d->dist = ED_view3d_offset_distance(ob_camera_eval->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
- }
- ED_view3d_from_object(ob_camera_eval, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
- }
+ if (ED_view3d_camera_lock_check(v3d, rv3d)) {
+ Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
+ if (calc_dist) {
+ /* using a fallback dist is OK here since ED_view3d_from_object() compensates for it */
+ rv3d->dist = ED_view3d_offset_distance(
+ ob_camera_eval->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
+ }
+ ED_view3d_from_object(ob_camera_eval, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
+ }
}
void ED_view3d_camera_lock_init(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d)
{
- ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, true);
+ ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, true);
}
/**
@@ -532,95 +543,95 @@ void ED_view3d_camera_lock_init(const Depsgraph *depsgraph, View3D *v3d, RegionV
*/
bool ED_view3d_camera_lock_sync(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d)
{
- if (ED_view3d_camera_lock_check(v3d, rv3d)) {
- ObjectTfmProtectedChannels obtfm;
- Object *root_parent;
-
- if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (root_parent = v3d->camera->parent)) {
- Object *ob_update;
- float tmat[4][4];
- float imat[4][4];
- float view_mat[4][4];
- float diff_mat[4][4];
- float parent_mat[4][4];
-
- while (root_parent->parent) {
- root_parent = root_parent->parent;
- }
- Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
- Object *root_parent_eval = DEG_get_evaluated_object(depsgraph, root_parent);
-
- ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
-
- normalize_m4_m4(tmat, ob_camera_eval->obmat);
-
- invert_m4_m4(imat, tmat);
- mul_m4_m4m4(diff_mat, view_mat, imat);
-
- mul_m4_m4m4(parent_mat, diff_mat, root_parent_eval->obmat);
-
- BKE_object_tfm_protected_backup(root_parent, &obtfm);
- BKE_object_apply_mat4(root_parent, parent_mat, true, false);
- BKE_object_tfm_protected_restore(root_parent, &obtfm, root_parent->protectflag);
-
- ob_update = v3d->camera;
- while (ob_update) {
- DEG_id_tag_update(&ob_update->id, ID_RECALC_TRANSFORM);
- WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, ob_update);
- ob_update = ob_update->parent;
- }
- }
- else {
- /* always maintain the same scale */
- const short protect_scale_all = (OB_LOCK_SCALEX | OB_LOCK_SCALEY | OB_LOCK_SCALEZ);
- BKE_object_tfm_protected_backup(v3d->camera, &obtfm);
- ED_view3d_to_object(depsgraph, v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
- BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag | protect_scale_all);
-
- DEG_id_tag_update(&v3d->camera->id, ID_RECALC_TRANSFORM);
- WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, v3d->camera);
- }
-
- return true;
- }
- else {
- return false;
- }
+ if (ED_view3d_camera_lock_check(v3d, rv3d)) {
+ ObjectTfmProtectedChannels obtfm;
+ Object *root_parent;
+
+ if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (root_parent = v3d->camera->parent)) {
+ Object *ob_update;
+ float tmat[4][4];
+ float imat[4][4];
+ float view_mat[4][4];
+ float diff_mat[4][4];
+ float parent_mat[4][4];
+
+ while (root_parent->parent) {
+ root_parent = root_parent->parent;
+ }
+ Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
+ Object *root_parent_eval = DEG_get_evaluated_object(depsgraph, root_parent);
+
+ ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+
+ normalize_m4_m4(tmat, ob_camera_eval->obmat);
+
+ invert_m4_m4(imat, tmat);
+ mul_m4_m4m4(diff_mat, view_mat, imat);
+
+ mul_m4_m4m4(parent_mat, diff_mat, root_parent_eval->obmat);
+
+ BKE_object_tfm_protected_backup(root_parent, &obtfm);
+ BKE_object_apply_mat4(root_parent, parent_mat, true, false);
+ BKE_object_tfm_protected_restore(root_parent, &obtfm, root_parent->protectflag);
+
+ ob_update = v3d->camera;
+ while (ob_update) {
+ DEG_id_tag_update(&ob_update->id, ID_RECALC_TRANSFORM);
+ WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, ob_update);
+ ob_update = ob_update->parent;
+ }
+ }
+ else {
+ /* always maintain the same scale */
+ const short protect_scale_all = (OB_LOCK_SCALEX | OB_LOCK_SCALEY | OB_LOCK_SCALEZ);
+ BKE_object_tfm_protected_backup(v3d->camera, &obtfm);
+ ED_view3d_to_object(depsgraph, v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+ BKE_object_tfm_protected_restore(
+ v3d->camera, &obtfm, v3d->camera->protectflag | protect_scale_all);
+
+ DEG_id_tag_update(&v3d->camera->id, ID_RECALC_TRANSFORM);
+ WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, v3d->camera);
+ }
+
+ return true;
+ }
+ else {
+ return false;
+ }
}
bool ED_view3d_camera_autokey(
- Scene *scene, ID *id_key,
- struct bContext *C, const bool do_rotate, const bool do_translate)
+ 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;
- ListBase dsources = {NULL, NULL};
-
- /* add data-source override for the camera object */
- ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL);
-
- /* insert keyframes
- * 1) on the first frame
- * 2) on each subsequent frame
- * TODO: need to check in future that frame changed before doing this
- */
- if (do_rotate) {
- struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_ROTATION_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
- }
- if (do_translate) {
- struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
- }
-
- /* free temp data */
- BLI_freelistN(&dsources);
-
- return true;
- }
- else {
- return false;
- }
+ if (autokeyframe_cfra_can_key(scene, id_key)) {
+ const float cfra = (float)CFRA;
+ ListBase dsources = {NULL, NULL};
+
+ /* add data-source override for the camera object */
+ ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL);
+
+ /* insert keyframes
+ * 1) on the first frame
+ * 2) on each subsequent frame
+ * TODO: need to check in future that frame changed before doing this
+ */
+ if (do_rotate) {
+ struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_ROTATION_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+ if (do_translate) {
+ struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+
+ /* free temp data */
+ BLI_freelistN(&dsources);
+
+ return true;
+ }
+ else {
+ return false;
+ }
}
/**
@@ -629,36 +640,36 @@ bool ED_view3d_camera_autokey(
* \note Not every view edit currently auto-keys (numpad for eg),
* this is complicated because of smoothview.
*/
-bool ED_view3d_camera_lock_autokey(
- View3D *v3d, RegionView3D *rv3d,
- struct bContext *C, const bool do_rotate, const bool do_translate)
+bool ED_view3d_camera_lock_autokey(View3D *v3d,
+ RegionView3D *rv3d,
+ struct bContext *C,
+ const bool do_rotate,
+ const bool do_translate)
{
- /* similar to ED_view3d_cameracontrol_update */
- if (ED_view3d_camera_lock_check(v3d, rv3d)) {
- Scene *scene = CTX_data_scene(C);
- ID *id_key;
- Object *root_parent;
- if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (root_parent = v3d->camera->parent)) {
- while (root_parent->parent) {
- root_parent = root_parent->parent;
- }
- id_key = &root_parent->id;
- }
- else {
- id_key = &v3d->camera->id;
- }
-
- return ED_view3d_camera_autokey(scene, id_key, C, do_rotate, do_translate);
- }
- else {
- return false;
- }
+ /* similar to ED_view3d_cameracontrol_update */
+ if (ED_view3d_camera_lock_check(v3d, rv3d)) {
+ Scene *scene = CTX_data_scene(C);
+ ID *id_key;
+ Object *root_parent;
+ if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (root_parent = v3d->camera->parent)) {
+ while (root_parent->parent) {
+ root_parent = root_parent->parent;
+ }
+ id_key = &root_parent->id;
+ }
+ else {
+ id_key = &v3d->camera->id;
+ }
+
+ return ED_view3d_camera_autokey(scene, id_key, C, do_rotate, do_translate);
+ }
+ else {
+ return false;
+ }
}
/** \} */
-
-
/* -------------------------------------------------------------------- */
/** \name Box View Support
*
@@ -667,100 +678,100 @@ bool ED_view3d_camera_lock_autokey(
static void view3d_boxview_clip(ScrArea *sa)
{
- ARegion *ar;
- 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;
-
- if (rv3d->viewlock & RV3D_BOXCLIP) {
- if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
- if (ar->winx > ar->winy) {
- x1 = rv3d->dist;
- }
- else {
- x1 = ar->winx * rv3d->dist / ar->winy;
- }
-
- if (ar->winx > ar->winy) {
- y1 = ar->winy * rv3d->dist / ar->winx;
- }
- else {
- y1 = rv3d->dist;
- }
- copy_v2_v2(ofs, rv3d->ofs);
- }
- 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;
- }
- else {
- z1 = rv3d->dist;
- }
- }
- }
- }
- }
-
- for (val = 0; val < 8; val++) {
- if (ELEM(val, 0, 3, 4, 7)) {
- bb->vec[val][0] = -x1 - ofs[0];
- }
- else {
- bb->vec[val][0] = x1 - ofs[0];
- }
-
- if (ELEM(val, 0, 1, 4, 5)) {
- bb->vec[val][1] = -y1 - ofs[1];
- }
- else {
- bb->vec[val][1] = y1 - ofs[1];
- }
-
- if (val > 3) {
- bb->vec[val][2] = -z1 - ofs[2];
- }
- else {
- bb->vec[val][2] = z1 - ofs[2];
- }
- }
-
- /* normals for plane equations */
- normal_tri_v3(clip[0], bb->vec[0], bb->vec[1], bb->vec[4]);
- normal_tri_v3(clip[1], bb->vec[1], bb->vec[2], bb->vec[5]);
- normal_tri_v3(clip[2], bb->vec[2], bb->vec[3], bb->vec[6]);
- normal_tri_v3(clip[3], bb->vec[3], bb->vec[0], bb->vec[7]);
- normal_tri_v3(clip[4], bb->vec[4], bb->vec[5], bb->vec[6]);
- normal_tri_v3(clip[5], bb->vec[0], bb->vec[2], bb->vec[1]);
-
- /* then plane equations */
- for (val = 0; val < 6; val++) {
- clip[val][3] = -dot_v3v3(clip[val], bb->vec[val % 5]);
- }
-
- /* create bounding box */
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = ar->regiondata;
-
- if (rv3d->viewlock & RV3D_BOXCLIP) {
- rv3d->rflag |= RV3D_CLIPPING;
- memcpy(rv3d->clip, clip, sizeof(clip));
- if (rv3d->clipbb) {
- MEM_freeN(rv3d->clipbb);
- }
- rv3d->clipbb = MEM_dupallocN(bb);
- }
- }
- }
- MEM_freeN(bb);
+ ARegion *ar;
+ 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;
+
+ if (rv3d->viewlock & RV3D_BOXCLIP) {
+ if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
+ if (ar->winx > ar->winy) {
+ x1 = rv3d->dist;
+ }
+ else {
+ x1 = ar->winx * rv3d->dist / ar->winy;
+ }
+
+ if (ar->winx > ar->winy) {
+ y1 = ar->winy * rv3d->dist / ar->winx;
+ }
+ else {
+ y1 = rv3d->dist;
+ }
+ copy_v2_v2(ofs, rv3d->ofs);
+ }
+ 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;
+ }
+ else {
+ z1 = rv3d->dist;
+ }
+ }
+ }
+ }
+ }
+
+ for (val = 0; val < 8; val++) {
+ if (ELEM(val, 0, 3, 4, 7)) {
+ bb->vec[val][0] = -x1 - ofs[0];
+ }
+ else {
+ bb->vec[val][0] = x1 - ofs[0];
+ }
+
+ if (ELEM(val, 0, 1, 4, 5)) {
+ bb->vec[val][1] = -y1 - ofs[1];
+ }
+ else {
+ bb->vec[val][1] = y1 - ofs[1];
+ }
+
+ if (val > 3) {
+ bb->vec[val][2] = -z1 - ofs[2];
+ }
+ else {
+ bb->vec[val][2] = z1 - ofs[2];
+ }
+ }
+
+ /* normals for plane equations */
+ normal_tri_v3(clip[0], bb->vec[0], bb->vec[1], bb->vec[4]);
+ normal_tri_v3(clip[1], bb->vec[1], bb->vec[2], bb->vec[5]);
+ normal_tri_v3(clip[2], bb->vec[2], bb->vec[3], bb->vec[6]);
+ normal_tri_v3(clip[3], bb->vec[3], bb->vec[0], bb->vec[7]);
+ normal_tri_v3(clip[4], bb->vec[4], bb->vec[5], bb->vec[6]);
+ normal_tri_v3(clip[5], bb->vec[0], bb->vec[2], bb->vec[1]);
+
+ /* then plane equations */
+ for (val = 0; val < 6; val++) {
+ clip[val][3] = -dot_v3v3(clip[val], bb->vec[val % 5]);
+ }
+
+ /* create bounding box */
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = ar->regiondata;
+
+ if (rv3d->viewlock & RV3D_BOXCLIP) {
+ rv3d->rflag |= RV3D_CLIPPING;
+ memcpy(rv3d->clip, clip, sizeof(clip));
+ if (rv3d->clipbb) {
+ MEM_freeN(rv3d->clipbb);
+ }
+ rv3d->clipbb = MEM_dupallocN(bb);
+ }
+ }
+ }
+ MEM_freeN(bb);
}
/**
@@ -769,161 +780,156 @@ static void view3d_boxview_clip(ScrArea *sa)
*/
static void view3d_boxview_sync_axis(RegionView3D *rv3d_dst, RegionView3D *rv3d_src)
{
- /* absolute axis values above this are considered to be set (will be ~1.0f) */
- const float axis_eps = 0.5f;
- float viewinv[4];
-
- /* use the view rotation to identify which axis to sync on */
- float view_axis_all[4][3] = {
- {1.0f, 0.0f, 0.0f},
- {0.0f, 1.0f, 0.0f},
- {1.0f, 0.0f, 0.0f},
- {0.0f, 1.0f, 0.0f}};
-
- float *view_src_x = &view_axis_all[0][0];
- float *view_src_y = &view_axis_all[1][0];
-
- float *view_dst_x = &view_axis_all[2][0];
- float *view_dst_y = &view_axis_all[3][0];
- 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)) {
- 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)) {
- return;
- }
- invert_qt_normalized(viewinv);
- mul_qt_v3(viewinv, view_dst_x);
- mul_qt_v3(viewinv, view_dst_y);
-
- /* check source and dest have a matching axis */
- for (i = 0; i < 3; i++) {
- if (((fabsf(view_src_x[i]) > axis_eps) || (fabsf(view_src_y[i]) > axis_eps)) &&
- ((fabsf(view_dst_x[i]) > axis_eps) || (fabsf(view_dst_y[i]) > axis_eps)))
- {
- rv3d_dst->ofs[i] = rv3d_src->ofs[i];
- }
- }
+ /* absolute axis values above this are considered to be set (will be ~1.0f) */
+ const float axis_eps = 0.5f;
+ float viewinv[4];
+
+ /* use the view rotation to identify which axis to sync on */
+ float view_axis_all[4][3] = {
+ {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}};
+
+ float *view_src_x = &view_axis_all[0][0];
+ float *view_src_y = &view_axis_all[1][0];
+
+ float *view_dst_x = &view_axis_all[2][0];
+ float *view_dst_y = &view_axis_all[3][0];
+ 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)) {
+ 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)) {
+ return;
+ }
+ invert_qt_normalized(viewinv);
+ mul_qt_v3(viewinv, view_dst_x);
+ mul_qt_v3(viewinv, view_dst_y);
+
+ /* check source and dest have a matching axis */
+ for (i = 0; i < 3; i++) {
+ if (((fabsf(view_src_x[i]) > axis_eps) || (fabsf(view_src_y[i]) > axis_eps)) &&
+ ((fabsf(view_dst_x[i]) > axis_eps) || (fabsf(view_dst_y[i]) > axis_eps))) {
+ rv3d_dst->ofs[i] = rv3d_src->ofs[i];
+ }
+ }
}
/* sync center/zoom view of region to others, for view transforms */
void view3d_boxview_sync(ScrArea *sa, ARegion *ar)
{
- ARegion *artest;
- RegionView3D *rv3d = ar->regiondata;
- short clip = 0;
-
- for (artest = sa->regionbase.first; artest; artest = artest->next) {
- if (artest != ar && artest->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3dtest = artest->regiondata;
-
- if (rv3dtest->viewlock & RV3D_LOCKED) {
- rv3dtest->dist = rv3d->dist;
- view3d_boxview_sync_axis(rv3dtest, rv3d);
- clip |= rv3dtest->viewlock & RV3D_BOXCLIP;
-
- ED_region_tag_redraw(artest);
- }
- }
- }
-
- if (clip) {
- view3d_boxview_clip(sa);
- }
+ ARegion *artest;
+ RegionView3D *rv3d = ar->regiondata;
+ short clip = 0;
+
+ for (artest = sa->regionbase.first; artest; artest = artest->next) {
+ if (artest != ar && artest->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3dtest = artest->regiondata;
+
+ if (rv3dtest->viewlock & RV3D_LOCKED) {
+ rv3dtest->dist = rv3d->dist;
+ view3d_boxview_sync_axis(rv3dtest, rv3d);
+ clip |= rv3dtest->viewlock & RV3D_BOXCLIP;
+
+ ED_region_tag_redraw(artest);
+ }
+ }
+ }
+
+ if (clip) {
+ view3d_boxview_clip(sa);
+ }
}
/* for home, center etc */
void view3d_boxview_copy(ScrArea *sa, ARegion *ar)
{
- ARegion *artest;
- RegionView3D *rv3d = ar->regiondata;
- bool clip = false;
-
- for (artest = sa->regionbase.first; artest; artest = artest->next) {
- if (artest != ar && artest->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3dtest = artest->regiondata;
-
- if (rv3dtest->viewlock) {
- rv3dtest->dist = rv3d->dist;
- copy_v3_v3(rv3dtest->ofs, rv3d->ofs);
- ED_region_tag_redraw(artest);
-
- clip |= ((rv3dtest->viewlock & RV3D_BOXCLIP) != 0);
- }
- }
- }
-
- if (clip) {
- view3d_boxview_clip(sa);
- }
+ ARegion *artest;
+ RegionView3D *rv3d = ar->regiondata;
+ bool clip = false;
+
+ for (artest = sa->regionbase.first; artest; artest = artest->next) {
+ if (artest != ar && artest->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3dtest = artest->regiondata;
+
+ if (rv3dtest->viewlock) {
+ rv3dtest->dist = rv3d->dist;
+ copy_v3_v3(rv3dtest->ofs, rv3d->ofs);
+ ED_region_tag_redraw(artest);
+
+ clip |= ((rv3dtest->viewlock & RV3D_BOXCLIP) != 0);
+ }
+ }
+ }
+
+ if (clip) {
+ view3d_boxview_clip(sa);
+ }
}
/* 'clip' is used to know if our clip setting has changed */
void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip)
{
- ARegion *ar_sync = NULL;
- RegionView3D *rv3d = ar->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) {
- do_clip = (viewlock & RV3D_BOXCLIP) != 0;
- viewlock = 0;
- }
- else if ((viewlock & RV3D_BOXVIEW) == 0 && (viewlock & RV3D_BOXCLIP) != 0) {
- do_clip = true;
- viewlock &= ~RV3D_BOXCLIP;
- }
-
- for (; ar; ar = ar->prev) {
- if (ar->alignment == RGN_ALIGN_QSPLIT) {
- rv3d = ar->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
- * else the view jumps on changing view settings like 'clip'
- * since it copies from the perspective view */
- ar_sync = ar;
- }
- }
-
- if (rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_sync(sa, ar_sync ? ar_sync : sa->regionbase.last);
- }
-
- /* ensure locked regions have an axis, locked user views don't make much sense */
- if (viewlock & RV3D_LOCKED) {
- int index_qsplit = 0;
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->alignment == RGN_ALIGN_QSPLIT) {
- rv3d = ar->regiondata;
- if (rv3d->viewlock) {
- if (!RV3D_VIEW_IS_AXIS(rv3d->view)) {
- rv3d->view = ED_view3d_lock_view_from_index(index_qsplit);
- rv3d->persp = RV3D_ORTHO;
- ED_view3d_lock(rv3d);
- }
- }
- index_qsplit++;
- }
- }
- }
-
- ED_area_tag_redraw(sa);
+ ARegion *ar_sync = NULL;
+ RegionView3D *rv3d = ar->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) {
+ do_clip = (viewlock & RV3D_BOXCLIP) != 0;
+ viewlock = 0;
+ }
+ else if ((viewlock & RV3D_BOXVIEW) == 0 && (viewlock & RV3D_BOXCLIP) != 0) {
+ do_clip = true;
+ viewlock &= ~RV3D_BOXCLIP;
+ }
+
+ for (; ar; ar = ar->prev) {
+ if (ar->alignment == RGN_ALIGN_QSPLIT) {
+ rv3d = ar->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
+ * else the view jumps on changing view settings like 'clip'
+ * since it copies from the perspective view */
+ ar_sync = ar;
+ }
+ }
+
+ if (rv3d->viewlock & RV3D_BOXVIEW) {
+ view3d_boxview_sync(sa, ar_sync ? ar_sync : sa->regionbase.last);
+ }
+
+ /* ensure locked regions have an axis, locked user views don't make much sense */
+ if (viewlock & RV3D_LOCKED) {
+ int index_qsplit = 0;
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->alignment == RGN_ALIGN_QSPLIT) {
+ rv3d = ar->regiondata;
+ if (rv3d->viewlock) {
+ if (!RV3D_VIEW_IS_AXIS(rv3d->view)) {
+ rv3d->view = ED_view3d_lock_view_from_index(index_qsplit);
+ rv3d->persp = RV3D_ORTHO;
+ ED_view3d_lock(rv3d);
+ }
+ }
+ index_qsplit++;
+ }
+ }
+ }
+
+ ED_area_tag_redraw(sa);
}
/** \} */
@@ -934,25 +940,25 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip)
static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int margin)
{
- ViewDepths depth_temp = {0};
- rcti rect;
- float depth_close;
-
- if (margin == 0) {
- /* Get Z Depths, needed for perspective, nice for ortho */
- rect.xmin = mval[0];
- rect.ymin = mval[1];
- rect.xmax = mval[0] + 1;
- rect.ymax = mval[1] + 1;
- }
- else {
- BLI_rcti_init_pt_radius(&rect, mval, margin);
- }
-
- view3d_update_depths_rect(ar, &depth_temp, &rect);
- depth_close = view3d_depth_near(&depth_temp);
- MEM_SAFE_FREE(depth_temp.depths);
- return depth_close;
+ ViewDepths depth_temp = {0};
+ rcti rect;
+ float depth_close;
+
+ if (margin == 0) {
+ /* Get Z Depths, needed for perspective, nice for ortho */
+ rect.xmin = mval[0];
+ rect.ymin = mval[1];
+ rect.xmax = mval[0] + 1;
+ rect.ymax = mval[1] + 1;
+ }
+ else {
+ BLI_rcti_init_pt_radius(&rect, mval, margin);
+ }
+
+ view3d_update_depths_rect(ar, &depth_temp, &rect);
+ depth_close = view3d_depth_near(&depth_temp);
+ MEM_SAFE_FREE(depth_temp.depths);
+ return depth_close;
}
/**
@@ -962,131 +968,139 @@ static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int marg
* \param mouse_worldloc: Output world-space location.
* \param fallback_depth_pt: Use this points depth when no depth can be found.
*/
-bool ED_view3d_autodist(
- Depsgraph *depsgraph, ARegion *ar, View3D *v3d,
- const int mval[2], float mouse_worldloc[3],
- const bool alphaoverride, const float fallback_depth_pt[3])
+bool ED_view3d_autodist(Depsgraph *depsgraph,
+ ARegion *ar,
+ View3D *v3d,
+ const int mval[2],
+ float mouse_worldloc[3],
+ const bool alphaoverride,
+ const float fallback_depth_pt[3])
{
- float depth_close;
- int margin_arr[] = {0, 2, 4};
- int i;
- bool depth_ok = false;
-
- /* Get Z Depths, needed for perspective, nice for ortho */
- ED_view3d_draw_depth(depsgraph, ar, 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_ok = (depth_close != FLT_MAX);
- } while ((depth_ok == false) && (i < ARRAY_SIZE(margin_arr)));
-
- if (depth_ok) {
- 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)) {
- return true;
- }
- }
-
- if (fallback_depth_pt) {
- ED_view3d_win_to_3d_int(v3d, ar, fallback_depth_pt, mval, mouse_worldloc);
- return true;
- }
- else {
- return false;
- }
+ float depth_close;
+ int margin_arr[] = {0, 2, 4};
+ int i;
+ bool depth_ok = false;
+
+ /* Get Z Depths, needed for perspective, nice for ortho */
+ ED_view3d_draw_depth(depsgraph, ar, 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_ok = (depth_close != FLT_MAX);
+ } while ((depth_ok == false) && (i < ARRAY_SIZE(margin_arr)));
+
+ if (depth_ok) {
+ 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)) {
+ return true;
+ }
+ }
+
+ if (fallback_depth_pt) {
+ ED_view3d_win_to_3d_int(v3d, ar, fallback_depth_pt, mval, mouse_worldloc);
+ return true;
+ }
+ else {
+ return false;
+ }
}
-void ED_view3d_autodist_init(Depsgraph *depsgraph,
- ARegion *ar, View3D *v3d, int mode)
+void ED_view3d_autodist_init(Depsgraph *depsgraph, ARegion *ar, 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);
- break;
- case 1:
- {
- Scene *scene = DEG_get_evaluated_scene(depsgraph);
- ED_view3d_draw_depth_gpencil(depsgraph, scene, ar, v3d);
- break;
- }
- }
+ /* Get Z Depths, needed for perspective, nice for ortho */
+ switch (mode) {
+ case 0:
+ ED_view3d_draw_depth(depsgraph, ar, v3d, true);
+ break;
+ case 1: {
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ ED_view3d_draw_depth_gpencil(depsgraph, scene, ar, v3d);
+ break;
+ }
+ }
}
/* 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)
+bool ED_view3d_autodist_simple(
+ ARegion *ar, const int mval[2], float mouse_worldloc[3], int margin, float *force_depth)
{
- float depth;
-
- /* Get Z Depths, needed for perspective, nice for ortho */
- if (force_depth) {
- depth = *force_depth;
- }
- else {
- depth = view_autodist_depth_margin(ar, mval, margin);
- }
-
- if (depth == FLT_MAX) {
- return false;
- }
-
- float centx = (float)mval[0] + 0.5f;
- float centy = (float)mval[1] + 0.5f;
- return ED_view3d_unproject(ar, centx, centy, depth, mouse_worldloc);
+ float depth;
+
+ /* Get Z Depths, needed for perspective, nice for ortho */
+ if (force_depth) {
+ depth = *force_depth;
+ }
+ else {
+ depth = view_autodist_depth_margin(ar, mval, margin);
+ }
+
+ if (depth == FLT_MAX) {
+ return false;
+ }
+
+ float centx = (float)mval[0] + 0.5f;
+ float centy = (float)mval[1] + 0.5f;
+ return ED_view3d_unproject(ar, centx, centy, depth, mouse_worldloc);
}
bool ED_view3d_autodist_depth(ARegion *ar, const int mval[2], int margin, float *depth)
{
- *depth = view_autodist_depth_margin(ar, mval, margin);
+ *depth = view_autodist_depth_margin(ar, mval, margin);
- return (*depth != FLT_MAX);
+ return (*depth != FLT_MAX);
}
static bool depth_segment_cb(int x, int y, void *userData)
{
- struct { ARegion *ar; int margin; float depth; } *data = userData;
- int mval[2];
- float depth;
-
- mval[0] = x;
- mval[1] = y;
-
- depth = view_autodist_depth_margin(data->ar, mval, data->margin);
-
- if (depth != FLT_MAX) {
- data->depth = depth;
- return 0;
- }
- else {
- return 1;
- }
+ struct {
+ ARegion *ar;
+ int margin;
+ float depth;
+ } *data = userData;
+ int mval[2];
+ float depth;
+
+ mval[0] = x;
+ mval[1] = y;
+
+ depth = view_autodist_depth_margin(data->ar, mval, data->margin);
+
+ if (depth != FLT_MAX) {
+ data->depth = depth;
+ return 0;
+ }
+ else {
+ return 1;
+ }
}
bool ED_view3d_autodist_depth_seg(
- ARegion *ar, const int mval_sta[2], const int mval_end[2],
- int margin, float *depth)
+ ARegion *ar, const int mval_sta[2], const int mval_end[2], int margin, float *depth)
{
- struct { ARegion *ar; int margin; float depth; } data = {NULL};
- int p1[2];
- int p2[2];
+ struct {
+ ARegion *ar;
+ int margin;
+ float depth;
+ } data = {NULL};
+ int p1[2];
+ int p2[2];
- data.ar = ar;
- data.margin = margin;
- data.depth = FLT_MAX;
+ data.ar = ar;
+ data.margin = margin;
+ data.depth = FLT_MAX;
- copy_v2_v2_int(p1, mval_sta);
- copy_v2_v2_int(p2, mval_end);
+ copy_v2_v2_int(p1, mval_sta);
+ copy_v2_v2_int(p2, mval_end);
- BLI_bitmap_draw_2d_line_v2v2i(p1, p2, depth_segment_cb, &data);
+ BLI_bitmap_draw_2d_line_v2v2i(p1, p2, depth_segment_cb, &data);
- *depth = data.depth;
+ *depth = data.depth;
- return (*depth != FLT_MAX);
+ return (*depth != FLT_MAX);
}
/** \} */
@@ -1099,12 +1113,12 @@ bool ED_view3d_autodist_depth_seg(
float ED_view3d_radius_to_dist_persp(const float angle, const float radius)
{
- return radius * (1.0f / tanf(angle / 2.0f));
+ return radius * (1.0f / tanf(angle / 2.0f));
}
float ED_view3d_radius_to_dist_ortho(const float lens, const float radius)
{
- return radius / (DEFAULT_SENSOR_WIDTH / lens);
+ return radius / (DEFAULT_SENSOR_WIDTH / lens);
}
/**
@@ -1131,78 +1145,79 @@ float ED_view3d_radius_to_dist_ortho(const float lens, const float radius)
* \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 struct Depsgraph *depsgraph,
- const char persp, const bool use_aspect,
- const float radius)
+float ED_view3d_radius_to_dist(const View3D *v3d,
+ const ARegion *ar,
+ const struct Depsgraph *depsgraph,
+ const char persp,
+ const bool use_aspect,
+ const float radius)
{
- float dist;
-
- BLI_assert(ELEM(persp, RV3D_ORTHO, RV3D_PERSP, RV3D_CAMOB));
- BLI_assert((persp != RV3D_CAMOB) || v3d->camera);
-
- if (persp == RV3D_ORTHO) {
- dist = ED_view3d_radius_to_dist_ortho(v3d->lens, radius);
- }
- else {
- float lens, sensor_size, zoom;
- float angle;
-
- if (persp == RV3D_CAMOB) {
- CameraParams params;
- BKE_camera_params_init(&params);
- params.clip_start = v3d->clip_start;
- params.clip_end = v3d->clip_end;
- Object *camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
- BKE_camera_params_from_object(&params, camera_eval);
-
- lens = params.lens;
- sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y);
-
- /* ignore 'rv3d->camzoom' because we want to fit to the cameras frame */
- zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB;
- }
- else {
- lens = v3d->lens;
- sensor_size = DEFAULT_SENSOR_WIDTH;
- zoom = CAMERA_PARAM_ZOOM_INIT_PERSP;
- }
-
- angle = focallength_to_fov(lens, sensor_size);
-
- /* zoom influences lens, correct this by scaling the angle as a distance
- * (by the zoom-level) */
- angle = atanf(tanf(angle / 2.0f) * zoom) * 2.0f;
-
- dist = ED_view3d_radius_to_dist_persp(angle, radius);
- }
-
- if (use_aspect) {
- const RegionView3D *rv3d = ar->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];
- }
- else {
- winx = ar->winx;
- winy = ar->winy;
- }
-
- if (winx && winy) {
- float aspect = winx / winy;
- if (aspect < 1.0f) {
- aspect = 1.0f / aspect;
- }
- dist *= aspect;
- }
- }
-
- return dist;
+ float dist;
+
+ BLI_assert(ELEM(persp, RV3D_ORTHO, RV3D_PERSP, RV3D_CAMOB));
+ BLI_assert((persp != RV3D_CAMOB) || v3d->camera);
+
+ if (persp == RV3D_ORTHO) {
+ dist = ED_view3d_radius_to_dist_ortho(v3d->lens, radius);
+ }
+ else {
+ float lens, sensor_size, zoom;
+ float angle;
+
+ if (persp == RV3D_CAMOB) {
+ CameraParams params;
+ BKE_camera_params_init(&params);
+ params.clip_start = v3d->clip_start;
+ params.clip_end = v3d->clip_end;
+ Object *camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
+ BKE_camera_params_from_object(&params, camera_eval);
+
+ lens = params.lens;
+ sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y);
+
+ /* ignore 'rv3d->camzoom' because we want to fit to the cameras frame */
+ zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB;
+ }
+ else {
+ lens = v3d->lens;
+ sensor_size = DEFAULT_SENSOR_WIDTH;
+ zoom = CAMERA_PARAM_ZOOM_INIT_PERSP;
+ }
+
+ angle = focallength_to_fov(lens, sensor_size);
+
+ /* zoom influences lens, correct this by scaling the angle as a distance
+ * (by the zoom-level) */
+ angle = atanf(tanf(angle / 2.0f) * zoom) * 2.0f;
+
+ dist = ED_view3d_radius_to_dist_persp(angle, radius);
+ }
+
+ if (use_aspect) {
+ const RegionView3D *rv3d = ar->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];
+ }
+ else {
+ winx = ar->winx;
+ winy = ar->winy;
+ }
+
+ if (winx && winy) {
+ float aspect = winx / winy;
+ if (aspect < 1.0f) {
+ aspect = 1.0f / aspect;
+ }
+ dist *= aspect;
+ }
+ }
+
+ return dist;
}
/** \} */
@@ -1217,22 +1232,22 @@ float ED_view3d_radius_to_dist(
*/
float ED_view3d_offset_distance(float mat[4][4], const float ofs[3], const float fallback_dist)
{
- float pos[4] = {0.0f, 0.0f, 0.0f, 1.0f};
- float dir[4] = {0.0f, 0.0f, 1.0f, 0.0f};
- float dist;
+ float pos[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ float dir[4] = {0.0f, 0.0f, 1.0f, 0.0f};
+ float dist;
- mul_m4_v4(mat, pos);
- add_v3_v3(pos, ofs);
- mul_m4_v4(mat, dir);
- normalize_v3(dir);
+ mul_m4_v4(mat, pos);
+ add_v3_v3(pos, ofs);
+ mul_m4_v4(mat, dir);
+ normalize_v3(dir);
- dist = dot_v3v3(pos, dir);
+ dist = dot_v3v3(pos, dir);
- if ((dist < FLT_EPSILON) && (fallback_dist != 0.0f)) {
- dist = fallback_dist;
- }
+ if ((dist < FLT_EPSILON) && (fallback_dist != 0.0f)) {
+ dist = fallback_dist;
+ }
- return dist;
+ return dist;
}
/**
@@ -1242,22 +1257,22 @@ float ED_view3d_offset_distance(float mat[4][4], const float ofs[3], const float
*/
void ED_view3d_distance_set(RegionView3D *rv3d, const float dist)
{
- float viewinv[4];
- float tvec[3];
+ float viewinv[4];
+ float tvec[3];
- BLI_assert(dist >= 0.0f);
+ BLI_assert(dist >= 0.0f);
- copy_v3_fl3(tvec, 0.0f, 0.0f, rv3d->dist - dist);
- /* rv3d->viewinv isn't always valid */
+ copy_v3_fl3(tvec, 0.0f, 0.0f, rv3d->dist - dist);
+ /* rv3d->viewinv isn't always valid */
#if 0
- mul_mat3_m4_v3(rv3d->viewinv, tvec);
+ mul_mat3_m4_v3(rv3d->viewinv, tvec);
#else
- invert_qt_qt_normalized(viewinv, rv3d->viewquat);
- mul_qt_v3(viewinv, tvec);
+ invert_qt_qt_normalized(viewinv, rv3d->viewquat);
+ mul_qt_v3(viewinv, tvec);
#endif
- sub_v3_v3(rv3d->ofs, tvec);
+ sub_v3_v3(rv3d->ofs, tvec);
- rv3d->dist = dist;
+ rv3d->dist = dist;
}
/** \} */
@@ -1266,70 +1281,77 @@ void ED_view3d_distance_set(RegionView3D *rv3d, const float dist)
/** \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 */
+ {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 */
};
-
bool ED_view3d_quat_from_axis_view(const char view, float quat[4])
{
- if (RV3D_VIEW_IS_AXIS(view)) {
- copy_qt_qt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT]);
- return true;
- }
- else {
- return false;
- }
+ if (RV3D_VIEW_IS_AXIS(view)) {
+ copy_qt_qt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT]);
+ return true;
+ }
+ else {
+ return false;
+ }
}
char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon)
{
- /* quat values are all unit length */
+ /* quat values are all unit length */
- char view;
+ char view;
- 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;
- }
- }
+ 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;
+ }
+ }
- return RV3D_VIEW_USER;
+ return RV3D_VIEW_USER;
}
char ED_view3d_lock_view_from_index(int index)
{
- switch (index) {
- case 0: return RV3D_VIEW_FRONT;
- case 1: return RV3D_VIEW_TOP;
- case 2: return RV3D_VIEW_RIGHT;
- default: return RV3D_VIEW_USER;
- }
-
+ switch (index) {
+ case 0:
+ return RV3D_VIEW_FRONT;
+ case 1:
+ return RV3D_VIEW_TOP;
+ case 2:
+ return RV3D_VIEW_RIGHT;
+ default:
+ return RV3D_VIEW_USER;
+ }
}
char ED_view3d_axis_view_opposite(char view)
{
- switch (view) {
- case RV3D_VIEW_FRONT: return RV3D_VIEW_BACK;
- case RV3D_VIEW_BACK: return RV3D_VIEW_FRONT;
- case RV3D_VIEW_LEFT: return RV3D_VIEW_RIGHT;
- case RV3D_VIEW_RIGHT: return RV3D_VIEW_LEFT;
- case RV3D_VIEW_TOP: return RV3D_VIEW_BOTTOM;
- case RV3D_VIEW_BOTTOM: return RV3D_VIEW_TOP;
- }
-
- return RV3D_VIEW_USER;
+ switch (view) {
+ case RV3D_VIEW_FRONT:
+ return RV3D_VIEW_BACK;
+ case RV3D_VIEW_BACK:
+ return RV3D_VIEW_FRONT;
+ case RV3D_VIEW_LEFT:
+ return RV3D_VIEW_RIGHT;
+ case RV3D_VIEW_RIGHT:
+ return RV3D_VIEW_LEFT;
+ case RV3D_VIEW_TOP:
+ return RV3D_VIEW_BOTTOM;
+ case RV3D_VIEW_BOTTOM:
+ return RV3D_VIEW_TOP;
+ }
+
+ return RV3D_VIEW_USER;
}
-
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->viewquat);
}
/** \} */
@@ -1348,28 +1370,28 @@ bool ED_view3d_lock(RegionView3D *rv3d)
*/
void ED_view3d_from_m4(const float mat[4][4], float ofs[3], float quat[4], float *dist)
{
- float nmat[3][3];
+ float nmat[3][3];
- /* dist depends on offset */
- BLI_assert(dist == NULL || ofs != NULL);
+ /* dist depends on offset */
+ BLI_assert(dist == NULL || ofs != NULL);
- copy_m3_m4(nmat, mat);
- normalize_m3(nmat);
+ copy_m3_m4(nmat, mat);
+ normalize_m3(nmat);
- /* Offset */
- if (ofs) {
- negate_v3_v3(ofs, mat[3]);
- }
+ /* Offset */
+ if (ofs) {
+ negate_v3_v3(ofs, mat[3]);
+ }
- /* Quat */
- if (quat) {
- mat3_normalized_to_quat(quat, nmat);
- invert_qt_normalized(quat);
- }
+ /* Quat */
+ if (quat) {
+ mat3_normalized_to_quat(quat, nmat);
+ invert_qt_normalized(quat);
+ }
- if (ofs && dist) {
- madd_v3_v3fl(ofs, nmat[2], *dist);
- }
+ if (ofs && dist) {
+ madd_v3_v3fl(ofs, nmat[2], *dist);
+ }
}
/**
@@ -1382,12 +1404,12 @@ void ED_view3d_from_m4(const float mat[4][4], float ofs[3], float quat[4], float
*/
void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], const float dist)
{
- float iviewquat[4] = {-quat[0], quat[1], quat[2], quat[3]};
- float dvec[3] = {0.0f, 0.0f, dist};
+ float iviewquat[4] = {-quat[0], quat[1], quat[2], quat[3]};
+ float dvec[3] = {0.0f, 0.0f, dist};
- quat_to_mat4(mat, iviewquat);
- mul_mat3_m4_v3(mat, dvec);
- sub_v3_v3v3(mat[3], dvec, ofs);
+ quat_to_mat4(mat, iviewquat);
+ mul_mat3_m4_v3(mat, dvec);
+ sub_v3_v3v3(mat[3], dvec, ofs);
}
/**
@@ -1400,15 +1422,15 @@ void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], c
*/
void ED_view3d_from_object(const Object *ob, float ofs[3], float quat[4], float *dist, float *lens)
{
- ED_view3d_from_m4(ob->obmat, ofs, quat, dist);
+ ED_view3d_from_m4(ob->obmat, ofs, quat, dist);
- if (lens) {
- CameraParams params;
+ if (lens) {
+ CameraParams params;
- BKE_camera_params_init(&params);
- BKE_camera_params_from_object(&params, ob);
- *lens = params.lens;
- }
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_object(&params, ob);
+ *lens = params.lens;
+ }
}
/**
@@ -1419,13 +1441,17 @@ void ED_view3d_from_object(const Object *ob, float ofs[3], float quat[4], float
* \param quat: The view rotation, quaternion normally from RegionView3D.viewquat.
* \param dist: The view distance from ofs, normally from RegionView3D.dist.
*/
-void ED_view3d_to_object(const Depsgraph *depsgraph, Object *ob, const float ofs[3], const float quat[4], const float dist)
+void ED_view3d_to_object(const Depsgraph *depsgraph,
+ Object *ob,
+ const float ofs[3],
+ const float quat[4],
+ const float dist)
{
- float mat[4][4];
- ED_view3d_to_m4(mat, ofs, quat, dist);
+ float mat[4][4];
+ ED_view3d_to_m4(mat, ofs, quat, dist);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- BKE_object_apply_mat4_ex(ob, mat, ob_eval->parent, ob_eval->parentinv, true);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ BKE_object_apply_mat4_ex(ob, mat, ob_eval->parent, ob_eval->parentinv, true);
}
/** \} */
@@ -1436,96 +1462,92 @@ void ED_view3d_to_object(const Depsgraph *depsgraph, Object *ob, const float ofs
float ED_view3d_depth_read_cached(const ViewContext *vc, const int mval[2])
{
- ViewDepths *vd = vc->rv3d->depths;
-
- int x = mval[0];
- int y = mval[1];
-
- if (vd && vd->depths && x > 0 && y > 0 && x < vd->w && y < vd->h) {
- return vd->depths[y * vd->w + x];
- }
- else {
- BLI_assert(1.0 <= vd->depth_range[1]);
- return 1.0f;
- }
+ ViewDepths *vd = vc->rv3d->depths;
+
+ int x = mval[0];
+ int y = mval[1];
+
+ if (vd && vd->depths && x > 0 && y > 0 && x < vd->w && y < vd->h) {
+ return vd->depths[y * vd->w + x];
+ }
+ else {
+ BLI_assert(1.0 <= vd->depth_range[1]);
+ return 1.0f;
+ }
}
-bool ED_view3d_depth_read_cached_normal(
- const ViewContext *vc, const int mval[2],
- float r_normal[3])
+bool ED_view3d_depth_read_cached_normal(const ViewContext *vc,
+ const int mval[2],
+ float r_normal[3])
{
- /* Note: we could support passing in a radius.
- * For now just read 9 pixels. */
-
- /* pixels surrounding */
- bool depths_valid[9] = {false};
- float coords[9][3] = {{0}};
-
- ARegion *ar = vc->ar;
- const ViewDepths *depths = vc->rv3d->depths;
-
- for (int x = 0, i = 0; x < 2; x++) {
- for (int y = 0; y < 2; y++) {
- const int mval_ofs[2] = {mval[0] + (x - 1), mval[1] + (y - 1)};
-
- 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])) {
- depths_valid[i] = true;
- }
- }
- i++;
- }
- }
-
- const int edges[2][6][2] = {
- /* x edges */
- {{0, 1}, {1, 2},
- {3, 4}, {4, 5},
- {6, 7}, {7, 8}},
- /* y edges */
- {{0, 3}, {3, 6},
- {1, 4}, {4, 7},
- {2, 5}, {5, 8}},
- };
-
- float cross[2][3] = {{0.0f}};
-
- for (int i = 0; i < 6; i++) {
- for (int axis = 0; axis < 2; axis++) {
- if (depths_valid[edges[axis][i][0]] && depths_valid[edges[axis][i][1]]) {
- float delta[3];
- sub_v3_v3v3(delta, coords[edges[axis][i][0]], coords[edges[axis][i][1]]);
- add_v3_v3(cross[axis], delta);
- }
- }
- }
-
- cross_v3_v3v3(r_normal, cross[0], cross[1]);
-
- if (normalize_v3(r_normal) != 0.0f) {
- return true;
- }
- else {
- return false;
- }
+ /* Note: we could support passing in a radius.
+ * For now just read 9 pixels. */
+
+ /* pixels surrounding */
+ bool depths_valid[9] = {false};
+ float coords[9][3] = {{0}};
+
+ ARegion *ar = vc->ar;
+ const ViewDepths *depths = vc->rv3d->depths;
+
+ for (int x = 0, i = 0; x < 2; x++) {
+ for (int y = 0; y < 2; y++) {
+ const int mval_ofs[2] = {mval[0] + (x - 1), mval[1] + (y - 1)};
+
+ 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])) {
+ depths_valid[i] = true;
+ }
+ }
+ i++;
+ }
+ }
+
+ const int edges[2][6][2] = {
+ /* x edges */
+ {{0, 1}, {1, 2}, {3, 4}, {4, 5}, {6, 7}, {7, 8}},
+ /* y edges */
+ {{0, 3}, {3, 6}, {1, 4}, {4, 7}, {2, 5}, {5, 8}},
+ };
+
+ float cross[2][3] = {{0.0f}};
+
+ for (int i = 0; i < 6; i++) {
+ for (int axis = 0; axis < 2; axis++) {
+ if (depths_valid[edges[axis][i][0]] && depths_valid[edges[axis][i][1]]) {
+ float delta[3];
+ sub_v3_v3v3(delta, coords[edges[axis][i][0]], coords[edges[axis][i][1]]);
+ add_v3_v3(cross[axis], delta);
+ }
+ }
+ }
+
+ cross_v3_v3v3(r_normal, cross[0], cross[1]);
+
+ if (normalize_v3(r_normal) != 0.0f) {
+ return true;
+ }
+ else {
+ return false;
+ }
}
-bool ED_view3d_depth_unproject(
- const ARegion *ar,
- const int mval[2], const double depth,
- float r_location_world[3])
+bool ED_view3d_depth_unproject(const ARegion *ar,
+ 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);
+ 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);
}
void ED_view3d_depth_tag_update(RegionView3D *rv3d)
{
- if (rv3d->depths) {
- rv3d->depths->damaged = true;
- }
+ if (rv3d->depths) {
+ rv3d->depths->damaged = true;
+ }
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 4e5dddf4742..e313ed39c49 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -62,7 +62,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "view3d_intern.h" /* own include */
+#include "view3d_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Smooth View Operator & Utilities
@@ -73,371 +73,378 @@
/* This operator is one of the 'timer refresh' ones like animation playback */
struct SmoothView3DState {
- float dist;
- float lens;
- float quat[4];
- float ofs[3];
+ float dist;
+ float lens;
+ float quat[4];
+ float ofs[3];
};
struct SmoothView3DStore {
- /* source*/
- struct SmoothView3DState src; /* source */
- struct SmoothView3DState dst; /* destination */
- struct SmoothView3DState org; /* original */
+ /* source*/
+ struct SmoothView3DState src; /* source */
+ struct SmoothView3DState dst; /* destination */
+ struct SmoothView3DState org; /* original */
- bool to_camera;
+ bool to_camera;
- bool use_dyn_ofs;
- float dyn_ofs[3];
+ bool use_dyn_ofs;
+ float dyn_ofs[3];
- /* When smooth-view is enabled, store the 'rv3d->view' here,
- * assign back when the view motion is completed. */
- char org_view;
+ /* When smooth-view is enabled, store the 'rv3d->view' here,
+ * assign back when the view motion is completed. */
+ char org_view;
- double time_allowed;
+ double time_allowed;
};
static void view3d_smooth_view_state_backup(struct SmoothView3DState *sms_state,
- const View3D *v3d, const RegionView3D *rv3d)
+ const View3D *v3d,
+ const RegionView3D *rv3d)
{
- copy_v3_v3(sms_state->ofs, rv3d->ofs);
- copy_qt_qt(sms_state->quat, rv3d->viewquat);
- sms_state->dist = rv3d->dist;
- sms_state->lens = v3d->lens;
+ copy_v3_v3(sms_state->ofs, rv3d->ofs);
+ copy_qt_qt(sms_state->quat, rv3d->viewquat);
+ sms_state->dist = rv3d->dist;
+ sms_state->lens = v3d->lens;
}
static void view3d_smooth_view_state_restore(const struct SmoothView3DState *sms_state,
- View3D *v3d, RegionView3D *rv3d)
+ View3D *v3d,
+ RegionView3D *rv3d)
{
- copy_v3_v3(rv3d->ofs, sms_state->ofs);
- copy_qt_qt(rv3d->viewquat, sms_state->quat);
- rv3d->dist = sms_state->dist;
- v3d->lens = sms_state->lens;
+ copy_v3_v3(rv3d->ofs, sms_state->ofs);
+ copy_qt_qt(rv3d->viewquat, sms_state->quat);
+ rv3d->dist = sms_state->dist;
+ v3d->lens = sms_state->lens;
}
/* will start timer if appropriate */
/* the arguments are the desired situation */
void ED_view3d_smooth_view_ex(
- /* avoid passing in the context */
- const Depsgraph *depsgraph, wmWindowManager *wm, wmWindow *win, ScrArea *sa,
- View3D *v3d, ARegion *ar, const int smooth_viewtx,
- const V3D_SmoothParams *sview)
+ /* avoid passing in the context */
+ const Depsgraph *depsgraph,
+ wmWindowManager *wm,
+ wmWindow *win,
+ ScrArea *sa,
+ View3D *v3d,
+ ARegion *ar,
+ const int smooth_viewtx,
+ const V3D_SmoothParams *sview)
{
- RegionView3D *rv3d = ar->regiondata;
- struct SmoothView3DStore sms = {{0}};
- bool ok = false;
-
- /* initialize sms */
- view3d_smooth_view_state_backup(&sms.dst, v3d, rv3d);
- view3d_smooth_view_state_backup(&sms.src, v3d, rv3d);
- /* if smoothview runs multiple times... */
- if (rv3d->sms == NULL) {
- view3d_smooth_view_state_backup(&sms.org, v3d, rv3d);
- }
- else {
- sms.org = rv3d->sms->org;
- }
- sms.org_view = rv3d->view;
-
- /* sms.to_camera = false; */ /* initizlized to zero anyway */
-
- /* note on camera locking, this is a little confusing but works ok.
- * we may be changing the view 'as if' there is no active camera, but in fact
- * there is an active camera which is locked to the view.
- *
- * In the case where smooth view is moving _to_ a camera we don't want that
- * camera to be moved or changed, so only when the camera is not being set should
- * we allow camera option locking to initialize the view settings from the camera.
- */
- if (sview->camera == NULL && sview->camera_old == NULL) {
- ED_view3d_camera_lock_init(depsgraph, v3d, rv3d);
- }
-
- /* store the options we want to end with */
- if (sview->ofs) {
- copy_v3_v3(sms.dst.ofs, sview->ofs);
- }
- if (sview->quat) {
- copy_qt_qt(sms.dst.quat, sview->quat);
- }
- if (sview->dist) {
- sms.dst.dist = *sview->dist;
- }
- if (sview->lens) {
- sms.dst.lens = *sview->lens;
- }
-
- if (sview->dyn_ofs) {
- BLI_assert(sview->ofs == NULL);
- BLI_assert(sview->quat != NULL);
-
- copy_v3_v3(sms.dyn_ofs, sview->dyn_ofs);
- sms.use_dyn_ofs = true;
-
- /* calculate the final destination offset */
- view3d_orbit_apply_dyn_ofs(sms.dst.ofs, sms.src.ofs, sms.src.quat, sms.dst.quat, sms.dyn_ofs);
- }
-
- if (sview->camera) {
- Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, sview->camera);
- sms.dst.dist = ED_view3d_offset_distance(ob_camera_eval->obmat, sview->ofs, VIEW3D_DIST_FALLBACK);
- ED_view3d_from_object(ob_camera_eval, sms.dst.ofs, sms.dst.quat, &sms.dst.dist, &sms.dst.lens);
- sms.to_camera = true; /* restore view3d values in end */
- }
-
- /* skip smooth viewing for render engine draw */
- if (smooth_viewtx && v3d->shading.type != OB_RENDER) {
- bool changed = false; /* zero means no difference */
-
- if (sview->camera_old != sview->camera) {
- changed = true;
- }
- else if (sms.dst.dist != rv3d->dist) {
- changed = true;
- }
- else if (sms.dst.lens != v3d->lens) {
- changed = true;
- }
- else if (!equals_v3v3(sms.dst.ofs, rv3d->ofs)) {
- changed = true;
- }
- else if (!equals_v4v4(sms.dst.quat, rv3d->viewquat)) {
- changed = true;
- }
-
- /* The new view is different from the old one
- * so animate the view */
- if (changed) {
- /* original values */
- if (sview->camera_old) {
- Object *ob_camera_old_eval = DEG_get_evaluated_object(depsgraph, sview->camera_old);
- sms.src.dist = ED_view3d_offset_distance(ob_camera_old_eval->obmat, rv3d->ofs, 0.0f);
- /* this */
- ED_view3d_from_object(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) {
- /* use existing if exists, means multiple calls to smooth view
- * wont loose the original 'view' setting */
- rv3d->view = RV3D_VIEW_USER;
- }
-
- sms.time_allowed = (double)smooth_viewtx / 1000.0;
-
- /* if this is view rotation only
- * we can decrease the time allowed by
- * the angle between quats
- * this means small rotations wont lag */
- if (sview->quat && !sview->ofs && !sview->dist) {
- /* scale the time allowed by the rotation */
- /* 180deg == 1.0 */
- sms.time_allowed *= (double)fabsf(angle_signed_normalized_qtqt(sms.dst.quat, sms.src.quat)) / M_PI;
- }
-
- /* ensure it shows correct */
- if (sms.to_camera) {
- /* use ortho if we move from an ortho view to an ortho camera */
- Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, sview->camera);
- rv3d->persp = (((rv3d->is_persp == false) &&
- (ob_camera_eval->type == OB_CAMERA) &&
- (((Camera *)ob_camera_eval->data)->type == CAM_ORTHO)) ?
- RV3D_ORTHO : RV3D_PERSP);
- }
-
- rv3d->rflag |= RV3D_NAVIGATING;
-
- /* not essential but in some cases the caller will tag the area for redraw, and in that
- * case we can get a flicker of the 'org' user view but we want to see 'src' */
- view3d_smooth_view_state_restore(&sms.src, v3d, rv3d);
-
- /* keep track of running timer! */
- if (rv3d->sms == NULL) {
- rv3d->sms = MEM_mallocN(sizeof(struct SmoothView3DStore), "smoothview v3d");
- }
- *rv3d->sms = sms;
- if (rv3d->smooth_timer) {
- WM_event_remove_timer(wm, win, rv3d->smooth_timer);
- }
- /* TIMER1 is hardcoded in keymap */
- /* max 30 frs/sec */
- rv3d->smooth_timer = WM_event_add_timer(wm, win, TIMER1, 1.0 / 100.0);
-
- ok = true;
- }
- }
-
- /* if we get here nothing happens */
- if (ok == false) {
- if (sms.to_camera == false) {
- copy_v3_v3(rv3d->ofs, sms.dst.ofs);
- copy_qt_qt(rv3d->viewquat, sms.dst.quat);
- rv3d->dist = sms.dst.dist;
- v3d->lens = sms.dst.lens;
-
- ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
- }
-
- if (rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_copy(sa, ar);
- }
-
- ED_region_tag_redraw(ar);
- }
+ RegionView3D *rv3d = ar->regiondata;
+ struct SmoothView3DStore sms = {{0}};
+ bool ok = false;
+
+ /* initialize sms */
+ view3d_smooth_view_state_backup(&sms.dst, v3d, rv3d);
+ view3d_smooth_view_state_backup(&sms.src, v3d, rv3d);
+ /* if smoothview runs multiple times... */
+ if (rv3d->sms == NULL) {
+ view3d_smooth_view_state_backup(&sms.org, v3d, rv3d);
+ }
+ else {
+ sms.org = rv3d->sms->org;
+ }
+ sms.org_view = rv3d->view;
+
+ /* sms.to_camera = false; */ /* initizlized to zero anyway */
+
+ /* note on camera locking, this is a little confusing but works ok.
+ * we may be changing the view 'as if' there is no active camera, but in fact
+ * there is an active camera which is locked to the view.
+ *
+ * In the case where smooth view is moving _to_ a camera we don't want that
+ * camera to be moved or changed, so only when the camera is not being set should
+ * we allow camera option locking to initialize the view settings from the camera.
+ */
+ if (sview->camera == NULL && sview->camera_old == NULL) {
+ ED_view3d_camera_lock_init(depsgraph, v3d, rv3d);
+ }
+
+ /* store the options we want to end with */
+ if (sview->ofs) {
+ copy_v3_v3(sms.dst.ofs, sview->ofs);
+ }
+ if (sview->quat) {
+ copy_qt_qt(sms.dst.quat, sview->quat);
+ }
+ if (sview->dist) {
+ sms.dst.dist = *sview->dist;
+ }
+ if (sview->lens) {
+ sms.dst.lens = *sview->lens;
+ }
+
+ if (sview->dyn_ofs) {
+ BLI_assert(sview->ofs == NULL);
+ BLI_assert(sview->quat != NULL);
+
+ copy_v3_v3(sms.dyn_ofs, sview->dyn_ofs);
+ sms.use_dyn_ofs = true;
+
+ /* calculate the final destination offset */
+ view3d_orbit_apply_dyn_ofs(sms.dst.ofs, sms.src.ofs, sms.src.quat, sms.dst.quat, sms.dyn_ofs);
+ }
+
+ if (sview->camera) {
+ Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, sview->camera);
+ sms.dst.dist = ED_view3d_offset_distance(
+ ob_camera_eval->obmat, sview->ofs, VIEW3D_DIST_FALLBACK);
+ ED_view3d_from_object(ob_camera_eval, sms.dst.ofs, sms.dst.quat, &sms.dst.dist, &sms.dst.lens);
+ sms.to_camera = true; /* restore view3d values in end */
+ }
+
+ /* skip smooth viewing for render engine draw */
+ if (smooth_viewtx && v3d->shading.type != OB_RENDER) {
+ bool changed = false; /* zero means no difference */
+
+ if (sview->camera_old != sview->camera) {
+ changed = true;
+ }
+ else if (sms.dst.dist != rv3d->dist) {
+ changed = true;
+ }
+ else if (sms.dst.lens != v3d->lens) {
+ changed = true;
+ }
+ else if (!equals_v3v3(sms.dst.ofs, rv3d->ofs)) {
+ changed = true;
+ }
+ else if (!equals_v4v4(sms.dst.quat, rv3d->viewquat)) {
+ changed = true;
+ }
+
+ /* The new view is different from the old one
+ * so animate the view */
+ if (changed) {
+ /* original values */
+ if (sview->camera_old) {
+ Object *ob_camera_old_eval = DEG_get_evaluated_object(depsgraph, sview->camera_old);
+ sms.src.dist = ED_view3d_offset_distance(ob_camera_old_eval->obmat, rv3d->ofs, 0.0f);
+ /* this */
+ ED_view3d_from_object(
+ 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) {
+ /* use existing if exists, means multiple calls to smooth view
+ * wont loose the original 'view' setting */
+ rv3d->view = RV3D_VIEW_USER;
+ }
+
+ sms.time_allowed = (double)smooth_viewtx / 1000.0;
+
+ /* if this is view rotation only
+ * we can decrease the time allowed by
+ * the angle between quats
+ * this means small rotations wont lag */
+ if (sview->quat && !sview->ofs && !sview->dist) {
+ /* scale the time allowed by the rotation */
+ /* 180deg == 1.0 */
+ sms.time_allowed *= (double)fabsf(
+ angle_signed_normalized_qtqt(sms.dst.quat, sms.src.quat)) /
+ M_PI;
+ }
+
+ /* ensure it shows correct */
+ if (sms.to_camera) {
+ /* use ortho if we move from an ortho view to an ortho camera */
+ Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, sview->camera);
+ rv3d->persp = (((rv3d->is_persp == false) && (ob_camera_eval->type == OB_CAMERA) &&
+ (((Camera *)ob_camera_eval->data)->type == CAM_ORTHO)) ?
+ RV3D_ORTHO :
+ RV3D_PERSP);
+ }
+
+ rv3d->rflag |= RV3D_NAVIGATING;
+
+ /* not essential but in some cases the caller will tag the area for redraw, and in that
+ * case we can get a flicker of the 'org' user view but we want to see 'src' */
+ view3d_smooth_view_state_restore(&sms.src, v3d, rv3d);
+
+ /* keep track of running timer! */
+ if (rv3d->sms == NULL) {
+ rv3d->sms = MEM_mallocN(sizeof(struct SmoothView3DStore), "smoothview v3d");
+ }
+ *rv3d->sms = sms;
+ if (rv3d->smooth_timer) {
+ WM_event_remove_timer(wm, win, rv3d->smooth_timer);
+ }
+ /* TIMER1 is hardcoded in keymap */
+ /* max 30 frs/sec */
+ rv3d->smooth_timer = WM_event_add_timer(wm, win, TIMER1, 1.0 / 100.0);
+
+ ok = true;
+ }
+ }
+
+ /* if we get here nothing happens */
+ if (ok == false) {
+ if (sms.to_camera == false) {
+ copy_v3_v3(rv3d->ofs, sms.dst.ofs);
+ copy_qt_qt(rv3d->viewquat, sms.dst.quat);
+ rv3d->dist = sms.dst.dist;
+ v3d->lens = sms.dst.lens;
+
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
+ }
+
+ if (rv3d->viewlock & RV3D_BOXVIEW) {
+ view3d_boxview_copy(sa, ar);
+ }
+
+ ED_region_tag_redraw(ar);
+ }
}
-void ED_view3d_smooth_view(
- bContext *C,
- View3D *v3d, ARegion *ar, const int smooth_viewtx,
- const struct V3D_SmoothParams *sview)
+void ED_view3d_smooth_view(bContext *C,
+ View3D *v3d,
+ ARegion *ar,
+ const int smooth_viewtx,
+ const struct V3D_SmoothParams *sview)
{
- const Depsgraph *depsgraph = CTX_data_depsgraph(C);
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
- ScrArea *sa = CTX_wm_area(C);
-
- ED_view3d_smooth_view_ex(
- depsgraph,
- wm, win, sa,
- v3d, ar, smooth_viewtx,
- sview);
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *sa = CTX_wm_area(C);
+
+ ED_view3d_smooth_view_ex(depsgraph, wm, win, sa, v3d, ar, smooth_viewtx, sview);
}
/* only meant for timer usage */
static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *ar, bool sync_boxview)
{
- const Depsgraph *depsgraph = CTX_data_depsgraph(C);
- RegionView3D *rv3d = ar->regiondata;
- struct SmoothView3DStore *sms = rv3d->sms;
- float step, step_inv;
-
- if (sms->time_allowed != 0.0) {
- step = (float)((rv3d->smooth_timer->duration) / sms->time_allowed);
- }
- else {
- step = 1.0f;
- }
-
- /* end timer */
- if (step >= 1.0f) {
-
- /* if we went to camera, store the original */
- if (sms->to_camera) {
- rv3d->persp = RV3D_CAMOB;
- view3d_smooth_view_state_restore(&sms->org, v3d, rv3d);
- }
- else {
- view3d_smooth_view_state_restore(&sms->dst, v3d, rv3d);
-
- ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
- ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
- }
-
- if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
- rv3d->view = sms->org_view;
- }
-
- MEM_freeN(rv3d->sms);
- rv3d->sms = NULL;
-
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), rv3d->smooth_timer);
- rv3d->smooth_timer = NULL;
- rv3d->rflag &= ~RV3D_NAVIGATING;
- }
- else {
- /* ease in/out */
- step = (3.0f * step * step - 2.0f * step * step * step);
-
- step_inv = 1.0f - step;
-
- interp_qt_qtqt(rv3d->viewquat, sms->src.quat, sms->dst.quat, step);
-
- if (sms->use_dyn_ofs) {
- view3d_orbit_apply_dyn_ofs(rv3d->ofs, sms->src.ofs, sms->src.quat, rv3d->viewquat, sms->dyn_ofs);
- }
- else {
- interp_v3_v3v3(rv3d->ofs, sms->src.ofs, sms->dst.ofs, step);
- }
-
- rv3d->dist = sms->dst.dist * step + sms->src.dist * step_inv;
- v3d->lens = sms->dst.lens * step + sms->src.lens * step_inv;
-
- ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
- if (ED_screen_animation_playing(CTX_wm_manager(C))) {
- ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
- }
-
- /* Event handling won't know if a UI item has been moved under the pointer. */
- WM_event_add_mousemove(C);
- }
-
- if (sync_boxview && (rv3d->viewlock & RV3D_BOXVIEW)) {
- view3d_boxview_copy(CTX_wm_area(C), ar);
- }
-
- /* note: this doesn't work right because the v3d->lens is now used in ortho mode r51636,
- * when switching camera in quad-view the other ortho views would zoom & reset.
- *
- * For now only redraw all regions when smoothview finishes.
- */
- if (step >= 1.0f) {
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
- }
- else {
- ED_region_tag_redraw(ar);
- }
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ RegionView3D *rv3d = ar->regiondata;
+ struct SmoothView3DStore *sms = rv3d->sms;
+ float step, step_inv;
+
+ if (sms->time_allowed != 0.0) {
+ step = (float)((rv3d->smooth_timer->duration) / sms->time_allowed);
+ }
+ else {
+ step = 1.0f;
+ }
+
+ /* end timer */
+ if (step >= 1.0f) {
+
+ /* if we went to camera, store the original */
+ if (sms->to_camera) {
+ rv3d->persp = RV3D_CAMOB;
+ view3d_smooth_view_state_restore(&sms->org, v3d, rv3d);
+ }
+ else {
+ view3d_smooth_view_state_restore(&sms->dst, v3d, rv3d);
+
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
+ ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
+ }
+
+ if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
+ rv3d->view = sms->org_view;
+ }
+
+ MEM_freeN(rv3d->sms);
+ rv3d->sms = NULL;
+
+ WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), rv3d->smooth_timer);
+ rv3d->smooth_timer = NULL;
+ rv3d->rflag &= ~RV3D_NAVIGATING;
+ }
+ else {
+ /* ease in/out */
+ step = (3.0f * step * step - 2.0f * step * step * step);
+
+ step_inv = 1.0f - step;
+
+ interp_qt_qtqt(rv3d->viewquat, sms->src.quat, sms->dst.quat, step);
+
+ if (sms->use_dyn_ofs) {
+ view3d_orbit_apply_dyn_ofs(
+ rv3d->ofs, sms->src.ofs, sms->src.quat, rv3d->viewquat, sms->dyn_ofs);
+ }
+ else {
+ interp_v3_v3v3(rv3d->ofs, sms->src.ofs, sms->dst.ofs, step);
+ }
+
+ rv3d->dist = sms->dst.dist * step + sms->src.dist * step_inv;
+ v3d->lens = sms->dst.lens * step + sms->src.lens * step_inv;
+
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
+ }
+
+ /* Event handling won't know if a UI item has been moved under the pointer. */
+ WM_event_add_mousemove(C);
+ }
+
+ if (sync_boxview && (rv3d->viewlock & RV3D_BOXVIEW)) {
+ view3d_boxview_copy(CTX_wm_area(C), ar);
+ }
+
+ /* note: this doesn't work right because the v3d->lens is now used in ortho mode r51636,
+ * when switching camera in quad-view the other ortho views would zoom & reset.
+ *
+ * For now only redraw all regions when smoothview finishes.
+ */
+ if (step >= 1.0f) {
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ }
+ else {
+ ED_region_tag_redraw(ar);
+ }
}
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;
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
- /* escape if not our timer */
- if (rv3d->smooth_timer == NULL || rv3d->smooth_timer != event->customdata) {
- return OPERATOR_PASS_THROUGH;
- }
+ /* 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, ar, true);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/**
* 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 *ar)
{
- RegionView3D *rv3d = ar->regiondata;
-
- if (rv3d && rv3d->sms) {
- rv3d->sms->time_allowed = 0.0; /* force finishing */
- view3d_smoothview_apply(C, v3d, ar, false);
-
- /* force update of view matrix so tools that run immediately after
- * can use them without redrawing first */
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL);
- }
+ RegionView3D *rv3d = ar->regiondata;
+
+ if (rv3d && rv3d->sms) {
+ rv3d->sms->time_allowed = 0.0; /* force finishing */
+ view3d_smoothview_apply(C, v3d, ar, false);
+
+ /* force update of view matrix so tools that run immediately after
+ * can use them without redrawing first */
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL);
+ }
}
void VIEW3D_OT_smoothview(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Smooth View";
- ot->idname = "VIEW3D_OT_smoothview";
+ /* identifiers */
+ ot->name = "Smooth View";
+ ot->idname = "VIEW3D_OT_smoothview";
- /* api callbacks */
- ot->invoke = view3d_smoothview_invoke;
+ /* api callbacks */
+ ot->invoke = view3d_smoothview_invoke;
- /* flags */
- ot->flag = OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_INTERNAL;
- ot->poll = ED_operator_view3d_active;
+ ot->poll = ED_operator_view3d_active;
}
/** \} */
@@ -448,65 +455,64 @@ void VIEW3D_OT_smoothview(wmOperatorType *ot)
static int view3d_camera_to_view_exec(bContext *C, wmOperator *UNUSED(op))
{
- const Depsgraph *depsgraph = CTX_data_depsgraph(C);
- View3D *v3d;
- ARegion *ar;
- RegionView3D *rv3d;
-
- ObjectTfmProtectedChannels obtfm;
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ View3D *v3d;
+ ARegion *ar;
+ RegionView3D *rv3d;
- ED_view3d_context_user_region(C, &v3d, &ar);
- rv3d = ar->regiondata;
+ ObjectTfmProtectedChannels obtfm;
- ED_view3d_lastview_store(rv3d);
+ ED_view3d_context_user_region(C, &v3d, &ar);
+ rv3d = ar->regiondata;
- BKE_object_tfm_protected_backup(v3d->camera, &obtfm);
+ ED_view3d_lastview_store(rv3d);
- ED_view3d_to_object(depsgraph, v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+ BKE_object_tfm_protected_backup(v3d->camera, &obtfm);
- BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag);
+ ED_view3d_to_object(depsgraph, v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
- DEG_id_tag_update(&v3d->camera->id, ID_RECALC_TRANSFORM);
- rv3d->persp = RV3D_CAMOB;
+ BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, v3d->camera);
+ DEG_id_tag_update(&v3d->camera->id, ID_RECALC_TRANSFORM);
+ rv3d->persp = RV3D_CAMOB;
- return OPERATOR_FINISHED;
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, v3d->camera);
+ return OPERATOR_FINISHED;
}
static bool view3d_camera_to_view_poll(bContext *C)
{
- View3D *v3d;
- ARegion *ar;
-
- if (ED_view3d_context_user_region(C, &v3d, &ar)) {
- RegionView3D *rv3d = ar->regiondata;
- if (v3d && v3d->camera && !ID_IS_LINKED(v3d->camera)) {
- if (rv3d && (rv3d->viewlock & RV3D_LOCKED) == 0) {
- if (rv3d->persp != RV3D_CAMOB) {
- return 1;
- }
- }
- }
- }
-
- return 0;
+ View3D *v3d;
+ ARegion *ar;
+
+ if (ED_view3d_context_user_region(C, &v3d, &ar)) {
+ RegionView3D *rv3d = ar->regiondata;
+ if (v3d && v3d->camera && !ID_IS_LINKED(v3d->camera)) {
+ if (rv3d && (rv3d->viewlock & RV3D_LOCKED) == 0) {
+ if (rv3d->persp != RV3D_CAMOB) {
+ return 1;
+ }
+ }
+ }
+ }
+
+ return 0;
}
void VIEW3D_OT_camera_to_view(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Align Camera To View";
- ot->description = "Set camera view to active view";
- ot->idname = "VIEW3D_OT_camera_to_view";
+ /* identifiers */
+ ot->name = "Align Camera To View";
+ ot->description = "Set camera view to active view";
+ ot->idname = "VIEW3D_OT_camera_to_view";
- /* api callbacks */
- ot->exec = view3d_camera_to_view_exec;
- ot->poll = view3d_camera_to_view_poll;
+ /* api callbacks */
+ ot->exec = view3d_camera_to_view_exec;
+ ot->poll = view3d_camera_to_view_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -519,60 +525,61 @@ void VIEW3D_OT_camera_to_view(wmOperatorType *ot)
* meant to take into account vertex/bone selection for eg. */
static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C); /* can be NULL */
- Object *camera_ob = v3d ? v3d->camera : scene->camera;
- Object *camera_ob_eval = DEG_get_evaluated_object(depsgraph, camera_ob);
-
- float r_co[3]; /* the new location to apply */
- float r_scale; /* only for ortho cameras */
-
- if (camera_ob_eval == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active camera");
- return OPERATOR_CANCELLED;
- }
-
- /* this function does all the important stuff */
- if (BKE_camera_view_frame_fit_to_scene(depsgraph, scene, camera_ob_eval, r_co, &r_scale)) {
- ObjectTfmProtectedChannels obtfm;
- float obmat_new[4][4];
-
- if ((camera_ob_eval->type == OB_CAMERA) && (((Camera *)camera_ob_eval->data)->type == CAM_ORTHO)) {
- ((Camera *)camera_ob->data)->ortho_scale = r_scale;
- }
-
- copy_m4_m4(obmat_new, camera_ob_eval->obmat);
- copy_v3_v3(obmat_new[3], r_co);
-
- /* only touch location */
- BKE_object_tfm_protected_backup(camera_ob, &obtfm);
- BKE_object_apply_mat4(camera_ob, obmat_new, true, true);
- BKE_object_tfm_protected_restore(camera_ob, &obtfm, OB_LOCK_SCALE | OB_LOCK_ROT4D);
-
- /* notifiers */
- DEG_id_tag_update(&camera_ob->id, ID_RECALC_TRANSFORM);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, camera_ob);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C); /* can be NULL */
+ Object *camera_ob = v3d ? v3d->camera : scene->camera;
+ Object *camera_ob_eval = DEG_get_evaluated_object(depsgraph, camera_ob);
+
+ float r_co[3]; /* the new location to apply */
+ float r_scale; /* only for ortho cameras */
+
+ if (camera_ob_eval == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active camera");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* this function does all the important stuff */
+ if (BKE_camera_view_frame_fit_to_scene(depsgraph, scene, camera_ob_eval, r_co, &r_scale)) {
+ ObjectTfmProtectedChannels obtfm;
+ float obmat_new[4][4];
+
+ if ((camera_ob_eval->type == OB_CAMERA) &&
+ (((Camera *)camera_ob_eval->data)->type == CAM_ORTHO)) {
+ ((Camera *)camera_ob->data)->ortho_scale = r_scale;
+ }
+
+ copy_m4_m4(obmat_new, camera_ob_eval->obmat);
+ copy_v3_v3(obmat_new[3], r_co);
+
+ /* only touch location */
+ BKE_object_tfm_protected_backup(camera_ob, &obtfm);
+ BKE_object_apply_mat4(camera_ob, obmat_new, true, true);
+ BKE_object_tfm_protected_restore(camera_ob, &obtfm, OB_LOCK_SCALE | OB_LOCK_ROT4D);
+
+ /* notifiers */
+ DEG_id_tag_update(&camera_ob->id, ID_RECALC_TRANSFORM);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, camera_ob);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void VIEW3D_OT_camera_to_view_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Camera Fit Frame to Selected";
- ot->description = "Move the camera so selected objects are framed";
- ot->idname = "VIEW3D_OT_camera_to_view_selected";
+ /* identifiers */
+ ot->name = "Camera Fit Frame to Selected";
+ ot->description = "Move the camera so selected objects are framed";
+ ot->idname = "VIEW3D_OT_camera_to_view_selected";
- /* api callbacks */
- ot->exec = view3d_camera_to_view_selected_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = view3d_camera_to_view_selected_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -581,124 +588,134 @@ void VIEW3D_OT_camera_to_view_selected(wmOperatorType *ot)
/** \name Object as Camera Operator
* \{ */
-static void sync_viewport_camera_smoothview(bContext *C, View3D *v3d, Object *ob, const int smooth_viewtx)
+static void sync_viewport_camera_smoothview(bContext *C,
+ View3D *v3d,
+ Object *ob,
+ const int smooth_viewtx)
{
- Main *bmain = CTX_data_main(C);
- for (bScreen *screen = bmain->screens.first; screen != NULL; screen = screen->id.next) {
- for (ScrArea *area = screen->areabase.first; area != NULL; area = area->next) {
- for (SpaceLink *space_link = area->spacedata.first; space_link != NULL; space_link = space_link->next) {
- if (space_link->spacetype == SPACE_VIEW3D) {
- View3D *other_v3d = (View3D *)space_link;
- if (other_v3d == v3d) {
- continue;
- }
- if (other_v3d->camera == ob) {
- continue;
- }
- 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;
- 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, smooth_viewtx,
- &(const V3D_SmoothParams) {
- .camera_old = other_camera_old,
- .camera = other_v3d->camera,
- .ofs = other_rv3d->ofs,
- .quat = other_rv3d->viewquat,
- .dist = &other_rv3d->dist,
- .lens = &other_v3d->lens,
- });
- }
- else {
- other_v3d->camera = ob;
- }
- }
- }
- }
- }
- }
- }
- }
- }
+ Main *bmain = CTX_data_main(C);
+ for (bScreen *screen = bmain->screens.first; screen != NULL; screen = screen->id.next) {
+ for (ScrArea *area = screen->areabase.first; area != NULL; area = area->next) {
+ for (SpaceLink *space_link = area->spacedata.first; space_link != NULL;
+ space_link = space_link->next) {
+ if (space_link->spacetype == SPACE_VIEW3D) {
+ View3D *other_v3d = (View3D *)space_link;
+ if (other_v3d == v3d) {
+ continue;
+ }
+ if (other_v3d->camera == ob) {
+ continue;
+ }
+ 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;
+ 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,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .camera_old = other_camera_old,
+ .camera = other_v3d->camera,
+ .ofs = other_rv3d->ofs,
+ .quat = other_rv3d->viewquat,
+ .dist = &other_rv3d->dist,
+ .lens = &other_v3d->lens,
+ });
+ }
+ else {
+ other_v3d->camera = ob;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
static int view3d_setobjectascamera_exec(bContext *C, wmOperator *op)
{
- View3D *v3d;
- ARegion *ar;
- RegionView3D *rv3d;
-
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
-
- 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;
-
- if (ob) {
- Object *camera_old = (rv3d->persp == RV3D_CAMOB) ? V3D_CAMERA_SCENE(scene, v3d) : NULL;
- rv3d->persp = RV3D_CAMOB;
- v3d->camera = ob;
- if (v3d->scenelock && scene->camera != ob) {
- scene->camera = ob;
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- }
-
- /* unlikely but looks like a glitch when set to the same */
- if (camera_old != ob) {
- ED_view3d_lastview_store(rv3d);
-
- ED_view3d_smooth_view(
- C, v3d, ar, smooth_viewtx,
- &(const V3D_SmoothParams) {
- .camera_old = camera_old, .camera = v3d->camera,
- .ofs = rv3d->ofs, .quat = rv3d->viewquat,
- .dist = &rv3d->dist, .lens = &v3d->lens,
- });
- }
-
- if (v3d->scenelock) {
- sync_viewport_camera_smoothview(C, v3d, ob, smooth_viewtx);
- WM_event_add_notifier(C, NC_SCENE, scene);
- }
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
- }
-
- return OPERATOR_FINISHED;
+ View3D *v3d;
+ ARegion *ar;
+ RegionView3D *rv3d;
+
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+
+ 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;
+
+ if (ob) {
+ Object *camera_old = (rv3d->persp == RV3D_CAMOB) ? V3D_CAMERA_SCENE(scene, v3d) : NULL;
+ rv3d->persp = RV3D_CAMOB;
+ v3d->camera = ob;
+ if (v3d->scenelock && scene->camera != ob) {
+ scene->camera = ob;
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ }
+
+ /* unlikely but looks like a glitch when set to the same */
+ if (camera_old != ob) {
+ ED_view3d_lastview_store(rv3d);
+
+ ED_view3d_smooth_view(C,
+ v3d,
+ ar,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .camera_old = camera_old,
+ .camera = v3d->camera,
+ .ofs = rv3d->ofs,
+ .quat = rv3d->viewquat,
+ .dist = &rv3d->dist,
+ .lens = &v3d->lens,
+ });
+ }
+
+ if (v3d->scenelock) {
+ sync_viewport_camera_smoothview(C, v3d, ob, smooth_viewtx);
+ WM_event_add_notifier(C, NC_SCENE, scene);
+ }
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
+ }
+
+ return OPERATOR_FINISHED;
}
bool ED_operator_rv3d_user_region_poll(bContext *C)
{
- View3D *v3d_dummy;
- ARegion *ar_dummy;
+ View3D *v3d_dummy;
+ ARegion *ar_dummy;
- return ED_view3d_context_user_region(C, &v3d_dummy, &ar_dummy);
+ return ED_view3d_context_user_region(C, &v3d_dummy, &ar_dummy);
}
void VIEW3D_OT_object_as_camera(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Active Object as Camera";
- ot->description = "Set the active object as the active camera for this view or scene";
- ot->idname = "VIEW3D_OT_object_as_camera";
+ /* identifiers */
+ ot->name = "Set Active Object as Camera";
+ ot->description = "Set the active object as the active camera for this view or scene";
+ ot->idname = "VIEW3D_OT_object_as_camera";
- /* api callbacks */
- ot->exec = view3d_setobjectascamera_exec;
- ot->poll = ED_operator_rv3d_user_region_poll;
+ /* api callbacks */
+ ot->exec = view3d_setobjectascamera_exec;
+ ot->poll = ED_operator_rv3d_user_region_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -712,51 +729,54 @@ void VIEW3D_OT_object_as_camera(wmOperatorType *ot)
*/
void view3d_winmatrix_set(Depsgraph *depsgraph, ARegion *ar, const View3D *v3d, const rcti *rect)
{
- RegionView3D *rv3d = ar->regiondata;
- rctf viewplane;
- float clipsta, clipend;
- bool is_ortho;
+ RegionView3D *rv3d = ar->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);
- rv3d->is_persp = !is_ortho;
+ is_ortho = ED_view3d_viewplane_get(
+ depsgraph, v3d, rv3d, ar->winx, ar->winy, &viewplane, &clipsta, &clipend, NULL);
+ rv3d->is_persp = !is_ortho;
#if 0
- printf("%s: %d %d %f %f %f %f %f %f\n", __func__, winx, winy,
- viewplane.xmin, viewplane.ymin, viewplane.xmax, viewplane.ymax,
- clipsta, clipend);
+ printf("%s: %d %d %f %f %f %f %f %f\n", __func__, winx, winy,
+ viewplane.xmin, viewplane.ymin, viewplane.xmax, viewplane.ymax,
+ clipsta, clipend);
#endif
- 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));
- viewplane = r;
- }
-
- if (is_ortho) {
- GPU_matrix_ortho_set(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
- }
- else {
- GPU_matrix_frustum_set(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
- }
-
- /* update matrix in 3d view region */
- GPU_matrix_projection_get(rv3d->winmat);
+ 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));
+ viewplane = r;
+ }
+
+ if (is_ortho) {
+ GPU_matrix_ortho_set(
+ viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
+ }
+ else {
+ GPU_matrix_frustum_set(
+ viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
+ }
+
+ /* update matrix in 3d view region */
+ GPU_matrix_projection_get(rv3d->winmat);
}
static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob)
{
- float bmat[4][4];
+ float bmat[4][4];
- rv3d->view = RV3D_VIEW_USER; /* don't show the grid */
+ rv3d->view = RV3D_VIEW_USER; /* don't show the grid */
- normalize_m4_m4(bmat, ob->obmat);
- invert_m4_m4(rv3d->viewmat, bmat);
+ normalize_m4_m4(bmat, ob->obmat);
+ invert_m4_m4(rv3d->viewmat, bmat);
- /* view quat calculation, needed for add object */
- mat4_normalized_to_quat(rv3d->viewquat, rv3d->viewmat);
+ /* view quat calculation, needed for add object */
+ mat4_normalized_to_quat(rv3d->viewquat, rv3d->viewmat);
}
/**
@@ -771,86 +791,87 @@ 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 View3D *v3d, RegionView3D *rv3d, const float rect_scale[2])
+void view3d_viewmatrix_set(Depsgraph *depsgraph,
+ Scene *scene,
+ const View3D *v3d,
+ RegionView3D *rv3d,
+ const float rect_scale[2])
{
- if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */
- if (v3d->camera) {
- Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
- obmat_to_viewmat(rv3d, ob_camera_eval);
- }
- else {
- quat_to_mat4(rv3d->viewmat, rv3d->viewquat);
- rv3d->viewmat[3][2] -= rv3d->dist;
- }
- }
- else {
- bool use_lock_ofs = false;
-
-
- /* should be moved to better initialize later on XXX */
- if (rv3d->viewlock & RV3D_LOCKED) {
- ED_view3d_lock(rv3d);
- }
-
- quat_to_mat4(rv3d->viewmat, rv3d->viewquat);
- 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);
- 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 (pchan) {
- copy_v3_v3(vec, pchan->pose_mat[3]);
- mul_m4_v3(ob_eval->obmat, vec);
- }
- }
- translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
- use_lock_ofs = true;
- }
- else if (v3d->ob_centre_cursor) {
- float vec[3];
- copy_v3_v3(vec, scene->cursor.location);
- translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
- use_lock_ofs = true;
- }
- else {
- translate_m4(rv3d->viewmat, rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2]);
- }
-
- /* lock offset */
- if (use_lock_ofs) {
- float persmat[4][4], persinv[4][4];
- float vec[3];
-
- /* we could calculate the real persmat/persinv here
- * but it would be unreliable so better to later */
- mul_m4_m4m4(persmat, rv3d->winmat, rv3d->viewmat);
- invert_m4_m4(persinv, persmat);
-
- mul_v2_v2fl(vec, rv3d->ofs_lock, rv3d->is_persp ? rv3d->dist : 1.0f);
- vec[2] = 0.0f;
-
- if (rect_scale) {
- /* Since 'RegionView3D.winmat' has been calculated and this function doesn't take the 'ARegion'
- * we don't know about the region size.
- * Use 'rect_scale' when drawing a sub-region to apply 2D offset,
- * scaled by the difference between the sub-region and the region size.
- */
- vec[0] /= rect_scale[0];
- vec[1] /= rect_scale[1];
- }
-
- mul_mat3_m4_v3(persinv, vec);
- translate_m4(rv3d->viewmat, vec[0], vec[1], vec[2]);
- }
- /* end lock offset */
- }
+ if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */
+ if (v3d->camera) {
+ Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
+ obmat_to_viewmat(rv3d, ob_camera_eval);
+ }
+ else {
+ quat_to_mat4(rv3d->viewmat, rv3d->viewquat);
+ rv3d->viewmat[3][2] -= rv3d->dist;
+ }
+ }
+ else {
+ bool use_lock_ofs = false;
+
+ /* should be moved to better initialize later on XXX */
+ if (rv3d->viewlock & RV3D_LOCKED) {
+ ED_view3d_lock(rv3d);
+ }
+
+ quat_to_mat4(rv3d->viewmat, rv3d->viewquat);
+ 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);
+ 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 (pchan) {
+ copy_v3_v3(vec, pchan->pose_mat[3]);
+ mul_m4_v3(ob_eval->obmat, vec);
+ }
+ }
+ translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
+ use_lock_ofs = true;
+ }
+ else if (v3d->ob_centre_cursor) {
+ float vec[3];
+ copy_v3_v3(vec, scene->cursor.location);
+ translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
+ use_lock_ofs = true;
+ }
+ else {
+ translate_m4(rv3d->viewmat, rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2]);
+ }
+
+ /* lock offset */
+ if (use_lock_ofs) {
+ float persmat[4][4], persinv[4][4];
+ float vec[3];
+
+ /* we could calculate the real persmat/persinv here
+ * but it would be unreliable so better to later */
+ mul_m4_m4m4(persmat, rv3d->winmat, rv3d->viewmat);
+ invert_m4_m4(persinv, persmat);
+
+ mul_v2_v2fl(vec, rv3d->ofs_lock, rv3d->is_persp ? rv3d->dist : 1.0f);
+ vec[2] = 0.0f;
+
+ if (rect_scale) {
+ /* Since 'RegionView3D.winmat' has been calculated and this function doesn't take the 'ARegion'
+ * we don't know about the region size.
+ * Use 'rect_scale' when drawing a sub-region to apply 2D offset,
+ * scaled by the difference between the sub-region and the region size.
+ */
+ vec[0] /= rect_scale[0];
+ vec[1] /= rect_scale[1];
+ }
+
+ mul_mat3_m4_v3(persinv, vec);
+ translate_m4(rv3d->viewmat, vec[0], vec[1], vec[2]);
+ }
+ /* end lock offset */
+ }
}
/** \} */
@@ -866,77 +887,76 @@ void view3d_viewmatrix_set(
*/
void view3d_opengl_select_cache_begin(void)
{
- GPU_select_cache_begin();
+ GPU_select_cache_begin();
}
void view3d_opengl_select_cache_end(void)
{
- GPU_select_cache_end();
+ GPU_select_cache_end();
}
struct DrawSelectLoopUserData {
- uint pass;
- uint hits;
- uint *buffer;
- uint buffer_len;
- const rcti *rect;
- char gpu_select_mode;
+ uint pass;
+ uint hits;
+ uint *buffer;
+ uint buffer_len;
+ const rcti *rect;
+ char gpu_select_mode;
};
static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data)
{
- bool continue_pass = false;
- struct DrawSelectLoopUserData *data = user_data;
- if (stage == DRW_SELECT_PASS_PRE) {
- GPU_select_begin(data->buffer, data->buffer_len, data->rect, data->gpu_select_mode, data->hits);
- /* always run POST after PRE. */
- continue_pass = true;
- }
- else if (stage == DRW_SELECT_PASS_POST) {
- int hits = GPU_select_end();
- if (data->pass == 0) {
- /* quirk of GPU_select_end, only take hits value from first call. */
- data->hits = hits;
- }
- if (data->gpu_select_mode == GPU_SELECT_NEAREST_FIRST_PASS) {
- data->gpu_select_mode = GPU_SELECT_NEAREST_SECOND_PASS;
- continue_pass = (hits > 0);
- }
- data->pass += 1;
- }
- else {
- BLI_assert(0);
- }
- return continue_pass;
-
+ bool continue_pass = false;
+ struct DrawSelectLoopUserData *data = user_data;
+ if (stage == DRW_SELECT_PASS_PRE) {
+ GPU_select_begin(
+ data->buffer, data->buffer_len, data->rect, data->gpu_select_mode, data->hits);
+ /* always run POST after PRE. */
+ continue_pass = true;
+ }
+ else if (stage == DRW_SELECT_PASS_POST) {
+ int hits = GPU_select_end();
+ if (data->pass == 0) {
+ /* quirk of GPU_select_end, only take hits value from first call. */
+ data->hits = hits;
+ }
+ if (data->gpu_select_mode == GPU_SELECT_NEAREST_FIRST_PASS) {
+ data->gpu_select_mode = GPU_SELECT_NEAREST_SECOND_PASS;
+ continue_pass = (hits > 0);
+ }
+ data->pass += 1;
+ }
+ else {
+ BLI_assert(0);
+ }
+ return continue_pass;
}
eV3DSelectObjectFilter ED_view3d_select_filter_from_mode(const Scene *scene, const Object *obact)
{
- if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
- if (obact && (obact->mode & OB_MODE_WEIGHT_PAINT) &&
- BKE_object_pose_armature_get((Object *)obact))
- {
- return VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK;
- }
- return VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK;
- }
- return VIEW3D_SELECT_FILTER_NOP;
+ if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ if (obact && (obact->mode & OB_MODE_WEIGHT_PAINT) &&
+ BKE_object_pose_armature_get((Object *)obact)) {
+ return VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK;
+ }
+ return VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK;
+ }
+ return VIEW3D_SELECT_FILTER_NOP;
}
/** Implement #VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK. */
static bool drw_select_filter_object_mode_lock(Object *ob, void *user_data)
{
- const Object *obact = user_data;
- return BKE_object_is_mode_compat(ob, obact->mode);
+ const Object *obact = user_data;
+ return BKE_object_is_mode_compat(ob, obact->mode);
}
/** Implement #VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK for special case when
* we want to select pose bones (this doesn't switch modes). */
static bool drw_select_filter_object_mode_lock_for_weight_paint(Object *ob, void *user_data)
{
- const Object *ob_pose = user_data;
- return (DEG_get_original_object(ob) == ob_pose);
+ const Object *ob_pose = user_data;
+ return (DEG_get_original_object(ob) == ob_pose);
}
/**
@@ -946,184 +966,196 @@ static bool drw_select_filter_object_mode_lock_for_weight_paint(Object *ob, void
*
* \note (vc->obedit == NULL) can be set to explicitly skip edit-object selection.
*/
-int view3d_opengl_select(
- ViewContext *vc, uint *buffer, uint bufsize, const rcti *input,
- eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter)
+int view3d_opengl_select(ViewContext *vc,
+ uint *buffer,
+ uint bufsize,
+ const rcti *input,
+ eV3DSelectMode select_mode,
+ eV3DSelectObjectFilter select_filter)
{
- struct bThemeState theme_state;
- Depsgraph *depsgraph = vc->depsgraph;
- Scene *scene = vc->scene;
- View3D *v3d = vc->v3d;
- ARegion *ar = vc->ar;
- rcti rect;
- int hits = 0;
- const bool use_obedit_skip = (OBEDIT_FROM_VIEW_LAYER(vc->view_layer) != NULL) && (vc->obedit == NULL);
- const bool is_pick_select = (U.gpu_flag & USER_GPU_FLAG_NO_DEPT_PICK) == 0;
- const bool do_passes = (
- (is_pick_select == false) &&
- (select_mode == VIEW3D_SELECT_PICK_NEAREST));
- const bool use_nearest = (is_pick_select && select_mode == VIEW3D_SELECT_PICK_NEAREST);
- bool draw_surface = true;
-
- char gpu_select_mode;
-
- /* case not a box select */
- if (input->xmin == input->xmax) {
- /* seems to be default value for bones only now */
- BLI_rcti_init_pt_radius(&rect, (const int[2]){input->xmin, input->ymin}, 12);
- }
- else {
- rect = *input;
- }
-
- if (is_pick_select) {
- if (is_pick_select && select_mode == VIEW3D_SELECT_PICK_NEAREST) {
- gpu_select_mode = GPU_SELECT_PICK_NEAREST;
- }
- else if (is_pick_select && select_mode == VIEW3D_SELECT_PICK_ALL) {
- gpu_select_mode = GPU_SELECT_PICK_ALL;
- }
- else {
- gpu_select_mode = GPU_SELECT_ALL;
- }
- }
- else {
- if (do_passes) {
- gpu_select_mode = GPU_SELECT_NEAREST_FIRST_PASS;
- }
- else {
- gpu_select_mode = GPU_SELECT_ALL;
- }
- }
-
- /* Important to use 'vc->obact', not 'OBACT(vc->view_layer)' below,
- * so it will be NULL when hidden. */
- struct {
- DRW_ObjectFilterFn fn;
- void *user_data;
- } object_filter = {NULL, NULL};
- switch (select_filter) {
- case VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK:
- {
- Object *obact = vc->obact;
- if (obact && obact->mode != OB_MODE_OBJECT) {
- object_filter.fn = drw_select_filter_object_mode_lock;
- object_filter.user_data = obact;
- }
- break;
- }
- case VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK:
- {
- Object *obact = vc->obact;
- BLI_assert(obact && (obact->mode & OB_MODE_WEIGHT_PAINT));
- Object *ob_pose = BKE_object_pose_armature_get(obact);
-
- object_filter.fn = drw_select_filter_object_mode_lock_for_weight_paint;
- object_filter.user_data = ob_pose;
- break;
- }
- case VIEW3D_SELECT_FILTER_NOP:
- break;
-
- }
-
- /* Tools may request depth outside of regular drawing code. */
- UI_Theme_Store(&theme_state);
- UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
-
- /* Re-use cache (rect must be smaller then the cached)
- * other context is assumed to be unchanged */
- if (GPU_select_is_cached()) {
- GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0);
- GPU_select_cache_load_id();
- hits = GPU_select_end();
- goto finally;
- }
-
- /* All of the queries need to be perform on the drawing context. */
- DRW_opengl_context_enable();
-
- G.f |= G_FLAG_PICKSEL;
-
- /* 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);
-
- if (!XRAY_ACTIVE(v3d)) {
- GPU_depth_test(true);
- }
-
- if (vc->rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_set(vc->rv3d);
- }
-
- /* If in xray mode, we select the wires in priority. */
- if (XRAY_ACTIVE(v3d) && use_nearest) {
- /* We need to call "GPU_select_*" API's inside DRW_draw_select_loop
- * because the OpenGL context created & destroyed inside this function. */
- struct DrawSelectLoopUserData drw_select_loop_user_data = {
- .pass = 0,
- .hits = 0,
- .buffer = buffer,
- .buffer_len = bufsize,
- .rect = &rect,
- .gpu_select_mode = gpu_select_mode,
- };
- draw_surface = false;
- DRW_draw_select_loop(
- depsgraph, ar, v3d,
- use_obedit_skip, draw_surface, use_nearest, &rect,
- drw_select_loop_pass, &drw_select_loop_user_data,
- object_filter.fn, object_filter.user_data);
- hits = drw_select_loop_user_data.hits;
- /* FIX: This cleanup the state before doing another selection pass.
- * (see T56695) */
- GPU_select_cache_end();
- }
-
- if (hits == 0) {
- /* We need to call "GPU_select_*" API's inside DRW_draw_select_loop
- * because the OpenGL context created & destroyed inside this function. */
- struct DrawSelectLoopUserData drw_select_loop_user_data = {
- .pass = 0,
- .hits = 0,
- .buffer = buffer,
- .buffer_len = bufsize,
- .rect = &rect,
- .gpu_select_mode = gpu_select_mode,
- };
- /* 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, v3d,
- use_obedit_skip, draw_surface, use_nearest, &rect,
- drw_select_loop_pass, &drw_select_loop_user_data,
- object_filter.fn, object_filter.user_data);
- hits = drw_select_loop_user_data.hits;
- }
-
- G.f &= ~G_FLAG_PICKSEL;
- ED_view3d_draw_setup_view(vc->win, depsgraph, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL);
-
- if (!XRAY_ACTIVE(v3d)) {
- GPU_depth_test(false);
- }
-
- if (vc->rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_disable();
- }
-
- DRW_opengl_context_disable();
+ struct bThemeState theme_state;
+ Depsgraph *depsgraph = vc->depsgraph;
+ Scene *scene = vc->scene;
+ View3D *v3d = vc->v3d;
+ ARegion *ar = vc->ar;
+ rcti rect;
+ int hits = 0;
+ const bool use_obedit_skip = (OBEDIT_FROM_VIEW_LAYER(vc->view_layer) != NULL) &&
+ (vc->obedit == NULL);
+ const bool is_pick_select = (U.gpu_flag & USER_GPU_FLAG_NO_DEPT_PICK) == 0;
+ const bool do_passes = ((is_pick_select == false) &&
+ (select_mode == VIEW3D_SELECT_PICK_NEAREST));
+ const bool use_nearest = (is_pick_select && select_mode == VIEW3D_SELECT_PICK_NEAREST);
+ bool draw_surface = true;
+
+ char gpu_select_mode;
+
+ /* case not a box select */
+ if (input->xmin == input->xmax) {
+ /* seems to be default value for bones only now */
+ BLI_rcti_init_pt_radius(&rect, (const int[2]){input->xmin, input->ymin}, 12);
+ }
+ else {
+ rect = *input;
+ }
+
+ if (is_pick_select) {
+ if (is_pick_select && select_mode == VIEW3D_SELECT_PICK_NEAREST) {
+ gpu_select_mode = GPU_SELECT_PICK_NEAREST;
+ }
+ else if (is_pick_select && select_mode == VIEW3D_SELECT_PICK_ALL) {
+ gpu_select_mode = GPU_SELECT_PICK_ALL;
+ }
+ else {
+ gpu_select_mode = GPU_SELECT_ALL;
+ }
+ }
+ else {
+ if (do_passes) {
+ gpu_select_mode = GPU_SELECT_NEAREST_FIRST_PASS;
+ }
+ else {
+ gpu_select_mode = GPU_SELECT_ALL;
+ }
+ }
+
+ /* Important to use 'vc->obact', not 'OBACT(vc->view_layer)' below,
+ * so it will be NULL when hidden. */
+ struct {
+ DRW_ObjectFilterFn fn;
+ void *user_data;
+ } object_filter = {NULL, NULL};
+ switch (select_filter) {
+ case VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK: {
+ Object *obact = vc->obact;
+ if (obact && obact->mode != OB_MODE_OBJECT) {
+ object_filter.fn = drw_select_filter_object_mode_lock;
+ object_filter.user_data = obact;
+ }
+ break;
+ }
+ case VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK: {
+ Object *obact = vc->obact;
+ BLI_assert(obact && (obact->mode & OB_MODE_WEIGHT_PAINT));
+ Object *ob_pose = BKE_object_pose_armature_get(obact);
+
+ object_filter.fn = drw_select_filter_object_mode_lock_for_weight_paint;
+ object_filter.user_data = ob_pose;
+ break;
+ }
+ case VIEW3D_SELECT_FILTER_NOP:
+ break;
+ }
+
+ /* Tools may request depth outside of regular drawing code. */
+ UI_Theme_Store(&theme_state);
+ UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
+
+ /* Re-use cache (rect must be smaller then the cached)
+ * other context is assumed to be unchanged */
+ if (GPU_select_is_cached()) {
+ GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0);
+ GPU_select_cache_load_id();
+ hits = GPU_select_end();
+ goto finally;
+ }
+
+ /* All of the queries need to be perform on the drawing context. */
+ DRW_opengl_context_enable();
+
+ G.f |= G_FLAG_PICKSEL;
+
+ /* 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);
+
+ if (!XRAY_ACTIVE(v3d)) {
+ GPU_depth_test(true);
+ }
+
+ if (vc->rv3d->rflag & RV3D_CLIPPING) {
+ ED_view3d_clipping_set(vc->rv3d);
+ }
+
+ /* If in xray mode, we select the wires in priority. */
+ if (XRAY_ACTIVE(v3d) && use_nearest) {
+ /* We need to call "GPU_select_*" API's inside DRW_draw_select_loop
+ * because the OpenGL context created & destroyed inside this function. */
+ struct DrawSelectLoopUserData drw_select_loop_user_data = {
+ .pass = 0,
+ .hits = 0,
+ .buffer = buffer,
+ .buffer_len = bufsize,
+ .rect = &rect,
+ .gpu_select_mode = gpu_select_mode,
+ };
+ draw_surface = false;
+ DRW_draw_select_loop(depsgraph,
+ ar,
+ v3d,
+ use_obedit_skip,
+ draw_surface,
+ use_nearest,
+ &rect,
+ drw_select_loop_pass,
+ &drw_select_loop_user_data,
+ object_filter.fn,
+ object_filter.user_data);
+ hits = drw_select_loop_user_data.hits;
+ /* FIX: This cleanup the state before doing another selection pass.
+ * (see T56695) */
+ GPU_select_cache_end();
+ }
+
+ if (hits == 0) {
+ /* We need to call "GPU_select_*" API's inside DRW_draw_select_loop
+ * because the OpenGL context created & destroyed inside this function. */
+ struct DrawSelectLoopUserData drw_select_loop_user_data = {
+ .pass = 0,
+ .hits = 0,
+ .buffer = buffer,
+ .buffer_len = bufsize,
+ .rect = &rect,
+ .gpu_select_mode = gpu_select_mode,
+ };
+ /* 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,
+ v3d,
+ use_obedit_skip,
+ draw_surface,
+ use_nearest,
+ &rect,
+ drw_select_loop_pass,
+ &drw_select_loop_user_data,
+ object_filter.fn,
+ object_filter.user_data);
+ hits = drw_select_loop_user_data.hits;
+ }
+
+ G.f &= ~G_FLAG_PICKSEL;
+ ED_view3d_draw_setup_view(vc->win, depsgraph, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL);
+
+ if (!XRAY_ACTIVE(v3d)) {
+ GPU_depth_test(false);
+ }
+
+ if (vc->rv3d->rflag & RV3D_CLIPPING) {
+ ED_view3d_clipping_disable();
+ }
+
+ DRW_opengl_context_disable();
finally:
- if (hits < 0) {
- printf("Too many objects in select buffer\n"); /* XXX make error message */
- }
+ if (hits < 0) {
+ printf("Too many objects in select buffer\n"); /* XXX make error message */
+ }
- UI_Theme_Restore(&theme_state);
+ UI_Theme_Restore(&theme_state);
- return hits;
+ return hits;
}
/** \} */
@@ -1134,332 +1166,348 @@ finally:
static uint free_localbit(Main *bmain)
{
- ScrArea *sa;
- bScreen *sc;
-
- 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 (; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *) sl;
- if (v3d->localvd) {
- local_view_bits |= v3d->local_view_uuid;
- }
- }
- }
- }
- }
-
- for (int i = 0; i < 16; i++) {
- if ((local_view_bits & (1 << i)) == 0) {
- return (1 << i);
- }
- }
-
- return 0;
+ ScrArea *sa;
+ bScreen *sc;
+
+ 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 (; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ if (v3d->localvd) {
+ local_view_bits |= v3d->local_view_uuid;
+ }
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < 16; i++) {
+ if ((local_view_bits & (1 << i)) == 0) {
+ return (1 << i);
+ }
+ }
+
+ return 0;
}
-static bool view3d_localview_init(
- const Depsgraph *depsgraph,
- wmWindowManager *wm,
- wmWindow *win,
- Main *bmain,
- ViewLayer *view_layer,
- ScrArea *sa,
- const bool frame_selected,
- const int smooth_viewtx,
- ReportList *reports)
+static bool view3d_localview_init(const Depsgraph *depsgraph,
+ wmWindowManager *wm,
+ wmWindow *win,
+ Main *bmain,
+ ViewLayer *view_layer,
+ ScrArea *sa,
+ const bool frame_selected,
+ const int smooth_viewtx,
+ ReportList *reports)
{
- View3D *v3d = sa->spacedata.first;
- Base *base;
- float min[3], max[3], box[3];
- float size = 0.0f;
- uint local_view_bit;
- bool ok = false;
-
- if (v3d->localvd) {
- return ok;
- }
-
- INIT_MINMAX(min, max);
-
- local_view_bit = free_localbit(bmain);
-
- if (local_view_bit == 0) {
- /* TODO(dfelinto): We can kick one of the other 3D views out of local view
- specially if it is not being used. */
- BKE_report(reports, RPT_ERROR, "No more than 16 local views");
- ok = false;
- }
- else {
- Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
- if (obedit) {
- FOREACH_BASE_IN_EDIT_MODE_BEGIN(view_layer, v3d, base_iter) {
- BKE_object_minmax(base_iter->object, min, max, false);
- base_iter->local_view_bits |= local_view_bit;
- ok = true;
- } FOREACH_BASE_IN_EDIT_MODE_END;
- }
- else {
- for (base = FIRSTBASE(view_layer); base; base = base->next) {
- if (BASE_SELECTED(v3d, base)) {
- BKE_object_minmax(base->object, min, max, false);
- base->local_view_bits |= local_view_bit;
- ok = true;
- }
- }
- }
-
- sub_v3_v3v3(box, max, min);
- size = max_fff(box[0], box[1], box[2]);
- }
-
- if (ok == false) {
- return false;
- }
-
- ARegion *ar;
-
- 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;
- bool ok_dist = true;
-
- /* New view values. */
- Object *camera_old = NULL;
- float dist_new, ofs_new[3];
-
- rv3d->localvd = MEM_mallocN(sizeof(RegionView3D), "localview region");
- memcpy(rv3d->localvd, rv3d, sizeof(RegionView3D));
-
- if (frame_selected) {
- float mid[3];
- mid_v3_v3v3(mid, min, max);
- negate_v3_v3(ofs_new, mid);
-
- if (rv3d->persp == RV3D_CAMOB) {
- rv3d->persp = RV3D_PERSP;
- camera_old = v3d->camera;
- }
-
- if (rv3d->persp == RV3D_ORTHO) {
- if (size < 0.0001f) {
- ok_dist = false;
- }
- }
-
- if (ok_dist) {
- dist_new = ED_view3d_radius_to_dist(v3d, ar, depsgraph, rv3d->persp, true, (size / 2) * VIEW3D_MARGIN);
-
- if (rv3d->persp == RV3D_PERSP) {
- /* Don't zoom closer than the near clipping plane. */
- dist_new = max_ff(dist_new, v3d->clip_start * 1.5f);
- }
- }
-
- ED_view3d_smooth_view_ex(
- depsgraph,
- wm, win, sa, v3d, ar, smooth_viewtx,
- &(const V3D_SmoothParams) {
- .camera_old = camera_old,
- .ofs = ofs_new, .quat = rv3d->viewquat,
- .dist = ok_dist ? &dist_new : NULL, .lens = &v3d->lens,
- });
- }
- }
- }
-
- return ok;
+ View3D *v3d = sa->spacedata.first;
+ Base *base;
+ float min[3], max[3], box[3];
+ float size = 0.0f;
+ uint local_view_bit;
+ bool ok = false;
+
+ if (v3d->localvd) {
+ return ok;
+ }
+
+ INIT_MINMAX(min, max);
+
+ local_view_bit = free_localbit(bmain);
+
+ if (local_view_bit == 0) {
+ /* TODO(dfelinto): We can kick one of the other 3D views out of local view
+ specially if it is not being used. */
+ BKE_report(reports, RPT_ERROR, "No more than 16 local views");
+ ok = false;
+ }
+ else {
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
+ if (obedit) {
+ FOREACH_BASE_IN_EDIT_MODE_BEGIN (view_layer, v3d, base_iter) {
+ BKE_object_minmax(base_iter->object, min, max, false);
+ base_iter->local_view_bits |= local_view_bit;
+ ok = true;
+ }
+ FOREACH_BASE_IN_EDIT_MODE_END;
+ }
+ else {
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
+ if (BASE_SELECTED(v3d, base)) {
+ BKE_object_minmax(base->object, min, max, false);
+ base->local_view_bits |= local_view_bit;
+ ok = true;
+ }
+ }
+ }
+
+ sub_v3_v3v3(box, max, min);
+ size = max_fff(box[0], box[1], box[2]);
+ }
+
+ if (ok == false) {
+ return false;
+ }
+
+ ARegion *ar;
+
+ 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;
+ bool ok_dist = true;
+
+ /* New view values. */
+ Object *camera_old = NULL;
+ float dist_new, ofs_new[3];
+
+ rv3d->localvd = MEM_mallocN(sizeof(RegionView3D), "localview region");
+ memcpy(rv3d->localvd, rv3d, sizeof(RegionView3D));
+
+ if (frame_selected) {
+ float mid[3];
+ mid_v3_v3v3(mid, min, max);
+ negate_v3_v3(ofs_new, mid);
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ rv3d->persp = RV3D_PERSP;
+ camera_old = v3d->camera;
+ }
+
+ if (rv3d->persp == RV3D_ORTHO) {
+ if (size < 0.0001f) {
+ ok_dist = false;
+ }
+ }
+
+ if (ok_dist) {
+ dist_new = ED_view3d_radius_to_dist(
+ v3d, ar, depsgraph, rv3d->persp, true, (size / 2) * VIEW3D_MARGIN);
+
+ if (rv3d->persp == RV3D_PERSP) {
+ /* Don't zoom closer than the near clipping plane. */
+ dist_new = max_ff(dist_new, v3d->clip_start * 1.5f);
+ }
+ }
+
+ ED_view3d_smooth_view_ex(depsgraph,
+ wm,
+ win,
+ sa,
+ v3d,
+ ar,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .camera_old = camera_old,
+ .ofs = ofs_new,
+ .quat = rv3d->viewquat,
+ .dist = ok_dist ? &dist_new : NULL,
+ .lens = &v3d->lens,
+ });
+ }
+ }
+ }
+
+ return ok;
}
-static void view3d_localview_exit(
- const Depsgraph *depsgraph,
- wmWindowManager *wm,
- wmWindow *win,
- ViewLayer *view_layer,
- ScrArea *sa,
- const bool frame_selected,
- const int smooth_viewtx)
+static void view3d_localview_exit(const Depsgraph *depsgraph,
+ wmWindowManager *wm,
+ wmWindow *win,
+ ViewLayer *view_layer,
+ ScrArea *sa,
+ const bool frame_selected,
+ const int smooth_viewtx)
{
- View3D *v3d = sa->spacedata.first;
-
- if (v3d->localvd == NULL) {
- return;
- }
-
- for (Base *base = FIRSTBASE(view_layer); base; base = base->next) {
- if (base->local_view_bits & v3d->local_view_uuid) {
- base->local_view_bits &= ~v3d->local_view_uuid;
- }
- }
-
- Object *camera_old = v3d->camera;
- Object *camera_new = v3d->localvd->camera;
-
- v3d->local_view_uuid = 0;
- v3d->camera = v3d->localvd->camera;
-
- 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;
-
- if (rv3d->localvd == NULL) {
- continue;
- }
-
- if (frame_selected) {
- Object *camera_old_rv3d, *camera_new_rv3d;
-
- camera_old_rv3d = (rv3d->persp == RV3D_CAMOB) ? camera_old : NULL;
- camera_new_rv3d = (rv3d->localvd->persp == RV3D_CAMOB) ? camera_new : NULL;
-
- rv3d->view = rv3d->localvd->view;
- rv3d->persp = rv3d->localvd->persp;
- rv3d->camzoom = rv3d->localvd->camzoom;
-
- ED_view3d_smooth_view_ex(
- depsgraph,
- wm, win, sa,
- v3d, ar, smooth_viewtx,
- &(const V3D_SmoothParams) {
- .camera_old = camera_old_rv3d, .camera = camera_new_rv3d,
- .ofs = rv3d->localvd->ofs, .quat = rv3d->localvd->viewquat,
- .dist = &rv3d->localvd->dist,
- });
- }
-
- MEM_freeN(rv3d->localvd);
- rv3d->localvd = NULL;
- }
- }
+ View3D *v3d = sa->spacedata.first;
+
+ if (v3d->localvd == NULL) {
+ return;
+ }
+
+ for (Base *base = FIRSTBASE(view_layer); base; base = base->next) {
+ if (base->local_view_bits & v3d->local_view_uuid) {
+ base->local_view_bits &= ~v3d->local_view_uuid;
+ }
+ }
+
+ Object *camera_old = v3d->camera;
+ Object *camera_new = v3d->localvd->camera;
+
+ v3d->local_view_uuid = 0;
+ v3d->camera = v3d->localvd->camera;
+
+ 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;
+
+ if (rv3d->localvd == NULL) {
+ continue;
+ }
+
+ if (frame_selected) {
+ Object *camera_old_rv3d, *camera_new_rv3d;
+
+ camera_old_rv3d = (rv3d->persp == RV3D_CAMOB) ? camera_old : NULL;
+ camera_new_rv3d = (rv3d->localvd->persp == RV3D_CAMOB) ? camera_new : NULL;
+
+ rv3d->view = rv3d->localvd->view;
+ rv3d->persp = rv3d->localvd->persp;
+ rv3d->camzoom = rv3d->localvd->camzoom;
+
+ ED_view3d_smooth_view_ex(depsgraph,
+ wm,
+ win,
+ sa,
+ v3d,
+ ar,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .camera_old = camera_old_rv3d,
+ .camera = camera_new_rv3d,
+ .ofs = rv3d->localvd->ofs,
+ .quat = rv3d->localvd->viewquat,
+ .dist = &rv3d->localvd->dist,
+ });
+ }
+
+ MEM_freeN(rv3d->localvd);
+ rv3d->localvd = NULL;
+ }
+ }
}
static int localview_exec(bContext *C, wmOperator *op)
{
- const Depsgraph *depsgraph = CTX_data_depsgraph(C);
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
- 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);
- 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);
- changed = true;
- }
- else {
- changed = view3d_localview_init(depsgraph, wm, win, bmain, view_layer, sa, frame_selected, smooth_viewtx, op->reports);
- }
-
- if (changed) {
- DEG_id_type_tag(bmain, ID_OB);
- ED_area_tag_redraw(sa);
-
- /* Unselected objects become selected when exiting. */
- if (v3d->localvd == NULL) {
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
- else {
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
- }
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+ 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);
+ 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);
+ changed = true;
+ }
+ else {
+ changed = view3d_localview_init(
+ depsgraph, wm, win, bmain, view_layer, sa, frame_selected, smooth_viewtx, op->reports);
+ }
+
+ if (changed) {
+ DEG_id_type_tag(bmain, ID_OB);
+ ED_area_tag_redraw(sa);
+
+ /* Unselected objects become selected when exiting. */
+ if (v3d->localvd == NULL) {
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ }
+ else {
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+ }
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void VIEW3D_OT_localview(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Local View";
- ot->description = "Toggle display of selected object(s) separately and centered in view";
- ot->idname = "VIEW3D_OT_localview";
-
- /* api callbacks */
- ot->exec = localview_exec;
- ot->flag = OPTYPE_UNDO; /* localview changes object layer bitflags */
-
- ot->poll = ED_operator_view3d_active;
-
- RNA_def_boolean(ot->srna, "frame_selected", true, "Frame Selected", "Move the view to frame the selected objects");
+ /* identifiers */
+ ot->name = "Local View";
+ ot->description = "Toggle display of selected object(s) separately and centered in view";
+ ot->idname = "VIEW3D_OT_localview";
+
+ /* api callbacks */
+ ot->exec = localview_exec;
+ ot->flag = OPTYPE_UNDO; /* localview changes object layer bitflags */
+
+ ot->poll = ED_operator_view3d_active;
+
+ RNA_def_boolean(ot->srna,
+ "frame_selected",
+ true,
+ "Frame Selected",
+ "Move the view to frame the selected objects");
}
static int localview_remove_from_exec(bContext *C, wmOperator *op)
{
- View3D *v3d = CTX_wm_view3d(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- bool changed = false;
-
- for (Base *base = FIRSTBASE(view_layer); base; base = base->next) {
- if (BASE_SELECTED(v3d, base)) {
- base->local_view_bits &= ~v3d->local_view_uuid;
- ED_object_base_select(base, BA_DESELECT);
-
- if (base == BASACT(view_layer)) {
- view_layer->basact = NULL;
- }
- changed = true;
- }
- }
-
- if (changed) {
- DEG_on_visible_update(bmain, false);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
- return OPERATOR_FINISHED;
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "No object selected");
- return OPERATOR_CANCELLED;
- }
+ View3D *v3d = CTX_wm_view3d(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ bool changed = false;
+
+ for (Base *base = FIRSTBASE(view_layer); base; base = base->next) {
+ if (BASE_SELECTED(v3d, base)) {
+ base->local_view_bits &= ~v3d->local_view_uuid;
+ ED_object_base_select(base, BA_DESELECT);
+
+ if (base == BASACT(view_layer)) {
+ view_layer->basact = NULL;
+ }
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ DEG_on_visible_update(bmain, false);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No object selected");
+ return OPERATOR_CANCELLED;
+ }
}
static bool localview_remove_from_poll(bContext *C)
{
- if (CTX_data_edit_object(C) != NULL) {
- return false;
- }
+ if (CTX_data_edit_object(C) != NULL) {
+ return false;
+ }
- View3D *v3d = CTX_wm_view3d(C);
- return v3d && v3d->localvd;
+ View3D *v3d = CTX_wm_view3d(C);
+ return v3d && v3d->localvd;
}
void VIEW3D_OT_localview_remove_from(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove from Local View";
- ot->description = "Move selected objects out of local view";
- ot->idname = "VIEW3D_OT_localview_remove_from";
-
- /* api callbacks */
- ot->exec = localview_remove_from_exec;
- ot->invoke = WM_operator_confirm;
- ot->poll = localview_remove_from_poll;
- ot->flag = OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Remove from Local View";
+ ot->description = "Move selected objects out of local view";
+ ot->idname = "VIEW3D_OT_localview_remove_from";
+
+ /* api callbacks */
+ ot->exec = localview_remove_from_exec;
+ ot->invoke = WM_operator_confirm;
+ ot->poll = localview_remove_from_poll;
+ ot->flag = OPTYPE_UNDO;
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index a015b7f9945..a0613d3b76f 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -52,7 +52,7 @@
#include "DEG_depsgraph.h"
-#include "view3d_intern.h" /* own include */
+#include "view3d_intern.h" /* own include */
#ifdef WITH_INPUT_NDOF
//# define NDOF_WALK_DEBUG
@@ -71,330 +71,344 @@ static float getVelocityZeroTime(const float gravity, const float velocity);
/* NOTE: these defines are saved in keymap files,
* do not change values but just add new ones */
enum {
- WALK_MODAL_CANCEL = 1,
- WALK_MODAL_CONFIRM,
- WALK_MODAL_DIR_FORWARD,
- WALK_MODAL_DIR_FORWARD_STOP,
- WALK_MODAL_DIR_BACKWARD,
- WALK_MODAL_DIR_BACKWARD_STOP,
- WALK_MODAL_DIR_LEFT,
- WALK_MODAL_DIR_LEFT_STOP,
- WALK_MODAL_DIR_RIGHT,
- WALK_MODAL_DIR_RIGHT_STOP,
- WALK_MODAL_DIR_UP,
- WALK_MODAL_DIR_UP_STOP,
- WALK_MODAL_DIR_DOWN,
- WALK_MODAL_DIR_DOWN_STOP,
- WALK_MODAL_FAST_ENABLE,
- WALK_MODAL_FAST_DISABLE,
- WALK_MODAL_SLOW_ENABLE,
- WALK_MODAL_SLOW_DISABLE,
- WALK_MODAL_JUMP,
- WALK_MODAL_JUMP_STOP,
- WALK_MODAL_TELEPORT,
- WALK_MODAL_TOGGLE,
- WALK_MODAL_ACCELERATE,
- WALK_MODAL_DECELERATE,
+ WALK_MODAL_CANCEL = 1,
+ WALK_MODAL_CONFIRM,
+ WALK_MODAL_DIR_FORWARD,
+ WALK_MODAL_DIR_FORWARD_STOP,
+ WALK_MODAL_DIR_BACKWARD,
+ WALK_MODAL_DIR_BACKWARD_STOP,
+ WALK_MODAL_DIR_LEFT,
+ WALK_MODAL_DIR_LEFT_STOP,
+ WALK_MODAL_DIR_RIGHT,
+ WALK_MODAL_DIR_RIGHT_STOP,
+ WALK_MODAL_DIR_UP,
+ WALK_MODAL_DIR_UP_STOP,
+ WALK_MODAL_DIR_DOWN,
+ WALK_MODAL_DIR_DOWN_STOP,
+ WALK_MODAL_FAST_ENABLE,
+ WALK_MODAL_FAST_DISABLE,
+ WALK_MODAL_SLOW_ENABLE,
+ WALK_MODAL_SLOW_DISABLE,
+ WALK_MODAL_JUMP,
+ WALK_MODAL_JUMP_STOP,
+ WALK_MODAL_TELEPORT,
+ WALK_MODAL_TOGGLE,
+ WALK_MODAL_ACCELERATE,
+ WALK_MODAL_DECELERATE,
};
enum {
- WALK_BIT_FORWARD = 1 << 0,
- WALK_BIT_BACKWARD = 1 << 1,
- WALK_BIT_LEFT = 1 << 2,
- WALK_BIT_RIGHT = 1 << 3,
- WALK_BIT_UP = 1 << 4,
- WALK_BIT_DOWN = 1 << 5,
+ WALK_BIT_FORWARD = 1 << 0,
+ WALK_BIT_BACKWARD = 1 << 1,
+ WALK_BIT_LEFT = 1 << 2,
+ WALK_BIT_RIGHT = 1 << 3,
+ WALK_BIT_UP = 1 << 4,
+ WALK_BIT_DOWN = 1 << 5,
};
typedef enum eWalkTeleportState {
- WALK_TELEPORT_STATE_OFF = 0,
- WALK_TELEPORT_STATE_ON,
+ WALK_TELEPORT_STATE_OFF = 0,
+ WALK_TELEPORT_STATE_ON,
} eWalkTeleportState;
typedef enum eWalkMethod {
- WALK_MODE_FREE = 0,
- WALK_MODE_GRAVITY,
+ WALK_MODE_FREE = 0,
+ WALK_MODE_GRAVITY,
} eWalkMethod;
typedef enum eWalkGravityState {
- WALK_GRAVITY_STATE_OFF = 0,
- WALK_GRAVITY_STATE_JUMP,
- WALK_GRAVITY_STATE_START,
- WALK_GRAVITY_STATE_ON,
+ WALK_GRAVITY_STATE_OFF = 0,
+ WALK_GRAVITY_STATE_JUMP,
+ WALK_GRAVITY_STATE_START,
+ WALK_GRAVITY_STATE_ON,
} eWalkGravityState;
/* called in transform_ops.c, on each regeneration of keymaps */
void walk_modal_keymap(wmKeyConfig *keyconf)
{
- static const EnumPropertyItem modal_items[] = {
- {WALK_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
- {WALK_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
+ static const EnumPropertyItem modal_items[] = {
+ {WALK_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+ {WALK_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
- {WALK_MODAL_DIR_FORWARD, "FORWARD", 0, "Forward", ""},
- {WALK_MODAL_DIR_BACKWARD, "BACKWARD", 0, "Backward", ""},
- {WALK_MODAL_DIR_LEFT, "LEFT", 0, "Left (Strafe)", ""},
- {WALK_MODAL_DIR_RIGHT, "RIGHT", 0, "Right (Strafe)", ""},
- {WALK_MODAL_DIR_UP, "UP", 0, "Up", ""},
- {WALK_MODAL_DIR_DOWN, "DOWN", 0, "Down", ""},
+ {WALK_MODAL_DIR_FORWARD, "FORWARD", 0, "Forward", ""},
+ {WALK_MODAL_DIR_BACKWARD, "BACKWARD", 0, "Backward", ""},
+ {WALK_MODAL_DIR_LEFT, "LEFT", 0, "Left (Strafe)", ""},
+ {WALK_MODAL_DIR_RIGHT, "RIGHT", 0, "Right (Strafe)", ""},
+ {WALK_MODAL_DIR_UP, "UP", 0, "Up", ""},
+ {WALK_MODAL_DIR_DOWN, "DOWN", 0, "Down", ""},
- {WALK_MODAL_DIR_FORWARD_STOP, "FORWARD_STOP", 0, "Stop Move Forward", ""},
- {WALK_MODAL_DIR_BACKWARD_STOP, "BACKWARD_STOP", 0, "Stop Mode Backward", ""},
- {WALK_MODAL_DIR_LEFT_STOP, "LEFT_STOP", 0, "Stop Move Left", ""},
- {WALK_MODAL_DIR_RIGHT_STOP, "RIGHT_STOP", 0, "Stop Mode Right", ""},
- {WALK_MODAL_DIR_UP_STOP, "UP_STOP", 0, "Stop Move Up", ""},
- {WALK_MODAL_DIR_DOWN_STOP, "DOWN_STOP", 0, "Stop Mode Down", ""},
+ {WALK_MODAL_DIR_FORWARD_STOP, "FORWARD_STOP", 0, "Stop Move Forward", ""},
+ {WALK_MODAL_DIR_BACKWARD_STOP, "BACKWARD_STOP", 0, "Stop Mode Backward", ""},
+ {WALK_MODAL_DIR_LEFT_STOP, "LEFT_STOP", 0, "Stop Move Left", ""},
+ {WALK_MODAL_DIR_RIGHT_STOP, "RIGHT_STOP", 0, "Stop Mode Right", ""},
+ {WALK_MODAL_DIR_UP_STOP, "UP_STOP", 0, "Stop Move Up", ""},
+ {WALK_MODAL_DIR_DOWN_STOP, "DOWN_STOP", 0, "Stop Mode Down", ""},
- {WALK_MODAL_TELEPORT, "TELEPORT", 0, "Teleport", "Move forward a few units at once"},
+ {WALK_MODAL_TELEPORT, "TELEPORT", 0, "Teleport", "Move forward a few units at once"},
- {WALK_MODAL_ACCELERATE, "ACCELERATE", 0, "Accelerate", ""},
- {WALK_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""},
+ {WALK_MODAL_ACCELERATE, "ACCELERATE", 0, "Accelerate", ""},
+ {WALK_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""},
- {WALK_MODAL_FAST_ENABLE, "FAST_ENABLE", 0, "Fast", "Move faster (walk or fly)"},
- {WALK_MODAL_FAST_DISABLE, "FAST_DISABLE", 0, "Fast (Off)", "Resume regular speed"},
+ {WALK_MODAL_FAST_ENABLE, "FAST_ENABLE", 0, "Fast", "Move faster (walk or fly)"},
+ {WALK_MODAL_FAST_DISABLE, "FAST_DISABLE", 0, "Fast (Off)", "Resume regular speed"},
- {WALK_MODAL_SLOW_ENABLE, "SLOW_ENABLE", 0, "Slow", "Move slower (walk or fly)"},
- {WALK_MODAL_SLOW_DISABLE, "SLOW_DISABLE", 0, "Slow (Off)", "Resume regular speed"},
+ {WALK_MODAL_SLOW_ENABLE, "SLOW_ENABLE", 0, "Slow", "Move slower (walk or fly)"},
+ {WALK_MODAL_SLOW_DISABLE, "SLOW_DISABLE", 0, "Slow (Off)", "Resume regular speed"},
- {WALK_MODAL_JUMP, "JUMP", 0, "Jump", "Jump when in walk mode"},
- {WALK_MODAL_JUMP_STOP, "JUMP_STOP", 0, "Jump (Off)", "Stop pushing jump"},
+ {WALK_MODAL_JUMP, "JUMP", 0, "Jump", "Jump when in walk mode"},
+ {WALK_MODAL_JUMP_STOP, "JUMP_STOP", 0, "Jump (Off)", "Stop pushing jump"},
- {WALK_MODAL_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"},
+ {WALK_MODAL_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"},
- {0, NULL, 0, NULL, NULL},
- };
+ {0, NULL, 0, NULL, NULL},
+ };
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Walk Modal");
+ wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Walk Modal");
- /* this function is called for each spacetype, only needs to add map once */
- if (keymap && keymap->modal_items) {
- return;
- }
+ /* 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_add(keyconf, "View3D Walk Modal", modal_items);
- /* assign map to operators */
- WM_modalkeymap_assign(keymap, "VIEW3D_OT_walk");
+ /* assign map to operators */
+ WM_modalkeymap_assign(keymap, "VIEW3D_OT_walk");
}
-
typedef struct WalkTeleport {
- eWalkTeleportState state;
- float duration; /* from user preferences */
- float origin[3];
- float direction[3];
- double initial_time;
- eWalkMethod navigation_mode; /* teleport always set FREE mode on */
+ eWalkTeleportState state;
+ float duration; /* from user preferences */
+ float origin[3];
+ float direction[3];
+ double initial_time;
+ eWalkMethod navigation_mode; /* teleport always set FREE mode on */
} WalkTeleport;
typedef struct WalkInfo {
- /* context stuff */
- RegionView3D *rv3d;
- View3D *v3d;
- ARegion *ar;
- struct Depsgraph *depsgraph;
- Scene *scene;
+ /* context stuff */
+ RegionView3D *rv3d;
+ View3D *v3d;
+ ARegion *ar;
+ struct Depsgraph *depsgraph;
+ Scene *scene;
- wmTimer *timer; /* needed for redraws */
+ wmTimer *timer; /* needed for redraws */
- short state;
- bool redraw;
+ short state;
+ bool redraw;
- int prev_mval[2]; /* previous 2D mouse values */
- int center_mval[2]; /* center mouse values */
- int moffset[2];
+ int prev_mval[2]; /* previous 2D mouse values */
+ int center_mval[2]; /* center mouse values */
+ int moffset[2];
#ifdef WITH_INPUT_NDOF
- wmNDOFMotionData *ndof; /* latest 3D mouse values */
+ wmNDOFMotionData *ndof; /* latest 3D mouse values */
#endif
- /* walk state state */
- float base_speed; /* the base speed without run/slow down modifications */
- float speed; /* the speed the view is moving per redraw */
- float grid; /* world scale 1.0 default */
+ /* walk state state */
+ float base_speed; /* the base speed without run/slow down modifications */
+ float speed; /* the speed the view is moving per redraw */
+ float grid; /* world scale 1.0 default */
- /* compare between last state */
- double time_lastdraw; /* time between draws */
+ /* compare between last state */
+ double time_lastdraw; /* time between draws */
- void *draw_handle_pixel;
+ void *draw_handle_pixel;
- /* use for some lag */
- float dvec_prev[3]; /* old for some lag */
+ /* use for some lag */
+ float dvec_prev[3]; /* old for some lag */
- /* walk/fly */
- eWalkMethod navigation_mode;
+ /* walk/fly */
+ eWalkMethod navigation_mode;
- /* teleport */
- WalkTeleport teleport;
+ /* teleport */
+ WalkTeleport teleport;
- /* look speed factor - user preferences */
- float mouse_speed;
+ /* look speed factor - user preferences */
+ float mouse_speed;
- /* speed adjustments */
- bool is_fast;
- bool is_slow;
+ /* speed adjustments */
+ bool is_fast;
+ bool is_slow;
- /* mouse reverse */
- bool is_reversed;
+ /* mouse reverse */
+ bool is_reversed;
#ifdef USE_TABLET_SUPPORT
- /* check if we had a cursor event before */
- bool is_cursor_first;
+ /* check if we had a cursor event before */
+ bool is_cursor_first;
- /* tablet devices (we can't relocate the cursor) */
- bool is_cursor_absolute;
+ /* tablet devices (we can't relocate the cursor) */
+ bool is_cursor_absolute;
#endif
- /* gravity system */
- eWalkGravityState gravity_state;
- float gravity;
+ /* gravity system */
+ eWalkGravityState gravity_state;
+ float gravity;
- /* height to use in walk mode */
- float view_height;
+ /* height to use in walk mode */
+ float view_height;
- /* counting system to allow movement to continue if a direction (WASD) key is still pressed */
- int active_directions;
+ /* counting system to allow movement to continue if a direction (WASD) key is still pressed */
+ int active_directions;
- float speed_jump;
- float jump_height; /* maximum jump height */
- float speed_factor; /* to use for fast/slow speeds */
+ float speed_jump;
+ float jump_height; /* maximum jump height */
+ float speed_factor; /* to use for fast/slow speeds */
- struct SnapObjectContext *snap_context;
+ struct SnapObjectContext *snap_context;
- struct View3DCameraControl *v3d_camera_control;
+ struct View3DCameraControl *v3d_camera_control;
} WalkInfo;
static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *ar, void *arg)
{
- /* draws an aim/cross in the center */
- WalkInfo *walk = arg;
+ /* draws an aim/cross in the center */
+ WalkInfo *walk = arg;
- const int outter_length = 24;
- const int inner_length = 14;
- int xoff, yoff;
- rctf viewborder;
+ const int outter_length = 24;
+ const int inner_length = 14;
+ int xoff, yoff;
+ rctf viewborder;
- 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);
- 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;
- }
+ 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);
+ 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;
+ }
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor(TH_VIEW_OVERLAY);
+ immUniformThemeColor(TH_VIEW_OVERLAY);
- immBegin(GPU_PRIM_LINES, 8);
+ immBegin(GPU_PRIM_LINES, 8);
- /* North */
- immVertex2i(pos, xoff, yoff + inner_length);
- immVertex2i(pos, xoff, yoff + outter_length);
+ /* North */
+ immVertex2i(pos, xoff, yoff + inner_length);
+ immVertex2i(pos, xoff, yoff + outter_length);
- /* East */
- immVertex2i(pos, xoff + inner_length, yoff);
- immVertex2i(pos, xoff + outter_length, yoff);
+ /* East */
+ immVertex2i(pos, xoff + inner_length, yoff);
+ immVertex2i(pos, xoff + outter_length, yoff);
- /* South */
- immVertex2i(pos, xoff, yoff - inner_length);
- immVertex2i(pos, xoff, yoff - outter_length);
+ /* South */
+ immVertex2i(pos, xoff, yoff - inner_length);
+ immVertex2i(pos, xoff, yoff - outter_length);
- /* West */
- immVertex2i(pos, xoff - inner_length, yoff);
- immVertex2i(pos, xoff - outter_length, yoff);
+ /* West */
+ immVertex2i(pos, xoff - inner_length, yoff);
+ immVertex2i(pos, xoff - outter_length, yoff);
- immEnd();
- immUnbindProgram();
+ immEnd();
+ immUnbindProgram();
}
static void walk_update_header(bContext *C, wmOperator *op, WalkInfo *walk)
{
- const bool gravity = (walk->navigation_mode == WALK_MODE_GRAVITY) ||
- ((walk->teleport.state == WALK_TELEPORT_STATE_ON) &&
- (walk->teleport.navigation_mode == WALK_MODE_GRAVITY));
- char header[UI_MAX_DRAW_STR];
- char buf[UI_MAX_DRAW_STR];
+ const bool gravity = (walk->navigation_mode == WALK_MODE_GRAVITY) ||
+ ((walk->teleport.state == WALK_TELEPORT_STATE_ON) &&
+ (walk->teleport.navigation_mode == WALK_MODE_GRAVITY));
+ char header[UI_MAX_DRAW_STR];
+ char buf[UI_MAX_DRAW_STR];
- char *p = buf;
- int available_len = sizeof(buf);
+ char *p = buf;
+ int available_len = sizeof(buf);
#define WM_MODALKEY(_id) \
- WM_modalkeymap_operator_items_to_string_buf(op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p)
-
- BLI_snprintf(header, sizeof(header), IFACE_("%s: confirm, %s: cancel, "
- "%s: gravity (%s), "
- "%s|%s|%s|%s: move around, "
- "%s: fast, %s: slow, "
- "%s|%s: up and down, "
- "%s: teleport, %s: jump, "
- "%s: increase speed, %s: decrease speed"),
- WM_MODALKEY(WALK_MODAL_CONFIRM), WM_MODALKEY(WALK_MODAL_CANCEL),
- WM_MODALKEY(WALK_MODAL_TOGGLE), WM_bool_as_string(gravity),
- WM_MODALKEY(WALK_MODAL_DIR_FORWARD), WM_MODALKEY(WALK_MODAL_DIR_LEFT),
- WM_MODALKEY(WALK_MODAL_DIR_BACKWARD), WM_MODALKEY(WALK_MODAL_DIR_RIGHT),
- WM_MODALKEY(WALK_MODAL_FAST_ENABLE), WM_MODALKEY(WALK_MODAL_SLOW_ENABLE),
- WM_MODALKEY(WALK_MODAL_DIR_UP), WM_MODALKEY(WALK_MODAL_DIR_DOWN),
- WM_MODALKEY(WALK_MODAL_TELEPORT), WM_MODALKEY(WALK_MODAL_JUMP),
- WM_MODALKEY(WALK_MODAL_ACCELERATE), WM_MODALKEY(WALK_MODAL_DECELERATE));
+ WM_modalkeymap_operator_items_to_string_buf( \
+ op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p)
+
+ BLI_snprintf(header,
+ sizeof(header),
+ IFACE_("%s: confirm, %s: cancel, "
+ "%s: gravity (%s), "
+ "%s|%s|%s|%s: move around, "
+ "%s: fast, %s: slow, "
+ "%s|%s: up and down, "
+ "%s: teleport, %s: jump, "
+ "%s: increase speed, %s: decrease speed"),
+ WM_MODALKEY(WALK_MODAL_CONFIRM),
+ WM_MODALKEY(WALK_MODAL_CANCEL),
+ WM_MODALKEY(WALK_MODAL_TOGGLE),
+ WM_bool_as_string(gravity),
+ WM_MODALKEY(WALK_MODAL_DIR_FORWARD),
+ WM_MODALKEY(WALK_MODAL_DIR_LEFT),
+ WM_MODALKEY(WALK_MODAL_DIR_BACKWARD),
+ WM_MODALKEY(WALK_MODAL_DIR_RIGHT),
+ WM_MODALKEY(WALK_MODAL_FAST_ENABLE),
+ WM_MODALKEY(WALK_MODAL_SLOW_ENABLE),
+ WM_MODALKEY(WALK_MODAL_DIR_UP),
+ WM_MODALKEY(WALK_MODAL_DIR_DOWN),
+ WM_MODALKEY(WALK_MODAL_TELEPORT),
+ WM_MODALKEY(WALK_MODAL_JUMP),
+ WM_MODALKEY(WALK_MODAL_ACCELERATE),
+ WM_MODALKEY(WALK_MODAL_DECELERATE));
#undef WM_MODALKEY
- ED_workspace_status_text(C, header);
+ ED_workspace_status_text(C, header);
}
static void walk_navigation_mode_set(bContext *C, wmOperator *op, WalkInfo *walk, eWalkMethod mode)
{
- if (mode == WALK_MODE_FREE) {
- walk->navigation_mode = WALK_MODE_FREE;
- walk->gravity_state = WALK_GRAVITY_STATE_OFF;
- }
- else { /* WALK_MODE_GRAVITY */
- walk->navigation_mode = WALK_MODE_GRAVITY;
- walk->gravity_state = WALK_GRAVITY_STATE_START;
- }
-
- walk_update_header(C, op, walk);
+ if (mode == WALK_MODE_FREE) {
+ walk->navigation_mode = WALK_MODE_FREE;
+ walk->gravity_state = WALK_GRAVITY_STATE_OFF;
+ }
+ else { /* WALK_MODE_GRAVITY */
+ walk->navigation_mode = WALK_MODE_GRAVITY;
+ walk->gravity_state = WALK_GRAVITY_STATE_START;
+ }
+
+ walk_update_header(C, op, walk);
}
/**
* \param r_distance: Distance to the hit point
*/
-static bool walk_floor_distance_get(
- RegionView3D *rv3d, WalkInfo *walk, const float dvec[3],
- float *r_distance)
+static bool walk_floor_distance_get(RegionView3D *rv3d,
+ WalkInfo *walk,
+ const float dvec[3],
+ float *r_distance)
{
- float ray_normal[3] = {0, 0, -1}; /* down */
- float ray_start[3];
- float r_location[3];
- float r_normal_dummy[3];
- float dvec_tmp[3];
- bool ret;
-
- *r_distance = BVH_RAYCAST_DIST_MAX;
-
- copy_v3_v3(ray_start, rv3d->viewinv[3]);
-
- mul_v3_v3fl(dvec_tmp, dvec, walk->grid);
- add_v3_v3(ray_start, dvec_tmp);
-
- ret = ED_transform_snap_object_project_ray(
- walk->snap_context,
- &(const struct SnapObjectParams){
- .snap_select = SNAP_ALL,
- },
- ray_start, ray_normal, r_distance,
- r_location, r_normal_dummy);
-
- /* artificially scale the distance to the scene size */
- *r_distance /= walk->grid;
- return ret;
+ float ray_normal[3] = {0, 0, -1}; /* down */
+ float ray_start[3];
+ float r_location[3];
+ float r_normal_dummy[3];
+ float dvec_tmp[3];
+ bool ret;
+
+ *r_distance = BVH_RAYCAST_DIST_MAX;
+
+ copy_v3_v3(ray_start, rv3d->viewinv[3]);
+
+ mul_v3_v3fl(dvec_tmp, dvec, walk->grid);
+ add_v3_v3(ray_start, dvec_tmp);
+
+ ret = ED_transform_snap_object_project_ray(walk->snap_context,
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ },
+ ray_start,
+ ray_normal,
+ r_distance,
+ r_location,
+ r_normal_dummy);
+
+ /* artificially scale the distance to the scene size */
+ *r_distance /= walk->grid;
+ return ret;
}
/**
@@ -402,46 +416,50 @@ static bool walk_floor_distance_get(
* \param r_location: Location of the hit point
* \param r_normal: Normal of the hit surface, transformed to always face the camera
*/
-static bool walk_ray_cast(
- RegionView3D *rv3d, WalkInfo *walk,
- float r_location[3], float r_normal[3], float *ray_distance)
+static bool walk_ray_cast(RegionView3D *rv3d,
+ WalkInfo *walk,
+ float r_location[3],
+ float r_normal[3],
+ float *ray_distance)
{
- float ray_normal[3] = {0, 0, -1}; /* forward */
- float ray_start[3];
- bool ret;
+ float ray_normal[3] = {0, 0, -1}; /* forward */
+ float ray_start[3];
+ bool ret;
- *ray_distance = BVH_RAYCAST_DIST_MAX;
+ *ray_distance = BVH_RAYCAST_DIST_MAX;
- copy_v3_v3(ray_start, rv3d->viewinv[3]);
+ copy_v3_v3(ray_start, rv3d->viewinv[3]);
- mul_mat3_m4_v3(rv3d->viewinv, ray_normal);
+ mul_mat3_m4_v3(rv3d->viewinv, ray_normal);
- normalize_v3(ray_normal);
+ normalize_v3(ray_normal);
- ret = ED_transform_snap_object_project_ray(
- walk->snap_context,
- &(const struct SnapObjectParams){
- .snap_select = SNAP_ALL,
- },
- ray_start, ray_normal, NULL,
- r_location, r_normal);
+ ret = ED_transform_snap_object_project_ray(walk->snap_context,
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ },
+ ray_start,
+ ray_normal,
+ NULL,
+ r_location,
+ r_normal);
- /* dot is positive if both rays are facing the same direction */
- if (dot_v3v3(ray_normal, r_normal) > 0) {
- negate_v3(r_normal);
- }
+ /* dot is positive if both rays are facing the same direction */
+ if (dot_v3v3(ray_normal, r_normal) > 0) {
+ negate_v3(r_normal);
+ }
- /* artificially scale the distance to the scene size */
- *ray_distance /= walk->grid;
+ /* artificially scale the distance to the scene size */
+ *ray_distance /= walk->grid;
- return ret;
+ return ret;
}
/* WalkInfo->state */
enum {
- WALK_RUNNING = 0,
- WALK_CANCEL = 1,
- WALK_CONFIRM = 2,
+ WALK_RUNNING = 0,
+ WALK_CANCEL = 1,
+ WALK_CONFIRM = 2,
};
/* keep the previous speed until user changes userpreferences */
@@ -450,484 +468,484 @@ static float userdef_speed = -1.f;
static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- wmWindow *win = CTX_wm_window(C);
+ Main *bmain = CTX_data_main(C);
+ wmWindow *win = CTX_wm_window(C);
- walk->rv3d = CTX_wm_region_view3d(C);
- walk->v3d = CTX_wm_view3d(C);
- walk->ar = CTX_wm_region(C);
- walk->depsgraph = CTX_data_depsgraph(C);
- walk->scene = CTX_data_scene(C);
+ walk->rv3d = CTX_wm_region_view3d(C);
+ walk->v3d = CTX_wm_view3d(C);
+ walk->ar = CTX_wm_region(C);
+ walk->depsgraph = CTX_data_depsgraph(C);
+ walk->scene = CTX_data_scene(C);
#ifdef NDOF_WALK_DEBUG
- puts("\n-- walk begin --");
+ puts("\n-- walk begin --");
#endif
- /* sanity check: for rare but possible case (if lib-linking the camera fails) */
- if ((walk->rv3d->persp == RV3D_CAMOB) && (walk->v3d->camera == NULL)) {
- walk->rv3d->persp = RV3D_PERSP;
- }
-
- if (walk->rv3d->persp == RV3D_CAMOB && ID_IS_LINKED(walk->v3d->camera)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot navigate a camera from an external library");
- return false;
- }
-
- if (ED_view3d_offset_lock_check(walk->v3d, walk->rv3d)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot navigate when the view offset is locked");
- return false;
- }
-
- if (walk->rv3d->persp == RV3D_CAMOB && walk->v3d->camera->constraints.first) {
- BKE_report(op->reports, RPT_ERROR, "Cannot navigate an object with constraints");
- return false;
- }
-
- walk->state = WALK_RUNNING;
-
- if (fabsf(U.walk_navigation.walk_speed - userdef_speed) > 0.1f) {
- base_speed = U.walk_navigation.walk_speed;
- userdef_speed = U.walk_navigation.walk_speed;
- }
-
- walk->speed = 0.0f;
- walk->is_fast = false;
- walk->is_slow = false;
- walk->grid = (walk->scene->unit.system == USER_UNIT_NONE) ? 1.f : 1.f / walk->scene->unit.scale_length;
-
- /* user preference settings */
- walk->teleport.duration = U.walk_navigation.teleport_time;
- walk->mouse_speed = U.walk_navigation.mouse_speed;
-
- if ((U.walk_navigation.flag & USER_WALK_GRAVITY)) {
- walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY);
- }
- else {
- walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE);
- }
-
- walk->view_height = U.walk_navigation.view_height;
- walk->jump_height = U.walk_navigation.jump_height;
- walk->speed = U.walk_navigation.walk_speed;
- walk->speed_factor = U.walk_navigation.walk_speed_factor;
-
- walk->gravity_state = WALK_GRAVITY_STATE_OFF;
-
- if ((walk->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY)) {
- walk->gravity = fabsf(walk->scene->physics_settings.gravity[2]);
- }
- else {
- walk->gravity = 9.80668f; /* m/s2 */
- }
-
- walk->is_reversed = ((U.walk_navigation.flag & USER_WALK_MOUSE_REVERSE) != 0);
+ /* sanity check: for rare but possible case (if lib-linking the camera fails) */
+ if ((walk->rv3d->persp == RV3D_CAMOB) && (walk->v3d->camera == NULL)) {
+ walk->rv3d->persp = RV3D_PERSP;
+ }
+
+ if (walk->rv3d->persp == RV3D_CAMOB && ID_IS_LINKED(walk->v3d->camera)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot navigate a camera from an external library");
+ return false;
+ }
+
+ if (ED_view3d_offset_lock_check(walk->v3d, walk->rv3d)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot navigate when the view offset is locked");
+ return false;
+ }
+
+ if (walk->rv3d->persp == RV3D_CAMOB && walk->v3d->camera->constraints.first) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot navigate an object with constraints");
+ return false;
+ }
+
+ walk->state = WALK_RUNNING;
+
+ if (fabsf(U.walk_navigation.walk_speed - userdef_speed) > 0.1f) {
+ base_speed = U.walk_navigation.walk_speed;
+ userdef_speed = U.walk_navigation.walk_speed;
+ }
+
+ walk->speed = 0.0f;
+ walk->is_fast = false;
+ walk->is_slow = false;
+ walk->grid = (walk->scene->unit.system == USER_UNIT_NONE) ? 1.f :
+ 1.f / walk->scene->unit.scale_length;
+
+ /* user preference settings */
+ walk->teleport.duration = U.walk_navigation.teleport_time;
+ walk->mouse_speed = U.walk_navigation.mouse_speed;
+
+ if ((U.walk_navigation.flag & USER_WALK_GRAVITY)) {
+ walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY);
+ }
+ else {
+ walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE);
+ }
+
+ walk->view_height = U.walk_navigation.view_height;
+ walk->jump_height = U.walk_navigation.jump_height;
+ walk->speed = U.walk_navigation.walk_speed;
+ walk->speed_factor = U.walk_navigation.walk_speed_factor;
+
+ walk->gravity_state = WALK_GRAVITY_STATE_OFF;
+
+ if ((walk->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY)) {
+ walk->gravity = fabsf(walk->scene->physics_settings.gravity[2]);
+ }
+ else {
+ walk->gravity = 9.80668f; /* m/s2 */
+ }
+
+ walk->is_reversed = ((U.walk_navigation.flag & USER_WALK_MOUSE_REVERSE) != 0);
#ifdef USE_TABLET_SUPPORT
- walk->is_cursor_first = true;
+ walk->is_cursor_first = true;
- walk->is_cursor_absolute = false;
+ walk->is_cursor_absolute = false;
#endif
- walk->active_directions = 0;
+ walk->active_directions = 0;
#ifdef NDOF_WALK_DRAW_TOOMUCH
- walk->redraw = 1;
+ walk->redraw = 1;
#endif
- zero_v3(walk->dvec_prev);
+ zero_v3(walk->dvec_prev);
- walk->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f);
+ walk->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f);
#ifdef WITH_INPUT_NDOF
- walk->ndof = NULL;
+ walk->ndof = NULL;
#endif
- walk->time_lastdraw = PIL_check_seconds_timer();
+ 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->draw_handle_pixel = ED_region_draw_cb_activate(
+ walk->ar->type, drawWalkPixel, walk, REGION_DRAW_POST_PIXEL);
- walk->rv3d->rflag |= RV3D_NAVIGATING;
+ walk->rv3d->rflag |= RV3D_NAVIGATING;
- walk->snap_context = ED_transform_snap_object_context_create_view3d(
- bmain, walk->scene, CTX_data_depsgraph(C), 0,
- walk->ar, walk->v3d);
+ walk->snap_context = ED_transform_snap_object_context_create_view3d(
+ bmain, walk->scene, CTX_data_depsgraph(C), 0, walk->ar, walk->v3d);
- walk->v3d_camera_control = ED_view3d_cameracontrol_acquire(
- walk->depsgraph, walk->scene, walk->v3d, walk->rv3d,
- (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0);
+ walk->v3d_camera_control = ED_view3d_cameracontrol_acquire(
+ walk->depsgraph,
+ walk->scene,
+ walk->v3d,
+ walk->rv3d,
+ (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;
+ /* center the mouse */
+ walk->center_mval[0] = walk->ar->winx * 0.5f;
+ walk->center_mval[1] = walk->ar->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->ar->winrct.xmin;
+ walk->center_mval[1] += walk->ar->winrct.ymin;
- WM_cursor_compatible_xy(win, &walk->center_mval[0], &walk->center_mval[1]);
+ 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->ar->winrct.xmin;
+ walk->center_mval[1] -= walk->ar->winrct.ymin;
#endif
- copy_v2_v2_int(walk->prev_mval, walk->center_mval);
+ 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]);
+ WM_cursor_warp(win,
+ walk->ar->winrct.xmin + walk->center_mval[0],
+ walk->ar->winrct.ymin + walk->center_mval[1]);
- /* remove the mouse cursor temporarily */
- WM_cursor_modal_set(win, CURSOR_NONE);
+ /* remove the mouse cursor temporarily */
+ WM_cursor_modal_set(win, CURSOR_NONE);
- return 1;
+ return 1;
}
static int walkEnd(bContext *C, WalkInfo *walk)
{
- wmWindow *win;
- RegionView3D *rv3d;
+ wmWindow *win;
+ RegionView3D *rv3d;
- if (walk->state == WALK_RUNNING) {
- return OPERATOR_RUNNING_MODAL;
- }
+ if (walk->state == WALK_RUNNING) {
+ return OPERATOR_RUNNING_MODAL;
+ }
#ifdef NDOF_WALK_DEBUG
- puts("\n-- walk end --");
+ puts("\n-- walk end --");
#endif
- win = CTX_wm_window(C);
- rv3d = walk->rv3d;
+ win = CTX_wm_window(C);
+ rv3d = walk->rv3d;
- WM_event_remove_timer(CTX_wm_manager(C), win, walk->timer);
+ 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->ar->type, walk->draw_handle_pixel);
- ED_transform_snap_object_context_destroy(walk->snap_context);
+ ED_transform_snap_object_context_destroy(walk->snap_context);
- ED_view3d_cameracontrol_release(walk->v3d_camera_control, walk->state == WALK_CANCEL);
+ ED_view3d_cameracontrol_release(walk->v3d_camera_control, walk->state == WALK_CANCEL);
- rv3d->rflag &= ~RV3D_NAVIGATING;
+ rv3d->rflag &= ~RV3D_NAVIGATING;
#ifdef WITH_INPUT_NDOF
- if (walk->ndof) {
- MEM_freeN(walk->ndof);
- }
+ if (walk->ndof) {
+ MEM_freeN(walk->ndof);
+ }
#endif
- /* restore the cursor */
- WM_cursor_modal_restore(win);
+ /* restore the cursor */
+ WM_cursor_modal_restore(win);
#ifdef USE_TABLET_SUPPORT
- if (walk->is_cursor_absolute == false)
+ if (walk->is_cursor_absolute == false)
#endif
- {
- /* center the mouse */
- WM_cursor_warp(
- win,
- walk->ar->winrct.xmin + walk->center_mval[0],
- walk->ar->winrct.ymin + walk->center_mval[1]);
- }
-
- if (walk->state == WALK_CONFIRM) {
- MEM_freeN(walk);
- return OPERATOR_FINISHED;
- }
-
- MEM_freeN(walk);
- return OPERATOR_CANCELLED;
+ {
+ /* center the mouse */
+ WM_cursor_warp(win,
+ walk->ar->winrct.xmin + walk->center_mval[0],
+ walk->ar->winrct.ymin + walk->center_mval[1]);
+ }
+
+ if (walk->state == WALK_CONFIRM) {
+ MEM_freeN(walk);
+ return OPERATOR_FINISHED;
+ }
+
+ MEM_freeN(walk);
+ return OPERATOR_CANCELLED;
}
static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent *event)
{
- if (event->type == TIMER && event->customdata == walk->timer) {
- walk->redraw = true;
- }
- else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+ if (event->type == TIMER && event->customdata == walk->timer) {
+ walk->redraw = true;
+ }
+ else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
#ifdef USE_TABLET_SUPPORT
- if (walk->is_cursor_first) {
- /* wait until we get the 'warp' event */
- if ((walk->center_mval[0] == event->mval[0]) &&
- (walk->center_mval[1] == event->mval[1]))
- {
- walk->is_cursor_first = false;
- }
- else {
- /* note, its possible the system isn't giving us the warp 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]);
- }
- return;
- }
-
- if ((walk->is_cursor_absolute == false) && event->is_motion_absolute) {
- walk->is_cursor_absolute = true;
- copy_v2_v2_int(walk->prev_mval, event->mval);
- copy_v2_v2_int(walk->center_mval, event->mval);
- /* without this we can't turn 180d */
- CLAMP_MIN(walk->mouse_speed, 4.0f);
- }
-#endif /* USE_TABLET_SUPPORT */
-
-
- walk->moffset[0] += event->mval[0] - walk->prev_mval[0];
- walk->moffset[1] += event->mval[1] - walk->prev_mval[1];
-
- copy_v2_v2_int(walk->prev_mval, event->mval);
-
- if ((walk->center_mval[0] != event->mval[0]) ||
- (walk->center_mval[1] != event->mval[1]))
- {
- walk->redraw = true;
+ if (walk->is_cursor_first) {
+ /* wait until we get the 'warp' event */
+ if ((walk->center_mval[0] == event->mval[0]) && (walk->center_mval[1] == event->mval[1])) {
+ walk->is_cursor_first = false;
+ }
+ else {
+ /* note, its possible the system isn't giving us the warp 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]);
+ }
+ return;
+ }
+
+ if ((walk->is_cursor_absolute == false) && event->is_motion_absolute) {
+ walk->is_cursor_absolute = true;
+ copy_v2_v2_int(walk->prev_mval, event->mval);
+ copy_v2_v2_int(walk->center_mval, event->mval);
+ /* without this we can't turn 180d */
+ CLAMP_MIN(walk->mouse_speed, 4.0f);
+ }
+#endif /* USE_TABLET_SUPPORT */
+
+ walk->moffset[0] += event->mval[0] - walk->prev_mval[0];
+ walk->moffset[1] += event->mval[1] - walk->prev_mval[1];
+
+ copy_v2_v2_int(walk->prev_mval, event->mval);
+
+ if ((walk->center_mval[0] != event->mval[0]) || (walk->center_mval[1] != event->mval[1])) {
+ walk->redraw = true;
#ifdef USE_TABLET_SUPPORT
- if (walk->is_cursor_absolute) {
- /* pass */
- }
- else
+ if (walk->is_cursor_absolute) {
+ /* pass */
+ }
+ else
#endif
- if (WM_event_is_last_mousemove(event)) {
- wmWindow *win = CTX_wm_window(C);
+ if (WM_event_is_last_mousemove(event)) {
+ wmWindow *win = CTX_wm_window(C);
#ifdef __APPLE__
- if ((abs(walk->prev_mval[0] - walk->center_mval[0]) > walk->center_mval[0] / 2) ||
- (abs(walk->prev_mval[1] - walk->center_mval[1]) > walk->center_mval[1] / 2))
+ if ((abs(walk->prev_mval[0] - walk->center_mval[0]) > walk->center_mval[0] / 2) ||
+ (abs(walk->prev_mval[1] - walk->center_mval[1]) > walk->center_mval[1] / 2))
#endif
- {
- WM_cursor_warp(win,
- walk->ar->winrct.xmin + walk->center_mval[0],
- walk->ar->winrct.ymin + walk->center_mval[1]);
- 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]);
+ copy_v2_v2_int(walk->prev_mval, walk->center_mval);
+ }
+ }
+ }
+ }
#ifdef WITH_INPUT_NDOF
- else if (event->type == NDOF_MOTION) {
- /* do these automagically get delivered? yes. */
- // puts("ndof motion detected in walk mode!");
- // static const char *tag_name = "3D mouse position";
-
- const wmNDOFMotionData *incoming_ndof = event->customdata;
- switch (incoming_ndof->progress) {
- case P_STARTING:
- /* start keeping track of 3D mouse position */
+ else if (event->type == NDOF_MOTION) {
+ /* do these automagically get delivered? yes. */
+ // puts("ndof motion detected in walk mode!");
+ // static const char *tag_name = "3D mouse position";
+
+ const wmNDOFMotionData *incoming_ndof = event->customdata;
+ switch (incoming_ndof->progress) {
+ case P_STARTING:
+ /* start keeping track of 3D mouse position */
# ifdef NDOF_WALK_DEBUG
- puts("start keeping track of 3D mouse position");
+ puts("start keeping track of 3D mouse position");
# endif
- /* fall-through */
- case P_IN_PROGRESS:
- /* update 3D mouse position */
+ /* fall-through */
+ case P_IN_PROGRESS:
+ /* update 3D mouse position */
# ifdef NDOF_WALK_DEBUG
- putchar('.'); fflush(stdout);
+ putchar('.');
+ fflush(stdout);
# endif
- if (walk->ndof == NULL) {
- // walk->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name);
- walk->ndof = MEM_dupallocN(incoming_ndof);
- // walk->ndof = malloc(sizeof(wmNDOFMotionData));
- }
- else {
- memcpy(walk->ndof, incoming_ndof, sizeof(wmNDOFMotionData));
- }
- break;
- case P_FINISHING:
- /* stop keeping track of 3D mouse position */
+ if (walk->ndof == NULL) {
+ // walk->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name);
+ walk->ndof = MEM_dupallocN(incoming_ndof);
+ // walk->ndof = malloc(sizeof(wmNDOFMotionData));
+ }
+ else {
+ memcpy(walk->ndof, incoming_ndof, sizeof(wmNDOFMotionData));
+ }
+ break;
+ case P_FINISHING:
+ /* stop keeping track of 3D mouse position */
# ifdef NDOF_WALK_DEBUG
- puts("stop keeping track of 3D mouse position");
+ puts("stop keeping track of 3D mouse position");
# endif
- if (walk->ndof) {
- MEM_freeN(walk->ndof);
- // free(walk->ndof);
- walk->ndof = NULL;
- }
-
- /* update the time else the view will jump when 2D mouse/timer resume */
- walk->time_lastdraw = PIL_check_seconds_timer();
-
- break;
- default:
- break; /* should always be one of the above 3 */
- }
- }
+ if (walk->ndof) {
+ MEM_freeN(walk->ndof);
+ // free(walk->ndof);
+ walk->ndof = NULL;
+ }
+
+ /* update the time else the view will jump when 2D mouse/timer resume */
+ walk->time_lastdraw = PIL_check_seconds_timer();
+
+ break;
+ default:
+ break; /* should always be one of the above 3 */
+ }
+ }
#endif /* WITH_INPUT_NDOF */
- /* handle modal keymap first */
- else if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case WALK_MODAL_CANCEL:
- walk->state = WALK_CANCEL;
- break;
- case WALK_MODAL_CONFIRM:
- walk->state = WALK_CONFIRM;
- break;
-
- case WALK_MODAL_ACCELERATE:
- base_speed *= 1.0f + (walk->is_slow ? 0.01f : 0.1f);
- break;
- case WALK_MODAL_DECELERATE:
- base_speed /= 1.0f + (walk->is_slow ? 0.01f : 0.1f);
- break;
-
- /* implement WASD keys */
- case WALK_MODAL_DIR_FORWARD:
- walk->active_directions |= WALK_BIT_FORWARD;
- break;
- case WALK_MODAL_DIR_BACKWARD:
- walk->active_directions |= WALK_BIT_BACKWARD;
- break;
- case WALK_MODAL_DIR_LEFT:
- walk->active_directions |= WALK_BIT_LEFT;
- break;
- case WALK_MODAL_DIR_RIGHT:
- walk->active_directions |= WALK_BIT_RIGHT;
- break;
- case WALK_MODAL_DIR_UP:
- walk->active_directions |= WALK_BIT_UP;
- break;
- case WALK_MODAL_DIR_DOWN:
- walk->active_directions |= WALK_BIT_DOWN;
- break;
-
- case WALK_MODAL_DIR_FORWARD_STOP:
- walk->active_directions &= ~WALK_BIT_FORWARD;
- break;
- case WALK_MODAL_DIR_BACKWARD_STOP:
- walk->active_directions &= ~WALK_BIT_BACKWARD;
- break;
- case WALK_MODAL_DIR_LEFT_STOP:
- walk->active_directions &= ~WALK_BIT_LEFT;
- break;
- case WALK_MODAL_DIR_RIGHT_STOP:
- walk->active_directions &= ~WALK_BIT_RIGHT;
- break;
- case WALK_MODAL_DIR_UP_STOP:
- walk->active_directions &= ~WALK_BIT_UP;
- break;
- case WALK_MODAL_DIR_DOWN_STOP:
- walk->active_directions &= ~WALK_BIT_DOWN;
- break;
-
- case WALK_MODAL_FAST_ENABLE:
- walk->is_fast = true;
- break;
- case WALK_MODAL_FAST_DISABLE:
- walk->is_fast = false;
- break;
- case WALK_MODAL_SLOW_ENABLE:
- walk->is_slow = true;
- break;
- case WALK_MODAL_SLOW_DISABLE:
- walk->is_slow = false;
- break;
+ /* handle modal keymap first */
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case WALK_MODAL_CANCEL:
+ walk->state = WALK_CANCEL;
+ break;
+ case WALK_MODAL_CONFIRM:
+ walk->state = WALK_CONFIRM;
+ break;
+
+ case WALK_MODAL_ACCELERATE:
+ base_speed *= 1.0f + (walk->is_slow ? 0.01f : 0.1f);
+ break;
+ case WALK_MODAL_DECELERATE:
+ base_speed /= 1.0f + (walk->is_slow ? 0.01f : 0.1f);
+ break;
+
+ /* implement WASD keys */
+ case WALK_MODAL_DIR_FORWARD:
+ walk->active_directions |= WALK_BIT_FORWARD;
+ break;
+ case WALK_MODAL_DIR_BACKWARD:
+ walk->active_directions |= WALK_BIT_BACKWARD;
+ break;
+ case WALK_MODAL_DIR_LEFT:
+ walk->active_directions |= WALK_BIT_LEFT;
+ break;
+ case WALK_MODAL_DIR_RIGHT:
+ walk->active_directions |= WALK_BIT_RIGHT;
+ break;
+ case WALK_MODAL_DIR_UP:
+ walk->active_directions |= WALK_BIT_UP;
+ break;
+ case WALK_MODAL_DIR_DOWN:
+ walk->active_directions |= WALK_BIT_DOWN;
+ break;
+
+ case WALK_MODAL_DIR_FORWARD_STOP:
+ walk->active_directions &= ~WALK_BIT_FORWARD;
+ break;
+ case WALK_MODAL_DIR_BACKWARD_STOP:
+ walk->active_directions &= ~WALK_BIT_BACKWARD;
+ break;
+ case WALK_MODAL_DIR_LEFT_STOP:
+ walk->active_directions &= ~WALK_BIT_LEFT;
+ break;
+ case WALK_MODAL_DIR_RIGHT_STOP:
+ walk->active_directions &= ~WALK_BIT_RIGHT;
+ break;
+ case WALK_MODAL_DIR_UP_STOP:
+ walk->active_directions &= ~WALK_BIT_UP;
+ break;
+ case WALK_MODAL_DIR_DOWN_STOP:
+ walk->active_directions &= ~WALK_BIT_DOWN;
+ break;
+
+ case WALK_MODAL_FAST_ENABLE:
+ walk->is_fast = true;
+ break;
+ case WALK_MODAL_FAST_DISABLE:
+ walk->is_fast = false;
+ break;
+ case WALK_MODAL_SLOW_ENABLE:
+ walk->is_slow = true;
+ break;
+ case WALK_MODAL_SLOW_DISABLE:
+ walk->is_slow = false;
+ break;
#define JUMP_SPEED_MIN 1.0f
#define JUMP_TIME_MAX 0.2f /* s */
#define JUMP_SPEED_MAX sqrtf(2.0f * walk->gravity * walk->jump_height)
- case WALK_MODAL_JUMP_STOP:
- if (walk->gravity_state == WALK_GRAVITY_STATE_JUMP) {
- float t;
-
- /* delta time */
- t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time);
-
- /* reduce the veolocity, if JUMP wasn't hold for long enough */
- t = min_ff(t, JUMP_TIME_MAX);
- walk->speed_jump = JUMP_SPEED_MIN + t * (JUMP_SPEED_MAX - JUMP_SPEED_MIN) / JUMP_TIME_MAX;
-
- /* when jumping, duration is how long it takes before we start going down */
- walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump);
-
- /* no more increase of jump speed */
- walk->gravity_state = WALK_GRAVITY_STATE_ON;
- }
- break;
- case WALK_MODAL_JUMP:
- if ((walk->navigation_mode == WALK_MODE_GRAVITY) &&
- (walk->gravity_state == WALK_GRAVITY_STATE_OFF) &&
- (walk->teleport.state == WALK_TELEPORT_STATE_OFF))
- {
- /* no need to check for ground,
- * walk->gravity wouldn't be off
- * if we were over a hole */
- walk->gravity_state = WALK_GRAVITY_STATE_JUMP;
- walk->speed_jump = JUMP_SPEED_MAX;
-
- walk->teleport.initial_time = PIL_check_seconds_timer();
- copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]);
-
- /* using previous vec because WASD keys are not called when SPACE is */
- copy_v2_v2(walk->teleport.direction, walk->dvec_prev);
-
- /* when jumping, duration is how long it takes before we start going down */
- walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump);
- }
-
- break;
-
- case WALK_MODAL_TELEPORT:
- {
- float loc[3], nor[3];
- float distance;
- bool ret = walk_ray_cast(walk->rv3d, walk, loc, nor, &distance);
-
- /* in case we are teleporting middle way from a jump */
- walk->speed_jump = 0.0f;
-
- if (ret) {
- WalkTeleport *teleport = &walk->teleport;
- teleport->state = WALK_TELEPORT_STATE_ON;
- teleport->initial_time = PIL_check_seconds_timer();
- teleport->duration = U.walk_navigation.teleport_time;
-
- teleport->navigation_mode = walk->navigation_mode;
- walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE);
-
- copy_v3_v3(teleport->origin, walk->rv3d->viewinv[3]);
-
- /* stop the camera from a distance (camera height) */
- normalize_v3_length(nor, walk->view_height);
- add_v3_v3(loc, nor);
-
- sub_v3_v3v3(teleport->direction, loc, teleport->origin);
- }
- else {
- walk->teleport.state = WALK_TELEPORT_STATE_OFF;
- }
- break;
- }
+ case WALK_MODAL_JUMP_STOP:
+ if (walk->gravity_state == WALK_GRAVITY_STATE_JUMP) {
+ float t;
+
+ /* delta time */
+ t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time);
+
+ /* reduce the veolocity, if JUMP wasn't hold for long enough */
+ t = min_ff(t, JUMP_TIME_MAX);
+ walk->speed_jump = JUMP_SPEED_MIN +
+ t * (JUMP_SPEED_MAX - JUMP_SPEED_MIN) / JUMP_TIME_MAX;
+
+ /* when jumping, duration is how long it takes before we start going down */
+ walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump);
+
+ /* no more increase of jump speed */
+ walk->gravity_state = WALK_GRAVITY_STATE_ON;
+ }
+ break;
+ case WALK_MODAL_JUMP:
+ if ((walk->navigation_mode == WALK_MODE_GRAVITY) &&
+ (walk->gravity_state == WALK_GRAVITY_STATE_OFF) &&
+ (walk->teleport.state == WALK_TELEPORT_STATE_OFF)) {
+ /* no need to check for ground,
+ * walk->gravity wouldn't be off
+ * if we were over a hole */
+ walk->gravity_state = WALK_GRAVITY_STATE_JUMP;
+ walk->speed_jump = JUMP_SPEED_MAX;
+
+ walk->teleport.initial_time = PIL_check_seconds_timer();
+ copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]);
+
+ /* using previous vec because WASD keys are not called when SPACE is */
+ copy_v2_v2(walk->teleport.direction, walk->dvec_prev);
+
+ /* when jumping, duration is how long it takes before we start going down */
+ walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump);
+ }
+
+ break;
+
+ case WALK_MODAL_TELEPORT: {
+ float loc[3], nor[3];
+ float distance;
+ bool ret = walk_ray_cast(walk->rv3d, walk, loc, nor, &distance);
+
+ /* in case we are teleporting middle way from a jump */
+ walk->speed_jump = 0.0f;
+
+ if (ret) {
+ WalkTeleport *teleport = &walk->teleport;
+ teleport->state = WALK_TELEPORT_STATE_ON;
+ teleport->initial_time = PIL_check_seconds_timer();
+ teleport->duration = U.walk_navigation.teleport_time;
+
+ teleport->navigation_mode = walk->navigation_mode;
+ walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE);
+
+ copy_v3_v3(teleport->origin, walk->rv3d->viewinv[3]);
+
+ /* stop the camera from a distance (camera height) */
+ normalize_v3_length(nor, walk->view_height);
+ add_v3_v3(loc, nor);
+
+ sub_v3_v3v3(teleport->direction, loc, teleport->origin);
+ }
+ else {
+ walk->teleport.state = WALK_TELEPORT_STATE_OFF;
+ }
+ break;
+ }
#undef JUMP_SPEED_MAX
#undef JUMP_TIME_MAX
#undef JUMP_SPEED_MIN
- case WALK_MODAL_TOGGLE:
- if (walk->navigation_mode == WALK_MODE_GRAVITY) {
- walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE);
- }
- else { /* WALK_MODE_FREE */
- walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY);
- }
- break;
- }
- }
+ case WALK_MODAL_TOGGLE:
+ if (walk->navigation_mode == WALK_MODE_GRAVITY) {
+ walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE);
+ }
+ else { /* WALK_MODE_FREE */
+ walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY);
+ }
+ break;
+ }
+ }
}
-static void walkMoveCamera(bContext *C, WalkInfo *walk,
- const bool do_rotate, const bool do_translate)
+static void walkMoveCamera(bContext *C,
+ WalkInfo *walk,
+ const bool do_rotate,
+ const bool do_translate)
{
- ED_view3d_cameracontrol_update(walk->v3d_camera_control, true, C, do_rotate, do_translate);
+ ED_view3d_cameracontrol_update(walk->v3d_camera_control, true, C, do_rotate, do_translate);
}
static float getFreeFallDistance(const float gravity, const float time)
{
- return gravity * (time * time) * 0.5f;
+ return gravity * (time * time) * 0.5f;
}
static float getVelocityZeroTime(const float gravity, const float velocity)
{
- return velocity / gravity;
+ return velocity / gravity;
}
static int walkApply(bContext *C, wmOperator *op, WalkInfo *walk)
@@ -938,361 +956,347 @@ static int walkApply(bContext *C, wmOperator *op, WalkInfo *walk)
#define WALK_MOVE_SPEED base_speed
#define WALK_BOOST_FACTOR ((void)0, walk->speed_factor)
- /* walk mode - Ctrl+Shift+F
- * 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;
+ /* walk mode - Ctrl+Shift+F
+ * 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;
- /* 3x3 copy of the view matrix so we can move along the view axis */
- float mat[3][3];
- /* this is the direction that's added to the view offset per redraw */
- float dvec[3] = {0.0f, 0.0f, 0.0f};
+ /* 3x3 copy of the view matrix so we can move along the view axis */
+ float mat[3][3];
+ /* this is the direction that's added to the view offset per redraw */
+ float dvec[3] = {0.0f, 0.0f, 0.0f};
- int moffset[2]; /* mouse offset from the views center */
- float tmp_quat[4]; /* used for rotating the view */
+ int moffset[2]; /* mouse offset from the views center */
+ float tmp_quat[4]; /* used for rotating the view */
#ifdef NDOF_WALK_DEBUG
- {
- static uint iteration = 1;
- printf("walk timer %d\n", iteration++);
- }
+ {
+ static uint iteration = 1;
+ printf("walk timer %d\n", iteration++);
+ }
#endif
- {
- /* mouse offset from the center */
- copy_v2_v2_int(moffset, walk->moffset);
-
- /* apply moffset so we can re-accumulate */
- walk->moffset[0] = 0;
- walk->moffset[1] = 0;
-
- /* revert mouse */
- if (walk->is_reversed) {
- moffset[1] = -moffset[1];
- }
-
- /* Should we redraw? */
- if ((walk->active_directions) ||
- moffset[0] || moffset[1] ||
- walk->teleport.state == WALK_TELEPORT_STATE_ON ||
- walk->gravity_state != WALK_GRAVITY_STATE_OFF)
- {
- float dvec_tmp[3];
-
- /* time how fast it takes for us to redraw,
- * this is so simple scenes don't walk too fast */
- double time_current;
- float time_redraw;
+ {
+ /* mouse offset from the center */
+ copy_v2_v2_int(moffset, walk->moffset);
+
+ /* apply moffset so we can re-accumulate */
+ walk->moffset[0] = 0;
+ walk->moffset[1] = 0;
+
+ /* revert mouse */
+ if (walk->is_reversed) {
+ moffset[1] = -moffset[1];
+ }
+
+ /* Should we redraw? */
+ if ((walk->active_directions) || moffset[0] || moffset[1] ||
+ walk->teleport.state == WALK_TELEPORT_STATE_ON ||
+ walk->gravity_state != WALK_GRAVITY_STATE_OFF) {
+ float dvec_tmp[3];
+
+ /* time how fast it takes for us to redraw,
+ * this is so simple scenes don't walk too fast */
+ double time_current;
+ float time_redraw;
#ifdef NDOF_WALK_DRAW_TOOMUCH
- walk->redraw = 1;
+ walk->redraw = 1;
#endif
- time_current = PIL_check_seconds_timer();
- time_redraw = (float)(time_current - walk->time_lastdraw);
-
- walk->time_lastdraw = time_current;
-
- /* base speed in m/s */
- walk->speed = WALK_MOVE_SPEED;
-
- if (walk->is_fast) {
- walk->speed *= WALK_BOOST_FACTOR;
- }
- else if (walk->is_slow) {
- walk->speed *= 1.0f / WALK_BOOST_FACTOR;
- }
-
- copy_m3_m4(mat, rv3d->viewinv);
+ time_current = PIL_check_seconds_timer();
+ time_redraw = (float)(time_current - walk->time_lastdraw);
- {
- /* rotate about the X axis- look up/down */
- if (moffset[1]) {
- float upvec[3];
- float angle;
- float y;
+ walk->time_lastdraw = time_current;
- /* relative offset */
- y = (float) moffset[1] / ar->winy;
+ /* base speed in m/s */
+ walk->speed = WALK_MOVE_SPEED;
- /* speed factor */
- y *= WALK_ROTATE_FAC;
+ if (walk->is_fast) {
+ walk->speed *= WALK_BOOST_FACTOR;
+ }
+ else if (walk->is_slow) {
+ walk->speed *= 1.0f / WALK_BOOST_FACTOR;
+ }
- /* user adjustment factor */
- y *= walk->mouse_speed;
+ copy_m3_m4(mat, rv3d->viewinv);
- /* clamp the angle limits */
- /* it ranges from 90.0f to -90.0f */
- angle = -asinf(rv3d->viewmat[2][2]);
+ {
+ /* rotate about the X axis- look up/down */
+ if (moffset[1]) {
+ float upvec[3];
+ float angle;
+ float y;
- if (angle > WALK_TOP_LIMIT && y > 0.0f) {
- y = 0.0f;
- }
- else if (angle < WALK_BOTTOM_LIMIT && y < 0.0f) {
- y = 0.0f;
- }
+ /* relative offset */
+ y = (float)moffset[1] / ar->winy;
- copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
- mul_m3_v3(mat, upvec);
- /* Rotate about the relative up vec */
- axis_angle_to_quat(tmp_quat, upvec, -y);
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
- }
+ /* speed factor */
+ y *= WALK_ROTATE_FAC;
- /* rotate about the Y axis- look left/right */
- if (moffset[0]) {
- float upvec[3];
- float x;
+ /* user adjustment factor */
+ y *= walk->mouse_speed;
- /* if we're upside down invert the moffset */
- copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f);
- mul_m3_v3(mat, upvec);
+ /* clamp the angle limits */
+ /* it ranges from 90.0f to -90.0f */
+ angle = -asinf(rv3d->viewmat[2][2]);
- if (upvec[2] < 0.0f) {
- moffset[0] = -moffset[0];
- }
+ if (angle > WALK_TOP_LIMIT && y > 0.0f) {
+ y = 0.0f;
+ }
+ else if (angle < WALK_BOTTOM_LIMIT && y < 0.0f) {
+ y = 0.0f;
+ }
- /* relative offset */
- x = (float) moffset[0] / ar->winx;
+ copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
+ mul_m3_v3(mat, upvec);
+ /* Rotate about the relative up vec */
+ axis_angle_to_quat(tmp_quat, upvec, -y);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
+ }
- /* speed factor */
- x *= WALK_ROTATE_FAC;
+ /* rotate about the Y axis- look left/right */
+ if (moffset[0]) {
+ float upvec[3];
+ float x;
- /* user adjustment factor */
- x *= walk->mouse_speed;
+ /* if we're upside down invert the moffset */
+ copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f);
+ mul_m3_v3(mat, upvec);
- /* Rotate about the relative up vec */
- axis_angle_to_quat_single(tmp_quat, 'Z', x);
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
- }
- }
+ if (upvec[2] < 0.0f) {
+ moffset[0] = -moffset[0];
+ }
- /* WASD - 'move' translation code */
- if ((walk->active_directions) &&
- (walk->gravity_state == WALK_GRAVITY_STATE_OFF))
- {
+ /* relative offset */
+ x = (float)moffset[0] / ar->winx;
- short direction;
- zero_v3(dvec);
+ /* speed factor */
+ x *= WALK_ROTATE_FAC;
- if ((walk->active_directions & WALK_BIT_FORWARD) ||
- (walk->active_directions & WALK_BIT_BACKWARD))
- {
+ /* user adjustment factor */
+ x *= walk->mouse_speed;
- direction = 0;
+ /* Rotate about the relative up vec */
+ axis_angle_to_quat_single(tmp_quat, 'Z', x);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
+ }
+ }
- if ((walk->active_directions & WALK_BIT_FORWARD)) {
- direction += 1;
- }
+ /* WASD - 'move' translation code */
+ if ((walk->active_directions) && (walk->gravity_state == WALK_GRAVITY_STATE_OFF)) {
- if ((walk->active_directions & WALK_BIT_BACKWARD)) {
- direction -= 1;
- }
+ short direction;
+ zero_v3(dvec);
- copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction);
- mul_m3_v3(mat, dvec_tmp);
+ if ((walk->active_directions & WALK_BIT_FORWARD) ||
+ (walk->active_directions & WALK_BIT_BACKWARD)) {
- if (walk->navigation_mode == WALK_MODE_GRAVITY) {
- dvec_tmp[2] = 0.0f;
- }
+ direction = 0;
- normalize_v3(dvec_tmp);
- add_v3_v3(dvec, dvec_tmp);
+ if ((walk->active_directions & WALK_BIT_FORWARD)) {
+ direction += 1;
+ }
- }
+ if ((walk->active_directions & WALK_BIT_BACKWARD)) {
+ direction -= 1;
+ }
- if ((walk->active_directions & WALK_BIT_LEFT) ||
- (walk->active_directions & WALK_BIT_RIGHT))
- {
+ copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction);
+ mul_m3_v3(mat, dvec_tmp);
- direction = 0;
+ if (walk->navigation_mode == WALK_MODE_GRAVITY) {
+ dvec_tmp[2] = 0.0f;
+ }
- if ((walk->active_directions & WALK_BIT_LEFT)) {
- direction += 1;
- }
+ normalize_v3(dvec_tmp);
+ add_v3_v3(dvec, dvec_tmp);
+ }
- if ((walk->active_directions & WALK_BIT_RIGHT)) {
- direction -= 1;
- }
+ if ((walk->active_directions & WALK_BIT_LEFT) ||
+ (walk->active_directions & WALK_BIT_RIGHT)) {
- dvec_tmp[0] = direction * rv3d->viewinv[0][0];
- dvec_tmp[1] = direction * rv3d->viewinv[0][1];
- dvec_tmp[2] = 0.0f;
+ direction = 0;
- normalize_v3(dvec_tmp);
- add_v3_v3(dvec, dvec_tmp);
+ if ((walk->active_directions & WALK_BIT_LEFT)) {
+ direction += 1;
+ }
- }
+ if ((walk->active_directions & WALK_BIT_RIGHT)) {
+ direction -= 1;
+ }
- if ((walk->active_directions & WALK_BIT_UP) ||
- (walk->active_directions & WALK_BIT_DOWN))
- {
+ dvec_tmp[0] = direction * rv3d->viewinv[0][0];
+ dvec_tmp[1] = direction * rv3d->viewinv[0][1];
+ dvec_tmp[2] = 0.0f;
- if (walk->navigation_mode == WALK_MODE_FREE) {
+ normalize_v3(dvec_tmp);
+ add_v3_v3(dvec, dvec_tmp);
+ }
- direction = 0;
-
- if ((walk->active_directions & WALK_BIT_UP)) {
- direction -= 1;
- }
-
- if ((walk->active_directions & WALK_BIT_DOWN)) {
- direction = 1;
- }
-
- copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction);
- add_v3_v3(dvec, dvec_tmp);
- }
- }
-
- /* apply movement */
- mul_v3_fl(dvec, walk->speed * time_redraw);
- }
-
- /* stick to the floor */
- if (walk->navigation_mode == WALK_MODE_GRAVITY &&
- ELEM(walk->gravity_state,
- WALK_GRAVITY_STATE_OFF,
- WALK_GRAVITY_STATE_START))
- {
-
- bool ret;
- float ray_distance;
- float difference = -100.0f;
- float fall_distance;
-
- ret = walk_floor_distance_get(rv3d, walk, dvec, &ray_distance);
-
- if (ret) {
- difference = walk->view_height - ray_distance;
- }
-
- /* the distance we would fall naturally smoothly enough that we
- * can manually drop the object without activating gravity */
- fall_distance = time_redraw * walk->speed * WALK_BOOST_FACTOR;
-
- if (fabsf(difference) < fall_distance) {
- /* slope/stairs */
- dvec[2] -= difference;
-
- /* in case we switched from FREE to GRAVITY too close to the ground */
- if (walk->gravity_state == WALK_GRAVITY_STATE_START) {
- walk->gravity_state = WALK_GRAVITY_STATE_OFF;
- }
- }
- else {
- /* hijack the teleport variables */
- walk->teleport.initial_time = PIL_check_seconds_timer();
- walk->gravity_state = WALK_GRAVITY_STATE_ON;
- walk->teleport.duration = 0.0f;
-
- copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]);
- copy_v2_v2(walk->teleport.direction, dvec);
-
- }
- }
-
- /* Falling or jumping) */
- if (ELEM(walk->gravity_state, WALK_GRAVITY_STATE_ON, WALK_GRAVITY_STATE_JUMP)) {
- float t;
- float z_cur, z_new;
- bool ret;
- float ray_distance, difference = -100.0f;
-
- /* delta time */
- t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time);
-
- /* keep moving if we were moving */
- copy_v2_v2(dvec, walk->teleport.direction);
-
- z_cur = walk->rv3d->viewinv[3][2];
- z_new = walk->teleport.origin[2] - getFreeFallDistance(walk->gravity, t) * walk->grid;
-
- /* jump */
- z_new += t * walk->speed_jump * walk->grid;
-
- /* duration is the jump duration */
- if (t > walk->teleport.duration) {
-
- /* check to see if we are landing */
- ret = walk_floor_distance_get(rv3d, walk, dvec, &ray_distance);
-
- if (ret) {
- difference = walk->view_height - ray_distance;
- }
-
- if (difference > 0.0f) {
- /* quit falling, lands at "view_height" from the floor */
- dvec[2] -= difference;
- walk->gravity_state = WALK_GRAVITY_STATE_OFF;
- walk->speed_jump = 0.0f;
- }
- else {
- /* keep falling */
- dvec[2] = z_cur - z_new;
- }
- }
- else {
- /* keep going up (jump) */
- dvec[2] = z_cur - z_new;
- }
- }
-
- /* Teleport */
- else if (walk->teleport.state == WALK_TELEPORT_STATE_ON) {
- float t; /* factor */
- float new_loc[3];
- float cur_loc[3];
-
- /* linear interpolation */
- t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time);
- t /= walk->teleport.duration;
-
- /* clamp so we don't go past our limit */
- if (t >= 1.0f) {
- t = 1.0f;
- walk->teleport.state = WALK_TELEPORT_STATE_OFF;
- walk_navigation_mode_set(C, op, walk, walk->teleport.navigation_mode);
- }
-
- mul_v3_v3fl(new_loc, walk->teleport.direction, t);
- add_v3_v3(new_loc, walk->teleport.origin);
-
- copy_v3_v3(cur_loc, walk->rv3d->viewinv[3]);
- sub_v3_v3v3(dvec, cur_loc, new_loc);
- }
-
- if (rv3d->persp == RV3D_CAMOB) {
- Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control);
- if (lock_ob->protectflag & OB_LOCK_LOCX) {
- dvec[0] = 0.0f;
- }
- if (lock_ob->protectflag & OB_LOCK_LOCY) {
- dvec[1] = 0.0f;
- }
- if (lock_ob->protectflag & OB_LOCK_LOCZ) {
- dvec[2] = 0.0f;
- }
- }
-
- /* scale the movement to the scene size */
- mul_v3_v3fl(dvec_tmp, dvec, walk->grid);
- add_v3_v3(rv3d->ofs, dvec_tmp);
-
- if (rv3d->persp == RV3D_CAMOB) {
- const bool do_rotate = (moffset[0] || moffset[1]);
- const bool do_translate = (walk->speed != 0.0f);
- walkMoveCamera(C, walk, do_rotate, do_translate);
- }
- }
- else {
- /* we're not redrawing but we need to update the time else the view will jump */
- walk->time_lastdraw = PIL_check_seconds_timer();
- }
- /* end drawing */
- copy_v3_v3(walk->dvec_prev, dvec);
- }
-
- return OPERATOR_FINISHED;
+ if ((walk->active_directions & WALK_BIT_UP) || (walk->active_directions & WALK_BIT_DOWN)) {
+
+ if (walk->navigation_mode == WALK_MODE_FREE) {
+
+ direction = 0;
+
+ if ((walk->active_directions & WALK_BIT_UP)) {
+ direction -= 1;
+ }
+
+ if ((walk->active_directions & WALK_BIT_DOWN)) {
+ direction = 1;
+ }
+
+ copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction);
+ add_v3_v3(dvec, dvec_tmp);
+ }
+ }
+
+ /* apply movement */
+ mul_v3_fl(dvec, walk->speed * time_redraw);
+ }
+
+ /* stick to the floor */
+ if (walk->navigation_mode == WALK_MODE_GRAVITY &&
+ ELEM(walk->gravity_state, WALK_GRAVITY_STATE_OFF, WALK_GRAVITY_STATE_START)) {
+
+ bool ret;
+ float ray_distance;
+ float difference = -100.0f;
+ float fall_distance;
+
+ ret = walk_floor_distance_get(rv3d, walk, dvec, &ray_distance);
+
+ if (ret) {
+ difference = walk->view_height - ray_distance;
+ }
+
+ /* the distance we would fall naturally smoothly enough that we
+ * can manually drop the object without activating gravity */
+ fall_distance = time_redraw * walk->speed * WALK_BOOST_FACTOR;
+
+ if (fabsf(difference) < fall_distance) {
+ /* slope/stairs */
+ dvec[2] -= difference;
+
+ /* in case we switched from FREE to GRAVITY too close to the ground */
+ if (walk->gravity_state == WALK_GRAVITY_STATE_START) {
+ walk->gravity_state = WALK_GRAVITY_STATE_OFF;
+ }
+ }
+ else {
+ /* hijack the teleport variables */
+ walk->teleport.initial_time = PIL_check_seconds_timer();
+ walk->gravity_state = WALK_GRAVITY_STATE_ON;
+ walk->teleport.duration = 0.0f;
+
+ copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]);
+ copy_v2_v2(walk->teleport.direction, dvec);
+ }
+ }
+
+ /* Falling or jumping) */
+ if (ELEM(walk->gravity_state, WALK_GRAVITY_STATE_ON, WALK_GRAVITY_STATE_JUMP)) {
+ float t;
+ float z_cur, z_new;
+ bool ret;
+ float ray_distance, difference = -100.0f;
+
+ /* delta time */
+ t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time);
+
+ /* keep moving if we were moving */
+ copy_v2_v2(dvec, walk->teleport.direction);
+
+ z_cur = walk->rv3d->viewinv[3][2];
+ z_new = walk->teleport.origin[2] - getFreeFallDistance(walk->gravity, t) * walk->grid;
+
+ /* jump */
+ z_new += t * walk->speed_jump * walk->grid;
+
+ /* duration is the jump duration */
+ if (t > walk->teleport.duration) {
+
+ /* check to see if we are landing */
+ ret = walk_floor_distance_get(rv3d, walk, dvec, &ray_distance);
+
+ if (ret) {
+ difference = walk->view_height - ray_distance;
+ }
+
+ if (difference > 0.0f) {
+ /* quit falling, lands at "view_height" from the floor */
+ dvec[2] -= difference;
+ walk->gravity_state = WALK_GRAVITY_STATE_OFF;
+ walk->speed_jump = 0.0f;
+ }
+ else {
+ /* keep falling */
+ dvec[2] = z_cur - z_new;
+ }
+ }
+ else {
+ /* keep going up (jump) */
+ dvec[2] = z_cur - z_new;
+ }
+ }
+
+ /* Teleport */
+ else if (walk->teleport.state == WALK_TELEPORT_STATE_ON) {
+ float t; /* factor */
+ float new_loc[3];
+ float cur_loc[3];
+
+ /* linear interpolation */
+ t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time);
+ t /= walk->teleport.duration;
+
+ /* clamp so we don't go past our limit */
+ if (t >= 1.0f) {
+ t = 1.0f;
+ walk->teleport.state = WALK_TELEPORT_STATE_OFF;
+ walk_navigation_mode_set(C, op, walk, walk->teleport.navigation_mode);
+ }
+
+ mul_v3_v3fl(new_loc, walk->teleport.direction, t);
+ add_v3_v3(new_loc, walk->teleport.origin);
+
+ copy_v3_v3(cur_loc, walk->rv3d->viewinv[3]);
+ sub_v3_v3v3(dvec, cur_loc, new_loc);
+ }
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control);
+ if (lock_ob->protectflag & OB_LOCK_LOCX) {
+ dvec[0] = 0.0f;
+ }
+ if (lock_ob->protectflag & OB_LOCK_LOCY) {
+ dvec[1] = 0.0f;
+ }
+ if (lock_ob->protectflag & OB_LOCK_LOCZ) {
+ dvec[2] = 0.0f;
+ }
+ }
+
+ /* scale the movement to the scene size */
+ mul_v3_v3fl(dvec_tmp, dvec, walk->grid);
+ add_v3_v3(rv3d->ofs, dvec_tmp);
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ const bool do_rotate = (moffset[0] || moffset[1]);
+ const bool do_translate = (walk->speed != 0.0f);
+ walkMoveCamera(C, walk, do_rotate, do_translate);
+ }
+ }
+ else {
+ /* we're not redrawing but we need to update the time else the view will jump */
+ walk->time_lastdraw = PIL_check_seconds_timer();
+ }
+ /* end drawing */
+ copy_v3_v3(walk->dvec_prev, dvec);
+ }
+
+ return OPERATOR_FINISHED;
#undef WALK_ROTATE_FAC
#undef WALK_ZUP_CORRECT_FAC
#undef WALK_ZUP_CORRECT_ACCEL
@@ -1306,121 +1310,124 @@ static int walkApply(bContext *C, wmOperator *op, WalkInfo *walk)
#ifdef WITH_INPUT_NDOF
static void walkApply_ndof(bContext *C, WalkInfo *walk)
{
- Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control);
- bool has_translate, has_rotate;
-
- view3d_ndof_fly(walk->ndof,
- walk->v3d, walk->rv3d,
- walk->is_slow, lock_ob ? lock_ob->protectflag : 0,
- &has_translate, &has_rotate);
-
- if (has_translate || has_rotate) {
- walk->redraw = true;
-
- if (walk->rv3d->persp == RV3D_CAMOB) {
- walkMoveCamera(C, walk, has_rotate, has_translate);
- }
- }
+ Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control);
+ bool has_translate, has_rotate;
+
+ view3d_ndof_fly(walk->ndof,
+ walk->v3d,
+ walk->rv3d,
+ walk->is_slow,
+ lock_ob ? lock_ob->protectflag : 0,
+ &has_translate,
+ &has_rotate);
+
+ if (has_translate || has_rotate) {
+ walk->redraw = true;
+
+ if (walk->rv3d->persp == RV3D_CAMOB) {
+ walkMoveCamera(C, walk, has_rotate, has_translate);
+ }
+ }
}
#endif /* WITH_INPUT_NDOF */
/****** walk operator ******/
static int walk_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- WalkInfo *walk;
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ WalkInfo *walk;
- if (rv3d->viewlock & RV3D_LOCKED) {
- return OPERATOR_CANCELLED;
- }
+ if (rv3d->viewlock & RV3D_LOCKED) {
+ return OPERATOR_CANCELLED;
+ }
- walk = MEM_callocN(sizeof(WalkInfo), "NavigationWalkOperation");
+ walk = MEM_callocN(sizeof(WalkInfo), "NavigationWalkOperation");
- op->customdata = walk;
+ op->customdata = walk;
- if (initWalkInfo(C, walk, op) == false) {
- MEM_freeN(op->customdata);
- return OPERATOR_CANCELLED;
- }
+ if (initWalkInfo(C, walk, op) == false) {
+ MEM_freeN(op->customdata);
+ return OPERATOR_CANCELLED;
+ }
- walkEvent(C, op, walk, event);
+ walkEvent(C, op, walk, event);
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static void walk_cancel(bContext *C, wmOperator *op)
{
- WalkInfo *walk = op->customdata;
+ WalkInfo *walk = op->customdata;
- walk->state = WALK_CANCEL;
- walkEnd(C, walk);
- op->customdata = NULL;
+ walk->state = WALK_CANCEL;
+ walkEnd(C, walk);
+ op->customdata = NULL;
}
static int walk_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- int exit_code;
- bool do_draw = false;
- WalkInfo *walk = op->customdata;
- RegionView3D *rv3d = walk->rv3d;
- Object *walk_object = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control);
+ int exit_code;
+ bool do_draw = false;
+ WalkInfo *walk = op->customdata;
+ RegionView3D *rv3d = walk->rv3d;
+ Object *walk_object = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control);
- walk->redraw = false;
+ walk->redraw = false;
- walkEvent(C, op, walk, event);
+ walkEvent(C, op, walk, event);
#ifdef WITH_INPUT_NDOF
- if (walk->ndof) { /* 3D mouse overrules [2D mouse + timer] */
- if (event->type == NDOF_MOTION) {
- walkApply_ndof(C, walk);
- }
- }
- else
+ if (walk->ndof) { /* 3D mouse overrules [2D mouse + timer] */
+ if (event->type == NDOF_MOTION) {
+ walkApply_ndof(C, walk);
+ }
+ }
+ else
#endif /* WITH_INPUT_NDOF */
- if (event->type == TIMER && event->customdata == walk->timer) {
- walkApply(C, op, walk);
- }
+ if (event->type == TIMER && event->customdata == walk->timer) {
+ walkApply(C, op, walk);
+ }
- do_draw |= walk->redraw;
+ do_draw |= walk->redraw;
- exit_code = walkEnd(C, walk);
+ exit_code = walkEnd(C, walk);
- if (exit_code != OPERATOR_RUNNING_MODAL) {
- do_draw = true;
- }
+ if (exit_code != OPERATOR_RUNNING_MODAL) {
+ do_draw = true;
+ }
- if (do_draw) {
- if (rv3d->persp == RV3D_CAMOB) {
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, walk_object);
- }
+ if (do_draw) {
+ if (rv3d->persp == RV3D_CAMOB) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, walk_object);
+ }
- // too frequent, commented with NDOF_WALK_DRAW_TOOMUCH for now
- // puts("redraw!");
- ED_region_tag_redraw(CTX_wm_region(C));
- }
+ // too frequent, commented with NDOF_WALK_DRAW_TOOMUCH for now
+ // puts("redraw!");
+ ED_region_tag_redraw(CTX_wm_region(C));
+ }
- if (ELEM(exit_code, OPERATOR_FINISHED, OPERATOR_CANCELLED)) {
- ED_workspace_status_text(C, NULL);
- }
+ if (ELEM(exit_code, OPERATOR_FINISHED, OPERATOR_CANCELLED)) {
+ ED_workspace_status_text(C, NULL);
+ }
- return exit_code;
+ return exit_code;
}
void VIEW3D_OT_walk(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Walk Navigation";
- ot->description = "Interactively walk around the scene";
- ot->idname = "VIEW3D_OT_walk";
-
- /* api callbacks */
- ot->invoke = walk_invoke;
- ot->cancel = walk_cancel;
- ot->modal = walk_modal;
- ot->poll = ED_operator_region_view3d_active;
-
- /* flags */
- ot->flag = OPTYPE_BLOCKING;
+ /* identifiers */
+ ot->name = "Walk Navigation";
+ ot->description = "Interactively walk around the scene";
+ ot->idname = "VIEW3D_OT_walk";
+
+ /* api callbacks */
+ ot->invoke = walk_invoke;
+ ot->cancel = walk_cancel;
+ ot->modal = walk_modal;
+ ot->poll = ED_operator_region_view3d_active;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
}
diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt
index c475a9e4e3d..05e0659637b 100644
--- a/source/blender/editors/transform/CMakeLists.txt
+++ b/source/blender/editors/transform/CMakeLists.txt
@@ -16,55 +16,55 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenfont
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../bmesh
- ../../gpu
- ../../ikplugin
- ../../makesdna
- ../../makesrna
- ../../render/extern/include
- ../../windowmanager
- ../../depsgraph
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenfont
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../bmesh
+ ../../gpu
+ ../../ikplugin
+ ../../makesdna
+ ../../makesrna
+ ../../render/extern/include
+ ../../windowmanager
+ ../../depsgraph
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- transform.c
- transform_constraints.c
- transform_conversions.c
- transform_generics.c
- transform_gizmo_2d.c
- transform_gizmo_3d.c
- transform_gizmo_extrude_3d.c
- transform_input.c
- transform_ops.c
- transform_orientations.c
- transform_snap.c
- transform_snap_object.c
+ transform.c
+ transform_constraints.c
+ transform_conversions.c
+ transform_generics.c
+ transform_gizmo_2d.c
+ transform_gizmo_3d.c
+ transform_gizmo_extrude_3d.c
+ transform_input.c
+ transform_ops.c
+ transform_orientations.c
+ transform_snap.c
+ transform_snap_object.c
- transform.h
+ transform.h
)
set(LIB
- bf_blenfont
- bf_blenkernel
- bf_blenlib
- bf_bmesh
- bf_editor_mask
- bf_gpu
+ bf_blenfont
+ bf_blenkernel
+ bf_blenlib
+ bf_bmesh
+ bf_editor_mask
+ bf_gpu
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 1358b526bca..944c6436dfb 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -35,7 +35,7 @@
#include "DNA_mask_types.h"
#include "DNA_mesh_types.h"
#include "DNA_movieclip_types.h"
-#include "DNA_scene_types.h" /* PET modes */
+#include "DNA_scene_types.h" /* PET modes */
#include "DNA_workspace_types.h"
#include "DNA_gpencil_types.h"
@@ -107,7 +107,8 @@ static void drawEdgeSlide(TransInfo *t);
static void drawVertSlide(TransInfo *t);
static void postInputRotation(TransInfo *t, float values[3]);
-static void ElementRotation(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around);
+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);
@@ -175,7 +176,8 @@ 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_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]);
@@ -210,496 +212,489 @@ 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)))
- );
+ 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))));
}
/* ************************** 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->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = t->ar->regiondata;
- copy_m4_m4(t->viewmat, rv3d->viewmat);
- copy_m4_m4(t->viewinv, rv3d->viewinv);
- copy_m4_m4(t->persmat, rv3d->persmat);
- copy_m4_m4(t->persinv, rv3d->persinv);
- t->persp = rv3d->persp;
- }
- else {
- unit_m4(t->viewmat);
- unit_m4(t->viewinv);
- unit_m4(t->persmat);
- unit_m4(t->persinv);
- t->persp = RV3D_ORTHO;
- }
+ copy_m4_m4(t->viewmat, rv3d->viewmat);
+ copy_m4_m4(t->viewinv, rv3d->viewinv);
+ copy_m4_m4(t->persmat, rv3d->persmat);
+ copy_m4_m4(t->persinv, rv3d->persinv);
+ t->persp = rv3d->persp;
+ }
+ else {
+ unit_m4(t->viewmat);
+ unit_m4(t->viewinv);
+ unit_m4(t->persmat);
+ unit_m4(t->persinv);
+ t->persp = RV3D_ORTHO;
+ }
- calculateCenter2D(t);
- calculateCenterLocal(t, t->center_global);
+ calculateCenter2D(t);
+ calculateCenterLocal(t, t->center_global);
}
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;
-
- if (t->options & CTX_MASK) {
- ED_space_image_get_aspect(sima, &r_aspect[0], &r_aspect[1]);
- }
- else if (t->options & CTX_PAINT_CURVE) {
- /* pass */
- }
- else {
- ED_space_image_get_uv_aspect(sima, &r_aspect[0], &r_aspect[1]);
- }
- }
- else if (t->spacetype == SPACE_CLIP) {
- SpaceClip *sclip = t->sa->spacedata.first;
-
- if (t->options & CTX_MOVIECLIP) {
- ED_space_clip_get_aspect_dimension_aware(sclip, &r_aspect[0], &r_aspect[1]);
- }
- else {
- ED_space_clip_get_aspect(sclip, &r_aspect[0], &r_aspect[1]);
- }
- }
- else if (t->spacetype == SPACE_GRAPH) {
- /* depemds on context of usage */
- }
+ copy_v3_fl(r_aspect, 1.0f);
+
+ if (t->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = t->sa->spacedata.first;
+
+ if (t->options & CTX_MASK) {
+ ED_space_image_get_aspect(sima, &r_aspect[0], &r_aspect[1]);
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ /* pass */
+ }
+ else {
+ ED_space_image_get_uv_aspect(sima, &r_aspect[0], &r_aspect[1]);
+ }
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *sclip = t->sa->spacedata.first;
+
+ if (t->options & CTX_MOVIECLIP) {
+ ED_space_clip_get_aspect_dimension_aware(sclip, &r_aspect[0], &r_aspect[1]);
+ }
+ else {
+ ED_space_clip_get_aspect(sclip, &r_aspect[0], &r_aspect[1]);
+ }
+ }
+ else if (t->spacetype == SPACE_GRAPH) {
+ /* depemds on context of usage */
+ }
}
static void convertViewVec2D(View2D *v2d, float r_vec[3], int dx, int dy)
{
- float divx = BLI_rcti_size_x(&v2d->mask);
- float divy = BLI_rcti_size_y(&v2d->mask);
+ float divx = BLI_rcti_size_x(&v2d->mask);
+ float divy = BLI_rcti_size_y(&v2d->mask);
- r_vec[0] = BLI_rctf_size_x(&v2d->cur) * dx / divx;
- r_vec[1] = BLI_rctf_size_y(&v2d->cur) * dy / divy;
- r_vec[2] = 0.0f;
+ r_vec[0] = BLI_rctf_size_x(&v2d->cur) * dx / divx;
+ r_vec[1] = BLI_rctf_size_y(&v2d->cur) * dy / divy;
+ r_vec[2] = 0.0f;
}
static void convertViewVec2D_mask(View2D *v2d, float r_vec[3], int dx, int dy)
{
- float divx = BLI_rcti_size_x(&v2d->mask);
- float divy = BLI_rcti_size_y(&v2d->mask);
+ float divx = BLI_rcti_size_x(&v2d->mask);
+ float divy = BLI_rcti_size_y(&v2d->mask);
- float mulx = BLI_rctf_size_x(&v2d->cur);
- float muly = BLI_rctf_size_y(&v2d->cur);
+ float mulx = BLI_rctf_size_x(&v2d->cur);
+ float muly = BLI_rctf_size_y(&v2d->cur);
- /* difference with convertViewVec2D */
- /* clamp w/h, mask only */
- if (mulx / divx < muly / divy) {
- divy = divx;
- muly = mulx;
- }
- else {
- divx = divy;
- mulx = muly;
- }
- /* end difference */
+ /* difference with convertViewVec2D */
+ /* clamp w/h, mask only */
+ if (mulx / divx < muly / divy) {
+ divy = divx;
+ muly = mulx;
+ }
+ else {
+ divx = divy;
+ mulx = muly;
+ }
+ /* end difference */
- r_vec[0] = mulx * dx / divx;
- r_vec[1] = muly * dy / divy;
- r_vec[2] = 0.0f;
+ r_vec[0] = mulx * dx / divx;
+ r_vec[1] = muly * dy / divy;
+ r_vec[2] = 0.0f;
}
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->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);
- }
- }
- else if (t->spacetype == SPACE_IMAGE) {
- if (t->options & CTX_MASK) {
- convertViewVec2D_mask(t->view, r_vec, dx, dy);
- }
- else if (t->options & CTX_PAINT_CURVE) {
- r_vec[0] = dx;
- r_vec[1] = dy;
- }
- else {
- convertViewVec2D(t->view, r_vec, dx, dy);
- }
-
- r_vec[0] *= t->aspect[0];
- r_vec[1] *= t->aspect[1];
- }
- else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) {
- convertViewVec2D(t->view, r_vec, dx, dy);
- }
- else if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) {
- convertViewVec2D(&t->ar->v2d, r_vec, dx, dy);
- }
- else if (t->spacetype == SPACE_CLIP) {
- if (t->options & CTX_MASK) {
- convertViewVec2D_mask(t->view, r_vec, dx, dy);
- }
- else {
- convertViewVec2D(t->view, r_vec, dx, dy);
- }
-
- r_vec[0] *= t->aspect[0];
- r_vec[1] *= t->aspect[1];
- }
- else {
- printf("%s: called in an invalid context\n", __func__);
- zero_v3(r_vec);
- }
+ if ((t->spacetype == SPACE_VIEW3D) && (t->ar->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);
+ }
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ if (t->options & CTX_MASK) {
+ convertViewVec2D_mask(t->view, r_vec, dx, dy);
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ r_vec[0] = dx;
+ r_vec[1] = dy;
+ }
+ else {
+ convertViewVec2D(t->view, r_vec, dx, dy);
+ }
+
+ r_vec[0] *= t->aspect[0];
+ r_vec[1] *= t->aspect[1];
+ }
+ else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) {
+ convertViewVec2D(t->view, r_vec, dx, dy);
+ }
+ else if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) {
+ convertViewVec2D(&t->ar->v2d, r_vec, dx, dy);
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ if (t->options & CTX_MASK) {
+ convertViewVec2D_mask(t->view, r_vec, dx, dy);
+ }
+ else {
+ convertViewVec2D(t->view, r_vec, dx, dy);
+ }
+
+ r_vec[0] *= t->aspect[0];
+ r_vec[1] *= t->aspect[1];
+ }
+ else {
+ printf("%s: called in an invalid context\n", __func__);
+ zero_v3(r_vec);
+ }
}
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) {
- /* this is what was done in 2.64, perhaps we can be smarter? */
- adr[0] = (int)2140000000.0f;
- adr[1] = (int)2140000000.0f;
- }
- }
- }
- else if (t->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = t->sa->spacedata.first;
-
- if (t->options & CTX_MASK) {
- float v[2];
-
- v[0] = vec[0] / t->aspect[0];
- v[1] = vec[1] / t->aspect[1];
-
- BKE_mask_coord_to_image(sima->image, &sima->iuser, v, v);
-
- ED_image_point_pos__reverse(sima, t->ar, v, v);
-
- adr[0] = v[0];
- adr[1] = v[1];
- }
- else if (t->options & CTX_PAINT_CURVE) {
- adr[0] = vec[0];
- adr[1] = vec[1];
- }
- else {
- float v[2];
-
- v[0] = vec[0] / t->aspect[0];
- v[1] = vec[1] / t->aspect[1];
-
- UI_view2d_view_to_region(t->view, v[0], v[1], &adr[0], &adr[1]);
- }
- }
- else if (t->spacetype == SPACE_ACTION) {
- int out[2] = {0, 0};
+ 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) {
+ /* this is what was done in 2.64, perhaps we can be smarter? */
+ adr[0] = (int)2140000000.0f;
+ adr[1] = (int)2140000000.0f;
+ }
+ }
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = t->sa->spacedata.first;
+
+ if (t->options & CTX_MASK) {
+ float v[2];
+
+ v[0] = vec[0] / t->aspect[0];
+ v[1] = vec[1] / t->aspect[1];
+
+ BKE_mask_coord_to_image(sima->image, &sima->iuser, v, v);
+
+ ED_image_point_pos__reverse(sima, t->ar, v, v);
+
+ adr[0] = v[0];
+ adr[1] = v[1];
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ adr[0] = vec[0];
+ adr[1] = vec[1];
+ }
+ else {
+ float v[2];
+
+ v[0] = vec[0] / t->aspect[0];
+ v[1] = vec[1] / t->aspect[1];
+
+ UI_view2d_view_to_region(t->view, v[0], v[1], &adr[0], &adr[1]);
+ }
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ int out[2] = {0, 0};
#if 0
- SpaceAction *sact = t->sa->spacedata.first;
-
- if (sact->flag & SACTION_DRAWTIME) {
- //vec[0] = vec[0]/((t->scene->r.frs_sec / t->scene->r.frs_sec_base));
- /* same as below */
- UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
- }
- else
+ SpaceAction *sact = t->sa->spacedata.first;
+
+ if (sact->flag & SACTION_DRAWTIME) {
+ //vec[0] = vec[0]/((t->scene->r.frs_sec / t->scene->r.frs_sec_base));
+ /* same as below */
+ UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
+ }
+ else
#endif
- {
- UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
- }
-
- adr[0] = out[0];
- adr[1] = out[1];
- }
- else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) {
- int out[2] = {0, 0};
-
- UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
- adr[0] = out[0];
- adr[1] = out[1];
- }
- else if (t->spacetype == SPACE_SEQ) { /* XXX not tested yet, but should work */
- int out[2] = {0, 0};
-
- UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
- adr[0] = out[0];
- adr[1] = out[1];
- }
- else if (t->spacetype == SPACE_CLIP) {
- SpaceClip *sc = t->sa->spacedata.first;
-
- if (t->options & CTX_MASK) {
- MovieClip *clip = ED_space_clip_get_clip(sc);
-
- if (clip) {
- float v[2];
-
- v[0] = vec[0] / t->aspect[0];
- v[1] = vec[1] / t->aspect[1];
-
- BKE_mask_coord_to_movieclip(sc->clip, &sc->user, v, v);
-
- ED_clip_point_stable_pos__reverse(sc, t->ar, v, v);
-
- adr[0] = v[0];
- adr[1] = v[1];
- }
- else {
- adr[0] = 0;
- adr[1] = 0;
- }
- }
- else if (t->options & CTX_MOVIECLIP) {
- float v[2];
-
- v[0] = vec[0] / t->aspect[0];
- v[1] = vec[1] / t->aspect[1];
-
- UI_view2d_view_to_region(t->view, v[0], v[1], &adr[0], &adr[1]);
- }
- else {
- BLI_assert(0);
- }
- }
- else if (t->spacetype == SPACE_NODE) {
- UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &adr[0], &adr[1]);
- }
+ {
+ UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
+ }
+
+ adr[0] = out[0];
+ adr[1] = out[1];
+ }
+ else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) {
+ int out[2] = {0, 0};
+
+ UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
+ adr[0] = out[0];
+ adr[1] = out[1];
+ }
+ else if (t->spacetype == SPACE_SEQ) { /* XXX not tested yet, but should work */
+ int out[2] = {0, 0};
+
+ UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
+ adr[0] = out[0];
+ adr[1] = out[1];
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *sc = t->sa->spacedata.first;
+
+ if (t->options & CTX_MASK) {
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+
+ if (clip) {
+ float v[2];
+
+ v[0] = vec[0] / t->aspect[0];
+ v[1] = vec[1] / t->aspect[1];
+
+ BKE_mask_coord_to_movieclip(sc->clip, &sc->user, v, v);
+
+ ED_clip_point_stable_pos__reverse(sc, t->ar, v, v);
+
+ adr[0] = v[0];
+ adr[1] = v[1];
+ }
+ else {
+ adr[0] = 0;
+ adr[1] = 0;
+ }
+ }
+ else if (t->options & CTX_MOVIECLIP) {
+ float v[2];
+
+ v[0] = vec[0] / t->aspect[0];
+ v[1] = vec[1] / t->aspect[1];
+
+ UI_view2d_view_to_region(t->view, v[0], v[1], &adr[0], &adr[1]);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &adr[0], &adr[1]);
+ }
}
void projectIntView(TransInfo *t, const float vec[3], int adr[2])
{
- projectIntViewEx(t, vec, adr, V3D_PROJ_TEST_NOP);
+ projectIntViewEx(t, vec, adr, V3D_PROJ_TEST_NOP);
}
void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV3DProjTest flag)
{
- switch (t->spacetype) {
- case SPACE_VIEW3D:
- {
- if (t->options & CTX_PAINT_CURVE) {
- adr[0] = vec[0];
- adr[1] = vec[1];
- }
- else if (t->ar->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) {
- /* XXX, 2.64 and prior did this, weak! */
- adr[0] = t->ar->winx / 2.0f;
- adr[1] = t->ar->winy / 2.0f;
- }
- return;
- }
- break;
- }
- default:
- {
- int a[2] = {0, 0};
- projectIntView(t, vec, a);
- adr[0] = a[0];
- adr[1] = a[1];
- break;
- }
- }
+ switch (t->spacetype) {
+ case SPACE_VIEW3D: {
+ if (t->options & CTX_PAINT_CURVE) {
+ adr[0] = vec[0];
+ adr[1] = vec[1];
+ }
+ else if (t->ar->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) {
+ /* XXX, 2.64 and prior did this, weak! */
+ adr[0] = t->ar->winx / 2.0f;
+ adr[1] = t->ar->winy / 2.0f;
+ }
+ return;
+ }
+ break;
+ }
+ default: {
+ int a[2] = {0, 0};
+ projectIntView(t, vec, a);
+ adr[0] = a[0];
+ adr[1] = a[1];
+ break;
+ }
+ }
}
void projectFloatView(TransInfo *t, const float vec[3], float adr[2])
{
- projectFloatViewEx(t, vec, adr, V3D_PROJ_TEST_NOP);
+ projectFloatViewEx(t, vec, adr, V3D_PROJ_TEST_NOP);
}
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;
+ if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION) &&
+ !(t->options & CTX_PAINT_CURVE)) {
+ SpaceImage *sima = t->sa->spacedata.first;
- if ((sima->flag & SI_COORDFLOATS) == 0) {
- int width, height;
- ED_space_image_get_size(sima, &width, &height);
+ if ((sima->flag & SI_COORDFLOATS) == 0) {
+ int width, height;
+ ED_space_image_get_size(sima, &width, &height);
- vec[0] *= width;
- vec[1] *= height;
- }
+ vec[0] *= width;
+ vec[1] *= height;
+ }
- vec[0] /= t->aspect[0];
- vec[1] /= t->aspect[1];
- }
- else if ((t->spacetype == SPACE_CLIP) && (t->mode == TFM_TRANSLATION)) {
- if (t->options & (CTX_MOVIECLIP | CTX_MASK)) {
- vec[0] /= t->aspect[0];
- vec[1] /= t->aspect[1];
- }
- }
+ vec[0] /= t->aspect[0];
+ vec[1] /= t->aspect[1];
+ }
+ else if ((t->spacetype == SPACE_CLIP) && (t->mode == TFM_TRANSLATION)) {
+ if (t->options & (CTX_MOVIECLIP | CTX_MASK)) {
+ vec[0] /= t->aspect[0];
+ vec[1] /= t->aspect[1];
+ }
+ }
}
void removeAspectRatio(TransInfo *t, float vec[2])
{
- if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION)) {
- SpaceImage *sima = t->sa->spacedata.first;
+ if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION)) {
+ SpaceImage *sima = t->sa->spacedata.first;
- if ((sima->flag & SI_COORDFLOATS) == 0) {
- int width, height;
- ED_space_image_get_size(sima, &width, &height);
+ if ((sima->flag & SI_COORDFLOATS) == 0) {
+ int width, height;
+ ED_space_image_get_size(sima, &width, &height);
- vec[0] /= width;
- vec[1] /= height;
- }
+ vec[0] /= width;
+ vec[1] /= height;
+ }
- vec[0] *= t->aspect[0];
- vec[1] *= t->aspect[1];
- }
- else if ((t->spacetype == SPACE_CLIP) && (t->mode == TFM_TRANSLATION)) {
- if (t->options & (CTX_MOVIECLIP | CTX_MASK)) {
- vec[0] *= t->aspect[0];
- vec[1] *= t->aspect[1];
- }
- }
+ vec[0] *= t->aspect[0];
+ vec[1] *= t->aspect[1];
+ }
+ else if ((t->spacetype == SPACE_CLIP) && (t->mode == TFM_TRANSLATION)) {
+ if (t->options & (CTX_MOVIECLIP | CTX_MASK)) {
+ vec[0] *= t->aspect[0];
+ vec[1] *= t->aspect[1];
+ }
+ }
}
static void viewRedrawForce(const bContext *C, TransInfo *t)
{
- if (t->options & CTX_GPENCIL_STROKES) {
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- if (gpd) {
- DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
- }
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
- }
- 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);
- }
- else {
- /* Do we need more refined tags? */
- if (t->flag & T_POSE)
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
- else
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- /* For real-time animation record - send notifiers recognized by animation editors */
- // XXX: is this notifier a lame duck?
- if ((t->animtimer) && IS_AUTOKEY_ON(t->scene))
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
-
- }
- }
- else if (t->spacetype == SPACE_ACTION) {
- //SpaceAction *saction = (SpaceAction *)t->sa->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;
- 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);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
- }
- else if (t->spacetype == SPACE_SEQ) {
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL);
- }
- else if (t->spacetype == SPACE_IMAGE) {
- if (t->options & CTX_MASK) {
- Mask *mask = CTX_data_edit_mask(C);
-
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
- }
- else if (t->options & CTX_PAINT_CURVE) {
- wmWindow *window = CTX_wm_window(C);
- WM_paint_cursor_tag_redraw(window, t->ar);
- }
- else if (t->flag & T_CURSOR) {
- ED_area_tag_redraw(t->sa);
- }
- else {
- // XXX how to deal with lock?
- SpaceImage *sima = (SpaceImage *)t->sa->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);
- }
- }
- }
- else if (t->spacetype == SPACE_CLIP) {
- SpaceClip *sc = (SpaceClip *)t->sa->spacedata.first;
-
- if (ED_space_clip_check_show_trackedit(sc)) {
- MovieClip *clip = ED_space_clip_get_clip(sc);
-
- /* objects could be parented to tracking data, so send this for viewport refresh */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
- }
- else if (ED_space_clip_check_show_maskedit(sc)) {
- Mask *mask = CTX_data_edit_mask(C);
-
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
- }
- }
+ if (t->options & CTX_GPENCIL_STROKES) {
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ if (gpd) {
+ DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
+ }
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+ }
+ 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);
+ }
+ else {
+ /* Do we need more refined tags? */
+ if (t->flag & T_POSE)
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+ else
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ /* For real-time animation record - send notifiers recognized by animation editors */
+ // XXX: is this notifier a lame duck?
+ if ((t->animtimer) && IS_AUTOKEY_ON(t->scene))
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
+ }
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ //SpaceAction *saction = (SpaceAction *)t->sa->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;
+ 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);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
+ }
+ else if (t->spacetype == SPACE_SEQ) {
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL);
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ if (t->options & CTX_MASK) {
+ Mask *mask = CTX_data_edit_mask(C);
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ wmWindow *window = CTX_wm_window(C);
+ WM_paint_cursor_tag_redraw(window, t->ar);
+ }
+ else if (t->flag & T_CURSOR) {
+ ED_area_tag_redraw(t->sa);
+ }
+ else {
+ // XXX how to deal with lock?
+ SpaceImage *sima = (SpaceImage *)t->sa->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);
+ }
+ }
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *sc = (SpaceClip *)t->sa->spacedata.first;
+
+ if (ED_space_clip_check_show_trackedit(sc)) {
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+
+ /* objects could be parented to tracking data, so send this for viewport refresh */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+ }
+ else if (ED_space_clip_check_show_maskedit(sc)) {
+ Mask *mask = CTX_data_edit_mask(C);
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ }
+ }
}
static void viewRedrawPost(bContext *C, TransInfo *t)
{
- ED_area_status_text(t->sa, NULL);
-
- if (t->spacetype == SPACE_VIEW3D) {
- /* if autokeying is enabled, send notifiers that keyframes were added */
- if (IS_AUTOKEY_ON(t->scene))
- WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
-
- /* redraw UV editor */
- if (ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) &&
- (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT))
- {
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
- }
-
- /* XXX temp, first hack to get auto-render in compositor work (ton) */
- WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, CTX_data_scene(C));
-
- }
-
-#if 0 // TRANSFORM_FIX_ME
- if (t->spacetype == SPACE_VIEW3D) {
- allqueue(REDRAWBUTSOBJECT, 0);
- allqueue(REDRAWVIEW3D, 0);
- }
- else if (t->spacetype == SPACE_IMAGE) {
- allqueue(REDRAWIMAGE, 0);
- allqueue(REDRAWVIEW3D, 0);
- }
- else if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_GRAPH)) {
- allqueue(REDRAWVIEW3D, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWNLA, 0);
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWTIME, 0);
- allqueue(REDRAWBUTSOBJECT, 0);
- }
-
- scrarea_queue_headredraw(curarea);
+ ED_area_status_text(t->sa, NULL);
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* if autokeying is enabled, send notifiers that keyframes were added */
+ if (IS_AUTOKEY_ON(t->scene))
+ WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+
+ /* redraw UV editor */
+ if (ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) &&
+ (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+ }
+
+ /* XXX temp, first hack to get auto-render in compositor work (ton) */
+ WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, CTX_data_scene(C));
+ }
+
+#if 0 // TRANSFORM_FIX_ME
+ if (t->spacetype == SPACE_VIEW3D) {
+ allqueue(REDRAWBUTSOBJECT, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_GRAPH)) {
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWTIME, 0);
+ allqueue(REDRAWBUTSOBJECT, 0);
+ }
+
+ scrarea_queue_headredraw(curarea);
#endif
}
@@ -707,81 +702,81 @@ static void viewRedrawPost(bContext *C, TransInfo *t)
static void view_editmove(unsigned short UNUSED(event))
{
-#if 0 // TRANSFORM_FIX_ME
- int refresh = 0;
- /* Regular: Zoom in */
- /* Shift: Scroll up */
- /* Ctrl: Scroll right */
- /* Alt-Shift: Rotate up */
- /* Alt-Ctrl: Rotate right */
-
- /* only work in 3D window for now
- * In the end, will have to send to event to a 2D window handler instead
- */
- if (Trans.flag & T_2D_EDIT)
- return;
-
- switch (event) {
- case WHEELUPMOUSE:
- if (G.qual & LR_SHIFTKEY) {
- if (G.qual & LR_ALTKEY) {
- G.qual &= ~LR_SHIFTKEY;
- persptoetsen(PAD2);
- G.qual |= LR_SHIFTKEY;
- }
- else {
- persptoetsen(PAD2);
- }
- }
- else if (G.qual & LR_CTRLKEY) {
- if (G.qual & LR_ALTKEY) {
- G.qual &= ~LR_CTRLKEY;
- persptoetsen(PAD4);
- G.qual |= LR_CTRLKEY;
- }
- else {
- persptoetsen(PAD4);
- }
- }
- else if (U.uiflag & USER_WHEELZOOMDIR)
- persptoetsen(PADMINUS);
- else
- persptoetsen(PADPLUSKEY);
-
- refresh = 1;
- break;
- case WHEELDOWNMOUSE:
- if (G.qual & LR_SHIFTKEY) {
- if (G.qual & LR_ALTKEY) {
- G.qual &= ~LR_SHIFTKEY;
- persptoetsen(PAD8);
- G.qual |= LR_SHIFTKEY;
- }
- else {
- persptoetsen(PAD8);
- }
- }
- else if (G.qual & LR_CTRLKEY) {
- if (G.qual & LR_ALTKEY) {
- G.qual &= ~LR_CTRLKEY;
- persptoetsen(PAD6);
- G.qual |= LR_CTRLKEY;
- }
- else {
- persptoetsen(PAD6);
- }
- }
- else if (U.uiflag & USER_WHEELZOOMDIR)
- persptoetsen(PADPLUSKEY);
- else
- persptoetsen(PADMINUS);
-
- refresh = 1;
- break;
- }
-
- if (refresh)
- setTransformViewMatrices(&Trans);
+#if 0 // TRANSFORM_FIX_ME
+ int refresh = 0;
+ /* Regular: Zoom in */
+ /* Shift: Scroll up */
+ /* Ctrl: Scroll right */
+ /* Alt-Shift: Rotate up */
+ /* Alt-Ctrl: Rotate right */
+
+ /* only work in 3D window for now
+ * In the end, will have to send to event to a 2D window handler instead
+ */
+ if (Trans.flag & T_2D_EDIT)
+ return;
+
+ switch (event) {
+ case WHEELUPMOUSE:
+ if (G.qual & LR_SHIFTKEY) {
+ if (G.qual & LR_ALTKEY) {
+ G.qual &= ~LR_SHIFTKEY;
+ persptoetsen(PAD2);
+ G.qual |= LR_SHIFTKEY;
+ }
+ else {
+ persptoetsen(PAD2);
+ }
+ }
+ else if (G.qual & LR_CTRLKEY) {
+ if (G.qual & LR_ALTKEY) {
+ G.qual &= ~LR_CTRLKEY;
+ persptoetsen(PAD4);
+ G.qual |= LR_CTRLKEY;
+ }
+ else {
+ persptoetsen(PAD4);
+ }
+ }
+ else if (U.uiflag & USER_WHEELZOOMDIR)
+ persptoetsen(PADMINUS);
+ else
+ persptoetsen(PADPLUSKEY);
+
+ refresh = 1;
+ break;
+ case WHEELDOWNMOUSE:
+ if (G.qual & LR_SHIFTKEY) {
+ if (G.qual & LR_ALTKEY) {
+ G.qual &= ~LR_SHIFTKEY;
+ persptoetsen(PAD8);
+ G.qual |= LR_SHIFTKEY;
+ }
+ else {
+ persptoetsen(PAD8);
+ }
+ }
+ else if (G.qual & LR_CTRLKEY) {
+ if (G.qual & LR_ALTKEY) {
+ G.qual &= ~LR_CTRLKEY;
+ persptoetsen(PAD6);
+ G.qual |= LR_CTRLKEY;
+ }
+ else {
+ persptoetsen(PAD6);
+ }
+ }
+ else if (U.uiflag & USER_WHEELZOOMDIR)
+ persptoetsen(PADPLUSKEY);
+ else
+ persptoetsen(PADMINUS);
+
+ refresh = 1;
+ break;
+ }
+
+ if (refresh)
+ setTransformViewMatrices(&Trans);
#endif
}
@@ -789,885 +784,898 @@ 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,
+ 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;
- switch (value) {
- case TFM_MODAL_CANCEL:
- {
- if ((t->flag & T_RELEASE_CONFIRM) && ISMOUSE(t->launch_event)) {
- return false;
- }
- break;
- }
- case TFM_MODAL_PROPSIZE:
- case TFM_MODAL_PROPSIZE_UP:
- case TFM_MODAL_PROPSIZE_DOWN:
- {
- if ((t->flag & T_PROP_EDIT) == 0) {
- return false;
- }
- break;
- }
- case TFM_MODAL_ADD_SNAP:
- case TFM_MODAL_REMOVE_SNAP:
- {
- if (t->spacetype != SPACE_VIEW3D) {
- return false;
- }
- else if (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) {
- return false;
- }
- else if (!validSnap(t)) {
- return false;
- }
- break;
- }
- case TFM_MODAL_AXIS_X:
- case TFM_MODAL_AXIS_Y:
- case TFM_MODAL_AXIS_Z:
- case TFM_MODAL_PLANE_X:
- case TFM_MODAL_PLANE_Y:
- case TFM_MODAL_PLANE_Z:
- {
- if (t->flag & T_NO_CONSTRAINT) {
- return false;
- }
- if (!ELEM(value, TFM_MODAL_AXIS_X, TFM_MODAL_AXIS_Y)) {
- if (t->flag & T_2D_EDIT) {
- return false;
- }
- }
- break;
- }
- case TFM_MODAL_CONS_OFF:
- {
- if ((t->con.mode & CON_APPLY) == 0) {
- return false;
- }
- break;
- }
- case TFM_MODAL_EDGESLIDE_UP:
- case TFM_MODAL_EDGESLIDE_DOWN:
- {
- if (t->mode != TFM_EDGE_SLIDE) {
- return false;
- }
- break;
- }
- case TFM_MODAL_INSERTOFS_TOGGLE_DIR:
- {
- if (t->spacetype != SPACE_NODE) {
- return false;
- }
- break;
- }
- case TFM_MODAL_AUTOIK_LEN_INC:
- case TFM_MODAL_AUTOIK_LEN_DEC:
- {
- if ((t->flag & T_AUTOIK) == 0) {
- return false;
- }
- break;
- }
- }
- return true;
+ const TransInfo *t = op->customdata;
+ switch (value) {
+ case TFM_MODAL_CANCEL: {
+ if ((t->flag & T_RELEASE_CONFIRM) && ISMOUSE(t->launch_event)) {
+ return false;
+ }
+ break;
+ }
+ case TFM_MODAL_PROPSIZE:
+ case TFM_MODAL_PROPSIZE_UP:
+ case TFM_MODAL_PROPSIZE_DOWN: {
+ if ((t->flag & T_PROP_EDIT) == 0) {
+ return false;
+ }
+ break;
+ }
+ case TFM_MODAL_ADD_SNAP:
+ case TFM_MODAL_REMOVE_SNAP: {
+ if (t->spacetype != SPACE_VIEW3D) {
+ return false;
+ }
+ else if (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) {
+ return false;
+ }
+ else if (!validSnap(t)) {
+ return false;
+ }
+ break;
+ }
+ case TFM_MODAL_AXIS_X:
+ case TFM_MODAL_AXIS_Y:
+ case TFM_MODAL_AXIS_Z:
+ case TFM_MODAL_PLANE_X:
+ case TFM_MODAL_PLANE_Y:
+ case TFM_MODAL_PLANE_Z: {
+ if (t->flag & T_NO_CONSTRAINT) {
+ return false;
+ }
+ if (!ELEM(value, TFM_MODAL_AXIS_X, TFM_MODAL_AXIS_Y)) {
+ if (t->flag & T_2D_EDIT) {
+ return false;
+ }
+ }
+ break;
+ }
+ case TFM_MODAL_CONS_OFF: {
+ if ((t->con.mode & CON_APPLY) == 0) {
+ return false;
+ }
+ break;
+ }
+ case TFM_MODAL_EDGESLIDE_UP:
+ case TFM_MODAL_EDGESLIDE_DOWN: {
+ if (t->mode != TFM_EDGE_SLIDE) {
+ return false;
+ }
+ break;
+ }
+ case TFM_MODAL_INSERTOFS_TOGGLE_DIR: {
+ if (t->spacetype != SPACE_NODE) {
+ return false;
+ }
+ break;
+ }
+ case TFM_MODAL_AUTOIK_LEN_INC:
+ case TFM_MODAL_AUTOIK_LEN_DEC: {
+ if ((t->flag & T_AUTOIK) == 0) {
+ return false;
+ }
+ break;
+ }
+ }
+ return true;
}
/* called in transform_ops.c, on each regeneration of keymaps */
wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
{
- static const EnumPropertyItem modal_items[] = {
- {TFM_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
- {TFM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
- {TFM_MODAL_AXIS_X, "AXIS_X", 0, "X axis", ""},
- {TFM_MODAL_AXIS_Y, "AXIS_Y", 0, "Y axis", ""},
- {TFM_MODAL_AXIS_Z, "AXIS_Z", 0, "Z axis", ""},
- {TFM_MODAL_PLANE_X, "PLANE_X", 0, "X plane", ""},
- {TFM_MODAL_PLANE_Y, "PLANE_Y", 0, "Y plane", ""},
- {TFM_MODAL_PLANE_Z, "PLANE_Z", 0, "Z plane", ""},
- {TFM_MODAL_CONS_OFF, "CONS_OFF", 0, "Clear Constraints", ""},
- {TFM_MODAL_SNAP_INV_ON, "SNAP_INV_ON", 0, "Snap Invert", ""},
- {TFM_MODAL_SNAP_INV_OFF, "SNAP_INV_OFF", 0, "Snap Invert (Off)", ""},
- {TFM_MODAL_SNAP_TOGGLE, "SNAP_TOGGLE", 0, "Snap Toggle", ""},
- {TFM_MODAL_ADD_SNAP, "ADD_SNAP", 0, "Add Snap Point", ""},
- {TFM_MODAL_REMOVE_SNAP, "REMOVE_SNAP", 0, "Remove Last Snap Point", ""},
- {NUM_MODAL_INCREMENT_UP, "INCREMENT_UP", 0, "Numinput Increment Up", ""},
- {NUM_MODAL_INCREMENT_DOWN, "INCREMENT_DOWN", 0, "Numinput Increment Down", ""},
- {TFM_MODAL_PROPSIZE_UP, "PROPORTIONAL_SIZE_UP", 0, "Increase Proportional Influence", ""},
- {TFM_MODAL_PROPSIZE_DOWN, "PROPORTIONAL_SIZE_DOWN", 0, "Decrease Proportional Influence", ""},
- {TFM_MODAL_AUTOIK_LEN_INC, "AUTOIK_CHAIN_LEN_UP", 0, "Increase Max AutoIK Chain Length", ""},
- {TFM_MODAL_AUTOIK_LEN_DEC, "AUTOIK_CHAIN_LEN_DOWN", 0, "Decrease Max AutoIK Chain Length", ""},
- {TFM_MODAL_EDGESLIDE_UP, "EDGESLIDE_EDGE_NEXT", 0, "Select next Edge Slide Edge", ""},
- {TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select previous Edge Slide Edge", ""},
- {TFM_MODAL_PROPSIZE, "PROPORTIONAL_SIZE", 0, "Adjust Proportional Influence", ""},
- {TFM_MODAL_INSERTOFS_TOGGLE_DIR, "INSERTOFS_TOGGLE_DIR", 0, "Toggle Direction for Node Auto-offset", ""},
- {TFM_MODAL_TRANSLATE, "TRANSLATE", 0, "Move", ""},
- {TFM_MODAL_ROTATE, "ROTATE", 0, "Rotate", ""},
- {TFM_MODAL_RESIZE, "RESIZE", 0, "Resize", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Transform Modal Map");
-
- keymap = WM_modalkeymap_add(keyconf, "Transform Modal Map", modal_items);
- keymap->poll_modal_item = transform_modal_item_poll;
-
- return keymap;
+ static const EnumPropertyItem modal_items[] = {
+ {TFM_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+ {TFM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
+ {TFM_MODAL_AXIS_X, "AXIS_X", 0, "X axis", ""},
+ {TFM_MODAL_AXIS_Y, "AXIS_Y", 0, "Y axis", ""},
+ {TFM_MODAL_AXIS_Z, "AXIS_Z", 0, "Z axis", ""},
+ {TFM_MODAL_PLANE_X, "PLANE_X", 0, "X plane", ""},
+ {TFM_MODAL_PLANE_Y, "PLANE_Y", 0, "Y plane", ""},
+ {TFM_MODAL_PLANE_Z, "PLANE_Z", 0, "Z plane", ""},
+ {TFM_MODAL_CONS_OFF, "CONS_OFF", 0, "Clear Constraints", ""},
+ {TFM_MODAL_SNAP_INV_ON, "SNAP_INV_ON", 0, "Snap Invert", ""},
+ {TFM_MODAL_SNAP_INV_OFF, "SNAP_INV_OFF", 0, "Snap Invert (Off)", ""},
+ {TFM_MODAL_SNAP_TOGGLE, "SNAP_TOGGLE", 0, "Snap Toggle", ""},
+ {TFM_MODAL_ADD_SNAP, "ADD_SNAP", 0, "Add Snap Point", ""},
+ {TFM_MODAL_REMOVE_SNAP, "REMOVE_SNAP", 0, "Remove Last Snap Point", ""},
+ {NUM_MODAL_INCREMENT_UP, "INCREMENT_UP", 0, "Numinput Increment Up", ""},
+ {NUM_MODAL_INCREMENT_DOWN, "INCREMENT_DOWN", 0, "Numinput Increment Down", ""},
+ {TFM_MODAL_PROPSIZE_UP, "PROPORTIONAL_SIZE_UP", 0, "Increase Proportional Influence", ""},
+ {TFM_MODAL_PROPSIZE_DOWN,
+ "PROPORTIONAL_SIZE_DOWN",
+ 0,
+ "Decrease Proportional Influence",
+ ""},
+ {TFM_MODAL_AUTOIK_LEN_INC, "AUTOIK_CHAIN_LEN_UP", 0, "Increase Max AutoIK Chain Length", ""},
+ {TFM_MODAL_AUTOIK_LEN_DEC,
+ "AUTOIK_CHAIN_LEN_DOWN",
+ 0,
+ "Decrease Max AutoIK Chain Length",
+ ""},
+ {TFM_MODAL_EDGESLIDE_UP, "EDGESLIDE_EDGE_NEXT", 0, "Select next Edge Slide Edge", ""},
+ {TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select previous Edge Slide Edge", ""},
+ {TFM_MODAL_PROPSIZE, "PROPORTIONAL_SIZE", 0, "Adjust Proportional Influence", ""},
+ {TFM_MODAL_INSERTOFS_TOGGLE_DIR,
+ "INSERTOFS_TOGGLE_DIR",
+ 0,
+ "Toggle Direction for Node Auto-offset",
+ ""},
+ {TFM_MODAL_TRANSLATE, "TRANSLATE", 0, "Move", ""},
+ {TFM_MODAL_ROTATE, "ROTATE", 0, "Rotate", ""},
+ {TFM_MODAL_RESIZE, "RESIZE", 0, "Resize", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Transform Modal Map");
+
+ keymap = WM_modalkeymap_add(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)
{
- if (!(t->flag & T_NO_CONSTRAINT)) {
- int constraint_axis, constraint_plane;
- const bool edit_2d = (t->flag & T_2D_EDIT) != 0;
- const char *msg1 = "", *msg2 = "", *msg3 = "";
- char axis;
-
- /* Initialize */
- switch (key_type) {
- case XKEY:
- msg1 = IFACE_("along X");
- msg2 = IFACE_("along %s X");
- msg3 = IFACE_("locking %s X");
- axis = 'X';
- constraint_axis = CON_AXIS0;
- break;
- case YKEY:
- msg1 = IFACE_("along Y");
- msg2 = IFACE_("along %s Y");
- msg3 = IFACE_("locking %s Y");
- axis = 'Y';
- constraint_axis = CON_AXIS1;
- break;
- case ZKEY:
- msg1 = IFACE_("along Z");
- msg2 = IFACE_("along %s Z");
- msg3 = IFACE_("locking %s Z");
- axis = 'Z';
- constraint_axis = CON_AXIS2;
- break;
- default:
- /* Invalid key */
- return;
- }
- constraint_plane = ((CON_AXIS0 | CON_AXIS1 | CON_AXIS2) & (~constraint_axis));
-
- if (edit_2d && (key_type != ZKEY)) {
- if (cmode == axis) {
- stopConstraint(t);
- }
- else {
- setUserConstraint(t, V3D_ORIENT_GLOBAL, constraint_axis, msg1);
- }
- }
- 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 {
- /* Successive presses on existing axis, cycle orientation modes. */
- t->orientation.index = (t->orientation.index + 1) % ARRAY_SIZE(t->orientation.types);
-
- if (t->orientation.index == 0) {
- stopConstraint(t);
- }
- 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);
- }
- }
- }
- }
- t->redraw |= TREDRAW_HARD;
- }
+ if (!(t->flag & T_NO_CONSTRAINT)) {
+ int constraint_axis, constraint_plane;
+ const bool edit_2d = (t->flag & T_2D_EDIT) != 0;
+ const char *msg1 = "", *msg2 = "", *msg3 = "";
+ char axis;
+
+ /* Initialize */
+ switch (key_type) {
+ case XKEY:
+ msg1 = IFACE_("along X");
+ msg2 = IFACE_("along %s X");
+ msg3 = IFACE_("locking %s X");
+ axis = 'X';
+ constraint_axis = CON_AXIS0;
+ break;
+ case YKEY:
+ msg1 = IFACE_("along Y");
+ msg2 = IFACE_("along %s Y");
+ msg3 = IFACE_("locking %s Y");
+ axis = 'Y';
+ constraint_axis = CON_AXIS1;
+ break;
+ case ZKEY:
+ msg1 = IFACE_("along Z");
+ msg2 = IFACE_("along %s Z");
+ msg3 = IFACE_("locking %s Z");
+ axis = 'Z';
+ constraint_axis = CON_AXIS2;
+ break;
+ default:
+ /* Invalid key */
+ return;
+ }
+ constraint_plane = ((CON_AXIS0 | CON_AXIS1 | CON_AXIS2) & (~constraint_axis));
+
+ if (edit_2d && (key_type != ZKEY)) {
+ if (cmode == axis) {
+ stopConstraint(t);
+ }
+ else {
+ setUserConstraint(t, V3D_ORIENT_GLOBAL, constraint_axis, msg1);
+ }
+ }
+ 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 {
+ /* Successive presses on existing axis, cycle orientation modes. */
+ t->orientation.index = (t->orientation.index + 1) % ARRAY_SIZE(t->orientation.types);
+
+ if (t->orientation.index == 0) {
+ stopConstraint(t);
+ }
+ 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);
+ }
+ }
+ }
+ }
+ t->redraw |= TREDRAW_HARD;
+ }
}
int transformEvent(TransInfo *t, const wmEvent *event)
{
- char cmode = constraintModeToChar(t);
- bool handled = false;
- const int modifiers_prev = t->modifiers;
-
- t->redraw |= handleMouseInput(t, &t->mouse, event);
-
- /* Handle modal numinput events first, if already activated. */
- if (((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) &&
- hasNumInput(&t->num) && handleNumInput(t->context, &(t->num), event))
- {
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- else if (event->type == MOUSEMOVE) {
- if (t->modifiers & MOD_CONSTRAINT_SELECT)
- t->con.mode |= CON_SELECT;
-
- copy_v2_v2_int(t->mval, event->mval);
-
- /* Use this for soft redraw. Might cause flicker in object mode */
- // t->redraw |= TREDRAW_SOFT;
- t->redraw |= TREDRAW_HARD;
-
- if (t->state == TRANS_STARTING) {
- t->state = TRANS_RUNNING;
- }
-
- applyMouseInput(t, &t->mouse, t->mval, t->values);
-
- // Snapping mouse move events
- t->redraw |= handleSnapping(t, event);
- handled = true;
- }
- /* handle modal keymap first */
- else if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case TFM_MODAL_CANCEL:
- t->state = TRANS_CANCEL;
- handled = true;
- break;
- case TFM_MODAL_CONFIRM:
- t->state = TRANS_CONFIRM;
- handled = true;
- break;
- case TFM_MODAL_TRANSLATE:
- /* only switch when... */
- if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
- restoreTransObjects(t);
- resetTransModal(t);
- resetTransRestrictions(t);
- initTranslation(t);
- initSnapping(t, NULL); // need to reinit after mode change
- t->redraw |= TREDRAW_HARD;
- WM_event_add_mousemove(t->context);
- handled = true;
- }
- else if (t->mode == TFM_SEQ_SLIDE) {
- t->flag ^= T_ALT_TRANSFORM;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- else {
- if (t->obedit_type == OB_MESH) {
- if ((t->mode == TFM_TRANSLATION) && (t->spacetype == SPACE_VIEW3D)) {
- restoreTransObjects(t);
- resetTransModal(t);
- resetTransRestrictions(t);
-
- /* first try edge slide */
- initEdgeSlide(t);
- /* if that fails, do vertex slide */
- if (t->state == TRANS_CANCEL) {
- resetTransModal(t);
- t->state = TRANS_STARTING;
- initVertSlide(t);
- }
- /* 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);
- }
- initSnapping(t, NULL); // need to reinit after mode change
- t->redraw |= TREDRAW_HARD;
- handled = true;
- WM_event_add_mousemove(t->context);
- }
- }
- else if (t->options & (CTX_MOVIECLIP | CTX_MASK)) {
- if (t->mode == TFM_TRANSLATION) {
- restoreTransObjects(t);
-
- t->flag ^= T_ALT_TRANSFORM;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- }
- }
- break;
- case TFM_MODAL_ROTATE:
- /* only switch when... */
- if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) {
- if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
- restoreTransObjects(t);
- resetTransModal(t);
- resetTransRestrictions(t);
-
- if (t->mode == TFM_ROTATION) {
- initTrackball(t);
- }
- else {
- initRotation(t);
- }
- initSnapping(t, NULL); // need to reinit after mode change
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- }
- break;
- case TFM_MODAL_RESIZE:
- /* only switch when... */
- if (ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
-
- /* Scale isn't normally very useful after extrude along normals, see T39756 */
- if ((t->con.mode & CON_APPLY) && (t->con.orientation == V3D_ORIENT_NORMAL)) {
- stopConstraint(t);
- }
-
- restoreTransObjects(t);
- resetTransModal(t);
- resetTransRestrictions(t);
- initResize(t);
- initSnapping(t, NULL); // need to reinit after mode change
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- else if (t->mode == TFM_SHRINKFATTEN) {
- t->flag ^= T_ALT_TRANSFORM;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- else if (t->mode == TFM_RESIZE) {
- if (t->options & CTX_MOVIECLIP) {
- restoreTransObjects(t);
-
- t->flag ^= T_ALT_TRANSFORM;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- }
- break;
-
- case TFM_MODAL_SNAP_INV_ON:
- t->modifiers |= MOD_SNAP_INVERT;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- break;
- case TFM_MODAL_SNAP_INV_OFF:
- t->modifiers &= ~MOD_SNAP_INVERT;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- break;
- case TFM_MODAL_SNAP_TOGGLE:
- t->modifiers ^= MOD_SNAP;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- break;
- case TFM_MODAL_AXIS_X:
- if (!(t->flag & T_NO_CONSTRAINT)) {
- transform_event_xyz_constraint(t, XKEY, cmode, 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);
- 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);
- 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);
- 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);
- 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);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_CONS_OFF:
- if ((t->flag & T_NO_CONSTRAINT) == 0) {
- stopConstraint(t);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_ADD_SNAP:
- addSnapPoint(t);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- break;
- case TFM_MODAL_REMOVE_SNAP:
- removeSnapPoint(t);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- break;
- case TFM_MODAL_PROPSIZE:
- /* MOUSEPAN usage... */
- if (t->flag & T_PROP_EDIT) {
- float fac = 1.0f + 0.005f *(event->y - event->prevy);
- t->prop_size *= fac;
- if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) {
- t->prop_size = max_ff(min_ff(t->prop_size, ((View3D *)t->view)->clip_end), T_PROP_SIZE_MIN);
- }
- else {
- t->prop_size = max_ff(min_ff(t->prop_size, T_PROP_SIZE_MAX), T_PROP_SIZE_MIN);
- }
- calculatePropRatio(t);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_PROPSIZE_UP:
- if (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) {
- t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->clip_end);
- }
- else {
- t->prop_size = min_ff(t->prop_size, T_PROP_SIZE_MAX);
- }
- calculatePropRatio(t);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_PROPSIZE_DOWN:
- if (t->flag & T_PROP_EDIT) {
- t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
- t->prop_size = max_ff(t->prop_size, T_PROP_SIZE_MIN);
- calculatePropRatio(t);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_AUTOIK_LEN_INC:
- if (t->flag & T_AUTOIK) {
- transform_autoik_update(t, 1);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_AUTOIK_LEN_DEC:
- if (t->flag & T_AUTOIK) {
- transform_autoik_update(t, -1);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_INSERTOFS_TOGGLE_DIR:
- if (t->spacetype == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
-
- BLI_assert(t->sa->spacetype == t->spacetype);
-
- if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) {
- snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_LEFT;
- }
- else if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_LEFT) {
- snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_RIGHT;
- }
- else {
- BLI_assert(0);
- }
-
- t->redraw |= TREDRAW_SOFT;
- }
- break;
- /* Those two are only handled in transform's own handler, see T44634! */
- case TFM_MODAL_EDGESLIDE_UP:
- case TFM_MODAL_EDGESLIDE_DOWN:
- default:
- break;
- }
- }
- /* else do non-mapped events */
- else if (event->val == KM_PRESS) {
- switch (event->type) {
- 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:
- t->state = TRANS_CONFIRM;
- handled = true;
- break;
-
- case MIDDLEMOUSE:
- if ((t->flag & T_NO_CONSTRAINT) == 0) {
- /* exception for switching to dolly, or trackball, in camera view */
- if (t->flag & T_CAMERA) {
- if (t->mode == TFM_TRANSLATION)
- setLocalConstraint(t, (CON_AXIS2), IFACE_("along local Z"));
- else if (t->mode == TFM_ROTATION) {
- restoreTransObjects(t);
- initTrackball(t);
- }
- }
- else {
- t->modifiers |= MOD_CONSTRAINT_SELECT;
- if (t->con.mode & CON_APPLY) {
- 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);
- }
- postSelectConstraint(t);
- }
- }
- t->redraw |= TREDRAW_HARD;
- 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:
- /* only switch when... */
- if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
- restoreTransObjects(t);
- resetTransModal(t);
- resetTransRestrictions(t);
- initTranslation(t);
- initSnapping(t, NULL); // need to reinit after mode change
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case SKEY:
- /* only switch when... */
- if (ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL)) {
- restoreTransObjects(t);
- resetTransModal(t);
- resetTransRestrictions(t);
- initResize(t);
- initSnapping(t, NULL); // need to reinit after mode change
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case RKEY:
- /* only switch when... */
- if (!(t->options & CTX_TEXTURE)) {
- if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION)) {
- restoreTransObjects(t);
- resetTransModal(t);
- resetTransRestrictions(t);
-
- if (t->mode == TFM_ROTATION) {
- initTrackball(t);
- }
- else {
- initRotation(t);
- }
- initSnapping(t, NULL); // need to reinit after mode change
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- }
- break;
- case CKEY:
- if (event->alt) {
- if (!(t->options & CTX_NO_PET)) {
- t->flag ^= T_PROP_CONNECTED;
- sort_trans_data_dist(t);
- calculatePropRatio(t);
- t->redraw = TREDRAW_HARD;
- handled = true;
- }
- }
- break;
- case OKEY:
- if (t->flag & T_PROP_EDIT && event->shift) {
- t->prop_mode = (t->prop_mode + 1) % PROP_MODE_MAX;
- calculatePropRatio(t);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case 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)
- t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->clip_end);
- calculatePropRatio(t);
- t->redraw = TREDRAW_HARD;
- handled = true;
- }
- break;
- case PAGEUPKEY:
- case WHEELDOWNMOUSE:
- if (t->flag & T_AUTOIK) {
- transform_autoik_update(t, 1);
- }
- else {
- view_editmove(event->type);
- }
- t->redraw = TREDRAW_HARD;
- handled = true;
- break;
- case PADMINUS:
- if (event->alt && t->flag & T_PROP_EDIT) {
- t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
- calculatePropRatio(t);
- t->redraw = TREDRAW_HARD;
- handled = true;
- }
- break;
- case PAGEDOWNKEY:
- case WHEELUPMOUSE:
- if (t->flag & T_AUTOIK) {
- transform_autoik_update(t, -1);
- }
- else {
- view_editmove(event->type);
- }
- t->redraw = TREDRAW_HARD;
- handled = true;
- break;
- case LEFTALTKEY:
- case RIGHTALTKEY:
- if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) {
- t->flag |= T_ALT_TRANSFORM;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case NKEY:
- if (ELEM(t->mode, TFM_ROTATION)) {
- if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
- restoreTransObjects(t);
- resetTransModal(t);
- resetTransRestrictions(t);
- initNormalRotation(t);
- t->redraw = TREDRAW_HARD;
- handled = true;
- }
- }
- break;
- default:
- break;
- }
-
- /* Snapping key events */
- t->redraw |= handleSnapping(t, event);
- }
- else if (event->val == KM_RELEASE) {
- switch (event->type) {
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
- t->modifiers &= ~MOD_CONSTRAINT_PLANE;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- break;
-
- case MIDDLEMOUSE:
- if ((t->flag & T_NO_CONSTRAINT) == 0) {
- t->modifiers &= ~MOD_CONSTRAINT_SELECT;
- postSelectConstraint(t);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case LEFTALTKEY:
- case RIGHTALTKEY:
- if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) {
- t->flag &= ~T_ALT_TRANSFORM;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- default:
- break;
- }
-
- /* confirm transform if launch key is released after mouse move */
- if (t->flag & T_RELEASE_CONFIRM) {
- /* XXX Keyrepeat bug in Xorg messes this up, will test when fixed */
- if ((event->type == t->launch_event) && ISMOUSE(t->launch_event)) {
- t->state = TRANS_CONFIRM;
- }
- }
- }
-
- /* if we change snap options, get the unsnapped values back */
- if ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) !=
- (modifiers_prev & (MOD_SNAP | MOD_SNAP_INVERT)))
- {
- applyMouseInput(t, &t->mouse, t->mval, t->values);
- }
-
- /* Per transform event, if present */
- if (t->handleEvent &&
- (!handled ||
- /* Needed for vertex slide, see [#38756] */
- (event->type == MOUSEMOVE)))
- {
- t->redraw |= t->handleEvent(t, event);
- }
-
- /* Try to init modal numinput now, if possible. */
- if (!(handled || t->redraw) && ((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) &&
- handleNumInput(t->context, &(t->num), event))
- {
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
-
- if (t->redraw &&
- !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE))
- {
- WM_window_status_area_tag_redraw(CTX_wm_window(t->context));
- }
-
- if (handled || t->redraw) {
- return 0;
- }
- else {
- return OPERATOR_PASS_THROUGH;
- }
+ char cmode = constraintModeToChar(t);
+ bool handled = false;
+ const int modifiers_prev = t->modifiers;
+
+ t->redraw |= handleMouseInput(t, &t->mouse, event);
+
+ /* Handle modal numinput events first, if already activated. */
+ if (((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) && hasNumInput(&t->num) &&
+ handleNumInput(t->context, &(t->num), event)) {
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ else if (event->type == MOUSEMOVE) {
+ if (t->modifiers & MOD_CONSTRAINT_SELECT)
+ t->con.mode |= CON_SELECT;
+
+ copy_v2_v2_int(t->mval, event->mval);
+
+ /* Use this for soft redraw. Might cause flicker in object mode */
+ // t->redraw |= TREDRAW_SOFT;
+ t->redraw |= TREDRAW_HARD;
+
+ if (t->state == TRANS_STARTING) {
+ t->state = TRANS_RUNNING;
+ }
+
+ applyMouseInput(t, &t->mouse, t->mval, t->values);
+
+ // Snapping mouse move events
+ t->redraw |= handleSnapping(t, event);
+ handled = true;
+ }
+ /* handle modal keymap first */
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case TFM_MODAL_CANCEL:
+ t->state = TRANS_CANCEL;
+ handled = true;
+ break;
+ case TFM_MODAL_CONFIRM:
+ t->state = TRANS_CONFIRM;
+ handled = true;
+ break;
+ case TFM_MODAL_TRANSLATE:
+ /* only switch when... */
+ if (ELEM(t->mode,
+ TFM_ROTATION,
+ TFM_RESIZE,
+ TFM_TRACKBALL,
+ TFM_EDGE_SLIDE,
+ TFM_VERT_SLIDE)) {
+ restoreTransObjects(t);
+ resetTransModal(t);
+ resetTransRestrictions(t);
+ initTranslation(t);
+ initSnapping(t, NULL); // need to reinit after mode change
+ t->redraw |= TREDRAW_HARD;
+ WM_event_add_mousemove(t->context);
+ handled = true;
+ }
+ else if (t->mode == TFM_SEQ_SLIDE) {
+ t->flag ^= T_ALT_TRANSFORM;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ else {
+ if (t->obedit_type == OB_MESH) {
+ if ((t->mode == TFM_TRANSLATION) && (t->spacetype == SPACE_VIEW3D)) {
+ restoreTransObjects(t);
+ resetTransModal(t);
+ resetTransRestrictions(t);
+
+ /* first try edge slide */
+ initEdgeSlide(t);
+ /* if that fails, do vertex slide */
+ if (t->state == TRANS_CANCEL) {
+ resetTransModal(t);
+ t->state = TRANS_STARTING;
+ initVertSlide(t);
+ }
+ /* 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);
+ }
+ initSnapping(t, NULL); // need to reinit after mode change
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ WM_event_add_mousemove(t->context);
+ }
+ }
+ else if (t->options & (CTX_MOVIECLIP | CTX_MASK)) {
+ if (t->mode == TFM_TRANSLATION) {
+ restoreTransObjects(t);
+
+ t->flag ^= T_ALT_TRANSFORM;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ }
+ }
+ break;
+ case TFM_MODAL_ROTATE:
+ /* only switch when... */
+ if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) {
+ if (ELEM(t->mode,
+ TFM_ROTATION,
+ TFM_RESIZE,
+ TFM_TRACKBALL,
+ TFM_TRANSLATION,
+ TFM_EDGE_SLIDE,
+ TFM_VERT_SLIDE)) {
+ restoreTransObjects(t);
+ resetTransModal(t);
+ resetTransRestrictions(t);
+
+ if (t->mode == TFM_ROTATION) {
+ initTrackball(t);
+ }
+ else {
+ initRotation(t);
+ }
+ initSnapping(t, NULL); // need to reinit after mode change
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ }
+ break;
+ case TFM_MODAL_RESIZE:
+ /* only switch when... */
+ if (ELEM(t->mode,
+ TFM_ROTATION,
+ TFM_TRANSLATION,
+ TFM_TRACKBALL,
+ TFM_EDGE_SLIDE,
+ TFM_VERT_SLIDE)) {
+
+ /* Scale isn't normally very useful after extrude along normals, see T39756 */
+ if ((t->con.mode & CON_APPLY) && (t->con.orientation == V3D_ORIENT_NORMAL)) {
+ stopConstraint(t);
+ }
+
+ restoreTransObjects(t);
+ resetTransModal(t);
+ resetTransRestrictions(t);
+ initResize(t);
+ initSnapping(t, NULL); // need to reinit after mode change
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ else if (t->mode == TFM_SHRINKFATTEN) {
+ t->flag ^= T_ALT_TRANSFORM;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ else if (t->mode == TFM_RESIZE) {
+ if (t->options & CTX_MOVIECLIP) {
+ restoreTransObjects(t);
+
+ t->flag ^= T_ALT_TRANSFORM;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ }
+ break;
+
+ case TFM_MODAL_SNAP_INV_ON:
+ t->modifiers |= MOD_SNAP_INVERT;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ break;
+ case TFM_MODAL_SNAP_INV_OFF:
+ t->modifiers &= ~MOD_SNAP_INVERT;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ break;
+ case TFM_MODAL_SNAP_TOGGLE:
+ t->modifiers ^= MOD_SNAP;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ break;
+ case TFM_MODAL_AXIS_X:
+ if (!(t->flag & T_NO_CONSTRAINT)) {
+ transform_event_xyz_constraint(t, XKEY, cmode, 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_CONS_OFF:
+ if ((t->flag & T_NO_CONSTRAINT) == 0) {
+ stopConstraint(t);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_ADD_SNAP:
+ addSnapPoint(t);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ break;
+ case TFM_MODAL_REMOVE_SNAP:
+ removeSnapPoint(t);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ break;
+ case TFM_MODAL_PROPSIZE:
+ /* MOUSEPAN usage... */
+ if (t->flag & T_PROP_EDIT) {
+ float fac = 1.0f + 0.005f * (event->y - event->prevy);
+ t->prop_size *= fac;
+ if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) {
+ t->prop_size = max_ff(min_ff(t->prop_size, ((View3D *)t->view)->clip_end),
+ T_PROP_SIZE_MIN);
+ }
+ else {
+ t->prop_size = max_ff(min_ff(t->prop_size, T_PROP_SIZE_MAX), T_PROP_SIZE_MIN);
+ }
+ calculatePropRatio(t);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_PROPSIZE_UP:
+ if (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) {
+ t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->clip_end);
+ }
+ else {
+ t->prop_size = min_ff(t->prop_size, T_PROP_SIZE_MAX);
+ }
+ calculatePropRatio(t);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_PROPSIZE_DOWN:
+ if (t->flag & T_PROP_EDIT) {
+ t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
+ t->prop_size = max_ff(t->prop_size, T_PROP_SIZE_MIN);
+ calculatePropRatio(t);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_AUTOIK_LEN_INC:
+ if (t->flag & T_AUTOIK) {
+ transform_autoik_update(t, 1);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_AUTOIK_LEN_DEC:
+ if (t->flag & T_AUTOIK) {
+ transform_autoik_update(t, -1);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_INSERTOFS_TOGGLE_DIR:
+ if (t->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
+
+ BLI_assert(t->sa->spacetype == t->spacetype);
+
+ if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) {
+ snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_LEFT;
+ }
+ else if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_LEFT) {
+ snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_RIGHT;
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ t->redraw |= TREDRAW_SOFT;
+ }
+ break;
+ /* Those two are only handled in transform's own handler, see T44634! */
+ case TFM_MODAL_EDGESLIDE_UP:
+ case TFM_MODAL_EDGESLIDE_DOWN:
+ default:
+ break;
+ }
+ }
+ /* else do non-mapped events */
+ else if (event->val == KM_PRESS) {
+ switch (event->type) {
+ 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:
+ t->state = TRANS_CONFIRM;
+ handled = true;
+ break;
+
+ case MIDDLEMOUSE:
+ if ((t->flag & T_NO_CONSTRAINT) == 0) {
+ /* exception for switching to dolly, or trackball, in camera view */
+ if (t->flag & T_CAMERA) {
+ if (t->mode == TFM_TRANSLATION)
+ setLocalConstraint(t, (CON_AXIS2), IFACE_("along local Z"));
+ else if (t->mode == TFM_ROTATION) {
+ restoreTransObjects(t);
+ initTrackball(t);
+ }
+ }
+ else {
+ t->modifiers |= MOD_CONSTRAINT_SELECT;
+ if (t->con.mode & CON_APPLY) {
+ 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);
+ }
+ postSelectConstraint(t);
+ }
+ }
+ t->redraw |= TREDRAW_HARD;
+ 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:
+ /* only switch when... */
+ if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
+ restoreTransObjects(t);
+ resetTransModal(t);
+ resetTransRestrictions(t);
+ initTranslation(t);
+ initSnapping(t, NULL); // need to reinit after mode change
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case SKEY:
+ /* only switch when... */
+ if (ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL)) {
+ restoreTransObjects(t);
+ resetTransModal(t);
+ resetTransRestrictions(t);
+ initResize(t);
+ initSnapping(t, NULL); // need to reinit after mode change
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case RKEY:
+ /* only switch when... */
+ if (!(t->options & CTX_TEXTURE)) {
+ if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION)) {
+ restoreTransObjects(t);
+ resetTransModal(t);
+ resetTransRestrictions(t);
+
+ if (t->mode == TFM_ROTATION) {
+ initTrackball(t);
+ }
+ else {
+ initRotation(t);
+ }
+ initSnapping(t, NULL); // need to reinit after mode change
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ }
+ break;
+ case CKEY:
+ if (event->alt) {
+ if (!(t->options & CTX_NO_PET)) {
+ t->flag ^= T_PROP_CONNECTED;
+ sort_trans_data_dist(t);
+ calculatePropRatio(t);
+ t->redraw = TREDRAW_HARD;
+ handled = true;
+ }
+ }
+ break;
+ case OKEY:
+ if (t->flag & T_PROP_EDIT && event->shift) {
+ t->prop_mode = (t->prop_mode + 1) % PROP_MODE_MAX;
+ calculatePropRatio(t);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case 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)
+ t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->clip_end);
+ calculatePropRatio(t);
+ t->redraw = TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case PAGEUPKEY:
+ case WHEELDOWNMOUSE:
+ if (t->flag & T_AUTOIK) {
+ transform_autoik_update(t, 1);
+ }
+ else {
+ view_editmove(event->type);
+ }
+ t->redraw = TREDRAW_HARD;
+ handled = true;
+ break;
+ case PADMINUS:
+ if (event->alt && t->flag & T_PROP_EDIT) {
+ t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
+ calculatePropRatio(t);
+ t->redraw = TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case PAGEDOWNKEY:
+ case WHEELUPMOUSE:
+ if (t->flag & T_AUTOIK) {
+ transform_autoik_update(t, -1);
+ }
+ else {
+ view_editmove(event->type);
+ }
+ t->redraw = TREDRAW_HARD;
+ handled = true;
+ break;
+ case LEFTALTKEY:
+ case RIGHTALTKEY:
+ if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) {
+ t->flag |= T_ALT_TRANSFORM;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case NKEY:
+ if (ELEM(t->mode, TFM_ROTATION)) {
+ if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
+ restoreTransObjects(t);
+ resetTransModal(t);
+ resetTransRestrictions(t);
+ initNormalRotation(t);
+ t->redraw = TREDRAW_HARD;
+ handled = true;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* Snapping key events */
+ t->redraw |= handleSnapping(t, event);
+ }
+ else if (event->val == KM_RELEASE) {
+ switch (event->type) {
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ t->modifiers &= ~MOD_CONSTRAINT_PLANE;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ break;
+
+ case MIDDLEMOUSE:
+ if ((t->flag & T_NO_CONSTRAINT) == 0) {
+ t->modifiers &= ~MOD_CONSTRAINT_SELECT;
+ postSelectConstraint(t);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case LEFTALTKEY:
+ case RIGHTALTKEY:
+ if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) {
+ t->flag &= ~T_ALT_TRANSFORM;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* confirm transform if launch key is released after mouse move */
+ if (t->flag & T_RELEASE_CONFIRM) {
+ /* XXX Keyrepeat bug in Xorg messes this up, will test when fixed */
+ if ((event->type == t->launch_event) && ISMOUSE(t->launch_event)) {
+ t->state = TRANS_CONFIRM;
+ }
+ }
+ }
+
+ /* if we change snap options, get the unsnapped values back */
+ if ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) !=
+ (modifiers_prev & (MOD_SNAP | MOD_SNAP_INVERT))) {
+ applyMouseInput(t, &t->mouse, t->mval, t->values);
+ }
+
+ /* Per transform event, if present */
+ if (t->handleEvent && (!handled ||
+ /* Needed for vertex slide, see [#38756] */
+ (event->type == MOUSEMOVE))) {
+ t->redraw |= t->handleEvent(t, event);
+ }
+
+ /* Try to init modal numinput now, if possible. */
+ if (!(handled || t->redraw) && ((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) &&
+ handleNumInput(t->context, &(t->num), event)) {
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+
+ if (t->redraw && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+ WM_window_status_area_tag_redraw(CTX_wm_window(t->context));
+ }
+
+ if (handled || t->redraw) {
+ return 0;
+ }
+ else {
+ return OPERATOR_PASS_THROUGH;
+ }
}
bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], float cent2d[2])
{
- TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data");
- bool success;
-
- t->context = C;
+ TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data");
+ bool success;
- t->state = TRANS_RUNNING;
+ t->context = C;
- /* avoid calculating PET */
- t->options = CTX_NO_PET;
+ t->state = TRANS_RUNNING;
- t->mode = TFM_DUMMY;
+ /* avoid calculating PET */
+ t->options = CTX_NO_PET;
- initTransInfo(C, t, NULL, NULL);
+ t->mode = TFM_DUMMY;
- /* avoid doing connectivity lookups (when V3D_AROUND_LOCAL_ORIGINS is set) */
- t->around = V3D_AROUND_CENTER_BOUNDS;
+ initTransInfo(C, t, NULL, NULL);
- createTransData(C, t); // make TransData structs from selection
+ /* avoid doing connectivity lookups (when V3D_AROUND_LOCAL_ORIGINS is set) */
+ t->around = V3D_AROUND_CENTER_BOUNDS;
- t->around = centerMode; // override userdefined mode
+ createTransData(C, t); // make TransData structs from selection
- if (t->data_len_all == 0) {
- success = false;
- }
- else {
- success = true;
+ t->around = centerMode; // override userdefined mode
- calculateCenter(t);
+ if (t->data_len_all == 0) {
+ success = false;
+ }
+ else {
+ success = true;
- if (cent2d) {
- copy_v2_v2(cent2d, t->center2d);
- }
+ calculateCenter(t);
- if (cent3d) {
- // Copy center from constraint center. Transform center can be local
- copy_v3_v3(cent3d, t->center_global);
- }
- }
+ if (cent2d) {
+ copy_v2_v2(cent2d, t->center2d);
+ }
+ if (cent3d) {
+ // Copy center from constraint center. Transform center can be local
+ copy_v3_v3(cent3d, t->center_global);
+ }
+ }
- /* aftertrans does insert keyframes, and clears base flags; doesn't read transdata */
- special_aftertrans_update(C, t);
+ /* aftertrans does insert keyframes, and clears base flags; doesn't read transdata */
+ special_aftertrans_update(C, t);
- postTrans(C, t);
+ postTrans(C, t);
- MEM_freeN(t);
+ MEM_freeN(t);
- return success;
+ return success;
}
typedef enum {
- UP,
- DOWN,
- LEFT,
- RIGHT,
+ UP,
+ DOWN,
+ LEFT,
+ RIGHT,
} ArrowDirection;
#define POS_INDEX 0
@@ -1677,382 +1685,384 @@ typedef enum {
static void drawArrow(ArrowDirection d, short offset, short length, short size)
{
- immBegin(GPU_PRIM_LINES, 6);
-
- switch (d) {
- case LEFT:
- offset = -offset;
- length = -length;
- size = -size;
- ATTR_FALLTHROUGH;
- case RIGHT:
- immVertex2f(POS_INDEX, offset, 0);
- immVertex2f(POS_INDEX, offset + length, 0);
- immVertex2f(POS_INDEX, offset + length, 0);
- immVertex2f(POS_INDEX, offset + length - size, -size);
- immVertex2f(POS_INDEX, offset + length, 0);
- immVertex2f(POS_INDEX, offset + length - size, size);
- break;
-
- case DOWN:
- offset = -offset;
- length = -length;
- size = -size;
- ATTR_FALLTHROUGH;
- case UP:
- immVertex2f(POS_INDEX, 0, offset);
- immVertex2f(POS_INDEX, 0, offset + length);
- immVertex2f(POS_INDEX, 0, offset + length);
- immVertex2f(POS_INDEX, -size, offset + length - size);
- immVertex2f(POS_INDEX, 0, offset + length);
- immVertex2f(POS_INDEX, size, offset + length - size);
- break;
- }
-
- immEnd();
+ immBegin(GPU_PRIM_LINES, 6);
+
+ switch (d) {
+ case LEFT:
+ offset = -offset;
+ length = -length;
+ size = -size;
+ ATTR_FALLTHROUGH;
+ case RIGHT:
+ immVertex2f(POS_INDEX, offset, 0);
+ immVertex2f(POS_INDEX, offset + length, 0);
+ immVertex2f(POS_INDEX, offset + length, 0);
+ immVertex2f(POS_INDEX, offset + length - size, -size);
+ immVertex2f(POS_INDEX, offset + length, 0);
+ immVertex2f(POS_INDEX, offset + length - size, size);
+ break;
+
+ case DOWN:
+ offset = -offset;
+ length = -length;
+ size = -size;
+ ATTR_FALLTHROUGH;
+ case UP:
+ immVertex2f(POS_INDEX, 0, offset);
+ immVertex2f(POS_INDEX, 0, offset + length);
+ immVertex2f(POS_INDEX, 0, offset + length);
+ immVertex2f(POS_INDEX, -size, offset + length - size);
+ immVertex2f(POS_INDEX, 0, offset + length);
+ immVertex2f(POS_INDEX, size, offset + length - size);
+ break;
+ }
+
+ immEnd();
}
static void drawArrowHead(ArrowDirection d, short size)
{
- immBegin(GPU_PRIM_LINES, 4);
-
- switch (d) {
- case LEFT:
- size = -size;
- ATTR_FALLTHROUGH;
- case RIGHT:
- immVertex2f(POS_INDEX, 0, 0);
- immVertex2f(POS_INDEX, -size, -size);
- immVertex2f(POS_INDEX, 0, 0);
- immVertex2f(POS_INDEX, -size, size);
- break;
-
- case DOWN:
- size = -size;
- ATTR_FALLTHROUGH;
- case UP:
- immVertex2f(POS_INDEX, 0, 0);
- immVertex2f(POS_INDEX, -size, -size);
- immVertex2f(POS_INDEX, 0, 0);
- immVertex2f(POS_INDEX, size, -size);
- break;
- }
-
- immEnd();
+ immBegin(GPU_PRIM_LINES, 4);
+
+ switch (d) {
+ case LEFT:
+ size = -size;
+ ATTR_FALLTHROUGH;
+ case RIGHT:
+ immVertex2f(POS_INDEX, 0, 0);
+ immVertex2f(POS_INDEX, -size, -size);
+ immVertex2f(POS_INDEX, 0, 0);
+ immVertex2f(POS_INDEX, -size, size);
+ break;
+
+ case DOWN:
+ size = -size;
+ ATTR_FALLTHROUGH;
+ case UP:
+ immVertex2f(POS_INDEX, 0, 0);
+ immVertex2f(POS_INDEX, -size, -size);
+ immVertex2f(POS_INDEX, 0, 0);
+ immVertex2f(POS_INDEX, size, -size);
+ break;
+ }
+
+ immEnd();
}
static void drawArc(float size, float angle_start, float angle_end, int segments)
{
- float delta = (angle_end - angle_start) / segments;
- float angle;
- int a;
+ float delta = (angle_end - angle_start) / segments;
+ float angle;
+ int a;
- immBegin(GPU_PRIM_LINE_STRIP, segments + 1);
+ immBegin(GPU_PRIM_LINE_STRIP, segments + 1);
- for (angle = angle_start, a = 0; a < segments; angle += delta, a++) {
- immVertex2f(POS_INDEX, cosf(angle) * size, sinf(angle) * size);
- }
- immVertex2f(POS_INDEX, cosf(angle_end) * size, sinf(angle_end) * size);
+ for (angle = angle_start, a = 0; a < segments; angle += delta, a++) {
+ immVertex2f(POS_INDEX, cosf(angle) * size, sinf(angle) * size);
+ }
+ immVertex2f(POS_INDEX, cosf(angle_end) * size, sinf(angle_end) * size);
- immEnd();
+ immEnd();
}
static bool helpline_poll(bContext *C)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *ar = CTX_wm_region(C);
- if (ar && ar->regiontype == RGN_TYPE_WINDOW)
- return 1;
- return 0;
+ if (ar && ar->regiontype == RGN_TYPE_WINDOW)
+ return 1;
+ return 0;
}
static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
{
- TransInfo *t = (TransInfo *)customdata;
-
- if (t->helpline != HLP_NONE) {
- float cent[2];
- float mval[3] = {
- x,
- y,
- 0.0f,
- };
- float tmval[2] = {
- (float)t->mval[0],
- (float)t->mval[1],
- };
-
- 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,
- };
-
- for (int i = 0; i < 2; i++) {
- cent[i] += offset[i];
- tmval[i] += offset[i];
- }
-
- GPU_matrix_push();
-
- /* Dashed lines first. */
- if (ELEM(t->helpline, HLP_SPRING, HLP_ANGLE)) {
- const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- UNUSED_VARS_NDEBUG(shdr_pos); /* silence warning */
- BLI_assert(shdr_pos == POS_INDEX);
-
- GPU_line_width(1.0f);
+ TransInfo *t = (TransInfo *)customdata;
+
+ if (t->helpline != HLP_NONE) {
+ float cent[2];
+ float mval[3] = {
+ x,
+ y,
+ 0.0f,
+ };
+ float tmval[2] = {
+ (float)t->mval[0],
+ (float)t->mval[1],
+ };
+
+ 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,
+ };
+
+ for (int i = 0; i < 2; i++) {
+ cent[i] += offset[i];
+ tmval[i] += offset[i];
+ }
+
+ GPU_matrix_push();
+
+ /* Dashed lines first. */
+ if (ELEM(t->helpline, HLP_SPRING, HLP_ANGLE)) {
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ UNUSED_VARS_NDEBUG(shdr_pos); /* silence warning */
+ BLI_assert(shdr_pos == POS_INDEX);
+
+ GPU_line_width(1.0f);
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+ 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 */
- immUniformThemeColor(TH_VIEW_OVERLAY);
- immUniform1f("dash_width", 6.0f);
- immUniform1f("dash_factor", 0.5f);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2fv(POS_INDEX, cent);
- immVertex2f(POS_INDEX, tmval[0], tmval[1]);
- immEnd();
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniformThemeColor(TH_VIEW_OVERLAY);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
- immUnbindProgram();
- }
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2fv(POS_INDEX, cent);
+ immVertex2f(POS_INDEX, tmval[0], tmval[1]);
+ immEnd();
- /* And now, solid lines. */
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- UNUSED_VARS_NDEBUG(pos); /* silence warning */
- BLI_assert(pos == POS_INDEX);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUnbindProgram();
+ }
- switch (t->helpline) {
- case HLP_SPRING:
- immUniformThemeColor(TH_VIEW_OVERLAY);
+ /* And now, solid lines. */
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ UNUSED_VARS_NDEBUG(pos); /* silence warning */
+ BLI_assert(pos == POS_INDEX);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- GPU_matrix_translate_3fv(mval);
- GPU_matrix_rotate_axis(-RAD2DEGF(atan2f(cent[0] - tmval[0], cent[1] - tmval[1])), 'Z');
+ switch (t->helpline) {
+ case HLP_SPRING:
+ immUniformThemeColor(TH_VIEW_OVERLAY);
- GPU_line_width(3.0f);
- drawArrow(UP, 5, 10, 5);
- drawArrow(DOWN, 5, 10, 5);
- break;
- case HLP_HARROW:
- immUniformThemeColor(TH_VIEW_OVERLAY);
- GPU_matrix_translate_3fv(mval);
+ GPU_matrix_translate_3fv(mval);
+ GPU_matrix_rotate_axis(-RAD2DEGF(atan2f(cent[0] - tmval[0], cent[1] - tmval[1])), 'Z');
- GPU_line_width(3.0f);
- drawArrow(RIGHT, 5, 10, 5);
- drawArrow(LEFT, 5, 10, 5);
- break;
- case HLP_VARROW:
- immUniformThemeColor(TH_VIEW_OVERLAY);
+ GPU_line_width(3.0f);
+ drawArrow(UP, 5, 10, 5);
+ drawArrow(DOWN, 5, 10, 5);
+ break;
+ case HLP_HARROW:
+ immUniformThemeColor(TH_VIEW_OVERLAY);
+ GPU_matrix_translate_3fv(mval);
- GPU_matrix_translate_3fv(mval);
+ GPU_line_width(3.0f);
+ drawArrow(RIGHT, 5, 10, 5);
+ drawArrow(LEFT, 5, 10, 5);
+ break;
+ case HLP_VARROW:
+ immUniformThemeColor(TH_VIEW_OVERLAY);
- GPU_line_width(3.0f);
- drawArrow(UP, 5, 10, 5);
- drawArrow(DOWN, 5, 10, 5);
- break;
- case HLP_CARROW:
- {
- /* Draw arrow based on direction defined by custom-points. */
- immUniformThemeColor(TH_VIEW_OVERLAY);
+ GPU_matrix_translate_3fv(mval);
- GPU_matrix_translate_3fv(mval);
+ GPU_line_width(3.0f);
+ drawArrow(UP, 5, 10, 5);
+ drawArrow(DOWN, 5, 10, 5);
+ break;
+ case HLP_CARROW: {
+ /* Draw arrow based on direction defined by custom-points. */
+ immUniformThemeColor(TH_VIEW_OVERLAY);
- GPU_line_width(3.0f);
+ GPU_matrix_translate_3fv(mval);
- const int *data = t->mouse.data;
- const float dx = data[2] - data[0], dy = data[3] - data[1];
- const float angle = -atan2f(dx, dy);
+ GPU_line_width(3.0f);
- GPU_matrix_push();
+ const int *data = t->mouse.data;
+ const float dx = data[2] - data[0], dy = data[3] - data[1];
+ const float angle = -atan2f(dx, dy);
- GPU_matrix_rotate_axis(RAD2DEGF(angle), 'Z');
+ GPU_matrix_push();
- drawArrow(UP, 5, 10, 5);
- drawArrow(DOWN, 5, 10, 5);
+ GPU_matrix_rotate_axis(RAD2DEGF(angle), 'Z');
- GPU_matrix_pop();
- break;
- }
- case HLP_ANGLE:
- {
- float dx = tmval[0] - cent[0], dy = tmval[1] - cent[1];
- float angle = atan2f(dy, dx);
- float dist = hypotf(dx, dy);
- float delta_angle = min_ff(15.0f / dist, (float)M_PI / 4.0f);
- float spacing_angle = min_ff(5.0f / dist, (float)M_PI / 12.0f);
+ drawArrow(UP, 5, 10, 5);
+ drawArrow(DOWN, 5, 10, 5);
- immUniformThemeColor(TH_VIEW_OVERLAY);
+ GPU_matrix_pop();
+ break;
+ }
+ case HLP_ANGLE: {
+ float dx = tmval[0] - cent[0], dy = tmval[1] - cent[1];
+ float angle = atan2f(dy, dx);
+ float dist = hypotf(dx, dy);
+ float delta_angle = min_ff(15.0f / dist, (float)M_PI / 4.0f);
+ float spacing_angle = min_ff(5.0f / dist, (float)M_PI / 12.0f);
- GPU_matrix_translate_3f(cent[0] - tmval[0] + mval[0], cent[1] - tmval[1] + mval[1], 0);
+ immUniformThemeColor(TH_VIEW_OVERLAY);
- GPU_line_width(3.0f);
- drawArc(dist, angle - delta_angle, angle - spacing_angle, 10);
- drawArc(dist, angle + spacing_angle, angle + delta_angle, 10);
+ GPU_matrix_translate_3f(cent[0] - tmval[0] + mval[0], cent[1] - tmval[1] + mval[1], 0);
- GPU_matrix_push();
+ GPU_line_width(3.0f);
+ drawArc(dist, angle - delta_angle, angle - spacing_angle, 10);
+ drawArc(dist, angle + spacing_angle, angle + delta_angle, 10);
- GPU_matrix_translate_3f(cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0);
- GPU_matrix_rotate_axis(RAD2DEGF(angle - delta_angle), 'Z');
+ GPU_matrix_push();
- drawArrowHead(DOWN, 5);
+ GPU_matrix_translate_3f(
+ cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0);
+ GPU_matrix_rotate_axis(RAD2DEGF(angle - delta_angle), 'Z');
- GPU_matrix_pop();
+ drawArrowHead(DOWN, 5);
- GPU_matrix_translate_3f(cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0);
- GPU_matrix_rotate_axis(RAD2DEGF(angle + delta_angle), 'Z');
+ GPU_matrix_pop();
- drawArrowHead(UP, 5);
- break;
- }
- case HLP_TRACKBALL:
- {
- unsigned char col[3], col2[3];
- UI_GetThemeColor3ubv(TH_GRID, col);
+ GPU_matrix_translate_3f(
+ cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0);
+ GPU_matrix_rotate_axis(RAD2DEGF(angle + delta_angle), 'Z');
- GPU_matrix_translate_3fv(mval);
+ drawArrowHead(UP, 5);
+ break;
+ }
+ case HLP_TRACKBALL: {
+ unsigned char col[3], col2[3];
+ UI_GetThemeColor3ubv(TH_GRID, col);
- GPU_line_width(3.0f);
+ GPU_matrix_translate_3fv(mval);
- UI_make_axis_color(col, col2, 'X');
- immUniformColor3ubv(col2);
+ GPU_line_width(3.0f);
- drawArrow(RIGHT, 5, 10, 5);
- drawArrow(LEFT, 5, 10, 5);
+ UI_make_axis_color(col, col2, 'X');
+ immUniformColor3ubv(col2);
- UI_make_axis_color(col, col2, 'Y');
- immUniformColor3ubv(col2);
+ drawArrow(RIGHT, 5, 10, 5);
+ drawArrow(LEFT, 5, 10, 5);
- drawArrow(UP, 5, 10, 5);
- drawArrow(DOWN, 5, 10, 5);
- break;
- }
- }
+ UI_make_axis_color(col, col2, 'Y');
+ immUniformColor3ubv(col2);
- immUnbindProgram();
- GPU_matrix_pop();
- }
+ drawArrow(UP, 5, 10, 5);
+ drawArrow(DOWN, 5, 10, 5);
+ break;
+ }
+ }
+
+ immUnbindProgram();
+ GPU_matrix_pop();
+ }
}
static bool transinfo_show_overlay(const struct bContext *C, TransInfo *t, ARegion *ar)
{
- /* Don't show overlays when not the active view and when overlay is disabled: T57139 */
- bool ok = false;
- if (ar == t->ar) {
- ok = true;
- }
- else {
- ScrArea *sa = CTX_wm_area(C);
- if (sa->spacetype == SPACE_VIEW3D) {
- View3D *v3d = sa->spacedata.first;
- if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) {
- ok = true;
- }
- }
- }
- return ok;
+ /* Don't show overlays when not the active view and when overlay is disabled: T57139 */
+ bool ok = false;
+ if (ar == t->ar) {
+ ok = true;
+ }
+ else {
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = sa->spacedata.first;
+ if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) {
+ ok = true;
+ }
+ }
+ }
+ return ok;
}
static void drawTransformView(const struct bContext *C, ARegion *ar, void *arg)
{
- TransInfo *t = arg;
+ TransInfo *t = arg;
- if (!transinfo_show_overlay(C, t, ar)) {
- return;
- }
+ if (!transinfo_show_overlay(C, t, ar)) {
+ return;
+ }
- GPU_line_width(1.0f);
+ GPU_line_width(1.0f);
- drawConstraint(t);
- drawPropCircle(C, t);
- drawSnapping(C, t);
+ drawConstraint(t);
+ drawPropCircle(C, t);
+ drawSnapping(C, t);
- if (ar == t->ar) {
- /* edge slide, vert slide */
- drawEdgeSlide(t);
- drawVertSlide(t);
+ if (ar == t->ar) {
+ /* edge slide, vert slide */
+ drawEdgeSlide(t);
+ drawVertSlide(t);
- /* Rotation */
- drawDial3d(t);
- }
+ /* Rotation */
+ drawDial3d(t);
+ }
}
/* 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)
{
- rcti rect;
- const char *printable = IFACE_("Auto Keying On");
- float printable_size[2];
- int xco, yco;
+ rcti rect;
+ const char *printable = IFACE_("Auto Keying On");
+ float printable_size[2];
+ int xco, yco;
- ED_region_visible_rect(ar, &rect);
+ ED_region_visible_rect(ar, &rect);
- const int font_id = BLF_default();
- BLF_width_and_height(font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
+ const int font_id = BLF_default();
+ BLF_width_and_height(
+ font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
- xco = (rect.xmax - U.widget_unit) - (int)printable_size[0];
- yco = (rect.ymax - U.widget_unit);
+ xco = (rect.xmax - U.widget_unit) - (int)printable_size[0];
+ yco = (rect.ymax - U.widget_unit);
- /* 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];
- UI_GetThemeColorShade3ubv(TH_TEXT_HI, -50, color);
- BLF_color3ubv(font_id, color);
+ /* 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];
+ UI_GetThemeColorShade3ubv(TH_TEXT_HI, -50, color);
+ BLF_color3ubv(font_id, color);
#ifdef WITH_INTERNATIONAL
- BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
+ 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);
+ BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
#endif
- /* autokey recording icon... */
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
+ /* autokey recording icon... */
+ 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;
+ xco -= U.widget_unit;
+ yco -= (int)printable_size[1] / 2;
- UI_icon_draw(xco, yco, ICON_REC);
+ UI_icon_draw(xco, yco, ICON_REC);
- GPU_blend(false);
+ GPU_blend(false);
}
static void drawTransformPixel(const struct bContext *C, ARegion *ar, void *arg)
{
- TransInfo *t = arg;
-
- if (!transinfo_show_overlay(C, t, ar)) {
- return;
- }
-
- if (ar == t->ar) {
- Scene *scene = t->scene;
- ViewLayer *view_layer = t->view_layer;
- Object *ob = OBACT(view_layer);
-
- /* draw auto-key-framing hint in the corner
- * - only draw if enabled (advanced users may be distracted/annoyed),
- * for objects that will be autokeyframed (no point otherwise),
- * 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 (t->flag & (T_OBJECT | T_POSE)) {
- if (ob && autokeyframe_cfra_can_key(scene, &ob->id)) {
- drawAutoKeyWarning(t, ar);
- }
- }
- }
- }
- }
+ TransInfo *t = arg;
+
+ if (!transinfo_show_overlay(C, t, ar)) {
+ return;
+ }
+
+ if (ar == t->ar) {
+ Scene *scene = t->scene;
+ ViewLayer *view_layer = t->view_layer;
+ Object *ob = OBACT(view_layer);
+
+ /* draw auto-key-framing hint in the corner
+ * - only draw if enabled (advanced users may be distracted/annoyed),
+ * for objects that will be autokeyframed (no point otherwise),
+ * 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 (t->flag & (T_OBJECT | T_POSE)) {
+ if (ob && autokeyframe_cfra_can_key(scene, &ob->id)) {
+ drawAutoKeyWarning(t, ar);
+ }
+ }
+ }
+ }
+ }
}
/**
@@ -2060,235 +2070,231 @@ static void drawTransformPixel(const struct bContext *C, ARegion *ar, void *arg)
*/
void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- int proportional = 0;
- PropertyRNA *prop;
-
- // Save back mode in case we're in the generic operator
- if ((prop = RNA_struct_find_property(op->ptr, "mode"))) {
- RNA_property_enum_set(op->ptr, prop, t->mode);
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "value"))) {
- float values[4];
-
- copy_v4_v4(values, (t->flag & T_AUTOVALUES) ? t->auto_values : t->values);
-
- if (RNA_property_array_check(prop)) {
- RNA_property_float_set_array(op->ptr, prop, values);
- }
- else {
- RNA_property_float_set(op->ptr, prop, values[0]);
- }
- }
-
- /* convert flag to enum */
- switch (t->flag & T_PROP_EDIT_ALL) {
- case T_PROP_EDIT:
- proportional = PROP_EDIT_ON;
- break;
- case (T_PROP_EDIT | T_PROP_CONNECTED):
- proportional = PROP_EDIT_CONNECTED;
- break;
- case (T_PROP_EDIT | T_PROP_PROJECTED):
- proportional = PROP_EDIT_PROJECTED;
- break;
- default:
- proportional = PROP_EDIT_OFF;
- break;
- }
-
- // If modal, save settings back in scene if not set as operator argument
- if ((t->flag & T_MODAL) || (op->flag & OP_IS_REPEAT)) {
- /* save settings if not set in operator */
-
- /* skip saving proportional edit if it was not actually used */
- if (!(t->options & CTX_NO_PET)) {
- if ((prop = RNA_struct_find_property(op->ptr, "proportional")) &&
- !RNA_property_is_set(op->ptr, prop))
- {
- if (t->spacetype == SPACE_GRAPH)
- ts->proportional_fcurve = proportional;
- else if (t->spacetype == SPACE_ACTION)
- ts->proportional_action = proportional;
- else if (t->obedit_type != -1)
- ts->proportional = proportional;
- else if (t->options & CTX_MASK)
- ts->proportional_mask = (proportional != PROP_EDIT_OFF);
- else
- ts->proportional_objects = (proportional != PROP_EDIT_OFF);
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "proportional_size"))) {
- ts->proportional_size =
- RNA_property_is_set(op->ptr, prop) ? RNA_property_float_get(op->ptr, prop) : t->prop_size;
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) &&
- !RNA_property_is_set(op->ptr, prop))
- {
- ts->prop_mode = t->prop_mode;
- }
- }
-
- /* do we check for parameter? */
- if (transformModeUseSnap(t)) {
- if (t->modifiers & MOD_SNAP) {
- ts->snap_flag |= SCE_SNAP;
- }
- else {
- ts->snap_flag &= ~SCE_SNAP;
- }
- }
-
- if (t->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 ((prop = RNA_struct_find_property(op->ptr, "proportional"))) {
- RNA_property_enum_set(op->ptr, prop, proportional);
- RNA_enum_set(op->ptr, "proportional_edit_falloff", t->prop_mode);
- RNA_float_set(op->ptr, "proportional_size", t->prop_size);
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "mirror"))) {
- 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) {
- int orient_axis = constraintModeToIndex(t);
- if (orient_axis != -1) {
- RNA_property_enum_set(op->ptr, prop, orient_axis);
- }
- }
- else {
- RNA_property_enum_set(op->ptr, prop, t->orient_axis);
- }
- }
- }
- if ((prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) {
- if (t->flag & T_MODAL) {
- RNA_property_enum_set(op->ptr, prop, t->orient_axis_ortho);
- }
- }
-
- 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 */
-
- /* Use 'orient_matrix' instead. */
- if (t->flag & T_MODAL) {
- if (orientation != V3D_ORIENT_CUSTOM_MATRIX) {
- RNA_property_enum_set(op->ptr, prop, orientation);
- }
- }
- }
-
- 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 (ELEM(true, UNPACK3(constraint_axis))) {
- RNA_property_boolean_set_array(op->ptr, prop, constraint_axis);
- }
- }
- }
-
- {
- const char *prop_id = NULL;
- bool prop_state = true;
- if (t->mode == TFM_SHRINKFATTEN) {
- prop_id = "use_even_offset";
- prop_state = false;
- }
-
- if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id))) {
- RNA_property_boolean_set(op->ptr, prop, ((t->flag & T_ALT_TRANSFORM) == 0) == prop_state);
- }
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "correct_uv"))) {
- RNA_property_boolean_set(op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0);
- }
-
- if (t->mode == TFM_SHEAR) {
- prop = RNA_struct_find_property(op->ptr, "shear_axis");
- t->custom.mode.data = POINTER_FROM_INT(RNA_property_enum_get(op->ptr, prop));
- RNA_property_enum_set(op->ptr, prop, POINTER_AS_INT(t->custom.mode.data));
- }
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ int proportional = 0;
+ PropertyRNA *prop;
+
+ // Save back mode in case we're in the generic operator
+ if ((prop = RNA_struct_find_property(op->ptr, "mode"))) {
+ RNA_property_enum_set(op->ptr, prop, t->mode);
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "value"))) {
+ float values[4];
+
+ copy_v4_v4(values, (t->flag & T_AUTOVALUES) ? t->auto_values : t->values);
+
+ if (RNA_property_array_check(prop)) {
+ RNA_property_float_set_array(op->ptr, prop, values);
+ }
+ else {
+ RNA_property_float_set(op->ptr, prop, values[0]);
+ }
+ }
+
+ /* convert flag to enum */
+ switch (t->flag & T_PROP_EDIT_ALL) {
+ case T_PROP_EDIT:
+ proportional = PROP_EDIT_ON;
+ break;
+ case (T_PROP_EDIT | T_PROP_CONNECTED):
+ proportional = PROP_EDIT_CONNECTED;
+ break;
+ case (T_PROP_EDIT | T_PROP_PROJECTED):
+ proportional = PROP_EDIT_PROJECTED;
+ break;
+ default:
+ proportional = PROP_EDIT_OFF;
+ break;
+ }
+
+ // If modal, save settings back in scene if not set as operator argument
+ if ((t->flag & T_MODAL) || (op->flag & OP_IS_REPEAT)) {
+ /* save settings if not set in operator */
+
+ /* skip saving proportional edit if it was not actually used */
+ if (!(t->options & CTX_NO_PET)) {
+ if ((prop = RNA_struct_find_property(op->ptr, "proportional")) &&
+ !RNA_property_is_set(op->ptr, prop)) {
+ if (t->spacetype == SPACE_GRAPH)
+ ts->proportional_fcurve = proportional;
+ else if (t->spacetype == SPACE_ACTION)
+ ts->proportional_action = proportional;
+ else if (t->obedit_type != -1)
+ ts->proportional = proportional;
+ else if (t->options & CTX_MASK)
+ ts->proportional_mask = (proportional != PROP_EDIT_OFF);
+ else
+ ts->proportional_objects = (proportional != PROP_EDIT_OFF);
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "proportional_size"))) {
+ ts->proportional_size = RNA_property_is_set(op->ptr, prop) ?
+ RNA_property_float_get(op->ptr, prop) :
+ t->prop_size;
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) &&
+ !RNA_property_is_set(op->ptr, prop)) {
+ ts->prop_mode = t->prop_mode;
+ }
+ }
+
+ /* do we check for parameter? */
+ if (transformModeUseSnap(t)) {
+ if (t->modifiers & MOD_SNAP) {
+ ts->snap_flag |= SCE_SNAP;
+ }
+ else {
+ ts->snap_flag &= ~SCE_SNAP;
+ }
+ }
+
+ if (t->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 ((prop = RNA_struct_find_property(op->ptr, "proportional"))) {
+ RNA_property_enum_set(op->ptr, prop, proportional);
+ RNA_enum_set(op->ptr, "proportional_edit_falloff", t->prop_mode);
+ RNA_float_set(op->ptr, "proportional_size", t->prop_size);
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "mirror"))) {
+ 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) {
+ int orient_axis = constraintModeToIndex(t);
+ if (orient_axis != -1) {
+ RNA_property_enum_set(op->ptr, prop, orient_axis);
+ }
+ }
+ else {
+ RNA_property_enum_set(op->ptr, prop, t->orient_axis);
+ }
+ }
+ }
+ if ((prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) {
+ if (t->flag & T_MODAL) {
+ RNA_property_enum_set(op->ptr, prop, t->orient_axis_ortho);
+ }
+ }
+
+ 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 */
+
+ /* Use 'orient_matrix' instead. */
+ if (t->flag & T_MODAL) {
+ if (orientation != V3D_ORIENT_CUSTOM_MATRIX) {
+ RNA_property_enum_set(op->ptr, prop, orientation);
+ }
+ }
+ }
+
+ 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 (ELEM(true, UNPACK3(constraint_axis))) {
+ RNA_property_boolean_set_array(op->ptr, prop, constraint_axis);
+ }
+ }
+ }
+
+ {
+ const char *prop_id = NULL;
+ bool prop_state = true;
+ if (t->mode == TFM_SHRINKFATTEN) {
+ prop_id = "use_even_offset";
+ prop_state = false;
+ }
+
+ if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id))) {
+ RNA_property_boolean_set(op->ptr, prop, ((t->flag & T_ALT_TRANSFORM) == 0) == prop_state);
+ }
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "correct_uv"))) {
+ RNA_property_boolean_set(
+ op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0);
+ }
+
+ if (t->mode == TFM_SHEAR) {
+ prop = RNA_struct_find_property(op->ptr, "shear_axis");
+ t->custom.mode.data = POINTER_FROM_INT(RNA_property_enum_get(op->ptr, prop));
+ RNA_property_enum_set(op->ptr, prop, POINTER_AS_INT(t->custom.mode.data));
+ }
}
/**
@@ -2298,896 +2304,896 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
*/
bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event, int mode)
{
- int options = 0;
- PropertyRNA *prop;
-
- t->context = C;
-
- /* added initialize, for external calls to set stuff in TransInfo, like undo string */
-
- t->state = TRANS_STARTING;
-
- if ((prop = RNA_struct_find_property(op->ptr, "cursor_transform")) && RNA_property_is_set(op->ptr, prop)) {
- if (RNA_property_boolean_get(op->ptr, prop)) {
- options |= CTX_CURSOR;
- }
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "texture_space")) && RNA_property_is_set(op->ptr, prop)) {
- if (RNA_property_boolean_get(op->ptr, prop)) {
- options |= CTX_TEXTURE;
- }
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "gpencil_strokes")) && RNA_property_is_set(op->ptr, prop)) {
- if (RNA_property_boolean_get(op->ptr, prop)) {
- options |= CTX_GPENCIL_STROKES;
- }
- }
-
- t->options = options;
-
- t->mode = mode;
-
- /* Needed to translate tweak events to mouse buttons. */
- t->launch_event = event ? WM_userdef_event_type_from_keymap_type(event->type) : -1;
-
- // XXX Remove this when wm_operator_call_internal doesn't use window->eventstate (which can have type = 0)
- // For gizmo only, so assume LEFTMOUSE
- if (t->launch_event == 0) {
- t->launch_event = LEFTMOUSE;
- }
-
- unit_m3(t->spacemtx);
-
- initTransInfo(C, t, op, event);
- initTransformOrientation(C, t);
-
- if (t->spacetype == SPACE_VIEW3D) {
- t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->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->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->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,
- helpline_poll, drawHelpline, t);
- }
- 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->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->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,
- helpline_poll, drawHelpline, t);
- }
- 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->draw_handle_cursor = WM_paint_cursor_activate(
- CTX_wm_manager(C),
- SPACE_TYPE_ANY, RGN_TYPE_ANY,
- helpline_poll, drawHelpline, t);
- }
- else if (t->spacetype == SPACE_NODE) {
- /*t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->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->draw_handle_cursor = WM_paint_cursor_activate(
- CTX_wm_manager(C),
- SPACE_TYPE_ANY, RGN_TYPE_ANY,
- helpline_poll, drawHelpline, t);
- }
- 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->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->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,
- helpline_poll, drawHelpline, t);
- }
- 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->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->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,
- helpline_poll, drawHelpline, t);
- }
-
- createTransData(C, t); // make TransData structs from selection
-
- if (t->data_len_all == 0) {
- postTrans(C, t);
- return 0;
- }
-
- if (event) {
- /* keymap for shortcut header prints */
- t->keymap = WM_keymap_active(CTX_wm_manager(C), op->type->modalkeymap);
-
- /* Stupid code to have Ctrl-Click on gizmo work ok.
- *
- * Do this only for translation/rotation/resize because only these
- * modes are available from gizmo and doing such check could
- * lead to keymap conflicts for other modes (see #31584)
- */
- if (ELEM(mode, TFM_TRANSLATION, TFM_ROTATION, TFM_RESIZE)) {
- wmKeyMapItem *kmi;
-
- for (kmi = t->keymap->items.first; kmi; kmi = kmi->next) {
- if (kmi->flag & KMI_INACTIVE) {
- continue;
- }
-
- 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) )
- {
- t->modifiers |= MOD_SNAP_INVERT;
- }
- break;
- }
- }
- }
- }
-
- initSnapping(t, op); // Initialize snapping data AFTER mode flags
-
- initSnapSpatial(t, t->snap_spatial);
-
- /* EVIL! posemode code can switch translation to rotate when 1 bone is selected.
- * will be removed (ton) */
-
- /* EVIL2: we gave as argument also texture space context bit... was cleared */
-
- /* EVIL3: extend mode for animation editors also switches modes...
- * but is best way to avoid duplicate code */
- mode = t->mode;
-
- 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->auto_values, values);
- t->flag |= T_AUTOVALUES;
- }
- }
-
- if (event) {
- /* Initialize accurate transform to settings requested by keymap. */
- bool use_accurate = false;
- if ((prop = RNA_struct_find_property(op->ptr, "use_accurate")) && RNA_property_is_set(op->ptr, prop)) {
- if (RNA_property_boolean_get(op->ptr, prop)) {
- use_accurate = true;
- }
- }
- 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:
- prop = RNA_struct_find_property(op->ptr, "shear_axis");
- t->custom.mode.data = POINTER_FROM_INT(RNA_property_enum_get(op->ptr, prop));
- 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;
- }
-
- if (t->state == TRANS_CANCEL) {
- postTrans(C, t);
- return 0;
- }
-
- /* Transformation axis from operator */
- if ((prop = RNA_struct_find_property(op->ptr, "orient_axis")) &&
- RNA_property_is_set(op->ptr, prop))
- {
- t->orient_axis = RNA_property_enum_get(op->ptr, prop);
- }
- if ((prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho")) &&
- RNA_property_is_set(op->ptr, prop))
- {
- t->orient_axis_ortho = RNA_property_enum_get(op->ptr, prop);
- }
-
- /* 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, "values") == 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");
- }
- }
-
- /* Don't write into the values when non-modal because they are already set from operator redo values. */
- if (t->flag & T_MODAL) {
- /* Setup the mouse input with initial values. */
- applyMouseInput(t, &t->mouse, t->mouse.imval, t->values);
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "preserve_clnor"))) {
- if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
-
- FOREACH_TRANS_DATA_CONTAINER(t, tc) {
- if ((((Mesh *)(tc->obedit->data))->flag & ME_AUTOSMOOTH)) {
- BMEditMesh *em = NULL;// BKE_editmesh_from_object(t->obedit);
- bool do_skip = false;
-
- /* Currently only used for two of three most frequent transform ops,
- * can include more ops.
- * Note that scaling cannot be included here,
- * non-uniform scaling will affect normals. */
- if (ELEM(t->mode, TFM_TRANSLATION, TFM_ROTATION)) {
- if (em->bm->totvertsel == em->bm->totvert) {
- /* No need to invalidate if whole mesh is selected. */
- do_skip = true;
- }
- }
-
- if (t->flag & T_MODAL) {
- RNA_property_boolean_set(op->ptr, prop, false);
- }
- else if (!do_skip) {
- const bool preserve_clnor = RNA_property_boolean_get(op->ptr, prop);
- if (preserve_clnor) {
- BKE_editmesh_lnorspace_update(em);
- t->flag |= T_CLNOR_REBUILD;
- }
- BM_lnorspace_invalidate(em->bm, true);
- }
- }
- }
- }
- }
-
- t->context = NULL;
-
- return 1;
+ int options = 0;
+ PropertyRNA *prop;
+
+ t->context = C;
+
+ /* added initialize, for external calls to set stuff in TransInfo, like undo string */
+
+ t->state = TRANS_STARTING;
+
+ if ((prop = RNA_struct_find_property(op->ptr, "cursor_transform")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ options |= CTX_CURSOR;
+ }
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "texture_space")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ options |= CTX_TEXTURE;
+ }
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "gpencil_strokes")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ options |= CTX_GPENCIL_STROKES;
+ }
+ }
+
+ t->options = options;
+
+ t->mode = mode;
+
+ /* Needed to translate tweak events to mouse buttons. */
+ t->launch_event = event ? WM_userdef_event_type_from_keymap_type(event->type) : -1;
+
+ // XXX Remove this when wm_operator_call_internal doesn't use window->eventstate (which can have type = 0)
+ // For gizmo only, so assume LEFTMOUSE
+ if (t->launch_event == 0) {
+ t->launch_event = LEFTMOUSE;
+ }
+
+ unit_m3(t->spacemtx);
+
+ initTransInfo(C, t, op, event);
+ initTransformOrientation(C, t);
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ t->draw_handle_apply = ED_region_draw_cb_activate(
+ t->ar->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->draw_handle_pixel = ED_region_draw_cb_activate(
+ t->ar->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, helpline_poll, drawHelpline, t);
+ }
+ 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->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->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, helpline_poll, drawHelpline, t);
+ }
+ 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->draw_handle_cursor = WM_paint_cursor_activate(
+ CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, helpline_poll, drawHelpline, t);
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ /*t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->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->draw_handle_cursor = WM_paint_cursor_activate(
+ CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, helpline_poll, drawHelpline, t);
+ }
+ 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->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->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, helpline_poll, drawHelpline, t);
+ }
+ 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->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->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, helpline_poll, drawHelpline, t);
+ }
+
+ createTransData(C, t); // make TransData structs from selection
+
+ if (t->data_len_all == 0) {
+ postTrans(C, t);
+ return 0;
+ }
+
+ if (event) {
+ /* keymap for shortcut header prints */
+ t->keymap = WM_keymap_active(CTX_wm_manager(C), op->type->modalkeymap);
+
+ /* Stupid code to have Ctrl-Click on gizmo work ok.
+ *
+ * Do this only for translation/rotation/resize because only these
+ * modes are available from gizmo and doing such check could
+ * lead to keymap conflicts for other modes (see #31584)
+ */
+ if (ELEM(mode, TFM_TRANSLATION, TFM_ROTATION, TFM_RESIZE)) {
+ wmKeyMapItem *kmi;
+
+ for (kmi = t->keymap->items.first; kmi; kmi = kmi->next) {
+ if (kmi->flag & KMI_INACTIVE) {
+ continue;
+ }
+
+ 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)) {
+ t->modifiers |= MOD_SNAP_INVERT;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ initSnapping(t, op); // Initialize snapping data AFTER mode flags
+
+ initSnapSpatial(t, t->snap_spatial);
+
+ /* EVIL! posemode code can switch translation to rotate when 1 bone is selected.
+ * will be removed (ton) */
+
+ /* EVIL2: we gave as argument also texture space context bit... was cleared */
+
+ /* EVIL3: extend mode for animation editors also switches modes...
+ * but is best way to avoid duplicate code */
+ mode = t->mode;
+
+ 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->auto_values, values);
+ t->flag |= T_AUTOVALUES;
+ }
+ }
+
+ if (event) {
+ /* Initialize accurate transform to settings requested by keymap. */
+ bool use_accurate = false;
+ if ((prop = RNA_struct_find_property(op->ptr, "use_accurate")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ use_accurate = true;
+ }
+ }
+ 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:
+ prop = RNA_struct_find_property(op->ptr, "shear_axis");
+ t->custom.mode.data = POINTER_FROM_INT(RNA_property_enum_get(op->ptr, prop));
+ 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;
+ }
+
+ if (t->state == TRANS_CANCEL) {
+ postTrans(C, t);
+ return 0;
+ }
+
+ /* Transformation axis from operator */
+ if ((prop = RNA_struct_find_property(op->ptr, "orient_axis")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ t->orient_axis = RNA_property_enum_get(op->ptr, prop);
+ }
+ if ((prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ t->orient_axis_ortho = RNA_property_enum_get(op->ptr, prop);
+ }
+
+ /* 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, "values") == 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");
+ }
+ }
+
+ /* Don't write into the values when non-modal because they are already set from operator redo values. */
+ if (t->flag & T_MODAL) {
+ /* Setup the mouse input with initial values. */
+ applyMouseInput(t, &t->mouse, t->mouse.imval, t->values);
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "preserve_clnor"))) {
+ if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ if ((((Mesh *)(tc->obedit->data))->flag & ME_AUTOSMOOTH)) {
+ BMEditMesh *em = NULL; // BKE_editmesh_from_object(t->obedit);
+ bool do_skip = false;
+
+ /* Currently only used for two of three most frequent transform ops,
+ * can include more ops.
+ * Note that scaling cannot be included here,
+ * non-uniform scaling will affect normals. */
+ if (ELEM(t->mode, TFM_TRANSLATION, TFM_ROTATION)) {
+ if (em->bm->totvertsel == em->bm->totvert) {
+ /* No need to invalidate if whole mesh is selected. */
+ do_skip = true;
+ }
+ }
+
+ if (t->flag & T_MODAL) {
+ RNA_property_boolean_set(op->ptr, prop, false);
+ }
+ else if (!do_skip) {
+ const bool preserve_clnor = RNA_property_boolean_get(op->ptr, prop);
+ if (preserve_clnor) {
+ BKE_editmesh_lnorspace_update(em);
+ t->flag |= T_CLNOR_REBUILD;
+ }
+ BM_lnorspace_invalidate(em->bm, true);
+ }
+ }
+ }
+ }
+ }
+
+ t->context = NULL;
+
+ return 1;
}
void transformApply(bContext *C, TransInfo *t)
{
- t->context = C;
+ t->context = C;
- if ((t->redraw & TREDRAW_HARD) || (t->draw_handle_apply == NULL && (t->redraw & TREDRAW_SOFT))) {
- selectConstraint(t);
- if (t->transform) {
- t->transform(t, t->mval); // calls recalcData()
- viewRedrawForce(C, t);
- }
- t->redraw = TREDRAW_NOTHING;
- }
- else if (t->redraw & TREDRAW_SOFT) {
- viewRedrawForce(C, t);
- }
+ if ((t->redraw & TREDRAW_HARD) || (t->draw_handle_apply == NULL && (t->redraw & TREDRAW_SOFT))) {
+ selectConstraint(t);
+ if (t->transform) {
+ t->transform(t, t->mval); // calls recalcData()
+ viewRedrawForce(C, t);
+ }
+ t->redraw = TREDRAW_NOTHING;
+ }
+ else if (t->redraw & TREDRAW_SOFT) {
+ viewRedrawForce(C, t);
+ }
- /* If auto confirm is on, break after one pass */
- if (t->options & CTX_AUTOCONFIRM) {
- t->state = TRANS_CONFIRM;
- }
+ /* If auto confirm is on, break after one pass */
+ if (t->options & CTX_AUTOCONFIRM) {
+ t->state = TRANS_CONFIRM;
+ }
- t->context = NULL;
+ t->context = NULL;
}
static void drawTransformApply(const bContext *C, ARegion *UNUSED(ar), void *arg)
{
- TransInfo *t = arg;
+ TransInfo *t = arg;
- if (t->redraw & TREDRAW_SOFT) {
- t->redraw |= TREDRAW_HARD;
- transformApply((bContext *)C, t);
- }
+ if (t->redraw & TREDRAW_SOFT) {
+ t->redraw |= TREDRAW_HARD;
+ transformApply((bContext *)C, t);
+ }
}
int transformEnd(bContext *C, TransInfo *t)
{
- int exit_code = OPERATOR_RUNNING_MODAL;
+ int exit_code = OPERATOR_RUNNING_MODAL;
- t->context = C;
+ t->context = C;
- if (t->state != TRANS_STARTING && t->state != TRANS_RUNNING) {
- /* handle restoring objects */
- if (t->state == TRANS_CANCEL) {
- /* exception, edge slide transformed UVs too */
- if (t->mode == TFM_EDGE_SLIDE) {
- doEdgeSlide(t, 0.0f);
- }
- else if (t->mode == TFM_VERT_SLIDE) {
- doVertSlide(t, 0.0f);
- }
+ if (t->state != TRANS_STARTING && t->state != TRANS_RUNNING) {
+ /* handle restoring objects */
+ if (t->state == TRANS_CANCEL) {
+ /* exception, edge slide transformed UVs too */
+ if (t->mode == TFM_EDGE_SLIDE) {
+ doEdgeSlide(t, 0.0f);
+ }
+ else if (t->mode == TFM_VERT_SLIDE) {
+ doVertSlide(t, 0.0f);
+ }
- exit_code = OPERATOR_CANCELLED;
- restoreTransObjects(t); // calls recalcData()
- }
- else {
- if (t->flag & T_CLNOR_REBUILD) {
- FOREACH_TRANS_DATA_CONTAINER(t, tc) {
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BM_lnorspace_rebuild(em->bm, true);
- }
- }
- exit_code = OPERATOR_FINISHED;
- }
+ exit_code = OPERATOR_CANCELLED;
+ restoreTransObjects(t); // calls recalcData()
+ }
+ else {
+ if (t->flag & T_CLNOR_REBUILD) {
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BM_lnorspace_rebuild(em->bm, true);
+ }
+ }
+ exit_code = OPERATOR_FINISHED;
+ }
- /* aftertrans does insert keyframes, and clears base flags; doesn't read transdata */
- special_aftertrans_update(C, t);
+ /* aftertrans does insert keyframes, and clears base flags; doesn't read transdata */
+ special_aftertrans_update(C, t);
- /* free data */
- postTrans(C, t);
+ /* free data */
+ postTrans(C, t);
- /* send events out for redraws */
- viewRedrawPost(C, t);
+ /* send events out for redraws */
+ viewRedrawPost(C, t);
- viewRedrawForce(C, t);
- }
+ viewRedrawForce(C, t);
+ }
- t->context = NULL;
+ t->context = NULL;
- return exit_code;
+ 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;
+ 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;
+ 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];
+ 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 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);
- }
- }
+ /* 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]);
- }
+ 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);
- }
- }
+ /* 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);
- }
- }
- }
+ 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);
- }
- }
+ 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) */
@@ -3195,246 +3201,258 @@ static void constraintSizeLim(TransInfo *t, TransData *td)
* \{ */
struct BendCustomData {
- /* All values are in global space. */
- float warp_sta[3];
- float warp_end[3];
+ /* All values are in global space. */
+ float warp_sta[3];
+ float warp_end[3];
- float warp_nor[3];
- float warp_tan[3];
+ float warp_nor[3];
+ float warp_tan[3];
- /* for applying the mouse distance */
- float warp_init_dist;
+ /* 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;
+ 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;
+ t->mode = TFM_BEND;
+ t->transform = Bend;
+ t->handleEvent = handleEventBend;
- setInputPostFct(&t->mouse, postInputRotation);
- initMouseInputMode(t, &t->mouse, INPUT_ANGLE_SPRING);
+ 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;
+ 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;
+ 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;
+ 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);
+ //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;
+ t->val = 0.0f;
- data = MEM_callocN(sizeof(*data), __func__);
+ 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);
+ 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);
+ 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);
+ /* 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);
+ data->warp_init_dist = len_v3v3(data->warp_end, data->warp_sta);
- t->custom.mode.data = data;
- t->custom.mode.use_free = true;
+ t->custom.mode.data = data;
+ t->custom.mode.use_free = true;
}
static eRedrawFlag handleEventBend(TransInfo *UNUSED(t), const wmEvent *event)
{
- eRedrawFlag status = TREDRAW_NOTHING;
+ eRedrawFlag status = TREDRAW_NOTHING;
- if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
- status = TREDRAW_HARD;
- }
+ if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
+ status = TREDRAW_HARD;
+ }
- return status;
+ 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;
+ 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;
+ union {
+ struct {
+ float angle, scale;
+ };
+ float vector[2];
+ } values;
- /* amount of radians for bend */
- copy_v2_v2(values.vector, t->values);
+ /* amount of radians for bend */
+ copy_v2_v2(values.vector, t->values);
#if 0
- snapGrid(t, angle_rad);
+ 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;
- }
+ /* 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, 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), IFACE_("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), IFACE_("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);
+ if (applyNumInput(&t->num, values.vector)) {
+ values.scale = values.scale / data->warp_init_dist;
+ }
+
+ copy_v2_v2(t->values, 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),
+ IFACE_("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),
+ IFACE_("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) */
@@ -3443,192 +3461,195 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
static void initShear_mouseInputMode(TransInfo *t)
{
- float dir[3];
+ float dir[3];
- if (t->custom.mode.data == NULL) {
- copy_v3_v3(dir, t->orient_matrix[t->orient_axis_ortho]);
- }
- else {
- cross_v3_v3v3(dir, t->orient_matrix[t->orient_axis_ortho], t->orient_matrix[t->orient_axis]);
- }
+ if (t->custom.mode.data == NULL) {
+ copy_v3_v3(dir, t->orient_matrix[t->orient_axis_ortho]);
+ }
+ else {
+ cross_v3_v3v3(dir, t->orient_matrix[t->orient_axis_ortho], t->orient_matrix[t->orient_axis]);
+ }
- /* Without this, half the gizmo handles move in the opposite direction. */
- if ((t->orient_axis_ortho + 1) % 3 != t->orient_axis) {
- negate_v3(dir);
- }
+ /* Without this, half the gizmo handles move in the opposite direction. */
+ if ((t->orient_axis_ortho + 1) % 3 != t->orient_axis) {
+ 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);
+ 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);
+ initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO);
}
static void initShear(TransInfo *t)
{
- t->mode = TFM_SHEAR;
- t->transform = applyShear;
- t->handleEvent = handleEventShear;
+ 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;
- }
+ if (t->orient_axis == t->orient_axis_ortho) {
+ t->orient_axis = 2;
+ t->orient_axis_ortho = 1;
+ }
- initShear_mouseInputMode(t);
+ 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;
+ 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? */
+ 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;
+ t->flag |= T_NO_CONSTRAINT;
}
static eRedrawFlag handleEventShear(TransInfo *t, const wmEvent *event)
{
- eRedrawFlag status = TREDRAW_NOTHING;
+ eRedrawFlag status = TREDRAW_NOTHING;
- if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
- /* Use custom.mode.data pointer to signal Shear direction */
- if (t->custom.mode.data == NULL) {
- t->custom.mode.data = (void *)1;
- }
- else {
- t->custom.mode.data = NULL;
- }
- initShear_mouseInputMode(t);
+ if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
+ /* Use custom.mode.data pointer to signal Shear direction */
+ if (t->custom.mode.data == NULL) {
+ t->custom.mode.data = (void *)1;
+ }
+ else {
+ t->custom.mode.data = NULL;
+ }
+ initShear_mouseInputMode(t);
- status = TREDRAW_HARD;
- }
- else if (event->type == XKEY && event->val == KM_PRESS) {
- t->custom.mode.data = NULL;
- initShear_mouseInputMode(t);
+ status = TREDRAW_HARD;
+ }
+ else if (event->type == XKEY && event->val == KM_PRESS) {
+ t->custom.mode.data = NULL;
+ initShear_mouseInputMode(t);
- status = TREDRAW_HARD;
- }
- else if (event->type == YKEY && event->val == KM_PRESS) {
- t->custom.mode.data = (void *)1;
- initShear_mouseInputMode(t);
+ status = TREDRAW_HARD;
+ }
+ else if (event->type == YKEY && event->val == KM_PRESS) {
+ t->custom.mode.data = (void *)1;
+ initShear_mouseInputMode(t);
- status = TREDRAW_HARD;
- }
+ status = TREDRAW_HARD;
+ }
- return status;
+ 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[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), IFACE_("Shear: %s %s"), c, t->proptext);
- }
- else {
- /* default header print */
- BLI_snprintf(str, sizeof(str), IFACE_("Shear: %.3f %s (Press X or Y to set shear axis)"), value, t->proptext);
- }
-
- unit_m3(smat);
-
- // Custom data signals shear direction
- if (t->custom.mode.data == NULL)
- smat[1][0] = value;
- else
- smat[0][1] = 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);
+ 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[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), IFACE_("Shear: %s %s"), c, t->proptext);
+ }
+ else {
+ /* default header print */
+ BLI_snprintf(str,
+ sizeof(str),
+ IFACE_("Shear: %.3f %s (Press X or Y to set shear axis)"),
+ value,
+ t->proptext);
+ }
+
+ unit_m3(smat);
+
+ // Custom data signals shear direction
+ if (t->custom.mode.data == NULL)
+ smat[1][0] = value;
+ else
+ smat[0][1] = 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) */
@@ -3637,81 +3658,108 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
static void initResize(TransInfo *t)
{
- t->mode = TFM_RESIZE;
- t->transform = applyResize;
+ t->mode = TFM_RESIZE;
+ t->transform = applyResize;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
+ 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;
+ 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;
+ 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;
+ 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;
+ 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, IFACE_("Scale: %s%s %s"),
- &tvec[0], t->con.text, t->proptext);
- break;
- case 1:
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("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, IFACE_("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, IFACE_("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, IFACE_("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, IFACE_(" Proportional size: %.2f"), t->prop_size);
- }
+ 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,
+ IFACE_("Scale: %s%s %s"),
+ &tvec[0],
+ t->con.text,
+ t->proptext);
+ break;
+ case 1:
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ IFACE_("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,
+ IFACE_("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,
+ IFACE_("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,
+ IFACE_("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, IFACE_(" Proportional size: %.2f"), t->prop_size);
+ }
}
/**
@@ -3721,227 +3769,228 @@ static void headerResize(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_
*/
static void TransMat3ToSize(float mat[3][3], float smat[3][3], float size[3])
{
- float rmat[3][3];
+ float rmat[3][3];
- mat3_to_rot_size(rmat, size, mat);
+ 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];
+ /* 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->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);
- applyNumInput(&t->num, t->values);
-
- float ratio = t->values[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);
+ 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->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);
+ applyNumInput(&t->num, t->values);
+
+ float ratio = t->values[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_AUTOVALUES) {
- copy_v3_v3(t->values, t->auto_values);
- }
- else {
- float ratio = t->values[0];
-
- copy_v3_fl(t->values, ratio);
-
- snapGridIncrement(t, t->values);
-
- if (applyNumInput(&t->num, t->values)) {
- constraintNumInput(t, t->values);
- }
-
- applySnapping(t, t->values);
- }
-
- size_to_mat3(mat, t->values);
- 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[i] = 1.0f;
- }
- else {
- pvec[j++] = t->values[i];
- }
- }
- headerResize(t, pvec, str);
- }
- else {
- headerResize(t, t->values, 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, 1)) {
- size_to_mat3(mat, t->values);
-
- 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);
+ float mat[3][3];
+ int i;
+ char str[UI_MAX_DRAW_STR];
+
+ if (t->flag & T_AUTOVALUES) {
+ copy_v3_v3(t->values, t->auto_values);
+ }
+ else {
+ float ratio = t->values[0];
+
+ copy_v3_fl(t->values, ratio);
+
+ snapGridIncrement(t, t->values);
+
+ if (applyNumInput(&t->num, t->values)) {
+ constraintNumInput(t, t->values);
+ }
+
+ applySnapping(t, t->values);
+ }
+
+ size_to_mat3(mat, t->values);
+ 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[i] = 1.0f;
+ }
+ else {
+ pvec[j++] = t->values[i];
+ }
+ }
+ headerResize(t, pvec, str);
+ }
+ else {
+ headerResize(t, t->values, 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, 1)) {
+ size_to_mat3(mat, t->values);
+
+ 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) */
@@ -3950,101 +3999,101 @@ static void applyResize(TransInfo *t, const int UNUSED(mval[2]))
static void initSkinResize(TransInfo *t)
{
- t->mode = TFM_SKIN_RESIZE;
- t->transform = applySkinResize;
+ t->mode = TFM_SKIN_RESIZE;
+ t->transform = applySkinResize;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
+ 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;
+ 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;
+ 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;
+ 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;
+ 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 size[3], mat[3][3];
- int i;
- char str[UI_MAX_DRAW_STR];
+ float size[3], mat[3][3];
+ int i;
+ char str[UI_MAX_DRAW_STR];
- copy_v3_fl(size, t->values[0]);
+ copy_v3_fl(size, t->values[0]);
- snapGridIncrement(t, size);
+ snapGridIncrement(t, size);
- if (applyNumInput(&t->num, size)) {
- constraintNumInput(t, size);
- }
+ if (applyNumInput(&t->num, size)) {
+ constraintNumInput(t, size);
+ }
- applySnapping(t, size);
+ applySnapping(t, size);
- if (t->flag & T_AUTOVALUES) {
- copy_v3_v3(size, t->auto_values);
- }
+ if (t->flag & T_AUTOVALUES) {
+ copy_v3_v3(size, t->auto_values);
+ }
- copy_v3_v3(t->values, size);
+ copy_v3_v3(t->values, size);
- size_to_mat3(mat, size);
+ size_to_mat3(mat, size);
- headerResize(t, size, str);
+ headerResize(t, size, 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];
+ 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_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ 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->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);
- }
+ 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);
- }
- }
+ 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);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (ToSphere) */
@@ -4053,96 +4102,97 @@ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2]))
static void initToSphere(TransInfo *t)
{
- int i;
+ int i;
- t->mode = TFM_TOSPHERE;
- t->transform = applyToSphere;
+ t->mode = TFM_TOSPHERE;
+ t->transform = applyToSphere;
- initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO);
+ 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;
+ 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;
+ 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;
+ 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);
- }
- }
+ // 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;
+ 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];
+ float vec[3];
+ float ratio, radius;
+ int i;
+ char str[UI_MAX_DRAW_STR];
- ratio = t->values[0];
+ ratio = t->values[0];
- snapGridIncrement(t, &ratio);
+ snapGridIncrement(t, &ratio);
- applyNumInput(&t->num, &ratio);
+ applyNumInput(&t->num, &ratio);
- CLAMP(ratio, 0.0f, 1.0f);
+ CLAMP(ratio, 0.0f, 1.0f);
- t->values[0] = ratio;
+ t->values[0] = ratio;
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
+ outputNumInput(&(t->num), c, &t->scene->unit);
- BLI_snprintf(str, sizeof(str), IFACE_("To Sphere: %s %s"), c, t->proptext);
- }
- else {
- /* default header print */
- BLI_snprintf(str, sizeof(str), IFACE_("To Sphere: %.4f %s"), ratio, t->proptext);
- }
+ BLI_snprintf(str, sizeof(str), IFACE_("To Sphere: %s %s"), c, t->proptext);
+ }
+ else {
+ /* default header print */
+ BLI_snprintf(str, sizeof(str), IFACE_("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;
+ 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;
+ if (td->flag & TD_SKIP)
+ continue;
- sub_v3_v3v3(vec, td->iloc, tc->center_local);
+ sub_v3_v3v3(vec, td->iloc, tc->center_local);
- radius = normalize_v3(vec);
+ radius = normalize_v3(vec);
- tratio = ratio * td->factor;
+ tratio = ratio * td->factor;
- mul_v3_fl(vec, radius * (1.0f - tratio) + t->val * tratio);
+ mul_v3_fl(vec, radius * (1.0f - tratio) + t->val * tratio);
- add_v3_v3v3(td->loc, tc->center_local, vec);
- }
- }
+ add_v3_v3v3(td->loc, tc->center_local, vec);
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Rotation) */
@@ -4151,56 +4201,66 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2]))
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);
- }
+ 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;
+ t->mode = TFM_ROTATION;
+ t->transform = applyRotation;
- setInputPostFct(&t->mouse, postInputRotation);
- initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
+ 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);
+ 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;
+ 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;
+ 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;
+ size_t ofs = 0;
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
+ outputNumInput(&(t->num), c, &t->scene->unit);
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext);
- }
- else {
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Rot: %.2f%s %s"),
- RAD2DEGF(final), t->con.text, t->proptext);
- }
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ IFACE_("Rot: %s %s %s"),
+ &c[0],
+ t->con.text,
+ t->proptext);
+ }
+ else {
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ IFACE_("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, IFACE_(" Proportional size: %.2f"), t->prop_size);
- }
+ if (t->flag & T_PROP_EDIT_ALL) {
+ ofs += BLI_snprintf(
+ str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
+ }
}
/**
@@ -4209,309 +4269,314 @@ static void headerRotation(TransInfo *t, char str[UI_MAX_DRAW_STR], float final)
*
* Protected axis and other transform settings are taken into account.
*/
-static void ElementRotation_ex(TransInfo *t, TransDataContainer *tc, TransData *td, 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)
+static void ElementRotation_ex(
+ TransInfo *t, TransDataContainer *tc, TransData *td, 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);
+ 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 void applyRotationValue(TransInfo *t, float angle, float axis[3])
{
- float mat[3][3];
- int i;
+ float mat[3][3];
+ int i;
- axis_angle_normalized_to_mat3(mat, axis, angle);
+ 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++) {
+ 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_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- if (t->con.applyRot) {
- t->con.applyRot(t, tc, td, axis, NULL);
- axis_angle_normalized_to_mat3(mat, axis, angle * td->factor);
- }
- else if (t->flag & T_PROP_EDIT) {
- axis_angle_normalized_to_mat3(mat, axis, angle * td->factor);
- }
+ if (t->con.applyRot) {
+ t->con.applyRot(t, tc, td, axis, NULL);
+ axis_angle_normalized_to_mat3(mat, axis, angle * td->factor);
+ }
+ else if (t->flag & T_PROP_EDIT) {
+ axis_angle_normalized_to_mat3(mat, axis, angle * td->factor);
+ }
- ElementRotation(t, tc, td, mat, t->around);
- }
- }
+ ElementRotation(t, tc, td, mat, t->around);
+ }
+ }
}
static void applyRotation(TransInfo *t, const int UNUSED(mval[2]))
{
- char str[UI_MAX_DRAW_STR];
+ char str[UI_MAX_DRAW_STR];
- float final;
+ float final;
- final = t->values[0];
+ final = t->values[0];
- snapGridIncrement(t, &final);
+ snapGridIncrement(t, &final);
- float axis_final[3];
- copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]);
+ 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);
- }
+ if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
+ t->con.applyRot(t, NULL, NULL, axis_final, NULL);
+ }
- applySnapping(t, &final);
+ applySnapping(t, &final);
- /* Used to clamp final result in [-PI, PI[ range, no idea why, inheritance from 2.4x area, see T48998. */
- applyNumInput(&t->num, &final);
+ /* Used to clamp final result in [-PI, PI[ range, no idea why, inheritance from 2.4x area, see T48998. */
+ applyNumInput(&t->num, &final);
- t->values[0] = final;
+ t->values[0] = final;
- headerRotation(t, str, final);
+ headerRotation(t, str, final);
- applyRotationValue(t, final, axis_final);
+ applyRotationValue(t, final, axis_final);
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Rotation - Trackball) */
@@ -4520,115 +4585,127 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2]))
static void initTrackball(TransInfo *t)
{
- t->mode = TFM_TRACKBALL;
- t->transform = applyTrackball;
+ t->mode = TFM_TRACKBALL;
+ t->transform = applyTrackball;
- initMouseInputMode(t, &t->mouse, INPUT_TRACKBALL);
+ 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);
+ 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;
+ 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;
+ t->flag |= T_NO_CONSTRAINT;
}
-static void applyTrackballValue(TransInfo *t, const float axis1[3], const float axis2[3], float angles[2])
+static void applyTrackballValue(TransInfo *t,
+ const float axis1[3],
+ const float axis2[3],
+ float angles[2])
{
- float mat[3][3];
- float axis[3];
- float angle;
- int i;
+ 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);
+ 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;
+ 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->flag & TD_SKIP)
+ continue;
- if (t->flag & T_PROP_EDIT) {
- axis_angle_normalized_to_mat3(mat, axis, td->factor * angle);
- }
+ if (t->flag & T_PROP_EDIT) {
+ axis_angle_normalized_to_mat3(mat, axis, td->factor * angle);
+ }
- ElementRotation(t, tc, td, mat, t->around);
- }
- }
+ 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];
+ 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];
+ float phi[2];
- copy_v3_v3(axis1, t->persinv[0]);
- copy_v3_v3(axis2, t->persinv[1]);
- normalize_v3(axis1);
- normalize_v3(axis2);
+ 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);
+ copy_v2_v2(phi, t->values);
- snapGridIncrement(t, phi);
+ snapGridIncrement(t, phi);
- applyNumInput(&t->num, phi);
+ applyNumInput(&t->num, phi);
- copy_v2_v2(t->values, phi);
+ copy_v2_v2(t->values, phi);
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN * 2];
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN * 2];
- outputNumInput(&(t->num), c, &t->scene->unit);
+ outputNumInput(&(t->num), c, &t->scene->unit);
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Trackball: %s %s %s"),
- &c[0], &c[NUM_STR_REP_LEN], t->proptext);
- }
- else {
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Trackball: %.2f %.2f %s"),
- RAD2DEGF(phi[0]), RAD2DEGF(phi[1]), t->proptext);
- }
+ ofs += BLI_snprintf(str + ofs,
+ sizeof(str) - ofs,
+ IFACE_("Trackball: %s %s %s"),
+ &c[0],
+ &c[NUM_STR_REP_LEN],
+ t->proptext);
+ }
+ else {
+ ofs += BLI_snprintf(str + ofs,
+ sizeof(str) - ofs,
+ IFACE_("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, IFACE_(" Proportional size: %.2f"), t->prop_size);
- }
+ if (t->flag & T_PROP_EDIT_ALL) {
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, IFACE_(" 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]);
+#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);
+ mul_m3_m3m3(mat, smat, totmat);
- // TRANSFORM_FIX_ME
- //copy_m3_m3(t->mat, mat); // used in gizmo
+ // TRANSFORM_FIX_ME
+ //copy_m3_m3(t->mat, mat); // used in gizmo
#endif
- applyTrackballValue(t, axis1, axis2, phi);
+ applyTrackballValue(t, axis1, axis2, phi);
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Normal Rotation) */
@@ -4637,153 +4714,154 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
static void storeCustomLNorValue(TransDataContainer *tc, BMesh *bm)
{
- BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
- // BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+ BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
+ // BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
- tc->custom.mode.data = lnors_ed_arr;
- tc->custom.mode.free_cb = freeCustomNormalArray;
+ 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;
+ 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;
+ 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);
- }
- }
+ /* 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);
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
- tc->custom.mode.data = NULL;
- tc->custom.mode.free_cb = NULL;
+ tc->custom.mode.data = NULL;
+ tc->custom.mode.free_cb = NULL;
}
static void initNormalRotation(TransInfo *t)
{
- t->mode = TFM_NORMAL_ROTATION;
- t->transform = applyNormalRotation;
+ t->mode = TFM_NORMAL_ROTATION;
+ t->transform = applyNormalRotation;
- setInputPostFct(&t->mouse, postInputRotation);
- initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
+ 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);
+ 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;
+ 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;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
- BKE_editmesh_lnorspace_update(em);
+ BKE_editmesh_lnorspace_update(em);
- storeCustomLNorValue(tc, bm);
- }
+ 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];
+ char str[UI_MAX_DRAW_STR];
- float axis_final[3];
- copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]);
+ 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);
- }
+ 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;
+ 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;
+ 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);
+ float axis[3];
+ float mat[3][3];
+ float angle = t->values[0];
+ copy_v3_v3(axis, axis_final);
- snapGridIncrement(t, &angle);
+ snapGridIncrement(t, &angle);
- applySnapping(t, &angle);
+ applySnapping(t, &angle);
- applyNumInput(&t->num, &angle);
+ applyNumInput(&t->num, &angle);
- headerRotation(t, str, angle);
+ headerRotation(t, str, angle);
- axis_angle_normalized_to_mat3(mat, axis, 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);
+ 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);
- }
- }
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->nloc, lnor_ed->clnors_data);
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ 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] = ED_node_grid_size();
- 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;
- }
+ 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] = ED_node_grid_size();
+ 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
@@ -4791,304 +4869,355 @@ static void initSnapSpatial(TransInfo *t, float r_snap[3])
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;
- }
+ 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, IFACE_("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, IFACE_(" 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) ? IFACE_("right") : IFACE_("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, IFACE_("Auto-offset set to %s - press %s to toggle direction | %s"),
- str_dir, str_km, str_old);
-
- MEM_freeN((void *)str_old);
- }
- }
+ 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, IFACE_("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, IFACE_(" 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) ?
+ IFACE_("right") :
+ IFACE_("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,
+ IFACE_("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);
- }
-
- if (use_rotate_offset) {
- add_v3_v3(tvec, rotate_offset);
- }
-
- mul_m3_v3(td->smtx, tvec);
-
- 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);
- }
- }
+ 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);
+ }
+
+ if (use_rotate_offset) {
+ add_v3_v3(tvec, rotate_offset);
+ }
+
+ mul_m3_v3(td->smtx, tvec);
+
+ 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 value_final[3];
+ char str[UI_MAX_DRAW_STR];
+ float value_final[3];
- if (t->flag & T_AUTOVALUES) {
- copy_v3_v3(t->values, t->auto_values);
- }
- else {
- if ((t->con.mode & CON_APPLY) == 0) {
- snapGridIncrement(t, t->values);
- }
+ if (t->flag & T_AUTOVALUES) {
+ copy_v3_v3(t->values, t->auto_values);
+ }
+ else {
+ if ((t->con.mode & CON_APPLY) == 0) {
+ snapGridIncrement(t, t->values);
+ }
- if (applyNumInput(&t->num, t->values)) {
- removeAspectRatio(t, t->values);
- }
+ if (applyNumInput(&t->num, t->values)) {
+ removeAspectRatio(t, t->values);
+ }
- applySnapping(t, t->values);
- }
+ applySnapping(t, t->values);
+ }
- if (t->con.mode & CON_APPLY) {
- float pvec[3] = {0.0f, 0.0f, 0.0f};
- t->con.applyVec(t, NULL, NULL, t->values, value_final, pvec);
- headerTranslation(t, pvec, str);
+ if (t->con.mode & CON_APPLY) {
+ float pvec[3] = {0.0f, 0.0f, 0.0f};
+ t->con.applyVec(t, NULL, NULL, t->values, value_final, pvec);
+ headerTranslation(t, pvec, str);
- /* only so we have re-usable value with redo, see T46741. */
- mul_v3_m3v3(t->values, t->con.imtx, value_final);
- }
- else {
- headerTranslation(t, t->values, str);
- copy_v3_v3(value_final, t->values);
- }
+ /* only so we have re-usable value with redo, see T46741. */
+ mul_v3_m3v3(t->values, t->con.imtx, value_final);
+ }
+ else {
+ headerTranslation(t, t->values, str);
+ copy_v3_v3(value_final, t->values);
+ }
- /* don't use 't->values' now on */
+ /* don't use 't->values' now on */
- applyTranslationValue(t, value_final);
+ applyTranslationValue(t, value_final);
- /* evil hack - redo translation if clipping needed */
- if (t->flag & T_CLIP_UV && clipUVTransform(t, value_final, 0)) {
- applyTranslationValue(t, value_final);
+ /* evil hack - redo translation if clipping needed */
+ if (t->flag & T_CLIP_UV && clipUVTransform(t, value_final, 0)) {
+ applyTranslationValue(t, value_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);
- }
- }
+ /* 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);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Shrink-Fatten) */
@@ -5097,100 +5226,101 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2]))
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;
+ // 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);
+ 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;
+ 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;
+ 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;
- }
+ 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[0] = -distance;
-
- /* header print for NumInput */
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_("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, IFACE_(" 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);
+ 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[0] = -distance;
+
+ /* header print for NumInput */
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_("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,
+ IFACE_(" 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) */
@@ -5199,77 +5329,76 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
static void initTilt(TransInfo *t)
{
- t->mode = TFM_TILT;
- t->transform = applyTilt;
+ t->mode = TFM_TILT;
+ t->transform = applyTilt;
- initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
+ 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);
+ 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;
+ 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;
+ 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];
+ int i;
+ char str[UI_MAX_DRAW_STR];
- float final;
+ float final;
- final = t->values[0];
+ final = t->values[0];
- snapGridIncrement(t, &final);
+ snapGridIncrement(t, &final);
- applyNumInput(&t->num, &final);
+ applyNumInput(&t->num, &final);
- t->values[0] = final;
+ t->values[0] = final;
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
+ outputNumInput(&(t->num), c, &t->scene->unit);
- BLI_snprintf(str, sizeof(str), IFACE_("Tilt: %s° %s"), &c[0], t->proptext);
+ BLI_snprintf(str, sizeof(str), IFACE_("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[0] = final;
- }
- else {
- BLI_snprintf(str, sizeof(str), IFACE_("Tilt: %.2f° %s"), RAD2DEGF(final), t->proptext);
- }
+ /* XXX For some reason, this seems needed for this op, else RNA prop is not updated... :/ */
+ t->values[0] = final;
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("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;
+ 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->flag & TD_SKIP)
+ continue;
- if (td->val) {
- *td->val = td->ival + final * td->factor;
- }
- }
- }
+ if (td->val) {
+ *td->val = td->ival + final * td->factor;
+ }
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Curve Shrink/Fatten) */
@@ -5278,79 +5407,80 @@ static void applyTilt(TransInfo *t, const int UNUSED(mval[2]))
static void initCurveShrinkFatten(TransInfo *t)
{
- t->mode = TFM_CURVE_SHRINKFATTEN;
- t->transform = applyCurveShrinkFatten;
+ t->mode = TFM_CURVE_SHRINKFATTEN;
+ t->transform = applyCurveShrinkFatten;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+ 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;
+ 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;
+ 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;
+ t->flag |= T_NO_ZERO;
#ifdef USE_NUM_NO_ZERO
- t->num.val_flag[0] |= NUM_NO_ZERO;
+ t->num.val_flag[0] |= NUM_NO_ZERO;
#endif
- t->flag |= T_NO_CONSTRAINT;
+ 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];
+ float ratio;
+ int i;
+ char str[UI_MAX_DRAW_STR];
- ratio = t->values[0];
+ ratio = t->values[0];
- snapGridIncrement(t, &ratio);
+ snapGridIncrement(t, &ratio);
- applyNumInput(&t->num, &ratio);
+ applyNumInput(&t->num, &ratio);
- t->values[0] = ratio;
+ t->values[0] = ratio;
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ /* 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), IFACE_("Shrink/Fatten: %s"), c);
- }
- else {
- BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %3f"), ratio);
- }
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %s"), c);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("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;
+ 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->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;
- }
- }
- }
+ 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);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Mask Shrink/Fatten) */
@@ -5359,104 +5489,106 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
static void initMaskShrinkFatten(TransInfo *t)
{
- t->mode = TFM_MASK_SHRINKFATTEN;
- t->transform = applyMaskShrinkFatten;
+ t->mode = TFM_MASK_SHRINKFATTEN;
+ t->transform = applyMaskShrinkFatten;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+ 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;
+ 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;
+ 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;
+ t->flag |= T_NO_ZERO;
#ifdef USE_NUM_NO_ZERO
- t->num.val_flag[0] |= NUM_NO_ZERO;
+ t->num.val_flag[0] |= NUM_NO_ZERO;
#endif
- t->flag |= T_NO_CONSTRAINT;
+ 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];
+ float ratio;
+ int i;
+ bool initial_feather = false;
+ char str[UI_MAX_DRAW_STR];
- ratio = t->values[0];
+ ratio = t->values[0];
- snapGridIncrement(t, &ratio);
+ snapGridIncrement(t, &ratio);
- applyNumInput(&t->num, &ratio);
+ applyNumInput(&t->num, &ratio);
- t->values[0] = ratio;
+ t->values[0] = ratio;
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ /* 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), IFACE_("Feather Shrink/Fatten: %s"), c);
- }
- else {
- BLI_snprintf(str, sizeof(str), IFACE_("Feather Shrink/Fatten: %3f"), ratio);
- }
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ BLI_snprintf(str, sizeof(str), IFACE_("Feather Shrink/Fatten: %s"), c);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("Feather Shrink/Fatten: %3f"), ratio);
+ }
- /* detect if no points have feather yet */
- if (ratio > 1.0f) {
- initial_feather = true;
+ /* 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;
+ 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->flag & TD_SKIP)
+ continue;
- if (td->ival >= 0.001f)
- initial_feather = false;
- }
- }
- }
+ 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;
+ /* 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->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;
+ 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;
- }
- }
- }
+ /* 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);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (GPencil Shrink/Fatten) */
@@ -5465,73 +5597,75 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
static void initGPShrinkFatten(TransInfo *t)
{
- t->mode = TFM_GPENCIL_SHRINKFATTEN;
- t->transform = applyGPShrinkFatten;
+ t->mode = TFM_GPENCIL_SHRINKFATTEN;
+ t->transform = applyGPShrinkFatten;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+ 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;
+ 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;
+ 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;
+ t->flag |= T_NO_ZERO;
#ifdef USE_NUM_NO_ZERO
- t->num.val_flag[0] |= NUM_NO_ZERO;
+ t->num.val_flag[0] |= NUM_NO_ZERO;
#endif
- t->flag |= T_NO_CONSTRAINT;
+ 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];
+ float ratio;
+ int i;
+ char str[UI_MAX_DRAW_STR];
- ratio = t->values[0];
+ ratio = t->values[0];
- snapGridIncrement(t, &ratio);
+ snapGridIncrement(t, &ratio);
- applyNumInput(&t->num, &ratio);
+ applyNumInput(&t->num, &ratio);
- t->values[0] = ratio;
+ t->values[0] = ratio;
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ /* 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), IFACE_("Shrink/Fatten: %s"), c);
- }
- else {
- BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %3f"), ratio);
- }
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %s"), c);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("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;
+ 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->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;
- }
- }
- }
+ 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);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -5543,77 +5677,77 @@ static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
static void initGPOpacity(TransInfo *t)
{
- t->mode = TFM_GPENCIL_OPACITY;
- t->transform = applyGPOpacity;
+ t->mode = TFM_GPENCIL_OPACITY;
+ t->transform = applyGPOpacity;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+ 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;
+ 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;
+ 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;
+ t->flag |= T_NO_ZERO;
#ifdef USE_NUM_NO_ZERO
- t->num.val_flag[0] |= NUM_NO_ZERO;
+ t->num.val_flag[0] |= NUM_NO_ZERO;
#endif
- t->flag |= T_NO_CONSTRAINT;
+ 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];
+ float ratio;
+ int i;
+ char str[UI_MAX_DRAW_STR];
- ratio = t->values[0];
+ ratio = t->values[0];
- snapGridIncrement(t, &ratio);
+ snapGridIncrement(t, &ratio);
- applyNumInput(&t->num, &ratio);
+ applyNumInput(&t->num, &ratio);
- t->values[0] = ratio;
+ t->values[0] = ratio;
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ /* 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), IFACE_("Opacity: %s"), c);
- }
- else {
- BLI_snprintf(str, sizeof(str), IFACE_("Opacity: %3f"), ratio);
- }
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ BLI_snprintf(str, sizeof(str), IFACE_("Opacity: %s"), c);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("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;
+ 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->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);
- }
- }
- }
+ 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);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Push/Pull) */
@@ -5622,93 +5756,93 @@ static void applyGPOpacity(TransInfo *t, const int UNUSED(mval[2]))
static void initPushPull(TransInfo *t)
{
- t->mode = TFM_PUSHPULL;
- t->transform = applyPushPull;
+ t->mode = TFM_PUSHPULL;
+ t->transform = applyPushPull;
- initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
+ 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;
+ 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;
+ 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];
+ float vec[3], axis_global[3];
+ float distance;
+ int i;
+ char str[UI_MAX_DRAW_STR];
- distance = t->values[0];
+ distance = t->values[0];
- snapGridIncrement(t, &distance);
+ snapGridIncrement(t, &distance);
- applyNumInput(&t->num, &distance);
+ applyNumInput(&t->num, &distance);
- t->values[0] = distance;
+ t->values[0] = distance;
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
+ outputNumInput(&(t->num), c, &t->scene->unit);
- BLI_snprintf(str, sizeof(str), IFACE_("Push/Pull: %s%s %s"), c, t->con.text, t->proptext);
- }
- else {
- /* default header print */
- BLI_snprintf(str, sizeof(str), IFACE_("Push/Pull: %.4f%s %s"), distance, t->con.text, t->proptext);
- }
+ BLI_snprintf(str, sizeof(str), IFACE_("Push/Pull: %s%s %s"), c, t->con.text, t->proptext);
+ }
+ else {
+ /* default header print */
+ BLI_snprintf(
+ str, sizeof(str), IFACE_("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);
- }
+ 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;
+ 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->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);
+ 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);
+ 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);
- }
- }
+ add_v3_v3v3(td->loc, td->iloc, vec);
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Bevel Weight) */
@@ -5717,80 +5851,82 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
static void initBevelWeight(TransInfo *t)
{
- t->mode = TFM_BWEIGHT;
- t->transform = applyBevelWeight;
+ t->mode = TFM_BWEIGHT;
+ t->transform = applyBevelWeight;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_DELTA);
+ 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;
+ 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;
+ 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;
+ 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];
+ float weight;
+ int i;
+ char str[UI_MAX_DRAW_STR];
- weight = t->values[0];
+ weight = t->values[0];
- CLAMP_MAX(weight, 1.0f);
+ CLAMP_MAX(weight, 1.0f);
- snapGridIncrement(t, &weight);
+ snapGridIncrement(t, &weight);
- applyNumInput(&t->num, &weight);
+ applyNumInput(&t->num, &weight);
- t->values[0] = weight;
+ t->values[0] = weight;
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
+ outputNumInput(&(t->num), c, &t->scene->unit);
- if (weight >= 0.0f)
- BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: +%s %s"), c, t->proptext);
- else
- BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: %s %s"), c, t->proptext);
- }
- else {
- /* default header print */
- if (weight >= 0.0f)
- BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: +%.3f %s"), weight, t->proptext);
- else
- BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: %.3f %s"), weight, t->proptext);
- }
+ if (weight >= 0.0f)
+ BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: +%s %s"), c, t->proptext);
+ else
+ BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: %s %s"), c, t->proptext);
+ }
+ else {
+ /* default header print */
+ if (weight >= 0.0f)
+ BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: +%.3f %s"), weight, t->proptext);
+ else
+ BLI_snprintf(str, sizeof(str), IFACE_("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;
+ 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;
- }
- }
- }
+ 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);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Crease) */
@@ -5799,83 +5935,85 @@ static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2]))
static void initCrease(TransInfo *t)
{
- t->mode = TFM_CREASE;
- t->transform = applyCrease;
+ t->mode = TFM_CREASE;
+ t->transform = applyCrease;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_DELTA);
+ 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;
+ 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;
+ 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;
+ 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];
+ float crease;
+ int i;
+ char str[UI_MAX_DRAW_STR];
- crease = t->values[0];
+ crease = t->values[0];
- CLAMP_MAX(crease, 1.0f);
+ CLAMP_MAX(crease, 1.0f);
- snapGridIncrement(t, &crease);
+ snapGridIncrement(t, &crease);
- applyNumInput(&t->num, &crease);
+ applyNumInput(&t->num, &crease);
- t->values[0] = crease;
+ t->values[0] = crease;
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
+ outputNumInput(&(t->num), c, &t->scene->unit);
- if (crease >= 0.0f)
- BLI_snprintf(str, sizeof(str), IFACE_("Crease: +%s %s"), c, t->proptext);
- else
- BLI_snprintf(str, sizeof(str), IFACE_("Crease: %s %s"), c, t->proptext);
- }
- else {
- /* default header print */
- if (crease >= 0.0f)
- BLI_snprintf(str, sizeof(str), IFACE_("Crease: +%.3f %s"), crease, t->proptext);
- else
- BLI_snprintf(str, sizeof(str), IFACE_("Crease: %.3f %s"), crease, t->proptext);
- }
+ if (crease >= 0.0f)
+ BLI_snprintf(str, sizeof(str), IFACE_("Crease: +%s %s"), c, t->proptext);
+ else
+ BLI_snprintf(str, sizeof(str), IFACE_("Crease: %s %s"), c, t->proptext);
+ }
+ else {
+ /* default header print */
+ if (crease >= 0.0f)
+ BLI_snprintf(str, sizeof(str), IFACE_("Crease: +%.3f %s"), crease, t->proptext);
+ else
+ BLI_snprintf(str, sizeof(str), IFACE_("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;
+ 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->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;
- }
- }
- }
+ 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);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (EditBone (B-bone) width scaling) */
@@ -5884,121 +6022,134 @@ static void applyCrease(TransInfo *t, const int UNUSED(mval[2]))
static void initBoneSize(TransInfo *t)
{
- t->mode = TFM_BONESIZE;
- t->transform = applyBoneSize;
+ t->mode = TFM_BONESIZE;
+ t->transform = applyBoneSize;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
+ 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;
+ 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;
+ 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, IFACE_("ScaleB: %s%s %s"), &tvec[0], t->con.text, t->proptext);
- else
- BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("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, IFACE_("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);
- }
+ 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, IFACE_("ScaleB: %s%s %s"), &tvec[0], t->con.text, t->proptext);
+ else
+ BLI_snprintf(str,
+ UI_MAX_DRAW_STR,
+ IFACE_("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,
+ IFACE_("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];
+ 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);
+ 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);
- }
+ 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;
+ /* 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];
+ float size[3], mat[3][3];
+ float ratio = t->values[0];
+ int i;
+ char str[UI_MAX_DRAW_STR];
- copy_v3_fl(size, ratio);
+ copy_v3_fl(size, ratio);
- snapGridIncrement(t, size);
+ snapGridIncrement(t, size);
- if (applyNumInput(&t->num, size)) {
- constraintNumInput(t, size);
- }
+ if (applyNumInput(&t->num, size)) {
+ constraintNumInput(t, size);
+ }
- copy_v3_v3(t->values, size);
+ copy_v3_v3(t->values, size);
- size_to_mat3(mat, size);
+ size_to_mat3(mat, size);
- if (t->con.applySize) {
- t->con.applySize(t, NULL, NULL, mat);
- }
+ if (t->con.applySize) {
+ t->con.applySize(t, NULL, NULL, mat);
+ }
- copy_m3_m3(t->mat, mat); // used in gizmo
+ copy_m3_m3(t->mat, mat); // used in gizmo
- headerBoneSize(t, size, str);
+ 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;
+ 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->flag & TD_SKIP)
+ continue;
- ElementBoneSize(t, tc, td, mat);
- }
- }
+ ElementBoneSize(t, tc, td, mat);
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Bone Envelope) */
@@ -6007,71 +6158,72 @@ static void applyBoneSize(TransInfo *t, const int UNUSED(mval[2]))
static void initBoneEnvelope(TransInfo *t)
{
- t->mode = TFM_BONE_ENVELOPE;
- t->transform = applyBoneEnvelope;
+ t->mode = TFM_BONE_ENVELOPE;
+ t->transform = applyBoneEnvelope;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+ 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;
+ 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;
+ 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;
+ 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];
+ float ratio;
+ int i;
+ char str[UI_MAX_DRAW_STR];
- ratio = t->values[0];
+ ratio = t->values[0];
- snapGridIncrement(t, &ratio);
+ snapGridIncrement(t, &ratio);
- applyNumInput(&t->num, &ratio);
+ applyNumInput(&t->num, &ratio);
- t->values[0] = ratio;
+ t->values[0] = ratio;
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ /* 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), IFACE_("Envelope: %s"), c);
- }
- else {
- BLI_snprintf(str, sizeof(str), IFACE_("Envelope: %3f"), ratio);
- }
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ BLI_snprintf(str, sizeof(str), IFACE_("Envelope: %s"), c);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("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;
+ 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->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;
- }
- }
- }
+ 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);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -6081,159 +6233,157 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
/** \name Orig-Data Store Utility Functions
* \{ */
-static void slide_origdata_init_flag(
- TransInfo *t, TransDataContainer *tc, SlideOrigData *sod)
-{
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
- const bool has_layer_math = CustomData_has_math(&bm->ldata);
- const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
-
- if ((t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) &&
- /* don't do this at all for non-basis shape keys, too easy to
- * accidentally break uv maps or vertex colors then */
- (bm->shapenr <= 1) &&
- (has_layer_math || (cd_loop_mdisp_offset != -1)))
- {
- sod->use_origfaces = true;
- sod->cd_loop_mdisp_offset = cd_loop_mdisp_offset;
- }
- else {
- sod->use_origfaces = false;
- sod->cd_loop_mdisp_offset = -1;
- }
-}
-
-static void slide_origdata_init_data(
- TransDataContainer *tc, SlideOrigData *sod)
-{
- if (sod->use_origfaces) {
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
-
- sod->origfaces = BLI_ghash_ptr_new(__func__);
- sod->bm_origfaces = BM_mesh_create(
- &bm_mesh_allocsize_default,
- &((struct BMeshCreateParams){.use_toolflags = false,}));
- /* we need to have matching customdata */
- BM_mesh_copy_init_customdata(sod->bm_origfaces, bm, NULL);
- }
-}
-
-static void slide_origdata_create_data_vert(
- BMesh *bm, SlideOrigData *sod,
- TransDataGenericSlideVert *sv)
-{
- BMIter liter;
- int j, l_num;
- float *loop_weights;
-
- /* copy face data */
- // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) {
- BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, sv->v);
- l_num = liter.count;
- loop_weights = BLI_array_alloca(loop_weights, l_num);
- for (j = 0; j < l_num; j++) {
- BMLoop *l = BM_iter_step(&liter);
- BMLoop *l_prev, *l_next;
- void **val_p;
- if (!BLI_ghash_ensure_p(sod->origfaces, l->f, &val_p)) {
- BMFace *f_copy = BM_face_copy(sod->bm_origfaces, bm, l->f, true, true);
- *val_p = f_copy;
- }
-
- if ((l_prev = BM_loop_find_prev_nodouble(l, l->next, FLT_EPSILON)) &&
- (l_next = BM_loop_find_next_nodouble(l, l_prev, FLT_EPSILON)))
- {
- loop_weights[j] = angle_v3v3v3(l_prev->v->co, l->v->co, l_next->v->co);
- }
- else {
- loop_weights[j] = 0.0f;
- }
-
- }
-
- /* store cd_loop_groups */
- if (sod->layer_math_map_num && (l_num != 0)) {
- sv->cd_loop_groups = BLI_memarena_alloc(sod->arena, sod->layer_math_map_num * sizeof(void *));
- for (j = 0; j < sod->layer_math_map_num; j++) {
- const int layer_nr = sod->layer_math_map[j];
- sv->cd_loop_groups[j] = BM_vert_loop_groups_data_layer_create(bm, sv->v, layer_nr, loop_weights, sod->arena);
- }
- }
- else {
- sv->cd_loop_groups = NULL;
- }
-
- BLI_ghash_insert(sod->origverts, sv->v, sv);
-}
-
-static void slide_origdata_create_data(
- TransDataContainer *tc, SlideOrigData *sod,
- TransDataGenericSlideVert *sv_array, unsigned int v_stride, unsigned int v_num)
-{
- if (sod->use_origfaces) {
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
- unsigned int i;
- TransDataGenericSlideVert *sv;
-
- int layer_index_dst;
- int j;
-
- layer_index_dst = 0;
-
- if (CustomData_has_math(&bm->ldata)) {
- /* over alloc, only 'math' layers are indexed */
- sod->layer_math_map = MEM_mallocN(bm->ldata.totlayer * sizeof(int), __func__);
- for (j = 0; j < bm->ldata.totlayer; j++) {
- if (CustomData_layer_has_math(&bm->ldata, j)) {
- sod->layer_math_map[layer_index_dst++] = j;
- }
- }
- BLI_assert(layer_index_dst != 0);
- }
-
- sod->layer_math_map_num = layer_index_dst;
-
- sod->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
-
- sod->origverts = BLI_ghash_ptr_new_ex(__func__, v_num);
-
- for (i = 0, sv = sv_array; i < v_num; i++, sv = POINTER_OFFSET(sv, v_stride)) {
- slide_origdata_create_data_vert(bm, sod, sv);
- }
-
- if (tc->mirror.axis_flag) {
- TransData *td = tc->data;
- TransDataGenericSlideVert *sv_mirror;
-
- sod->sv_mirror = MEM_callocN(sizeof(*sv_mirror) * tc->data_len, __func__);
- sod->totsv_mirror = tc->data_len;
-
- sv_mirror = sod->sv_mirror;
-
- for (i = 0; i < tc->data_len; i++, td++) {
- BMVert *eve = td->extra;
- /* Check the vertex has been used since both sides of the mirror may be selected & sliding. */
- if (eve && !BLI_ghash_haskey(sod->origverts, eve)) {
- sv_mirror->v = eve;
- copy_v3_v3(sv_mirror->co_orig_3d, eve->co);
-
- slide_origdata_create_data_vert(bm, sod, sv_mirror);
- sv_mirror++;
- }
- else {
- sod->totsv_mirror--;
- }
- }
-
- if (sod->totsv_mirror == 0) {
- MEM_freeN(sod->sv_mirror);
- sod->sv_mirror = NULL;
- }
- }
- }
+static void slide_origdata_init_flag(TransInfo *t, TransDataContainer *tc, SlideOrigData *sod)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+ const bool has_layer_math = CustomData_has_math(&bm->ldata);
+ const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
+
+ if ((t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) &&
+ /* don't do this at all for non-basis shape keys, too easy to
+ * accidentally break uv maps or vertex colors then */
+ (bm->shapenr <= 1) && (has_layer_math || (cd_loop_mdisp_offset != -1))) {
+ sod->use_origfaces = true;
+ sod->cd_loop_mdisp_offset = cd_loop_mdisp_offset;
+ }
+ else {
+ sod->use_origfaces = false;
+ sod->cd_loop_mdisp_offset = -1;
+ }
+}
+
+static void slide_origdata_init_data(TransDataContainer *tc, SlideOrigData *sod)
+{
+ if (sod->use_origfaces) {
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+
+ sod->origfaces = BLI_ghash_ptr_new(__func__);
+ sod->bm_origfaces = BM_mesh_create(&bm_mesh_allocsize_default,
+ &((struct BMeshCreateParams){
+ .use_toolflags = false,
+ }));
+ /* we need to have matching customdata */
+ BM_mesh_copy_init_customdata(sod->bm_origfaces, bm, NULL);
+ }
+}
+
+static void slide_origdata_create_data_vert(BMesh *bm,
+ SlideOrigData *sod,
+ TransDataGenericSlideVert *sv)
+{
+ BMIter liter;
+ int j, l_num;
+ float *loop_weights;
+
+ /* copy face data */
+ // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) {
+ BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, sv->v);
+ l_num = liter.count;
+ loop_weights = BLI_array_alloca(loop_weights, l_num);
+ for (j = 0; j < l_num; j++) {
+ BMLoop *l = BM_iter_step(&liter);
+ BMLoop *l_prev, *l_next;
+ void **val_p;
+ if (!BLI_ghash_ensure_p(sod->origfaces, l->f, &val_p)) {
+ BMFace *f_copy = BM_face_copy(sod->bm_origfaces, bm, l->f, true, true);
+ *val_p = f_copy;
+ }
+
+ if ((l_prev = BM_loop_find_prev_nodouble(l, l->next, FLT_EPSILON)) &&
+ (l_next = BM_loop_find_next_nodouble(l, l_prev, FLT_EPSILON))) {
+ loop_weights[j] = angle_v3v3v3(l_prev->v->co, l->v->co, l_next->v->co);
+ }
+ else {
+ loop_weights[j] = 0.0f;
+ }
+ }
+
+ /* store cd_loop_groups */
+ if (sod->layer_math_map_num && (l_num != 0)) {
+ sv->cd_loop_groups = BLI_memarena_alloc(sod->arena, sod->layer_math_map_num * sizeof(void *));
+ for (j = 0; j < sod->layer_math_map_num; j++) {
+ const int layer_nr = sod->layer_math_map[j];
+ sv->cd_loop_groups[j] = BM_vert_loop_groups_data_layer_create(
+ bm, sv->v, layer_nr, loop_weights, sod->arena);
+ }
+ }
+ else {
+ sv->cd_loop_groups = NULL;
+ }
+
+ BLI_ghash_insert(sod->origverts, sv->v, sv);
+}
+
+static void slide_origdata_create_data(TransDataContainer *tc,
+ SlideOrigData *sod,
+ TransDataGenericSlideVert *sv_array,
+ unsigned int v_stride,
+ unsigned int v_num)
+{
+ if (sod->use_origfaces) {
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+ unsigned int i;
+ TransDataGenericSlideVert *sv;
+
+ int layer_index_dst;
+ int j;
+
+ layer_index_dst = 0;
+
+ if (CustomData_has_math(&bm->ldata)) {
+ /* over alloc, only 'math' layers are indexed */
+ sod->layer_math_map = MEM_mallocN(bm->ldata.totlayer * sizeof(int), __func__);
+ for (j = 0; j < bm->ldata.totlayer; j++) {
+ if (CustomData_layer_has_math(&bm->ldata, j)) {
+ sod->layer_math_map[layer_index_dst++] = j;
+ }
+ }
+ BLI_assert(layer_index_dst != 0);
+ }
+
+ sod->layer_math_map_num = layer_index_dst;
+
+ sod->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
+ sod->origverts = BLI_ghash_ptr_new_ex(__func__, v_num);
+
+ for (i = 0, sv = sv_array; i < v_num; i++, sv = POINTER_OFFSET(sv, v_stride)) {
+ slide_origdata_create_data_vert(bm, sod, sv);
+ }
+
+ if (tc->mirror.axis_flag) {
+ TransData *td = tc->data;
+ TransDataGenericSlideVert *sv_mirror;
+
+ sod->sv_mirror = MEM_callocN(sizeof(*sv_mirror) * tc->data_len, __func__);
+ sod->totsv_mirror = tc->data_len;
+
+ sv_mirror = sod->sv_mirror;
+
+ for (i = 0; i < tc->data_len; i++, td++) {
+ BMVert *eve = td->extra;
+ /* Check the vertex has been used since both sides of the mirror may be selected & sliding. */
+ if (eve && !BLI_ghash_haskey(sod->origverts, eve)) {
+ sv_mirror->v = eve;
+ copy_v3_v3(sv_mirror->co_orig_3d, eve->co);
+
+ slide_origdata_create_data_vert(bm, sod, sv_mirror);
+ sv_mirror++;
+ }
+ else {
+ sod->totsv_mirror--;
+ }
+ }
+
+ if (sod->totsv_mirror == 0) {
+ MEM_freeN(sod->sv_mirror);
+ sod->sv_mirror = NULL;
+ }
+ }
+ }
}
/**
@@ -6241,192 +6391,199 @@ static void slide_origdata_create_data(
*/
static const float *slide_origdata_orig_vert_co(SlideOrigData *sod, BMVert *v)
{
- TransDataGenericSlideVert *sv = BLI_ghash_lookup(sod->origverts, v);
- return sv ? sv->co_orig_3d : v->co;
-}
-
-static void slide_origdata_interp_data_vert(
- SlideOrigData *sod, BMesh *bm, bool is_final,
- TransDataGenericSlideVert *sv)
-{
- BMIter liter;
- int j, l_num;
- float *loop_weights;
- const bool is_moved = (len_squared_v3v3(sv->v->co, sv->co_orig_3d) > FLT_EPSILON);
- const bool do_loop_weight = sod->layer_math_map_num && is_moved;
- const bool do_loop_mdisps = is_final && is_moved && (sod->cd_loop_mdisp_offset != -1);
- const float *v_proj_axis = sv->v->no;
- /* original (l->prev, l, l->next) projections for each loop ('l' remains unchanged) */
- float v_proj[3][3];
-
- if (do_loop_weight || do_loop_mdisps) {
- project_plane_normalized_v3_v3v3(v_proj[1], sv->co_orig_3d, v_proj_axis);
- }
-
- // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT)
- BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, sv->v);
- l_num = liter.count;
- loop_weights = do_loop_weight ? BLI_array_alloca(loop_weights, l_num) : NULL;
- for (j = 0; j < l_num; j++) {
- BMFace *f_copy; /* the copy of 'f' */
- BMLoop *l = BM_iter_step(&liter);
-
- f_copy = BLI_ghash_lookup(sod->origfaces, l->f);
-
- /* only loop data, no vertex data since that contains shape keys,
- * and we do not want to mess up other shape keys */
- BM_loop_interp_from_face(bm, l, f_copy, false, false);
-
- /* make sure face-attributes are correct (e.g. MTexPoly) */
- BM_elem_attrs_copy_ex(sod->bm_origfaces, bm, f_copy, l->f, 0x0, CD_MASK_NORMAL);
-
- /* weight the loop */
- if (do_loop_weight) {
- const float eps = 1.0e-8f;
- const BMLoop *l_prev = l->prev;
- const BMLoop *l_next = l->next;
- const float *co_prev = slide_origdata_orig_vert_co(sod, l_prev->v);
- const float *co_next = slide_origdata_orig_vert_co(sod, l_next->v);
- bool co_prev_ok;
- bool co_next_ok;
-
-
- /* In the unlikely case that we're next to a zero length edge -
- * walk around the to the next.
- *
- * Since we only need to check if the vertex is in this corner,
- * its not important _which_ loop - as long as its not overlapping
- * 'sv->co_orig_3d', see: T45096. */
- project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
- while (UNLIKELY(((co_prev_ok = (len_squared_v3v3(v_proj[1], v_proj[0]) > eps)) == false) &&
- ((l_prev = l_prev->prev) != l->next)))
- {
- co_prev = slide_origdata_orig_vert_co(sod, l_prev->v);
- project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
- }
- project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis);
- while (UNLIKELY(((co_next_ok = (len_squared_v3v3(v_proj[1], v_proj[2]) > eps)) == false) &&
- ((l_next = l_next->next) != l->prev)))
- {
- co_next = slide_origdata_orig_vert_co(sod, l_next->v);
- project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis);
- }
-
- if (co_prev_ok && co_next_ok) {
- const float dist = dist_signed_squared_to_corner_v3v3v3(sv->v->co, UNPACK3(v_proj), v_proj_axis);
-
- loop_weights[j] = (dist >= 0.0f) ? 1.0f : ((dist <= -eps) ? 0.0f : (1.0f + (dist / eps)));
- if (UNLIKELY(!isfinite(loop_weights[j]))) {
- loop_weights[j] = 0.0f;
- }
- }
- else {
- loop_weights[j] = 0.0f;
- }
- }
- }
-
- if (sod->layer_math_map_num) {
- if (do_loop_weight) {
- for (j = 0; j < sod->layer_math_map_num; j++) {
- BM_vert_loop_groups_data_layer_merge_weights(bm, sv->cd_loop_groups[j], sod->layer_math_map[j], loop_weights);
- }
- }
- else {
- for (j = 0; j < sod->layer_math_map_num; j++) {
- BM_vert_loop_groups_data_layer_merge(bm, sv->cd_loop_groups[j], sod->layer_math_map[j]);
- }
- }
- }
-
- /* Special handling for multires
- *
- * Interpolate from every other loop (not ideal)
- * However values will only be taken from loops which overlap other mdisps.
- * */
- if (do_loop_mdisps) {
- float (*faces_center)[3] = BLI_array_alloca(faces_center, l_num);
- BMLoop *l;
-
- BM_ITER_ELEM_INDEX (l, &liter, sv->v, BM_LOOPS_OF_VERT, j) {
- BM_face_calc_center_median(l->f, faces_center[j]);
- }
-
- BM_ITER_ELEM_INDEX (l, &liter, sv->v, BM_LOOPS_OF_VERT, j) {
- BMFace *f_copy = BLI_ghash_lookup(sod->origfaces, l->f);
- float f_copy_center[3];
- BMIter liter_other;
- BMLoop *l_other;
- int j_other;
-
- BM_face_calc_center_median(f_copy, f_copy_center);
-
- BM_ITER_ELEM_INDEX (l_other, &liter_other, sv->v, BM_LOOPS_OF_VERT, j_other) {
- BM_face_interp_multires_ex(
- bm, l_other->f, f_copy,
- faces_center[j_other], f_copy_center, sod->cd_loop_mdisp_offset);
- }
- }
- }
-}
-
-static void slide_origdata_interp_data(
- Object *obedit, SlideOrigData *sod,
- TransDataGenericSlideVert *sv, unsigned int v_stride, unsigned int v_num,
- bool is_final)
-{
- if (sod->use_origfaces) {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- unsigned int i;
- const bool has_mdisps = (sod->cd_loop_mdisp_offset != -1);
-
- for (i = 0; i < v_num; i++, sv = POINTER_OFFSET(sv, v_stride)) {
-
- if (sv->cd_loop_groups || has_mdisps) {
- slide_origdata_interp_data_vert(sod, bm, is_final, sv);
- }
- }
-
- if (sod->sv_mirror) {
- sv = sod->sv_mirror;
- for (i = 0; i < v_num; i++, sv++) {
- if (sv->cd_loop_groups || has_mdisps) {
- slide_origdata_interp_data_vert(sod, bm, is_final, sv);
- }
- }
- }
- }
-}
-
-static void slide_origdata_free_date(
- SlideOrigData *sod)
-{
- if (sod->use_origfaces) {
- if (sod->bm_origfaces) {
- BM_mesh_free(sod->bm_origfaces);
- sod->bm_origfaces = NULL;
- }
-
- if (sod->origfaces) {
- BLI_ghash_free(sod->origfaces, NULL, NULL);
- sod->origfaces = NULL;
- }
-
- if (sod->origverts) {
- BLI_ghash_free(sod->origverts, NULL, NULL);
- sod->origverts = NULL;
- }
-
- if (sod->arena) {
- BLI_memarena_free(sod->arena);
- sod->arena = NULL;
- }
-
- MEM_SAFE_FREE(sod->layer_math_map);
-
- MEM_SAFE_FREE(sod->sv_mirror);
- }
+ TransDataGenericSlideVert *sv = BLI_ghash_lookup(sod->origverts, v);
+ return sv ? sv->co_orig_3d : v->co;
+}
+
+static void slide_origdata_interp_data_vert(SlideOrigData *sod,
+ BMesh *bm,
+ bool is_final,
+ TransDataGenericSlideVert *sv)
+{
+ BMIter liter;
+ int j, l_num;
+ float *loop_weights;
+ const bool is_moved = (len_squared_v3v3(sv->v->co, sv->co_orig_3d) > FLT_EPSILON);
+ const bool do_loop_weight = sod->layer_math_map_num && is_moved;
+ const bool do_loop_mdisps = is_final && is_moved && (sod->cd_loop_mdisp_offset != -1);
+ const float *v_proj_axis = sv->v->no;
+ /* original (l->prev, l, l->next) projections for each loop ('l' remains unchanged) */
+ float v_proj[3][3];
+
+ if (do_loop_weight || do_loop_mdisps) {
+ project_plane_normalized_v3_v3v3(v_proj[1], sv->co_orig_3d, v_proj_axis);
+ }
+
+ // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT)
+ BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, sv->v);
+ l_num = liter.count;
+ loop_weights = do_loop_weight ? BLI_array_alloca(loop_weights, l_num) : NULL;
+ for (j = 0; j < l_num; j++) {
+ BMFace *f_copy; /* the copy of 'f' */
+ BMLoop *l = BM_iter_step(&liter);
+
+ f_copy = BLI_ghash_lookup(sod->origfaces, l->f);
+
+ /* only loop data, no vertex data since that contains shape keys,
+ * and we do not want to mess up other shape keys */
+ BM_loop_interp_from_face(bm, l, f_copy, false, false);
+
+ /* make sure face-attributes are correct (e.g. MTexPoly) */
+ BM_elem_attrs_copy_ex(sod->bm_origfaces, bm, f_copy, l->f, 0x0, CD_MASK_NORMAL);
+
+ /* weight the loop */
+ if (do_loop_weight) {
+ const float eps = 1.0e-8f;
+ const BMLoop *l_prev = l->prev;
+ const BMLoop *l_next = l->next;
+ const float *co_prev = slide_origdata_orig_vert_co(sod, l_prev->v);
+ const float *co_next = slide_origdata_orig_vert_co(sod, l_next->v);
+ bool co_prev_ok;
+ bool co_next_ok;
+
+ /* In the unlikely case that we're next to a zero length edge -
+ * walk around the to the next.
+ *
+ * Since we only need to check if the vertex is in this corner,
+ * its not important _which_ loop - as long as its not overlapping
+ * 'sv->co_orig_3d', see: T45096. */
+ project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
+ while (UNLIKELY(((co_prev_ok = (len_squared_v3v3(v_proj[1], v_proj[0]) > eps)) == false) &&
+ ((l_prev = l_prev->prev) != l->next))) {
+ co_prev = slide_origdata_orig_vert_co(sod, l_prev->v);
+ project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
+ }
+ project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis);
+ while (UNLIKELY(((co_next_ok = (len_squared_v3v3(v_proj[1], v_proj[2]) > eps)) == false) &&
+ ((l_next = l_next->next) != l->prev))) {
+ co_next = slide_origdata_orig_vert_co(sod, l_next->v);
+ project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis);
+ }
+
+ if (co_prev_ok && co_next_ok) {
+ const float dist = dist_signed_squared_to_corner_v3v3v3(
+ sv->v->co, UNPACK3(v_proj), v_proj_axis);
+
+ loop_weights[j] = (dist >= 0.0f) ? 1.0f : ((dist <= -eps) ? 0.0f : (1.0f + (dist / eps)));
+ if (UNLIKELY(!isfinite(loop_weights[j]))) {
+ loop_weights[j] = 0.0f;
+ }
+ }
+ else {
+ loop_weights[j] = 0.0f;
+ }
+ }
+ }
+
+ if (sod->layer_math_map_num) {
+ if (do_loop_weight) {
+ for (j = 0; j < sod->layer_math_map_num; j++) {
+ BM_vert_loop_groups_data_layer_merge_weights(
+ bm, sv->cd_loop_groups[j], sod->layer_math_map[j], loop_weights);
+ }
+ }
+ else {
+ for (j = 0; j < sod->layer_math_map_num; j++) {
+ BM_vert_loop_groups_data_layer_merge(bm, sv->cd_loop_groups[j], sod->layer_math_map[j]);
+ }
+ }
+ }
+
+ /* Special handling for multires
+ *
+ * Interpolate from every other loop (not ideal)
+ * However values will only be taken from loops which overlap other mdisps.
+ * */
+ if (do_loop_mdisps) {
+ float(*faces_center)[3] = BLI_array_alloca(faces_center, l_num);
+ BMLoop *l;
+
+ BM_ITER_ELEM_INDEX(l, &liter, sv->v, BM_LOOPS_OF_VERT, j)
+ {
+ BM_face_calc_center_median(l->f, faces_center[j]);
+ }
+
+ BM_ITER_ELEM_INDEX(l, &liter, sv->v, BM_LOOPS_OF_VERT, j)
+ {
+ BMFace *f_copy = BLI_ghash_lookup(sod->origfaces, l->f);
+ float f_copy_center[3];
+ BMIter liter_other;
+ BMLoop *l_other;
+ int j_other;
+
+ BM_face_calc_center_median(f_copy, f_copy_center);
+
+ BM_ITER_ELEM_INDEX(l_other, &liter_other, sv->v, BM_LOOPS_OF_VERT, j_other)
+ {
+ BM_face_interp_multires_ex(bm,
+ l_other->f,
+ f_copy,
+ faces_center[j_other],
+ f_copy_center,
+ sod->cd_loop_mdisp_offset);
+ }
+ }
+ }
+}
+
+static void slide_origdata_interp_data(Object *obedit,
+ SlideOrigData *sod,
+ TransDataGenericSlideVert *sv,
+ unsigned int v_stride,
+ unsigned int v_num,
+ bool is_final)
+{
+ if (sod->use_origfaces) {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ unsigned int i;
+ const bool has_mdisps = (sod->cd_loop_mdisp_offset != -1);
+
+ for (i = 0; i < v_num; i++, sv = POINTER_OFFSET(sv, v_stride)) {
+
+ if (sv->cd_loop_groups || has_mdisps) {
+ slide_origdata_interp_data_vert(sod, bm, is_final, sv);
+ }
+ }
+
+ if (sod->sv_mirror) {
+ sv = sod->sv_mirror;
+ for (i = 0; i < v_num; i++, sv++) {
+ if (sv->cd_loop_groups || has_mdisps) {
+ slide_origdata_interp_data_vert(sod, bm, is_final, sv);
+ }
+ }
+ }
+ }
+}
+
+static void slide_origdata_free_date(SlideOrigData *sod)
+{
+ if (sod->use_origfaces) {
+ if (sod->bm_origfaces) {
+ BM_mesh_free(sod->bm_origfaces);
+ sod->bm_origfaces = NULL;
+ }
+
+ if (sod->origfaces) {
+ BLI_ghash_free(sod->origfaces, NULL, NULL);
+ sod->origfaces = NULL;
+ }
+
+ if (sod->origverts) {
+ BLI_ghash_free(sod->origverts, NULL, NULL);
+ sod->origverts = NULL;
+ }
+
+ if (sod->arena) {
+ BLI_memarena_free(sod->arena);
+ sod->arena = NULL;
+ }
+
+ MEM_SAFE_FREE(sod->layer_math_map);
+
+ MEM_SAFE_FREE(sod->sv_mirror);
+ }
}
/** \} */
@@ -6439,100 +6596,95 @@ static void slide_origdata_free_date(
static void calcEdgeSlideCustomPoints(struct TransInfo *t)
{
- EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+ EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
- setCustomPoints(t, &t->mouse, sld->mval_end, sld->mval_start);
+ 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);
+ /* 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;
+ 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;
- }
- }
+ 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;
+ 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);
- }
- }
+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;
+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;
}
/**
@@ -6542,667 +6694,673 @@ static bool bm_loop_calc_opposite_co(BMLoop *l_tmp,
* \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);
+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);
+ /* 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);
- }
+ /* 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;
- }
+ 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);
- }
+ 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);
- }
+ 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));
+ } while ((l != l->radial_next) && ((l = l->radial_next) != l_first));
- if (i) {
- normalize_v3_length(vec_accum, vec_accum_len / (float)i);
- }
+ if (i) {
+ normalize_v3_length(vec_accum, vec_accum_len / (float)i);
+ }
- copy_v3_v3(r_slide_vec, vec_accum);
+ copy_v3_v3(r_slide_vec, vec_accum);
- return NULL;
+ 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 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;
-
- slide_origdata_init_flag(t, tc, &sld->orig_data);
-
- 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
+ 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;
+
+ slide_origdata_init_flag(t, tc, &sld->orig_data);
+
+ 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)
- */
+ {
+ 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));
+ ((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++;
+ loop_nr++;
#undef EDGESLIDE_VERT_IS_INNER
- }
+ }
- /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */
+ /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */
- BLI_assert(STACK_SIZE(sv_array) == sv_tot);
+ BLI_assert(STACK_SIZE(sv_array) == sv_tot);
- sld->sv = sv_array;
- sld->totsv = 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));
- }
+ /* 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);
+ calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, true);
- /* create copies of faces for customdata projection */
- bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
- slide_origdata_init_data(tc, &sld->orig_data);
- slide_origdata_create_data(tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
+ /* create copies of faces for customdata projection */
+ bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+ slide_origdata_init_data(tc, &sld->orig_data);
+ slide_origdata_create_data(
+ tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
- if (rv3d) {
- calcEdgeSlide_even(t, tc, sld, mval);
- }
+ if (rv3d) {
+ calcEdgeSlide_even(t, tc, sld, mval);
+ }
- sld->em = em;
+ sld->em = em;
- tc->custom.mode.data = sld;
+ tc->custom.mode.data = sld;
- MEM_freeN(sv_table);
+ MEM_freeN(sv_table);
- return true;
+ return true;
}
/**
@@ -7211,600 +7369,623 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t, TransDataContainer *t
*/
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;
- }
-
- slide_origdata_init_flag(t, tc, &sld->orig_data);
-
- 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);
-
- /* create copies of faces for customdata projection */
- bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
- slide_origdata_init_data(tc, &sld->orig_data);
- slide_origdata_create_data(tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
-
- if (rv3d) {
- calcEdgeSlide_even(t, tc, sld, mval);
- }
-
- sld->em = em;
-
- tc->custom.mode.data = sld;
-
- MEM_freeN(sv_table);
-
- return true;
+ 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;
+ }
+
+ slide_origdata_init_flag(t, tc, &sld->orig_data);
+
+ 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);
+
+ /* create copies of faces for customdata projection */
+ bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+ slide_origdata_init_data(tc, &sld->orig_data);
+ slide_origdata_create_data(
+ tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
+
+ if (rv3d) {
+ calcEdgeSlide_even(t, tc, sld, mval);
+ }
+
+ sld->em = em;
+
+ 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;
- SlideOrigData *sod = &sld->orig_data;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ EdgeSlideData *sld = tc->custom.mode.data;
+ SlideOrigData *sod = &sld->orig_data;
- if (sod->use_origfaces == false) {
- return;
- }
+ if (sod->use_origfaces == false) {
+ return;
+ }
- slide_origdata_interp_data(tc->obedit, sod, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv, is_final);
- }
+ slide_origdata_interp_data(tc->obedit,
+ sod,
+ (TransDataGenericSlideVert *)sld->sv,
+ sizeof(*sld->sv),
+ sld->totsv,
+ is_final);
+ }
}
void freeEdgeSlideTempFaces(EdgeSlideData *sld)
{
- slide_origdata_free_date(&sld->orig_data);
+ slide_origdata_free_date(&sld->orig_data);
}
-void freeEdgeSlideVerts(TransInfo *UNUSED(t), TransDataContainer *UNUSED(tc), TransCustomData *custom_data)
+void freeEdgeSlideVerts(TransInfo *UNUSED(t),
+ TransDataContainer *UNUSED(tc),
+ TransCustomData *custom_data)
{
- EdgeSlideData *sld = custom_data->data;
+ EdgeSlideData *sld = custom_data->data;
- if (!sld)
- return;
+ if (!sld)
+ return;
- freeEdgeSlideTempFaces(sld);
+ freeEdgeSlideTempFaces(sld);
- bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+ bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
- MEM_freeN(sld->sv);
- MEM_freeN(sld);
+ MEM_freeN(sld->sv);
+ MEM_freeN(sld);
- custom_data->data = NULL;
+ custom_data->data = NULL;
}
-static void initEdgeSlide_ex(TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp)
+static void initEdgeSlide_ex(
+ TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp)
{
- EdgeSlideData *sld;
- bool ok = false;
+ EdgeSlideData *sld;
+ bool ok = false;
- t->mode = TFM_EDGE_SLIDE;
- t->transform = applyEdgeSlide;
- t->handleEvent = handleEventEdgeSlide;
+ 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;
+ {
+ 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;
- }
+ if (!use_clamp) {
+ t->flag |= T_ALT_TRANSFORM;
+ }
- t->custom.mode.data = slp;
- t->custom.mode.use_free = true;
- }
+ 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 (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;
- }
+ 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;
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ sld = tc->custom.mode.data;
+ if (!sld) {
+ continue;
+ }
+ tc->custom.mode.free_cb = freeEdgeSlideVerts;
+ }
- /* set custom point first if you want value to be initialized by init */
- calcEdgeSlideCustomPoints(t);
- initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO_FLIP);
+ /* 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;
+ 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;
+ 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;
+ t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
}
static void initEdgeSlide(TransInfo *t)
{
- initEdgeSlide_ex(t, true, false, false, true);
+ 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 (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;
- }
+ 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;
+ break;
+ case MOUSEMOVE:
+ calcEdgeSlideCustomPoints(t);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return TREDRAW_NOTHING;
}
static void drawEdgeSlide(TransInfo *t)
{
- if ((t->mode == TFM_EDGE_SLIDE) && TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data) {
- const EdgeSlideParams *slp = t->custom.mode.data;
- EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
- 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();
-
- immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
- GPU_point_size(ctrl_size);
- immBegin(GPU_PRIM_POINTS, 1);
- if (slp->flipped) {
- if (curr_sv->v_side[1]) immVertex3fv(pos, curr_sv->v_side[1]->co);
- }
- else {
- if (curr_sv->v_side[0]) immVertex3fv(pos, curr_sv->v_side[0]->co);
- }
- 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);
- }
- }
+ if ((t->mode == TFM_EDGE_SLIDE) && TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data) {
+ const EdgeSlideParams *slp = t->custom.mode.data;
+ EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+ 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();
+
+ immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
+ GPU_point_size(ctrl_size);
+ immBegin(GPU_PRIM_POINTS, 1);
+ if (slp->flipped) {
+ if (curr_sv->v_side[1])
+ immVertex3fv(pos, curr_sv->v_side[1]->co);
+ }
+ else {
+ if (curr_sv->v_side[0])
+ immVertex3fv(pos, curr_sv->v_side[0]->co);
+ }
+ 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 = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
-
- 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;
- 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;
- 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;
- 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);
- }
- }
- }
- }
- }
+ EdgeSlideParams *slp = t->custom.mode.data;
+ EdgeSlideData *sld_active = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+
+ 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;
+ 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;
+ 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;
+ 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[0] = final;
-
- /* header string */
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_("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, IFACE_("(E)ven: %s, "), WM_bool_as_string(use_even));
- if (use_even) {
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped));
- }
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("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);
+ 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[0] = final;
+
+ /* header string */
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_("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, IFACE_("(E)ven: %s, "), WM_bool_as_string(use_even));
+ if (use_even) {
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped));
+ }
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, IFACE_("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) */
@@ -7813,35 +7994,35 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
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];
+ 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];
+ 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];
+ float co_curr_2d[2], co_orig_2d[2];
- int mval_ofs[2], mval_start[2], mval_end[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);
+ 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]);
+ 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);
- }
+ 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);
+ /* 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);
}
/**
@@ -7849,27 +8030,27 @@ static void calcVertSlideCustomPoints(struct TransInfo *t)
*/
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;
+ /* 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;
+ /* 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];
+ 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);
+ 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;
- }
- }
+ 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;
+ }
+ }
}
/**
@@ -7877,530 +8058,547 @@ static void calcVertSlideMouseActiveVert(struct TransInfo *t, const int mval[2])
*/
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)};
+ 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;
+ 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. */
+ /* 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);
+ /* 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 (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;
+ 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]);
+ 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;
- }
- }
+ 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;
- }
- }
- }
+ 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;
-
- slide_origdata_init_flag(t, tc, &sld->orig_data);
-
- 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;
-
- bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
- slide_origdata_init_data(tc, &sld->orig_data);
- slide_origdata_create_data(tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
-
- sld->em = em;
-
- 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;
+ 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;
+
+ slide_origdata_init_flag(t, tc, &sld->orig_data);
+
+ 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;
+
+ bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+ slide_origdata_init_data(tc, &sld->orig_data);
+ slide_origdata_create_data(
+ tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
+
+ sld->em = em;
+
+ 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) {
- VertSlideData *sld = tc->custom.mode.data;
- SlideOrigData *sod = &sld->orig_data;
- if (sod->use_origfaces == true) {
- slide_origdata_interp_data(tc->obedit, sod, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv, is_final);
- }
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ VertSlideData *sld = tc->custom.mode.data;
+ SlideOrigData *sod = &sld->orig_data;
+ if (sod->use_origfaces == true) {
+ slide_origdata_interp_data(tc->obedit,
+ sod,
+ (TransDataGenericSlideVert *)sld->sv,
+ sizeof(*sld->sv),
+ sld->totsv,
+ is_final);
+ }
+ }
}
void freeVertSlideTempFaces(VertSlideData *sld)
{
- slide_origdata_free_date(&sld->orig_data);
+ slide_origdata_free_date(&sld->orig_data);
}
-void freeVertSlideVerts(TransInfo *UNUSED(t), TransDataContainer *UNUSED(tc), TransCustomData *custom_data)
+void freeVertSlideVerts(TransInfo *UNUSED(t),
+ TransDataContainer *UNUSED(tc),
+ TransCustomData *custom_data)
{
- VertSlideData *sld = custom_data->data;
+ VertSlideData *sld = custom_data->data;
- if (!sld)
- return;
+ if (!sld)
+ return;
- freeVertSlideTempFaces(sld);
+ freeVertSlideTempFaces(sld);
- bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+ bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
- 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);
- }
- }
+ 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);
+ MEM_freeN(sld->sv);
+ MEM_freeN(sld);
- custom_data->data = NULL;
+ 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;
+ 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;
+ {
+ 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;
- }
+ if (!use_clamp) {
+ t->flag |= T_ALT_TRANSFORM;
+ }
- t->custom.mode.data = slp;
- t->custom.mode.use_free = true;
- }
+ 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;
- }
- }
+ 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;
- }
+ if (ok == false) {
+ t->state = TRANS_CANCEL;
+ return;
+ }
- /* set custom point first if you want value to be initialized by init */
- calcVertSlideCustomPoints(t);
- initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO);
+ /* 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;
+ 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;
+ 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;
+ t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
}
static void initVertSlide(TransInfo *t)
{
- initVertSlide_ex(t, false, false, true);
+ 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 (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;
+ 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;
+ 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);
+ 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_matrix_push();
- GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_line_width(line_size);
+ GPU_matrix_push();
+ GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
- const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ GPU_line_width(line_size);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- 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);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- immVertex3fv(shdr_pos, a);
- immVertex3fv(shdr_pos, b);
- }
- }
- immEnd();
+ 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);
- GPU_point_size(ctrl_size);
+ immVertex3fv(shdr_pos, a);
+ immVertex3fv(shdr_pos, b);
+ }
+ }
+ immEnd();
- 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();
+ GPU_point_size(ctrl_size);
- immUnbindProgram();
+ 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();
- /* 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];
+ immUnbindProgram();
- mval_ofs[0] = t->mval[0] - t->mouse.imval[0];
- mval_ofs[1] = t->mval[1] - t->mouse.imval[1];
+ /* 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];
- 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);
+ mval_ofs[0] = t->mval[0] - t->mouse.imval[0];
+ mval_ofs[1] = t->mval[1] - t->mouse.imval[1];
- ED_view3d_win_to_delta(t->ar, mval_ofs, co_dest_3d, zfac);
+ 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);
- 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);
+ ED_view3d_win_to_delta(t->ar, mval_ofs, co_dest_3d, zfac);
- add_v3_v3(co_dest_3d, curr_sv->co_orig_3d);
+ 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);
- GPU_line_width(1.0f);
+ add_v3_v3(co_dest_3d, curr_sv->co_orig_3d);
- immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
+ GPU_line_width(1.0f);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
- 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);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3fv(shdr_pos, curr_sv->co_orig_3d);
- immVertex3fv(shdr_pos, co_dest_3d);
- immEnd();
+ 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();
- }
+ immUnbindProgram();
+ }
- GPU_matrix_pop();
+ GPU_matrix_pop();
- GPU_depth_test(true);
- }
- }
+ 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);
- }
- }
- }
- }
+ 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[0] = final;
-
- /* header string */
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_("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, IFACE_("(E)ven: %s, "), WM_bool_as_string(use_even));
- if (use_even) {
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped));
- }
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("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);
+ 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[0] = final;
+
+ /* header string */
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_("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, IFACE_("(E)ven: %s, "), WM_bool_as_string(use_even));
+ if (use_even) {
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped));
+ }
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, IFACE_("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) */
@@ -8409,72 +8607,72 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
static void initBoneRoll(TransInfo *t)
{
- t->mode = TFM_BONE_ROLL;
- t->transform = applyBoneRoll;
+ t->mode = TFM_BONE_ROLL;
+ t->transform = applyBoneRoll;
- initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
+ 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);
+ 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;
+ 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;
+ 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];
+ int i;
+ char str[UI_MAX_DRAW_STR];
- float final;
+ float final;
- final = t->values[0];
+ final = t->values[0];
- snapGridIncrement(t, &final);
+ snapGridIncrement(t, &final);
- applyNumInput(&t->num, &final);
+ applyNumInput(&t->num, &final);
- t->values[0] = final;
+ t->values[0] = final;
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
+ outputNumInput(&(t->num), c, &t->scene->unit);
- BLI_snprintf(str, sizeof(str), IFACE_("Roll: %s"), &c[0]);
- }
- else {
- BLI_snprintf(str, sizeof(str), IFACE_("Roll: %.2f"), RAD2DEGF(final));
- }
+ BLI_snprintf(str, sizeof(str), IFACE_("Roll: %s"), &c[0]);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("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;
+ /* 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;
+ if (td->flag & TD_SKIP)
+ continue;
- *(td->val) = td->ival - final;
- }
- }
+ *(td->val) = td->ival - final;
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Bake-Time) */
@@ -8483,89 +8681,91 @@ static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2]))
static void initBakeTime(TransInfo *t)
{
- t->transform = applyBakeTime;
- initMouseInputMode(t, &t->mouse, INPUT_NONE);
+ 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;
+ 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? */
+ 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 time;
+ int i;
+ char str[UI_MAX_DRAW_STR];
- float fac = 0.1f;
+ float fac = 0.1f;
- /* XXX, disable precision for now,
- * this isn't even accessible by the user */
+ /* 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
+ 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), IFACE_("Time: +%s %s"), c, t->proptext);
- else
- BLI_snprintf(str, sizeof(str), IFACE_("Time: %s %s"), c, t->proptext);
- }
- else {
- /* default header print */
- if (time >= 0.0f)
- BLI_snprintf(str, sizeof(str), IFACE_("Time: +%.3f %s"), time, t->proptext);
- else
- BLI_snprintf(str, sizeof(str), IFACE_("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);
+ {
+ 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), IFACE_("Time: +%s %s"), c, t->proptext);
+ else
+ BLI_snprintf(str, sizeof(str), IFACE_("Time: %s %s"), c, t->proptext);
+ }
+ else {
+ /* default header print */
+ if (time >= 0.0f)
+ BLI_snprintf(str, sizeof(str), IFACE_("Time: +%.3f %s"), time, t->proptext);
+ else
+ BLI_snprintf(str, sizeof(str), IFACE_("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) */
@@ -8574,85 +8774,86 @@ static void applyBakeTime(TransInfo *t, const int mval[2])
static void initMirror(TransInfo *t)
{
- t->transform = applyMirror;
- initMouseInputMode(t, &t->mouse, INPUT_NONE);
+ 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;
- }
+ 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];
+ float size[3], mat[3][3];
+ int i;
+ char str[UI_MAX_DRAW_STR];
- /*
- * OPTIMIZATION:
- * This still recalcs transformation on mouse move
- * while it should only recalc on constraint change
- * */
+ /*
+ * 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;
+ /* if an axis has been selected */
+ if (t->con.mode & CON_APPLY) {
+ size[0] = size[1] = size[2] = -1;
- size_to_mat3(mat, size);
+ size_to_mat3(mat, size);
- if (t->con.applySize) {
- t->con.applySize(t, NULL, NULL, mat);
- }
+ if (t->con.applySize) {
+ t->con.applySize(t, NULL, NULL, mat);
+ }
- BLI_snprintf(str, sizeof(str), IFACE_("Mirror%s"), t->con.text);
+ BLI_snprintf(str, sizeof(str), IFACE_("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;
+ 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->flag & TD_SKIP)
+ continue;
- ElementResize(t, tc, td, mat);
- }
- }
+ ElementResize(t, tc, td, mat);
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
- }
- else {
- size[0] = size[1] = size[2] = 1;
+ ED_area_status_text(t->sa, str);
+ }
+ else {
+ size[0] = size[1] = size[2] = 1;
- size_to_mat3(mat, size);
+ 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;
+ 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->flag & TD_SKIP)
+ continue;
- ElementResize(t, tc, td, mat);
- }
- }
+ ElementResize(t, tc, td, mat);
+ }
+ }
- recalcData(t);
+ recalcData(t);
- if (t->flag & T_2D_EDIT)
- ED_area_status_text(t->sa, IFACE_("Select a mirror axis (X, Y)"));
- else
- ED_area_status_text(t->sa, IFACE_("Select a mirror axis (X, Y, Z)"));
- }
+ if (t->flag & T_2D_EDIT)
+ ED_area_status_text(t->sa, IFACE_("Select a mirror axis (X, Y)"));
+ else
+ ED_area_status_text(t->sa, IFACE_("Select a mirror axis (X, Y, Z)"));
+ }
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Align) */
@@ -8661,59 +8862,58 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2]))
static void initAlign(TransInfo *t)
{
- t->flag |= T_NO_CONSTRAINT;
+ t->flag |= T_NO_CONSTRAINT;
- t->transform = applyAlign;
+ t->transform = applyAlign;
- initMouseInputMode(t, &t->mouse, INPUT_NONE);
+ initMouseInputMode(t, &t->mouse, INPUT_NONE);
}
static void applyAlign(TransInfo *t, const int UNUSED(mval[2]))
{
- float center[3];
- int i;
+ 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];
- 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_NOACTION)
- break;
+ if (td->flag & TD_SKIP)
+ continue;
- 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);
+ }
+ }
- /* 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);
- invert_m3_m3(invmat, td->axismtx);
+ mul_m3_m3m3(mat, t->spacemtx, invmat);
- mul_m3_m3m3(mat, t->spacemtx, invmat);
+ ElementRotation(t, tc, td, mat, t->around);
+ }
+ /* restoring original center */
+ copy_v3_v3(tc->center_local, center);
+ }
- ElementRotation(t, tc, td, mat, t->around);
- }
- /* restoring original center */
- copy_v3_v3(tc->center_local, center);
- }
+ recalcData(t);
- recalcData(t);
-
- ED_area_status_text(t->sa, IFACE_("Align"));
+ ED_area_status_text(t->sa, IFACE_("Align"));
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Sequencer Slide) */
@@ -8722,98 +8922,101 @@ static void applyAlign(TransInfo *t, const int UNUSED(mval[2]))
static void initSeqSlide(TransInfo *t)
{
- t->transform = applySeqSlide;
+ t->transform = applySeqSlide;
- initMouseInputMode(t, &t->mouse, INPUT_VECTOR);
+ initMouseInputMode(t, &t->mouse, INPUT_VECTOR);
- t->idx_max = 1;
- t->num.flag = 0;
- t->num.idx_max = t->idx_max;
+ 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;
+ 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;
+ 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;
+ 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]);
- }
+ 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, IFACE_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text);
+ ofs += BLI_snprintf(
+ str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("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, IFACE_(" or Alt) Expand to fit %s"),
- WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0));
+ 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,
+ IFACE_(" 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;
+ 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;
+ 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->flag & TD_SKIP)
+ continue;
- madd_v2_v2v2fl(td->loc, td->iloc, val, td->factor);
- }
- }
+ 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];
+ char str[UI_MAX_DRAW_STR];
- snapSequenceBounds(t, mval);
+ 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, tvec);
- }
- else {
- // snapGridIncrement(t, t->values);
- applyNumInput(&t->num, t->values);
- }
+ 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, tvec);
+ }
+ else {
+ // snapGridIncrement(t, t->values);
+ applyNumInput(&t->num, t->values);
+ }
- t->values[0] = floorf(t->values[0] + 0.5f);
- t->values[1] = floorf(t->values[1] + 0.5f);
+ t->values[0] = floorf(t->values[0] + 0.5f);
+ t->values[1] = floorf(t->values[1] + 0.5f);
- headerSeqSlide(t, t->values, str);
- applySeqSlideValue(t, t->values);
+ headerSeqSlide(t, t->values, str);
+ applySeqSlideValue(t, t->values);
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Animation Editors - Transform Utils
*
@@ -8829,109 +9032,109 @@ static void applySeqSlide(TransInfo *t, const int mval[2])
// XXX these modifier checks should be keymappable
static short getAnimEdit_SnapMode(TransInfo *t)
{
- short autosnap = SACTSNAP_OFF;
+ short autosnap = SACTSNAP_OFF;
- if (t->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
+ 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 (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 (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;
- }
+ 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;
- }
+ /* 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;
+ 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)
-{
- /* snap key to nearest frame or second? */
- if (ELEM(autosnap, SACTSNAP_FRAME, SACTSNAP_SECOND)) {
- const Scene *scene = t->scene;
- const double secf = FPS;
- double 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);
-
- /* do the snapping to nearest frame/second */
- if (autosnap == SACTSNAP_FRAME) {
- val = floorf(val + 0.5);
- }
- else if (autosnap == SACTSNAP_SECOND) {
- val = (float)(floor((val / secf) + 0.5) * secf);
- }
-
- /* convert frame out of nla-action time */
- if (adt)
- *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP);
- else
- *(td->val) = val;
- }
- /* snap key to nearest marker? */
- else if (autosnap == 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);
-
- /* snap to nearest marker */
- // TODO: need some more careful checks for where data comes from
- val = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, 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;
- }
+static void doAnimEdit_SnapFrame(
+ TransInfo *t, TransData *td, TransData2D *td2d, AnimData *adt, short autosnap)
+{
+ /* snap key to nearest frame or second? */
+ if (ELEM(autosnap, SACTSNAP_FRAME, SACTSNAP_SECOND)) {
+ const Scene *scene = t->scene;
+ const double secf = FPS;
+ double 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);
+
+ /* do the snapping to nearest frame/second */
+ if (autosnap == SACTSNAP_FRAME) {
+ val = floorf(val + 0.5);
+ }
+ else if (autosnap == SACTSNAP_SECOND) {
+ val = (float)(floor((val / secf) + 0.5) * secf);
+ }
+
+ /* convert frame out of nla-action time */
+ if (adt)
+ *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP);
+ else
+ *(td->val) = val;
+ }
+ /* snap key to nearest marker? */
+ else if (autosnap == 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);
+
+ /* snap to nearest marker */
+ // TODO: need some more careful checks for where data comes from
+ val = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, 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) */
@@ -8940,164 +9143,165 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, TransData2D *td2d,
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;
- }
+ /* 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;
+ t->mode = TFM_TIME_TRANSLATE;
+ t->transform = applyTimeTranslate;
- initMouseInputMode(t, &t->mouse, INPUT_NONE);
+ 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;
+ /* 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;
+ /* 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;
+ 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 Scene *scene = t->scene;
- const short autosnap = getAnimEdit_SnapMode(t);
- const double secf = FPS;
- float val = t->values[0];
-
- /* apply snapping + frame->seconds conversions */
- if (autosnap == SACTSNAP_STEP) {
- /* frame step */
- val = floorf(val + 0.5f);
- }
- else if (autosnap == SACTSNAP_TSTEP) {
- /* second step */
- val = floorf((double)val / secf + 0.5);
- }
- else if (autosnap == SACTSNAP_SECOND) {
- /* nearest second */
- val = (float)((double)val / secf);
- }
-
- if (autosnap == SACTSNAP_FRAME)
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%d.00 (%.4f)", (int)val, val);
- else if (autosnap == SACTSNAP_SECOND)
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%d.00 sec (%.4f)", (int)val, val);
- else if (autosnap == SACTSNAP_TSTEP)
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f sec", val);
- else
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val);
- }
-
- ofs += BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("DeltaX: %s"), &tvec[0]);
-
- if (t->flag & T_PROP_EDIT_ALL) {
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
- }
+ 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 Scene *scene = t->scene;
+ const short autosnap = getAnimEdit_SnapMode(t);
+ const double secf = FPS;
+ float val = t->values[0];
+
+ /* apply snapping + frame->seconds conversions */
+ if (autosnap == SACTSNAP_STEP) {
+ /* frame step */
+ val = floorf(val + 0.5f);
+ }
+ else if (autosnap == SACTSNAP_TSTEP) {
+ /* second step */
+ val = floorf((double)val / secf + 0.5);
+ }
+ else if (autosnap == SACTSNAP_SECOND) {
+ /* nearest second */
+ val = (float)((double)val / secf);
+ }
+
+ if (autosnap == SACTSNAP_FRAME)
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%d.00 (%.4f)", (int)val, val);
+ else if (autosnap == SACTSNAP_SECOND)
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%d.00 sec (%.4f)", (int)val, val);
+ else if (autosnap == SACTSNAP_TSTEP)
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f sec", val);
+ else
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val);
+ }
+
+ ofs += BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("DeltaX: %s"), &tvec[0]);
+
+ if (t->flag & T_PROP_EDIT_ALL) {
+ ofs += BLI_snprintf(
+ str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
+ }
}
static void applyTimeTranslateValue(TransInfo *t)
{
- 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)
- */
- 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 = t->values[0];
-
- 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[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;
- }
-
- /* apply nearest snapping */
- doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap);
- }
- }
+ 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)
+ */
+ 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 = t->values[0];
+
+ 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[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;
+ }
+
+ /* 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];
+ 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]);
+ /* 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];
- }
+ /* 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[0] = t->vec[0];
- headerTimeTranslate(t, str);
+ /* handle numeric-input stuff */
+ t->vec[0] = t->values[0];
+ applyNumInput(&t->num, &t->vec[0]);
+ t->values[0] = t->vec[0];
+ headerTimeTranslate(t, str);
- applyTimeTranslateValue(t);
+ applyTimeTranslateValue(t);
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Animation Time Slide) */
@@ -9106,188 +9310,190 @@ static void applyTimeTranslate(TransInfo *t, const int mval[2])
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;
+ /* 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];
+ 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[0];
- float val;
+ 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[0];
+ float val;
- val = 2.0f * (cval - sval) / (maxx - minx);
- CLAMP(val, -1.0f, 1.0f);
+ 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(&tvec[0], NUM_STR_REP_LEN, "%.4f", val);
+ }
- BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("TimeSlide: %s"), &tvec[0]);
+ BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("TimeSlide: %s"), &tvec[0]);
}
static void applyTimeSlideValue(TransInfo *t, float sval)
{
- 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;
- float cvalf = t->values[0];
-
- saction->timeslide = cvalf;
- }
-
- /* 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;
- float cval = t->values[0];
-
- /* 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);
- }
- }
- }
- }
+ 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;
+ float cvalf = t->values[0];
+
+ saction->timeslide = cvalf;
+ }
+
+ /* 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;
+ float cval = t->values[0];
+
+ /* 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];
+ 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]);
+ /* 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[0] stores cval[0], which is the current mouse-pointer location (in frames) */
- // XXX Need to be able to repeat this
- /* t->values[0] = cval[0]; */ /* UNUSED (reset again later). */
+ /* t->values[0] stores cval[0], which is the current mouse-pointer location (in frames) */
+ // XXX Need to be able to repeat this
+ /* t->values[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[0] = (maxx - minx) * t->vec[0] / 2.0f + sval[0];
+ /* handle numeric-input stuff */
+ t->vec[0] = 2.0f * (cval[0] - sval[0]) / (maxx - minx);
+ applyNumInput(&t->num, &t->vec[0]);
+ t->values[0] = (maxx - minx) * t->vec[0] / 2.0f + sval[0];
- headerTimeSlide(t, sval[0], str);
- applyTimeSlideValue(t, sval[0]);
+ headerTimeSlide(t, sval[0], str);
+ applyTimeSlideValue(t, sval[0]);
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Animation Time Scale) */
@@ -9296,134 +9502,133 @@ static void applyTimeSlide(TransInfo *t, const int mval[2])
static void initTimeScale(TransInfo *t)
{
- float center[2];
+ 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;
- }
+ /* 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;
+ 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];
- }
+ /* 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);
+ /* force a reinit with the center2d used here */
+ initMouseInput(t, &t->mouse, center, t->mouse.imval, false);
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
- t->flag |= T_NULL_ONE;
- t->num.val_flag[0] |= NUM_NULL_ONE;
+ 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;
+ /* 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;
+ /* 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;
+ 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];
+ 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[0]);
+ if (hasNumInput(&t->num))
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
+ else
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", t->values[0]);
- BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("ScaleX: %s"), &tvec[0]);
+ BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("ScaleX: %s"), &tvec[0]);
}
static void applyTimeScaleValue(TransInfo *t)
{
- Scene *scene = t->scene;
- int i;
+ Scene *scene = t->scene;
+ int i;
- const short autosnap = getAnimEdit_SnapMode(t);
- const double secf = FPS;
+ 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 = t->values[0];
+ 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 = t->values[0];
- if (autosnap == SACTSNAP_TSTEP) {
- fac = (float)(floor((double)fac / secf + 0.5) * secf);
- }
- else if (autosnap == SACTSNAP_STEP) {
- fac = floorf(fac + 0.5f);
- }
+ 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;
+ /* 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);
+ /* 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;
+ /* now, calculate the new value */
+ *(td->val) = ((td->ival - startx) * fac) + startx;
- /* apply nearest snapping */
- doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap);
- }
- }
+ /* 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];
+ char str[UI_MAX_DRAW_STR];
- /* handle numeric-input stuff */
- t->vec[0] = t->values[0];
- applyNumInput(&t->num, &t->vec[0]);
- t->values[0] = t->vec[0];
- headerTimeScale(t, str);
+ /* handle numeric-input stuff */
+ t->vec[0] = t->values[0];
+ applyNumInput(&t->num, &t->vec[0]);
+ t->values[0] = t->vec[0];
+ headerTimeScale(t, str);
- applyTimeScaleValue(t);
+ applyTimeScaleValue(t);
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* TODO, move to: transform_query.c */
bool checkUseAxisMatrix(TransInfo *t)
{
- /* currently only checks for editmode */
- if (t->flag & T_EDIT) {
- if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
- (ELEM(t->obedit_type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE)))
- {
- /* not all editmode supports axis-matrix */
- return true;
- }
- }
-
- return false;
+ /* currently only checks for editmode */
+ if (t->flag & T_EDIT) {
+ if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
+ (ELEM(t->obedit_type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE))) {
+ /* not all editmode supports axis-matrix */
+ return true;
+ }
+ }
+
+ return false;
}
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 835346d9eee..6451d82e45c 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -21,7 +21,6 @@
* \ingroup edtransform
*/
-
#ifndef __TRANSFORM_H__
#define __TRANSFORM_H__
@@ -66,158 +65,170 @@ struct wmTimer;
/* transinfo->redraw */
typedef enum {
- TREDRAW_NOTHING = 0,
- TREDRAW_HARD = 1,
- TREDRAW_SOFT = 2,
+ TREDRAW_NOTHING = 0,
+ TREDRAW_HARD = 1,
+ TREDRAW_SOFT = 2,
} eRedrawFlag;
typedef struct TransSnapPoint {
- struct TransSnapPoint *next, *prev;
- float co[3];
+ struct TransSnapPoint *next, *prev;
+ float co[3];
} TransSnapPoint;
typedef struct TransSnap {
- short mode;
- short target;
- short modePoint;
- short modeSelect;
- bool align;
- bool project;
- bool snap_self;
- bool peel;
- bool snap_spatial_grid;
- short status;
- /** snapping from this point (in global-space). */
- float snapPoint[3];
- /** to this point (in global-space). */
- float snapTarget[3];
- float snapNormal[3];
- char snapNodeBorder;
- ListBase points;
- TransSnapPoint *selectedPoint;
- double last;
- void (*applySnap)(struct TransInfo *, float *);
- void (*calcSnap)(struct TransInfo *, float *);
- void (*targetSnap)(struct TransInfo *);
- /**
- * Get the transform distance between two points (used by Closest snap)
- *
- * \note Return value can be anything,
- * where the smallest absolute value defines whats closest.
- */
- float (*distance)(struct TransInfo *t, const float p1[3], const float p2[3]);
-
- /**
- * Re-usable snap context data.
- */
- struct SnapObjectContext *object_context;
+ short mode;
+ short target;
+ short modePoint;
+ short modeSelect;
+ bool align;
+ bool project;
+ bool snap_self;
+ bool peel;
+ bool snap_spatial_grid;
+ short status;
+ /** snapping from this point (in global-space). */
+ float snapPoint[3];
+ /** to this point (in global-space). */
+ float snapTarget[3];
+ float snapNormal[3];
+ char snapNodeBorder;
+ ListBase points;
+ TransSnapPoint *selectedPoint;
+ double last;
+ void (*applySnap)(struct TransInfo *, float *);
+ void (*calcSnap)(struct TransInfo *, float *);
+ void (*targetSnap)(struct TransInfo *);
+ /**
+ * Get the transform distance between two points (used by Closest snap)
+ *
+ * \note Return value can be anything,
+ * where the smallest absolute value defines whats closest.
+ */
+ float (*distance)(struct TransInfo *t, const float p1[3], const float p2[3]);
+
+ /**
+ * Re-usable snap context data.
+ */
+ struct SnapObjectContext *object_context;
} TransSnap;
typedef struct TransCon {
- short orientation;
- /** Description of the constraint for header_print. */
- char text[50];
- /** Matrix of the constraint space. */
- float mtx[3][3];
- /** Inverse matrix of the constraint space. */
- float imtx[3][3];
- /** Projection constraint matrix (same as #imtx with some axis == 0). */
- float pmtx[3][3];
- /** Initial mouse value for visual calculation
- * the one in #TransInfo is not guarantee to stay the same (Rotates change it). */
- int imval[2];
- /** Mode flags of the constraint. */
- int mode;
- void (*drawExtra)(struct TransInfo *t);
-
- /* Note: if 'tc' is NULL, 'td' must also be NULL.
- * For constraints that needs to draw differently from the other
- * uses this instead of the generic draw function. */
-
- /** Apply function pointer for linear vectorial transformation
- * The last three parameters are pointers to the in/out/printable vectors. */
- void (*applyVec)(struct TransInfo *t, struct TransDataContainer *tc, struct TransData *td, const float in[3], float out[3], float pvec[3]);
- /** Apply function pointer for size transformation. */
- void (*applySize)(struct TransInfo *t, struct TransDataContainer *tc, struct TransData *td, float smat[3][3]);
- /** Apply function pointer for rotation transformation */
- void (*applyRot)(struct TransInfo *t, struct TransDataContainer *tc, struct TransData *td, float vec[3], float *angle);
+ short orientation;
+ /** Description of the constraint for header_print. */
+ char text[50];
+ /** Matrix of the constraint space. */
+ float mtx[3][3];
+ /** Inverse matrix of the constraint space. */
+ float imtx[3][3];
+ /** Projection constraint matrix (same as #imtx with some axis == 0). */
+ float pmtx[3][3];
+ /** Initial mouse value for visual calculation
+ * the one in #TransInfo is not guarantee to stay the same (Rotates change it). */
+ int imval[2];
+ /** Mode flags of the constraint. */
+ int mode;
+ void (*drawExtra)(struct TransInfo *t);
+
+ /* Note: if 'tc' is NULL, 'td' must also be NULL.
+ * For constraints that needs to draw differently from the other
+ * uses this instead of the generic draw function. */
+
+ /** Apply function pointer for linear vectorial transformation
+ * The last three parameters are pointers to the in/out/printable vectors. */
+ void (*applyVec)(struct TransInfo *t,
+ struct TransDataContainer *tc,
+ struct TransData *td,
+ const float in[3],
+ float out[3],
+ float pvec[3]);
+ /** Apply function pointer for size transformation. */
+ void (*applySize)(struct TransInfo *t,
+ struct TransDataContainer *tc,
+ struct TransData *td,
+ float smat[3][3]);
+ /** Apply function pointer for rotation transformation */
+ void (*applyRot)(struct TransInfo *t,
+ struct TransDataContainer *tc,
+ struct TransData *td,
+ float vec[3],
+ float *angle);
} TransCon;
typedef struct TransDataExtension {
- /** Initial object drot. */
- float drot[3];
- // /* Initial object drotAngle, TODO: not yet implemented */
- // float drotAngle;
- // /* Initial object drotAxis, TODO: not yet implemented */
- // float drotAxis[3];
- /** Initial object delta quat. */
- float dquat[4];
- /** Initial object delta scale. */
- float dscale[3];
- /** Rotation of the data to transform. */
- float *rot;
- /** Initial rotation. */
- float irot[3];
- /** Rotation quaternion of the data to transform. */
- float *quat;
- /** Initial rotation quaternion. */
- float iquat[4];
- /** Rotation angle of the data to transform. */
- float *rotAngle;
- /** Initial rotation angle. */
- float irotAngle;
- /** Rotation axis of the data to transform. */
- float *rotAxis;
- /** Initial rotation axis. */
- float irotAxis[4];
- /** Size of the data to transform. */
- float *size;
- /** Initial size. */
- float isize[3];
- /** Object matrix. */
- float obmat[4][4];
- /** Use instead of #TransData.smtx,
- * It is the same but without the #Bone.bone_mat, see #TD_PBONE_LOCAL_MTX_C. */
- float l_smtx[3][3];
- /** The rotscale matrix of pose bone, to allow using snap-align in translation mode,
- * when td->mtx is the loc pose bone matrix (and hence can't be used to apply
- * rotation in some cases, namely when a bone is in "NoLocal" or "Hinge" mode)... */
- float r_mtx[3][3];
- /** Inverse of previous one. */
- float r_smtx[3][3];
- /** Rotation mode, as defined in #eRotationModes (DNA_action_types.h). */
- int rotOrder;
- /** Original object transformation used for rigid bodies. */
- float oloc[3], orot[3], oquat[4], orotAxis[3], orotAngle;
+ /** Initial object drot. */
+ float drot[3];
+ // /* Initial object drotAngle, TODO: not yet implemented */
+ // float drotAngle;
+ // /* Initial object drotAxis, TODO: not yet implemented */
+ // float drotAxis[3];
+ /** Initial object delta quat. */
+ float dquat[4];
+ /** Initial object delta scale. */
+ float dscale[3];
+ /** Rotation of the data to transform. */
+ float *rot;
+ /** Initial rotation. */
+ float irot[3];
+ /** Rotation quaternion of the data to transform. */
+ float *quat;
+ /** Initial rotation quaternion. */
+ float iquat[4];
+ /** Rotation angle of the data to transform. */
+ float *rotAngle;
+ /** Initial rotation angle. */
+ float irotAngle;
+ /** Rotation axis of the data to transform. */
+ float *rotAxis;
+ /** Initial rotation axis. */
+ float irotAxis[4];
+ /** Size of the data to transform. */
+ float *size;
+ /** Initial size. */
+ float isize[3];
+ /** Object matrix. */
+ float obmat[4][4];
+ /** Use instead of #TransData.smtx,
+ * It is the same but without the #Bone.bone_mat, see #TD_PBONE_LOCAL_MTX_C. */
+ float l_smtx[3][3];
+ /** The rotscale matrix of pose bone, to allow using snap-align in translation mode,
+ * when td->mtx is the loc pose bone matrix (and hence can't be used to apply
+ * rotation in some cases, namely when a bone is in "NoLocal" or "Hinge" mode)... */
+ float r_mtx[3][3];
+ /** Inverse of previous one. */
+ float r_smtx[3][3];
+ /** Rotation mode, as defined in #eRotationModes (DNA_action_types.h). */
+ int rotOrder;
+ /** Original object transformation used for rigid bodies. */
+ float oloc[3], orot[3], oquat[4], orotAxis[3], orotAngle;
} TransDataExtension;
typedef struct TransData2D {
- /** Location of data used to transform (x,y,0). */
- float loc[3];
- /** Pointer to real 2d location of data. */
- float *loc2d;
-
- /** Pointer to handle locations, if handles aren't being moved independently. */
- float *h1, *h2;
- float ih1[2], ih2[2];
+ /** Location of data used to transform (x,y,0). */
+ float loc[3];
+ /** Pointer to real 2d location of data. */
+ float *loc2d;
+
+ /** Pointer to handle locations, if handles aren't being moved independently. */
+ float *h1, *h2;
+ float ih1[2], ih2[2];
} TransData2D;
/** Used to store 2 handles for each #TransData in case the other handle wasn't selected. */
typedef struct TransDataCurveHandleFlags {
- char ih1, ih2;
- char *h1, *h2;
+ char ih1, ih2;
+ char *h1, *h2;
} TransDataCurveHandleFlags;
/** Used for sequencer transform. */
typedef struct TransDataSeq {
- struct Sequence *seq;
- /** A copy of #Sequence.flag that may be modified for nested strips. */
- int flag;
- /** Use this so we can have transform data at the strips start,
- * but apply correctly to the start frame. */
- int start_offset;
- /** one of #SELECT, #SEQ_LEFTSEL and #SEQ_RIGHTSEL. */
- short sel_flag;
+ struct Sequence *seq;
+ /** A copy of #Sequence.flag that may be modified for nested strips. */
+ int flag;
+ /** Use this so we can have transform data at the strips start,
+ * but apply correctly to the start frame. */
+ int start_offset;
+ /** one of #SELECT, #SEQ_LEFTSEL and #SEQ_RIGHTSEL. */
+ short sel_flag;
} TransDataSeq;
@@ -225,35 +236,35 @@ typedef struct TransDataSeq {
* Sequencer transform customdata (stored in #TransCustomDataContainer).
*/
typedef struct TransSeq {
- TransDataSeq *tdseq;
- int min;
- int max;
- bool snap_left;
+ TransDataSeq *tdseq;
+ int min;
+ int max;
+ bool snap_left;
} TransSeq;
/** Used for NLA transform (stored in #TransData.extra pointer). */
typedef struct TransDataNla {
- /** ID-block NLA-data is attached to. */
- ID *id;
-
- /** Original NLA-Track that the strip belongs to. */
- struct NlaTrack *oldTrack;
- /** Current NLA-Track that the strip belongs to. */
- struct NlaTrack *nlt;
-
- /** NLA-strip this data represents. */
- struct NlaStrip *strip;
-
- /* dummy values for transform to write in - must have 3 elements... */
- /** start handle. */
- float h1[3];
- /** end handle. */
- float h2[3];
-
- /** index of track that strip is currently in. */
- int trackIndex;
- /** handle-index: 0 for dummy entry, -1 for start, 1 for end, 2 for both ends. */
- int handle;
+ /** ID-block NLA-data is attached to. */
+ ID *id;
+
+ /** Original NLA-Track that the strip belongs to. */
+ struct NlaTrack *oldTrack;
+ /** Current NLA-Track that the strip belongs to. */
+ struct NlaTrack *nlt;
+
+ /** NLA-strip this data represents. */
+ struct NlaStrip *strip;
+
+ /* dummy values for transform to write in - must have 3 elements... */
+ /** start handle. */
+ float h1[3];
+ /** end handle. */
+ float h2[3];
+
+ /** index of track that strip is currently in. */
+ int trackIndex;
+ /** handle-index: 0 for dummy entry, -1 for start, 1 for end, 2 for both ends. */
+ int handle;
} TransDataNla;
struct GHash;
@@ -261,197 +272,197 @@ struct LinkNode;
/* header of TransDataEdgeSlideVert, TransDataEdgeSlideEdge */
typedef struct TransDataGenericSlideVert {
- struct BMVert *v;
- struct LinkNode **cd_loop_groups;
- float co_orig_3d[3];
+ 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 */
+ /** #TransDataGenericSlideVert (header) */
+ struct BMVert *v;
+ struct LinkNode **cd_loop_groups;
+ float v_co_orig[3];
+ /* end generic */
- float edge_len;
+ float edge_len;
- struct BMVert *v_side[2];
+ struct BMVert *v_side[2];
- /* add origvert.co to get the original locations */
- float dir_side[2][3];
+ /* add origvert.co to get the original locations */
+ float dir_side[2][3];
- int loop_nr;
+ int loop_nr;
} TransDataEdgeSlideVert;
-
/* store original data so we can correct UV's and similar when sliding */
typedef struct SlideOrigData {
- /** Set when #origfaces is initialized. */
- bool use_origfaces;
- int cd_loop_mdisp_offset;
-
- /** map {BMVert: TransDataGenericSlideVert} */
- struct GHash *origverts;
- struct GHash *origfaces;
- struct BMesh *bm_origfaces;
-
- struct MemArena *arena;
- /** Number of math BMLoop layers. */
- int layer_math_map_num;
- /** Array size of 'layer_math_map_num'
- * maps TransDataVertSlideVert.cd_group index to absolute CustomData layer index */
- int *layer_math_map;
-
- /** Array of slide vert data especially for mirror verts. */
- TransDataGenericSlideVert *sv_mirror;
- int totsv_mirror;
+ /** Set when #origfaces is initialized. */
+ bool use_origfaces;
+ int cd_loop_mdisp_offset;
+
+ /** map {BMVert: TransDataGenericSlideVert} */
+ struct GHash *origverts;
+ struct GHash *origfaces;
+ struct BMesh *bm_origfaces;
+
+ struct MemArena *arena;
+ /** Number of math BMLoop layers. */
+ int layer_math_map_num;
+ /** Array size of 'layer_math_map_num'
+ * maps TransDataVertSlideVert.cd_group index to absolute CustomData layer index */
+ int *layer_math_map;
+
+ /** Array of slide vert data especially for mirror verts. */
+ TransDataGenericSlideVert *sv_mirror;
+ int totsv_mirror;
} SlideOrigData;
typedef struct EdgeSlideData {
- TransDataEdgeSlideVert *sv;
- int totsv;
+ TransDataEdgeSlideVert *sv;
+ int totsv;
- int mval_start[2], mval_end[2];
- struct BMEditMesh *em;
+ int mval_start[2], mval_end[2];
+ struct BMEditMesh *em;
- SlideOrigData orig_data;
+ SlideOrigData orig_data;
+ int curr_sv_index;
- int curr_sv_index;
-
- /** when un-clamped - use this index: #TransDataEdgeSlideVert.dir_side */
- int curr_side_unclamp;
+ /** when un-clamped - use this index: #TransDataEdgeSlideVert.dir_side */
+ int curr_side_unclamp;
} EdgeSlideData;
typedef struct EdgeSlideParams {
- float perc;
+ float perc;
- bool use_even;
- bool flipped;
+ 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;
+ /** #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;
+ TransDataVertSlideVert *sv;
+ int totsv;
- struct BMEditMesh *em;
+ struct BMEditMesh *em;
- SlideOrigData orig_data;
+ SlideOrigData orig_data;
- int curr_sv_index;
+ int curr_sv_index;
- /* result of ED_view3d_ob_project_mat_get */
- float proj_mat[4][4];
+ /* result of ED_view3d_ob_project_mat_get */
+ float proj_mat[4][4];
} VertSlideData;
typedef struct VertSlideParams {
- float perc;
+ float perc;
- bool use_even;
- bool flipped;
+ bool use_even;
+ bool flipped;
} VertSlideParams;
typedef struct BoneInitData {
- struct EditBone *bone;
- float tail[3];
- float rad_tail;
- float roll;
- float head[3];
- float dist;
- float xwidth;
- float zwidth;
+ struct EditBone *bone;
+ float tail[3];
+ float rad_tail;
+ float roll;
+ float head[3];
+ float dist;
+ float xwidth;
+ float zwidth;
} BoneInitData;
typedef struct TransData {
- /** Distance needed to affect element (for Proportionnal Editing). */
- float dist;
- /** Distance to the nearest element (for Proportionnal Editing). */
- float rdist;
- /** Factor of the transformation (for Proportionnal Editing). */
- float factor;
- /** Location of the data to transform. */
- float *loc;
- /** Initial location. */
- float iloc[3];
- /** Value pointer for special transforms. */
- float *val;
- /** Old value. */
- float ival;
- /** Individual data center. */
- float center[3];
- /** Transformation matrix from data space to global space. */
- float mtx[3][3];
- /** Transformation matrix from global space to data space. */
- float smtx[3][3];
- /** Axis orientation matrix of the data. */
- float axismtx[3][3];
- struct Object *ob;
- /** For objects/bones, the first constraint in its constraint stack. */
- struct bConstraint *con;
- /** For objects, poses. 1 single malloc per TransInfo! */
- TransDataExtension *ext;
- /** for curves, stores handle flags for modification/cancel. */
- TransDataCurveHandleFlags *hdata;
- /**
- * Extra data (mirrored element pointer, in editmode mesh to BMVert)
- * (editbone for roll fixing) (...).
- */
- void *extra;
- /** Various flags. */
- int flag;
- /** If set, copy of Object or PoseChannel protection. */
- short protectflag;
+ /** Distance needed to affect element (for Proportionnal Editing). */
+ float dist;
+ /** Distance to the nearest element (for Proportionnal Editing). */
+ float rdist;
+ /** Factor of the transformation (for Proportionnal Editing). */
+ float factor;
+ /** Location of the data to transform. */
+ float *loc;
+ /** Initial location. */
+ float iloc[3];
+ /** Value pointer for special transforms. */
+ float *val;
+ /** Old value. */
+ float ival;
+ /** Individual data center. */
+ float center[3];
+ /** Transformation matrix from data space to global space. */
+ float mtx[3][3];
+ /** Transformation matrix from global space to data space. */
+ float smtx[3][3];
+ /** Axis orientation matrix of the data. */
+ float axismtx[3][3];
+ struct Object *ob;
+ /** For objects/bones, the first constraint in its constraint stack. */
+ struct bConstraint *con;
+ /** For objects, poses. 1 single malloc per TransInfo! */
+ TransDataExtension *ext;
+ /** for curves, stores handle flags for modification/cancel. */
+ TransDataCurveHandleFlags *hdata;
+ /**
+ * Extra data (mirrored element pointer, in editmode mesh to BMVert)
+ * (editbone for roll fixing) (...).
+ */
+ void *extra;
+ /** Various flags. */
+ int flag;
+ /** If set, copy of Object or PoseChannel protection. */
+ short protectflag;
} TransData;
typedef struct MouseInput {
- void (*apply)(struct TransInfo *t, struct MouseInput *mi, const double mval[2], float output[3]);
- void (*post)(struct TransInfo *t, float values[3]);
-
- /** Initial mouse position. */
- int imval[2];
- bool precision;
- float precision_factor;
- float center[2];
- float factor;
- /** Additional data, if needed by the particular function. */
- void *data;
-
- /**
- * Use virtual cursor, which takes precision into account
- * keeping track of the cursors 'virtual' location,
- * to avoid jumping values when its toggled.
- *
- * This works well for scaling drag motion,
- * but not for rotating around a point (rotaton needs its own custom accumulator)
- */
- bool use_virtual_mval;
- struct {
- double prev[2];
- double accum[2];
- } virtual_mval;
+ void (*apply)(struct TransInfo *t, struct MouseInput *mi, const double mval[2], float output[3]);
+ void (*post)(struct TransInfo *t, float values[3]);
+
+ /** Initial mouse position. */
+ int imval[2];
+ bool precision;
+ float precision_factor;
+ float center[2];
+ float factor;
+ /** Additional data, if needed by the particular function. */
+ void *data;
+
+ /**
+ * Use virtual cursor, which takes precision into account
+ * keeping track of the cursors 'virtual' location,
+ * to avoid jumping values when its toggled.
+ *
+ * This works well for scaling drag motion,
+ * but not for rotating around a point (rotaton needs its own custom accumulator)
+ */
+ bool use_virtual_mval;
+ struct {
+ double prev[2];
+ double accum[2];
+ } virtual_mval;
} MouseInput;
typedef struct TransCustomData {
- void *data;
- void (*free_cb)(struct TransInfo *, struct TransDataContainer *tc, struct TransCustomData *custom_data);
- unsigned int use_free : 1;
+ void *data;
+ void (*free_cb)(struct TransInfo *,
+ struct TransDataContainer *tc,
+ struct TransCustomData *custom_data);
+ unsigned int use_free : 1;
} TransCustomData;
typedef struct TransCenterData {
- float global[3];
- unsigned int is_set : 1;
+ float global[3];
+ unsigned int is_set : 1;
} TransCenterData;
/**
@@ -462,304 +473,303 @@ typedef struct TransCenterData {
* (typically in transform_conversion.c).
*/
typedef struct TransCustomDataContainer {
- /** Owned by the mode (grab, scale, bend... ).*/
- union {
- TransCustomData mode, first_elem;
- };
- TransCustomData type;
+ /** Owned by the mode (grab, scale, bend... ).*/
+ union {
+ TransCustomData mode, first_elem;
+ };
+ TransCustomData type;
} TransCustomDataContainer;
#define TRANS_CUSTOM_DATA_ELEM_MAX (sizeof(TransCustomDataContainer) / sizeof(TransCustomData))
typedef struct TransDataContainer {
- /**
- * Use for cases we care about the active, eg: active vert of active mesh.
- * if set this will _always_ be the first item in the array.
- */
- bool is_active;
-
- /** Transformed data (array). */
- TransData *data;
- /** Total number of transformed data. */
- int data_len;
-
- /** Transformed data extension (array). */
- TransDataExtension *data_ext;
- /** Transformed data for 2d (array). */
- TransData2D *data_2d;
-
- struct Object *obedit;
-
- /**
- * Use when #T_LOCAL_MATRIX is set.
- * Typically: 'obedit->obmat' or 'poseobj->obmat', but may be used elsewhere too.
- */
- bool use_local_mat;
- float mat[4][4];
- float imat[4][4];
- /** 3x3 copies of matrices above. */
- float mat3[3][3];
- float imat3[3][3];
-
- /** Normalized 'mat3' */
- float mat3_unit[3][3];
-
- /** if 't->flag & T_POSE', this denotes pose object */
- struct Object *poseobj;
-
- /** Center of transformation (in local-space), Calculated from #TransInfo.center_global. */
- float center_local[3];
-
- /**
- * Mirror option
- */
- struct {
- /* Currently for mesh X mirror only. */
- int axis_flag;
- /** Set to -1.0f or 1.0 when use_mirror is set. */
- float sign;
- } mirror;
-
- TransCustomDataContainer custom;
+ /**
+ * Use for cases we care about the active, eg: active vert of active mesh.
+ * if set this will _always_ be the first item in the array.
+ */
+ bool is_active;
+
+ /** Transformed data (array). */
+ TransData *data;
+ /** Total number of transformed data. */
+ int data_len;
+
+ /** Transformed data extension (array). */
+ TransDataExtension *data_ext;
+ /** Transformed data for 2d (array). */
+ TransData2D *data_2d;
+
+ struct Object *obedit;
+
+ /**
+ * Use when #T_LOCAL_MATRIX is set.
+ * Typically: 'obedit->obmat' or 'poseobj->obmat', but may be used elsewhere too.
+ */
+ bool use_local_mat;
+ float mat[4][4];
+ float imat[4][4];
+ /** 3x3 copies of matrices above. */
+ float mat3[3][3];
+ float imat3[3][3];
+
+ /** Normalized 'mat3' */
+ float mat3_unit[3][3];
+
+ /** if 't->flag & T_POSE', this denotes pose object */
+ struct Object *poseobj;
+
+ /** Center of transformation (in local-space), Calculated from #TransInfo.center_global. */
+ float center_local[3];
+
+ /**
+ * Mirror option
+ */
+ struct {
+ /* Currently for mesh X mirror only. */
+ int axis_flag;
+ /** Set to -1.0f or 1.0 when use_mirror is set. */
+ float sign;
+ } mirror;
+
+ TransCustomDataContainer custom;
} TransDataContainer;
typedef struct TransInfo {
- TransDataContainer *data_container;
- int data_container_len;
- /** Combine length of all #TransDataContainer.data_len
- * Use to check if nothing is selected or if we have a single selection. */
- int data_len_all;
-
- /** Current mode. */
- int mode;
- /** Generic flags for special behaviors. */
- int flag;
- /** Special modifiers, by function, not key. */
- int modifiers;
- /** Current state (running, canceled. */
- short state;
- /** Current context/options for transform. */
- int options;
- /** Init value for some transformations (and rotation angle). */
- float val;
- void (*transform)(struct TransInfo *, const int[2]);
- /** Transform function pointer. */
- eRedrawFlag (*handleEvent)(struct TransInfo *, const struct wmEvent *);
- /* event handler function pointer RETURN 1 if redraw is needed */
- /** transformed constraint. */
- TransCon con;
- TransSnap tsnap;
- /** numerical input. */
- NumInput num;
- /** mouse input. */
- MouseInput mouse;
- /** redraw flag. */
- eRedrawFlag redraw;
- /** proportional circle radius. */
- float prop_size;
- /** proportional falloff text. */
- char proptext[20];
- /**
- * Spaces using non 1:1 aspect, (uv's, f-curve, movie-clip... etc)
- * use for conversion and snapping.
- */
- float aspect[3];
- /** center of transformation (in global-space) */
- float center_global[3];
- /** center in screen coordinates. */
- float center2d[2];
- /* Lazy initialize center data for when we need other center values.
- * V3D_AROUND_ACTIVE + 1 (static assert checks this) */
- TransCenterData center_cache[5];
- /** maximum index on the input vector. */
- short idx_max;
- /** Snapping Gears. */
- float snap[3];
- /** Spatial snapping gears(even when rotating, scaling... etc). */
- float snap_spatial[3];
- /** Mouse side of the cfra, 'L', 'R' or 'B' */
- char frame_side;
-
- /** copy from G.vd, prevents feedback. */
- float viewmat[4][4];
- /** and to make sure we don't have to. */
- float viewinv[4][4];
- /** access G.vd from other space types. */
- float persmat[4][4];
- float persinv[4][4];
- short persp;
- short around;
- /** spacetype where transforming is. */
- char spacetype;
- /** Choice of custom cursor with or without a help line from the gizmo to the mouse position. */
- char helpline;
- /** Avoid looking inside TransDataContainer obedit. */
- short obedit_type;
-
- /** translation, to show for widget. */
- float vec[3];
- /** rot/rescale, to show for widget. */
- float mat[3][3];
-
- /** orientation matrix of the current space. */
- float spacemtx[3][3];
- /** name of the current space, MAX_NAME. */
- char spacename[64];
-
- /*************** NEW STUFF *********************/
- /** event type used to launch transform. */
- short launch_event;
-
- 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 */
- TransformOrientation *custom;
- } orientation;
- /** backup from view3d, to restore on end. */
- short gizmo_flag;
-
- short prop_mode;
-
- float values[4];
- /** Offset applied ontop of modal input. */
- float values_modal_offset[4];
- float auto_values[4];
-
- /* Axis members for modes that use an axis separate from the orientation (rotate & shear). */
-
- /** Primary axis, rotate only uses this. */
- int orient_axis;
- /** 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 Depsgraph *depsgraph;
- struct Scene *scene;
- struct ViewLayer *view_layer;
- struct ToolSettings *settings;
- struct wmTimer *animtimer;
- /** so we can do lookups for header text. */
- struct wmKeyMap *keymap;
- /** assign from the operator, or can be NULL. */
- struct ReportList *reports;
- /** current mouse position. */
- int mval[2];
- /** use for 3d view. */
- float zfac;
- void *draw_handle_apply;
- void *draw_handle_view;
- void *draw_handle_pixel;
- void *draw_handle_cursor;
-
- /** Currently only used for random curve of proportional editing. */
- struct RNG *rng;
-
- /** Typically for mode settings. */
- TransCustomDataContainer custom;
+ TransDataContainer *data_container;
+ int data_container_len;
+ /** Combine length of all #TransDataContainer.data_len
+ * Use to check if nothing is selected or if we have a single selection. */
+ int data_len_all;
+
+ /** Current mode. */
+ int mode;
+ /** Generic flags for special behaviors. */
+ int flag;
+ /** Special modifiers, by function, not key. */
+ int modifiers;
+ /** Current state (running, canceled. */
+ short state;
+ /** Current context/options for transform. */
+ int options;
+ /** Init value for some transformations (and rotation angle). */
+ float val;
+ void (*transform)(struct TransInfo *, const int[2]);
+ /** Transform function pointer. */
+ eRedrawFlag (*handleEvent)(struct TransInfo *, const struct wmEvent *);
+ /* event handler function pointer RETURN 1 if redraw is needed */
+ /** transformed constraint. */
+ TransCon con;
+ TransSnap tsnap;
+ /** numerical input. */
+ NumInput num;
+ /** mouse input. */
+ MouseInput mouse;
+ /** redraw flag. */
+ eRedrawFlag redraw;
+ /** proportional circle radius. */
+ float prop_size;
+ /** proportional falloff text. */
+ char proptext[20];
+ /**
+ * Spaces using non 1:1 aspect, (uv's, f-curve, movie-clip... etc)
+ * use for conversion and snapping.
+ */
+ float aspect[3];
+ /** center of transformation (in global-space) */
+ float center_global[3];
+ /** center in screen coordinates. */
+ float center2d[2];
+ /* Lazy initialize center data for when we need other center values.
+ * V3D_AROUND_ACTIVE + 1 (static assert checks this) */
+ TransCenterData center_cache[5];
+ /** maximum index on the input vector. */
+ short idx_max;
+ /** Snapping Gears. */
+ float snap[3];
+ /** Spatial snapping gears(even when rotating, scaling... etc). */
+ float snap_spatial[3];
+ /** Mouse side of the cfra, 'L', 'R' or 'B' */
+ char frame_side;
+
+ /** copy from G.vd, prevents feedback. */
+ float viewmat[4][4];
+ /** and to make sure we don't have to. */
+ float viewinv[4][4];
+ /** access G.vd from other space types. */
+ float persmat[4][4];
+ float persinv[4][4];
+ short persp;
+ short around;
+ /** spacetype where transforming is. */
+ char spacetype;
+ /** Choice of custom cursor with or without a help line from the gizmo to the mouse position. */
+ char helpline;
+ /** Avoid looking inside TransDataContainer obedit. */
+ short obedit_type;
+
+ /** translation, to show for widget. */
+ float vec[3];
+ /** rot/rescale, to show for widget. */
+ float mat[3][3];
+
+ /** orientation matrix of the current space. */
+ float spacemtx[3][3];
+ /** name of the current space, MAX_NAME. */
+ char spacename[64];
+
+ /*************** NEW STUFF *********************/
+ /** event type used to launch transform. */
+ short launch_event;
+
+ 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 */
+ TransformOrientation *custom;
+ } orientation;
+ /** backup from view3d, to restore on end. */
+ short gizmo_flag;
+
+ short prop_mode;
+
+ float values[4];
+ /** Offset applied ontop of modal input. */
+ float values_modal_offset[4];
+ float auto_values[4];
+
+ /* Axis members for modes that use an axis separate from the orientation (rotate & shear). */
+
+ /** Primary axis, rotate only uses this. */
+ int orient_axis;
+ /** 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 Depsgraph *depsgraph;
+ struct Scene *scene;
+ struct ViewLayer *view_layer;
+ struct ToolSettings *settings;
+ struct wmTimer *animtimer;
+ /** so we can do lookups for header text. */
+ struct wmKeyMap *keymap;
+ /** assign from the operator, or can be NULL. */
+ struct ReportList *reports;
+ /** current mouse position. */
+ int mval[2];
+ /** use for 3d view. */
+ float zfac;
+ void *draw_handle_apply;
+ void *draw_handle_view;
+ void *draw_handle_pixel;
+ void *draw_handle_cursor;
+
+ /** Currently only used for random curve of proportional editing. */
+ struct RNG *rng;
+
+ /** Typically for mode settings. */
+ TransCustomDataContainer custom;
} TransInfo;
-
/* ******************** Macros & Prototypes *********************** */
/* transinfo->state */
enum {
- TRANS_STARTING = 0,
- TRANS_RUNNING = 1,
- TRANS_CONFIRM = 2,
- TRANS_CANCEL = 3,
+ TRANS_STARTING = 0,
+ TRANS_RUNNING = 1,
+ TRANS_CONFIRM = 2,
+ TRANS_CANCEL = 3,
};
/* transinfo->flag */
enum {
- T_OBJECT = 1 << 0,
- /** \note We could remove 'T_EDIT' and use 'obedit_type', for now ensure they're in sync. */
- T_EDIT = 1 << 1,
- T_POSE = 1 << 2,
- T_TEXTURE = 1 << 3,
- /** Transforming the camera while in camera view. */
- T_CAMERA = 1 << 4,
- /** Transforming the 3D cursor. */
- T_CURSOR = 1 << 5,
- /** Transform points, having no rotation/scale. */
- T_POINTS = 1 << 6,
- /**
- * Apply matrix #TransDataContainer.matrix, this avoids having to have duplicate check all over
- * that happen to apply to specific modes (edit & pose for eg). */
- T_LOCAL_MATRIX = 1 << 7,
-
- /** restrictions flags */
- T_NO_CONSTRAINT = 1 << 8,
- T_NULL_ONE = 1 << 9,
- T_NO_ZERO = 1 << 10,
- T_ALL_RESTRICTIONS = T_NO_CONSTRAINT | T_NULL_ONE | T_NO_ZERO,
-
- T_PROP_EDIT = 1 << 11,
- T_PROP_CONNECTED = 1 << 12,
- T_PROP_PROJECTED = 1 << 13,
- T_PROP_EDIT_ALL = T_PROP_EDIT | T_PROP_CONNECTED | T_PROP_PROJECTED,
-
- T_V3D_ALIGN = 1 << 14,
- /** For 2d views like uv or fcurve. */
- T_2D_EDIT = 1 << 15,
- T_CLIP_UV = 1 << 16,
-
- /** Auto-ik is on. */
- T_AUTOIK = 1 << 18,
-
- /** Don't use mirror even if the data-block option is set. */
- T_NO_MIRROR = 1 << 19,
-
- T_AUTOVALUES = 1 << 20,
-
- /** To specify if we save back settings at the end. */
- T_MODAL = 1 << 21,
-
- /** No retopo. */
- T_NO_PROJECT = 1 << 22,
-
- T_RELEASE_CONFIRM = 1 << 23,
-
- /** Alternative transformation. used to add offset to tracking markers. */
- T_ALT_TRANSFORM = 1 << 24,
-
- /** #TransInfo.center has been set, don't change it. */
- T_OVERRIDE_CENTER = 1 << 25,
-
- T_MODAL_CURSOR_SET = 1 << 26,
-
- T_CLNOR_REBUILD = 1 << 27,
+ T_OBJECT = 1 << 0,
+ /** \note We could remove 'T_EDIT' and use 'obedit_type', for now ensure they're in sync. */
+ T_EDIT = 1 << 1,
+ T_POSE = 1 << 2,
+ T_TEXTURE = 1 << 3,
+ /** Transforming the camera while in camera view. */
+ T_CAMERA = 1 << 4,
+ /** Transforming the 3D cursor. */
+ T_CURSOR = 1 << 5,
+ /** Transform points, having no rotation/scale. */
+ T_POINTS = 1 << 6,
+ /**
+ * Apply matrix #TransDataContainer.matrix, this avoids having to have duplicate check all over
+ * that happen to apply to specific modes (edit & pose for eg). */
+ T_LOCAL_MATRIX = 1 << 7,
+
+ /** restrictions flags */
+ T_NO_CONSTRAINT = 1 << 8,
+ T_NULL_ONE = 1 << 9,
+ T_NO_ZERO = 1 << 10,
+ T_ALL_RESTRICTIONS = T_NO_CONSTRAINT | T_NULL_ONE | T_NO_ZERO,
+
+ T_PROP_EDIT = 1 << 11,
+ T_PROP_CONNECTED = 1 << 12,
+ T_PROP_PROJECTED = 1 << 13,
+ T_PROP_EDIT_ALL = T_PROP_EDIT | T_PROP_CONNECTED | T_PROP_PROJECTED,
+
+ T_V3D_ALIGN = 1 << 14,
+ /** For 2d views like uv or fcurve. */
+ T_2D_EDIT = 1 << 15,
+ T_CLIP_UV = 1 << 16,
+
+ /** Auto-ik is on. */
+ T_AUTOIK = 1 << 18,
+
+ /** Don't use mirror even if the data-block option is set. */
+ T_NO_MIRROR = 1 << 19,
+
+ T_AUTOVALUES = 1 << 20,
+
+ /** To specify if we save back settings at the end. */
+ T_MODAL = 1 << 21,
+
+ /** No retopo. */
+ T_NO_PROJECT = 1 << 22,
+
+ T_RELEASE_CONFIRM = 1 << 23,
+
+ /** Alternative transformation. used to add offset to tracking markers. */
+ T_ALT_TRANSFORM = 1 << 24,
+
+ /** #TransInfo.center has been set, don't change it. */
+ T_OVERRIDE_CENTER = 1 << 25,
+
+ T_MODAL_CURSOR_SET = 1 << 26,
+
+ T_CLNOR_REBUILD = 1 << 27,
};
/** #TransInfo.modifiers */
enum {
- MOD_CONSTRAINT_SELECT = 1 << 0,
- MOD_PRECISION = 1 << 1,
- MOD_SNAP = 1 << 2,
- MOD_SNAP_INVERT = 1 << 3,
- MOD_CONSTRAINT_PLANE = 1 << 4,
+ MOD_CONSTRAINT_SELECT = 1 << 0,
+ MOD_PRECISION = 1 << 1,
+ MOD_SNAP = 1 << 2,
+ MOD_SNAP_INVERT = 1 << 3,
+ MOD_CONSTRAINT_PLANE = 1 << 4,
};
/* use node center for transform instead of upper-left corner.
@@ -767,87 +777,90 @@ enum {
*/
// #define USE_NODE_CENTER
-
/* ******************************************************************************** */
/** #TransInfo.helpline */
enum {
- HLP_NONE = 0,
- HLP_SPRING = 1,
- HLP_ANGLE = 2,
- HLP_HARROW = 3,
- HLP_VARROW = 4,
- HLP_CARROW = 5,
- HLP_TRACKBALL = 6,
+ HLP_NONE = 0,
+ HLP_SPRING = 1,
+ HLP_ANGLE = 2,
+ HLP_HARROW = 3,
+ HLP_VARROW = 4,
+ HLP_CARROW = 5,
+ HLP_TRACKBALL = 6,
};
/** #TransCon.mode, #TransInfo.con.mode */
enum {
- /** When set constraints are in use. */
- CON_APPLY = 1 << 0,
- /** These are only used for modal execution. */
- CON_AXIS0 = 1 << 1,
- CON_AXIS1 = 1 << 2,
- CON_AXIS2 = 1 << 3,
- CON_SELECT = 1 << 4,
- /** Does not reorient vector to face viewport when on. */
- CON_NOFLIP = 1 << 5,
- CON_USER = 1 << 6,
+ /** When set constraints are in use. */
+ CON_APPLY = 1 << 0,
+ /** These are only used for modal execution. */
+ CON_AXIS0 = 1 << 1,
+ CON_AXIS1 = 1 << 2,
+ CON_AXIS2 = 1 << 3,
+ CON_SELECT = 1 << 4,
+ /** Does not reorient vector to face viewport when on. */
+ CON_NOFLIP = 1 << 5,
+ CON_USER = 1 << 6,
};
/** #TransData.flag */
enum {
- TD_SELECTED = 1 << 0,
- TD_NOACTION = 1 << 2,
- TD_USEQUAT = 1 << 3,
- TD_NOTCONNECTED = 1 << 4,
- /** Used for scaling of #MetaElem.rad */
- TD_SINGLESIZE = 1 << 5,
- /** Scale relative to individual element center */
- TD_INDIVIDUAL_SCALE = 1 << 8,
- TD_NOCENTER = 1 << 9,
- /** #TransData.ext abused for particle key timing. */
- TD_NO_EXT = 1 << 10,
- /** don't transform this data */
- TD_SKIP = 1 << 11,
- /** if this is a bez triple, we need to restore the handles,
- * if this is set #TransData.hdata needs freeing */
- TD_BEZTRIPLE = 1 << 12,
- /** when this is set, don't apply translation changes to this element */
- TD_NO_LOC = 1 << 13,
- /** for Graph Editor autosnap, indicates that point should not undergo autosnapping */
- TD_NOTIMESNAP = 1 << 14,
- /** for Graph Editor - curves that can only have int-values need their keyframes tagged with this */
- TD_INTVALUES = 1 << 15,
- /** For editmode mirror, clamp to x = 0 */
- TD_MIRROR_EDGE = 1 << 16,
- /** For fcurve handles, move them along with their keyframes */
- TD_MOVEHANDLE1 = 1 << 17,
- TD_MOVEHANDLE2 = 1 << 18,
- /** Exceptional case with pose bone rotating when a parent bone has 'Local Location'
- * option enabled and rotating also transforms it. */
- TD_PBONE_LOCAL_MTX_P = 1 << 19,
- /** Same as above but for a child bone. */
- TD_PBONE_LOCAL_MTX_C = 1 << 20,
+ TD_SELECTED = 1 << 0,
+ TD_NOACTION = 1 << 2,
+ TD_USEQUAT = 1 << 3,
+ TD_NOTCONNECTED = 1 << 4,
+ /** Used for scaling of #MetaElem.rad */
+ TD_SINGLESIZE = 1 << 5,
+ /** Scale relative to individual element center */
+ TD_INDIVIDUAL_SCALE = 1 << 8,
+ TD_NOCENTER = 1 << 9,
+ /** #TransData.ext abused for particle key timing. */
+ TD_NO_EXT = 1 << 10,
+ /** don't transform this data */
+ TD_SKIP = 1 << 11,
+ /** if this is a bez triple, we need to restore the handles,
+ * if this is set #TransData.hdata needs freeing */
+ TD_BEZTRIPLE = 1 << 12,
+ /** when this is set, don't apply translation changes to this element */
+ TD_NO_LOC = 1 << 13,
+ /** for Graph Editor autosnap, indicates that point should not undergo autosnapping */
+ TD_NOTIMESNAP = 1 << 14,
+ /** for Graph Editor - curves that can only have int-values need their keyframes tagged with this */
+ TD_INTVALUES = 1 << 15,
+ /** For editmode mirror, clamp to x = 0 */
+ TD_MIRROR_EDGE = 1 << 16,
+ /** For fcurve handles, move them along with their keyframes */
+ TD_MOVEHANDLE1 = 1 << 17,
+ TD_MOVEHANDLE2 = 1 << 18,
+ /** Exceptional case with pose bone rotating when a parent bone has 'Local Location'
+ * option enabled and rotating also transforms it. */
+ TD_PBONE_LOCAL_MTX_P = 1 << 19,
+ /** Same as above but for a child bone. */
+ TD_PBONE_LOCAL_MTX_C = 1 << 20,
};
/** #TransSnap.status */
enum {
- SNAP_FORCED = 1 << 0,
- TARGET_INIT = 1 << 1,
- POINT_INIT = 1 << 2,
- MULTI_POINTS = 1 << 3,
+ SNAP_FORCED = 1 << 0,
+ TARGET_INIT = 1 << 1,
+ POINT_INIT = 1 << 2,
+ MULTI_POINTS = 1 << 3,
};
/* Hard min/max for proportional size. */
#define T_PROP_SIZE_MIN 1e-6f
#define T_PROP_SIZE_MAX 1e12f
-bool initTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op, const struct wmEvent *event, int mode);
+bool initTransform(struct bContext *C,
+ struct TransInfo *t,
+ struct wmOperator *op,
+ const struct wmEvent *event,
+ int mode);
void saveTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op);
-int transformEvent(TransInfo *t, const struct wmEvent *event);
+int transformEvent(TransInfo *t, const struct wmEvent *event);
void transformApply(struct bContext *C, TransInfo *t);
-int transformEnd(struct bContext *C, TransInfo *t);
+int transformEnd(struct bContext *C, TransInfo *t);
void setTransformViewMatrices(TransInfo *t);
void setTransformViewAspect(TransInfo *t, float r_aspect[3]);
@@ -864,7 +877,6 @@ void drawPropCircle(const struct bContext *C, TransInfo *t);
struct wmKeyMap *transform_modal_keymap(struct wmKeyConfig *keyconf);
-
/*********************** transform_conversions.c ********** */
void flushTransIntFrameActionData(TransInfo *t);
@@ -893,18 +905,24 @@ void drawDial3d(const TransInfo *t);
void createTransData(struct bContext *C, TransInfo *t);
void sort_trans_data_dist(TransInfo *t);
void special_aftertrans_update(struct bContext *C, TransInfo *t);
-int special_transform_moving(TransInfo *t);
+int special_transform_moving(TransInfo *t);
void transform_autoik_update(TransInfo *t, short mode);
bool transdata_check_local_islands(TransInfo *t, short around);
-int count_set_pose_transflags(struct Object *ob, const int mode, const short around, bool has_translate_rotate[2]);
+int count_set_pose_transflags(struct Object *ob,
+ const int mode,
+ const short around,
+ bool has_translate_rotate[2]);
/* Auto-keyframe applied after transform, returns true if motion paths need to be updated. */
-void autokeyframe_object(
- struct bContext *C, struct Scene *scene, struct ViewLayer *view_layer, struct Object *ob, int tmode);
+void autokeyframe_object(struct bContext *C,
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ struct Object *ob,
+ int tmode);
void autokeyframe_pose(
- struct bContext *C, struct Scene *scene, struct Object *ob, int tmode, short targetless_ik);
+ struct bContext *C, struct Scene *scene, struct Object *ob, int tmode, short targetless_ik);
/* Test if we need to update motion paths for a given object. */
bool motionpath_need_update_object(struct Scene *scene, struct Object *ob);
@@ -923,8 +941,8 @@ void setUserConstraint(TransInfo *t, short orientation, int mode, const char tex
void constraintNumInput(TransInfo *t, float vec[3]);
bool isLockConstraint(TransInfo *t);
-int getConstraintSpaceDimension(TransInfo *t);
-int constraintModeToIndex(const TransInfo *t);
+int getConstraintSpaceDimension(TransInfo *t);
+int constraintModeToIndex(const TransInfo *t);
char constraintModeToChar(const TransInfo *t);
void startConstraint(TransInfo *t);
@@ -939,9 +957,9 @@ void setNearestAxis(TransInfo *t);
/*********************** Snapping ********************************/
typedef enum {
- NO_GEARS = 0,
- BIG_GEARS = 1,
- SMALL_GEARS = 2,
+ NO_GEARS = 0,
+ BIG_GEARS = 1,
+ SMALL_GEARS = 2,
} GearsType;
bool transformModeUseSnap(const TransInfo *t);
@@ -973,35 +991,47 @@ void removeSnapPoint(TransInfo *t);
/********************** Mouse Input ******************************/
typedef enum {
- INPUT_NONE,
- INPUT_VECTOR,
- INPUT_SPRING,
- INPUT_SPRING_FLIP,
- INPUT_SPRING_DELTA,
- INPUT_ANGLE,
- INPUT_ANGLE_SPRING,
- INPUT_TRACKBALL,
- INPUT_HORIZONTAL_RATIO,
- INPUT_HORIZONTAL_ABSOLUTE,
- INPUT_VERTICAL_RATIO,
- INPUT_VERTICAL_ABSOLUTE,
- INPUT_CUSTOM_RATIO,
- INPUT_CUSTOM_RATIO_FLIP,
+ INPUT_NONE,
+ INPUT_VECTOR,
+ INPUT_SPRING,
+ INPUT_SPRING_FLIP,
+ INPUT_SPRING_DELTA,
+ INPUT_ANGLE,
+ INPUT_ANGLE_SPRING,
+ INPUT_TRACKBALL,
+ INPUT_HORIZONTAL_RATIO,
+ INPUT_HORIZONTAL_ABSOLUTE,
+ INPUT_VERTICAL_RATIO,
+ INPUT_VERTICAL_ABSOLUTE,
+ INPUT_CUSTOM_RATIO,
+ INPUT_CUSTOM_RATIO_FLIP,
} MouseInputMode;
-void initMouseInput(TransInfo *t, MouseInput *mi, const float center[2], const int mval[2], const bool precision);
+void initMouseInput(
+ TransInfo *t, MouseInput *mi, const float center[2], const int mval[2], const bool precision);
void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode);
-eRedrawFlag handleMouseInput(struct TransInfo *t, struct MouseInput *mi, const struct wmEvent *event);
-void applyMouseInput(struct TransInfo *t, struct MouseInput *mi, const int mval[2], float output[3]);
+eRedrawFlag handleMouseInput(struct TransInfo *t,
+ struct MouseInput *mi,
+ const struct wmEvent *event);
+void applyMouseInput(struct TransInfo *t,
+ struct MouseInput *mi,
+ const int mval[2],
+ float output[3]);
void setCustomPoints(TransInfo *t, MouseInput *mi, const int start[2], const int end[2]);
void setCustomPointsFromDirection(TransInfo *t, MouseInput *mi, const float dir[2]);
-void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3]));
+void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3]));
/*********************** Generics ********************************/
-void initTransDataContainers_FromObjectData(TransInfo *t, struct Object *obact, struct Object **objects, uint objects_len);
-void initTransInfo(struct bContext *C, TransInfo *t, struct wmOperator *op, const struct wmEvent *event);
+void initTransDataContainers_FromObjectData(TransInfo *t,
+ struct Object *obact,
+ struct Object **objects,
+ uint objects_len);
+void initTransInfo(struct bContext *C,
+ TransInfo *t,
+ struct wmOperator *op,
+ const struct wmEvent *event);
void freeTransCustomDataForMode(TransInfo *t);
void postTrans(struct bContext *C, TransInfo *t);
void resetTransModal(TransInfo *t);
@@ -1010,7 +1040,7 @@ void resetTransRestrictions(TransInfo *t);
void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis, short options);
/* DRAWLINE options flags */
-#define DRAWLIGHT 1
+#define DRAWLIGHT 1
void applyTransObjects(TransInfo *t);
void restoreTransObjects(TransInfo *t);
@@ -1044,21 +1074,27 @@ void initTransformOrientation(struct bContext *C, TransInfo *t);
bool createSpaceNormal(float mat[3][3], const float normal[3]);
bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const float tangent[3]);
-struct TransformOrientation *addMatrixSpace(struct bContext *C, float mat[3][3],
- const char *name, const bool overwrite);
-bool applyTransformOrientation(const struct TransformOrientation *ts, float r_mat[3][3], char r_name[64]);
+struct TransformOrientation *addMatrixSpace(struct bContext *C,
+ float mat[3][3],
+ const char *name,
+ const bool overwrite);
+bool applyTransformOrientation(const struct TransformOrientation *ts,
+ float r_mat[3][3],
+ char r_name[64]);
enum {
- ORIENTATION_NONE = 0,
- ORIENTATION_NORMAL = 1,
- ORIENTATION_VERT = 2,
- ORIENTATION_EDGE = 3,
- ORIENTATION_FACE = 4,
+ ORIENTATION_NONE = 0,
+ ORIENTATION_NORMAL = 1,
+ ORIENTATION_VERT = 2,
+ ORIENTATION_EDGE = 3,
+ ORIENTATION_FACE = 4,
};
-#define ORIENTATION_USE_PLANE(ty) \
- ELEM(ty, ORIENTATION_NORMAL, ORIENTATION_EDGE, ORIENTATION_FACE)
+#define ORIENTATION_USE_PLANE(ty) ELEM(ty, ORIENTATION_NORMAL, ORIENTATION_EDGE, ORIENTATION_FACE)
-int getTransformOrientation_ex(const struct bContext *C, float normal[3], float plane[3], const short around);
+int getTransformOrientation_ex(const struct bContext *C,
+ float normal[3],
+ float plane[3],
+ const short around);
int getTransformOrientation(const struct bContext *C, float normal[3], float plane[3]);
void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data);
@@ -1071,7 +1107,6 @@ void freeVertSlideTempFaces(VertSlideData *sld);
void freeVertSlideVerts(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data);
void projectVertSlideData(TransInfo *t, bool is_final);
-
/* TODO. transform_query.c */
bool checkUseAxisMatrix(TransInfo *t);
@@ -1082,16 +1117,19 @@ bool checkUseAxisMatrix(TransInfo *t);
#define TRANS_DATA_CONTAINER_FIRST_OK(t) (&(t)->data_container[0])
/* For cases we _know_ there is only one handle. */
-#define TRANS_DATA_CONTAINER_FIRST_SINGLE(t) (BLI_assert((t)->data_container_len == 1), (&(t)->data_container[0]))
+#define TRANS_DATA_CONTAINER_FIRST_SINGLE(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; \
- th != tc_end; \
- th++)
+ 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; \
- th != tc_end; \
- th++, i++)
+ for (TransDataContainer *tc = ((i = 0), t->data_container), \
+ *tc_end = t->data_container + t->data_container_len; \
+ th != tc_end; \
+ th++, i++)
#endif
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 2e8a921c7d8..27d6e597931 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -59,213 +59,221 @@ static void drawObjectConstraint(TransInfo *t);
/* ************************** CONSTRAINTS ************************* */
static void constraintAutoValues(TransInfo *t, float vec[3])
{
- int mode = t->con.mode;
- if (mode & CON_APPLY) {
- float nval = (t->flag & T_NULL_ONE) ? 1.0f : 0.0f;
-
- if ((mode & CON_AXIS0) == 0) {
- vec[0] = nval;
- }
- if ((mode & CON_AXIS1) == 0) {
- vec[1] = nval;
- }
- if ((mode & CON_AXIS2) == 0) {
- vec[2] = nval;
- }
- }
+ int mode = t->con.mode;
+ if (mode & CON_APPLY) {
+ float nval = (t->flag & T_NULL_ONE) ? 1.0f : 0.0f;
+
+ if ((mode & CON_AXIS0) == 0) {
+ vec[0] = nval;
+ }
+ if ((mode & CON_AXIS1) == 0) {
+ vec[1] = nval;
+ }
+ if ((mode & CON_AXIS2) == 0) {
+ vec[2] = nval;
+ }
+ }
}
void constraintNumInput(TransInfo *t, float vec[3])
{
- int mode = t->con.mode;
- if (mode & CON_APPLY) {
- float nval = (t->flag & T_NULL_ONE) ? 1.0f : 0.0f;
-
- const int dims = getConstraintSpaceDimension(t);
- if (dims == 2) {
- int axis = mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
- if (axis == (CON_AXIS0 | CON_AXIS1)) {
- /* vec[0] = vec[0]; */ /* same */
- /* vec[1] = vec[1]; */ /* same */
- vec[2] = nval;
- }
- else if (axis == (CON_AXIS1 | CON_AXIS2)) {
- vec[2] = vec[1];
- vec[1] = vec[0];
- vec[0] = nval;
- }
- else if (axis == (CON_AXIS0 | CON_AXIS2)) {
- /* vec[0] = vec[0]; */ /* same */
- vec[2] = vec[1];
- vec[1] = nval;
- }
- }
- else if (dims == 1) {
- if (mode & CON_AXIS0) {
- /* vec[0] = vec[0]; */ /* same */
- vec[1] = nval;
- vec[2] = nval;
- }
- else if (mode & CON_AXIS1) {
- vec[1] = vec[0];
- vec[0] = nval;
- vec[2] = nval;
- }
- else if (mode & CON_AXIS2) {
- vec[2] = vec[0];
- vec[0] = nval;
- vec[1] = nval;
- }
- }
- }
+ int mode = t->con.mode;
+ if (mode & CON_APPLY) {
+ float nval = (t->flag & T_NULL_ONE) ? 1.0f : 0.0f;
+
+ const int dims = getConstraintSpaceDimension(t);
+ if (dims == 2) {
+ int axis = mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
+ if (axis == (CON_AXIS0 | CON_AXIS1)) {
+ /* vec[0] = vec[0]; */ /* same */
+ /* vec[1] = vec[1]; */ /* same */
+ vec[2] = nval;
+ }
+ else if (axis == (CON_AXIS1 | CON_AXIS2)) {
+ vec[2] = vec[1];
+ vec[1] = vec[0];
+ vec[0] = nval;
+ }
+ else if (axis == (CON_AXIS0 | CON_AXIS2)) {
+ /* vec[0] = vec[0]; */ /* same */
+ vec[2] = vec[1];
+ vec[1] = nval;
+ }
+ }
+ else if (dims == 1) {
+ if (mode & CON_AXIS0) {
+ /* vec[0] = vec[0]; */ /* same */
+ vec[1] = nval;
+ vec[2] = nval;
+ }
+ else if (mode & CON_AXIS1) {
+ vec[1] = vec[0];
+ vec[0] = nval;
+ vec[2] = nval;
+ }
+ else if (mode & CON_AXIS2) {
+ vec[2] = vec[0];
+ vec[0] = nval;
+ vec[1] = nval;
+ }
+ }
+ }
}
static void postConstraintChecks(TransInfo *t, float vec[3], float pvec[3])
{
- int i = 0;
-
- mul_m3_v3(t->con.imtx, vec);
-
- snapGridIncrement(t, vec);
-
- if (t->flag & T_NULL_ONE) {
- if (!(t->con.mode & CON_AXIS0))
- vec[0] = 1.0f;
-
- if (!(t->con.mode & CON_AXIS1))
- vec[1] = 1.0f;
-
- if (!(t->con.mode & CON_AXIS2))
- vec[2] = 1.0f;
- }
-
- if (applyNumInput(&t->num, vec)) {
- constraintNumInput(t, vec);
- removeAspectRatio(t, vec);
- }
-
- /* autovalues is operator param, use that directly but not if snapping is forced */
- if (t->flag & T_AUTOVALUES && (t->tsnap.status & SNAP_FORCED) == 0) {
- copy_v3_v3(vec, t->auto_values);
- constraintAutoValues(t, vec);
- /* inverse transformation at the end */
- }
-
- if (t->con.mode & CON_AXIS0) {
- pvec[i++] = vec[0];
- }
- if (t->con.mode & CON_AXIS1) {
- pvec[i++] = vec[1];
- }
- if (t->con.mode & CON_AXIS2) {
- pvec[i++] = vec[2];
- }
-
- mul_m3_v3(t->con.mtx, vec);
+ int i = 0;
+
+ mul_m3_v3(t->con.imtx, vec);
+
+ snapGridIncrement(t, vec);
+
+ if (t->flag & T_NULL_ONE) {
+ if (!(t->con.mode & CON_AXIS0))
+ vec[0] = 1.0f;
+
+ if (!(t->con.mode & CON_AXIS1))
+ vec[1] = 1.0f;
+
+ if (!(t->con.mode & CON_AXIS2))
+ vec[2] = 1.0f;
+ }
+
+ if (applyNumInput(&t->num, vec)) {
+ constraintNumInput(t, vec);
+ removeAspectRatio(t, vec);
+ }
+
+ /* autovalues is operator param, use that directly but not if snapping is forced */
+ if (t->flag & T_AUTOVALUES && (t->tsnap.status & SNAP_FORCED) == 0) {
+ copy_v3_v3(vec, t->auto_values);
+ constraintAutoValues(t, vec);
+ /* inverse transformation at the end */
+ }
+
+ if (t->con.mode & CON_AXIS0) {
+ pvec[i++] = vec[0];
+ }
+ if (t->con.mode & CON_AXIS1) {
+ pvec[i++] = vec[1];
+ }
+ if (t->con.mode & CON_AXIS2) {
+ pvec[i++] = vec[2];
+ }
+
+ mul_m3_v3(t->con.mtx, vec);
}
static void viewAxisCorrectCenter(const TransInfo *t, float t_con_center[3])
{
- if (t->spacetype == SPACE_VIEW3D) {
- // View3D *v3d = t->sa->spacedata.first;
- const float min_dist = 1.0f; /* v3d->clip_start; */
- float dir[3];
- float l;
-
- sub_v3_v3v3(dir, t_con_center, t->viewinv[3]);
- if (dot_v3v3(dir, t->viewinv[2]) < 0.0f) {
- negate_v3(dir);
- }
- project_v3_v3v3(dir, dir, t->viewinv[2]);
-
- l = len_v3(dir);
-
- if (l < min_dist) {
- float diff[3];
- normalize_v3_v3_length(diff, t->viewinv[2], min_dist - l);
- sub_v3_v3(t_con_center, diff);
- }
- }
+ if (t->spacetype == SPACE_VIEW3D) {
+ // View3D *v3d = t->sa->spacedata.first;
+ const float min_dist = 1.0f; /* v3d->clip_start; */
+ float dir[3];
+ float l;
+
+ sub_v3_v3v3(dir, t_con_center, t->viewinv[3]);
+ if (dot_v3v3(dir, t->viewinv[2]) < 0.0f) {
+ negate_v3(dir);
+ }
+ project_v3_v3v3(dir, dir, t->viewinv[2]);
+
+ l = len_v3(dir);
+
+ if (l < min_dist) {
+ float diff[3];
+ normalize_v3_v3_length(diff, t->viewinv[2], min_dist - l);
+ sub_v3_v3(t_con_center, diff);
+ }
+ }
}
/**
* Axis calculation taking the view into account, correcting view-aligned axis.
*/
-static void axisProjection(const TransInfo *t, const float axis[3], const float in[3], float out[3])
+static void axisProjection(const TransInfo *t,
+ const float axis[3],
+ const float in[3],
+ float out[3])
{
- float norm[3], vec[3], factor, angle;
- float t_con_center[3];
-
- if (is_zero_v3(in)) {
- return;
- }
-
- copy_v3_v3(t_con_center, t->center_global);
-
- /* checks for center being too close to the view center */
- viewAxisCorrectCenter(t, t_con_center);
-
- angle = fabsf(angle_v3v3(axis, t->viewinv[2]));
- if (angle > (float)M_PI_2) {
- angle = (float)M_PI - angle;
- }
-
- /* For when view is parallel to constraint... will cause NaNs otherwise
- * So we take vertical motion in 3D space and apply it to the
- * constraint axis. Nice for camera grab + MMB */
- if (angle < DEG2RADF(5.0f)) {
- project_v3_v3v3(vec, in, t->viewinv[1]);
- factor = dot_v3v3(t->viewinv[1], vec) * 2.0f;
- /* since camera distance is quite relative, use quadratic relationship. holding shift can compensate */
- if (factor < 0.0f) factor *= -factor;
- else factor *= factor;
-
- /* -factor makes move down going backwards */
- normalize_v3_v3_length(out, axis, -factor);
- }
- else {
- float v[3], i1[3], i2[3];
- float v2[3], v4[3];
- float norm_center[3];
- float plane[3];
-
- getViewVector(t, t_con_center, norm_center);
- cross_v3_v3v3(plane, norm_center, axis);
-
- project_v3_v3v3(vec, in, plane);
- sub_v3_v3v3(vec, in, vec);
-
- add_v3_v3v3(v, vec, t_con_center);
- getViewVector(t, v, norm);
-
- /* give arbitrary large value if projection is impossible */
- factor = dot_v3v3(axis, norm);
- if (1.0f - fabsf(factor) < 0.0002f) {
- copy_v3_v3(out, axis);
- if (factor > 0) {
- mul_v3_fl(out, 1000000000.0f);
- }
- else {
- mul_v3_fl(out, -1000000000.0f);
- }
- }
- else {
- add_v3_v3v3(v2, t_con_center, axis);
- add_v3_v3v3(v4, v, norm);
-
- isect_line_line_v3(t_con_center, v2, v, v4, i1, i2);
-
- sub_v3_v3v3(v, i2, v);
-
- sub_v3_v3v3(out, i1, t_con_center);
-
- /* possible some values become nan when
- * viewpoint and object are both zero */
- if (!isfinite(out[0])) out[0] = 0.0f;
- if (!isfinite(out[1])) out[1] = 0.0f;
- if (!isfinite(out[2])) out[2] = 0.0f;
- }
- }
+ float norm[3], vec[3], factor, angle;
+ float t_con_center[3];
+
+ if (is_zero_v3(in)) {
+ return;
+ }
+
+ copy_v3_v3(t_con_center, t->center_global);
+
+ /* checks for center being too close to the view center */
+ viewAxisCorrectCenter(t, t_con_center);
+
+ angle = fabsf(angle_v3v3(axis, t->viewinv[2]));
+ if (angle > (float)M_PI_2) {
+ angle = (float)M_PI - angle;
+ }
+
+ /* For when view is parallel to constraint... will cause NaNs otherwise
+ * So we take vertical motion in 3D space and apply it to the
+ * constraint axis. Nice for camera grab + MMB */
+ if (angle < DEG2RADF(5.0f)) {
+ project_v3_v3v3(vec, in, t->viewinv[1]);
+ factor = dot_v3v3(t->viewinv[1], vec) * 2.0f;
+ /* since camera distance is quite relative, use quadratic relationship. holding shift can compensate */
+ if (factor < 0.0f)
+ factor *= -factor;
+ else
+ factor *= factor;
+
+ /* -factor makes move down going backwards */
+ normalize_v3_v3_length(out, axis, -factor);
+ }
+ else {
+ float v[3], i1[3], i2[3];
+ float v2[3], v4[3];
+ float norm_center[3];
+ float plane[3];
+
+ getViewVector(t, t_con_center, norm_center);
+ cross_v3_v3v3(plane, norm_center, axis);
+
+ project_v3_v3v3(vec, in, plane);
+ sub_v3_v3v3(vec, in, vec);
+
+ add_v3_v3v3(v, vec, t_con_center);
+ getViewVector(t, v, norm);
+
+ /* give arbitrary large value if projection is impossible */
+ factor = dot_v3v3(axis, norm);
+ if (1.0f - fabsf(factor) < 0.0002f) {
+ copy_v3_v3(out, axis);
+ if (factor > 0) {
+ mul_v3_fl(out, 1000000000.0f);
+ }
+ else {
+ mul_v3_fl(out, -1000000000.0f);
+ }
+ }
+ else {
+ add_v3_v3v3(v2, t_con_center, axis);
+ add_v3_v3v3(v4, v, norm);
+
+ isect_line_line_v3(t_con_center, v2, v, v4, i1, i2);
+
+ sub_v3_v3v3(v, i2, v);
+
+ sub_v3_v3v3(out, i1, t_con_center);
+
+ /* possible some values become nan when
+ * viewpoint and object are both zero */
+ if (!isfinite(out[0]))
+ out[0] = 0.0f;
+ if (!isfinite(out[1]))
+ out[1] = 0.0f;
+ if (!isfinite(out[2]))
+ out[2] = 0.0f;
+ }
+ }
}
/**
@@ -274,49 +282,49 @@ static void axisProjection(const TransInfo *t, const float axis[3], const float
*/
static bool isPlaneProjectionViewAligned(const TransInfo *t)
{
- const float eps = 0.001f;
- const float *constraint_vector[2];
- int n = 0;
- for (int i = 0; i < 3; i++) {
- if (t->con.mode & (CON_AXIS0 << i)) {
- constraint_vector[n++] = t->con.mtx[i];
- if (n == 2) {
- break;
- }
- }
- }
- BLI_assert(n == 2);
-
- float view_to_plane[3], plane_normal[3];
-
- getViewVector(t, t->center_global, view_to_plane);
-
- cross_v3_v3v3(plane_normal, constraint_vector[0], constraint_vector[1]);
- normalize_v3(plane_normal);
-
- float factor = dot_v3v3(plane_normal, view_to_plane);
- return fabsf(factor) < eps;
+ const float eps = 0.001f;
+ const float *constraint_vector[2];
+ int n = 0;
+ for (int i = 0; i < 3; i++) {
+ if (t->con.mode & (CON_AXIS0 << i)) {
+ constraint_vector[n++] = t->con.mtx[i];
+ if (n == 2) {
+ break;
+ }
+ }
+ }
+ BLI_assert(n == 2);
+
+ float view_to_plane[3], plane_normal[3];
+
+ getViewVector(t, t->center_global, view_to_plane);
+
+ cross_v3_v3v3(plane_normal, constraint_vector[0], constraint_vector[1]);
+ normalize_v3(plane_normal);
+
+ float factor = dot_v3v3(plane_normal, view_to_plane);
+ return fabsf(factor) < eps;
}
static void planeProjection(const TransInfo *t, const float in[3], float out[3])
{
- float vec[3], factor, norm[3];
+ float vec[3], factor, norm[3];
- add_v3_v3v3(vec, in, t->center_global);
- getViewVector(t, vec, norm);
+ add_v3_v3v3(vec, in, t->center_global);
+ getViewVector(t, vec, norm);
- sub_v3_v3v3(vec, out, in);
+ sub_v3_v3v3(vec, out, in);
- factor = dot_v3v3(vec, norm);
- if (fabsf(factor) <= 0.001f) {
- return; /* prevent divide by zero */
- }
- factor = dot_v3v3(vec, vec) / factor;
+ factor = dot_v3v3(vec, norm);
+ if (fabsf(factor) <= 0.001f) {
+ return; /* prevent divide by zero */
+ }
+ factor = dot_v3v3(vec, vec) / factor;
- copy_v3_v3(vec, norm);
- mul_v3_fl(vec, factor);
+ copy_v3_v3(vec, norm);
+ mul_v3_fl(vec, factor);
- add_v3_v3v3(out, in, vec);
+ add_v3_v3v3(out, in, vec);
}
/*
@@ -327,40 +335,44 @@ static void planeProjection(const TransInfo *t, const float in[3], float out[3])
* (in perspective mode, the view vector is relative to the position on screen)
*/
-static void applyAxisConstraintVec(
- TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, const float in[3], float out[3], float pvec[3])
+static void applyAxisConstraintVec(TransInfo *t,
+ TransDataContainer *UNUSED(tc),
+ TransData *td,
+ const float in[3],
+ float out[3],
+ float pvec[3])
{
- copy_v3_v3(out, in);
- if (!td && t->con.mode & CON_APPLY) {
- mul_m3_v3(t->con.pmtx, out);
-
- // With snap, a projection is alright, no need to correct for view alignment
- if (!validSnap(t)) {
- const int dims = getConstraintSpaceDimension(t);
- if (dims == 2) {
- if (!is_zero_v3(out)) {
- if (!isPlaneProjectionViewAligned(t)) {
- planeProjection(t, in, out);
- }
- }
- }
- else if (dims == 1) {
- float c[3];
-
- if (t->con.mode & CON_AXIS0) {
- copy_v3_v3(c, t->con.mtx[0]);
- }
- else if (t->con.mode & CON_AXIS1) {
- copy_v3_v3(c, t->con.mtx[1]);
- }
- else if (t->con.mode & CON_AXIS2) {
- copy_v3_v3(c, t->con.mtx[2]);
- }
- axisProjection(t, c, in, out);
- }
- }
- postConstraintChecks(t, out, pvec);
- }
+ copy_v3_v3(out, in);
+ if (!td && t->con.mode & CON_APPLY) {
+ mul_m3_v3(t->con.pmtx, out);
+
+ // With snap, a projection is alright, no need to correct for view alignment
+ if (!validSnap(t)) {
+ const int dims = getConstraintSpaceDimension(t);
+ if (dims == 2) {
+ if (!is_zero_v3(out)) {
+ if (!isPlaneProjectionViewAligned(t)) {
+ planeProjection(t, in, out);
+ }
+ }
+ }
+ else if (dims == 1) {
+ float c[3];
+
+ if (t->con.mode & CON_AXIS0) {
+ copy_v3_v3(c, t->con.mtx[0]);
+ }
+ else if (t->con.mode & CON_AXIS1) {
+ copy_v3_v3(c, t->con.mtx[1]);
+ }
+ else if (t->con.mode & CON_AXIS2) {
+ copy_v3_v3(c, t->con.mtx[2]);
+ }
+ axisProjection(t, c, in, out);
+ }
+ }
+ postConstraintChecks(t, out, pvec);
+ }
}
/*
@@ -374,115 +386,123 @@ static void applyAxisConstraintVec(
* Further down, that vector is mapped to each data's space.
*/
-static void applyObjectConstraintVec(
- TransInfo *t, TransDataContainer *tc, TransData *td, const float in[3], float out[3], float pvec[3])
+static void applyObjectConstraintVec(TransInfo *t,
+ TransDataContainer *tc,
+ TransData *td,
+ const float in[3],
+ float out[3],
+ float pvec[3])
{
- copy_v3_v3(out, in);
- if (t->con.mode & CON_APPLY) {
- if (!td) {
- mul_m3_v3(t->con.pmtx, out);
-
- const int dims = getConstraintSpaceDimension(t);
- if (dims == 2) {
- if (!is_zero_v3(out)) {
- if (!isPlaneProjectionViewAligned(t)) {
- planeProjection(t, in, out);
- }
- }
- }
- else if (dims == 1) {
- float c[3];
-
- if (t->con.mode & CON_AXIS0) {
- copy_v3_v3(c, t->con.mtx[0]);
- }
- else if (t->con.mode & CON_AXIS1) {
- copy_v3_v3(c, t->con.mtx[1]);
- }
- else if (t->con.mode & CON_AXIS2) {
- copy_v3_v3(c, t->con.mtx[2]);
- }
- axisProjection(t, c, in, out);
- }
- postConstraintChecks(t, out, pvec);
- copy_v3_v3(out, pvec);
- }
- else {
- int i = 0;
-
- out[0] = out[1] = out[2] = 0.0f;
- if (t->con.mode & CON_AXIS0) {
- out[0] = in[i++];
- }
- if (t->con.mode & CON_AXIS1) {
- out[1] = in[i++];
- }
- if (t->con.mode & CON_AXIS2) {
- out[2] = in[i++];
- }
-
- mul_m3_v3(td->axismtx, out);
- if (t->flag & T_EDIT) {
- mul_m3_v3(tc->mat3_unit, out);
- }
- }
- }
+ copy_v3_v3(out, in);
+ if (t->con.mode & CON_APPLY) {
+ if (!td) {
+ mul_m3_v3(t->con.pmtx, out);
+
+ const int dims = getConstraintSpaceDimension(t);
+ if (dims == 2) {
+ if (!is_zero_v3(out)) {
+ if (!isPlaneProjectionViewAligned(t)) {
+ planeProjection(t, in, out);
+ }
+ }
+ }
+ else if (dims == 1) {
+ float c[3];
+
+ if (t->con.mode & CON_AXIS0) {
+ copy_v3_v3(c, t->con.mtx[0]);
+ }
+ else if (t->con.mode & CON_AXIS1) {
+ copy_v3_v3(c, t->con.mtx[1]);
+ }
+ else if (t->con.mode & CON_AXIS2) {
+ copy_v3_v3(c, t->con.mtx[2]);
+ }
+ axisProjection(t, c, in, out);
+ }
+ postConstraintChecks(t, out, pvec);
+ copy_v3_v3(out, pvec);
+ }
+ else {
+ int i = 0;
+
+ out[0] = out[1] = out[2] = 0.0f;
+ if (t->con.mode & CON_AXIS0) {
+ out[0] = in[i++];
+ }
+ if (t->con.mode & CON_AXIS1) {
+ out[1] = in[i++];
+ }
+ if (t->con.mode & CON_AXIS2) {
+ out[2] = in[i++];
+ }
+
+ mul_m3_v3(td->axismtx, out);
+ if (t->flag & T_EDIT) {
+ mul_m3_v3(tc->mat3_unit, out);
+ }
+ }
+ }
}
/*
* Generic callback for constant spatial constraints applied to resize motion
*/
-static void applyAxisConstraintSize(
- TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, float smat[3][3])
+static void applyAxisConstraintSize(TransInfo *t,
+ TransDataContainer *UNUSED(tc),
+ TransData *td,
+ float smat[3][3])
{
- if (!td && t->con.mode & CON_APPLY) {
- float tmat[3][3];
-
- if (!(t->con.mode & CON_AXIS0)) {
- smat[0][0] = 1.0f;
- }
- if (!(t->con.mode & CON_AXIS1)) {
- smat[1][1] = 1.0f;
- }
- if (!(t->con.mode & CON_AXIS2)) {
- smat[2][2] = 1.0f;
- }
-
- mul_m3_m3m3(tmat, smat, t->con.imtx);
- mul_m3_m3m3(smat, t->con.mtx, tmat);
- }
+ if (!td && t->con.mode & CON_APPLY) {
+ float tmat[3][3];
+
+ if (!(t->con.mode & CON_AXIS0)) {
+ smat[0][0] = 1.0f;
+ }
+ if (!(t->con.mode & CON_AXIS1)) {
+ smat[1][1] = 1.0f;
+ }
+ if (!(t->con.mode & CON_AXIS2)) {
+ smat[2][2] = 1.0f;
+ }
+
+ mul_m3_m3m3(tmat, smat, t->con.imtx);
+ mul_m3_m3m3(smat, t->con.mtx, tmat);
+ }
}
/*
* Callback for object based spatial constraints applied to resize motion
*/
-static void applyObjectConstraintSize(
- TransInfo *t, TransDataContainer *tc, TransData *td, float smat[3][3])
+static void applyObjectConstraintSize(TransInfo *t,
+ TransDataContainer *tc,
+ TransData *td,
+ float smat[3][3])
{
- if (td && t->con.mode & CON_APPLY) {
- float tmat[3][3];
- float imat[3][3];
-
- invert_m3_m3(imat, td->axismtx);
-
- if (!(t->con.mode & CON_AXIS0)) {
- smat[0][0] = 1.0f;
- }
- if (!(t->con.mode & CON_AXIS1)) {
- smat[1][1] = 1.0f;
- }
- if (!(t->con.mode & CON_AXIS2)) {
- smat[2][2] = 1.0f;
- }
-
- mul_m3_m3m3(tmat, smat, imat);
- if (t->flag & T_EDIT) {
- mul_m3_m3m3(smat, tc->mat3_unit, smat);
- }
- mul_m3_m3m3(smat, td->axismtx, tmat);
- }
+ if (td && t->con.mode & CON_APPLY) {
+ float tmat[3][3];
+ float imat[3][3];
+
+ invert_m3_m3(imat, td->axismtx);
+
+ if (!(t->con.mode & CON_AXIS0)) {
+ smat[0][0] = 1.0f;
+ }
+ if (!(t->con.mode & CON_AXIS1)) {
+ smat[1][1] = 1.0f;
+ }
+ if (!(t->con.mode & CON_AXIS2)) {
+ smat[2][2] = 1.0f;
+ }
+
+ mul_m3_m3m3(tmat, smat, imat);
+ if (t->flag & T_EDIT) {
+ mul_m3_m3m3(smat, tc->mat3_unit, smat);
+ }
+ mul_m3_m3m3(smat, td->axismtx, tmat);
+ }
}
/*
@@ -499,32 +519,33 @@ static void applyObjectConstraintSize(
* (ie: not doing counterclockwise rotations when the mouse moves clockwise).
*/
-static void applyAxisConstraintRot(TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, float vec[3], float *angle)
+static void applyAxisConstraintRot(
+ TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, float vec[3], float *angle)
{
- if (!td && t->con.mode & CON_APPLY) {
- int mode = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
-
- switch (mode) {
- case CON_AXIS0:
- case (CON_AXIS1 | CON_AXIS2):
- copy_v3_v3(vec, t->con.mtx[0]);
- break;
- case CON_AXIS1:
- case (CON_AXIS0 | CON_AXIS2):
- copy_v3_v3(vec, t->con.mtx[1]);
- break;
- case CON_AXIS2:
- case (CON_AXIS0 | CON_AXIS1):
- copy_v3_v3(vec, t->con.mtx[2]);
- break;
- }
- /* don't flip axis if asked to or if num input */
- if (angle && (mode & CON_NOFLIP) == 0 && hasNumInput(&t->num) == 0) {
- if (dot_v3v3(vec, t->viewinv[2]) > 0.0f) {
- *angle = -(*angle);
- }
- }
- }
+ if (!td && t->con.mode & CON_APPLY) {
+ int mode = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
+
+ switch (mode) {
+ case CON_AXIS0:
+ case (CON_AXIS1 | CON_AXIS2):
+ copy_v3_v3(vec, t->con.mtx[0]);
+ break;
+ case CON_AXIS1:
+ case (CON_AXIS0 | CON_AXIS2):
+ copy_v3_v3(vec, t->con.mtx[1]);
+ break;
+ case CON_AXIS2:
+ case (CON_AXIS0 | CON_AXIS1):
+ copy_v3_v3(vec, t->con.mtx[2]);
+ break;
+ }
+ /* don't flip axis if asked to or if num input */
+ if (angle && (mode & CON_NOFLIP) == 0 && hasNumInput(&t->num) == 0) {
+ if (dot_v3v3(vec, t->viewinv[2]) > 0.0f) {
+ *angle = -(*angle);
+ }
+ }
+ }
}
/*
@@ -542,110 +563,110 @@ static void applyAxisConstraintRot(TransInfo *t, TransDataContainer *UNUSED(tc),
*/
static void applyObjectConstraintRot(
- TransInfo *t, TransDataContainer *tc, TransData *td, float vec[3], float *angle)
+ TransInfo *t, TransDataContainer *tc, TransData *td, float vec[3], float *angle)
{
- if (t->con.mode & CON_APPLY) {
- int mode = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
- float tmp_axismtx[3][3];
- float (*axismtx)[3];
-
- /* on setup call, use first object */
- if (td == NULL) {
- BLI_assert(tc == NULL);
- tc = TRANS_DATA_CONTAINER_FIRST_OK(t);
- td = tc->data;
- }
-
- if (t->flag & T_EDIT) {
- mul_m3_m3m3(tmp_axismtx, tc->mat3_unit, td->axismtx);
- axismtx = tmp_axismtx;
- }
- else {
- axismtx = td->axismtx;
- }
-
- switch (mode) {
- case CON_AXIS0:
- case (CON_AXIS1 | CON_AXIS2):
- copy_v3_v3(vec, axismtx[0]);
- break;
- case CON_AXIS1:
- case (CON_AXIS0 | CON_AXIS2):
- copy_v3_v3(vec, axismtx[1]);
- break;
- case CON_AXIS2:
- case (CON_AXIS0 | CON_AXIS1):
- copy_v3_v3(vec, axismtx[2]);
- break;
- }
- if (angle && (mode & CON_NOFLIP) == 0 && hasNumInput(&t->num) == 0) {
- if (dot_v3v3(vec, t->viewinv[2]) > 0.0f) {
- *angle = -(*angle);
- }
- }
- }
+ if (t->con.mode & CON_APPLY) {
+ int mode = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
+ float tmp_axismtx[3][3];
+ float(*axismtx)[3];
+
+ /* on setup call, use first object */
+ if (td == NULL) {
+ BLI_assert(tc == NULL);
+ tc = TRANS_DATA_CONTAINER_FIRST_OK(t);
+ td = tc->data;
+ }
+
+ if (t->flag & T_EDIT) {
+ mul_m3_m3m3(tmp_axismtx, tc->mat3_unit, td->axismtx);
+ axismtx = tmp_axismtx;
+ }
+ else {
+ axismtx = td->axismtx;
+ }
+
+ switch (mode) {
+ case CON_AXIS0:
+ case (CON_AXIS1 | CON_AXIS2):
+ copy_v3_v3(vec, axismtx[0]);
+ break;
+ case CON_AXIS1:
+ case (CON_AXIS0 | CON_AXIS2):
+ copy_v3_v3(vec, axismtx[1]);
+ break;
+ case CON_AXIS2:
+ case (CON_AXIS0 | CON_AXIS1):
+ copy_v3_v3(vec, axismtx[2]);
+ break;
+ }
+ if (angle && (mode & CON_NOFLIP) == 0 && hasNumInput(&t->num) == 0) {
+ if (dot_v3v3(vec, t->viewinv[2]) > 0.0f) {
+ *angle = -(*angle);
+ }
+ }
+ }
}
/*--------------------- INTERNAL SETUP CALLS ------------------*/
void setConstraint(TransInfo *t, float space[3][3], int mode, const char text[])
{
- BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1);
- copy_m3_m3(t->con.mtx, space);
- t->con.mode = mode;
- getConstraintMatrix(t);
-
- startConstraint(t);
-
- t->con.drawExtra = NULL;
- t->con.applyVec = applyAxisConstraintVec;
- t->con.applySize = applyAxisConstraintSize;
- t->con.applyRot = applyAxisConstraintRot;
- t->redraw = TREDRAW_HARD;
+ BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1);
+ copy_m3_m3(t->con.mtx, space);
+ t->con.mode = mode;
+ getConstraintMatrix(t);
+
+ startConstraint(t);
+
+ t->con.drawExtra = NULL;
+ t->con.applyVec = applyAxisConstraintVec;
+ t->con.applySize = applyAxisConstraintSize;
+ t->con.applyRot = applyAxisConstraintRot;
+ t->redraw = TREDRAW_HARD;
}
/* applies individual td->axismtx constraints */
void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[])
{
- TransDataContainer *tc = t->data_container;
- if (t->data_len_all == 1) {
- float axismtx[3][3];
- if (t->flag & T_EDIT) {
- mul_m3_m3m3(axismtx, tc->mat3_unit, tc->data->axismtx);
- }
- else {
- copy_m3_m3(axismtx, tc->data->axismtx);
- }
-
- setConstraint(t, axismtx, mode, text);
- }
- else {
- BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1);
- copy_m3_m3(t->con.mtx, tc->data->axismtx);
- t->con.mode = mode;
- getConstraintMatrix(t);
-
- startConstraint(t);
-
- t->con.drawExtra = drawObjectConstraint;
- t->con.applyVec = applyObjectConstraintVec;
- t->con.applySize = applyObjectConstraintSize;
- t->con.applyRot = applyObjectConstraintRot;
- t->redraw = TREDRAW_HARD;
- }
+ TransDataContainer *tc = t->data_container;
+ if (t->data_len_all == 1) {
+ float axismtx[3][3];
+ if (t->flag & T_EDIT) {
+ mul_m3_m3m3(axismtx, tc->mat3_unit, tc->data->axismtx);
+ }
+ else {
+ copy_m3_m3(axismtx, tc->data->axismtx);
+ }
+
+ setConstraint(t, axismtx, mode, text);
+ }
+ else {
+ BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1);
+ copy_m3_m3(t->con.mtx, tc->data->axismtx);
+ t->con.mode = mode;
+ getConstraintMatrix(t);
+
+ startConstraint(t);
+
+ t->con.drawExtra = drawObjectConstraint;
+ t->con.applyVec = applyObjectConstraintVec;
+ t->con.applySize = applyObjectConstraintSize;
+ t->con.applyRot = applyObjectConstraintRot;
+ t->redraw = TREDRAW_HARD;
+ }
}
void setLocalConstraint(TransInfo *t, int mode, const char text[])
{
- /* edit-mode now allows local transforms too */
- if (t->flag & T_EDIT) {
- /* Use the active (first) edit object. */
- TransDataContainer *tc = t->data_container;
- setConstraint(t, tc->mat3_unit, mode, text);
- }
- else {
- setAxisMatrixConstraint(t, mode, text);
- }
+ /* edit-mode now allows local transforms too */
+ if (t->flag & T_EDIT) {
+ /* Use the active (first) edit object. */
+ TransDataContainer *tc = t->data_container;
+ setConstraint(t, tc->mat3_unit, mode, text);
+ }
+ else {
+ setAxisMatrixConstraint(t, mode, text);
+ }
}
/*
@@ -656,486 +677,489 @@ void setLocalConstraint(TransInfo *t, int mode, const char text[])
*/
void setUserConstraint(TransInfo *t, short orientation, int mode, const char ftext[])
{
- char text[256];
-
- switch (orientation) {
- case V3D_ORIENT_GLOBAL:
- {
- float mtx[3][3];
- BLI_snprintf(text, sizeof(text), ftext, IFACE_("global"));
- unit_m3(mtx);
- setConstraint(t, mtx, mode, text);
- break;
- }
- case V3D_ORIENT_LOCAL:
- BLI_snprintf(text, sizeof(text), ftext, IFACE_("local"));
- setLocalConstraint(t, mode, text);
- break;
- case V3D_ORIENT_NORMAL:
- BLI_snprintf(text, sizeof(text), ftext, IFACE_("normal"));
- if (checkUseAxisMatrix(t)) {
- setAxisMatrixConstraint(t, mode, text);
- }
- else {
- setConstraint(t, t->spacemtx, mode, text);
- }
- break;
- case V3D_ORIENT_VIEW:
- BLI_snprintf(text, sizeof(text), ftext, IFACE_("view"));
- setConstraint(t, t->spacemtx, mode, text);
- break;
- case V3D_ORIENT_CURSOR:
- BLI_snprintf(text, sizeof(text), ftext, IFACE_("cursor"));
- setConstraint(t, t->spacemtx, mode, text);
- break;
- case V3D_ORIENT_GIMBAL:
- BLI_snprintf(text, sizeof(text), ftext, IFACE_("gimbal"));
- setConstraint(t, t->spacemtx, mode, text);
- break;
- case V3D_ORIENT_CUSTOM_MATRIX:
- BLI_snprintf(text, sizeof(text), ftext, IFACE_("custom matrix"));
- setConstraint(t, t->spacemtx, mode, text);
- break;
- case V3D_ORIENT_CUSTOM:
- {
- char orientation_str[128];
- BLI_snprintf(orientation_str, sizeof(orientation_str), "%s \"%s\"",
- IFACE_("custom orientation"), t->orientation.custom->name);
- BLI_snprintf(text, sizeof(text), ftext, orientation_str);
- setConstraint(t, t->spacemtx, mode, text);
- break;
- }
- }
-
- t->con.orientation = orientation;
-
- t->con.mode |= CON_USER;
+ char text[256];
+
+ switch (orientation) {
+ case V3D_ORIENT_GLOBAL: {
+ float mtx[3][3];
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("global"));
+ unit_m3(mtx);
+ setConstraint(t, mtx, mode, text);
+ break;
+ }
+ case V3D_ORIENT_LOCAL:
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("local"));
+ setLocalConstraint(t, mode, text);
+ break;
+ case V3D_ORIENT_NORMAL:
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("normal"));
+ if (checkUseAxisMatrix(t)) {
+ setAxisMatrixConstraint(t, mode, text);
+ }
+ else {
+ setConstraint(t, t->spacemtx, mode, text);
+ }
+ break;
+ case V3D_ORIENT_VIEW:
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("view"));
+ setConstraint(t, t->spacemtx, mode, text);
+ break;
+ case V3D_ORIENT_CURSOR:
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("cursor"));
+ setConstraint(t, t->spacemtx, mode, text);
+ break;
+ case V3D_ORIENT_GIMBAL:
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("gimbal"));
+ setConstraint(t, t->spacemtx, mode, text);
+ break;
+ case V3D_ORIENT_CUSTOM_MATRIX:
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("custom matrix"));
+ setConstraint(t, t->spacemtx, mode, text);
+ break;
+ case V3D_ORIENT_CUSTOM: {
+ char orientation_str[128];
+ BLI_snprintf(orientation_str,
+ sizeof(orientation_str),
+ "%s \"%s\"",
+ IFACE_("custom orientation"),
+ t->orientation.custom->name);
+ BLI_snprintf(text, sizeof(text), ftext, orientation_str);
+ setConstraint(t, t->spacemtx, mode, text);
+ break;
+ }
+ }
+
+ t->con.orientation = orientation;
+
+ t->con.mode |= CON_USER;
}
/*----------------- DRAWING CONSTRAINTS -------------------*/
void drawConstraint(TransInfo *t)
{
- TransCon *tc = &(t->con);
-
- if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE))
- return;
- if (!(tc->mode & CON_APPLY))
- return;
- if (t->flag & T_NO_CONSTRAINT)
- return;
-
- if (tc->drawExtra) {
- tc->drawExtra(t);
- }
- else {
- if (tc->mode & CON_SELECT) {
- float vec[3];
- int depth_test_enabled;
-
- convertViewVec(t, vec, (t->mval[0] - t->con.imval[0]), (t->mval[1] - t->con.imval[1]));
- add_v3_v3(vec, t->center_global);
-
- drawLine(t, t->center_global, tc->mtx[0], 'X', 0);
- drawLine(t, t->center_global, tc->mtx[1], 'Y', 0);
- drawLine(t, t->center_global, tc->mtx[2], 'Z', 0);
-
- depth_test_enabled = GPU_depth_test_enabled();
- if (depth_test_enabled)
- GPU_depth_test(false);
-
- const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-
- 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", 2.0f);
- immUniform1f("dash_factor", 0.5f);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3fv(shdr_pos, t->center_global);
- immVertex3fv(shdr_pos, vec);
- immEnd();
-
- immUnbindProgram();
-
- if (depth_test_enabled)
- GPU_depth_test(true);
- }
-
- if (tc->mode & CON_AXIS0) {
- drawLine(t, t->center_global, tc->mtx[0], 'X', DRAWLIGHT);
- }
- if (tc->mode & CON_AXIS1) {
- drawLine(t, t->center_global, tc->mtx[1], 'Y', DRAWLIGHT);
- }
- if (tc->mode & CON_AXIS2) {
- drawLine(t, t->center_global, tc->mtx[2], 'Z', DRAWLIGHT);
- }
- }
+ TransCon *tc = &(t->con);
+
+ if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE))
+ return;
+ if (!(tc->mode & CON_APPLY))
+ return;
+ if (t->flag & T_NO_CONSTRAINT)
+ return;
+
+ if (tc->drawExtra) {
+ tc->drawExtra(t);
+ }
+ else {
+ if (tc->mode & CON_SELECT) {
+ float vec[3];
+ int depth_test_enabled;
+
+ convertViewVec(t, vec, (t->mval[0] - t->con.imval[0]), (t->mval[1] - t->con.imval[1]));
+ add_v3_v3(vec, t->center_global);
+
+ drawLine(t, t->center_global, tc->mtx[0], 'X', 0);
+ drawLine(t, t->center_global, tc->mtx[1], 'Y', 0);
+ drawLine(t, t->center_global, tc->mtx[2], 'Z', 0);
+
+ depth_test_enabled = GPU_depth_test_enabled();
+ if (depth_test_enabled)
+ GPU_depth_test(false);
+
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ 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", 2.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3fv(shdr_pos, t->center_global);
+ immVertex3fv(shdr_pos, vec);
+ immEnd();
+
+ immUnbindProgram();
+
+ if (depth_test_enabled)
+ GPU_depth_test(true);
+ }
+
+ if (tc->mode & CON_AXIS0) {
+ drawLine(t, t->center_global, tc->mtx[0], 'X', DRAWLIGHT);
+ }
+ if (tc->mode & CON_AXIS1) {
+ drawLine(t, t->center_global, tc->mtx[1], 'Y', DRAWLIGHT);
+ }
+ if (tc->mode & CON_AXIS2) {
+ drawLine(t, t->center_global, tc->mtx[2], 'Z', DRAWLIGHT);
+ }
+ }
}
/* called from drawview.c, as an extra per-window draw option */
void drawPropCircle(const struct bContext *C, TransInfo *t)
{
- if (t->flag & T_PROP_EDIT) {
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- float tmat[4][4], imat[4][4];
- int depth_test_enabled;
-
- if (t->spacetype == SPACE_VIEW3D && rv3d != NULL) {
- copy_m4_m4(tmat, rv3d->viewmat);
- invert_m4_m4(imat, tmat);
- }
- else {
- unit_m4(tmat);
- unit_m4(imat);
- }
-
- GPU_matrix_push();
-
- if (t->spacetype == SPACE_VIEW3D) {
- /* pass */
- }
- else if (t->spacetype == SPACE_IMAGE) {
- GPU_matrix_scale_2f(1.0f / t->aspect[0], 1.0f / t->aspect[1]);
- }
- else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_ACTION)) {
- /* only scale y */
- rcti *mask = &t->ar->v2d.mask;
- rctf *datamask = &t->ar->v2d.cur;
- float xsize = BLI_rctf_size_x(datamask);
- float ysize = BLI_rctf_size_y(datamask);
- float xmask = BLI_rcti_size_x(mask);
- float ymask = BLI_rcti_size_y(mask);
- GPU_matrix_scale_2f(1.0f, (ysize / xsize) * (xmask / ymask));
- }
-
- depth_test_enabled = GPU_depth_test_enabled();
- if (depth_test_enabled)
- GPU_depth_test(false);
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformThemeColor(TH_GRID);
-
- set_inverted_drawing(1);
- imm_drawcircball(t->center_global, t->prop_size, imat, pos);
- set_inverted_drawing(0);
-
- immUnbindProgram();
-
- if (depth_test_enabled)
- GPU_depth_test(true);
-
- GPU_matrix_pop();
- }
+ if (t->flag & T_PROP_EDIT) {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float tmat[4][4], imat[4][4];
+ int depth_test_enabled;
+
+ if (t->spacetype == SPACE_VIEW3D && rv3d != NULL) {
+ copy_m4_m4(tmat, rv3d->viewmat);
+ invert_m4_m4(imat, tmat);
+ }
+ else {
+ unit_m4(tmat);
+ unit_m4(imat);
+ }
+
+ GPU_matrix_push();
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* pass */
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ GPU_matrix_scale_2f(1.0f / t->aspect[0], 1.0f / t->aspect[1]);
+ }
+ else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_ACTION)) {
+ /* only scale y */
+ rcti *mask = &t->ar->v2d.mask;
+ rctf *datamask = &t->ar->v2d.cur;
+ float xsize = BLI_rctf_size_x(datamask);
+ float ysize = BLI_rctf_size_y(datamask);
+ float xmask = BLI_rcti_size_x(mask);
+ float ymask = BLI_rcti_size_y(mask);
+ GPU_matrix_scale_2f(1.0f, (ysize / xsize) * (xmask / ymask));
+ }
+
+ depth_test_enabled = GPU_depth_test_enabled();
+ if (depth_test_enabled)
+ GPU_depth_test(false);
+
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_GRID);
+
+ set_inverted_drawing(1);
+ imm_drawcircball(t->center_global, t->prop_size, imat, pos);
+ set_inverted_drawing(0);
+
+ immUnbindProgram();
+
+ if (depth_test_enabled)
+ GPU_depth_test(true);
+
+ GPU_matrix_pop();
+ }
}
static void drawObjectConstraint(TransInfo *t)
{
- /* Draw the first one lighter because that's the one who controls the others.
- * Meaning the transformation is projected on that one and just copied on the others
- * constraint space.
- * In a nutshell, the object with light axis is controlled by the user and the others follow.
- * Without drawing the first light, users have little clue what they are doing.
- */
- short options = DRAWLIGHT;
- int i;
- float tmp_axismtx[3][3];
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- float co[3];
- float (*axismtx)[3];
-
- if (t->flag & T_PROP_EDIT) {
- /* we're sorted, so skip the rest */
- if (td->factor == 0.0f) {
- break;
- }
- }
-
- if (t->options & CTX_GPENCIL_STROKES) {
- /* only draw a constraint line for one point, otherwise we can't see anything */
- if ((options & DRAWLIGHT) == 0) {
- break;
- }
- }
-
- if (t->flag & T_OBJECT) {
- copy_v3_v3(co, td->ob->obmat[3]);
- axismtx = td->axismtx;
- }
- else if (t->flag & T_EDIT) {
- mul_v3_m4v3(co, tc->mat, td->center);
-
- mul_m3_m3m3(tmp_axismtx, tc->mat3_unit, td->axismtx);
- axismtx = tmp_axismtx;
- }
- else if (t->flag & T_POSE) {
- mul_v3_m4v3(co, tc->mat, td->center);
- axismtx = td->axismtx;
- }
- else {
- copy_v3_v3(co, td->center);
- axismtx = td->axismtx;
- }
-
- if (t->con.mode & CON_AXIS0) {
- drawLine(t, co, axismtx[0], 'X', options);
- }
- if (t->con.mode & CON_AXIS1) {
- drawLine(t, co, axismtx[1], 'Y', options);
- }
- if (t->con.mode & CON_AXIS2) {
- drawLine(t, co, axismtx[2], 'Z', options);
- }
- options &= ~DRAWLIGHT;
- }
- }
+ /* Draw the first one lighter because that's the one who controls the others.
+ * Meaning the transformation is projected on that one and just copied on the others
+ * constraint space.
+ * In a nutshell, the object with light axis is controlled by the user and the others follow.
+ * Without drawing the first light, users have little clue what they are doing.
+ */
+ short options = DRAWLIGHT;
+ int i;
+ float tmp_axismtx[3][3];
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ float co[3];
+ float(*axismtx)[3];
+
+ if (t->flag & T_PROP_EDIT) {
+ /* we're sorted, so skip the rest */
+ if (td->factor == 0.0f) {
+ break;
+ }
+ }
+
+ if (t->options & CTX_GPENCIL_STROKES) {
+ /* only draw a constraint line for one point, otherwise we can't see anything */
+ if ((options & DRAWLIGHT) == 0) {
+ break;
+ }
+ }
+
+ if (t->flag & T_OBJECT) {
+ copy_v3_v3(co, td->ob->obmat[3]);
+ axismtx = td->axismtx;
+ }
+ else if (t->flag & T_EDIT) {
+ mul_v3_m4v3(co, tc->mat, td->center);
+
+ mul_m3_m3m3(tmp_axismtx, tc->mat3_unit, td->axismtx);
+ axismtx = tmp_axismtx;
+ }
+ else if (t->flag & T_POSE) {
+ mul_v3_m4v3(co, tc->mat, td->center);
+ axismtx = td->axismtx;
+ }
+ else {
+ copy_v3_v3(co, td->center);
+ axismtx = td->axismtx;
+ }
+
+ if (t->con.mode & CON_AXIS0) {
+ drawLine(t, co, axismtx[0], 'X', options);
+ }
+ if (t->con.mode & CON_AXIS1) {
+ drawLine(t, co, axismtx[1], 'Y', options);
+ }
+ if (t->con.mode & CON_AXIS2) {
+ drawLine(t, co, axismtx[2], 'Z', options);
+ }
+ options &= ~DRAWLIGHT;
+ }
+ }
}
/*--------------------- START / STOP CONSTRAINTS ---------------------- */
void startConstraint(TransInfo *t)
{
- t->con.mode |= CON_APPLY;
- *t->con.text = ' ';
- t->num.idx_max = min_ii(getConstraintSpaceDimension(t) - 1, t->idx_max);
+ t->con.mode |= CON_APPLY;
+ *t->con.text = ' ';
+ t->num.idx_max = min_ii(getConstraintSpaceDimension(t) - 1, t->idx_max);
}
void stopConstraint(TransInfo *t)
{
- t->con.mode &= ~(CON_APPLY | CON_SELECT);
- *t->con.text = '\0';
- t->num.idx_max = t->idx_max;
+ t->con.mode &= ~(CON_APPLY | CON_SELECT);
+ *t->con.text = '\0';
+ t->num.idx_max = t->idx_max;
}
void getConstraintMatrix(TransInfo *t)
{
- float mat[3][3];
- invert_m3_m3(t->con.imtx, t->con.mtx);
- unit_m3(t->con.pmtx);
+ float mat[3][3];
+ invert_m3_m3(t->con.imtx, t->con.mtx);
+ unit_m3(t->con.pmtx);
- if (!(t->con.mode & CON_AXIS0)) {
- zero_v3(t->con.pmtx[0]);
- }
+ if (!(t->con.mode & CON_AXIS0)) {
+ zero_v3(t->con.pmtx[0]);
+ }
- if (!(t->con.mode & CON_AXIS1)) {
- zero_v3(t->con.pmtx[1]);
- }
+ if (!(t->con.mode & CON_AXIS1)) {
+ zero_v3(t->con.pmtx[1]);
+ }
- if (!(t->con.mode & CON_AXIS2)) {
- zero_v3(t->con.pmtx[2]);
- }
+ if (!(t->con.mode & CON_AXIS2)) {
+ zero_v3(t->con.pmtx[2]);
+ }
- mul_m3_m3m3(mat, t->con.pmtx, t->con.imtx);
- mul_m3_m3m3(t->con.pmtx, t->con.mtx, mat);
+ mul_m3_m3m3(mat, t->con.pmtx, t->con.imtx);
+ mul_m3_m3m3(t->con.pmtx, t->con.mtx, mat);
}
/*------------------------- MMB Select -------------------------------*/
void initSelectConstraint(TransInfo *t, float mtx[3][3])
{
- copy_m3_m3(t->con.mtx, mtx);
- t->con.mode |= CON_APPLY;
- t->con.mode |= CON_SELECT;
-
- setNearestAxis(t);
- t->con.drawExtra = NULL;
- t->con.applyVec = applyAxisConstraintVec;
- t->con.applySize = applyAxisConstraintSize;
- t->con.applyRot = applyAxisConstraintRot;
+ copy_m3_m3(t->con.mtx, mtx);
+ t->con.mode |= CON_APPLY;
+ t->con.mode |= CON_SELECT;
+
+ setNearestAxis(t);
+ t->con.drawExtra = NULL;
+ t->con.applyVec = applyAxisConstraintVec;
+ t->con.applySize = applyAxisConstraintSize;
+ t->con.applyRot = applyAxisConstraintRot;
}
void selectConstraint(TransInfo *t)
{
- if (t->con.mode & CON_SELECT) {
- setNearestAxis(t);
- startConstraint(t);
- }
+ if (t->con.mode & CON_SELECT) {
+ setNearestAxis(t);
+ startConstraint(t);
+ }
}
void postSelectConstraint(TransInfo *t)
{
- if (!(t->con.mode & CON_SELECT))
- return;
+ if (!(t->con.mode & CON_SELECT))
+ return;
- t->con.mode &= ~CON_AXIS0;
- t->con.mode &= ~CON_AXIS1;
- t->con.mode &= ~CON_AXIS2;
- t->con.mode &= ~CON_SELECT;
+ t->con.mode &= ~CON_AXIS0;
+ t->con.mode &= ~CON_AXIS1;
+ t->con.mode &= ~CON_AXIS2;
+ t->con.mode &= ~CON_SELECT;
- setNearestAxis(t);
+ setNearestAxis(t);
- startConstraint(t);
- t->redraw = TREDRAW_HARD;
+ startConstraint(t);
+ t->redraw = TREDRAW_HARD;
}
static void setNearestAxis2d(TransInfo *t)
{
- /* no correction needed... just use whichever one is lower */
- if (abs(t->mval[0] - t->con.imval[0]) < abs(t->mval[1] - t->con.imval[1])) {
- t->con.mode |= CON_AXIS1;
- BLI_strncpy(t->con.text, IFACE_(" along Y axis"), sizeof(t->con.text));
- }
- else {
- t->con.mode |= CON_AXIS0;
- BLI_strncpy(t->con.text, IFACE_(" along X axis"), sizeof(t->con.text));
- }
+ /* no correction needed... just use whichever one is lower */
+ if (abs(t->mval[0] - t->con.imval[0]) < abs(t->mval[1] - t->con.imval[1])) {
+ t->con.mode |= CON_AXIS1;
+ BLI_strncpy(t->con.text, IFACE_(" along Y axis"), sizeof(t->con.text));
+ }
+ else {
+ t->con.mode |= CON_AXIS0;
+ BLI_strncpy(t->con.text, IFACE_(" along X axis"), sizeof(t->con.text));
+ }
}
static void setNearestAxis3d(TransInfo *t)
{
- float zfac;
- float mvec[3], proj[3];
- float len[3];
- int i;
-
- /* calculate mouse movement */
- mvec[0] = (float)(t->mval[0] - t->con.imval[0]);
- mvec[1] = (float)(t->mval[1] - t->con.imval[1]);
- mvec[2] = 0.0f;
-
- /* We need to correct axis length for the current zoom-level of view,
- * this to prevent projected values to be clipped behind the camera
- * and to overflow the short integers.
- * The formula used is a bit stupid, just a simplification of the subtraction
- * of two 2D points 30 pixels apart (that's the last factor in the formula) after
- * 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;
-
- for (i = 0; i < 3; i++) {
- float axis[3], axis_2d[2];
-
- copy_v3_v3(axis, t->con.mtx[i]);
-
- mul_v3_fl(axis, zfac);
- /* now we can project to get window coordinate */
- add_v3_v3(axis, t->center_global);
- projectFloatView(t, axis, axis_2d);
-
- sub_v2_v2v2(axis, axis_2d, t->center2d);
- axis[2] = 0.0f;
-
- if (normalize_v3(axis) > 1e-3f) {
- project_v3_v3v3(proj, mvec, axis);
- sub_v3_v3v3(axis, mvec, proj);
- len[i] = normalize_v3(axis);
- }
- else {
- len[i] = 1e10f;
- }
- }
-
- if (len[0] <= len[1] && len[0] <= len[2]) {
- if (t->modifiers & MOD_CONSTRAINT_PLANE) {
- t->con.mode |= (CON_AXIS1 | CON_AXIS2);
- BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s X axis"), t->spacename);
- }
- else {
- t->con.mode |= CON_AXIS0;
- BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s X axis"), t->spacename);
- }
- }
- else if (len[1] <= len[0] && len[1] <= len[2]) {
- if (t->modifiers & MOD_CONSTRAINT_PLANE) {
- t->con.mode |= (CON_AXIS0 | CON_AXIS2);
- BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s Y axis"), t->spacename);
- }
- else {
- t->con.mode |= CON_AXIS1;
- BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s Y axis"), t->spacename);
- }
- }
- else if (len[2] <= len[1] && len[2] <= len[0]) {
- if (t->modifiers & MOD_CONSTRAINT_PLANE) {
- t->con.mode |= (CON_AXIS0 | CON_AXIS1);
- BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s Z axis"), t->spacename);
- }
- else {
- t->con.mode |= CON_AXIS2;
- BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s Z axis"), t->spacename);
- }
- }
+ float zfac;
+ float mvec[3], proj[3];
+ float len[3];
+ int i;
+
+ /* calculate mouse movement */
+ mvec[0] = (float)(t->mval[0] - t->con.imval[0]);
+ mvec[1] = (float)(t->mval[1] - t->con.imval[1]);
+ mvec[2] = 0.0f;
+
+ /* We need to correct axis length for the current zoom-level of view,
+ * this to prevent projected values to be clipped behind the camera
+ * and to overflow the short integers.
+ * The formula used is a bit stupid, just a simplification of the subtraction
+ * of two 2D points 30 pixels apart (that's the last factor in the formula) after
+ * 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;
+
+ for (i = 0; i < 3; i++) {
+ float axis[3], axis_2d[2];
+
+ copy_v3_v3(axis, t->con.mtx[i]);
+
+ mul_v3_fl(axis, zfac);
+ /* now we can project to get window coordinate */
+ add_v3_v3(axis, t->center_global);
+ projectFloatView(t, axis, axis_2d);
+
+ sub_v2_v2v2(axis, axis_2d, t->center2d);
+ axis[2] = 0.0f;
+
+ if (normalize_v3(axis) > 1e-3f) {
+ project_v3_v3v3(proj, mvec, axis);
+ sub_v3_v3v3(axis, mvec, proj);
+ len[i] = normalize_v3(axis);
+ }
+ else {
+ len[i] = 1e10f;
+ }
+ }
+
+ if (len[0] <= len[1] && len[0] <= len[2]) {
+ if (t->modifiers & MOD_CONSTRAINT_PLANE) {
+ t->con.mode |= (CON_AXIS1 | CON_AXIS2);
+ BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s X axis"), t->spacename);
+ }
+ else {
+ t->con.mode |= CON_AXIS0;
+ BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s X axis"), t->spacename);
+ }
+ }
+ else if (len[1] <= len[0] && len[1] <= len[2]) {
+ if (t->modifiers & MOD_CONSTRAINT_PLANE) {
+ t->con.mode |= (CON_AXIS0 | CON_AXIS2);
+ BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s Y axis"), t->spacename);
+ }
+ else {
+ t->con.mode |= CON_AXIS1;
+ BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s Y axis"), t->spacename);
+ }
+ }
+ else if (len[2] <= len[1] && len[2] <= len[0]) {
+ if (t->modifiers & MOD_CONSTRAINT_PLANE) {
+ t->con.mode |= (CON_AXIS0 | CON_AXIS1);
+ BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s Z axis"), t->spacename);
+ }
+ else {
+ t->con.mode |= CON_AXIS2;
+ BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s Z axis"), t->spacename);
+ }
+ }
}
void setNearestAxis(TransInfo *t)
{
- /* clear any prior constraint flags */
- t->con.mode &= ~CON_AXIS0;
- t->con.mode &= ~CON_AXIS1;
- t->con.mode &= ~CON_AXIS2;
-
- /* constraint setting - depends on spacetype */
- if (t->spacetype == SPACE_VIEW3D) {
- /* 3d-view */
- setNearestAxis3d(t);
- }
- else {
- /* assume that this means a 2D-Editor */
- setNearestAxis2d(t);
- }
-
- getConstraintMatrix(t);
+ /* clear any prior constraint flags */
+ t->con.mode &= ~CON_AXIS0;
+ t->con.mode &= ~CON_AXIS1;
+ t->con.mode &= ~CON_AXIS2;
+
+ /* constraint setting - depends on spacetype */
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* 3d-view */
+ setNearestAxis3d(t);
+ }
+ else {
+ /* assume that this means a 2D-Editor */
+ setNearestAxis2d(t);
+ }
+
+ getConstraintMatrix(t);
}
/*-------------- HELPER FUNCTIONS ----------------*/
int constraintModeToIndex(const TransInfo *t)
{
- if ((t->con.mode & CON_APPLY) == 0) {
- return -1;
- }
- switch (t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2)) {
- case (CON_AXIS0):
- case (CON_AXIS1 | CON_AXIS2):
- return 0;
- case (CON_AXIS1):
- case (CON_AXIS0 | CON_AXIS2):
- return 1;
- case (CON_AXIS2):
- case (CON_AXIS0 | CON_AXIS1):
- return 2;
- default:
- return -1;
- }
+ if ((t->con.mode & CON_APPLY) == 0) {
+ return -1;
+ }
+ switch (t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2)) {
+ case (CON_AXIS0):
+ case (CON_AXIS1 | CON_AXIS2):
+ return 0;
+ case (CON_AXIS1):
+ case (CON_AXIS0 | CON_AXIS2):
+ return 1;
+ case (CON_AXIS2):
+ case (CON_AXIS0 | CON_AXIS1):
+ return 2;
+ default:
+ return -1;
+ }
}
char constraintModeToChar(const TransInfo *t)
{
- int index = constraintModeToIndex(t);
- if (index == -1) {
- return '\0';
- }
- BLI_assert((uint)index < 3);
- return 'X' + index;
+ int index = constraintModeToIndex(t);
+ if (index == -1) {
+ return '\0';
+ }
+ BLI_assert((uint)index < 3);
+ return 'X' + index;
}
bool isLockConstraint(TransInfo *t)
{
- int mode = t->con.mode;
+ int mode = t->con.mode;
- if ((mode & (CON_AXIS0 | CON_AXIS1)) == (CON_AXIS0 | CON_AXIS1))
- return true;
+ if ((mode & (CON_AXIS0 | CON_AXIS1)) == (CON_AXIS0 | CON_AXIS1))
+ return true;
- if ((mode & (CON_AXIS1 | CON_AXIS2)) == (CON_AXIS1 | CON_AXIS2))
- return true;
+ if ((mode & (CON_AXIS1 | CON_AXIS2)) == (CON_AXIS1 | CON_AXIS2))
+ return true;
- if ((mode & (CON_AXIS0 | CON_AXIS2)) == (CON_AXIS0 | CON_AXIS2))
- return true;
+ if ((mode & (CON_AXIS0 | CON_AXIS2)) == (CON_AXIS0 | CON_AXIS2))
+ return true;
- return false;
+ return false;
}
/*
@@ -1148,19 +1172,19 @@ bool isLockConstraint(TransInfo *t)
int getConstraintSpaceDimension(TransInfo *t)
{
- int n = 0;
+ int n = 0;
- if (t->con.mode & CON_AXIS0)
- n++;
+ if (t->con.mode & CON_AXIS0)
+ n++;
- if (t->con.mode & CON_AXIS1)
- n++;
+ if (t->con.mode & CON_AXIS1)
+ n++;
- if (t->con.mode & CON_AXIS2)
- n++;
+ if (t->con.mode & CON_AXIS2)
+ n++;
- return n;
-/*
+ return n;
+ /*
* Someone willing to do it cryptically could do the following instead:
*
* return t->con & (CON_AXIS0|CON_AXIS1|CON_AXIS2);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 217dd194f57..b682617f348 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -102,7 +102,7 @@
#include "ED_mask.h"
#include "ED_gpencil.h"
-#include "WM_api.h" /* for WM_event_add_notifier to deal with stabilization nodes */
+#include "WM_api.h" /* for WM_event_add_notifier to deal with stabilization nodes */
#include "WM_types.h"
#include "UI_view2d.h"
@@ -123,18 +123,17 @@
*/
static 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 ((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;
+ }
}
/* when transforming islands */
struct TransIslandData {
- float co[3];
- float axismtx[3][3];
+ float co[3];
+ float axismtx[3][3];
};
/* local function prototype - for Object/Bone Constraints */
@@ -144,151 +143,160 @@ static bool constraints_list_needinv(TransInfo *t, ListBase *list);
static int trans_data_compare_dist(const void *a, const void *b)
{
- const TransData *td_a = (const TransData *)a;
- const TransData *td_b = (const TransData *)b;
+ const TransData *td_a = (const TransData *)a;
+ const TransData *td_b = (const TransData *)b;
- if (td_a->dist < td_b->dist) return -1;
- else if (td_a->dist > td_b->dist) return 1;
- else return 0;
+ if (td_a->dist < td_b->dist)
+ return -1;
+ else if (td_a->dist > td_b->dist)
+ return 1;
+ else
+ return 0;
}
static int trans_data_compare_rdist(const void *a, const void *b)
{
- const TransData *td_a = (const TransData *)a;
- const TransData *td_b = (const TransData *)b;
+ const TransData *td_a = (const TransData *)a;
+ const TransData *td_b = (const TransData *)b;
- if (td_a->rdist < td_b->rdist) return -1;
- else if (td_a->rdist > td_b->rdist) return 1;
- else return 0;
+ if (td_a->rdist < td_b->rdist)
+ return -1;
+ else if (td_a->rdist > td_b->rdist)
+ return 1;
+ else
+ return 0;
}
static void sort_trans_data_dist_container(const TransInfo *t, TransDataContainer *tc)
{
- TransData *start = tc->data;
- int i;
+ TransData *start = tc->data;
+ int i;
- for (i = 0; i < tc->data_len && start->flag & TD_SELECTED; i++) {
- start++;
- }
+ for (i = 0; i < tc->data_len && start->flag & TD_SELECTED; i++) {
+ start++;
+ }
- if (i < tc->data_len) {
- if (t->flag & T_PROP_CONNECTED) {
- qsort(start, tc->data_len - i, sizeof(TransData), trans_data_compare_dist);
- }
- else {
- qsort(start, tc->data_len - i, sizeof(TransData), trans_data_compare_rdist);
- }
- }
+ if (i < tc->data_len) {
+ if (t->flag & T_PROP_CONNECTED) {
+ qsort(start, tc->data_len - i, sizeof(TransData), trans_data_compare_dist);
+ }
+ else {
+ qsort(start, tc->data_len - i, sizeof(TransData), trans_data_compare_rdist);
+ }
+ }
}
void sort_trans_data_dist(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- sort_trans_data_dist_container(t, tc);
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ sort_trans_data_dist_container(t, tc);
+ }
}
static void sort_trans_data_container(TransDataContainer *tc)
{
- TransData *sel, *unsel;
- TransData temp;
- unsel = tc->data;
- sel = tc->data;
- sel += tc->data_len - 1;
- while (sel > unsel) {
- while (unsel->flag & TD_SELECTED) {
- unsel++;
- if (unsel == sel) {
- return;
- }
- }
- while (!(sel->flag & TD_SELECTED)) {
- sel--;
- if (unsel == sel) {
- return;
- }
- }
- temp = *unsel;
- *unsel = *sel;
- *sel = temp;
- sel--;
- unsel++;
- }
+ TransData *sel, *unsel;
+ TransData temp;
+ unsel = tc->data;
+ sel = tc->data;
+ sel += tc->data_len - 1;
+ while (sel > unsel) {
+ while (unsel->flag & TD_SELECTED) {
+ unsel++;
+ if (unsel == sel) {
+ return;
+ }
+ }
+ while (!(sel->flag & TD_SELECTED)) {
+ sel--;
+ if (unsel == sel) {
+ return;
+ }
+ }
+ temp = *unsel;
+ *unsel = *sel;
+ *sel = temp;
+ sel--;
+ unsel++;
+ }
}
static void sort_trans_data(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- sort_trans_data_container(tc);
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ sort_trans_data_container(tc);
+ }
}
/* distance calculated from not-selected vertex to nearest selected vertex
* warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
static void set_prop_dist(TransInfo *t, const bool with_dist)
{
- int a;
-
- float _proj_vec[3];
- const float *proj_vec = NULL;
-
- /* support for face-islands */
- 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;
- normalize_v3_v3(_proj_vec, rv3d->viewinv[2]);
- proj_vec = _proj_vec;
- }
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *tob = tc->data;
- for (a = 0; a < tc->data_len; a++, tob++) {
-
- tob->rdist = 0.0f; // init, it was mallocced
-
- if ((tob->flag & TD_SELECTED) == 0) {
- TransData *td;
- int i;
- float dist_sq, vec[3];
-
- tob->rdist = -1.0f; // signal for next loop
-
- for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
- if (td->flag & TD_SELECTED) {
- if (use_island) {
- sub_v3_v3v3(vec, tob->iloc, td->iloc);
- }
- else {
- sub_v3_v3v3(vec, tob->center, td->center);
- }
- mul_m3_v3(tob->mtx, vec);
-
- if (proj_vec) {
- float vec_p[3];
- project_v3_v3v3(vec_p, vec, proj_vec);
- sub_v3_v3(vec, vec_p);
- }
-
- dist_sq = len_squared_v3(vec);
- if ((tob->rdist == -1.0f) || (dist_sq < SQUARE(tob->rdist))) {
- tob->rdist = sqrtf(dist_sq);
- if (use_island) {
- copy_v3_v3(tob->center, td->center);
- copy_m3_m3(tob->axismtx, td->axismtx);
- }
- }
- }
- else {
- break; /* by definition transdata has selected items in beginning */
- }
- }
- if (with_dist) {
- tob->dist = tob->rdist;
- }
- }
- }
- }
+ int a;
+
+ float _proj_vec[3];
+ const float *proj_vec = NULL;
+
+ /* support for face-islands */
+ 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;
+ normalize_v3_v3(_proj_vec, rv3d->viewinv[2]);
+ proj_vec = _proj_vec;
+ }
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *tob = tc->data;
+ for (a = 0; a < tc->data_len; a++, tob++) {
+
+ tob->rdist = 0.0f; // init, it was mallocced
+
+ if ((tob->flag & TD_SELECTED) == 0) {
+ TransData *td;
+ int i;
+ float dist_sq, vec[3];
+
+ tob->rdist = -1.0f; // signal for next loop
+
+ for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_SELECTED) {
+ if (use_island) {
+ sub_v3_v3v3(vec, tob->iloc, td->iloc);
+ }
+ else {
+ sub_v3_v3v3(vec, tob->center, td->center);
+ }
+ mul_m3_v3(tob->mtx, vec);
+
+ if (proj_vec) {
+ float vec_p[3];
+ project_v3_v3v3(vec_p, vec, proj_vec);
+ sub_v3_v3(vec, vec_p);
+ }
+
+ dist_sq = len_squared_v3(vec);
+ if ((tob->rdist == -1.0f) || (dist_sq < SQUARE(tob->rdist))) {
+ tob->rdist = sqrtf(dist_sq);
+ if (use_island) {
+ copy_v3_v3(tob->center, td->center);
+ copy_m3_m3(tob->axismtx, td->axismtx);
+ }
+ }
+ }
+ else {
+ break; /* by definition transdata has selected items in beginning */
+ }
+ }
+ if (with_dist) {
+ tob->dist = tob->rdist;
+ }
+ }
+ }
+ }
}
/* ************************** CONVERSIONS ************************* */
@@ -297,55 +305,54 @@ static void set_prop_dist(TransInfo *t, const bool with_dist)
static void createTransTexspace(TransInfo *t)
{
- ViewLayer *view_layer = t->view_layer;
- TransData *td;
- Object *ob;
- ID *id;
- short *texflag;
+ ViewLayer *view_layer = t->view_layer;
+ TransData *td;
+ Object *ob;
+ ID *id;
+ short *texflag;
- ob = OBACT(view_layer);
+ ob = OBACT(view_layer);
- if (ob == NULL) { // Shouldn't logically happen, but still...
- return;
- }
+ if (ob == NULL) { // Shouldn't logically happen, but still...
+ return;
+ }
- id = ob->data;
- if (id == NULL || !ELEM(GS(id->name), ID_ME, ID_CU, ID_MB)) {
- BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform");
- return;
- }
+ id = ob->data;
+ if (id == NULL || !ELEM(GS(id->name), ID_ME, ID_CU, ID_MB)) {
+ BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform");
+ return;
+ }
- if (BKE_object_obdata_is_libdata(ob)) {
- BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform");
- return;
- }
+ if (BKE_object_obdata_is_libdata(ob)) {
+ BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform");
+ return;
+ }
+ {
+ BLI_assert(t->data_container_len == 1);
+ TransDataContainer *tc = t->data_container;
+ tc->data_len = 1;
+ td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace");
+ td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
+ }
- {
- BLI_assert(t->data_container_len == 1);
- TransDataContainer *tc = t->data_container;
- tc->data_len = 1;
- td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace");
- td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
- }
+ td->flag = TD_SELECTED;
+ copy_v3_v3(td->center, ob->obmat[3]);
+ td->ob = ob;
- td->flag = TD_SELECTED;
- copy_v3_v3(td->center, ob->obmat[3]);
- td->ob = ob;
+ copy_m3_m4(td->mtx, ob->obmat);
+ copy_m3_m4(td->axismtx, ob->obmat);
+ normalize_m3(td->axismtx);
+ pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
- copy_m3_m4(td->mtx, ob->obmat);
- copy_m3_m4(td->axismtx, ob->obmat);
- normalize_m3(td->axismtx);
- pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
+ if (BKE_object_obdata_texspace_get(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
+ ob->dtx |= OB_TEXSPACE;
+ *texflag &= ~ME_AUTOSPACE;
+ }
- if (BKE_object_obdata_texspace_get(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
- ob->dtx |= OB_TEXSPACE;
- *texflag &= ~ME_AUTOSPACE;
- }
-
- copy_v3_v3(td->iloc, td->loc);
- copy_v3_v3(td->ext->irot, td->ext->rot);
- copy_v3_v3(td->ext->isize, td->ext->size);
+ copy_v3_v3(td->iloc, td->loc);
+ copy_v3_v3(td->ext->irot, td->ext->rot);
+ copy_v3_v3(td->ext->isize, td->ext->size);
}
/* -------------------------------------------------------------------- */
@@ -357,87 +364,87 @@ static void createTransTexspace(TransInfo *t)
static void createTransCursor_image(TransInfo *t)
{
- TransData *td;
- SpaceImage *sima = t->sa->spacedata.first;
- float *cursor_location = sima->cursor;
+ TransData *td;
+ SpaceImage *sima = t->sa->spacedata.first;
+ float *cursor_location = sima->cursor;
- {
- BLI_assert(t->data_container_len == 1);
- TransDataContainer *tc = t->data_container;
- tc->data_len = 1;
- td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace");
- td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
- }
+ {
+ BLI_assert(t->data_container_len == 1);
+ TransDataContainer *tc = t->data_container;
+ tc->data_len = 1;
+ td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace");
+ td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
+ }
- td->flag = TD_SELECTED;
- copy_v3_v3(td->center, cursor_location);
- td->ob = NULL;
+ td->flag = TD_SELECTED;
+ copy_v3_v3(td->center, cursor_location);
+ td->ob = NULL;
- unit_m3(td->mtx);
- unit_m3(td->axismtx);
- pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
+ unit_m3(td->mtx);
+ unit_m3(td->axismtx);
+ pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
- td->loc = cursor_location;
- copy_v3_v3(td->iloc, cursor_location);
+ td->loc = cursor_location;
+ copy_v3_v3(td->iloc, cursor_location);
}
static void createTransCursor_view3d(TransInfo *t)
{
- TransData *td;
-
- Scene *scene = t->scene;
- if (ID_IS_LINKED(scene)) {
- BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform");
- return;
- }
-
- View3DCursor *cursor = &scene->cursor;
- {
- BLI_assert(t->data_container_len == 1);
- TransDataContainer *tc = t->data_container;
- tc->data_len = 1;
- td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace");
- td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
- }
-
- td->flag = TD_SELECTED;
- copy_v3_v3(td->center, cursor->location);
- td->ob = NULL;
-
- unit_m3(td->mtx);
- BKE_scene_cursor_rot_to_mat3(cursor, td->axismtx);
- normalize_m3(td->axismtx);
- pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
-
- td->loc = cursor->location;
- copy_v3_v3(td->iloc, cursor->location);
-
- if (cursor->rotation_mode > 0) {
- td->ext->rot = cursor->rotation_euler;
- td->ext->rotAxis = NULL;
- td->ext->rotAngle = NULL;
- td->ext->quat = NULL;
-
- copy_v3_v3(td->ext->irot, cursor->rotation_euler);
- }
- else if (cursor->rotation_mode == ROT_MODE_AXISANGLE) {
- td->ext->rot = NULL;
- td->ext->rotAxis = cursor->rotation_axis;
- td->ext->rotAngle = &cursor->rotation_angle;
- td->ext->quat = NULL;
-
- td->ext->irotAngle = cursor->rotation_angle;
- copy_v3_v3(td->ext->irotAxis, cursor->rotation_axis);
- }
- else {
- td->ext->rot = NULL;
- td->ext->rotAxis = NULL;
- td->ext->rotAngle = NULL;
- td->ext->quat = cursor->rotation_quaternion;
-
- copy_qt_qt(td->ext->iquat, cursor->rotation_quaternion);
- }
- td->ext->rotOrder = cursor->rotation_mode;
+ TransData *td;
+
+ Scene *scene = t->scene;
+ if (ID_IS_LINKED(scene)) {
+ BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform");
+ return;
+ }
+
+ View3DCursor *cursor = &scene->cursor;
+ {
+ BLI_assert(t->data_container_len == 1);
+ TransDataContainer *tc = t->data_container;
+ tc->data_len = 1;
+ td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace");
+ td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
+ }
+
+ td->flag = TD_SELECTED;
+ copy_v3_v3(td->center, cursor->location);
+ td->ob = NULL;
+
+ unit_m3(td->mtx);
+ BKE_scene_cursor_rot_to_mat3(cursor, td->axismtx);
+ normalize_m3(td->axismtx);
+ pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
+
+ td->loc = cursor->location;
+ copy_v3_v3(td->iloc, cursor->location);
+
+ if (cursor->rotation_mode > 0) {
+ td->ext->rot = cursor->rotation_euler;
+ td->ext->rotAxis = NULL;
+ td->ext->rotAngle = NULL;
+ td->ext->quat = NULL;
+
+ copy_v3_v3(td->ext->irot, cursor->rotation_euler);
+ }
+ else if (cursor->rotation_mode == ROT_MODE_AXISANGLE) {
+ td->ext->rot = NULL;
+ td->ext->rotAxis = cursor->rotation_axis;
+ td->ext->rotAngle = &cursor->rotation_angle;
+ td->ext->quat = NULL;
+
+ td->ext->irotAngle = cursor->rotation_angle;
+ copy_v3_v3(td->ext->irotAxis, cursor->rotation_axis);
+ }
+ else {
+ td->ext->rot = NULL;
+ td->ext->rotAxis = NULL;
+ td->ext->rotAngle = NULL;
+ td->ext->quat = cursor->rotation_quaternion;
+
+ copy_qt_qt(td->ext->iquat, cursor->rotation_quaternion);
+ }
+ td->ext->rotOrder = cursor->rotation_mode;
}
/** \} */
@@ -446,1293 +453,1308 @@ static void createTransCursor_view3d(TransInfo *t)
static void createTransEdge(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- TransData *td = NULL;
- BMEdge *eed;
- BMIter iter;
- float mtx[3][3], smtx[3][3];
- int count = 0, countsel = 0;
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
- int cd_edge_float_offset;
-
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) countsel++;
- if (is_prop_edit) count++;
- }
- }
-
- if (countsel == 0) {
- tc->data_len = 0;
- continue;
- }
-
- if (is_prop_edit) {
- tc->data_len = count;
- }
- else {
- tc->data_len = countsel;
- }
-
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransCrease");
-
- copy_m3_m4(mtx, tc->obedit->obmat);
- pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
-
- /* create data we need */
- if (t->mode == TFM_BWEIGHT) {
- BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_EDGE_BWEIGHT);
- cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT);
- }
- else { //if (t->mode == TFM_CREASE) {
- BLI_assert(t->mode == TFM_CREASE);
- BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_EDGE_CREASE);
- cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE);
- }
-
- BLI_assert(cd_edge_float_offset != -1);
-
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && (BM_elem_flag_test(eed, BM_ELEM_SELECT) || is_prop_edit)) {
- float *fl_ptr;
- /* need to set center for center calculations */
- mid_v3_v3v3(td->center, eed->v1->co, eed->v2->co);
-
- td->loc = NULL;
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT))
- td->flag = TD_SELECTED;
- else
- td->flag = 0;
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
-
- td->ext = NULL;
-
- fl_ptr = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_float_offset);
- td->val = fl_ptr;
- td->ival = *fl_ptr;
-
- td++;
- }
- }
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ TransData *td = NULL;
+ BMEdge *eed;
+ BMIter iter;
+ float mtx[3][3], smtx[3][3];
+ int count = 0, countsel = 0;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+ int cd_edge_float_offset;
+
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT))
+ countsel++;
+ if (is_prop_edit)
+ count++;
+ }
+ }
+
+ if (countsel == 0) {
+ tc->data_len = 0;
+ continue;
+ }
+
+ if (is_prop_edit) {
+ tc->data_len = count;
+ }
+ else {
+ tc->data_len = countsel;
+ }
+
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransCrease");
+
+ copy_m3_m4(mtx, tc->obedit->obmat);
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
+
+ /* create data we need */
+ if (t->mode == TFM_BWEIGHT) {
+ BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_EDGE_BWEIGHT);
+ cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT);
+ }
+ else { //if (t->mode == TFM_CREASE) {
+ BLI_assert(t->mode == TFM_CREASE);
+ BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_EDGE_CREASE);
+ cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE);
+ }
+
+ BLI_assert(cd_edge_float_offset != -1);
+
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) &&
+ (BM_elem_flag_test(eed, BM_ELEM_SELECT) || is_prop_edit)) {
+ float *fl_ptr;
+ /* need to set center for center calculations */
+ mid_v3_v3v3(td->center, eed->v1->co, eed->v2->co);
+
+ td->loc = NULL;
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT))
+ td->flag = TD_SELECTED;
+ else
+ td->flag = 0;
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+
+ td->ext = NULL;
+
+ fl_ptr = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_float_offset);
+ td->val = fl_ptr;
+ td->ival = *fl_ptr;
+
+ td++;
+ }
+ }
+ }
}
/* ********************* pose mode ************* */
static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
{
- bConstraint *con = pchan->constraints.first;
+ bConstraint *con = pchan->constraints.first;
- for (; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
- bKinematicConstraint *data = con->data;
+ for (; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC && (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;
+ if (data->tar == NULL)
+ return data;
+ if (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0)
+ return data;
+ }
+ }
+ return NULL;
}
static short apply_targetless_ik(Object *ob)
{
- bPoseChannel *pchan, *parchan, *chanlist[256];
- bKinematicConstraint *data;
- int segcount, apply = 0;
-
- /* now we got a difficult situation... we have to find the
- * target-less IK pchans, and apply transformation to the all
- * pchans that were in the chain */
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- data = has_targetless_ik(pchan);
- if (data && (data->flag & CONSTRAINT_IK_AUTO)) {
-
- /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
- segcount = 0;
-
- /* exclude tip from chain? */
- if (!(data->flag & CONSTRAINT_IK_TIP))
- parchan = pchan->parent;
- else
- parchan = pchan;
-
- /* Find the chain's root & count the segments needed */
- for (; parchan; parchan = parchan->parent) {
- chanlist[segcount] = parchan;
- segcount++;
-
- if (segcount == data->rootbone || segcount > 255) break; // 255 is weak
- }
- for (; segcount; segcount--) {
- Bone *bone;
- float rmat[4][4] /*, tmat[4][4], imat[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 ) */
-
- 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);
-
- /* 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);
-
- /* rotation */
- /* [#22409] is partially caused by this, as slight numeric error introduced during
- * the solving process leads to locked-axis values changing. However, we cannot modify
- * the values here, or else there are huge discrepancies between IK-solver (interactive)
- * and applied poses.
- */
- if (parchan->rotmode > 0)
- mat3_to_eulO(parchan->eul, parchan->rotmode, rmat3);
- else if (parchan->rotmode == ROT_MODE_AXISANGLE)
- mat3_to_axis_angle(parchan->rotAxis, &parchan->rotAngle, rmat3);
- else
- mat3_to_quat(parchan->quat, rmat3);
-
- /* for size, remove rotation */
- /* causes problems with some constraints (so apply only if needed) */
- if (data->flag & CONSTRAINT_IK_STRETCH) {
- if (parchan->rotmode > 0)
- eulO_to_mat3(qrmat, parchan->eul, parchan->rotmode);
- else if (parchan->rotmode == ROT_MODE_AXISANGLE)
- axis_angle_to_mat3(qrmat, parchan->rotAxis, parchan->rotAngle);
- else
- quat_to_mat3(qrmat, parchan->quat);
-
- invert_m3_m3(imat3, qrmat);
- mul_m3_m3m3(smat, rmat3, imat3);
- mat3_to_size(parchan->size, smat);
- }
-
- /* 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]); */
- }
-
- }
-
- apply = 1;
- data->flag &= ~CONSTRAINT_IK_AUTO;
- }
- }
-
- return apply;
-}
-
-static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransDataContainer *tc, TransData *td)
-{
- Bone *bone = pchan->bone;
- float pmat[3][3], omat[3][3];
- float cmat[3][3], tmat[3][3];
- float vec[3];
-
- copy_v3_v3(vec, pchan->pose_mat[3]);
- copy_v3_v3(td->center, vec);
-
- td->ob = ob;
- td->flag = TD_SELECTED;
- if (bone->flag & BONE_HINGE_CHILD_TRANSFORM) {
- td->flag |= TD_NOCENTER;
- }
-
- if (bone->flag & BONE_TRANSFORM_CHILD) {
- td->flag |= TD_NOCENTER;
- td->flag |= TD_NO_LOC;
- }
-
- td->protectflag = pchan->protectflag;
-
- td->loc = pchan->loc;
- copy_v3_v3(td->iloc, pchan->loc);
-
- td->ext->size = pchan->size;
- copy_v3_v3(td->ext->isize, pchan->size);
-
- if (pchan->rotmode > 0) {
- td->ext->rot = pchan->eul;
- td->ext->rotAxis = NULL;
- td->ext->rotAngle = NULL;
- td->ext->quat = NULL;
-
- copy_v3_v3(td->ext->irot, pchan->eul);
- }
- else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- td->ext->rot = NULL;
- td->ext->rotAxis = pchan->rotAxis;
- td->ext->rotAngle = &pchan->rotAngle;
- td->ext->quat = NULL;
-
- td->ext->irotAngle = pchan->rotAngle;
- copy_v3_v3(td->ext->irotAxis, pchan->rotAxis);
- }
- else {
- td->ext->rot = NULL;
- td->ext->rotAxis = NULL;
- td->ext->rotAngle = NULL;
- td->ext->quat = pchan->quat;
-
- copy_qt_qt(td->ext->iquat, pchan->quat);
- }
- td->ext->rotOrder = pchan->rotmode;
-
-
- /* proper way to get parent transform + own transform + constraints transform */
- copy_m3_m4(omat, ob->obmat);
-
- /* New code, using "generic" BKE_bone_parent_transform_calc_from_pchan(). */
- {
- BoneParentTransform bpt;
- float rpmat[3][3];
-
- BKE_bone_parent_transform_calc_from_pchan(pchan, &bpt);
- if (t->mode == TFM_TRANSLATION)
- copy_m3_m4(pmat, bpt.loc_mat);
- else
- copy_m3_m4(pmat, bpt.rotscale_mat);
-
- /* Grrr! Exceptional case: When translating pose bones that are either Hinge or NoLocal,
- * and want align snapping, we just need both loc_mat and rotscale_mat.
- * So simply always store rotscale mat in td->ext, and always use it to apply rotations...
- * Ugly to need such hacks! :/ */
- copy_m3_m4(rpmat, bpt.rotscale_mat);
-
- if (constraints_list_needinv(t, &pchan->constraints)) {
- copy_m3_m4(tmat, pchan->constinv);
- invert_m3_m3(cmat, tmat);
- mul_m3_series(td->mtx, cmat, omat, pmat);
- mul_m3_series(td->ext->r_mtx, cmat, omat, rpmat);
- }
- else {
- mul_m3_series(td->mtx, omat, pmat);
- mul_m3_series(td->ext->r_mtx, omat, rpmat);
- }
- invert_m3_m3(td->ext->r_smtx, td->ext->r_mtx);
- }
-
- pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
-
- /* exceptional case: rotate the pose bone which also applies transformation
- * when a parentless bone has BONE_NO_LOCAL_LOCATION [] */
- if (!ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE) && (pchan->bone->flag & BONE_NO_LOCAL_LOCATION)) {
- if (pchan->parent) {
- /* same as td->smtx but without pchan->bone->bone_mat */
- td->flag |= TD_PBONE_LOCAL_MTX_C;
- mul_m3_m3m3(td->ext->l_smtx, pchan->bone->bone_mat, td->smtx);
- }
- else {
- td->flag |= TD_PBONE_LOCAL_MTX_P;
- }
- }
-
- /* for axismat we use bone's own transform */
- copy_m3_m4(pmat, pchan->pose_mat);
- mul_m3_m3m3(td->axismtx, omat, pmat);
- normalize_m3(td->axismtx);
-
- if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
- bArmature *arm = tc->poseobj->data;
-
- if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) {
- td->loc = NULL;
- td->val = &bone->dist;
- td->ival = bone->dist;
- }
- else {
- // abusive storage of scale in the loc pointer :)
- td->loc = &bone->xwidth;
- copy_v3_v3(td->iloc, td->loc);
- td->val = NULL;
- }
- }
-
- /* in this case we can do target-less IK grabbing */
- if (t->mode == TFM_TRANSLATION) {
- bKinematicConstraint *data = has_targetless_ik(pchan);
- if (data) {
- if (data->flag & CONSTRAINT_IK_TIP) {
- copy_v3_v3(data->grabtarget, pchan->pose_tail);
- }
- else {
- copy_v3_v3(data->grabtarget, pchan->pose_head);
- }
- td->loc = data->grabtarget;
- copy_v3_v3(td->iloc, td->loc);
- data->flag |= CONSTRAINT_IK_AUTO;
-
- /* only object matrix correction */
- copy_m3_m3(td->mtx, omat);
- pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
- }
- }
-
- /* store reference to first constraint */
- td->con = pchan->constraints.first;
+ bPoseChannel *pchan, *parchan, *chanlist[256];
+ bKinematicConstraint *data;
+ int segcount, apply = 0;
+
+ /* now we got a difficult situation... we have to find the
+ * target-less IK pchans, and apply transformation to the all
+ * pchans that were in the chain */
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ data = has_targetless_ik(pchan);
+ if (data && (data->flag & CONSTRAINT_IK_AUTO)) {
+
+ /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
+ segcount = 0;
+
+ /* exclude tip from chain? */
+ if (!(data->flag & CONSTRAINT_IK_TIP))
+ parchan = pchan->parent;
+ else
+ parchan = pchan;
+
+ /* Find the chain's root & count the segments needed */
+ for (; parchan; parchan = parchan->parent) {
+ chanlist[segcount] = parchan;
+ segcount++;
+
+ if (segcount == data->rootbone || segcount > 255)
+ break; // 255 is weak
+ }
+ for (; segcount; segcount--) {
+ Bone *bone;
+ float rmat[4][4] /*, tmat[4][4], imat[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 ) */
+
+ 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);
+
+ /* 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);
+
+ /* rotation */
+ /* [#22409] is partially caused by this, as slight numeric error introduced during
+ * the solving process leads to locked-axis values changing. However, we cannot modify
+ * the values here, or else there are huge discrepancies between IK-solver (interactive)
+ * and applied poses.
+ */
+ if (parchan->rotmode > 0)
+ mat3_to_eulO(parchan->eul, parchan->rotmode, rmat3);
+ else if (parchan->rotmode == ROT_MODE_AXISANGLE)
+ mat3_to_axis_angle(parchan->rotAxis, &parchan->rotAngle, rmat3);
+ else
+ mat3_to_quat(parchan->quat, rmat3);
+
+ /* for size, remove rotation */
+ /* causes problems with some constraints (so apply only if needed) */
+ if (data->flag & CONSTRAINT_IK_STRETCH) {
+ if (parchan->rotmode > 0)
+ eulO_to_mat3(qrmat, parchan->eul, parchan->rotmode);
+ else if (parchan->rotmode == ROT_MODE_AXISANGLE)
+ axis_angle_to_mat3(qrmat, parchan->rotAxis, parchan->rotAngle);
+ else
+ quat_to_mat3(qrmat, parchan->quat);
+
+ invert_m3_m3(imat3, qrmat);
+ mul_m3_m3m3(smat, rmat3, imat3);
+ mat3_to_size(parchan->size, smat);
+ }
+
+ /* 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]); */
+ }
+ }
+
+ apply = 1;
+ data->flag &= ~CONSTRAINT_IK_AUTO;
+ }
+ }
+
+ return apply;
+}
+
+static void add_pose_transdata(
+ TransInfo *t, bPoseChannel *pchan, Object *ob, TransDataContainer *tc, TransData *td)
+{
+ Bone *bone = pchan->bone;
+ float pmat[3][3], omat[3][3];
+ float cmat[3][3], tmat[3][3];
+ float vec[3];
+
+ copy_v3_v3(vec, pchan->pose_mat[3]);
+ copy_v3_v3(td->center, vec);
+
+ td->ob = ob;
+ td->flag = TD_SELECTED;
+ if (bone->flag & BONE_HINGE_CHILD_TRANSFORM) {
+ td->flag |= TD_NOCENTER;
+ }
+
+ if (bone->flag & BONE_TRANSFORM_CHILD) {
+ td->flag |= TD_NOCENTER;
+ td->flag |= TD_NO_LOC;
+ }
+
+ td->protectflag = pchan->protectflag;
+
+ td->loc = pchan->loc;
+ copy_v3_v3(td->iloc, pchan->loc);
+
+ td->ext->size = pchan->size;
+ copy_v3_v3(td->ext->isize, pchan->size);
+
+ if (pchan->rotmode > 0) {
+ td->ext->rot = pchan->eul;
+ td->ext->rotAxis = NULL;
+ td->ext->rotAngle = NULL;
+ td->ext->quat = NULL;
+
+ copy_v3_v3(td->ext->irot, pchan->eul);
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ td->ext->rot = NULL;
+ td->ext->rotAxis = pchan->rotAxis;
+ td->ext->rotAngle = &pchan->rotAngle;
+ td->ext->quat = NULL;
+
+ td->ext->irotAngle = pchan->rotAngle;
+ copy_v3_v3(td->ext->irotAxis, pchan->rotAxis);
+ }
+ else {
+ td->ext->rot = NULL;
+ td->ext->rotAxis = NULL;
+ td->ext->rotAngle = NULL;
+ td->ext->quat = pchan->quat;
+
+ copy_qt_qt(td->ext->iquat, pchan->quat);
+ }
+ td->ext->rotOrder = pchan->rotmode;
+
+ /* proper way to get parent transform + own transform + constraints transform */
+ copy_m3_m4(omat, ob->obmat);
+
+ /* New code, using "generic" BKE_bone_parent_transform_calc_from_pchan(). */
+ {
+ BoneParentTransform bpt;
+ float rpmat[3][3];
+
+ BKE_bone_parent_transform_calc_from_pchan(pchan, &bpt);
+ if (t->mode == TFM_TRANSLATION)
+ copy_m3_m4(pmat, bpt.loc_mat);
+ else
+ copy_m3_m4(pmat, bpt.rotscale_mat);
+
+ /* Grrr! Exceptional case: When translating pose bones that are either Hinge or NoLocal,
+ * and want align snapping, we just need both loc_mat and rotscale_mat.
+ * So simply always store rotscale mat in td->ext, and always use it to apply rotations...
+ * Ugly to need such hacks! :/ */
+ copy_m3_m4(rpmat, bpt.rotscale_mat);
+
+ if (constraints_list_needinv(t, &pchan->constraints)) {
+ copy_m3_m4(tmat, pchan->constinv);
+ invert_m3_m3(cmat, tmat);
+ mul_m3_series(td->mtx, cmat, omat, pmat);
+ mul_m3_series(td->ext->r_mtx, cmat, omat, rpmat);
+ }
+ else {
+ mul_m3_series(td->mtx, omat, pmat);
+ mul_m3_series(td->ext->r_mtx, omat, rpmat);
+ }
+ invert_m3_m3(td->ext->r_smtx, td->ext->r_mtx);
+ }
+
+ pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
+
+ /* exceptional case: rotate the pose bone which also applies transformation
+ * when a parentless bone has BONE_NO_LOCAL_LOCATION [] */
+ if (!ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE) &&
+ (pchan->bone->flag & BONE_NO_LOCAL_LOCATION)) {
+ if (pchan->parent) {
+ /* same as td->smtx but without pchan->bone->bone_mat */
+ td->flag |= TD_PBONE_LOCAL_MTX_C;
+ mul_m3_m3m3(td->ext->l_smtx, pchan->bone->bone_mat, td->smtx);
+ }
+ else {
+ td->flag |= TD_PBONE_LOCAL_MTX_P;
+ }
+ }
+
+ /* for axismat we use bone's own transform */
+ copy_m3_m4(pmat, pchan->pose_mat);
+ mul_m3_m3m3(td->axismtx, omat, pmat);
+ normalize_m3(td->axismtx);
+
+ if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
+ bArmature *arm = tc->poseobj->data;
+
+ if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) {
+ td->loc = NULL;
+ td->val = &bone->dist;
+ td->ival = bone->dist;
+ }
+ else {
+ // abusive storage of scale in the loc pointer :)
+ td->loc = &bone->xwidth;
+ copy_v3_v3(td->iloc, td->loc);
+ td->val = NULL;
+ }
+ }
+
+ /* in this case we can do target-less IK grabbing */
+ if (t->mode == TFM_TRANSLATION) {
+ bKinematicConstraint *data = has_targetless_ik(pchan);
+ if (data) {
+ if (data->flag & CONSTRAINT_IK_TIP) {
+ copy_v3_v3(data->grabtarget, pchan->pose_tail);
+ }
+ else {
+ copy_v3_v3(data->grabtarget, pchan->pose_head);
+ }
+ td->loc = data->grabtarget;
+ copy_v3_v3(td->iloc, td->loc);
+ data->flag |= CONSTRAINT_IK_AUTO;
+
+ /* only object matrix correction */
+ copy_m3_m3(td->mtx, omat);
+ pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
+ }
+ }
+
+ /* store reference to first constraint */
+ td->con = pchan->constraints.first;
}
static void bone_children_clear_transflag(int mode, short around, ListBase *lb)
{
- Bone *bone = lb->first;
+ Bone *bone = lb->first;
- for (; bone; bone = bone->next) {
- if ((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED)) {
- bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
- }
- else if ((bone->flag & BONE_TRANSFORM) &&
- (mode == TFM_ROTATION || mode == TFM_TRACKBALL) &&
- (around == V3D_AROUND_LOCAL_ORIGINS))
- {
- bone->flag |= BONE_TRANSFORM_CHILD;
- }
- else {
- bone->flag &= ~BONE_TRANSFORM;
- }
+ for (; bone; bone = bone->next) {
+ if ((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED)) {
+ bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
+ }
+ else if ((bone->flag & BONE_TRANSFORM) && (mode == TFM_ROTATION || mode == TFM_TRACKBALL) &&
+ (around == V3D_AROUND_LOCAL_ORIGINS)) {
+ bone->flag |= BONE_TRANSFORM_CHILD;
+ }
+ else {
+ bone->flag &= ~BONE_TRANSFORM;
+ }
- bone_children_clear_transflag(mode, around, &bone->childbase);
- }
+ bone_children_clear_transflag(mode, around, &bone->childbase);
+ }
}
/* 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])
-{
- bArmature *arm = ob->data;
- bPoseChannel *pchan;
- Bone *bone;
- int total = 0;
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- bone = pchan->bone;
- 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 */
- /* since pchans are depsgraph sorted, the parents are in beginning of list */
- if (!ELEM(mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- bone = pchan->bone;
- if (bone->flag & BONE_TRANSFORM)
- bone_children_clear_transflag(mode, around, &bone->childbase);
- }
- }
- /* now count, and check if we have autoIK or have to switch from translate to rotate */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- bone = pchan->bone;
- if (bone->flag & BONE_TRANSFORM) {
- total++;
-
- if (has_translate_rotate != NULL) {
- if (has_targetless_ik(pchan) == NULL) {
- if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
- if (pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM) {
- has_translate_rotate[0] = true;
- }
- }
- else {
- if ((pchan->protectflag & OB_LOCK_LOC) != OB_LOCK_LOC) {
- has_translate_rotate[0] = true;
- }
- }
- if ((pchan->protectflag & OB_LOCK_ROT) != OB_LOCK_ROT) {
- has_translate_rotate[1] = true;
- }
- }
- else {
- has_translate_rotate[0] = true;
- }
- }
- }
- }
-
- return total;
+int count_set_pose_transflags(Object *ob,
+ const int mode,
+ const short around,
+ bool has_translate_rotate[2])
+{
+ bArmature *arm = ob->data;
+ bPoseChannel *pchan;
+ Bone *bone;
+ int total = 0;
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ bone = pchan->bone;
+ 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 */
+ /* since pchans are depsgraph sorted, the parents are in beginning of list */
+ if (!ELEM(mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ bone = pchan->bone;
+ if (bone->flag & BONE_TRANSFORM)
+ bone_children_clear_transflag(mode, around, &bone->childbase);
+ }
+ }
+ /* now count, and check if we have autoIK or have to switch from translate to rotate */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ bone = pchan->bone;
+ if (bone->flag & BONE_TRANSFORM) {
+ total++;
+
+ if (has_translate_rotate != NULL) {
+ if (has_targetless_ik(pchan) == NULL) {
+ if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
+ if (pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM) {
+ has_translate_rotate[0] = true;
+ }
+ }
+ else {
+ if ((pchan->protectflag & OB_LOCK_LOC) != OB_LOCK_LOC) {
+ has_translate_rotate[0] = true;
+ }
+ }
+ if ((pchan->protectflag & OB_LOCK_ROT) != OB_LOCK_ROT) {
+ has_translate_rotate[1] = true;
+ }
+ }
+ else {
+ has_translate_rotate[0] = true;
+ }
+ }
+ }
+ }
+
+ return total;
}
-
/* -------- Auto-IK ---------- */
/* adjust pose-channel's auto-ik chainlen */
static bool pchan_autoik_adjust(bPoseChannel *pchan, short chainlen)
{
- bConstraint *con;
- bool changed = false;
-
- /* don't bother to search if no valid constraints */
- if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0) {
- return changed;
- }
-
- /* check if pchan has ik-constraint */
- for (con = pchan->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
- bKinematicConstraint *data = con->data;
-
- /* only accept if a temporary one (for auto-ik) */
- if (data->flag & CONSTRAINT_IK_TEMP) {
- /* chainlen is new chainlen, but is limited by maximum chainlen */
- const int old_rootbone = data->rootbone;
- if ((chainlen == 0) || (chainlen > data->max_rootbone)) {
- data->rootbone = data->max_rootbone;
- }
- else {
- data->rootbone = chainlen;
- }
- changed |= (data->rootbone != old_rootbone);
- }
- }
- }
-
- return changed;
+ bConstraint *con;
+ bool changed = false;
+
+ /* don't bother to search if no valid constraints */
+ if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0) {
+ return changed;
+ }
+
+ /* check if pchan has ik-constraint */
+ for (con = pchan->constraints.first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
+ bKinematicConstraint *data = con->data;
+
+ /* only accept if a temporary one (for auto-ik) */
+ if (data->flag & CONSTRAINT_IK_TEMP) {
+ /* chainlen is new chainlen, but is limited by maximum chainlen */
+ const int old_rootbone = data->rootbone;
+ if ((chainlen == 0) || (chainlen > data->max_rootbone)) {
+ data->rootbone = data->max_rootbone;
+ }
+ else {
+ data->rootbone = chainlen;
+ }
+ changed |= (data->rootbone != old_rootbone);
+ }
+ }
+ }
+
+ return changed;
}
/* change the chain-length of auto-ik */
void transform_autoik_update(TransInfo *t, short mode)
{
- Main *bmain = CTX_data_main(t->context);
-
- short *chainlen = &t->settings->autoik_chainlen;
- bPoseChannel *pchan;
-
- /* mode determines what change to apply to chainlen */
- if (mode == 1) {
- /* mode=1 is from WHEELMOUSEDOWN... increases len */
- (*chainlen)++;
- }
- else if (mode == -1) {
- /* mode==-1 is from WHEELMOUSEUP... decreases len */
- if (*chainlen > 0) {
- (*chainlen)--;
- }
- else {
- /* IK length did not change, skip updates. */
- return;
- }
- }
-
- /* apply to all pose-channels */
- bool changed = false;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
- /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
- if (ELEM(NULL, tc->poseobj, tc->poseobj->pose)) {
- continue;
- }
-
- for (pchan = tc->poseobj->pose->chanbase.first; pchan; pchan = pchan->next) {
- changed |= pchan_autoik_adjust(pchan, *chainlen);
- }
- }
-
- if (changed) {
- /* TODO(sergey): Consider doing partial update only. */
- DEG_relations_tag_update(bmain);
- }
+ Main *bmain = CTX_data_main(t->context);
+
+ short *chainlen = &t->settings->autoik_chainlen;
+ bPoseChannel *pchan;
+
+ /* mode determines what change to apply to chainlen */
+ if (mode == 1) {
+ /* mode=1 is from WHEELMOUSEDOWN... increases len */
+ (*chainlen)++;
+ }
+ else if (mode == -1) {
+ /* mode==-1 is from WHEELMOUSEUP... decreases len */
+ if (*chainlen > 0) {
+ (*chainlen)--;
+ }
+ else {
+ /* IK length did not change, skip updates. */
+ return;
+ }
+ }
+
+ /* apply to all pose-channels */
+ bool changed = false;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+
+ /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
+ if (ELEM(NULL, tc->poseobj, tc->poseobj->pose)) {
+ continue;
+ }
+
+ for (pchan = tc->poseobj->pose->chanbase.first; pchan; pchan = pchan->next) {
+ changed |= pchan_autoik_adjust(pchan, *chainlen);
+ }
+ }
+
+ if (changed) {
+ /* TODO(sergey): Consider doing partial update only. */
+ DEG_relations_tag_update(bmain);
+ }
}
/* frees temporal IKs */
static void pose_grab_with_ik_clear(Main *bmain, Object *ob)
{
- bKinematicConstraint *data;
- bPoseChannel *pchan;
- bConstraint *con, *next;
- bool relations_changed = false;
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- /* clear all temporary lock flags */
- pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP | BONE_IK_NO_YDOF_TEMP | BONE_IK_NO_ZDOF_TEMP);
-
- pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_TARGET);
-
- /* remove all temporary IK-constraints added */
- for (con = pchan->constraints.first; con; con = next) {
- next = con->next;
- if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
- data = con->data;
- if (data->flag & CONSTRAINT_IK_TEMP) {
- relations_changed = true;
-
- /* iTaSC needs clear for removed constraints */
- BIK_clear_data(ob->pose);
-
- BLI_remlink(&pchan->constraints, con);
- MEM_freeN(con->data);
- MEM_freeN(con);
- continue;
- }
- pchan->constflag |= PCHAN_HAS_IK;
- if (data->tar == NULL || (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0))
- pchan->constflag |= PCHAN_HAS_TARGET;
- }
- }
- }
-
- if (relations_changed) {
- /* TODO(sergey): Consider doing partial update only. */
- DEG_relations_tag_update(bmain);
- }
+ bKinematicConstraint *data;
+ bPoseChannel *pchan;
+ bConstraint *con, *next;
+ bool relations_changed = false;
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ /* clear all temporary lock flags */
+ pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP | BONE_IK_NO_YDOF_TEMP | BONE_IK_NO_ZDOF_TEMP);
+
+ pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_TARGET);
+
+ /* remove all temporary IK-constraints added */
+ for (con = pchan->constraints.first; con; con = next) {
+ next = con->next;
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
+ data = con->data;
+ if (data->flag & CONSTRAINT_IK_TEMP) {
+ relations_changed = true;
+
+ /* iTaSC needs clear for removed constraints */
+ BIK_clear_data(ob->pose);
+
+ BLI_remlink(&pchan->constraints, con);
+ MEM_freeN(con->data);
+ MEM_freeN(con);
+ continue;
+ }
+ pchan->constflag |= PCHAN_HAS_IK;
+ if (data->tar == NULL || (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0))
+ pchan->constflag |= PCHAN_HAS_TARGET;
+ }
+ }
+ }
+
+ if (relations_changed) {
+ /* TODO(sergey): Consider doing partial update only. */
+ DEG_relations_tag_update(bmain);
+ }
}
/* adds the IK to pchan - returns if added */
static short pose_grab_with_ik_add(bPoseChannel *pchan)
{
- bKinematicConstraint *targetless = NULL;
- bKinematicConstraint *data;
- bConstraint *con;
-
- /* Sanity check */
- if (pchan == NULL)
- return 0;
-
- /* 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) {
- data = con->data;
-
- if (data->tar == NULL || (data->tar->type == OB_ARMATURE && data->subtarget[0] == '\0')) {
- /* make reference to constraint to base things off later
- * (if it's the last targetless constraint encountered) */
- targetless = (bKinematicConstraint *)con->data;
-
- /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
- if (con->enforce != 0.0f) {
- data->flag |= CONSTRAINT_IK_AUTO;
-
- /* if no chain length has been specified,
- * just make things obey standard rotation locks too */
- if (data->rootbone == 0) {
- for (; pchan; pchan = pchan->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->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
- if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
- }
- }
-
- return 0;
- }
- }
-
- if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f))
- return 0;
- }
- }
-
- con = BKE_constraint_add_for_pose(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC);
-
- /* 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
- * same bone for the first time through the loop T25885. */
- data->rootbone = 0;
-
- /* we only include bones that are part of a continual connected chain */
- do {
- /* 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->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
- if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
-
- /* now we count this pchan as being included */
- data->rootbone++;
-
- /* continue to parent, but only if we're connected to it */
- if (pchan->bone->flag & BONE_CONNECTED)
- pchan = pchan->parent;
- else
- pchan = NULL;
- } while (pchan);
-
- /* make a copy of maximum chain-length */
- data->max_rootbone = data->rootbone;
-
- return 1;
+ bKinematicConstraint *targetless = NULL;
+ bKinematicConstraint *data;
+ bConstraint *con;
+
+ /* Sanity check */
+ if (pchan == NULL)
+ return 0;
+
+ /* 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) {
+ data = con->data;
+
+ if (data->tar == NULL || (data->tar->type == OB_ARMATURE && data->subtarget[0] == '\0')) {
+ /* make reference to constraint to base things off later
+ * (if it's the last targetless constraint encountered) */
+ targetless = (bKinematicConstraint *)con->data;
+
+ /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
+ if (con->enforce != 0.0f) {
+ data->flag |= CONSTRAINT_IK_AUTO;
+
+ /* if no chain length has been specified,
+ * just make things obey standard rotation locks too */
+ if (data->rootbone == 0) {
+ for (; pchan; pchan = pchan->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->protectflag & OB_LOCK_ROTY)
+ pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
+ if (pchan->protectflag & OB_LOCK_ROTZ)
+ pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
+ }
+ }
+
+ return 0;
+ }
+ }
+
+ if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f))
+ return 0;
+ }
+ }
+
+ con = BKE_constraint_add_for_pose(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC);
+
+ /* 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
+ * same bone for the first time through the loop T25885. */
+ data->rootbone = 0;
+
+ /* we only include bones that are part of a continual connected chain */
+ do {
+ /* 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->protectflag & OB_LOCK_ROTY)
+ pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
+ if (pchan->protectflag & OB_LOCK_ROTZ)
+ pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
+
+ /* now we count this pchan as being included */
+ data->rootbone++;
+
+ /* continue to parent, but only if we're connected to it */
+ if (pchan->bone->flag & BONE_CONNECTED)
+ pchan = pchan->parent;
+ else
+ pchan = NULL;
+ } while (pchan);
+
+ /* make a copy of maximum chain-length */
+ data->max_rootbone = data->rootbone;
+
+ return 1;
}
/* bone is a candidate to get IK, but we don't do it if it has children connected */
static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
{
- Bone *bonec;
- short wentdeeper = 0, added = 0;
+ Bone *bonec;
+ short wentdeeper = 0, added = 0;
- /* go deeper if children & children are connected */
- for (bonec = bone->childbase.first; bonec; bonec = bonec->next) {
- if (bonec->flag & BONE_CONNECTED) {
- wentdeeper = 1;
- added += pose_grab_with_ik_children(pose, bonec);
- }
- }
- if (wentdeeper == 0) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
- if (pchan)
- added += pose_grab_with_ik_add(pchan);
- }
+ /* go deeper if children & children are connected */
+ for (bonec = bone->childbase.first; bonec; bonec = bonec->next) {
+ if (bonec->flag & BONE_CONNECTED) {
+ wentdeeper = 1;
+ added += pose_grab_with_ik_children(pose, bonec);
+ }
+ }
+ if (wentdeeper == 0) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
+ if (pchan)
+ added += pose_grab_with_ik_add(pchan);
+ }
- return added;
+ return added;
}
/* main call which adds temporal IK chains */
static short pose_grab_with_ik(Main *bmain, Object *ob)
{
- bArmature *arm;
- bPoseChannel *pchan, *parent;
- Bone *bonec;
- short tot_ik = 0;
-
- if ((ob == NULL) || (ob->pose == NULL) || (ob->mode & OB_MODE_POSE) == 0)
- return 0;
-
- arm = ob->data;
-
- /* Rule: allow multiple Bones
- * (but they must be selected, and only one ik-solver per chain should get added) */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->layer & arm->layer) {
- if (pchan->bone->flag & BONE_SELECTED) {
- /* Rule: no IK for solitatry (unconnected) bones */
- for (bonec = pchan->bone->childbase.first; bonec; bonec = bonec->next) {
- if (bonec->flag & BONE_CONNECTED) {
- break;
- }
- }
- if ((pchan->bone->flag & BONE_CONNECTED) == 0 && (bonec == NULL))
- continue;
-
- /* rule: if selected Bone is not a root bone, it gets a temporal IK */
- if (pchan->parent) {
- /* only adds if there's no IK yet (and no parent bone was selected) */
- for (parent = pchan->parent; parent; parent = parent->parent) {
- if (parent->bone->flag & BONE_SELECTED)
- break;
- }
- if (parent == NULL)
- tot_ik += pose_grab_with_ik_add(pchan);
- }
- else {
- /* rule: go over the children and add IK to the tips */
- tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
- }
- }
- }
- }
-
- /* 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);
- }
-
- return (tot_ik) ? 1 : 0;
+ bArmature *arm;
+ bPoseChannel *pchan, *parent;
+ Bone *bonec;
+ short tot_ik = 0;
+
+ if ((ob == NULL) || (ob->pose == NULL) || (ob->mode & OB_MODE_POSE) == 0)
+ return 0;
+
+ arm = ob->data;
+
+ /* Rule: allow multiple Bones
+ * (but they must be selected, and only one ik-solver per chain should get added) */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->bone->layer & arm->layer) {
+ if (pchan->bone->flag & BONE_SELECTED) {
+ /* Rule: no IK for solitatry (unconnected) bones */
+ for (bonec = pchan->bone->childbase.first; bonec; bonec = bonec->next) {
+ if (bonec->flag & BONE_CONNECTED) {
+ break;
+ }
+ }
+ if ((pchan->bone->flag & BONE_CONNECTED) == 0 && (bonec == NULL))
+ continue;
+
+ /* rule: if selected Bone is not a root bone, it gets a temporal IK */
+ if (pchan->parent) {
+ /* only adds if there's no IK yet (and no parent bone was selected) */
+ for (parent = pchan->parent; parent; parent = parent->parent) {
+ if (parent->bone->flag & BONE_SELECTED)
+ break;
+ }
+ if (parent == NULL)
+ tot_ik += pose_grab_with_ik_add(pchan);
+ }
+ else {
+ /* rule: go over the children and add IK to the tips */
+ tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
+ }
+ }
+ }
+ }
+
+ /* 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);
+ }
+
+ return (tot_ik) ? 1 : 0;
}
-
/**
* When objects array is NULL, use 't->data_container' as is.
*/
static void createTransPose(TransInfo *t)
{
- Main *bmain = CTX_data_main(t->context);
-
- t->data_len_all = 0;
-
- bool has_translate_rotate_buf[2] = {false, false};
- bool *has_translate_rotate = (t->mode == TFM_TRANSLATION) ? has_translate_rotate_buf : NULL;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- Object *ob = tc->poseobj;
-
- bArmature *arm;
- short ik_on = 0;
-
- /* check validity of state */
- arm = BKE_armature_from_object(tc->poseobj);
- if ((arm == NULL) || (ob->pose == NULL)) {
- continue;
- }
-
- /* set flags and count total */
- tc->data_len = count_set_pose_transflags(ob, t->mode, t->around, has_translate_rotate);
- if (tc->data_len == 0) {
- continue;
- }
-
- if (arm->flag & ARM_RESTPOS) {
- if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE) == 0) {
- BKE_report(t->reports, RPT_ERROR, "Cannot change Pose when 'Rest Position' is enabled");
- tc->data_len = 0;
- continue;
- }
- }
-
- /* do we need to add temporal IK chains? */
- if ((arm->flag & ARM_AUTO_IK) && t->mode == TFM_TRANSLATION) {
- ik_on = pose_grab_with_ik(bmain, ob);
- if (ik_on) {
- t->flag |= T_AUTOIK;
- has_translate_rotate[0] = true;
- }
- }
- }
-
- /* if there are no translatable bones, do rotation */
- if ((t->mode == TFM_TRANSLATION) && !has_translate_rotate[0]) {
- if (has_translate_rotate[1]) {
- t->mode = TFM_ROTATION;
- }
- else {
- t->mode = TFM_RESIZE;
- }
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- if (tc->data_len == 0) {
- continue;
- }
- Object *ob = tc->poseobj;
- TransData *td;
- TransDataExtension *tdx;
- short ik_on = 0;
- int i;
-
- tc->poseobj = ob; /* we also allow non-active objects to be transformed, in weightpaint */
-
- /* init trans data */
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransPoseBone");
- tdx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), "TransPoseBoneExt");
- for (i = 0; i < tc->data_len; i++, td++, tdx++) {
- td->ext = tdx;
- td->val = NULL;
- }
-
- /* use pose channels to fill trans data */
- td = tc->data;
- for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->flag & BONE_TRANSFORM) {
- add_pose_transdata(t, pchan, ob, tc, td);
- td++;
- }
- }
-
- if (td != (tc->data + tc->data_len)) {
- BKE_report(t->reports, RPT_DEBUG, "Bone selection count error");
- }
-
- /* initialize initial auto=ik chainlen's? */
- if (ik_on) {
- transform_autoik_update(t, 0);
- }
- }
-
- t->flag |= T_POSE;
- /* disable PET, its not usable in pose mode yet [#32444] */
- t->flag &= ~T_PROP_EDIT_ALL;
-
+ Main *bmain = CTX_data_main(t->context);
+
+ t->data_len_all = 0;
+
+ bool has_translate_rotate_buf[2] = {false, false};
+ bool *has_translate_rotate = (t->mode == TFM_TRANSLATION) ? has_translate_rotate_buf : NULL;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ Object *ob = tc->poseobj;
+
+ bArmature *arm;
+ short ik_on = 0;
+
+ /* check validity of state */
+ arm = BKE_armature_from_object(tc->poseobj);
+ if ((arm == NULL) || (ob->pose == NULL)) {
+ continue;
+ }
+
+ /* set flags and count total */
+ tc->data_len = count_set_pose_transflags(ob, t->mode, t->around, has_translate_rotate);
+ if (tc->data_len == 0) {
+ continue;
+ }
+
+ if (arm->flag & ARM_RESTPOS) {
+ if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE) == 0) {
+ BKE_report(t->reports, RPT_ERROR, "Cannot change Pose when 'Rest Position' is enabled");
+ tc->data_len = 0;
+ continue;
+ }
+ }
+
+ /* do we need to add temporal IK chains? */
+ if ((arm->flag & ARM_AUTO_IK) && t->mode == TFM_TRANSLATION) {
+ ik_on = pose_grab_with_ik(bmain, ob);
+ if (ik_on) {
+ t->flag |= T_AUTOIK;
+ has_translate_rotate[0] = true;
+ }
+ }
+ }
+
+ /* if there are no translatable bones, do rotation */
+ if ((t->mode == TFM_TRANSLATION) && !has_translate_rotate[0]) {
+ if (has_translate_rotate[1]) {
+ t->mode = TFM_ROTATION;
+ }
+ else {
+ t->mode = TFM_RESIZE;
+ }
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ if (tc->data_len == 0) {
+ continue;
+ }
+ Object *ob = tc->poseobj;
+ TransData *td;
+ TransDataExtension *tdx;
+ short ik_on = 0;
+ int i;
+
+ tc->poseobj = ob; /* we also allow non-active objects to be transformed, in weightpaint */
+
+ /* init trans data */
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransPoseBone");
+ tdx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension),
+ "TransPoseBoneExt");
+ for (i = 0; i < tc->data_len; i++, td++, tdx++) {
+ td->ext = tdx;
+ td->val = NULL;
+ }
+
+ /* use pose channels to fill trans data */
+ td = tc->data;
+ for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->bone->flag & BONE_TRANSFORM) {
+ add_pose_transdata(t, pchan, ob, tc, td);
+ td++;
+ }
+ }
+
+ if (td != (tc->data + tc->data_len)) {
+ BKE_report(t->reports, RPT_DEBUG, "Bone selection count error");
+ }
+
+ /* initialize initial auto=ik chainlen's? */
+ if (ik_on) {
+ transform_autoik_update(t, 0);
+ }
+ }
+
+ t->flag |= T_POSE;
+ /* disable PET, its not usable in pose mode yet [#32444] */
+ t->flag &= ~T_PROP_EDIT_ALL;
}
void restoreBones(TransDataContainer *tc)
{
- bArmature *arm = tc->obedit->data;
- BoneInitData *bid = tc->custom.type.data;
- EditBone *ebo;
+ bArmature *arm = tc->obedit->data;
+ BoneInitData *bid = tc->custom.type.data;
+ EditBone *ebo;
- while (bid->bone) {
- ebo = bid->bone;
+ while (bid->bone) {
+ ebo = bid->bone;
- ebo->dist = bid->dist;
- ebo->rad_tail = bid->rad_tail;
- ebo->roll = bid->roll;
- ebo->xwidth = bid->xwidth;
- ebo->zwidth = bid->zwidth;
- copy_v3_v3(ebo->head, bid->head);
- copy_v3_v3(ebo->tail, bid->tail);
+ ebo->dist = bid->dist;
+ ebo->rad_tail = bid->rad_tail;
+ ebo->roll = bid->roll;
+ ebo->xwidth = bid->xwidth;
+ ebo->zwidth = bid->zwidth;
+ copy_v3_v3(ebo->head, bid->head);
+ copy_v3_v3(ebo->tail, bid->tail);
- if (arm->flag & ARM_MIRROR_EDIT) {
- EditBone *ebo_child;
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ EditBone *ebo_child;
- /* Also move connected ebo_child, in case ebo_child's name aren't mirrored properly */
- for (ebo_child = arm->edbo->first; ebo_child; ebo_child = ebo_child->next) {
- if ((ebo_child->flag & BONE_CONNECTED) && (ebo_child->parent == ebo)) {
- copy_v3_v3(ebo_child->head, ebo->tail);
- ebo_child->rad_head = ebo->rad_tail;
- }
- }
+ /* Also move connected ebo_child, in case ebo_child's name aren't mirrored properly */
+ for (ebo_child = arm->edbo->first; ebo_child; ebo_child = ebo_child->next) {
+ if ((ebo_child->flag & BONE_CONNECTED) && (ebo_child->parent == ebo)) {
+ copy_v3_v3(ebo_child->head, ebo->tail);
+ ebo_child->rad_head = ebo->rad_tail;
+ }
+ }
- /* Also move connected parent, in case parent's name isn't mirrored properly */
- if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
- EditBone *parent = ebo->parent;
- copy_v3_v3(parent->tail, ebo->head);
- parent->rad_tail = ebo->rad_head;
- }
- }
+ /* Also move connected parent, in case parent's name isn't mirrored properly */
+ if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
+ EditBone *parent = ebo->parent;
+ copy_v3_v3(parent->tail, ebo->head);
+ parent->rad_tail = ebo->rad_head;
+ }
+ }
- bid++;
- }
+ bid++;
+ }
}
-
/* ********************* armature ************** */
static void createTransArmatureVerts(TransInfo *t)
{
- t->data_len_all = 0;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- EditBone *ebo, *eboflip;
- bArmature *arm = tc->obedit->data;
- ListBase *edbo = arm->edbo;
- bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
- int total_mirrored = 0;
-
- tc->data_len = 0;
- for (ebo = edbo->first; ebo; ebo = ebo->next) {
- const int data_len_prev = tc->data_len;
-
- if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
- if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
- if (ebo->flag & BONE_SELECTED)
- tc->data_len++;
- }
- else if (t->mode == TFM_BONE_ROLL) {
- if (ebo->flag & BONE_SELECTED)
- tc->data_len++;
- }
- else {
- if (ebo->flag & BONE_TIPSEL)
- tc->data_len++;
- if (ebo->flag & BONE_ROOTSEL)
- tc->data_len++;
- }
- }
-
- if (mirror && (data_len_prev < tc->data_len)) {
- eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
- if (eboflip)
- total_mirrored++;
- }
- }
- if (!tc->data_len) {
- continue;
- }
-
- if (mirror) {
- BoneInitData *bid = MEM_mallocN((total_mirrored + 1) * sizeof(BoneInitData), "BoneInitData");
-
- /* trick to terminate iteration */
- bid[total_mirrored].bone = NULL;
-
- tc->custom.type.data = bid;
- tc->custom.type.use_free = true;
- }
- t->data_len_all += tc->data_len;
- }
-
- transform_around_single_fallback(t);
- t->data_len_all = -1;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- if (!tc->data_len) {
- continue;
- }
-
- EditBone *ebo, *eboflip;
- bArmature *arm = tc->obedit->data;
- ListBase *edbo = arm->edbo;
- TransData *td, *td_old;
- float mtx[3][3], smtx[3][3], bonemat[3][3];
- bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
- BoneInitData *bid = tc->custom.type.data;
-
- copy_m3_m4(mtx, tc->obedit->obmat);
- pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
-
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransEditBone");
- int i = 0;
-
- for (ebo = edbo->first; ebo; ebo = ebo->next) {
- td_old = td;
- ebo->oldlength = ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
-
- if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
- if (t->mode == TFM_BONE_ENVELOPE) {
- if (ebo->flag & BONE_ROOTSEL) {
- td->val = &ebo->rad_head;
- td->ival = *td->val;
-
- copy_v3_v3(td->center, ebo->head);
- td->flag = TD_SELECTED;
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
-
- td->loc = NULL;
- td->ext = NULL;
- td->ob = tc->obedit;
-
- td++;
- }
- if (ebo->flag & BONE_TIPSEL) {
- td->val = &ebo->rad_tail;
- td->ival = *td->val;
- copy_v3_v3(td->center, ebo->tail);
- td->flag = TD_SELECTED;
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
-
- td->loc = NULL;
- td->ext = NULL;
- td->ob = tc->obedit;
-
- td++;
- }
-
- }
- else if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
- if (ebo->flag & BONE_SELECTED) {
- if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) {
- td->loc = NULL;
- td->val = &ebo->dist;
- td->ival = ebo->dist;
- }
- else {
- // abusive storage of scale in the loc pointer :)
- td->loc = &ebo->xwidth;
- copy_v3_v3(td->iloc, td->loc);
- td->val = NULL;
- }
- copy_v3_v3(td->center, ebo->head);
- td->flag = TD_SELECTED;
-
- /* use local bone matrix */
- ED_armature_ebone_to_mat3(ebo, bonemat);
- mul_m3_m3m3(td->mtx, mtx, bonemat);
- invert_m3_m3(td->smtx, td->mtx);
-
- copy_m3_m3(td->axismtx, td->mtx);
- normalize_m3(td->axismtx);
-
- td->ext = NULL;
- td->ob = tc->obedit;
-
- td++;
- }
- }
- else if (t->mode == TFM_BONE_ROLL) {
- if (ebo->flag & BONE_SELECTED) {
- td->loc = NULL;
- td->val = &(ebo->roll);
- td->ival = ebo->roll;
-
- copy_v3_v3(td->center, ebo->head);
- td->flag = TD_SELECTED;
-
- td->ext = NULL;
- td->ob = tc->obedit;
-
- td++;
- }
- }
- else {
- if (ebo->flag & BONE_TIPSEL) {
- copy_v3_v3(td->iloc, ebo->tail);
-
- /* Don't allow single selected tips to have a modified center,
- * causes problem with snapping (see T45974).
- * However, in rotation mode, we want to keep that 'rotate bone around root with
- * only its tip selected' behavior (see T46325). */
- if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
- ((t->mode == TFM_ROTATION) || (ebo->flag & BONE_ROOTSEL)))
- {
- copy_v3_v3(td->center, ebo->head);
- }
- else {
- copy_v3_v3(td->center, td->iloc);
- }
-
- td->loc = ebo->tail;
- td->flag = TD_SELECTED;
- if (ebo->flag & BONE_EDITMODE_LOCKED)
- td->protectflag = OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE;
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
-
- ED_armature_ebone_to_mat3(ebo, td->axismtx);
-
- if ((ebo->flag & BONE_ROOTSEL) == 0) {
- td->extra = ebo;
- td->ival = ebo->roll;
- }
-
- td->ext = NULL;
- td->val = NULL;
- td->ob = tc->obedit;
-
- td++;
- }
- if (ebo->flag & BONE_ROOTSEL) {
- copy_v3_v3(td->iloc, ebo->head);
- copy_v3_v3(td->center, td->iloc);
- td->loc = ebo->head;
- td->flag = TD_SELECTED;
- if (ebo->flag & BONE_EDITMODE_LOCKED)
- td->protectflag = OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE;
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
-
- ED_armature_ebone_to_mat3(ebo, td->axismtx);
-
- td->extra = ebo; /* to fix roll */
- td->ival = ebo->roll;
-
- td->ext = NULL;
- td->val = NULL;
- td->ob = tc->obedit;
-
- td++;
- }
- }
- }
-
- if (mirror && (td_old != td)) {
- eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
- if (eboflip) {
- bid[i].bone = eboflip;
- bid[i].dist = eboflip->dist;
- bid[i].rad_tail = eboflip->rad_tail;
- bid[i].roll = eboflip->roll;
- bid[i].xwidth = eboflip->xwidth;
- bid[i].zwidth = eboflip->zwidth;
- copy_v3_v3(bid[i].head, eboflip->head);
- copy_v3_v3(bid[i].tail, eboflip->tail);
- i++;
- }
- }
- }
-
- if (mirror) {
- /* trick to terminate iteration */
- BLI_assert(i + 1 == (MEM_allocN_len(bid) / sizeof(*bid)));
- bid[i].bone = NULL;
- }
- }
+ t->data_len_all = 0;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ EditBone *ebo, *eboflip;
+ bArmature *arm = tc->obedit->data;
+ ListBase *edbo = arm->edbo;
+ bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
+ int total_mirrored = 0;
+
+ tc->data_len = 0;
+ for (ebo = edbo->first; ebo; ebo = ebo->next) {
+ const int data_len_prev = tc->data_len;
+
+ if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
+ if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
+ if (ebo->flag & BONE_SELECTED)
+ tc->data_len++;
+ }
+ else if (t->mode == TFM_BONE_ROLL) {
+ if (ebo->flag & BONE_SELECTED)
+ tc->data_len++;
+ }
+ else {
+ if (ebo->flag & BONE_TIPSEL)
+ tc->data_len++;
+ if (ebo->flag & BONE_ROOTSEL)
+ tc->data_len++;
+ }
+ }
+
+ if (mirror && (data_len_prev < tc->data_len)) {
+ eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
+ if (eboflip)
+ total_mirrored++;
+ }
+ }
+ if (!tc->data_len) {
+ continue;
+ }
+
+ if (mirror) {
+ BoneInitData *bid = MEM_mallocN((total_mirrored + 1) * sizeof(BoneInitData), "BoneInitData");
+
+ /* trick to terminate iteration */
+ bid[total_mirrored].bone = NULL;
+
+ tc->custom.type.data = bid;
+ tc->custom.type.use_free = true;
+ }
+ t->data_len_all += tc->data_len;
+ }
+
+ transform_around_single_fallback(t);
+ t->data_len_all = -1;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ if (!tc->data_len) {
+ continue;
+ }
+
+ EditBone *ebo, *eboflip;
+ bArmature *arm = tc->obedit->data;
+ ListBase *edbo = arm->edbo;
+ TransData *td, *td_old;
+ float mtx[3][3], smtx[3][3], bonemat[3][3];
+ bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
+ BoneInitData *bid = tc->custom.type.data;
+
+ copy_m3_m4(mtx, tc->obedit->obmat);
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
+
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransEditBone");
+ int i = 0;
+
+ for (ebo = edbo->first; ebo; ebo = ebo->next) {
+ td_old = td;
+ ebo->oldlength =
+ ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
+
+ if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
+ if (t->mode == TFM_BONE_ENVELOPE) {
+ if (ebo->flag & BONE_ROOTSEL) {
+ td->val = &ebo->rad_head;
+ td->ival = *td->val;
+
+ copy_v3_v3(td->center, ebo->head);
+ td->flag = TD_SELECTED;
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+
+ td->loc = NULL;
+ td->ext = NULL;
+ td->ob = tc->obedit;
+
+ td++;
+ }
+ if (ebo->flag & BONE_TIPSEL) {
+ td->val = &ebo->rad_tail;
+ td->ival = *td->val;
+ copy_v3_v3(td->center, ebo->tail);
+ td->flag = TD_SELECTED;
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+
+ td->loc = NULL;
+ td->ext = NULL;
+ td->ob = tc->obedit;
+
+ td++;
+ }
+ }
+ else if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
+ if (ebo->flag & BONE_SELECTED) {
+ if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) {
+ td->loc = NULL;
+ td->val = &ebo->dist;
+ td->ival = ebo->dist;
+ }
+ else {
+ // abusive storage of scale in the loc pointer :)
+ td->loc = &ebo->xwidth;
+ copy_v3_v3(td->iloc, td->loc);
+ td->val = NULL;
+ }
+ copy_v3_v3(td->center, ebo->head);
+ td->flag = TD_SELECTED;
+
+ /* use local bone matrix */
+ ED_armature_ebone_to_mat3(ebo, bonemat);
+ mul_m3_m3m3(td->mtx, mtx, bonemat);
+ invert_m3_m3(td->smtx, td->mtx);
+
+ copy_m3_m3(td->axismtx, td->mtx);
+ normalize_m3(td->axismtx);
+
+ td->ext = NULL;
+ td->ob = tc->obedit;
+
+ td++;
+ }
+ }
+ else if (t->mode == TFM_BONE_ROLL) {
+ if (ebo->flag & BONE_SELECTED) {
+ td->loc = NULL;
+ td->val = &(ebo->roll);
+ td->ival = ebo->roll;
+
+ copy_v3_v3(td->center, ebo->head);
+ td->flag = TD_SELECTED;
+
+ td->ext = NULL;
+ td->ob = tc->obedit;
+
+ td++;
+ }
+ }
+ else {
+ if (ebo->flag & BONE_TIPSEL) {
+ copy_v3_v3(td->iloc, ebo->tail);
+
+ /* Don't allow single selected tips to have a modified center,
+ * causes problem with snapping (see T45974).
+ * However, in rotation mode, we want to keep that 'rotate bone around root with
+ * only its tip selected' behavior (see T46325). */
+ if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
+ ((t->mode == TFM_ROTATION) || (ebo->flag & BONE_ROOTSEL))) {
+ copy_v3_v3(td->center, ebo->head);
+ }
+ else {
+ copy_v3_v3(td->center, td->iloc);
+ }
+
+ td->loc = ebo->tail;
+ td->flag = TD_SELECTED;
+ if (ebo->flag & BONE_EDITMODE_LOCKED)
+ td->protectflag = OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE;
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+
+ ED_armature_ebone_to_mat3(ebo, td->axismtx);
+
+ if ((ebo->flag & BONE_ROOTSEL) == 0) {
+ td->extra = ebo;
+ td->ival = ebo->roll;
+ }
+
+ td->ext = NULL;
+ td->val = NULL;
+ td->ob = tc->obedit;
+
+ td++;
+ }
+ if (ebo->flag & BONE_ROOTSEL) {
+ copy_v3_v3(td->iloc, ebo->head);
+ copy_v3_v3(td->center, td->iloc);
+ td->loc = ebo->head;
+ td->flag = TD_SELECTED;
+ if (ebo->flag & BONE_EDITMODE_LOCKED)
+ td->protectflag = OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE;
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+
+ ED_armature_ebone_to_mat3(ebo, td->axismtx);
+
+ td->extra = ebo; /* to fix roll */
+ td->ival = ebo->roll;
+
+ td->ext = NULL;
+ td->val = NULL;
+ td->ob = tc->obedit;
+
+ td++;
+ }
+ }
+ }
+
+ if (mirror && (td_old != td)) {
+ eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
+ if (eboflip) {
+ bid[i].bone = eboflip;
+ bid[i].dist = eboflip->dist;
+ bid[i].rad_tail = eboflip->rad_tail;
+ bid[i].roll = eboflip->roll;
+ bid[i].xwidth = eboflip->xwidth;
+ bid[i].zwidth = eboflip->zwidth;
+ copy_v3_v3(bid[i].head, eboflip->head);
+ copy_v3_v3(bid[i].tail, eboflip->tail);
+ i++;
+ }
+ }
+ }
+
+ if (mirror) {
+ /* trick to terminate iteration */
+ BLI_assert(i + 1 == (MEM_allocN_len(bid) / sizeof(*bid)));
+ bid[i].bone = NULL;
+ }
+ }
}
/* ********************* meta elements ********* */
static void createTransMBallVerts(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- MetaBall *mb = (MetaBall *)tc->obedit->data;
- MetaElem *ml;
- TransData *td;
- TransDataExtension *tx;
- float mtx[3][3], smtx[3][3];
- int count = 0, countsel = 0;
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
-
- /* count totals */
- for (ml = mb->editelems->first; ml; ml = ml->next) {
- if (ml->flag & SELECT) countsel++;
- if (is_prop_edit) count++;
- }
-
- /* note: in prop mode we need at least 1 selected */
- if (countsel == 0) {
- continue;
- }
-
- if (is_prop_edit) tc->data_len = count;
- else tc->data_len = countsel;
-
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(MBall EditMode)");
- tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), "MetaElement_TransExtension");
-
- copy_m3_m4(mtx, tc->obedit->obmat);
- pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
-
- for (ml = mb->editelems->first; ml; ml = ml->next) {
- if (is_prop_edit || (ml->flag & SELECT)) {
- td->loc = &ml->x;
- copy_v3_v3(td->iloc, td->loc);
- copy_v3_v3(td->center, td->loc);
-
- quat_to_mat3(td->axismtx, ml->quat);
-
- if (ml->flag & SELECT) td->flag = TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
- else td->flag = TD_USEQUAT;
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
-
- td->ext = tx;
-
- /* Radius of MetaElem (mass of MetaElem influence) */
- if (ml->flag & MB_SCALE_RAD) {
- td->val = &ml->rad;
- td->ival = ml->rad;
- }
- else {
- td->val = &ml->s;
- td->ival = ml->s;
- }
-
- /* expx/expy/expz determine "shape" of some MetaElem types */
- tx->size = &ml->expx;
- tx->isize[0] = ml->expx;
- tx->isize[1] = ml->expy;
- tx->isize[2] = ml->expz;
-
- /* quat is used for rotation of MetaElem */
- tx->quat = ml->quat;
- copy_qt_qt(tx->iquat, ml->quat);
-
- tx->rot = NULL;
-
- td++;
- tx++;
- }
- }
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ MetaBall *mb = (MetaBall *)tc->obedit->data;
+ MetaElem *ml;
+ TransData *td;
+ TransDataExtension *tx;
+ float mtx[3][3], smtx[3][3];
+ int count = 0, countsel = 0;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+
+ /* count totals */
+ for (ml = mb->editelems->first; ml; ml = ml->next) {
+ if (ml->flag & SELECT)
+ countsel++;
+ if (is_prop_edit)
+ count++;
+ }
+
+ /* note: in prop mode we need at least 1 selected */
+ if (countsel == 0) {
+ continue;
+ }
+
+ if (is_prop_edit)
+ tc->data_len = count;
+ else
+ tc->data_len = countsel;
+
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(MBall EditMode)");
+ tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension),
+ "MetaElement_TransExtension");
+
+ copy_m3_m4(mtx, tc->obedit->obmat);
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
+
+ for (ml = mb->editelems->first; ml; ml = ml->next) {
+ if (is_prop_edit || (ml->flag & SELECT)) {
+ td->loc = &ml->x;
+ copy_v3_v3(td->iloc, td->loc);
+ copy_v3_v3(td->center, td->loc);
+
+ quat_to_mat3(td->axismtx, ml->quat);
+
+ if (ml->flag & SELECT)
+ td->flag = TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
+ else
+ td->flag = TD_USEQUAT;
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+
+ td->ext = tx;
+
+ /* Radius of MetaElem (mass of MetaElem influence) */
+ if (ml->flag & MB_SCALE_RAD) {
+ td->val = &ml->rad;
+ td->ival = ml->rad;
+ }
+ else {
+ td->val = &ml->s;
+ td->ival = ml->s;
+ }
+
+ /* expx/expy/expz determine "shape" of some MetaElem types */
+ tx->size = &ml->expx;
+ tx->isize[0] = ml->expx;
+ tx->isize[1] = ml->expy;
+ tx->isize[2] = ml->expz;
+
+ /* quat is used for rotation of MetaElem */
+ tx->quat = ml->quat;
+ copy_qt_qt(tx->iquat, ml->quat);
+
+ tx->rot = NULL;
+
+ td++;
+ tx++;
+ }
+ }
+ }
}
/* ********************* curve/surface ********* */
static void calc_distanceCurveVerts(TransData *head, TransData *tail)
{
- TransData *td, *td_near = NULL;
- for (td = head; td <= tail; td++) {
- if (td->flag & TD_SELECTED) {
- td_near = td;
- td->dist = 0.0f;
- }
- else if (td_near) {
- float dist;
- dist = len_v3v3(td_near->center, td->center);
- if (dist < (td - 1)->dist) {
- td->dist = (td - 1)->dist;
- }
- else {
- td->dist = dist;
- }
- }
- else {
- td->dist = FLT_MAX;
- td->flag |= TD_NOTCONNECTED;
- }
- }
- td_near = NULL;
- for (td = tail; td >= head; td--) {
- if (td->flag & TD_SELECTED) {
- td_near = td;
- td->dist = 0.0f;
- }
- else if (td_near) {
- float dist;
- dist = len_v3v3(td_near->center, td->center);
- if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td + 1)->dist < td->dist) {
- td->flag &= ~TD_NOTCONNECTED;
- if (dist < (td + 1)->dist) {
- td->dist = (td + 1)->dist;
- }
- else {
- td->dist = dist;
- }
- }
- }
- }
+ TransData *td, *td_near = NULL;
+ for (td = head; td <= tail; td++) {
+ if (td->flag & TD_SELECTED) {
+ td_near = td;
+ td->dist = 0.0f;
+ }
+ else if (td_near) {
+ float dist;
+ dist = len_v3v3(td_near->center, td->center);
+ if (dist < (td - 1)->dist) {
+ td->dist = (td - 1)->dist;
+ }
+ else {
+ td->dist = dist;
+ }
+ }
+ else {
+ td->dist = FLT_MAX;
+ td->flag |= TD_NOTCONNECTED;
+ }
+ }
+ td_near = NULL;
+ for (td = tail; td >= head; td--) {
+ if (td->flag & TD_SELECTED) {
+ td_near = td;
+ td->dist = 0.0f;
+ }
+ else if (td_near) {
+ float dist;
+ dist = len_v3v3(td_near->center, td->center);
+ if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td + 1)->dist < td->dist) {
+ td->flag &= ~TD_NOTCONNECTED;
+ if (dist < (td + 1)->dist) {
+ td->dist = (td + 1)->dist;
+ }
+ else {
+ td->dist = dist;
+ }
+ }
+ }
+ }
}
/* Utility function for getting the handle data from bezier's */
static TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTriple *bezt)
{
- TransDataCurveHandleFlags *hdata;
- td->flag |= TD_BEZTRIPLE;
- hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
- hdata->ih1 = bezt->h1;
- hdata->h1 = &bezt->h1;
- hdata->ih2 = bezt->h2; /* in case the second is not selected */
- hdata->h2 = &bezt->h2;
- return hdata;
+ TransDataCurveHandleFlags *hdata;
+ td->flag |= TD_BEZTRIPLE;
+ hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
+ hdata->ih1 = bezt->h1;
+ hdata->h1 = &bezt->h1;
+ hdata->ih2 = bezt->h2; /* in case the second is not selected */
+ hdata->h2 = &bezt->h2;
+ return hdata;
}
/**
* For the purpose of transform code we need to behave as if handles are selected,
* even when they aren't (see special case below).
*/
-static int bezt_select_to_transform_triple_flag(
- const BezTriple *bezt, const bool hide_handles)
-{
- int flag = 0;
-
- if (hide_handles) {
- if (bezt->f2 & SELECT) {
- flag = (1 << 0) | (1 << 1) | (1 << 2);
- }
- }
- else {
- flag = (
- ((bezt->f1 & SELECT) ? (1 << 0) : 0) |
- ((bezt->f2 & SELECT) ? (1 << 1) : 0) |
- ((bezt->f3 & SELECT) ? (1 << 2) : 0)
- );
- }
-
- /* Special case for auto & aligned handles:
- * When a center point is being moved without the handles,
- * leaving the handles stationary makes no sense and only causes strange behavior,
- * where one handle is arbitrarily anchored, the other one is aligned and lengthened
- * based on where the center point is moved. Also a bug when cancelling, see: T52007.
- *
- * A more 'correct' solution could be to store handle locations in 'TransDataCurveHandleFlags'.
- * However that doesn't resolve odd behavior, so best transform the handles in this case.
- */
- if ((flag != ((1 << 0) | (1 << 1) | (1 << 2))) && (flag & (1 << 1))) {
- if (ELEM(bezt->h1, HD_AUTO, HD_ALIGN) &&
- ELEM(bezt->h2, HD_AUTO, HD_ALIGN))
- {
- flag = (1 << 0) | (1 << 1) | (1 << 2);
- }
- }
-
- return flag;
+static int bezt_select_to_transform_triple_flag(const BezTriple *bezt, const bool hide_handles)
+{
+ int flag = 0;
+
+ if (hide_handles) {
+ if (bezt->f2 & SELECT) {
+ flag = (1 << 0) | (1 << 1) | (1 << 2);
+ }
+ }
+ else {
+ flag = (((bezt->f1 & SELECT) ? (1 << 0) : 0) | ((bezt->f2 & SELECT) ? (1 << 1) : 0) |
+ ((bezt->f3 & SELECT) ? (1 << 2) : 0));
+ }
+
+ /* Special case for auto & aligned handles:
+ * When a center point is being moved without the handles,
+ * leaving the handles stationary makes no sense and only causes strange behavior,
+ * where one handle is arbitrarily anchored, the other one is aligned and lengthened
+ * based on where the center point is moved. Also a bug when cancelling, see: T52007.
+ *
+ * A more 'correct' solution could be to store handle locations in 'TransDataCurveHandleFlags'.
+ * However that doesn't resolve odd behavior, so best transform the handles in this case.
+ */
+ if ((flag != ((1 << 0) | (1 << 1) | (1 << 2))) && (flag & (1 << 1))) {
+ if (ELEM(bezt->h1, HD_AUTO, HD_ALIGN) && ELEM(bezt->h2, HD_AUTO, HD_ALIGN)) {
+ flag = (1 << 0) | (1 << 1) | (1 << 2);
+ }
+ }
+
+ return flag;
}
static void createTransCurveVerts(TransInfo *t)
@@ -1742,288 +1764,320 @@ static void createTransCurveVerts(TransInfo *t)
#define SEL_F2 (1 << 1)
#define SEL_F3 (1 << 2)
- t->data_len_all = 0;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- Curve *cu = tc->obedit->data;
- BLI_assert(cu->editnurb != NULL);
- BezTriple *bezt;
- BPoint *bp;
- int a;
- int count = 0, countsel = 0;
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
- View3D *v3d = t->view;
- short hide_handles = (v3d != NULL) ? ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) : false;
-
- /* 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) {
- if (nu->type == CU_BEZIER) {
- for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
- if (bezt->hide == 0) {
- const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
- if (bezt_tx & SEL_F1) { countsel++; }
- if (bezt_tx & SEL_F2) { countsel++; }
- if (bezt_tx & SEL_F3) { countsel++; }
- if (is_prop_edit) count += 3;
-
- }
- }
- }
- else {
- for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
- if (bp->hide == 0) {
- if (is_prop_edit) count++;
- if (bp->f1 & SELECT) countsel++;
- }
- }
- }
- }
- /* note: in prop mode we need at least 1 selected */
- if (countsel == 0) {
- tc->data_len = 0;
- continue;
- }
-
- if (is_prop_edit) tc->data_len = count;
- else tc->data_len = countsel;
- tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Curve EditMode)");
-
- t->data_len_all += tc->data_len;
- }
-
- transform_around_single_fallback(t);
- t->data_len_all = -1;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- if (tc->data_len == 0) {
- continue;
- }
-
- Curve *cu = tc->obedit->data;
- BezTriple *bezt;
- BPoint *bp;
- int a;
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
- View3D *v3d = t->view;
- short hide_handles = (v3d != NULL) ? ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) : false;
-
- float mtx[3][3], smtx[3][3];
-
- copy_m3_m4(mtx, tc->obedit->obmat);
- pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
-
- TransData *td = tc->data;
- ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- for (Nurb *nu = nurbs->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- TransData *head, *tail;
- head = tail = td;
- for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
- if (bezt->hide == 0) {
- TransDataCurveHandleFlags *hdata = NULL;
- float axismtx[3][3];
-
- if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
- float normal[3], plane[3];
-
- BKE_nurb_bezt_calc_normal(nu, bezt, normal);
- BKE_nurb_bezt_calc_plane(nu, bezt, plane);
-
- if (createSpaceNormalTangent(axismtx, normal, plane)) {
- /* pass */
- }
- else {
- normalize_v3(normal);
- axis_dominant_v3_to_m3(axismtx, normal);
- invert_m3(axismtx);
- }
- }
-
- /* Elements that will be transform (not always a match to selection). */
- const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
-
- if (is_prop_edit || bezt_tx & SEL_F1) {
- copy_v3_v3(td->iloc, bezt->vec[0]);
- td->loc = bezt->vec[0];
- copy_v3_v3(td->center, bezt->vec[(hide_handles ||
- (t->around == V3D_AROUND_LOCAL_ORIGINS) ||
- (bezt->f2 & SELECT)) ? 1 : 0]);
- if (hide_handles) {
- if (bezt->f2 & SELECT) td->flag = TD_SELECTED;
- else td->flag = 0;
- }
- else {
- if (bezt->f1 & SELECT) td->flag = TD_SELECTED;
- else td->flag = 0;
- }
- td->ext = NULL;
- td->val = NULL;
-
- hdata = initTransDataCurveHandles(td, bezt);
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
- if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
- copy_m3_m3(td->axismtx, axismtx);
- }
-
- td++;
- tail++;
- }
-
- /* This is the Curve Point, the other two are handles */
- if (is_prop_edit || bezt_tx & SEL_F2) {
- copy_v3_v3(td->iloc, bezt->vec[1]);
- td->loc = bezt->vec[1];
- copy_v3_v3(td->center, td->loc);
- if (bezt->f2 & SELECT) td->flag = TD_SELECTED;
- else td->flag = 0;
- td->ext = NULL;
-
- /* TODO - make points scale */
- if (t->mode == TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/
- td->val = &(bezt->radius);
- td->ival = bezt->radius;
- }
- else if (t->mode == TFM_TILT) {
- td->val = &(bezt->tilt);
- td->ival = bezt->tilt;
- }
- else {
- td->val = NULL;
- }
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
- if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
- copy_m3_m3(td->axismtx, axismtx);
- }
-
- if ((bezt_tx & SEL_F1) == 0 && (bezt_tx & SEL_F3) == 0)
- /* If the middle is selected but the sides arnt, this is needed */
- if (hdata == NULL) {
- /* if the handle was not saved by the previous handle */
- hdata = initTransDataCurveHandles(td, bezt);
- }
-
- td++;
- tail++;
- }
- if (is_prop_edit || bezt_tx & SEL_F3) {
- copy_v3_v3(td->iloc, bezt->vec[2]);
- td->loc = bezt->vec[2];
- copy_v3_v3(td->center, bezt->vec[(hide_handles ||
- (t->around == V3D_AROUND_LOCAL_ORIGINS) ||
- (bezt->f2 & SELECT)) ? 1 : 2]);
- if (hide_handles) {
- if (bezt->f2 & SELECT) td->flag = TD_SELECTED;
- else td->flag = 0;
- }
- else {
- if (bezt->f3 & SELECT) td->flag = TD_SELECTED;
- else td->flag = 0;
- }
- td->ext = NULL;
- td->val = NULL;
-
- if (hdata == NULL) {
- /* if the handle was not saved by the previous handle */
- hdata = initTransDataCurveHandles(td, bezt);
- }
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
- if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
- copy_m3_m3(td->axismtx, axismtx);
- }
-
- td++;
- tail++;
- }
-
- (void)hdata; /* quiet warning */
- }
- else if (is_prop_edit && head != tail) {
- calc_distanceCurveVerts(head, tail - 1);
- head = tail;
- }
- }
- if (is_prop_edit && head != tail)
- calc_distanceCurveVerts(head, tail - 1);
-
- /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandles
- * but for now just don't change handle types */
- 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);
- }
- }
- else {
- TransData *head, *tail;
- head = tail = td;
- for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
- if (bp->hide == 0) {
- if (is_prop_edit || (bp->f1 & SELECT)) {
- float axismtx[3][3];
-
- if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
- if (nu->pntsv == 1) {
- float normal[3], plane[3];
-
- BKE_nurb_bpoint_calc_normal(nu, bp, normal);
- BKE_nurb_bpoint_calc_plane(nu, bp, plane);
-
- if (createSpaceNormalTangent(axismtx, normal, plane)) {
- /* pass */
- }
- else {
- normalize_v3(normal);
- axis_dominant_v3_to_m3(axismtx, normal);
- invert_m3(axismtx);
- }
- }
- }
-
- copy_v3_v3(td->iloc, bp->vec);
- td->loc = bp->vec;
- copy_v3_v3(td->center, td->loc);
- if (bp->f1 & SELECT) td->flag = TD_SELECTED;
- else td->flag = 0;
- td->ext = NULL;
-
- if (t->mode == TFM_CURVE_SHRINKFATTEN || t->mode == TFM_RESIZE) {
- td->val = &(bp->radius);
- td->ival = bp->radius;
- }
- else {
- td->val = &(bp->tilt);
- td->ival = bp->tilt;
- }
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
- if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
- if (nu->pntsv == 1) {
- copy_m3_m3(td->axismtx, axismtx);
- }
- }
-
- td++;
- tail++;
- }
- }
- else if (is_prop_edit && head != tail) {
- calc_distanceCurveVerts(head, tail - 1);
- head = tail;
- }
- }
- if (is_prop_edit && head != tail)
- calc_distanceCurveVerts(head, tail - 1);
- }
- }
- }
+ t->data_len_all = 0;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ Curve *cu = tc->obedit->data;
+ BLI_assert(cu->editnurb != NULL);
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+ int count = 0, countsel = 0;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+ View3D *v3d = t->view;
+ short hide_handles = (v3d != NULL) ?
+ ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) :
+ false;
+
+ /* 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) {
+ if (nu->type == CU_BEZIER) {
+ for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
+ if (bezt->hide == 0) {
+ const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
+ if (bezt_tx & SEL_F1) {
+ countsel++;
+ }
+ if (bezt_tx & SEL_F2) {
+ countsel++;
+ }
+ if (bezt_tx & SEL_F3) {
+ countsel++;
+ }
+ if (is_prop_edit)
+ count += 3;
+ }
+ }
+ }
+ else {
+ for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
+ if (bp->hide == 0) {
+ if (is_prop_edit)
+ count++;
+ if (bp->f1 & SELECT)
+ countsel++;
+ }
+ }
+ }
+ }
+ /* note: in prop mode we need at least 1 selected */
+ if (countsel == 0) {
+ tc->data_len = 0;
+ continue;
+ }
+
+ if (is_prop_edit)
+ tc->data_len = count;
+ else
+ tc->data_len = countsel;
+ tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Curve EditMode)");
+
+ t->data_len_all += tc->data_len;
+ }
+
+ transform_around_single_fallback(t);
+ t->data_len_all = -1;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ if (tc->data_len == 0) {
+ continue;
+ }
+
+ Curve *cu = tc->obedit->data;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+ View3D *v3d = t->view;
+ short hide_handles = (v3d != NULL) ?
+ ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) :
+ false;
+
+ float mtx[3][3], smtx[3][3];
+
+ copy_m3_m4(mtx, tc->obedit->obmat);
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
+
+ TransData *td = tc->data;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+ for (Nurb *nu = nurbs->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ TransData *head, *tail;
+ head = tail = td;
+ for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
+ if (bezt->hide == 0) {
+ TransDataCurveHandleFlags *hdata = NULL;
+ float axismtx[3][3];
+
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ float normal[3], plane[3];
+
+ BKE_nurb_bezt_calc_normal(nu, bezt, normal);
+ BKE_nurb_bezt_calc_plane(nu, bezt, plane);
+
+ if (createSpaceNormalTangent(axismtx, normal, plane)) {
+ /* pass */
+ }
+ else {
+ normalize_v3(normal);
+ axis_dominant_v3_to_m3(axismtx, normal);
+ invert_m3(axismtx);
+ }
+ }
+
+ /* Elements that will be transform (not always a match to selection). */
+ const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
+
+ if (is_prop_edit || bezt_tx & SEL_F1) {
+ copy_v3_v3(td->iloc, bezt->vec[0]);
+ td->loc = bezt->vec[0];
+ copy_v3_v3(td->center,
+ bezt->vec[(hide_handles || (t->around == V3D_AROUND_LOCAL_ORIGINS) ||
+ (bezt->f2 & SELECT)) ?
+ 1 :
+ 0]);
+ if (hide_handles) {
+ if (bezt->f2 & SELECT)
+ td->flag = TD_SELECTED;
+ else
+ td->flag = 0;
+ }
+ else {
+ if (bezt->f1 & SELECT)
+ td->flag = TD_SELECTED;
+ else
+ td->flag = 0;
+ }
+ td->ext = NULL;
+ td->val = NULL;
+
+ hdata = initTransDataCurveHandles(td, bezt);
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ copy_m3_m3(td->axismtx, axismtx);
+ }
+
+ td++;
+ tail++;
+ }
+
+ /* This is the Curve Point, the other two are handles */
+ if (is_prop_edit || bezt_tx & SEL_F2) {
+ copy_v3_v3(td->iloc, bezt->vec[1]);
+ td->loc = bezt->vec[1];
+ copy_v3_v3(td->center, td->loc);
+ if (bezt->f2 & SELECT)
+ td->flag = TD_SELECTED;
+ else
+ td->flag = 0;
+ td->ext = NULL;
+
+ /* TODO - make points scale */
+ if (t->mode == TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/
+ td->val = &(bezt->radius);
+ td->ival = bezt->radius;
+ }
+ else if (t->mode == TFM_TILT) {
+ td->val = &(bezt->tilt);
+ td->ival = bezt->tilt;
+ }
+ else {
+ td->val = NULL;
+ }
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ copy_m3_m3(td->axismtx, axismtx);
+ }
+
+ if ((bezt_tx & SEL_F1) == 0 && (bezt_tx & SEL_F3) == 0)
+ /* If the middle is selected but the sides arnt, this is needed */
+ if (hdata == NULL) {
+ /* if the handle was not saved by the previous handle */
+ hdata = initTransDataCurveHandles(td, bezt);
+ }
+
+ td++;
+ tail++;
+ }
+ if (is_prop_edit || bezt_tx & SEL_F3) {
+ copy_v3_v3(td->iloc, bezt->vec[2]);
+ td->loc = bezt->vec[2];
+ copy_v3_v3(td->center,
+ bezt->vec[(hide_handles || (t->around == V3D_AROUND_LOCAL_ORIGINS) ||
+ (bezt->f2 & SELECT)) ?
+ 1 :
+ 2]);
+ if (hide_handles) {
+ if (bezt->f2 & SELECT)
+ td->flag = TD_SELECTED;
+ else
+ td->flag = 0;
+ }
+ else {
+ if (bezt->f3 & SELECT)
+ td->flag = TD_SELECTED;
+ else
+ td->flag = 0;
+ }
+ td->ext = NULL;
+ td->val = NULL;
+
+ if (hdata == NULL) {
+ /* if the handle was not saved by the previous handle */
+ hdata = initTransDataCurveHandles(td, bezt);
+ }
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ copy_m3_m3(td->axismtx, axismtx);
+ }
+
+ td++;
+ tail++;
+ }
+
+ (void)hdata; /* quiet warning */
+ }
+ else if (is_prop_edit && head != tail) {
+ calc_distanceCurveVerts(head, tail - 1);
+ head = tail;
+ }
+ }
+ if (is_prop_edit && head != tail)
+ calc_distanceCurveVerts(head, tail - 1);
+
+ /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandles
+ * but for now just don't change handle types */
+ 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);
+ }
+ }
+ else {
+ TransData *head, *tail;
+ head = tail = td;
+ for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
+ if (bp->hide == 0) {
+ if (is_prop_edit || (bp->f1 & SELECT)) {
+ float axismtx[3][3];
+
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ if (nu->pntsv == 1) {
+ float normal[3], plane[3];
+
+ BKE_nurb_bpoint_calc_normal(nu, bp, normal);
+ BKE_nurb_bpoint_calc_plane(nu, bp, plane);
+
+ if (createSpaceNormalTangent(axismtx, normal, plane)) {
+ /* pass */
+ }
+ else {
+ normalize_v3(normal);
+ axis_dominant_v3_to_m3(axismtx, normal);
+ invert_m3(axismtx);
+ }
+ }
+ }
+
+ copy_v3_v3(td->iloc, bp->vec);
+ td->loc = bp->vec;
+ copy_v3_v3(td->center, td->loc);
+ if (bp->f1 & SELECT)
+ td->flag = TD_SELECTED;
+ else
+ td->flag = 0;
+ td->ext = NULL;
+
+ if (t->mode == TFM_CURVE_SHRINKFATTEN || t->mode == TFM_RESIZE) {
+ td->val = &(bp->radius);
+ td->ival = bp->radius;
+ }
+ else {
+ td->val = &(bp->tilt);
+ td->ival = bp->tilt;
+ }
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ if (nu->pntsv == 1) {
+ copy_m3_m3(td->axismtx, axismtx);
+ }
+ }
+
+ td++;
+ tail++;
+ }
+ }
+ else if (is_prop_edit && head != tail) {
+ calc_distanceCurveVerts(head, tail - 1);
+ head = tail;
+ }
+ }
+ if (is_prop_edit && head != tail)
+ calc_distanceCurveVerts(head, tail - 1);
+ }
+ }
+ }
#undef SEL_F1
#undef SEL_F2
#undef SEL_F3
@@ -2033,262 +2087,281 @@ static void createTransCurveVerts(TransInfo *t)
static void createTransLatticeVerts(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
- Lattice *latt = ((Lattice *)tc->obedit->data)->editlatt->latt;
- TransData *td = NULL;
- BPoint *bp;
- float mtx[3][3], smtx[3][3];
- int a;
- int count = 0, countsel = 0;
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
-
- bp = latt->def;
- a = latt->pntsu * latt->pntsv * latt->pntsw;
- while (a--) {
- if (bp->hide == 0) {
- if (bp->f1 & SELECT) countsel++;
- if (is_prop_edit) count++;
- }
- bp++;
- }
-
- /* note: in prop mode we need at least 1 selected */
- if (countsel == 0) return;
-
- if (is_prop_edit) tc->data_len = count;
- else tc->data_len = countsel;
- tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Lattice EditMode)");
-
- copy_m3_m4(mtx, tc->obedit->obmat);
- pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
-
- td = tc->data;
- bp = latt->def;
- a = latt->pntsu * latt->pntsv * latt->pntsw;
- while (a--) {
- if (is_prop_edit || (bp->f1 & SELECT)) {
- if (bp->hide == 0) {
- copy_v3_v3(td->iloc, bp->vec);
- td->loc = bp->vec;
- copy_v3_v3(td->center, td->loc);
- if (bp->f1 & SELECT) {
- td->flag = TD_SELECTED;
- }
- else {
- td->flag = 0;
- }
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
-
- td->ext = NULL;
- td->val = NULL;
-
- td++;
- }
- }
- bp++;
- }
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+
+ Lattice *latt = ((Lattice *)tc->obedit->data)->editlatt->latt;
+ TransData *td = NULL;
+ BPoint *bp;
+ float mtx[3][3], smtx[3][3];
+ int a;
+ int count = 0, countsel = 0;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+
+ bp = latt->def;
+ a = latt->pntsu * latt->pntsv * latt->pntsw;
+ while (a--) {
+ if (bp->hide == 0) {
+ if (bp->f1 & SELECT)
+ countsel++;
+ if (is_prop_edit)
+ count++;
+ }
+ bp++;
+ }
+
+ /* note: in prop mode we need at least 1 selected */
+ if (countsel == 0)
+ return;
+
+ if (is_prop_edit)
+ tc->data_len = count;
+ else
+ tc->data_len = countsel;
+ tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Lattice EditMode)");
+
+ copy_m3_m4(mtx, tc->obedit->obmat);
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
+
+ td = tc->data;
+ bp = latt->def;
+ a = latt->pntsu * latt->pntsv * latt->pntsw;
+ while (a--) {
+ if (is_prop_edit || (bp->f1 & SELECT)) {
+ if (bp->hide == 0) {
+ copy_v3_v3(td->iloc, bp->vec);
+ td->loc = bp->vec;
+ copy_v3_v3(td->center, td->loc);
+ if (bp->f1 & SELECT) {
+ td->flag = TD_SELECTED;
+ }
+ else {
+ td->flag = 0;
+ }
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+
+ td->ext = NULL;
+ td->val = NULL;
+
+ td++;
+ }
+ }
+ bp++;
+ }
+ }
}
/* ******************* particle edit **************** */
static void createTransParticleVerts(bContext *C, TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
- TransData *td = NULL;
- TransDataExtension *tx;
- Object *ob = CTX_data_active_object(C);
- ParticleEditSettings *pset = PE_settings(t->scene);
- PTCacheEdit *edit = PE_get_current(t->scene, ob);
- ParticleSystem *psys = NULL;
- PTCacheEditPoint *point;
- PTCacheEditKey *key;
- float mat[4][4];
- int i, k, transformparticle;
- int count = 0, hasselected = 0;
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
-
- if (edit == NULL || t->settings->particle.selectmode == SCE_SELECT_PATH) return;
-
- psys = edit->psys;
-
- for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
- point->flag &= ~PEP_TRANSFORM;
- transformparticle = 0;
-
- if ((point->flag & PEP_HIDE) == 0) {
- for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
- if ((key->flag & PEK_HIDE) == 0) {
- if (key->flag & PEK_SELECT) {
- hasselected = 1;
- transformparticle = 1;
- }
- else if (is_prop_edit)
- transformparticle = 1;
- }
- }
- }
-
- if (transformparticle) {
- count += point->totkey;
- point->flag |= PEP_TRANSFORM;
- }
- }
-
- /* note: in prop mode we need at least 1 selected */
- if (hasselected == 0) return;
-
- tc->data_len = count;
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Particle Mode)");
-
- if (t->mode == TFM_BAKE_TIME)
- tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), "Particle_TransExtension");
- else
- tx = tc->data_ext = NULL;
-
- unit_m4(mat);
-
- invert_m4_m4(ob->imat, ob->obmat);
-
- for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
- TransData *head, *tail;
- head = tail = td;
-
- if (!(point->flag & PEP_TRANSFORM)) continue;
-
- if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
- psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, psys->particles + i, mat);
- }
-
- for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
- if (key->flag & PEK_USE_WCO) {
- copy_v3_v3(key->world_co, key->co);
- mul_m4_v3(mat, key->world_co);
- td->loc = key->world_co;
- }
- else
- td->loc = key->co;
-
- copy_v3_v3(td->iloc, td->loc);
- copy_v3_v3(td->center, td->loc);
-
- if (key->flag & PEK_SELECT)
- td->flag |= TD_SELECTED;
- else if (!is_prop_edit)
- td->flag |= TD_SKIP;
-
- unit_m3(td->mtx);
- unit_m3(td->smtx);
-
- /* don't allow moving roots */
- if (k == 0 && pset->flag & PE_LOCK_FIRST && (!psys || !(psys->flag & PSYS_GLOBAL_HAIR)))
- td->protectflag |= OB_LOCK_LOC;
-
- td->ob = ob;
- td->ext = tx;
- if (t->mode == TFM_BAKE_TIME) {
- td->val = key->time;
- td->ival = *(key->time);
- /* abuse size and quat for min/max values */
- td->flag |= TD_NO_EXT;
- if (k == 0) tx->size = NULL;
- else tx->size = (key - 1)->time;
-
- if (k == point->totkey - 1) tx->quat = NULL;
- else tx->quat = (key + 1)->time;
- }
-
- td++;
- if (tx)
- tx++;
- tail++;
- }
- if (is_prop_edit && head != tail)
- calc_distanceCurveVerts(head, tail - 1);
- }
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+
+ TransData *td = NULL;
+ TransDataExtension *tx;
+ Object *ob = CTX_data_active_object(C);
+ ParticleEditSettings *pset = PE_settings(t->scene);
+ PTCacheEdit *edit = PE_get_current(t->scene, ob);
+ ParticleSystem *psys = NULL;
+ PTCacheEditPoint *point;
+ PTCacheEditKey *key;
+ float mat[4][4];
+ int i, k, transformparticle;
+ int count = 0, hasselected = 0;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+
+ if (edit == NULL || t->settings->particle.selectmode == SCE_SELECT_PATH)
+ return;
+
+ psys = edit->psys;
+
+ for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
+ point->flag &= ~PEP_TRANSFORM;
+ transformparticle = 0;
+
+ if ((point->flag & PEP_HIDE) == 0) {
+ for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
+ if ((key->flag & PEK_HIDE) == 0) {
+ if (key->flag & PEK_SELECT) {
+ hasselected = 1;
+ transformparticle = 1;
+ }
+ else if (is_prop_edit)
+ transformparticle = 1;
+ }
+ }
+ }
+
+ if (transformparticle) {
+ count += point->totkey;
+ point->flag |= PEP_TRANSFORM;
+ }
+ }
+
+ /* note: in prop mode we need at least 1 selected */
+ if (hasselected == 0)
+ return;
+
+ tc->data_len = count;
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Particle Mode)");
+
+ if (t->mode == TFM_BAKE_TIME)
+ tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension),
+ "Particle_TransExtension");
+ else
+ tx = tc->data_ext = NULL;
+
+ unit_m4(mat);
+
+ invert_m4_m4(ob->imat, ob->obmat);
+
+ for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
+ TransData *head, *tail;
+ head = tail = td;
+
+ if (!(point->flag & PEP_TRANSFORM))
+ continue;
+
+ if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
+ ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
+ psys_mat_hair_to_global(
+ ob, psmd_eval->mesh_final, psys->part->from, psys->particles + i, mat);
+ }
+
+ for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
+ if (key->flag & PEK_USE_WCO) {
+ copy_v3_v3(key->world_co, key->co);
+ mul_m4_v3(mat, key->world_co);
+ td->loc = key->world_co;
+ }
+ else
+ td->loc = key->co;
+
+ copy_v3_v3(td->iloc, td->loc);
+ copy_v3_v3(td->center, td->loc);
+
+ if (key->flag & PEK_SELECT)
+ td->flag |= TD_SELECTED;
+ else if (!is_prop_edit)
+ td->flag |= TD_SKIP;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+
+ /* don't allow moving roots */
+ if (k == 0 && pset->flag & PE_LOCK_FIRST && (!psys || !(psys->flag & PSYS_GLOBAL_HAIR)))
+ td->protectflag |= OB_LOCK_LOC;
+
+ td->ob = ob;
+ td->ext = tx;
+ if (t->mode == TFM_BAKE_TIME) {
+ td->val = key->time;
+ td->ival = *(key->time);
+ /* abuse size and quat for min/max values */
+ td->flag |= TD_NO_EXT;
+ if (k == 0)
+ tx->size = NULL;
+ else
+ tx->size = (key - 1)->time;
+
+ if (k == point->totkey - 1)
+ tx->quat = NULL;
+ else
+ tx->quat = (key + 1)->time;
+ }
+
+ td++;
+ if (tx)
+ tx++;
+ tail++;
+ }
+ if (is_prop_edit && head != tail)
+ calc_distanceCurveVerts(head, tail - 1);
+ }
+ }
}
void flushTransParticles(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- Scene *scene = t->scene;
- ViewLayer *view_layer = t->view_layer;
- Object *ob = OBACT(view_layer);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- ParticleSystem *psys = edit->psys;
- PTCacheEditPoint *point;
- PTCacheEditKey *key;
- TransData *td;
- float mat[4][4], imat[4][4], co[3];
- int i, k;
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
-
- /* we do transform in world space, so flush world space position
- * back to particle local space (only for hair particles) */
- td = tc->data;
- for (i = 0, point = edit->points; i < edit->totpoint; i++, point++, td++) {
- if (!(point->flag & PEP_TRANSFORM)) continue;
-
- if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
- psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, psys->particles + i, mat);
- invert_m4_m4(imat, mat);
-
- for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
- copy_v3_v3(co, key->world_co);
- mul_m4_v3(imat, co);
-
-
- /* optimization for proportional edit */
- if (!is_prop_edit || !compare_v3v3(key->co, co, 0.0001f)) {
- copy_v3_v3(key->co, co);
- point->flag |= PEP_EDIT_RECALC;
- }
- }
- }
- else
- point->flag |= PEP_EDIT_RECALC;
- }
-
- PE_update_object(t->depsgraph, scene, OBACT(view_layer), 1);
- DEG_id_tag_update(&ob->id, ID_RECALC_PSYS_REDO);
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ Scene *scene = t->scene;
+ ViewLayer *view_layer = t->view_layer;
+ Object *ob = OBACT(view_layer);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ ParticleSystem *psys = edit->psys;
+ PTCacheEditPoint *point;
+ PTCacheEditKey *key;
+ TransData *td;
+ float mat[4][4], imat[4][4], co[3];
+ int i, k;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+
+ /* we do transform in world space, so flush world space position
+ * back to particle local space (only for hair particles) */
+ td = tc->data;
+ for (i = 0, point = edit->points; i < edit->totpoint; i++, point++, td++) {
+ if (!(point->flag & PEP_TRANSFORM))
+ continue;
+
+ if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
+ ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
+ psys_mat_hair_to_global(
+ ob, psmd_eval->mesh_final, psys->part->from, psys->particles + i, mat);
+ invert_m4_m4(imat, mat);
+
+ for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
+ copy_v3_v3(co, key->world_co);
+ mul_m4_v3(imat, co);
+
+ /* optimization for proportional edit */
+ if (!is_prop_edit || !compare_v3v3(key->co, co, 0.0001f)) {
+ copy_v3_v3(key->co, co);
+ point->flag |= PEP_EDIT_RECALC;
+ }
+ }
+ }
+ else
+ point->flag |= PEP_EDIT_RECALC;
+ }
+
+ PE_update_object(t->depsgraph, scene, OBACT(view_layer), 1);
+ DEG_id_tag_update(&ob->id, ID_RECALC_PSYS_REDO);
+ }
}
/* ********************* mesh ****************** */
-static bool bmesh_test_dist_add(
- BMVert *v, BMVert *v_other,
- float *dists, const float *dists_prev,
- /* optionally track original index */
- int *index, const int *index_prev,
- float mtx[3][3])
-{
- if ((BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) &&
- (BM_elem_flag_test(v_other, BM_ELEM_HIDDEN) == 0))
- {
- const int i = BM_elem_index_get(v);
- const int i_other = BM_elem_index_get(v_other);
- float vec[3];
- float dist_other;
- sub_v3_v3v3(vec, v->co, v_other->co);
- mul_m3_v3(mtx, vec);
-
- dist_other = dists_prev[i] + len_v3(vec);
- if (dist_other < dists[i_other]) {
- dists[i_other] = dist_other;
- if (index != NULL) {
- index[i_other] = index_prev[i];
- }
- return true;
- }
- }
-
- return false;
+static bool bmesh_test_dist_add(BMVert *v,
+ BMVert *v_other,
+ float *dists,
+ const float *dists_prev,
+ /* optionally track original index */
+ int *index,
+ const int *index_prev,
+ float mtx[3][3])
+{
+ if ((BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) &&
+ (BM_elem_flag_test(v_other, BM_ELEM_HIDDEN) == 0)) {
+ const int i = BM_elem_index_get(v);
+ const int i_other = BM_elem_index_get(v_other);
+ float vec[3];
+ float dist_other;
+ sub_v3_v3v3(vec, v->co, v_other->co);
+ mul_m3_v3(mtx, vec);
+
+ dist_other = dists_prev[i] + len_v3(vec);
+ if (dist_other < dists[i_other]) {
+ dists[i_other] = dist_other;
+ if (index != NULL) {
+ index[i_other] = index_prev[i];
+ }
+ return true;
+ }
+ }
+
+ return false;
}
/**
@@ -2296,680 +2369,679 @@ static bool bmesh_test_dist_add(
* \param dists: Store the closest connected distance to selected vertices.
* \param index: Optionally store the original index we're measuring the distance to (can be NULL).
*/
-static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists, int *index)
-{
- BLI_LINKSTACK_DECLARE(queue, BMVert *);
-
- /* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */
- BLI_LINKSTACK_DECLARE(queue_next, BMVert *);
-
- BLI_LINKSTACK_INIT(queue);
- BLI_LINKSTACK_INIT(queue_next);
-
- {
- BMIter viter;
- BMVert *v;
- int i;
-
- BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
- float dist;
- BM_elem_index_set(v, i); /* set_inline */
- BM_elem_flag_disable(v, BM_ELEM_TAG);
-
- if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
- dist = FLT_MAX;
- if (index != NULL) {
- index[i] = i;
- }
- }
- else {
- BLI_LINKSTACK_PUSH(queue, v);
- dist = 0.0f;
- if (index != NULL) {
- index[i] = i;
- }
- }
-
- dists[i] = dist;
- }
- bm->elem_index_dirty &= ~BM_VERT;
- }
-
- /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */
- float *dists_prev = MEM_dupallocN(dists);
- int *index_prev = MEM_dupallocN(index); /* may be NULL */
-
- do {
- BMVert *v;
- LinkNode *lnk;
-
- /* this is correct but slow to do each iteration,
- * instead sync the dist's while clearing BM_ELEM_TAG (below) */
+static void editmesh_set_connectivity_distance(BMesh *bm,
+ float mtx[3][3],
+ float *dists,
+ int *index)
+{
+ BLI_LINKSTACK_DECLARE(queue, BMVert *);
+
+ /* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */
+ BLI_LINKSTACK_DECLARE(queue_next, BMVert *);
+
+ BLI_LINKSTACK_INIT(queue);
+ BLI_LINKSTACK_INIT(queue_next);
+
+ {
+ BMIter viter;
+ BMVert *v;
+ int i;
+
+ BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
+ float dist;
+ BM_elem_index_set(v, i); /* set_inline */
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
+ dist = FLT_MAX;
+ if (index != NULL) {
+ index[i] = i;
+ }
+ }
+ else {
+ BLI_LINKSTACK_PUSH(queue, v);
+ dist = 0.0f;
+ if (index != NULL) {
+ index[i] = i;
+ }
+ }
+
+ dists[i] = dist;
+ }
+ bm->elem_index_dirty &= ~BM_VERT;
+ }
+
+ /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */
+ float *dists_prev = MEM_dupallocN(dists);
+ int *index_prev = MEM_dupallocN(index); /* may be NULL */
+
+ do {
+ BMVert *v;
+ LinkNode *lnk;
+
+ /* this is correct but slow to do each iteration,
+ * instead sync the dist's while clearing BM_ELEM_TAG (below) */
#if 0
- memcpy(dists_prev, dists, sizeof(float) * bm->totvert);
+ memcpy(dists_prev, dists, sizeof(float) * bm->totvert);
#endif
- while ((v = BLI_LINKSTACK_POP(queue))) {
- BLI_assert(dists[BM_elem_index_get(v)] != FLT_MAX);
-
- /* connected edge-verts */
- if (v->e != NULL) {
- BMEdge *e_iter, *e_first;
-
- e_iter = e_first = v->e;
-
- /* would normally use BM_EDGES_OF_VERT, but this runs so often,
- * its faster to iterate on the data directly */
- do {
-
- if (BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == 0) {
-
- /* edge distance */
- {
- BMVert *v_other = BM_edge_other_vert(e_iter, v);
- if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) {
- if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
- BM_elem_flag_enable(v_other, BM_ELEM_TAG);
- BLI_LINKSTACK_PUSH(queue_next, v_other);
- }
- }
- }
-
- /* face distance */
- if (e_iter->l) {
- BMLoop *l_iter_radial, *l_first_radial;
- /**
- * imaginary edge diagonally across quad,
- * \note, this takes advantage of the rules of winding that we
- * know 2 or more of a verts edges wont reference the same face twice.
- * Also, if the edge is hidden, the face will be hidden too.
- */
- l_iter_radial = l_first_radial = e_iter->l;
-
- do {
- if ((l_iter_radial->v == v) &&
- (l_iter_radial->f->len == 4) &&
- (BM_elem_flag_test(l_iter_radial->f, BM_ELEM_HIDDEN) == 0))
- {
- BMVert *v_other = l_iter_radial->next->next->v;
- if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) {
- if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
- BM_elem_flag_enable(v_other, BM_ELEM_TAG);
- BLI_LINKSTACK_PUSH(queue_next, v_other);
- }
- }
- }
- } while ((l_iter_radial = l_iter_radial->radial_next) != l_first_radial);
- }
- }
- } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first);
- }
- }
-
-
- /* clear for the next loop */
- for (lnk = queue_next; lnk; lnk = lnk->next) {
- BMVert *v_link = lnk->link;
- const int i = BM_elem_index_get(v_link);
-
- BM_elem_flag_disable(v_link, BM_ELEM_TAG);
-
- /* keep in sync, avoid having to do full memcpy each iteration */
- dists_prev[i] = dists[i];
- if (index != NULL) {
- index_prev[i] = index[i];
- }
- }
-
- BLI_LINKSTACK_SWAP(queue, queue_next);
-
- /* none should be tagged now since 'queue_next' is empty */
- BLI_assert(BM_iter_mesh_count_flag(BM_VERTS_OF_MESH, bm, BM_ELEM_TAG, true) == 0);
-
- } while (BLI_LINKSTACK_SIZE(queue));
-
- BLI_LINKSTACK_FREE(queue);
- BLI_LINKSTACK_FREE(queue_next);
-
- MEM_freeN(dists_prev);
- if (index_prev != NULL) {
- MEM_freeN(index_prev);
- }
-}
-
-static struct TransIslandData *editmesh_islands_info_calc(
- BMEditMesh *em, int *r_island_tot, int **r_island_vert_map,
- bool calc_single_islands)
-{
- BMesh *bm = em->bm;
- struct TransIslandData *trans_islands;
- char htype;
- char itype;
- int i;
-
- /* group vars */
- int *groups_array;
- int (*group_index)[2];
- int group_tot;
- void **ele_array;
-
- int *vert_map;
-
- if (em->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
- groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totedgesel, __func__);
- group_tot = BM_mesh_calc_edge_groups(bm, groups_array, &group_index,
- NULL, NULL,
- BM_ELEM_SELECT);
-
- htype = BM_EDGE;
- itype = BM_VERTS_OF_EDGE;
-
- }
- else { /* (bm->selectmode & SCE_SELECT_FACE) */
- groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__);
- group_tot = BM_mesh_calc_face_groups(bm, groups_array, &group_index,
- NULL, NULL,
- BM_ELEM_SELECT, BM_VERT);
-
- htype = BM_FACE;
- itype = BM_VERTS_OF_FACE;
- }
-
-
- trans_islands = MEM_mallocN(sizeof(*trans_islands) * group_tot, __func__);
-
- vert_map = MEM_mallocN(sizeof(*vert_map) * bm->totvert, __func__);
- /* we shouldn't need this, but with incorrect selection flushing
- * its possible we have a selected vertex that's not in a face,
- * for now best not crash in that case. */
- copy_vn_i(vert_map, bm->totvert, -1);
-
- BM_mesh_elem_table_ensure(bm, htype);
- ele_array = (htype == BM_FACE) ? (void **)bm->ftable : (void **)bm->etable;
-
- BM_mesh_elem_index_ensure(bm, BM_VERT);
-
- /* may be an edge OR a face array */
- for (i = 0; i < group_tot; i++) {
- BMEditSelection ese = {NULL};
-
- const int fg_sta = group_index[i][0];
- const int fg_len = group_index[i][1];
- float co[3], no[3], tangent[3];
- int j;
-
- zero_v3(co);
- zero_v3(no);
- zero_v3(tangent);
-
- ese.htype = htype;
-
- /* loop on each face in this group:
- * - assign r_vert_map
- * - calculate (co, no)
- */
- for (j = 0; j < fg_len; j++) {
- float tmp_co[3], tmp_no[3], tmp_tangent[3];
-
- 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);
-
- {
- /* setup vertex map */
- BMIter iter;
- BMVert *v;
-
- /* connected edge-verts */
- BM_ITER_ELEM (v, &iter, ese.ele, itype) {
- vert_map[BM_elem_index_get(v)] = i;
- }
- }
- }
-
- mul_v3_v3fl(trans_islands[i].co, 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);
- }
- else {
- unit_m3(trans_islands[i].axismtx);
- }
- }
- }
-
- MEM_freeN(groups_array);
- MEM_freeN(group_index);
-
- /* for PET we need islands of 1 so connected vertices can use it with V3D_AROUND_LOCAL_ORIGINS */
- if (calc_single_islands) {
- BMIter viter;
- BMVert *v;
- int group_tot_single = 0;
-
- 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)) {
- group_tot_single += 1;
- }
- }
-
- if (group_tot_single != 0) {
- trans_islands = MEM_reallocN(trans_islands, sizeof(*trans_islands) * (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(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);
- }
-
- group_tot += 1;
- }
- }
- }
- }
-
- *r_island_tot = group_tot;
- *r_island_vert_map = vert_map;
-
- return trans_islands;
+ while ((v = BLI_LINKSTACK_POP(queue))) {
+ BLI_assert(dists[BM_elem_index_get(v)] != FLT_MAX);
+
+ /* connected edge-verts */
+ if (v->e != NULL) {
+ BMEdge *e_iter, *e_first;
+
+ e_iter = e_first = v->e;
+
+ /* would normally use BM_EDGES_OF_VERT, but this runs so often,
+ * its faster to iterate on the data directly */
+ do {
+
+ if (BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == 0) {
+
+ /* edge distance */
+ {
+ BMVert *v_other = BM_edge_other_vert(e_iter, v);
+ if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) {
+ if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
+ BM_elem_flag_enable(v_other, BM_ELEM_TAG);
+ BLI_LINKSTACK_PUSH(queue_next, v_other);
+ }
+ }
+ }
+
+ /* face distance */
+ if (e_iter->l) {
+ BMLoop *l_iter_radial, *l_first_radial;
+ /**
+ * imaginary edge diagonally across quad,
+ * \note, this takes advantage of the rules of winding that we
+ * know 2 or more of a verts edges wont reference the same face twice.
+ * Also, if the edge is hidden, the face will be hidden too.
+ */
+ l_iter_radial = l_first_radial = e_iter->l;
+
+ do {
+ if ((l_iter_radial->v == v) && (l_iter_radial->f->len == 4) &&
+ (BM_elem_flag_test(l_iter_radial->f, BM_ELEM_HIDDEN) == 0)) {
+ BMVert *v_other = l_iter_radial->next->next->v;
+ if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) {
+ if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
+ BM_elem_flag_enable(v_other, BM_ELEM_TAG);
+ BLI_LINKSTACK_PUSH(queue_next, v_other);
+ }
+ }
+ }
+ } while ((l_iter_radial = l_iter_radial->radial_next) != l_first_radial);
+ }
+ }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first);
+ }
+ }
+
+ /* clear for the next loop */
+ for (lnk = queue_next; lnk; lnk = lnk->next) {
+ BMVert *v_link = lnk->link;
+ const int i = BM_elem_index_get(v_link);
+
+ BM_elem_flag_disable(v_link, BM_ELEM_TAG);
+
+ /* keep in sync, avoid having to do full memcpy each iteration */
+ dists_prev[i] = dists[i];
+ if (index != NULL) {
+ index_prev[i] = index[i];
+ }
+ }
+
+ BLI_LINKSTACK_SWAP(queue, queue_next);
+
+ /* none should be tagged now since 'queue_next' is empty */
+ BLI_assert(BM_iter_mesh_count_flag(BM_VERTS_OF_MESH, bm, BM_ELEM_TAG, true) == 0);
+
+ } while (BLI_LINKSTACK_SIZE(queue));
+
+ BLI_LINKSTACK_FREE(queue);
+ BLI_LINKSTACK_FREE(queue_next);
+
+ MEM_freeN(dists_prev);
+ if (index_prev != NULL) {
+ MEM_freeN(index_prev);
+ }
+}
+
+static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em,
+ int *r_island_tot,
+ int **r_island_vert_map,
+ bool calc_single_islands)
+{
+ BMesh *bm = em->bm;
+ struct TransIslandData *trans_islands;
+ char htype;
+ char itype;
+ int i;
+
+ /* group vars */
+ int *groups_array;
+ int(*group_index)[2];
+ int group_tot;
+ void **ele_array;
+
+ int *vert_map;
+
+ if (em->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
+ groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totedgesel, __func__);
+ group_tot = BM_mesh_calc_edge_groups(
+ bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT);
+
+ htype = BM_EDGE;
+ itype = BM_VERTS_OF_EDGE;
+ }
+ else { /* (bm->selectmode & SCE_SELECT_FACE) */
+ groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__);
+ group_tot = BM_mesh_calc_face_groups(
+ bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT, BM_VERT);
+
+ htype = BM_FACE;
+ itype = BM_VERTS_OF_FACE;
+ }
+
+ trans_islands = MEM_mallocN(sizeof(*trans_islands) * group_tot, __func__);
+
+ vert_map = MEM_mallocN(sizeof(*vert_map) * bm->totvert, __func__);
+ /* we shouldn't need this, but with incorrect selection flushing
+ * its possible we have a selected vertex that's not in a face,
+ * for now best not crash in that case. */
+ copy_vn_i(vert_map, bm->totvert, -1);
+
+ BM_mesh_elem_table_ensure(bm, htype);
+ ele_array = (htype == BM_FACE) ? (void **)bm->ftable : (void **)bm->etable;
+
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+ /* may be an edge OR a face array */
+ for (i = 0; i < group_tot; i++) {
+ BMEditSelection ese = {NULL};
+
+ const int fg_sta = group_index[i][0];
+ const int fg_len = group_index[i][1];
+ float co[3], no[3], tangent[3];
+ int j;
+
+ zero_v3(co);
+ zero_v3(no);
+ zero_v3(tangent);
+
+ ese.htype = htype;
+
+ /* loop on each face in this group:
+ * - assign r_vert_map
+ * - calculate (co, no)
+ */
+ for (j = 0; j < fg_len; j++) {
+ float tmp_co[3], tmp_no[3], tmp_tangent[3];
+
+ 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);
+
+ {
+ /* setup vertex map */
+ BMIter iter;
+ BMVert *v;
+
+ /* connected edge-verts */
+ BM_ITER_ELEM (v, &iter, ese.ele, itype) {
+ vert_map[BM_elem_index_get(v)] = i;
+ }
+ }
+ }
+
+ mul_v3_v3fl(trans_islands[i].co, 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);
+ }
+ else {
+ unit_m3(trans_islands[i].axismtx);
+ }
+ }
+ }
+
+ MEM_freeN(groups_array);
+ MEM_freeN(group_index);
+
+ /* for PET we need islands of 1 so connected vertices can use it with V3D_AROUND_LOCAL_ORIGINS */
+ if (calc_single_islands) {
+ BMIter viter;
+ BMVert *v;
+ int group_tot_single = 0;
+
+ 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)) {
+ group_tot_single += 1;
+ }
+ }
+
+ if (group_tot_single != 0) {
+ trans_islands = MEM_reallocN(trans_islands,
+ sizeof(*trans_islands) * (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(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);
+ }
+
+ group_tot += 1;
+ }
+ }
+ }
+ }
+
+ *r_island_tot = group_tot;
+ *r_island_vert_map = vert_map;
+
+ return trans_islands;
}
/* way to overwrite what data is edited with transform */
-static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx,
- BMEditMesh *em, BMVert *eve, float *bweight,
- struct TransIslandData *v_island, const bool no_island_center)
-{
- float *no, _no[3];
- BLI_assert(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) == 0);
-
- td->flag = 0;
- //if (key)
- // td->loc = key->co;
- //else
- td->loc = eve->co;
- copy_v3_v3(td->iloc, td->loc);
-
- if ((t->mode == TFM_SHRINKFATTEN) &&
- (em->selectmode & SCE_SELECT_FACE) &&
- BM_elem_flag_test(eve, BM_ELEM_SELECT) &&
- (BM_vert_calc_normal_ex(eve, BM_ELEM_SELECT, _no)))
- {
- no = _no;
- }
- else {
- no = eve->no;
- }
-
- if (v_island) {
- if (no_island_center) {
- copy_v3_v3(td->center, td->loc);
- }
- else {
- copy_v3_v3(td->center, v_island->co);
- }
- copy_m3_m3(td->axismtx, v_island->axismtx);
- }
- else if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
- copy_v3_v3(td->center, td->loc);
- createSpaceNormal(td->axismtx, no);
- }
- else {
- copy_v3_v3(td->center, td->loc);
-
- /* Setting normals */
- copy_v3_v3(td->axismtx[2], no);
- td->axismtx[0][0] =
- td->axismtx[0][1] =
- td->axismtx[0][2] =
- td->axismtx[1][0] =
- td->axismtx[1][1] =
- td->axismtx[1][2] = 0.0f;
- }
-
-
- td->ext = NULL;
- td->val = NULL;
- td->extra = NULL;
- if (t->mode == TFM_BWEIGHT) {
- td->val = bweight;
- td->ival = *bweight;
- }
- else if (t->mode == TFM_SKIN_RESIZE) {
- MVertSkin *vs = CustomData_bmesh_get(&em->bm->vdata,
- eve->head.data,
- CD_MVERT_SKIN);
- /* skin node size */
- td->ext = tx;
- copy_v3_v3(tx->isize, vs->radius);
- tx->size = vs->radius;
- td->val = vs->radius;
- }
- else if (t->mode == TFM_SHRINKFATTEN) {
- td->ext = tx;
- tx->isize[0] = BM_vert_calc_shell_factor_ex(eve, no, BM_ELEM_SELECT);
- }
+static void VertsToTransData(TransInfo *t,
+ TransData *td,
+ TransDataExtension *tx,
+ BMEditMesh *em,
+ BMVert *eve,
+ float *bweight,
+ struct TransIslandData *v_island,
+ const bool no_island_center)
+{
+ float *no, _no[3];
+ BLI_assert(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) == 0);
+
+ td->flag = 0;
+ //if (key)
+ // td->loc = key->co;
+ //else
+ td->loc = eve->co;
+ copy_v3_v3(td->iloc, td->loc);
+
+ if ((t->mode == TFM_SHRINKFATTEN) && (em->selectmode & SCE_SELECT_FACE) &&
+ BM_elem_flag_test(eve, BM_ELEM_SELECT) &&
+ (BM_vert_calc_normal_ex(eve, BM_ELEM_SELECT, _no))) {
+ no = _no;
+ }
+ else {
+ no = eve->no;
+ }
+
+ if (v_island) {
+ if (no_island_center) {
+ copy_v3_v3(td->center, td->loc);
+ }
+ else {
+ copy_v3_v3(td->center, v_island->co);
+ }
+ copy_m3_m3(td->axismtx, v_island->axismtx);
+ }
+ else if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ copy_v3_v3(td->center, td->loc);
+ createSpaceNormal(td->axismtx, no);
+ }
+ else {
+ copy_v3_v3(td->center, td->loc);
+
+ /* Setting normals */
+ copy_v3_v3(td->axismtx[2], no);
+ td->axismtx[0][0] = td->axismtx[0][1] = td->axismtx[0][2] = td->axismtx[1][0] =
+ td->axismtx[1][1] = td->axismtx[1][2] = 0.0f;
+ }
+
+ td->ext = NULL;
+ td->val = NULL;
+ td->extra = NULL;
+ if (t->mode == TFM_BWEIGHT) {
+ td->val = bweight;
+ td->ival = *bweight;
+ }
+ else if (t->mode == TFM_SKIN_RESIZE) {
+ MVertSkin *vs = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MVERT_SKIN);
+ /* skin node size */
+ td->ext = tx;
+ copy_v3_v3(tx->isize, vs->radius);
+ tx->size = vs->radius;
+ td->val = vs->radius;
+ }
+ else if (t->mode == TFM_SHRINKFATTEN) {
+ td->ext = tx;
+ tx->isize[0] = BM_vert_calc_shell_factor_ex(eve, no, BM_ELEM_SELECT);
+ }
}
static void createTransEditVerts(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *tob = NULL;
- TransDataExtension *tx = NULL;
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- Mesh *me = tc->obedit->data;
- BMesh *bm = em->bm;
- BMVert *eve;
- BMIter iter;
- float (*mappedcos)[3] = NULL, (*quats)[4] = NULL;
- float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
- float *dists = NULL;
- int a;
- const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
- int mirror = 0;
- int cd_vert_bweight_offset = -1;
- bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
-
- struct TransIslandData *island_info = NULL;
- int island_info_tot;
- int *island_vert_map = NULL;
-
- /* Snap rotation along normal needs a common axis for whole islands,
- * otherwise one get random crazy results, see T59104.
- * However, we do not want to use the island center for the pivot/translation reference. */
- const bool is_snap_rotate = ((t->mode == TFM_TRANSLATION) &&
- /* There is not guarantee that snapping
- * is initialized yet at this point... */
- (usingSnappingNormal(t) || (t->settings->snap_flag & SCE_SNAP_ROTATE) != 0) &&
- (t->around != V3D_AROUND_LOCAL_ORIGINS));
- /* Even for translation this is needed because of island-orientation, see: T51651. */
- const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) || is_snap_rotate;
- /* Original index of our connected vertex when connected distances are calculated.
- * Optional, allocate if needed. */
- int *dists_index = NULL;
-
- if (tc->mirror.axis_flag) {
- EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology);
- mirror = 1;
- }
-
- /**
- * Quick check if we can transform.
- *
- * \note ignore modes here, even in edge/face modes, transform data is created by selected vertices.
- * \note in prop mode we need at least 1 selected.
- */
- if (bm->totvertsel == 0) {
- goto cleanup;
- }
-
- if (t->mode == TFM_BWEIGHT) {
- BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_VERT_BWEIGHT);
- cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
- }
-
- if (prop_mode) {
- unsigned int count = 0;
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- count++;
- }
- }
-
- tc->data_len = count;
-
- /* allocating scratch arrays */
- if (prop_mode & T_PROP_CONNECTED) {
- dists = MEM_mallocN(em->bm->totvert * sizeof(float), __func__);
- if (is_island_center) {
- dists_index = MEM_mallocN(em->bm->totvert * sizeof(int), __func__);
- }
- }
- }
- else {
- tc->data_len = bm->totvertsel;
- }
-
- tob = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Mesh EditMode)");
- if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) {
- /* warning, this is overkill, we only need 2 extra floats,
- * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill
- * since we may not use the 'alt' transform mode to maintain shell thickness,
- * but with generic transform code its hard to lazy init vars */
- tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), "TransObData ext");
- }
-
- copy_m3_m4(mtx, tc->obedit->obmat);
- /* we use a pseudo-inverse so that when one of the axes is scaled to 0,
- * matrix inversion still works and we can still moving along the other */
- pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
-
- if (prop_mode & T_PROP_CONNECTED) {
- editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index);
- }
-
- if (is_island_center) {
- /* In this specific case, near-by vertices will need to know the island of the nearest connected vertex. */
- const bool calc_single_islands = (
- (prop_mode & T_PROP_CONNECTED) &&
- (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);
- }
-
- /* detect CrazySpace [tm] */
- if (modifiers_getCageIndex(t->scene, tc->obedit, NULL, 1) != -1) {
- int totleft = -1;
- if (modifiers_isCorrectableDeformed(t->scene, tc->obedit)) {
- /* Use evaluated state because we need b-bone cache. */
- Scene *scene_eval = (Scene *)DEG_get_evaluated_id(t->depsgraph, &t->scene->id);
- Object *obedit_eval = (Object *)DEG_get_evaluated_id(t->depsgraph, &tc->obedit->id);
- BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval);
- /* check if we can use deform matrices for modifier from the
- * start up to stack, they are more accurate than quats */
- totleft = BKE_crazyspace_get_first_deform_matrices_editbmesh(
- t->depsgraph, scene_eval, obedit_eval, em_eval,
- &defmats, &defcos);
- }
-
- /* if we still have more modifiers, also do crazyspace
- * correction with quats, relative to the coordinates after
- * the modifiers that support deform matrices (defcos) */
-
-#if 0 /* TODO, fix crazyspace+extrude so it can be enabled for general use - campbell */
- if ((totleft > 0) || (totleft == -1))
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *tob = NULL;
+ TransDataExtension *tx = NULL;
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ Mesh *me = tc->obedit->data;
+ BMesh *bm = em->bm;
+ BMVert *eve;
+ BMIter iter;
+ float(*mappedcos)[3] = NULL, (*quats)[4] = NULL;
+ float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
+ float *dists = NULL;
+ int a;
+ const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
+ int mirror = 0;
+ int cd_vert_bweight_offset = -1;
+ bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+
+ struct TransIslandData *island_info = NULL;
+ int island_info_tot;
+ int *island_vert_map = NULL;
+
+ /* Snap rotation along normal needs a common axis for whole islands,
+ * otherwise one get random crazy results, see T59104.
+ * However, we do not want to use the island center for the pivot/translation reference. */
+ const bool is_snap_rotate = ((t->mode == TFM_TRANSLATION) &&
+ /* There is not guarantee that snapping
+ * is initialized yet at this point... */
+ (usingSnappingNormal(t) ||
+ (t->settings->snap_flag & SCE_SNAP_ROTATE) != 0) &&
+ (t->around != V3D_AROUND_LOCAL_ORIGINS));
+ /* Even for translation this is needed because of island-orientation, see: T51651. */
+ const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) || is_snap_rotate;
+ /* Original index of our connected vertex when connected distances are calculated.
+ * Optional, allocate if needed. */
+ int *dists_index = NULL;
+
+ if (tc->mirror.axis_flag) {
+ EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology);
+ mirror = 1;
+ }
+
+ /**
+ * Quick check if we can transform.
+ *
+ * \note ignore modes here, even in edge/face modes, transform data is created by selected vertices.
+ * \note in prop mode we need at least 1 selected.
+ */
+ if (bm->totvertsel == 0) {
+ goto cleanup;
+ }
+
+ if (t->mode == TFM_BWEIGHT) {
+ BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_VERT_BWEIGHT);
+ cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
+ }
+
+ if (prop_mode) {
+ unsigned int count = 0;
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+ count++;
+ }
+ }
+
+ tc->data_len = count;
+
+ /* allocating scratch arrays */
+ if (prop_mode & T_PROP_CONNECTED) {
+ dists = MEM_mallocN(em->bm->totvert * sizeof(float), __func__);
+ if (is_island_center) {
+ dists_index = MEM_mallocN(em->bm->totvert * sizeof(int), __func__);
+ }
+ }
+ }
+ else {
+ tc->data_len = bm->totvertsel;
+ }
+
+ tob = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Mesh EditMode)");
+ if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) {
+ /* warning, this is overkill, we only need 2 extra floats,
+ * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill
+ * since we may not use the 'alt' transform mode to maintain shell thickness,
+ * but with generic transform code its hard to lazy init vars */
+ tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension),
+ "TransObData ext");
+ }
+
+ copy_m3_m4(mtx, tc->obedit->obmat);
+ /* we use a pseudo-inverse so that when one of the axes is scaled to 0,
+ * matrix inversion still works and we can still moving along the other */
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
+
+ if (prop_mode & T_PROP_CONNECTED) {
+ editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index);
+ }
+
+ if (is_island_center) {
+ /* In this specific case, near-by vertices will need to know the island of the nearest connected vertex. */
+ const bool calc_single_islands = ((prop_mode & T_PROP_CONNECTED) &&
+ (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);
+ }
+
+ /* detect CrazySpace [tm] */
+ if (modifiers_getCageIndex(t->scene, tc->obedit, NULL, 1) != -1) {
+ int totleft = -1;
+ if (modifiers_isCorrectableDeformed(t->scene, tc->obedit)) {
+ /* Use evaluated state because we need b-bone cache. */
+ Scene *scene_eval = (Scene *)DEG_get_evaluated_id(t->depsgraph, &t->scene->id);
+ Object *obedit_eval = (Object *)DEG_get_evaluated_id(t->depsgraph, &tc->obedit->id);
+ BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval);
+ /* check if we can use deform matrices for modifier from the
+ * start up to stack, they are more accurate than quats */
+ totleft = BKE_crazyspace_get_first_deform_matrices_editbmesh(
+ t->depsgraph, scene_eval, obedit_eval, em_eval, &defmats, &defcos);
+ }
+
+ /* if we still have more modifiers, also do crazyspace
+ * correction with quats, relative to the coordinates after
+ * the modifiers that support deform matrices (defcos) */
+
+#if 0 /* TODO, fix crazyspace+extrude so it can be enabled for general use - campbell */
+ if ((totleft > 0) || (totleft == -1))
#else
- if (totleft > 0)
+ if (totleft > 0)
#endif
- {
- mappedcos = BKE_crazyspace_get_mapped_editverts(t->depsgraph, t->scene, tc->obedit);
- quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats");
- BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode);
- if (mappedcos)
- MEM_freeN(mappedcos);
- }
-
- if (defcos) {
- MEM_freeN(defcos);
- }
- }
-
- /* find out which half we do */
- if (mirror) {
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && eve->co[0] != 0.0f) {
- if (eve->co[0] < 0.0f) {
- tc->mirror.sign = -1.0f;
- mirror = -1;
- }
- break;
- }
- }
- }
-
- BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
- if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- 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) {
- 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;
- }
-
-
- /* 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);
- if (tx)
- tx++;
-
- /* selected */
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT))
- tob->flag |= TD_SELECTED;
-
- if (prop_mode) {
- if (prop_mode & T_PROP_CONNECTED) {
- tob->dist = dists[a];
- }
- else {
- tob->flag |= TD_NOTCONNECTED;
- tob->dist = FLT_MAX;
- }
- }
-
- /* CrazySpace */
- if (defmats || (quats && BM_elem_flag_test(eve, BM_ELEM_TAG))) {
- float mat[3][3], qmat[3][3], imat[3][3];
-
- /* use both or either quat and defmat correction */
- if (quats && BM_elem_flag_test(eve, BM_ELEM_TAG)) {
- quat_to_mat3(qmat, quats[BM_elem_index_get(eve)]);
-
- if (defmats)
- mul_m3_series(mat, defmats[a], qmat, mtx);
- else
- mul_m3_m3m3(mat, mtx, qmat);
- }
- else
- mul_m3_m3m3(mat, mtx, defmats[a]);
-
- invert_m3_m3(imat, mat);
-
- copy_m3_m3(tob->smtx, imat);
- copy_m3_m3(tob->mtx, mat);
- }
- else {
- copy_m3_m3(tob->smtx, smtx);
- copy_m3_m3(tob->mtx, mtx);
- }
-
- /* Mirror? */
- if ((mirror > 0 && tob->iloc[0] > 0.0f) || (mirror < 0 && tob->iloc[0] < 0.0f)) {
- BMVert *vmir = EDBM_verts_mirror_get(em, eve); //t->obedit, em, eve, tob->iloc, a);
- if (vmir && vmir != eve) {
- tob->extra = vmir;
- }
- }
- tob++;
- }
- }
- }
-
- if (island_info) {
- MEM_freeN(island_info);
- MEM_freeN(island_vert_map);
- }
-
- if (mirror != 0) {
- tob = tc->data;
- for (a = 0; a < tc->data_len; a++, tob++) {
- if (ABS(tob->loc[0]) <= 0.00001f) {
- tob->flag |= TD_MIRROR_EDGE;
- }
- }
- }
-
-cleanup:
- /* crazy space free */
- if (quats)
- MEM_freeN(quats);
- if (defmats)
- MEM_freeN(defmats);
- if (dists)
- MEM_freeN(dists);
- if (dists_index)
- MEM_freeN(dists_index);
-
- if (tc->mirror.axis_flag) {
- EDBM_verts_mirror_cache_end(em);
- }
- }
+ {
+ mappedcos = BKE_crazyspace_get_mapped_editverts(t->depsgraph, t->scene, tc->obedit);
+ quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats");
+ BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode);
+ if (mappedcos)
+ MEM_freeN(mappedcos);
+ }
+
+ if (defcos) {
+ MEM_freeN(defcos);
+ }
+ }
+
+ /* find out which half we do */
+ if (mirror) {
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && eve->co[0] != 0.0f) {
+ if (eve->co[0] < 0.0f) {
+ tc->mirror.sign = -1.0f;
+ mirror = -1;
+ }
+ break;
+ }
+ }
+ }
+
+ BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+ 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) {
+ 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;
+ }
+
+ /* 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);
+ if (tx)
+ tx++;
+
+ /* selected */
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT))
+ tob->flag |= TD_SELECTED;
+
+ if (prop_mode) {
+ if (prop_mode & T_PROP_CONNECTED) {
+ tob->dist = dists[a];
+ }
+ else {
+ tob->flag |= TD_NOTCONNECTED;
+ tob->dist = FLT_MAX;
+ }
+ }
+
+ /* CrazySpace */
+ if (defmats || (quats && BM_elem_flag_test(eve, BM_ELEM_TAG))) {
+ float mat[3][3], qmat[3][3], imat[3][3];
+
+ /* use both or either quat and defmat correction */
+ if (quats && BM_elem_flag_test(eve, BM_ELEM_TAG)) {
+ quat_to_mat3(qmat, quats[BM_elem_index_get(eve)]);
+
+ if (defmats)
+ mul_m3_series(mat, defmats[a], qmat, mtx);
+ else
+ mul_m3_m3m3(mat, mtx, qmat);
+ }
+ else
+ mul_m3_m3m3(mat, mtx, defmats[a]);
+
+ invert_m3_m3(imat, mat);
+
+ copy_m3_m3(tob->smtx, imat);
+ copy_m3_m3(tob->mtx, mat);
+ }
+ else {
+ copy_m3_m3(tob->smtx, smtx);
+ copy_m3_m3(tob->mtx, mtx);
+ }
+
+ /* Mirror? */
+ if ((mirror > 0 && tob->iloc[0] > 0.0f) || (mirror < 0 && tob->iloc[0] < 0.0f)) {
+ BMVert *vmir = EDBM_verts_mirror_get(em, eve); //t->obedit, em, eve, tob->iloc, a);
+ if (vmir && vmir != eve) {
+ tob->extra = vmir;
+ }
+ }
+ tob++;
+ }
+ }
+ }
+
+ if (island_info) {
+ MEM_freeN(island_info);
+ MEM_freeN(island_vert_map);
+ }
+
+ if (mirror != 0) {
+ tob = tc->data;
+ for (a = 0; a < tc->data_len; a++, tob++) {
+ if (ABS(tob->loc[0]) <= 0.00001f) {
+ tob->flag |= TD_MIRROR_EDGE;
+ }
+ }
+ }
+
+ cleanup:
+ /* crazy space free */
+ if (quats)
+ MEM_freeN(quats);
+ if (defmats)
+ MEM_freeN(defmats);
+ if (dists)
+ MEM_freeN(dists);
+ if (dists_index)
+ MEM_freeN(dists_index);
+
+ if (tc->mirror.axis_flag) {
+ EDBM_verts_mirror_cache_end(em);
+ }
+ }
}
/* *** NODE EDITOR *** */
void flushTransNodes(TransInfo *t)
{
- const float dpi_fac = UI_DPI_FAC;
+ const float dpi_fac = UI_DPI_FAC;
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- int a;
- TransData *td;
- TransData2D *td2d;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ int a;
+ TransData *td;
+ TransData2D *td2d;
- applyGridAbsolute(t);
+ applyGridAbsolute(t);
- /* flush to 2d vector from internally used 3d vector */
- for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) {
- bNode *node = td->extra;
- float locx, locy;
+ /* flush to 2d vector from internally used 3d vector */
+ for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) {
+ bNode *node = td->extra;
+ float locx, locy;
- /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */
+ /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */
#ifdef USE_NODE_CENTER
- locx = (td2d->loc[0] - (BLI_rctf_size_x(&node->totr)) * +0.5f) / dpi_fac;
- locy = (td2d->loc[1] - (BLI_rctf_size_y(&node->totr)) * -0.5f) / dpi_fac;
+ locx = (td2d->loc[0] - (BLI_rctf_size_x(&node->totr)) * +0.5f) / dpi_fac;
+ locy = (td2d->loc[1] - (BLI_rctf_size_y(&node->totr)) * -0.5f) / dpi_fac;
#else
- locx = td2d->loc[0] / dpi_fac;
- locy = td2d->loc[1] / dpi_fac;
+ locx = td2d->loc[0] / dpi_fac;
+ locy = td2d->loc[1] / dpi_fac;
#endif
- /* account for parents (nested nodes) */
- if (node->parent) {
- nodeFromView(node->parent, locx, locy, &node->locx, &node->locy);
- }
- else {
- node->locx = locx;
- node->locy = locy;
- }
- }
+ /* account for parents (nested nodes) */
+ if (node->parent) {
+ nodeFromView(node->parent, locx, locy, &node->locx, &node->locy);
+ }
+ else {
+ node->locx = locx;
+ node->locy = locy;
+ }
+ }
- /* handle intersection with noodles */
- if (tc->data_len == 1) {
- ED_node_link_intersect_test(t->sa, 1);
- }
- }
+ /* handle intersection with noodles */
+ if (tc->data_len == 1) {
+ ED_node_link_intersect_test(t->sa, 1);
+ }
+ }
}
/* *** SEQUENCE EDITOR *** */
@@ -2981,476 +3053,485 @@ void flushTransNodes(TransInfo *t)
BLI_INLINE void trans_update_seq(Scene *sce, Sequence *seq, int old_start, int sel_flag)
{
- if (seq->depth == 0) {
- /* Calculate this strip and all nested strips.
- * Children are ALWAYS transformed first so we don't need to do this in another loop.
- */
- BKE_sequence_calc(sce, seq);
- }
- else {
- BKE_sequence_calc_disp(sce, seq);
- }
+ if (seq->depth == 0) {
+ /* Calculate this strip and all nested strips.
+ * Children are ALWAYS transformed first so we don't need to do this in another loop.
+ */
+ BKE_sequence_calc(sce, seq);
+ }
+ else {
+ BKE_sequence_calc_disp(sce, seq);
+ }
- if (sel_flag == SELECT)
- BKE_sequencer_offset_animdata(sce, seq, seq->start - old_start);
+ if (sel_flag == SELECT)
+ BKE_sequencer_offset_animdata(sce, seq, seq->start - old_start);
}
void flushTransSeq(TransInfo *t)
{
- /* Editing null check already done */
- ListBase *seqbasep = BKE_sequencer_editing_get(t->scene, false)->seqbasep;
-
- int a, new_frame;
- TransData *td = NULL;
- TransData2D *td2d = NULL;
- TransDataSeq *tdsq = NULL;
- Sequence *seq;
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* prevent updating the same seq twice
- * if the transdata order is changed this will mess up
- * but so will TransDataSeq */
- Sequence *seq_prev = NULL;
- int old_start_prev = 0, sel_flag_prev = 0;
-
- /* flush to 2d vector from internally used 3d vector */
- for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) {
- int old_start;
- tdsq = (TransDataSeq *)td->extra;
- seq = tdsq->seq;
- old_start = seq->start;
- new_frame = round_fl_to_int(td2d->loc[0]);
-
- switch (tdsq->sel_flag) {
- case SELECT:
+ /* Editing null check already done */
+ ListBase *seqbasep = BKE_sequencer_editing_get(t->scene, false)->seqbasep;
+
+ int a, new_frame;
+ TransData *td = NULL;
+ TransData2D *td2d = NULL;
+ TransDataSeq *tdsq = NULL;
+ Sequence *seq;
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* prevent updating the same seq twice
+ * if the transdata order is changed this will mess up
+ * but so will TransDataSeq */
+ Sequence *seq_prev = NULL;
+ int old_start_prev = 0, sel_flag_prev = 0;
+
+ /* flush to 2d vector from internally used 3d vector */
+ for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) {
+ int old_start;
+ tdsq = (TransDataSeq *)td->extra;
+ seq = tdsq->seq;
+ old_start = seq->start;
+ new_frame = round_fl_to_int(td2d->loc[0]);
+
+ switch (tdsq->sel_flag) {
+ case SELECT:
#ifdef SEQ_TX_NESTED_METAS
- if ((seq->depth != 0 || BKE_sequence_tx_test(seq))) {
- /* for meta's, their children move */
- seq->start = new_frame - tdsq->start_offset;
- }
+ if ((seq->depth != 0 || BKE_sequence_tx_test(seq))) {
+ /* for meta's, their children move */
+ seq->start = new_frame - tdsq->start_offset;
+ }
#else
- if (seq->type != SEQ_TYPE_META && (seq->depth != 0 || seq_tx_test(seq))) {
- /* for meta's, their children move */
- seq->start = new_frame - tdsq->start_offset;
- }
+ if (seq->type != SEQ_TYPE_META && (seq->depth != 0 || seq_tx_test(seq))) {
+ /* for meta's, their children move */
+ seq->start = new_frame - tdsq->start_offset;
+ }
#endif
- if (seq->depth == 0) {
- seq->machine = round_fl_to_int(td2d->loc[1]);
- CLAMP(seq->machine, 1, MAXSEQ);
- }
- break;
- case SEQ_LEFTSEL: /* no vertical transform */
- BKE_sequence_tx_set_final_left(seq, new_frame);
- BKE_sequence_tx_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
-
- /* todo - move this into aftertrans update? - old seq tx needed it anyway */
- BKE_sequence_single_fix(seq);
- break;
- case SEQ_RIGHTSEL: /* no vertical transform */
- BKE_sequence_tx_set_final_right(seq, new_frame);
- BKE_sequence_tx_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
-
- /* todo - move this into aftertrans update? - old seq tx needed it anyway */
- BKE_sequence_single_fix(seq);
- break;
- }
-
- /* Update *previous* seq! Else, we would update a seq after its first transform, and if it has more than one
- * (like e.g. SEQ_LEFTSEL and SEQ_RIGHTSEL), the others are not updated! See T38469.
- */
- if (seq != seq_prev) {
- if (seq_prev) {
- trans_update_seq(t->scene, seq_prev, old_start_prev, sel_flag_prev);
- }
-
- seq_prev = seq;
- old_start_prev = old_start;
- sel_flag_prev = tdsq->sel_flag;
- }
- else {
- /* We want to accumulate *all* sel_flags for this seq! */
- sel_flag_prev |= tdsq->sel_flag;
- }
- }
-
- /* Don't forget to update the last seq! */
- if (seq_prev) {
- trans_update_seq(t->scene, seq_prev, old_start_prev, sel_flag_prev);
- }
-
- /* originally TFM_TIME_EXTEND, transform changes */
- if (ELEM(t->mode, TFM_SEQ_SLIDE, TFM_TIME_TRANSLATE)) {
- /* Special annoying case here, need to calc metas with TFM_TIME_EXTEND only */
-
- /* calc all meta's then effects [#27953] */
- for (seq = seqbasep->first; seq; seq = seq->next) {
- if (seq->type == SEQ_TYPE_META && seq->flag & SELECT) {
- BKE_sequence_calc(t->scene, seq);
- }
- }
- for (seq = seqbasep->first; seq; seq = seq->next) {
- if (seq->seq1 || seq->seq2 || seq->seq3) {
- BKE_sequence_calc(t->scene, seq);
- }
- }
-
- /* update effects inside meta's */
- for (a = 0, seq_prev = NULL, td = tc->data, td2d = tc->data_2d;
- a < tc->data_len;
- a++, td++, td2d++, seq_prev = seq)
- {
- tdsq = (TransDataSeq *)td->extra;
- seq = tdsq->seq;
- if ((seq != seq_prev) && (seq->depth != 0)) {
- if (seq->seq1 || seq->seq2 || seq->seq3) {
- BKE_sequence_calc(t->scene, seq);
- }
- }
- }
- }
-
- /* need to do the overlap check in a new loop otherwise adjacent strips
- * will not be updated and we'll get false positives */
- seq_prev = NULL;
- for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) {
-
- tdsq = (TransDataSeq *)td->extra;
- seq = tdsq->seq;
-
- if (seq != seq_prev) {
- if (seq->depth == 0) {
- /* test overlap, displays red outline */
- seq->flag &= ~SEQ_OVERLAP;
- if (BKE_sequence_test_overlap(seqbasep, seq)) {
- seq->flag |= SEQ_OVERLAP;
- }
- }
- }
- seq_prev = seq;
- }
+ if (seq->depth == 0) {
+ seq->machine = round_fl_to_int(td2d->loc[1]);
+ CLAMP(seq->machine, 1, MAXSEQ);
+ }
+ break;
+ case SEQ_LEFTSEL: /* no vertical transform */
+ BKE_sequence_tx_set_final_left(seq, new_frame);
+ BKE_sequence_tx_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
+
+ /* todo - move this into aftertrans update? - old seq tx needed it anyway */
+ BKE_sequence_single_fix(seq);
+ break;
+ case SEQ_RIGHTSEL: /* no vertical transform */
+ BKE_sequence_tx_set_final_right(seq, new_frame);
+ BKE_sequence_tx_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
+
+ /* todo - move this into aftertrans update? - old seq tx needed it anyway */
+ BKE_sequence_single_fix(seq);
+ break;
+ }
+
+ /* Update *previous* seq! Else, we would update a seq after its first transform, and if it has more than one
+ * (like e.g. SEQ_LEFTSEL and SEQ_RIGHTSEL), the others are not updated! See T38469.
+ */
+ if (seq != seq_prev) {
+ if (seq_prev) {
+ trans_update_seq(t->scene, seq_prev, old_start_prev, sel_flag_prev);
+ }
+
+ seq_prev = seq;
+ old_start_prev = old_start;
+ sel_flag_prev = tdsq->sel_flag;
+ }
+ else {
+ /* We want to accumulate *all* sel_flags for this seq! */
+ sel_flag_prev |= tdsq->sel_flag;
+ }
+ }
+
+ /* Don't forget to update the last seq! */
+ if (seq_prev) {
+ trans_update_seq(t->scene, seq_prev, old_start_prev, sel_flag_prev);
+ }
+
+ /* originally TFM_TIME_EXTEND, transform changes */
+ if (ELEM(t->mode, TFM_SEQ_SLIDE, TFM_TIME_TRANSLATE)) {
+ /* Special annoying case here, need to calc metas with TFM_TIME_EXTEND only */
+
+ /* calc all meta's then effects [#27953] */
+ for (seq = seqbasep->first; seq; seq = seq->next) {
+ if (seq->type == SEQ_TYPE_META && seq->flag & SELECT) {
+ BKE_sequence_calc(t->scene, seq);
+ }
+ }
+ for (seq = seqbasep->first; seq; seq = seq->next) {
+ if (seq->seq1 || seq->seq2 || seq->seq3) {
+ BKE_sequence_calc(t->scene, seq);
+ }
+ }
+
+ /* update effects inside meta's */
+ for (a = 0, seq_prev = NULL, td = tc->data, td2d = tc->data_2d; a < tc->data_len;
+ a++, td++, td2d++, seq_prev = seq) {
+ tdsq = (TransDataSeq *)td->extra;
+ seq = tdsq->seq;
+ if ((seq != seq_prev) && (seq->depth != 0)) {
+ if (seq->seq1 || seq->seq2 || seq->seq3) {
+ BKE_sequence_calc(t->scene, seq);
+ }
+ }
+ }
+ }
+
+ /* need to do the overlap check in a new loop otherwise adjacent strips
+ * will not be updated and we'll get false positives */
+ seq_prev = NULL;
+ for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) {
+
+ tdsq = (TransDataSeq *)td->extra;
+ seq = tdsq->seq;
+
+ if (seq != seq_prev) {
+ if (seq->depth == 0) {
+ /* test overlap, displays red outline */
+ seq->flag &= ~SEQ_OVERLAP;
+ if (BKE_sequence_test_overlap(seqbasep, seq)) {
+ seq->flag |= SEQ_OVERLAP;
+ }
+ }
+ }
+ seq_prev = seq;
+ }
}
/* ********************* UV ****************** */
-static void UVsToTransData(
- const float aspect[2], TransData *td, TransData2D *td2d,
- float *uv, const float *center, bool selected)
-{
- /* uv coords are scaled by aspects. this is needed for rotations and
- * proportional editing to be consistent with the stretched uv coords
- * that are displayed. this also means that for display and numinput,
- * and when the uv coords are flushed, these are converted each time */
- td2d->loc[0] = uv[0] * aspect[0];
- td2d->loc[1] = uv[1] * aspect[1];
- td2d->loc[2] = 0.0f;
- td2d->loc2d = uv;
-
- td->flag = 0;
- td->loc = td2d->loc;
- copy_v2_v2(td->center, center ? center : td->loc);
- td->center[2] = 0.0f;
- copy_v3_v3(td->iloc, td->loc);
-
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
-
- td->ext = NULL; td->val = NULL;
-
- if (selected) {
- td->flag |= TD_SELECTED;
- td->dist = 0.0;
- }
- else {
- td->dist = FLT_MAX;
- }
- unit_m3(td->mtx);
- unit_m3(td->smtx);
+static void UVsToTransData(const float aspect[2],
+ TransData *td,
+ TransData2D *td2d,
+ float *uv,
+ const float *center,
+ bool selected)
+{
+ /* uv coords are scaled by aspects. this is needed for rotations and
+ * proportional editing to be consistent with the stretched uv coords
+ * that are displayed. this also means that for display and numinput,
+ * and when the uv coords are flushed, these are converted each time */
+ td2d->loc[0] = uv[0] * aspect[0];
+ td2d->loc[1] = uv[1] * aspect[1];
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = uv;
+
+ td->flag = 0;
+ td->loc = td2d->loc;
+ copy_v2_v2(td->center, center ? center : td->loc);
+ td->center[2] = 0.0f;
+ copy_v3_v3(td->iloc, td->loc);
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+
+ if (selected) {
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
+ }
+ else {
+ td->dist = FLT_MAX;
+ }
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
}
static void createTransUVs(bContext *C, TransInfo *t)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
- Scene *scene = t->scene;
- ToolSettings *ts = CTX_data_tool_settings(C);
-
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
- const bool is_prop_connected = (t->flag & T_PROP_CONNECTED) != 0;
- const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS);
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
- TransData *td = NULL;
- TransData2D *td2d = NULL;
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMFace *efa;
- BMIter iter, liter;
- UvElementMap *elementmap = NULL;
- BLI_bitmap *island_enabled = NULL;
- struct { float co[2]; int co_num; } *island_center = NULL;
- int count = 0, countsel = 0, count_rejected = 0;
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- if (!ED_space_image_show_uvedit(sima, tc->obedit)) {
- continue;
- }
-
- /* count */
- if (is_prop_connected || is_island_center) {
- /* create element map with island information */
- const bool use_facesel = (ts->uv_flag & UV_SYNC_SELECTION) == 0;
- elementmap = BM_uv_element_map_create(em->bm, use_facesel, false, true);
- if (elementmap == NULL) {
- return;
- }
-
- if (is_prop_connected) {
- island_enabled = BLI_BITMAP_NEW(elementmap->totalIslands, "TransIslandData(UV Editing)");
- }
-
- if (is_island_center) {
- island_center = MEM_callocN(sizeof(*island_center) * elementmap->totalIslands, __func__);
- }
- }
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BMLoop *l;
-
- if (!uvedit_face_visible_test(scene, tc->obedit, ima, efa)) {
- BM_elem_flag_disable(efa, BM_ELEM_TAG);
- continue;
- }
-
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- countsel++;
-
- if (is_prop_connected || island_center) {
- UvElement *element = BM_uv_element_get(elementmap, efa, l);
-
- if (is_prop_connected) {
- BLI_BITMAP_ENABLE(island_enabled, element->island);
- }
-
- if (is_island_center) {
- if (element->flag == false) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- add_v2_v2(island_center[element->island].co, luv->uv);
- island_center[element->island].co_num++;
- element->flag = true;
- }
- }
- }
- }
-
- if (is_prop_edit) {
- count++;
- }
- }
- }
-
- /* note: in prop mode we need at least 1 selected */
- if (countsel == 0) {
- goto finally;
- }
-
- if (is_island_center) {
- int i;
-
- for (i = 0; i < elementmap->totalIslands; i++) {
- mul_v2_fl(island_center[i].co, 1.0f / island_center[i].co_num);
- mul_v2_v2(island_center[i].co, t->aspect);
- }
- }
-
- tc->data_len = (is_prop_edit) ? count : countsel;
- tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(UV Editing)");
- /* for each 2d uv coord a 3d vector is allocated, so that they can be
- * treated just as if they were 3d verts */
- tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransObData2D(UV Editing)");
-
- if (sima->flag & SI_CLIP_UV)
- t->flag |= T_CLIP_UV;
-
- td = tc->data;
- td2d = tc->data_2d;
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BMLoop *l;
-
- if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
- continue;
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- const bool selected = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
- MLoopUV *luv;
- const float *center = NULL;
-
- if (!is_prop_edit && !selected)
- continue;
-
- if (is_prop_connected || is_island_center) {
- UvElement *element = BM_uv_element_get(elementmap, efa, l);
-
- if (is_prop_connected) {
- if (!BLI_BITMAP_TEST(island_enabled, element->island)) {
- count_rejected++;
- continue;
- }
- }
-
- if (is_island_center) {
- center = island_center[element->island].co;
- }
- }
-
- BM_elem_flag_enable(l, BM_ELEM_TAG);
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- UVsToTransData(t->aspect, td++, td2d++, luv->uv, center, selected);
- }
- }
-
- if (is_prop_connected) {
- tc->data_len -= count_rejected;
- }
-
- if (sima->flag & SI_LIVE_UNWRAP) {
- ED_uvedit_live_unwrap_begin(t->scene, tc->obedit);
- }
-
-finally:
- if (is_prop_connected || is_island_center) {
- BM_uv_element_map_free(elementmap);
-
- if (is_prop_connected) {
- MEM_freeN(island_enabled);
- }
-
- if (island_center) {
- MEM_freeN(island_center);
- }
- }
- }
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = CTX_data_edit_image(C);
+ Scene *scene = t->scene;
+ ToolSettings *ts = CTX_data_tool_settings(C);
+
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+ const bool is_prop_connected = (t->flag & T_PROP_CONNECTED) != 0;
+ const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS);
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+
+ TransData *td = NULL;
+ TransData2D *td2d = NULL;
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMFace *efa;
+ BMIter iter, liter;
+ UvElementMap *elementmap = NULL;
+ BLI_bitmap *island_enabled = NULL;
+ struct {
+ float co[2];
+ int co_num;
+ } *island_center = NULL;
+ int count = 0, countsel = 0, count_rejected = 0;
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ if (!ED_space_image_show_uvedit(sima, tc->obedit)) {
+ continue;
+ }
+
+ /* count */
+ if (is_prop_connected || is_island_center) {
+ /* create element map with island information */
+ const bool use_facesel = (ts->uv_flag & UV_SYNC_SELECTION) == 0;
+ elementmap = BM_uv_element_map_create(em->bm, use_facesel, false, true);
+ if (elementmap == NULL) {
+ return;
+ }
+
+ if (is_prop_connected) {
+ island_enabled = BLI_BITMAP_NEW(elementmap->totalIslands, "TransIslandData(UV Editing)");
+ }
+
+ if (is_island_center) {
+ island_center = MEM_callocN(sizeof(*island_center) * elementmap->totalIslands, __func__);
+ }
+ }
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BMLoop *l;
+
+ if (!uvedit_face_visible_test(scene, tc->obedit, ima, efa)) {
+ BM_elem_flag_disable(efa, BM_ELEM_TAG);
+ continue;
+ }
+
+ BM_elem_flag_enable(efa, BM_ELEM_TAG);
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ countsel++;
+
+ if (is_prop_connected || island_center) {
+ UvElement *element = BM_uv_element_get(elementmap, efa, l);
+
+ if (is_prop_connected) {
+ BLI_BITMAP_ENABLE(island_enabled, element->island);
+ }
+
+ if (is_island_center) {
+ if (element->flag == false) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ add_v2_v2(island_center[element->island].co, luv->uv);
+ island_center[element->island].co_num++;
+ element->flag = true;
+ }
+ }
+ }
+ }
+
+ if (is_prop_edit) {
+ count++;
+ }
+ }
+ }
+
+ /* note: in prop mode we need at least 1 selected */
+ if (countsel == 0) {
+ goto finally;
+ }
+
+ if (is_island_center) {
+ int i;
+
+ for (i = 0; i < elementmap->totalIslands; i++) {
+ mul_v2_fl(island_center[i].co, 1.0f / island_center[i].co_num);
+ mul_v2_v2(island_center[i].co, t->aspect);
+ }
+ }
+
+ tc->data_len = (is_prop_edit) ? count : countsel;
+ tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(UV Editing)");
+ /* for each 2d uv coord a 3d vector is allocated, so that they can be
+ * treated just as if they were 3d verts */
+ tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransObData2D(UV Editing)");
+
+ if (sima->flag & SI_CLIP_UV)
+ t->flag |= T_CLIP_UV;
+
+ td = tc->data;
+ td2d = tc->data_2d;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BMLoop *l;
+
+ if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
+ continue;
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ const bool selected = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
+ MLoopUV *luv;
+ const float *center = NULL;
+
+ if (!is_prop_edit && !selected)
+ continue;
+
+ if (is_prop_connected || is_island_center) {
+ UvElement *element = BM_uv_element_get(elementmap, efa, l);
+
+ if (is_prop_connected) {
+ if (!BLI_BITMAP_TEST(island_enabled, element->island)) {
+ count_rejected++;
+ continue;
+ }
+ }
+
+ if (is_island_center) {
+ center = island_center[element->island].co;
+ }
+ }
+
+ BM_elem_flag_enable(l, BM_ELEM_TAG);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ UVsToTransData(t->aspect, td++, td2d++, luv->uv, center, selected);
+ }
+ }
+
+ if (is_prop_connected) {
+ tc->data_len -= count_rejected;
+ }
+
+ if (sima->flag & SI_LIVE_UNWRAP) {
+ ED_uvedit_live_unwrap_begin(t->scene, tc->obedit);
+ }
+
+ finally:
+ if (is_prop_connected || is_island_center) {
+ BM_uv_element_map_free(elementmap);
+
+ if (is_prop_connected) {
+ MEM_freeN(island_enabled);
+ }
+
+ if (island_center) {
+ MEM_freeN(island_center);
+ }
+ }
+ }
}
void flushTransUVs(TransInfo *t)
{
- SpaceImage *sima = t->sa->spacedata.first;
- const bool use_pixel_snap = ((sima->pixel_snap_mode != SI_PIXEL_SNAP_DISABLED) &&
- (t->state != TRANS_CANCEL));
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData2D *td;
- int a;
- float aspect_inv[2], size[2];
-
- aspect_inv[0] = 1.0f / t->aspect[0];
- aspect_inv[1] = 1.0f / t->aspect[1];
-
- if (use_pixel_snap) {
- 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];
- }
-
- /* flush to 2d vector from internally used 3d vector */
- for (a = 0, td = tc->data_2d; a < tc->data_len; a++, td++) {
- td->loc2d[0] = td->loc[0] * aspect_inv[0];
- td->loc2d[1] = td->loc[1] * aspect_inv[1];
-
- if (use_pixel_snap) {
- td->loc2d[0] *= size[0];
- td->loc2d[1] *= size[1];
-
- switch (sima->pixel_snap_mode) {
- case SI_PIXEL_SNAP_CENTER:
- td->loc2d[0] = roundf(td->loc2d[0] - 0.5f) + 0.5f;
- td->loc2d[1] = roundf(td->loc2d[1] - 0.5f) + 0.5f;
- break;
- case SI_PIXEL_SNAP_CORNER:
- td->loc2d[0] = roundf(td->loc2d[0]);
- td->loc2d[1] = roundf(td->loc2d[1]);
- break;
- }
-
- td->loc2d[0] /= size[0];
- td->loc2d[1] /= size[1];
- }
- }
- }
+ SpaceImage *sima = t->sa->spacedata.first;
+ const bool use_pixel_snap = ((sima->pixel_snap_mode != SI_PIXEL_SNAP_DISABLED) &&
+ (t->state != TRANS_CANCEL));
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData2D *td;
+ int a;
+ float aspect_inv[2], size[2];
+
+ aspect_inv[0] = 1.0f / t->aspect[0];
+ aspect_inv[1] = 1.0f / t->aspect[1];
+
+ if (use_pixel_snap) {
+ 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];
+ }
+
+ /* flush to 2d vector from internally used 3d vector */
+ for (a = 0, td = tc->data_2d; a < tc->data_len; a++, td++) {
+ td->loc2d[0] = td->loc[0] * aspect_inv[0];
+ td->loc2d[1] = td->loc[1] * aspect_inv[1];
+
+ if (use_pixel_snap) {
+ td->loc2d[0] *= size[0];
+ td->loc2d[1] *= size[1];
+
+ switch (sima->pixel_snap_mode) {
+ case SI_PIXEL_SNAP_CENTER:
+ td->loc2d[0] = roundf(td->loc2d[0] - 0.5f) + 0.5f;
+ td->loc2d[1] = roundf(td->loc2d[1] - 0.5f) + 0.5f;
+ break;
+ case SI_PIXEL_SNAP_CORNER:
+ td->loc2d[0] = roundf(td->loc2d[0]);
+ td->loc2d[1] = roundf(td->loc2d[1]);
+ break;
+ }
+
+ td->loc2d[0] /= size[0];
+ td->loc2d[1] /= size[1];
+ }
+ }
+ }
}
bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
{
- bool clipx = true, clipy = true;
- float min[2], max[2];
-
- min[0] = min[1] = 0.0f;
- max[0] = t->aspect[0];
- max[1] = t->aspect[1];
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
- TransData *td;
- int a;
-
- for (a = 0, td = tc->data; a < tc->data_len; a++, td++) {
- minmax_v2v2_v2(min, max, td->loc);
- }
-
- if (resize) {
- if (min[0] < 0.0f && t->center_global[0] > 0.0f && t->center_global[0] < t->aspect[0] * 0.5f)
- vec[0] *= t->center_global[0] / (t->center_global[0] - min[0]);
- else if (max[0] > t->aspect[0] && t->center_global[0] < t->aspect[0])
- vec[0] *= (t->center_global[0] - t->aspect[0]) / (t->center_global[0] - max[0]);
- else
- clipx = 0;
-
- if (min[1] < 0.0f && t->center_global[1] > 0.0f && t->center_global[1] < t->aspect[1] * 0.5f)
- vec[1] *= t->center_global[1] / (t->center_global[1] - min[1]);
- else if (max[1] > t->aspect[1] && t->center_global[1] < t->aspect[1])
- vec[1] *= (t->center_global[1] - t->aspect[1]) / (t->center_global[1] - max[1]);
- else
- clipy = 0;
- }
- else {
- if (min[0] < 0.0f)
- vec[0] -= min[0];
- else if (max[0] > t->aspect[0])
- vec[0] -= max[0] - t->aspect[0];
- else
- clipx = 0;
-
- if (min[1] < 0.0f)
- vec[1] -= min[1];
- else if (max[1] > t->aspect[1])
- vec[1] -= max[1] - t->aspect[1];
- else
- clipy = 0;
- }
- }
-
- return (clipx || clipy);
+ bool clipx = true, clipy = true;
+ float min[2], max[2];
+
+ min[0] = min[1] = 0.0f;
+ max[0] = t->aspect[0];
+ max[1] = t->aspect[1];
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+
+ TransData *td;
+ int a;
+
+ for (a = 0, td = tc->data; a < tc->data_len; a++, td++) {
+ minmax_v2v2_v2(min, max, td->loc);
+ }
+
+ if (resize) {
+ if (min[0] < 0.0f && t->center_global[0] > 0.0f && t->center_global[0] < t->aspect[0] * 0.5f)
+ vec[0] *= t->center_global[0] / (t->center_global[0] - min[0]);
+ else if (max[0] > t->aspect[0] && t->center_global[0] < t->aspect[0])
+ vec[0] *= (t->center_global[0] - t->aspect[0]) / (t->center_global[0] - max[0]);
+ else
+ clipx = 0;
+
+ if (min[1] < 0.0f && t->center_global[1] > 0.0f && t->center_global[1] < t->aspect[1] * 0.5f)
+ vec[1] *= t->center_global[1] / (t->center_global[1] - min[1]);
+ else if (max[1] > t->aspect[1] && t->center_global[1] < t->aspect[1])
+ vec[1] *= (t->center_global[1] - t->aspect[1]) / (t->center_global[1] - max[1]);
+ else
+ clipy = 0;
+ }
+ else {
+ if (min[0] < 0.0f)
+ vec[0] -= min[0];
+ else if (max[0] > t->aspect[0])
+ vec[0] -= max[0] - t->aspect[0];
+ else
+ clipx = 0;
+
+ if (min[1] < 0.0f)
+ vec[1] -= min[1];
+ else if (max[1] > t->aspect[1])
+ vec[1] -= max[1] - t->aspect[1];
+ else
+ clipy = 0;
+ }
+ }
+
+ return (clipx || clipy);
}
void clipUVData(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (int a = 0; a < tc->data_len; a++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (int a = 0; a < tc->data_len; a++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
- if ((td->flag & TD_SKIP) || (!td->loc))
- continue;
+ if ((td->flag & TD_SKIP) || (!td->loc))
+ continue;
- td->loc[0] = min_ff(max_ff(0.0f, td->loc[0]), t->aspect[0]);
- td->loc[1] = min_ff(max_ff(0.0f, td->loc[1]), t->aspect[1]);
- }
- }
+ td->loc[0] = min_ff(max_ff(0.0f, td->loc[0]), t->aspect[0]);
+ td->loc[1] = min_ff(max_ff(0.0f, td->loc[1]), t->aspect[1]);
+ }
+ }
}
/* ********************* ANIMATION EDITORS (GENERAL) ************************* */
@@ -3458,258 +3539,264 @@ void clipUVData(TransInfo *t)
/* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
static bool FrameOnMouseSide(char side, float frame, float cframe)
{
- /* both sides, so it doesn't matter */
- if (side == 'B') return true;
+ /* both sides, so it doesn't matter */
+ if (side == 'B')
+ return true;
- /* only on the named side */
- if (side == 'R')
- return (frame >= cframe);
- else
- return (frame <= cframe);
+ /* only on the named side */
+ if (side == 'R')
+ return (frame >= cframe);
+ else
+ return (frame <= cframe);
}
/* ********************* NLA EDITOR ************************* */
static void createTransNlaData(bContext *C, TransInfo *t)
{
- Scene *scene = t->scene;
- SpaceNla *snla = NULL;
- TransData *td = NULL;
- TransDataNla *tdn = NULL;
-
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- int count = 0;
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* determine what type of data we are operating on */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return;
- snla = (SpaceNla *)ac.sl;
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* 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';
- }
- else {
- /* normal transform - both sides of current frame are considered */
- t->frame_side = 'B';
- }
-
- /* loop 1: count how many strips are selected (consider each strip as 2 points) */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
-
- /* make some meta-strips for chains of selected strips */
- BKE_nlastrips_make_metas(&nlt->strips, 1);
-
- /* only consider selected strips */
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- // TODO: we can make strips have handles later on...
- /* transition strips can't get directly transformed */
- if (strip->type != NLASTRIP_TYPE_TRANSITION) {
- if (strip->flag & NLASTRIP_FLAG_SELECT) {
- if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA)) count++;
- if (FrameOnMouseSide(t->frame_side, strip->end, (float)CFRA)) count++;
- }
- }
- }
- }
-
- /* stop if trying to build list if nothing selected */
- if (count == 0) {
- /* clear temp metas that may have been created but aren't needed now
- * because they fell on the wrong side of CFRA
- */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
- }
-
- /* cleanup temp list */
- ANIM_animdata_freelist(&anim_data);
- return;
- }
-
- /* allocate memory for data */
- tc->data_len = count;
-
- tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData(NLA Editor)");
- td = tc->data;
- tc->custom.type.data = tdn = MEM_callocN(tc->data_len * sizeof(TransDataNla), "TransDataNla (NLA Editor)");
- tc->custom.type.use_free = true;
-
- /* loop 2: build transdata array */
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* only if a real NLA-track */
- if (ale->type == ANIMTYPE_NLATRACK) {
- AnimData *adt = ale->adt;
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
-
- /* only consider selected strips */
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- // TODO: we can make strips have handles later on...
- /* transition strips can't get directly transformed */
- if (strip->type != NLASTRIP_TYPE_TRANSITION) {
- if (strip->flag & NLASTRIP_FLAG_SELECT) {
- /* our transform data is constructed as follows:
- * - only the handles on the right side of the current-frame get included
- * - td structs are transform-elements operated on by the transform system
- * and represent a single handle. The storage/pointer used (val or loc) depends on
- * whether we're scaling or transforming. Ultimately though, the handles
- * the td writes to will simply be a dummy in tdn
- * - for each strip being transformed, a single tdn struct is used, so in some
- * cases, there will need to be 1 of these tdn elements in the array skipped...
- */
- float center[3], yval;
-
- /* firstly, init tdn settings */
- tdn->id = ale->id;
- tdn->oldTrack = tdn->nlt = nlt;
- tdn->strip = strip;
- tdn->trackIndex = BLI_findindex(&adt->nla_tracks, nlt);
-
- yval = (float)(tdn->trackIndex * NLACHANNEL_STEP(snla));
-
- tdn->h1[0] = strip->start;
- tdn->h1[1] = yval;
- tdn->h2[0] = strip->end;
- tdn->h2[1] = yval;
-
- center[0] = (float)CFRA;
- center[1] = yval;
- center[2] = 0.0f;
-
- /* set td's based on which handles are applicable */
- if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA)) {
- /* just set tdn to assume that it only has one handle for now */
- tdn->handle = -1;
-
- /* now, link the transform data up to this data */
- if (ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_EXTEND)) {
- td->loc = tdn->h1;
- copy_v3_v3(td->iloc, tdn->h1);
-
- /* store all the other gunk that is required by transform */
- copy_v3_v3(td->center, center);
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
-
- td->ext = NULL; td->val = NULL;
-
- td->flag |= TD_SELECTED;
- td->dist = 0.0f;
-
- unit_m3(td->mtx);
- unit_m3(td->smtx);
- }
- else {
- /* time scaling only needs single value */
- td->val = &tdn->h1[0];
- td->ival = tdn->h1[0];
- }
-
- td->extra = tdn;
- td++;
- }
- if (FrameOnMouseSide(t->frame_side, strip->end, (float)CFRA)) {
- /* if tdn is already holding the start handle,
- * then we're doing both, otherwise, only end */
- tdn->handle = (tdn->handle) ? 2 : 1;
-
- /* now, link the transform data up to this data */
- if (ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_EXTEND)) {
- td->loc = tdn->h2;
- copy_v3_v3(td->iloc, tdn->h2);
-
- /* store all the other gunk that is required by transform */
- copy_v3_v3(td->center, center);
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
-
- td->ext = NULL; td->val = NULL;
-
- td->flag |= TD_SELECTED;
- td->dist = 0.0f;
-
- unit_m3(td->mtx);
- unit_m3(td->smtx);
- }
- else {
- /* time scaling only needs single value */
- td->val = &tdn->h2[0];
- td->ival = tdn->h2[0];
- }
-
- td->extra = tdn;
- td++;
- }
-
- /* if both handles were used, skip the next tdn (i.e. leave it blank) since the counting code is dumb...
- * otherwise, just advance to the next one...
- */
- if (tdn->handle == 2)
- tdn += 2;
- else
- tdn++;
- }
- }
- }
- }
- }
-
- /* cleanup temp list */
- ANIM_animdata_freelist(&anim_data);
+ Scene *scene = t->scene;
+ SpaceNla *snla = NULL;
+ TransData *td = NULL;
+ TransDataNla *tdn = NULL;
+
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ int count = 0;
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* determine what type of data we are operating on */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return;
+ snla = (SpaceNla *)ac.sl;
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* 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';
+ }
+ else {
+ /* normal transform - both sides of current frame are considered */
+ t->frame_side = 'B';
+ }
+
+ /* loop 1: count how many strips are selected (consider each strip as 2 points) */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ /* make some meta-strips for chains of selected strips */
+ BKE_nlastrips_make_metas(&nlt->strips, 1);
+
+ /* only consider selected strips */
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ // TODO: we can make strips have handles later on...
+ /* transition strips can't get directly transformed */
+ if (strip->type != NLASTRIP_TYPE_TRANSITION) {
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA))
+ count++;
+ if (FrameOnMouseSide(t->frame_side, strip->end, (float)CFRA))
+ count++;
+ }
+ }
+ }
+ }
+
+ /* stop if trying to build list if nothing selected */
+ if (count == 0) {
+ /* clear temp metas that may have been created but aren't needed now
+ * because they fell on the wrong side of CFRA
+ */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
+ }
+
+ /* cleanup temp list */
+ ANIM_animdata_freelist(&anim_data);
+ return;
+ }
+
+ /* allocate memory for data */
+ tc->data_len = count;
+
+ tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData(NLA Editor)");
+ td = tc->data;
+ tc->custom.type.data = tdn = MEM_callocN(tc->data_len * sizeof(TransDataNla),
+ "TransDataNla (NLA Editor)");
+ tc->custom.type.use_free = true;
+
+ /* loop 2: build transdata array */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* only if a real NLA-track */
+ if (ale->type == ANIMTYPE_NLATRACK) {
+ AnimData *adt = ale->adt;
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ /* only consider selected strips */
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ // TODO: we can make strips have handles later on...
+ /* transition strips can't get directly transformed */
+ if (strip->type != NLASTRIP_TYPE_TRANSITION) {
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ /* our transform data is constructed as follows:
+ * - only the handles on the right side of the current-frame get included
+ * - td structs are transform-elements operated on by the transform system
+ * and represent a single handle. The storage/pointer used (val or loc) depends on
+ * whether we're scaling or transforming. Ultimately though, the handles
+ * the td writes to will simply be a dummy in tdn
+ * - for each strip being transformed, a single tdn struct is used, so in some
+ * cases, there will need to be 1 of these tdn elements in the array skipped...
+ */
+ float center[3], yval;
+
+ /* firstly, init tdn settings */
+ tdn->id = ale->id;
+ tdn->oldTrack = tdn->nlt = nlt;
+ tdn->strip = strip;
+ tdn->trackIndex = BLI_findindex(&adt->nla_tracks, nlt);
+
+ yval = (float)(tdn->trackIndex * NLACHANNEL_STEP(snla));
+
+ tdn->h1[0] = strip->start;
+ tdn->h1[1] = yval;
+ tdn->h2[0] = strip->end;
+ tdn->h2[1] = yval;
+
+ center[0] = (float)CFRA;
+ center[1] = yval;
+ center[2] = 0.0f;
+
+ /* set td's based on which handles are applicable */
+ if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA)) {
+ /* just set tdn to assume that it only has one handle for now */
+ tdn->handle = -1;
+
+ /* now, link the transform data up to this data */
+ if (ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_EXTEND)) {
+ td->loc = tdn->h1;
+ copy_v3_v3(td->iloc, tdn->h1);
+
+ /* store all the other gunk that is required by transform */
+ copy_v3_v3(td->center, center);
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0f;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+ }
+ else {
+ /* time scaling only needs single value */
+ td->val = &tdn->h1[0];
+ td->ival = tdn->h1[0];
+ }
+
+ td->extra = tdn;
+ td++;
+ }
+ if (FrameOnMouseSide(t->frame_side, strip->end, (float)CFRA)) {
+ /* if tdn is already holding the start handle,
+ * then we're doing both, otherwise, only end */
+ tdn->handle = (tdn->handle) ? 2 : 1;
+
+ /* now, link the transform data up to this data */
+ if (ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_EXTEND)) {
+ td->loc = tdn->h2;
+ copy_v3_v3(td->iloc, tdn->h2);
+
+ /* store all the other gunk that is required by transform */
+ copy_v3_v3(td->center, center);
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0f;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+ }
+ else {
+ /* time scaling only needs single value */
+ td->val = &tdn->h2[0];
+ td->ival = tdn->h2[0];
+ }
+
+ td->extra = tdn;
+ td++;
+ }
+
+ /* if both handles were used, skip the next tdn (i.e. leave it blank) since the counting code is dumb...
+ * otherwise, just advance to the next one...
+ */
+ if (tdn->handle == 2)
+ tdn += 2;
+ else
+ tdn++;
+ }
+ }
+ }
+ }
+ }
+
+ /* cleanup temp list */
+ ANIM_animdata_freelist(&anim_data);
}
/* ********************* 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;
+ 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;
+ 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;
}
static int masklay_shape_cmp_frame(void *thunk, const void *a, const void *b)
{
- const MaskLayerShape *frame_a = a;
- const MaskLayerShape *frame_b = b;
+ const MaskLayerShape *frame_a = a;
+ const MaskLayerShape *frame_b = b;
- if (frame_a->frame < frame_b->frame) return -1;
- if (frame_a->frame > frame_b->frame) return 1;
- *((bool *)thunk) = true;
- /* selected last */
- if ((frame_a->flag & MASK_SHAPE_SELECT) &&
- ((frame_b->flag & MASK_SHAPE_SELECT) == 0))
- {
- return 1;
- }
- return 0;
+ if (frame_a->frame < frame_b->frame)
+ return -1;
+ if (frame_a->frame > frame_b->frame)
+ return 1;
+ *((bool *)thunk) = true;
+ /* selected last */
+ if ((frame_a->flag & MASK_SHAPE_SELECT) && ((frame_b->flag & MASK_SHAPE_SELECT) == 0)) {
+ return 1;
+ }
+ return 0;
}
/* Called by special_aftertrans_update to make sure selected gp-frames replace
@@ -3719,68 +3806,70 @@ static int masklay_shape_cmp_frame(void *thunk, const void *a, const void *b)
*/
static void posttrans_gpd_clean(bGPdata *gpd)
{
- bGPDlayer *gpl;
+ bGPDlayer *gpl;
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- bGPDframe *gpf, *gpfn;
- bool is_double = false;
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ bGPDframe *gpf, *gpfn;
+ bool is_double = false;
- BLI_listbase_sort_r(&gpl->frames, gpf_cmp_frame, &is_double);
+ BLI_listbase_sort_r(&gpl->frames, gpf_cmp_frame, &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);
- }
- }
- }
+ 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);
+ }
+ }
+ }
#ifdef DEBUG
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- BLI_assert(!gpf->next || gpf->framenum < gpf->next->framenum);
- }
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ BLI_assert(!gpf->next || gpf->framenum < gpf->next->framenum);
+ }
#endif
- }
- /* set cache flag to dirty */
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ }
+ /* set cache flag to dirty */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
}
static void posttrans_mask_clean(Mask *mask)
{
- MaskLayer *masklay;
+ MaskLayer *masklay;
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskLayerShape *masklay_shape, *masklay_shape_next;
- bool is_double = false;
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskLayerShape *masklay_shape, *masklay_shape_next;
+ bool is_double = false;
- BLI_listbase_sort_r(&masklay->splines_shapes, masklay_shape_cmp_frame, &is_double);
+ BLI_listbase_sort_r(&masklay->splines_shapes, masklay_shape_cmp_frame, &is_double);
- if (is_double) {
- for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape_next) {
- masklay_shape_next = masklay_shape->next;
- if (masklay_shape_next && masklay_shape->frame == masklay_shape_next->frame) {
- BKE_mask_layer_shape_unlink(masklay, masklay_shape);
- }
- }
- }
+ if (is_double) {
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape_next) {
+ masklay_shape_next = masklay_shape->next;
+ if (masklay_shape_next && masklay_shape->frame == masklay_shape_next->frame) {
+ BKE_mask_layer_shape_unlink(masklay, masklay_shape);
+ }
+ }
+ }
#ifdef DEBUG
- for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
- BLI_assert(!masklay_shape->next || masklay_shape->frame < masklay_shape->next->frame);
- }
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape->next) {
+ BLI_assert(!masklay_shape->next || masklay_shape->frame < masklay_shape->next->frame);
+ }
#endif
- }
+ }
}
/* Time + Average value */
typedef struct tRetainedKeyframe {
- struct tRetainedKeyframe *next, *prev;
- float frame; /* frame to cluster around */
- float val; /* average value */
+ struct tRetainedKeyframe *next, *prev;
+ float frame; /* frame to cluster around */
+ float val; /* average value */
- size_t tot_count; /* number of keyframes that have been averaged */
- size_t del_count; /* number of keyframes of this sort that have been deleted so far */
+ size_t tot_count; /* number of keyframes that have been averaged */
+ size_t del_count; /* number of keyframes of this sort that have been deleted so far */
} tRetainedKeyframe;
/* Called during special_aftertrans_update to make sure selected keyframes replace
@@ -3788,152 +3877,152 @@ typedef struct tRetainedKeyframe {
*/
static void posttrans_fcurve_clean(FCurve *fcu, const bool use_handle)
{
- /* NOTE: We assume that all keys are sorted */
- ListBase retained_keys = {NULL, NULL};
- const bool can_average_points = ((fcu->flag & (FCURVE_INT_VALUES | FCURVE_DISCRETE_VALUES)) == 0);
-
- /* sanity checks */
- if ((fcu->totvert == 0) || (fcu->bezt == NULL))
- return;
-
- /* 1) Identify selected keyframes, and average the values on those
- * in case there are collisions due to multiple keys getting scaled
- * to all end up on the same frame
- */
- for (int i = 0; i < fcu->totvert; i++) {
- BezTriple *bezt = &fcu->bezt[i];
-
- if (BEZT_ISSEL_ANY(bezt)) {
- bool found = false;
-
- /* If there's another selected frame here, merge it */
- for (tRetainedKeyframe *rk = retained_keys.last; rk; rk = rk->prev) {
- if (IS_EQT(rk->frame, bezt->vec[1][0], BEZT_BINARYSEARCH_THRESH)) {
- rk->val += bezt->vec[1][1];
- rk->tot_count++;
-
- found = true;
- break;
- }
- else if (rk->frame < bezt->vec[1][0]) {
- /* Terminate early if have passed the supposed insertion point? */
- break;
- }
- }
-
- /* If nothing found yet, create a new one */
- if (found == false) {
- tRetainedKeyframe *rk = MEM_callocN(sizeof(tRetainedKeyframe), "tRetainedKeyframe");
-
- rk->frame = bezt->vec[1][0];
- rk->val = bezt->vec[1][1];
- rk->tot_count = 1;
-
- BLI_addtail(&retained_keys, rk);
- }
- }
- }
-
- if (BLI_listbase_is_empty(&retained_keys)) {
- /* This may happen if none of the points were selected... */
- if (G.debug & G_DEBUG) {
- printf("%s: nothing to do for FCurve %p (rna_path = '%s')\n", __func__, fcu, fcu->rna_path);
- }
- return;
- }
- else {
- /* Compute the average values for each retained keyframe */
- for (tRetainedKeyframe *rk = retained_keys.first; rk; rk = rk->next) {
- rk->val = rk->val / (float)rk->tot_count;
- }
- }
-
- /* 2) Delete all keyframes duplicating the "retained keys" found above
- * - Most of these will be unselected keyframes
- * - Some will be selected keyframes though. For those, we only keep the last one
- * (or else everything is gone), and replace its value with the averaged value.
- */
- for (int i = fcu->totvert - 1; i >= 0; i--) {
- BezTriple *bezt = &fcu->bezt[i];
-
- /* Is this keyframe a candidate for deletion? */
- /* TODO: Replace loop with an O(1) lookup instead */
- for (tRetainedKeyframe *rk = retained_keys.last; rk; rk = rk->prev) {
- if (IS_EQT(bezt->vec[1][0], rk->frame, BEZT_BINARYSEARCH_THRESH)) {
- /* Selected keys are treated with greater care than unselected ones... */
- if (BEZT_ISSEL_ANY(bezt)) {
- /* - If this is the last selected key left (based on rk->del_count) ==> UPDATE IT
- * (or else we wouldn't have any keyframe left here)
- * - Otherwise, there are still other selected keyframes on this frame
- * to be merged down still ==> DELETE IT
- */
- if (rk->del_count == rk->tot_count - 1) {
- /* Update keyframe... */
- if (can_average_points) {
- /* TODO: update handles too? */
- bezt->vec[1][1] = rk->val;
- }
- }
- else {
- /* Delete Keyframe */
- delete_fcurve_key(fcu, i, 0);
- }
-
- /* Update count of how many we've deleted
- * - It should only matter that we're doing this for all but the last one
- */
- rk->del_count++;
- }
- else {
- /* Always delete - Unselected keys don't matter */
- delete_fcurve_key(fcu, i, 0);
- }
-
- /* Stop the RK search... we've found our match now */
- break;
- }
- }
- }
-
- /* 3) Recalculate handles */
- testhandles_fcurve(fcu, use_handle);
-
- /* cleanup */
- BLI_freelistN(&retained_keys);
+ /* NOTE: We assume that all keys are sorted */
+ ListBase retained_keys = {NULL, NULL};
+ const bool can_average_points = ((fcu->flag & (FCURVE_INT_VALUES | FCURVE_DISCRETE_VALUES)) ==
+ 0);
+
+ /* sanity checks */
+ if ((fcu->totvert == 0) || (fcu->bezt == NULL))
+ return;
+
+ /* 1) Identify selected keyframes, and average the values on those
+ * in case there are collisions due to multiple keys getting scaled
+ * to all end up on the same frame
+ */
+ for (int i = 0; i < fcu->totvert; i++) {
+ BezTriple *bezt = &fcu->bezt[i];
+
+ if (BEZT_ISSEL_ANY(bezt)) {
+ bool found = false;
+
+ /* If there's another selected frame here, merge it */
+ for (tRetainedKeyframe *rk = retained_keys.last; rk; rk = rk->prev) {
+ if (IS_EQT(rk->frame, bezt->vec[1][0], BEZT_BINARYSEARCH_THRESH)) {
+ rk->val += bezt->vec[1][1];
+ rk->tot_count++;
+
+ found = true;
+ break;
+ }
+ else if (rk->frame < bezt->vec[1][0]) {
+ /* Terminate early if have passed the supposed insertion point? */
+ break;
+ }
+ }
+
+ /* If nothing found yet, create a new one */
+ if (found == false) {
+ tRetainedKeyframe *rk = MEM_callocN(sizeof(tRetainedKeyframe), "tRetainedKeyframe");
+
+ rk->frame = bezt->vec[1][0];
+ rk->val = bezt->vec[1][1];
+ rk->tot_count = 1;
+
+ BLI_addtail(&retained_keys, rk);
+ }
+ }
+ }
+
+ if (BLI_listbase_is_empty(&retained_keys)) {
+ /* This may happen if none of the points were selected... */
+ if (G.debug & G_DEBUG) {
+ printf("%s: nothing to do for FCurve %p (rna_path = '%s')\n", __func__, fcu, fcu->rna_path);
+ }
+ return;
+ }
+ else {
+ /* Compute the average values for each retained keyframe */
+ for (tRetainedKeyframe *rk = retained_keys.first; rk; rk = rk->next) {
+ rk->val = rk->val / (float)rk->tot_count;
+ }
+ }
+
+ /* 2) Delete all keyframes duplicating the "retained keys" found above
+ * - Most of these will be unselected keyframes
+ * - Some will be selected keyframes though. For those, we only keep the last one
+ * (or else everything is gone), and replace its value with the averaged value.
+ */
+ for (int i = fcu->totvert - 1; i >= 0; i--) {
+ BezTriple *bezt = &fcu->bezt[i];
+
+ /* Is this keyframe a candidate for deletion? */
+ /* TODO: Replace loop with an O(1) lookup instead */
+ for (tRetainedKeyframe *rk = retained_keys.last; rk; rk = rk->prev) {
+ if (IS_EQT(bezt->vec[1][0], rk->frame, BEZT_BINARYSEARCH_THRESH)) {
+ /* Selected keys are treated with greater care than unselected ones... */
+ if (BEZT_ISSEL_ANY(bezt)) {
+ /* - If this is the last selected key left (based on rk->del_count) ==> UPDATE IT
+ * (or else we wouldn't have any keyframe left here)
+ * - Otherwise, there are still other selected keyframes on this frame
+ * to be merged down still ==> DELETE IT
+ */
+ if (rk->del_count == rk->tot_count - 1) {
+ /* Update keyframe... */
+ if (can_average_points) {
+ /* TODO: update handles too? */
+ bezt->vec[1][1] = rk->val;
+ }
+ }
+ else {
+ /* Delete Keyframe */
+ delete_fcurve_key(fcu, i, 0);
+ }
+
+ /* Update count of how many we've deleted
+ * - It should only matter that we're doing this for all but the last one
+ */
+ rk->del_count++;
+ }
+ else {
+ /* Always delete - Unselected keys don't matter */
+ delete_fcurve_key(fcu, i, 0);
+ }
+
+ /* Stop the RK search... we've found our match now */
+ break;
+ }
+ }
+ }
+
+ /* 3) Recalculate handles */
+ testhandles_fcurve(fcu, use_handle);
+
+ /* cleanup */
+ BLI_freelistN(&retained_keys);
}
-
/* Called by special_aftertrans_update to make sure selected keyframes replace
* any other keyframes which may reside on that frame (that is not selected).
* remake_action_ipos should have already been called
*/
static void posttrans_action_clean(bAnimContext *ac, bAction *act)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
- ANIM_animdata_filter(ac, &anim_data, filter, act, ANIMCONT_ACTION);
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
+ ANIM_animdata_filter(ac, &anim_data, filter, act, ANIMCONT_ACTION);
- /* loop through relevant data, removing keyframes as appropriate
- * - all keyframes are converted in/out of global time
- */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+ /* loop through relevant data, removing keyframes as appropriate
+ * - all keyframes are converted in/out of global time
+ */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
- if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
- posttrans_fcurve_clean(ale->key_data, false); /* only use handles in graph editor */
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
- }
- else
- posttrans_fcurve_clean(ale->key_data, false); /* only use handles in graph editor */
- }
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
+ posttrans_fcurve_clean(ale->key_data, false); /* only use handles in graph editor */
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
+ }
+ else
+ posttrans_fcurve_clean(ale->key_data, false); /* only use handles in graph editor */
+ }
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
}
/* ----------------------------- */
@@ -3941,92 +4030,93 @@ static void posttrans_action_clean(bAnimContext *ac, bAction *act)
/* fully select selected beztriples, but only include if it's on the right side of cfra */
static int count_fcurve_keys(FCurve *fcu, char side, float cfra, bool is_prop_edit)
{
- BezTriple *bezt;
- int i, count = 0, count_all = 0;
+ BezTriple *bezt;
+ int i, count = 0, count_all = 0;
- if (ELEM(NULL, fcu, fcu->bezt))
- return count;
+ if (ELEM(NULL, fcu, fcu->bezt))
+ return count;
- /* only include points that occur on the right side of cfra */
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
- /* no need to adjust the handle selection since they are assumed
- * selected (like graph editor with SIPO_NOHANDLES) */
- if (bezt->f2 & SELECT)
- count++;
+ /* only include points that occur on the right side of cfra */
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
+ /* no need to adjust the handle selection since they are assumed
+ * selected (like graph editor with SIPO_NOHANDLES) */
+ if (bezt->f2 & SELECT)
+ count++;
- count_all++;
- }
- }
+ count_all++;
+ }
+ }
- if (is_prop_edit && count > 0)
- return count_all;
- else return count;
+ if (is_prop_edit && count > 0)
+ return count_all;
+ else
+ return count;
}
/* fully select selected beztriples, but only include if it's on the right side of cfra */
static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra, bool is_prop_edit)
{
- bGPDframe *gpf;
- int count = 0, count_all = 0;
+ bGPDframe *gpf;
+ int count = 0, count_all = 0;
- if (gpl == NULL)
- return count;
+ if (gpl == NULL)
+ return count;
- /* only include points that occur on the right side of cfra */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) {
- if (gpf->flag & GP_FRAME_SELECT)
- count++;
- count_all++;
- }
- }
+ /* only include points that occur on the right side of cfra */
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) {
+ if (gpf->flag & GP_FRAME_SELECT)
+ count++;
+ count_all++;
+ }
+ }
- if (is_prop_edit && count > 0)
- return count_all;
- else
- return count;
+ if (is_prop_edit && count > 0)
+ return count_all;
+ else
+ return count;
}
/* fully select selected beztriples, but only include if it's on the right side of cfra */
static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra, bool is_prop_edit)
{
- MaskLayerShape *masklayer_shape;
- int count = 0, count_all = 0;
+ MaskLayerShape *masklayer_shape;
+ int count = 0, count_all = 0;
- if (masklay == NULL)
- return count;
+ if (masklay == NULL)
+ return count;
- /* only include points that occur on the right side of cfra */
- for (masklayer_shape = masklay->splines_shapes.first; masklayer_shape; masklayer_shape = masklayer_shape->next) {
- if (FrameOnMouseSide(side, (float)masklayer_shape->frame, cfra)) {
- if (masklayer_shape->flag & MASK_SHAPE_SELECT)
- count++;
- count_all++;
- }
- }
+ /* only include points that occur on the right side of cfra */
+ for (masklayer_shape = masklay->splines_shapes.first; masklayer_shape;
+ masklayer_shape = masklayer_shape->next) {
+ if (FrameOnMouseSide(side, (float)masklayer_shape->frame, cfra)) {
+ if (masklayer_shape->flag & MASK_SHAPE_SELECT)
+ count++;
+ count_all++;
+ }
+ }
- if (is_prop_edit && count > 0)
- return count_all;
- else
- return count;
+ if (is_prop_edit && count > 0)
+ return count_all;
+ else
+ return count;
}
-
/* This function assigns the information to transdata */
static void TimeToTransData(TransData *td, float *time, AnimData *adt, float ypos)
{
- /* memory is calloc'ed, so that should zero everything nicely for us */
- td->val = time;
- td->ival = *(time);
+ /* memory is calloc'ed, so that should zero everything nicely for us */
+ td->val = time;
+ td->ival = *(time);
- td->center[0] = td->ival;
- td->center[1] = ypos;
+ td->center[0] = td->ival;
+ td->center[1] = ypos;
- /* store the AnimData where this keyframe exists as a keyframe of the
- * active action as td->extra.
- */
- td->extra = adt;
+ /* store the AnimData where this keyframe exists as a keyframe of the
+ * active action as td->extra.
+ */
+ td->extra = adt;
}
/* This function advances the address to which td points to, so it must return
@@ -4036,61 +4126,68 @@ static void TimeToTransData(TransData *td, float *time, AnimData *adt, float ypo
* The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data
* on the named side are used.
*/
-static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra, bool is_prop_edit, float ypos)
+static TransData *ActionFCurveToTransData(TransData *td,
+ TransData2D **td2dv,
+ FCurve *fcu,
+ AnimData *adt,
+ char side,
+ float cfra,
+ bool is_prop_edit,
+ float ypos)
{
- BezTriple *bezt;
- TransData2D *td2d = *td2dv;
- int i;
+ BezTriple *bezt;
+ TransData2D *td2d = *td2dv;
+ int i;
- if (ELEM(NULL, fcu, fcu->bezt))
- return td;
+ if (ELEM(NULL, fcu, fcu->bezt))
+ return td;
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- /* only add selected keyframes (for now, proportional edit is not enabled) */
- if (is_prop_edit || (bezt->f2 & SELECT)) { /* note this MUST match count_fcurve_keys(),
- * so can't use BEZT_ISSEL_ANY() macro */
- /* only add if on the right 'side' of the current frame */
- if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
- TimeToTransData(td, bezt->vec[1], adt, ypos);
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ /* only add selected keyframes (for now, proportional edit is not enabled) */
+ if (is_prop_edit || (bezt->f2 & SELECT)) { /* note this MUST match count_fcurve_keys(),
+ * so can't use BEZT_ISSEL_ANY() macro */
+ /* only add if on the right 'side' of the current frame */
+ if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
+ TimeToTransData(td, bezt->vec[1], adt, ypos);
- if (bezt->f2 & SELECT)
- td->flag |= TD_SELECTED;
+ if (bezt->f2 & SELECT)
+ td->flag |= TD_SELECTED;
- /*set flags to move handles as necessary*/
- td->flag |= TD_MOVEHANDLE1 | TD_MOVEHANDLE2;
- td2d->h1 = bezt->vec[0];
- td2d->h2 = bezt->vec[2];
+ /*set flags to move handles as necessary*/
+ td->flag |= TD_MOVEHANDLE1 | TD_MOVEHANDLE2;
+ td2d->h1 = bezt->vec[0];
+ td2d->h2 = bezt->vec[2];
- copy_v2_v2(td2d->ih1, td2d->h1);
- copy_v2_v2(td2d->ih2, td2d->h2);
+ copy_v2_v2(td2d->ih1, td2d->h1);
+ copy_v2_v2(td2d->ih2, td2d->h2);
- td++;
- td2d++;
- }
- }
- }
+ td++;
+ td2d++;
+ }
+ }
+ }
- *td2dv = td2d;
+ *td2dv = td2d;
- return td;
+ return td;
}
/* helper struct for gp-frame transforms (only used here) */
typedef struct tGPFtransdata {
- float val; /* where transdata writes transform */
- int *sdata; /* pointer to gpf->framenum */
+ float val; /* where transdata writes transform */
+ int *sdata; /* pointer to gpf->framenum */
} tGPFtransdata;
/* This function helps flush transdata written to tempdata into the gp-frames */
void flushTransIntFrameActionData(TransInfo *t)
{
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- tGPFtransdata *tfd = tc->custom.type.data;
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ tGPFtransdata *tfd = tc->custom.type.data;
- /* flush data! */
- for (int i = 0; i < tc->data_len; i++, tfd++) {
- *(tfd->sdata) = round_fl_to_int(tfd->val);
- }
+ /* flush data! */
+ for (int i = 0; i < tc->data_len; i++, tfd++) {
+ *(tfd->sdata) = round_fl_to_int(tfd->val);
+ }
}
/* This function advances the address to which td points to, so it must return
@@ -4100,916 +4197,1011 @@ void flushTransIntFrameActionData(TransInfo *t)
* The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data
* on the named side are used.
*/
-static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra, bool is_prop_edit, float ypos)
-{
- bGPDframe *gpf;
- int count = 0;
-
- /* check for select frames on right side of current frame */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- if (is_prop_edit || (gpf->flag & GP_FRAME_SELECT)) {
- if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) {
- /* memory is calloc'ed, so that should zero everything nicely for us */
- td->val = &tfd->val;
- td->ival = (float)gpf->framenum;
-
- td->center[0] = td->ival;
- td->center[1] = ypos;
-
- tfd->val = (float)gpf->framenum;
- tfd->sdata = &gpf->framenum;
-
- /* advance td now */
- td++;
- tfd++;
- count++;
- }
- }
- }
-
- return count;
+static int GPLayerToTransData(TransData *td,
+ tGPFtransdata *tfd,
+ bGPDlayer *gpl,
+ char side,
+ float cfra,
+ bool is_prop_edit,
+ float ypos)
+{
+ bGPDframe *gpf;
+ int count = 0;
+
+ /* check for select frames on right side of current frame */
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ if (is_prop_edit || (gpf->flag & GP_FRAME_SELECT)) {
+ if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) {
+ /* memory is calloc'ed, so that should zero everything nicely for us */
+ td->val = &tfd->val;
+ td->ival = (float)gpf->framenum;
+
+ td->center[0] = td->ival;
+ td->center[1] = ypos;
+
+ tfd->val = (float)gpf->framenum;
+ tfd->sdata = &gpf->framenum;
+
+ /* advance td now */
+ td++;
+ tfd++;
+ count++;
+ }
+ }
+ }
+
+ return count;
}
/* refer to comment above #GPLayerToTransData, this is the same but for masks */
-static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra, bool is_prop_edit, float ypos)
-{
- MaskLayerShape *masklay_shape;
- int count = 0;
-
- /* check for select frames on right side of current frame */
- for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
- if (is_prop_edit || (masklay_shape->flag & MASK_SHAPE_SELECT)) {
- if (FrameOnMouseSide(side, (float)masklay_shape->frame, cfra)) {
- /* memory is calloc'ed, so that should zero everything nicely for us */
- td->val = &tfd->val;
- td->ival = (float)masklay_shape->frame;
-
- td->center[0] = td->ival;
- td->center[1] = ypos;
-
- tfd->val = (float)masklay_shape->frame;
- tfd->sdata = &masklay_shape->frame;
-
- /* advance td now */
- td++;
- tfd++;
- count++;
- }
- }
- }
-
- return count;
+static int MaskLayerToTransData(TransData *td,
+ tGPFtransdata *tfd,
+ MaskLayer *masklay,
+ char side,
+ float cfra,
+ bool is_prop_edit,
+ float ypos)
+{
+ MaskLayerShape *masklay_shape;
+ int count = 0;
+
+ /* check for select frames on right side of current frame */
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape->next) {
+ if (is_prop_edit || (masklay_shape->flag & MASK_SHAPE_SELECT)) {
+ if (FrameOnMouseSide(side, (float)masklay_shape->frame, cfra)) {
+ /* memory is calloc'ed, so that should zero everything nicely for us */
+ td->val = &tfd->val;
+ td->ival = (float)masklay_shape->frame;
+
+ td->center[0] = td->ival;
+ td->center[1] = ypos;
+
+ tfd->val = (float)masklay_shape->frame;
+ tfd->sdata = &masklay_shape->frame;
+
+ /* advance td now */
+ td++;
+ tfd++;
+ count++;
+ }
+ }
+ }
+
+ return count;
}
-
static void createTransActionData(bContext *C, TransInfo *t)
{
- Scene *scene = t->scene;
- TransData *td = NULL;
- TransData2D *td2d = NULL;
- tGPFtransdata *tfd = NULL;
-
- rcti *mask = &t->ar->v2d.mask;
- rctf *datamask = &t->ar->v2d.cur;
-
- float xsize = BLI_rctf_size_x(datamask);
- float ysize = BLI_rctf_size_y(datamask);
- float xmask = BLI_rcti_size_x(mask);
- float ymask = BLI_rcti_size_y(mask);
-
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
-
- int count = 0;
- float cfra;
- float ypos = 1.0f / ((ysize / xsize) * (xmask / ymask)) * BLI_rctf_cent_y(&t->ar->v2d.cur);
-
- /* determine what type of data we are operating on */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return;
-
- /* filter data */
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT);
- else
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* 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
- }
- else {
- /* normal transform - both sides of current frame are considered */
- t->frame_side = 'B';
- }
-
- /* loop 1: fully select ipo-keys and count how many BezTriples are selected */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
- int adt_count = 0;
- /* convert current-frame to action-time (slightly less accurate, especially under
- * higher scaling ratios, but is faster than converting all points)
- */
- if (adt)
- cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
- else
- cfra = (float)CFRA;
-
- if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE))
- adt_count = count_fcurve_keys(ale->key_data, t->frame_side, cfra, is_prop_edit);
- else if (ale->type == ANIMTYPE_GPLAYER)
- adt_count = count_gplayer_frames(ale->data, t->frame_side, cfra, is_prop_edit);
- else if (ale->type == ANIMTYPE_MASKLAYER)
- adt_count = count_masklayer_frames(ale->data, t->frame_side, cfra, is_prop_edit);
- else
- BLI_assert(0);
-
- if (adt_count > 0) {
- count += adt_count;
- ale->tag = true;
- }
- }
-
- /* stop if trying to build list if nothing selected */
- if (count == 0) {
- /* cleanup temp list */
- ANIM_animdata_freelist(&anim_data);
- return;
- }
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* allocate memory for data */
- tc->data_len = count;
-
- tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData(Action Editor)");
- tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "transdata2d");
- td = tc->data;
- td2d = tc->data_2d;
-
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
- tc->custom.type.data = tfd = MEM_callocN(sizeof(tGPFtransdata) * count, "tGPFtransdata");
- tc->custom.type.use_free = true;
- }
-
- /* loop 2: build transdata array */
- for (ale = anim_data.first; ale; ale = ale->next) {
-
- if (is_prop_edit && !ale->tag)
- continue;
-
- cfra = (float)CFRA;
-
- {
- AnimData *adt;
- adt = ANIM_nla_mapping_get(&ac, ale);
- if (adt) {
- cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
- }
- }
-
- if (ale->type == ANIMTYPE_GPLAYER) {
- bGPDlayer *gpl = (bGPDlayer *)ale->data;
- int i;
-
- i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra, is_prop_edit, ypos);
- td += i;
- tfd += i;
- }
- else if (ale->type == ANIMTYPE_MASKLAYER) {
- MaskLayer *masklay = (MaskLayer *)ale->data;
- int i;
-
- i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra, is_prop_edit, ypos);
- td += i;
- tfd += i;
- }
- else {
- AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
- FCurve *fcu = (FCurve *)ale->key_data;
-
- td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra, is_prop_edit, ypos);
- }
- }
-
- /* calculate distances for proportional editing */
- if (is_prop_edit) {
- td = tc->data;
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt;
-
- /* F-Curve may not have any keyframes */
- if (!ale->tag)
- continue;
-
- adt = ANIM_nla_mapping_get(&ac, ale);
- if (adt)
- cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
- else
- cfra = (float)CFRA;
-
- if (ale->type == ANIMTYPE_GPLAYER) {
- bGPDlayer *gpl = (bGPDlayer *)ale->data;
- bGPDframe *gpf;
-
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- if (gpf->flag & GP_FRAME_SELECT) {
- td->dist = td->rdist = 0.0f;
- }
- else {
- bGPDframe *gpf_iter;
- int min = INT_MAX;
- for (gpf_iter = gpl->frames.first; gpf_iter; gpf_iter = gpf_iter->next) {
- if (gpf_iter->flag & GP_FRAME_SELECT) {
- if (FrameOnMouseSide(t->frame_side, (float)gpf_iter->framenum, cfra)) {
- int val = abs(gpf->framenum - gpf_iter->framenum);
- if (val < min) {
- min = val;
- }
- }
- }
- }
- td->dist = td->rdist = min;
- }
- td++;
- }
- }
- else if (ale->type == ANIMTYPE_MASKLAYER) {
- MaskLayer *masklay = (MaskLayer *)ale->data;
- MaskLayerShape *masklay_shape;
-
- for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
- if (FrameOnMouseSide(t->frame_side, (float)masklay_shape->frame, cfra)) {
- if (masklay_shape->flag & MASK_SHAPE_SELECT) {
- td->dist = td->rdist = 0.0f;
- }
- else {
- MaskLayerShape *masklay_iter;
- int min = INT_MAX;
- for (masklay_iter = masklay->splines_shapes.first; masklay_iter; masklay_iter = masklay_iter->next) {
- if (masklay_iter->flag & MASK_SHAPE_SELECT) {
- if (FrameOnMouseSide(t->frame_side, (float)masklay_iter->frame, cfra)) {
- int val = abs(masklay_shape->frame - masklay_iter->frame);
- if (val < min) {
- min = val;
- }
- }
- }
- }
- td->dist = td->rdist = min;
- }
- td++;
- }
- }
- }
- else {
- FCurve *fcu = (FCurve *)ale->key_data;
- BezTriple *bezt;
- int i;
-
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
- if (bezt->f2 & SELECT) {
- td->dist = td->rdist = 0.0f;
- }
- else {
- BezTriple *bezt_iter;
- int j;
- float min = FLT_MAX;
- for (j = 0, bezt_iter = fcu->bezt; j < fcu->totvert; j++, bezt_iter++) {
- if (bezt_iter->f2 & SELECT) {
- if (FrameOnMouseSide(t->frame_side, (float)bezt_iter->vec[1][0], cfra)) {
- float val = fabs(bezt->vec[1][0] - bezt_iter->vec[1][0]);
- if (val < min)
- min = val;
- }
- }
- }
- td->dist = td->rdist = min;
- }
- td++;
- }
- }
- }
- }
- }
-
- /* cleanup temp list */
- ANIM_animdata_freelist(&anim_data);
+ Scene *scene = t->scene;
+ TransData *td = NULL;
+ TransData2D *td2d = NULL;
+ tGPFtransdata *tfd = NULL;
+
+ rcti *mask = &t->ar->v2d.mask;
+ rctf *datamask = &t->ar->v2d.cur;
+
+ float xsize = BLI_rctf_size_x(datamask);
+ float ysize = BLI_rctf_size_y(datamask);
+ float xmask = BLI_rcti_size_x(mask);
+ float ymask = BLI_rcti_size_y(mask);
+
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+
+ int count = 0;
+ float cfra;
+ float ypos = 1.0f / ((ysize / xsize) * (xmask / ymask)) * BLI_rctf_cent_y(&t->ar->v2d.cur);
+
+ /* determine what type of data we are operating on */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return;
+
+ /* filter data */
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT);
+ else
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* 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
+ }
+ else {
+ /* normal transform - both sides of current frame are considered */
+ t->frame_side = 'B';
+ }
+
+ /* loop 1: fully select ipo-keys and count how many BezTriples are selected */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
+ int adt_count = 0;
+ /* convert current-frame to action-time (slightly less accurate, especially under
+ * higher scaling ratios, but is faster than converting all points)
+ */
+ if (adt)
+ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+ else
+ cfra = (float)CFRA;
+
+ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE))
+ adt_count = count_fcurve_keys(ale->key_data, t->frame_side, cfra, is_prop_edit);
+ else if (ale->type == ANIMTYPE_GPLAYER)
+ adt_count = count_gplayer_frames(ale->data, t->frame_side, cfra, is_prop_edit);
+ else if (ale->type == ANIMTYPE_MASKLAYER)
+ adt_count = count_masklayer_frames(ale->data, t->frame_side, cfra, is_prop_edit);
+ else
+ BLI_assert(0);
+
+ if (adt_count > 0) {
+ count += adt_count;
+ ale->tag = true;
+ }
+ }
+
+ /* stop if trying to build list if nothing selected */
+ if (count == 0) {
+ /* cleanup temp list */
+ ANIM_animdata_freelist(&anim_data);
+ return;
+ }
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* allocate memory for data */
+ tc->data_len = count;
+
+ tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData(Action Editor)");
+ tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "transdata2d");
+ td = tc->data;
+ td2d = tc->data_2d;
+
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ tc->custom.type.data = tfd = MEM_callocN(sizeof(tGPFtransdata) * count, "tGPFtransdata");
+ tc->custom.type.use_free = true;
+ }
+
+ /* loop 2: build transdata array */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+
+ if (is_prop_edit && !ale->tag)
+ continue;
+
+ cfra = (float)CFRA;
+
+ {
+ AnimData *adt;
+ adt = ANIM_nla_mapping_get(&ac, ale);
+ if (adt) {
+ cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
+ }
+ }
+
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+ int i;
+
+ i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra, is_prop_edit, ypos);
+ td += i;
+ tfd += i;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ MaskLayer *masklay = (MaskLayer *)ale->data;
+ int i;
+
+ i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra, is_prop_edit, ypos);
+ td += i;
+ tfd += i;
+ }
+ else {
+ AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
+ FCurve *fcu = (FCurve *)ale->key_data;
+
+ td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra, is_prop_edit, ypos);
+ }
+ }
+
+ /* calculate distances for proportional editing */
+ if (is_prop_edit) {
+ td = tc->data;
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt;
+
+ /* F-Curve may not have any keyframes */
+ if (!ale->tag)
+ continue;
+
+ adt = ANIM_nla_mapping_get(&ac, ale);
+ if (adt)
+ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+ else
+ cfra = (float)CFRA;
+
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+ bGPDframe *gpf;
+
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ if (gpf->flag & GP_FRAME_SELECT) {
+ td->dist = td->rdist = 0.0f;
+ }
+ else {
+ bGPDframe *gpf_iter;
+ int min = INT_MAX;
+ for (gpf_iter = gpl->frames.first; gpf_iter; gpf_iter = gpf_iter->next) {
+ if (gpf_iter->flag & GP_FRAME_SELECT) {
+ if (FrameOnMouseSide(t->frame_side, (float)gpf_iter->framenum, cfra)) {
+ int val = abs(gpf->framenum - gpf_iter->framenum);
+ if (val < min) {
+ min = val;
+ }
+ }
+ }
+ }
+ td->dist = td->rdist = min;
+ }
+ td++;
+ }
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ MaskLayer *masklay = (MaskLayer *)ale->data;
+ MaskLayerShape *masklay_shape;
+
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape->next) {
+ if (FrameOnMouseSide(t->frame_side, (float)masklay_shape->frame, cfra)) {
+ if (masklay_shape->flag & MASK_SHAPE_SELECT) {
+ td->dist = td->rdist = 0.0f;
+ }
+ else {
+ MaskLayerShape *masklay_iter;
+ int min = INT_MAX;
+ for (masklay_iter = masklay->splines_shapes.first; masklay_iter;
+ masklay_iter = masklay_iter->next) {
+ if (masklay_iter->flag & MASK_SHAPE_SELECT) {
+ if (FrameOnMouseSide(t->frame_side, (float)masklay_iter->frame, cfra)) {
+ int val = abs(masklay_shape->frame - masklay_iter->frame);
+ if (val < min) {
+ min = val;
+ }
+ }
+ }
+ }
+ td->dist = td->rdist = min;
+ }
+ td++;
+ }
+ }
+ }
+ else {
+ FCurve *fcu = (FCurve *)ale->key_data;
+ BezTriple *bezt;
+ int i;
+
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
+ if (bezt->f2 & SELECT) {
+ td->dist = td->rdist = 0.0f;
+ }
+ else {
+ BezTriple *bezt_iter;
+ int j;
+ float min = FLT_MAX;
+ for (j = 0, bezt_iter = fcu->bezt; j < fcu->totvert; j++, bezt_iter++) {
+ if (bezt_iter->f2 & SELECT) {
+ if (FrameOnMouseSide(t->frame_side, (float)bezt_iter->vec[1][0], cfra)) {
+ float val = fabs(bezt->vec[1][0] - bezt_iter->vec[1][0]);
+ if (val < min)
+ min = val;
+ }
+ }
+ }
+ td->dist = td->rdist = min;
+ }
+ td++;
+ }
+ }
+ }
+ }
+ }
+
+ /* cleanup temp list */
+ ANIM_animdata_freelist(&anim_data);
}
/* ********************* GRAPH EDITOR ************************* */
typedef struct TransDataGraph {
- float unit_scale;
- float offset;
+ float unit_scale;
+ float offset;
} TransDataGraph;
/* Helper function for createTransGraphEditData, which is responsible for associating
* source data with transform data
*/
-static void bezt_to_transdata(TransData *td, TransData2D *td2d, TransDataGraph *tdg,
- AnimData *adt, BezTriple *bezt,
- int bi, bool selected, bool ishandle, bool intvals,
- float mtx[3][3], float smtx[3][3], float unit_scale, float offset)
-{
- float *loc = bezt->vec[bi];
- const float *cent = bezt->vec[1];
-
- /* New location from td gets dumped onto the old-location of td2d, which then
- * gets copied to the actual data at td2d->loc2d (bezt->vec[n])
- *
- * Due to NLA mapping, we apply NLA mapping to some of the verts here,
- * and then that mapping will be undone after transform is done.
- */
-
- if (adt) {
- td2d->loc[0] = BKE_nla_tweakedit_remap(adt, loc[0], NLATIME_CONVERT_MAP);
- td2d->loc[1] = (loc[1] + offset) * unit_scale;
- td2d->loc[2] = 0.0f;
- td2d->loc2d = loc;
-
- td->loc = td2d->loc;
- td->center[0] = BKE_nla_tweakedit_remap(adt, cent[0], NLATIME_CONVERT_MAP);
- td->center[1] = (cent[1] + offset) * unit_scale;
- td->center[2] = 0.0f;
-
- copy_v3_v3(td->iloc, td->loc);
- }
- else {
- td2d->loc[0] = loc[0];
- td2d->loc[1] = (loc[1] + offset) * unit_scale;
- td2d->loc[2] = 0.0f;
- td2d->loc2d = loc;
-
- td->loc = td2d->loc;
- copy_v3_v3(td->center, cent);
- td->center[1] = (td->center[1] + offset) * unit_scale;
- copy_v3_v3(td->iloc, td->loc);
- }
-
- if (!ishandle) {
- td2d->h1 = bezt->vec[0];
- td2d->h2 = bezt->vec[2];
- copy_v2_v2(td2d->ih1, td2d->h1);
- copy_v2_v2(td2d->ih2, td2d->h2);
- }
- else {
- td2d->h1 = NULL;
- td2d->h2 = NULL;
- }
-
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
-
- td->ext = NULL; td->val = NULL;
-
- /* store AnimData info in td->extra, for applying mapping when flushing */
- td->extra = adt;
-
- if (selected) {
- td->flag |= TD_SELECTED;
- td->dist = 0.0f;
- }
- else
- td->dist = FLT_MAX;
-
- if (ishandle)
- td->flag |= TD_NOTIMESNAP;
- if (intvals)
- td->flag |= TD_INTVALUES;
-
- /* copy space-conversion matrices for dealing with non-uniform scales */
- copy_m3_m3(td->mtx, mtx);
- copy_m3_m3(td->smtx, smtx);
-
- tdg->unit_scale = unit_scale;
- tdg->offset = offset;
+static void bezt_to_transdata(TransData *td,
+ TransData2D *td2d,
+ TransDataGraph *tdg,
+ AnimData *adt,
+ BezTriple *bezt,
+ int bi,
+ bool selected,
+ bool ishandle,
+ bool intvals,
+ float mtx[3][3],
+ float smtx[3][3],
+ float unit_scale,
+ float offset)
+{
+ float *loc = bezt->vec[bi];
+ const float *cent = bezt->vec[1];
+
+ /* New location from td gets dumped onto the old-location of td2d, which then
+ * gets copied to the actual data at td2d->loc2d (bezt->vec[n])
+ *
+ * Due to NLA mapping, we apply NLA mapping to some of the verts here,
+ * and then that mapping will be undone after transform is done.
+ */
+
+ if (adt) {
+ td2d->loc[0] = BKE_nla_tweakedit_remap(adt, loc[0], NLATIME_CONVERT_MAP);
+ td2d->loc[1] = (loc[1] + offset) * unit_scale;
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = loc;
+
+ td->loc = td2d->loc;
+ td->center[0] = BKE_nla_tweakedit_remap(adt, cent[0], NLATIME_CONVERT_MAP);
+ td->center[1] = (cent[1] + offset) * unit_scale;
+ td->center[2] = 0.0f;
+
+ copy_v3_v3(td->iloc, td->loc);
+ }
+ else {
+ td2d->loc[0] = loc[0];
+ td2d->loc[1] = (loc[1] + offset) * unit_scale;
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = loc;
+
+ td->loc = td2d->loc;
+ copy_v3_v3(td->center, cent);
+ td->center[1] = (td->center[1] + offset) * unit_scale;
+ copy_v3_v3(td->iloc, td->loc);
+ }
+
+ if (!ishandle) {
+ td2d->h1 = bezt->vec[0];
+ td2d->h2 = bezt->vec[2];
+ copy_v2_v2(td2d->ih1, td2d->h1);
+ copy_v2_v2(td2d->ih2, td2d->h2);
+ }
+ else {
+ td2d->h1 = NULL;
+ td2d->h2 = NULL;
+ }
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+
+ /* store AnimData info in td->extra, for applying mapping when flushing */
+ td->extra = adt;
+
+ if (selected) {
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0f;
+ }
+ else
+ td->dist = FLT_MAX;
+
+ if (ishandle)
+ td->flag |= TD_NOTIMESNAP;
+ if (intvals)
+ td->flag |= TD_INTVALUES;
+
+ /* copy space-conversion matrices for dealing with non-uniform scales */
+ copy_m3_m3(td->mtx, mtx);
+ copy_m3_m3(td->smtx, smtx);
+
+ tdg->unit_scale = unit_scale;
+ tdg->offset = offset;
}
static bool graph_edit_is_translation_mode(TransInfo *t)
{
- return ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE, TFM_TIME_DUPLICATE);
+ return ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE, TFM_TIME_DUPLICATE);
}
static bool graph_edit_use_local_center(TransInfo *t)
{
- return ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
- (graph_edit_is_translation_mode(t) == false));
+ return ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (graph_edit_is_translation_mode(t) == false));
}
-
-static void graph_key_shortest_dist(TransInfo *t, FCurve *fcu, TransData *td_start, TransData *td, int cfra, bool use_handle)
+static void graph_key_shortest_dist(
+ TransInfo *t, FCurve *fcu, TransData *td_start, TransData *td, int cfra, bool use_handle)
{
- int j = 0;
- TransData *td_iter = td_start;
+ int j = 0;
+ TransData *td_iter = td_start;
- td->dist = FLT_MAX;
- for (; j < fcu->totvert; j++) {
- BezTriple *bezt = fcu->bezt + j;
- if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
- const bool sel2 = (bezt->f2 & SELECT) != 0;
- const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
- const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
+ td->dist = FLT_MAX;
+ for (; j < fcu->totvert; j++) {
+ BezTriple *bezt = fcu->bezt + j;
+ if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
+ const bool sel2 = (bezt->f2 & SELECT) != 0;
+ const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
+ const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
- if (sel1 || sel2 || sel3) {
- td->dist = td->rdist = min_ff(td->dist, fabs(td_iter->center[0] - td->center[0]));
- }
+ if (sel1 || sel2 || sel3) {
+ td->dist = td->rdist = min_ff(td->dist, fabs(td_iter->center[0] - td->center[0]));
+ }
- td_iter += 3;
- }
- }
+ td_iter += 3;
+ }
+ }
}
static void createTransGraphEditData(bContext *C, TransInfo *t)
{
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
- Scene *scene = t->scene;
- ARegion *ar = t->ar;
- View2D *v2d = &ar->v2d;
-
- TransData *td = NULL;
- TransData2D *td2d = NULL;
- TransDataGraph *tdg = NULL;
-
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- BezTriple *bezt;
- int count = 0, i;
- float mtx[3][3], smtx[3][3];
- const bool is_translation_mode = graph_edit_is_translation_mode(t);
- const bool use_handle = !(sipo->flag & SIPO_NOHANDLES);
- const bool use_local_center = graph_edit_use_local_center(t);
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
- short anim_map_flag = ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS;
-
- /* determine what type of data we are operating on */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return;
-
- anim_map_flag |= ANIM_get_normalization_flags(&ac);
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* 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
- }
- else {
- /* normal transform - both sides of current frame are considered */
- t->frame_side = 'B';
- }
-
- /* loop 1: count how many BezTriples (specifically their verts) are selected (or should be edited) */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
- FCurve *fcu = (FCurve *)ale->key_data;
- float cfra;
- int curvecount = 0;
- bool selected = false;
-
- /* F-Curve may not have any keyframes */
- if (fcu->bezt == NULL)
- continue;
-
- /* convert current-frame to action-time (slightly less accurate, especially under
- * higher scaling ratios, but is faster than converting all points)
- */
- if (adt)
- cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
- else
- cfra = (float)CFRA;
-
- /* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse */
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
- const bool sel2 = (bezt->f2 & SELECT) != 0;
- const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
- const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
-
- if (is_prop_edit) {
- curvecount += 3;
- if (sel2 || sel1 || sel3)
- selected = true;
- }
- else {
- if (!is_translation_mode || !(sel2)) {
- if (sel1) {
- count++;
- }
-
- if (sel3) {
- count++;
- }
- }
-
- /* only include main vert if selected */
- if (sel2 && !use_local_center) {
- count++;
- }
- }
- }
- }
-
- if (is_prop_edit) {
- if (selected) {
- count += curvecount;
- ale->tag = true;
- }
- }
- }
-
- /* stop if trying to build list if nothing selected */
- if (count == 0) {
- /* cleanup temp list */
- ANIM_animdata_freelist(&anim_data);
- return;
- }
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* allocate memory for data */
- tc->data_len = count;
-
- tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData (Graph Editor)");
- /* for each 2d vert a 3d vector is allocated, so that they can be treated just as if they were 3d verts */
- tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransData2D (Graph Editor)");
- tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataGraph), "TransDataGraph");
- tc->custom.type.use_free = true;
-
- td = tc->data;
- td2d = tc->data_2d;
- tdg = tc->custom.type.data;
-
- /* precompute space-conversion matrices for dealing with non-uniform scaling of Graph Editor */
- unit_m3(mtx);
- unit_m3(smtx);
-
- if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) {
- float xscale, yscale;
-
- /* apply scale factors to x and y axes of space-conversion matrices */
- UI_view2d_scale_get(v2d, &xscale, &yscale);
-
- /* mtx is data to global (i.e. view) conversion */
- mul_v3_fl(mtx[0], xscale);
- mul_v3_fl(mtx[1], yscale);
-
- /* smtx is global (i.e. view) to data conversion */
- if (IS_EQF(xscale, 0.0f) == 0) mul_v3_fl(smtx[0], 1.0f / xscale);
- if (IS_EQF(yscale, 0.0f) == 0) mul_v3_fl(smtx[1], 1.0f / yscale);
- }
-
- /* loop 2: build transdata arrays */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
- FCurve *fcu = (FCurve *)ale->key_data;
- bool intvals = (fcu->flag & FCURVE_INT_VALUES) != 0;
- float unit_scale, offset;
- float cfra;
-
- /* F-Curve may not have any keyframes */
- if (fcu->bezt == NULL || (is_prop_edit && ale->tag == 0))
- continue;
-
- /* convert current-frame to action-time (slightly less accurate, especially under
- * higher scaling ratios, but is faster than converting all points)
- */
- if (adt)
- cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
- else
- cfra = (float)CFRA;
-
- unit_scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, ale->key_data, anim_map_flag, &offset);
-
- /* only include BezTriples whose 'keyframe' occurs on the same side
- * of the current frame as mouse (if applicable) */
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
- const bool sel2 = (bezt->f2 & SELECT) != 0;
- const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
- const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
-
- TransDataCurveHandleFlags *hdata = NULL;
- /* short h1=1, h2=1; */ /* UNUSED */
-
- if (is_prop_edit) {
- bool is_sel = (sel2 || sel1 || sel3);
- /* we always select all handles for proportional editing if central handle is selected */
- initTransDataCurveHandles(td, bezt);
- bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, is_sel, true, intvals, mtx, smtx, unit_scale, offset);
- initTransDataCurveHandles(td, bezt);
- bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, is_sel, false, intvals, mtx, smtx, unit_scale, offset);
- initTransDataCurveHandles(td, bezt);
- bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, is_sel, true, intvals, mtx, smtx, unit_scale, offset);
- }
- else {
- /* only include handles if selected, irrespective of the interpolation modes.
- * also, only treat handles specially if the center point isn't selected.
- */
- if (!is_translation_mode || !(sel2)) {
- if (sel1) {
- hdata = initTransDataCurveHandles(td, bezt);
- bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, sel1, true, intvals, mtx, smtx, unit_scale, offset);
- }
- else {
- /* h1 = 0; */ /* UNUSED */
- }
-
- if (sel3) {
- if (hdata == NULL)
- hdata = initTransDataCurveHandles(td, bezt);
- bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, sel3, true, intvals, mtx, smtx, unit_scale, offset);
- }
- else {
- /* h2 = 0; */ /* UNUSED */
- }
- }
-
- /* only include main vert if selected */
- if (sel2 && !use_local_center) {
- /* move handles relative to center */
- if (is_translation_mode) {
- if (sel1) td->flag |= TD_MOVEHANDLE1;
- if (sel3) td->flag |= TD_MOVEHANDLE2;
- }
-
- /* if handles were not selected, store their selection status */
- if (!(sel1) || !(sel3)) {
- if (hdata == NULL)
- hdata = initTransDataCurveHandles(td, bezt);
- }
-
- bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, sel2, false, intvals, mtx, smtx, unit_scale, offset);
-
- }
- /* special hack (must be done after initTransDataCurveHandles(), as that stores handle settings to restore...):
- * - Check if we've got entire BezTriple selected and we're scaling/rotating that point,
- * then check if we're using auto-handles.
- * - If so, change them auto-handles to aligned handles so that handles get affected too
- */
- if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) &&
- ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM) &&
- ELEM(t->mode, TFM_ROTATION, TFM_RESIZE))
- {
- if (hdata && (sel1) && (sel3)) {
- bezt->h1 = HD_ALIGN;
- bezt->h2 = HD_ALIGN;
- }
- }
- }
- }
- }
-
- /* Sets handles based on the selection */
- testhandles_fcurve(fcu, use_handle);
- }
-
- if (is_prop_edit) {
- /* loop 2: build transdata arrays */
- td = tc->data;
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
- FCurve *fcu = (FCurve *)ale->key_data;
- TransData *td_start = td;
- float cfra;
-
- /* F-Curve may not have any keyframes */
- if (fcu->bezt == NULL || (ale->tag == 0))
- continue;
-
- /* convert current-frame to action-time (slightly less accurate, especially under
- * higher scaling ratios, but is faster than converting all points)
- */
- if (adt)
- cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
- else
- cfra = (float)CFRA;
-
- /* only include BezTriples whose 'keyframe' occurs on the
- * same side of the current frame as mouse (if applicable) */
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
- const bool sel2 = (bezt->f2 & SELECT) != 0;
- const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
- const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
-
- if (sel1 || sel2) {
- td->dist = td->rdist = 0.0f;
- }
- else {
- graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
- }
- td++;
-
- if (sel2) {
- td->dist = td->rdist = 0.0f;
- }
- else {
- graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
- }
- td++;
-
- if (sel3 || sel2) {
- td->dist = td->rdist = 0.0f;
- }
- else {
- graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
- }
- td++;
- }
- }
- }
- }
-
- /* cleanup temp list */
- ANIM_animdata_freelist(&anim_data);
+ SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ Scene *scene = t->scene;
+ ARegion *ar = t->ar;
+ View2D *v2d = &ar->v2d;
+
+ TransData *td = NULL;
+ TransData2D *td2d = NULL;
+ TransDataGraph *tdg = NULL;
+
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BezTriple *bezt;
+ int count = 0, i;
+ float mtx[3][3], smtx[3][3];
+ const bool is_translation_mode = graph_edit_is_translation_mode(t);
+ const bool use_handle = !(sipo->flag & SIPO_NOHANDLES);
+ const bool use_local_center = graph_edit_use_local_center(t);
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+ short anim_map_flag = ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS;
+
+ /* determine what type of data we are operating on */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return;
+
+ anim_map_flag |= ANIM_get_normalization_flags(&ac);
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* 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
+ }
+ else {
+ /* normal transform - both sides of current frame are considered */
+ t->frame_side = 'B';
+ }
+
+ /* loop 1: count how many BezTriples (specifically their verts) are selected (or should be edited) */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
+ FCurve *fcu = (FCurve *)ale->key_data;
+ float cfra;
+ int curvecount = 0;
+ bool selected = false;
+
+ /* F-Curve may not have any keyframes */
+ if (fcu->bezt == NULL)
+ continue;
+
+ /* convert current-frame to action-time (slightly less accurate, especially under
+ * higher scaling ratios, but is faster than converting all points)
+ */
+ if (adt)
+ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+ else
+ cfra = (float)CFRA;
+
+ /* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse */
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
+ const bool sel2 = (bezt->f2 & SELECT) != 0;
+ const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
+ const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
+
+ if (is_prop_edit) {
+ curvecount += 3;
+ if (sel2 || sel1 || sel3)
+ selected = true;
+ }
+ else {
+ if (!is_translation_mode || !(sel2)) {
+ if (sel1) {
+ count++;
+ }
+
+ if (sel3) {
+ count++;
+ }
+ }
+
+ /* only include main vert if selected */
+ if (sel2 && !use_local_center) {
+ count++;
+ }
+ }
+ }
+ }
+
+ if (is_prop_edit) {
+ if (selected) {
+ count += curvecount;
+ ale->tag = true;
+ }
+ }
+ }
+
+ /* stop if trying to build list if nothing selected */
+ if (count == 0) {
+ /* cleanup temp list */
+ ANIM_animdata_freelist(&anim_data);
+ return;
+ }
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* allocate memory for data */
+ tc->data_len = count;
+
+ tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData (Graph Editor)");
+ /* for each 2d vert a 3d vector is allocated, so that they can be treated just as if they were 3d verts */
+ tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransData2D (Graph Editor)");
+ tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataGraph), "TransDataGraph");
+ tc->custom.type.use_free = true;
+
+ td = tc->data;
+ td2d = tc->data_2d;
+ tdg = tc->custom.type.data;
+
+ /* precompute space-conversion matrices for dealing with non-uniform scaling of Graph Editor */
+ unit_m3(mtx);
+ unit_m3(smtx);
+
+ if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) {
+ float xscale, yscale;
+
+ /* apply scale factors to x and y axes of space-conversion matrices */
+ UI_view2d_scale_get(v2d, &xscale, &yscale);
+
+ /* mtx is data to global (i.e. view) conversion */
+ mul_v3_fl(mtx[0], xscale);
+ mul_v3_fl(mtx[1], yscale);
+
+ /* smtx is global (i.e. view) to data conversion */
+ if (IS_EQF(xscale, 0.0f) == 0)
+ mul_v3_fl(smtx[0], 1.0f / xscale);
+ if (IS_EQF(yscale, 0.0f) == 0)
+ mul_v3_fl(smtx[1], 1.0f / yscale);
+ }
+
+ /* loop 2: build transdata arrays */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
+ FCurve *fcu = (FCurve *)ale->key_data;
+ bool intvals = (fcu->flag & FCURVE_INT_VALUES) != 0;
+ float unit_scale, offset;
+ float cfra;
+
+ /* F-Curve may not have any keyframes */
+ if (fcu->bezt == NULL || (is_prop_edit && ale->tag == 0))
+ continue;
+
+ /* convert current-frame to action-time (slightly less accurate, especially under
+ * higher scaling ratios, but is faster than converting all points)
+ */
+ if (adt)
+ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+ else
+ cfra = (float)CFRA;
+
+ unit_scale = ANIM_unit_mapping_get_factor(
+ ac.scene, ale->id, ale->key_data, anim_map_flag, &offset);
+
+ /* only include BezTriples whose 'keyframe' occurs on the same side
+ * of the current frame as mouse (if applicable) */
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
+ const bool sel2 = (bezt->f2 & SELECT) != 0;
+ const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
+ const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
+
+ TransDataCurveHandleFlags *hdata = NULL;
+ /* short h1=1, h2=1; */ /* UNUSED */
+
+ if (is_prop_edit) {
+ bool is_sel = (sel2 || sel1 || sel3);
+ /* we always select all handles for proportional editing if central handle is selected */
+ initTransDataCurveHandles(td, bezt);
+ bezt_to_transdata(td++,
+ td2d++,
+ tdg++,
+ adt,
+ bezt,
+ 0,
+ is_sel,
+ true,
+ intvals,
+ mtx,
+ smtx,
+ unit_scale,
+ offset);
+ initTransDataCurveHandles(td, bezt);
+ bezt_to_transdata(td++,
+ td2d++,
+ tdg++,
+ adt,
+ bezt,
+ 1,
+ is_sel,
+ false,
+ intvals,
+ mtx,
+ smtx,
+ unit_scale,
+ offset);
+ initTransDataCurveHandles(td, bezt);
+ bezt_to_transdata(td++,
+ td2d++,
+ tdg++,
+ adt,
+ bezt,
+ 2,
+ is_sel,
+ true,
+ intvals,
+ mtx,
+ smtx,
+ unit_scale,
+ offset);
+ }
+ else {
+ /* only include handles if selected, irrespective of the interpolation modes.
+ * also, only treat handles specially if the center point isn't selected.
+ */
+ if (!is_translation_mode || !(sel2)) {
+ if (sel1) {
+ hdata = initTransDataCurveHandles(td, bezt);
+ bezt_to_transdata(td++,
+ td2d++,
+ tdg++,
+ adt,
+ bezt,
+ 0,
+ sel1,
+ true,
+ intvals,
+ mtx,
+ smtx,
+ unit_scale,
+ offset);
+ }
+ else {
+ /* h1 = 0; */ /* UNUSED */
+ }
+
+ if (sel3) {
+ if (hdata == NULL)
+ hdata = initTransDataCurveHandles(td, bezt);
+ bezt_to_transdata(td++,
+ td2d++,
+ tdg++,
+ adt,
+ bezt,
+ 2,
+ sel3,
+ true,
+ intvals,
+ mtx,
+ smtx,
+ unit_scale,
+ offset);
+ }
+ else {
+ /* h2 = 0; */ /* UNUSED */
+ }
+ }
+
+ /* only include main vert if selected */
+ if (sel2 && !use_local_center) {
+ /* move handles relative to center */
+ if (is_translation_mode) {
+ if (sel1)
+ td->flag |= TD_MOVEHANDLE1;
+ if (sel3)
+ td->flag |= TD_MOVEHANDLE2;
+ }
+
+ /* if handles were not selected, store their selection status */
+ if (!(sel1) || !(sel3)) {
+ if (hdata == NULL)
+ hdata = initTransDataCurveHandles(td, bezt);
+ }
+
+ bezt_to_transdata(td++,
+ td2d++,
+ tdg++,
+ adt,
+ bezt,
+ 1,
+ sel2,
+ false,
+ intvals,
+ mtx,
+ smtx,
+ unit_scale,
+ offset);
+ }
+ /* special hack (must be done after initTransDataCurveHandles(), as that stores handle settings to restore...):
+ * - Check if we've got entire BezTriple selected and we're scaling/rotating that point,
+ * then check if we're using auto-handles.
+ * - If so, change them auto-handles to aligned handles so that handles get affected too
+ */
+ if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) && ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM) &&
+ ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) {
+ if (hdata && (sel1) && (sel3)) {
+ bezt->h1 = HD_ALIGN;
+ bezt->h2 = HD_ALIGN;
+ }
+ }
+ }
+ }
+ }
+
+ /* Sets handles based on the selection */
+ testhandles_fcurve(fcu, use_handle);
+ }
+
+ if (is_prop_edit) {
+ /* loop 2: build transdata arrays */
+ td = tc->data;
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
+ FCurve *fcu = (FCurve *)ale->key_data;
+ TransData *td_start = td;
+ float cfra;
+
+ /* F-Curve may not have any keyframes */
+ if (fcu->bezt == NULL || (ale->tag == 0))
+ continue;
+
+ /* convert current-frame to action-time (slightly less accurate, especially under
+ * higher scaling ratios, but is faster than converting all points)
+ */
+ if (adt)
+ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+ else
+ cfra = (float)CFRA;
+
+ /* only include BezTriples whose 'keyframe' occurs on the
+ * same side of the current frame as mouse (if applicable) */
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
+ const bool sel2 = (bezt->f2 & SELECT) != 0;
+ const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
+ const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
+
+ if (sel1 || sel2) {
+ td->dist = td->rdist = 0.0f;
+ }
+ else {
+ graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
+ }
+ td++;
+
+ if (sel2) {
+ td->dist = td->rdist = 0.0f;
+ }
+ else {
+ graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
+ }
+ td++;
+
+ if (sel3 || sel2) {
+ td->dist = td->rdist = 0.0f;
+ }
+ else {
+ graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
+ }
+ td++;
+ }
+ }
+ }
+ }
+
+ /* cleanup temp list */
+ ANIM_animdata_freelist(&anim_data);
}
-
/* ------------------------ */
/* 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 */
+ 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 */
} BeztMap;
-
/* This function converts an FCurve's BezTriple array to a BeztMap array
* NOTE: this allocates memory that will need to get freed later
*/
static BeztMap *bezt_to_beztmaps(BezTriple *bezts, int totvert, const short UNUSED(use_handle))
{
- BezTriple *bezt = bezts;
- BezTriple *prevbezt = NULL;
- BeztMap *bezm, *bezms;
- int i;
+ BezTriple *bezt = bezts;
+ BezTriple *prevbezt = NULL;
+ BeztMap *bezm, *bezms;
+ int i;
- /* allocate memory for this array */
- if (totvert == 0 || bezts == NULL)
- return NULL;
- bezm = bezms = MEM_callocN(sizeof(BeztMap) * totvert, "BeztMaps");
+ /* allocate memory for this array */
+ if (totvert == 0 || bezts == NULL)
+ return NULL;
+ bezm = bezms = MEM_callocN(sizeof(BeztMap) * totvert, "BeztMaps");
- /* assign beztriples to beztmaps */
- for (i = 0; i < totvert; i++, bezm++, prevbezt = bezt, bezt++) {
- bezm->bezt = bezt;
+ /* assign beztriples to beztmaps */
+ for (i = 0; i < totvert; i++, bezm++, prevbezt = bezt, bezt++) {
+ bezm->bezt = bezt;
- bezm->oldIndex = i;
- bezm->newIndex = i;
+ bezm->oldIndex = i;
+ bezm->newIndex = i;
- bezm->pipo = (prevbezt) ? prevbezt->ipo : bezt->ipo;
- bezm->cipo = bezt->ipo;
- }
+ bezm->pipo = (prevbezt) ? prevbezt->ipo : bezt->ipo;
+ bezm->cipo = bezt->ipo;
+ }
- return bezms;
+ return bezms;
}
/* This function copies the code of sort_time_ipocurve, but acts on BeztMap structs instead */
static void sort_time_beztmaps(BeztMap *bezms, int totvert, const short UNUSED(use_handle))
{
- BeztMap *bezm;
- int i, ok = 1;
-
- /* keep repeating the process until nothing is out of place anymore */
- while (ok) {
- ok = 0;
-
- bezm = bezms;
- i = totvert;
- while (i--) {
- /* is current bezm out of order (i.e. occurs later than next)? */
- if (i > 0) {
- if (bezm->bezt->vec[1][0] > (bezm + 1)->bezt->vec[1][0]) {
- bezm->newIndex++;
- (bezm + 1)->newIndex--;
-
- SWAP(BeztMap, *bezm, *(bezm + 1));
-
- ok = 1;
- }
- }
-
- /* do we need to check if the handles need to be swapped?
- * optimization: this only needs to be performed in the first loop
- */
- if (bezm->swapHs == 0) {
- if ((bezm->bezt->vec[0][0] > bezm->bezt->vec[1][0]) &&
- (bezm->bezt->vec[2][0] < bezm->bezt->vec[1][0]) )
- {
- /* handles need to be swapped */
- bezm->swapHs = 1;
- }
- else {
- /* handles need to be cleared */
- bezm->swapHs = -1;
- }
- }
-
- bezm++;
- }
- }
+ BeztMap *bezm;
+ int i, ok = 1;
+
+ /* keep repeating the process until nothing is out of place anymore */
+ while (ok) {
+ ok = 0;
+
+ bezm = bezms;
+ i = totvert;
+ while (i--) {
+ /* is current bezm out of order (i.e. occurs later than next)? */
+ if (i > 0) {
+ if (bezm->bezt->vec[1][0] > (bezm + 1)->bezt->vec[1][0]) {
+ bezm->newIndex++;
+ (bezm + 1)->newIndex--;
+
+ SWAP(BeztMap, *bezm, *(bezm + 1));
+
+ ok = 1;
+ }
+ }
+
+ /* do we need to check if the handles need to be swapped?
+ * optimization: this only needs to be performed in the first loop
+ */
+ if (bezm->swapHs == 0) {
+ if ((bezm->bezt->vec[0][0] > bezm->bezt->vec[1][0]) &&
+ (bezm->bezt->vec[2][0] < bezm->bezt->vec[1][0])) {
+ /* handles need to be swapped */
+ bezm->swapHs = 1;
+ }
+ else {
+ /* handles need to be cleared */
+ bezm->swapHs = -1;
+ }
+ }
+
+ bezm++;
+ }
+ }
}
/* This function firstly adjusts the pointers that the transdata has to each BezTriple */
-static void beztmap_to_data(TransInfo *t, FCurve *fcu, BeztMap *bezms, int totvert, const short UNUSED(use_handle))
-{
- BezTriple *bezts = fcu->bezt;
- BeztMap *bezm;
- TransData2D *td2d;
- TransData *td;
- int i, j;
- char *adjusted;
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* dynamically allocate an array of chars to mark whether an TransData's
- * pointers have been fixed already, so that we don't override ones that are
- * already done
- */
- adjusted = MEM_callocN(tc->data_len, "beztmap_adjusted_map");
-
- /* for each beztmap item, find if it is used anywhere */
- bezm = bezms;
- for (i = 0; i < totvert; i++, bezm++) {
- /* loop through transdata, testing if we have a hit
- * for the handles (vec[0]/vec[2]), we must also check if they need to be swapped...
- */
- td2d = tc->data_2d;
- td = tc->data;
- for (j = 0; j < tc->data_len; j++, td2d++, td++) {
- /* skip item if already marked */
- if (adjusted[j] != 0) continue;
-
- /* update all transdata pointers, no need to check for selections etc,
- * since only points that are really needed were created as transdata
- */
- if (td2d->loc2d == bezm->bezt->vec[0]) {
- if (bezm->swapHs == 1)
- td2d->loc2d = (bezts + bezm->newIndex)->vec[2];
- else
- td2d->loc2d = (bezts + bezm->newIndex)->vec[0];
- adjusted[j] = 1;
- }
- else if (td2d->loc2d == bezm->bezt->vec[2]) {
- if (bezm->swapHs == 1)
- td2d->loc2d = (bezts + bezm->newIndex)->vec[0];
- else
- td2d->loc2d = (bezts + bezm->newIndex)->vec[2];
- adjusted[j] = 1;
- }
- else if (td2d->loc2d == bezm->bezt->vec[1]) {
- td2d->loc2d = (bezts + bezm->newIndex)->vec[1];
-
- /* if only control point is selected, the handle pointers need to be updated as well */
- if (td2d->h1)
- td2d->h1 = (bezts + bezm->newIndex)->vec[0];
- if (td2d->h2)
- td2d->h2 = (bezts + bezm->newIndex)->vec[2];
-
- adjusted[j] = 1;
- }
-
- /* the handle type pointer has to be updated too */
- if (adjusted[j] && td->flag & TD_BEZTRIPLE && td->hdata) {
- if (bezm->swapHs == 1) {
- td->hdata->h1 = &(bezts + bezm->newIndex)->h2;
- td->hdata->h2 = &(bezts + bezm->newIndex)->h1;
- }
- else {
- td->hdata->h1 = &(bezts + bezm->newIndex)->h1;
- td->hdata->h2 = &(bezts + bezm->newIndex)->h2;
- }
- }
- }
-
- }
-
- /* free temp memory used for 'adjusted' array */
- MEM_freeN(adjusted);
+static void beztmap_to_data(
+ TransInfo *t, FCurve *fcu, BeztMap *bezms, int totvert, const short UNUSED(use_handle))
+{
+ BezTriple *bezts = fcu->bezt;
+ BeztMap *bezm;
+ TransData2D *td2d;
+ TransData *td;
+ int i, j;
+ char *adjusted;
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* dynamically allocate an array of chars to mark whether an TransData's
+ * pointers have been fixed already, so that we don't override ones that are
+ * already done
+ */
+ adjusted = MEM_callocN(tc->data_len, "beztmap_adjusted_map");
+
+ /* for each beztmap item, find if it is used anywhere */
+ bezm = bezms;
+ for (i = 0; i < totvert; i++, bezm++) {
+ /* loop through transdata, testing if we have a hit
+ * for the handles (vec[0]/vec[2]), we must also check if they need to be swapped...
+ */
+ td2d = tc->data_2d;
+ td = tc->data;
+ for (j = 0; j < tc->data_len; j++, td2d++, td++) {
+ /* skip item if already marked */
+ if (adjusted[j] != 0)
+ continue;
+
+ /* update all transdata pointers, no need to check for selections etc,
+ * since only points that are really needed were created as transdata
+ */
+ if (td2d->loc2d == bezm->bezt->vec[0]) {
+ if (bezm->swapHs == 1)
+ td2d->loc2d = (bezts + bezm->newIndex)->vec[2];
+ else
+ td2d->loc2d = (bezts + bezm->newIndex)->vec[0];
+ adjusted[j] = 1;
+ }
+ else if (td2d->loc2d == bezm->bezt->vec[2]) {
+ if (bezm->swapHs == 1)
+ td2d->loc2d = (bezts + bezm->newIndex)->vec[0];
+ else
+ td2d->loc2d = (bezts + bezm->newIndex)->vec[2];
+ adjusted[j] = 1;
+ }
+ else if (td2d->loc2d == bezm->bezt->vec[1]) {
+ td2d->loc2d = (bezts + bezm->newIndex)->vec[1];
+
+ /* if only control point is selected, the handle pointers need to be updated as well */
+ if (td2d->h1)
+ td2d->h1 = (bezts + bezm->newIndex)->vec[0];
+ if (td2d->h2)
+ td2d->h2 = (bezts + bezm->newIndex)->vec[2];
+
+ adjusted[j] = 1;
+ }
+
+ /* the handle type pointer has to be updated too */
+ if (adjusted[j] && td->flag & TD_BEZTRIPLE && td->hdata) {
+ if (bezm->swapHs == 1) {
+ td->hdata->h1 = &(bezts + bezm->newIndex)->h2;
+ td->hdata->h2 = &(bezts + bezm->newIndex)->h1;
+ }
+ else {
+ td->hdata->h1 = &(bezts + bezm->newIndex)->h1;
+ td->hdata->h2 = &(bezts + bezm->newIndex)->h2;
+ }
+ }
+ }
+ }
+
+ /* free temp memory used for 'adjusted' array */
+ MEM_freeN(adjusted);
}
/* This function is called by recalcData during the Transform loop to recalculate
@@ -5021,33 +5213,33 @@ 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;
- bAnimListElem *ale;
- const bool use_handle = (sipo->flag & SIPO_NOHANDLES) == 0;
+ SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ bAnimListElem *ale;
+ const bool use_handle = (sipo->flag & SIPO_NOHANDLES) == 0;
- /* sort and reassign verts */
- for (ale = anim_data->first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
+ /* sort and reassign verts */
+ for (ale = anim_data->first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
- if (fcu->bezt) {
- BeztMap *bezm;
+ if (fcu->bezt) {
+ BeztMap *bezm;
- /* adjust transform-data pointers */
- /* note, none of these functions use 'use_handle', it could be removed */
- bezm = bezt_to_beztmaps(fcu->bezt, fcu->totvert, use_handle);
- sort_time_beztmaps(bezm, fcu->totvert, use_handle);
- beztmap_to_data(t, fcu, bezm, fcu->totvert, use_handle);
+ /* adjust transform-data pointers */
+ /* note, none of these functions use 'use_handle', it could be removed */
+ bezm = bezt_to_beztmaps(fcu->bezt, fcu->totvert, use_handle);
+ sort_time_beztmaps(bezm, fcu->totvert, use_handle);
+ beztmap_to_data(t, fcu, bezm, fcu->totvert, use_handle);
- /* free mapping stuff */
- MEM_freeN(bezm);
+ /* free mapping stuff */
+ MEM_freeN(bezm);
- /* re-sort actual beztriples (perhaps this could be done using the beztmaps to save time?) */
- sort_time_fcurve(fcu);
+ /* re-sort actual beztriples (perhaps this could be done using the beztmaps to save time?) */
+ sort_time_fcurve(fcu);
- /* make sure handles are all set correctly */
- testhandles_fcurve(fcu, use_handle);
- }
- }
+ /* make sure handles are all set correctly */
+ testhandles_fcurve(fcu, use_handle);
+ }
+ }
}
/* this function is called on recalcData to apply the transforms applied
@@ -5055,94 +5247,92 @@ void remake_graph_transdata(TransInfo *t, ListBase *anim_data)
*/
void flushTransGraphData(TransInfo *t)
{
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
- TransData *td;
- TransData2D *td2d;
- TransDataGraph *tdg;
- Scene *scene = t->scene;
- double secf = FPS;
- int a;
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* flush to 2d vector from internally used 3d vector */
- for (a = 0, td = tc->data, td2d = tc->data_2d, tdg = tc->custom.type.data;
- a < tc->data_len;
- a++, td++, td2d++, tdg++)
- {
- /* pointers to relevant AnimData blocks are stored in the td->extra pointers */
- AnimData *adt = (AnimData *)td->extra;
-
- float inv_unit_scale = 1.0f / tdg->unit_scale;
-
- /* handle snapping for time values
- * - we should still be in NLA-mapping timespace
- * - only apply to keyframes (but never to handles)
- * - don't do this when canceling, or else these changes won't go away
- */
- if ((t->state != TRANS_CANCEL) && (td->flag & TD_NOTIMESNAP) == 0) {
- switch (sipo->autosnap) {
- case SACTSNAP_FRAME: /* snap to nearest frame */
- td2d->loc[0] = floor((double)td2d->loc[0] + 0.5);
- break;
-
- case SACTSNAP_SECOND: /* snap to nearest second */
- td2d->loc[0] = floor(((double)td2d->loc[0] / secf) + 0.5) * secf;
- break;
-
- case SACTSNAP_MARKER: /* snap to nearest marker */
- td2d->loc[0] = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, td2d->loc[0]);
- break;
- }
- }
-
- /* we need to unapply the nla-mapping from the time in some situations */
- if (adt)
- td2d->loc2d[0] = BKE_nla_tweakedit_remap(adt, td2d->loc[0], NLATIME_CONVERT_UNMAP);
- else
- td2d->loc2d[0] = td2d->loc[0];
-
- /* Time-stepping auto-snapping modes don't get applied for Graph Editor transforms,
- * as these use the generic transform modes which don't account for this sort of thing.
- * These ones aren't affected by NLA mapping, so we do this after the conversion...
- *
- * NOTE: We also have to apply to td->loc, as that's what the handle-adjustment step below looks
- * to, otherwise we get "swimming handles"
- * NOTE: We don't do this when canceling transforms, or else these changes don't go away
- */
- if ((t->state != TRANS_CANCEL) && (td->flag & TD_NOTIMESNAP) == 0 &&
- ELEM(sipo->autosnap, SACTSNAP_STEP, SACTSNAP_TSTEP))
- {
- switch (sipo->autosnap) {
- case SACTSNAP_STEP: /* frame step */
- td2d->loc2d[0] = floor((double)td2d->loc[0] + 0.5);
- td->loc[0] = floor((double)td->loc[0] + 0.5);
- break;
-
- case SACTSNAP_TSTEP: /* second step */
- /* XXX: the handle behavior in this case is still not quite right... */
- td2d->loc[0] = floor(((double)td2d->loc[0] / secf) + 0.5) * secf;
- td->loc[0] = floor(((double)td->loc[0] / secf) + 0.5) * secf;
- break;
- }
- }
-
- /* if int-values only, truncate to integers */
- if (td->flag & TD_INTVALUES)
- td2d->loc2d[1] = floorf(td2d->loc[1] * inv_unit_scale - tdg->offset + 0.5f);
- else
- td2d->loc2d[1] = td2d->loc[1] * inv_unit_scale - tdg->offset;
-
- if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) {
- td2d->h1[0] = td2d->ih1[0] + td->loc[0] - td->iloc[0];
- td2d->h1[1] = td2d->ih1[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale;
- }
-
- if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) {
- td2d->h2[0] = td2d->ih2[0] + td->loc[0] - td->iloc[0];
- td2d->h2[1] = td2d->ih2[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale;
- }
- }
+ SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ TransData *td;
+ TransData2D *td2d;
+ TransDataGraph *tdg;
+ Scene *scene = t->scene;
+ double secf = FPS;
+ int a;
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* flush to 2d vector from internally used 3d vector */
+ for (a = 0, td = tc->data, td2d = tc->data_2d, tdg = tc->custom.type.data; a < tc->data_len;
+ a++, td++, td2d++, tdg++) {
+ /* pointers to relevant AnimData blocks are stored in the td->extra pointers */
+ AnimData *adt = (AnimData *)td->extra;
+
+ float inv_unit_scale = 1.0f / tdg->unit_scale;
+
+ /* handle snapping for time values
+ * - we should still be in NLA-mapping timespace
+ * - only apply to keyframes (but never to handles)
+ * - don't do this when canceling, or else these changes won't go away
+ */
+ if ((t->state != TRANS_CANCEL) && (td->flag & TD_NOTIMESNAP) == 0) {
+ switch (sipo->autosnap) {
+ case SACTSNAP_FRAME: /* snap to nearest frame */
+ td2d->loc[0] = floor((double)td2d->loc[0] + 0.5);
+ break;
+
+ case SACTSNAP_SECOND: /* snap to nearest second */
+ td2d->loc[0] = floor(((double)td2d->loc[0] / secf) + 0.5) * secf;
+ break;
+
+ case SACTSNAP_MARKER: /* snap to nearest marker */
+ td2d->loc[0] = (float)ED_markers_find_nearest_marker_time(&t->scene->markers,
+ td2d->loc[0]);
+ break;
+ }
+ }
+
+ /* we need to unapply the nla-mapping from the time in some situations */
+ if (adt)
+ td2d->loc2d[0] = BKE_nla_tweakedit_remap(adt, td2d->loc[0], NLATIME_CONVERT_UNMAP);
+ else
+ td2d->loc2d[0] = td2d->loc[0];
+
+ /* Time-stepping auto-snapping modes don't get applied for Graph Editor transforms,
+ * as these use the generic transform modes which don't account for this sort of thing.
+ * These ones aren't affected by NLA mapping, so we do this after the conversion...
+ *
+ * NOTE: We also have to apply to td->loc, as that's what the handle-adjustment step below looks
+ * to, otherwise we get "swimming handles"
+ * NOTE: We don't do this when canceling transforms, or else these changes don't go away
+ */
+ if ((t->state != TRANS_CANCEL) && (td->flag & TD_NOTIMESNAP) == 0 &&
+ ELEM(sipo->autosnap, SACTSNAP_STEP, SACTSNAP_TSTEP)) {
+ switch (sipo->autosnap) {
+ case SACTSNAP_STEP: /* frame step */
+ td2d->loc2d[0] = floor((double)td2d->loc[0] + 0.5);
+ td->loc[0] = floor((double)td->loc[0] + 0.5);
+ break;
+
+ case SACTSNAP_TSTEP: /* second step */
+ /* XXX: the handle behavior in this case is still not quite right... */
+ td2d->loc[0] = floor(((double)td2d->loc[0] / secf) + 0.5) * secf;
+ td->loc[0] = floor(((double)td->loc[0] / secf) + 0.5) * secf;
+ break;
+ }
+ }
+
+ /* if int-values only, truncate to integers */
+ if (td->flag & TD_INTVALUES)
+ td2d->loc2d[1] = floorf(td2d->loc[1] * inv_unit_scale - tdg->offset + 0.5f);
+ else
+ td2d->loc2d[1] = td2d->loc[1] * inv_unit_scale - tdg->offset;
+
+ if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) {
+ td2d->h1[0] = td2d->ih1[0] + td->loc[0] - td->iloc[0];
+ td2d->h1[1] = td2d->ih1[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale;
+ }
+
+ if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) {
+ td2d->h2[0] = td2d->ih2[0] + td->loc[0] - td->iloc[0];
+ td2d->h2[1] = td2d->ih2[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale;
+ }
+ }
}
/* ******************* Sequencer Transform data ******************* */
@@ -5157,540 +5347,543 @@ void flushTransGraphData(TransInfo *t)
*/
static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count, int *flag)
{
- /* for extend we need to do some tricks */
- if (t->mode == TFM_TIME_EXTEND) {
-
- /* *** Extend Transform *** */
-
- Scene *scene = t->scene;
- int cfra = CFRA;
- int left = BKE_sequence_tx_get_final_left(seq, true);
- 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;
- }
- 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;
- else if (t->frame_side == 'L' && left >= cfra) *recursive = false;
- else *recursive = true;
-
- *count = 1;
- *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);
-
- if (t->frame_side == 'R') {
- if (right <= cfra) { *count = *flag = 0; } /* ignore */
- else if (left > cfra) { } /* keep the selection */
- else *flag |= SEQ_RIGHTSEL;
- }
- else {
- if (left >= cfra) { *count = *flag = 0; } /* ignore */
- else if (right < cfra) { } /* keep the selection */
- else *flag |= SEQ_LEFTSEL;
- }
- }
- }
- else {
-
- t->frame_side = 'B';
-
- /* *** Normal Transform *** */
-
- if (seq->depth == 0) {
-
- /* Count */
-
- /* Non nested strips (resect selection and handles) */
- if ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK)) {
- *recursive = false;
- *count = 0;
- *flag = 0;
- }
- else {
- if ((seq->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) == (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
- *flag = seq->flag;
- *count = 2; /* we need 2 transdata's */
- }
- else {
- *flag = seq->flag;
- *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;
- }
- else {
- *recursive = false;
- }
- }
- }
- else {
- /* Nested, different rules apply */
+ /* for extend we need to do some tricks */
+ if (t->mode == TFM_TIME_EXTEND) {
+
+ /* *** Extend Transform *** */
+
+ Scene *scene = t->scene;
+ int cfra = CFRA;
+ int left = BKE_sequence_tx_get_final_left(seq, true);
+ 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;
+ }
+ 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;
+ else if (t->frame_side == 'L' && left >= cfra)
+ *recursive = false;
+ else
+ *recursive = true;
+
+ *count = 1;
+ *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);
+
+ if (t->frame_side == 'R') {
+ if (right <= cfra) {
+ *count = *flag = 0;
+ } /* ignore */
+ else if (left > cfra) {
+ } /* keep the selection */
+ else
+ *flag |= SEQ_RIGHTSEL;
+ }
+ else {
+ if (left >= cfra) {
+ *count = *flag = 0;
+ } /* ignore */
+ else if (right < cfra) {
+ } /* keep the selection */
+ else
+ *flag |= SEQ_LEFTSEL;
+ }
+ }
+ }
+ else {
+
+ t->frame_side = 'B';
+
+ /* *** Normal Transform *** */
+
+ if (seq->depth == 0) {
+
+ /* Count */
+
+ /* Non nested strips (resect selection and handles) */
+ if ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK)) {
+ *recursive = false;
+ *count = 0;
+ *flag = 0;
+ }
+ else {
+ if ((seq->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) == (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
+ *flag = seq->flag;
+ *count = 2; /* we need 2 transdata's */
+ }
+ else {
+ *flag = seq->flag;
+ *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;
+ }
+ else {
+ *recursive = false;
+ }
+ }
+ }
+ else {
+ /* 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);
+ *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
+ *count = 1; /* ignore the selection for nested */
+ *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 toplevel meta */
- *flag = 0;
- *count = 0;
- *recursive = true;
- }
- else {
- *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
- *count = 1; /* ignore the selection for nested */
- *recursive = false;
- }
+ 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 toplevel meta */
+ *flag = 0;
+ *count = 0;
+ *recursive = true;
+ }
+ else {
+ *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
+ *count = 1; /* ignore the selection for nested */
+ *recursive = false;
+ }
#endif
- }
- }
+ }
+ }
}
-
-
static int SeqTransCount(TransInfo *t, Sequence *parent, ListBase *seqbase, int depth)
{
- Sequence *seq;
- int tot = 0, recursive, count, flag;
+ Sequence *seq;
+ int tot = 0, recursive, count, flag;
- for (seq = seqbase->first; seq; seq = seq->next) {
- seq->depth = depth;
+ for (seq = seqbase->first; seq; seq = seq->next) {
+ seq->depth = depth;
- /* seq->tmp is used by seq_tx_get_final_{left, right} to check sequence's range and clamp to it if needed.
- * it's first place where digging into sequences tree, so store link to parent here */
- seq->tmp = parent;
+ /* seq->tmp is used by seq_tx_get_final_{left, right} to check sequence's range and clamp to it if needed.
+ * it's first place where digging into sequences tree, so store link to parent here */
+ seq->tmp = parent;
- SeqTransInfo(t, seq, &recursive, &count, &flag); /* ignore the flag */
- tot += count;
+ SeqTransInfo(t, seq, &recursive, &count, &flag); /* ignore the flag */
+ tot += count;
- if (recursive) {
- tot += SeqTransCount(t, seq, &seq->seqbase, depth + 1);
- }
- }
+ if (recursive) {
+ tot += SeqTransCount(t, seq, &seq->seqbase, depth + 1);
+ }
+ }
- return tot;
+ return tot;
}
-
-static TransData *SeqToTransData(TransData *td, TransData2D *td2d, TransDataSeq *tdsq, Sequence *seq, int flag, int sel_flag)
+static TransData *SeqToTransData(
+ TransData *td, TransData2D *td2d, TransDataSeq *tdsq, Sequence *seq, int flag, int sel_flag)
{
- int start_left;
-
- switch (sel_flag) {
- case SELECT:
- /* Use seq_tx_get_final_left() and an offset here
- * so transform has the left hand location of the strip.
- * tdsq->start_offset is used when flushing the tx data back */
- start_left = BKE_sequence_tx_get_final_left(seq, false);
- td2d->loc[0] = start_left;
- tdsq->start_offset = start_left - seq->start; /* use to apply the original location */
- break;
- case SEQ_LEFTSEL:
- start_left = BKE_sequence_tx_get_final_left(seq, false);
- td2d->loc[0] = start_left;
- break;
- case SEQ_RIGHTSEL:
- td2d->loc[0] = BKE_sequence_tx_get_final_right(seq, false);
- break;
- }
+ int start_left;
- td2d->loc[1] = seq->machine; /* channel - Y location */
- td2d->loc[2] = 0.0f;
- td2d->loc2d = NULL;
+ switch (sel_flag) {
+ case SELECT:
+ /* Use seq_tx_get_final_left() and an offset here
+ * so transform has the left hand location of the strip.
+ * tdsq->start_offset is used when flushing the tx data back */
+ start_left = BKE_sequence_tx_get_final_left(seq, false);
+ td2d->loc[0] = start_left;
+ tdsq->start_offset = start_left - seq->start; /* use to apply the original location */
+ break;
+ case SEQ_LEFTSEL:
+ start_left = BKE_sequence_tx_get_final_left(seq, false);
+ td2d->loc[0] = start_left;
+ break;
+ case SEQ_RIGHTSEL:
+ td2d->loc[0] = BKE_sequence_tx_get_final_right(seq, false);
+ break;
+ }
+ td2d->loc[1] = seq->machine; /* channel - Y location */
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = NULL;
- tdsq->seq = seq;
+ tdsq->seq = seq;
- /* Use instead of seq->flag for nested strips and other
- * cases where the selection may need to be modified */
- tdsq->flag = flag;
- tdsq->sel_flag = sel_flag;
+ /* Use instead of seq->flag for nested strips and other
+ * cases where the selection may need to be modified */
+ tdsq->flag = flag;
+ tdsq->sel_flag = sel_flag;
+ td->extra = (void *)tdsq; /* allow us to update the strip from here */
- td->extra = (void *)tdsq; /* allow us to update the strip from here */
+ td->flag = 0;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->center, td->loc);
+ copy_v3_v3(td->iloc, td->loc);
- td->flag = 0;
- td->loc = td2d->loc;
- copy_v3_v3(td->center, td->loc);
- copy_v3_v3(td->iloc, td->loc);
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
+ td->ext = NULL;
+ td->val = NULL;
- td->ext = NULL; td->val = NULL;
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
- td->flag |= TD_SELECTED;
- td->dist = 0.0;
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
- unit_m3(td->mtx);
- unit_m3(td->smtx);
+ /* Time Transform (extend) */
+ td->val = td2d->loc;
+ td->ival = td2d->loc[0];
- /* Time Transform (extend) */
- td->val = td2d->loc;
- td->ival = td2d->loc[0];
-
- return td;
+ return td;
}
-static int SeqToTransData_Recursive(TransInfo *t, ListBase *seqbase, TransData *td, TransData2D *td2d, TransDataSeq *tdsq)
+static int SeqToTransData_Recursive(
+ TransInfo *t, ListBase *seqbase, TransData *td, TransData2D *td2d, TransDataSeq *tdsq)
{
- Sequence *seq;
- int recursive, count, flag;
- int tot = 0;
+ Sequence *seq;
+ int recursive, count, flag;
+ int tot = 0;
- for (seq = seqbase->first; seq; seq = seq->next) {
+ for (seq = seqbase->first; seq; seq = seq->next) {
- SeqTransInfo(t, seq, &recursive, &count, &flag);
+ SeqTransInfo(t, seq, &recursive, &count, &flag);
- /* add children first so recalculating metastrips does nested strips first */
- if (recursive) {
- int tot_children = SeqToTransData_Recursive(t, &seq->seqbase, td, td2d, tdsq);
+ /* add children first so recalculating metastrips does nested strips first */
+ if (recursive) {
+ int tot_children = SeqToTransData_Recursive(t, &seq->seqbase, td, td2d, tdsq);
- td = td + tot_children;
- td2d = td2d + tot_children;
- tdsq = tdsq + tot_children;
+ td = td + tot_children;
+ td2d = td2d + tot_children;
+ tdsq = tdsq + tot_children;
- tot += tot_children;
- }
+ tot += tot_children;
+ }
- /* use 'flag' which is derived from seq->flag but modified for special cases */
- if (flag & SELECT) {
- if (flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
- if (flag & SEQ_LEFTSEL) {
- SeqToTransData(td++, td2d++, tdsq++, seq, flag, SEQ_LEFTSEL);
- tot++;
- }
- if (flag & SEQ_RIGHTSEL) {
- SeqToTransData(td++, td2d++, tdsq++, seq, flag, SEQ_RIGHTSEL);
- tot++;
- }
- }
- else {
- SeqToTransData(td++, td2d++, tdsq++, seq, flag, SELECT);
- tot++;
- }
- }
- }
- return tot;
+ /* use 'flag' which is derived from seq->flag but modified for special cases */
+ if (flag & SELECT) {
+ if (flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
+ if (flag & SEQ_LEFTSEL) {
+ SeqToTransData(td++, td2d++, tdsq++, seq, flag, SEQ_LEFTSEL);
+ tot++;
+ }
+ if (flag & SEQ_RIGHTSEL) {
+ SeqToTransData(td++, td2d++, tdsq++, seq, flag, SEQ_RIGHTSEL);
+ tot++;
+ }
+ }
+ else {
+ SeqToTransData(td++, td2d++, tdsq++, seq, flag, SELECT);
+ tot++;
+ }
+ }
+ }
+ return tot;
}
-
static void SeqTransDataBounds(TransInfo *t, ListBase *seqbase, TransSeq *ts)
{
- Sequence *seq;
- int recursive, count, flag;
- int max = INT32_MIN, min = INT32_MAX;
-
- for (seq = seqbase->first; seq; seq = seq->next) {
-
- /* just to get the flag since there are corner cases where this isn't totally obvious */
- SeqTransInfo(t, seq, &recursive, &count, &flag);
-
- /* use 'flag' which is derived from seq->flag but modified for special cases */
- if (flag & SELECT) {
- if (flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
- if (flag & SEQ_LEFTSEL) {
- min = min_ii(seq->startdisp, min);
- max = max_ii(seq->startdisp, max);
- }
- if (flag & SEQ_RIGHTSEL) {
- min = min_ii(seq->enddisp, min);
- max = max_ii(seq->enddisp, max);
- }
- }
- else {
- min = min_ii(seq->startdisp, min);
- max = max_ii(seq->enddisp, max);
- }
- }
- }
-
- if (ts) {
- ts->max = max;
- ts->min = min;
- }
+ Sequence *seq;
+ int recursive, count, flag;
+ int max = INT32_MIN, min = INT32_MAX;
+
+ for (seq = seqbase->first; seq; seq = seq->next) {
+
+ /* just to get the flag since there are corner cases where this isn't totally obvious */
+ SeqTransInfo(t, seq, &recursive, &count, &flag);
+
+ /* use 'flag' which is derived from seq->flag but modified for special cases */
+ if (flag & SELECT) {
+ if (flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
+ if (flag & SEQ_LEFTSEL) {
+ min = min_ii(seq->startdisp, min);
+ max = max_ii(seq->startdisp, max);
+ }
+ if (flag & SEQ_RIGHTSEL) {
+ min = min_ii(seq->enddisp, min);
+ max = max_ii(seq->enddisp, max);
+ }
+ }
+ else {
+ min = min_ii(seq->startdisp, min);
+ max = max_ii(seq->enddisp, max);
+ }
+ }
+ }
+
+ if (ts) {
+ ts->max = max;
+ ts->min = min;
+ }
}
-
static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data)
{
- Editing *ed = BKE_sequencer_editing_get(t->scene, false);
-
- if (ed != NULL) {
-
-
- ListBase *seqbasep = ed->seqbasep;
- TransData *td = tc->data;
- int a;
-
- /* prevent updating the same seq twice
- * if the transdata order is changed this will mess up
- * but so will TransDataSeq */
- Sequence *seq_prev = NULL;
- Sequence *seq;
-
-
- if (!(t->state == TRANS_CANCEL)) {
-
-#if 0 // default 2.4 behavior
-
- /* flush to 2d vector from internally used 3d vector */
- for (a = 0; a < t->total; a++, td++) {
- if ((seq != seq_prev) && (seq->depth == 0) && (seq->flag & SEQ_OVERLAP)) {
- seq = ((TransDataSeq *)td->extra)->seq;
- BKE_sequence_base_shuffle(seqbasep, seq, t->scene);
- }
-
- seq_prev = seq;
- }
-
-#else // durian hack
- {
- int overlap = 0;
-
- for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
- seq = ((TransDataSeq *)td->extra)->seq;
- if ((seq != seq_prev) && (seq->depth == 0) && (seq->flag & SEQ_OVERLAP)) {
- overlap = 1;
- break;
- }
- }
-
- if (overlap) {
- bool has_effect_root = false, has_effect_any = false;
- for (seq = seqbasep->first; seq; seq = seq->next)
- seq->tmp = NULL;
-
- td = tc->data;
- for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
- seq = ((TransDataSeq *)td->extra)->seq;
- if ((seq != seq_prev)) {
- /* check effects strips, we cant change their time */
- if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) {
- has_effect_any = true;
- if (seq->depth == 0) {
- has_effect_root = true;
- }
- }
- else {
- /* Tag seq with a non zero value, used by
- * BKE_sequence_base_shuffle_time to identify the ones to shuffle */
- if (seq->depth == 0) {
- seq->tmp = (void *)1;
- }
- }
- }
-
- }
-
- if (t->flag & T_ALT_TRANSFORM) {
- int minframe = MAXFRAME;
- td = tc->data;
- for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
- seq = ((TransDataSeq *)td->extra)->seq;
- if ((seq != seq_prev) && (seq->depth == 0)) {
- minframe = min_ii(minframe, seq->startdisp);
- }
- }
-
-
- for (seq = seqbasep->first; seq; seq = seq->next) {
- if (!(seq->flag & SELECT)) {
- if (seq->startdisp >= minframe) {
- seq->machine += MAXSEQ * 2;
- }
- }
- }
-
- BKE_sequence_base_shuffle_time(seqbasep, t->scene);
-
- for (seq = seqbasep->first; seq; seq = seq->next) {
- if (seq->machine >= MAXSEQ * 2) {
- seq->machine -= MAXSEQ * 2;
- seq->tmp = (void *)1;
- }
- else {
- seq->tmp = NULL;
- }
- }
-
- BKE_sequence_base_shuffle_time(seqbasep, t->scene);
- }
- else {
- BKE_sequence_base_shuffle_time(seqbasep, t->scene);
- }
-
- if (has_effect_any) {
- /* update effects strips based on strips just moved in time */
- td = tc->data;
- for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
- seq = ((TransDataSeq *)td->extra)->seq;
- if ((seq != seq_prev)) {
- if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) {
- BKE_sequence_calc(t->scene, seq);
- }
- }
- }
- }
-
- if (has_effect_root) {
- /* now if any effects _still_ overlap, we need to move them up */
- td = tc->data;
- for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
- seq = ((TransDataSeq *)td->extra)->seq;
- if ((seq != seq_prev) && (seq->depth == 0)) {
- if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) {
- if (BKE_sequence_test_overlap(seqbasep, seq)) {
- BKE_sequence_base_shuffle(seqbasep, seq, t->scene);
- }
- }
- }
- }
- /* done with effects */
- }
- }
- }
+ Editing *ed = BKE_sequencer_editing_get(t->scene, false);
+
+ if (ed != NULL) {
+
+ ListBase *seqbasep = ed->seqbasep;
+ TransData *td = tc->data;
+ int a;
+
+ /* prevent updating the same seq twice
+ * if the transdata order is changed this will mess up
+ * but so will TransDataSeq */
+ Sequence *seq_prev = NULL;
+ Sequence *seq;
+
+ if (!(t->state == TRANS_CANCEL)) {
+
+#if 0 // default 2.4 behavior
+
+ /* flush to 2d vector from internally used 3d vector */
+ for (a = 0; a < t->total; a++, td++) {
+ if ((seq != seq_prev) && (seq->depth == 0) && (seq->flag & SEQ_OVERLAP)) {
+ seq = ((TransDataSeq *)td->extra)->seq;
+ BKE_sequence_base_shuffle(seqbasep, seq, t->scene);
+ }
+
+ seq_prev = seq;
+ }
+
+#else // durian hack
+ {
+ int overlap = 0;
+
+ for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
+ seq = ((TransDataSeq *)td->extra)->seq;
+ if ((seq != seq_prev) && (seq->depth == 0) && (seq->flag & SEQ_OVERLAP)) {
+ overlap = 1;
+ break;
+ }
+ }
+
+ if (overlap) {
+ bool has_effect_root = false, has_effect_any = false;
+ for (seq = seqbasep->first; seq; seq = seq->next)
+ seq->tmp = NULL;
+
+ td = tc->data;
+ for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
+ seq = ((TransDataSeq *)td->extra)->seq;
+ if ((seq != seq_prev)) {
+ /* check effects strips, we cant change their time */
+ if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) {
+ has_effect_any = true;
+ if (seq->depth == 0) {
+ has_effect_root = true;
+ }
+ }
+ else {
+ /* Tag seq with a non zero value, used by
+ * BKE_sequence_base_shuffle_time to identify the ones to shuffle */
+ if (seq->depth == 0) {
+ seq->tmp = (void *)1;
+ }
+ }
+ }
+ }
+
+ if (t->flag & T_ALT_TRANSFORM) {
+ int minframe = MAXFRAME;
+ td = tc->data;
+ for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
+ seq = ((TransDataSeq *)td->extra)->seq;
+ if ((seq != seq_prev) && (seq->depth == 0)) {
+ minframe = min_ii(minframe, seq->startdisp);
+ }
+ }
+
+ for (seq = seqbasep->first; seq; seq = seq->next) {
+ if (!(seq->flag & SELECT)) {
+ if (seq->startdisp >= minframe) {
+ seq->machine += MAXSEQ * 2;
+ }
+ }
+ }
+
+ BKE_sequence_base_shuffle_time(seqbasep, t->scene);
+
+ for (seq = seqbasep->first; seq; seq = seq->next) {
+ if (seq->machine >= MAXSEQ * 2) {
+ seq->machine -= MAXSEQ * 2;
+ seq->tmp = (void *)1;
+ }
+ else {
+ seq->tmp = NULL;
+ }
+ }
+
+ BKE_sequence_base_shuffle_time(seqbasep, t->scene);
+ }
+ else {
+ BKE_sequence_base_shuffle_time(seqbasep, t->scene);
+ }
+
+ if (has_effect_any) {
+ /* update effects strips based on strips just moved in time */
+ td = tc->data;
+ for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
+ seq = ((TransDataSeq *)td->extra)->seq;
+ if ((seq != seq_prev)) {
+ if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) {
+ BKE_sequence_calc(t->scene, seq);
+ }
+ }
+ }
+ }
+
+ if (has_effect_root) {
+ /* now if any effects _still_ overlap, we need to move them up */
+ td = tc->data;
+ for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
+ seq = ((TransDataSeq *)td->extra)->seq;
+ if ((seq != seq_prev) && (seq->depth == 0)) {
+ if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) {
+ if (BKE_sequence_test_overlap(seqbasep, seq)) {
+ BKE_sequence_base_shuffle(seqbasep, seq, t->scene);
+ }
+ }
+ }
+ }
+ /* done with effects */
+ }
+ }
+ }
#endif
- for (seq = seqbasep->first; seq; seq = seq->next) {
- /* We might want to build a list of effects that need to be updated during transform */
- if (seq->type & SEQ_TYPE_EFFECT) {
- if (seq->seq1 && seq->seq1->flag & SELECT) BKE_sequence_calc(t->scene, seq);
- else if (seq->seq2 && seq->seq2->flag & SELECT) BKE_sequence_calc(t->scene, seq);
- else if (seq->seq3 && seq->seq3->flag & SELECT) BKE_sequence_calc(t->scene, seq);
- }
- }
-
- BKE_sequencer_sort(t->scene);
- }
- else {
- /* Canceled, need to update the strips display */
- for (a = 0; a < tc->data_len; a++, td++) {
- seq = ((TransDataSeq *)td->extra)->seq;
- if ((seq != seq_prev) && (seq->depth == 0)) {
- if (seq->flag & SEQ_OVERLAP)
- BKE_sequence_base_shuffle(seqbasep, seq, t->scene);
-
- BKE_sequence_calc_disp(t->scene, seq);
- }
- seq_prev = seq;
- }
- }
- }
-
- if ((custom_data->data != NULL) && custom_data->use_free) {
- TransSeq *ts = custom_data->data;
- MEM_freeN(ts->tdseq);
- MEM_freeN(custom_data->data);
- custom_data->data = NULL;
- }
+ for (seq = seqbasep->first; seq; seq = seq->next) {
+ /* We might want to build a list of effects that need to be updated during transform */
+ if (seq->type & SEQ_TYPE_EFFECT) {
+ if (seq->seq1 && seq->seq1->flag & SELECT)
+ BKE_sequence_calc(t->scene, seq);
+ else if (seq->seq2 && seq->seq2->flag & SELECT)
+ BKE_sequence_calc(t->scene, seq);
+ else if (seq->seq3 && seq->seq3->flag & SELECT)
+ BKE_sequence_calc(t->scene, seq);
+ }
+ }
+
+ BKE_sequencer_sort(t->scene);
+ }
+ else {
+ /* Canceled, need to update the strips display */
+ for (a = 0; a < tc->data_len; a++, td++) {
+ seq = ((TransDataSeq *)td->extra)->seq;
+ if ((seq != seq_prev) && (seq->depth == 0)) {
+ if (seq->flag & SEQ_OVERLAP)
+ BKE_sequence_base_shuffle(seqbasep, seq, t->scene);
+
+ BKE_sequence_calc_disp(t->scene, seq);
+ }
+ seq_prev = seq;
+ }
+ }
+ }
+
+ if ((custom_data->data != NULL) && custom_data->use_free) {
+ TransSeq *ts = custom_data->data;
+ MEM_freeN(ts->tdseq);
+ MEM_freeN(custom_data->data);
+ custom_data->data = NULL;
+ }
}
static void createTransSeqData(bContext *C, 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;
+ 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;
+ int count = 0;
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- if (ed == NULL) {
- tc->data_len = 0;
- return;
- }
+ if (ed == NULL) {
+ tc->data_len = 0;
+ return;
+ }
- tc->custom.type.free_cb = freeSeqData;
+ tc->custom.type.free_cb = freeSeqData;
- xmouse = (int)UI_view2d_region_to_view_x(v2d, t->mouse.imval[0]);
+ 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';
- }
+ /* 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';
+ }
#ifdef XXX_DURIAN_ANIM_TX_HACK
- {
- Sequence *seq;
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- /* hack */
- if ((seq->flag & SELECT) == 0 && seq->type & SEQ_TYPE_EFFECT) {
- Sequence *seq_user;
- int i;
- for (i = 0; i < 3; i++) {
- seq_user = *((&seq->seq1) + i);
- if (seq_user && (seq_user->flag & SELECT) &&
- !(seq_user->flag & SEQ_LOCK) &&
- !(seq_user->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)))
- {
- seq->flag |= SELECT;
- }
- }
- }
- }
- }
+ {
+ Sequence *seq;
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ /* hack */
+ if ((seq->flag & SELECT) == 0 && seq->type & SEQ_TYPE_EFFECT) {
+ Sequence *seq_user;
+ int i;
+ for (i = 0; i < 3; i++) {
+ seq_user = *((&seq->seq1) + i);
+ if (seq_user && (seq_user->flag & SELECT) && !(seq_user->flag & SEQ_LOCK) &&
+ !(seq_user->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL))) {
+ seq->flag |= SELECT;
+ }
+ }
+ }
+ }
+ }
#endif
- count = SeqTransCount(t, NULL, ed->seqbasep, 0);
+ count = SeqTransCount(t, NULL, ed->seqbasep, 0);
- /* allocate memory for data */
- tc->data_len = count;
+ /* allocate memory for data */
+ tc->data_len = count;
- /* stop if trying to build list if nothing selected */
- if (count == 0) {
- return;
- }
+ /* stop if trying to build list if nothing selected */
+ if (count == 0) {
+ return;
+ }
- tc->custom.type.data = ts = MEM_callocN(sizeof(TransSeq), "transseq");
- tc->custom.type.use_free = true;
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransSeq TransData");
- td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransSeq TransData2D");
- ts->tdseq = tdsq = MEM_callocN(tc->data_len * sizeof(TransDataSeq), "TransSeq TransDataSeq");
+ tc->custom.type.data = ts = MEM_callocN(sizeof(TransSeq), "transseq");
+ tc->custom.type.use_free = true;
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransSeq TransData");
+ td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransSeq TransData2D");
+ ts->tdseq = tdsq = MEM_callocN(tc->data_len * sizeof(TransDataSeq), "TransSeq TransDataSeq");
- /* loop 2: build transdata array */
- SeqToTransData_Recursive(t, ed->seqbasep, td, td2d, tdsq);
- SeqTransDataBounds(t, ed->seqbasep, ts);
+ /* loop 2: build transdata array */
+ 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;
+ /* 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;
#undef XXX_DURIAN_ANIM_TX_HACK
}
-
/* *********************** Object Transform data ******************* */
/* Little helper function for ObjectToTransData used to give certain
@@ -5701,381 +5894,375 @@ static void createTransSeqData(bContext *C, TransInfo *t)
*/
static bool constraints_list_needinv(TransInfo *t, ListBase *list)
{
- bConstraint *con;
-
- /* loop through constraints, checking if there's one of the mentioned
- * constraints needing special crazyspace corrections
- */
- if (list) {
- for (con = list->first; con; con = con->next) {
- /* only consider constraint if it is enabled, and has influence on result */
- if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f)) {
- /* (affirmative) returns for specific constraints here... */
- /* constraints that require this regardless */
- if (ELEM(con->type,
- CONSTRAINT_TYPE_FOLLOWPATH,
- CONSTRAINT_TYPE_CLAMPTO,
- CONSTRAINT_TYPE_ARMATURE,
- CONSTRAINT_TYPE_OBJECTSOLVER,
- CONSTRAINT_TYPE_FOLLOWTRACK))
- {
- return true;
- }
-
- /* constraints that require this only under special conditions */
- if (con->type == CONSTRAINT_TYPE_CHILDOF) {
- /* ChildOf constraint only works when using all location components, see T42256. */
- bChildOfConstraint *data = (bChildOfConstraint *)con->data;
-
- if ((data->flag & CHILDOF_LOCX) && (data->flag & CHILDOF_LOCY) && (data->flag & CHILDOF_LOCZ))
- return true;
- }
- else if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
- /* CopyRot constraint only does this when rotating, and offset is on */
- bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data;
-
- if ((data->flag & ROTLIKE_OFFSET) && (t->mode == TFM_ROTATION))
- return true;
- }
- else if (con->type == CONSTRAINT_TYPE_TRANSFORM) {
- /* Transform constraint needs it for rotation at least (r.57309),
- * but doing so when translating may also mess things up [#36203]
- */
-
- if (t->mode == TFM_ROTATION)
- return true;
- /* ??? (t->mode == TFM_SCALE) ? */
- }
- }
- }
- }
-
- /* no appropriate candidates found */
- return false;
+ bConstraint *con;
+
+ /* loop through constraints, checking if there's one of the mentioned
+ * constraints needing special crazyspace corrections
+ */
+ if (list) {
+ for (con = list->first; con; con = con->next) {
+ /* only consider constraint if it is enabled, and has influence on result */
+ if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f)) {
+ /* (affirmative) returns for specific constraints here... */
+ /* constraints that require this regardless */
+ if (ELEM(con->type,
+ CONSTRAINT_TYPE_FOLLOWPATH,
+ CONSTRAINT_TYPE_CLAMPTO,
+ CONSTRAINT_TYPE_ARMATURE,
+ CONSTRAINT_TYPE_OBJECTSOLVER,
+ CONSTRAINT_TYPE_FOLLOWTRACK)) {
+ return true;
+ }
+
+ /* constraints that require this only under special conditions */
+ if (con->type == CONSTRAINT_TYPE_CHILDOF) {
+ /* ChildOf constraint only works when using all location components, see T42256. */
+ bChildOfConstraint *data = (bChildOfConstraint *)con->data;
+
+ if ((data->flag & CHILDOF_LOCX) && (data->flag & CHILDOF_LOCY) &&
+ (data->flag & CHILDOF_LOCZ))
+ return true;
+ }
+ else if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
+ /* CopyRot constraint only does this when rotating, and offset is on */
+ bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data;
+
+ if ((data->flag & ROTLIKE_OFFSET) && (t->mode == TFM_ROTATION))
+ return true;
+ }
+ else if (con->type == CONSTRAINT_TYPE_TRANSFORM) {
+ /* Transform constraint needs it for rotation at least (r.57309),
+ * but doing so when translating may also mess things up [#36203]
+ */
+
+ if (t->mode == TFM_ROTATION)
+ return true;
+ /* ??? (t->mode == TFM_SCALE) ? */
+ }
+ }
+ }
+ }
+
+ /* no appropriate candidates found */
+ return false;
}
/* transcribe given object into TransData for Transforming */
static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
{
- Scene *scene = t->scene;
- bool constinv;
- bool skip_invert = false;
-
- if (t->mode != TFM_DUMMY && ob->rigidbody_object) {
- float rot[3][3], scale[3];
- float ctime = BKE_scene_frame_get(scene);
-
- /* only use rigid body transform if simulation is running,
- * avoids problems with initial setup of rigid bodies */
- if (BKE_rigidbody_check_sim_running(scene->rigidbody_world, ctime)) {
-
- /* save original object transform */
- copy_v3_v3(td->ext->oloc, ob->loc);
-
- if (ob->rotmode > 0) {
- copy_v3_v3(td->ext->orot, ob->rot);
- }
- else if (ob->rotmode == ROT_MODE_AXISANGLE) {
- td->ext->orotAngle = ob->rotAngle;
- copy_v3_v3(td->ext->orotAxis, ob->rotAxis);
- }
- else {
- copy_qt_qt(td->ext->oquat, ob->quat);
- }
- /* update object's loc/rot to get current rigid body transform */
- mat4_to_loc_rot_size(ob->loc, rot, scale, ob->obmat);
- sub_v3_v3(ob->loc, ob->dloc);
- BKE_object_mat3_to_rot(ob, rot, false); /* drot is already corrected here */
- }
- }
-
- /* axismtx has the real orientation */
- copy_m3_m4(td->axismtx, ob->obmat);
- normalize_m3(td->axismtx);
-
- td->con = ob->constraints.first;
-
- /* hack: temporarily disable tracking and/or constraints when getting
- * object matrix, if tracking is on, or if constraints don't need
- * inverse correction to stop it from screwing up space conversion
- * matrix later
- */
- constinv = constraints_list_needinv(t, &ob->constraints);
-
- /* disable constraints inversion for dummy pass */
- if (t->mode == TFM_DUMMY)
- skip_invert = true;
-
- /* 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
- * 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. */
- Object *object_eval = DEG_get_evaluated_object(t->depsgraph, ob);
- if (skip_invert == false && constinv == false) {
- object_eval->transflag |= OB_NO_CONSTRAINTS; /* BKE_object_where_is_calc checks this */
- /* It is possible to have transform data initialization prior to a
- * complete dependency graph evaluated. Happens, for example, when
- * changing transformation mode. */
- BKE_object_tfm_copy(object_eval, ob);
- BKE_object_where_is_calc(t->depsgraph, t->scene, object_eval);
- object_eval->transflag &= ~OB_NO_CONSTRAINTS;
- }
- else {
- BKE_object_where_is_calc(t->depsgraph, t->scene, object_eval);
- }
- /* Copy newly evaluated fields to the original object, similar to how
- * active dependency graph will do it. */
- copy_m4_m4(ob->obmat, object_eval->obmat);
- /* Only copy negative scale flag, this is the only flag which is modified by
- * the BKE_object_where_is_calc(). The rest of the flags we need to keep,
- * otherwise we might loose dupli flags (see T61787). */
- ob->transflag &= ~OB_NEG_SCALE;
- ob->transflag |= (object_eval->transflag & OB_NEG_SCALE);
-
- td->ob = ob;
-
- td->loc = ob->loc;
- copy_v3_v3(td->iloc, td->loc);
-
- if (ob->rotmode > 0) {
- td->ext->rot = ob->rot;
- td->ext->rotAxis = NULL;
- td->ext->rotAngle = NULL;
- td->ext->quat = NULL;
-
- copy_v3_v3(td->ext->irot, ob->rot);
- copy_v3_v3(td->ext->drot, ob->drot);
- }
- else if (ob->rotmode == ROT_MODE_AXISANGLE) {
- td->ext->rot = NULL;
- td->ext->rotAxis = ob->rotAxis;
- td->ext->rotAngle = &ob->rotAngle;
- td->ext->quat = NULL;
-
- td->ext->irotAngle = ob->rotAngle;
- copy_v3_v3(td->ext->irotAxis, ob->rotAxis);
- // td->ext->drotAngle = ob->drotAngle; // XXX, not implemented
- // copy_v3_v3(td->ext->drotAxis, ob->drotAxis); // XXX, not implemented
- }
- else {
- td->ext->rot = NULL;
- td->ext->rotAxis = NULL;
- td->ext->rotAngle = NULL;
- td->ext->quat = ob->quat;
-
- copy_qt_qt(td->ext->iquat, ob->quat);
- copy_qt_qt(td->ext->dquat, ob->dquat);
- }
- td->ext->rotOrder = ob->rotmode;
-
- td->ext->size = ob->scale;
- copy_v3_v3(td->ext->isize, ob->scale);
- copy_v3_v3(td->ext->dscale, ob->dscale);
-
- copy_v3_v3(td->center, ob->obmat[3]);
-
- copy_m4_m4(td->ext->obmat, ob->obmat);
-
- /* is there a need to set the global<->data space conversion matrices? */
- if (ob->parent || constinv) {
- float obmtx[3][3], totmat[3][3], obinv[3][3];
-
- /* Get the effect of parenting, and/or certain constraints.
- * NOTE: some Constraints, and also Tracking should never get this
- * done, as it doesn't work well.
- */
- BKE_object_to_mat3(ob, obmtx);
- copy_m3_m4(totmat, ob->obmat);
- invert_m3_m3(obinv, totmat);
- mul_m3_m3m3(td->smtx, obmtx, obinv);
- invert_m3_m3(td->mtx, td->smtx);
- }
- else {
- /* no conversion to/from dataspace */
- unit_m3(td->smtx);
- unit_m3(td->mtx);
- }
+ Scene *scene = t->scene;
+ bool constinv;
+ bool skip_invert = false;
+
+ if (t->mode != TFM_DUMMY && ob->rigidbody_object) {
+ float rot[3][3], scale[3];
+ float ctime = BKE_scene_frame_get(scene);
+
+ /* only use rigid body transform if simulation is running,
+ * avoids problems with initial setup of rigid bodies */
+ if (BKE_rigidbody_check_sim_running(scene->rigidbody_world, ctime)) {
+
+ /* save original object transform */
+ copy_v3_v3(td->ext->oloc, ob->loc);
+
+ if (ob->rotmode > 0) {
+ copy_v3_v3(td->ext->orot, ob->rot);
+ }
+ else if (ob->rotmode == ROT_MODE_AXISANGLE) {
+ td->ext->orotAngle = ob->rotAngle;
+ copy_v3_v3(td->ext->orotAxis, ob->rotAxis);
+ }
+ else {
+ copy_qt_qt(td->ext->oquat, ob->quat);
+ }
+ /* update object's loc/rot to get current rigid body transform */
+ mat4_to_loc_rot_size(ob->loc, rot, scale, ob->obmat);
+ sub_v3_v3(ob->loc, ob->dloc);
+ BKE_object_mat3_to_rot(ob, rot, false); /* drot is already corrected here */
+ }
+ }
+
+ /* axismtx has the real orientation */
+ copy_m3_m4(td->axismtx, ob->obmat);
+ normalize_m3(td->axismtx);
+
+ td->con = ob->constraints.first;
+
+ /* hack: temporarily disable tracking and/or constraints when getting
+ * object matrix, if tracking is on, or if constraints don't need
+ * inverse correction to stop it from screwing up space conversion
+ * matrix later
+ */
+ constinv = constraints_list_needinv(t, &ob->constraints);
+
+ /* disable constraints inversion for dummy pass */
+ if (t->mode == TFM_DUMMY)
+ skip_invert = true;
+
+ /* 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
+ * 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. */
+ Object *object_eval = DEG_get_evaluated_object(t->depsgraph, ob);
+ if (skip_invert == false && constinv == false) {
+ object_eval->transflag |= OB_NO_CONSTRAINTS; /* BKE_object_where_is_calc checks this */
+ /* It is possible to have transform data initialization prior to a
+ * complete dependency graph evaluated. Happens, for example, when
+ * changing transformation mode. */
+ BKE_object_tfm_copy(object_eval, ob);
+ BKE_object_where_is_calc(t->depsgraph, t->scene, object_eval);
+ object_eval->transflag &= ~OB_NO_CONSTRAINTS;
+ }
+ else {
+ BKE_object_where_is_calc(t->depsgraph, t->scene, object_eval);
+ }
+ /* Copy newly evaluated fields to the original object, similar to how
+ * active dependency graph will do it. */
+ copy_m4_m4(ob->obmat, object_eval->obmat);
+ /* Only copy negative scale flag, this is the only flag which is modified by
+ * the BKE_object_where_is_calc(). The rest of the flags we need to keep,
+ * otherwise we might loose dupli flags (see T61787). */
+ ob->transflag &= ~OB_NEG_SCALE;
+ ob->transflag |= (object_eval->transflag & OB_NEG_SCALE);
+
+ td->ob = ob;
+
+ td->loc = ob->loc;
+ copy_v3_v3(td->iloc, td->loc);
+
+ if (ob->rotmode > 0) {
+ td->ext->rot = ob->rot;
+ td->ext->rotAxis = NULL;
+ td->ext->rotAngle = NULL;
+ td->ext->quat = NULL;
+
+ copy_v3_v3(td->ext->irot, ob->rot);
+ copy_v3_v3(td->ext->drot, ob->drot);
+ }
+ else if (ob->rotmode == ROT_MODE_AXISANGLE) {
+ td->ext->rot = NULL;
+ td->ext->rotAxis = ob->rotAxis;
+ td->ext->rotAngle = &ob->rotAngle;
+ td->ext->quat = NULL;
+
+ td->ext->irotAngle = ob->rotAngle;
+ copy_v3_v3(td->ext->irotAxis, ob->rotAxis);
+ // td->ext->drotAngle = ob->drotAngle; // XXX, not implemented
+ // copy_v3_v3(td->ext->drotAxis, ob->drotAxis); // XXX, not implemented
+ }
+ else {
+ td->ext->rot = NULL;
+ td->ext->rotAxis = NULL;
+ td->ext->rotAngle = NULL;
+ td->ext->quat = ob->quat;
+
+ copy_qt_qt(td->ext->iquat, ob->quat);
+ copy_qt_qt(td->ext->dquat, ob->dquat);
+ }
+ td->ext->rotOrder = ob->rotmode;
+
+ td->ext->size = ob->scale;
+ copy_v3_v3(td->ext->isize, ob->scale);
+ copy_v3_v3(td->ext->dscale, ob->dscale);
+
+ copy_v3_v3(td->center, ob->obmat[3]);
+
+ copy_m4_m4(td->ext->obmat, ob->obmat);
+
+ /* is there a need to set the global<->data space conversion matrices? */
+ if (ob->parent || constinv) {
+ float obmtx[3][3], totmat[3][3], obinv[3][3];
+
+ /* Get the effect of parenting, and/or certain constraints.
+ * NOTE: some Constraints, and also Tracking should never get this
+ * done, as it doesn't work well.
+ */
+ BKE_object_to_mat3(ob, obmtx);
+ copy_m3_m4(totmat, ob->obmat);
+ invert_m3_m3(obinv, totmat);
+ mul_m3_m3m3(td->smtx, obmtx, obinv);
+ invert_m3_m3(td->mtx, td->smtx);
+ }
+ else {
+ /* no conversion to/from dataspace */
+ unit_m3(td->smtx);
+ unit_m3(td->mtx);
+ }
}
static void trans_object_base_deps_flag_prepare(ViewLayer *view_layer)
{
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- base->object->id.tag &= ~LIB_TAG_DOIT;
- }
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ base->object->id.tag &= ~LIB_TAG_DOIT;
+ }
}
static void set_trans_object_base_deps_flag_cb(ID *id, void *UNUSED(user_data))
{
- /* Here we only handle object IDs. */
- if (GS(id->name) != ID_OB) {
- return;
- }
- id->tag |= LIB_TAG_DOIT;
+ /* Here we only handle object IDs. */
+ if (GS(id->name) != ID_OB) {
+ return;
+ }
+ id->tag |= LIB_TAG_DOIT;
}
static void flush_trans_object_base_deps_flag(Depsgraph *depsgraph, Object *object)
{
- object->id.tag |= LIB_TAG_DOIT;
- DEG_foreach_dependent_ID(depsgraph, &object->id,
- set_trans_object_base_deps_flag_cb, NULL);
+ object->id.tag |= LIB_TAG_DOIT;
+ DEG_foreach_dependent_ID(depsgraph, &object->id, set_trans_object_base_deps_flag_cb, NULL);
}
static void trans_object_base_deps_flag_finish(ViewLayer *view_layer)
{
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (base->object->id.tag & LIB_TAG_DOIT) {
- base->flag_legacy |= BA_SNAP_FIX_DEPS_FIASCO;
- }
- }
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->object->id.tag & LIB_TAG_DOIT) {
+ base->flag_legacy |= BA_SNAP_FIX_DEPS_FIASCO;
+ }
+ }
}
/* sets flags in Bases to define whether they take part in transform */
/* it deselects Bases, so we have to call the clear function always after */
static void set_trans_object_base_flags(TransInfo *t)
{
- Main *bmain = CTX_data_main(t->context);
- ViewLayer *view_layer = t->view_layer;
- View3D *v3d = t->view;
- Scene *scene = t->scene;
- Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
- /* NOTE: if Base selected and has parent selected:
- * base->flag_legacy = BA_WAS_SEL
- */
- /* Don't do it if we're not actually going to recalculate anything. */
- if (t->mode == TFM_DUMMY) {
- return;
- }
- /* Makes sure base flags and object flags are identical. */
- BKE_scene_base_flag_to_objects(t->view_layer);
- /* Make sure depsgraph is here. */
- DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
- /* 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) {
- base->flag_legacy &= ~BA_WAS_SEL;
- if (BASE_SELECTED_EDITABLE(v3d, base)) {
- Object *ob = base->object;
- Object *parsel = ob->parent;
- /* If parent selected, deselect. */
- while (parsel != NULL) {
- if (parsel->base_flag & BASE_SELECTED) {
- Base *parbase = BKE_view_layer_base_find(view_layer, parsel);
- if (parbase != NULL) { /* in rare cases this can fail */
- if (BASE_SELECTED_EDITABLE(v3d, parbase)) {
- break;
- }
- }
- }
- parsel = parsel->parent;
- }
- if (parsel != NULL) {
- /* Rotation around local centers are allowed to propagate. */
- if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
- (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL))
- {
- base->flag_legacy |= BA_TRANSFORM_CHILD;
- }
- else {
- base->flag &= ~BASE_SELECTED;
- base->flag_legacy |= BA_WAS_SEL;
- }
- }
- flush_trans_object_base_deps_flag(depsgraph, ob);
- }
- }
- /* Store temporary bits in base indicating that base is being modified
- * (directly or indirectly) by transforming objects.
- */
- trans_object_base_deps_flag_finish(view_layer);
+ Main *bmain = CTX_data_main(t->context);
+ ViewLayer *view_layer = t->view_layer;
+ View3D *v3d = t->view;
+ Scene *scene = t->scene;
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+ /* NOTE: if Base selected and has parent selected:
+ * base->flag_legacy = BA_WAS_SEL
+ */
+ /* Don't do it if we're not actually going to recalculate anything. */
+ if (t->mode == TFM_DUMMY) {
+ return;
+ }
+ /* Makes sure base flags and object flags are identical. */
+ BKE_scene_base_flag_to_objects(t->view_layer);
+ /* Make sure depsgraph is here. */
+ DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
+ /* 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) {
+ base->flag_legacy &= ~BA_WAS_SEL;
+ if (BASE_SELECTED_EDITABLE(v3d, base)) {
+ Object *ob = base->object;
+ Object *parsel = ob->parent;
+ /* If parent selected, deselect. */
+ while (parsel != NULL) {
+ if (parsel->base_flag & BASE_SELECTED) {
+ Base *parbase = BKE_view_layer_base_find(view_layer, parsel);
+ if (parbase != NULL) { /* in rare cases this can fail */
+ if (BASE_SELECTED_EDITABLE(v3d, parbase)) {
+ break;
+ }
+ }
+ }
+ parsel = parsel->parent;
+ }
+ if (parsel != NULL) {
+ /* Rotation around local centers are allowed to propagate. */
+ if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
+ (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL)) {
+ base->flag_legacy |= BA_TRANSFORM_CHILD;
+ }
+ else {
+ base->flag &= ~BASE_SELECTED;
+ base->flag_legacy |= BA_WAS_SEL;
+ }
+ }
+ flush_trans_object_base_deps_flag(depsgraph, ob);
+ }
+ }
+ /* Store temporary bits in base indicating that base is being modified
+ * (directly or indirectly) by transforming objects.
+ */
+ trans_object_base_deps_flag_finish(view_layer);
}
static bool mark_children(Object *ob)
{
- if (ob->flag & (SELECT | BA_TRANSFORM_CHILD))
- return true;
+ if (ob->flag & (SELECT | BA_TRANSFORM_CHILD))
+ return true;
- if (ob->parent) {
- if (mark_children(ob->parent)) {
- ob->flag |= BA_TRANSFORM_CHILD;
- return true;
- }
- }
+ if (ob->parent) {
+ if (mark_children(ob->parent)) {
+ ob->flag |= BA_TRANSFORM_CHILD;
+ return true;
+ }
+ }
- return false;
+ return false;
}
static int count_proportional_objects(TransInfo *t)
{
- int total = 0;
- ViewLayer *view_layer = t->view_layer;
- View3D *v3d = t->view;
- Scene *scene = t->scene;
- Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
- /* Clear all flags we need. It will be used to detect dependencies. */
- trans_object_base_deps_flag_prepare(view_layer);
- /* Rotations around local centers are allowed to propagate, so we take all objects. */
- 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) {
- if (BASE_SELECTED_EDITABLE(v3d, base)) {
- Object *parent = base->object->parent;
- /* flag all parents */
- while (parent != NULL) {
- parent->flag |= BA_TRANSFORM_PARENT;
- parent = parent->parent;
- }
- }
- }
- /* Mark all children. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- /* 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 &&
- (BASE_EDITABLE(v3d, base)))
- {
- mark_children(base->object);
- }
- }
- }
- /* Flush changed flags to all dependencies. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- Object *ob = base->object;
- /* If base is not selected, not a parent of selection or not a child of
- * selection and it is editable.
- */
- if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
- (base->flag & BASE_SELECTED) == 0 &&
- (BASE_EDITABLE(v3d, base)))
- {
- flush_trans_object_base_deps_flag(depsgraph, ob);
- total += 1;
- }
- }
- /* Store temporary bits in base indicating that base is being modified
- * (directly or indirectly) by transforming objects.
- */
- trans_object_base_deps_flag_finish(view_layer);
- return total;
+ int total = 0;
+ ViewLayer *view_layer = t->view_layer;
+ View3D *v3d = t->view;
+ Scene *scene = t->scene;
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+ /* Clear all flags we need. It will be used to detect dependencies. */
+ trans_object_base_deps_flag_prepare(view_layer);
+ /* Rotations around local centers are allowed to propagate, so we take all objects. */
+ 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) {
+ if (BASE_SELECTED_EDITABLE(v3d, base)) {
+ Object *parent = base->object->parent;
+ /* flag all parents */
+ while (parent != NULL) {
+ parent->flag |= BA_TRANSFORM_PARENT;
+ parent = parent->parent;
+ }
+ }
+ }
+ /* Mark all children. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ /* 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 && (BASE_EDITABLE(v3d, base))) {
+ mark_children(base->object);
+ }
+ }
+ }
+ /* Flush changed flags to all dependencies. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ Object *ob = base->object;
+ /* If base is not selected, not a parent of selection or not a child of
+ * selection and it is editable.
+ */
+ if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
+ (base->flag & BASE_SELECTED) == 0 && (BASE_EDITABLE(v3d, base))) {
+ flush_trans_object_base_deps_flag(depsgraph, ob);
+ total += 1;
+ }
+ }
+ /* Store temporary bits in base indicating that base is being modified
+ * (directly or indirectly) by transforming objects.
+ */
+ trans_object_base_deps_flag_finish(view_layer);
+ return total;
}
static void clear_trans_object_base_flags(TransInfo *t)
{
- ViewLayer *view_layer = t->view_layer;
- Base *base;
+ ViewLayer *view_layer = t->view_layer;
+ Base *base;
- for (base = view_layer->object_bases.first; base; base = base->next) {
- if (base->flag_legacy & BA_WAS_SEL) {
- base->flag |= BASE_SELECTED;
- }
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->flag_legacy & BA_WAS_SEL) {
+ base->flag |= BASE_SELECTED;
+ }
- base->flag_legacy &= ~(BA_WAS_SEL | BA_SNAP_FIX_DEPS_FIASCO | BA_TEMP_TAG | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT);
- }
+ base->flag_legacy &= ~(BA_WAS_SEL | BA_SNAP_FIX_DEPS_FIASCO | BA_TEMP_TAG |
+ BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT);
+ }
}
/* auto-keyframing feature - for objects
@@ -6084,123 +6271,131 @@ static void clear_trans_object_base_flags(TransInfo *t)
// NOTE: context may not always be available, so must check before using it as it's a luxury for a few cases
void autokeyframe_object(bContext *C, Scene *scene, ViewLayer *view_layer, Object *ob, int tmode)
{
- Main *bmain = CTX_data_main(C);
- ID *id = &ob->id;
- FCurve *fcu;
-
- // TODO: this should probably be done per channel instead...
- if (autokeyframe_cfra_can_key(scene, id)) {
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ReportList *reports = CTX_wm_reports(C);
- ToolSettings *ts = scene->toolsettings;
- 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;
-
- /* get flags used for inserting keyframes */
- flag = ANIM_get_keyframing_flags(scene, 1);
-
- /* add datasource override for the object */
- ANIM_relative_keyingset_add_source(&dsources, id, NULL, NULL);
-
- if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) {
- /* only insert into active keyingset
- * NOTE: we assume here that the active Keying Set does not need to have its iterator overridden
- */
- ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
- }
- else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) {
- AnimData *adt = ob->adt;
-
- /* only key on available channels */
- 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, depsgraph, reports, id, adt->action,
- (fcu->grp ? fcu->grp->name : NULL),
- fcu->rna_path, fcu->array_index, cfra,
- ts->keyframe_type, &nla_cache, flag);
- }
-
- BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
- }
- }
- 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_VIE3D) */
- if (tmode == TFM_TRANSLATION) {
- do_loc = true;
- }
- else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) {
- if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
- if (ob != OBACT(view_layer))
- do_loc = true;
- }
- else if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) {
- do_loc = true;
- }
-
- if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
- do_rot = true;
- }
- }
- else if (tmode == TFM_RESIZE) {
- if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
- if (ob != OBACT(view_layer))
- do_loc = true;
- }
- else if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) {
- do_loc = true;
- }
-
- if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
- do_scale = true;
- }
- }
-
- /* insert keyframes for the affected sets of channels using the builtin KeyingSets found */
- 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);
- }
+ Main *bmain = CTX_data_main(C);
+ ID *id = &ob->id;
+ FCurve *fcu;
+
+ // TODO: this should probably be done per channel instead...
+ if (autokeyframe_cfra_can_key(scene, id)) {
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ReportList *reports = CTX_wm_reports(C);
+ ToolSettings *ts = scene->toolsettings;
+ 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;
+
+ /* get flags used for inserting keyframes */
+ flag = ANIM_get_keyframing_flags(scene, 1);
+
+ /* add datasource override for the object */
+ ANIM_relative_keyingset_add_source(&dsources, id, NULL, NULL);
+
+ if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) {
+ /* only insert into active keyingset
+ * NOTE: we assume here that the active Keying Set does not need to have its iterator overridden
+ */
+ ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+ else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) {
+ AnimData *adt = ob->adt;
+
+ /* only key on available channels */
+ 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,
+ depsgraph,
+ reports,
+ id,
+ adt->action,
+ (fcu->grp ? fcu->grp->name : NULL),
+ fcu->rna_path,
+ fcu->array_index,
+ cfra,
+ ts->keyframe_type,
+ &nla_cache,
+ flag);
+ }
+
+ BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
+ }
+ }
+ 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_VIE3D) */
+ if (tmode == TFM_TRANSLATION) {
+ do_loc = true;
+ }
+ else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) {
+ if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
+ if (ob != OBACT(view_layer))
+ do_loc = true;
+ }
+ else if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) {
+ do_loc = true;
+ }
+
+ if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
+ do_rot = true;
+ }
+ }
+ else if (tmode == TFM_RESIZE) {
+ if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
+ if (ob != OBACT(view_layer))
+ do_loc = true;
+ }
+ else if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) {
+ do_loc = true;
+ }
+
+ if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
+ do_scale = true;
+ }
+ }
+
+ /* insert keyframes for the affected sets of channels using the builtin KeyingSets found */
+ 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);
+ }
}
/* 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_object(Scene *scene, Object *ob)
{
- /* XXX: there's potential here for problems with unkeyed rotations/scale,
- * but for now (until proper data-locality for baking operations),
- * this should be a better fix for T24451 and T37755
- */
+ /* XXX: there's potential here for problems with unkeyed rotations/scale,
+ * but for now (until proper data-locality for baking operations),
+ * this should be a better fix for T24451 and T37755
+ */
- if (autokeyframe_cfra_can_key(scene, &ob->id)) {
- return (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
- }
+ if (autokeyframe_cfra_can_key(scene, &ob->id)) {
+ return (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
+ }
- return false;
+ return false;
}
/* auto-keyframing feature - for poses/pose-channels
@@ -6210,286 +6405,296 @@ bool motionpath_need_update_object(Scene *scene, Object *ob)
// NOTE: context may not always be available, so must check before using it as it's a luxury for a few cases
void autokeyframe_pose(bContext *C, Scene *scene, Object *ob, int tmode, short targetless_ik)
{
- Main *bmain = CTX_data_main(C);
- ID *id = &ob->id;
- AnimData *adt = ob->adt;
- bAction *act = (adt) ? adt->action : NULL;
- bPose *pose = ob->pose;
- bPoseChannel *pchan;
- FCurve *fcu;
-
- // TODO: this should probably be done per channel instead...
- if (autokeyframe_cfra_can_key(scene, id)) {
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- 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 (targetless_ik)
- flag |= INSERTKEY_MATRIX;
-
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->flag & BONE_TRANSFORM) {
- 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, depsgraph, 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;
-
- /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */
- 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;
- }
-
- 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;
- }
-
- 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);
- }
- 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;
- }
- }
- }
+ Main *bmain = CTX_data_main(C);
+ ID *id = &ob->id;
+ AnimData *adt = ob->adt;
+ bAction *act = (adt) ? adt->action : NULL;
+ bPose *pose = ob->pose;
+ bPoseChannel *pchan;
+ FCurve *fcu;
+
+ // TODO: this should probably be done per channel instead...
+ if (autokeyframe_cfra_can_key(scene, id)) {
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ 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 (targetless_ik)
+ flag |= INSERTKEY_MATRIX;
+
+ for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->bone->flag & BONE_TRANSFORM) {
+ 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,
+ depsgraph,
+ 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;
+
+ /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */
+ 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;
+ }
+
+ 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;
+ }
+
+ 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);
+ }
+ 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;
+ }
+ }
+ }
}
/* 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)
{
- if (autokeyframe_cfra_can_key(scene, &ob->id)) {
- return (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
- }
+ if (autokeyframe_cfra_can_key(scene, &ob->id)) {
+ return (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
+ }
- return false;
+ return false;
}
static void special_aftertrans_update__movieclip(bContext *C, TransInfo *t)
{
- SpaceClip *sc = t->sa->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)
- {
- bool do_update = false;
- if (plane_track->flag & PLANE_TRACK_HIDDEN) {
- continue;
- }
- do_update |= PLANE_TRACK_VIEW_SELECTED(plane_track) != 0;
- if (do_update == false) {
- if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
- int i;
- for (i = 0; i < plane_track->point_tracksnr; i++) {
- MovieTrackingTrack *track = plane_track->point_tracks[i];
- if (TRACK_VIEW_SELECTED(sc, track)) {
- do_update = true;
- break;
- }
- }
- }
- }
- if (do_update) {
- BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
- }
- }
- if (t->scene->nodetree != NULL) {
- /* Tracks can be used for stabilization nodes,
- * flush update for such nodes.
- */
- nodeUpdateID(t->scene->nodetree, &clip->id);
- WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL);
- }
+ SpaceClip *sc = t->sa->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) {
+ bool do_update = false;
+ if (plane_track->flag & PLANE_TRACK_HIDDEN) {
+ continue;
+ }
+ do_update |= PLANE_TRACK_VIEW_SELECTED(plane_track) != 0;
+ if (do_update == false) {
+ if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
+ int i;
+ for (i = 0; i < plane_track->point_tracksnr; i++) {
+ MovieTrackingTrack *track = plane_track->point_tracks[i];
+ if (TRACK_VIEW_SELECTED(sc, track)) {
+ do_update = true;
+ break;
+ }
+ }
+ }
+ }
+ if (do_update) {
+ BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
+ }
+ }
+ if (t->scene->nodetree != NULL) {
+ /* Tracks can be used for stabilization nodes,
+ * flush update for such nodes.
+ */
+ nodeUpdateID(t->scene->nodetree, &clip->id);
+ WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL);
+ }
}
static void special_aftertrans_update__mask(bContext *C, TransInfo *t)
{
- Mask *mask = NULL;
-
- if (t->spacetype == SPACE_CLIP) {
- SpaceClip *sc = t->sa->spacedata.first;
- mask = ED_space_clip_get_mask(sc);
- }
- else if (t->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = t->sa->spacedata.first;
- mask = ED_space_image_get_mask(sima);
- }
- else {
- BLI_assert(0);
- }
-
- if (t->scene->nodetree) {
- /* tracks can be used for stabilization nodes,
- * flush update for such nodes */
- //if (nodeUpdateID(t->scene->nodetree, &mask->id))
- {
- WM_event_add_notifier(C, NC_MASK | ND_DATA, &mask->id);
- }
- }
-
- /* TODO - dont key all masks... */
- if (IS_AUTOKEY_ON(t->scene)) {
- Scene *scene = t->scene;
-
- ED_mask_layer_shape_auto_key_select(mask, CFRA);
- }
+ Mask *mask = NULL;
+
+ if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *sc = t->sa->spacedata.first;
+ mask = ED_space_clip_get_mask(sc);
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = t->sa->spacedata.first;
+ mask = ED_space_image_get_mask(sima);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ if (t->scene->nodetree) {
+ /* tracks can be used for stabilization nodes,
+ * flush update for such nodes */
+ //if (nodeUpdateID(t->scene->nodetree, &mask->id))
+ {
+ WM_event_add_notifier(C, NC_MASK | ND_DATA, &mask->id);
+ }
+ }
+
+ /* TODO - dont key all masks... */
+ if (IS_AUTOKEY_ON(t->scene)) {
+ Scene *scene = t->scene;
+
+ ED_mask_layer_shape_auto_key_select(mask, CFRA);
+ }
}
static void special_aftertrans_update__node(bContext *C, TransInfo *t)
{
- Main *bmain = CTX_data_main(C);
- const bool canceled = (t->state == TRANS_CANCEL);
+ Main *bmain = CTX_data_main(C);
+ const bool canceled = (t->state == TRANS_CANCEL);
- if (canceled && t->remove_on_cancel) {
- /* remove selected nodes on cancel */
- SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
- bNodeTree *ntree = snode->edittree;
- if (ntree) {
- bNode *node, *node_next;
- for (node = ntree->nodes.first; node; node = node_next) {
- node_next = node->next;
- if (node->flag & NODE_SELECT)
- nodeRemoveNode(bmain, ntree, node, true);
- }
- }
- }
+ if (canceled && t->remove_on_cancel) {
+ /* remove selected nodes on cancel */
+ SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
+ bNodeTree *ntree = snode->edittree;
+ if (ntree) {
+ bNode *node, *node_next;
+ for (node = ntree->nodes.first; node; node = node_next) {
+ node_next = node->next;
+ if (node->flag & NODE_SELECT)
+ nodeRemoveNode(bmain, ntree, node, true);
+ }
+ }
+ }
}
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))
- {
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ /* so automerge supports mirror */
+ if ((t->scene->toolsettings->automerge) && ((t->flag & T_EDIT) && t->obedit_type == OB_MESH)) {
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
- char hflag;
- bool has_face_sel = (bm->totfacesel != 0);
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+ char hflag;
+ bool has_face_sel = (bm->totfacesel != 0);
- if (tc->mirror.axis_flag) {
- TransData *td;
- int i;
+ if (tc->mirror.axis_flag) {
+ TransData *td;
+ int i;
- /* Rather then adjusting the selection (which the user would notice)
- * tag all mirrored verts, then auto-merge those. */
- BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
+ /* Rather then adjusting the selection (which the user would notice)
+ * tag all mirrored verts, then auto-merge those. */
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
- for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
- if (td->extra) {
- BM_elem_flag_enable((BMVert *)td->extra, BM_ELEM_TAG);
- }
- }
+ for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
+ if (td->extra) {
+ BM_elem_flag_enable((BMVert *)td->extra, BM_ELEM_TAG);
+ }
+ }
- hflag = BM_ELEM_SELECT | BM_ELEM_TAG;
- }
- else {
- hflag = BM_ELEM_SELECT;
- }
+ hflag = BM_ELEM_SELECT | BM_ELEM_TAG;
+ }
+ else {
+ hflag = BM_ELEM_SELECT;
+ }
- EDBM_automerge(t->scene, tc->obedit, true, hflag);
+ EDBM_automerge(t->scene, tc->obedit, true, hflag);
- /* Special case, this is needed or faces won't re-select.
- * Flush selected edges to faces. */
- if (has_face_sel && (em->selectmode == SCE_SELECT_FACE)) {
- EDBM_selectmode_flush_ex(em, SCE_SELECT_EDGE);
- }
- }
- }
+ /* Special case, this is needed or faces won't re-select.
+ * Flush selected edges to faces. */
+ if (has_face_sel && (em->selectmode == SCE_SELECT_FACE)) {
+ EDBM_selectmode_flush_ex(em, SCE_SELECT_EDGE);
+ }
+ }
+ }
}
/* inserting keys, pointcache, redraw events... */
@@ -6499,704 +6704,704 @@ static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
* */
void special_aftertrans_update(bContext *C, TransInfo *t)
{
- Main *bmain = CTX_data_main(t->context);
- BLI_assert(bmain == CTX_data_main(C));
-
- Object *ob;
-// short redrawipo=0, resetslowpar=1;
- const bool canceled = (t->state == TRANS_CANCEL);
- const bool duplicate = (t->mode == TFM_TIME_DUPLICATE);
-
- /* early out when nothing happened */
- if (t->data_len_all == 0 || t->mode == TFM_DUMMY) {
- return;
- }
-
- if (t->spacetype == SPACE_VIEW3D) {
- if (t->flag & T_EDIT) {
- /* Special Exception:
- * We don't normally access 't->custom.mode' here, but its needed in this case. */
-
- if (canceled == 0) {
- /* we need to delete the temporary faces before automerging */
- if (t->mode == TFM_EDGE_SLIDE) {
- /* handle multires re-projection, done
- * on transform completion since it's
- * really slow -joeedh */
- projectEdgeSlideData(t, true);
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- EdgeSlideData *sld = tc->custom.mode.data;
-
- /* Free temporary faces to avoid auto-merging and deleting
- * during cleanup - psy-fi. */
- freeEdgeSlideTempFaces(sld);
- }
- }
- else if (t->mode == TFM_VERT_SLIDE) {
- /* as above */
- projectVertSlideData(t, true);
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- VertSlideData *sld = tc->custom.mode.data;
- freeVertSlideTempFaces(sld);
- }
- }
-
- if (t->obedit_type == OB_MESH) {
- special_aftertrans_update__mesh(C, 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);
- }
- }
- }
- }
-
-
- if (t->options & CTX_GPENCIL_STROKES) {
- /* pass */
- }
- else if (t->spacetype == SPACE_SEQ) {
- /* freeSeqData in transform_conversions.c does this
- * keep here so the else at the end wont run... */
-
- SpaceSeq *sseq = (SpaceSeq *)t->sa->spacedata.first;
-
- /* marker transform, not especially nice but we may want to move markers
- * at the same time as keyframes in the dope sheet. */
- if ((sseq->flag & SEQ_MARKER_TRANS) && (canceled == 0)) {
- /* cant use TFM_TIME_EXTEND
- * for some reason EXTEND is changed into TRANSLATE, so use frame_side instead */
-
- if (t->mode == TFM_SEQ_SLIDE) {
- if (t->frame_side == 'B')
- ED_markers_post_apply_transform(&t->scene->markers, t->scene, TFM_TIME_TRANSLATE, t->values[0], t->frame_side);
- }
- else if (ELEM(t->frame_side, 'L', 'R')) {
- ED_markers_post_apply_transform(&t->scene->markers, t->scene, TFM_TIME_EXTEND, t->values[0], t->frame_side);
- }
- }
- }
- else if (t->spacetype == SPACE_IMAGE) {
- if (t->options & CTX_MASK) {
- special_aftertrans_update__mask(C, t);
- }
- }
- else if (t->spacetype == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)t->sa->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);
- }
-
- /* clear link line */
- ED_node_link_intersect_test(t->sa, 0);
- }
- else if (t->spacetype == SPACE_CLIP) {
- if (t->options & CTX_MOVIECLIP) {
- special_aftertrans_update__movieclip(C, t);
- }
- else if (t->options & CTX_MASK) {
- special_aftertrans_update__mask(C, t);
- }
- }
- else if (t->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
- bAnimContext ac;
-
- /* initialize relevant anim-context 'context' data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return;
-
- ob = ac.obact;
-
- if (ELEM(ac.datatype, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY, ANIMCONT_TIMELINE)) {
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
-
- /* get channels to work on */
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* these should all be F-Curves */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
- FCurve *fcu = (FCurve *)ale->key_data;
-
- /* 3 cases here for curve cleanups:
- * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
- * 2) canceled == 0 -> user confirmed the transform,
- * so duplicates should be removed
- * 3) canceled + duplicate -> user canceled the transform,
- * but we made duplicates, so get rid of these
- */
- if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 &&
- ((canceled == 0) || (duplicate)) )
- {
- if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
- posttrans_fcurve_clean(fcu, false); /* only use handles in graph editor */
- ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
- }
- else
- posttrans_fcurve_clean(fcu, false); /* only use handles in graph editor */
- }
- }
-
- /* free temp memory */
- ANIM_animdata_freelist(&anim_data);
- }
- else if (ac.datatype == ANIMCONT_ACTION) { // TODO: just integrate into the above...
- /* Depending on the lock status, draw necessary views */
- // fixme... some of this stuff is not good
- if (ob) {
- if (ob->pose || BKE_key_from_object(ob))
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- else
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
-
- /* 3 cases here for curve cleanups:
- * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
- * 2) canceled == 0 -> user confirmed the transform,
- * so duplicates should be removed.
- * 3) canceled + duplicate -> user canceled the transform,
- * but we made duplicates, so get rid of these.
- */
- if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 &&
- ((canceled == 0) || (duplicate)))
- {
- posttrans_action_clean(&ac, (bAction *)ac.data);
- }
- }
- else if (ac.datatype == ANIMCONT_GPENCIL) {
- /* remove duplicate frames and also make sure points are in order! */
- /* 3 cases here for curve cleanups:
- * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
- * 2) canceled == 0 -> user confirmed the transform,
- * so duplicates should be removed
- * 3) canceled + duplicate -> user canceled the transform,
- * but we made duplicates, so get rid of these
- */
- if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 &&
- ((canceled == 0) || (duplicate)))
- {
- bGPdata *gpd;
-
- // 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);
- }
- }
- }
- else if (ac.datatype == ANIMCONT_MASK) {
- /* remove duplicate frames and also make sure points are in order! */
- /* 3 cases here for curve cleanups:
- * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
- * 2) canceled == 0 -> user confirmed the transform, so duplicates should be removed
- * 3) canceled + duplicate -> user canceled the transform, but we made duplicates, so get rid of these
- */
- if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 &&
- ((canceled == 0) || (duplicate)))
- {
- Mask *mask;
-
- // 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);
- }
- }
- }
-
- /* marker transform, not especially nice but we may want to move markers
- * at the same time as keyframes in the dope sheet.
- */
- if ((saction->flag & SACTION_MARKERS_MOVE) && (canceled == 0)) {
- if (t->mode == TFM_TIME_TRANSLATE) {
+ Main *bmain = CTX_data_main(t->context);
+ BLI_assert(bmain == CTX_data_main(C));
+
+ Object *ob;
+ // short redrawipo=0, resetslowpar=1;
+ const bool canceled = (t->state == TRANS_CANCEL);
+ const bool duplicate = (t->mode == TFM_TIME_DUPLICATE);
+
+ /* early out when nothing happened */
+ if (t->data_len_all == 0 || t->mode == TFM_DUMMY) {
+ return;
+ }
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ if (t->flag & T_EDIT) {
+ /* Special Exception:
+ * We don't normally access 't->custom.mode' here, but its needed in this case. */
+
+ if (canceled == 0) {
+ /* we need to delete the temporary faces before automerging */
+ if (t->mode == TFM_EDGE_SLIDE) {
+ /* handle multires re-projection, done
+ * on transform completion since it's
+ * really slow -joeedh */
+ projectEdgeSlideData(t, true);
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ EdgeSlideData *sld = tc->custom.mode.data;
+
+ /* Free temporary faces to avoid auto-merging and deleting
+ * during cleanup - psy-fi. */
+ freeEdgeSlideTempFaces(sld);
+ }
+ }
+ else if (t->mode == TFM_VERT_SLIDE) {
+ /* as above */
+ projectVertSlideData(t, true);
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ VertSlideData *sld = tc->custom.mode.data;
+ freeVertSlideTempFaces(sld);
+ }
+ }
+
+ if (t->obedit_type == OB_MESH) {
+ special_aftertrans_update__mesh(C, 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);
+ }
+ }
+ }
+ }
+
+ if (t->options & CTX_GPENCIL_STROKES) {
+ /* pass */
+ }
+ else if (t->spacetype == SPACE_SEQ) {
+ /* freeSeqData in transform_conversions.c does this
+ * keep here so the else at the end wont run... */
+
+ SpaceSeq *sseq = (SpaceSeq *)t->sa->spacedata.first;
+
+ /* marker transform, not especially nice but we may want to move markers
+ * at the same time as keyframes in the dope sheet. */
+ if ((sseq->flag & SEQ_MARKER_TRANS) && (canceled == 0)) {
+ /* cant use TFM_TIME_EXTEND
+ * for some reason EXTEND is changed into TRANSLATE, so use frame_side instead */
+
+ if (t->mode == TFM_SEQ_SLIDE) {
+ if (t->frame_side == 'B')
+ ED_markers_post_apply_transform(
+ &t->scene->markers, t->scene, TFM_TIME_TRANSLATE, t->values[0], t->frame_side);
+ }
+ else if (ELEM(t->frame_side, 'L', 'R')) {
+ ED_markers_post_apply_transform(
+ &t->scene->markers, t->scene, TFM_TIME_EXTEND, t->values[0], t->frame_side);
+ }
+ }
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ if (t->options & CTX_MASK) {
+ special_aftertrans_update__mask(C, t);
+ }
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)t->sa->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);
+ }
+
+ /* clear link line */
+ ED_node_link_intersect_test(t->sa, 0);
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ if (t->options & CTX_MOVIECLIP) {
+ special_aftertrans_update__movieclip(C, t);
+ }
+ else if (t->options & CTX_MASK) {
+ special_aftertrans_update__mask(C, t);
+ }
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
+ bAnimContext ac;
+
+ /* initialize relevant anim-context 'context' data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return;
+
+ ob = ac.obact;
+
+ if (ELEM(ac.datatype, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY, ANIMCONT_TIMELINE)) {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
+
+ /* get channels to work on */
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* these should all be F-Curves */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
+ FCurve *fcu = (FCurve *)ale->key_data;
+
+ /* 3 cases here for curve cleanups:
+ * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
+ * 2) canceled == 0 -> user confirmed the transform,
+ * so duplicates should be removed
+ * 3) canceled + duplicate -> user canceled the transform,
+ * but we made duplicates, so get rid of these
+ */
+ if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
+ posttrans_fcurve_clean(fcu, false); /* only use handles in graph editor */
+ ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
+ }
+ else
+ posttrans_fcurve_clean(fcu, false); /* only use handles in graph editor */
+ }
+ }
+
+ /* free temp memory */
+ ANIM_animdata_freelist(&anim_data);
+ }
+ else if (ac.datatype == ANIMCONT_ACTION) { // TODO: just integrate into the above...
+ /* Depending on the lock status, draw necessary views */
+ // fixme... some of this stuff is not good
+ if (ob) {
+ if (ob->pose || BKE_key_from_object(ob))
+ DEG_id_tag_update(&ob->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ else
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+
+ /* 3 cases here for curve cleanups:
+ * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
+ * 2) canceled == 0 -> user confirmed the transform,
+ * so duplicates should be removed.
+ * 3) canceled + duplicate -> user canceled the transform,
+ * but we made duplicates, so get rid of these.
+ */
+ if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
+ posttrans_action_clean(&ac, (bAction *)ac.data);
+ }
+ }
+ else if (ac.datatype == ANIMCONT_GPENCIL) {
+ /* remove duplicate frames and also make sure points are in order! */
+ /* 3 cases here for curve cleanups:
+ * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
+ * 2) canceled == 0 -> user confirmed the transform,
+ * so duplicates should be removed
+ * 3) canceled + duplicate -> user canceled the transform,
+ * but we made duplicates, so get rid of these
+ */
+ if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
+ bGPdata *gpd;
+
+ // 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);
+ }
+ }
+ }
+ else if (ac.datatype == ANIMCONT_MASK) {
+ /* remove duplicate frames and also make sure points are in order! */
+ /* 3 cases here for curve cleanups:
+ * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
+ * 2) canceled == 0 -> user confirmed the transform, so duplicates should be removed
+ * 3) canceled + duplicate -> user canceled the transform, but we made duplicates, so get rid of these
+ */
+ if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
+ Mask *mask;
+
+ // 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);
+ }
+ }
+ }
+
+ /* marker transform, not especially nice but we may want to move markers
+ * at the same time as keyframes in the dope sheet.
+ */
+ if ((saction->flag & SACTION_MARKERS_MOVE) && (canceled == 0)) {
+ if (t->mode == TFM_TIME_TRANSLATE) {
#if 0
- if (ELEM(t->frame_side, 'L', 'R')) { /* TFM_TIME_EXTEND */
- /* same as below */
- ED_markers_post_apply_transform(ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side);
- }
- else /* TFM_TIME_TRANSLATE */
+ if (ELEM(t->frame_side, 'L', 'R')) { /* TFM_TIME_EXTEND */
+ /* same as below */
+ ED_markers_post_apply_transform(ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side);
+ }
+ else /* TFM_TIME_TRANSLATE */
#endif
- {
- ED_markers_post_apply_transform(ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side);
- }
- }
- else if (t->mode == TFM_TIME_SCALE) {
- ED_markers_post_apply_transform(ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side);
- }
- }
-
- /* make sure all F-Curves are set correctly */
- if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
- ANIM_editkeyframes_refresh(&ac);
-
- /* clear flag that was set for time-slide drawing */
- saction->flag &= ~SACTION_MOVING;
- }
- else if (t->spacetype == SPACE_GRAPH) {
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
- bAnimContext ac;
- const bool use_handle = (sipo->flag & SIPO_NOHANDLES) == 0;
-
- /* initialize relevant anim-context 'context' data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return;
-
- if (ac.datatype) {
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
-
- /* get channels to work on */
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
- FCurve *fcu = (FCurve *)ale->key_data;
-
- /* 3 cases here for curve cleanups:
- * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
- * 2) canceled == 0 -> user confirmed the transform,
- * so duplicates should be removed
- * 3) canceled + duplicate -> user canceled the transform,
- * but we made duplicates, so get rid of these
- */
- if ((sipo->flag & SIPO_NOTRANSKEYCULL) == 0 &&
- ((canceled == 0) || (duplicate)))
- {
- if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
- posttrans_fcurve_clean(fcu, use_handle);
- ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
- }
- else
- posttrans_fcurve_clean(fcu, use_handle);
- }
- }
-
- /* free temp memory */
- ANIM_animdata_freelist(&anim_data);
- }
-
- /* Make sure all F-Curves are set correctly, but not if transform was
- * canceled, since then curves were already restored to initial state.
- * Note: if the refresh is really needed after cancel then some way
- * has to be added to not update handle types (see bug 22289).
- */
- if (!canceled)
- ANIM_editkeyframes_refresh(&ac);
- }
- else if (t->spacetype == SPACE_NLA) {
- bAnimContext ac;
-
- /* initialize relevant anim-context 'context' data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return;
-
- if (ac.datatype) {
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT);
-
- /* get channels to work on */
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
-
- /* make sure strips are in order again */
- BKE_nlatrack_sort_strips(nlt);
-
- /* remove the temp metas */
- BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
- }
-
- /* free temp memory */
- ANIM_animdata_freelist(&anim_data);
-
- /* perform after-transfrom validation */
- ED_nla_postop_refresh(&ac);
- }
- }
- 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');
- /* TODO(campbell): xform: We need support for many mirror objects at once! */
- break;
- }
- }
- }
- else if (t->flag & T_POSE && (t->mode == TFM_BONESIZE)) {
- /* Handle the exception where for TFM_BONESIZE in edit mode we pretend to be
- * in pose mode (to use bone orientation matrix),
- * in that case we don't do operations like autokeyframing. */
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- ob = tc->poseobj;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- }
- else if (t->flag & T_POSE) {
- GSet *motionpath_updates = BLI_gset_ptr_new("motionpath updates");
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
- bArmature *arm;
- bPoseChannel *pchan;
- short targetless_ik = 0;
-
- ob = tc->poseobj;
- arm = ob->data;
-
- if ((t->flag & T_AUTOIK) && (t->options & CTX_AUTOCONFIRM)) {
- /* when running transform non-interactively (operator exec),
- * we need to update the pose otherwise no updates get called during
- * transform and the auto-ik is not applied. see [#26164] */
- struct Object *pose_ob = tc->poseobj;
- BKE_pose_where_is(t->depsgraph, t->scene, pose_ob);
- }
-
- /* 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);
- }
-
- /* if target-less IK grabbing, we calculate the pchan transforms and clear flag */
- if (!canceled && t->mode == TFM_TRANSLATION)
- targetless_ik = apply_targetless_ik(ob);
- else {
- /* not forget to clear the auto flag */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- bKinematicConstraint *data = has_targetless_ik(pchan);
- if (data) data->flag &= ~CONSTRAINT_IK_AUTO;
- }
- }
-
- if (t->mode == TFM_TRANSLATION)
- pose_grab_with_ik_clear(bmain, ob);
-
- /* automatic inserting of keys and unkeyed tagging -
- * only if transform wasn't canceled (or TFM_DUMMY) */
- if (!canceled && (t->mode != TFM_DUMMY)) {
- autokeyframe_pose(C, t->scene, ob, t->mode, targetless_ik);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- else if (arm->flag & ARM_DELAYDEFORM) {
- /* TODO(sergey): Armature is already updated by recalcData(), so we
- * might save some time by skipping re-evaluating it. But this isn't
- * possible yet within new dependency graph, and also other contexts
- * might need to update their CoW copies.
- */
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- else {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
-
- if (t->mode != TFM_DUMMY && motionpath_need_update_pose(t->scene, ob)) {
- BLI_gset_insert(motionpath_updates, ob);
- }
- }
-
- /* Update motion paths once for all transformed bones in an object. */
- GSetIterator gs_iter;
- GSET_ITER (gs_iter, motionpath_updates) {
- bool current_frame_only = canceled;
- ob = BLI_gsetIterator_getKey(&gs_iter);
- ED_pose_recalculate_paths(C, t->scene, ob, current_frame_only);
- }
- BLI_gset_free(motionpath_updates, NULL);
- }
- else if (t->options & CTX_PAINT_CURVE) {
- /* pass */
- }
- else if ((t->view_layer->basact) &&
- (ob = t->view_layer->basact->object) &&
- (ob->mode & OB_MODE_PARTICLE_EDIT) &&
- PE_get_current(t->scene, ob))
- {
- /* do nothing */
- }
- else if (t->flag & T_CURSOR) {
- /* do nothing */
- }
- else { /* Objects */
- BLI_assert(t->flag & (T_OBJECT | T_TEXTURE));
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- bool motionpath_update = false;
-
- for (int i = 0; i < tc->data_len; i++) {
- TransData *td = tc->data + i;
- ListBase pidlist;
- PTCacheID *pid;
- ob = td->ob;
-
- if (td->flag & TD_NOACTION)
- break;
-
- if (td->flag & TD_SKIP)
- continue;
-
- /* flag object caches as outdated */
- BKE_ptcache_ids_from_object(&pidlist, ob, t->scene, MAX_DUPLI_RECUR);
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->type != PTCACHE_TYPE_PARTICLES) {
- /* particles don't need reset on geometry change */
- pid->cache->flag |= PTCACHE_OUTDATED;
- }
- }
- BLI_freelistN(&pidlist);
-
- /* pointcache refresh */
- if (BKE_ptcache_object_reset(t->scene, ob, PTCACHE_RESET_OUTDATED))
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
-
- /* Needed for proper updating of "quick cached" dynamics. */
- /* Creates troubles for moving animated objects without */
- /* autokey though, probably needed is an anim sys override? */
- /* Please remove if some other solution is found. -jahka */
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
-
- /* Set autokey if necessary */
- if (!canceled) {
- autokeyframe_object(C, t->scene, t->view_layer, ob, t->mode);
- }
-
- motionpath_update |= motionpath_need_update_object(t->scene, ob);
-
- /* restore rigid body transform */
- if (ob->rigidbody_object && canceled) {
- float ctime = BKE_scene_frame_get(t->scene);
- if (BKE_rigidbody_check_sim_running(t->scene->rigidbody_world, ctime))
- BKE_rigidbody_aftertrans_update(ob, td->ext->oloc, td->ext->orot, td->ext->oquat, td->ext->orotAxis, td->ext->orotAngle);
- }
- }
-
- if (motionpath_update) {
- /* Update motion paths once for all transformed objects. */
- bool current_frame_only = canceled;
- ED_objects_recalculate_paths(C, t->scene, current_frame_only);
- }
- }
-
- clear_trans_object_base_flags(t);
+ {
+ ED_markers_post_apply_transform(
+ ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side);
+ }
+ }
+ else if (t->mode == TFM_TIME_SCALE) {
+ ED_markers_post_apply_transform(
+ ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side);
+ }
+ }
+
+ /* make sure all F-Curves are set correctly */
+ if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* clear flag that was set for time-slide drawing */
+ saction->flag &= ~SACTION_MOVING;
+ }
+ else if (t->spacetype == SPACE_GRAPH) {
+ SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ bAnimContext ac;
+ const bool use_handle = (sipo->flag & SIPO_NOHANDLES) == 0;
+
+ /* initialize relevant anim-context 'context' data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return;
+
+ if (ac.datatype) {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
+
+ /* get channels to work on */
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
+ FCurve *fcu = (FCurve *)ale->key_data;
+
+ /* 3 cases here for curve cleanups:
+ * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
+ * 2) canceled == 0 -> user confirmed the transform,
+ * so duplicates should be removed
+ * 3) canceled + duplicate -> user canceled the transform,
+ * but we made duplicates, so get rid of these
+ */
+ if ((sipo->flag & SIPO_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
+ posttrans_fcurve_clean(fcu, use_handle);
+ ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
+ }
+ else
+ posttrans_fcurve_clean(fcu, use_handle);
+ }
+ }
+
+ /* free temp memory */
+ ANIM_animdata_freelist(&anim_data);
+ }
+
+ /* Make sure all F-Curves are set correctly, but not if transform was
+ * canceled, since then curves were already restored to initial state.
+ * Note: if the refresh is really needed after cancel then some way
+ * has to be added to not update handle types (see bug 22289).
+ */
+ if (!canceled)
+ ANIM_editkeyframes_refresh(&ac);
+ }
+ else if (t->spacetype == SPACE_NLA) {
+ bAnimContext ac;
+
+ /* initialize relevant anim-context 'context' data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return;
+
+ if (ac.datatype) {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT);
+
+ /* get channels to work on */
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+
+ /* make sure strips are in order again */
+ BKE_nlatrack_sort_strips(nlt);
+
+ /* remove the temp metas */
+ BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
+ }
+
+ /* free temp memory */
+ ANIM_animdata_freelist(&anim_data);
+
+ /* perform after-transfrom validation */
+ ED_nla_postop_refresh(&ac);
+ }
+ }
+ 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');
+ /* TODO(campbell): xform: We need support for many mirror objects at once! */
+ break;
+ }
+ }
+ }
+ else if (t->flag & T_POSE && (t->mode == TFM_BONESIZE)) {
+ /* Handle the exception where for TFM_BONESIZE in edit mode we pretend to be
+ * in pose mode (to use bone orientation matrix),
+ * in that case we don't do operations like autokeyframing. */
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ ob = tc->poseobj;
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ }
+ else if (t->flag & T_POSE) {
+ GSet *motionpath_updates = BLI_gset_ptr_new("motionpath updates");
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+
+ bArmature *arm;
+ bPoseChannel *pchan;
+ short targetless_ik = 0;
+
+ ob = tc->poseobj;
+ arm = ob->data;
+
+ if ((t->flag & T_AUTOIK) && (t->options & CTX_AUTOCONFIRM)) {
+ /* when running transform non-interactively (operator exec),
+ * we need to update the pose otherwise no updates get called during
+ * transform and the auto-ik is not applied. see [#26164] */
+ struct Object *pose_ob = tc->poseobj;
+ BKE_pose_where_is(t->depsgraph, t->scene, pose_ob);
+ }
+
+ /* 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);
+ }
+
+ /* if target-less IK grabbing, we calculate the pchan transforms and clear flag */
+ if (!canceled && t->mode == TFM_TRANSLATION)
+ targetless_ik = apply_targetless_ik(ob);
+ else {
+ /* not forget to clear the auto flag */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ bKinematicConstraint *data = has_targetless_ik(pchan);
+ if (data)
+ data->flag &= ~CONSTRAINT_IK_AUTO;
+ }
+ }
+
+ if (t->mode == TFM_TRANSLATION)
+ pose_grab_with_ik_clear(bmain, ob);
+
+ /* automatic inserting of keys and unkeyed tagging -
+ * only if transform wasn't canceled (or TFM_DUMMY) */
+ if (!canceled && (t->mode != TFM_DUMMY)) {
+ autokeyframe_pose(C, t->scene, ob, t->mode, targetless_ik);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ else if (arm->flag & ARM_DELAYDEFORM) {
+ /* TODO(sergey): Armature is already updated by recalcData(), so we
+ * might save some time by skipping re-evaluating it. But this isn't
+ * possible yet within new dependency graph, and also other contexts
+ * might need to update their CoW copies.
+ */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ else {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+
+ if (t->mode != TFM_DUMMY && motionpath_need_update_pose(t->scene, ob)) {
+ BLI_gset_insert(motionpath_updates, ob);
+ }
+ }
+
+ /* Update motion paths once for all transformed bones in an object. */
+ GSetIterator gs_iter;
+ GSET_ITER (gs_iter, motionpath_updates) {
+ bool current_frame_only = canceled;
+ ob = BLI_gsetIterator_getKey(&gs_iter);
+ ED_pose_recalculate_paths(C, t->scene, ob, current_frame_only);
+ }
+ BLI_gset_free(motionpath_updates, NULL);
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ /* pass */
+ }
+ else if ((t->view_layer->basact) && (ob = t->view_layer->basact->object) &&
+ (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_get_current(t->scene, ob)) {
+ /* do nothing */
+ }
+ else if (t->flag & T_CURSOR) {
+ /* do nothing */
+ }
+ else { /* Objects */
+ BLI_assert(t->flag & (T_OBJECT | T_TEXTURE));
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ bool motionpath_update = false;
+
+ for (int i = 0; i < tc->data_len; i++) {
+ TransData *td = tc->data + i;
+ ListBase pidlist;
+ PTCacheID *pid;
+ ob = td->ob;
+
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ /* flag object caches as outdated */
+ BKE_ptcache_ids_from_object(&pidlist, ob, t->scene, MAX_DUPLI_RECUR);
+ for (pid = pidlist.first; pid; pid = pid->next) {
+ if (pid->type != PTCACHE_TYPE_PARTICLES) {
+ /* particles don't need reset on geometry change */
+ pid->cache->flag |= PTCACHE_OUTDATED;
+ }
+ }
+ BLI_freelistN(&pidlist);
+
+ /* pointcache refresh */
+ if (BKE_ptcache_object_reset(t->scene, ob, PTCACHE_RESET_OUTDATED))
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+
+ /* Needed for proper updating of "quick cached" dynamics. */
+ /* Creates troubles for moving animated objects without */
+ /* autokey though, probably needed is an anim sys override? */
+ /* Please remove if some other solution is found. -jahka */
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+
+ /* Set autokey if necessary */
+ if (!canceled) {
+ autokeyframe_object(C, t->scene, t->view_layer, ob, t->mode);
+ }
+
+ motionpath_update |= motionpath_need_update_object(t->scene, ob);
+
+ /* restore rigid body transform */
+ if (ob->rigidbody_object && canceled) {
+ float ctime = BKE_scene_frame_get(t->scene);
+ if (BKE_rigidbody_check_sim_running(t->scene->rigidbody_world, ctime))
+ BKE_rigidbody_aftertrans_update(ob,
+ td->ext->oloc,
+ td->ext->orot,
+ td->ext->oquat,
+ td->ext->orotAxis,
+ td->ext->orotAngle);
+ }
+ }
+
+ if (motionpath_update) {
+ /* Update motion paths once for all transformed objects. */
+ bool current_frame_only = canceled;
+ ED_objects_recalculate_paths(C, t->scene, current_frame_only);
+ }
+ }
+
+ clear_trans_object_base_flags(t);
}
int special_transform_moving(TransInfo *t)
{
- if (t->spacetype == SPACE_SEQ) {
- return G_TRANSFORM_SEQ;
- }
- else if (t->spacetype == SPACE_GRAPH) {
- return G_TRANSFORM_FCURVES;
- }
- else if ((t->flag & T_EDIT) || (t->flag & T_POSE)) {
- return G_TRANSFORM_EDIT;
- }
- else if (t->flag & (T_OBJECT | T_TEXTURE)) {
- return G_TRANSFORM_OBJ;
- }
+ if (t->spacetype == SPACE_SEQ) {
+ return G_TRANSFORM_SEQ;
+ }
+ else if (t->spacetype == SPACE_GRAPH) {
+ return G_TRANSFORM_FCURVES;
+ }
+ else if ((t->flag & T_EDIT) || (t->flag & T_POSE)) {
+ return G_TRANSFORM_EDIT;
+ }
+ else if (t->flag & (T_OBJECT | T_TEXTURE)) {
+ return G_TRANSFORM_OBJ;
+ }
- return 0;
+ return 0;
}
static void createTransObject(bContext *C, TransInfo *t)
{
- TransData *td = NULL;
- TransDataExtension *tx;
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
-
- set_trans_object_base_flags(t);
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* count */
- tc->data_len = CTX_DATA_COUNT(C, selected_bases);
-
- if (!tc->data_len) {
- /* clear here, main transform function escapes too */
- clear_trans_object_base_flags(t);
- return;
- }
-
- if (is_prop_edit) {
- tc->data_len += count_proportional_objects(t);
- }
-
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransOb");
- tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), "TransObExtension");
-
- CTX_DATA_BEGIN(C, Base *, base, selected_bases)
- {
- Object *ob = base->object;
-
- td->flag = TD_SELECTED;
- td->protectflag = ob->protectflag;
- td->ext = tx;
- td->ext->rotOrder = ob->rotmode;
-
- if (base->flag & BA_TRANSFORM_CHILD) {
- td->flag |= TD_NOCENTER;
- td->flag |= TD_NO_LOC;
- }
-
- /* select linked objects, but skip them later */
- if (ID_IS_LINKED(ob)) {
- td->flag |= TD_SKIP;
- }
-
- ObjectToTransData(t, td, ob);
- td->val = NULL;
- td++;
- tx++;
- }
- CTX_DATA_END;
-
- if (is_prop_edit) {
- ViewLayer *view_layer = t->view_layer;
- View3D *v3d = t->view;
- Base *base;
-
- for (base = view_layer->object_bases.first; base; base = base->next) {
- Object *ob = base->object;
-
- /* if base is not selected, not a parent of selection
- * or not a child of selection and it is editable */
- if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
- (base->flag & BASE_SELECTED) == 0 &&
- BASE_EDITABLE(v3d, base))
- {
- td->protectflag = ob->protectflag;
- td->ext = tx;
- td->ext->rotOrder = ob->rotmode;
-
- ObjectToTransData(t, td, ob);
- td->val = NULL;
- td++;
- tx++;
- }
- }
- }
+ TransData *td = NULL;
+ TransDataExtension *tx;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+
+ set_trans_object_base_flags(t);
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* count */
+ tc->data_len = CTX_DATA_COUNT(C, selected_bases);
+
+ if (!tc->data_len) {
+ /* clear here, main transform function escapes too */
+ clear_trans_object_base_flags(t);
+ return;
+ }
+
+ if (is_prop_edit) {
+ tc->data_len += count_proportional_objects(t);
+ }
+
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransOb");
+ tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), "TransObExtension");
+
+ CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
+ Object *ob = base->object;
+
+ td->flag = TD_SELECTED;
+ td->protectflag = ob->protectflag;
+ td->ext = tx;
+ td->ext->rotOrder = ob->rotmode;
+
+ if (base->flag & BA_TRANSFORM_CHILD) {
+ td->flag |= TD_NOCENTER;
+ td->flag |= TD_NO_LOC;
+ }
+
+ /* select linked objects, but skip them later */
+ if (ID_IS_LINKED(ob)) {
+ td->flag |= TD_SKIP;
+ }
+
+ ObjectToTransData(t, td, ob);
+ td->val = NULL;
+ td++;
+ tx++;
+ }
+ CTX_DATA_END;
+
+ if (is_prop_edit) {
+ ViewLayer *view_layer = t->view_layer;
+ View3D *v3d = t->view;
+ Base *base;
+
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ Object *ob = base->object;
+
+ /* if base is not selected, not a parent of selection
+ * or not a child of selection and it is editable */
+ if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
+ (base->flag & BASE_SELECTED) == 0 && BASE_EDITABLE(v3d, base)) {
+ td->protectflag = ob->protectflag;
+ td->ext = tx;
+ td->ext->rotOrder = ob->rotmode;
+
+ ObjectToTransData(t, td, ob);
+ td->val = NULL;
+ td++;
+ tx++;
+ }
+ }
+ }
}
/* transcribe given node into TransData2D for Transforming */
static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node, const float dpi_fac)
{
- float locx, locy;
+ float locx, locy;
- /* account for parents (nested nodes) */
- if (node->parent) {
- nodeToView(node->parent, node->locx, node->locy, &locx, &locy);
- }
- else {
- locx = node->locx;
- locy = node->locy;
- }
+ /* account for parents (nested nodes) */
+ if (node->parent) {
+ nodeToView(node->parent, node->locx, node->locy, &locx, &locy);
+ }
+ else {
+ locx = node->locx;
+ locy = node->locy;
+ }
- /* use top-left corner as the transform origin for nodes */
- /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */
+ /* use top-left corner as the transform origin for nodes */
+ /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */
#ifdef USE_NODE_CENTER
- td2d->loc[0] = (locx * dpi_fac) + (BLI_rctf_size_x(&node->totr) * +0.5f);
- td2d->loc[1] = (locy * dpi_fac) + (BLI_rctf_size_y(&node->totr) * -0.5f);
+ td2d->loc[0] = (locx * dpi_fac) + (BLI_rctf_size_x(&node->totr) * +0.5f);
+ td2d->loc[1] = (locy * dpi_fac) + (BLI_rctf_size_y(&node->totr) * -0.5f);
#else
- td2d->loc[0] = locx * dpi_fac;
- td2d->loc[1] = locy * dpi_fac;
+ td2d->loc[0] = locx * dpi_fac;
+ td2d->loc[1] = locy * dpi_fac;
#endif
- td2d->loc[2] = 0.0f;
- td2d->loc2d = td2d->loc; /* current location */
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = td2d->loc; /* current location */
- td->flag = 0;
+ td->flag = 0;
- td->loc = td2d->loc;
- copy_v3_v3(td->iloc, td->loc);
- /* use node center instead of origin (top-left corner) */
- td->center[0] = td2d->loc[0];
- td->center[1] = td2d->loc[1];
- td->center[2] = 0.0f;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->iloc, td->loc);
+ /* use node center instead of origin (top-left corner) */
+ td->center[0] = td2d->loc[0];
+ td->center[1] = td2d->loc[1];
+ td->center[2] = 0.0f;
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
- td->ext = NULL; td->val = NULL;
+ td->ext = NULL;
+ td->val = NULL;
- td->flag |= TD_SELECTED;
- td->dist = 0.0;
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
- unit_m3(td->mtx);
- unit_m3(td->smtx);
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
- td->extra = node;
+ td->extra = node;
}
static bool is_node_parent_select(bNode *node)
{
- while ((node = node->parent)) {
- if (node->flag & NODE_TRANSFORM) {
- return true;
- }
- }
- return false;
+ while ((node = node->parent)) {
+ if (node->flag & NODE_TRANSFORM) {
+ return true;
+ }
+ }
+ return false;
}
static void createTransNodeData(bContext *UNUSED(C), TransInfo *t)
{
- const float dpi_fac = UI_DPI_FAC;
- TransData *td;
- TransData2D *td2d;
- SpaceNode *snode = t->sa->spacedata.first;
- bNode *node;
+ const float dpi_fac = UI_DPI_FAC;
+ TransData *td;
+ TransData2D *td2d;
+ SpaceNode *snode = t->sa->spacedata.first;
+ bNode *node;
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- tc->data_len = 0;
+ tc->data_len = 0;
- if (!snode->edittree) {
- return;
- }
+ if (!snode->edittree) {
+ return;
+ }
- /* nodes dont support PET and probably never will */
- t->flag &= ~T_PROP_EDIT_ALL;
+ /* nodes dont support PET and probably never will */
+ t->flag &= ~T_PROP_EDIT_ALL;
- /* set transform flags on nodes */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_SELECT && is_node_parent_select(node) == false) {
- node->flag |= NODE_TRANSFORM;
- tc->data_len++;
- }
- else {
- node->flag &= ~NODE_TRANSFORM;
- }
- }
+ /* set transform flags on nodes */
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (node->flag & NODE_SELECT && is_node_parent_select(node) == false) {
+ node->flag |= NODE_TRANSFORM;
+ tc->data_len++;
+ }
+ else {
+ node->flag &= ~NODE_TRANSFORM;
+ }
+ }
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransNode TransData");
- td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransNode TransData2D");
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransNode TransData");
+ td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransNode TransData2D");
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_TRANSFORM) {
- NodeToTransData(td++, td2d++, node, dpi_fac);
- }
- }
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (node->flag & NODE_TRANSFORM) {
+ NodeToTransData(td++, td2d++, node, dpi_fac);
+ }
+ }
}
/* *** CLIP EDITOR *** */
@@ -7204,1782 +7409,1872 @@ static void createTransNodeData(bContext *UNUSED(C), TransInfo *t)
/* * motion tracking * */
enum transDataTracking_Mode {
- transDataTracking_ModeTracks = 0,
- transDataTracking_ModeCurves = 1,
- transDataTracking_ModePlaneTracks = 2,
+ transDataTracking_ModeTracks = 0,
+ transDataTracking_ModeCurves = 1,
+ transDataTracking_ModePlaneTracks = 2,
};
typedef struct TransDataTracking {
- int mode, flag;
+ int mode, flag;
- /* tracks transformation from main window */
- int area;
- const float *relative, *loc;
- float soffset[2], srelative[2];
- float offset[2];
+ /* tracks transformation from main window */
+ int area;
+ const float *relative, *loc;
+ float soffset[2], srelative[2];
+ float offset[2];
- float (*smarkers)[2];
- int markersnr;
- MovieTrackingMarker *markers;
+ float (*smarkers)[2];
+ int markersnr;
+ MovieTrackingMarker *markers;
- /* marker transformation from curves editor */
- float *prev_pos, scale;
- short coord;
+ /* marker transformation from curves editor */
+ float *prev_pos, scale;
+ short coord;
- MovieTrackingTrack *track;
- MovieTrackingPlaneTrack *plane_track;
+ MovieTrackingTrack *track;
+ MovieTrackingPlaneTrack *plane_track;
} TransDataTracking;
-static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
- MovieTrackingTrack *track, MovieTrackingMarker *marker,
- int area, float loc[2], float rel[2], const float off[2], const float aspect[2])
-{
- int anchor = area == TRACK_AREA_POINT && off;
-
- tdt->mode = transDataTracking_ModeTracks;
-
- if (anchor) {
- td2d->loc[0] = rel[0] * aspect[0]; /* hold original location */
- td2d->loc[1] = rel[1] * aspect[1];
-
- tdt->loc = loc;
- td2d->loc2d = loc; /* current location */
- }
- else {
- td2d->loc[0] = loc[0] * aspect[0]; /* hold original location */
- td2d->loc[1] = loc[1] * aspect[1];
-
- td2d->loc2d = loc; /* current location */
- }
- td2d->loc[2] = 0.0f;
-
- tdt->relative = rel;
- tdt->area = area;
-
- tdt->markersnr = track->markersnr;
- tdt->markers = track->markers;
- tdt->track = track;
-
- if (rel) {
- if (!anchor) {
- td2d->loc[0] += rel[0] * aspect[0];
- td2d->loc[1] += rel[1] * aspect[1];
- }
-
- copy_v2_v2(tdt->srelative, rel);
- }
-
- if (off)
- copy_v2_v2(tdt->soffset, off);
-
- td->flag = 0;
- td->loc = td2d->loc;
- copy_v3_v3(td->iloc, td->loc);
-
- //copy_v3_v3(td->center, td->loc);
- td->flag |= TD_INDIVIDUAL_SCALE;
- td->center[0] = marker->pos[0] * aspect[0];
- td->center[1] = marker->pos[1] * aspect[1];
-
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
-
- td->ext = NULL;
- td->val = NULL;
-
- td->flag |= TD_SELECTED;
- td->dist = 0.0;
-
- unit_m3(td->mtx);
- unit_m3(td->smtx);
-}
-
-static void trackToTransData(
- const int framenr, TransData *td, TransData2D *td2d,
- TransDataTracking *tdt, MovieTrackingTrack *track, const float aspect[2])
+static void markerToTransDataInit(TransData *td,
+ TransData2D *td2d,
+ TransDataTracking *tdt,
+ MovieTrackingTrack *track,
+ MovieTrackingMarker *marker,
+ int area,
+ float loc[2],
+ float rel[2],
+ const float off[2],
+ const float aspect[2])
{
- MovieTrackingMarker *marker = BKE_tracking_marker_ensure(track, framenr);
-
- tdt->flag = marker->flag;
- marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED);
-
- markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT,
- track->offset, marker->pos, track->offset, aspect);
-
- if (track->flag & SELECT) {
- markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT,
- marker->pos, NULL, NULL, aspect);
- }
-
- if (track->pat_flag & SELECT) {
- int a;
-
- for (a = 0; a < 4; a++) {
- markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_PAT,
- marker->pattern_corners[a], marker->pos, NULL, aspect);
- }
- }
-
- if (track->search_flag & SELECT) {
- markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_SEARCH,
- marker->search_min, marker->pos, NULL, aspect);
-
- markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_SEARCH,
- marker->search_max, marker->pos, NULL, aspect);
- }
-}
-
-static void planeMarkerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
- MovieTrackingPlaneTrack *plane_track, float corner[2],
+ int anchor = area == TRACK_AREA_POINT && off;
+
+ tdt->mode = transDataTracking_ModeTracks;
+
+ if (anchor) {
+ td2d->loc[0] = rel[0] * aspect[0]; /* hold original location */
+ td2d->loc[1] = rel[1] * aspect[1];
+
+ tdt->loc = loc;
+ td2d->loc2d = loc; /* current location */
+ }
+ else {
+ td2d->loc[0] = loc[0] * aspect[0]; /* hold original location */
+ td2d->loc[1] = loc[1] * aspect[1];
+
+ td2d->loc2d = loc; /* current location */
+ }
+ td2d->loc[2] = 0.0f;
+
+ tdt->relative = rel;
+ tdt->area = area;
+
+ tdt->markersnr = track->markersnr;
+ tdt->markers = track->markers;
+ tdt->track = track;
+
+ if (rel) {
+ if (!anchor) {
+ td2d->loc[0] += rel[0] * aspect[0];
+ td2d->loc[1] += rel[1] * aspect[1];
+ }
+
+ copy_v2_v2(tdt->srelative, rel);
+ }
+
+ if (off)
+ copy_v2_v2(tdt->soffset, off);
+
+ td->flag = 0;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->iloc, td->loc);
+
+ //copy_v3_v3(td->center, td->loc);
+ td->flag |= TD_INDIVIDUAL_SCALE;
+ td->center[0] = marker->pos[0] * aspect[0];
+ td->center[1] = marker->pos[1] * aspect[1];
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+}
+
+static void trackToTransData(const int framenr,
+ TransData *td,
+ TransData2D *td2d,
+ TransDataTracking *tdt,
+ MovieTrackingTrack *track,
+ const float aspect[2])
+{
+ MovieTrackingMarker *marker = BKE_tracking_marker_ensure(track, framenr);
+
+ tdt->flag = marker->flag;
+ marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED);
+
+ markerToTransDataInit(td++,
+ td2d++,
+ tdt++,
+ track,
+ marker,
+ TRACK_AREA_POINT,
+ track->offset,
+ marker->pos,
+ track->offset,
+ aspect);
+
+ if (track->flag & SELECT) {
+ markerToTransDataInit(
+ td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT, marker->pos, NULL, NULL, aspect);
+ }
+
+ if (track->pat_flag & SELECT) {
+ int a;
+
+ for (a = 0; a < 4; a++) {
+ markerToTransDataInit(td++,
+ td2d++,
+ tdt++,
+ track,
+ marker,
+ TRACK_AREA_PAT,
+ marker->pattern_corners[a],
+ marker->pos,
+ NULL,
+ aspect);
+ }
+ }
+
+ if (track->search_flag & SELECT) {
+ markerToTransDataInit(td++,
+ td2d++,
+ tdt++,
+ track,
+ marker,
+ TRACK_AREA_SEARCH,
+ marker->search_min,
+ marker->pos,
+ NULL,
+ aspect);
+
+ markerToTransDataInit(td++,
+ td2d++,
+ tdt++,
+ track,
+ marker,
+ TRACK_AREA_SEARCH,
+ marker->search_max,
+ marker->pos,
+ NULL,
+ aspect);
+ }
+}
+
+static void planeMarkerToTransDataInit(TransData *td,
+ TransData2D *td2d,
+ TransDataTracking *tdt,
+ MovieTrackingPlaneTrack *plane_track,
+ float corner[2],
const float aspect[2])
{
- tdt->mode = transDataTracking_ModePlaneTracks;
- tdt->plane_track = plane_track;
+ tdt->mode = transDataTracking_ModePlaneTracks;
+ tdt->plane_track = plane_track;
- td2d->loc[0] = corner[0] * aspect[0]; /* hold original location */
- td2d->loc[1] = corner[1] * aspect[1];
+ td2d->loc[0] = corner[0] * aspect[0]; /* hold original location */
+ td2d->loc[1] = corner[1] * aspect[1];
- td2d->loc2d = corner; /* current location */
- td2d->loc[2] = 0.0f;
+ td2d->loc2d = corner; /* current location */
+ td2d->loc[2] = 0.0f;
- td->flag = 0;
- td->loc = td2d->loc;
- copy_v3_v3(td->iloc, td->loc);
- copy_v3_v3(td->center, td->loc);
+ td->flag = 0;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->iloc, td->loc);
+ copy_v3_v3(td->center, td->loc);
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
- td->ext = NULL;
- td->val = NULL;
+ td->ext = NULL;
+ td->val = NULL;
- td->flag |= TD_SELECTED;
- td->dist = 0.0;
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
- unit_m3(td->mtx);
- unit_m3(td->smtx);
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
}
-static void planeTrackToTransData(const int framenr, TransData *td, TransData2D *td2d,
- TransDataTracking *tdt, MovieTrackingPlaneTrack *plane_track,
+static void planeTrackToTransData(const int framenr,
+ TransData *td,
+ TransData2D *td2d,
+ TransDataTracking *tdt,
+ MovieTrackingPlaneTrack *plane_track,
const float aspect[2])
{
- MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr);
- int i;
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr);
+ int i;
- tdt->flag = plane_marker->flag;
- plane_marker->flag &= ~PLANE_MARKER_TRACKED;
+ tdt->flag = plane_marker->flag;
+ plane_marker->flag &= ~PLANE_MARKER_TRACKED;
- for (i = 0; i < 4; i++) {
- planeMarkerToTransDataInit(td++, td2d++, tdt++, plane_track, plane_marker->corners[i], aspect);
- }
+ for (i = 0; i < 4; i++) {
+ planeMarkerToTransDataInit(td++, td2d++, tdt++, plane_track, plane_marker->corners[i], aspect);
+ }
}
-static void transDataTrackingFree(TransInfo *UNUSED(t), TransDataContainer *UNUSED(tc), TransCustomData *custom_data)
+static void transDataTrackingFree(TransInfo *UNUSED(t),
+ TransDataContainer *UNUSED(tc),
+ TransCustomData *custom_data)
{
- if (custom_data->data) {
- TransDataTracking *tdt = custom_data->data;
- if (tdt->smarkers)
- MEM_freeN(tdt->smarkers);
+ if (custom_data->data) {
+ TransDataTracking *tdt = custom_data->data;
+ if (tdt->smarkers)
+ MEM_freeN(tdt->smarkers);
- MEM_freeN(tdt);
- custom_data->data = NULL;
- }
+ MEM_freeN(tdt);
+ custom_data->data = NULL;
+ }
}
static void createTransTrackingTracksData(bContext *C, TransInfo *t)
{
- TransData *td;
- TransData2D *td2d;
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
- MovieTrackingTrack *track;
- MovieTrackingPlaneTrack *plane_track;
- TransDataTracking *tdt;
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* count */
- tc->data_len = 0;
-
- track = tracksbase->first;
- while (track) {
- if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
- tc->data_len++; /* offset */
-
- if (track->flag & SELECT)
- tc->data_len++;
-
- if (track->pat_flag & SELECT)
- tc->data_len += 4;
-
- if (track->search_flag & SELECT)
- tc->data_len += 2;
- }
-
- track = track->next;
- }
-
- for (plane_track = plane_tracks_base->first;
- plane_track;
- plane_track = plane_track->next)
- {
- if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
- tc->data_len += 4;
- }
- }
-
- if (tc->data_len == 0)
- return;
-
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransTracking TransData");
- td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransTracking TransData2D");
- tdt = tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataTracking), "TransTracking TransDataTracking");
-
- tc->custom.type.free_cb = transDataTrackingFree;
-
- /* create actual data */
- track = tracksbase->first;
- while (track) {
- if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
- trackToTransData(framenr, td, td2d, tdt, track, t->aspect);
-
- /* offset */
- td++;
- td2d++;
- tdt++;
-
- if (track->flag & SELECT) {
- td++;
- td2d++;
- tdt++;
- }
-
- if (track->pat_flag & SELECT) {
- td += 4;
- td2d += 4;
- tdt += 4;
- }
-
- if (track->search_flag & SELECT) {
- td += 2;
- td2d += 2;
- tdt += 2;
- }
- }
-
- track = track->next;
- }
-
- for (plane_track = plane_tracks_base->first;
- plane_track;
- plane_track = plane_track->next)
- {
- if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
- planeTrackToTransData(framenr, td, td2d, tdt, plane_track, t->aspect);
- td += 4;
- td2d += 4;
- tdt += 4;
- }
- }
-}
-
-static void markerToTransCurveDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
- MovieTrackingTrack *track, MovieTrackingMarker *marker,
- MovieTrackingMarker *prev_marker, short coord, float size)
-{
- float frames_delta = (marker->framenr - prev_marker->framenr);
-
- tdt->flag = marker->flag;
- marker->flag &= ~MARKER_TRACKED;
-
- tdt->mode = transDataTracking_ModeCurves;
- tdt->coord = coord;
- tdt->scale = 1.0f / size * frames_delta;
- tdt->prev_pos = prev_marker->pos;
- tdt->track = track;
+ TransData *td;
+ TransData2D *td2d;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
+ MovieTrackingTrack *track;
+ MovieTrackingPlaneTrack *plane_track;
+ TransDataTracking *tdt;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* count */
+ tc->data_len = 0;
+
+ track = tracksbase->first;
+ while (track) {
+ if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
+ tc->data_len++; /* offset */
+
+ if (track->flag & SELECT)
+ tc->data_len++;
+
+ if (track->pat_flag & SELECT)
+ tc->data_len += 4;
+
+ if (track->search_flag & SELECT)
+ tc->data_len += 2;
+ }
+
+ track = track->next;
+ }
+
+ for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
+ if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
+ tc->data_len += 4;
+ }
+ }
+
+ if (tc->data_len == 0)
+ return;
+
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransTracking TransData");
+ td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D),
+ "TransTracking TransData2D");
+ tdt = tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataTracking),
+ "TransTracking TransDataTracking");
+
+ tc->custom.type.free_cb = transDataTrackingFree;
+
+ /* create actual data */
+ track = tracksbase->first;
+ while (track) {
+ if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
+ trackToTransData(framenr, td, td2d, tdt, track, t->aspect);
+
+ /* offset */
+ td++;
+ td2d++;
+ tdt++;
+
+ if (track->flag & SELECT) {
+ td++;
+ td2d++;
+ tdt++;
+ }
+
+ if (track->pat_flag & SELECT) {
+ td += 4;
+ td2d += 4;
+ tdt += 4;
+ }
+
+ if (track->search_flag & SELECT) {
+ td += 2;
+ td2d += 2;
+ tdt += 2;
+ }
+ }
+
+ track = track->next;
+ }
+
+ for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
+ if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
+ planeTrackToTransData(framenr, td, td2d, tdt, plane_track, t->aspect);
+ td += 4;
+ td2d += 4;
+ tdt += 4;
+ }
+ }
+}
+
+static void markerToTransCurveDataInit(TransData *td,
+ TransData2D *td2d,
+ TransDataTracking *tdt,
+ MovieTrackingTrack *track,
+ MovieTrackingMarker *marker,
+ MovieTrackingMarker *prev_marker,
+ short coord,
+ float size)
+{
+ float frames_delta = (marker->framenr - prev_marker->framenr);
+
+ tdt->flag = marker->flag;
+ marker->flag &= ~MARKER_TRACKED;
+
+ tdt->mode = transDataTracking_ModeCurves;
+ tdt->coord = coord;
+ tdt->scale = 1.0f / size * frames_delta;
+ tdt->prev_pos = prev_marker->pos;
+ tdt->track = track;
+
+ /* calculate values depending on marker's speed */
+ td2d->loc[0] = marker->framenr;
+ td2d->loc[1] = (marker->pos[coord] - prev_marker->pos[coord]) * size / frames_delta;
+ td2d->loc[2] = 0.0f;
+
+ td2d->loc2d = marker->pos; /* current location */
- /* calculate values depending on marker's speed */
- td2d->loc[0] = marker->framenr;
- td2d->loc[1] = (marker->pos[coord] - prev_marker->pos[coord]) * size / frames_delta;
- td2d->loc[2] = 0.0f;
-
- td2d->loc2d = marker->pos; /* current location */
-
- td->flag = 0;
- td->loc = td2d->loc;
- copy_v3_v3(td->center, td->loc);
- copy_v3_v3(td->iloc, td->loc);
-
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
-
- td->ext = NULL;
- td->val = NULL;
-
- td->flag |= TD_SELECTED;
- td->dist = 0.0;
-
- unit_m3(td->mtx);
- unit_m3(td->smtx);
+ td->flag = 0;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->center, td->loc);
+ copy_v3_v3(td->iloc, td->loc);
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
}
static void createTransTrackingCurvesData(bContext *C, TransInfo *t)
{
- TransData *td;
- TransData2D *td2d;
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
- MovieTrackingTrack *track;
- MovieTrackingMarker *marker, *prev_marker;
- TransDataTracking *tdt;
- int i, width, height;
-
- BKE_movieclip_get_size(clip, &sc->user, &width, &height);
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* count */
- tc->data_len = 0;
-
- if ((sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) == 0) {
- return;
- }
-
- track = tracksbase->first;
- while (track) {
- if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
- for (i = 1; i < track->markersnr; i++) {
- marker = &track->markers[i];
- prev_marker = &track->markers[i - 1];
-
- if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED))
- continue;
-
- if (marker->flag & MARKER_GRAPH_SEL_X)
- tc->data_len += 1;
-
- if (marker->flag & MARKER_GRAPH_SEL_Y)
- tc->data_len += 1;
- }
- }
-
- track = track->next;
- }
-
- if (tc->data_len == 0)
- return;
-
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransTracking TransData");
- td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransTracking TransData2D");
- tc->custom.type.data = tdt = MEM_callocN(tc->data_len * sizeof(TransDataTracking), "TransTracking TransDataTracking");
- tc->custom.type.free_cb = transDataTrackingFree;
-
- /* create actual data */
- track = tracksbase->first;
- while (track) {
- if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
- for (i = 1; i < track->markersnr; i++) {
- marker = &track->markers[i];
- prev_marker = &track->markers[i - 1];
-
- if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED))
- continue;
-
- if (marker->flag & MARKER_GRAPH_SEL_X) {
- markerToTransCurveDataInit(td, td2d, tdt, track, marker, &track->markers[i - 1], 0, width);
- td += 1;
- td2d += 1;
- tdt += 1;
- }
-
- if (marker->flag & MARKER_GRAPH_SEL_Y) {
- markerToTransCurveDataInit(td, td2d, tdt, track, marker, &track->markers[i - 1], 1, height);
-
- td += 1;
- td2d += 1;
- tdt += 1;
- }
- }
- }
-
- track = track->next;
- }
+ TransData *td;
+ TransData2D *td2d;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+ MovieTrackingTrack *track;
+ MovieTrackingMarker *marker, *prev_marker;
+ TransDataTracking *tdt;
+ int i, width, height;
+
+ BKE_movieclip_get_size(clip, &sc->user, &width, &height);
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* count */
+ tc->data_len = 0;
+
+ if ((sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) == 0) {
+ return;
+ }
+
+ track = tracksbase->first;
+ while (track) {
+ if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
+ for (i = 1; i < track->markersnr; i++) {
+ marker = &track->markers[i];
+ prev_marker = &track->markers[i - 1];
+
+ if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED))
+ continue;
+
+ if (marker->flag & MARKER_GRAPH_SEL_X)
+ tc->data_len += 1;
+
+ if (marker->flag & MARKER_GRAPH_SEL_Y)
+ tc->data_len += 1;
+ }
+ }
+
+ track = track->next;
+ }
+
+ if (tc->data_len == 0)
+ return;
+
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransTracking TransData");
+ td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D),
+ "TransTracking TransData2D");
+ tc->custom.type.data = tdt = MEM_callocN(tc->data_len * sizeof(TransDataTracking),
+ "TransTracking TransDataTracking");
+ tc->custom.type.free_cb = transDataTrackingFree;
+
+ /* create actual data */
+ track = tracksbase->first;
+ while (track) {
+ if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
+ for (i = 1; i < track->markersnr; i++) {
+ marker = &track->markers[i];
+ prev_marker = &track->markers[i - 1];
+
+ if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED))
+ continue;
+
+ if (marker->flag & MARKER_GRAPH_SEL_X) {
+ markerToTransCurveDataInit(
+ td, td2d, tdt, track, marker, &track->markers[i - 1], 0, width);
+ td += 1;
+ td2d += 1;
+ tdt += 1;
+ }
+
+ if (marker->flag & MARKER_GRAPH_SEL_Y) {
+ markerToTransCurveDataInit(
+ td, td2d, tdt, track, marker, &track->markers[i - 1], 1, height);
+
+ td += 1;
+ td2d += 1;
+ tdt += 1;
+ }
+ }
+ }
+
+ track = track->next;
+ }
}
static void createTransTrackingData(bContext *C, TransInfo *t)
{
- ARegion *ar = CTX_wm_region(C);
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- int width, height;
+ ARegion *ar = CTX_wm_region(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ int width, height;
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- tc->data_len = 0;
+ tc->data_len = 0;
- if (!clip)
- return;
+ if (!clip)
+ return;
- BKE_movieclip_get_size(clip, &sc->user, &width, &height);
+ BKE_movieclip_get_size(clip, &sc->user, &width, &height);
- if (width == 0 || height == 0)
- return;
+ if (width == 0 || height == 0)
+ return;
- if (ar->regiontype == RGN_TYPE_PREVIEW) {
- /* transformation was called from graph editor */
- createTransTrackingCurvesData(C, t);
- }
- else {
- createTransTrackingTracksData(C, t);
- }
+ if (ar->regiontype == RGN_TYPE_PREVIEW) {
+ /* transformation was called from graph editor */
+ createTransTrackingCurvesData(C, t);
+ }
+ else {
+ createTransTrackingTracksData(C, t);
+ }
}
static void cancelTransTracking(TransInfo *t)
{
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- SpaceClip *sc = t->sa->spacedata.first;
- int i, framenr = ED_space_clip_get_clip_frame_number(sc);
- TransDataTracking *tdt_array = tc->custom.type.data;
-
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ SpaceClip *sc = t->sa->spacedata.first;
+ int i, framenr = ED_space_clip_get_clip_frame_number(sc);
+ TransDataTracking *tdt_array = tc->custom.type.data;
- i = 0;
- while (i < tc->data_len) {
- TransDataTracking *tdt = &tdt_array[i];
+ i = 0;
+ while (i < tc->data_len) {
+ TransDataTracking *tdt = &tdt_array[i];
- if (tdt->mode == transDataTracking_ModeTracks) {
- MovieTrackingTrack *track = tdt->track;
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+ if (tdt->mode == transDataTracking_ModeTracks) {
+ MovieTrackingTrack *track = tdt->track;
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
- marker->flag = tdt->flag;
+ marker->flag = tdt->flag;
- if (track->flag & SELECT)
- i++;
+ if (track->flag & SELECT)
+ i++;
- if (track->pat_flag & SELECT)
- i += 4;
+ if (track->pat_flag & SELECT)
+ i += 4;
- if (track->search_flag & SELECT)
- i += 2;
- }
- else if (tdt->mode == transDataTracking_ModeCurves) {
- MovieTrackingTrack *track = tdt->track;
- MovieTrackingMarker *marker, *prev_marker;
- int a;
+ if (track->search_flag & SELECT)
+ i += 2;
+ }
+ else if (tdt->mode == transDataTracking_ModeCurves) {
+ MovieTrackingTrack *track = tdt->track;
+ MovieTrackingMarker *marker, *prev_marker;
+ int a;
- for (a = 1; a < track->markersnr; a++) {
- marker = &track->markers[a];
- prev_marker = &track->markers[a - 1];
+ for (a = 1; a < track->markersnr; a++) {
+ marker = &track->markers[a];
+ prev_marker = &track->markers[a - 1];
- if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED))
- continue;
+ if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED))
+ continue;
- if (marker->flag & (MARKER_GRAPH_SEL_X | MARKER_GRAPH_SEL_Y)) {
- marker->flag = tdt->flag;
- }
- }
- }
- else if (tdt->mode == transDataTracking_ModePlaneTracks) {
- MovieTrackingPlaneTrack *plane_track = tdt->plane_track;
- MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+ if (marker->flag & (MARKER_GRAPH_SEL_X | MARKER_GRAPH_SEL_Y)) {
+ marker->flag = tdt->flag;
+ }
+ }
+ }
+ else if (tdt->mode == transDataTracking_ModePlaneTracks) {
+ MovieTrackingPlaneTrack *plane_track = tdt->plane_track;
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
- plane_marker->flag = tdt->flag;
- i += 3;
- }
+ plane_marker->flag = tdt->flag;
+ i += 3;
+ }
- i++;
- }
+ i++;
+ }
}
void flushTransTracking(TransInfo *t)
{
- TransData *td;
- TransData2D *td2d;
- TransDataTracking *tdt;
- int a;
-
- if (t->state == TRANS_CANCEL)
- cancelTransTracking(t);
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* flush to 2d vector from internally used 3d vector */
- for (a = 0, td = tc->data, td2d = tc->data_2d, tdt = tc->custom.type.data; a < tc->data_len; a++, td2d++, td++, tdt++) {
- if (tdt->mode == transDataTracking_ModeTracks) {
- float loc2d[2];
-
- if (t->mode == TFM_ROTATION && tdt->area == TRACK_AREA_SEARCH) {
- continue;
- }
-
- loc2d[0] = td2d->loc[0] / t->aspect[0];
- loc2d[1] = td2d->loc[1] / t->aspect[1];
-
- if (t->flag & T_ALT_TRANSFORM) {
- if (t->mode == TFM_RESIZE) {
- if (tdt->area != TRACK_AREA_PAT)
- continue;
- }
- else if (t->mode == TFM_TRANSLATION) {
- if (tdt->area == TRACK_AREA_POINT && tdt->relative) {
- float d[2], d2[2];
-
- if (!tdt->smarkers) {
- tdt->smarkers = MEM_callocN(sizeof(*tdt->smarkers) * tdt->markersnr, "flushTransTracking markers");
- for (a = 0; a < tdt->markersnr; a++)
- copy_v2_v2(tdt->smarkers[a], tdt->markers[a].pos);
- }
-
- sub_v2_v2v2(d, loc2d, tdt->soffset);
- sub_v2_v2(d, tdt->srelative);
-
- sub_v2_v2v2(d2, loc2d, tdt->srelative);
-
- for (a = 0; a < tdt->markersnr; a++)
- add_v2_v2v2(tdt->markers[a].pos, tdt->smarkers[a], d2);
-
- negate_v2_v2(td2d->loc2d, d);
- }
- }
- }
-
- if (tdt->area != TRACK_AREA_POINT || tdt->relative == NULL) {
- td2d->loc2d[0] = loc2d[0];
- td2d->loc2d[1] = loc2d[1];
-
- if (tdt->relative)
- sub_v2_v2(td2d->loc2d, tdt->relative);
- }
- }
- else if (tdt->mode == transDataTracking_ModeCurves) {
- td2d->loc2d[tdt->coord] = tdt->prev_pos[tdt->coord] + td2d->loc[1] * tdt->scale;
- }
- else if (tdt->mode == transDataTracking_ModePlaneTracks) {
- td2d->loc2d[0] = td2d->loc[0] / t->aspect[0];
- td2d->loc2d[1] = td2d->loc[1] / t->aspect[1];
- }
- }
+ TransData *td;
+ TransData2D *td2d;
+ TransDataTracking *tdt;
+ int a;
+
+ if (t->state == TRANS_CANCEL)
+ cancelTransTracking(t);
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* flush to 2d vector from internally used 3d vector */
+ for (a = 0, td = tc->data, td2d = tc->data_2d, tdt = tc->custom.type.data; a < tc->data_len;
+ a++, td2d++, td++, tdt++) {
+ if (tdt->mode == transDataTracking_ModeTracks) {
+ float loc2d[2];
+
+ if (t->mode == TFM_ROTATION && tdt->area == TRACK_AREA_SEARCH) {
+ continue;
+ }
+
+ loc2d[0] = td2d->loc[0] / t->aspect[0];
+ loc2d[1] = td2d->loc[1] / t->aspect[1];
+
+ if (t->flag & T_ALT_TRANSFORM) {
+ if (t->mode == TFM_RESIZE) {
+ if (tdt->area != TRACK_AREA_PAT)
+ continue;
+ }
+ else if (t->mode == TFM_TRANSLATION) {
+ if (tdt->area == TRACK_AREA_POINT && tdt->relative) {
+ float d[2], d2[2];
+
+ if (!tdt->smarkers) {
+ tdt->smarkers = MEM_callocN(sizeof(*tdt->smarkers) * tdt->markersnr,
+ "flushTransTracking markers");
+ for (a = 0; a < tdt->markersnr; a++)
+ copy_v2_v2(tdt->smarkers[a], tdt->markers[a].pos);
+ }
+
+ sub_v2_v2v2(d, loc2d, tdt->soffset);
+ sub_v2_v2(d, tdt->srelative);
+
+ sub_v2_v2v2(d2, loc2d, tdt->srelative);
+
+ for (a = 0; a < tdt->markersnr; a++)
+ add_v2_v2v2(tdt->markers[a].pos, tdt->smarkers[a], d2);
+
+ negate_v2_v2(td2d->loc2d, d);
+ }
+ }
+ }
+
+ if (tdt->area != TRACK_AREA_POINT || tdt->relative == NULL) {
+ td2d->loc2d[0] = loc2d[0];
+ td2d->loc2d[1] = loc2d[1];
+
+ if (tdt->relative)
+ sub_v2_v2(td2d->loc2d, tdt->relative);
+ }
+ }
+ else if (tdt->mode == transDataTracking_ModeCurves) {
+ td2d->loc2d[tdt->coord] = tdt->prev_pos[tdt->coord] + td2d->loc[1] * tdt->scale;
+ }
+ else if (tdt->mode == transDataTracking_ModePlaneTracks) {
+ td2d->loc2d[0] = td2d->loc[0] / t->aspect[0];
+ td2d->loc2d[1] = td2d->loc[1] / t->aspect[1];
+ }
+ }
}
/* * masking * */
typedef struct TransDataMasking {
- bool is_handle;
+ bool is_handle;
- float handle[2], orig_handle[2];
- float vec[3][3];
- MaskSplinePoint *point;
- float parent_matrix[3][3];
- float parent_inverse_matrix[3][3];
- char orig_handle_type;
+ float handle[2], orig_handle[2];
+ float vec[3][3];
+ MaskSplinePoint *point;
+ float parent_matrix[3][3];
+ float parent_inverse_matrix[3][3];
+ char orig_handle_type;
- eMaskWhichHandle which_handle;
+ eMaskWhichHandle which_handle;
} TransDataMasking;
-static void MaskHandleToTransData(MaskSplinePoint *point, eMaskWhichHandle which_handle,
- TransData *td, TransData2D *td2d, TransDataMasking *tdm,
+static void MaskHandleToTransData(MaskSplinePoint *point,
+ eMaskWhichHandle which_handle,
+ TransData *td,
+ TransData2D *td2d,
+ TransDataMasking *tdm,
const float asp[2],
/*const*/ float parent_matrix[3][3],
/*const*/ float parent_inverse_matrix[3][3])
{
- BezTriple *bezt = &point->bezt;
- const bool is_sel_any = MASKPOINT_ISSEL_ANY(point);
+ BezTriple *bezt = &point->bezt;
+ const bool is_sel_any = MASKPOINT_ISSEL_ANY(point);
- tdm->point = point;
- copy_m3_m3(tdm->vec, bezt->vec);
+ tdm->point = point;
+ copy_m3_m3(tdm->vec, bezt->vec);
- tdm->is_handle = true;
- copy_m3_m3(tdm->parent_matrix, parent_matrix);
- copy_m3_m3(tdm->parent_inverse_matrix, parent_inverse_matrix);
+ tdm->is_handle = true;
+ copy_m3_m3(tdm->parent_matrix, parent_matrix);
+ copy_m3_m3(tdm->parent_inverse_matrix, parent_inverse_matrix);
- BKE_mask_point_handle(point, which_handle, tdm->handle);
- tdm->which_handle = which_handle;
+ BKE_mask_point_handle(point, which_handle, tdm->handle);
+ tdm->which_handle = which_handle;
- copy_v2_v2(tdm->orig_handle, tdm->handle);
+ copy_v2_v2(tdm->orig_handle, tdm->handle);
- mul_v2_m3v2(td2d->loc, parent_matrix, tdm->handle);
- td2d->loc[0] *= asp[0];
- td2d->loc[1] *= asp[1];
- td2d->loc[2] = 0.0f;
+ mul_v2_m3v2(td2d->loc, parent_matrix, tdm->handle);
+ td2d->loc[0] *= asp[0];
+ td2d->loc[1] *= asp[1];
+ td2d->loc[2] = 0.0f;
- td2d->loc2d = tdm->handle;
+ td2d->loc2d = tdm->handle;
- td->flag = 0;
- td->loc = td2d->loc;
- mul_v2_m3v2(td->center, parent_matrix, bezt->vec[1]);
- td->center[0] *= asp[0];
- td->center[1] *= asp[1];
- copy_v3_v3(td->iloc, td->loc);
-
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
-
- td->ext = NULL;
- td->val = NULL;
-
- if (is_sel_any) {
- td->flag |= TD_SELECTED;
- }
-
- td->dist = 0.0;
-
- unit_m3(td->mtx);
- unit_m3(td->smtx);
-
- if (which_handle == MASK_WHICH_HANDLE_LEFT) {
- tdm->orig_handle_type = bezt->h1;
- }
- else if (which_handle == MASK_WHICH_HANDLE_RIGHT) {
- tdm->orig_handle_type = bezt->h2;
- }
-}
-
-static void MaskPointToTransData(
- Scene *scene, MaskSplinePoint *point,
- TransData *td, TransData2D *td2d, TransDataMasking *tdm,
- const bool is_prop_edit, const float asp[2])
-{
- BezTriple *bezt = &point->bezt;
- const bool is_sel_point = MASKPOINT_ISSEL_KNOT(point);
- const bool is_sel_any = MASKPOINT_ISSEL_ANY(point);
- float parent_matrix[3][3], parent_inverse_matrix[3][3];
-
- BKE_mask_point_parent_matrix_get(point, CFRA, parent_matrix);
- invert_m3_m3(parent_inverse_matrix, parent_matrix);
-
- if (is_prop_edit || is_sel_point) {
- int i;
-
- tdm->point = point;
- copy_m3_m3(tdm->vec, bezt->vec);
-
- for (i = 0; i < 3; i++) {
- copy_m3_m3(tdm->parent_matrix, parent_matrix);
- copy_m3_m3(tdm->parent_inverse_matrix, parent_inverse_matrix);
-
- /* CV coords are scaled by aspects. this is needed for rotations and
- * proportional editing to be consistent with the stretched CV coords
- * that are displayed. this also means that for display and numinput,
- * and when the CV coords are flushed, these are converted each time */
- mul_v2_m3v2(td2d->loc, parent_matrix, bezt->vec[i]);
- td2d->loc[0] *= asp[0];
- td2d->loc[1] *= asp[1];
- td2d->loc[2] = 0.0f;
-
- td2d->loc2d = bezt->vec[i];
-
- td->flag = 0;
- td->loc = td2d->loc;
- mul_v2_m3v2(td->center, parent_matrix, bezt->vec[1]);
- td->center[0] *= asp[0];
- td->center[1] *= asp[1];
- copy_v3_v3(td->iloc, td->loc);
-
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
-
- td->ext = NULL;
-
- if (i == 1) {
- /* scaling weights */
- td->val = &bezt->weight;
- td->ival = *td->val;
- }
- else {
- td->val = NULL;
- }
-
- if (is_sel_any) {
- td->flag |= TD_SELECTED;
- }
- td->dist = 0.0;
-
- unit_m3(td->mtx);
- unit_m3(td->smtx);
-
- if (i == 0) {
- tdm->orig_handle_type = bezt->h1;
- }
- else if (i == 2) {
- tdm->orig_handle_type = bezt->h2;
- }
-
- td++;
- td2d++;
- tdm++;
- }
- }
- else {
- if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
- MaskHandleToTransData(point, MASK_WHICH_HANDLE_STICK,
- td, td2d, tdm, asp, parent_matrix,
- parent_inverse_matrix);
-
- td++;
- td2d++;
- tdm++;
- }
- else {
- if (bezt->f1 & SELECT) {
- MaskHandleToTransData(point, MASK_WHICH_HANDLE_LEFT,
- td, td2d, tdm, asp, parent_matrix,
- parent_inverse_matrix);
-
- if (bezt->h1 == HD_VECT) {
- bezt->h1 = HD_FREE;
- }
- else if (bezt->h1 == HD_AUTO) {
- bezt->h1 = HD_ALIGN_DOUBLESIDE;
- bezt->h2 = HD_ALIGN_DOUBLESIDE;
- }
-
- td++;
- td2d++;
- tdm++;
- }
- if (bezt->f3 & SELECT) {
- MaskHandleToTransData(point, MASK_WHICH_HANDLE_RIGHT,
- td, td2d, tdm, asp, parent_matrix,
- parent_inverse_matrix);
-
- if (bezt->h2 == HD_VECT) {
- bezt->h2 = HD_FREE;
- }
- else if (bezt->h2 == HD_AUTO) {
- bezt->h1 = HD_ALIGN_DOUBLESIDE;
- bezt->h2 = HD_ALIGN_DOUBLESIDE;
- }
-
- td++;
- td2d++;
- tdm++;
- }
- }
- }
+ td->flag = 0;
+ td->loc = td2d->loc;
+ mul_v2_m3v2(td->center, parent_matrix, bezt->vec[1]);
+ td->center[0] *= asp[0];
+ td->center[1] *= asp[1];
+ copy_v3_v3(td->iloc, td->loc);
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+
+ if (is_sel_any) {
+ td->flag |= TD_SELECTED;
+ }
+
+ td->dist = 0.0;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+
+ if (which_handle == MASK_WHICH_HANDLE_LEFT) {
+ tdm->orig_handle_type = bezt->h1;
+ }
+ else if (which_handle == MASK_WHICH_HANDLE_RIGHT) {
+ tdm->orig_handle_type = bezt->h2;
+ }
+}
+
+static void MaskPointToTransData(Scene *scene,
+ MaskSplinePoint *point,
+ TransData *td,
+ TransData2D *td2d,
+ TransDataMasking *tdm,
+ const bool is_prop_edit,
+ const float asp[2])
+{
+ BezTriple *bezt = &point->bezt;
+ const bool is_sel_point = MASKPOINT_ISSEL_KNOT(point);
+ const bool is_sel_any = MASKPOINT_ISSEL_ANY(point);
+ float parent_matrix[3][3], parent_inverse_matrix[3][3];
+
+ BKE_mask_point_parent_matrix_get(point, CFRA, parent_matrix);
+ invert_m3_m3(parent_inverse_matrix, parent_matrix);
+
+ if (is_prop_edit || is_sel_point) {
+ int i;
+
+ tdm->point = point;
+ copy_m3_m3(tdm->vec, bezt->vec);
+
+ for (i = 0; i < 3; i++) {
+ copy_m3_m3(tdm->parent_matrix, parent_matrix);
+ copy_m3_m3(tdm->parent_inverse_matrix, parent_inverse_matrix);
+
+ /* CV coords are scaled by aspects. this is needed for rotations and
+ * proportional editing to be consistent with the stretched CV coords
+ * that are displayed. this also means that for display and numinput,
+ * and when the CV coords are flushed, these are converted each time */
+ mul_v2_m3v2(td2d->loc, parent_matrix, bezt->vec[i]);
+ td2d->loc[0] *= asp[0];
+ td2d->loc[1] *= asp[1];
+ td2d->loc[2] = 0.0f;
+
+ td2d->loc2d = bezt->vec[i];
+
+ td->flag = 0;
+ td->loc = td2d->loc;
+ mul_v2_m3v2(td->center, parent_matrix, bezt->vec[1]);
+ td->center[0] *= asp[0];
+ td->center[1] *= asp[1];
+ copy_v3_v3(td->iloc, td->loc);
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+
+ if (i == 1) {
+ /* scaling weights */
+ td->val = &bezt->weight;
+ td->ival = *td->val;
+ }
+ else {
+ td->val = NULL;
+ }
+
+ if (is_sel_any) {
+ td->flag |= TD_SELECTED;
+ }
+ td->dist = 0.0;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+
+ if (i == 0) {
+ tdm->orig_handle_type = bezt->h1;
+ }
+ else if (i == 2) {
+ tdm->orig_handle_type = bezt->h2;
+ }
+
+ td++;
+ td2d++;
+ tdm++;
+ }
+ }
+ else {
+ if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
+ MaskHandleToTransData(point,
+ MASK_WHICH_HANDLE_STICK,
+ td,
+ td2d,
+ tdm,
+ asp,
+ parent_matrix,
+ parent_inverse_matrix);
+
+ td++;
+ td2d++;
+ tdm++;
+ }
+ else {
+ if (bezt->f1 & SELECT) {
+ MaskHandleToTransData(point,
+ MASK_WHICH_HANDLE_LEFT,
+ td,
+ td2d,
+ tdm,
+ asp,
+ parent_matrix,
+ parent_inverse_matrix);
+
+ if (bezt->h1 == HD_VECT) {
+ bezt->h1 = HD_FREE;
+ }
+ else if (bezt->h1 == HD_AUTO) {
+ bezt->h1 = HD_ALIGN_DOUBLESIDE;
+ bezt->h2 = HD_ALIGN_DOUBLESIDE;
+ }
+
+ td++;
+ td2d++;
+ tdm++;
+ }
+ if (bezt->f3 & SELECT) {
+ MaskHandleToTransData(point,
+ MASK_WHICH_HANDLE_RIGHT,
+ td,
+ td2d,
+ tdm,
+ asp,
+ parent_matrix,
+ parent_inverse_matrix);
+
+ if (bezt->h2 == HD_VECT) {
+ bezt->h2 = HD_FREE;
+ }
+ else if (bezt->h2 == HD_AUTO) {
+ bezt->h1 = HD_ALIGN_DOUBLESIDE;
+ bezt->h2 = HD_ALIGN_DOUBLESIDE;
+ }
+
+ td++;
+ td2d++;
+ tdm++;
+ }
+ }
+ }
}
static void createTransMaskingData(bContext *C, TransInfo *t)
{
- Scene *scene = CTX_data_scene(C);
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
- TransData *td = NULL;
- TransData2D *td2d = NULL;
- TransDataMasking *tdm = NULL;
- int count = 0, countsel = 0;
- const bool is_prop_edit = (t->flag & T_PROP_EDIT);
- float asp[2];
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- tc->data_len = 0;
-
- if (!mask)
- return;
-
- if (t->spacetype == SPACE_CLIP) {
- SpaceClip *sc = t->sa->spacedata.first;
- MovieClip *clip = ED_space_clip_get_clip(sc);
- if (!clip) {
- return;
- }
- }
-
- /* count */
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
-
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
-
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- int i;
-
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
-
- if (MASKPOINT_ISSEL_ANY(point)) {
- if (MASKPOINT_ISSEL_KNOT(point)) {
- countsel += 3;
- }
- else {
- if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
- countsel += 1;
- }
- else {
- BezTriple *bezt = &point->bezt;
- if (bezt->f1 & SELECT) {
- countsel++;
- }
- if (bezt->f3 & SELECT) {
- countsel++;
- }
- }
- }
- }
-
- if (is_prop_edit)
- count += 3;
- }
- }
- }
-
- /* note: in prop mode we need at least 1 selected */
- if (countsel == 0) {
- return;
- }
-
- ED_mask_get_aspect(t->sa, t->ar, &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)");
- /* for each 2d uv coord a 3d vector is allocated, so that they can be
- * treated just as if they were 3d verts */
- td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransObData2D(Mask Editing)");
- tc->custom.type.data = tdm = MEM_callocN(tc->data_len * sizeof(TransDataMasking), "TransDataMasking(Mask Editing)");
- tc->custom.type.use_free = true;
-
- /* create data */
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
-
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
-
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- int i;
-
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
-
- if (is_prop_edit || MASKPOINT_ISSEL_ANY(point)) {
- MaskPointToTransData(scene, point, td, td2d, tdm, is_prop_edit, asp);
-
- if (is_prop_edit || MASKPOINT_ISSEL_KNOT(point)) {
- td += 3;
- td2d += 3;
- tdm += 3;
- }
- else {
- if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
- td++;
- td2d++;
- tdm++;
- }
- else {
- BezTriple *bezt = &point->bezt;
- if (bezt->f1 & SELECT) {
- td++;
- td2d++;
- tdm++;
- }
- if (bezt->f3 & SELECT) {
- td++;
- td2d++;
- tdm++;
- }
- }
- }
- }
- }
- }
- }
+ Scene *scene = CTX_data_scene(C);
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+ TransData *td = NULL;
+ TransData2D *td2d = NULL;
+ TransDataMasking *tdm = NULL;
+ int count = 0, countsel = 0;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT);
+ float asp[2];
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ tc->data_len = 0;
+
+ if (!mask)
+ return;
+
+ if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *sc = t->sa->spacedata.first;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ if (!clip) {
+ return;
+ }
+ }
+
+ /* count */
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ int i;
+
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
+
+ if (MASKPOINT_ISSEL_ANY(point)) {
+ if (MASKPOINT_ISSEL_KNOT(point)) {
+ countsel += 3;
+ }
+ else {
+ if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
+ countsel += 1;
+ }
+ else {
+ BezTriple *bezt = &point->bezt;
+ if (bezt->f1 & SELECT) {
+ countsel++;
+ }
+ if (bezt->f3 & SELECT) {
+ countsel++;
+ }
+ }
+ }
+ }
+
+ if (is_prop_edit)
+ count += 3;
+ }
+ }
+ }
+
+ /* note: in prop mode we need at least 1 selected */
+ if (countsel == 0) {
+ return;
+ }
+
+ ED_mask_get_aspect(t->sa, t->ar, &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)");
+ /* for each 2d uv coord a 3d vector is allocated, so that they can be
+ * treated just as if they were 3d verts */
+ td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D),
+ "TransObData2D(Mask Editing)");
+ tc->custom.type.data = tdm = MEM_callocN(tc->data_len * sizeof(TransDataMasking),
+ "TransDataMasking(Mask Editing)");
+ tc->custom.type.use_free = true;
+
+ /* create data */
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ int i;
+
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
+
+ if (is_prop_edit || MASKPOINT_ISSEL_ANY(point)) {
+ MaskPointToTransData(scene, point, td, td2d, tdm, is_prop_edit, asp);
+
+ if (is_prop_edit || MASKPOINT_ISSEL_KNOT(point)) {
+ td += 3;
+ td2d += 3;
+ tdm += 3;
+ }
+ else {
+ if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
+ td++;
+ td2d++;
+ tdm++;
+ }
+ else {
+ BezTriple *bezt = &point->bezt;
+ if (bezt->f1 & SELECT) {
+ td++;
+ td2d++;
+ tdm++;
+ }
+ if (bezt->f3 & SELECT) {
+ td++;
+ td2d++;
+ tdm++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
void flushTransMasking(TransInfo *t)
{
- TransData2D *td;
- TransDataMasking *tdm;
- int a;
- float asp[2], inv[2];
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- ED_mask_get_aspect(t->sa, t->ar, &asp[0], &asp[1]);
- inv[0] = 1.0f / asp[0];
- inv[1] = 1.0f / asp[1];
-
- /* flush to 2d vector from internally used 3d vector */
- for (a = 0, td = tc->data_2d, tdm = tc->custom.type.data; a < tc->data_len; a++, td++, tdm++) {
- td->loc2d[0] = td->loc[0] * inv[0];
- td->loc2d[1] = td->loc[1] * inv[1];
- mul_m3_v2(tdm->parent_inverse_matrix, td->loc2d);
-
- if (tdm->is_handle) {
- BKE_mask_point_set_handle(tdm->point, tdm->which_handle,
- td->loc2d,
- (t->flag & T_ALT_TRANSFORM) != 0,
- tdm->orig_handle, tdm->vec);
- }
-
- if (t->state == TRANS_CANCEL) {
- if (tdm->which_handle == MASK_WHICH_HANDLE_LEFT) {
- tdm->point->bezt.h1 = tdm->orig_handle_type;
- }
- else if (tdm->which_handle == MASK_WHICH_HANDLE_RIGHT) {
- tdm->point->bezt.h2 = tdm->orig_handle_type;
- }
- }
- }
+ TransData2D *td;
+ TransDataMasking *tdm;
+ int a;
+ float asp[2], inv[2];
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ ED_mask_get_aspect(t->sa, t->ar, &asp[0], &asp[1]);
+ inv[0] = 1.0f / asp[0];
+ inv[1] = 1.0f / asp[1];
+
+ /* flush to 2d vector from internally used 3d vector */
+ for (a = 0, td = tc->data_2d, tdm = tc->custom.type.data; a < tc->data_len; a++, td++, tdm++) {
+ td->loc2d[0] = td->loc[0] * inv[0];
+ td->loc2d[1] = td->loc[1] * inv[1];
+ mul_m3_v2(tdm->parent_inverse_matrix, td->loc2d);
+
+ if (tdm->is_handle) {
+ BKE_mask_point_set_handle(tdm->point,
+ tdm->which_handle,
+ td->loc2d,
+ (t->flag & T_ALT_TRANSFORM) != 0,
+ tdm->orig_handle,
+ tdm->vec);
+ }
+
+ if (t->state == TRANS_CANCEL) {
+ if (tdm->which_handle == MASK_WHICH_HANDLE_LEFT) {
+ tdm->point->bezt.h1 = tdm->orig_handle_type;
+ }
+ else if (tdm->which_handle == MASK_WHICH_HANDLE_RIGHT) {
+ tdm->point->bezt.h2 = tdm->orig_handle_type;
+ }
+ }
+ }
}
typedef struct TransDataPaintCurve {
- PaintCurvePoint *pcp; /* initial curve point */
- char id;
+ PaintCurvePoint *pcp; /* initial curve point */
+ char id;
} TransDataPaintCurve;
-
#define PC_IS_ANY_SEL(pc) (((pc)->bez.f1 | (pc)->bez.f2 | (pc)->bez.f3) & SELECT)
-static void PaintCurveConvertHandle(PaintCurvePoint *pcp, int id, TransData2D *td2d, TransDataPaintCurve *tdpc, TransData *td)
+static void PaintCurveConvertHandle(
+ PaintCurvePoint *pcp, int id, TransData2D *td2d, TransDataPaintCurve *tdpc, TransData *td)
{
- BezTriple *bezt = &pcp->bez;
- copy_v2_v2(td2d->loc, bezt->vec[id]);
- td2d->loc[2] = 0.0f;
- td2d->loc2d = bezt->vec[id];
+ BezTriple *bezt = &pcp->bez;
+ copy_v2_v2(td2d->loc, bezt->vec[id]);
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = bezt->vec[id];
- td->flag = 0;
- td->loc = td2d->loc;
- copy_v3_v3(td->center, bezt->vec[1]);
- copy_v3_v3(td->iloc, td->loc);
+ td->flag = 0;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->center, bezt->vec[1]);
+ copy_v3_v3(td->iloc, td->loc);
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
- td->ext = NULL;
- td->val = NULL;
- td->flag |= TD_SELECTED;
- td->dist = 0.0;
+ td->ext = NULL;
+ td->val = NULL;
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
- unit_m3(td->mtx);
- unit_m3(td->smtx);
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
- tdpc->id = id;
- tdpc->pcp = pcp;
+ tdpc->id = id;
+ tdpc->pcp = pcp;
}
-static void PaintCurvePointToTransData(PaintCurvePoint *pcp, TransData *td, TransData2D *td2d, TransDataPaintCurve *tdpc)
+static void PaintCurvePointToTransData(PaintCurvePoint *pcp,
+ TransData *td,
+ TransData2D *td2d,
+ TransDataPaintCurve *tdpc)
{
- BezTriple *bezt = &pcp->bez;
+ BezTriple *bezt = &pcp->bez;
- if (pcp->bez.f2 == SELECT) {
- int i;
- for (i = 0; i < 3; i++) {
- copy_v2_v2(td2d->loc, bezt->vec[i]);
- td2d->loc[2] = 0.0f;
- td2d->loc2d = bezt->vec[i];
+ if (pcp->bez.f2 == SELECT) {
+ int i;
+ for (i = 0; i < 3; i++) {
+ copy_v2_v2(td2d->loc, bezt->vec[i]);
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = bezt->vec[i];
- td->flag = 0;
- td->loc = td2d->loc;
- copy_v3_v3(td->center, bezt->vec[1]);
- copy_v3_v3(td->iloc, td->loc);
+ td->flag = 0;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->center, bezt->vec[1]);
+ copy_v3_v3(td->iloc, td->loc);
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
- td->ext = NULL;
- td->val = NULL;
- td->flag |= TD_SELECTED;
- td->dist = 0.0;
+ td->ext = NULL;
+ td->val = NULL;
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
- unit_m3(td->mtx);
- unit_m3(td->smtx);
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
- tdpc->id = i;
- tdpc->pcp = pcp;
+ tdpc->id = i;
+ tdpc->pcp = pcp;
- td++;
- td2d++;
- tdpc++;
- }
- }
- else {
- if (bezt->f3 & SELECT) {
- PaintCurveConvertHandle(pcp, 2, td2d, tdpc, td);
- td2d++;
- tdpc++;
- td++;
- }
+ td++;
+ td2d++;
+ tdpc++;
+ }
+ }
+ else {
+ if (bezt->f3 & SELECT) {
+ PaintCurveConvertHandle(pcp, 2, td2d, tdpc, td);
+ td2d++;
+ tdpc++;
+ td++;
+ }
- if (bezt->f1 & SELECT) {
- PaintCurveConvertHandle(pcp, 0, td2d, tdpc, td);
- }
- }
+ if (bezt->f1 & SELECT) {
+ PaintCurveConvertHandle(pcp, 0, td2d, tdpc, td);
+ }
+ }
}
static void createTransPaintCurveVerts(bContext *C, TransInfo *t)
{
- Paint *paint = BKE_paint_get_active_from_context(C);
- PaintCurve *pc;
- PaintCurvePoint *pcp;
- Brush *br;
- TransData *td = NULL;
- TransData2D *td2d = NULL;
- TransDataPaintCurve *tdpc = NULL;
- int i;
- int total = 0;
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- tc->data_len = 0;
-
- if (!paint || !paint->brush || !paint->brush->paint_curve)
- return;
-
- br = paint->brush;
- pc = br->paint_curve;
-
- for (pcp = pc->points, i = 0; i < pc->tot_points; i++, pcp++) {
- if (PC_IS_ANY_SEL(pcp)) {
- if (pcp->bez.f2 & SELECT) {
- total += 3;
- continue;
- }
- else {
- if (pcp->bez.f1 & SELECT)
- total++;
- if (pcp->bez.f3 & SELECT)
- total++;
- }
- }
- }
-
- if (!total)
- return;
-
- tc->data_len = total;
- td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransData2D");
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData");
- tc->custom.type.data = tdpc = MEM_callocN(tc->data_len * sizeof(TransDataPaintCurve), "TransDataPaintCurve");
- tc->custom.type.use_free = true;
-
- for (pcp = pc->points, i = 0; i < pc->tot_points; i++, pcp++) {
- if (PC_IS_ANY_SEL(pcp)) {
- PaintCurvePointToTransData(pcp, td, td2d, tdpc);
-
- if (pcp->bez.f2 & SELECT) {
- td += 3;
- td2d += 3;
- tdpc += 3;
- }
- else {
- if (pcp->bez.f1 & SELECT) {
- td++;
- td2d++;
- tdpc++;
- }
- if (pcp->bez.f3 & SELECT) {
- td++;
- td2d++;
- tdpc++;
- }
- }
- }
- }
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ PaintCurve *pc;
+ PaintCurvePoint *pcp;
+ Brush *br;
+ TransData *td = NULL;
+ TransData2D *td2d = NULL;
+ TransDataPaintCurve *tdpc = NULL;
+ int i;
+ int total = 0;
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ tc->data_len = 0;
+
+ if (!paint || !paint->brush || !paint->brush->paint_curve)
+ return;
+
+ br = paint->brush;
+ pc = br->paint_curve;
+
+ for (pcp = pc->points, i = 0; i < pc->tot_points; i++, pcp++) {
+ if (PC_IS_ANY_SEL(pcp)) {
+ if (pcp->bez.f2 & SELECT) {
+ total += 3;
+ continue;
+ }
+ else {
+ if (pcp->bez.f1 & SELECT)
+ total++;
+ if (pcp->bez.f3 & SELECT)
+ total++;
+ }
+ }
+ }
+
+ if (!total)
+ return;
+
+ tc->data_len = total;
+ td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransData2D");
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData");
+ tc->custom.type.data = tdpc = MEM_callocN(tc->data_len * sizeof(TransDataPaintCurve),
+ "TransDataPaintCurve");
+ tc->custom.type.use_free = true;
+
+ for (pcp = pc->points, i = 0; i < pc->tot_points; i++, pcp++) {
+ if (PC_IS_ANY_SEL(pcp)) {
+ PaintCurvePointToTransData(pcp, td, td2d, tdpc);
+
+ if (pcp->bez.f2 & SELECT) {
+ td += 3;
+ td2d += 3;
+ tdpc += 3;
+ }
+ else {
+ if (pcp->bez.f1 & SELECT) {
+ td++;
+ td2d++;
+ tdpc++;
+ }
+ if (pcp->bez.f3 & SELECT) {
+ td++;
+ td2d++;
+ tdpc++;
+ }
+ }
+ }
+ }
}
-
void flushTransPaintCurve(TransInfo *t)
{
- int i;
+ int i;
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- TransData2D *td2d = tc->data_2d;
- TransDataPaintCurve *tdpc = tc->custom.type.data;
+ TransData2D *td2d = tc->data_2d;
+ TransDataPaintCurve *tdpc = tc->custom.type.data;
- for (i = 0; i < tc->data_len; i++, tdpc++, td2d++) {
- PaintCurvePoint *pcp = tdpc->pcp;
- copy_v2_v2(pcp->bez.vec[tdpc->id], td2d->loc);
- }
+ for (i = 0; i < tc->data_len; i++, tdpc++, td2d++) {
+ PaintCurvePoint *pcp = tdpc->pcp;
+ copy_v2_v2(pcp->bez.vec[tdpc->id], td2d->loc);
+ }
}
static void createTransGPencil_center_get(bGPDstroke *gps, float r_center[3])
{
- bGPDspoint *pt;
- int i;
+ bGPDspoint *pt;
+ int i;
- zero_v3(r_center);
- int tot_sel = 0;
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT) {
- add_v3_v3(r_center, &pt->x);
- tot_sel++;
- }
- }
+ zero_v3(r_center);
+ int tot_sel = 0;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ add_v3_v3(r_center, &pt->x);
+ tot_sel++;
+ }
+ }
- if (tot_sel > 0) {
- mul_v3_fl(r_center, 1.0f / tot_sel);
- }
+ if (tot_sel > 0) {
+ mul_v3_fl(r_center, 1.0f / tot_sel);
+ }
}
static void createTransGPencil(bContext *C, TransInfo *t)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
-
- bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- bool use_multiframe_falloff = (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) != 0;
-
- Object *obact = CTX_data_active_object(C);
- bGPDlayer *gpl;
- TransData *td = NULL;
- float mtx[3][3], smtx[3][3];
-
- const Scene *scene = CTX_data_scene(C);
- const int cfra_scene = CFRA;
-
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
- const bool is_prop_edit_connected = (t->flag & T_PROP_CONNECTED) != 0;
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* == Grease Pencil Strokes to Transform Data ==
- * Grease Pencil stroke points can be a mixture of 2D (screen-space),
- * or 3D coordinates. However, they're always saved as 3D points.
- * For now, we just do these without creating TransData2D for the 2D
- * strokes. This may cause issues in future though.
- */
- tc->data_len = 0;
-
- if (gpd == NULL)
- return;
-
- /* initialize falloff curve */
- if (is_multiedit) {
- curvemapping_initialize(ts->gp_sculpt.cur_falloff);
- }
-
- /* First Pass: Count the number of data-points required for the strokes,
- * (and additional info about the configuration - e.g. 2D/3D?).
- */
- 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)) {
- bGPDframe *gpf;
- bGPDstroke *gps;
- bGPDframe *init_gpf = gpl->actframe;
- if (is_multiedit) {
- init_gpf = gpl->frames.first;
- }
-
- 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) {
- /* 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(obact, gpl, gps) == false) {
- continue;
- }
-
- if (is_prop_edit) {
- /* Proportional Editing... */
- if (is_prop_edit_connected) {
- /* connected only - so only if selected */
- if (gps->flag & GP_STROKE_SELECT)
- tc->data_len += gps->totpoints;
- }
- else {
- /* everything goes - connection status doesn't matter */
- tc->data_len += gps->totpoints;
- }
- }
- else {
- /* only selected stroke points are considered */
- if (gps->flag & GP_STROKE_SELECT) {
- bGPDspoint *pt;
- int i;
-
- // TODO: 2D vs 3D?
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT)
- tc->data_len++;
- }
- }
- }
- }
- }
- /* if not multiedit out of loop */
- if (!is_multiedit) {
- break;
- }
- }
- }
- }
-
- /* Stop trying if nothing selected */
- if (tc->data_len == 0) {
- return;
- }
-
- /* Allocate memory for data */
- tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData(GPencil)");
- td = tc->data;
-
- unit_m3(smtx);
- unit_m3(mtx);
-
- /* 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)) {
- const int cfra = (gpl->flag & GP_LAYER_FRAMELOCK) ? gpl->actframe->framenum : cfra_scene;
- bGPDframe *gpf = gpl->actframe;
- bGPDstroke *gps;
- float diff_mat[4][4];
- float inverse_diff_mat[4][4];
-
- bGPDframe *init_gpf = gpl->actframe;
- if (is_multiedit) {
- init_gpf = gpl->frames.first;
- }
- /* init multiframe falloff options */
- int f_init = 0;
- int f_end = 0;
-
- if (use_multiframe_falloff) {
- BKE_gpencil_get_range_selected(gpl, &f_init, &f_end);
- }
-
- /* calculate difference matrix */
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
- /* undo matrix */
- invert_m4_m4(inverse_diff_mat, diff_mat);
-
- /* Make a new frame to work on if the layer's frame and the current scene frame don't match up
- * - This is useful when animating as it saves that "uh-oh" moment when you realize you've
- * spent too much time editing the wrong frame...
- */
- // XXX: should this be allowed when framelock is enabled?
- if ((gpf->framenum != cfra) && (!is_multiedit)) {
- gpf = BKE_gpencil_frame_addcopy(gpl, cfra);
- /* in some weird situations (framelock enabled) return NULL */
- if (gpf == NULL) {
- continue;
- }
- if (!is_multiedit) {
- init_gpf = gpf;
- }
- }
-
- /* Loop over strokes, adding TransData for points as needed... */
- 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 */
- 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 = BKE_gpencil_multiframe_falloff_calc(
- gpf, gpl->actframe->framenum,
- f_init, f_end, ts->gp_sculpt.cur_falloff);
- }
-
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- TransData *head = td;
- TransData *tail = td;
- bool stroke_ok;
-
- /* 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(obact, gpl, gps) == false) {
- continue;
- }
- /* What we need to include depends on proportional editing settings... */
- if (is_prop_edit) {
- if (is_prop_edit_connected) {
- /* A) "Connected" - Only those in selected strokes */
- stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
- }
- else {
- /* B) All points, always */
- stroke_ok = true;
- }
- }
- else {
- /* C) Only selected points in selected strokes */
- stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
- }
-
- /* Do stroke... */
- if (stroke_ok && gps->totpoints) {
- bGPDspoint *pt;
- int i;
-
- /* save falloff factor */
- gps->runtime.multi_frame_falloff = falloff;
-
- /* calculate stroke center */
- float center[3];
- createTransGPencil_center_get(gps, center);
-
- /* add all necessary points... */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- bool point_ok;
-
- /* include point? */
- if (is_prop_edit) {
- /* Always all points in strokes that get included */
- point_ok = true;
- }
- else {
- /* Only selected points in selected strokes */
- point_ok = (pt->flag & GP_SPOINT_SELECT) != 0;
- }
-
- /* do point... */
- if (point_ok) {
- copy_v3_v3(td->iloc, &pt->x);
- /* only copy center in local origins.
- * This allows get interesting effects also when move
- * using proportional editing */
- if ((gps->flag & GP_STROKE_SELECT) &&
- (ts->transform_pivot_point == V3D_AROUND_LOCAL_ORIGINS))
- {
- copy_v3_v3(td->center, center);
- }
- else {
- copy_v3_v3(td->center, &pt->x);
- }
-
- td->loc = &pt->x;
-
- td->flag = 0;
-
- if (pt->flag & GP_SPOINT_SELECT) {
- td->flag |= TD_SELECTED;
- }
-
- /* for other transform modes (e.g. shrink-fatten), need to additional data
- * but never for scale or mirror
- */
- if ((t->mode != TFM_RESIZE) && (t->mode != TFM_MIRROR)) {
- if (t->mode != TFM_GPENCIL_OPACITY) {
- td->val = &pt->pressure;
- td->ival = pt->pressure;
- }
- else {
- td->val = &pt->strength;
- td->ival = pt->strength;
- }
- }
-
- /* screenspace needs special matrices... */
- if ((gps->flag & (GP_STROKE_3DSPACE | GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) == 0) {
- /* screenspace */
- td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ;
- }
- else {
- /* configure 2D dataspace points so that they don't play up... */
- if (gps->flag & (GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) {
- td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ;
- }
- }
- /* apply parent transformations */
- copy_m3_m4(td->smtx, inverse_diff_mat); /* final position */
- copy_m3_m4(td->mtx, diff_mat); /* display position */
- copy_m3_m4(td->axismtx, diff_mat); /* axis orientation */
-
- /* Triangulation must be calculated again,
- * so save the stroke for recalc function */
- td->extra = gps;
-
- /* save pointer to object */
- td->ob = obact;
-
- td++;
- tail++;
- }
- }
-
- /* March over these points, and calculate the proportional editing distances */
- if (is_prop_edit && (head != tail)) {
- /* XXX: for now, we are similar enough that this works... */
- calc_distanceCurveVerts(head, tail - 1);
- }
- }
- }
- }
- /* if not multiedit out of loop */
- if (!is_multiedit) {
- break;
- }
- }
- }
- }
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+
+ bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ bool use_multiframe_falloff = (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) != 0;
+
+ Object *obact = CTX_data_active_object(C);
+ bGPDlayer *gpl;
+ TransData *td = NULL;
+ float mtx[3][3], smtx[3][3];
+
+ const Scene *scene = CTX_data_scene(C);
+ const int cfra_scene = CFRA;
+
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+ const bool is_prop_edit_connected = (t->flag & T_PROP_CONNECTED) != 0;
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* == Grease Pencil Strokes to Transform Data ==
+ * Grease Pencil stroke points can be a mixture of 2D (screen-space),
+ * or 3D coordinates. However, they're always saved as 3D points.
+ * For now, we just do these without creating TransData2D for the 2D
+ * strokes. This may cause issues in future though.
+ */
+ tc->data_len = 0;
+
+ if (gpd == NULL)
+ return;
+
+ /* initialize falloff curve */
+ if (is_multiedit) {
+ curvemapping_initialize(ts->gp_sculpt.cur_falloff);
+ }
+
+ /* First Pass: Count the number of data-points required for the strokes,
+ * (and additional info about the configuration - e.g. 2D/3D?).
+ */
+ 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)) {
+ bGPDframe *gpf;
+ bGPDstroke *gps;
+ bGPDframe *init_gpf = gpl->actframe;
+ if (is_multiedit) {
+ init_gpf = gpl->frames.first;
+ }
+
+ 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) {
+ /* 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(obact, gpl, gps) == false) {
+ continue;
+ }
+
+ if (is_prop_edit) {
+ /* Proportional Editing... */
+ if (is_prop_edit_connected) {
+ /* connected only - so only if selected */
+ if (gps->flag & GP_STROKE_SELECT)
+ tc->data_len += gps->totpoints;
+ }
+ else {
+ /* everything goes - connection status doesn't matter */
+ tc->data_len += gps->totpoints;
+ }
+ }
+ else {
+ /* only selected stroke points are considered */
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ // TODO: 2D vs 3D?
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT)
+ tc->data_len++;
+ }
+ }
+ }
+ }
+ }
+ /* if not multiedit out of loop */
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ }
+
+ /* Stop trying if nothing selected */
+ if (tc->data_len == 0) {
+ return;
+ }
+
+ /* Allocate memory for data */
+ tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData(GPencil)");
+ td = tc->data;
+
+ unit_m3(smtx);
+ unit_m3(mtx);
+
+ /* 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)) {
+ const int cfra = (gpl->flag & GP_LAYER_FRAMELOCK) ? gpl->actframe->framenum : cfra_scene;
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps;
+ float diff_mat[4][4];
+ float inverse_diff_mat[4][4];
+
+ bGPDframe *init_gpf = gpl->actframe;
+ if (is_multiedit) {
+ init_gpf = gpl->frames.first;
+ }
+ /* init multiframe falloff options */
+ int f_init = 0;
+ int f_end = 0;
+
+ if (use_multiframe_falloff) {
+ BKE_gpencil_get_range_selected(gpl, &f_init, &f_end);
+ }
+
+ /* calculate difference matrix */
+ ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ /* undo matrix */
+ invert_m4_m4(inverse_diff_mat, diff_mat);
+
+ /* Make a new frame to work on if the layer's frame and the current scene frame don't match up
+ * - This is useful when animating as it saves that "uh-oh" moment when you realize you've
+ * spent too much time editing the wrong frame...
+ */
+ // XXX: should this be allowed when framelock is enabled?
+ if ((gpf->framenum != cfra) && (!is_multiedit)) {
+ gpf = BKE_gpencil_frame_addcopy(gpl, cfra);
+ /* in some weird situations (framelock enabled) return NULL */
+ if (gpf == NULL) {
+ continue;
+ }
+ if (!is_multiedit) {
+ init_gpf = gpf;
+ }
+ }
+
+ /* Loop over strokes, adding TransData for points as needed... */
+ 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 */
+ 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 = BKE_gpencil_multiframe_falloff_calc(
+ gpf, gpl->actframe->framenum, f_init, f_end, ts->gp_sculpt.cur_falloff);
+ }
+
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ TransData *head = td;
+ TransData *tail = td;
+ bool stroke_ok;
+
+ /* 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(obact, gpl, gps) == false) {
+ continue;
+ }
+ /* What we need to include depends on proportional editing settings... */
+ if (is_prop_edit) {
+ if (is_prop_edit_connected) {
+ /* A) "Connected" - Only those in selected strokes */
+ stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
+ }
+ else {
+ /* B) All points, always */
+ stroke_ok = true;
+ }
+ }
+ else {
+ /* C) Only selected points in selected strokes */
+ stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
+ }
+
+ /* Do stroke... */
+ if (stroke_ok && gps->totpoints) {
+ bGPDspoint *pt;
+ int i;
+
+ /* save falloff factor */
+ gps->runtime.multi_frame_falloff = falloff;
+
+ /* calculate stroke center */
+ float center[3];
+ createTransGPencil_center_get(gps, center);
+
+ /* add all necessary points... */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ bool point_ok;
+
+ /* include point? */
+ if (is_prop_edit) {
+ /* Always all points in strokes that get included */
+ point_ok = true;
+ }
+ else {
+ /* Only selected points in selected strokes */
+ point_ok = (pt->flag & GP_SPOINT_SELECT) != 0;
+ }
+
+ /* do point... */
+ if (point_ok) {
+ copy_v3_v3(td->iloc, &pt->x);
+ /* only copy center in local origins.
+ * This allows get interesting effects also when move
+ * using proportional editing */
+ if ((gps->flag & GP_STROKE_SELECT) &&
+ (ts->transform_pivot_point == V3D_AROUND_LOCAL_ORIGINS)) {
+ copy_v3_v3(td->center, center);
+ }
+ else {
+ copy_v3_v3(td->center, &pt->x);
+ }
+
+ td->loc = &pt->x;
+
+ td->flag = 0;
+
+ if (pt->flag & GP_SPOINT_SELECT) {
+ td->flag |= TD_SELECTED;
+ }
+
+ /* for other transform modes (e.g. shrink-fatten), need to additional data
+ * but never for scale or mirror
+ */
+ if ((t->mode != TFM_RESIZE) && (t->mode != TFM_MIRROR)) {
+ if (t->mode != TFM_GPENCIL_OPACITY) {
+ td->val = &pt->pressure;
+ td->ival = pt->pressure;
+ }
+ else {
+ td->val = &pt->strength;
+ td->ival = pt->strength;
+ }
+ }
+
+ /* screenspace needs special matrices... */
+ if ((gps->flag & (GP_STROKE_3DSPACE | GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) ==
+ 0) {
+ /* screenspace */
+ td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ;
+ }
+ else {
+ /* configure 2D dataspace points so that they don't play up... */
+ if (gps->flag & (GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) {
+ td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ;
+ }
+ }
+ /* apply parent transformations */
+ copy_m3_m4(td->smtx, inverse_diff_mat); /* final position */
+ copy_m3_m4(td->mtx, diff_mat); /* display position */
+ copy_m3_m4(td->axismtx, diff_mat); /* axis orientation */
+
+ /* Triangulation must be calculated again,
+ * so save the stroke for recalc function */
+ td->extra = gps;
+
+ /* save pointer to object */
+ td->ob = obact;
+
+ td++;
+ tail++;
+ }
+ }
+
+ /* March over these points, and calculate the proportional editing distances */
+ if (is_prop_edit && (head != tail)) {
+ /* XXX: for now, we are similar enough that this works... */
+ calc_distanceCurveVerts(head, tail - 1);
+ }
+ }
+ }
+ }
+ /* if not multiedit out of loop */
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ }
}
static int countAndCleanTransDataContainer(TransInfo *t)
{
- BLI_assert(ELEM(t->data_len_all, 0, -1));
- t->data_len_all = 0;
- uint data_container_len_orig = t->data_container_len;
- for (TransDataContainer *th_end = t->data_container - 1, *tc = t->data_container + (t->data_container_len - 1); tc != th_end; tc--) {
- if (tc->data_len == 0) {
- uint index = tc - t->data_container;
- if (index + 1 != t->data_container_len) {
- SWAP(TransDataContainer, t->data_container[index], t->data_container[t->data_container_len - 1]);
- }
- t->data_container_len -= 1;
- }
- else {
- t->data_len_all += tc->data_len;
- }
- }
- if (data_container_len_orig != t->data_container_len) {
- t->data_container = MEM_reallocN(t->data_container, sizeof(*t->data_container) * t->data_container_len);
- }
- return t->data_len_all;
+ BLI_assert(ELEM(t->data_len_all, 0, -1));
+ t->data_len_all = 0;
+ uint data_container_len_orig = t->data_container_len;
+ for (TransDataContainer *th_end = t->data_container - 1,
+ *tc = t->data_container + (t->data_container_len - 1);
+ tc != th_end;
+ tc--) {
+ if (tc->data_len == 0) {
+ uint index = tc - t->data_container;
+ if (index + 1 != t->data_container_len) {
+ SWAP(TransDataContainer,
+ t->data_container[index],
+ t->data_container[t->data_container_len - 1]);
+ }
+ t->data_container_len -= 1;
+ }
+ else {
+ t->data_len_all += tc->data_len;
+ }
+ }
+ if (data_container_len_orig != t->data_container_len) {
+ t->data_container = MEM_reallocN(t->data_container,
+ sizeof(*t->data_container) * t->data_container_len);
+ }
+ return t->data_len_all;
}
-
void createTransData(bContext *C, TransInfo *t)
{
- Scene *scene = t->scene;
- ViewLayer *view_layer = t->view_layer;
- Object *ob = OBACT(view_layer);
-
- bool has_transform_context = true;
- t->data_len_all = -1;
-
- /* if tests must match recalcData for correct updates */
- if (t->options & CTX_CURSOR) {
- t->flag |= T_CURSOR;
- t->obedit_type = -1;
-
- if (t->spacetype == SPACE_IMAGE) {
- createTransCursor_image(t);
- }
- else {
- createTransCursor_view3d(t);
- }
- countAndCleanTransDataContainer(t);
- }
- else if (t->options & CTX_TEXTURE) {
- t->flag |= T_TEXTURE;
- t->obedit_type = -1;
-
- createTransTexspace(t);
- countAndCleanTransDataContainer(t);
- }
- else if (t->options & CTX_EDGE) {
- /* Multi object editing. */
- initTransDataContainers_FromObjectData(t, ob, NULL, 0);
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- tc->data_ext = NULL;
- }
- t->flag |= T_EDIT;
-
- createTransEdge(t);
- countAndCleanTransDataContainer(t);
-
- if (t->data_len_all && t->flag & T_PROP_EDIT) {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, 1);
- sort_trans_data_dist(t);
- }
- }
- else if (t->options & CTX_GPENCIL_STROKES) {
- t->options |= CTX_GPENCIL_STROKES;
- t->flag |= T_POINTS | T_EDIT;
-
- initTransDataContainers_FromObjectData(t, ob, NULL, 0);
- createTransGPencil(C, t);
- countAndCleanTransDataContainer(t);
-
- if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, 1);
- sort_trans_data_dist(t);
- }
- }
- else if (t->spacetype == SPACE_IMAGE) {
- t->flag |= T_POINTS | T_2D_EDIT;
- if (t->options & CTX_MASK) {
-
- /* copied from below */
- createTransMaskingData(C, t);
- countAndCleanTransDataContainer(t);
-
- if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, true);
- sort_trans_data_dist(t);
- }
- }
- else if (t->options & CTX_PAINT_CURVE) {
- if (!ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
- createTransPaintCurveVerts(C, t);
- countAndCleanTransDataContainer(t);
- }
- else {
- has_transform_context = false;
- }
- }
- else if (t->obedit_type == OB_MESH) {
-
- initTransDataContainers_FromObjectData(t, ob, NULL, 0);
- createTransUVs(C, t);
- countAndCleanTransDataContainer(t);
-
- t->flag |= T_EDIT;
-
- if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, 1);
- sort_trans_data_dist(t);
- }
- }
- else {
- has_transform_context = false;
- }
- }
- else if (t->spacetype == SPACE_ACTION) {
- t->flag |= T_POINTS | T_2D_EDIT;
- t->obedit_type = -1;
-
- createTransActionData(C, t);
- countAndCleanTransDataContainer(t);
-
- if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
- /* don't do that, distance has been set in createTransActionData already */
- //set_prop_dist(t, false);
- sort_trans_data_dist(t);
- }
- }
- else if (t->spacetype == SPACE_NLA) {
- t->flag |= T_POINTS | T_2D_EDIT;
- t->obedit_type = -1;
-
- createTransNlaData(C, t);
- countAndCleanTransDataContainer(t);
- }
- else if (t->spacetype == SPACE_SEQ) {
- t->flag |= T_POINTS | T_2D_EDIT;
- t->obedit_type = -1;
-
- t->num.flag |= NUM_NO_FRACTION; /* sequencer has no use for floating point trasnform */
- createTransSeqData(C, t);
- countAndCleanTransDataContainer(t);
- }
- else if (t->spacetype == SPACE_GRAPH) {
- t->flag |= T_POINTS | T_2D_EDIT;
- t->obedit_type = -1;
-
- createTransGraphEditData(C, t);
- countAndCleanTransDataContainer(t);
-
- if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- /* makes selected become first in array */
- sort_trans_data(t);
-
- /* don't do that, distance has been set in createTransGraphEditData already */
- set_prop_dist(t, false);
-
- sort_trans_data_dist(t);
- }
- }
- else if (t->spacetype == SPACE_NODE) {
- t->flag |= T_POINTS | T_2D_EDIT;
- t->obedit_type = -1;
-
- createTransNodeData(C, t);
- countAndCleanTransDataContainer(t);
-
- if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, 1);
- sort_trans_data_dist(t);
- }
- }
- else if (t->spacetype == SPACE_CLIP) {
- t->flag |= T_POINTS | T_2D_EDIT;
- t->obedit_type = -1;
-
- if (t->options & CTX_MOVIECLIP) {
- createTransTrackingData(C, t);
- countAndCleanTransDataContainer(t);
- }
- else if (t->options & CTX_MASK) {
- /* copied from above */
- createTransMaskingData(C, t);
- countAndCleanTransDataContainer(t);
-
- if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, true);
- sort_trans_data_dist(t);
- }
- }
- else {
- has_transform_context = false;
- }
- }
- else if (t->obedit_type != -1) {
- /* Multi object editing. */
- initTransDataContainers_FromObjectData(t, ob, NULL, 0);
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- tc->data_ext = NULL;
- }
- if (t->obedit_type == OB_MESH) {
- createTransEditVerts(t);
- }
- else if (ELEM(t->obedit_type, OB_CURVE, OB_SURF)) {
- createTransCurveVerts(t);
- }
- else if (t->obedit_type == OB_LATTICE) {
- createTransLatticeVerts(t);
- }
- else if (t->obedit_type == OB_MBALL) {
- createTransMBallVerts(t);
- }
- else if (t->obedit_type == OB_ARMATURE) {
- t->flag &= ~T_PROP_EDIT;
- createTransArmatureVerts(t);
- }
- else {
- printf("edit type not implemented!\n");
- }
-
- countAndCleanTransDataContainer(t);
-
- t->flag |= T_EDIT | T_POINTS;
-
- if (t->data_len_all && t->flag & T_PROP_EDIT) {
- if (ELEM(t->obedit_type, OB_CURVE, OB_MESH)) {
- sort_trans_data(t); // makes selected become first in array
- if ((t->obedit_type == OB_MESH) && (t->flag & T_PROP_CONNECTED)) {
- /* already calculated by editmesh_set_connectivity_distance */
- }
- else {
- set_prop_dist(t, 0);
- }
- sort_trans_data_dist(t);
- }
- else {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, 1);
- sort_trans_data_dist(t);
- }
- }
-
- /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */
- if (t->mode == TFM_BONESIZE) {
- t->flag &= ~(T_EDIT | T_POINTS);
- t->flag |= T_POSE;
- t->obedit_type = -1;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- tc->poseobj = tc->obedit;
- tc->obedit = NULL;
- }
- }
- }
- else if (ob && (ob->mode & OB_MODE_POSE)) {
- // XXX this is currently limited to active armature only...
- // XXX active-layer checking isn't done as that should probably be checked through context instead
-
- /* Multi object editing. */
- initTransDataContainers_FromObjectData(t, ob, NULL, 0);
- createTransPose(t);
- countAndCleanTransDataContainer(t);
- }
- else if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && !(t->options & CTX_PAINT_CURVE)) {
- /* 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);
- 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) {
- View3D *v3d = t->view;
- if (BASE_VISIBLE(v3d, base_arm)) {
- Object *objects[1];
- objects[0] = ob_armature;
- uint objects_len = 1;
- initTransDataContainers_FromObjectData(t, ob_armature, objects, objects_len);
- createTransPose(t);
- countAndCleanTransDataContainer(t);
- has_transform_context = true;
- }
- }
- }
- }
- else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_start_edit(PE_get_current(scene, ob))) {
- createTransParticleVerts(C, t);
- countAndCleanTransDataContainer(t);
- t->flag |= T_POINTS;
-
- if (t->data_len_all && t->flag & T_PROP_EDIT) {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, 1);
- sort_trans_data_dist(t);
- }
- }
- else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
- if ((t->options & CTX_PAINT_CURVE) && !ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
- t->flag |= T_POINTS | T_2D_EDIT;
- createTransPaintCurveVerts(C, t);
- countAndCleanTransDataContainer(t);
- }
- else {
- has_transform_context = false;
- }
- }
- else if ((ob) &&
- (ELEM(ob->mode, OB_MODE_PAINT_GPENCIL,
- OB_MODE_SCULPT_GPENCIL, OB_MODE_WEIGHT_GPENCIL)))
- {
- /* In grease pencil all transformations must be canceled if not Object or Edit. */
- has_transform_context = false;
- }
- else {
- createTransObject(C, t);
- countAndCleanTransDataContainer(t);
- t->flag |= T_OBJECT;
-
- if (t->data_len_all && t->flag & T_PROP_EDIT) {
- // selected objects are already first, no need to presort
- set_prop_dist(t, 1);
- sort_trans_data_dist(t);
- }
-
- /* Check if we're transforming the camera from the camera */
- if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) {
- View3D *v3d = t->view;
- RegionView3D *rv3d = t->ar->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;
- }
- }
- }
- }
-
- /* Check that 'countAndCleanTransDataContainer' ran. */
- if (has_transform_context) {
- BLI_assert(t->data_len_all != -1);
- }
- else {
- BLI_assert(t->data_len_all == -1);
- t->data_len_all = 0;
- }
-
- BLI_assert((!(t->flag & T_EDIT)) == (!(t->obedit_type != -1)));
+ Scene *scene = t->scene;
+ ViewLayer *view_layer = t->view_layer;
+ Object *ob = OBACT(view_layer);
+
+ bool has_transform_context = true;
+ t->data_len_all = -1;
+
+ /* if tests must match recalcData for correct updates */
+ if (t->options & CTX_CURSOR) {
+ t->flag |= T_CURSOR;
+ t->obedit_type = -1;
+
+ if (t->spacetype == SPACE_IMAGE) {
+ createTransCursor_image(t);
+ }
+ else {
+ createTransCursor_view3d(t);
+ }
+ countAndCleanTransDataContainer(t);
+ }
+ else if (t->options & CTX_TEXTURE) {
+ t->flag |= T_TEXTURE;
+ t->obedit_type = -1;
+
+ createTransTexspace(t);
+ countAndCleanTransDataContainer(t);
+ }
+ else if (t->options & CTX_EDGE) {
+ /* Multi object editing. */
+ initTransDataContainers_FromObjectData(t, ob, NULL, 0);
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ tc->data_ext = NULL;
+ }
+ t->flag |= T_EDIT;
+
+ createTransEdge(t);
+ countAndCleanTransDataContainer(t);
+
+ if (t->data_len_all && t->flag & T_PROP_EDIT) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+ }
+ else if (t->options & CTX_GPENCIL_STROKES) {
+ t->options |= CTX_GPENCIL_STROKES;
+ t->flag |= T_POINTS | T_EDIT;
+
+ initTransDataContainers_FromObjectData(t, ob, NULL, 0);
+ createTransGPencil(C, t);
+ countAndCleanTransDataContainer(t);
+
+ if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ t->flag |= T_POINTS | T_2D_EDIT;
+ if (t->options & CTX_MASK) {
+
+ /* copied from below */
+ createTransMaskingData(C, t);
+ countAndCleanTransDataContainer(t);
+
+ if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, true);
+ sort_trans_data_dist(t);
+ }
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ if (!ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
+ createTransPaintCurveVerts(C, t);
+ countAndCleanTransDataContainer(t);
+ }
+ else {
+ has_transform_context = false;
+ }
+ }
+ else if (t->obedit_type == OB_MESH) {
+
+ initTransDataContainers_FromObjectData(t, ob, NULL, 0);
+ createTransUVs(C, t);
+ countAndCleanTransDataContainer(t);
+
+ t->flag |= T_EDIT;
+
+ if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+ }
+ else {
+ has_transform_context = false;
+ }
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ t->flag |= T_POINTS | T_2D_EDIT;
+ t->obedit_type = -1;
+
+ createTransActionData(C, t);
+ countAndCleanTransDataContainer(t);
+
+ if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ /* don't do that, distance has been set in createTransActionData already */
+ //set_prop_dist(t, false);
+ sort_trans_data_dist(t);
+ }
+ }
+ else if (t->spacetype == SPACE_NLA) {
+ t->flag |= T_POINTS | T_2D_EDIT;
+ t->obedit_type = -1;
+
+ createTransNlaData(C, t);
+ countAndCleanTransDataContainer(t);
+ }
+ else if (t->spacetype == SPACE_SEQ) {
+ t->flag |= T_POINTS | T_2D_EDIT;
+ t->obedit_type = -1;
+
+ t->num.flag |= NUM_NO_FRACTION; /* sequencer has no use for floating point trasnform */
+ createTransSeqData(C, t);
+ countAndCleanTransDataContainer(t);
+ }
+ else if (t->spacetype == SPACE_GRAPH) {
+ t->flag |= T_POINTS | T_2D_EDIT;
+ t->obedit_type = -1;
+
+ createTransGraphEditData(C, t);
+ countAndCleanTransDataContainer(t);
+
+ if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
+ /* makes selected become first in array */
+ sort_trans_data(t);
+
+ /* don't do that, distance has been set in createTransGraphEditData already */
+ set_prop_dist(t, false);
+
+ sort_trans_data_dist(t);
+ }
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ t->flag |= T_POINTS | T_2D_EDIT;
+ t->obedit_type = -1;
+
+ createTransNodeData(C, t);
+ countAndCleanTransDataContainer(t);
+
+ if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ t->flag |= T_POINTS | T_2D_EDIT;
+ t->obedit_type = -1;
+
+ if (t->options & CTX_MOVIECLIP) {
+ createTransTrackingData(C, t);
+ countAndCleanTransDataContainer(t);
+ }
+ else if (t->options & CTX_MASK) {
+ /* copied from above */
+ createTransMaskingData(C, t);
+ countAndCleanTransDataContainer(t);
+
+ if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, true);
+ sort_trans_data_dist(t);
+ }
+ }
+ else {
+ has_transform_context = false;
+ }
+ }
+ else if (t->obedit_type != -1) {
+ /* Multi object editing. */
+ initTransDataContainers_FromObjectData(t, ob, NULL, 0);
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ tc->data_ext = NULL;
+ }
+ if (t->obedit_type == OB_MESH) {
+ createTransEditVerts(t);
+ }
+ else if (ELEM(t->obedit_type, OB_CURVE, OB_SURF)) {
+ createTransCurveVerts(t);
+ }
+ else if (t->obedit_type == OB_LATTICE) {
+ createTransLatticeVerts(t);
+ }
+ else if (t->obedit_type == OB_MBALL) {
+ createTransMBallVerts(t);
+ }
+ else if (t->obedit_type == OB_ARMATURE) {
+ t->flag &= ~T_PROP_EDIT;
+ createTransArmatureVerts(t);
+ }
+ else {
+ printf("edit type not implemented!\n");
+ }
+
+ countAndCleanTransDataContainer(t);
+
+ t->flag |= T_EDIT | T_POINTS;
+
+ if (t->data_len_all && t->flag & T_PROP_EDIT) {
+ if (ELEM(t->obedit_type, OB_CURVE, OB_MESH)) {
+ sort_trans_data(t); // makes selected become first in array
+ if ((t->obedit_type == OB_MESH) && (t->flag & T_PROP_CONNECTED)) {
+ /* already calculated by editmesh_set_connectivity_distance */
+ }
+ else {
+ set_prop_dist(t, 0);
+ }
+ sort_trans_data_dist(t);
+ }
+ else {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+ }
+
+ /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */
+ if (t->mode == TFM_BONESIZE) {
+ t->flag &= ~(T_EDIT | T_POINTS);
+ t->flag |= T_POSE;
+ t->obedit_type = -1;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ tc->poseobj = tc->obedit;
+ tc->obedit = NULL;
+ }
+ }
+ }
+ else if (ob && (ob->mode & OB_MODE_POSE)) {
+ // XXX this is currently limited to active armature only...
+ // XXX active-layer checking isn't done as that should probably be checked through context instead
+
+ /* Multi object editing. */
+ initTransDataContainers_FromObjectData(t, ob, NULL, 0);
+ createTransPose(t);
+ countAndCleanTransDataContainer(t);
+ }
+ else if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && !(t->options & CTX_PAINT_CURVE)) {
+ /* 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);
+ 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) {
+ View3D *v3d = t->view;
+ if (BASE_VISIBLE(v3d, base_arm)) {
+ Object *objects[1];
+ objects[0] = ob_armature;
+ uint objects_len = 1;
+ initTransDataContainers_FromObjectData(t, ob_armature, objects, objects_len);
+ createTransPose(t);
+ countAndCleanTransDataContainer(t);
+ has_transform_context = true;
+ }
+ }
+ }
+ }
+ else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_start_edit(PE_get_current(scene, ob))) {
+ createTransParticleVerts(C, t);
+ countAndCleanTransDataContainer(t);
+ t->flag |= T_POINTS;
+
+ if (t->data_len_all && t->flag & T_PROP_EDIT) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+ }
+ else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
+ if ((t->options & CTX_PAINT_CURVE) && !ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
+ t->flag |= T_POINTS | T_2D_EDIT;
+ createTransPaintCurveVerts(C, t);
+ countAndCleanTransDataContainer(t);
+ }
+ else {
+ has_transform_context = false;
+ }
+ }
+ else if ((ob) &&
+ (ELEM(
+ ob->mode, OB_MODE_PAINT_GPENCIL, OB_MODE_SCULPT_GPENCIL, OB_MODE_WEIGHT_GPENCIL))) {
+ /* In grease pencil all transformations must be canceled if not Object or Edit. */
+ has_transform_context = false;
+ }
+ else {
+ createTransObject(C, t);
+ countAndCleanTransDataContainer(t);
+ t->flag |= T_OBJECT;
+
+ if (t->data_len_all && t->flag & T_PROP_EDIT) {
+ // selected objects are already first, no need to presort
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+
+ /* Check if we're transforming the camera from the camera */
+ if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) {
+ View3D *v3d = t->view;
+ RegionView3D *rv3d = t->ar->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;
+ }
+ }
+ }
+ }
+
+ /* Check that 'countAndCleanTransDataContainer' ran. */
+ if (has_transform_context) {
+ BLI_assert(t->data_len_all != -1);
+ }
+ else {
+ BLI_assert(t->data_len_all == -1);
+ t->data_len_all = 0;
+ }
+
+ BLI_assert((!(t->flag & T_EDIT)) == (!(t->obedit_type != -1)));
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 0f7992e0b4a..46e8447efc6 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -113,1063 +113,1070 @@
void getViewVector(const TransInfo *t, const float coord[3], float vec[3])
{
- if (t->persp != RV3D_ORTHO) {
- sub_v3_v3v3(vec, coord, t->viewinv[3]);
- }
- else {
- copy_v3_v3(vec, t->viewinv[2]);
- }
- normalize_v3(vec);
+ if (t->persp != RV3D_ORTHO) {
+ sub_v3_v3v3(vec, coord, t->viewinv[3]);
+ }
+ else {
+ copy_v3_v3(vec, t->viewinv[2]);
+ }
+ normalize_v3(vec);
}
/* ************************** GENERICS **************************** */
-
static void clipMirrorModifier(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- Object *ob = tc->obedit;
- ModifierData *md = ob->modifiers.first;
- float tolerance[3] = {0.0f, 0.0f, 0.0f};
- int axis = 0;
-
- for (; md; md = md->next) {
- if ((md->type == eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
- MirrorModifierData *mmd = (MirrorModifierData *) md;
-
- if (mmd->flag & MOD_MIR_CLIPPING) {
- axis = 0;
- if (mmd->flag & MOD_MIR_AXIS_X) {
- axis |= 1;
- tolerance[0] = mmd->tolerance;
- }
- if (mmd->flag & MOD_MIR_AXIS_Y) {
- axis |= 2;
- tolerance[1] = mmd->tolerance;
- }
- if (mmd->flag & MOD_MIR_AXIS_Z) {
- axis |= 4;
- tolerance[2] = mmd->tolerance;
- }
- if (axis) {
- float mtx[4][4], imtx[4][4];
- int i;
-
- if (mmd->mirror_ob) {
- float obinv[4][4];
-
- invert_m4_m4(obinv, mmd->mirror_ob->obmat);
- mul_m4_m4m4(mtx, obinv, ob->obmat);
- invert_m4_m4(imtx, mtx);
- }
-
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- int clip;
- float loc[3], iloc[3];
-
- if (td->flag & TD_NOACTION)
- break;
- if (td->loc == NULL)
- break;
-
- if (td->flag & TD_SKIP)
- continue;
-
- copy_v3_v3(loc, td->loc);
- copy_v3_v3(iloc, td->iloc);
-
- if (mmd->mirror_ob) {
- mul_m4_v3(mtx, loc);
- mul_m4_v3(mtx, iloc);
- }
-
- clip = 0;
- if (axis & 1) {
- if (fabsf(iloc[0]) <= tolerance[0] ||
- loc[0] * iloc[0] < 0.0f)
- {
- loc[0] = 0.0f;
- clip = 1;
- }
- }
-
- if (axis & 2) {
- if (fabsf(iloc[1]) <= tolerance[1] ||
- loc[1] * iloc[1] < 0.0f)
- {
- loc[1] = 0.0f;
- clip = 1;
- }
- }
- if (axis & 4) {
- if (fabsf(iloc[2]) <= tolerance[2] ||
- loc[2] * iloc[2] < 0.0f)
- {
- loc[2] = 0.0f;
- clip = 1;
- }
- }
- if (clip) {
- if (mmd->mirror_ob) {
- mul_m4_v3(imtx, loc);
- }
- copy_v3_v3(td->loc, loc);
- }
- }
- }
-
- }
- }
- }
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ Object *ob = tc->obedit;
+ ModifierData *md = ob->modifiers.first;
+ float tolerance[3] = {0.0f, 0.0f, 0.0f};
+ int axis = 0;
+
+ for (; md; md = md->next) {
+ if ((md->type == eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
+ MirrorModifierData *mmd = (MirrorModifierData *)md;
+
+ if (mmd->flag & MOD_MIR_CLIPPING) {
+ axis = 0;
+ if (mmd->flag & MOD_MIR_AXIS_X) {
+ axis |= 1;
+ tolerance[0] = mmd->tolerance;
+ }
+ if (mmd->flag & MOD_MIR_AXIS_Y) {
+ axis |= 2;
+ tolerance[1] = mmd->tolerance;
+ }
+ if (mmd->flag & MOD_MIR_AXIS_Z) {
+ axis |= 4;
+ tolerance[2] = mmd->tolerance;
+ }
+ if (axis) {
+ float mtx[4][4], imtx[4][4];
+ int i;
+
+ if (mmd->mirror_ob) {
+ float obinv[4][4];
+
+ invert_m4_m4(obinv, mmd->mirror_ob->obmat);
+ mul_m4_m4m4(mtx, obinv, ob->obmat);
+ invert_m4_m4(imtx, mtx);
+ }
+
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ int clip;
+ float loc[3], iloc[3];
+
+ if (td->flag & TD_NOACTION)
+ break;
+ if (td->loc == NULL)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ copy_v3_v3(loc, td->loc);
+ copy_v3_v3(iloc, td->iloc);
+
+ if (mmd->mirror_ob) {
+ mul_m4_v3(mtx, loc);
+ mul_m4_v3(mtx, iloc);
+ }
+
+ clip = 0;
+ if (axis & 1) {
+ if (fabsf(iloc[0]) <= tolerance[0] || loc[0] * iloc[0] < 0.0f) {
+ loc[0] = 0.0f;
+ clip = 1;
+ }
+ }
+
+ if (axis & 2) {
+ if (fabsf(iloc[1]) <= tolerance[1] || loc[1] * iloc[1] < 0.0f) {
+ loc[1] = 0.0f;
+ clip = 1;
+ }
+ }
+ if (axis & 4) {
+ if (fabsf(iloc[2]) <= tolerance[2] || loc[2] * iloc[2] < 0.0f) {
+ loc[2] = 0.0f;
+ clip = 1;
+ }
+ }
+ if (clip) {
+ if (mmd->mirror_ob) {
+ mul_m4_v3(imtx, loc);
+ }
+ copy_v3_v3(td->loc, loc);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
/* assumes obedit set to mesh object */
static void editbmesh_apply_to_mirror(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- if (tc->mirror.axis_flag) {
- TransData *td = tc->data;
- BMVert *eve;
- int i;
-
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
- if (td->loc == NULL)
- break;
- if (td->flag & TD_SKIP)
- continue;
-
- eve = td->extra;
- if (eve) {
- eve->co[0] = -td->loc[0];
- eve->co[1] = td->loc[1];
- eve->co[2] = td->loc[2];
- }
-
- if (td->flag & TD_MIRROR_EDGE) {
- td->loc[0] = 0;
- }
- }
- }
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ if (tc->mirror.axis_flag) {
+ TransData *td = tc->data;
+ BMVert *eve;
+ int i;
+
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+ if (td->loc == NULL)
+ break;
+ if (td->flag & TD_SKIP)
+ continue;
+
+ eve = td->extra;
+ if (eve) {
+ eve->co[0] = -td->loc[0];
+ eve->co[1] = td->loc[1];
+ eve->co[2] = td->loc[2];
+ }
+
+ if (td->flag & TD_MIRROR_EDGE) {
+ td->loc[0] = 0;
+ }
+ }
+ }
+ }
}
/* for the realtime animation recording feature, handle overlapping data */
static void animrecord_check_state(Scene *scene, ID *id, wmTimer *animtimer)
{
- ScreenAnimData *sad = (animtimer) ? animtimer->customdata : NULL;
-
- /* sanity checks */
- if (ELEM(NULL, scene, id, sad))
- return;
-
- /* check if we need a new strip if:
- * - if animtimer is running
- * - we're not only keying for available channels
- * - the option to add new actions for each round is not enabled
- */
- if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL) == 0 && (scene->toolsettings->autokey_flag & ANIMRECORD_FLAG_WITHNLA)) {
- /* if playback has just looped around,
- * we need to add a new NLA track+strip to allow a clean pass to occur */
- if ((sad) && (sad->flag & ANIMPLAY_FLAG_JUMPED)) {
- AnimData *adt = BKE_animdata_from_id(id);
- const bool is_first = (adt) && (adt->nla_tracks.first == NULL);
-
- /* perform push-down manually with some differences
- * NOTE: BKE_nla_action_pushdown() sync warning...
- */
- if ((adt->action) && !(adt->flag & ADT_NLA_EDIT_ON)) {
- float astart, aend;
-
- /* only push down if action is more than 1-2 frames long */
- calc_action_range(adt->action, &astart, &aend, 1);
- if (aend > astart + 2.0f) {
- NlaStrip *strip = BKE_nlastack_add_strip(adt, adt->action);
-
- /* clear reference to action now that we've pushed it onto the stack */
- id_us_min(&adt->action->id);
- adt->action = NULL;
-
- /* adjust blending + extend so that they will behave correctly */
- strip->extendmode = NLASTRIP_EXTEND_NOTHING;
- strip->flag &= ~(NLASTRIP_FLAG_AUTO_BLENDS | NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_ACTIVE);
-
- /* copy current "action blending" settings from adt to the strip,
- * as it was keyframed with these settings, so omitting them will
- * change the effect [T54766]
- */
- if (is_first == false) {
- strip->blendmode = adt->act_blendmode;
- strip->influence = adt->act_influence;
-
- if (adt->act_influence < 1.0f) {
- /* enable "user-controlled" influence (which will insert a default keyframe)
- * so that the influence doesn't get lost on the new update
- *
- * NOTE: An alternative way would have been to instead hack the influence
- * to not get always get reset to full strength if NLASTRIP_FLAG_USR_INFLUENCE
- * is disabled but auto-blending isn't being used. However, that approach
- * is a bit hacky/hard to discover, and may cause backwards compatibility issues,
- * so it's better to just do it this way.
- */
- strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
- BKE_nlastrip_validate_fcurves(strip);
- }
- }
-
- /* also, adjust the AnimData's action extend mode to be on
- * 'nothing' so that previous result still play
- */
- adt->act_extendmode = NLASTRIP_EXTEND_NOTHING;
- }
- }
- }
- }
+ ScreenAnimData *sad = (animtimer) ? animtimer->customdata : NULL;
+
+ /* sanity checks */
+ if (ELEM(NULL, scene, id, sad))
+ return;
+
+ /* check if we need a new strip if:
+ * - if animtimer is running
+ * - we're not only keying for available channels
+ * - the option to add new actions for each round is not enabled
+ */
+ if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL) == 0 &&
+ (scene->toolsettings->autokey_flag & ANIMRECORD_FLAG_WITHNLA)) {
+ /* if playback has just looped around,
+ * we need to add a new NLA track+strip to allow a clean pass to occur */
+ if ((sad) && (sad->flag & ANIMPLAY_FLAG_JUMPED)) {
+ AnimData *adt = BKE_animdata_from_id(id);
+ const bool is_first = (adt) && (adt->nla_tracks.first == NULL);
+
+ /* perform push-down manually with some differences
+ * NOTE: BKE_nla_action_pushdown() sync warning...
+ */
+ if ((adt->action) && !(adt->flag & ADT_NLA_EDIT_ON)) {
+ float astart, aend;
+
+ /* only push down if action is more than 1-2 frames long */
+ calc_action_range(adt->action, &astart, &aend, 1);
+ if (aend > astart + 2.0f) {
+ NlaStrip *strip = BKE_nlastack_add_strip(adt, adt->action);
+
+ /* clear reference to action now that we've pushed it onto the stack */
+ id_us_min(&adt->action->id);
+ adt->action = NULL;
+
+ /* adjust blending + extend so that they will behave correctly */
+ strip->extendmode = NLASTRIP_EXTEND_NOTHING;
+ strip->flag &= ~(NLASTRIP_FLAG_AUTO_BLENDS | NLASTRIP_FLAG_SELECT |
+ NLASTRIP_FLAG_ACTIVE);
+
+ /* copy current "action blending" settings from adt to the strip,
+ * as it was keyframed with these settings, so omitting them will
+ * change the effect [T54766]
+ */
+ if (is_first == false) {
+ strip->blendmode = adt->act_blendmode;
+ strip->influence = adt->act_influence;
+
+ if (adt->act_influence < 1.0f) {
+ /* enable "user-controlled" influence (which will insert a default keyframe)
+ * so that the influence doesn't get lost on the new update
+ *
+ * NOTE: An alternative way would have been to instead hack the influence
+ * to not get always get reset to full strength if NLASTRIP_FLAG_USR_INFLUENCE
+ * is disabled but auto-blending isn't being used. However, that approach
+ * is a bit hacky/hard to discover, and may cause backwards compatibility issues,
+ * so it's better to just do it this way.
+ */
+ strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
+ BKE_nlastrip_validate_fcurves(strip);
+ }
+ }
+
+ /* also, adjust the AnimData's action extend mode to be on
+ * 'nothing' so that previous result still play
+ */
+ adt->act_extendmode = NLASTRIP_EXTEND_NOTHING;
+ }
+ }
+ }
+ }
}
static bool fcu_test_selected(FCurve *fcu)
{
- BezTriple *bezt = fcu->bezt;
- unsigned int i;
+ BezTriple *bezt = fcu->bezt;
+ unsigned int i;
- if (bezt == NULL) /* ignore baked */
- return 0;
+ if (bezt == NULL) /* ignore baked */
+ return 0;
- for (i = 0; i < fcu->totvert; i++, bezt++) {
- if (BEZT_ISSEL_ANY(bezt)) return 1;
- }
+ for (i = 0; i < fcu->totvert; i++, bezt++) {
+ if (BEZT_ISSEL_ANY(bezt))
+ return 1;
+ }
- return 0;
+ return 0;
}
/* helper for recalcData() - for Action Editor transforms */
static void recalcData_actedit(TransInfo *t)
{
- ViewLayer *view_layer = t->view_layer;
- SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
-
- bAnimContext ac = {NULL};
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* initialize relevant anim-context 'context' data from TransInfo data */
- /* NOTE: sync this with the code in ANIM_animdata_get_context() */
- ac.bmain = CTX_data_main(t->context);
- 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;
-
- ANIM_animdata_context_getdata(&ac);
-
- /* perform flush */
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
- /* flush transform values back to actual coordinates */
- flushTransIntFrameActionData(t);
- }
-
- if (ac.datatype != ANIMCONT_MASK) {
- /* get animdata blocks visible in editor, assuming that these will be the ones where things changed */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* just tag these animdata-blocks to recalc, assuming that some data there changed
- * BUT only do this if realtime updates are enabled
- */
- if ((saction->flag & SACTION_NOREALTIMEUPDATES) == 0) {
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* set refresh tags for objects using this animation */
- ANIM_list_elem_update(CTX_data_main(t->context), t->scene, ale);
- }
- }
-
- /* now free temp channels */
- ANIM_animdata_freelist(&anim_data);
- }
+ ViewLayer *view_layer = t->view_layer;
+ SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
+
+ bAnimContext ac = {NULL};
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* initialize relevant anim-context 'context' data from TransInfo data */
+ /* NOTE: sync this with the code in ANIM_animdata_get_context() */
+ ac.bmain = CTX_data_main(t->context);
+ 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;
+
+ ANIM_animdata_context_getdata(&ac);
+
+ /* perform flush */
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ /* flush transform values back to actual coordinates */
+ flushTransIntFrameActionData(t);
+ }
+
+ if (ac.datatype != ANIMCONT_MASK) {
+ /* get animdata blocks visible in editor, assuming that these will be the ones where things changed */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* just tag these animdata-blocks to recalc, assuming that some data there changed
+ * BUT only do this if realtime updates are enabled
+ */
+ if ((saction->flag & SACTION_NOREALTIMEUPDATES) == 0) {
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* set refresh tags for objects using this animation */
+ ANIM_list_elem_update(CTX_data_main(t->context), t->scene, ale);
+ }
+ }
+
+ /* now free temp channels */
+ ANIM_animdata_freelist(&anim_data);
+ }
}
/* helper for recalcData() - for Graph Editor transforms */
static void recalcData_graphedit(TransInfo *t)
{
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
- ViewLayer *view_layer = t->view_layer;
-
- ListBase anim_data = {NULL, NULL};
- bAnimContext ac = {NULL};
- int filter;
-
- bAnimListElem *ale;
- int dosort = 0;
-
- /* initialize relevant anim-context 'context' data from TransInfo data */
- /* NOTE: sync this with the code in ANIM_animdata_get_context() */
- ac.bmain = CTX_data_main(t->context);
- 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;
-
- ANIM_animdata_context_getdata(&ac);
-
- /* do the flush first */
- flushTransGraphData(t);
-
- /* get curves to check if a re-sort is needed */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* now test if there is a need to re-sort */
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
-
- /* ignore FC-Curves without any selected verts */
- if (!fcu_test_selected(fcu))
- continue;
-
- /* watch it: if the time is wrong: do not correct handles yet */
- if (test_time_fcurve(fcu))
- dosort++;
- else
- calchandles_fcurve(fcu);
-
- /* set refresh tags for objects using this animation,
- * BUT only if realtime updates are enabled
- */
- if ((sipo->flag & SIPO_NOREALTIMEUPDATES) == 0)
- ANIM_list_elem_update(CTX_data_main(t->context), t->scene, ale);
- }
-
- /* do resort and other updates? */
- if (dosort) remake_graph_transdata(t, &anim_data);
-
- /* now free temp channels */
- ANIM_animdata_freelist(&anim_data);
+ SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ ViewLayer *view_layer = t->view_layer;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimContext ac = {NULL};
+ int filter;
+
+ bAnimListElem *ale;
+ int dosort = 0;
+
+ /* initialize relevant anim-context 'context' data from TransInfo data */
+ /* NOTE: sync this with the code in ANIM_animdata_get_context() */
+ ac.bmain = CTX_data_main(t->context);
+ 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;
+
+ ANIM_animdata_context_getdata(&ac);
+
+ /* do the flush first */
+ flushTransGraphData(t);
+
+ /* get curves to check if a re-sort is needed */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* now test if there is a need to re-sort */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
+
+ /* ignore FC-Curves without any selected verts */
+ if (!fcu_test_selected(fcu))
+ continue;
+
+ /* watch it: if the time is wrong: do not correct handles yet */
+ if (test_time_fcurve(fcu))
+ dosort++;
+ else
+ calchandles_fcurve(fcu);
+
+ /* set refresh tags for objects using this animation,
+ * BUT only if realtime updates are enabled
+ */
+ if ((sipo->flag & SIPO_NOREALTIMEUPDATES) == 0)
+ ANIM_list_elem_update(CTX_data_main(t->context), t->scene, ale);
+ }
+
+ /* do resort and other updates? */
+ if (dosort)
+ remake_graph_transdata(t, &anim_data);
+
+ /* now free temp channels */
+ ANIM_animdata_freelist(&anim_data);
}
/* helper for recalcData() - for NLA Editor transforms */
static void recalcData_nla(TransInfo *t)
{
- SpaceNla *snla = (SpaceNla *)t->sa->spacedata.first;
- Scene *scene = t->scene;
- double secf = FPS;
- int i;
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- TransDataNla *tdn = tc->custom.type.data;
-
- /* for each strip we've got, perform some additional validation of the values that got set before
- * using RNA to set the value (which does some special operations when setting these values to make
- * sure that everything works ok)
- */
- for (i = 0; i < tc->data_len; i++, tdn++) {
- NlaStrip *strip = tdn->strip;
- PointerRNA strip_ptr;
- short pExceeded, nExceeded, iter;
- int delta_y1, delta_y2;
-
- /* if this tdn has no handles, that means it is just a dummy that should be skipped */
- if (tdn->handle == 0)
- continue;
-
- /* set refresh tags for objects using this animation,
- * BUT only if realtime updates are enabled
- */
- if ((snla->flag & SNLA_NOREALTIMEUPDATES) == 0)
- ANIM_id_update(CTX_data_main(t->context), tdn->id);
-
- /* if canceling transform, just write the values without validating, then move on */
- if (t->state == TRANS_CANCEL) {
- /* clear the values by directly overwriting the originals, but also need to restore
- * endpoints of neighboring transition-strips
- */
-
- /* start */
- strip->start = tdn->h1[0];
-
- if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION))
- strip->prev->end = tdn->h1[0];
-
- /* end */
- strip->end = tdn->h2[0];
-
- if ((strip->next) && (strip->next->type == NLASTRIP_TYPE_TRANSITION))
- strip->next->start = tdn->h2[0];
-
- /* flush transforms to child strips (since this should be a meta) */
- BKE_nlameta_flush_transforms(strip);
-
- /* restore to original track (if needed) */
- if (tdn->oldTrack != tdn->nlt) {
- /* just append to end of list for now, since strips get sorted in special_aftertrans_update() */
- BLI_remlink(&tdn->nlt->strips, strip);
- BLI_addtail(&tdn->oldTrack->strips, strip);
- }
-
- continue;
- }
-
- /* firstly, check if the proposed transform locations would overlap with any neighboring strips
- * (barring transitions) which are absolute barriers since they are not being moved
- *
- * this is done as a iterative procedure (done 5 times max for now)
- */
- for (iter = 0; iter < 5; iter++) {
- pExceeded = ((strip->prev) && (strip->prev->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h1[0] < strip->prev->end));
- nExceeded = ((strip->next) && (strip->next->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h2[0] > strip->next->start));
-
- if ((pExceeded && nExceeded) || (iter == 4)) {
- /* both endpoints exceeded (or iteration ping-pong'd meaning that we need a compromise)
- * - simply crop strip to fit within the bounds of the strips bounding it
- * - if there were no neighbors, clear the transforms (make it default to the strip's current values)
- */
- if (strip->prev && strip->next) {
- tdn->h1[0] = strip->prev->end;
- tdn->h2[0] = strip->next->start;
- }
- else {
- tdn->h1[0] = strip->start;
- tdn->h2[0] = strip->end;
- }
- }
- else if (nExceeded) {
- /* move backwards */
- float offset = tdn->h2[0] - strip->next->start;
-
- tdn->h1[0] -= offset;
- tdn->h2[0] -= offset;
- }
- else if (pExceeded) {
- /* more forwards */
- float offset = strip->prev->end - tdn->h1[0];
-
- tdn->h1[0] += offset;
- tdn->h2[0] += offset;
- }
- else /* all is fine and well */
- break;
- }
-
- /* handle auto-snapping
- * NOTE: only do this when transform is still running, or we can't restore
- */
- if (t->state != TRANS_CANCEL) {
- switch (snla->autosnap) {
- case SACTSNAP_FRAME: /* snap to nearest frame */
- case SACTSNAP_STEP: /* frame step - this is basically the same,
- * since we don't have any remapping going on */
- {
- tdn->h1[0] = floorf(tdn->h1[0] + 0.5f);
- tdn->h2[0] = floorf(tdn->h2[0] + 0.5f);
- break;
- }
-
- case SACTSNAP_SECOND: /* snap to nearest second */
- case SACTSNAP_TSTEP: /* second step - this is basically the same,
- * since we don't have any remapping going on */
- {
- /* This case behaves differently from the rest, since lengths of strips
- * may not be multiples of a second. If we just naively resize adjust
- * the handles, things may not work correctly. Instead, we only snap
- * the first handle, and move the other to fit.
- *
- * FIXME: we do run into problems here when user attempts to negatively
- * scale the strip, as it then just compresses down and refuses
- * to expand out the other end.
- */
- float h1_new = (float)(floor(((double)tdn->h1[0] / secf) + 0.5) * secf);
- float delta = h1_new - tdn->h1[0];
-
- tdn->h1[0] = h1_new;
- tdn->h2[0] += delta;
- break;
- }
-
- case SACTSNAP_MARKER: /* snap to nearest marker */
- {
- tdn->h1[0] = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h1[0]);
- tdn->h2[0] = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h2[0]);
- break;
- }
- }
- }
-
- /* Use RNA to write the values to ensure that constraints on these are obeyed
- * (e.g. for transition strips, the values are taken from the neighbors)
- *
- * NOTE: we write these twice to avoid truncation errors which can arise when
- * moving the strips a large distance using numeric input [#33852]
- */
- RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
-
- RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
- RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
-
- RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
- RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
-
- /* flush transforms to child strips (since this should be a meta) */
- BKE_nlameta_flush_transforms(strip);
-
-
- /* now, check if we need to try and move track
- * - we need to calculate both, as only one may have been altered by transform if only 1 handle moved
- */
- delta_y1 = ((int)tdn->h1[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
- delta_y2 = ((int)tdn->h2[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
-
- if (delta_y1 || delta_y2) {
- NlaTrack *track;
- int delta = (delta_y2) ? delta_y2 : delta_y1;
- int n;
-
- /* move in the requested direction, checking at each layer if there's space for strip to pass through,
- * stopping on the last track available or that we're able to fit in
- */
- if (delta > 0) {
- for (track = tdn->nlt->next, n = 0; (track) && (n < delta); track = track->next, n++) {
- /* check if space in this track for the strip */
- if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
- /* move strip to this track */
- BLI_remlink(&tdn->nlt->strips, strip);
- BKE_nlatrack_add_strip(track, strip);
-
- tdn->nlt = track;
- tdn->trackIndex++;
- }
- else /* can't move any further */
- break;
- }
- }
- else {
- /* make delta 'positive' before using it, since we now know to go backwards */
- delta = -delta;
-
- for (track = tdn->nlt->prev, n = 0; (track) && (n < delta); track = track->prev, n++) {
- /* check if space in this track for the strip */
- if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
- /* move strip to this track */
- BLI_remlink(&tdn->nlt->strips, strip);
- BKE_nlatrack_add_strip(track, strip);
-
- tdn->nlt = track;
- tdn->trackIndex--;
- }
- else /* can't move any further */
- break;
- }
- }
- }
- }
+ SpaceNla *snla = (SpaceNla *)t->sa->spacedata.first;
+ Scene *scene = t->scene;
+ double secf = FPS;
+ int i;
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ TransDataNla *tdn = tc->custom.type.data;
+
+ /* for each strip we've got, perform some additional validation of the values that got set before
+ * using RNA to set the value (which does some special operations when setting these values to make
+ * sure that everything works ok)
+ */
+ for (i = 0; i < tc->data_len; i++, tdn++) {
+ NlaStrip *strip = tdn->strip;
+ PointerRNA strip_ptr;
+ short pExceeded, nExceeded, iter;
+ int delta_y1, delta_y2;
+
+ /* if this tdn has no handles, that means it is just a dummy that should be skipped */
+ if (tdn->handle == 0)
+ continue;
+
+ /* set refresh tags for objects using this animation,
+ * BUT only if realtime updates are enabled
+ */
+ if ((snla->flag & SNLA_NOREALTIMEUPDATES) == 0)
+ ANIM_id_update(CTX_data_main(t->context), tdn->id);
+
+ /* if canceling transform, just write the values without validating, then move on */
+ if (t->state == TRANS_CANCEL) {
+ /* clear the values by directly overwriting the originals, but also need to restore
+ * endpoints of neighboring transition-strips
+ */
+
+ /* start */
+ strip->start = tdn->h1[0];
+
+ if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION))
+ strip->prev->end = tdn->h1[0];
+
+ /* end */
+ strip->end = tdn->h2[0];
+
+ if ((strip->next) && (strip->next->type == NLASTRIP_TYPE_TRANSITION))
+ strip->next->start = tdn->h2[0];
+
+ /* flush transforms to child strips (since this should be a meta) */
+ BKE_nlameta_flush_transforms(strip);
+
+ /* restore to original track (if needed) */
+ if (tdn->oldTrack != tdn->nlt) {
+ /* just append to end of list for now, since strips get sorted in special_aftertrans_update() */
+ BLI_remlink(&tdn->nlt->strips, strip);
+ BLI_addtail(&tdn->oldTrack->strips, strip);
+ }
+
+ continue;
+ }
+
+ /* firstly, check if the proposed transform locations would overlap with any neighboring strips
+ * (barring transitions) which are absolute barriers since they are not being moved
+ *
+ * this is done as a iterative procedure (done 5 times max for now)
+ */
+ for (iter = 0; iter < 5; iter++) {
+ pExceeded = ((strip->prev) && (strip->prev->type != NLASTRIP_TYPE_TRANSITION) &&
+ (tdn->h1[0] < strip->prev->end));
+ nExceeded = ((strip->next) && (strip->next->type != NLASTRIP_TYPE_TRANSITION) &&
+ (tdn->h2[0] > strip->next->start));
+
+ if ((pExceeded && nExceeded) || (iter == 4)) {
+ /* both endpoints exceeded (or iteration ping-pong'd meaning that we need a compromise)
+ * - simply crop strip to fit within the bounds of the strips bounding it
+ * - if there were no neighbors, clear the transforms (make it default to the strip's current values)
+ */
+ if (strip->prev && strip->next) {
+ tdn->h1[0] = strip->prev->end;
+ tdn->h2[0] = strip->next->start;
+ }
+ else {
+ tdn->h1[0] = strip->start;
+ tdn->h2[0] = strip->end;
+ }
+ }
+ else if (nExceeded) {
+ /* move backwards */
+ float offset = tdn->h2[0] - strip->next->start;
+
+ tdn->h1[0] -= offset;
+ tdn->h2[0] -= offset;
+ }
+ else if (pExceeded) {
+ /* more forwards */
+ float offset = strip->prev->end - tdn->h1[0];
+
+ tdn->h1[0] += offset;
+ tdn->h2[0] += offset;
+ }
+ else /* all is fine and well */
+ break;
+ }
+
+ /* handle auto-snapping
+ * NOTE: only do this when transform is still running, or we can't restore
+ */
+ if (t->state != TRANS_CANCEL) {
+ switch (snla->autosnap) {
+ case SACTSNAP_FRAME: /* snap to nearest frame */
+ case SACTSNAP_STEP: /* frame step - this is basically the same,
+ * since we don't have any remapping going on */
+ {
+ tdn->h1[0] = floorf(tdn->h1[0] + 0.5f);
+ tdn->h2[0] = floorf(tdn->h2[0] + 0.5f);
+ break;
+ }
+
+ case SACTSNAP_SECOND: /* snap to nearest second */
+ case SACTSNAP_TSTEP: /* second step - this is basically the same,
+ * since we don't have any remapping going on */
+ {
+ /* This case behaves differently from the rest, since lengths of strips
+ * may not be multiples of a second. If we just naively resize adjust
+ * the handles, things may not work correctly. Instead, we only snap
+ * the first handle, and move the other to fit.
+ *
+ * FIXME: we do run into problems here when user attempts to negatively
+ * scale the strip, as it then just compresses down and refuses
+ * to expand out the other end.
+ */
+ float h1_new = (float)(floor(((double)tdn->h1[0] / secf) + 0.5) * secf);
+ float delta = h1_new - tdn->h1[0];
+
+ tdn->h1[0] = h1_new;
+ tdn->h2[0] += delta;
+ break;
+ }
+
+ case SACTSNAP_MARKER: /* snap to nearest marker */
+ {
+ tdn->h1[0] = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h1[0]);
+ tdn->h2[0] = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h2[0]);
+ break;
+ }
+ }
+ }
+
+ /* Use RNA to write the values to ensure that constraints on these are obeyed
+ * (e.g. for transition strips, the values are taken from the neighbors)
+ *
+ * NOTE: we write these twice to avoid truncation errors which can arise when
+ * moving the strips a large distance using numeric input [#33852]
+ */
+ RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
+
+ RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
+ RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
+
+ RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
+ RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
+
+ /* flush transforms to child strips (since this should be a meta) */
+ BKE_nlameta_flush_transforms(strip);
+
+ /* now, check if we need to try and move track
+ * - we need to calculate both, as only one may have been altered by transform if only 1 handle moved
+ */
+ delta_y1 = ((int)tdn->h1[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
+ delta_y2 = ((int)tdn->h2[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
+
+ if (delta_y1 || delta_y2) {
+ NlaTrack *track;
+ int delta = (delta_y2) ? delta_y2 : delta_y1;
+ int n;
+
+ /* move in the requested direction, checking at each layer if there's space for strip to pass through,
+ * stopping on the last track available or that we're able to fit in
+ */
+ if (delta > 0) {
+ for (track = tdn->nlt->next, n = 0; (track) && (n < delta); track = track->next, n++) {
+ /* check if space in this track for the strip */
+ if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
+ /* move strip to this track */
+ BLI_remlink(&tdn->nlt->strips, strip);
+ BKE_nlatrack_add_strip(track, strip);
+
+ tdn->nlt = track;
+ tdn->trackIndex++;
+ }
+ else /* can't move any further */
+ break;
+ }
+ }
+ else {
+ /* make delta 'positive' before using it, since we now know to go backwards */
+ delta = -delta;
+
+ for (track = tdn->nlt->prev, n = 0; (track) && (n < delta); track = track->prev, n++) {
+ /* check if space in this track for the strip */
+ if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
+ /* move strip to this track */
+ BLI_remlink(&tdn->nlt->strips, strip);
+ BKE_nlatrack_add_strip(track, strip);
+
+ tdn->nlt = track;
+ tdn->trackIndex--;
+ }
+ else /* can't move any further */
+ break;
+ }
+ }
+ }
+ }
}
static void recalcData_mask_common(TransInfo *t)
{
- Mask *mask = CTX_data_edit_mask(t->context);
+ Mask *mask = CTX_data_edit_mask(t->context);
- flushTransMasking(t);
+ flushTransMasking(t);
- DEG_id_tag_update(&mask->id, 0);
+ DEG_id_tag_update(&mask->id, 0);
}
/* helper for recalcData() - for Image Editor transforms */
static void recalcData_image(TransInfo *t)
{
- if (t->options & CTX_MASK) {
- recalcData_mask_common(t);
- }
- else if (t->options & CTX_PAINT_CURVE) {
- flushTransPaintCurve(t);
- }
- else if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
- SpaceImage *sima = t->sa->spacedata.first;
-
- flushTransUVs(t);
- if (sima->flag & SI_LIVE_UNWRAP)
- ED_uvedit_live_unwrap_re_solve();
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- if (tc->data_len) {
- DEG_id_tag_update(tc->obedit->data, 0);
- }
- }
- }
+ if (t->options & CTX_MASK) {
+ recalcData_mask_common(t);
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ flushTransPaintCurve(t);
+ }
+ else if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
+ SpaceImage *sima = t->sa->spacedata.first;
+
+ flushTransUVs(t);
+ if (sima->flag & SI_LIVE_UNWRAP)
+ ED_uvedit_live_unwrap_re_solve();
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ if (tc->data_len) {
+ DEG_id_tag_update(tc->obedit->data, 0);
+ }
+ }
+ }
}
/* helper for recalcData() - for Movie Clip transforms */
static void recalcData_spaceclip(TransInfo *t)
{
- SpaceClip *sc = t->sa->spacedata.first;
-
- if (ED_space_clip_check_show_trackedit(sc)) {
- MovieClip *clip = ED_space_clip_get_clip(sc);
- ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
- MovieTrackingTrack *track;
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- flushTransTracking(t);
-
- track = tracksbase->first;
- while (track) {
- if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
-
- if (t->mode == TFM_TRANSLATION) {
- if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
- BKE_tracking_marker_clamp(marker, CLAMP_PAT_POS);
- if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
- BKE_tracking_marker_clamp(marker, CLAMP_SEARCH_POS);
- }
- else if (t->mode == TFM_RESIZE) {
- if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
- BKE_tracking_marker_clamp(marker, CLAMP_PAT_DIM);
- if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
- BKE_tracking_marker_clamp(marker, CLAMP_SEARCH_DIM);
- }
- else if (t->mode == TFM_ROTATION) {
- if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
- BKE_tracking_marker_clamp(marker, CLAMP_PAT_POS);
- }
- }
-
- track = track->next;
- }
-
- DEG_id_tag_update(&clip->id, 0);
- }
- else if (t->options & CTX_MASK) {
- recalcData_mask_common(t);
- }
+ SpaceClip *sc = t->sa->spacedata.first;
+
+ if (ED_space_clip_check_show_trackedit(sc)) {
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+ MovieTrackingTrack *track;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ flushTransTracking(t);
+
+ track = tracksbase->first;
+ while (track) {
+ if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+
+ if (t->mode == TFM_TRANSLATION) {
+ if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
+ BKE_tracking_marker_clamp(marker, CLAMP_PAT_POS);
+ if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
+ BKE_tracking_marker_clamp(marker, CLAMP_SEARCH_POS);
+ }
+ else if (t->mode == TFM_RESIZE) {
+ if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
+ BKE_tracking_marker_clamp(marker, CLAMP_PAT_DIM);
+ if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
+ BKE_tracking_marker_clamp(marker, CLAMP_SEARCH_DIM);
+ }
+ else if (t->mode == TFM_ROTATION) {
+ if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
+ BKE_tracking_marker_clamp(marker, CLAMP_PAT_POS);
+ }
+ }
+
+ track = track->next;
+ }
+
+ DEG_id_tag_update(&clip->id, 0);
+ }
+ else if (t->options & CTX_MASK) {
+ recalcData_mask_common(t);
+ }
}
/* helper for recalcData() - for object transforms, typically in the 3D view */
static void recalcData_objects(TransInfo *t)
{
- Base *base = t->view_layer->basact;
-
- if (t->obedit_type != -1) {
- if (ELEM(t->obedit_type, OB_CURVE, OB_SURF)) {
-
- if (t->state != TRANS_CANCEL) {
- clipMirrorModifier(t);
- applyProject(t);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- Curve *cu = tc->obedit->data;
- ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- Nurb *nu = nurbs->first;
-
- DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
-
- if (t->state == TRANS_CANCEL) {
- while (nu) {
- /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */
- BKE_nurb_handles_calc(nu);
- nu = nu->next;
- }
- }
- else {
- /* Normal updating */
- while (nu) {
- BKE_nurb_test_2d(nu);
- BKE_nurb_handles_calc(nu);
- nu = nu->next;
- }
- }
- }
- }
- else if (t->obedit_type == OB_LATTICE) {
-
- if (t->state != TRANS_CANCEL) {
- applyProject(t);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- Lattice *la = tc->obedit->data;
- DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
- if (la->editlatt->latt->flag & LT_OUTSIDE) {
- outside_lattice(la->editlatt->latt);
- }
- }
- }
- else if (t->obedit_type == OB_MESH) {
- /* mirror modifier clipping? */
- if (t->state != TRANS_CANCEL) {
- /* apply clipping after so we never project past the clip plane [#25423] */
- applyProject(t);
- clipMirrorModifier(t);
- }
- if ((t->flag & T_NO_MIRROR) == 0 &&
- (t->options & CTX_NO_MIRROR) == 0)
- {
- editbmesh_apply_to_mirror(t);
- }
-
- if (t->mode == TFM_EDGE_SLIDE) {
- projectEdgeSlideData(t, false);
- }
- else if (t->mode == TFM_VERT_SLIDE) {
- projectVertSlideData(t, false);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- EDBM_mesh_normals_update(em);
- BKE_editmesh_tessface_calc(em);
- }
- }
- else if (t->obedit_type == OB_ARMATURE) { /* no recalc flag, does pose */
-
- if (t->state != TRANS_CANCEL) {
- applyProject(t);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- bArmature *arm = tc->obedit->data;
- ListBase *edbo = arm->edbo;
- EditBone *ebo, *ebo_parent;
- TransData *td = tc->data;
- int i;
-
- /* Ensure all bones are correctly adjusted */
- for (ebo = edbo->first; ebo; ebo = ebo->next) {
- ebo_parent = (ebo->flag & BONE_CONNECTED) ? ebo->parent : NULL;
-
- if (ebo_parent) {
- /* If this bone has a parent tip that has been moved */
- if (ebo_parent->flag & BONE_TIPSEL) {
- copy_v3_v3(ebo->head, ebo_parent->tail);
- if (t->mode == TFM_BONE_ENVELOPE) ebo->rad_head = ebo_parent->rad_tail;
- }
- /* If this bone has a parent tip that has NOT been moved */
- else {
- copy_v3_v3(ebo_parent->tail, ebo->head);
- if (t->mode == TFM_BONE_ENVELOPE) ebo_parent->rad_tail = ebo->rad_head;
- }
- }
-
- /* on extrude bones, oldlength==0.0f, so we scale radius of points */
- ebo->length = len_v3v3(ebo->head, ebo->tail);
- if (ebo->oldlength == 0.0f) {
- ebo->rad_head = 0.25f * ebo->length;
- ebo->rad_tail = 0.10f * ebo->length;
- ebo->dist = 0.25f * ebo->length;
- if (ebo->parent) {
- if (ebo->rad_head > ebo->parent->rad_tail)
- ebo->rad_head = ebo->parent->rad_tail;
- }
- }
- else if (t->mode != TFM_BONE_ENVELOPE) {
- /* if bones change length, lets do that for the deform distance as well */
- ebo->dist *= ebo->length / ebo->oldlength;
- ebo->rad_head *= ebo->length / ebo->oldlength;
- ebo->rad_tail *= ebo->length / ebo->oldlength;
- ebo->oldlength = ebo->length;
-
- if (ebo_parent) {
- ebo_parent->rad_tail = ebo->rad_head;
- }
- }
- }
-
- if (!ELEM(t->mode, TFM_BONE_ROLL, TFM_BONE_ENVELOPE, TFM_BONE_ENVELOPE_DIST, TFM_BONESIZE)) {
- /* fix roll */
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->extra) {
- float vec[3], up_axis[3];
- float qrot[4];
- float roll;
-
- ebo = td->extra;
-
- if (t->state == TRANS_CANCEL) {
- /* restore roll */
- ebo->roll = td->ival;
- }
- else {
- copy_v3_v3(up_axis, td->axismtx[2]);
-
- sub_v3_v3v3(vec, ebo->tail, ebo->head);
- normalize_v3(vec);
- rotation_between_vecs_to_quat(qrot, td->axismtx[1], vec);
- mul_qt_v3(qrot, up_axis);
-
- /* roll has a tendency to flip in certain orientations - [#34283], [#33974] */
- roll = ED_armature_ebone_roll_to_vector(ebo, up_axis, false);
- ebo->roll = angle_compat_rad(roll, td->ival);
- }
- }
- }
- }
-
- if (arm->flag & ARM_MIRROR_EDIT) {
- if (t->state != TRANS_CANCEL) {
- ED_armature_edit_transform_mirror_update(tc->obedit);
- }
- else {
- restoreBones(tc);
- }
- }
- }
- }
- else {
- if (t->state != TRANS_CANCEL) {
- applyProject(t);
- }
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- if (tc->data_len) {
- DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
- }
- }
- }
-
- }
- else if (t->flag & T_POSE) {
- GSet *motionpath_updates = BLI_gset_ptr_new("motionpath updates");
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- Object *ob = tc->poseobj;
- bArmature *arm = ob->data;
-
- /* if animtimer is running, and the object already has animation data,
- * check if the auto-record feature means that we should record 'samples'
- * (i.e. un-editable animation values)
- *
- * context is needed for keying set poll() functions.
- */
- // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
- if ((t->animtimer) && (t->context) && IS_AUTOKEY_ON(t->scene)) {
- int targetless_ik = (t->flag & T_AUTOIK); // XXX this currently doesn't work, since flags aren't set yet!
-
- animrecord_check_state(t->scene, &ob->id, t->animtimer);
- autokeyframe_pose(t->context, t->scene, ob, t->mode, targetless_ik);
- }
-
- if (motionpath_need_update_pose(t->scene, ob)) {
- BLI_gset_insert(motionpath_updates, ob);
- }
-
- /* old optimize trick... this enforces to bypass the depgraph */
- if (!(arm->flag & ARM_DELAYDEFORM)) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); /* sets recalc flags */
- /* transformation of pose may affect IK tree, make sure it is rebuilt */
- BIK_clear_data(ob->pose);
- }
- else {
- BKE_pose_where_is(t->depsgraph, t->scene, ob);
- }
- }
-
- /* Update motion paths once for all transformed bones in an object. */
- GSetIterator gs_iter;
- GSET_ITER (gs_iter, motionpath_updates) {
- Object *ob = BLI_gsetIterator_getKey(&gs_iter);
- ED_pose_recalculate_paths(t->context, t->scene, ob, true);
- }
- BLI_gset_free(motionpath_updates, NULL);
- }
- else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) &&
- PE_get_current(t->scene, base->object))
- {
- if (t->state != TRANS_CANCEL) {
- applyProject(t);
- }
- flushTransParticles(t);
- }
- else {
- bool motionpath_update = false;
-
- if (t->state != TRANS_CANCEL) {
- applyProject(t);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
-
- for (int i = 0; i < tc->data_len; i++, td++) {
- Object *ob = td->ob;
-
- if (td->flag & TD_NOACTION)
- break;
-
- if (td->flag & TD_SKIP)
- continue;
-
- /* if animtimer is running, and the object already has animation data,
- * check if the auto-record feature means that we should record 'samples'
- * (i.e. uneditable animation values)
- */
- // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
- if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
- animrecord_check_state(t->scene, &ob->id, t->animtimer);
- autokeyframe_object(t->context, t->scene, t->view_layer, ob, t->mode);
- }
-
- motionpath_update |= motionpath_need_update_object(t->scene, ob);
-
- /* sets recalc flags fully, instead of flushing existing ones
- * otherwise proxies don't function correctly
- */
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
-
- if (t->flag & T_TEXTURE)
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- }
-
- if (motionpath_update) {
- /* Update motion paths once for all transformed objects. */
- ED_objects_recalculate_paths(t->context, t->scene, true);
- }
- }
+ Base *base = t->view_layer->basact;
+
+ if (t->obedit_type != -1) {
+ if (ELEM(t->obedit_type, OB_CURVE, OB_SURF)) {
+
+ if (t->state != TRANS_CANCEL) {
+ clipMirrorModifier(t);
+ applyProject(t);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ Curve *cu = tc->obedit->data;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+ Nurb *nu = nurbs->first;
+
+ DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
+
+ if (t->state == TRANS_CANCEL) {
+ while (nu) {
+ /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */
+ BKE_nurb_handles_calc(nu);
+ nu = nu->next;
+ }
+ }
+ else {
+ /* Normal updating */
+ while (nu) {
+ BKE_nurb_test_2d(nu);
+ BKE_nurb_handles_calc(nu);
+ nu = nu->next;
+ }
+ }
+ }
+ }
+ else if (t->obedit_type == OB_LATTICE) {
+
+ if (t->state != TRANS_CANCEL) {
+ applyProject(t);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ Lattice *la = tc->obedit->data;
+ DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
+ if (la->editlatt->latt->flag & LT_OUTSIDE) {
+ outside_lattice(la->editlatt->latt);
+ }
+ }
+ }
+ else if (t->obedit_type == OB_MESH) {
+ /* mirror modifier clipping? */
+ if (t->state != TRANS_CANCEL) {
+ /* apply clipping after so we never project past the clip plane [#25423] */
+ applyProject(t);
+ clipMirrorModifier(t);
+ }
+ if ((t->flag & T_NO_MIRROR) == 0 && (t->options & CTX_NO_MIRROR) == 0) {
+ editbmesh_apply_to_mirror(t);
+ }
+
+ if (t->mode == TFM_EDGE_SLIDE) {
+ projectEdgeSlideData(t, false);
+ }
+ else if (t->mode == TFM_VERT_SLIDE) {
+ projectVertSlideData(t, false);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ EDBM_mesh_normals_update(em);
+ BKE_editmesh_tessface_calc(em);
+ }
+ }
+ else if (t->obedit_type == OB_ARMATURE) { /* no recalc flag, does pose */
+
+ if (t->state != TRANS_CANCEL) {
+ applyProject(t);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ bArmature *arm = tc->obedit->data;
+ ListBase *edbo = arm->edbo;
+ EditBone *ebo, *ebo_parent;
+ TransData *td = tc->data;
+ int i;
+
+ /* Ensure all bones are correctly adjusted */
+ for (ebo = edbo->first; ebo; ebo = ebo->next) {
+ ebo_parent = (ebo->flag & BONE_CONNECTED) ? ebo->parent : NULL;
+
+ if (ebo_parent) {
+ /* If this bone has a parent tip that has been moved */
+ if (ebo_parent->flag & BONE_TIPSEL) {
+ copy_v3_v3(ebo->head, ebo_parent->tail);
+ if (t->mode == TFM_BONE_ENVELOPE)
+ ebo->rad_head = ebo_parent->rad_tail;
+ }
+ /* If this bone has a parent tip that has NOT been moved */
+ else {
+ copy_v3_v3(ebo_parent->tail, ebo->head);
+ if (t->mode == TFM_BONE_ENVELOPE)
+ ebo_parent->rad_tail = ebo->rad_head;
+ }
+ }
+
+ /* on extrude bones, oldlength==0.0f, so we scale radius of points */
+ ebo->length = len_v3v3(ebo->head, ebo->tail);
+ if (ebo->oldlength == 0.0f) {
+ ebo->rad_head = 0.25f * ebo->length;
+ ebo->rad_tail = 0.10f * ebo->length;
+ ebo->dist = 0.25f * ebo->length;
+ if (ebo->parent) {
+ if (ebo->rad_head > ebo->parent->rad_tail)
+ ebo->rad_head = ebo->parent->rad_tail;
+ }
+ }
+ else if (t->mode != TFM_BONE_ENVELOPE) {
+ /* if bones change length, lets do that for the deform distance as well */
+ ebo->dist *= ebo->length / ebo->oldlength;
+ ebo->rad_head *= ebo->length / ebo->oldlength;
+ ebo->rad_tail *= ebo->length / ebo->oldlength;
+ ebo->oldlength = ebo->length;
+
+ if (ebo_parent) {
+ ebo_parent->rad_tail = ebo->rad_head;
+ }
+ }
+ }
+
+ if (!ELEM(
+ t->mode, TFM_BONE_ROLL, TFM_BONE_ENVELOPE, TFM_BONE_ENVELOPE_DIST, TFM_BONESIZE)) {
+ /* fix roll */
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->extra) {
+ float vec[3], up_axis[3];
+ float qrot[4];
+ float roll;
+
+ ebo = td->extra;
+
+ if (t->state == TRANS_CANCEL) {
+ /* restore roll */
+ ebo->roll = td->ival;
+ }
+ else {
+ copy_v3_v3(up_axis, td->axismtx[2]);
+
+ sub_v3_v3v3(vec, ebo->tail, ebo->head);
+ normalize_v3(vec);
+ rotation_between_vecs_to_quat(qrot, td->axismtx[1], vec);
+ mul_qt_v3(qrot, up_axis);
+
+ /* roll has a tendency to flip in certain orientations - [#34283], [#33974] */
+ roll = ED_armature_ebone_roll_to_vector(ebo, up_axis, false);
+ ebo->roll = angle_compat_rad(roll, td->ival);
+ }
+ }
+ }
+ }
+
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ if (t->state != TRANS_CANCEL) {
+ ED_armature_edit_transform_mirror_update(tc->obedit);
+ }
+ else {
+ restoreBones(tc);
+ }
+ }
+ }
+ }
+ else {
+ if (t->state != TRANS_CANCEL) {
+ applyProject(t);
+ }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ if (tc->data_len) {
+ DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
+ }
+ }
+ }
+ }
+ else if (t->flag & T_POSE) {
+ GSet *motionpath_updates = BLI_gset_ptr_new("motionpath updates");
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ Object *ob = tc->poseobj;
+ bArmature *arm = ob->data;
+
+ /* if animtimer is running, and the object already has animation data,
+ * check if the auto-record feature means that we should record 'samples'
+ * (i.e. un-editable animation values)
+ *
+ * context is needed for keying set poll() functions.
+ */
+ // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
+ if ((t->animtimer) && (t->context) && IS_AUTOKEY_ON(t->scene)) {
+ int targetless_ik =
+ (t->flag & T_AUTOIK); // XXX this currently doesn't work, since flags aren't set yet!
+
+ animrecord_check_state(t->scene, &ob->id, t->animtimer);
+ autokeyframe_pose(t->context, t->scene, ob, t->mode, targetless_ik);
+ }
+
+ if (motionpath_need_update_pose(t->scene, ob)) {
+ BLI_gset_insert(motionpath_updates, ob);
+ }
+
+ /* old optimize trick... this enforces to bypass the depgraph */
+ if (!(arm->flag & ARM_DELAYDEFORM)) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); /* sets recalc flags */
+ /* transformation of pose may affect IK tree, make sure it is rebuilt */
+ BIK_clear_data(ob->pose);
+ }
+ else {
+ BKE_pose_where_is(t->depsgraph, t->scene, ob);
+ }
+ }
+
+ /* Update motion paths once for all transformed bones in an object. */
+ GSetIterator gs_iter;
+ GSET_ITER (gs_iter, motionpath_updates) {
+ Object *ob = BLI_gsetIterator_getKey(&gs_iter);
+ ED_pose_recalculate_paths(t->context, t->scene, ob, true);
+ }
+ BLI_gset_free(motionpath_updates, NULL);
+ }
+ else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) &&
+ PE_get_current(t->scene, base->object)) {
+ if (t->state != TRANS_CANCEL) {
+ applyProject(t);
+ }
+ flushTransParticles(t);
+ }
+ else {
+ bool motionpath_update = false;
+
+ if (t->state != TRANS_CANCEL) {
+ applyProject(t);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+
+ for (int i = 0; i < tc->data_len; i++, td++) {
+ Object *ob = td->ob;
+
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ /* if animtimer is running, and the object already has animation data,
+ * check if the auto-record feature means that we should record 'samples'
+ * (i.e. uneditable animation values)
+ */
+ // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
+ if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
+ animrecord_check_state(t->scene, &ob->id, t->animtimer);
+ autokeyframe_object(t->context, t->scene, t->view_layer, ob, t->mode);
+ }
+
+ motionpath_update |= motionpath_need_update_object(t->scene, ob);
+
+ /* sets recalc flags fully, instead of flushing existing ones
+ * otherwise proxies don't function correctly
+ */
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+
+ if (t->flag & T_TEXTURE)
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ }
+
+ if (motionpath_update) {
+ /* Update motion paths once for all transformed objects. */
+ ED_objects_recalculate_paths(t->context, t->scene, true);
+ }
+ }
}
static void recalcData_cursor(TransInfo *t)
{
- DEG_id_tag_update(&t->scene->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_id_tag_update(&t->scene->id, ID_RECALC_COPY_ON_WRITE);
}
/* helper for recalcData() - for sequencer transforms */
static void recalcData_sequencer(TransInfo *t)
{
- TransData *td;
- int a;
- Sequence *seq_prev = NULL;
+ TransData *td;
+ int a;
+ Sequence *seq_prev = NULL;
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- for (a = 0, td = tc->data; a < tc->data_len; a++, td++) {
- TransDataSeq *tdsq = (TransDataSeq *) td->extra;
- Sequence *seq = tdsq->seq;
+ for (a = 0, td = tc->data; a < tc->data_len; a++, td++) {
+ TransDataSeq *tdsq = (TransDataSeq *)td->extra;
+ Sequence *seq = tdsq->seq;
- if (seq != seq_prev) {
- if (BKE_sequence_tx_fullupdate_test(seq)) {
- /* A few effect strip types need a complete recache on transform. */
- BKE_sequence_invalidate_cache(t->scene, seq);
- }
- else {
- BKE_sequence_invalidate_dependent(t->scene, seq);
- }
- }
+ if (seq != seq_prev) {
+ if (BKE_sequence_tx_fullupdate_test(seq)) {
+ /* A few effect strip types need a complete recache on transform. */
+ BKE_sequence_invalidate_cache(t->scene, seq);
+ }
+ else {
+ BKE_sequence_invalidate_dependent(t->scene, seq);
+ }
+ }
- seq_prev = seq;
- }
+ seq_prev = seq;
+ }
- BKE_sequencer_preprocessed_cache_cleanup();
+ BKE_sequencer_preprocessed_cache_cleanup();
- flushTransSeq(t);
+ flushTransSeq(t);
}
/* force recalculation of triangles during transformation */
static void recalcData_gpencil_strokes(TransInfo *t)
{
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- 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;
- }
- }
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ 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;
+ }
+ }
}
/* called for updating while transform acts, once per redraw */
void recalcData(TransInfo *t)
{
- /* if tests must match createTransData for correct updates */
- if (t->options & CTX_CURSOR) {
- recalcData_cursor(t);
- }
- else if (t->options & CTX_TEXTURE) {
- recalcData_objects(t);
- }
- else if (t->options & CTX_EDGE) {
- recalcData_objects(t);
- }
- else if (t->options & CTX_PAINT_CURVE) {
- flushTransPaintCurve(t);
- }
- else if (t->options & CTX_GPENCIL_STROKES) {
- /* set recalc triangle cache flag */
- recalcData_gpencil_strokes(t);
- }
- else if (t->spacetype == SPACE_IMAGE) {
- recalcData_image(t);
- }
- else if (t->spacetype == SPACE_ACTION) {
- recalcData_actedit(t);
- }
- else if (t->spacetype == SPACE_NLA) {
- recalcData_nla(t);
- }
- else if (t->spacetype == SPACE_SEQ) {
- recalcData_sequencer(t);
- }
- else if (t->spacetype == SPACE_GRAPH) {
- recalcData_graphedit(t);
- }
- else if (t->spacetype == SPACE_NODE) {
- flushTransNodes(t);
- }
- else if (t->spacetype == SPACE_CLIP) {
- recalcData_spaceclip(t);
- }
- else {
- recalcData_objects(t);
- }
+ /* if tests must match createTransData for correct updates */
+ if (t->options & CTX_CURSOR) {
+ recalcData_cursor(t);
+ }
+ else if (t->options & CTX_TEXTURE) {
+ recalcData_objects(t);
+ }
+ else if (t->options & CTX_EDGE) {
+ recalcData_objects(t);
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ flushTransPaintCurve(t);
+ }
+ else if (t->options & CTX_GPENCIL_STROKES) {
+ /* set recalc triangle cache flag */
+ recalcData_gpencil_strokes(t);
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ recalcData_image(t);
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ recalcData_actedit(t);
+ }
+ else if (t->spacetype == SPACE_NLA) {
+ recalcData_nla(t);
+ }
+ else if (t->spacetype == SPACE_SEQ) {
+ recalcData_sequencer(t);
+ }
+ else if (t->spacetype == SPACE_GRAPH) {
+ recalcData_graphedit(t);
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ flushTransNodes(t);
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ recalcData_spaceclip(t);
+ }
+ else {
+ recalcData_objects(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];
+ float v1[3], v2[3], v3[3];
+ unsigned char col[3], col2[3];
- if (t->spacetype == SPACE_VIEW3D) {
- View3D *v3d = t->view;
+ if (t->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = t->view;
- GPU_matrix_push();
+ GPU_matrix_push();
- copy_v3_v3(v3, dir);
- mul_v3_fl(v3, v3d->clip_end);
+ copy_v3_v3(v3, dir);
+ mul_v3_fl(v3, v3d->clip_end);
- sub_v3_v3v3(v2, center, v3);
- add_v3_v3v3(v1, center, v3);
+ sub_v3_v3v3(v2, center, v3);
+ add_v3_v3v3(v1, center, v3);
- if (options & DRAWLIGHT) {
- col[0] = col[1] = col[2] = 220;
- }
- else {
- UI_GetThemeColor3ubv(TH_GRID, col);
- }
- UI_make_axis_color(col, col2, axis);
+ if (options & DRAWLIGHT) {
+ col[0] = col[1] = col[2] = 220;
+ }
+ else {
+ UI_GetThemeColor3ubv(TH_GRID, col);
+ }
+ UI_make_axis_color(col, col2, axis);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformColor3ubv(col2);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ubv(col2);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3fv(pos, v1);
- immVertex3fv(pos, v2);
- immEnd();
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
- GPU_matrix_pop();
- }
+ GPU_matrix_pop();
+ }
}
/**
@@ -1177,94 +1184,96 @@ void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis
*/
void resetTransModal(TransInfo *t)
{
- freeTransCustomDataForMode(t);
+ freeTransCustomDataForMode(t);
}
void resetTransRestrictions(TransInfo *t)
{
- t->flag &= ~T_ALL_RESTRICTIONS;
+ t->flag &= ~T_ALL_RESTRICTIONS;
}
static int initTransInfo_edit_pet_to_flag(const int proportional)
{
- switch (proportional) {
- case PROP_EDIT_ON:
- return T_PROP_EDIT;
- case PROP_EDIT_CONNECTED:
- return T_PROP_EDIT | T_PROP_CONNECTED;
- case PROP_EDIT_PROJECTED:
- return T_PROP_EDIT | T_PROP_PROJECTED;
- default:
- return 0;
- }
+ switch (proportional) {
+ case PROP_EDIT_ON:
+ return T_PROP_EDIT;
+ case PROP_EDIT_CONNECTED:
+ return T_PROP_EDIT | T_PROP_CONNECTED;
+ case PROP_EDIT_PROJECTED:
+ return T_PROP_EDIT | T_PROP_PROJECTED;
+ default:
+ return 0;
+ }
}
-void initTransDataContainers_FromObjectData(TransInfo *t, Object *obact, Object **objects, uint objects_len)
+void initTransDataContainers_FromObjectData(TransInfo *t,
+ Object *obact,
+ Object **objects,
+ uint objects_len)
{
- const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT;
- const short object_type = obact ? obact->type : -1;
-
- if ((object_mode & OB_MODE_EDIT) || (t->options & CTX_GPENCIL_STROKES) ||
- ((object_mode & OB_MODE_POSE) && (object_type == OB_ARMATURE)))
- {
- if (t->data_container) {
- MEM_freeN(t->data_container);
- }
-
- bool free_objects = false;
- if (objects == NULL) {
- objects = BKE_view_layer_array_from_objects_in_mode(
- t->view_layer,
- (t->spacetype == SPACE_VIEW3D) ? t->view : NULL,
- &objects_len, {
- .object_mode = object_mode,
- .no_dup_data = true,
- });
- free_objects = true;
- }
-
- t->data_container = MEM_callocN(sizeof(*t->data_container) * objects_len, __func__);
- t->data_container_len = objects_len;
-
- for (int i = 0; i < objects_len; i++) {
- TransDataContainer *tc = &t->data_container[i];
- /* TODO, multiple axes. */
- tc->mirror.axis_flag = (
- ((t->flag & T_NO_MIRROR) == 0) &&
- ((t->options & CTX_NO_MIRROR) == 0) &&
- (objects[i]->type == OB_MESH) &&
- (((Mesh *)objects[i]->data)->editflag & ME_EDIT_MIRROR_X) != 0);
-
- if (object_mode & OB_MODE_EDIT) {
- tc->obedit = objects[i];
- /* Check needed for UV's */
- if ((t->flag & T_2D_EDIT) == 0) {
- tc->use_local_mat = true;
- }
- }
- else if (object_mode & OB_MODE_POSE) {
- tc->poseobj = objects[i];
- tc->use_local_mat = true;
- }
- else if (t->options & CTX_GPENCIL_STROKES) {
- tc->use_local_mat = true;
- }
-
- if (tc->use_local_mat) {
- BLI_assert((t->flag & T_2D_EDIT) == 0);
- copy_m4_m4(tc->mat, objects[i]->obmat);
- copy_m3_m4(tc->mat3, tc->mat);
- invert_m4_m4(tc->imat, tc->mat);
- invert_m3_m3(tc->imat3, tc->mat3);
- normalize_m3_m3(tc->mat3_unit, tc->mat3);
- }
- /* Otherwise leave as zero. */
- }
-
- if (free_objects) {
- MEM_freeN(objects);
- }
- }
+ const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT;
+ const short object_type = obact ? obact->type : -1;
+
+ if ((object_mode & OB_MODE_EDIT) || (t->options & CTX_GPENCIL_STROKES) ||
+ ((object_mode & OB_MODE_POSE) && (object_type == OB_ARMATURE))) {
+ if (t->data_container) {
+ MEM_freeN(t->data_container);
+ }
+
+ bool free_objects = false;
+ if (objects == NULL) {
+ objects = BKE_view_layer_array_from_objects_in_mode(
+ t->view_layer,
+ (t->spacetype == SPACE_VIEW3D) ? t->view : NULL,
+ &objects_len,
+ {
+ .object_mode = object_mode,
+ .no_dup_data = true,
+ });
+ free_objects = true;
+ }
+
+ t->data_container = MEM_callocN(sizeof(*t->data_container) * objects_len, __func__);
+ t->data_container_len = objects_len;
+
+ for (int i = 0; i < objects_len; i++) {
+ TransDataContainer *tc = &t->data_container[i];
+ /* TODO, multiple axes. */
+ tc->mirror.axis_flag = (((t->flag & T_NO_MIRROR) == 0) &&
+ ((t->options & CTX_NO_MIRROR) == 0) &&
+ (objects[i]->type == OB_MESH) &&
+ (((Mesh *)objects[i]->data)->editflag & ME_EDIT_MIRROR_X) != 0);
+
+ if (object_mode & OB_MODE_EDIT) {
+ tc->obedit = objects[i];
+ /* Check needed for UV's */
+ if ((t->flag & T_2D_EDIT) == 0) {
+ tc->use_local_mat = true;
+ }
+ }
+ else if (object_mode & OB_MODE_POSE) {
+ tc->poseobj = objects[i];
+ tc->use_local_mat = true;
+ }
+ else if (t->options & CTX_GPENCIL_STROKES) {
+ tc->use_local_mat = true;
+ }
+
+ if (tc->use_local_mat) {
+ BLI_assert((t->flag & T_2D_EDIT) == 0);
+ copy_m4_m4(tc->mat, objects[i]->obmat);
+ copy_m3_m4(tc->mat3, tc->mat);
+ invert_m4_m4(tc->imat, tc->mat);
+ invert_m3_m3(tc->imat3, tc->mat3);
+ normalize_m3_m3(tc->mat3_unit, tc->mat3);
+ }
+ /* Otherwise leave as zero. */
+ }
+
+ if (free_objects) {
+ MEM_freeN(objects);
+ }
+ }
}
/**
@@ -1276,437 +1285,431 @@ void initTransDataContainers_FromObjectData(TransInfo *t, Object *obact, Object
*/
void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *sce = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const eObjectMode object_mode = OBACT(view_layer) ? OBACT(view_layer)->mode : OB_MODE_OBJECT;
- const short object_type = OBACT(view_layer) ? OBACT(view_layer)->type : -1;
- ToolSettings *ts = CTX_data_tool_settings(C);
- ARegion *ar = CTX_wm_region(C);
- ScrArea *sa = CTX_wm_area(C);
-
- bGPdata *gpd = CTX_data_gpencil_data(C);
- PropertyRNA *prop;
-
- t->depsgraph = depsgraph;
- t->scene = sce;
- t->view_layer = view_layer;
- t->sa = sa;
- t->ar = ar;
- t->settings = ts;
- t->reports = op ? op->reports : NULL;
-
- t->helpline = HLP_NONE;
-
- t->flag = 0;
-
- t->obedit_type = ((object_mode == OB_MODE_EDIT) || (object_mode == OB_MODE_EDIT_GPENCIL)) ? object_type : -1;
-
- /* Many kinds of transform only use a single handle. */
- if (t->data_container == NULL) {
- t->data_container = MEM_callocN(sizeof(*t->data_container), __func__);
- t->data_container_len = 1;
- }
-
- t->redraw = TREDRAW_HARD; /* redraw first time */
-
- if (event) {
- t->mouse.imval[0] = event->mval[0];
- t->mouse.imval[1] = event->mval[1];
- }
- else {
- t->mouse.imval[0] = 0;
- t->mouse.imval[1] = 0;
- }
-
- 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];
-
- t->transform = NULL;
- t->handleEvent = NULL;
-
- t->data_len_all = 0;
-
- t->val = 0.0f;
-
- zero_v3(t->vec);
- zero_v3(t->center_global);
-
- 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;
-
- /* if there's an event, we're modal */
- if (event) {
- t->flag |= T_MODAL;
- }
-
- /* Crease needs edge flag */
- if (ELEM(t->mode, TFM_CREASE, TFM_BWEIGHT)) {
- t->options |= CTX_EDGE;
- }
-
- t->remove_on_cancel = false;
-
- if (op && (prop = RNA_struct_find_property(op->ptr, "remove_on_cancel")) && RNA_property_is_set(op->ptr, prop)) {
- if (RNA_property_boolean_get(op->ptr, prop)) {
- t->remove_on_cancel = true;
- }
- }
-
- /* GPencil editing context */
- if (GPENCIL_EDIT_MODE(gpd)) {
- t->options |= CTX_GPENCIL_STROKES;
- }
-
- /* Assign the space type, some exceptions for running in different mode */
- if (sa == NULL) {
- /* background mode */
- t->spacetype = SPACE_EMPTY;
- }
- else if ((ar == NULL) && (sa->spacetype == SPACE_VIEW3D)) {
- /* running in the text editor */
- t->spacetype = SPACE_EMPTY;
- }
- else {
- /* normal operation */
- t->spacetype = sa->spacetype;
- }
-
- /* handle T_ALT_TRANSFORM initialization, we may use for different operators */
- if (op) {
- const char *prop_id = NULL;
- if (t->mode == TFM_SHRINKFATTEN) {
- prop_id = "use_even_offset";
- }
-
- if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id))) {
- SET_FLAG_FROM_TEST(t->flag, RNA_property_boolean_get(op->ptr, prop), T_ALT_TRANSFORM);
- }
- }
-
- if (t->spacetype == SPACE_VIEW3D) {
- View3D *v3d = sa->spacedata.first;
- bScreen *animscreen = ED_screen_animation_playing(CTX_wm_manager(C));
-
- t->view = v3d;
- t->animtimer = (animscreen) ? animscreen->animtimer : NULL;
-
- /* turn gizmo off during transform */
- if (t->flag & T_MODAL) {
- t->gizmo_flag = v3d->gizmo_flag;
- v3d->gizmo_flag = V3D_GIZMO_HIDE;
- }
-
- if (t->scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) {
- t->flag |= T_V3D_ALIGN;
- }
- t->around = t->scene->toolsettings->transform_pivot_point;
-
- /* bend always uses the cursor */
- if (t->mode == TFM_BEND) {
- 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)) {
- const bool use_island = transdata_check_local_islands(t, t->around);
-
- if ((t->obedit_type != -1) && !use_island) {
- t->options |= CTX_NO_PET;
- }
- }
- }
-
- if (object_mode & OB_MODE_ALL_PAINT) {
- Paint *p = BKE_paint_get_active_from_context(C);
- if (p && p->brush && (p->brush->flag & BRUSH_CURVE)) {
- t->options |= CTX_PAINT_CURVE;
- }
- }
-
- /* initialize UV transform from */
- if (op && ((prop = RNA_struct_find_property(op->ptr, "correct_uv")))) {
- if (RNA_property_is_set(op->ptr, prop)) {
- if (RNA_property_boolean_get(op->ptr, prop)) {
- t->settings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT;
- }
- else {
- t->settings->uvcalc_flag &= ~UVCALC_TRANSFORM_CORRECT;
- }
- }
- else {
- RNA_property_boolean_set(op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0);
- }
- }
-
- }
- else if (t->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = sa->spacedata.first;
- // XXX for now, get View2D from the active region
- t->view = &ar->v2d;
- t->around = sima->around;
-
- if (ED_space_image_show_uvedit(sima, OBACT(t->view_layer))) {
- /* UV transform */
- }
- else if (sima->mode == SI_MODE_MASK) {
- t->options |= CTX_MASK;
- }
- else if (sima->mode == SI_MODE_PAINT) {
- Paint *p = &sce->toolsettings->imapaint.paint;
- if (p->brush && (p->brush->flag & BRUSH_CURVE)) {
- t->options |= CTX_PAINT_CURVE;
- }
- }
- /* image not in uv edit, nor in mask mode, can happen for some tools */
- }
- else if (t->spacetype == SPACE_NODE) {
- // XXX for now, get View2D from the active region
- t->view = &ar->v2d;
- t->around = V3D_AROUND_CENTER_BOUNDS;
- }
- else if (t->spacetype == SPACE_GRAPH) {
- SpaceGraph *sipo = sa->spacedata.first;
- t->view = &ar->v2d;
- t->around = sipo->around;
- }
- else if (t->spacetype == SPACE_CLIP) {
- SpaceClip *sclip = sa->spacedata.first;
- t->view = &ar->v2d;
- t->around = sclip->around;
-
- if (ED_space_clip_check_show_trackedit(sclip))
- t->options |= CTX_MOVIECLIP;
- else if (ED_space_clip_check_show_maskedit(sclip))
- t->options |= CTX_MASK;
- }
- else {
- if (ar) {
- // XXX for now, get View2D from the active region
- t->view = &ar->v2d;
- // XXX for now, the center point is the midpoint of the data
- }
- else {
- t->view = NULL;
- }
- 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);
- }
-
- 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 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;
- if (t->flag & T_MODAL) {
- RNA_enum_set(op->ptr, "orient_matrix_type", RNA_enum_get(op->ptr, "orient_type"));
- }
- }
- 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);
- TransformOrientation *custom_orientation = NULL;
-
- if (orientation >= V3D_ORIENT_CUSTOM) {
- if (orientation >= V3D_ORIENT_CUSTOM + BIF_countTransformOrientation(C)) {
- orientation = V3D_ORIENT_GLOBAL;
- }
- else {
- custom_orientation = BKE_scene_transform_orientation_find(
- t->scene, orientation - V3D_ORIENT_CUSTOM);
- orientation = V3D_ORIENT_CUSTOM;
- }
- }
-
- t->orientation.user = orientation;
- t->orientation.custom = custom_orientation;
- }
-
- if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) &&
- RNA_property_is_set(op->ptr, prop)))
- {
- if (RNA_property_boolean_get(op->ptr, prop)) {
- t->flag |= T_RELEASE_CONFIRM;
- }
- }
- else {
- if (U.flag & USER_RELEASECONFIRM) {
- t->flag |= T_RELEASE_CONFIRM;
- }
- }
-
- if (op && ((prop = RNA_struct_find_property(op->ptr, "mirror")) &&
- RNA_property_is_set(op->ptr, prop)))
- {
- if (!RNA_property_boolean_get(op->ptr, prop)) {
- t->flag |= T_NO_MIRROR;
- }
- }
- else if ((t->spacetype == SPACE_VIEW3D) && (t->obedit_type == OB_MESH)) {
- /* pass */
- }
- else {
- /* Avoid mirroring for unsupported contexts. */
- t->options |= CTX_NO_MIRROR;
- }
-
- /* setting PET flag only if property exist in operator. Otherwise, assume it's not supported */
- if (op && (prop = RNA_struct_find_property(op->ptr, "proportional"))) {
- if (RNA_property_is_set(op->ptr, prop)) {
- t->flag |= initTransInfo_edit_pet_to_flag(RNA_property_enum_get(op->ptr, prop));
- }
- else {
- /* use settings from scene only if modal */
- if (t->flag & T_MODAL) {
- if ((t->options & CTX_NO_PET) == 0) {
- if (t->spacetype == SPACE_GRAPH) {
- t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_fcurve);
- }
- else if (t->spacetype == SPACE_ACTION) {
- t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_action);
- }
- else if (t->obedit_type != -1) {
- t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
- }
- else if (t->options & CTX_GPENCIL_STROKES) {
- t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
- }
- else if (t->options & CTX_MASK) {
- if (ts->proportional_mask) {
- t->flag |= T_PROP_EDIT;
-
- if (ts->proportional == PROP_EDIT_CONNECTED) {
- t->flag |= T_PROP_CONNECTED;
- }
- }
- }
- else if ((t->obedit_type == -1) && ts->proportional_objects) {
- t->flag |= T_PROP_EDIT;
- }
- }
- }
- }
-
- if (op && ((prop = RNA_struct_find_property(op->ptr, "proportional_size")) &&
- RNA_property_is_set(op->ptr, prop)))
- {
- t->prop_size = RNA_property_float_get(op->ptr, prop);
- }
- else {
- t->prop_size = ts->proportional_size;
- }
-
-
- /* TRANSFORM_FIX_ME rna restrictions */
- if (t->prop_size <= 0.00001f) {
- printf("Proportional size (%f) under 0.00001, resetting to 1!\n", t->prop_size);
- t->prop_size = 1.0f;
- }
-
- if (op && ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) &&
- RNA_property_is_set(op->ptr, prop)))
- {
- t->prop_mode = RNA_property_enum_get(op->ptr, prop);
- }
- else {
- t->prop_mode = ts->prop_mode;
- }
- }
- else { /* add not pet option to context when not available */
- t->options |= CTX_NO_PET;
- }
-
- // Mirror is not supported with PET, turn it off.
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *sce = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const eObjectMode object_mode = OBACT(view_layer) ? OBACT(view_layer)->mode : OB_MODE_OBJECT;
+ const short object_type = OBACT(view_layer) ? OBACT(view_layer)->type : -1;
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ ARegion *ar = CTX_wm_region(C);
+ ScrArea *sa = CTX_wm_area(C);
+
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ PropertyRNA *prop;
+
+ t->depsgraph = depsgraph;
+ t->scene = sce;
+ t->view_layer = view_layer;
+ t->sa = sa;
+ t->ar = ar;
+ t->settings = ts;
+ t->reports = op ? op->reports : NULL;
+
+ t->helpline = HLP_NONE;
+
+ t->flag = 0;
+
+ t->obedit_type = ((object_mode == OB_MODE_EDIT) || (object_mode == OB_MODE_EDIT_GPENCIL)) ?
+ object_type :
+ -1;
+
+ /* Many kinds of transform only use a single handle. */
+ if (t->data_container == NULL) {
+ t->data_container = MEM_callocN(sizeof(*t->data_container), __func__);
+ t->data_container_len = 1;
+ }
+
+ t->redraw = TREDRAW_HARD; /* redraw first time */
+
+ if (event) {
+ t->mouse.imval[0] = event->mval[0];
+ t->mouse.imval[1] = event->mval[1];
+ }
+ else {
+ t->mouse.imval[0] = 0;
+ t->mouse.imval[1] = 0;
+ }
+
+ 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];
+
+ t->transform = NULL;
+ t->handleEvent = NULL;
+
+ t->data_len_all = 0;
+
+ t->val = 0.0f;
+
+ zero_v3(t->vec);
+ zero_v3(t->center_global);
+
+ 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;
+
+ /* if there's an event, we're modal */
+ if (event) {
+ t->flag |= T_MODAL;
+ }
+
+ /* Crease needs edge flag */
+ if (ELEM(t->mode, TFM_CREASE, TFM_BWEIGHT)) {
+ t->options |= CTX_EDGE;
+ }
+
+ t->remove_on_cancel = false;
+
+ if (op && (prop = RNA_struct_find_property(op->ptr, "remove_on_cancel")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ t->remove_on_cancel = true;
+ }
+ }
+
+ /* GPencil editing context */
+ if (GPENCIL_EDIT_MODE(gpd)) {
+ t->options |= CTX_GPENCIL_STROKES;
+ }
+
+ /* Assign the space type, some exceptions for running in different mode */
+ if (sa == NULL) {
+ /* background mode */
+ t->spacetype = SPACE_EMPTY;
+ }
+ else if ((ar == NULL) && (sa->spacetype == SPACE_VIEW3D)) {
+ /* running in the text editor */
+ t->spacetype = SPACE_EMPTY;
+ }
+ else {
+ /* normal operation */
+ t->spacetype = sa->spacetype;
+ }
+
+ /* handle T_ALT_TRANSFORM initialization, we may use for different operators */
+ if (op) {
+ const char *prop_id = NULL;
+ if (t->mode == TFM_SHRINKFATTEN) {
+ prop_id = "use_even_offset";
+ }
+
+ if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id))) {
+ SET_FLAG_FROM_TEST(t->flag, RNA_property_boolean_get(op->ptr, prop), T_ALT_TRANSFORM);
+ }
+ }
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = sa->spacedata.first;
+ bScreen *animscreen = ED_screen_animation_playing(CTX_wm_manager(C));
+
+ t->view = v3d;
+ t->animtimer = (animscreen) ? animscreen->animtimer : NULL;
+
+ /* turn gizmo off during transform */
+ if (t->flag & T_MODAL) {
+ t->gizmo_flag = v3d->gizmo_flag;
+ v3d->gizmo_flag = V3D_GIZMO_HIDE;
+ }
+
+ if (t->scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) {
+ t->flag |= T_V3D_ALIGN;
+ }
+ t->around = t->scene->toolsettings->transform_pivot_point;
+
+ /* bend always uses the cursor */
+ if (t->mode == TFM_BEND) {
+ 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)) {
+ const bool use_island = transdata_check_local_islands(t, t->around);
+
+ if ((t->obedit_type != -1) && !use_island) {
+ t->options |= CTX_NO_PET;
+ }
+ }
+ }
+
+ if (object_mode & OB_MODE_ALL_PAINT) {
+ Paint *p = BKE_paint_get_active_from_context(C);
+ if (p && p->brush && (p->brush->flag & BRUSH_CURVE)) {
+ t->options |= CTX_PAINT_CURVE;
+ }
+ }
+
+ /* initialize UV transform from */
+ if (op && ((prop = RNA_struct_find_property(op->ptr, "correct_uv")))) {
+ if (RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ t->settings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT;
+ }
+ else {
+ t->settings->uvcalc_flag &= ~UVCALC_TRANSFORM_CORRECT;
+ }
+ }
+ else {
+ RNA_property_boolean_set(
+ op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0);
+ }
+ }
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = sa->spacedata.first;
+ // XXX for now, get View2D from the active region
+ t->view = &ar->v2d;
+ t->around = sima->around;
+
+ if (ED_space_image_show_uvedit(sima, OBACT(t->view_layer))) {
+ /* UV transform */
+ }
+ else if (sima->mode == SI_MODE_MASK) {
+ t->options |= CTX_MASK;
+ }
+ else if (sima->mode == SI_MODE_PAINT) {
+ Paint *p = &sce->toolsettings->imapaint.paint;
+ if (p->brush && (p->brush->flag & BRUSH_CURVE)) {
+ t->options |= CTX_PAINT_CURVE;
+ }
+ }
+ /* image not in uv edit, nor in mask mode, can happen for some tools */
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ // XXX for now, get View2D from the active region
+ t->view = &ar->v2d;
+ t->around = V3D_AROUND_CENTER_BOUNDS;
+ }
+ else if (t->spacetype == SPACE_GRAPH) {
+ SpaceGraph *sipo = sa->spacedata.first;
+ t->view = &ar->v2d;
+ t->around = sipo->around;
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *sclip = sa->spacedata.first;
+ t->view = &ar->v2d;
+ t->around = sclip->around;
+
+ if (ED_space_clip_check_show_trackedit(sclip))
+ t->options |= CTX_MOVIECLIP;
+ else if (ED_space_clip_check_show_maskedit(sclip))
+ t->options |= CTX_MASK;
+ }
+ else {
+ if (ar) {
+ // XXX for now, get View2D from the active region
+ t->view = &ar->v2d;
+ // XXX for now, the center point is the midpoint of the data
+ }
+ else {
+ t->view = NULL;
+ }
+ 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);
+ }
+
+ 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 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;
+ if (t->flag & T_MODAL) {
+ RNA_enum_set(op->ptr, "orient_matrix_type", RNA_enum_get(op->ptr, "orient_type"));
+ }
+ }
+ 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);
+ TransformOrientation *custom_orientation = NULL;
+
+ if (orientation >= V3D_ORIENT_CUSTOM) {
+ if (orientation >= V3D_ORIENT_CUSTOM + BIF_countTransformOrientation(C)) {
+ orientation = V3D_ORIENT_GLOBAL;
+ }
+ else {
+ custom_orientation = BKE_scene_transform_orientation_find(t->scene,
+ orientation - V3D_ORIENT_CUSTOM);
+ orientation = V3D_ORIENT_CUSTOM;
+ }
+ }
+
+ t->orientation.user = orientation;
+ t->orientation.custom = custom_orientation;
+ }
+
+ if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) &&
+ RNA_property_is_set(op->ptr, prop))) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ t->flag |= T_RELEASE_CONFIRM;
+ }
+ }
+ else {
+ if (U.flag & USER_RELEASECONFIRM) {
+ t->flag |= T_RELEASE_CONFIRM;
+ }
+ }
+
+ if (op && ((prop = RNA_struct_find_property(op->ptr, "mirror")) &&
+ RNA_property_is_set(op->ptr, prop))) {
+ if (!RNA_property_boolean_get(op->ptr, prop)) {
+ t->flag |= T_NO_MIRROR;
+ }
+ }
+ else if ((t->spacetype == SPACE_VIEW3D) && (t->obedit_type == OB_MESH)) {
+ /* pass */
+ }
+ else {
+ /* Avoid mirroring for unsupported contexts. */
+ t->options |= CTX_NO_MIRROR;
+ }
+
+ /* setting PET flag only if property exist in operator. Otherwise, assume it's not supported */
+ if (op && (prop = RNA_struct_find_property(op->ptr, "proportional"))) {
+ if (RNA_property_is_set(op->ptr, prop)) {
+ t->flag |= initTransInfo_edit_pet_to_flag(RNA_property_enum_get(op->ptr, prop));
+ }
+ else {
+ /* use settings from scene only if modal */
+ if (t->flag & T_MODAL) {
+ if ((t->options & CTX_NO_PET) == 0) {
+ if (t->spacetype == SPACE_GRAPH) {
+ t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_fcurve);
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_action);
+ }
+ else if (t->obedit_type != -1) {
+ t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
+ }
+ else if (t->options & CTX_GPENCIL_STROKES) {
+ t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
+ }
+ else if (t->options & CTX_MASK) {
+ if (ts->proportional_mask) {
+ t->flag |= T_PROP_EDIT;
+
+ if (ts->proportional == PROP_EDIT_CONNECTED) {
+ t->flag |= T_PROP_CONNECTED;
+ }
+ }
+ }
+ else if ((t->obedit_type == -1) && ts->proportional_objects) {
+ t->flag |= T_PROP_EDIT;
+ }
+ }
+ }
+ }
+
+ if (op && ((prop = RNA_struct_find_property(op->ptr, "proportional_size")) &&
+ RNA_property_is_set(op->ptr, prop))) {
+ t->prop_size = RNA_property_float_get(op->ptr, prop);
+ }
+ else {
+ t->prop_size = ts->proportional_size;
+ }
+
+ /* TRANSFORM_FIX_ME rna restrictions */
+ if (t->prop_size <= 0.00001f) {
+ printf("Proportional size (%f) under 0.00001, resetting to 1!\n", t->prop_size);
+ t->prop_size = 1.0f;
+ }
+
+ if (op && ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) &&
+ RNA_property_is_set(op->ptr, prop))) {
+ t->prop_mode = RNA_property_enum_get(op->ptr, prop);
+ }
+ else {
+ t->prop_mode = ts->prop_mode;
+ }
+ }
+ else { /* add not pet option to context when not available */
+ t->options |= CTX_NO_PET;
+ }
+
+ // Mirror is not supported with PET, turn it off.
#if 0
- if (t->flag & T_PROP_EDIT) {
- t->flag &= ~T_MIRROR;
- }
+ if (t->flag & T_PROP_EDIT) {
+ t->flag &= ~T_MIRROR;
+ }
#endif
- setTransformViewAspect(t, t->aspect);
+ setTransformViewAspect(t, t->aspect);
- if (op && (prop = RNA_struct_find_property(op->ptr, "center_override")) && RNA_property_is_set(op->ptr, prop)) {
- RNA_property_float_get_array(op->ptr, prop, t->center_global);
- mul_v3_v3(t->center_global, t->aspect);
- t->flag |= T_OVERRIDE_CENTER;
- }
+ if (op && (prop = RNA_struct_find_property(op->ptr, "center_override")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_float_get_array(op->ptr, prop, t->center_global);
+ mul_v3_v3(t->center_global, t->aspect);
+ t->flag |= T_OVERRIDE_CENTER;
+ }
- setTransformViewMatrices(t);
- initNumInput(&t->num);
+ setTransformViewMatrices(t);
+ initNumInput(&t->num);
}
-
-static void freeTransCustomData(
- TransInfo *t, TransDataContainer *tc,
- TransCustomData *custom_data)
+static void freeTransCustomData(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data)
{
- if (custom_data->free_cb) {
- /* Can take over freeing t->data and data_2d etc... */
- custom_data->free_cb(t, tc, custom_data);
- BLI_assert(custom_data->data == NULL);
- }
- else if ((custom_data->data != NULL) && custom_data->use_free) {
- MEM_freeN(custom_data->data);
- custom_data->data = NULL;
- }
- /* In case modes are switched in the same transform session. */
- custom_data->free_cb = false;
- custom_data->use_free = false;
+ if (custom_data->free_cb) {
+ /* Can take over freeing t->data and data_2d etc... */
+ custom_data->free_cb(t, tc, custom_data);
+ BLI_assert(custom_data->data == NULL);
+ }
+ else if ((custom_data->data != NULL) && custom_data->use_free) {
+ MEM_freeN(custom_data->data);
+ custom_data->data = NULL;
+ }
+ /* In case modes are switched in the same transform session. */
+ custom_data->free_cb = false;
+ custom_data->use_free = false;
}
-static void freeTransCustomDataContainer(TransInfo *t, TransDataContainer *tc, TransCustomDataContainer *tcdc)
+static void freeTransCustomDataContainer(TransInfo *t,
+ TransDataContainer *tc,
+ TransCustomDataContainer *tcdc)
{
- TransCustomData *custom_data = &tcdc->first_elem;
- for (int i = 0; i < TRANS_CUSTOM_DATA_ELEM_MAX; i++, custom_data++) {
- freeTransCustomData(t, tc, custom_data);
- }
+ TransCustomData *custom_data = &tcdc->first_elem;
+ for (int i = 0; i < TRANS_CUSTOM_DATA_ELEM_MAX; i++, custom_data++) {
+ freeTransCustomData(t, tc, custom_data);
+ }
}
/**
@@ -1714,321 +1717,325 @@ static void freeTransCustomDataContainer(TransInfo *t, TransDataContainer *tc, T
*/
void freeTransCustomDataForMode(TransInfo *t)
{
- freeTransCustomData(t, NULL, &t->custom.mode);
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- freeTransCustomData(t, tc, &tc->custom.mode);
- }
+ freeTransCustomData(t, NULL, &t->custom.mode);
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ freeTransCustomData(t, tc, &tc->custom.mode);
+ }
}
/* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */
void postTrans(bContext *C, TransInfo *t)
{
- if (t->draw_handle_view)
- ED_region_draw_cb_exit(t->ar->type, t->draw_handle_view);
- if (t->draw_handle_apply)
- ED_region_draw_cb_exit(t->ar->type, t->draw_handle_apply);
- if (t->draw_handle_pixel)
- ED_region_draw_cb_exit(t->ar->type, t->draw_handle_pixel);
- if (t->draw_handle_cursor)
- WM_paint_cursor_end(CTX_wm_manager(C), t->draw_handle_cursor);
-
- if (t->flag & T_MODAL_CURSOR_SET) {
- WM_cursor_modal_restore(CTX_wm_window(C));
- }
-
- /* Free all custom-data */
- freeTransCustomDataContainer(t, NULL, &t->custom);
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- freeTransCustomDataContainer(t, tc, &tc->custom);
- }
-
- /* postTrans can be called when nothing is selected, so data is NULL already */
- if (t->data_len_all != 0) {
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- /* free data malloced per trans-data */
- if (ELEM(t->obedit_type, OB_CURVE, OB_SURF) ||
- (t->spacetype == SPACE_GRAPH))
- {
- TransData *td = tc->data;
- for (int a = 0; a < tc->data_len; a++, td++) {
- if (td->flag & TD_BEZTRIPLE) {
- MEM_freeN(td->hdata);
- }
- }
- }
- MEM_freeN(tc->data);
-
- MEM_SAFE_FREE(tc->data_ext);
- MEM_SAFE_FREE(tc->data_2d);
- }
- }
-
- MEM_SAFE_FREE(t->data_container);
- t->data_container = NULL;
-
- BLI_freelistN(&t->tsnap.points);
-
- if (t->spacetype == SPACE_IMAGE) {
- if (t->options & (CTX_MASK | CTX_PAINT_CURVE)) {
- /* pass */
- }
- else {
- SpaceImage *sima = t->sa->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;
- /* restore gizmo */
- if (t->flag & T_MODAL) {
- v3d->gizmo_flag = t->gizmo_flag;
- }
- }
-
- if (t->mouse.data) {
- MEM_freeN(t->mouse.data);
- }
-
- if (t->rng != NULL) {
- BLI_rng_free(t->rng);
- }
-
- freeSnapping(t);
+ if (t->draw_handle_view)
+ ED_region_draw_cb_exit(t->ar->type, t->draw_handle_view);
+ if (t->draw_handle_apply)
+ ED_region_draw_cb_exit(t->ar->type, t->draw_handle_apply);
+ if (t->draw_handle_pixel)
+ ED_region_draw_cb_exit(t->ar->type, t->draw_handle_pixel);
+ if (t->draw_handle_cursor)
+ WM_paint_cursor_end(CTX_wm_manager(C), t->draw_handle_cursor);
+
+ if (t->flag & T_MODAL_CURSOR_SET) {
+ WM_cursor_modal_restore(CTX_wm_window(C));
+ }
+
+ /* Free all custom-data */
+ freeTransCustomDataContainer(t, NULL, &t->custom);
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ freeTransCustomDataContainer(t, tc, &tc->custom);
+ }
+
+ /* postTrans can be called when nothing is selected, so data is NULL already */
+ if (t->data_len_all != 0) {
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ /* free data malloced per trans-data */
+ if (ELEM(t->obedit_type, OB_CURVE, OB_SURF) || (t->spacetype == SPACE_GRAPH)) {
+ TransData *td = tc->data;
+ for (int a = 0; a < tc->data_len; a++, td++) {
+ if (td->flag & TD_BEZTRIPLE) {
+ MEM_freeN(td->hdata);
+ }
+ }
+ }
+ MEM_freeN(tc->data);
+
+ MEM_SAFE_FREE(tc->data_ext);
+ MEM_SAFE_FREE(tc->data_2d);
+ }
+ }
+
+ MEM_SAFE_FREE(t->data_container);
+ t->data_container = NULL;
+
+ BLI_freelistN(&t->tsnap.points);
+
+ if (t->spacetype == SPACE_IMAGE) {
+ if (t->options & (CTX_MASK | CTX_PAINT_CURVE)) {
+ /* pass */
+ }
+ else {
+ SpaceImage *sima = t->sa->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;
+ /* restore gizmo */
+ if (t->flag & T_MODAL) {
+ v3d->gizmo_flag = t->gizmo_flag;
+ }
+ }
+
+ if (t->mouse.data) {
+ MEM_freeN(t->mouse.data);
+ }
+
+ if (t->rng != NULL) {
+ BLI_rng_free(t->rng);
+ }
+
+ freeSnapping(t);
}
void applyTransObjects(TransInfo *t)
{
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- TransData *td;
-
- for (td = tc->data; td < tc->data + tc->data_len; td++) {
- copy_v3_v3(td->iloc, td->loc);
- if (td->ext->rot) {
- copy_v3_v3(td->ext->irot, td->ext->rot);
- }
- if (td->ext->size) {
- copy_v3_v3(td->ext->isize, td->ext->size);
- }
- }
- recalcData(t);
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ TransData *td;
+
+ for (td = tc->data; td < tc->data + tc->data_len; td++) {
+ copy_v3_v3(td->iloc, td->loc);
+ if (td->ext->rot) {
+ copy_v3_v3(td->ext->irot, td->ext->rot);
+ }
+ if (td->ext->size) {
+ copy_v3_v3(td->ext->isize, td->ext->size);
+ }
+ }
+ recalcData(t);
}
static void restoreElement(TransData *td)
{
- /* TransData for crease has no loc */
- if (td->loc) {
- copy_v3_v3(td->loc, td->iloc);
- }
- if (td->val) {
- *td->val = td->ival;
- }
-
- if (td->ext && (td->flag & TD_NO_EXT) == 0) {
- if (td->ext->rot) {
- copy_v3_v3(td->ext->rot, td->ext->irot);
- }
- if (td->ext->rotAngle) {
- *td->ext->rotAngle = td->ext->irotAngle;
- }
- if (td->ext->rotAxis) {
- copy_v3_v3(td->ext->rotAxis, td->ext->irotAxis);
- }
- /* XXX, drotAngle & drotAxis not used yet */
- if (td->ext->size) {
- copy_v3_v3(td->ext->size, td->ext->isize);
- }
- if (td->ext->quat) {
- copy_qt_qt(td->ext->quat, td->ext->iquat);
- }
- }
-
- if (td->flag & TD_BEZTRIPLE) {
- *(td->hdata->h1) = td->hdata->ih1;
- *(td->hdata->h2) = td->hdata->ih2;
- }
+ /* TransData for crease has no loc */
+ if (td->loc) {
+ copy_v3_v3(td->loc, td->iloc);
+ }
+ if (td->val) {
+ *td->val = td->ival;
+ }
+
+ if (td->ext && (td->flag & TD_NO_EXT) == 0) {
+ if (td->ext->rot) {
+ copy_v3_v3(td->ext->rot, td->ext->irot);
+ }
+ if (td->ext->rotAngle) {
+ *td->ext->rotAngle = td->ext->irotAngle;
+ }
+ if (td->ext->rotAxis) {
+ copy_v3_v3(td->ext->rotAxis, td->ext->irotAxis);
+ }
+ /* XXX, drotAngle & drotAxis not used yet */
+ if (td->ext->size) {
+ copy_v3_v3(td->ext->size, td->ext->isize);
+ }
+ if (td->ext->quat) {
+ copy_qt_qt(td->ext->quat, td->ext->iquat);
+ }
+ }
+
+ if (td->flag & TD_BEZTRIPLE) {
+ *(td->hdata->h1) = td->hdata->ih1;
+ *(td->hdata->h2) = td->hdata->ih2;
+ }
}
void restoreTransObjects(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
- TransData *td;
- TransData2D *td2d;
-
- for (td = tc->data; td < tc->data + tc->data_len; td++) {
- restoreElement(td);
- }
-
- for (td2d = tc->data_2d; tc->data_2d && td2d < tc->data_2d + tc->data_len; td2d++) {
- if (td2d->h1) {
- td2d->h1[0] = td2d->ih1[0];
- td2d->h1[1] = td2d->ih1[1];
- }
- if (td2d->h2) {
- td2d->h2[0] = td2d->ih2[0];
- td2d->h2[1] = td2d->ih2[1];
- }
- }
-
- unit_m3(t->mat);
-
- }
-
- recalcData(t);
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+
+ TransData *td;
+ TransData2D *td2d;
+
+ for (td = tc->data; td < tc->data + tc->data_len; td++) {
+ restoreElement(td);
+ }
+
+ for (td2d = tc->data_2d; tc->data_2d && td2d < tc->data_2d + tc->data_len; td2d++) {
+ if (td2d->h1) {
+ td2d->h1[0] = td2d->ih1[0];
+ td2d->h1[1] = td2d->ih1[1];
+ }
+ if (td2d->h2) {
+ td2d->h2[0] = td2d->ih2[0];
+ td2d->h2[1] = td2d->ih2[1];
+ }
+ }
+
+ unit_m3(t->mat);
+ }
+
+ recalcData(t);
}
void calculateCenter2D(TransInfo *t)
{
- BLI_assert(!is_zero_v3(t->aspect));
- projectFloatView(t, t->center_global, t->center2d);
+ BLI_assert(!is_zero_v3(t->aspect));
+ projectFloatView(t, t->center_global, t->center2d);
}
-void calculateCenterLocal(
- TransInfo *t, const float center_global[3])
+void calculateCenterLocal(TransInfo *t, const float center_global[3])
{
- /* setting constraint center */
- /* note, init functions may over-ride t->center */
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- if (tc->use_local_mat) {
- mul_v3_m4v3(tc->center_local, tc->imat, center_global);
- }
- else {
- copy_v3_v3(tc->center_local, center_global);
- }
- }
+ /* setting constraint center */
+ /* note, init functions may over-ride t->center */
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ if (tc->use_local_mat) {
+ mul_v3_m4v3(tc->center_local, tc->imat, center_global);
+ }
+ else {
+ copy_v3_v3(tc->center_local, center_global);
+ }
+ }
}
void calculateCenterCursor(TransInfo *t, float r_center[3])
{
- const float *cursor = t->scene->cursor.location;
- copy_v3_v3(r_center, cursor);
-
- /* 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) != V3D_PROJ_RET_OK) {
- r_center[0] = t->ar->winx / 2.0f;
- r_center[1] = t->ar->winy / 2.0f;
- }
- r_center[2] = 0.0f;
- }
+ const float *cursor = t->scene->cursor.location;
+ copy_v3_v3(r_center, cursor);
+
+ /* 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) !=
+ V3D_PROJ_RET_OK) {
+ r_center[0] = t->ar->winx / 2.0f;
+ r_center[1] = t->ar->winy / 2.0f;
+ }
+ r_center[2] = 0.0f;
+ }
}
void calculateCenterCursor2D(TransInfo *t, float r_center[2])
{
- const float *cursor = NULL;
-
- if (t->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
- cursor = sima->cursor;
- }
- else if (t->spacetype == SPACE_CLIP) {
- SpaceClip *space_clip = (SpaceClip *) t->sa->spacedata.first;
- cursor = space_clip->cursor;
- }
-
- if (cursor) {
- if (t->options & CTX_MASK) {
- float co[2];
-
- if (t->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)t->sa->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;
- BKE_mask_coord_from_movieclip(space_clip->clip, &space_clip->user, co, cursor);
- }
- else {
- BLI_assert(!"Shall not happen");
- }
-
- r_center[0] = co[0] * t->aspect[0];
- r_center[1] = co[1] * t->aspect[1];
- }
- 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]);
- }
- }
- else {
- r_center[0] = cursor[0] * t->aspect[0];
- r_center[1] = cursor[1] * t->aspect[1];
- }
- }
+ const float *cursor = NULL;
+
+ if (t->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
+ cursor = sima->cursor;
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *space_clip = (SpaceClip *)t->sa->spacedata.first;
+ cursor = space_clip->cursor;
+ }
+
+ if (cursor) {
+ if (t->options & CTX_MASK) {
+ float co[2];
+
+ if (t->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)t->sa->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;
+ BKE_mask_coord_from_movieclip(space_clip->clip, &space_clip->user, co, cursor);
+ }
+ else {
+ BLI_assert(!"Shall not happen");
+ }
+
+ r_center[0] = co[0] * t->aspect[0];
+ r_center[1] = co[1] * t->aspect[1];
+ }
+ 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]);
+ }
+ }
+ else {
+ r_center[0] = cursor[0] * t->aspect[0];
+ r_center[1] = cursor[1] * t->aspect[1];
+ }
+ }
}
void calculateCenterCursorGraph2D(TransInfo *t, float r_center[2])
{
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
- Scene *scene = t->scene;
-
- /* cursor is combination of current frame, and graph-editor cursor value */
- if (sipo->mode == SIPO_MODE_DRIVERS) {
- r_center[0] = sipo->cursorTime;
- r_center[1] = sipo->cursorVal;
- }
- else {
- r_center[0] = (float)(scene->r.cfra);
- r_center[1] = sipo->cursorVal;
- }
+ SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ Scene *scene = t->scene;
+
+ /* cursor is combination of current frame, and graph-editor cursor value */
+ if (sipo->mode == SIPO_MODE_DRIVERS) {
+ r_center[0] = sipo->cursorTime;
+ r_center[1] = sipo->cursorVal;
+ }
+ else {
+ r_center[0] = (float)(scene->r.cfra);
+ r_center[1] = sipo->cursorVal;
+ }
}
void calculateCenterMedian(TransInfo *t, float r_center[3])
{
- float partial[3] = {0.0f, 0.0f, 0.0f};
- int total = 0;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- for (int i = 0; i < tc->data_len; i++) {
- if (tc->data[i].flag & TD_SELECTED) {
- if (!(tc->data[i].flag & TD_NOCENTER)) {
- if (tc->use_local_mat) {
- float v[3];
- mul_v3_m4v3(v, tc->mat, tc->data[i].center);
- add_v3_v3(partial, v);
- }
- else {
- add_v3_v3(partial, tc->data[i].center);
- }
- total++;
- }
- }
- }
- }
- if (total) {
- mul_v3_fl(partial, 1.0f / (float)total);
- }
- copy_v3_v3(r_center, partial);
+ float partial[3] = {0.0f, 0.0f, 0.0f};
+ int total = 0;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ for (int i = 0; i < tc->data_len; i++) {
+ if (tc->data[i].flag & TD_SELECTED) {
+ if (!(tc->data[i].flag & TD_NOCENTER)) {
+ if (tc->use_local_mat) {
+ float v[3];
+ mul_v3_m4v3(v, tc->mat, tc->data[i].center);
+ add_v3_v3(partial, v);
+ }
+ else {
+ add_v3_v3(partial, tc->data[i].center);
+ }
+ total++;
+ }
+ }
+ }
+ }
+ if (total) {
+ mul_v3_fl(partial, 1.0f / (float)total);
+ }
+ copy_v3_v3(r_center, partial);
}
void calculateCenterBound(TransInfo *t, float r_center[3])
{
- float max[3], min[3];
- bool changed = false;
- INIT_MINMAX(min, max);
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- for (int i = 0; i < tc->data_len; i++) {
- if (tc->data[i].flag & TD_SELECTED) {
- if (!(tc->data[i].flag & TD_NOCENTER)) {
- if (tc->use_local_mat) {
- float v[3];
- mul_v3_m4v3(v, tc->mat, tc->data[i].center);
- minmax_v3v3_v3(min, max, v);
- }
- else {
- minmax_v3v3_v3(min, max, tc->data[i].center);
- }
- changed = true;
- }
- }
- }
- }
- if (changed) {
- mid_v3_v3v3(r_center, min, max);
- }
+ float max[3], min[3];
+ bool changed = false;
+ INIT_MINMAX(min, max);
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ for (int i = 0; i < tc->data_len; i++) {
+ if (tc->data[i].flag & TD_SELECTED) {
+ if (!(tc->data[i].flag & TD_NOCENTER)) {
+ if (tc->use_local_mat) {
+ float v[3];
+ mul_v3_m4v3(v, tc->mat, tc->data[i].center);
+ minmax_v3v3_v3(min, max, v);
+ }
+ else {
+ minmax_v3v3_v3(min, max, tc->data[i].center);
+ }
+ changed = true;
+ }
+ }
+ }
+ }
+ if (changed) {
+ mid_v3_v3v3(r_center, min, max);
+ }
}
/**
@@ -2036,286 +2043,287 @@ void calculateCenterBound(TransInfo *t, float r_center[3])
*/
bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
{
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t);
-
- if (t->spacetype != SPACE_VIEW3D) {
- return false;
- }
- else if (tc->obedit) {
- if (ED_object_calc_active_center_for_editmode(tc->obedit, select_only, r_center)) {
- mul_m4_v3(tc->obedit->obmat, r_center);
- return true;
- }
- }
- else if (t->flag & T_POSE) {
- ViewLayer *view_layer = t->view_layer;
- Object *ob = OBACT(view_layer) ;
- if (ED_object_calc_active_center_for_posemode(ob, select_only, r_center)) {
- mul_m4_v3(ob->obmat, r_center);
- return true;
- }
- }
- else if (t->options & CTX_PAINT_CURVE) {
- Paint *p = BKE_paint_get_active(t->scene, t->view_layer);
- Brush *br = p->brush;
- PaintCurve *pc = br->paint_curve;
- copy_v3_v3(r_center, pc->points[pc->add_index - 1].bez.vec[1]);
- r_center[2] = 0.0f;
- return true;
- }
- else {
- /* object mode */
- ViewLayer *view_layer = t->view_layer;
- Object *ob = OBACT(view_layer);
- Base *base = BASACT(view_layer);
- if (ob && ((!select_only) || ((base->flag & BASE_SELECTED) != 0))) {
- copy_v3_v3(r_center, ob->obmat[3]);
- return true;
- }
- }
-
- return false;
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t);
+
+ if (t->spacetype != SPACE_VIEW3D) {
+ return false;
+ }
+ else if (tc->obedit) {
+ if (ED_object_calc_active_center_for_editmode(tc->obedit, select_only, r_center)) {
+ mul_m4_v3(tc->obedit->obmat, r_center);
+ return true;
+ }
+ }
+ else if (t->flag & T_POSE) {
+ ViewLayer *view_layer = t->view_layer;
+ Object *ob = OBACT(view_layer);
+ if (ED_object_calc_active_center_for_posemode(ob, select_only, r_center)) {
+ mul_m4_v3(ob->obmat, r_center);
+ return true;
+ }
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ Paint *p = BKE_paint_get_active(t->scene, t->view_layer);
+ Brush *br = p->brush;
+ PaintCurve *pc = br->paint_curve;
+ copy_v3_v3(r_center, pc->points[pc->add_index - 1].bez.vec[1]);
+ r_center[2] = 0.0f;
+ return true;
+ }
+ else {
+ /* object mode */
+ ViewLayer *view_layer = t->view_layer;
+ Object *ob = OBACT(view_layer);
+ Base *base = BASACT(view_layer);
+ if (ob && ((!select_only) || ((base->flag & BASE_SELECTED) != 0))) {
+ copy_v3_v3(r_center, ob->obmat[3]);
+ return true;
+ }
+ }
+
+ return false;
}
static void calculateCenter_FromAround(TransInfo *t, int around, float r_center[3])
{
- switch (around) {
- case V3D_AROUND_CENTER_BOUNDS:
- calculateCenterBound(t, r_center);
- break;
- case V3D_AROUND_CENTER_MEDIAN:
- calculateCenterMedian(t, r_center);
- break;
- case V3D_AROUND_CURSOR:
- if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP))
- calculateCenterCursor2D(t, r_center);
- else if (t->spacetype == SPACE_GRAPH)
- calculateCenterCursorGraph2D(t, r_center);
- else
- calculateCenterCursor(t, r_center);
- break;
- case V3D_AROUND_LOCAL_ORIGINS:
- /* Individual element center uses median center for helpline and such */
- calculateCenterMedian(t, r_center);
- break;
- case V3D_AROUND_ACTIVE:
- {
- if (calculateCenterActive(t, false, r_center)) {
- /* pass */
- }
- else {
- /* fallback */
- calculateCenterMedian(t, r_center);
- }
- break;
- }
- }
+ switch (around) {
+ case V3D_AROUND_CENTER_BOUNDS:
+ calculateCenterBound(t, r_center);
+ break;
+ case V3D_AROUND_CENTER_MEDIAN:
+ calculateCenterMedian(t, r_center);
+ break;
+ case V3D_AROUND_CURSOR:
+ if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP))
+ calculateCenterCursor2D(t, r_center);
+ else if (t->spacetype == SPACE_GRAPH)
+ calculateCenterCursorGraph2D(t, r_center);
+ else
+ calculateCenterCursor(t, r_center);
+ break;
+ case V3D_AROUND_LOCAL_ORIGINS:
+ /* Individual element center uses median center for helpline and such */
+ calculateCenterMedian(t, r_center);
+ break;
+ case V3D_AROUND_ACTIVE: {
+ if (calculateCenterActive(t, false, r_center)) {
+ /* pass */
+ }
+ else {
+ /* fallback */
+ calculateCenterMedian(t, r_center);
+ }
+ break;
+ }
+ }
}
void calculateCenter(TransInfo *t)
{
- if ((t->flag & T_OVERRIDE_CENTER) == 0) {
- calculateCenter_FromAround(t, t->around, t->center_global);
- }
- calculateCenterLocal(t, t->center_global);
-
- /* avoid calculating again */
- {
- TransCenterData *cd = &t->center_cache[t->around];
- copy_v3_v3(cd->global, t->center_global);
- cd->is_set = true;
- }
-
- calculateCenter2D(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->flag & T_CAMERA) {
- float axis[3];
- /* persinv is nasty, use viewinv instead, always right */
- copy_v3_v3(axis, t->viewinv[2]);
- normalize_v3(axis);
-
- /* 6.0 = 6 grid units */
- axis[0] = t->center_global[0] - 6.0f * axis[0];
- axis[1] = t->center_global[1] - 6.0f * axis[1];
- axis[2] = t->center_global[2] - 6.0f * axis[2];
-
- projectFloatView(t, axis, t->center2d);
-
- /* rotate only needs correct 2d center, grab needs ED_view3d_calc_zfac() value */
- if (t->mode == TFM_TRANSLATION) {
- copy_v3_v3(t->center_global, axis);
- }
- }
- }
- }
-
- if (t->spacetype == SPACE_VIEW3D) {
- /* ED_view3d_calc_zfac() defines a factor for perspective depth correction, used in ED_view3d_win_to_delta() */
-
- /* zfac is only used convertViewVec only in cases operator was invoked in RGN_TYPE_WINDOW
- * and never used in other cases.
- *
- * 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);
- }
- else {
- t->zfac = 0.0f;
- }
- }
+ if ((t->flag & T_OVERRIDE_CENTER) == 0) {
+ calculateCenter_FromAround(t, t->around, t->center_global);
+ }
+ calculateCenterLocal(t, t->center_global);
+
+ /* avoid calculating again */
+ {
+ TransCenterData *cd = &t->center_cache[t->around];
+ copy_v3_v3(cd->global, t->center_global);
+ cd->is_set = true;
+ }
+
+ calculateCenter2D(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->flag & T_CAMERA) {
+ float axis[3];
+ /* persinv is nasty, use viewinv instead, always right */
+ copy_v3_v3(axis, t->viewinv[2]);
+ normalize_v3(axis);
+
+ /* 6.0 = 6 grid units */
+ axis[0] = t->center_global[0] - 6.0f * axis[0];
+ axis[1] = t->center_global[1] - 6.0f * axis[1];
+ axis[2] = t->center_global[2] - 6.0f * axis[2];
+
+ projectFloatView(t, axis, t->center2d);
+
+ /* rotate only needs correct 2d center, grab needs ED_view3d_calc_zfac() value */
+ if (t->mode == TFM_TRANSLATION) {
+ copy_v3_v3(t->center_global, axis);
+ }
+ }
+ }
+ }
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* ED_view3d_calc_zfac() defines a factor for perspective depth correction, used in ED_view3d_win_to_delta() */
+
+ /* zfac is only used convertViewVec only in cases operator was invoked in RGN_TYPE_WINDOW
+ * and never used in other cases.
+ *
+ * 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);
+ }
+ else {
+ t->zfac = 0.0f;
+ }
+ }
}
-BLI_STATIC_ASSERT(ARRAY_SIZE(((TransInfo *)NULL)->center_cache) == (V3D_AROUND_ACTIVE + 1), "test size");
+BLI_STATIC_ASSERT(ARRAY_SIZE(((TransInfo *)NULL)->center_cache) == (V3D_AROUND_ACTIVE + 1),
+ "test size");
/**
* Lazy initialize transform center data, when we need to access center values from other types.
*/
const TransCenterData *transformCenter_from_type(TransInfo *t, int around)
{
- BLI_assert(around <= V3D_AROUND_ACTIVE);
- TransCenterData *cd = &t->center_cache[around];
- if (cd->is_set == false) {
- calculateCenter_FromAround(t, around, cd->global);
- cd->is_set = true;
- }
- return cd;
+ BLI_assert(around <= V3D_AROUND_ACTIVE);
+ TransCenterData *cd = &t->center_cache[around];
+ if (cd->is_set == false) {
+ calculateCenter_FromAround(t, around, cd->global);
+ cd->is_set = true;
+ }
+ return cd;
}
void calculatePropRatio(TransInfo *t)
{
- int i;
- float dist;
- const bool connected = (t->flag & T_PROP_CONNECTED) != 0;
-
- t->proptext[0] = '\0';
-
- if (t->flag & T_PROP_EDIT) {
- const char *pet_id = NULL;
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_SELECTED) {
- td->factor = 1.0f;
- }
- else if (tc->mirror.axis_flag && (td->loc[0] * tc->mirror.sign) < -0.00001f) {
- td->flag |= TD_SKIP;
- td->factor = 0.0f;
- restoreElement(td);
- }
- else if ((connected && (td->flag & TD_NOTCONNECTED || td->dist > t->prop_size)) ||
- (connected == 0 && td->rdist > t->prop_size))
- {
- /*
- * The elements are sorted according to their dist member in the array,
- * that means we can stop when it finds one element outside of the propsize.
- * do not set 'td->flag |= TD_NOACTION', the prop circle is being changed.
- */
-
- td->factor = 0.0f;
- restoreElement(td);
- }
- else {
- /* Use rdist for falloff calculations, it is the real distance */
- td->flag &= ~TD_NOACTION;
-
- if (connected)
- dist = (t->prop_size - td->dist) / t->prop_size;
- else
- dist = (t->prop_size - td->rdist) / t->prop_size;
-
- /*
- * Clamp to positive numbers.
- * Certain corner cases with connectivity and individual centers
- * can give values of rdist larger than propsize.
- */
- if (dist < 0.0f)
- dist = 0.0f;
-
- switch (t->prop_mode) {
- case PROP_SHARP:
- td->factor = dist * dist;
- break;
- case PROP_SMOOTH:
- td->factor = 3.0f * dist * dist - 2.0f * dist * dist * dist;
- break;
- case PROP_ROOT:
- td->factor = sqrtf(dist);
- break;
- case PROP_LIN:
- td->factor = dist;
- break;
- case PROP_CONST:
- td->factor = 1.0f;
- break;
- case PROP_SPHERE:
- td->factor = sqrtf(2 * dist - dist * dist);
- break;
- case PROP_RANDOM:
- if (t->rng == NULL) {
- /* Lazy initialization. */
- uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
- t->rng = BLI_rng_new(rng_seed);
- }
- td->factor = BLI_rng_get_float(t->rng) * dist;
- break;
- case PROP_INVSQUARE:
- td->factor = dist * (2.0f - dist);
- break;
- default:
- td->factor = 1;
- break;
- }
- }
- }
- }
-
- switch (t->prop_mode) {
- case PROP_SHARP:
- pet_id = N_("(Sharp)");
- break;
- case PROP_SMOOTH:
- pet_id = N_("(Smooth)");
- break;
- case PROP_ROOT:
- pet_id = N_("(Root)");
- break;
- case PROP_LIN:
- pet_id = N_("(Linear)");
- break;
- case PROP_CONST:
- pet_id = N_("(Constant)");
- break;
- case PROP_SPHERE:
- pet_id = N_("(Sphere)");
- break;
- case PROP_RANDOM:
- pet_id = N_("(Random)");
- break;
- case PROP_INVSQUARE:
- pet_id = N_("(InvSquare)");
- break;
- default:
- break;
- }
-
- if (pet_id) {
- BLI_strncpy(t->proptext, IFACE_(pet_id), sizeof(t->proptext));
- }
- }
- else {
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- td->factor = 1.0;
- }
- }
- }
+ int i;
+ float dist;
+ const bool connected = (t->flag & T_PROP_CONNECTED) != 0;
+
+ t->proptext[0] = '\0';
+
+ if (t->flag & T_PROP_EDIT) {
+ const char *pet_id = NULL;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_SELECTED) {
+ td->factor = 1.0f;
+ }
+ else if (tc->mirror.axis_flag && (td->loc[0] * tc->mirror.sign) < -0.00001f) {
+ td->flag |= TD_SKIP;
+ td->factor = 0.0f;
+ restoreElement(td);
+ }
+ else if ((connected && (td->flag & TD_NOTCONNECTED || td->dist > t->prop_size)) ||
+ (connected == 0 && td->rdist > t->prop_size)) {
+ /*
+ * The elements are sorted according to their dist member in the array,
+ * that means we can stop when it finds one element outside of the propsize.
+ * do not set 'td->flag |= TD_NOACTION', the prop circle is being changed.
+ */
+
+ td->factor = 0.0f;
+ restoreElement(td);
+ }
+ else {
+ /* Use rdist for falloff calculations, it is the real distance */
+ td->flag &= ~TD_NOACTION;
+
+ if (connected)
+ dist = (t->prop_size - td->dist) / t->prop_size;
+ else
+ dist = (t->prop_size - td->rdist) / t->prop_size;
+
+ /*
+ * Clamp to positive numbers.
+ * Certain corner cases with connectivity and individual centers
+ * can give values of rdist larger than propsize.
+ */
+ if (dist < 0.0f)
+ dist = 0.0f;
+
+ switch (t->prop_mode) {
+ case PROP_SHARP:
+ td->factor = dist * dist;
+ break;
+ case PROP_SMOOTH:
+ td->factor = 3.0f * dist * dist - 2.0f * dist * dist * dist;
+ break;
+ case PROP_ROOT:
+ td->factor = sqrtf(dist);
+ break;
+ case PROP_LIN:
+ td->factor = dist;
+ break;
+ case PROP_CONST:
+ td->factor = 1.0f;
+ break;
+ case PROP_SPHERE:
+ td->factor = sqrtf(2 * dist - dist * dist);
+ break;
+ case PROP_RANDOM:
+ if (t->rng == NULL) {
+ /* Lazy initialization. */
+ uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
+ t->rng = BLI_rng_new(rng_seed);
+ }
+ td->factor = BLI_rng_get_float(t->rng) * dist;
+ break;
+ case PROP_INVSQUARE:
+ td->factor = dist * (2.0f - dist);
+ break;
+ default:
+ td->factor = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ switch (t->prop_mode) {
+ case PROP_SHARP:
+ pet_id = N_("(Sharp)");
+ break;
+ case PROP_SMOOTH:
+ pet_id = N_("(Smooth)");
+ break;
+ case PROP_ROOT:
+ pet_id = N_("(Root)");
+ break;
+ case PROP_LIN:
+ pet_id = N_("(Linear)");
+ break;
+ case PROP_CONST:
+ pet_id = N_("(Constant)");
+ break;
+ case PROP_SPHERE:
+ pet_id = N_("(Sphere)");
+ break;
+ case PROP_RANDOM:
+ pet_id = N_("(Random)");
+ break;
+ case PROP_INVSQUARE:
+ pet_id = N_("(InvSquare)");
+ break;
+ default:
+ break;
+ }
+
+ if (pet_id) {
+ BLI_strncpy(t->proptext, IFACE_(pet_id), sizeof(t->proptext));
+ }
+ }
+ else {
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ td->factor = 1.0;
+ }
+ }
+ }
}
/**
@@ -2325,101 +2333,100 @@ void calculatePropRatio(TransInfo *t)
*/
void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot)
{
- float totmat[3][3];
- float smat[3][3];
- float fmat[3][3];
- float obmat[3][3];
-
- float dmat[3][3]; /* delta rotation */
- float dmat_inv[3][3];
-
- mul_m3_m3m3(totmat, mat, td->mtx);
- mul_m3_m3m3(smat, td->smtx, mat);
-
- /* logic from BKE_object_rot_to_mat3 */
- if (use_drot) {
- if (td->ext->rotOrder > 0) {
- eulO_to_mat3(dmat, td->ext->drot, td->ext->rotOrder);
- }
- else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
+ float totmat[3][3];
+ float smat[3][3];
+ float fmat[3][3];
+ float obmat[3][3];
+
+ float dmat[3][3]; /* delta rotation */
+ float dmat_inv[3][3];
+
+ mul_m3_m3m3(totmat, mat, td->mtx);
+ mul_m3_m3m3(smat, td->smtx, mat);
+
+ /* logic from BKE_object_rot_to_mat3 */
+ if (use_drot) {
+ if (td->ext->rotOrder > 0) {
+ eulO_to_mat3(dmat, td->ext->drot, td->ext->rotOrder);
+ }
+ else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
#if 0
- axis_angle_to_mat3(dmat, td->ext->drotAxis, td->ext->drotAngle);
+ axis_angle_to_mat3(dmat, td->ext->drotAxis, td->ext->drotAngle);
#else
- unit_m3(dmat);
+ unit_m3(dmat);
#endif
- }
- else {
- float tquat[4];
- normalize_qt_qt(tquat, td->ext->dquat);
- quat_to_mat3(dmat, tquat);
- }
-
- invert_m3_m3(dmat_inv, dmat);
- }
-
-
- if (td->ext->rotOrder == ROT_MODE_QUAT) {
- float quat[4];
-
- /* calculate the total rotatation */
- quat_to_mat3(obmat, td->ext->iquat);
- if (use_drot) {
- mul_m3_m3m3(obmat, dmat, obmat);
- }
-
- /* mat = transform, obmat = object rotation */
- mul_m3_m3m3(fmat, smat, obmat);
-
- if (use_drot) {
- mul_m3_m3m3(fmat, dmat_inv, fmat);
- }
-
- mat3_to_quat(quat, fmat);
-
- /* apply */
- copy_qt_qt(td->ext->quat, quat);
- }
- else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
- float axis[3], angle;
-
- /* calculate the total rotatation */
- axis_angle_to_mat3(obmat, td->ext->irotAxis, td->ext->irotAngle);
- if (use_drot) {
- mul_m3_m3m3(obmat, dmat, obmat);
- }
-
- /* mat = transform, obmat = object rotation */
- mul_m3_m3m3(fmat, smat, obmat);
-
- if (use_drot) {
- mul_m3_m3m3(fmat, dmat_inv, fmat);
- }
-
- mat3_to_axis_angle(axis, &angle, fmat);
-
- /* apply */
- copy_v3_v3(td->ext->rotAxis, axis);
- *td->ext->rotAngle = angle;
- }
- else {
- float eul[3];
-
- /* calculate the total rotatation */
- eulO_to_mat3(obmat, td->ext->irot, td->ext->rotOrder);
- if (use_drot) {
- mul_m3_m3m3(obmat, dmat, obmat);
- }
-
- /* mat = transform, obmat = object rotation */
- mul_m3_m3m3(fmat, smat, obmat);
-
- if (use_drot) {
- mul_m3_m3m3(fmat, dmat_inv, fmat);
- }
-
- mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
-
- /* apply */
- copy_v3_v3(td->ext->rot, eul);
- }
+ }
+ else {
+ float tquat[4];
+ normalize_qt_qt(tquat, td->ext->dquat);
+ quat_to_mat3(dmat, tquat);
+ }
+
+ invert_m3_m3(dmat_inv, dmat);
+ }
+
+ if (td->ext->rotOrder == ROT_MODE_QUAT) {
+ float quat[4];
+
+ /* calculate the total rotatation */
+ quat_to_mat3(obmat, td->ext->iquat);
+ if (use_drot) {
+ mul_m3_m3m3(obmat, dmat, obmat);
+ }
+
+ /* mat = transform, obmat = object rotation */
+ mul_m3_m3m3(fmat, smat, obmat);
+
+ if (use_drot) {
+ mul_m3_m3m3(fmat, dmat_inv, fmat);
+ }
+
+ mat3_to_quat(quat, fmat);
+
+ /* apply */
+ copy_qt_qt(td->ext->quat, quat);
+ }
+ else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
+ float axis[3], angle;
+
+ /* calculate the total rotatation */
+ axis_angle_to_mat3(obmat, td->ext->irotAxis, td->ext->irotAngle);
+ if (use_drot) {
+ mul_m3_m3m3(obmat, dmat, obmat);
+ }
+
+ /* mat = transform, obmat = object rotation */
+ mul_m3_m3m3(fmat, smat, obmat);
+
+ if (use_drot) {
+ mul_m3_m3m3(fmat, dmat_inv, fmat);
+ }
+
+ mat3_to_axis_angle(axis, &angle, fmat);
+
+ /* apply */
+ copy_v3_v3(td->ext->rotAxis, axis);
+ *td->ext->rotAngle = angle;
+ }
+ else {
+ float eul[3];
+
+ /* calculate the total rotatation */
+ eulO_to_mat3(obmat, td->ext->irot, td->ext->rotOrder);
+ if (use_drot) {
+ mul_m3_m3m3(obmat, dmat, obmat);
+ }
+
+ /* mat = transform, obmat = object rotation */
+ mul_m3_m3m3(fmat, smat, obmat);
+
+ if (use_drot) {
+ mul_m3_m3m3(fmat, dmat_inv, fmat);
+ }
+
+ mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
+
+ /* apply */
+ copy_v3_v3(td->ext->rot, eul);
+ }
}
diff --git a/source/blender/editors/transform/transform_gizmo_2d.c b/source/blender/editors/transform/transform_gizmo_2d.c
index cbc72f99168..f5b8f19ed02 100644
--- a/source/blender/editors/transform/transform_gizmo_2d.c
+++ b/source/blender/editors/transform/transform_gizmo_2d.c
@@ -54,93 +54,92 @@
/* axes as index */
enum {
- MAN2D_AXIS_TRANS_X = 0,
- MAN2D_AXIS_TRANS_Y,
+ MAN2D_AXIS_TRANS_X = 0,
+ MAN2D_AXIS_TRANS_Y,
- MAN2D_AXIS_LAST,
+ MAN2D_AXIS_LAST,
};
typedef struct GizmoGroup2D {
- wmGizmo *translate_x,
- *translate_y;
+ wmGizmo *translate_x, *translate_y;
- wmGizmo *cage;
+ wmGizmo *cage;
- /* Current origin in view space, used to update widget origin for possible view changes */
- float origin[2];
- float min[2];
- float max[2];
+ /* Current origin in view space, used to update widget origin for possible view changes */
+ float origin[2];
+ float min[2];
+ float max[2];
} GizmoGroup2D;
-
/* **************** Utilities **************** */
/* loop over axes */
#define MAN2D_ITER_AXES_BEGIN(axis, axis_idx) \
- { \
- wmGizmo *axis; \
- int axis_idx; \
- for (axis_idx = 0; axis_idx < MAN2D_AXIS_LAST; axis_idx++) { \
- axis = gizmo2d_get_axis_from_index(ggd, axis_idx);
+ { \
+ wmGizmo *axis; \
+ int axis_idx; \
+ for (axis_idx = 0; axis_idx < MAN2D_AXIS_LAST; axis_idx++) { \
+ axis = gizmo2d_get_axis_from_index(ggd, axis_idx);
#define MAN2D_ITER_AXES_END \
- } \
- } ((void)0)
+ } \
+ } \
+ ((void)0)
static wmGizmo *gizmo2d_get_axis_from_index(const GizmoGroup2D *ggd, const short axis_idx)
{
- BLI_assert(IN_RANGE_INCL(axis_idx, (float)MAN2D_AXIS_TRANS_X, (float)MAN2D_AXIS_TRANS_Y));
+ BLI_assert(IN_RANGE_INCL(axis_idx, (float)MAN2D_AXIS_TRANS_X, (float)MAN2D_AXIS_TRANS_Y));
- switch (axis_idx) {
- case MAN2D_AXIS_TRANS_X:
- return ggd->translate_x;
- case MAN2D_AXIS_TRANS_Y:
- return ggd->translate_y;
- }
+ switch (axis_idx) {
+ case MAN2D_AXIS_TRANS_X:
+ return ggd->translate_x;
+ case MAN2D_AXIS_TRANS_Y:
+ return ggd->translate_y;
+ }
- return NULL;
+ return NULL;
}
static void gizmo2d_get_axis_color(const int axis_idx, float *r_col, float *r_col_hi)
{
- const float alpha = 0.6f;
- const float alpha_hi = 1.0f;
- int col_id;
-
- switch (axis_idx) {
- case MAN2D_AXIS_TRANS_X:
- col_id = TH_AXIS_X;
- break;
- case MAN2D_AXIS_TRANS_Y:
- col_id = TH_AXIS_Y;
- break;
- }
-
- UI_GetThemeColor4fv(col_id, r_col);
-
- copy_v4_v4(r_col_hi, r_col);
- r_col[3] *= alpha;
- r_col_hi[3] *= alpha_hi;
+ const float alpha = 0.6f;
+ const float alpha_hi = 1.0f;
+ int col_id;
+
+ switch (axis_idx) {
+ case MAN2D_AXIS_TRANS_X:
+ col_id = TH_AXIS_X;
+ break;
+ case MAN2D_AXIS_TRANS_Y:
+ col_id = TH_AXIS_Y;
+ break;
+ }
+
+ UI_GetThemeColor4fv(col_id, r_col);
+
+ copy_v4_v4(r_col_hi, r_col);
+ r_col[3] *= alpha;
+ r_col_hi[3] *= alpha_hi;
}
static GizmoGroup2D *gizmogroup2d_init(wmGizmoGroup *gzgroup)
{
- const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_2d", true);
- const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_2d", true);
+ const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_2d", true);
+ const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_2d", true);
- GizmoGroup2D *ggd = MEM_callocN(sizeof(GizmoGroup2D), __func__);
+ GizmoGroup2D *ggd = MEM_callocN(sizeof(GizmoGroup2D), __func__);
- ggd->translate_x = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
- ggd->translate_y = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
- ggd->cage = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL);
+ ggd->translate_x = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ ggd->translate_y = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ ggd->cage = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL);
- RNA_enum_set(ggd->cage->ptr, "transform",
- ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE |
- ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE |
- ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE);
+ RNA_enum_set(ggd->cage->ptr,
+ "transform",
+ ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE |
+ ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE);
- return ggd;
+ return ggd;
}
/**
@@ -148,33 +147,33 @@ static GizmoGroup2D *gizmogroup2d_init(wmGizmoGroup *gzgroup)
*/
static void gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min, float *r_max)
{
- float min_buf[2], max_buf[2];
- if (r_min == NULL) {
- r_min = min_buf;
- }
- if (r_max == NULL) {
- r_max = max_buf;
- }
-
- ScrArea *sa = CTX_wm_area(C);
- if (sa->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = sa->spacedata.first;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Image *ima = ED_space_image(sima);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
- view_layer, NULL, &objects_len);
- if (!ED_uvedit_minmax_multi(CTX_data_scene(C), ima, objects, objects_len, r_min, r_max)) {
- zero_v2(r_min);
- zero_v2(r_max);
- }
- MEM_freeN(objects);
- }
- else {
- zero_v2(r_min);
- zero_v2(r_max);
- }
- mid_v2_v2v2(r_center, r_min, r_max);
+ float min_buf[2], max_buf[2];
+ if (r_min == NULL) {
+ r_min = min_buf;
+ }
+ if (r_max == NULL) {
+ r_max = max_buf;
+ }
+
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = sa->spacedata.first;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Image *ima = ED_space_image(sima);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, NULL, &objects_len);
+ if (!ED_uvedit_minmax_multi(CTX_data_scene(C), ima, objects, objects_len, r_min, r_max)) {
+ zero_v2(r_min);
+ zero_v2(r_max);
+ }
+ MEM_freeN(objects);
+ }
+ else {
+ zero_v2(r_min);
+ zero_v2(r_max);
+ }
+ mid_v2_v2v2(r_center, r_min, r_max);
}
/**
@@ -182,171 +181,183 @@ static void gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min
*/
BLI_INLINE void gizmo2d_origin_to_region(ARegion *ar, 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(&ar->v2d, r_origin[0], r_origin[1], &r_origin[0], &r_origin[1]);
}
/**
* Custom handler for gizmo widgets
*/
-static int gizmo2d_modal(
- bContext *C, wmGizmo *widget, const wmEvent *UNUSED(event),
- eWM_GizmoFlagTweak UNUSED(tweak_flag))
+static int gizmo2d_modal(bContext *C,
+ wmGizmo *widget,
+ const wmEvent *UNUSED(event),
+ eWM_GizmoFlagTweak UNUSED(tweak_flag))
{
- ARegion *ar = CTX_wm_region(C);
- float origin[3];
+ ARegion *ar = CTX_wm_region(C);
+ float origin[3];
- gizmo2d_calc_bounds(C, origin, NULL, NULL);
- gizmo2d_origin_to_region(ar, origin);
- WM_gizmo_set_matrix_location(widget, origin);
+ gizmo2d_calc_bounds(C, origin, NULL, NULL);
+ gizmo2d_origin_to_region(ar, origin);
+ WM_gizmo_set_matrix_location(widget, origin);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void ED_widgetgroup_gizmo2d_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- wmOperatorType *ot_translate = WM_operatortype_find("TRANSFORM_OT_translate", true);
- GizmoGroup2D *ggd = gizmogroup2d_init(gzgroup);
- gzgroup->customdata = ggd;
-
- MAN2D_ITER_AXES_BEGIN(axis, axis_idx)
- {
- const float offset[3] = {0.0f, 0.2f};
-
- float color[4], color_hi[4];
- gizmo2d_get_axis_color(axis_idx, color, color_hi);
-
- /* custom handler! */
- WM_gizmo_set_fn_custom_modal(axis, gizmo2d_modal);
- /* set up widget data */
- RNA_float_set(axis->ptr, "angle", -M_PI_2 * axis_idx);
- RNA_float_set(axis->ptr, "length", 0.8f);
- WM_gizmo_set_matrix_offset_location(axis, offset);
- WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH);
- WM_gizmo_set_scale(axis, U.gizmo_size);
- WM_gizmo_set_color(axis, color);
- WM_gizmo_set_color_highlight(axis, color_hi);
-
- /* assign operator */
- PointerRNA *ptr = WM_gizmo_operator_set(axis, 0, ot_translate, NULL);
- bool constraint[3] = {0};
- constraint[(axis_idx + 1) % 2] = 1;
- if (RNA_struct_find_property(ptr, "constraint_axis"))
- RNA_boolean_set_array(ptr, "constraint_axis", constraint);
- RNA_boolean_set(ptr, "release_confirm", 1);
- }
- MAN2D_ITER_AXES_END;
-
- {
- wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
- wmOperatorType *ot_rotate = WM_operatortype_find("TRANSFORM_OT_rotate", true);
- PointerRNA *ptr;
-
- /* assign operator */
- ptr = WM_gizmo_operator_set(ggd->cage, 0, ot_translate, NULL);
- RNA_boolean_set(ptr, "release_confirm", 1);
-
- bool constraint_x[3] = {1, 0, 0};
- bool constraint_y[3] = {0, 1, 0};
-
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X, ot_resize, NULL);
- PropertyRNA *prop_release_confirm = RNA_struct_find_property(ptr, "release_confirm");
- PropertyRNA *prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
- RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_x);
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X, ot_resize, NULL);
- RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_x);
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y, ot_resize, NULL);
- RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_y);
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y, ot_resize, NULL);
- RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_y);
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
-
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y, ot_resize, NULL);
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y, ot_resize, NULL);
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y, ot_resize, NULL);
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y, ot_resize, NULL);
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_ROTATE, ot_rotate, NULL);
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
- }
+ wmOperatorType *ot_translate = WM_operatortype_find("TRANSFORM_OT_translate", true);
+ GizmoGroup2D *ggd = gizmogroup2d_init(gzgroup);
+ gzgroup->customdata = ggd;
+
+ MAN2D_ITER_AXES_BEGIN (axis, axis_idx) {
+ const float offset[3] = {0.0f, 0.2f};
+
+ float color[4], color_hi[4];
+ gizmo2d_get_axis_color(axis_idx, color, color_hi);
+
+ /* custom handler! */
+ WM_gizmo_set_fn_custom_modal(axis, gizmo2d_modal);
+ /* set up widget data */
+ RNA_float_set(axis->ptr, "angle", -M_PI_2 * axis_idx);
+ RNA_float_set(axis->ptr, "length", 0.8f);
+ WM_gizmo_set_matrix_offset_location(axis, offset);
+ WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH);
+ WM_gizmo_set_scale(axis, U.gizmo_size);
+ WM_gizmo_set_color(axis, color);
+ WM_gizmo_set_color_highlight(axis, color_hi);
+
+ /* assign operator */
+ PointerRNA *ptr = WM_gizmo_operator_set(axis, 0, ot_translate, NULL);
+ bool constraint[3] = {0};
+ constraint[(axis_idx + 1) % 2] = 1;
+ if (RNA_struct_find_property(ptr, "constraint_axis"))
+ RNA_boolean_set_array(ptr, "constraint_axis", constraint);
+ RNA_boolean_set(ptr, "release_confirm", 1);
+ }
+ MAN2D_ITER_AXES_END;
+
+ {
+ wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
+ wmOperatorType *ot_rotate = WM_operatortype_find("TRANSFORM_OT_rotate", true);
+ PointerRNA *ptr;
+
+ /* assign operator */
+ ptr = WM_gizmo_operator_set(ggd->cage, 0, ot_translate, NULL);
+ RNA_boolean_set(ptr, "release_confirm", 1);
+
+ bool constraint_x[3] = {1, 0, 0};
+ bool constraint_y[3] = {0, 1, 0};
+
+ ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X, ot_resize, NULL);
+ PropertyRNA *prop_release_confirm = RNA_struct_find_property(ptr, "release_confirm");
+ PropertyRNA *prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_x);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X, ot_resize, NULL);
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_x);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y, ot_resize, NULL);
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_y);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y, ot_resize, NULL);
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_y);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+
+ ptr = WM_gizmo_operator_set(
+ ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y, ot_resize, NULL);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_gizmo_operator_set(
+ ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y, ot_resize, NULL);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_gizmo_operator_set(
+ ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y, ot_resize, NULL);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_gizmo_operator_set(
+ ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y, ot_resize, NULL);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_ROTATE, ot_rotate, NULL);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ }
}
void ED_widgetgroup_gizmo2d_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoGroup2D *ggd = gzgroup->customdata;
- float origin[3];
- gizmo2d_calc_bounds(C, origin, ggd->min, ggd->max);
- copy_v2_v2(ggd->origin, origin);
- bool show_cage = !equals_v2v2(ggd->min, ggd->max);
-
- if (show_cage) {
- ggd->cage->flag &= ~WM_GIZMO_HIDDEN;
- ggd->translate_x->flag |= WM_GIZMO_HIDDEN;
- ggd->translate_y->flag |= WM_GIZMO_HIDDEN;
- }
- else {
- ggd->cage->flag |= WM_GIZMO_HIDDEN;
- ggd->translate_x->flag &= ~WM_GIZMO_HIDDEN;
- ggd->translate_y->flag &= ~WM_GIZMO_HIDDEN;
- }
-
- if (show_cage) {
- wmGizmoOpElem *gzop;
- float mid[2];
- const float *min = ggd->min;
- const float *max = ggd->max;
- mid_v2_v2v2(mid, min, max);
-
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X);
- PropertyRNA *prop_center_override = RNA_struct_find_property(&gzop->ptr, "center_override");
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, (float[3]){max[0], mid[1], 0.0f});
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X);
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, (float[3]){min[0], mid[1], 0.0f});
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y);
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, (float[3]){mid[0], max[1], 0.0f});
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y);
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, (float[3]){mid[0], min[1], 0.0f});
-
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y);
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, (float[3]){max[0], max[1], 0.0f});
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y);
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, (float[3]){max[0], min[1], 0.0f});
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y);
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, (float[3]){min[0], max[1], 0.0f});
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y);
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, (float[3]){min[0], min[1], 0.0f});
-
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_ROTATE);
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, (float[3]){mid[0], mid[1], 0.0f});
- }
+ GizmoGroup2D *ggd = gzgroup->customdata;
+ float origin[3];
+ gizmo2d_calc_bounds(C, origin, ggd->min, ggd->max);
+ copy_v2_v2(ggd->origin, origin);
+ bool show_cage = !equals_v2v2(ggd->min, ggd->max);
+
+ if (show_cage) {
+ ggd->cage->flag &= ~WM_GIZMO_HIDDEN;
+ ggd->translate_x->flag |= WM_GIZMO_HIDDEN;
+ ggd->translate_y->flag |= WM_GIZMO_HIDDEN;
+ }
+ else {
+ ggd->cage->flag |= WM_GIZMO_HIDDEN;
+ ggd->translate_x->flag &= ~WM_GIZMO_HIDDEN;
+ ggd->translate_y->flag &= ~WM_GIZMO_HIDDEN;
+ }
+
+ if (show_cage) {
+ wmGizmoOpElem *gzop;
+ float mid[2];
+ const float *min = ggd->min;
+ const float *max = ggd->max;
+ mid_v2_v2v2(mid, min, max);
+
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X);
+ PropertyRNA *prop_center_override = RNA_struct_find_property(&gzop->ptr, "center_override");
+ RNA_property_float_set_array(
+ &gzop->ptr, prop_center_override, (float[3]){max[0], mid[1], 0.0f});
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X);
+ RNA_property_float_set_array(
+ &gzop->ptr, prop_center_override, (float[3]){min[0], mid[1], 0.0f});
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y);
+ RNA_property_float_set_array(
+ &gzop->ptr, prop_center_override, (float[3]){mid[0], max[1], 0.0f});
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y);
+ RNA_property_float_set_array(
+ &gzop->ptr, prop_center_override, (float[3]){mid[0], min[1], 0.0f});
+
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y);
+ RNA_property_float_set_array(
+ &gzop->ptr, prop_center_override, (float[3]){max[0], max[1], 0.0f});
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y);
+ RNA_property_float_set_array(
+ &gzop->ptr, prop_center_override, (float[3]){max[0], min[1], 0.0f});
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y);
+ RNA_property_float_set_array(
+ &gzop->ptr, prop_center_override, (float[3]){min[0], max[1], 0.0f});
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y);
+ RNA_property_float_set_array(
+ &gzop->ptr, prop_center_override, (float[3]){min[0], min[1], 0.0f});
+
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_ROTATE);
+ RNA_property_float_set_array(
+ &gzop->ptr, prop_center_override, (float[3]){mid[0], mid[1], 0.0f});
+ }
}
void ED_widgetgroup_gizmo2d_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- ARegion *ar = 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);
-
- MAN2D_ITER_AXES_BEGIN(axis, axis_idx)
- {
- WM_gizmo_set_matrix_location(axis, origin);
- }
- MAN2D_ITER_AXES_END;
-
- UI_view2d_view_to_region_m4(&ar->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]);
+ ARegion *ar = 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);
+
+ MAN2D_ITER_AXES_BEGIN (axis, axis_idx) {
+ WM_gizmo_set_matrix_location(axis, origin);
+ }
+ MAN2D_ITER_AXES_END;
+
+ UI_view2d_view_to_region_m4(&ar->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]);
}
/* TODO (Julian)
@@ -355,35 +366,35 @@ void ED_widgetgroup_gizmo2d_draw_prepare(const bContext *C, wmGizmoGroup *gzgrou
*/
bool ED_widgetgroup_gizmo2d_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
- if ((U.gizmo_flag & USER_GIZMO_DRAW) == 0) {
- return false;
- }
-
- SpaceImage *sima = CTX_wm_space_image(C);
- Object *obedit = CTX_data_edit_object(C);
-
- if (ED_space_image_show_uvedit(sima, obedit)) {
- Image *ima = ED_space_image(sima);
- Scene *scene = CTX_data_scene(C);
- 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);
-
- /* check if there's a selected poly */
- 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 (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- return true;
- }
- }
- }
- }
-
- return false;
+ if ((U.gizmo_flag & USER_GIZMO_DRAW) == 0) {
+ return false;
+ }
+
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Object *obedit = CTX_data_edit_object(C);
+
+ if (ED_space_image_show_uvedit(sima, obedit)) {
+ Image *ima = ED_space_image(sima);
+ Scene *scene = CTX_data_scene(C);
+ 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);
+
+ /* check if there's a selected poly */
+ 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 (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
}
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index 77480e1a8ce..1fde0006c2b 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -94,89 +94,89 @@
/* return codes for select, and drawing flags */
-#define MAN_TRANS_X (1 << 0)
-#define MAN_TRANS_Y (1 << 1)
-#define MAN_TRANS_Z (1 << 2)
-#define MAN_TRANS_C (MAN_TRANS_X | MAN_TRANS_Y | MAN_TRANS_Z)
+#define MAN_TRANS_X (1 << 0)
+#define MAN_TRANS_Y (1 << 1)
+#define MAN_TRANS_Z (1 << 2)
+#define MAN_TRANS_C (MAN_TRANS_X | MAN_TRANS_Y | MAN_TRANS_Z)
-#define MAN_ROT_X (1 << 3)
-#define MAN_ROT_Y (1 << 4)
-#define MAN_ROT_Z (1 << 5)
-#define MAN_ROT_C (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z)
+#define MAN_ROT_X (1 << 3)
+#define MAN_ROT_Y (1 << 4)
+#define MAN_ROT_Z (1 << 5)
+#define MAN_ROT_C (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z)
-#define MAN_SCALE_X (1 << 8)
-#define MAN_SCALE_Y (1 << 9)
-#define MAN_SCALE_Z (1 << 10)
-#define MAN_SCALE_C (MAN_SCALE_X | MAN_SCALE_Y | MAN_SCALE_Z)
+#define MAN_SCALE_X (1 << 8)
+#define MAN_SCALE_Y (1 << 9)
+#define MAN_SCALE_Z (1 << 10)
+#define MAN_SCALE_C (MAN_SCALE_X | MAN_SCALE_Y | MAN_SCALE_Z)
/* threshold for testing view aligned gizmo axis */
static struct {
- float min, max;
+ float min, max;
} g_tw_axis_range[2] = {
- /* Regular range */
- {0.02f, 0.1f},
- /* Use a different range because we flip the dot product,
- * also the view aligned planes are harder to see so hiding early is preferred. */
- {0.175f, 0.25f},
+ /* Regular range */
+ {0.02f, 0.1f},
+ /* Use a different range because we flip the dot product,
+ * also the view aligned planes are harder to see so hiding early is preferred. */
+ {0.175f, 0.25f},
};
/* axes as index */
enum {
- MAN_AXIS_TRANS_X = 0,
- MAN_AXIS_TRANS_Y,
- MAN_AXIS_TRANS_Z,
- MAN_AXIS_TRANS_C,
-
- MAN_AXIS_TRANS_XY,
- MAN_AXIS_TRANS_YZ,
- MAN_AXIS_TRANS_ZX,
+ MAN_AXIS_TRANS_X = 0,
+ MAN_AXIS_TRANS_Y,
+ MAN_AXIS_TRANS_Z,
+ MAN_AXIS_TRANS_C,
+
+ MAN_AXIS_TRANS_XY,
+ MAN_AXIS_TRANS_YZ,
+ MAN_AXIS_TRANS_ZX,
#define MAN_AXIS_RANGE_TRANS_START MAN_AXIS_TRANS_X
#define MAN_AXIS_RANGE_TRANS_END (MAN_AXIS_TRANS_ZX + 1)
- MAN_AXIS_ROT_X,
- MAN_AXIS_ROT_Y,
- MAN_AXIS_ROT_Z,
- MAN_AXIS_ROT_C,
- MAN_AXIS_ROT_T, /* trackball rotation */
+ MAN_AXIS_ROT_X,
+ MAN_AXIS_ROT_Y,
+ MAN_AXIS_ROT_Z,
+ MAN_AXIS_ROT_C,
+ MAN_AXIS_ROT_T, /* trackball rotation */
#define MAN_AXIS_RANGE_ROT_START MAN_AXIS_ROT_X
#define MAN_AXIS_RANGE_ROT_END (MAN_AXIS_ROT_T + 1)
- MAN_AXIS_SCALE_X,
- MAN_AXIS_SCALE_Y,
- MAN_AXIS_SCALE_Z,
- MAN_AXIS_SCALE_C,
- MAN_AXIS_SCALE_XY,
- MAN_AXIS_SCALE_YZ,
- MAN_AXIS_SCALE_ZX,
+ MAN_AXIS_SCALE_X,
+ MAN_AXIS_SCALE_Y,
+ MAN_AXIS_SCALE_Z,
+ MAN_AXIS_SCALE_C,
+ MAN_AXIS_SCALE_XY,
+ MAN_AXIS_SCALE_YZ,
+ MAN_AXIS_SCALE_ZX,
#define MAN_AXIS_RANGE_SCALE_START MAN_AXIS_SCALE_X
#define MAN_AXIS_RANGE_SCALE_END (MAN_AXIS_SCALE_ZX + 1)
- MAN_AXIS_LAST = MAN_AXIS_SCALE_ZX + 1,
+ MAN_AXIS_LAST = MAN_AXIS_SCALE_ZX + 1,
};
/* axis types */
enum {
- MAN_AXES_ALL = 0,
- MAN_AXES_TRANSLATE,
- MAN_AXES_ROTATE,
- MAN_AXES_SCALE,
+ MAN_AXES_ALL = 0,
+ MAN_AXES_TRANSLATE,
+ MAN_AXES_ROTATE,
+ MAN_AXES_SCALE,
};
typedef struct GizmoGroup {
- bool all_hidden;
- int twtype;
+ bool all_hidden;
+ int twtype;
- /* Users may change the twtype, detect changes to re-setup gizmo options. */
- int twtype_init;
- int twtype_prev;
- int use_twtype_refresh;
+ /* Users may change the twtype, detect changes to re-setup gizmo options. */
+ int twtype_init;
+ int twtype_prev;
+ int use_twtype_refresh;
- /* Only for view orientation. */
- struct {
- float viewinv_m3[3][3];
- } prev;
+ /* Only for view orientation. */
+ struct {
+ float viewinv_m3[3][3];
+ } prev;
- struct wmGizmo *gizmos[MAN_AXIS_LAST];
+ struct wmGizmo *gizmos[MAN_AXIS_LAST];
} GizmoGroup;
/* -------------------------------------------------------------------- */
@@ -185,991 +185,987 @@ typedef struct GizmoGroup {
/* loop over axes */
#define MAN_ITER_AXES_BEGIN(axis, axis_idx) \
- { \
- wmGizmo *axis; \
- int axis_idx; \
- for (axis_idx = 0; axis_idx < MAN_AXIS_LAST; axis_idx++) { \
- axis = gizmo_get_axis_from_index(ggd, axis_idx);
+ { \
+ wmGizmo *axis; \
+ int axis_idx; \
+ for (axis_idx = 0; axis_idx < MAN_AXIS_LAST; axis_idx++) { \
+ axis = gizmo_get_axis_from_index(ggd, axis_idx);
#define MAN_ITER_AXES_END \
- } \
- } ((void)0)
+ } \
+ } \
+ ((void)0)
static wmGizmo *gizmo_get_axis_from_index(const GizmoGroup *ggd, const short axis_idx)
{
- BLI_assert(IN_RANGE_INCL(axis_idx, (float)MAN_AXIS_TRANS_X, (float)MAN_AXIS_LAST));
- return ggd->gizmos[axis_idx];
+ BLI_assert(IN_RANGE_INCL(axis_idx, (float)MAN_AXIS_TRANS_X, (float)MAN_AXIS_LAST));
+ return ggd->gizmos[axis_idx];
}
static short gizmo_get_axis_type(const int axis_idx)
{
- if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
- return MAN_AXES_TRANSLATE;
- }
- if (axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) {
- return MAN_AXES_ROTATE;
- }
- if (axis_idx >= MAN_AXIS_RANGE_SCALE_START && axis_idx < MAN_AXIS_RANGE_SCALE_END) {
- return MAN_AXES_SCALE;
- }
- BLI_assert(0);
- return -1;
+ if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
+ return MAN_AXES_TRANSLATE;
+ }
+ if (axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) {
+ return MAN_AXES_ROTATE;
+ }
+ if (axis_idx >= MAN_AXIS_RANGE_SCALE_START && axis_idx < MAN_AXIS_RANGE_SCALE_END) {
+ return MAN_AXES_SCALE;
+ }
+ BLI_assert(0);
+ return -1;
}
static uint gizmo_orientation_axis(const int axis_idx, bool *r_is_plane)
{
- switch (axis_idx) {
- case MAN_AXIS_TRANS_YZ:
- case MAN_AXIS_SCALE_YZ:
- if (r_is_plane) {
- *r_is_plane = true;
- }
- ATTR_FALLTHROUGH;
- case MAN_AXIS_TRANS_X:
- case MAN_AXIS_ROT_X:
- case MAN_AXIS_SCALE_X:
- return 0;
-
- case MAN_AXIS_TRANS_ZX:
- case MAN_AXIS_SCALE_ZX:
- if (r_is_plane) {
- *r_is_plane = true;
- }
- ATTR_FALLTHROUGH;
- case MAN_AXIS_TRANS_Y:
- case MAN_AXIS_ROT_Y:
- case MAN_AXIS_SCALE_Y:
- return 1;
-
- case MAN_AXIS_TRANS_XY:
- case MAN_AXIS_SCALE_XY:
- if (r_is_plane) {
- *r_is_plane = true;
- }
- ATTR_FALLTHROUGH;
- case MAN_AXIS_TRANS_Z:
- case MAN_AXIS_ROT_Z:
- case MAN_AXIS_SCALE_Z:
- return 2;
- }
- return 3;
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_YZ:
+ case MAN_AXIS_SCALE_YZ:
+ if (r_is_plane) {
+ *r_is_plane = true;
+ }
+ ATTR_FALLTHROUGH;
+ case MAN_AXIS_TRANS_X:
+ case MAN_AXIS_ROT_X:
+ case MAN_AXIS_SCALE_X:
+ return 0;
+
+ case MAN_AXIS_TRANS_ZX:
+ case MAN_AXIS_SCALE_ZX:
+ if (r_is_plane) {
+ *r_is_plane = true;
+ }
+ ATTR_FALLTHROUGH;
+ case MAN_AXIS_TRANS_Y:
+ case MAN_AXIS_ROT_Y:
+ case MAN_AXIS_SCALE_Y:
+ return 1;
+
+ case MAN_AXIS_TRANS_XY:
+ case MAN_AXIS_SCALE_XY:
+ if (r_is_plane) {
+ *r_is_plane = true;
+ }
+ ATTR_FALLTHROUGH;
+ case MAN_AXIS_TRANS_Z:
+ case MAN_AXIS_ROT_Z:
+ case MAN_AXIS_SCALE_Z:
+ return 2;
+ }
+ return 3;
}
-static bool gizmo_is_axis_visible(
- const RegionView3D *rv3d, const int twtype,
- const float idot[3], const int axis_type, const int axis_idx)
+static bool gizmo_is_axis_visible(const RegionView3D *rv3d,
+ const int twtype,
+ const float idot[3],
+ const int axis_type,
+ const int axis_idx)
{
- if ((axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) == 0) {
- bool is_plane = false;
- const uint aidx_norm = gizmo_orientation_axis(axis_idx, &is_plane);
- /* don't draw axis perpendicular to the view */
- if (aidx_norm < 3) {
- float idot_axis = idot[aidx_norm];
- if (is_plane) {
- idot_axis = 1.0f - idot_axis;
- }
- if (idot_axis < g_tw_axis_range[is_plane].min) {
- return false;
- }
- }
- }
-
- if ((axis_type == MAN_AXES_TRANSLATE && !(twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE)) ||
- (axis_type == MAN_AXES_ROTATE && !(twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE)) ||
- (axis_type == MAN_AXES_SCALE && !(twtype & V3D_GIZMO_SHOW_OBJECT_SCALE)))
- {
- return false;
- }
-
- switch (axis_idx) {
- case MAN_AXIS_TRANS_X:
- return (rv3d->twdrawflag & MAN_TRANS_X);
- case MAN_AXIS_TRANS_Y:
- return (rv3d->twdrawflag & MAN_TRANS_Y);
- case MAN_AXIS_TRANS_Z:
- return (rv3d->twdrawflag & MAN_TRANS_Z);
- case MAN_AXIS_TRANS_C:
- return (rv3d->twdrawflag & MAN_TRANS_C);
- case MAN_AXIS_ROT_X:
- return (rv3d->twdrawflag & MAN_ROT_X);
- case MAN_AXIS_ROT_Y:
- return (rv3d->twdrawflag & MAN_ROT_Y);
- case MAN_AXIS_ROT_Z:
- return (rv3d->twdrawflag & MAN_ROT_Z);
- case MAN_AXIS_ROT_C:
- case MAN_AXIS_ROT_T:
- return (rv3d->twdrawflag & MAN_ROT_C);
- case MAN_AXIS_SCALE_X:
- return (rv3d->twdrawflag & MAN_SCALE_X);
- case MAN_AXIS_SCALE_Y:
- return (rv3d->twdrawflag & MAN_SCALE_Y);
- case MAN_AXIS_SCALE_Z:
- return (rv3d->twdrawflag & MAN_SCALE_Z);
- case MAN_AXIS_SCALE_C:
- return (rv3d->twdrawflag & MAN_SCALE_C && (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0);
- case MAN_AXIS_TRANS_XY:
- return (rv3d->twdrawflag & MAN_TRANS_X &&
- rv3d->twdrawflag & MAN_TRANS_Y &&
- (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
- case MAN_AXIS_TRANS_YZ:
- return (rv3d->twdrawflag & MAN_TRANS_Y &&
- rv3d->twdrawflag & MAN_TRANS_Z &&
- (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
- case MAN_AXIS_TRANS_ZX:
- return (rv3d->twdrawflag & MAN_TRANS_Z &&
- rv3d->twdrawflag & MAN_TRANS_X &&
- (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
- case MAN_AXIS_SCALE_XY:
- return (rv3d->twdrawflag & MAN_SCALE_X &&
- rv3d->twdrawflag & MAN_SCALE_Y &&
- (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0 &&
- (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
- case MAN_AXIS_SCALE_YZ:
- return (rv3d->twdrawflag & MAN_SCALE_Y &&
- rv3d->twdrawflag & MAN_SCALE_Z &&
- (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0 &&
- (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
- case MAN_AXIS_SCALE_ZX:
- return (rv3d->twdrawflag & MAN_SCALE_Z &&
- rv3d->twdrawflag & MAN_SCALE_X &&
- (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0 &&
- (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
- }
- return false;
+ if ((axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) == 0) {
+ bool is_plane = false;
+ const uint aidx_norm = gizmo_orientation_axis(axis_idx, &is_plane);
+ /* don't draw axis perpendicular to the view */
+ if (aidx_norm < 3) {
+ float idot_axis = idot[aidx_norm];
+ if (is_plane) {
+ idot_axis = 1.0f - idot_axis;
+ }
+ if (idot_axis < g_tw_axis_range[is_plane].min) {
+ return false;
+ }
+ }
+ }
+
+ if ((axis_type == MAN_AXES_TRANSLATE && !(twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE)) ||
+ (axis_type == MAN_AXES_ROTATE && !(twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE)) ||
+ (axis_type == MAN_AXES_SCALE && !(twtype & V3D_GIZMO_SHOW_OBJECT_SCALE))) {
+ return false;
+ }
+
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_X:
+ return (rv3d->twdrawflag & MAN_TRANS_X);
+ case MAN_AXIS_TRANS_Y:
+ return (rv3d->twdrawflag & MAN_TRANS_Y);
+ case MAN_AXIS_TRANS_Z:
+ return (rv3d->twdrawflag & MAN_TRANS_Z);
+ case MAN_AXIS_TRANS_C:
+ return (rv3d->twdrawflag & MAN_TRANS_C);
+ case MAN_AXIS_ROT_X:
+ return (rv3d->twdrawflag & MAN_ROT_X);
+ case MAN_AXIS_ROT_Y:
+ return (rv3d->twdrawflag & MAN_ROT_Y);
+ case MAN_AXIS_ROT_Z:
+ return (rv3d->twdrawflag & MAN_ROT_Z);
+ case MAN_AXIS_ROT_C:
+ case MAN_AXIS_ROT_T:
+ return (rv3d->twdrawflag & MAN_ROT_C);
+ case MAN_AXIS_SCALE_X:
+ return (rv3d->twdrawflag & MAN_SCALE_X);
+ case MAN_AXIS_SCALE_Y:
+ return (rv3d->twdrawflag & MAN_SCALE_Y);
+ case MAN_AXIS_SCALE_Z:
+ return (rv3d->twdrawflag & MAN_SCALE_Z);
+ case MAN_AXIS_SCALE_C:
+ return (rv3d->twdrawflag & MAN_SCALE_C && (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0);
+ case MAN_AXIS_TRANS_XY:
+ return (rv3d->twdrawflag & MAN_TRANS_X && rv3d->twdrawflag & MAN_TRANS_Y &&
+ (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
+ case MAN_AXIS_TRANS_YZ:
+ return (rv3d->twdrawflag & MAN_TRANS_Y && rv3d->twdrawflag & MAN_TRANS_Z &&
+ (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
+ case MAN_AXIS_TRANS_ZX:
+ return (rv3d->twdrawflag & MAN_TRANS_Z && rv3d->twdrawflag & MAN_TRANS_X &&
+ (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
+ case MAN_AXIS_SCALE_XY:
+ return (rv3d->twdrawflag & MAN_SCALE_X && rv3d->twdrawflag & MAN_SCALE_Y &&
+ (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0 &&
+ (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
+ case MAN_AXIS_SCALE_YZ:
+ return (rv3d->twdrawflag & MAN_SCALE_Y && rv3d->twdrawflag & MAN_SCALE_Z &&
+ (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0 &&
+ (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
+ case MAN_AXIS_SCALE_ZX:
+ return (rv3d->twdrawflag & MAN_SCALE_Z && rv3d->twdrawflag & MAN_SCALE_X &&
+ (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0 &&
+ (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
+ }
+ return false;
}
-static void gizmo_get_axis_color(
- const int axis_idx, const float idot[3],
- float r_col[4], float r_col_hi[4])
+static void gizmo_get_axis_color(const int axis_idx,
+ const float idot[3],
+ float r_col[4],
+ float r_col_hi[4])
{
- /* alpha values for normal/highlighted states */
- const float alpha = 0.6f;
- const float alpha_hi = 1.0f;
- float alpha_fac;
-
- 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;
- }
- else {
- bool is_plane = false;
- const int axis_idx_norm = gizmo_orientation_axis(axis_idx, &is_plane);
- /* get alpha fac based on axis angle, to fade axis out when hiding it because it points towards view */
- if (axis_idx_norm < 3) {
- const float idot_min = g_tw_axis_range[is_plane].min;
- const float idot_max = g_tw_axis_range[is_plane].max;
- float idot_axis = idot[axis_idx_norm];
- if (is_plane) {
- idot_axis = 1.0f - idot_axis;
- }
- alpha_fac = (
- (idot_axis > idot_max) ?
- 1.0f : (idot_axis < idot_min) ?
- 0.0f : ((idot_axis - idot_min) / (idot_max - idot_min)));
- }
- else {
- alpha_fac = 1.0f;
- }
- }
-
- switch (axis_idx) {
- case MAN_AXIS_TRANS_X:
- case MAN_AXIS_ROT_X:
- case MAN_AXIS_SCALE_X:
- case MAN_AXIS_TRANS_YZ:
- case MAN_AXIS_SCALE_YZ:
- UI_GetThemeColor4fv(TH_AXIS_X, r_col);
- break;
- case MAN_AXIS_TRANS_Y:
- case MAN_AXIS_ROT_Y:
- case MAN_AXIS_SCALE_Y:
- case MAN_AXIS_TRANS_ZX:
- case MAN_AXIS_SCALE_ZX:
- UI_GetThemeColor4fv(TH_AXIS_Y, r_col);
- break;
- case MAN_AXIS_TRANS_Z:
- case MAN_AXIS_ROT_Z:
- case MAN_AXIS_SCALE_Z:
- case MAN_AXIS_TRANS_XY:
- case MAN_AXIS_SCALE_XY:
- UI_GetThemeColor4fv(TH_AXIS_Z, r_col);
- break;
- case MAN_AXIS_TRANS_C:
- case MAN_AXIS_ROT_C:
- case MAN_AXIS_SCALE_C:
- case MAN_AXIS_ROT_T:
- copy_v4_fl(r_col, 1.0f);
- break;
- }
-
- copy_v4_v4(r_col_hi, r_col);
-
- r_col[3] = alpha * alpha_fac;
- r_col_hi[3] = alpha_hi * alpha_fac;
+ /* alpha values for normal/highlighted states */
+ const float alpha = 0.6f;
+ const float alpha_hi = 1.0f;
+ float alpha_fac;
+
+ 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;
+ }
+ else {
+ bool is_plane = false;
+ const int axis_idx_norm = gizmo_orientation_axis(axis_idx, &is_plane);
+ /* get alpha fac based on axis angle, to fade axis out when hiding it because it points towards view */
+ if (axis_idx_norm < 3) {
+ const float idot_min = g_tw_axis_range[is_plane].min;
+ const float idot_max = g_tw_axis_range[is_plane].max;
+ float idot_axis = idot[axis_idx_norm];
+ if (is_plane) {
+ idot_axis = 1.0f - idot_axis;
+ }
+ alpha_fac = ((idot_axis > idot_max) ?
+ 1.0f :
+ (idot_axis < idot_min) ? 0.0f :
+ ((idot_axis - idot_min) / (idot_max - idot_min)));
+ }
+ else {
+ alpha_fac = 1.0f;
+ }
+ }
+
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_X:
+ case MAN_AXIS_ROT_X:
+ case MAN_AXIS_SCALE_X:
+ case MAN_AXIS_TRANS_YZ:
+ case MAN_AXIS_SCALE_YZ:
+ UI_GetThemeColor4fv(TH_AXIS_X, r_col);
+ break;
+ case MAN_AXIS_TRANS_Y:
+ case MAN_AXIS_ROT_Y:
+ case MAN_AXIS_SCALE_Y:
+ case MAN_AXIS_TRANS_ZX:
+ case MAN_AXIS_SCALE_ZX:
+ UI_GetThemeColor4fv(TH_AXIS_Y, r_col);
+ break;
+ case MAN_AXIS_TRANS_Z:
+ case MAN_AXIS_ROT_Z:
+ case MAN_AXIS_SCALE_Z:
+ case MAN_AXIS_TRANS_XY:
+ case MAN_AXIS_SCALE_XY:
+ UI_GetThemeColor4fv(TH_AXIS_Z, r_col);
+ break;
+ case MAN_AXIS_TRANS_C:
+ case MAN_AXIS_ROT_C:
+ case MAN_AXIS_SCALE_C:
+ case MAN_AXIS_ROT_T:
+ copy_v4_fl(r_col, 1.0f);
+ break;
+ }
+
+ copy_v4_v4(r_col_hi, r_col);
+
+ r_col[3] = alpha * alpha_fac;
+ r_col_hi[3] = alpha_hi * alpha_fac;
}
static void gizmo_get_axis_constraint(const int axis_idx, bool r_axis[3])
{
- ARRAY_SET_ITEMS(r_axis, 0, 0, 0);
-
- switch (axis_idx) {
- case MAN_AXIS_TRANS_X:
- case MAN_AXIS_ROT_X:
- case MAN_AXIS_SCALE_X:
- r_axis[0] = 1;
- break;
- case MAN_AXIS_TRANS_Y:
- case MAN_AXIS_ROT_Y:
- case MAN_AXIS_SCALE_Y:
- r_axis[1] = 1;
- break;
- case MAN_AXIS_TRANS_Z:
- case MAN_AXIS_ROT_Z:
- case MAN_AXIS_SCALE_Z:
- r_axis[2] = 1;
- break;
- case MAN_AXIS_TRANS_XY:
- case MAN_AXIS_SCALE_XY:
- r_axis[0] = r_axis[1] = 1;
- break;
- case MAN_AXIS_TRANS_YZ:
- case MAN_AXIS_SCALE_YZ:
- r_axis[1] = r_axis[2] = 1;
- break;
- case MAN_AXIS_TRANS_ZX:
- case MAN_AXIS_SCALE_ZX:
- r_axis[2] = r_axis[0] = 1;
- break;
- default:
- break;
- }
+ ARRAY_SET_ITEMS(r_axis, 0, 0, 0);
+
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_X:
+ case MAN_AXIS_ROT_X:
+ case MAN_AXIS_SCALE_X:
+ r_axis[0] = 1;
+ break;
+ case MAN_AXIS_TRANS_Y:
+ case MAN_AXIS_ROT_Y:
+ case MAN_AXIS_SCALE_Y:
+ r_axis[1] = 1;
+ break;
+ case MAN_AXIS_TRANS_Z:
+ case MAN_AXIS_ROT_Z:
+ case MAN_AXIS_SCALE_Z:
+ r_axis[2] = 1;
+ break;
+ case MAN_AXIS_TRANS_XY:
+ case MAN_AXIS_SCALE_XY:
+ r_axis[0] = r_axis[1] = 1;
+ break;
+ case MAN_AXIS_TRANS_YZ:
+ case MAN_AXIS_SCALE_YZ:
+ r_axis[1] = r_axis[2] = 1;
+ break;
+ case MAN_AXIS_TRANS_ZX:
+ case MAN_AXIS_SCALE_ZX:
+ r_axis[2] = r_axis[0] = 1;
+ break;
+ default:
+ break;
+ }
}
-
/* **************** Preparation Stuff **************** */
static void reset_tw_center(struct TransformBounds *tbounds)
{
- INIT_MINMAX(tbounds->min, tbounds->max);
- zero_v3(tbounds->center);
+ INIT_MINMAX(tbounds->min, tbounds->max);
+ zero_v3(tbounds->center);
- for (int i = 0; i < 3; i++) {
- tbounds->axis_min[i] = +FLT_MAX;
- tbounds->axis_max[i] = -FLT_MAX;
- }
+ for (int i = 0; i < 3; i++) {
+ tbounds->axis_min[i] = +FLT_MAX;
+ tbounds->axis_max[i] = -FLT_MAX;
+ }
}
/* transform widget center calc helper for below */
static void calc_tw_center(struct TransformBounds *tbounds, const float co[3])
{
- minmax_v3v3_v3(tbounds->min, tbounds->max, co);
- add_v3_v3(tbounds->center, co);
-
- for (int i = 0; i < 3; i++) {
- const float d = dot_v3v3(tbounds->axis[i], co);
- tbounds->axis_min[i] = min_ff(d, tbounds->axis_min[i]);
- tbounds->axis_max[i] = max_ff(d, tbounds->axis_max[i]);
- }
+ minmax_v3v3_v3(tbounds->min, tbounds->max, co);
+ add_v3_v3(tbounds->center, co);
+
+ for (int i = 0; i < 3; i++) {
+ const float d = dot_v3v3(tbounds->axis[i], co);
+ tbounds->axis_min[i] = min_ff(d, tbounds->axis_min[i]);
+ tbounds->axis_max[i] = max_ff(d, tbounds->axis_max[i]);
+ }
}
-static void calc_tw_center_with_matrix(
- struct TransformBounds *tbounds, const float co[3],
- const bool use_matrix, const float matrix[4][4])
+static void calc_tw_center_with_matrix(struct TransformBounds *tbounds,
+ const float co[3],
+ const bool use_matrix,
+ const float matrix[4][4])
{
- float co_world[3];
- if (use_matrix) {
- mul_v3_m4v3(co_world, matrix, co);
- co = co_world;
- }
- calc_tw_center(tbounds, co);
+ float co_world[3];
+ if (use_matrix) {
+ mul_v3_m4v3(co_world, matrix, co);
+ co = co_world;
+ }
+ calc_tw_center(tbounds, co);
}
static void protectflag_to_drawflags(short protectflag, short *drawflags)
{
- if (protectflag & OB_LOCK_LOCX)
- *drawflags &= ~MAN_TRANS_X;
- if (protectflag & OB_LOCK_LOCY)
- *drawflags &= ~MAN_TRANS_Y;
- if (protectflag & OB_LOCK_LOCZ)
- *drawflags &= ~MAN_TRANS_Z;
-
- if (protectflag & OB_LOCK_ROTX)
- *drawflags &= ~MAN_ROT_X;
- if (protectflag & OB_LOCK_ROTY)
- *drawflags &= ~MAN_ROT_Y;
- if (protectflag & OB_LOCK_ROTZ)
- *drawflags &= ~MAN_ROT_Z;
-
- if (protectflag & OB_LOCK_SCALEX)
- *drawflags &= ~MAN_SCALE_X;
- if (protectflag & OB_LOCK_SCALEY)
- *drawflags &= ~MAN_SCALE_Y;
- if (protectflag & OB_LOCK_SCALEZ)
- *drawflags &= ~MAN_SCALE_Z;
+ if (protectflag & OB_LOCK_LOCX)
+ *drawflags &= ~MAN_TRANS_X;
+ if (protectflag & OB_LOCK_LOCY)
+ *drawflags &= ~MAN_TRANS_Y;
+ if (protectflag & OB_LOCK_LOCZ)
+ *drawflags &= ~MAN_TRANS_Z;
+
+ if (protectflag & OB_LOCK_ROTX)
+ *drawflags &= ~MAN_ROT_X;
+ if (protectflag & OB_LOCK_ROTY)
+ *drawflags &= ~MAN_ROT_Y;
+ if (protectflag & OB_LOCK_ROTZ)
+ *drawflags &= ~MAN_ROT_Z;
+
+ if (protectflag & OB_LOCK_SCALEX)
+ *drawflags &= ~MAN_SCALE_X;
+ if (protectflag & OB_LOCK_SCALEY)
+ *drawflags &= ~MAN_SCALE_Y;
+ if (protectflag & OB_LOCK_SCALEZ)
+ *drawflags &= ~MAN_SCALE_Z;
}
/* for pose mode */
static void protectflag_to_drawflags_pchan(RegionView3D *rv3d, const bPoseChannel *pchan)
{
- protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag);
+ protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag);
}
/* for editmode*/
static void protectflag_to_drawflags_ebone(RegionView3D *rv3d, const EditBone *ebo)
{
- if (ebo->flag & BONE_EDITMODE_LOCKED) {
- protectflag_to_drawflags(OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE, &rv3d->twdrawflag);
- }
+ if (ebo->flag & BONE_EDITMODE_LOCKED) {
+ protectflag_to_drawflags(OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE, &rv3d->twdrawflag);
+ }
}
/* could move into BLI_math however this is only useful for display/editing purposes */
static void axis_angle_to_gimbal_axis(float gmat[3][3], const float axis[3], const float angle)
{
- /* X/Y are arbitrary axies, most importantly Z is the axis of rotation */
+ /* X/Y are arbitrary axies, most importantly Z is the axis of rotation */
- float cross_vec[3];
- float quat[4];
+ float cross_vec[3];
+ float quat[4];
- /* this is an un-scientific method to get a vector to cross with
- * XYZ intentionally YZX */
- cross_vec[0] = axis[1];
- cross_vec[1] = axis[2];
- cross_vec[2] = axis[0];
+ /* this is an un-scientific method to get a vector to cross with
+ * XYZ intentionally YZX */
+ cross_vec[0] = axis[1];
+ cross_vec[1] = axis[2];
+ cross_vec[2] = axis[0];
- /* X-axis */
- cross_v3_v3v3(gmat[0], cross_vec, axis);
- normalize_v3(gmat[0]);
- axis_angle_to_quat(quat, axis, angle);
- mul_qt_v3(quat, gmat[0]);
+ /* X-axis */
+ cross_v3_v3v3(gmat[0], cross_vec, axis);
+ normalize_v3(gmat[0]);
+ axis_angle_to_quat(quat, axis, angle);
+ mul_qt_v3(quat, gmat[0]);
- /* Y-axis */
- axis_angle_to_quat(quat, axis, M_PI_2);
- copy_v3_v3(gmat[1], gmat[0]);
- mul_qt_v3(quat, gmat[1]);
+ /* Y-axis */
+ axis_angle_to_quat(quat, axis, M_PI_2);
+ copy_v3_v3(gmat[1], gmat[0]);
+ mul_qt_v3(quat, gmat[1]);
- /* Z-axis */
- copy_v3_v3(gmat[2], axis);
+ /* Z-axis */
+ copy_v3_v3(gmat[2], axis);
- normalize_m3(gmat);
+ normalize_m3(gmat);
}
-
static bool test_rotmode_euler(short rotmode)
{
- return (ELEM(rotmode, ROT_MODE_AXISANGLE, ROT_MODE_QUAT)) ? 0 : 1;
+ return (ELEM(rotmode, ROT_MODE_AXISANGLE, ROT_MODE_QUAT)) ? 0 : 1;
}
bool gimbal_axis(Object *ob, float gmat[3][3])
{
- if (ob->mode & OB_MODE_POSE) {
- bPoseChannel *pchan = BKE_pose_channel_active(ob);
-
- if (pchan) {
- float mat[3][3], tmat[3][3], obmat[3][3];
- if (test_rotmode_euler(pchan->rotmode)) {
- eulO_to_gimbal_axis(mat, pchan->eul, pchan->rotmode);
- }
- else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- axis_angle_to_gimbal_axis(mat, pchan->rotAxis, pchan->rotAngle);
- }
- else { /* quat */
- return 0;
- }
-
-
- /* apply bone transformation */
- mul_m3_m3m3(tmat, pchan->bone->bone_mat, mat);
-
- if (pchan->parent) {
- float parent_mat[3][3];
-
- copy_m3_m4(parent_mat, pchan->parent->pose_mat);
- mul_m3_m3m3(mat, parent_mat, tmat);
-
- /* needed if object transformation isn't identity */
- copy_m3_m4(obmat, ob->obmat);
- mul_m3_m3m3(gmat, obmat, mat);
- }
- else {
- /* needed if object transformation isn't identity */
- copy_m3_m4(obmat, ob->obmat);
- mul_m3_m3m3(gmat, obmat, tmat);
- }
-
- normalize_m3(gmat);
- return 1;
- }
- }
- else {
- if (test_rotmode_euler(ob->rotmode)) {
- eulO_to_gimbal_axis(gmat, ob->rot, ob->rotmode);
- }
- else if (ob->rotmode == ROT_MODE_AXISANGLE) {
- axis_angle_to_gimbal_axis(gmat, ob->rotAxis, ob->rotAngle);
- }
- else { /* quat */
- return 0;
- }
-
- if (ob->parent) {
- float parent_mat[3][3];
- copy_m3_m4(parent_mat, ob->parent->obmat);
- normalize_m3(parent_mat);
- mul_m3_m3m3(gmat, parent_mat, gmat);
- }
- return 1;
- }
-
- return 0;
+ if (ob->mode & OB_MODE_POSE) {
+ bPoseChannel *pchan = BKE_pose_channel_active(ob);
+
+ if (pchan) {
+ float mat[3][3], tmat[3][3], obmat[3][3];
+ if (test_rotmode_euler(pchan->rotmode)) {
+ eulO_to_gimbal_axis(mat, pchan->eul, pchan->rotmode);
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ axis_angle_to_gimbal_axis(mat, pchan->rotAxis, pchan->rotAngle);
+ }
+ else { /* quat */
+ return 0;
+ }
+
+ /* apply bone transformation */
+ mul_m3_m3m3(tmat, pchan->bone->bone_mat, mat);
+
+ if (pchan->parent) {
+ float parent_mat[3][3];
+
+ copy_m3_m4(parent_mat, pchan->parent->pose_mat);
+ mul_m3_m3m3(mat, parent_mat, tmat);
+
+ /* needed if object transformation isn't identity */
+ copy_m3_m4(obmat, ob->obmat);
+ mul_m3_m3m3(gmat, obmat, mat);
+ }
+ else {
+ /* needed if object transformation isn't identity */
+ copy_m3_m4(obmat, ob->obmat);
+ mul_m3_m3m3(gmat, obmat, tmat);
+ }
+
+ normalize_m3(gmat);
+ return 1;
+ }
+ }
+ else {
+ if (test_rotmode_euler(ob->rotmode)) {
+ eulO_to_gimbal_axis(gmat, ob->rot, ob->rotmode);
+ }
+ else if (ob->rotmode == ROT_MODE_AXISANGLE) {
+ axis_angle_to_gimbal_axis(gmat, ob->rotAxis, ob->rotAngle);
+ }
+ else { /* quat */
+ return 0;
+ }
+
+ if (ob->parent) {
+ float parent_mat[3][3];
+ copy_m3_m4(parent_mat, ob->parent->obmat);
+ normalize_m3(parent_mat);
+ mul_m3_m3m3(gmat, parent_mat, gmat);
+ }
+ return 1;
+ }
+
+ return 0;
}
-void ED_transform_calc_orientation_from_type(
- const bContext *C, float r_mat[3][3])
+void ED_transform_calc_orientation_from_type(const bContext *C, float r_mat[3][3])
{
- ARegion *ar = 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;
- Object *ob = OBACT(view_layer);
- const short orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
- const short orientation_index_custom = scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
- const int pivot_point = scene->toolsettings->transform_pivot_point;
-
- ED_transform_calc_orientation_from_type_ex(
- C, r_mat,
- scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point);
+ ARegion *ar = 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;
+ Object *ob = OBACT(view_layer);
+ const short orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
+ const short orientation_index_custom = scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
+ const int pivot_point = scene->toolsettings->transform_pivot_point;
+
+ ED_transform_calc_orientation_from_type_ex(
+ C, r_mat, scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point);
}
-void ED_transform_calc_orientation_from_type_ex(
- const bContext *C, float r_mat[3][3],
- /* extra args (can be accessed from context) */
- Scene *scene, RegionView3D *rv3d, Object *ob, Object *obedit,
- const short orientation_type, int orientation_index_custom,
- const int pivot_point)
+void ED_transform_calc_orientation_from_type_ex(const bContext *C,
+ float r_mat[3][3],
+ /* extra args (can be accessed from context) */
+ Scene *scene,
+ RegionView3D *rv3d,
+ Object *ob,
+ Object *obedit,
+ const short orientation_type,
+ int orientation_index_custom,
+ const int pivot_point)
{
- bool ok = false;
-
- switch (orientation_type) {
- case V3D_ORIENT_GLOBAL:
- {
- break; /* nothing to do */
- }
- case V3D_ORIENT_GIMBAL:
- {
- if (gimbal_axis(ob, r_mat)) {
- ok = true;
- break;
- }
- /* if not gimbal, fall through to normal */
- ATTR_FALLTHROUGH;
- }
- case V3D_ORIENT_NORMAL:
- {
- if (obedit || ob->mode & OB_MODE_POSE) {
- ED_getTransformOrientationMatrix(C, r_mat, pivot_point);
- ok = true;
- break;
- }
- /* no break we define 'normal' as 'local' in Object mode */
- ATTR_FALLTHROUGH;
- }
- case V3D_ORIENT_LOCAL:
- {
- if (ob->mode & OB_MODE_POSE) {
- /* each bone moves on its own local axis, but to avoid confusion,
- * use the active pones axis for display [#33575], this works as expected on a single bone
- * and users who select many bones will understand what's going on and what local means
- * when they start transforming */
- ED_getTransformOrientationMatrix(C, r_mat, pivot_point);
- ok = true;
- break;
- }
- copy_m3_m4(r_mat, ob->obmat);
- normalize_m3(r_mat);
- ok = true;
- break;
- }
- case V3D_ORIENT_VIEW:
- {
- if (rv3d != NULL) {
- copy_m3_m4(r_mat, rv3d->viewinv);
- normalize_m3(r_mat);
- ok = true;
- }
- break;
- }
- case V3D_ORIENT_CURSOR:
- {
- ED_view3d_cursor3d_calc_mat3(scene, r_mat);
- ok = true;
- break;
- }
- case V3D_ORIENT_CUSTOM:
- {
- TransformOrientation *custom_orientation = BKE_scene_transform_orientation_find(
- scene, orientation_index_custom);
- if (applyTransformOrientation(custom_orientation, r_mat, NULL)) {
- ok = true;
- }
- break;
- }
- }
-
- if (!ok) {
- unit_m3(r_mat);
- }
+ bool ok = false;
+
+ switch (orientation_type) {
+ case V3D_ORIENT_GLOBAL: {
+ break; /* nothing to do */
+ }
+ case V3D_ORIENT_GIMBAL: {
+ if (gimbal_axis(ob, r_mat)) {
+ ok = true;
+ break;
+ }
+ /* if not gimbal, fall through to normal */
+ ATTR_FALLTHROUGH;
+ }
+ case V3D_ORIENT_NORMAL: {
+ if (obedit || ob->mode & OB_MODE_POSE) {
+ ED_getTransformOrientationMatrix(C, r_mat, pivot_point);
+ ok = true;
+ break;
+ }
+ /* no break we define 'normal' as 'local' in Object mode */
+ ATTR_FALLTHROUGH;
+ }
+ case V3D_ORIENT_LOCAL: {
+ if (ob->mode & OB_MODE_POSE) {
+ /* each bone moves on its own local axis, but to avoid confusion,
+ * use the active pones axis for display [#33575], this works as expected on a single bone
+ * and users who select many bones will understand what's going on and what local means
+ * when they start transforming */
+ ED_getTransformOrientationMatrix(C, r_mat, pivot_point);
+ ok = true;
+ break;
+ }
+ copy_m3_m4(r_mat, ob->obmat);
+ normalize_m3(r_mat);
+ ok = true;
+ break;
+ }
+ case V3D_ORIENT_VIEW: {
+ if (rv3d != NULL) {
+ copy_m3_m4(r_mat, rv3d->viewinv);
+ normalize_m3(r_mat);
+ ok = true;
+ }
+ break;
+ }
+ case V3D_ORIENT_CURSOR: {
+ ED_view3d_cursor3d_calc_mat3(scene, r_mat);
+ ok = true;
+ break;
+ }
+ case V3D_ORIENT_CUSTOM: {
+ TransformOrientation *custom_orientation = BKE_scene_transform_orientation_find(
+ scene, orientation_index_custom);
+ if (applyTransformOrientation(custom_orientation, r_mat, NULL)) {
+ ok = true;
+ }
+ break;
+ }
+ }
+
+ if (!ok) {
+ unit_m3(r_mat);
+ }
}
/* centroid, boundbox, of selection */
/* returns total items selected */
-int ED_transform_calc_gizmo_stats(
- const bContext *C,
- const struct TransformCalcParams *params,
- struct TransformBounds *tbounds)
+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);
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = sa->spacedata.first;
- Object *obedit = CTX_data_edit_object(C);
- RegionView3D *rv3d = ar->regiondata;
- Base *base;
- Object *ob = OBACT(view_layer);
- bGPdata *gpd = CTX_data_gpencil_data(C);
- const bool is_gp_edit = GPENCIL_ANY_MODE(gpd);
- int a, totsel = 0;
- const int pivot_point = scene->toolsettings->transform_pivot_point;
-
- /* transform widget matrix */
- unit_m4(rv3d->twmat);
-
- unit_m3(rv3d->tw_axis_matrix);
- zero_v3(rv3d->tw_axis_min);
- zero_v3(rv3d->tw_axis_max);
-
- rv3d->twdrawflag = 0xFFFF;
-
- /* global, local or normal orientation?
- * if we could check 'totsel' now, this should be skipped with no selection. */
- if (ob) {
- const short orientation_type = params->orientation_type ?
- (params->orientation_type - 1) : scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
- const short orientation_index_custom = params->orientation_type ?
- params->orientation_index_custom : scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
- float mat[3][3];
- ED_transform_calc_orientation_from_type_ex(
- C, mat,
- scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point);
- copy_m4_m3(rv3d->twmat, mat);
- }
-
- /* transform widget centroid/center */
- reset_tw_center(tbounds);
-
- copy_m3_m4(tbounds->axis, rv3d->twmat);
- if (params->use_local_axis && (ob && ob->mode & OB_MODE_EDIT)) {
- float diff_mat[3][3];
- copy_m3_m4(diff_mat, ob->obmat);
- normalize_m3(diff_mat);
- invert_m3(diff_mat);
- mul_m3_m3m3(tbounds->axis, tbounds->axis, diff_mat);
- normalize_m3(tbounds->axis);
- }
-
- 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) {
- /* only editable and visible layers are considered */
-
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
-
- /* calculate difference matrix */
- ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat);
-
- for (bGPDstroke *gps = gpl->actframe->strokes.first; gps; gps = gps->next) {
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps) == false) {
- continue;
- }
-
- /* we're only interested in selected points here... */
- if (gps->flag & GP_STROKE_SELECT) {
- bGPDspoint *pt;
- int i;
-
- /* Change selection status of all points, then make the stroke match */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT) {
- calc_tw_center_with_matrix(tbounds, &pt->x, use_mat_local, diff_mat);
- totsel++;
- }
- }
- }
- }
- }
- }
-
-
- /* selection center */
- if (totsel) {
- mul_v3_fl(tbounds->center, 1.0f / (float)totsel); /* centroid! */
- }
- }
- else if (obedit) {
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = sa->spacedata.first;
+ Object *obedit = CTX_data_edit_object(C);
+ RegionView3D *rv3d = ar->regiondata;
+ Base *base;
+ Object *ob = OBACT(view_layer);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ const bool is_gp_edit = GPENCIL_ANY_MODE(gpd);
+ int a, totsel = 0;
+ const int pivot_point = scene->toolsettings->transform_pivot_point;
+
+ /* transform widget matrix */
+ unit_m4(rv3d->twmat);
+
+ unit_m3(rv3d->tw_axis_matrix);
+ zero_v3(rv3d->tw_axis_min);
+ zero_v3(rv3d->tw_axis_max);
+
+ rv3d->twdrawflag = 0xFFFF;
+
+ /* global, local or normal orientation?
+ * if we could check 'totsel' now, this should be skipped with no selection. */
+ if (ob) {
+ const short orientation_type = params->orientation_type ?
+ (params->orientation_type - 1) :
+ scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
+ const short orientation_index_custom =
+ params->orientation_type ? params->orientation_index_custom :
+ scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
+ float mat[3][3];
+ ED_transform_calc_orientation_from_type_ex(
+ C, mat, scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point);
+ copy_m4_m3(rv3d->twmat, mat);
+ }
+
+ /* transform widget centroid/center */
+ reset_tw_center(tbounds);
+
+ copy_m3_m4(tbounds->axis, rv3d->twmat);
+ if (params->use_local_axis && (ob && ob->mode & OB_MODE_EDIT)) {
+ float diff_mat[3][3];
+ copy_m3_m4(diff_mat, ob->obmat);
+ normalize_m3(diff_mat);
+ invert_m3(diff_mat);
+ mul_m3_m3m3(tbounds->axis, tbounds->axis, diff_mat);
+ normalize_m3(tbounds->axis);
+ }
+
+ 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) {
+ /* only editable and visible layers are considered */
+
+ if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+
+ /* calculate difference matrix */
+ ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat);
+
+ for (bGPDstroke *gps = gpl->actframe->strokes.first; gps; gps = gps->next) {
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+
+ /* we're only interested in selected points here... */
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ /* Change selection status of all points, then make the stroke match */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ calc_tw_center_with_matrix(tbounds, &pt->x, use_mat_local, diff_mat);
+ totsel++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* selection center */
+ if (totsel) {
+ mul_v3_fl(tbounds->center, 1.0f / (float)totsel); /* centroid! */
+ }
+ }
+ else if (obedit) {
#define FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) \
- { \
- invert_m4_m4(obedit->imat, obedit->obmat); \
- uint objects_len = 0; \
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(view_layer, CTX_wm_view3d(C), &objects_len); \
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) { \
- Object *ob_iter = objects[ob_index]; \
- const bool use_mat_local = (ob_iter != obedit);
+ { \
+ invert_m4_m4(obedit->imat, obedit->obmat); \
+ uint objects_len = 0; \
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( \
+ view_layer, CTX_wm_view3d(C), &objects_len); \
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) { \
+ Object *ob_iter = objects[ob_index]; \
+ const bool use_mat_local = (ob_iter != obedit);
#define FOREACH_EDIT_OBJECT_END() \
- } \
- MEM_freeN(objects); \
- } ((void)0)
-
- ob = obedit;
- if (obedit->type == OB_MESH) {
- FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
- BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
- BMesh *bm = em_iter->bm;
-
- if (bm->totvertsel == 0) {
- continue;
- }
-
- BMVert *eve;
- BMIter iter;
-
- float mat_local[4][4];
- if (use_mat_local) {
- mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
- }
-
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- calc_tw_center_with_matrix(tbounds, eve->co, use_mat_local, mat_local);
- totsel++;
- }
- }
- }
- } FOREACH_EDIT_OBJECT_END();
- } /* end editmesh */
- else if (obedit->type == OB_ARMATURE) {
- FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
- bArmature *arm = ob_iter->data;
-
- float mat_local[4][4];
- if (use_mat_local) {
- mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
- }
- for (EditBone *ebo = arm->edbo->first; ebo; ebo = ebo->next) {
- if (EBONE_VISIBLE(arm, ebo)) {
- if (ebo->flag & BONE_TIPSEL) {
- calc_tw_center_with_matrix(tbounds, ebo->tail, use_mat_local, mat_local);
- totsel++;
- }
- if ((ebo->flag & BONE_ROOTSEL) &&
- /* don't include same point multiple times */
- ((ebo->flag & BONE_CONNECTED) &&
- (ebo->parent != NULL) &&
- (ebo->parent->flag & BONE_TIPSEL) &&
- EBONE_VISIBLE(arm, ebo->parent)) == 0)
- {
- calc_tw_center_with_matrix(tbounds, ebo->head, use_mat_local, mat_local);
- totsel++;
- }
- if (ebo->flag & BONE_SELECTED) {
- protectflag_to_drawflags_ebone(rv3d, ebo);
- }
- }
- }
- } FOREACH_EDIT_OBJECT_END();
- }
- else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
- FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
- Curve *cu = ob_iter->data;
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- ListBase *nurbs = BKE_curve_editNurbs_get(cu);
-
- float mat_local[4][4];
- if (use_mat_local) {
- mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
- }
-
- nu = nurbs->first;
- while (nu) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- /* exceptions
- * if handles are hidden then only check the center points.
- * If the center knot is selected then only use this as the center point.
- */
- if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
- if (bezt->f2 & SELECT) {
- calc_tw_center_with_matrix(tbounds, bezt->vec[1], use_mat_local, mat_local);
- totsel++;
- }
- }
- else if (bezt->f2 & SELECT) {
- calc_tw_center_with_matrix(tbounds, bezt->vec[1], use_mat_local, mat_local);
- totsel++;
- }
- else {
- if (bezt->f1 & SELECT) {
- const float *co = bezt->vec[(pivot_point == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 0];
- calc_tw_center_with_matrix(tbounds, co, use_mat_local, mat_local);
- totsel++;
- }
- if (bezt->f3 & SELECT) {
- const float *co = bezt->vec[(pivot_point == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 2];
- calc_tw_center_with_matrix(tbounds, co, use_mat_local, mat_local);
- totsel++;
- }
- }
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (bp->f1 & SELECT) {
- calc_tw_center_with_matrix(tbounds, bp->vec, use_mat_local, mat_local);
- totsel++;
- }
- bp++;
- }
- }
- nu = nu->next;
- }
- } FOREACH_EDIT_OBJECT_END();
- }
- else if (obedit->type == OB_MBALL) {
- FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
- MetaBall *mb = (MetaBall *)ob_iter->data;
-
- float mat_local[4][4];
- if (use_mat_local) {
- mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
- }
-
- for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) {
- if (ml->flag & SELECT) {
- calc_tw_center_with_matrix(tbounds, &ml->x, use_mat_local, mat_local);
- totsel++;
- }
- }
- } FOREACH_EDIT_OBJECT_END();
- }
- else if (obedit->type == OB_LATTICE) {
- FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
- Lattice *lt = ((Lattice *)ob_iter->data)->editlatt->latt;
- BPoint *bp = lt->def;
- a = lt->pntsu * lt->pntsv * lt->pntsw;
-
- float mat_local[4][4];
- if (use_mat_local) {
- mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
- }
-
- while (a--) {
- if (bp->f1 & SELECT) {
- calc_tw_center_with_matrix(tbounds, bp->vec, use_mat_local, mat_local);
- totsel++;
- }
- bp++;
- }
- } FOREACH_EDIT_OBJECT_END();
- }
+ } \
+ MEM_freeN(objects); \
+ } \
+ ((void)0)
+
+ ob = obedit;
+ if (obedit->type == OB_MESH) {
+ FOREACH_EDIT_OBJECT_BEGIN (ob_iter, use_mat_local) {
+ BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
+ BMesh *bm = em_iter->bm;
+
+ if (bm->totvertsel == 0) {
+ continue;
+ }
+
+ BMVert *eve;
+ BMIter iter;
+
+ float mat_local[4][4];
+ if (use_mat_local) {
+ mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+ }
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ calc_tw_center_with_matrix(tbounds, eve->co, use_mat_local, mat_local);
+ totsel++;
+ }
+ }
+ }
+ }
+ FOREACH_EDIT_OBJECT_END();
+ } /* end editmesh */
+ else if (obedit->type == OB_ARMATURE) {
+ FOREACH_EDIT_OBJECT_BEGIN (ob_iter, use_mat_local) {
+ bArmature *arm = ob_iter->data;
+
+ float mat_local[4][4];
+ if (use_mat_local) {
+ mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+ }
+ for (EditBone *ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ if (EBONE_VISIBLE(arm, ebo)) {
+ if (ebo->flag & BONE_TIPSEL) {
+ calc_tw_center_with_matrix(tbounds, ebo->tail, use_mat_local, mat_local);
+ totsel++;
+ }
+ if ((ebo->flag & BONE_ROOTSEL) &&
+ /* don't include same point multiple times */
+ ((ebo->flag & BONE_CONNECTED) && (ebo->parent != NULL) &&
+ (ebo->parent->flag & BONE_TIPSEL) && EBONE_VISIBLE(arm, ebo->parent)) == 0) {
+ calc_tw_center_with_matrix(tbounds, ebo->head, use_mat_local, mat_local);
+ totsel++;
+ }
+ if (ebo->flag & BONE_SELECTED) {
+ protectflag_to_drawflags_ebone(rv3d, ebo);
+ }
+ }
+ }
+ }
+ FOREACH_EDIT_OBJECT_END();
+ }
+ else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ FOREACH_EDIT_OBJECT_BEGIN (ob_iter, use_mat_local) {
+ Curve *cu = ob_iter->data;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+
+ float mat_local[4][4];
+ if (use_mat_local) {
+ mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+ }
+
+ nu = nurbs->first;
+ while (nu) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ /* exceptions
+ * if handles are hidden then only check the center points.
+ * If the center knot is selected then only use this as the center point.
+ */
+ if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
+ if (bezt->f2 & SELECT) {
+ calc_tw_center_with_matrix(tbounds, bezt->vec[1], use_mat_local, mat_local);
+ totsel++;
+ }
+ }
+ else if (bezt->f2 & SELECT) {
+ calc_tw_center_with_matrix(tbounds, bezt->vec[1], use_mat_local, mat_local);
+ totsel++;
+ }
+ else {
+ if (bezt->f1 & SELECT) {
+ const float *co = bezt->vec[(pivot_point == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 0];
+ calc_tw_center_with_matrix(tbounds, co, use_mat_local, mat_local);
+ totsel++;
+ }
+ if (bezt->f3 & SELECT) {
+ const float *co = bezt->vec[(pivot_point == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 2];
+ calc_tw_center_with_matrix(tbounds, co, use_mat_local, mat_local);
+ totsel++;
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ calc_tw_center_with_matrix(tbounds, bp->vec, use_mat_local, mat_local);
+ totsel++;
+ }
+ bp++;
+ }
+ }
+ nu = nu->next;
+ }
+ }
+ FOREACH_EDIT_OBJECT_END();
+ }
+ else if (obedit->type == OB_MBALL) {
+ FOREACH_EDIT_OBJECT_BEGIN (ob_iter, use_mat_local) {
+ MetaBall *mb = (MetaBall *)ob_iter->data;
+
+ float mat_local[4][4];
+ if (use_mat_local) {
+ mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+ }
+
+ for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) {
+ if (ml->flag & SELECT) {
+ calc_tw_center_with_matrix(tbounds, &ml->x, use_mat_local, mat_local);
+ totsel++;
+ }
+ }
+ }
+ FOREACH_EDIT_OBJECT_END();
+ }
+ else if (obedit->type == OB_LATTICE) {
+ FOREACH_EDIT_OBJECT_BEGIN (ob_iter, use_mat_local) {
+ Lattice *lt = ((Lattice *)ob_iter->data)->editlatt->latt;
+ BPoint *bp = lt->def;
+ a = lt->pntsu * lt->pntsv * lt->pntsw;
+
+ float mat_local[4][4];
+ if (use_mat_local) {
+ mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+ }
+
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ calc_tw_center_with_matrix(tbounds, bp->vec, use_mat_local, mat_local);
+ totsel++;
+ }
+ bp++;
+ }
+ }
+ FOREACH_EDIT_OBJECT_END();
+ }
#undef FOREACH_EDIT_OBJECT_BEGIN
#undef FOREACH_EDIT_OBJECT_END
- /* selection center */
- if (totsel) {
- mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
- mul_m4_v3(obedit->obmat, tbounds->center);
- mul_m4_v3(obedit->obmat, tbounds->min);
- mul_m4_v3(obedit->obmat, tbounds->max);
- }
- }
- else if (ob && (ob->mode & OB_MODE_POSE)) {
- invert_m4_m4(ob->imat, ob->obmat);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_mode(
- view_layer, v3d, &objects_len, {.object_mode = OB_MODE_POSE});
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob_iter = objects[ob_index];
- const bool use_mat_local = (ob_iter != ob);
- bPoseChannel *pchan;
-
- /* 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(ob_iter, mode, V3D_AROUND_CENTER_BOUNDS, NULL);
-
- if (totsel_iter) {
- float mat_local[4][4];
- if (use_mat_local) {
- mul_m4_m4m4(mat_local, ob->imat, ob_iter->obmat);
- }
-
- /* use channels to get stats */
- for (pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) {
- Bone *bone = pchan->bone;
- if (bone && (bone->flag & BONE_TRANSFORM)) {
- calc_tw_center_with_matrix(tbounds, pchan->pose_head, use_mat_local, mat_local);
- protectflag_to_drawflags_pchan(rv3d, pchan);
- }
- }
- totsel += totsel_iter;
- }
- }
- MEM_freeN(objects);
-
- if (totsel) {
- mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
- mul_m4_v3(ob->obmat, tbounds->center);
- mul_m4_v3(ob->obmat, tbounds->min);
- mul_m4_v3(ob->obmat, tbounds->max);
- }
- }
- else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
- /* pass */
- }
- else if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) {
- PTCacheEdit *edit = PE_get_current(scene, ob);
- PTCacheEditPoint *point;
- PTCacheEditKey *ek;
- int k;
-
- if (edit) {
- point = edit->points;
- for (a = 0; a < edit->totpoint; a++, point++) {
- if (point->flag & PEP_HIDE) continue;
-
- for (k = 0, ek = point->keys; k < point->totkey; k++, ek++) {
- if (ek->flag & PEK_SELECT) {
- calc_tw_center(tbounds, (ek->flag & PEK_USE_WCO) ? ek->world_co : ek->co);
- totsel++;
- }
- }
- }
-
- /* selection center */
- if (totsel)
- mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
- }
- }
- else {
-
- /* we need the one selected object, if its not active */
- base = BASACT(view_layer);
- ob = OBACT(view_layer);
- if (base && ((base->flag & BASE_SELECTED) == 0)) ob = NULL;
-
- for (base = view_layer->object_bases.first; base; base = base->next) {
- if (!BASE_SELECTED_EDITABLE(v3d, base)) {
- continue;
- }
- if (ob == NULL) {
- ob = base->object;
- }
-
- /* Get the boundbox out of the evaluated object. */
- const BoundBox *bb = NULL;
- if (params->use_only_center == false) {
- bb = BKE_object_boundbox_get(base->object);
- }
-
- if (params->use_only_center || (bb == NULL)) {
- calc_tw_center(tbounds, base->object->obmat[3]);
- }
- else {
- for (uint j = 0; j < 8; j++) {
- float co[3];
- mul_v3_m4v3(co, base->object->obmat, bb->vec[j]);
- calc_tw_center(tbounds, co);
- }
- }
- protectflag_to_drawflags(base->object->protectflag, &rv3d->twdrawflag);
- totsel++;
- }
-
- /* selection center */
- if (totsel) {
- mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
- }
- }
-
- if (totsel == 0) {
- unit_m4(rv3d->twmat);
- }
- else {
- copy_v3_v3(rv3d->tw_axis_min, tbounds->axis_min);
- copy_v3_v3(rv3d->tw_axis_max, tbounds->axis_max);
- copy_m3_m3(rv3d->tw_axis_matrix, tbounds->axis);
- }
-
- return totsel;
+ /* selection center */
+ if (totsel) {
+ mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
+ mul_m4_v3(obedit->obmat, tbounds->center);
+ mul_m4_v3(obedit->obmat, tbounds->min);
+ mul_m4_v3(obedit->obmat, tbounds->max);
+ }
+ }
+ else if (ob && (ob->mode & OB_MODE_POSE)) {
+ invert_m4_m4(ob->imat, ob->obmat);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_mode(
+ view_layer, v3d, &objects_len, {.object_mode = OB_MODE_POSE});
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob_iter = objects[ob_index];
+ const bool use_mat_local = (ob_iter != ob);
+ bPoseChannel *pchan;
+
+ /* 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(
+ ob_iter, mode, V3D_AROUND_CENTER_BOUNDS, NULL);
+
+ if (totsel_iter) {
+ float mat_local[4][4];
+ if (use_mat_local) {
+ mul_m4_m4m4(mat_local, ob->imat, ob_iter->obmat);
+ }
+
+ /* use channels to get stats */
+ for (pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) {
+ Bone *bone = pchan->bone;
+ if (bone && (bone->flag & BONE_TRANSFORM)) {
+ calc_tw_center_with_matrix(tbounds, pchan->pose_head, use_mat_local, mat_local);
+ protectflag_to_drawflags_pchan(rv3d, pchan);
+ }
+ }
+ totsel += totsel_iter;
+ }
+ }
+ MEM_freeN(objects);
+
+ if (totsel) {
+ mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
+ mul_m4_v3(ob->obmat, tbounds->center);
+ mul_m4_v3(ob->obmat, tbounds->min);
+ mul_m4_v3(ob->obmat, tbounds->max);
+ }
+ }
+ else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
+ /* pass */
+ }
+ else if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) {
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ PTCacheEditPoint *point;
+ PTCacheEditKey *ek;
+ int k;
+
+ if (edit) {
+ point = edit->points;
+ for (a = 0; a < edit->totpoint; a++, point++) {
+ if (point->flag & PEP_HIDE)
+ continue;
+
+ for (k = 0, ek = point->keys; k < point->totkey; k++, ek++) {
+ if (ek->flag & PEK_SELECT) {
+ calc_tw_center(tbounds, (ek->flag & PEK_USE_WCO) ? ek->world_co : ek->co);
+ totsel++;
+ }
+ }
+ }
+
+ /* selection center */
+ if (totsel)
+ mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
+ }
+ }
+ else {
+
+ /* we need the one selected object, if its not active */
+ base = BASACT(view_layer);
+ ob = OBACT(view_layer);
+ if (base && ((base->flag & BASE_SELECTED) == 0))
+ ob = NULL;
+
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ if (!BASE_SELECTED_EDITABLE(v3d, base)) {
+ continue;
+ }
+ if (ob == NULL) {
+ ob = base->object;
+ }
+
+ /* Get the boundbox out of the evaluated object. */
+ const BoundBox *bb = NULL;
+ if (params->use_only_center == false) {
+ bb = BKE_object_boundbox_get(base->object);
+ }
+
+ if (params->use_only_center || (bb == NULL)) {
+ calc_tw_center(tbounds, base->object->obmat[3]);
+ }
+ else {
+ for (uint j = 0; j < 8; j++) {
+ float co[3];
+ mul_v3_m4v3(co, base->object->obmat, bb->vec[j]);
+ calc_tw_center(tbounds, co);
+ }
+ }
+ protectflag_to_drawflags(base->object->protectflag, &rv3d->twdrawflag);
+ totsel++;
+ }
+
+ /* selection center */
+ if (totsel) {
+ mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
+ }
+ }
+
+ if (totsel == 0) {
+ unit_m4(rv3d->twmat);
+ }
+ else {
+ copy_v3_v3(rv3d->tw_axis_min, tbounds->axis_min);
+ copy_v3_v3(rv3d->tw_axis_max, tbounds->axis_max);
+ copy_m3_m3(rv3d->tw_axis_matrix, tbounds->axis);
+ }
+
+ return totsel;
}
static void gizmo_get_idot(RegionView3D *rv3d, float r_idot[3])
{
- float view_vec[3], axis_vec[3];
- ED_view3d_global_to_vector(rv3d, rv3d->twmat[3], view_vec);
- for (int i = 0; i < 3; i++) {
- normalize_v3_v3(axis_vec, rv3d->twmat[i]);
- r_idot[i] = 1.0f - fabsf(dot_v3v3(view_vec, axis_vec));
- }
+ float view_vec[3], axis_vec[3];
+ ED_view3d_global_to_vector(rv3d, rv3d->twmat[3], view_vec);
+ for (int i = 0; i < 3; i++) {
+ normalize_v3_v3(axis_vec, rv3d->twmat[i]);
+ r_idot[i] = 1.0f - fabsf(dot_v3v3(view_vec, axis_vec));
+ }
}
-static void gizmo_prepare_mat(
- const bContext *C, RegionView3D *rv3d, const struct TransformBounds *tbounds)
+static void gizmo_prepare_mat(const bContext *C,
+ RegionView3D *rv3d,
+ const struct TransformBounds *tbounds)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- switch (scene->toolsettings->transform_pivot_point) {
- case V3D_AROUND_CENTER_BOUNDS:
- case V3D_AROUND_ACTIVE:
- {
- mid_v3_v3v3(rv3d->twmat[3], tbounds->min, tbounds->max);
-
- if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
- bGPdata *gpd = CTX_data_gpencil_data(C);
- Object *ob = OBACT(view_layer);
- if (gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE)) {
- /* pass */
- }
- else if (ob != NULL) {
- ED_object_calc_active_center(ob, false, rv3d->twmat[3]);
- }
- }
- break;
- }
- case V3D_AROUND_LOCAL_ORIGINS:
- case V3D_AROUND_CENTER_MEDIAN:
- copy_v3_v3(rv3d->twmat[3], tbounds->center);
- break;
- case V3D_AROUND_CURSOR:
- copy_v3_v3(rv3d->twmat[3], scene->cursor.location);
- break;
- }
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ switch (scene->toolsettings->transform_pivot_point) {
+ case V3D_AROUND_CENTER_BOUNDS:
+ case V3D_AROUND_ACTIVE: {
+ mid_v3_v3v3(rv3d->twmat[3], tbounds->min, tbounds->max);
+
+ if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ Object *ob = OBACT(view_layer);
+ if (gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE)) {
+ /* pass */
+ }
+ else if (ob != NULL) {
+ ED_object_calc_active_center(ob, false, rv3d->twmat[3]);
+ }
+ }
+ break;
+ }
+ case V3D_AROUND_LOCAL_ORIGINS:
+ case V3D_AROUND_CENTER_MEDIAN:
+ copy_v3_v3(rv3d->twmat[3], tbounds->center);
+ break;
+ case V3D_AROUND_CURSOR:
+ copy_v3_v3(rv3d->twmat[3], scene->cursor.location);
+ break;
+ }
}
/**
@@ -1178,771 +1174,779 @@ static void gizmo_prepare_mat(
*/
static void gizmo_line_range(const int twtype, const short axis_type, float *r_start, float *r_len)
{
- const float ofs = 0.2f;
-
- *r_start = 0.2f;
- *r_len = 1.0f;
-
- switch (axis_type) {
- case MAN_AXES_TRANSLATE:
- if (twtype & V3D_GIZMO_SHOW_OBJECT_SCALE) {
- *r_start = *r_len - ofs + 0.075f;
- }
- if (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) {
- *r_len += ofs;
- }
- break;
- case MAN_AXES_SCALE:
- if (twtype & (V3D_GIZMO_SHOW_OBJECT_TRANSLATE | V3D_GIZMO_SHOW_OBJECT_ROTATE)) {
- *r_len -= ofs + 0.025f;
- }
- break;
- }
-
- *r_len -= *r_start;
+ const float ofs = 0.2f;
+
+ *r_start = 0.2f;
+ *r_len = 1.0f;
+
+ switch (axis_type) {
+ case MAN_AXES_TRANSLATE:
+ if (twtype & V3D_GIZMO_SHOW_OBJECT_SCALE) {
+ *r_start = *r_len - ofs + 0.075f;
+ }
+ if (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) {
+ *r_len += ofs;
+ }
+ break;
+ case MAN_AXES_SCALE:
+ if (twtype & (V3D_GIZMO_SHOW_OBJECT_TRANSLATE | V3D_GIZMO_SHOW_OBJECT_ROTATE)) {
+ *r_len -= ofs + 0.025f;
+ }
+ break;
+ }
+
+ *r_len -= *r_start;
}
-static void gizmo_xform_message_subscribe(
- wmGizmoGroup *gzgroup, struct wmMsgBus *mbus,
- Scene *scene, bScreen *screen, ScrArea *sa, ARegion *ar, const void *type_fn)
+static void gizmo_xform_message_subscribe(wmGizmoGroup *gzgroup,
+ struct wmMsgBus *mbus,
+ Scene *scene,
+ bScreen *screen,
+ ScrArea *sa,
+ ARegion *ar,
+ const void *type_fn)
{
- /* Subscribe to view properties */
- wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
- .owner = ar,
- .user_data = gzgroup->parent_gzmap,
- .notify = WM_gizmo_do_msg_notify_tag_refresh,
- };
-
- int orient_flag = 0;
- if (type_fn == VIEW3D_GGT_xform_gizmo) {
- GizmoGroup *ggd = gzgroup->customdata;
- orient_flag = ggd->twtype_init;
- }
- else if (type_fn == VIEW3D_GGT_xform_cage) {
- orient_flag = V3D_GIZMO_SHOW_OBJECT_SCALE;
- /* pass */
- }
- else if (type_fn == VIEW3D_GGT_xform_shear) {
- orient_flag = V3D_GIZMO_SHOW_OBJECT_ROTATE;
- }
- TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get_from_flag(scene, orient_flag);
- PointerRNA orient_ref_ptr;
- RNA_pointer_create(&scene->id, &RNA_TransformOrientationSlot, orient_slot, &orient_ref_ptr);
- const ToolSettings *ts = scene->toolsettings;
-
- PointerRNA scene_ptr;
- RNA_id_pointer_create(&scene->id, &scene_ptr);
- {
- extern PropertyRNA rna_Scene_transform_orientation_slots;
- const PropertyRNA *props[] = {
- &rna_Scene_transform_orientation_slots,
- };
- for (int i = 0; i < ARRAY_SIZE(props); i++) {
- WM_msg_subscribe_rna(mbus, &scene_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
- }
- }
-
- if ((ts->transform_pivot_point == V3D_AROUND_CURSOR) ||
- (orient_slot->type == V3D_ORIENT_CURSOR))
- {
- /* We could be more specific here, for now subscribe to any cursor change. */
- PointerRNA cursor_ptr;
- RNA_pointer_create(&scene->id, &RNA_View3DCursor, &scene->cursor, &cursor_ptr);
- WM_msg_subscribe_rna(mbus, &cursor_ptr, NULL, &msg_sub_value_gz_tag_refresh, __func__);
- }
-
- {
- extern PropertyRNA rna_TransformOrientationSlot_type;
- extern PropertyRNA rna_TransformOrientationSlot_use;
- const PropertyRNA *props[] = {
- &rna_TransformOrientationSlot_type,
- &rna_TransformOrientationSlot_use,
- };
- for (int i = 0; i < ARRAY_SIZE(props); i++) {
- if (props[i]) {
- WM_msg_subscribe_rna(mbus, &orient_ref_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
- }
- }
- }
-
- PointerRNA toolsettings_ptr;
- RNA_pointer_create(&scene->id, &RNA_ToolSettings, scene->toolsettings, &toolsettings_ptr);
-
- if (type_fn == VIEW3D_GGT_xform_gizmo) {
- extern PropertyRNA rna_ToolSettings_transform_pivot_point;
- const PropertyRNA *props[] = {
- &rna_ToolSettings_transform_pivot_point,
- };
- for (int i = 0; i < ARRAY_SIZE(props); i++) {
- WM_msg_subscribe_rna(mbus, &toolsettings_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
- }
- }
-
- PointerRNA view3d_ptr;
- RNA_pointer_create(&screen->id, &RNA_SpaceView3D, sa->spacedata.first, &view3d_ptr);
-
- if (type_fn == VIEW3D_GGT_xform_gizmo) {
- GizmoGroup *ggd = gzgroup->customdata;
- if (ggd->use_twtype_refresh) {
- extern PropertyRNA rna_SpaceView3D_show_gizmo_object_translate;
- extern PropertyRNA rna_SpaceView3D_show_gizmo_object_rotate;
- extern PropertyRNA rna_SpaceView3D_show_gizmo_object_scale;
- const PropertyRNA *props[] = {
- &rna_SpaceView3D_show_gizmo_object_translate,
- &rna_SpaceView3D_show_gizmo_object_rotate,
- &rna_SpaceView3D_show_gizmo_object_scale,
- };
- for (int i = 0; i < ARRAY_SIZE(props); i++) {
- WM_msg_subscribe_rna(mbus, &view3d_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
- }
- }
- }
- else if (type_fn == VIEW3D_GGT_xform_cage) {
- /* pass */
- }
- else if (type_fn == VIEW3D_GGT_xform_shear) {
- /* pass */
- }
- else {
- BLI_assert(0);
- }
-
- WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_gz_tag_refresh);
+ /* Subscribe to view properties */
+ wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
+ .owner = ar,
+ .user_data = gzgroup->parent_gzmap,
+ .notify = WM_gizmo_do_msg_notify_tag_refresh,
+ };
+
+ int orient_flag = 0;
+ if (type_fn == VIEW3D_GGT_xform_gizmo) {
+ GizmoGroup *ggd = gzgroup->customdata;
+ orient_flag = ggd->twtype_init;
+ }
+ else if (type_fn == VIEW3D_GGT_xform_cage) {
+ orient_flag = V3D_GIZMO_SHOW_OBJECT_SCALE;
+ /* pass */
+ }
+ else if (type_fn == VIEW3D_GGT_xform_shear) {
+ orient_flag = V3D_GIZMO_SHOW_OBJECT_ROTATE;
+ }
+ TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get_from_flag(scene,
+ orient_flag);
+ PointerRNA orient_ref_ptr;
+ RNA_pointer_create(&scene->id, &RNA_TransformOrientationSlot, orient_slot, &orient_ref_ptr);
+ const ToolSettings *ts = scene->toolsettings;
+
+ PointerRNA scene_ptr;
+ RNA_id_pointer_create(&scene->id, &scene_ptr);
+ {
+ extern PropertyRNA rna_Scene_transform_orientation_slots;
+ const PropertyRNA *props[] = {
+ &rna_Scene_transform_orientation_slots,
+ };
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &scene_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
+ }
+ }
+
+ if ((ts->transform_pivot_point == V3D_AROUND_CURSOR) ||
+ (orient_slot->type == V3D_ORIENT_CURSOR)) {
+ /* We could be more specific here, for now subscribe to any cursor change. */
+ PointerRNA cursor_ptr;
+ RNA_pointer_create(&scene->id, &RNA_View3DCursor, &scene->cursor, &cursor_ptr);
+ WM_msg_subscribe_rna(mbus, &cursor_ptr, NULL, &msg_sub_value_gz_tag_refresh, __func__);
+ }
+
+ {
+ extern PropertyRNA rna_TransformOrientationSlot_type;
+ extern PropertyRNA rna_TransformOrientationSlot_use;
+ const PropertyRNA *props[] = {
+ &rna_TransformOrientationSlot_type,
+ &rna_TransformOrientationSlot_use,
+ };
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ if (props[i]) {
+ WM_msg_subscribe_rna(
+ mbus, &orient_ref_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
+ }
+ }
+ }
+
+ PointerRNA toolsettings_ptr;
+ RNA_pointer_create(&scene->id, &RNA_ToolSettings, scene->toolsettings, &toolsettings_ptr);
+
+ if (type_fn == VIEW3D_GGT_xform_gizmo) {
+ extern PropertyRNA rna_ToolSettings_transform_pivot_point;
+ const PropertyRNA *props[] = {
+ &rna_ToolSettings_transform_pivot_point,
+ };
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(
+ mbus, &toolsettings_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
+ }
+ }
+
+ PointerRNA view3d_ptr;
+ RNA_pointer_create(&screen->id, &RNA_SpaceView3D, sa->spacedata.first, &view3d_ptr);
+
+ if (type_fn == VIEW3D_GGT_xform_gizmo) {
+ GizmoGroup *ggd = gzgroup->customdata;
+ if (ggd->use_twtype_refresh) {
+ extern PropertyRNA rna_SpaceView3D_show_gizmo_object_translate;
+ extern PropertyRNA rna_SpaceView3D_show_gizmo_object_rotate;
+ extern PropertyRNA rna_SpaceView3D_show_gizmo_object_scale;
+ const PropertyRNA *props[] = {
+ &rna_SpaceView3D_show_gizmo_object_translate,
+ &rna_SpaceView3D_show_gizmo_object_rotate,
+ &rna_SpaceView3D_show_gizmo_object_scale,
+ };
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &view3d_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
+ }
+ }
+ }
+ else if (type_fn == VIEW3D_GGT_xform_cage) {
+ /* pass */
+ }
+ else if (type_fn == VIEW3D_GGT_xform_shear) {
+ /* pass */
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_gz_tag_refresh);
}
-
void drawDial3d(const TransInfo *t)
{
- if (t->mode == TFM_ROTATION && t->spacetype == SPACE_VIEW3D) {
- wmGizmo *gz = wm_gizmomap_modal_get(t->ar->gizmo_map);
- if (gz == NULL) {
- /* We only draw Dial3d if the operator has been called by a gizmo. */
- return;
- }
-
- float mat_basis[4][4];
- float mat_final[4][4];
- float color[4];
- float increment;
- float line_with = GIZMO_AXIS_LINE_WIDTH + 1.0f;
- float scale = UI_DPI_FAC * U.gizmo_size;
-
- int axis_idx;
-
- const TransCon *tc = &(t->con);
- if (tc->mode & CON_APPLY) {
- if (tc->mode & CON_AXIS0) {
- axis_idx = MAN_AXIS_ROT_X;
- negate_v3_v3(mat_basis[2], tc->mtx[0]);
- }
- else if (tc->mode & CON_AXIS1) {
- axis_idx = MAN_AXIS_ROT_Y;
- negate_v3_v3(mat_basis[2], tc->mtx[1]);
- }
- else {
- BLI_assert((tc->mode & CON_AXIS2) != 0);
- axis_idx = MAN_AXIS_ROT_Z;
- negate_v3_v3(mat_basis[2], tc->mtx[2]);
- }
- }
- else {
- axis_idx = MAN_AXIS_ROT_C;
- negate_v3_v3(mat_basis[2], t->orient_matrix[t->orient_axis]);
- scale *= 1.2f;
- line_with -= 1.0f;
- }
-
- copy_v3_v3(mat_basis[3], t->center_global);
- 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]))
- {
- 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]);
- }
- else {
- /* The plane and the mouse direction are parallel.
- * Calculate a matrix orthogonal to the axis. */
- ortho_basis_v3v3_v3(mat_basis[0], mat_basis[1], mat_basis[2]);
- }
-
- mat_basis[0][3] = 0.0f;
- mat_basis[1][3] = 0.0f;
- mat_basis[2][3] = 0.0f;
- 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]);
- mul_mat3_m4_fl(mat_final, scale);
-
- if ((t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) &&
- activeSnap(t))
- {
- increment = (t->modifiers & MOD_PRECISION) ? t->snap[2] : t->snap[1];
- }
- else {
- increment = t->snap[0];
- }
-
- BLI_assert(axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END);
- gizmo_get_axis_color(axis_idx, NULL, color, color);
-
- GPU_depth_test(false);
- GPU_blend(true);
- GPU_line_smooth(true);
-
- ED_gizmotypes_dial_3d_draw_util(
- mat_basis, mat_final, line_with, color, false,
- &(struct Dial3dParams){
- .draw_options = ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE,
- .angle_delta = t->values[0],
- .angle_increment = increment,
- });
-
- GPU_line_smooth(false);
- GPU_depth_test(true);
- GPU_blend(false);
- }
+ if (t->mode == TFM_ROTATION && t->spacetype == SPACE_VIEW3D) {
+ wmGizmo *gz = wm_gizmomap_modal_get(t->ar->gizmo_map);
+ if (gz == NULL) {
+ /* We only draw Dial3d if the operator has been called by a gizmo. */
+ return;
+ }
+
+ float mat_basis[4][4];
+ float mat_final[4][4];
+ float color[4];
+ float increment;
+ float line_with = GIZMO_AXIS_LINE_WIDTH + 1.0f;
+ float scale = UI_DPI_FAC * U.gizmo_size;
+
+ int axis_idx;
+
+ const TransCon *tc = &(t->con);
+ if (tc->mode & CON_APPLY) {
+ if (tc->mode & CON_AXIS0) {
+ axis_idx = MAN_AXIS_ROT_X;
+ negate_v3_v3(mat_basis[2], tc->mtx[0]);
+ }
+ else if (tc->mode & CON_AXIS1) {
+ axis_idx = MAN_AXIS_ROT_Y;
+ negate_v3_v3(mat_basis[2], tc->mtx[1]);
+ }
+ else {
+ BLI_assert((tc->mode & CON_AXIS2) != 0);
+ axis_idx = MAN_AXIS_ROT_Z;
+ negate_v3_v3(mat_basis[2], tc->mtx[2]);
+ }
+ }
+ else {
+ axis_idx = MAN_AXIS_ROT_C;
+ negate_v3_v3(mat_basis[2], t->orient_matrix[t->orient_axis]);
+ scale *= 1.2f;
+ line_with -= 1.0f;
+ }
+
+ copy_v3_v3(mat_basis[3], t->center_global);
+ 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])) {
+ 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]);
+ }
+ else {
+ /* The plane and the mouse direction are parallel.
+ * Calculate a matrix orthogonal to the axis. */
+ ortho_basis_v3v3_v3(mat_basis[0], mat_basis[1], mat_basis[2]);
+ }
+
+ mat_basis[0][3] = 0.0f;
+ mat_basis[1][3] = 0.0f;
+ mat_basis[2][3] = 0.0f;
+ 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]);
+ mul_mat3_m4_fl(mat_final, scale);
+
+ if ((t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) && activeSnap(t)) {
+ increment = (t->modifiers & MOD_PRECISION) ? t->snap[2] : t->snap[1];
+ }
+ else {
+ increment = t->snap[0];
+ }
+
+ BLI_assert(axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END);
+ gizmo_get_axis_color(axis_idx, NULL, color, color);
+
+ GPU_depth_test(false);
+ GPU_blend(true);
+ GPU_line_smooth(true);
+
+ ED_gizmotypes_dial_3d_draw_util(mat_basis,
+ mat_final,
+ line_with,
+ color,
+ false,
+ &(struct Dial3dParams){
+ .draw_options = ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE,
+ .angle_delta = t->values[0],
+ .angle_increment = increment,
+ });
+
+ GPU_line_smooth(false);
+ GPU_depth_test(true);
+ GPU_blend(false);
+ }
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Transform Gizmo
* \{ */
static GizmoGroup *gizmogroup_init(wmGizmoGroup *gzgroup)
{
- GizmoGroup *ggd;
-
- ggd = MEM_callocN(sizeof(GizmoGroup), "gizmo_data");
-
- const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
- const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true);
- const wmGizmoType *gzt_prim = WM_gizmotype_find("GIZMO_GT_primitive_3d", true);
-
-#define GIZMO_NEW_ARROW(v, draw_style) { \
- ggd->gizmos[v] = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL); \
- RNA_enum_set(ggd->gizmos[v]->ptr, "draw_style", draw_style); \
-} ((void)0)
-#define GIZMO_NEW_DIAL(v, draw_options) { \
- ggd->gizmos[v] = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL); \
- RNA_enum_set(ggd->gizmos[v]->ptr, "draw_options", draw_options); \
-} ((void)0)
-#define GIZMO_NEW_PRIM(v, draw_style) { \
- ggd->gizmos[v] = WM_gizmo_new_ptr(gzt_prim, gzgroup, NULL); \
- RNA_enum_set(ggd->gizmos[v]->ptr, "draw_style", draw_style); \
-} ((void)0)
-
- /* add/init widgets - order matters! */
- GIZMO_NEW_DIAL(MAN_AXIS_ROT_T, ED_GIZMO_DIAL_DRAW_FLAG_FILL);
-
- GIZMO_NEW_DIAL(MAN_AXIS_SCALE_C, ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT);
-
- GIZMO_NEW_ARROW(MAN_AXIS_SCALE_X, ED_GIZMO_ARROW_STYLE_BOX);
- GIZMO_NEW_ARROW(MAN_AXIS_SCALE_Y, ED_GIZMO_ARROW_STYLE_BOX);
- GIZMO_NEW_ARROW(MAN_AXIS_SCALE_Z, ED_GIZMO_ARROW_STYLE_BOX);
-
- GIZMO_NEW_PRIM(MAN_AXIS_SCALE_XY, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
- GIZMO_NEW_PRIM(MAN_AXIS_SCALE_YZ, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
- GIZMO_NEW_PRIM(MAN_AXIS_SCALE_ZX, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
-
- GIZMO_NEW_DIAL(MAN_AXIS_ROT_X, ED_GIZMO_DIAL_DRAW_FLAG_CLIP);
- GIZMO_NEW_DIAL(MAN_AXIS_ROT_Y, ED_GIZMO_DIAL_DRAW_FLAG_CLIP);
- GIZMO_NEW_DIAL(MAN_AXIS_ROT_Z, ED_GIZMO_DIAL_DRAW_FLAG_CLIP);
-
- /* init screen aligned widget last here, looks better, behaves better */
- GIZMO_NEW_DIAL(MAN_AXIS_ROT_C, ED_GIZMO_DIAL_DRAW_FLAG_NOP);
-
- GIZMO_NEW_DIAL(MAN_AXIS_TRANS_C, ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT);
-
- GIZMO_NEW_ARROW(MAN_AXIS_TRANS_X, ED_GIZMO_ARROW_STYLE_NORMAL);
- GIZMO_NEW_ARROW(MAN_AXIS_TRANS_Y, ED_GIZMO_ARROW_STYLE_NORMAL);
- GIZMO_NEW_ARROW(MAN_AXIS_TRANS_Z, ED_GIZMO_ARROW_STYLE_NORMAL);
-
- GIZMO_NEW_PRIM(MAN_AXIS_TRANS_XY, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
- GIZMO_NEW_PRIM(MAN_AXIS_TRANS_YZ, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
- GIZMO_NEW_PRIM(MAN_AXIS_TRANS_ZX, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
-
- ggd->gizmos[MAN_AXIS_ROT_T]->flag |= WM_GIZMO_SELECT_BACKGROUND;
-
- return ggd;
+ GizmoGroup *ggd;
+
+ ggd = MEM_callocN(sizeof(GizmoGroup), "gizmo_data");
+
+ const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
+ const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true);
+ const wmGizmoType *gzt_prim = WM_gizmotype_find("GIZMO_GT_primitive_3d", true);
+
+#define GIZMO_NEW_ARROW(v, draw_style) \
+ { \
+ ggd->gizmos[v] = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL); \
+ RNA_enum_set(ggd->gizmos[v]->ptr, "draw_style", draw_style); \
+ } \
+ ((void)0)
+#define GIZMO_NEW_DIAL(v, draw_options) \
+ { \
+ ggd->gizmos[v] = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL); \
+ RNA_enum_set(ggd->gizmos[v]->ptr, "draw_options", draw_options); \
+ } \
+ ((void)0)
+#define GIZMO_NEW_PRIM(v, draw_style) \
+ { \
+ ggd->gizmos[v] = WM_gizmo_new_ptr(gzt_prim, gzgroup, NULL); \
+ RNA_enum_set(ggd->gizmos[v]->ptr, "draw_style", draw_style); \
+ } \
+ ((void)0)
+
+ /* add/init widgets - order matters! */
+ GIZMO_NEW_DIAL(MAN_AXIS_ROT_T, ED_GIZMO_DIAL_DRAW_FLAG_FILL);
+
+ GIZMO_NEW_DIAL(MAN_AXIS_SCALE_C, ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT);
+
+ GIZMO_NEW_ARROW(MAN_AXIS_SCALE_X, ED_GIZMO_ARROW_STYLE_BOX);
+ GIZMO_NEW_ARROW(MAN_AXIS_SCALE_Y, ED_GIZMO_ARROW_STYLE_BOX);
+ GIZMO_NEW_ARROW(MAN_AXIS_SCALE_Z, ED_GIZMO_ARROW_STYLE_BOX);
+
+ GIZMO_NEW_PRIM(MAN_AXIS_SCALE_XY, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
+ GIZMO_NEW_PRIM(MAN_AXIS_SCALE_YZ, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
+ GIZMO_NEW_PRIM(MAN_AXIS_SCALE_ZX, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
+
+ GIZMO_NEW_DIAL(MAN_AXIS_ROT_X, ED_GIZMO_DIAL_DRAW_FLAG_CLIP);
+ GIZMO_NEW_DIAL(MAN_AXIS_ROT_Y, ED_GIZMO_DIAL_DRAW_FLAG_CLIP);
+ GIZMO_NEW_DIAL(MAN_AXIS_ROT_Z, ED_GIZMO_DIAL_DRAW_FLAG_CLIP);
+
+ /* init screen aligned widget last here, looks better, behaves better */
+ GIZMO_NEW_DIAL(MAN_AXIS_ROT_C, ED_GIZMO_DIAL_DRAW_FLAG_NOP);
+
+ GIZMO_NEW_DIAL(MAN_AXIS_TRANS_C, ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT);
+
+ GIZMO_NEW_ARROW(MAN_AXIS_TRANS_X, ED_GIZMO_ARROW_STYLE_NORMAL);
+ GIZMO_NEW_ARROW(MAN_AXIS_TRANS_Y, ED_GIZMO_ARROW_STYLE_NORMAL);
+ GIZMO_NEW_ARROW(MAN_AXIS_TRANS_Z, ED_GIZMO_ARROW_STYLE_NORMAL);
+
+ GIZMO_NEW_PRIM(MAN_AXIS_TRANS_XY, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
+ GIZMO_NEW_PRIM(MAN_AXIS_TRANS_YZ, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
+ GIZMO_NEW_PRIM(MAN_AXIS_TRANS_ZX, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
+
+ ggd->gizmos[MAN_AXIS_ROT_T]->flag |= WM_GIZMO_SELECT_BACKGROUND;
+
+ return ggd;
}
/**
* Custom handler for gizmo widgets
*/
-static int gizmo_modal(
- bContext *C, wmGizmo *widget, const wmEvent *event,
- eWM_GizmoFlagTweak UNUSED(tweak_flag))
+static int gizmo_modal(bContext *C,
+ wmGizmo *widget,
+ const wmEvent *event,
+ eWM_GizmoFlagTweak UNUSED(tweak_flag))
{
- /* Avoid unnecessary updates, partially address: T55458. */
- if (ELEM(event->type, TIMER, INBETWEEN_MOUSEMOVE)) {
- return OPERATOR_RUNNING_MODAL;
- }
-
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
- struct TransformBounds tbounds;
-
-
- if (ED_transform_calc_gizmo_stats(
- C, &(struct TransformCalcParams){
- .use_only_center = true,
- }, &tbounds))
- {
- gizmo_prepare_mat(C, rv3d, &tbounds);
- WM_gizmo_set_matrix_location(widget, rv3d->twmat[3]);
- }
-
- ED_region_tag_redraw(ar);
-
- return OPERATOR_RUNNING_MODAL;
+ /* Avoid unnecessary updates, partially address: T55458. */
+ if (ELEM(event->type, TIMER, INBETWEEN_MOUSEMOVE)) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ struct TransformBounds tbounds;
+
+ if (ED_transform_calc_gizmo_stats(C,
+ &(struct TransformCalcParams){
+ .use_only_center = true,
+ },
+ &tbounds)) {
+ gizmo_prepare_mat(C, rv3d, &tbounds);
+ WM_gizmo_set_matrix_location(widget, rv3d->twmat[3]);
+ }
+
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_RUNNING_MODAL;
}
static void gizmogroup_init_properties_from_twtype(wmGizmoGroup *gzgroup)
{
- struct {
- wmOperatorType *translate, *rotate, *trackball, *resize;
- } ot_store = {NULL};
- GizmoGroup *ggd = gzgroup->customdata;
-
- MAN_ITER_AXES_BEGIN(axis, axis_idx)
- {
- const short axis_type = gizmo_get_axis_type(axis_idx);
- bool constraint_axis[3] = {1, 0, 0};
- PointerRNA *ptr = NULL;
-
- gizmo_get_axis_constraint(axis_idx, constraint_axis);
-
- /* custom handler! */
- WM_gizmo_set_fn_custom_modal(axis, gizmo_modal);
-
- switch (axis_idx) {
- case MAN_AXIS_TRANS_X:
- case MAN_AXIS_TRANS_Y:
- case MAN_AXIS_TRANS_Z:
- case MAN_AXIS_SCALE_X:
- case MAN_AXIS_SCALE_Y:
- case MAN_AXIS_SCALE_Z:
- if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
- int draw_options = 0;
- if ((ggd->twtype & (V3D_GIZMO_SHOW_OBJECT_ROTATE | V3D_GIZMO_SHOW_OBJECT_SCALE)) == 0) {
- draw_options |= ED_GIZMO_ARROW_DRAW_FLAG_STEM;
- }
- RNA_enum_set(axis->ptr, "draw_options", draw_options);
- }
-
- WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH);
- break;
- case MAN_AXIS_ROT_X:
- case MAN_AXIS_ROT_Y:
- case MAN_AXIS_ROT_Z:
- /* increased line width for better display */
- WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH + 1.0f);
- WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_VALUE, true);
- break;
- case MAN_AXIS_TRANS_XY:
- case MAN_AXIS_TRANS_YZ:
- case MAN_AXIS_TRANS_ZX:
- case MAN_AXIS_SCALE_XY:
- case MAN_AXIS_SCALE_YZ:
- case MAN_AXIS_SCALE_ZX:
- {
- const float ofs_ax = 7.0f;
- const float ofs[3] = {ofs_ax, ofs_ax, 0.0f};
- WM_gizmo_set_scale(axis, 0.07f);
- WM_gizmo_set_matrix_offset_location(axis, ofs);
- WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_OFFSET_SCALE, true);
- break;
- }
- case MAN_AXIS_TRANS_C:
- case MAN_AXIS_ROT_C:
- case MAN_AXIS_SCALE_C:
- case MAN_AXIS_ROT_T:
- WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH);
- if (axis_idx == MAN_AXIS_ROT_T) {
- WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_HOVER, true);
- }
- else if (axis_idx == MAN_AXIS_ROT_C) {
- WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_VALUE, true);
- WM_gizmo_set_scale(axis, 1.2f);
- }
- else {
- WM_gizmo_set_scale(axis, 0.2f);
- }
- break;
- }
-
- switch (axis_type) {
- case MAN_AXES_TRANSLATE:
- if (ot_store.translate == NULL) {
- ot_store.translate = WM_operatortype_find("TRANSFORM_OT_translate", true);
- }
- ptr = WM_gizmo_operator_set(axis, 0, ot_store.translate, NULL);
- break;
- case MAN_AXES_ROTATE:
- {
- wmOperatorType *ot_rotate;
- if (axis_idx == MAN_AXIS_ROT_T) {
- if (ot_store.trackball == NULL) {
- ot_store.trackball = WM_operatortype_find("TRANSFORM_OT_trackball", true);
- }
- ot_rotate = ot_store.trackball;
- }
- else {
- if (ot_store.rotate == NULL) {
- ot_store.rotate = WM_operatortype_find("TRANSFORM_OT_rotate", true);
- }
- ot_rotate = ot_store.rotate;
- }
- ptr = WM_gizmo_operator_set(axis, 0, ot_rotate, NULL);
- break;
- }
- case MAN_AXES_SCALE:
- {
- if (ot_store.resize == NULL) {
- ot_store.resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
- }
- ptr = WM_gizmo_operator_set(axis, 0, ot_store.resize, NULL);
- break;
- }
- }
-
- if (ptr) {
- PropertyRNA *prop;
- if (ELEM(true, UNPACK3(constraint_axis))) {
- if ((prop = RNA_struct_find_property(ptr, "constraint_axis"))) {
- RNA_property_boolean_set_array(ptr, prop, constraint_axis);
- }
- }
-
- RNA_boolean_set(ptr, "release_confirm", 1);
- }
- }
- MAN_ITER_AXES_END;
+ struct {
+ wmOperatorType *translate, *rotate, *trackball, *resize;
+ } ot_store = {NULL};
+ GizmoGroup *ggd = gzgroup->customdata;
+
+ MAN_ITER_AXES_BEGIN (axis, axis_idx) {
+ const short axis_type = gizmo_get_axis_type(axis_idx);
+ bool constraint_axis[3] = {1, 0, 0};
+ PointerRNA *ptr = NULL;
+
+ gizmo_get_axis_constraint(axis_idx, constraint_axis);
+
+ /* custom handler! */
+ WM_gizmo_set_fn_custom_modal(axis, gizmo_modal);
+
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_X:
+ case MAN_AXIS_TRANS_Y:
+ case MAN_AXIS_TRANS_Z:
+ case MAN_AXIS_SCALE_X:
+ case MAN_AXIS_SCALE_Y:
+ case MAN_AXIS_SCALE_Z:
+ if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
+ int draw_options = 0;
+ if ((ggd->twtype & (V3D_GIZMO_SHOW_OBJECT_ROTATE | V3D_GIZMO_SHOW_OBJECT_SCALE)) == 0) {
+ draw_options |= ED_GIZMO_ARROW_DRAW_FLAG_STEM;
+ }
+ RNA_enum_set(axis->ptr, "draw_options", draw_options);
+ }
+
+ WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH);
+ break;
+ case MAN_AXIS_ROT_X:
+ case MAN_AXIS_ROT_Y:
+ case MAN_AXIS_ROT_Z:
+ /* increased line width for better display */
+ WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH + 1.0f);
+ WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_VALUE, true);
+ break;
+ case MAN_AXIS_TRANS_XY:
+ case MAN_AXIS_TRANS_YZ:
+ case MAN_AXIS_TRANS_ZX:
+ case MAN_AXIS_SCALE_XY:
+ case MAN_AXIS_SCALE_YZ:
+ case MAN_AXIS_SCALE_ZX: {
+ const float ofs_ax = 7.0f;
+ const float ofs[3] = {ofs_ax, ofs_ax, 0.0f};
+ WM_gizmo_set_scale(axis, 0.07f);
+ WM_gizmo_set_matrix_offset_location(axis, ofs);
+ WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_OFFSET_SCALE, true);
+ break;
+ }
+ case MAN_AXIS_TRANS_C:
+ case MAN_AXIS_ROT_C:
+ case MAN_AXIS_SCALE_C:
+ case MAN_AXIS_ROT_T:
+ WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH);
+ if (axis_idx == MAN_AXIS_ROT_T) {
+ WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_HOVER, true);
+ }
+ else if (axis_idx == MAN_AXIS_ROT_C) {
+ WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_VALUE, true);
+ WM_gizmo_set_scale(axis, 1.2f);
+ }
+ else {
+ WM_gizmo_set_scale(axis, 0.2f);
+ }
+ break;
+ }
+
+ switch (axis_type) {
+ case MAN_AXES_TRANSLATE:
+ if (ot_store.translate == NULL) {
+ ot_store.translate = WM_operatortype_find("TRANSFORM_OT_translate", true);
+ }
+ ptr = WM_gizmo_operator_set(axis, 0, ot_store.translate, NULL);
+ break;
+ case MAN_AXES_ROTATE: {
+ wmOperatorType *ot_rotate;
+ if (axis_idx == MAN_AXIS_ROT_T) {
+ if (ot_store.trackball == NULL) {
+ ot_store.trackball = WM_operatortype_find("TRANSFORM_OT_trackball", true);
+ }
+ ot_rotate = ot_store.trackball;
+ }
+ else {
+ if (ot_store.rotate == NULL) {
+ ot_store.rotate = WM_operatortype_find("TRANSFORM_OT_rotate", true);
+ }
+ ot_rotate = ot_store.rotate;
+ }
+ ptr = WM_gizmo_operator_set(axis, 0, ot_rotate, NULL);
+ break;
+ }
+ case MAN_AXES_SCALE: {
+ if (ot_store.resize == NULL) {
+ ot_store.resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
+ }
+ ptr = WM_gizmo_operator_set(axis, 0, ot_store.resize, NULL);
+ break;
+ }
+ }
+
+ if (ptr) {
+ PropertyRNA *prop;
+ if (ELEM(true, UNPACK3(constraint_axis))) {
+ if ((prop = RNA_struct_find_property(ptr, "constraint_axis"))) {
+ RNA_property_boolean_set_array(ptr, prop, constraint_axis);
+ }
+ }
+
+ RNA_boolean_set(ptr, "release_confirm", 1);
+ }
+ }
+ MAN_ITER_AXES_END;
}
static void WIDGETGROUP_gizmo_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoGroup *ggd = gizmogroup_init(gzgroup);
-
- gzgroup->customdata = ggd;
-
- {
- ScrArea *sa = CTX_wm_area(C);
- const bToolRef *tref = sa->runtime.tool;
-
- ggd->twtype = 0;
- if (tref && STREQ(tref->idname, "builtin.move")) {
- ggd->twtype |= V3D_GIZMO_SHOW_OBJECT_TRANSLATE;
- }
- else if (tref && STREQ(tref->idname, "builtin.rotate")) {
- ggd->twtype |= V3D_GIZMO_SHOW_OBJECT_ROTATE;
- }
- else if (tref && STREQ(tref->idname, "builtin.scale")) {
- ggd->twtype |= V3D_GIZMO_SHOW_OBJECT_SCALE;
- }
- else {
- /* Setup all gizmos, they can be toggled via 'ToolSettings.gizmo_flag' */
- ggd->twtype = V3D_GIZMO_SHOW_OBJECT_TRANSLATE | V3D_GIZMO_SHOW_OBJECT_ROTATE | V3D_GIZMO_SHOW_OBJECT_SCALE;
- ggd->use_twtype_refresh = true;
- }
- BLI_assert(ggd->twtype != 0);
- ggd->twtype_init = ggd->twtype;
- }
-
- /* *** set properties for axes *** */
- gizmogroup_init_properties_from_twtype(gzgroup);
+ GizmoGroup *ggd = gizmogroup_init(gzgroup);
+
+ gzgroup->customdata = ggd;
+
+ {
+ ScrArea *sa = CTX_wm_area(C);
+ const bToolRef *tref = sa->runtime.tool;
+
+ ggd->twtype = 0;
+ if (tref && STREQ(tref->idname, "builtin.move")) {
+ ggd->twtype |= V3D_GIZMO_SHOW_OBJECT_TRANSLATE;
+ }
+ else if (tref && STREQ(tref->idname, "builtin.rotate")) {
+ ggd->twtype |= V3D_GIZMO_SHOW_OBJECT_ROTATE;
+ }
+ else if (tref && STREQ(tref->idname, "builtin.scale")) {
+ ggd->twtype |= V3D_GIZMO_SHOW_OBJECT_SCALE;
+ }
+ else {
+ /* Setup all gizmos, they can be toggled via 'ToolSettings.gizmo_flag' */
+ ggd->twtype = V3D_GIZMO_SHOW_OBJECT_TRANSLATE | V3D_GIZMO_SHOW_OBJECT_ROTATE |
+ V3D_GIZMO_SHOW_OBJECT_SCALE;
+ ggd->use_twtype_refresh = true;
+ }
+ BLI_assert(ggd->twtype != 0);
+ ggd->twtype_init = ggd->twtype;
+ }
+
+ /* *** set properties for axes *** */
+ gizmogroup_init_properties_from_twtype(gzgroup);
}
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;
- struct TransformBounds tbounds;
-
- if (ggd->use_twtype_refresh) {
- ggd->twtype = v3d->gizmo_show_object & ggd->twtype_init;
- if (ggd->twtype != ggd->twtype_prev) {
- ggd->twtype_prev = ggd->twtype;
- gizmogroup_init_properties_from_twtype(gzgroup);
- }
- }
-
- const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get_from_flag(scene, ggd->twtype_init);
-
- /* skip, we don't draw anything anyway */
- if ((ggd->all_hidden =
- (ED_transform_calc_gizmo_stats(
- C, &(struct TransformCalcParams){
- .use_only_center = true,
- .orientation_type = orient_slot->type + 1,
- .orientation_index_custom = orient_slot->index_custom,
- }, &tbounds) == 0)))
- {
- return;
- }
-
- gizmo_prepare_mat(C, rv3d, &tbounds);
-
- /* *** set properties for axes *** */
-
- MAN_ITER_AXES_BEGIN(axis, axis_idx)
- {
- const short axis_type = gizmo_get_axis_type(axis_idx);
- const int aidx_norm = gizmo_orientation_axis(axis_idx, NULL);
-
- WM_gizmo_set_matrix_location(axis, rv3d->twmat[3]);
-
- switch (axis_idx) {
- case MAN_AXIS_TRANS_X:
- case MAN_AXIS_TRANS_Y:
- case MAN_AXIS_TRANS_Z:
- case MAN_AXIS_SCALE_X:
- case MAN_AXIS_SCALE_Y:
- case MAN_AXIS_SCALE_Z:
- {
- float start_co[3] = {0.0f, 0.0f, 0.0f};
- float len;
-
- gizmo_line_range(ggd->twtype, axis_type, &start_co[2], &len);
-
- WM_gizmo_set_matrix_rotation_from_z_axis(axis, rv3d->twmat[aidx_norm]);
- RNA_float_set(axis->ptr, "length", len);
-
- if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
- if (ggd->twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) {
- /* Avoid rotate and translate arrows overlap. */
- start_co[2] += 0.215f;
- }
- }
- WM_gizmo_set_matrix_offset_location(axis, start_co);
- WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_OFFSET_SCALE, true);
- break;
- }
- case MAN_AXIS_ROT_X:
- case MAN_AXIS_ROT_Y:
- case MAN_AXIS_ROT_Z:
- WM_gizmo_set_matrix_rotation_from_z_axis(axis, rv3d->twmat[aidx_norm]);
- break;
- case MAN_AXIS_TRANS_XY:
- case MAN_AXIS_TRANS_YZ:
- case MAN_AXIS_TRANS_ZX:
- case MAN_AXIS_SCALE_XY:
- case MAN_AXIS_SCALE_YZ:
- case MAN_AXIS_SCALE_ZX:
- {
- const float *y_axis = rv3d->twmat[aidx_norm - 1 < 0 ? 2 : aidx_norm - 1];
- const float *z_axis = rv3d->twmat[aidx_norm];
- WM_gizmo_set_matrix_rotation_from_yz_axis(axis, y_axis, z_axis);
- break;
- }
- }
- }
- MAN_ITER_AXES_END;
+ 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;
+ struct TransformBounds tbounds;
+
+ if (ggd->use_twtype_refresh) {
+ ggd->twtype = v3d->gizmo_show_object & ggd->twtype_init;
+ if (ggd->twtype != ggd->twtype_prev) {
+ ggd->twtype_prev = ggd->twtype;
+ gizmogroup_init_properties_from_twtype(gzgroup);
+ }
+ }
+
+ const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get_from_flag(
+ scene, ggd->twtype_init);
+
+ /* skip, we don't draw anything anyway */
+ if ((ggd->all_hidden = (ED_transform_calc_gizmo_stats(
+ C,
+ &(struct TransformCalcParams){
+ .use_only_center = true,
+ .orientation_type = orient_slot->type + 1,
+ .orientation_index_custom = orient_slot->index_custom,
+ },
+ &tbounds) == 0))) {
+ return;
+ }
+
+ gizmo_prepare_mat(C, rv3d, &tbounds);
+
+ /* *** set properties for axes *** */
+
+ MAN_ITER_AXES_BEGIN (axis, axis_idx) {
+ const short axis_type = gizmo_get_axis_type(axis_idx);
+ const int aidx_norm = gizmo_orientation_axis(axis_idx, NULL);
+
+ WM_gizmo_set_matrix_location(axis, rv3d->twmat[3]);
+
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_X:
+ case MAN_AXIS_TRANS_Y:
+ case MAN_AXIS_TRANS_Z:
+ case MAN_AXIS_SCALE_X:
+ case MAN_AXIS_SCALE_Y:
+ case MAN_AXIS_SCALE_Z: {
+ float start_co[3] = {0.0f, 0.0f, 0.0f};
+ float len;
+
+ gizmo_line_range(ggd->twtype, axis_type, &start_co[2], &len);
+
+ WM_gizmo_set_matrix_rotation_from_z_axis(axis, rv3d->twmat[aidx_norm]);
+ RNA_float_set(axis->ptr, "length", len);
+
+ if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
+ if (ggd->twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) {
+ /* Avoid rotate and translate arrows overlap. */
+ start_co[2] += 0.215f;
+ }
+ }
+ WM_gizmo_set_matrix_offset_location(axis, start_co);
+ WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_OFFSET_SCALE, true);
+ break;
+ }
+ case MAN_AXIS_ROT_X:
+ case MAN_AXIS_ROT_Y:
+ case MAN_AXIS_ROT_Z:
+ WM_gizmo_set_matrix_rotation_from_z_axis(axis, rv3d->twmat[aidx_norm]);
+ break;
+ case MAN_AXIS_TRANS_XY:
+ case MAN_AXIS_TRANS_YZ:
+ case MAN_AXIS_TRANS_ZX:
+ case MAN_AXIS_SCALE_XY:
+ case MAN_AXIS_SCALE_YZ:
+ case MAN_AXIS_SCALE_ZX: {
+ const float *y_axis = rv3d->twmat[aidx_norm - 1 < 0 ? 2 : aidx_norm - 1];
+ const float *z_axis = rv3d->twmat[aidx_norm];
+ WM_gizmo_set_matrix_rotation_from_yz_axis(axis, y_axis, z_axis);
+ break;
+ }
+ }
+ }
+ MAN_ITER_AXES_END;
}
-static void WIDGETGROUP_gizmo_message_subscribe(
- const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus)
+static void WIDGETGROUP_gizmo_message_subscribe(const bContext *C,
+ wmGizmoGroup *gzgroup,
+ struct wmMsgBus *mbus)
{
- 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);
+ 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);
}
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;
- 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) {
- MAN_ITER_AXES_BEGIN(axis, axis_idx)
- {
- WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, true);
- }
- MAN_ITER_AXES_END;
- return;
- }
- gizmo_get_idot(rv3d, idot);
-
- /* *** set properties for axes *** */
- MAN_ITER_AXES_BEGIN(axis, axis_idx) {
- const short axis_type = gizmo_get_axis_type(axis_idx);
- /* XXX maybe unset _HIDDEN flag on redraw? */
-
- if (gizmo_is_axis_visible(rv3d, ggd->twtype, idot, axis_type, axis_idx)) {
- WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, false);
- }
- else {
- WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, true);
- continue;
- }
-
- float color[4], color_hi[4];
- gizmo_get_axis_color(axis_idx, idot, color, color_hi);
- WM_gizmo_set_color(axis, color);
- WM_gizmo_set_color_highlight(axis, color_hi);
-
- switch (axis_idx) {
- case MAN_AXIS_TRANS_C:
- case MAN_AXIS_ROT_C:
- case MAN_AXIS_SCALE_C:
- case MAN_AXIS_ROT_T:
- WM_gizmo_set_matrix_rotation_from_z_axis(axis, rv3d->viewinv[2]);
- break;
- }
- } MAN_ITER_AXES_END;
-
- /* Refresh handled above when using view orientation. */
- if (!equals_m3m3(viewinv_m3, ggd->prev.viewinv_m3)) {
- {
- Scene *scene = CTX_data_scene(C);
- const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get_from_flag(scene, ggd->twtype_init);
- switch (orient_slot->type) {
- case V3D_ORIENT_VIEW:
- {
- WIDGETGROUP_gizmo_refresh(C, gzgroup);
- break;
- }
- }
- }
- copy_m3_m4(ggd->prev.viewinv_m3, rv3d->viewinv);
- }
-
+ 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;
+ 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) {
+ MAN_ITER_AXES_BEGIN (axis, axis_idx) {
+ WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, true);
+ }
+ MAN_ITER_AXES_END;
+ return;
+ }
+ gizmo_get_idot(rv3d, idot);
+
+ /* *** set properties for axes *** */
+ MAN_ITER_AXES_BEGIN (axis, axis_idx) {
+ const short axis_type = gizmo_get_axis_type(axis_idx);
+ /* XXX maybe unset _HIDDEN flag on redraw? */
+
+ if (gizmo_is_axis_visible(rv3d, ggd->twtype, idot, axis_type, axis_idx)) {
+ WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, false);
+ }
+ else {
+ WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, true);
+ continue;
+ }
+
+ float color[4], color_hi[4];
+ gizmo_get_axis_color(axis_idx, idot, color, color_hi);
+ WM_gizmo_set_color(axis, color);
+ WM_gizmo_set_color_highlight(axis, color_hi);
+
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_C:
+ case MAN_AXIS_ROT_C:
+ case MAN_AXIS_SCALE_C:
+ case MAN_AXIS_ROT_T:
+ WM_gizmo_set_matrix_rotation_from_z_axis(axis, rv3d->viewinv[2]);
+ break;
+ }
+ }
+ MAN_ITER_AXES_END;
+
+ /* Refresh handled above when using view orientation. */
+ if (!equals_m3m3(viewinv_m3, ggd->prev.viewinv_m3)) {
+ {
+ Scene *scene = CTX_data_scene(C);
+ const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get_from_flag(
+ scene, ggd->twtype_init);
+ switch (orient_slot->type) {
+ case V3D_ORIENT_VIEW: {
+ WIDGETGROUP_gizmo_refresh(C, gzgroup);
+ break;
+ }
+ }
+ }
+ copy_m3_m4(ggd->prev.viewinv_m3, rv3d->viewinv);
+ }
}
-static void WIDGETGROUP_gizmo_invoke_prepare(
- const bContext *C, wmGizmoGroup *gzgroup, wmGizmo *gz)
+static void WIDGETGROUP_gizmo_invoke_prepare(const bContext *C, wmGizmoGroup *gzgroup, wmGizmo *gz)
{
- GizmoGroup *ggd = gzgroup->customdata;
-
- /* Support gizmo spesific orientation. */
- if (gz != ggd->gizmos[MAN_AXIS_ROT_T]) {
- Scene *scene = CTX_data_scene(C);
- wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
- PointerRNA *ptr = &gzop->ptr;
- PropertyRNA *prop_orient_type = RNA_struct_find_property(ptr, "orient_type");
- const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get_from_flag(scene, ggd->twtype_init);
- if (orient_slot == &scene->orientation_slots[SCE_ORIENT_DEFAULT]) {
- RNA_property_unset(ptr, prop_orient_type);
- }
- else {
- /* TODO: APIfunction */
- int index = BKE_scene_orientation_slot_get_index(orient_slot);
- RNA_property_enum_set(ptr, prop_orient_type, index);
- }
- }
-
- /* Support shift click to constrain axis. */
- const int axis_idx = BLI_array_findindex(ggd->gizmos, ARRAY_SIZE(ggd->gizmos), &gz);
- int axis = -1;
- switch (axis_idx) {
- case MAN_AXIS_TRANS_X:
- case MAN_AXIS_TRANS_Y:
- case MAN_AXIS_TRANS_Z:
- axis = axis_idx - MAN_AXIS_TRANS_X; break;
- case MAN_AXIS_SCALE_X:
- case MAN_AXIS_SCALE_Y:
- case MAN_AXIS_SCALE_Z:
- axis = axis_idx - MAN_AXIS_SCALE_X; break;
- }
-
- if (axis != -1) {
- wmWindow *win = CTX_wm_window(C);
- /* Swap single axis for two-axis constraint. */
- bool flip = win->eventstate->shift;
- BLI_assert(axis_idx != -1);
- const short axis_type = gizmo_get_axis_type(axis_idx);
- if (axis_type != MAN_AXES_ROTATE) {
- wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
- PointerRNA *ptr = &gzop->ptr;
- PropertyRNA *prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
- if (prop_constraint_axis) {
- bool constraint[3] = {false};
- constraint[axis] = true;
- if (flip) {
- for (int i = 0; i < ARRAY_SIZE(constraint); i++) {
- constraint[i] = !constraint[i];
- }
- }
- RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint);
- }
- }
- }
+ GizmoGroup *ggd = gzgroup->customdata;
+
+ /* Support gizmo spesific orientation. */
+ if (gz != ggd->gizmos[MAN_AXIS_ROT_T]) {
+ Scene *scene = CTX_data_scene(C);
+ wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
+ PointerRNA *ptr = &gzop->ptr;
+ PropertyRNA *prop_orient_type = RNA_struct_find_property(ptr, "orient_type");
+ const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get_from_flag(
+ scene, ggd->twtype_init);
+ if (orient_slot == &scene->orientation_slots[SCE_ORIENT_DEFAULT]) {
+ RNA_property_unset(ptr, prop_orient_type);
+ }
+ else {
+ /* TODO: APIfunction */
+ int index = BKE_scene_orientation_slot_get_index(orient_slot);
+ RNA_property_enum_set(ptr, prop_orient_type, index);
+ }
+ }
+
+ /* Support shift click to constrain axis. */
+ const int axis_idx = BLI_array_findindex(ggd->gizmos, ARRAY_SIZE(ggd->gizmos), &gz);
+ int axis = -1;
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_X:
+ case MAN_AXIS_TRANS_Y:
+ case MAN_AXIS_TRANS_Z:
+ axis = axis_idx - MAN_AXIS_TRANS_X;
+ break;
+ case MAN_AXIS_SCALE_X:
+ case MAN_AXIS_SCALE_Y:
+ case MAN_AXIS_SCALE_Z:
+ axis = axis_idx - MAN_AXIS_SCALE_X;
+ break;
+ }
+
+ if (axis != -1) {
+ wmWindow *win = CTX_wm_window(C);
+ /* Swap single axis for two-axis constraint. */
+ bool flip = win->eventstate->shift;
+ BLI_assert(axis_idx != -1);
+ const short axis_type = gizmo_get_axis_type(axis_idx);
+ if (axis_type != MAN_AXES_ROTATE) {
+ wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
+ PointerRNA *ptr = &gzop->ptr;
+ PropertyRNA *prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
+ if (prop_constraint_axis) {
+ bool constraint[3] = {false};
+ constraint[axis] = true;
+ if (flip) {
+ for (int i = 0; i < ARRAY_SIZE(constraint); i++) {
+ constraint[i] = !constraint[i];
+ }
+ }
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint);
+ }
+ }
+ }
}
static bool WIDGETGROUP_gizmo_poll_generic(View3D *v3d)
{
- if (v3d->gizmo_flag & V3D_GIZMO_HIDE) {
- return false;
- }
- if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) {
- return false;
- }
- return true;
+ if (v3d->gizmo_flag & V3D_GIZMO_HIDE) {
+ return false;
+ }
+ if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) {
+ return false;
+ }
+ return true;
}
-static bool WIDGETGROUP_gizmo_poll_context(const struct bContext *C, struct wmGizmoGroupType *UNUSED(gzgt))
+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;
- if (!WIDGETGROUP_gizmo_poll_generic(v3d)) {
- return false;
- }
-
- const bToolRef *tref = sa->runtime.tool;
- if (v3d->gizmo_flag & V3D_GIZMO_HIDE_CONTEXT) {
- return false;
- }
- if ((v3d->gizmo_show_object & (V3D_GIZMO_SHOW_OBJECT_TRANSLATE | V3D_GIZMO_SHOW_OBJECT_ROTATE | V3D_GIZMO_SHOW_OBJECT_SCALE)) == 0) {
- return false;
- }
-
- /* Don't show if the tool has a gizmo. */
- if (tref && tref->runtime && tref->runtime->gizmo_group[0]) {
- return false;
- }
- return true;
+ ScrArea *sa = CTX_wm_area(C);
+ View3D *v3d = sa->spacedata.first;
+ if (!WIDGETGROUP_gizmo_poll_generic(v3d)) {
+ return false;
+ }
+
+ const bToolRef *tref = sa->runtime.tool;
+ if (v3d->gizmo_flag & V3D_GIZMO_HIDE_CONTEXT) {
+ return false;
+ }
+ if ((v3d->gizmo_show_object & (V3D_GIZMO_SHOW_OBJECT_TRANSLATE | V3D_GIZMO_SHOW_OBJECT_ROTATE |
+ V3D_GIZMO_SHOW_OBJECT_SCALE)) == 0) {
+ return false;
+ }
+
+ /* Don't show if the tool has a gizmo. */
+ if (tref && tref->runtime && tref->runtime->gizmo_group[0]) {
+ return false;
+ }
+ return true;
}
static bool WIDGETGROUP_gizmo_poll_tool(const struct bContext *C, struct wmGizmoGroupType *gzgt)
{
- if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
- return false;
- }
-
- return true;
- ScrArea *sa = CTX_wm_area(C);
- View3D *v3d = sa->spacedata.first;
- if (!WIDGETGROUP_gizmo_poll_generic(v3d)) {
- return false;
- }
-
- if (v3d->gizmo_flag & V3D_GIZMO_HIDE_TOOL) {
- return false;
- }
-
- return true;
+ if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
+ return false;
+ }
+
+ return true;
+ ScrArea *sa = CTX_wm_area(C);
+ View3D *v3d = sa->spacedata.first;
+ if (!WIDGETGROUP_gizmo_poll_generic(v3d)) {
+ return false;
+ }
+
+ if (v3d->gizmo_flag & V3D_GIZMO_HIDE_TOOL) {
+ return false;
+ }
+
+ return true;
}
/* Expose as multiple gizmos so tools use one, persistant context another.
@@ -1950,236 +1954,238 @@ static bool WIDGETGROUP_gizmo_poll_tool(const struct bContext *C, struct wmGizmo
void VIEW3D_GGT_xform_gizmo(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Transform Gizmo";
- gzgt->idname = "VIEW3D_GGT_xform_gizmo";
+ gzgt->name = "Transform Gizmo";
+ gzgt->idname = "VIEW3D_GGT_xform_gizmo";
- gzgt->flag = WM_GIZMOGROUPTYPE_3D;
+ gzgt->flag = WM_GIZMOGROUPTYPE_3D;
- gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
- gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- gzgt->poll = WIDGETGROUP_gizmo_poll_tool;
- gzgt->setup = WIDGETGROUP_gizmo_setup;
- gzgt->refresh = WIDGETGROUP_gizmo_refresh;
- gzgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe;
- gzgt->draw_prepare = WIDGETGROUP_gizmo_draw_prepare;
- gzgt->invoke_prepare = WIDGETGROUP_gizmo_invoke_prepare;
+ gzgt->poll = WIDGETGROUP_gizmo_poll_tool;
+ gzgt->setup = WIDGETGROUP_gizmo_setup;
+ gzgt->refresh = WIDGETGROUP_gizmo_refresh;
+ gzgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe;
+ gzgt->draw_prepare = WIDGETGROUP_gizmo_draw_prepare;
+ gzgt->invoke_prepare = WIDGETGROUP_gizmo_invoke_prepare;
}
/** Only poll, flag & gzmap_params differ. */
void VIEW3D_GGT_xform_gizmo_context(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Transform Gizmo Context";
- gzgt->idname = "VIEW3D_GGT_xform_gizmo_context";
+ gzgt->name = "Transform Gizmo Context";
+ gzgt->idname = "VIEW3D_GGT_xform_gizmo_context";
- gzgt->flag = WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_PERSISTENT;
+ gzgt->flag = WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_PERSISTENT;
- gzgt->poll = WIDGETGROUP_gizmo_poll_context;
- gzgt->setup = WIDGETGROUP_gizmo_setup;
- gzgt->refresh = WIDGETGROUP_gizmo_refresh;
- gzgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe;
- gzgt->draw_prepare = WIDGETGROUP_gizmo_draw_prepare;
- gzgt->invoke_prepare = WIDGETGROUP_gizmo_invoke_prepare;
+ gzgt->poll = WIDGETGROUP_gizmo_poll_context;
+ gzgt->setup = WIDGETGROUP_gizmo_setup;
+ gzgt->refresh = WIDGETGROUP_gizmo_refresh;
+ gzgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe;
+ gzgt->draw_prepare = WIDGETGROUP_gizmo_draw_prepare;
+ gzgt->invoke_prepare = WIDGETGROUP_gizmo_invoke_prepare;
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Scale Cage Gizmo
* \{ */
struct XFormCageWidgetGroup {
- wmGizmo *gizmo;
- /* Only for view orientation. */
- struct {
- float viewinv_m3[3][3];
- } prev;
+ wmGizmo *gizmo;
+ /* Only for view orientation. */
+ struct {
+ float viewinv_m3[3][3];
+ } prev;
};
static bool WIDGETGROUP_xform_cage_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
- if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
- return false;
- }
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) {
- return false;
- }
- if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) {
- return false;
- }
- return true;
+ if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
+ return false;
+ }
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) {
+ return false;
+ }
+ if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) {
+ return false;
+ }
+ return true;
}
static void WIDGETGROUP_xform_cage_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- struct XFormCageWidgetGroup *xgzgroup = MEM_mallocN(sizeof(struct XFormCageWidgetGroup), __func__);
- const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_3d", true);
- xgzgroup->gizmo = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL);
- wmGizmo *gz = xgzgroup->gizmo;
-
- RNA_enum_set(gz->ptr, "transform",
- ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE |
- ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE);
-
- gz->color[0] = 1;
- gz->color_hi[0] = 1;
-
- gzgroup->customdata = xgzgroup;
-
- {
- wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
- PointerRNA *ptr;
-
- /* assign operator */
- PropertyRNA *prop_release_confirm = NULL;
- PropertyRNA *prop_constraint_axis = NULL;
-
- int i = ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z;
- for (int x = 0; x < 3; x++) {
- for (int y = 0; y < 3; y++) {
- for (int z = 0; z < 3; z++) {
- bool constraint[3] = {x != 1, y != 1, z != 1};
- ptr = WM_gizmo_operator_set(gz, i, ot_resize, NULL);
- if (prop_release_confirm == NULL) {
- prop_release_confirm = RNA_struct_find_property(ptr, "release_confirm");
- prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
- }
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
- RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint);
- i++;
- }
- }
- }
- }
+ struct XFormCageWidgetGroup *xgzgroup = MEM_mallocN(sizeof(struct XFormCageWidgetGroup),
+ __func__);
+ const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_3d", true);
+ xgzgroup->gizmo = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL);
+ wmGizmo *gz = xgzgroup->gizmo;
+
+ RNA_enum_set(gz->ptr,
+ "transform",
+ ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE | ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE);
+
+ gz->color[0] = 1;
+ gz->color_hi[0] = 1;
+
+ gzgroup->customdata = xgzgroup;
+
+ {
+ wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
+ PointerRNA *ptr;
+
+ /* assign operator */
+ PropertyRNA *prop_release_confirm = NULL;
+ PropertyRNA *prop_constraint_axis = NULL;
+
+ int i = ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z;
+ for (int x = 0; x < 3; x++) {
+ for (int y = 0; y < 3; y++) {
+ for (int z = 0; z < 3; z++) {
+ bool constraint[3] = {x != 1, y != 1, z != 1};
+ ptr = WM_gizmo_operator_set(gz, i, ot_resize, NULL);
+ if (prop_release_confirm == NULL) {
+ prop_release_confirm = RNA_struct_find_property(ptr, "release_confirm");
+ prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
+ }
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint);
+ i++;
+ }
+ }
+ }
+ }
}
static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
- Scene *scene = CTX_data_scene(C);
-
- struct XFormCageWidgetGroup *xgzgroup = gzgroup->customdata;
- wmGizmo *gz = xgzgroup->gizmo;
-
- struct TransformBounds tbounds;
-
- const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene, SCE_ORIENT_SCALE);
-
- if ((ED_transform_calc_gizmo_stats(
- C, &(struct TransformCalcParams) {
- .use_local_axis = true,
- .orientation_type = orient_slot->type + 1,
- .orientation_index_custom = orient_slot->index_custom,
- }, &tbounds) == 0) ||
- equals_v3v3(rv3d->tw_axis_min, rv3d->tw_axis_max))
- {
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
- }
- else {
- gizmo_prepare_mat(C, rv3d, &tbounds);
-
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
- WM_gizmo_set_flag(gz, WM_GIZMO_MOVE_CURSOR, true);
-
- float dims[3];
- sub_v3_v3v3(dims, rv3d->tw_axis_max, rv3d->tw_axis_min);
- RNA_float_set_array(gz->ptr, "dimensions", dims);
- mul_v3_fl(dims, 0.5f);
-
- copy_m4_m3(gz->matrix_offset, rv3d->tw_axis_matrix);
- mid_v3_v3v3(gz->matrix_offset[3], rv3d->tw_axis_max, rv3d->tw_axis_min);
- mul_m3_v3(rv3d->tw_axis_matrix, gz->matrix_offset[3]);
-
- float matrix_offset_global[4][4];
- mul_m4_m4m4(matrix_offset_global, gz->matrix_space, gz->matrix_offset);
-
- PropertyRNA *prop_center_override = NULL;
- float center[3];
- float center_global[3];
- int i = ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z;
- for (int x = 0; x < 3; x++) {
- center[0] = (float)(1 - x) * dims[0];
- for (int y = 0; y < 3; y++) {
- center[1] = (float)(1 - y) * dims[1];
- for (int z = 0; z < 3; z++) {
- center[2] = (float)(1 - z) * dims[2];
- struct wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, i);
- if (prop_center_override == NULL) {
- prop_center_override = RNA_struct_find_property(&gzop->ptr, "center_override");
- }
- mul_v3_m4v3(center_global, matrix_offset_global, center);
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, center_global);
- i++;
- }
- }
- }
- }
-
- /* Needed to test view orientation changes. */
- copy_m3_m4(xgzgroup->prev.viewinv_m3, rv3d->viewinv);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ Scene *scene = CTX_data_scene(C);
+
+ struct XFormCageWidgetGroup *xgzgroup = gzgroup->customdata;
+ wmGizmo *gz = xgzgroup->gizmo;
+
+ struct TransformBounds tbounds;
+
+ const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene,
+ SCE_ORIENT_SCALE);
+
+ if ((ED_transform_calc_gizmo_stats(C,
+ &(struct TransformCalcParams){
+ .use_local_axis = true,
+ .orientation_type = orient_slot->type + 1,
+ .orientation_index_custom = orient_slot->index_custom,
+ },
+ &tbounds) == 0) ||
+ equals_v3v3(rv3d->tw_axis_min, rv3d->tw_axis_max)) {
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
+ }
+ else {
+ gizmo_prepare_mat(C, rv3d, &tbounds);
+
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
+ WM_gizmo_set_flag(gz, WM_GIZMO_MOVE_CURSOR, true);
+
+ float dims[3];
+ sub_v3_v3v3(dims, rv3d->tw_axis_max, rv3d->tw_axis_min);
+ RNA_float_set_array(gz->ptr, "dimensions", dims);
+ mul_v3_fl(dims, 0.5f);
+
+ copy_m4_m3(gz->matrix_offset, rv3d->tw_axis_matrix);
+ mid_v3_v3v3(gz->matrix_offset[3], rv3d->tw_axis_max, rv3d->tw_axis_min);
+ mul_m3_v3(rv3d->tw_axis_matrix, gz->matrix_offset[3]);
+
+ float matrix_offset_global[4][4];
+ mul_m4_m4m4(matrix_offset_global, gz->matrix_space, gz->matrix_offset);
+
+ PropertyRNA *prop_center_override = NULL;
+ float center[3];
+ float center_global[3];
+ int i = ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z;
+ for (int x = 0; x < 3; x++) {
+ center[0] = (float)(1 - x) * dims[0];
+ for (int y = 0; y < 3; y++) {
+ center[1] = (float)(1 - y) * dims[1];
+ for (int z = 0; z < 3; z++) {
+ center[2] = (float)(1 - z) * dims[2];
+ struct wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, i);
+ if (prop_center_override == NULL) {
+ prop_center_override = RNA_struct_find_property(&gzop->ptr, "center_override");
+ }
+ mul_v3_m4v3(center_global, matrix_offset_global, center);
+ RNA_property_float_set_array(&gzop->ptr, prop_center_override, center_global);
+ i++;
+ }
+ }
+ }
+ }
+
+ /* Needed to test view orientation changes. */
+ copy_m3_m4(xgzgroup->prev.viewinv_m3, rv3d->viewinv);
}
-static void WIDGETGROUP_xform_cage_message_subscribe(
- const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus)
+static void WIDGETGROUP_xform_cage_message_subscribe(const bContext *C,
+ wmGizmoGroup *gzgroup,
+ struct wmMsgBus *mbus)
{
- 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);
+ 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);
}
static void WIDGETGROUP_xform_cage_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct XFormCageWidgetGroup *xgzgroup = gzgroup->customdata;
- wmGizmo *gz = xgzgroup->gizmo;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- if (ob && ob->mode & OB_MODE_EDIT) {
- copy_m4_m4(gz->matrix_space, ob->obmat);
- }
- else {
- unit_m4(gz->matrix_space);
- }
-
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- {
- Scene *scene = CTX_data_scene(C);
- const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene, SCE_ORIENT_SCALE);
- switch (orient_slot->type) {
- case V3D_ORIENT_VIEW:
- {
- float viewinv_m3[3][3];
- copy_m3_m4(viewinv_m3, rv3d->viewinv);
- if (!equals_m3m3(viewinv_m3, xgzgroup->prev.viewinv_m3)) {
- /* Take care calling refresh from draw_prepare,
- * this should be OK because it's only adjusting the cage orientation. */
- WIDGETGROUP_xform_cage_refresh(C, gzgroup);
- }
- break;
- }
- }
- }
+ struct XFormCageWidgetGroup *xgzgroup = gzgroup->customdata;
+ wmGizmo *gz = xgzgroup->gizmo;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ if (ob && ob->mode & OB_MODE_EDIT) {
+ copy_m4_m4(gz->matrix_space, ob->obmat);
+ }
+ else {
+ unit_m4(gz->matrix_space);
+ }
+
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ {
+ Scene *scene = CTX_data_scene(C);
+ const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene,
+ SCE_ORIENT_SCALE);
+ switch (orient_slot->type) {
+ case V3D_ORIENT_VIEW: {
+ float viewinv_m3[3][3];
+ copy_m3_m4(viewinv_m3, rv3d->viewinv);
+ if (!equals_m3m3(viewinv_m3, xgzgroup->prev.viewinv_m3)) {
+ /* Take care calling refresh from draw_prepare,
+ * this should be OK because it's only adjusting the cage orientation. */
+ WIDGETGROUP_xform_cage_refresh(C, gzgroup);
+ }
+ break;
+ }
+ }
+ }
}
void VIEW3D_GGT_xform_cage(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Transform Cage";
- gzgt->idname = "VIEW3D_GGT_xform_cage";
+ gzgt->name = "Transform Cage";
+ gzgt->idname = "VIEW3D_GGT_xform_cage";
- gzgt->flag |= WM_GIZMOGROUPTYPE_3D;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_3D;
- gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
- gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- gzgt->poll = WIDGETGROUP_xform_cage_poll;
- gzgt->setup = WIDGETGROUP_xform_cage_setup;
- gzgt->refresh = WIDGETGROUP_xform_cage_refresh;
- gzgt->message_subscribe = WIDGETGROUP_xform_cage_message_subscribe;
- gzgt->draw_prepare = WIDGETGROUP_xform_cage_draw_prepare;
+ gzgt->poll = WIDGETGROUP_xform_cage_poll;
+ gzgt->setup = WIDGETGROUP_xform_cage_setup;
+ gzgt->refresh = WIDGETGROUP_xform_cage_refresh;
+ gzgt->message_subscribe = WIDGETGROUP_xform_cage_message_subscribe;
+ gzgt->draw_prepare = WIDGETGROUP_xform_cage_draw_prepare;
}
/** \} */
@@ -2189,177 +2195,180 @@ void VIEW3D_GGT_xform_cage(wmGizmoGroupType *gzgt)
* \{ */
struct XFormShearWidgetGroup {
- wmGizmo *gizmo[3][2];
- /* Only for view orientation. */
- struct {
- float viewinv_m3[3][3];
- } prev;
+ wmGizmo *gizmo[3][2];
+ /* Only for view orientation. */
+ struct {
+ float viewinv_m3[3][3];
+ } prev;
};
static bool WIDGETGROUP_xform_shear_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
- if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
- return false;
- }
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) {
- return false;
- }
- return true;
+ if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
+ return false;
+ }
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) {
+ return false;
+ }
+ return true;
}
static void WIDGETGROUP_xform_shear_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- struct XFormShearWidgetGroup *xgzgroup = MEM_mallocN(sizeof(struct XFormShearWidgetGroup), __func__);
- const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
- wmOperatorType *ot_shear = WM_operatortype_find("TRANSFORM_OT_shear", true);
-
- float axis_color[3][3];
- for (int i = 0; i < 3; i++) {
- UI_GetThemeColor3fv(TH_AXIS_X + i, axis_color[i]);
- }
-
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 2; j++) {
- wmGizmo *gz = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
- RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_BOX);
- const int i_ortho_a = (i + j + 1) % 3;
- const int i_ortho_b = (i + (1 - j) + 1) % 3;
- interp_v3_v3v3(gz->color, axis_color[i_ortho_a], axis_color[i_ortho_b], 0.75f);
- gz->color[3] = 0.5f;
- PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot_shear, NULL);
- RNA_enum_set(ptr, "shear_axis", 0);
- RNA_boolean_set(ptr, "release_confirm", 1);
- xgzgroup->gizmo[i][j] = gz;
- }
- }
-
- gzgroup->customdata = xgzgroup;
+ struct XFormShearWidgetGroup *xgzgroup = MEM_mallocN(sizeof(struct XFormShearWidgetGroup),
+ __func__);
+ const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
+ wmOperatorType *ot_shear = WM_operatortype_find("TRANSFORM_OT_shear", true);
+
+ float axis_color[3][3];
+ for (int i = 0; i < 3; i++) {
+ UI_GetThemeColor3fv(TH_AXIS_X + i, axis_color[i]);
+ }
+
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 2; j++) {
+ wmGizmo *gz = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_BOX);
+ const int i_ortho_a = (i + j + 1) % 3;
+ const int i_ortho_b = (i + (1 - j) + 1) % 3;
+ interp_v3_v3v3(gz->color, axis_color[i_ortho_a], axis_color[i_ortho_b], 0.75f);
+ gz->color[3] = 0.5f;
+ PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot_shear, NULL);
+ RNA_enum_set(ptr, "shear_axis", 0);
+ RNA_boolean_set(ptr, "release_confirm", 1);
+ xgzgroup->gizmo[i][j] = gz;
+ }
+ }
+
+ gzgroup->customdata = xgzgroup;
}
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;
-
- struct XFormShearWidgetGroup *xgzgroup = gzgroup->customdata;
- struct TransformBounds tbounds;
-
- const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene, SCE_ORIENT_ROTATE);
-
- if (ED_transform_calc_gizmo_stats(
- C, &(struct TransformCalcParams) {
- .use_local_axis = false,
- .orientation_type = orient_slot->type + 1,
- .orientation_index_custom = orient_slot->index_custom,
- }, &tbounds) == 0)
- {
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 2; j++) {
- wmGizmo *gz = xgzgroup->gizmo[i][j];
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
- }
- }
- }
- else {
- gizmo_prepare_mat(C, rv3d, &tbounds);
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 2; j++) {
- wmGizmo *gz = xgzgroup->gizmo[i][j];
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
- WM_gizmo_set_flag(gz, WM_GIZMO_MOVE_CURSOR, true);
-
- wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
- const int i_ortho_a = (i + j + 1) % 3;
- const int i_ortho_b = (i + (1 - j) + 1) % 3;
- WM_gizmo_set_matrix_rotation_from_yz_axis(gz, rv3d->twmat[i_ortho_a], rv3d->twmat[i]);
- WM_gizmo_set_matrix_location(gz, rv3d->twmat[3]);
-
- RNA_float_set_array(&gzop->ptr, "orient_matrix", &tbounds.axis[0][0]);
- RNA_enum_set(&gzop->ptr, "orient_type", orient_slot->type);
-
- RNA_enum_set(&gzop->ptr, "orient_axis", i_ortho_b);
- RNA_enum_set(&gzop->ptr, "orient_axis_ortho", i_ortho_a);
-
- mul_v3_fl(gz->matrix_basis[0], 0.5f);
- mul_v3_fl(gz->matrix_basis[1], 6.0f);
- }
- }
- }
-
- /* Needed to test view orientation changes. */
- copy_m3_m4(xgzgroup->prev.viewinv_m3, rv3d->viewinv);
+ Scene *scene = CTX_data_scene(C);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ struct XFormShearWidgetGroup *xgzgroup = gzgroup->customdata;
+ struct TransformBounds tbounds;
+
+ const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene,
+ SCE_ORIENT_ROTATE);
+
+ if (ED_transform_calc_gizmo_stats(C,
+ &(struct TransformCalcParams){
+ .use_local_axis = false,
+ .orientation_type = orient_slot->type + 1,
+ .orientation_index_custom = orient_slot->index_custom,
+ },
+ &tbounds) == 0) {
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 2; j++) {
+ wmGizmo *gz = xgzgroup->gizmo[i][j];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
+ }
+ }
+ }
+ else {
+ gizmo_prepare_mat(C, rv3d, &tbounds);
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 2; j++) {
+ wmGizmo *gz = xgzgroup->gizmo[i][j];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
+ WM_gizmo_set_flag(gz, WM_GIZMO_MOVE_CURSOR, true);
+
+ wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
+ const int i_ortho_a = (i + j + 1) % 3;
+ const int i_ortho_b = (i + (1 - j) + 1) % 3;
+ WM_gizmo_set_matrix_rotation_from_yz_axis(gz, rv3d->twmat[i_ortho_a], rv3d->twmat[i]);
+ WM_gizmo_set_matrix_location(gz, rv3d->twmat[3]);
+
+ RNA_float_set_array(&gzop->ptr, "orient_matrix", &tbounds.axis[0][0]);
+ RNA_enum_set(&gzop->ptr, "orient_type", orient_slot->type);
+
+ RNA_enum_set(&gzop->ptr, "orient_axis", i_ortho_b);
+ RNA_enum_set(&gzop->ptr, "orient_axis_ortho", i_ortho_a);
+
+ mul_v3_fl(gz->matrix_basis[0], 0.5f);
+ mul_v3_fl(gz->matrix_basis[1], 6.0f);
+ }
+ }
+ }
+
+ /* Needed to test view orientation changes. */
+ copy_m3_m4(xgzgroup->prev.viewinv_m3, rv3d->viewinv);
}
-static void WIDGETGROUP_xform_shear_message_subscribe(
- const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus)
+static void WIDGETGROUP_xform_shear_message_subscribe(const bContext *C,
+ wmGizmoGroup *gzgroup,
+ struct wmMsgBus *mbus)
{
- 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);
+ 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);
}
static void WIDGETGROUP_xform_shear_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct XFormShearWidgetGroup *xgzgroup = gzgroup->customdata;
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- {
- Scene *scene = CTX_data_scene(C);
- /* Shear is like rotate, use the rotate setting. */
- const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene, SCE_ORIENT_ROTATE);
- switch (orient_slot->type) {
- case V3D_ORIENT_VIEW:
- {
- float viewinv_m3[3][3];
- copy_m3_m4(viewinv_m3, rv3d->viewinv);
- if (!equals_m3m3(viewinv_m3, xgzgroup->prev.viewinv_m3)) {
- /* Take care calling refresh from draw_prepare,
- * this should be OK because it's only adjusting the cage orientation. */
- WIDGETGROUP_xform_shear_refresh(C, gzgroup);
- }
- break;
- }
- }
- }
-
- /* Basic ordering for drawing only. */
- {
- LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
- /* Since we have two pairs of each axis,
- * bias the values so gizmos that are orthogonal to the view get priority.
- * This means we never default to shearing along
- * the view axis in the case of an overlap. */
- float axis_order[3], axis_bias[3];
- copy_v3_v3(axis_order, gz->matrix_basis[2]);
- copy_v3_v3(axis_bias, gz->matrix_basis[1]);
- if (dot_v3v3(axis_bias, rv3d->viewinv[2]) < 0.0f) {
- negate_v3(axis_bias);
- }
- madd_v3_v3fl(axis_order, axis_bias, 0.01f);
- gz->temp.f = dot_v3v3(rv3d->viewinv[2], axis_order);
- }
- BLI_listbase_sort(&gzgroup->gizmos, WM_gizmo_cmp_temp_fl_reverse);
- }
+ struct XFormShearWidgetGroup *xgzgroup = gzgroup->customdata;
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ {
+ Scene *scene = CTX_data_scene(C);
+ /* Shear is like rotate, use the rotate setting. */
+ const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(
+ scene, SCE_ORIENT_ROTATE);
+ switch (orient_slot->type) {
+ case V3D_ORIENT_VIEW: {
+ float viewinv_m3[3][3];
+ copy_m3_m4(viewinv_m3, rv3d->viewinv);
+ if (!equals_m3m3(viewinv_m3, xgzgroup->prev.viewinv_m3)) {
+ /* Take care calling refresh from draw_prepare,
+ * this should be OK because it's only adjusting the cage orientation. */
+ WIDGETGROUP_xform_shear_refresh(C, gzgroup);
+ }
+ break;
+ }
+ }
+ }
+
+ /* Basic ordering for drawing only. */
+ {
+ LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
+ /* Since we have two pairs of each axis,
+ * bias the values so gizmos that are orthogonal to the view get priority.
+ * This means we never default to shearing along
+ * the view axis in the case of an overlap. */
+ float axis_order[3], axis_bias[3];
+ copy_v3_v3(axis_order, gz->matrix_basis[2]);
+ copy_v3_v3(axis_bias, gz->matrix_basis[1]);
+ if (dot_v3v3(axis_bias, rv3d->viewinv[2]) < 0.0f) {
+ negate_v3(axis_bias);
+ }
+ madd_v3_v3fl(axis_order, axis_bias, 0.01f);
+ gz->temp.f = dot_v3v3(rv3d->viewinv[2], axis_order);
+ }
+ BLI_listbase_sort(&gzgroup->gizmos, WM_gizmo_cmp_temp_fl_reverse);
+ }
}
void VIEW3D_GGT_xform_shear(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Transform Shear";
- gzgt->idname = "VIEW3D_GGT_xform_shear";
+ gzgt->name = "Transform Shear";
+ gzgt->idname = "VIEW3D_GGT_xform_shear";
- gzgt->flag |= WM_GIZMOGROUPTYPE_3D;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_3D;
- gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
- gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- gzgt->poll = WIDGETGROUP_xform_shear_poll;
- gzgt->setup = WIDGETGROUP_xform_shear_setup;
- gzgt->refresh = WIDGETGROUP_xform_shear_refresh;
- gzgt->message_subscribe = WIDGETGROUP_xform_shear_message_subscribe;
- gzgt->draw_prepare = WIDGETGROUP_xform_shear_draw_prepare;
+ gzgt->poll = WIDGETGROUP_xform_shear_poll;
+ gzgt->setup = WIDGETGROUP_xform_shear_setup;
+ gzgt->refresh = WIDGETGROUP_xform_shear_refresh;
+ gzgt->message_subscribe = WIDGETGROUP_xform_shear_message_subscribe;
+ gzgt->draw_prepare = WIDGETGROUP_xform_shear_draw_prepare;
}
/** \} */
diff --git a/source/blender/editors/transform/transform_gizmo_extrude_3d.c b/source/blender/editors/transform/transform_gizmo_extrude_3d.c
index 3d2e7c89f2b..47a584561f9 100644
--- a/source/blender/editors/transform/transform_gizmo_extrude_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_extrude_3d.c
@@ -49,8 +49,8 @@
* \{ */
enum {
- EXTRUDE_AXIS_NORMAL = 0,
- EXTRUDE_AXIS_XYZ = 1,
+ EXTRUDE_AXIS_NORMAL = 0,
+ EXTRUDE_AXIS_XYZ = 1,
};
static const float extrude_button_scale = 0.15f;
@@ -61,415 +61,418 @@ static const float extrude_arrow_normal_axis_scale = 1.0f;
static const float extrude_dial_scale = 0.2;
static const uchar shape_plus[] = {
- 0x5f, 0xfb, 0x40, 0xee, 0x25, 0xda, 0x11, 0xbf, 0x4, 0xa0, 0x0, 0x80, 0x4, 0x5f, 0x11,
- 0x40, 0x25, 0x25, 0x40, 0x11, 0x5f, 0x4, 0x7f, 0x0, 0xa0, 0x4, 0xbf, 0x11, 0xda, 0x25,
- 0xee, 0x40, 0xfb, 0x5f, 0xff, 0x7f, 0xfb, 0xa0, 0xee, 0xbf, 0xda, 0xda, 0xbf, 0xee,
- 0xa0, 0xfb, 0x80, 0xff, 0x6e, 0xd7, 0x92, 0xd7, 0x92, 0x90, 0xd8, 0x90, 0xd8, 0x6d,
- 0x92, 0x6d, 0x92, 0x27, 0x6e, 0x27, 0x6e, 0x6d, 0x28, 0x6d, 0x28, 0x90, 0x6e,
- 0x90, 0x6e, 0xd7, 0x80, 0xff, 0x5f, 0xfb, 0x5f, 0xfb,
+ 0x5f, 0xfb, 0x40, 0xee, 0x25, 0xda, 0x11, 0xbf, 0x4, 0xa0, 0x0, 0x80, 0x4, 0x5f, 0x11, 0x40,
+ 0x25, 0x25, 0x40, 0x11, 0x5f, 0x4, 0x7f, 0x0, 0xa0, 0x4, 0xbf, 0x11, 0xda, 0x25, 0xee, 0x40,
+ 0xfb, 0x5f, 0xff, 0x7f, 0xfb, 0xa0, 0xee, 0xbf, 0xda, 0xda, 0xbf, 0xee, 0xa0, 0xfb, 0x80, 0xff,
+ 0x6e, 0xd7, 0x92, 0xd7, 0x92, 0x90, 0xd8, 0x90, 0xd8, 0x6d, 0x92, 0x6d, 0x92, 0x27, 0x6e, 0x27,
+ 0x6e, 0x6d, 0x28, 0x6d, 0x28, 0x90, 0x6e, 0x90, 0x6e, 0xd7, 0x80, 0xff, 0x5f, 0xfb, 0x5f, 0xfb,
};
typedef struct GizmoExtrudeGroup {
- /* XYZ & normal. */
- wmGizmo *invoke_xyz_no[4];
- /* Constrained & unconstrained (arrow & circle). */
- wmGizmo *adjust[2];
- int adjust_axis;
-
- /* Copied from the transform operator,
- * use to redo with the same settings. */
- struct {
- float orient_matrix[3][3];
- bool constraint_axis[3];
- float value[4];
- } redo_xform;
-
- /* Depends on object type. */
- int normal_axis;
-
- struct {
- float normal_mat3[3][3]; /* use Z axis for normal. */
- int orientation_type;
- } data;
-
- wmOperatorType *ot_extrude;
- PropertyRNA *gzgt_axis_type_prop;
+ /* XYZ & normal. */
+ wmGizmo *invoke_xyz_no[4];
+ /* Constrained & unconstrained (arrow & circle). */
+ wmGizmo *adjust[2];
+ int adjust_axis;
+
+ /* Copied from the transform operator,
+ * use to redo with the same settings. */
+ struct {
+ float orient_matrix[3][3];
+ bool constraint_axis[3];
+ float value[4];
+ } redo_xform;
+
+ /* Depends on object type. */
+ int normal_axis;
+
+ struct {
+ float normal_mat3[3][3]; /* use Z axis for normal. */
+ int orientation_type;
+ } data;
+
+ wmOperatorType *ot_extrude;
+ PropertyRNA *gzgt_axis_type_prop;
} GizmoExtrudeGroup;
-static void gizmo_mesh_extrude_orientation_matrix_set(
- struct GizmoExtrudeGroup *ggd, const float mat[3][3])
+static void gizmo_mesh_extrude_orientation_matrix_set(struct GizmoExtrudeGroup *ggd,
+ const float mat[3][3])
{
- for (int i = 0; i < 3; i++) {
- mul_v3_v3fl(
- ggd->invoke_xyz_no[i]->matrix_offset[3],
- mat[i],
- (extrude_arrow_xyz_axis_scale * extrude_button_offset_scale) / extrude_button_scale);
- }
+ for (int i = 0; i < 3; i++) {
+ mul_v3_v3fl(ggd->invoke_xyz_no[i]->matrix_offset[3],
+ mat[i],
+ (extrude_arrow_xyz_axis_scale * extrude_button_offset_scale) /
+ extrude_button_scale);
+ }
}
-static void gizmo_mesh_extrude_orientation_matrix_set_for_adjust(
- struct GizmoExtrudeGroup *ggd, const float mat[3][3])
+static void gizmo_mesh_extrude_orientation_matrix_set_for_adjust(struct GizmoExtrudeGroup *ggd,
+ const float mat[3][3])
{
- /* Set orientation without location. */
- for (int j = 0; j < 3; j++) {
- copy_v3_v3(ggd->adjust[0]->matrix_basis[j], mat[j]);
- }
- /* nop when (i == 2). */
- swap_v3_v3(ggd->adjust[0]->matrix_basis[ggd->adjust_axis], ggd->adjust[0]->matrix_basis[2]);
+ /* Set orientation without location. */
+ for (int j = 0; j < 3; j++) {
+ copy_v3_v3(ggd->adjust[0]->matrix_basis[j], mat[j]);
+ }
+ /* nop when (i == 2). */
+ swap_v3_v3(ggd->adjust[0]->matrix_basis[ggd->adjust_axis], ggd->adjust[0]->matrix_basis[2]);
}
static void gizmo_mesh_extrude_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct GizmoExtrudeGroup *ggd = MEM_callocN(sizeof(GizmoExtrudeGroup), __func__);
- gzgroup->customdata = ggd;
-
- const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
- const wmGizmoType *gzt_move = WM_gizmotype_find("GIZMO_GT_button_2d", true);
- const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true);
-
- ggd->adjust[0] = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
- ggd->adjust[1] = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL);
- for (int i = 0; i < 4; i++) {
- ggd->invoke_xyz_no[i] = WM_gizmo_new_ptr(gzt_move, gzgroup, NULL);
- ggd->invoke_xyz_no[i]->flag |= WM_GIZMO_DRAW_OFFSET_SCALE;
- }
-
- {
- PropertyRNA *prop = RNA_struct_find_property(ggd->invoke_xyz_no[3]->ptr, "shape");
- for (int i = 0; i < 4; i++) {
- RNA_property_string_set_bytes(
- ggd->invoke_xyz_no[i]->ptr, prop,
- (const char *)shape_plus, ARRAY_SIZE(shape_plus));
- }
- }
-
- {
- const char *op_idname = NULL;
- /* grease pencil does not use obedit */
- /* GPXX: Remove if OB_MODE_EDIT_GPENCIL is merged with OB_MODE_EDIT */
- const Object *obact = CTX_data_active_object(C);
- if (obact->type == OB_GPENCIL) {
- op_idname = "GPENCIL_OT_extrude_move";
- }
- else if (obact->type == OB_MESH) {
- op_idname = "MESH_OT_extrude_context_move";
- ggd->normal_axis = 2;
- }
- else if (obact->type == OB_ARMATURE) {
- op_idname = "ARMATURE_OT_extrude_move";
- ggd->normal_axis = 1;
- }
- else if (obact->type == OB_CURVE) {
- op_idname = "CURVE_OT_extrude_move";
- ggd->normal_axis = 2;
- }
- else {
- BLI_assert(0);
- }
- ggd->ot_extrude = WM_operatortype_find(op_idname, true);
- ggd->gzgt_axis_type_prop = RNA_struct_type_find_property(gzgroup->type->srna, "axis_type");
- }
-
- for (int i = 0; i < 3; i++) {
- UI_GetThemeColor3fv(TH_AXIS_X + i, ggd->invoke_xyz_no[i]->color);
- }
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, ggd->invoke_xyz_no[3]->color);
- for (int i = 0; i < 2; i++) {
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, ggd->adjust[i]->color);
- }
-
- for (int i = 0; i < 4; i++) {
- WM_gizmo_set_scale(ggd->invoke_xyz_no[i], extrude_button_scale);
- }
- WM_gizmo_set_scale(ggd->adjust[0], extrude_arrow_scale);
- WM_gizmo_set_scale(ggd->adjust[1], extrude_dial_scale);
- ggd->adjust[1]->line_width = 2.0f;
-
- /* XYZ & normal axis extrude. */
- for (int i = 0; i < 4; i++) {
- PointerRNA *ptr = WM_gizmo_operator_set(ggd->invoke_xyz_no[i], 0, ggd->ot_extrude, NULL);
- {
- bool constraint[3] = {0, 0, 0};
- constraint[(i < 3) ? i : ggd->normal_axis] = true;
- PointerRNA macroptr = RNA_pointer_get(ptr, "TRANSFORM_OT_translate");
- RNA_boolean_set(&macroptr, "release_confirm", true);
- RNA_boolean_set_array(&macroptr, "constraint_axis", constraint);
- }
- }
-
- /* Adjust extrude. */
- for (int i = 0; i < 2; i++) {
- wmGizmo *gz = ggd->adjust[i];
- PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ggd->ot_extrude, NULL);
- PointerRNA macroptr = RNA_pointer_get(ptr, "TRANSFORM_OT_translate");
- RNA_boolean_set(&macroptr, "release_confirm", true);
- wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
- gzop->is_redo = true;
- }
+ struct GizmoExtrudeGroup *ggd = MEM_callocN(sizeof(GizmoExtrudeGroup), __func__);
+ gzgroup->customdata = ggd;
+
+ const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
+ const wmGizmoType *gzt_move = WM_gizmotype_find("GIZMO_GT_button_2d", true);
+ const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true);
+
+ ggd->adjust[0] = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ ggd->adjust[1] = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL);
+ for (int i = 0; i < 4; i++) {
+ ggd->invoke_xyz_no[i] = WM_gizmo_new_ptr(gzt_move, gzgroup, NULL);
+ ggd->invoke_xyz_no[i]->flag |= WM_GIZMO_DRAW_OFFSET_SCALE;
+ }
+
+ {
+ PropertyRNA *prop = RNA_struct_find_property(ggd->invoke_xyz_no[3]->ptr, "shape");
+ for (int i = 0; i < 4; i++) {
+ RNA_property_string_set_bytes(
+ ggd->invoke_xyz_no[i]->ptr, prop, (const char *)shape_plus, ARRAY_SIZE(shape_plus));
+ }
+ }
+
+ {
+ const char *op_idname = NULL;
+ /* grease pencil does not use obedit */
+ /* GPXX: Remove if OB_MODE_EDIT_GPENCIL is merged with OB_MODE_EDIT */
+ const Object *obact = CTX_data_active_object(C);
+ if (obact->type == OB_GPENCIL) {
+ op_idname = "GPENCIL_OT_extrude_move";
+ }
+ else if (obact->type == OB_MESH) {
+ op_idname = "MESH_OT_extrude_context_move";
+ ggd->normal_axis = 2;
+ }
+ else if (obact->type == OB_ARMATURE) {
+ op_idname = "ARMATURE_OT_extrude_move";
+ ggd->normal_axis = 1;
+ }
+ else if (obact->type == OB_CURVE) {
+ op_idname = "CURVE_OT_extrude_move";
+ ggd->normal_axis = 2;
+ }
+ else {
+ BLI_assert(0);
+ }
+ ggd->ot_extrude = WM_operatortype_find(op_idname, true);
+ ggd->gzgt_axis_type_prop = RNA_struct_type_find_property(gzgroup->type->srna, "axis_type");
+ }
+
+ for (int i = 0; i < 3; i++) {
+ UI_GetThemeColor3fv(TH_AXIS_X + i, ggd->invoke_xyz_no[i]->color);
+ }
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, ggd->invoke_xyz_no[3]->color);
+ for (int i = 0; i < 2; i++) {
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, ggd->adjust[i]->color);
+ }
+
+ for (int i = 0; i < 4; i++) {
+ WM_gizmo_set_scale(ggd->invoke_xyz_no[i], extrude_button_scale);
+ }
+ WM_gizmo_set_scale(ggd->adjust[0], extrude_arrow_scale);
+ WM_gizmo_set_scale(ggd->adjust[1], extrude_dial_scale);
+ ggd->adjust[1]->line_width = 2.0f;
+
+ /* XYZ & normal axis extrude. */
+ for (int i = 0; i < 4; i++) {
+ PointerRNA *ptr = WM_gizmo_operator_set(ggd->invoke_xyz_no[i], 0, ggd->ot_extrude, NULL);
+ {
+ bool constraint[3] = {0, 0, 0};
+ constraint[(i < 3) ? i : ggd->normal_axis] = true;
+ PointerRNA macroptr = RNA_pointer_get(ptr, "TRANSFORM_OT_translate");
+ RNA_boolean_set(&macroptr, "release_confirm", true);
+ RNA_boolean_set_array(&macroptr, "constraint_axis", constraint);
+ }
+ }
+
+ /* Adjust extrude. */
+ for (int i = 0; i < 2; i++) {
+ wmGizmo *gz = ggd->adjust[i];
+ PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ggd->ot_extrude, NULL);
+ PointerRNA macroptr = RNA_pointer_get(ptr, "TRANSFORM_OT_translate");
+ RNA_boolean_set(&macroptr, "release_confirm", true);
+ wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
+ gzop->is_redo = true;
+ }
}
static void gizmo_mesh_extrude_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoExtrudeGroup *ggd = gzgroup->customdata;
-
- for (int i = 0; i < 4; i++) {
- WM_gizmo_set_flag(ggd->invoke_xyz_no[i], WM_GIZMO_HIDDEN, true);
- }
- for (int i = 0; i < 2; i++) {
- WM_gizmo_set_flag(ggd->adjust[i], WM_GIZMO_HIDDEN, true);
- }
-
- if (G.moving) {
- return;
- }
-
- Scene *scene = CTX_data_scene(C);
-
- int axis_type;
- {
- PointerRNA ptr;
- bToolRef *tref = WM_toolsystem_ref_from_context((bContext *)C);
- WM_toolsystem_ref_properties_ensure_from_gizmo_group(tref, gzgroup->type, &ptr);
- axis_type = RNA_property_enum_get(&ptr, ggd->gzgt_axis_type_prop);
- }
-
- ggd->data.orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
- const bool use_normal = (
- (ggd->data.orientation_type != V3D_ORIENT_NORMAL) ||
- (axis_type == EXTRUDE_AXIS_NORMAL));
- const int axis_len_used = use_normal ? 4 : 3;
-
- struct TransformBounds tbounds;
-
- if (use_normal) {
- struct TransformBounds tbounds_normal;
- if (!ED_transform_calc_gizmo_stats(
- C, &(struct TransformCalcParams){
- .orientation_type = V3D_ORIENT_NORMAL + 1,
- }, &tbounds_normal))
- {
- unit_m3(tbounds_normal.axis);
- }
- copy_m3_m3(ggd->data.normal_mat3, tbounds_normal.axis);
- }
-
- /* TODO(campbell): run second since this modifies the 3D view, it should not. */
- if (!ED_transform_calc_gizmo_stats(
- C, &(struct TransformCalcParams){
- .orientation_type = ggd->data.orientation_type + 1,
- }, &tbounds))
- {
- return;
- }
-
- /* Main axis is normal. */
- if (!use_normal) {
- copy_m3_m3(ggd->data.normal_mat3, tbounds.axis);
- }
-
- /* Offset the add icon. */
- mul_v3_v3fl(
- ggd->invoke_xyz_no[3]->matrix_offset[3],
- ggd->data.normal_mat3[ggd->normal_axis],
- (extrude_arrow_normal_axis_scale * extrude_button_offset_scale) / extrude_button_scale);
-
- /* Adjust current operator. */
- /* Don't use 'WM_operator_last_redo' because selection actions will be ignored. */
- wmOperator *op = CTX_wm_manager(C)->operators.last;
- bool has_redo = (op && op->type == ggd->ot_extrude);
- wmOperator *op_xform = has_redo ? op->macro.last : NULL;
-
- bool adjust_is_flip = false;
- wmGizmo *gz_adjust = NULL;
-
- if (has_redo) {
- gz_adjust = ggd->adjust[1];
- /* We can't access this from 'ot->last_properties'
- * because some properties use skip-save. */
- RNA_float_get_array(op_xform->ptr, "orient_matrix", &ggd->redo_xform.orient_matrix[0][0]);
- RNA_boolean_get_array(op_xform->ptr, "constraint_axis", ggd->redo_xform.constraint_axis);
- RNA_float_get_array(op_xform->ptr, "value", ggd->redo_xform.value);
-
- /* Set properties for redo. */
- for (int i = 0; i < 3; i++) {
- if (ggd->redo_xform.constraint_axis[i]) {
- adjust_is_flip = ggd->redo_xform.value[i] < 0.0f;
- ggd->adjust_axis = i;
- gz_adjust = ggd->adjust[0];
- break;
- }
- }
- }
-
- /* Needed for normal orientation. */
- gizmo_mesh_extrude_orientation_matrix_set(ggd, tbounds.axis);
-
- /* Location. */
- for (int i = 0; i < axis_len_used; i++) {
- WM_gizmo_set_matrix_location(ggd->invoke_xyz_no[i], tbounds.center);
- }
- /* Un-hide. */
- for (int i = 0; i < axis_len_used; i++) {
- WM_gizmo_set_flag(ggd->invoke_xyz_no[i], WM_GIZMO_HIDDEN, false);
- }
-
- if (has_redo) {
- if (gz_adjust == ggd->adjust[0]) {
- gizmo_mesh_extrude_orientation_matrix_set_for_adjust(ggd, ggd->redo_xform.orient_matrix);
- if (adjust_is_flip) {
- negate_v3(ggd->adjust[0]->matrix_basis[2]);
- }
- }
- WM_gizmo_set_matrix_location(gz_adjust, tbounds.center);
- WM_gizmo_set_flag(gz_adjust, WM_GIZMO_HIDDEN, false);
- }
-
- /* Redo with current settings. */
- if (has_redo) {
- for (int i = 0; i < 4; i++) {
- RNA_enum_set(
- ggd->invoke_xyz_no[i]->ptr,
- "draw_options",
- ((gz_adjust == ggd->adjust[0]) &&
- dot_v3v3(ggd->adjust[0]->matrix_basis[2],
- ggd->invoke_xyz_no[i]->matrix_offset[3]) > 0.98f) ? 0 : ED_GIZMO_BUTTON_SHOW_HELPLINE);
- }
- }
- else {
- for (int i = 0; i < 4; i++) {
- RNA_enum_set(ggd->invoke_xyz_no[i]->ptr, "draw_options", ED_GIZMO_BUTTON_SHOW_HELPLINE);
- }
- }
-
- /* TODO: skip calculating axis which wont be used (above). */
- switch (axis_type) {
- case EXTRUDE_AXIS_NORMAL:
- for (int i = 0; i < 3; i++) {
- WM_gizmo_set_flag(ggd->invoke_xyz_no[i], WM_GIZMO_HIDDEN, true);
- }
- break;
- case EXTRUDE_AXIS_XYZ:
- WM_gizmo_set_flag(ggd->invoke_xyz_no[3], WM_GIZMO_HIDDEN, true);
- break;
- }
+ GizmoExtrudeGroup *ggd = gzgroup->customdata;
+
+ for (int i = 0; i < 4; i++) {
+ WM_gizmo_set_flag(ggd->invoke_xyz_no[i], WM_GIZMO_HIDDEN, true);
+ }
+ for (int i = 0; i < 2; i++) {
+ WM_gizmo_set_flag(ggd->adjust[i], WM_GIZMO_HIDDEN, true);
+ }
+
+ if (G.moving) {
+ return;
+ }
+
+ Scene *scene = CTX_data_scene(C);
+
+ int axis_type;
+ {
+ PointerRNA ptr;
+ bToolRef *tref = WM_toolsystem_ref_from_context((bContext *)C);
+ WM_toolsystem_ref_properties_ensure_from_gizmo_group(tref, gzgroup->type, &ptr);
+ axis_type = RNA_property_enum_get(&ptr, ggd->gzgt_axis_type_prop);
+ }
+
+ ggd->data.orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
+ const bool use_normal = ((ggd->data.orientation_type != V3D_ORIENT_NORMAL) ||
+ (axis_type == EXTRUDE_AXIS_NORMAL));
+ const int axis_len_used = use_normal ? 4 : 3;
+
+ struct TransformBounds tbounds;
+
+ if (use_normal) {
+ struct TransformBounds tbounds_normal;
+ if (!ED_transform_calc_gizmo_stats(C,
+ &(struct TransformCalcParams){
+ .orientation_type = V3D_ORIENT_NORMAL + 1,
+ },
+ &tbounds_normal)) {
+ unit_m3(tbounds_normal.axis);
+ }
+ copy_m3_m3(ggd->data.normal_mat3, tbounds_normal.axis);
+ }
+
+ /* TODO(campbell): run second since this modifies the 3D view, it should not. */
+ if (!ED_transform_calc_gizmo_stats(C,
+ &(struct TransformCalcParams){
+ .orientation_type = ggd->data.orientation_type + 1,
+ },
+ &tbounds)) {
+ return;
+ }
+
+ /* Main axis is normal. */
+ if (!use_normal) {
+ copy_m3_m3(ggd->data.normal_mat3, tbounds.axis);
+ }
+
+ /* Offset the add icon. */
+ mul_v3_v3fl(ggd->invoke_xyz_no[3]->matrix_offset[3],
+ ggd->data.normal_mat3[ggd->normal_axis],
+ (extrude_arrow_normal_axis_scale * extrude_button_offset_scale) /
+ extrude_button_scale);
+
+ /* Adjust current operator. */
+ /* Don't use 'WM_operator_last_redo' because selection actions will be ignored. */
+ wmOperator *op = CTX_wm_manager(C)->operators.last;
+ bool has_redo = (op && op->type == ggd->ot_extrude);
+ wmOperator *op_xform = has_redo ? op->macro.last : NULL;
+
+ bool adjust_is_flip = false;
+ wmGizmo *gz_adjust = NULL;
+
+ if (has_redo) {
+ gz_adjust = ggd->adjust[1];
+ /* We can't access this from 'ot->last_properties'
+ * because some properties use skip-save. */
+ RNA_float_get_array(op_xform->ptr, "orient_matrix", &ggd->redo_xform.orient_matrix[0][0]);
+ RNA_boolean_get_array(op_xform->ptr, "constraint_axis", ggd->redo_xform.constraint_axis);
+ RNA_float_get_array(op_xform->ptr, "value", ggd->redo_xform.value);
+
+ /* Set properties for redo. */
+ for (int i = 0; i < 3; i++) {
+ if (ggd->redo_xform.constraint_axis[i]) {
+ adjust_is_flip = ggd->redo_xform.value[i] < 0.0f;
+ ggd->adjust_axis = i;
+ gz_adjust = ggd->adjust[0];
+ break;
+ }
+ }
+ }
+
+ /* Needed for normal orientation. */
+ gizmo_mesh_extrude_orientation_matrix_set(ggd, tbounds.axis);
+
+ /* Location. */
+ for (int i = 0; i < axis_len_used; i++) {
+ WM_gizmo_set_matrix_location(ggd->invoke_xyz_no[i], tbounds.center);
+ }
+ /* Un-hide. */
+ for (int i = 0; i < axis_len_used; i++) {
+ WM_gizmo_set_flag(ggd->invoke_xyz_no[i], WM_GIZMO_HIDDEN, false);
+ }
+
+ if (has_redo) {
+ if (gz_adjust == ggd->adjust[0]) {
+ gizmo_mesh_extrude_orientation_matrix_set_for_adjust(ggd, ggd->redo_xform.orient_matrix);
+ if (adjust_is_flip) {
+ negate_v3(ggd->adjust[0]->matrix_basis[2]);
+ }
+ }
+ WM_gizmo_set_matrix_location(gz_adjust, tbounds.center);
+ WM_gizmo_set_flag(gz_adjust, WM_GIZMO_HIDDEN, false);
+ }
+
+ /* Redo with current settings. */
+ if (has_redo) {
+ for (int i = 0; i < 4; i++) {
+ RNA_enum_set(ggd->invoke_xyz_no[i]->ptr,
+ "draw_options",
+ ((gz_adjust == ggd->adjust[0]) &&
+ dot_v3v3(ggd->adjust[0]->matrix_basis[2],
+ ggd->invoke_xyz_no[i]->matrix_offset[3]) > 0.98f) ?
+ 0 :
+ ED_GIZMO_BUTTON_SHOW_HELPLINE);
+ }
+ }
+ else {
+ for (int i = 0; i < 4; i++) {
+ RNA_enum_set(ggd->invoke_xyz_no[i]->ptr, "draw_options", ED_GIZMO_BUTTON_SHOW_HELPLINE);
+ }
+ }
+
+ /* TODO: skip calculating axis which wont be used (above). */
+ switch (axis_type) {
+ case EXTRUDE_AXIS_NORMAL:
+ for (int i = 0; i < 3; i++) {
+ WM_gizmo_set_flag(ggd->invoke_xyz_no[i], WM_GIZMO_HIDDEN, true);
+ }
+ break;
+ case EXTRUDE_AXIS_XYZ:
+ WM_gizmo_set_flag(ggd->invoke_xyz_no[3], WM_GIZMO_HIDDEN, true);
+ break;
+ }
}
static void gizmo_mesh_extrude_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoExtrudeGroup *ggd = gzgroup->customdata;
- switch (ggd->data.orientation_type) {
- case V3D_ORIENT_VIEW:
- {
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- float mat[3][3];
- copy_m3_m4(mat, rv3d->viewinv);
- normalize_m3(mat);
- gizmo_mesh_extrude_orientation_matrix_set(ggd, mat);
- break;
- }
- }
-
- /* Basic ordering for drawing only. */
- {
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
- gz->temp.f = dot_v3v3(rv3d->viewinv[2], gz->matrix_offset[3]);
- }
- BLI_listbase_sort(&gzgroup->gizmos, WM_gizmo_cmp_temp_fl_reverse);
-
- if ((ggd->adjust[1]->flag & WM_GIZMO_HIDDEN) == 0) {
- copy_v3_v3(ggd->adjust[1]->matrix_basis[0], rv3d->viewinv[0]);
- copy_v3_v3(ggd->adjust[1]->matrix_basis[1], rv3d->viewinv[1]);
- copy_v3_v3(ggd->adjust[1]->matrix_basis[2], rv3d->viewinv[2]);
- }
- }
+ GizmoExtrudeGroup *ggd = gzgroup->customdata;
+ switch (ggd->data.orientation_type) {
+ case V3D_ORIENT_VIEW: {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float mat[3][3];
+ copy_m3_m4(mat, rv3d->viewinv);
+ normalize_m3(mat);
+ gizmo_mesh_extrude_orientation_matrix_set(ggd, mat);
+ break;
+ }
+ }
+
+ /* Basic ordering for drawing only. */
+ {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
+ gz->temp.f = dot_v3v3(rv3d->viewinv[2], gz->matrix_offset[3]);
+ }
+ BLI_listbase_sort(&gzgroup->gizmos, WM_gizmo_cmp_temp_fl_reverse);
+
+ if ((ggd->adjust[1]->flag & WM_GIZMO_HIDDEN) == 0) {
+ copy_v3_v3(ggd->adjust[1]->matrix_basis[0], rv3d->viewinv[0]);
+ copy_v3_v3(ggd->adjust[1]->matrix_basis[1], rv3d->viewinv[1]);
+ copy_v3_v3(ggd->adjust[1]->matrix_basis[2], rv3d->viewinv[2]);
+ }
+ }
}
-static void gizmo_mesh_extrude_invoke_prepare(const bContext *UNUSED(C), wmGizmoGroup *gzgroup, wmGizmo *gz)
+static void gizmo_mesh_extrude_invoke_prepare(const bContext *UNUSED(C),
+ wmGizmoGroup *gzgroup,
+ wmGizmo *gz)
{
- GizmoExtrudeGroup *ggd = gzgroup->customdata;
- if (ELEM(gz, ggd->adjust[0], ggd->adjust[1])) {
- /* Set properties for redo. */
- wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
- PointerRNA macroptr = RNA_pointer_get(&gzop->ptr, "TRANSFORM_OT_translate");
- if (gz == ggd->adjust[0]) {
- RNA_boolean_set_array(&macroptr, "constraint_axis", ggd->redo_xform.constraint_axis);
- RNA_float_set_array(&macroptr, "orient_matrix", &ggd->redo_xform.orient_matrix[0][0]);
- RNA_enum_set(&macroptr, "orient_type", V3D_ORIENT_NORMAL);
- }
- RNA_float_set_array(&macroptr, "value", ggd->redo_xform.value);
- }
- else {
- /* Workaround for extrude action modifying normals. */
- const int i = BLI_array_findindex(ggd->invoke_xyz_no, ARRAY_SIZE(ggd->invoke_xyz_no), &gz);
- BLI_assert(i != -1);
- bool use_normal_matrix = false;
- if (i == 3) {
- use_normal_matrix = true;
- }
- else if (ggd->data.orientation_type == V3D_ORIENT_NORMAL) {
- use_normal_matrix = true;
- }
- if (use_normal_matrix) {
- wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
- PointerRNA macroptr = RNA_pointer_get(&gzop->ptr, "TRANSFORM_OT_translate");
- RNA_float_set_array(&macroptr, "orient_matrix", &ggd->data.normal_mat3[0][0]);
- RNA_enum_set(&macroptr, "orient_type", V3D_ORIENT_NORMAL);
- }
- }
+ GizmoExtrudeGroup *ggd = gzgroup->customdata;
+ if (ELEM(gz, ggd->adjust[0], ggd->adjust[1])) {
+ /* Set properties for redo. */
+ wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
+ PointerRNA macroptr = RNA_pointer_get(&gzop->ptr, "TRANSFORM_OT_translate");
+ if (gz == ggd->adjust[0]) {
+ RNA_boolean_set_array(&macroptr, "constraint_axis", ggd->redo_xform.constraint_axis);
+ RNA_float_set_array(&macroptr, "orient_matrix", &ggd->redo_xform.orient_matrix[0][0]);
+ RNA_enum_set(&macroptr, "orient_type", V3D_ORIENT_NORMAL);
+ }
+ RNA_float_set_array(&macroptr, "value", ggd->redo_xform.value);
+ }
+ else {
+ /* Workaround for extrude action modifying normals. */
+ const int i = BLI_array_findindex(ggd->invoke_xyz_no, ARRAY_SIZE(ggd->invoke_xyz_no), &gz);
+ BLI_assert(i != -1);
+ bool use_normal_matrix = false;
+ if (i == 3) {
+ use_normal_matrix = true;
+ }
+ else if (ggd->data.orientation_type == V3D_ORIENT_NORMAL) {
+ use_normal_matrix = true;
+ }
+ if (use_normal_matrix) {
+ wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
+ PointerRNA macroptr = RNA_pointer_get(&gzop->ptr, "TRANSFORM_OT_translate");
+ RNA_float_set_array(&macroptr, "orient_matrix", &ggd->data.normal_mat3[0][0]);
+ RNA_enum_set(&macroptr, "orient_type", V3D_ORIENT_NORMAL);
+ }
+ }
}
-static void gizmo_mesh_extrude_message_subscribe(
- const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus)
+static void gizmo_mesh_extrude_message_subscribe(const bContext *C,
+ wmGizmoGroup *gzgroup,
+ struct wmMsgBus *mbus)
{
- GizmoExtrudeGroup *ggd = gzgroup->customdata;
- ARegion *ar = CTX_wm_region(C);
-
- /* Subscribe to view properties */
- wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
- .owner = ar,
- .user_data = gzgroup->parent_gzmap,
- .notify = WM_gizmo_do_msg_notify_tag_refresh,
- };
-
- {
- WM_msg_subscribe_rna_anon_prop(mbus, TransformOrientationSlot, type, &msg_sub_value_gz_tag_refresh);
- }
-
-
- WM_msg_subscribe_rna_params(
- mbus,
- &(const wmMsgParams_RNA){
- .ptr = (PointerRNA){ .type = gzgroup->type->srna, },
- .prop = ggd->gzgt_axis_type_prop,
- },
- &msg_sub_value_gz_tag_refresh, __func__);
+ GizmoExtrudeGroup *ggd = gzgroup->customdata;
+ ARegion *ar = CTX_wm_region(C);
+
+ /* Subscribe to view properties */
+ wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
+ .owner = ar,
+ .user_data = gzgroup->parent_gzmap,
+ .notify = WM_gizmo_do_msg_notify_tag_refresh,
+ };
+
+ {
+ WM_msg_subscribe_rna_anon_prop(
+ mbus, TransformOrientationSlot, type, &msg_sub_value_gz_tag_refresh);
+ }
+
+ WM_msg_subscribe_rna_params(mbus,
+ &(const wmMsgParams_RNA){
+ .ptr =
+ (PointerRNA){
+ .type = gzgroup->type->srna,
+ },
+ .prop = ggd->gzgt_axis_type_prop,
+ },
+ &msg_sub_value_gz_tag_refresh,
+ __func__);
}
void VIEW3D_GGT_xform_extrude(struct wmGizmoGroupType *gzgt)
{
- gzgt->name = "3D View Extrude";
- gzgt->idname = "VIEW3D_GGT_xform_extrude";
-
- gzgt->flag = WM_GIZMOGROUPTYPE_3D;
-
- gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
- gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
-
- gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool;
- gzgt->setup = gizmo_mesh_extrude_setup;
- gzgt->refresh = gizmo_mesh_extrude_refresh;
- gzgt->draw_prepare = gizmo_mesh_extrude_draw_prepare;
- gzgt->invoke_prepare = gizmo_mesh_extrude_invoke_prepare;
- gzgt->message_subscribe = gizmo_mesh_extrude_message_subscribe;
-
- static const EnumPropertyItem axis_type_items[] = {
- {EXTRUDE_AXIS_NORMAL, "NORMAL", 0, "Regular", "Only show normal axis"},
- {EXTRUDE_AXIS_XYZ, "XYZ", 0, "XYZ", "Follow scene orientation"},
- {0, NULL, 0, NULL, NULL},
- };
- RNA_def_enum(gzgt->srna, "axis_type", axis_type_items, 0, "Axis Type", "");
+ gzgt->name = "3D View Extrude";
+ gzgt->idname = "VIEW3D_GGT_xform_extrude";
+
+ gzgt->flag = WM_GIZMOGROUPTYPE_3D;
+
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+
+ gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool;
+ gzgt->setup = gizmo_mesh_extrude_setup;
+ gzgt->refresh = gizmo_mesh_extrude_refresh;
+ gzgt->draw_prepare = gizmo_mesh_extrude_draw_prepare;
+ gzgt->invoke_prepare = gizmo_mesh_extrude_invoke_prepare;
+ gzgt->message_subscribe = gizmo_mesh_extrude_message_subscribe;
+
+ static const EnumPropertyItem axis_type_items[] = {
+ {EXTRUDE_AXIS_NORMAL, "NORMAL", 0, "Regular", "Only show normal axis"},
+ {EXTRUDE_AXIS_XYZ, "XYZ", 0, "XYZ", "Follow scene orientation"},
+ {0, NULL, 0, NULL, NULL},
+ };
+ RNA_def_enum(gzgt->srna, "axis_type", axis_type_items, 0, "Axis Type", "");
}
/** \} */
diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c
index b03d50e11e7..46f6e576cf4 100644
--- a/source/blender/editors/transform/transform_input.c
+++ b/source/blender/editors/transform/transform_input.c
@@ -18,7 +18,6 @@
* \ingroup edtransform
*/
-
#include <stdlib.h>
#include <math.h>
@@ -40,426 +39,454 @@
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]);
+ convertViewVec(t, output, mval[0] - mi->imval[0], mval[1] - mi->imval[1]);
}
-static void InputSpring(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2], float output[3])
+static void InputSpring(TransInfo *UNUSED(t),
+ MouseInput *mi,
+ const double mval[2],
+ float output[3])
{
- double dx, dy;
- float ratio;
+ double dx, dy;
+ float ratio;
- dx = ((double)mi->center[0] - mval[0]);
- dy = ((double)mi->center[1] - mval[1]);
- ratio = hypot(dx, dy) / (double)mi->factor;
+ dx = ((double)mi->center[0] - mval[0]);
+ dy = ((double)mi->center[1] - mval[1]);
+ ratio = hypot(dx, dy) / (double)mi->factor;
- output[0] = ratio;
+ output[0] = ratio;
}
static void InputSpringFlip(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
- InputSpring(t, mi, mval, output);
-
- /* flip scale */
- /* values can become really big when zoomed in so use longs [#26598] */
- if ((int64_t)((int)mi->center[0] - mval[0]) * (int64_t)((int)mi->center[0] - mi->imval[0]) +
- (int64_t)((int)mi->center[1] - mval[1]) * (int64_t)((int)mi->center[1] - mi->imval[1]) < 0)
- {
- output[0] *= -1.0f;
- }
+ InputSpring(t, mi, mval, output);
+
+ /* flip scale */
+ /* values can become really big when zoomed in so use longs [#26598] */
+ if ((int64_t)((int)mi->center[0] - mval[0]) * (int64_t)((int)mi->center[0] - mi->imval[0]) +
+ (int64_t)((int)mi->center[1] - mval[1]) * (int64_t)((int)mi->center[1] - mi->imval[1]) <
+ 0) {
+ output[0] *= -1.0f;
+ }
}
static void InputSpringDelta(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
- InputSpring(t, mi, mval, output);
- output[0] -= 1.0f;
+ InputSpring(t, mi, mval, output);
+ output[0] -= 1.0f;
}
-static void InputTrackBall(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2], float output[3])
+static void InputTrackBall(TransInfo *UNUSED(t),
+ MouseInput *mi,
+ const double mval[2],
+ float output[3])
{
- output[0] = (float)(mi->imval[1] - mval[1]);
- output[1] = (float)(mval[0] - mi->imval[0]);
+ output[0] = (float)(mi->imval[1] - mval[1]);
+ output[1] = (float)(mval[0] - mi->imval[0]);
- output[0] *= mi->factor;
- output[1] *= mi->factor;
+ output[0] *= mi->factor;
+ output[1] *= mi->factor;
}
-static void InputHorizontalRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
+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->ar ? t->ar->winx : 1;
- output[0] = ((mval[0] - mi->imval[0]) / winx) * 2.0f;
+ output[0] = ((mval[0] - mi->imval[0]) / winx) * 2.0f;
}
-static void InputHorizontalAbsolute(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
+static void InputHorizontalAbsolute(TransInfo *t,
+ MouseInput *mi,
+ const double mval[2],
+ float output[3])
{
- float vec[3];
+ float vec[3];
- InputVector(t, mi, mval, vec);
- project_v3_v3v3(vec, vec, t->viewinv[0]);
+ InputVector(t, mi, mval, vec);
+ project_v3_v3v3(vec, vec, t->viewinv[0]);
- output[0] = dot_v3v3(t->viewinv[0], vec) * 2.0f;
+ output[0] = dot_v3v3(t->viewinv[0], vec) * 2.0f;
}
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->ar ? t->ar->winy : 1;
- output[0] = ((mval[1] - mi->imval[1]) / winy) * 2.0f;
+ output[0] = ((mval[1] - mi->imval[1]) / winy) * 2.0f;
}
-static void InputVerticalAbsolute(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
+static void InputVerticalAbsolute(TransInfo *t,
+ MouseInput *mi,
+ const double mval[2],
+ float output[3])
{
- float vec[3];
+ float vec[3];
- InputVector(t, mi, mval, vec);
- project_v3_v3v3(vec, vec, t->viewinv[1]);
+ InputVector(t, mi, mval, vec);
+ project_v3_v3v3(vec, vec, t->viewinv[1]);
- output[0] = dot_v3v3(t->viewinv[1], vec) * 2.0f;
+ 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])
+void setCustomPoints(TransInfo *UNUSED(t),
+ MouseInput *mi,
+ const int mval_start[2],
+ const int mval_end[2])
{
- int *data;
+ int *data;
- mi->data = MEM_reallocN(mi->data, sizeof(int) * 4);
+ mi->data = MEM_reallocN(mi->data, sizeof(int) * 4);
- data = mi->data;
+ data = mi->data;
- data[0] = mval_start[0];
- data[1] = mval_start[1];
- data[2] = mval_end[0];
- data[3] = mval_end[1];
+ 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);
+ 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);
}
-static void InputCustomRatioFlip(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2], float output[3])
+static void InputCustomRatioFlip(TransInfo *UNUSED(t),
+ MouseInput *mi,
+ const double mval[2],
+ float output[3])
{
- double length;
- double distance;
- double dx, dy;
- const int *data = mi->data;
+ double length;
+ double distance;
+ double dx, dy;
+ const int *data = mi->data;
- if (data) {
- int mdx, mdy;
- dx = data[2] - data[0];
- dy = data[3] - data[1];
+ if (data) {
+ int mdx, mdy;
+ dx = data[2] - data[0];
+ dy = data[3] - data[1];
- length = hypot(dx, dy);
+ length = hypot(dx, dy);
- mdx = mval[0] - data[2];
- mdy = mval[1] - data[3];
+ mdx = mval[0] - data[2];
+ mdy = mval[1] - data[3];
- distance = (length != 0.0) ? (mdx * dx + mdy * dy) / length : 0.0;
+ distance = (length != 0.0) ? (mdx * dx + mdy * dy) / length : 0.0;
- output[0] = (length != 0.0) ? (double)(distance / length) : 0.0;
- }
+ output[0] = (length != 0.0) ? (double)(distance / length) : 0.0;
+ }
}
static void InputCustomRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
- InputCustomRatioFlip(t, mi, mval, output);
- output[0] = -output[0];
+ InputCustomRatioFlip(t, mi, mval, output);
+ output[0] = -output[0];
}
struct InputAngle_Data {
- double angle;
- double mval_prev[2];
+ double angle;
+ double mval_prev[2];
};
static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2], float output[3])
{
- struct InputAngle_Data *data = mi->data;
- double dx2 = mval[0] - (double)mi->center[0];
- double dy2 = mval[1] - (double)mi->center[1];
- double B = sqrt(dx2 * dx2 + dy2 * dy2);
+ struct InputAngle_Data *data = mi->data;
+ double dx2 = mval[0] - (double)mi->center[0];
+ double dy2 = mval[1] - (double)mi->center[1];
+ double B = sqrt(dx2 * dx2 + dy2 * dy2);
- double dx1 = data->mval_prev[0] - (double)mi->center[0];
- double dy1 = data->mval_prev[1] - (double)mi->center[1];
- double A = sqrt(dx1 * dx1 + dy1 * dy1);
+ double dx1 = data->mval_prev[0] - (double)mi->center[0];
+ double dy1 = data->mval_prev[1] - (double)mi->center[1];
+ double A = sqrt(dx1 * dx1 + dy1 * dy1);
- double dx3 = mval[0] - data->mval_prev[0];
- double dy3 = mval[1] - data->mval_prev[1];
+ double dx3 = mval[0] - data->mval_prev[0];
+ double dy3 = mval[1] - data->mval_prev[1];
- /* use doubles here, to make sure a "1.0" (no rotation)
- * doesn't become 9.999999e-01, which gives 0.02 for acos */
- double deler = (((dx1 * dx1 + dy1 * dy1) +
- (dx2 * dx2 + dy2 * dy2) -
- (dx3 * dx3 + dy3 * dy3)) / (2.0 * (((A * B) != 0.0) ? (A * B) : 1.0)));
- /* ((A * B) ? (A * B) : 1.0) this takes care of potential divide by zero errors */
+ /* use doubles here, to make sure a "1.0" (no rotation)
+ * doesn't become 9.999999e-01, which gives 0.02 for acos */
+ double deler = (((dx1 * dx1 + dy1 * dy1) + (dx2 * dx2 + dy2 * dy2) - (dx3 * dx3 + dy3 * dy3)) /
+ (2.0 * (((A * B) != 0.0) ? (A * B) : 1.0)));
+ /* ((A * B) ? (A * B) : 1.0) this takes care of potential divide by zero errors */
- float dphi;
+ float dphi;
- dphi = saacos((float)deler);
- if ((dx1 * dy2 - dx2 * dy1) > 0.0) dphi = -dphi;
+ dphi = saacos((float)deler);
+ if ((dx1 * dy2 - dx2 * dy1) > 0.0)
+ dphi = -dphi;
- /* If the angle is zero, because of lack of precision close to the 1.0 value in acos
- * approximate the angle with the opposite side of the normalized triangle
- * This is a good approximation here since the smallest acos value seems to be around
- * 0.02 degree and lower values don't even have a 0.01% error compared to the approximation
- */
- if (dphi == 0) {
- double dx, dy;
+ /* If the angle is zero, because of lack of precision close to the 1.0 value in acos
+ * approximate the angle with the opposite side of the normalized triangle
+ * This is a good approximation here since the smallest acos value seems to be around
+ * 0.02 degree and lower values don't even have a 0.01% error compared to the approximation
+ */
+ if (dphi == 0) {
+ double dx, dy;
- dx2 /= A;
- dy2 /= A;
+ dx2 /= A;
+ dy2 /= A;
- dx1 /= B;
- dy1 /= B;
+ dx1 /= B;
+ dy1 /= B;
- dx = dx1 - dx2;
- dy = dy1 - dy2;
+ dx = dx1 - dx2;
+ dy = dy1 - dy2;
- dphi = sqrt(dx * dx + dy * dy);
- if ((dx1 * dy2 - dx2 * dy1) > 0.0) dphi = -dphi;
- }
+ dphi = sqrt(dx * dx + dy * dy);
+ if ((dx1 * dy2 - dx2 * dy1) > 0.0)
+ dphi = -dphi;
+ }
- data->angle += ((double)dphi) * (mi->precision ? (double)mi->precision_factor : 1.0);
+ data->angle += ((double)dphi) * (mi->precision ? (double)mi->precision_factor : 1.0);
- data->mval_prev[0] = mval[0];
- data->mval_prev[1] = mval[1];
+ data->mval_prev[0] = mval[0];
+ data->mval_prev[1] = mval[1];
- output[0] = data->angle;
+ output[0] = data->angle;
}
static void InputAngleSpring(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
- float toutput[3];
+ float toutput[3];
- InputAngle(t, mi, mval, output);
- InputSpring(t, mi, mval, toutput);
+ InputAngle(t, mi, mval, output);
+ InputSpring(t, mi, mval, toutput);
- output[1] = toutput[0];
+ output[1] = toutput[0];
}
-void initMouseInput(TransInfo *UNUSED(t), MouseInput *mi, const float center[2], const int mval[2], const bool precision)
+void initMouseInput(TransInfo *UNUSED(t),
+ MouseInput *mi,
+ const float center[2],
+ const int mval[2],
+ const bool precision)
{
- mi->factor = 0;
- mi->precision = precision;
+ mi->factor = 0;
+ mi->precision = precision;
- mi->center[0] = center[0];
- mi->center[1] = center[1];
+ mi->center[0] = center[0];
+ mi->center[1] = center[1];
- mi->imval[0] = mval[0];
- mi->imval[1] = mval[1];
+ mi->imval[0] = mval[0];
+ mi->imval[1] = mval[1];
- mi->post = NULL;
+ mi->post = NULL;
}
static void calcSpringFactor(MouseInput *mi)
{
- mi->factor = sqrtf(((float)(mi->center[1] - mi->imval[1])) * ((float)(mi->center[1] - mi->imval[1])) +
- ((float)(mi->center[0] - mi->imval[0])) * ((float)(mi->center[0] - mi->imval[0])));
+ mi->factor = sqrtf(
+ ((float)(mi->center[1] - mi->imval[1])) * ((float)(mi->center[1] - mi->imval[1])) +
+ ((float)(mi->center[0] - mi->imval[0])) * ((float)(mi->center[0] - mi->imval[0])));
- if (mi->factor == 0.0f) {
- mi->factor = 1.0f; /* prevent Inf */
- }
+ if (mi->factor == 0.0f) {
+ mi->factor = 1.0f; /* prevent Inf */
+ }
}
void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
{
- /* incase we allocate a new value */
- void *mi_data_prev = mi->data;
-
- mi->use_virtual_mval = true;
- mi->precision_factor = 1.0f / 10.0f;
-
- switch (mode) {
- case INPUT_VECTOR:
- mi->apply = InputVector;
- t->helpline = HLP_NONE;
- break;
- case INPUT_SPRING:
- calcSpringFactor(mi);
- mi->apply = InputSpring;
- t->helpline = HLP_SPRING;
- break;
- case INPUT_SPRING_FLIP:
- calcSpringFactor(mi);
- mi->apply = InputSpringFlip;
- t->helpline = HLP_SPRING;
- break;
- case INPUT_SPRING_DELTA:
- calcSpringFactor(mi);
- mi->apply = InputSpringDelta;
- t->helpline = HLP_SPRING;
- break;
- case INPUT_ANGLE:
- case INPUT_ANGLE_SPRING:
- {
- struct InputAngle_Data *data;
- mi->use_virtual_mval = false;
- mi->precision_factor = 1.0f / 30.0f;
- data = MEM_callocN(sizeof(struct InputAngle_Data), "angle accumulator");
- data->mval_prev[0] = mi->imval[0];
- data->mval_prev[1] = mi->imval[1];
- mi->data = data;
- if (mode == INPUT_ANGLE) {
- mi->apply = InputAngle;
- }
- else {
- calcSpringFactor(mi);
- mi->apply = InputAngleSpring;
- }
- t->helpline = HLP_ANGLE;
- break;
- }
- case INPUT_TRACKBALL:
- mi->precision_factor = 1.0f / 30.0f;
- /* factor has to become setting or so */
- mi->factor = 0.01f;
- mi->apply = InputTrackBall;
- t->helpline = HLP_TRACKBALL;
- break;
- case INPUT_HORIZONTAL_RATIO:
- mi->apply = InputHorizontalRatio;
- t->helpline = HLP_HARROW;
- break;
- case INPUT_HORIZONTAL_ABSOLUTE:
- mi->apply = InputHorizontalAbsolute;
- t->helpline = HLP_HARROW;
- break;
- case INPUT_VERTICAL_RATIO:
- mi->apply = InputVerticalRatio;
- t->helpline = HLP_VARROW;
- break;
- case INPUT_VERTICAL_ABSOLUTE:
- mi->apply = InputVerticalAbsolute;
- t->helpline = HLP_VARROW;
- break;
- case INPUT_CUSTOM_RATIO:
- mi->apply = InputCustomRatio;
- t->helpline = HLP_CARROW;
- break;
- case INPUT_CUSTOM_RATIO_FLIP:
- mi->apply = InputCustomRatioFlip;
- t->helpline = HLP_CARROW;
- break;
- case INPUT_NONE:
- default:
- mi->apply = NULL;
- break;
- }
-
- /* setup for the mouse cursor: either set a custom one,
- * or hide it if it will be drawn with the helpline */
- wmWindow *win = CTX_wm_window(t->context);
- switch (t->helpline) {
- case HLP_NONE:
- /* INPUT_VECTOR, INPUT_CUSTOM_RATIO, INPUT_CUSTOM_RATIO_FLIP */
- if (t->flag & T_MODAL) {
- t->flag |= T_MODAL_CURSOR_SET;
- WM_cursor_modal_set(win, BC_NSEW_SCROLLCURSOR);
- }
- break;
- case HLP_SPRING:
- case HLP_ANGLE:
- case HLP_TRACKBALL:
- case HLP_HARROW:
- case HLP_VARROW:
- case HLP_CARROW:
- if (t->flag & T_MODAL) {
- t->flag |= T_MODAL_CURSOR_SET;
- WM_cursor_modal_set(win, CURSOR_NONE);
- }
- break;
- default:
- break;
- }
-
- /* if we've allocated new data, free the old data
- * less hassle then checking before every alloc above */
- if (mi_data_prev && (mi_data_prev != mi->data)) {
- MEM_freeN(mi_data_prev);
- }
+ /* incase we allocate a new value */
+ void *mi_data_prev = mi->data;
+
+ mi->use_virtual_mval = true;
+ mi->precision_factor = 1.0f / 10.0f;
+
+ switch (mode) {
+ case INPUT_VECTOR:
+ mi->apply = InputVector;
+ t->helpline = HLP_NONE;
+ break;
+ case INPUT_SPRING:
+ calcSpringFactor(mi);
+ mi->apply = InputSpring;
+ t->helpline = HLP_SPRING;
+ break;
+ case INPUT_SPRING_FLIP:
+ calcSpringFactor(mi);
+ mi->apply = InputSpringFlip;
+ t->helpline = HLP_SPRING;
+ break;
+ case INPUT_SPRING_DELTA:
+ calcSpringFactor(mi);
+ mi->apply = InputSpringDelta;
+ t->helpline = HLP_SPRING;
+ break;
+ case INPUT_ANGLE:
+ case INPUT_ANGLE_SPRING: {
+ struct InputAngle_Data *data;
+ mi->use_virtual_mval = false;
+ mi->precision_factor = 1.0f / 30.0f;
+ data = MEM_callocN(sizeof(struct InputAngle_Data), "angle accumulator");
+ data->mval_prev[0] = mi->imval[0];
+ data->mval_prev[1] = mi->imval[1];
+ mi->data = data;
+ if (mode == INPUT_ANGLE) {
+ mi->apply = InputAngle;
+ }
+ else {
+ calcSpringFactor(mi);
+ mi->apply = InputAngleSpring;
+ }
+ t->helpline = HLP_ANGLE;
+ break;
+ }
+ case INPUT_TRACKBALL:
+ mi->precision_factor = 1.0f / 30.0f;
+ /* factor has to become setting or so */
+ mi->factor = 0.01f;
+ mi->apply = InputTrackBall;
+ t->helpline = HLP_TRACKBALL;
+ break;
+ case INPUT_HORIZONTAL_RATIO:
+ mi->apply = InputHorizontalRatio;
+ t->helpline = HLP_HARROW;
+ break;
+ case INPUT_HORIZONTAL_ABSOLUTE:
+ mi->apply = InputHorizontalAbsolute;
+ t->helpline = HLP_HARROW;
+ break;
+ case INPUT_VERTICAL_RATIO:
+ mi->apply = InputVerticalRatio;
+ t->helpline = HLP_VARROW;
+ break;
+ case INPUT_VERTICAL_ABSOLUTE:
+ mi->apply = InputVerticalAbsolute;
+ t->helpline = HLP_VARROW;
+ break;
+ case INPUT_CUSTOM_RATIO:
+ mi->apply = InputCustomRatio;
+ t->helpline = HLP_CARROW;
+ break;
+ case INPUT_CUSTOM_RATIO_FLIP:
+ mi->apply = InputCustomRatioFlip;
+ t->helpline = HLP_CARROW;
+ break;
+ case INPUT_NONE:
+ default:
+ mi->apply = NULL;
+ break;
+ }
+
+ /* setup for the mouse cursor: either set a custom one,
+ * or hide it if it will be drawn with the helpline */
+ wmWindow *win = CTX_wm_window(t->context);
+ switch (t->helpline) {
+ case HLP_NONE:
+ /* INPUT_VECTOR, INPUT_CUSTOM_RATIO, INPUT_CUSTOM_RATIO_FLIP */
+ if (t->flag & T_MODAL) {
+ t->flag |= T_MODAL_CURSOR_SET;
+ WM_cursor_modal_set(win, BC_NSEW_SCROLLCURSOR);
+ }
+ break;
+ case HLP_SPRING:
+ case HLP_ANGLE:
+ case HLP_TRACKBALL:
+ case HLP_HARROW:
+ case HLP_VARROW:
+ case HLP_CARROW:
+ if (t->flag & T_MODAL) {
+ t->flag |= T_MODAL_CURSOR_SET;
+ WM_cursor_modal_set(win, CURSOR_NONE);
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* if we've allocated new data, free the old data
+ * less hassle then checking before every alloc above */
+ if (mi_data_prev && (mi_data_prev != mi->data)) {
+ MEM_freeN(mi_data_prev);
+ }
}
void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3]))
{
- mi->post = post;
+ mi->post = post;
}
void applyMouseInput(TransInfo *t, MouseInput *mi, const int mval[2], float output[3])
{
- double mval_db[2];
-
- if (mi->use_virtual_mval) {
- /* update accumulator */
- double mval_delta[2];
-
- mval_delta[0] = (mval[0] - mi->imval[0]) - mi->virtual_mval.prev[0];
- mval_delta[1] = (mval[1] - mi->imval[1]) - mi->virtual_mval.prev[1];
-
- mi->virtual_mval.prev[0] += mval_delta[0];
- mi->virtual_mval.prev[1] += mval_delta[1];
-
- if (mi->precision) {
- mval_delta[0] *= (double)mi->precision_factor;
- mval_delta[1] *= (double)mi->precision_factor;
- }
-
- mi->virtual_mval.accum[0] += mval_delta[0];
- mi->virtual_mval.accum[1] += mval_delta[1];
-
- mval_db[0] = mi->imval[0] + mi->virtual_mval.accum[0];
- mval_db[1] = mi->imval[1] + mi->virtual_mval.accum[1];
- }
- else {
- mval_db[0] = mval[0];
- mval_db[1] = mval[1];
- }
-
-
- if (mi->apply != NULL) {
- mi->apply(t, mi, mval_db, output);
- }
-
- if (!is_zero_v3(t->values_modal_offset)) {
- float values_ofs[3];
- if (t->con.mode & CON_APPLY) {
- mul_v3_m3v3(values_ofs, t->spacemtx, t->values_modal_offset);
- }
- else {
- copy_v3_v3(values_ofs, t->values_modal_offset);
- }
- add_v3_v3(t->values, values_ofs);
- }
-
- if (mi->post) {
- mi->post(t, output);
- }
+ double mval_db[2];
+
+ if (mi->use_virtual_mval) {
+ /* update accumulator */
+ double mval_delta[2];
+
+ mval_delta[0] = (mval[0] - mi->imval[0]) - mi->virtual_mval.prev[0];
+ mval_delta[1] = (mval[1] - mi->imval[1]) - mi->virtual_mval.prev[1];
+
+ mi->virtual_mval.prev[0] += mval_delta[0];
+ mi->virtual_mval.prev[1] += mval_delta[1];
+
+ if (mi->precision) {
+ mval_delta[0] *= (double)mi->precision_factor;
+ mval_delta[1] *= (double)mi->precision_factor;
+ }
+
+ mi->virtual_mval.accum[0] += mval_delta[0];
+ mi->virtual_mval.accum[1] += mval_delta[1];
+
+ mval_db[0] = mi->imval[0] + mi->virtual_mval.accum[0];
+ mval_db[1] = mi->imval[1] + mi->virtual_mval.accum[1];
+ }
+ else {
+ mval_db[0] = mval[0];
+ mval_db[1] = mval[1];
+ }
+
+ if (mi->apply != NULL) {
+ mi->apply(t, mi, mval_db, output);
+ }
+
+ if (!is_zero_v3(t->values_modal_offset)) {
+ float values_ofs[3];
+ if (t->con.mode & CON_APPLY) {
+ mul_v3_m3v3(values_ofs, t->spacemtx, t->values_modal_offset);
+ }
+ else {
+ copy_v3_v3(values_ofs, t->values_modal_offset);
+ }
+ add_v3_v3(t->values, values_ofs);
+ }
+
+ if (mi->post) {
+ mi->post(t, output);
+ }
}
eRedrawFlag handleMouseInput(TransInfo *t, MouseInput *mi, const wmEvent *event)
{
- eRedrawFlag redraw = TREDRAW_NOTHING;
-
- switch (event->type) {
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
- if (event->val == KM_PRESS) {
- t->modifiers |= MOD_PRECISION;
- /* shift is modifier for higher precision transforn */
- mi->precision = 1;
- redraw = TREDRAW_HARD;
- }
- else if (event->val == KM_RELEASE) {
- t->modifiers &= ~MOD_PRECISION;
- mi->precision = 0;
- redraw = TREDRAW_HARD;
- }
- break;
- }
-
- return redraw;
+ eRedrawFlag redraw = TREDRAW_NOTHING;
+
+ switch (event->type) {
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ if (event->val == KM_PRESS) {
+ t->modifiers |= MOD_PRECISION;
+ /* shift is modifier for higher precision transforn */
+ mi->precision = 1;
+ redraw = TREDRAW_HARD;
+ }
+ else if (event->val == KM_RELEASE) {
+ t->modifiers &= ~MOD_PRECISION;
+ mi->precision = 0;
+ redraw = TREDRAW_HARD;
+ }
+ break;
+ }
+
+ return redraw;
}
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 7140938c99a..14d904fdc6d 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -54,9 +54,9 @@
#include "transform.h"
typedef struct TransformModeItem {
- const char *idname;
- int mode;
- void (*opfunc)(wmOperatorType *);
+ const char *idname;
+ int mode;
+ void (*opfunc)(wmOperatorType *);
} TransformModeItem;
static const float VecOne[3] = {1, 1, 1};
@@ -99,1079 +99,1141 @@ static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot);
static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot);
static void TRANSFORM_OT_rotate_normal(struct wmOperatorType *ot);
-static TransformModeItem transform_modes[] =
-{
- {OP_TRANSLATION, TFM_TRANSLATION, TRANSFORM_OT_translate},
- {OP_ROTATION, TFM_ROTATION, TRANSFORM_OT_rotate},
- {OP_TOSPHERE, TFM_TOSPHERE, TRANSFORM_OT_tosphere},
- {OP_RESIZE, TFM_RESIZE, TRANSFORM_OT_resize},
- {OP_SKIN_RESIZE, TFM_SKIN_RESIZE, TRANSFORM_OT_skin_resize},
- {OP_SHEAR, TFM_SHEAR, TRANSFORM_OT_shear},
- {OP_BEND, TFM_BEND, TRANSFORM_OT_bend},
- {OP_SHRINK_FATTEN, TFM_SHRINKFATTEN, TRANSFORM_OT_shrink_fatten},
- {OP_PUSH_PULL, TFM_PUSHPULL, TRANSFORM_OT_push_pull},
- {OP_TILT, TFM_TILT, TRANSFORM_OT_tilt},
- {OP_TRACKBALL, TFM_TRACKBALL, TRANSFORM_OT_trackball},
- {OP_MIRROR, TFM_MIRROR, TRANSFORM_OT_mirror},
- {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},
- {OP_EDGE_BWEIGHT, TFM_BWEIGHT, TRANSFORM_OT_edge_bevelweight},
- {OP_SEQ_SLIDE, TFM_SEQ_SLIDE, TRANSFORM_OT_seq_slide},
- {OP_NORMAL_ROTATION, TFM_NORMAL_ROTATION, TRANSFORM_OT_rotate_normal},
- {NULL, 0},
+static TransformModeItem transform_modes[] = {
+ {OP_TRANSLATION, TFM_TRANSLATION, TRANSFORM_OT_translate},
+ {OP_ROTATION, TFM_ROTATION, TRANSFORM_OT_rotate},
+ {OP_TOSPHERE, TFM_TOSPHERE, TRANSFORM_OT_tosphere},
+ {OP_RESIZE, TFM_RESIZE, TRANSFORM_OT_resize},
+ {OP_SKIN_RESIZE, TFM_SKIN_RESIZE, TRANSFORM_OT_skin_resize},
+ {OP_SHEAR, TFM_SHEAR, TRANSFORM_OT_shear},
+ {OP_BEND, TFM_BEND, TRANSFORM_OT_bend},
+ {OP_SHRINK_FATTEN, TFM_SHRINKFATTEN, TRANSFORM_OT_shrink_fatten},
+ {OP_PUSH_PULL, TFM_PUSHPULL, TRANSFORM_OT_push_pull},
+ {OP_TILT, TFM_TILT, TRANSFORM_OT_tilt},
+ {OP_TRACKBALL, TFM_TRACKBALL, TRANSFORM_OT_trackball},
+ {OP_MIRROR, TFM_MIRROR, TRANSFORM_OT_mirror},
+ {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},
+ {OP_EDGE_BWEIGHT, TFM_BWEIGHT, TRANSFORM_OT_edge_bevelweight},
+ {OP_SEQ_SLIDE, TFM_SEQ_SLIDE, TRANSFORM_OT_seq_slide},
+ {OP_NORMAL_ROTATION, TFM_NORMAL_ROTATION, TRANSFORM_OT_rotate_normal},
+ {NULL, 0},
};
-const EnumPropertyItem rna_enum_transform_mode_types[] =
-{
- {TFM_INIT, "INIT", 0, "Init", ""},
- {TFM_DUMMY, "DUMMY", 0, "Dummy", ""},
- {TFM_TRANSLATION, "TRANSLATION", 0, "Translation", ""},
- {TFM_ROTATION, "ROTATION", 0, "Rotation", ""},
- {TFM_RESIZE, "RESIZE", 0, "Resize", ""},
- {TFM_SKIN_RESIZE, "SKIN_RESIZE", 0, "Skin Resize", ""},
- {TFM_TOSPHERE, "TOSPHERE", 0, "Tosphere", ""},
- {TFM_SHEAR, "SHEAR", 0, "Shear", ""},
- {TFM_BEND, "BEND", 0, "Bend", ""},
- {TFM_SHRINKFATTEN, "SHRINKFATTEN", 0, "Shrinkfatten", ""},
- {TFM_TILT, "TILT", 0, "Tilt", ""},
- {TFM_TRACKBALL, "TRACKBALL", 0, "Trackball", ""},
- {TFM_PUSHPULL, "PUSHPULL", 0, "Pushpull", ""},
- {TFM_CREASE, "CREASE", 0, "Crease", ""},
- {TFM_MIRROR, "MIRROR", 0, "Mirror", ""},
- {TFM_BONESIZE, "BONE_SIZE", 0, "Bonesize", ""},
- {TFM_BONE_ENVELOPE, "BONE_ENVELOPE", 0, "Bone_Envelope", ""},
- {TFM_BONE_ENVELOPE_DIST, "BONE_ENVELOPE_DIST", 0, "Bone_Envelope_Distance", ""},
- {TFM_CURVE_SHRINKFATTEN, "CURVE_SHRINKFATTEN", 0, "Curve_Shrinkfatten", ""},
- {TFM_MASK_SHRINKFATTEN, "MASK_SHRINKFATTEN", 0, "Mask_Shrinkfatten", ""},
- {TFM_GPENCIL_SHRINKFATTEN, "GPENCIL_SHRINKFATTEN", 0, "GPencil_Shrinkfatten", ""},
- {TFM_BONE_ROLL, "BONE_ROLL", 0, "Bone_Roll", ""},
- {TFM_TIME_TRANSLATE, "TIME_TRANSLATE", 0, "Time_Translate", ""},
- {TFM_TIME_SLIDE, "TIME_SLIDE", 0, "Time_Slide", ""},
- {TFM_TIME_SCALE, "TIME_SCALE", 0, "Time_Scale", ""},
- {TFM_TIME_EXTEND, "TIME_EXTEND", 0, "Time_Extend", ""},
- {TFM_BAKE_TIME, "BAKE_TIME", 0, "Bake_Time", ""},
- {TFM_BWEIGHT, "BWEIGHT", 0, "Bweight", ""},
- {TFM_ALIGN, "ALIGN", 0, "Align", ""},
- {TFM_EDGE_SLIDE, "EDGESLIDE", 0, "Edge Slide", ""},
- {TFM_SEQ_SLIDE, "SEQSLIDE", 0, "Sequence Slide", ""},
- {TFM_GPENCIL_OPACITY, "GPENCIL_OPACITY", 0, "GPencil_Opacity", ""},
- {0, NULL, 0, NULL, NULL},
+const EnumPropertyItem rna_enum_transform_mode_types[] = {
+ {TFM_INIT, "INIT", 0, "Init", ""},
+ {TFM_DUMMY, "DUMMY", 0, "Dummy", ""},
+ {TFM_TRANSLATION, "TRANSLATION", 0, "Translation", ""},
+ {TFM_ROTATION, "ROTATION", 0, "Rotation", ""},
+ {TFM_RESIZE, "RESIZE", 0, "Resize", ""},
+ {TFM_SKIN_RESIZE, "SKIN_RESIZE", 0, "Skin Resize", ""},
+ {TFM_TOSPHERE, "TOSPHERE", 0, "Tosphere", ""},
+ {TFM_SHEAR, "SHEAR", 0, "Shear", ""},
+ {TFM_BEND, "BEND", 0, "Bend", ""},
+ {TFM_SHRINKFATTEN, "SHRINKFATTEN", 0, "Shrinkfatten", ""},
+ {TFM_TILT, "TILT", 0, "Tilt", ""},
+ {TFM_TRACKBALL, "TRACKBALL", 0, "Trackball", ""},
+ {TFM_PUSHPULL, "PUSHPULL", 0, "Pushpull", ""},
+ {TFM_CREASE, "CREASE", 0, "Crease", ""},
+ {TFM_MIRROR, "MIRROR", 0, "Mirror", ""},
+ {TFM_BONESIZE, "BONE_SIZE", 0, "Bonesize", ""},
+ {TFM_BONE_ENVELOPE, "BONE_ENVELOPE", 0, "Bone_Envelope", ""},
+ {TFM_BONE_ENVELOPE_DIST, "BONE_ENVELOPE_DIST", 0, "Bone_Envelope_Distance", ""},
+ {TFM_CURVE_SHRINKFATTEN, "CURVE_SHRINKFATTEN", 0, "Curve_Shrinkfatten", ""},
+ {TFM_MASK_SHRINKFATTEN, "MASK_SHRINKFATTEN", 0, "Mask_Shrinkfatten", ""},
+ {TFM_GPENCIL_SHRINKFATTEN, "GPENCIL_SHRINKFATTEN", 0, "GPencil_Shrinkfatten", ""},
+ {TFM_BONE_ROLL, "BONE_ROLL", 0, "Bone_Roll", ""},
+ {TFM_TIME_TRANSLATE, "TIME_TRANSLATE", 0, "Time_Translate", ""},
+ {TFM_TIME_SLIDE, "TIME_SLIDE", 0, "Time_Slide", ""},
+ {TFM_TIME_SCALE, "TIME_SCALE", 0, "Time_Scale", ""},
+ {TFM_TIME_EXTEND, "TIME_EXTEND", 0, "Time_Extend", ""},
+ {TFM_BAKE_TIME, "BAKE_TIME", 0, "Bake_Time", ""},
+ {TFM_BWEIGHT, "BWEIGHT", 0, "Bweight", ""},
+ {TFM_ALIGN, "ALIGN", 0, "Align", ""},
+ {TFM_EDGE_SLIDE, "EDGESLIDE", 0, "Edge Slide", ""},
+ {TFM_SEQ_SLIDE, "SEQSLIDE", 0, "Sequence Slide", ""},
+ {TFM_GPENCIL_OPACITY, "GPENCIL_OPACITY", 0, "GPencil_Opacity", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int select_orientation_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
- int orientation = RNA_enum_get(op->ptr, "orientation");
+ int orientation = RNA_enum_get(op->ptr, "orientation");
- BKE_scene_orientation_slot_set_index(&scene->orientation_slots[SCE_ORIENT_DEFAULT], orientation);
+ BKE_scene_orientation_slot_set_index(&scene->orientation_slots[SCE_ORIENT_DEFAULT], orientation);
- WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- WM_msg_publish_rna_prop(mbus, &scene->id, scene, TransformOrientationSlot, type);
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ WM_msg_publish_rna_prop(mbus, &scene->id, scene, TransformOrientationSlot, type);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static int select_orientation_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
+static int select_orientation_invoke(bContext *C,
+ wmOperator *UNUSED(op),
+ const wmEvent *UNUSED(event))
{
- uiPopupMenu *pup;
- uiLayout *layout;
+ uiPopupMenu *pup;
+ uiLayout *layout;
- pup = UI_popup_menu_begin(C, IFACE_("Orientation"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
- uiItemsEnumO(layout, "TRANSFORM_OT_select_orientation", "orientation");
- UI_popup_menu_end(C, pup);
+ pup = UI_popup_menu_begin(C, IFACE_("Orientation"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ uiItemsEnumO(layout, "TRANSFORM_OT_select_orientation", "orientation");
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
static void TRANSFORM_OT_select_orientation(struct wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Select Orientation";
- ot->description = "Select transformation orientation";
- ot->idname = "TRANSFORM_OT_select_orientation";
- ot->flag = OPTYPE_UNDO;
-
- /* api callbacks */
- ot->invoke = select_orientation_invoke;
- ot->exec = select_orientation_exec;
- ot->poll = ED_operator_view3d_active;
-
- prop = RNA_def_property(ot->srna, "orientation", PROP_ENUM, PROP_NONE);
- RNA_def_property_ui_text(prop, "Orientation", "Transformation orientation");
- RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Orientation";
+ ot->description = "Select transformation orientation";
+ ot->idname = "TRANSFORM_OT_select_orientation";
+ ot->flag = OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->invoke = select_orientation_invoke;
+ ot->exec = select_orientation_exec;
+ ot->poll = ED_operator_view3d_active;
+
+ prop = RNA_def_property(ot->srna, "orientation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Orientation", "Transformation orientation");
+ RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
}
-
static int delete_orientation_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- BIF_removeTransformOrientationIndex(C, scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom);
+ Scene *scene = CTX_data_scene(C);
+ BIF_removeTransformOrientationIndex(C,
+ scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom);
- WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
+ WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int delete_orientation_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- return delete_orientation_exec(C, op);
+ return delete_orientation_exec(C, op);
}
static bool delete_orientation_poll(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- if (ED_operator_areaactive(C) == 0)
- return 0;
+ if (ED_operator_areaactive(C) == 0)
+ return 0;
- return ((scene->orientation_slots[SCE_ORIENT_DEFAULT].type >= V3D_ORIENT_CUSTOM) &&
- (scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom != -1));
+ return ((scene->orientation_slots[SCE_ORIENT_DEFAULT].type >= V3D_ORIENT_CUSTOM) &&
+ (scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom != -1));
}
static void TRANSFORM_OT_delete_orientation(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Orientation";
- ot->description = "Delete transformation orientation";
- ot->idname = "TRANSFORM_OT_delete_orientation";
- ot->flag = OPTYPE_UNDO;
-
- /* api callbacks */
- ot->invoke = delete_orientation_invoke;
- ot->exec = delete_orientation_exec;
- ot->poll = delete_orientation_poll;
+ /* identifiers */
+ ot->name = "Delete Orientation";
+ ot->description = "Delete transformation orientation";
+ ot->idname = "TRANSFORM_OT_delete_orientation";
+ ot->flag = OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->invoke = delete_orientation_invoke;
+ ot->exec = delete_orientation_exec;
+ ot->poll = delete_orientation_poll;
}
static int create_orientation_exec(bContext *C, wmOperator *op)
{
- char name[MAX_NAME];
- const bool use = RNA_boolean_get(op->ptr, "use");
- 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);
+ char name[MAX_NAME];
+ const bool use = RNA_boolean_get(op->ptr, "use");
+ 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);
- RNA_string_get(op->ptr, "name", name);
+ RNA_string_get(op->ptr, "name", name);
- if (use && !v3d) {
- BKE_report(op->reports, RPT_ERROR, "Create Orientation's 'use' parameter only valid in a 3DView context");
- return OPERATOR_CANCELLED;
- }
+ if (use && !v3d) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Create Orientation's 'use' parameter only valid in a 3DView context");
+ return OPERATOR_CANCELLED;
+ }
- BIF_createTransformOrientation(C, op->reports, name, use_view, use, overwrite);
+ BIF_createTransformOrientation(C, op->reports, name, use_view, use, overwrite);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
- WM_event_add_notifier(C, NC_SCENE | NA_EDITED, CTX_data_scene(C));
+ 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;
+ return OPERATOR_FINISHED;
}
static void TRANSFORM_OT_create_orientation(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Create Orientation";
- ot->description = "Create transformation orientation from selection";
- ot->idname = "TRANSFORM_OT_create_orientation";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* api callbacks */
- ot->exec = create_orientation_exec;
- ot->poll = ED_operator_areaactive;
-
- RNA_def_string(ot->srna, "name", NULL, MAX_NAME, "Name", "Name of the new custom orientation");
- RNA_def_boolean(ot->srna, "use_view", false, "Use View",
- "Use the current view instead of the active object to create the new orientation");
-
- WM_operatortype_props_advanced_begin(ot);
-
- RNA_def_boolean(ot->srna, "use", false, "Use after creation", "Select orientation after its creation");
- RNA_def_boolean(ot->srna, "overwrite", false, "Overwrite previous",
- "Overwrite previously created orientation with same name");
+ /* identifiers */
+ ot->name = "Create Orientation";
+ ot->description = "Create transformation orientation from selection";
+ ot->idname = "TRANSFORM_OT_create_orientation";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec = create_orientation_exec;
+ ot->poll = ED_operator_areaactive;
+
+ RNA_def_string(ot->srna, "name", NULL, MAX_NAME, "Name", "Name of the new custom orientation");
+ RNA_def_boolean(
+ ot->srna,
+ "use_view",
+ false,
+ "Use View",
+ "Use the current view instead of the active object to create the new orientation");
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ RNA_def_boolean(
+ ot->srna, "use", false, "Use after creation", "Select orientation after its creation");
+ RNA_def_boolean(ot->srna,
+ "overwrite",
+ false,
+ "Overwrite previous",
+ "Overwrite previously created orientation with same name");
}
-
#ifdef USE_LOOPSLIDE_HACK
/**
* Special hack for MESH_OT_loopcut_slide so we get back to the selection mode
*/
static void transformops_loopsel_hack(bContext *C, wmOperator *op)
{
- if (op->type->idname == OP_EDGE_SLIDE) {
- if (op->opm && op->opm->opm && op->opm->opm->prev) {
- wmOperator *op_prev = op->opm->opm->prev;
- Scene *scene = CTX_data_scene(C);
- bool mesh_select_mode[3];
- PropertyRNA *prop = RNA_struct_find_property(op_prev->ptr, "mesh_select_mode_init");
-
- if (prop && RNA_property_is_set(op_prev->ptr, prop)) {
- ToolSettings *ts = scene->toolsettings;
- short selectmode_orig;
-
- RNA_property_boolean_get_array(op_prev->ptr, prop, mesh_select_mode);
- selectmode_orig = ((mesh_select_mode[0] ? SCE_SELECT_VERTEX : 0) |
- (mesh_select_mode[1] ? SCE_SELECT_EDGE : 0) |
- (mesh_select_mode[2] ? SCE_SELECT_FACE : 0));
-
- /* still switch if we were originally in face select mode */
- if ((ts->selectmode != selectmode_orig) && (selectmode_orig != SCE_SELECT_FACE)) {
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- em->selectmode = ts->selectmode = selectmode_orig;
- EDBM_selectmode_set(em);
- }
- }
- }
- }
+ if (op->type->idname == OP_EDGE_SLIDE) {
+ if (op->opm && op->opm->opm && op->opm->opm->prev) {
+ wmOperator *op_prev = op->opm->opm->prev;
+ Scene *scene = CTX_data_scene(C);
+ bool mesh_select_mode[3];
+ PropertyRNA *prop = RNA_struct_find_property(op_prev->ptr, "mesh_select_mode_init");
+
+ if (prop && RNA_property_is_set(op_prev->ptr, prop)) {
+ ToolSettings *ts = scene->toolsettings;
+ short selectmode_orig;
+
+ RNA_property_boolean_get_array(op_prev->ptr, prop, mesh_select_mode);
+ selectmode_orig = ((mesh_select_mode[0] ? SCE_SELECT_VERTEX : 0) |
+ (mesh_select_mode[1] ? SCE_SELECT_EDGE : 0) |
+ (mesh_select_mode[2] ? SCE_SELECT_FACE : 0));
+
+ /* still switch if we were originally in face select mode */
+ if ((ts->selectmode != selectmode_orig) && (selectmode_orig != SCE_SELECT_FACE)) {
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ em->selectmode = ts->selectmode = selectmode_orig;
+ EDBM_selectmode_set(em);
+ }
+ }
+ }
+ }
}
#else
/* prevent removal by cleanup */
# error "loopslide hack removed!"
-#endif /* USE_LOOPSLIDE_HACK */
-
+#endif /* USE_LOOPSLIDE_HACK */
static void transformops_exit(bContext *C, wmOperator *op)
{
#ifdef USE_LOOPSLIDE_HACK
- transformops_loopsel_hack(C, op);
+ transformops_loopsel_hack(C, op);
#endif
- saveTransform(C, op->customdata, op);
- MEM_freeN(op->customdata);
- op->customdata = NULL;
- G.moving = 0;
+ saveTransform(C, op->customdata, op);
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+ G.moving = 0;
}
static int transformops_data(bContext *C, wmOperator *op, const wmEvent *event)
{
- int retval = 1;
- if (op->customdata == NULL) {
- TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data2");
- TransformModeItem *tmode;
- int mode = -1;
-
- for (tmode = transform_modes; tmode->idname; tmode++) {
- if (op->type->idname == tmode->idname) {
- mode = tmode->mode;
- break;
- }
- }
-
- if (mode == -1) {
- mode = RNA_enum_get(op->ptr, "mode");
- }
-
- retval = initTransform(C, t, op, event, mode);
-
- /* store data */
- if (retval) {
- G.moving = special_transform_moving(t);
- op->customdata = t;
- }
- else {
- MEM_freeN(t);
- }
- }
-
- return retval; /* return 0 on error */
+ int retval = 1;
+ if (op->customdata == NULL) {
+ TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data2");
+ TransformModeItem *tmode;
+ int mode = -1;
+
+ for (tmode = transform_modes; tmode->idname; tmode++) {
+ if (op->type->idname == tmode->idname) {
+ mode = tmode->mode;
+ break;
+ }
+ }
+
+ if (mode == -1) {
+ mode = RNA_enum_get(op->ptr, "mode");
+ }
+
+ retval = initTransform(C, t, op, event, mode);
+
+ /* store data */
+ if (retval) {
+ G.moving = special_transform_moving(t);
+ op->customdata = t;
+ }
+ else {
+ MEM_freeN(t);
+ }
+ }
+
+ return retval; /* return 0 on error */
}
static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- int exit_code;
+ int exit_code;
- TransInfo *t = op->customdata;
- const enum TfmMode mode_prev = t->mode;
+ TransInfo *t = op->customdata;
+ const enum TfmMode mode_prev = t->mode;
#if defined(WITH_INPUT_NDOF) && 0
- // stable 2D mouse coords map to different 3D coords while the 3D mouse is active
- // in other words, 2D deltas are no longer good enough!
- // disable until individual 'transformers' behave better
+ // stable 2D mouse coords map to different 3D coords while the 3D mouse is active
+ // in other words, 2D deltas are no longer good enough!
+ // disable until individual 'transformers' behave better
- if (event->type == NDOF_MOTION)
- return OPERATOR_PASS_THROUGH;
+ if (event->type == NDOF_MOTION)
+ return OPERATOR_PASS_THROUGH;
#endif
- /* XXX insert keys are called here, and require context */
- t->context = C;
- exit_code = transformEvent(t, event);
- t->context = NULL;
-
- /* XXX, workaround: active needs to be calculated before transforming,
- * since we're not reading from 'td->center' in this case. see: T40241 */
- if (t->tsnap.target == SCE_SNAP_TARGET_ACTIVE) {
- /* In camera view, tsnap callback is not set
- * (see initSnappingMode() in transfrom_snap.c, and T40348). */
- if (t->tsnap.targetSnap && ((t->tsnap.status & TARGET_INIT) == 0)) {
- t->tsnap.targetSnap(t);
- }
- }
-
- transformApply(C, t);
-
- exit_code |= transformEnd(C, t);
-
- if ((exit_code & OPERATOR_RUNNING_MODAL) == 0) {
- transformops_exit(C, op);
- exit_code &= ~OPERATOR_PASS_THROUGH; /* preventively remove passthrough */
- }
- else {
- if (mode_prev != t->mode) {
- /* WARNING: this is not normal to switch operator types
- * normally it would not be supported but transform happens
- * to share callbacks between different operators. */
- wmOperatorType *ot_new = NULL;
- TransformModeItem *item = transform_modes;
- while (item->idname) {
- if (item->mode == t->mode) {
- ot_new = WM_operatortype_find(item->idname, false);
- break;
- }
- item++;
- }
-
- BLI_assert(ot_new != NULL);
- if (ot_new) {
- WM_operator_type_set(op, ot_new);
- }
- /* end suspicious code */
- }
- }
-
- return exit_code;
+ /* XXX insert keys are called here, and require context */
+ t->context = C;
+ exit_code = transformEvent(t, event);
+ t->context = NULL;
+
+ /* XXX, workaround: active needs to be calculated before transforming,
+ * since we're not reading from 'td->center' in this case. see: T40241 */
+ if (t->tsnap.target == SCE_SNAP_TARGET_ACTIVE) {
+ /* In camera view, tsnap callback is not set
+ * (see initSnappingMode() in transfrom_snap.c, and T40348). */
+ if (t->tsnap.targetSnap && ((t->tsnap.status & TARGET_INIT) == 0)) {
+ t->tsnap.targetSnap(t);
+ }
+ }
+
+ transformApply(C, t);
+
+ exit_code |= transformEnd(C, t);
+
+ if ((exit_code & OPERATOR_RUNNING_MODAL) == 0) {
+ transformops_exit(C, op);
+ exit_code &= ~OPERATOR_PASS_THROUGH; /* preventively remove passthrough */
+ }
+ else {
+ if (mode_prev != t->mode) {
+ /* WARNING: this is not normal to switch operator types
+ * normally it would not be supported but transform happens
+ * to share callbacks between different operators. */
+ wmOperatorType *ot_new = NULL;
+ TransformModeItem *item = transform_modes;
+ while (item->idname) {
+ if (item->mode == t->mode) {
+ ot_new = WM_operatortype_find(item->idname, false);
+ break;
+ }
+ item++;
+ }
+
+ BLI_assert(ot_new != NULL);
+ if (ot_new) {
+ WM_operator_type_set(op, ot_new);
+ }
+ /* end suspicious code */
+ }
+ }
+
+ return exit_code;
}
static void transform_cancel(bContext *C, wmOperator *op)
{
- TransInfo *t = op->customdata;
+ TransInfo *t = op->customdata;
- t->state = TRANS_CANCEL;
- transformEnd(C, t);
- transformops_exit(C, op);
+ t->state = TRANS_CANCEL;
+ transformEnd(C, t);
+ transformops_exit(C, op);
}
static int transform_exec(bContext *C, wmOperator *op)
{
- TransInfo *t;
+ TransInfo *t;
- if (!transformops_data(C, op, NULL)) {
- G.moving = 0;
- return OPERATOR_CANCELLED;
- }
+ if (!transformops_data(C, op, NULL)) {
+ G.moving = 0;
+ return OPERATOR_CANCELLED;
+ }
- t = op->customdata;
+ t = op->customdata;
- t->options |= CTX_AUTOCONFIRM;
+ t->options |= CTX_AUTOCONFIRM;
- transformApply(C, t);
+ transformApply(C, t);
- transformEnd(C, t);
+ transformEnd(C, t);
- transformops_exit(C, op);
+ transformops_exit(C, op);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int transform_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (!transformops_data(C, op, event)) {
- G.moving = 0;
- return OPERATOR_CANCELLED;
- }
-
- /* When modal, allow 'value' to set initial offset. */
- if ((event == NULL) &&
- RNA_struct_property_is_set(op->ptr, "value"))
- {
- return transform_exec(C, op);
- }
- else {
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
-
- op->flag |= OP_IS_MODAL_GRAB_CURSOR; // XXX maybe we want this with the gizmo only?
-
- /* Use when modal input has some transformation to begin with. */
- {
- TransInfo *t = op->customdata;
- if (UNLIKELY(!is_zero_v4(t->values_modal_offset))) {
- transformApply(C, t);
- }
- }
-
- return OPERATOR_RUNNING_MODAL;
- }
+ if (!transformops_data(C, op, event)) {
+ G.moving = 0;
+ return OPERATOR_CANCELLED;
+ }
+
+ /* When modal, allow 'value' to set initial offset. */
+ if ((event == NULL) && RNA_struct_property_is_set(op->ptr, "value")) {
+ return transform_exec(C, op);
+ }
+ else {
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ op->flag |= OP_IS_MODAL_GRAB_CURSOR; // XXX maybe we want this with the gizmo only?
+
+ /* Use when modal input has some transformation to begin with. */
+ {
+ TransInfo *t = op->customdata;
+ if (UNLIKELY(!is_zero_v4(t->values_modal_offset))) {
+ transformApply(C, t);
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+ }
}
-static bool transform_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop)
+static bool transform_poll_property(const bContext *UNUSED(C),
+ wmOperator *op,
+ const PropertyRNA *prop)
{
- const char *prop_id = RNA_property_identifier(prop);
-
- /* Orientation/Constraints. */
- {
- /* Hide orientation axis if no constraints are set, since it wont be used. */
- PropertyRNA *prop_con = RNA_struct_find_property(op->ptr, "orient_type");
- if (prop_con != NULL && (prop_con != prop)) {
- if (STRPREFIX(prop_id, "constraint")) {
-
- /* Special case: show constraint axis if we don't have values,
- * needed for mirror operator. */
- if (STREQ(prop_id, "constraint_axis") &&
- (RNA_struct_find_property(op->ptr, "value") == NULL))
- {
- return true;
- }
-
- return false;
- }
- }
- }
-
- /* Proportional Editing. */
- {
- PropertyRNA *prop_pet = RNA_struct_find_property(op->ptr, "proportional");
- if (prop_pet && (prop_pet != prop) &&
- (RNA_property_enum_get(op->ptr, prop_pet) == PROP_EDIT_OFF))
- {
- if (STRPREFIX(prop_id, "proportional")) {
- return false;
- }
- }
- }
-
- return true;
+ const char *prop_id = RNA_property_identifier(prop);
+
+ /* Orientation/Constraints. */
+ {
+ /* Hide orientation axis if no constraints are set, since it wont be used. */
+ PropertyRNA *prop_con = RNA_struct_find_property(op->ptr, "orient_type");
+ if (prop_con != NULL && (prop_con != prop)) {
+ if (STRPREFIX(prop_id, "constraint")) {
+
+ /* Special case: show constraint axis if we don't have values,
+ * needed for mirror operator. */
+ if (STREQ(prop_id, "constraint_axis") &&
+ (RNA_struct_find_property(op->ptr, "value") == NULL)) {
+ return true;
+ }
+
+ return false;
+ }
+ }
+ }
+
+ /* Proportional Editing. */
+ {
+ PropertyRNA *prop_pet = RNA_struct_find_property(op->ptr, "proportional");
+ if (prop_pet && (prop_pet != prop) &&
+ (RNA_property_enum_get(op->ptr, prop_pet) == PROP_EDIT_OFF)) {
+ if (STRPREFIX(prop_id, "proportional")) {
+ return false;
+ }
+ }
+ }
+
+ return true;
}
void Transform_Properties(struct wmOperatorType *ot, int flags)
{
- PropertyRNA *prop;
-
- if (flags & P_ORIENT_AXIS) {
- prop = RNA_def_property(ot->srna, "orient_axis", PROP_ENUM, PROP_NONE);
- RNA_def_property_ui_text(prop, "Axis", "");
- RNA_def_property_enum_default(prop, 2);
- RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- }
- if (flags & P_ORIENT_AXIS_ORTHO) {
- prop = RNA_def_property(ot->srna, "orient_axis_ortho", PROP_ENUM, PROP_NONE);
- RNA_def_property_ui_text(prop, "Axis Ortho", "");
- RNA_def_property_enum_default(prop, 1);
- RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- }
-
- if (flags & P_ORIENT_MATRIX) {
- prop = RNA_def_property(ot->srna, "orient_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_ui_text(prop, "Orientation", "Transformation orientation");
- RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
-
- /* Set by 'orient_type' or gizmo which acts on non-standard orientation. */
- prop = RNA_def_float_matrix(ot->srna, "orient_matrix", 3, 3, NULL, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
-
- /* Only use 'orient_matrix' when 'orient_matrix_type == orient_type',
- * this allows us to reuse the orientation set by a gizmo for eg, without disabling the ability
- * to switch over to other orientations. */
- prop = RNA_def_property(ot->srna, "orient_matrix_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_ui_text(prop, "Matrix Orientation", "");
- RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
- RNA_def_property_flag(prop, PROP_HIDDEN);
- }
-
- if (flags & P_CONSTRAINT) {
- RNA_def_boolean_vector(ot->srna, "constraint_axis", 3, NULL, "Constraint Axis", "");
- }
-
- if (flags & P_MIRROR) {
- prop = RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
- if (flags & P_MIRROR_DUMMY) {
- /* only used so macros can disable this option */
- RNA_def_property_flag(prop, PROP_HIDDEN);
- }
- }
-
-
- if (flags & P_PROPORTIONAL) {
- RNA_def_enum(ot->srna, "proportional", rna_enum_proportional_editing_items, 0, "Proportional Editing", "");
- prop = RNA_def_enum(ot->srna, "proportional_edit_falloff", rna_enum_proportional_falloff_items, 0,
- "Proportional Falloff", "Falloff type for proportional editing mode");
- /* Abusing id_curve :/ */
- RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE);
- RNA_def_float(ot->srna, "proportional_size", 1, T_PROP_SIZE_MIN, T_PROP_SIZE_MAX,
- "Proportional Size", "", 0.001f, 100.0f);
- }
-
- if (flags & P_SNAP) {
- prop = RNA_def_boolean(ot->srna, "snap", 0, "Use Snapping Options", "");
- RNA_def_property_flag(prop, PROP_HIDDEN);
-
- if (flags & P_GEO_SNAP) {
- prop = RNA_def_enum(ot->srna, "snap_target", rna_enum_snap_target_items, 0, "Target", "");
- RNA_def_property_flag(prop, PROP_HIDDEN);
- prop = RNA_def_float_vector(ot->srna, "snap_point", 3, NULL, -FLT_MAX, FLT_MAX, "Point", "", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
-
- if (flags & P_ALIGN_SNAP) {
- prop = RNA_def_boolean(ot->srna, "snap_align", 0, "Align with Point Normal", "");
- RNA_def_property_flag(prop, PROP_HIDDEN);
- prop = RNA_def_float_vector(ot->srna, "snap_normal", 3, NULL, -FLT_MAX, FLT_MAX, "Normal", "", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
- }
- }
- }
-
- if (flags & P_GPENCIL_EDIT) {
- prop = RNA_def_boolean(ot->srna, "gpencil_strokes", 0, "Edit Grease Pencil", "Edit selected Grease Pencil strokes");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- }
-
- if (flags & P_CURSOR_EDIT) {
- prop = RNA_def_boolean(ot->srna, "cursor_transform", 0, "Transform Cursor", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- }
-
- if ((flags & P_OPTIONS) && !(flags & P_NO_TEXSPACE)) {
- prop = RNA_def_boolean(ot->srna, "texture_space", 0, "Edit Texture Space", "Edit Object data texture space");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "remove_on_cancel", 0, "Remove on Cancel", "Remove elements on cancel");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- }
-
- if (flags & P_CORRECT_UV) {
- RNA_def_boolean(ot->srna, "correct_uv", true, "Correct UVs", "Correct UV coordinates when transforming");
- }
-
- if (flags & P_CENTER) {
- /* For gizmos that define their own center. */
- prop = RNA_def_property(ot->srna, "center_override", PROP_FLOAT, PROP_XYZ);
- RNA_def_property_array(prop, 3);
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- RNA_def_property_ui_text(prop, "Center Override", "Force using this center value (when set)");
- }
-
- if ((flags & P_NO_DEFAULTS) == 0) {
- prop = RNA_def_boolean(ot->srna, "release_confirm", 0, "Confirm on Release", "Always confirm operation when releasing button");
- RNA_def_property_flag(prop, PROP_HIDDEN);
-
- prop = RNA_def_boolean(ot->srna, "use_accurate", 0, "Accurate", "Use accurate transformation");
- RNA_def_property_flag(prop, PROP_HIDDEN);
- }
+ PropertyRNA *prop;
+
+ if (flags & P_ORIENT_AXIS) {
+ prop = RNA_def_property(ot->srna, "orient_axis", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Axis", "");
+ RNA_def_property_enum_default(prop, 2);
+ RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ }
+ if (flags & P_ORIENT_AXIS_ORTHO) {
+ prop = RNA_def_property(ot->srna, "orient_axis_ortho", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Axis Ortho", "");
+ RNA_def_property_enum_default(prop, 1);
+ RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ }
+
+ if (flags & P_ORIENT_MATRIX) {
+ prop = RNA_def_property(ot->srna, "orient_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Orientation", "Transformation orientation");
+ RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
+
+ /* Set by 'orient_type' or gizmo which acts on non-standard orientation. */
+ prop = RNA_def_float_matrix(
+ ot->srna, "orient_matrix", 3, 3, NULL, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ /* Only use 'orient_matrix' when 'orient_matrix_type == orient_type',
+ * this allows us to reuse the orientation set by a gizmo for eg, without disabling the ability
+ * to switch over to other orientations. */
+ prop = RNA_def_property(ot->srna, "orient_matrix_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Matrix Orientation", "");
+ RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ }
+
+ if (flags & P_CONSTRAINT) {
+ RNA_def_boolean_vector(ot->srna, "constraint_axis", 3, NULL, "Constraint Axis", "");
+ }
+
+ if (flags & P_MIRROR) {
+ prop = RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
+ if (flags & P_MIRROR_DUMMY) {
+ /* only used so macros can disable this option */
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ }
+ }
+
+ if (flags & P_PROPORTIONAL) {
+ RNA_def_enum(ot->srna,
+ "proportional",
+ rna_enum_proportional_editing_items,
+ 0,
+ "Proportional Editing",
+ "");
+ prop = RNA_def_enum(ot->srna,
+ "proportional_edit_falloff",
+ rna_enum_proportional_falloff_items,
+ 0,
+ "Proportional Falloff",
+ "Falloff type for proportional editing mode");
+ /* Abusing id_curve :/ */
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE);
+ RNA_def_float(ot->srna,
+ "proportional_size",
+ 1,
+ T_PROP_SIZE_MIN,
+ T_PROP_SIZE_MAX,
+ "Proportional Size",
+ "",
+ 0.001f,
+ 100.0f);
+ }
+
+ if (flags & P_SNAP) {
+ prop = RNA_def_boolean(ot->srna, "snap", 0, "Use Snapping Options", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ if (flags & P_GEO_SNAP) {
+ prop = RNA_def_enum(ot->srna, "snap_target", rna_enum_snap_target_items, 0, "Target", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_float_vector(
+ ot->srna, "snap_point", 3, NULL, -FLT_MAX, FLT_MAX, "Point", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ if (flags & P_ALIGN_SNAP) {
+ prop = RNA_def_boolean(ot->srna, "snap_align", 0, "Align with Point Normal", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_float_vector(
+ ot->srna, "snap_normal", 3, NULL, -FLT_MAX, FLT_MAX, "Normal", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ }
+ }
+ }
+
+ if (flags & P_GPENCIL_EDIT) {
+ prop = RNA_def_boolean(ot->srna,
+ "gpencil_strokes",
+ 0,
+ "Edit Grease Pencil",
+ "Edit selected Grease Pencil strokes");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ }
+
+ if (flags & P_CURSOR_EDIT) {
+ prop = RNA_def_boolean(ot->srna, "cursor_transform", 0, "Transform Cursor", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ }
+
+ if ((flags & P_OPTIONS) && !(flags & P_NO_TEXSPACE)) {
+ prop = RNA_def_boolean(
+ ot->srna, "texture_space", 0, "Edit Texture Space", "Edit Object data texture space");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(
+ ot->srna, "remove_on_cancel", 0, "Remove on Cancel", "Remove elements on cancel");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ }
+
+ if (flags & P_CORRECT_UV) {
+ RNA_def_boolean(
+ ot->srna, "correct_uv", true, "Correct UVs", "Correct UV coordinates when transforming");
+ }
+
+ if (flags & P_CENTER) {
+ /* For gizmos that define their own center. */
+ prop = RNA_def_property(ot->srna, "center_override", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ RNA_def_property_ui_text(prop, "Center Override", "Force using this center value (when set)");
+ }
+
+ if ((flags & P_NO_DEFAULTS) == 0) {
+ prop = RNA_def_boolean(ot->srna,
+ "release_confirm",
+ 0,
+ "Confirm on Release",
+ "Always confirm operation when releasing button");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ prop = RNA_def_boolean(ot->srna, "use_accurate", 0, "Accurate", "Use accurate transformation");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ }
}
static void TRANSFORM_OT_translate(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move";
- ot->description = "Move selected items";
- ot->idname = OP_TRANSLATION;
- 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_screenactive;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_vector_xyz(ot->srna, "value", 3, NULL, -FLT_MAX, FLT_MAX, "Move", "", -FLT_MAX, FLT_MAX);
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(
- ot,
- P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_OPTIONS |
- P_GPENCIL_EDIT | P_CURSOR_EDIT);
+ /* identifiers */
+ ot->name = "Move";
+ ot->description = "Move selected items";
+ ot->idname = OP_TRANSLATION;
+ 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_screenactive;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_vector_xyz(
+ ot->srna, "value", 3, NULL, -FLT_MAX, FLT_MAX, "Move", "", -FLT_MAX, FLT_MAX);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot,
+ P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP |
+ P_OPTIONS | P_GPENCIL_EDIT | P_CURSOR_EDIT);
}
static void TRANSFORM_OT_resize(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Resize";
- ot->description = "Scale (resize) selected items";
- ot->idname = OP_RESIZE;
- 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_screenactive;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Scale", "", -FLT_MAX, FLT_MAX);
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(
- ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_OPTIONS | P_GPENCIL_EDIT | P_CENTER);
+ /* identifiers */
+ ot->name = "Resize";
+ ot->description = "Scale (resize) selected items";
+ ot->idname = OP_RESIZE;
+ 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_screenactive;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_vector(
+ ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Scale", "", -FLT_MAX, FLT_MAX);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot,
+ P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP |
+ P_OPTIONS | P_GPENCIL_EDIT | P_CENTER);
}
static bool skin_resize_poll(bContext *C)
{
- struct Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_MESH) {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- return (em && CustomData_has_layer(&em->bm->vdata, CD_MVERT_SKIN));
- }
- return 0;
+ struct Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_MESH) {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ return (em && CustomData_has_layer(&em->bm->vdata, CD_MVERT_SKIN));
+ }
+ return 0;
}
static void TRANSFORM_OT_skin_resize(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Skin Resize";
- ot->description = "Scale selected vertices' skin radii";
- ot->idname = OP_SKIN_RESIZE;
- 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 = skin_resize_poll;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Scale", "", -FLT_MAX, FLT_MAX);
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(
- ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_OPTIONS | P_NO_TEXSPACE);
+ /* identifiers */
+ ot->name = "Skin Resize";
+ ot->description = "Scale selected vertices' skin radii";
+ ot->idname = OP_SKIN_RESIZE;
+ 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 = skin_resize_poll;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_vector(
+ ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Scale", "", -FLT_MAX, FLT_MAX);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot,
+ P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP |
+ P_OPTIONS | P_NO_TEXSPACE);
}
static void TRANSFORM_OT_trackball(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Trackball";
- ot->description = "Trackball style rotation of selected items";
- ot->idname = OP_TRACKBALL;
- 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_screenactive;
- ot->poll_property = transform_poll_property;
-
- /* Maybe we could use float_vector_xyz here too? */
- RNA_def_float_rotation(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX);
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
+ /* identifiers */
+ ot->name = "Trackball";
+ ot->description = "Trackball style rotation of selected items";
+ ot->idname = OP_TRACKBALL;
+ 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_screenactive;
+ ot->poll_property = transform_poll_property;
+
+ /* Maybe we could use float_vector_xyz here too? */
+ RNA_def_float_rotation(
+ ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
static void TRANSFORM_OT_rotate(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Rotate";
- ot->description = "Rotate selected items";
- ot->idname = OP_ROTATION;
- 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_screenactive;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(
- ot, P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_GPENCIL_EDIT | P_CENTER);
+ /* identifiers */
+ ot->name = "Rotate";
+ ot->description = "Rotate selected items";
+ ot->idname = OP_ROTATION;
+ 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_screenactive;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_rotation(
+ ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot,
+ P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR |
+ P_GEO_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
static void TRANSFORM_OT_tilt(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Tilt";
- /* optional -
- * "Tilt selected vertices"
- * "Specify an extra axis rotation for selected vertices of 3D curve" */
- ot->description = "Tilt selected control vertices of 3D curve";
- ot->idname = OP_TILT;
- 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_editcurve_3d;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
+ /* identifiers */
+ ot->name = "Tilt";
+ /* optional -
+ * "Tilt selected vertices"
+ * "Specify an extra axis rotation for selected vertices of 3D curve" */
+ ot->description = "Tilt selected control vertices of 3D curve";
+ ot->idname = OP_TILT;
+ 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_editcurve_3d;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_rotation(
+ ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
}
static void TRANSFORM_OT_bend(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Bend";
- ot->description = "Bend selected items between the 3D cursor and the mouse";
- ot->idname = OP_BEND;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* api callbacks */
- ot->invoke = transform_invoke;
- // ot->exec = transform_exec; // unsupported
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_region_view3d_active;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
+ /* identifiers */
+ ot->name = "Bend";
+ ot->description = "Bend selected items between the 3D cursor and the mouse";
+ ot->idname = OP_BEND;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ // ot->exec = transform_exec; // unsupported
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_region_view3d_active;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_rotation(
+ ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
static void TRANSFORM_OT_shear(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Shear";
- ot->description = "Shear selected items along the horizontal screen axis";
- ot->idname = OP_SHEAR;
- 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_screenactive;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
- RNA_def_enum(ot->srna, "shear_axis", rna_enum_axis_xy_items, 0, "Shear Axis", "");
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(
- ot, P_ORIENT_AXIS | P_ORIENT_AXIS_ORTHO | P_ORIENT_MATRIX | P_PROPORTIONAL | P_MIRROR |
- P_SNAP | P_GPENCIL_EDIT);
+ /* identifiers */
+ ot->name = "Shear";
+ ot->description = "Shear selected items along the horizontal screen axis";
+ ot->idname = OP_SHEAR;
+ 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_screenactive;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
+ RNA_def_enum(ot->srna, "shear_axis", rna_enum_axis_xy_items, 0, "Shear Axis", "");
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot,
+ P_ORIENT_AXIS | P_ORIENT_AXIS_ORTHO | P_ORIENT_MATRIX | P_PROPORTIONAL |
+ P_MIRROR | P_SNAP | P_GPENCIL_EDIT);
}
static void TRANSFORM_OT_push_pull(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Push/Pull";
- ot->description = "Push/Pull selected items";
- ot->idname = OP_PUSH_PULL;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ /* identifiers */
+ ot->name = "Push/Pull";
+ ot->description = "Push/Pull selected items";
+ ot->idname = OP_PUSH_PULL;
+ 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_screenactive;
- ot->poll_property = transform_poll_property;
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
- RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Distance", "", -FLT_MAX, FLT_MAX);
+ RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Distance", "", -FLT_MAX, FLT_MAX);
- WM_operatortype_props_advanced_begin(ot);
+ WM_operatortype_props_advanced_begin(ot);
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_CENTER);
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_CENTER);
}
static void TRANSFORM_OT_shrink_fatten(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Shrink/Fatten";
- ot->description = "Shrink/fatten selected vertices along normals";
- ot->idname = OP_SHRINK_FATTEN;
- 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_editmesh;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_distance(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
-
- RNA_def_boolean(ot->srna, "use_even_offset", false, "Offset Even", "Scale the offset to give more even thickness");
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
+ /* identifiers */
+ ot->name = "Shrink/Fatten";
+ ot->description = "Shrink/fatten selected vertices along normals";
+ ot->idname = OP_SHRINK_FATTEN;
+ 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_editmesh;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_distance(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
+
+ RNA_def_boolean(ot->srna,
+ "use_even_offset",
+ false,
+ "Offset Even",
+ "Scale the offset to give more even thickness");
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
}
static void TRANSFORM_OT_tosphere(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "To Sphere";
- //added "around mesh center" to differentiate between "MESH_OT_vertices_to_sphere()"
- ot->description = "Move selected vertices outward in a spherical shape around mesh center";
- ot->idname = OP_TOSPHERE;
- 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_screenactive;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_factor(ot->srna, "value", 0, 0, 1, "Factor", "", 0, 1);
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
+ /* identifiers */
+ ot->name = "To Sphere";
+ //added "around mesh center" to differentiate between "MESH_OT_vertices_to_sphere()"
+ ot->description = "Move selected vertices outward in a spherical shape around mesh center";
+ ot->idname = OP_TOSPHERE;
+ 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_screenactive;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_factor(ot->srna, "value", 0, 0, 1, "Factor", "", 0, 1);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
static void TRANSFORM_OT_mirror(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Mirror";
- ot->description = "Mirror selected items around one or more axes";
- ot->idname = OP_MIRROR;
- 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_screenactive;
- ot->poll_property = transform_poll_property;
-
- Transform_Properties(ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_GPENCIL_EDIT | P_CENTER);
+ /* identifiers */
+ ot->name = "Mirror";
+ ot->description = "Mirror selected items around one or more axes";
+ ot->idname = OP_MIRROR;
+ 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_screenactive;
+ ot->poll_property = transform_poll_property;
+
+ Transform_Properties(
+ ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_GPENCIL_EDIT | P_CENTER);
}
static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Edge Slide";
- ot->description = "Slide an edge loop along a mesh";
- ot->idname = OP_EDGE_SLIDE;
- 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_editmesh_region_view3d;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
-
- prop = RNA_def_boolean(ot->srna, "single_side", false, "Single Side", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- RNA_def_boolean(ot->srna, "use_even", false, "Even",
- "Make the edge loop match the shape of the adjacent edge loop");
-
- WM_operatortype_props_advanced_begin(ot);
-
- RNA_def_boolean(ot->srna, "flipped", false, "Flipped",
- "When Even mode is active, flips between the two adjacent edge loops");
- RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp",
- "Clamp within the edge extents");
-
- Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Edge Slide";
+ ot->description = "Slide an edge loop along a mesh";
+ ot->idname = OP_EDGE_SLIDE;
+ 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_editmesh_region_view3d;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
+
+ prop = RNA_def_boolean(ot->srna, "single_side", false, "Single Side", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ RNA_def_boolean(ot->srna,
+ "use_even",
+ false,
+ "Even",
+ "Make the edge loop match the shape of the adjacent edge loop");
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ RNA_def_boolean(ot->srna,
+ "flipped",
+ false,
+ "Flipped",
+ "When Even mode is active, flips between the two adjacent edge loops");
+ RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp", "Clamp within the edge extents");
+
+ Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
}
static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Vertex Slide";
- ot->description = "Slide a vertex along a mesh";
- ot->idname = OP_VERT_SLIDE;
- 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_editmesh_region_view3d;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
- RNA_def_boolean(ot->srna, "use_even", false, "Even",
- "Make the edge loop match the shape of the adjacent edge loop");
-
- WM_operatortype_props_advanced_begin(ot);
-
- RNA_def_boolean(ot->srna, "flipped", false, "Flipped",
- "When Even mode is active, flips between the two adjacent edge loops");
- RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp",
- "Clamp within the edge extents");
-
- Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
+ /* identifiers */
+ ot->name = "Vertex Slide";
+ ot->description = "Slide a vertex along a mesh";
+ ot->idname = OP_VERT_SLIDE;
+ 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_editmesh_region_view3d;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
+ RNA_def_boolean(ot->srna,
+ "use_even",
+ false,
+ "Even",
+ "Make the edge loop match the shape of the adjacent edge loop");
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ RNA_def_boolean(ot->srna,
+ "flipped",
+ false,
+ "Flipped",
+ "When Even mode is active, flips between the two adjacent edge loops");
+ RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp", "Clamp within the edge extents");
+
+ Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
}
static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Edge Crease";
- ot->description = "Change the crease of edges";
- ot->idname = OP_EDGE_CREASE;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ /* identifiers */
+ ot->name = "Edge Crease";
+ ot->description = "Change the crease of edges";
+ ot->idname = OP_EDGE_CREASE;
+ 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_editmesh;
- ot->poll_property = transform_poll_property;
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_editmesh;
+ ot->poll_property = transform_poll_property;
- RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f);
+ RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f);
- WM_operatortype_props_advanced_begin(ot);
+ WM_operatortype_props_advanced_begin(ot);
- Transform_Properties(ot, P_SNAP);
+ Transform_Properties(ot, P_SNAP);
}
static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Edge Bevel Weight";
- ot->description = "Change the bevel weight of edges";
- ot->idname = OP_EDGE_BWEIGHT;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ /* identifiers */
+ ot->name = "Edge Bevel Weight";
+ ot->description = "Change the bevel weight of edges";
+ ot->idname = OP_EDGE_BWEIGHT;
+ 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_editmesh;
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_editmesh;
- RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f);
+ RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f);
- WM_operatortype_props_advanced_begin(ot);
+ WM_operatortype_props_advanced_begin(ot);
- Transform_Properties(ot, P_SNAP);
+ Transform_Properties(ot, P_SNAP);
}
static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Sequence Slide";
- ot->description = "Slide a sequence strip in time";
- ot->idname = OP_SEQ_SLIDE;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ /* identifiers */
+ ot->name = "Sequence Slide";
+ ot->description = "Slide a sequence strip in time";
+ ot->idname = OP_SEQ_SLIDE;
+ 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_sequencer_active;
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_sequencer_active;
- RNA_def_float_vector_xyz(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
+ RNA_def_float_vector_xyz(
+ ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
- WM_operatortype_props_advanced_begin(ot);
+ WM_operatortype_props_advanced_begin(ot);
- Transform_Properties(ot, P_SNAP);
+ Transform_Properties(ot, P_SNAP);
}
static void TRANSFORM_OT_rotate_normal(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Normal Rotate";
- ot->description = "Rotate split normal of selected items";
- ot->idname = OP_NORMAL_ROTATION;
- 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_editmesh_auto_smooth;
-
- RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
-
- Transform_Properties(ot, P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_MIRROR);
+ /* identifiers */
+ ot->name = "Normal Rotate";
+ ot->description = "Rotate split normal of selected items";
+ ot->idname = OP_NORMAL_ROTATION;
+ 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_editmesh_auto_smooth;
+
+ RNA_def_float_rotation(
+ ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
+
+ Transform_Properties(ot, P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_MIRROR);
}
-
static void TRANSFORM_OT_transform(struct wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Transform";
- ot->description = "Transform selected items by mode type";
- ot->idname = "TRANSFORM_OT_transform";
- 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_screenactive;
- ot->poll_property = transform_poll_property;
-
- prop = RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
- RNA_def_property_flag(prop, PROP_HIDDEN);
-
- RNA_def_float_vector(ot->srna, "value", 4, NULL, -FLT_MAX, FLT_MAX, "Values", "", -FLT_MAX, FLT_MAX);
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(
- ot, P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP |
- P_GPENCIL_EDIT | P_CENTER);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Transform";
+ ot->description = "Transform selected items by mode type";
+ ot->idname = "TRANSFORM_OT_transform";
+ 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_screenactive;
+ ot->poll_property = transform_poll_property;
+
+ prop = RNA_def_enum(
+ ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ RNA_def_float_vector(
+ ot->srna, "value", 4, NULL, -FLT_MAX, FLT_MAX, "Values", "", -FLT_MAX, FLT_MAX);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot,
+ P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR |
+ P_ALIGN_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
void transform_operatortypes(void)
{
- TransformModeItem *tmode;
+ TransformModeItem *tmode;
- for (tmode = transform_modes; tmode->idname; tmode++) {
- WM_operatortype_append(tmode->opfunc);
- }
+ for (tmode = transform_modes; tmode->idname; tmode++) {
+ WM_operatortype_append(tmode->opfunc);
+ }
- WM_operatortype_append(TRANSFORM_OT_transform);
+ WM_operatortype_append(TRANSFORM_OT_transform);
- WM_operatortype_append(TRANSFORM_OT_select_orientation);
- WM_operatortype_append(TRANSFORM_OT_create_orientation);
- WM_operatortype_append(TRANSFORM_OT_delete_orientation);
+ WM_operatortype_append(TRANSFORM_OT_select_orientation);
+ WM_operatortype_append(TRANSFORM_OT_create_orientation);
+ WM_operatortype_append(TRANSFORM_OT_delete_orientation);
}
void ED_keymap_transform(wmKeyConfig *keyconf)
{
- wmKeyMap *modalmap = transform_modal_keymap(keyconf);
+ wmKeyMap *modalmap = transform_modal_keymap(keyconf);
- TransformModeItem *tmode;
+ TransformModeItem *tmode;
- for (tmode = transform_modes; tmode->idname; tmode++) {
- WM_modalkeymap_assign(modalmap, tmode->idname);
- }
- WM_modalkeymap_assign(modalmap, "TRANSFORM_OT_transform");
+ for (tmode = transform_modes; tmode->idname; tmode++) {
+ WM_modalkeymap_assign(modalmap, tmode->idname);
+ }
+ WM_modalkeymap_assign(modalmap, "TRANSFORM_OT_transform");
}
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index b486976bfad..18b19d903c4 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -58,194 +58,207 @@
void BIF_clearTransformOrientation(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- ListBase *transform_orientations = &scene->transform_spaces;
-
- BLI_freelistN(transform_orientations);
-
- for (int i = 0; i < ARRAY_SIZE(scene->orientation_slots); i++) {
- TransformOrientationSlot *orient_slot = &scene->orientation_slots[i];
- if (orient_slot->type == V3D_ORIENT_CUSTOM) {
- orient_slot->type = V3D_ORIENT_GLOBAL; /* fallback to global */
- orient_slot->index_custom = -1;
- }
- }
+ Scene *scene = CTX_data_scene(C);
+ ListBase *transform_orientations = &scene->transform_spaces;
+
+ BLI_freelistN(transform_orientations);
+
+ for (int i = 0; i < ARRAY_SIZE(scene->orientation_slots); i++) {
+ TransformOrientationSlot *orient_slot = &scene->orientation_slots[i];
+ if (orient_slot->type == V3D_ORIENT_CUSTOM) {
+ orient_slot->type = V3D_ORIENT_GLOBAL; /* fallback to global */
+ orient_slot->index_custom = -1;
+ }
+ }
}
static TransformOrientation *findOrientationName(ListBase *lb, const char *name)
{
- return BLI_findstring(lb, name, offsetof(TransformOrientation, name));
+ return BLI_findstring(lb, name, offsetof(TransformOrientation, name));
}
static bool uniqueOrientationNameCheck(void *arg, const char *name)
{
- return findOrientationName((ListBase *)arg, name) != NULL;
+ return findOrientationName((ListBase *)arg, name) != NULL;
}
static void uniqueOrientationName(ListBase *lb, char *name)
{
- BLI_uniquename_cb(uniqueOrientationNameCheck, lb, CTX_DATA_(BLT_I18NCONTEXT_ID_SCENE, "Space"), '.', name,
- sizeof(((TransformOrientation *)NULL)->name));
+ BLI_uniquename_cb(uniqueOrientationNameCheck,
+ lb,
+ CTX_DATA_(BLT_I18NCONTEXT_ID_SCENE, "Space"),
+ '.',
+ name,
+ sizeof(((TransformOrientation *)NULL)->name));
}
-static TransformOrientation *createViewSpace(bContext *C, ReportList *UNUSED(reports),
- const char *name, const bool overwrite)
+static TransformOrientation *createViewSpace(bContext *C,
+ ReportList *UNUSED(reports),
+ const char *name,
+ const bool overwrite)
{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- float mat[3][3];
-
- if (!rv3d)
- return NULL;
-
- copy_m3_m4(mat, rv3d->viewinv);
- normalize_m3(mat);
-
- if (name[0] == 0) {
- View3D *v3d = CTX_wm_view3d(C);
- if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
- /* If an object is used as camera, then this space is the same as object space! */
- name = v3d->camera->id.name + 2;
- }
- else {
- name = "Custom View";
- }
- }
-
- return addMatrixSpace(C, mat, name, overwrite);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float mat[3][3];
+
+ if (!rv3d)
+ return NULL;
+
+ copy_m3_m4(mat, rv3d->viewinv);
+ normalize_m3(mat);
+
+ if (name[0] == 0) {
+ View3D *v3d = CTX_wm_view3d(C);
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ /* If an object is used as camera, then this space is the same as object space! */
+ name = v3d->camera->id.name + 2;
+ }
+ else {
+ name = "Custom View";
+ }
+ }
+
+ return addMatrixSpace(C, mat, name, overwrite);
}
-static TransformOrientation *createObjectSpace(bContext *C, ReportList *UNUSED(reports),
- const char *name, const bool overwrite)
+static TransformOrientation *createObjectSpace(bContext *C,
+ ReportList *UNUSED(reports),
+ const char *name,
+ const bool overwrite)
{
- Base *base = CTX_data_active_base(C);
- Object *ob;
- float mat[3][3];
+ Base *base = CTX_data_active_base(C);
+ Object *ob;
+ float mat[3][3];
- if (base == NULL)
- return NULL;
+ if (base == NULL)
+ return NULL;
- ob = base->object;
+ ob = base->object;
- copy_m3_m4(mat, ob->obmat);
- normalize_m3(mat);
+ copy_m3_m4(mat, ob->obmat);
+ normalize_m3(mat);
- /* use object name if no name is given */
- if (name[0] == 0) {
- name = ob->id.name + 2;
- }
+ /* use object name if no name is given */
+ if (name[0] == 0) {
+ name = ob->id.name + 2;
+ }
- return addMatrixSpace(C, mat, name, overwrite);
+ return addMatrixSpace(C, mat, name, overwrite);
}
-static TransformOrientation *createBoneSpace(bContext *C, ReportList *reports,
- const char *name, const bool overwrite)
+static TransformOrientation *createBoneSpace(bContext *C,
+ ReportList *reports,
+ const char *name,
+ const bool overwrite)
{
- float mat[3][3];
- float normal[3], plane[3];
+ float mat[3][3];
+ float normal[3], plane[3];
- getTransformOrientation(C, normal, plane);
+ getTransformOrientation(C, normal, plane);
- if (createSpaceNormalTangent(mat, normal, plane) == 0) {
- BKE_reports_prepend(reports, "Cannot use zero-length bone");
- return NULL;
- }
+ if (createSpaceNormalTangent(mat, normal, plane) == 0) {
+ BKE_reports_prepend(reports, "Cannot use zero-length bone");
+ return NULL;
+ }
- if (name[0] == 0) {
- name = "Bone";
- }
+ if (name[0] == 0) {
+ name = "Bone";
+ }
- return addMatrixSpace(C, mat, name, overwrite);
+ return addMatrixSpace(C, mat, name, overwrite);
}
-static TransformOrientation *createCurveSpace(bContext *C, ReportList *reports,
- const char *name, const bool overwrite)
+static TransformOrientation *createCurveSpace(bContext *C,
+ ReportList *reports,
+ const char *name,
+ const bool overwrite)
{
- float mat[3][3];
- float normal[3], plane[3];
+ float mat[3][3];
+ float normal[3], plane[3];
- getTransformOrientation(C, normal, plane);
+ getTransformOrientation(C, normal, plane);
- if (createSpaceNormalTangent(mat, normal, plane) == 0) {
- BKE_reports_prepend(reports, "Cannot use zero-length curve");
- return NULL;
- }
+ if (createSpaceNormalTangent(mat, normal, plane) == 0) {
+ BKE_reports_prepend(reports, "Cannot use zero-length curve");
+ return NULL;
+ }
- if (name[0] == 0) {
- name = "Curve";
- }
+ if (name[0] == 0) {
+ name = "Curve";
+ }
- return addMatrixSpace(C, mat, name, overwrite);
+ return addMatrixSpace(C, mat, name, overwrite);
}
-
-static TransformOrientation *createMeshSpace(bContext *C, ReportList *reports,
- const char *name, const bool overwrite)
+static TransformOrientation *createMeshSpace(bContext *C,
+ ReportList *reports,
+ const char *name,
+ const bool overwrite)
{
- float mat[3][3];
- float normal[3], plane[3];
- int type;
-
- type = getTransformOrientation(C, normal, plane);
-
- switch (type) {
- case ORIENTATION_VERT:
- if (createSpaceNormal(mat, normal) == 0) {
- BKE_reports_prepend(reports, "Cannot use vertex with zero-length normal");
- return NULL;
- }
-
- if (name[0] == 0) {
- name = "Vertex";
- }
- break;
- case ORIENTATION_EDGE:
- if (createSpaceNormalTangent(mat, normal, plane) == 0) {
- BKE_reports_prepend(reports, "Cannot use zero-length edge");
- return NULL;
- }
-
- if (name[0] == 0) {
- name = "Edge";
- }
- break;
- case ORIENTATION_FACE:
- if (createSpaceNormalTangent(mat, normal, plane) == 0) {
- BKE_reports_prepend(reports, "Cannot use zero-area face");
- return NULL;
- }
-
- if (name[0] == 0) {
- name = "Face";
- }
- break;
- default:
- return NULL;
- }
-
- return addMatrixSpace(C, mat, name, overwrite);
+ float mat[3][3];
+ float normal[3], plane[3];
+ int type;
+
+ type = getTransformOrientation(C, normal, plane);
+
+ switch (type) {
+ case ORIENTATION_VERT:
+ if (createSpaceNormal(mat, normal) == 0) {
+ BKE_reports_prepend(reports, "Cannot use vertex with zero-length normal");
+ return NULL;
+ }
+
+ if (name[0] == 0) {
+ name = "Vertex";
+ }
+ break;
+ case ORIENTATION_EDGE:
+ if (createSpaceNormalTangent(mat, normal, plane) == 0) {
+ BKE_reports_prepend(reports, "Cannot use zero-length edge");
+ return NULL;
+ }
+
+ if (name[0] == 0) {
+ name = "Edge";
+ }
+ break;
+ case ORIENTATION_FACE:
+ if (createSpaceNormalTangent(mat, normal, plane) == 0) {
+ BKE_reports_prepend(reports, "Cannot use zero-area face");
+ return NULL;
+ }
+
+ if (name[0] == 0) {
+ name = "Face";
+ }
+ break;
+ default:
+ return NULL;
+ }
+
+ return addMatrixSpace(C, mat, name, overwrite);
}
bool createSpaceNormal(float mat[3][3], const float normal[3])
{
- float tangent[3] = {0.0f, 0.0f, 1.0f};
+ float tangent[3] = {0.0f, 0.0f, 1.0f};
- copy_v3_v3(mat[2], normal);
- if (normalize_v3(mat[2]) == 0.0f) {
- return false; /* error return */
- }
+ copy_v3_v3(mat[2], normal);
+ if (normalize_v3(mat[2]) == 0.0f) {
+ return false; /* error return */
+ }
- cross_v3_v3v3(mat[0], mat[2], tangent);
- if (is_zero_v3(mat[0])) {
- tangent[0] = 1.0f;
- tangent[1] = tangent[2] = 0.0f;
- cross_v3_v3v3(mat[0], tangent, mat[2]);
- }
+ cross_v3_v3v3(mat[0], mat[2], tangent);
+ if (is_zero_v3(mat[0])) {
+ tangent[0] = 1.0f;
+ tangent[1] = tangent[2] = 0.0f;
+ cross_v3_v3v3(mat[0], tangent, mat[2]);
+ }
- cross_v3_v3v3(mat[1], mat[2], mat[0]);
+ cross_v3_v3v3(mat[1], mat[2], mat[0]);
- normalize_m3(mat);
+ normalize_m3(mat);
- return true;
+ return true;
}
/**
@@ -255,902 +268,909 @@ bool createSpaceNormal(float mat[3][3], const float normal[3])
*/
bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const float tangent[3])
{
- if (normalize_v3_v3(mat[2], normal) == 0.0f) {
- return false; /* error return */
- }
+ if (normalize_v3_v3(mat[2], normal) == 0.0f) {
+ return false; /* error return */
+ }
- /* negate so we can use values from the matrix as input */
- negate_v3_v3(mat[1], tangent);
- /* preempt zero length tangent from causing trouble */
- if (is_zero_v3(mat[1])) {
- mat[1][2] = 1.0f;
- }
+ /* negate so we can use values from the matrix as input */
+ negate_v3_v3(mat[1], tangent);
+ /* preempt zero length tangent from causing trouble */
+ if (is_zero_v3(mat[1])) {
+ mat[1][2] = 1.0f;
+ }
- cross_v3_v3v3(mat[0], mat[2], mat[1]);
- if (normalize_v3(mat[0]) == 0.0f) {
- return false; /* error return */
- }
+ cross_v3_v3v3(mat[0], mat[2], mat[1]);
+ if (normalize_v3(mat[0]) == 0.0f) {
+ return false; /* error return */
+ }
- cross_v3_v3v3(mat[1], mat[2], mat[0]);
- normalize_v3(mat[1]);
+ cross_v3_v3v3(mat[1], mat[2], mat[0]);
+ normalize_v3(mat[1]);
- /* final matrix must be normalized, do inline */
- // normalize_m3(mat);
+ /* final matrix must be normalized, do inline */
+ // normalize_m3(mat);
- return true;
+ return true;
}
-void BIF_createTransformOrientation(bContext *C, ReportList *reports,
- const char *name, const bool use_view,
- const bool activate, const bool overwrite)
+void BIF_createTransformOrientation(bContext *C,
+ ReportList *reports,
+ const char *name,
+ const bool use_view,
+ const bool activate,
+ const bool overwrite)
{
- TransformOrientation *ts = NULL;
-
- if (use_view) {
- ts = createViewSpace(C, reports, name, overwrite);
- }
- else {
- Object *obedit = CTX_data_edit_object(C);
- Object *ob = CTX_data_active_object(C);
- if (obedit) {
- if (obedit->type == OB_MESH)
- ts = createMeshSpace(C, reports, name, overwrite);
- else if (obedit->type == OB_ARMATURE)
- ts = createBoneSpace(C, reports, name, overwrite);
- else if (obedit->type == OB_CURVE)
- ts = createCurveSpace(C, reports, name, overwrite);
- }
- else if (ob && (ob->mode & OB_MODE_POSE)) {
- ts = createBoneSpace(C, reports, name, overwrite);
- }
- else {
- ts = createObjectSpace(C, reports, name, overwrite);
- }
- }
-
- if (activate && ts != NULL) {
- BIF_selectTransformOrientation(C, ts);
- }
+ TransformOrientation *ts = NULL;
+
+ if (use_view) {
+ ts = createViewSpace(C, reports, name, overwrite);
+ }
+ else {
+ Object *obedit = CTX_data_edit_object(C);
+ Object *ob = CTX_data_active_object(C);
+ if (obedit) {
+ if (obedit->type == OB_MESH)
+ ts = createMeshSpace(C, reports, name, overwrite);
+ else if (obedit->type == OB_ARMATURE)
+ ts = createBoneSpace(C, reports, name, overwrite);
+ else if (obedit->type == OB_CURVE)
+ ts = createCurveSpace(C, reports, name, overwrite);
+ }
+ else if (ob && (ob->mode & OB_MODE_POSE)) {
+ ts = createBoneSpace(C, reports, name, overwrite);
+ }
+ else {
+ ts = createObjectSpace(C, reports, name, overwrite);
+ }
+ }
+
+ if (activate && ts != NULL) {
+ BIF_selectTransformOrientation(C, ts);
+ }
}
-TransformOrientation *addMatrixSpace(bContext *C, float mat[3][3],
- const char *name, const bool overwrite)
+TransformOrientation *addMatrixSpace(bContext *C,
+ float mat[3][3],
+ const char *name,
+ const bool overwrite)
{
- TransformOrientation *ts = NULL;
- Scene *scene = CTX_data_scene(C);
- ListBase *transform_orientations = &scene->transform_spaces;
- char name_unique[sizeof(ts->name)];
-
- if (overwrite) {
- ts = findOrientationName(transform_orientations, name);
- }
- else {
- BLI_strncpy(name_unique, name, sizeof(name_unique));
- uniqueOrientationName(transform_orientations, name_unique);
- name = name_unique;
- }
-
- /* if not, create a new one */
- if (ts == NULL) {
- ts = MEM_callocN(sizeof(TransformOrientation), "UserTransSpace from matrix");
- BLI_addtail(transform_orientations, ts);
- BLI_strncpy(ts->name, name, sizeof(ts->name));
- }
-
- /* copy matrix into transform space */
- copy_m3_m3(ts->mat, mat);
-
- return ts;
+ TransformOrientation *ts = NULL;
+ Scene *scene = CTX_data_scene(C);
+ ListBase *transform_orientations = &scene->transform_spaces;
+ char name_unique[sizeof(ts->name)];
+
+ if (overwrite) {
+ ts = findOrientationName(transform_orientations, name);
+ }
+ else {
+ BLI_strncpy(name_unique, name, sizeof(name_unique));
+ uniqueOrientationName(transform_orientations, name_unique);
+ name = name_unique;
+ }
+
+ /* if not, create a new one */
+ if (ts == NULL) {
+ ts = MEM_callocN(sizeof(TransformOrientation), "UserTransSpace from matrix");
+ BLI_addtail(transform_orientations, ts);
+ BLI_strncpy(ts->name, name, sizeof(ts->name));
+ }
+
+ /* copy matrix into transform space */
+ copy_m3_m3(ts->mat, mat);
+
+ return ts;
}
void BIF_removeTransformOrientation(bContext *C, TransformOrientation *target)
{
- BKE_scene_transform_orientation_remove(CTX_data_scene(C), target);
+ BKE_scene_transform_orientation_remove(CTX_data_scene(C), target);
}
void BIF_removeTransformOrientationIndex(bContext *C, int index)
{
- TransformOrientation *target = BKE_scene_transform_orientation_find(CTX_data_scene(C), index);
- BIF_removeTransformOrientation(C, target);
+ TransformOrientation *target = BKE_scene_transform_orientation_find(CTX_data_scene(C), index);
+ BIF_removeTransformOrientation(C, target);
}
void BIF_selectTransformOrientation(bContext *C, TransformOrientation *target)
{
- Scene *scene = CTX_data_scene(C);
- int index = BKE_scene_transform_orientation_get_index(scene, target);
+ Scene *scene = CTX_data_scene(C);
+ int index = BKE_scene_transform_orientation_get_index(scene, target);
- BLI_assert(index != -1);
+ BLI_assert(index != -1);
- scene->orientation_slots[SCE_ORIENT_DEFAULT].type = V3D_ORIENT_CUSTOM;
- scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom = index;
+ scene->orientation_slots[SCE_ORIENT_DEFAULT].type = V3D_ORIENT_CUSTOM;
+ scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom = index;
}
int BIF_countTransformOrientation(const bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- ListBase *transform_orientations = &scene->transform_spaces;
- return BLI_listbase_count(transform_orientations);
+ Scene *scene = CTX_data_scene(C);
+ ListBase *transform_orientations = &scene->transform_spaces;
+ return BLI_listbase_count(transform_orientations);
}
bool applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char *r_name)
{
- if (r_name) {
- BLI_strncpy(r_name, ts->name, MAX_NAME);
- }
- copy_m3_m3(r_mat, ts->mat);
+ if (r_name) {
+ BLI_strncpy(r_name, ts->name, MAX_NAME);
+ }
+ copy_m3_m3(r_mat, ts->mat);
- return true;
+ return true;
}
static int count_bone_select(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;
- do_next = do_it;
- if (do_it) {
- if (bone->layer & arm->layer) {
- if (bone->flag & BONE_SELECTED) {
- bone->flag |= BONE_TRANSFORM;
- total++;
-
- /* no transform on children if one parent bone is selected */
- do_next = false;
- }
- }
- }
- total += count_bone_select(arm, &bone->childbase, do_next);
- }
-
- return total;
+ Bone *bone;
+ bool do_next;
+ int total = 0;
+
+ for (bone = lb->first; bone; bone = bone->next) {
+ bone->flag &= ~BONE_TRANSFORM;
+ do_next = do_it;
+ if (do_it) {
+ if (bone->layer & arm->layer) {
+ if (bone->flag & BONE_SELECTED) {
+ bone->flag |= BONE_TRANSFORM;
+ total++;
+
+ /* no transform on children if one parent bone is selected */
+ do_next = false;
+ }
+ }
+ }
+ total += count_bone_select(arm, &bone->childbase, do_next);
+ }
+
+ return total;
}
void initTransformOrientation(bContext *C, TransInfo *t)
{
- Object *ob = CTX_data_active_object(C);
- Object *obedit = CTX_data_active_object(C);
-
- switch (t->orientation.user) {
- case V3D_ORIENT_GLOBAL:
- unit_m3(t->spacemtx);
- BLI_strncpy(t->spacename, IFACE_("global"), sizeof(t->spacename));
- break;
-
- case V3D_ORIENT_GIMBAL:
- unit_m3(t->spacemtx);
- if (ob && gimbal_axis(ob, t->spacemtx)) {
- BLI_strncpy(t->spacename, IFACE_("gimbal"), sizeof(t->spacename));
- break;
- }
- ATTR_FALLTHROUGH; /* no gimbal fallthrough to normal */
- case V3D_ORIENT_NORMAL:
- if (obedit || (ob && ob->mode & OB_MODE_POSE)) {
- BLI_strncpy(t->spacename, IFACE_("normal"), sizeof(t->spacename));
- ED_getTransformOrientationMatrix(C, t->spacemtx, t->around);
- break;
- }
- ATTR_FALLTHROUGH; /* we define 'normal' as 'local' in Object mode */
- case V3D_ORIENT_LOCAL:
- BLI_strncpy(t->spacename, IFACE_("local"), sizeof(t->spacename));
-
- if (ob) {
- copy_m3_m4(t->spacemtx, ob->obmat);
- normalize_m3(t->spacemtx);
- }
- else {
- unit_m3(t->spacemtx);
- }
-
- 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];
-
- BLI_strncpy(t->spacename, IFACE_("view"), sizeof(t->spacename));
- copy_m3_m4(mat, rv3d->viewinv);
- normalize_m3(mat);
- copy_m3_m3(t->spacemtx, mat);
- }
- else {
- unit_m3(t->spacemtx);
- }
- break;
- case V3D_ORIENT_CURSOR:
- {
- BLI_strncpy(t->spacename, IFACE_("cursor"), sizeof(t->spacename));
- ED_view3d_cursor3d_calc_mat3(t->scene, t->spacemtx);
- break;
- }
- case V3D_ORIENT_CUSTOM_MATRIX:
- /* Already set. */
- BLI_strncpy(t->spacename, IFACE_("custom"), sizeof(t->spacename));
- break;
- case V3D_ORIENT_CUSTOM:
- BLI_strncpy(t->spacename, t->orientation.custom->name, sizeof(t->spacename));
-
- if (applyTransformOrientation(t->orientation.custom, t->spacemtx, t->spacename)) {
- /* pass */
- }
- else {
- unit_m3(t->spacemtx);
- }
- break;
- }
-
- 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);
- }
+ Object *ob = CTX_data_active_object(C);
+ Object *obedit = CTX_data_active_object(C);
+
+ switch (t->orientation.user) {
+ case V3D_ORIENT_GLOBAL:
+ unit_m3(t->spacemtx);
+ BLI_strncpy(t->spacename, IFACE_("global"), sizeof(t->spacename));
+ break;
+
+ case V3D_ORIENT_GIMBAL:
+ unit_m3(t->spacemtx);
+ if (ob && gimbal_axis(ob, t->spacemtx)) {
+ BLI_strncpy(t->spacename, IFACE_("gimbal"), sizeof(t->spacename));
+ break;
+ }
+ ATTR_FALLTHROUGH; /* no gimbal fallthrough to normal */
+ case V3D_ORIENT_NORMAL:
+ if (obedit || (ob && ob->mode & OB_MODE_POSE)) {
+ BLI_strncpy(t->spacename, IFACE_("normal"), sizeof(t->spacename));
+ ED_getTransformOrientationMatrix(C, t->spacemtx, t->around);
+ break;
+ }
+ ATTR_FALLTHROUGH; /* we define 'normal' as 'local' in Object mode */
+ case V3D_ORIENT_LOCAL:
+ BLI_strncpy(t->spacename, IFACE_("local"), sizeof(t->spacename));
+
+ if (ob) {
+ copy_m3_m4(t->spacemtx, ob->obmat);
+ normalize_m3(t->spacemtx);
+ }
+ else {
+ unit_m3(t->spacemtx);
+ }
+
+ 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];
+
+ BLI_strncpy(t->spacename, IFACE_("view"), sizeof(t->spacename));
+ copy_m3_m4(mat, rv3d->viewinv);
+ normalize_m3(mat);
+ copy_m3_m3(t->spacemtx, mat);
+ }
+ else {
+ unit_m3(t->spacemtx);
+ }
+ break;
+ case V3D_ORIENT_CURSOR: {
+ BLI_strncpy(t->spacename, IFACE_("cursor"), sizeof(t->spacename));
+ ED_view3d_cursor3d_calc_mat3(t->scene, t->spacemtx);
+ break;
+ }
+ case V3D_ORIENT_CUSTOM_MATRIX:
+ /* Already set. */
+ BLI_strncpy(t->spacename, IFACE_("custom"), sizeof(t->spacename));
+ break;
+ case V3D_ORIENT_CUSTOM:
+ BLI_strncpy(t->spacename, t->orientation.custom->name, sizeof(t->spacename));
+
+ if (applyTransformOrientation(t->orientation.custom, t->spacemtx, t->spacename)) {
+ /* pass */
+ }
+ else {
+ unit_m3(t->spacemtx);
+ }
+ break;
+ }
+
+ 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)
+ BMesh *bm, BMElem **elems, const unsigned int n, const BMIterType itype, const char htype)
{
- BMIter iter;
- BMElem *ele;
- unsigned int 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));
-
- if (!BLI_listbase_is_empty(&bm->selected)) {
- /* quick check */
- BMEditSelection *ese;
- i = 0;
- for (ese = bm->selected.last; ese; ese = ese->prev) {
- /* shouldn't need this check */
- if (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT)) {
-
- /* only use contiguous selection */
- if (ese->htype != htype) {
- i = 0;
- break;
- }
-
- elems[i++] = ese->ele;
- if (n == i) {
- break;
- }
- }
- else {
- BLI_assert(0);
- }
- }
-
- if (i == 0) {
- /* pass */
- }
- else if (i == n) {
- return i;
- }
- }
-
- i = 0;
- BM_ITER_MESH (ele, &iter, bm, itype) {
- BLI_assert(ele->head.htype == htype);
- if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
- elems[i++] = ele;
- if (n == i) {
- break;
- }
- }
- }
-
- return i;
+ BMIter iter;
+ BMElem *ele;
+ unsigned int 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));
+
+ if (!BLI_listbase_is_empty(&bm->selected)) {
+ /* quick check */
+ BMEditSelection *ese;
+ i = 0;
+ for (ese = bm->selected.last; ese; ese = ese->prev) {
+ /* shouldn't need this check */
+ if (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT)) {
+
+ /* only use contiguous selection */
+ if (ese->htype != htype) {
+ i = 0;
+ break;
+ }
+
+ elems[i++] = ese->ele;
+ if (n == i) {
+ break;
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+
+ if (i == 0) {
+ /* pass */
+ }
+ else if (i == n) {
+ return i;
+ }
+ }
+
+ i = 0;
+ BM_ITER_MESH (ele, &iter, bm, itype) {
+ BLI_assert(ele->head.htype == htype);
+ if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+ elems[i++] = ele;
+ if (n == i) {
+ break;
+ }
+ }
+ }
+
+ return i;
}
static unsigned int bm_mesh_verts_select_get_n(BMesh *bm, BMVert **elems, const unsigned int n)
{
- return bm_mesh_elems_select_get_n__internal(
- bm, (BMElem **)elems, min_ii(n, bm->totvertsel),
- BM_VERTS_OF_MESH, BM_VERT);
+ 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)
{
- return bm_mesh_elems_select_get_n__internal(
- bm, (BMElem **)elems, min_ii(n, bm->totedgesel),
- BM_EDGES_OF_MESH, BM_EDGE);
+ 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)
{
- return bm_mesh_elems_select_get_n__internal(
- bm, (BMElem **)elems, min_ii(n, bm->totfacesel),
- BM_FACES_OF_MESH, BM_FACE);
+ return bm_mesh_elems_select_get_n__internal(
+ bm, (BMElem **)elems, min_ii(n, bm->totfacesel),
+ BM_FACES_OF_MESH, BM_FACE);
}
#endif
-int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3], const short around)
+int getTransformOrientation_ex(const bContext *C,
+ float normal[3],
+ float plane[3],
+ const short around)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- Object *obedit = CTX_data_edit_object(C);
- Base *base;
- Object *ob = OBACT(view_layer);
- int result = ORIENTATION_NONE;
- const bool activeOnly = (around == V3D_AROUND_ACTIVE);
-
- zero_v3(normal);
- zero_v3(plane);
-
- if (obedit) {
- float imat[3][3], mat[3][3];
-
- /* we need the transpose of the inverse for a normal... */
- copy_m3_m4(imat, ob->obmat);
-
- invert_m3_m3(mat, imat);
- transpose_m3(mat);
-
- ob = obedit;
-
- if (ob->type == OB_MESH) {
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMEditSelection ese;
- float vec[3] = {0, 0, 0};
-
- /* USE LAST SELECTED WITH ACTIVE */
- if (activeOnly && BM_select_history_active_get(em->bm, &ese)) {
- BM_editselection_normal(&ese, normal);
- BM_editselection_plane(&ese, plane);
-
- switch (ese.htype) {
- case BM_VERT:
- result = ORIENTATION_VERT;
- break;
- case BM_EDGE:
- result = ORIENTATION_EDGE;
- break;
- case BM_FACE:
- result = ORIENTATION_FACE;
- break;
- }
- }
- else {
- if (em->bm->totfacesel >= 1) {
- BMFace *efa;
- BMIter iter;
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- BM_face_calc_tangent_auto(efa, vec);
- add_v3_v3(normal, efa->no);
- add_v3_v3(plane, vec);
- }
- }
-
- result = ORIENTATION_FACE;
- }
- else if (em->bm->totvertsel == 3) {
- BMVert *v_tri[3];
-
- if (bm_mesh_verts_select_get_n(em->bm, v_tri, 3) == 3) {
- BMEdge *e = NULL;
- float no_test[3];
-
- normal_tri_v3(normal, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co);
-
- /* check if the normal is pointing opposite to vert normals */
- no_test[0] = v_tri[0]->no[0] + v_tri[1]->no[0] + v_tri[2]->no[0];
- no_test[1] = v_tri[0]->no[1] + v_tri[1]->no[1] + v_tri[2]->no[1];
- no_test[2] = v_tri[0]->no[2] + v_tri[1]->no[2] + v_tri[2]->no[2];
- if (dot_v3v3(no_test, normal) < 0.0f) {
- negate_v3(normal);
- }
-
- if (em->bm->totedgesel >= 1) {
- /* find an edge that's apart of v_tri (no need to search all edges) */
- float e_length;
- int j;
-
- for (j = 0; j < 3; j++) {
- BMEdge *e_test = BM_edge_exists(v_tri[j], v_tri[(j + 1) % 3]);
- if (e_test && BM_elem_flag_test(e_test, BM_ELEM_SELECT)) {
- const float e_test_length = BM_edge_calc_length_squared(e_test);
- if ((e == NULL) || (e_length < e_test_length)) {
- e = e_test;
- e_length = e_test_length;
- }
- }
- }
- }
-
- if (e) {
- BMVert *v_pair[2];
- if (BM_edge_is_boundary(e)) {
- BM_edge_ordered_verts(e, &v_pair[0], &v_pair[1]);
- }
- else {
- v_pair[0] = e->v1;
- v_pair[1] = e->v2;
- }
- sub_v3_v3v3(plane, v_pair[0]->co, v_pair[1]->co);
- }
- else {
- BM_vert_tri_calc_tangent_edge(v_tri, plane);
- }
- }
- else {
- BLI_assert(0);
- }
-
- result = ORIENTATION_FACE;
- }
- else if (em->bm->totedgesel == 1 || em->bm->totvertsel == 2) {
- BMVert *v_pair[2] = {NULL, NULL};
- BMEdge *eed = NULL;
-
- if (em->bm->totedgesel == 1) {
- if (bm_mesh_edges_select_get_n(em->bm, &eed, 1) == 1) {
- v_pair[0] = eed->v1;
- v_pair[1] = eed->v2;
- }
- }
- else {
- BLI_assert(em->bm->totvertsel == 2);
- bm_mesh_verts_select_get_n(em->bm, v_pair, 2);
- }
-
- /* should never fail */
- if (LIKELY(v_pair[0] && v_pair[1])) {
- bool v_pair_swap = false;
- /**
- * Logic explained:
- *
- * - Edges and vert-pairs treated the same way.
- * - Point the Y axis along the edge vector (towards the active vertex).
- * - Point the Z axis outwards (the same direction as the normals).
- *
- * \note Z points outwards - along the normal.
- * take care making changes here, see: T38592, T43708
- */
-
- /* be deterministic where possible and ensure v_pair[0] is active */
- if (BM_mesh_active_vert_get(em->bm) == v_pair[1]) {
- v_pair_swap = true;
- }
- else if (eed && BM_edge_is_boundary(eed)) {
- /* predictable direction for boundary edges */
- if (eed->l->v != v_pair[0]) {
- v_pair_swap = true;
- }
- }
-
- if (v_pair_swap) {
- SWAP(BMVert *, v_pair[0], v_pair[1]);
- }
-
- add_v3_v3v3(normal, v_pair[1]->no, v_pair[0]->no);
- sub_v3_v3v3(plane, v_pair[1]->co, v_pair[0]->co);
-
- if (normalize_v3(plane) != 0.0f) {
- /* For edges it'd important the resulting matrix can rotate around the edge,
- * project onto the plane so we can use a fallback value. */
- project_plane_normalized_v3_v3v3(normal, normal, plane);
- if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
- /* in the case the normal and plane are aligned,
- * use a fallback normal which is orthogonal to the plane. */
- ortho_v3_v3(normal, plane);
- }
- }
- }
-
- result = ORIENTATION_EDGE;
- }
- else if (em->bm->totvertsel == 1) {
- BMVert *v = NULL;
-
- if (bm_mesh_verts_select_get_n(em->bm, &v, 1) == 1) {
- copy_v3_v3(normal, v->no);
- BMEdge *e_pair[2];
-
- if (BM_vert_edge_pair(v, &e_pair[0], &e_pair[1])) {
- bool v_pair_swap = false;
- BMVert *v_pair[2] = {BM_edge_other_vert(e_pair[0], v), BM_edge_other_vert(e_pair[1], v)};
- float dir_pair[2][3];
-
- if (BM_edge_is_boundary(e_pair[0])) {
- if (e_pair[0]->l->v != v) {
- v_pair_swap = true;
- }
- }
- else {
- if (BM_edge_calc_length_squared(e_pair[0]) < BM_edge_calc_length_squared(e_pair[1])) {
- v_pair_swap = true;
- }
- }
-
- if (v_pair_swap) {
- SWAP(BMVert *, v_pair[0], v_pair[1]);
- }
-
- sub_v3_v3v3(dir_pair[0], v->co, v_pair[0]->co);
- sub_v3_v3v3(dir_pair[1], v_pair[1]->co, v->co);
- normalize_v3(dir_pair[0]);
- normalize_v3(dir_pair[1]);
-
- add_v3_v3v3(plane, dir_pair[0], dir_pair[1]);
- }
- }
-
- result = is_zero_v3(plane) ? ORIENTATION_VERT : ORIENTATION_EDGE;
- }
- else if (em->bm->totvertsel > 3) {
- BMIter iter;
- BMVert *v;
-
- zero_v3(normal);
-
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- add_v3_v3(normal, v->no);
- }
- }
- normalize_v3(normal);
- result = ORIENTATION_VERT;
- }
- }
-
- /* not needed but this matches 2.68 and older behavior */
- negate_v3(plane);
-
- } /* end editmesh */
- else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
- Curve *cu = obedit->data;
- Nurb *nu = NULL;
- int a;
- ListBase *nurbs = BKE_curve_editNurbs_get(cu);
-
- void *vert_act = NULL;
- if (activeOnly && BKE_curve_nurb_vert_active_get(cu, &nu, &vert_act)) {
- if (nu->type == CU_BEZIER) {
- BezTriple *bezt = vert_act;
- BKE_nurb_bezt_calc_normal(nu, bezt, normal);
- BKE_nurb_bezt_calc_plane(nu, bezt, plane);
- }
- else {
- BPoint *bp = vert_act;
- BKE_nurb_bpoint_calc_normal(nu, bp, normal);
- BKE_nurb_bpoint_calc_plane(nu, bp, plane);
- }
- }
- else {
- const bool use_handle = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) != 0;
-
- for (nu = nurbs->first; nu; nu = nu->next) {
- /* only bezier has a normal */
- if (nu->type == CU_BEZIER) {
- BezTriple *bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- short flag = 0;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Object *obedit = CTX_data_edit_object(C);
+ Base *base;
+ Object *ob = OBACT(view_layer);
+ int result = ORIENTATION_NONE;
+ const bool activeOnly = (around == V3D_AROUND_ACTIVE);
+
+ zero_v3(normal);
+ zero_v3(plane);
+
+ if (obedit) {
+ float imat[3][3], mat[3][3];
+
+ /* we need the transpose of the inverse for a normal... */
+ copy_m3_m4(imat, ob->obmat);
+
+ invert_m3_m3(mat, imat);
+ transpose_m3(mat);
+
+ ob = obedit;
+
+ if (ob->type == OB_MESH) {
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMEditSelection ese;
+ float vec[3] = {0, 0, 0};
+
+ /* USE LAST SELECTED WITH ACTIVE */
+ if (activeOnly && BM_select_history_active_get(em->bm, &ese)) {
+ BM_editselection_normal(&ese, normal);
+ BM_editselection_plane(&ese, plane);
+
+ switch (ese.htype) {
+ case BM_VERT:
+ result = ORIENTATION_VERT;
+ break;
+ case BM_EDGE:
+ result = ORIENTATION_EDGE;
+ break;
+ case BM_FACE:
+ result = ORIENTATION_FACE;
+ break;
+ }
+ }
+ else {
+ if (em->bm->totfacesel >= 1) {
+ BMFace *efa;
+ BMIter iter;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ BM_face_calc_tangent_auto(efa, vec);
+ add_v3_v3(normal, efa->no);
+ add_v3_v3(plane, vec);
+ }
+ }
+
+ result = ORIENTATION_FACE;
+ }
+ else if (em->bm->totvertsel == 3) {
+ BMVert *v_tri[3];
+
+ if (bm_mesh_verts_select_get_n(em->bm, v_tri, 3) == 3) {
+ BMEdge *e = NULL;
+ float no_test[3];
+
+ normal_tri_v3(normal, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co);
+
+ /* check if the normal is pointing opposite to vert normals */
+ no_test[0] = v_tri[0]->no[0] + v_tri[1]->no[0] + v_tri[2]->no[0];
+ no_test[1] = v_tri[0]->no[1] + v_tri[1]->no[1] + v_tri[2]->no[1];
+ no_test[2] = v_tri[0]->no[2] + v_tri[1]->no[2] + v_tri[2]->no[2];
+ if (dot_v3v3(no_test, normal) < 0.0f) {
+ negate_v3(normal);
+ }
+
+ if (em->bm->totedgesel >= 1) {
+ /* find an edge that's apart of v_tri (no need to search all edges) */
+ float e_length;
+ int j;
+
+ for (j = 0; j < 3; j++) {
+ BMEdge *e_test = BM_edge_exists(v_tri[j], v_tri[(j + 1) % 3]);
+ if (e_test && BM_elem_flag_test(e_test, BM_ELEM_SELECT)) {
+ const float e_test_length = BM_edge_calc_length_squared(e_test);
+ if ((e == NULL) || (e_length < e_test_length)) {
+ e = e_test;
+ e_length = e_test_length;
+ }
+ }
+ }
+ }
+
+ if (e) {
+ BMVert *v_pair[2];
+ if (BM_edge_is_boundary(e)) {
+ BM_edge_ordered_verts(e, &v_pair[0], &v_pair[1]);
+ }
+ else {
+ v_pair[0] = e->v1;
+ v_pair[1] = e->v2;
+ }
+ sub_v3_v3v3(plane, v_pair[0]->co, v_pair[1]->co);
+ }
+ else {
+ BM_vert_tri_calc_tangent_edge(v_tri, plane);
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ result = ORIENTATION_FACE;
+ }
+ else if (em->bm->totedgesel == 1 || em->bm->totvertsel == 2) {
+ BMVert *v_pair[2] = {NULL, NULL};
+ BMEdge *eed = NULL;
+
+ if (em->bm->totedgesel == 1) {
+ if (bm_mesh_edges_select_get_n(em->bm, &eed, 1) == 1) {
+ v_pair[0] = eed->v1;
+ v_pair[1] = eed->v2;
+ }
+ }
+ else {
+ BLI_assert(em->bm->totvertsel == 2);
+ bm_mesh_verts_select_get_n(em->bm, v_pair, 2);
+ }
+
+ /* should never fail */
+ if (LIKELY(v_pair[0] && v_pair[1])) {
+ bool v_pair_swap = false;
+ /**
+ * Logic explained:
+ *
+ * - Edges and vert-pairs treated the same way.
+ * - Point the Y axis along the edge vector (towards the active vertex).
+ * - Point the Z axis outwards (the same direction as the normals).
+ *
+ * \note Z points outwards - along the normal.
+ * take care making changes here, see: T38592, T43708
+ */
+
+ /* be deterministic where possible and ensure v_pair[0] is active */
+ if (BM_mesh_active_vert_get(em->bm) == v_pair[1]) {
+ v_pair_swap = true;
+ }
+ else if (eed && BM_edge_is_boundary(eed)) {
+ /* predictable direction for boundary edges */
+ if (eed->l->v != v_pair[0]) {
+ v_pair_swap = true;
+ }
+ }
+
+ if (v_pair_swap) {
+ SWAP(BMVert *, v_pair[0], v_pair[1]);
+ }
+
+ add_v3_v3v3(normal, v_pair[1]->no, v_pair[0]->no);
+ sub_v3_v3v3(plane, v_pair[1]->co, v_pair[0]->co);
+
+ if (normalize_v3(plane) != 0.0f) {
+ /* For edges it'd important the resulting matrix can rotate around the edge,
+ * project onto the plane so we can use a fallback value. */
+ project_plane_normalized_v3_v3v3(normal, normal, plane);
+ if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
+ /* in the case the normal and plane are aligned,
+ * use a fallback normal which is orthogonal to the plane. */
+ ortho_v3_v3(normal, plane);
+ }
+ }
+ }
+
+ result = ORIENTATION_EDGE;
+ }
+ else if (em->bm->totvertsel == 1) {
+ BMVert *v = NULL;
+
+ if (bm_mesh_verts_select_get_n(em->bm, &v, 1) == 1) {
+ copy_v3_v3(normal, v->no);
+ BMEdge *e_pair[2];
+
+ if (BM_vert_edge_pair(v, &e_pair[0], &e_pair[1])) {
+ bool v_pair_swap = false;
+ BMVert *v_pair[2] = {BM_edge_other_vert(e_pair[0], v),
+ BM_edge_other_vert(e_pair[1], v)};
+ float dir_pair[2][3];
+
+ if (BM_edge_is_boundary(e_pair[0])) {
+ if (e_pair[0]->l->v != v) {
+ v_pair_swap = true;
+ }
+ }
+ else {
+ if (BM_edge_calc_length_squared(e_pair[0]) <
+ BM_edge_calc_length_squared(e_pair[1])) {
+ v_pair_swap = true;
+ }
+ }
+
+ if (v_pair_swap) {
+ SWAP(BMVert *, v_pair[0], v_pair[1]);
+ }
+
+ sub_v3_v3v3(dir_pair[0], v->co, v_pair[0]->co);
+ sub_v3_v3v3(dir_pair[1], v_pair[1]->co, v->co);
+ normalize_v3(dir_pair[0]);
+ normalize_v3(dir_pair[1]);
+
+ add_v3_v3v3(plane, dir_pair[0], dir_pair[1]);
+ }
+ }
+
+ result = is_zero_v3(plane) ? ORIENTATION_VERT : ORIENTATION_EDGE;
+ }
+ else if (em->bm->totvertsel > 3) {
+ BMIter iter;
+ BMVert *v;
+
+ zero_v3(normal);
+
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ add_v3_v3(normal, v->no);
+ }
+ }
+ normalize_v3(normal);
+ result = ORIENTATION_VERT;
+ }
+ }
+
+ /* not needed but this matches 2.68 and older behavior */
+ negate_v3(plane);
+
+ } /* end editmesh */
+ else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ Curve *cu = obedit->data;
+ Nurb *nu = NULL;
+ int a;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+
+ void *vert_act = NULL;
+ if (activeOnly && BKE_curve_nurb_vert_active_get(cu, &nu, &vert_act)) {
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt = vert_act;
+ BKE_nurb_bezt_calc_normal(nu, bezt, normal);
+ BKE_nurb_bezt_calc_plane(nu, bezt, plane);
+ }
+ else {
+ BPoint *bp = vert_act;
+ BKE_nurb_bpoint_calc_normal(nu, bp, normal);
+ BKE_nurb_bpoint_calc_plane(nu, bp, plane);
+ }
+ }
+ else {
+ const bool use_handle = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) != 0;
+
+ for (nu = nurbs->first; nu; nu = nu->next) {
+ /* only bezier has a normal */
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ short flag = 0;
#define SEL_F1 (1 << 0)
#define SEL_F2 (1 << 1)
#define SEL_F3 (1 << 2)
- if (use_handle) {
- if (bezt->f1 & SELECT) flag |= SEL_F1;
- if (bezt->f2 & SELECT) flag |= SEL_F2;
- if (bezt->f3 & SELECT) flag |= SEL_F3;
- }
- else {
- flag = (bezt->f2 & SELECT) ? (SEL_F1 | SEL_F2 | SEL_F3) : 0;
- }
-
- /* exception */
- if (flag) {
- float tvec[3];
- if ((around == V3D_AROUND_LOCAL_ORIGINS) ||
- ELEM(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3))
- {
- BKE_nurb_bezt_calc_normal(nu, bezt, tvec);
- add_v3_v3(normal, tvec);
- }
- else {
- /* ignore bezt->f2 in this case */
- if (flag & SEL_F1) {
- sub_v3_v3v3(tvec, bezt->vec[0], bezt->vec[1]);
- normalize_v3(tvec);
- add_v3_v3(normal, tvec);
- }
- if (flag & SEL_F3) {
- sub_v3_v3v3(tvec, bezt->vec[1], bezt->vec[2]);
- normalize_v3(tvec);
- add_v3_v3(normal, tvec);
- }
- }
-
- BKE_nurb_bezt_calc_plane(nu, bezt, tvec);
- add_v3_v3(plane, tvec);
- }
+ if (use_handle) {
+ if (bezt->f1 & SELECT)
+ flag |= SEL_F1;
+ if (bezt->f2 & SELECT)
+ flag |= SEL_F2;
+ if (bezt->f3 & SELECT)
+ flag |= SEL_F3;
+ }
+ else {
+ flag = (bezt->f2 & SELECT) ? (SEL_F1 | SEL_F2 | SEL_F3) : 0;
+ }
+
+ /* exception */
+ if (flag) {
+ float tvec[3];
+ if ((around == V3D_AROUND_LOCAL_ORIGINS) ||
+ ELEM(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3)) {
+ BKE_nurb_bezt_calc_normal(nu, bezt, tvec);
+ add_v3_v3(normal, tvec);
+ }
+ else {
+ /* ignore bezt->f2 in this case */
+ if (flag & SEL_F1) {
+ sub_v3_v3v3(tvec, bezt->vec[0], bezt->vec[1]);
+ normalize_v3(tvec);
+ add_v3_v3(normal, tvec);
+ }
+ if (flag & SEL_F3) {
+ sub_v3_v3v3(tvec, bezt->vec[1], bezt->vec[2]);
+ normalize_v3(tvec);
+ add_v3_v3(normal, tvec);
+ }
+ }
+
+ BKE_nurb_bezt_calc_plane(nu, bezt, tvec);
+ add_v3_v3(plane, tvec);
+ }
#undef SEL_F1
#undef SEL_F2
#undef SEL_F3
- bezt++;
- }
- }
- else if (nu->bp && (nu->pntsv == 1)) {
- BPoint *bp = nu->bp;
- a = nu->pntsu;
- while (a--) {
- if (bp->f1 & SELECT) {
- float tvec[3];
-
- BPoint *bp_prev = BKE_nurb_bpoint_get_prev(nu, bp);
- BPoint *bp_next = BKE_nurb_bpoint_get_next(nu, bp);
-
- const bool is_prev_sel = bp_prev && (bp_prev->f1 & SELECT);
- const bool is_next_sel = bp_next && (bp_next->f1 & SELECT);
- if (is_prev_sel == false && is_next_sel == false) {
- /* Isolated, add based on surrounding */
- BKE_nurb_bpoint_calc_normal(nu, bp, tvec);
- add_v3_v3(normal, tvec);
- }
- else if (is_next_sel) {
- /* A segment, add the edge normal */
- sub_v3_v3v3(tvec, bp->vec, bp_next->vec);
- normalize_v3(tvec);
- add_v3_v3(normal, tvec);
- }
-
- BKE_nurb_bpoint_calc_plane(nu, bp, tvec);
- add_v3_v3(plane, tvec);
- }
- bp++;
- }
- }
- }
- }
-
- if (!is_zero_v3(normal)) {
- result = ORIENTATION_FACE;
- }
- }
- else if (obedit->type == OB_MBALL) {
- MetaBall *mb = obedit->data;
- MetaElem *ml;
- bool ok = false;
- float tmat[3][3];
-
- if (activeOnly && (ml = mb->lastelem)) {
- quat_to_mat3(tmat, ml->quat);
- add_v3_v3(normal, tmat[2]);
- add_v3_v3(plane, tmat[1]);
- ok = true;
- }
- else {
- for (ml = mb->editelems->first; ml; ml = ml->next) {
- if (ml->flag & SELECT) {
- quat_to_mat3(tmat, ml->quat);
- add_v3_v3(normal, tmat[2]);
- add_v3_v3(plane, tmat[1]);
- ok = true;
- }
- }
- }
-
- if (ok) {
- if (!is_zero_v3(plane)) {
- result = ORIENTATION_FACE;
- }
- }
- }
- else if (obedit->type == OB_ARMATURE) {
- bArmature *arm = obedit->data;
- EditBone *ebone;
- bool ok = false;
- float tmat[3][3];
-
- if (activeOnly && (ebone = arm->act_edbone)) {
- ED_armature_ebone_to_mat3(ebone, tmat);
- add_v3_v3(normal, tmat[2]);
- add_v3_v3(plane, tmat[1]);
- ok = true;
- }
- else {
- /* When we only have the root/tip are selected. */
- bool fallback_ok = false;
- float fallback_normal[3];
- float fallback_plane[3];
-
- zero_v3(fallback_normal);
- zero_v3(fallback_plane);
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (arm->layer & ebone->layer) {
- if (ebone->flag & BONE_SELECTED) {
- ED_armature_ebone_to_mat3(ebone, tmat);
- add_v3_v3(normal, tmat[2]);
- add_v3_v3(plane, tmat[1]);
- ok = true;
- }
- else if ((ok == false) &&
- ((ebone->flag & BONE_TIPSEL) ||
- ((ebone->flag & BONE_ROOTSEL) &&
- (ebone->parent && ebone->flag & BONE_CONNECTED) == false)))
- {
- ED_armature_ebone_to_mat3(ebone, tmat);
- add_v3_v3(fallback_normal, tmat[2]);
- add_v3_v3(fallback_plane, tmat[1]);
- fallback_ok = true;
- }
- }
- }
- if ((ok == false) && fallback_ok) {
- ok = true;
- copy_v3_v3(normal, fallback_normal);
- copy_v3_v3(plane, fallback_plane);
- }
- }
-
- if (ok) {
- if (!is_zero_v3(plane)) {
- result = ORIENTATION_EDGE;
- }
- }
- }
-
- /* Vectors from edges don't need the special transpose inverse multiplication */
- if (result == ORIENTATION_EDGE) {
- float tvec[3];
-
- mul_mat3_m4_v3(ob->obmat, normal);
- mul_mat3_m4_v3(ob->obmat, plane);
-
- /* align normal to edge direction (so normal is perpendicular to the plane).
- * 'ORIENTATION_EDGE' will do the other way around.
- * This has to be done **after** applying obmat, see T45775! */
- project_v3_v3v3(tvec, normal, plane);
- sub_v3_v3(normal, tvec);
- }
- else {
- mul_m3_v3(mat, normal);
- mul_m3_v3(mat, plane);
- }
- }
- else if (ob && (ob->mode & OB_MODE_POSE)) {
- bArmature *arm = ob->data;
- bPoseChannel *pchan;
- float imat[3][3], mat[3][3];
- bool ok = false;
-
- if (activeOnly && (pchan = BKE_pose_channel_active(ob))) {
- add_v3_v3(normal, pchan->pose_mat[2]);
- add_v3_v3(plane, pchan->pose_mat[1]);
- ok = true;
- }
- else {
- int totsel;
-
- totsel = count_bone_select(arm, &arm->bonebase, true);
- if (totsel) {
- /* use channels to get stats */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) {
- add_v3_v3(normal, pchan->pose_mat[2]);
- add_v3_v3(plane, pchan->pose_mat[1]);
- }
- }
- ok = true;
- }
- }
-
- /* use for both active & all */
- if (ok) {
- /* we need the transpose of the inverse for a normal... */
- copy_m3_m4(imat, ob->obmat);
-
- invert_m3_m3(mat, imat);
- transpose_m3(mat);
- mul_m3_v3(mat, normal);
- mul_m3_v3(mat, plane);
-
- result = ORIENTATION_EDGE;
- }
- }
- else if (ob && (ob->mode & (OB_MODE_ALL_PAINT | OB_MODE_PARTICLE_EDIT))) {
- /* pass */
- }
- else {
- /* we need the one selected object, if its not active */
- base = BASACT(view_layer);
- ob = OBACT(view_layer);
- if (base && ((base->flag & BASE_SELECTED) != 0)) {
- /* pass */
- }
- else {
- /* first selected */
- ob = NULL;
- for (base = view_layer->object_bases.first; base; base = base->next) {
- if (BASE_SELECTED_EDITABLE(v3d, base)) {
- ob = base->object;
- break;
- }
- }
- }
-
- if (ob) {
- copy_v3_v3(normal, ob->obmat[2]);
- copy_v3_v3(plane, ob->obmat[1]);
- }
- result = ORIENTATION_NORMAL;
- }
-
- return result;
+ bezt++;
+ }
+ }
+ else if (nu->bp && (nu->pntsv == 1)) {
+ BPoint *bp = nu->bp;
+ a = nu->pntsu;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ float tvec[3];
+
+ BPoint *bp_prev = BKE_nurb_bpoint_get_prev(nu, bp);
+ BPoint *bp_next = BKE_nurb_bpoint_get_next(nu, bp);
+
+ const bool is_prev_sel = bp_prev && (bp_prev->f1 & SELECT);
+ const bool is_next_sel = bp_next && (bp_next->f1 & SELECT);
+ if (is_prev_sel == false && is_next_sel == false) {
+ /* Isolated, add based on surrounding */
+ BKE_nurb_bpoint_calc_normal(nu, bp, tvec);
+ add_v3_v3(normal, tvec);
+ }
+ else if (is_next_sel) {
+ /* A segment, add the edge normal */
+ sub_v3_v3v3(tvec, bp->vec, bp_next->vec);
+ normalize_v3(tvec);
+ add_v3_v3(normal, tvec);
+ }
+
+ BKE_nurb_bpoint_calc_plane(nu, bp, tvec);
+ add_v3_v3(plane, tvec);
+ }
+ bp++;
+ }
+ }
+ }
+ }
+
+ if (!is_zero_v3(normal)) {
+ result = ORIENTATION_FACE;
+ }
+ }
+ else if (obedit->type == OB_MBALL) {
+ MetaBall *mb = obedit->data;
+ MetaElem *ml;
+ bool ok = false;
+ float tmat[3][3];
+
+ if (activeOnly && (ml = mb->lastelem)) {
+ quat_to_mat3(tmat, ml->quat);
+ add_v3_v3(normal, tmat[2]);
+ add_v3_v3(plane, tmat[1]);
+ ok = true;
+ }
+ else {
+ for (ml = mb->editelems->first; ml; ml = ml->next) {
+ if (ml->flag & SELECT) {
+ quat_to_mat3(tmat, ml->quat);
+ add_v3_v3(normal, tmat[2]);
+ add_v3_v3(plane, tmat[1]);
+ ok = true;
+ }
+ }
+ }
+
+ if (ok) {
+ if (!is_zero_v3(plane)) {
+ result = ORIENTATION_FACE;
+ }
+ }
+ }
+ else if (obedit->type == OB_ARMATURE) {
+ bArmature *arm = obedit->data;
+ EditBone *ebone;
+ bool ok = false;
+ float tmat[3][3];
+
+ if (activeOnly && (ebone = arm->act_edbone)) {
+ ED_armature_ebone_to_mat3(ebone, tmat);
+ add_v3_v3(normal, tmat[2]);
+ add_v3_v3(plane, tmat[1]);
+ ok = true;
+ }
+ else {
+ /* When we only have the root/tip are selected. */
+ bool fallback_ok = false;
+ float fallback_normal[3];
+ float fallback_plane[3];
+
+ zero_v3(fallback_normal);
+ zero_v3(fallback_plane);
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (arm->layer & ebone->layer) {
+ if (ebone->flag & BONE_SELECTED) {
+ ED_armature_ebone_to_mat3(ebone, tmat);
+ add_v3_v3(normal, tmat[2]);
+ add_v3_v3(plane, tmat[1]);
+ ok = true;
+ }
+ else if ((ok == false) &&
+ ((ebone->flag & BONE_TIPSEL) ||
+ ((ebone->flag & BONE_ROOTSEL) &&
+ (ebone->parent && ebone->flag & BONE_CONNECTED) == false))) {
+ ED_armature_ebone_to_mat3(ebone, tmat);
+ add_v3_v3(fallback_normal, tmat[2]);
+ add_v3_v3(fallback_plane, tmat[1]);
+ fallback_ok = true;
+ }
+ }
+ }
+ if ((ok == false) && fallback_ok) {
+ ok = true;
+ copy_v3_v3(normal, fallback_normal);
+ copy_v3_v3(plane, fallback_plane);
+ }
+ }
+
+ if (ok) {
+ if (!is_zero_v3(plane)) {
+ result = ORIENTATION_EDGE;
+ }
+ }
+ }
+
+ /* Vectors from edges don't need the special transpose inverse multiplication */
+ if (result == ORIENTATION_EDGE) {
+ float tvec[3];
+
+ mul_mat3_m4_v3(ob->obmat, normal);
+ mul_mat3_m4_v3(ob->obmat, plane);
+
+ /* align normal to edge direction (so normal is perpendicular to the plane).
+ * 'ORIENTATION_EDGE' will do the other way around.
+ * This has to be done **after** applying obmat, see T45775! */
+ project_v3_v3v3(tvec, normal, plane);
+ sub_v3_v3(normal, tvec);
+ }
+ else {
+ mul_m3_v3(mat, normal);
+ mul_m3_v3(mat, plane);
+ }
+ }
+ else if (ob && (ob->mode & OB_MODE_POSE)) {
+ bArmature *arm = ob->data;
+ bPoseChannel *pchan;
+ float imat[3][3], mat[3][3];
+ bool ok = false;
+
+ if (activeOnly && (pchan = BKE_pose_channel_active(ob))) {
+ add_v3_v3(normal, pchan->pose_mat[2]);
+ add_v3_v3(plane, pchan->pose_mat[1]);
+ ok = true;
+ }
+ else {
+ int totsel;
+
+ totsel = count_bone_select(arm, &arm->bonebase, true);
+ if (totsel) {
+ /* use channels to get stats */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) {
+ add_v3_v3(normal, pchan->pose_mat[2]);
+ add_v3_v3(plane, pchan->pose_mat[1]);
+ }
+ }
+ ok = true;
+ }
+ }
+
+ /* use for both active & all */
+ if (ok) {
+ /* we need the transpose of the inverse for a normal... */
+ copy_m3_m4(imat, ob->obmat);
+
+ invert_m3_m3(mat, imat);
+ transpose_m3(mat);
+ mul_m3_v3(mat, normal);
+ mul_m3_v3(mat, plane);
+
+ result = ORIENTATION_EDGE;
+ }
+ }
+ else if (ob && (ob->mode & (OB_MODE_ALL_PAINT | OB_MODE_PARTICLE_EDIT))) {
+ /* pass */
+ }
+ else {
+ /* we need the one selected object, if its not active */
+ base = BASACT(view_layer);
+ ob = OBACT(view_layer);
+ if (base && ((base->flag & BASE_SELECTED) != 0)) {
+ /* pass */
+ }
+ else {
+ /* first selected */
+ ob = NULL;
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTED_EDITABLE(v3d, base)) {
+ ob = base->object;
+ break;
+ }
+ }
+ }
+
+ if (ob) {
+ copy_v3_v3(normal, ob->obmat[2]);
+ copy_v3_v3(plane, ob->obmat[1]);
+ }
+ result = ORIENTATION_NORMAL;
+ }
+
+ return result;
}
int getTransformOrientation(const bContext *C, float normal[3], float plane[3])
{
- /* dummy value, not V3D_AROUND_ACTIVE and not V3D_AROUND_LOCAL_ORIGINS */
- short around = V3D_AROUND_CENTER_BOUNDS;
+ /* dummy value, not V3D_AROUND_ACTIVE and not V3D_AROUND_LOCAL_ORIGINS */
+ short around = V3D_AROUND_CENTER_BOUNDS;
- return getTransformOrientation_ex(C, normal, plane, around);
+ return getTransformOrientation_ex(C, normal, plane, around);
}
-void ED_getTransformOrientationMatrix(const bContext *C, float orientation_mat[3][3], const short around)
+void ED_getTransformOrientationMatrix(const bContext *C,
+ float orientation_mat[3][3],
+ const short around)
{
- float normal[3] = {0.0, 0.0, 0.0};
- float plane[3] = {0.0, 0.0, 0.0};
-
- int type;
-
- type = getTransformOrientation_ex(C, normal, plane, around);
-
- /* Fallback, when the plane can't be calculated. */
- if (ORIENTATION_USE_PLANE(type) && is_zero_v3(plane)) {
- type = ORIENTATION_VERT;
- }
-
- switch (type) {
- case ORIENTATION_NORMAL:
- if (createSpaceNormalTangent(orientation_mat, normal, plane) == 0) {
- type = ORIENTATION_NONE;
- }
- break;
- case ORIENTATION_VERT:
- if (createSpaceNormal(orientation_mat, normal) == 0) {
- type = ORIENTATION_NONE;
- }
- break;
- case ORIENTATION_EDGE:
- if (createSpaceNormalTangent(orientation_mat, normal, plane) == 0) {
- type = ORIENTATION_NONE;
- }
- break;
- case ORIENTATION_FACE:
- if (createSpaceNormalTangent(orientation_mat, normal, plane) == 0) {
- type = ORIENTATION_NONE;
- }
- break;
- default:
- BLI_assert(type == ORIENTATION_NONE);
- break;
- }
-
- if (type == ORIENTATION_NONE) {
- unit_m3(orientation_mat);
- }
+ float normal[3] = {0.0, 0.0, 0.0};
+ float plane[3] = {0.0, 0.0, 0.0};
+
+ int type;
+
+ type = getTransformOrientation_ex(C, normal, plane, around);
+
+ /* Fallback, when the plane can't be calculated. */
+ if (ORIENTATION_USE_PLANE(type) && is_zero_v3(plane)) {
+ type = ORIENTATION_VERT;
+ }
+
+ switch (type) {
+ case ORIENTATION_NORMAL:
+ if (createSpaceNormalTangent(orientation_mat, normal, plane) == 0) {
+ type = ORIENTATION_NONE;
+ }
+ break;
+ case ORIENTATION_VERT:
+ if (createSpaceNormal(orientation_mat, normal) == 0) {
+ type = ORIENTATION_NONE;
+ }
+ break;
+ case ORIENTATION_EDGE:
+ if (createSpaceNormalTangent(orientation_mat, normal, plane) == 0) {
+ type = ORIENTATION_NONE;
+ }
+ break;
+ case ORIENTATION_FACE:
+ if (createSpaceNormalTangent(orientation_mat, normal, plane) == 0) {
+ type = ORIENTATION_NONE;
+ }
+ break;
+ default:
+ BLI_assert(type == ORIENTATION_NONE);
+ break;
+ }
+
+ if (type == ORIENTATION_NONE) {
+ unit_m3(orientation_mat);
+ }
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 305b17949c8..d9cc9e3fcee 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -30,7 +30,7 @@
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
-#include "DNA_meshdata_types.h" /* Temporary, for snapping to other unselected meshes */
+#include "DNA_meshdata_types.h" /* Temporary, for snapping to other unselected meshes */
#include "DNA_node_types.h"
#include "DNA_space_types.h"
#include "DNA_screen_types.h"
@@ -46,7 +46,7 @@
#include "BKE_layer.h"
#include "BKE_object.h"
-#include "BKE_anim.h" /* for duplis */
+#include "BKE_anim.h" /* for duplis */
#include "BKE_context.h"
#include "BKE_editmesh.h"
#include "BKE_sequencer.h"
@@ -96,7 +96,6 @@ static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3])
static float TranslationBetween(TransInfo *t, const float p1[3], const float p2[3]);
static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3]);
-
/****************** IMPLEMENTATIONS *********************/
static bool snapNodeTest(View2D *v2d, bNode *node, eSnapSelect snap_select);
@@ -105,1506 +104,1534 @@ static NodeBorder snapNodeBorder(int snap_node_mode);
#if 0
int BIF_snappingSupported(Object *obedit)
{
- int status = 0;
+ int status = 0;
- /* only support object mesh, armature, curves */
- if (obedit == NULL || ELEM(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) {
- status = 1;
- }
+ /* only support object mesh, armature, curves */
+ if (obedit == NULL || ELEM(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) {
+ status = 1;
+ }
- return status;
+ return status;
}
#endif
bool validSnap(const TransInfo *t)
{
- return (t->tsnap.status & (POINT_INIT | TARGET_INIT)) == (POINT_INIT | TARGET_INIT) ||
- (t->tsnap.status & (MULTI_POINTS | TARGET_INIT)) == (MULTI_POINTS | TARGET_INIT);
+ return (t->tsnap.status & (POINT_INIT | TARGET_INIT)) == (POINT_INIT | TARGET_INIT) ||
+ (t->tsnap.status & (MULTI_POINTS | TARGET_INIT)) == (MULTI_POINTS | TARGET_INIT);
}
bool activeSnap(const TransInfo *t)
{
- return ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP) ||
- ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP_INVERT);
+ return ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP) ||
+ ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP_INVERT);
}
bool transformModeUseSnap(const TransInfo *t)
{
- ToolSettings *ts = t->settings;
- if (t->mode == TFM_TRANSLATION) {
- return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_TRANSLATE) != 0;
- }
- if (t->mode == TFM_ROTATION) {
- return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_ROTATE) != 0;
- }
- if (t->mode == TFM_RESIZE) {
- return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_SCALE) != 0;
- }
-
- return false;
+ ToolSettings *ts = t->settings;
+ if (t->mode == TFM_TRANSLATION) {
+ return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_TRANSLATE) != 0;
+ }
+ if (t->mode == TFM_ROTATION) {
+ return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_ROTATE) != 0;
+ }
+ if (t->mode == TFM_RESIZE) {
+ return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_SCALE) != 0;
+ }
+
+ return false;
}
static bool doForceIncrementSnap(const TransInfo *t)
{
- return !transformModeUseSnap(t);
+ return !transformModeUseSnap(t);
}
void drawSnapping(const struct bContext *C, TransInfo *t)
{
- unsigned char col[4], selectedCol[4], activeCol[4];
+ unsigned char col[4], selectedCol[4], activeCol[4];
- if (!activeSnap(t))
- return;
+ if (!activeSnap(t))
+ return;
- UI_GetThemeColor3ubv(TH_TRANSFORM, col);
- col[3] = 128;
+ UI_GetThemeColor3ubv(TH_TRANSFORM, col);
+ col[3] = 128;
- UI_GetThemeColor3ubv(TH_SELECT, selectedCol);
- selectedCol[3] = 128;
+ UI_GetThemeColor3ubv(TH_SELECT, selectedCol);
+ selectedCol[3] = 128;
- UI_GetThemeColor3ubv(TH_ACTIVE, activeCol);
- activeCol[3] = 192;
+ UI_GetThemeColor3ubv(TH_ACTIVE, activeCol);
+ activeCol[3] = 192;
- if (t->spacetype == SPACE_VIEW3D) {
- if (validSnap(t)) {
- TransSnapPoint *p;
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- float imat[4][4];
- float size;
+ if (t->spacetype == SPACE_VIEW3D) {
+ if (validSnap(t)) {
+ TransSnapPoint *p;
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float imat[4][4];
+ float size;
- GPU_depth_test(false);
+ GPU_depth_test(false);
- size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
+ size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
- invert_m4_m4(imat, rv3d->viewmat);
+ invert_m4_m4(imat, rv3d->viewmat);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- for (p = t->tsnap.points.first; p; p = p->next) {
- if (p == t->tsnap.selectedPoint) {
- immUniformColor4ubv(selectedCol);
- }
- else {
- immUniformColor4ubv(col);
- }
+ for (p = t->tsnap.points.first; p; p = p->next) {
+ if (p == t->tsnap.selectedPoint) {
+ immUniformColor4ubv(selectedCol);
+ }
+ else {
+ immUniformColor4ubv(col);
+ }
- imm_drawcircball(p->co, ED_view3d_pixel_size(rv3d, p->co) * size * 0.75f, imat, pos);
- }
+ imm_drawcircball(p->co, ED_view3d_pixel_size(rv3d, p->co) * size * 0.75f, imat, pos);
+ }
- if (t->tsnap.status & POINT_INIT) {
- immUniformColor4ubv(activeCol);
+ if (t->tsnap.status & POINT_INIT) {
+ immUniformColor4ubv(activeCol);
- imm_drawcircball(t->tsnap.snapPoint, ED_view3d_pixel_size(rv3d, t->tsnap.snapPoint) * size, imat, pos);
- }
+ imm_drawcircball(
+ t->tsnap.snapPoint, ED_view3d_pixel_size(rv3d, t->tsnap.snapPoint) * size, imat, pos);
+ }
- /* draw normal if needed */
- if (usingSnappingNormal(t) && validSnappingNormal(t)) {
- immUniformColor4ubv(activeCol);
+ /* draw normal if needed */
+ if (usingSnappingNormal(t) && validSnappingNormal(t)) {
+ immUniformColor4ubv(activeCol);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3f(pos, t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]);
- immVertex3f(pos, t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0],
- t->tsnap.snapPoint[1] + t->tsnap.snapNormal[1],
- t->tsnap.snapPoint[2] + t->tsnap.snapNormal[2]);
- immEnd();
- }
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3f(pos, t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]);
+ immVertex3f(pos,
+ t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0],
+ t->tsnap.snapPoint[1] + t->tsnap.snapNormal[1],
+ t->tsnap.snapPoint[2] + t->tsnap.snapNormal[2]);
+ immEnd();
+ }
- immUnbindProgram();
+ immUnbindProgram();
- GPU_depth_test(true);
- }
- }
- else if (t->spacetype == SPACE_IMAGE) {
- if (validSnap(t)) {
- /* This will not draw, and Im nor sure why - campbell */
- /* TODO: see 2.7x for non-working code */
- }
- }
- else if (t->spacetype == SPACE_NODE) {
- if (validSnap(t)) {
- ARegion *ar = CTX_wm_region(C);
- TransSnapPoint *p;
- float size;
+ GPU_depth_test(true);
+ }
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ if (validSnap(t)) {
+ /* This will not draw, and Im nor sure why - campbell */
+ /* TODO: see 2.7x for non-working code */
+ }
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ if (validSnap(t)) {
+ ARegion *ar = CTX_wm_region(C);
+ TransSnapPoint *p;
+ float size;
- size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
+ size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
- GPU_blend(true);
+ GPU_blend(true);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- for (p = t->tsnap.points.first; p; p = p->next) {
- if (p == t->tsnap.selectedPoint) {
- immUniformColor4ubv(selectedCol);
- }
- else {
- immUniformColor4ubv(col);
- }
+ for (p = t->tsnap.points.first; p; p = p->next) {
+ if (p == t->tsnap.selectedPoint) {
+ immUniformColor4ubv(selectedCol);
+ }
+ else {
+ immUniformColor4ubv(col);
+ }
- ED_node_draw_snap(&ar->v2d, p->co, size, 0, pos);
- }
+ ED_node_draw_snap(&ar->v2d, p->co, size, 0, pos);
+ }
- if (t->tsnap.status & POINT_INIT) {
- immUniformColor4ubv(activeCol);
+ 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(&ar->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder, pos);
+ }
- immUnbindProgram();
+ immUnbindProgram();
- GPU_blend(false);
- }
- }
+ GPU_blend(false);
+ }
+ }
}
eRedrawFlag handleSnapping(TransInfo *t, const wmEvent *event)
{
- eRedrawFlag status = TREDRAW_NOTHING;
-
-#if 0 // XXX need a proper selector for all snap mode
- if (BIF_snappingSupported(t->obedit) && event->type == TABKEY && event->shift) {
- /* toggle snap and reinit */
- t->settings->snap_flag ^= SCE_SNAP;
- initSnapping(t, NULL);
- status = TREDRAW_HARD;
- }
+ eRedrawFlag status = TREDRAW_NOTHING;
+
+#if 0 // XXX need a proper selector for all snap mode
+ if (BIF_snappingSupported(t->obedit) && event->type == TABKEY && event->shift) {
+ /* toggle snap and reinit */
+ t->settings->snap_flag ^= SCE_SNAP;
+ initSnapping(t, NULL);
+ status = TREDRAW_HARD;
+ }
#endif
- if (event->type == MOUSEMOVE) {
- status |= updateSelectedSnapPoint(t);
- }
+ if (event->type == MOUSEMOVE) {
+ status |= updateSelectedSnapPoint(t);
+ }
- return status;
+ return status;
}
void applyProject(TransInfo *t)
{
- /* XXX FLICKER IN OBJECT MODE */
- if ((t->tsnap.project) && activeSnap(t) && (t->flag & T_NO_PROJECT) == 0) {
- float tvec[3];
- int i;
-
- FOREACH_TRANS_DATA_CONTAINER(t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- float iloc[3], loc[3], no[3];
- float mval_fl[2];
-
- if (td->flag & TD_NOACTION)
- break;
-
- if (td->flag & TD_SKIP)
- continue;
-
- if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f))
- continue;
-
- copy_v3_v3(iloc, td->loc);
- if (tc->use_local_mat) {
- mul_m4_v3(tc->mat, iloc);
- }
- else if (t->flag & T_OBJECT) {
- BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob);
- copy_v3_v3(iloc, td->ob->obmat[3]);
- }
-
- if (ED_view3d_project_float_global(t->ar, iloc, mval_fl, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- if (ED_transform_snap_object_project_view3d(
- t->tsnap.object_context,
- SCE_SNAP_MODE_FACE,
- &(const struct SnapObjectParams){
- .snap_select = t->tsnap.modeSelect,
- .use_object_edit_cage = (t->flag & T_EDIT) != 0,
- .use_occlusion_test = false,
- },
- mval_fl, 0, loc, no))
- {
+ /* XXX FLICKER IN OBJECT MODE */
+ if ((t->tsnap.project) && activeSnap(t) && (t->flag & T_NO_PROJECT) == 0) {
+ float tvec[3];
+ int i;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ float iloc[3], loc[3], no[3];
+ float mval_fl[2];
+
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f))
+ continue;
+
+ copy_v3_v3(iloc, td->loc);
+ if (tc->use_local_mat) {
+ mul_m4_v3(tc->mat, iloc);
+ }
+ else if (t->flag & T_OBJECT) {
+ BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob);
+ copy_v3_v3(iloc, td->ob->obmat[3]);
+ }
+
+ if (ED_view3d_project_float_global(t->ar, iloc, mval_fl, V3D_PROJ_TEST_NOP) ==
+ V3D_PROJ_RET_OK) {
+ if (ED_transform_snap_object_project_view3d(
+ t->tsnap.object_context,
+ SCE_SNAP_MODE_FACE,
+ &(const struct SnapObjectParams){
+ .snap_select = t->tsnap.modeSelect,
+ .use_object_edit_cage = (t->flag & T_EDIT) != 0,
+ .use_occlusion_test = false,
+ },
+ mval_fl,
+ 0,
+ loc,
+ no)) {
#if 0
- if (tc->use_local_mat) {
- mul_m4_v3(tc->imat, loc);
- }
+ if (tc->use_local_mat) {
+ mul_m4_v3(tc->imat, loc);
+ }
#endif
- sub_v3_v3v3(tvec, loc, iloc);
+ sub_v3_v3v3(tvec, loc, iloc);
- mul_m3_v3(td->smtx, tvec);
+ mul_m3_v3(td->smtx, tvec);
- add_v3_v3(td->loc, tvec);
+ add_v3_v3(td->loc, tvec);
- if (t->tsnap.align && (t->flag & T_OBJECT)) {
- /* handle alignment as well */
- const float *original_normal;
- float mat[3][3];
+ if (t->tsnap.align && (t->flag & T_OBJECT)) {
+ /* handle alignment as well */
+ const float *original_normal;
+ float mat[3][3];
- /* In pose mode, we want to align normals with Y axis of bones... */
- original_normal = td->axismtx[2];
+ /* In pose mode, we want to align normals with Y axis of bones... */
+ original_normal = td->axismtx[2];
- rotation_between_vecs_to_mat3(mat, original_normal, no);
+ rotation_between_vecs_to_mat3(mat, original_normal, no);
- transform_data_ext_rotate(td, mat, true);
+ transform_data_ext_rotate(td, mat, true);
- /* TODO support constraints for rotation too? see ElementRotation */
- }
- }
- }
+ /* TODO support constraints for rotation too? see ElementRotation */
+ }
+ }
+ }
- //XXX constraintTransLim(t, td);
- }
- }
- }
+ //XXX constraintTransLim(t, td);
+ }
+ }
+ }
}
void applyGridAbsolute(TransInfo *t)
{
- float grid_size = 0.0f;
- GearsType grid_action;
- int i;
-
- if (!(activeSnap(t) && (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID))))
- return;
-
- grid_action = BIG_GEARS;
- if (t->modifiers & MOD_PRECISION)
- grid_action = SMALL_GEARS;
-
- switch (grid_action) {
- case NO_GEARS: grid_size = t->snap_spatial[0]; break;
- case BIG_GEARS: grid_size = t->snap_spatial[1]; break;
- case SMALL_GEARS: grid_size = t->snap_spatial[2]; break;
- }
- /* early exit on unusable grid size */
- if (grid_size == 0.0f)
- return;
-
- FOREACH_TRANS_DATA_CONTAINER(t, tc) {
- TransData *td;
-
- for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
- float iloc[3], loc[3], tvec[3];
-
- if (td->flag & TD_NOACTION)
- break;
-
- if (td->flag & TD_SKIP)
- continue;
-
- if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f))
- continue;
-
- copy_v3_v3(iloc, td->loc);
- if (tc->use_local_mat) {
- mul_m4_v3(tc->mat, iloc);
- }
- else if (t->flag & T_OBJECT) {
- BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob);
- copy_v3_v3(iloc, td->ob->obmat[3]);
- }
-
- mul_v3_v3fl(loc, iloc, 1.0f / grid_size);
- loc[0] = roundf(loc[0]);
- loc[1] = roundf(loc[1]);
- loc[2] = roundf(loc[2]);
- mul_v3_fl(loc, grid_size);
-
- sub_v3_v3v3(tvec, loc, iloc);
- mul_m3_v3(td->smtx, tvec);
- add_v3_v3(td->loc, tvec);
- }
- }
+ float grid_size = 0.0f;
+ GearsType grid_action;
+ int i;
+
+ if (!(activeSnap(t) && (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID))))
+ return;
+
+ grid_action = BIG_GEARS;
+ if (t->modifiers & MOD_PRECISION)
+ grid_action = SMALL_GEARS;
+
+ switch (grid_action) {
+ case NO_GEARS:
+ grid_size = t->snap_spatial[0];
+ break;
+ case BIG_GEARS:
+ grid_size = t->snap_spatial[1];
+ break;
+ case SMALL_GEARS:
+ grid_size = t->snap_spatial[2];
+ break;
+ }
+ /* early exit on unusable grid size */
+ if (grid_size == 0.0f)
+ return;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td;
+
+ for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
+ float iloc[3], loc[3], tvec[3];
+
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f))
+ continue;
+
+ copy_v3_v3(iloc, td->loc);
+ if (tc->use_local_mat) {
+ mul_m4_v3(tc->mat, iloc);
+ }
+ else if (t->flag & T_OBJECT) {
+ BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob);
+ copy_v3_v3(iloc, td->ob->obmat[3]);
+ }
+
+ mul_v3_v3fl(loc, iloc, 1.0f / grid_size);
+ loc[0] = roundf(loc[0]);
+ loc[1] = roundf(loc[1]);
+ loc[2] = roundf(loc[2]);
+ mul_v3_fl(loc, grid_size);
+
+ sub_v3_v3v3(tvec, loc, iloc);
+ mul_m3_v3(td->smtx, tvec);
+ add_v3_v3(td->loc, tvec);
+ }
+ }
}
void applySnapping(TransInfo *t, float *vec)
{
- /* Each Trans Data already makes the snap to face */
- if (doForceIncrementSnap(t) ||
- (t->tsnap.project && t->tsnap.mode == SCE_SNAP_MODE_FACE))
- {
- return;
- }
-
- if (t->tsnap.status & SNAP_FORCED) {
- t->tsnap.targetSnap(t);
-
- t->tsnap.applySnap(t, vec);
- }
- else if (((t->tsnap.mode & ~(SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) != 0) &&
- activeSnap(t))
- {
- double current = PIL_check_seconds_timer();
-
- // Time base quirky code to go around findnearest slowness
- /* !TODO! add exception for object mode, no need to slow it down then */
- if (current - t->tsnap.last >= 0.01) {
- t->tsnap.calcSnap(t, vec);
- t->tsnap.targetSnap(t);
-
- t->tsnap.last = current;
- }
- if (validSnap(t)) {
- t->tsnap.applySnap(t, vec);
- }
- }
+ /* Each Trans Data already makes the snap to face */
+ if (doForceIncrementSnap(t) || (t->tsnap.project && t->tsnap.mode == SCE_SNAP_MODE_FACE)) {
+ return;
+ }
+
+ if (t->tsnap.status & SNAP_FORCED) {
+ t->tsnap.targetSnap(t);
+
+ t->tsnap.applySnap(t, vec);
+ }
+ else if (((t->tsnap.mode & ~(SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) != 0) &&
+ activeSnap(t)) {
+ double current = PIL_check_seconds_timer();
+
+ // Time base quirky code to go around findnearest slowness
+ /* !TODO! add exception for object mode, no need to slow it down then */
+ if (current - t->tsnap.last >= 0.01) {
+ t->tsnap.calcSnap(t, vec);
+ t->tsnap.targetSnap(t);
+
+ t->tsnap.last = current;
+ }
+ if (validSnap(t)) {
+ t->tsnap.applySnap(t, vec);
+ }
+ }
}
void resetSnapping(TransInfo *t)
{
- t->tsnap.status = 0;
- t->tsnap.align = false;
- t->tsnap.project = 0;
- t->tsnap.mode = 0;
- t->tsnap.modeSelect = 0;
- t->tsnap.target = 0;
- t->tsnap.last = 0;
- t->tsnap.applySnap = NULL;
-
- t->tsnap.snapNormal[0] = 0;
- t->tsnap.snapNormal[1] = 0;
- t->tsnap.snapNormal[2] = 0;
-
- t->tsnap.snapNodeBorder = 0;
+ t->tsnap.status = 0;
+ t->tsnap.align = false;
+ t->tsnap.project = 0;
+ t->tsnap.mode = 0;
+ t->tsnap.modeSelect = 0;
+ t->tsnap.target = 0;
+ t->tsnap.last = 0;
+ t->tsnap.applySnap = NULL;
+
+ t->tsnap.snapNormal[0] = 0;
+ t->tsnap.snapNormal[1] = 0;
+ t->tsnap.snapNormal[2] = 0;
+
+ t->tsnap.snapNodeBorder = 0;
}
bool usingSnappingNormal(const TransInfo *t)
{
- return t->tsnap.align;
+ return t->tsnap.align;
}
bool validSnappingNormal(const TransInfo *t)
{
- if (validSnap(t)) {
- if (!is_zero_v3(t->tsnap.snapNormal)) {
- return true;
- }
- }
+ if (validSnap(t)) {
+ if (!is_zero_v3(t->tsnap.snapNormal)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
static bool bm_edge_is_snap_target(BMEdge *e, void *UNUSED(user_data))
{
- if (BM_elem_flag_test(e, BM_ELEM_SELECT | BM_ELEM_HIDDEN) ||
- BM_elem_flag_test(e->v1, BM_ELEM_SELECT) ||
- BM_elem_flag_test(e->v2, BM_ELEM_SELECT))
- {
- return false;
- }
-
- return true;
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT | BM_ELEM_HIDDEN) ||
+ BM_elem_flag_test(e->v1, BM_ELEM_SELECT) || BM_elem_flag_test(e->v2, BM_ELEM_SELECT)) {
+ return false;
+ }
+
+ return true;
}
static bool bm_face_is_snap_target(BMFace *f, void *UNUSED(user_data))
{
- if (BM_elem_flag_test(f, BM_ELEM_SELECT | BM_ELEM_HIDDEN)) {
- return false;
- }
-
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
- return false;
- }
- } while ((l_iter = l_iter->next) != l_first);
-
- return true;
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT | BM_ELEM_HIDDEN)) {
+ return false;
+ }
+
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
+ return false;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ return true;
}
static void initSnappingMode(TransInfo *t)
{
- Main *bmain = CTX_data_main(t->context);
- ToolSettings *ts = t->settings;
- /* All obedit types will match. */
- const int obedit_type = t->data_container->obedit ? t->data_container->obedit->type : -1;
- ViewLayer *view_layer = t->view_layer;
- Base *base_act = view_layer->basact;
-
- if (t->spacetype == SPACE_NODE) {
- /* force project off when not supported */
- t->tsnap.project = 0;
-
- t->tsnap.mode = ts->snap_node_mode;
- }
- else if (t->spacetype == SPACE_IMAGE) {
- /* force project off when not supported */
- t->tsnap.project = 0;
-
- t->tsnap.mode = ts->snap_uv_mode;
- }
- else {
- /* force project off when not supported */
- if ((ts->snap_mode & SCE_SNAP_MODE_FACE) == 0)
- t->tsnap.project = 0;
-
- t->tsnap.mode = ts->snap_mode;
- }
-
- if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && /* Only 3D view or UV */
- (t->flag & T_CAMERA) == 0) /* Not with camera selected in camera view */
- {
- setSnappingCallback(t);
-
- /* Edit mode */
- if (t->tsnap.applySnap != NULL && // A snapping function actually exist
- ((obedit_type != -1) && ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) ) // Temporary limited to edit mode meshes, armature, curves, metaballs
- {
- /* Exclude editmesh if using proportional edit */
- if ((obedit_type == OB_MESH) && (t->flag & T_PROP_EDIT)) {
- t->tsnap.modeSelect = SNAP_NOT_ACTIVE;
- }
- else {
- t->tsnap.modeSelect = t->tsnap.snap_self ? SNAP_ALL : SNAP_NOT_ACTIVE;
- }
- }
- /* Particles edit mode*/
- else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
- ((obedit_type == -1) && base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT))
- {
- t->tsnap.modeSelect = SNAP_ALL;
- }
- /* Object mode */
- else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
- (obedit_type == -1) ) // Object Mode
- {
- /* In "Edit Strokes" mode, Snap tool can perform snap to selected or active objects (see T49632)
- * TODO: perform self snap in gpencil_strokes */
- t->tsnap.modeSelect = (
- ((t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR)) != 0) ?
- SNAP_ALL : SNAP_NOT_SELECTED);
- }
- else {
- /* Grid if snap is not possible */
- t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
- }
- }
- else if (t->spacetype == SPACE_NODE) {
- setSnappingCallback(t);
-
- if (t->tsnap.applySnap != NULL) {
- t->tsnap.modeSelect = SNAP_NOT_SELECTED;
- }
- else {
- /* Grid if snap is not possible */
- t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
- }
- }
- else if (t->spacetype == SPACE_SEQ) {
- /* We do our own snapping currently, so nothing here */
- t->tsnap.mode = SCE_SNAP_MODE_GRID; /* Dummy, should we rather add a NOP mode? */
- }
- else {
- /* Always grid outside of 3D view */
- t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
- }
-
- 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);
-
- ED_transform_snap_object_context_set_editmesh_callbacks(
- t->tsnap.object_context,
- (bool (*)(BMVert *, void *))BM_elem_cb_check_hflag_disabled,
- bm_edge_is_snap_target,
- bm_face_is_snap_target,
- POINTER_FROM_UINT((BM_ELEM_SELECT | BM_ELEM_HIDDEN)));
- }
- }
+ Main *bmain = CTX_data_main(t->context);
+ ToolSettings *ts = t->settings;
+ /* All obedit types will match. */
+ const int obedit_type = t->data_container->obedit ? t->data_container->obedit->type : -1;
+ ViewLayer *view_layer = t->view_layer;
+ Base *base_act = view_layer->basact;
+
+ if (t->spacetype == SPACE_NODE) {
+ /* force project off when not supported */
+ t->tsnap.project = 0;
+
+ t->tsnap.mode = ts->snap_node_mode;
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ /* force project off when not supported */
+ t->tsnap.project = 0;
+
+ t->tsnap.mode = ts->snap_uv_mode;
+ }
+ else {
+ /* force project off when not supported */
+ if ((ts->snap_mode & SCE_SNAP_MODE_FACE) == 0)
+ t->tsnap.project = 0;
+
+ t->tsnap.mode = ts->snap_mode;
+ }
+
+ if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && /* Only 3D view or UV */
+ (t->flag & T_CAMERA) == 0) /* Not with camera selected in camera view */
+ {
+ setSnappingCallback(t);
+
+ /* Edit mode */
+ if (t->tsnap.applySnap != NULL && // A snapping function actually exist
+ ((obedit_type != -1) &&
+ ELEM(obedit_type,
+ OB_MESH,
+ OB_ARMATURE,
+ OB_CURVE,
+ OB_LATTICE,
+ OB_MBALL))) // Temporary limited to edit mode meshes, armature, curves, metaballs
+ {
+ /* Exclude editmesh if using proportional edit */
+ if ((obedit_type == OB_MESH) && (t->flag & T_PROP_EDIT)) {
+ t->tsnap.modeSelect = SNAP_NOT_ACTIVE;
+ }
+ else {
+ t->tsnap.modeSelect = t->tsnap.snap_self ? SNAP_ALL : SNAP_NOT_ACTIVE;
+ }
+ }
+ /* Particles edit mode*/
+ else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
+ ((obedit_type == -1) && base_act && base_act->object &&
+ base_act->object->mode & OB_MODE_PARTICLE_EDIT)) {
+ t->tsnap.modeSelect = SNAP_ALL;
+ }
+ /* Object mode */
+ else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
+ (obedit_type == -1)) // Object Mode
+ {
+ /* In "Edit Strokes" mode, Snap tool can perform snap to selected or active objects (see T49632)
+ * TODO: perform self snap in gpencil_strokes */
+ t->tsnap.modeSelect = (((t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR)) != 0) ?
+ SNAP_ALL :
+ SNAP_NOT_SELECTED);
+ }
+ else {
+ /* Grid if snap is not possible */
+ t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
+ }
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ setSnappingCallback(t);
+
+ if (t->tsnap.applySnap != NULL) {
+ t->tsnap.modeSelect = SNAP_NOT_SELECTED;
+ }
+ else {
+ /* Grid if snap is not possible */
+ t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
+ }
+ }
+ else if (t->spacetype == SPACE_SEQ) {
+ /* We do our own snapping currently, so nothing here */
+ t->tsnap.mode = SCE_SNAP_MODE_GRID; /* Dummy, should we rather add a NOP mode? */
+ }
+ else {
+ /* Always grid outside of 3D view */
+ t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
+ }
+
+ 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);
+
+ ED_transform_snap_object_context_set_editmesh_callbacks(
+ t->tsnap.object_context,
+ (bool (*)(BMVert *, void *))BM_elem_cb_check_hflag_disabled,
+ bm_edge_is_snap_target,
+ bm_face_is_snap_target,
+ POINTER_FROM_UINT((BM_ELEM_SELECT | BM_ELEM_HIDDEN)));
+ }
+ }
}
void initSnapping(TransInfo *t, wmOperator *op)
{
- ToolSettings *ts = t->settings;
- short snap_target = t->settings->snap_target;
-
- resetSnapping(t);
-
- /* if snap property exists */
- if (op && RNA_struct_find_property(op->ptr, "snap") && RNA_struct_property_is_set(op->ptr, "snap")) {
- if (RNA_boolean_get(op->ptr, "snap")) {
- t->modifiers |= MOD_SNAP;
-
- if (RNA_struct_property_is_set(op->ptr, "snap_target")) {
- snap_target = RNA_enum_get(op->ptr, "snap_target");
- }
-
- if (RNA_struct_property_is_set(op->ptr, "snap_point")) {
- RNA_float_get_array(op->ptr, "snap_point", t->tsnap.snapPoint);
- t->tsnap.status |= SNAP_FORCED | POINT_INIT;
- }
-
- /* snap align only defined in specific cases */
- if (RNA_struct_find_property(op->ptr, "snap_align")) {
- t->tsnap.align = RNA_boolean_get(op->ptr, "snap_align");
- RNA_float_get_array(op->ptr, "snap_normal", t->tsnap.snapNormal);
- normalize_v3(t->tsnap.snapNormal);
- }
-
- if (RNA_struct_find_property(op->ptr, "use_snap_project")) {
- t->tsnap.project = RNA_boolean_get(op->ptr, "use_snap_project");
- }
-
- if (RNA_struct_find_property(op->ptr, "use_snap_self")) {
- t->tsnap.snap_self = RNA_boolean_get(op->ptr, "use_snap_self");
- }
- }
- }
- /* use scene defaults only when transform is modal */
- else if (t->flag & T_MODAL) {
- if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE)) {
- if (transformModeUseSnap(t) && (ts->snap_flag & SCE_SNAP)) {
- t->modifiers |= MOD_SNAP;
- }
-
- t->tsnap.align = ((t->settings->snap_flag & SCE_SNAP_ROTATE) != 0);
- t->tsnap.project = ((t->settings->snap_flag & SCE_SNAP_PROJECT) != 0);
- t->tsnap.snap_self = !((t->settings->snap_flag & SCE_SNAP_NO_SELF) != 0);
- t->tsnap.peel = ((t->settings->snap_flag & SCE_SNAP_PROJECT) != 0);
- }
-
- /* for now only 3d view (others can be added if we want) */
- if (t->spacetype == SPACE_VIEW3D) {
- t->tsnap.snap_spatial_grid = ((t->settings->snap_flag & SCE_SNAP_ABS_GRID) != 0);
- }
- }
-
- t->tsnap.target = snap_target;
-
- initSnappingMode(t);
+ ToolSettings *ts = t->settings;
+ short snap_target = t->settings->snap_target;
+
+ resetSnapping(t);
+
+ /* if snap property exists */
+ if (op && RNA_struct_find_property(op->ptr, "snap") &&
+ RNA_struct_property_is_set(op->ptr, "snap")) {
+ if (RNA_boolean_get(op->ptr, "snap")) {
+ t->modifiers |= MOD_SNAP;
+
+ if (RNA_struct_property_is_set(op->ptr, "snap_target")) {
+ snap_target = RNA_enum_get(op->ptr, "snap_target");
+ }
+
+ if (RNA_struct_property_is_set(op->ptr, "snap_point")) {
+ RNA_float_get_array(op->ptr, "snap_point", t->tsnap.snapPoint);
+ t->tsnap.status |= SNAP_FORCED | POINT_INIT;
+ }
+
+ /* snap align only defined in specific cases */
+ if (RNA_struct_find_property(op->ptr, "snap_align")) {
+ t->tsnap.align = RNA_boolean_get(op->ptr, "snap_align");
+ RNA_float_get_array(op->ptr, "snap_normal", t->tsnap.snapNormal);
+ normalize_v3(t->tsnap.snapNormal);
+ }
+
+ if (RNA_struct_find_property(op->ptr, "use_snap_project")) {
+ t->tsnap.project = RNA_boolean_get(op->ptr, "use_snap_project");
+ }
+
+ if (RNA_struct_find_property(op->ptr, "use_snap_self")) {
+ t->tsnap.snap_self = RNA_boolean_get(op->ptr, "use_snap_self");
+ }
+ }
+ }
+ /* use scene defaults only when transform is modal */
+ else if (t->flag & T_MODAL) {
+ if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE)) {
+ if (transformModeUseSnap(t) && (ts->snap_flag & SCE_SNAP)) {
+ t->modifiers |= MOD_SNAP;
+ }
+
+ t->tsnap.align = ((t->settings->snap_flag & SCE_SNAP_ROTATE) != 0);
+ t->tsnap.project = ((t->settings->snap_flag & SCE_SNAP_PROJECT) != 0);
+ t->tsnap.snap_self = !((t->settings->snap_flag & SCE_SNAP_NO_SELF) != 0);
+ t->tsnap.peel = ((t->settings->snap_flag & SCE_SNAP_PROJECT) != 0);
+ }
+
+ /* for now only 3d view (others can be added if we want) */
+ if (t->spacetype == SPACE_VIEW3D) {
+ t->tsnap.snap_spatial_grid = ((t->settings->snap_flag & SCE_SNAP_ABS_GRID) != 0);
+ }
+ }
+
+ t->tsnap.target = snap_target;
+
+ initSnappingMode(t);
}
void freeSnapping(TransInfo *t)
{
- if (t->tsnap.object_context) {
- ED_transform_snap_object_context_destroy(t->tsnap.object_context);
- t->tsnap.object_context = NULL;
- }
+ if (t->tsnap.object_context) {
+ ED_transform_snap_object_context_destroy(t->tsnap.object_context);
+ t->tsnap.object_context = NULL;
+ }
}
static void setSnappingCallback(TransInfo *t)
{
- t->tsnap.calcSnap = CalcSnapGeometry;
-
- switch (t->tsnap.target) {
- case SCE_SNAP_TARGET_CLOSEST:
- t->tsnap.targetSnap = TargetSnapClosest;
- break;
- case SCE_SNAP_TARGET_CENTER:
- t->tsnap.targetSnap = TargetSnapCenter;
- break;
- case SCE_SNAP_TARGET_MEDIAN:
- t->tsnap.targetSnap = TargetSnapMedian;
- break;
- case SCE_SNAP_TARGET_ACTIVE:
- t->tsnap.targetSnap = TargetSnapActive;
- break;
-
- }
-
- switch (t->mode) {
- case TFM_TRANSLATION:
- t->tsnap.applySnap = ApplySnapTranslation;
- t->tsnap.distance = TranslationBetween;
- break;
- case TFM_ROTATION:
- t->tsnap.applySnap = ApplySnapRotation;
- t->tsnap.distance = RotationBetween;
-
- // Can't do TARGET_CENTER with rotation, use TARGET_MEDIAN instead
- if (t->tsnap.target == SCE_SNAP_TARGET_CENTER) {
- t->tsnap.target = SCE_SNAP_TARGET_MEDIAN;
- t->tsnap.targetSnap = TargetSnapMedian;
- }
- break;
- case TFM_RESIZE:
- t->tsnap.applySnap = ApplySnapResize;
- t->tsnap.distance = ResizeBetween;
-
- // Can't do TARGET_CENTER with resize, use TARGET_MEDIAN instead
- if (t->tsnap.target == SCE_SNAP_TARGET_CENTER) {
- t->tsnap.target = SCE_SNAP_TARGET_MEDIAN;
- t->tsnap.targetSnap = TargetSnapMedian;
- }
- break;
- default:
- t->tsnap.applySnap = NULL;
- break;
- }
+ t->tsnap.calcSnap = CalcSnapGeometry;
+
+ switch (t->tsnap.target) {
+ case SCE_SNAP_TARGET_CLOSEST:
+ t->tsnap.targetSnap = TargetSnapClosest;
+ break;
+ case SCE_SNAP_TARGET_CENTER:
+ t->tsnap.targetSnap = TargetSnapCenter;
+ break;
+ case SCE_SNAP_TARGET_MEDIAN:
+ t->tsnap.targetSnap = TargetSnapMedian;
+ break;
+ case SCE_SNAP_TARGET_ACTIVE:
+ t->tsnap.targetSnap = TargetSnapActive;
+ break;
+ }
+
+ switch (t->mode) {
+ case TFM_TRANSLATION:
+ t->tsnap.applySnap = ApplySnapTranslation;
+ t->tsnap.distance = TranslationBetween;
+ break;
+ case TFM_ROTATION:
+ t->tsnap.applySnap = ApplySnapRotation;
+ t->tsnap.distance = RotationBetween;
+
+ // Can't do TARGET_CENTER with rotation, use TARGET_MEDIAN instead
+ if (t->tsnap.target == SCE_SNAP_TARGET_CENTER) {
+ t->tsnap.target = SCE_SNAP_TARGET_MEDIAN;
+ t->tsnap.targetSnap = TargetSnapMedian;
+ }
+ break;
+ case TFM_RESIZE:
+ t->tsnap.applySnap = ApplySnapResize;
+ t->tsnap.distance = ResizeBetween;
+
+ // Can't do TARGET_CENTER with resize, use TARGET_MEDIAN instead
+ if (t->tsnap.target == SCE_SNAP_TARGET_CENTER) {
+ t->tsnap.target = SCE_SNAP_TARGET_MEDIAN;
+ t->tsnap.targetSnap = TargetSnapMedian;
+ }
+ break;
+ default:
+ t->tsnap.applySnap = NULL;
+ break;
+ }
}
void addSnapPoint(TransInfo *t)
{
- /* Currently only 3D viewport works for snapping points. */
- if (t->tsnap.status & POINT_INIT && t->spacetype == SPACE_VIEW3D) {
- TransSnapPoint *p = MEM_callocN(sizeof(TransSnapPoint), "SnapPoint");
+ /* Currently only 3D viewport works for snapping points. */
+ if (t->tsnap.status & POINT_INIT && t->spacetype == SPACE_VIEW3D) {
+ TransSnapPoint *p = MEM_callocN(sizeof(TransSnapPoint), "SnapPoint");
- t->tsnap.selectedPoint = p;
+ t->tsnap.selectedPoint = p;
- copy_v3_v3(p->co, t->tsnap.snapPoint);
+ copy_v3_v3(p->co, t->tsnap.snapPoint);
- BLI_addtail(&t->tsnap.points, p);
+ BLI_addtail(&t->tsnap.points, p);
- t->tsnap.status |= MULTI_POINTS;
- }
+ t->tsnap.status |= MULTI_POINTS;
+ }
}
eRedrawFlag updateSelectedSnapPoint(TransInfo *t)
{
- eRedrawFlag status = TREDRAW_NOTHING;
+ eRedrawFlag status = TREDRAW_NOTHING;
- if (t->tsnap.status & MULTI_POINTS) {
- TransSnapPoint *p, *closest_p = NULL;
- float dist_min_sq = TRANSFORM_SNAP_MAX_PX;
- const float mval_fl[2] = {t->mval[0], t->mval[1]};
- float screen_loc[2];
+ if (t->tsnap.status & MULTI_POINTS) {
+ TransSnapPoint *p, *closest_p = NULL;
+ float dist_min_sq = TRANSFORM_SNAP_MAX_PX;
+ const float mval_fl[2] = {t->mval[0], t->mval[1]};
+ float screen_loc[2];
- for (p = t->tsnap.points.first; p; p = p->next) {
- float dist_sq;
+ 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) != V3D_PROJ_RET_OK) {
- continue;
- }
+ if (ED_view3d_project_float_global(t->ar, p->co, screen_loc, V3D_PROJ_TEST_NOP) !=
+ V3D_PROJ_RET_OK) {
+ continue;
+ }
- dist_sq = len_squared_v2v2(mval_fl, screen_loc);
+ dist_sq = len_squared_v2v2(mval_fl, screen_loc);
- if (dist_sq < dist_min_sq) {
- closest_p = p;
- dist_min_sq = dist_sq;
- }
- }
+ if (dist_sq < dist_min_sq) {
+ closest_p = p;
+ dist_min_sq = dist_sq;
+ }
+ }
- if (closest_p) {
- if (t->tsnap.selectedPoint != closest_p) {
- status = TREDRAW_HARD;
- }
+ if (closest_p) {
+ if (t->tsnap.selectedPoint != closest_p) {
+ status = TREDRAW_HARD;
+ }
- t->tsnap.selectedPoint = closest_p;
- }
- }
+ t->tsnap.selectedPoint = closest_p;
+ }
+ }
- return status;
+ return status;
}
void removeSnapPoint(TransInfo *t)
{
- if (t->tsnap.status & MULTI_POINTS) {
- updateSelectedSnapPoint(t);
-
- if (t->tsnap.selectedPoint) {
- BLI_freelinkN(&t->tsnap.points, t->tsnap.selectedPoint);
+ if (t->tsnap.status & MULTI_POINTS) {
+ updateSelectedSnapPoint(t);
- if (BLI_listbase_is_empty(&t->tsnap.points)) {
- t->tsnap.status &= ~MULTI_POINTS;
- }
+ if (t->tsnap.selectedPoint) {
+ BLI_freelinkN(&t->tsnap.points, t->tsnap.selectedPoint);
- t->tsnap.selectedPoint = NULL;
- }
+ if (BLI_listbase_is_empty(&t->tsnap.points)) {
+ t->tsnap.status &= ~MULTI_POINTS;
+ }
- }
+ t->tsnap.selectedPoint = NULL;
+ }
+ }
}
void getSnapPoint(const TransInfo *t, float vec[3])
{
- if (t->tsnap.points.first) {
- TransSnapPoint *p;
- int total = 0;
-
- vec[0] = vec[1] = vec[2] = 0;
-
- for (p = t->tsnap.points.first; p; p = p->next, total++) {
- add_v3_v3(vec, p->co);
- }
-
- if (t->tsnap.status & POINT_INIT) {
- add_v3_v3(vec, t->tsnap.snapPoint);
- total++;
- }
-
- mul_v3_fl(vec, 1.0f / total);
- }
- else {
- copy_v3_v3(vec, t->tsnap.snapPoint);
- }
+ if (t->tsnap.points.first) {
+ TransSnapPoint *p;
+ int total = 0;
+
+ vec[0] = vec[1] = vec[2] = 0;
+
+ for (p = t->tsnap.points.first; p; p = p->next, total++) {
+ add_v3_v3(vec, p->co);
+ }
+
+ if (t->tsnap.status & POINT_INIT) {
+ add_v3_v3(vec, t->tsnap.snapPoint);
+ total++;
+ }
+
+ mul_v3_fl(vec, 1.0f / total);
+ }
+ else {
+ copy_v3_v3(vec, t->tsnap.snapPoint);
+ }
}
/********************** APPLY **************************/
static void ApplySnapTranslation(TransInfo *t, float vec[3])
{
- float point[3];
- getSnapPoint(t, point);
-
- if (t->spacetype == SPACE_NODE) {
- char border = t->tsnap.snapNodeBorder;
- if (border & (NODE_LEFT | NODE_RIGHT))
- vec[0] = point[0] - t->tsnap.snapTarget[0];
- if (border & (NODE_BOTTOM | NODE_TOP))
- vec[1] = point[1] - t->tsnap.snapTarget[1];
- }
- 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) != V3D_PROJ_RET_OK) {
- zero_v3(point); /* no good answer here... */
- }
- }
- }
-
- sub_v3_v3v3(vec, point, t->tsnap.snapTarget);
- }
+ float point[3];
+ getSnapPoint(t, point);
+
+ if (t->spacetype == SPACE_NODE) {
+ char border = t->tsnap.snapNodeBorder;
+ if (border & (NODE_LEFT | NODE_RIGHT))
+ vec[0] = point[0] - t->tsnap.snapTarget[0];
+ if (border & (NODE_BOTTOM | NODE_TOP))
+ vec[1] = point[1] - t->tsnap.snapTarget[1];
+ }
+ 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) !=
+ V3D_PROJ_RET_OK) {
+ zero_v3(point); /* no good answer here... */
+ }
+ }
+ }
+
+ sub_v3_v3v3(vec, point, t->tsnap.snapTarget);
+ }
}
static void ApplySnapRotation(TransInfo *t, float *value)
{
- float point[3];
- getSnapPoint(t, point);
+ float point[3];
+ getSnapPoint(t, point);
- float dist = RotationBetween(t, t->tsnap.snapTarget, point);
- *value = dist;
+ float dist = RotationBetween(t, t->tsnap.snapTarget, point);
+ *value = dist;
}
static void ApplySnapResize(TransInfo *t, float vec[3])
{
- float point[3];
- getSnapPoint(t, point);
+ float point[3];
+ getSnapPoint(t, point);
- float dist = ResizeBetween(t, t->tsnap.snapTarget, point);
- if (dist != TRANSFORM_DIST_INVALID) {
- copy_v3_fl(vec, dist);
- }
+ float dist = ResizeBetween(t, t->tsnap.snapTarget, point);
+ if (dist != TRANSFORM_DIST_INVALID) {
+ copy_v3_fl(vec, dist);
+ }
}
/********************** DISTANCE **************************/
static float TranslationBetween(TransInfo *UNUSED(t), const float p1[3], const float p2[3])
{
- return len_squared_v3v3(p1, p2);
+ return len_squared_v3v3(p1, p2);
}
-static float RotationBetween(
- TransInfo *t, const float p1[3], const float p2[3])
+static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3])
{
- float angle, start[3], end[3];
+ float angle, start[3], end[3];
- sub_v3_v3v3(start, p1, t->center_global);
- sub_v3_v3v3(end, p2, t->center_global);
+ sub_v3_v3v3(start, p1, t->center_global);
+ sub_v3_v3v3(end, p2, t->center_global);
- // Angle around a constraint axis (error prone, will need debug)
- if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
- float axis[3], tmp[3];
+ // Angle around a constraint axis (error prone, will need debug)
+ if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
+ float axis[3], tmp[3];
- t->con.applyRot(t, NULL, NULL, axis, NULL);
+ t->con.applyRot(t, NULL, NULL, axis, NULL);
- project_v3_v3v3(tmp, end, axis);
- sub_v3_v3v3(end, end, tmp);
+ project_v3_v3v3(tmp, end, axis);
+ sub_v3_v3v3(end, end, tmp);
- project_v3_v3v3(tmp, start, axis);
- sub_v3_v3v3(start, start, tmp);
+ project_v3_v3v3(tmp, start, axis);
+ sub_v3_v3v3(start, start, tmp);
- normalize_v3(end);
- normalize_v3(start);
+ normalize_v3(end);
+ normalize_v3(start);
- cross_v3_v3v3(tmp, start, end);
+ cross_v3_v3v3(tmp, start, end);
- if (dot_v3v3(tmp, axis) < 0.0f)
- angle = -acosf(dot_v3v3(start, end));
- else
- angle = acosf(dot_v3v3(start, end));
- }
- else {
- float mtx[3][3];
+ if (dot_v3v3(tmp, axis) < 0.0f)
+ angle = -acosf(dot_v3v3(start, end));
+ else
+ angle = acosf(dot_v3v3(start, end));
+ }
+ else {
+ float mtx[3][3];
- copy_m3_m4(mtx, t->viewmat);
+ copy_m3_m4(mtx, t->viewmat);
- mul_m3_v3(mtx, end);
- mul_m3_v3(mtx, start);
+ mul_m3_v3(mtx, end);
+ mul_m3_v3(mtx, start);
- angle = atan2f(start[1], start[0]) - atan2f(end[1], end[0]);
- }
+ angle = atan2f(start[1], start[0]) - atan2f(end[1], end[0]);
+ }
- if (angle > (float)M_PI) {
- angle = angle - 2 * (float)M_PI;
- }
- else if (angle < -((float)M_PI)) {
- angle = 2.0f * (float)M_PI + angle;
- }
+ if (angle > (float)M_PI) {
+ angle = angle - 2 * (float)M_PI;
+ }
+ else if (angle < -((float)M_PI)) {
+ angle = 2.0f * (float)M_PI + angle;
+ }
- return angle;
+ return angle;
}
static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3])
{
- float d1[3], d2[3], len_d1;
+ float d1[3], d2[3], len_d1;
- sub_v3_v3v3(d1, p1, t->center_global);
- sub_v3_v3v3(d2, p2, t->center_global);
+ sub_v3_v3v3(d1, p1, t->center_global);
+ sub_v3_v3v3(d2, p2, t->center_global);
- if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
- mul_m3_v3(t->con.pmtx, d1);
- mul_m3_v3(t->con.pmtx, d2);
- }
+ if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
+ mul_m3_v3(t->con.pmtx, d1);
+ mul_m3_v3(t->con.pmtx, d2);
+ }
- project_v3_v3v3(d1, d1, d2);
+ project_v3_v3v3(d1, d1, d2);
- len_d1 = len_v3(d1);
+ len_d1 = len_v3(d1);
- /* Use 'invalid' dist when `center == p1` (after projecting),
- * in this case scale will _never_ move the point in relation to the center,
- * so it makes no sense to take it into account when scaling. see: T46503 */
- return len_d1 != 0.0f ? len_v3(d2) / len_d1 : TRANSFORM_DIST_INVALID;
+ /* Use 'invalid' dist when `center == p1` (after projecting),
+ * in this case scale will _never_ move the point in relation to the center,
+ * so it makes no sense to take it into account when scaling. see: T46503 */
+ return len_d1 != 0.0f ? len_v3(d2) / len_d1 : TRANSFORM_DIST_INVALID;
}
/********************** CALC **************************/
-static void UNUSED_FUNCTION(CalcSnapGrid) (TransInfo *t, float *UNUSED(vec))
+static void UNUSED_FUNCTION(CalcSnapGrid)(TransInfo *t, float *UNUSED(vec))
{
- snapGridIncrementAction(t, t->tsnap.snapPoint, BIG_GEARS);
+ snapGridIncrementAction(t, t->tsnap.snapPoint, BIG_GEARS);
}
static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
{
- if (t->spacetype == SPACE_VIEW3D) {
- float loc[3];
- float no[3];
- float mval[2];
- bool found = false;
- float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
-
- mval[0] = t->mval[0];
- mval[1] = t->mval[1];
-
- if (t->tsnap.mode &
- (SCE_SNAP_MODE_VERTEX |
- SCE_SNAP_MODE_EDGE |
- SCE_SNAP_MODE_FACE))
- {
- zero_v3(no); /* objects won't set this */
- found = snapObjectsTransform(
- t, mval, &dist_px,
- loc, no);
- }
- if ((found == false) && (t->tsnap.mode & SCE_SNAP_MODE_VOLUME)) {
- found = peelObjectsTransform(
- t, mval,
- (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0,
- loc, no, NULL);
- }
-
- if (found == true) {
- copy_v3_v3(t->tsnap.snapPoint, loc);
- copy_v3_v3(t->tsnap.snapNormal, no);
-
- t->tsnap.status |= POINT_INIT;
- }
- else {
- t->tsnap.status &= ~POINT_INIT;
- }
- }
- 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);
- float co[2];
-
- UI_view2d_region_to_view(&t->ar->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(
- t->view_layer, NULL, &objects_len);
-
- float dist_sq = FLT_MAX;
- if (ED_uvedit_nearest_uv_multi(t->scene, ima, objects, objects_len, co, &dist_sq, t->tsnap.snapPoint)) {
- t->tsnap.snapPoint[0] *= t->aspect[0];
- t->tsnap.snapPoint[1] *= t->aspect[1];
-
- t->tsnap.status |= POINT_INIT;
- }
- else {
- t->tsnap.status &= ~POINT_INIT;
- }
- MEM_freeN(objects);
- }
- }
- else if (t->spacetype == SPACE_NODE) {
- if (t->tsnap.mode & (SCE_SNAP_MODE_NODE_X | SCE_SNAP_MODE_NODE_Y)) {
- float loc[2];
- float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
- char node_border;
-
- if (snapNodesTransform(t, t->mval, loc, &dist_px, &node_border)) {
- copy_v2_v2(t->tsnap.snapPoint, loc);
- t->tsnap.snapNodeBorder = node_border;
-
- t->tsnap.status |= POINT_INIT;
- }
- else {
- t->tsnap.status &= ~POINT_INIT;
- }
- }
- }
+ if (t->spacetype == SPACE_VIEW3D) {
+ float loc[3];
+ float no[3];
+ float mval[2];
+ bool found = false;
+ float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
+
+ mval[0] = t->mval[0];
+ mval[1] = t->mval[1];
+
+ if (t->tsnap.mode & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE)) {
+ zero_v3(no); /* objects won't set this */
+ found = snapObjectsTransform(t, mval, &dist_px, loc, no);
+ }
+ if ((found == false) && (t->tsnap.mode & SCE_SNAP_MODE_VOLUME)) {
+ found = peelObjectsTransform(
+ t, mval, (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0, loc, no, NULL);
+ }
+
+ if (found == true) {
+ copy_v3_v3(t->tsnap.snapPoint, loc);
+ copy_v3_v3(t->tsnap.snapNormal, no);
+
+ t->tsnap.status |= POINT_INIT;
+ }
+ else {
+ t->tsnap.status &= ~POINT_INIT;
+ }
+ }
+ 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);
+ float co[2];
+
+ UI_view2d_region_to_view(&t->ar->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(
+ t->view_layer, NULL, &objects_len);
+
+ float dist_sq = FLT_MAX;
+ if (ED_uvedit_nearest_uv_multi(
+ t->scene, ima, objects, objects_len, co, &dist_sq, t->tsnap.snapPoint)) {
+ t->tsnap.snapPoint[0] *= t->aspect[0];
+ t->tsnap.snapPoint[1] *= t->aspect[1];
+
+ t->tsnap.status |= POINT_INIT;
+ }
+ else {
+ t->tsnap.status &= ~POINT_INIT;
+ }
+ MEM_freeN(objects);
+ }
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ if (t->tsnap.mode & (SCE_SNAP_MODE_NODE_X | SCE_SNAP_MODE_NODE_Y)) {
+ float loc[2];
+ float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
+ char node_border;
+
+ if (snapNodesTransform(t, t->mval, loc, &dist_px, &node_border)) {
+ copy_v2_v2(t->tsnap.snapPoint, loc);
+ t->tsnap.snapNodeBorder = node_border;
+
+ t->tsnap.status |= POINT_INIT;
+ }
+ else {
+ t->tsnap.status &= ~POINT_INIT;
+ }
+ }
+ }
}
/********************** TARGET **************************/
static void TargetSnapOffset(TransInfo *t, TransData *td)
{
- if (t->spacetype == SPACE_NODE && td != NULL) {
- bNode *node = td->extra;
- char border = t->tsnap.snapNodeBorder;
- float width = BLI_rctf_size_x(&node->totr);
- float height = BLI_rctf_size_y(&node->totr);
+ if (t->spacetype == SPACE_NODE && td != NULL) {
+ bNode *node = td->extra;
+ char border = t->tsnap.snapNodeBorder;
+ float width = BLI_rctf_size_x(&node->totr);
+ float height = BLI_rctf_size_y(&node->totr);
#ifdef USE_NODE_CENTER
- if (border & NODE_LEFT)
- t->tsnap.snapTarget[0] -= 0.5f * width;
- if (border & NODE_RIGHT)
- t->tsnap.snapTarget[0] += 0.5f * width;
- if (border & NODE_BOTTOM)
- t->tsnap.snapTarget[1] -= 0.5f * height;
- if (border & NODE_TOP)
- t->tsnap.snapTarget[1] += 0.5f * height;
+ if (border & NODE_LEFT)
+ t->tsnap.snapTarget[0] -= 0.5f * width;
+ if (border & NODE_RIGHT)
+ t->tsnap.snapTarget[0] += 0.5f * width;
+ if (border & NODE_BOTTOM)
+ t->tsnap.snapTarget[1] -= 0.5f * height;
+ if (border & NODE_TOP)
+ t->tsnap.snapTarget[1] += 0.5f * height;
#else
- if (border & NODE_LEFT)
- t->tsnap.snapTarget[0] -= 0.0f;
- if (border & NODE_RIGHT)
- t->tsnap.snapTarget[0] += width;
- if (border & NODE_BOTTOM)
- t->tsnap.snapTarget[1] -= height;
- if (border & NODE_TOP)
- t->tsnap.snapTarget[1] += 0.0f;
+ if (border & NODE_LEFT)
+ t->tsnap.snapTarget[0] -= 0.0f;
+ if (border & NODE_RIGHT)
+ t->tsnap.snapTarget[0] += width;
+ if (border & NODE_BOTTOM)
+ t->tsnap.snapTarget[1] -= height;
+ if (border & NODE_TOP)
+ t->tsnap.snapTarget[1] += 0.0f;
#endif
- }
+ }
}
static void TargetSnapCenter(TransInfo *t)
{
- /* Only need to calculate once */
- if ((t->tsnap.status & TARGET_INIT) == 0) {
- copy_v3_v3(t->tsnap.snapTarget, t->center_global);
- TargetSnapOffset(t, NULL);
+ /* Only need to calculate once */
+ if ((t->tsnap.status & TARGET_INIT) == 0) {
+ copy_v3_v3(t->tsnap.snapTarget, t->center_global);
+ TargetSnapOffset(t, NULL);
- t->tsnap.status |= TARGET_INIT;
- }
+ t->tsnap.status |= TARGET_INIT;
+ }
}
static void TargetSnapActive(TransInfo *t)
{
- /* Only need to calculate once */
- if ((t->tsnap.status & TARGET_INIT) == 0) {
- if (calculateCenterActive(t, true, t->tsnap.snapTarget)) {
- TargetSnapOffset(t, NULL);
-
- t->tsnap.status |= TARGET_INIT;
- }
- /* No active, default to median */
- else {
- t->tsnap.target = SCE_SNAP_TARGET_MEDIAN;
- t->tsnap.targetSnap = TargetSnapMedian;
- TargetSnapMedian(t);
- }
- }
+ /* Only need to calculate once */
+ if ((t->tsnap.status & TARGET_INIT) == 0) {
+ if (calculateCenterActive(t, true, t->tsnap.snapTarget)) {
+ TargetSnapOffset(t, NULL);
+
+ t->tsnap.status |= TARGET_INIT;
+ }
+ /* No active, default to median */
+ else {
+ t->tsnap.target = SCE_SNAP_TARGET_MEDIAN;
+ t->tsnap.targetSnap = TargetSnapMedian;
+ TargetSnapMedian(t);
+ }
+ }
}
static void TargetSnapMedian(TransInfo *t)
{
- // Only need to calculate once
- if ((t->tsnap.status & TARGET_INIT) == 0) {
- int i_accum = 0;
+ // Only need to calculate once
+ if ((t->tsnap.status & TARGET_INIT) == 0) {
+ int i_accum = 0;
- t->tsnap.snapTarget[0] = 0;
- t->tsnap.snapTarget[1] = 0;
- t->tsnap.snapTarget[2] = 0;
+ t->tsnap.snapTarget[0] = 0;
+ t->tsnap.snapTarget[1] = 0;
+ t->tsnap.snapTarget[2] = 0;
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- int i;
- float v[3];
- zero_v3(v);
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ int i;
+ float v[3];
+ zero_v3(v);
- for (i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) {
- add_v3_v3(v, td->center);
- }
+ for (i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) {
+ add_v3_v3(v, td->center);
+ }
- if (tc->use_local_mat) {
- mul_m4_v3(tc->mat, v);
- }
+ if (tc->use_local_mat) {
+ mul_m4_v3(tc->mat, v);
+ }
- add_v3_v3(t->tsnap.snapTarget, v);
- i_accum += i;
- }
+ add_v3_v3(t->tsnap.snapTarget, v);
+ i_accum += i;
+ }
- mul_v3_fl(t->tsnap.snapTarget, 1.0 / i_accum);
+ mul_v3_fl(t->tsnap.snapTarget, 1.0 / i_accum);
- TargetSnapOffset(t, NULL);
+ TargetSnapOffset(t, NULL);
- t->tsnap.status |= TARGET_INIT;
- }
+ t->tsnap.status |= TARGET_INIT;
+ }
}
static void TargetSnapClosest(TransInfo *t)
{
- // Only valid if a snap point has been selected
- if (t->tsnap.status & POINT_INIT) {
- float dist_closest = 0.0f;
- TransData *closest = NULL;
-
- /* Object mode */
- if (t->flag & T_OBJECT) {
- int i;
- FOREACH_TRANS_DATA_CONTAINER(t, tc) {
- TransData *td = tc->data;
- for (td = tc->data, i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) {
- struct BoundBox *bb = BKE_object_boundbox_get(td->ob);
-
- /* use boundbox if possible */
- if (bb) {
- int j;
-
- for (j = 0; j < 8; j++) {
- float loc[3];
- float dist;
-
- copy_v3_v3(loc, bb->vec[j]);
- mul_m4_v3(td->ext->obmat, loc);
-
- dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
-
- if ((dist != TRANSFORM_DIST_INVALID) &&
- (closest == NULL || fabsf(dist) < fabsf(dist_closest)))
- {
- copy_v3_v3(t->tsnap.snapTarget, loc);
- closest = td;
- dist_closest = dist;
- }
- }
- }
- /* use element center otherwise */
- else {
- float loc[3];
- float dist;
-
- copy_v3_v3(loc, td->center);
-
- dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
-
- if ((dist != TRANSFORM_DIST_INVALID) &&
- (closest == NULL || fabsf(dist) < fabsf(dist_closest)))
- {
- copy_v3_v3(t->tsnap.snapTarget, loc);
- closest = td;
- }
- }
- }
- }
- }
- else {
- FOREACH_TRANS_DATA_CONTAINER(t, tc) {
- TransData *td = tc->data;
- int i;
- for (i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) {
- float loc[3];
- float dist;
-
- copy_v3_v3(loc, td->center);
-
- if (tc->use_local_mat) {
- mul_m4_v3(tc->mat, loc);
- }
-
- dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
-
- if ((dist != TRANSFORM_DIST_INVALID) &&
- (closest == NULL || fabsf(dist) < fabsf(dist_closest)))
- {
- copy_v3_v3(t->tsnap.snapTarget, loc);
- closest = td;
- dist_closest = dist;
- }
- }
- }
- }
-
- TargetSnapOffset(t, closest);
-
- t->tsnap.status |= TARGET_INIT;
- }
+ // Only valid if a snap point has been selected
+ if (t->tsnap.status & POINT_INIT) {
+ float dist_closest = 0.0f;
+ TransData *closest = NULL;
+
+ /* Object mode */
+ if (t->flag & T_OBJECT) {
+ int i;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (td = tc->data, i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) {
+ struct BoundBox *bb = BKE_object_boundbox_get(td->ob);
+
+ /* use boundbox if possible */
+ if (bb) {
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ float loc[3];
+ float dist;
+
+ copy_v3_v3(loc, bb->vec[j]);
+ mul_m4_v3(td->ext->obmat, loc);
+
+ dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
+
+ if ((dist != TRANSFORM_DIST_INVALID) &&
+ (closest == NULL || fabsf(dist) < fabsf(dist_closest))) {
+ copy_v3_v3(t->tsnap.snapTarget, loc);
+ closest = td;
+ dist_closest = dist;
+ }
+ }
+ }
+ /* use element center otherwise */
+ else {
+ float loc[3];
+ float dist;
+
+ copy_v3_v3(loc, td->center);
+
+ dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
+
+ if ((dist != TRANSFORM_DIST_INVALID) &&
+ (closest == NULL || fabsf(dist) < fabsf(dist_closest))) {
+ copy_v3_v3(t->tsnap.snapTarget, loc);
+ closest = td;
+ }
+ }
+ }
+ }
+ }
+ else {
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ int i;
+ for (i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) {
+ float loc[3];
+ float dist;
+
+ copy_v3_v3(loc, td->center);
+
+ if (tc->use_local_mat) {
+ mul_m4_v3(tc->mat, loc);
+ }
+
+ dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
+
+ if ((dist != TRANSFORM_DIST_INVALID) &&
+ (closest == NULL || fabsf(dist) < fabsf(dist_closest))) {
+ copy_v3_v3(t->tsnap.snapTarget, loc);
+ closest = td;
+ dist_closest = dist;
+ }
+ }
+ }
+ }
+
+ TargetSnapOffset(t, closest);
+
+ t->tsnap.status |= TARGET_INIT;
+ }
}
bool snapObjectsTransform(
- TransInfo *t, const float mval[2],
- float *dist_px,
- float r_loc[3], float r_no[3])
+ TransInfo *t, const float mval[2], float *dist_px, float r_loc[3], float r_no[3])
{
- return ED_transform_snap_object_project_view3d(
- t->tsnap.object_context,
- t->scene->toolsettings->snap_mode,
- &(const struct SnapObjectParams){
- .snap_select = t->tsnap.modeSelect,
- .use_object_edit_cage = (t->flag & T_EDIT) != 0,
- .use_occlusion_test = t->scene->toolsettings->snap_mode != SCE_SNAP_MODE_FACE,
- },
- mval, dist_px, r_loc, r_no);
+ return ED_transform_snap_object_project_view3d(
+ t->tsnap.object_context,
+ t->scene->toolsettings->snap_mode,
+ &(const struct SnapObjectParams){
+ .snap_select = t->tsnap.modeSelect,
+ .use_object_edit_cage = (t->flag & T_EDIT) != 0,
+ .use_occlusion_test = t->scene->toolsettings->snap_mode != SCE_SNAP_MODE_FACE,
+ },
+ mval,
+ dist_px,
+ r_loc,
+ r_no);
}
-
/******************** 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 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)
{
- ListBase depths_peel = {0};
- ED_transform_snap_object_project_all_view3d_ex(
- sctx,
- params,
- 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 */
- struct SnapObjectHitDepth *hit_min = depths_peel.first;
- for (struct SnapObjectHitDepth *iter = hit_min->next; iter; iter = iter->next) {
- if (iter->depth < hit_min->depth) {
- hit_min = iter;
- }
- }
- struct SnapObjectHitDepth *hit_max = NULL;
-
- if (use_peel_object) {
- /* if peeling objects, take the first and last from each object */
- hit_max = hit_min;
- for (struct SnapObjectHitDepth *iter = depths_peel.first; iter; iter = iter->next) {
- if ((iter->depth > hit_max->depth) && (iter->ob_uuid == hit_min->ob_uuid)) {
- hit_max = iter;
- }
- }
- }
- else {
- /* otherwise, pair first with second and so on */
- for (struct SnapObjectHitDepth *iter = depths_peel.first; iter; iter = iter->next) {
- if ((iter != hit_min) && (iter->ob_uuid == hit_min->ob_uuid)) {
- if (hit_max == NULL) {
- hit_max = iter;
- }
- else if (iter->depth < hit_max->depth) {
- hit_max = iter;
- }
- }
- }
- /* in this case has only one hit. treat as raycast */
- if (hit_max == NULL) {
- hit_max = hit_min;
- }
- }
-
- mid_v3_v3v3(r_loc, hit_min->co, hit_max->co);
-
- if (r_thickness) {
- *r_thickness = hit_max->depth - hit_min->depth;
- }
-
- /* XXX, is there a correct normal in this case ???, for now just z up */
- r_no[0] = 0.0;
- r_no[1] = 0.0;
- r_no[2] = 1.0;
-
- BLI_freelistN(&depths_peel);
- return true;
- }
- return false;
+ ListBase depths_peel = {0};
+ ED_transform_snap_object_project_all_view3d_ex(sctx, params, 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 */
+ struct SnapObjectHitDepth *hit_min = depths_peel.first;
+ for (struct SnapObjectHitDepth *iter = hit_min->next; iter; iter = iter->next) {
+ if (iter->depth < hit_min->depth) {
+ hit_min = iter;
+ }
+ }
+ struct SnapObjectHitDepth *hit_max = NULL;
+
+ if (use_peel_object) {
+ /* if peeling objects, take the first and last from each object */
+ hit_max = hit_min;
+ for (struct SnapObjectHitDepth *iter = depths_peel.first; iter; iter = iter->next) {
+ if ((iter->depth > hit_max->depth) && (iter->ob_uuid == hit_min->ob_uuid)) {
+ hit_max = iter;
+ }
+ }
+ }
+ else {
+ /* otherwise, pair first with second and so on */
+ for (struct SnapObjectHitDepth *iter = depths_peel.first; iter; iter = iter->next) {
+ if ((iter != hit_min) && (iter->ob_uuid == hit_min->ob_uuid)) {
+ if (hit_max == NULL) {
+ hit_max = iter;
+ }
+ else if (iter->depth < hit_max->depth) {
+ hit_max = iter;
+ }
+ }
+ }
+ /* in this case has only one hit. treat as raycast */
+ if (hit_max == NULL) {
+ hit_max = hit_min;
+ }
+ }
+
+ mid_v3_v3v3(r_loc, hit_min->co, hit_max->co);
+
+ if (r_thickness) {
+ *r_thickness = hit_max->depth - hit_min->depth;
+ }
+
+ /* XXX, is there a correct normal in this case ???, for now just z up */
+ r_no[0] = 0.0;
+ r_no[1] = 0.0;
+ r_no[2] = 1.0;
+
+ BLI_freelistN(&depths_peel);
+ return true;
+ }
+ 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)
+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);
+ 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);
}
/******************** NODES ***********************************/
static bool snapNodeTest(View2D *v2d, bNode *node, eSnapSelect snap_select)
{
- /* node is use for snapping only if a) snap mode matches and b) node is inside the view */
- return ((snap_select == SNAP_NOT_SELECTED && !(node->flag & NODE_SELECT)) ||
- (snap_select == SNAP_ALL && !(node->flag & NODE_ACTIVE))) &&
- (node->totr.xmin < v2d->cur.xmax && node->totr.xmax > v2d->cur.xmin &&
- node->totr.ymin < v2d->cur.ymax && node->totr.ymax > v2d->cur.ymin);
+ /* node is use for snapping only if a) snap mode matches and b) node is inside the view */
+ return ((snap_select == SNAP_NOT_SELECTED && !(node->flag & NODE_SELECT)) ||
+ (snap_select == SNAP_ALL && !(node->flag & NODE_ACTIVE))) &&
+ (node->totr.xmin < v2d->cur.xmax && node->totr.xmax > v2d->cur.xmin &&
+ node->totr.ymin < v2d->cur.ymax && node->totr.ymax > v2d->cur.ymin);
}
static NodeBorder snapNodeBorder(int snap_node_mode)
{
- NodeBorder flag = 0;
- if (snap_node_mode & SCE_SNAP_MODE_NODE_X) {
- flag |= NODE_LEFT | NODE_RIGHT;
- }
- if (snap_node_mode & SCE_SNAP_MODE_NODE_Y) {
- flag |= NODE_TOP | NODE_BOTTOM;
- }
- return flag;
+ NodeBorder flag = 0;
+ if (snap_node_mode & SCE_SNAP_MODE_NODE_X) {
+ flag |= NODE_LEFT | NODE_RIGHT;
+ }
+ if (snap_node_mode & SCE_SNAP_MODE_NODE_Y) {
+ flag |= NODE_TOP | NODE_BOTTOM;
+ }
+ return flag;
}
-static bool snapNode(
- ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNode *node, const int mval[2],
- float r_loc[2], float *r_dist_px, char *r_node_border)
+static bool snapNode(ToolSettings *ts,
+ SpaceNode *UNUSED(snode),
+ ARegion *ar,
+ bNode *node,
+ const int mval[2],
+ float r_loc[2],
+ float *r_dist_px,
+ char *r_node_border)
{
- View2D *v2d = &ar->v2d;
- NodeBorder border = snapNodeBorder(ts->snap_node_mode);
- bool retval = false;
- rcti totr;
- int new_dist;
-
- UI_view2d_view_to_region_rcti(v2d, &node->totr, &totr);
-
- if (border & NODE_LEFT) {
- new_dist = abs(totr.xmin - mval[0]);
- if (new_dist < *r_dist_px) {
- UI_view2d_region_to_view(v2d, totr.xmin, mval[1], &r_loc[0], &r_loc[1]);
- *r_dist_px = new_dist;
- *r_node_border = NODE_LEFT;
- retval = true;
- }
- }
-
- if (border & NODE_RIGHT) {
- new_dist = abs(totr.xmax - mval[0]);
- if (new_dist < *r_dist_px) {
- UI_view2d_region_to_view(v2d, totr.xmax, mval[1], &r_loc[0], &r_loc[1]);
- *r_dist_px = new_dist;
- *r_node_border = NODE_RIGHT;
- retval = true;
- }
- }
-
- if (border & NODE_BOTTOM) {
- new_dist = abs(totr.ymin - mval[1]);
- if (new_dist < *r_dist_px) {
- UI_view2d_region_to_view(v2d, mval[0], totr.ymin, &r_loc[0], &r_loc[1]);
- *r_dist_px = new_dist;
- *r_node_border = NODE_BOTTOM;
- retval = true;
- }
- }
-
- if (border & NODE_TOP) {
- new_dist = abs(totr.ymax - mval[1]);
- if (new_dist < *r_dist_px) {
- UI_view2d_region_to_view(v2d, mval[0], totr.ymax, &r_loc[0], &r_loc[1]);
- *r_dist_px = new_dist;
- *r_node_border = NODE_TOP;
- retval = true;
- }
- }
-
- return retval;
+ View2D *v2d = &ar->v2d;
+ NodeBorder border = snapNodeBorder(ts->snap_node_mode);
+ bool retval = false;
+ rcti totr;
+ int new_dist;
+
+ UI_view2d_view_to_region_rcti(v2d, &node->totr, &totr);
+
+ if (border & NODE_LEFT) {
+ new_dist = abs(totr.xmin - mval[0]);
+ if (new_dist < *r_dist_px) {
+ UI_view2d_region_to_view(v2d, totr.xmin, mval[1], &r_loc[0], &r_loc[1]);
+ *r_dist_px = new_dist;
+ *r_node_border = NODE_LEFT;
+ retval = true;
+ }
+ }
+
+ if (border & NODE_RIGHT) {
+ new_dist = abs(totr.xmax - mval[0]);
+ if (new_dist < *r_dist_px) {
+ UI_view2d_region_to_view(v2d, totr.xmax, mval[1], &r_loc[0], &r_loc[1]);
+ *r_dist_px = new_dist;
+ *r_node_border = NODE_RIGHT;
+ retval = true;
+ }
+ }
+
+ if (border & NODE_BOTTOM) {
+ new_dist = abs(totr.ymin - mval[1]);
+ if (new_dist < *r_dist_px) {
+ UI_view2d_region_to_view(v2d, mval[0], totr.ymin, &r_loc[0], &r_loc[1]);
+ *r_dist_px = new_dist;
+ *r_node_border = NODE_BOTTOM;
+ retval = true;
+ }
+ }
+
+ if (border & NODE_TOP) {
+ new_dist = abs(totr.ymax - mval[1]);
+ if (new_dist < *r_dist_px) {
+ UI_view2d_region_to_view(v2d, mval[0], totr.ymax, &r_loc[0], &r_loc[1]);
+ *r_dist_px = new_dist;
+ *r_node_border = NODE_TOP;
+ retval = true;
+ }
+ }
+
+ return retval;
}
-static bool snapNodes(
- ToolSettings *ts, SpaceNode *snode, ARegion *ar,
- const int mval[2], eSnapSelect snap_select,
- float r_loc[2], float *r_dist_px, char *r_node_border)
+static bool snapNodes(ToolSettings *ts,
+ SpaceNode *snode,
+ ARegion *ar,
+ const int mval[2],
+ eSnapSelect snap_select,
+ float r_loc[2],
+ float *r_dist_px,
+ char *r_node_border)
{
- bNodeTree *ntree = snode->edittree;
- bNode *node;
- bool retval = false;
+ bNodeTree *ntree = snode->edittree;
+ bNode *node;
+ bool retval = false;
- *r_node_border = 0;
+ *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);
- }
- }
+ 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);
+ }
+ }
- return retval;
+ return retval;
}
bool snapNodesTransform(
- TransInfo *t, const int mval[2],
- float r_loc[2], float *r_dist_px, char *r_node_border)
+ 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, mval, t->tsnap.modeSelect,
- r_loc, r_dist_px, r_node_border);
+ return snapNodes(t->settings,
+ t->sa->spacedata.first,
+ t->ar,
+ mval,
+ t->tsnap.modeSelect,
+ r_loc,
+ r_dist_px,
+ r_node_border);
}
/*================================================================*/
-static void applyGridIncrement(TransInfo *t, float *val, int max_index, const float fac[3], GearsType action);
-
+static void applyGridIncrement(
+ TransInfo *t, float *val, int max_index, const float fac[3], GearsType action);
void snapGridIncrementAction(TransInfo *t, float *val, GearsType action)
{
- float fac[3];
+ float fac[3];
- fac[NO_GEARS] = t->snap[0];
- fac[BIG_GEARS] = t->snap[1];
- fac[SMALL_GEARS] = t->snap[2];
+ fac[NO_GEARS] = t->snap[0];
+ fac[BIG_GEARS] = t->snap[1];
+ fac[SMALL_GEARS] = t->snap[2];
- applyGridIncrement(t, val, t->idx_max, fac, action);
+ applyGridIncrement(t, val, t->idx_max, fac, action);
}
-
void snapGridIncrement(TransInfo *t, float *val)
{
- GearsType action;
+ GearsType action;
- /* only do something if using absolute or incremental grid snapping
- * and there is no valid snap point */
- if ((!(t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) ||
- validSnap(t)) && !doForceIncrementSnap(t))
- {
- return;
- }
+ /* only do something if using absolute or incremental grid snapping
+ * and there is no valid snap point */
+ if ((!(t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) || validSnap(t)) &&
+ !doForceIncrementSnap(t)) {
+ return;
+ }
- action = activeSnap(t) ? BIG_GEARS : NO_GEARS;
+ action = activeSnap(t) ? BIG_GEARS : NO_GEARS;
- if (action == BIG_GEARS && (t->modifiers & MOD_PRECISION)) {
- action = SMALL_GEARS;
- }
+ if (action == BIG_GEARS && (t->modifiers & MOD_PRECISION)) {
+ action = SMALL_GEARS;
+ }
- snapGridIncrementAction(t, val, action);
+ snapGridIncrementAction(t, val, action);
}
void snapSequenceBounds(TransInfo *t, const int mval[2])
{
- float xmouse, ymouse;
- int frame;
- int mframe;
- TransSeq *ts = TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data;
- /* reuse increment, strictly speaking could be another snap mode, but leave as is */
- if (!(t->modifiers & MOD_SNAP_INVERT))
- return;
-
- /* convert to frame range */
- UI_view2d_region_to_view(&t->ar->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);
-
- if (!ts->snap_left)
- frame = frame - (ts->max - ts->min);
-
- t->values[0] = frame - ts->min;
+ float xmouse, ymouse;
+ int frame;
+ int mframe;
+ TransSeq *ts = TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data;
+ /* reuse increment, strictly speaking could be another snap mode, but leave as is */
+ if (!(t->modifiers & MOD_SNAP_INVERT))
+ return;
+
+ /* convert to frame range */
+ UI_view2d_region_to_view(&t->ar->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);
+
+ if (!ts->snap_left)
+ frame = frame - (ts->max - ts->min);
+
+ t->values[0] = frame - ts->min;
}
-static void applyGridIncrement(TransInfo *t, float *val, int max_index, const float fac[3], GearsType action)
+static void applyGridIncrement(
+ TransInfo *t, float *val, int max_index, const float fac[3], GearsType action)
{
- float asp_local[3] = {1, 1, 1};
- const bool use_aspect = ELEM(t->mode, TFM_TRANSLATION);
- const float *asp = use_aspect ? t->aspect : asp_local;
- int i;
-
- BLI_assert((t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) || doForceIncrementSnap(t));
- BLI_assert(max_index <= 2);
-
- /* Early bailing out if no need to snap */
- if (fac[action] == 0.0f) {
- return;
- }
-
- if (use_aspect) {
- /* custom aspect for fcurve */
- if (t->spacetype == SPACE_GRAPH) {
- View2D *v2d = &t->ar->v2d;
- View2DGrid *grid;
- SpaceGraph *sipo = t->sa->spacedata.first;
- int unity = V2D_UNIT_VALUES;
- int unitx = (sipo->flag & SIPO_DRAWTIME) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMESCALE;
-
- /* grid */
- grid = UI_view2d_grid_calc(t->scene, v2d, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP, t->ar->winx, t->ar->winy);
-
- UI_view2d_grid_size(grid, &asp_local[0], &asp_local[1]);
- UI_view2d_grid_free(grid);
-
- asp = asp_local;
- }
- }
-
- /* absolute snapping on grid based on global center */
- if ((t->tsnap.snap_spatial_grid) && (t->mode == TFM_TRANSLATION)) {
- const float *center_global = t->center_global;
- bool use_local_axis = false;
-
- /* use a fallback for cursor selection,
- * this isn't useful as a global center for absolute grid snapping
- * since its not based on the position of the selection. */
- if (t->around == V3D_AROUND_CURSOR) {
- const TransCenterData *cd = transformCenter_from_type(t, V3D_AROUND_CENTER_MEDIAN);
- center_global = cd->global;
- }
-
- if (t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2)) {
- use_local_axis = true;
- }
-
- for (i = 0; i <= max_index; i++) {
- /* do not let unconstrained axis jump to absolute grid increments */
- if (!(t->con.mode & CON_APPLY) || t->con.mode & (CON_AXIS0 << i)) {
- const float iter_fac = fac[action] * asp[i];
-
- if (use_local_axis) {
- float local_axis[3];
- float pos_on_axis[3];
-
- copy_v3_v3(local_axis, t->con.mtx[i]);
- copy_v3_v3(pos_on_axis, t->con.mtx[i]);
-
- /* amount of movement on axis from initial pos */
- mul_v3_fl(pos_on_axis, val[i]);
-
- /* actual global position on axis */
- add_v3_v3(pos_on_axis, center_global);
-
- float min_dist = INFINITY;
- for (int j = 0; j < 3; j++) {
- if (fabs(local_axis[j]) < 0.01f) {
- /* Ignore very small (normalized) axis changes */
- continue;
- }
-
- /* closest point on grid */
- float grid_p = iter_fac * roundf(pos_on_axis[j] / iter_fac);
- float dist_p = fabs((grid_p - pos_on_axis[j]) / local_axis[j]);
-
- /* The amount of distance needed to travel along the
- * local axis to snap to the closest grid point */
- /* in the global j axis direction */
- float move_dist = (grid_p - center_global[j]) / local_axis[j];
-
- if (dist_p < min_dist) {
- min_dist = dist_p;
- val[i] = move_dist;
- }
- }
- }
- else {
- val[i] = iter_fac * roundf((val[i] + center_global[i]) / iter_fac) - center_global[i];
- }
- }
- }
- }
- else {
- /* relative snapping in fixed increments */
- for (i = 0; i <= max_index; i++) {
- const float iter_fac = fac[action] * asp[i];
- val[i] = iter_fac * roundf(val[i] / iter_fac);
- }
- }
+ float asp_local[3] = {1, 1, 1};
+ const bool use_aspect = ELEM(t->mode, TFM_TRANSLATION);
+ const float *asp = use_aspect ? t->aspect : asp_local;
+ int i;
+
+ BLI_assert((t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) ||
+ doForceIncrementSnap(t));
+ BLI_assert(max_index <= 2);
+
+ /* Early bailing out if no need to snap */
+ if (fac[action] == 0.0f) {
+ return;
+ }
+
+ if (use_aspect) {
+ /* custom aspect for fcurve */
+ if (t->spacetype == SPACE_GRAPH) {
+ View2D *v2d = &t->ar->v2d;
+ View2DGrid *grid;
+ SpaceGraph *sipo = t->sa->spacedata.first;
+ int unity = V2D_UNIT_VALUES;
+ int unitx = (sipo->flag & SIPO_DRAWTIME) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMESCALE;
+
+ /* grid */
+ grid = UI_view2d_grid_calc(t->scene,
+ v2d,
+ unitx,
+ V2D_GRID_NOCLAMP,
+ unity,
+ V2D_GRID_NOCLAMP,
+ t->ar->winx,
+ t->ar->winy);
+
+ UI_view2d_grid_size(grid, &asp_local[0], &asp_local[1]);
+ UI_view2d_grid_free(grid);
+
+ asp = asp_local;
+ }
+ }
+
+ /* absolute snapping on grid based on global center */
+ if ((t->tsnap.snap_spatial_grid) && (t->mode == TFM_TRANSLATION)) {
+ const float *center_global = t->center_global;
+ bool use_local_axis = false;
+
+ /* use a fallback for cursor selection,
+ * this isn't useful as a global center for absolute grid snapping
+ * since its not based on the position of the selection. */
+ if (t->around == V3D_AROUND_CURSOR) {
+ const TransCenterData *cd = transformCenter_from_type(t, V3D_AROUND_CENTER_MEDIAN);
+ center_global = cd->global;
+ }
+
+ if (t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2)) {
+ use_local_axis = true;
+ }
+
+ for (i = 0; i <= max_index; i++) {
+ /* do not let unconstrained axis jump to absolute grid increments */
+ if (!(t->con.mode & CON_APPLY) || t->con.mode & (CON_AXIS0 << i)) {
+ const float iter_fac = fac[action] * asp[i];
+
+ if (use_local_axis) {
+ float local_axis[3];
+ float pos_on_axis[3];
+
+ copy_v3_v3(local_axis, t->con.mtx[i]);
+ copy_v3_v3(pos_on_axis, t->con.mtx[i]);
+
+ /* amount of movement on axis from initial pos */
+ mul_v3_fl(pos_on_axis, val[i]);
+
+ /* actual global position on axis */
+ add_v3_v3(pos_on_axis, center_global);
+
+ float min_dist = INFINITY;
+ for (int j = 0; j < 3; j++) {
+ if (fabs(local_axis[j]) < 0.01f) {
+ /* Ignore very small (normalized) axis changes */
+ continue;
+ }
+
+ /* closest point on grid */
+ float grid_p = iter_fac * roundf(pos_on_axis[j] / iter_fac);
+ float dist_p = fabs((grid_p - pos_on_axis[j]) / local_axis[j]);
+
+ /* The amount of distance needed to travel along the
+ * local axis to snap to the closest grid point */
+ /* in the global j axis direction */
+ float move_dist = (grid_p - center_global[j]) / local_axis[j];
+
+ if (dist_p < min_dist) {
+ min_dist = dist_p;
+ val[i] = move_dist;
+ }
+ }
+ }
+ else {
+ val[i] = iter_fac * roundf((val[i] + center_global[i]) / iter_fac) - center_global[i];
+ }
+ }
+ }
+ }
+ else {
+ /* relative snapping in fixed increments */
+ for (i = 0; i <= max_index; i++) {
+ const float iter_fac = fac[action] * asp[i];
+ val[i] = iter_fac * roundf(val[i] / iter_fac);
+ }
+ }
}
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index f2692f57a35..93f89c1919e 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -45,7 +45,7 @@
#include "BKE_armature.h"
#include "BKE_curve.h"
#include "BKE_object.h"
-#include "BKE_anim.h" /* for duplis */
+#include "BKE_anim.h" /* for duplis */
#include "BKE_editmesh.h"
#include "BKE_main.h"
#include "BKE_tracking.h"
@@ -70,78 +70,76 @@
#define MAX_CLIPPLANE_LEN 3
enum eViewProj {
- VIEW_PROJ_NONE = -1,
- VIEW_PROJ_ORTHO = 0,
- VIEW_PROJ_PERSP = -1,
+ VIEW_PROJ_NONE = -1,
+ VIEW_PROJ_ORTHO = 0,
+ VIEW_PROJ_PERSP = -1,
};
typedef struct SnapData {
- short snap_to_flag;
- float mval[2];
- float pmat[4][4]; /* perspective matrix */
- float win_size[2];/* win x and y */
- enum eViewProj view_proj;
- float clip_plane[MAX_CLIPPLANE_LEN][4];
- short clip_plane_len;
+ short snap_to_flag;
+ float mval[2];
+ float pmat[4][4]; /* perspective matrix */
+ float win_size[2]; /* win x and y */
+ enum eViewProj view_proj;
+ float clip_plane[MAX_CLIPPLANE_LEN][4];
+ short clip_plane_len;
} SnapData;
typedef struct SnapObjectData {
- enum {
- SNAP_MESH = 1,
- SNAP_EDIT_MESH,
- } type;
+ enum {
+ 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 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;
typedef struct SnapObjectData_EditMesh {
- SnapObjectData sd;
- BVHTreeFromEditMesh *bvh_trees[3];
- float min[3], max[3];
+ SnapObjectData sd;
+ BVHTreeFromEditMesh *bvh_trees[3];
+ float min[3], max[3];
} SnapObjectData_EditMesh;
struct SnapObjectContext {
- Main *bmain;
- Scene *scene;
- Depsgraph *depsgraph;
-
- int flag;
-
- /* Optional: when performing screen-space projection.
- * otherwise this doesn't take viewport into account. */
- bool use_v3d;
- struct {
- const struct View3D *v3d;
- const struct ARegion *ar;
- } v3d_data;
-
-
- /* Object -> SnapObjectData map */
- struct {
- GHash *object_map;
- MemArena *mem_arena;
- } cache;
-
- /* Filter data, returns true to check this value */
- struct {
- struct {
- bool (*test_vert_fn)(BMVert *, void *user_data);
- bool (*test_edge_fn)(BMEdge *, void *user_data);
- bool (*test_face_fn)(BMFace *, void *user_data);
- void *user_data;
- } edit_mesh;
- } callbacks;
-
+ Main *bmain;
+ Scene *scene;
+ Depsgraph *depsgraph;
+
+ int flag;
+
+ /* Optional: when performing screen-space projection.
+ * otherwise this doesn't take viewport into account. */
+ bool use_v3d;
+ struct {
+ const struct View3D *v3d;
+ const struct ARegion *ar;
+ } v3d_data;
+
+ /* Object -> SnapObjectData map */
+ struct {
+ GHash *object_map;
+ MemArena *mem_arena;
+ } cache;
+
+ /* Filter data, returns true to check this value */
+ struct {
+ struct {
+ bool (*test_vert_fn)(BMVert *, void *user_data);
+ bool (*test_edge_fn)(BMEdge *, void *user_data);
+ bool (*test_face_fn)(BMFace *, void *user_data);
+ void *user_data;
+ } edit_mesh;
+ } callbacks;
};
/** \} */
@@ -155,51 +153,54 @@ struct SnapObjectContext {
*/
static void bm_mesh_minmax(BMesh *bm, float r_min[3], float r_max[3])
{
- INIT_MINMAX(r_min, r_max);
- BMIter iter;
- BMVert *v;
+ INIT_MINMAX(r_min, r_max);
+ BMIter iter;
+ BMVert *v;
- BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
- minmax_v3v3_v3(r_min, r_max, v->co);
- }
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ minmax_v3v3_v3(r_min, r_max, v->co);
+ }
}
static SnapObjectData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, Object *ob)
{
- void **sod_p;
- if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
- BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_MESH);
- }
- else {
- SnapObjectData_Mesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
- sod->sd.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;
+ void **sod_p;
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
+ BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_MESH);
+ }
+ else {
+ SnapObjectData_Mesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ sod->sd.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;
}
/* Use `em->ob` as the key in ghash since the editmesh is used
* to create bvhtree and is the same for each linked object. */
-static SnapObjectData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext *sctx, BMEditMesh *em)
+static SnapObjectData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext *sctx,
+ BMEditMesh *em)
{
- void **sod_p;
- if (BLI_ghash_ensure_p(sctx->cache.object_map, em->ob, &sod_p)) {
- BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_EDIT_MESH);
- }
- 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);
- }
-
- return *sod_p;
+ void **sod_p;
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, em->ob, &sod_p)) {
+ BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_EDIT_MESH);
+ }
+ 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);
+ }
+
+ return *sod_p;
}
-typedef void(*IterSnapObjsCallback)(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data);
+typedef void (*IterSnapObjsCallback)(
+ SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data);
/**
* Walks through all objects in the scene to create the list of objects to snap.
@@ -207,36 +208,35 @@ typedef void(*IterSnapObjsCallback)(SnapObjectContext *sctx, bool is_obedit, Obj
* \param sctx: Snap context to store data.
* \param snap_select: from enum #eSnapSelect.
*/
-static void iter_snap_objects(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- IterSnapObjsCallback sob_callback,
- void *data)
+static void iter_snap_objects(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ IterSnapObjsCallback sob_callback,
+ void *data)
{
- ViewLayer *view_layer = DEG_get_input_view_layer(sctx->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;
-
- Base *base_act = view_layer->basact;
- for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
- if ((BASE_VISIBLE(v3d, base)) && (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) == 0 &&
- !((snap_select == SNAP_NOT_SELECTED && ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) ||
- (snap_select == SNAP_NOT_ACTIVE && base == base_act)))
- {
- Object *obj_eval = DEG_get_evaluated_object(sctx->depsgraph, base->object);
- if (obj_eval->transflag & OB_DUPLI) {
- DupliObject *dupli_ob;
- ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj_eval);
- for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
- sob_callback(sctx, use_object_edit_cage, dupli_ob->ob, dupli_ob->mat, data);
- }
- free_object_duplilist(lb);
- }
-
- sob_callback(sctx, use_object_edit_cage, obj_eval, obj_eval->obmat, data);
- }
- }
+ ViewLayer *view_layer = DEG_get_input_view_layer(sctx->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;
+
+ Base *base_act = view_layer->basact;
+ for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
+ if ((BASE_VISIBLE(v3d, base)) && (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) == 0 &&
+ !((snap_select == SNAP_NOT_SELECTED &&
+ ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) ||
+ (snap_select == SNAP_NOT_ACTIVE && base == base_act))) {
+ Object *obj_eval = DEG_get_evaluated_object(sctx->depsgraph, base->object);
+ if (obj_eval->transflag & OB_DUPLI) {
+ DupliObject *dupli_ob;
+ ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj_eval);
+ for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
+ sob_callback(sctx, use_object_edit_cage, dupli_ob->ob, dupli_ob->mat, data);
+ }
+ free_object_duplilist(lb);
+ }
+
+ sob_callback(sctx, use_object_edit_cage, obj_eval, obj_eval->obmat, data);
+ }
+ }
}
/** \} */
@@ -249,516 +249,567 @@ static void iter_snap_objects(
* Support for storing all depths, not just the first (raycast 'all') */
struct RayCastAll_Data {
- void *bvhdata;
+ void *bvhdata;
- /* internal vars for adding depths */
- BVHTree_RayCastCallback raycast_callback;
+ /* internal vars for adding depths */
+ BVHTree_RayCastCallback raycast_callback;
- const float(*obmat)[4];
- const float(*timat)[3];
+ const float (*obmat)[4];
+ const float (*timat)[3];
- float len_diff;
- float local_scale;
+ float len_diff;
+ float local_scale;
- Object *ob;
- unsigned int ob_uuid;
+ Object *ob;
+ unsigned int ob_uuid;
- /* output data */
- ListBase *hit_list;
- bool retval;
+ /* output data */
+ ListBase *hit_list;
+ bool retval;
};
-
-static struct SnapObjectHitDepth *hit_depth_create(
- const float depth, const float co[3], const float no[3], int index,
- Object *ob, const float obmat[4][4], unsigned int ob_uuid)
+static struct SnapObjectHitDepth *hit_depth_create(const float depth,
+ const float co[3],
+ const float no[3],
+ int index,
+ Object *ob,
+ const float obmat[4][4],
+ unsigned int ob_uuid)
{
- struct SnapObjectHitDepth *hit = MEM_mallocN(sizeof(*hit), __func__);
+ struct SnapObjectHitDepth *hit = MEM_mallocN(sizeof(*hit), __func__);
- hit->depth = depth;
- copy_v3_v3(hit->co, co);
- copy_v3_v3(hit->no, no);
- hit->index = index;
+ hit->depth = depth;
+ copy_v3_v3(hit->co, co);
+ copy_v3_v3(hit->no, no);
+ hit->index = index;
- hit->ob = ob;
- copy_m4_m4(hit->obmat, (float(*)[4])obmat);
- hit->ob_uuid = ob_uuid;
+ hit->ob = ob;
+ copy_m4_m4(hit->obmat, (float(*)[4])obmat);
+ hit->ob_uuid = ob_uuid;
- return hit;
+ return hit;
}
static int hit_depth_cmp(const void *arg1, const void *arg2)
{
- const struct SnapObjectHitDepth *h1 = arg1;
- const struct SnapObjectHitDepth *h2 = arg2;
- int val = 0;
-
- if (h1->depth < h2->depth) {
- val = -1;
- }
- else if (h1->depth > h2->depth) {
- val = 1;
- }
-
- return val;
+ const struct SnapObjectHitDepth *h1 = arg1;
+ const struct SnapObjectHitDepth *h2 = arg2;
+ int val = 0;
+
+ if (h1->depth < h2->depth) {
+ val = -1;
+ }
+ else if (h1->depth > h2->depth) {
+ val = 1;
+ }
+
+ return val;
}
static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
- struct RayCastAll_Data *data = userdata;
- data->raycast_callback(data->bvhdata, index, ray, hit);
- if (hit->index != -1) {
- /* get all values in worldspace */
- float location[3], normal[3];
- float depth;
-
- /* worldspace location */
- mul_v3_m4v3(location, (float(*)[4])data->obmat, hit->co);
- depth = (hit->dist + data->len_diff) / data->local_scale;
-
- /* worldspace normal */
- copy_v3_v3(normal, hit->no);
- mul_m3_v3((float(*)[3])data->timat, normal);
- normalize_v3(normal);
-
- struct SnapObjectHitDepth *hit_item = hit_depth_create(
- depth, location, normal, hit->index,
- data->ob, data->obmat, data->ob_uuid);
- BLI_addtail(data->hit_list, hit_item);
- }
+ struct RayCastAll_Data *data = userdata;
+ data->raycast_callback(data->bvhdata, index, ray, hit);
+ if (hit->index != -1) {
+ /* get all values in worldspace */
+ float location[3], normal[3];
+ float depth;
+
+ /* worldspace location */
+ mul_v3_m4v3(location, (float(*)[4])data->obmat, hit->co);
+ depth = (hit->dist + data->len_diff) / data->local_scale;
+
+ /* worldspace normal */
+ copy_v3_v3(normal, hit->no);
+ mul_m3_v3((float(*)[3])data->timat, normal);
+ normalize_v3(normal);
+
+ struct SnapObjectHitDepth *hit_item = hit_depth_create(
+ depth, location, normal, hit->index, data->ob, data->obmat, data->ob_uuid);
+ BLI_addtail(data->hit_list, hit_item);
+ }
}
-
-static bool raycastMesh(
- SnapObjectContext *sctx,
- const float ray_start[3], const float ray_dir[3],
- Object *ob, Mesh *me, float obmat[4][4], const unsigned int ob_index,
- /* read/write args */
- float *ray_depth,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- ListBase *r_hit_list)
+static bool raycastMesh(SnapObjectContext *sctx,
+ const float ray_start[3],
+ const float ray_dir[3],
+ Object *ob,
+ Mesh *me,
+ float obmat[4][4],
+ const unsigned int ob_index,
+ /* read/write args */
+ float *ray_depth,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ ListBase *r_hit_list)
{
- bool retval = false;
-
- if (me->totpoly == 0) {
- return retval;
- }
-
- float imat[4][4];
- float ray_start_local[3], ray_normal_local[3];
- float local_scale, local_depth, len_diff = 0.0f;
-
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(ray_start_local, ray_start);
- copy_v3_v3(ray_normal_local, ray_dir);
-
- mul_m4_v3(imat, ray_start_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
-
- /* local scale in normal direction */
- local_scale = normalize_v3(ray_normal_local);
- local_depth = *ray_depth;
- if (local_depth != BVH_RAYCAST_DIST_MAX) {
- local_depth *= local_scale;
- }
-
- /* Test BoundBox */
- BoundBox *bb = BKE_mesh_boundbox_get(ob);
- if (bb) {
- /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
- if (!isect_ray_aabb_v3_simple(
- ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &len_diff, NULL))
- {
- return retval;
- }
- }
- /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
- * very far away ray_start values (as returned in case of ortho view3d), see T50486, T38358.
- */
- if (len_diff > 400.0f) {
- len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
- madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
- local_depth -= len_diff;
- }
- else {
- len_diff = 0.0f;
- }
-
- SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob);
-
- BVHTreeFromMesh *treedata = &sod->treedata;
-
- /* The tree is owned by the Mesh and may have been freed since we last used. */
- if (treedata->tree) {
- BLI_assert(treedata->cached);
- if (!bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) {
- free_bvhtree_from_mesh(treedata);
- }
- else {
- /* Update Pointers. */
- if (treedata->vert && treedata->vert_allocated == false) {
- treedata->vert = me->mvert;
- }
- if (treedata->loop && treedata->loop_allocated == false) {
- treedata->loop = me->mloop;
- }
- if (treedata->looptri && treedata->looptri_allocated == false) {
- treedata->looptri = BKE_mesh_runtime_looptri_ensure(me);
- }
- /* required for snapping with occlusion. */
- treedata->edge = me->medge;
- sod->poly = me->mpoly;
- }
- }
-
- if (treedata->tree == NULL) {
- BKE_bvhtree_from_mesh_get(treedata, me, BVHTREE_FROM_LOOPTRI, 4);
-
- /* required for snapping with occlusion. */
- treedata->edge = me->medge;
- sod->poly = me->mpoly;
-
- if (treedata->tree == NULL) {
- return retval;
- }
- }
-
- float timat[3][3]; /* transpose inverse matrix for normals */
- transpose_m3_m4(timat, imat);
-
- if (r_hit_list) {
- struct RayCastAll_Data data;
-
- data.bvhdata = treedata;
- data.raycast_callback = treedata->raycast_callback;
- data.obmat = obmat;
- data.timat = timat;
- data.len_diff = len_diff;
- data.local_scale = local_scale;
- data.ob = ob;
- data.ob_uuid = ob_index;
- data.hit_list = r_hit_list;
- data.retval = retval;
-
- BLI_bvhtree_ray_cast_all(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- *ray_depth, raycast_all_cb, &data);
-
- retval = data.retval;
- }
- else {
- BVHTreeRayHit hit = { .index = -1, .dist = local_depth, };
-
- if (BLI_bvhtree_ray_cast(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- &hit, treedata->raycast_callback, treedata) != -1)
- {
- hit.dist += len_diff;
- hit.dist /= local_scale;
- if (hit.dist <= *ray_depth) {
- *ray_depth = hit.dist;
- copy_v3_v3(r_loc, hit.co);
-
- /* back to worldspace */
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- copy_v3_v3(r_no, hit.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
-
- retval = true;
-
- if (r_index) {
- *r_index = treedata->looptri[hit.index].poly;
- }
- }
- }
- }
-
- return retval;
+ bool retval = false;
+
+ if (me->totpoly == 0) {
+ return retval;
+ }
+
+ float imat[4][4];
+ float ray_start_local[3], ray_normal_local[3];
+ float local_scale, local_depth, len_diff = 0.0f;
+
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(ray_start_local, ray_start);
+ copy_v3_v3(ray_normal_local, ray_dir);
+
+ mul_m4_v3(imat, ray_start_local);
+ mul_mat3_m4_v3(imat, ray_normal_local);
+
+ /* local scale in normal direction */
+ local_scale = normalize_v3(ray_normal_local);
+ local_depth = *ray_depth;
+ if (local_depth != BVH_RAYCAST_DIST_MAX) {
+ local_depth *= local_scale;
+ }
+
+ /* Test BoundBox */
+ BoundBox *bb = BKE_mesh_boundbox_get(ob);
+ if (bb) {
+ /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
+ if (!isect_ray_aabb_v3_simple(
+ ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &len_diff, NULL)) {
+ return retval;
+ }
+ }
+ /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
+ * very far away ray_start values (as returned in case of ortho view3d), see T50486, T38358.
+ */
+ if (len_diff > 400.0f) {
+ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
+ madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
+ local_depth -= len_diff;
+ }
+ else {
+ len_diff = 0.0f;
+ }
+
+ SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob);
+
+ BVHTreeFromMesh *treedata = &sod->treedata;
+
+ /* The tree is owned by the Mesh and may have been freed since we last used. */
+ if (treedata->tree) {
+ BLI_assert(treedata->cached);
+ if (!bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) {
+ free_bvhtree_from_mesh(treedata);
+ }
+ else {
+ /* Update Pointers. */
+ if (treedata->vert && treedata->vert_allocated == false) {
+ treedata->vert = me->mvert;
+ }
+ if (treedata->loop && treedata->loop_allocated == false) {
+ treedata->loop = me->mloop;
+ }
+ if (treedata->looptri && treedata->looptri_allocated == false) {
+ treedata->looptri = BKE_mesh_runtime_looptri_ensure(me);
+ }
+ /* required for snapping with occlusion. */
+ treedata->edge = me->medge;
+ sod->poly = me->mpoly;
+ }
+ }
+
+ if (treedata->tree == NULL) {
+ BKE_bvhtree_from_mesh_get(treedata, me, BVHTREE_FROM_LOOPTRI, 4);
+
+ /* required for snapping with occlusion. */
+ treedata->edge = me->medge;
+ sod->poly = me->mpoly;
+
+ if (treedata->tree == NULL) {
+ return retval;
+ }
+ }
+
+ float timat[3][3]; /* transpose inverse matrix for normals */
+ transpose_m3_m4(timat, imat);
+
+ if (r_hit_list) {
+ struct RayCastAll_Data data;
+
+ data.bvhdata = treedata;
+ data.raycast_callback = treedata->raycast_callback;
+ data.obmat = obmat;
+ data.timat = timat;
+ data.len_diff = len_diff;
+ data.local_scale = local_scale;
+ data.ob = ob;
+ data.ob_uuid = ob_index;
+ data.hit_list = r_hit_list;
+ data.retval = retval;
+
+ BLI_bvhtree_ray_cast_all(treedata->tree,
+ ray_start_local,
+ ray_normal_local,
+ 0.0f,
+ *ray_depth,
+ raycast_all_cb,
+ &data);
+
+ retval = data.retval;
+ }
+ else {
+ BVHTreeRayHit hit = {
+ .index = -1,
+ .dist = local_depth,
+ };
+
+ if (BLI_bvhtree_ray_cast(treedata->tree,
+ ray_start_local,
+ ray_normal_local,
+ 0.0f,
+ &hit,
+ treedata->raycast_callback,
+ treedata) != -1) {
+ hit.dist += len_diff;
+ hit.dist /= local_scale;
+ if (hit.dist <= *ray_depth) {
+ *ray_depth = hit.dist;
+ copy_v3_v3(r_loc, hit.co);
+
+ /* back to worldspace */
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ copy_v3_v3(r_no, hit.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
+
+ retval = true;
+
+ if (r_index) {
+ *r_index = treedata->looptri[hit.index].poly;
+ }
+ }
+ }
+ }
+
+ return retval;
}
-static bool raycastEditMesh(
- SnapObjectContext *sctx,
- const float ray_start[3], const float ray_dir[3],
- Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index,
- /* read/write args */
- float *ray_depth,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- ListBase *r_hit_list)
+static bool raycastEditMesh(SnapObjectContext *sctx,
+ const float ray_start[3],
+ const float ray_dir[3],
+ Object *ob,
+ BMEditMesh *em,
+ float obmat[4][4],
+ const unsigned int ob_index,
+ /* read/write args */
+ float *ray_depth,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ ListBase *r_hit_list)
{
- bool retval = false;
- if (em->bm->totface == 0) {
- return retval;
- }
-
- BLI_assert(BKE_object_get_pre_modified_mesh(em->ob) == BKE_object_get_pre_modified_mesh(ob));
-
- float imat[4][4];
- float ray_start_local[3], ray_normal_local[3];
- float local_scale, local_depth, len_diff = 0.0f;
-
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(ray_start_local, ray_start);
- copy_v3_v3(ray_normal_local, ray_dir);
-
- mul_m4_v3(imat, ray_start_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
-
- /* local scale in normal direction */
- local_scale = normalize_v3(ray_normal_local);
- local_depth = *ray_depth;
- if (local_depth != BVH_RAYCAST_DIST_MAX) {
- local_depth *= local_scale;
- }
-
- SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, em);
-
- /* Test BoundBox */
-
- /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
- if (!isect_ray_aabb_v3_simple(
- ray_start_local, ray_normal_local, sod->min, sod->max, &len_diff, NULL))
- {
- return retval;
- }
-
- /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
- * very far away ray_start values (as returned in case of ortho view3d), see T50486, T38358.
- */
- if (len_diff > 400.0f) {
- len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
- madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
- local_depth -= len_diff;
- }
- else {
- 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 *)em->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 (!bvhcache_has_tree(em_bvh_cache, treedata->tree)) {
- free_bvhtree_from_editmesh(treedata);
- }
- }
-
- if (treedata->tree == NULL) {
- BVHCache **bvh_cache = NULL;
- BLI_bitmap *elem_mask = NULL;
- BMEditMesh *em_orig;
- int looptri_num_active = -1;
-
- /* Get original version of the edit_mesh. */
- em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
-
- 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);
-
- elem_mask = BLI_BITMAP_NEW(em_orig->tottri, __func__);
- looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
- bm, elem_mask,
- sctx->callbacks.edit_mesh.test_face_fn,
- sctx->callbacks.edit_mesh.user_data);
- }
- else {
- /* Only cache if bvhtree is created without a mask.
- * This helps keep a standardized bvhtree in cache. */
- bvh_cache = &em_bvh_cache;
- }
-
- bvhtree_from_editmesh_looptri_ex(
- treedata, em_orig, elem_mask, looptri_num_active,
- 0.0f, 4, 6, bvh_cache);
-
- if (elem_mask) {
- MEM_freeN(elem_mask);
- }
- if (treedata->tree == NULL) {
- return retval;
- }
- }
-
- float timat[3][3]; /* transpose inverse matrix for normals */
- transpose_m3_m4(timat, imat);
-
- if (r_hit_list) {
- struct RayCastAll_Data data;
-
- data.bvhdata = treedata;
- data.raycast_callback = treedata->raycast_callback;
- data.obmat = obmat;
- data.timat = timat;
- data.len_diff = len_diff;
- data.local_scale = local_scale;
- data.ob = ob;
- data.ob_uuid = ob_index;
- data.hit_list = r_hit_list;
- data.retval = retval;
-
- BLI_bvhtree_ray_cast_all(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- *ray_depth, raycast_all_cb, &data);
-
- retval = data.retval;
- }
- else {
- BVHTreeRayHit hit = { .index = -1, .dist = local_depth, };
-
- if (BLI_bvhtree_ray_cast(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- &hit, treedata->raycast_callback, treedata) != -1)
- {
- hit.dist += len_diff;
- hit.dist /= local_scale;
- if (hit.dist <= *ray_depth) {
- *ray_depth = hit.dist;
- copy_v3_v3(r_loc, hit.co);
-
- /* back to worldspace */
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- copy_v3_v3(r_no, hit.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
-
- retval = true;
-
- if (r_index) {
- /* Get original version of the edit_mesh. */
- BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
-
- *r_index = BM_elem_index_get(em_orig->looptris[hit.index][0]->f);
- }
- }
- }
- }
-
- return retval;
+ bool retval = false;
+ if (em->bm->totface == 0) {
+ return retval;
+ }
+
+ BLI_assert(BKE_object_get_pre_modified_mesh(em->ob) == BKE_object_get_pre_modified_mesh(ob));
+
+ float imat[4][4];
+ float ray_start_local[3], ray_normal_local[3];
+ float local_scale, local_depth, len_diff = 0.0f;
+
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(ray_start_local, ray_start);
+ copy_v3_v3(ray_normal_local, ray_dir);
+
+ mul_m4_v3(imat, ray_start_local);
+ mul_mat3_m4_v3(imat, ray_normal_local);
+
+ /* local scale in normal direction */
+ local_scale = normalize_v3(ray_normal_local);
+ local_depth = *ray_depth;
+ if (local_depth != BVH_RAYCAST_DIST_MAX) {
+ local_depth *= local_scale;
+ }
+
+ SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, em);
+
+ /* Test BoundBox */
+
+ /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
+ if (!isect_ray_aabb_v3_simple(
+ ray_start_local, ray_normal_local, sod->min, sod->max, &len_diff, NULL)) {
+ return retval;
+ }
+
+ /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
+ * very far away ray_start values (as returned in case of ortho view3d), see T50486, T38358.
+ */
+ if (len_diff > 400.0f) {
+ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
+ madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
+ local_depth -= len_diff;
+ }
+ else {
+ 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 *)em->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 (!bvhcache_has_tree(em_bvh_cache, treedata->tree)) {
+ free_bvhtree_from_editmesh(treedata);
+ }
+ }
+
+ if (treedata->tree == NULL) {
+ BVHCache **bvh_cache = NULL;
+ BLI_bitmap *elem_mask = NULL;
+ BMEditMesh *em_orig;
+ int looptri_num_active = -1;
+
+ /* Get original version of the edit_mesh. */
+ em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
+
+ 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);
+
+ elem_mask = BLI_BITMAP_NEW(em_orig->tottri, __func__);
+ looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
+ bm,
+ elem_mask,
+ sctx->callbacks.edit_mesh.test_face_fn,
+ sctx->callbacks.edit_mesh.user_data);
+ }
+ else {
+ /* Only cache if bvhtree is created without a mask.
+ * This helps keep a standardized bvhtree in cache. */
+ bvh_cache = &em_bvh_cache;
+ }
+
+ bvhtree_from_editmesh_looptri_ex(
+ treedata, em_orig, elem_mask, looptri_num_active, 0.0f, 4, 6, bvh_cache);
+
+ if (elem_mask) {
+ MEM_freeN(elem_mask);
+ }
+ if (treedata->tree == NULL) {
+ return retval;
+ }
+ }
+
+ float timat[3][3]; /* transpose inverse matrix for normals */
+ transpose_m3_m4(timat, imat);
+
+ if (r_hit_list) {
+ struct RayCastAll_Data data;
+
+ data.bvhdata = treedata;
+ data.raycast_callback = treedata->raycast_callback;
+ data.obmat = obmat;
+ data.timat = timat;
+ data.len_diff = len_diff;
+ data.local_scale = local_scale;
+ data.ob = ob;
+ data.ob_uuid = ob_index;
+ data.hit_list = r_hit_list;
+ data.retval = retval;
+
+ BLI_bvhtree_ray_cast_all(treedata->tree,
+ ray_start_local,
+ ray_normal_local,
+ 0.0f,
+ *ray_depth,
+ raycast_all_cb,
+ &data);
+
+ retval = data.retval;
+ }
+ else {
+ BVHTreeRayHit hit = {
+ .index = -1,
+ .dist = local_depth,
+ };
+
+ if (BLI_bvhtree_ray_cast(treedata->tree,
+ ray_start_local,
+ ray_normal_local,
+ 0.0f,
+ &hit,
+ treedata->raycast_callback,
+ treedata) != -1) {
+ hit.dist += len_diff;
+ hit.dist /= local_scale;
+ if (hit.dist <= *ray_depth) {
+ *ray_depth = hit.dist;
+ copy_v3_v3(r_loc, hit.co);
+
+ /* back to worldspace */
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ copy_v3_v3(r_no, hit.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
+
+ retval = true;
+
+ if (r_index) {
+ /* Get original version of the edit_mesh. */
+ BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
+
+ *r_index = BM_elem_index_get(em_orig->looptris[hit.index][0]->f);
+ }
+ }
+ }
+ }
+
+ return retval;
}
-
/**
* \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping;
*
* \note Duplicate args here are documented at #snapObjectsRay
*/
-static bool raycastObj(
- SnapObjectContext *sctx,
- const float ray_start[3], const float ray_dir[3],
- Object *ob, float obmat[4][4], const unsigned int ob_index,
- bool use_obedit, bool use_occlusion_test,
- /* read/write args */
- float *ray_depth,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4],
- ListBase *r_hit_list)
+static bool raycastObj(SnapObjectContext *sctx,
+ const float ray_start[3],
+ const float ray_dir[3],
+ Object *ob,
+ float obmat[4][4],
+ const unsigned int ob_index,
+ bool use_obedit,
+ bool use_occlusion_test,
+ /* read/write args */
+ float *ray_depth,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4],
+ ListBase *r_hit_list)
{
- bool retval = false;
-
- switch (ob->type) {
- case OB_MESH:
- {
- if (use_occlusion_test) {
- if (use_obedit && sctx->use_v3d &&
- XRAY_ENABLED(sctx->v3d_data.v3d))
- {
- /* Use of occlude geometry in editing mode disabled. */
- return false;
- }
-
- if (ELEM(ob->dt, OB_BOUNDBOX, OB_WIRE)) {
- /* Do not hit objects that are in wire or bounding box
- * display mode. */
- return false;
- }
- }
-
- Mesh *me = ob->data;
- if (BKE_object_is_in_editmode(ob)) {
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- if (use_obedit) {
- retval = raycastEditMesh(
- sctx,
- ray_start, ray_dir,
- ob, em, obmat, ob_index,
- ray_depth, r_loc, r_no, r_index, r_hit_list);
- break;
- }
- else if (em->mesh_eval_final) {
- me = em->mesh_eval_final;
- }
- }
- retval = raycastMesh(
- sctx,
- ray_start, ray_dir,
- ob, me, obmat, ob_index,
- ray_depth, r_loc, r_no, r_index, r_hit_list);
- break;
- }
- }
-
- if (retval) {
- if (r_ob) {
- *r_ob = ob;
- }
- if (r_obmat) {
- copy_m4_m4(r_obmat, obmat);
- }
- return true;
- }
-
- return false;
+ bool retval = false;
+
+ switch (ob->type) {
+ case OB_MESH: {
+ if (use_occlusion_test) {
+ if (use_obedit && sctx->use_v3d && XRAY_ENABLED(sctx->v3d_data.v3d)) {
+ /* Use of occlude geometry in editing mode disabled. */
+ return false;
+ }
+
+ if (ELEM(ob->dt, OB_BOUNDBOX, OB_WIRE)) {
+ /* Do not hit objects that are in wire or bounding box
+ * display mode. */
+ return false;
+ }
+ }
+
+ Mesh *me = ob->data;
+ if (BKE_object_is_in_editmode(ob)) {
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ if (use_obedit) {
+ retval = raycastEditMesh(sctx,
+ ray_start,
+ ray_dir,
+ ob,
+ em,
+ obmat,
+ ob_index,
+ ray_depth,
+ r_loc,
+ r_no,
+ r_index,
+ r_hit_list);
+ break;
+ }
+ else if (em->mesh_eval_final) {
+ me = em->mesh_eval_final;
+ }
+ }
+ retval = raycastMesh(sctx,
+ ray_start,
+ ray_dir,
+ ob,
+ me,
+ obmat,
+ ob_index,
+ ray_depth,
+ r_loc,
+ r_no,
+ r_index,
+ r_hit_list);
+ break;
+ }
+ }
+
+ if (retval) {
+ if (r_ob) {
+ *r_ob = ob;
+ }
+ if (r_obmat) {
+ copy_m4_m4(r_obmat, obmat);
+ }
+ return true;
+ }
+
+ return false;
}
-
struct RaycastObjUserData {
- const float *ray_start;
- const float *ray_dir;
- unsigned int ob_index;
- /* read/write args */
- float *ray_depth;
- /* return args */
- float *r_loc;
- float *r_no;
- int *r_index;
- Object **r_ob;
- float (*r_obmat)[4];
- ListBase *r_hit_list;
- bool use_occlusion_test;
- bool ret;
+ const float *ray_start;
+ const float *ray_dir;
+ unsigned int ob_index;
+ /* read/write args */
+ float *ray_depth;
+ /* return args */
+ float *r_loc;
+ float *r_no;
+ int *r_index;
+ Object **r_ob;
+ float (*r_obmat)[4];
+ ListBase *r_hit_list;
+ bool use_occlusion_test;
+ bool ret;
};
-static void raycast_obj_cb(SnapObjectContext *sctx, bool use_obedit, Object *ob, float obmat[4][4], void *data)
+static void raycast_obj_cb(
+ SnapObjectContext *sctx, bool use_obedit, Object *ob, float obmat[4][4], void *data)
{
- struct RaycastObjUserData *dt = data;
-
- dt->ret |= raycastObj(
- sctx,
- dt->ray_start, dt->ray_dir,
- ob, obmat, dt->ob_index++,
- use_obedit, dt->use_occlusion_test,
- dt->ray_depth,
- dt->r_loc, dt->r_no, dt->r_index,
- dt->r_ob, dt->r_obmat,
- dt->r_hit_list);
+ struct RaycastObjUserData *dt = data;
+
+ dt->ret |= raycastObj(sctx,
+ dt->ray_start,
+ dt->ray_dir,
+ ob,
+ obmat,
+ dt->ob_index++,
+ use_obedit,
+ dt->use_occlusion_test,
+ dt->ray_depth,
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index,
+ dt->r_ob,
+ dt->r_obmat,
+ dt->r_hit_list);
}
/**
@@ -788,202 +839,194 @@ static void raycast_obj_cb(SnapObjectContext *sctx, bool use_obedit, Object *ob,
* \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances).
* \param r_hit_list: List of #SnapObjectHitDepth (caller must free).
*/
-static bool raycastObjects(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_start[3], const float ray_dir[3],
- /* read/write args */
- float *ray_depth,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4],
- ListBase *r_hit_list)
+static bool raycastObjects(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_start[3],
+ const float ray_dir[3],
+ /* read/write args */
+ float *ray_depth,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4],
+ ListBase *r_hit_list)
{
- struct RaycastObjUserData data = {
- .ray_start = ray_start,
- .ray_dir = ray_dir,
- .ob_index = 0,
- .ray_depth = ray_depth,
- .r_loc = r_loc,
- .r_no = r_no,
- .r_index = r_index,
- .r_ob = r_ob,
- .r_obmat = r_obmat,
- .r_hit_list = r_hit_list,
- .use_occlusion_test = params->use_occlusion_test,
- .ret = false,
- };
-
- iter_snap_objects(sctx, params, raycast_obj_cb, &data);
-
- return data.ret;
+ struct RaycastObjUserData data = {
+ .ray_start = ray_start,
+ .ray_dir = ray_dir,
+ .ob_index = 0,
+ .ray_depth = ray_depth,
+ .r_loc = r_loc,
+ .r_no = r_no,
+ .r_index = r_index,
+ .r_ob = r_ob,
+ .r_obmat = r_obmat,
+ .r_hit_list = r_hit_list,
+ .use_occlusion_test = params->use_occlusion_test,
+ .ret = false,
+ };
+
+ iter_snap_objects(sctx, params, raycast_obj_cb, &data);
+
+ return data.ret;
}
-
/** \} */
/* -------------------------------------------------------------------- */
/** Snap Nearest utilities
* \{ */
- /* Test BoundBox */
-static bool snap_bound_box_check_dist(
- float min[3], float max[3], float lpmat[4][4],
- float win_size[2], float mval[2], float dist_px_sq)
+/* Test BoundBox */
+static bool snap_bound_box_check_dist(float min[3],
+ float max[3],
+ float lpmat[4][4],
+ float win_size[2],
+ float mval[2],
+ float dist_px_sq)
{
- /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
+ /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
- struct DistProjectedAABBPrecalc data_precalc;
- dist_squared_to_projected_aabb_precalc(
- &data_precalc, lpmat, win_size, mval);
+ struct DistProjectedAABBPrecalc data_precalc;
+ dist_squared_to_projected_aabb_precalc(&data_precalc, lpmat, win_size, mval);
- bool dummy[3];
- float bb_dist_px_sq = dist_squared_to_projected_aabb(
- &data_precalc, min, max, dummy);
+ bool dummy[3];
+ float bb_dist_px_sq = dist_squared_to_projected_aabb(&data_precalc, min, max, dummy);
- if (bb_dist_px_sq > dist_px_sq) {
- return false;
- }
- return true;
+ if (bb_dist_px_sq > dist_px_sq) {
+ return false;
+ }
+ return true;
}
-static void cb_mvert_co_get(
- const int index, const float **co, const BVHTreeFromMesh *data)
+static void cb_mvert_co_get(const int index, const float **co, const BVHTreeFromMesh *data)
{
- *co = data->vert[index].co;
+ *co = data->vert[index].co;
}
-static void cb_bvert_co_get(
- const int index, const float **co, const BMEditMesh *data)
+static void cb_bvert_co_get(const int index, const float **co, const BMEditMesh *data)
{
- BMVert *eve = BM_vert_at_index(data->bm, index);
- *co = eve->co;
+ BMVert *eve = BM_vert_at_index(data->bm, index);
+ *co = eve->co;
}
-static void cb_mvert_no_copy(
- const int index, float r_no[3], const BVHTreeFromMesh *data)
+static void cb_mvert_no_copy(const int index, float r_no[3], const BVHTreeFromMesh *data)
{
- const MVert *vert = data->vert + index;
+ const MVert *vert = data->vert + index;
- normal_short_to_float_v3(r_no, vert->no);
+ normal_short_to_float_v3(r_no, vert->no);
}
-static void cb_bvert_no_copy(
- const int index, float r_no[3], const BMEditMesh *data)
+static void cb_bvert_no_copy(const int index, float r_no[3], const BMEditMesh *data)
{
- BMVert *eve = BM_vert_at_index(data->bm, index);
+ BMVert *eve = BM_vert_at_index(data->bm, index);
- copy_v3_v3(r_no, eve->no);
+ copy_v3_v3(r_no, eve->no);
}
-static void cb_medge_verts_get(
- const int index, int v_index[2], const BVHTreeFromMesh *data)
+static void cb_medge_verts_get(const int index, int v_index[2], const BVHTreeFromMesh *data)
{
- const MEdge *edge = &data->edge[index];
-
- v_index[0] = edge->v1;
- v_index[1] = edge->v2;
+ const MEdge *edge = &data->edge[index];
+ v_index[0] = edge->v1;
+ v_index[1] = edge->v2;
}
-static void cb_bedge_verts_get(
- const int index, int v_index[2], const BMEditMesh *data)
+static void cb_bedge_verts_get(const int index, int v_index[2], const BMEditMesh *data)
{
- BMEdge *eed = BM_edge_at_index(data->bm, index);
+ BMEdge *eed = BM_edge_at_index(data->bm, index);
- v_index[0] = BM_elem_index_get(eed->v1);
- v_index[1] = BM_elem_index_get(eed->v2);
+ v_index[0] = BM_elem_index_get(eed->v1);
+ v_index[1] = BM_elem_index_get(eed->v2);
}
-static void cb_mlooptri_edges_get(
- const int index, int v_index[3], const BVHTreeFromMesh *data)
+static void cb_mlooptri_edges_get(const int index, int v_index[3], const BVHTreeFromMesh *data)
{
- const MEdge *medge = data->edge;
- const MLoop *mloop = data->loop;
- 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};
- 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;
- }
- else
- v_index[j] = -1;
- }
+ const MEdge *medge = data->edge;
+ const MLoop *mloop = data->loop;
+ 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};
+ 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;
+ }
+ else
+ v_index[j] = -1;
+ }
}
-static void cb_mlooptri_verts_get(
- const int index, int v_index[3], const BVHTreeFromMesh *data)
+static void cb_mlooptri_verts_get(const int index, int v_index[3], const BVHTreeFromMesh *data)
{
- const MLoop *loop = data->loop;
- const MLoopTri *looptri = &data->looptri[index];
+ const MLoop *loop = data->loop;
+ const MLoopTri *looptri = &data->looptri[index];
- v_index[0] = loop[looptri->tri[0]].v;
- v_index[1] = loop[looptri->tri[1]].v;
- v_index[2] = loop[looptri->tri[2]].v;
+ v_index[0] = loop[looptri->tri[0]].v;
+ v_index[1] = loop[looptri->tri[1]].v;
+ v_index[2] = loop[looptri->tri[2]].v;
}
-static bool test_projected_vert_dist(
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- const bool is_persp, const float co[3],
- float *dist_px_sq, float r_co[3])
+static bool test_projected_vert_dist(const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ const bool is_persp,
+ const float co[3],
+ float *dist_px_sq,
+ float r_co[3])
{
- if (!isect_point_planes_v3_negated(clip_plane, clip_plane_len, co)) {
- return false;
- }
-
- float co2d[2] = {
- (dot_m4_v3_row_x(precalc->pmat, co) + precalc->pmat[3][0]),
- (dot_m4_v3_row_y(precalc->pmat, co) + precalc->pmat[3][1]),
- };
-
- if (is_persp) {
- float w = mul_project_m4_v3_zfac(precalc->pmat, co);
- mul_v2_fl(co2d, 1.0f / w);
- }
-
- const float dist_sq = len_squared_v2v2(precalc->mval, co2d);
- if (dist_sq < *dist_px_sq) {
- copy_v3_v3(r_co, co);
- *dist_px_sq = dist_sq;
- return true;
- }
- return false;
+ if (!isect_point_planes_v3_negated(clip_plane, clip_plane_len, co)) {
+ return false;
+ }
+
+ float co2d[2] = {
+ (dot_m4_v3_row_x(precalc->pmat, co) + precalc->pmat[3][0]),
+ (dot_m4_v3_row_y(precalc->pmat, co) + precalc->pmat[3][1]),
+ };
+
+ if (is_persp) {
+ float w = mul_project_m4_v3_zfac(precalc->pmat, co);
+ mul_v2_fl(co2d, 1.0f / w);
+ }
+
+ const float dist_sq = len_squared_v2v2(precalc->mval, co2d);
+ if (dist_sq < *dist_px_sq) {
+ copy_v3_v3(r_co, co);
+ *dist_px_sq = dist_sq;
+ return true;
+ }
+ return false;
}
-static bool test_projected_edge_dist(
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- const bool is_persp, const float va[3], const float vb[3],
- float *dist_px_sq, float r_co[3])
+static bool test_projected_edge_dist(const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ const bool is_persp,
+ const float va[3],
+ const float vb[3],
+ float *dist_px_sq,
+ float r_co[3])
{
- float near_co[3], lambda;
- if (!isect_ray_seg_v3(
- precalc->ray_origin,
- precalc->ray_direction,
- va, vb, &lambda))
- {
- copy_v3_v3(near_co, va);
- }
- else {
- if (lambda <= 0.0f) {
- copy_v3_v3(near_co, va);
- }
- else if (lambda >= 1.0f) {
- copy_v3_v3(near_co, vb);
- }
- else {
- interp_v3_v3v3(near_co, va, vb, lambda);
- }
- }
-
- return test_projected_vert_dist(
- precalc, clip_plane, clip_plane_len,
- is_persp, near_co, dist_px_sq, r_co);
+ float near_co[3], lambda;
+ if (!isect_ray_seg_v3(precalc->ray_origin, precalc->ray_direction, va, vb, &lambda)) {
+ copy_v3_v3(near_co, va);
+ }
+ else {
+ if (lambda <= 0.0f) {
+ copy_v3_v3(near_co, va);
+ }
+ else if (lambda >= 1.0f) {
+ copy_v3_v3(near_co, vb);
+ }
+ else {
+ interp_v3_v3v3(near_co, va, vb, lambda);
+ }
+ }
+
+ return test_projected_vert_dist(
+ precalc, clip_plane, clip_plane_len, is_persp, near_co, dist_px_sq, r_co);
}
/** \} */
@@ -1000,132 +1043,128 @@ typedef void (*Nearest2DGetTriEdgesCallback)(const int index, int e_index[3], vo
typedef void (*Nearest2DCopyVertNoCallback)(const int index, float r_no[3], void *data);
typedef struct Nearest2dUserData {
- bool is_persp;
+ bool is_persp;
- void *userdata;
- Nearest2DGetVertCoCallback get_vert_co;
- Nearest2DGetEdgeVertsCallback get_edge_verts_index;
- Nearest2DGetTriVertsCallback get_tri_verts_index;
- Nearest2DGetTriEdgesCallback get_tri_edges_index;
- Nearest2DCopyVertNoCallback copy_vert_no;
+ void *userdata;
+ Nearest2DGetVertCoCallback get_vert_co;
+ Nearest2DGetEdgeVertsCallback get_edge_verts_index;
+ Nearest2DGetTriVertsCallback get_tri_verts_index;
+ Nearest2DGetTriEdgesCallback get_tri_edges_index;
+ Nearest2DCopyVertNoCallback copy_vert_no;
} Nearest2dUserData;
-
-static void cb_snap_vert(
- void *userdata, int index,
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- BVHTreeNearest *nearest)
+static void cb_snap_vert(void *userdata,
+ int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ BVHTreeNearest *nearest)
{
- struct Nearest2dUserData *data = userdata;
-
- const float *co;
- data->get_vert_co(index, &co, data->userdata);
-
- if (test_projected_vert_dist(
- precalc,
- clip_plane,
- clip_plane_len,
- data->is_persp, co,
- &nearest->dist_sq,
- nearest->co))
- {
- data->copy_vert_no(index, nearest->no, data->userdata);
- nearest->index = index;
- }
+ struct Nearest2dUserData *data = userdata;
+
+ const float *co;
+ data->get_vert_co(index, &co, data->userdata);
+
+ if (test_projected_vert_dist(precalc,
+ clip_plane,
+ clip_plane_len,
+ data->is_persp,
+ co,
+ &nearest->dist_sq,
+ nearest->co)) {
+ data->copy_vert_no(index, nearest->no, data->userdata);
+ nearest->index = index;
+ }
}
-static void cb_snap_edge(
- void *userdata, int index,
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- BVHTreeNearest *nearest)
+static void cb_snap_edge(void *userdata,
+ int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ BVHTreeNearest *nearest)
{
- struct Nearest2dUserData *data = userdata;
-
- int vindex[2];
- data->get_edge_verts_index(index, vindex, data->userdata);
-
- const float *v_pair[2];
- data->get_vert_co(vindex[0], &v_pair[0], data->userdata);
- data->get_vert_co(vindex[1], &v_pair[1], data->userdata);
-
- if (test_projected_edge_dist(
- precalc,
- clip_plane,
- clip_plane_len,
- data->is_persp,
- v_pair[0], v_pair[1],
- &nearest->dist_sq,
- nearest->co))
- {
- sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]);
- nearest->index = index;
- }
+ struct Nearest2dUserData *data = userdata;
+
+ int vindex[2];
+ data->get_edge_verts_index(index, vindex, data->userdata);
+
+ const float *v_pair[2];
+ data->get_vert_co(vindex[0], &v_pair[0], data->userdata);
+ data->get_vert_co(vindex[1], &v_pair[1], data->userdata);
+
+ if (test_projected_edge_dist(precalc,
+ clip_plane,
+ clip_plane_len,
+ data->is_persp,
+ v_pair[0],
+ v_pair[1],
+ &nearest->dist_sq,
+ nearest->co)) {
+ sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]);
+ nearest->index = index;
+ }
}
-static void cb_snap_edge_verts(
- void *userdata, int index,
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- BVHTreeNearest *nearest)
+static void cb_snap_edge_verts(void *userdata,
+ int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ BVHTreeNearest *nearest)
{
- struct Nearest2dUserData *data = userdata;
-
- int vindex[2];
- data->get_edge_verts_index(index, vindex, data->userdata);
-
- for (int i = 2; i--;) {
- if (vindex[i] == nearest->index) {
- continue;
- }
- cb_snap_vert(
- userdata, vindex[i], precalc,
- clip_plane, clip_plane_len, nearest);
- }
+ struct Nearest2dUserData *data = userdata;
+
+ int vindex[2];
+ data->get_edge_verts_index(index, vindex, data->userdata);
+
+ for (int i = 2; i--;) {
+ if (vindex[i] == nearest->index) {
+ continue;
+ }
+ cb_snap_vert(userdata, vindex[i], precalc, clip_plane, clip_plane_len, nearest);
+ }
}
-static void cb_snap_tri_edges(
- void *userdata, int index,
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- BVHTreeNearest *nearest)
+static void cb_snap_tri_edges(void *userdata,
+ int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ BVHTreeNearest *nearest)
{
- struct Nearest2dUserData *data = userdata;
-
- int eindex[3];
- data->get_tri_edges_index(index, eindex, data->userdata);
- for (int i = 3; i--;) {
- if (eindex[i] != -1) {
- if (eindex[i] == nearest->index) {
- continue;
- }
- cb_snap_edge(
- userdata, eindex[i], precalc,
- clip_plane, clip_plane_len, nearest);
- }
- }
+ struct Nearest2dUserData *data = userdata;
+
+ int eindex[3];
+ data->get_tri_edges_index(index, eindex, data->userdata);
+ for (int i = 3; i--;) {
+ if (eindex[i] != -1) {
+ if (eindex[i] == nearest->index) {
+ continue;
+ }
+ cb_snap_edge(userdata, eindex[i], precalc, clip_plane, clip_plane_len, nearest);
+ }
+ }
}
-static void cb_snap_tri_verts(
- void *userdata, int index,
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- BVHTreeNearest *nearest)
+static void cb_snap_tri_verts(void *userdata,
+ int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ BVHTreeNearest *nearest)
{
- struct Nearest2dUserData *data = userdata;
-
- int vindex[3];
- data->get_tri_verts_index(index, vindex, data->userdata);
- for (int i = 3; i--;) {
- if (vindex[i] == nearest->index) {
- continue;
- }
- cb_snap_vert(
- userdata, vindex[i], precalc,
- clip_plane, clip_plane_len, nearest);
- }
+ struct Nearest2dUserData *data = userdata;
+
+ int vindex[3];
+ data->get_tri_verts_index(index, vindex, data->userdata);
+ for (int i = 3; i--;) {
+ if (vindex[i] == nearest->index) {
+ continue;
+ }
+ cb_snap_vert(userdata, vindex[i], precalc, clip_plane, clip_plane_len, nearest);
+ }
}
/** \} */
@@ -1134,1028 +1173,1124 @@ static void cb_snap_tri_verts(
/** \name Internal Object Snapping API
* \{ */
-static short snap_mesh_polygon(
- SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, float obmat[4][4],
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index)
+static short snap_mesh_polygon(SnapObjectContext *sctx,
+ SnapData *snapdata,
+ Object *ob,
+ float obmat[4][4],
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index)
{
- short elem = 0;
-
- float lpmat[4][4];
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
-
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- Nearest2dUserData nearest2d = {
- .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
- };
-
- BVHTreeNearest nearest = {
- .index = -1,
- .dist_sq = SQUARE(*dist_px),
- };
-
- SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
- if (sod == NULL) {
- /* The object is in edit mode, and the key used
- * was the object referenced in BMEditMesh */
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- sod = BLI_ghash_lookup(sctx->cache.object_map, em->ob);
- }
-
- BLI_assert(sod != NULL);
-
- if (sod->type == SNAP_MESH) {
- BVHTreeFromMesh *treedata = &((SnapObjectData_Mesh *)sod)->treedata;
-
- 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 MLoop *ml = &treedata->loop[mp->loopstart];
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- elem = SCE_SNAP_MODE_EDGE;
- BLI_assert(treedata->edge != NULL);
- for (int i = mp->totloop; i--; ml++) {
- cb_snap_edge(
- &nearest2d, ml->e, &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest);
- }
- }
- else {
- elem = SCE_SNAP_MODE_VERTEX;
- for (int i = mp->totloop; i--; ml++) {
- cb_snap_vert(
- &nearest2d, ml->v, &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest);
- }
- }
- }
- else {
- BLI_assert(sod->type == SNAP_EDIT_MESH);
- BMEditMesh *em = BKE_editmesh_from_object(ob);
-
- nearest2d.userdata = 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;
-
- BM_mesh_elem_table_ensure(em->bm, BM_FACE);
- BMFace *f = BM_face_at_index(em->bm, *r_index);
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- elem = SCE_SNAP_MODE_EDGE;
- BM_mesh_elem_index_ensure(em->bm, BM_EDGE);
- BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE);
- do {
- cb_snap_edge(
- &nearest2d, BM_elem_index_get(l_iter->e),
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest);
- } while ((l_iter = l_iter->next) != l_first);
- }
- else {
- elem = SCE_SNAP_MODE_VERTEX;
- BM_mesh_elem_index_ensure(em->bm, BM_VERT);
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
- do {
- cb_snap_vert(
- &nearest2d, BM_elem_index_get(l_iter->v),
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest);
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
-
- if (nearest.index != -1) {
- *dist_px = sqrtf(nearest.dist_sq);
-
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- float imat[4][4];
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(r_no, nearest.no);
- mul_transposed_mat3_m4_v3(imat, r_no);
- normalize_v3(r_no);
- }
-
- *r_index = nearest.index;
- return elem;
- }
-
- return 0;
+ short elem = 0;
+
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ Nearest2dUserData nearest2d = {
+ .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
+ };
+
+ BVHTreeNearest nearest = {
+ .index = -1,
+ .dist_sq = SQUARE(*dist_px),
+ };
+
+ SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
+ if (sod == NULL) {
+ /* The object is in edit mode, and the key used
+ * was the object referenced in BMEditMesh */
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ sod = BLI_ghash_lookup(sctx->cache.object_map, em->ob);
+ }
+
+ BLI_assert(sod != NULL);
+
+ if (sod->type == SNAP_MESH) {
+ BVHTreeFromMesh *treedata = &((SnapObjectData_Mesh *)sod)->treedata;
+
+ 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 MLoop *ml = &treedata->loop[mp->loopstart];
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ elem = SCE_SNAP_MODE_EDGE;
+ BLI_assert(treedata->edge != NULL);
+ for (int i = mp->totloop; i--; ml++) {
+ cb_snap_edge(&nearest2d,
+ ml->e,
+ &neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest);
+ }
+ }
+ else {
+ elem = SCE_SNAP_MODE_VERTEX;
+ for (int i = mp->totloop; i--; ml++) {
+ cb_snap_vert(&nearest2d,
+ ml->v,
+ &neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest);
+ }
+ }
+ }
+ else {
+ BLI_assert(sod->type == SNAP_EDIT_MESH);
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+
+ nearest2d.userdata = 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;
+
+ BM_mesh_elem_table_ensure(em->bm, BM_FACE);
+ BMFace *f = BM_face_at_index(em->bm, *r_index);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ elem = SCE_SNAP_MODE_EDGE;
+ BM_mesh_elem_index_ensure(em->bm, BM_EDGE);
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE);
+ do {
+ cb_snap_edge(&nearest2d,
+ BM_elem_index_get(l_iter->e),
+ &neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ else {
+ elem = SCE_SNAP_MODE_VERTEX;
+ BM_mesh_elem_index_ensure(em->bm, BM_VERT);
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ do {
+ cb_snap_vert(&nearest2d,
+ BM_elem_index_get(l_iter->v),
+ &neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+
+ if (nearest.index != -1) {
+ *dist_px = sqrtf(nearest.dist_sq);
+
+ copy_v3_v3(r_loc, nearest.co);
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ float imat[4][4];
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(r_no, nearest.no);
+ mul_transposed_mat3_m4_v3(imat, r_no);
+ normalize_v3(r_no);
+ }
+
+ *r_index = nearest.index;
+ return elem;
+ }
+
+ return 0;
}
-
-static short snap_mesh_edge_verts_mixed(
- SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, float obmat[4][4], float original_dist_px,
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index)
+static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
+ SnapData *snapdata,
+ Object *ob,
+ float obmat[4][4],
+ float original_dist_px,
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index)
{
- short elem = SCE_SNAP_MODE_EDGE;
-
- if (ob->type != OB_MESH) {
- return elem;
- }
-
- float lpmat[4][4];
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
-
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
-
- Nearest2dUserData nearest2d = {
- .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
- };
-
- BVHTreeNearest nearest = {
- .index = -1,
- .dist_sq = SQUARE(original_dist_px),
- };
-
- SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
- BLI_assert(sod != NULL);
-
- if (sod->type == SNAP_MESH) {
- nearest2d.userdata = &((SnapObjectData_Mesh *)sod)->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;
- }
- else {
- BLI_assert(sod->type == SNAP_EDIT_MESH);
- nearest2d.userdata = BKE_editmesh_from_object(ob);
- 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;
- }
-
- int vindex[2];
- nearest2d.get_edge_verts_index(*r_index, vindex, nearest2d.userdata);
-
- const float *v_pair[2];
- nearest2d.get_vert_co(vindex[0], &v_pair[0], nearest2d.userdata);
- nearest2d.get_vert_co(vindex[1], &v_pair[1], nearest2d.userdata);
-
- float lambda;
- if (!isect_ray_seg_v3(
- neasrest_precalc.ray_origin,
- neasrest_precalc.ray_direction,
- v_pair[0], v_pair[1], &lambda))
- {
- /* do nothing */
- }
- else if (lambda < 0.25f || 0.75f < lambda) {
- int v_id = lambda < 0.5f ? 0 : 1;
-
- if (test_projected_vert_dist(
- &neasrest_precalc, NULL, 0,
- nearest2d.is_persp, v_pair[v_id],
- &nearest.dist_sq, nearest.co))
- {
- nearest.index = vindex[v_id];
- nearest2d.copy_vert_no(vindex[v_id], nearest.no, nearest2d.userdata);
- elem = SCE_SNAP_MODE_VERTEX;
- }
- }
-
- if (nearest.index != -1) {
- *dist_px = sqrtf(nearest.dist_sq);
-
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- float imat[4][4];
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(r_no, nearest.no);
- mul_transposed_mat3_m4_v3(imat, r_no);
- normalize_v3(r_no);
- }
-
- *r_index = nearest.index;
- }
-
- return elem;
+ short elem = SCE_SNAP_MODE_EDGE;
+
+ if (ob->type != OB_MESH) {
+ return elem;
+ }
+
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
+
+ Nearest2dUserData nearest2d = {
+ .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
+ };
+
+ BVHTreeNearest nearest = {
+ .index = -1,
+ .dist_sq = SQUARE(original_dist_px),
+ };
+
+ SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
+ BLI_assert(sod != NULL);
+
+ if (sod->type == SNAP_MESH) {
+ nearest2d.userdata = &((SnapObjectData_Mesh *)sod)->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;
+ }
+ else {
+ BLI_assert(sod->type == SNAP_EDIT_MESH);
+ nearest2d.userdata = BKE_editmesh_from_object(ob);
+ 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;
+ }
+
+ int vindex[2];
+ nearest2d.get_edge_verts_index(*r_index, vindex, nearest2d.userdata);
+
+ const float *v_pair[2];
+ nearest2d.get_vert_co(vindex[0], &v_pair[0], nearest2d.userdata);
+ nearest2d.get_vert_co(vindex[1], &v_pair[1], nearest2d.userdata);
+
+ float lambda;
+ if (!isect_ray_seg_v3(neasrest_precalc.ray_origin,
+ neasrest_precalc.ray_direction,
+ v_pair[0],
+ v_pair[1],
+ &lambda)) {
+ /* do nothing */
+ }
+ else if (lambda < 0.25f || 0.75f < lambda) {
+ int v_id = lambda < 0.5f ? 0 : 1;
+
+ if (test_projected_vert_dist(&neasrest_precalc,
+ NULL,
+ 0,
+ nearest2d.is_persp,
+ v_pair[v_id],
+ &nearest.dist_sq,
+ nearest.co)) {
+ nearest.index = vindex[v_id];
+ nearest2d.copy_vert_no(vindex[v_id], nearest.no, nearest2d.userdata);
+ elem = SCE_SNAP_MODE_VERTEX;
+ }
+ }
+
+ if (nearest.index != -1) {
+ *dist_px = sqrtf(nearest.dist_sq);
+
+ copy_v3_v3(r_loc, nearest.co);
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ float imat[4][4];
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(r_no, nearest.no);
+ mul_transposed_mat3_m4_v3(imat, r_no);
+ normalize_v3(r_no);
+ }
+
+ *r_index = nearest.index;
+ }
+
+ return elem;
}
-static short snapArmature(
- SnapData *snapdata,
- Object *ob, float obmat[4][4], bool use_obedit,
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float *UNUSED(r_no), int *r_index)
+static short snapArmature(SnapData *snapdata,
+ Object *ob,
+ float obmat[4][4],
+ bool use_obedit,
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float *UNUSED(r_no),
+ int *r_index)
{
- short retval = 0;
-
- if (snapdata->snap_to_flag == SCE_SNAP_MODE_FACE) { /* Currently only edge and vert */
- return retval;
- }
-
- float lpmat[4][4], dist_px_sq = SQUARE(*dist_px);
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
-
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
-
- use_obedit = use_obedit && BKE_object_is_in_editmode(ob);
-
- if (use_obedit == false) {
- /* Test BoundBox */
- BoundBox *bb = BKE_armature_boundbox_get(ob);
- if (bb && !snap_bound_box_check_dist(
- bb->vec[0], bb->vec[6], lpmat,
- snapdata->win_size, snapdata->mval, dist_px_sq))
- {
- return retval;
- }
- }
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
-
- bArmature *arm = ob->data;
- if (arm->edbo) {
- for (EditBone *eBone = arm->edbo->first; eBone; eBone = eBone->next) {
- if (eBone->layer & arm->layer) {
- /* skip hidden or moving (selected) bones */
- if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
- bool has_vert_snap = false;
-
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- has_vert_snap = test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, eBone->head, &dist_px_sq, r_loc);
- has_vert_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, eBone->tail, &dist_px_sq, r_loc);
-
- if (has_vert_snap) {
- retval = SCE_SNAP_MODE_VERTEX;
- }
- }
- if (!has_vert_snap && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- if (test_projected_edge_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, eBone->head, eBone->tail,
- &dist_px_sq, r_loc))
- {
- retval = SCE_SNAP_MODE_EDGE;
- }
- }
- }
- }
- }
- }
- else if (ob->pose && ob->pose->chanbase.first) {
- for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- Bone *bone = pchan->bone;
- /* skip hidden bones */
- if (bone && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
- bool has_vert_snap = false;
- const float *head_vec = pchan->pose_head;
- const float *tail_vec = pchan->pose_tail;
-
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- has_vert_snap = test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, head_vec, &dist_px_sq, r_loc);
- has_vert_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, tail_vec, &dist_px_sq, r_loc);
-
- if (has_vert_snap) {
- retval = SCE_SNAP_MODE_VERTEX;
- }
- }
- if (!has_vert_snap && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- if (test_projected_edge_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, head_vec, tail_vec,
- &dist_px_sq, r_loc))
- {
- retval = SCE_SNAP_MODE_EDGE;
- }
- }
- }
- }
- }
-
- if (retval) {
- *dist_px = sqrtf(dist_px_sq);
- mul_m4_v3(obmat, r_loc);
- if (r_index) {
- /* Does not support index. */
- *r_index = -1;
- }
- return retval;
- }
-
- return 0;
+ short retval = 0;
+
+ if (snapdata->snap_to_flag == SCE_SNAP_MODE_FACE) { /* Currently only edge and vert */
+ return retval;
+ }
+
+ float lpmat[4][4], dist_px_sq = SQUARE(*dist_px);
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
+
+ use_obedit = use_obedit && BKE_object_is_in_editmode(ob);
+
+ if (use_obedit == false) {
+ /* Test BoundBox */
+ BoundBox *bb = BKE_armature_boundbox_get(ob);
+ if (bb && !snap_bound_box_check_dist(
+ bb->vec[0], bb->vec[6], lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
+ return retval;
+ }
+ }
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+
+ bArmature *arm = ob->data;
+ if (arm->edbo) {
+ for (EditBone *eBone = arm->edbo->first; eBone; eBone = eBone->next) {
+ if (eBone->layer & arm->layer) {
+ /* skip hidden or moving (selected) bones */
+ if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
+ bool has_vert_snap = false;
+
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ has_vert_snap = test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ eBone->head,
+ &dist_px_sq,
+ r_loc);
+ has_vert_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ eBone->tail,
+ &dist_px_sq,
+ r_loc);
+
+ if (has_vert_snap) {
+ retval = SCE_SNAP_MODE_VERTEX;
+ }
+ }
+ if (!has_vert_snap && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ if (test_projected_edge_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ eBone->head,
+ eBone->tail,
+ &dist_px_sq,
+ r_loc)) {
+ retval = SCE_SNAP_MODE_EDGE;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (ob->pose && ob->pose->chanbase.first) {
+ for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ Bone *bone = pchan->bone;
+ /* skip hidden bones */
+ if (bone && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
+ bool has_vert_snap = false;
+ const float *head_vec = pchan->pose_head;
+ const float *tail_vec = pchan->pose_tail;
+
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ has_vert_snap = test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ head_vec,
+ &dist_px_sq,
+ r_loc);
+ has_vert_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ tail_vec,
+ &dist_px_sq,
+ r_loc);
+
+ if (has_vert_snap) {
+ retval = SCE_SNAP_MODE_VERTEX;
+ }
+ }
+ if (!has_vert_snap && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ if (test_projected_edge_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ head_vec,
+ tail_vec,
+ &dist_px_sq,
+ r_loc)) {
+ retval = SCE_SNAP_MODE_EDGE;
+ }
+ }
+ }
+ }
+ }
+
+ if (retval) {
+ *dist_px = sqrtf(dist_px_sq);
+ mul_m4_v3(obmat, r_loc);
+ if (r_index) {
+ /* Does not support index. */
+ *r_index = -1;
+ }
+ return retval;
+ }
+
+ return 0;
}
-static short snapCurve(
- SnapData *snapdata,
- Object *ob, float obmat[4][4], bool use_obedit,
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float *UNUSED(r_no), int *r_index)
+static short snapCurve(SnapData *snapdata,
+ Object *ob,
+ float obmat[4][4],
+ bool use_obedit,
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float *UNUSED(r_no),
+ int *r_index)
{
- bool has_snap = false;
-
- /* only vertex snapping mode (eg control points and handles) supported for now) */
- if (snapdata->snap_to_flag != SCE_SNAP_MODE_VERTEX) {
- return 0;
- }
-
- Curve *cu = ob->data;
- float dist_px_sq = SQUARE(*dist_px);
-
- float lpmat[4][4];
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
-
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
-
- use_obedit = use_obedit && BKE_object_is_in_editmode(ob);
-
- if (use_obedit == false) {
- /* Test BoundBox */
- BoundBox *bb = BKE_curve_texspace_get(cu, NULL, NULL, NULL);
- if (bb && !snap_bound_box_check_dist(
- bb->vec[0], bb->vec[6], lpmat,
- snapdata->win_size, snapdata->mval, dist_px_sq))
- {
- return 0;
- }
- }
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
-
- for (Nurb *nu = (use_obedit ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
- for (int u = 0; u < nu->pntsu; u++) {
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- if (use_obedit) {
- if (nu->bezt) {
- /* don't snap to selected (moving) or hidden */
- if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) {
- continue;
- }
- has_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, nu->bezt[u].vec[1], &dist_px_sq,
- r_loc);
- /* don't snap if handle is selected (moving), or if it is aligning to a moving handle */
- if (!(nu->bezt[u].f1 & SELECT) &&
- !(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT))
- {
- has_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, nu->bezt[u].vec[0], &dist_px_sq,
- r_loc);
- }
- if (!(nu->bezt[u].f3 & SELECT) &&
- !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT))
- {
- has_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, nu->bezt[u].vec[2], &dist_px_sq,
- r_loc);
- }
- }
- else {
- /* don't snap to selected (moving) or hidden */
- if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) {
- continue;
- }
- has_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, nu->bp[u].vec, &dist_px_sq,
- r_loc);
- }
- }
- else {
- /* curve is not visible outside editmode if nurb length less than two */
- if (nu->pntsu > 1) {
- if (nu->bezt) {
- has_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, nu->bezt[u].vec[1], &dist_px_sq,
- r_loc);
- }
- else {
- has_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, nu->bp[u].vec, &dist_px_sq,
- r_loc);
- }
- }
- }
- }
- }
- }
- if (has_snap) {
- *dist_px = sqrtf(dist_px_sq);
- mul_m4_v3(obmat, r_loc);
- if (r_index) {
- /* Does not support index yet. */
- *r_index = -1;
- }
- return SCE_SNAP_MODE_VERTEX;
- }
-
- return 0;
+ bool has_snap = false;
+
+ /* only vertex snapping mode (eg control points and handles) supported for now) */
+ if (snapdata->snap_to_flag != SCE_SNAP_MODE_VERTEX) {
+ return 0;
+ }
+
+ Curve *cu = ob->data;
+ float dist_px_sq = SQUARE(*dist_px);
+
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
+
+ use_obedit = use_obedit && BKE_object_is_in_editmode(ob);
+
+ if (use_obedit == false) {
+ /* Test BoundBox */
+ BoundBox *bb = BKE_curve_texspace_get(cu, NULL, NULL, NULL);
+ if (bb && !snap_bound_box_check_dist(
+ bb->vec[0], bb->vec[6], lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
+ return 0;
+ }
+ }
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+
+ for (Nurb *nu = (use_obedit ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
+ for (int u = 0; u < nu->pntsu; u++) {
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ if (use_obedit) {
+ if (nu->bezt) {
+ /* don't snap to selected (moving) or hidden */
+ if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) {
+ continue;
+ }
+ has_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ nu->bezt[u].vec[1],
+ &dist_px_sq,
+ r_loc);
+ /* don't snap if handle is selected (moving), or if it is aligning to a moving handle */
+ if (!(nu->bezt[u].f1 & SELECT) &&
+ !(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT)) {
+ has_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ nu->bezt[u].vec[0],
+ &dist_px_sq,
+ r_loc);
+ }
+ if (!(nu->bezt[u].f3 & SELECT) &&
+ !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT)) {
+ has_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ nu->bezt[u].vec[2],
+ &dist_px_sq,
+ r_loc);
+ }
+ }
+ else {
+ /* don't snap to selected (moving) or hidden */
+ if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) {
+ continue;
+ }
+ has_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ nu->bp[u].vec,
+ &dist_px_sq,
+ r_loc);
+ }
+ }
+ else {
+ /* curve is not visible outside editmode if nurb length less than two */
+ if (nu->pntsu > 1) {
+ if (nu->bezt) {
+ has_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ nu->bezt[u].vec[1],
+ &dist_px_sq,
+ r_loc);
+ }
+ else {
+ has_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ nu->bp[u].vec,
+ &dist_px_sq,
+ r_loc);
+ }
+ }
+ }
+ }
+ }
+ }
+ if (has_snap) {
+ *dist_px = sqrtf(dist_px_sq);
+ mul_m4_v3(obmat, r_loc);
+ if (r_index) {
+ /* Does not support index yet. */
+ *r_index = -1;
+ }
+ return SCE_SNAP_MODE_VERTEX;
+ }
+
+ return 0;
}
/* may extend later (for now just snaps to empty center) */
-static short snapEmpty(
- SnapData *snapdata,
- Object *ob, float obmat[4][4],
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float *UNUSED(r_no), int *r_index)
+static short snapEmpty(SnapData *snapdata,
+ Object *ob,
+ float obmat[4][4],
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float *UNUSED(r_no),
+ int *r_index)
{
- short retval = 0;
-
- if (ob->transflag & OB_DUPLI) {
- return retval;
- }
-
- /* for now only vertex supported */
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
- float dist_px_sq = SQUARE(*dist_px);
- float co[3];
- copy_v3_v3(co, obmat[3]);
- if (test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, co, &dist_px_sq, r_loc))
- {
- *dist_px = sqrtf(dist_px_sq);
- retval = SCE_SNAP_MODE_VERTEX;
- }
- }
-
- if (retval) {
- if (r_index) {
- /* Does not support index. */
- *r_index = -1;
- }
- return retval;
- }
-
- return 0;
+ short retval = 0;
+
+ if (ob->transflag & OB_DUPLI) {
+ return retval;
+ }
+
+ /* for now only vertex supported */
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+ float dist_px_sq = SQUARE(*dist_px);
+ float co[3];
+ copy_v3_v3(co, obmat[3]);
+ if (test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ co,
+ &dist_px_sq,
+ r_loc)) {
+ *dist_px = sqrtf(dist_px_sq);
+ retval = SCE_SNAP_MODE_VERTEX;
+ }
+ }
+
+ if (retval) {
+ if (r_index) {
+ /* Does not support index. */
+ *r_index = -1;
+ }
+ return retval;
+ }
+
+ return 0;
}
-static short snapCamera(
- const SnapObjectContext *sctx, SnapData *snapdata,
- Object *object, float obmat[4][4],
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float *UNUSED(r_no), int *r_index)
+static short snapCamera(const SnapObjectContext *sctx,
+ SnapData *snapdata,
+ Object *object,
+ float obmat[4][4],
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float *UNUSED(r_no),
+ int *r_index)
{
- short retval = 0;
-
- Scene *scene = sctx->scene;
-
- bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
- float dist_px_sq = SQUARE(*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);
- MovieTracking *tracking;
-
- if (clip == NULL) {
- return retval;
- }
- if (object->transflag & OB_DUPLI) {
- return retval;
- }
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- tracking = &clip->tracking;
-
- BKE_tracking_get_camera_object_matrix(scene, object, orig_camera_mat);
-
- invert_m4_m4(orig_camera_imat, orig_camera_mat);
- invert_m4_m4(imat, obmat);
-
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
-
- MovieTrackingObject *tracking_object;
- for (tracking_object = tracking->objects.first;
- tracking_object;
- tracking_object = tracking_object->next)
- {
- ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
- MovieTrackingTrack *track;
- float reconstructed_camera_mat[4][4],
- reconstructed_camera_imat[4][4];
- float (*vertex_obmat)[4];
-
- if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) {
- BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object,
- CFRA, reconstructed_camera_mat);
-
- invert_m4_m4(reconstructed_camera_imat, reconstructed_camera_mat);
- }
-
- for (track = tracksbase->first; track; track = track->next) {
- float bundle_pos[3];
-
- if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
- continue;
- }
-
- copy_v3_v3(bundle_pos, track->bundle_pos);
- if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
- vertex_obmat = orig_camera_mat;
- }
- else {
- mul_m4_v3(reconstructed_camera_imat, bundle_pos);
- vertex_obmat = obmat;
- }
-
- mul_m4_v3(vertex_obmat, bundle_pos);
- if (test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, bundle_pos, &dist_px_sq, r_loc))
- {
- retval = SCE_SNAP_MODE_VERTEX;
- }
- }
- }
- }
-
- if (retval) {
- *dist_px = sqrtf(dist_px_sq);
- if (r_index) {
- /* Does not support index. */
- *r_index = -1;
- }
- return retval;
- }
-
- return 0;
+ short retval = 0;
+
+ Scene *scene = sctx->scene;
+
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+ float dist_px_sq = SQUARE(*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);
+ MovieTracking *tracking;
+
+ if (clip == NULL) {
+ return retval;
+ }
+ if (object->transflag & OB_DUPLI) {
+ return retval;
+ }
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ tracking = &clip->tracking;
+
+ BKE_tracking_get_camera_object_matrix(scene, object, orig_camera_mat);
+
+ invert_m4_m4(orig_camera_imat, orig_camera_mat);
+ invert_m4_m4(imat, obmat);
+
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
+
+ MovieTrackingObject *tracking_object;
+ for (tracking_object = tracking->objects.first; tracking_object;
+ tracking_object = tracking_object->next) {
+ ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
+ MovieTrackingTrack *track;
+ float reconstructed_camera_mat[4][4], reconstructed_camera_imat[4][4];
+ float(*vertex_obmat)[4];
+
+ if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) {
+ BKE_tracking_camera_get_reconstructed_interpolate(
+ tracking, tracking_object, CFRA, reconstructed_camera_mat);
+
+ invert_m4_m4(reconstructed_camera_imat, reconstructed_camera_mat);
+ }
+
+ for (track = tracksbase->first; track; track = track->next) {
+ float bundle_pos[3];
+
+ if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
+ continue;
+ }
+
+ copy_v3_v3(bundle_pos, track->bundle_pos);
+ if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
+ vertex_obmat = orig_camera_mat;
+ }
+ else {
+ mul_m4_v3(reconstructed_camera_imat, bundle_pos);
+ vertex_obmat = obmat;
+ }
+
+ mul_m4_v3(vertex_obmat, bundle_pos);
+ if (test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ bundle_pos,
+ &dist_px_sq,
+ r_loc)) {
+ retval = SCE_SNAP_MODE_VERTEX;
+ }
+ }
+ }
+ }
+
+ if (retval) {
+ *dist_px = sqrtf(dist_px_sq);
+ if (r_index) {
+ /* Does not support index. */
+ *r_index = -1;
+ }
+ return retval;
+ }
+
+ return 0;
}
-static short snapMesh(
- SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, Mesh *me, float obmat[4][4],
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index)
+static short snapMesh(SnapObjectContext *sctx,
+ SnapData *snapdata,
+ Object *ob,
+ Mesh *me,
+ float obmat[4][4],
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index)
{
- BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
-
- if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) {
- if (me->totedge == 0) {
- return 0;
- }
- }
- else {
- if (me->totvert == 0) {
- return 0;
- }
- }
-
- float lpmat[4][4];
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
-
- float dist_px_sq = SQUARE(*dist_px);
-
- /* Test BoundBox */
- BoundBox *bb = BKE_mesh_boundbox_get(ob);
- if (bb && !snap_bound_box_check_dist(
- bb->vec[0], bb->vec[6], lpmat, snapdata->win_size,
- snapdata->mval, dist_px_sq))
- {
- return 0;
- }
-
- SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob);
-
- BVHTreeFromMesh *treedata, dummy_treedata;
- BVHTree **bvhtree;
- treedata = &sod->treedata;
- bvhtree = sod->bvhtree;
-
- /* 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]));
-
- free_bvhtree_from_mesh(treedata);
- bvhtree[0] = NULL;
- bvhtree[1] = NULL;
- }
-
- if (sod->has_looptris && treedata->tree == NULL) {
- BKE_bvhtree_from_mesh_get(treedata, me, BVHTREE_FROM_LOOPTRI, 4);
- sod->has_looptris = (treedata->tree != NULL);
- if (sod->has_looptris) {
- /* Make sure that the array of edges is referenced in the callbacks. */
- 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) {
- BLI_assert(treedata->vert_allocated == false);
- treedata->vert = dummy_treedata.vert;
- treedata->vert_allocated = dummy_treedata.vert_allocated;
-
- BLI_assert(treedata->edge_allocated == false);
- treedata->edge = dummy_treedata.edge;
- treedata->edge_allocated = dummy_treedata.edge_allocated;
- }
- }
- 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) {
- BLI_assert(treedata->vert_allocated == false);
- treedata->vert = dummy_treedata.vert;
- treedata->vert_allocated = dummy_treedata.vert_allocated;
- }
- }
- }
- else {
- /* Not necessary, just to keep the data more consistent. */
- sod->has_loose_vert = false;
- }
-
- /* Update pointers. */
- if (treedata->vert_allocated == false) {
- treedata->vert = me->mvert; /* CustomData_get_layer(&me->vdata, CD_MVERT);? */
- }
- if (treedata->tree || 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);? */
- }
- if (treedata->loop && treedata->loop_allocated == false) {
- treedata->loop = me->mloop; /* CustomData_get_layer(&me->edata, CD_MLOOP);? */
- }
- if (treedata->looptri && treedata->looptri_allocated == false) {
- treedata->looptri = BKE_mesh_runtime_looptri_ensure(me);
- }
- }
-
- Nearest2dUserData nearest2d = {
- .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
- .userdata = treedata,
- .get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get,
- .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get,
- .get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get,
- .get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get,
- .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy,
- };
-
- BVHTreeNearest nearest = {
- .index = -1,
- .dist_sq = dist_px_sq,
- };
- int last_index = nearest.index;
- short elem = SCE_SNAP_MODE_VERTEX;
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- if (bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
- /* snap to loose verts */
- BLI_bvhtree_find_nearest_projected(
- bvhtree[1], lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_vert, &nearest2d);
-
- last_index = nearest.index;
- }
-
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- if (bvhtree[0]) {
- /* snap to loose edges */
- BLI_bvhtree_find_nearest_projected(
- bvhtree[0], lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_edge, &nearest2d);
- }
-
- if (treedata->tree) {
- /* snap to looptris */
- BLI_bvhtree_find_nearest_projected(
- treedata->tree, lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_tri_edges, &nearest2d);
- }
-
- if (last_index != nearest.index) {
- elem = SCE_SNAP_MODE_EDGE;
- }
- }
- 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], lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_edge_verts, &nearest2d);
- }
-
- if (treedata->tree) {
- /* snap to looptris */
- BLI_bvhtree_find_nearest_projected(
- treedata->tree, lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_tri_verts, &nearest2d);
- }
- }
-
- if (nearest.index != -1) {
- *dist_px = sqrtf(nearest.dist_sq);
-
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- float imat[4][4];
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(r_no, nearest.no);
- mul_transposed_mat3_m4_v3(imat, r_no);
- normalize_v3(r_no);
- }
- if (r_index) {
- *r_index = nearest.index;
- }
-
- return elem;
- }
-
- return 0;
+ BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
+
+ if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) {
+ if (me->totedge == 0) {
+ return 0;
+ }
+ }
+ else {
+ if (me->totvert == 0) {
+ return 0;
+ }
+ }
+
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+
+ float dist_px_sq = SQUARE(*dist_px);
+
+ /* Test BoundBox */
+ BoundBox *bb = BKE_mesh_boundbox_get(ob);
+ if (bb && !snap_bound_box_check_dist(
+ bb->vec[0], bb->vec[6], lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
+ return 0;
+ }
+
+ SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob);
+
+ BVHTreeFromMesh *treedata, dummy_treedata;
+ BVHTree **bvhtree;
+ treedata = &sod->treedata;
+ bvhtree = sod->bvhtree;
+
+ /* 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]));
+
+ free_bvhtree_from_mesh(treedata);
+ bvhtree[0] = NULL;
+ bvhtree[1] = NULL;
+ }
+
+ if (sod->has_looptris && treedata->tree == NULL) {
+ BKE_bvhtree_from_mesh_get(treedata, me, BVHTREE_FROM_LOOPTRI, 4);
+ sod->has_looptris = (treedata->tree != NULL);
+ if (sod->has_looptris) {
+ /* Make sure that the array of edges is referenced in the callbacks. */
+ 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) {
+ BLI_assert(treedata->vert_allocated == false);
+ treedata->vert = dummy_treedata.vert;
+ treedata->vert_allocated = dummy_treedata.vert_allocated;
+
+ BLI_assert(treedata->edge_allocated == false);
+ treedata->edge = dummy_treedata.edge;
+ treedata->edge_allocated = dummy_treedata.edge_allocated;
+ }
+ }
+ 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) {
+ BLI_assert(treedata->vert_allocated == false);
+ treedata->vert = dummy_treedata.vert;
+ treedata->vert_allocated = dummy_treedata.vert_allocated;
+ }
+ }
+ }
+ else {
+ /* Not necessary, just to keep the data more consistent. */
+ sod->has_loose_vert = false;
+ }
+
+ /* Update pointers. */
+ if (treedata->vert_allocated == false) {
+ treedata->vert = me->mvert; /* CustomData_get_layer(&me->vdata, CD_MVERT);? */
+ }
+ if (treedata->tree || 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);? */
+ }
+ if (treedata->loop && treedata->loop_allocated == false) {
+ treedata->loop = me->mloop; /* CustomData_get_layer(&me->edata, CD_MLOOP);? */
+ }
+ if (treedata->looptri && treedata->looptri_allocated == false) {
+ treedata->looptri = BKE_mesh_runtime_looptri_ensure(me);
+ }
+ }
+
+ Nearest2dUserData nearest2d = {
+ .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
+ .userdata = treedata,
+ .get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get,
+ .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get,
+ .get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get,
+ .get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get,
+ .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy,
+ };
+
+ BVHTreeNearest nearest = {
+ .index = -1,
+ .dist_sq = dist_px_sq,
+ };
+ int last_index = nearest.index;
+ short elem = SCE_SNAP_MODE_VERTEX;
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ if (bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
+ /* snap to loose verts */
+ BLI_bvhtree_find_nearest_projected(bvhtree[1],
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_vert,
+ &nearest2d);
+
+ last_index = nearest.index;
+ }
+
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ if (bvhtree[0]) {
+ /* snap to loose edges */
+ BLI_bvhtree_find_nearest_projected(bvhtree[0],
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_edge,
+ &nearest2d);
+ }
+
+ if (treedata->tree) {
+ /* snap to looptris */
+ BLI_bvhtree_find_nearest_projected(treedata->tree,
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_tri_edges,
+ &nearest2d);
+ }
+
+ if (last_index != nearest.index) {
+ elem = SCE_SNAP_MODE_EDGE;
+ }
+ }
+ 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],
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_edge_verts,
+ &nearest2d);
+ }
+
+ if (treedata->tree) {
+ /* snap to looptris */
+ BLI_bvhtree_find_nearest_projected(treedata->tree,
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_tri_verts,
+ &nearest2d);
+ }
+ }
+
+ if (nearest.index != -1) {
+ *dist_px = sqrtf(nearest.dist_sq);
+
+ copy_v3_v3(r_loc, nearest.co);
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ float imat[4][4];
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(r_no, nearest.no);
+ mul_transposed_mat3_m4_v3(imat, r_no);
+ normalize_v3(r_no);
+ }
+ if (r_index) {
+ *r_index = nearest.index;
+ }
+
+ return elem;
+ }
+
+ return 0;
}
-static short snapEditMesh(
- SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, BMEditMesh *em, float obmat[4][4],
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index)
+static short snapEditMesh(SnapObjectContext *sctx,
+ SnapData *snapdata,
+ Object *ob,
+ BMEditMesh *em,
+ float obmat[4][4],
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index)
{
- BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
-
- if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) {
- if (em->bm->totedge == 0) {
- return 0;
- }
- }
- else {
- if (em->bm->totvert == 0) {
- return 0;
- }
- }
-
- 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);
-
- SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, em);
-
- /* Test BoundBox */
-
- /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
- if (!snap_bound_box_check_dist(
- sod->min, sod->max, lpmat, snapdata->win_size, snapdata->mval, dist_px_sq))
- {
- return 0;
- }
-
- BVHCache *em_bvh_cache = ((Mesh *)em->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 (!bvhcache_has_tree(em_bvh_cache, treedata_vert->tree)) {
- free_bvhtree_from_editmesh(treedata_vert);
- }
- }
-
- if (treedata_vert->tree == NULL) {
- BLI_bitmap *verts_mask = NULL;
- int verts_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_vert_fn) {
- verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
- verts_num_active = BM_iter_mesh_bitmap_from_filter(
- BM_VERTS_OF_MESH, em->bm, verts_mask,
- (bool(*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
- sctx->callbacks.edit_mesh.user_data);
-
- bvhtree_from_editmesh_verts_ex(treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6);
- MEM_freeN(verts_mask);
- }
- else {
- bvhtree_from_editmesh_verts(treedata_vert, em, 0.0f, 2, 6, &em_bvh_cache);
- }
- }
- }
-
- 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 (!bvhcache_has_tree(em_bvh_cache, treedata_edge->tree)) {
- free_bvhtree_from_editmesh(treedata_edge);
- }
- }
-
- if (treedata_edge->tree == NULL) {
- BLI_bitmap *edges_mask = NULL;
- int edges_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_edge_fn) {
- edges_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
- edges_num_active = BM_iter_mesh_bitmap_from_filter(
- BM_EDGES_OF_MESH, em->bm, edges_mask,
- (bool(*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
- sctx->callbacks.edit_mesh.user_data);
-
- bvhtree_from_editmesh_edges_ex(treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6);
- MEM_freeN(edges_mask);
- }
- else {
- bvhtree_from_editmesh_edges(treedata_edge, em, 0.0f, 2, 6, &em_bvh_cache);
- }
- }
- }
-
- Nearest2dUserData nearest2d = {
- .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
- .userdata = em,
- .get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get,
- .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get,
- .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy,
- };
-
- BVHTreeNearest nearest = {
- .index = -1,
- .dist_sq = dist_px_sq,
- };
- int last_index = nearest.index;
- short elem = SCE_SNAP_MODE_VERTEX;
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
-
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- if (treedata_vert && snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
- BLI_bvhtree_find_nearest_projected(
- treedata_vert->tree, lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_vert, &nearest2d);
-
- last_index = nearest.index;
- }
-
- if (treedata_edge && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT);
- BLI_bvhtree_find_nearest_projected(
- treedata_edge->tree, lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_edge, &nearest2d);
-
- if (last_index != nearest.index) {
- elem = SCE_SNAP_MODE_EDGE;
- }
- }
-
- if (nearest.index != -1) {
- *dist_px = sqrtf(nearest.dist_sq);
-
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- float imat[4][4];
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(r_no, nearest.no);
- mul_transposed_mat3_m4_v3(imat, r_no);
- normalize_v3(r_no);
- }
- if (r_index) {
- *r_index = nearest.index;
- }
-
- return elem;
- }
-
- return 0;
+ BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
+
+ if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) {
+ if (em->bm->totedge == 0) {
+ return 0;
+ }
+ }
+ else {
+ if (em->bm->totvert == 0) {
+ return 0;
+ }
+ }
+
+ 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);
+
+ SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, em);
+
+ /* Test BoundBox */
+
+ /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
+ if (!snap_bound_box_check_dist(
+ sod->min, sod->max, lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
+ return 0;
+ }
+
+ BVHCache *em_bvh_cache = ((Mesh *)em->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 (!bvhcache_has_tree(em_bvh_cache, treedata_vert->tree)) {
+ free_bvhtree_from_editmesh(treedata_vert);
+ }
+ }
+
+ if (treedata_vert->tree == NULL) {
+ BLI_bitmap *verts_mask = NULL;
+ int verts_num_active = -1;
+ if (sctx->callbacks.edit_mesh.test_vert_fn) {
+ verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
+ verts_num_active = BM_iter_mesh_bitmap_from_filter(
+ BM_VERTS_OF_MESH,
+ em->bm,
+ verts_mask,
+ (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
+ sctx->callbacks.edit_mesh.user_data);
+
+ bvhtree_from_editmesh_verts_ex(
+ treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6);
+ MEM_freeN(verts_mask);
+ }
+ else {
+ bvhtree_from_editmesh_verts(treedata_vert, em, 0.0f, 2, 6, &em_bvh_cache);
+ }
+ }
+ }
+
+ 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 (!bvhcache_has_tree(em_bvh_cache, treedata_edge->tree)) {
+ free_bvhtree_from_editmesh(treedata_edge);
+ }
+ }
+
+ if (treedata_edge->tree == NULL) {
+ BLI_bitmap *edges_mask = NULL;
+ int edges_num_active = -1;
+ if (sctx->callbacks.edit_mesh.test_edge_fn) {
+ edges_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
+ edges_num_active = BM_iter_mesh_bitmap_from_filter(
+ BM_EDGES_OF_MESH,
+ em->bm,
+ edges_mask,
+ (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
+ sctx->callbacks.edit_mesh.user_data);
+
+ bvhtree_from_editmesh_edges_ex(
+ treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6);
+ MEM_freeN(edges_mask);
+ }
+ else {
+ bvhtree_from_editmesh_edges(treedata_edge, em, 0.0f, 2, 6, &em_bvh_cache);
+ }
+ }
+ }
+
+ Nearest2dUserData nearest2d = {
+ .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
+ .userdata = em,
+ .get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get,
+ .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get,
+ .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy,
+ };
+
+ BVHTreeNearest nearest = {
+ .index = -1,
+ .dist_sq = dist_px_sq,
+ };
+ int last_index = nearest.index;
+ short elem = SCE_SNAP_MODE_VERTEX;
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ if (treedata_vert && snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ BLI_bvhtree_find_nearest_projected(treedata_vert->tree,
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_vert,
+ &nearest2d);
+
+ last_index = nearest.index;
+ }
+
+ if (treedata_edge && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT);
+ BLI_bvhtree_find_nearest_projected(treedata_edge->tree,
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_edge,
+ &nearest2d);
+
+ if (last_index != nearest.index) {
+ elem = SCE_SNAP_MODE_EDGE;
+ }
+ }
+
+ if (nearest.index != -1) {
+ *dist_px = sqrtf(nearest.dist_sq);
+
+ copy_v3_v3(r_loc, nearest.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ float imat[4][4];
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(r_no, nearest.no);
+ mul_transposed_mat3_m4_v3(imat, r_no);
+ normalize_v3(r_no);
+ }
+ if (r_index) {
+ *r_index = nearest.index;
+ }
+
+ return elem;
+ }
+
+ return 0;
}
/**
@@ -2163,127 +2298,112 @@ static short snapEditMesh(
*
* \note Duplicate args here are documented at #snapObjectsRay
*/
-static short snapObject(
- SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, float obmat[4][4], bool use_obedit,
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4])
+static short snapObject(SnapObjectContext *sctx,
+ SnapData *snapdata,
+ Object *ob,
+ float obmat[4][4],
+ bool use_obedit,
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4])
{
- short retval = 0;
-
- switch (ob->type) {
- 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,
- dist_px,
- r_loc, r_no, r_index);
- break;
- }
- else if (em->mesh_eval_final) {
- me = em->mesh_eval_final;
- }
- }
- else if (ob->dt == OB_BOUNDBOX) {
- /* Do not snap to objects that are in bounding box display mode */
- return 0;
- }
-
- retval = snapMesh(
- sctx, snapdata, ob, me, obmat,
- dist_px,
- r_loc, r_no, r_index);
- break;
- }
- case OB_ARMATURE:
- retval = snapArmature(
- snapdata,
- ob, obmat, use_obedit,
- dist_px,
- r_loc, r_no, r_index);
- break;
-
- case OB_CURVE:
- retval = snapCurve(
- snapdata,
- ob, obmat, use_obedit,
- dist_px,
- r_loc, r_no, r_index);
- break;
-
- case OB_EMPTY:
- retval = snapEmpty(
- snapdata, ob, obmat,
- dist_px,
- r_loc, r_no, r_index);
- break;
- case OB_GPENCIL:
- retval = snapEmpty(
- snapdata, ob, obmat,
- dist_px,
- r_loc, r_no, r_index);
- break;
- case OB_CAMERA:
- retval = snapCamera(
- sctx, snapdata, ob, obmat,
- dist_px,
- r_loc, r_no, r_index);
- break;
- }
-
- if (retval) {
- if (r_ob) {
- *r_ob = ob;
- }
- if (r_obmat) {
- copy_m4_m4(r_obmat, obmat);
- }
- return retval;
- }
-
- return 0;
+ short retval = 0;
+
+ switch (ob->type) {
+ 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, dist_px, r_loc, r_no, r_index);
+ break;
+ }
+ else if (em->mesh_eval_final) {
+ me = em->mesh_eval_final;
+ }
+ }
+ else if (ob->dt == OB_BOUNDBOX) {
+ /* Do not snap to objects that are in bounding box display mode */
+ return 0;
+ }
+
+ retval = snapMesh(sctx, snapdata, ob, me, obmat, dist_px, r_loc, r_no, r_index);
+ break;
+ }
+ case OB_ARMATURE:
+ retval = snapArmature(snapdata, ob, obmat, use_obedit, dist_px, r_loc, r_no, r_index);
+ break;
+
+ case OB_CURVE:
+ retval = snapCurve(snapdata, ob, obmat, use_obedit, dist_px, r_loc, r_no, r_index);
+ break;
+
+ case OB_EMPTY:
+ retval = snapEmpty(snapdata, ob, obmat, dist_px, r_loc, r_no, r_index);
+ break;
+ case OB_GPENCIL:
+ retval = snapEmpty(snapdata, ob, obmat, dist_px, r_loc, r_no, r_index);
+ break;
+ case OB_CAMERA:
+ retval = snapCamera(sctx, snapdata, ob, obmat, dist_px, r_loc, r_no, r_index);
+ break;
+ }
+
+ if (retval) {
+ if (r_ob) {
+ *r_ob = ob;
+ }
+ if (r_obmat) {
+ copy_m4_m4(r_obmat, obmat);
+ }
+ return retval;
+ }
+
+ return 0;
}
-
struct SnapObjUserData {
- SnapData *snapdata;
- /* read/write args */
- float *dist_px;
- /* return args */
- float *r_loc;
- float *r_no;
- int *r_index;
- Object **r_ob;
- float (*r_obmat)[4];
- short ret;
+ SnapData *snapdata;
+ /* read/write args */
+ float *dist_px;
+ /* return args */
+ float *r_loc;
+ float *r_no;
+ int *r_index;
+ Object **r_ob;
+ float (*r_obmat)[4];
+ short ret;
};
-static void sanp_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data)
+static void sanp_obj_cb(
+ SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data)
{
- struct SnapObjUserData *dt = data;
-
- short elem = snapObject(
- sctx, dt->snapdata,
- ob, obmat, is_obedit,
- /* read/write args */
- dt->dist_px,
- /* return args */
- dt->r_loc, dt->r_no, dt->r_index,
- dt->r_ob, dt->r_obmat);
-
- if (elem) {
- dt->ret = elem;
- }
+ struct SnapObjUserData *dt = data;
+
+ short elem = snapObject(sctx,
+ dt->snapdata,
+ ob,
+ obmat,
+ is_obedit,
+ /* read/write args */
+ dt->dist_px,
+ /* return args */
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index,
+ dt->r_ob,
+ dt->r_obmat);
+
+ if (elem) {
+ dt->ret = elem;
+ }
}
-
/**
* Main Snapping Function
* ======================
@@ -2309,29 +2429,32 @@ static void sanp_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, flo
* \param r_ob: Hit object.
* \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances).
*/
-static short snapObjectsRay(
- SnapObjectContext *sctx, SnapData *snapdata,
- const struct SnapObjectParams *params,
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4])
+static short snapObjectsRay(SnapObjectContext *sctx,
+ SnapData *snapdata,
+ const struct SnapObjectParams *params,
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4])
{
- struct SnapObjUserData data = {
- .snapdata = snapdata,
- .dist_px = dist_px,
- .r_loc = r_loc,
- .r_no = r_no,
- .r_ob = r_ob,
- .r_index = r_index,
- .r_obmat = r_obmat,
- .ret = 0,
- };
-
- iter_snap_objects(sctx, params, sanp_obj_cb, &data);
-
- return data.ret;
+ struct SnapObjUserData data = {
+ .snapdata = snapdata,
+ .dist_px = dist_px,
+ .r_loc = r_loc,
+ .r_no = r_no,
+ .r_ob = r_ob,
+ .r_index = r_index,
+ .r_obmat = r_obmat,
+ .ret = 0,
+ };
+
+ iter_snap_objects(sctx, params, sanp_obj_cb, &data);
+
+ return data.ret;
}
/** \} */
@@ -2340,95 +2463,99 @@ static short snapObjectsRay(
/** \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,
+ Depsgraph *depsgraph,
+ int flag)
{
- SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__);
+ SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__);
- sctx->flag = flag;
+ sctx->flag = flag;
- sctx->bmain = bmain;
- sctx->scene = scene;
- sctx->depsgraph = depsgraph;
+ sctx->bmain = bmain;
+ sctx->scene = scene;
+ sctx->depsgraph = depsgraph;
- sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
- sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
+ sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- return sctx;
+ return sctx;
}
-SnapObjectContext *ED_transform_snap_object_context_create_view3d(
- Main *bmain, Scene *scene, Depsgraph *depsgraph, int flag,
- /* extra args for view3d */
- const ARegion *ar, const View3D *v3d)
+SnapObjectContext *ED_transform_snap_object_context_create_view3d(Main *bmain,
+ Scene *scene,
+ Depsgraph *depsgraph,
+ int flag,
+ /* extra args for view3d */
+ const ARegion *ar,
+ 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, depsgraph, flag);
- sctx->use_v3d = true;
- sctx->v3d_data.ar = ar;
- sctx->v3d_data.v3d = v3d;
+ sctx->use_v3d = true;
+ sctx->v3d_data.ar = ar;
+ sctx->v3d_data.v3d = v3d;
- return sctx;
+ return sctx;
}
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;
- }
- }
+ 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;
+ }
+ }
}
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)
{
- BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free);
- BLI_memarena_free(sctx->cache.mem_arena);
+ BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free);
+ BLI_memarena_free(sctx->cache.mem_arena);
- MEM_freeN(sctx);
+ MEM_freeN(sctx);
}
void ED_transform_snap_object_context_set_editmesh_callbacks(
- SnapObjectContext *sctx,
- bool (*test_vert_fn)(BMVert *, void *user_data),
- bool (*test_edge_fn)(BMEdge *, void *user_data),
- bool (*test_face_fn)(BMFace *, void *user_data),
- void *user_data)
+ SnapObjectContext *sctx,
+ bool (*test_vert_fn)(BMVert *, void *user_data),
+ bool (*test_edge_fn)(BMEdge *, void *user_data),
+ bool (*test_face_fn)(BMFace *, void *user_data),
+ void *user_data)
{
- sctx->callbacks.edit_mesh.test_vert_fn = test_vert_fn;
- sctx->callbacks.edit_mesh.test_edge_fn = test_edge_fn;
- sctx->callbacks.edit_mesh.test_face_fn = test_face_fn;
+ sctx->callbacks.edit_mesh.test_vert_fn = test_vert_fn;
+ sctx->callbacks.edit_mesh.test_edge_fn = test_edge_fn;
+ sctx->callbacks.edit_mesh.test_face_fn = test_face_fn;
- sctx->callbacks.edit_mesh.user_data = user_data;
+ sctx->callbacks.edit_mesh.user_data = user_data;
}
-bool ED_transform_snap_object_project_ray_ex(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_start[3], const float ray_normal[3],
- float *ray_depth,
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4])
+bool ED_transform_snap_object_project_ray_ex(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_start[3],
+ const float ray_normal[3],
+ float *ray_depth,
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ 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, params, ray_start, ray_normal, ray_depth, r_loc, r_no, r_index, r_ob, r_obmat, NULL);
}
/**
@@ -2438,37 +2565,35 @@ bool ED_transform_snap_object_project_ray_ex(
* \param sort: Optionally sort the hits by depth.
* \param r_hit_list: List of #SnapObjectHitDepth (caller must free).
*/
-bool ED_transform_snap_object_project_ray_all(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_start[3], const float ray_normal[3],
- float ray_depth, bool sort,
- ListBase *r_hit_list)
+bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_start[3],
+ const float ray_normal[3],
+ float ray_depth,
+ bool sort,
+ ListBase *r_hit_list)
{
- if (ray_depth == -1.0f) {
- ray_depth = BVH_RAYCAST_DIST_MAX;
- }
+ if (ray_depth == -1.0f) {
+ ray_depth = BVH_RAYCAST_DIST_MAX;
+ }
#ifdef DEBUG
- float ray_depth_prev = ray_depth;
+ 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, 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 */
+ /* meant to be readonly for 'all' hits, ensure it is */
#ifdef DEBUG
- BLI_assert(ray_depth_prev == ray_depth);
+ BLI_assert(ray_depth_prev == ray_depth);
#endif
- if (sort) {
- BLI_listbase_sort(r_hit_list, hit_depth_cmp);
- }
+ if (sort) {
+ BLI_listbase_sort(r_hit_list, hit_depth_cmp);
+ }
- return retval;
+ return retval;
}
/**
@@ -2478,196 +2603,183 @@ bool ED_transform_snap_object_project_ray_all(
*
* \return Snap success
*/
-static bool transform_snap_context_project_ray_impl(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_start[3], const float ray_normal[3], float *ray_depth,
- float r_co[3], float r_no[3])
+static bool transform_snap_context_project_ray_impl(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_start[3],
+ const float ray_normal[3],
+ float *ray_depth,
+ float r_co[3],
+ float r_no[3])
{
- bool ret;
+ bool ret;
- /* 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);
+ /* 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);
- return ret;
+ return ret;
}
-bool ED_transform_snap_object_project_ray(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_origin[3], const float ray_direction[3], float *ray_depth,
- float r_co[3], float r_no[3])
+bool ED_transform_snap_object_project_ray(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_origin[3],
+ const float ray_direction[3],
+ float *ray_depth,
+ float r_co[3],
+ float r_no[3])
{
- float ray_depth_fallback;
- if (ray_depth == NULL) {
- ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
- ray_depth = &ray_depth_fallback;
- }
-
- return transform_snap_context_project_ray_impl(
- sctx,
- params,
- ray_origin, ray_direction, ray_depth,
- r_co, r_no);
+ float ray_depth_fallback;
+ if (ray_depth == NULL) {
+ ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
+ ray_depth = &ray_depth_fallback;
+ }
+
+ return transform_snap_context_project_ray_impl(
+ sctx, 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,
- const struct SnapObjectParams *params,
- const float mval[2], float *dist_px,
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4])
+ SnapObjectContext *sctx,
+ const unsigned short snap_to_flag,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float *dist_px,
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4])
{
- BLI_assert(
- (snap_to_flag & (
- SCE_SNAP_MODE_VERTEX |
- SCE_SNAP_MODE_EDGE |
- SCE_SNAP_MODE_FACE)) != 0);
-
- short retval = 0;
- bool has_hit = false;
- int index = -1;
-
- float loc[3], no[3], obmat[4][4];
- Object *ob = NULL;
-
- const ARegion *ar = sctx->v3d_data.ar;
- const RegionView3D *rv3d = ar->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, sctx->v3d_data.v3d,
- mval, NULL, ray_normal, ray_start, true))
- {
- return false;
- }
-
- 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);
-
- if (has_hit && (snap_to_flag & SCE_SNAP_MODE_FACE)) {
- retval = SCE_SNAP_MODE_FACE;
- }
- }
-
- if (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE)) {
- short elem;
- float dist_px_tmp = *dist_px;
-
- SnapData snapdata;
- copy_m4_m4(snapdata.pmat, rv3d->persmat);
- snapdata.win_size[0] = ar->winx;
- snapdata.win_size[1] = ar->winy;
- copy_v2_v2(snapdata.mval, mval);
- snapdata.snap_to_flag = snap_to_flag;
- snapdata.view_proj = rv3d->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO;
-
- planes_from_projmat(
- snapdata.pmat,
- NULL, NULL, NULL, NULL,
- snapdata.clip_plane[0], snapdata.clip_plane[1]);
-
- snapdata.clip_plane_len = 2;
-
- if (has_hit) {
- /* Compute the new clip_pane but do not add it yet. */
- float new_clipplane[4];
- plane_from_point_normal_v3(new_clipplane, loc, no);
- if (dot_v3v3(snapdata.clip_plane[0], new_clipplane) > 0.0f) {
- /* The plane is facing the wrong direction. */
- negate_v4(new_clipplane);
- }
-
- /* Small offset to simulate a kind of volume for edges and vertices. */
- new_clipplane[3] += 0.01f;
-
- /* Try to snap only to the polygon. */
- elem = snap_mesh_polygon(
- sctx, &snapdata, ob, obmat,
- &dist_px_tmp, loc, no, &index);
-
- if (elem) {
- retval = elem;
- }
-
- /* Add the new clip plane to the beginning of the list. */
- for (int i = snapdata.clip_plane_len; i != 0; i--) {
- copy_v4_v4(snapdata.clip_plane[i], snapdata.clip_plane[i - 1]);
- }
- copy_v4_v4(snapdata.clip_plane[0], new_clipplane);
- snapdata.clip_plane_len++;
- }
-
- elem = snapObjectsRay(
- sctx, &snapdata, params,
- &dist_px_tmp, loc, no, &index, &ob, obmat);
-
- if (elem) {
- retval = elem;
- }
-
- if ((retval == SCE_SNAP_MODE_EDGE) &&
- (snapdata.snap_to_flag & SCE_SNAP_MODE_VERTEX))
- {
- retval = snap_mesh_edge_verts_mixed(
- sctx, &snapdata,
- ob, obmat, *dist_px,
- &dist_px_tmp, loc, no, &index);
- }
-
- *dist_px = dist_px_tmp;
- }
-
- if (retval) {
- copy_v3_v3(r_loc, loc);
- if (r_no) {
- copy_v3_v3(r_no, no);
- }
- if (r_ob) {
- *r_ob = ob;
- }
- if (r_obmat) {
- copy_m4_m4(r_obmat, obmat);
- }
- if (r_index) {
- *r_index = index;
- }
- return retval;
- }
-
- return 0;
+ BLI_assert((snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE)) !=
+ 0);
+
+ short retval = 0;
+ bool has_hit = false;
+ int index = -1;
+
+ float loc[3], no[3], obmat[4][4];
+ Object *ob = NULL;
+
+ const ARegion *ar = sctx->v3d_data.ar;
+ const RegionView3D *rv3d = ar->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,
+ sctx->v3d_data.v3d,
+ mval,
+ NULL,
+ ray_normal,
+ ray_start,
+ true)) {
+ return false;
+ }
+
+ 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);
+
+ if (has_hit && (snap_to_flag & SCE_SNAP_MODE_FACE)) {
+ retval = SCE_SNAP_MODE_FACE;
+ }
+ }
+
+ if (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE)) {
+ short elem;
+ float dist_px_tmp = *dist_px;
+
+ SnapData snapdata;
+ copy_m4_m4(snapdata.pmat, rv3d->persmat);
+ snapdata.win_size[0] = ar->winx;
+ snapdata.win_size[1] = ar->winy;
+ copy_v2_v2(snapdata.mval, mval);
+ snapdata.snap_to_flag = snap_to_flag;
+ snapdata.view_proj = rv3d->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO;
+
+ planes_from_projmat(
+ snapdata.pmat, NULL, NULL, NULL, NULL, snapdata.clip_plane[0], snapdata.clip_plane[1]);
+
+ snapdata.clip_plane_len = 2;
+
+ if (has_hit) {
+ /* Compute the new clip_pane but do not add it yet. */
+ float new_clipplane[4];
+ plane_from_point_normal_v3(new_clipplane, loc, no);
+ if (dot_v3v3(snapdata.clip_plane[0], new_clipplane) > 0.0f) {
+ /* The plane is facing the wrong direction. */
+ negate_v4(new_clipplane);
+ }
+
+ /* Small offset to simulate a kind of volume for edges and vertices. */
+ new_clipplane[3] += 0.01f;
+
+ /* Try to snap only to the polygon. */
+ elem = snap_mesh_polygon(sctx, &snapdata, ob, obmat, &dist_px_tmp, loc, no, &index);
+
+ if (elem) {
+ retval = elem;
+ }
+
+ /* Add the new clip plane to the beginning of the list. */
+ for (int i = snapdata.clip_plane_len; i != 0; i--) {
+ copy_v4_v4(snapdata.clip_plane[i], snapdata.clip_plane[i - 1]);
+ }
+ copy_v4_v4(snapdata.clip_plane[0], new_clipplane);
+ snapdata.clip_plane_len++;
+ }
+
+ elem = snapObjectsRay(sctx, &snapdata, params, &dist_px_tmp, loc, no, &index, &ob, obmat);
+
+ if (elem) {
+ retval = elem;
+ }
+
+ if ((retval == SCE_SNAP_MODE_EDGE) && (snapdata.snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
+ retval = snap_mesh_edge_verts_mixed(
+ sctx, &snapdata, ob, obmat, *dist_px, &dist_px_tmp, loc, no, &index);
+ }
+
+ *dist_px = dist_px_tmp;
+ }
+
+ if (retval) {
+ copy_v3_v3(r_loc, loc);
+ if (r_no) {
+ copy_v3_v3(r_no, no);
+ }
+ if (r_ob) {
+ *r_ob = ob;
+ }
+ if (r_obmat) {
+ copy_m4_m4(r_obmat, obmat);
+ }
+ if (r_index) {
+ *r_index = index;
+ }
+ return retval;
+ }
+
+ return 0;
}
-bool ED_transform_snap_object_project_view3d_ex(
- SnapObjectContext *sctx,
- const unsigned short snap_to,
- const struct SnapObjectParams *params,
- const float mval[2], float *dist_px,
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4])
+bool ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx,
+ const unsigned short snap_to,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float *dist_px,
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4])
{
- return transform_snap_context_project_view3d_mixed_impl(
- sctx,
- snap_to, params,
- mval, dist_px,
- r_loc, r_no, r_index, r_ob, r_obmat) != 0;
+ return transform_snap_context_project_view3d_mixed_impl(
+ sctx, snap_to, params, mval, dist_px, r_loc, r_no, r_index, r_ob, r_obmat) != 0;
}
/**
@@ -2682,47 +2794,43 @@ bool ED_transform_snap_object_project_view3d_ex(
* \param r_no: hit normal (optional).
* \return Snap success
*/
-bool ED_transform_snap_object_project_view3d(
- SnapObjectContext *sctx,
- const unsigned short snap_to,
- const struct SnapObjectParams *params,
- const float mval[2], float *dist_px,
- float r_loc[3], float r_no[3])
+bool ED_transform_snap_object_project_view3d(SnapObjectContext *sctx,
+ const unsigned short snap_to,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float *dist_px,
+ float r_loc[3],
+ float r_no[3])
{
- return ED_transform_snap_object_project_view3d_ex(
- sctx,
- snap_to,
- params,
- mval, dist_px,
- r_loc, r_no, NULL,
- NULL, NULL);
+ return ED_transform_snap_object_project_view3d_ex(
+ sctx, snap_to, params, mval, dist_px, r_loc, r_no, NULL, NULL, NULL);
}
/**
* see: #ED_transform_snap_object_project_ray_all
*/
-bool ED_transform_snap_object_project_all_view3d_ex(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float mval[2],
- float ray_depth, bool sort,
- ListBase *r_hit_list)
+bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float ray_depth,
+ bool sort,
+ ListBase *r_hit_list)
{
- float ray_start[3], ray_normal[3];
-
- if (!ED_view3d_win_to_ray_clipped_ex(
- sctx->depsgraph,
- sctx->v3d_data.ar, sctx->v3d_data.v3d,
- mval, NULL, ray_normal, ray_start, true))
- {
- return false;
- }
-
- return ED_transform_snap_object_project_ray_all(
- sctx,
- params,
- ray_start, ray_normal, ray_depth, sort,
- r_hit_list);
+ float ray_start[3], ray_normal[3];
+
+ if (!ED_view3d_win_to_ray_clipped_ex(sctx->depsgraph,
+ sctx->v3d_data.ar,
+ sctx->v3d_data.v3d,
+ mval,
+ NULL,
+ ray_normal,
+ ray_start,
+ true)) {
+ return false;
+ }
+
+ return ED_transform_snap_object_project_ray_all(
+ sctx, params, ray_start, ray_normal, ray_depth, sort, r_hit_list);
}
/** \} */
diff --git a/source/blender/editors/undo/CMakeLists.txt b/source/blender/editors/undo/CMakeLists.txt
index cebfa0d67f4..7c1a074bb13 100644
--- a/source/blender/editors/undo/CMakeLists.txt
+++ b/source/blender/editors/undo/CMakeLists.txt
@@ -16,38 +16,38 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blenloader
- ../../blentranslation
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/clog
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blenloader
+ ../../blentranslation
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/clog
)
set(SRC
- ed_undo.c
- memfile_undo.c
- undo_system_types.c
+ ed_undo.c
+ memfile_undo.c
+ undo_system_types.c
- undo_intern.h
+ undo_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
- bf_editor_curve
- bf_editor_lattice
- bf_editor_mesh
- bf_editor_metaball
- bf_editor_physics
+ bf_blenkernel
+ bf_blenlib
+ bf_editor_curve
+ bf_editor_lattice
+ bf_editor_mesh
+ bf_editor_metaball
+ bf_editor_physics
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
blender_add_lib(bf_editor_undo "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c
index 7c8fc4ef8ba..08f1a13e0c2 100644
--- a/source/blender/editors/undo/ed_undo.c
+++ b/source/blender/editors/undo/ed_undo.c
@@ -77,29 +77,29 @@ static CLG_LogRef LOG = {"ed.undo"};
void ED_undo_push(bContext *C, const char *str)
{
- CLOG_INFO(&LOG, 1, "name='%s'", str);
+ CLOG_INFO(&LOG, 1, "name='%s'", str);
- const int steps = U.undosteps;
+ const int steps = U.undosteps;
- if (steps <= 0) {
- return;
- }
+ if (steps <= 0) {
+ return;
+ }
- wmWindowManager *wm = CTX_wm_manager(C);
+ 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);
- }
+ /* 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);
+ }
- BKE_undosys_step_push(wm->undo_stack, C, str);
+ BKE_undosys_step_push(wm->undo_stack, C, 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);
- }
+ 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);
+ }
- WM_file_tag_modified();
+ WM_file_tag_modified();
}
/**
@@ -107,190 +107,194 @@ void ED_undo_push(bContext *C, const char *str)
*/
static int ed_undo_step(bContext *C, int step, const char *undoname, ReportList *reports)
{
- /* Mutually exclusives, ensure correct input. */
- BLI_assert((undoname && !step) || (!undoname && step));
- 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);
-
- /* 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 */
- WM_jobs_kill_all(wm);
-
- if (G.debug & G_DEBUG_IO) {
- Main *bmain = CTX_data_main(C);
- if (bmain->lock != NULL) {
- BKE_report(reports, RPT_INFO, "Checking sanity of current .blend file *BEFORE* undo step");
- BLO_main_validate_libraries(bmain, reports);
- }
- }
-
- /* TODO(campbell): undo_system: use undo system */
- /* grease pencil can be can be used in plenty of spaces, so check it first */
- if (ED_gpencil_session_active()) {
- return ED_undo_gpencil_step(C, step, undoname);
- }
- if (sa && (sa->spacetype == SPACE_VIEW3D)) {
- Object *obact = CTX_data_active_object(C);
- if (obact && (obact->type == OB_GPENCIL)) {
- ED_gpencil_toggle_brush_cursor(C, false, NULL);
- }
- }
-
- UndoStep *step_data_from_name = NULL;
- int step_for_callback = step;
- if (undoname != NULL) {
- step_data_from_name = BKE_undosys_step_find_by_name(wm->undo_stack, undoname);
- if (step_data_from_name == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- /* TODO(campbell), could use simple optimization. */
- /* Pointers match on redo. */
- step_for_callback = (
- BLI_findindex(&wm->undo_stack->steps, step_data_from_name) <
- BLI_findindex(&wm->undo_stack->steps, wm->undo_stack->step_active)) ? 1 : -1;
- }
-
- /* App-Handlers (pre). */
- {
- /* Note: ignore grease pencil for now. */
- Main *bmain = CTX_data_main(C);
- wm->op_undo_depth++;
- BLI_callback_exec(bmain, &scene->id, (step_for_callback > 0) ? BLI_CB_EVT_UNDO_PRE : BLI_CB_EVT_REDO_PRE);
- wm->op_undo_depth--;
- }
-
-
- /* Undo System */
- {
- if (undoname) {
- BKE_undosys_step_undo_with_data(wm->undo_stack, C, step_data_from_name);
- }
- else {
- if (step == 1) {
- BKE_undosys_step_undo(wm->undo_stack, C);
- }
- else {
- BKE_undosys_step_redo(wm->undo_stack, C);
- }
- }
-
- /* Set special modes for grease pencil */
- if (sa && (sa->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)) {
- ED_gpencil_toggle_brush_cursor(C, true, NULL);
- }
- else {
- ED_gpencil_toggle_brush_cursor(C, false, NULL);
- }
- /* set workspace mode */
- Base *basact = CTX_data_active_base(C);
- ED_object_base_activate(C, basact);
- }
- }
- }
-
- /* App-Handlers (post). */
- {
- Main *bmain = CTX_data_main(C);
- scene = CTX_data_scene(C);
- wm->op_undo_depth++;
- BLI_callback_exec(bmain, &scene->id, step_for_callback > 0 ? BLI_CB_EVT_UNDO_POST : BLI_CB_EVT_REDO_POST);
- wm->op_undo_depth--;
- }
-
- if (G.debug & G_DEBUG_IO) {
- Main *bmain = CTX_data_main(C);
- if (bmain->lock != NULL) {
- BKE_report(reports, RPT_INFO, "Checking sanity of current .blend file *AFTER* undo step");
- BLO_main_validate_libraries(bmain, reports);
- }
- }
-
- WM_event_add_notifier(C, NC_WINDOW, NULL);
- WM_event_add_notifier(C, NC_WM | ND_UNDO, NULL);
-
- WM_toolsystem_refresh_active(C);
-
- Main *bmain = CTX_data_main(C);
- WM_toolsystem_refresh_screen_all(bmain);
-
- return OPERATOR_FINISHED;
+ /* Mutually exclusives, ensure correct input. */
+ BLI_assert((undoname && !step) || (!undoname && step));
+ 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);
+
+ /* 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 */
+ WM_jobs_kill_all(wm);
+
+ if (G.debug & G_DEBUG_IO) {
+ Main *bmain = CTX_data_main(C);
+ if (bmain->lock != NULL) {
+ BKE_report(reports, RPT_INFO, "Checking sanity of current .blend file *BEFORE* undo step");
+ BLO_main_validate_libraries(bmain, reports);
+ }
+ }
+
+ /* TODO(campbell): undo_system: use undo system */
+ /* grease pencil can be can be used in plenty of spaces, so check it first */
+ if (ED_gpencil_session_active()) {
+ return ED_undo_gpencil_step(C, step, undoname);
+ }
+ if (sa && (sa->spacetype == SPACE_VIEW3D)) {
+ Object *obact = CTX_data_active_object(C);
+ if (obact && (obact->type == OB_GPENCIL)) {
+ ED_gpencil_toggle_brush_cursor(C, false, NULL);
+ }
+ }
+
+ UndoStep *step_data_from_name = NULL;
+ int step_for_callback = step;
+ if (undoname != NULL) {
+ step_data_from_name = BKE_undosys_step_find_by_name(wm->undo_stack, undoname);
+ if (step_data_from_name == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* TODO(campbell), could use simple optimization. */
+ /* Pointers match on redo. */
+ step_for_callback = (BLI_findindex(&wm->undo_stack->steps, step_data_from_name) <
+ BLI_findindex(&wm->undo_stack->steps, wm->undo_stack->step_active)) ?
+ 1 :
+ -1;
+ }
+
+ /* App-Handlers (pre). */
+ {
+ /* Note: ignore grease pencil for now. */
+ Main *bmain = CTX_data_main(C);
+ wm->op_undo_depth++;
+ BLI_callback_exec(
+ bmain, &scene->id, (step_for_callback > 0) ? BLI_CB_EVT_UNDO_PRE : BLI_CB_EVT_REDO_PRE);
+ wm->op_undo_depth--;
+ }
+
+ /* Undo System */
+ {
+ if (undoname) {
+ BKE_undosys_step_undo_with_data(wm->undo_stack, C, step_data_from_name);
+ }
+ else {
+ if (step == 1) {
+ BKE_undosys_step_undo(wm->undo_stack, C);
+ }
+ else {
+ BKE_undosys_step_redo(wm->undo_stack, C);
+ }
+ }
+
+ /* Set special modes for grease pencil */
+ if (sa && (sa->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)) {
+ ED_gpencil_toggle_brush_cursor(C, true, NULL);
+ }
+ else {
+ ED_gpencil_toggle_brush_cursor(C, false, NULL);
+ }
+ /* set workspace mode */
+ Base *basact = CTX_data_active_base(C);
+ ED_object_base_activate(C, basact);
+ }
+ }
+ }
+
+ /* App-Handlers (post). */
+ {
+ Main *bmain = CTX_data_main(C);
+ scene = CTX_data_scene(C);
+ wm->op_undo_depth++;
+ BLI_callback_exec(
+ bmain, &scene->id, step_for_callback > 0 ? BLI_CB_EVT_UNDO_POST : BLI_CB_EVT_REDO_POST);
+ wm->op_undo_depth--;
+ }
+
+ if (G.debug & G_DEBUG_IO) {
+ Main *bmain = CTX_data_main(C);
+ if (bmain->lock != NULL) {
+ BKE_report(reports, RPT_INFO, "Checking sanity of current .blend file *AFTER* undo step");
+ BLO_main_validate_libraries(bmain, reports);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ WM_event_add_notifier(C, NC_WM | ND_UNDO, NULL);
+
+ WM_toolsystem_refresh_active(C);
+
+ Main *bmain = CTX_data_main(C);
+ WM_toolsystem_refresh_screen_all(bmain);
+
+ return OPERATOR_FINISHED;
}
void ED_undo_grouped_push(bContext *C, const char *str)
{
- /* do nothing if previous undo task is the same as this one (or from the same undo group) */
- wmWindowManager *wm = CTX_wm_manager(C);
- const UndoStep *us = wm->undo_stack->step_active;
- if (us && STREQ(str, us->name)) {
- BKE_undosys_stack_clear_active(wm->undo_stack);
- }
-
- /* push as usual */
- ED_undo_push(C, str);
+ /* do nothing if previous undo task is the same as this one (or from the same undo group) */
+ wmWindowManager *wm = CTX_wm_manager(C);
+ const UndoStep *us = wm->undo_stack->step_active;
+ if (us && STREQ(str, us->name)) {
+ BKE_undosys_stack_clear_active(wm->undo_stack);
+ }
+
+ /* push as usual */
+ ED_undo_push(C, str);
}
void ED_undo_pop(bContext *C)
{
- ed_undo_step(C, 1, NULL, NULL);
+ ed_undo_step(C, 1, NULL, NULL);
}
void ED_undo_redo(bContext *C)
{
- ed_undo_step(C, -1, NULL, NULL);
+ ed_undo_step(C, -1, NULL, NULL);
}
void ED_undo_push_op(bContext *C, wmOperator *op)
{
- /* in future, get undo string info? */
- ED_undo_push(C, op->type->name);
+ /* in future, get undo string info? */
+ ED_undo_push(C, op->type->name);
}
void ED_undo_grouped_push_op(bContext *C, wmOperator *op)
{
- if (op->type->undo_group[0] != '\0') {
- ED_undo_grouped_push(C, op->type->undo_group);
- }
- else {
- ED_undo_grouped_push(C, op->type->name);
- }
+ if (op->type->undo_group[0] != '\0') {
+ ED_undo_grouped_push(C, op->type->undo_group);
+ }
+ else {
+ ED_undo_grouped_push(C, op->type->name);
+ }
}
void ED_undo_pop_op(bContext *C, wmOperator *op)
{
- /* search back a couple of undo's, in case something else added pushes */
- ed_undo_step(C, 0, op->type->name, op->reports);
+ /* search back a couple of undo's, in case something else added pushes */
+ ed_undo_step(C, 0, op->type->name, op->reports);
}
/* name optionally, function used to check for operator redo panel */
bool ED_undo_is_valid(const bContext *C, const char *undoname)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- return BKE_undosys_stack_has_undo(wm->undo_stack, undoname);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ return BKE_undosys_stack_has_undo(wm->undo_stack, undoname);
}
bool ED_undo_is_memfile_compatible(const bContext *C)
{
- /* Some modes don't co-exist with memfile undo, disable their use: T60593
- * (this matches 2.7x behavior). */
- ViewLayer *view_layer = CTX_data_view_layer(C);
- if (view_layer != NULL) {
- Object *obact = OBACT(view_layer);
- if (obact != NULL) {
- if (obact->mode & (OB_MODE_SCULPT | OB_MODE_EDIT)) {
- return false;
- }
- }
- }
- return true;
+ /* Some modes don't co-exist with memfile undo, disable their use: T60593
+ * (this matches 2.7x behavior). */
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ if (view_layer != NULL) {
+ Object *obact = OBACT(view_layer);
+ if (obact != NULL) {
+ if (obact->mode & (OB_MODE_SCULPT | OB_MODE_EDIT)) {
+ return false;
+ }
+ }
+ }
+ return true;
}
-
/**
* Ideally we wont access the stack directly,
* this is needed for modes which handle undo themselves (bypassing #ED_undo_push).
@@ -300,8 +304,8 @@ bool ED_undo_is_memfile_compatible(const bContext *C)
*/
UndoStack *ED_undo_stack_get(void)
{
- wmWindowManager *wm = G_MAIN->wm.first;
- return wm->undo_stack;
+ wmWindowManager *wm = G_MAIN->wm.first;
+ return wm->undo_stack;
}
/** \} */
@@ -312,133 +316,138 @@ UndoStack *ED_undo_stack_get(void)
static int ed_undo_exec(bContext *C, wmOperator *op)
{
- /* "last operator" should disappear, later we can tie this with undo stack nicer */
- WM_operator_stack_clear(CTX_wm_manager(C));
- int ret = ed_undo_step(C, 1, NULL, op->reports);
- if (ret & OPERATOR_FINISHED) {
- /* Keep button under the cursor active. */
- WM_event_add_mousemove(C);
- }
- return ret;
+ /* "last operator" should disappear, later we can tie this with undo stack nicer */
+ WM_operator_stack_clear(CTX_wm_manager(C));
+ int ret = ed_undo_step(C, 1, NULL, op->reports);
+ if (ret & OPERATOR_FINISHED) {
+ /* Keep button under the cursor active. */
+ WM_event_add_mousemove(C);
+ }
+ return ret;
}
static int ed_undo_push_exec(bContext *C, wmOperator *op)
{
- if (G.background) {
- /* Exception for background mode, see: T60934.
- * Note: since the undo stack isn't initialized on startup, background mode behavior
- * won't match regular usage, this is just for scripts to do explicit undo pushes. */
- wmWindowManager *wm = CTX_wm_manager(C);
- if (wm->undo_stack == NULL) {
- wm->undo_stack = BKE_undosys_stack_create();
- }
- }
- char str[BKE_UNDO_STR_MAX];
- RNA_string_get(op->ptr, "message", str);
- ED_undo_push(C, str);
- return OPERATOR_FINISHED;
+ if (G.background) {
+ /* Exception for background mode, see: T60934.
+ * Note: since the undo stack isn't initialized on startup, background mode behavior
+ * won't match regular usage, this is just for scripts to do explicit undo pushes. */
+ wmWindowManager *wm = CTX_wm_manager(C);
+ if (wm->undo_stack == NULL) {
+ wm->undo_stack = BKE_undosys_stack_create();
+ }
+ }
+ char str[BKE_UNDO_STR_MAX];
+ RNA_string_get(op->ptr, "message", str);
+ ED_undo_push(C, str);
+ return OPERATOR_FINISHED;
}
static int ed_redo_exec(bContext *C, wmOperator *op)
{
- int ret = ed_undo_step(C, -1, NULL, op->reports);
- if (ret & OPERATOR_FINISHED) {
- /* Keep button under the cursor active. */
- WM_event_add_mousemove(C);
- }
- return ret;
+ int ret = ed_undo_step(C, -1, NULL, op->reports);
+ if (ret & OPERATOR_FINISHED) {
+ /* Keep button under the cursor active. */
+ WM_event_add_mousemove(C);
+ }
+ return ret;
}
static int ed_undo_redo_exec(bContext *C, wmOperator *UNUSED(op))
{
- wmOperator *last_op = WM_operator_last_redo(C);
- int ret = ED_undo_operator_repeat(C, last_op);
- ret = ret ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
- if (ret & OPERATOR_FINISHED) {
- /* Keep button under the cursor active. */
- WM_event_add_mousemove(C);
- }
- return ret;
+ wmOperator *last_op = WM_operator_last_redo(C);
+ int ret = ED_undo_operator_repeat(C, last_op);
+ ret = ret ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ if (ret & OPERATOR_FINISHED) {
+ /* Keep button under the cursor active. */
+ WM_event_add_mousemove(C);
+ }
+ return ret;
}
/* Disable in background mode, we could support if it's useful, T60934. */
static bool ed_undo_is_init_poll(bContext *C)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- if (wm->undo_stack == NULL) {
- CTX_wm_operator_poll_msg_set(C, "Undo disabled at startup");
- return false;
- }
- return true;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ if (wm->undo_stack == NULL) {
+ CTX_wm_operator_poll_msg_set(C, "Undo disabled at startup");
+ return false;
+ }
+ return true;
}
static bool ed_undo_is_init_and_screenactive_poll(bContext *C)
{
- if (ed_undo_is_init_poll(C) == false) {
- return false;
- }
- return ED_operator_screenactive(C);
+ if (ed_undo_is_init_poll(C) == false) {
+ return false;
+ }
+ return ED_operator_screenactive(C);
}
static bool ed_undo_redo_poll(bContext *C)
{
- wmOperator *last_op = WM_operator_last_redo(C);
- return (last_op && ed_undo_is_init_and_screenactive_poll(C) &&
- WM_operator_check_ui_enabled(C, last_op->type->name));
+ wmOperator *last_op = WM_operator_last_redo(C);
+ return (last_op && ed_undo_is_init_and_screenactive_poll(C) &&
+ WM_operator_check_ui_enabled(C, last_op->type->name));
}
void ED_OT_undo(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Undo";
- ot->description = "Undo previous action";
- ot->idname = "ED_OT_undo";
-
- /* api callbacks */
- ot->exec = ed_undo_exec;
- ot->poll = ed_undo_is_init_and_screenactive_poll;
+ /* identifiers */
+ ot->name = "Undo";
+ ot->description = "Undo previous action";
+ ot->idname = "ED_OT_undo";
+
+ /* api callbacks */
+ ot->exec = ed_undo_exec;
+ ot->poll = ed_undo_is_init_and_screenactive_poll;
}
void ED_OT_undo_push(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Undo Push";
- ot->description = "Add an undo state (internal use only)";
- ot->idname = "ED_OT_undo_push";
-
- /* api callbacks */
- ot->exec = ed_undo_push_exec;
- /* Unlike others undo operators this initializes undo stack. */
- ot->poll = ED_operator_screenactive;
-
- ot->flag = OPTYPE_INTERNAL;
-
- RNA_def_string(ot->srna, "message", "Add an undo step *function may be moved*", BKE_UNDO_STR_MAX, "Undo Message", "");
+ /* identifiers */
+ ot->name = "Undo Push";
+ ot->description = "Add an undo state (internal use only)";
+ ot->idname = "ED_OT_undo_push";
+
+ /* api callbacks */
+ ot->exec = ed_undo_push_exec;
+ /* Unlike others undo operators this initializes undo stack. */
+ ot->poll = ED_operator_screenactive;
+
+ ot->flag = OPTYPE_INTERNAL;
+
+ RNA_def_string(ot->srna,
+ "message",
+ "Add an undo step *function may be moved*",
+ BKE_UNDO_STR_MAX,
+ "Undo Message",
+ "");
}
void ED_OT_redo(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Redo";
- ot->description = "Redo previous action";
- ot->idname = "ED_OT_redo";
-
- /* api callbacks */
- ot->exec = ed_redo_exec;
- ot->poll = ed_undo_is_init_and_screenactive_poll;
+ /* identifiers */
+ ot->name = "Redo";
+ ot->description = "Redo previous action";
+ ot->idname = "ED_OT_redo";
+
+ /* api callbacks */
+ ot->exec = ed_redo_exec;
+ ot->poll = ed_undo_is_init_and_screenactive_poll;
}
void ED_OT_undo_redo(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Undo and Redo";
- ot->description = "Undo and redo previous action";
- ot->idname = "ED_OT_undo_redo";
-
- /* api callbacks */
- ot->exec = ed_undo_redo_exec;
- ot->poll = ed_undo_redo_poll;
+ /* identifiers */
+ ot->name = "Undo and Redo";
+ ot->description = "Undo and redo previous action";
+ ot->idname = "ED_OT_undo_redo";
+
+ /* api callbacks */
+ ot->exec = ed_undo_redo_exec;
+ ot->poll = ed_undo_redo_poll;
}
/** \} */
@@ -450,93 +459,90 @@ void ED_OT_undo_redo(wmOperatorType *ot)
/* ui callbacks should call this rather than calling WM_operator_repeat() themselves */
int ED_undo_operator_repeat(bContext *C, wmOperator *op)
{
- int ret = 0;
-
- if (op) {
- CLOG_INFO(&LOG, 1, "idname='%s'", op->type->idname);
- wmWindowManager *wm = CTX_wm_manager(C);
- 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));
-
- if (ar_win) {
- CTX_wm_region_set(C, ar_win);
- }
-
- if ((WM_operator_repeat_check(C, op)) &&
- (WM_operator_poll(C, op->type)) &&
- /* note, undo/redo cant run if there are jobs active,
- * check for screen jobs only so jobs like material/texture/world preview
- * (which copy their data), wont stop redo, see [#29579]],
- *
- * note, - WM_operator_check_ui_enabled() jobs test _must_ stay in sync with this */
- (WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY) == 0))
- {
- int retval;
-
- if (G.debug & G_DEBUG)
- printf("redo_cb: operator redo %s\n", op->type->name);
-
- WM_operator_free_all_after(wm, op);
-
- ED_undo_pop_op(C, 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);
- }
- }
- }
-
- if (op->type->flag & OPTYPE_USE_EVAL_DATA) {
- /* We need to force refresh of depsgraph after undo step,
- * redoing the operator *may* rely on some valid evaluated data. */
- Main *bmain = CTX_data_main(C);
- scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- BKE_scene_view_layer_graph_evaluated_ensure(bmain, scene, view_layer);
- }
-
- retval = WM_operator_repeat(C, op);
- if ((retval & OPERATOR_FINISHED) == 0) {
- if (G.debug & G_DEBUG)
- printf("redo_cb: operator redo failed: %s, return %d\n", op->type->name, retval);
- ED_undo_redo(C);
- }
- else {
- ret = 1;
- }
- }
- else {
- if (G.debug & G_DEBUG) {
- printf("redo_cb: WM_operator_repeat_check returned false %s\n", op->type->name);
- }
- }
-
- /* set region back */
- CTX_wm_region_set(C, ar_orig);
- }
- else {
- CLOG_WARN(&LOG, "called with NULL 'op'");
- }
-
- return ret;
+ int ret = 0;
+
+ if (op) {
+ CLOG_INFO(&LOG, 1, "idname='%s'", op->type->idname);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ 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));
+
+ if (ar_win) {
+ CTX_wm_region_set(C, ar_win);
+ }
+
+ if ((WM_operator_repeat_check(C, op)) && (WM_operator_poll(C, op->type)) &&
+ /* note, undo/redo cant run if there are jobs active,
+ * check for screen jobs only so jobs like material/texture/world preview
+ * (which copy their data), wont stop redo, see [#29579]],
+ *
+ * note, - WM_operator_check_ui_enabled() jobs test _must_ stay in sync with this */
+ (WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY) == 0)) {
+ int retval;
+
+ if (G.debug & G_DEBUG)
+ printf("redo_cb: operator redo %s\n", op->type->name);
+
+ WM_operator_free_all_after(wm, op);
+
+ ED_undo_pop_op(C, 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);
+ }
+ }
+ }
+
+ if (op->type->flag & OPTYPE_USE_EVAL_DATA) {
+ /* We need to force refresh of depsgraph after undo step,
+ * redoing the operator *may* rely on some valid evaluated data. */
+ Main *bmain = CTX_data_main(C);
+ scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_scene_view_layer_graph_evaluated_ensure(bmain, scene, view_layer);
+ }
+
+ retval = WM_operator_repeat(C, op);
+ if ((retval & OPERATOR_FINISHED) == 0) {
+ if (G.debug & G_DEBUG)
+ printf("redo_cb: operator redo failed: %s, return %d\n", op->type->name, retval);
+ ED_undo_redo(C);
+ }
+ else {
+ ret = 1;
+ }
+ }
+ else {
+ if (G.debug & G_DEBUG) {
+ printf("redo_cb: WM_operator_repeat_check returned false %s\n", op->type->name);
+ }
+ }
+
+ /* set region back */
+ CTX_wm_region_set(C, ar_orig);
+ }
+ else {
+ CLOG_WARN(&LOG, "called with NULL 'op'");
+ }
+
+ return ret;
}
-
void ED_undo_operator_repeat_cb(bContext *C, void *arg_op, void *UNUSED(arg_unused))
{
- ED_undo_operator_repeat(C, (wmOperator *)arg_op);
+ ED_undo_operator_repeat(C, (wmOperator *)arg_op);
}
void ED_undo_operator_repeat_cb_evt(bContext *C, void *arg_op, int UNUSED(arg_event))
{
- ED_undo_operator_repeat(C, (wmOperator *)arg_op);
+ ED_undo_operator_repeat(C, (wmOperator *)arg_op);
}
/** \} */
@@ -548,99 +554,96 @@ void ED_undo_operator_repeat_cb_evt(bContext *C, void *arg_op, int UNUSED(arg_ev
/* create enum based on undo items */
static const EnumPropertyItem *rna_undo_itemf(bContext *C, int *totitem)
{
- EnumPropertyItem item_tmp = {0}, *item = NULL;
- int i = 0;
-
- wmWindowManager *wm = CTX_wm_manager(C);
- if (wm->undo_stack == NULL) {
- return NULL;
- }
-
- for (UndoStep *us = wm->undo_stack->steps.first; us; us = us->next, i++) {
- if (us->skip == false) {
- item_tmp.identifier = us->name;
- item_tmp.name = IFACE_(us->name);
- if (us == wm->undo_stack->step_active) {
- item_tmp.icon = ICON_HIDE_OFF;
- }
- else {
- item_tmp.icon = ICON_NONE;
- }
- item_tmp.value = i;
- RNA_enum_item_add(&item, totitem, &item_tmp);
- }
- }
- RNA_enum_item_end(&item, totitem);
-
- return item;
+ EnumPropertyItem item_tmp = {0}, *item = NULL;
+ int i = 0;
+
+ wmWindowManager *wm = CTX_wm_manager(C);
+ if (wm->undo_stack == NULL) {
+ return NULL;
+ }
+
+ for (UndoStep *us = wm->undo_stack->steps.first; us; us = us->next, i++) {
+ if (us->skip == false) {
+ item_tmp.identifier = us->name;
+ item_tmp.name = IFACE_(us->name);
+ if (us == wm->undo_stack->step_active) {
+ item_tmp.icon = ICON_HIDE_OFF;
+ }
+ else {
+ item_tmp.icon = ICON_NONE;
+ }
+ item_tmp.value = i;
+ RNA_enum_item_add(&item, totitem, &item_tmp);
+ }
+ }
+ RNA_enum_item_end(&item, totitem);
+
+ return item;
}
-
static int undo_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- int totitem = 0;
-
- {
- const EnumPropertyItem *item = rna_undo_itemf(C, &totitem);
-
- if (totitem > 0) {
- uiPopupMenu *pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
- uiLayout *layout = UI_popup_menu_layout(pup);
- uiLayout *split = uiLayoutSplit(layout, 0.0f, false);
- uiLayout *column = NULL;
- const int col_size = 20 + totitem / 12;
- int i, c;
- bool add_col = true;
-
- for (c = 0, i = totitem; i--;) {
- if (add_col && !(c % col_size)) {
- column = uiLayoutColumn(split, false);
- add_col = false;
- }
- if (item[i].identifier) {
- uiItemIntO(column, item[i].name, item[i].icon, op->type->idname, "item", item[i].value);
- ++c;
- add_col = true;
- }
- }
-
- MEM_freeN((void *)item);
-
- UI_popup_menu_end(C, pup);
- }
-
- }
- return OPERATOR_CANCELLED;
+ int totitem = 0;
+
+ {
+ const EnumPropertyItem *item = rna_undo_itemf(C, &totitem);
+
+ if (totitem > 0) {
+ uiPopupMenu *pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+ uiLayout *split = uiLayoutSplit(layout, 0.0f, false);
+ uiLayout *column = NULL;
+ const int col_size = 20 + totitem / 12;
+ int i, c;
+ bool add_col = true;
+
+ for (c = 0, i = totitem; i--;) {
+ if (add_col && !(c % col_size)) {
+ column = uiLayoutColumn(split, false);
+ add_col = false;
+ }
+ if (item[i].identifier) {
+ uiItemIntO(column, item[i].name, item[i].icon, op->type->idname, "item", item[i].value);
+ ++c;
+ add_col = true;
+ }
+ }
+
+ MEM_freeN((void *)item);
+
+ UI_popup_menu_end(C, pup);
+ }
+ }
+ return OPERATOR_CANCELLED;
}
/* note: also check ed_undo_step() in top if you change notifiers */
static int undo_history_exec(bContext *C, wmOperator *op)
{
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, "item");
- if (RNA_property_is_set(op->ptr, prop)) {
- int item = RNA_property_int_get(op->ptr, prop);
- wmWindowManager *wm = CTX_wm_manager(C);
- BKE_undosys_step_undo_from_index(wm->undo_stack, C, item);
- WM_event_add_notifier(C, NC_WINDOW, NULL);
- return OPERATOR_FINISHED;
- }
- return OPERATOR_CANCELLED;
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "item");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ int item = RNA_property_int_get(op->ptr, prop);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ BKE_undosys_step_undo_from_index(wm->undo_stack, C, item);
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_CANCELLED;
}
void ED_OT_undo_history(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Undo History";
- ot->description = "Redo specific action in history";
- ot->idname = "ED_OT_undo_history";
-
- /* api callbacks */
- ot->invoke = undo_history_invoke;
- ot->exec = undo_history_exec;
- ot->poll = ed_undo_is_init_and_screenactive_poll;
+ /* identifiers */
+ ot->name = "Undo History";
+ ot->description = "Redo specific action in history";
+ ot->idname = "ED_OT_undo_history";
- RNA_def_int(ot->srna, "item", 0, 0, INT_MAX, "Item", "", 0, INT_MAX);
+ /* api callbacks */
+ ot->invoke = undo_history_invoke;
+ ot->exec = undo_history_exec;
+ ot->poll = ed_undo_is_init_and_screenactive_poll;
+ RNA_def_int(ot->srna, "item", 0, 0, INT_MAX, "Item", "", 0, INT_MAX);
}
/** \} */
@@ -649,52 +652,55 @@ void ED_OT_undo_history(wmOperatorType *ot)
/** \name Undo Helper Functions
* \{ */
-void ED_undo_object_set_active_or_warn(ViewLayer *view_layer, Object *ob, const char *info, CLG_LogRef *log)
+void ED_undo_object_set_active_or_warn(ViewLayer *view_layer,
+ Object *ob,
+ const char *info,
+ CLG_LogRef *log)
{
- Object *ob_prev = OBACT(view_layer);
- if (ob_prev != ob) {
- Base *base = BKE_view_layer_base_find(view_layer, ob);
- if (base != NULL) {
- view_layer->basact = base;
- }
- else {
- /* Should never fail, may not crash but can give odd behavior. */
- CLOG_WARN(log, "'%s' failed to restore active object: '%s'", info, ob->id.name + 2);
- }
- }
+ Object *ob_prev = OBACT(view_layer);
+ if (ob_prev != ob) {
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+ if (base != NULL) {
+ view_layer->basact = base;
+ }
+ else {
+ /* Should never fail, may not crash but can give odd behavior. */
+ CLOG_WARN(log, "'%s' failed to restore active object: '%s'", info, ob->id.name + 2);
+ }
+ }
}
-void ED_undo_object_editmode_restore_helper(
- struct bContext *C, Object **object_array, uint object_array_len, uint object_array_stride)
+void ED_undo_object_editmode_restore_helper(struct bContext *C,
+ Object **object_array,
+ uint object_array_len,
+ uint object_array_stride)
{
- Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint bases_len = 0;
- /* Don't request unique data because we wan't 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);
- for (uint i = 0; i < bases_len; i++) {
- ((ID *)bases[i]->object->data)->tag |= LIB_TAG_DOIT;
- }
- Scene *scene = CTX_data_scene(C);
- Object **ob_p = object_array;
- for (uint i = 0; i < object_array_len; i++, ob_p = POINTER_OFFSET(ob_p, object_array_stride)) {
- Object *obedit = *ob_p;
- ED_object_editmode_enter_ex(bmain, scene, obedit, EM_NO_CONTEXT);
- ((ID *)obedit->data)->tag &= ~LIB_TAG_DOIT;
- }
- for (uint i = 0; i < bases_len; i++) {
- ID *id = bases[i]->object->data;
- if (id->tag & LIB_TAG_DOIT) {
- ED_object_editmode_exit_ex(bmain, scene, bases[i]->object, EM_FREEDATA);
- /* Ideally we would know the selection state it was before entering edit-mode,
- * for now follow the convention of having them unselected when exiting the mode. */
- ED_object_base_select(bases[i], BA_DESELECT);
-
- }
- }
- MEM_freeN(bases);
+ Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint bases_len = 0;
+ /* Don't request unique data because we wan't 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);
+ for (uint i = 0; i < bases_len; i++) {
+ ((ID *)bases[i]->object->data)->tag |= LIB_TAG_DOIT;
+ }
+ Scene *scene = CTX_data_scene(C);
+ Object **ob_p = object_array;
+ for (uint i = 0; i < object_array_len; i++, ob_p = POINTER_OFFSET(ob_p, object_array_stride)) {
+ Object *obedit = *ob_p;
+ ED_object_editmode_enter_ex(bmain, scene, obedit, EM_NO_CONTEXT);
+ ((ID *)obedit->data)->tag &= ~LIB_TAG_DOIT;
+ }
+ for (uint i = 0; i < bases_len; i++) {
+ ID *id = bases[i]->object->data;
+ if (id->tag & LIB_TAG_DOIT) {
+ ED_object_editmode_exit_ex(bmain, scene, bases[i]->object, EM_FREEDATA);
+ /* Ideally we would know the selection state it was before entering edit-mode,
+ * for now follow the convention of having them unselected when exiting the mode. */
+ ED_object_base_select(bases[i], BA_DESELECT);
+ }
+ }
+ MEM_freeN(bases);
}
/** \} */
diff --git a/source/blender/editors/undo/memfile_undo.c b/source/blender/editors/undo/memfile_undo.c
index c6719f6433a..36ce38091d4 100644
--- a/source/blender/editors/undo/memfile_undo.c
+++ b/source/blender/editors/undo/memfile_undo.c
@@ -45,97 +45,101 @@
* \{ */
typedef struct MemFileUndoStep {
- UndoStep step;
- MemFileUndoData *data;
+ UndoStep step;
+ MemFileUndoData *data;
} MemFileUndoStep;
static bool memfile_undosys_poll(bContext *C)
{
- /* other poll functions must run first, this is a catch-all. */
-
- if ((U.uiflag & USER_GLOBALUNDO) == 0) {
- return false;
- }
-
- /* Allow a single memfile undo step (the first). */
- UndoStack *ustack = ED_undo_stack_get();
- if ((ustack->step_active != NULL) &&
- (ED_undo_is_memfile_compatible(C) == false))
- {
- return false;
- }
- return true;
+ /* other poll functions must run first, this is a catch-all. */
+
+ if ((U.uiflag & USER_GLOBALUNDO) == 0) {
+ return false;
+ }
+
+ /* Allow a single memfile undo step (the first). */
+ UndoStack *ustack = ED_undo_stack_get();
+ if ((ustack->step_active != NULL) && (ED_undo_is_memfile_compatible(C) == false)) {
+ return false;
+ }
+ return true;
}
-static bool memfile_undosys_step_encode(struct bContext *UNUSED(C), struct Main *bmain, UndoStep *us_p)
+static bool memfile_undosys_step_encode(struct bContext *UNUSED(C),
+ struct Main *bmain,
+ UndoStep *us_p)
{
- MemFileUndoStep *us = (MemFileUndoStep *)us_p;
+ MemFileUndoStep *us = (MemFileUndoStep *)us_p;
- /* Important we only use 'main' from the context (see: BKE_undosys_stack_init_from_main). */
- UndoStack *ustack = ED_undo_stack_get();
+ /* Important we only use 'main' from the context (see: BKE_undosys_stack_init_from_main). */
+ UndoStack *ustack = ED_undo_stack_get();
- /* can be NULL, use when set. */
- MemFileUndoStep *us_prev = (MemFileUndoStep *)BKE_undosys_step_find_by_type(ustack, BKE_UNDOSYS_TYPE_MEMFILE);
- us->data = BKE_memfile_undo_encode(bmain, us_prev ? us_prev->data : NULL);
- us->step.data_size = us->data->undo_size;
+ /* can be NULL, use when set. */
+ MemFileUndoStep *us_prev = (MemFileUndoStep *)BKE_undosys_step_find_by_type(
+ ustack, BKE_UNDOSYS_TYPE_MEMFILE);
+ us->data = BKE_memfile_undo_encode(bmain, us_prev ? us_prev->data : NULL);
+ us->step.data_size = us->data->undo_size;
- return true;
+ return true;
}
-static void memfile_undosys_step_decode(struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir))
+static void memfile_undosys_step_decode(struct bContext *C,
+ struct Main *bmain,
+ UndoStep *us_p,
+ int UNUSED(dir))
{
- ED_editors_exit(bmain, false);
-
- MemFileUndoStep *us = (MemFileUndoStep *)us_p;
- BKE_memfile_undo_decode(us->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)) {
- continue;
- }
- us_iter->is_applied = false;
- }
- for (UndoStep *us_iter = us_p; us_iter; us_iter = us_iter->prev) {
- if (BKE_UNDOSYS_TYPE_IS_MEMFILE_SKIP(us_iter->type)) {
- continue;
- }
- us_iter->is_applied = true;
- }
-
- /* bmain has been freed. */
- bmain = CTX_data_main(C);
- ED_editors_init_for_undo(bmain);
-
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
+ ED_editors_exit(bmain, false);
+
+ MemFileUndoStep *us = (MemFileUndoStep *)us_p;
+ BKE_memfile_undo_decode(us->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)) {
+ continue;
+ }
+ us_iter->is_applied = false;
+ }
+ for (UndoStep *us_iter = us_p; us_iter; us_iter = us_iter->prev) {
+ if (BKE_UNDOSYS_TYPE_IS_MEMFILE_SKIP(us_iter->type)) {
+ continue;
+ }
+ us_iter->is_applied = true;
+ }
+
+ /* bmain has been freed. */
+ bmain = CTX_data_main(C);
+ ED_editors_init_for_undo(bmain);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
}
static void memfile_undosys_step_free(UndoStep *us_p)
{
- /* To avoid unnecessary slow down, free backwards (so we don't need to merge when clearing all). */
- MemFileUndoStep *us = (MemFileUndoStep *)us_p;
- if (us_p->next != NULL) {
- UndoStep *us_next_p = BKE_undosys_step_same_type_next(us_p);
- if (us_next_p != NULL) {
- MemFileUndoStep *us_next = (MemFileUndoStep *)us_next_p;
- BLO_memfile_merge(&us->data->memfile, &us_next->data->memfile);
- }
- }
-
- BKE_memfile_undo_free(us->data);
+ /* To avoid unnecessary slow down, free backwards (so we don't need to merge when clearing all). */
+ MemFileUndoStep *us = (MemFileUndoStep *)us_p;
+ if (us_p->next != NULL) {
+ UndoStep *us_next_p = BKE_undosys_step_same_type_next(us_p);
+ if (us_next_p != NULL) {
+ MemFileUndoStep *us_next = (MemFileUndoStep *)us_next_p;
+ BLO_memfile_merge(&us->data->memfile, &us_next->data->memfile);
+ }
+ }
+
+ BKE_memfile_undo_free(us->data);
}
/* Export for ED_undo_sys. */
void ED_memfile_undosys_type(UndoType *ut)
{
- ut->name = "Global Undo";
- ut->poll = memfile_undosys_poll;
- ut->step_encode = memfile_undosys_step_encode;
- ut->step_decode = memfile_undosys_step_decode;
- ut->step_free = memfile_undosys_step_free;
+ ut->name = "Global Undo";
+ ut->poll = memfile_undosys_poll;
+ ut->step_encode = memfile_undosys_step_encode;
+ ut->step_decode = memfile_undosys_step_decode;
+ ut->step_free = memfile_undosys_step_free;
- ut->use_context = true;
+ ut->use_context = true;
- ut->step_size = sizeof(MemFileUndoStep);
+ ut->step_size = sizeof(MemFileUndoStep);
}
/** \} */
@@ -149,18 +153,17 @@ void ED_memfile_undosys_type(UndoType *ut)
*/
static struct MemFile *ed_undosys_step_get_memfile(UndoStep *us_p)
{
- MemFileUndoStep *us = (MemFileUndoStep *)us_p;
- return &us->data->memfile;
+ MemFileUndoStep *us = (MemFileUndoStep *)us_p;
+ return &us->data->memfile;
}
struct MemFile *ED_undosys_stack_memfile_get_active(UndoStack *ustack)
{
- UndoStep *us = BKE_undosys_stack_active_with_type(ustack, BKE_UNDOSYS_TYPE_MEMFILE);
- if (us) {
- return ed_undosys_step_get_memfile(us);
- }
- return NULL;
+ UndoStep *us = BKE_undosys_stack_active_with_type(ustack, BKE_UNDOSYS_TYPE_MEMFILE);
+ if (us) {
+ return ed_undosys_step_get_memfile(us);
+ }
+ return NULL;
}
-
/** \} */
diff --git a/source/blender/editors/undo/undo_system_types.c b/source/blender/editors/undo/undo_system_types.c
index 0f052920993..300ab606a03 100644
--- a/source/blender/editors/undo/undo_system_types.c
+++ b/source/blender/editors/undo/undo_system_types.c
@@ -22,7 +22,6 @@
#include "BLI_utildefines.h"
-
#include "ED_armature.h"
#include "ED_curve.h"
#include "ED_lattice.h"
@@ -40,31 +39,31 @@
void ED_undosys_type_init(void)
{
- /* Edit Modes */
- BKE_undosys_type_append(ED_armature_undosys_type);
- BKE_undosys_type_append(ED_curve_undosys_type);
- BKE_undosys_type_append(ED_font_undosys_type);
- BKE_undosys_type_append(ED_lattice_undosys_type);
- BKE_undosys_type_append(ED_mball_undosys_type);
- BKE_undosys_type_append(ED_mesh_undosys_type);
+ /* Edit Modes */
+ BKE_undosys_type_append(ED_armature_undosys_type);
+ BKE_undosys_type_append(ED_curve_undosys_type);
+ BKE_undosys_type_append(ED_font_undosys_type);
+ BKE_undosys_type_append(ED_lattice_undosys_type);
+ BKE_undosys_type_append(ED_mball_undosys_type);
+ BKE_undosys_type_append(ED_mesh_undosys_type);
- /* Paint Modes */
- BKE_UNDOSYS_TYPE_IMAGE = BKE_undosys_type_append(ED_image_undosys_type);
+ /* Paint Modes */
+ BKE_UNDOSYS_TYPE_IMAGE = BKE_undosys_type_append(ED_image_undosys_type);
- BKE_UNDOSYS_TYPE_SCULPT = BKE_undosys_type_append(ED_sculpt_undosys_type);
+ BKE_UNDOSYS_TYPE_SCULPT = BKE_undosys_type_append(ED_sculpt_undosys_type);
- BKE_UNDOSYS_TYPE_PARTICLE = BKE_undosys_type_append(ED_particle_undosys_type);
+ BKE_UNDOSYS_TYPE_PARTICLE = BKE_undosys_type_append(ED_particle_undosys_type);
- BKE_UNDOSYS_TYPE_PAINTCURVE = BKE_undosys_type_append(ED_paintcurve_undosys_type);
+ BKE_UNDOSYS_TYPE_PAINTCURVE = BKE_undosys_type_append(ED_paintcurve_undosys_type);
- /* Text editor */
- BKE_UNDOSYS_TYPE_TEXT = BKE_undosys_type_append(ED_text_undosys_type);
+ /* Text editor */
+ BKE_UNDOSYS_TYPE_TEXT = BKE_undosys_type_append(ED_text_undosys_type);
- /* Keep global undo last (as a fallback). */
- BKE_UNDOSYS_TYPE_MEMFILE = BKE_undosys_type_append(ED_memfile_undosys_type);
+ /* Keep global undo last (as a fallback). */
+ BKE_UNDOSYS_TYPE_MEMFILE = BKE_undosys_type_append(ED_memfile_undosys_type);
}
void ED_undosys_type_free(void)
{
- BKE_undosys_type_free_all();
+ BKE_undosys_type_free_all();
}
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index 728dacc1649..a1893d8e6f1 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -16,87 +16,87 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../bmesh
- ../../depsgraph
- ../../imbuf
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/clog
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../bmesh
+ ../../depsgraph
+ ../../imbuf
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/clog
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- ed_transverts.c
- ed_util.c
- gizmo_utils.c
- numinput.c
- select_utils.c
+ ed_transverts.c
+ ed_util.c
+ gizmo_utils.c
+ numinput.c
+ select_utils.c
- # general includes
- ../include/BIF_gl.h
- ../include/BIF_glutil.h
- ../include/ED_anim_api.h
- ../include/ED_armature.h
- ../include/ED_buttons.h
- ../include/ED_clip.h
- ../include/ED_curve.h
- ../include/ED_datafiles.h
- ../include/ED_fileselect.h
- ../include/ED_gizmo_library.h
- ../include/ED_gizmo_utils.h
- ../include/ED_gpencil.h
- ../include/ED_image.h
- ../include/ED_info.h
- ../include/ED_keyframes_draw.h
- ../include/ED_keyframes_edit.h
- ../include/ED_keyframing.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_numinput.h
- ../include/ED_object.h
- ../include/ED_outliner.h
- ../include/ED_paint.h
- ../include/ED_particle.h
- ../include/ED_physics.h
- ../include/ED_render.h
- ../include/ED_scene.h
- ../include/ED_screen.h
- ../include/ED_screen_types.h
- ../include/ED_sculpt.h
- ../include/ED_select_utils.h
- ../include/ED_sequencer.h
- ../include/ED_sound.h
- ../include/ED_space_api.h
- ../include/ED_text.h
- ../include/ED_transform.h
- ../include/ED_transform_snap_object_context.h
- ../include/ED_transverts.h
- ../include/ED_types.h
- ../include/ED_undo.h
- ../include/ED_util.h
- ../include/ED_uvedit.h
- ../include/ED_view3d.h
- ../include/UI_icons.h
- ../include/UI_interface.h
- ../include/UI_interface_icons.h
- ../include/UI_resources.h
- ../include/UI_view2d.h
+ # general includes
+ ../include/BIF_gl.h
+ ../include/BIF_glutil.h
+ ../include/ED_anim_api.h
+ ../include/ED_armature.h
+ ../include/ED_buttons.h
+ ../include/ED_clip.h
+ ../include/ED_curve.h
+ ../include/ED_datafiles.h
+ ../include/ED_fileselect.h
+ ../include/ED_gizmo_library.h
+ ../include/ED_gizmo_utils.h
+ ../include/ED_gpencil.h
+ ../include/ED_image.h
+ ../include/ED_info.h
+ ../include/ED_keyframes_draw.h
+ ../include/ED_keyframes_edit.h
+ ../include/ED_keyframing.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_numinput.h
+ ../include/ED_object.h
+ ../include/ED_outliner.h
+ ../include/ED_paint.h
+ ../include/ED_particle.h
+ ../include/ED_physics.h
+ ../include/ED_render.h
+ ../include/ED_scene.h
+ ../include/ED_screen.h
+ ../include/ED_screen_types.h
+ ../include/ED_sculpt.h
+ ../include/ED_select_utils.h
+ ../include/ED_sequencer.h
+ ../include/ED_sound.h
+ ../include/ED_space_api.h
+ ../include/ED_text.h
+ ../include/ED_transform.h
+ ../include/ED_transform_snap_object_context.h
+ ../include/ED_transverts.h
+ ../include/ED_types.h
+ ../include/ED_undo.h
+ ../include/ED_util.h
+ ../include/ED_uvedit.h
+ ../include/ED_view3d.h
+ ../include/UI_icons.h
+ ../include/UI_interface.h
+ ../include/UI_interface_icons.h
+ ../include/UI_resources.h
+ ../include/UI_view2d.h
)
set(LIB
@@ -105,14 +105,14 @@ set(LIB
add_definitions(${GL_DEFINITIONS})
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
if(WITH_PYTHON)
- add_definitions(-DWITH_PYTHON)
- list(APPEND INC
- ../../python
- )
+ add_definitions(-DWITH_PYTHON)
+ list(APPEND INC
+ ../../python
+ )
endif()
blender_add_lib(bf_editor_util "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/util/ed_transverts.c b/source/blender/editors/util/ed_transverts.c
index ccd35983551..4cc74bec7d9 100644
--- a/source/blender/editors/util/ed_transverts.c
+++ b/source/blender/editors/util/ed_transverts.c
@@ -45,462 +45,468 @@
#include "ED_armature.h"
-#include "ED_transverts.h" /* own include */
-
+#include "ED_transverts.h" /* own include */
/* copied from editobject.c, now uses (almost) proper depgraph */
void ED_transverts_update_obedit(TransVertStore *tvs, Object *obedit)
{
- const int mode = tvs->mode;
- BLI_assert(ED_transverts_check_obedit(obedit) == true);
-
- DEG_id_tag_update(obedit->data, 0);
-
- if (obedit->type == OB_MESH) {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BM_mesh_normals_update(em->bm);
- }
- else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
- Curve *cu = obedit->data;
- ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- Nurb *nu = nurbs->first;
-
- while (nu) {
- /* keep handles' vectors unchanged */
- if (nu->bezt && (mode & TM_SKIP_HANDLES)) {
- int a = nu->pntsu;
- TransVert *tv = tvs->transverts;
- BezTriple *bezt = nu->bezt;
-
- while (a--) {
- if (bezt->hide == 0) {
- bool skip_handle = false;
- if (bezt->f2 & SELECT)
- skip_handle = (mode & TM_SKIP_HANDLES) != 0;
-
- if ((bezt->f1 & SELECT) && !skip_handle) {
- BLI_assert(tv->loc == bezt->vec[0]);
- tv++;
- }
-
- if (bezt->f2 & SELECT) {
- float v[3];
-
- if (((bezt->f1 & SELECT) && !skip_handle) == 0) {
- sub_v3_v3v3(v, tv->loc, tv->oldloc);
- add_v3_v3(bezt->vec[0], v);
- }
-
- if (((bezt->f3 & SELECT) && !skip_handle) == 0) {
- sub_v3_v3v3(v, tv->loc, tv->oldloc);
- add_v3_v3(bezt->vec[2], v);
- }
-
- BLI_assert(tv->loc == bezt->vec[1]);
- tv++;
- }
-
- if ((bezt->f3 & SELECT) && !skip_handle) {
- BLI_assert(tv->loc == bezt->vec[2]);
- tv++;
- }
- }
-
- bezt++;
- }
- }
-
- BKE_nurb_test_2d(nu);
- BKE_nurb_handles_test(nu, true); /* test for bezier too */
- nu = nu->next;
- }
- }
- else if (obedit->type == OB_ARMATURE) {
- bArmature *arm = obedit->data;
- EditBone *ebo;
- TransVert *tv = tvs->transverts;
- int a = 0;
-
- /* Ensure all bone tails are correctly adjusted */
- for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
- /* adjust tip if both ends selected */
- if ((ebo->flag & BONE_ROOTSEL) && (ebo->flag & BONE_TIPSEL)) {
- if (tv) {
- float diffvec[3];
-
- sub_v3_v3v3(diffvec, tv->loc, tv->oldloc);
- add_v3_v3(ebo->tail, diffvec);
-
- a++;
- if (a < tvs->transverts_tot) tv++;
- }
- }
- }
-
- /* Ensure all bones are correctly adjusted */
- for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
- if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
- /* If this bone has a parent tip that has been moved */
- if (ebo->parent->flag & BONE_TIPSEL) {
- copy_v3_v3(ebo->head, ebo->parent->tail);
- }
- /* If this bone has a parent tip that has NOT been moved */
- else {
- copy_v3_v3(ebo->parent->tail, ebo->head);
- }
- }
- }
- if (arm->flag & ARM_MIRROR_EDIT)
- ED_armature_edit_transform_mirror_update(obedit);
- }
- else if (obedit->type == OB_LATTICE) {
- Lattice *lt = obedit->data;
-
- if (lt->editlatt->latt->flag & LT_OUTSIDE)
- outside_lattice(lt->editlatt->latt);
- }
+ const int mode = tvs->mode;
+ BLI_assert(ED_transverts_check_obedit(obedit) == true);
+
+ DEG_id_tag_update(obedit->data, 0);
+
+ if (obedit->type == OB_MESH) {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BM_mesh_normals_update(em->bm);
+ }
+ else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ Curve *cu = obedit->data;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+ Nurb *nu = nurbs->first;
+
+ while (nu) {
+ /* keep handles' vectors unchanged */
+ if (nu->bezt && (mode & TM_SKIP_HANDLES)) {
+ int a = nu->pntsu;
+ TransVert *tv = tvs->transverts;
+ BezTriple *bezt = nu->bezt;
+
+ while (a--) {
+ if (bezt->hide == 0) {
+ bool skip_handle = false;
+ if (bezt->f2 & SELECT)
+ skip_handle = (mode & TM_SKIP_HANDLES) != 0;
+
+ if ((bezt->f1 & SELECT) && !skip_handle) {
+ BLI_assert(tv->loc == bezt->vec[0]);
+ tv++;
+ }
+
+ if (bezt->f2 & SELECT) {
+ float v[3];
+
+ if (((bezt->f1 & SELECT) && !skip_handle) == 0) {
+ sub_v3_v3v3(v, tv->loc, tv->oldloc);
+ add_v3_v3(bezt->vec[0], v);
+ }
+
+ if (((bezt->f3 & SELECT) && !skip_handle) == 0) {
+ sub_v3_v3v3(v, tv->loc, tv->oldloc);
+ add_v3_v3(bezt->vec[2], v);
+ }
+
+ BLI_assert(tv->loc == bezt->vec[1]);
+ tv++;
+ }
+
+ if ((bezt->f3 & SELECT) && !skip_handle) {
+ BLI_assert(tv->loc == bezt->vec[2]);
+ tv++;
+ }
+ }
+
+ bezt++;
+ }
+ }
+
+ BKE_nurb_test_2d(nu);
+ BKE_nurb_handles_test(nu, true); /* test for bezier too */
+ nu = nu->next;
+ }
+ }
+ else if (obedit->type == OB_ARMATURE) {
+ bArmature *arm = obedit->data;
+ EditBone *ebo;
+ TransVert *tv = tvs->transverts;
+ int a = 0;
+
+ /* Ensure all bone tails are correctly adjusted */
+ for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ /* adjust tip if both ends selected */
+ if ((ebo->flag & BONE_ROOTSEL) && (ebo->flag & BONE_TIPSEL)) {
+ if (tv) {
+ float diffvec[3];
+
+ sub_v3_v3v3(diffvec, tv->loc, tv->oldloc);
+ add_v3_v3(ebo->tail, diffvec);
+
+ a++;
+ if (a < tvs->transverts_tot)
+ tv++;
+ }
+ }
+ }
+
+ /* Ensure all bones are correctly adjusted */
+ for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
+ /* If this bone has a parent tip that has been moved */
+ if (ebo->parent->flag & BONE_TIPSEL) {
+ copy_v3_v3(ebo->head, ebo->parent->tail);
+ }
+ /* If this bone has a parent tip that has NOT been moved */
+ else {
+ copy_v3_v3(ebo->parent->tail, ebo->head);
+ }
+ }
+ }
+ if (arm->flag & ARM_MIRROR_EDIT)
+ ED_armature_edit_transform_mirror_update(obedit);
+ }
+ else if (obedit->type == OB_LATTICE) {
+ Lattice *lt = obedit->data;
+
+ if (lt->editlatt->latt->flag & LT_OUTSIDE)
+ outside_lattice(lt->editlatt->latt);
+ }
}
-static void set_mapped_co(void *vuserdata, int index, const float co[3],
- const float UNUSED(no[3]), const short UNUSED(no_s[3]))
+static void set_mapped_co(void *vuserdata,
+ int index,
+ const float co[3],
+ const float UNUSED(no[3]),
+ const short UNUSED(no_s[3]))
{
- void **userdata = vuserdata;
- BMEditMesh *em = userdata[0];
- TransVert *tv = userdata[1];
- BMVert *eve = BM_vert_at_index(em->bm, index);
-
- if (BM_elem_index_get(eve) != TM_INDEX_SKIP) {
- tv = &tv[BM_elem_index_get(eve)];
-
- /* be clever, get the closest vertex to the original,
- * behaves most logically when the mirror modifier is used for eg [#33051]*/
- if ((tv->flag & TX_VERT_USE_MAPLOC) == 0) {
- /* first time */
- copy_v3_v3(tv->maploc, co);
- tv->flag |= TX_VERT_USE_MAPLOC;
- }
- else {
- /* find best location to use */
- if (len_squared_v3v3(eve->co, co) < len_squared_v3v3(eve->co, tv->maploc)) {
- copy_v3_v3(tv->maploc, co);
- }
- }
- }
+ void **userdata = vuserdata;
+ BMEditMesh *em = userdata[0];
+ TransVert *tv = userdata[1];
+ BMVert *eve = BM_vert_at_index(em->bm, index);
+
+ if (BM_elem_index_get(eve) != TM_INDEX_SKIP) {
+ tv = &tv[BM_elem_index_get(eve)];
+
+ /* be clever, get the closest vertex to the original,
+ * behaves most logically when the mirror modifier is used for eg [#33051]*/
+ if ((tv->flag & TX_VERT_USE_MAPLOC) == 0) {
+ /* first time */
+ copy_v3_v3(tv->maploc, co);
+ tv->flag |= TX_VERT_USE_MAPLOC;
+ }
+ else {
+ /* find best location to use */
+ if (len_squared_v3v3(eve->co, co) < len_squared_v3v3(eve->co, tv->maploc)) {
+ copy_v3_v3(tv->maploc, co);
+ }
+ }
+ }
}
bool ED_transverts_check_obedit(Object *obedit)
{
- return (ELEM(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL));
+ return (ELEM(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL));
}
void ED_transverts_create_from_obedit(TransVertStore *tvs, Object *obedit, const int mode)
{
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- TransVert *tv = NULL;
- MetaElem *ml;
- BMVert *eve;
- EditBone *ebo;
- int a;
-
- tvs->transverts_tot = 0;
-
- if (obedit->type == OB_MESH) {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMIter iter;
- void *userdata[2] = {em, NULL};
- /*int proptrans = 0; */ /*UNUSED*/
-
- /* abuses vertex index all over, set, just set dirty here,
- * perhaps this could use its own array instead? - campbell */
-
- /* transform now requires awareness for select mode, so we tag the f1 flags in verts */
- tvs->transverts_tot = 0;
- if (em->selectmode & SCE_SELECT_VERTEX) {
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- BM_elem_index_set(eve, TM_INDEX_ON); /* set_dirty! */
- tvs->transverts_tot++;
- }
- else {
- BM_elem_index_set(eve, TM_INDEX_OFF); /* set_dirty! */
- }
- }
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- BMEdge *eed;
-
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_index_set(eve, TM_INDEX_OFF); /* set_dirty! */
- }
-
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- BM_elem_index_set(eed->v1, TM_INDEX_ON); /* set_dirty! */
- BM_elem_index_set(eed->v2, TM_INDEX_ON); /* set_dirty! */
- }
- }
-
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_index_get(eve) == TM_INDEX_ON) tvs->transverts_tot++;
- }
- }
- else {
- BMFace *efa;
-
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_index_set(eve, TM_INDEX_OFF); /* set_dirty! */
- }
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- BMIter liter;
- BMLoop *l;
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- BM_elem_index_set(l->v, TM_INDEX_ON); /* set_dirty! */
- }
- }
- }
-
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_index_get(eve) == TM_INDEX_ON) tvs->transverts_tot++;
- }
- }
- /* for any of the 3 loops above which all dirty the indices */
- bm->elem_index_dirty |= BM_VERT;
-
- /* and now make transverts */
- if (tvs->transverts_tot) {
- tv = tvs->transverts = MEM_callocN(tvs->transverts_tot * sizeof(TransVert), __func__);
-
- a = 0;
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_index_get(eve)) {
- BM_elem_index_set(eve, a); /* set_dirty! */
- copy_v3_v3(tv->oldloc, eve->co);
- tv->loc = eve->co;
- tv->flag = (BM_elem_index_get(eve) == TM_INDEX_ON) ? SELECT : 0;
-
- if (mode & TM_CALC_NORMALS) {
- tv->flag |= TX_VERT_USE_NORMAL;
- copy_v3_v3(tv->normal, eve->no);
- }
-
- tv++;
- a++;
- }
- else {
- BM_elem_index_set(eve, TM_INDEX_SKIP); /* set_dirty! */
- }
- }
- /* set dirty already, above */
-
- userdata[1] = tvs->transverts;
- }
-
- if (tvs->transverts && em->mesh_eval_cage) {
- BM_mesh_elem_table_ensure(bm, BM_VERT);
- BKE_mesh_foreach_mapped_vert(em->mesh_eval_cage, set_mapped_co, userdata, MESH_FOREACH_NOP);
- }
- }
- else if (obedit->type == OB_ARMATURE) {
- bArmature *arm = obedit->data;
- int totmalloc = BLI_listbase_count(arm->edbo);
-
- totmalloc *= 2; /* probably overkill but bones can have 2 trans verts each */
-
- tv = tvs->transverts = MEM_callocN(totmalloc * sizeof(TransVert), __func__);
-
- for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
- if (ebo->layer & arm->layer) {
- const bool tipsel = (ebo->flag & BONE_TIPSEL) != 0;
- const bool rootsel = (ebo->flag & BONE_ROOTSEL) != 0;
- const bool rootok = (!(ebo->parent && (ebo->flag & BONE_CONNECTED) && (ebo->parent->flag & BONE_TIPSEL)));
-
- if ((tipsel && rootsel) || (rootsel)) {
- /* Don't add the tip (unless mode & TM_ALL_JOINTS, for getting all joints),
- * otherwise we get zero-length bones as tips will snap to the same
- * location as heads.
- */
- if (rootok) {
- copy_v3_v3(tv->oldloc, ebo->head);
- tv->loc = ebo->head;
- tv->flag = SELECT;
- tv++;
- tvs->transverts_tot++;
- }
-
- if ((mode & TM_ALL_JOINTS) && (tipsel)) {
- copy_v3_v3(tv->oldloc, ebo->tail);
- tv->loc = ebo->tail;
- tv->flag = SELECT;
- tv++;
- tvs->transverts_tot++;
- }
- }
- else if (tipsel) {
- copy_v3_v3(tv->oldloc, ebo->tail);
- tv->loc = ebo->tail;
- tv->flag = SELECT;
- tv++;
- tvs->transverts_tot++;
- }
- }
- }
- }
- else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
- Curve *cu = obedit->data;
- int totmalloc = 0;
- ListBase *nurbs = BKE_curve_editNurbs_get(cu);
-
- for (nu = nurbs->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER)
- totmalloc += 3 * nu->pntsu;
- else
- totmalloc += nu->pntsu * nu->pntsv;
- }
- tv = tvs->transverts = MEM_callocN(totmalloc * sizeof(TransVert), __func__);
-
- nu = nurbs->first;
- while (nu) {
- if (nu->type == CU_BEZIER) {
- a = nu->pntsu;
- bezt = nu->bezt;
- while (a--) {
- if (bezt->hide == 0) {
- bool skip_handle = false;
- if (bezt->f2 & SELECT)
- skip_handle = (mode & TM_SKIP_HANDLES) != 0;
-
- if ((bezt->f1 & SELECT) && !skip_handle) {
- copy_v3_v3(tv->oldloc, bezt->vec[0]);
- tv->loc = bezt->vec[0];
- tv->flag = bezt->f1 & SELECT;
-
- if (mode & TM_CALC_NORMALS) {
- tv->flag |= TX_VERT_USE_NORMAL;
- BKE_nurb_bezt_calc_plane(nu, bezt, tv->normal);
- }
-
- tv++;
- tvs->transverts_tot++;
- }
- if (bezt->f2 & SELECT) {
- copy_v3_v3(tv->oldloc, bezt->vec[1]);
- tv->loc = bezt->vec[1];
- tv->flag = bezt->f2 & SELECT;
-
- if (mode & TM_CALC_NORMALS) {
- tv->flag |= TX_VERT_USE_NORMAL;
- BKE_nurb_bezt_calc_plane(nu, bezt, tv->normal);
- }
-
- tv++;
- tvs->transverts_tot++;
- }
- if ((bezt->f3 & SELECT) && !skip_handle) {
- copy_v3_v3(tv->oldloc, bezt->vec[2]);
- tv->loc = bezt->vec[2];
- tv->flag = bezt->f3 & SELECT;
-
- if (mode & TM_CALC_NORMALS) {
- tv->flag |= TX_VERT_USE_NORMAL;
- BKE_nurb_bezt_calc_plane(nu, bezt, tv->normal);
- }
-
- tv++;
- tvs->transverts_tot++;
- }
- }
- bezt++;
- }
- }
- else {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a--) {
- if (bp->hide == 0) {
- if (bp->f1 & SELECT) {
- copy_v3_v3(tv->oldloc, bp->vec);
- tv->loc = bp->vec;
- tv->flag = bp->f1 & SELECT;
- tv++;
- tvs->transverts_tot++;
- }
- }
- bp++;
- }
- }
- nu = nu->next;
- }
- }
- else if (obedit->type == OB_MBALL) {
- MetaBall *mb = obedit->data;
- int totmalloc = BLI_listbase_count(mb->editelems);
-
- tv = tvs->transverts = MEM_callocN(totmalloc * sizeof(TransVert), __func__);
-
- ml = mb->editelems->first;
- while (ml) {
- if (ml->flag & SELECT) {
- tv->loc = &ml->x;
- copy_v3_v3(tv->oldloc, tv->loc);
- tv->flag = SELECT;
- tv++;
- tvs->transverts_tot++;
- }
- ml = ml->next;
- }
- }
- else if (obedit->type == OB_LATTICE) {
- Lattice *lt = obedit->data;
-
- bp = lt->editlatt->latt->def;
-
- a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
-
- tv = tvs->transverts = MEM_callocN(a * sizeof(TransVert), __func__);
-
- while (a--) {
- if (bp->f1 & SELECT) {
- if (bp->hide == 0) {
- copy_v3_v3(tv->oldloc, bp->vec);
- tv->loc = bp->vec;
- tv->flag = bp->f1 & SELECT;
- tv++;
- tvs->transverts_tot++;
- }
- }
- bp++;
- }
- }
-
- if (!tvs->transverts_tot && tvs->transverts) {
- /* prevent memory leak. happens for curves/latticies due to */
- /* difficult condition of adding points to trans data */
- MEM_freeN(tvs->transverts);
- tvs->transverts = NULL;
- }
-
- tvs->mode = mode;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ TransVert *tv = NULL;
+ MetaElem *ml;
+ BMVert *eve;
+ EditBone *ebo;
+ int a;
+
+ tvs->transverts_tot = 0;
+
+ if (obedit->type == OB_MESH) {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMIter iter;
+ void *userdata[2] = {em, NULL};
+ /*int proptrans = 0; */ /*UNUSED*/
+
+ /* abuses vertex index all over, set, just set dirty here,
+ * perhaps this could use its own array instead? - campbell */
+
+ /* transform now requires awareness for select mode, so we tag the f1 flags in verts */
+ tvs->transverts_tot = 0;
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ BM_elem_index_set(eve, TM_INDEX_ON); /* set_dirty! */
+ tvs->transverts_tot++;
+ }
+ else {
+ BM_elem_index_set(eve, TM_INDEX_OFF); /* set_dirty! */
+ }
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ BMEdge *eed;
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_index_set(eve, TM_INDEX_OFF); /* set_dirty! */
+ }
+
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ BM_elem_index_set(eed->v1, TM_INDEX_ON); /* set_dirty! */
+ BM_elem_index_set(eed->v2, TM_INDEX_ON); /* set_dirty! */
+ }
+ }
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_index_get(eve) == TM_INDEX_ON)
+ tvs->transverts_tot++;
+ }
+ }
+ else {
+ BMFace *efa;
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_index_set(eve, TM_INDEX_OFF); /* set_dirty! */
+ }
+
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ BMIter liter;
+ BMLoop *l;
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ BM_elem_index_set(l->v, TM_INDEX_ON); /* set_dirty! */
+ }
+ }
+ }
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_index_get(eve) == TM_INDEX_ON)
+ tvs->transverts_tot++;
+ }
+ }
+ /* for any of the 3 loops above which all dirty the indices */
+ bm->elem_index_dirty |= BM_VERT;
+
+ /* and now make transverts */
+ if (tvs->transverts_tot) {
+ tv = tvs->transverts = MEM_callocN(tvs->transverts_tot * sizeof(TransVert), __func__);
+
+ a = 0;
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_index_get(eve)) {
+ BM_elem_index_set(eve, a); /* set_dirty! */
+ copy_v3_v3(tv->oldloc, eve->co);
+ tv->loc = eve->co;
+ tv->flag = (BM_elem_index_get(eve) == TM_INDEX_ON) ? SELECT : 0;
+
+ if (mode & TM_CALC_NORMALS) {
+ tv->flag |= TX_VERT_USE_NORMAL;
+ copy_v3_v3(tv->normal, eve->no);
+ }
+
+ tv++;
+ a++;
+ }
+ else {
+ BM_elem_index_set(eve, TM_INDEX_SKIP); /* set_dirty! */
+ }
+ }
+ /* set dirty already, above */
+
+ userdata[1] = tvs->transverts;
+ }
+
+ if (tvs->transverts && em->mesh_eval_cage) {
+ BM_mesh_elem_table_ensure(bm, BM_VERT);
+ BKE_mesh_foreach_mapped_vert(em->mesh_eval_cage, set_mapped_co, userdata, MESH_FOREACH_NOP);
+ }
+ }
+ else if (obedit->type == OB_ARMATURE) {
+ bArmature *arm = obedit->data;
+ int totmalloc = BLI_listbase_count(arm->edbo);
+
+ totmalloc *= 2; /* probably overkill but bones can have 2 trans verts each */
+
+ tv = tvs->transverts = MEM_callocN(totmalloc * sizeof(TransVert), __func__);
+
+ for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ if (ebo->layer & arm->layer) {
+ const bool tipsel = (ebo->flag & BONE_TIPSEL) != 0;
+ const bool rootsel = (ebo->flag & BONE_ROOTSEL) != 0;
+ const bool rootok = (!(ebo->parent && (ebo->flag & BONE_CONNECTED) &&
+ (ebo->parent->flag & BONE_TIPSEL)));
+
+ if ((tipsel && rootsel) || (rootsel)) {
+ /* Don't add the tip (unless mode & TM_ALL_JOINTS, for getting all joints),
+ * otherwise we get zero-length bones as tips will snap to the same
+ * location as heads.
+ */
+ if (rootok) {
+ copy_v3_v3(tv->oldloc, ebo->head);
+ tv->loc = ebo->head;
+ tv->flag = SELECT;
+ tv++;
+ tvs->transverts_tot++;
+ }
+
+ if ((mode & TM_ALL_JOINTS) && (tipsel)) {
+ copy_v3_v3(tv->oldloc, ebo->tail);
+ tv->loc = ebo->tail;
+ tv->flag = SELECT;
+ tv++;
+ tvs->transverts_tot++;
+ }
+ }
+ else if (tipsel) {
+ copy_v3_v3(tv->oldloc, ebo->tail);
+ tv->loc = ebo->tail;
+ tv->flag = SELECT;
+ tv++;
+ tvs->transverts_tot++;
+ }
+ }
+ }
+ }
+ else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ Curve *cu = obedit->data;
+ int totmalloc = 0;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+
+ for (nu = nurbs->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER)
+ totmalloc += 3 * nu->pntsu;
+ else
+ totmalloc += nu->pntsu * nu->pntsv;
+ }
+ tv = tvs->transverts = MEM_callocN(totmalloc * sizeof(TransVert), __func__);
+
+ nu = nurbs->first;
+ while (nu) {
+ if (nu->type == CU_BEZIER) {
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ while (a--) {
+ if (bezt->hide == 0) {
+ bool skip_handle = false;
+ if (bezt->f2 & SELECT)
+ skip_handle = (mode & TM_SKIP_HANDLES) != 0;
+
+ if ((bezt->f1 & SELECT) && !skip_handle) {
+ copy_v3_v3(tv->oldloc, bezt->vec[0]);
+ tv->loc = bezt->vec[0];
+ tv->flag = bezt->f1 & SELECT;
+
+ if (mode & TM_CALC_NORMALS) {
+ tv->flag |= TX_VERT_USE_NORMAL;
+ BKE_nurb_bezt_calc_plane(nu, bezt, tv->normal);
+ }
+
+ tv++;
+ tvs->transverts_tot++;
+ }
+ if (bezt->f2 & SELECT) {
+ copy_v3_v3(tv->oldloc, bezt->vec[1]);
+ tv->loc = bezt->vec[1];
+ tv->flag = bezt->f2 & SELECT;
+
+ if (mode & TM_CALC_NORMALS) {
+ tv->flag |= TX_VERT_USE_NORMAL;
+ BKE_nurb_bezt_calc_plane(nu, bezt, tv->normal);
+ }
+
+ tv++;
+ tvs->transverts_tot++;
+ }
+ if ((bezt->f3 & SELECT) && !skip_handle) {
+ copy_v3_v3(tv->oldloc, bezt->vec[2]);
+ tv->loc = bezt->vec[2];
+ tv->flag = bezt->f3 & SELECT;
+
+ if (mode & TM_CALC_NORMALS) {
+ tv->flag |= TX_VERT_USE_NORMAL;
+ BKE_nurb_bezt_calc_plane(nu, bezt, tv->normal);
+ }
+
+ tv++;
+ tvs->transverts_tot++;
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a--) {
+ if (bp->hide == 0) {
+ if (bp->f1 & SELECT) {
+ copy_v3_v3(tv->oldloc, bp->vec);
+ tv->loc = bp->vec;
+ tv->flag = bp->f1 & SELECT;
+ tv++;
+ tvs->transverts_tot++;
+ }
+ }
+ bp++;
+ }
+ }
+ nu = nu->next;
+ }
+ }
+ else if (obedit->type == OB_MBALL) {
+ MetaBall *mb = obedit->data;
+ int totmalloc = BLI_listbase_count(mb->editelems);
+
+ tv = tvs->transverts = MEM_callocN(totmalloc * sizeof(TransVert), __func__);
+
+ ml = mb->editelems->first;
+ while (ml) {
+ if (ml->flag & SELECT) {
+ tv->loc = &ml->x;
+ copy_v3_v3(tv->oldloc, tv->loc);
+ tv->flag = SELECT;
+ tv++;
+ tvs->transverts_tot++;
+ }
+ ml = ml->next;
+ }
+ }
+ else if (obedit->type == OB_LATTICE) {
+ Lattice *lt = obedit->data;
+
+ bp = lt->editlatt->latt->def;
+
+ a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
+
+ tv = tvs->transverts = MEM_callocN(a * sizeof(TransVert), __func__);
+
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ if (bp->hide == 0) {
+ copy_v3_v3(tv->oldloc, bp->vec);
+ tv->loc = bp->vec;
+ tv->flag = bp->f1 & SELECT;
+ tv++;
+ tvs->transverts_tot++;
+ }
+ }
+ bp++;
+ }
+ }
+
+ if (!tvs->transverts_tot && tvs->transverts) {
+ /* prevent memory leak. happens for curves/latticies due to */
+ /* difficult condition of adding points to trans data */
+ MEM_freeN(tvs->transverts);
+ tvs->transverts = NULL;
+ }
+
+ tvs->mode = mode;
}
void ED_transverts_free(TransVertStore *tvs)
{
- MEM_SAFE_FREE(tvs->transverts);
- tvs->transverts_tot = 0;
+ MEM_SAFE_FREE(tvs->transverts);
+ tvs->transverts_tot = 0;
}
bool ED_transverts_poll(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit) {
- if (ED_transverts_check_obedit(obedit)) {
- return true;
- }
- }
- return false;
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit) {
+ if (ED_transverts_check_obedit(obedit)) {
+ return true;
+ }
+ }
+ return false;
}
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index e2405591141..503910d1734 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -75,310 +75,311 @@
#include "WM_api.h"
#include "RNA_access.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) {
- ViewLayer *view_layer = WM_window_get_active_view_layer(win);
- Base *base = BASACT(view_layer);
- if (base != NULL) {
- Object *ob = base->object;
- if (ob->mode & OB_MODE_TEXTURE_PAINT) {
- Scene *scene = WM_window_get_active_scene(win);
-
- BKE_texpaint_slots_refresh_object(scene, ob);
- BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
- }
- }
- }
+ wmWindowManager *wm = bmain->wm.first;
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ ViewLayer *view_layer = WM_window_get_active_view_layer(win);
+ Base *base = BASACT(view_layer);
+ if (base != NULL) {
+ Object *ob = base->object;
+ if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ Scene *scene = WM_window_get_active_scene(win);
+
+ BKE_texpaint_slots_refresh_object(scene, ob);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ }
+ }
+ }
}
void ED_editors_init(bContext *C)
{
- struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- wmWindowManager *wm = CTX_wm_manager(C);
-
- /* This is called during initialization, so we don't want to store any reports */
- ReportList *reports = CTX_wm_reports(C);
- int reports_flag_prev = reports->flag & ~RPT_STORE;
-
- SWAP(int, reports->flag, reports_flag_prev);
-
- /* Don't do undo pushes when calling an operator. */
- wm->op_undo_depth++;
-
- /* toggle on modes for objects that were saved with these enabled. for
- * e.g. linked objects we have to ensure that they are actually the
- * active object in this scene. */
- Object *obact = CTX_data_active_object(C);
- if (obact != NULL) {
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- int mode = ob->mode;
- if (mode == OB_MODE_OBJECT) {
- continue;
- }
- else if (BKE_object_has_mode_data(ob, mode)) {
- continue;
- }
- else if (ob->type == OB_GPENCIL) {
- /* For multi-edit mode we may already have mode data.
- * (grease pencil does not need it) */
- continue;
- }
-
- ID *ob_data = ob->data;
- ob->mode = OB_MODE_OBJECT;
- if ((ob->type == obact->type) &&
- !ID_IS_LINKED(ob) &&
- !(ob_data && ID_IS_LINKED(ob_data)))
- {
- if (mode == OB_MODE_EDIT) {
- ED_object_editmode_enter_ex(bmain, scene, ob, 0);
- }
- else if (mode == OB_MODE_POSE) {
- ED_object_posemode_enter_ex(bmain, ob);
- }
- else if (mode & OB_MODE_ALL_SCULPT) {
- if (obact == ob) {
- if (mode == OB_MODE_SCULPT) {
- ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, true, reports);
- }
- else if (mode == OB_MODE_VERTEX_PAINT) {
- ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
- }
- else if (mode == OB_MODE_WEIGHT_PAINT) {
- ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
- }
- else {
- BLI_assert(0);
- }
- }
- else {
- /* Create data for non-active objects which need it for
- * mode-switching but don't yet support multi-editing. */
- if (mode & OB_MODE_ALL_SCULPT) {
- ob->mode = mode;
- BKE_object_sculpt_data_create(ob);
- }
- }
- }
- else {
- /* TODO(campbell): avoid operator calls. */
- if (obact == ob) {
- ED_object_mode_toggle(C, mode);
- }
- }
- }
- }
- }
-
-
- /* image editor paint mode */
- if (scene) {
- ED_space_image_paint_update(bmain, wm, scene);
- }
-
- SWAP(int, reports->flag, reports_flag_prev);
- wm->op_undo_depth--;
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+
+ /* This is called during initialization, so we don't want to store any reports */
+ ReportList *reports = CTX_wm_reports(C);
+ int reports_flag_prev = reports->flag & ~RPT_STORE;
+
+ SWAP(int, reports->flag, reports_flag_prev);
+
+ /* Don't do undo pushes when calling an operator. */
+ wm->op_undo_depth++;
+
+ /* toggle on modes for objects that were saved with these enabled. for
+ * e.g. linked objects we have to ensure that they are actually the
+ * active object in this scene. */
+ Object *obact = CTX_data_active_object(C);
+ if (obact != NULL) {
+ for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
+ int mode = ob->mode;
+ if (mode == OB_MODE_OBJECT) {
+ continue;
+ }
+ else if (BKE_object_has_mode_data(ob, mode)) {
+ continue;
+ }
+ else if (ob->type == OB_GPENCIL) {
+ /* For multi-edit mode we may already have mode data.
+ * (grease pencil does not need it) */
+ continue;
+ }
+
+ ID *ob_data = ob->data;
+ ob->mode = OB_MODE_OBJECT;
+ if ((ob->type == obact->type) && !ID_IS_LINKED(ob) && !(ob_data && ID_IS_LINKED(ob_data))) {
+ if (mode == OB_MODE_EDIT) {
+ ED_object_editmode_enter_ex(bmain, scene, ob, 0);
+ }
+ else if (mode == OB_MODE_POSE) {
+ ED_object_posemode_enter_ex(bmain, ob);
+ }
+ else if (mode & OB_MODE_ALL_SCULPT) {
+ if (obact == ob) {
+ if (mode == OB_MODE_SCULPT) {
+ ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, true, reports);
+ }
+ else if (mode == OB_MODE_VERTEX_PAINT) {
+ ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
+ }
+ else if (mode == OB_MODE_WEIGHT_PAINT) {
+ ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ /* Create data for non-active objects which need it for
+ * mode-switching but don't yet support multi-editing. */
+ if (mode & OB_MODE_ALL_SCULPT) {
+ ob->mode = mode;
+ BKE_object_sculpt_data_create(ob);
+ }
+ }
+ }
+ else {
+ /* TODO(campbell): avoid operator calls. */
+ if (obact == ob) {
+ ED_object_mode_toggle(C, mode);
+ }
+ }
+ }
+ }
+ }
+
+ /* image editor paint mode */
+ if (scene) {
+ ED_space_image_paint_update(bmain, wm, scene);
+ }
+
+ SWAP(int, reports->flag, reports_flag_prev);
+ wm->op_undo_depth--;
}
/* frees all editmode stuff */
void ED_editors_exit(Main *bmain, bool do_undo_system)
{
- if (!bmain) {
- return;
- }
-
- /* frees all editmode undos */
- if (do_undo_system && G_MAIN->wm.first) {
- wmWindowManager *wm = G_MAIN->wm.first;
- /* normally we don't check for NULL undo stack,
- * do here since it may run in different context. */
- if (wm->undo_stack) {
- BKE_undosys_stack_destroy(wm->undo_stack);
- wm->undo_stack = NULL;
- }
- }
-
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
- if (me->edit_mesh) {
- EDBM_mesh_free(me->edit_mesh);
- MEM_freeN(me->edit_mesh);
- me->edit_mesh = NULL;
- }
- }
- else if (ob->type == OB_ARMATURE) {
- bArmature *arm = ob->data;
- if (arm->edbo) {
- ED_armature_edit_free(ob->data);
- }
- }
- }
-
- /* global in meshtools... */
- ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
- ED_mesh_mirror_topo_table(NULL, NULL, 'e');
+ if (!bmain) {
+ return;
+ }
+
+ /* frees all editmode undos */
+ if (do_undo_system && G_MAIN->wm.first) {
+ wmWindowManager *wm = G_MAIN->wm.first;
+ /* normally we don't check for NULL undo stack,
+ * do here since it may run in different context. */
+ if (wm->undo_stack) {
+ BKE_undosys_stack_destroy(wm->undo_stack);
+ wm->undo_stack = NULL;
+ }
+ }
+
+ for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ if (me->edit_mesh) {
+ EDBM_mesh_free(me->edit_mesh);
+ MEM_freeN(me->edit_mesh);
+ me->edit_mesh = NULL;
+ }
+ }
+ else if (ob->type == OB_ARMATURE) {
+ bArmature *arm = ob->data;
+ if (arm->edbo) {
+ ED_armature_edit_free(ob->data);
+ }
+ }
+ }
+
+ /* global in meshtools... */
+ ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
+ ED_mesh_mirror_topo_table(NULL, NULL, 'e');
}
/* flush any temp data from object editing to DNA before writing files,
* rendering, copying, etc. */
bool ED_editors_flush_edits(Main *bmain, bool for_render)
{
- bool has_edited = false;
- Object *ob;
-
- /* loop through all data to find edit mode or object mode, because during
- * exiting we might not have a context for edit object and multiple sculpt
- * objects can exist at the same time */
- for (ob = bmain->objects.first; ob; ob = ob->id.next) {
- if (ob->mode & OB_MODE_SCULPT) {
- /* 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) {
- /* flush multires changes (for sculpt) */
- multires_force_update(ob);
- has_edited = true;
-
- if (for_render) {
- /* flush changes from dynamic topology sculpt */
- BKE_sculptsession_bm_to_me_for_render(ob);
- }
- else {
- /* Set reorder=false so that saving the file doesn't reorder
- * the BMesh's elements */
- BKE_sculptsession_bm_to_me(ob, false);
- }
- }
- }
- else if (ob->mode & OB_MODE_EDIT) {
- /* get editmode results */
- has_edited = true;
- ED_object_editmode_load(bmain, ob);
- }
- }
-
- return has_edited;
+ bool has_edited = false;
+ Object *ob;
+
+ /* loop through all data to find edit mode or object mode, because during
+ * exiting we might not have a context for edit object and multiple sculpt
+ * objects can exist at the same time */
+ for (ob = bmain->objects.first; ob; ob = ob->id.next) {
+ if (ob->mode & OB_MODE_SCULPT) {
+ /* 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) {
+ /* flush multires changes (for sculpt) */
+ multires_force_update(ob);
+ has_edited = true;
+
+ if (for_render) {
+ /* flush changes from dynamic topology sculpt */
+ BKE_sculptsession_bm_to_me_for_render(ob);
+ }
+ else {
+ /* Set reorder=false so that saving the file doesn't reorder
+ * the BMesh's elements */
+ BKE_sculptsession_bm_to_me(ob, false);
+ }
+ }
+ }
+ else if (ob->mode & OB_MODE_EDIT) {
+ /* get editmode results */
+ has_edited = true;
+ ED_object_editmode_load(bmain, ob);
+ }
+ }
+
+ return has_edited;
}
/* ***** XXX: functions are using old blender names, cleanup later ***** */
-
/* now only used in 2d spaces, like time, ipo, nla, sima... */
/* XXX shift/ctrl not configurable */
-void apply_keyb_grid(int shift, int ctrl, float *val, float fac1, float fac2, float fac3, int invert)
+void apply_keyb_grid(
+ int shift, int ctrl, float *val, float fac1, float fac2, float fac3, int invert)
{
- /* fac1 is for 'nothing', fac2 for CTRL, fac3 for SHIFT */
- if (invert)
- ctrl = !ctrl;
-
- if (ctrl && shift) {
- if (fac3 != 0.0f) *val = fac3 * floorf(*val / fac3 + 0.5f);
- }
- else if (ctrl) {
- if (fac2 != 0.0f) *val = fac2 * floorf(*val / fac2 + 0.5f);
- }
- else {
- if (fac1 != 0.0f) *val = fac1 * floorf(*val / fac1 + 0.5f);
- }
+ /* fac1 is for 'nothing', fac2 for CTRL, fac3 for SHIFT */
+ if (invert)
+ ctrl = !ctrl;
+
+ if (ctrl && shift) {
+ if (fac3 != 0.0f)
+ *val = fac3 * floorf(*val / fac3 + 0.5f);
+ }
+ else if (ctrl) {
+ if (fac2 != 0.0f)
+ *val = fac2 * floorf(*val / fac2 + 0.5f);
+ }
+ else {
+ if (fac1 != 0.0f)
+ *val = fac1 * floorf(*val / fac1 + 0.5f);
+ }
}
-void unpack_menu(bContext *C, const char *opname, const char *id_name, const char *abs_name, const char *folder, struct PackedFile *pf)
+void unpack_menu(bContext *C,
+ const char *opname,
+ const char *id_name,
+ const char *abs_name,
+ const char *folder,
+ struct PackedFile *pf)
{
- Main *bmain = CTX_data_main(C);
- PointerRNA props_ptr;
- uiPopupMenu *pup;
- uiLayout *layout;
- char line[FILE_MAX + 100];
- wmOperatorType *ot = WM_operatortype_find(opname, 1);
-
- pup = UI_popup_menu_begin(C, IFACE_("Unpack File"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
-
- uiItemFullO_ptr(
- layout, ot, IFACE_("Remove Pack"), ICON_NONE,
- NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
- RNA_enum_set(&props_ptr, "method", PF_REMOVE);
- RNA_string_set(&props_ptr, "id", id_name);
-
- if (G.relbase_valid) {
- char local_name[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX];
-
- BLI_split_file_part(abs_name, fi, sizeof(fi));
- BLI_snprintf(local_name, sizeof(local_name), "//%s/%s", folder, fi);
- if (!STREQ(abs_name, local_name)) {
- switch (checkPackedFile(BKE_main_blendfile_path(bmain), local_name, pf)) {
- case PF_NOFILE:
- BLI_snprintf(line, sizeof(line), IFACE_("Create %s"), local_name);
- uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
- RNA_enum_set(&props_ptr, "method", PF_WRITE_LOCAL);
- RNA_string_set(&props_ptr, "id", id_name);
-
- break;
- case PF_EQUAL:
- BLI_snprintf(line, sizeof(line), IFACE_("Use %s (identical)"), local_name);
- //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_LOCAL);
- uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
- RNA_enum_set(&props_ptr, "method", PF_USE_LOCAL);
- RNA_string_set(&props_ptr, "id", id_name);
-
- break;
- case PF_DIFFERS:
- BLI_snprintf(line, sizeof(line), IFACE_("Use %s (differs)"), local_name);
- //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_LOCAL);
- uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
- RNA_enum_set(&props_ptr, "method", PF_USE_LOCAL);
- RNA_string_set(&props_ptr, "id", id_name);
-
- BLI_snprintf(line, sizeof(line), IFACE_("Overwrite %s"), local_name);
- //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_WRITE_LOCAL);
- uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
- RNA_enum_set(&props_ptr, "method", PF_WRITE_LOCAL);
- RNA_string_set(&props_ptr, "id", id_name);
- break;
- }
- }
- }
-
- switch (checkPackedFile(BKE_main_blendfile_path(bmain), abs_name, pf)) {
- case PF_NOFILE:
- BLI_snprintf(line, sizeof(line), IFACE_("Create %s"), abs_name);
- //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_WRITE_ORIGINAL);
- uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
- RNA_enum_set(&props_ptr, "method", PF_WRITE_ORIGINAL);
- RNA_string_set(&props_ptr, "id", id_name);
- break;
- case PF_EQUAL:
- BLI_snprintf(line, sizeof(line), IFACE_("Use %s (identical)"), abs_name);
- //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_ORIGINAL);
- uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
- RNA_enum_set(&props_ptr, "method", PF_USE_ORIGINAL);
- RNA_string_set(&props_ptr, "id", id_name);
- break;
- case PF_DIFFERS:
- BLI_snprintf(line, sizeof(line), IFACE_("Use %s (differs)"), abs_name);
- //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_ORIGINAL);
- uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
- RNA_enum_set(&props_ptr, "method", PF_USE_ORIGINAL);
- RNA_string_set(&props_ptr, "id", id_name);
-
- BLI_snprintf(line, sizeof(line), IFACE_("Overwrite %s"), abs_name);
- //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_WRITE_ORIGINAL);
- uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
- RNA_enum_set(&props_ptr, "method", PF_WRITE_ORIGINAL);
- RNA_string_set(&props_ptr, "id", id_name);
- break;
- }
-
- UI_popup_menu_end(C, pup);
+ Main *bmain = CTX_data_main(C);
+ PointerRNA props_ptr;
+ uiPopupMenu *pup;
+ uiLayout *layout;
+ char line[FILE_MAX + 100];
+ wmOperatorType *ot = WM_operatortype_find(opname, 1);
+
+ pup = UI_popup_menu_begin(C, IFACE_("Unpack File"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+
+ uiItemFullO_ptr(
+ layout, ot, IFACE_("Remove Pack"), ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
+ RNA_enum_set(&props_ptr, "method", PF_REMOVE);
+ RNA_string_set(&props_ptr, "id", id_name);
+
+ if (G.relbase_valid) {
+ char local_name[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX];
+
+ BLI_split_file_part(abs_name, fi, sizeof(fi));
+ BLI_snprintf(local_name, sizeof(local_name), "//%s/%s", folder, fi);
+ if (!STREQ(abs_name, local_name)) {
+ switch (checkPackedFile(BKE_main_blendfile_path(bmain), local_name, pf)) {
+ case PF_NOFILE:
+ BLI_snprintf(line, sizeof(line), IFACE_("Create %s"), local_name);
+ uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
+ RNA_enum_set(&props_ptr, "method", PF_WRITE_LOCAL);
+ RNA_string_set(&props_ptr, "id", id_name);
+
+ break;
+ case PF_EQUAL:
+ BLI_snprintf(line, sizeof(line), IFACE_("Use %s (identical)"), local_name);
+ //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_LOCAL);
+ uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
+ RNA_enum_set(&props_ptr, "method", PF_USE_LOCAL);
+ RNA_string_set(&props_ptr, "id", id_name);
+
+ break;
+ case PF_DIFFERS:
+ BLI_snprintf(line, sizeof(line), IFACE_("Use %s (differs)"), local_name);
+ //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_LOCAL);
+ uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
+ RNA_enum_set(&props_ptr, "method", PF_USE_LOCAL);
+ RNA_string_set(&props_ptr, "id", id_name);
+
+ BLI_snprintf(line, sizeof(line), IFACE_("Overwrite %s"), local_name);
+ //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_WRITE_LOCAL);
+ uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
+ RNA_enum_set(&props_ptr, "method", PF_WRITE_LOCAL);
+ RNA_string_set(&props_ptr, "id", id_name);
+ break;
+ }
+ }
+ }
+
+ switch (checkPackedFile(BKE_main_blendfile_path(bmain), abs_name, pf)) {
+ case PF_NOFILE:
+ BLI_snprintf(line, sizeof(line), IFACE_("Create %s"), abs_name);
+ //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_WRITE_ORIGINAL);
+ uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
+ RNA_enum_set(&props_ptr, "method", PF_WRITE_ORIGINAL);
+ RNA_string_set(&props_ptr, "id", id_name);
+ break;
+ case PF_EQUAL:
+ BLI_snprintf(line, sizeof(line), IFACE_("Use %s (identical)"), abs_name);
+ //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_ORIGINAL);
+ uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
+ RNA_enum_set(&props_ptr, "method", PF_USE_ORIGINAL);
+ RNA_string_set(&props_ptr, "id", id_name);
+ break;
+ case PF_DIFFERS:
+ BLI_snprintf(line, sizeof(line), IFACE_("Use %s (differs)"), abs_name);
+ //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_ORIGINAL);
+ uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
+ RNA_enum_set(&props_ptr, "method", PF_USE_ORIGINAL);
+ RNA_string_set(&props_ptr, "id", id_name);
+
+ BLI_snprintf(line, sizeof(line), IFACE_("Overwrite %s"), abs_name);
+ //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_WRITE_ORIGINAL);
+ uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
+ RNA_enum_set(&props_ptr, "method", PF_WRITE_ORIGINAL);
+ RNA_string_set(&props_ptr, "id", id_name);
+ break;
+ }
+
+ UI_popup_menu_end(C, pup);
}
/* ********************* generic callbacks for drawcall api *********************** */
@@ -388,32 +389,33 @@ void unpack_menu(bContext *C, const char *opname, const char *id_name, const cha
*/
void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, 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};
+ 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};
- const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- GPU_line_width(1.0f);
+ GPU_line_width(1.0f);
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
- immUniform1i("colors_len", 0); /* "simple" mode */
- immUniformThemeColor(TH_VIEW_OVERLAY);
- immUniform1f("dash_width", 6.0f);
- immUniform1f("dash_factor", 0.5f);
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniformThemeColor(TH_VIEW_OVERLAY);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2fv(shdr_pos, mval_src);
- immVertex2fv(shdr_pos, mval_dst);
- immEnd();
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2fv(shdr_pos, mval_src);
+ immVertex2fv(shdr_pos, mval_dst);
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
}
/**
@@ -423,30 +425,30 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info
*/
void ED_spacedata_id_remap(struct ScrArea *sa, struct SpaceLink *sl, ID *old_id, ID *new_id)
{
- SpaceType *st = BKE_spacetype_from_id(sl->spacetype);
+ SpaceType *st = BKE_spacetype_from_id(sl->spacetype);
- if (st && st->id_remap) {
- st->id_remap(sa, sl, old_id, new_id);
- }
+ if (st && st->id_remap) {
+ st->id_remap(sa, sl, old_id, new_id);
+ }
}
static int ed_flush_edits_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- ED_editors_flush_edits(bmain, false);
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ ED_editors_flush_edits(bmain, false);
+ return OPERATOR_FINISHED;
}
void ED_OT_flush_edits(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Flush Edits";
- ot->description = "Flush edit data from active editing modes";
- ot->idname = "ED_OT_flush_edits";
+ /* identifiers */
+ ot->name = "Flush Edits";
+ ot->description = "Flush edit data from active editing modes";
+ ot->idname = "ED_OT_flush_edits";
- /* api callbacks */
- ot->exec = ed_flush_edits_exec;
+ /* api callbacks */
+ ot->exec = ed_flush_edits_exec;
- /* flags */
- ot->flag = OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_INTERNAL;
}
diff --git a/source/blender/editors/util/gizmo_utils.c b/source/blender/editors/util/gizmo_utils.c
index 002425b11b6..d330019c816 100644
--- a/source/blender/editors/util/gizmo_utils.c
+++ b/source/blender/editors/util/gizmo_utils.c
@@ -34,39 +34,39 @@
#include "ED_gizmo_utils.h"
-bool ED_gizmo_poll_or_unlink_delayed_from_operator(
- const bContext *C, wmGizmoGroupType *gzgt,
- const char *idname)
+bool ED_gizmo_poll_or_unlink_delayed_from_operator(const bContext *C,
+ wmGizmoGroupType *gzgt,
+ const char *idname)
{
#if 0
- /* Causes selection to continue showing the last gizmo. */
- wmOperator *op = WM_operator_last_redo(C);
+ /* Causes selection to continue showing the last gizmo. */
+ wmOperator *op = WM_operator_last_redo(C);
#else
- wmWindowManager *wm = CTX_wm_manager(C);
- wmOperator *op = wm->operators.last;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmOperator *op = wm->operators.last;
#endif
- if (op == NULL || !STREQ(op->type->idname, idname)) {
- WM_gizmo_group_type_unlink_delayed_ptr(gzgt);
- return false;
- }
- return true;
+ if (op == NULL || !STREQ(op->type->idname, idname)) {
+ WM_gizmo_group_type_unlink_delayed_ptr(gzgt);
+ return false;
+ }
+ return true;
}
-bool ED_gizmo_poll_or_unlink_delayed_from_tool_ex(const bContext *C, wmGizmoGroupType *gzgt, const char *gzgt_idname)
+bool ED_gizmo_poll_or_unlink_delayed_from_tool_ex(const bContext *C,
+ wmGizmoGroupType *gzgt,
+ const char *gzgt_idname)
{
- bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
- if ((tref_rt == NULL) ||
- !STREQ(gzgt_idname, tref_rt->gizmo_group))
- {
- WM_gizmo_group_type_unlink_delayed_ptr(gzgt);
- return false;
- }
- return true;
+ bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
+ if ((tref_rt == NULL) || !STREQ(gzgt_idname, tref_rt->gizmo_group)) {
+ WM_gizmo_group_type_unlink_delayed_ptr(gzgt);
+ return false;
+ }
+ return true;
}
/** Can use this as poll function directly. */
bool ED_gizmo_poll_or_unlink_delayed_from_tool(const bContext *C, wmGizmoGroupType *gzgt)
{
- return ED_gizmo_poll_or_unlink_delayed_from_tool_ex(C, gzgt, gzgt->idname);
+ return ED_gizmo_poll_or_unlink_delayed_from_tool_ex(C, gzgt, gzgt->idname);
}
diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c
index aeb764f9960..0ab37d61ce4 100644
--- a/source/blender/editors/util/numinput.c
+++ b/source/blender/editors/util/numinput.c
@@ -36,7 +36,7 @@
#include "WM_types.h"
#ifdef WITH_PYTHON
-#include "BPY_extern.h"
+# include "BPY_extern.h"
#endif
#include "ED_numinput.h"
@@ -49,26 +49,26 @@
* (1 << 8) and below are reserved for public flags!
*/
enum {
- /** Enable full editing, with units and math operators support. */
- NUM_EDIT_FULL = (1 << 9),
+ /** Enable full editing, with units and math operators support. */
+ NUM_EDIT_FULL = (1 << 9),
#ifdef USE_FAKE_EDIT
- /** Fake edited state (temp, avoids issue with backspace). */
- NUM_FAKE_EDITED = (1 << 10),
+ /** Fake edited state (temp, avoids issue with backspace). */
+ NUM_FAKE_EDITED = (1 << 10),
#endif
};
/* NumInput.val_flag[] */
enum {
- /* (1 << 8) and below are reserved for public flags! */
- /** User has edited this value somehow. */
- NUM_EDITED = (1 << 9),
- /** Current expression for this value is invalid. */
- NUM_INVALID = (1 << 10),
+ /* (1 << 8) and below are reserved for public flags! */
+ /** User has edited this value somehow. */
+ NUM_EDITED = (1 << 9),
+ /** Current expression for this value is invalid. */
+ NUM_INVALID = (1 << 10),
#ifdef USE_FAKE_EDIT
- /** Current expression's result has to be negated. */
- NUM_NEGATE = (1 << 11),
- /** Current expression's result has to be inverted. */
- NUM_INVERSE = (1 << 12),
+ /** Current expression's result has to be negated. */
+ NUM_NEGATE = (1 << 11),
+ /** Current expression's result has to be inverted. */
+ NUM_INVERSE = (1 << 12),
#endif
};
@@ -78,108 +78,123 @@ enum {
void initNumInput(NumInput *n)
{
- n->idx_max = 0;
- n->unit_sys = USER_UNIT_NONE;
- copy_vn_i(n->unit_type, NUM_MAX_ELEMENTS, B_UNIT_NONE);
- n->unit_use_radians = false;
-
- n->flag = 0;
- copy_vn_short(n->val_flag, NUM_MAX_ELEMENTS, 0);
- zero_v3(n->val);
- copy_vn_fl(n->val_org, NUM_MAX_ELEMENTS, 0.0f);
- copy_vn_fl(n->val_inc, NUM_MAX_ELEMENTS, 1.0f);
-
- n->idx = 0;
- n->str[0] = '\0';
- n->str_cur = 0;
+ n->idx_max = 0;
+ n->unit_sys = USER_UNIT_NONE;
+ copy_vn_i(n->unit_type, NUM_MAX_ELEMENTS, B_UNIT_NONE);
+ n->unit_use_radians = false;
+
+ n->flag = 0;
+ copy_vn_short(n->val_flag, NUM_MAX_ELEMENTS, 0);
+ zero_v3(n->val);
+ copy_vn_fl(n->val_org, NUM_MAX_ELEMENTS, 0.0f);
+ copy_vn_fl(n->val_inc, NUM_MAX_ELEMENTS, 1.0f);
+
+ n->idx = 0;
+ n->str[0] = '\0';
+ n->str_cur = 0;
}
/* str must be NUM_STR_REP_LEN * (idx_max + 1) length. */
void outputNumInput(NumInput *n, char *str, UnitSettings *unit_settings)
{
- short j;
- const int ln = NUM_STR_REP_LEN;
- int prec = 2; /* draw-only, and avoids too much issues with radian->degrees conversion. */
-
- for (j = 0; j <= n->idx_max; j++) {
- /* if AFFECTALL and no number typed and cursor not on number, use first number */
- const short i = (n->flag & NUM_AFFECT_ALL && n->idx != j && !(n->val_flag[j] & NUM_EDITED)) ? 0 : j;
-
- /* Use scale_length if needed! */
- const float fac = (float)BKE_scene_unit_scale(unit_settings, n->unit_type[j], 1.0);
-
- if (n->val_flag[i] & NUM_EDITED) {
- /* Get the best precision, allows us to draw '10.0001' as '10' instead! */
- prec = UI_calc_float_precision(prec, (double)n->val[i]);
- if (i == n->idx) {
- const char *heading_exp = "", *trailing_exp = "";
- char before_cursor[NUM_STR_REP_LEN];
- char val[16];
+ short j;
+ const int ln = NUM_STR_REP_LEN;
+ int prec = 2; /* draw-only, and avoids too much issues with radian->degrees conversion. */
+
+ for (j = 0; j <= n->idx_max; j++) {
+ /* if AFFECTALL and no number typed and cursor not on number, use first number */
+ const short i = (n->flag & NUM_AFFECT_ALL && n->idx != j && !(n->val_flag[j] & NUM_EDITED)) ?
+ 0 :
+ j;
+
+ /* Use scale_length if needed! */
+ const float fac = (float)BKE_scene_unit_scale(unit_settings, n->unit_type[j], 1.0);
+
+ if (n->val_flag[i] & NUM_EDITED) {
+ /* Get the best precision, allows us to draw '10.0001' as '10' instead! */
+ prec = UI_calc_float_precision(prec, (double)n->val[i]);
+ if (i == n->idx) {
+ const char *heading_exp = "", *trailing_exp = "";
+ char before_cursor[NUM_STR_REP_LEN];
+ char val[16];
#ifdef USE_FAKE_EDIT
- if (n->val_flag[i] & NUM_NEGATE) {
- heading_exp = (n->val_flag[i] & NUM_INVERSE) ? "-1/(" : "-(";
- trailing_exp = ")";
- }
- else if (n->val_flag[i] & NUM_INVERSE) {
- heading_exp = "1/(";
- trailing_exp = ")";
- }
+ if (n->val_flag[i] & NUM_NEGATE) {
+ heading_exp = (n->val_flag[i] & NUM_INVERSE) ? "-1/(" : "-(";
+ trailing_exp = ")";
+ }
+ else if (n->val_flag[i] & NUM_INVERSE) {
+ heading_exp = "1/(";
+ trailing_exp = ")";
+ }
#endif
- if (n->val_flag[i] & NUM_INVALID) {
- BLI_strncpy(val, "Invalid", sizeof(val));
- }
- else {
- bUnit_AsString(val, sizeof(val), (double)(n->val[i] * fac), prec,
- n->unit_sys, n->unit_type[i], true, false);
- }
-
- /* +1 because of trailing '\0' */
- BLI_strncpy(before_cursor, n->str, n->str_cur + 1);
- BLI_snprintf(&str[j * ln], ln, "[%s%s|%s%s] = %s",
- heading_exp, before_cursor, &n->str[n->str_cur], trailing_exp, val);
- }
- else {
- const char *cur = (i == n->idx) ? "|" : "";
- if (n->unit_use_radians && n->unit_type[i] == B_UNIT_ROTATION) {
- /* Radian exception... */
- BLI_snprintf(&str[j * ln], ln, "%s%.6gr%s", cur, n->val[i], cur);
- }
- else {
- char tstr[NUM_STR_REP_LEN];
- bUnit_AsString(tstr, ln, (double)n->val[i], prec, n->unit_sys, n->unit_type[i], true, false);
- BLI_snprintf(&str[j * ln], ln, "%s%s%s", cur, tstr, cur);
- }
- }
- }
- else {
- const char *cur = (i == n->idx) ? "|" : "";
- BLI_snprintf(&str[j * ln], ln, "%sNONE%s", cur, cur);
- }
- /* We might have cut some multi-bytes utf8 chars
- * (e.g. trailing '°' of degrees values can become only 'A')... */
- BLI_utf8_invalid_strip(&str[j * ln], strlen(&str[j * ln]));
- }
+ if (n->val_flag[i] & NUM_INVALID) {
+ BLI_strncpy(val, "Invalid", sizeof(val));
+ }
+ else {
+ bUnit_AsString(val,
+ sizeof(val),
+ (double)(n->val[i] * fac),
+ prec,
+ n->unit_sys,
+ n->unit_type[i],
+ true,
+ false);
+ }
+
+ /* +1 because of trailing '\0' */
+ BLI_strncpy(before_cursor, n->str, n->str_cur + 1);
+ BLI_snprintf(&str[j * ln],
+ ln,
+ "[%s%s|%s%s] = %s",
+ heading_exp,
+ before_cursor,
+ &n->str[n->str_cur],
+ trailing_exp,
+ val);
+ }
+ else {
+ const char *cur = (i == n->idx) ? "|" : "";
+ if (n->unit_use_radians && n->unit_type[i] == B_UNIT_ROTATION) {
+ /* Radian exception... */
+ BLI_snprintf(&str[j * ln], ln, "%s%.6gr%s", cur, n->val[i], cur);
+ }
+ else {
+ char tstr[NUM_STR_REP_LEN];
+ bUnit_AsString(
+ tstr, ln, (double)n->val[i], prec, n->unit_sys, n->unit_type[i], true, false);
+ BLI_snprintf(&str[j * ln], ln, "%s%s%s", cur, tstr, cur);
+ }
+ }
+ }
+ else {
+ const char *cur = (i == n->idx) ? "|" : "";
+ BLI_snprintf(&str[j * ln], ln, "%sNONE%s", cur, cur);
+ }
+ /* We might have cut some multi-bytes utf8 chars
+ * (e.g. trailing '°' of degrees values can become only 'A')... */
+ BLI_utf8_invalid_strip(&str[j * ln], strlen(&str[j * ln]));
+ }
}
bool hasNumInput(const NumInput *n)
{
- short i;
+ short i;
#ifdef USE_FAKE_EDIT
- if (n->flag & NUM_FAKE_EDITED) {
- return true;
- }
+ if (n->flag & NUM_FAKE_EDITED) {
+ return true;
+ }
#endif
- for (i = 0; i <= n->idx_max; i++) {
- if (n->val_flag[i] & NUM_EDITED) {
- return true;
- }
- }
+ for (i = 0; i <= n->idx_max; i++) {
+ if (n->val_flag[i] & NUM_EDITED) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
/**
@@ -187,410 +202,412 @@ bool hasNumInput(const NumInput *n)
*/
bool applyNumInput(NumInput *n, float *vec)
{
- short i, j;
- float val;
+ short i, j;
+ float val;
- if (hasNumInput(n)) {
- for (j = 0; j <= n->idx_max; j++) {
+ if (hasNumInput(n)) {
+ for (j = 0; j <= n->idx_max; j++) {
#ifdef USE_FAKE_EDIT
- if (n->flag & NUM_FAKE_EDITED) {
- val = n->val[j];
- }
- else
+ if (n->flag & NUM_FAKE_EDITED) {
+ val = n->val[j];
+ }
+ else
#endif
- {
- /* if AFFECTALL and no number typed and cursor not on number, use first number */
- i = (n->flag & NUM_AFFECT_ALL && n->idx != j && !(n->val_flag[j] & NUM_EDITED)) ? 0 : j;
- val = (!(n->val_flag[i] & NUM_EDITED) && n->val_flag[i] & NUM_NULL_ONE) ? 1.0f : n->val[i];
-
- if (n->val_flag[i] & NUM_NO_NEGATIVE && val < 0.0f) {
- val = 0.0f;
- }
- if (n->val_flag[i] & NUM_NO_FRACTION && val != floorf(val)) {
- val = floorf(val + 0.5f);
- if (n->val_flag[i] & NUM_NO_ZERO && val == 0.0f) {
- val = 1.0f;
- }
- }
- else if (n->val_flag[i] & NUM_NO_ZERO && val == 0.0f) {
- val = 0.0001f;
- }
- }
- vec[j] = val;
- }
+ {
+ /* if AFFECTALL and no number typed and cursor not on number, use first number */
+ i = (n->flag & NUM_AFFECT_ALL && n->idx != j && !(n->val_flag[j] & NUM_EDITED)) ? 0 : j;
+ val = (!(n->val_flag[i] & NUM_EDITED) && n->val_flag[i] & NUM_NULL_ONE) ? 1.0f : n->val[i];
+
+ if (n->val_flag[i] & NUM_NO_NEGATIVE && val < 0.0f) {
+ val = 0.0f;
+ }
+ if (n->val_flag[i] & NUM_NO_FRACTION && val != floorf(val)) {
+ val = floorf(val + 0.5f);
+ if (n->val_flag[i] & NUM_NO_ZERO && val == 0.0f) {
+ val = 1.0f;
+ }
+ }
+ else if (n->val_flag[i] & NUM_NO_ZERO && val == 0.0f) {
+ val = 0.0001f;
+ }
+ }
+ vec[j] = val;
+ }
#ifdef USE_FAKE_EDIT
- n->flag &= ~NUM_FAKE_EDITED;
+ n->flag &= ~NUM_FAKE_EDITED;
#endif
- return true;
- }
- else {
- /* Else, we set the 'org' values for numinput! */
- for (j = 0; j <= n->idx_max; j++) {
- n->val[j] = n->val_org[j] = vec[j];
- }
- return false;
- }
+ return true;
+ }
+ else {
+ /* Else, we set the 'org' values for numinput! */
+ for (j = 0; j <= n->idx_max; j++) {
+ n->val[j] = n->val_org[j] = vec[j];
+ }
+ return false;
+ }
}
-
static void value_to_editstr(NumInput *n, int idx)
{
- const int prec = 6; /* editing, higher precision needed. */
- n->str_cur = bUnit_AsString(n->str, NUM_STR_REP_LEN, (double)n->val[idx], prec,
- n->unit_sys, n->unit_type[idx], true, false);
+ const int prec = 6; /* editing, higher precision needed. */
+ n->str_cur = bUnit_AsString(n->str,
+ NUM_STR_REP_LEN,
+ (double)n->val[idx],
+ prec,
+ n->unit_sys,
+ n->unit_type[idx],
+ true,
+ false);
}
static bool editstr_insert_at_cursor(NumInput *n, const char *buf, const int buf_len)
{
- int cur = n->str_cur;
- int len = strlen(&n->str[cur]) + 1; /* +1 for the trailing '\0'. */
- int n_cur = cur + buf_len;
+ int cur = n->str_cur;
+ int len = strlen(&n->str[cur]) + 1; /* +1 for the trailing '\0'. */
+ int n_cur = cur + buf_len;
- if (n_cur + len >= NUM_STR_REP_LEN) {
- return false;
- }
+ if (n_cur + len >= NUM_STR_REP_LEN) {
+ return false;
+ }
- memmove(&n->str[n_cur], &n->str[cur], len);
- memcpy(&n->str[cur], buf, sizeof(char) * buf_len);
+ memmove(&n->str[n_cur], &n->str[cur], len);
+ memcpy(&n->str[cur], buf, sizeof(char) * buf_len);
- n->str_cur = n_cur;
- return true;
+ n->str_cur = n_cur;
+ return true;
}
-bool user_string_to_number(bContext *C, const char *str, const UnitSettings *unit, int type, double *r_value)
+bool user_string_to_number(
+ bContext *C, const char *str, const UnitSettings *unit, int type, double *r_value)
{
#ifdef WITH_PYTHON
- double unit_scale = BKE_scene_unit_scale(unit, type, 1.0);
- if (bUnit_ContainsUnit(str, type)) {
- char str_unit_convert[256];
- BLI_strncpy(str_unit_convert, str, sizeof(str_unit_convert));
- bUnit_ReplaceString(
- str_unit_convert, sizeof(str_unit_convert), str,
- unit_scale, unit->system, type);
-
- return BPY_execute_string_as_number(C, NULL, str_unit_convert, true, r_value);
- }
- else {
- int success = BPY_execute_string_as_number(C, NULL, str, true, r_value);
- *r_value *= bUnit_PreferredInputUnitScalar(unit, type);
- *r_value /= unit_scale;
- return success;
- }
+ double unit_scale = BKE_scene_unit_scale(unit, type, 1.0);
+ if (bUnit_ContainsUnit(str, type)) {
+ char str_unit_convert[256];
+ BLI_strncpy(str_unit_convert, str, sizeof(str_unit_convert));
+ bUnit_ReplaceString(
+ str_unit_convert, sizeof(str_unit_convert), str, unit_scale, unit->system, type);
+
+ return BPY_execute_string_as_number(C, NULL, str_unit_convert, true, r_value);
+ }
+ else {
+ int success = BPY_execute_string_as_number(C, NULL, str, true, r_value);
+ *r_value *= bUnit_PreferredInputUnitScalar(unit, type);
+ *r_value /= unit_scale;
+ return success;
+ }
#else
- *r_value = atof(str);
- return true;
+ *r_value = atof(str);
+ return true;
#endif
}
-
static bool editstr_is_simple_numinput(const char ascii)
{
- if (ascii >= '0' && ascii <= '9') {
- return true;
- }
- else if (ascii == '.') {
- return true;
- }
- else {
- return false;
- }
+ if (ascii >= '0' && ascii <= '9') {
+ return true;
+ }
+ else if (ascii == '.') {
+ return true;
+ }
+ else {
+ return false;
+ }
}
bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
{
- const char *utf8_buf = NULL;
- char ascii[2] = {'\0', '\0'};
- bool updated = false;
- short idx = n->idx, idx_max = n->idx_max;
- short dir = STRCUR_DIR_NEXT, mode = STRCUR_JUMP_NONE;
- int cur;
+ const char *utf8_buf = NULL;
+ char ascii[2] = {'\0', '\0'};
+ bool updated = false;
+ short idx = n->idx, idx_max = n->idx_max;
+ short dir = STRCUR_DIR_NEXT, mode = STRCUR_JUMP_NONE;
+ int cur;
#ifdef USE_FAKE_EDIT
- if (U.flag & USER_FLAG_NUMINPUT_ADVANCED)
+ if (U.flag & USER_FLAG_NUMINPUT_ADVANCED)
#endif
- {
- if ((event->ctrl == 0) && (event->alt == 0) && (event->ascii != '\0') &&
- strchr("01234567890@%^&*-+/{}()[]<>.|", event->ascii))
- {
- if (!(n->flag & NUM_EDIT_FULL)) {
- n->flag |= NUM_EDITED;
- n->flag |= NUM_EDIT_FULL;
- n->val_flag[idx] |= NUM_EDITED;
- }
- }
- }
-
- switch (event->type) {
- case EVT_MODAL_MAP:
- if (ELEM(event->val, NUM_MODAL_INCREMENT_UP, NUM_MODAL_INCREMENT_DOWN)) {
- n->val[idx] += (event->val == NUM_MODAL_INCREMENT_UP) ? n->val_inc[idx] : -n->val_inc[idx];
- value_to_editstr(n, idx);
- n->val_flag[idx] |= NUM_EDITED;
- updated = true;
- }
- else {
- /* might be a char too... */
- utf8_buf = event->utf8_buf;
- ascii[0] = event->ascii;
- }
- break;
- case BACKSPACEKEY:
- /* Part specific to backspace... */
- if (!(n->val_flag[idx] & NUM_EDITED)) {
- copy_v3_v3(n->val, n->val_org);
- n->val_flag[0] &= ~NUM_EDITED;
- n->val_flag[1] &= ~NUM_EDITED;
- n->val_flag[2] &= ~NUM_EDITED;
+ {
+ if ((event->ctrl == 0) && (event->alt == 0) && (event->ascii != '\0') &&
+ strchr("01234567890@%^&*-+/{}()[]<>.|", event->ascii)) {
+ if (!(n->flag & NUM_EDIT_FULL)) {
+ n->flag |= NUM_EDITED;
+ n->flag |= NUM_EDIT_FULL;
+ n->val_flag[idx] |= NUM_EDITED;
+ }
+ }
+ }
+
+ switch (event->type) {
+ case EVT_MODAL_MAP:
+ if (ELEM(event->val, NUM_MODAL_INCREMENT_UP, NUM_MODAL_INCREMENT_DOWN)) {
+ n->val[idx] += (event->val == NUM_MODAL_INCREMENT_UP) ? n->val_inc[idx] : -n->val_inc[idx];
+ value_to_editstr(n, idx);
+ n->val_flag[idx] |= NUM_EDITED;
+ updated = true;
+ }
+ else {
+ /* might be a char too... */
+ utf8_buf = event->utf8_buf;
+ ascii[0] = event->ascii;
+ }
+ break;
+ case BACKSPACEKEY:
+ /* Part specific to backspace... */
+ if (!(n->val_flag[idx] & NUM_EDITED)) {
+ copy_v3_v3(n->val, n->val_org);
+ n->val_flag[0] &= ~NUM_EDITED;
+ n->val_flag[1] &= ~NUM_EDITED;
+ n->val_flag[2] &= ~NUM_EDITED;
#ifdef USE_FAKE_EDIT
- n->flag |= NUM_FAKE_EDITED;
+ n->flag |= NUM_FAKE_EDITED;
#else
- n->flag |= NUM_EDIT_FULL;
+ n->flag |= NUM_EDIT_FULL;
#endif
- updated = true;
- break;
- }
- else if (event->shift || !n->str[0]) {
- n->val[idx] = n->val_org[idx];
- n->val_flag[idx] &= ~NUM_EDITED;
- n->str[0] = '\0';
- n->str_cur = 0;
- updated = true;
- break;
- }
- /* Else, common behavior with DELKEY,
- * only difference is remove char(s) before/after the cursor. */
- dir = STRCUR_DIR_PREV;
- ATTR_FALLTHROUGH;
- case DELKEY:
- if ((n->val_flag[idx] & NUM_EDITED) && n->str[0]) {
- int t_cur = cur = n->str_cur;
- if (event->ctrl) {
- mode = STRCUR_JUMP_DELIM;
- }
- BLI_str_cursor_step_utf8(n->str, strlen(n->str), &t_cur, dir, mode, true);
- if (t_cur != cur) {
- if (t_cur < cur) {
- SWAP(int, t_cur, cur);
- n->str_cur = cur;
- }
- /* +1 for trailing '\0'. */
- memmove(&n->str[cur], &n->str[t_cur], strlen(&n->str[t_cur]) + 1);
- updated = true;
- }
- if (!n->str[0]) {
- n->val[idx] = n->val_org[idx];
- }
- }
- else {
- return false;
- }
- break;
- case LEFTARROWKEY:
- dir = STRCUR_DIR_PREV;
- ATTR_FALLTHROUGH;
- case RIGHTARROWKEY:
- cur = n->str_cur;
- if (event->ctrl) {
- mode = STRCUR_JUMP_DELIM;
- }
- BLI_str_cursor_step_utf8(n->str, strlen(n->str), &cur, dir, mode, true);
- if (cur != n->str_cur) {
- n->str_cur = cur;
- return true;
- }
- return false;
- case HOMEKEY:
- if (n->str[0]) {
- n->str_cur = 0;
- return true;
- }
- return false;
- case ENDKEY:
- if (n->str[0]) {
- n->str_cur = strlen(n->str);
- return true;
- }
- return false;
- case TABKEY:
+ updated = true;
+ break;
+ }
+ else if (event->shift || !n->str[0]) {
+ n->val[idx] = n->val_org[idx];
+ n->val_flag[idx] &= ~NUM_EDITED;
+ n->str[0] = '\0';
+ n->str_cur = 0;
+ updated = true;
+ break;
+ }
+ /* Else, common behavior with DELKEY,
+ * only difference is remove char(s) before/after the cursor. */
+ dir = STRCUR_DIR_PREV;
+ ATTR_FALLTHROUGH;
+ case DELKEY:
+ if ((n->val_flag[idx] & NUM_EDITED) && n->str[0]) {
+ int t_cur = cur = n->str_cur;
+ if (event->ctrl) {
+ mode = STRCUR_JUMP_DELIM;
+ }
+ BLI_str_cursor_step_utf8(n->str, strlen(n->str), &t_cur, dir, mode, true);
+ if (t_cur != cur) {
+ if (t_cur < cur) {
+ SWAP(int, t_cur, cur);
+ n->str_cur = cur;
+ }
+ /* +1 for trailing '\0'. */
+ memmove(&n->str[cur], &n->str[t_cur], strlen(&n->str[t_cur]) + 1);
+ updated = true;
+ }
+ if (!n->str[0]) {
+ n->val[idx] = n->val_org[idx];
+ }
+ }
+ else {
+ return false;
+ }
+ break;
+ case LEFTARROWKEY:
+ dir = STRCUR_DIR_PREV;
+ ATTR_FALLTHROUGH;
+ case RIGHTARROWKEY:
+ cur = n->str_cur;
+ if (event->ctrl) {
+ mode = STRCUR_JUMP_DELIM;
+ }
+ BLI_str_cursor_step_utf8(n->str, strlen(n->str), &cur, dir, mode, true);
+ if (cur != n->str_cur) {
+ n->str_cur = cur;
+ return true;
+ }
+ return false;
+ case HOMEKEY:
+ if (n->str[0]) {
+ n->str_cur = 0;
+ return true;
+ }
+ return false;
+ case ENDKEY:
+ if (n->str[0]) {
+ n->str_cur = strlen(n->str);
+ return true;
+ }
+ return false;
+ case TABKEY:
#ifdef USE_FAKE_EDIT
- n->val_flag[idx] &= ~(NUM_NEGATE | NUM_INVERSE);
+ n->val_flag[idx] &= ~(NUM_NEGATE | NUM_INVERSE);
#endif
- idx = (idx + idx_max + (event->ctrl ? 0 : 2)) % (idx_max + 1);
- n->idx = idx;
- if (n->val_flag[idx] & NUM_EDITED) {
- value_to_editstr(n, idx);
- }
- else {
- n->str[0] = '\0';
- n->str_cur = 0;
- }
- return true;
- case PADPERIOD:
- case PERIODKEY:
- /* Force numdot, some OSs/countries generate a comma char in this case,
- * sic... (T37992) */
- ascii[0] = '.';
- utf8_buf = ascii;
- break;
+ idx = (idx + idx_max + (event->ctrl ? 0 : 2)) % (idx_max + 1);
+ n->idx = idx;
+ if (n->val_flag[idx] & NUM_EDITED) {
+ value_to_editstr(n, idx);
+ }
+ else {
+ n->str[0] = '\0';
+ n->str_cur = 0;
+ }
+ return true;
+ case PADPERIOD:
+ case PERIODKEY:
+ /* Force numdot, some OSs/countries generate a comma char in this case,
+ * sic... (T37992) */
+ ascii[0] = '.';
+ utf8_buf = ascii;
+ break;
#if 0
- /* Those keys are not directly accessible in all layouts, preventing to generate matching events.
- * So we use a hack (ascii value) instead, see below.
- */
- case EQUALKEY:
- case PADASTERKEY:
- 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;
- }
- break;
+ /* Those keys are not directly accessible in all layouts, preventing to generate matching events.
+ * So we use a hack (ascii value) instead, see below.
+ */
+ case EQUALKEY:
+ case PADASTERKEY:
+ 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;
+ }
+ break;
#endif
#ifdef USE_FAKE_EDIT
- case PADMINUS:
- case MINUSKEY:
- if (event->ctrl || !(n->flag & NUM_EDIT_FULL)) {
- n->val_flag[idx] ^= NUM_NEGATE;
- updated = true;
- }
- break;
- case PADSLASHKEY:
- case SLASHKEY:
- if (event->ctrl || !(n->flag & NUM_EDIT_FULL)) {
- n->val_flag[idx] ^= NUM_INVERSE;
- updated = true;
- }
- break;
+ case PADMINUS:
+ case MINUSKEY:
+ if (event->ctrl || !(n->flag & NUM_EDIT_FULL)) {
+ n->val_flag[idx] ^= NUM_NEGATE;
+ updated = true;
+ }
+ break;
+ case PADSLASHKEY:
+ case SLASHKEY:
+ if (event->ctrl || !(n->flag & NUM_EDIT_FULL)) {
+ n->val_flag[idx] ^= NUM_INVERSE;
+ updated = true;
+ }
+ break;
#endif
- case CKEY:
- if (event->ctrl) {
- /* Copy current str to the copypaste buffer. */
- WM_clipboard_text_set(n->str, 0);
- updated = true;
- }
- break;
- case VKEY:
- if (event->ctrl) {
- /* extract the first line from the clipboard */
- int pbuf_len;
- char *pbuf = WM_clipboard_text_get_firstline(false, &pbuf_len);
-
- if (pbuf) {
- const bool success = editstr_insert_at_cursor(n, pbuf, pbuf_len);
-
- MEM_freeN(pbuf);
- if (!success) {
- return false;
- }
-
- n->val_flag[idx] |= NUM_EDITED;
- }
- updated = true;
- }
- break;
- default:
- break;
- }
-
- if (!updated && !utf8_buf && (event->utf8_buf[0] || event->ascii)) {
- utf8_buf = event->utf8_buf;
- ascii[0] = event->ascii;
- }
+ case CKEY:
+ if (event->ctrl) {
+ /* Copy current str to the copypaste buffer. */
+ WM_clipboard_text_set(n->str, 0);
+ updated = true;
+ }
+ break;
+ case VKEY:
+ if (event->ctrl) {
+ /* extract the first line from the clipboard */
+ int pbuf_len;
+ char *pbuf = WM_clipboard_text_get_firstline(false, &pbuf_len);
+
+ if (pbuf) {
+ const bool success = editstr_insert_at_cursor(n, pbuf, pbuf_len);
+
+ MEM_freeN(pbuf);
+ if (!success) {
+ return false;
+ }
+
+ n->val_flag[idx] |= NUM_EDITED;
+ }
+ updated = true;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!updated && !utf8_buf && (event->utf8_buf[0] || event->ascii)) {
+ utf8_buf = event->utf8_buf;
+ 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;
- }
- }
+ /* 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.
- */
- if (!updated && event->ctrl) {
- return false;
- }
-
- if ((!utf8_buf || !utf8_buf[0]) && ascii[0]) {
- /* Fallback to ascii. */
- utf8_buf = ascii;
- }
-
- if (utf8_buf && utf8_buf[0]) {
- if (!(n->flag & NUM_EDIT_FULL)) {
- /* In simple edit mode, we only keep a few chars as valid! */
- /* no need to decode unicode, ascii is first char only */
- if (!editstr_is_simple_numinput(utf8_buf[0])) {
- return false;
- }
- }
-
- if (!editstr_insert_at_cursor(n, utf8_buf, BLI_str_utf8_size(utf8_buf))) {
- return false;
- }
-
- n->val_flag[idx] |= NUM_EDITED;
- }
- else if (!updated) {
- return false;
- }
-
- /* At this point, our value has changed, try to interpret it with python
- * (if str is not empty!). */
- if (n->str[0]) {
- const float val_prev = n->val[idx];
- Scene *sce = CTX_data_scene(C);
-
- double val;
- int success = user_string_to_number(C, n->str, &sce->unit, n->unit_type[idx], &val);
-
- if (success) {
- n->val[idx] = (float)val;
- n->val_flag[idx] &= ~NUM_INVALID;
- }
- else {
- n->val_flag[idx] |= NUM_INVALID;
- }
-
+ /* Up to this point, if we have a ctrl modifier, skip.
+ * This allows to still access most of modals' shortcuts even in numinput mode.
+ */
+ if (!updated && event->ctrl) {
+ return false;
+ }
+
+ if ((!utf8_buf || !utf8_buf[0]) && ascii[0]) {
+ /* Fallback to ascii. */
+ utf8_buf = ascii;
+ }
+
+ if (utf8_buf && utf8_buf[0]) {
+ if (!(n->flag & NUM_EDIT_FULL)) {
+ /* In simple edit mode, we only keep a few chars as valid! */
+ /* no need to decode unicode, ascii is first char only */
+ if (!editstr_is_simple_numinput(utf8_buf[0])) {
+ return false;
+ }
+ }
+
+ if (!editstr_insert_at_cursor(n, utf8_buf, BLI_str_utf8_size(utf8_buf))) {
+ return false;
+ }
+
+ n->val_flag[idx] |= NUM_EDITED;
+ }
+ else if (!updated) {
+ return false;
+ }
+
+ /* At this point, our value has changed, try to interpret it with python
+ * (if str is not empty!). */
+ if (n->str[0]) {
+ const float val_prev = n->val[idx];
+ Scene *sce = CTX_data_scene(C);
+
+ double val;
+ int success = user_string_to_number(C, n->str, &sce->unit, n->unit_type[idx], &val);
+
+ if (success) {
+ n->val[idx] = (float)val;
+ n->val_flag[idx] &= ~NUM_INVALID;
+ }
+ else {
+ n->val_flag[idx] |= NUM_INVALID;
+ }
#ifdef USE_FAKE_EDIT
- if (n->val_flag[idx] & NUM_NEGATE) {
- n->val[idx] = -n->val[idx];
- }
- if (n->val_flag[idx] & NUM_INVERSE) {
- val = n->val[idx];
- /* If we invert on radians when user is in degrees,
- * you get unexpected results... See T53463. */
- if (!n->unit_use_radians && n->unit_type[idx] == B_UNIT_ROTATION) {
- val = RAD2DEG(val);
- }
- val = 1.0 / val;
- if (!n->unit_use_radians && n->unit_type[idx] == B_UNIT_ROTATION) {
- val = DEG2RAD(val);
- }
- n->val[idx] = (float)val;
- }
+ if (n->val_flag[idx] & NUM_NEGATE) {
+ n->val[idx] = -n->val[idx];
+ }
+ if (n->val_flag[idx] & NUM_INVERSE) {
+ val = n->val[idx];
+ /* If we invert on radians when user is in degrees,
+ * you get unexpected results... See T53463. */
+ if (!n->unit_use_radians && n->unit_type[idx] == B_UNIT_ROTATION) {
+ val = RAD2DEG(val);
+ }
+ val = 1.0 / val;
+ if (!n->unit_use_radians && n->unit_type[idx] == B_UNIT_ROTATION) {
+ val = DEG2RAD(val);
+ }
+ n->val[idx] = (float)val;
+ }
#endif
- if (UNLIKELY(!isfinite(n->val[idx]))) {
- n->val[idx] = val_prev;
- n->val_flag[idx] |= NUM_INVALID;
- }
- }
+ if (UNLIKELY(!isfinite(n->val[idx]))) {
+ n->val[idx] = val_prev;
+ n->val_flag[idx] |= NUM_INVALID;
+ }
+ }
- /* REDRAW SINCE NUMBERS HAVE CHANGED */
- return true;
+ /* REDRAW SINCE NUMBERS HAVE CHANGED */
+ return true;
}
diff --git a/source/blender/editors/util/select_utils.c b/source/blender/editors/util/select_utils.c
index b8167632fd9..13c623a2860 100644
--- a/source/blender/editors/util/select_utils.c
+++ b/source/blender/editors/util/select_utils.c
@@ -29,20 +29,20 @@
/** 1: select, 0: deselect, -1: pass. */
int ED_select_op_action(const eSelectOp sel_op, const bool is_select, const bool is_inside)
{
- switch (sel_op) {
- case SEL_OP_ADD:
- return (!is_select && (is_inside)) ? 1 : -1;
- case SEL_OP_SUB:
- return (is_select && is_inside) ? 0 : -1;
- case SEL_OP_SET:
- return is_inside ? 1 : 0;
- case SEL_OP_AND:
- return (is_select && is_inside) ? -1 : (is_select ? 0 : -1);
- case SEL_OP_XOR:
- return (is_select && is_inside) ? 0 : ((!is_select && is_inside) ? 1 : -1);
- }
- BLI_assert(!"invalid sel_op");
- return -1;
+ switch (sel_op) {
+ case SEL_OP_ADD:
+ return (!is_select && (is_inside)) ? 1 : -1;
+ case SEL_OP_SUB:
+ return (is_select && is_inside) ? 0 : -1;
+ case SEL_OP_SET:
+ return is_inside ? 1 : 0;
+ case SEL_OP_AND:
+ return (is_select && is_inside) ? -1 : (is_select ? 0 : -1);
+ case SEL_OP_XOR:
+ return (is_select && is_inside) ? 0 : ((!is_select && is_inside) ? 1 : -1);
+ }
+ BLI_assert(!"invalid sel_op");
+ return -1;
}
/**
* Use when we've de-selected all items first (for modes that need it).
@@ -50,23 +50,25 @@ int ED_select_op_action(const eSelectOp sel_op, const bool is_select, const bool
* \note In some cases changing selection needs to perform other checks,
* so it's more straightforward to deselect all, then select.
*/
-int ED_select_op_action_deselected(const eSelectOp sel_op, const bool is_select, const bool is_inside)
+int ED_select_op_action_deselected(const eSelectOp sel_op,
+ const bool is_select,
+ const bool is_inside)
{
- switch (sel_op) {
- case SEL_OP_ADD:
- return (!is_select && is_inside) ? 1 : -1;
- case SEL_OP_SUB:
- return (is_select && is_inside) ? 0 : -1;
- case SEL_OP_SET:
- /* Only difference w/ function above. */
- return is_inside ? 1 : -1;
- case SEL_OP_AND:
- return (is_select && is_inside) ? -1 : (is_select ? 0 : -1);
- case SEL_OP_XOR:
- return (is_select && is_inside) ? 0 : ((!is_select && is_inside) ? 1 : -1);
- }
- BLI_assert(!"invalid sel_op");
- return -1;
+ switch (sel_op) {
+ case SEL_OP_ADD:
+ return (!is_select && is_inside) ? 1 : -1;
+ case SEL_OP_SUB:
+ return (is_select && is_inside) ? 0 : -1;
+ case SEL_OP_SET:
+ /* Only difference w/ function above. */
+ return is_inside ? 1 : -1;
+ case SEL_OP_AND:
+ return (is_select && is_inside) ? -1 : (is_select ? 0 : -1);
+ case SEL_OP_XOR:
+ return (is_select && is_inside) ? 0 : ((!is_select && is_inside) ? 1 : -1);
+ }
+ BLI_assert(!"invalid sel_op");
+ return -1;
}
/**
@@ -74,60 +76,63 @@ int ED_select_op_action_deselected(const eSelectOp sel_op, const bool is_select,
*/
eSelectOp ED_select_op_modal(const eSelectOp sel_op, const bool is_first)
{
- if (sel_op == SEL_OP_SET) {
- if (is_first == false) {
- return SEL_OP_ADD;
- }
- }
- return sel_op;
+ if (sel_op == SEL_OP_SET) {
+ if (is_first == false) {
+ return SEL_OP_ADD;
+ }
+ }
+ return sel_op;
}
int ED_select_similar_compare_float(const float delta, const float thresh, const int compare)
{
- switch (compare) {
- case SIM_CMP_EQ:
- return (fabsf(delta) < thresh + FLT_EPSILON);
- case SIM_CMP_GT:
- return ((delta + thresh) > -FLT_EPSILON);
- case SIM_CMP_LT:
- return ((delta - thresh) < FLT_EPSILON);
- default:
- BLI_assert(0);
- return 0;
- }
+ switch (compare) {
+ case SIM_CMP_EQ:
+ return (fabsf(delta) < thresh + FLT_EPSILON);
+ case SIM_CMP_GT:
+ return ((delta + thresh) > -FLT_EPSILON);
+ case SIM_CMP_LT:
+ return ((delta - thresh) < FLT_EPSILON);
+ default:
+ BLI_assert(0);
+ return 0;
+ }
}
-bool ED_select_similar_compare_float_tree(const KDTree_1d *tree, const float length, const float thresh, const int compare)
+bool ED_select_similar_compare_float_tree(const KDTree_1d *tree,
+ const float length,
+ const float thresh,
+ const int compare)
{
- /* Length of the edge we want to compare against. */
- float nearest_edge_length;
+ /* Length of the edge we want to compare against. */
+ float nearest_edge_length;
- switch (compare) {
- case SIM_CMP_EQ:
- /* Compare to the edge closest to the current edge. */
- nearest_edge_length = length;
- break;
- case SIM_CMP_GT:
- /* Compare against the shortest edge. */
- /* -FLT_MAX leads to some precision issues and the wrong edge being selected.
- * For example, in a tree with 1, 2 and 3, which is stored squared as 1, 4, 9, it returns as the nearest
- * length/node the "4" instead of "1". */
- nearest_edge_length = -1.0f;
- break;
- case SIM_CMP_LT:
- /* Compare against the longest edge. */
- nearest_edge_length = FLT_MAX;
- break;
- default:
- BLI_assert(0);
- return false;
- }
+ switch (compare) {
+ case SIM_CMP_EQ:
+ /* Compare to the edge closest to the current edge. */
+ nearest_edge_length = length;
+ break;
+ case SIM_CMP_GT:
+ /* Compare against the shortest edge. */
+ /* -FLT_MAX leads to some precision issues and the wrong edge being selected.
+ * For example, in a tree with 1, 2 and 3, which is stored squared as 1, 4, 9, it returns as the nearest
+ * length/node the "4" instead of "1". */
+ nearest_edge_length = -1.0f;
+ break;
+ case SIM_CMP_LT:
+ /* Compare against the longest edge. */
+ nearest_edge_length = FLT_MAX;
+ break;
+ default:
+ BLI_assert(0);
+ return false;
+ }
- KDTreeNearest_1d nearest;
- if (BLI_kdtree_1d_find_nearest(tree, &nearest_edge_length, &nearest) != -1) {
- float delta = length - nearest.co[0];
- return ED_select_similar_compare_float(delta, thresh, compare);
- }
+ KDTreeNearest_1d nearest;
+ if (BLI_kdtree_1d_find_nearest(tree, &nearest_edge_length, &nearest) != -1) {
+ float delta = length - nearest.co[0];
+ return ED_select_similar_compare_float(delta, thresh, compare);
+ }
- return false;
+ return false;
}
diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt
index 45cd9b09de3..240cfd382a4 100644
--- a/source/blender/editors/uvedit/CMakeLists.txt
+++ b/source/blender/editors/uvedit/CMakeLists.txt
@@ -16,42 +16,42 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../bmesh
- ../../depsgraph
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/eigen
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../bmesh
+ ../../depsgraph
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/eigen
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- uvedit_buttons.c
- uvedit_draw.c
- uvedit_ops.c
- uvedit_parametrizer.c
- uvedit_smart_stitch.c
- uvedit_unwrap_ops.c
-
- uvedit_intern.h
- uvedit_parametrizer.h
+ uvedit_buttons.c
+ uvedit_draw.c
+ uvedit_ops.c
+ uvedit_parametrizer.c
+ uvedit_smart_stitch.c
+ uvedit_unwrap_ops.c
+
+ uvedit_intern.h
+ uvedit_parametrizer.h
)
set(LIB
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/uvedit/uvedit_buttons.c b/source/blender/editors/uvedit/uvedit_buttons.c
index 6f8bfac8c57..16620436029 100644
--- a/source/blender/editors/uvedit/uvedit_buttons.c
+++ b/source/blender/editors/uvedit/uvedit_buttons.c
@@ -53,62 +53,63 @@
#include "WM_api.h"
#include "WM_types.h"
-#define B_UVEDIT_VERTEX 3
+#define B_UVEDIT_VERTEX 3
/* UV Utilities */
static int uvedit_center(Scene *scene, Object *obedit, BMEditMesh *em, Image *ima, float center[2])
{
- BMFace *f;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
- int tot = 0;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- zero_v2(center);
- BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, f))
- continue;
-
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- add_v2_v2(center, luv->uv);
- tot++;
- }
- }
- }
-
- if (tot > 0) {
- center[0] /= tot;
- center[1] /= tot;
- }
-
- return tot;
+ BMFace *f;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+ int tot = 0;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ zero_v2(center);
+ BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, f))
+ continue;
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ add_v2_v2(center, luv->uv);
+ tot++;
+ }
+ }
+ }
+
+ if (tot > 0) {
+ center[0] /= tot;
+ center[1] /= tot;
+ }
+
+ return tot;
}
-static void uvedit_translate(Scene *scene, Object *obedit, BMEditMesh *em, Image *ima, float delta[2])
+static void uvedit_translate(
+ Scene *scene, Object *obedit, BMEditMesh *em, Image *ima, float delta[2])
{
- BMFace *f;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, f))
- continue;
-
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- add_v2_v2(luv->uv, delta);
- }
- }
- }
+ BMFace *f;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, f))
+ continue;
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ add_v2_v2(luv->uv, delta);
+ }
+ }
+ }
}
/* Button Functions, using an evil static variable */
@@ -117,122 +118,144 @@ static float uvedit_old_center[2];
static void uvedit_vertex_buttons(const bContext *C, uiBlock *block)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- Image *ima = sima->image;
- BMEditMesh *em;
- float center[2];
- int imx, imy, step, digits;
- float width = 8 * UI_UNIT_X;
-
- ED_space_image_get_size(sima, &imx, &imy);
-
- em = BKE_editmesh_from_object(obedit);
-
- if (uvedit_center(scene, obedit, em, ima, center)) {
- float range_xy[2][2] = {
- {-10.0f, 10.0f},
- {-10.0f, 10.0f},
- };
-
- copy_v2_v2(uvedit_old_center, center);
-
- /* expand UI range by center */
- CLAMP_MAX(range_xy[0][0], uvedit_old_center[0]);
- CLAMP_MIN(range_xy[0][1], uvedit_old_center[0]);
- CLAMP_MAX(range_xy[1][0], uvedit_old_center[1]);
- CLAMP_MIN(range_xy[1][1], uvedit_old_center[1]);
-
- if (!(sima->flag & SI_COORDFLOATS)) {
- uvedit_old_center[0] *= imx;
- uvedit_old_center[1] *= imy;
-
- mul_v2_fl(range_xy[0], imx);
- mul_v2_fl(range_xy[1], imy);
- }
-
- if (sima->flag & SI_COORDFLOATS) {
- step = 1;
- digits = 3;
- }
- else {
- step = 100;
- digits = 2;
- }
-
- UI_block_align_begin(block);
- uiDefButF(block, UI_BTYPE_NUM, B_UVEDIT_VERTEX, IFACE_("X:"), 0, 0, width, UI_UNIT_Y, &uvedit_old_center[0],
- UNPACK2(range_xy[0]), step, digits, "");
- uiDefButF(block, UI_BTYPE_NUM, B_UVEDIT_VERTEX, IFACE_("Y:"), width, 0, width, UI_UNIT_Y, &uvedit_old_center[1],
- UNPACK2(range_xy[1]), step, digits, "");
- UI_block_align_end(block);
- }
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ Image *ima = sima->image;
+ BMEditMesh *em;
+ float center[2];
+ int imx, imy, step, digits;
+ float width = 8 * UI_UNIT_X;
+
+ ED_space_image_get_size(sima, &imx, &imy);
+
+ em = BKE_editmesh_from_object(obedit);
+
+ if (uvedit_center(scene, obedit, em, ima, center)) {
+ float range_xy[2][2] = {
+ {-10.0f, 10.0f},
+ {-10.0f, 10.0f},
+ };
+
+ copy_v2_v2(uvedit_old_center, center);
+
+ /* expand UI range by center */
+ CLAMP_MAX(range_xy[0][0], uvedit_old_center[0]);
+ CLAMP_MIN(range_xy[0][1], uvedit_old_center[0]);
+ CLAMP_MAX(range_xy[1][0], uvedit_old_center[1]);
+ CLAMP_MIN(range_xy[1][1], uvedit_old_center[1]);
+
+ if (!(sima->flag & SI_COORDFLOATS)) {
+ uvedit_old_center[0] *= imx;
+ uvedit_old_center[1] *= imy;
+
+ mul_v2_fl(range_xy[0], imx);
+ mul_v2_fl(range_xy[1], imy);
+ }
+
+ if (sima->flag & SI_COORDFLOATS) {
+ step = 1;
+ digits = 3;
+ }
+ else {
+ step = 100;
+ digits = 2;
+ }
+
+ UI_block_align_begin(block);
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_UVEDIT_VERTEX,
+ IFACE_("X:"),
+ 0,
+ 0,
+ width,
+ UI_UNIT_Y,
+ &uvedit_old_center[0],
+ UNPACK2(range_xy[0]),
+ step,
+ digits,
+ "");
+ uiDefButF(block,
+ UI_BTYPE_NUM,
+ B_UVEDIT_VERTEX,
+ IFACE_("Y:"),
+ width,
+ 0,
+ width,
+ UI_UNIT_Y,
+ &uvedit_old_center[1],
+ UNPACK2(range_xy[1]),
+ step,
+ digits,
+ "");
+ UI_block_align_end(block);
+ }
}
static void do_uvedit_vertex(bContext *C, void *UNUSED(arg), int event)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- Image *ima = sima->image;
- BMEditMesh *em;
- float center[2], delta[2];
- int imx, imy;
-
- if (event != B_UVEDIT_VERTEX)
- return;
-
- em = BKE_editmesh_from_object(obedit);
-
- ED_space_image_get_size(sima, &imx, &imy);
- uvedit_center(scene, obedit, em, ima, center);
-
- if (sima->flag & SI_COORDFLOATS) {
- delta[0] = uvedit_old_center[0] - center[0];
- delta[1] = uvedit_old_center[1] - center[1];
- }
- else {
- delta[0] = uvedit_old_center[0] / imx - center[0];
- delta[1] = uvedit_old_center[1] / imy - center[1];
- }
-
- uvedit_translate(scene, obedit, em, ima, delta);
-
- WM_event_add_notifier(C, NC_IMAGE, sima->image);
- DEG_id_tag_update((ID *)obedit->data, ID_RECALC_GEOMETRY);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ Image *ima = sima->image;
+ BMEditMesh *em;
+ float center[2], delta[2];
+ int imx, imy;
+
+ if (event != B_UVEDIT_VERTEX)
+ return;
+
+ em = BKE_editmesh_from_object(obedit);
+
+ ED_space_image_get_size(sima, &imx, &imy);
+ uvedit_center(scene, obedit, em, ima, center);
+
+ if (sima->flag & SI_COORDFLOATS) {
+ delta[0] = uvedit_old_center[0] - center[0];
+ delta[1] = uvedit_old_center[1] - center[1];
+ }
+ else {
+ delta[0] = uvedit_old_center[0] / imx - center[0];
+ delta[1] = uvedit_old_center[1] / imy - center[1];
+ }
+
+ uvedit_translate(scene, obedit, em, ima, delta);
+
+ WM_event_add_notifier(C, NC_IMAGE, sima->image);
+ DEG_id_tag_update((ID *)obedit->data, ID_RECALC_GEOMETRY);
}
/* Panels */
static bool image_panel_uv_poll(const bContext *C, PanelType *UNUSED(pt))
{
- SpaceImage *sima = CTX_wm_space_image(C);
- if (sima->mode != SI_MODE_UV) {
- return false;
- }
- Object *obedit = CTX_data_edit_object(C);
- return ED_uvedit_test(obedit);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ if (sima->mode != SI_MODE_UV) {
+ return false;
+ }
+ Object *obedit = CTX_data_edit_object(C);
+ return ED_uvedit_test(obedit);
}
static void image_panel_uv(const bContext *C, Panel *pa)
{
- uiBlock *block;
+ uiBlock *block;
- block = uiLayoutAbsoluteBlock(pa->layout);
- UI_block_func_handle_set(block, do_uvedit_vertex, NULL);
+ block = uiLayoutAbsoluteBlock(pa->layout);
+ UI_block_func_handle_set(block, do_uvedit_vertex, NULL);
- uvedit_vertex_buttons(C, block);
+ uvedit_vertex_buttons(C, block);
}
void ED_uvedit_buttons_register(ARegionType *art)
{
- PanelType *pt;
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype image panel uv");
- strcpy(pt->idname, "IMAGE_PT_uv");
- strcpy(pt->label, N_("UV Vertex")); /* XXX C panels unavailable through RNA bpy.types! */
- pt->draw = image_panel_uv;
- pt->poll = image_panel_uv_poll;
- BLI_addtail(&art->paneltypes, pt);
+ PanelType *pt;
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype image panel uv");
+ strcpy(pt->idname, "IMAGE_PT_uv");
+ strcpy(pt->label, N_("UV Vertex")); /* XXX C panels unavailable through RNA bpy.types! */
+ pt->draw = image_panel_uv;
+ pt->poll = image_panel_uv_poll;
+ BLI_addtail(&art->paneltypes, pt);
}
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index 8bc2be11934..5ff90097840 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -21,7 +21,6 @@
* \ingroup eduv
*/
-
#include <float.h>
#include <math.h>
#include <stdlib.h>
@@ -71,434 +70,442 @@
static int draw_uvs_face_check(const ToolSettings *ts)
{
- /* checks if we are selecting only faces */
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- if (ts->selectmode == SCE_SELECT_FACE)
- return 2;
- else if (ts->selectmode & SCE_SELECT_FACE)
- return 1;
- else
- return 0;
- }
- else
- return (ts->uv_selectmode == UV_SELECT_FACE);
+ /* checks if we are selecting only faces */
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ if (ts->selectmode == SCE_SELECT_FACE)
+ return 2;
+ else if (ts->selectmode & SCE_SELECT_FACE)
+ return 1;
+ else
+ return 0;
+ }
+ else
+ return (ts->uv_selectmode == UV_SELECT_FACE);
}
/* ------------------------- */
void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
{
- float zoom[2], x_fac, y_fac;
+ float zoom[2], x_fac, y_fac;
- UI_view2d_scale_get_inverse(&ar->v2d, &zoom[0], &zoom[1]);
+ UI_view2d_scale_get_inverse(&ar->v2d, &zoom[0], &zoom[1]);
- mul_v2_fl(zoom, 256.0f * UI_DPI_FAC);
- x_fac = zoom[0];
- y_fac = zoom[1];
+ mul_v2_fl(zoom, 256.0f * UI_DPI_FAC);
+ x_fac = zoom[0];
+ y_fac = zoom[1];
- GPU_line_width(1.0f);
+ GPU_line_width(1.0f);
- GPU_matrix_translate_2fv(cursor);
+ GPU_matrix_translate_2fv(cursor);
- const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
- immUniform1i("colors_len", 2); /* "advanced" mode */
- immUniformArray4fv("colors", (float *)(float[][4]){{1.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2);
- immUniform1f("dash_width", 8.0f);
+ immUniform1i("colors_len", 2); /* "advanced" mode */
+ immUniformArray4fv(
+ "colors", (float *)(float[][4]){{1.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2);
+ immUniform1f("dash_width", 8.0f);
- immBegin(GPU_PRIM_LINES, 8);
+ immBegin(GPU_PRIM_LINES, 8);
- immVertex2f(shdr_pos, -0.05f * x_fac, 0.0f);
- immVertex2f(shdr_pos, 0.0f, 0.05f * y_fac);
+ immVertex2f(shdr_pos, -0.05f * x_fac, 0.0f);
+ immVertex2f(shdr_pos, 0.0f, 0.05f * y_fac);
- immVertex2f(shdr_pos, 0.0f, 0.05f * y_fac);
- immVertex2f(shdr_pos, 0.05f * x_fac, 0.0f);
+ immVertex2f(shdr_pos, 0.0f, 0.05f * y_fac);
+ immVertex2f(shdr_pos, 0.05f * x_fac, 0.0f);
- immVertex2f(shdr_pos, 0.05f * x_fac, 0.0f);
- immVertex2f(shdr_pos, 0.0f, -0.05f * y_fac);
+ immVertex2f(shdr_pos, 0.05f * x_fac, 0.0f);
+ immVertex2f(shdr_pos, 0.0f, -0.05f * y_fac);
- immVertex2f(shdr_pos, 0.0f, -0.05f * y_fac);
- immVertex2f(shdr_pos, -0.05f * x_fac, 0.0f);
+ immVertex2f(shdr_pos, 0.0f, -0.05f * y_fac);
+ immVertex2f(shdr_pos, -0.05f * x_fac, 0.0f);
- immEnd();
+ immEnd();
- immUniformArray4fv("colors", (float *)(float[][4]){{1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2);
- immUniform1f("dash_width", 2.0f);
+ immUniformArray4fv(
+ "colors", (float *)(float[][4]){{1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2);
+ immUniform1f("dash_width", 2.0f);
- immBegin(GPU_PRIM_LINES, 8);
+ immBegin(GPU_PRIM_LINES, 8);
- immVertex2f(shdr_pos, -0.020f * x_fac, 0.0f);
- immVertex2f(shdr_pos, -0.1f * x_fac, 0.0f);
+ immVertex2f(shdr_pos, -0.020f * x_fac, 0.0f);
+ immVertex2f(shdr_pos, -0.1f * x_fac, 0.0f);
- immVertex2f(shdr_pos, 0.1f * x_fac, 0.0f);
- immVertex2f(shdr_pos, 0.020f * x_fac, 0.0f);
+ immVertex2f(shdr_pos, 0.1f * x_fac, 0.0f);
+ immVertex2f(shdr_pos, 0.020f * x_fac, 0.0f);
- immVertex2f(shdr_pos, 0.0f, -0.020f * y_fac);
- immVertex2f(shdr_pos, 0.0f, -0.1f * y_fac);
+ immVertex2f(shdr_pos, 0.0f, -0.020f * y_fac);
+ immVertex2f(shdr_pos, 0.0f, -0.1f * y_fac);
- immVertex2f(shdr_pos, 0.0f, 0.1f * y_fac);
- immVertex2f(shdr_pos, 0.0f, 0.020f * y_fac);
+ immVertex2f(shdr_pos, 0.0f, 0.1f * y_fac);
+ immVertex2f(shdr_pos, 0.0f, 0.020f * y_fac);
- immEnd();
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
- GPU_matrix_translate_2f(-cursor[0], -cursor[1]);
+ GPU_matrix_translate_2f(-cursor[0], -cursor[1]);
}
-static void uvedit_get_batches(
- Object *ob, SpaceImage *sima, const ToolSettings *ts,
- GPUBatch **faces, GPUBatch **edges, GPUBatch **verts, GPUBatch **facedots)
+static void uvedit_get_batches(Object *ob,
+ SpaceImage *sima,
+ const ToolSettings *ts,
+ GPUBatch **faces,
+ GPUBatch **edges,
+ GPUBatch **verts,
+ GPUBatch **facedots)
{
- int drawfaces = draw_uvs_face_check(ts);
- const bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0;
- const bool draw_faces = (sima->flag & SI_NO_DRAWFACES) == 0;
-
- *edges = DRW_mesh_batch_cache_get_edituv_edges(ob->data);
- *verts = DRW_mesh_batch_cache_get_edituv_verts(ob->data);
-
- if (drawfaces) {
- *facedots = DRW_mesh_batch_cache_get_edituv_facedots(ob->data);
- }
- else {
- *facedots = NULL;
- }
-
- if (draw_stretch && (sima->dt_uvstretch == SI_UVDT_STRETCH_AREA)) {
- *faces = DRW_mesh_batch_cache_get_edituv_faces_strech_area(ob->data);
- }
- else if (draw_stretch) {
- *faces = DRW_mesh_batch_cache_get_edituv_faces_strech_angle(ob->data);
- }
- else if (draw_faces) {
- *faces = DRW_mesh_batch_cache_get_edituv_faces(ob->data);
- }
- else {
- *faces = NULL;
- }
-
- DRW_mesh_batch_cache_create_requested(ob, ob->data, ts, false, false);
+ int drawfaces = draw_uvs_face_check(ts);
+ const bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0;
+ const bool draw_faces = (sima->flag & SI_NO_DRAWFACES) == 0;
+
+ *edges = DRW_mesh_batch_cache_get_edituv_edges(ob->data);
+ *verts = DRW_mesh_batch_cache_get_edituv_verts(ob->data);
+
+ if (drawfaces) {
+ *facedots = DRW_mesh_batch_cache_get_edituv_facedots(ob->data);
+ }
+ else {
+ *facedots = NULL;
+ }
+
+ if (draw_stretch && (sima->dt_uvstretch == SI_UVDT_STRETCH_AREA)) {
+ *faces = DRW_mesh_batch_cache_get_edituv_faces_strech_area(ob->data);
+ }
+ else if (draw_stretch) {
+ *faces = DRW_mesh_batch_cache_get_edituv_faces_strech_angle(ob->data);
+ }
+ else if (draw_faces) {
+ *faces = DRW_mesh_batch_cache_get_edituv_faces(ob->data);
+ }
+ else {
+ *faces = NULL;
+ }
+
+ DRW_mesh_batch_cache_create_requested(ob, ob->data, ts, false, false);
}
-static void draw_uvs_shadow(SpaceImage *UNUSED(sima), Scene *scene, Object *obedit, Depsgraph *depsgraph)
+static void draw_uvs_shadow(SpaceImage *UNUSED(sima),
+ Scene *scene,
+ Object *obedit,
+ Depsgraph *depsgraph)
{
- Object *eval_ob = DEG_get_evaluated_object(depsgraph, obedit);
- Mesh *me = eval_ob->data;
- float col[4];
- UI_GetThemeColor4fv(TH_UV_SHADOW, col);
-
- GPUBatch *edges = DRW_mesh_batch_cache_get_uv_edges(me);
- DRW_mesh_batch_cache_create_requested(eval_ob, me, scene->toolsettings, false, false);
-
- if (edges) {
- GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_UV_UNIFORM_COLOR);
- GPU_batch_uniform_4fv(edges, "color", col);
- GPU_batch_draw(edges);
- }
+ Object *eval_ob = DEG_get_evaluated_object(depsgraph, obedit);
+ Mesh *me = eval_ob->data;
+ float col[4];
+ UI_GetThemeColor4fv(TH_UV_SHADOW, col);
+
+ GPUBatch *edges = DRW_mesh_batch_cache_get_uv_edges(me);
+ DRW_mesh_batch_cache_create_requested(eval_ob, me, scene->toolsettings, false, false);
+
+ if (edges) {
+ GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_UV_UNIFORM_COLOR);
+ GPU_batch_uniform_4fv(edges, "color", col);
+ GPU_batch_draw(edges);
+ }
}
static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph)
{
- Object *eval_ob = DEG_get_evaluated_object(depsgraph, ob);
- Mesh *me = eval_ob->data;
- ToolSettings *ts = scene->toolsettings;
- float col[4];
- UI_GetThemeColor4fv(TH_UV_SHADOW, col);
-
- if (me->mloopuv == NULL) {
- return;
- }
-
- GPUBatch *geom = DRW_mesh_batch_cache_get_uv_edges(me);
- DRW_mesh_batch_cache_create_requested(eval_ob, me, scene->toolsettings, false, false);
-
- GPU_batch_program_set_builtin(geom, GPU_SHADER_2D_UV_UNIFORM_COLOR);
- GPU_batch_uniform_4fv(geom, "color", col);
-
- const bool do_material_masking = (ts->uv_flag & UV_SHOW_SAME_IMAGE);
- if (do_material_masking && me->mloopuv) {
- /* Render loops that have the active material. Minize draw calls. */
- MPoly *mpoly = me->mpoly;
- uint draw_start = 0;
- uint idx = 0;
- bool prev_ma_match = (mpoly->mat_nr == (eval_ob->actcol - 1));
-
- GPU_matrix_bind(geom->interface);
-
- /* TODO(fclem): If drawcall count becomes a problem in the future
- * we can use multi draw indirect drawcalls for this.
- * (not implemented in GPU module at the time of writing). */
- for (int a = 0; a < me->totpoly; a++, mpoly++) {
- bool ma_match = (mpoly->mat_nr == (eval_ob->actcol - 1));
- if (ma_match != prev_ma_match) {
- if (ma_match == false) {
- GPU_batch_draw_range_ex(geom, draw_start, idx - draw_start, false);
- }
- else {
- draw_start = idx;
- }
- }
- idx += mpoly->totloop + 1;
- prev_ma_match = ma_match;
- }
- if (prev_ma_match == true) {
- GPU_batch_draw_range_ex(geom, draw_start, idx - draw_start, false);
- }
-
- GPU_batch_program_use_end(geom);
- }
- else {
- GPU_batch_draw(geom);
- }
+ Object *eval_ob = DEG_get_evaluated_object(depsgraph, ob);
+ Mesh *me = eval_ob->data;
+ ToolSettings *ts = scene->toolsettings;
+ float col[4];
+ UI_GetThemeColor4fv(TH_UV_SHADOW, col);
+
+ if (me->mloopuv == NULL) {
+ return;
+ }
+
+ GPUBatch *geom = DRW_mesh_batch_cache_get_uv_edges(me);
+ DRW_mesh_batch_cache_create_requested(eval_ob, me, scene->toolsettings, false, false);
+
+ GPU_batch_program_set_builtin(geom, GPU_SHADER_2D_UV_UNIFORM_COLOR);
+ GPU_batch_uniform_4fv(geom, "color", col);
+
+ const bool do_material_masking = (ts->uv_flag & UV_SHOW_SAME_IMAGE);
+ if (do_material_masking && me->mloopuv) {
+ /* Render loops that have the active material. Minize draw calls. */
+ MPoly *mpoly = me->mpoly;
+ uint draw_start = 0;
+ uint idx = 0;
+ bool prev_ma_match = (mpoly->mat_nr == (eval_ob->actcol - 1));
+
+ GPU_matrix_bind(geom->interface);
+
+ /* TODO(fclem): If drawcall count becomes a problem in the future
+ * we can use multi draw indirect drawcalls for this.
+ * (not implemented in GPU module at the time of writing). */
+ for (int a = 0; a < me->totpoly; a++, mpoly++) {
+ bool ma_match = (mpoly->mat_nr == (eval_ob->actcol - 1));
+ if (ma_match != prev_ma_match) {
+ if (ma_match == false) {
+ GPU_batch_draw_range_ex(geom, draw_start, idx - draw_start, false);
+ }
+ else {
+ draw_start = idx;
+ }
+ }
+ idx += mpoly->totloop + 1;
+ prev_ma_match = ma_match;
+ }
+ if (prev_ma_match == true) {
+ GPU_batch_draw_range_ex(geom, draw_start, idx - draw_start, false);
+ }
+
+ GPU_batch_program_use_end(geom);
+ }
+ else {
+ GPU_batch_draw(geom);
+ }
}
/* draws uv's in the image space */
static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph *depsgraph)
{
- GPUBatch *faces, *edges, *verts, *facedots;
- Object *eval_ob = DEG_get_evaluated_object(depsgraph, obedit);
- const ToolSettings *ts = scene->toolsettings;
- float col1[4], col2[4], col3[4], transparent[4] = {0.0f, 0.0f, 0.0f, 0.0f};
-
- if (sima->flag & SI_DRAWSHADOW) {
- bool is_cage_like_final_meshes = false;
- Mesh *me = (Mesh *)eval_ob->data;
- BMEditMesh *embm = me->edit_mesh;
- is_cage_like_final_meshes = embm &&
- embm->mesh_eval_final &&
- embm->mesh_eval_final->runtime.is_original;
-
- /* When sync selection is enabled, all faces are drawn (except for hidden)
- * so if cage is the same as the final, there is no point in drawing this. */
- if (!((ts->uv_flag & UV_SYNC_SELECTION) && is_cage_like_final_meshes)) {
- draw_uvs_shadow(sima, scene, obedit, depsgraph);
- }
- }
-
- uvedit_get_batches(
- eval_ob, sima, ts,
- &faces, &edges, &verts, &facedots);
-
-
- bool interpedges;
- bool do_elem_order_fix = (ts->uv_flag & UV_SYNC_SELECTION) && (ts->selectmode & SCE_SELECT_FACE);
- bool do_selected_edges = ((sima->flag & SI_NO_DRAWEDGES) == 0);
- bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0;
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- interpedges = (ts->selectmode & SCE_SELECT_VERTEX) != 0;
- }
- else {
- interpedges = (ts->uv_selectmode == UV_SELECT_VERTEX);
- }
-
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- if (faces) {
- GPU_batch_program_set_builtin(faces, (draw_stretch)
- ? (sima->dt_uvstretch == SI_UVDT_STRETCH_AREA)
- ? GPU_SHADER_2D_UV_FACES_STRETCH_AREA
- : GPU_SHADER_2D_UV_FACES_STRETCH_ANGLE
- : GPU_SHADER_2D_UV_FACES);
-
- if (!draw_stretch) {
- GPU_blend(true);
-
- UI_GetThemeColor4fv(TH_FACE, col1);
- UI_GetThemeColor4fv(TH_FACE_SELECT, col2);
- UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, col3);
- col3[3] *= 0.2; /* Simulate dithering */
- GPU_batch_uniform_4fv(faces, "faceColor", col1);
- GPU_batch_uniform_4fv(faces, "selectColor", col2);
- GPU_batch_uniform_4fv(faces, "activeColor", col3);
- }
- else if (sima->dt_uvstretch == SI_UVDT_STRETCH_ANGLE) {
- float asp[2];
- ED_space_image_get_uv_aspect(sima, &asp[0], &asp[1]);
- GPU_batch_uniform_2fv(faces, "aspect", asp);
- }
-
- GPU_batch_draw(faces);
-
- if (!draw_stretch) {
- GPU_blend(false);
- }
- }
- if (edges) {
- if (sima->flag & SI_SMOOTH_UV) {
- GPU_line_smooth(true);
- 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 viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
-
- GPU_line_width(1.0f);
- GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- GPU_batch_uniform_4fv_array(edges, "colors", 2, (float *)dash_colors);
- GPU_batch_uniform_2f(edges, "viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
- GPU_batch_uniform_1i(edges, "colors_len", 2); /* "advanced" mode */
- GPU_batch_uniform_1f(edges, "dash_width", 4.0f);
- GPU_batch_draw(edges);
- break;
- }
- case SI_UVDT_BLACK:
- case SI_UVDT_WHITE:
- {
- GPU_line_width(1.0f);
- GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_UNIFORM_COLOR);
- if (sima->dt_uv == SI_UVDT_WHITE) {
- GPU_batch_uniform_4f(edges, "color", 1.0f, 1.0f, 1.0f, 1.0f);
- }
- else {
- GPU_batch_uniform_4f(edges, "color", 0.0f, 0.0f, 0.0f, 1.0f);
- }
- GPU_batch_draw(edges);
- break;
- }
- case SI_UVDT_OUTLINE:
- {
- GPU_line_width(3.0f);
- GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_UNIFORM_COLOR);
- GPU_batch_uniform_4f(edges, "color", 0.0f, 0.0f, 0.0f, 1.0f);
- GPU_batch_draw(edges);
-
- UI_GetThemeColor4fv(TH_WIRE_EDIT, col1);
- UI_GetThemeColor4fv(TH_EDGE_SELECT, col2);
-
- /* We could modify the vbo's data filling
- * instead of modifying the provoking vert. */
- glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
-
- GPU_line_width(1.0f);
- GPU_batch_program_set_builtin(edges, (interpedges)
- ? GPU_SHADER_2D_UV_EDGES_SMOOTH
- : GPU_SHADER_2D_UV_EDGES);
- GPU_batch_uniform_4fv(edges, "edgeColor", col1);
- GPU_batch_uniform_4fv(edges, "selectColor", do_selected_edges ? col2 : col1);
- GPU_batch_draw(edges);
-
- if (do_elem_order_fix && do_selected_edges) {
- /* We have problem in this mode when face order make some edges
- * appear unselected because an adjacent face is not selected and
- * render after the selected face.
- * So, to avoid sorting edges by state we just render selected edges
- * on top. A bit overkill but it's simple. */
- GPU_blend(true);
- GPU_batch_uniform_4fv(edges, "edgeColor", transparent);
- GPU_batch_uniform_4fv(edges, "selectColor", col2);
- GPU_batch_draw(edges);
- GPU_blend(false);
- }
- glProvokingVertex(GL_LAST_VERTEX_CONVENTION);
- break;
- }
- }
- if (sima->flag & SI_SMOOTH_UV) {
- GPU_line_smooth(false);
- GPU_blend(false);
- }
- }
- if (verts || facedots) {
- float pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
- UI_GetThemeColor4fv(TH_VERTEX_SELECT, col2);
- if (verts) {
- float pinned_col[4] = {1.0f, 0.0f, 0.0f, 1.0f}; /* TODO Theme? */
- UI_GetThemeColor4fv(TH_VERTEX, col1);
- GPU_blend(true);
- GPU_enable_program_point_size();
-
- GPU_batch_program_set_builtin(verts, GPU_SHADER_2D_UV_VERTS);
- GPU_batch_uniform_4f(verts, "vertColor", col1[0], col1[1], col1[2], 1.0f);
- GPU_batch_uniform_4fv(verts, "selectColor", (do_elem_order_fix) ? transparent : col2);
- GPU_batch_uniform_4fv(verts, "pinnedColor", pinned_col);
- GPU_batch_uniform_1f(verts, "pointSize", (pointsize + 1.5f) * M_SQRT2);
- GPU_batch_uniform_1f(verts, "outlineWidth", 0.75f);
- GPU_batch_draw(verts);
-
- if (do_elem_order_fix) {
- /* We have problem in this mode when face order make some verts
- * appear unselected because an adjacent face is not selected and
- * render after the selected face.
- * So, to avoid sorting verts by state we just render selected verts
- * on top. A bit overkill but it's simple. */
- GPU_batch_uniform_4fv(verts, "vertColor", transparent);
- GPU_batch_uniform_4fv(verts, "selectColor", col2);
- GPU_batch_uniform_4fv(verts, "pinnedColor", pinned_col);
- GPU_batch_uniform_1f(verts, "pointSize", (pointsize + 1.5f) * M_SQRT2);
- GPU_batch_uniform_1f(verts, "outlineWidth", 0.75f);
- GPU_batch_draw(verts);
- }
-
- GPU_blend(false);
- GPU_disable_program_point_size();
- }
- if (facedots) {
- GPU_point_size(pointsize);
-
- UI_GetThemeColor4fv(TH_WIRE, col1);
- GPU_batch_program_set_builtin(facedots, GPU_SHADER_2D_UV_FACEDOTS);
- GPU_batch_uniform_4fv(facedots, "vertColor", col1);
- GPU_batch_uniform_4fv(facedots, "selectColor", col2);
- GPU_batch_draw(facedots);
- }
- }
+ GPUBatch *faces, *edges, *verts, *facedots;
+ Object *eval_ob = DEG_get_evaluated_object(depsgraph, obedit);
+ const ToolSettings *ts = scene->toolsettings;
+ float col1[4], col2[4], col3[4], transparent[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ if (sima->flag & SI_DRAWSHADOW) {
+ bool is_cage_like_final_meshes = false;
+ Mesh *me = (Mesh *)eval_ob->data;
+ BMEditMesh *embm = me->edit_mesh;
+ is_cage_like_final_meshes = embm && embm->mesh_eval_final &&
+ embm->mesh_eval_final->runtime.is_original;
+
+ /* When sync selection is enabled, all faces are drawn (except for hidden)
+ * so if cage is the same as the final, there is no point in drawing this. */
+ if (!((ts->uv_flag & UV_SYNC_SELECTION) && is_cage_like_final_meshes)) {
+ draw_uvs_shadow(sima, scene, obedit, depsgraph);
+ }
+ }
+
+ uvedit_get_batches(eval_ob, sima, ts, &faces, &edges, &verts, &facedots);
+
+ bool interpedges;
+ bool do_elem_order_fix = (ts->uv_flag & UV_SYNC_SELECTION) && (ts->selectmode & SCE_SELECT_FACE);
+ bool do_selected_edges = ((sima->flag & SI_NO_DRAWEDGES) == 0);
+ bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0;
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ interpedges = (ts->selectmode & SCE_SELECT_VERTEX) != 0;
+ }
+ else {
+ interpedges = (ts->uv_selectmode == UV_SELECT_VERTEX);
+ }
+
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ if (faces) {
+ GPU_batch_program_set_builtin(faces,
+ (draw_stretch) ? (sima->dt_uvstretch == SI_UVDT_STRETCH_AREA) ?
+ GPU_SHADER_2D_UV_FACES_STRETCH_AREA :
+ GPU_SHADER_2D_UV_FACES_STRETCH_ANGLE :
+ GPU_SHADER_2D_UV_FACES);
+
+ if (!draw_stretch) {
+ GPU_blend(true);
+
+ UI_GetThemeColor4fv(TH_FACE, col1);
+ UI_GetThemeColor4fv(TH_FACE_SELECT, col2);
+ UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, col3);
+ col3[3] *= 0.2; /* Simulate dithering */
+ GPU_batch_uniform_4fv(faces, "faceColor", col1);
+ GPU_batch_uniform_4fv(faces, "selectColor", col2);
+ GPU_batch_uniform_4fv(faces, "activeColor", col3);
+ }
+ else if (sima->dt_uvstretch == SI_UVDT_STRETCH_ANGLE) {
+ float asp[2];
+ ED_space_image_get_uv_aspect(sima, &asp[0], &asp[1]);
+ GPU_batch_uniform_2fv(faces, "aspect", asp);
+ }
+
+ GPU_batch_draw(faces);
+
+ if (!draw_stretch) {
+ GPU_blend(false);
+ }
+ }
+ if (edges) {
+ if (sima->flag & SI_SMOOTH_UV) {
+ GPU_line_smooth(true);
+ 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 viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+
+ GPU_line_width(1.0f);
+ GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ GPU_batch_uniform_4fv_array(edges, "colors", 2, (float *)dash_colors);
+ GPU_batch_uniform_2f(
+ edges, "viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+ GPU_batch_uniform_1i(edges, "colors_len", 2); /* "advanced" mode */
+ GPU_batch_uniform_1f(edges, "dash_width", 4.0f);
+ GPU_batch_draw(edges);
+ break;
+ }
+ case SI_UVDT_BLACK:
+ case SI_UVDT_WHITE: {
+ GPU_line_width(1.0f);
+ GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_UNIFORM_COLOR);
+ if (sima->dt_uv == SI_UVDT_WHITE) {
+ GPU_batch_uniform_4f(edges, "color", 1.0f, 1.0f, 1.0f, 1.0f);
+ }
+ else {
+ GPU_batch_uniform_4f(edges, "color", 0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ GPU_batch_draw(edges);
+ break;
+ }
+ case SI_UVDT_OUTLINE: {
+ GPU_line_width(3.0f);
+ GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_UNIFORM_COLOR);
+ GPU_batch_uniform_4f(edges, "color", 0.0f, 0.0f, 0.0f, 1.0f);
+ GPU_batch_draw(edges);
+
+ UI_GetThemeColor4fv(TH_WIRE_EDIT, col1);
+ UI_GetThemeColor4fv(TH_EDGE_SELECT, col2);
+
+ /* We could modify the vbo's data filling
+ * instead of modifying the provoking vert. */
+ glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
+
+ GPU_line_width(1.0f);
+ GPU_batch_program_set_builtin(
+ edges, (interpedges) ? GPU_SHADER_2D_UV_EDGES_SMOOTH : GPU_SHADER_2D_UV_EDGES);
+ GPU_batch_uniform_4fv(edges, "edgeColor", col1);
+ GPU_batch_uniform_4fv(edges, "selectColor", do_selected_edges ? col2 : col1);
+ GPU_batch_draw(edges);
+
+ if (do_elem_order_fix && do_selected_edges) {
+ /* We have problem in this mode when face order make some edges
+ * appear unselected because an adjacent face is not selected and
+ * render after the selected face.
+ * So, to avoid sorting edges by state we just render selected edges
+ * on top. A bit overkill but it's simple. */
+ GPU_blend(true);
+ GPU_batch_uniform_4fv(edges, "edgeColor", transparent);
+ GPU_batch_uniform_4fv(edges, "selectColor", col2);
+ GPU_batch_draw(edges);
+ GPU_blend(false);
+ }
+ glProvokingVertex(GL_LAST_VERTEX_CONVENTION);
+ break;
+ }
+ }
+ if (sima->flag & SI_SMOOTH_UV) {
+ GPU_line_smooth(false);
+ GPU_blend(false);
+ }
+ }
+ if (verts || facedots) {
+ float pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, col2);
+ if (verts) {
+ float pinned_col[4] = {1.0f, 0.0f, 0.0f, 1.0f}; /* TODO Theme? */
+ UI_GetThemeColor4fv(TH_VERTEX, col1);
+ GPU_blend(true);
+ GPU_enable_program_point_size();
+
+ GPU_batch_program_set_builtin(verts, GPU_SHADER_2D_UV_VERTS);
+ GPU_batch_uniform_4f(verts, "vertColor", col1[0], col1[1], col1[2], 1.0f);
+ GPU_batch_uniform_4fv(verts, "selectColor", (do_elem_order_fix) ? transparent : col2);
+ GPU_batch_uniform_4fv(verts, "pinnedColor", pinned_col);
+ GPU_batch_uniform_1f(verts, "pointSize", (pointsize + 1.5f) * M_SQRT2);
+ GPU_batch_uniform_1f(verts, "outlineWidth", 0.75f);
+ GPU_batch_draw(verts);
+
+ if (do_elem_order_fix) {
+ /* We have problem in this mode when face order make some verts
+ * appear unselected because an adjacent face is not selected and
+ * render after the selected face.
+ * So, to avoid sorting verts by state we just render selected verts
+ * on top. A bit overkill but it's simple. */
+ GPU_batch_uniform_4fv(verts, "vertColor", transparent);
+ GPU_batch_uniform_4fv(verts, "selectColor", col2);
+ GPU_batch_uniform_4fv(verts, "pinnedColor", pinned_col);
+ GPU_batch_uniform_1f(verts, "pointSize", (pointsize + 1.5f) * M_SQRT2);
+ GPU_batch_uniform_1f(verts, "outlineWidth", 0.75f);
+ GPU_batch_draw(verts);
+ }
+
+ GPU_blend(false);
+ GPU_disable_program_point_size();
+ }
+ if (facedots) {
+ GPU_point_size(pointsize);
+
+ UI_GetThemeColor4fv(TH_WIRE, col1);
+ GPU_batch_program_set_builtin(facedots, GPU_SHADER_2D_UV_FACEDOTS);
+ GPU_batch_uniform_4fv(facedots, "vertColor", col1);
+ GPU_batch_uniform_4fv(facedots, "selectColor", col2);
+ GPU_batch_draw(facedots);
+ }
+ }
}
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 *show_shadow, bool *show_texpaint)
{
- *show_shadow = *show_texpaint = false;
+ *show_shadow = *show_texpaint = false;
- if (ED_space_image_show_render(sima) || (sima->flag & SI_NO_DRAW_TEXPAINT))
- return;
+ if (ED_space_image_show_render(sima) || (sima->flag & SI_NO_DRAW_TEXPAINT))
+ return;
- if ((sima->mode == SI_MODE_PAINT) && obedit && obedit->type == OB_MESH) {
- struct BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ 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);
- }
+ *show_shadow = EDBM_uv_check(em);
+ }
- *show_texpaint = (ob && ob->type == OB_MESH && ob->mode == OB_MODE_TEXTURE_PAINT);
+ *show_texpaint = (ob && ob->type == OB_MESH && ob->mode == OB_MODE_TEXTURE_PAINT);
}
-void ED_uvedit_draw_main(
- SpaceImage *sima,
- ARegion *ar, Scene *scene, ViewLayer *view_layer, Object *obedit, Object *obact, Depsgraph *depsgraph)
+void ED_uvedit_draw_main(SpaceImage *sima,
+ ARegion *ar,
+ Scene *scene,
+ ViewLayer *view_layer,
+ Object *obedit,
+ Object *obact,
+ Depsgraph *depsgraph)
{
- ToolSettings *toolsettings = scene->toolsettings;
- bool show_uvedit, show_uvshadow, show_texpaint_uvshadow;
-
- show_uvedit = ED_space_image_show_uvedit(sima, obedit);
- draw_uv_shadows_get(sima, obact, obedit, &show_uvshadow, &show_texpaint_uvshadow);
-
- if (show_uvedit || show_uvshadow || show_texpaint_uvshadow) {
- if (show_uvshadow) {
- draw_uvs_shadow(sima, scene, obedit, depsgraph);
- }
- else if (show_uvedit) {
- 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 *ob_iter = objects[ob_index];
- draw_uvs(sima, scene, ob_iter, depsgraph);
- }
- MEM_freeN(objects);
- }
- else {
- draw_uvs_texpaint(scene, obact, depsgraph);
- }
-
- if (show_uvedit && !(toolsettings->use_uv_sculpt))
- ED_image_draw_cursor(ar, sima->cursor);
- }
+ ToolSettings *toolsettings = scene->toolsettings;
+ bool show_uvedit, show_uvshadow, show_texpaint_uvshadow;
+
+ show_uvedit = ED_space_image_show_uvedit(sima, obedit);
+ draw_uv_shadows_get(sima, obact, obedit, &show_uvshadow, &show_texpaint_uvshadow);
+
+ if (show_uvedit || show_uvshadow || show_texpaint_uvshadow) {
+ if (show_uvshadow) {
+ draw_uvs_shadow(sima, scene, obedit, depsgraph);
+ }
+ else if (show_uvedit) {
+ 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 *ob_iter = objects[ob_index];
+ draw_uvs(sima, scene, ob_iter, depsgraph);
+ }
+ MEM_freeN(objects);
+ }
+ else {
+ draw_uvs_texpaint(scene, obact, depsgraph);
+ }
+
+ if (show_uvedit && !(toolsettings->use_uv_sculpt))
+ ED_image_draw_cursor(ar, sima->cursor);
+ }
}
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index 5510549ba0e..3f544ad90d1 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -21,7 +21,6 @@
* \ingroup eduv
*/
-
#ifndef __UVEDIT_INTERN_H__
#define __UVEDIT_INTERN_H__
@@ -35,50 +34,72 @@ struct SpaceImage;
struct wmOperatorType;
/* geometric utilities */
-void uv_poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len);
-void uv_poly_center(struct BMFace *f, float r_cent[2], const int cd_loop_uv_offset);
+void uv_poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len);
+void uv_poly_center(struct BMFace *f, float r_cent[2], const int cd_loop_uv_offset);
/* find nearest */
typedef struct UvNearestHit {
- /** Only for `*_multi(..)` versions of functions. */
- struct Object *ob;
- /** Always set if we have a hit. */
- struct BMFace *efa;
- struct BMLoop *l;
- struct MLoopUV *luv, *luv_next;
- /** Index of loop within face. */
- int lindex;
- /** Needs to be set before calling nearest functions. */
- float dist_sq;
+ /** Only for `*_multi(..)` versions of functions. */
+ struct Object *ob;
+ /** Always set if we have a hit. */
+ struct BMFace *efa;
+ struct BMLoop *l;
+ struct MLoopUV *luv, *luv_next;
+ /** Index of loop within face. */
+ int lindex;
+ /** Needs to be set before calling nearest functions. */
+ float dist_sq;
} UvNearestHit;
-#define UV_NEAREST_HIT_INIT { .dist_sq = FLT_MAX, }
-
-bool uv_find_nearest_vert(
- struct Scene *scene, struct Image *ima, struct Object *obedit,
- const float co[2], const float penalty_dist, struct UvNearestHit *hit_final);
-bool uv_find_nearest_vert_multi(
- struct Scene *scene, struct Image *ima, struct Object **objects, const uint objects_len,
- const float co[2], const float penalty_dist, struct UvNearestHit *hit_final);
-
-bool uv_find_nearest_edge(
- struct Scene *scene, struct Image *ima, struct Object *obedit,
- const float co[2], struct UvNearestHit *hit_final);
-bool uv_find_nearest_edge_multi(
- struct Scene *scene, struct Image *ima, struct Object **objects, const uint objects_len,
- const float co[2], struct UvNearestHit *hit_final);
-
-bool uv_find_nearest_face(
- struct Scene *scene, struct Image *ima, struct Object *obedit,
- const float co[2], struct UvNearestHit *hit_final);
-bool uv_find_nearest_face_multi(
- struct Scene *scene, struct Image *ima, struct Object **objects, const uint objects_len,
- const float co[2], struct UvNearestHit *hit_final);
+#define UV_NEAREST_HIT_INIT \
+ { \
+ .dist_sq = FLT_MAX, \
+ }
+
+bool uv_find_nearest_vert(struct Scene *scene,
+ struct Image *ima,
+ struct Object *obedit,
+ const float co[2],
+ const float penalty_dist,
+ struct UvNearestHit *hit_final);
+bool uv_find_nearest_vert_multi(struct Scene *scene,
+ struct Image *ima,
+ struct Object **objects,
+ const uint objects_len,
+ const float co[2],
+ const float penalty_dist,
+ struct UvNearestHit *hit_final);
+
+bool uv_find_nearest_edge(struct Scene *scene,
+ struct Image *ima,
+ struct Object *obedit,
+ const float co[2],
+ struct UvNearestHit *hit_final);
+bool uv_find_nearest_edge_multi(struct Scene *scene,
+ struct Image *ima,
+ struct Object **objects,
+ const uint objects_len,
+ const float co[2],
+ struct UvNearestHit *hit_final);
+
+bool uv_find_nearest_face(struct Scene *scene,
+ struct Image *ima,
+ struct Object *obedit,
+ const float co[2],
+ struct UvNearestHit *hit_final);
+bool uv_find_nearest_face_multi(struct Scene *scene,
+ struct Image *ima,
+ struct Object **objects,
+ const uint objects_len,
+ const float co[2],
+ struct UvNearestHit *hit_final);
/* utility tool functions */
-void uvedit_live_unwrap_update(struct SpaceImage *sima, struct Scene *scene, struct Object *obedit);
+void uvedit_live_unwrap_update(struct SpaceImage *sima,
+ struct Scene *scene,
+ struct Object *obedit);
/* operators */
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 1bcf60077ff..291dbdf6942 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -21,7 +21,6 @@
* \ingroup eduv
*/
-
#include <stdlib.h>
#include <string.h>
#include <math.h>
@@ -87,12 +86,24 @@
#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 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);
+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
@@ -100,42 +111,42 @@ static void uv_select_tag_update_for_object(Depsgraph *depsgraph, const ToolSett
bool ED_uvedit_test(Object *obedit)
{
- BMEditMesh *em;
- int ret;
+ BMEditMesh *em;
+ int ret;
- if (!obedit)
- return 0;
+ if (!obedit)
+ return 0;
- if (obedit->type != OB_MESH)
- return 0;
+ if (obedit->type != OB_MESH)
+ return 0;
- em = BKE_editmesh_from_object(obedit);
- ret = EDBM_uv_check(em);
+ em = BKE_editmesh_from_object(obedit);
+ ret = EDBM_uv_check(em);
- return ret;
+ return ret;
}
static bool ED_operator_uvedit_can_uv_sculpt(struct bContext *C)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- ToolSettings *toolsettings = CTX_data_tool_settings(C);
- Object *obedit = CTX_data_edit_object(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ToolSettings *toolsettings = CTX_data_tool_settings(C);
+ Object *obedit = CTX_data_edit_object(C);
- return ED_space_image_show_uvedit(sima, obedit) && !(toolsettings->use_uv_sculpt);
+ return ED_space_image_show_uvedit(sima, obedit) && !(toolsettings->use_uv_sculpt);
}
-static int UNUSED_FUNCTION(ED_operator_uvmap_mesh) (bContext *C)
+static int UNUSED_FUNCTION(ED_operator_uvmap_mesh)(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if (ob && ob->type == OB_MESH) {
- Mesh *me = ob->data;
+ if (ob && ob->type == OB_MESH) {
+ Mesh *me = ob->data;
- if (CustomData_get_layer(&me->fdata, CD_MTFACE) != NULL)
- return 1;
- }
+ if (CustomData_get_layer(&me->fdata, CD_MTFACE) != NULL)
+ return 1;
+ }
- return 0;
+ return 0;
}
/** \} */
@@ -146,52 +157,62 @@ static int UNUSED_FUNCTION(ED_operator_uvmap_mesh) (bContext *C)
static bool is_image_texture_node(bNode *node)
{
- return ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT);
-}
-
-bool ED_object_get_active_image(
- Object *ob, int mat_nr,
- Image **r_ima, ImageUser **r_iuser, bNode **r_node, bNodeTree **r_ntree)
-{
- Material *ma = give_current_material(ob, mat_nr);
- bNodeTree *ntree = (ma && ma->use_nodes) ? ma->nodetree : NULL;
- bNode *node = (ntree) ? nodeGetActiveTexture(ntree) : NULL;
-
- if (node && is_image_texture_node(node)) {
- if (r_ima) *r_ima = (Image *)node->id;
- if (r_iuser) {
- if (node->type == SH_NODE_TEX_IMAGE) {
- *r_iuser = &((NodeTexImage *)node->storage)->iuser;
- }
- else if (node->type == SH_NODE_TEX_ENVIRONMENT) {
- *r_iuser = &((NodeTexEnvironment *)node->storage)->iuser;
- }
- else {
- *r_iuser = NULL;
- }
- }
- if (r_node) *r_node = node;
- if (r_ntree) *r_ntree = ntree;
- return true;
- }
-
- if (r_ima) *r_ima = NULL;
- if (r_iuser) *r_iuser = NULL;
- if (r_node) *r_node = node;
- if (r_ntree) *r_ntree = ntree;
-
- return false;
+ return ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT);
+}
+
+bool ED_object_get_active_image(Object *ob,
+ int mat_nr,
+ Image **r_ima,
+ ImageUser **r_iuser,
+ bNode **r_node,
+ bNodeTree **r_ntree)
+{
+ Material *ma = give_current_material(ob, mat_nr);
+ bNodeTree *ntree = (ma && ma->use_nodes) ? ma->nodetree : NULL;
+ bNode *node = (ntree) ? nodeGetActiveTexture(ntree) : NULL;
+
+ if (node && is_image_texture_node(node)) {
+ if (r_ima)
+ *r_ima = (Image *)node->id;
+ if (r_iuser) {
+ if (node->type == SH_NODE_TEX_IMAGE) {
+ *r_iuser = &((NodeTexImage *)node->storage)->iuser;
+ }
+ else if (node->type == SH_NODE_TEX_ENVIRONMENT) {
+ *r_iuser = &((NodeTexEnvironment *)node->storage)->iuser;
+ }
+ else {
+ *r_iuser = NULL;
+ }
+ }
+ if (r_node)
+ *r_node = node;
+ if (r_ntree)
+ *r_ntree = ntree;
+ return true;
+ }
+
+ if (r_ima)
+ *r_ima = NULL;
+ if (r_iuser)
+ *r_iuser = NULL;
+ if (r_node)
+ *r_node = node;
+ if (r_ntree)
+ *r_ntree = ntree;
+
+ return false;
}
void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *ima)
{
- Material *ma = give_current_material(ob, mat_nr);
- bNode *node = (ma && ma->use_nodes) ? nodeGetActiveTexture(ma->nodetree) : NULL;
+ Material *ma = give_current_material(ob, mat_nr);
+ bNode *node = (ma && ma->use_nodes) ? nodeGetActiveTexture(ma->nodetree) : NULL;
- if (node && is_image_texture_node(node)) {
- node->id = &ima->id;
- ED_node_tag_update_nodetree(bmain, ma->nodetree, node);
- }
+ if (node && is_image_texture_node(node)) {
+ node->id = &ima->id;
+ ED_node_tag_update_nodetree(bmain, ma->nodetree, node);
+ }
}
/** \} */
@@ -202,18 +223,18 @@ void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *i
static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist)
{
- int width, height;
+ int width, height;
- if (sima) {
- ED_space_image_get_size(sima, &width, &height);
- }
- else {
- width = IMG_SIZE_FALLBACK;
- height = IMG_SIZE_FALLBACK;
- }
+ if (sima) {
+ ED_space_image_get_size(sima, &width, &height);
+ }
+ else {
+ width = IMG_SIZE_FALLBACK;
+ height = IMG_SIZE_FALLBACK;
+ }
- dist[0] = pixeldist / width;
- dist[1] = pixeldist / height;
+ dist[0] = pixeldist / width;
+ dist[1] = pixeldist / height;
}
/** \} */
@@ -222,313 +243,316 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist
/** \name Visibility and Selection Utilities
* \{ */
-static void uvedit_vertex_select_tagged(BMEditMesh *em, Scene *scene, bool select, int cd_loop_uv_offset)
+static void uvedit_vertex_select_tagged(BMEditMesh *em,
+ Scene *scene,
+ bool select,
+ int cd_loop_uv_offset)
{
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
+ 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);
- }
- }
- }
+ 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));
+ 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(Scene *scene, BMFace *efa)
{
- return uvedit_face_visible_nolocal_ex(scene->toolsettings, 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);
- }
+ 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(Scene *scene, Object *obedit, Image *ima, BMFace *efa)
{
- return uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa);
+ return uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa);
}
-bool uvedit_face_select_test_ex(
- const ToolSettings *ts, BMFace *efa,
- const int cd_loop_uv_offset)
+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;
+ 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;
- }
+ 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;
- }
+ return true;
+ }
}
bool uvedit_face_select_test(Scene *scene, BMFace *efa, const int cd_loop_uv_offset)
{
- return uvedit_face_select_test_ex(scene->toolsettings, efa, cd_loop_uv_offset);
+ return uvedit_face_select_test_ex(scene->toolsettings, efa, cd_loop_uv_offset);
}
-bool uvedit_face_select_set(
- struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa, const bool select,
- const bool do_history, const int cd_loop_uv_offset)
+bool uvedit_face_select_set(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);
- }
+ 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(
- Scene *scene, BMEditMesh *em, BMFace *efa, const bool do_history,
- const int cd_loop_uv_offset)
-{
- 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(
- Scene *scene, BMEditMesh *em, BMFace *efa,
- const int cd_loop_uv_offset)
-{
- 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);
- }
+ Scene *scene, BMEditMesh *em, BMFace *efa, const bool do_history, const int cd_loop_uv_offset)
+{
+ 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(Scene *scene,
+ BMEditMesh *em,
+ BMFace *efa,
+ const int cd_loop_uv_offset)
+{
+ 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(Scene *scene, BMLoop *l, const int cd_loop_uv_offset)
{
- return uvedit_edge_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset);
+ return uvedit_edge_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset);
}
-void uvedit_edge_select_set(
- BMEditMesh *em, Scene *scene, BMLoop *l, const bool select,
- const bool do_history, const int cd_loop_uv_offset)
+void uvedit_edge_select_set(BMEditMesh *em,
+ 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);
- }
+ 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, Scene *scene, BMLoop *l, const bool do_history,
- const int cd_loop_uv_offset)
-
-{
- 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, Scene *scene, BMLoop *l,
- const int cd_loop_uv_offset)
-
-{
- 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;
- }
+ BMEditMesh *em, Scene *scene, BMLoop *l, const bool do_history, const int cd_loop_uv_offset)
+
+{
+ 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,
+ Scene *scene,
+ BMLoop *l,
+ const int cd_loop_uv_offset)
+
+{
+ 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(Scene *scene, BMLoop *l, const int cd_loop_uv_offset)
{
- return uvedit_uv_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset);
+ return uvedit_uv_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset);
}
-void uvedit_uv_select_set(
- BMEditMesh *em, Scene *scene, BMLoop *l, const bool select,
- const bool do_history, const int cd_loop_uv_offset)
+void uvedit_uv_select_set(BMEditMesh *em,
+ 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);
- }
+ 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, Scene *scene, BMLoop *l,
- const bool do_history, const int cd_loop_uv_offset)
+ BMEditMesh *em, Scene *scene, BMLoop *l, const bool do_history, const int cd_loop_uv_offset)
{
- ToolSettings *ts = scene->toolsettings;
+ 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 (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;
- }
+ 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, Scene *scene, BMLoop *l,
- const int cd_loop_uv_offset)
+void uvedit_uv_select_disable(BMEditMesh *em, Scene *scene, BMLoop *l, const int cd_loop_uv_offset)
{
- ToolSettings *ts = scene->toolsettings;
+ 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;
- }
+ 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;
+ }
}
/** \} */
@@ -539,11 +563,11 @@ void uvedit_uv_select_disable(
void uvedit_live_unwrap_update(SpaceImage *sima, Scene *scene, Object *obedit)
{
- if (sima && (sima->flag & SI_LIVE_UNWRAP)) {
- ED_uvedit_live_unwrap_begin(scene, obedit);
- ED_uvedit_live_unwrap_re_solve();
- ED_uvedit_live_unwrap_end(0);
- }
+ if (sima && (sima->flag & SI_LIVE_UNWRAP)) {
+ ED_uvedit_live_unwrap_begin(scene, obedit);
+ ED_uvedit_live_unwrap_re_solve();
+ ED_uvedit_live_unwrap_end(0);
+ }
}
/** \} */
@@ -554,149 +578,157 @@ void uvedit_live_unwrap_update(SpaceImage *sima, Scene *scene, Object *obedit)
void uv_poly_center(BMFace *f, float r_cent[2], const int cd_loop_uv_offset)
{
- BMLoop *l;
- MLoopUV *luv;
- BMIter liter;
+ BMLoop *l;
+ MLoopUV *luv;
+ BMIter liter;
- zero_v2(r_cent);
+ zero_v2(r_cent);
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- add_v2_v2(r_cent, luv->uv);
- }
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ add_v2_v2(r_cent, luv->uv);
+ }
- mul_v2_fl(r_cent, 1.0f / (float)f->len);
+ mul_v2_fl(r_cent, 1.0f / (float)f->len);
}
void uv_poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len)
{
- int i;
- for (i = 0; i < len; i++) {
- uv[i][0] = uv_orig[i][0] * aspx;
- uv[i][1] = uv_orig[i][1] * aspy;
- }
+ int i;
+ for (i = 0; i < len; i++) {
+ uv[i][0] = uv_orig[i][0] * aspx;
+ uv[i][1] = uv_orig[i][1] * aspy;
+ }
}
-bool ED_uvedit_minmax_multi(
- Scene *scene, Image *ima, Object **objects_edit, uint objects_len,
- float r_min[2], float r_max[2])
+bool ED_uvedit_minmax_multi(Scene *scene,
+ Image *ima,
+ Object **objects_edit,
+ uint objects_len,
+ float r_min[2],
+ float r_max[2])
{
- bool changed = false;
- INIT_MINMAX2(r_min, r_max);
+ bool changed = false;
+ INIT_MINMAX2(r_min, r_max);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects_edit[ob_index];
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects_edit[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
+ 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);
+ 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_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 (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- minmax_v2v2_v2(r_min, r_max, luv->uv);
- changed = true;
- }
- }
- }
- }
- return changed;
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ minmax_v2v2_v2(r_min, r_max, luv->uv);
+ changed = true;
+ }
+ }
+ }
+ }
+ return changed;
}
bool ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float r_min[2], float r_max[2])
{
- return ED_uvedit_minmax_multi(scene, ima, &obedit, 1, r_min, r_max);
+ return ED_uvedit_minmax_multi(scene, ima, &obedit, 1, r_min, r_max);
}
/* Be careful when using this, it bypasses all synchronization options */
void ED_uvedit_select_all(BMesh *bm)
{
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ 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 (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->flag |= MLOOPUV_VERTSEL;
- }
- }
+ BM_ITER_MESH (efa, &iter, 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);
+ luv->flag |= MLOOPUV_VERTSEL;
+ }
+ }
}
-static bool ED_uvedit_median_multi(Scene *scene, Image *ima, Object **objects_edit, uint objects_len, float co[2])
+static bool ED_uvedit_median_multi(
+ Scene *scene, Image *ima, Object **objects_edit, uint objects_len, float co[2])
{
- unsigned int sel = 0;
- zero_v2(co);
+ unsigned int sel = 0;
+ zero_v2(co);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects_edit[ob_index];
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects_edit[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
+ 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);
+ 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_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 (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- add_v2_v2(co, luv->uv);
- sel++;
- }
- }
- }
- }
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ add_v2_v2(co, luv->uv);
+ sel++;
+ }
+ }
+ }
+ }
- mul_v2_fl(co, 1.0f / (float)sel);
+ mul_v2_fl(co, 1.0f / (float)sel);
- return (sel != 0);
+ return (sel != 0);
}
-static bool UNUSED_FUNCTION(ED_uvedit_median)(Scene *scene, Image *ima, Object *obedit, float co[2])
+static bool UNUSED_FUNCTION(ED_uvedit_median)(Scene *scene,
+ Image *ima,
+ Object *obedit,
+ float co[2])
{
- return ED_uvedit_median_multi(scene, ima, &obedit, 1, co);
+ return ED_uvedit_median_multi(scene, ima, &obedit, 1, co);
}
-bool ED_uvedit_center_multi(Scene *scene, Image *ima, Object **objects_edit, uint objects_len, float cent[2], char mode)
+bool ED_uvedit_center_multi(
+ Scene *scene, Image *ima, Object **objects_edit, uint objects_len, float cent[2], char mode)
{
- bool changed = false;
+ bool changed = false;
- if (mode == V3D_AROUND_CENTER_BOUNDS) { /* bounding box */
- float min[2], max[2];
- if (ED_uvedit_minmax_multi(scene, ima, objects_edit, objects_len, min, max)) {
- mid_v2_v2v2(cent, min, max);
- changed = true;
- }
- }
- else {
- if (ED_uvedit_median_multi(scene, ima, objects_edit, objects_len, cent)) {
- changed = true;
- }
- }
+ if (mode == V3D_AROUND_CENTER_BOUNDS) { /* bounding box */
+ float min[2], max[2];
+ if (ED_uvedit_minmax_multi(scene, ima, objects_edit, objects_len, min, max)) {
+ mid_v2_v2v2(cent, min, max);
+ changed = true;
+ }
+ }
+ else {
+ if (ED_uvedit_median_multi(scene, ima, objects_edit, objects_len, cent)) {
+ changed = true;
+ }
+ }
- return changed;
+ return changed;
}
bool ED_uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], char mode)
{
- return ED_uvedit_center_multi(scene, ima, &obedit, 1, cent, mode);
+ return ED_uvedit_center_multi(scene, ima, &obedit, 1, cent, mode);
}
/** \} */
@@ -706,264 +738,278 @@ bool ED_uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], c
* \{ */
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;
+ 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)
+ 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;
+ 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(
- 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(
- 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;
+ 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(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;
}
/** \} */
@@ -974,185 +1020,192 @@ bool ED_uvedit_nearest_uv_multi(
static void uv_select_edgeloop_vertex_loop_flag(UvMapVert *first)
{
- UvMapVert *iterv;
- int count = 0;
+ UvMapVert *iterv;
+ int count = 0;
- for (iterv = first; iterv; iterv = iterv->next) {
- if (iterv->separate && iterv != first)
- break;
+ for (iterv = first; iterv; iterv = iterv->next) {
+ if (iterv->separate && iterv != first)
+ break;
- count++;
- }
+ count++;
+ }
- if (count < 5)
- first->flag = 1;
+ 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 *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;
+ 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;
}
/** \} */
@@ -1161,203 +1214,212 @@ static int uv_select_edgeloop(
/** \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)
- return;
-
- 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;
- }
- }
- }
- }
+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)
+ return;
+
+ 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);
- }
- }
+ 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);
- }
+ 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)
+static float *uv_sel_co_from_eve(
+ Scene *scene, Object *obedit, Image *ima, BMEditMesh *em, BMVert *eve)
{
- BMIter liter;
- BMLoop *l;
+ BMIter liter;
+ BMLoop *l;
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ 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;
+ 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;
- }
- }
+ 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;
+ return NULL;
}
/** \} */
@@ -1368,149 +1430,149 @@ static float *uv_sel_co_from_eve(Scene *scene, Object *obedit, Image *ima, BMEdi
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);
+ 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;
- ToolSettings *ts = scene->toolsettings;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ 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);
+ 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);
+ 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;
+ bool changed = false;
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ 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);
- }
+ 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;
- }
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ continue;
+ }
- if (ts->uv_selectmode == UV_SELECT_FACE) {
+ if (ts->uv_selectmode == UV_SELECT_FACE) {
- /* clear tags */
- BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
+ /* 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)) {
+ /* 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_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;
- }
- }
+ 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) {
- /* 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;
+ }
+ }
+ }
+ 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) {
+ /* 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);
+ 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;
+ /* 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;
+ /* 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);
+ 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;
+ /* 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;
+ /* api callbacks */
+ ot->exec = uv_select_less_exec;
+ ot->poll = ED_operator_uvedit_space_image;
}
/** \} */
@@ -1520,297 +1582,308 @@ static void UV_OT_select_less(wmOperatorType *ot)
* \{ */
typedef enum eUVWeldAlign {
- UV_STRAIGHTEN,
- UV_STRAIGHTEN_X,
- UV_STRAIGHTEN_Y,
- UV_ALIGN_AUTO,
- UV_ALIGN_X,
- UV_ALIGN_Y,
- UV_WELD,
+ UV_STRAIGHTEN,
+ UV_STRAIGHTEN_X,
+ UV_STRAIGHTEN_Y,
+ UV_ALIGN_AUTO,
+ UV_ALIGN_X,
+ UV_ALIGN_Y,
+ UV_WELD,
} eUVWeldAlign;
static void uv_weld_align(bContext *C, eUVWeldAlign tool)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
- ToolSettings *ts = scene->toolsettings;
- const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
- float cent[2], min[2], max[2];
-
- INIT_MINMAX2(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);
-
- if (tool == UV_ALIGN_AUTO) {
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (synced_selection && (em->bm->totvertsel == 0)) {
- continue;
- }
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- BMIter iter, liter;
- BMFace *efa;
- BMLoop *l;
-
- 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 (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- minmax_v2v2_v2(min, max, luv->uv);
- }
- }
- }
- }
- tool = (max[0] - min[0] >= max[1] - min[1]) ? UV_ALIGN_Y : UV_ALIGN_X;
- }
-
- ED_uvedit_center_multi(scene, ima, objects, objects_len, cent, 0);
-
- 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;
-
- if (synced_selection && (em->bm->totvertsel == 0)) {
- continue;
- }
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- if (ELEM(tool, UV_ALIGN_X, UV_WELD)) {
- BMIter iter, liter;
- BMFace *efa;
- BMLoop *l;
-
- 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 (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->uv[0] = cent[0];
- changed = true;
- }
-
- }
- }
- }
-
- if (ELEM(tool, UV_ALIGN_Y, UV_WELD)) {
- BMIter iter, liter;
- BMFace *efa;
- BMLoop *l;
-
- 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 (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->uv[1] = cent[1];
- changed = true;
- }
-
- }
- }
- }
-
- if (ELEM(tool, UV_STRAIGHTEN, UV_STRAIGHTEN_X, UV_STRAIGHTEN_Y)) {
- BMEdge *eed;
- BMLoop *l;
- BMVert *eve;
- BMVert *eve_start;
- BMIter iter, liter, eiter;
-
- /* clear tag */
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
-
- /* tag verts with a selected UV */
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) {
- if (!uvedit_face_visible_test(scene, obedit, ima, l->f))
- continue;
-
- if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- BM_elem_flag_enable(eve, BM_ELEM_TAG);
- break;
- }
- }
- }
-
- /* flush vertex tags to edges */
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_set(
- eed, BM_ELEM_TAG,
- (BM_elem_flag_test(eed->v1, BM_ELEM_TAG) &&
- BM_elem_flag_test(eed->v2, BM_ELEM_TAG)));
- }
-
- /* find a vertex with only one tagged edge */
- eve_start = NULL;
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- int tot_eed_tag = 0;
- BM_ITER_ELEM (eed, &eiter, eve, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(eed, BM_ELEM_TAG)) {
- tot_eed_tag++;
- }
- }
-
- if (tot_eed_tag == 1) {
- eve_start = eve;
- break;
- }
- }
-
- if (eve_start) {
- BMVert **eve_line = NULL;
- BMVert *eve_next = NULL;
- BLI_array_declare(eve_line);
- int i;
-
- eve = eve_start;
-
- /* walk over edges, building an array of verts in a line */
- while (eve) {
- BLI_array_append(eve_line, eve);
- /* don't touch again */
- BM_elem_flag_disable(eve, BM_ELEM_TAG);
-
- eve_next = NULL;
-
- /* find next eve */
- BM_ITER_ELEM (eed, &eiter, eve, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(eed, BM_ELEM_TAG)) {
- BMVert *eve_other = BM_edge_other_vert(eed, eve);
- if (BM_elem_flag_test(eve_other, BM_ELEM_TAG)) {
- /* this is a tagged vert we didn't walk over yet, step onto it */
- eve_next = eve_other;
- break;
- }
- }
- }
-
- eve = eve_next;
- }
-
- /* now we have all verts, make into a line */
- 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]);
- /* For UV_STRAIGHTEN_X & UV_STRAIGHTEN_Y modes */
- float a = 0.0f;
- eUVWeldAlign tool_local = tool;
-
- if (tool_local == UV_STRAIGHTEN_X) {
- if (uv_start[1] == uv_end[1])
- tool_local = UV_STRAIGHTEN;
- else
- a = (uv_end[0] - uv_start[0]) / (uv_end[1] - uv_start[1]);
- }
- else if (tool_local == UV_STRAIGHTEN_Y) {
- if (uv_start[0] == uv_end[0])
- tool_local = UV_STRAIGHTEN;
- else
- a = (uv_end[1] - uv_start[1]) / (uv_end[0] - uv_start[0]);
- }
-
- /* go over all verts except for endpoints */
- for (i = 0; i < BLI_array_len(eve_line); i++) {
- BM_ITER_ELEM (l, &liter, eve_line[i], BM_LOOPS_OF_VERT) {
- if (!uvedit_face_visible_test(scene, obedit, ima, l->f))
- 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);
- /* Projection of point (x, y) over line (x1, y1, x2, y2) along X axis:
- * new_y = (y2 - y1) / (x2 - x1) * (x - x1) + y1
- * Maybe this should be a BLI func? Or is it already existing?
- * Could use interp_v2_v2v2, but not sure it's worth it here...*/
- if (tool_local == UV_STRAIGHTEN_X)
- luv->uv[0] = a * (luv->uv[1] - uv_start[1]) + uv_start[0];
- else if (tool_local == UV_STRAIGHTEN_Y)
- luv->uv[1] = a * (luv->uv[0] - uv_start[0]) + uv_start[1];
- else
- closest_to_line_segment_v2(luv->uv, luv->uv, uv_start, uv_end);
- changed = true;
- }
- }
- }
- }
- else {
- /* error - not a line, needs 3+ points */
- }
-
- if (eve_line) {
- MEM_freeN(eve_line);
- }
- }
- else {
- /* error - cant find an endpoint */
- }
- }
-
- if (changed) {
- uvedit_live_unwrap_update(sima, scene, obedit);
- DEG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- }
- }
-
- MEM_freeN(objects);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = CTX_data_edit_image(C);
+ ToolSettings *ts = scene->toolsettings;
+ const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
+ float cent[2], min[2], max[2];
+
+ INIT_MINMAX2(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);
+
+ if (tool == UV_ALIGN_AUTO) {
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (synced_selection && (em->bm->totvertsel == 0)) {
+ continue;
+ }
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ BMIter iter, liter;
+ BMFace *efa;
+ BMLoop *l;
+
+ 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 (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ minmax_v2v2_v2(min, max, luv->uv);
+ }
+ }
+ }
+ }
+ tool = (max[0] - min[0] >= max[1] - min[1]) ? UV_ALIGN_Y : UV_ALIGN_X;
+ }
+
+ ED_uvedit_center_multi(scene, ima, objects, objects_len, cent, 0);
+
+ 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;
+
+ if (synced_selection && (em->bm->totvertsel == 0)) {
+ continue;
+ }
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ if (ELEM(tool, UV_ALIGN_X, UV_WELD)) {
+ BMIter iter, liter;
+ BMFace *efa;
+ BMLoop *l;
+
+ 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 (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv->uv[0] = cent[0];
+ changed = true;
+ }
+ }
+ }
+ }
+
+ if (ELEM(tool, UV_ALIGN_Y, UV_WELD)) {
+ BMIter iter, liter;
+ BMFace *efa;
+ BMLoop *l;
+
+ 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 (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv->uv[1] = cent[1];
+ changed = true;
+ }
+ }
+ }
+ }
+
+ if (ELEM(tool, UV_STRAIGHTEN, UV_STRAIGHTEN_X, UV_STRAIGHTEN_Y)) {
+ BMEdge *eed;
+ BMLoop *l;
+ BMVert *eve;
+ BMVert *eve_start;
+ BMIter iter, liter, eiter;
+
+ /* clear tag */
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
+ /* tag verts with a selected UV */
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, l->f))
+ continue;
+
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ BM_elem_flag_enable(eve, BM_ELEM_TAG);
+ break;
+ }
+ }
+ }
+
+ /* flush vertex tags to edges */
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_set(
+ eed,
+ BM_ELEM_TAG,
+ (BM_elem_flag_test(eed->v1, BM_ELEM_TAG) && BM_elem_flag_test(eed->v2, BM_ELEM_TAG)));
+ }
+
+ /* find a vertex with only one tagged edge */
+ eve_start = NULL;
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ int tot_eed_tag = 0;
+ BM_ITER_ELEM (eed, &eiter, eve, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(eed, BM_ELEM_TAG)) {
+ tot_eed_tag++;
+ }
+ }
+
+ if (tot_eed_tag == 1) {
+ eve_start = eve;
+ break;
+ }
+ }
+
+ if (eve_start) {
+ BMVert **eve_line = NULL;
+ BMVert *eve_next = NULL;
+ BLI_array_declare(eve_line);
+ int i;
+
+ eve = eve_start;
+
+ /* walk over edges, building an array of verts in a line */
+ while (eve) {
+ BLI_array_append(eve_line, eve);
+ /* don't touch again */
+ BM_elem_flag_disable(eve, BM_ELEM_TAG);
+
+ eve_next = NULL;
+
+ /* find next eve */
+ BM_ITER_ELEM (eed, &eiter, eve, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(eed, BM_ELEM_TAG)) {
+ BMVert *eve_other = BM_edge_other_vert(eed, eve);
+ if (BM_elem_flag_test(eve_other, BM_ELEM_TAG)) {
+ /* this is a tagged vert we didn't walk over yet, step onto it */
+ eve_next = eve_other;
+ break;
+ }
+ }
+ }
+
+ eve = eve_next;
+ }
+
+ /* now we have all verts, make into a line */
+ 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]);
+ /* For UV_STRAIGHTEN_X & UV_STRAIGHTEN_Y modes */
+ float a = 0.0f;
+ eUVWeldAlign tool_local = tool;
+
+ if (tool_local == UV_STRAIGHTEN_X) {
+ if (uv_start[1] == uv_end[1])
+ tool_local = UV_STRAIGHTEN;
+ else
+ a = (uv_end[0] - uv_start[0]) / (uv_end[1] - uv_start[1]);
+ }
+ else if (tool_local == UV_STRAIGHTEN_Y) {
+ if (uv_start[0] == uv_end[0])
+ tool_local = UV_STRAIGHTEN;
+ else
+ a = (uv_end[1] - uv_start[1]) / (uv_end[0] - uv_start[0]);
+ }
+
+ /* go over all verts except for endpoints */
+ for (i = 0; i < BLI_array_len(eve_line); i++) {
+ BM_ITER_ELEM (l, &liter, eve_line[i], BM_LOOPS_OF_VERT) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, l->f))
+ 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);
+ /* Projection of point (x, y) over line (x1, y1, x2, y2) along X axis:
+ * new_y = (y2 - y1) / (x2 - x1) * (x - x1) + y1
+ * Maybe this should be a BLI func? Or is it already existing?
+ * Could use interp_v2_v2v2, but not sure it's worth it here...*/
+ if (tool_local == UV_STRAIGHTEN_X)
+ luv->uv[0] = a * (luv->uv[1] - uv_start[1]) + uv_start[0];
+ else if (tool_local == UV_STRAIGHTEN_Y)
+ luv->uv[1] = a * (luv->uv[0] - uv_start[0]) + uv_start[1];
+ else
+ closest_to_line_segment_v2(luv->uv, luv->uv, uv_start, uv_end);
+ changed = true;
+ }
+ }
+ }
+ }
+ else {
+ /* error - not a line, needs 3+ points */
+ }
+
+ if (eve_line) {
+ MEM_freeN(eve_line);
+ }
+ }
+ else {
+ /* error - cant find an endpoint */
+ }
+ }
+
+ if (changed) {
+ uvedit_live_unwrap_update(sima, scene, obedit);
+ DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ }
+ }
+
+ MEM_freeN(objects);
}
static int uv_align_exec(bContext *C, wmOperator *op)
{
- uv_weld_align(C, RNA_enum_get(op->ptr, "axis"));
+ uv_weld_align(C, RNA_enum_get(op->ptr, "axis"));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void UV_OT_align(wmOperatorType *ot)
{
- static const EnumPropertyItem axis_items[] = {
- {UV_STRAIGHTEN, "ALIGN_S", 0, "Straighten",
- "Align UVs along the line defined by the endpoints"},
- {UV_STRAIGHTEN_X, "ALIGN_T", 0, "Straighten X",
- "Align UVs along the line defined by the endpoints along the X axis"},
- {UV_STRAIGHTEN_Y, "ALIGN_U", 0, "Straighten Y",
- "Align UVs along the line defined by the endpoints along the Y axis"},
- {UV_ALIGN_AUTO, "ALIGN_AUTO", 0, "Align Auto",
- "Automatically choose the axis on which there is most alignment already"},
- {UV_ALIGN_X, "ALIGN_X", 0, "Align X", "Align UVs on X axis"},
- {UV_ALIGN_Y, "ALIGN_Y", 0, "Align Y", "Align UVs on Y axis"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Align";
- ot->description = "Align selected UV vertices to an axis";
- ot->idname = "UV_OT_align";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* api callbacks */
- ot->exec = uv_align_exec;
- ot->poll = ED_operator_uvedit;
-
- /* properties */
- RNA_def_enum(ot->srna, "axis", axis_items, UV_ALIGN_AUTO, "Axis", "Axis to align UV locations on");
+ static const EnumPropertyItem axis_items[] = {
+ {UV_STRAIGHTEN,
+ "ALIGN_S",
+ 0,
+ "Straighten",
+ "Align UVs along the line defined by the endpoints"},
+ {UV_STRAIGHTEN_X,
+ "ALIGN_T",
+ 0,
+ "Straighten X",
+ "Align UVs along the line defined by the endpoints along the X axis"},
+ {UV_STRAIGHTEN_Y,
+ "ALIGN_U",
+ 0,
+ "Straighten Y",
+ "Align UVs along the line defined by the endpoints along the Y axis"},
+ {UV_ALIGN_AUTO,
+ "ALIGN_AUTO",
+ 0,
+ "Align Auto",
+ "Automatically choose the axis on which there is most alignment already"},
+ {UV_ALIGN_X, "ALIGN_X", 0, "Align X", "Align UVs on X axis"},
+ {UV_ALIGN_Y, "ALIGN_Y", 0, "Align Y", "Align UVs on Y axis"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Align";
+ ot->description = "Align selected UV vertices to an axis";
+ ot->idname = "UV_OT_align";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec = uv_align_exec;
+ ot->poll = ED_operator_uvedit;
+
+ /* properties */
+ RNA_def_enum(
+ ot->srna, "axis", axis_items, UV_ALIGN_AUTO, "Axis", "Axis to align UV locations on");
}
/** \} */
@@ -1821,282 +1894,293 @@ static void UV_OT_align(wmOperatorType *ot)
static int uv_remove_doubles_to_selected(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
- ToolSettings *ts = scene->toolsettings;
-
- const float threshold = RNA_float_get(op->ptr, "threshold");
- const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
-
- 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 *changed = MEM_callocN(sizeof(bool) * objects_len, "uv_remove_doubles_selected.changed");
-
- /* Maximum index of an objects[i]'s MLoopUVs in MLoopUV_arr.
- * It helps find which MLoopUV in *MLoopUV_arr belongs to which object. */
- uint *ob_mloopuv_max_idx = MEM_callocN(sizeof(uint) * objects_len,
- "uv_remove_doubles_selected.ob_mloopuv_max_idx");
-
- /* Calculate max possible number of kdtree nodes. */
- int uv_maxlen = 0;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (synced_selection && (em->bm->totvertsel == 0)) {
- continue;
- }
-
- uv_maxlen += em->bm->totloop;
- }
-
- KDTree_2d *tree = BLI_kdtree_2d_new(uv_maxlen);
-
- int *duplicates = NULL;
- BLI_array_declare(duplicates);
-
- MLoopUV **mloopuv_arr = NULL;
- BLI_array_declare(mloopuv_arr);
-
- int mloopuv_count = 0; /* Also used for *duplicates count. */
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- BMIter iter, liter;
- BMFace *efa;
- BMLoop *l;
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (synced_selection && (em->bm->totvertsel == 0)) {
- continue;
- }
-
- 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) {
- if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- BLI_kdtree_2d_insert(tree, mloopuv_count, luv->uv);
- BLI_array_append(duplicates, -1);
- BLI_array_append(mloopuv_arr, luv);
- mloopuv_count++;
- }
- }
- }
-
- ob_mloopuv_max_idx[ob_index] = mloopuv_count - 1;
- }
-
- BLI_kdtree_2d_balance(tree);
- int found_duplicates = BLI_kdtree_2d_calc_duplicates_fast(tree, threshold, false, duplicates);
-
- if (found_duplicates > 0) {
- /* Calculate average uv for duplicates. */
- int *uv_duplicate_count = MEM_callocN(sizeof(int) * mloopuv_count,
- "uv_remove_doubles_selected.uv_duplicate_count");
- for (int i = 0; i < mloopuv_count; i++) {
- if (duplicates[i] == -1) { /* If doesn't reference another */
- uv_duplicate_count[i]++; /* self */
- continue;
- }
-
- if (duplicates[i] != i) {
- /* If not self then accumulate uv for averaging.
- * Self uv is already present in accumulator */
- add_v2_v2(mloopuv_arr[duplicates[i]]->uv, mloopuv_arr[i]->uv);
- }
- uv_duplicate_count[duplicates[i]]++;
- }
-
- for (int i = 0; i < mloopuv_count; i++) {
- if (uv_duplicate_count[i] < 2) {
- continue;
- }
-
- mul_v2_fl(mloopuv_arr[i]->uv, 1.0f / (float)uv_duplicate_count[i]);
- }
- MEM_freeN(uv_duplicate_count);
-
- /* Update duplicated uvs. */
- uint ob_index = 0;
- for (int i = 0; i < mloopuv_count; i++) {
- /* Make sure we know which object owns the MLoopUV at this index.
- * Remember that in some cases the object will have no loop uv,
- * thus we need the while loop, and not simply an if check. */
- while (ob_mloopuv_max_idx[ob_index] < i) {
- ob_index++;
- }
-
- if (duplicates[i] == -1) {
- continue;
- }
-
- copy_v2_v2(mloopuv_arr[i]->uv, mloopuv_arr[duplicates[i]]->uv);
- changed[ob_index] = true;
- }
-
- for (ob_index = 0; ob_index < objects_len; ob_index++) {
- if (changed[ob_index]) {
- Object *obedit = objects[ob_index];
- uvedit_live_unwrap_update(sima, scene, obedit);
- DEG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- }
- }
- }
-
- BLI_kdtree_2d_free(tree);
- BLI_array_free(mloopuv_arr);
- BLI_array_free(duplicates);
- MEM_freeN(changed);
- MEM_freeN(objects);
- MEM_freeN(ob_mloopuv_max_idx);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = CTX_data_edit_image(C);
+ ToolSettings *ts = scene->toolsettings;
+
+ const float threshold = RNA_float_get(op->ptr, "threshold");
+ const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
+
+ 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 *changed = MEM_callocN(sizeof(bool) * objects_len, "uv_remove_doubles_selected.changed");
+
+ /* Maximum index of an objects[i]'s MLoopUVs in MLoopUV_arr.
+ * It helps find which MLoopUV in *MLoopUV_arr belongs to which object. */
+ uint *ob_mloopuv_max_idx = MEM_callocN(sizeof(uint) * objects_len,
+ "uv_remove_doubles_selected.ob_mloopuv_max_idx");
+
+ /* Calculate max possible number of kdtree nodes. */
+ int uv_maxlen = 0;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (synced_selection && (em->bm->totvertsel == 0)) {
+ continue;
+ }
+
+ uv_maxlen += em->bm->totloop;
+ }
+
+ KDTree_2d *tree = BLI_kdtree_2d_new(uv_maxlen);
+
+ int *duplicates = NULL;
+ BLI_array_declare(duplicates);
+
+ MLoopUV **mloopuv_arr = NULL;
+ BLI_array_declare(mloopuv_arr);
+
+ int mloopuv_count = 0; /* Also used for *duplicates count. */
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ BMIter iter, liter;
+ BMFace *efa;
+ BMLoop *l;
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (synced_selection && (em->bm->totvertsel == 0)) {
+ continue;
+ }
+
+ 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) {
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ BLI_kdtree_2d_insert(tree, mloopuv_count, luv->uv);
+ BLI_array_append(duplicates, -1);
+ BLI_array_append(mloopuv_arr, luv);
+ mloopuv_count++;
+ }
+ }
+ }
+
+ ob_mloopuv_max_idx[ob_index] = mloopuv_count - 1;
+ }
+
+ BLI_kdtree_2d_balance(tree);
+ int found_duplicates = BLI_kdtree_2d_calc_duplicates_fast(tree, threshold, false, duplicates);
+
+ if (found_duplicates > 0) {
+ /* Calculate average uv for duplicates. */
+ int *uv_duplicate_count = MEM_callocN(sizeof(int) * mloopuv_count,
+ "uv_remove_doubles_selected.uv_duplicate_count");
+ for (int i = 0; i < mloopuv_count; i++) {
+ if (duplicates[i] == -1) { /* If doesn't reference another */
+ uv_duplicate_count[i]++; /* self */
+ continue;
+ }
+
+ if (duplicates[i] != i) {
+ /* If not self then accumulate uv for averaging.
+ * Self uv is already present in accumulator */
+ add_v2_v2(mloopuv_arr[duplicates[i]]->uv, mloopuv_arr[i]->uv);
+ }
+ uv_duplicate_count[duplicates[i]]++;
+ }
+
+ for (int i = 0; i < mloopuv_count; i++) {
+ if (uv_duplicate_count[i] < 2) {
+ continue;
+ }
+
+ mul_v2_fl(mloopuv_arr[i]->uv, 1.0f / (float)uv_duplicate_count[i]);
+ }
+ MEM_freeN(uv_duplicate_count);
+
+ /* Update duplicated uvs. */
+ uint ob_index = 0;
+ for (int i = 0; i < mloopuv_count; i++) {
+ /* Make sure we know which object owns the MLoopUV at this index.
+ * Remember that in some cases the object will have no loop uv,
+ * thus we need the while loop, and not simply an if check. */
+ while (ob_mloopuv_max_idx[ob_index] < i) {
+ ob_index++;
+ }
+
+ if (duplicates[i] == -1) {
+ continue;
+ }
+
+ copy_v2_v2(mloopuv_arr[i]->uv, mloopuv_arr[duplicates[i]]->uv);
+ changed[ob_index] = true;
+ }
+
+ for (ob_index = 0; ob_index < objects_len; ob_index++) {
+ if (changed[ob_index]) {
+ Object *obedit = objects[ob_index];
+ uvedit_live_unwrap_update(sima, scene, obedit);
+ DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ }
+ }
+ }
+
+ BLI_kdtree_2d_free(tree);
+ BLI_array_free(mloopuv_arr);
+ BLI_array_free(duplicates);
+ MEM_freeN(changed);
+ MEM_freeN(objects);
+ MEM_freeN(ob_mloopuv_max_idx);
+
+ return OPERATOR_FINISHED;
}
static int uv_remove_doubles_to_unselected(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
- ToolSettings *ts = scene->toolsettings;
-
- const float threshold = RNA_float_get(op->ptr, "threshold");
- const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
-
- 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 max possible number of kdtree nodes. */
- int uv_maxlen = 0;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- uv_maxlen += em->bm->totloop;
- }
-
- KDTree_2d *tree = BLI_kdtree_2d_new(uv_maxlen);
-
- MLoopUV **mloopuv_arr = NULL;
- BLI_array_declare(mloopuv_arr);
-
- int mloopuv_count = 0;
-
- /* Add visible non-selected uvs to tree */
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- BMIter iter, liter;
- BMFace *efa;
- BMLoop *l;
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (synced_selection && (em->bm->totvertsel == em->bm->totvert)) {
- continue;
- }
-
- 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) {
- if (!uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- BLI_kdtree_2d_insert(tree, mloopuv_count, luv->uv);
- BLI_array_append(mloopuv_arr, luv);
- mloopuv_count++;
- }
- }
- }
- }
-
- BLI_kdtree_2d_balance(tree);
-
- /* For each selected uv, find duplicate non selected uv. */
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- BMIter iter, liter;
- BMFace *efa;
- BMLoop *l;
- bool changed = false;
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (synced_selection && (em->bm->totvertsel == 0)) {
- continue;
- }
-
- 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) {
- if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- KDTreeNearest_2d nearest;
- const int i = BLI_kdtree_2d_find_nearest(tree, luv->uv, &nearest);
-
- if (i != -1 && nearest.dist < threshold) {
- copy_v2_v2(luv->uv, mloopuv_arr[i]->uv);
- changed = true;
- }
- }
- }
- }
-
- if (changed) {
- uvedit_live_unwrap_update(sima, scene, obedit);
- DEG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- }
- }
-
- BLI_kdtree_2d_free(tree);
- BLI_array_free(mloopuv_arr);
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = CTX_data_edit_image(C);
+ ToolSettings *ts = scene->toolsettings;
+
+ const float threshold = RNA_float_get(op->ptr, "threshold");
+ const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
+
+ 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 max possible number of kdtree nodes. */
+ int uv_maxlen = 0;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ uv_maxlen += em->bm->totloop;
+ }
+
+ KDTree_2d *tree = BLI_kdtree_2d_new(uv_maxlen);
+
+ MLoopUV **mloopuv_arr = NULL;
+ BLI_array_declare(mloopuv_arr);
+
+ int mloopuv_count = 0;
+
+ /* Add visible non-selected uvs to tree */
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ BMIter iter, liter;
+ BMFace *efa;
+ BMLoop *l;
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (synced_selection && (em->bm->totvertsel == em->bm->totvert)) {
+ continue;
+ }
+
+ 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) {
+ if (!uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ BLI_kdtree_2d_insert(tree, mloopuv_count, luv->uv);
+ BLI_array_append(mloopuv_arr, luv);
+ mloopuv_count++;
+ }
+ }
+ }
+ }
+
+ BLI_kdtree_2d_balance(tree);
+
+ /* For each selected uv, find duplicate non selected uv. */
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ BMIter iter, liter;
+ BMFace *efa;
+ BMLoop *l;
+ bool changed = false;
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (synced_selection && (em->bm->totvertsel == 0)) {
+ continue;
+ }
+
+ 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) {
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ KDTreeNearest_2d nearest;
+ const int i = BLI_kdtree_2d_find_nearest(tree, luv->uv, &nearest);
+
+ if (i != -1 && nearest.dist < threshold) {
+ copy_v2_v2(luv->uv, mloopuv_arr[i]->uv);
+ changed = true;
+ }
+ }
+ }
+ }
+
+ if (changed) {
+ uvedit_live_unwrap_update(sima, scene, obedit);
+ DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ }
+ }
+
+ BLI_kdtree_2d_free(tree);
+ BLI_array_free(mloopuv_arr);
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
static int uv_remove_doubles_exec(bContext *C, wmOperator *op)
{
- if (RNA_boolean_get(op->ptr, "use_unselected")) {
- return uv_remove_doubles_to_unselected(C, op);
- }
- else {
- return uv_remove_doubles_to_selected(C, op);
- }
+ if (RNA_boolean_get(op->ptr, "use_unselected")) {
+ return uv_remove_doubles_to_unselected(C, op);
+ }
+ else {
+ return uv_remove_doubles_to_selected(C, op);
+ }
}
static void UV_OT_remove_doubles(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Doubles UV";
- ot->description = "Selected UV vertices that are within a radius of each other are welded together";
- ot->idname = "UV_OT_remove_doubles";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* api callbacks */
- ot->exec = uv_remove_doubles_exec;
- ot->poll = ED_operator_uvedit;
-
- RNA_def_float(ot->srna, "threshold", 0.02f, 0.0f, 10.0f,
- "Merge Distance", "Maximum distance between welded vertices", 0.0f, 1.0f);
- RNA_def_boolean(ot->srna, "use_unselected", 0, "Unselected", "Merge selected to other unselected vertices");
+ /* identifiers */
+ ot->name = "Remove Doubles UV";
+ ot->description =
+ "Selected UV vertices that are within a radius of each other are welded together";
+ ot->idname = "UV_OT_remove_doubles";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec = uv_remove_doubles_exec;
+ ot->poll = ED_operator_uvedit;
+
+ RNA_def_float(ot->srna,
+ "threshold",
+ 0.02f,
+ 0.0f,
+ 10.0f,
+ "Merge Distance",
+ "Maximum distance between welded vertices",
+ 0.0f,
+ 1.0f);
+ RNA_def_boolean(
+ ot->srna, "use_unselected", 0, "Unselected", "Merge selected to other unselected vertices");
}
/** \} */
@@ -2107,22 +2191,22 @@ static void UV_OT_remove_doubles(wmOperatorType *ot)
static int uv_weld_exec(bContext *C, wmOperator *UNUSED(op))
{
- uv_weld_align(C, UV_WELD);
+ uv_weld_align(C, UV_WELD);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void UV_OT_weld(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Weld";
- ot->description = "Weld selected UV vertices together";
- ot->idname = "UV_OT_weld";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Weld";
+ ot->description = "Weld selected UV vertices together";
+ ot->idname = "UV_OT_weld";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* api callbacks */
- ot->exec = uv_weld_exec;
- ot->poll = ED_operator_uvedit;
+ /* api callbacks */
+ ot->exec = uv_weld_exec;
+ ot->poll = ED_operator_uvedit;
}
/** \} */
@@ -2133,153 +2217,158 @@ static void UV_OT_weld(wmOperatorType *ot)
static bool uv_select_is_any_selected(Scene *scene, Image *ima, Object *obedit)
{
- 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;
+ 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)
{
- 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;
- }
- }
- }
- }
+ 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)
+ 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;
- }
+ 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);
- }
+ 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_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = scene->toolsettings;
- Image *ima = CTX_data_edit_image(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ 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");
+ 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);
+ 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);
+ 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);
- }
+ 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);
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ 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;
+ /* 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;
+ /* api callbacks */
+ ot->exec = uv_select_all_exec;
+ ot->poll = ED_operator_uvedit;
- WM_operator_properties_select_all(ot);
+ WM_operator_properties_select_all(ot);
}
/** \} */
@@ -2288,352 +2377,370 @@ static void UV_OT_select_all(wmOperatorType *ot)
/** \name Mouse Select Operator
* \{ */
-static bool uv_sticky_select(float *limit, int hitv[], int v, float *hituv[], float *uv, int sticky, int hitlen)
+static bool uv_sticky_select(
+ float *limit, int hitv[], int v, float *hituv[], float *uv, int sticky, int hitlen)
{
- int i;
+ 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;
+ /* 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;
- }
- }
+ 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;
+ return false;
}
static int uv_mouse_select_multi(
- bContext *C, Object **objects, uint objects_len,
- const float co[2], bool extend, bool loop)
-{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- Scene *scene = CTX_data_scene(C);
- 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;
- /* 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 */
- if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) {
- return OPERATOR_CANCELLED;
- }
-
- hitlen = 0;
- }
- else if (selectmode == UV_SELECT_VERTEX) {
- /* find vertex */
- if (!uv_find_nearest_vert_multi(scene, ima, objects, objects_len, co, penalty_dist, &hit)) {
- return OPERATOR_CANCELLED;
- }
-
- /* 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 */
- if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) {
- return OPERATOR_CANCELLED;
- }
-
- /* 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 */
- if (!uv_find_nearest_face_multi(scene, ima, objects, objects_len, co, &hit)) {
- return OPERATOR_CANCELLED;
- }
-
- 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) {
- if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) {
- return OPERATOR_CANCELLED;
- }
-
- hitlen = 0;
- }
- else {
- hitlen = 0;
- 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 */
+ bContext *C, Object **objects, uint objects_len, const float co[2], bool extend, bool loop)
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Scene *scene = CTX_data_scene(C);
+ 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;
+ /* 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 */
+ if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ hitlen = 0;
+ }
+ else if (selectmode == UV_SELECT_VERTEX) {
+ /* find vertex */
+ if (!uv_find_nearest_vert_multi(scene, ima, objects, objects_len, co, penalty_dist, &hit)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* 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 */
+ if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* 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 */
+ if (!uv_find_nearest_face_multi(scene, ima, objects, objects_len, co, &hit)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ 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) {
+ if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ hitlen = 0;
+ }
+ else {
+ hitlen = 0;
+ 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);
- }
+ 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);
- }
- }
+ 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);
- }
+ 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;
+ return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED;
}
static int uv_mouse_select(bContext *C, const float co[2], bool extend, 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, loop);
- MEM_freeN(objects);
- return ret;
+ 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, loop);
+ MEM_freeN(objects);
+ return ret;
}
static int uv_select_exec(bContext *C, wmOperator *op)
{
- float co[2];
- bool extend, loop;
+ float co[2];
+ bool extend, loop;
- RNA_float_get_array(op->ptr, "location", co);
- extend = RNA_boolean_get(op->ptr, "extend");
- loop = false;
+ RNA_float_get_array(op->ptr, "location", co);
+ extend = RNA_boolean_get(op->ptr, "extend");
+ loop = false;
- return uv_mouse_select(C, co, extend, loop);
+ return uv_mouse_select(C, co, extend, loop);
}
static int uv_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- float co[2];
+ 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);
+ 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);
+ 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 */
- 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);
+ /* 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 */
+ 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);
}
/** \} */
@@ -2644,45 +2751,57 @@ static void UV_OT_select(wmOperatorType *ot)
static int uv_select_loop_exec(bContext *C, wmOperator *op)
{
- float co[2];
- bool extend, loop;
+ float co[2];
+ bool extend, loop;
- RNA_float_get_array(op->ptr, "location", co);
- extend = RNA_boolean_get(op->ptr, "extend");
- loop = true;
+ RNA_float_get_array(op->ptr, "location", co);
+ extend = RNA_boolean_get(op->ptr, "extend");
+ loop = true;
- return uv_mouse_select(C, co, extend, loop);
+ return uv_mouse_select(C, co, extend, loop);
}
static int uv_select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- float co[2];
+ 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);
+ 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);
+ 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);
+ /* 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);
}
/** \} */
@@ -2693,95 +2812,105 @@ static void UV_OT_select_loop(wmOperatorType *ot)
static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent *event, int pick)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- Scene *scene = CTX_data_scene(C);
- 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;
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Scene *scene = CTX_data_scene(C);
+ 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, 0);
+ return uv_select_linked_internal(C, op, NULL, 0);
}
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;
+ /* 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 */
+ /* api callbacks */
+ ot->exec = uv_select_linked_exec;
+ ot->poll = ED_operator_uvedit; /* requires space image */
}
/** \} */
@@ -2792,33 +2921,49 @@ static void UV_OT_select_linked(wmOperatorType *ot)
static int uv_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- return uv_select_linked_internal(C, op, event, 1);
+ return uv_select_linked_internal(C, op, event, 1);
}
static int uv_select_linked_pick_exec(bContext *C, wmOperator *op)
{
- return uv_select_linked_internal(C, op, NULL, 1);
+ return uv_select_linked_internal(C, op, NULL, 1);
}
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";
- ot->flag = 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);
+ /* identifiers */
+ ot->name = "Select Linked Pick";
+ ot->description = "Select all UV vertices linked under the mouse";
+ ot->idname = "UV_OT_select_linked_pick";
+ ot->flag = 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);
}
/** \} */
@@ -2835,124 +2980,126 @@ static void UV_OT_select_linked_pick(wmOperatorType *ot)
*/
static int uv_select_split_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- ToolSettings *ts = scene->toolsettings;
- Image *ima = CTX_data_edit_image(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ ToolSettings *ts = scene->toolsettings;
+ Image *ima = CTX_data_edit_image(C);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
+ 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;
- }
+ 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;
+ 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);
+ 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;
+ 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;
+ bool changed = false;
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ 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;
+ 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;
- }
+ 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);
+ /* 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;
- }
+ if (luv->flag & MLOOPUV_VERTSEL) {
+ is_sel = true;
+ }
+ else {
+ is_unsel = true;
+ }
- /* we have mixed selection, bail out */
- if (is_sel && is_unsel) {
- break;
- }
- }
+ /* 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;
- }
+ 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;
- }
- }
+ changed = true;
+ }
+ }
- if (changed) {
- changed_multi = true;
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL);
- }
- }
- MEM_freeN(objects);
+ 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;
+ 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;
+ /* 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 */
+ /* api callbacks */
+ ot->exec = uv_select_split_exec;
+ ot->poll = ED_operator_uvedit; /* requires space image */
}
static void uv_select_sync_flush(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);
- }
+ /* 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);
+ }
}
/** \} */
@@ -2966,45 +3113,49 @@ static void uv_select_tag_update_for_object(Depsgraph *depsgraph, const ToolSett
/**
* 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)
+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;
+ UvMapVert *start_vlist = NULL, *vlist_iter;
+ BMFace *efa_vlist;
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ 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));
+ 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;
+ while (vlist_iter) {
+ if (vlist_iter->separate)
+ start_vlist = vlist_iter;
- if (efa_index == vlist_iter->poly_index)
- break;
+ if (efa_index == vlist_iter->poly_index)
+ break;
- vlist_iter = vlist_iter->next;
- }
+ vlist_iter = vlist_iter->next;
+ }
- vlist_iter = start_vlist;
- while (vlist_iter) {
+ vlist_iter = start_vlist;
+ while (vlist_iter) {
- if (vlist_iter != start_vlist && vlist_iter->separate)
- break;
+ 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 */
+ 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);
+ 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;
- }
+ uvedit_uv_select_set(em, scene, l_other, select, false, cd_loop_uv_offset);
+ }
+ vlist_iter = vlist_iter->next;
+ }
}
/**
@@ -3015,83 +3166,82 @@ static void uv_select_flush_from_tag_sticky_loc_internal(
*
* \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). */
-
- 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);
- }
- }
- }
+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). */
+
+ 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.
*
@@ -3100,83 +3250,83 @@ static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object
*
* \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). */
-
- 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);
- }
- }
- }
- }
+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). */
+
+ 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);
+ }
+ }
+ }
+ }
}
/** \} */
@@ -3187,144 +3337,144 @@ static void uv_select_flush_from_tag_loop(SpaceImage *sima, Scene *scene, Object
static int uv_box_select_exec(bContext *C, wmOperator *op)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- Scene *scene = CTX_data_scene(C);
- 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);
-
- 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 (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- 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];
-
- changed = false;
-
- 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) {
- 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;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Scene *scene = CTX_data_scene(C);
+ 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);
+
+ 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 (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ 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];
+
+ changed = false;
+
+ 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) {
+ 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";
+ /* 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;
+ /* 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;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "pinned", 0, "Pinned", "Border select pinned UVs only");
+ /* 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);
+ WM_operator_properties_gesture_box(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
/** \} */
@@ -3335,142 +3485,142 @@ static void UV_OT_select_box(wmOperatorType *ot)
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);
+ /* 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_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);
- 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);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
- changed_multi = true;
- }
-
- 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) {
- changed = false;
- 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) {
- 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;
+ Depsgraph *depsgraph = CTX_data_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);
+ 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);
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
+ changed_multi = true;
+ }
+
+ 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) {
+ changed = false;
+ 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) {
+ 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";
+ /* 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;
+ /* 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;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_gesture_circle(ot);
- WM_operator_properties_select_operation_simple(ot);
+ /* properties */
+ WM_operator_properties_gesture_circle(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
/** \} */
@@ -3479,148 +3629,148 @@ static void UV_OT_select_circle(wmOperatorType *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_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);
- 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);
-
- 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 (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- 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) {
- 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 bool do_lasso_select_mesh_uv(bContext *C,
+ const int mcords[][2],
+ short moves,
+ const eSelectOp sel_op)
+{
+ Depsgraph *depsgraph = CTX_data_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);
+ 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);
+
+ 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 (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ 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) {
+ 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);
+ 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);
+ 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 changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ }
- return OPERATOR_PASS_THROUGH;
+ 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->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;
+ 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;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_gesture_lasso(ot);
- WM_operator_properties_select_operation_simple(ot);
+ /* properties */
+ WM_operator_properties_gesture_lasso(ot);
+ WM_operator_properties_select_operation_simple(ot);
}
/** \} */
@@ -3631,78 +3781,78 @@ static void UV_OT_select_lasso(wmOperatorType *ot)
static void uv_snap_to_pixel(float uvco[2], float w, float h)
{
- uvco[0] = roundf(uvco[0] * w) / w;
- uvco[1] = roundf(uvco[1] * h) / h;
+ uvco[0] = roundf(uvco[0] * w) / w;
+ uvco[1] = roundf(uvco[1] * h) / h;
}
static void uv_snap_cursor_to_pixels(SpaceImage *sima)
{
- int width = 0, height = 0;
+ int width = 0, height = 0;
- ED_space_image_get_size(sima, &width, &height);
- uv_snap_to_pixel(sima->cursor, width, height);
+ ED_space_image_get_size(sima, &width, &height);
+ uv_snap_to_pixel(sima->cursor, width, height);
}
static bool uv_snap_cursor_to_selection(
- Scene *scene, Image *ima, Object **objects_edit, uint objects_len, SpaceImage *sima)
+ Scene *scene, Image *ima, Object **objects_edit, uint objects_len, SpaceImage *sima)
{
- return ED_uvedit_center_multi(scene, ima, objects_edit, objects_len, sima->cursor, sima->around);
+ return ED_uvedit_center_multi(scene, ima, objects_edit, objects_len, sima->cursor, sima->around);
}
static int uv_snap_cursor_exec(bContext *C, wmOperator *op)
{
- SpaceImage *sima = CTX_wm_space_image(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
- bool changed = false;
+ bool changed = false;
- switch (RNA_enum_get(op->ptr, "target")) {
- case 0:
- uv_snap_cursor_to_pixels(sima);
- changed = true;
- break;
- case 1:
- {
- Scene *scene = CTX_data_scene(C);
- Image *ima = CTX_data_edit_image(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
+ switch (RNA_enum_get(op->ptr, "target")) {
+ case 0:
+ uv_snap_cursor_to_pixels(sima);
+ changed = true;
+ break;
+ case 1: {
+ Scene *scene = CTX_data_scene(C);
+ Image *ima = CTX_data_edit_image(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
- view_layer, ((View3D *)NULL), &objects_len);
- changed = uv_snap_cursor_to_selection(scene, ima, objects, objects_len, sima);
- MEM_freeN(objects);
- break;
- }
- }
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, ((View3D *)NULL), &objects_len);
+ changed = uv_snap_cursor_to_selection(scene, ima, objects, objects_len, sima);
+ MEM_freeN(objects);
+ break;
+ }
+ }
- if (!changed)
- return OPERATOR_CANCELLED;
+ if (!changed)
+ return OPERATOR_CANCELLED;
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, sima);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, sima);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void UV_OT_snap_cursor(wmOperatorType *ot)
{
- static const EnumPropertyItem target_items[] = {
- {0, "PIXELS", 0, "Pixels", ""},
- {1, "SELECTED", 0, "Selected", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem target_items[] = {
+ {0, "PIXELS", 0, "Pixels", ""},
+ {1, "SELECTED", 0, "Selected", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Snap Cursor";
- ot->description = "Snap cursor to target type";
- ot->idname = "UV_OT_snap_cursor";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Snap Cursor";
+ ot->description = "Snap cursor to target type";
+ ot->idname = "UV_OT_snap_cursor";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* api callbacks */
- ot->exec = uv_snap_cursor_exec;
- ot->poll = ED_operator_uvedit_space_image; /* requires space image */
+ /* api callbacks */
+ ot->exec = uv_snap_cursor_exec;
+ ot->poll = ED_operator_uvedit_space_image; /* requires space image */
- /* properties */
- RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UVs to");
+ /* properties */
+ RNA_def_enum(
+ ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UVs to");
}
/** \} */
@@ -3713,230 +3863,232 @@ static void UV_OT_snap_cursor(wmOperatorType *ot)
static bool uv_snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, const float cursor[2])
{
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
- bool changed = false;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+ bool changed = false;
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ 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_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 (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- copy_v2_v2(luv->uv, cursor);
- changed = true;
- }
- }
- }
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ copy_v2_v2(luv->uv, cursor);
+ changed = true;
+ }
+ }
+ }
- return changed;
+ return changed;
}
static bool uv_snap_uvs_offset(Scene *scene, Image *ima, Object *obedit, const float offset[2])
{
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
- bool changed = false;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+ bool changed = false;
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ 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_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 (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- add_v2_v2(luv->uv, offset);
- changed = true;
- }
- }
- }
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ add_v2_v2(luv->uv, offset);
+ changed = true;
+ }
+ }
+ }
- return changed;
+ return changed;
}
static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obedit)
{
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMFace *f;
- BMLoop *l, *lsub;
- BMIter iter, liter, lsubiter;
- MLoopUV *luv;
- bool changed = false;
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-
- /* index every vert that has a selected UV using it, but only once so as to
- * get unique indices and to count how much to malloc */
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, obedit, ima, f)) {
- BM_elem_flag_enable(f, BM_ELEM_TAG);
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- BM_elem_flag_set(l, BM_ELEM_TAG, uvedit_uv_select_test(scene, l, cd_loop_uv_offset));
- }
- }
- else {
- BM_elem_flag_disable(f, BM_ELEM_TAG);
- }
- }
-
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_TAG)) { /* face: visible */
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- if (BM_elem_flag_test(l, BM_ELEM_TAG)) { /* loop: selected*/
- float uv[2] = {0.0f, 0.0f};
- int uv_tot = 0;
-
- BM_ITER_ELEM (lsub, &lsubiter, l->v, BM_LOOPS_OF_VERT) {
- if (BM_elem_flag_test(lsub->f, BM_ELEM_TAG) && /* face: visible */
- !BM_elem_flag_test(lsub, BM_ELEM_TAG)) /* loop: unselected */
- {
- luv = BM_ELEM_CD_GET_VOID_P(lsub, cd_loop_uv_offset);
- add_v2_v2(uv, luv->uv);
- uv_tot++;
- }
- }
-
- if (uv_tot) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- mul_v2_v2fl(luv->uv, uv, 1.0f / (float)uv_tot);
- changed = true;
- }
- }
- }
- }
- }
-
- return changed;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMFace *f;
+ BMLoop *l, *lsub;
+ BMIter iter, liter, lsubiter;
+ MLoopUV *luv;
+ bool changed = false;
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+ /* index every vert that has a selected UV using it, but only once so as to
+ * get unique indices and to count how much to malloc */
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (uvedit_face_visible_test(scene, obedit, ima, f)) {
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ BM_elem_flag_set(l, BM_ELEM_TAG, uvedit_uv_select_test(scene, l, cd_loop_uv_offset));
+ }
+ }
+ else {
+ BM_elem_flag_disable(f, BM_ELEM_TAG);
+ }
+ }
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_TAG)) { /* face: visible */
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ if (BM_elem_flag_test(l, BM_ELEM_TAG)) { /* loop: selected*/
+ float uv[2] = {0.0f, 0.0f};
+ int uv_tot = 0;
+
+ BM_ITER_ELEM (lsub, &lsubiter, l->v, BM_LOOPS_OF_VERT) {
+ if (BM_elem_flag_test(lsub->f, BM_ELEM_TAG) && /* face: visible */
+ !BM_elem_flag_test(lsub, BM_ELEM_TAG)) /* loop: unselected */
+ {
+ luv = BM_ELEM_CD_GET_VOID_P(lsub, cd_loop_uv_offset);
+ add_v2_v2(uv, luv->uv);
+ uv_tot++;
+ }
+ }
+
+ if (uv_tot) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ mul_v2_v2fl(luv->uv, uv, 1.0f / (float)uv_tot);
+ changed = true;
+ }
+ }
+ }
+ }
+ }
+
+ return changed;
}
static bool uv_snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit)
{
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- Image *ima = sima->image;
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
- int width = 0, height = 0;
- float w, h;
- bool changed = false;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ Image *ima = sima->image;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+ int width = 0, height = 0;
+ float w, h;
+ bool changed = false;
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- ED_space_image_get_size(sima, &width, &height);
- w = (float)width;
- h = (float)height;
+ ED_space_image_get_size(sima, &width, &height);
+ w = (float)width;
+ h = (float)height;
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa))
- continue;
+ 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 (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- uv_snap_to_pixel(luv->uv, w, h);
- }
- }
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ uv_snap_to_pixel(luv->uv, w, h);
+ }
+ }
- changed = true;
- }
+ changed = true;
+ }
- return changed;
+ return changed;
}
static int uv_snap_selection_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
- ToolSettings *ts = scene->toolsettings;
- const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
- const int target = RNA_enum_get(op->ptr, "target");
- float offset[2] = {0};
-
- 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 (target == 2) {
- float center[2];
- if (!ED_uvedit_center_multi(scene, ima, objects, objects_len, center, sima->around)) {
- MEM_freeN(objects);
- return OPERATOR_CANCELLED;
- }
- sub_v2_v2v2(offset, sima->cursor, center);
- }
-
- bool changed_multi = false;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (synced_selection && (em->bm->totvertsel == 0)) {
- continue;
- }
-
- bool changed = false;
- switch (target) {
- case 0:
- changed = uv_snap_uvs_to_pixels(sima, scene, obedit);
- break;
- case 1:
- changed = uv_snap_uvs_to_cursor(scene, ima, obedit, sima->cursor);
- break;
- case 2:
- changed = uv_snap_uvs_offset(scene, ima, obedit, offset);
- break;
- case 3:
- changed = uv_snap_uvs_to_adjacent_unselected(scene, ima, obedit);
- break;
- }
-
- if (changed) {
- changed_multi = true;
- uvedit_live_unwrap_update(sima, scene, obedit);
- DEG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- }
- }
- MEM_freeN(objects);
-
- return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = CTX_data_edit_image(C);
+ ToolSettings *ts = scene->toolsettings;
+ const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
+ const int target = RNA_enum_get(op->ptr, "target");
+ float offset[2] = {0};
+
+ 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 (target == 2) {
+ float center[2];
+ if (!ED_uvedit_center_multi(scene, ima, objects, objects_len, center, sima->around)) {
+ MEM_freeN(objects);
+ return OPERATOR_CANCELLED;
+ }
+ sub_v2_v2v2(offset, sima->cursor, center);
+ }
+
+ bool changed_multi = false;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (synced_selection && (em->bm->totvertsel == 0)) {
+ continue;
+ }
+
+ bool changed = false;
+ switch (target) {
+ case 0:
+ changed = uv_snap_uvs_to_pixels(sima, scene, obedit);
+ break;
+ case 1:
+ changed = uv_snap_uvs_to_cursor(scene, ima, obedit, sima->cursor);
+ break;
+ case 2:
+ changed = uv_snap_uvs_offset(scene, ima, obedit, offset);
+ break;
+ case 3:
+ changed = uv_snap_uvs_to_adjacent_unselected(scene, ima, obedit);
+ break;
+ }
+
+ if (changed) {
+ changed_multi = true;
+ uvedit_live_unwrap_update(sima, scene, obedit);
+ DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ }
+ }
+ MEM_freeN(objects);
+
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static void UV_OT_snap_selected(wmOperatorType *ot)
{
- static const EnumPropertyItem target_items[] = {
- {0, "PIXELS", 0, "Pixels", ""},
- {1, "CURSOR", 0, "Cursor", ""},
- {2, "CURSOR_OFFSET", 0, "Cursor (Offset)", ""},
- {3, "ADJACENT_UNSELECTED", 0, "Adjacent Unselected", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem target_items[] = {
+ {0, "PIXELS", 0, "Pixels", ""},
+ {1, "CURSOR", 0, "Cursor", ""},
+ {2, "CURSOR_OFFSET", 0, "Cursor (Offset)", ""},
+ {3, "ADJACENT_UNSELECTED", 0, "Adjacent Unselected", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- /* identifiers */
- ot->name = "Snap Selection";
- ot->description = "Snap selected UV vertices to target type";
- ot->idname = "UV_OT_snap_selected";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Snap Selection";
+ ot->description = "Snap selected UV vertices to target type";
+ ot->idname = "UV_OT_snap_selected";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* api callbacks */
- ot->exec = uv_snap_selection_exec;
- ot->poll = ED_operator_uvedit_space_image;
+ /* api callbacks */
+ ot->exec = uv_snap_selection_exec;
+ ot->poll = ED_operator_uvedit_space_image;
- /* properties */
- RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UVs to");
+ /* properties */
+ RNA_def_enum(
+ ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UVs to");
}
/** \} */
@@ -3947,75 +4099,78 @@ static void UV_OT_snap_selected(wmOperatorType *ot)
static int uv_pin_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Image *ima = CTX_data_edit_image(C);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
- ToolSettings *ts = scene->toolsettings;
- const bool clear = RNA_boolean_get(op->ptr, "clear");
- const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
-
- 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);
-
- bool changed = false;
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- if (synced_selection && (em->bm->totvertsel == 0)) {
- continue;
- }
-
- 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 (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- changed = true;
- if (clear) {
- luv->flag &= ~MLOOPUV_PINNED;
- }
- else {
- luv->flag |= MLOOPUV_PINNED;
- }
- }
- }
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, ID_RECALC_COPY_ON_WRITE);
- }
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Image *ima = CTX_data_edit_image(C);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+ ToolSettings *ts = scene->toolsettings;
+ const bool clear = RNA_boolean_get(op->ptr, "clear");
+ const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
+
+ 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);
+
+ bool changed = false;
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ if (synced_selection && (em->bm->totvertsel == 0)) {
+ continue;
+ }
+
+ 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 (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ changed = true;
+ if (clear) {
+ luv->flag &= ~MLOOPUV_PINNED;
+ }
+ else {
+ luv->flag |= MLOOPUV_PINNED;
+ }
+ }
+ }
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, ID_RECALC_COPY_ON_WRITE);
+ }
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
static void UV_OT_pin(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Pin";
- ot->description = "Set/clear selected UV vertices as anchored between multiple unwrap operations";
- ot->idname = "UV_OT_pin";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Pin";
+ ot->description =
+ "Set/clear selected UV vertices as anchored between multiple unwrap operations";
+ ot->idname = "UV_OT_pin";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* api callbacks */
- ot->exec = uv_pin_exec;
- ot->poll = ED_operator_uvedit;
+ /* api callbacks */
+ ot->exec = uv_pin_exec;
+ ot->poll = ED_operator_uvedit;
- /* properties */
- RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear pinning for the selection instead of setting it");
+ /* properties */
+ RNA_def_boolean(
+ ot->srna, "clear", 0, "Clear", "Clear pinning for the selection instead of setting it");
}
/** \} */
@@ -4026,61 +4181,62 @@ static void UV_OT_pin(wmOperatorType *ot)
static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op))
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- 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;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ 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);
+ 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);
+ 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;
+ 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_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);
+ 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 (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);
+ if (changed) {
+ uv_select_tag_update_for_object(depsgraph, ts, obedit);
+ }
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ 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;
+ /* 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;
+ /* api callbacks */
+ ot->exec = uv_select_pinned_exec;
+ ot->poll = ED_operator_uvedit;
}
/** \} */
@@ -4091,137 +4247,138 @@ static void UV_OT_select_pinned(wmOperatorType *ot)
/* check if we are selected or unselected based on 'bool_test' arg,
* needed for select swap support */
-#define UV_SEL_TEST(luv, bool_test) ((((luv)->flag & MLOOPUV_VERTSEL) == MLOOPUV_VERTSEL) == bool_test)
+#define UV_SEL_TEST(luv, bool_test) \
+ ((((luv)->flag & MLOOPUV_VERTSEL) == MLOOPUV_VERTSEL) == bool_test)
/* is every UV vert selected or unselected depending on bool_test */
-static bool bm_face_is_all_uv_sel(
- BMFace *f, bool select_test,
- const int cd_loop_uv_offset)
+static bool bm_face_is_all_uv_sel(BMFace *f, bool select_test, const int cd_loop_uv_offset)
{
- BMLoop *l_iter;
- BMLoop *l_first;
+ BMLoop *l_iter;
+ BMLoop *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
- if (!UV_SEL_TEST(luv, select_test)) {
- return false;
- }
- } while ((l_iter = l_iter->next) != l_first);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
+ if (!UV_SEL_TEST(luv, select_test)) {
+ return false;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
- return true;
+ return true;
}
static int uv_hide_exec(bContext *C, wmOperator *op)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- Object *obedit = CTX_data_edit_object(C);
- Scene *scene = CTX_data_scene(C);
- 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);
-
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- if (EDBM_mesh_hide(em, swap)) {
- EDBM_update_generic(em, true, false);
- }
- return OPERATOR_FINISHED;
- }
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- int hide = 0;
-
- 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_SEL_TEST(luv, !swap)) {
- hide = 1;
- break;
- }
- }
-
- 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);
- }
- }
- 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;
- }
- }
- }
- }
- }
-
- /* 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);
-
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ 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);
+
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ if (EDBM_mesh_hide(em, swap)) {
+ EDBM_update_generic(em, true, false);
+ }
+ return OPERATOR_FINISHED;
+ }
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ int hide = 0;
+
+ 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_SEL_TEST(luv, !swap)) {
+ hide = 1;
+ break;
+ }
+ }
+
+ 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);
+ }
+ }
+ 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;
+ }
+ }
+ }
+ }
+ }
+
+ /* 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);
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
}
#undef UV_SEL_TEST
static void UV_OT_hide(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Selected";
- ot->description = "Hide (un)selected UV vertices";
- ot->idname = "UV_OT_hide";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Hide Selected";
+ ot->description = "Hide (un)selected UV vertices";
+ ot->idname = "UV_OT_hide";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* api callbacks */
- ot->exec = uv_hide_exec;
- ot->poll = ED_operator_uvedit;
+ /* api callbacks */
+ ot->exec = uv_hide_exec;
+ ot->poll = ED_operator_uvedit;
- /* props */
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
}
/** \} */
@@ -4232,136 +4389,136 @@ static void UV_OT_hide(wmOperatorType *ot)
static int uv_reveal_exec(bContext *C, wmOperator *op)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- Object *obedit = CTX_data_edit_object(C);
- Scene *scene = CTX_data_scene(C);
- 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 int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- const bool select = RNA_boolean_get(op->ptr, "select");
-
- /* 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(em, 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);
- }
- }
- }
- 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) {
- 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);
- }
- }
- }
- }
- 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);
- }
- }
- }
- }
- }
- 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);
- }
- }
- }
- 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);
- }
- }
- }
-
- /* 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(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ 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 int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ const bool select = RNA_boolean_get(op->ptr, "select");
+
+ /* 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(em, 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);
+ }
+ }
+ }
+ 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) {
+ 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);
+ }
+ }
+ }
+ }
+ 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);
+ }
+ }
+ }
+ }
+ }
+ 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);
+ }
+ }
+ }
+ 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);
+ }
+ }
+ }
+
+ /* 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(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
}
static void UV_OT_reveal(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reveal Hidden";
- ot->description = "Reveal all hidden UV vertices";
- ot->idname = "UV_OT_reveal";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Reveal Hidden";
+ ot->description = "Reveal all hidden UV vertices";
+ ot->idname = "UV_OT_reveal";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* api callbacks */
- ot->exec = uv_reveal_exec;
- ot->poll = ED_operator_uvedit;
+ /* api callbacks */
+ ot->exec = uv_reveal_exec;
+ ot->poll = ED_operator_uvedit;
- RNA_def_boolean(ot->srna, "select", true, "Select", "");
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
/** \} */
@@ -4372,60 +4529,67 @@ static void UV_OT_reveal(wmOperatorType *ot)
static bool uv_set_2d_cursor_poll(bContext *C)
{
- return ED_operator_uvedit_space_image(C) ||
- ED_space_image_maskedit_poll(C) ||
- ED_space_image_paint_curve(C);
+ return ED_operator_uvedit_space_image(C) || ED_space_image_maskedit_poll(C) ||
+ ED_space_image_paint_curve(C);
}
static int uv_set_2d_cursor_exec(bContext *C, wmOperator *op)
{
- SpaceImage *sima = CTX_wm_space_image(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
- if (!sima)
- return OPERATOR_CANCELLED;
+ if (!sima)
+ return OPERATOR_CANCELLED;
- RNA_float_get_array(op->ptr, "location", sima->cursor);
+ RNA_float_get_array(op->ptr, "location", sima->cursor);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int uv_set_2d_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- float location[2];
+ ARegion *ar = CTX_wm_region(C);
+ float location[2];
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- if (event->mval[1] <= 16) {
- SpaceImage *sima = CTX_wm_space_image(C);
- if (sima && ED_space_image_show_cache(sima)) {
- return OPERATOR_PASS_THROUGH;
- }
- }
- }
+ if (ar->regiontype == RGN_TYPE_WINDOW) {
+ if (event->mval[1] <= 16) {
+ SpaceImage *sima = CTX_wm_space_image(C);
+ if (sima && ED_space_image_show_cache(sima)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+ }
+ }
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
- RNA_float_set_array(op->ptr, "location", location);
+ UI_view2d_region_to_view(&ar->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);
+ return uv_set_2d_cursor_exec(C, op);
}
static void UV_OT_cursor_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set 2D Cursor";
- ot->description = "Set 2D cursor location";
- ot->idname = "UV_OT_cursor_set";
-
- /* api callbacks */
- ot->exec = uv_set_2d_cursor_exec;
- ot->invoke = uv_set_2d_cursor_invoke;
- ot->poll = uv_set_2d_cursor_poll;
-
- /* properties */
- RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location",
- "Cursor location in normalized (0.0-1.0) coordinates", -10.0f, 10.0f);
+ /* identifiers */
+ ot->name = "Set 2D Cursor";
+ ot->description = "Set 2D cursor location";
+ ot->idname = "UV_OT_cursor_set";
+
+ /* api callbacks */
+ ot->exec = uv_set_2d_cursor_exec;
+ ot->invoke = uv_set_2d_cursor_invoke;
+ ot->poll = uv_set_2d_cursor_poll;
+
+ /* properties */
+ RNA_def_float_vector(ot->srna,
+ "location",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Location",
+ "Cursor location in normalized (0.0-1.0) coordinates",
+ -10.0f,
+ 10.0f);
}
/** \} */
@@ -4436,136 +4600,136 @@ static void UV_OT_cursor_set(wmOperatorType *ot)
static int uv_seams_from_islands_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- int ret = OPERATOR_CANCELLED;
- const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT};
- const bool mark_seams = RNA_boolean_get(op->ptr, "mark_seams");
- const bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp");
-
- 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 *ob = objects[ob_index];
- Mesh *me = (Mesh *)ob->data;
- BMEditMesh *em = me->edit_mesh;
- BMesh *bm = em->bm;
-
- UvVertMap *vmap;
- BMEdge *editedge;
- BMIter iter;
-
- if (!EDBM_uv_check(em)) {
- continue;
- }
- ret = OPERATOR_FINISHED;
-
- /* This code sets editvert->tmp.l to the index. This will be useful later on. */
- BM_mesh_elem_table_ensure(bm, BM_FACE);
- vmap = BM_uv_vert_map_create(bm, limit, false, false);
-
- BM_ITER_MESH (editedge, &iter, bm, BM_EDGES_OF_MESH) {
- /* flags to determine if we uv is separated from first editface match */
- char separated1 = 0, separated2;
- /* set to denote edge must be flagged as seam */
- char faces_separated = 0;
- /* flag to keep track if uv1 is disconnected from first editface match */
- char v1coincident = 1;
- /* For use with v1coincident. v1coincident will change only if we've had commonFaces */
- int commonFaces = 0;
-
- BMFace *efa1, *efa2;
-
- UvMapVert *mv1, *mvinit1, *mv2, *mvinit2, *mviter;
- /* mv2cache stores the first of the list of coincident uv's for later comparison
- * mv2sep holds the last separator and is copied to mv2cache
- * when a hit is first found */
- UvMapVert *mv2cache = NULL, *mv2sep = NULL;
-
- mvinit1 = vmap->vert[BM_elem_index_get(editedge->v1)];
- if (mark_seams)
- BM_elem_flag_disable(editedge, BM_ELEM_SEAM);
-
- for (mv1 = mvinit1; mv1 && !faces_separated; mv1 = mv1->next) {
- if (mv1->separate && commonFaces)
- v1coincident = 0;
-
- separated2 = 0;
- efa1 = BM_face_at_index(bm, mv1->poly_index);
- mvinit2 = vmap->vert[BM_elem_index_get(editedge->v2)];
-
- for (mv2 = mvinit2; mv2; mv2 = mv2->next) {
- if (mv2->separate)
- mv2sep = mv2;
-
- efa2 = BM_face_at_index(bm, mv2->poly_index);
- if (efa1 == efa2) {
- /* if v1 is not coincident no point in comparing */
- if (v1coincident) {
- /* have we found previously anything? */
- if (mv2cache) {
- /* flag seam unless proved to be coincident with previous hit */
- separated2 = 1;
- for (mviter = mv2cache; mviter; mviter = mviter->next) {
- if (mviter->separate && mviter != mv2cache)
- break;
- /* coincident with previous hit, do not flag seam */
- if (mviter == mv2)
- separated2 = 0;
- }
- }
- /* First hit case, store the hit in the cache */
- else {
- mv2cache = mv2sep;
- commonFaces = 1;
- }
- }
- else
- separated1 = 1;
-
- if (separated1 || separated2) {
- faces_separated = 1;
- break;
- }
- }
- }
- }
-
- if (faces_separated) {
- if (mark_seams)
- BM_elem_flag_enable(editedge, BM_ELEM_SEAM);
- if (mark_sharp)
- BM_elem_flag_disable(editedge, BM_ELEM_SMOOTH);
- }
- }
-
- BM_uv_vert_map_free(vmap);
-
- DEG_id_tag_update(&me->id, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
- }
- MEM_freeN(objects);
-
- return ret;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ int ret = OPERATOR_CANCELLED;
+ const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT};
+ const bool mark_seams = RNA_boolean_get(op->ptr, "mark_seams");
+ const bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp");
+
+ 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 *ob = objects[ob_index];
+ Mesh *me = (Mesh *)ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ BMesh *bm = em->bm;
+
+ UvVertMap *vmap;
+ BMEdge *editedge;
+ BMIter iter;
+
+ if (!EDBM_uv_check(em)) {
+ continue;
+ }
+ ret = OPERATOR_FINISHED;
+
+ /* This code sets editvert->tmp.l to the index. This will be useful later on. */
+ BM_mesh_elem_table_ensure(bm, BM_FACE);
+ vmap = BM_uv_vert_map_create(bm, limit, false, false);
+
+ BM_ITER_MESH (editedge, &iter, bm, BM_EDGES_OF_MESH) {
+ /* flags to determine if we uv is separated from first editface match */
+ char separated1 = 0, separated2;
+ /* set to denote edge must be flagged as seam */
+ char faces_separated = 0;
+ /* flag to keep track if uv1 is disconnected from first editface match */
+ char v1coincident = 1;
+ /* For use with v1coincident. v1coincident will change only if we've had commonFaces */
+ int commonFaces = 0;
+
+ BMFace *efa1, *efa2;
+
+ UvMapVert *mv1, *mvinit1, *mv2, *mvinit2, *mviter;
+ /* mv2cache stores the first of the list of coincident uv's for later comparison
+ * mv2sep holds the last separator and is copied to mv2cache
+ * when a hit is first found */
+ UvMapVert *mv2cache = NULL, *mv2sep = NULL;
+
+ mvinit1 = vmap->vert[BM_elem_index_get(editedge->v1)];
+ if (mark_seams)
+ BM_elem_flag_disable(editedge, BM_ELEM_SEAM);
+
+ for (mv1 = mvinit1; mv1 && !faces_separated; mv1 = mv1->next) {
+ if (mv1->separate && commonFaces)
+ v1coincident = 0;
+
+ separated2 = 0;
+ efa1 = BM_face_at_index(bm, mv1->poly_index);
+ mvinit2 = vmap->vert[BM_elem_index_get(editedge->v2)];
+
+ for (mv2 = mvinit2; mv2; mv2 = mv2->next) {
+ if (mv2->separate)
+ mv2sep = mv2;
+
+ efa2 = BM_face_at_index(bm, mv2->poly_index);
+ if (efa1 == efa2) {
+ /* if v1 is not coincident no point in comparing */
+ if (v1coincident) {
+ /* have we found previously anything? */
+ if (mv2cache) {
+ /* flag seam unless proved to be coincident with previous hit */
+ separated2 = 1;
+ for (mviter = mv2cache; mviter; mviter = mviter->next) {
+ if (mviter->separate && mviter != mv2cache)
+ break;
+ /* coincident with previous hit, do not flag seam */
+ if (mviter == mv2)
+ separated2 = 0;
+ }
+ }
+ /* First hit case, store the hit in the cache */
+ else {
+ mv2cache = mv2sep;
+ commonFaces = 1;
+ }
+ }
+ else
+ separated1 = 1;
+
+ if (separated1 || separated2) {
+ faces_separated = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if (faces_separated) {
+ if (mark_seams)
+ BM_elem_flag_enable(editedge, BM_ELEM_SEAM);
+ if (mark_sharp)
+ BM_elem_flag_disable(editedge, BM_ELEM_SMOOTH);
+ }
+ }
+
+ BM_uv_vert_map_free(vmap);
+
+ DEG_id_tag_update(&me->id, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+ }
+ MEM_freeN(objects);
+
+ return ret;
}
-
static void UV_OT_seams_from_islands(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Seams From Islands";
- ot->description = "Set mesh seams according to island setup in the UV editor";
- ot->idname = "UV_OT_seams_from_islands";
+ /* identifiers */
+ ot->name = "Seams From Islands";
+ ot->description = "Set mesh seams according to island setup in the UV editor";
+ ot->idname = "UV_OT_seams_from_islands";
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* api callbacks */
- ot->exec = uv_seams_from_islands_exec;
- ot->poll = ED_operator_uvedit;
+ /* api callbacks */
+ ot->exec = uv_seams_from_islands_exec;
+ ot->poll = ED_operator_uvedit;
- RNA_def_boolean(ot->srna, "mark_seams", 1, "Mark Seams", "Mark boundary edges as seams");
- RNA_def_boolean(ot->srna, "mark_sharp", 0, "Mark Sharp", "Mark boundary edges as sharp");
+ RNA_def_boolean(ot->srna, "mark_seams", 1, "Mark Seams", "Mark boundary edges as seams");
+ RNA_def_boolean(ot->srna, "mark_sharp", 0, "Mark Sharp", "Mark boundary edges as sharp");
}
/** \} */
@@ -4576,95 +4740,106 @@ static void UV_OT_seams_from_islands(wmOperatorType *ot)
static int uv_mark_seam_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- ToolSettings *ts = scene->toolsettings;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ ToolSettings *ts = scene->toolsettings;
- BMFace *efa;
- BMLoop *loop;
- BMIter iter, liter;
+ BMFace *efa;
+ BMLoop *loop;
+ BMIter iter, liter;
- const bool flag_set = !RNA_boolean_get(op->ptr, "clear");
- const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
+ const bool flag_set = !RNA_boolean_get(op->ptr, "clear");
+ const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
- 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);
+ 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 changed = false;
+ bool changed = false;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- Mesh *me = (Mesh *)ob->data;
- BMEditMesh *em = me->edit_mesh;
- BMesh *bm = em->bm;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ Mesh *me = (Mesh *)ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ BMesh *bm = em->bm;
- if (synced_selection && (bm->totedgesel == 0)) {
- continue;
- }
+ if (synced_selection && (bm->totedgesel == 0)) {
+ continue;
+ }
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ 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;
- }
- }
- }
+ 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 (changed) {
- DEG_id_tag_update(&me->id, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
- }
- }
+ if (changed) {
+ DEG_id_tag_update(&me->id, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+ }
+ }
- if (changed) {
- ED_uvedit_live_unwrap(scene, objects, objects_len);
- }
+ if (changed) {
+ ED_uvedit_live_unwrap(scene, objects, objects_len);
+ }
- MEM_freeN(objects);
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int uv_mark_seam_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- uiPopupMenu *pup;
- uiLayout *layout;
+ uiPopupMenu *pup;
+ uiLayout *layout;
- if (RNA_struct_property_is_set(op->ptr, "clear")) {
- return uv_mark_seam_exec(C, op);
- }
+ if (RNA_struct_property_is_set(op->ptr, "clear")) {
+ return uv_mark_seam_exec(C, op);
+ }
- pup = UI_popup_menu_begin(C, IFACE_("Edges"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
+ pup = UI_popup_menu_begin(C, IFACE_("Edges"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
- uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
- uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Mark Seam"), ICON_NONE, op->type->idname, "clear", false);
- uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Seam"), ICON_NONE, op->type->idname, "clear", true);
+ uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Mark Seam"),
+ ICON_NONE,
+ op->type->idname,
+ "clear",
+ false);
+ uiItemBooleanO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Seam"),
+ ICON_NONE,
+ op->type->idname,
+ "clear",
+ true);
- UI_popup_menu_end(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
static void UV_OT_mark_seam(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Mark Seam";
- ot->description = "Mark selected UV edges as seams";
- ot->idname = "UV_OT_mark_seam";
+ /* identifiers */
+ ot->name = "Mark Seam";
+ ot->description = "Mark selected UV edges as seams";
+ ot->idname = "UV_OT_mark_seam";
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* api callbacks */
- ot->exec = uv_mark_seam_exec;
- ot->invoke = uv_mark_seam_invoke;
- ot->poll = ED_operator_uvedit;
+ /* api callbacks */
+ ot->exec = uv_mark_seam_exec;
+ ot->invoke = uv_mark_seam_invoke;
+ ot->poll = ED_operator_uvedit;
- RNA_def_boolean(ot->srna, "clear", false, "Clear Seams", "Clear instead of marking seams");
+ RNA_def_boolean(ot->srna, "clear", false, "Clear Seams", "Clear instead of marking seams");
}
/** \} */
@@ -4675,54 +4850,54 @@ static void UV_OT_mark_seam(wmOperatorType *ot)
void ED_operatortypes_uvedit(void)
{
- WM_operatortype_append(UV_OT_select_all);
- WM_operatortype_append(UV_OT_select);
- WM_operatortype_append(UV_OT_select_loop);
- WM_operatortype_append(UV_OT_select_linked);
- WM_operatortype_append(UV_OT_select_linked_pick);
- WM_operatortype_append(UV_OT_select_split);
- WM_operatortype_append(UV_OT_select_pinned);
- WM_operatortype_append(UV_OT_select_box);
- WM_operatortype_append(UV_OT_select_lasso);
- WM_operatortype_append(UV_OT_select_circle);
- WM_operatortype_append(UV_OT_select_more);
- WM_operatortype_append(UV_OT_select_less);
+ WM_operatortype_append(UV_OT_select_all);
+ WM_operatortype_append(UV_OT_select);
+ WM_operatortype_append(UV_OT_select_loop);
+ WM_operatortype_append(UV_OT_select_linked);
+ WM_operatortype_append(UV_OT_select_linked_pick);
+ WM_operatortype_append(UV_OT_select_split);
+ WM_operatortype_append(UV_OT_select_pinned);
+ WM_operatortype_append(UV_OT_select_box);
+ WM_operatortype_append(UV_OT_select_lasso);
+ WM_operatortype_append(UV_OT_select_circle);
+ WM_operatortype_append(UV_OT_select_more);
+ WM_operatortype_append(UV_OT_select_less);
- WM_operatortype_append(UV_OT_snap_cursor);
- WM_operatortype_append(UV_OT_snap_selected);
+ WM_operatortype_append(UV_OT_snap_cursor);
+ WM_operatortype_append(UV_OT_snap_selected);
- WM_operatortype_append(UV_OT_align);
+ WM_operatortype_append(UV_OT_align);
- WM_operatortype_append(UV_OT_stitch);
+ WM_operatortype_append(UV_OT_stitch);
- WM_operatortype_append(UV_OT_seams_from_islands);
- WM_operatortype_append(UV_OT_mark_seam);
- WM_operatortype_append(UV_OT_weld);
- WM_operatortype_append(UV_OT_remove_doubles);
- WM_operatortype_append(UV_OT_pin);
+ WM_operatortype_append(UV_OT_seams_from_islands);
+ WM_operatortype_append(UV_OT_mark_seam);
+ WM_operatortype_append(UV_OT_weld);
+ WM_operatortype_append(UV_OT_remove_doubles);
+ WM_operatortype_append(UV_OT_pin);
- WM_operatortype_append(UV_OT_average_islands_scale);
- WM_operatortype_append(UV_OT_cube_project);
- WM_operatortype_append(UV_OT_cylinder_project);
- WM_operatortype_append(UV_OT_project_from_view);
- WM_operatortype_append(UV_OT_minimize_stretch);
- WM_operatortype_append(UV_OT_pack_islands);
- WM_operatortype_append(UV_OT_reset);
- WM_operatortype_append(UV_OT_sphere_project);
- WM_operatortype_append(UV_OT_unwrap);
+ WM_operatortype_append(UV_OT_average_islands_scale);
+ WM_operatortype_append(UV_OT_cube_project);
+ WM_operatortype_append(UV_OT_cylinder_project);
+ WM_operatortype_append(UV_OT_project_from_view);
+ WM_operatortype_append(UV_OT_minimize_stretch);
+ WM_operatortype_append(UV_OT_pack_islands);
+ WM_operatortype_append(UV_OT_reset);
+ WM_operatortype_append(UV_OT_sphere_project);
+ WM_operatortype_append(UV_OT_unwrap);
- WM_operatortype_append(UV_OT_reveal);
- WM_operatortype_append(UV_OT_hide);
+ WM_operatortype_append(UV_OT_reveal);
+ WM_operatortype_append(UV_OT_hide);
- WM_operatortype_append(UV_OT_cursor_set);
+ WM_operatortype_append(UV_OT_cursor_set);
}
void ED_keymap_uvedit(wmKeyConfig *keyconf)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- keymap = WM_keymap_ensure(keyconf, "UV Editor", 0, 0);
- keymap->poll = ED_operator_uvedit_can_uv_sculpt;
+ keymap = WM_keymap_ensure(keyconf, "UV Editor", 0, 0);
+ keymap->poll = ED_operator_uvedit_can_uv_sculpt;
}
/** \} */
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index 1a4e040472e..69183d02ab9 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -37,7 +37,7 @@
#include <stdio.h>
#include <string.h>
-#include "BLI_sys_types.h" /* for intptr_t support */
+#include "BLI_sys_types.h" /* for intptr_t support */
#include "eigen_capi.h"
@@ -50,22 +50,25 @@
# define param_test_equals_int(condition)
#else
# define param_assert(condition) \
- if (!(condition)) \
- { /*printf("Assertion %s:%d\n", __FILE__, __LINE__); abort();*/ } (void)0
+ if (!(condition)) { /*printf("Assertion %s:%d\n", __FILE__, __LINE__); abort();*/ \
+ } \
+ (void)0
# define param_warning(message) \
- { /*printf("Warning %s:%d: %s\n", __FILE__, __LINE__, message);*/ } (void)0
+ {/*printf("Warning %s:%d: %s\n", __FILE__, __LINE__, message);*/}(void)0
# if 0
# define param_test_equals_ptr(str, a, b) \
- if (a != b) \
- { /*printf("Equals %s => %p != %p\n", str, a, b);*/ } (void)0
+ if (a != b) { /*printf("Equals %s => %p != %p\n", str, a, b);*/ \
+ } \
+ (void)0
# define param_test_equals_int(str, a, b) \
- if (a != b) \
- { /*printf("Equals %s => %d != %d\n", str, a, b);*/ } (void)0
+ if (a != b) { /*printf("Equals %s => %d != %d\n", str, a, b);*/ \
+ } \
+ (void)0
# endif
#endif
typedef enum PBool {
- P_TRUE = 1,
- P_FALSE = 0,
+ P_TRUE = 1,
+ P_FALSE = 0,
} PBool;
/* Special Purpose Hash */
@@ -73,18 +76,16 @@ typedef enum PBool {
typedef intptr_t PHashKey;
typedef struct PHashLink {
- struct PHashLink *next;
- PHashKey key;
+ struct PHashLink *next;
+ PHashKey key;
} PHashLink;
typedef struct PHash {
- PHashLink **list;
- PHashLink **buckets;
- int size, cursize, cursize_id;
+ PHashLink **list;
+ PHashLink **buckets;
+ int size, cursize, cursize_id;
} PHash;
-
-
struct PChart;
struct PEdge;
struct PFace;
@@ -94,142 +95,142 @@ struct PVert;
/* Simplices */
typedef struct PVert {
- struct PVert *nextlink;
+ struct PVert *nextlink;
- union PVertUnion {
- PHashKey key; /* construct */
- int id; /* abf/lscm matrix index */
- float distortion; /* area smoothing */
- HeapNode *heaplink; /* edge collapsing */
- } u;
+ union PVertUnion {
+ PHashKey key; /* construct */
+ int id; /* abf/lscm matrix index */
+ float distortion; /* area smoothing */
+ HeapNode *heaplink; /* edge collapsing */
+ } u;
- struct PEdge *edge;
- float co[3];
- float uv[2];
- unsigned char flag;
+ struct PEdge *edge;
+ float co[3];
+ float uv[2];
+ unsigned char flag;
} PVert;
typedef struct PEdge {
- struct PEdge *nextlink;
-
- union PEdgeUnion {
- PHashKey key; /* construct */
- int id; /* abf matrix index */
- HeapNode *heaplink; /* fill holes */
- struct PEdge *nextcollapse; /* simplification */
- } u;
-
- struct PVert *vert;
- struct PEdge *pair;
- struct PEdge *next;
- struct PFace *face;
- float *orig_uv, old_uv[2];
- unsigned short flag;
+ struct PEdge *nextlink;
+
+ union PEdgeUnion {
+ PHashKey key; /* construct */
+ int id; /* abf matrix index */
+ HeapNode *heaplink; /* fill holes */
+ struct PEdge *nextcollapse; /* simplification */
+ } u;
+
+ struct PVert *vert;
+ struct PEdge *pair;
+ struct PEdge *next;
+ struct PFace *face;
+ float *orig_uv, old_uv[2];
+ unsigned short flag;
} PEdge;
typedef struct PFace {
- struct PFace *nextlink;
+ struct PFace *nextlink;
- union PFaceUnion {
- PHashKey key; /* construct */
- int chart; /* construct splitting*/
- float area3d; /* stretch */
- int id; /* abf matrix index */
- } u;
+ union PFaceUnion {
+ PHashKey key; /* construct */
+ int chart; /* construct splitting*/
+ float area3d; /* stretch */
+ int id; /* abf matrix index */
+ } u;
- struct PEdge *edge;
- unsigned char flag;
+ struct PEdge *edge;
+ unsigned char flag;
} PFace;
enum PVertFlag {
- PVERT_PIN = 1,
- PVERT_SELECT = 2,
- PVERT_INTERIOR = 4,
- PVERT_COLLAPSE = 8,
- PVERT_SPLIT = 16,
+ PVERT_PIN = 1,
+ PVERT_SELECT = 2,
+ PVERT_INTERIOR = 4,
+ PVERT_COLLAPSE = 8,
+ PVERT_SPLIT = 16,
};
enum PEdgeFlag {
- PEDGE_SEAM = 1,
- PEDGE_VERTEX_SPLIT = 2,
- PEDGE_PIN = 4,
- PEDGE_SELECT = 8,
- PEDGE_DONE = 16,
- PEDGE_FILLED = 32,
- PEDGE_COLLAPSE = 64,
- PEDGE_COLLAPSE_EDGE = 128,
- PEDGE_COLLAPSE_PAIR = 256,
+ PEDGE_SEAM = 1,
+ PEDGE_VERTEX_SPLIT = 2,
+ PEDGE_PIN = 4,
+ PEDGE_SELECT = 8,
+ PEDGE_DONE = 16,
+ PEDGE_FILLED = 32,
+ PEDGE_COLLAPSE = 64,
+ PEDGE_COLLAPSE_EDGE = 128,
+ PEDGE_COLLAPSE_PAIR = 256,
};
/* for flipping faces */
#define PEDGE_VERTEX_FLAGS (PEDGE_PIN)
enum PFaceFlag {
- PFACE_CONNECTED = 1,
- PFACE_FILLED = 2,
- PFACE_COLLAPSE = 4,
+ PFACE_CONNECTED = 1,
+ PFACE_FILLED = 2,
+ PFACE_COLLAPSE = 4,
};
/* Chart */
typedef struct PChart {
- PVert *verts;
- PEdge *edges;
- PFace *faces;
- int nverts, nedges, nfaces;
-
- PVert *collapsed_verts;
- PEdge *collapsed_edges;
- PFace *collapsed_faces;
-
- union PChartUnion {
- struct PChartLscm {
- LinearSolver *context;
- float *abf_alpha;
- PVert *pin1, *pin2;
- } lscm;
- struct PChartPack {
- float rescale, area;
- float size[2] /* , trans[2] */;
- } pack;
- } u;
-
- unsigned char flag;
- struct PHandle *handle;
+ PVert *verts;
+ PEdge *edges;
+ PFace *faces;
+ int nverts, nedges, nfaces;
+
+ PVert *collapsed_verts;
+ PEdge *collapsed_edges;
+ PFace *collapsed_faces;
+
+ union PChartUnion {
+ struct PChartLscm {
+ LinearSolver *context;
+ float *abf_alpha;
+ PVert *pin1, *pin2;
+ } lscm;
+ struct PChartPack {
+ float rescale, area;
+ float size[2] /* , trans[2] */;
+ } pack;
+ } u;
+
+ unsigned char flag;
+ struct PHandle *handle;
} PChart;
enum PChartFlag {
- PCHART_HAS_PINS = 1,
+ PCHART_HAS_PINS = 1,
};
enum PHandleState {
- PHANDLE_STATE_ALLOCATED,
- PHANDLE_STATE_CONSTRUCTED,
- PHANDLE_STATE_LSCM,
- PHANDLE_STATE_STRETCH,
+ PHANDLE_STATE_ALLOCATED,
+ PHANDLE_STATE_CONSTRUCTED,
+ PHANDLE_STATE_LSCM,
+ PHANDLE_STATE_STRETCH,
};
typedef struct PHandle {
- enum PHandleState state;
- MemArena *arena;
- MemArena *polyfill_arena;
- Heap *polyfill_heap;
+ enum PHandleState state;
+ MemArena *arena;
+ MemArena *polyfill_arena;
+ Heap *polyfill_heap;
- PChart *construction_chart;
- PHash *hash_verts;
- PHash *hash_edges;
- PHash *hash_faces;
+ PChart *construction_chart;
+ PHash *hash_verts;
+ PHash *hash_edges;
+ PHash *hash_faces;
- PChart **charts;
- int ncharts;
+ PChart **charts;
+ int ncharts;
- float aspx, aspy;
+ float aspx, aspy;
- RNG *rng;
- float blend;
- char do_aspect;
+ RNG *rng;
+ float blend;
+ char do_aspect;
} PHandle;
/* PHash
@@ -239,315 +240,319 @@ typedef struct PHandle {
*/
static int PHashSizes[] = {
- 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
- 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169,
- 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459,
+ 1, 3, 5, 11, 17, 37, 67, 131, 257, 521,
+ 1031, 2053, 4099, 8209, 16411, 32771, 65537, 131101, 262147, 524309,
+ 1048583, 2097169, 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459,
};
-#define PHASH_hash(ph, item) (((uintptr_t) (item)) % ((unsigned int) (ph)->cursize))
-#define PHASH_edge(v1, v2) (((v1) < (v2)) ? ((v1) * 39) ^ ((v2) * 31) : ((v1) * 31) ^ ((v2) * 39))
+#define PHASH_hash(ph, item) (((uintptr_t)(item)) % ((unsigned int)(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)
{
- PHash *ph = (PHash *)MEM_callocN(sizeof(PHash), "PHash");
- ph->size = 0;
- ph->cursize_id = 0;
- ph->list = list;
+ PHash *ph = (PHash *)MEM_callocN(sizeof(PHash), "PHash");
+ ph->size = 0;
+ ph->cursize_id = 0;
+ ph->list = list;
- while (PHashSizes[ph->cursize_id] < sizehint)
- ph->cursize_id++;
+ while (PHashSizes[ph->cursize_id] < sizehint)
+ ph->cursize_id++;
- ph->cursize = PHashSizes[ph->cursize_id];
- ph->buckets = (PHashLink **)MEM_callocN(ph->cursize * sizeof(*ph->buckets), "PHashBuckets");
+ ph->cursize = PHashSizes[ph->cursize_id];
+ ph->buckets = (PHashLink **)MEM_callocN(ph->cursize * sizeof(*ph->buckets), "PHashBuckets");
- return ph;
+ return ph;
}
static void phash_delete(PHash *ph)
{
- MEM_freeN(ph->buckets);
- MEM_freeN(ph);
+ MEM_freeN(ph->buckets);
+ MEM_freeN(ph);
}
static int phash_size(PHash *ph)
{
- return ph->size;
+ return ph->size;
}
static void phash_insert(PHash *ph, PHashLink *link)
{
- int size = ph->cursize;
- uintptr_t hash = PHASH_hash(ph, link->key);
- PHashLink *lookup = ph->buckets[hash];
+ int size = ph->cursize;
+ uintptr_t hash = PHASH_hash(ph, link->key);
+ PHashLink *lookup = ph->buckets[hash];
- if (lookup == NULL) {
- /* insert in front of the list */
- ph->buckets[hash] = link;
- link->next = *(ph->list);
- *(ph->list) = link;
- }
- else {
- /* insert after existing element */
- link->next = lookup->next;
- lookup->next = link;
- }
+ if (lookup == NULL) {
+ /* insert in front of the list */
+ ph->buckets[hash] = link;
+ link->next = *(ph->list);
+ *(ph->list) = link;
+ }
+ else {
+ /* insert after existing element */
+ link->next = lookup->next;
+ lookup->next = link;
+ }
- ph->size++;
+ ph->size++;
- if (ph->size > (size * 3)) {
- PHashLink *next = NULL, *first = *(ph->list);
+ if (ph->size > (size * 3)) {
+ PHashLink *next = NULL, *first = *(ph->list);
- ph->cursize = PHashSizes[++ph->cursize_id];
- MEM_freeN(ph->buckets);
- ph->buckets = (PHashLink **)MEM_callocN(ph->cursize * sizeof(*ph->buckets), "PHashBuckets");
- ph->size = 0;
- *(ph->list) = NULL;
+ ph->cursize = PHashSizes[++ph->cursize_id];
+ MEM_freeN(ph->buckets);
+ ph->buckets = (PHashLink **)MEM_callocN(ph->cursize * sizeof(*ph->buckets), "PHashBuckets");
+ ph->size = 0;
+ *(ph->list) = NULL;
- for (link = first; link; link = next) {
- next = link->next;
- phash_insert(ph, link);
- }
- }
+ for (link = first; link; link = next) {
+ next = link->next;
+ phash_insert(ph, link);
+ }
+ }
}
static PHashLink *phash_lookup(PHash *ph, PHashKey key)
{
- PHashLink *link;
- uintptr_t hash = PHASH_hash(ph, key);
+ PHashLink *link;
+ uintptr_t hash = PHASH_hash(ph, key);
- for (link = ph->buckets[hash]; link; link = link->next)
- if (link->key == key)
- return link;
- else if (PHASH_hash(ph, link->key) != hash)
- return NULL;
+ for (link = ph->buckets[hash]; link; link = link->next)
+ if (link->key == key)
+ return link;
+ else if (PHASH_hash(ph, link->key) != hash)
+ return NULL;
- return link;
+ return link;
}
static PHashLink *phash_next(PHash *ph, PHashKey key, PHashLink *link)
{
- uintptr_t hash = PHASH_hash(ph, key);
+ uintptr_t hash = PHASH_hash(ph, key);
- for (link = link->next; link; link = link->next)
- if (link->key == key)
- return link;
- else if (PHASH_hash(ph, link->key) != hash)
- return NULL;
+ for (link = link->next; link; link = link->next)
+ if (link->key == key)
+ return link;
+ else if (PHASH_hash(ph, link->key) != hash)
+ return NULL;
- return link;
+ return link;
}
/* Geometry */
static float p_vec_angle_cos(float *v1, float *v2, float *v3)
{
- float d1[3], d2[3];
+ float d1[3], d2[3];
- d1[0] = v1[0] - v2[0];
- d1[1] = v1[1] - v2[1];
- d1[2] = v1[2] - v2[2];
+ d1[0] = v1[0] - v2[0];
+ d1[1] = v1[1] - v2[1];
+ d1[2] = v1[2] - v2[2];
- d2[0] = v3[0] - v2[0];
- d2[1] = v3[1] - v2[1];
- d2[2] = v3[2] - v2[2];
+ d2[0] = v3[0] - v2[0];
+ d2[1] = v3[1] - v2[1];
+ d2[2] = v3[2] - v2[2];
- normalize_v3(d1);
- normalize_v3(d2);
+ normalize_v3(d1);
+ normalize_v3(d2);
- return d1[0] * d2[0] + d1[1] * d2[1] + d1[2] * d2[2];
+ return d1[0] * d2[0] + d1[1] * d2[1] + d1[2] * d2[2];
}
static float p_vec_angle(float *v1, float *v2, float *v3)
{
- float dot = p_vec_angle_cos(v1, v2, v3);
+ float dot = p_vec_angle_cos(v1, v2, v3);
- if (dot <= -1.0f)
- return (float)M_PI;
- else if (dot >= 1.0f)
- return 0.0f;
- else
- return acosf(dot);
+ if (dot <= -1.0f)
+ return (float)M_PI;
+ else if (dot >= 1.0f)
+ return 0.0f;
+ else
+ return acosf(dot);
}
static float p_vec2_angle(float *v1, float *v2, float *v3)
{
- float u1[3], u2[3], u3[3];
+ float u1[3], u2[3], u3[3];
- u1[0] = v1[0]; u1[1] = v1[1]; u1[2] = 0.0f;
- u2[0] = v2[0]; u2[1] = v2[1]; u2[2] = 0.0f;
- u3[0] = v3[0]; u3[1] = v3[1]; u3[2] = 0.0f;
+ u1[0] = v1[0];
+ u1[1] = v1[1];
+ u1[2] = 0.0f;
+ u2[0] = v2[0];
+ u2[1] = v2[1];
+ u2[2] = 0.0f;
+ u3[0] = v3[0];
+ u3[1] = v3[1];
+ u3[2] = 0.0f;
- return p_vec_angle(u1, u2, u3);
+ return p_vec_angle(u1, u2, u3);
}
static void p_triangle_angles(float *v1, float *v2, float *v3, float *a1, float *a2, float *a3)
{
- *a1 = p_vec_angle(v3, v1, v2);
- *a2 = p_vec_angle(v1, v2, v3);
- *a3 = (float)M_PI - *a2 - *a1;
+ *a1 = p_vec_angle(v3, v1, v2);
+ *a2 = p_vec_angle(v1, v2, v3);
+ *a3 = (float)M_PI - *a2 - *a1;
}
static void p_face_angles(PFace *f, float *a1, float *a2, float *a3)
{
- PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
- PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
+ 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, a1, a2, a3);
}
static float p_face_area(PFace *f)
{
- PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
- PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
- return area_tri_v3(v1->co, v2->co, v3->co);
+ return area_tri_v3(v1->co, v2->co, v3->co);
}
static float p_area_signed(float *v1, float *v2, float *v3)
{
- return 0.5f * (((v2[0] - v1[0]) * (v3[1] - v1[1])) -
- ((v3[0] - v1[0]) * (v2[1] - v1[1])));
+ return 0.5f * (((v2[0] - v1[0]) * (v3[1] - v1[1])) - ((v3[0] - v1[0]) * (v2[1] - v1[1])));
}
static float p_face_uv_area_signed(PFace *f)
{
- PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
- PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
- return 0.5f * (((v2->uv[0] - v1->uv[0]) * (v3->uv[1] - v1->uv[1])) -
- ((v3->uv[0] - v1->uv[0]) * (v2->uv[1] - v1->uv[1])));
+ return 0.5f * (((v2->uv[0] - v1->uv[0]) * (v3->uv[1] - v1->uv[1])) -
+ ((v3->uv[0] - v1->uv[0]) * (v2->uv[1] - v1->uv[1])));
}
static float p_edge_length(PEdge *e)
{
- PVert *v1 = e->vert, *v2 = e->next->vert;
- float d[3];
+ PVert *v1 = e->vert, *v2 = e->next->vert;
+ float d[3];
- d[0] = v2->co[0] - v1->co[0];
- d[1] = v2->co[1] - v1->co[1];
- d[2] = v2->co[2] - v1->co[2];
+ d[0] = v2->co[0] - v1->co[0];
+ d[1] = v2->co[1] - v1->co[1];
+ d[2] = v2->co[2] - v1->co[2];
- return sqrtf(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
+ return sqrtf(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
}
static float p_edge_uv_length(PEdge *e)
{
- PVert *v1 = e->vert, *v2 = e->next->vert;
- float d[3];
+ PVert *v1 = e->vert, *v2 = e->next->vert;
+ float d[3];
- d[0] = v2->uv[0] - v1->uv[0];
- d[1] = v2->uv[1] - v1->uv[1];
+ d[0] = v2->uv[0] - v1->uv[0];
+ d[1] = v2->uv[1] - v1->uv[1];
- return sqrtf(d[0] * d[0] + d[1] * d[1]);
+ return sqrtf(d[0] * d[0] + d[1] * d[1]);
}
static void p_chart_uv_bbox(PChart *chart, float minv[2], float maxv[2])
{
- PVert *v;
+ PVert *v;
- INIT_MINMAX2(minv, maxv);
+ INIT_MINMAX2(minv, maxv);
- for (v = chart->verts; v; v = v->nextlink) {
- minmax_v2v2_v2(minv, maxv, v->uv);
- }
+ for (v = chart->verts; v; v = v->nextlink) {
+ minmax_v2v2_v2(minv, maxv, v->uv);
+ }
}
static void p_chart_uv_scale(PChart *chart, float scale)
{
- PVert *v;
+ PVert *v;
- for (v = chart->verts; v; v = v->nextlink) {
- v->uv[0] *= scale;
- v->uv[1] *= scale;
- }
+ for (v = chart->verts; v; v = v->nextlink) {
+ v->uv[0] *= scale;
+ v->uv[1] *= scale;
+ }
}
static void p_chart_uv_scale_xy(PChart *chart, float x, float y)
{
- PVert *v;
+ PVert *v;
- for (v = chart->verts; v; v = v->nextlink) {
- v->uv[0] *= x;
- v->uv[1] *= y;
- }
+ for (v = chart->verts; v; v = v->nextlink) {
+ v->uv[0] *= x;
+ v->uv[1] *= y;
+ }
}
static void p_chart_uv_translate(PChart *chart, float trans[2])
{
- PVert *v;
+ PVert *v;
- for (v = chart->verts; v; v = v->nextlink) {
- v->uv[0] += trans[0];
- v->uv[1] += trans[1];
- }
+ for (v = chart->verts; v; v = v->nextlink) {
+ v->uv[0] += trans[0];
+ v->uv[1] += trans[1];
+ }
}
static void p_chart_uv_transform(PChart *chart, float mat[2][2])
{
- PVert *v;
+ PVert *v;
- for (v = chart->verts; v; v = v->nextlink) {
- mul_m2v2(mat, v->uv);
- }
+ for (v = chart->verts; v; v = v->nextlink) {
+ mul_m2v2(mat, v->uv);
+ }
}
static void p_chart_uv_to_array(PChart *chart, float (*points)[2])
{
- PVert *v;
- unsigned int i = 0;
+ PVert *v;
+ unsigned int i = 0;
- for (v = chart->verts; v; v = v->nextlink) {
- copy_v2_v2(points[i++], v->uv);
- }
+ for (v = chart->verts; v; v = v->nextlink) {
+ copy_v2_v2(points[i++], v->uv);
+ }
}
static void UNUSED_FUNCTION(p_chart_uv_from_array)(PChart *chart, float (*points)[2])
{
- PVert *v;
- unsigned int i = 0;
+ PVert *v;
+ unsigned int i = 0;
- for (v = chart->verts; v; v = v->nextlink) {
- copy_v2_v2(v->uv, points[i++]);
- }
+ 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)
{
- float lmbda, div;
+ float lmbda, div;
- div = dir2[0] * dir1[1] - dir2[1] * dir1[0];
+ div = dir2[0] * dir1[1] - dir2[1] * dir1[0];
- if (div == 0.0f)
- return P_FALSE;
+ if (div == 0.0f)
+ return P_FALSE;
- 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];
+ 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];
- return P_TRUE;
+ return P_TRUE;
}
#if 0
static PBool p_intersect_line_2d(float *v1, float *v2, float *v3, float *v4, float *isect)
{
- float dir1[2], dir2[2];
+ float dir1[2], dir2[2];
- dir1[0] = v4[0] - v3[0];
- dir1[1] = v4[1] - v3[1];
+ dir1[0] = v4[0] - v3[0];
+ dir1[1] = v4[1] - v3[1];
- dir2[0] = v2[0] - v1[0];
- dir2[1] = v2[1] - v1[1];
+ dir2[0] = v2[0] - v1[0];
+ dir2[1] = v2[1] - v1[1];
- if (!p_intersect_line_2d_dir(v1, dir1, v2, dir2, isect)) {
- /* parallel - should never happen in theory for polygon kernel, but
- * let's give a point nearby in case things go wrong */
- isect[0] = (v1[0] + v2[0]) * 0.5f;
- isect[1] = (v1[1] + v2[1]) * 0.5f;
- return P_FALSE;
- }
+ if (!p_intersect_line_2d_dir(v1, dir1, v2, dir2, isect)) {
+ /* parallel - should never happen in theory for polygon kernel, but
+ * let's give a point nearby in case things go wrong */
+ isect[0] = (v1[0] + v2[0]) * 0.5f;
+ isect[1] = (v1[1] + v2[1]) * 0.5f;
+ return P_FALSE;
+ }
- return P_TRUE;
+ return P_TRUE;
}
#endif
@@ -555,75 +560,75 @@ static PBool p_intersect_line_2d(float *v1, float *v2, float *v3, float *v4, flo
static PEdge *p_wheel_edge_next(PEdge *e)
{
- return e->next->next->pair;
+ return e->next->next->pair;
}
static PEdge *p_wheel_edge_prev(PEdge *e)
{
- return (e->pair) ? e->pair->next : NULL;
+ return (e->pair) ? e->pair->next : NULL;
}
static PEdge *p_boundary_edge_next(PEdge *e)
{
- return e->next->vert->edge;
+ return e->next->vert->edge;
}
static PEdge *p_boundary_edge_prev(PEdge *e)
{
- PEdge *we = e, *last;
+ PEdge *we = e, *last;
- do {
- last = we;
- we = p_wheel_edge_next(we);
- } while (we && (we != e));
+ do {
+ last = we;
+ we = p_wheel_edge_next(we);
+ } while (we && (we != e));
- return last->next->next;
+ return last->next->next;
}
static PBool p_vert_interior(PVert *v)
{
- return (v->edge->pair != NULL);
+ return (v->edge->pair != NULL);
}
static void p_face_flip(PFace *f)
{
- PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
- PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
- int f1 = e1->flag, f2 = e2->flag, f3 = e3->flag;
- float *orig_uv1 = e1->orig_uv, *orig_uv2 = e2->orig_uv, *orig_uv3 = e3->orig_uv;
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
+ int f1 = e1->flag, f2 = e2->flag, f3 = e3->flag;
+ float *orig_uv1 = e1->orig_uv, *orig_uv2 = e2->orig_uv, *orig_uv3 = e3->orig_uv;
- e1->vert = v2;
- e1->next = e3;
- e1->orig_uv = orig_uv2;
- e1->flag = (f1 & ~PEDGE_VERTEX_FLAGS) | (f2 & PEDGE_VERTEX_FLAGS);
+ e1->vert = v2;
+ e1->next = e3;
+ e1->orig_uv = orig_uv2;
+ e1->flag = (f1 & ~PEDGE_VERTEX_FLAGS) | (f2 & PEDGE_VERTEX_FLAGS);
- e2->vert = v3;
- e2->next = e1;
- e2->orig_uv = orig_uv3;
- e2->flag = (f2 & ~PEDGE_VERTEX_FLAGS) | (f3 & PEDGE_VERTEX_FLAGS);
+ e2->vert = v3;
+ e2->next = e1;
+ e2->orig_uv = orig_uv3;
+ e2->flag = (f2 & ~PEDGE_VERTEX_FLAGS) | (f3 & PEDGE_VERTEX_FLAGS);
- e3->vert = v1;
- e3->next = e2;
- e3->orig_uv = orig_uv1;
- e3->flag = (f3 & ~PEDGE_VERTEX_FLAGS) | (f1 & PEDGE_VERTEX_FLAGS);
+ e3->vert = v1;
+ e3->next = e2;
+ e3->orig_uv = orig_uv1;
+ e3->flag = (f3 & ~PEDGE_VERTEX_FLAGS) | (f1 & PEDGE_VERTEX_FLAGS);
}
#if 0
static void p_chart_topological_sanity_check(PChart *chart)
{
- PVert *v;
- PEdge *e;
+ PVert *v;
+ PEdge *e;
- for (v = chart->verts; v; v = v->nextlink)
- param_test_equals_ptr("v->edge->vert", v, v->edge->vert);
+ for (v = chart->verts; v; v = v->nextlink)
+ param_test_equals_ptr("v->edge->vert", v, v->edge->vert);
- for (e = chart->edges; e; e = e->nextlink) {
- if (e->pair) {
- param_test_equals_ptr("e->pair->pair", e, e->pair->pair);
- param_test_equals_ptr("pair->vert", e->vert, e->pair->next->vert);
- param_test_equals_ptr("pair->next->vert", e->next->vert, e->pair->vert);
- }
- }
+ for (e = chart->edges; e; e = e->nextlink) {
+ if (e->pair) {
+ param_test_equals_ptr("e->pair->pair", e, e->pair->pair);
+ param_test_equals_ptr("pair->vert", e->vert, e->pair->next->vert);
+ param_test_equals_ptr("pair->next->vert", e->next->vert, e->pair->vert);
+ }
+ }
}
#endif
@@ -631,737 +636,748 @@ static void p_chart_topological_sanity_check(PChart *chart)
static void p_vert_load_pin_select_uvs(PHandle *handle, PVert *v)
{
- PEdge *e;
- int nedges = 0, npins = 0;
- float pinuv[2];
-
- v->uv[0] = v->uv[1] = 0.0f;
- pinuv[0] = pinuv[1] = 0.0f;
- e = v->edge;
- do {
- if (e->orig_uv) {
- if (e->flag & PEDGE_SELECT)
- v->flag |= PVERT_SELECT;
-
- if (e->flag & PEDGE_PIN) {
- pinuv[0] += e->orig_uv[0] * handle->aspx;
- pinuv[1] += e->orig_uv[1] * handle->aspy;
- npins++;
- }
- else {
- v->uv[0] += e->orig_uv[0] * handle->aspx;
- v->uv[1] += e->orig_uv[1] * handle->aspy;
- }
-
- nedges++;
- }
-
- e = p_wheel_edge_next(e);
- } while (e && e != (v->edge));
-
- if (npins > 0) {
- v->uv[0] = pinuv[0] / npins;
- v->uv[1] = pinuv[1] / npins;
- v->flag |= PVERT_PIN;
- }
- else if (nedges > 0) {
- v->uv[0] /= nedges;
- v->uv[1] /= nedges;
- }
+ PEdge *e;
+ int nedges = 0, npins = 0;
+ float pinuv[2];
+
+ v->uv[0] = v->uv[1] = 0.0f;
+ pinuv[0] = pinuv[1] = 0.0f;
+ e = v->edge;
+ do {
+ if (e->orig_uv) {
+ if (e->flag & PEDGE_SELECT)
+ v->flag |= PVERT_SELECT;
+
+ if (e->flag & PEDGE_PIN) {
+ pinuv[0] += e->orig_uv[0] * handle->aspx;
+ pinuv[1] += e->orig_uv[1] * handle->aspy;
+ npins++;
+ }
+ else {
+ v->uv[0] += e->orig_uv[0] * handle->aspx;
+ v->uv[1] += e->orig_uv[1] * handle->aspy;
+ }
+
+ nedges++;
+ }
+
+ e = p_wheel_edge_next(e);
+ } while (e && e != (v->edge));
+
+ if (npins > 0) {
+ v->uv[0] = pinuv[0] / npins;
+ v->uv[1] = pinuv[1] / npins;
+ v->flag |= PVERT_PIN;
+ }
+ else if (nedges > 0) {
+ v->uv[0] /= nedges;
+ v->uv[1] /= nedges;
+ }
}
static void p_flush_uvs(PHandle *handle, PChart *chart)
{
- PEdge *e;
+ PEdge *e;
- for (e = chart->edges; e; e = e->nextlink) {
- if (e->orig_uv) {
- e->orig_uv[0] = e->vert->uv[0] / handle->aspx;
- e->orig_uv[1] = e->vert->uv[1] / handle->aspy;
- }
- }
+ for (e = chart->edges; e; e = e->nextlink) {
+ if (e->orig_uv) {
+ e->orig_uv[0] = e->vert->uv[0] / handle->aspx;
+ e->orig_uv[1] = e->vert->uv[1] / handle->aspy;
+ }
+ }
}
static void p_flush_uvs_blend(PHandle *handle, PChart *chart, float blend)
{
- PEdge *e;
- float invblend = 1.0f - blend;
+ PEdge *e;
+ float invblend = 1.0f - blend;
- for (e = chart->edges; e; e = e->nextlink) {
- if (e->orig_uv) {
- e->orig_uv[0] = blend * e->old_uv[0] + invblend * e->vert->uv[0] / handle->aspx;
- e->orig_uv[1] = blend * e->old_uv[1] + invblend * e->vert->uv[1] / handle->aspy;
- }
- }
+ for (e = chart->edges; e; e = e->nextlink) {
+ if (e->orig_uv) {
+ e->orig_uv[0] = blend * e->old_uv[0] + invblend * e->vert->uv[0] / handle->aspx;
+ e->orig_uv[1] = blend * e->old_uv[1] + invblend * e->vert->uv[1] / handle->aspy;
+ }
+ }
}
static void p_face_backup_uvs(PFace *f)
{
- PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
- if (e1->orig_uv) {
- e1->old_uv[0] = e1->orig_uv[0];
- e1->old_uv[1] = e1->orig_uv[1];
- }
- if (e2->orig_uv) {
- e2->old_uv[0] = e2->orig_uv[0];
- e2->old_uv[1] = e2->orig_uv[1];
- }
- if (e3->orig_uv) {
- e3->old_uv[0] = e3->orig_uv[0];
- e3->old_uv[1] = e3->orig_uv[1];
- }
+ if (e1->orig_uv) {
+ e1->old_uv[0] = e1->orig_uv[0];
+ e1->old_uv[1] = e1->orig_uv[1];
+ }
+ if (e2->orig_uv) {
+ e2->old_uv[0] = e2->orig_uv[0];
+ e2->old_uv[1] = e2->orig_uv[1];
+ }
+ if (e3->orig_uv) {
+ e3->old_uv[0] = e3->orig_uv[0];
+ e3->old_uv[1] = e3->orig_uv[1];
+ }
}
static void p_face_restore_uvs(PFace *f)
{
- PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
- if (e1->orig_uv) {
- e1->orig_uv[0] = e1->old_uv[0];
- e1->orig_uv[1] = e1->old_uv[1];
- }
- if (e2->orig_uv) {
- e2->orig_uv[0] = e2->old_uv[0];
- e2->orig_uv[1] = e2->old_uv[1];
- }
- if (e3->orig_uv) {
- e3->orig_uv[0] = e3->old_uv[0];
- e3->orig_uv[1] = e3->old_uv[1];
- }
+ if (e1->orig_uv) {
+ e1->orig_uv[0] = e1->old_uv[0];
+ e1->orig_uv[1] = e1->old_uv[1];
+ }
+ if (e2->orig_uv) {
+ e2->orig_uv[0] = e2->old_uv[0];
+ e2->orig_uv[1] = e2->old_uv[1];
+ }
+ if (e3->orig_uv) {
+ e3->orig_uv[0] = e3->old_uv[0];
+ e3->orig_uv[1] = e3->old_uv[1];
+ }
}
/* Construction (use only during construction, relies on u.key being set */
static PVert *p_vert_add(PHandle *handle, PHashKey key, const float co[3], PEdge *e)
{
- PVert *v = (PVert *)BLI_memarena_alloc(handle->arena, sizeof(*v));
- copy_v3_v3(v->co, co);
+ PVert *v = (PVert *)BLI_memarena_alloc(handle->arena, sizeof(*v));
+ copy_v3_v3(v->co, co);
- /* Sanity check, a single nan/inf point causes the entire result to be invalid.
- * Note that values within the calculation may _become_ non-finite,
- * so the rest of the code still needs to take this possibility into account. */
- for (int i = 0; i < 3; i++) {
- if (UNLIKELY(!isfinite(v->co[i]))) {
- v->co[i] = 0.0f;
- }
- }
+ /* Sanity check, a single nan/inf point causes the entire result to be invalid.
+ * Note that values within the calculation may _become_ non-finite,
+ * so the rest of the code still needs to take this possibility into account. */
+ for (int i = 0; i < 3; i++) {
+ if (UNLIKELY(!isfinite(v->co[i]))) {
+ v->co[i] = 0.0f;
+ }
+ }
- v->u.key = key;
- v->edge = e;
- v->flag = 0;
+ v->u.key = key;
+ v->edge = e;
+ v->flag = 0;
- phash_insert(handle->hash_verts, (PHashLink *)v);
+ phash_insert(handle->hash_verts, (PHashLink *)v);
- return v;
+ return v;
}
static PVert *p_vert_lookup(PHandle *handle, PHashKey key, const float co[3], PEdge *e)
{
- PVert *v = (PVert *)phash_lookup(handle->hash_verts, key);
+ PVert *v = (PVert *)phash_lookup(handle->hash_verts, key);
- if (v)
- return v;
- else
- return p_vert_add(handle, key, co, e);
+ if (v)
+ return v;
+ else
+ return p_vert_add(handle, key, co, e);
}
static PVert *p_vert_copy(PChart *chart, PVert *v)
{
- PVert *nv = (PVert *)BLI_memarena_alloc(chart->handle->arena, sizeof(*nv));
+ PVert *nv = (PVert *)BLI_memarena_alloc(chart->handle->arena, sizeof(*nv));
- copy_v3_v3(nv->co, v->co);
- nv->uv[0] = v->uv[0];
- nv->uv[1] = v->uv[1];
- nv->u.key = v->u.key;
- nv->edge = v->edge;
- nv->flag = v->flag;
+ copy_v3_v3(nv->co, v->co);
+ nv->uv[0] = v->uv[0];
+ nv->uv[1] = v->uv[1];
+ nv->u.key = v->u.key;
+ nv->edge = v->edge;
+ nv->flag = v->flag;
- return nv;
+ return nv;
}
static PEdge *p_edge_lookup(PHandle *handle, PHashKey *vkeys)
{
- PHashKey key = PHASH_edge(vkeys[0], vkeys[1]);
- PEdge *e = (PEdge *)phash_lookup(handle->hash_edges, key);
+ PHashKey key = PHASH_edge(vkeys[0], vkeys[1]);
+ PEdge *e = (PEdge *)phash_lookup(handle->hash_edges, key);
- while (e) {
- if ((e->vert->u.key == vkeys[0]) && (e->next->vert->u.key == vkeys[1]))
- return e;
- else if ((e->vert->u.key == vkeys[1]) && (e->next->vert->u.key == vkeys[0]))
- return e;
+ while (e) {
+ if ((e->vert->u.key == vkeys[0]) && (e->next->vert->u.key == vkeys[1]))
+ return e;
+ else if ((e->vert->u.key == vkeys[1]) && (e->next->vert->u.key == vkeys[0]))
+ return e;
- e = (PEdge *)phash_next(handle->hash_edges, key, (PHashLink *)e);
- }
+ e = (PEdge *)phash_next(handle->hash_edges, key, (PHashLink *)e);
+ }
- return NULL;
+ return NULL;
}
static int p_face_exists(ParamHandle *phandle, ParamKey *pvkeys, int i1, int i2, int i3)
{
- PHandle *handle = (PHandle *)phandle;
- PHashKey *vkeys = (PHashKey *)pvkeys;
- PHashKey key = PHASH_edge(vkeys[i1], vkeys[i2]);
- PEdge *e = (PEdge *)phash_lookup(handle->hash_edges, key);
+ PHandle *handle = (PHandle *)phandle;
+ PHashKey *vkeys = (PHashKey *)pvkeys;
+ PHashKey key = PHASH_edge(vkeys[i1], vkeys[i2]);
+ PEdge *e = (PEdge *)phash_lookup(handle->hash_edges, key);
- while (e) {
- if ((e->vert->u.key == vkeys[i1]) && (e->next->vert->u.key == vkeys[i2])) {
- if (e->next->next->vert->u.key == vkeys[i3])
- return P_TRUE;
- }
- else if ((e->vert->u.key == vkeys[i2]) && (e->next->vert->u.key == vkeys[i1])) {
- if (e->next->next->vert->u.key == vkeys[i3])
- return P_TRUE;
- }
+ while (e) {
+ if ((e->vert->u.key == vkeys[i1]) && (e->next->vert->u.key == vkeys[i2])) {
+ if (e->next->next->vert->u.key == vkeys[i3])
+ return P_TRUE;
+ }
+ else if ((e->vert->u.key == vkeys[i2]) && (e->next->vert->u.key == vkeys[i1])) {
+ if (e->next->next->vert->u.key == vkeys[i3])
+ return P_TRUE;
+ }
- e = (PEdge *)phash_next(handle->hash_edges, key, (PHashLink *)e);
- }
+ e = (PEdge *)phash_next(handle->hash_edges, key, (PHashLink *)e);
+ }
- return P_FALSE;
+ return P_FALSE;
}
static PChart *p_chart_new(PHandle *handle)
{
- PChart *chart = (PChart *)MEM_callocN(sizeof(*chart), "PChart");
- chart->handle = handle;
+ PChart *chart = (PChart *)MEM_callocN(sizeof(*chart), "PChart");
+ chart->handle = handle;
- return chart;
+ return chart;
}
static void p_chart_delete(PChart *chart)
{
- /* the actual links are free by memarena */
- MEM_freeN(chart);
+ /* the actual links are free by memarena */
+ MEM_freeN(chart);
}
static PBool p_edge_implicit_seam(PEdge *e, PEdge *ep)
{
- float *uv1, *uv2, *uvp1, *uvp2;
- float limit[2];
+ float *uv1, *uv2, *uvp1, *uvp2;
+ float limit[2];
- limit[0] = 0.00001;
- limit[1] = 0.00001;
+ limit[0] = 0.00001;
+ limit[1] = 0.00001;
- uv1 = e->orig_uv;
- uv2 = e->next->orig_uv;
+ uv1 = e->orig_uv;
+ uv2 = e->next->orig_uv;
- if (e->vert->u.key == ep->vert->u.key) {
- uvp1 = ep->orig_uv;
- uvp2 = ep->next->orig_uv;
- }
- else {
- uvp1 = ep->next->orig_uv;
- uvp2 = ep->orig_uv;
- }
+ if (e->vert->u.key == ep->vert->u.key) {
+ uvp1 = ep->orig_uv;
+ uvp2 = ep->next->orig_uv;
+ }
+ else {
+ uvp1 = ep->next->orig_uv;
+ uvp2 = ep->orig_uv;
+ }
- if ((fabsf(uv1[0] - uvp1[0]) > limit[0]) || (fabsf(uv1[1] - uvp1[1]) > limit[1])) {
- e->flag |= PEDGE_SEAM;
- ep->flag |= PEDGE_SEAM;
- return P_TRUE;
- }
- if ((fabsf(uv2[0] - uvp2[0]) > limit[0]) || (fabsf(uv2[1] - uvp2[1]) > limit[1])) {
- e->flag |= PEDGE_SEAM;
- ep->flag |= PEDGE_SEAM;
- return P_TRUE;
- }
+ if ((fabsf(uv1[0] - uvp1[0]) > limit[0]) || (fabsf(uv1[1] - uvp1[1]) > limit[1])) {
+ e->flag |= PEDGE_SEAM;
+ ep->flag |= PEDGE_SEAM;
+ return P_TRUE;
+ }
+ if ((fabsf(uv2[0] - uvp2[0]) > limit[0]) || (fabsf(uv2[1] - uvp2[1]) > limit[1])) {
+ e->flag |= PEDGE_SEAM;
+ ep->flag |= PEDGE_SEAM;
+ return P_TRUE;
+ }
- return P_FALSE;
+ return P_FALSE;
}
static PBool p_edge_has_pair(PHandle *handle, PEdge *e, PEdge **pair, PBool impl)
{
- PHashKey key;
- PEdge *pe;
- PVert *v1, *v2;
- PHashKey key1 = e->vert->u.key;
- PHashKey key2 = e->next->vert->u.key;
+ PHashKey key;
+ PEdge *pe;
+ PVert *v1, *v2;
+ PHashKey key1 = e->vert->u.key;
+ PHashKey key2 = e->next->vert->u.key;
- if (e->flag & PEDGE_SEAM)
- return P_FALSE;
+ if (e->flag & PEDGE_SEAM)
+ return P_FALSE;
- key = PHASH_edge(key1, key2);
- pe = (PEdge *)phash_lookup(handle->hash_edges, key);
- *pair = NULL;
+ key = PHASH_edge(key1, key2);
+ pe = (PEdge *)phash_lookup(handle->hash_edges, key);
+ *pair = NULL;
- while (pe) {
- if (pe != e) {
- v1 = pe->vert;
- v2 = pe->next->vert;
+ while (pe) {
+ if (pe != e) {
+ v1 = pe->vert;
+ v2 = pe->next->vert;
- if (((v1->u.key == key1) && (v2->u.key == key2)) ||
- ((v1->u.key == key2) && (v2->u.key == key1)))
- {
+ if (((v1->u.key == key1) && (v2->u.key == key2)) ||
+ ((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;
- return P_FALSE;
- }
+ /* don't connect seams and t-junctions */
+ if ((pe->flag & PEDGE_SEAM) || *pair || (impl && p_edge_implicit_seam(e, pe))) {
+ *pair = NULL;
+ return P_FALSE;
+ }
- *pair = pe;
- }
- }
+ *pair = pe;
+ }
+ }
- pe = (PEdge *)phash_next(handle->hash_edges, key, (PHashLink *)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) {
- /* non unfoldable, maybe mobius ring or klein bottle */
- *pair = NULL;
- return P_FALSE;
- }
- }
+ if (*pair && (e->vert == (*pair)->vert)) {
+ if ((*pair)->next->pair || (*pair)->next->next->pair) {
+ /* non unfoldable, maybe mobius ring or klein bottle */
+ *pair = NULL;
+ return P_FALSE;
+ }
+ }
- return (*pair != NULL);
+ return (*pair != NULL);
}
static PBool p_edge_connect_pair(PHandle *handle, PEdge *e, PEdge ***stack, PBool impl)
{
- PEdge *pair = NULL;
+ PEdge *pair = NULL;
- if (!e->pair && p_edge_has_pair(handle, e, &pair, impl)) {
- if (e->vert == pair->vert)
- p_face_flip(pair->face);
+ if (!e->pair && p_edge_has_pair(handle, e, &pair, impl)) {
+ if (e->vert == pair->vert)
+ p_face_flip(pair->face);
- e->pair = pair;
- pair->pair = e;
+ e->pair = pair;
+ pair->pair = e;
- if (!(pair->face->flag & PFACE_CONNECTED)) {
- **stack = pair;
- (*stack)++;
- }
- }
+ if (!(pair->face->flag & PFACE_CONNECTED)) {
+ **stack = pair;
+ (*stack)++;
+ }
+ }
- return (e->pair != NULL);
+ return (e->pair != NULL);
}
static int p_connect_pairs(PHandle *handle, PBool impl)
{
- PEdge **stackbase = MEM_mallocN(sizeof(*stackbase) * phash_size(handle->hash_faces), "Pstackbase");
- PEdge **stack = stackbase;
- PFace *f, *first;
- PEdge *e, *e1, *e2;
- PChart *chart = handle->construction_chart;
- int ncharts = 0;
+ PEdge **stackbase = MEM_mallocN(sizeof(*stackbase) * phash_size(handle->hash_faces),
+ "Pstackbase");
+ PEdge **stack = stackbase;
+ PFace *f, *first;
+ PEdge *e, *e1, *e2;
+ PChart *chart = handle->construction_chart;
+ int ncharts = 0;
- /* connect pairs, count edges, set vertex-edge pointer to a pairless edge */
- for (first = chart->faces; first; first = first->nextlink) {
- if (first->flag & PFACE_CONNECTED)
- continue;
+ /* connect pairs, count edges, set vertex-edge pointer to a pairless edge */
+ for (first = chart->faces; first; first = first->nextlink) {
+ if (first->flag & PFACE_CONNECTED)
+ continue;
- *stack = first->edge;
- stack++;
+ *stack = first->edge;
+ stack++;
- while (stack != stackbase) {
- stack--;
- e = *stack;
- e1 = e->next;
- e2 = e1->next;
+ while (stack != stackbase) {
+ stack--;
+ e = *stack;
+ e1 = e->next;
+ e2 = e1->next;
- f = e->face;
- f->flag |= PFACE_CONNECTED;
+ f = e->face;
+ f->flag |= PFACE_CONNECTED;
- /* assign verts to charts so we can sort them later */
- f->u.chart = ncharts;
+ /* assign verts to charts so we can sort them later */
+ f->u.chart = ncharts;
- if (!p_edge_connect_pair(handle, e, &stack, impl))
- e->vert->edge = e;
- if (!p_edge_connect_pair(handle, e1, &stack, impl))
- e1->vert->edge = e1;
- if (!p_edge_connect_pair(handle, e2, &stack, impl))
- e2->vert->edge = e2;
- }
+ if (!p_edge_connect_pair(handle, e, &stack, impl))
+ e->vert->edge = e;
+ if (!p_edge_connect_pair(handle, e1, &stack, impl))
+ e1->vert->edge = e1;
+ if (!p_edge_connect_pair(handle, e2, &stack, impl))
+ e2->vert->edge = e2;
+ }
- ncharts++;
- }
+ ncharts++;
+ }
- MEM_freeN(stackbase);
+ MEM_freeN(stackbase);
- return ncharts;
+ return ncharts;
}
static void p_split_vert(PChart *chart, PEdge *e)
{
- PEdge *we, *lastwe = NULL;
- PVert *v = e->vert;
- PBool copy = P_TRUE;
+ PEdge *we, *lastwe = NULL;
+ PVert *v = e->vert;
+ PBool copy = P_TRUE;
- if (e->flag & PEDGE_PIN) {
- chart->flag |= PCHART_HAS_PINS;
- }
+ if (e->flag & PEDGE_PIN) {
+ chart->flag |= PCHART_HAS_PINS;
+ }
- if (e->flag & PEDGE_VERTEX_SPLIT)
- return;
+ if (e->flag & PEDGE_VERTEX_SPLIT)
+ return;
- /* rewind to start */
- lastwe = e;
- for (we = p_wheel_edge_prev(e); we && (we != e); we = p_wheel_edge_prev(we))
- lastwe = we;
+ /* rewind to start */
+ lastwe = e;
+ for (we = p_wheel_edge_prev(e); we && (we != e); we = p_wheel_edge_prev(we))
+ lastwe = we;
- /* go over all edges in wheel */
- for (we = lastwe; we; we = p_wheel_edge_next(we)) {
- if (we->flag & PEDGE_VERTEX_SPLIT)
- break;
+ /* go over all edges in wheel */
+ for (we = lastwe; we; we = p_wheel_edge_next(we)) {
+ if (we->flag & PEDGE_VERTEX_SPLIT)
+ break;
- we->flag |= PEDGE_VERTEX_SPLIT;
+ we->flag |= PEDGE_VERTEX_SPLIT;
- if (we == v->edge) {
- /* found it, no need to copy */
- copy = P_FALSE;
- v->nextlink = chart->verts;
- chart->verts = v;
- chart->nverts++;
- }
- }
+ if (we == v->edge) {
+ /* found it, no need to copy */
+ copy = P_FALSE;
+ v->nextlink = chart->verts;
+ chart->verts = v;
+ chart->nverts++;
+ }
+ }
- if (copy) {
- /* not found, copying */
- v->flag |= PVERT_SPLIT;
- v = p_vert_copy(chart, v);
- v->flag |= PVERT_SPLIT;
+ if (copy) {
+ /* not found, copying */
+ v->flag |= PVERT_SPLIT;
+ v = p_vert_copy(chart, v);
+ v->flag |= PVERT_SPLIT;
- v->nextlink = chart->verts;
- chart->verts = v;
- chart->nverts++;
+ v->nextlink = chart->verts;
+ chart->verts = v;
+ chart->nverts++;
- v->edge = lastwe;
+ v->edge = lastwe;
- we = lastwe;
- do {
- we->vert = v;
- we = p_wheel_edge_next(we);
- } while (we && (we != lastwe));
- }
+ we = lastwe;
+ do {
+ we->vert = v;
+ we = p_wheel_edge_next(we);
+ } while (we && (we != lastwe));
+ }
}
static PChart **p_split_charts(PHandle *handle, PChart *chart, int ncharts)
{
- PChart **charts = MEM_mallocN(sizeof(*charts) * ncharts, "PCharts"), *nchart;
- PFace *f, *nextf;
- int i;
+ PChart **charts = MEM_mallocN(sizeof(*charts) * ncharts, "PCharts"), *nchart;
+ PFace *f, *nextf;
+ int i;
- for (i = 0; i < ncharts; i++)
- charts[i] = p_chart_new(handle);
+ for (i = 0; i < ncharts; i++)
+ charts[i] = p_chart_new(handle);
- f = chart->faces;
- while (f) {
- PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
- nextf = f->nextlink;
+ f = chart->faces;
+ while (f) {
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ nextf = f->nextlink;
- nchart = charts[f->u.chart];
+ nchart = charts[f->u.chart];
- f->nextlink = nchart->faces;
- nchart->faces = f;
- e1->nextlink = nchart->edges;
- nchart->edges = e1;
- e2->nextlink = nchart->edges;
- nchart->edges = e2;
- e3->nextlink = nchart->edges;
- nchart->edges = e3;
+ f->nextlink = nchart->faces;
+ nchart->faces = f;
+ e1->nextlink = nchart->edges;
+ nchart->edges = e1;
+ e2->nextlink = nchart->edges;
+ nchart->edges = e2;
+ e3->nextlink = nchart->edges;
+ nchart->edges = e3;
- nchart->nfaces++;
- nchart->nedges += 3;
+ nchart->nfaces++;
+ nchart->nedges += 3;
- p_split_vert(nchart, e1);
- p_split_vert(nchart, e2);
- p_split_vert(nchart, e3);
+ p_split_vert(nchart, e1);
+ p_split_vert(nchart, e2);
+ p_split_vert(nchart, e3);
- f = nextf;
- }
+ f = nextf;
+ }
- return charts;
+ return charts;
}
static PFace *p_face_add(PHandle *handle)
{
- PFace *f;
- PEdge *e1, *e2, *e3;
+ PFace *f;
+ PEdge *e1, *e2, *e3;
- /* allocate */
- f = (PFace *)BLI_memarena_alloc(handle->arena, sizeof(*f));
- f->flag = 0; /* init ! */
+ /* allocate */
+ f = (PFace *)BLI_memarena_alloc(handle->arena, sizeof(*f));
+ f->flag = 0; /* init ! */
- e1 = (PEdge *)BLI_memarena_alloc(handle->arena, sizeof(*e1));
- e2 = (PEdge *)BLI_memarena_alloc(handle->arena, sizeof(*e2));
- e3 = (PEdge *)BLI_memarena_alloc(handle->arena, sizeof(*e3));
+ e1 = (PEdge *)BLI_memarena_alloc(handle->arena, sizeof(*e1));
+ e2 = (PEdge *)BLI_memarena_alloc(handle->arena, sizeof(*e2));
+ e3 = (PEdge *)BLI_memarena_alloc(handle->arena, sizeof(*e3));
- /* set up edges */
- f->edge = e1;
- e1->face = e2->face = e3->face = f;
+ /* set up edges */
+ f->edge = e1;
+ e1->face = e2->face = e3->face = f;
- e1->next = e2;
- e2->next = e3;
- e3->next = e1;
+ e1->next = e2;
+ e2->next = e3;
+ e3->next = e1;
- e1->pair = NULL;
- e2->pair = NULL;
- e3->pair = NULL;
+ e1->pair = NULL;
+ e2->pair = NULL;
+ e3->pair = NULL;
- e1->flag = 0;
- e2->flag = 0;
- e3->flag = 0;
+ e1->flag = 0;
+ e2->flag = 0;
+ e3->flag = 0;
- return f;
+ return f;
}
-static PFace *p_face_add_construct(PHandle *handle, ParamKey key, ParamKey *vkeys,
- float *co[4], float *uv[4], int i1, int i2, int i3,
- ParamBool *pin, ParamBool *select)
+static PFace *p_face_add_construct(PHandle *handle,
+ ParamKey key,
+ ParamKey *vkeys,
+ float *co[4],
+ float *uv[4],
+ int i1,
+ int i2,
+ int i3,
+ ParamBool *pin,
+ ParamBool *select)
{
- PFace *f = p_face_add(handle);
- PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PFace *f = p_face_add(handle);
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
- e1->vert = p_vert_lookup(handle, vkeys[i1], co[i1], e1);
- e2->vert = p_vert_lookup(handle, vkeys[i2], co[i2], e2);
- e3->vert = p_vert_lookup(handle, vkeys[i3], co[i3], e3);
+ e1->vert = p_vert_lookup(handle, vkeys[i1], co[i1], e1);
+ e2->vert = p_vert_lookup(handle, vkeys[i2], co[i2], e2);
+ e3->vert = p_vert_lookup(handle, vkeys[i3], co[i3], e3);
- e1->orig_uv = uv[i1];
- e2->orig_uv = uv[i2];
- e3->orig_uv = uv[i3];
+ e1->orig_uv = uv[i1];
+ e2->orig_uv = uv[i2];
+ e3->orig_uv = uv[i3];
- if (pin) {
- if (pin[i1]) e1->flag |= PEDGE_PIN;
- if (pin[i2]) e2->flag |= PEDGE_PIN;
- if (pin[i3]) e3->flag |= PEDGE_PIN;
- }
+ if (pin) {
+ if (pin[i1])
+ e1->flag |= PEDGE_PIN;
+ if (pin[i2])
+ e2->flag |= PEDGE_PIN;
+ if (pin[i3])
+ e3->flag |= PEDGE_PIN;
+ }
- if (select) {
- if (select[i1]) e1->flag |= PEDGE_SELECT;
- if (select[i2]) e2->flag |= PEDGE_SELECT;
- if (select[i3]) e3->flag |= PEDGE_SELECT;
- }
+ if (select) {
+ if (select[i1])
+ e1->flag |= PEDGE_SELECT;
+ if (select[i2])
+ e2->flag |= PEDGE_SELECT;
+ if (select[i3])
+ e3->flag |= PEDGE_SELECT;
+ }
- /* insert into hash */
- f->u.key = key;
- phash_insert(handle->hash_faces, (PHashLink *)f);
+ /* insert into hash */
+ f->u.key = key;
+ phash_insert(handle->hash_faces, (PHashLink *)f);
- e1->u.key = PHASH_edge(vkeys[i1], vkeys[i2]);
- e2->u.key = PHASH_edge(vkeys[i2], vkeys[i3]);
- e3->u.key = PHASH_edge(vkeys[i3], vkeys[i1]);
+ e1->u.key = PHASH_edge(vkeys[i1], vkeys[i2]);
+ e2->u.key = PHASH_edge(vkeys[i2], vkeys[i3]);
+ e3->u.key = PHASH_edge(vkeys[i3], vkeys[i1]);
- phash_insert(handle->hash_edges, (PHashLink *)e1);
- phash_insert(handle->hash_edges, (PHashLink *)e2);
- phash_insert(handle->hash_edges, (PHashLink *)e3);
+ phash_insert(handle->hash_edges, (PHashLink *)e1);
+ phash_insert(handle->hash_edges, (PHashLink *)e2);
+ phash_insert(handle->hash_edges, (PHashLink *)e3);
- return f;
+ return f;
}
static PFace *p_face_add_fill(PChart *chart, PVert *v1, PVert *v2, PVert *v3)
{
- PFace *f = p_face_add(chart->handle);
- PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PFace *f = p_face_add(chart->handle);
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
- e1->vert = v1;
- e2->vert = v2;
- e3->vert = v3;
+ e1->vert = v1;
+ e2->vert = v2;
+ e3->vert = v3;
- e1->orig_uv = e2->orig_uv = e3->orig_uv = NULL;
+ e1->orig_uv = e2->orig_uv = e3->orig_uv = NULL;
- f->nextlink = chart->faces;
- chart->faces = f;
- e1->nextlink = chart->edges;
- chart->edges = e1;
- e2->nextlink = chart->edges;
- chart->edges = e2;
- e3->nextlink = chart->edges;
- chart->edges = e3;
+ f->nextlink = chart->faces;
+ chart->faces = f;
+ e1->nextlink = chart->edges;
+ chart->edges = e1;
+ e2->nextlink = chart->edges;
+ chart->edges = e2;
+ e3->nextlink = chart->edges;
+ chart->edges = e3;
- chart->nfaces++;
- chart->nedges += 3;
+ chart->nfaces++;
+ chart->nedges += 3;
- return f;
+ return f;
}
static PBool p_quad_split_direction(PHandle *handle, float **co, PHashKey *vkeys)
{
- /* slight bias to prefer one edge over the other in case they are equal, so
- * that in symmetric models we choose the same split direction instead of
- * depending on floating point errors to decide */
- float bias = 1.0f + 1e-6f;
- float fac = len_v3v3(co[0], co[2]) * bias - len_v3v3(co[1], co[3]);
- PBool dir = (fac <= 0.0f);
-
- /* the face exists check is there because of a special case: when
- * two quads share three vertices, they can each be split into two
- * triangles, resulting in two identical triangles. for example in
- * suzanne's nose. */
- if (dir) {
- if (p_face_exists(handle, vkeys, 0, 1, 2) || p_face_exists(handle, vkeys, 0, 2, 3))
- return !dir;
- }
- else {
- if (p_face_exists(handle, vkeys, 0, 1, 3) || p_face_exists(handle, vkeys, 1, 2, 3))
- return !dir;
- }
-
- return dir;
+ /* slight bias to prefer one edge over the other in case they are equal, so
+ * that in symmetric models we choose the same split direction instead of
+ * depending on floating point errors to decide */
+ float bias = 1.0f + 1e-6f;
+ float fac = len_v3v3(co[0], co[2]) * bias - len_v3v3(co[1], co[3]);
+ PBool dir = (fac <= 0.0f);
+
+ /* the face exists check is there because of a special case: when
+ * two quads share three vertices, they can each be split into two
+ * triangles, resulting in two identical triangles. for example in
+ * suzanne's nose. */
+ if (dir) {
+ if (p_face_exists(handle, vkeys, 0, 1, 2) || p_face_exists(handle, vkeys, 0, 2, 3))
+ return !dir;
+ }
+ else {
+ if (p_face_exists(handle, vkeys, 0, 1, 3) || p_face_exists(handle, vkeys, 1, 2, 3))
+ return !dir;
+ }
+
+ return dir;
}
/* Construction: boundary filling */
static void p_chart_boundaries(PChart *chart, int *nboundaries, PEdge **outer)
{
- PEdge *e, *be;
- float len, maxlen = -1.0;
+ PEdge *e, *be;
+ float len, maxlen = -1.0;
- if (nboundaries)
- *nboundaries = 0;
- if (outer)
- *outer = NULL;
+ if (nboundaries)
+ *nboundaries = 0;
+ if (outer)
+ *outer = NULL;
- for (e = chart->edges; e; e = e->nextlink) {
- if (e->pair || (e->flag & PEDGE_DONE))
- continue;
+ for (e = chart->edges; e; e = e->nextlink) {
+ if (e->pair || (e->flag & PEDGE_DONE))
+ continue;
- if (nboundaries)
- (*nboundaries)++;
+ if (nboundaries)
+ (*nboundaries)++;
- len = 0.0f;
+ len = 0.0f;
- be = e;
- do {
- be->flag |= PEDGE_DONE;
- len += p_edge_length(be);
- be = be->next->vert->edge;
- } while (be != e);
+ be = e;
+ do {
+ be->flag |= PEDGE_DONE;
+ len += p_edge_length(be);
+ be = be->next->vert->edge;
+ } while (be != e);
- if (outer && (len > maxlen)) {
- *outer = e;
- maxlen = len;
- }
- }
+ if (outer && (len > maxlen)) {
+ *outer = e;
+ maxlen = len;
+ }
+ }
- for (e = chart->edges; e; e = e->nextlink)
- e->flag &= ~PEDGE_DONE;
+ for (e = chart->edges; e; e = e->nextlink)
+ e->flag &= ~PEDGE_DONE;
}
static float p_edge_boundary_angle(PEdge *e)
{
- PEdge *we;
- PVert *v, *v1, *v2;
- float angle;
- int n = 0;
+ PEdge *we;
+ PVert *v, *v1, *v2;
+ float angle;
+ int n = 0;
- v = e->vert;
+ v = e->vert;
- /* concave angle check -- could be better */
- angle = M_PI;
+ /* concave angle check -- could be better */
+ angle = M_PI;
- we = v->edge;
- do {
- v1 = we->next->vert;
- v2 = we->next->next->vert;
- angle -= p_vec_angle(v1->co, v->co, v2->co);
+ we = v->edge;
+ do {
+ v1 = we->next->vert;
+ v2 = we->next->next->vert;
+ angle -= p_vec_angle(v1->co, v->co, v2->co);
- we = we->next->next->pair;
- n++;
- } while (we && (we != v->edge));
+ we = we->next->next->pair;
+ n++;
+ } while (we && (we != v->edge));
- return angle;
+ return angle;
}
static void p_chart_fill_boundary(PChart *chart, PEdge *be, int nedges)
{
- PEdge *e, *e1, *e2;
+ PEdge *e, *e1, *e2;
- PFace *f;
- struct Heap *heap = BLI_heap_new();
- float angle;
+ PFace *f;
+ struct Heap *heap = BLI_heap_new();
+ float angle;
- e = be;
- do {
- angle = p_edge_boundary_angle(e);
- e->u.heaplink = BLI_heap_insert(heap, angle, e);
+ e = be;
+ do {
+ angle = p_edge_boundary_angle(e);
+ e->u.heaplink = BLI_heap_insert(heap, angle, e);
- e = p_boundary_edge_next(e);
- } while (e != be);
+ e = p_boundary_edge_next(e);
+ } while (e != be);
- if (nedges == 2) {
- /* no real boundary, but an isolated seam */
- e = be->next->vert->edge;
- e->pair = be;
- be->pair = e;
+ if (nedges == 2) {
+ /* no real boundary, but an isolated seam */
+ e = be->next->vert->edge;
+ e->pair = be;
+ be->pair = e;
- BLI_heap_remove(heap, e->u.heaplink);
- BLI_heap_remove(heap, be->u.heaplink);
- }
- else {
- while (nedges > 2) {
- PEdge *ne, *ne1, *ne2;
+ BLI_heap_remove(heap, e->u.heaplink);
+ BLI_heap_remove(heap, be->u.heaplink);
+ }
+ else {
+ while (nedges > 2) {
+ PEdge *ne, *ne1, *ne2;
- e = (PEdge *)BLI_heap_pop_min(heap);
+ e = (PEdge *)BLI_heap_pop_min(heap);
- e1 = p_boundary_edge_prev(e);
- e2 = p_boundary_edge_next(e);
+ e1 = p_boundary_edge_prev(e);
+ e2 = p_boundary_edge_next(e);
- BLI_heap_remove(heap, e1->u.heaplink);
- BLI_heap_remove(heap, e2->u.heaplink);
- e->u.heaplink = e1->u.heaplink = e2->u.heaplink = NULL;
+ BLI_heap_remove(heap, e1->u.heaplink);
+ BLI_heap_remove(heap, e2->u.heaplink);
+ e->u.heaplink = e1->u.heaplink = e2->u.heaplink = NULL;
- e->flag |= PEDGE_FILLED;
- e1->flag |= PEDGE_FILLED;
+ e->flag |= PEDGE_FILLED;
+ e1->flag |= PEDGE_FILLED;
- f = p_face_add_fill(chart, e->vert, e1->vert, e2->vert);
- f->flag |= PFACE_FILLED;
+ f = p_face_add_fill(chart, e->vert, e1->vert, e2->vert);
+ f->flag |= PFACE_FILLED;
- ne = f->edge->next->next;
- ne1 = f->edge;
- ne2 = f->edge->next;
+ ne = f->edge->next->next;
+ ne1 = f->edge;
+ ne2 = f->edge->next;
- ne->flag = ne1->flag = ne2->flag = PEDGE_FILLED;
+ ne->flag = ne1->flag = ne2->flag = PEDGE_FILLED;
- e->pair = ne;
- ne->pair = e;
- e1->pair = ne1;
- ne1->pair = e1;
+ e->pair = ne;
+ ne->pair = e;
+ e1->pair = ne1;
+ ne1->pair = e1;
- ne->vert = e2->vert;
- ne1->vert = e->vert;
- ne2->vert = e1->vert;
+ ne->vert = e2->vert;
+ ne1->vert = e->vert;
+ ne2->vert = e1->vert;
- if (nedges == 3) {
- e2->pair = ne2;
- ne2->pair = e2;
- }
- else {
- ne2->vert->edge = ne2;
+ if (nedges == 3) {
+ e2->pair = ne2;
+ ne2->pair = e2;
+ }
+ else {
+ ne2->vert->edge = ne2;
- ne2->u.heaplink = BLI_heap_insert(heap, p_edge_boundary_angle(ne2), ne2);
- e2->u.heaplink = BLI_heap_insert(heap, p_edge_boundary_angle(e2), e2);
- }
+ ne2->u.heaplink = BLI_heap_insert(heap, p_edge_boundary_angle(ne2), ne2);
+ e2->u.heaplink = BLI_heap_insert(heap, p_edge_boundary_angle(e2), e2);
+ }
- nedges--;
- }
- }
+ nedges--;
+ }
+ }
- BLI_heap_free(heap, NULL);
+ BLI_heap_free(heap, NULL);
}
static void p_chart_fill_boundaries(PChart *chart, PEdge *outer)
{
- PEdge *e, *be; /* *enext - as yet unused */
- int nedges;
+ PEdge *e, *be; /* *enext - as yet unused */
+ int nedges;
- for (e = chart->edges; e; e = e->nextlink) {
- /* enext = e->nextlink; - as yet unused */
+ for (e = chart->edges; e; e = e->nextlink) {
+ /* enext = e->nextlink; - as yet unused */
- if (e->pair || (e->flag & PEDGE_FILLED))
- continue;
+ if (e->pair || (e->flag & PEDGE_FILLED))
+ continue;
- nedges = 0;
- be = e;
- do {
- be->flag |= PEDGE_FILLED;
- be = be->next->vert->edge;
- nedges++;
- } while (be != e);
+ nedges = 0;
+ be = e;
+ do {
+ be->flag |= PEDGE_FILLED;
+ be = be->next->vert->edge;
+ nedges++;
+ } while (be != e);
- if (e != outer)
- p_chart_fill_boundary(chart, e, nedges);
- }
+ if (e != outer)
+ p_chart_fill_boundary(chart, e, nedges);
+ }
}
#if 0
@@ -1369,116 +1385,116 @@ static void p_chart_fill_boundaries(PChart *chart, PEdge *outer)
static int p_polygon_point_in(float *cp1, float *cp2, float *p)
{
- if ((cp1[0] == p[0]) && (cp1[1] == p[1]))
- return 2;
- else if ((cp2[0] == p[0]) && (cp2[1] == p[1]))
- return 3;
- else
- return (p_area_signed(cp1, cp2, p) >= 0.0f);
+ if ((cp1[0] == p[0]) && (cp1[1] == p[1]))
+ return 2;
+ else if ((cp2[0] == p[0]) && (cp2[1] == p[1]))
+ return 3;
+ else
+ return (p_area_signed(cp1, cp2, p) >= 0.0f);
}
static void p_polygon_kernel_clip(float (*oldpoints)[2], int noldpoints, float (*newpoints)[2], int *nnewpoints, float *cp1, float *cp2)
{
- float *p2, *p1, isect[2];
- int i, p2in, p1in;
-
- p1 = oldpoints[noldpoints - 1];
- p1in = p_polygon_point_in(cp1, cp2, p1);
- *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)++;
- }
- 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)++;
- }
- }
- 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[*nnewpoints][0] = p2[0];
- newpoints[*nnewpoints][1] = p2[1];
- (*nnewpoints)++;
- }
-
- p1in = p2in;
- p1 = p2;
- }
+ float *p2, *p1, isect[2];
+ int i, p2in, p1in;
+
+ p1 = oldpoints[noldpoints - 1];
+ p1in = p_polygon_point_in(cp1, cp2, p1);
+ *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)++;
+ }
+ 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)++;
+ }
+ }
+ 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[*nnewpoints][0] = p2[0];
+ newpoints[*nnewpoints][1] = p2[1];
+ (*nnewpoints)++;
+ }
+
+ p1in = p2in;
+ p1 = p2;
+ }
}
static void p_polygon_kernel_center(float (*points)[2], int npoints, float *center)
{
- int i, size, nnewpoints = npoints;
- float (*oldpoints)[2], (*newpoints)[2], *p1, *p2;
-
- size = npoints * 3;
- oldpoints = MEM_mallocN(sizeof(float) * 2 * size, "PPolygonOldPoints");
- newpoints = MEM_mallocN(sizeof(float) * 2 * size, "PPolygonNewPoints");
-
- memcpy(oldpoints, points, sizeof(float) * 2 * npoints);
-
- for (i = 0; i < npoints; i++) {
- p1 = points[i];
- p2 = points[(i + 1) % npoints];
- p_polygon_kernel_clip(oldpoints, nnewpoints, newpoints, &nnewpoints, p1, p2);
-
- if (nnewpoints == 0) {
- /* degenerate case, use center of original polygon */
- memcpy(oldpoints, points, sizeof(float) * 2 * npoints);
- nnewpoints = npoints;
- break;
- }
- else if (nnewpoints == 1) {
- /* degenerate case, use remaining point */
- center[0] = newpoints[0][0];
- center[1] = newpoints[0][1];
-
- MEM_freeN(oldpoints);
- MEM_freeN(newpoints);
-
- return;
- }
-
- if (nnewpoints * 2 > size) {
- size *= 2;
- MEM_freeN(oldpoints);
- oldpoints = MEM_mallocN(sizeof(float) * 2 * size, "oldpoints");
- memcpy(oldpoints, newpoints, sizeof(float) * 2 * nnewpoints);
- MEM_freeN(newpoints);
- newpoints = MEM_mallocN(sizeof(float) * 2 * size, "newpoints");
- }
- else {
- float (*sw_points)[2] = oldpoints;
- oldpoints = newpoints;
- newpoints = sw_points;
- }
- }
-
- center[0] = center[1] = 0.0f;
-
- for (i = 0; i < nnewpoints; i++) {
- center[0] += oldpoints[i][0];
- center[1] += oldpoints[i][1];
- }
-
- center[0] /= nnewpoints;
- center[1] /= nnewpoints;
-
- MEM_freeN(oldpoints);
- MEM_freeN(newpoints);
+ int i, size, nnewpoints = npoints;
+ float (*oldpoints)[2], (*newpoints)[2], *p1, *p2;
+
+ size = npoints * 3;
+ oldpoints = MEM_mallocN(sizeof(float) * 2 * size, "PPolygonOldPoints");
+ newpoints = MEM_mallocN(sizeof(float) * 2 * size, "PPolygonNewPoints");
+
+ memcpy(oldpoints, points, sizeof(float) * 2 * npoints);
+
+ for (i = 0; i < npoints; i++) {
+ p1 = points[i];
+ p2 = points[(i + 1) % npoints];
+ p_polygon_kernel_clip(oldpoints, nnewpoints, newpoints, &nnewpoints, p1, p2);
+
+ if (nnewpoints == 0) {
+ /* degenerate case, use center of original polygon */
+ memcpy(oldpoints, points, sizeof(float) * 2 * npoints);
+ nnewpoints = npoints;
+ break;
+ }
+ else if (nnewpoints == 1) {
+ /* degenerate case, use remaining point */
+ center[0] = newpoints[0][0];
+ center[1] = newpoints[0][1];
+
+ MEM_freeN(oldpoints);
+ MEM_freeN(newpoints);
+
+ return;
+ }
+
+ if (nnewpoints * 2 > size) {
+ size *= 2;
+ MEM_freeN(oldpoints);
+ oldpoints = MEM_mallocN(sizeof(float) * 2 * size, "oldpoints");
+ memcpy(oldpoints, newpoints, sizeof(float) * 2 * nnewpoints);
+ MEM_freeN(newpoints);
+ newpoints = MEM_mallocN(sizeof(float) * 2 * size, "newpoints");
+ }
+ else {
+ float (*sw_points)[2] = oldpoints;
+ oldpoints = newpoints;
+ newpoints = sw_points;
+ }
+ }
+
+ center[0] = center[1] = 0.0f;
+
+ for (i = 0; i < nnewpoints; i++) {
+ center[0] += oldpoints[i][0];
+ center[1] += oldpoints[i][1];
+ }
+
+ center[0] /= nnewpoints;
+ center[1] /= nnewpoints;
+
+ MEM_freeN(oldpoints);
+ MEM_freeN(newpoints);
}
#endif
@@ -1490,809 +1506,809 @@ int NCOLLAPSEX = 0;
static float p_vert_cotan(float *v1, float *v2, float *v3)
{
- float a[3], b[3], c[3], clen;
+ float a[3], b[3], c[3], clen;
- sub_v3_v3v3(a, v2, v1);
- sub_v3_v3v3(b, v3, v1);
- cross_v3_v3v3(c, a, b);
+ sub_v3_v3v3(a, v2, v1);
+ sub_v3_v3v3(b, v3, v1);
+ cross_v3_v3v3(c, a, b);
- clen = len_v3(c);
+ clen = len_v3(c);
- if (clen == 0.0f)
- return 0.0f;
+ if (clen == 0.0f)
+ return 0.0f;
- return dot_v3v3(a, b) / clen;
+ return dot_v3v3(a, b) / clen;
}
static PBool p_vert_flipped_wheel_triangle(PVert *v)
{
- PEdge *e = v->edge;
+ PEdge *e = v->edge;
- do {
- if (p_face_uv_area_signed(e->face) < 0.0f)
- return P_TRUE;
+ do {
+ if (p_face_uv_area_signed(e->face) < 0.0f)
+ return P_TRUE;
- e = p_wheel_edge_next(e);
- } while (e && (e != v->edge));
+ e = p_wheel_edge_next(e);
+ } while (e && (e != v->edge));
- return P_FALSE;
+ return P_FALSE;
}
static PBool p_vert_map_harmonic_weights(PVert *v)
{
- float weightsum, positionsum[2], olduv[2];
+ float weightsum, positionsum[2], olduv[2];
- weightsum = 0.0f;
- positionsum[0] = positionsum[1] = 0.0f;
+ weightsum = 0.0f;
+ positionsum[0] = positionsum[1] = 0.0f;
- if (p_vert_interior(v)) {
- PEdge *e = v->edge;
+ if (p_vert_interior(v)) {
+ PEdge *e = v->edge;
- do {
- float t1, t2, weight;
- PVert *v1, *v2;
+ do {
+ float t1, t2, weight;
+ PVert *v1, *v2;
- v1 = e->next->vert;
- v2 = e->next->next->vert;
- t1 = p_vert_cotan(v2->co, e->vert->co, v1->co);
+ v1 = e->next->vert;
+ v2 = e->next->next->vert;
+ t1 = p_vert_cotan(v2->co, e->vert->co, v1->co);
- v1 = e->pair->next->vert;
- v2 = e->pair->next->next->vert;
- t2 = p_vert_cotan(v2->co, e->pair->vert->co, v1->co);
+ v1 = e->pair->next->vert;
+ v2 = e->pair->next->next->vert;
+ t2 = p_vert_cotan(v2->co, e->pair->vert->co, v1->co);
- weight = 0.5f * (t1 + t2);
- weightsum += weight;
- positionsum[0] += weight * e->pair->vert->uv[0];
- positionsum[1] += weight * e->pair->vert->uv[1];
+ weight = 0.5f * (t1 + t2);
+ weightsum += weight;
+ positionsum[0] += weight * e->pair->vert->uv[0];
+ positionsum[1] += weight * e->pair->vert->uv[1];
- e = p_wheel_edge_next(e);
- } while (e && (e != v->edge));
- }
- else {
- PEdge *e = v->edge;
+ e = p_wheel_edge_next(e);
+ } while (e && (e != v->edge));
+ }
+ else {
+ PEdge *e = v->edge;
- do {
- float t1, t2;
- PVert *v1, *v2;
+ do {
+ float t1, t2;
+ PVert *v1, *v2;
- v2 = e->next->vert;
- v1 = e->next->next->vert;
+ v2 = e->next->vert;
+ v1 = e->next->next->vert;
- t1 = p_vert_cotan(v1->co, v->co, v2->co);
- t2 = p_vert_cotan(v2->co, v->co, v1->co);
+ t1 = p_vert_cotan(v1->co, v->co, v2->co);
+ t2 = p_vert_cotan(v2->co, v->co, v1->co);
- weightsum += t1 + t2;
- positionsum[0] += (v2->uv[1] - v1->uv[1]) + (t1 * v2->uv[0] + t2 * v1->uv[0]);
- positionsum[1] += (v1->uv[0] - v2->uv[0]) + (t1 * v2->uv[1] + t2 * v1->uv[1]);
+ weightsum += t1 + t2;
+ positionsum[0] += (v2->uv[1] - v1->uv[1]) + (t1 * v2->uv[0] + t2 * v1->uv[0]);
+ positionsum[1] += (v1->uv[0] - v2->uv[0]) + (t1 * v2->uv[1] + t2 * v1->uv[1]);
- e = p_wheel_edge_next(e);
- } while (e && (e != v->edge));
- }
+ e = p_wheel_edge_next(e);
+ } while (e && (e != v->edge));
+ }
- if (weightsum != 0.0f) {
- weightsum = 1.0f / weightsum;
- positionsum[0] *= weightsum;
- positionsum[1] *= weightsum;
- }
+ if (weightsum != 0.0f) {
+ weightsum = 1.0f / weightsum;
+ positionsum[0] *= weightsum;
+ positionsum[1] *= weightsum;
+ }
- olduv[0] = v->uv[0];
- olduv[1] = v->uv[1];
- v->uv[0] = positionsum[0];
- v->uv[1] = positionsum[1];
+ olduv[0] = v->uv[0];
+ olduv[1] = v->uv[1];
+ v->uv[0] = positionsum[0];
+ v->uv[1] = positionsum[1];
- if (p_vert_flipped_wheel_triangle(v)) {
- v->uv[0] = olduv[0];
- v->uv[1] = olduv[1];
+ if (p_vert_flipped_wheel_triangle(v)) {
+ v->uv[0] = olduv[0];
+ v->uv[1] = olduv[1];
- return P_FALSE;
- }
+ return P_FALSE;
+ }
- return P_TRUE;
+ return P_TRUE;
}
static void p_vert_harmonic_insert(PVert *v)
{
- PEdge *e;
+ PEdge *e;
- if (!p_vert_map_harmonic_weights(v)) {
- /* do polygon kernel center insertion: this is quite slow, but should
- * only be needed for 0.01 % of verts or so, when insert with harmonic
- * weights fails */
+ if (!p_vert_map_harmonic_weights(v)) {
+ /* do polygon kernel center insertion: this is quite slow, but should
+ * only be needed for 0.01 % of verts or so, when insert with harmonic
+ * weights fails */
- int npoints = 0, i;
- float (*points)[2];
+ int npoints = 0, i;
+ float (*points)[2];
- e = v->edge;
- do {
- npoints++;
- e = p_wheel_edge_next(e);
- } while (e && (e != v->edge));
+ e = v->edge;
+ do {
+ npoints++;
+ e = p_wheel_edge_next(e);
+ } while (e && (e != v->edge));
- if (e == NULL)
- npoints++;
+ if (e == NULL)
+ npoints++;
- points = MEM_mallocN(sizeof(float) * 2 * npoints, "PHarmonicPoints");
+ points = MEM_mallocN(sizeof(float) * 2 * npoints, "PHarmonicPoints");
- e = v->edge;
- i = 0;
- do {
- PEdge *nexte = p_wheel_edge_next(e);
+ e = v->edge;
+ i = 0;
+ do {
+ PEdge *nexte = p_wheel_edge_next(e);
- points[i][0] = e->next->vert->uv[0];
- points[i][1] = e->next->vert->uv[1];
+ points[i][0] = e->next->vert->uv[0];
+ points[i][1] = e->next->vert->uv[1];
- if (nexte == NULL) {
- i++;
- points[i][0] = e->next->next->vert->uv[0];
- points[i][1] = e->next->next->vert->uv[1];
- break;
- }
+ if (nexte == NULL) {
+ i++;
+ points[i][0] = e->next->next->vert->uv[0];
+ points[i][1] = e->next->next->vert->uv[1];
+ break;
+ }
- e = nexte;
- i++;
- } while (e != v->edge);
+ e = nexte;
+ i++;
+ } while (e != v->edge);
- p_polygon_kernel_center(points, npoints, v->uv);
+ p_polygon_kernel_center(points, npoints, v->uv);
- MEM_freeN(points);
- }
+ MEM_freeN(points);
+ }
- e = v->edge;
- do {
- if (!(e->next->vert->flag & PVERT_PIN))
- p_vert_map_harmonic_weights(e->next->vert);
- e = p_wheel_edge_next(e);
- } while (e && (e != v->edge));
+ e = v->edge;
+ do {
+ if (!(e->next->vert->flag & PVERT_PIN))
+ p_vert_map_harmonic_weights(e->next->vert);
+ e = p_wheel_edge_next(e);
+ } while (e && (e != v->edge));
- p_vert_map_harmonic_weights(v);
+ p_vert_map_harmonic_weights(v);
}
static void p_vert_fix_edge_pointer(PVert *v)
{
- PEdge *start = v->edge;
+ PEdge *start = v->edge;
- /* set v->edge pointer to the edge with no pair, if there is one */
- while (v->edge->pair) {
- v->edge = p_wheel_edge_prev(v->edge);
+ /* set v->edge pointer to the edge with no pair, if there is one */
+ while (v->edge->pair) {
+ v->edge = p_wheel_edge_prev(v->edge);
- if (v->edge == start)
- break;
- }
+ if (v->edge == start)
+ break;
+ }
}
static void p_collapsing_verts(PEdge *edge, PEdge *pair, PVert **newv, PVert **keepv)
{
- /* the two vertices that are involved in the collapse */
- if (edge) {
- *newv = edge->vert;
- *keepv = edge->next->vert;
- }
- else {
- *newv = pair->next->vert;
- *keepv = pair->vert;
- }
+ /* the two vertices that are involved in the collapse */
+ if (edge) {
+ *newv = edge->vert;
+ *keepv = edge->next->vert;
+ }
+ else {
+ *newv = pair->next->vert;
+ *keepv = pair->vert;
+ }
}
static void p_collapse_edge(PEdge *edge, PEdge *pair)
{
- PVert *oldv, *keepv;
- PEdge *e;
+ PVert *oldv, *keepv;
+ PEdge *e;
- p_collapsing_verts(edge, pair, &oldv, &keepv);
+ p_collapsing_verts(edge, pair, &oldv, &keepv);
- /* change e->vert pointers from old vertex to the target vertex */
- e = oldv->edge;
- do {
- if ((e != edge) && !(pair && pair->next == e))
- e->vert = keepv;
+ /* change e->vert pointers from old vertex to the target vertex */
+ e = oldv->edge;
+ do {
+ if ((e != edge) && !(pair && pair->next == e))
+ e->vert = keepv;
- e = p_wheel_edge_next(e);
- } while (e && (e != oldv->edge));
+ e = p_wheel_edge_next(e);
+ } while (e && (e != oldv->edge));
- /* set keepv->edge pointer */
- if ((edge && (keepv->edge == edge->next)) || (keepv->edge == pair)) {
- if (edge && edge->next->pair)
- keepv->edge = edge->next->pair->next;
- else if (pair && pair->next->next->pair)
- keepv->edge = pair->next->next->pair;
- else if (edge && edge->next->next->pair)
- keepv->edge = edge->next->next->pair;
- else
- keepv->edge = pair->next->pair->next;
- }
+ /* set keepv->edge pointer */
+ if ((edge && (keepv->edge == edge->next)) || (keepv->edge == pair)) {
+ if (edge && edge->next->pair)
+ keepv->edge = edge->next->pair->next;
+ else if (pair && pair->next->next->pair)
+ keepv->edge = pair->next->next->pair;
+ else if (edge && edge->next->next->pair)
+ keepv->edge = edge->next->next->pair;
+ else
+ keepv->edge = pair->next->pair->next;
+ }
- /* update pairs and v->edge pointers */
- if (edge) {
- PEdge *e1 = edge->next, *e2 = e1->next;
+ /* update pairs and v->edge pointers */
+ if (edge) {
+ PEdge *e1 = edge->next, *e2 = e1->next;
- if (e1->pair)
- e1->pair->pair = e2->pair;
+ if (e1->pair)
+ e1->pair->pair = e2->pair;
- if (e2->pair) {
- e2->pair->pair = e1->pair;
- e2->vert->edge = p_wheel_edge_prev(e2);
- }
- else
- e2->vert->edge = p_wheel_edge_next(e2);
+ if (e2->pair) {
+ e2->pair->pair = e1->pair;
+ e2->vert->edge = p_wheel_edge_prev(e2);
+ }
+ else
+ e2->vert->edge = p_wheel_edge_next(e2);
- p_vert_fix_edge_pointer(e2->vert);
- }
+ p_vert_fix_edge_pointer(e2->vert);
+ }
- if (pair) {
- PEdge *e1 = pair->next, *e2 = e1->next;
+ if (pair) {
+ PEdge *e1 = pair->next, *e2 = e1->next;
- if (e1->pair)
- e1->pair->pair = e2->pair;
+ if (e1->pair)
+ e1->pair->pair = e2->pair;
- if (e2->pair) {
- e2->pair->pair = e1->pair;
- e2->vert->edge = p_wheel_edge_prev(e2);
- }
- else
- e2->vert->edge = p_wheel_edge_next(e2);
+ if (e2->pair) {
+ e2->pair->pair = e1->pair;
+ e2->vert->edge = p_wheel_edge_prev(e2);
+ }
+ else
+ e2->vert->edge = p_wheel_edge_next(e2);
- p_vert_fix_edge_pointer(e2->vert);
- }
+ p_vert_fix_edge_pointer(e2->vert);
+ }
- p_vert_fix_edge_pointer(keepv);
+ p_vert_fix_edge_pointer(keepv);
- /* mark for move to collapsed list later */
- oldv->flag |= PVERT_COLLAPSE;
+ /* mark for move to collapsed list later */
+ oldv->flag |= PVERT_COLLAPSE;
- if (edge) {
- PFace *f = edge->face;
- PEdge *e1 = edge->next, *e2 = e1->next;
+ if (edge) {
+ PFace *f = edge->face;
+ PEdge *e1 = edge->next, *e2 = e1->next;
- f->flag |= PFACE_COLLAPSE;
- edge->flag |= PEDGE_COLLAPSE;
- e1->flag |= PEDGE_COLLAPSE;
- e2->flag |= PEDGE_COLLAPSE;
- }
+ f->flag |= PFACE_COLLAPSE;
+ edge->flag |= PEDGE_COLLAPSE;
+ e1->flag |= PEDGE_COLLAPSE;
+ e2->flag |= PEDGE_COLLAPSE;
+ }
- if (pair) {
- PFace *f = pair->face;
- PEdge *e1 = pair->next, *e2 = e1->next;
+ if (pair) {
+ PFace *f = pair->face;
+ PEdge *e1 = pair->next, *e2 = e1->next;
- f->flag |= PFACE_COLLAPSE;
- pair->flag |= PEDGE_COLLAPSE;
- e1->flag |= PEDGE_COLLAPSE;
- e2->flag |= PEDGE_COLLAPSE;
- }
+ f->flag |= PFACE_COLLAPSE;
+ pair->flag |= PEDGE_COLLAPSE;
+ e1->flag |= PEDGE_COLLAPSE;
+ e2->flag |= PEDGE_COLLAPSE;
+ }
}
static void p_split_vertex(PEdge *edge, PEdge *pair)
{
- PVert *newv, *keepv;
- PEdge *e;
+ PVert *newv, *keepv;
+ PEdge *e;
- p_collapsing_verts(edge, pair, &newv, &keepv);
+ p_collapsing_verts(edge, pair, &newv, &keepv);
- /* update edge pairs */
- if (edge) {
- PEdge *e1 = edge->next, *e2 = e1->next;
+ /* update edge pairs */
+ if (edge) {
+ PEdge *e1 = edge->next, *e2 = e1->next;
- if (e1->pair)
- e1->pair->pair = e1;
- if (e2->pair)
- e2->pair->pair = e2;
+ if (e1->pair)
+ e1->pair->pair = e1;
+ if (e2->pair)
+ e2->pair->pair = e2;
- e2->vert->edge = e2;
- p_vert_fix_edge_pointer(e2->vert);
- keepv->edge = e1;
- }
+ e2->vert->edge = e2;
+ p_vert_fix_edge_pointer(e2->vert);
+ keepv->edge = e1;
+ }
- if (pair) {
- PEdge *e1 = pair->next, *e2 = e1->next;
+ if (pair) {
+ PEdge *e1 = pair->next, *e2 = e1->next;
- if (e1->pair)
- e1->pair->pair = e1;
- if (e2->pair)
- e2->pair->pair = e2;
+ if (e1->pair)
+ e1->pair->pair = e1;
+ if (e2->pair)
+ e2->pair->pair = e2;
- e2->vert->edge = e2;
- p_vert_fix_edge_pointer(e2->vert);
- keepv->edge = pair;
- }
+ e2->vert->edge = e2;
+ p_vert_fix_edge_pointer(e2->vert);
+ keepv->edge = pair;
+ }
- p_vert_fix_edge_pointer(keepv);
+ p_vert_fix_edge_pointer(keepv);
- /* set e->vert pointers to restored vertex */
- e = newv->edge;
- do {
- e->vert = newv;
- e = p_wheel_edge_next(e);
- } while (e && (e != newv->edge));
+ /* set e->vert pointers to restored vertex */
+ e = newv->edge;
+ do {
+ e->vert = newv;
+ e = p_wheel_edge_next(e);
+ } while (e && (e != newv->edge));
}
static PBool p_collapse_allowed_topologic(PEdge *edge, PEdge *pair)
{
- PVert *oldv, *keepv;
+ PVert *oldv, *keepv;
- p_collapsing_verts(edge, pair, &oldv, &keepv);
+ p_collapsing_verts(edge, pair, &oldv, &keepv);
- /* boundary edges */
- if (!edge || !pair) {
- /* avoid collapsing chart into an edge */
- if (edge && !edge->next->pair && !edge->next->next->pair)
- return P_FALSE;
- else if (pair && !pair->next->pair && !pair->next->next->pair)
- return P_FALSE;
- }
- /* avoid merging two boundaries (oldv and keepv are on the 'other side' of
- * the chart) */
- else if (!p_vert_interior(oldv) && !p_vert_interior(keepv))
- return P_FALSE;
+ /* boundary edges */
+ if (!edge || !pair) {
+ /* avoid collapsing chart into an edge */
+ if (edge && !edge->next->pair && !edge->next->next->pair)
+ return P_FALSE;
+ else if (pair && !pair->next->pair && !pair->next->next->pair)
+ return P_FALSE;
+ }
+ /* avoid merging two boundaries (oldv and keepv are on the 'other side' of
+ * the chart) */
+ else if (!p_vert_interior(oldv) && !p_vert_interior(keepv))
+ return P_FALSE;
- return P_TRUE;
+ return P_TRUE;
}
static PBool p_collapse_normal_flipped(float *v1, float *v2, float *vold, float *vnew)
{
- float nold[3], nnew[3], sub1[3], sub2[3];
+ float nold[3], nnew[3], sub1[3], sub2[3];
- sub_v3_v3v3(sub1, vold, v1);
- sub_v3_v3v3(sub2, vold, v2);
- cross_v3_v3v3(nold, sub1, sub2);
+ sub_v3_v3v3(sub1, vold, v1);
+ sub_v3_v3v3(sub2, vold, v2);
+ cross_v3_v3v3(nold, sub1, sub2);
- sub_v3_v3v3(sub1, vnew, v1);
- sub_v3_v3v3(sub2, vnew, v2);
- cross_v3_v3v3(nnew, sub1, sub2);
+ sub_v3_v3v3(sub1, vnew, v1);
+ sub_v3_v3v3(sub2, vnew, v2);
+ cross_v3_v3v3(nnew, sub1, sub2);
- return (dot_v3v3(nold, nnew) <= 0.0f);
+ return (dot_v3v3(nold, nnew) <= 0.0f);
}
static PBool p_collapse_allowed_geometric(PEdge *edge, PEdge *pair)
{
- PVert *oldv, *keepv;
- PEdge *e;
- float angulardefect, angle;
+ PVert *oldv, *keepv;
+ PEdge *e;
+ float angulardefect, angle;
- p_collapsing_verts(edge, pair, &oldv, &keepv);
+ p_collapsing_verts(edge, pair, &oldv, &keepv);
- angulardefect = 2 * M_PI;
+ angulardefect = 2 * M_PI;
- e = oldv->edge;
- do {
- float a[3], b[3], minangle, maxangle;
- PEdge *e1 = e->next, *e2 = e1->next;
- PVert *v1 = e1->vert, *v2 = e2->vert;
- int i;
+ e = oldv->edge;
+ do {
+ float a[3], b[3], minangle, maxangle;
+ PEdge *e1 = e->next, *e2 = e1->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert;
+ int i;
- angle = p_vec_angle(v1->co, oldv->co, v2->co);
- angulardefect -= angle;
+ angle = p_vec_angle(v1->co, oldv->co, v2->co);
+ angulardefect -= angle;
- /* skip collapsing faces */
- if (v1 == keepv || v2 == keepv) {
- e = p_wheel_edge_next(e);
- continue;
- }
+ /* skip collapsing faces */
+ if (v1 == keepv || v2 == keepv) {
+ e = p_wheel_edge_next(e);
+ continue;
+ }
- if (p_collapse_normal_flipped(v1->co, v2->co, oldv->co, keepv->co))
- return P_FALSE;
+ if (p_collapse_normal_flipped(v1->co, v2->co, oldv->co, keepv->co))
+ return P_FALSE;
- a[0] = angle;
- a[1] = p_vec_angle(v2->co, v1->co, oldv->co);
- a[2] = M_PI - a[0] - a[1];
+ a[0] = angle;
+ a[1] = p_vec_angle(v2->co, v1->co, oldv->co);
+ a[2] = M_PI - a[0] - a[1];
- b[0] = p_vec_angle(v1->co, keepv->co, v2->co);
- b[1] = p_vec_angle(v2->co, v1->co, keepv->co);
- b[2] = M_PI - b[0] - b[1];
+ b[0] = p_vec_angle(v1->co, keepv->co, v2->co);
+ b[1] = p_vec_angle(v2->co, v1->co, keepv->co);
+ b[2] = M_PI - b[0] - b[1];
- /* abf criterion 1: avoid sharp and obtuse angles */
- minangle = 15.0f * M_PI / 180.0f;
- maxangle = M_PI - minangle;
+ /* abf criterion 1: avoid sharp and obtuse angles */
+ minangle = 15.0f * M_PI / 180.0f;
+ maxangle = M_PI - minangle;
- for (i = 0; i < 3; i++) {
- if ((b[i] < a[i]) && (b[i] < minangle))
- return P_FALSE;
- else if ((b[i] > a[i]) && (b[i] > maxangle))
- return P_FALSE;
- }
+ for (i = 0; i < 3; i++) {
+ if ((b[i] < a[i]) && (b[i] < minangle))
+ return P_FALSE;
+ else if ((b[i] > a[i]) && (b[i] > maxangle))
+ return P_FALSE;
+ }
- e = p_wheel_edge_next(e);
- } while (e && (e != oldv->edge));
+ e = p_wheel_edge_next(e);
+ } while (e && (e != oldv->edge));
- if (p_vert_interior(oldv)) {
- /* hlscm criterion: angular defect smaller than threshold */
- if (fabsf(angulardefect) > (float)(M_PI * 30.0 / 180.0))
- return P_FALSE;
- }
- else {
- PVert *v1 = p_boundary_edge_next(oldv->edge)->vert;
- PVert *v2 = p_boundary_edge_prev(oldv->edge)->vert;
+ if (p_vert_interior(oldv)) {
+ /* hlscm criterion: angular defect smaller than threshold */
+ if (fabsf(angulardefect) > (float)(M_PI * 30.0 / 180.0))
+ return P_FALSE;
+ }
+ else {
+ PVert *v1 = p_boundary_edge_next(oldv->edge)->vert;
+ PVert *v2 = p_boundary_edge_prev(oldv->edge)->vert;
- /* abf++ criterion 2: avoid collapsing verts inwards */
- if (p_vert_interior(keepv))
- return P_FALSE;
+ /* abf++ criterion 2: avoid collapsing verts inwards */
+ if (p_vert_interior(keepv))
+ return P_FALSE;
- /* don't collapse significant boundary changes */
- angle = p_vec_angle(v1->co, oldv->co, v2->co);
- if (angle < (M_PI * 160.0 / 180.0))
- return P_FALSE;
- }
+ /* don't collapse significant boundary changes */
+ angle = p_vec_angle(v1->co, oldv->co, v2->co);
+ if (angle < (M_PI * 160.0 / 180.0))
+ return P_FALSE;
+ }
- return P_TRUE;
+ return P_TRUE;
}
static PBool p_collapse_allowed(PEdge *edge, PEdge *pair)
{
- PVert *oldv, *keepv;
+ PVert *oldv, *keepv;
- p_collapsing_verts(edge, pair, &oldv, &keepv);
+ p_collapsing_verts(edge, pair, &oldv, &keepv);
- if (oldv->flag & PVERT_PIN)
- return P_FALSE;
+ if (oldv->flag & PVERT_PIN)
+ return P_FALSE;
- return (p_collapse_allowed_topologic(edge, pair) &&
- p_collapse_allowed_geometric(edge, pair));
+ return (p_collapse_allowed_topologic(edge, pair) &&
+ p_collapse_allowed_geometric(edge, pair));
}
static float p_collapse_cost(PEdge *edge, PEdge *pair)
{
- /* based on volume and boundary optimization from:
- * "Fast and Memory Efficient Polygonal Simplification" P. Lindstrom, G. Turk */
+ /* based on volume and boundary optimization from:
+ * "Fast and Memory Efficient Polygonal Simplification" P. Lindstrom, G. Turk */
- PVert *oldv, *keepv;
- PEdge *e;
- PFace *oldf1, *oldf2;
- float volumecost = 0.0f, areacost = 0.0f, edgevec[3], cost, weight, elen;
- float shapecost = 0.0f;
- float shapeold = 0.0f, shapenew = 0.0f;
- int nshapeold = 0, nshapenew = 0;
+ PVert *oldv, *keepv;
+ PEdge *e;
+ PFace *oldf1, *oldf2;
+ float volumecost = 0.0f, areacost = 0.0f, edgevec[3], cost, weight, elen;
+ float shapecost = 0.0f;
+ float shapeold = 0.0f, shapenew = 0.0f;
+ int nshapeold = 0, nshapenew = 0;
- p_collapsing_verts(edge, pair, &oldv, &keepv);
- oldf1 = (edge) ? edge->face : NULL;
- oldf2 = (pair) ? pair->face : NULL;
+ p_collapsing_verts(edge, pair, &oldv, &keepv);
+ oldf1 = (edge) ? edge->face : NULL;
+ oldf2 = (pair) ? pair->face : NULL;
- sub_v3_v3v3(edgevec, keepv->co, oldv->co);
+ sub_v3_v3v3(edgevec, keepv->co, oldv->co);
- e = oldv->edge;
- do {
- float a1, a2, a3;
- float *co1 = e->next->vert->co;
- float *co2 = e->next->next->vert->co;
+ e = oldv->edge;
+ do {
+ float a1, a2, a3;
+ float *co1 = e->next->vert->co;
+ float *co2 = e->next->next->vert->co;
- if ((e->face != oldf1) && (e->face != oldf2)) {
- float tetrav2[3], tetrav3[3], c[3];
+ if ((e->face != oldf1) && (e->face != oldf2)) {
+ float tetrav2[3], tetrav3[3], c[3];
- /* tetrahedron volume = (1/3!)*|a.(b x c)| */
- sub_v3_v3v3(tetrav2, co1, oldv->co);
- sub_v3_v3v3(tetrav3, co2, oldv->co);
- cross_v3_v3v3(c, tetrav2, tetrav3);
+ /* tetrahedron volume = (1/3!)*|a.(b x c)| */
+ sub_v3_v3v3(tetrav2, co1, oldv->co);
+ sub_v3_v3v3(tetrav3, co2, oldv->co);
+ cross_v3_v3v3(c, tetrav2, tetrav3);
- volumecost += fabsf(dot_v3v3(edgevec, c) / 6.0f);
-#if 0
- shapecost += dot_v3v3(co1, keepv->co);
+ volumecost += fabsf(dot_v3v3(edgevec, c) / 6.0f);
+# if 0
+ shapecost += dot_v3v3(co1, keepv->co);
- if (p_wheel_edge_next(e) == NULL)
- shapecost += dot_v3v3(co2, keepv->co);
-#endif
+ if (p_wheel_edge_next(e) == NULL)
+ shapecost += dot_v3v3(co2, keepv->co);
+# endif
- p_triangle_angles(oldv->co, co1, co2, &a1, &a2, &a3);
- a1 = a1 - M_PI / 3.0;
- a2 = a2 - M_PI / 3.0;
- a3 = a3 - M_PI / 3.0;
- shapeold = (a1 * a1 + a2 * a2 + a3 * a3) / ((M_PI / 2) * (M_PI / 2));
-
- nshapeold++;
- }
- else {
- p_triangle_angles(keepv->co, co1, co2, &a1, &a2, &a3);
- a1 = a1 - M_PI / 3.0;
- a2 = a2 - M_PI / 3.0;
- a3 = a3 - M_PI / 3.0;
- shapenew = (a1 * a1 + a2 * a2 + a3 * a3) / ((M_PI / 2) * (M_PI / 2));
-
- nshapenew++;
- }
-
- e = p_wheel_edge_next(e);
- } while (e && (e != oldv->edge));
-
- if (!p_vert_interior(oldv)) {
- PVert *v1 = p_boundary_edge_prev(oldv->edge)->vert;
- PVert *v2 = p_boundary_edge_next(oldv->edge)->vert;
-
- areacost = area_tri_v3(oldv->co, v1->co, v2->co);
- }
-
- elen = len_v3(edgevec);
- weight = 1.0f; /* 0.2f */
- cost = weight * volumecost * volumecost + elen * elen * areacost * areacost;
-#if 0
- cost += shapecost;
-#else
- shapeold /= nshapeold;
- shapenew /= nshapenew;
- shapecost = (shapeold + 0.00001) / (shapenew + 0.00001);
+ p_triangle_angles(oldv->co, co1, co2, &a1, &a2, &a3);
+ a1 = a1 - M_PI / 3.0;
+ a2 = a2 - M_PI / 3.0;
+ a3 = a3 - M_PI / 3.0;
+ shapeold = (a1 * a1 + a2 * a2 + a3 * a3) / ((M_PI / 2) * (M_PI / 2));
+
+ nshapeold++;
+ }
+ else {
+ p_triangle_angles(keepv->co, co1, co2, &a1, &a2, &a3);
+ a1 = a1 - M_PI / 3.0;
+ a2 = a2 - M_PI / 3.0;
+ a3 = a3 - M_PI / 3.0;
+ shapenew = (a1 * a1 + a2 * a2 + a3 * a3) / ((M_PI / 2) * (M_PI / 2));
+
+ nshapenew++;
+ }
+
+ e = p_wheel_edge_next(e);
+ } while (e && (e != oldv->edge));
+
+ if (!p_vert_interior(oldv)) {
+ PVert *v1 = p_boundary_edge_prev(oldv->edge)->vert;
+ PVert *v2 = p_boundary_edge_next(oldv->edge)->vert;
+
+ areacost = area_tri_v3(oldv->co, v1->co, v2->co);
+ }
+
+ elen = len_v3(edgevec);
+ weight = 1.0f; /* 0.2f */
+ cost = weight * volumecost * volumecost + elen * elen * areacost * areacost;
+# if 0
+ cost += shapecost;
+# else
+ shapeold /= nshapeold;
+ shapenew /= nshapenew;
+ shapecost = (shapeold + 0.00001) / (shapenew + 0.00001);
- cost *= shapecost;
-#endif
+ cost *= shapecost;
+# endif
- return cost;
+ return cost;
}
static void p_collapse_cost_vertex(PVert *vert, float *mincost, PEdge **mine)
{
- PEdge *e, *enext, *pair;
+ PEdge *e, *enext, *pair;
- *mine = NULL;
- *mincost = 0.0f;
- e = vert->edge;
- do {
- if (p_collapse_allowed(e, e->pair)) {
- float cost = p_collapse_cost(e, e->pair);
+ *mine = NULL;
+ *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 ((*mine == NULL) || (cost < *mincost)) {
+ *mincost = cost;
+ *mine = e;
+ }
+ }
- enext = p_wheel_edge_next(e);
+ enext = p_wheel_edge_next(e);
- if (enext == NULL) {
- /* the other boundary edge, where we only have the pair halfedge */
- pair = e->next->next;
+ if (enext == NULL) {
+ /* the other boundary edge, where we only have the pair halfedge */
+ pair = e->next->next;
- if (p_collapse_allowed(NULL, pair)) {
- float cost = p_collapse_cost(NULL, pair);
+ if (p_collapse_allowed(NULL, pair)) {
+ float cost = p_collapse_cost(NULL, pair);
- if ((*mine == NULL) || (cost < *mincost)) {
- *mincost = cost;
- *mine = pair;
- }
- }
+ if ((*mine == NULL) || (cost < *mincost)) {
+ *mincost = cost;
+ *mine = pair;
+ }
+ }
- break;
- }
+ break;
+ }
- e = enext;
- } while (e != vert->edge);
+ e = enext;
+ } while (e != vert->edge);
}
static void p_chart_post_collapse_flush(PChart *chart, PEdge *collapsed)
{
- /* move to collapsed_ */
-
- PVert *v, *nextv = NULL, *verts = chart->verts;
- PEdge *e, *nexte = NULL, *edges = chart->edges, *laste = NULL;
- PFace *f, *nextf = NULL, *faces = chart->faces;
-
- chart->verts = chart->collapsed_verts = NULL;
- chart->edges = chart->collapsed_edges = NULL;
- chart->faces = chart->collapsed_faces = NULL;
-
- chart->nverts = chart->nedges = chart->nfaces = 0;
-
- for (v = verts; v; v = nextv) {
- nextv = v->nextlink;
-
- if (v->flag & PVERT_COLLAPSE) {
- v->nextlink = chart->collapsed_verts;
- chart->collapsed_verts = v;
- }
- else {
- v->nextlink = chart->verts;
- chart->verts = v;
- chart->nverts++;
- }
- }
-
- for (e = edges; e; e = nexte) {
- nexte = e->nextlink;
-
- if (!collapsed || !(e->flag & PEDGE_COLLAPSE_EDGE)) {
- if (e->flag & PEDGE_COLLAPSE) {
- e->nextlink = chart->collapsed_edges;
- chart->collapsed_edges = e;
- }
- else {
- e->nextlink = chart->edges;
- chart->edges = e;
- chart->nedges++;
- }
- }
- }
-
- /* these are added last so they can be popped of in the right order
- * for splitting */
- for (e = collapsed; e; e = e->nextlink) {
- e->nextlink = e->u.nextcollapse;
- laste = e;
- }
- if (laste) {
- laste->nextlink = chart->collapsed_edges;
- chart->collapsed_edges = collapsed;
- }
-
- for (f = faces; f; f = nextf) {
- nextf = f->nextlink;
-
- if (f->flag & PFACE_COLLAPSE) {
- f->nextlink = chart->collapsed_faces;
- chart->collapsed_faces = f;
- }
- else {
- f->nextlink = chart->faces;
- chart->faces = f;
- chart->nfaces++;
- }
- }
+ /* move to collapsed_ */
+
+ PVert *v, *nextv = NULL, *verts = chart->verts;
+ PEdge *e, *nexte = NULL, *edges = chart->edges, *laste = NULL;
+ PFace *f, *nextf = NULL, *faces = chart->faces;
+
+ chart->verts = chart->collapsed_verts = NULL;
+ chart->edges = chart->collapsed_edges = NULL;
+ chart->faces = chart->collapsed_faces = NULL;
+
+ chart->nverts = chart->nedges = chart->nfaces = 0;
+
+ for (v = verts; v; v = nextv) {
+ nextv = v->nextlink;
+
+ if (v->flag & PVERT_COLLAPSE) {
+ v->nextlink = chart->collapsed_verts;
+ chart->collapsed_verts = v;
+ }
+ else {
+ v->nextlink = chart->verts;
+ chart->verts = v;
+ chart->nverts++;
+ }
+ }
+
+ for (e = edges; e; e = nexte) {
+ nexte = e->nextlink;
+
+ if (!collapsed || !(e->flag & PEDGE_COLLAPSE_EDGE)) {
+ if (e->flag & PEDGE_COLLAPSE) {
+ e->nextlink = chart->collapsed_edges;
+ chart->collapsed_edges = e;
+ }
+ else {
+ e->nextlink = chart->edges;
+ chart->edges = e;
+ chart->nedges++;
+ }
+ }
+ }
+
+ /* these are added last so they can be popped of in the right order
+ * for splitting */
+ for (e = collapsed; e; e = e->nextlink) {
+ e->nextlink = e->u.nextcollapse;
+ laste = e;
+ }
+ if (laste) {
+ laste->nextlink = chart->collapsed_edges;
+ chart->collapsed_edges = collapsed;
+ }
+
+ for (f = faces; f; f = nextf) {
+ nextf = f->nextlink;
+
+ if (f->flag & PFACE_COLLAPSE) {
+ f->nextlink = chart->collapsed_faces;
+ chart->collapsed_faces = f;
+ }
+ else {
+ f->nextlink = chart->faces;
+ chart->faces = f;
+ chart->nfaces++;
+ }
+ }
}
static void p_chart_post_split_flush(PChart *chart)
{
- /* move from collapsed_ */
+ /* move from collapsed_ */
- PVert *v, *nextv = NULL;
- PEdge *e, *nexte = NULL;
- PFace *f, *nextf = NULL;
+ PVert *v, *nextv = NULL;
+ PEdge *e, *nexte = NULL;
+ PFace *f, *nextf = NULL;
- for (v = chart->collapsed_verts; v; v = nextv) {
- nextv = v->nextlink;
- v->nextlink = chart->verts;
- chart->verts = v;
- chart->nverts++;
- }
+ for (v = chart->collapsed_verts; v; v = nextv) {
+ nextv = v->nextlink;
+ v->nextlink = chart->verts;
+ chart->verts = v;
+ chart->nverts++;
+ }
- for (e = chart->collapsed_edges; e; e = nexte) {
- nexte = e->nextlink;
- e->nextlink = chart->edges;
- chart->edges = e;
- chart->nedges++;
- }
+ for (e = chart->collapsed_edges; e; e = nexte) {
+ nexte = e->nextlink;
+ e->nextlink = chart->edges;
+ chart->edges = e;
+ chart->nedges++;
+ }
- for (f = chart->collapsed_faces; f; f = nextf) {
- nextf = f->nextlink;
- f->nextlink = chart->faces;
- chart->faces = f;
- chart->nfaces++;
- }
+ for (f = chart->collapsed_faces; f; f = nextf) {
+ nextf = f->nextlink;
+ f->nextlink = chart->faces;
+ chart->faces = f;
+ chart->nfaces++;
+ }
- chart->collapsed_verts = NULL;
- chart->collapsed_edges = NULL;
- chart->collapsed_faces = NULL;
+ chart->collapsed_verts = NULL;
+ chart->collapsed_edges = NULL;
+ chart->collapsed_faces = NULL;
}
static void p_chart_simplify_compute(PChart *chart)
{
- /* Computes a list of edge collapses / vertex splits. The collapsed
- * simplices go in the chart->collapsed_* lists, The original and
- * collapsed may then be view as stacks, where the next collapse/split
- * is at the top of the respective lists. */
+ /* Computes a list of edge collapses / vertex splits. The collapsed
+ * simplices go in the chart->collapsed_* lists, The original and
+ * collapsed may then be view as stacks, where the next collapse/split
+ * is at the top of the respective lists. */
- Heap *heap = BLI_heap_new();
- PVert *v, **wheelverts;
- PEdge *collapsededges = NULL, *e;
- int nwheelverts, i, ncollapsed = 0;
+ Heap *heap = BLI_heap_new();
+ PVert *v, **wheelverts;
+ PEdge *collapsededges = NULL, *e;
+ int nwheelverts, i, ncollapsed = 0;
- wheelverts = MEM_mallocN(sizeof(PVert *) * chart->nverts, "PChartWheelVerts");
+ wheelverts = MEM_mallocN(sizeof(PVert *) * chart->nverts, "PChartWheelVerts");
- /* insert all potential collapses into heap */
- for (v = chart->verts; v; v = v->nextlink) {
- float cost;
- PEdge *e = NULL;
+ /* insert all potential collapses into heap */
+ for (v = chart->verts; v; v = v->nextlink) {
+ float cost;
+ PEdge *e = NULL;
- p_collapse_cost_vertex(v, &cost, &e);
+ p_collapse_cost_vertex(v, &cost, &e);
- if (e)
- v->u.heaplink = BLI_heap_insert(heap, cost, e);
- else
- v->u.heaplink = NULL;
- }
+ if (e)
+ v->u.heaplink = BLI_heap_insert(heap, cost, e);
+ else
+ v->u.heaplink = NULL;
+ }
- for (e = chart->edges; e; e = e->nextlink)
- e->u.nextcollapse = NULL;
+ for (e = chart->edges; e; e = e->nextlink)
+ e->u.nextcollapse = NULL;
- /* pop edge collapse out of heap one by one */
- while (!BLI_heap_is_empty(heap)) {
- if (ncollapsed == NCOLLAPSE)
- break;
+ /* pop edge collapse out of heap one by one */
+ while (!BLI_heap_is_empty(heap)) {
+ if (ncollapsed == NCOLLAPSE)
+ break;
- HeapNode *link = BLI_heap_top(heap);
- PEdge *edge = (PEdge *)BLI_heap_pop_min(heap), *pair = edge->pair;
- PVert *oldv, *keepv;
- PEdge *wheele, *nexte;
+ HeapNode *link = BLI_heap_top(heap);
+ PEdge *edge = (PEdge *)BLI_heap_pop_min(heap), *pair = edge->pair;
+ PVert *oldv, *keepv;
+ PEdge *wheele, *nexte;
- /* remember the edges we collapsed */
- edge->u.nextcollapse = collapsededges;
- collapsededges = edge;
+ /* remember the edges we collapsed */
+ edge->u.nextcollapse = collapsededges;
+ collapsededges = edge;
- if (edge->vert->u.heaplink != link) {
- edge->flag |= (PEDGE_COLLAPSE_EDGE | PEDGE_COLLAPSE_PAIR);
- edge->next->vert->u.heaplink = NULL;
- SWAP(PEdge *, edge, pair);
- }
- else {
- edge->flag |= PEDGE_COLLAPSE_EDGE;
- edge->vert->u.heaplink = NULL;
- }
+ if (edge->vert->u.heaplink != link) {
+ edge->flag |= (PEDGE_COLLAPSE_EDGE | PEDGE_COLLAPSE_PAIR);
+ edge->next->vert->u.heaplink = NULL;
+ SWAP(PEdge *, edge, pair);
+ }
+ else {
+ edge->flag |= PEDGE_COLLAPSE_EDGE;
+ edge->vert->u.heaplink = NULL;
+ }
- p_collapsing_verts(edge, pair, &oldv, &keepv);
+ p_collapsing_verts(edge, pair, &oldv, &keepv);
- /* gather all wheel verts and remember them before collapse */
- nwheelverts = 0;
- wheele = oldv->edge;
+ /* gather all wheel verts and remember them before collapse */
+ nwheelverts = 0;
+ wheele = oldv->edge;
- do {
- wheelverts[nwheelverts++] = wheele->next->vert;
- nexte = p_wheel_edge_next(wheele);
+ do {
+ wheelverts[nwheelverts++] = wheele->next->vert;
+ nexte = p_wheel_edge_next(wheele);
- if (nexte == NULL)
- wheelverts[nwheelverts++] = wheele->next->next->vert;
+ if (nexte == NULL)
+ wheelverts[nwheelverts++] = wheele->next->next->vert;
- wheele = nexte;
- } while (wheele && (wheele != oldv->edge));
+ wheele = nexte;
+ } while (wheele && (wheele != oldv->edge));
- /* collapse */
- p_collapse_edge(edge, pair);
+ /* collapse */
+ p_collapse_edge(edge, pair);
- for (i = 0; i < nwheelverts; i++) {
- float cost;
- PEdge *collapse = NULL;
+ for (i = 0; i < nwheelverts; i++) {
+ float cost;
+ PEdge *collapse = NULL;
- v = wheelverts[i];
+ v = wheelverts[i];
- if (v->u.heaplink) {
- BLI_heap_remove(heap, v->u.heaplink);
- v->u.heaplink = NULL;
- }
+ if (v->u.heaplink) {
+ BLI_heap_remove(heap, v->u.heaplink);
+ v->u.heaplink = NULL;
+ }
- p_collapse_cost_vertex(v, &cost, &collapse);
+ p_collapse_cost_vertex(v, &cost, &collapse);
- if (collapse)
- v->u.heaplink = BLI_heap_insert(heap, cost, collapse);
- }
+ if (collapse)
+ v->u.heaplink = BLI_heap_insert(heap, cost, collapse);
+ }
- ncollapsed++;
- }
+ ncollapsed++;
+ }
- MEM_freeN(wheelverts);
- BLI_heap_free(heap, NULL);
+ MEM_freeN(wheelverts);
+ BLI_heap_free(heap, NULL);
- p_chart_post_collapse_flush(chart, collapsededges);
+ p_chart_post_collapse_flush(chart, collapsededges);
}
static void p_chart_complexify(PChart *chart)
{
- PEdge *e, *pair, *edge;
- PVert *newv, *keepv;
- int x = 0;
+ PEdge *e, *pair, *edge;
+ PVert *newv, *keepv;
+ int x = 0;
- for (e = chart->collapsed_edges; e; e = e->nextlink) {
- if (!(e->flag & PEDGE_COLLAPSE_EDGE))
- break;
+ for (e = chart->collapsed_edges; e; e = e->nextlink) {
+ if (!(e->flag & PEDGE_COLLAPSE_EDGE))
+ break;
- edge = e;
- pair = e->pair;
+ edge = e;
+ pair = e->pair;
- if (edge->flag & PEDGE_COLLAPSE_PAIR) {
- SWAP(PEdge *, edge, pair);
- }
+ if (edge->flag & PEDGE_COLLAPSE_PAIR) {
+ SWAP(PEdge *, edge, pair);
+ }
- p_split_vertex(edge, pair);
- p_collapsing_verts(edge, pair, &newv, &keepv);
+ p_split_vertex(edge, pair);
+ p_collapsing_verts(edge, pair, &newv, &keepv);
- if (x >= NCOLLAPSEX) {
- newv->uv[0] = keepv->uv[0];
- newv->uv[1] = keepv->uv[1];
- }
- else {
- p_vert_harmonic_insert(newv);
- x++;
- }
- }
+ if (x >= NCOLLAPSEX) {
+ newv->uv[0] = keepv->uv[0];
+ newv->uv[1] = keepv->uv[1];
+ }
+ else {
+ p_vert_harmonic_insert(newv);
+ x++;
+ }
+ }
- p_chart_post_split_flush(chart);
+ p_chart_post_split_flush(chart);
}
-#if 0
+# if 0
static void p_chart_simplify(PChart *chart)
{
- /* Not implemented, needs proper reordering in split_flush. */
+ /* Not implemented, needs proper reordering in split_flush. */
}
-#endif
+# endif
#endif
/* ABF */
@@ -2300,925 +2316,937 @@ static void p_chart_simplify(PChart *chart)
#define ABF_MAX_ITER 20
typedef struct PAbfSystem {
- int ninterior, nfaces, nangles;
- float *alpha, *beta, *sine, *cosine, *weight;
- float *bAlpha, *bTriangle, *bInterior;
- float *lambdaTriangle, *lambdaPlanar, *lambdaLength;
- float (*J2dt)[3], *bstar, *dstar;
- float minangle, maxangle;
+ int ninterior, nfaces, nangles;
+ float *alpha, *beta, *sine, *cosine, *weight;
+ float *bAlpha, *bTriangle, *bInterior;
+ float *lambdaTriangle, *lambdaPlanar, *lambdaLength;
+ float (*J2dt)[3], *bstar, *dstar;
+ float minangle, maxangle;
} PAbfSystem;
static void p_abf_setup_system(PAbfSystem *sys)
{
- int i;
+ int i;
- sys->alpha = (float *)MEM_mallocN(sizeof(float) * sys->nangles, "ABFalpha");
- sys->beta = (float *)MEM_mallocN(sizeof(float) * sys->nangles, "ABFbeta");
- sys->sine = (float *)MEM_mallocN(sizeof(float) * sys->nangles, "ABFsine");
- sys->cosine = (float *)MEM_mallocN(sizeof(float) * sys->nangles, "ABFcosine");
- sys->weight = (float *)MEM_mallocN(sizeof(float) * sys->nangles, "ABFweight");
+ sys->alpha = (float *)MEM_mallocN(sizeof(float) * sys->nangles, "ABFalpha");
+ sys->beta = (float *)MEM_mallocN(sizeof(float) * sys->nangles, "ABFbeta");
+ sys->sine = (float *)MEM_mallocN(sizeof(float) * sys->nangles, "ABFsine");
+ sys->cosine = (float *)MEM_mallocN(sizeof(float) * sys->nangles, "ABFcosine");
+ sys->weight = (float *)MEM_mallocN(sizeof(float) * sys->nangles, "ABFweight");
- sys->bAlpha = (float *)MEM_mallocN(sizeof(float) * sys->nangles, "ABFbalpha");
- sys->bTriangle = (float *)MEM_mallocN(sizeof(float) * sys->nfaces, "ABFbtriangle");
- sys->bInterior = (float *)MEM_mallocN(sizeof(float) * 2 * sys->ninterior, "ABFbinterior");
+ sys->bAlpha = (float *)MEM_mallocN(sizeof(float) * sys->nangles, "ABFbalpha");
+ sys->bTriangle = (float *)MEM_mallocN(sizeof(float) * sys->nfaces, "ABFbtriangle");
+ sys->bInterior = (float *)MEM_mallocN(sizeof(float) * 2 * sys->ninterior, "ABFbinterior");
- sys->lambdaTriangle = (float *)MEM_callocN(sizeof(float) * sys->nfaces, "ABFlambdatri");
- sys->lambdaPlanar = (float *)MEM_callocN(sizeof(float) * sys->ninterior, "ABFlamdaplane");
- sys->lambdaLength = (float *)MEM_mallocN(sizeof(float) * sys->ninterior, "ABFlambdalen");
+ sys->lambdaTriangle = (float *)MEM_callocN(sizeof(float) * sys->nfaces, "ABFlambdatri");
+ sys->lambdaPlanar = (float *)MEM_callocN(sizeof(float) * sys->ninterior, "ABFlamdaplane");
+ sys->lambdaLength = (float *)MEM_mallocN(sizeof(float) * sys->ninterior, "ABFlambdalen");
- sys->J2dt = MEM_mallocN(sizeof(float) * sys->nangles * 3, "ABFj2dt");
- sys->bstar = (float *)MEM_mallocN(sizeof(float) * sys->nfaces, "ABFbstar");
- sys->dstar = (float *)MEM_mallocN(sizeof(float) * sys->nfaces, "ABFdstar");
+ sys->J2dt = MEM_mallocN(sizeof(float) * sys->nangles * 3, "ABFj2dt");
+ sys->bstar = (float *)MEM_mallocN(sizeof(float) * sys->nfaces, "ABFbstar");
+ sys->dstar = (float *)MEM_mallocN(sizeof(float) * sys->nfaces, "ABFdstar");
- for (i = 0; i < sys->ninterior; i++)
- sys->lambdaLength[i] = 1.0;
+ for (i = 0; i < sys->ninterior; i++)
+ sys->lambdaLength[i] = 1.0;
- sys->minangle = 1.0 * M_PI / 180.0;
- sys->maxangle = (float)M_PI - sys->minangle;
+ sys->minangle = 1.0 * M_PI / 180.0;
+ sys->maxangle = (float)M_PI - sys->minangle;
}
static void p_abf_free_system(PAbfSystem *sys)
{
- MEM_freeN(sys->alpha);
- MEM_freeN(sys->beta);
- MEM_freeN(sys->sine);
- MEM_freeN(sys->cosine);
- MEM_freeN(sys->weight);
- MEM_freeN(sys->bAlpha);
- MEM_freeN(sys->bTriangle);
- MEM_freeN(sys->bInterior);
- MEM_freeN(sys->lambdaTriangle);
- MEM_freeN(sys->lambdaPlanar);
- MEM_freeN(sys->lambdaLength);
- MEM_freeN(sys->J2dt);
- MEM_freeN(sys->bstar);
- MEM_freeN(sys->dstar);
+ MEM_freeN(sys->alpha);
+ MEM_freeN(sys->beta);
+ MEM_freeN(sys->sine);
+ MEM_freeN(sys->cosine);
+ MEM_freeN(sys->weight);
+ MEM_freeN(sys->bAlpha);
+ MEM_freeN(sys->bTriangle);
+ MEM_freeN(sys->bInterior);
+ MEM_freeN(sys->lambdaTriangle);
+ MEM_freeN(sys->lambdaPlanar);
+ MEM_freeN(sys->lambdaLength);
+ MEM_freeN(sys->J2dt);
+ MEM_freeN(sys->bstar);
+ MEM_freeN(sys->dstar);
}
static void p_abf_compute_sines(PAbfSystem *sys)
{
- int i;
- float *sine = sys->sine, *cosine = sys->cosine, *alpha = sys->alpha;
+ int i;
+ float *sine = sys->sine, *cosine = sys->cosine, *alpha = sys->alpha;
- for (i = 0; i < sys->nangles; i++, sine++, cosine++, alpha++) {
- *sine = sinf(*alpha);
- *cosine = cosf(*alpha);
- }
+ for (i = 0; i < sys->nangles; i++, sine++, cosine++, alpha++) {
+ *sine = sinf(*alpha);
+ *cosine = cosf(*alpha);
+ }
}
static float p_abf_compute_sin_product(PAbfSystem *sys, PVert *v, int aid)
{
- PEdge *e, *e1, *e2;
- float sin1, sin2;
+ PEdge *e, *e1, *e2;
+ float sin1, sin2;
- sin1 = sin2 = 1.0;
+ sin1 = sin2 = 1.0;
- e = v->edge;
- do {
- e1 = e->next;
- e2 = e->next->next;
+ e = v->edge;
+ do {
+ e1 = e->next;
+ e2 = e->next->next;
- if (aid == e1->u.id) {
- /* we are computing a derivative for this angle,
- * so we use cos and drop the other part */
- sin1 *= sys->cosine[e1->u.id];
- sin2 = 0.0;
- }
- else
- sin1 *= sys->sine[e1->u.id];
+ if (aid == e1->u.id) {
+ /* we are computing a derivative for this angle,
+ * so we use cos and drop the other part */
+ sin1 *= sys->cosine[e1->u.id];
+ sin2 = 0.0;
+ }
+ else
+ sin1 *= sys->sine[e1->u.id];
- if (aid == e2->u.id) {
- /* see above */
- sin1 = 0.0;
- sin2 *= sys->cosine[e2->u.id];
- }
- else
- sin2 *= sys->sine[e2->u.id];
+ if (aid == e2->u.id) {
+ /* see above */
+ sin1 = 0.0;
+ sin2 *= sys->cosine[e2->u.id];
+ }
+ else
+ sin2 *= sys->sine[e2->u.id];
- e = e->next->next->pair;
- } while (e && (e != v->edge));
+ e = e->next->next->pair;
+ } while (e && (e != v->edge));
- return (sin1 - sin2);
+ return (sin1 - sin2);
}
static float p_abf_compute_grad_alpha(PAbfSystem *sys, PFace *f, PEdge *e)
{
- PVert *v = e->vert, *v1 = e->next->vert, *v2 = e->next->next->vert;
- float deriv;
+ PVert *v = e->vert, *v1 = e->next->vert, *v2 = e->next->next->vert;
+ float deriv;
- deriv = (sys->alpha[e->u.id] - sys->beta[e->u.id]) * sys->weight[e->u.id];
- deriv += sys->lambdaTriangle[f->u.id];
+ deriv = (sys->alpha[e->u.id] - sys->beta[e->u.id]) * sys->weight[e->u.id];
+ deriv += sys->lambdaTriangle[f->u.id];
- if (v->flag & PVERT_INTERIOR) {
- deriv += sys->lambdaPlanar[v->u.id];
- }
+ if (v->flag & PVERT_INTERIOR) {
+ deriv += sys->lambdaPlanar[v->u.id];
+ }
- if (v1->flag & PVERT_INTERIOR) {
- float product = p_abf_compute_sin_product(sys, v1, e->u.id);
- deriv += sys->lambdaLength[v1->u.id] * product;
- }
+ if (v1->flag & PVERT_INTERIOR) {
+ float product = p_abf_compute_sin_product(sys, v1, e->u.id);
+ deriv += sys->lambdaLength[v1->u.id] * product;
+ }
- if (v2->flag & PVERT_INTERIOR) {
- float product = p_abf_compute_sin_product(sys, v2, e->u.id);
- deriv += sys->lambdaLength[v2->u.id] * product;
- }
+ if (v2->flag & PVERT_INTERIOR) {
+ float product = p_abf_compute_sin_product(sys, v2, e->u.id);
+ deriv += sys->lambdaLength[v2->u.id] * product;
+ }
- return deriv;
+ return deriv;
}
static float p_abf_compute_gradient(PAbfSystem *sys, PChart *chart)
{
- PFace *f;
- PEdge *e;
- PVert *v;
- float norm = 0.0;
+ PFace *f;
+ PEdge *e;
+ PVert *v;
+ float norm = 0.0;
- for (f = chart->faces; f; f = f->nextlink) {
- PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
- float gtriangle, galpha1, galpha2, galpha3;
+ for (f = chart->faces; f; f = f->nextlink) {
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ float gtriangle, galpha1, galpha2, galpha3;
- galpha1 = p_abf_compute_grad_alpha(sys, f, e1);
- galpha2 = p_abf_compute_grad_alpha(sys, f, e2);
- galpha3 = p_abf_compute_grad_alpha(sys, f, e3);
+ galpha1 = p_abf_compute_grad_alpha(sys, f, e1);
+ galpha2 = p_abf_compute_grad_alpha(sys, f, e2);
+ galpha3 = p_abf_compute_grad_alpha(sys, f, e3);
- sys->bAlpha[e1->u.id] = -galpha1;
- sys->bAlpha[e2->u.id] = -galpha2;
- sys->bAlpha[e3->u.id] = -galpha3;
+ sys->bAlpha[e1->u.id] = -galpha1;
+ sys->bAlpha[e2->u.id] = -galpha2;
+ sys->bAlpha[e3->u.id] = -galpha3;
- norm += galpha1 * galpha1 + galpha2 * galpha2 + galpha3 * galpha3;
+ norm += galpha1 * galpha1 + galpha2 * galpha2 + galpha3 * galpha3;
- gtriangle = sys->alpha[e1->u.id] + sys->alpha[e2->u.id] + sys->alpha[e3->u.id] - (float)M_PI;
- sys->bTriangle[f->u.id] = -gtriangle;
- norm += gtriangle * gtriangle;
- }
+ gtriangle = sys->alpha[e1->u.id] + sys->alpha[e2->u.id] + sys->alpha[e3->u.id] - (float)M_PI;
+ sys->bTriangle[f->u.id] = -gtriangle;
+ norm += gtriangle * gtriangle;
+ }
- for (v = chart->verts; v; v = v->nextlink) {
- if (v->flag & PVERT_INTERIOR) {
- float gplanar = -2 * M_PI, glength;
+ for (v = chart->verts; v; v = v->nextlink) {
+ if (v->flag & PVERT_INTERIOR) {
+ float gplanar = -2 * M_PI, glength;
- e = v->edge;
- do {
- gplanar += sys->alpha[e->u.id];
- e = e->next->next->pair;
- } while (e && (e != v->edge));
+ e = v->edge;
+ do {
+ gplanar += sys->alpha[e->u.id];
+ e = e->next->next->pair;
+ } while (e && (e != v->edge));
- sys->bInterior[v->u.id] = -gplanar;
- norm += gplanar * gplanar;
+ sys->bInterior[v->u.id] = -gplanar;
+ norm += gplanar * gplanar;
- glength = p_abf_compute_sin_product(sys, v, -1);
- sys->bInterior[sys->ninterior + v->u.id] = -glength;
- norm += glength * glength;
- }
- }
+ glength = p_abf_compute_sin_product(sys, v, -1);
+ sys->bInterior[sys->ninterior + v->u.id] = -glength;
+ norm += glength * glength;
+ }
+ }
- return norm;
+ return norm;
}
static PBool p_abf_matrix_invert(PAbfSystem *sys, PChart *chart)
{
- PFace *f;
- PEdge *e;
- int i, j, ninterior = sys->ninterior, nvar = 2 * sys->ninterior;
- PBool success;
- LinearSolver *context;
-
- context = EIG_linear_solver_new(0, nvar, 1);
-
- for (i = 0; i < nvar; i++)
- EIG_linear_solver_right_hand_side_add(context, 0, i, sys->bInterior[i]);
-
- for (f = chart->faces; f; f = f->nextlink) {
- float wi1, wi2, wi3, b, si, beta[3], j2[3][3], W[3][3];
- float row1[6], row2[6], row3[6];
- int vid[6];
- PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
- PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
-
- wi1 = 1.0f / sys->weight[e1->u.id];
- wi2 = 1.0f / sys->weight[e2->u.id];
- wi3 = 1.0f / sys->weight[e3->u.id];
-
- /* bstar1 = (J1*dInv*bAlpha - bTriangle) */
- b = sys->bAlpha[e1->u.id] * wi1;
- b += sys->bAlpha[e2->u.id] * wi2;
- b += sys->bAlpha[e3->u.id] * wi3;
- b -= sys->bTriangle[f->u.id];
-
- /* si = J1*d*J1t */
- si = 1.0f / (wi1 + wi2 + wi3);
-
- /* J1t*si*bstar1 - bAlpha */
- beta[0] = b * si - sys->bAlpha[e1->u.id];
- beta[1] = b * si - sys->bAlpha[e2->u.id];
- beta[2] = b * si - sys->bAlpha[e3->u.id];
-
- /* use this later for computing other lambda's */
- sys->bstar[f->u.id] = b;
- sys->dstar[f->u.id] = si;
-
- /* set matrix */
- W[0][0] = si - sys->weight[e1->u.id]; W[0][1] = si; W[0][2] = si;
- W[1][0] = si; W[1][1] = si - sys->weight[e2->u.id]; W[1][2] = si;
- W[2][0] = si; W[2][1] = si; W[2][2] = si - sys->weight[e3->u.id];
-
- vid[0] = vid[1] = vid[2] = vid[3] = vid[4] = vid[5] = -1;
-
- if (v1->flag & PVERT_INTERIOR) {
- vid[0] = v1->u.id;
- vid[3] = ninterior + v1->u.id;
-
- sys->J2dt[e1->u.id][0] = j2[0][0] = 1.0f * wi1;
- sys->J2dt[e2->u.id][0] = j2[1][0] = p_abf_compute_sin_product(sys, v1, e2->u.id) * wi2;
- sys->J2dt[e3->u.id][0] = j2[2][0] = p_abf_compute_sin_product(sys, v1, e3->u.id) * wi3;
-
- EIG_linear_solver_right_hand_side_add(context, 0, v1->u.id, j2[0][0] * beta[0]);
- EIG_linear_solver_right_hand_side_add(context, 0, ninterior + v1->u.id, j2[1][0] * beta[1] + j2[2][0] * beta[2]);
-
- row1[0] = j2[0][0] * W[0][0];
- row2[0] = j2[0][0] * W[1][0];
- row3[0] = j2[0][0] * W[2][0];
-
- row1[3] = j2[1][0] * W[0][1] + j2[2][0] * W[0][2];
- row2[3] = j2[1][0] * W[1][1] + j2[2][0] * W[1][2];
- row3[3] = j2[1][0] * W[2][1] + j2[2][0] * W[2][2];
- }
-
- if (v2->flag & PVERT_INTERIOR) {
- vid[1] = v2->u.id;
- vid[4] = ninterior + v2->u.id;
-
- sys->J2dt[e1->u.id][1] = j2[0][1] = p_abf_compute_sin_product(sys, v2, e1->u.id) * wi1;
- sys->J2dt[e2->u.id][1] = j2[1][1] = 1.0f * wi2;
- sys->J2dt[e3->u.id][1] = j2[2][1] = p_abf_compute_sin_product(sys, v2, e3->u.id) * wi3;
-
- EIG_linear_solver_right_hand_side_add(context, 0, v2->u.id, j2[1][1] * beta[1]);
- EIG_linear_solver_right_hand_side_add(context, 0, ninterior + v2->u.id, j2[0][1] * beta[0] + j2[2][1] * beta[2]);
-
- row1[1] = j2[1][1] * W[0][1];
- row2[1] = j2[1][1] * W[1][1];
- row3[1] = j2[1][1] * W[2][1];
-
- row1[4] = j2[0][1] * W[0][0] + j2[2][1] * W[0][2];
- row2[4] = j2[0][1] * W[1][0] + j2[2][1] * W[1][2];
- row3[4] = j2[0][1] * W[2][0] + j2[2][1] * W[2][2];
- }
-
- if (v3->flag & PVERT_INTERIOR) {
- vid[2] = v3->u.id;
- vid[5] = ninterior + v3->u.id;
-
- sys->J2dt[e1->u.id][2] = j2[0][2] = p_abf_compute_sin_product(sys, v3, e1->u.id) * wi1;
- sys->J2dt[e2->u.id][2] = j2[1][2] = p_abf_compute_sin_product(sys, v3, e2->u.id) * wi2;
- sys->J2dt[e3->u.id][2] = j2[2][2] = 1.0f * wi3;
-
- EIG_linear_solver_right_hand_side_add(context, 0, v3->u.id, j2[2][2] * beta[2]);
- EIG_linear_solver_right_hand_side_add(context, 0, ninterior + v3->u.id, j2[0][2] * beta[0] + j2[1][2] * beta[1]);
-
- row1[2] = j2[2][2] * W[0][2];
- row2[2] = j2[2][2] * W[1][2];
- row3[2] = j2[2][2] * W[2][2];
-
- row1[5] = j2[0][2] * W[0][0] + j2[1][2] * W[0][1];
- row2[5] = j2[0][2] * W[1][0] + j2[1][2] * W[1][1];
- row3[5] = j2[0][2] * W[2][0] + j2[1][2] * W[2][1];
- }
-
- for (i = 0; i < 3; i++) {
- int r = vid[i];
-
- if (r == -1)
- continue;
-
- for (j = 0; j < 6; j++) {
- int c = vid[j];
-
- if (c == -1)
- continue;
-
- if (i == 0)
- EIG_linear_solver_matrix_add(context, r, c, j2[0][i] * row1[j]);
- else
- EIG_linear_solver_matrix_add(context, r + ninterior, c, j2[0][i] * row1[j]);
-
- if (i == 1)
- EIG_linear_solver_matrix_add(context, r, c, j2[1][i] * row2[j]);
- else
- EIG_linear_solver_matrix_add(context, r + ninterior, c, j2[1][i] * row2[j]);
-
-
- if (i == 2)
- EIG_linear_solver_matrix_add(context, r, c, j2[2][i] * row3[j]);
- else
- EIG_linear_solver_matrix_add(context, r + ninterior, c, j2[2][i] * row3[j]);
- }
- }
- }
-
- success = EIG_linear_solver_solve(context);
-
- if (success) {
- for (f = chart->faces; f; f = f->nextlink) {
- float dlambda1, pre[3], dalpha;
- PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
- PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
-
- pre[0] = pre[1] = pre[2] = 0.0;
-
- if (v1->flag & PVERT_INTERIOR) {
- float x = EIG_linear_solver_variable_get(context, 0, v1->u.id);
- float x2 = EIG_linear_solver_variable_get(context, 0, ninterior + v1->u.id);
- pre[0] += sys->J2dt[e1->u.id][0] * x;
- pre[1] += sys->J2dt[e2->u.id][0] * x2;
- pre[2] += sys->J2dt[e3->u.id][0] * x2;
- }
-
- if (v2->flag & PVERT_INTERIOR) {
- float x = EIG_linear_solver_variable_get(context, 0, v2->u.id);
- float x2 = EIG_linear_solver_variable_get(context, 0, ninterior + v2->u.id);
- pre[0] += sys->J2dt[e1->u.id][1] * x2;
- pre[1] += sys->J2dt[e2->u.id][1] * x;
- pre[2] += sys->J2dt[e3->u.id][1] * x2;
- }
-
- if (v3->flag & PVERT_INTERIOR) {
- float x = EIG_linear_solver_variable_get(context, 0, v3->u.id);
- float x2 = EIG_linear_solver_variable_get(context, 0, ninterior + v3->u.id);
- pre[0] += sys->J2dt[e1->u.id][2] * x2;
- pre[1] += sys->J2dt[e2->u.id][2] * x2;
- pre[2] += sys->J2dt[e3->u.id][2] * x;
- }
-
- dlambda1 = pre[0] + pre[1] + pre[2];
- dlambda1 = sys->dstar[f->u.id] * (sys->bstar[f->u.id] - dlambda1);
-
- sys->lambdaTriangle[f->u.id] += dlambda1;
-
- dalpha = (sys->bAlpha[e1->u.id] - dlambda1);
- sys->alpha[e1->u.id] += dalpha / sys->weight[e1->u.id] - pre[0];
-
- dalpha = (sys->bAlpha[e2->u.id] - dlambda1);
- sys->alpha[e2->u.id] += dalpha / sys->weight[e2->u.id] - pre[1];
-
- dalpha = (sys->bAlpha[e3->u.id] - dlambda1);
- sys->alpha[e3->u.id] += dalpha / sys->weight[e3->u.id] - pre[2];
-
- /* clamp */
- e = f->edge;
- do {
- if (sys->alpha[e->u.id] > (float)M_PI)
- sys->alpha[e->u.id] = (float)M_PI;
- else if (sys->alpha[e->u.id] < 0.0f)
- sys->alpha[e->u.id] = 0.0f;
- } while (e != f->edge);
- }
-
- for (i = 0; i < ninterior; i++) {
- sys->lambdaPlanar[i] += (float)EIG_linear_solver_variable_get(context, 0, i);
- sys->lambdaLength[i] += (float)EIG_linear_solver_variable_get(context, 0, ninterior + i);
- }
- }
-
- EIG_linear_solver_delete(context);
-
- return success;
+ PFace *f;
+ PEdge *e;
+ int i, j, ninterior = sys->ninterior, nvar = 2 * sys->ninterior;
+ PBool success;
+ LinearSolver *context;
+
+ context = EIG_linear_solver_new(0, nvar, 1);
+
+ for (i = 0; i < nvar; i++)
+ EIG_linear_solver_right_hand_side_add(context, 0, i, sys->bInterior[i]);
+
+ for (f = chart->faces; f; f = f->nextlink) {
+ float wi1, wi2, wi3, b, si, beta[3], j2[3][3], W[3][3];
+ float row1[6], row2[6], row3[6];
+ int vid[6];
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
+
+ wi1 = 1.0f / sys->weight[e1->u.id];
+ wi2 = 1.0f / sys->weight[e2->u.id];
+ wi3 = 1.0f / sys->weight[e3->u.id];
+
+ /* bstar1 = (J1*dInv*bAlpha - bTriangle) */
+ b = sys->bAlpha[e1->u.id] * wi1;
+ b += sys->bAlpha[e2->u.id] * wi2;
+ b += sys->bAlpha[e3->u.id] * wi3;
+ b -= sys->bTriangle[f->u.id];
+
+ /* si = J1*d*J1t */
+ si = 1.0f / (wi1 + wi2 + wi3);
+
+ /* J1t*si*bstar1 - bAlpha */
+ beta[0] = b * si - sys->bAlpha[e1->u.id];
+ beta[1] = b * si - sys->bAlpha[e2->u.id];
+ beta[2] = b * si - sys->bAlpha[e3->u.id];
+
+ /* use this later for computing other lambda's */
+ sys->bstar[f->u.id] = b;
+ sys->dstar[f->u.id] = si;
+
+ /* set matrix */
+ W[0][0] = si - sys->weight[e1->u.id];
+ W[0][1] = si;
+ W[0][2] = si;
+ W[1][0] = si;
+ W[1][1] = si - sys->weight[e2->u.id];
+ W[1][2] = si;
+ W[2][0] = si;
+ W[2][1] = si;
+ W[2][2] = si - sys->weight[e3->u.id];
+
+ vid[0] = vid[1] = vid[2] = vid[3] = vid[4] = vid[5] = -1;
+
+ if (v1->flag & PVERT_INTERIOR) {
+ vid[0] = v1->u.id;
+ vid[3] = ninterior + v1->u.id;
+
+ sys->J2dt[e1->u.id][0] = j2[0][0] = 1.0f * wi1;
+ sys->J2dt[e2->u.id][0] = j2[1][0] = p_abf_compute_sin_product(sys, v1, e2->u.id) * wi2;
+ sys->J2dt[e3->u.id][0] = j2[2][0] = p_abf_compute_sin_product(sys, v1, e3->u.id) * wi3;
+
+ EIG_linear_solver_right_hand_side_add(context, 0, v1->u.id, j2[0][0] * beta[0]);
+ EIG_linear_solver_right_hand_side_add(
+ context, 0, ninterior + v1->u.id, j2[1][0] * beta[1] + j2[2][0] * beta[2]);
+
+ row1[0] = j2[0][0] * W[0][0];
+ row2[0] = j2[0][0] * W[1][0];
+ row3[0] = j2[0][0] * W[2][0];
+
+ row1[3] = j2[1][0] * W[0][1] + j2[2][0] * W[0][2];
+ row2[3] = j2[1][0] * W[1][1] + j2[2][0] * W[1][2];
+ row3[3] = j2[1][0] * W[2][1] + j2[2][0] * W[2][2];
+ }
+
+ if (v2->flag & PVERT_INTERIOR) {
+ vid[1] = v2->u.id;
+ vid[4] = ninterior + v2->u.id;
+
+ sys->J2dt[e1->u.id][1] = j2[0][1] = p_abf_compute_sin_product(sys, v2, e1->u.id) * wi1;
+ sys->J2dt[e2->u.id][1] = j2[1][1] = 1.0f * wi2;
+ sys->J2dt[e3->u.id][1] = j2[2][1] = p_abf_compute_sin_product(sys, v2, e3->u.id) * wi3;
+
+ EIG_linear_solver_right_hand_side_add(context, 0, v2->u.id, j2[1][1] * beta[1]);
+ EIG_linear_solver_right_hand_side_add(
+ context, 0, ninterior + v2->u.id, j2[0][1] * beta[0] + j2[2][1] * beta[2]);
+
+ row1[1] = j2[1][1] * W[0][1];
+ row2[1] = j2[1][1] * W[1][1];
+ row3[1] = j2[1][1] * W[2][1];
+
+ row1[4] = j2[0][1] * W[0][0] + j2[2][1] * W[0][2];
+ row2[4] = j2[0][1] * W[1][0] + j2[2][1] * W[1][2];
+ row3[4] = j2[0][1] * W[2][0] + j2[2][1] * W[2][2];
+ }
+
+ if (v3->flag & PVERT_INTERIOR) {
+ vid[2] = v3->u.id;
+ vid[5] = ninterior + v3->u.id;
+
+ sys->J2dt[e1->u.id][2] = j2[0][2] = p_abf_compute_sin_product(sys, v3, e1->u.id) * wi1;
+ sys->J2dt[e2->u.id][2] = j2[1][2] = p_abf_compute_sin_product(sys, v3, e2->u.id) * wi2;
+ sys->J2dt[e3->u.id][2] = j2[2][2] = 1.0f * wi3;
+
+ EIG_linear_solver_right_hand_side_add(context, 0, v3->u.id, j2[2][2] * beta[2]);
+ EIG_linear_solver_right_hand_side_add(
+ context, 0, ninterior + v3->u.id, j2[0][2] * beta[0] + j2[1][2] * beta[1]);
+
+ row1[2] = j2[2][2] * W[0][2];
+ row2[2] = j2[2][2] * W[1][2];
+ row3[2] = j2[2][2] * W[2][2];
+
+ row1[5] = j2[0][2] * W[0][0] + j2[1][2] * W[0][1];
+ row2[5] = j2[0][2] * W[1][0] + j2[1][2] * W[1][1];
+ row3[5] = j2[0][2] * W[2][0] + j2[1][2] * W[2][1];
+ }
+
+ for (i = 0; i < 3; i++) {
+ int r = vid[i];
+
+ if (r == -1)
+ continue;
+
+ for (j = 0; j < 6; j++) {
+ int c = vid[j];
+
+ if (c == -1)
+ continue;
+
+ if (i == 0)
+ EIG_linear_solver_matrix_add(context, r, c, j2[0][i] * row1[j]);
+ else
+ EIG_linear_solver_matrix_add(context, r + ninterior, c, j2[0][i] * row1[j]);
+
+ if (i == 1)
+ EIG_linear_solver_matrix_add(context, r, c, j2[1][i] * row2[j]);
+ else
+ EIG_linear_solver_matrix_add(context, r + ninterior, c, j2[1][i] * row2[j]);
+
+ if (i == 2)
+ EIG_linear_solver_matrix_add(context, r, c, j2[2][i] * row3[j]);
+ else
+ EIG_linear_solver_matrix_add(context, r + ninterior, c, j2[2][i] * row3[j]);
+ }
+ }
+ }
+
+ success = EIG_linear_solver_solve(context);
+
+ if (success) {
+ for (f = chart->faces; f; f = f->nextlink) {
+ float dlambda1, pre[3], dalpha;
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
+
+ pre[0] = pre[1] = pre[2] = 0.0;
+
+ if (v1->flag & PVERT_INTERIOR) {
+ float x = EIG_linear_solver_variable_get(context, 0, v1->u.id);
+ float x2 = EIG_linear_solver_variable_get(context, 0, ninterior + v1->u.id);
+ pre[0] += sys->J2dt[e1->u.id][0] * x;
+ pre[1] += sys->J2dt[e2->u.id][0] * x2;
+ pre[2] += sys->J2dt[e3->u.id][0] * x2;
+ }
+
+ if (v2->flag & PVERT_INTERIOR) {
+ float x = EIG_linear_solver_variable_get(context, 0, v2->u.id);
+ float x2 = EIG_linear_solver_variable_get(context, 0, ninterior + v2->u.id);
+ pre[0] += sys->J2dt[e1->u.id][1] * x2;
+ pre[1] += sys->J2dt[e2->u.id][1] * x;
+ pre[2] += sys->J2dt[e3->u.id][1] * x2;
+ }
+
+ if (v3->flag & PVERT_INTERIOR) {
+ float x = EIG_linear_solver_variable_get(context, 0, v3->u.id);
+ float x2 = EIG_linear_solver_variable_get(context, 0, ninterior + v3->u.id);
+ pre[0] += sys->J2dt[e1->u.id][2] * x2;
+ pre[1] += sys->J2dt[e2->u.id][2] * x2;
+ pre[2] += sys->J2dt[e3->u.id][2] * x;
+ }
+
+ dlambda1 = pre[0] + pre[1] + pre[2];
+ dlambda1 = sys->dstar[f->u.id] * (sys->bstar[f->u.id] - dlambda1);
+
+ sys->lambdaTriangle[f->u.id] += dlambda1;
+
+ dalpha = (sys->bAlpha[e1->u.id] - dlambda1);
+ sys->alpha[e1->u.id] += dalpha / sys->weight[e1->u.id] - pre[0];
+
+ dalpha = (sys->bAlpha[e2->u.id] - dlambda1);
+ sys->alpha[e2->u.id] += dalpha / sys->weight[e2->u.id] - pre[1];
+
+ dalpha = (sys->bAlpha[e3->u.id] - dlambda1);
+ sys->alpha[e3->u.id] += dalpha / sys->weight[e3->u.id] - pre[2];
+
+ /* clamp */
+ e = f->edge;
+ do {
+ if (sys->alpha[e->u.id] > (float)M_PI)
+ sys->alpha[e->u.id] = (float)M_PI;
+ else if (sys->alpha[e->u.id] < 0.0f)
+ sys->alpha[e->u.id] = 0.0f;
+ } while (e != f->edge);
+ }
+
+ for (i = 0; i < ninterior; i++) {
+ sys->lambdaPlanar[i] += (float)EIG_linear_solver_variable_get(context, 0, i);
+ sys->lambdaLength[i] += (float)EIG_linear_solver_variable_get(context, 0, ninterior + i);
+ }
+ }
+
+ EIG_linear_solver_delete(context);
+
+ return success;
}
static PBool p_chart_abf_solve(PChart *chart)
{
- PVert *v;
- PFace *f;
- PEdge *e, *e1, *e2, *e3;
- PAbfSystem sys;
- int i;
- float /* lastnorm, */ /* UNUSED */ limit = (chart->nfaces > 100) ? 1.0f : 0.001f;
-
- /* setup id's */
- sys.ninterior = sys.nfaces = sys.nangles = 0;
-
- for (v = chart->verts; v; v = v->nextlink) {
- if (p_vert_interior(v)) {
- v->flag |= PVERT_INTERIOR;
- v->u.id = sys.ninterior++;
- }
- else
- v->flag &= ~PVERT_INTERIOR;
- }
-
- for (f = chart->faces; f; f = f->nextlink) {
- e1 = f->edge; e2 = e1->next; e3 = e2->next;
- f->u.id = sys.nfaces++;
-
- /* angle id's are conveniently stored in half edges */
- e1->u.id = sys.nangles++;
- e2->u.id = sys.nangles++;
- e3->u.id = sys.nangles++;
- }
-
- p_abf_setup_system(&sys);
-
- /* compute initial angles */
- for (f = chart->faces; f; f = f->nextlink) {
- float a1, a2, a3;
-
- e1 = f->edge; e2 = e1->next; e3 = e2->next;
- p_face_angles(f, &a1, &a2, &a3);
-
- if (a1 < sys.minangle)
- a1 = sys.minangle;
- else if (a1 > sys.maxangle)
- a1 = sys.maxangle;
- if (a2 < sys.minangle)
- a2 = sys.minangle;
- else if (a2 > sys.maxangle)
- a2 = sys.maxangle;
- if (a3 < sys.minangle)
- a3 = sys.minangle;
- else if (a3 > sys.maxangle)
- a3 = sys.maxangle;
-
- sys.alpha[e1->u.id] = sys.beta[e1->u.id] = a1;
- sys.alpha[e2->u.id] = sys.beta[e2->u.id] = a2;
- sys.alpha[e3->u.id] = sys.beta[e3->u.id] = a3;
-
- sys.weight[e1->u.id] = 2.0f / (a1 * a1);
- sys.weight[e2->u.id] = 2.0f / (a2 * a2);
- sys.weight[e3->u.id] = 2.0f / (a3 * a3);
- }
-
- for (v = chart->verts; v; v = v->nextlink) {
- if (v->flag & PVERT_INTERIOR) {
- float anglesum = 0.0, scale;
-
- e = v->edge;
- do {
- anglesum += sys.beta[e->u.id];
- e = e->next->next->pair;
- } while (e && (e != v->edge));
-
- scale = (anglesum == 0.0f) ? 0.0f : 2.0f * (float)M_PI / anglesum;
-
- e = v->edge;
- do {
- sys.beta[e->u.id] = sys.alpha[e->u.id] = sys.beta[e->u.id] * scale;
- e = e->next->next->pair;
- } while (e && (e != v->edge));
- }
- }
-
- if (sys.ninterior > 0) {
- p_abf_compute_sines(&sys);
-
- /* iteration */
- /* lastnorm = 1e10; */ /* UNUSED */
-
- for (i = 0; i < ABF_MAX_ITER; i++) {
- float norm = p_abf_compute_gradient(&sys, chart);
-
- /* lastnorm = norm; */ /* UNUSED */
-
- if (norm < limit)
- break;
-
- if (!p_abf_matrix_invert(&sys, chart)) {
- param_warning("ABF failed to invert matrix");
- p_abf_free_system(&sys);
- return P_FALSE;
- }
-
- p_abf_compute_sines(&sys);
- }
-
- if (i == ABF_MAX_ITER) {
- param_warning("ABF maximum iterations reached");
- p_abf_free_system(&sys);
- return P_FALSE;
- }
- }
-
- chart->u.lscm.abf_alpha = MEM_dupallocN(sys.alpha);
- p_abf_free_system(&sys);
-
- return P_TRUE;
+ PVert *v;
+ PFace *f;
+ PEdge *e, *e1, *e2, *e3;
+ PAbfSystem sys;
+ int i;
+ float /* lastnorm, */ /* UNUSED */ limit = (chart->nfaces > 100) ? 1.0f : 0.001f;
+
+ /* setup id's */
+ sys.ninterior = sys.nfaces = sys.nangles = 0;
+
+ for (v = chart->verts; v; v = v->nextlink) {
+ if (p_vert_interior(v)) {
+ v->flag |= PVERT_INTERIOR;
+ v->u.id = sys.ninterior++;
+ }
+ else
+ v->flag &= ~PVERT_INTERIOR;
+ }
+
+ for (f = chart->faces; f; f = f->nextlink) {
+ e1 = f->edge;
+ e2 = e1->next;
+ e3 = e2->next;
+ f->u.id = sys.nfaces++;
+
+ /* angle id's are conveniently stored in half edges */
+ e1->u.id = sys.nangles++;
+ e2->u.id = sys.nangles++;
+ e3->u.id = sys.nangles++;
+ }
+
+ p_abf_setup_system(&sys);
+
+ /* compute initial angles */
+ for (f = chart->faces; f; f = f->nextlink) {
+ float a1, a2, a3;
+
+ e1 = f->edge;
+ e2 = e1->next;
+ e3 = e2->next;
+ p_face_angles(f, &a1, &a2, &a3);
+
+ if (a1 < sys.minangle)
+ a1 = sys.minangle;
+ else if (a1 > sys.maxangle)
+ a1 = sys.maxangle;
+ if (a2 < sys.minangle)
+ a2 = sys.minangle;
+ else if (a2 > sys.maxangle)
+ a2 = sys.maxangle;
+ if (a3 < sys.minangle)
+ a3 = sys.minangle;
+ else if (a3 > sys.maxangle)
+ a3 = sys.maxangle;
+
+ sys.alpha[e1->u.id] = sys.beta[e1->u.id] = a1;
+ sys.alpha[e2->u.id] = sys.beta[e2->u.id] = a2;
+ sys.alpha[e3->u.id] = sys.beta[e3->u.id] = a3;
+
+ sys.weight[e1->u.id] = 2.0f / (a1 * a1);
+ sys.weight[e2->u.id] = 2.0f / (a2 * a2);
+ sys.weight[e3->u.id] = 2.0f / (a3 * a3);
+ }
+
+ for (v = chart->verts; v; v = v->nextlink) {
+ if (v->flag & PVERT_INTERIOR) {
+ float anglesum = 0.0, scale;
+
+ e = v->edge;
+ do {
+ anglesum += sys.beta[e->u.id];
+ e = e->next->next->pair;
+ } while (e && (e != v->edge));
+
+ scale = (anglesum == 0.0f) ? 0.0f : 2.0f * (float)M_PI / anglesum;
+
+ e = v->edge;
+ do {
+ sys.beta[e->u.id] = sys.alpha[e->u.id] = sys.beta[e->u.id] * scale;
+ e = e->next->next->pair;
+ } while (e && (e != v->edge));
+ }
+ }
+
+ if (sys.ninterior > 0) {
+ p_abf_compute_sines(&sys);
+
+ /* iteration */
+ /* lastnorm = 1e10; */ /* UNUSED */
+
+ for (i = 0; i < ABF_MAX_ITER; i++) {
+ float norm = p_abf_compute_gradient(&sys, chart);
+
+ /* lastnorm = norm; */ /* UNUSED */
+
+ if (norm < limit)
+ break;
+
+ if (!p_abf_matrix_invert(&sys, chart)) {
+ param_warning("ABF failed to invert matrix");
+ p_abf_free_system(&sys);
+ return P_FALSE;
+ }
+
+ p_abf_compute_sines(&sys);
+ }
+
+ if (i == ABF_MAX_ITER) {
+ param_warning("ABF maximum iterations reached");
+ p_abf_free_system(&sys);
+ return P_FALSE;
+ }
+ }
+
+ chart->u.lscm.abf_alpha = MEM_dupallocN(sys.alpha);
+ p_abf_free_system(&sys);
+
+ return P_TRUE;
}
/* Least Squares Conformal Maps */
static void p_chart_pin_positions(PChart *chart, PVert **pin1, PVert **pin2)
{
- if (!*pin1 || !*pin2 || *pin1 == *pin2) {
- /* degenerate case */
- PFace *f = chart->faces;
- *pin1 = f->edge->vert;
- *pin2 = f->edge->next->vert;
-
- (*pin1)->uv[0] = 0.0f;
- (*pin1)->uv[1] = 0.5f;
- (*pin2)->uv[0] = 1.0f;
- (*pin2)->uv[1] = 0.5f;
- }
- else {
- int diru, dirv, dirx, diry;
- float sub[3];
-
- sub_v3_v3v3(sub, (*pin1)->co, (*pin2)->co);
- sub[0] = fabsf(sub[0]);
- sub[1] = fabsf(sub[1]);
- sub[2] = fabsf(sub[2]);
-
- if ((sub[0] > sub[1]) && (sub[0] > sub[2])) {
- dirx = 0;
- diry = (sub[1] > sub[2]) ? 1 : 2;
- }
- else if ((sub[1] > sub[0]) && (sub[1] > sub[2])) {
- dirx = 1;
- diry = (sub[0] > sub[2]) ? 0 : 2;
- }
- else {
- dirx = 2;
- diry = (sub[0] > sub[1]) ? 0 : 1;
- }
-
- if (dirx == 2) {
- diru = 1;
- dirv = 0;
- }
- else {
- diru = 0;
- dirv = 1;
- }
-
- (*pin1)->uv[diru] = (*pin1)->co[dirx];
- (*pin1)->uv[dirv] = (*pin1)->co[diry];
- (*pin2)->uv[diru] = (*pin2)->co[dirx];
- (*pin2)->uv[dirv] = (*pin2)->co[diry];
- }
+ if (!*pin1 || !*pin2 || *pin1 == *pin2) {
+ /* degenerate case */
+ PFace *f = chart->faces;
+ *pin1 = f->edge->vert;
+ *pin2 = f->edge->next->vert;
+
+ (*pin1)->uv[0] = 0.0f;
+ (*pin1)->uv[1] = 0.5f;
+ (*pin2)->uv[0] = 1.0f;
+ (*pin2)->uv[1] = 0.5f;
+ }
+ else {
+ int diru, dirv, dirx, diry;
+ float sub[3];
+
+ sub_v3_v3v3(sub, (*pin1)->co, (*pin2)->co);
+ sub[0] = fabsf(sub[0]);
+ sub[1] = fabsf(sub[1]);
+ sub[2] = fabsf(sub[2]);
+
+ if ((sub[0] > sub[1]) && (sub[0] > sub[2])) {
+ dirx = 0;
+ diry = (sub[1] > sub[2]) ? 1 : 2;
+ }
+ else if ((sub[1] > sub[0]) && (sub[1] > sub[2])) {
+ dirx = 1;
+ diry = (sub[0] > sub[2]) ? 0 : 2;
+ }
+ else {
+ dirx = 2;
+ diry = (sub[0] > sub[1]) ? 0 : 1;
+ }
+
+ if (dirx == 2) {
+ diru = 1;
+ dirv = 0;
+ }
+ else {
+ diru = 0;
+ dirv = 1;
+ }
+
+ (*pin1)->uv[diru] = (*pin1)->co[dirx];
+ (*pin1)->uv[dirv] = (*pin1)->co[diry];
+ (*pin2)->uv[diru] = (*pin2)->co[dirx];
+ (*pin2)->uv[dirv] = (*pin2)->co[diry];
+ }
}
static PBool p_chart_symmetry_pins(PChart *chart, PEdge *outer, PVert **pin1, PVert **pin2)
{
- PEdge *be, *lastbe = NULL, *maxe1 = NULL, *maxe2 = NULL, *be1, *be2;
- PEdge *cure = NULL, *firste1 = NULL, *firste2 = NULL, *nextbe;
- float maxlen = 0.0f, curlen = 0.0f, totlen = 0.0f, firstlen = 0.0f;
- float len1, len2;
-
- /* find longest series of verts split in the chart itself, these are
- * marked during construction */
- be = outer;
- lastbe = p_boundary_edge_prev(be);
- do {
- float len = p_edge_length(be);
- totlen += len;
-
- nextbe = p_boundary_edge_next(be);
-
- if ((be->vert->flag & PVERT_SPLIT) ||
- (lastbe->vert->flag & nextbe->vert->flag & PVERT_SPLIT))
- {
- if (!cure) {
- if (be == outer)
- firste1 = be;
- cure = be;
- }
- else
- curlen += p_edge_length(lastbe);
- }
- else if (cure) {
- if (curlen > maxlen) {
- maxlen = curlen;
- maxe1 = cure;
- maxe2 = lastbe;
- }
-
- if (firste1 == cure) {
- firstlen = curlen;
- firste2 = lastbe;
- }
-
- curlen = 0.0f;
- cure = NULL;
- }
-
- lastbe = be;
- be = nextbe;
- } while (be != outer);
-
- /* make sure we also count a series of splits over the starting point */
- if (cure && (cure != outer)) {
- firstlen += curlen + p_edge_length(be);
-
- if (firstlen > maxlen) {
- maxlen = firstlen;
- maxe1 = cure;
- maxe2 = firste2;
- }
- }
-
- if (!maxe1 || !maxe2 || (maxlen < 0.5f * totlen))
- return P_FALSE;
-
- /* find pin1 in the split vertices */
- be1 = maxe1;
- be2 = maxe2;
- len1 = 0.0f;
- len2 = 0.0f;
-
- do {
- if (len1 < len2) {
- len1 += p_edge_length(be1);
- be1 = p_boundary_edge_next(be1);
- }
- else {
- be2 = p_boundary_edge_prev(be2);
- len2 += p_edge_length(be2);
- }
- } while (be1 != be2);
-
- *pin1 = be1->vert;
-
- /* find pin2 outside the split vertices */
- be1 = maxe1;
- be2 = maxe2;
- len1 = 0.0f;
- len2 = 0.0f;
-
- do {
- if (len1 < len2) {
- be1 = p_boundary_edge_prev(be1);
- len1 += p_edge_length(be1);
- }
- else {
- len2 += p_edge_length(be2);
- be2 = p_boundary_edge_next(be2);
- }
- } while (be1 != be2);
-
- *pin2 = be1->vert;
-
- p_chart_pin_positions(chart, pin1, pin2);
-
- return !equals_v3v3((*pin1)->co, (*pin2)->co);
+ PEdge *be, *lastbe = NULL, *maxe1 = NULL, *maxe2 = NULL, *be1, *be2;
+ PEdge *cure = NULL, *firste1 = NULL, *firste2 = NULL, *nextbe;
+ float maxlen = 0.0f, curlen = 0.0f, totlen = 0.0f, firstlen = 0.0f;
+ float len1, len2;
+
+ /* find longest series of verts split in the chart itself, these are
+ * marked during construction */
+ be = outer;
+ lastbe = p_boundary_edge_prev(be);
+ do {
+ float len = p_edge_length(be);
+ totlen += len;
+
+ nextbe = p_boundary_edge_next(be);
+
+ if ((be->vert->flag & PVERT_SPLIT) ||
+ (lastbe->vert->flag & nextbe->vert->flag & PVERT_SPLIT)) {
+ if (!cure) {
+ if (be == outer)
+ firste1 = be;
+ cure = be;
+ }
+ else
+ curlen += p_edge_length(lastbe);
+ }
+ else if (cure) {
+ if (curlen > maxlen) {
+ maxlen = curlen;
+ maxe1 = cure;
+ maxe2 = lastbe;
+ }
+
+ if (firste1 == cure) {
+ firstlen = curlen;
+ firste2 = lastbe;
+ }
+
+ curlen = 0.0f;
+ cure = NULL;
+ }
+
+ lastbe = be;
+ be = nextbe;
+ } while (be != outer);
+
+ /* make sure we also count a series of splits over the starting point */
+ if (cure && (cure != outer)) {
+ firstlen += curlen + p_edge_length(be);
+
+ if (firstlen > maxlen) {
+ maxlen = firstlen;
+ maxe1 = cure;
+ maxe2 = firste2;
+ }
+ }
+
+ if (!maxe1 || !maxe2 || (maxlen < 0.5f * totlen))
+ return P_FALSE;
+
+ /* find pin1 in the split vertices */
+ be1 = maxe1;
+ be2 = maxe2;
+ len1 = 0.0f;
+ len2 = 0.0f;
+
+ do {
+ if (len1 < len2) {
+ len1 += p_edge_length(be1);
+ be1 = p_boundary_edge_next(be1);
+ }
+ else {
+ be2 = p_boundary_edge_prev(be2);
+ len2 += p_edge_length(be2);
+ }
+ } while (be1 != be2);
+
+ *pin1 = be1->vert;
+
+ /* find pin2 outside the split vertices */
+ be1 = maxe1;
+ be2 = maxe2;
+ len1 = 0.0f;
+ len2 = 0.0f;
+
+ do {
+ if (len1 < len2) {
+ be1 = p_boundary_edge_prev(be1);
+ len1 += p_edge_length(be1);
+ }
+ else {
+ len2 += p_edge_length(be2);
+ be2 = p_boundary_edge_next(be2);
+ }
+ } while (be1 != be2);
+
+ *pin2 = be1->vert;
+
+ p_chart_pin_positions(chart, pin1, pin2);
+
+ return !equals_v3v3((*pin1)->co, (*pin2)->co);
}
static void p_chart_extrema_verts(PChart *chart, PVert **pin1, PVert **pin2)
{
- float minv[3], maxv[3], dirlen;
- PVert *v, *minvert[3], *maxvert[3];
- int i, dir;
+ float minv[3], maxv[3], dirlen;
+ PVert *v, *minvert[3], *maxvert[3];
+ int i, dir;
- /* find minimum and maximum verts over x/y/z axes */
- minv[0] = minv[1] = minv[2] = 1e20;
- maxv[0] = maxv[1] = maxv[2] = -1e20;
+ /* find minimum and maximum verts over x/y/z axes */
+ minv[0] = minv[1] = minv[2] = 1e20;
+ maxv[0] = maxv[1] = maxv[2] = -1e20;
- minvert[0] = minvert[1] = minvert[2] = NULL;
- maxvert[0] = maxvert[1] = maxvert[2] = NULL;
+ minvert[0] = minvert[1] = minvert[2] = NULL;
+ maxvert[0] = maxvert[1] = maxvert[2] = NULL;
- for (v = chart->verts; v; v = v->nextlink) {
- for (i = 0; i < 3; i++) {
- if (v->co[i] < minv[i]) {
- minv[i] = v->co[i];
- minvert[i] = v;
- }
- if (v->co[i] > maxv[i]) {
- maxv[i] = v->co[i];
- maxvert[i] = v;
- }
- }
- }
+ for (v = chart->verts; v; v = v->nextlink) {
+ for (i = 0; i < 3; i++) {
+ if (v->co[i] < minv[i]) {
+ minv[i] = v->co[i];
+ minvert[i] = v;
+ }
+ if (v->co[i] > maxv[i]) {
+ maxv[i] = v->co[i];
+ maxvert[i] = v;
+ }
+ }
+ }
- /* find axes with longest distance */
- dir = 0;
- dirlen = -1.0;
+ /* find axes with longest distance */
+ dir = 0;
+ dirlen = -1.0;
- for (i = 0; i < 3; i++) {
- if (maxv[i] - minv[i] > dirlen) {
- dir = i;
- dirlen = maxv[i] - minv[i];
- }
- }
+ for (i = 0; i < 3; i++) {
+ if (maxv[i] - minv[i] > dirlen) {
+ dir = i;
+ dirlen = maxv[i] - minv[i];
+ }
+ }
- *pin1 = minvert[dir];
- *pin2 = maxvert[dir];
+ *pin1 = minvert[dir];
+ *pin2 = maxvert[dir];
- p_chart_pin_positions(chart, pin1, pin2);
+ p_chart_pin_positions(chart, pin1, pin2);
}
static void p_chart_lscm_load_solution(PChart *chart)
{
- LinearSolver *context = chart->u.lscm.context;
- PVert *v;
+ LinearSolver *context = chart->u.lscm.context;
+ PVert *v;
- for (v = chart->verts; v; v = v->nextlink) {
- v->uv[0] = EIG_linear_solver_variable_get(context, 0, 2 * v->u.id);
- v->uv[1] = EIG_linear_solver_variable_get(context, 0, 2 * v->u.id + 1);
- }
+ for (v = chart->verts; v; v = v->nextlink) {
+ v->uv[0] = EIG_linear_solver_variable_get(context, 0, 2 * v->u.id);
+ v->uv[1] = EIG_linear_solver_variable_get(context, 0, 2 * v->u.id + 1);
+ }
}
static void p_chart_lscm_begin(PChart *chart, PBool live, PBool abf)
{
- PVert *v, *pin1, *pin2;
- PBool select = P_FALSE, deselect = P_FALSE;
- int npins = 0, id = 0;
-
- /* give vertices matrix indices and count pins */
- for (v = chart->verts; v; v = v->nextlink) {
- if (v->flag & PVERT_PIN) {
- npins++;
- if (v->flag & PVERT_SELECT)
- select = P_TRUE;
- }
-
- if (!(v->flag & PVERT_SELECT))
- deselect = P_TRUE;
- }
-
- if ((live && (!select || !deselect)) || (npins == 1)) {
- chart->u.lscm.context = NULL;
- }
- else {
+ PVert *v, *pin1, *pin2;
+ PBool select = P_FALSE, deselect = P_FALSE;
+ int npins = 0, id = 0;
+
+ /* give vertices matrix indices and count pins */
+ for (v = chart->verts; v; v = v->nextlink) {
+ if (v->flag & PVERT_PIN) {
+ npins++;
+ if (v->flag & PVERT_SELECT)
+ select = P_TRUE;
+ }
+
+ if (!(v->flag & PVERT_SELECT))
+ deselect = P_TRUE;
+ }
+
+ if ((live && (!select || !deselect)) || (npins == 1)) {
+ chart->u.lscm.context = NULL;
+ }
+ else {
#if 0
- p_chart_simplify_compute(chart);
- p_chart_topological_sanity_check(chart);
+ p_chart_simplify_compute(chart);
+ p_chart_topological_sanity_check(chart);
#endif
- if (abf) {
- if (!p_chart_abf_solve(chart))
- param_warning("ABF solving failed: falling back to LSCM.\n");
- }
+ if (abf) {
+ if (!p_chart_abf_solve(chart))
+ param_warning("ABF solving failed: falling back to LSCM.\n");
+ }
- if (npins <= 1) {
- /* not enough pins, lets find some ourself */
- PEdge *outer;
+ if (npins <= 1) {
+ /* not enough pins, lets find some ourself */
+ PEdge *outer;
- p_chart_boundaries(chart, NULL, &outer);
+ p_chart_boundaries(chart, NULL, &outer);
- /* outer can be NULL with non-finite coords. */
- if (!(outer && p_chart_symmetry_pins(chart, outer, &pin1, &pin2))) {
- p_chart_extrema_verts(chart, &pin1, &pin2);
- }
+ /* outer can be NULL with non-finite coords. */
+ if (!(outer && p_chart_symmetry_pins(chart, outer, &pin1, &pin2))) {
+ p_chart_extrema_verts(chart, &pin1, &pin2);
+ }
- chart->u.lscm.pin1 = pin1;
- chart->u.lscm.pin2 = pin2;
- }
+ chart->u.lscm.pin1 = pin1;
+ chart->u.lscm.pin2 = pin2;
+ }
- for (v = chart->verts; v; v = v->nextlink)
- v->u.id = id++;
+ for (v = chart->verts; v; v = v->nextlink)
+ v->u.id = id++;
- chart->u.lscm.context = EIG_linear_least_squares_solver_new(2 * chart->nfaces, 2 * chart->nverts, 1);
- }
+ chart->u.lscm.context = EIG_linear_least_squares_solver_new(
+ 2 * chart->nfaces, 2 * chart->nverts, 1);
+ }
}
static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
{
- LinearSolver *context = chart->u.lscm.context;
- PVert *v, *pin1 = chart->u.lscm.pin1, *pin2 = chart->u.lscm.pin2;
- PFace *f;
- float *alpha = chart->u.lscm.abf_alpha;
- float area_pinned_up, area_pinned_down;
- bool flip_faces;
- int row;
+ LinearSolver *context = chart->u.lscm.context;
+ PVert *v, *pin1 = chart->u.lscm.pin1, *pin2 = chart->u.lscm.pin2;
+ PFace *f;
+ float *alpha = chart->u.lscm.abf_alpha;
+ float area_pinned_up, area_pinned_down;
+ bool flip_faces;
+ int row;
#if 0
- /* TODO: make loading pins work for simplify/complexify. */
+ /* TODO: make loading pins work for simplify/complexify. */
#endif
- for (v = chart->verts; v; v = v->nextlink)
- if (v->flag & PVERT_PIN)
- p_vert_load_pin_select_uvs(handle, v); /* reload for live */
-
- if (chart->u.lscm.pin1) {
- EIG_linear_solver_variable_lock(context, 2 * pin1->u.id);
- EIG_linear_solver_variable_lock(context, 2 * pin1->u.id + 1);
- EIG_linear_solver_variable_lock(context, 2 * pin2->u.id);
- EIG_linear_solver_variable_lock(context, 2 * pin2->u.id + 1);
-
- EIG_linear_solver_variable_set(context, 0, 2 * pin1->u.id, pin1->uv[0]);
- EIG_linear_solver_variable_set(context, 0, 2 * pin1->u.id + 1, pin1->uv[1]);
- EIG_linear_solver_variable_set(context, 0, 2 * pin2->u.id, pin2->uv[0]);
- EIG_linear_solver_variable_set(context, 0, 2 * pin2->u.id + 1, pin2->uv[1]);
- }
- else {
- /* set and lock the pins */
- for (v = chart->verts; v; v = v->nextlink) {
- if (v->flag & PVERT_PIN) {
- EIG_linear_solver_variable_lock(context, 2 * v->u.id);
- EIG_linear_solver_variable_lock(context, 2 * v->u.id + 1);
-
- EIG_linear_solver_variable_set(context, 0, 2 * v->u.id, v->uv[0]);
- EIG_linear_solver_variable_set(context, 0, 2 * v->u.id + 1, v->uv[1]);
- }
- }
- }
-
- /* detect up direction based on pinned vertices */
- area_pinned_up = 0.0f;
- area_pinned_down = 0.0f;
-
- for (f = chart->faces; f; f = f->nextlink) {
- PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
- PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
-
- if ((v1->flag & PVERT_PIN) && (v2->flag & PVERT_PIN) && (v3->flag & PVERT_PIN)) {
- float area = p_face_uv_area_signed(f);
-
- if (area > 0.0f)
- area_pinned_up += area;
- else
- area_pinned_down -= area;
- }
- }
-
- flip_faces = (area_pinned_down > area_pinned_up);
-
- /* construct matrix */
-
- row = 0;
- for (f = chart->faces; f; f = f->nextlink) {
- PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
- PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
- float a1, a2, a3, ratio, cosine, sine;
- float sina1, sina2, sina3, sinmax;
-
- if (alpha) {
- /* use abf angles if passed on */
- a1 = *(alpha++);
- a2 = *(alpha++);
- a3 = *(alpha++);
- }
- else
- p_face_angles(f, &a1, &a2, &a3);
-
- if (flip_faces) {
- SWAP(float, a2, a3);
- SWAP(PEdge *, e2, e3);
- SWAP(PVert *, v2, v3);
- }
-
- sina1 = sinf(a1);
- sina2 = sinf(a2);
- sina3 = sinf(a3);
-
- sinmax = max_fff(sina1, sina2, sina3);
-
- /* shift vertices to find most stable order */
- if (sina3 != sinmax) {
- SHIFT3(PVert *, v1, v2, v3);
- SHIFT3(float, a1, a2, a3);
- SHIFT3(float, sina1, sina2, sina3);
-
- if (sina2 == sinmax) {
- SHIFT3(PVert *, v1, v2, v3);
- SHIFT3(float, a1, a2, a3);
- SHIFT3(float, sina1, sina2, sina3);
- }
- }
-
- /* angle based lscm formulation */
- ratio = (sina3 == 0.0f) ? 1.0f : sina2 / sina3;
- cosine = cosf(a1) * ratio;
- sine = sina1 * ratio;
-
- EIG_linear_solver_matrix_add(context, row, 2 * v1->u.id, cosine - 1.0f);
- EIG_linear_solver_matrix_add(context, row, 2 * v1->u.id + 1, -sine);
- EIG_linear_solver_matrix_add(context, row, 2 * v2->u.id, -cosine);
- EIG_linear_solver_matrix_add(context, row, 2 * v2->u.id + 1, sine);
- EIG_linear_solver_matrix_add(context, row, 2 * v3->u.id, 1.0);
- row++;
-
- EIG_linear_solver_matrix_add(context, row, 2 * v1->u.id, sine);
- EIG_linear_solver_matrix_add(context, row, 2 * v1->u.id + 1, cosine - 1.0f);
- EIG_linear_solver_matrix_add(context, row, 2 * v2->u.id, -sine);
- EIG_linear_solver_matrix_add(context, row, 2 * v2->u.id + 1, -cosine);
- EIG_linear_solver_matrix_add(context, row, 2 * v3->u.id + 1, 1.0);
- row++;
- }
-
- if (EIG_linear_solver_solve(context)) {
- p_chart_lscm_load_solution(chart);
- return P_TRUE;
- }
- else {
- for (v = chart->verts; v; v = v->nextlink) {
- v->uv[0] = 0.0f;
- v->uv[1] = 0.0f;
- }
- }
-
- return P_FALSE;
+ for (v = chart->verts; v; v = v->nextlink)
+ if (v->flag & PVERT_PIN)
+ p_vert_load_pin_select_uvs(handle, v); /* reload for live */
+
+ if (chart->u.lscm.pin1) {
+ EIG_linear_solver_variable_lock(context, 2 * pin1->u.id);
+ EIG_linear_solver_variable_lock(context, 2 * pin1->u.id + 1);
+ EIG_linear_solver_variable_lock(context, 2 * pin2->u.id);
+ EIG_linear_solver_variable_lock(context, 2 * pin2->u.id + 1);
+
+ EIG_linear_solver_variable_set(context, 0, 2 * pin1->u.id, pin1->uv[0]);
+ EIG_linear_solver_variable_set(context, 0, 2 * pin1->u.id + 1, pin1->uv[1]);
+ EIG_linear_solver_variable_set(context, 0, 2 * pin2->u.id, pin2->uv[0]);
+ EIG_linear_solver_variable_set(context, 0, 2 * pin2->u.id + 1, pin2->uv[1]);
+ }
+ else {
+ /* set and lock the pins */
+ for (v = chart->verts; v; v = v->nextlink) {
+ if (v->flag & PVERT_PIN) {
+ EIG_linear_solver_variable_lock(context, 2 * v->u.id);
+ EIG_linear_solver_variable_lock(context, 2 * v->u.id + 1);
+
+ EIG_linear_solver_variable_set(context, 0, 2 * v->u.id, v->uv[0]);
+ EIG_linear_solver_variable_set(context, 0, 2 * v->u.id + 1, v->uv[1]);
+ }
+ }
+ }
+
+ /* detect up direction based on pinned vertices */
+ area_pinned_up = 0.0f;
+ area_pinned_down = 0.0f;
+
+ for (f = chart->faces; f; f = f->nextlink) {
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
+
+ if ((v1->flag & PVERT_PIN) && (v2->flag & PVERT_PIN) && (v3->flag & PVERT_PIN)) {
+ float area = p_face_uv_area_signed(f);
+
+ if (area > 0.0f)
+ area_pinned_up += area;
+ else
+ area_pinned_down -= area;
+ }
+ }
+
+ flip_faces = (area_pinned_down > area_pinned_up);
+
+ /* construct matrix */
+
+ row = 0;
+ for (f = chart->faces; f; f = f->nextlink) {
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
+ float a1, a2, a3, ratio, cosine, sine;
+ float sina1, sina2, sina3, sinmax;
+
+ if (alpha) {
+ /* use abf angles if passed on */
+ a1 = *(alpha++);
+ a2 = *(alpha++);
+ a3 = *(alpha++);
+ }
+ else
+ p_face_angles(f, &a1, &a2, &a3);
+
+ if (flip_faces) {
+ SWAP(float, a2, a3);
+ SWAP(PEdge *, e2, e3);
+ SWAP(PVert *, v2, v3);
+ }
+
+ sina1 = sinf(a1);
+ sina2 = sinf(a2);
+ sina3 = sinf(a3);
+
+ sinmax = max_fff(sina1, sina2, sina3);
+
+ /* shift vertices to find most stable order */
+ if (sina3 != sinmax) {
+ SHIFT3(PVert *, v1, v2, v3);
+ SHIFT3(float, a1, a2, a3);
+ SHIFT3(float, sina1, sina2, sina3);
+
+ if (sina2 == sinmax) {
+ SHIFT3(PVert *, v1, v2, v3);
+ SHIFT3(float, a1, a2, a3);
+ SHIFT3(float, sina1, sina2, sina3);
+ }
+ }
+
+ /* angle based lscm formulation */
+ ratio = (sina3 == 0.0f) ? 1.0f : sina2 / sina3;
+ cosine = cosf(a1) * ratio;
+ sine = sina1 * ratio;
+
+ EIG_linear_solver_matrix_add(context, row, 2 * v1->u.id, cosine - 1.0f);
+ EIG_linear_solver_matrix_add(context, row, 2 * v1->u.id + 1, -sine);
+ EIG_linear_solver_matrix_add(context, row, 2 * v2->u.id, -cosine);
+ EIG_linear_solver_matrix_add(context, row, 2 * v2->u.id + 1, sine);
+ EIG_linear_solver_matrix_add(context, row, 2 * v3->u.id, 1.0);
+ row++;
+
+ EIG_linear_solver_matrix_add(context, row, 2 * v1->u.id, sine);
+ EIG_linear_solver_matrix_add(context, row, 2 * v1->u.id + 1, cosine - 1.0f);
+ EIG_linear_solver_matrix_add(context, row, 2 * v2->u.id, -sine);
+ EIG_linear_solver_matrix_add(context, row, 2 * v2->u.id + 1, -cosine);
+ EIG_linear_solver_matrix_add(context, row, 2 * v3->u.id + 1, 1.0);
+ row++;
+ }
+
+ if (EIG_linear_solver_solve(context)) {
+ p_chart_lscm_load_solution(chart);
+ return P_TRUE;
+ }
+ else {
+ for (v = chart->verts; v; v = v->nextlink) {
+ v->uv[0] = 0.0f;
+ v->uv[1] = 0.0f;
+ }
+ }
+
+ return P_FALSE;
}
static void p_chart_lscm_end(PChart *chart)
{
- if (chart->u.lscm.context)
- EIG_linear_solver_delete(chart->u.lscm.context);
+ if (chart->u.lscm.context)
+ EIG_linear_solver_delete(chart->u.lscm.context);
- if (chart->u.lscm.abf_alpha) {
- MEM_freeN(chart->u.lscm.abf_alpha);
- chart->u.lscm.abf_alpha = NULL;
- }
+ if (chart->u.lscm.abf_alpha) {
+ MEM_freeN(chart->u.lscm.abf_alpha);
+ chart->u.lscm.abf_alpha = NULL;
+ }
- chart->u.lscm.context = NULL;
- chart->u.lscm.pin1 = NULL;
- chart->u.lscm.pin2 = NULL;
+ chart->u.lscm.context = NULL;
+ chart->u.lscm.pin1 = NULL;
+ chart->u.lscm.pin2 = NULL;
}
/* Stretch */
@@ -3227,386 +3255,386 @@ static void p_chart_lscm_end(PChart *chart)
static void p_stretch_pin_boundary(PChart *chart)
{
- PVert *v;
+ PVert *v;
- for (v = chart->verts; v; v = v->nextlink)
- if (v->edge->pair == NULL)
- v->flag |= PVERT_PIN;
- else
- v->flag &= ~PVERT_PIN;
+ for (v = chart->verts; v; v = v->nextlink)
+ if (v->edge->pair == NULL)
+ v->flag |= PVERT_PIN;
+ else
+ v->flag &= ~PVERT_PIN;
}
static float p_face_stretch(PFace *f)
{
- float T, w, tmp[3];
- float Ps[3], Pt[3];
- float a, c, area;
- PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
- PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
+ float T, w, tmp[3];
+ float Ps[3], Pt[3];
+ float a, c, area;
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
- area = p_face_uv_area_signed(f);
+ area = p_face_uv_area_signed(f);
- if (area <= 0.0f) /* flipped face -> infinite stretch */
- return 1e10f;
+ if (area <= 0.0f) /* flipped face -> infinite stretch */
+ return 1e10f;
- w = 1.0f / (2.0f * area);
+ w = 1.0f / (2.0f * area);
- /* compute derivatives */
- copy_v3_v3(Ps, v1->co);
- mul_v3_fl(Ps, (v2->uv[1] - v3->uv[1]));
+ /* compute derivatives */
+ copy_v3_v3(Ps, v1->co);
+ mul_v3_fl(Ps, (v2->uv[1] - v3->uv[1]));
- copy_v3_v3(tmp, v2->co);
- mul_v3_fl(tmp, (v3->uv[1] - v1->uv[1]));
- add_v3_v3(Ps, tmp);
+ copy_v3_v3(tmp, v2->co);
+ mul_v3_fl(tmp, (v3->uv[1] - v1->uv[1]));
+ add_v3_v3(Ps, tmp);
- copy_v3_v3(tmp, v3->co);
- mul_v3_fl(tmp, (v1->uv[1] - v2->uv[1]));
- add_v3_v3(Ps, tmp);
+ copy_v3_v3(tmp, v3->co);
+ mul_v3_fl(tmp, (v1->uv[1] - v2->uv[1]));
+ add_v3_v3(Ps, tmp);
- mul_v3_fl(Ps, w);
+ mul_v3_fl(Ps, w);
- copy_v3_v3(Pt, v1->co);
- mul_v3_fl(Pt, (v3->uv[0] - v2->uv[0]));
+ copy_v3_v3(Pt, v1->co);
+ mul_v3_fl(Pt, (v3->uv[0] - v2->uv[0]));
- copy_v3_v3(tmp, v2->co);
- mul_v3_fl(tmp, (v1->uv[0] - v3->uv[0]));
- add_v3_v3(Pt, tmp);
+ copy_v3_v3(tmp, v2->co);
+ mul_v3_fl(tmp, (v1->uv[0] - v3->uv[0]));
+ add_v3_v3(Pt, tmp);
- copy_v3_v3(tmp, v3->co);
- mul_v3_fl(tmp, (v2->uv[0] - v1->uv[0]));
- add_v3_v3(Pt, tmp);
+ copy_v3_v3(tmp, v3->co);
+ mul_v3_fl(tmp, (v2->uv[0] - v1->uv[0]));
+ add_v3_v3(Pt, tmp);
- mul_v3_fl(Pt, w);
+ mul_v3_fl(Pt, w);
- /* Sander Tensor */
- a = dot_v3v3(Ps, Ps);
- c = dot_v3v3(Pt, Pt);
+ /* Sander Tensor */
+ a = dot_v3v3(Ps, Ps);
+ c = dot_v3v3(Pt, Pt);
- T = sqrtf(0.5f * (a + c));
- if (f->flag & PFACE_FILLED)
- T *= 0.2f;
+ T = sqrtf(0.5f * (a + c));
+ if (f->flag & PFACE_FILLED)
+ T *= 0.2f;
- return T;
+ return T;
}
static float p_stretch_compute_vertex(PVert *v)
{
- PEdge *e = v->edge;
- float sum = 0.0f;
+ PEdge *e = v->edge;
+ float sum = 0.0f;
- do {
- sum += p_face_stretch(e->face);
- e = p_wheel_edge_next(e);
- } while (e && e != (v->edge));
+ do {
+ sum += p_face_stretch(e->face);
+ e = p_wheel_edge_next(e);
+ } while (e && e != (v->edge));
- return sum;
+ return sum;
}
static void p_chart_stretch_minimize(PChart *chart, RNG *rng)
{
- PVert *v;
- PEdge *e;
- int j, nedges;
- float orig_stretch, low, stretch_low, high, stretch_high, mid, stretch;
- float orig_uv[2], dir[2], random_angle, trusted_radius;
-
- for (v = chart->verts; v; v = v->nextlink) {
- if ((v->flag & PVERT_PIN) || !(v->flag & PVERT_SELECT))
- continue;
-
- orig_stretch = p_stretch_compute_vertex(v);
- orig_uv[0] = v->uv[0];
- orig_uv[1] = v->uv[1];
-
- /* move vertex in a random direction */
- trusted_radius = 0.0f;
- nedges = 0;
- e = v->edge;
-
- do {
- trusted_radius += p_edge_uv_length(e);
- nedges++;
-
- e = p_wheel_edge_next(e);
- } while (e && e != (v->edge));
-
- trusted_radius /= 2 * nedges;
-
- random_angle = BLI_rng_get_float(rng) * 2.0f * (float)M_PI;
- dir[0] = trusted_radius * cosf(random_angle);
- dir[1] = trusted_radius * sinf(random_angle);
-
- /* calculate old and new stretch */
- low = 0;
- stretch_low = orig_stretch;
-
- add_v2_v2v2(v->uv, orig_uv, dir);
- high = 1;
- stretch = stretch_high = p_stretch_compute_vertex(v);
-
- /* binary search for lowest stretch position */
- for (j = 0; j < P_STRETCH_ITER; j++) {
- mid = 0.5f * (low + high);
- v->uv[0] = orig_uv[0] + mid * dir[0];
- v->uv[1] = orig_uv[1] + mid * dir[1];
- stretch = p_stretch_compute_vertex(v);
-
- if (stretch_low < stretch_high) {
- high = mid;
- stretch_high = stretch;
- }
- else {
- low = mid;
- stretch_low = stretch;
- }
- }
-
- /* no luck, stretch has increased, reset to old values */
- if (stretch >= orig_stretch)
- copy_v2_v2(v->uv, orig_uv);
- }
+ PVert *v;
+ PEdge *e;
+ int j, nedges;
+ float orig_stretch, low, stretch_low, high, stretch_high, mid, stretch;
+ float orig_uv[2], dir[2], random_angle, trusted_radius;
+
+ for (v = chart->verts; v; v = v->nextlink) {
+ if ((v->flag & PVERT_PIN) || !(v->flag & PVERT_SELECT))
+ continue;
+
+ orig_stretch = p_stretch_compute_vertex(v);
+ orig_uv[0] = v->uv[0];
+ orig_uv[1] = v->uv[1];
+
+ /* move vertex in a random direction */
+ trusted_radius = 0.0f;
+ nedges = 0;
+ e = v->edge;
+
+ do {
+ trusted_radius += p_edge_uv_length(e);
+ nedges++;
+
+ e = p_wheel_edge_next(e);
+ } while (e && e != (v->edge));
+
+ trusted_radius /= 2 * nedges;
+
+ random_angle = BLI_rng_get_float(rng) * 2.0f * (float)M_PI;
+ dir[0] = trusted_radius * cosf(random_angle);
+ dir[1] = trusted_radius * sinf(random_angle);
+
+ /* calculate old and new stretch */
+ low = 0;
+ stretch_low = orig_stretch;
+
+ add_v2_v2v2(v->uv, orig_uv, dir);
+ high = 1;
+ stretch = stretch_high = p_stretch_compute_vertex(v);
+
+ /* binary search for lowest stretch position */
+ for (j = 0; j < P_STRETCH_ITER; j++) {
+ mid = 0.5f * (low + high);
+ v->uv[0] = orig_uv[0] + mid * dir[0];
+ v->uv[1] = orig_uv[1] + mid * dir[1];
+ stretch = p_stretch_compute_vertex(v);
+
+ if (stretch_low < stretch_high) {
+ high = mid;
+ stretch_high = stretch;
+ }
+ else {
+ low = mid;
+ stretch_low = stretch;
+ }
+ }
+
+ /* no luck, stretch has increased, reset to old values */
+ if (stretch >= orig_stretch)
+ copy_v2_v2(v->uv, orig_uv);
+ }
}
/* Minimum area enclosing rectangle for packing */
static int p_compare_geometric_uv(const void *a, const void *b)
{
- const PVert *v1 = *(const PVert * const *)a;
- const PVert *v2 = *(const PVert * const *)b;
+ const PVert *v1 = *(const PVert *const *)a;
+ const PVert *v2 = *(const PVert *const *)b;
- if (v1->uv[0] < v2->uv[0])
- return -1;
- else if (v1->uv[0] == v2->uv[0]) {
- if (v1->uv[1] < v2->uv[1])
- return -1;
- else if (v1->uv[1] == v2->uv[1])
- return 0;
- else
- return 1;
- }
- else
- return 1;
+ if (v1->uv[0] < v2->uv[0])
+ return -1;
+ else if (v1->uv[0] == v2->uv[0]) {
+ if (v1->uv[1] < v2->uv[1])
+ return -1;
+ else if (v1->uv[1] == v2->uv[1])
+ return 0;
+ else
+ return 1;
+ }
+ else
+ return 1;
}
static PBool p_chart_convex_hull(PChart *chart, PVert ***verts, int *nverts, int *right)
{
- /* Graham algorithm, taken from:
- * http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/117225 */
+ /* Graham algorithm, taken from:
+ * http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/117225 */
- PEdge *be, *e;
- int npoints = 0, i, ulen, llen;
- PVert **U, **L, **points, **p;
+ PEdge *be, *e;
+ int npoints = 0, i, ulen, llen;
+ PVert **U, **L, **points, **p;
- p_chart_boundaries(chart, NULL, &be);
+ p_chart_boundaries(chart, NULL, &be);
- if (!be)
- return P_FALSE;
+ if (!be)
+ return P_FALSE;
- e = be;
- do {
- npoints++;
- e = p_boundary_edge_next(e);
- } while (e != be);
+ e = be;
+ do {
+ npoints++;
+ e = p_boundary_edge_next(e);
+ } while (e != be);
- p = points = (PVert **)MEM_mallocN(sizeof(PVert *) * npoints * 2, "PCHullpoints");
- U = (PVert **)MEM_mallocN(sizeof(PVert *) * npoints, "PCHullU");
- L = (PVert **)MEM_mallocN(sizeof(PVert *) * npoints, "PCHullL");
+ p = points = (PVert **)MEM_mallocN(sizeof(PVert *) * npoints * 2, "PCHullpoints");
+ U = (PVert **)MEM_mallocN(sizeof(PVert *) * npoints, "PCHullU");
+ L = (PVert **)MEM_mallocN(sizeof(PVert *) * npoints, "PCHullL");
- e = be;
- do {
- *p = e->vert;
- p++;
- e = p_boundary_edge_next(e);
- } while (e != be);
+ e = be;
+ do {
+ *p = e->vert;
+ p++;
+ e = p_boundary_edge_next(e);
+ } while (e != be);
- qsort(points, npoints, sizeof(PVert *), p_compare_geometric_uv);
+ qsort(points, npoints, sizeof(PVert *), p_compare_geometric_uv);
- ulen = llen = 0;
- for (p = points, i = 0; i < npoints; i++, p++) {
- while ((ulen > 1) && (p_area_signed(U[ulen - 2]->uv, (*p)->uv, U[ulen - 1]->uv) <= 0))
- ulen--;
- while ((llen > 1) && (p_area_signed(L[llen - 2]->uv, (*p)->uv, L[llen - 1]->uv) >= 0))
- llen--;
+ ulen = llen = 0;
+ for (p = points, i = 0; i < npoints; i++, p++) {
+ while ((ulen > 1) && (p_area_signed(U[ulen - 2]->uv, (*p)->uv, U[ulen - 1]->uv) <= 0))
+ ulen--;
+ while ((llen > 1) && (p_area_signed(L[llen - 2]->uv, (*p)->uv, L[llen - 1]->uv) >= 0))
+ llen--;
- U[ulen] = *p;
- ulen++;
- L[llen] = *p;
- llen++;
- }
+ U[ulen] = *p;
+ ulen++;
+ L[llen] = *p;
+ llen++;
+ }
- npoints = 0;
- for (p = points, i = 0; i < ulen; i++, p++, npoints++)
- *p = U[i];
+ npoints = 0;
+ for (p = points, i = 0; i < ulen; i++, p++, npoints++)
+ *p = U[i];
- /* the first and last point in L are left out, since they are also in U */
- for (i = llen - 2; i > 0; i--, p++, npoints++)
- *p = L[i];
+ /* the first and last point in L are left out, since they are also in U */
+ for (i = llen - 2; i > 0; i--, p++, npoints++)
+ *p = L[i];
- *verts = points;
- *nverts = npoints;
- *right = ulen - 1;
+ *verts = points;
+ *nverts = npoints;
+ *right = ulen - 1;
- MEM_freeN(U);
- MEM_freeN(L);
+ MEM_freeN(U);
+ MEM_freeN(L);
- return P_TRUE;
+ return P_TRUE;
}
static float p_rectangle_area(float *p1, float *dir, float *p2, float *p3, float *p4)
{
- /* given 4 points on the rectangle edges and the direction of on edge,
- * compute the area of the rectangle */
+ /* given 4 points on the rectangle edges and the direction of on edge,
+ * compute the area of the rectangle */
- float orthodir[2], corner1[2], corner2[2], corner3[2];
+ float orthodir[2], corner1[2], corner2[2], corner3[2];
- orthodir[0] = dir[1];
- orthodir[1] = -dir[0];
+ orthodir[0] = dir[1];
+ orthodir[1] = -dir[0];
- if (!p_intersect_line_2d_dir(p1, dir, p2, orthodir, corner1))
- return 1e10;
+ if (!p_intersect_line_2d_dir(p1, dir, p2, orthodir, corner1))
+ return 1e10;
- if (!p_intersect_line_2d_dir(p1, dir, p4, orthodir, corner2))
- return 1e10;
+ if (!p_intersect_line_2d_dir(p1, dir, p4, orthodir, corner2))
+ return 1e10;
- if (!p_intersect_line_2d_dir(p3, dir, p4, orthodir, corner3))
- return 1e10;
+ if (!p_intersect_line_2d_dir(p3, dir, p4, orthodir, corner3))
+ return 1e10;
- return len_v2v2(corner1, corner2) * len_v2v2(corner2, corner3);
+ return len_v2v2(corner1, corner2) * len_v2v2(corner2, corner3);
}
static float p_chart_minimum_area_angle(PChart *chart)
{
- /* minimum area enclosing rectangle with rotating calipers, info:
- * http://cgm.cs.mcgill.ca/~orm/maer.html */
-
- float rotated, minarea, minangle, area, len;
- float *angles, miny, maxy, v[2], a[4], mina;
- int npoints, right, i_min, i_max, i, idx[4], nextidx;
- PVert **points, *p1, *p2, *p3, *p4, *p1n;
-
- /* compute convex hull */
- if (!p_chart_convex_hull(chart, &points, &npoints, &right))
- return 0.0;
-
- /* find left/top/right/bottom points, and compute angle for each point */
- angles = MEM_mallocN(sizeof(float) * npoints, "PMinAreaAngles");
-
- i_min = i_max = 0;
- miny = 1e10;
- maxy = -1e10;
+ /* minimum area enclosing rectangle with rotating calipers, info:
+ * http://cgm.cs.mcgill.ca/~orm/maer.html */
+
+ float rotated, minarea, minangle, area, len;
+ float *angles, miny, maxy, v[2], a[4], mina;
+ int npoints, right, i_min, i_max, i, idx[4], nextidx;
+ PVert **points, *p1, *p2, *p3, *p4, *p1n;
+
+ /* compute convex hull */
+ if (!p_chart_convex_hull(chart, &points, &npoints, &right))
+ return 0.0;
+
+ /* find left/top/right/bottom points, and compute angle for each point */
+ angles = MEM_mallocN(sizeof(float) * npoints, "PMinAreaAngles");
+
+ i_min = i_max = 0;
+ miny = 1e10;
+ maxy = -1e10;
- for (i = 0; i < npoints; i++) {
- p1 = (i == 0) ? points[npoints - 1] : points[i - 1];
- p2 = points[i];
- p3 = (i == npoints - 1) ? points[0] : points[i + 1];
+ for (i = 0; i < npoints; i++) {
+ p1 = (i == 0) ? points[npoints - 1] : points[i - 1];
+ p2 = points[i];
+ p3 = (i == npoints - 1) ? points[0] : points[i + 1];
- angles[i] = (float)M_PI - p_vec2_angle(p1->uv, p2->uv, p3->uv);
+ angles[i] = (float)M_PI - p_vec2_angle(p1->uv, p2->uv, p3->uv);
- if (points[i]->uv[1] < miny) {
- miny = points[i]->uv[1];
- i_min = i;
- }
- if (points[i]->uv[1] > maxy) {
- maxy = points[i]->uv[1];
- i_max = i;
- }
- }
+ if (points[i]->uv[1] < miny) {
+ miny = points[i]->uv[1];
+ i_min = i;
+ }
+ if (points[i]->uv[1] > maxy) {
+ maxy = points[i]->uv[1];
+ i_max = i;
+ }
+ }
- /* left, top, right, bottom */
- idx[0] = 0;
- idx[1] = i_max;
- idx[2] = right;
- idx[3] = i_min;
+ /* left, top, right, bottom */
+ idx[0] = 0;
+ idx[1] = i_max;
+ idx[2] = right;
+ idx[3] = i_min;
- v[0] = points[idx[0]]->uv[0];
- v[1] = points[idx[0]]->uv[1] + 1.0f;
- a[0] = p_vec2_angle(points[(idx[0] + 1) % npoints]->uv, points[idx[0]]->uv, v);
+ v[0] = points[idx[0]]->uv[0];
+ v[1] = points[idx[0]]->uv[1] + 1.0f;
+ a[0] = p_vec2_angle(points[(idx[0] + 1) % npoints]->uv, points[idx[0]]->uv, v);
- v[0] = points[idx[1]]->uv[0] + 1.0f;
- v[1] = points[idx[1]]->uv[1];
- a[1] = p_vec2_angle(points[(idx[1] + 1) % npoints]->uv, points[idx[1]]->uv, v);
+ v[0] = points[idx[1]]->uv[0] + 1.0f;
+ v[1] = points[idx[1]]->uv[1];
+ a[1] = p_vec2_angle(points[(idx[1] + 1) % npoints]->uv, points[idx[1]]->uv, v);
- v[0] = points[idx[2]]->uv[0];
- v[1] = points[idx[2]]->uv[1] - 1.0f;
- a[2] = p_vec2_angle(points[(idx[2] + 1) % npoints]->uv, points[idx[2]]->uv, v);
+ v[0] = points[idx[2]]->uv[0];
+ v[1] = points[idx[2]]->uv[1] - 1.0f;
+ a[2] = p_vec2_angle(points[(idx[2] + 1) % npoints]->uv, points[idx[2]]->uv, v);
- v[0] = points[idx[3]]->uv[0] - 1.0f;
- v[1] = points[idx[3]]->uv[1];
- a[3] = p_vec2_angle(points[(idx[3] + 1) % npoints]->uv, points[idx[3]]->uv, v);
+ v[0] = points[idx[3]]->uv[0] - 1.0f;
+ v[1] = points[idx[3]]->uv[1];
+ a[3] = p_vec2_angle(points[(idx[3] + 1) % npoints]->uv, points[idx[3]]->uv, v);
- /* 4 rotating calipers */
+ /* 4 rotating calipers */
- rotated = 0.0;
- minarea = 1e10;
- minangle = 0.0;
+ rotated = 0.0;
+ minarea = 1e10;
+ minangle = 0.0;
- while (rotated <= (float)(M_PI / 2.0)) { /* INVESTIGATE: how far to rotate? */
- /* rotate with the smallest angle */
- i_min = 0;
- mina = 1e10;
+ while (rotated <= (float)(M_PI / 2.0)) { /* INVESTIGATE: how far to rotate? */
+ /* rotate with the smallest angle */
+ i_min = 0;
+ mina = 1e10;
- for (i = 0; i < 4; i++)
- if (a[i] < mina) {
- mina = a[i];
- i_min = i;
- }
+ for (i = 0; i < 4; i++)
+ if (a[i] < mina) {
+ mina = a[i];
+ i_min = i;
+ }
- rotated += mina;
- nextidx = (idx[i_min] + 1) % npoints;
+ rotated += mina;
+ nextidx = (idx[i_min] + 1) % npoints;
- a[i_min] = angles[nextidx];
- a[(i_min + 1) % 4] = a[(i_min + 1) % 4] - mina;
- a[(i_min + 2) % 4] = a[(i_min + 2) % 4] - mina;
- a[(i_min + 3) % 4] = a[(i_min + 3) % 4] - mina;
+ a[i_min] = angles[nextidx];
+ a[(i_min + 1) % 4] = a[(i_min + 1) % 4] - mina;
+ a[(i_min + 2) % 4] = a[(i_min + 2) % 4] - mina;
+ a[(i_min + 3) % 4] = a[(i_min + 3) % 4] - mina;
- /* compute area */
- p1 = points[idx[i_min]];
- p1n = points[nextidx];
- p2 = points[idx[(i_min + 1) % 4]];
- p3 = points[idx[(i_min + 2) % 4]];
- p4 = points[idx[(i_min + 3) % 4]];
+ /* compute area */
+ p1 = points[idx[i_min]];
+ p1n = points[nextidx];
+ p2 = points[idx[(i_min + 1) % 4]];
+ p3 = points[idx[(i_min + 2) % 4]];
+ p4 = points[idx[(i_min + 3) % 4]];
- len = len_v2v2(p1->uv, p1n->uv);
+ len = len_v2v2(p1->uv, p1n->uv);
- if (len > 0.0f) {
- len = 1.0f / len;
- v[0] = (p1n->uv[0] - p1->uv[0]) * len;
- v[1] = (p1n->uv[1] - p1->uv[1]) * len;
+ if (len > 0.0f) {
+ len = 1.0f / len;
+ v[0] = (p1n->uv[0] - p1->uv[0]) * len;
+ v[1] = (p1n->uv[1] - p1->uv[1]) * len;
- area = p_rectangle_area(p1->uv, v, p2->uv, p3->uv, p4->uv);
+ area = p_rectangle_area(p1->uv, v, p2->uv, p3->uv, p4->uv);
- /* remember smallest area */
- if (area < minarea) {
- minarea = area;
- minangle = rotated;
- }
- }
+ /* remember smallest area */
+ if (area < minarea) {
+ minarea = area;
+ minangle = rotated;
+ }
+ }
- idx[i_min] = nextidx;
- }
+ idx[i_min] = nextidx;
+ }
- /* try keeping rotation as small as possible */
- if (minangle > (float)(M_PI / 4))
- minangle -= (float)(M_PI / 2.0);
+ /* try keeping rotation as small as possible */
+ if (minangle > (float)(M_PI / 4))
+ minangle -= (float)(M_PI / 2.0);
- MEM_freeN(angles);
- MEM_freeN(points);
-
- return minangle;
+ MEM_freeN(angles);
+ MEM_freeN(points);
+
+ return minangle;
}
static void p_chart_rotate_minimum_area(PChart *chart)
{
- float angle = p_chart_minimum_area_angle(chart);
- float sine = sinf(angle);
- float cosine = cosf(angle);
- PVert *v;
+ float angle = p_chart_minimum_area_angle(chart);
+ float sine = sinf(angle);
+ float cosine = cosf(angle);
+ PVert *v;
- for (v = chart->verts; v; v = v->nextlink) {
- float oldu = v->uv[0], oldv = v->uv[1];
- v->uv[0] = cosine * oldu - sine * oldv;
- v->uv[1] = sine * oldu + cosine * oldv;
- }
+ for (v = chart->verts; v; v = v->nextlink) {
+ float oldu = v->uv[0], oldv = v->uv[1];
+ v->uv[0] = cosine * oldu - sine * oldv;
+ v->uv[1] = sine * oldu + cosine * oldv;
+ }
}
/* Area Smoothing */
@@ -3614,1083 +3642,1110 @@ static void p_chart_rotate_minimum_area(PChart *chart)
/* 2d bsp tree for inverse mapping - that's a bit silly */
typedef struct SmoothTriangle {
- float co1[2], co2[2], co3[2];
- float oco1[2], oco2[2], oco3[2];
+ float co1[2], co2[2], co3[2];
+ float oco1[2], oco2[2], oco3[2];
} SmoothTriangle;
typedef struct SmoothNode {
- struct SmoothNode *c1, *c2;
- SmoothTriangle **tri;
- float split;
- int axis, ntri;
+ struct SmoothNode *c1, *c2;
+ SmoothTriangle **tri;
+ float split;
+ int axis, ntri;
} SmoothNode;
-static void p_barycentric_2d(const float v1[2], const float v2[2], const float v3[2], const float p[2], float b[3])
+static void p_barycentric_2d(
+ const float v1[2], const float v2[2], const float v3[2], const float p[2], float b[3])
{
- float a[2], c[2], h[2], div;
+ float a[2], c[2], h[2], div;
- a[0] = v2[0] - v1[0];
- a[1] = v2[1] - v1[1];
- c[0] = v3[0] - v1[0];
- c[1] = v3[1] - v1[1];
+ a[0] = v2[0] - v1[0];
+ a[1] = v2[1] - v1[1];
+ c[0] = v3[0] - v1[0];
+ c[1] = v3[1] - v1[1];
- div = a[0] * c[1] - a[1] * c[0];
+ div = a[0] * c[1] - a[1] * c[0];
- if (div == 0.0f) {
- b[0] = 1.0f / 3.0f;
- b[1] = 1.0f / 3.0f;
- b[2] = 1.0f / 3.0f;
- }
- else {
- h[0] = p[0] - v1[0];
- h[1] = p[1] - v1[1];
+ if (div == 0.0f) {
+ b[0] = 1.0f / 3.0f;
+ b[1] = 1.0f / 3.0f;
+ b[2] = 1.0f / 3.0f;
+ }
+ else {
+ h[0] = p[0] - v1[0];
+ h[1] = p[1] - v1[1];
- div = 1.0f / div;
+ div = 1.0f / div;
- b[1] = (h[0] * c[1] - h[1] * c[0]) * div;
- b[2] = (a[0] * h[1] - a[1] * h[0]) * div;
- b[0] = 1.0f - b[1] - b[2];
- }
+ b[1] = (h[0] * c[1] - h[1] * c[0]) * div;
+ b[2] = (a[0] * h[1] - a[1] * h[0]) * div;
+ b[0] = 1.0f - b[1] - b[2];
+ }
}
static PBool p_triangle_inside(SmoothTriangle *t, float co[2])
{
- float b[3];
+ float b[3];
- p_barycentric_2d(t->co1, t->co2, t->co3, co, b);
+ p_barycentric_2d(t->co1, t->co2, t->co3, co, b);
- if ((b[0] >= 0.0f) && (b[1] >= 0.0f) && (b[2] >= 0.0f)) {
- co[0] = t->oco1[0] * b[0] + t->oco2[0] * b[1] + t->oco3[0] * b[2];
- co[1] = t->oco1[1] * b[0] + t->oco2[1] * b[1] + t->oco3[1] * b[2];
- return P_TRUE;
- }
+ if ((b[0] >= 0.0f) && (b[1] >= 0.0f) && (b[2] >= 0.0f)) {
+ co[0] = t->oco1[0] * b[0] + t->oco2[0] * b[1] + t->oco3[0] * b[2];
+ co[1] = t->oco1[1] * b[0] + t->oco2[1] * b[1] + t->oco3[1] * b[2];
+ return P_TRUE;
+ }
- return P_FALSE;
+ return P_FALSE;
}
-static SmoothNode *p_node_new(MemArena *arena, SmoothTriangle **tri, int ntri, float *bmin, float *bmax, int depth)
+static SmoothNode *p_node_new(
+ MemArena *arena, SmoothTriangle **tri, int ntri, float *bmin, float *bmax, int depth)
{
- SmoothNode *node = BLI_memarena_alloc(arena, sizeof(*node));
- int axis, i, t1size = 0, t2size = 0;
- float split, /* mi, */ /* UNUSED */ mx;
- SmoothTriangle **t1, **t2, *t;
+ SmoothNode *node = BLI_memarena_alloc(arena, sizeof(*node));
+ int axis, i, t1size = 0, t2size = 0;
+ float split, /* mi, */ /* UNUSED */ mx;
+ SmoothTriangle **t1, **t2, *t;
- node->tri = tri;
- node->ntri = ntri;
+ node->tri = tri;
+ node->ntri = ntri;
- if (ntri <= 10 || depth >= 15)
- return node;
+ if (ntri <= 10 || depth >= 15)
+ return node;
- t1 = MEM_mallocN(sizeof(*t1) * ntri, "PNodeTri1");
- t2 = MEM_mallocN(sizeof(*t2) * ntri, "PNodeTri1");
+ t1 = MEM_mallocN(sizeof(*t1) * ntri, "PNodeTri1");
+ t2 = MEM_mallocN(sizeof(*t2) * ntri, "PNodeTri1");
- axis = (bmax[0] - bmin[0] > bmax[1] - bmin[1]) ? 0 : 1;
- split = 0.5f * (bmin[axis] + bmax[axis]);
+ axis = (bmax[0] - bmin[0] > bmax[1] - bmin[1]) ? 0 : 1;
+ split = 0.5f * (bmin[axis] + bmax[axis]);
- for (i = 0; i < ntri; i++) {
- t = tri[i];
+ for (i = 0; i < ntri; i++) {
+ t = tri[i];
- if ((t->co1[axis] <= split) || (t->co2[axis] <= split) || (t->co3[axis] <= split)) {
- t1[t1size] = t;
- t1size++;
- }
- if ((t->co1[axis] >= split) || (t->co2[axis] >= split) || (t->co3[axis] >= split)) {
- t2[t2size] = t;
- t2size++;
- }
- }
+ if ((t->co1[axis] <= split) || (t->co2[axis] <= split) || (t->co3[axis] <= split)) {
+ t1[t1size] = t;
+ t1size++;
+ }
+ if ((t->co1[axis] >= split) || (t->co2[axis] >= split) || (t->co3[axis] >= split)) {
+ t2[t2size] = t;
+ t2size++;
+ }
+ }
- if ((t1size == t2size) && (t1size == ntri)) {
- MEM_freeN(t1);
- MEM_freeN(t2);
- return node;
- }
+ if ((t1size == t2size) && (t1size == ntri)) {
+ MEM_freeN(t1);
+ MEM_freeN(t2);
+ return node;
+ }
- node->tri = NULL;
- node->ntri = 0;
- MEM_freeN(tri);
+ node->tri = NULL;
+ node->ntri = 0;
+ MEM_freeN(tri);
- node->axis = axis;
- node->split = split;
+ node->axis = axis;
+ node->split = split;
- /* mi = bmin[axis]; */ /* UNUSED */
- mx = bmax[axis];
- bmax[axis] = split;
- node->c1 = p_node_new(arena, t1, t1size, bmin, bmax, depth + 1);
+ /* mi = bmin[axis]; */ /* UNUSED */
+ mx = bmax[axis];
+ bmax[axis] = split;
+ node->c1 = p_node_new(arena, t1, t1size, bmin, bmax, depth + 1);
- bmin[axis] = bmax[axis];
- bmax[axis] = mx;
- node->c2 = p_node_new(arena, t2, t2size, bmin, bmax, depth + 1);
+ bmin[axis] = bmax[axis];
+ bmax[axis] = mx;
+ node->c2 = p_node_new(arena, t2, t2size, bmin, bmax, depth + 1);
- return node;
+ return node;
}
static void p_node_delete(SmoothNode *node)
{
- if (node->c1)
- p_node_delete(node->c1);
- if (node->c2)
- p_node_delete(node->c2);
- if (node->tri)
- MEM_freeN(node->tri);
+ if (node->c1)
+ p_node_delete(node->c1);
+ if (node->c2)
+ p_node_delete(node->c2);
+ if (node->tri)
+ MEM_freeN(node->tri);
}
static PBool p_node_intersect(SmoothNode *node, float co[2])
{
- int i;
-
- if (node->tri) {
- for (i = 0; i < node->ntri; i++)
- if (p_triangle_inside(node->tri[i], co))
- return P_TRUE;
+ int i;
- return P_FALSE;
- }
- else {
- if (co[node->axis] < node->split)
- return p_node_intersect(node->c1, co);
- else
- return p_node_intersect(node->c2, co);
- }
+ if (node->tri) {
+ for (i = 0; i < node->ntri; i++)
+ if (p_triangle_inside(node->tri[i], co))
+ return P_TRUE;
+ return P_FALSE;
+ }
+ else {
+ if (co[node->axis] < node->split)
+ return p_node_intersect(node->c1, co);
+ else
+ return p_node_intersect(node->c2, co);
+ }
}
/* smoothing */
static int p_compare_float(const void *a_, const void *b_)
{
- const float a = *(const float *)a_;
- const float b = *(const float *)b_;
+ const float a = *(const float *)a_;
+ const float b = *(const float *)b_;
- if (a < b)
- return -1;
- else if (a == b)
- return 0;
- else
- return 1;
+ if (a < b)
+ return -1;
+ else if (a == b)
+ return 0;
+ else
+ return 1;
}
static float p_smooth_median_edge_length(PChart *chart)
{
- PEdge *e;
- float *lengths = MEM_mallocN(sizeof(chart->edges) * chart->nedges, "PMedianLength");
- float median;
- int i;
+ PEdge *e;
+ float *lengths = MEM_mallocN(sizeof(chart->edges) * chart->nedges, "PMedianLength");
+ float median;
+ int i;
- /* ok, so i'm lazy */
- for (i = 0, e = chart->edges; e; e = e->nextlink, i++)
- lengths[i] = p_edge_length(e);
+ /* ok, so i'm lazy */
+ for (i = 0, e = chart->edges; e; e = e->nextlink, i++)
+ lengths[i] = p_edge_length(e);
- qsort(lengths, i, sizeof(float), p_compare_float);
+ qsort(lengths, i, sizeof(float), p_compare_float);
- median = lengths[i / 2];
- MEM_freeN(lengths);
+ median = lengths[i / 2];
+ MEM_freeN(lengths);
- return median;
+ return median;
}
static float p_smooth_distortion(PEdge *e, float avg2d, float avg3d)
{
- float len2d = p_edge_uv_length(e) * avg3d;
- float len3d = p_edge_length(e) * avg2d;
+ float len2d = p_edge_uv_length(e) * avg3d;
+ float len3d = p_edge_length(e) * avg2d;
- return (len3d == 0.0f) ? 0.0f : len2d / len3d;
+ return (len3d == 0.0f) ? 0.0f : len2d / len3d;
}
static void p_smooth(PChart *chart)
{
- PEdge *e;
- PVert *v;
- PFace *f;
- int j, it2, maxiter2, it;
- int nedges = chart->nedges, nwheel, gridx, gridy;
- int edgesx, edgesy, nsize, esize, i, x, y, maxiter, totiter;
- float minv[2], maxv[2], median, invmedian, avglen2d, avglen3d;
- float center[2], dx, dy, *nodes, dlimit, d, *oldnodesx, *oldnodesy;
- float *nodesx, *nodesy, *hedges, *vedges, climit, moved, padding;
- SmoothTriangle *triangles, *t, *t2, **tri, **trip;
- SmoothNode *root;
- MemArena *arena;
-
- if (nedges == 0)
- return;
-
- p_chart_uv_bbox(chart, minv, maxv);
- median = p_smooth_median_edge_length(chart) * 0.10f;
-
- if (median == 0.0f)
- return;
-
- invmedian = 1.0f / median;
-
- /* compute edge distortion */
- avglen2d = avglen3d = 0.0;
-
- for (e = chart->edges; e; e = e->nextlink) {
- avglen2d += p_edge_uv_length(e);
- avglen3d += p_edge_length(e);
- }
-
- avglen2d /= nedges;
- avglen3d /= nedges;
-
- for (v = chart->verts; v; v = v->nextlink) {
- v->u.distortion = 0.0;
- nwheel = 0;
-
- e = v->edge;
- do {
- v->u.distortion += p_smooth_distortion(e, avglen2d, avglen3d);
- nwheel++;
-
- e = e->next->next->pair;
- } while (e && (e != v->edge));
-
- v->u.distortion /= nwheel;
- }
-
- /* need to do excessive grid size checking still */
- center[0] = 0.5f * (minv[0] + maxv[0]);
- center[1] = 0.5f * (minv[1] + maxv[1]);
-
- dx = 0.5f * (maxv[0] - minv[0]);
- dy = 0.5f * (maxv[1] - minv[1]);
-
- padding = 0.15f;
- dx += padding * dx + 2.0f * median;
- dy += padding * dy + 2.0f * median;
-
- gridx = (int)(dx * invmedian);
- gridy = (int)(dy * invmedian);
-
- minv[0] = center[0] - median * gridx;
- minv[1] = center[1] - median * gridy;
- maxv[0] = center[0] + median * gridx;
- maxv[1] = center[1] + median * gridy;
-
- /* create grid */
- gridx = gridx * 2 + 1;
- gridy = gridy * 2 + 1;
-
- if ((gridx <= 2) || (gridy <= 2))
- return;
-
- edgesx = gridx - 1;
- edgesy = gridy - 1;
- nsize = gridx * gridy;
- esize = edgesx * edgesy;
-
- nodes = MEM_mallocN(sizeof(float) * nsize, "PSmoothNodes");
- nodesx = MEM_mallocN(sizeof(float) * nsize, "PSmoothNodesX");
- nodesy = MEM_mallocN(sizeof(float) * nsize, "PSmoothNodesY");
- oldnodesx = MEM_mallocN(sizeof(float) * nsize, "PSmoothOldNodesX");
- oldnodesy = MEM_mallocN(sizeof(float) * nsize, "PSmoothOldNodesY");
- hedges = MEM_mallocN(sizeof(float) * esize, "PSmoothHEdges");
- vedges = MEM_mallocN(sizeof(float) * esize, "PSmoothVEdges");
-
- if (!nodes || !nodesx || !nodesy || !oldnodesx || !oldnodesy || !hedges || !vedges) {
- if (nodes) MEM_freeN(nodes);
- if (nodesx) MEM_freeN(nodesx);
- if (nodesy) MEM_freeN(nodesy);
- if (oldnodesx) MEM_freeN(oldnodesx);
- if (oldnodesy) MEM_freeN(oldnodesy);
- if (hedges) MEM_freeN(hedges);
- if (vedges) MEM_freeN(vedges);
-
- // printf("Not enough memory for area smoothing grid");
- return;
- }
-
- for (x = 0; x < gridx; x++) {
- for (y = 0; y < gridy; y++) {
- i = x + y * gridx;
-
- nodesx[i] = minv[0] + median * x;
- nodesy[i] = minv[1] + median * y;
-
- nodes[i] = 1.0f;
- }
- }
-
- /* embed in grid */
- for (f = chart->faces; f; f = f->nextlink) {
- PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
- float fmin[2], fmax[2];
- int bx1, by1, bx2, by2;
-
- INIT_MINMAX2(fmin, fmax);
+ PEdge *e;
+ PVert *v;
+ PFace *f;
+ int j, it2, maxiter2, it;
+ int nedges = chart->nedges, nwheel, gridx, gridy;
+ int edgesx, edgesy, nsize, esize, i, x, y, maxiter, totiter;
+ float minv[2], maxv[2], median, invmedian, avglen2d, avglen3d;
+ float center[2], dx, dy, *nodes, dlimit, d, *oldnodesx, *oldnodesy;
+ float *nodesx, *nodesy, *hedges, *vedges, climit, moved, padding;
+ SmoothTriangle *triangles, *t, *t2, **tri, **trip;
+ SmoothNode *root;
+ MemArena *arena;
+
+ if (nedges == 0)
+ return;
+
+ p_chart_uv_bbox(chart, minv, maxv);
+ median = p_smooth_median_edge_length(chart) * 0.10f;
+
+ if (median == 0.0f)
+ return;
+
+ invmedian = 1.0f / median;
+
+ /* compute edge distortion */
+ avglen2d = avglen3d = 0.0;
+
+ for (e = chart->edges; e; e = e->nextlink) {
+ avglen2d += p_edge_uv_length(e);
+ avglen3d += p_edge_length(e);
+ }
+
+ avglen2d /= nedges;
+ avglen3d /= nedges;
+
+ for (v = chart->verts; v; v = v->nextlink) {
+ v->u.distortion = 0.0;
+ nwheel = 0;
+
+ e = v->edge;
+ do {
+ v->u.distortion += p_smooth_distortion(e, avglen2d, avglen3d);
+ nwheel++;
+
+ e = e->next->next->pair;
+ } while (e && (e != v->edge));
+
+ v->u.distortion /= nwheel;
+ }
+
+ /* need to do excessive grid size checking still */
+ center[0] = 0.5f * (minv[0] + maxv[0]);
+ center[1] = 0.5f * (minv[1] + maxv[1]);
+
+ dx = 0.5f * (maxv[0] - minv[0]);
+ dy = 0.5f * (maxv[1] - minv[1]);
+
+ padding = 0.15f;
+ dx += padding * dx + 2.0f * median;
+ dy += padding * dy + 2.0f * median;
+
+ gridx = (int)(dx * invmedian);
+ gridy = (int)(dy * invmedian);
+
+ minv[0] = center[0] - median * gridx;
+ minv[1] = center[1] - median * gridy;
+ maxv[0] = center[0] + median * gridx;
+ maxv[1] = center[1] + median * gridy;
+
+ /* create grid */
+ gridx = gridx * 2 + 1;
+ gridy = gridy * 2 + 1;
+
+ if ((gridx <= 2) || (gridy <= 2))
+ return;
+
+ edgesx = gridx - 1;
+ edgesy = gridy - 1;
+ nsize = gridx * gridy;
+ esize = edgesx * edgesy;
+
+ nodes = MEM_mallocN(sizeof(float) * nsize, "PSmoothNodes");
+ nodesx = MEM_mallocN(sizeof(float) * nsize, "PSmoothNodesX");
+ nodesy = MEM_mallocN(sizeof(float) * nsize, "PSmoothNodesY");
+ oldnodesx = MEM_mallocN(sizeof(float) * nsize, "PSmoothOldNodesX");
+ oldnodesy = MEM_mallocN(sizeof(float) * nsize, "PSmoothOldNodesY");
+ hedges = MEM_mallocN(sizeof(float) * esize, "PSmoothHEdges");
+ vedges = MEM_mallocN(sizeof(float) * esize, "PSmoothVEdges");
+
+ if (!nodes || !nodesx || !nodesy || !oldnodesx || !oldnodesy || !hedges || !vedges) {
+ if (nodes)
+ MEM_freeN(nodes);
+ if (nodesx)
+ MEM_freeN(nodesx);
+ if (nodesy)
+ MEM_freeN(nodesy);
+ if (oldnodesx)
+ MEM_freeN(oldnodesx);
+ if (oldnodesy)
+ MEM_freeN(oldnodesy);
+ if (hedges)
+ MEM_freeN(hedges);
+ if (vedges)
+ MEM_freeN(vedges);
+
+ // printf("Not enough memory for area smoothing grid");
+ return;
+ }
+
+ for (x = 0; x < gridx; x++) {
+ for (y = 0; y < gridy; y++) {
+ i = x + y * gridx;
+
+ nodesx[i] = minv[0] + median * x;
+ nodesy[i] = minv[1] + median * y;
+
+ nodes[i] = 1.0f;
+ }
+ }
+
+ /* embed in grid */
+ for (f = chart->faces; f; f = f->nextlink) {
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ float fmin[2], fmax[2];
+ int bx1, by1, bx2, by2;
+
+ INIT_MINMAX2(fmin, fmax);
+
+ minmax_v2v2_v2(fmin, fmax, e1->vert->uv);
+ minmax_v2v2_v2(fmin, fmax, e2->vert->uv);
+ minmax_v2v2_v2(fmin, fmax, e3->vert->uv);
+
+ bx1 = (int)((fmin[0] - minv[0]) * invmedian);
+ by1 = (int)((fmin[1] - minv[1]) * invmedian);
+ bx2 = (int)((fmax[0] - minv[0]) * invmedian + 2);
+ by2 = (int)((fmax[1] - minv[1]) * invmedian + 2);
+
+ for (x = bx1; x < bx2; x++) {
+ for (y = by1; y < by2; y++) {
+ float p[2], b[3];
+
+ i = x + y * gridx;
+
+ p[0] = nodesx[i];
+ p[1] = nodesy[i];
+
+ p_barycentric_2d(e1->vert->uv, e2->vert->uv, e3->vert->uv, p, b);
+
+ if ((b[0] > 0.0f) && (b[1] > 0.0f) && (b[2] > 0.0f)) {
+ nodes[i] = e1->vert->u.distortion * b[0];
+ nodes[i] += e2->vert->u.distortion * b[1];
+ nodes[i] += e3->vert->u.distortion * b[2];
+ }
+ }
+ }
+ }
+
+ /* smooth the grid */
+ maxiter = 10;
+ totiter = 0;
+ climit = 0.00001f * nsize;
+
+ for (it = 0; it < maxiter; it++) {
+ moved = 0.0f;
+
+ for (x = 0; x < edgesx; x++) {
+ for (y = 0; y < edgesy; y++) {
+ i = x + y * gridx;
+ j = x + y * edgesx;
+
+ hedges[j] = (nodes[i] + nodes[i + 1]) * 0.5f;
+ vedges[j] = (nodes[i] + nodes[i + gridx]) * 0.5f;
+
+ /* we do *inverse* mapping */
+ hedges[j] = 1.0f / hedges[j];
+ vedges[j] = 1.0f / vedges[j];
+ }
+ }
+
+ maxiter2 = 50;
+ dlimit = 0.0001f;
+
+ for (it2 = 0; it2 < maxiter2; it2++) {
+ d = 0.0f;
+ totiter += 1;
+
+ memcpy(oldnodesx, nodesx, sizeof(float) * nsize);
+ memcpy(oldnodesy, nodesy, sizeof(float) * nsize);
- minmax_v2v2_v2(fmin, fmax, e1->vert->uv);
- minmax_v2v2_v2(fmin, fmax, e2->vert->uv);
- minmax_v2v2_v2(fmin, fmax, e3->vert->uv);
-
- bx1 = (int)((fmin[0] - minv[0]) * invmedian);
- by1 = (int)((fmin[1] - minv[1]) * invmedian);
- bx2 = (int)((fmax[0] - minv[0]) * invmedian + 2);
- by2 = (int)((fmax[1] - minv[1]) * invmedian + 2);
-
- for (x = bx1; x < bx2; x++) {
- for (y = by1; y < by2; y++) {
- float p[2], b[3];
-
- i = x + y * gridx;
-
- p[0] = nodesx[i];
- p[1] = nodesy[i];
-
- p_barycentric_2d(e1->vert->uv, e2->vert->uv, e3->vert->uv, p, b);
-
- if ((b[0] > 0.0f) && (b[1] > 0.0f) && (b[2] > 0.0f)) {
- nodes[i] = e1->vert->u.distortion * b[0];
- nodes[i] += e2->vert->u.distortion * b[1];
- nodes[i] += e3->vert->u.distortion * b[2];
- }
- }
- }
- }
-
- /* smooth the grid */
- maxiter = 10;
- totiter = 0;
- climit = 0.00001f * nsize;
-
- for (it = 0; it < maxiter; it++) {
- moved = 0.0f;
-
- for (x = 0; x < edgesx; x++) {
- for (y = 0; y < edgesy; y++) {
- i = x + y * gridx;
- j = x + y * edgesx;
-
- hedges[j] = (nodes[i] + nodes[i + 1]) * 0.5f;
- vedges[j] = (nodes[i] + nodes[i + gridx]) * 0.5f;
-
- /* we do *inverse* mapping */
- hedges[j] = 1.0f / hedges[j];
- vedges[j] = 1.0f / vedges[j];
- }
- }
+ for (x = 1; x < gridx - 1; x++) {
+ for (y = 1; y < gridy - 1; y++) {
+ float p[2], oldp[2], sum1, sum2, diff[2], length;
- maxiter2 = 50;
- dlimit = 0.0001f;
+ i = x + gridx * y;
+ j = x + edgesx * y;
- for (it2 = 0; it2 < maxiter2; it2++) {
- d = 0.0f;
- totiter += 1;
+ oldp[0] = oldnodesx[i];
+ oldp[1] = oldnodesy[i];
- memcpy(oldnodesx, nodesx, sizeof(float) * nsize);
- memcpy(oldnodesy, nodesy, sizeof(float) * nsize);
+ sum1 = hedges[j - 1] * oldnodesx[i - 1];
+ sum1 += hedges[j] * oldnodesx[i + 1];
+ sum1 += vedges[j - edgesx] * oldnodesx[i - gridx];
+ sum1 += vedges[j] * oldnodesx[i + gridx];
- for (x = 1; x < gridx - 1; x++) {
- for (y = 1; y < gridy - 1; y++) {
- float p[2], oldp[2], sum1, sum2, diff[2], length;
+ sum2 = hedges[j - 1];
+ sum2 += hedges[j];
+ sum2 += vedges[j - edgesx];
+ sum2 += vedges[j];
- i = x + gridx * y;
- j = x + edgesx * y;
+ nodesx[i] = sum1 / sum2;
- oldp[0] = oldnodesx[i];
- oldp[1] = oldnodesy[i];
+ sum1 = hedges[j - 1] * oldnodesy[i - 1];
+ sum1 += hedges[j] * oldnodesy[i + 1];
+ sum1 += vedges[j - edgesx] * oldnodesy[i - gridx];
+ sum1 += vedges[j] * oldnodesy[i + gridx];
- sum1 = hedges[j - 1] * oldnodesx[i - 1];
- sum1 += hedges[j] * oldnodesx[i + 1];
- sum1 += vedges[j - edgesx] * oldnodesx[i - gridx];
- sum1 += vedges[j] * oldnodesx[i + gridx];
+ nodesy[i] = sum1 / sum2;
- sum2 = hedges[j - 1];
- sum2 += hedges[j];
- sum2 += vedges[j - edgesx];
- sum2 += vedges[j];
+ p[0] = nodesx[i];
+ p[1] = nodesy[i];
- nodesx[i] = sum1 / sum2;
+ diff[0] = p[0] - oldp[0];
+ diff[1] = p[1] - oldp[1];
- sum1 = hedges[j - 1] * oldnodesy[i - 1];
- sum1 += hedges[j] * oldnodesy[i + 1];
- sum1 += vedges[j - edgesx] * oldnodesy[i - gridx];
- sum1 += vedges[j] * oldnodesy[i + gridx];
+ length = len_v2(diff);
+ d = max_ff(d, length);
+ moved += length;
+ }
+ }
- nodesy[i] = sum1 / sum2;
+ if (d < dlimit)
+ break;
+ }
- p[0] = nodesx[i];
- p[1] = nodesy[i];
+ if (moved < climit)
+ break;
+ }
- diff[0] = p[0] - oldp[0];
- diff[1] = p[1] - oldp[1];
+ MEM_freeN(oldnodesx);
+ MEM_freeN(oldnodesy);
+ MEM_freeN(hedges);
+ MEM_freeN(vedges);
- length = len_v2(diff);
- d = max_ff(d, length);
- moved += length;
- }
- }
+ /* create bsp */
+ t = triangles = MEM_mallocN(sizeof(SmoothTriangle) * esize * 2, "PSmoothTris");
+ trip = tri = MEM_mallocN(sizeof(SmoothTriangle *) * esize * 2, "PSmoothTriP");
- if (d < dlimit)
- break;
- }
+ if (!triangles || !tri) {
+ MEM_freeN(nodes);
+ MEM_freeN(nodesx);
+ MEM_freeN(nodesy);
- if (moved < climit)
- break;
- }
+ if (triangles)
+ MEM_freeN(triangles);
+ if (tri)
+ MEM_freeN(tri);
- MEM_freeN(oldnodesx);
- MEM_freeN(oldnodesy);
- MEM_freeN(hedges);
- MEM_freeN(vedges);
+ // printf("Not enough memory for area smoothing grid");
+ return;
+ }
- /* create bsp */
- t = triangles = MEM_mallocN(sizeof(SmoothTriangle) * esize * 2, "PSmoothTris");
- trip = tri = MEM_mallocN(sizeof(SmoothTriangle *) * esize * 2, "PSmoothTriP");
+ for (x = 0; x < edgesx; x++) {
+ for (y = 0; y < edgesy; y++) {
+ i = x + y * gridx;
- if (!triangles || !tri) {
- MEM_freeN(nodes);
- MEM_freeN(nodesx);
- MEM_freeN(nodesy);
+ t->co1[0] = nodesx[i];
+ t->co1[1] = nodesy[i];
- if (triangles) MEM_freeN(triangles);
- if (tri) MEM_freeN(tri);
+ t->co2[0] = nodesx[i + 1];
+ t->co2[1] = nodesy[i + 1];
- // printf("Not enough memory for area smoothing grid");
- return;
- }
+ t->co3[0] = nodesx[i + gridx];
+ t->co3[1] = nodesy[i + gridx];
- for (x = 0; x < edgesx; x++) {
- for (y = 0; y < edgesy; y++) {
- i = x + y * gridx;
+ t->oco1[0] = minv[0] + x * median;
+ t->oco1[1] = minv[1] + y * median;
- t->co1[0] = nodesx[i];
- t->co1[1] = nodesy[i];
+ t->oco2[0] = minv[0] + (x + 1) * median;
+ t->oco2[1] = minv[1] + y * median;
- t->co2[0] = nodesx[i + 1];
- t->co2[1] = nodesy[i + 1];
+ t->oco3[0] = minv[0] + x * median;
+ t->oco3[1] = minv[1] + (y + 1) * median;
- t->co3[0] = nodesx[i + gridx];
- t->co3[1] = nodesy[i + gridx];
+ t2 = t + 1;
- t->oco1[0] = minv[0] + x * median;
- t->oco1[1] = minv[1] + y * median;
+ t2->co1[0] = nodesx[i + gridx + 1];
+ t2->co1[1] = nodesy[i + gridx + 1];
- t->oco2[0] = minv[0] + (x + 1) * median;
- t->oco2[1] = minv[1] + y * median;
+ t2->oco1[0] = minv[0] + (x + 1) * median;
+ t2->oco1[1] = minv[1] + (y + 1) * median;
- t->oco3[0] = minv[0] + x * median;
- t->oco3[1] = minv[1] + (y + 1) * median;
+ t2->co2[0] = t->co2[0];
+ t2->co2[1] = t->co2[1];
+ t2->oco2[0] = t->oco2[0];
+ t2->oco2[1] = t->oco2[1];
- t2 = t + 1;
+ t2->co3[0] = t->co3[0];
+ t2->co3[1] = t->co3[1];
+ t2->oco3[0] = t->oco3[0];
+ t2->oco3[1] = t->oco3[1];
- t2->co1[0] = nodesx[i + gridx + 1];
- t2->co1[1] = nodesy[i + gridx + 1];
+ *trip = t;
+ trip++;
+ t++;
+ *trip = t;
+ trip++;
+ t++;
+ }
+ }
- t2->oco1[0] = minv[0] + (x + 1) * median;
- t2->oco1[1] = minv[1] + (y + 1) * median;
+ MEM_freeN(nodes);
+ MEM_freeN(nodesx);
+ MEM_freeN(nodesy);
- t2->co2[0] = t->co2[0]; t2->co2[1] = t->co2[1];
- t2->oco2[0] = t->oco2[0]; t2->oco2[1] = t->oco2[1];
+ arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "param smooth arena");
+ root = p_node_new(arena, tri, esize * 2, minv, maxv, 0);
- t2->co3[0] = t->co3[0]; t2->co3[1] = t->co3[1];
- t2->oco3[0] = t->oco3[0]; t2->oco3[1] = t->oco3[1];
+ for (v = chart->verts; v; v = v->nextlink)
+ if (!p_node_intersect(root, v->uv))
+ param_warning("area smoothing error: couldn't find mapping triangle\n");
- *trip = t; trip++; t++;
- *trip = t; trip++; t++;
- }
- }
+ p_node_delete(root);
+ BLI_memarena_free(arena);
- MEM_freeN(nodes);
- MEM_freeN(nodesx);
- MEM_freeN(nodesy);
-
- arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "param smooth arena");
- root = p_node_new(arena, tri, esize * 2, minv, maxv, 0);
-
- for (v = chart->verts; v; v = v->nextlink)
- if (!p_node_intersect(root, v->uv))
- param_warning("area smoothing error: couldn't find mapping triangle\n");
-
- p_node_delete(root);
- BLI_memarena_free(arena);
-
- MEM_freeN(triangles);
+ MEM_freeN(triangles);
}
/* Exported */
ParamHandle *param_construct_begin(void)
{
- PHandle *handle = MEM_callocN(sizeof(*handle), "PHandle");
- handle->construction_chart = p_chart_new(handle);
- handle->state = PHANDLE_STATE_ALLOCATED;
- handle->arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "param construct arena");
- handle->polyfill_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "param polyfill arena");
- handle->polyfill_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
- handle->aspx = 1.0f;
- handle->aspy = 1.0f;
- handle->do_aspect = false;
+ PHandle *handle = MEM_callocN(sizeof(*handle), "PHandle");
+ handle->construction_chart = p_chart_new(handle);
+ handle->state = PHANDLE_STATE_ALLOCATED;
+ handle->arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "param construct arena");
+ handle->polyfill_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "param polyfill arena");
+ handle->polyfill_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
+ handle->aspx = 1.0f;
+ handle->aspy = 1.0f;
+ handle->do_aspect = false;
- handle->hash_verts = phash_new((PHashLink **)&handle->construction_chart->verts, 1);
- handle->hash_edges = phash_new((PHashLink **)&handle->construction_chart->edges, 1);
- handle->hash_faces = phash_new((PHashLink **)&handle->construction_chart->faces, 1);
+ handle->hash_verts = phash_new((PHashLink **)&handle->construction_chart->verts, 1);
+ handle->hash_edges = phash_new((PHashLink **)&handle->construction_chart->edges, 1);
+ handle->hash_faces = phash_new((PHashLink **)&handle->construction_chart->faces, 1);
- return (ParamHandle *)handle;
+ return (ParamHandle *)handle;
}
void param_aspect_ratio(ParamHandle *handle, float aspx, float aspy)
{
- PHandle *phandle = (PHandle *)handle;
+ PHandle *phandle = (PHandle *)handle;
- phandle->aspx = aspx;
- phandle->aspy = aspy;
- phandle->do_aspect = true;
+ phandle->aspx = aspx;
+ phandle->aspy = aspy;
+ phandle->do_aspect = true;
}
void param_delete(ParamHandle *handle)
{
- PHandle *phandle = (PHandle *)handle;
- int i;
-
- param_assert((phandle->state == PHANDLE_STATE_ALLOCATED) ||
- (phandle->state == PHANDLE_STATE_CONSTRUCTED));
-
- for (i = 0; i < phandle->ncharts; i++)
- p_chart_delete(phandle->charts[i]);
-
- if (phandle->charts)
- MEM_freeN(phandle->charts);
-
- if (phandle->construction_chart) {
- p_chart_delete(phandle->construction_chart);
-
- phash_delete(phandle->hash_verts);
- phash_delete(phandle->hash_edges);
- phash_delete(phandle->hash_faces);
- }
-
- BLI_memarena_free(phandle->arena);
- BLI_memarena_free(phandle->polyfill_arena);
- BLI_heap_free(phandle->polyfill_heap, NULL);
- MEM_freeN(phandle);
-}
-
-static void p_add_ngon(ParamHandle *handle, ParamKey key, int nverts,
- ParamKey *vkeys, float **co, float **uv,
- ParamBool *pin, ParamBool *select)
-{
- /* Allocate memory for polyfill. */
- 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);
- float (*projverts)[2] = BLI_memarena_alloc(arena, sizeof(*projverts) * (size_t)nverts);
-
- /* Calc normal, flipped: to get a positive 2d cross product. */
- float normal[3];
- zero_v3(normal);
-
- const float *co_curr, *co_prev = co[nverts - 1];
- for (int j = 0; j < nverts; j++) {
- co_curr = co[j];
- add_newell_cross_v3_v3v3(normal, co_prev, co_curr);
- co_prev = co_curr;
- }
- if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
- normal[2] = 1.0f;
- }
-
- /* Project verts to 2d. */
- float axis_mat[3][3];
- axis_dominant_v3_to_m3_negate(axis_mat, normal);
- for (int j = 0; j < nverts; j++) {
- mul_v2_m3v3(projverts[j], axis_mat, co[j]);
- }
-
- BLI_polyfill_calc_arena(projverts, nverts, 1, tris, arena);
-
- /* Beautify helps avoid thin triangles that give numerical problems. */
- BLI_polyfill_beautify(projverts, nverts, tris, arena, heap);
-
- /* 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];
-
- ParamKey tri_vkeys[3] = {vkeys[v0], vkeys[v1], vkeys[v2]};
- float *tri_co[3] = {co[v0], co[v1], co[v2]};
- float *tri_uv[3] = {uv[v0], uv[v1], uv[v2]};
- ParamBool tri_pin[3] = {pin[v0], pin[v1], pin[v2]};
- ParamBool tri_select[3] = {select[v0], select[v1], select[v2]};
-
- param_face_add(handle, key, 3, tri_vkeys, tri_co, tri_uv, tri_pin, tri_select);
- }
-
- BLI_memarena_clear(arena);
-}
-
-void param_face_add(ParamHandle *handle, ParamKey key, int nverts,
- ParamKey *vkeys, float *co[4], float *uv[4],
- ParamBool *pin, ParamBool *select)
-{
- PHandle *phandle = (PHandle *)handle;
-
- param_assert(phash_lookup(phandle->hash_faces, key) == NULL);
- param_assert(phandle->state == PHANDLE_STATE_ALLOCATED);
- param_assert((nverts == 3) || (nverts == 4));
-
- if (nverts > 4) {
- /* ngon */
- p_add_ngon(handle, key, nverts, vkeys, co, uv, pin, select);
- }
- else if (nverts == 4) {
- /* quad */
- if (p_quad_split_direction(phandle, co, vkeys)) {
- p_face_add_construct(phandle, key, vkeys, co, uv, 0, 1, 2, pin, select);
- p_face_add_construct(phandle, key, vkeys, co, uv, 0, 2, 3, pin, select);
- }
- else {
- p_face_add_construct(phandle, key, vkeys, co, uv, 0, 1, 3, pin, select);
- p_face_add_construct(phandle, key, vkeys, co, uv, 1, 2, 3, pin, select);
- }
- }
- else if (!p_face_exists(phandle, vkeys, 0, 1, 2)) {
- /* triangle */
- p_face_add_construct(phandle, key, vkeys, co, uv, 0, 1, 2, pin, select);
- }
+ PHandle *phandle = (PHandle *)handle;
+ int i;
+
+ param_assert((phandle->state == PHANDLE_STATE_ALLOCATED) ||
+ (phandle->state == PHANDLE_STATE_CONSTRUCTED));
+
+ for (i = 0; i < phandle->ncharts; i++)
+ p_chart_delete(phandle->charts[i]);
+
+ if (phandle->charts)
+ MEM_freeN(phandle->charts);
+
+ if (phandle->construction_chart) {
+ p_chart_delete(phandle->construction_chart);
+
+ phash_delete(phandle->hash_verts);
+ phash_delete(phandle->hash_edges);
+ phash_delete(phandle->hash_faces);
+ }
+
+ BLI_memarena_free(phandle->arena);
+ BLI_memarena_free(phandle->polyfill_arena);
+ BLI_heap_free(phandle->polyfill_heap, NULL);
+ MEM_freeN(phandle);
+}
+
+static void p_add_ngon(ParamHandle *handle,
+ ParamKey key,
+ int nverts,
+ ParamKey *vkeys,
+ float **co,
+ float **uv,
+ ParamBool *pin,
+ ParamBool *select)
+{
+ /* Allocate memory for polyfill. */
+ 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);
+ float(*projverts)[2] = BLI_memarena_alloc(arena, sizeof(*projverts) * (size_t)nverts);
+
+ /* Calc normal, flipped: to get a positive 2d cross product. */
+ float normal[3];
+ zero_v3(normal);
+
+ const float *co_curr, *co_prev = co[nverts - 1];
+ for (int j = 0; j < nverts; j++) {
+ co_curr = co[j];
+ add_newell_cross_v3_v3v3(normal, co_prev, co_curr);
+ co_prev = co_curr;
+ }
+ if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
+ normal[2] = 1.0f;
+ }
+
+ /* Project verts to 2d. */
+ float axis_mat[3][3];
+ axis_dominant_v3_to_m3_negate(axis_mat, normal);
+ for (int j = 0; j < nverts; j++) {
+ mul_v2_m3v3(projverts[j], axis_mat, co[j]);
+ }
+
+ BLI_polyfill_calc_arena(projverts, nverts, 1, tris, arena);
+
+ /* Beautify helps avoid thin triangles that give numerical problems. */
+ BLI_polyfill_beautify(projverts, nverts, tris, arena, heap);
+
+ /* 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];
+
+ ParamKey tri_vkeys[3] = {vkeys[v0], vkeys[v1], vkeys[v2]};
+ float *tri_co[3] = {co[v0], co[v1], co[v2]};
+ float *tri_uv[3] = {uv[v0], uv[v1], uv[v2]};
+ ParamBool tri_pin[3] = {pin[v0], pin[v1], pin[v2]};
+ ParamBool tri_select[3] = {select[v0], select[v1], select[v2]};
+
+ param_face_add(handle, key, 3, tri_vkeys, tri_co, tri_uv, tri_pin, tri_select);
+ }
+
+ BLI_memarena_clear(arena);
+}
+
+void param_face_add(ParamHandle *handle,
+ ParamKey key,
+ int nverts,
+ ParamKey *vkeys,
+ float *co[4],
+ float *uv[4],
+ ParamBool *pin,
+ ParamBool *select)
+{
+ PHandle *phandle = (PHandle *)handle;
+
+ param_assert(phash_lookup(phandle->hash_faces, key) == NULL);
+ param_assert(phandle->state == PHANDLE_STATE_ALLOCATED);
+ param_assert((nverts == 3) || (nverts == 4));
+
+ if (nverts > 4) {
+ /* ngon */
+ p_add_ngon(handle, key, nverts, vkeys, co, uv, pin, select);
+ }
+ else if (nverts == 4) {
+ /* quad */
+ if (p_quad_split_direction(phandle, co, vkeys)) {
+ p_face_add_construct(phandle, key, vkeys, co, uv, 0, 1, 2, pin, select);
+ p_face_add_construct(phandle, key, vkeys, co, uv, 0, 2, 3, pin, select);
+ }
+ else {
+ p_face_add_construct(phandle, key, vkeys, co, uv, 0, 1, 3, pin, select);
+ p_face_add_construct(phandle, key, vkeys, co, uv, 1, 2, 3, pin, select);
+ }
+ }
+ else if (!p_face_exists(phandle, vkeys, 0, 1, 2)) {
+ /* triangle */
+ p_face_add_construct(phandle, key, vkeys, co, uv, 0, 1, 2, pin, select);
+ }
}
void param_edge_set_seam(ParamHandle *handle, ParamKey *vkeys)
{
- PHandle *phandle = (PHandle *)handle;
- PEdge *e;
+ PHandle *phandle = (PHandle *)handle;
+ PEdge *e;
- param_assert(phandle->state == PHANDLE_STATE_ALLOCATED);
+ param_assert(phandle->state == PHANDLE_STATE_ALLOCATED);
- e = p_edge_lookup(phandle, vkeys);
- if (e)
- e->flag |= PEDGE_SEAM;
+ e = p_edge_lookup(phandle, vkeys);
+ if (e)
+ e->flag |= PEDGE_SEAM;
}
void param_construct_end(ParamHandle *handle, ParamBool fill, ParamBool impl)
{
- PHandle *phandle = (PHandle *)handle;
- PChart *chart = phandle->construction_chart;
- int i, j, nboundaries = 0;
- PEdge *outer;
+ PHandle *phandle = (PHandle *)handle;
+ PChart *chart = phandle->construction_chart;
+ int i, j, nboundaries = 0;
+ PEdge *outer;
- param_assert(phandle->state == PHANDLE_STATE_ALLOCATED);
+ param_assert(phandle->state == PHANDLE_STATE_ALLOCATED);
- phandle->ncharts = p_connect_pairs(phandle, (PBool)impl);
- phandle->charts = p_split_charts(phandle, chart, phandle->ncharts);
+ phandle->ncharts = p_connect_pairs(phandle, (PBool)impl);
+ phandle->charts = p_split_charts(phandle, chart, phandle->ncharts);
- p_chart_delete(phandle->construction_chart);
- phandle->construction_chart = NULL;
+ p_chart_delete(phandle->construction_chart);
+ phandle->construction_chart = NULL;
- phash_delete(phandle->hash_verts);
- phash_delete(phandle->hash_edges);
- phash_delete(phandle->hash_faces);
- phandle->hash_verts = phandle->hash_edges = phandle->hash_faces = NULL;
+ phash_delete(phandle->hash_verts);
+ phash_delete(phandle->hash_edges);
+ phash_delete(phandle->hash_faces);
+ phandle->hash_verts = phandle->hash_edges = phandle->hash_faces = NULL;
- for (i = j = 0; i < phandle->ncharts; i++) {
- PVert *v;
- chart = phandle->charts[i];
+ for (i = j = 0; i < phandle->ncharts; i++) {
+ PVert *v;
+ chart = phandle->charts[i];
- p_chart_boundaries(chart, &nboundaries, &outer);
+ p_chart_boundaries(chart, &nboundaries, &outer);
- if (!impl && nboundaries == 0) {
- p_chart_delete(chart);
- continue;
- }
+ if (!impl && nboundaries == 0) {
+ p_chart_delete(chart);
+ continue;
+ }
- phandle->charts[j] = chart;
- j++;
+ phandle->charts[j] = chart;
+ j++;
- if (fill && (nboundaries > 1))
- p_chart_fill_boundaries(chart, outer);
+ if (fill && (nboundaries > 1))
+ p_chart_fill_boundaries(chart, outer);
- for (v = chart->verts; v; v = v->nextlink)
- p_vert_load_pin_select_uvs(handle, v);
- }
+ for (v = chart->verts; v; v = v->nextlink)
+ p_vert_load_pin_select_uvs(handle, v);
+ }
- phandle->ncharts = j;
+ phandle->ncharts = j;
- phandle->state = PHANDLE_STATE_CONSTRUCTED;
+ phandle->state = PHANDLE_STATE_CONSTRUCTED;
}
void param_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf)
{
- PHandle *phandle = (PHandle *)handle;
- PFace *f;
- int i;
+ PHandle *phandle = (PHandle *)handle;
+ PFace *f;
+ int i;
- param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED);
- phandle->state = PHANDLE_STATE_LSCM;
+ param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED);
+ phandle->state = PHANDLE_STATE_LSCM;
- for (i = 0; i < phandle->ncharts; i++) {
- for (f = phandle->charts[i]->faces; f; f = f->nextlink)
- p_face_backup_uvs(f);
- p_chart_lscm_begin(phandle->charts[i], (PBool)live, (PBool)abf);
- }
+ for (i = 0; i < phandle->ncharts; i++) {
+ for (f = phandle->charts[i]->faces; f; f = f->nextlink)
+ p_face_backup_uvs(f);
+ p_chart_lscm_begin(phandle->charts[i], (PBool)live, (PBool)abf);
+ }
}
void param_lscm_solve(ParamHandle *handle)
{
- PHandle *phandle = (PHandle *)handle;
- PChart *chart;
- int i;
- PBool result;
+ PHandle *phandle = (PHandle *)handle;
+ PChart *chart;
+ int i;
+ PBool result;
- param_assert(phandle->state == PHANDLE_STATE_LSCM);
+ param_assert(phandle->state == PHANDLE_STATE_LSCM);
- for (i = 0; i < phandle->ncharts; i++) {
- chart = phandle->charts[i];
+ for (i = 0; i < phandle->ncharts; i++) {
+ chart = phandle->charts[i];
- if (chart->u.lscm.context) {
- result = p_chart_lscm_solve(phandle, chart);
+ if (chart->u.lscm.context) {
+ result = p_chart_lscm_solve(phandle, chart);
- if (result && !(chart->flag & PCHART_HAS_PINS))
- p_chart_rotate_minimum_area(chart);
+ if (result && !(chart->flag & PCHART_HAS_PINS))
+ p_chart_rotate_minimum_area(chart);
- if (!result || (chart->u.lscm.pin1))
- p_chart_lscm_end(chart);
- }
- }
+ if (!result || (chart->u.lscm.pin1))
+ p_chart_lscm_end(chart);
+ }
+ }
}
void param_lscm_end(ParamHandle *handle)
{
- PHandle *phandle = (PHandle *)handle;
- int i;
+ PHandle *phandle = (PHandle *)handle;
+ int i;
- param_assert(phandle->state == PHANDLE_STATE_LSCM);
+ param_assert(phandle->state == PHANDLE_STATE_LSCM);
- for (i = 0; i < phandle->ncharts; i++) {
- p_chart_lscm_end(phandle->charts[i]);
+ for (i = 0; i < phandle->ncharts; i++) {
+ p_chart_lscm_end(phandle->charts[i]);
#if 0
- p_chart_complexify(phandle->charts[i]);
+ p_chart_complexify(phandle->charts[i]);
#endif
- }
+ }
- phandle->state = PHANDLE_STATE_CONSTRUCTED;
+ phandle->state = PHANDLE_STATE_CONSTRUCTED;
}
void param_stretch_begin(ParamHandle *handle)
{
- PHandle *phandle = (PHandle *)handle;
- PChart *chart;
- PVert *v;
- PFace *f;
- int i;
+ PHandle *phandle = (PHandle *)handle;
+ PChart *chart;
+ PVert *v;
+ PFace *f;
+ int i;
- param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED);
- phandle->state = PHANDLE_STATE_STRETCH;
+ param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED);
+ phandle->state = PHANDLE_STATE_STRETCH;
- phandle->rng = BLI_rng_new(31415926);
- phandle->blend = 0.0f;
+ phandle->rng = BLI_rng_new(31415926);
+ phandle->blend = 0.0f;
- for (i = 0; i < phandle->ncharts; i++) {
- chart = phandle->charts[i];
+ for (i = 0; i < phandle->ncharts; i++) {
+ chart = phandle->charts[i];
- for (v = chart->verts; v; v = v->nextlink)
- v->flag &= ~PVERT_PIN; /* don't use user-defined pins */
+ for (v = chart->verts; v; v = v->nextlink)
+ v->flag &= ~PVERT_PIN; /* don't use user-defined pins */
- p_stretch_pin_boundary(chart);
+ p_stretch_pin_boundary(chart);
- for (f = chart->faces; f; f = f->nextlink) {
- p_face_backup_uvs(f);
- f->u.area3d = p_face_area(f);
- }
- }
+ for (f = chart->faces; f; f = f->nextlink) {
+ p_face_backup_uvs(f);
+ f->u.area3d = p_face_area(f);
+ }
+ }
}
void param_stretch_blend(ParamHandle *handle, float blend)
{
- PHandle *phandle = (PHandle *)handle;
+ PHandle *phandle = (PHandle *)handle;
- param_assert(phandle->state == PHANDLE_STATE_STRETCH);
- phandle->blend = blend;
+ param_assert(phandle->state == PHANDLE_STATE_STRETCH);
+ phandle->blend = blend;
}
void param_stretch_iter(ParamHandle *handle)
{
- PHandle *phandle = (PHandle *)handle;
- PChart *chart;
- int i;
+ PHandle *phandle = (PHandle *)handle;
+ PChart *chart;
+ int i;
- param_assert(phandle->state == PHANDLE_STATE_STRETCH);
+ param_assert(phandle->state == PHANDLE_STATE_STRETCH);
- for (i = 0; i < phandle->ncharts; i++) {
- chart = phandle->charts[i];
- p_chart_stretch_minimize(chart, phandle->rng);
- }
+ for (i = 0; i < phandle->ncharts; i++) {
+ chart = phandle->charts[i];
+ p_chart_stretch_minimize(chart, phandle->rng);
+ }
}
void param_stretch_end(ParamHandle *handle)
{
- PHandle *phandle = (PHandle *)handle;
+ PHandle *phandle = (PHandle *)handle;
- param_assert(phandle->state == PHANDLE_STATE_STRETCH);
- phandle->state = PHANDLE_STATE_CONSTRUCTED;
+ param_assert(phandle->state == PHANDLE_STATE_STRETCH);
+ phandle->state = PHANDLE_STATE_CONSTRUCTED;
- BLI_rng_free(phandle->rng);
- phandle->rng = NULL;
+ BLI_rng_free(phandle->rng);
+ phandle->rng = NULL;
}
void param_smooth_area(ParamHandle *handle)
{
- PHandle *phandle = (PHandle *)handle;
- int i;
+ PHandle *phandle = (PHandle *)handle;
+ int i;
- param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED);
+ param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED);
- for (i = 0; i < phandle->ncharts; i++) {
- PChart *chart = phandle->charts[i];
- PVert *v;
+ for (i = 0; i < phandle->ncharts; i++) {
+ PChart *chart = phandle->charts[i];
+ PVert *v;
- for (v = chart->verts; v; v = v->nextlink)
- v->flag &= ~PVERT_PIN;
+ for (v = chart->verts; v; v = v->nextlink)
+ v->flag &= ~PVERT_PIN;
- p_smooth(chart);
- }
+ p_smooth(chart);
+ }
}
/* don't pack, just rotate (used for better packing) */
static void param_pack_rotate(ParamHandle *handle, bool ignore_pinned)
{
- PChart *chart;
- int i;
+ PChart *chart;
+ int i;
- PHandle *phandle = (PHandle *)handle;
+ PHandle *phandle = (PHandle *)handle;
- for (i = 0; i < phandle->ncharts; i++) {
- float (*points)[2];
- float angle;
+ for (i = 0; i < phandle->ncharts; i++) {
+ float(*points)[2];
+ float angle;
- chart = phandle->charts[i];
+ chart = phandle->charts[i];
- if (ignore_pinned && (chart->flag & PCHART_HAS_PINS)) {
- continue;
- }
+ if (ignore_pinned && (chart->flag & PCHART_HAS_PINS)) {
+ continue;
+ }
- points = MEM_mallocN(sizeof(*points) * chart->nverts, __func__);
+ points = MEM_mallocN(sizeof(*points) * chart->nverts, __func__);
- p_chart_uv_to_array(chart, points);
+ p_chart_uv_to_array(chart, points);
- angle = BLI_convexhull_aabb_fit_points_2d(points, chart->nverts);
+ angle = BLI_convexhull_aabb_fit_points_2d(points, chart->nverts);
- MEM_freeN(points);
+ MEM_freeN(points);
- if (angle != 0.0f) {
- float mat[2][2];
- angle_to_mat2(mat, angle);
- p_chart_uv_transform(chart, mat);
- }
- }
+ if (angle != 0.0f) {
+ float mat[2][2];
+ angle_to_mat2(mat, angle);
+ p_chart_uv_transform(chart, mat);
+ }
+ }
}
void param_pack(ParamHandle *handle, float margin, bool do_rotate, bool ignore_pinned)
{
- /* box packing variables */
- BoxPack *boxarray, *box;
- float tot_width, tot_height, scale;
-
- PChart *chart;
- int i, unpacked = 0;
- float trans[2];
- double area = 0.0;
+ /* box packing variables */
+ BoxPack *boxarray, *box;
+ float tot_width, tot_height, scale;
- PHandle *phandle = (PHandle *)handle;
+ PChart *chart;
+ int i, unpacked = 0;
+ float trans[2];
+ double area = 0.0;
- if (phandle->ncharts == 0)
- return;
+ PHandle *phandle = (PHandle *)handle;
- /* this could be its own function */
- if (do_rotate) {
- param_pack_rotate(handle, ignore_pinned);
- }
+ if (phandle->ncharts == 0)
+ return;
- if (phandle->aspx != phandle->aspy)
- param_scale(handle, 1.0f / phandle->aspx, 1.0f / phandle->aspy);
+ /* this could be its own function */
+ if (do_rotate) {
+ param_pack_rotate(handle, ignore_pinned);
+ }
- /* we may not use all these boxes */
- boxarray = MEM_mallocN(phandle->ncharts * sizeof(BoxPack), "BoxPack box");
+ if (phandle->aspx != phandle->aspy)
+ param_scale(handle, 1.0f / phandle->aspx, 1.0f / phandle->aspy);
+ /* we may not use all these boxes */
+ boxarray = MEM_mallocN(phandle->ncharts * sizeof(BoxPack), "BoxPack box");
- for (i = 0; i < phandle->ncharts; i++) {
- chart = phandle->charts[i];
+ for (i = 0; i < phandle->ncharts; i++) {
+ chart = phandle->charts[i];
- if (ignore_pinned && (chart->flag & PCHART_HAS_PINS)) {
- unpacked++;
- continue;
- }
+ if (ignore_pinned && (chart->flag & PCHART_HAS_PINS)) {
+ unpacked++;
+ continue;
+ }
- box = boxarray + (i - unpacked);
+ box = boxarray + (i - unpacked);
- p_chart_uv_bbox(chart, trans, chart->u.pack.size);
+ p_chart_uv_bbox(chart, trans, chart->u.pack.size);
- trans[0] = -trans[0];
- trans[1] = -trans[1];
+ trans[0] = -trans[0];
+ trans[1] = -trans[1];
- p_chart_uv_translate(chart, trans);
+ p_chart_uv_translate(chart, trans);
- box->w = chart->u.pack.size[0] + trans[0];
- box->h = chart->u.pack.size[1] + trans[1];
- box->index = i; /* warning this index skips PCHART_HAS_PINS boxes */
+ box->w = chart->u.pack.size[0] + trans[0];
+ box->h = chart->u.pack.size[1] + trans[1];
+ box->index = i; /* warning this index skips PCHART_HAS_PINS boxes */
- if (margin > 0.0f)
- area += (double)sqrtf(box->w * box->h);
- }
+ if (margin > 0.0f)
+ area += (double)sqrtf(box->w * box->h);
+ }
- if (margin > 0.0f) {
- /* multiply the margin by the area to give predictable results not dependent on UV scale,
- * ...Without using the area running pack multiple times also gives a bad feedback loop.
- * multiply by 0.1 so the margin value from the UI can be from
- * 0.0 to 1.0 but not give a massive margin */
- margin = (margin * (float)area) * 0.1f;
- unpacked = 0;
- for (i = 0; i < phandle->ncharts; i++) {
- chart = phandle->charts[i];
+ if (margin > 0.0f) {
+ /* multiply the margin by the area to give predictable results not dependent on UV scale,
+ * ...Without using the area running pack multiple times also gives a bad feedback loop.
+ * multiply by 0.1 so the margin value from the UI can be from
+ * 0.0 to 1.0 but not give a massive margin */
+ margin = (margin * (float)area) * 0.1f;
+ unpacked = 0;
+ for (i = 0; i < phandle->ncharts; i++) {
+ chart = phandle->charts[i];
- if (ignore_pinned && (chart->flag & PCHART_HAS_PINS)) {
- unpacked++;
- continue;
- }
+ if (ignore_pinned && (chart->flag & PCHART_HAS_PINS)) {
+ unpacked++;
+ continue;
+ }
- box = boxarray + (i - unpacked);
- trans[0] = margin;
- trans[1] = margin;
- p_chart_uv_translate(chart, trans);
- box->w += margin * 2;
- box->h += margin * 2;
- }
- }
+ box = boxarray + (i - unpacked);
+ trans[0] = margin;
+ trans[1] = margin;
+ p_chart_uv_translate(chart, trans);
+ box->w += margin * 2;
+ box->h += margin * 2;
+ }
+ }
- BLI_box_pack_2d(boxarray, phandle->ncharts - unpacked, &tot_width, &tot_height);
+ BLI_box_pack_2d(boxarray, phandle->ncharts - unpacked, &tot_width, &tot_height);
- if (tot_height > tot_width)
- scale = 1.0f / tot_height;
- else
- scale = 1.0f / tot_width;
+ if (tot_height > tot_width)
+ scale = 1.0f / tot_height;
+ else
+ scale = 1.0f / tot_width;
- for (i = 0; i < phandle->ncharts - unpacked; i++) {
- box = boxarray + i;
- trans[0] = box->x;
- trans[1] = box->y;
+ for (i = 0; i < phandle->ncharts - unpacked; i++) {
+ box = boxarray + i;
+ trans[0] = box->x;
+ trans[1] = box->y;
- chart = phandle->charts[box->index];
- p_chart_uv_translate(chart, trans);
- p_chart_uv_scale(chart, scale);
- }
- MEM_freeN(boxarray);
+ chart = phandle->charts[box->index];
+ p_chart_uv_translate(chart, trans);
+ p_chart_uv_scale(chart, scale);
+ }
+ MEM_freeN(boxarray);
- if (phandle->aspx != phandle->aspy)
- param_scale(handle, phandle->aspx, phandle->aspy);
+ if (phandle->aspx != phandle->aspy)
+ param_scale(handle, phandle->aspx, phandle->aspy);
}
void param_average(ParamHandle *handle, bool ignore_pinned)
{
- PChart *chart;
- int i;
- float tot_uvarea = 0.0f, tot_facearea = 0.0f;
- float tot_fac, fac;
- float minv[2], maxv[2], trans[2];
- PHandle *phandle = (PHandle *)handle;
+ PChart *chart;
+ int i;
+ float tot_uvarea = 0.0f, tot_facearea = 0.0f;
+ float tot_fac, fac;
+ float minv[2], maxv[2], trans[2];
+ PHandle *phandle = (PHandle *)handle;
- if (phandle->ncharts == 0)
- return;
+ if (phandle->ncharts == 0)
+ return;
- for (i = 0; i < phandle->ncharts; i++) {
- PFace *f;
- chart = phandle->charts[i];
+ for (i = 0; i < phandle->ncharts; i++) {
+ PFace *f;
+ chart = phandle->charts[i];
- if (ignore_pinned && (chart->flag & PCHART_HAS_PINS)) {
- continue;
- }
+ if (ignore_pinned && (chart->flag & PCHART_HAS_PINS)) {
+ continue;
+ }
- chart->u.pack.area = 0.0f; /* 3d area */
- chart->u.pack.rescale = 0.0f; /* UV area, abusing rescale for tmp storage, oh well :/ */
+ chart->u.pack.area = 0.0f; /* 3d area */
+ chart->u.pack.rescale = 0.0f; /* UV area, abusing rescale for tmp storage, oh well :/ */
- for (f = chart->faces; f; f = f->nextlink) {
- chart->u.pack.area += p_face_area(f);
- chart->u.pack.rescale += fabsf(p_face_uv_area_signed(f));
- }
+ for (f = chart->faces; f; f = f->nextlink) {
+ chart->u.pack.area += p_face_area(f);
+ chart->u.pack.rescale += fabsf(p_face_uv_area_signed(f));
+ }
- tot_facearea += chart->u.pack.area;
- tot_uvarea += chart->u.pack.rescale;
- }
+ tot_facearea += chart->u.pack.area;
+ tot_uvarea += chart->u.pack.rescale;
+ }
- if (tot_facearea == tot_uvarea || tot_facearea == 0.0f || tot_uvarea == 0.0f) {
- /* nothing to do */
- return;
- }
+ if (tot_facearea == tot_uvarea || tot_facearea == 0.0f || tot_uvarea == 0.0f) {
+ /* nothing to do */
+ return;
+ }
- tot_fac = tot_facearea / tot_uvarea;
+ tot_fac = tot_facearea / tot_uvarea;
- for (i = 0; i < phandle->ncharts; i++) {
- chart = phandle->charts[i];
+ for (i = 0; i < phandle->ncharts; i++) {
+ chart = phandle->charts[i];
- if (ignore_pinned && (chart->flag & PCHART_HAS_PINS)) {
- continue;
- }
+ if (ignore_pinned && (chart->flag & PCHART_HAS_PINS)) {
+ continue;
+ }
- if (chart->u.pack.area != 0.0f && chart->u.pack.rescale != 0.0f) {
- fac = chart->u.pack.area / chart->u.pack.rescale;
+ if (chart->u.pack.area != 0.0f && chart->u.pack.rescale != 0.0f) {
+ fac = chart->u.pack.area / chart->u.pack.rescale;
- /* Get the island center */
- p_chart_uv_bbox(chart, minv, maxv);
- trans[0] = (minv[0] + maxv[0]) / -2.0f;
- trans[1] = (minv[1] + maxv[1]) / -2.0f;
+ /* Get the island center */
+ p_chart_uv_bbox(chart, minv, maxv);
+ trans[0] = (minv[0] + maxv[0]) / -2.0f;
+ trans[1] = (minv[1] + maxv[1]) / -2.0f;
- /* Move center to 0,0 */
- p_chart_uv_translate(chart, trans);
- p_chart_uv_scale(chart, sqrtf(fac / tot_fac));
+ /* Move center to 0,0 */
+ p_chart_uv_translate(chart, trans);
+ p_chart_uv_scale(chart, sqrtf(fac / tot_fac));
- /* Move to original center */
- trans[0] = -trans[0];
- trans[1] = -trans[1];
- p_chart_uv_translate(chart, trans);
- }
- }
+ /* Move to original center */
+ trans[0] = -trans[0];
+ trans[1] = -trans[1];
+ p_chart_uv_translate(chart, trans);
+ }
+ }
}
void param_scale(ParamHandle *handle, float x, float y)
{
- PHandle *phandle = (PHandle *)handle;
- PChart *chart;
- int i;
+ PHandle *phandle = (PHandle *)handle;
+ PChart *chart;
+ int i;
- for (i = 0; i < phandle->ncharts; i++) {
- chart = phandle->charts[i];
- p_chart_uv_scale_xy(chart, x, y);
- }
+ for (i = 0; i < phandle->ncharts; i++) {
+ chart = phandle->charts[i];
+ p_chart_uv_scale_xy(chart, x, y);
+ }
}
void param_flush(ParamHandle *handle)
{
- PHandle *phandle = (PHandle *)handle;
- PChart *chart;
- int i;
+ PHandle *phandle = (PHandle *)handle;
+ PChart *chart;
+ int i;
- for (i = 0; i < phandle->ncharts; i++) {
- chart = phandle->charts[i];
+ for (i = 0; i < phandle->ncharts; i++) {
+ chart = phandle->charts[i];
- if ((phandle->state == PHANDLE_STATE_LSCM) && !chart->u.lscm.context)
- continue;
+ if ((phandle->state == PHANDLE_STATE_LSCM) && !chart->u.lscm.context)
+ continue;
- if (phandle->blend == 0.0f)
- p_flush_uvs(phandle, chart);
- else
- p_flush_uvs_blend(phandle, chart, phandle->blend);
- }
+ if (phandle->blend == 0.0f)
+ p_flush_uvs(phandle, chart);
+ else
+ p_flush_uvs_blend(phandle, chart, phandle->blend);
+ }
}
void param_flush_restore(ParamHandle *handle)
{
- PHandle *phandle = (PHandle *)handle;
- PChart *chart;
- PFace *f;
- int i;
+ PHandle *phandle = (PHandle *)handle;
+ PChart *chart;
+ PFace *f;
+ int i;
- for (i = 0; i < phandle->ncharts; i++) {
- chart = phandle->charts[i];
+ for (i = 0; i < phandle->ncharts; i++) {
+ chart = phandle->charts[i];
- for (f = chart->faces; f; f = f->nextlink)
- p_face_restore_uvs(f);
- }
+ for (f = chart->faces; f; f = f->nextlink)
+ p_face_restore_uvs(f);
+ }
}
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.h b/source/blender/editors/uvedit/uvedit_parametrizer.h
index 6724b568f57..2b80241e6e3 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.h
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.h
@@ -25,13 +25,13 @@
extern "C" {
#endif
-#include "BLI_sys_types.h" // for intptr_t support
+#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 void ParamHandle; /* handle to a set of charts */
+typedef intptr_t ParamKey; /* (hash) key for identifying verts and faces */
typedef enum ParamBool {
- PARAM_TRUE = 1,
- PARAM_FALSE = 0,
+ PARAM_TRUE = 1,
+ PARAM_FALSE = 0,
} ParamBool;
/* Chart construction:
@@ -58,8 +58,7 @@ void param_face_add(ParamHandle *handle,
ParamBool *pin,
ParamBool *select);
-void param_edge_set_seam(ParamHandle *handle,
- ParamKey *vkeys);
+void param_edge_set_seam(ParamHandle *handle, ParamKey *vkeys);
void param_construct_end(ParamHandle *handle, ParamBool fill, ParamBool impl);
void param_delete(ParamHandle *chart);
@@ -107,7 +106,6 @@ void param_scale(ParamHandle *handle, float x, float y);
void param_flush(ParamHandle *handle);
void param_flush_restore(ParamHandle *handle);
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index 91167e247f4..71a3fdf055e 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -21,7 +21,6 @@
* \ingroup eduv
*/
-
#include <stdlib.h>
#include <string.h>
#include <math.h>
@@ -73,26 +72,25 @@
/* object that stores display data for previewing before confirming stitching */
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;
- /*number of preview polygons */
- unsigned int 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;
- /* ...and here we'll store the static island triangles */
- float *static_tris;
- unsigned int num_static_tris;
+ /* here we'll store the preview triangle indices of the mesh */
+ float *preview_polys;
+ /* uvs per polygon. */
+ unsigned int *uvs_per_polygon;
+ /*number of preview polygons */
+ unsigned int 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;
+ /* ...and here we'll store the static island triangles */
+ float *static_tris;
+ unsigned int num_static_tris;
} StitchPreviewer;
-
struct IslandStitchData;
/**
@@ -101,115 +99,114 @@ struct IslandStitchData;
* elements of the island except from the stitchable.
*/
typedef struct IslandStitchData {
- /* rotation can be used only for edges, for vertices there is no such notion */
- float rotation;
- float rotation_neg;
- float translation[2];
- /* Used for rotation, the island will rotate around this point */
- float medianPoint[2];
- int numOfElements;
- int num_rot_elements;
- int num_rot_elements_neg;
- /* flag to remember if island has been added for preview */
- char addedForPreview;
- /* flag an island to be considered for determining static island */
- char stitchableCandidate;
- /* if edge rotation is used, flag so that vertex rotation is not used */
- bool use_edge_rotation;
+ /* rotation can be used only for edges, for vertices there is no such notion */
+ float rotation;
+ float rotation_neg;
+ float translation[2];
+ /* Used for rotation, the island will rotate around this point */
+ float medianPoint[2];
+ int numOfElements;
+ int num_rot_elements;
+ int num_rot_elements_neg;
+ /* flag to remember if island has been added for preview */
+ char addedForPreview;
+ /* flag an island to be considered for determining static island */
+ char stitchableCandidate;
+ /* if edge rotation is used, flag so that vertex rotation is not used */
+ bool use_edge_rotation;
} IslandStitchData;
/* just for averaging UVs */
typedef struct UVVertAverage {
- float uv[2];
- unsigned short count;
+ float uv[2];
+ unsigned short count;
} UVVertAverage;
typedef struct UvEdge {
- /** index to uv buffer */
- unsigned int uv1;
- unsigned int uv2;
- /** general use flag
- * (Used to check if edge is boundary here, and propagates to adjacency elements) */
- unsigned char flag;
- /** element that guarantees element->face
- * has the edge on element->tfindex and element->tfindex+1 is the second uv */
- UvElement *element;
- /** next uv edge with the same exact vertices as this one.
- * Calculated at startup to save time */
- struct UvEdge *next;
- /** point to first of common edges. Needed for iteration */
- struct UvEdge *first;
+ /** index to uv buffer */
+ unsigned int uv1;
+ unsigned int uv2;
+ /** general use flag
+ * (Used to check if edge is boundary here, and propagates to adjacency elements) */
+ unsigned char flag;
+ /** element that guarantees element->face
+ * has the edge on element->tfindex and element->tfindex+1 is the second uv */
+ UvElement *element;
+ /** next uv edge with the same exact vertices as this one.
+ * Calculated at startup to save time */
+ struct UvEdge *next;
+ /** point to first of common edges. Needed for iteration */
+ struct UvEdge *first;
} UvEdge;
-
/* stitch state object */
typedef struct StitchState {
- float aspect;
- /* object for editmesh */
- Object *obedit;
- /* editmesh, cached for use in modal handler */
- BMEditMesh *em;
-
- /* element map for getting info about uv connectivity */
- UvElementMap *element_map;
- /* edge container */
- UvEdge *uvedges;
- /* container of first of a group of coincident uvs, these will be operated upon */
- UvElement **uvs;
- /* maps uvelements to their first coincident uv */
- int *map;
- /* 2D normals per uv to calculate rotation for snapping */
- float *normals;
- /* edge storage */
- UvEdge *edges;
- /* hash for quick lookup of edges */
- GHash *edge_hash;
- /* which islands to stop at (to make active) when pressing 'I' */
- bool *island_is_stitchable;
-
- /* count of separate uvs and edges */
- int total_separate_edges;
- int total_separate_uvs;
- /* hold selection related information */
- void **selection_stack;
- int selection_size;
-
- /* store number of primitives per face so that we can allocate the active island buffer later */
- unsigned int *tris_per_island;
- /* preview data */
- StitchPreviewer *stitch_preview;
+ float aspect;
+ /* object for editmesh */
+ Object *obedit;
+ /* editmesh, cached for use in modal handler */
+ BMEditMesh *em;
+
+ /* element map for getting info about uv connectivity */
+ UvElementMap *element_map;
+ /* edge container */
+ UvEdge *uvedges;
+ /* container of first of a group of coincident uvs, these will be operated upon */
+ UvElement **uvs;
+ /* maps uvelements to their first coincident uv */
+ int *map;
+ /* 2D normals per uv to calculate rotation for snapping */
+ float *normals;
+ /* edge storage */
+ UvEdge *edges;
+ /* hash for quick lookup of edges */
+ GHash *edge_hash;
+ /* which islands to stop at (to make active) when pressing 'I' */
+ bool *island_is_stitchable;
+
+ /* count of separate uvs and edges */
+ int total_separate_edges;
+ int total_separate_uvs;
+ /* hold selection related information */
+ void **selection_stack;
+ int selection_size;
+
+ /* store number of primitives per face so that we can allocate the active island buffer later */
+ unsigned int *tris_per_island;
+ /* preview data */
+ StitchPreviewer *stitch_preview;
} StitchState;
/* Stitch state container. */
typedef struct StitchStateContainer {
- /* clear seams of stitched edges after stitch */
- bool clear_seams;
- /* use limit flag */
- bool use_limit;
- /* limit to operator, same as original operator */
- float limit_dist;
- /* snap uv islands together during stitching */
- bool snap_islands;
- /* stitch at midpoints or at islands */
- bool midpoints;
- /* vert or edge mode used for stitching */
- char mode;
- /* handle for drawing */
- void *draw_handle;
- /* island that stays in place */
- int static_island;
-
- /* Objects and states are aligned. */
- int objects_len;
- Object **objects;
- StitchState **states;
-
- int active_object_index;
+ /* clear seams of stitched edges after stitch */
+ bool clear_seams;
+ /* use limit flag */
+ bool use_limit;
+ /* limit to operator, same as original operator */
+ float limit_dist;
+ /* snap uv islands together during stitching */
+ bool snap_islands;
+ /* stitch at midpoints or at islands */
+ bool midpoints;
+ /* vert or edge mode used for stitching */
+ char mode;
+ /* handle for drawing */
+ void *draw_handle;
+ /* island that stays in place */
+ int static_island;
+
+ /* Objects and states are aligned. */
+ int objects_len;
+ Object **objects;
+ StitchState **states;
+
+ int active_object_index;
} StitchStateContainer;
typedef struct PreviewPosition {
- int data_position;
- int polycount_position;
+ int data_position;
+ int polycount_position;
} PreviewPosition;
/*
* defines for UvElement/UcEdge flags
@@ -223,2529 +220,2614 @@ typedef struct PreviewPosition {
#define STITCH_NO_PREVIEW -1
enum StitchModes {
- STITCH_VERT,
- STITCH_EDGE,
+ STITCH_VERT,
+ STITCH_EDGE,
};
/* UvElement identification. */
typedef struct UvElementID {
- int faceIndex;
- int elementIndex;
+ int faceIndex;
+ int elementIndex;
} UvElementID;
/* StitchState initializition. */
typedef struct StitchStateInit {
- int uv_selected_count;
- UvElementID *to_select;
+ int uv_selected_count;
+ UvElementID *to_select;
} StitchStateInit;
/* constructor */
static StitchPreviewer *stitch_preview_init(void)
{
- StitchPreviewer *stitch_preview;
+ StitchPreviewer *stitch_preview;
- stitch_preview = MEM_mallocN(sizeof(StitchPreviewer), "stitch_previewer");
- stitch_preview->preview_polys = NULL;
- stitch_preview->preview_stitchable = NULL;
- stitch_preview->preview_unstitchable = NULL;
- stitch_preview->uvs_per_polygon = NULL;
+ stitch_preview = MEM_mallocN(sizeof(StitchPreviewer), "stitch_previewer");
+ stitch_preview->preview_polys = NULL;
+ stitch_preview->preview_stitchable = NULL;
+ stitch_preview->preview_unstitchable = NULL;
+ stitch_preview->uvs_per_polygon = NULL;
- stitch_preview->preview_uvs = 0;
- stitch_preview->num_polys = 0;
- stitch_preview->num_stitchable = 0;
- stitch_preview->num_unstitchable = 0;
+ stitch_preview->preview_uvs = 0;
+ stitch_preview->num_polys = 0;
+ stitch_preview->num_stitchable = 0;
+ stitch_preview->num_unstitchable = 0;
- stitch_preview->static_tris = NULL;
+ stitch_preview->static_tris = NULL;
- stitch_preview->num_static_tris = 0;
+ stitch_preview->num_static_tris = 0;
- return stitch_preview;
+ return stitch_preview;
}
/* destructor...yeah this should be C++ :) */
static void stitch_preview_delete(StitchPreviewer *stitch_preview)
{
- if (stitch_preview) {
- if (stitch_preview->preview_polys) {
- MEM_freeN(stitch_preview->preview_polys);
- stitch_preview->preview_polys = NULL;
- }
- if (stitch_preview->uvs_per_polygon) {
- MEM_freeN(stitch_preview->uvs_per_polygon);
- stitch_preview->uvs_per_polygon = NULL;
- }
- if (stitch_preview->preview_stitchable) {
- MEM_freeN(stitch_preview->preview_stitchable);
- stitch_preview->preview_stitchable = NULL;
- }
- if (stitch_preview->preview_unstitchable) {
- MEM_freeN(stitch_preview->preview_unstitchable);
- stitch_preview->preview_unstitchable = NULL;
- }
- if (stitch_preview->static_tris) {
- MEM_freeN(stitch_preview->static_tris);
- stitch_preview->static_tris = NULL;
- }
- MEM_freeN(stitch_preview);
- }
+ if (stitch_preview) {
+ if (stitch_preview->preview_polys) {
+ MEM_freeN(stitch_preview->preview_polys);
+ stitch_preview->preview_polys = NULL;
+ }
+ if (stitch_preview->uvs_per_polygon) {
+ MEM_freeN(stitch_preview->uvs_per_polygon);
+ stitch_preview->uvs_per_polygon = NULL;
+ }
+ if (stitch_preview->preview_stitchable) {
+ MEM_freeN(stitch_preview->preview_stitchable);
+ stitch_preview->preview_stitchable = NULL;
+ }
+ if (stitch_preview->preview_unstitchable) {
+ MEM_freeN(stitch_preview->preview_unstitchable);
+ stitch_preview->preview_unstitchable = NULL;
+ }
+ if (stitch_preview->static_tris) {
+ MEM_freeN(stitch_preview->static_tris);
+ stitch_preview->static_tris = NULL;
+ }
+ MEM_freeN(stitch_preview);
+ }
}
/* This function updates the header of the UV editor when the stitch tool updates its settings */
static void stitch_update_header(StitchStateContainer *ssc, bContext *C)
{
- const char *str = IFACE_(
- "Mode(TAB) %s, "
- "(S)nap %s, "
- "(M)idpoints %s, "
- "(L)imit %.2f (Alt Wheel adjust) %s, "
- "Switch (I)sland, "
- "shift select vertices"
- );
-
- char msg[UI_MAX_DRAW_STR];
- ScrArea *sa = CTX_wm_area(C);
-
- if (sa) {
- BLI_snprintf(
- msg, sizeof(msg), str,
- ssc->mode == STITCH_VERT ? IFACE_("Vertex") : IFACE_("Edge"),
- WM_bool_as_string(ssc->snap_islands),
- WM_bool_as_string(ssc->midpoints),
- ssc->limit_dist,
- WM_bool_as_string(ssc->use_limit));
-
- ED_workspace_status_text(C, msg);
- }
+ const char *str = IFACE_(
+ "Mode(TAB) %s, "
+ "(S)nap %s, "
+ "(M)idpoints %s, "
+ "(L)imit %.2f (Alt Wheel adjust) %s, "
+ "Switch (I)sland, "
+ "shift select vertices");
+
+ char msg[UI_MAX_DRAW_STR];
+ ScrArea *sa = CTX_wm_area(C);
+
+ if (sa) {
+ BLI_snprintf(msg,
+ sizeof(msg),
+ str,
+ ssc->mode == STITCH_VERT ? IFACE_("Vertex") : IFACE_("Edge"),
+ WM_bool_as_string(ssc->snap_islands),
+ WM_bool_as_string(ssc->midpoints),
+ ssc->limit_dist,
+ WM_bool_as_string(ssc->use_limit));
+
+ ED_workspace_status_text(C, msg);
+ }
}
static int getNumOfIslandUvs(UvElementMap *elementMap, int island)
{
- if (island == elementMap->totalIslands - 1) {
- return elementMap->totalUVs - elementMap->islandIndices[island];
- }
- else {
- return elementMap->islandIndices[island + 1] - elementMap->islandIndices[island];
- }
+ if (island == elementMap->totalIslands - 1) {
+ return elementMap->totalUVs - elementMap->islandIndices[island];
+ }
+ else {
+ return elementMap->islandIndices[island + 1] - elementMap->islandIndices[island];
+ }
}
static void stitch_uv_rotate(float mat[2][2], float medianPoint[2], float uv[2], float aspect)
{
- float uv_rotation_result[2];
+ float uv_rotation_result[2];
- uv[1] /= aspect;
+ uv[1] /= aspect;
- sub_v2_v2(uv, medianPoint);
- mul_v2_m2v2(uv_rotation_result, mat, uv);
- add_v2_v2v2(uv, uv_rotation_result, medianPoint);
+ sub_v2_v2(uv, medianPoint);
+ mul_v2_m2v2(uv_rotation_result, mat, uv);
+ add_v2_v2v2(uv, uv_rotation_result, medianPoint);
- uv[1] *= aspect;
+ uv[1] *= aspect;
}
/* check if two uvelements are stitchable.
* This should only operate on -different- separate UvElements */
-static bool stitch_check_uvs_stitchable(
- UvElement *element, UvElement *element_iter,
- StitchStateContainer *ssc, StitchState *state)
+static bool stitch_check_uvs_stitchable(UvElement *element,
+ UvElement *element_iter,
+ StitchStateContainer *ssc,
+ StitchState *state)
{
- BMesh *bm = state->em->bm;
- float limit;
-
- if (element_iter == element) {
- return 0;
- }
-
- limit = ssc->limit_dist;
-
- if (ssc->use_limit) {
- MLoopUV *luv, *luv_iter;
- BMLoop *l;
-
-
- l = element->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
- l = element_iter->l;
- luv_iter = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
-
- if (fabsf(luv->uv[0] - luv_iter->uv[0]) < limit &&
- fabsf(luv->uv[1] - luv_iter->uv[1]) < limit)
- {
- return 1;
- }
- else {
- return 0;
- }
- }
- else {
- return 1;
- }
+ BMesh *bm = state->em->bm;
+ float limit;
+
+ if (element_iter == element) {
+ return 0;
+ }
+
+ limit = ssc->limit_dist;
+
+ if (ssc->use_limit) {
+ MLoopUV *luv, *luv_iter;
+ BMLoop *l;
+
+ l = element->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ l = element_iter->l;
+ luv_iter = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (fabsf(luv->uv[0] - luv_iter->uv[0]) < limit &&
+ fabsf(luv->uv[1] - luv_iter->uv[1]) < limit) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+ }
+ else {
+ return 1;
+ }
}
-static bool stitch_check_edges_stitchable(
- UvEdge *edge, UvEdge *edge_iter,
- StitchStateContainer *ssc, StitchState *state)
+static bool stitch_check_edges_stitchable(UvEdge *edge,
+ UvEdge *edge_iter,
+ StitchStateContainer *ssc,
+ StitchState *state)
{
- BMesh *bm = state->em->bm;
- float limit;
-
- if (edge_iter == edge) {
- return 0;
- }
-
- limit = ssc->limit_dist;
-
- if (ssc->use_limit) {
- BMLoop *l;
- MLoopUV *luv_orig1, *luv_iter1;
- MLoopUV *luv_orig2, *luv_iter2;
-
- l = state->uvs[edge->uv1]->l;
- luv_orig1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
- l = state->uvs[edge_iter->uv1]->l;
- luv_iter1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
-
- l = state->uvs[edge->uv2]->l;
- luv_orig2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
- l = state->uvs[edge_iter->uv2]->l;
- luv_iter2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
-
- if (fabsf(luv_orig1->uv[0] - luv_iter1->uv[0]) < limit &&
- fabsf(luv_orig1->uv[1] - luv_iter1->uv[1]) < limit &&
- fabsf(luv_orig2->uv[0] - luv_iter2->uv[0]) < limit &&
- fabsf(luv_orig2->uv[1] - luv_iter2->uv[1]) < limit)
- {
- return 1;
- }
- else {
- return 0;
- }
- }
- else {
- return 1;
- }
+ BMesh *bm = state->em->bm;
+ float limit;
+
+ if (edge_iter == edge) {
+ return 0;
+ }
+
+ limit = ssc->limit_dist;
+
+ if (ssc->use_limit) {
+ BMLoop *l;
+ MLoopUV *luv_orig1, *luv_iter1;
+ MLoopUV *luv_orig2, *luv_iter2;
+
+ l = state->uvs[edge->uv1]->l;
+ luv_orig1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ l = state->uvs[edge_iter->uv1]->l;
+ luv_iter1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+
+ l = state->uvs[edge->uv2]->l;
+ luv_orig2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ l = state->uvs[edge_iter->uv2]->l;
+ luv_iter2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (fabsf(luv_orig1->uv[0] - luv_iter1->uv[0]) < limit &&
+ fabsf(luv_orig1->uv[1] - luv_iter1->uv[1]) < limit &&
+ fabsf(luv_orig2->uv[0] - luv_iter2->uv[0]) < limit &&
+ fabsf(luv_orig2->uv[1] - luv_iter2->uv[1]) < limit) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+ }
+ else {
+ return 1;
+ }
}
-static bool stitch_check_uvs_state_stitchable(
- UvElement *element, UvElement *element_iter,
- StitchStateContainer *ssc, StitchState *state)
+static bool stitch_check_uvs_state_stitchable(UvElement *element,
+ UvElement *element_iter,
+ StitchStateContainer *ssc,
+ StitchState *state)
{
- if ((ssc->snap_islands && element->island == element_iter->island) ||
- (!ssc->midpoints && element->island == element_iter->island))
- {
- return 0;
- }
+ if ((ssc->snap_islands && element->island == element_iter->island) ||
+ (!ssc->midpoints && element->island == element_iter->island)) {
+ return 0;
+ }
- return stitch_check_uvs_stitchable(element, element_iter, ssc, state);
+ return stitch_check_uvs_stitchable(element, element_iter, ssc, state);
}
-static bool stitch_check_edges_state_stitchable(
- UvEdge *edge, UvEdge *edge_iter,
- StitchStateContainer *ssc, StitchState *state)
+static bool stitch_check_edges_state_stitchable(UvEdge *edge,
+ UvEdge *edge_iter,
+ StitchStateContainer *ssc,
+ StitchState *state)
{
- if ((ssc->snap_islands && edge->element->island == edge_iter->element->island) ||
- (!ssc->midpoints && edge->element->island == edge_iter->element->island))
- {
- return 0;
- }
+ if ((ssc->snap_islands && edge->element->island == edge_iter->element->island) ||
+ (!ssc->midpoints && edge->element->island == edge_iter->element->island)) {
+ return 0;
+ }
- return stitch_check_edges_stitchable(edge, edge_iter, ssc, state);
+ return stitch_check_edges_stitchable(edge, edge_iter, ssc, state);
}
/* calculate snapping for islands */
-static void stitch_calculate_island_snapping(
- StitchState *state, PreviewPosition *preview_position, StitchPreviewer *preview,
- IslandStitchData *island_stitch_data, int final)
+static void stitch_calculate_island_snapping(StitchState *state,
+ PreviewPosition *preview_position,
+ StitchPreviewer *preview,
+ IslandStitchData *island_stitch_data,
+ int final)
{
- BMesh *bm = state->em->bm;
- int i;
- UvElement *element;
-
- for (i = 0; i < state->element_map->totalIslands; i++) {
- if (island_stitch_data[i].addedForPreview) {
- int numOfIslandUVs = 0, j;
- int totelem = island_stitch_data[i].num_rot_elements_neg + island_stitch_data[i].num_rot_elements;
- float rotation;
- float rotation_mat[2][2];
-
- /* check to avoid divide by 0 */
- if (island_stitch_data[i].num_rot_elements > 1)
- island_stitch_data[i].rotation /= island_stitch_data[i].num_rot_elements;
-
- if (island_stitch_data[i].num_rot_elements_neg > 1)
- island_stitch_data[i].rotation_neg /= island_stitch_data[i].num_rot_elements_neg;
-
- if (island_stitch_data[i].numOfElements > 1) {
- island_stitch_data[i].medianPoint[0] /= island_stitch_data[i].numOfElements;
- island_stitch_data[i].medianPoint[1] /= island_stitch_data[i].numOfElements;
-
- island_stitch_data[i].translation[0] /= island_stitch_data[i].numOfElements;
- island_stitch_data[i].translation[1] /= island_stitch_data[i].numOfElements;
- }
-
- island_stitch_data[i].medianPoint[1] /= state->aspect;
- if ((island_stitch_data[i].rotation + island_stitch_data[i].rotation_neg < (float)M_PI_2) ||
- island_stitch_data[i].num_rot_elements == 0 || island_stitch_data[i].num_rot_elements_neg == 0)
- {
- rotation = (island_stitch_data[i].rotation * island_stitch_data[i].num_rot_elements -
- island_stitch_data[i].rotation_neg *
- island_stitch_data[i].num_rot_elements_neg) / totelem;
- }
- else {
- rotation = (island_stitch_data[i].rotation * island_stitch_data[i].num_rot_elements +
- (2.0f * (float)M_PI - island_stitch_data[i].rotation_neg) *
- island_stitch_data[i].num_rot_elements_neg) / totelem;
- }
-
- angle_to_mat2(rotation_mat, rotation);
- numOfIslandUVs = getNumOfIslandUvs(state->element_map, i);
- element = &state->element_map->buf[state->element_map->islandIndices[i]];
- for (j = 0; j < numOfIslandUVs; j++, element++) {
- /* stitchable uvs have already been processed, don't process */
- if (!(element->flag & STITCH_PROCESSED)) {
- MLoopUV *luv;
- BMLoop *l;
-
- l = element->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
-
- if (final) {
-
- stitch_uv_rotate(rotation_mat, island_stitch_data[i].medianPoint, luv->uv, state->aspect);
-
- add_v2_v2(luv->uv, island_stitch_data[i].translation);
- }
-
- else {
-
- int face_preview_pos = preview_position[BM_elem_index_get(element->l->f)].data_position;
-
- stitch_uv_rotate(rotation_mat, island_stitch_data[i].medianPoint,
- preview->preview_polys + face_preview_pos + 2 * element->loop_of_poly_index,
- state->aspect);
-
- add_v2_v2(preview->preview_polys + face_preview_pos + 2 * element->loop_of_poly_index,
- island_stitch_data[i].translation);
- }
- }
- /* cleanup */
- element->flag &= STITCH_SELECTED;
- }
- }
- }
+ BMesh *bm = state->em->bm;
+ int i;
+ UvElement *element;
+
+ for (i = 0; i < state->element_map->totalIslands; i++) {
+ if (island_stitch_data[i].addedForPreview) {
+ int numOfIslandUVs = 0, j;
+ int totelem = island_stitch_data[i].num_rot_elements_neg +
+ island_stitch_data[i].num_rot_elements;
+ float rotation;
+ float rotation_mat[2][2];
+
+ /* check to avoid divide by 0 */
+ if (island_stitch_data[i].num_rot_elements > 1)
+ island_stitch_data[i].rotation /= island_stitch_data[i].num_rot_elements;
+
+ if (island_stitch_data[i].num_rot_elements_neg > 1)
+ island_stitch_data[i].rotation_neg /= island_stitch_data[i].num_rot_elements_neg;
+
+ if (island_stitch_data[i].numOfElements > 1) {
+ island_stitch_data[i].medianPoint[0] /= island_stitch_data[i].numOfElements;
+ island_stitch_data[i].medianPoint[1] /= island_stitch_data[i].numOfElements;
+
+ island_stitch_data[i].translation[0] /= island_stitch_data[i].numOfElements;
+ island_stitch_data[i].translation[1] /= island_stitch_data[i].numOfElements;
+ }
+
+ island_stitch_data[i].medianPoint[1] /= state->aspect;
+ if ((island_stitch_data[i].rotation + island_stitch_data[i].rotation_neg < (float)M_PI_2) ||
+ island_stitch_data[i].num_rot_elements == 0 ||
+ island_stitch_data[i].num_rot_elements_neg == 0) {
+ rotation = (island_stitch_data[i].rotation * island_stitch_data[i].num_rot_elements -
+ island_stitch_data[i].rotation_neg *
+ island_stitch_data[i].num_rot_elements_neg) /
+ totelem;
+ }
+ else {
+ rotation = (island_stitch_data[i].rotation * island_stitch_data[i].num_rot_elements +
+ (2.0f * (float)M_PI - island_stitch_data[i].rotation_neg) *
+ island_stitch_data[i].num_rot_elements_neg) /
+ totelem;
+ }
+
+ angle_to_mat2(rotation_mat, rotation);
+ numOfIslandUVs = getNumOfIslandUvs(state->element_map, i);
+ element = &state->element_map->buf[state->element_map->islandIndices[i]];
+ for (j = 0; j < numOfIslandUVs; j++, element++) {
+ /* stitchable uvs have already been processed, don't process */
+ if (!(element->flag & STITCH_PROCESSED)) {
+ MLoopUV *luv;
+ BMLoop *l;
+
+ l = element->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (final) {
+
+ stitch_uv_rotate(
+ rotation_mat, island_stitch_data[i].medianPoint, luv->uv, state->aspect);
+
+ add_v2_v2(luv->uv, island_stitch_data[i].translation);
+ }
+
+ else {
+
+ int face_preview_pos =
+ preview_position[BM_elem_index_get(element->l->f)].data_position;
+
+ stitch_uv_rotate(rotation_mat,
+ island_stitch_data[i].medianPoint,
+ preview->preview_polys + face_preview_pos +
+ 2 * element->loop_of_poly_index,
+ state->aspect);
+
+ add_v2_v2(preview->preview_polys + face_preview_pos + 2 * element->loop_of_poly_index,
+ island_stitch_data[i].translation);
+ }
+ }
+ /* cleanup */
+ element->flag &= STITCH_SELECTED;
+ }
+ }
+ }
}
-
-
-static void stitch_island_calculate_edge_rotation(
- UvEdge *edge, StitchStateContainer *ssc, StitchState *state, UVVertAverage *uv_average,
- unsigned int *uvfinal_map, IslandStitchData *island_stitch_data)
+static void stitch_island_calculate_edge_rotation(UvEdge *edge,
+ StitchStateContainer *ssc,
+ StitchState *state,
+ UVVertAverage *uv_average,
+ unsigned int *uvfinal_map,
+ IslandStitchData *island_stitch_data)
{
- BMesh *bm = state->em->bm;
- UvElement *element1, *element2;
- float uv1[2], uv2[2];
- float edgecos, edgesin;
- int index1, index2;
- float rotation;
- MLoopUV *luv1, *luv2;
-
- element1 = state->uvs[edge->uv1];
- element2 = state->uvs[edge->uv2];
-
- luv1 = CustomData_bmesh_get(&bm->ldata, element1->l->head.data, CD_MLOOPUV);
- luv2 = CustomData_bmesh_get(&bm->ldata, element2->l->head.data, CD_MLOOPUV);
-
- if (ssc->mode == STITCH_VERT) {
- index1 = uvfinal_map[element1 - state->element_map->buf];
- index2 = uvfinal_map[element2 - state->element_map->buf];
- }
- else {
- index1 = edge->uv1;
- index2 = edge->uv2;
- }
- /* the idea here is to take the directions of the edges and find the rotation between
- * final and initial direction. This, using inner and outer vector products,
- * gives the angle. Directions are differences so... */
- uv1[0] = luv2->uv[0] - luv1->uv[0];
- uv1[1] = luv2->uv[1] - luv1->uv[1];
-
- uv1[1] /= state->aspect;
-
- uv2[0] = uv_average[index2].uv[0] - uv_average[index1].uv[0];
- uv2[1] = uv_average[index2].uv[1] - uv_average[index1].uv[1];
-
- uv2[1] /= state->aspect;
-
- normalize_v2(uv1);
- normalize_v2(uv2);
-
- edgecos = dot_v2v2(uv1, uv2);
- edgesin = cross_v2v2(uv1, uv2);
- rotation = acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
-
- if (edgesin > 0.0f) {
- island_stitch_data[element1->island].num_rot_elements++;
- island_stitch_data[element1->island].rotation += rotation;
- }
- else {
- island_stitch_data[element1->island].num_rot_elements_neg++;
- island_stitch_data[element1->island].rotation_neg += rotation;
- }
+ BMesh *bm = state->em->bm;
+ UvElement *element1, *element2;
+ float uv1[2], uv2[2];
+ float edgecos, edgesin;
+ int index1, index2;
+ float rotation;
+ MLoopUV *luv1, *luv2;
+
+ element1 = state->uvs[edge->uv1];
+ element2 = state->uvs[edge->uv2];
+
+ luv1 = CustomData_bmesh_get(&bm->ldata, element1->l->head.data, CD_MLOOPUV);
+ luv2 = CustomData_bmesh_get(&bm->ldata, element2->l->head.data, CD_MLOOPUV);
+
+ if (ssc->mode == STITCH_VERT) {
+ index1 = uvfinal_map[element1 - state->element_map->buf];
+ index2 = uvfinal_map[element2 - state->element_map->buf];
+ }
+ else {
+ index1 = edge->uv1;
+ index2 = edge->uv2;
+ }
+ /* the idea here is to take the directions of the edges and find the rotation between
+ * final and initial direction. This, using inner and outer vector products,
+ * gives the angle. Directions are differences so... */
+ uv1[0] = luv2->uv[0] - luv1->uv[0];
+ uv1[1] = luv2->uv[1] - luv1->uv[1];
+
+ uv1[1] /= state->aspect;
+
+ uv2[0] = uv_average[index2].uv[0] - uv_average[index1].uv[0];
+ uv2[1] = uv_average[index2].uv[1] - uv_average[index1].uv[1];
+
+ uv2[1] /= state->aspect;
+
+ normalize_v2(uv1);
+ normalize_v2(uv2);
+
+ edgecos = dot_v2v2(uv1, uv2);
+ edgesin = cross_v2v2(uv1, uv2);
+ rotation = acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
+
+ if (edgesin > 0.0f) {
+ island_stitch_data[element1->island].num_rot_elements++;
+ island_stitch_data[element1->island].rotation += rotation;
+ }
+ else {
+ island_stitch_data[element1->island].num_rot_elements_neg++;
+ island_stitch_data[element1->island].rotation_neg += rotation;
+ }
}
-
-static void stitch_island_calculate_vert_rotation(
- UvElement *element, StitchStateContainer *ssc, StitchState *state,
- IslandStitchData *island_stitch_data)
+static void stitch_island_calculate_vert_rotation(UvElement *element,
+ StitchStateContainer *ssc,
+ StitchState *state,
+ IslandStitchData *island_stitch_data)
{
- float edgecos = 1.0f, edgesin = 0.0f;
- int index;
- UvElement *element_iter;
- float rotation = 0, rotation_neg = 0;
- int rot_elem = 0, rot_elem_neg = 0;
- BMLoop *l;
-
- if (element->island == ssc->static_island && !ssc->midpoints)
- return;
-
- l = element->l;
-
- index = BM_elem_index_get(l->v);
-
- element_iter = state->element_map->vert[index];
-
- for (; element_iter; element_iter = element_iter->next) {
- if (element_iter->separate && stitch_check_uvs_state_stitchable(element, element_iter, ssc, state)) {
- int index_tmp1, index_tmp2;
- float normal[2];
-
- /* only calculate rotation against static island uv verts */
- if (!ssc->midpoints && element_iter->island != ssc->static_island)
- continue;
-
- index_tmp1 = element_iter - state->element_map->buf;
- index_tmp1 = state->map[index_tmp1];
- index_tmp2 = element - state->element_map->buf;
- index_tmp2 = state->map[index_tmp2];
-
- negate_v2_v2(normal, state->normals + index_tmp2 * 2);
- edgecos = dot_v2v2(normal, state->normals + index_tmp1 * 2);
- edgesin = cross_v2v2(normal, state->normals + index_tmp1 * 2);
- if (edgesin > 0.0f) {
- rotation += acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
- rot_elem++;
- }
- else {
- rotation_neg += acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
- rot_elem_neg++;
- }
- }
- }
-
- if (ssc->midpoints) {
- rotation /= 2.0f;
- rotation_neg /= 2.0f;
- }
- island_stitch_data[element->island].num_rot_elements += rot_elem;
- island_stitch_data[element->island].rotation += rotation;
- island_stitch_data[element->island].num_rot_elements_neg += rot_elem_neg;
- island_stitch_data[element->island].rotation_neg += rotation_neg;
+ float edgecos = 1.0f, edgesin = 0.0f;
+ int index;
+ UvElement *element_iter;
+ float rotation = 0, rotation_neg = 0;
+ int rot_elem = 0, rot_elem_neg = 0;
+ BMLoop *l;
+
+ if (element->island == ssc->static_island && !ssc->midpoints)
+ return;
+
+ l = element->l;
+
+ index = BM_elem_index_get(l->v);
+
+ element_iter = state->element_map->vert[index];
+
+ for (; element_iter; element_iter = element_iter->next) {
+ if (element_iter->separate &&
+ stitch_check_uvs_state_stitchable(element, element_iter, ssc, state)) {
+ int index_tmp1, index_tmp2;
+ float normal[2];
+
+ /* only calculate rotation against static island uv verts */
+ if (!ssc->midpoints && element_iter->island != ssc->static_island)
+ continue;
+
+ index_tmp1 = element_iter - state->element_map->buf;
+ index_tmp1 = state->map[index_tmp1];
+ index_tmp2 = element - state->element_map->buf;
+ index_tmp2 = state->map[index_tmp2];
+
+ negate_v2_v2(normal, state->normals + index_tmp2 * 2);
+ edgecos = dot_v2v2(normal, state->normals + index_tmp1 * 2);
+ edgesin = cross_v2v2(normal, state->normals + index_tmp1 * 2);
+ if (edgesin > 0.0f) {
+ rotation += acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
+ rot_elem++;
+ }
+ else {
+ rotation_neg += acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
+ rot_elem_neg++;
+ }
+ }
+ }
+
+ if (ssc->midpoints) {
+ rotation /= 2.0f;
+ rotation_neg /= 2.0f;
+ }
+ island_stitch_data[element->island].num_rot_elements += rot_elem;
+ island_stitch_data[element->island].rotation += rotation;
+ island_stitch_data[element->island].num_rot_elements_neg += rot_elem_neg;
+ island_stitch_data[element->island].rotation_neg += rotation_neg;
}
-
static void state_delete(StitchState *state)
{
- if (state) {
- if (state->island_is_stitchable) {
- MEM_freeN(state->island_is_stitchable);
- }
- if (state->element_map) {
- BM_uv_element_map_free(state->element_map);
- }
- if (state->uvs) {
- MEM_freeN(state->uvs);
- }
- if (state->selection_stack) {
- MEM_freeN(state->selection_stack);
- }
- if (state->tris_per_island) {
- MEM_freeN(state->tris_per_island);
- }
- if (state->map) {
- MEM_freeN(state->map);
- }
- if (state->normals) {
- MEM_freeN(state->normals);
- }
- if (state->edges) {
- MEM_freeN(state->edges);
- }
- if (state->stitch_preview) {
- stitch_preview_delete(state->stitch_preview);
- }
- if (state->edge_hash) {
- BLI_ghash_free(state->edge_hash, NULL, NULL);
- }
- MEM_freeN(state);
- }
+ if (state) {
+ if (state->island_is_stitchable) {
+ MEM_freeN(state->island_is_stitchable);
+ }
+ if (state->element_map) {
+ BM_uv_element_map_free(state->element_map);
+ }
+ if (state->uvs) {
+ MEM_freeN(state->uvs);
+ }
+ if (state->selection_stack) {
+ MEM_freeN(state->selection_stack);
+ }
+ if (state->tris_per_island) {
+ MEM_freeN(state->tris_per_island);
+ }
+ if (state->map) {
+ MEM_freeN(state->map);
+ }
+ if (state->normals) {
+ MEM_freeN(state->normals);
+ }
+ if (state->edges) {
+ MEM_freeN(state->edges);
+ }
+ if (state->stitch_preview) {
+ stitch_preview_delete(state->stitch_preview);
+ }
+ if (state->edge_hash) {
+ BLI_ghash_free(state->edge_hash, NULL, NULL);
+ }
+ MEM_freeN(state);
+ }
}
static void state_delete_all(StitchStateContainer *ssc)
{
- if (ssc) {
- for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
- state_delete(ssc->states[ob_index]);
- }
- MEM_freeN(ssc->states);
- MEM_freeN(ssc->objects);
- MEM_freeN(ssc);
- }
+ if (ssc) {
+ for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
+ state_delete(ssc->states[ob_index]);
+ }
+ MEM_freeN(ssc->states);
+ MEM_freeN(ssc->objects);
+ MEM_freeN(ssc);
+ }
}
static void stitch_uv_edge_generate_linked_edges(GHash *edge_hash, StitchState *state)
{
- UvEdge *edges = state->edges;
- const int *map = state->map;
- UvElementMap *element_map = state->element_map;
- UvElement *first_element = element_map->buf;
- int i;
-
- for (i = 0; i < state->total_separate_edges; i++) {
- UvEdge *edge = edges + i;
-
- if (edge->first)
- continue;
-
- /* only boundary edges can be stitched. Yes. Sorry about that :p */
- if (edge->flag & STITCH_BOUNDARY) {
- UvElement *element1 = state->uvs[edge->uv1];
- UvElement *element2 = state->uvs[edge->uv2];
-
- /* Now iterate through all faces and try to find edges sharing the same vertices */
- UvElement *iter1 = element_map->vert[BM_elem_index_get(element1->l->v)];
- UvEdge *last_set = edge;
- int elemindex2 = BM_elem_index_get(element2->l->v);
-
- edge->first = edge;
-
- for (; iter1; iter1 = iter1->next) {
- UvElement *iter2 = NULL;
-
- /* check to see if other vertex of edge belongs to same vertex as */
- if (BM_elem_index_get(iter1->l->next->v) == elemindex2)
- iter2 = BM_uv_element_get(element_map, iter1->l->f, iter1->l->next);
- else if (BM_elem_index_get(iter1->l->prev->v) == elemindex2)
- iter2 = BM_uv_element_get(element_map, iter1->l->f, iter1->l->prev);
-
- if (iter2) {
- int index1 = map[iter1 - first_element];
- int index2 = map[iter2 - first_element];
- UvEdge edgetmp;
- UvEdge *edge2, *eiter;
- bool valid = true;
-
- /* make sure the indices are well behaved */
- if (index1 > index2) {
- SWAP(int, index1, index2);
- }
-
- edgetmp.uv1 = index1;
- edgetmp.uv2 = index2;
-
- /* get the edge from the hash */
- edge2 = BLI_ghash_lookup(edge_hash, &edgetmp);
-
- /* more iteration to make sure non-manifold case is handled nicely */
- for (eiter = edge; eiter; eiter = eiter->next) {
- if (edge2 == eiter) {
- valid = false;
- break;
- }
- }
-
- if (valid) {
- /* here I am taking care of non manifold case, assuming more than two matching edges.
- * I am not too sure we want this though */
- last_set->next = edge2;
- last_set = edge2;
- /* set first, similarly to uv elements.
- * Now we can iterate among common edges easily */
- edge2->first = edge;
- }
- }
- }
- }
- else {
- /* so stitchability code works */
- edge->first = edge;
- }
- }
+ UvEdge *edges = state->edges;
+ const int *map = state->map;
+ UvElementMap *element_map = state->element_map;
+ UvElement *first_element = element_map->buf;
+ int i;
+
+ for (i = 0; i < state->total_separate_edges; i++) {
+ UvEdge *edge = edges + i;
+
+ if (edge->first)
+ continue;
+
+ /* only boundary edges can be stitched. Yes. Sorry about that :p */
+ if (edge->flag & STITCH_BOUNDARY) {
+ UvElement *element1 = state->uvs[edge->uv1];
+ UvElement *element2 = state->uvs[edge->uv2];
+
+ /* Now iterate through all faces and try to find edges sharing the same vertices */
+ UvElement *iter1 = element_map->vert[BM_elem_index_get(element1->l->v)];
+ UvEdge *last_set = edge;
+ int elemindex2 = BM_elem_index_get(element2->l->v);
+
+ edge->first = edge;
+
+ for (; iter1; iter1 = iter1->next) {
+ UvElement *iter2 = NULL;
+
+ /* check to see if other vertex of edge belongs to same vertex as */
+ if (BM_elem_index_get(iter1->l->next->v) == elemindex2)
+ iter2 = BM_uv_element_get(element_map, iter1->l->f, iter1->l->next);
+ else if (BM_elem_index_get(iter1->l->prev->v) == elemindex2)
+ iter2 = BM_uv_element_get(element_map, iter1->l->f, iter1->l->prev);
+
+ if (iter2) {
+ int index1 = map[iter1 - first_element];
+ int index2 = map[iter2 - first_element];
+ UvEdge edgetmp;
+ UvEdge *edge2, *eiter;
+ bool valid = true;
+
+ /* make sure the indices are well behaved */
+ if (index1 > index2) {
+ SWAP(int, index1, index2);
+ }
+
+ edgetmp.uv1 = index1;
+ edgetmp.uv2 = index2;
+
+ /* get the edge from the hash */
+ edge2 = BLI_ghash_lookup(edge_hash, &edgetmp);
+
+ /* more iteration to make sure non-manifold case is handled nicely */
+ for (eiter = edge; eiter; eiter = eiter->next) {
+ if (edge2 == eiter) {
+ valid = false;
+ break;
+ }
+ }
+
+ if (valid) {
+ /* here I am taking care of non manifold case, assuming more than two matching edges.
+ * I am not too sure we want this though */
+ last_set->next = edge2;
+ last_set = edge2;
+ /* set first, similarly to uv elements.
+ * Now we can iterate among common edges easily */
+ edge2->first = edge;
+ }
+ }
+ }
+ }
+ else {
+ /* so stitchability code works */
+ edge->first = edge;
+ }
+ }
}
-
/* checks for remote uvs that may be stitched with a certain uv, flags them if stitchable. */
-static void determine_uv_stitchability(
- UvElement *element, StitchStateContainer *ssc, StitchState *state,
- IslandStitchData *island_stitch_data)
+static void determine_uv_stitchability(UvElement *element,
+ StitchStateContainer *ssc,
+ StitchState *state,
+ IslandStitchData *island_stitch_data)
{
- int vert_index;
- UvElement *element_iter;
- BMLoop *l;
-
- l = element->l;
-
- vert_index = BM_elem_index_get(l->v);
- element_iter = state->element_map->vert[vert_index];
-
- for (; element_iter; element_iter = element_iter->next) {
- if (element_iter->separate) {
- if (stitch_check_uvs_stitchable(element, element_iter, ssc, state)) {
- island_stitch_data[element_iter->island].stitchableCandidate = 1;
- island_stitch_data[element->island].stitchableCandidate = 1;
- element->flag |= STITCH_STITCHABLE_CANDIDATE;
- }
- }
- }
+ int vert_index;
+ UvElement *element_iter;
+ BMLoop *l;
+
+ l = element->l;
+
+ vert_index = BM_elem_index_get(l->v);
+ element_iter = state->element_map->vert[vert_index];
+
+ for (; element_iter; element_iter = element_iter->next) {
+ if (element_iter->separate) {
+ if (stitch_check_uvs_stitchable(element, element_iter, ssc, state)) {
+ island_stitch_data[element_iter->island].stitchableCandidate = 1;
+ island_stitch_data[element->island].stitchableCandidate = 1;
+ element->flag |= STITCH_STITCHABLE_CANDIDATE;
+ }
+ }
+ }
}
-static void determine_uv_edge_stitchability(
- UvEdge *edge, StitchStateContainer *ssc, StitchState *state,
- IslandStitchData *island_stitch_data)
+static void determine_uv_edge_stitchability(UvEdge *edge,
+ StitchStateContainer *ssc,
+ StitchState *state,
+ IslandStitchData *island_stitch_data)
{
- UvEdge *edge_iter = edge->first;
-
- for (; edge_iter; edge_iter = edge_iter->next) {
- if (stitch_check_edges_stitchable(edge, edge_iter, ssc, state)) {
- island_stitch_data[edge_iter->element->island].stitchableCandidate = 1;
- island_stitch_data[edge->element->island].stitchableCandidate = 1;
- edge->flag |= STITCH_STITCHABLE_CANDIDATE;
- }
- }
+ UvEdge *edge_iter = edge->first;
+
+ for (; edge_iter; edge_iter = edge_iter->next) {
+ if (stitch_check_edges_stitchable(edge, edge_iter, ssc, state)) {
+ island_stitch_data[edge_iter->element->island].stitchableCandidate = 1;
+ island_stitch_data[edge->element->island].stitchableCandidate = 1;
+ edge->flag |= STITCH_STITCHABLE_CANDIDATE;
+ }
+ }
}
-
/* set preview buffer position of UV face in editface->tmp.l */
-static void stitch_set_face_preview_buffer_position(
- BMFace *efa, StitchPreviewer *preview, PreviewPosition *preview_position)
+static void stitch_set_face_preview_buffer_position(BMFace *efa,
+ StitchPreviewer *preview,
+ PreviewPosition *preview_position)
{
- int index = BM_elem_index_get(efa);
+ int index = BM_elem_index_get(efa);
- if (preview_position[index].data_position == STITCH_NO_PREVIEW) {
- preview_position[index].data_position = preview->preview_uvs * 2;
- preview_position[index].polycount_position = preview->num_polys++;
- preview->preview_uvs += efa->len;
- }
+ if (preview_position[index].data_position == STITCH_NO_PREVIEW) {
+ preview_position[index].data_position = preview->preview_uvs * 2;
+ preview_position[index].polycount_position = preview->num_polys++;
+ preview->preview_uvs += efa->len;
+ }
}
-
/* setup face preview for all coincident uvs and their faces */
-static void stitch_setup_face_preview_for_uv_group(
- UvElement *element, StitchStateContainer *ssc, StitchState *state,
- IslandStitchData *island_stitch_data, PreviewPosition *preview_position)
+static void stitch_setup_face_preview_for_uv_group(UvElement *element,
+ StitchStateContainer *ssc,
+ StitchState *state,
+ IslandStitchData *island_stitch_data,
+ PreviewPosition *preview_position)
{
- StitchPreviewer *preview = state->stitch_preview;
+ StitchPreviewer *preview = state->stitch_preview;
- /* static island does not change so returning immediately */
- if (ssc->snap_islands && !ssc->midpoints && ssc->static_island == element->island)
- return;
+ /* static island does not change so returning immediately */
+ if (ssc->snap_islands && !ssc->midpoints && ssc->static_island == element->island)
+ return;
- if (ssc->snap_islands) {
- island_stitch_data[element->island].addedForPreview = 1;
- }
+ if (ssc->snap_islands) {
+ island_stitch_data[element->island].addedForPreview = 1;
+ }
- do {
- stitch_set_face_preview_buffer_position(element->l->f, preview, preview_position);
- element = element->next;
- } while (element && !element->separate);
+ do {
+ stitch_set_face_preview_buffer_position(element->l->f, preview, preview_position);
+ element = element->next;
+ } while (element && !element->separate);
}
-
/* checks if uvs are indeed stitchable and registers so that they can be shown in preview */
-static void stitch_validate_uv_stitchability(
- UvElement *element, StitchStateContainer *ssc, StitchState *state,
- IslandStitchData *island_stitch_data, PreviewPosition *preview_position)
+static void stitch_validate_uv_stitchability(UvElement *element,
+ StitchStateContainer *ssc,
+ StitchState *state,
+ IslandStitchData *island_stitch_data,
+ PreviewPosition *preview_position)
{
- StitchPreviewer *preview = state->stitch_preview;
-
- /* If not the active object, then it's unstitchable */
- if (ssc->states[ssc->active_object_index] != state) {
- preview->num_unstitchable++;
- return;
- }
-
- UvElement *element_iter;
- int vert_index;
- BMLoop *l;
-
- l = element->l;
-
- vert_index = BM_elem_index_get(l->v);
-
- element_iter = state->element_map->vert[vert_index];
-
- for (; element_iter; element_iter = element_iter->next) {
- if (element_iter->separate) {
- if (element_iter == element)
- continue;
- if (stitch_check_uvs_state_stitchable(element, element_iter, ssc, state)) {
- if ((element_iter->island == ssc->static_island) || (element->island == ssc->static_island)) {
- element->flag |= STITCH_STITCHABLE;
- preview->num_stitchable++;
- stitch_setup_face_preview_for_uv_group(element, ssc, state, island_stitch_data, preview_position);
- return;
- }
- }
- }
- }
-
- /* this can happen if the uvs to be stitched are not on a stitchable island */
- if (!(element->flag & STITCH_STITCHABLE)) {
- preview->num_unstitchable++;
- }
+ StitchPreviewer *preview = state->stitch_preview;
+
+ /* If not the active object, then it's unstitchable */
+ if (ssc->states[ssc->active_object_index] != state) {
+ preview->num_unstitchable++;
+ return;
+ }
+
+ UvElement *element_iter;
+ int vert_index;
+ BMLoop *l;
+
+ l = element->l;
+
+ vert_index = BM_elem_index_get(l->v);
+
+ element_iter = state->element_map->vert[vert_index];
+
+ for (; element_iter; element_iter = element_iter->next) {
+ if (element_iter->separate) {
+ if (element_iter == element)
+ continue;
+ if (stitch_check_uvs_state_stitchable(element, element_iter, ssc, state)) {
+ if ((element_iter->island == ssc->static_island) ||
+ (element->island == ssc->static_island)) {
+ element->flag |= STITCH_STITCHABLE;
+ preview->num_stitchable++;
+ stitch_setup_face_preview_for_uv_group(
+ element, ssc, state, island_stitch_data, preview_position);
+ return;
+ }
+ }
+ }
+ }
+
+ /* this can happen if the uvs to be stitched are not on a stitchable island */
+ if (!(element->flag & STITCH_STITCHABLE)) {
+ preview->num_unstitchable++;
+ }
}
-
-static void stitch_validate_edge_stitchability(
- UvEdge *edge, StitchStateContainer *ssc, StitchState *state,
- IslandStitchData *island_stitch_data, PreviewPosition *preview_position)
+static void stitch_validate_edge_stitchability(UvEdge *edge,
+ StitchStateContainer *ssc,
+ StitchState *state,
+ IslandStitchData *island_stitch_data,
+ PreviewPosition *preview_position)
{
- StitchPreviewer *preview = state->stitch_preview;
-
- /* If not the active object, then it's unstitchable */
- if (ssc->states[ssc->active_object_index] != state) {
- preview->num_unstitchable++;
- return;
- }
-
- UvEdge *edge_iter = edge->first;
-
- for (; edge_iter; edge_iter = edge_iter->next) {
- if (edge_iter == edge)
- continue;
- if (stitch_check_edges_state_stitchable(edge, edge_iter, ssc, state)) {
- if ((edge_iter->element->island == ssc->static_island) || (edge->element->island == ssc->static_island)) {
- edge->flag |= STITCH_STITCHABLE;
- preview->num_stitchable++;
- stitch_setup_face_preview_for_uv_group(state->uvs[edge->uv1],
- ssc,
- state,
- island_stitch_data,
- preview_position);
- stitch_setup_face_preview_for_uv_group(state->uvs[edge->uv2],
- ssc,
- state,
- island_stitch_data,
- preview_position);
- return;
- }
- }
- }
-
- /* this can happen if the uvs to be stitched are not on a stitchable island */
- if (!(edge->flag & STITCH_STITCHABLE)) {
- preview->num_unstitchable++;
- }
+ StitchPreviewer *preview = state->stitch_preview;
+
+ /* If not the active object, then it's unstitchable */
+ if (ssc->states[ssc->active_object_index] != state) {
+ preview->num_unstitchable++;
+ return;
+ }
+
+ UvEdge *edge_iter = edge->first;
+
+ for (; edge_iter; edge_iter = edge_iter->next) {
+ if (edge_iter == edge)
+ continue;
+ if (stitch_check_edges_state_stitchable(edge, edge_iter, ssc, state)) {
+ if ((edge_iter->element->island == ssc->static_island) ||
+ (edge->element->island == ssc->static_island)) {
+ edge->flag |= STITCH_STITCHABLE;
+ preview->num_stitchable++;
+ stitch_setup_face_preview_for_uv_group(
+ state->uvs[edge->uv1], ssc, state, island_stitch_data, preview_position);
+ stitch_setup_face_preview_for_uv_group(
+ state->uvs[edge->uv2], ssc, state, island_stitch_data, preview_position);
+ return;
+ }
+ }
+ }
+
+ /* this can happen if the uvs to be stitched are not on a stitchable island */
+ if (!(edge->flag & STITCH_STITCHABLE)) {
+ preview->num_unstitchable++;
+ }
}
-
-static void stitch_propagate_uv_final_position(
- Scene *scene,
- UvElement *element, int index, PreviewPosition *preview_position,
- UVVertAverage *final_position, StitchStateContainer *ssc, StitchState *state,
- const bool final)
+static void stitch_propagate_uv_final_position(Scene *scene,
+ UvElement *element,
+ int index,
+ PreviewPosition *preview_position,
+ UVVertAverage *final_position,
+ StitchStateContainer *ssc,
+ StitchState *state,
+ const bool final)
{
- BMesh *bm = state->em->bm;
- StitchPreviewer *preview = state->stitch_preview;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-
- if (element->flag & STITCH_STITCHABLE) {
- UvElement *element_iter = element;
- /* propagate to coincident uvs */
- do {
- BMLoop *l;
- MLoopUV *luv;
-
- l = element_iter->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
-
- element_iter->flag |= STITCH_PROCESSED;
- /* either flush to preview or to the MTFace, if final */
- if (final) {
- copy_v2_v2(luv->uv, final_position[index].uv);
-
- uvedit_uv_select_enable(state->em, scene, l, false, cd_loop_uv_offset);
- }
- else {
- int face_preview_pos = preview_position[BM_elem_index_get(element_iter->l->f)].data_position;
- if (face_preview_pos != STITCH_NO_PREVIEW) {
- copy_v2_v2(preview->preview_polys + face_preview_pos + 2 * element_iter->loop_of_poly_index,
- final_position[index].uv);
- }
- }
-
- /* end of calculations, keep only the selection flag */
- if ((!ssc->snap_islands) || ((!ssc->midpoints) && (element_iter->island == ssc->static_island))) {
- element_iter->flag &= STITCH_SELECTED;
- }
-
- element_iter = element_iter->next;
- } while (element_iter && !element_iter->separate);
- }
+ BMesh *bm = state->em->bm;
+ StitchPreviewer *preview = state->stitch_preview;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+ if (element->flag & STITCH_STITCHABLE) {
+ UvElement *element_iter = element;
+ /* propagate to coincident uvs */
+ do {
+ BMLoop *l;
+ MLoopUV *luv;
+
+ l = element_iter->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+
+ element_iter->flag |= STITCH_PROCESSED;
+ /* either flush to preview or to the MTFace, if final */
+ if (final) {
+ copy_v2_v2(luv->uv, final_position[index].uv);
+
+ uvedit_uv_select_enable(state->em, scene, l, false, cd_loop_uv_offset);
+ }
+ else {
+ int face_preview_pos =
+ preview_position[BM_elem_index_get(element_iter->l->f)].data_position;
+ if (face_preview_pos != STITCH_NO_PREVIEW) {
+ copy_v2_v2(preview->preview_polys + face_preview_pos +
+ 2 * element_iter->loop_of_poly_index,
+ final_position[index].uv);
+ }
+ }
+
+ /* end of calculations, keep only the selection flag */
+ if ((!ssc->snap_islands) ||
+ ((!ssc->midpoints) && (element_iter->island == ssc->static_island))) {
+ element_iter->flag &= STITCH_SELECTED;
+ }
+
+ element_iter = element_iter->next;
+ } while (element_iter && !element_iter->separate);
+ }
}
/* main processing function. It calculates preview and final positions. */
-static int stitch_process_data(
- StitchStateContainer *ssc, StitchState *state, Scene *scene, int final)
+static int stitch_process_data(StitchStateContainer *ssc,
+ StitchState *state,
+ Scene *scene,
+ int final)
{
- int i;
- StitchPreviewer *preview;
- IslandStitchData *island_stitch_data = NULL;
- int previous_island = ssc->static_island;
- BMesh *bm = state->em->bm;
- BMFace *efa;
- BMIter iter;
- UVVertAverage *final_position = NULL;
- bool is_active_state = (state == ssc->states[ssc->active_object_index]);
-
- char stitch_midpoints = ssc->midpoints;
- /* used to map uv indices to uvaverage indices for selection */
- unsigned int *uvfinal_map = NULL;
- /* per face preview position in preview buffer */
- PreviewPosition *preview_position = NULL;
-
- /* cleanup previous preview */
- stitch_preview_delete(state->stitch_preview);
- preview = state->stitch_preview = stitch_preview_init();
- if (preview == NULL)
- return 0;
-
- preview_position = MEM_mallocN(bm->totface * sizeof(*preview_position), "stitch_face_preview_position");
- /* each face holds its position in the preview buffer in tmp. -1 is uninitialized */
- for (i = 0; i < bm->totface; i++) {
- preview_position[i].data_position = STITCH_NO_PREVIEW;
- }
-
- island_stitch_data = MEM_callocN(sizeof(*island_stitch_data) * state->element_map->totalIslands,
- "stitch_island_data");
- if (!island_stitch_data) {
- return 0;
- }
-
- /* store indices to editVerts and Faces. May be unneeded but ensuring anyway */
- BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
-
- /****************************************
- * First determine stitchability of uvs *
- ****************************************/
-
- for (i = 0; i < state->selection_size; i++) {
- if (ssc->mode == STITCH_VERT) {
- UvElement *element = (UvElement *)state->selection_stack[i];
- determine_uv_stitchability(element, ssc, state, island_stitch_data);
- }
- else {
- UvEdge *edge = (UvEdge *)state->selection_stack[i];
- determine_uv_edge_stitchability(edge, ssc, state, island_stitch_data);
- }
- }
-
- /* remember stitchable candidates as places the 'I' button */
- /* will stop at. */
- for (int island_idx = 0; island_idx < state->element_map->totalIslands; island_idx++) {
- state->island_is_stitchable[island_idx] = island_stitch_data[island_idx].stitchableCandidate ? true : false;
- }
-
- if (is_active_state) {
- /* set static island to one that is added for preview */
- ssc->static_island %= state->element_map->totalIslands;
- while (!(island_stitch_data[ssc->static_island].stitchableCandidate)) {
- ssc->static_island++;
- ssc->static_island %= state->element_map->totalIslands;
- /* this is entirely possible if for example limit stitching
- * with no stitchable verts or no selection */
- if (ssc->static_island == previous_island) {
- break;
- }
- }
- }
-
- for (i = 0; i < state->selection_size; i++) {
- if (ssc->mode == STITCH_VERT) {
- UvElement *element = (UvElement *)state->selection_stack[i];
- if (element->flag & STITCH_STITCHABLE_CANDIDATE) {
- element->flag &= ~STITCH_STITCHABLE_CANDIDATE;
- stitch_validate_uv_stitchability(element, ssc, state, island_stitch_data, preview_position);
- }
- else {
- /* add to preview for unstitchable */
- preview->num_unstitchable++;
- }
- }
- else {
- UvEdge *edge = (UvEdge *)state->selection_stack[i];
- if (edge->flag & STITCH_STITCHABLE_CANDIDATE) {
- edge->flag &= ~STITCH_STITCHABLE_CANDIDATE;
- stitch_validate_edge_stitchability(edge, ssc, state, island_stitch_data, preview_position);
- }
- else {
- preview->num_unstitchable++;
- }
- }
- }
-
- /*********************************************************************
- * Setup the stitchable & unstitchable preview buffers and fill *
- * them with the appropriate data *
- *********************************************************************/
- if (!final) {
- BMLoop *l;
- MLoopUV *luv;
- int stitchBufferIndex = 0, unstitchBufferIndex = 0;
- int preview_size = (ssc->mode == STITCH_VERT) ? 2 : 4;
- /* initialize the preview buffers */
- preview->preview_stitchable = (float *)MEM_mallocN(preview->num_stitchable * sizeof(float) * preview_size,
- "stitch_preview_stitchable_data");
- preview->preview_unstitchable = (float *)MEM_mallocN(preview->num_unstitchable * sizeof(float) * preview_size,
- "stitch_preview_unstitchable_data");
-
- /* will cause cancel and freeing of all data structures so OK */
- if (!preview->preview_stitchable || !preview->preview_unstitchable) {
- return 0;
- }
-
- /* fill the appropriate preview buffers */
- if (ssc->mode == STITCH_VERT) {
- for (i = 0; i < state->total_separate_uvs; i++) {
- UvElement *element = (UvElement *)state->uvs[i];
- if (element->flag & STITCH_STITCHABLE) {
- l = element->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
-
- copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 2], luv->uv);
-
- stitchBufferIndex++;
- }
- else if (element->flag & STITCH_SELECTED) {
- l = element->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
-
- copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 2], luv->uv);
- unstitchBufferIndex++;
- }
- }
- }
- else {
- for (i = 0; i < state->total_separate_edges; i++) {
- UvEdge *edge = state->edges + i;
- UvElement *element1 = state->uvs[edge->uv1];
- UvElement *element2 = state->uvs[edge->uv2];
-
- if (edge->flag & STITCH_STITCHABLE) {
- l = element1->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
- copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4], luv->uv);
-
- l = element2->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
- copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4 + 2], luv->uv);
-
- stitchBufferIndex++;
- BLI_assert(stitchBufferIndex <= preview->num_stitchable);
- }
- else if (edge->flag & STITCH_SELECTED) {
- l = element1->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
- copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4], luv->uv);
-
- l = element2->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
- copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4 + 2], luv->uv);
-
- unstitchBufferIndex++;
- BLI_assert(unstitchBufferIndex <= preview->num_unstitchable);
- }
- }
- }
- }
-
- if (ssc->states[ssc->active_object_index] != state) {
- /* This is not the active object/state, exit here */
- MEM_freeN(island_stitch_data);
- MEM_freeN(preview_position);
- return 1;
- }
-
- /****************************************
- * Setup preview for stitchable islands *
- ****************************************/
- if (ssc->snap_islands) {
- for (i = 0; i < state->element_map->totalIslands; i++) {
- if (island_stitch_data[i].addedForPreview) {
- int numOfIslandUVs = 0, j;
- UvElement *element;
- numOfIslandUVs = getNumOfIslandUvs(state->element_map, i);
- element = &state->element_map->buf[state->element_map->islandIndices[i]];
- for (j = 0; j < numOfIslandUVs; j++, element++) {
- stitch_set_face_preview_buffer_position(element->l->f, preview, preview_position);
- }
- }
- }
- }
-
- /*********************************************************************
- * Setup the remaining preview buffers and fill them with the *
- * appropriate data *
- *********************************************************************/
- if (!final) {
- BMIter liter;
- BMLoop *l;
- MLoopUV *luv;
- unsigned int buffer_index = 0;
-
- /* initialize the preview buffers */
- preview->preview_polys = MEM_mallocN(preview->preview_uvs * sizeof(float) * 2, "tri_uv_stitch_prev");
- preview->uvs_per_polygon = MEM_mallocN(preview->num_polys * sizeof(*preview->uvs_per_polygon),
- "tri_uv_stitch_prev");
-
- preview->static_tris = MEM_mallocN(state->tris_per_island[ssc->static_island] * sizeof(float) * 6,
- "static_island_preview_tris");
-
- preview->num_static_tris = state->tris_per_island[ssc->static_island];
- /* will cause cancel and freeing of all data structures so OK */
- if (!preview->preview_polys) {
- return 0;
- }
-
- /* copy data from MLoopUVs to the preview display buffers */
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- /* just to test if face was added for processing.
- * uvs of unselected vertices will return NULL */
- UvElement *element = BM_uv_element_get(state->element_map, efa, BM_FACE_FIRST_LOOP(efa));
-
- if (element) {
- int numoftris = efa->len - 2;
- int index = BM_elem_index_get(efa);
- int face_preview_pos = preview_position[index].data_position;
- if (face_preview_pos != STITCH_NO_PREVIEW) {
- preview->uvs_per_polygon[preview_position[index].polycount_position] = efa->len;
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
- copy_v2_v2(preview->preview_polys + face_preview_pos + i * 2, luv->uv);
- }
- }
-
- /* if this is the static_island on the active object */
- if (element->island == ssc->static_island) {
- BMLoop *fl = BM_FACE_FIRST_LOOP(efa);
- MLoopUV *fuv = CustomData_bmesh_get(&bm->ldata, fl->head.data, CD_MLOOPUV);
-
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- if (i < numoftris) {
- /* using next since the first uv is already accounted for */
- BMLoop *lnext = l->next;
- MLoopUV *luvnext = CustomData_bmesh_get(&bm->ldata, lnext->next->head.data, CD_MLOOPUV);
- luv = CustomData_bmesh_get(&bm->ldata, lnext->head.data, CD_MLOOPUV);
-
- memcpy(preview->static_tris + buffer_index, fuv->uv, 2 * sizeof(float));
- memcpy(preview->static_tris + buffer_index + 2, luv->uv, 2 * sizeof(float));
- memcpy(preview->static_tris + buffer_index + 4, luvnext->uv, 2 * sizeof(float));
- buffer_index += 6;
- }
- else {
- break;
- }
- }
- }
- }
- }
- }
-
- /******************************************************
- * Here we calculate the final coordinates of the uvs *
- ******************************************************/
-
- if (ssc->mode == STITCH_VERT) {
- final_position = MEM_callocN(state->selection_size * sizeof(*final_position), "stitch_uv_average");
- uvfinal_map = MEM_mallocN(state->element_map->totalUVs * sizeof(*uvfinal_map), "stitch_uv_final_map");
- }
- else {
- final_position = MEM_callocN(state->total_separate_uvs * sizeof(*final_position), "stitch_uv_average");
- }
-
- /* first pass, calculate final position for stitchable uvs of the static island */
- for (i = 0; i < state->selection_size; i++) {
- if (ssc->mode == STITCH_VERT) {
- UvElement *element = state->selection_stack[i];
-
- if (element->flag & STITCH_STITCHABLE) {
- BMLoop *l;
- MLoopUV *luv;
- UvElement *element_iter;
-
- l = element->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
-
- uvfinal_map[element - state->element_map->buf] = i;
-
- copy_v2_v2(final_position[i].uv, luv->uv);
- final_position[i].count = 1;
-
- if (ssc->snap_islands && element->island == ssc->static_island && !stitch_midpoints)
- continue;
-
- element_iter = state->element_map->vert[BM_elem_index_get(l->v)];
-
- for ( ; element_iter; element_iter = element_iter->next) {
- if (element_iter->separate) {
- if (stitch_check_uvs_state_stitchable(element, element_iter, ssc, state)) {
- l = element_iter->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
- if (stitch_midpoints) {
- add_v2_v2(final_position[i].uv, luv->uv);
- final_position[i].count++;
- }
- else if (element_iter->island == ssc->static_island) {
- /* if multiple uvs on the static island exist,
- * last checked remains. to disambiguate we need to limit or use
- * edge stitch */
- copy_v2_v2(final_position[i].uv, luv->uv);
- }
- }
- }
- }
- }
- if (stitch_midpoints) {
- final_position[i].uv[0] /= final_position[i].count;
- final_position[i].uv[1] /= final_position[i].count;
- }
- }
- else {
- UvEdge *edge = state->selection_stack[i];
-
- if (edge->flag & STITCH_STITCHABLE) {
- MLoopUV *luv2, *luv1;
- BMLoop *l;
- UvEdge *edge_iter;
-
- l = state->uvs[edge->uv1]->l;
- luv1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
- l = state->uvs[edge->uv2]->l;
- luv2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
-
- copy_v2_v2(final_position[edge->uv1].uv, luv1->uv);
- copy_v2_v2(final_position[edge->uv2].uv, luv2->uv);
- final_position[edge->uv1].count = 1;
- final_position[edge->uv2].count = 1;
-
- state->uvs[edge->uv1]->flag |= STITCH_STITCHABLE;
- state->uvs[edge->uv2]->flag |= STITCH_STITCHABLE;
-
- if (ssc->snap_islands && edge->element->island == ssc->static_island && !stitch_midpoints)
- continue;
-
- for (edge_iter = edge->first; edge_iter; edge_iter = edge_iter->next) {
- if (stitch_check_edges_state_stitchable(edge, edge_iter, ssc, state)) {
- l = state->uvs[edge_iter->uv1]->l;
- luv1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
- l = state->uvs[edge_iter->uv2]->l;
- luv2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
-
- if (stitch_midpoints) {
- add_v2_v2(final_position[edge->uv1].uv, luv1->uv);
- final_position[edge->uv1].count++;
- add_v2_v2(final_position[edge->uv2].uv, luv2->uv);
- final_position[edge->uv2].count++;
- }
- else if (edge_iter->element->island == ssc->static_island) {
- copy_v2_v2(final_position[edge->uv1].uv, luv1->uv);
- copy_v2_v2(final_position[edge->uv2].uv, luv2->uv);
- }
- }
- }
- }
- }
- }
-
- /* take mean position here.
- * For edge case, this can't be done inside the loop for shared uvverts */
- if (ssc->mode == STITCH_EDGE && stitch_midpoints) {
- for (i = 0; i < state->total_separate_uvs; i++) {
- final_position[i].uv[0] /= final_position[i].count;
- final_position[i].uv[1] /= final_position[i].count;
- }
- }
-
- /* second pass, calculate island rotation and translation before modifying any uvs */
- if (ssc->snap_islands) {
- if (ssc->mode == STITCH_VERT) {
- for (i = 0; i < state->selection_size; i++) {
- UvElement *element = state->selection_stack[i];
-
- if (element->flag & STITCH_STITCHABLE) {
- BMLoop *l;
- MLoopUV *luv;
-
- l = element->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
-
- /* accumulate each islands' translation from stitchable elements. it is important to do here
- * because in final pass MTFaces get modified and result is zero. */
- island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - luv->uv[0];
- island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - luv->uv[1];
- island_stitch_data[element->island].medianPoint[0] += luv->uv[0];
- island_stitch_data[element->island].medianPoint[1] += luv->uv[1];
- island_stitch_data[element->island].numOfElements++;
- }
- }
-
- /* only calculate rotation when an edge has been fully selected */
- for (i = 0; i < state->total_separate_edges; i++) {
- UvEdge *edge = state->edges + i;
- if ((edge->flag & STITCH_BOUNDARY) &&
- (state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) &&
- (state->uvs[edge->uv2]->flag & STITCH_STITCHABLE))
- {
- stitch_island_calculate_edge_rotation(edge,
- ssc,
- state,
- final_position,
- uvfinal_map,
- island_stitch_data);
- island_stitch_data[state->uvs[edge->uv1]->island].use_edge_rotation = true;
- }
- }
-
- /* clear seams of stitched edges */
- if (final && ssc->clear_seams) {
- for (i = 0; i < state->total_separate_edges; i++) {
- UvEdge *edge = state->edges + i;
- if ((state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) &&
- (state->uvs[edge->uv2]->flag & STITCH_STITCHABLE))
- {
- BM_elem_flag_disable(edge->element->l->e, BM_ELEM_SEAM);
- }
- }
- }
-
- for (i = 0; i < state->selection_size; i++) {
- UvElement *element = state->selection_stack[i];
- if (!island_stitch_data[element->island].use_edge_rotation) {
- if (element->flag & STITCH_STITCHABLE) {
- stitch_island_calculate_vert_rotation(element, ssc, state, island_stitch_data);
- }
- }
- }
- }
- else {
- for (i = 0; i < state->total_separate_uvs; i++) {
- UvElement *element = state->uvs[i];
-
- if (element->flag & STITCH_STITCHABLE) {
- BMLoop *l;
- MLoopUV *luv;
-
- l = element->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
-
- /* accumulate each islands' translation from stitchable elements. it is important to do here
- * because in final pass MTFaces get modified and result is zero. */
- island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - luv->uv[0];
- island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - luv->uv[1];
- island_stitch_data[element->island].medianPoint[0] += luv->uv[0];
- island_stitch_data[element->island].medianPoint[1] += luv->uv[1];
- island_stitch_data[element->island].numOfElements++;
- }
- }
-
- for (i = 0; i < state->selection_size; i++) {
- UvEdge *edge = state->selection_stack[i];
-
- if (edge->flag & STITCH_STITCHABLE) {
- stitch_island_calculate_edge_rotation(edge, ssc, state, final_position, NULL, island_stitch_data);
- island_stitch_data[state->uvs[edge->uv1]->island].use_edge_rotation = true;
- }
- }
-
- /* clear seams of stitched edges */
- if (final && ssc->clear_seams) {
- for (i = 0; i < state->selection_size; i++) {
- UvEdge *edge = state->selection_stack[i];
- if (edge->flag & STITCH_STITCHABLE) {
- BM_elem_flag_disable(edge->element->l->e, BM_ELEM_SEAM);
- }
- }
- }
- }
- }
-
- /* third pass, propagate changes to coincident uvs */
- for (i = 0; i < state->selection_size; i++) {
- if (ssc->mode == STITCH_VERT) {
- UvElement *element = state->selection_stack[i];
-
- stitch_propagate_uv_final_position(scene, element, i, preview_position, final_position, ssc, state, final);
- }
- else {
- UvEdge *edge = state->selection_stack[i];
-
- stitch_propagate_uv_final_position(
- scene, state->uvs[edge->uv1], edge->uv1, preview_position, final_position, ssc, state, final);
- stitch_propagate_uv_final_position(
- scene, state->uvs[edge->uv2], edge->uv2, preview_position, final_position, ssc, state, final);
-
- edge->flag &= (STITCH_SELECTED | STITCH_BOUNDARY);
- }
- }
-
- /* final pass, calculate Island translation/rotation if needed */
- if (ssc->snap_islands) {
- stitch_calculate_island_snapping(state, preview_position, preview, island_stitch_data, final);
- }
-
- MEM_freeN(final_position);
- if (ssc->mode == STITCH_VERT) {
- MEM_freeN(uvfinal_map);
- }
- MEM_freeN(island_stitch_data);
- MEM_freeN(preview_position);
-
- return 1;
+ int i;
+ StitchPreviewer *preview;
+ IslandStitchData *island_stitch_data = NULL;
+ int previous_island = ssc->static_island;
+ BMesh *bm = state->em->bm;
+ BMFace *efa;
+ BMIter iter;
+ UVVertAverage *final_position = NULL;
+ bool is_active_state = (state == ssc->states[ssc->active_object_index]);
+
+ char stitch_midpoints = ssc->midpoints;
+ /* used to map uv indices to uvaverage indices for selection */
+ unsigned int *uvfinal_map = NULL;
+ /* per face preview position in preview buffer */
+ PreviewPosition *preview_position = NULL;
+
+ /* cleanup previous preview */
+ stitch_preview_delete(state->stitch_preview);
+ preview = state->stitch_preview = stitch_preview_init();
+ if (preview == NULL)
+ return 0;
+
+ preview_position = MEM_mallocN(bm->totface * sizeof(*preview_position),
+ "stitch_face_preview_position");
+ /* each face holds its position in the preview buffer in tmp. -1 is uninitialized */
+ for (i = 0; i < bm->totface; i++) {
+ preview_position[i].data_position = STITCH_NO_PREVIEW;
+ }
+
+ island_stitch_data = MEM_callocN(sizeof(*island_stitch_data) * state->element_map->totalIslands,
+ "stitch_island_data");
+ if (!island_stitch_data) {
+ return 0;
+ }
+
+ /* store indices to editVerts and Faces. May be unneeded but ensuring anyway */
+ BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
+
+ /****************************************
+ * First determine stitchability of uvs *
+ ****************************************/
+
+ for (i = 0; i < state->selection_size; i++) {
+ if (ssc->mode == STITCH_VERT) {
+ UvElement *element = (UvElement *)state->selection_stack[i];
+ determine_uv_stitchability(element, ssc, state, island_stitch_data);
+ }
+ else {
+ UvEdge *edge = (UvEdge *)state->selection_stack[i];
+ determine_uv_edge_stitchability(edge, ssc, state, island_stitch_data);
+ }
+ }
+
+ /* remember stitchable candidates as places the 'I' button */
+ /* will stop at. */
+ for (int island_idx = 0; island_idx < state->element_map->totalIslands; island_idx++) {
+ state->island_is_stitchable[island_idx] = island_stitch_data[island_idx].stitchableCandidate ?
+ true :
+ false;
+ }
+
+ if (is_active_state) {
+ /* set static island to one that is added for preview */
+ ssc->static_island %= state->element_map->totalIslands;
+ while (!(island_stitch_data[ssc->static_island].stitchableCandidate)) {
+ ssc->static_island++;
+ ssc->static_island %= state->element_map->totalIslands;
+ /* this is entirely possible if for example limit stitching
+ * with no stitchable verts or no selection */
+ if (ssc->static_island == previous_island) {
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < state->selection_size; i++) {
+ if (ssc->mode == STITCH_VERT) {
+ UvElement *element = (UvElement *)state->selection_stack[i];
+ if (element->flag & STITCH_STITCHABLE_CANDIDATE) {
+ element->flag &= ~STITCH_STITCHABLE_CANDIDATE;
+ stitch_validate_uv_stitchability(
+ element, ssc, state, island_stitch_data, preview_position);
+ }
+ else {
+ /* add to preview for unstitchable */
+ preview->num_unstitchable++;
+ }
+ }
+ else {
+ UvEdge *edge = (UvEdge *)state->selection_stack[i];
+ if (edge->flag & STITCH_STITCHABLE_CANDIDATE) {
+ edge->flag &= ~STITCH_STITCHABLE_CANDIDATE;
+ stitch_validate_edge_stitchability(edge, ssc, state, island_stitch_data, preview_position);
+ }
+ else {
+ preview->num_unstitchable++;
+ }
+ }
+ }
+
+ /*********************************************************************
+ * Setup the stitchable & unstitchable preview buffers and fill *
+ * them with the appropriate data *
+ *********************************************************************/
+ if (!final) {
+ BMLoop *l;
+ MLoopUV *luv;
+ int stitchBufferIndex = 0, unstitchBufferIndex = 0;
+ int preview_size = (ssc->mode == STITCH_VERT) ? 2 : 4;
+ /* initialize the preview buffers */
+ preview->preview_stitchable = (float *)MEM_mallocN(
+ preview->num_stitchable * sizeof(float) * preview_size, "stitch_preview_stitchable_data");
+ preview->preview_unstitchable = (float *)MEM_mallocN(preview->num_unstitchable *
+ sizeof(float) * preview_size,
+ "stitch_preview_unstitchable_data");
+
+ /* will cause cancel and freeing of all data structures so OK */
+ if (!preview->preview_stitchable || !preview->preview_unstitchable) {
+ return 0;
+ }
+
+ /* fill the appropriate preview buffers */
+ if (ssc->mode == STITCH_VERT) {
+ for (i = 0; i < state->total_separate_uvs; i++) {
+ UvElement *element = (UvElement *)state->uvs[i];
+ if (element->flag & STITCH_STITCHABLE) {
+ l = element->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+
+ copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 2], luv->uv);
+
+ stitchBufferIndex++;
+ }
+ else if (element->flag & STITCH_SELECTED) {
+ l = element->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+
+ copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 2], luv->uv);
+ unstitchBufferIndex++;
+ }
+ }
+ }
+ else {
+ for (i = 0; i < state->total_separate_edges; i++) {
+ UvEdge *edge = state->edges + i;
+ UvElement *element1 = state->uvs[edge->uv1];
+ UvElement *element2 = state->uvs[edge->uv2];
+
+ if (edge->flag & STITCH_STITCHABLE) {
+ l = element1->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4], luv->uv);
+
+ l = element2->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4 + 2], luv->uv);
+
+ stitchBufferIndex++;
+ BLI_assert(stitchBufferIndex <= preview->num_stitchable);
+ }
+ else if (edge->flag & STITCH_SELECTED) {
+ l = element1->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4], luv->uv);
+
+ l = element2->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4 + 2], luv->uv);
+
+ unstitchBufferIndex++;
+ BLI_assert(unstitchBufferIndex <= preview->num_unstitchable);
+ }
+ }
+ }
+ }
+
+ if (ssc->states[ssc->active_object_index] != state) {
+ /* This is not the active object/state, exit here */
+ MEM_freeN(island_stitch_data);
+ MEM_freeN(preview_position);
+ return 1;
+ }
+
+ /****************************************
+ * Setup preview for stitchable islands *
+ ****************************************/
+ if (ssc->snap_islands) {
+ for (i = 0; i < state->element_map->totalIslands; i++) {
+ if (island_stitch_data[i].addedForPreview) {
+ int numOfIslandUVs = 0, j;
+ UvElement *element;
+ numOfIslandUVs = getNumOfIslandUvs(state->element_map, i);
+ element = &state->element_map->buf[state->element_map->islandIndices[i]];
+ for (j = 0; j < numOfIslandUVs; j++, element++) {
+ stitch_set_face_preview_buffer_position(element->l->f, preview, preview_position);
+ }
+ }
+ }
+ }
+
+ /*********************************************************************
+ * Setup the remaining preview buffers and fill them with the *
+ * appropriate data *
+ *********************************************************************/
+ if (!final) {
+ BMIter liter;
+ BMLoop *l;
+ MLoopUV *luv;
+ unsigned int buffer_index = 0;
+
+ /* initialize the preview buffers */
+ preview->preview_polys = MEM_mallocN(preview->preview_uvs * sizeof(float) * 2,
+ "tri_uv_stitch_prev");
+ preview->uvs_per_polygon = MEM_mallocN(preview->num_polys * sizeof(*preview->uvs_per_polygon),
+ "tri_uv_stitch_prev");
+
+ preview->static_tris = MEM_mallocN(state->tris_per_island[ssc->static_island] * sizeof(float) *
+ 6,
+ "static_island_preview_tris");
+
+ preview->num_static_tris = state->tris_per_island[ssc->static_island];
+ /* will cause cancel and freeing of all data structures so OK */
+ if (!preview->preview_polys) {
+ return 0;
+ }
+
+ /* copy data from MLoopUVs to the preview display buffers */
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ /* just to test if face was added for processing.
+ * uvs of unselected vertices will return NULL */
+ UvElement *element = BM_uv_element_get(state->element_map, efa, BM_FACE_FIRST_LOOP(efa));
+
+ if (element) {
+ int numoftris = efa->len - 2;
+ int index = BM_elem_index_get(efa);
+ int face_preview_pos = preview_position[index].data_position;
+ if (face_preview_pos != STITCH_NO_PREVIEW) {
+ preview->uvs_per_polygon[preview_position[index].polycount_position] = efa->len;
+ BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i)
+ {
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ copy_v2_v2(preview->preview_polys + face_preview_pos + i * 2, luv->uv);
+ }
+ }
+
+ /* if this is the static_island on the active object */
+ if (element->island == ssc->static_island) {
+ BMLoop *fl = BM_FACE_FIRST_LOOP(efa);
+ MLoopUV *fuv = CustomData_bmesh_get(&bm->ldata, fl->head.data, CD_MLOOPUV);
+
+ BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i)
+ {
+ if (i < numoftris) {
+ /* using next since the first uv is already accounted for */
+ BMLoop *lnext = l->next;
+ MLoopUV *luvnext = CustomData_bmesh_get(
+ &bm->ldata, lnext->next->head.data, CD_MLOOPUV);
+ luv = CustomData_bmesh_get(&bm->ldata, lnext->head.data, CD_MLOOPUV);
+
+ memcpy(preview->static_tris + buffer_index, fuv->uv, 2 * sizeof(float));
+ memcpy(preview->static_tris + buffer_index + 2, luv->uv, 2 * sizeof(float));
+ memcpy(preview->static_tris + buffer_index + 4, luvnext->uv, 2 * sizeof(float));
+ buffer_index += 6;
+ }
+ else {
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /******************************************************
+ * Here we calculate the final coordinates of the uvs *
+ ******************************************************/
+
+ if (ssc->mode == STITCH_VERT) {
+ final_position = MEM_callocN(state->selection_size * sizeof(*final_position),
+ "stitch_uv_average");
+ uvfinal_map = MEM_mallocN(state->element_map->totalUVs * sizeof(*uvfinal_map),
+ "stitch_uv_final_map");
+ }
+ else {
+ final_position = MEM_callocN(state->total_separate_uvs * sizeof(*final_position),
+ "stitch_uv_average");
+ }
+
+ /* first pass, calculate final position for stitchable uvs of the static island */
+ for (i = 0; i < state->selection_size; i++) {
+ if (ssc->mode == STITCH_VERT) {
+ UvElement *element = state->selection_stack[i];
+
+ if (element->flag & STITCH_STITCHABLE) {
+ BMLoop *l;
+ MLoopUV *luv;
+ UvElement *element_iter;
+
+ l = element->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+
+ uvfinal_map[element - state->element_map->buf] = i;
+
+ copy_v2_v2(final_position[i].uv, luv->uv);
+ final_position[i].count = 1;
+
+ if (ssc->snap_islands && element->island == ssc->static_island && !stitch_midpoints)
+ continue;
+
+ element_iter = state->element_map->vert[BM_elem_index_get(l->v)];
+
+ for (; element_iter; element_iter = element_iter->next) {
+ if (element_iter->separate) {
+ if (stitch_check_uvs_state_stitchable(element, element_iter, ssc, state)) {
+ l = element_iter->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ if (stitch_midpoints) {
+ add_v2_v2(final_position[i].uv, luv->uv);
+ final_position[i].count++;
+ }
+ else if (element_iter->island == ssc->static_island) {
+ /* if multiple uvs on the static island exist,
+ * last checked remains. to disambiguate we need to limit or use
+ * edge stitch */
+ copy_v2_v2(final_position[i].uv, luv->uv);
+ }
+ }
+ }
+ }
+ }
+ if (stitch_midpoints) {
+ final_position[i].uv[0] /= final_position[i].count;
+ final_position[i].uv[1] /= final_position[i].count;
+ }
+ }
+ else {
+ UvEdge *edge = state->selection_stack[i];
+
+ if (edge->flag & STITCH_STITCHABLE) {
+ MLoopUV *luv2, *luv1;
+ BMLoop *l;
+ UvEdge *edge_iter;
+
+ l = state->uvs[edge->uv1]->l;
+ luv1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ l = state->uvs[edge->uv2]->l;
+ luv2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+
+ copy_v2_v2(final_position[edge->uv1].uv, luv1->uv);
+ copy_v2_v2(final_position[edge->uv2].uv, luv2->uv);
+ final_position[edge->uv1].count = 1;
+ final_position[edge->uv2].count = 1;
+
+ state->uvs[edge->uv1]->flag |= STITCH_STITCHABLE;
+ state->uvs[edge->uv2]->flag |= STITCH_STITCHABLE;
+
+ if (ssc->snap_islands && edge->element->island == ssc->static_island && !stitch_midpoints)
+ continue;
+
+ for (edge_iter = edge->first; edge_iter; edge_iter = edge_iter->next) {
+ if (stitch_check_edges_state_stitchable(edge, edge_iter, ssc, state)) {
+ l = state->uvs[edge_iter->uv1]->l;
+ luv1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ l = state->uvs[edge_iter->uv2]->l;
+ luv2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (stitch_midpoints) {
+ add_v2_v2(final_position[edge->uv1].uv, luv1->uv);
+ final_position[edge->uv1].count++;
+ add_v2_v2(final_position[edge->uv2].uv, luv2->uv);
+ final_position[edge->uv2].count++;
+ }
+ else if (edge_iter->element->island == ssc->static_island) {
+ copy_v2_v2(final_position[edge->uv1].uv, luv1->uv);
+ copy_v2_v2(final_position[edge->uv2].uv, luv2->uv);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* take mean position here.
+ * For edge case, this can't be done inside the loop for shared uvverts */
+ if (ssc->mode == STITCH_EDGE && stitch_midpoints) {
+ for (i = 0; i < state->total_separate_uvs; i++) {
+ final_position[i].uv[0] /= final_position[i].count;
+ final_position[i].uv[1] /= final_position[i].count;
+ }
+ }
+
+ /* second pass, calculate island rotation and translation before modifying any uvs */
+ if (ssc->snap_islands) {
+ if (ssc->mode == STITCH_VERT) {
+ for (i = 0; i < state->selection_size; i++) {
+ UvElement *element = state->selection_stack[i];
+
+ if (element->flag & STITCH_STITCHABLE) {
+ BMLoop *l;
+ MLoopUV *luv;
+
+ l = element->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+
+ /* accumulate each islands' translation from stitchable elements. it is important to do here
+ * because in final pass MTFaces get modified and result is zero. */
+ island_stitch_data[element->island].translation[0] += final_position[i].uv[0] -
+ luv->uv[0];
+ island_stitch_data[element->island].translation[1] += final_position[i].uv[1] -
+ luv->uv[1];
+ island_stitch_data[element->island].medianPoint[0] += luv->uv[0];
+ island_stitch_data[element->island].medianPoint[1] += luv->uv[1];
+ island_stitch_data[element->island].numOfElements++;
+ }
+ }
+
+ /* only calculate rotation when an edge has been fully selected */
+ for (i = 0; i < state->total_separate_edges; i++) {
+ UvEdge *edge = state->edges + i;
+ if ((edge->flag & STITCH_BOUNDARY) && (state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) &&
+ (state->uvs[edge->uv2]->flag & STITCH_STITCHABLE)) {
+ stitch_island_calculate_edge_rotation(
+ edge, ssc, state, final_position, uvfinal_map, island_stitch_data);
+ island_stitch_data[state->uvs[edge->uv1]->island].use_edge_rotation = true;
+ }
+ }
+
+ /* clear seams of stitched edges */
+ if (final && ssc->clear_seams) {
+ for (i = 0; i < state->total_separate_edges; i++) {
+ UvEdge *edge = state->edges + i;
+ if ((state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) &&
+ (state->uvs[edge->uv2]->flag & STITCH_STITCHABLE)) {
+ BM_elem_flag_disable(edge->element->l->e, BM_ELEM_SEAM);
+ }
+ }
+ }
+
+ for (i = 0; i < state->selection_size; i++) {
+ UvElement *element = state->selection_stack[i];
+ if (!island_stitch_data[element->island].use_edge_rotation) {
+ if (element->flag & STITCH_STITCHABLE) {
+ stitch_island_calculate_vert_rotation(element, ssc, state, island_stitch_data);
+ }
+ }
+ }
+ }
+ else {
+ for (i = 0; i < state->total_separate_uvs; i++) {
+ UvElement *element = state->uvs[i];
+
+ if (element->flag & STITCH_STITCHABLE) {
+ BMLoop *l;
+ MLoopUV *luv;
+
+ l = element->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+
+ /* accumulate each islands' translation from stitchable elements. it is important to do here
+ * because in final pass MTFaces get modified and result is zero. */
+ island_stitch_data[element->island].translation[0] += final_position[i].uv[0] -
+ luv->uv[0];
+ island_stitch_data[element->island].translation[1] += final_position[i].uv[1] -
+ luv->uv[1];
+ island_stitch_data[element->island].medianPoint[0] += luv->uv[0];
+ island_stitch_data[element->island].medianPoint[1] += luv->uv[1];
+ island_stitch_data[element->island].numOfElements++;
+ }
+ }
+
+ for (i = 0; i < state->selection_size; i++) {
+ UvEdge *edge = state->selection_stack[i];
+
+ if (edge->flag & STITCH_STITCHABLE) {
+ stitch_island_calculate_edge_rotation(
+ edge, ssc, state, final_position, NULL, island_stitch_data);
+ island_stitch_data[state->uvs[edge->uv1]->island].use_edge_rotation = true;
+ }
+ }
+
+ /* clear seams of stitched edges */
+ if (final && ssc->clear_seams) {
+ for (i = 0; i < state->selection_size; i++) {
+ UvEdge *edge = state->selection_stack[i];
+ if (edge->flag & STITCH_STITCHABLE) {
+ BM_elem_flag_disable(edge->element->l->e, BM_ELEM_SEAM);
+ }
+ }
+ }
+ }
+ }
+
+ /* third pass, propagate changes to coincident uvs */
+ for (i = 0; i < state->selection_size; i++) {
+ if (ssc->mode == STITCH_VERT) {
+ UvElement *element = state->selection_stack[i];
+
+ stitch_propagate_uv_final_position(
+ scene, element, i, preview_position, final_position, ssc, state, final);
+ }
+ else {
+ UvEdge *edge = state->selection_stack[i];
+
+ stitch_propagate_uv_final_position(scene,
+ state->uvs[edge->uv1],
+ edge->uv1,
+ preview_position,
+ final_position,
+ ssc,
+ state,
+ final);
+ stitch_propagate_uv_final_position(scene,
+ state->uvs[edge->uv2],
+ edge->uv2,
+ preview_position,
+ final_position,
+ ssc,
+ state,
+ final);
+
+ edge->flag &= (STITCH_SELECTED | STITCH_BOUNDARY);
+ }
+ }
+
+ /* final pass, calculate Island translation/rotation if needed */
+ if (ssc->snap_islands) {
+ stitch_calculate_island_snapping(state, preview_position, preview, island_stitch_data, final);
+ }
+
+ MEM_freeN(final_position);
+ if (ssc->mode == STITCH_VERT) {
+ MEM_freeN(uvfinal_map);
+ }
+ MEM_freeN(island_stitch_data);
+ MEM_freeN(preview_position);
+
+ return 1;
}
static int stitch_process_data_all(StitchStateContainer *ssc, Scene *scene, int final)
{
- for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
- if (!stitch_process_data(ssc, ssc->states[ob_index], scene, final)) {
- return 0;
- }
- }
+ for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
+ if (!stitch_process_data(ssc, ssc->states[ob_index], scene, final)) {
+ return 0;
+ }
+ }
- return 1;
+ return 1;
}
/* Stitch hash initialization functions */
static unsigned int uv_edge_hash(const void *key)
{
- const UvEdge *edge = key;
- return (BLI_ghashutil_uinthash(edge->uv2) +
- BLI_ghashutil_uinthash(edge->uv1));
+ const UvEdge *edge = key;
+ return (BLI_ghashutil_uinthash(edge->uv2) + BLI_ghashutil_uinthash(edge->uv1));
}
static bool uv_edge_compare(const void *a, const void *b)
{
- const UvEdge *edge1 = a;
- const UvEdge *edge2 = b;
+ const UvEdge *edge1 = a;
+ const UvEdge *edge2 = b;
- if ((edge1->uv1 == edge2->uv1) && (edge1->uv2 == edge2->uv2)) {
- return 0;
- }
- return 1;
+ if ((edge1->uv1 == edge2->uv1) && (edge1->uv2 == edge2->uv2)) {
+ return 0;
+ }
+ return 1;
}
/* select all common edges */
static void stitch_select_edge(UvEdge *edge, StitchState *state, int always_select)
{
- UvEdge *eiter;
- UvEdge **selection_stack = (UvEdge **)state->selection_stack;
-
- for (eiter = edge->first; eiter; eiter = eiter->next) {
- if (eiter->flag & STITCH_SELECTED) {
- int i;
- if (always_select)
- continue;
-
- eiter->flag &= ~STITCH_SELECTED;
- for (i = 0; i < state->selection_size; i++) {
- if (selection_stack[i] == eiter) {
- (state->selection_size)--;
- selection_stack[i] = selection_stack[state->selection_size];
- break;
- }
- }
- }
- else {
- eiter->flag |= STITCH_SELECTED;
- selection_stack[state->selection_size++] = eiter;
- }
- }
+ UvEdge *eiter;
+ UvEdge **selection_stack = (UvEdge **)state->selection_stack;
+
+ for (eiter = edge->first; eiter; eiter = eiter->next) {
+ if (eiter->flag & STITCH_SELECTED) {
+ int i;
+ if (always_select)
+ continue;
+
+ eiter->flag &= ~STITCH_SELECTED;
+ for (i = 0; i < state->selection_size; i++) {
+ if (selection_stack[i] == eiter) {
+ (state->selection_size)--;
+ selection_stack[i] = selection_stack[state->selection_size];
+ break;
+ }
+ }
+ }
+ else {
+ eiter->flag |= STITCH_SELECTED;
+ selection_stack[state->selection_size++] = eiter;
+ }
+ }
}
-
/* Select all common uvs */
static void stitch_select_uv(UvElement *element, StitchState *state, int always_select)
{
- BMLoop *l;
- UvElement *element_iter;
- UvElement **selection_stack = (UvElement **)state->selection_stack;
-
- l = element->l;
-
- element_iter = state->element_map->vert[BM_elem_index_get(l->v)];
- /* first deselect all common uvs */
- for (; element_iter; element_iter = element_iter->next) {
- if (element_iter->separate) {
- /* only separators go to selection */
- if (element_iter->flag & STITCH_SELECTED) {
- int i;
- if (always_select)
- continue;
-
- element_iter->flag &= ~STITCH_SELECTED;
- for (i = 0; i < state->selection_size; i++) {
- if (selection_stack[i] == element_iter) {
- (state->selection_size)--;
- selection_stack[i] = selection_stack[state->selection_size];
- break;
- }
- }
- }
- else {
- element_iter->flag |= STITCH_SELECTED;
- selection_stack[state->selection_size++] = element_iter;
- }
- }
- }
+ BMLoop *l;
+ UvElement *element_iter;
+ UvElement **selection_stack = (UvElement **)state->selection_stack;
+
+ l = element->l;
+
+ element_iter = state->element_map->vert[BM_elem_index_get(l->v)];
+ /* first deselect all common uvs */
+ for (; element_iter; element_iter = element_iter->next) {
+ if (element_iter->separate) {
+ /* only separators go to selection */
+ if (element_iter->flag & STITCH_SELECTED) {
+ int i;
+ if (always_select)
+ continue;
+
+ element_iter->flag &= ~STITCH_SELECTED;
+ for (i = 0; i < state->selection_size; i++) {
+ if (selection_stack[i] == element_iter) {
+ (state->selection_size)--;
+ selection_stack[i] = selection_stack[state->selection_size];
+ break;
+ }
+ }
+ }
+ else {
+ element_iter->flag |= STITCH_SELECTED;
+ selection_stack[state->selection_size++] = element_iter;
+ }
+ }
+ }
}
static void stitch_set_selection_mode(StitchState *state, const char from_stitch_mode)
{
- void **old_selection_stack = state->selection_stack;
- int old_selection_size = state->selection_size;
- state->selection_size = 0;
-
- if (from_stitch_mode == STITCH_VERT) {
- int i;
- state->selection_stack = MEM_mallocN(state->total_separate_edges * sizeof(*state->selection_stack),
- "stitch_new_edge_selection_stack");
-
- /* check if both elements of an edge are selected */
- for (i = 0; i < state->total_separate_edges; i++) {
- UvEdge *edge = state->edges + i;
- UvElement *element1 = state->uvs[edge->uv1];
- UvElement *element2 = state->uvs[edge->uv2];
-
- if ((element1->flag & STITCH_SELECTED) && (element2->flag & STITCH_SELECTED))
- stitch_select_edge(edge, state, true);
- }
-
- /* unselect selected uvelements */
- for (i = 0; i < old_selection_size; i++) {
- UvElement *element = old_selection_stack[i];
-
- element->flag &= ~STITCH_SELECTED;
- }
- }
- else {
- int i;
- state->selection_stack = MEM_mallocN(state->total_separate_uvs * sizeof(*state->selection_stack),
- "stitch_new_vert_selection_stack");
-
- for (i = 0; i < old_selection_size; i++) {
- UvEdge *edge = old_selection_stack[i];
- UvElement *element1 = state->uvs[edge->uv1];
- UvElement *element2 = state->uvs[edge->uv2];
-
- stitch_select_uv(element1, state, true);
- stitch_select_uv(element2, state, true);
-
- edge->flag &= ~STITCH_SELECTED;
- }
- }
- MEM_freeN(old_selection_stack);
+ void **old_selection_stack = state->selection_stack;
+ int old_selection_size = state->selection_size;
+ state->selection_size = 0;
+
+ if (from_stitch_mode == STITCH_VERT) {
+ int i;
+ state->selection_stack = MEM_mallocN(state->total_separate_edges *
+ sizeof(*state->selection_stack),
+ "stitch_new_edge_selection_stack");
+
+ /* check if both elements of an edge are selected */
+ for (i = 0; i < state->total_separate_edges; i++) {
+ UvEdge *edge = state->edges + i;
+ UvElement *element1 = state->uvs[edge->uv1];
+ UvElement *element2 = state->uvs[edge->uv2];
+
+ if ((element1->flag & STITCH_SELECTED) && (element2->flag & STITCH_SELECTED))
+ stitch_select_edge(edge, state, true);
+ }
+
+ /* unselect selected uvelements */
+ for (i = 0; i < old_selection_size; i++) {
+ UvElement *element = old_selection_stack[i];
+
+ element->flag &= ~STITCH_SELECTED;
+ }
+ }
+ else {
+ int i;
+ state->selection_stack = MEM_mallocN(state->total_separate_uvs *
+ sizeof(*state->selection_stack),
+ "stitch_new_vert_selection_stack");
+
+ for (i = 0; i < old_selection_size; i++) {
+ UvEdge *edge = old_selection_stack[i];
+ UvElement *element1 = state->uvs[edge->uv1];
+ UvElement *element2 = state->uvs[edge->uv2];
+
+ stitch_select_uv(element1, state, true);
+ stitch_select_uv(element2, state, true);
+
+ edge->flag &= ~STITCH_SELECTED;
+ }
+ }
+ MEM_freeN(old_selection_stack);
}
static void stitch_switch_selection_mode_all(StitchStateContainer *ssc)
{
- for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
- stitch_set_selection_mode(ssc->states[ob_index], ssc->mode);
- }
-
- if (ssc->mode == STITCH_VERT) {
- ssc->mode = STITCH_EDGE;
- }
- else {
- ssc->mode = STITCH_VERT;
- }
+ for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
+ stitch_set_selection_mode(ssc->states[ob_index], ssc->mode);
+ }
+
+ if (ssc->mode == STITCH_VERT) {
+ ssc->mode = STITCH_EDGE;
+ }
+ else {
+ ssc->mode = STITCH_VERT;
+ }
}
-static void stitch_calculate_edge_normal(
- BMEditMesh *em, UvEdge *edge, float *normal, float aspect)
+static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *normal, float aspect)
{
- BMLoop *l1 = edge->element->l;
- MLoopUV *luv1, *luv2;
- float tangent[2];
+ BMLoop *l1 = edge->element->l;
+ MLoopUV *luv1, *luv2;
+ float tangent[2];
- luv1 = CustomData_bmesh_get(&em->bm->ldata, l1->head.data, CD_MLOOPUV);
- luv2 = CustomData_bmesh_get(&em->bm->ldata, l1->next->head.data, CD_MLOOPUV);
+ luv1 = CustomData_bmesh_get(&em->bm->ldata, l1->head.data, CD_MLOOPUV);
+ luv2 = CustomData_bmesh_get(&em->bm->ldata, l1->next->head.data, CD_MLOOPUV);
- sub_v2_v2v2(tangent, luv2->uv, luv1->uv);
+ sub_v2_v2v2(tangent, luv2->uv, luv1->uv);
- tangent[1] /= aspect;
+ tangent[1] /= aspect;
- normal[0] = tangent[1];
- normal[1] = -tangent[0];
+ normal[0] = tangent[1];
+ normal[1] = -tangent[0];
- normalize_v2(normal);
+ normalize_v2(normal);
}
/**
*/
static void stitch_draw_vbo(GPUVertBuf *vbo, GPUPrimType prim_type, const float col[4])
{
- GPUBatch *batch = GPU_batch_create_ex(prim_type, vbo, NULL, GPU_BATCH_OWNS_VBO);
- GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR);
- GPU_batch_uniform_4fv(batch, "color", col);
- GPU_batch_draw(batch);
- GPU_batch_discard(batch);
+ GPUBatch *batch = GPU_batch_create_ex(prim_type, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR);
+ GPU_batch_uniform_4fv(batch, "color", col);
+ GPU_batch_draw(batch);
+ GPU_batch_discard(batch);
}
/* 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)
{
- 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;
- 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;
- if (format.attr_len == 0) {
- pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- }
-
- GPU_blend(true);
-
- /* Static Tris */
- if (stitch_preview->static_tris) {
- UI_GetThemeColor4fv(TH_STITCH_PREVIEW_ACTIVE, col);
- vbo = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, stitch_preview->num_static_tris * 3);
- for (int i = 0; i < stitch_preview->num_static_tris * 3; i++) {
- GPU_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->static_tris[i * 2]);
- }
- stitch_draw_vbo(vbo, GPU_PRIM_TRIS, col);
- }
-
- /* Preview Polys */
- if (stitch_preview->preview_polys) {
- for (int i = 0; i < stitch_preview->num_polys; i++)
- num_line += stitch_preview->uvs_per_polygon[i];
-
- num_tri = num_line - 2 * stitch_preview->num_polys;
-
- /* we need to convert the polys into triangles / lines */
- vbo = GPU_vertbuf_create_with_format(&format);
- vbo_line = GPU_vertbuf_create_with_format(&format);
-
- GPU_vertbuf_data_alloc(vbo, num_tri * 3);
- GPU_vertbuf_data_alloc(vbo_line, num_line * 2);
-
-
- for (int i = 0; i < stitch_preview->num_polys; i++) {
- BLI_assert(stitch_preview->uvs_per_polygon[i] >= 3);
-
- /* Start line */
- GPU_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index]);
- GPU_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + 2]);
-
- for (j = 1; j < stitch_preview->uvs_per_polygon[i] - 1; ++j) {
- GPU_vertbuf_attr_set(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index]);
- GPU_vertbuf_attr_set(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index + (j + 0) * 2]);
- GPU_vertbuf_attr_set(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index + (j + 1) * 2]);
-
- GPU_vertbuf_attr_set(vbo_line,
- pos_id,
- line_idx++,
- &stitch_preview->preview_polys[index + (j + 0) * 2]);
- GPU_vertbuf_attr_set(vbo_line,
- pos_id,
- line_idx++,
- &stitch_preview->preview_polys[index + (j + 1) * 2]);
- }
-
- /* Closing line */
- GPU_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index]);
- /* j = uvs_per_polygon[i] - 1*/
- GPU_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + j * 2]);
-
- index += stitch_preview->uvs_per_polygon[i] * 2;
- }
-
- UI_GetThemeColor4fv(TH_STITCH_PREVIEW_FACE, col);
- stitch_draw_vbo(vbo, GPU_PRIM_TRIS, col);
- UI_GetThemeColor4fv(TH_STITCH_PREVIEW_EDGE, col);
- stitch_draw_vbo(vbo_line, GPU_PRIM_LINES, col);
- }
-
- GPU_blend(false);
-
- /* draw stitch vert/lines preview */
- if (ssc->mode == STITCH_VERT) {
- GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE) * 2.0f);
-
- UI_GetThemeColor4fv(TH_STITCH_PREVIEW_STITCHABLE, col);
- vbo = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, stitch_preview->num_stitchable);
- for (int i = 0; i < stitch_preview->num_stitchable; i++) {
- GPU_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_stitchable[i * 2]);
- }
- stitch_draw_vbo(vbo, GPU_PRIM_POINTS, col);
-
- UI_GetThemeColor4fv(TH_STITCH_PREVIEW_UNSTITCHABLE, col);
- vbo = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, stitch_preview->num_unstitchable);
- for (int i = 0; i < stitch_preview->num_unstitchable; i++) {
- GPU_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_unstitchable[i * 2]);
- }
- stitch_draw_vbo(vbo, GPU_PRIM_POINTS, col);
- }
- else {
- UI_GetThemeColor4fv(TH_STITCH_PREVIEW_STITCHABLE, col);
- vbo = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, stitch_preview->num_stitchable * 2);
- for (int i = 0; i < stitch_preview->num_stitchable * 2; i++) {
- GPU_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_stitchable[i * 2]);
- }
- stitch_draw_vbo(vbo, GPU_PRIM_LINES, col);
-
- UI_GetThemeColor4fv(TH_STITCH_PREVIEW_UNSTITCHABLE, col);
- vbo = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, stitch_preview->num_unstitchable * 2);
- for (int i = 0; i < stitch_preview->num_unstitchable * 2; i++) {
- GPU_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_unstitchable[i * 2]);
- }
- stitch_draw_vbo(vbo, GPU_PRIM_LINES, col);
- }
- }
+ 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;
+ 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;
+ if (format.attr_len == 0) {
+ pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ }
+
+ GPU_blend(true);
+
+ /* Static Tris */
+ if (stitch_preview->static_tris) {
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_ACTIVE, col);
+ vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, stitch_preview->num_static_tris * 3);
+ for (int i = 0; i < stitch_preview->num_static_tris * 3; i++) {
+ GPU_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->static_tris[i * 2]);
+ }
+ stitch_draw_vbo(vbo, GPU_PRIM_TRIS, col);
+ }
+
+ /* Preview Polys */
+ if (stitch_preview->preview_polys) {
+ for (int i = 0; i < stitch_preview->num_polys; i++)
+ num_line += stitch_preview->uvs_per_polygon[i];
+
+ num_tri = num_line - 2 * stitch_preview->num_polys;
+
+ /* we need to convert the polys into triangles / lines */
+ vbo = GPU_vertbuf_create_with_format(&format);
+ vbo_line = GPU_vertbuf_create_with_format(&format);
+
+ GPU_vertbuf_data_alloc(vbo, num_tri * 3);
+ GPU_vertbuf_data_alloc(vbo_line, num_line * 2);
+
+ for (int i = 0; i < stitch_preview->num_polys; i++) {
+ BLI_assert(stitch_preview->uvs_per_polygon[i] >= 3);
+
+ /* Start line */
+ GPU_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index]);
+ GPU_vertbuf_attr_set(
+ vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + 2]);
+
+ for (j = 1; j < stitch_preview->uvs_per_polygon[i] - 1; ++j) {
+ GPU_vertbuf_attr_set(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index]);
+ GPU_vertbuf_attr_set(
+ vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index + (j + 0) * 2]);
+ GPU_vertbuf_attr_set(
+ vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index + (j + 1) * 2]);
+
+ GPU_vertbuf_attr_set(
+ vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + (j + 0) * 2]);
+ GPU_vertbuf_attr_set(
+ vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + (j + 1) * 2]);
+ }
+
+ /* Closing line */
+ GPU_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index]);
+ /* j = uvs_per_polygon[i] - 1*/
+ GPU_vertbuf_attr_set(
+ vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + j * 2]);
+
+ index += stitch_preview->uvs_per_polygon[i] * 2;
+ }
+
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_FACE, col);
+ stitch_draw_vbo(vbo, GPU_PRIM_TRIS, col);
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_EDGE, col);
+ stitch_draw_vbo(vbo_line, GPU_PRIM_LINES, col);
+ }
+
+ GPU_blend(false);
+
+ /* draw stitch vert/lines preview */
+ if (ssc->mode == STITCH_VERT) {
+ GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE) * 2.0f);
+
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_STITCHABLE, col);
+ vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, stitch_preview->num_stitchable);
+ for (int i = 0; i < stitch_preview->num_stitchable; i++) {
+ GPU_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_stitchable[i * 2]);
+ }
+ stitch_draw_vbo(vbo, GPU_PRIM_POINTS, col);
+
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_UNSTITCHABLE, col);
+ vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, stitch_preview->num_unstitchable);
+ for (int i = 0; i < stitch_preview->num_unstitchable; i++) {
+ GPU_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_unstitchable[i * 2]);
+ }
+ stitch_draw_vbo(vbo, GPU_PRIM_POINTS, col);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_STITCHABLE, col);
+ vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, stitch_preview->num_stitchable * 2);
+ for (int i = 0; i < stitch_preview->num_stitchable * 2; i++) {
+ GPU_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_stitchable[i * 2]);
+ }
+ stitch_draw_vbo(vbo, GPU_PRIM_LINES, col);
+
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_UNSTITCHABLE, col);
+ vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, stitch_preview->num_unstitchable * 2);
+ for (int i = 0; i < stitch_preview->num_unstitchable * 2; i++) {
+ GPU_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_unstitchable[i * 2]);
+ }
+ stitch_draw_vbo(vbo, GPU_PRIM_LINES, col);
+ }
+ }
}
static UvEdge *uv_edge_get(BMLoop *l, StitchState *state)
{
- UvEdge tmp_edge;
+ UvEdge tmp_edge;
- UvElement *element1 = BM_uv_element_get(state->element_map, l->f, l);
- UvElement *element2 = BM_uv_element_get(state->element_map, l->f, l->next);
+ UvElement *element1 = BM_uv_element_get(state->element_map, l->f, l);
+ UvElement *element2 = BM_uv_element_get(state->element_map, l->f, l->next);
- int uv1 = state->map[element1 - state->element_map->buf];
- int uv2 = state->map[element2 - state->element_map->buf];
+ int uv1 = state->map[element1 - state->element_map->buf];
+ int uv2 = state->map[element2 - state->element_map->buf];
- if (uv1 < uv2) {
- tmp_edge.uv1 = uv1;
- tmp_edge.uv2 = uv2;
- }
- else {
- tmp_edge.uv1 = uv2;
- tmp_edge.uv2 = uv1;
- }
+ if (uv1 < uv2) {
+ tmp_edge.uv1 = uv1;
+ tmp_edge.uv2 = uv2;
+ }
+ else {
+ tmp_edge.uv1 = uv2;
+ tmp_edge.uv2 = uv1;
+ }
- return BLI_ghash_lookup(state->edge_hash, &tmp_edge);
+ return BLI_ghash_lookup(state->edge_hash, &tmp_edge);
}
-static StitchState *stitch_init(
- bContext *C, wmOperator *op,
- StitchStateContainer *ssc, Object *obedit, StitchStateInit *state_init)
+static StitchState *stitch_init(bContext *C,
+ wmOperator *op,
+ StitchStateContainer *ssc,
+ Object *obedit,
+ StitchStateInit *state_init)
{
- /* for fast edge lookup... */
- GHash *edge_hash;
- /* ...and actual edge storage */
- UvEdge *edges;
- int total_edges;
- /* maps uvelements to their first coincident uv */
- int *map;
- int counter = 0, i;
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- GHashIterator gh_iter;
- UvEdge *all_edges;
- StitchState *state;
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = scene->toolsettings;
- float aspx, aspy;
-
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- state = MEM_callocN(sizeof(StitchState), "stitch state obj");
-
- /* initialize state */
- state->obedit = obedit;
- state->em = em;
-
- /* in uv synch selection, all uv's are visible */
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- state->element_map = BM_uv_element_map_create(state->em->bm, false, true, true);
- }
- else {
- state->element_map = BM_uv_element_map_create(state->em->bm, true, true, true);
- }
- if (!state->element_map) {
- state_delete(state);
- return NULL;
- }
-
- ED_uvedit_get_aspect(scene, obedit, em->bm, &aspx, &aspy);
- state->aspect = aspx / aspy;
-
- /* Count 'unique' uvs */
- for (i = 0; i < state->element_map->totalUVs; i++) {
- if (state->element_map->buf[i].separate) {
- counter++;
- }
- }
-
- /* explicitly set preview to NULL,
- * to avoid deleting an invalid pointer on stitch_process_data */
- state->stitch_preview = NULL;
- /* Allocate the unique uv buffers */
- state->uvs = MEM_mallocN(sizeof(*state->uvs) * counter, "uv_stitch_unique_uvs");
- /* internal uvs need no normals but it is hard and slow to keep a map of
- * normals only for boundary uvs, so allocating for all uvs */
- state->normals = MEM_callocN(sizeof(*state->normals) * counter * 2, "uv_stitch_normals");
- state->total_separate_uvs = counter;
- state->map = map = MEM_mallocN(sizeof(*map) * state->element_map->totalUVs, "uv_stitch_unique_map");
- /* Allocate the edge stack */
- edge_hash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "stitch_edge_hash");
- all_edges = MEM_mallocN(sizeof(*all_edges) * state->element_map->totalUVs, "ssc_edges");
-
- if (!state->uvs || !map || !edge_hash || !all_edges) {
- state_delete(state);
- return NULL;
- }
-
- /* So that we can use this as index for the UvElements */
- counter = -1;
- /* initialize the unique UVs and map */
- for (i = 0; i < em->bm->totvert; i++) {
- UvElement *element = state->element_map->vert[i];
- for (; element; element = element->next) {
- if (element->separate) {
- counter++;
- state->uvs[counter] = element;
- }
- /* pointer arithmetic to the rescue, as always :)*/
- map[element - state->element_map->buf] = counter;
- }
- }
-
- counter = 0;
- /* Now, on to generate our uv connectivity data */
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!(ts->uv_flag & UV_SYNC_SELECTION) &&
- ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || !BM_elem_flag_test(efa, BM_ELEM_SELECT)))
- {
- continue;
- }
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- UvElement *element = BM_uv_element_get(state->element_map, efa, l);
- int offset1, itmp1 = element - state->element_map->buf;
- int offset2, itmp2 = BM_uv_element_get(state->element_map, efa, l->next) - state->element_map->buf;
- UvEdge *edge;
-
- offset1 = map[itmp1];
- offset2 = map[itmp2];
-
- all_edges[counter].next = NULL;
- all_edges[counter].first = NULL;
- all_edges[counter].flag = 0;
- all_edges[counter].element = element;
- /* using an order policy, sort uvs according to address space. This avoids
- * Having two different UvEdges with the same uvs on different positions */
- if (offset1 < offset2) {
- all_edges[counter].uv1 = offset1;
- all_edges[counter].uv2 = offset2;
- }
- else {
- all_edges[counter].uv1 = offset2;
- all_edges[counter].uv2 = offset1;
- }
-
- edge = BLI_ghash_lookup(edge_hash, &all_edges[counter]);
- if (edge) {
- edge->flag = 0;
- }
- else {
- BLI_ghash_insert(edge_hash, &all_edges[counter], &all_edges[counter]);
- all_edges[counter].flag = STITCH_BOUNDARY;
- }
- counter++;
- }
- }
-
- total_edges = BLI_ghash_len(edge_hash);
- state->edges = edges = MEM_mallocN(sizeof(*edges) * total_edges, "stitch_edges");
-
- /* I assume any system will be able to at least allocate an iterator :p */
- if (!edges) {
- state_delete(state);
- return NULL;
- }
-
- state->total_separate_edges = total_edges;
-
- /* fill the edges with data */
- i = 0;
- GHASH_ITER (gh_iter, edge_hash) {
- edges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(&gh_iter));
- }
-
- /* cleanup temporary stuff */
- MEM_freeN(all_edges);
-
- BLI_ghash_free(edge_hash, NULL, NULL);
-
- /* refill an edge hash to create edge connnectivity data */
- state->edge_hash = edge_hash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "stitch_edge_hash");
- for (i = 0; i < total_edges; i++) {
- BLI_ghash_insert(edge_hash, edges + i, edges + i);
- }
- stitch_uv_edge_generate_linked_edges(edge_hash, state);
-
- /***** calculate 2D normals for boundary uvs *****/
-
- /* we use boundary edges to calculate 2D normals.
- * to disambiguate the direction of the normal, we also need
- * a point "inside" the island, that can be provided by
- * the winding of the polygon (assuming counter-clockwise flow). */
-
- for (i = 0; i < total_edges; i++) {
- UvEdge *edge = edges + i;
- float normal[2];
- if (edge->flag & STITCH_BOUNDARY) {
- stitch_calculate_edge_normal(em, edge, normal, state->aspect);
-
- add_v2_v2(state->normals + edge->uv1 * 2, normal);
- add_v2_v2(state->normals + edge->uv2 * 2, normal);
-
- normalize_v2(state->normals + edge->uv1 * 2);
- normalize_v2(state->normals + edge->uv2 * 2);
- }
- }
-
-
- /***** fill selection stack *******/
-
- state->selection_size = 0;
-
- /* Load old selection if redoing operator with different settings */
- if (state_init != NULL) {
- int faceIndex, elementIndex;
- UvElement *element;
- enum StitchModes stored_mode = RNA_enum_get(op->ptr, "stored_mode");
-
- BM_mesh_elem_table_ensure(em->bm, BM_FACE);
-
- int selected_count = state_init->uv_selected_count;
-
- if (stored_mode == STITCH_VERT) {
- state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * state->total_separate_uvs,
- "uv_stitch_selection_stack");
-
- while (selected_count--) {
- faceIndex = state_init->to_select[selected_count].faceIndex;
- elementIndex = state_init->to_select[selected_count].elementIndex;
- efa = BM_face_at_index(em->bm, faceIndex);
- element = BM_uv_element_get(state->element_map,
- efa,
- BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
- stitch_select_uv(element, state, 1);
- }
- }
- else {
- state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * state->total_separate_edges,
- "uv_stitch_selection_stack");
-
- while (selected_count--) {
- UvEdge tmp_edge, *edge;
- int uv1, uv2;
- faceIndex = state_init->to_select[selected_count].faceIndex;
- elementIndex = state_init->to_select[selected_count].elementIndex;
- efa = BM_face_at_index(em->bm, faceIndex);
- element = BM_uv_element_get(state->element_map,
- efa,
- BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
- uv1 = map[element - state->element_map->buf];
-
- element = BM_uv_element_get(state->element_map,
- efa,
- BM_iter_at_index(NULL,
- BM_LOOPS_OF_FACE,
- efa,
- (elementIndex + 1) % efa->len));
- uv2 = map[element - state->element_map->buf];
-
- if (uv1 < uv2) {
- tmp_edge.uv1 = uv1;
- tmp_edge.uv2 = uv2;
- }
- else {
- tmp_edge.uv1 = uv2;
- tmp_edge.uv2 = uv1;
- }
-
- edge = BLI_ghash_lookup(edge_hash, &tmp_edge);
-
- stitch_select_edge(edge, state, true);
- }
- }
- /* if user has switched the operator mode after operation, we need to convert
- * the stored format */
- if (ssc->mode != stored_mode) {
- stitch_set_selection_mode(state, stored_mode);
- }
- }
- else {
- if (ssc->mode == STITCH_VERT) {
- state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * state->total_separate_uvs,
- "uv_stitch_selection_stack");
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- UvElement *element = BM_uv_element_get(state->element_map, efa, l);
- if (element) {
- stitch_select_uv(element, state, 1);
- }
- }
- }
- }
- }
- else {
- state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * state->total_separate_edges,
- "uv_stitch_selection_stack");
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!(ts->uv_flag & UV_SYNC_SELECTION) &&
- ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || !BM_elem_flag_test(efa, BM_ELEM_SELECT)))
- {
- continue;
- }
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (uvedit_edge_select_test(scene, l, cd_loop_uv_offset)) {
- UvEdge *edge = uv_edge_get(l, state);
- if (edge) {
- stitch_select_edge(edge, state, true);
- }
- }
- }
- }
- }
- }
-
- /***** initialize static island preview data *****/
-
- state->tris_per_island = MEM_mallocN(sizeof(*state->tris_per_island) * state->element_map->totalIslands,
- "stitch island tris");
- for (i = 0; i < state->element_map->totalIslands; i++) {
- state->tris_per_island[i] = 0;
- }
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- UvElement *element = BM_uv_element_get(state->element_map, efa, BM_FACE_FIRST_LOOP(efa));
-
- if (element) {
- state->tris_per_island[element->island] += (efa->len > 2) ? efa->len - 2 : 0;
- }
- }
-
- state->island_is_stitchable = MEM_callocN(sizeof(bool) * state->element_map->totalIslands, "stitch I stops");
- if (!state->island_is_stitchable) {
- state_delete(state);
- return NULL;
- }
-
- if (!stitch_process_data(ssc, state, scene, false)) {
- state_delete(state);
- return NULL;
- }
-
- return state;
+ /* for fast edge lookup... */
+ GHash *edge_hash;
+ /* ...and actual edge storage */
+ UvEdge *edges;
+ int total_edges;
+ /* maps uvelements to their first coincident uv */
+ int *map;
+ int counter = 0, i;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ GHashIterator gh_iter;
+ UvEdge *all_edges;
+ StitchState *state;
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
+ float aspx, aspy;
+
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ state = MEM_callocN(sizeof(StitchState), "stitch state obj");
+
+ /* initialize state */
+ state->obedit = obedit;
+ state->em = em;
+
+ /* in uv synch selection, all uv's are visible */
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ state->element_map = BM_uv_element_map_create(state->em->bm, false, true, true);
+ }
+ else {
+ state->element_map = BM_uv_element_map_create(state->em->bm, true, true, true);
+ }
+ if (!state->element_map) {
+ state_delete(state);
+ return NULL;
+ }
+
+ ED_uvedit_get_aspect(scene, obedit, em->bm, &aspx, &aspy);
+ state->aspect = aspx / aspy;
+
+ /* Count 'unique' uvs */
+ for (i = 0; i < state->element_map->totalUVs; i++) {
+ if (state->element_map->buf[i].separate) {
+ counter++;
+ }
+ }
+
+ /* explicitly set preview to NULL,
+ * to avoid deleting an invalid pointer on stitch_process_data */
+ state->stitch_preview = NULL;
+ /* Allocate the unique uv buffers */
+ state->uvs = MEM_mallocN(sizeof(*state->uvs) * counter, "uv_stitch_unique_uvs");
+ /* internal uvs need no normals but it is hard and slow to keep a map of
+ * normals only for boundary uvs, so allocating for all uvs */
+ state->normals = MEM_callocN(sizeof(*state->normals) * counter * 2, "uv_stitch_normals");
+ state->total_separate_uvs = counter;
+ state->map = map = MEM_mallocN(sizeof(*map) * state->element_map->totalUVs,
+ "uv_stitch_unique_map");
+ /* Allocate the edge stack */
+ edge_hash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "stitch_edge_hash");
+ all_edges = MEM_mallocN(sizeof(*all_edges) * state->element_map->totalUVs, "ssc_edges");
+
+ if (!state->uvs || !map || !edge_hash || !all_edges) {
+ state_delete(state);
+ return NULL;
+ }
+
+ /* So that we can use this as index for the UvElements */
+ counter = -1;
+ /* initialize the unique UVs and map */
+ for (i = 0; i < em->bm->totvert; i++) {
+ UvElement *element = state->element_map->vert[i];
+ for (; element; element = element->next) {
+ if (element->separate) {
+ counter++;
+ state->uvs[counter] = element;
+ }
+ /* pointer arithmetic to the rescue, as always :)*/
+ map[element - state->element_map->buf] = counter;
+ }
+ }
+
+ counter = 0;
+ /* Now, on to generate our uv connectivity data */
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!(ts->uv_flag & UV_SYNC_SELECTION) &&
+ ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || !BM_elem_flag_test(efa, BM_ELEM_SELECT))) {
+ continue;
+ }
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ UvElement *element = BM_uv_element_get(state->element_map, efa, l);
+ int offset1, itmp1 = element - state->element_map->buf;
+ int offset2,
+ itmp2 = BM_uv_element_get(state->element_map, efa, l->next) - state->element_map->buf;
+ UvEdge *edge;
+
+ offset1 = map[itmp1];
+ offset2 = map[itmp2];
+
+ all_edges[counter].next = NULL;
+ all_edges[counter].first = NULL;
+ all_edges[counter].flag = 0;
+ all_edges[counter].element = element;
+ /* using an order policy, sort uvs according to address space. This avoids
+ * Having two different UvEdges with the same uvs on different positions */
+ if (offset1 < offset2) {
+ all_edges[counter].uv1 = offset1;
+ all_edges[counter].uv2 = offset2;
+ }
+ else {
+ all_edges[counter].uv1 = offset2;
+ all_edges[counter].uv2 = offset1;
+ }
+
+ edge = BLI_ghash_lookup(edge_hash, &all_edges[counter]);
+ if (edge) {
+ edge->flag = 0;
+ }
+ else {
+ BLI_ghash_insert(edge_hash, &all_edges[counter], &all_edges[counter]);
+ all_edges[counter].flag = STITCH_BOUNDARY;
+ }
+ counter++;
+ }
+ }
+
+ total_edges = BLI_ghash_len(edge_hash);
+ state->edges = edges = MEM_mallocN(sizeof(*edges) * total_edges, "stitch_edges");
+
+ /* I assume any system will be able to at least allocate an iterator :p */
+ if (!edges) {
+ state_delete(state);
+ return NULL;
+ }
+
+ state->total_separate_edges = total_edges;
+
+ /* fill the edges with data */
+ i = 0;
+ GHASH_ITER (gh_iter, edge_hash) {
+ edges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(&gh_iter));
+ }
+
+ /* cleanup temporary stuff */
+ MEM_freeN(all_edges);
+
+ BLI_ghash_free(edge_hash, NULL, NULL);
+
+ /* refill an edge hash to create edge connnectivity data */
+ state->edge_hash = edge_hash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "stitch_edge_hash");
+ for (i = 0; i < total_edges; i++) {
+ BLI_ghash_insert(edge_hash, edges + i, edges + i);
+ }
+ stitch_uv_edge_generate_linked_edges(edge_hash, state);
+
+ /***** calculate 2D normals for boundary uvs *****/
+
+ /* we use boundary edges to calculate 2D normals.
+ * to disambiguate the direction of the normal, we also need
+ * a point "inside" the island, that can be provided by
+ * the winding of the polygon (assuming counter-clockwise flow). */
+
+ for (i = 0; i < total_edges; i++) {
+ UvEdge *edge = edges + i;
+ float normal[2];
+ if (edge->flag & STITCH_BOUNDARY) {
+ stitch_calculate_edge_normal(em, edge, normal, state->aspect);
+
+ add_v2_v2(state->normals + edge->uv1 * 2, normal);
+ add_v2_v2(state->normals + edge->uv2 * 2, normal);
+
+ normalize_v2(state->normals + edge->uv1 * 2);
+ normalize_v2(state->normals + edge->uv2 * 2);
+ }
+ }
+
+ /***** fill selection stack *******/
+
+ state->selection_size = 0;
+
+ /* Load old selection if redoing operator with different settings */
+ if (state_init != NULL) {
+ int faceIndex, elementIndex;
+ UvElement *element;
+ enum StitchModes stored_mode = RNA_enum_get(op->ptr, "stored_mode");
+
+ BM_mesh_elem_table_ensure(em->bm, BM_FACE);
+
+ int selected_count = state_init->uv_selected_count;
+
+ if (stored_mode == STITCH_VERT) {
+ state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) *
+ state->total_separate_uvs,
+ "uv_stitch_selection_stack");
+
+ while (selected_count--) {
+ faceIndex = state_init->to_select[selected_count].faceIndex;
+ elementIndex = state_init->to_select[selected_count].elementIndex;
+ efa = BM_face_at_index(em->bm, faceIndex);
+ element = BM_uv_element_get(
+ state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
+ stitch_select_uv(element, state, 1);
+ }
+ }
+ else {
+ state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) *
+ state->total_separate_edges,
+ "uv_stitch_selection_stack");
+
+ while (selected_count--) {
+ UvEdge tmp_edge, *edge;
+ int uv1, uv2;
+ faceIndex = state_init->to_select[selected_count].faceIndex;
+ elementIndex = state_init->to_select[selected_count].elementIndex;
+ efa = BM_face_at_index(em->bm, faceIndex);
+ element = BM_uv_element_get(
+ state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
+ uv1 = map[element - state->element_map->buf];
+
+ element = BM_uv_element_get(
+ state->element_map,
+ efa,
+ BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, (elementIndex + 1) % efa->len));
+ uv2 = map[element - state->element_map->buf];
+
+ if (uv1 < uv2) {
+ tmp_edge.uv1 = uv1;
+ tmp_edge.uv2 = uv2;
+ }
+ else {
+ tmp_edge.uv1 = uv2;
+ tmp_edge.uv2 = uv1;
+ }
+
+ edge = BLI_ghash_lookup(edge_hash, &tmp_edge);
+
+ stitch_select_edge(edge, state, true);
+ }
+ }
+ /* if user has switched the operator mode after operation, we need to convert
+ * the stored format */
+ if (ssc->mode != stored_mode) {
+ stitch_set_selection_mode(state, stored_mode);
+ }
+ }
+ else {
+ if (ssc->mode == STITCH_VERT) {
+ state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) *
+ state->total_separate_uvs,
+ "uv_stitch_selection_stack");
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i)
+ {
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ UvElement *element = BM_uv_element_get(state->element_map, efa, l);
+ if (element) {
+ stitch_select_uv(element, state, 1);
+ }
+ }
+ }
+ }
+ }
+ else {
+ state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) *
+ state->total_separate_edges,
+ "uv_stitch_selection_stack");
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!(ts->uv_flag & UV_SYNC_SELECTION) && ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) ||
+ !BM_elem_flag_test(efa, BM_ELEM_SELECT))) {
+ continue;
+ }
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (uvedit_edge_select_test(scene, l, cd_loop_uv_offset)) {
+ UvEdge *edge = uv_edge_get(l, state);
+ if (edge) {
+ stitch_select_edge(edge, state, true);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /***** initialize static island preview data *****/
+
+ state->tris_per_island = MEM_mallocN(
+ sizeof(*state->tris_per_island) * state->element_map->totalIslands, "stitch island tris");
+ for (i = 0; i < state->element_map->totalIslands; i++) {
+ state->tris_per_island[i] = 0;
+ }
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ UvElement *element = BM_uv_element_get(state->element_map, efa, BM_FACE_FIRST_LOOP(efa));
+
+ if (element) {
+ state->tris_per_island[element->island] += (efa->len > 2) ? efa->len - 2 : 0;
+ }
+ }
+
+ state->island_is_stitchable = MEM_callocN(sizeof(bool) * state->element_map->totalIslands,
+ "stitch I stops");
+ if (!state->island_is_stitchable) {
+ state_delete(state);
+ return NULL;
+ }
+
+ if (!stitch_process_data(ssc, state, scene, false)) {
+ state_delete(state);
+ return NULL;
+ }
+
+ return state;
}
static bool goto_next_island(StitchStateContainer *ssc)
{
- StitchState *active_state = ssc->states[ssc->active_object_index];
- StitchState *original_active_state = active_state;
-
- int original_island = ssc->static_island;
-
- do {
- ssc->static_island++;
- if (ssc->static_island >= active_state->element_map->totalIslands) {
- /* go to next object */
- ssc->active_object_index++;
- ssc->active_object_index %= ssc->objects_len;
-
- active_state = ssc->states[ssc->active_object_index];
- ssc->static_island = 0;
- }
-
- if (active_state->island_is_stitchable[ssc->static_island]) {
- /* We're at an island to make active */
- return true;
- }
- } while (!(active_state == original_active_state &&
- ssc->static_island == original_island));
-
- return false;
+ StitchState *active_state = ssc->states[ssc->active_object_index];
+ StitchState *original_active_state = active_state;
+
+ int original_island = ssc->static_island;
+
+ do {
+ ssc->static_island++;
+ if (ssc->static_island >= active_state->element_map->totalIslands) {
+ /* go to next object */
+ ssc->active_object_index++;
+ ssc->active_object_index %= ssc->objects_len;
+
+ active_state = ssc->states[ssc->active_object_index];
+ ssc->static_island = 0;
+ }
+
+ if (active_state->island_is_stitchable[ssc->static_island]) {
+ /* We're at an island to make active */
+ return true;
+ }
+ } while (!(active_state == original_active_state && ssc->static_island == original_island));
+
+ return false;
}
static int stitch_init_all(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
- if (!ar)
- return 0;
-
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = scene->toolsettings;
-
- StitchStateContainer *ssc = MEM_callocN(sizeof(StitchStateContainer), "stitch collection");
-
- op->customdata = ssc;
-
- ssc->use_limit = RNA_boolean_get(op->ptr, "use_limit");
- ssc->limit_dist = RNA_float_get(op->ptr, "limit");
- ssc->snap_islands = RNA_boolean_get(op->ptr, "snap_islands");
- ssc->midpoints = RNA_boolean_get(op->ptr, "midpoint_snap");
- ssc->clear_seams = RNA_boolean_get(op->ptr, "clear_seams");
- ssc->active_object_index = RNA_int_get(op->ptr, "active_object_index");
- ssc->static_island = 0;
-
- if (RNA_struct_property_is_set(op->ptr, "mode")) {
- ssc->mode = RNA_enum_get(op->ptr, "mode");
- }
- else {
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- if (ts->selectmode & SCE_SELECT_VERTEX)
- ssc->mode = STITCH_VERT;
- else
- ssc->mode = STITCH_EDGE;
- }
- else {
- if (ts->uv_selectmode & UV_SELECT_VERTEX) {
- ssc->mode = STITCH_VERT;
- }
- else {
- ssc->mode = STITCH_EDGE;
- }
- }
- }
-
- ssc->objects_len = 0;
- ssc->states = NULL;
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(view_layer, v3d, &objects_len);
-
- if (objects_len == 0) {
- MEM_freeN(objects);
- state_delete_all(ssc);
- return 0;
- }
-
- ssc->objects = MEM_callocN(sizeof(Object *) * objects_len, "Object *ssc->objects");
- ssc->states = MEM_callocN(sizeof(StitchState *) * objects_len, "StitchState");
- ssc->objects_len = 0;
-
- int *objs_selection_count = NULL;
- UvElementID *selected_uvs_arr = NULL;
- StitchStateInit *state_init = NULL;
-
- if (RNA_struct_property_is_set(op->ptr, "selection") &&
- RNA_struct_property_is_set(op->ptr, "objects_selection_count"))
- {
- /* Retrieve list of selected UVs, one list contains all selected UVs
- * for all objects. */
-
- objs_selection_count = MEM_mallocN(sizeof(int *) * objects_len, "objects_selection_count");
- RNA_int_get_array(op->ptr, "objects_selection_count", objs_selection_count);
-
- int total_selected = 0;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- total_selected += objs_selection_count[ob_index];
- }
-
- selected_uvs_arr = MEM_callocN(sizeof(UvElementID) * total_selected, "selected_uvs_arr");
- int sel_idx = 0;
- RNA_BEGIN (op->ptr, itemptr, "selection")
- {
- BLI_assert(sel_idx < total_selected);
- selected_uvs_arr[sel_idx].faceIndex = RNA_int_get(&itemptr, "face_index");
- selected_uvs_arr[sel_idx].elementIndex = RNA_int_get(&itemptr, "element_index");
- sel_idx++;
- }
- RNA_END;
-
- RNA_collection_clear(op->ptr, "selection");
-
- state_init = MEM_callocN(sizeof(StitchStateInit), "UV_init_selected");
- state_init->to_select = selected_uvs_arr;
- }
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
-
- if (state_init != NULL) {
- state_init->uv_selected_count = objs_selection_count[ob_index];
- }
-
- StitchState *stitch_state_ob = stitch_init(C, op, ssc, obedit, state_init);
-
- if (state_init != NULL) {
- /* Move pointer to beginning of next object's data. */
- state_init->to_select += state_init->uv_selected_count;
- }
-
- if (stitch_state_ob) {
- ssc->objects[ssc->objects_len] = obedit;
- ssc->states[ssc->objects_len] = stitch_state_ob;
- ssc->objects_len++;
- }
- }
-
- MEM_freeN(objects);
- MEM_SAFE_FREE(selected_uvs_arr);
- MEM_SAFE_FREE(objs_selection_count);
- MEM_SAFE_FREE(state_init);
-
- if (ssc->objects_len == 0) {
- state_delete_all(ssc);
- return 0;
- }
-
- ssc->active_object_index %= ssc->objects_len;
-
- ssc->static_island = RNA_int_get(op->ptr, "static_island");
-
- StitchState *state = ssc->states[ssc->active_object_index];
- ssc->static_island %= state->element_map->totalIslands;
-
- /* If the initial active object doesn't have any stitchable islands */
- /* then no active island will be seen in the UI. Make sure we're on */
- /* a stitchable object and island. */
- if (!state->island_is_stitchable[ssc->static_island]) {
- goto_next_island(ssc);
- state = ssc->states[ssc->active_object_index];
- }
-
- /* process active stitchobj again now that it can detect it's the active stitchobj */
- stitch_process_data(ssc, state, scene, false);
-
- stitch_update_header(ssc, C);
-
- ssc->draw_handle = ED_region_draw_cb_activate(ar->type, stitch_draw, ssc, REGION_DRAW_POST_VIEW);
-
- return 1;
+ ARegion *ar = CTX_wm_region(C);
+ if (!ar)
+ return 0;
+
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
+
+ StitchStateContainer *ssc = MEM_callocN(sizeof(StitchStateContainer), "stitch collection");
+
+ op->customdata = ssc;
+
+ ssc->use_limit = RNA_boolean_get(op->ptr, "use_limit");
+ ssc->limit_dist = RNA_float_get(op->ptr, "limit");
+ ssc->snap_islands = RNA_boolean_get(op->ptr, "snap_islands");
+ ssc->midpoints = RNA_boolean_get(op->ptr, "midpoint_snap");
+ ssc->clear_seams = RNA_boolean_get(op->ptr, "clear_seams");
+ ssc->active_object_index = RNA_int_get(op->ptr, "active_object_index");
+ ssc->static_island = 0;
+
+ if (RNA_struct_property_is_set(op->ptr, "mode")) {
+ ssc->mode = RNA_enum_get(op->ptr, "mode");
+ }
+ else {
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ if (ts->selectmode & SCE_SELECT_VERTEX)
+ ssc->mode = STITCH_VERT;
+ else
+ ssc->mode = STITCH_EDGE;
+ }
+ else {
+ if (ts->uv_selectmode & UV_SELECT_VERTEX) {
+ ssc->mode = STITCH_VERT;
+ }
+ else {
+ ssc->mode = STITCH_EDGE;
+ }
+ }
+ }
+
+ ssc->objects_len = 0;
+ ssc->states = NULL;
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, v3d, &objects_len);
+
+ if (objects_len == 0) {
+ MEM_freeN(objects);
+ state_delete_all(ssc);
+ return 0;
+ }
+
+ ssc->objects = MEM_callocN(sizeof(Object *) * objects_len, "Object *ssc->objects");
+ ssc->states = MEM_callocN(sizeof(StitchState *) * objects_len, "StitchState");
+ ssc->objects_len = 0;
+
+ int *objs_selection_count = NULL;
+ UvElementID *selected_uvs_arr = NULL;
+ StitchStateInit *state_init = NULL;
+
+ if (RNA_struct_property_is_set(op->ptr, "selection") &&
+ RNA_struct_property_is_set(op->ptr, "objects_selection_count")) {
+ /* Retrieve list of selected UVs, one list contains all selected UVs
+ * for all objects. */
+
+ objs_selection_count = MEM_mallocN(sizeof(int *) * objects_len, "objects_selection_count");
+ RNA_int_get_array(op->ptr, "objects_selection_count", objs_selection_count);
+
+ int total_selected = 0;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ total_selected += objs_selection_count[ob_index];
+ }
+
+ selected_uvs_arr = MEM_callocN(sizeof(UvElementID) * total_selected, "selected_uvs_arr");
+ int sel_idx = 0;
+ RNA_BEGIN (op->ptr, itemptr, "selection") {
+ BLI_assert(sel_idx < total_selected);
+ selected_uvs_arr[sel_idx].faceIndex = RNA_int_get(&itemptr, "face_index");
+ selected_uvs_arr[sel_idx].elementIndex = RNA_int_get(&itemptr, "element_index");
+ sel_idx++;
+ }
+ RNA_END;
+
+ RNA_collection_clear(op->ptr, "selection");
+
+ state_init = MEM_callocN(sizeof(StitchStateInit), "UV_init_selected");
+ state_init->to_select = selected_uvs_arr;
+ }
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+
+ if (state_init != NULL) {
+ state_init->uv_selected_count = objs_selection_count[ob_index];
+ }
+
+ StitchState *stitch_state_ob = stitch_init(C, op, ssc, obedit, state_init);
+
+ if (state_init != NULL) {
+ /* Move pointer to beginning of next object's data. */
+ state_init->to_select += state_init->uv_selected_count;
+ }
+
+ if (stitch_state_ob) {
+ ssc->objects[ssc->objects_len] = obedit;
+ ssc->states[ssc->objects_len] = stitch_state_ob;
+ ssc->objects_len++;
+ }
+ }
+
+ MEM_freeN(objects);
+ MEM_SAFE_FREE(selected_uvs_arr);
+ MEM_SAFE_FREE(objs_selection_count);
+ MEM_SAFE_FREE(state_init);
+
+ if (ssc->objects_len == 0) {
+ state_delete_all(ssc);
+ return 0;
+ }
+
+ ssc->active_object_index %= ssc->objects_len;
+
+ ssc->static_island = RNA_int_get(op->ptr, "static_island");
+
+ StitchState *state = ssc->states[ssc->active_object_index];
+ ssc->static_island %= state->element_map->totalIslands;
+
+ /* If the initial active object doesn't have any stitchable islands */
+ /* then no active island will be seen in the UI. Make sure we're on */
+ /* a stitchable object and island. */
+ if (!state->island_is_stitchable[ssc->static_island]) {
+ goto_next_island(ssc);
+ state = ssc->states[ssc->active_object_index];
+ }
+
+ /* process active stitchobj again now that it can detect it's the active stitchobj */
+ stitch_process_data(ssc, state, scene, false);
+
+ stitch_update_header(ssc, C);
+
+ ssc->draw_handle = ED_region_draw_cb_activate(ar->type, stitch_draw, ssc, REGION_DRAW_POST_VIEW);
+
+ return 1;
}
static int stitch_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (!stitch_init_all(C, op))
- return OPERATOR_CANCELLED;
+ if (!stitch_init_all(C, op))
+ return OPERATOR_CANCELLED;
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = scene->toolsettings;
- const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
+ const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
- StitchStateContainer *ssc = (StitchStateContainer *)op->customdata;
+ StitchStateContainer *ssc = (StitchStateContainer *)op->customdata;
- for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
- StitchState *state = ssc->states[ob_index];
- Object *obedit = state->obedit;
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
+ StitchState *state = ssc->states[ob_index];
+ Object *obedit = state->obedit;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (synced_selection && (em->bm->totvertsel == 0)) {
- continue;
- }
+ if (synced_selection && (em->bm->totvertsel == 0)) {
+ continue;
+ }
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- }
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ }
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
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);
-
- StitchStateContainer *ssc = (StitchStateContainer *)op->customdata;
-
- if (finished) {
- RNA_float_set(op->ptr, "limit", ssc->limit_dist);
- RNA_boolean_set(op->ptr, "use_limit", ssc->use_limit);
- RNA_boolean_set(op->ptr, "snap_islands", ssc->snap_islands);
- RNA_boolean_set(op->ptr, "midpoint_snap", ssc->midpoints);
- RNA_boolean_set(op->ptr, "clear_seams", ssc->clear_seams);
- RNA_enum_set(op->ptr, "mode", ssc->mode);
- RNA_enum_set(op->ptr, "stored_mode", ssc->mode);
- RNA_int_set(op->ptr, "active_object_index", ssc->active_object_index);
-
- RNA_int_set(op->ptr, "static_island", ssc->static_island);
-
- int *objs_selection_count = NULL;
- objs_selection_count = MEM_mallocN(sizeof(int *) * ssc->objects_len, "objects_selection_count");
-
- /* Store selection for re-execution of stitch
- * - Store all selected UVs in "selection"
- * - Store how many each object has in "objects_selection_count". */
- RNA_collection_clear(op->ptr, "selection");
- for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
- StitchState *state = ssc->states[ob_index];
- Object *obedit = state->obedit;
-
- PointerRNA itemptr;
- for (int i = 0; i < state->selection_size; i++) {
- UvElement *element;
-
- if (ssc->mode == STITCH_VERT) {
- element = state->selection_stack[i];
- }
- else {
- element = ((UvEdge *)state->selection_stack[i])->element;
- }
- RNA_collection_add(op->ptr, "selection", &itemptr);
-
- RNA_int_set(&itemptr, "face_index", BM_elem_index_get(element->l->f));
- RNA_int_set(&itemptr, "element_index", element->loop_of_poly_index);
- }
- uvedit_live_unwrap_update(sima, scene, obedit);
-
- objs_selection_count[ob_index] = state->selection_size;
- }
-
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, "objects_selection_count");
- RNA_def_property_array(prop, ssc->objects_len);
- RNA_int_set_array(op->ptr, "objects_selection_count", objs_selection_count);
- MEM_freeN(objs_selection_count);
- }
-
- if (sa)
- ED_workspace_status_text(C, NULL);
-
- ED_region_draw_cb_exit(CTX_wm_region(C)->type, ssc->draw_handle);
-
- ToolSettings *ts = scene->toolsettings;
- const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
-
- for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
- StitchState *state = ssc->states[ob_index];
- Object *obedit = state->obedit;
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (synced_selection && (em->bm->totvertsel == 0)) {
- continue;
- }
-
- DEG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- }
-
- state_delete_all(ssc);
-
- op->customdata = NULL;
+ Scene *scene = CTX_data_scene(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ScrArea *sa = CTX_wm_area(C);
+
+ StitchStateContainer *ssc = (StitchStateContainer *)op->customdata;
+
+ if (finished) {
+ RNA_float_set(op->ptr, "limit", ssc->limit_dist);
+ RNA_boolean_set(op->ptr, "use_limit", ssc->use_limit);
+ RNA_boolean_set(op->ptr, "snap_islands", ssc->snap_islands);
+ RNA_boolean_set(op->ptr, "midpoint_snap", ssc->midpoints);
+ RNA_boolean_set(op->ptr, "clear_seams", ssc->clear_seams);
+ RNA_enum_set(op->ptr, "mode", ssc->mode);
+ RNA_enum_set(op->ptr, "stored_mode", ssc->mode);
+ RNA_int_set(op->ptr, "active_object_index", ssc->active_object_index);
+
+ RNA_int_set(op->ptr, "static_island", ssc->static_island);
+
+ int *objs_selection_count = NULL;
+ objs_selection_count = MEM_mallocN(sizeof(int *) * ssc->objects_len,
+ "objects_selection_count");
+
+ /* Store selection for re-execution of stitch
+ * - Store all selected UVs in "selection"
+ * - Store how many each object has in "objects_selection_count". */
+ RNA_collection_clear(op->ptr, "selection");
+ for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
+ StitchState *state = ssc->states[ob_index];
+ Object *obedit = state->obedit;
+
+ PointerRNA itemptr;
+ for (int i = 0; i < state->selection_size; i++) {
+ UvElement *element;
+
+ if (ssc->mode == STITCH_VERT) {
+ element = state->selection_stack[i];
+ }
+ else {
+ element = ((UvEdge *)state->selection_stack[i])->element;
+ }
+ RNA_collection_add(op->ptr, "selection", &itemptr);
+
+ RNA_int_set(&itemptr, "face_index", BM_elem_index_get(element->l->f));
+ RNA_int_set(&itemptr, "element_index", element->loop_of_poly_index);
+ }
+ uvedit_live_unwrap_update(sima, scene, obedit);
+
+ objs_selection_count[ob_index] = state->selection_size;
+ }
+
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "objects_selection_count");
+ RNA_def_property_array(prop, ssc->objects_len);
+ RNA_int_set_array(op->ptr, "objects_selection_count", objs_selection_count);
+ MEM_freeN(objs_selection_count);
+ }
+
+ if (sa)
+ ED_workspace_status_text(C, NULL);
+
+ ED_region_draw_cb_exit(CTX_wm_region(C)->type, ssc->draw_handle);
+
+ ToolSettings *ts = scene->toolsettings;
+ const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
+
+ for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
+ StitchState *state = ssc->states[ob_index];
+ Object *obedit = state->obedit;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (synced_selection && (em->bm->totvertsel == 0)) {
+ continue;
+ }
+
+ DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ }
+
+ state_delete_all(ssc);
+
+ op->customdata = NULL;
}
-
static void stitch_cancel(bContext *C, wmOperator *op)
{
- stitch_exit(C, op, 0);
+ stitch_exit(C, op, 0);
}
-
static int stitch_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
-
- if (!stitch_init_all(C, op))
- return OPERATOR_CANCELLED;
- if (stitch_process_data_all((StitchStateContainer *)op->customdata, scene, 1)) {
- stitch_exit(C, op, 1);
- return OPERATOR_FINISHED;
- }
- else {
- stitch_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
+ Scene *scene = CTX_data_scene(C);
+
+ if (!stitch_init_all(C, op))
+ return OPERATOR_CANCELLED;
+ if (stitch_process_data_all((StitchStateContainer *)op->customdata, scene, 1)) {
+ stitch_exit(C, op, 1);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ stitch_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
}
-static StitchState *stitch_select(
- bContext *C, Scene *scene, const wmEvent *event, StitchStateContainer *ssc)
+static StitchState *stitch_select(bContext *C,
+ Scene *scene,
+ const wmEvent *event,
+ StitchStateContainer *ssc)
{
- /* add uv under mouse to processed uv's */
- float co[2];
- UvNearestHit hit = UV_NEAREST_HIT_INIT;
- ARegion *ar = 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]);
-
- if (ssc->mode == STITCH_VERT) {
- if (uv_find_nearest_vert_multi(scene, ima, ssc->objects, ssc->objects_len, co, 0.0f, &hit)) {
- /* Add vertex to selection, deselect all common uv's of vert other than selected and
- * update the preview. This behavior was decided so that you can do stuff like deselect
- * the opposite stitchable vertex and the initial still gets deselected */
-
- /* find StitchState from hit->ob */
- StitchState *state = NULL;
- for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
- if (hit.ob == ssc->objects[ob_index]) {
- state = ssc->states[ob_index];
- break;
- }
- }
-
- /* This works due to setting of tmp in find nearest uv vert */
- UvElement *element = BM_uv_element_get(state->element_map, hit.efa, hit.l);
- stitch_select_uv(element, state, false);
-
- return state;
- }
- }
- else if (uv_find_nearest_edge_multi(scene, ima, ssc->objects, ssc->objects_len, co, &hit)) {
- /* find StitchState from hit->ob */
- StitchState *state = NULL;
- for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
- if (hit.ob == ssc->objects[ob_index]) {
- state = ssc->states[ob_index];
- break;
- }
- }
-
- UvEdge *edge = uv_edge_get(hit.l, state);
- stitch_select_edge(edge, state, false);
-
- return state;
- }
-
- return NULL;
+ /* add uv under mouse to processed uv's */
+ float co[2];
+ UvNearestHit hit = UV_NEAREST_HIT_INIT;
+ ARegion *ar = 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]);
+
+ if (ssc->mode == STITCH_VERT) {
+ if (uv_find_nearest_vert_multi(scene, ima, ssc->objects, ssc->objects_len, co, 0.0f, &hit)) {
+ /* Add vertex to selection, deselect all common uv's of vert other than selected and
+ * update the preview. This behavior was decided so that you can do stuff like deselect
+ * the opposite stitchable vertex and the initial still gets deselected */
+
+ /* find StitchState from hit->ob */
+ StitchState *state = NULL;
+ for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
+ if (hit.ob == ssc->objects[ob_index]) {
+ state = ssc->states[ob_index];
+ break;
+ }
+ }
+
+ /* This works due to setting of tmp in find nearest uv vert */
+ UvElement *element = BM_uv_element_get(state->element_map, hit.efa, hit.l);
+ stitch_select_uv(element, state, false);
+
+ return state;
+ }
+ }
+ else if (uv_find_nearest_edge_multi(scene, ima, ssc->objects, ssc->objects_len, co, &hit)) {
+ /* find StitchState from hit->ob */
+ StitchState *state = NULL;
+ for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
+ if (hit.ob == ssc->objects[ob_index]) {
+ state = ssc->states[ob_index];
+ break;
+ }
+ }
+
+ UvEdge *edge = uv_edge_get(hit.l, state);
+ stitch_select_edge(edge, state, false);
+
+ return state;
+ }
+
+ return NULL;
}
static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- StitchStateContainer *ssc;
- Scene *scene = CTX_data_scene(C);
-
- ssc = op->customdata;
- StitchState *active_state = ssc->states[ssc->active_object_index];
-
- switch (event->type) {
- case MIDDLEMOUSE:
- return OPERATOR_PASS_THROUGH;
-
- /* Cancel */
- case ESCKEY:
- stitch_cancel(C, op);
- return OPERATOR_CANCELLED;
-
- case LEFTMOUSE:
- case PADENTER:
- case RETKEY:
- if (event->val == KM_PRESS) {
- if (stitch_process_data(ssc, active_state, scene, true)) {
- stitch_exit(C, op, 1);
- return OPERATOR_FINISHED;
- }
- else {
- stitch_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- }
- else {
- return OPERATOR_PASS_THROUGH;
- }
- /* Increase limit */
- case PADPLUSKEY:
- case WHEELUPMOUSE:
- if (event->val == KM_PRESS && event->alt) {
- ssc->limit_dist += 0.01f;
- if (!stitch_process_data(ssc, active_state, scene, false)) {
- stitch_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- break;
- }
- else {
- return OPERATOR_PASS_THROUGH;
- }
- /* Decrease limit */
- case PADMINUS:
- case WHEELDOWNMOUSE:
- if (event->val == KM_PRESS && event->alt) {
- ssc->limit_dist -= 0.01f;
- ssc->limit_dist = MAX2(0.01f, ssc->limit_dist);
- if (!stitch_process_data(ssc, active_state, scene, false)) {
- stitch_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- break;
- }
- else {
- return OPERATOR_PASS_THROUGH;
- }
-
- /* Use Limit (Default off) */
- case LKEY:
- if (event->val == KM_PRESS) {
- ssc->use_limit = !ssc->use_limit;
- if (!stitch_process_data(ssc, active_state, scene, false)) {
- stitch_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- break;
- }
- return OPERATOR_RUNNING_MODAL;
-
- case IKEY:
- if (event->val == KM_PRESS) {
- /* Move to next island and maybe next object */
-
- if (goto_next_island(ssc)) {
- StitchState *new_active_state = ssc->states[ssc->active_object_index];
-
- /* active_state is the original active state */
- if (active_state != new_active_state) {
- if (!stitch_process_data(ssc, active_state, scene, false)) {
- stitch_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- }
-
- if (!stitch_process_data(ssc, new_active_state, scene, false)) {
- stitch_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- }
- break;
- }
- return OPERATOR_RUNNING_MODAL;
-
- case MKEY:
- if (event->val == KM_PRESS) {
- ssc->midpoints = !ssc->midpoints;
- if (!stitch_process_data(ssc, active_state, scene, false)) {
- stitch_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- }
- break;
-
- /* Select geometry */
- case RIGHTMOUSE:
- if (!event->shift) {
- stitch_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- if (event->val == KM_PRESS) {
- StitchState *selected_state = stitch_select(C, scene, event, ssc);
-
- if (selected_state && !stitch_process_data(ssc, selected_state, scene, false)) {
- stitch_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- break;
- }
- return OPERATOR_RUNNING_MODAL;
-
- /* snap islands on/off */
- case SKEY:
- if (event->val == KM_PRESS) {
- ssc->snap_islands = !ssc->snap_islands;
- if (!stitch_process_data(ssc, active_state, scene, false)) {
- stitch_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- break;
- }
- else {
- return OPERATOR_RUNNING_MODAL;
- }
-
- /* switch between edge/vertex mode */
- case TABKEY:
- if (event->val == KM_PRESS) {
- stitch_switch_selection_mode_all(ssc);
-
- if (!stitch_process_data_all(ssc, scene, false)) {
- stitch_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
- }
- break;
-
- default:
- return OPERATOR_RUNNING_MODAL;
- }
-
- /* if updated settings, renew feedback message */
- stitch_update_header(ssc, C);
- ED_region_tag_redraw(CTX_wm_region(C));
-
- return OPERATOR_RUNNING_MODAL;
+ StitchStateContainer *ssc;
+ Scene *scene = CTX_data_scene(C);
+
+ ssc = op->customdata;
+ StitchState *active_state = ssc->states[ssc->active_object_index];
+
+ switch (event->type) {
+ case MIDDLEMOUSE:
+ return OPERATOR_PASS_THROUGH;
+
+ /* Cancel */
+ case ESCKEY:
+ stitch_cancel(C, op);
+ return OPERATOR_CANCELLED;
+
+ case LEFTMOUSE:
+ case PADENTER:
+ case RETKEY:
+ if (event->val == KM_PRESS) {
+ if (stitch_process_data(ssc, active_state, scene, true)) {
+ stitch_exit(C, op, 1);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ stitch_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ return OPERATOR_PASS_THROUGH;
+ }
+ /* Increase limit */
+ case PADPLUSKEY:
+ case WHEELUPMOUSE:
+ if (event->val == KM_PRESS && event->alt) {
+ ssc->limit_dist += 0.01f;
+ if (!stitch_process_data(ssc, active_state, scene, false)) {
+ stitch_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ break;
+ }
+ else {
+ return OPERATOR_PASS_THROUGH;
+ }
+ /* Decrease limit */
+ case PADMINUS:
+ case WHEELDOWNMOUSE:
+ if (event->val == KM_PRESS && event->alt) {
+ ssc->limit_dist -= 0.01f;
+ ssc->limit_dist = MAX2(0.01f, ssc->limit_dist);
+ if (!stitch_process_data(ssc, active_state, scene, false)) {
+ stitch_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ break;
+ }
+ else {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ /* Use Limit (Default off) */
+ case LKEY:
+ if (event->val == KM_PRESS) {
+ ssc->use_limit = !ssc->use_limit;
+ if (!stitch_process_data(ssc, active_state, scene, false)) {
+ stitch_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ break;
+ }
+ return OPERATOR_RUNNING_MODAL;
+
+ case IKEY:
+ if (event->val == KM_PRESS) {
+ /* Move to next island and maybe next object */
+
+ if (goto_next_island(ssc)) {
+ StitchState *new_active_state = ssc->states[ssc->active_object_index];
+
+ /* active_state is the original active state */
+ if (active_state != new_active_state) {
+ if (!stitch_process_data(ssc, active_state, scene, false)) {
+ stitch_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ if (!stitch_process_data(ssc, new_active_state, scene, false)) {
+ stitch_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ break;
+ }
+ return OPERATOR_RUNNING_MODAL;
+
+ case MKEY:
+ if (event->val == KM_PRESS) {
+ ssc->midpoints = !ssc->midpoints;
+ if (!stitch_process_data(ssc, active_state, scene, false)) {
+ stitch_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ break;
+
+ /* Select geometry */
+ case RIGHTMOUSE:
+ if (!event->shift) {
+ stitch_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ if (event->val == KM_PRESS) {
+ StitchState *selected_state = stitch_select(C, scene, event, ssc);
+
+ if (selected_state && !stitch_process_data(ssc, selected_state, scene, false)) {
+ stitch_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ break;
+ }
+ return OPERATOR_RUNNING_MODAL;
+
+ /* snap islands on/off */
+ case SKEY:
+ if (event->val == KM_PRESS) {
+ ssc->snap_islands = !ssc->snap_islands;
+ if (!stitch_process_data(ssc, active_state, scene, false)) {
+ stitch_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ break;
+ }
+ else {
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ /* switch between edge/vertex mode */
+ case TABKEY:
+ if (event->val == KM_PRESS) {
+ stitch_switch_selection_mode_all(ssc);
+
+ if (!stitch_process_data_all(ssc, scene, false)) {
+ stitch_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ break;
+
+ default:
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ /* if updated settings, renew feedback message */
+ stitch_update_header(ssc, C);
+ ED_region_tag_redraw(CTX_wm_region(C));
+
+ return OPERATOR_RUNNING_MODAL;
}
void UV_OT_stitch(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- static const EnumPropertyItem stitch_modes[] = {
- {STITCH_VERT, "VERTEX", 0, "Vertex", ""},
- {STITCH_EDGE, "EDGE", 0, "Edge", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Stitch";
- ot->description = "Stitch selected UV vertices by proximity";
- ot->idname = "UV_OT_stitch";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* api callbacks */
- ot->invoke = stitch_invoke;
- ot->modal = stitch_modal;
- ot->exec = stitch_exec;
- ot->cancel = stitch_cancel;
- ot->poll = ED_operator_uvedit;
-
- /* properties */
- RNA_def_boolean(ot->srna, "use_limit", 0, "Use Limit", "Stitch UVs within a specified limit distance");
- RNA_def_boolean(ot->srna, "snap_islands", 1, "Snap Islands",
- "Snap islands together (on edge stitch mode, rotates the islands too)");
-
- RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, FLT_MAX, "Limit",
- "Limit distance in normalized coordinates", 0.0, FLT_MAX);
- RNA_def_int(ot->srna, "static_island", 0, 0, INT_MAX, "Static Island",
- "Island that stays in place when stitching islands", 0, INT_MAX);
- RNA_def_int(ot->srna, "active_object_index", 0, 0, INT_MAX, "Active Object",
- "Index of the active object", 0, INT_MAX);
- RNA_def_boolean(ot->srna, "midpoint_snap", 0, "Snap At Midpoint",
- "UVs are stitched at midpoint instead of at static island");
- RNA_def_boolean(ot->srna, "clear_seams", 1, "Clear Seams",
- "Clear seams of stitched edges");
- RNA_def_enum(ot->srna, "mode", stitch_modes, STITCH_VERT, "Operation Mode",
- "Use vertex or edge stitching");
- prop = RNA_def_enum(ot->srna, "stored_mode", stitch_modes, STITCH_VERT, "Stored Operation Mode",
- "Use vertex or edge stitching");
- RNA_def_property_flag(prop, PROP_HIDDEN);
- prop = RNA_def_collection_runtime(ot->srna, "selection", &RNA_SelectedUvElement, "Selection", "");
- /* Selection should not be editable or viewed in toolbar */
- RNA_def_property_flag(prop, PROP_HIDDEN);
-
- /* test should not be editable or viewed in toolbar */
- prop = RNA_def_int_array(ot->srna, "objects_selection_count", 1, NULL, 0, INT_MAX, "Objects Selection Count",
- "", 0, INT_MAX);
- RNA_def_property_array(prop, 6);
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop;
+
+ static const EnumPropertyItem stitch_modes[] = {
+ {STITCH_VERT, "VERTEX", 0, "Vertex", ""},
+ {STITCH_EDGE, "EDGE", 0, "Edge", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Stitch";
+ ot->description = "Stitch selected UV vertices by proximity";
+ ot->idname = "UV_OT_stitch";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->invoke = stitch_invoke;
+ ot->modal = stitch_modal;
+ ot->exec = stitch_exec;
+ ot->cancel = stitch_cancel;
+ ot->poll = ED_operator_uvedit;
+
+ /* properties */
+ RNA_def_boolean(
+ ot->srna, "use_limit", 0, "Use Limit", "Stitch UVs within a specified limit distance");
+ RNA_def_boolean(ot->srna,
+ "snap_islands",
+ 1,
+ "Snap Islands",
+ "Snap islands together (on edge stitch mode, rotates the islands too)");
+
+ RNA_def_float(ot->srna,
+ "limit",
+ 0.01f,
+ 0.0f,
+ FLT_MAX,
+ "Limit",
+ "Limit distance in normalized coordinates",
+ 0.0,
+ FLT_MAX);
+ RNA_def_int(ot->srna,
+ "static_island",
+ 0,
+ 0,
+ INT_MAX,
+ "Static Island",
+ "Island that stays in place when stitching islands",
+ 0,
+ INT_MAX);
+ RNA_def_int(ot->srna,
+ "active_object_index",
+ 0,
+ 0,
+ INT_MAX,
+ "Active Object",
+ "Index of the active object",
+ 0,
+ INT_MAX);
+ RNA_def_boolean(ot->srna,
+ "midpoint_snap",
+ 0,
+ "Snap At Midpoint",
+ "UVs are stitched at midpoint instead of at static island");
+ RNA_def_boolean(ot->srna, "clear_seams", 1, "Clear Seams", "Clear seams of stitched edges");
+ RNA_def_enum(ot->srna,
+ "mode",
+ stitch_modes,
+ STITCH_VERT,
+ "Operation Mode",
+ "Use vertex or edge stitching");
+ prop = RNA_def_enum(ot->srna,
+ "stored_mode",
+ stitch_modes,
+ STITCH_VERT,
+ "Stored Operation Mode",
+ "Use vertex or edge stitching");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_collection_runtime(
+ ot->srna, "selection", &RNA_SelectedUvElement, "Selection", "");
+ /* Selection should not be editable or viewed in toolbar */
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ /* test should not be editable or viewed in toolbar */
+ prop = RNA_def_int_array(ot->srna,
+ "objects_selection_count",
+ 1,
+ NULL,
+ 0,
+ INT_MAX,
+ "Objects Selection Count",
+ "",
+ 0,
+ INT_MAX);
+ RNA_def_property_array(prop, 6);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 19925c2fcd7..0caa478ffa9 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -21,7 +21,6 @@
* \ingroup eduv
*/
-
#include <string.h>
#include <stdlib.h>
#include <math.h>
@@ -70,7 +69,6 @@
#include "RNA_access.h"
#include "RNA_define.h"
-
#include "WM_api.h"
#include "WM_types.h"
@@ -79,1333 +77,1432 @@
static void modifier_unwrap_state(Object *obedit, Scene *scene, bool *r_use_subsurf)
{
- ModifierData *md;
- bool subsurf = (scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF) != 0;
+ ModifierData *md;
+ bool subsurf = (scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF) != 0;
- md = obedit->modifiers.first;
+ md = obedit->modifiers.first;
- /* subsurf will take the modifier settings only if modifier is first or right after mirror */
- if (subsurf) {
- if (md && md->type == eModifierType_Subsurf)
- subsurf = true;
- else
- subsurf = false;
- }
+ /* subsurf will take the modifier settings only if modifier is first or right after mirror */
+ if (subsurf) {
+ if (md && md->type == eModifierType_Subsurf)
+ subsurf = true;
+ else
+ subsurf = false;
+ }
- *r_use_subsurf = subsurf;
+ *r_use_subsurf = subsurf;
}
static bool ED_uvedit_ensure_uvs(bContext *C, Scene *UNUSED(scene), Object *obedit)
{
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMIter iter;
- Image *ima;
- bScreen *sc;
- ScrArea *sa;
- SpaceLink *slink;
- SpaceImage *sima;
- int cd_loop_uv_offset;
-
- if (ED_uvedit_test(obedit))
- return 1;
-
- if (em && em->bm->totface && !CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV))
- ED_mesh_uv_texture_add(obedit->data, NULL, true, true);
-
- if (!ED_uvedit_test(obedit))
- return 0;
-
- cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- ima = CTX_data_edit_image(C);
-
- if (!ima) {
- /* no image in context in the 3d view, we find first image window .. */
- sc = CTX_wm_screen(C);
-
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- slink = sa->spacedata.first;
- if (slink->spacetype == SPACE_IMAGE) {
- sima = (SpaceImage *)slink;
-
- ima = sima->image;
- if (ima) {
- if (ima->type == IMA_TYPE_R_RESULT || ima->type == IMA_TYPE_COMPOSITE)
- ima = NULL;
- else
- break;
- }
- }
- }
- }
-
- /* select new UV's (ignore UV_SYNC_SELECTION in this case) */
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BMIter liter;
- BMLoop *l;
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->flag |= MLOOPUV_VERTSEL;
- }
- }
-
- return 1;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMIter iter;
+ Image *ima;
+ bScreen *sc;
+ ScrArea *sa;
+ SpaceLink *slink;
+ SpaceImage *sima;
+ int cd_loop_uv_offset;
+
+ if (ED_uvedit_test(obedit))
+ return 1;
+
+ if (em && em->bm->totface && !CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV))
+ ED_mesh_uv_texture_add(obedit->data, NULL, true, true);
+
+ if (!ED_uvedit_test(obedit))
+ return 0;
+
+ cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ ima = CTX_data_edit_image(C);
+
+ if (!ima) {
+ /* no image in context in the 3d view, we find first image window .. */
+ sc = CTX_wm_screen(C);
+
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ slink = sa->spacedata.first;
+ if (slink->spacetype == SPACE_IMAGE) {
+ sima = (SpaceImage *)slink;
+
+ ima = sima->image;
+ if (ima) {
+ if (ima->type == IMA_TYPE_R_RESULT || ima->type == IMA_TYPE_COMPOSITE)
+ ima = NULL;
+ else
+ break;
+ }
+ }
+ }
+ }
+
+ /* select new UV's (ignore UV_SYNC_SELECTION in this case) */
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BMIter liter;
+ BMLoop *l;
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv->flag |= MLOOPUV_VERTSEL;
+ }
+ }
+
+ return 1;
}
/****************** 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. */
+ 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. */
} UnwrapOptions;
static bool uvedit_have_selection(Scene *scene, BMEditMesh *em, const UnwrapOptions *options)
{
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- if (cd_loop_uv_offset == -1) {
- return (em->bm->totfacesel != 0);
- }
-
- /* verify if we have any selected uv's before unwrapping,
- * so we can cancel the operator early */
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
- if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
- continue;
- }
- else if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
- continue;
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))
- break;
- }
-
- if (options->topology_from_uvs && !l)
- continue;
-
- return true;
- }
-
- return false;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ if (cd_loop_uv_offset == -1) {
+ return (em->bm->totfacesel != 0);
+ }
+
+ /* verify if we have any selected uv's before unwrapping,
+ * so we can cancel the operator early */
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
+ continue;
+ }
+ else if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ continue;
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))
+ break;
+ }
+
+ if (options->topology_from_uvs && !l)
+ continue;
+
+ return true;
+ }
+
+ return false;
}
-static bool uvedit_have_selection_multi(
- Scene *scene, Object **objects, const uint objects_len,
- const UnwrapOptions *options)
+static bool uvedit_have_selection_multi(Scene *scene,
+ Object **objects,
+ const uint objects_len,
+ const UnwrapOptions *options)
{
- bool have_select = false;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (uvedit_have_selection(scene, em, options)) {
- have_select = true;
- break;
- }
- }
- return have_select;
+ bool have_select = false;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ if (uvedit_have_selection(scene, em, options)) {
+ have_select = true;
+ break;
+ }
+ }
+ return have_select;
}
void ED_uvedit_get_aspect(Scene *UNUSED(scene), Object *ob, BMesh *bm, float *aspx, float *aspy)
{
- bool sloppy = true;
- bool selected = false;
- BMFace *efa;
- Image *ima;
-
- efa = BM_mesh_active_face_get(bm, sloppy, selected);
-
- 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);
- }
- else {
- *aspx = 1.0f;
- *aspy = 1.0f;
- }
+ bool sloppy = true;
+ bool selected = false;
+ BMFace *efa;
+ Image *ima;
+
+ efa = BM_mesh_active_face_get(bm, sloppy, selected);
+
+ 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);
+ }
+ else {
+ *aspx = 1.0f;
+ *aspy = 1.0f;
+ }
}
-static void construct_param_handle_face_add(ParamHandle *handle, Scene *scene,
- BMFace *efa, int face_index, const int cd_loop_uv_offset)
+static void construct_param_handle_face_add(
+ ParamHandle *handle, Scene *scene, BMFace *efa, int face_index, const int cd_loop_uv_offset)
{
- ParamKey key;
- ParamKey *vkeys = BLI_array_alloca(vkeys, efa->len);
- ParamBool *pin = BLI_array_alloca(pin, efa->len);
- ParamBool *select = BLI_array_alloca(select, efa->len);
- float **co = BLI_array_alloca(co, efa->len);
- float **uv = BLI_array_alloca(uv, efa->len);
- int i;
-
- BMIter liter;
- BMLoop *l;
-
- key = (ParamKey)face_index;
-
- /* let parametrizer split the ngon, it can make better decisions
- * about which split is best for unwrapping than scanfill */
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- vkeys[i] = (ParamKey)BM_elem_index_get(l->v);
- co[i] = l->v->co;
- uv[i] = luv->uv;
- pin[i] = (luv->flag & MLOOPUV_PINNED) != 0;
- select[i] = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
- }
-
- param_face_add(handle, key, i, vkeys, co, uv, pin, select);
+ ParamKey key;
+ ParamKey *vkeys = BLI_array_alloca(vkeys, efa->len);
+ ParamBool *pin = BLI_array_alloca(pin, efa->len);
+ ParamBool *select = BLI_array_alloca(select, efa->len);
+ float **co = BLI_array_alloca(co, efa->len);
+ float **uv = BLI_array_alloca(uv, efa->len);
+ int i;
+
+ BMIter liter;
+ BMLoop *l;
+
+ key = (ParamKey)face_index;
+
+ /* let parametrizer split the ngon, it can make better decisions
+ * about which split is best for unwrapping than scanfill */
+ BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i)
+ {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ vkeys[i] = (ParamKey)BM_elem_index_get(l->v);
+ co[i] = l->v->co;
+ uv[i] = luv->uv;
+ pin[i] = (luv->flag & MLOOPUV_PINNED) != 0;
+ select[i] = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
+ }
+
+ param_face_add(handle, key, i, vkeys, co, uv, pin, select);
}
/* See: construct_param_handle_multi to handle multiple objects at once. */
-static ParamHandle *construct_param_handle(
- Scene *scene, Object *ob, BMesh *bm,
- const UnwrapOptions *options)
+static ParamHandle *construct_param_handle(Scene *scene,
+ Object *ob,
+ BMesh *bm,
+ const UnwrapOptions *options)
{
- ParamHandle *handle;
- BMFace *efa;
- BMLoop *l;
- BMEdge *eed;
- BMIter iter, liter;
- int i;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-
- handle = param_construct_begin();
-
- if (options->correct_aspect) {
- float aspx, aspy;
-
- ED_uvedit_get_aspect(scene, ob, bm, &aspx, &aspy);
-
- if (aspx != aspy)
- param_aspect_ratio(handle, aspx, aspy);
- }
-
- /* we need the vert indices */
- BM_mesh_elem_index_ensure(bm, BM_VERT);
-
- BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
-
- if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) ||
- (options->only_selected && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0))
- {
- continue;
- }
-
- if (options->topology_from_uvs) {
- bool is_loopsel = false;
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- is_loopsel = true;
- break;
- }
- }
- if (is_loopsel == false) {
- continue;
- }
- }
-
- construct_param_handle_face_add(handle, scene, efa, i, cd_loop_uv_offset);
- }
-
- if (!options->topology_from_uvs) {
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SEAM)) {
- ParamKey vkeys[2];
- vkeys[0] = (ParamKey)BM_elem_index_get(eed->v1);
- vkeys[1] = (ParamKey)BM_elem_index_get(eed->v2);
- param_edge_set_seam(handle, vkeys);
- }
- }
- }
-
- param_construct_end(handle, options->fill_holes, options->topology_from_uvs);
-
- return handle;
+ ParamHandle *handle;
+ BMFace *efa;
+ BMLoop *l;
+ BMEdge *eed;
+ BMIter iter, liter;
+ int i;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+ handle = param_construct_begin();
+
+ if (options->correct_aspect) {
+ float aspx, aspy;
+
+ ED_uvedit_get_aspect(scene, ob, bm, &aspx, &aspy);
+
+ if (aspx != aspy)
+ param_aspect_ratio(handle, aspx, aspy);
+ }
+
+ /* we need the vert indices */
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+ BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
+
+ if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) ||
+ (options->only_selected && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0)) {
+ continue;
+ }
+
+ if (options->topology_from_uvs) {
+ bool is_loopsel = false;
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ is_loopsel = true;
+ break;
+ }
+ }
+ if (is_loopsel == false) {
+ continue;
+ }
+ }
+
+ construct_param_handle_face_add(handle, scene, efa, i, cd_loop_uv_offset);
+ }
+
+ if (!options->topology_from_uvs) {
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SEAM)) {
+ ParamKey vkeys[2];
+ vkeys[0] = (ParamKey)BM_elem_index_get(eed->v1);
+ vkeys[1] = (ParamKey)BM_elem_index_get(eed->v2);
+ param_edge_set_seam(handle, vkeys);
+ }
+ }
+ }
+
+ param_construct_end(handle, options->fill_holes, options->topology_from_uvs);
+
+ return handle;
}
/**
* Version of #construct_param_handle_single that handles multiple objects.
*/
-static ParamHandle *construct_param_handle_multi(
- Scene *scene, Object **objects, const uint objects_len,
- const UnwrapOptions *options)
+static ParamHandle *construct_param_handle_multi(Scene *scene,
+ Object **objects,
+ const uint objects_len,
+ const UnwrapOptions *options)
{
- ParamHandle *handle;
- BMFace *efa;
- BMLoop *l;
- BMEdge *eed;
- BMIter iter, liter;
- int i;
-
- handle = param_construct_begin();
-
- if (options->correct_aspect) {
- Object *ob = objects[0];
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em->bm;
- float aspx, aspy;
-
- ED_uvedit_get_aspect(scene, ob, bm, &aspx, &aspy);
- if (aspx != aspy) {
- param_aspect_ratio(handle, aspx, aspy);
- }
- }
-
- /* we need the vert indices */
- EDBM_mesh_elem_index_ensure_multi(objects, objects_len, BM_VERT);
-
- int offset = 0;
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-
- BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
-
- if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) ||
- (options->only_selected && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0))
- {
- continue;
- }
-
- if (options->topology_from_uvs) {
- bool is_loopsel = false;
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- is_loopsel = true;
- break;
- }
- }
- if (is_loopsel == false) {
- continue;
- }
- }
-
- construct_param_handle_face_add(handle, scene, efa, i + offset, cd_loop_uv_offset);
- }
-
- if (!options->topology_from_uvs) {
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SEAM)) {
- ParamKey vkeys[2];
- vkeys[0] = (ParamKey)BM_elem_index_get(eed->v1);
- vkeys[1] = (ParamKey)BM_elem_index_get(eed->v2);
- param_edge_set_seam(handle, vkeys);
- }
- }
- }
- offset += bm->totface;
- }
-
- param_construct_end(handle, options->fill_holes, options->topology_from_uvs);
-
- return handle;
+ ParamHandle *handle;
+ BMFace *efa;
+ BMLoop *l;
+ BMEdge *eed;
+ BMIter iter, liter;
+ int i;
+
+ handle = param_construct_begin();
+
+ if (options->correct_aspect) {
+ Object *ob = objects[0];
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
+ float aspx, aspy;
+
+ ED_uvedit_get_aspect(scene, ob, bm, &aspx, &aspy);
+ if (aspx != aspy) {
+ param_aspect_ratio(handle, aspx, aspy);
+ }
+ }
+
+ /* we need the vert indices */
+ EDBM_mesh_elem_index_ensure_multi(objects, objects_len, BM_VERT);
+
+ int offset = 0;
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+ BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
+
+ if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) ||
+ (options->only_selected && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0)) {
+ continue;
+ }
+
+ if (options->topology_from_uvs) {
+ bool is_loopsel = false;
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ is_loopsel = true;
+ break;
+ }
+ }
+ if (is_loopsel == false) {
+ continue;
+ }
+ }
+
+ construct_param_handle_face_add(handle, scene, efa, i + offset, cd_loop_uv_offset);
+ }
+
+ if (!options->topology_from_uvs) {
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SEAM)) {
+ ParamKey vkeys[2];
+ vkeys[0] = (ParamKey)BM_elem_index_get(eed->v1);
+ vkeys[1] = (ParamKey)BM_elem_index_get(eed->v2);
+ param_edge_set_seam(handle, vkeys);
+ }
+ }
+ }
+ offset += bm->totface;
+ }
+
+ param_construct_end(handle, options->fill_holes, options->topology_from_uvs);
+
+ return handle;
}
-
-static void texface_from_original_index(BMFace *efa, int index, float **uv, ParamBool *pin, ParamBool *select,
- Scene *scene, const int cd_loop_uv_offset)
+static void texface_from_original_index(BMFace *efa,
+ int index,
+ float **uv,
+ ParamBool *pin,
+ ParamBool *select,
+ Scene *scene,
+ const int cd_loop_uv_offset)
{
- BMLoop *l;
- BMIter liter;
- MLoopUV *luv;
-
- *uv = NULL;
- *pin = 0;
- *select = 1;
-
- if (index == ORIGINDEX_NONE)
- return;
-
- 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);
- break;
- }
- }
+ BMLoop *l;
+ BMIter liter;
+ MLoopUV *luv;
+
+ *uv = NULL;
+ *pin = 0;
+ *select = 1;
+
+ if (index == ORIGINDEX_NONE)
+ return;
+
+ 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);
+ break;
+ }
+ }
}
/* unwrap handle initialization for subsurf aware-unwrapper. The many modifications required to make the original function(see above)
* work justified the existence of a new function. */
-static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, BMEditMesh *em, const UnwrapOptions *options)
+static ParamHandle *construct_param_handle_subsurfed(Scene *scene,
+ Object *ob,
+ BMEditMesh *em,
+ const UnwrapOptions *options)
{
- ParamHandle *handle;
- /* index pointers */
- MPoly *mpoly;
- MLoop *mloop;
- MEdge *edge;
- int i;
-
- /* pointers to modifier data for unwrap control */
- ModifierData *md;
- SubsurfModifierData *smd_real;
- /* modifier initialization data, will control what type of subdivision will happen*/
- SubsurfModifierData smd = {{NULL}};
- /* Used to hold subsurfed Mesh */
- DerivedMesh *derivedMesh, *initialDerived;
- /* holds original indices for subsurfed mesh */
- const int *origVertIndices, *origEdgeIndices, *origPolyIndices;
- /* Holds vertices of subsurfed mesh */
- MVert *subsurfedVerts;
- MEdge *subsurfedEdges;
- MPoly *subsurfedPolys;
- MLoop *subsurfedLoops;
- /* number of vertices and faces for subsurfed mesh*/
- int numOfEdges, numOfFaces;
-
- /* holds a map to editfaces for every subsurfed MFace.
- * These will be used to get hidden/ selected flags etc. */
- BMFace **faceMap;
- /* similar to the above, we need a way to map edges to their original ones */
- BMEdge **edgeMap;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- handle = param_construct_begin();
-
- if (options->correct_aspect) {
- float aspx, aspy;
-
- ED_uvedit_get_aspect(scene, ob, em->bm, &aspx, &aspy);
-
- if (aspx != aspy)
- param_aspect_ratio(handle, aspx, aspy);
- }
-
- /* number of subdivisions to perform */
- md = ob->modifiers.first;
- smd_real = (SubsurfModifierData *)md;
-
- smd.levels = smd_real->levels;
- smd.subdivType = smd_real->subdivType;
-
- initialDerived = CDDM_from_editbmesh(em, false, false);
- derivedMesh = subsurf_make_derived_from_derived(initialDerived, &smd, scene,
- NULL, SUBSURF_IN_EDIT_MODE);
-
- initialDerived->release(initialDerived);
-
- /* get the derived data */
- subsurfedVerts = derivedMesh->getVertArray(derivedMesh);
- subsurfedEdges = derivedMesh->getEdgeArray(derivedMesh);
- subsurfedPolys = derivedMesh->getPolyArray(derivedMesh);
- subsurfedLoops = derivedMesh->getLoopArray(derivedMesh);
-
- origVertIndices = derivedMesh->getVertDataArray(derivedMesh, CD_ORIGINDEX);
- origEdgeIndices = derivedMesh->getEdgeDataArray(derivedMesh, CD_ORIGINDEX);
- origPolyIndices = derivedMesh->getPolyDataArray(derivedMesh, CD_ORIGINDEX);
-
- numOfEdges = derivedMesh->getNumEdges(derivedMesh);
- numOfFaces = derivedMesh->getNumPolys(derivedMesh);
-
- faceMap = MEM_mallocN(numOfFaces * sizeof(BMFace *), "unwrap_edit_face_map");
-
- BM_mesh_elem_index_ensure(em->bm, BM_VERT);
- BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_FACE);
-
- /* map subsurfed faces to original editFaces */
- for (i = 0; i < numOfFaces; i++)
- faceMap[i] = BM_face_at_index(em->bm, origPolyIndices[i]);
-
- edgeMap = MEM_mallocN(numOfEdges * sizeof(BMEdge *), "unwrap_edit_edge_map");
-
- /* map subsurfed edges to original editEdges */
- for (i = 0; i < numOfEdges; i++) {
- /* not all edges correspond to an old edge */
- edgeMap[i] = (origEdgeIndices[i] != ORIGINDEX_NONE) ?
- BM_edge_at_index(em->bm, origEdgeIndices[i]) : NULL;
- }
-
- /* Prepare and feed faces to the solver */
- for (i = 0, mpoly = subsurfedPolys; i < numOfFaces; i++, mpoly++) {
- ParamKey key, vkeys[4];
- ParamBool pin[4], select[4];
- float *co[4];
- float *uv[4];
- BMFace *origFace = faceMap[i];
-
- if (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
- if (BM_elem_flag_test(origFace, BM_ELEM_HIDDEN))
- continue;
- }
- else {
- if (BM_elem_flag_test(origFace, BM_ELEM_HIDDEN) ||
- (options->only_selected && !BM_elem_flag_test(origFace, BM_ELEM_SELECT)))
- {
- continue;
- }
- }
-
- mloop = &subsurfedLoops[mpoly->loopstart];
-
- /* We will not check for v4 here. Subsurfed mfaces always have 4 vertices. */
- BLI_assert(mpoly->totloop == 4);
- key = (ParamKey)i;
- vkeys[0] = (ParamKey)mloop[0].v;
- vkeys[1] = (ParamKey)mloop[1].v;
- vkeys[2] = (ParamKey)mloop[2].v;
- vkeys[3] = (ParamKey)mloop[3].v;
-
- co[0] = subsurfedVerts[mloop[0].v].co;
- co[1] = subsurfedVerts[mloop[1].v].co;
- co[2] = subsurfedVerts[mloop[2].v].co;
- co[3] = subsurfedVerts[mloop[3].v].co;
-
- /* 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, origVertIndices[mloop[0].v], &uv[0], &pin[0], &select[0], scene, cd_loop_uv_offset);
- texface_from_original_index(origFace, origVertIndices[mloop[1].v], &uv[1], &pin[1], &select[1], scene, cd_loop_uv_offset);
- texface_from_original_index(origFace, origVertIndices[mloop[2].v], &uv[2], &pin[2], &select[2], scene, cd_loop_uv_offset);
- texface_from_original_index(origFace, origVertIndices[mloop[3].v], &uv[3], &pin[3], &select[3], scene, cd_loop_uv_offset);
-
- param_face_add(handle, key, 4, vkeys, co, uv, pin, select);
- }
-
- /* these are calculated from original mesh too */
- for (edge = subsurfedEdges, i = 0; i < numOfEdges; i++, edge++) {
- if ((edgeMap[i] != NULL) && BM_elem_flag_test(edgeMap[i], BM_ELEM_SEAM)) {
- ParamKey vkeys[2];
- vkeys[0] = (ParamKey)edge->v1;
- vkeys[1] = (ParamKey)edge->v2;
- param_edge_set_seam(handle, vkeys);
- }
- }
-
- param_construct_end(handle, options->fill_holes, options->topology_from_uvs);
-
- /* cleanup */
- MEM_freeN(faceMap);
- MEM_freeN(edgeMap);
- derivedMesh->release(derivedMesh);
-
- return handle;
+ ParamHandle *handle;
+ /* index pointers */
+ MPoly *mpoly;
+ MLoop *mloop;
+ MEdge *edge;
+ int i;
+
+ /* pointers to modifier data for unwrap control */
+ ModifierData *md;
+ SubsurfModifierData *smd_real;
+ /* modifier initialization data, will control what type of subdivision will happen*/
+ SubsurfModifierData smd = {{NULL}};
+ /* Used to hold subsurfed Mesh */
+ DerivedMesh *derivedMesh, *initialDerived;
+ /* holds original indices for subsurfed mesh */
+ const int *origVertIndices, *origEdgeIndices, *origPolyIndices;
+ /* Holds vertices of subsurfed mesh */
+ MVert *subsurfedVerts;
+ MEdge *subsurfedEdges;
+ MPoly *subsurfedPolys;
+ MLoop *subsurfedLoops;
+ /* number of vertices and faces for subsurfed mesh*/
+ int numOfEdges, numOfFaces;
+
+ /* holds a map to editfaces for every subsurfed MFace.
+ * These will be used to get hidden/ selected flags etc. */
+ BMFace **faceMap;
+ /* similar to the above, we need a way to map edges to their original ones */
+ BMEdge **edgeMap;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ handle = param_construct_begin();
+
+ if (options->correct_aspect) {
+ float aspx, aspy;
+
+ ED_uvedit_get_aspect(scene, ob, em->bm, &aspx, &aspy);
+
+ if (aspx != aspy)
+ param_aspect_ratio(handle, aspx, aspy);
+ }
+
+ /* number of subdivisions to perform */
+ md = ob->modifiers.first;
+ smd_real = (SubsurfModifierData *)md;
+
+ smd.levels = smd_real->levels;
+ smd.subdivType = smd_real->subdivType;
+
+ initialDerived = CDDM_from_editbmesh(em, false, false);
+ derivedMesh = subsurf_make_derived_from_derived(
+ initialDerived, &smd, scene, NULL, SUBSURF_IN_EDIT_MODE);
+
+ initialDerived->release(initialDerived);
+
+ /* get the derived data */
+ subsurfedVerts = derivedMesh->getVertArray(derivedMesh);
+ subsurfedEdges = derivedMesh->getEdgeArray(derivedMesh);
+ subsurfedPolys = derivedMesh->getPolyArray(derivedMesh);
+ subsurfedLoops = derivedMesh->getLoopArray(derivedMesh);
+
+ origVertIndices = derivedMesh->getVertDataArray(derivedMesh, CD_ORIGINDEX);
+ origEdgeIndices = derivedMesh->getEdgeDataArray(derivedMesh, CD_ORIGINDEX);
+ origPolyIndices = derivedMesh->getPolyDataArray(derivedMesh, CD_ORIGINDEX);
+
+ numOfEdges = derivedMesh->getNumEdges(derivedMesh);
+ numOfFaces = derivedMesh->getNumPolys(derivedMesh);
+
+ faceMap = MEM_mallocN(numOfFaces * sizeof(BMFace *), "unwrap_edit_face_map");
+
+ BM_mesh_elem_index_ensure(em->bm, BM_VERT);
+ BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_FACE);
+
+ /* map subsurfed faces to original editFaces */
+ for (i = 0; i < numOfFaces; i++)
+ faceMap[i] = BM_face_at_index(em->bm, origPolyIndices[i]);
+
+ edgeMap = MEM_mallocN(numOfEdges * sizeof(BMEdge *), "unwrap_edit_edge_map");
+
+ /* map subsurfed edges to original editEdges */
+ for (i = 0; i < numOfEdges; i++) {
+ /* not all edges correspond to an old edge */
+ edgeMap[i] = (origEdgeIndices[i] != ORIGINDEX_NONE) ?
+ BM_edge_at_index(em->bm, origEdgeIndices[i]) :
+ NULL;
+ }
+
+ /* Prepare and feed faces to the solver */
+ for (i = 0, mpoly = subsurfedPolys; i < numOfFaces; i++, mpoly++) {
+ ParamKey key, vkeys[4];
+ ParamBool pin[4], select[4];
+ float *co[4];
+ float *uv[4];
+ BMFace *origFace = faceMap[i];
+
+ if (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+ if (BM_elem_flag_test(origFace, BM_ELEM_HIDDEN))
+ continue;
+ }
+ else {
+ if (BM_elem_flag_test(origFace, BM_ELEM_HIDDEN) ||
+ (options->only_selected && !BM_elem_flag_test(origFace, BM_ELEM_SELECT))) {
+ continue;
+ }
+ }
+
+ mloop = &subsurfedLoops[mpoly->loopstart];
+
+ /* We will not check for v4 here. Subsurfed mfaces always have 4 vertices. */
+ BLI_assert(mpoly->totloop == 4);
+ key = (ParamKey)i;
+ vkeys[0] = (ParamKey)mloop[0].v;
+ vkeys[1] = (ParamKey)mloop[1].v;
+ vkeys[2] = (ParamKey)mloop[2].v;
+ vkeys[3] = (ParamKey)mloop[3].v;
+
+ co[0] = subsurfedVerts[mloop[0].v].co;
+ co[1] = subsurfedVerts[mloop[1].v].co;
+ co[2] = subsurfedVerts[mloop[2].v].co;
+ co[3] = subsurfedVerts[mloop[3].v].co;
+
+ /* 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,
+ origVertIndices[mloop[0].v],
+ &uv[0],
+ &pin[0],
+ &select[0],
+ scene,
+ cd_loop_uv_offset);
+ texface_from_original_index(origFace,
+ origVertIndices[mloop[1].v],
+ &uv[1],
+ &pin[1],
+ &select[1],
+ scene,
+ cd_loop_uv_offset);
+ texface_from_original_index(origFace,
+ origVertIndices[mloop[2].v],
+ &uv[2],
+ &pin[2],
+ &select[2],
+ scene,
+ cd_loop_uv_offset);
+ texface_from_original_index(origFace,
+ origVertIndices[mloop[3].v],
+ &uv[3],
+ &pin[3],
+ &select[3],
+ scene,
+ cd_loop_uv_offset);
+
+ param_face_add(handle, key, 4, vkeys, co, uv, pin, select);
+ }
+
+ /* these are calculated from original mesh too */
+ for (edge = subsurfedEdges, i = 0; i < numOfEdges; i++, edge++) {
+ if ((edgeMap[i] != NULL) && BM_elem_flag_test(edgeMap[i], BM_ELEM_SEAM)) {
+ ParamKey vkeys[2];
+ vkeys[0] = (ParamKey)edge->v1;
+ vkeys[1] = (ParamKey)edge->v2;
+ param_edge_set_seam(handle, vkeys);
+ }
+ }
+
+ param_construct_end(handle, options->fill_holes, options->topology_from_uvs);
+
+ /* cleanup */
+ MEM_freeN(faceMap);
+ MEM_freeN(edgeMap);
+ derivedMesh->release(derivedMesh);
+
+ return handle;
}
/* ******************** Minimize Stretch operator **************** */
typedef struct MinStretch {
- Scene *scene;
- Object **objects_edit;
- uint objects_len;
- ParamHandle *handle;
- float blend;
- double lasttime;
- int i, iterations;
- wmTimer *timer;
+ Scene *scene;
+ Object **objects_edit;
+ uint objects_len;
+ ParamHandle *handle;
+ float blend;
+ double lasttime;
+ int i, iterations;
+ wmTimer *timer;
} MinStretch;
static bool minimize_stretch_init(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- const UnwrapOptions options = {
- .topology_from_uvs = true,
- .fill_holes = RNA_boolean_get(op->ptr, "fill_holes"),
- .only_selected = true,
- .correct_aspect = true,
- };
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(view_layer, CTX_wm_view3d(C), &objects_len);
-
- if (!uvedit_have_selection_multi(scene, objects, objects_len, &options)) {
- MEM_freeN(objects);
- return false;
- }
-
- MinStretch *ms = MEM_callocN(sizeof(MinStretch), "MinStretch");
- ms->scene = scene;
- ms->objects_edit = objects;
- ms->objects_len = objects_len;
- ms->blend = RNA_float_get(op->ptr, "blend");
- ms->iterations = RNA_int_get(op->ptr, "iterations");
- ms->i = 0;
- ms->handle = construct_param_handle_multi(scene, objects, objects_len, &options);
- ms->lasttime = PIL_check_seconds_timer();
-
- param_stretch_begin(ms->handle);
- if (ms->blend != 0.0f)
- param_stretch_blend(ms->handle, ms->blend);
-
- op->customdata = ms;
-
- return true;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ const UnwrapOptions options = {
+ .topology_from_uvs = true,
+ .fill_holes = RNA_boolean_get(op->ptr, "fill_holes"),
+ .only_selected = true,
+ .correct_aspect = true,
+ };
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ if (!uvedit_have_selection_multi(scene, objects, objects_len, &options)) {
+ MEM_freeN(objects);
+ return false;
+ }
+
+ MinStretch *ms = MEM_callocN(sizeof(MinStretch), "MinStretch");
+ ms->scene = scene;
+ ms->objects_edit = objects;
+ ms->objects_len = objects_len;
+ ms->blend = RNA_float_get(op->ptr, "blend");
+ ms->iterations = RNA_int_get(op->ptr, "iterations");
+ ms->i = 0;
+ ms->handle = construct_param_handle_multi(scene, objects, objects_len, &options);
+ ms->lasttime = PIL_check_seconds_timer();
+
+ param_stretch_begin(ms->handle);
+ if (ms->blend != 0.0f)
+ param_stretch_blend(ms->handle, ms->blend);
+
+ op->customdata = ms;
+
+ return true;
}
static void minimize_stretch_iteration(bContext *C, wmOperator *op, bool interactive)
{
- MinStretch *ms = op->customdata;
- ScrArea *sa = CTX_wm_area(C);
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = scene->toolsettings;
- const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
+ MinStretch *ms = op->customdata;
+ ScrArea *sa = CTX_wm_area(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
+ const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
- param_stretch_blend(ms->handle, ms->blend);
- param_stretch_iter(ms->handle);
+ param_stretch_blend(ms->handle, ms->blend);
+ param_stretch_iter(ms->handle);
- ms->i++;
- RNA_int_set(op->ptr, "iterations", ms->i);
+ ms->i++;
+ RNA_int_set(op->ptr, "iterations", ms->i);
- if (interactive && (PIL_check_seconds_timer() - ms->lasttime > 0.5)) {
- char str[UI_MAX_DRAW_STR];
+ if (interactive && (PIL_check_seconds_timer() - ms->lasttime > 0.5)) {
+ char str[UI_MAX_DRAW_STR];
- param_flush(ms->handle);
+ param_flush(ms->handle);
- if (sa) {
- BLI_snprintf(str, sizeof(str), IFACE_("Minimize Stretch. Blend %.2f"), ms->blend);
- ED_area_status_text(sa, str);
- ED_workspace_status_text(C, IFACE_("Press + and -, or scroll wheel to set blending"));
- }
+ if (sa) {
+ BLI_snprintf(str, sizeof(str), IFACE_("Minimize Stretch. Blend %.2f"), ms->blend);
+ ED_area_status_text(sa, str);
+ ED_workspace_status_text(C, IFACE_("Press + and -, or scroll wheel to set blending"));
+ }
- ms->lasttime = PIL_check_seconds_timer();
+ ms->lasttime = PIL_check_seconds_timer();
- for (uint ob_index = 0; ob_index < ms->objects_len; ob_index++) {
- Object *obedit = ms->objects_edit[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ for (uint ob_index = 0; ob_index < ms->objects_len; ob_index++) {
+ Object *obedit = ms->objects_edit[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (synced_selection && (em->bm->totfacesel == 0)) {
- continue;
- }
+ if (synced_selection && (em->bm->totfacesel == 0)) {
+ continue;
+ }
- DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- }
- }
+ DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ }
+ }
}
static void minimize_stretch_exit(bContext *C, wmOperator *op, bool cancel)
{
- MinStretch *ms = op->customdata;
- ScrArea *sa = CTX_wm_area(C);
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = scene->toolsettings;
- const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
+ MinStretch *ms = op->customdata;
+ ScrArea *sa = CTX_wm_area(C);
+ 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_workspace_status_text(C, NULL);
+ ED_area_status_text(sa, NULL);
+ ED_workspace_status_text(C, NULL);
- if (ms->timer)
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), ms->timer);
+ if (ms->timer)
+ WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), ms->timer);
- if (cancel)
- param_flush_restore(ms->handle);
- else
- param_flush(ms->handle);
+ if (cancel)
+ param_flush_restore(ms->handle);
+ else
+ param_flush(ms->handle);
- param_stretch_end(ms->handle);
- param_delete(ms->handle);
+ param_stretch_end(ms->handle);
+ param_delete(ms->handle);
- for (uint ob_index = 0; ob_index < ms->objects_len; ob_index++) {
- Object *obedit = ms->objects_edit[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ for (uint ob_index = 0; ob_index < ms->objects_len; ob_index++) {
+ Object *obedit = ms->objects_edit[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (synced_selection && (em->bm->totfacesel == 0)) {
- continue;
- }
+ if (synced_selection && (em->bm->totfacesel == 0)) {
+ continue;
+ }
- DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- }
+ DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ }
- MEM_freeN(ms->objects_edit);
- MEM_freeN(ms);
- op->customdata = NULL;
+ MEM_freeN(ms->objects_edit);
+ MEM_freeN(ms);
+ op->customdata = NULL;
}
static int minimize_stretch_exec(bContext *C, wmOperator *op)
{
- int i, iterations;
+ int i, iterations;
- if (!minimize_stretch_init(C, op))
- return OPERATOR_CANCELLED;
+ if (!minimize_stretch_init(C, op))
+ return OPERATOR_CANCELLED;
- iterations = RNA_int_get(op->ptr, "iterations");
- for (i = 0; i < iterations; i++)
- minimize_stretch_iteration(C, op, false);
- minimize_stretch_exit(C, op, false);
+ iterations = RNA_int_get(op->ptr, "iterations");
+ for (i = 0; i < iterations; i++)
+ minimize_stretch_iteration(C, op, false);
+ minimize_stretch_exit(C, op, false);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int minimize_stretch_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- MinStretch *ms;
+ MinStretch *ms;
- if (!minimize_stretch_init(C, op))
- return OPERATOR_CANCELLED;
+ if (!minimize_stretch_init(C, op))
+ return OPERATOR_CANCELLED;
- minimize_stretch_iteration(C, op, true);
+ minimize_stretch_iteration(C, op, true);
- ms = op->customdata;
- WM_event_add_modal_handler(C, op);
- ms->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
+ ms = op->customdata;
+ WM_event_add_modal_handler(C, op);
+ ms->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static int minimize_stretch_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- MinStretch *ms = op->customdata;
-
- switch (event->type) {
- case ESCKEY:
- case RIGHTMOUSE:
- minimize_stretch_exit(C, op, true);
- return OPERATOR_CANCELLED;
- case RETKEY:
- case PADENTER:
- case LEFTMOUSE:
- minimize_stretch_exit(C, op, false);
- return OPERATOR_FINISHED;
- case PADPLUSKEY:
- case WHEELUPMOUSE:
- if (event->val == KM_PRESS) {
- if (ms->blend < 0.95f) {
- ms->blend += 0.1f;
- ms->lasttime = 0.0f;
- RNA_float_set(op->ptr, "blend", ms->blend);
- minimize_stretch_iteration(C, op, true);
- }
- }
- break;
- case PADMINUS:
- case WHEELDOWNMOUSE:
- if (event->val == KM_PRESS) {
- if (ms->blend > 0.05f) {
- ms->blend -= 0.1f;
- ms->lasttime = 0.0f;
- RNA_float_set(op->ptr, "blend", ms->blend);
- minimize_stretch_iteration(C, op, true);
- }
- }
- break;
- case TIMER:
- if (ms->timer == event->customdata) {
- double start = PIL_check_seconds_timer();
-
- do {
- minimize_stretch_iteration(C, op, true);
- } while (PIL_check_seconds_timer() - start < 0.01);
- }
- break;
- }
-
- if (ms->iterations && ms->i >= ms->iterations) {
- minimize_stretch_exit(C, op, false);
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_RUNNING_MODAL;
+ MinStretch *ms = op->customdata;
+
+ switch (event->type) {
+ case ESCKEY:
+ case RIGHTMOUSE:
+ minimize_stretch_exit(C, op, true);
+ return OPERATOR_CANCELLED;
+ case RETKEY:
+ case PADENTER:
+ case LEFTMOUSE:
+ minimize_stretch_exit(C, op, false);
+ return OPERATOR_FINISHED;
+ case PADPLUSKEY:
+ case WHEELUPMOUSE:
+ if (event->val == KM_PRESS) {
+ if (ms->blend < 0.95f) {
+ ms->blend += 0.1f;
+ ms->lasttime = 0.0f;
+ RNA_float_set(op->ptr, "blend", ms->blend);
+ minimize_stretch_iteration(C, op, true);
+ }
+ }
+ break;
+ case PADMINUS:
+ case WHEELDOWNMOUSE:
+ if (event->val == KM_PRESS) {
+ if (ms->blend > 0.05f) {
+ ms->blend -= 0.1f;
+ ms->lasttime = 0.0f;
+ RNA_float_set(op->ptr, "blend", ms->blend);
+ minimize_stretch_iteration(C, op, true);
+ }
+ }
+ break;
+ case TIMER:
+ if (ms->timer == event->customdata) {
+ double start = PIL_check_seconds_timer();
+
+ do {
+ minimize_stretch_iteration(C, op, true);
+ } while (PIL_check_seconds_timer() - start < 0.01);
+ }
+ break;
+ }
+
+ if (ms->iterations && ms->i >= ms->iterations) {
+ minimize_stretch_exit(C, op, false);
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
static void minimize_stretch_cancel(bContext *C, wmOperator *op)
{
- minimize_stretch_exit(C, op, true);
+ minimize_stretch_exit(C, op, true);
}
void UV_OT_minimize_stretch(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Minimize Stretch";
- ot->idname = "UV_OT_minimize_stretch";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
- ot->description = "Reduce UV stretching by relaxing angles";
-
- /* api callbacks */
- ot->exec = minimize_stretch_exec;
- ot->invoke = minimize_stretch_invoke;
- ot->modal = minimize_stretch_modal;
- ot->cancel = minimize_stretch_cancel;
- ot->poll = ED_operator_uvedit;
-
- /* properties */
- RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes", "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry");
- RNA_def_float_factor(ot->srna, "blend", 0.0f, 0.0f, 1.0f, "Blend", "Blend factor between stretch minimized and original", 0.0f, 1.0f);
- RNA_def_int(ot->srna, "iterations", 0, 0, INT_MAX, "Iterations", "Number of iterations to run, 0 is unlimited when run interactively", 0, 100);
+ /* identifiers */
+ ot->name = "Minimize Stretch";
+ ot->idname = "UV_OT_minimize_stretch";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
+ ot->description = "Reduce UV stretching by relaxing angles";
+
+ /* api callbacks */
+ ot->exec = minimize_stretch_exec;
+ ot->invoke = minimize_stretch_invoke;
+ ot->modal = minimize_stretch_modal;
+ ot->cancel = minimize_stretch_cancel;
+ ot->poll = ED_operator_uvedit;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "fill_holes",
+ 1,
+ "Fill Holes",
+ "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and "
+ "preserve symmetry");
+ RNA_def_float_factor(ot->srna,
+ "blend",
+ 0.0f,
+ 0.0f,
+ 1.0f,
+ "Blend",
+ "Blend factor between stretch minimized and original",
+ 0.0f,
+ 1.0f);
+ RNA_def_int(ot->srna,
+ "iterations",
+ 0,
+ 0,
+ INT_MAX,
+ "Iterations",
+ "Number of iterations to run, 0 is unlimited when run interactively",
+ 0,
+ 100);
}
/* ******************** Pack Islands operator **************** */
static void uvedit_pack_islands(Scene *scene, Object *ob, BMesh *bm)
{
- const UnwrapOptions options = {
- .topology_from_uvs = true,
- .only_selected = false,
- .fill_holes = false,
- .correct_aspect = false,
- };
-
- bool rotate = true;
- bool ignore_pinned = false;
-
- ParamHandle *handle;
- handle = construct_param_handle(scene, ob, bm, &options);
- param_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned);
- param_flush(handle);
- param_delete(handle);
+ const UnwrapOptions options = {
+ .topology_from_uvs = true,
+ .only_selected = false,
+ .fill_holes = false,
+ .correct_aspect = false,
+ };
+
+ bool rotate = true;
+ bool ignore_pinned = false;
+
+ ParamHandle *handle;
+ handle = construct_param_handle(scene, ob, bm, &options);
+ param_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned);
+ param_flush(handle);
+ param_delete(handle);
}
-static void uvedit_pack_islands_multi(
- Scene *scene, Object **objects, const uint objects_len,
- const UnwrapOptions *options, bool rotate, bool ignore_pinned)
+static void uvedit_pack_islands_multi(Scene *scene,
+ Object **objects,
+ const uint objects_len,
+ const UnwrapOptions *options,
+ bool rotate,
+ bool ignore_pinned)
{
- ParamHandle *handle;
- handle = construct_param_handle_multi(scene, objects, objects_len, options);
- param_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned);
- param_flush(handle);
- param_delete(handle);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
- WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
- }
+ ParamHandle *handle;
+ handle = construct_param_handle_multi(scene, objects, objects_len, options);
+ param_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned);
+ param_flush(handle);
+ param_delete(handle);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
+ }
}
static int pack_islands_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Scene *scene = CTX_data_scene(C);
- const UnwrapOptions options = {
- .topology_from_uvs = true,
- .only_selected = true,
- .fill_holes = false,
- .correct_aspect = true,
- };
+ const UnwrapOptions options = {
+ .topology_from_uvs = true,
+ .only_selected = true,
+ .fill_holes = false,
+ .correct_aspect = true,
+ };
- bool rotate = RNA_boolean_get(op->ptr, "rotate");
- bool ignore_pinned = false;
+ bool rotate = RNA_boolean_get(op->ptr, "rotate");
+ bool ignore_pinned = false;
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(view_layer, CTX_wm_view3d(C), &objects_len);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, CTX_wm_view3d(C), &objects_len);
- if (!uvedit_have_selection_multi(scene, objects, objects_len, &options)) {
- MEM_freeN(objects);
- return OPERATOR_CANCELLED;
- }
+ if (!uvedit_have_selection_multi(scene, objects, objects_len, &options)) {
+ MEM_freeN(objects);
+ return OPERATOR_CANCELLED;
+ }
- if (RNA_struct_property_is_set(op->ptr, "margin"))
- scene->toolsettings->uvcalc_margin = RNA_float_get(op->ptr, "margin");
- else
- RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
+ if (RNA_struct_property_is_set(op->ptr, "margin"))
+ scene->toolsettings->uvcalc_margin = RNA_float_get(op->ptr, "margin");
+ else
+ RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
- uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned);
+ uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned);
- MEM_freeN(objects);
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void UV_OT_pack_islands(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Pack Islands";
- ot->idname = "UV_OT_pack_islands";
- ot->description = "Transform all islands so that they fill up the UV space as much as possible";
+ /* identifiers */
+ ot->name = "Pack Islands";
+ ot->idname = "UV_OT_pack_islands";
+ ot->description = "Transform all islands so that they fill up the UV space as much as possible";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* api callbacks */
- ot->exec = pack_islands_exec;
- ot->poll = ED_operator_uvedit;
+ /* api callbacks */
+ ot->exec = pack_islands_exec;
+ ot->poll = ED_operator_uvedit;
- /* properties */
- RNA_def_boolean(ot->srna, "rotate", true, "Rotate", "Rotate islands for best fit");
- RNA_def_float_factor(ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
+ /* properties */
+ RNA_def_boolean(ot->srna, "rotate", true, "Rotate", "Rotate islands for best fit");
+ RNA_def_float_factor(
+ ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
}
/* ******************** Average Islands Scale operator **************** */
static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- ToolSettings *ts = scene->toolsettings;
- const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
-
- const UnwrapOptions options = {
- .topology_from_uvs = true,
- .only_selected = true,
- .fill_holes = false,
- .correct_aspect = true,
- };
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(view_layer, CTX_wm_view3d(C), &objects_len);
-
- if (!uvedit_have_selection_multi(scene, objects, objects_len, &options)) {
- MEM_freeN(objects);
- return OPERATOR_CANCELLED;
- }
-
- ParamHandle *handle = construct_param_handle_multi(scene, objects, objects_len, &options);
- param_average(handle, false);
- param_flush(handle);
- param_delete(handle);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (synced_selection && (em->bm->totvertsel == 0)) {
- continue;
- }
-
- DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ ToolSettings *ts = scene->toolsettings;
+ const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
+
+ const UnwrapOptions options = {
+ .topology_from_uvs = true,
+ .only_selected = true,
+ .fill_holes = false,
+ .correct_aspect = true,
+ };
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ if (!uvedit_have_selection_multi(scene, objects, objects_len, &options)) {
+ MEM_freeN(objects);
+ return OPERATOR_CANCELLED;
+ }
+
+ ParamHandle *handle = construct_param_handle_multi(scene, objects, objects_len, &options);
+ param_average(handle, false);
+ param_flush(handle);
+ param_delete(handle);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (synced_selection && (em->bm->totvertsel == 0)) {
+ continue;
+ }
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void UV_OT_average_islands_scale(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Average Islands Scale";
- ot->idname = "UV_OT_average_islands_scale";
- ot->description = "Average the size of separate UV islands, based on their area in 3D space";
+ /* identifiers */
+ ot->name = "Average Islands Scale";
+ ot->idname = "UV_OT_average_islands_scale";
+ ot->description = "Average the size of separate UV islands, based on their area in 3D space";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* api callbacks */
- ot->exec = average_islands_scale_exec;
- ot->poll = ED_operator_uvedit;
+ /* api callbacks */
+ ot->exec = average_islands_scale_exec;
+ ot->poll = ED_operator_uvedit;
}
/**************** Live Unwrap *****************/
static struct {
- ParamHandle **handles;
- uint len, len_alloc;
+ ParamHandle **handles;
+ uint len, len_alloc;
} g_live_unwrap = {NULL};
void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit)
{
- ParamHandle *handle = NULL;
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- const bool abf = (scene->toolsettings->unwrapper == 0);
- bool use_subsurf;
-
- modifier_unwrap_state(obedit, scene, &use_subsurf);
-
- if (!ED_uvedit_test(obedit)) {
- return;
- }
-
- const UnwrapOptions options = {
- .topology_from_uvs = false,
- .only_selected = false,
- .fill_holes = (scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES) != 0,
- .correct_aspect = (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) == 0,
- };
-
- if (use_subsurf)
- handle = construct_param_handle_subsurfed(scene, obedit, em, &options);
- else
- handle = construct_param_handle(scene, obedit, em->bm, &options);
-
- param_lscm_begin(handle, PARAM_TRUE, abf);
-
- /* Create or increase size of g_live_unwrap.handles array */
- if (g_live_unwrap.handles == NULL) {
- g_live_unwrap.len_alloc = 32;
- g_live_unwrap.handles = MEM_mallocN(sizeof(ParamHandle *) * g_live_unwrap.len_alloc, "uvedit_live_unwrap_liveHandles");
- g_live_unwrap.len = 0;
- }
- if (g_live_unwrap.len >= g_live_unwrap.len_alloc) {
- g_live_unwrap.len_alloc *= 2;
- g_live_unwrap.handles = MEM_reallocN(g_live_unwrap.handles, sizeof(ParamHandle *) * g_live_unwrap.len_alloc);
- }
- g_live_unwrap.handles[g_live_unwrap.len] = handle;
- g_live_unwrap.len++;
+ ParamHandle *handle = NULL;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ const bool abf = (scene->toolsettings->unwrapper == 0);
+ bool use_subsurf;
+
+ modifier_unwrap_state(obedit, scene, &use_subsurf);
+
+ if (!ED_uvedit_test(obedit)) {
+ return;
+ }
+
+ const UnwrapOptions options = {
+ .topology_from_uvs = false,
+ .only_selected = false,
+ .fill_holes = (scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES) != 0,
+ .correct_aspect = (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) == 0,
+ };
+
+ if (use_subsurf)
+ handle = construct_param_handle_subsurfed(scene, obedit, em, &options);
+ else
+ handle = construct_param_handle(scene, obedit, em->bm, &options);
+
+ param_lscm_begin(handle, PARAM_TRUE, abf);
+
+ /* Create or increase size of g_live_unwrap.handles array */
+ if (g_live_unwrap.handles == NULL) {
+ g_live_unwrap.len_alloc = 32;
+ g_live_unwrap.handles = MEM_mallocN(sizeof(ParamHandle *) * g_live_unwrap.len_alloc,
+ "uvedit_live_unwrap_liveHandles");
+ g_live_unwrap.len = 0;
+ }
+ if (g_live_unwrap.len >= g_live_unwrap.len_alloc) {
+ g_live_unwrap.len_alloc *= 2;
+ g_live_unwrap.handles = MEM_reallocN(g_live_unwrap.handles,
+ sizeof(ParamHandle *) * g_live_unwrap.len_alloc);
+ }
+ g_live_unwrap.handles[g_live_unwrap.len] = handle;
+ g_live_unwrap.len++;
}
void ED_uvedit_live_unwrap_re_solve(void)
{
- if (g_live_unwrap.handles) {
- for (int i = 0; i < g_live_unwrap.len; i++) {
- param_lscm_solve(g_live_unwrap.handles[i]);
- param_flush(g_live_unwrap.handles[i]);
- }
- }
+ if (g_live_unwrap.handles) {
+ for (int i = 0; i < g_live_unwrap.len; i++) {
+ param_lscm_solve(g_live_unwrap.handles[i]);
+ param_flush(g_live_unwrap.handles[i]);
+ }
+ }
}
void ED_uvedit_live_unwrap_end(short cancel)
{
- if (g_live_unwrap.handles) {
- for (int i = 0; i < g_live_unwrap.len; i++) {
- param_lscm_end(g_live_unwrap.handles[i]);
- if (cancel)
- param_flush_restore(g_live_unwrap.handles[i]);
- param_delete(g_live_unwrap.handles[i]);
- }
- MEM_freeN(g_live_unwrap.handles);
- g_live_unwrap.handles = NULL;
- g_live_unwrap.len = 0;
- g_live_unwrap.len_alloc = 0;
- }
+ if (g_live_unwrap.handles) {
+ for (int i = 0; i < g_live_unwrap.len; i++) {
+ param_lscm_end(g_live_unwrap.handles[i]);
+ if (cancel)
+ param_flush_restore(g_live_unwrap.handles[i]);
+ param_delete(g_live_unwrap.handles[i]);
+ }
+ MEM_freeN(g_live_unwrap.handles);
+ g_live_unwrap.handles = NULL;
+ g_live_unwrap.len = 0;
+ g_live_unwrap.len_alloc = 0;
+ }
}
/*************** UV Map Common Transforms *****************/
#define VIEW_ON_EQUATOR 0
-#define VIEW_ON_POLES 1
+#define VIEW_ON_POLES 1
#define ALIGN_TO_OBJECT 2
-#define POLAR_ZX 0
-#define POLAR_ZY 1
+#define POLAR_ZX 0
+#define POLAR_ZY 1
static void uv_map_transform_calc_bounds(BMEditMesh *em, float r_min[3], float r_max[3])
{
- BMFace *efa;
- BMIter iter;
- INIT_MINMAX(r_min, r_max);
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- BM_face_calc_bounds_expand(efa, r_min, r_max);
- }
- }
+ BMFace *efa;
+ BMIter iter;
+ INIT_MINMAX(r_min, r_max);
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ BM_face_calc_bounds_expand(efa, r_min, r_max);
+ }
+ }
}
static void uv_map_transform_calc_center_median(BMEditMesh *em, float r_center[3])
{
- BMFace *efa;
- BMIter iter;
- uint center_accum_num = 0;
- zero_v3(r_center);
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- float center[3];
- BM_face_calc_center_median(efa, center);
- add_v3_v3(r_center, center);
- center_accum_num += 1;
- }
- }
- mul_v3_fl(r_center, 1.0f / (float)center_accum_num);
+ BMFace *efa;
+ BMIter iter;
+ uint center_accum_num = 0;
+ zero_v3(r_center);
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ float center[3];
+ BM_face_calc_center_median(efa, center);
+ add_v3_v3(r_center, center);
+ center_accum_num += 1;
+ }
+ }
+ mul_v3_fl(r_center, 1.0f / (float)center_accum_num);
}
static void uv_map_transform_center(
- Scene *scene, View3D *v3d, Object *ob, BMEditMesh *em,
- float r_center[3],
- float r_bounds[2][3])
+ Scene *scene, View3D *v3d, Object *ob, BMEditMesh *em, float r_center[3], float r_bounds[2][3])
{
- /* only operates on the edit object - this is all that's needed now */
- const int around = (v3d) ? scene->toolsettings->transform_pivot_point : V3D_AROUND_CENTER_BOUNDS;
-
- float bounds[2][3];
- INIT_MINMAX(bounds[0], bounds[1]);
- bool is_minmax_set = false;
-
- switch (around) {
- case V3D_AROUND_CENTER_BOUNDS: /* bounding box center */
- {
- uv_map_transform_calc_bounds(em, bounds[0], bounds[1]);
- is_minmax_set = true;
- mid_v3_v3v3(r_center, bounds[0], bounds[1]);
- break;
- }
- case V3D_AROUND_CENTER_MEDIAN:
- {
- uv_map_transform_calc_center_median(em, r_center);
- break;
- }
- case V3D_AROUND_CURSOR: /* cursor center */
- {
- invert_m4_m4(ob->imat, ob->obmat);
- mul_v3_m4v3(r_center, ob->imat, scene->cursor.location);
- break;
- }
- case V3D_AROUND_ACTIVE:
- {
- BMEditSelection ese;
- if (BM_select_history_active_get(em->bm, &ese)) {
- BM_editselection_center(&ese, r_center);
- break;
- }
- ATTR_FALLTHROUGH;
- }
- case V3D_AROUND_LOCAL_ORIGINS: /* object center */
- default:
- zero_v3(r_center);
- break;
- }
-
- /* if this is passed, always set! */
- if (r_bounds) {
- if (!is_minmax_set) {
- uv_map_transform_calc_bounds(em, bounds[0], bounds[1]);
- }
- copy_v3_v3(r_bounds[0], bounds[0]);
- copy_v3_v3(r_bounds[1], bounds[1]);
- }
+ /* only operates on the edit object - this is all that's needed now */
+ const int around = (v3d) ? scene->toolsettings->transform_pivot_point : V3D_AROUND_CENTER_BOUNDS;
+
+ float bounds[2][3];
+ INIT_MINMAX(bounds[0], bounds[1]);
+ bool is_minmax_set = false;
+
+ switch (around) {
+ case V3D_AROUND_CENTER_BOUNDS: /* bounding box center */
+ {
+ uv_map_transform_calc_bounds(em, bounds[0], bounds[1]);
+ is_minmax_set = true;
+ mid_v3_v3v3(r_center, bounds[0], bounds[1]);
+ break;
+ }
+ case V3D_AROUND_CENTER_MEDIAN: {
+ uv_map_transform_calc_center_median(em, r_center);
+ break;
+ }
+ case V3D_AROUND_CURSOR: /* cursor center */
+ {
+ invert_m4_m4(ob->imat, ob->obmat);
+ mul_v3_m4v3(r_center, ob->imat, scene->cursor.location);
+ break;
+ }
+ case V3D_AROUND_ACTIVE: {
+ BMEditSelection ese;
+ if (BM_select_history_active_get(em->bm, &ese)) {
+ BM_editselection_center(&ese, r_center);
+ break;
+ }
+ ATTR_FALLTHROUGH;
+ }
+ case V3D_AROUND_LOCAL_ORIGINS: /* object center */
+ default:
+ zero_v3(r_center);
+ break;
+ }
+
+ /* if this is passed, always set! */
+ if (r_bounds) {
+ if (!is_minmax_set) {
+ uv_map_transform_calc_bounds(em, bounds[0], bounds[1]);
+ }
+ copy_v3_v3(r_bounds[0], bounds[0]);
+ copy_v3_v3(r_bounds[1], bounds[1]);
+ }
}
-static void uv_map_rotation_matrix_ex(
- float result[4][4], RegionView3D *rv3d, Object *ob,
- float upangledeg, float sideangledeg, float radius, float offset[4])
+static void uv_map_rotation_matrix_ex(float result[4][4],
+ RegionView3D *rv3d,
+ Object *ob,
+ float upangledeg,
+ float sideangledeg,
+ float radius,
+ float offset[4])
{
- float rotup[4][4], rotside[4][4], viewmatrix[4][4], rotobj[4][4];
- float sideangle = 0.0f, upangle = 0.0f;
-
- /* get rotation of the current view matrix */
- if (rv3d)
- copy_m4_m4(viewmatrix, rv3d->viewmat);
- else
- unit_m4(viewmatrix);
-
- /* but shifting */
- copy_v4_fl(viewmatrix[3], 0.0f);
-
- /* get rotation of the current object matrix */
- copy_m4_m4(rotobj, ob->obmat);
-
- /* but shifting */
- add_v4_v4(rotobj[3], offset);
- rotobj[3][3] = 0.0f;
-
- zero_m4(rotup);
- zero_m4(rotside);
-
- /* compensate front/side.. against opengl x,y,z world definition */
- /* this is "kanonen gegen spatzen", a few plus minus 1 will do here */
- /* i wanted to keep the reason here, so we're rotating*/
- sideangle = (float)M_PI * (sideangledeg + 180.0f) / 180.0f;
- rotside[0][0] = cosf(sideangle);
- rotside[0][1] = -sinf(sideangle);
- rotside[1][0] = sinf(sideangle);
- rotside[1][1] = cosf(sideangle);
- rotside[2][2] = 1.0f;
-
- upangle = (float)M_PI * upangledeg / 180.0f;
- rotup[1][1] = cosf(upangle) / radius;
- rotup[1][2] = -sinf(upangle) / radius;
- rotup[2][1] = sinf(upangle) / radius;
- rotup[2][2] = cosf(upangle) / radius;
- rotup[0][0] = 1.0f / radius;
-
- /* calculate transforms*/
- mul_m4_series(result, rotup, rotside, viewmatrix, rotobj);
+ float rotup[4][4], rotside[4][4], viewmatrix[4][4], rotobj[4][4];
+ float sideangle = 0.0f, upangle = 0.0f;
+
+ /* get rotation of the current view matrix */
+ if (rv3d)
+ copy_m4_m4(viewmatrix, rv3d->viewmat);
+ else
+ unit_m4(viewmatrix);
+
+ /* but shifting */
+ copy_v4_fl(viewmatrix[3], 0.0f);
+
+ /* get rotation of the current object matrix */
+ copy_m4_m4(rotobj, ob->obmat);
+
+ /* but shifting */
+ add_v4_v4(rotobj[3], offset);
+ rotobj[3][3] = 0.0f;
+
+ zero_m4(rotup);
+ zero_m4(rotside);
+
+ /* compensate front/side.. against opengl x,y,z world definition */
+ /* this is "kanonen gegen spatzen", a few plus minus 1 will do here */
+ /* i wanted to keep the reason here, so we're rotating*/
+ sideangle = (float)M_PI * (sideangledeg + 180.0f) / 180.0f;
+ rotside[0][0] = cosf(sideangle);
+ rotside[0][1] = -sinf(sideangle);
+ rotside[1][0] = sinf(sideangle);
+ rotside[1][1] = cosf(sideangle);
+ rotside[2][2] = 1.0f;
+
+ upangle = (float)M_PI * upangledeg / 180.0f;
+ rotup[1][1] = cosf(upangle) / radius;
+ rotup[1][2] = -sinf(upangle) / radius;
+ rotup[2][1] = sinf(upangle) / radius;
+ rotup[2][2] = cosf(upangle) / radius;
+ rotup[0][0] = 1.0f / radius;
+
+ /* calculate transforms*/
+ mul_m4_series(result, rotup, rotside, viewmatrix, rotobj);
}
-static void uv_map_rotation_matrix(
- float result[4][4], RegionView3D *rv3d, Object *ob,
- float upangledeg, float sideangledeg, float radius)
+static void uv_map_rotation_matrix(float result[4][4],
+ RegionView3D *rv3d,
+ Object *ob,
+ float upangledeg,
+ float sideangledeg,
+ float radius)
{
- float offset[4] = {0};
- uv_map_rotation_matrix_ex(result, rv3d, ob, upangledeg, sideangledeg, radius, offset);
+ float offset[4] = {0};
+ uv_map_rotation_matrix_ex(result, rv3d, ob, upangledeg, sideangledeg, radius, offset);
}
static void uv_map_transform(bContext *C, wmOperator *op, float rotmat[4][4])
{
- /* context checks are messy here, making it work in both 3d view and uv editor */
- Object *obedit = CTX_data_edit_object(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- /* common operator properties */
- int align = RNA_enum_get(op->ptr, "align");
- int direction = RNA_enum_get(op->ptr, "direction");
- float radius = RNA_struct_find_property(op->ptr, "radius") ? RNA_float_get(op->ptr, "radius") : 1.0f;
- float upangledeg, sideangledeg;
-
- if (direction == VIEW_ON_EQUATOR) {
- upangledeg = 90.0f;
- sideangledeg = 0.0f;
- }
- else {
- upangledeg = 0.0f;
- if (align == POLAR_ZY) sideangledeg = 0.0f;
- else sideangledeg = 90.0f;
- }
-
- /* be compatible to the "old" sphere/cylinder mode */
- if (direction == ALIGN_TO_OBJECT)
- unit_m4(rotmat);
- else
- uv_map_rotation_matrix(rotmat, rv3d, obedit, upangledeg, sideangledeg, radius);
-
+ /* context checks are messy here, making it work in both 3d view and uv editor */
+ Object *obedit = CTX_data_edit_object(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ /* common operator properties */
+ int align = RNA_enum_get(op->ptr, "align");
+ int direction = RNA_enum_get(op->ptr, "direction");
+ float radius = RNA_struct_find_property(op->ptr, "radius") ? RNA_float_get(op->ptr, "radius") :
+ 1.0f;
+ float upangledeg, sideangledeg;
+
+ if (direction == VIEW_ON_EQUATOR) {
+ upangledeg = 90.0f;
+ sideangledeg = 0.0f;
+ }
+ else {
+ upangledeg = 0.0f;
+ if (align == POLAR_ZY)
+ sideangledeg = 0.0f;
+ else
+ sideangledeg = 90.0f;
+ }
+
+ /* be compatible to the "old" sphere/cylinder mode */
+ if (direction == ALIGN_TO_OBJECT)
+ unit_m4(rotmat);
+ else
+ uv_map_rotation_matrix(rotmat, rv3d, obedit, upangledeg, sideangledeg, radius);
}
static void uv_transform_properties(wmOperatorType *ot, int radius)
{
- static const EnumPropertyItem direction_items[] = {
- {VIEW_ON_EQUATOR, "VIEW_ON_EQUATOR", 0, "View on Equator", "3D view is on the equator"},
- {VIEW_ON_POLES, "VIEW_ON_POLES", 0, "View on Poles", "3D view is on the poles"},
- {ALIGN_TO_OBJECT, "ALIGN_TO_OBJECT", 0, "Align to Object", "Align according to object transform"},
- {0, NULL, 0, NULL, NULL},
- };
- static const EnumPropertyItem align_items[] = {
- {POLAR_ZX, "POLAR_ZX", 0, "Polar ZX", "Polar 0 is X"},
- {POLAR_ZY, "POLAR_ZY", 0, "Polar ZY", "Polar 0 is Y"},
- {0, NULL, 0, NULL, NULL},
- };
-
- RNA_def_enum(ot->srna, "direction", direction_items, VIEW_ON_EQUATOR, "Direction",
- "Direction of the sphere or cylinder");
- RNA_def_enum(ot->srna, "align", align_items, VIEW_ON_EQUATOR, "Align",
- "How to determine rotation around the pole");
- if (radius)
- RNA_def_float(ot->srna, "radius", 1.0f, 0.0f, FLT_MAX, "Radius",
- "Radius of the sphere or cylinder", 0.0001f, 100.0f);
+ static const EnumPropertyItem direction_items[] = {
+ {VIEW_ON_EQUATOR, "VIEW_ON_EQUATOR", 0, "View on Equator", "3D view is on the equator"},
+ {VIEW_ON_POLES, "VIEW_ON_POLES", 0, "View on Poles", "3D view is on the poles"},
+ {ALIGN_TO_OBJECT,
+ "ALIGN_TO_OBJECT",
+ 0,
+ "Align to Object",
+ "Align according to object transform"},
+ {0, NULL, 0, NULL, NULL},
+ };
+ static const EnumPropertyItem align_items[] = {
+ {POLAR_ZX, "POLAR_ZX", 0, "Polar ZX", "Polar 0 is X"},
+ {POLAR_ZY, "POLAR_ZY", 0, "Polar ZY", "Polar 0 is Y"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ RNA_def_enum(ot->srna,
+ "direction",
+ direction_items,
+ VIEW_ON_EQUATOR,
+ "Direction",
+ "Direction of the sphere or cylinder");
+ RNA_def_enum(ot->srna,
+ "align",
+ align_items,
+ VIEW_ON_EQUATOR,
+ "Align",
+ "How to determine rotation around the pole");
+ if (radius)
+ RNA_def_float(ot->srna,
+ "radius",
+ 1.0f,
+ 0.0f,
+ FLT_MAX,
+ "Radius",
+ "Radius of the sphere or cylinder",
+ 0.0001f,
+ 100.0f);
}
static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em)
{
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
- BMFace *efa;
- float scale, aspx, aspy;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- ED_uvedit_get_aspect(scene, ob, em->bm, &aspx, &aspy);
-
- if (aspx == aspy)
- return;
-
- if (aspx > aspy) {
- scale = aspy / aspx;
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
- continue;
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->uv[0] = ((luv->uv[0] - 0.5f) * scale) + 0.5f;
- }
- }
- }
- else {
- scale = aspx / aspy;
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
- continue;
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->uv[1] = ((luv->uv[1] - 0.5f) * scale) + 0.5f;
- }
- }
- }
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+ BMFace *efa;
+ float scale, aspx, aspy;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ ED_uvedit_get_aspect(scene, ob, em->bm, &aspx, &aspy);
+
+ if (aspx == aspy)
+ return;
+
+ if (aspx > aspy) {
+ scale = aspy / aspx;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ continue;
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv->uv[0] = ((luv->uv[0] - 0.5f) * scale) + 0.5f;
+ }
+ }
+ }
+ else {
+ scale = aspx / aspy;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ continue;
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv->uv[1] = ((luv->uv[1] - 0.5f) * scale) + 0.5f;
+ }
+ }
+ }
}
/******************** Map Clip & Correct ******************/
static void uv_map_clip_correct_properties(wmOperatorType *ot)
{
- RNA_def_boolean(ot->srna, "correct_aspect", 1, "Correct Aspect",
- "Map UVs taking image aspect ratio into account");
- RNA_def_boolean(ot->srna, "clip_to_bounds", 0, "Clip to Bounds",
- "Clip UV coordinates to bounds after unwrapping");
- RNA_def_boolean(ot->srna, "scale_to_bounds", 0, "Scale to Bounds",
- "Scale UV coordinates to bounds after unwrapping");
+ RNA_def_boolean(ot->srna,
+ "correct_aspect",
+ 1,
+ "Correct Aspect",
+ "Map UVs taking image aspect ratio into account");
+ RNA_def_boolean(ot->srna,
+ "clip_to_bounds",
+ 0,
+ "Clip to Bounds",
+ "Clip UV coordinates to bounds after unwrapping");
+ RNA_def_boolean(ot->srna,
+ "scale_to_bounds",
+ 0,
+ "Scale to Bounds",
+ "Scale UV coordinates to bounds after unwrapping");
}
-static void uv_map_clip_correct_multi(Scene *scene, Object **objects, uint objects_len, wmOperator *op)
+static void uv_map_clip_correct_multi(Scene *scene,
+ Object **objects,
+ uint objects_len,
+ wmOperator *op)
{
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
- float dx, dy, min[2], max[2];
- const bool correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect");
- const bool clip_to_bounds = RNA_boolean_get(op->ptr, "clip_to_bounds");
- const bool scale_to_bounds = RNA_boolean_get(op->ptr, "scale_to_bounds");
-
- INIT_MINMAX2(min, max);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
-
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- /* correct for image aspect ratio */
- if (correct_aspect)
- correct_uv_aspect(scene, ob, em);
-
- if (scale_to_bounds) {
- /* find uv limits */
- BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
- continue;
-
- BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- minmax_v2v2_v2(min, max, luv->uv);
- }
- }
- }
- else if (clip_to_bounds) {
- /* clipping and wrapping */
- BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
- continue;
-
- 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);
- }
- }
- }
- }
-
- if (scale_to_bounds) {
- /* rescale UV to be in 1/1 */
- dx = (max[0] - min[0]);
- dy = (max[1] - min[1]);
-
- if (dx > 0.0f)
- dx = 1.0f / dx;
- if (dy > 0.0f)
- dy = 1.0f / dy;
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
-
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- 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 (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
- continue;
-
- BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- luv->uv[0] = (luv->uv[0] - min[0]) * dx;
- luv->uv[1] = (luv->uv[1] - min[1]) * dy;
- }
- }
- }
- }
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+ float dx, dy, min[2], max[2];
+ const bool correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect");
+ const bool clip_to_bounds = RNA_boolean_get(op->ptr, "clip_to_bounds");
+ const bool scale_to_bounds = RNA_boolean_get(op->ptr, "scale_to_bounds");
+
+ INIT_MINMAX2(min, max);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ /* correct for image aspect ratio */
+ if (correct_aspect)
+ correct_uv_aspect(scene, ob, em);
+
+ if (scale_to_bounds) {
+ /* find uv limits */
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ continue;
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ minmax_v2v2_v2(min, max, luv->uv);
+ }
+ }
+ }
+ else if (clip_to_bounds) {
+ /* clipping and wrapping */
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ continue;
+
+ 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);
+ }
+ }
+ }
+ }
+
+ if (scale_to_bounds) {
+ /* rescale UV to be in 1/1 */
+ dx = (max[0] - min[0]);
+ dy = (max[1] - min[1]);
+
+ if (dx > 0.0f)
+ dx = 1.0f / dx;
+ if (dy > 0.0f)
+ dy = 1.0f / dy;
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ 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 (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ continue;
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ luv->uv[0] = (luv->uv[0] - min[0]) * dx;
+ luv->uv[1] = (luv->uv[1] - min[1]) * dy;
+ }
+ }
+ }
+ }
}
static void uv_map_clip_correct(Scene *scene, Object *ob, wmOperator *op)
{
- uv_map_clip_correct_multi(scene, &ob, 1, op);
+ uv_map_clip_correct_multi(scene, &ob, 1, op);
}
/* ******************** Unwrap operator **************** */
@@ -1413,195 +1510,228 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, wmOperator *op)
/* Assumes UV Map exists, doesn't run update funcs. */
static void uvedit_unwrap(Scene *scene, Object *obedit, const UnwrapOptions *options)
{
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (!CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV)) {
- return;
- }
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ if (!CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV)) {
+ return;
+ }
- bool use_subsurf;
- modifier_unwrap_state(obedit, scene, &use_subsurf);
+ bool use_subsurf;
+ modifier_unwrap_state(obedit, scene, &use_subsurf);
- ParamHandle *handle;
- if (use_subsurf)
- handle = construct_param_handle_subsurfed(scene, obedit, em, options);
- else
- handle = construct_param_handle(scene, obedit, em->bm, options);
+ ParamHandle *handle;
+ if (use_subsurf)
+ handle = construct_param_handle_subsurfed(scene, obedit, em, options);
+ else
+ handle = construct_param_handle(scene, obedit, em->bm, options);
- param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0);
- param_lscm_solve(handle);
- param_lscm_end(handle);
+ param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0);
+ param_lscm_solve(handle);
+ param_lscm_end(handle);
- param_average(handle, true);
+ param_average(handle, true);
- param_flush(handle);
+ param_flush(handle);
- param_delete(handle);
+ param_delete(handle);
}
-static void uvedit_unwrap_multi(Scene *scene, Object **objects, const int objects_len, const UnwrapOptions *options)
+static void uvedit_unwrap_multi(Scene *scene,
+ Object **objects,
+ const int objects_len,
+ const UnwrapOptions *options)
{
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- uvedit_unwrap(scene, obedit, options);
- DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
- WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
- }
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ uvedit_unwrap(scene, obedit, options);
+ DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
+ }
}
void ED_uvedit_live_unwrap(Scene *scene, Object **objects, int objects_len)
{
- if (scene->toolsettings->edge_mode_live_unwrap) {
- const UnwrapOptions options = {
- .topology_from_uvs = false,
- .only_selected = false,
- .fill_holes = (scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES) != 0,
- .correct_aspect = (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) == 0,
- };
-
- bool rotate = true;
- bool ignore_pinned = true;
-
- uvedit_unwrap_multi(scene, objects, objects_len, &options);
- uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned);
- }
+ if (scene->toolsettings->edge_mode_live_unwrap) {
+ const UnwrapOptions options = {
+ .topology_from_uvs = false,
+ .only_selected = false,
+ .fill_holes = (scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES) != 0,
+ .correct_aspect = (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) == 0,
+ };
+
+ bool rotate = true;
+ bool ignore_pinned = true;
+
+ uvedit_unwrap_multi(scene, objects, objects_len, &options);
+ uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned);
+ }
}
enum {
- UNWRAP_ERROR_NONUNIFORM = (1 << 0),
- UNWRAP_ERROR_NEGATIVE = (1 << 1),
+ UNWRAP_ERROR_NONUNIFORM = (1 << 0),
+ UNWRAP_ERROR_NEGATIVE = (1 << 1),
};
static int unwrap_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Scene *scene = CTX_data_scene(C);
- int method = RNA_enum_get(op->ptr, "method");
- const bool use_subsurf = RNA_boolean_get(op->ptr, "use_subsurf_data");
- int reported_errors = 0;
- /* We will report an error unless at least one object
- * has the subsurf modifier in the right place. */
- bool subsurf_error = use_subsurf;
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
-
- const UnwrapOptions options = {
- .topology_from_uvs = false,
- .only_selected = true,
- .fill_holes = RNA_boolean_get(op->ptr, "fill_holes"),
- .correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect"),
- };
-
- bool rotate = true;
- bool ignore_pinned = true;
-
- if (!uvedit_have_selection_multi(scene, objects, objects_len, &options)) {
- MEM_freeN(objects);
- return OPERATOR_CANCELLED;
- }
-
- /* add uvs if they don't exist yet */
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- float obsize[3];
- bool use_subsurf_final;
-
- if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
- continue;
- }
-
- if (subsurf_error) {
- /* Double up the check here but better keep uvedit_unwrap interface simple and not
- * pass operator for warning append. */
- modifier_unwrap_state(obedit, scene, &use_subsurf_final);
- if (use_subsurf_final) {
- subsurf_error = false;
- }
- }
-
- if (reported_errors & (UNWRAP_ERROR_NONUNIFORM | UNWRAP_ERROR_NEGATIVE)) {
- continue;
- }
-
- mat4_to_size(obsize, obedit->obmat);
- if (!(fabsf(obsize[0] - obsize[1]) < 1e-4f && fabsf(obsize[1] - obsize[2]) < 1e-4f)) {
- if ((reported_errors & UNWRAP_ERROR_NONUNIFORM) == 0) {
- BKE_report(op->reports, RPT_INFO,
- "Object has non-uniform scale, unwrap will operate on a non-scaled version of the mesh");
- reported_errors |= UNWRAP_ERROR_NONUNIFORM;
- }
- }
- else if (is_negative_m4(obedit->obmat)) {
- if ((reported_errors & UNWRAP_ERROR_NEGATIVE) == 0) {
- BKE_report(op->reports, RPT_INFO,
- "Object has negative scale, unwrap will operate on a non-flipped version of the mesh");
- reported_errors |= UNWRAP_ERROR_NEGATIVE;
- }
- }
- }
-
- if (subsurf_error) {
- BKE_report(op->reports, RPT_INFO, "Subdivision Surface modifier needs to be first to work with unwrap");
- }
-
- /* remember last method for live unwrap */
- if (RNA_struct_property_is_set(op->ptr, "method"))
- scene->toolsettings->unwrapper = method;
- else
- RNA_enum_set(op->ptr, "method", scene->toolsettings->unwrapper);
-
- /* remember packing margin */
- if (RNA_struct_property_is_set(op->ptr, "margin"))
- scene->toolsettings->uvcalc_margin = RNA_float_get(op->ptr, "margin");
- else
- RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
-
- if (options.fill_holes) scene->toolsettings->uvcalc_flag |= UVCALC_FILLHOLES;
- else scene->toolsettings->uvcalc_flag &= ~UVCALC_FILLHOLES;
-
- if (options.correct_aspect) scene->toolsettings->uvcalc_flag &= ~UVCALC_NO_ASPECT_CORRECT;
- else scene->toolsettings->uvcalc_flag |= UVCALC_NO_ASPECT_CORRECT;
-
- if (use_subsurf) scene->toolsettings->uvcalc_flag |= UVCALC_USESUBSURF;
- else scene->toolsettings->uvcalc_flag &= ~UVCALC_USESUBSURF;
-
- /* execute unwrap */
- uvedit_unwrap_multi(scene, objects, objects_len, &options);
- uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned);
-
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Scene *scene = CTX_data_scene(C);
+ int method = RNA_enum_get(op->ptr, "method");
+ const bool use_subsurf = RNA_boolean_get(op->ptr, "use_subsurf_data");
+ int reported_errors = 0;
+ /* We will report an error unless at least one object
+ * has the subsurf modifier in the right place. */
+ bool subsurf_error = use_subsurf;
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ const UnwrapOptions options = {
+ .topology_from_uvs = false,
+ .only_selected = true,
+ .fill_holes = RNA_boolean_get(op->ptr, "fill_holes"),
+ .correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect"),
+ };
+
+ bool rotate = true;
+ bool ignore_pinned = true;
+
+ if (!uvedit_have_selection_multi(scene, objects, objects_len, &options)) {
+ MEM_freeN(objects);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* add uvs if they don't exist yet */
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ float obsize[3];
+ bool use_subsurf_final;
+
+ if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
+ continue;
+ }
+
+ if (subsurf_error) {
+ /* Double up the check here but better keep uvedit_unwrap interface simple and not
+ * pass operator for warning append. */
+ modifier_unwrap_state(obedit, scene, &use_subsurf_final);
+ if (use_subsurf_final) {
+ subsurf_error = false;
+ }
+ }
+
+ if (reported_errors & (UNWRAP_ERROR_NONUNIFORM | UNWRAP_ERROR_NEGATIVE)) {
+ continue;
+ }
+
+ mat4_to_size(obsize, obedit->obmat);
+ if (!(fabsf(obsize[0] - obsize[1]) < 1e-4f && fabsf(obsize[1] - obsize[2]) < 1e-4f)) {
+ if ((reported_errors & UNWRAP_ERROR_NONUNIFORM) == 0) {
+ BKE_report(op->reports,
+ RPT_INFO,
+ "Object has non-uniform scale, unwrap will operate on a non-scaled version of "
+ "the mesh");
+ reported_errors |= UNWRAP_ERROR_NONUNIFORM;
+ }
+ }
+ else if (is_negative_m4(obedit->obmat)) {
+ if ((reported_errors & UNWRAP_ERROR_NEGATIVE) == 0) {
+ BKE_report(
+ op->reports,
+ RPT_INFO,
+ "Object has negative scale, unwrap will operate on a non-flipped version of the mesh");
+ reported_errors |= UNWRAP_ERROR_NEGATIVE;
+ }
+ }
+ }
+
+ if (subsurf_error) {
+ BKE_report(op->reports,
+ RPT_INFO,
+ "Subdivision Surface modifier needs to be first to work with unwrap");
+ }
+
+ /* remember last method for live unwrap */
+ if (RNA_struct_property_is_set(op->ptr, "method"))
+ scene->toolsettings->unwrapper = method;
+ else
+ RNA_enum_set(op->ptr, "method", scene->toolsettings->unwrapper);
+
+ /* remember packing margin */
+ if (RNA_struct_property_is_set(op->ptr, "margin"))
+ scene->toolsettings->uvcalc_margin = RNA_float_get(op->ptr, "margin");
+ else
+ RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
+
+ if (options.fill_holes)
+ scene->toolsettings->uvcalc_flag |= UVCALC_FILLHOLES;
+ else
+ scene->toolsettings->uvcalc_flag &= ~UVCALC_FILLHOLES;
+
+ if (options.correct_aspect)
+ scene->toolsettings->uvcalc_flag &= ~UVCALC_NO_ASPECT_CORRECT;
+ else
+ scene->toolsettings->uvcalc_flag |= UVCALC_NO_ASPECT_CORRECT;
+
+ if (use_subsurf)
+ scene->toolsettings->uvcalc_flag |= UVCALC_USESUBSURF;
+ else
+ scene->toolsettings->uvcalc_flag &= ~UVCALC_USESUBSURF;
+
+ /* execute unwrap */
+ uvedit_unwrap_multi(scene, objects, objects_len, &options);
+ uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned);
+
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void UV_OT_unwrap(wmOperatorType *ot)
{
- static const EnumPropertyItem method_items[] = {
- {0, "ANGLE_BASED", 0, "Angle Based", ""},
- {1, "CONFORMAL", 0, "Conformal", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Unwrap";
- ot->description = "Unwrap the mesh of the object being edited";
- ot->idname = "UV_OT_unwrap";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* api callbacks */
- ot->exec = unwrap_exec;
- ot->poll = ED_operator_uvmap;
-
- /* properties */
- RNA_def_enum(ot->srna, "method", method_items, 0, "Method",
- "Unwrapping method (Angle Based usually gives better results than Conformal, while being somewhat slower)");
- RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes",
- "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry");
- RNA_def_boolean(ot->srna, "correct_aspect", 1, "Correct Aspect",
- "Map UVs taking image aspect ratio into account");
- RNA_def_boolean(ot->srna, "use_subsurf_data", 0, "Use Subsurf Modifier",
- "Map UVs taking vertex position after Subdivision Surface modifier has been applied");
- RNA_def_float_factor(ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
+ static const EnumPropertyItem method_items[] = {
+ {0, "ANGLE_BASED", 0, "Angle Based", ""},
+ {1, "CONFORMAL", 0, "Conformal", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Unwrap";
+ ot->description = "Unwrap the mesh of the object being edited";
+ ot->idname = "UV_OT_unwrap";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec = unwrap_exec;
+ ot->poll = ED_operator_uvmap;
+
+ /* properties */
+ RNA_def_enum(ot->srna,
+ "method",
+ method_items,
+ 0,
+ "Method",
+ "Unwrapping method (Angle Based usually gives better results than Conformal, while "
+ "being somewhat slower)");
+ RNA_def_boolean(ot->srna,
+ "fill_holes",
+ 1,
+ "Fill Holes",
+ "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and "
+ "preserve symmetry");
+ RNA_def_boolean(ot->srna,
+ "correct_aspect",
+ 1,
+ "Correct Aspect",
+ "Map UVs taking image aspect ratio into account");
+ RNA_def_boolean(
+ ot->srna,
+ "use_subsurf_data",
+ 0,
+ "Use Subsurf Modifier",
+ "Map UVs taking vertex position after Subdivision Surface modifier has been applied");
+ RNA_def_float_factor(
+ ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
}
/**************** Project From View operator **************/
@@ -1609,574 +1739,605 @@ static int uv_from_view_exec(bContext *C, wmOperator *op);
static int uv_from_view_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- Camera *camera = ED_view3d_camera_data_get(v3d, rv3d);
- PropertyRNA *prop;
-
- prop = RNA_struct_find_property(op->ptr, "camera_bounds");
- if (!RNA_property_is_set(op->ptr, prop)) RNA_property_boolean_set(op->ptr, prop, (camera != NULL));
- prop = RNA_struct_find_property(op->ptr, "correct_aspect");
- if (!RNA_property_is_set(op->ptr, prop)) RNA_property_boolean_set(op->ptr, prop, (camera == NULL));
-
- return uv_from_view_exec(C, op);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ Camera *camera = ED_view3d_camera_data_get(v3d, rv3d);
+ PropertyRNA *prop;
+
+ prop = RNA_struct_find_property(op->ptr, "camera_bounds");
+ if (!RNA_property_is_set(op->ptr, prop))
+ RNA_property_boolean_set(op->ptr, prop, (camera != NULL));
+ prop = RNA_struct_find_property(op->ptr, "correct_aspect");
+ if (!RNA_property_is_set(op->ptr, prop))
+ RNA_property_boolean_set(op->ptr, prop, (camera == NULL));
+
+ return uv_from_view_exec(C, op);
}
static int uv_from_view_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Scene *scene = CTX_data_scene(C);
- ARegion *ar = 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);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
- float rotmat[4][4];
- float objects_pos_offset[4];
- bool changed_multi = false;
-
- const bool use_orthographic = RNA_boolean_get(op->ptr, "orthographic");
-
- /* Note: objects that aren't touched are set to NULL (to skip clipping). */
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, v3d, &objects_len);
-
- if (use_orthographic) {
- /* Calculate average object position. */
- float objects_pos_avg[4] = {0};
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- add_v4_v4(objects_pos_avg, objects[ob_index]->obmat[3]);
- }
-
- mul_v4_fl(objects_pos_avg, 1.0f / objects_len);
- negate_v4_v4(objects_pos_offset, objects_pos_avg);
- }
-
- 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;
-
- /* add uvs if they don't exist yet */
- if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
- continue;
- }
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- if (use_orthographic) {
- uv_map_rotation_matrix_ex(rotmat, rv3d, obedit, 90.0f, 0.0f, 1.0f, objects_pos_offset);
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
- continue;
-
- 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_ortho(luv->uv, l->v->co, rotmat);
- }
- changed = true;
- }
- }
- else if (camera) {
- const bool camera_bounds = RNA_boolean_get(op->ptr, "camera_bounds");
- struct ProjCameraInfo *uci = BLI_uvproject_camera_info(
- v3d->camera, obedit->obmat,
- camera_bounds ? (scene->r.xsch * scene->r.xasp) : 1.0f,
- camera_bounds ? (scene->r.ysch * scene->r.yasp) : 1.0f);
-
- if (uci) {
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
- continue;
-
- 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_camera(luv->uv, l->v->co, uci);
- }
- changed = true;
- }
-
- MEM_freeN(uci);
- }
- }
- else {
- copy_m4_m4(rotmat, obedit->obmat);
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
- continue;
-
- 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);
- }
- changed = true;
- }
- }
-
- if (changed) {
- changed_multi = true;
- DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- }
- else {
- ARRAY_DELETE_REORDER_LAST(objects, ob_index, 1, objects_len);
- objects_len -= 1;
- ob_index -= 1;
- }
- }
-
- if (changed_multi) {
- uv_map_clip_correct_multi(scene, objects, objects_len, op);
- }
-
- MEM_freeN(objects);
-
- if (changed_multi) {
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Scene *scene = CTX_data_scene(C);
+ ARegion *ar = 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);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+ float rotmat[4][4];
+ float objects_pos_offset[4];
+ bool changed_multi = false;
+
+ const bool use_orthographic = RNA_boolean_get(op->ptr, "orthographic");
+
+ /* Note: objects that aren't touched are set to NULL (to skip clipping). */
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, v3d, &objects_len);
+
+ if (use_orthographic) {
+ /* Calculate average object position. */
+ float objects_pos_avg[4] = {0};
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ add_v4_v4(objects_pos_avg, objects[ob_index]->obmat[3]);
+ }
+
+ mul_v4_fl(objects_pos_avg, 1.0f / objects_len);
+ negate_v4_v4(objects_pos_offset, objects_pos_avg);
+ }
+
+ 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;
+
+ /* add uvs if they don't exist yet */
+ if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
+ continue;
+ }
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ if (use_orthographic) {
+ uv_map_rotation_matrix_ex(rotmat, rv3d, obedit, 90.0f, 0.0f, 1.0f, objects_pos_offset);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ continue;
+
+ 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_ortho(luv->uv, l->v->co, rotmat);
+ }
+ changed = true;
+ }
+ }
+ else if (camera) {
+ const bool camera_bounds = RNA_boolean_get(op->ptr, "camera_bounds");
+ struct ProjCameraInfo *uci = BLI_uvproject_camera_info(
+ v3d->camera,
+ obedit->obmat,
+ camera_bounds ? (scene->r.xsch * scene->r.xasp) : 1.0f,
+ camera_bounds ? (scene->r.ysch * scene->r.yasp) : 1.0f);
+
+ if (uci) {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ continue;
+
+ 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_camera(luv->uv, l->v->co, uci);
+ }
+ changed = true;
+ }
+
+ MEM_freeN(uci);
+ }
+ }
+ else {
+ copy_m4_m4(rotmat, obedit->obmat);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ continue;
+
+ 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);
+ }
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ changed_multi = true;
+ DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ }
+ else {
+ ARRAY_DELETE_REORDER_LAST(objects, ob_index, 1, objects_len);
+ objects_len -= 1;
+ ob_index -= 1;
+ }
+ }
+
+ if (changed_multi) {
+ uv_map_clip_correct_multi(scene, objects, objects_len, op);
+ }
+
+ MEM_freeN(objects);
+
+ if (changed_multi) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static bool uv_from_view_poll(bContext *C)
{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
- if (!ED_operator_uvmap(C))
- return 0;
+ if (!ED_operator_uvmap(C))
+ return 0;
- return (rv3d != NULL);
+ return (rv3d != NULL);
}
void UV_OT_project_from_view(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Project From View";
- ot->idname = "UV_OT_project_from_view";
- ot->description = "Project the UV vertices of the mesh as seen in current 3D view";
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* api callbacks */
- ot->invoke = uv_from_view_invoke;
- ot->exec = uv_from_view_exec;
- ot->poll = uv_from_view_poll;
-
- /* properties */
- RNA_def_boolean(ot->srna, "orthographic", 0, "Orthographic",
- "Use orthographic projection");
- RNA_def_boolean(ot->srna, "camera_bounds", 1, "Camera Bounds",
- "Map UVs to the camera region taking resolution and aspect into account");
- uv_map_clip_correct_properties(ot);
+ /* identifiers */
+ ot->name = "Project From View";
+ ot->idname = "UV_OT_project_from_view";
+ ot->description = "Project the UV vertices of the mesh as seen in current 3D view";
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->invoke = uv_from_view_invoke;
+ ot->exec = uv_from_view_exec;
+ ot->poll = uv_from_view_poll;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "orthographic", 0, "Orthographic", "Use orthographic projection");
+ RNA_def_boolean(ot->srna,
+ "camera_bounds",
+ 1,
+ "Camera Bounds",
+ "Map UVs to the camera region taking resolution and aspect into account");
+ uv_map_clip_correct_properties(ot);
}
/********************** Reset operator ********************/
static int reset_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, v3d, &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- Mesh *me = (Mesh *)obedit->data;
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totfacesel == 0) {
- continue;
- }
-
- /* add uvs if they don't exist yet */
- if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
- continue;
- }
-
- ED_mesh_uv_loop_reset(C, me);
-
- DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, v3d, &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Mesh *me = (Mesh *)obedit->data;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
+
+ /* add uvs if they don't exist yet */
+ if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
+ continue;
+ }
+
+ ED_mesh_uv_loop_reset(C, me);
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void UV_OT_reset(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reset";
- ot->idname = "UV_OT_reset";
- ot->description = "Reset UV projection";
+ /* identifiers */
+ ot->name = "Reset";
+ ot->idname = "UV_OT_reset";
+ ot->description = "Reset UV projection";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* api callbacks */
- ot->exec = reset_exec;
- ot->poll = ED_operator_uvmap;
+ /* api callbacks */
+ ot->exec = reset_exec;
+ ot->poll = ED_operator_uvmap;
}
/****************** Sphere Project operator ***************/
-static void uv_sphere_project(float target[2], float source[3], float center[3], float rotmat[4][4])
+static void uv_sphere_project(float target[2],
+ float source[3],
+ float center[3],
+ float rotmat[4][4])
{
- float pv[3];
+ float pv[3];
- sub_v3_v3v3(pv, source, center);
- mul_m4_v3(rotmat, pv);
+ sub_v3_v3v3(pv, source, center);
+ mul_m4_v3(rotmat, pv);
- map_to_sphere(&target[0], &target[1], pv[0], pv[1], pv[2]);
+ map_to_sphere(&target[0], &target[1], pv[0], pv[1], pv[2]);
- /* split line is always zero */
- if (target[0] >= 1.0f)
- target[0] -= 1.0f;
+ /* split line is always zero */
+ if (target[0] >= 1.0f)
+ target[0] -= 1.0f;
}
static void uv_map_mirror(BMEditMesh *em, BMFace *efa)
{
- BMLoop *l;
- BMIter liter;
- MLoopUV *luv;
- float **uvs = BLI_array_alloca(uvs, efa->len);
- float dx;
- int i, mi;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- uvs[i] = luv->uv;
- }
-
- mi = 0;
- for (i = 1; i < efa->len; i++)
- if (uvs[i][0] > uvs[mi][0])
- mi = i;
-
- for (i = 0; i < efa->len; i++) {
- if (i != mi) {
- dx = uvs[mi][0] - uvs[i][0];
- if (dx > 0.5f) uvs[i][0] += 1.0f;
- }
- }
+ BMLoop *l;
+ BMIter liter;
+ MLoopUV *luv;
+ float **uvs = BLI_array_alloca(uvs, efa->len);
+ float dx;
+ int i, mi;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i)
+ {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ uvs[i] = luv->uv;
+ }
+
+ mi = 0;
+ for (i = 1; i < efa->len; i++)
+ if (uvs[i][0] > uvs[mi][0])
+ mi = i;
+
+ for (i = 0; i < efa->len; i++) {
+ if (i != mi) {
+ dx = uvs[mi][0] - uvs[i][0];
+ if (dx > 0.5f)
+ uvs[i][0] += 1.0f;
+ }
+ }
}
static int sphere_project_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(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, v3d, &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);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
+ 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, v3d, &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);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
- if (em->bm->totfacesel == 0) {
- continue;
- }
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
- /* add uvs if they don't exist yet */
- if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
- continue;
- }
+ /* add uvs if they don't exist yet */
+ if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
+ continue;
+ }
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- float center[3], rotmat[4][4];
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ float center[3], rotmat[4][4];
- uv_map_transform(C, op, rotmat);
- uv_map_transform_center(scene, v3d, obedit, em, center, NULL);
+ uv_map_transform(C, op, rotmat);
+ uv_map_transform_center(scene, v3d, obedit, em, center, NULL);
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
- continue;
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ continue;
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, 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);
- uv_sphere_project(luv->uv, l->v->co, center, rotmat);
- }
+ uv_sphere_project(luv->uv, l->v->co, center, rotmat);
+ }
- uv_map_mirror(em, efa);
- }
+ uv_map_mirror(em, efa);
+ }
- uv_map_clip_correct(scene, obedit, op);
+ uv_map_clip_correct(scene, obedit, op);
- DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- }
- MEM_freeN(objects);
+ DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void UV_OT_sphere_project(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Sphere Projection";
- ot->idname = "UV_OT_sphere_project";
- ot->description = "Project the UV vertices of the mesh over the curved surface of a sphere";
+ /* identifiers */
+ ot->name = "Sphere Projection";
+ ot->idname = "UV_OT_sphere_project";
+ ot->description = "Project the UV vertices of the mesh over the curved surface of a sphere";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* api callbacks */
- ot->exec = sphere_project_exec;
- ot->poll = ED_operator_uvmap;
+ /* api callbacks */
+ ot->exec = sphere_project_exec;
+ ot->poll = ED_operator_uvmap;
- /* properties */
- uv_transform_properties(ot, 0);
- uv_map_clip_correct_properties(ot);
+ /* properties */
+ uv_transform_properties(ot, 0);
+ uv_map_clip_correct_properties(ot);
}
/***************** Cylinder Project operator **************/
-static void uv_cylinder_project(float target[2], float source[3], float center[3], float rotmat[4][4])
+static void uv_cylinder_project(float target[2],
+ float source[3],
+ float center[3],
+ float rotmat[4][4])
{
- float pv[3];
+ float pv[3];
- sub_v3_v3v3(pv, source, center);
- mul_m4_v3(rotmat, pv);
+ sub_v3_v3v3(pv, source, center);
+ mul_m4_v3(rotmat, pv);
- map_to_tube(&target[0], &target[1], pv[0], pv[1], pv[2]);
+ map_to_tube(&target[0], &target[1], pv[0], pv[1], pv[2]);
- /* split line is always zero */
- if (target[0] >= 1.0f)
- target[0] -= 1.0f;
+ /* split line is always zero */
+ if (target[0] >= 1.0f)
+ target[0] -= 1.0f;
}
static int cylinder_project_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(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, v3d, &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);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
+ 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, v3d, &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);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
- if (em->bm->totfacesel == 0) {
- continue;
- }
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
- /* add uvs if they don't exist yet */
- if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
- continue;
- }
+ /* add uvs if they don't exist yet */
+ if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
+ continue;
+ }
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- float center[3], rotmat[4][4];
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ float center[3], rotmat[4][4];
- uv_map_transform(C, op, rotmat);
- uv_map_transform_center(scene, v3d, obedit, em, center, NULL);
+ uv_map_transform(C, op, rotmat);
+ uv_map_transform_center(scene, v3d, obedit, em, center, NULL);
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
- continue;
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ continue;
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, 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);
- uv_cylinder_project(luv->uv, l->v->co, center, rotmat);
- }
+ uv_cylinder_project(luv->uv, l->v->co, center, rotmat);
+ }
- uv_map_mirror(em, efa);
- }
+ uv_map_mirror(em, efa);
+ }
- uv_map_clip_correct(scene, obedit, op);
+ uv_map_clip_correct(scene, obedit, op);
- DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- }
- MEM_freeN(objects);
+ DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void UV_OT_cylinder_project(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Cylinder Projection";
- ot->idname = "UV_OT_cylinder_project";
- ot->description = "Project the UV vertices of the mesh over the curved wall of a cylinder";
+ /* identifiers */
+ ot->name = "Cylinder Projection";
+ ot->idname = "UV_OT_cylinder_project";
+ ot->description = "Project the UV vertices of the mesh over the curved wall of a cylinder";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* api callbacks */
- ot->exec = cylinder_project_exec;
- ot->poll = ED_operator_uvmap;
+ /* api callbacks */
+ ot->exec = cylinder_project_exec;
+ ot->poll = ED_operator_uvmap;
- /* properties */
- uv_transform_properties(ot, 1);
- uv_map_clip_correct_properties(ot);
+ /* properties */
+ uv_transform_properties(ot, 1);
+ uv_map_clip_correct_properties(ot);
}
/******************* Cube Project operator ****************/
-static void uvedit_unwrap_cube_project(BMesh *bm, float cube_size, bool use_select, const float center[3])
+static void uvedit_unwrap_cube_project(BMesh *bm,
+ float cube_size,
+ bool use_select,
+ const float center[3])
{
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
- float loc[3];
- int cox, coy;
-
- int cd_loop_uv_offset;
-
- cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-
- if (center) {
- copy_v3_v3(loc, center);
- }
- else {
- zero_v3(loc);
- }
-
- /* choose x,y,z axis for projection depending on the largest normal
- * component, but clusters all together around the center of map. */
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
- if (use_select && !BM_elem_flag_test(efa, BM_ELEM_SELECT))
- continue;
-
- axis_dominant_v3(&cox, &coy, efa->no);
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->uv[0] = 0.5f + 0.5f * cube_size * (l->v->co[cox] - loc[cox]);
- luv->uv[1] = 0.5f + 0.5f * cube_size * (l->v->co[coy] - loc[coy]);
- }
- }
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+ float loc[3];
+ int cox, coy;
+
+ int cd_loop_uv_offset;
+
+ cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+ if (center) {
+ copy_v3_v3(loc, center);
+ }
+ else {
+ zero_v3(loc);
+ }
+
+ /* choose x,y,z axis for projection depending on the largest normal
+ * component, but clusters all together around the center of map. */
+
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
+ if (use_select && !BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ continue;
+
+ axis_dominant_v3(&cox, &coy, efa->no);
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv->uv[0] = 0.5f + 0.5f * cube_size * (l->v->co[cox] - loc[cox]);
+ luv->uv[1] = 0.5f + 0.5f * cube_size * (l->v->co[coy] - loc[coy]);
+ }
+ }
}
static int cube_project_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
-
- PropertyRNA *prop_cube_size = RNA_struct_find_property(op->ptr, "cube_size");
- const float cube_size_init = RNA_property_float_get(op->ptr, prop_cube_size);
-
- 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, v3d, &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);
-
- if (em->bm->totfacesel == 0) {
- continue;
- }
-
- /* add uvs if they don't exist yet */
- if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
- continue;
- }
-
- float bounds[2][3];
- float (*bounds_buf)[3] = NULL;
-
- if (!RNA_property_is_set(op->ptr, prop_cube_size)) {
- bounds_buf = bounds;
- }
-
- float center[3];
- uv_map_transform_center(scene, v3d, obedit, em, center, bounds_buf);
-
- /* calculate based on bounds */
- float cube_size = cube_size_init;
- if (bounds_buf) {
- float dims[3];
- sub_v3_v3v3(dims, bounds[1], bounds[0]);
- cube_size = max_fff(UNPACK3(dims));
- cube_size = cube_size ? 2.0f / cube_size : 1.0f;
- if (ob_index == 0) {
- /* This doesn't fit well with, multiple objects. */
- RNA_property_float_set(op->ptr, prop_cube_size, cube_size);
- }
- }
-
- uvedit_unwrap_cube_project(em->bm, cube_size, true, center);
-
- uv_map_clip_correct(scene, obedit, op);
-
- DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ PropertyRNA *prop_cube_size = RNA_struct_find_property(op->ptr, "cube_size");
+ const float cube_size_init = RNA_property_float_get(op->ptr, prop_cube_size);
+
+ 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, v3d, &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);
+
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
+
+ /* add uvs if they don't exist yet */
+ if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
+ continue;
+ }
+
+ float bounds[2][3];
+ float(*bounds_buf)[3] = NULL;
+
+ if (!RNA_property_is_set(op->ptr, prop_cube_size)) {
+ bounds_buf = bounds;
+ }
+
+ float center[3];
+ uv_map_transform_center(scene, v3d, obedit, em, center, bounds_buf);
+
+ /* calculate based on bounds */
+ float cube_size = cube_size_init;
+ if (bounds_buf) {
+ float dims[3];
+ sub_v3_v3v3(dims, bounds[1], bounds[0]);
+ cube_size = max_fff(UNPACK3(dims));
+ cube_size = cube_size ? 2.0f / cube_size : 1.0f;
+ if (ob_index == 0) {
+ /* This doesn't fit well with, multiple objects. */
+ RNA_property_float_set(op->ptr, prop_cube_size, cube_size);
+ }
+ }
+
+ uvedit_unwrap_cube_project(em->bm, cube_size, true, center);
+
+ uv_map_clip_correct(scene, obedit, op);
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void UV_OT_cube_project(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Cube Projection";
- ot->idname = "UV_OT_cube_project";
- ot->description = "Project the UV vertices of the mesh over the six faces of a cube";
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* api callbacks */
- ot->exec = cube_project_exec;
- ot->poll = ED_operator_uvmap;
-
- /* properties */
- RNA_def_float(ot->srna, "cube_size", 1.0f, 0.0f, FLT_MAX, "Cube Size", "Size of the cube to project on", 0.001f, 100.0f);
- uv_map_clip_correct_properties(ot);
+ /* identifiers */
+ ot->name = "Cube Projection";
+ ot->idname = "UV_OT_cube_project";
+ ot->description = "Project the UV vertices of the mesh over the six faces of a cube";
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec = cube_project_exec;
+ ot->poll = ED_operator_uvmap;
+
+ /* properties */
+ RNA_def_float(ot->srna,
+ "cube_size",
+ 1.0f,
+ 0.0f,
+ FLT_MAX,
+ "Cube Size",
+ "Size of the cube to project on",
+ 0.001f,
+ 100.0f);
+ uv_map_clip_correct_properties(ot);
}
/************************* Simple UVs for texture painting *****************/
void ED_uvedit_add_simple_uvs(Main *bmain, Scene *scene, Object *ob)
{
- Mesh *me = ob->data;
- bool sync_selection = (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
-
- BMesh *bm = BM_mesh_create(
- &bm_mesh_allocsize_default,
- &((struct BMeshCreateParams){.use_toolflags = false,}));
-
- /* turn sync selection off,
- * since we are not in edit mode we need to ensure only the uv flags are tested */
- scene->toolsettings->uv_flag &= ~UV_SYNC_SELECTION;
-
- ED_mesh_uv_texture_ensure(me, NULL);
-
- BM_mesh_bm_from_me(
- bm, me, (&(struct BMeshFromMeshParams){
- .calc_face_normal = true,
- }));
- /* select all uv loops first - pack parameters needs this to make sure charts are registered */
- ED_uvedit_select_all(bm);
- uvedit_unwrap_cube_project(bm, 1.0, false, NULL);
- /* set the margin really quickly before the packing operation*/
- scene->toolsettings->uvcalc_margin = 0.001f;
- uvedit_pack_islands(scene, ob, bm);
- BM_mesh_bm_to_me(bmain, bm, me, (&(struct BMeshToMeshParams){0}));
- BM_mesh_free(bm);
-
- if (sync_selection)
- scene->toolsettings->uv_flag |= UV_SYNC_SELECTION;
+ Mesh *me = ob->data;
+ bool sync_selection = (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
+
+ BMesh *bm = BM_mesh_create(&bm_mesh_allocsize_default,
+ &((struct BMeshCreateParams){
+ .use_toolflags = false,
+ }));
+
+ /* turn sync selection off,
+ * since we are not in edit mode we need to ensure only the uv flags are tested */
+ scene->toolsettings->uv_flag &= ~UV_SYNC_SELECTION;
+
+ ED_mesh_uv_texture_ensure(me, NULL);
+
+ BM_mesh_bm_from_me(bm,
+ me,
+ (&(struct BMeshFromMeshParams){
+ .calc_face_normal = true,
+ }));
+ /* select all uv loops first - pack parameters needs this to make sure charts are registered */
+ ED_uvedit_select_all(bm);
+ uvedit_unwrap_cube_project(bm, 1.0, false, NULL);
+ /* set the margin really quickly before the packing operation*/
+ scene->toolsettings->uvcalc_margin = 0.001f;
+ uvedit_pack_islands(scene, ob, bm);
+ BM_mesh_bm_to_me(bmain, bm, me, (&(struct BMeshToMeshParams){0}));
+ BM_mesh_free(bm);
+
+ if (sync_selection)
+ scene->toolsettings->uv_flag |= UV_SYNC_SELECTION;
}